Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6:
  JFS: Get rid of "may be used uninitialized" warnings
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..bf62dbe
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,96 @@
+#
+# This list is used by git-shortlog to fix a few botched name translations
+# in the git archive, either because the author's full name was messed up
+# and/or not always written the same way, making contributions from the
+# same person appearing not to be so or badly displayed.
+#
+# repo-abbrev: /pub/scm/linux/kernel/git/
+#
+
+Aaron Durbin <adurbin@google.com>
+Adam Oldham <oldhamca@gmail.com>
+Adam Radford <aradford@gmail.com>
+Adrian Bunk <bunk@stusta.de>
+Alan Cox <alan@lxorguk.ukuu.org.uk>
+Alan Cox <root@hraefn.swansea.linux.org.uk>
+Aleksey Gorelov <aleksey_gorelov@phoenix.com>
+Al Viro <viro@ftp.linux.org.uk>
+Al Viro <viro@zenIV.linux.org.uk>
+Andreas Herrmann <aherrman@de.ibm.com>
+Andrew Morton <akpm@osdl.org>
+Andrew Vasquez <andrew.vasquez@qlogic.com>
+Andy Adamson <andros@citi.umich.edu>
+Arnaud Patard <arnaud.patard@rtp-net.org>
+Arnd Bergmann <arnd@arndb.de>
+Axel Dyks <xl@xlsigned.net>
+Ben Gardner <bgardner@wabtec.com>
+Ben M Cahill <ben.m.cahill@intel.com>
+Björn Steinbrink <B.Steinbrink@gmx.de>
+Brian Avery <b.avery@hp.com>
+Brian King <brking@us.ibm.com>
+Christoph Hellwig <hch@lst.de>
+Corey Minyard <minyard@acm.org>
+David Brownell <david-b@pacbell.net>
+David Woodhouse <dwmw2@shinybook.infradead.org>
+Domen Puncer <domen@coderock.org>
+Douglas Gilbert <dougg@torque.net>
+Ed L. Cashin <ecashin@coraid.com>
+Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Felipe W Damasio <felipewd@terra.com.br>
+Felix Kuhling <fxkuehl@gmx.de>
+Felix Moeller <felix@derklecks.de>
+Filipe Lautert <filipe@icewall.org>
+Franck Bui-Huu <vagabon.xyz@gmail.com>
+Frank Zago <fzago@systemfabricworks.com>
+Greg Kroah-Hartman <greg@echidna.(none)>
+Greg Kroah-Hartman <gregkh@suse.de>
+Greg Kroah-Hartman <greg@kroah.com>
+Henk Vergonet <Henk.Vergonet@gmail.com>
+Henrik Kretzschmar <henne@nachtwindheim.de>
+Herbert Xu <herbert@gondor.apana.org.au>
+Jacob Shin <Jacob.Shin@amd.com>
+James Bottomley <jejb@mulgrave.(none)>
+James Bottomley <jejb@titanic.il.steeleye.com>
+James E Wilson <wilson@specifix.com>
+James Ketrenos <jketreno@io.(none)>
+Jean Tourrilhes <jt@hpl.hp.com>
+Jeff Garzik <jgarzik@pretzel.yyz.us>
+Jens Axboe <axboe@suse.de>
+Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+John Stultz <johnstul@us.ibm.com>
+Juha Yrjola <at solidboot.com>
+Juha Yrjola <juha.yrjola@nokia.com>
+Juha Yrjola <juha.yrjola@solidboot.com>
+Kay Sievers <kay.sievers@vrfy.org>
+Kenneth W Chen <kenneth.w.chen@intel.com>
+Koushik <raghavendra.koushik@neterion.com>
+Leonid I Ananiev <leonid.i.ananiev@intel.com>
+Linas Vepstas <linas@austin.ibm.com>
+Matthieu CASTET <castet.matthieu@free.fr>
+Michel Dänzer <michel@tungstengraphics.com>
+Mitesh shah <mshah@teja.com>
+Morten Welinder <terra@gnome.org>
+Morten Welinder <welinder@anemone.rentec.com>
+Morten Welinder <welinder@darter.rentec.com>
+Morten Welinder <welinder@troll.com>
+Nguyen Anh Quynh <aquynh@gmail.com>
+Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
+Patrick Mochel <mochel@digitalimplant.org>
+Peter A Jonsson <pj@ludd.ltu.se>
+Praveen BP <praveenbp@ti.com>
+Rajesh Shah <rajesh.shah@intel.com>
+Ralf Baechle <ralf@linux-mips.org>
+Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
+Rémi Denis-Courmont <rdenis@simphalempin.com>
+Rudolf Marek <R.Marek@sh.cvut.cz>
+Rui Saraiva <rmps@joel.ist.utl.pt>
+Sachin P Sant <ssant@in.ibm.com>
+Sam Ravnborg <sam@mars.ravnborg.org>
+Simon Kelley <simon@thekelleys.org.uk>
+Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
+Stephen Hemminger <shemminger@osdl.org>
+Tejun Heo <htejun@gmail.com>
+Thomas Graf <tgraf@suug.ch>
+Tony Luck <tony.luck@intel.com>
+Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
+Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
diff --git a/CREDITS b/CREDITS
index ae08e4c..a4e55990 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2571,6 +2571,16 @@
 S: Perth, Western Australia
 S: Australia
 
+N: Miguel Ojeda Sandonis
+E: maxextreme@gmail.com
+D: Author: Auxiliary LCD Controller driver (ks0108)
+D: Author: Auxiliary LCD driver (cfag12864b)
+D: Author: Auxiliary LCD framebuffer driver (cfag12864bfb)
+D: Maintainer: Auxiliary display drivers tree (drivers/auxdisplay/*)
+S: C/ Mieses 20, 9-B
+S: Valladolid 47009
+S: Spain
+
 N: Greg Page
 E: gpage@sovereign.org
 D: IPX development and support
diff --git a/Documentation/ABI/testing/debugfs-pktcdvd b/Documentation/ABI/testing/debugfs-pktcdvd
index 03dbd88..bf9c16b 100644
--- a/Documentation/ABI/testing/debugfs-pktcdvd
+++ b/Documentation/ABI/testing/debugfs-pktcdvd
@@ -1,6 +1,6 @@
 What:           /debug/pktcdvd/pktcdvd[0-7]
 Date:           Oct. 2006
-KernelVersion:  2.6.19
+KernelVersion:  2.6.20
 Contact:        Thomas Maier <balagi@justmail.de>
 Description:
 
@@ -11,8 +11,7 @@
 these files in debugfs:
 
 /debug/pktcdvd/pktcdvd[0-7]/
-    info            (0444) Lots of human readable driver
-                           statistics and infos. Multiple lines!
+    info            (0444) Lots of driver statistics and infos.
 
 Example:
 -------
diff --git a/Documentation/ABI/testing/sysfs-class-pktcdvd b/Documentation/ABI/testing/sysfs-class-pktcdvd
index c4c55ed..b1c3f02 100644
--- a/Documentation/ABI/testing/sysfs-class-pktcdvd
+++ b/Documentation/ABI/testing/sysfs-class-pktcdvd
@@ -1,6 +1,6 @@
 What:           /sys/class/pktcdvd/
 Date:           Oct. 2006
-KernelVersion:  2.6.19
+KernelVersion:  2.6.20
 Contact:        Thomas Maier <balagi@justmail.de>
 Description:
 
diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
index a344424..e7fc964 100644
--- a/Documentation/DocBook/gadget.tmpl
+++ b/Documentation/DocBook/gadget.tmpl
@@ -482,13 +482,13 @@
 <para>Gadget drivers
 rely on common USB structures and constants
 defined in the
-<filename>&lt;linux/usb_ch9.h&gt;</filename>
+<filename>&lt;linux/usb/ch9.h&gt;</filename>
 header file, which is standard in Linux 2.6 kernels.
 These are the same types and constants used by host
 side drivers (and usbcore).
 </para>
 
-!Iinclude/linux/usb_ch9.h
+!Iinclude/linux/usb/ch9.h
 </sect1>
 
 <sect1 id="core"><title>Core Objects and Methods</title>
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 3fa0c4b..0bb9023 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -316,6 +316,9 @@
      <sect1><title>DMI Interfaces</title>
 !Edrivers/firmware/dmi_scan.c
      </sect1>
+     <sect1><title>EDD Interfaces</title>
+!Idrivers/firmware/edd.c
+     </sect1>
   </chapter>
 
   <chapter id="security">
diff --git a/Documentation/DocBook/stylesheet.xsl b/Documentation/DocBook/stylesheet.xsl
index 3ccce88..974e17c 100644
--- a/Documentation/DocBook/stylesheet.xsl
+++ b/Documentation/DocBook/stylesheet.xsl
@@ -4,4 +4,5 @@
 <param name="funcsynopsis.style">ansi</param>
 <param name="funcsynopsis.tabular.threshold">80</param>
 <!-- <param name="paper.type">A4</param> -->
+<param name="generate.section.toc.level">2</param>
 </stylesheet>
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
index 143e5ff..a2ebd65 100644
--- a/Documentation/DocBook/usb.tmpl
+++ b/Documentation/DocBook/usb.tmpl
@@ -187,13 +187,13 @@
 
 <chapter><title>USB-Standard Types</title>
 
-    <para>In <filename>&lt;linux/usb_ch9.h&gt;</filename> you will find
+    <para>In <filename>&lt;linux/usb/ch9.h&gt;</filename> you will find
     the USB data types defined in chapter 9 of the USB specification.
     These data types are used throughout USB, and in APIs including
     this host side API, gadget APIs, and usbfs.
     </para>
 
-!Iinclude/linux/usb_ch9.h
+!Iinclude/linux/usb/ch9.h
 
     </chapter>
 
@@ -574,7 +574,7 @@
 #include &lt;asm/byteorder.h&gt;</programlisting>
 	    The standard USB device model requests, from "Chapter 9" of
 	    the USB 2.0 specification, are automatically included from
-	    the <filename>&lt;linux/usb_ch9.h&gt;</filename> header.
+	    the <filename>&lt;linux/usb/ch9.h&gt;</filename> header.
 	    </para>
 
 	    <para>Unless noted otherwise, the ioctl requests
diff --git a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt
deleted file mode 100644
index 38040fa..0000000
--- a/Documentation/acpi-hotkey.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-driver/acpi/hotkey.c implement:
-1. /proc/acpi/hotkey/event_config 
-(event based hotkey or event config interface):
-a. add a  event based hotkey(event) : 
-echo "0:bus::action:method:num:num" > event_config
-
-b. delete a event based hotkey(event): 
-echo "1:::::num:num" > event_config
-
-c.  modify a event based hotkey(event):    
-echo "2:bus::action:method:num:num" > event_config
-
-2. /proc/acpi/hotkey/poll_config 
-(polling based hotkey or event config interface):
-a.add a polling based hotkey(event) : 	
-echo "0:bus:method:action:method:num" > poll_config
-this adding command will create a proc file 
-/proc/acpi/hotkey/method, which is used to get 
-result of polling.
-
-b.delete a polling based hotkey(event): 	
-echo "1:::::num" > event_config
-
-c.modify a polling based hotkey(event):    
-echo "2:bus:method:action:method:num" > poll_config
-
-3./proc/acpi/hotkey/action 
-(interface to call aml method associated with a 
-specific hotkey(event))
-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 dynamically
-created.  Please use command "cat /proc/acpi/hotkey/polling_method" 
-to retrieve it.
-
-Note: Use cmdline "acpi_generic_hotkey" to over-ride
-platform-specific with generic driver.
diff --git a/Documentation/arm/Samsung-S3C24XX/DMA.txt b/Documentation/arm/Samsung-S3C24XX/DMA.txt
new file mode 100644
index 0000000..37f4edc
--- /dev/null
+++ b/Documentation/arm/Samsung-S3C24XX/DMA.txt
@@ -0,0 +1,46 @@
+			S3C2410 DMA
+			===========
+
+Introduction
+------------
+
+   The kernel provides an interface to manage DMA transfers
+   using the DMA channels in the cpu, so that the central
+   duty of managing channel mappings, and programming the
+   channel generators is in one place.
+
+
+DMA Channel Ordering
+--------------------
+
+   Many of the range do not have connections for the DMA
+   channels to all sources, which means that some devices
+   have a restricted number of channels that can be used.
+
+   To allow flexibilty for each cpu type and board, the
+   dma code can be given an dma ordering structure which
+   allows the order of channel search to be specified, as
+   well as allowing the prohibition of certain claims.
+
+   struct s3c24xx_dma_order has a list of channels, and
+   each channel within has a slot for a list of dma
+   channel numbers. The slots are searched in order, for
+   the presence of a dma channel number with DMA_CH_VALID
+   orred in.
+
+   If the order has the flag DMA_CH_NEVER set, then after
+   checking the channel list, the system will return no
+   found channel, thus denying the request.
+
+   A board support file can call s3c24xx_dma_order_set()
+   to register an complete ordering set. The routine will
+   copy the data, so the original can be discared with
+   __initdata.
+
+
+Authour
+-------
+
+Ben Dooks,
+Copyright (c) 2007 Ben Dooks, Simtec Electronics
+Licensed under the GPL v2
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
index 28d0147..c31b76f 100644
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
@@ -8,13 +8,10 @@
 
   The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
   by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
-  S3C2440 and S3C2442 devices are supported.
+  S3C2412, S3C2413, S3C2440 and S3C2442 devices are supported.
 
   Support for the S3C2400 series is in progress.
 
-  Support for the S3C2412 and S3C2413 CPUs is being merged.
-
-
 Configuration
 -------------
 
@@ -26,6 +23,22 @@
   please check the machine specific documentation.
 
 
+Layout
+------
+
+  The core support files are located in the platform code contained in
+  arch/arm/plat-s3c24xx with headers in include/asm-arm/plat-s3c24xx.
+  This directory should be kept to items shared between the platform
+  code (arch/arm/plat-s3c24xx) and the arch/arm/mach-s3c24* code.
+
+  Each cpu has a directory with the support files for it, and the
+  machines that carry the device. For example S3C2410 is contained
+  in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440
+
+  Register, kernel and platform data definitions are held in the
+  include/asm-arm/arch-s3c2410 directory.
+
+
 Machines
 --------
 
diff --git a/Documentation/auxdisplay/cfag12864b b/Documentation/auxdisplay/cfag12864b
new file mode 100644
index 0000000..3572b98
--- /dev/null
+++ b/Documentation/auxdisplay/cfag12864b
@@ -0,0 +1,105 @@
+	===================================
+	cfag12864b LCD Driver Documentation
+	===================================
+
+License:		GPLv2
+Author & Maintainer:	Miguel Ojeda Sandonis <maxextreme@gmail.com>
+Date:			2006-10-27
+
+
+
+--------
+0. INDEX
+--------
+
+	1. DRIVER INFORMATION
+	2. DEVICE INFORMATION
+	3. WIRING
+	4. USERSPACE PROGRAMMING
+
+
+---------------------
+1. DRIVER INFORMATION
+---------------------
+
+This driver support one cfag12864b display at time.
+
+
+---------------------
+2. DEVICE INFORMATION
+---------------------
+
+Manufacturer:	Crystalfontz
+Device Name:	Crystalfontz 12864b LCD Series
+Device Code:	cfag12864b
+Webpage:	http://www.crystalfontz.com
+Device Webpage:	http://www.crystalfontz.com/products/12864b/
+Type:		LCD (Liquid Crystal Display)
+Width:		128
+Height:		64
+Colors:		2 (B/N)
+Controller:	ks0108
+Controllers:	2
+Pages:		8 each controller
+Addresses:	64 each page
+Data size:	1 byte each address
+Memory size:	2 * 8 * 64 * 1 = 1024 bytes = 1 Kbyte
+
+
+---------
+3. WIRING
+---------
+
+The cfag12864b LCD Series don't have official wiring.
+
+The common wiring is done to the parallel port as shown:
+
+Parallel Port                          cfag12864b
+
+  Name Pin#                            Pin# Name
+
+Strobe ( 1)------------------------------(17) Enable
+Data 0 ( 2)------------------------------( 4) Data 0
+Data 1 ( 3)------------------------------( 5) Data 1
+Data 2 ( 4)------------------------------( 6) Data 2
+Data 3 ( 5)------------------------------( 7) Data 3
+Data 4 ( 6)------------------------------( 8) Data 4
+Data 5 ( 7)------------------------------( 9) Data 5
+Data 6 ( 8)------------------------------(10) Data 6
+Data 7 ( 9)------------------------------(11) Data 7
+       (10)                      [+5v]---( 1) Vdd
+       (11)                      [GND]---( 2) Ground
+       (12)                      [+5v]---(14) Reset
+       (13)                      [GND]---(15) Read / Write
+  Line (14)------------------------------(13) Controller Select 1
+       (15)
+  Init (16)------------------------------(12) Controller Select 2
+Select (17)------------------------------(16) Data / Instruction
+Ground (18)---[GND]              [+5v]---(19) LED +
+Ground (19)---[GND]
+Ground (20)---[GND]              E    A             Values:
+Ground (21)---[GND]       [GND]---[P1]---(18) Vee    · R = Resistor = 22 ohm
+Ground (22)---[GND]                |                 · P1 = Preset = 10 Kohm
+Ground (23)---[GND]       ----   S ------( 3) V0     · P2 = Preset = 1 Kohm
+Ground (24)---[GND]       |  |
+Ground (25)---[GND] [GND]---[P2]---[R]---(20) LED -
+
+
+------------------------
+4. USERSPACE PROGRAMMING
+------------------------
+
+The cfag12864bfb describes a framebuffer device (/dev/fbX).
+
+It has a size of 1024 bytes = 1 Kbyte.
+Each bit represents one pixel. If the bit is high, the pixel will
+turn on. If the pixel is low, the pixel will turn off.
+
+You can use the framebuffer as a file: fopen, fwrite, fclose...
+Although the LCD won't get updated until the next refresh time arrives.
+
+Also, you can mmap the framebuffer: open & mmap, munmap & close...
+which is the best option for most uses.
+
+Check Documentation/auxdisplay/cfag12864b-example.c
+for a real working userspace complete program with usage examples.
diff --git a/Documentation/auxdisplay/cfag12864b-example.c b/Documentation/auxdisplay/cfag12864b-example.c
new file mode 100644
index 0000000..7bfac35
--- /dev/null
+++ b/Documentation/auxdisplay/cfag12864b-example.c
@@ -0,0 +1,282 @@
+/*
+ *    Filename: cfag12864b-example.c
+ *     Version: 0.1.0
+ * Description: cfag12864b LCD userspace example program
+ *     License: GPLv2
+ *
+ *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *        Date: 2006-10-31
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ * ------------------------
+ * start of cfag12864b code
+ * ------------------------
+ */
+
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#define CFAG12864B_WIDTH		(128)
+#define CFAG12864B_HEIGHT		(64)
+#define CFAG12864B_SIZE			(128 * 64 / 8)
+#define CFAG12864B_BPB			(8)
+#define CFAG12864B_ADDRESS(x, y)	((y) * CFAG12864B_WIDTH / \
+					CFAG12864B_BPB + (x) / CFAG12864B_BPB)
+#define CFAG12864B_BIT(n)		(((unsigned char) 1) << (n))
+
+#undef CFAG12864B_DOCHECK
+#ifdef CFAG12864B_DOCHECK
+	#define CFAG12864B_CHECK(x, y)		((x) < CFAG12864B_WIDTH && \
+						(y) < CFAG12864B_HEIGHT)
+#else
+	#define CFAG12864B_CHECK(x, y)		(1)
+#endif
+
+int cfag12864b_fd;
+unsigned char * cfag12864b_mem;
+unsigned char cfag12864b_buffer[CFAG12864B_SIZE];
+
+/*
+ * init a cfag12864b framebuffer device
+ *
+ * No error:       return = 0
+ * Unable to open: return = -1
+ * Unable to mmap: return = -2
+ */
+int cfag12864b_init(char *path)
+{
+	cfag12864b_fd = open(path, O_RDWR);
+	if (cfag12864b_fd == -1)
+		return -1;
+
+	cfag12864b_mem = mmap(0, CFAG12864B_SIZE, PROT_READ | PROT_WRITE,
+		MAP_SHARED, cfag12864b_fd, 0);
+	if (cfag12864b_mem == MAP_FAILED) {
+		close(cfag12864b_fd);
+		return -2;
+	}
+
+	return 0;
+}
+
+/*
+ * exit a cfag12864b framebuffer device
+ */
+void cfag12864b_exit(void)
+{
+	munmap(cfag12864b_mem, CFAG12864B_SIZE);
+	close(cfag12864b_fd);
+}
+
+/*
+ * set (x, y) pixel
+ */
+void cfag12864b_set(unsigned char x, unsigned char y)
+{
+	if (CFAG12864B_CHECK(x, y))
+		cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] |=
+			CFAG12864B_BIT(x % CFAG12864B_BPB);
+}
+
+/*
+ * unset (x, y) pixel
+ */
+void cfag12864b_unset(unsigned char x, unsigned char y)
+{
+	if (CFAG12864B_CHECK(x, y))
+		cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &=
+			~CFAG12864B_BIT(x % CFAG12864B_BPB);
+}
+
+/*
+ * is set (x, y) pixel?
+ *
+ * Pixel off: return = 0
+ * Pixel on:  return = 1
+ */
+unsigned char cfag12864b_isset(unsigned char x, unsigned char y)
+{
+	if (CFAG12864B_CHECK(x, y))
+		if (cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &
+			CFAG12864B_BIT(x % CFAG12864B_BPB))
+			return 1;
+
+	return 0;
+}
+
+/*
+ * not (x, y) pixel
+ */
+void cfag12864b_not(unsigned char x, unsigned char y)
+{
+	if (cfag12864b_isset(x, y))
+		cfag12864b_unset(x, y);
+	else
+		cfag12864b_set(x, y);
+}
+
+/*
+ * fill (set all pixels)
+ */
+void cfag12864b_fill(void)
+{
+	unsigned short i;
+
+	for (i = 0; i < CFAG12864B_SIZE; i++)
+		cfag12864b_buffer[i] = 0xFF;
+}
+
+/*
+ * clear (unset all pixels)
+ */
+void cfag12864b_clear(void)
+{
+	unsigned short i;
+
+	for (i = 0; i < CFAG12864B_SIZE; i++)
+		cfag12864b_buffer[i] = 0;
+}
+
+/*
+ * format a [128*64] matrix
+ *
+ * Pixel off: src[i] = 0
+ * Pixel on:  src[i] > 0
+ */
+void cfag12864b_format(unsigned char * matrix)
+{
+	unsigned char i, j, n;
+
+	for (i = 0; i < CFAG12864B_HEIGHT; i++)
+	for (j = 0; j < CFAG12864B_WIDTH / CFAG12864B_BPB; j++) {
+		cfag12864b_buffer[i * CFAG12864B_WIDTH / CFAG12864B_BPB +
+			j] = 0;
+		for (n = 0; n < CFAG12864B_BPB; n++)
+			if (matrix[i * CFAG12864B_WIDTH +
+				j * CFAG12864B_BPB + n])
+				cfag12864b_buffer[i * CFAG12864B_WIDTH /
+					CFAG12864B_BPB + j] |=
+					CFAG12864B_BIT(n);
+	}
+}
+
+/*
+ * blit buffer to lcd
+ */
+void cfag12864b_blit(void)
+{
+	memcpy(cfag12864b_mem, cfag12864b_buffer, CFAG12864B_SIZE);
+}
+
+/*
+ * ----------------------
+ * end of cfag12864b code
+ * ----------------------
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#define EXAMPLES	6
+
+void example(unsigned char n)
+{
+	unsigned short i, j;
+	unsigned char matrix[CFAG12864B_WIDTH * CFAG12864B_HEIGHT];
+
+	if (n > EXAMPLES)
+		return;
+
+	printf("Example %i/%i - ", n, EXAMPLES);
+
+	switch (n) {
+	case 1:
+		printf("Draw points setting bits");
+		cfag12864b_clear();
+		for (i = 0; i < CFAG12864B_WIDTH; i += 2)
+			for (j = 0; j < CFAG12864B_HEIGHT; j += 2)
+				cfag12864b_set(i, j);
+		break;
+
+	case 2:
+		printf("Clear the LCD");
+		cfag12864b_clear();
+		break;
+
+	case 3:
+		printf("Draw rows formatting a [128*64] matrix");
+		memset(matrix, 0, CFAG12864B_WIDTH * CFAG12864B_HEIGHT);
+		for (i = 0; i < CFAG12864B_WIDTH; i++)
+			for (j = 0; j < CFAG12864B_HEIGHT; j += 2)
+				matrix[j * CFAG12864B_WIDTH + i] = 1;
+		cfag12864b_format(matrix);
+		break;
+
+	case 4:
+		printf("Fill the lcd");
+		cfag12864b_fill();
+		break;
+
+	case 5:
+		printf("Draw columns unsetting bits");
+		for (i = 0; i < CFAG12864B_WIDTH; i += 2)
+			for (j = 0; j < CFAG12864B_HEIGHT; j++)
+				cfag12864b_unset(i, j);
+		break;
+
+	case 6:
+		printf("Do negative not-ing all bits");
+		for (i = 0; i < CFAG12864B_WIDTH; i++)
+			for (j = 0; j < CFAG12864B_HEIGHT; j ++)
+				cfag12864b_not(i, j);
+		break;
+	}
+
+	puts(" - [Press Enter]");
+}
+
+int main(int argc, char *argv[])
+{
+	unsigned char n;
+
+	if (argc != 2) {
+		printf(
+			"Sintax:  %s fbdev\n"
+			"Usually: /dev/fb0, /dev/fb1...\n", argv[0]);
+		return -1;
+	}
+
+	if (cfag12864b_init(argv[1])) {
+		printf("Can't init %s fbdev\n", argv[1]);
+		return -2;
+	}
+
+	for (n = 1; n <= EXAMPLES; n++) {
+		example(n);
+		cfag12864b_blit();
+		while (getchar() != '\n');
+	}
+
+	cfag12864b_exit();
+
+	return 0;
+}
diff --git a/Documentation/auxdisplay/ks0108 b/Documentation/auxdisplay/ks0108
new file mode 100644
index 0000000..92b03b6
--- /dev/null
+++ b/Documentation/auxdisplay/ks0108
@@ -0,0 +1,55 @@
+	==========================================
+	ks0108 LCD Controller Driver Documentation
+	==========================================
+
+License:		GPLv2
+Author & Maintainer:	Miguel Ojeda Sandonis <maxextreme@gmail.com>
+Date:			2006-10-27
+
+
+
+--------
+0. INDEX
+--------
+
+	1. DRIVER INFORMATION
+	2. DEVICE INFORMATION
+	3. WIRING
+
+
+---------------------
+1. DRIVER INFORMATION
+---------------------
+
+This driver support the ks0108 LCD controller.
+
+
+---------------------
+2. DEVICE INFORMATION
+---------------------
+
+Manufacturer:	Samsung
+Device Name:	KS0108 LCD Controller
+Device Code:	ks0108
+Webpage:	-
+Device Webpage:	-
+Type:		LCD Controller (Liquid Crystal Display Controller)
+Width:		64
+Height:		64
+Colors:		2 (B/N)
+Pages:		8
+Addresses:	64 each page
+Data size:	1 byte each address
+Memory size:	8 * 64 * 1 = 512 bytes
+
+
+---------
+3. WIRING
+---------
+
+The driver supports data parallel port wiring.
+
+If you aren't building LCD related hardware, you should check
+your LCD specific wiring information in the same folder.
+
+For example, check Documentation/auxdisplay/cfag12864b.
diff --git a/Documentation/cdrom/packet-writing.txt b/Documentation/cdrom/packet-writing.txt
index 7715d22..cf1f812 100644
--- a/Documentation/cdrom/packet-writing.txt
+++ b/Documentation/cdrom/packet-writing.txt
@@ -93,7 +93,7 @@
 Using the pktcdvd sysfs interface
 ---------------------------------
 
-Since Linux 2.6.19, the pktcdvd module has a sysfs interface
+Since Linux 2.6.20, the pktcdvd module has a sysfs interface
 and can be controlled by it. For example the "pktcdvd" tool uses
 this interface. (see http://people.freenet.de/BalaGi#pktcdvd )
 
diff --git a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
index 5a03a28..e41a79a 100644
--- a/Documentation/crypto/api-intro.txt
+++ b/Documentation/crypto/api-intro.txt
@@ -193,6 +193,7 @@
   Kartikey Mahendra Bhatt (CAST6)
   Jon Oberheide (ARC4)
   Jouni Malinen (Michael MIC)
+  NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
 
 SHA1 algorithm contributors:
   Jean-Francois Dive
@@ -246,6 +247,9 @@
 VIA PadLock contributors:
   Michal Ludvig
 
+Camellia algorithm contributors:
+  NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
+
 Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 
 Please send any credits updates or corrections to:
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
new file mode 100644
index 0000000..5163b85
--- /dev/null
+++ b/Documentation/driver-model/devres.txt
@@ -0,0 +1,268 @@
+Devres - Managed Device Resource
+================================
+
+Tejun Heo	<teheo@suse.de>
+
+First draft	10 January 2007
+
+
+1. Intro			: Huh? Devres?
+2. Devres			: Devres in a nutshell
+3. Devres Group			: Group devres'es and release them together
+4. Details			: Life time rules, calling context, ...
+5. Overhead			: How much do we have to pay for this?
+6. List of managed interfaces	: Currently implemented managed interfaces
+
+
+  1. Intro
+  --------
+
+devres came up while trying to convert libata to use iomap.  Each
+iomapped address should be kept and unmapped on driver detach.  For
+example, a plain SFF ATA controller (that is, good old PCI IDE) in
+native mode makes use of 5 PCI BARs and all of them should be
+maintained.
+
+As with many other device drivers, libata low level drivers have
+sufficient bugs in ->remove and ->probe failure path.  Well, yes,
+that's probably because libata low level driver developers are lazy
+bunch, but aren't all low level driver developers?  After spending a
+day fiddling with braindamaged hardware with no document or
+braindamaged document, if it's finally working, well, it's working.
+
+For one reason or another, low level drivers don't receive as much
+attention or testing as core code, and bugs on driver detach or
+initilaization failure doesn't happen often enough to be noticeable.
+Init failure path is worse because it's much less travelled while
+needs to handle multiple entry points.
+
+So, many low level drivers end up leaking resources on driver detach
+and having half broken failure path implementation in ->probe() which
+would leak resources or even cause oops when failure occurs.  iomap
+adds more to this mix.  So do msi and msix.
+
+
+  2. Devres
+  ---------
+
+devres is basically linked list of arbitrarily sized memory areas
+associated with a struct device.  Each devres entry is associated with
+a release function.  A devres can be released in several ways.  No
+matter what, all devres entries are released on driver detach.  On
+release, the associated release function is invoked and then the
+devres entry is freed.
+
+Managed interface is created for resources commonly used by device
+drivers using devres.  For example, coherent DMA memory is acquired
+using dma_alloc_coherent().  The managed version is called
+dmam_alloc_coherent().  It is identical to dma_alloc_coherent() except
+for the DMA memory allocated using it is managed and will be
+automatically released on driver detach.  Implementation looks like
+the following.
+
+  struct dma_devres {
+	size_t		size;
+	void		*vaddr;
+	dma_addr_t	dma_handle;
+  };
+
+  static void dmam_coherent_release(struct device *dev, void *res)
+  {
+	struct dma_devres *this = res;
+
+	dma_free_coherent(dev, this->size, this->vaddr, this->dma_handle);
+  }
+
+  dmam_alloc_coherent(dev, size, dma_handle, gfp)
+  {
+	struct dma_devres *dr;
+	void *vaddr;
+
+	dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp);
+	...
+
+	/* alloc DMA memory as usual */
+	vaddr = dma_alloc_coherent(...);
+	...
+
+	/* record size, vaddr, dma_handle in dr */
+	dr->vaddr = vaddr;
+	...
+
+	devres_add(dev, dr);
+
+	return vaddr;
+  }
+
+If a driver uses dmam_alloc_coherent(), the area is guaranteed to be
+freed whether initialization fails half-way or the device gets
+detached.  If most resources are acquired using managed interface, a
+driver can have much simpler init and exit code.  Init path basically
+looks like the following.
+
+  my_init_one()
+  {
+	struct mydev *d;
+
+	d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
+	if (!d)
+		return -ENOMEM;
+
+	d->ring = dmam_alloc_coherent(...);
+	if (!d->ring)
+		return -ENOMEM;
+
+	if (check something)
+		return -EINVAL;
+	...
+
+	return register_to_upper_layer(d);
+  }
+
+And exit path,
+
+  my_remove_one()
+  {
+	unregister_from_upper_layer(d);
+	shutdown_my_hardware();
+  }
+
+As shown above, low level drivers can be simplified a lot by using
+devres.  Complexity is shifted from less maintained low level drivers
+to better maintained higher layer.  Also, as init failure path is
+shared with exit path, both can get more testing.
+
+
+  3. Devres group
+  ---------------
+
+Devres entries can be grouped using devres group.  When a group is
+released, all contained normal devres entries and properly nested
+groups are released.  One usage is to rollback series of acquired
+resources on failure.  For example,
+
+  if (!devres_open_group(dev, NULL, GFP_KERNEL))
+	return -ENOMEM;
+
+  acquire A;
+  if (failed)
+	goto err;
+
+  acquire B;
+  if (failed)
+	goto err;
+  ...
+
+  devres_remove_group(dev, NULL);
+  return 0;
+
+ err:
+  devres_release_group(dev, NULL);
+  return err_code;
+
+As resource acquision failure usually means probe failure, constructs
+like above are usually useful in midlayer driver (e.g. libata core
+layer) where interface function shouldn't have side effect on failure.
+For LLDs, just returning error code suffices in most cases.
+
+Each group is identified by void *id.  It can either be explicitly
+specified by @id argument to devres_open_group() or automatically
+created by passing NULL as @id as in the above example.  In both
+cases, devres_open_group() returns the group's id.  The returned id
+can be passed to other devres functions to select the target group.
+If NULL is given to those functions, the latest open group is
+selected.
+
+For example, you can do something like the following.
+
+  int my_midlayer_create_something()
+  {
+	if (!devres_open_group(dev, my_midlayer_create_something, GFP_KERNEL))
+		return -ENOMEM;
+
+	...
+
+	devres_close_group(dev, my_midlayer_something);
+	return 0;
+  }
+
+  void my_midlayer_destroy_something()
+  {
+	devres_release_group(dev, my_midlayer_create_soemthing);
+  }
+
+
+  4. Details
+  ----------
+
+Lifetime of a devres entry begins on devres allocation and finishes
+when it is released or destroyed (removed and freed) - no reference
+counting.
+
+devres core guarantees atomicity to all basic devres operations and
+has support for single-instance devres types (atomic
+lookup-and-add-if-not-found).  Other than that, synchronizing
+concurrent accesses to allocated devres data is caller's
+responsibility.  This is usually non-issue because bus ops and
+resource allocations already do the job.
+
+For an example of single-instance devres type, read pcim_iomap_table()
+in lib/iomap.c.
+
+All devres interface functions can be called without context if the
+right gfp mask is given.
+
+
+  5. Overhead
+  -----------
+
+Each devres bookkeeping info is allocated together with requested data
+area.  With debug option turned off, bookkeeping info occupies 16
+bytes on 32bit machines and 24 bytes on 64bit (three pointers rounded
+up to ull alignment).  If singly linked list is used, it can be
+reduced to two pointers (8 bytes on 32bit, 16 bytes on 64bit).
+
+Each devres group occupies 8 pointers.  It can be reduced to 6 if
+singly linked list is used.
+
+Memory space overhead on ahci controller with two ports is between 300
+and 400 bytes on 32bit machine after naive conversion (we can
+certainly invest a bit more effort into libata core layer).
+
+
+  6. List of managed interfaces
+  -----------------------------
+
+IO region
+  devm_request_region()
+  devm_request_mem_region()
+  devm_release_region()
+  devm_release_mem_region()
+
+IRQ
+  devm_request_irq()
+  devm_free_irq()
+
+DMA
+  dmam_alloc_coherent()
+  dmam_free_coherent()
+  dmam_alloc_noncoherent()
+  dmam_free_noncoherent()
+  dmam_declare_coherent_memory()
+  dmam_pool_create()
+  dmam_pool_destroy()
+
+PCI
+  pcim_enable_device()	: after success, all PCI ops become managed
+  pcim_pin_device()	: keep PCI device enabled after release
+
+IOMAP
+  devm_ioport_map()
+  devm_ioport_unmap()
+  devm_ioremap()
+  devm_ioremap_nocache()
+  devm_iounmap()
+  pcim_iomap()
+  pcim_iounmap()
+  pcim_iomap_table()	: array of mapped addresses indexed by BAR
+  pcim_iomap_regions()	: do request_region() and iomap() on multiple BARs
diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
index 9f0bc3b..f7c9262 100644
--- a/Documentation/driver-model/platform.txt
+++ b/Documentation/driver-model/platform.txt
@@ -66,7 +66,7 @@
 
 Device Enumeration
 ~~~~~~~~~~~~~~~~~~
-As a rule, platform specific (and often board-specific) setup code wil
+As a rule, platform specific (and often board-specific) setup code will
 register platform devices:
 
 	int platform_device_register(struct platform_device *pdev);
@@ -106,7 +106,7 @@
     * platform_device.id ... the device instance number, or else "-1"
       to indicate there's only one.
 
-These are catenated, so name/id "serial"/0 indicates bus_id "serial.0", and
+These are concatenated, so name/id "serial"/0 indicates bus_id "serial.0", and
 "serial/3" indicates bus_id "serial.3"; both would use the platform_driver
 named "serial".  While "my_rtc"/-1 would be bus_id "my_rtc" (no instance id)
 and use the platform_driver called "my_rtc".
diff --git a/Documentation/drivers/edac/edac.txt b/Documentation/drivers/edac/edac.txt
index 7b3d969..3c5a9e4 100644
--- a/Documentation/drivers/edac/edac.txt
+++ b/Documentation/drivers/edac/edac.txt
@@ -339,7 +339,21 @@
 
 	'device'
 
-	Symlink to the memory controller device
+	Symlink to the memory controller device.
+
+Sdram memory scrubbing rate:
+
+	'sdram_scrub_rate'
+
+	Read/Write attribute file that controls memory scrubbing. The scrubbing
+	rate is set by writing a minimum bandwith in bytes/sec to the attribute
+	file. The rate will be translated to an internal value that gives at
+	least the specified rate.
+
+	Reading the file will return the actual scrubbing rate employed.
+
+	If configuration fails or memory scrubbing is not implemented, the value
+	of the attribute file will be -1.
 
 
 
diff --git a/Documentation/fb/s3fb.txt b/Documentation/fb/s3fb.txt
new file mode 100644
index 0000000..8a04c0d
--- /dev/null
+++ b/Documentation/fb/s3fb.txt
@@ -0,0 +1,78 @@
+
+	s3fb - fbdev driver for S3 Trio/Virge chips
+	===========================================
+
+
+Supported Hardware
+==================
+
+	S3 Trio32
+	S3 Trio64 (and variants V+, UV+, V2/DX, V2/GX)
+	S3 Virge  (and variants VX, DX, GX and GX2+)
+	S3 Plato/PX		(completely untested)
+	S3 Aurora64V+		(completely untested)
+
+	- only PCI bus supported
+	- only BIOS initialized VGA devices supported
+	- probably not working on big endian
+
+I tested s3fb on Trio64 (plain, V+ and V2/DX) and Virge (plain, VX, DX),
+all on i386.
+
+
+Supported Features
+==================
+
+	*  4 bpp pseudocolor modes (with 18bit palette, two variants)
+	*  8 bpp pseudocolor mode (with 18bit palette)
+	* 16 bpp truecolor modes (RGB 555 and RGB 565)
+	* 24 bpp truecolor mode (RGB 888) on (only on Virge VX)
+	* 32 bpp truecolor mode (RGB 888) on (not on Virge VX)
+	* text mode (activated by bpp = 0)
+	* interlaced mode variant (not available in text mode)
+	* doublescan mode variant (not available in text mode)
+	* panning in both directions
+	* suspend/resume support
+	* DPMS support
+
+Text mode is supported even in higher resolutions, but there is limitation
+to lower pixclocks (maximum between 50-60 MHz, depending on specific hardware).
+This limitation is not enforced by driver. Text mode supports 8bit wide fonts
+only (hardware limitation) and 16bit tall fonts (driver limitation).
+
+There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with
+packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode
+with interleaved planes (1 byte interleave), MSB first. Both modes support
+8bit wide fonts only (driver limitation).
+
+Suspend/resume works on systems that initialize video card during resume and
+if device is active (for example used by fbcon).
+
+
+Missing Features
+================
+(alias TODO list)
+
+	* secondary (not initialized by BIOS) device support
+   	* big endian support
+	* Zorro bus support
+	* MMIO support
+	* 24 bpp mode support on more cards
+	* support for fontwidths != 8 in 4 bpp modes
+	* support for fontheight != 16 in text mode
+	* composite and external sync (is anyone able to test this?)
+	* hardware cursor
+	* video overlay support
+	* vsync synchronization
+	* feature connector support
+	* acceleration support (8514-like 2D, Virge 3D, busmaster transfers)
+	* better values for some magic registers (performance issues)
+
+
+Known bugs
+==========
+
+	* cursor disable in text mode doesn't work
+
+--
+Ondrej Zajicek <santiago@crfreenet.org>
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 2dc5e5d..6a451f4 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -50,22 +50,6 @@
 
 ---------------------------
 
-What:	ieee1394 core's unused exports (CONFIG_IEEE1394_EXPORT_FULL_API)
-When:	January 2007
-Why:	There are no projects known to use these exported symbols, except
-	dfg1394 (uses one symbol whose functionality is core-internal now).
-Who:	Stefan Richter <stefanr@s5r6.in-berlin.de>
-
----------------------------
-
-What:	ieee1394's *_oui sysfs attributes (CONFIG_IEEE1394_OUI_DB)
-When:	January 2007
-Files:	drivers/ieee1394/: oui.db, oui2c.sh
-Why:	big size, little value
-Who:	Stefan Richter <stefanr@s5r6.in-berlin.de>
-
----------------------------
-
 What:	Video4Linux API 1 ioctls and video_decoder.h from Video devices.
 When:	December 2006
 Why:	V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
@@ -186,18 +170,6 @@
 
 ---------------------------
 
-What:	find_trylock_page
-When:	January 2007
-Why:	The interface no longer has any callers left in the kernel. It
-	is an odd interface (compared with other find_*_page functions), in
-	that it does not take a refcount to the page, only the page lock.
-	It should be replaced with find_get_page or find_lock_page if possible.
-	This feature removal can be reevaluated if users of the interface
-	cannot cleanly use something else.
-Who:	Nick Piggin <npiggin@suse.de>
-
----------------------------
-
 What:	Interrupt only SA_* flags
 When:	Januar 2007
 Why:	The interrupt related SA_* flags are replaced by IRQF_* to move them
@@ -243,6 +215,13 @@
 
 ---------------------------
 
+What:  drivers depending on OBSOLETE_OSS
+When:  options in 2.6.22, code in 2.6.24
+Why:   OSS drivers with ALSA replacements
+Who:   Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
 What:	IPv4 only connection tracking/NAT/helpers
 When:	2.6.22
 Why:	The new layer 3 independant connection tracking replaces the old
@@ -274,29 +253,6 @@
 
 ---------------------------
 
-<<<<<<< test:Documentation/feature-removal-schedule.txt
-What:	ACPI hotkey driver (CONFIG_ACPI_HOTKEY)
-When:	2.6.21
-Why:	hotkey.c was an attempt to consolidate multiple drivers that use
-	ACPI to implement hotkeys.  However, hotkeys are not documented
-	in the ACPI specification, so the drivers used undocumented
-	vendor-specific hooks and turned out to be more different than
-	the same.
-
-	Further, the keys and the features supplied by each platform
-	are different, so there will always be a need for
-	platform-specific drivers.
-
-	So the new plan is to delete hotkey.c and instead, work on the
-	platform specific drivers to try to make them look the same
-	to the user when they supply the same features.
-
-	hotkey.c has always depended on CONFIG_EXPERIMENTAL
-
-Who:	Len Brown <len.brown@intel.com>
-
----------------------------
-
 What:	/sys/firmware/acpi/namespace
 When:	2.6.21
 Why:	The ACPI namespace is effectively the symbol list for
@@ -327,16 +283,24 @@
 
 ---------------------------
 
-What:	JFFS (version 1)
-When:	2.6.21
-Why:	Unmaintained for years, superceded by JFFS2 for years.
-Who:	Jeff Garzik <jeff@garzik.org>
-
----------------------------
-
 What:   sk98lin network driver
 When:   July 2007
 Why:    In kernel tree version of driver is unmaintained. Sk98lin driver
 	replaced by the skge driver. 
 Who:    Stephen Hemminger <shemminger@osdl.org>
 
+---------------------------
+
+What:	Compaq touchscreen device emulation
+When:	Oct 2007
+Files:	drivers/input/tsdev.c
+Why:	The code says it was obsolete when it was written in 2001.
+	tslib is a userspace library which does anything tsdev can do and
+	much more besides in userspace where this code belongs. There is no
+	longer any need for tsdev and applications should have converted to
+	use tslib by now.
+	The name "tsdev" is also extremely confusing and lots of people have
+	it loaded when they don't need/use it.
+Who:	Richard Purdie <rpurdie@rpsys.net>
+
+---------------------------
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 4dc28cc..57178588 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -4,6 +4,8 @@
 	- explanation of how to make filesystems exportable.
 Locking
 	- info on locking rules as they pertain to Linux VFS.
+9p.txt
+	- 9p (v9fs) is an implementation of the Plan 9 remote fs protocol.
 adfs.txt
 	- info and mount options for the Acorn Advanced Disc Filing System.
 afs.txt
@@ -82,8 +84,6 @@
 	- info and mount options for the UDF filesystem.
 ufs.txt
 	- info on the ufs filesystem.
-v9fs.txt
-	- v9fs is a Unix implementation of the Plan 9 9p remote fs protocol.
 vfat.txt
 	- info on using the VFAT filesystem used in Windows NT and Windows 95
 vfs.txt
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt
index 4d075a4..bbd8b28 100644
--- a/Documentation/filesystems/9p.txt
+++ b/Documentation/filesystems/9p.txt
@@ -40,6 +40,10 @@
   aname=name	aname specifies the file tree to access when the server is
   		offering several exported file systems.
 
+  cache=mode	specifies a cacheing policy.  By default, no caches are used.
+			loose = no attempts are made at consistency,
+                                intended for exclusive, read-only mounts
+
   debug=n	specifies debug level.  The debug level is a bitmask.
   			0x01 = display verbose error messages
 			0x02 = developer debug (DEBUG_CURRENT)
diff --git a/Documentation/filesystems/relay.txt b/Documentation/filesystems/relay.txt
index d6788da..7fbb6ff 100644
--- a/Documentation/filesystems/relay.txt
+++ b/Documentation/filesystems/relay.txt
@@ -157,7 +157,7 @@
   channel management functions:
 
     relay_open(base_filename, parent, subbuf_size, n_subbufs,
-               callbacks)
+               callbacks, private_data)
     relay_close(chan)
     relay_flush(chan)
     relay_reset(chan)
@@ -251,7 +251,7 @@
 
 And an example relay_open() invocation using them:
 
-  chan = relay_open("cpu", NULL, SUBBUF_SIZE, N_SUBBUFS, &relay_callbacks);
+  chan = relay_open("cpu", NULL, SUBBUF_SIZE, N_SUBBUFS, &relay_callbacks, NULL);
 
 If the create_buf_file() callback fails, or isn't defined, channel
 creation and thus relay_open() will fail.
@@ -289,6 +289,11 @@
 writes in a spinlock, or by copying a write function from relay.h and
 creating a local version that internally does the proper locking.
 
+The private_data passed into relay_open() allows clients to associate
+user-defined data with a channel, and is immediately available
+(including in create_buf_file()) via chan->private_data or
+buf->chan->private_data.
+
 Channel 'modes'
 ---------------
 
diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt
index 7ba2baa..5daa2aa 100644
--- a/Documentation/filesystems/sysfs-pci.txt
+++ b/Documentation/filesystems/sysfs-pci.txt
@@ -65,7 +65,7 @@
 ----------------------------------------
 
 Legacy I/O port and ISA memory resources are also provided in sysfs if the
-underlying platform supports them.  They're located in the PCI class heirarchy,
+underlying platform supports them.  They're located in the PCI class hierarchy,
 e.g.
 
 	/sys/class/pci_bus/0000:17/
diff --git a/Documentation/filesystems/ufs.txt b/Documentation/filesystems/ufs.txt
index 2b5a56a..7a602ad 100644
--- a/Documentation/filesystems/ufs.txt
+++ b/Documentation/filesystems/ufs.txt
@@ -21,7 +21,7 @@
 		supported as read-write
 
 	ufs2    used in FreeBSD 5.x
-		supported as read-only
+		supported as read-write
 
 	5xbsd	synonym for ufs2
 
@@ -50,12 +50,11 @@
 POSSIBLE PROBLEMS
 =================
 
-There is still bug in reallocation of fragment, in file fs/ufs/balloc.c, 
-line 364. But it seems working on current buffer cache configuration.
+See next section, if you have any.
 
 
 BUG REPORTS
 ===========
 
-Any ufs bug report you can send to daniel.pirkl@email.cz (do not send 
-partition tables bug reports.)
+Any ufs bug report you can send to daniel.pirkl@email.cz or
+to dushistov@mail.ru (do not send partition tables bug reports).
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 7737bfd..ea271f2 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -617,6 +617,11 @@
 	In this case the prepare_write will be retried one the lock is
   	regained.
 
+	Note: the page _must not_ be marked uptodate in this function
+	(or anywhere else) unless it actually is uptodate right now. As
+	soon as a page is marked uptodate, it is possible for a concurrent
+	read(2) to copy it to userspace.
+
   commit_write: If prepare_write succeeds, new data will be copied
         into the page and then commit_write will be called.  It will
         typically update the size of the file (if appropriate) and
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
new file mode 100644
index 0000000..576ce46
--- /dev/null
+++ b/Documentation/gpio.txt
@@ -0,0 +1,274 @@
+GPIO Interfaces
+
+This provides an overview of GPIO access conventions on Linux.
+
+
+What is a GPIO?
+===============
+A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
+digital signal.  They are provided from many kinds of chip, and are familiar
+to Linux developers working with embedded and custom hardware.  Each GPIO
+represents a bit connected to a particular pin, or "ball" on Ball Grid Array
+(BGA) packages.  Board schematics show which external hardware connects to
+which GPIOs.  Drivers can be written generically, so that board setup code
+passes such pin configuration data to drivers.
+
+System-on-Chip (SOC) processors heavily rely on GPIOs.  In some cases, every
+non-dedicated pin can be configured as a GPIO; and most chips have at least
+several dozen of them.  Programmable logic devices (like FPGAs) can easily
+provide GPIOs; multifunction chips like power managers, and audio codecs
+often have a few such pins to help with pin scarcity on SOCs; and there are
+also "GPIO Expander" chips that connect using the I2C or SPI serial busses.
+Most PC southbridges have a few dozen GPIO-capable pins (with only the BIOS
+firmware knowing how they're used).
+
+The exact capabilities of GPIOs vary between systems.  Common options:
+
+  - Output values are writable (high=1, low=0).  Some chips also have
+    options about how that value is driven, so that for example only one
+    value might be driven ... supporting "wire-OR" and similar schemes
+    for the other value.
+
+  - Input values are likewise readable (1, 0).  Some chips support readback
+    of pins configured as "output", which is very useful in such "wire-OR"
+    cases (to support bidirectional signaling).  GPIO controllers may have
+    input de-glitch logic, sometimes with software controls.
+
+  - Inputs can often be used as IRQ signals, often edge triggered but
+    sometimes level triggered.  Such IRQs may be configurable as system
+    wakeup events, to wake the system from a low power state.
+
+  - Usually a GPIO will be configurable as either input or output, as needed
+    by different product boards; single direction ones exist too.
+
+  - Most GPIOs can be accessed while holding spinlocks, but those accessed
+    through a serial bus normally can't.  Some systems support both types.
+
+On a given board each GPIO is used for one specific purpose like monitoring
+MMC/SD card insertion/removal, detecting card writeprotect status, driving
+a LED, configuring a transceiver, bitbanging a serial bus, poking a hardware
+watchdog, sensing a switch, and so on.
+
+
+GPIO conventions
+================
+Note that this is called a "convention" because you don't need to do it this
+way, and it's no crime if you don't.  There **are** cases where portability
+is not the main issue; GPIOs are often used for the kind of board-specific
+glue logic that may even change between board revisions, and can't ever be
+used on a board that's wired differently.  Only least-common-denominator
+functionality can be very portable.  Other features are platform-specific,
+and that can be critical for glue logic.
+
+Plus, this doesn't define an implementation framework, just an interface.
+One platform might implement it as simple inline functions accessing chip
+registers; another might implement it by delegating through abstractions
+used for several very different kinds of GPIO controller.
+
+That said, if the convention is supported on their platform, drivers should
+use it when possible:
+
+	#include <asm/gpio.h>
+
+If you stick to this convention then it'll be easier for other developers to
+see what your code is doing, and help maintain it.
+
+
+Identifying GPIOs
+-----------------
+GPIOs are identified by unsigned integers in the range 0..MAX_INT.  That
+reserves "negative" numbers for other purposes like marking signals as
+"not available on this board", or indicating faults.  Code that doesn't
+touch the underlying hardware treats these integers as opaque cookies.
+
+Platforms define how they use those integers, and usually #define symbols
+for the GPIO lines so that board-specific setup code directly corresponds
+to the relevant schematics.  In contrast, drivers should only use GPIO
+numbers passed to them from that setup code, using platform_data to hold
+board-specific pin configuration data (along with other board specific
+data they need).  That avoids portability problems.
+
+So for example one platform uses numbers 32-159 for GPIOs; while another
+uses numbers 0..63 with one set of GPIO controllers, 64-79 with another
+type of GPIO controller, and on one particular board 80-95 with an FPGA.
+The numbers need not be contiguous; either of those platforms could also
+use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders.
+
+Whether a platform supports multiple GPIO controllers is currently a
+platform-specific implementation issue.
+
+
+Using GPIOs
+-----------
+One of the first things to do with a GPIO, often in board setup code when
+setting up a platform_device using the GPIO, is mark its direction:
+
+	/* set as input or output, returning 0 or negative errno */
+	int gpio_direction_input(unsigned gpio);
+	int gpio_direction_output(unsigned gpio);
+
+The return value is zero for success, else a negative errno.  It should
+be checked, since the get/set calls don't have error returns and since
+misconfiguration is possible.  (These calls could sleep.)
+
+Setting the direction can fail if the GPIO number is invalid, or when
+that particular GPIO can't be used in that mode.  It's generally a bad
+idea to rely on boot firmware to have set the direction correctly, since
+it probably wasn't validated to do more than boot Linux.  (Similarly,
+that board setup code probably needs to multiplex that pin as a GPIO,
+and configure pullups/pulldowns appropriately.)
+
+
+Spinlock-Safe GPIO access
+-------------------------
+Most GPIO controllers can be accessed with memory read/write instructions.
+That doesn't need to sleep, and can safely be done from inside IRQ handlers.
+
+Use these calls to access such GPIOs:
+
+	/* GPIO INPUT:  return zero or nonzero */
+	int gpio_get_value(unsigned gpio);
+
+	/* GPIO OUTPUT */
+	void gpio_set_value(unsigned gpio, int value);
+
+The values are boolean, zero for low, nonzero for high.  When reading the
+value of an output pin, the value returned should be what's seen on the
+pin ... that won't always match the specified output value, because of
+issues including wire-OR and output latencies.
+
+The get/set calls have no error returns because "invalid GPIO" should have
+been reported earlier in gpio_set_direction().  However, note that not all
+platforms can read the value of output pins; those that can't should always
+return zero.  Also, using these calls for GPIOs that can't safely be accessed
+without sleeping (see below) is an error.
+
+Platform-specific implementations are encouraged to optimize the two
+calls to access the GPIO value in cases where the GPIO number (and for
+output, value) are constant.  It's normal for them to need only a couple
+of instructions in such cases (reading or writing a hardware register),
+and not to need spinlocks.  Such optimized calls can make bitbanging
+applications a lot more efficient (in both space and time) than spending
+dozens of instructions on subroutine calls.
+
+
+GPIO access that may sleep
+--------------------------
+Some GPIO controllers must be accessed using message based busses like I2C
+or SPI.  Commands to read or write those GPIO values require waiting to
+get to the head of a queue to transmit a command and get its response.
+This requires sleeping, which can't be done from inside IRQ handlers.
+
+Platforms that support this type of GPIO distinguish them from other GPIOs
+by returning nonzero from this call:
+
+	int gpio_cansleep(unsigned gpio);
+
+To access such GPIOs, a different set of accessors is defined:
+
+	/* GPIO INPUT:  return zero or nonzero, might sleep */
+	int gpio_get_value_cansleep(unsigned gpio);
+
+	/* GPIO OUTPUT, might sleep */
+	void gpio_set_value_cansleep(unsigned gpio, int value);
+
+Other than the fact that these calls might sleep, and will not be ignored
+for GPIOs that can't be accessed from IRQ handlers, these calls act the
+same as the spinlock-safe calls.
+
+
+Claiming and Releasing GPIOs (OPTIONAL)
+---------------------------------------
+To help catch system configuration errors, two calls are defined.
+However, many platforms don't currently support this mechanism.
+
+	/* request GPIO, returning 0 or negative errno.
+	 * non-null labels may be useful for diagnostics.
+	 */
+	int gpio_request(unsigned gpio, const char *label);
+
+	/* release previously-claimed GPIO */
+	void gpio_free(unsigned gpio);
+
+Passing invalid GPIO numbers to gpio_request() will fail, as will requesting
+GPIOs that have already been claimed with that call.  The return value of
+gpio_request() must be checked.  (These calls could sleep.)
+
+These calls serve two basic purposes.  One is marking the signals which
+are actually in use as GPIOs, for better diagnostics; systems may have
+several hundred potential GPIOs, but often only a dozen are used on any
+given board.  Another is to catch conflicts between drivers, reporting
+errors when drivers wrongly think they have exclusive use of that signal.
+
+These two calls are optional because not not all current Linux platforms
+offer such functionality in their GPIO support; a valid implementation
+could return success for all gpio_request() calls.  Unlike the other calls,
+the state they represent doesn't normally match anything from a hardware
+register; it's just a software bitmap which clearly is not necessary for
+correct operation of hardware or (bug free) drivers.
+
+Note that requesting a GPIO does NOT cause it to be configured in any
+way; it just marks that GPIO as in use.  Separate code must handle any
+pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown).
+
+
+GPIOs mapped to IRQs
+--------------------
+GPIO numbers are unsigned integers; so are IRQ numbers.  These make up
+two logically distinct namespaces (GPIO 0 need not use IRQ 0).  You can
+map between them using calls like:
+
+	/* map GPIO numbers to IRQ numbers */
+	int gpio_to_irq(unsigned gpio);
+
+	/* map IRQ numbers to GPIO numbers */
+	int irq_to_gpio(unsigned irq);
+
+Those return either the corresponding number in the other namespace, or
+else a negative errno code if the mapping can't be done.  (For example,
+some GPIOs can't used as IRQs.)  It is an unchecked error to use a GPIO
+number that hasn't been marked as an input using gpio_set_direction(), or
+to use an IRQ number that didn't originally come from gpio_to_irq().
+
+These two mapping calls are expected to cost on the order of a single
+addition or subtraction.  They're not allowed to sleep.
+
+Non-error values returned from gpio_to_irq() can be passed to request_irq()
+or free_irq().  They will often be stored into IRQ resources for platform
+devices, by the board-specific initialization code.  Note that IRQ trigger
+options are part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are
+system wakeup capabilities.
+
+Non-error values returned from irq_to_gpio() would most commonly be used
+with gpio_get_value(), for example to initialize or update driver state
+when the IRQ is edge-triggered.
+
+
+
+What do these conventions omit?
+===============================
+One of the biggest things these conventions omit is pin multiplexing, since
+this is highly chip-specific and nonportable.  One platform might not need
+explicit multiplexing; another might have just two options for use of any
+given pin; another might have eight options per pin; another might be able
+to route a given GPIO to any one of several pins.  (Yes, those examples all
+come from systems that run Linux today.)
+
+Related to multiplexing is configuration and enabling of the pullups or
+pulldowns integrated on some platforms.  Not all platforms support them,
+or support them in the same way; and any given board might use external
+pullups (or pulldowns) so that the on-chip ones should not be used.
+
+There are other system-specific mechanisms that are not specified here,
+like the aforementioned options for input de-glitching and wire-OR output.
+Hardware may support reading or writing GPIOs in gangs, but that's usually
+configuration dependent:  for GPIOs sharing the same bank.  (GPIOs are
+commonly grouped in banks of 16 or 32, with a given SOC having several such
+banks.)  Some systems can trigger IRQs from output GPIOs.  Code relying on
+such mechanisms will necessarily be nonportable.
+
+Dynamic definition of GPIOs is not currently supported; for example, as
+a side effect of configuring an add-on board with some GPIO expanders.
+
+These calls are purely for kernel space, but a userspace API could be built
+on top of it.
diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt
new file mode 100644
index 0000000..27f782e
--- /dev/null
+++ b/Documentation/hrtimer/timer_stats.txt
@@ -0,0 +1,68 @@
+timer_stats - timer usage statistics
+------------------------------------
+
+timer_stats is a debugging facility to make the timer (ab)usage in a Linux
+system visible to kernel and userspace developers. It is not intended for
+production usage as it adds significant overhead to the (hr)timer code and the
+(hr)timer data structures.
+
+timer_stats should be used by kernel and userspace developers to verify that
+their code does not make unduly use of timers. This helps to avoid unnecessary
+wakeups, which should be avoided to optimize power consumption.
+
+It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration
+section.
+
+timer_stats collects information about the timer events which are fired in a
+Linux system over a sample period:
+
+- the pid of the task(process) which initialized the timer
+- the name of the process which initialized the timer
+- the function where the timer was intialized
+- the callback function which is associated to the timer
+- the number of events (callbacks)
+
+timer_stats adds an entry to /proc: /proc/timer_stats
+
+This entry is used to control the statistics functionality and to read out the
+sampled information.
+
+The timer_stats functionality is inactive on bootup.
+
+To activate a sample period issue:
+# echo 1 >/proc/timer_stats
+
+To stop a sample period issue:
+# echo 0 >/proc/timer_stats
+
+The statistics can be retrieved by:
+# cat /proc/timer_stats
+
+The readout of /proc/timer_stats automatically disables sampling. The sampled
+information is kept until a new sample period is started. This allows multiple
+readouts.
+
+Sample output of /proc/timer_stats:
+
+Timerstats sample period: 3.888770 s
+  12,     0 swapper          hrtimer_stop_sched_tick (hrtimer_sched_tick)
+  15,     1 swapper          hcd_submit_urb (rh_timer_func)
+   4,   959 kedac            schedule_timeout (process_timeout)
+   1,     0 swapper          page_writeback_init (wb_timer_fn)
+  28,     0 swapper          hrtimer_stop_sched_tick (hrtimer_sched_tick)
+  22,  2948 IRQ 4            tty_flip_buffer_push (delayed_work_timer_fn)
+   3,  3100 bash             schedule_timeout (process_timeout)
+   1,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
+   1,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
+   1,     1 swapper          neigh_table_init_no_netlink (neigh_periodic_timer)
+   1,  2292 ip               __netdev_watchdog_up (dev_watchdog)
+   1,    23 events/1         do_cache_clean (delayed_work_timer_fn)
+90 total events, 30.0 events/sec
+
+The first column is the number of events, the second column the pid, the third
+column is the name of the process. The forth column shows the function which
+initialized the timer and in parantheses the callback function which was
+executed on expiry.
+
+    Thomas, Ingo
+
diff --git a/Documentation/hrtimers/highres.txt b/Documentation/hrtimers/highres.txt
new file mode 100644
index 0000000..ce0e9a9
--- /dev/null
+++ b/Documentation/hrtimers/highres.txt
@@ -0,0 +1,249 @@
+High resolution timers and dynamic ticks design notes
+-----------------------------------------------------
+
+Further information can be found in the paper of the OLS 2006 talk "hrtimers
+and beyond". The paper is part of the OLS 2006 Proceedings Volume 1, which can
+be found on the OLS website:
+http://www.linuxsymposium.org/2006/linuxsymposium_procv1.pdf
+
+The slides to this talk are available from:
+http://tglx.de/projects/hrtimers/ols2006-hrtimers.pdf
+
+The slides contain five figures (pages 2, 15, 18, 20, 22), which illustrate the
+changes in the time(r) related Linux subsystems. Figure #1 (p. 2) shows the
+design of the Linux time(r) system before hrtimers and other building blocks
+got merged into mainline.
+
+Note: the paper and the slides are talking about "clock event source", while we
+switched to the name "clock event devices" in meantime.
+
+The design contains the following basic building blocks:
+
+- hrtimer base infrastructure
+- timeofday and clock source management
+- clock event management
+- high resolution timer functionality
+- dynamic ticks
+
+
+hrtimer base infrastructure
+---------------------------
+
+The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
+the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See
+also figure #2 (OLS slides p. 15)
+
+The main differences to the timer wheel, which holds the armed timer_list type
+timers are:
+       - time ordered enqueueing into a rb-tree
+       - independent of ticks (the processing is based on nanoseconds)
+
+
+timeofday and clock source management
+-------------------------------------
+
+John Stultz's Generic Time Of Day (GTOD) framework moves a large portion of
+code out of the architecture-specific areas into a generic management
+framework, as illustrated in figure #3 (OLS slides p. 18). The architecture
+specific portion is reduced to the low level hardware details of the clock
+sources, which are registered in the framework and selected on a quality based
+decision. The low level code provides hardware setup and readout routines and
+initializes data structures, which are used by the generic time keeping code to
+convert the clock ticks to nanosecond based time values. All other time keeping
+related functionality is moved into the generic code. The GTOD base patch got
+merged into the 2.6.18 kernel.
+
+Further information about the Generic Time Of Day framework is available in the
+OLS 2005 Proceedings Volume 1:
+http://www.linuxsymposium.org/2005/linuxsymposium_procv1.pdf
+
+The paper "We Are Not Getting Any Younger: A New Approach to Time and
+Timers" was written by J. Stultz, D.V. Hart, & N. Aravamudan.
+
+Figure #3 (OLS slides p.18) illustrates the transformation.
+
+
+clock event management
+----------------------
+
+While clock sources provide read access to the monotonically increasing time
+value, clock event devices are used to schedule the next event
+interrupt(s). The next event is currently defined to be periodic, with its
+period defined at compile time. The setup and selection of the event device
+for various event driven functionalities is hardwired into the architecture
+dependent code. This results in duplicated code across all architectures and
+makes it extremely difficult to change the configuration of the system to use
+event interrupt devices other than those already built into the
+architecture. Another implication of the current design is that it is necessary
+to touch all the architecture-specific implementations in order to provide new
+functionality like high resolution timers or dynamic ticks.
+
+The clock events subsystem tries to address this problem by providing a generic
+solution to manage clock event devices and their usage for the various clock
+event driven kernel functionalities. The goal of the clock event subsystem is
+to minimize the clock event related architecture dependent code to the pure
+hardware related handling and to allow easy addition and utilization of new
+clock event devices. It also minimizes the duplicated code across the
+architectures as it provides generic functionality down to the interrupt
+service handler, which is almost inherently hardware dependent.
+
+Clock event devices are registered either by the architecture dependent boot
+code or at module insertion time. Each clock event device fills a data
+structure with clock-specific property parameters and callback functions. The
+clock event management decides, by using the specified property parameters, the
+set of system functions a clock event device will be used to support. This
+includes the distinction of per-CPU and per-system global event devices.
+
+System-level global event devices are used for the Linux periodic tick. Per-CPU
+event devices are used to provide local CPU functionality such as process
+accounting, profiling, and high resolution timers.
+
+The management layer assignes one or more of the folliwing functions to a clock
+event device:
+      - system global periodic tick (jiffies update)
+      - cpu local update_process_times
+      - cpu local profiling
+      - cpu local next event interrupt (non periodic mode)
+
+The clock event device delegates the selection of those timer interrupt related
+functions completely to the management layer. The clock management layer stores
+a function pointer in the device description structure, which has to be called
+from the hardware level handler. This removes a lot of duplicated code from the
+architecture specific timer interrupt handlers and hands the control over the
+clock event devices and the assignment of timer interrupt related functionality
+to the core code.
+
+The clock event layer API is rather small. Aside from the clock event device
+registration interface it provides functions to schedule the next event
+interrupt, clock event device notification service and support for suspend and
+resume.
+
+The framework adds about 700 lines of code which results in a 2KB increase of
+the kernel binary size. The conversion of i386 removes about 100 lines of
+code. The binary size decrease is in the range of 400 byte. We believe that the
+increase of flexibility and the avoidance of duplicated code across
+architectures justifies the slight increase of the binary size.
+
+The conversion of an architecture has no functional impact, but allows to
+utilize the high resolution and dynamic tick functionalites without any change
+to the clock event device and timer interrupt code. After the conversion the
+enabling of high resolution timers and dynamic ticks is simply provided by
+adding the kernel/time/Kconfig file to the architecture specific Kconfig and
+adding the dynamic tick specific calls to the idle routine (a total of 3 lines
+added to the idle function and the Kconfig file)
+
+Figure #4 (OLS slides p.20) illustrates the transformation.
+
+
+high resolution timer functionality
+-----------------------------------
+
+During system boot it is not possible to use the high resolution timer
+functionality, while making it possible would be difficult and would serve no
+useful function. The initialization of the clock event device framework, the
+clock source framework (GTOD) and hrtimers itself has to be done and
+appropriate clock sources and clock event devices have to be registered before
+the high resolution functionality can work. Up to the point where hrtimers are
+initialized, the system works in the usual low resolution periodic mode. The
+clock source and the clock event device layers provide notification functions
+which inform hrtimers about availability of new hardware. hrtimers validates
+the usability of the registered clock sources and clock event devices before
+switching to high resolution mode. This ensures also that a kernel which is
+configured for high resolution timers can run on a system which lacks the
+necessary hardware support.
+
+The high resolution timer code does not support SMP machines which have only
+global clock event devices. The support of such hardware would involve IPI
+calls when an interrupt happens. The overhead would be much larger than the
+benefit. This is the reason why we currently disable high resolution and
+dynamic ticks on i386 SMP systems which stop the local APIC in C3 power
+state. A workaround is available as an idea, but the problem has not been
+tackled yet.
+
+The time ordered insertion of timers provides all the infrastructure to decide
+whether the event device has to be reprogrammed when a timer is added. The
+decision is made per timer base and synchronized across per-cpu timer bases in
+a support function. The design allows the system to utilize separate per-CPU
+clock event devices for the per-CPU timer bases, but currently only one
+reprogrammable clock event device per-CPU is utilized.
+
+When the timer interrupt happens, the next event interrupt handler is called
+from the clock event distribution code and moves expired timers from the
+red-black tree to a separate double linked list and invokes the softirq
+handler. An additional mode field in the hrtimer structure allows the system to
+execute callback functions directly from the next event interrupt handler. This
+is restricted to code which can safely be executed in the hard interrupt
+context. This applies, for example, to the common case of a wakeup function as
+used by nanosleep. The advantage of executing the handler in the interrupt
+context is the avoidance of up to two context switches - from the interrupted
+context to the softirq and to the task which is woken up by the expired
+timer.
+
+Once a system has switched to high resolution mode, the periodic tick is
+switched off. This disables the per system global periodic clock event device -
+e.g. the PIT on i386 SMP systems.
+
+The periodic tick functionality is provided by an per-cpu hrtimer. The callback
+function is executed in the next event interrupt context and updates jiffies
+and calls update_process_times and profiling. The implementation of the hrtimer
+based periodic tick is designed to be extended with dynamic tick functionality.
+This allows to use a single clock event device to schedule high resolution
+timer and periodic events (jiffies tick, profiling, process accounting) on UP
+systems. This has been proved to work with the PIT on i386 and the Incrementer
+on PPC.
+
+The softirq for running the hrtimer queues and executing the callbacks has been
+separated from the tick bound timer softirq to allow accurate delivery of high
+resolution timer signals which are used by itimer and POSIX interval
+timers. The execution of this softirq can still be delayed by other softirqs,
+but the overall latencies have been significantly improved by this separation.
+
+Figure #5 (OLS slides p.22) illustrates the transformation.
+
+
+dynamic ticks
+-------------
+
+Dynamic ticks are the logical consequence of the hrtimer based periodic tick
+replacement (sched_tick). The functionality of the sched_tick hrtimer is
+extended by three functions:
+
+- hrtimer_stop_sched_tick
+- hrtimer_restart_sched_tick
+- hrtimer_update_jiffies
+
+hrtimer_stop_sched_tick() is called when a CPU goes into idle state. The code
+evaluates the next scheduled timer event (from both hrtimers and the timer
+wheel) and in case that the next event is further away than the next tick it
+reprograms the sched_tick to this future event, to allow longer idle sleeps
+without worthless interruption by the periodic tick. The function is also
+called when an interrupt happens during the idle period, which does not cause a
+reschedule. The call is necessary as the interrupt handler might have armed a
+new timer whose expiry time is before the time which was identified as the
+nearest event in the previous call to hrtimer_stop_sched_tick.
+
+hrtimer_restart_sched_tick() is called when the CPU leaves the idle state before
+it calls schedule(). hrtimer_restart_sched_tick() resumes the periodic tick,
+which is kept active until the next call to hrtimer_stop_sched_tick().
+
+hrtimer_update_jiffies() is called from irq_enter() when an interrupt happens
+in the idle period to make sure that jiffies are up to date and the interrupt
+handler has not to deal with an eventually stale jiffy value.
+
+The dynamic tick feature provides statistical values which are exported to
+userspace via /proc/stats and can be made available for enhanced power
+management control.
+
+The implementation leaves room for further development like full tickless
+systems, where the time slice is controlled by the scheduler, variable
+frequency profiling, and a complete removal of jiffies in the future.
+
+
+Aside the current initial submission of i386 support, the patchset has been
+extended to x86_64 and ARM already. Initial (work in progress) support is also
+available for MIPS and PowerPC.
+
+	  Thomas, Ingo
+
+
+
diff --git a/Documentation/hrtimers.txt b/Documentation/hrtimers/hrtimers.txt
similarity index 100%
rename from Documentation/hrtimers.txt
rename to Documentation/hrtimers/hrtimers.txt
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 74a8099..c0528d6 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -135,6 +135,16 @@
 startup, consult lm_sensors's /etc/sensors.conf. (2 = thermistor;
 3 = thermal diode)
 
+
+Fan speed control
+-----------------
+
 The fan speed control features are limited to manual PWM mode. Automatic
 "Smart Guardian" mode control handling is not implemented. However
 if you want to go for "manual mode" just write 1 to pwmN_enable.
+
+If you are only able to control the fan speed with very small PWM values,
+try lowering the PWM base frequency (pwm1_freq). Depending on the fan,
+it may give you a somewhat greater control range. The same frequency is
+used to drive all fan outputs, which is why pwm2_freq and pwm3_freq are
+read-only.
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index efef3b9..d73d2e8 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -166,16 +166,21 @@
 
 pwm[1-*]_enable
 		Switch PWM on and off.
-		Not always present even if fan*_pwm is.
+		Not always present even if pwmN is.
 		0: turn off
 		1: turn on in manual mode
 		2+: turn on in automatic mode
-		Check individual chip documentation files for automatic mode details.
+		Check individual chip documentation files for automatic mode
+		details.
 		RW
 
-pwm[1-*]_mode
-		0: DC mode
-		1: PWM mode
+pwm[1-*]_mode	0: DC mode (direct current)
+		1: PWM mode (pulse-width modulation)
+		RW
+
+pwm[1-*]_freq	Base PWM frequency in Hz.
+		Only possibly available when pwmN_mode is PWM, but not always
+		present even then.
 		RW
 
 pwm[1-*]_auto_channels_temp
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
index 8a15a74..030fac6 100644
--- a/Documentation/hwmon/w83627ehf
+++ b/Documentation/hwmon/w83627ehf
@@ -2,26 +2,29 @@
 =======================
 
 Supported chips:
-  * Winbond W83627EHF/EHG (ISA access ONLY)
+  * Winbond W83627EHF/EHG/DHG (ISA access ONLY)
     Prefix: 'w83627ehf'
     Addresses scanned: ISA address retrieved from Super I/O registers
-    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627EHF_%20W83627EHGb.pdf
+    Datasheet:
+        http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627EHF_%20W83627EHGb.pdf
+        DHG datasheet confidential.
 
 Authors:
         Jean Delvare <khali@linux-fr.org>
         Yuan Mu (Winbond)
         Rudolf Marek <r.marek@assembler.cz>
+        David Hubbard <david.c.hubbard@gmail.com>
 
 Description
 -----------
 
-This driver implements support for the Winbond W83627EHF and W83627EHG
-super I/O chips. We will refer to them collectively as Winbond chips.
+This driver implements support for the Winbond W83627EHF, W83627EHG, and
+W83627DHG super I/O chips. We will refer to them collectively as Winbond chips.
 
 The chips implement three temperature sensors, five fan rotation
-speed sensors, ten analog voltage sensors, alarms with beep warnings (control
-unimplemented), and some automatic fan regulation strategies (plus manual
-fan control mode).
+speed sensors, ten analog voltage sensors (only nine for the 627DHG), alarms
+with beep warnings (control unimplemented), and some automatic fan regulation
+strategies (plus manual fan control mode).
 
 Temperatures are measured in degrees Celsius and measurement resolution is 1
 degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
@@ -55,6 +58,9 @@
 /sys files
 ----------
 
+name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG,
+       it is set to "w83627ehf" and for the W83627DHG it is set to "w83627dhg"
+
 pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
 	   0 (stop) to 255 (full)
 
@@ -83,3 +89,37 @@
 
 Note: last two functions are influenced by other control bits, not yet exported
       by the driver, so a change might not have any effect.
+
+Implementation Details
+----------------------
+
+Future driver development should bear in mind that the following registers have
+different functions on the 627EHF and the 627DHG. Some registers also have
+different power-on default values, but BIOS should already be loading
+appropriate defaults. Note that bank selection must be performed as is currently
+done in the driver for all register addresses.
+
+0x49:  only on DHG, selects temperature source for AUX fan, CPU fan0
+0x4a:  not completely documented for the EHF and the DHG documentation assigns
+       different behavior to bits 7 and 6, including extending the temperature
+       input selection to SmartFan I, not just SmartFan III. Testing on the EHF
+       will reveal whether they are compatible or not.
+
+0x58:  Chip ID: 0xa1=EHF 0xc1=DHG
+0x5e:  only on DHG, has bits to enable "current mode" temperature detection and
+       critical temperature protection
+0x45b: only on EHF, bit 3, vin4 alarm (EHF supports 10 inputs, only 9 on DHG)
+0x552: only on EHF, vin4
+0x558: only on EHF, vin4 high limit
+0x559: only on EHF, vin4 low limit
+0x6b:  only on DHG, SYS fan critical temperature
+0x6c:  only on DHG, CPU fan0 critical temperature
+0x6d:  only on DHG, AUX fan critical temperature
+0x6e:  only on DHG, CPU fan1 critical temperature
+
+0x50-0x55 and 0x650-0x657 are marked "Test Register" for the EHF, but "Reserved
+       Register" for the DHG
+
+The DHG also supports PECI, where the DHG queries Intel CPU temperatures, and
+the ICH8 southbridge gets that data via PECI from the DHG, so that the
+southbridge drives the fans. And the DHG supports SST, a one-wire serial bus.
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
index 3db69a0..c34f0db 100644
--- a/Documentation/i2c/busses/i2c-i801
+++ b/Documentation/i2c/busses/i2c-i801
@@ -48,14 +48,9 @@
 The SMBus controller is function 3 in device 1f. Class 0c05 is SMBus Serial
 Controller.
 
-If you do NOT see the 24x3 device at function 3, and you can't figure out
-any way in the BIOS to enable it,
-
 The ICH chips are quite similar to Intel's PIIX4 chip, at least in the
 SMBus controller.
 
-See the file i2c-piix4 for some additional information.
-
 
 Process Call Support
 --------------------
@@ -74,6 +69,61 @@
 
 The 82801DB (ICH4) and later chips support several SMBus 2.0 features.
 
+
+Hidden ICH SMBus
+----------------
+
+If your system has an Intel ICH south bridge, but you do NOT see the
+SMBus device at 00:1f.3 in lspci, and you can't figure out any way in the
+BIOS to enable it, it means it has been hidden by the BIOS code. Asus is
+well known for first doing this on their P4B motherboard, and many other
+boards after that. Some vendor machines are affected as well.
+
+The first thing to try is the "i2c_ec" ACPI driver. It could be that the
+SMBus was hidden on purpose because it'll be driven by ACPI. If the
+i2c_ec driver works for you, just forget about the i2c-i801 driver and
+don't try to unhide the ICH SMBus. Even if i2c_ec doesn't work, you
+better make sure that the SMBus isn't used by the ACPI code. Try loading
+the "fan" and "thermal" drivers, and check in /proc/acpi/fan and
+/proc/acpi/thermal_zone. If you find anything there, it's likely that
+the ACPI is accessing the SMBus and it's safer not to unhide it. Only
+once you are certain that ACPI isn't using the SMBus, you can attempt
+to unhide it.
+
+In order to unhide the SMBus, we need to change the value of a PCI
+register before the kernel enumerates the PCI devices. This is done in
+drivers/pci/quirks.c, where all affected boards must be listed (see
+function asus_hides_smbus_hostbridge.) If the SMBus device is missing,
+and you think there's something interesting on the SMBus (e.g. a
+hardware monitoring chip), you need to add your board to the list.
+
+The motherboard is identified using the subvendor and subdevice IDs of the
+host bridge PCI device. Get yours with "lspci -n -v -s 00:00.0":
+
+00:00.0 Class 0600: 8086:2570 (rev 02)
+        Subsystem: 1043:80f2
+        Flags: bus master, fast devsel, latency 0
+        Memory at fc000000 (32-bit, prefetchable) [size=32M]
+        Capabilities: [e4] #09 [2106]
+        Capabilities: [a0] AGP version 3.0
+
+Here the host bridge ID is 2570 (82865G/PE/P), the subvendor ID is 1043
+(Asus) and the subdevice ID is 80f2 (P4P800-X). You can find the symbolic
+names for the bridge ID and the subvendor ID in include/linux/pci_ids.h,
+and then add a case for your subdevice ID at the right place in
+drivers/pci/quirks.c. Then please give it very good testing, to make sure
+that the unhidden SMBus doesn't conflict with e.g. ACPI.
+
+If it works, proves useful (i.e. there are usable chips on the SMBus)
+and seems safe, please submit a patch for inclusion into the kernel.
+
+Note: There's a useful script in lm_sensors 2.10.2 and later, named
+unhide_ICH_SMBus (in prog/hotplug), which uses the fakephp driver to
+temporarily unhide the SMBus without having to patch and recompile your
+kernel. It's very convenient if you just want to check if there's
+anything interesting on your hidden ICH SMBus.
+
+
 **********************
 The lm_sensors project gratefully acknowledges the support of Texas
 Instruments in the initial development of this driver.
diff --git a/Documentation/i2c/busses/i2c-parport b/Documentation/i2c/busses/i2c-parport
index 77b995d..dceaba1 100644
--- a/Documentation/i2c/busses/i2c-parport
+++ b/Documentation/i2c/busses/i2c-parport
@@ -19,6 +19,7 @@
  * (type=4) Analog Devices ADM1032 evaluation board
  * (type=5) Analog Devices evaluation boards: ADM1025, ADM1030, ADM1031
  * (type=6) Barco LPT->DVI (K5800236) adapter
+ * (type=7) One For All JP1 parallel port 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
@@ -157,3 +158,17 @@
   http://home.wanadoo.nl/hihihi/libk8005.htm
   http://struyve.mine.nu:8080/index.php?block=k8000
   http://sourceforge.net/projects/libk8005/
+
+
+One For All JP1 parallel port adapter
+-------------------------------------
+
+The JP1 project revolves around a set of remote controls which expose
+the I2C bus their internal configuration EEPROM lives on via a 6 pin
+jumper in the battery compartment. More details can be found at:
+
+http://www.hifi-remote.com/jp1/
+
+Details of the simple parallel port hardware can be found at:
+
+http://www.hifi-remote.com/jp1/hardware.shtml
diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4
index 9214763..7cbe43f 100644
--- a/Documentation/i2c/busses/i2c-piix4
+++ b/Documentation/i2c/busses/i2c-piix4
@@ -6,7 +6,7 @@
     Datasheet: Publicly available at the Intel website
   * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges
     Datasheet: Only available via NDA from ServerWorks
-  * ATI IXP southbridges IXP200, IXP300, IXP400
+  * ATI IXP200, IXP300, IXP400 and SB600 southbridges
     Datasheet: Not publicly available
   * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
     Datasheet: Publicly available at the SMSC website http://www.smsc.com
diff --git a/Documentation/i2c/busses/i2c-viapro b/Documentation/i2c/busses/i2c-viapro
index 2568034..775f489 100644
--- a/Documentation/i2c/busses/i2c-viapro
+++ b/Documentation/i2c/busses/i2c-viapro
@@ -13,6 +13,9 @@
   * VIA Technologies, Inc. VT8235, VT8237R, VT8237A, VT8251
     Datasheet: available on request and under NDA from VIA
 
+  * VIA Technologies, Inc. CX700
+    Datasheet: available on request and under NDA from VIA
+
 Authors:
 	Kyösti Mälkki <kmalkki@cc.hut.fi>,
 	Mark D. Studebaker <mdsxyz123@yahoo.com>,
@@ -44,6 +47,7 @@
  device 1106:3227   (VT8237R)
  device 1106:3337   (VT8237A)
  device 1106:3287   (VT8251)
+ device 1106:8324   (CX700)
 
 If none of these show up, you should look in the BIOS for settings like
 enable ACPI / SMBus or even USB.
@@ -51,3 +55,6 @@
 Except for the oldest chips (VT82C596A/B, VT82C686A and most probably
 VT8231), this driver supports I2C block transactions. Such transactions
 are mainly useful to read from and write to EEPROMs.
+
+The CX700 additionally appears to support SMBus PEC, although this driver
+doesn't implement it yet.
diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
index f03c2a0..ca272b2 100644
--- a/Documentation/i2c/porting-clients
+++ b/Documentation/i2c/porting-clients
@@ -129,6 +129,12 @@
   structure, those name member should be initialized to a driver name
   string. i2c_driver itself has no name member anymore.
 
+* [Driver model] Instead of shutdown or reboot notifiers, provide a
+  shutdown() method in your driver.
+
+* [Power management] Use the driver model suspend() and resume()
+  callbacks instead of the obsolete pm_register() calls.
+
 Coding policy:
 
 * [Copyright] Use (C), not (c), for copyright.
diff --git a/Documentation/i2c/smbus-protocol b/Documentation/i2c/smbus-protocol
index 09f5e5c..8a653c6 100644
--- a/Documentation/i2c/smbus-protocol
+++ b/Documentation/i2c/smbus-protocol
@@ -97,7 +97,7 @@
 =====================
 
 This is the opposite operation of the Read Word Data command. 16 bits
-of data is read from a device, from a designated register that is 
+of data is written to a device, to the designated register that is
 specified through the Comm byte. 
 
 S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 3a057c8..fbcff96 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -21,20 +21,26 @@
 
 Usually, you will implement a single driver structure, and instantiate
 all clients from it. Remember, a driver structure contains general access 
-routines, a client structure specific information like the actual I2C
-address.
+routines, and should be zero-initialized except for fields with data you
+provide.  A client structure holds device-specific information like the
+driver model device node, and its I2C address.
 
 static struct i2c_driver foo_driver = {
 	.driver = {
 		.name	= "foo",
 	},
-	.attach_adapter	= &foo_attach_adapter,
-	.detach_client	= &foo_detach_client,
-	.command	= &foo_command /* may be NULL */
+	.attach_adapter	= foo_attach_adapter,
+	.detach_client	= foo_detach_client,
+	.shutdown	= foo_shutdown,	/* optional */
+	.suspend	= foo_suspend,	/* optional */
+	.resume		= foo_resume,	/* optional */
+	.command	= foo_command,	/* optional */
 }
  
-The name field must match the driver name, including the case. It must not
-contain spaces, and may be up to 31 characters long.
+The name field is the driver name, and must not contain spaces.  It
+should match the module name (if the driver can be compiled as a module),
+although you can use MODULE_ALIAS (passing "foo" in this example) to add
+another name for the module.
 
 All other fields are for call-back functions which will be explained 
 below.
@@ -43,11 +49,18 @@
 Extra client data
 =================
 
-The client structure has a special `data' field that can point to any
-structure at all. You can use this to keep client-specific data. You
+Each client structure has a special `data' field that can point to any
+structure at all.  You should use this to keep device-specific data,
+especially in drivers that handle multiple I2C or SMBUS devices.  You
 do not always need this, but especially for `sensors' drivers, it can
 be very useful.
 
+	/* store the value */
+	void i2c_set_clientdata(struct i2c_client *client, void *data);
+
+	/* retrieve the value */
+	void *i2c_get_clientdata(struct i2c_client *client);
+
 An example structure is below.
 
   struct foo_data {
@@ -493,6 +506,33 @@
 kernel booting (or module loading) is completed.
 
 
+Power Management
+================
+
+If your I2C device needs special handling when entering a system low
+power state -- like putting a transceiver into a low power mode, or
+activating a system wakeup mechanism -- do that in the suspend() method.
+The resume() method should reverse what the suspend() method does.
+
+These are standard driver model calls, and they work just like they
+would for any other driver stack.  The calls can sleep, and can use
+I2C messaging to the device being suspended or resumed (since their
+parent I2C adapter is active when these calls are issued, and IRQs
+are still enabled).
+
+
+System Shutdown
+===============
+
+If your I2C device needs special handling when the system shuts down
+or reboots (including kexec) -- like turning something off -- use a
+shutdown() method.
+
+Again, this is a standard driver model call, working just like it
+would for any other driver stack:  the calls can sleep, and can use
+I2C messaging.
+
+
 Command function
 ================
 
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
index 5a8bd5b..8f750c0 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl-number.txt
@@ -94,8 +94,7 @@
 'L'	00-1F	linux/loop.h
 'L'	E0-FF	linux/ppdd.h		encrypted disk device driver
 					<http://linux01.gwdg.de/~alatham/ppdd.html>
-'M'	all	linux/soundcard.h	conflict!
-'M'	00-1F	linux/isicom.h		conflict!
+'M'	all	linux/soundcard.h
 'N'	00-1F	drivers/usb/scanner.h
 'P'	all	linux/soundcard.h
 'Q'	all	linux/soundcard.h
diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset
index fa0d4cc..55b2852 100644
--- a/Documentation/isdn/README.gigaset
+++ b/Documentation/isdn/README.gigaset
@@ -8,29 +8,33 @@
      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
+
+     Bases:
+        Siemens Gigaset 3070/3075 isdn
+        Siemens Gigaset 4170/4175 isdn
+        Siemens Gigaset SX205/255
+        Siemens Gigaset SX353
+        T-Com Sinus 45 [AB] isdn
+        T-Com Sinus 721X[A] [SE]
         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
+
+     RS232 data boxes:
+        Siemens Gigaset M101 Data
+        T-Com Sinus 45 Data 1
+
+     USB data boxes:
+        Siemens Gigaset M105 Data
+        Siemens Gigaset USB Adapter DECT
+        T-Com Sinus 45 Data 2
+        T-Com 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
@@ -60,14 +64,28 @@
      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).
+     where modulename is ser_gigaset (M101), usb_gigaset (M105), or
+     bas_gigaset (direct USB connection to the base).
+
+     The module ser_gigaset provides a serial line discipline N_GIGASET_M101
+     which drives the device through the regular serial line driver. To use it,
+     run the Gigaset M101 daemon "gigasetm101d" (also available from
+     http://sourceforge.net/projects/gigaset307x/) with the device file of the
+     RS232 port to the M101 as an argument, for example:
+	 gigasetm101d /dev/ttyS1
+     This will open the device file, set its line discipline to N_GIGASET_M101,
+     and then sleep in the background, keeping the device open so that the
+     line discipline remains active. To deactivate it, kill the daemon, for
+     example with
+	 killall gigasetm101d
+     before disconnecting the device.
 
 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/ttyGS0 for M101 (RS232 data boxes)
      - /dev/ttyGU0 for M105 (USB data boxes)
      - /dev/ttyGB0 for the base driver (direct USB connection)
 
@@ -168,6 +186,19 @@
      You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode
      setting (ttyGxy is ttyGU0 or ttyGB0).
 
+2.6. M105 Undocumented USB Requests
+     ------------------------------
+
+     The Gigaset M105 USB data box understands a couple of useful, but
+     undocumented USB commands. These requests are not used in normal
+     operation (for wireless access to the base), but are needed for access
+     to the M105's own configuration mode (registration to the base, baudrate
+     and line format settings, device status queries) via the gigacontr
+     utility. Their use is disabled in the driver by default for safety
+     reasons but can be enabled by setting the kernel configuration option
+     "Support for undocumented USB requests" (GIGASET_UNDOCREQ) to "Y" and
+     recompiling.
+
 
 3.   Troubleshooting
      ---------------
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 4b3d671..bb5306e 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -34,7 +34,7 @@
 	   --- 6.1 Set variables to tweak the build to the architecture
 	   --- 6.2 Add prerequisites to archprepare:
 	   --- 6.3 List directories to visit when descending
-	   --- 6.4 Architecture specific boot images
+	   --- 6.4 Architecture-specific boot images
 	   --- 6.5 Building non-kbuild targets
 	   --- 6.6 Commands useful for building a boot image
 	   --- 6.7 Custom kbuild commands
@@ -124,7 +124,7 @@
 	Example:
 		obj-y += foo.o
 
-	This tell kbuild that there is one object in that directory, named
+	This tells kbuild that there is one object in that directory, named
 	foo.o. foo.o will be built from foo.c or foo.S.
 
 	If foo.o shall be built as a module, the variable obj-m is used.
@@ -353,7 +353,7 @@
 	Special rules are used when the kbuild infrastructure does
 	not provide the required support. A typical example is
 	header files generated during the build process.
-	Another example are the architecture specific Makefiles which
+	Another example are the architecture-specific Makefiles which
 	need special rules to prepare boot images etc.
 
 	Special rules are written as normal Make rules.
@@ -416,7 +416,7 @@
 		#arch/i386/kernel/Makefile
 		vsyscall-flags += $(call ld-option, -Wl$(comma)--hash-style=sysv)
 
-	In the above example vsyscall-flags will be assigned the option
+	In the above example, vsyscall-flags will be assigned the option
 	-Wl$(comma)--hash-style=sysv if it is supported by $(CC).
 	The second argument is optional, and if supplied will be used
 	if first argument is not supported.
@@ -434,7 +434,7 @@
 		#arch/i386/Makefile
 		cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)
 
-	In the above example cflags-y will be assigned the option
+	In the above example, cflags-y will be assigned the option
 	-march=pentium-mmx if supported by $(CC), otherwise -march=i586.
 	The second argument to cc-option is optional, and if omitted,
 	cflags-y will be assigned no value if first option is not supported.
@@ -750,10 +750,10 @@
    located at the root of the obj tree.
    The very first objects linked are listed in head-y, assigned by
    arch/$(ARCH)/Makefile.
-7) Finally, the architecture specific part does any required post processing
+7) Finally, the architecture-specific part does any required post processing
    and builds the final bootimage.
    - This includes building boot records
-   - Preparing initrd images and thelike
+   - Preparing initrd images and the like
 
 
 --- 6.1 Set variables to tweak the build to the architecture
@@ -880,7 +880,7 @@
 
 	$(head-y) lists objects to be linked first in vmlinux.
 	$(libs-y) lists directories where a lib.a archive can be located.
-	The rest lists directories where a built-in.o object file can be
+	The rest list directories where a built-in.o object file can be
 	located.
 
 	$(init-y) objects will be located after $(head-y).
@@ -888,7 +888,7 @@
 	$(core-y), $(libs-y), $(drivers-y) and $(net-y).
 
 	The top level Makefile defines values for all generic directories,
-	and arch/$(ARCH)/Makefile only adds architecture specific directories.
+	and arch/$(ARCH)/Makefile only adds architecture-specific directories.
 
 	Example:
 		#arch/sparc64/Makefile
@@ -897,7 +897,7 @@
 		drivers-$(CONFIG_OPROFILE)  += arch/sparc64/oprofile/
 
 
---- 6.4 Architecture specific boot images
+--- 6.4 Architecture-specific boot images
 
 	An arch Makefile specifies goals that take the vmlinux file, compress
 	it, wrap it in bootstrapping code, and copy the resulting files
@@ -924,7 +924,7 @@
 	"$(Q)$(MAKE) $(build)=<dir>" is the recommended way to invoke
 	make in a subdirectory.
 
-	There are no rules for naming architecture specific targets,
+	There are no rules for naming architecture-specific targets,
 	but executing "make help" will list all relevant targets.
 	To support this, $(archhelp) must be defined.
 
@@ -982,7 +982,7 @@
 			$(call if_changed,ld/objcopy/gzip)
 
 	When the rule is evaluated, it is checked to see if any files
-	needs an update, or the command line has changed since the last
+	need an update, or the command line has changed since the last
 	invocation. The latter will force a rebuild if any options
 	to the executable have changed.
 	Any target that utilises if_changed must be listed in $(targets),
@@ -1089,7 +1089,7 @@
 	                  assignment.
 
 	The kbuild infrastructure for *lds file are used in several
-	architecture specific files.
+	architecture-specific files.
 
 
 === 7 Kbuild Variables
@@ -1133,7 +1133,7 @@
 
 	This variable defines a place for the arch Makefiles to install
 	the resident kernel image and System.map file.
-	Use this for architecture specific install targets.
+	Use this for architecture-specific install targets.
 
     INSTALL_MOD_PATH, MODLIB
 
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 0733068..2fedc08 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -30,6 +30,10 @@
 regardless of where the kernel loads. Therefore, kexec backs up this
 region just before rebooting into the dump-capture kernel.
 
+Similarly on PPC64 machines first 32KB of physical memory is needed for
+booting regardless of where the kernel is loaded and to support 64K page
+size kexec backs up the first 64KB memory.
+
 All of the necessary information about the system kernel's core image is
 encoded in the ELF format, and stored in a reserved area of memory
 before a crash. The physical address of the start of the ELF header is
@@ -224,7 +228,7 @@
 Dump-capture kernel config options (Arch Dependent, ppc64)
 ----------------------------------------------------------
 
--  Make and install the kernel and its modules. DO NOT add this kernel
+*  Make and install the kernel and its modules. DO NOT add this kernel
    to the boot loader configuration files.
 
 Dump-capture kernel config options (Arch Dependent, ia64)
@@ -251,8 +255,8 @@
 Boot into System Kernel
 =======================
 
-1) Make and install the kernel and its modules. Update the boot loader
-   (such as grub, yaboot, or lilo) configuration files as necessary.
+1) Update the boot loader (such as grub, yaboot, or lilo) configuration
+   files as necessary.
 
 2) Boot the system kernel with the boot parameter "crashkernel=Y@X",
    where Y specifies how much memory to reserve for the dump-capture kernel
@@ -311,10 +315,10 @@
 loading dump-capture kernel.
 
 For i386, x86_64 and ia64:
-	"init 1 irqpoll maxcpus=1"
+	"1 irqpoll maxcpus=1"
 
 For ppc64:
-	"init 1 maxcpus=1 noirqdistrib"
+	"1 maxcpus=1 noirqdistrib"
 
 
 Notes on loading the dump-capture kernel:
@@ -332,8 +336,8 @@
 * You must specify <root-dev> in the format corresponding to the root
   device name in the output of mount command.
 
-* "init 1" boots the dump-capture kernel into single-user mode without
-  networking. If you want networking, use "init 3."
+* Boot parameter "1" boots the dump-capture kernel into single-user
+  mode without networking. If you want networking, use "3".
 
 * We generally don' have to bring up a SMP kernel just to capture the
   dump. Hence generally it is useful either to build a UP dump-capture
@@ -356,10 +360,11 @@
 is called inside interrupt context or die() is called and panic_on_oops is set,
 the system will boot into the dump-capture kernel.
 
-On powererpc systems when a soft-reset is generated, die() is called by all cpus and the system will boot into the dump-capture kernel.
+On powererpc systems when a soft-reset is generated, die() is called by all cpus
+and the system will boot into the dump-capture kernel.
 
 For testing purposes, you can trigger a crash by using "ALT-SysRq-c",
-"echo c > /proc/sysrq-trigger or write a module to force the panic.
+"echo c > /proc/sysrq-trigger" or write a module to force the panic.
 
 Write Out the Dump File
 =======================
@@ -410,12 +415,9 @@
 To Do
 =====
 
-1) Provide a kernel pages filtering mechanism, so core file size is not
-   extreme on systems with huge memory banks.
-
-2) Relocatable kernel can help in maintaining multiple kernels for
-   crash_dump, and the same kernel as the system kernel can be used to
-   capture the dump.
+1) Provide relocatable kernels for all architectures to help in maintaining
+   multiple kernels for crash_dump, and the same kernel as the system kernel
+   can be used to capture the dump.
 
 
 Contact
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt
index 284e7e1..2075c06 100644
--- a/Documentation/kernel-doc-nano-HOWTO.txt
+++ b/Documentation/kernel-doc-nano-HOWTO.txt
@@ -101,16 +101,20 @@
 
 /**
  * function_name(:)? (- short description)?
-(* @parameterx: (description of parameter x)?)*
+(* @parameterx(space)*: (description of parameter x)?)*
 (* a blank line)?
  * (Description:)? (Description of function)?
  * (section header: (section description)? )*
 (*)?*/
 
-The short function description cannot be multiline, but the other
-descriptions can be (and they can contain blank lines). Avoid putting a
-spurious blank line after the function name, or else the description will
-be repeated!
+The short function description ***cannot be multiline***, but the other
+descriptions can be (and they can contain blank lines).  If you continue
+that initial short description onto a second line, that second line will
+appear further down at the beginning of the description section, which is
+almost certainly not what you had in mind.
+
+Avoid putting a spurious blank line after the function name, or else the
+description will be repeated!
 
 All descriptive text is further processed, scanning for the following special
 patterns, which are highlighted appropriately.
@@ -121,6 +125,31 @@
 '@parameter' - name of a parameter
 '%CONST' - name of a constant.
 
+NOTE 1:  The multi-line descriptive text you provide does *not* recognize
+line breaks, so if you try to format some text nicely, as in:
+
+  Return codes
+    0 - cool
+    1 - invalid arg
+    2 - out of memory
+
+this will all run together and produce:
+
+  Return codes 0 - cool 1 - invalid arg 2 - out of memory
+
+NOTE 2:  If the descriptive text you provide has lines that begin with
+some phrase followed by a colon, each of those phrases will be taken as
+a new section heading, which means you should similarly try to avoid text
+like:
+
+  Return codes:
+    0: cool
+    1: invalid arg
+    2: out of memory
+
+every line of which would start a new section.  Again, probably not
+what you were after.
+
 Take a look around the source tree for examples.
 
 
diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt
index b53bccb..c68dafe 100644
--- a/Documentation/kernel-docs.txt
+++ b/Documentation/kernel-docs.txt
@@ -1,10 +1,10 @@
 
-       Index of Documentation for People Interested in Writing and/or
-                                      
-                      Understanding the Linux Kernel.
-                                      
-               Juan-Mariano de Goyeneche <jmseyas@dit.upm.es>
-                                      
+    Index of Documentation for People Interested in Writing and/or
+
+                   Understanding the Linux Kernel.
+
+          Juan-Mariano de Goyeneche <jmseyas@dit.upm.es>
+
 /*
  * The latest version of this document may be found at:
  *   http://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
@@ -61,18 +61,18 @@
        13.-The Linux Kernel Sources, A.-Linux Data Structures, B.-The
        Alpha AXP Processor, C.-Useful Web and FTP Sites, D.-The GNU
        General Public License, Glossary". In short: a must have.
-       
-     * Title: "The Linux Kernel Hackers' Guide"
-       Author: Michael K.Johnson and others.
-       URL: http://www.tldp.org/LDP/khg/HyperNews/get/khg.html
-       Keywords: everything!
-       Description: No more Postscript book-like version. Only HTML now.
-       Many people have contributed. The interface is similar to web
-       available mailing lists archives. You can find some articles and
-       then some mails asking questions about them and/or complementing
-       previous contributions. A little bit anarchic in this aspect, but
-       with some valuable information in some cases.
-       
+
+     * Title: "Linux Device Drivers, 2nd Edition"
+       Author: Alessandro Rubini and Jonathan Corbet.
+       URL: http://www.xml.com/ldd/chapter/book/index.html
+       Keywords: device drivers, modules, debugging, memory, hardware,
+       interrupt handling, char drivers, block drivers, kmod, mmap, DMA,
+       buses.
+       Description: O'Reilly's popular book, now also on-line under the
+       GNU Free Documentation License.
+       Notes: You can also buy it in paper-form from O'Reilly. See below
+       under BOOKS (Not on-line).
+
      * Title: "Conceptual Architecture of the Linux Kernel"
        Author: Ivan T. Bowman.
        URL: http://plg.uwaterloo.ca/~itbowman/papers/CS746G-a1.html
@@ -81,17 +81,17 @@
        Description: Conceptual software arquitecture of the Linux kernel,
        automatically extracted from the source code. Very detailed. Good
        figures. Gives good overall kernel understanding.
-       
+
      * Title: "Concrete Architecture of the Linux Kernel"
        Author: Ivan T. Bowman, Saheem Siddiqi, and Meyer C. Tanuan.
        URL: http://plg.uwaterloo.ca/~itbowman/papers/CS746G-a2.html
-       Keywords: concrete arquitecture, extracted design, reverse
+       Keywords: concrete architecture, extracted design, reverse
        engineering, system structure, dependencies.
-       Description: Concrete arquitecture of the Linux kernel,
+       Description: Concrete architecture of the Linux kernel,
        automatically extracted from the source code. Very detailed. Good
        figures. Gives good overall kernel understanding. This papers
        focus on lower details than its predecessor (files, variables...).
-       
+
      * Title: "Linux as a Case Study: Its Extracted Software
        Architecture"
        Author: Ivan T. Bowman, Richard C. Holt and Neil V. Brewster.
@@ -101,7 +101,7 @@
        Description: Paper appeared at ICSE'99, Los Angeles, May 16-22,
        1999. A mixture of the previous two documents from the same
        author.
-       
+
      * Title: "Overview of the Virtual File System"
        Author: Richard Gooch.
        URL: http://www.atnf.csiro.au/~rgooch/linux/vfs.txt
@@ -111,20 +111,20 @@
        What is it, how it works, operations taken when opening a file or
        mounting a file system and description of important data
        structures explaining the purpose of each of their entries.
-       
+
      * Title: "The Linux RAID-1, 4, 5 Code"
        Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza.
-       URL: http://www2.linuxjournal.com/lj-issues/issue44/2391.html
+       URL: http://www.linuxjournal.com/article.php?sid=2391
        Keywords: RAID, MD driver.
        Description: Linux Journal Kernel Korner article. Here is it's
        abstract: "A description of the implementation of the RAID-1,
        RAID-4 and RAID-5 personalities of the MD device driver in the
        Linux kernel, providing users with high performance and reliable,
        secondary-storage capability using software".
-       
+
      * Title: "Dynamic Kernels: Modularized Device Drivers"
        Author: Alessandro Rubini.
-       URL: http://www2.linuxjournal.com/lj-issues/issue23/1219.html
+       URL: http://www.linuxjournal.com/article.php?sid=1219
        Keywords: device driver, module, loading/unloading modules,
        allocating resources.
        Description: Linux Journal Kernel Korner article. Here is it's
@@ -134,10 +134,10 @@
        loadable modules. This installment presents an introduction to the
        topic, preparing the reader to understand next month's
        installment".
-       
+
      * Title: "Dynamic Kernels: Discovery"
        Author: Alessandro Rubini.
-       URL: http://www2.linuxjournal.com/lj-issues/issue24/1220.html
+       URL: http://www.linuxjournal.com/article.php?sid=1220
        Keywords: character driver, init_module, clean_up module,
        autodetection, mayor number, minor number, file operations,
        open(), close().
@@ -146,20 +146,20 @@
        the actual code to create custom module implementing a character
        device driver. It describes the code for module initialization and
        cleanup, as well as the open() and close() system calls".
-       
+
      * Title: "The Devil's in the Details"
        Author: Georg v. Zezschwitz and Alessandro Rubini.
-       URL: http://www2.linuxjournal.com/lj-issues/issue25/1221.html
+       URL: http://www.linuxjournal.com/article.php?sid=1221
        Keywords: read(), write(), select(), ioctl(), blocking/non
        blocking mode, interrupt handler.
        Description: Linux Journal Kernel Korner article. Here is it's
        abstract: "This article, the third of four on writing character
        device drivers, introduces concepts of reading, writing, and using
        ioctl-calls".
-       
+
      * Title: "Dissecting Interrupts and Browsing DMA"
        Author: Alessandro Rubini and Georg v. Zezschwitz.
-       URL: http://www2.linuxjournal.com/lj-issues/issue26/1222.html
+       URL: http://www.linuxjournal.com/article.php?sid=1222
        Keywords: interrupts, irqs, DMA, bottom halves, task queues.
        Description: Linux Journal Kernel Korner article. Here is it's
        abstract: "This is the fourth in a series of articles about
@@ -170,10 +170,10 @@
        writing, and several different facilities have been provided for
        different situations. We also investigate the complex topic of
        DMA".
-       
+
      * Title: "Device Drivers Concluded"
        Author: Georg v. Zezschwitz.
-       URL: http://www2.linuxjournal.com/lj-issues/issue28/1287.html
+       URL: http://www.linuxjournal.com/article.php?sid=1287
        Keywords: address spaces, pages, pagination, page management,
        demand loading, swapping, memory protection, memory mapping, mmap,
        virtual memory areas (VMAs), vremap, PCI.
@@ -182,10 +182,10 @@
        five articles about character device drivers. In this final
        section, Georg deals with memory mapping devices, beginning with
        an overall description of the Linux memory management concepts".
-       
+
      * Title: "Network Buffers And Memory Management"
        Author: Alan Cox.
-       URL: http://www2.linuxjournal.com/lj-issues/issue30/1312.html
+       URL: http://www.linuxjournal.com/article.php?sid=1312
        Keywords: sk_buffs, network devices, protocol/link layer
        variables, network devices flags, transmit, receive,
        configuration, multicast.
@@ -214,28 +214,26 @@
        of the Coda filesystem. This version document is meant to describe
        the current interface (version 1.0) as well as improvements we
        envisage".
-       
+
      * Title: "Programming PCI-Devices under Linux"
        Author: Claus Schroeter.
        URL:
-       ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/pcip.ps
-       .gz
+       ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/pcip.ps.gz
        Keywords: PCI, device, busmastering.
        Description: 6 pages tutorial on PCI programming under Linux.
        Gives the basic concepts on the architecture of the PCI subsystem,
        as long as basic functions and macros to read/write the devices
        and perform busmastering.
-       
+
      * Title: "Writing Character Device Driver for Linux"
        Author: R. Baruch and C. Schroeter.
        URL:
-       ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/drivers
-       .ps.gz
+       ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/drivers.ps.gz
        Keywords: character device drivers, I/O, signals, DMA, accessing
        ports in user space, kernel environment.
        Description: 68 pages paper on writing character drivers. A little
        bit old (1.993, 1.994) although still useful.
-       
+
      * Title: "Design and Implementation of the Second Extended
        Filesystem"
        Author: Rémy Card, Theodore Ts'o, Stephen Tweedie.
@@ -249,14 +247,14 @@
        e2fsck's passes description... A must read!
        Notes: This paper was first published in the Proceedings of the
        First Dutch International Symposium on Linux, ISBN 90-367-0385-9.
-       
+
      * Title: "Analysis of the Ext2fs structure"
        Author: Louis-Dominique Dubeau.
-       URL: http://step.polymtl.ca/~ldd/ext2fs/ext2fs_toc.html
+       URL: http://www.nondot.org/sabre/os/files/FileSystems/ext2fs/
        Keywords: ext2, filesystem, ext2fs.
        Description: Description of ext2's blocks, directories, inodes,
        bitmaps, invariants...
-       
+
      * Title: "Journaling the Linux ext2fs Filesystem"
        Author: Stephen C. Tweedie.
        URL:
@@ -265,7 +263,7 @@
        Description: Excellent 8-pages paper explaining the journaling
        capabilities added to ext2 by the author, showing different
        problems faced and the alternatives chosen.
-       
+
      * Title: "Kernel API changes from 2.0 to 2.2"
        Author: Richard Gooch.
        URL:
@@ -273,7 +271,7 @@
        Keywords: 2.2, changes.
        Description: Kernel functions/structures/variables which changed
        from 2.0.x to 2.2.x.
-       
+
      * Title: "Kernel API changes from 2.2 to 2.4"
        Author: Richard Gooch.
        URL:
@@ -345,17 +343,7 @@
        Notes: Beware: the main page states: "This document may not be
        published, printed or used in excerpts without explicit permission
        of the author". Fortunately, it may still be read...
-       
-     * Title: "Tour Of the Linux Kernel Source"
-       Author: Vijo Cherian.
-       URL: http://www.geocities.com/vijoc/tolks/tolks.html
-       Keywords: .
-       Description: A classic of this page! Was lost for a while and is
-       back again. Thanks Vijo! TOLKS: the name says it all. A tour of
-       the sources, describing directories, files, variables, data
-       structures... It covers general stuff, device drivers,
-       filesystems, IPC and Networking Code.
-       
+
      * Title: "Linux Kernel Mailing List Glossary"
        Author: various
        URL: http://kernelnewbies.org/glossary/
@@ -377,7 +365,17 @@
        kernels, but most of it applies to 2.2 too; 2.0 is slightly
        different". Freely redistributable under the conditions of the GNU
        General Public License.
-       
+
+     * Title: "Global spinlock list and usage"
+       Author: Rick Lindsley.
+       URL: http://lse.sourceforge.net/lockhier/global-spin-lock
+       Keywords: spinlock.
+       Description: This is an attempt to document both the existence and
+       usage of the spinlocks in the Linux 2.4.5 kernel. Comprehensive
+       list of spinlocks showing when they are used, which functions
+       access them, how each lock is acquired, under what conditions it
+       is held, whether interrupts can occur or not while it is held...
+
      * Title: "Porting Linux 2.0 Drivers To Linux 2.2: Changes and New
        Features "
        Author: Alan Cox.
@@ -385,70 +383,70 @@
        Keywords: ports, porting.
        Description: Article from Linux Magazine on porting from 2.0 to
        2.2 kernels.
-       
+
      * Title: "Porting Device Drivers To Linux 2.2: part II"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-06/gear_01.html
        Keywords: ports, porting.
        Description: Second part on porting from 2.0 to 2.2 kernels.
-       
+
      * Title: "How To Make Sure Your Driver Will Work On The Power
        Macintosh"
        Author: Paul Mackerras.
        URL: http://www.linux-mag.com/1999-07/gear_01.html
        Keywords: Mac, Power Macintosh, porting, drivers, compatibility.
        Description: The title says it all.
-       
+
      * Title: "An Introduction to SCSI Drivers"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-08/gear_01.html
        Keywords: SCSI, device, driver.
        Description: The title says it all.
-       
+
      * Title: "Advanced SCSI Drivers And Other Tales"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-09/gear_01.html
        Keywords: SCSI, device, driver, advanced.
        Description: The title says it all.
-       
+
      * Title: "Writing Linux Mouse Drivers"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-10/gear_01.html
        Keywords: mouse, driver, gpm.
        Description: The title says it all.
-       
+
      * Title: "More on Mouse Drivers"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-11/gear_01.html
        Keywords: mouse, driver, gpm, races, asynchronous I/O.
        Description: The title still says it all.
-       
+
      * Title: "Writing Video4linux Radio Driver"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/1999-12/gear_01.html
        Keywords: video4linux, driver, radio, radio devices.
        Description: The title says it all.
-       
+
      * Title: "Video4linux Drivers, Part 1: Video-Capture Device"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/2000-01/gear_01.html
        Keywords: video4linux, driver, video capture, capture devices,
        camera driver.
        Description: The title says it all.
-       
+
      * Title: "Video4linux Drivers, Part 2: Video-capture Devices"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/2000-02/gear_01.html
        Keywords: video4linux, driver, video capture, capture devices,
        camera driver, control, query capabilities, capability, facility.
        Description: The title says it all.
-       
+
      * Title: "PCI Management in Linux 2.2"
        Author: Alan Cox.
        URL: http://www.linux-mag.com/2000-03/gear_01.html
        Keywords: PCI, bus, bus-mastering.
        Description: The title says it all.
-       
+
      * Title: "Linux 2.4 Kernel Internals"
        Author: Tigran Aivazian and Christoph Hellwig.
        URL: http://www.moses.uklinux.net/patches/lki.html
@@ -456,13 +454,11 @@
        Description: A little book used for a short training course.
        Covers building the kernel image, booting (including SMP bootup),
        process management, VFS and more.
-       
+
      * Title: "Linux IP Networking. A Guide to the Implementation and
        Modification of the Linux Protocol Stack."
        Author: Glenn Herrin.
-       URL:
-       http://kernelnewbies.org/documents/ipnetworking/linuxipnetworking.
-       html
+       URL: http://www.cs.unh.edu/cnrg/gherrin
        Keywords: network, networking, protocol, IP, UDP, TCP, connection,
        socket, receiving, transmitting, forwarding, routing, packets,
        modules, /proc, sk_buff, FIB, tags.
@@ -495,7 +491,7 @@
        drivers for the Linux PCMCIA Card Services interface. It also
        describes how to write user-mode utilities for communicating with
        Card Services.
-       
+
      * Title: "The Linux Kernel NFSD Implementation"
        Author: Neil Brown.
        URL:
@@ -591,47 +587,22 @@
        Pages: 520.
        ISBN: 2-212-08932-5
        Notes: French.
-       
-     * Title: "The Linux Kernel Book"
-       Author: Remy Card, Eric Dumas, Franck Mevel.
-       Publisher: John Wiley & Sons.
-       Date: 1998.
-       ISBN: 0-471-98141-9
-       Notes: English translation.
-       
-     * Title: "Linux 2.0"
-       Author: Remy Card, Eric Dumas, Franck Mevel.
-       Publisher: Gestión 2000.
-       Date: 1997.
-       Pages: 501.
-       ISBN: 8-480-88208-5
-       Notes: Spanish translation.
-       
+
      * Title: "Unix internals -- the new frontiers"
        Author: Uresh Vahalia.
        Publisher: Prentice Hall.
        Date: 1996.
        Pages: 600.
        ISBN: 0-13-101908-2
-       
-     * Title: "Linux Core Kernel Commentary. Guide to Insider's Knowledge
-       on the Core Kernel of the Linux Code"
-       Author: Scott Maxwell.
-       Publisher: Coriolis.
-       Date: 1999.
-       Pages: 592.
-       ISBN: 1-57610-469-9
-       Notes: CD-ROM included. Line by line commentary of the kernel
-       code.
-       
-     * Title: "Linux IP Stacks Commentary"
-       Author: Stephen Satchell and HBJ Clifford.
-       Publisher: Coriolis.
-       Date: 2000.
-       Pages: ???.
-       ISBN: 1-57610-470-2
-       Notes: Line by line source code commentary book.
-       
+
+     * Title:  "The  Design  and Implementation of the 4.4 BSD UNIX
+       Operating System"
+       Author: Marshall Kirk McKusick, Keith Bostic, Michael J. Karels,
+       John S. Quarterman.
+       Publisher: Addison-Wesley.
+       Date: 1996.
+       ISBN: 0-201-54979-4
+
      * Title: "Programming for the real world - POSIX.4"
        Author: Bill O. Gallmeister.
        Publisher: O'Reilly & Associates, Inc..
@@ -640,18 +611,32 @@
        ISBN: I-56592-074-0
        Notes: Though not being directly about Linux, Linux aims to be
        POSIX. Good reference.
-       
-     * Title: "Understanding the Linux Kernel"
-       Author: Daniel P. Bovet and Marco Cesati.
-       Publisher: O'Reilly & Associates, Inc..
-       Date: 2000.
-       Pages: 702.
-       ISBN: 0-596-00002-2
-       Notes: Further information in
-       http://www.oreilly.com/catalog/linuxkernel/
-       
+
+     * Title:  "UNIX  Systems  for  Modern Architectures: Symmetric
+       Multiprocesssing and Caching for Kernel Programmers"
+       Author: Curt Schimmel.
+       Publisher: Addison Wesley.
+       Date: June, 1994.
+       Pages: 432.
+       ISBN: 0-201-63338-8
+
+     * Title:  "The  Design  and Implementation of the 4.3 BSD UNIX
+       Operating System"
+       Author: Samuel J. Leffler, Marshall Kirk McKusick, Michael J.
+       Karels, John S. Quarterman.
+       Publisher: Addison-Wesley.
+       Date: 1989 (reprinted with corrections on October, 1990).
+       ISBN: 0-201-06196-1
+
+     * Title: "The Design of the UNIX Operating System"
+       Author: Maurice J. Bach.
+       Publisher: Prentice Hall.
+       Date: 1986.
+       Pages: 471.
+       ISBN: 0-13-201757-1
+
      MISCELLANEOUS:
-   
+
      * Name: linux/Documentation
        Author: Many.
        URL: Just look inside your kernel sources.
@@ -660,7 +645,7 @@
        inside the Documentation directory. Some pages from this document
        (including this document itself) have been moved there, and might
        be more up to date than the web version.
-       
+
      * Name: "Linux Source Driver"
        URL: http://lsd.linux.cz
        Keywords: Browsing source code.
@@ -671,7 +656,7 @@
        you can search Linux kernel (fulltext, macros, types, functions
        and variables) and LSD can generate patches for you on the fly
        (files, directories or kernel)".
-       
+
      * Name: "Linux Kernel Source Reference"
        Author: Thomas Graichen.
        URL: http://innominate.org/~graichen/projects/lksr/
@@ -681,27 +666,27 @@
        sources of any version starting from 1.0 up to the (daily updated)
        current version available. Also you can check the differences
        between two versions of a file".
-       
+
      * Name: "Cross-Referencing Linux"
        URL: http://lxr.linux.no/source/
        Keywords: Browsing source code.
        Description: Another web-based Linux kernel source code browser.
        Lots of cross references to variables and functions. You can see
        where they are defined and where they are used.
-       
+
      * Name: "Linux Weekly News"
        URL: http://lwn.net
        Keywords: latest kernel news.
        Description: The title says it all. There's a fixed kernel section
        summarizing developers' work, bug fixes, new features and versions
        produced during the week. Published every Thursday.
-       
+
      * Name: "Kernel Traffic"
-       URL: http://www.kerneltraffic.org/kernel-traffic/
+       URL: http://kt.zork.net/kernel-traffic/
        Keywords: linux-kernel mailing list, weekly kernel news.
        Description: Weekly newsletter covering the most relevant
        discussions of the linux-kernel mailing list.
-       
+
      * Name: "CuTTiNG.eDGe.LiNuX"
        URL: http://edge.kernelnotes.org
        Keywords: changelist.
@@ -709,7 +694,7 @@
        release. What's new, what's better, what's changed. Myrdraal reads
        the patches and describes them. Pointers to the patches are there,
        too.
-       
+
      * Name: "New linux-kernel Mailing List FAQ"
        URL: http://www.tux.org/lkml/
        Keywords: linux-kernel mailing list FAQ.
@@ -719,7 +704,7 @@
        it. Read it to see how to join the mailing list. Dozens of
        interesting questions regarding the list, Linux, developers (who
        is ...?), terms (what is...?) are answered here too. Just read it.
-       
+
      * Name: "Linux Virtual File System"
        Author: Peter J. Braam.
        URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs/
@@ -727,10 +712,10 @@
        Description: Set of slides, presumably from a presentation on the
        Linux VFS layer. Covers version 2.1.x, with dentries and the
        dcache.
-       
+
      * Name: "Gary's Encyclopedia - The Linux Kernel"
        Author: Gary (I suppose...).
-       URL: http://members.aa.net/~swear/pedia/kernel.html
+       URL: http://www.lisoleg.net/cgi-bin/lisoleg.pl?view=kernel.htm
        Keywords: links, not found here?.
        Description: Gary's Encyclopedia exists to allow the rapid finding
        of documentation and other information of interest to GNU/Linux
@@ -738,7 +723,7 @@
        categories. This link is for kernel-specific links, documents,
        sites... Look there if you could not find here what you were
        looking for.
-       
+
      * Name: "The home page of Linux-MM"
        Author: The Linux-MM team.
        URL: http://linux-mm.org/
@@ -747,7 +732,7 @@
        Description: Site devoted to Linux Memory Management development.
        Memory related patches, HOWTOs, links, mm developers... Don't miss
        it if you are interested in memory management development!
-       
+
      * Name: "Kernel Newbies IRC Channel"
        URL: http://www.kernelnewbies.org
        Keywords: IRC, newbies, channel, asking doubts.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 25d2985..03eb5ed 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -48,6 +48,7 @@
 	ISAPNP	ISA PnP code is enabled.
 	ISDN	Appropriate ISDN support is enabled.
 	JOY	Appropriate joystick support is enabled.
+	LIBATA  Libata driver is enabled
 	LP	Printer support is enabled.
 	LOOP	Loopback device support is enabled.
 	M68k	M68k architecture is enabled.
@@ -104,6 +105,9 @@
 Do not modify the syntax of boot loader parameters without extreme
 need or coordination with <Documentation/i386/boot.txt>.
 
+There are also arch-specific kernel-parameters not documented here.
+See for example <Documentation/x86_64/boot-options.txt>.
+
 Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
 a trailing = on the name of any parameter states that that parameter will
 be entered as an environment variable, whereas its absence indicates that
@@ -361,6 +365,11 @@
 			clocksource is not available, it defaults to PIT.
 			Format: { pit | tsc | cyclone | pmtmr }
 
+	code_bytes	[IA32] How many bytes of object code to print in an
+			oops report.
+			Range: 0 - 8192
+			Default: 64
+
 	disable_8254_timer
 	enable_8254_timer
 			[IA32/X86_64] Disable/Enable interrupt 0 timer routing
@@ -601,6 +610,10 @@
 			highmem otherwise. This also works to reduce highmem
 			size on bigger boxes.
 
+	highres=	[KNL] Enable/disable high resolution timer mode.
+			Valid parameters: "on", "off"
+			Default: "on"
+
 	hisax=		[HW,ISDN]
 			See Documentation/isdn/README.HiSax.
 
@@ -851,7 +864,14 @@
 			Format: <1-256>
 
 	maxcpus=	[SMP] Maximum number of processors that	an SMP kernel
-			should make use of
+			should make use of.
+			Using "nosmp" or "maxcpus=0" will disable SMP
+			entirely (the MPS table probe still happens, though).
+			A command-line option of "maxcpus=<NUM>", where <NUM>
+			is an integer greater than 0, limits the maximum number
+			of CPUs activated in SMP mode to <NUM>.
+			Using "maxcpus=1" on an SMP kernel is the trivial
+			case of an SMP kernel with only one CPU.
 
 	max_addr=[KMG]	[KNL,BOOT,ia64] All physical memory greater than or
 			equal to this physical address is ignored.
@@ -1026,6 +1046,10 @@
 			emulation library even if a 387 maths coprocessor
 			is present.
 
+	noacpi		[LIBATA] Disables use of ACPI in libata suspend/resume
+			when set.
+			Format: <int>
+
 	noaliencache	[MM, NUMA] Disables the allcoation of alien caches in
 			the slab allocator.  Saves per-node memory, but will
 			impact performance on real NUMA hardware.
@@ -1070,6 +1094,10 @@
 			in certain environments such as networked servers or
 			real-time systems.
 
+	nohz=		[KNL] Boottime enable/disable dynamic ticks
+			Valid arguments: on, off
+			Default: on
+
 	noirqbalance	[IA-32,SMP,KNL] Disable kernel irq balancing
 
 	noirqdebug	[IA-32] Disables the code which attempts to detect and
@@ -1259,6 +1287,12 @@
 				This sorting is done to get a device
 				order compatible with older (<= 2.4) kernels.
 		nobfsort	Don't sort PCI devices into breadth-first order.
+		cbiosize=nn[KMG]	The fixed amount of bus space which is
+				reserved for the CardBus bridge's IO window.
+				The default value is 256 bytes.
+		cbmemsize=nn[KMG]	The fixed amount of bus space which is
+				reserved for the CardBus bridge's memory
+				window. The default value is 64 megabytes.
 
 	pcmv=		[HW,PCMCIA] BadgePAD 4
 
@@ -1396,6 +1430,8 @@
 			in <PAGE_SIZE> units (needed only for swap files).
 			See  Documentation/power/swsusp-and-swap-files.txt
 
+	retain_initrd	[RAM] Keep initrd memory after extraction
+
 	rhash_entries=	[KNL,NET]
 			Set number of hash buckets for route cache
 
@@ -1722,6 +1758,13 @@
 			Note that genuine overcurrent events won't be
 			reported either.
 
+	usbcore.autosuspend=
+			[USB] The autosuspend time delay (in seconds) used
+			for newly-detected USB devices (default 2).  This
+			is the time required before an idle device will be
+			autosuspended.  Devices for which the delay is set
+			to 0 won't be autosuspended at all.
+
 	usbhid.mousepoll=
 			[USBHID] The interval which mice are to be polled at.
 
diff --git a/Documentation/local_ops.txt b/Documentation/local_ops.txt
new file mode 100644
index 0000000..b0aca07
--- /dev/null
+++ b/Documentation/local_ops.txt
@@ -0,0 +1,163 @@
+	     Semantics and Behavior of Local Atomic Operations
+
+			    Mathieu Desnoyers
+
+
+	This document explains the purpose of the local atomic operations, how
+to implement them for any given architecture and shows how they can be used
+properly. It also stresses on the precautions that must be taken when reading
+those local variables across CPUs when the order of memory writes matters.
+
+
+
+* Purpose of local atomic operations
+
+Local atomic operations are meant to provide fast and highly reentrant per CPU
+counters. They minimize the performance cost of standard atomic operations by
+removing the LOCK prefix and memory barriers normally required to synchronize
+across CPUs.
+
+Having fast per CPU atomic counters is interesting in many cases : it does not
+require disabling interrupts to protect from interrupt handlers and it permits
+coherent counters in NMI handlers. It is especially useful for tracing purposes
+and for various performance monitoring counters.
+
+Local atomic operations only guarantee variable modification atomicity wrt the
+CPU which owns the data. Therefore, care must taken to make sure that only one
+CPU writes to the local_t data. This is done by using per cpu data and making
+sure that we modify it from within a preemption safe context. It is however
+permitted to read local_t data from any CPU : it will then appear to be written
+out of order wrt other memory writes on the owner CPU.
+
+
+* Implementation for a given architecture
+
+It can be done by slightly modifying the standard atomic operations : only
+their UP variant must be kept. It typically means removing LOCK prefix (on
+i386 and x86_64) and any SMP sychronization barrier. If the architecture does
+not have a different behavior between SMP and UP, including asm-generic/local.h
+in your archtecture's local.h is sufficient.
+
+The local_t type is defined as an opaque signed long by embedding an
+atomic_long_t inside a structure. This is made so a cast from this type to a
+long fails. The definition looks like :
+
+typedef struct { atomic_long_t a; } local_t;
+
+
+* How to use local atomic operations
+
+#include <linux/percpu.h>
+#include <asm/local.h>
+
+static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
+
+
+* Counting
+
+Counting is done on all the bits of a signed long.
+
+In preemptible context, use get_cpu_var() and put_cpu_var() around local atomic
+operations : it makes sure that preemption is disabled around write access to
+the per cpu variable. For instance :
+
+	local_inc(&get_cpu_var(counters));
+	put_cpu_var(counters);
+
+If you are already in a preemption-safe context, you can directly use
+__get_cpu_var() instead.
+
+	local_inc(&__get_cpu_var(counters));
+
+
+
+* Reading the counters
+
+Those local counters can be read from foreign CPUs to sum the count. Note that
+the data seen by local_read across CPUs must be considered to be out of order
+relatively to other memory writes happening on the CPU that owns the data.
+
+	long sum = 0;
+	for_each_online_cpu(cpu)
+		sum += local_read(&per_cpu(counters, cpu));
+
+If you want to use a remote local_read to synchronize access to a resource
+between CPUs, explicit smp_wmb() and smp_rmb() memory barriers must be used
+respectively on the writer and the reader CPUs. It would be the case if you use
+the local_t variable as a counter of bytes written in a buffer : there should
+be a smp_wmb() between the buffer write and the counter increment and also a
+smp_rmb() between the counter read and the buffer read.
+
+
+Here is a sample module which implements a basic per cpu counter using local.h.
+
+--- BEGIN ---
+/* test-local.c
+ *
+ * Sample module for local.h usage.
+ */
+
+
+#include <asm/local.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+
+static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
+
+static struct timer_list test_timer;
+
+/* IPI called on each CPU. */
+static void test_each(void *info)
+{
+	/* Increment the counter from a non preemptible context */
+	printk("Increment on cpu %d\n", smp_processor_id());
+	local_inc(&__get_cpu_var(counters));
+
+	/* This is what incrementing the variable would look like within a
+	 * preemptible context (it disables preemption) :
+	 *
+	 * local_inc(&get_cpu_var(counters));
+	 * put_cpu_var(counters);
+	 */
+}
+
+static void do_test_timer(unsigned long data)
+{
+	int cpu;
+
+	/* Increment the counters */
+	on_each_cpu(test_each, NULL, 0, 1);
+	/* Read all the counters */
+	printk("Counters read from CPU %d\n", smp_processor_id());
+	for_each_online_cpu(cpu) {
+		printk("Read : CPU %d, count %ld\n", cpu,
+			local_read(&per_cpu(counters, cpu)));
+	}
+	del_timer(&test_timer);
+	test_timer.expires = jiffies + 1000;
+	add_timer(&test_timer);
+}
+
+static int __init test_init(void)
+{
+	/* initialize the timer that will increment the counter */
+	init_timer(&test_timer);
+	test_timer.function = do_test_timer;
+	test_timer.expires = jiffies + 1;
+	add_timer(&test_timer);
+
+	return 0;
+}
+
+static void __exit test_exit(void)
+{
+	del_timer_sync(&test_timer);
+}
+
+module_init(test_init);
+module_exit(test_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mathieu Desnoyers");
+MODULE_DESCRIPTION("Local Atomic Ops");
+--- END ---
diff --git a/Documentation/nfsroot.txt b/Documentation/nfsroot.txt
index 719f9a9..16a7cae 100644
--- a/Documentation/nfsroot.txt
+++ b/Documentation/nfsroot.txt
@@ -67,8 +67,8 @@
   <nfs-options>	Standard NFS options. All options are separated by commas.
 		The following defaults are used:
 			port		= as given by server portmap daemon
-			rsize		= 1024
-			wsize		= 1024
+			rsize		= 4096
+			wsize		= 4096
 			timeo		= 7
 			retrans		= 3
 			acregmin	= 3
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index 2503404..ea55ea8 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -234,6 +234,12 @@
   6: 'B' if a page-release function has found a bad page reference or
      some unexpected page flags.
 
+  7: 'U' if a user specifically requested that the Tainted flag be set,
+     ' ' otherwise.
+
+  7: 'U' if a user or user application specifically requested that the
+     Tainted flag be set, ' ' otherwise.
+
 The primary reason for the 'Tainted: ' string is to tell kernel
 debuggers if this is a clean kernel or if anything unusual has
 occurred.  Tainting is permanent: even if an offending module is
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index fd5028e..cdf2f3c 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -205,8 +205,8 @@
 	  exclusively called by the probe() routine, can be marked __devinit.
 	  Ditto for remove() and __devexit.
 
-	o If mydriver_probe() is marked with __devinit(), then all address
-	  references to mydriver_probe must use __devexit_p(mydriver_probe)
+	o If mydriver_remove() is marked with __devexit(), then all address
+	  references to mydriver_remove must use __devexit_p(mydriver_remove)
 	  (in the struct pci_driver declaration for example).
 	  __devexit_p() will generate the function name _or_ NULL if the
 	  function will be discarded.  For an example, see drivers/net/tg3.c.
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 3399427..b41397d 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -497,7 +497,7 @@
       |   |- device_type = "cpu"
       |   |- reg = <0>
       |   |- clock-frequency = <5f5e1000>
-      |   |- linux,boot-cpu
+      |   |- 64-bit
       |   |- linux,phandle = <2>
       |
       o memory@0
@@ -509,7 +509,6 @@
       o chosen
         |- name = "chosen"
         |- bootargs = "root=/dev/sda2"
-        |- linux,platform = <00000600>
         |- linux,phandle = <4>
 
 This tree is almost a minimal tree. It pretty much contains the
@@ -519,7 +518,7 @@
 through /chosen, like in this example, the platform type (mandatory)
 and the kernel command line arguments (optional).
 
-The /cpus/PowerPC,970@0/linux,boot-cpu property is an example of a
+The /cpus/PowerPC,970@0/64-bit property is an example of a
 property without a value. All other properties have a value. The
 significance of the #address-cells and #size-cells properties will be
 explained in chapter IV which defines precisely the required nodes and
@@ -733,8 +732,7 @@
       that typically get driven by the same platform code in the
       kernel, you would use a different "model" property but put a
       value in "compatible". The kernel doesn't directly use that
-      value (see /chosen/linux,platform for how the kernel chooses a
-      platform type) but it is generally useful.
+      value but it is generally useful.
 
   The root node is also generally where you add additional properties
   specific to your board like the serial number if any, that sort of
@@ -778,7 +776,6 @@
       bytes
     - d-cache-size : one cell, size of L1 data cache in bytes
     - i-cache-size : one cell, size of L1 instruction cache in bytes
-    - linux, boot-cpu : Should be defined if this cpu is the boot cpu.
 
   Recommended properties:
 
@@ -843,11 +840,6 @@
   the prom_init() trampoline when booting with an OF client interface,
   but that you have to provide yourself when using the flattened format.
 
-  Required properties:
-
-    - linux,platform : This is your platform number as assigned by the
-      architecture maintainers
-
   Recommended properties:
 
     - bootargs : This zero-terminated string is passed as the kernel
@@ -1334,6 +1326,9 @@
       fsl-usb2-mph compatible controllers.  Either this property or
       "port0" (or both) must be defined for "fsl-usb2-mph" compatible 
       controllers.
+    - dr_mode : indicates the working mode for "fsl-usb2-dr" compatible
+      controllers.  Can be "host", "peripheral", or "otg".  Default to
+      "host" if not defined for backward compatibility.
 
    Recommended properties :
     - interrupts : <a b> where a is the interrupt number and b is a
@@ -1367,6 +1362,7 @@
 		#size-cells = <0>;
 		interrupt-parent = <700>;
 		interrupts = <26 1>;
+		dr_mode = "otg";
 		phy = "ulpi";
 	};
 
diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
index 69f016f..e59fcbb 100644
--- a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
+++ b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
@@ -1,7 +1,7 @@
-MPC52xx Device Tree Bindings
+MPC5200 Device Tree Bindings
 ----------------------------
 
-(c) 2006 Secret Lab Technologies Ltd
+(c) 2006-2007 Secret Lab Technologies Ltd
 Grant Likely <grant.likely at secretlab.ca>
 
 ********** DRAFT ***********
@@ -20,11 +20,11 @@
 by Open Firmare (IEEE 1275) compatible firmware using an OF compatible
 client interface API.
 
-This document specifies the requirements on the device-tree for mpc52xx
+This document specifies the requirements on the device-tree for mpc5200
 based boards.  These requirements are above and beyond the details
 specified in either the OpenFirmware spec or booting-without-of.txt
 
-All new mpc52xx-based boards are expected to match this document.  In
+All new mpc5200-based boards are expected to match this document.  In
 cases where this document is not sufficient to support a new board port,
 this document should be updated as part of adding the new board support.
 
@@ -32,26 +32,26 @@
 ===============
 The core of this document is naming convention.  The whole point of
 defining this convention is to reduce or eliminate the number of
-special cases required to support a 52xx board.  If all 52xx boards
-follow the same convention, then generic 52xx support code will work
+special cases required to support a 5200 board.  If all 5200 boards
+follow the same convention, then generic 5200 support code will work
 rather than coding special cases for each new board.
 
 This section tries to capture the thought process behind why the naming
 convention is what it is.
 
-1. Node names
--------------
+1.  names
+---------
 There is strong convention/requirements already established for children
 of the root node.  'cpus' describes the processor cores, 'memory'
 describes memory, and 'chosen' provides boot configuration.  Other nodes
 are added to describe devices attached to the processor local bus.
-Following convention already established with other system-on-chip
-processors, MPC52xx boards must have an 'soc5200' node as a child of the
-root node.
 
-The soc5200 node holds child nodes for all on chip devices.  Child nodes
-are typically named after the configured function.  ie. the FEC node is
-named 'ethernet', and a PSC in uart mode is named 'serial'.
+Following convention already established with other system-on-chip
+processors, 5200 device trees should use the name 'soc5200' for the
+parent node of on chip devices, and the root node should be its parent.
+
+Child nodes are typically named after the configured function.  ie.
+the FEC node is named 'ethernet', and a PSC in uart mode is named 'serial'.
 
 2. device_type property
 -----------------------
@@ -66,28 +66,47 @@
 Since device_type isn't enough to match devices to drivers, there also
 needs to be a naming convention for the compatible property.  Compatible
 is an list of device descriptions sorted from specific to generic.  For
-the mpc52xx, the required format for each compatible value is
-<chip>-<device>[-<mode>].  At the minimum, the list shall contain two
-items; the first specifying the exact chip, and the second specifying
-mpc52xx for the chip.
+the mpc5200, the required format for each compatible value is
+<chip>-<device>[-<mode>].  The OS should be able to match a device driver
+to the device based solely on the compatible value.  If two drivers
+match on the compatible list; the 'most compatible' driver should be
+selected.
 
-ie. ethernet on mpc5200b: compatible = "mpc5200b-ethernet\0mpc52xx-ethernet"
+The split between the MPC5200 and the MPC5200B leaves a bit of a
+connundrum.  How should the compatible property be set up to provide
+maximum compatability information; but still acurately describe the
+chip?  For the MPC5200; the answer is easy.  Most of the SoC devices
+originally appeared on the MPC5200.  Since they didn't exist anywhere
+else; the 5200 compatible properties will contain only one item;
+"mpc5200-<device>".
 
-The idea here is that most drivers will match to the most generic field
-in the compatible list (mpc52xx-*), but can also test the more specific
-field for enabling bug fixes or extra features.
+The 5200B is almost the same as the 5200, but not quite.  It fixes
+silicon bugs and it adds a small number of enhancements.  Most of the
+devices either provide exactly the same interface as on the 5200.  A few
+devices have extra functions but still have a backwards compatible mode.
+To express this infomation as completely as possible, 5200B device trees
+should have two items in the compatible list;
+"mpc5200b-<device>\0mpc5200-<device>".  It is *strongly* recommended
+that 5200B device trees follow this convention (instead of only listing
+the base mpc5200 item).
+
+If another chip appear on the market with one of the mpc5200 SoC
+devices, then the compatible list should include mpc5200-<device>.
+
+ie. ethernet on mpc5200: compatible = "mpc5200-ethernet"
+    ethernet on mpc5200b: compatible = "mpc5200b-ethernet\0mpc5200-ethernet"
 
 Modal devices, like PSCs, also append the configured function to the
 end of the compatible field.  ie. A PSC in i2s mode would specify
-"mpc52xx-psc-i2s", not "mpc52xx-i2s".  This convention is chosen to
+"mpc5200-psc-i2s", not "mpc5200-i2s".  This convention is chosen to
 avoid naming conflicts with non-psc devices providing the same
-function.  For example, "mpc52xx-spi" and "mpc52xx-psc-spi" describe
+function.  For example, "mpc5200-spi" and "mpc5200-psc-spi" describe
 the mpc5200 simple spi device and a PSC spi mode respectively.
 
 If the soc device is more generic and present on other SOCs, the
 compatible property can specify the more generic device type also.
 
-ie. mscan: compatible = "mpc5200-mscan\0mpc52xx-mscan\0fsl,mscan";
+ie. mscan: compatible = "mpc5200-mscan\0fsl,mscan";
 
 At the time of writing, exact chip may be either 'mpc5200' or
 'mpc5200b'.
@@ -96,7 +115,7 @@
 
 III - Structure
 ===============
-The device tree for an mpc52xx board follows the structure defined in
+The device tree for an mpc5200 board follows the structure defined in
 booting-without-of.txt with the following additional notes:
 
 0) the root node
@@ -115,7 +134,7 @@
 
 3) The soc5200 node
 -------------------
-This node describes the on chip SOC peripherals.  Every mpc52xx based
+This node describes the on chip SOC peripherals.  Every mpc5200 based
 board will have this node, and as such there is a common naming
 convention for SOC devices.
 
@@ -125,71 +144,111 @@
 device_type		string		must be "soc"
 ranges			int		should be <0 baseaddr baseaddr+10000>
 reg			int		must be <baseaddr 10000>
+compatible		string		mpc5200: "mpc5200-soc"
+					mpc5200b: "mpc5200b-soc\0mpc5200-soc"
+system-frequency	int		Fsystem frequency; source of all
+					other clocks.
+bus-frequency		int		IPB bus frequency in HZ.  Clock rate
+					used by most of the soc devices.
+#interrupt-cells	int		must be <3>.
 
 Recommended properties:
 name			type		description
 ----			----		-----------
-compatible		string		should be "<chip>-soc\0mpc52xx-soc"
-					ie. "mpc5200b-soc\0mpc52xx-soc"
-#interrupt-cells	int		must be <3>.  If it is not defined
-					here then it must be defined in every
-					soc device node.
-bus-frequency		int		IPB bus frequency in HZ.  Clock rate
-					used by most of the soc devices.
-					Defining it here avoids needing it
-					added to every device node.
+model			string		Exact model of the chip;
+					ie: model="fsl,mpc5200"
+revision		string		Silicon revision of chip
+					ie: revision="M08A"
+
+The 'model' and 'revision' properties are *strongly* recommended.  Having
+them presence acts as a bit of a safety net for working around as yet
+undiscovered bugs on one version of silicon.  For example, device drivers
+can use the model and revision properties to decide if a bug fix should
+be turned on.
 
 4) soc5200 child nodes
 ----------------------
 Any on chip SOC devices available to Linux must appear as soc5200 child nodes.
 
-Note: in the tables below, '*' matches all <chip> values.  ie.
-*-pic would translate to "mpc5200-pic\0mpc52xx-pic"
+Note: The tables below show the value for the mpc5200.  A mpc5200b device
+tree should use the "mpc5200b-<device>\0mpc5200-<device> form.
 
 Required soc5200 child nodes:
 name		device_type		compatible	Description
 ----		-----------		----------	-----------
-cdm@<addr>	cdm			*-cmd		Clock Distribution
-pic@<addr>	interrupt-controller	*-pic		need an interrupt
+cdm@<addr>	cdm			mpc5200-cmd	Clock Distribution
+pic@<addr>	interrupt-controller	mpc5200-pic	need an interrupt
 							controller to boot
-bestcomm@<addr>	dma-controller		*-bestcomm	52xx pic also requires
-							the bestcomm device
+bestcomm@<addr>	dma-controller		mpc5200-bestcomm 5200 pic also requires
+							 the bestcomm device
 
 Recommended soc5200 child nodes; populate as needed for your board
-name		device_type	compatible	Description
-----		-----------	----------	-----------
-gpt@<addr>	gpt		*-gpt		General purpose timers
-rtc@<addr>	rtc		*-rtc		Real time clock
-mscan@<addr>	mscan		*-mscan		CAN bus controller
-pci@<addr>	pci		*-pci		PCI bridge
-serial@<addr>	serial		*-psc-uart	PSC in serial mode
-i2s@<addr>	sound		*-psc-i2s	PSC in i2s mode
-ac97@<addr>	sound		*-psc-ac97	PSC in ac97 mode
-spi@<addr>	spi		*-psc-spi	PSC in spi mode
-irda@<addr>	irda		*-psc-irda	PSC in IrDA mode
-spi@<addr>	spi		*-spi		MPC52xx spi device
-ethernet@<addr>	network		*-fec		MPC52xx ethernet device
-ata@<addr>	ata		*-ata		IDE ATA interface
-i2c@<addr>	i2c		*-i2c		I2C controller
-usb@<addr>	usb-ohci-be	*-ohci,ohci-be	USB controller
-xlb@<addr>	xlb		*-xlb		XLB arbritrator
+name		device_type	compatible	  Description
+----		-----------	----------	  -----------
+gpt@<addr>	gpt		mpc5200-gpt	  General purpose timers
+rtc@<addr>	rtc		mpc5200-rtc	  Real time clock
+mscan@<addr>	mscan		mpc5200-mscan	  CAN bus controller
+pci@<addr>	pci		mpc5200-pci	  PCI bridge
+serial@<addr>	serial		mpc5200-psc-uart  PSC in serial mode
+i2s@<addr>	sound		mpc5200-psc-i2s	  PSC in i2s mode
+ac97@<addr>	sound		mpc5200-psc-ac97  PSC in ac97 mode
+spi@<addr>	spi		mpc5200-psc-spi	  PSC in spi mode
+irda@<addr>	irda		mpc5200-psc-irda  PSC in IrDA mode
+spi@<addr>	spi		mpc5200-spi	  MPC5200 spi device
+ethernet@<addr>	network		mpc5200-fec	  MPC5200 ethernet device
+ata@<addr>	ata		mpc5200-ata	  IDE ATA interface
+i2c@<addr>	i2c		mpc5200-i2c	  I2C controller
+usb@<addr>	usb-ohci-be	mpc5200-ohci,ohci-be	USB controller
+xlb@<addr>	xlb		mpc5200-xlb	  XLB arbritrator
+
+Important child node properties
+name		type		description
+----		----		-----------
+cell-index	int		When multiple devices are present, is the
+				index of the device in the hardware (ie. There
+				are 6 PSC on the 5200 numbered PSC1 to PSC6)
+				    PSC1 has 'cell-index = <0>'
+				    PSC4 has 'cell-index = <3>'
+
+5) General Purpose Timer nodes (child of soc5200 node)
+On the mpc5200 and 5200b, GPT0 has a watchdog timer function.  If the board
+design supports the internal wdt, then the device node for GPT0 should
+include the empty property 'has-wdt'.
+
+6) PSC nodes (child of soc5200 node)
+PSC nodes can define the optional 'port-number' property to force assignment
+order of serial ports.  For example, PSC5 might be physically connected to
+the port labeled 'COM1' and PSC1 wired to 'COM1'.  In this case, PSC5 would
+have a "port-number = <0>" property, and PSC1 would have "port-number = <1>".
+
+PSC in i2s mode:  The mpc5200 and mpc5200b PSCs are not compatible when in
+i2s mode.  An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the
+compatible field.
 
 IV - Extra Notes
 ================
 
 1. Interrupt mapping
 --------------------
-The mpc52xx pic driver splits hardware IRQ numbers into two levels.  The
+The mpc5200 pic driver splits hardware IRQ numbers into two levels.  The
 split reflects the layout of the PIC hardware itself, which groups
 interrupts into one of three groups; CRIT, MAIN or PERP.  Also, the
 Bestcomm dma engine has it's own set of interrupt sources which are
 cascaded off of peripheral interrupt 0, which the driver interprets as a
 fourth group, SDMA.
 
-The interrupts property for device nodes using the mpc52xx pic consists
+The interrupts property for device nodes using the mpc5200 pic consists
 of three cells; <L1 L2 level>
 
     L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3]
     L2 := interrupt number; directly mapped from the value in the
           "ICTL PerStat, MainStat, CritStat Encoded Register"
     level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3]
+
+2. Shared registers
+-------------------
+Some SoC devices share registers between them.  ie. the i2c devices use
+a single clock control register, and almost all device are affected by
+the port_config register.  Devices which need to manipulate shared regs
+should look to the parent SoC node.  The soc node is responsible
+for arbitrating all shared register access.
diff --git a/Documentation/rbtree.txt b/Documentation/rbtree.txt
new file mode 100644
index 0000000..7224459b
--- /dev/null
+++ b/Documentation/rbtree.txt
@@ -0,0 +1,192 @@
+Red-black Trees (rbtree) in Linux
+January 18, 2007
+Rob Landley <rob@landley.net>
+=============================
+
+What are red-black trees, and what are they for?
+------------------------------------------------
+
+Red-black trees are a type of self-balancing binary search tree, used for
+storing sortable key/value data pairs.  This differs from radix trees (which
+are used to efficiently store sparse arrays and thus use long integer indexes
+to insert/access/delete nodes) and hash tables (which are not kept sorted to
+be easily traversed in order, and must be tuned for a specific size and
+hash function where rbtrees scale gracefully storing arbitrary keys).
+
+Red-black trees are similar to AVL trees, but provide faster real-time bounded
+worst case performance for insertion and deletion (at most two rotations and
+three rotations, respectively, to balance the tree), with slightly slower
+(but still O(log n)) lookup time.
+
+To quote Linux Weekly News:
+
+    There are a number of red-black trees in use in the kernel.
+    The anticipatory, deadline, and CFQ I/O schedulers all employ
+    rbtrees to track requests; the packet CD/DVD driver does the same.
+    The high-resolution timer code uses an rbtree to organize outstanding
+    timer requests.  The ext3 filesystem tracks directory entries in a
+    red-black tree.  Virtual memory areas (VMAs) are tracked with red-black
+    trees, as are epoll file descriptors, cryptographic keys, and network
+    packets in the "hierarchical token bucket" scheduler.
+
+This document covers use of the Linux rbtree implementation.  For more
+information on the nature and implementation of Red Black Trees,  see:
+
+  Linux Weekly News article on red-black trees
+    http://lwn.net/Articles/184495/
+
+  Wikipedia entry on red-black trees
+    http://en.wikipedia.org/wiki/Red-black_tree
+
+Linux implementation of red-black trees
+---------------------------------------
+
+Linux's rbtree implementation lives in the file "lib/rbtree.c".  To use it,
+"#include <linux/rbtree.h>".
+
+The Linux rbtree implementation is optimized for speed, and thus has one
+less layer of indirection (and better cache locality) than more traditional
+tree implementations.  Instead of using pointers to separate rb_node and data
+structures, each instance of struct rb_node is embedded in the data structure
+it organizes.  And instead of using a comparison callback function pointer,
+users are expected to write their own tree search and insert functions
+which call the provided rbtree functions.  Locking is also left up to the
+user of the rbtree code.
+
+Creating a new rbtree
+---------------------
+
+Data nodes in an rbtree tree are structures containing a struct rb_node member:
+
+  struct mytype {
+  	struct rb_node node;
+  	char *keystring;
+  };
+
+When dealing with a pointer to the embedded struct rb_node, the containing data
+structure may be accessed with the standard container_of() macro.  In addition,
+individual members may be accessed directly via rb_entry(node, type, member).
+
+At the root of each rbtree is an rb_root structure, which is initialized to be
+empty via:
+
+  struct rb_root mytree = RB_ROOT;
+
+Searching for a value in an rbtree
+----------------------------------
+
+Writing a search function for your tree is fairly straightforward: start at the
+root, compare each value, and follow the left or right branch as necessary.
+
+Example:
+
+  struct mytype *my_search(struct rb_root *root, char *string)
+  {
+  	struct rb_node *node = root->rb_node;
+
+  	while (node) {
+  		struct mytype *data = container_of(node, struct mytype, node);
+		int result;
+
+		result = strcmp(string, data->keystring);
+
+		if (result < 0)
+  			node = node->rb_left;
+		else if (result > 0)
+  			node = node->rb_right;
+		else
+  			return data;
+	}
+	return NULL;
+  }
+
+Inserting data into an rbtree
+-----------------------------
+
+Inserting data in the tree involves first searching for the place to insert the
+new node, then inserting the node and rebalancing ("recoloring") the tree.
+
+The search for insertion differs from the previous search by finding the
+location of the pointer on which to graft the new node.  The new node also
+needs a link to its parent node for rebalancing purposes.
+
+Example:
+
+  int my_insert(struct rb_root *root, struct mytype *data)
+  {
+  	struct rb_node **new = &(root->rb_node), *parent = NULL;
+
+  	/* Figure out where to put new node */
+  	while (*new) {
+  		struct mytype *this = container_of(*new, struct mytype, node);
+  		int result = strcmp(data->keystring, this->keystring);
+
+		parent = *new;
+  		if (result < 0)
+  			new = &((*new)->rb_left);
+  		else if (result > 0)
+  			new = &((*new)->rb_right);
+  		else
+  			return FALSE;
+  	}
+
+  	/* Add new node and rebalance tree. */
+  	rb_link_node(data->node, parent, new);
+  	rb_insert_color(data->node, root);
+
+	return TRUE;
+  }
+
+Removing or replacing existing data in an rbtree
+------------------------------------------------
+
+To remove an existing node from a tree, call:
+
+  void rb_erase(struct rb_node *victim, struct rb_root *tree);
+
+Example:
+
+  struct mytype *data = mysearch(mytree, "walrus");
+
+  if (data) {
+  	rb_erase(data->node, mytree);
+  	myfree(data);
+  }
+
+To replace an existing node in a tree with a new one with the same key, call:
+
+  void rb_replace_node(struct rb_node *old, struct rb_node *new,
+  			struct rb_root *tree);
+
+Replacing a node this way does not re-sort the tree: If the new node doesn't
+have the same key as the old node, the rbtree will probably become corrupted.
+
+Iterating through the elements stored in an rbtree (in sort order)
+------------------------------------------------------------------
+
+Four functions are provided for iterating through an rbtree's contents in
+sorted order.  These work on arbitrary trees, and should not need to be
+modified or wrapped (except for locking purposes):
+
+  struct rb_node *rb_first(struct rb_root *tree);
+  struct rb_node *rb_last(struct rb_root *tree);
+  struct rb_node *rb_next(struct rb_node *node);
+  struct rb_node *rb_prev(struct rb_node *node);
+
+To start iterating, call rb_first() or rb_last() with a pointer to the root
+of the tree, which will return a pointer to the node structure contained in
+the first or last element in the tree.  To continue, fetch the next or previous
+node by calling rb_next() or rb_prev() on the current node.  This will return
+NULL when there are no more nodes left.
+
+The iterator functions return a pointer to the embedded struct rb_node, from
+which the containing data structure may be accessed with the container_of()
+macro, and individual members may be accessed directly via
+rb_entry(node, type, member).
+
+Example:
+
+  struct rb_node *node;
+  for (node = rb_first(&mytree); node; node = rb_next(node))
+  	printk("key=%s\n", rb_entry(node, int, keystring));
+
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 7cf1ec5..1ef6bb8 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -149,7 +149,7 @@
 	is connected to an IRQ line, it can often issue an alarm IRQ up to
 	24 hours in the future.
 
-    *	RTC_WKALM_SET, RTC_WKALM_READ ... RTCs that can issue alarms beyond
+    *	RTC_WKALM_SET, RTC_WKALM_RD ... RTCs that can issue alarms beyond
 	the next 24 hours use a slightly more powerful API, which supports
 	setting the longer alarm time and enabling its IRQ using a single
 	request (using the same model as EFI firmware).
@@ -167,6 +167,28 @@
 operational state.  For example, a system could enter a deep power saving
 state until it's time to execute some scheduled tasks.
 
+Note that many of these ioctls need not actually be implemented by your
+driver.  The common rtc-dev interface handles many of these nicely if your
+driver returns ENOIOCTLCMD.  Some common examples:
+
+    *	RTC_RD_TIME, RTC_SET_TIME: the read_time/set_time functions will be
+	called with appropriate values.
+
+    *	RTC_ALM_SET, RTC_ALM_READ, RTC_WKALM_SET, RTC_WKALM_RD: the
+	set_alarm/read_alarm functions will be called.  To differentiate
+	between the ALM and WKALM, check the larger fields of the rtc_wkalrm
+	struct (like tm_year).  These will be set to -1 when using ALM and
+	will be set to proper values when using WKALM.
+
+    *	RTC_IRQP_SET, RTC_IRQP_READ: the irq_set_freq function will be called
+	to set the frequency while the framework will handle the read for you
+	since the frequency is stored in the irq_freq member of the rtc_device
+	structure.  Also make sure you set the max_user_freq member in your
+	initialization routines so the framework can sanity check the user
+	input for you.
+
+If all else fails, check out the rtc-test.c driver!
+
 
 -------------------- 8< ---------------- 8< -----------------------------
 
@@ -237,7 +259,7 @@
 				"\n...Update IRQs not supported.\n");
 			goto test_READ;
 		}
-		perror("ioctl");
+		perror("RTC_UIE_ON ioctl");
 		exit(errno);
 	}
 
@@ -284,7 +306,7 @@
 	/* Turn off update interrupts */
 	retval = ioctl(fd, RTC_UIE_OFF, 0);
 	if (retval == -1) {
-		perror("ioctl");
+		perror("RTC_UIE_OFF ioctl");
 		exit(errno);
 	}
 
@@ -292,7 +314,7 @@
 	/* Read the RTC time/date */
 	retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
 	if (retval == -1) {
-		perror("ioctl");
+		perror("RTC_RD_TIME ioctl");
 		exit(errno);
 	}
 
@@ -320,14 +342,14 @@
 				"\n...Alarm IRQs not supported.\n");
 			goto test_PIE;
 		}
-		perror("ioctl");
+		perror("RTC_ALM_SET ioctl");
 		exit(errno);
 	}
 
 	/* Read the current alarm settings */
 	retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
 	if (retval == -1) {
-		perror("ioctl");
+		perror("RTC_ALM_READ ioctl");
 		exit(errno);
 	}
 
@@ -337,7 +359,7 @@
 	/* Enable alarm interrupts */
 	retval = ioctl(fd, RTC_AIE_ON, 0);
 	if (retval == -1) {
-		perror("ioctl");
+		perror("RTC_AIE_ON ioctl");
 		exit(errno);
 	}
 
@@ -355,7 +377,7 @@
 	/* Disable alarm interrupts */
 	retval = ioctl(fd, RTC_AIE_OFF, 0);
 	if (retval == -1) {
-		perror("ioctl");
+		perror("RTC_AIE_OFF ioctl");
 		exit(errno);
 	}
 
@@ -368,7 +390,7 @@
 			fprintf(stderr, "\nNo periodic IRQ support\n");
 			return 0;
 		}
-		perror("ioctl");
+		perror("RTC_IRQP_READ ioctl");
 		exit(errno);
 	}
 	fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp);
@@ -387,7 +409,7 @@
 					"\n...Periodic IRQ rate is fixed\n");
 				goto done;
 			}
-		        perror("ioctl");
+		        perror("RTC_IRQP_SET ioctl");
 		        exit(errno);
 		}
 
@@ -397,7 +419,7 @@
 		/* Enable periodic interrupts */
 		retval = ioctl(fd, RTC_PIE_ON, 0);
 		if (retval == -1) {
-		        perror("ioctl");
+		        perror("RTC_PIE_ON ioctl");
 		        exit(errno);
 		}
 
@@ -416,7 +438,7 @@
 		/* Disable periodic interrupts */
 		retval = ioctl(fd, RTC_PIE_OFF, 0);
 		if (retval == -1) {
-		        perror("ioctl");
+		        perror("RTC_PIE_OFF ioctl");
 		        exit(errno);
 		}
 	}
diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid
index a056bbe..37796fe 100644
--- a/Documentation/scsi/ChangeLog.megaraid
+++ b/Documentation/scsi/ChangeLog.megaraid
@@ -1,3 +1,19 @@
+Release Date	: Thu Nov 16 15:32:35 EST 2006 -
+				Sumant Patro <sumant.patro@lsi.com>
+Current Version : 2.20.5.1 (scsi module), 2.20.2.6 (cmm module)
+Older Version	: 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
+
+1.	Changes in Initialization to fix kdump failure.
+	Send SYNC command on loading.
+	This command clears the pending commands in the adapter
+	and re-initialize its internal RAID structure.
+	Without this change, megaraid driver either panics or fails to
+	initialize the adapter during kdump's second kernel boot
+	if there are pending commands or interrupts from other devices
+	sharing the same IRQ.
+2. 	Authors email-id domain name changed from lsil.com to lsi.com.
+	Also modified the MODULE_AUTHOR to megaraidlinux@lsi.com
+
 Release Date	: Fri May 19 09:31:45 EST 2006 - Seokmann Ju <sju@lsil.com>
 Current Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
 Older Version	: 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
diff --git a/Documentation/sh/new-machine.txt b/Documentation/sh/new-machine.txt
index 73988e0..5482bf5 100644
--- a/Documentation/sh/new-machine.txt
+++ b/Documentation/sh/new-machine.txt
@@ -17,7 +17,7 @@
 in arch/sh/kernel/ directly, with board-specific headers ending up in
 include/asm-sh/. For the new kernel, things are broken out by board type,
 companion chip type, and CPU type. Looking at a tree view of this directory
-heirarchy looks like the following:
+hierarchy looks like the following:
 
 Board-specific code:
 
@@ -108,7 +108,7 @@
 member itself.
 
 There are a few things that each board is required to have, both in the
-arch/sh/boards and the include/asm-sh/ heirarchy. In order to better
+arch/sh/boards and the include/asm-sh/ hierarchy. In order to better
 explain this, we use some examples for adding an imaginary board. For
 setup code, we're required at the very least to provide definitions for
 get_system_type() and platform_setup(). For our imaginary board, this
diff --git a/Documentation/sony-laptop.txt b/Documentation/sony-laptop.txt
new file mode 100644
index 0000000..dfd26df
--- /dev/null
+++ b/Documentation/sony-laptop.txt
@@ -0,0 +1,106 @@
+Sony Notebook Control Driver (SNC) Readme
+-----------------------------------------
+	Copyright (C) 2004- 2005 Stelian Pop <stelian@popies.net>
+	Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
+
+This mini-driver drives the SNC device present in the ACPI BIOS of
+the Sony Vaio laptops.
+
+It gives access to some extra laptop functionalities. In its current
+form, this driver let the user set or query the screen brightness
+through the backlight subsystem and remove/apply power to some devices.
+
+Backlight control:
+------------------
+If your laptop model supports it, you will find sysfs files in the
+/sys/class/backlight/sony/
+directory. You will be able to query and set the current screen
+brightness:
+	brightness		get/set screen brightness (an iteger
+				between 0 and 7)
+	actual_brightness	reading from this file will query the HW
+				to get real brightness value
+	max_brightness		the maximum brightness value
+
+
+Platform specific:
+------------------
+Loading the sony-laptop module will create a
+/sys/devices/platform/sony-laptop/
+directory populated with some files.
+
+You then read/write integer values from/to those files by using
+standard UNIX tools.
+
+The files are:
+	brightness_default	screen brightness which will be set
+				when the laptop will be rebooted
+	cdpower			power on/off the internal CD drive
+	audiopower		power on/off the internal sound card
+	lanpower		power on/off the internal ethernet card
+				(only in debug mode)
+
+Note that some files may be missing if they are not supported
+by your particular laptop model.
+
+Example usage:
+	# echo "1" > /sys/devices/platform/sony-laptop/brightness_default
+sets the lowest screen brightness for the next and later reboots,
+	# echo "8" > /sys/devices/platform/sony-laptop/brightness_default
+sets the highest screen brightness for the next and later reboots,
+	# cat /sys/devices/platform/sony-laptop/brightness_default
+retrieves the value.
+
+	# echo "0" > /sys/devices/platform/sony-laptop/audiopower
+powers off the sound card,
+	# echo "1" > /sys/devices/platform/sony-laptop/audiopower
+powers on the sound card.
+
+Development:
+------------
+
+If you want to help with the development of this driver (and
+you are not afraid of any side effects doing strange things with
+your ACPI BIOS could have on your laptop), load the driver and
+pass the option 'debug=1'.
+
+REPEAT: DON'T DO THIS IF YOU DON'T LIKE RISKY BUSINESS.
+
+In your kernel logs you will find the list of all ACPI methods
+the SNC device has on your laptop. You can see the GCDP/GCDP methods
+used to pwer on/off the CD drive, but there are others.
+
+I HAVE NO IDEA WHAT THOSE METHODS DO.
+
+The sony-laptop driver creates, for some of those methods (the most
+current ones found on several Vaio models), an entry under
+/sys/devices/platform/sony-laptop, just like the 'cdpower' one.
+You can create other entries corresponding to your own laptop methods by
+further editing the source (see the 'sony_acpi_values' table, and add a new
+entry to this table with your get/set method names using the
+HANDLE_NAMES macro).
+
+Your mission, should you accept it, is to try finding out what
+those entries are for, by reading/writing random values from/to those
+files and find out what is the impact on your laptop.
+
+Should you find anything interesting, please report it back to me,
+I will not disavow all knowledge of your actions :)
+
+Bugs/Limitations:
+-----------------
+
+* This driver is not based on official documentation from Sony
+  (because there is none), so there is no guarantee this driver
+  will work at all, or do the right thing. Although this hasn't
+  happened to me, this driver could do very bad things to your
+  laptop, including permanent damage.
+
+* The sony-laptop and sonypi drivers do not interact at all. In the
+  future, sonypi could use sony-laptop to do (part of) its business.
+
+* spicctrl, which is the userspace tool used to communicate with the
+  sonypi driver (through /dev/sonypi) does not try to use the
+  sony-laptop driver. In the future, spicctrl could try sonypi first,
+  and if it isn't present, try sony-laptop instead.
+
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 9fef210..c30ff1b 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -242,6 +242,12 @@
     ac97_clock		- AC'97 clock (default = 48000)
     ac97_quirk		- AC'97 workaround for strange hardware
 			  See "AC97 Quirk Option" section below.
+    ac97_codec		- Workaround to specify which AC'97 codec 
+			  instead of probing.  If this works for you
+			  file a bug with your `lspci -vn` output.
+			  -2  -- Force probing.
+			  -1  -- Default behavior.
+			  0-2 -- Use the specified codec.
     spdif_aclink	- S/PDIF transfer over AC-link (default = 1)
 
     This module supports one card and autoprobe.
@@ -779,6 +785,7 @@
 	  asus-dig	ASUS with SPDIF out
 	  asus-dig2	ASUS with SPDIF out (using GPIO2)
 	  uniwill	3-jack
+	  fujitsu	Fujitsu Laptops (Pi1536)
 	  F1734		2-jack
 	  lg		LG laptop (m1 express dual)
 	  lg-lw		LG LW20/LW25 laptop
@@ -800,14 +807,18 @@
 	ALC262
 	  fujitsu	Fujitsu Laptop
 	  hp-bpc	HP xw4400/6400/8400/9400 laptops
+	  hp-bpc-d7000	HP BPC D7000
 	  benq		Benq ED8
+	  hippo		Hippo (ATI) with jack detection, Sony UX-90s
+	  hippo_1	Hippo (Benq) with jack detection
 	  basic		fixed pin assignment w/o SPDIF
 	  auto		auto-config reading BIOS (default)
 
 	ALC882/885
 	  3stack-dig	3-jack with SPDIF I/O
-	  6stck-dig	6-jack digital with SPDIF I/O
+	  6stack-dig	6-jack digital with SPDIF I/O
 	  arima		Arima W820Di1
+	  macpro	MacPro support
 	  auto		auto-config reading BIOS (default)
 
 	ALC883/888
@@ -817,6 +828,10 @@
 	  3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
 	  6stack-dig-demo  6-jack digital for Intel demo board
 	  acer		Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
+	  medion	Medion Laptops
+	  targa-dig	Targa/MSI
+	  targa-2ch-dig	Targs/MSI with 2-channel
+	  laptop-eapd   3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
 	  auto		auto-config reading BIOS (default)
 
 	ALC861/660
@@ -825,6 +840,16 @@
 	  6stack-dig	6-jack with SPDIF I/O
 	  3stack-660	3-jack (for ALC660)
 	  uniwill-m31	Uniwill M31 laptop
+	  toshiba	Toshiba laptop support
+	  asus		Asus laptop support
+	  asus-laptop	ASUS F2/F3 laptops
+	  auto		auto-config reading BIOS (default)
+
+	ALC861VD/660VD
+	  3stack	3-jack
+	  3stack-dig	3-jack with SPDIF OUT
+	  6stack-dig	6-jack with SPDIF OUT
+	  3stack-660	3-jack (for ALC660VD)
 	  auto		auto-config reading BIOS (default)
 
 	CMI9880
@@ -845,6 +870,7 @@
 	  3stack	3-stack, shared surrounds
 	  laptop	2-channel only (FSC V2060, Samsung M50)
 	  laptop-eapd	2-channel with EAPD (Samsung R65, ASUS A6J)
+	  ultra		2-channel with EAPD (Samsung Ultra tablet PC)
 
 	AD1988
 	  6stack	6-jack
@@ -854,12 +880,31 @@
 	  laptop	3-jack with hp-jack automute
 	  laptop-dig	ditto with SPDIF
 	  auto		auto-config reading BIOS (default)
+	
+	Conexant 5045
+	  laptop	Laptop config 
+	  test		for testing/debugging purpose, almost all controls
+			can be adjusted.  Appearing only when compiled with
+			$CONFIG_SND_DEBUG=y
+
+	Conexant 5047
+	  laptop	Basic Laptop config 
+	  laptop-hp	Laptop config for some HP models (subdevice 30A5)
+	  laptop-eapd	Laptop config with EAPD support
+	  test		for testing/debugging purpose, almost all controls
+			can be adjusted.  Appearing only when compiled with
+			$CONFIG_SND_DEBUG=y
 
 	STAC9200/9205/9220/9221/9254
 	  ref		Reference board
 	  3stack	D945 3stack
 	  5stack	D945 5stack + SPDIF
 
+	STAC9202/9250/9251
+	  ref		Reference board, base config
+	  m2-2		Some Gateway MX series laptops
+	  m6		Some Gateway NX series laptops
+
 	STAC9227/9228/9229/927x
 	  ref		Reference board
 	  3stack	D965 3stack
@@ -974,6 +1019,7 @@
     Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
 			* MidiMan M Audio Revolution 5.1
 			* MidiMan M Audio Revolution 7.1
+			* MidiMan M Audio Audiophile 192
 			* AMP Ltd AUDIO2000
 			* TerraTec Aureon 5.1 Sky
 			* TerraTec Aureon 7.1 Space
@@ -993,7 +1039,7 @@
 
     model       - Use the given board model, one of the following:
 		  revo51, revo71, amp2000, prodigy71, prodigy71lt,
-		  prodigy192, aureon51, aureon71, universe,
+		  prodigy192, aureon51, aureon71, universe, ap192,
 		  k8x800, phase22, phase28, ms300, av710
 
     This module supports multiple cards and autoprobe.
@@ -1049,6 +1095,9 @@
     buggy_semaphore - Enable workaround for hardwares with buggy
 		    semaphores (e.g. on some ASUS laptops)
 		    (default off)
+    spdif_aclink  - Use S/PDIF over AC-link instead of direct connection
+		    from the controller chip
+		    (0 = off, 1 = on, -1 = default)
 
     This module supports one chip and autoprobe.
 
@@ -1371,6 +1420,13 @@
 
     This module supports multiple cards.
 
+  Module snd-portman2x4
+  ---------------------
+
+    Module for Midiman Portman 2x4 parallel port MIDI interface
+
+    This module supports multiple cards.
+
   Module snd-powermac (on ppc only)
   ---------------------------------
 
diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
index 1f3ae3e..c4d2e35 100644
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
@@ -36,7 +36,7 @@
   </bookinfo>
 
   <chapter><title>Management of Cards and Devices</title>
-     <sect1><title>Card Managment</title>
+     <sect1><title>Card Management</title>
 !Esound/core/init.c
      </sect1>
      <sect1><title>Device Components</title>
@@ -59,7 +59,7 @@
      <sect1><title>PCM Format Helpers</title>
 !Esound/core/pcm_misc.c
      </sect1>
-     <sect1><title>PCM Memory Managment</title>
+     <sect1><title>PCM Memory Management</title>
 !Esound/core/pcm_memory.c
      </sect1>
   </chapter>
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index ccd0a95..74d3a35 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -1360,8 +1360,7 @@
         <informalexample>
           <programlisting>
 <![CDATA[
-  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
-                                          struct pt_regs *regs)
+  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
   {
           struct mychip *chip = dev_id;
           ....
@@ -2127,7 +2126,7 @@
 	accessible via <constant>substream-&gt;runtime</constant>.
 	This runtime pointer holds the various information; it holds
 	the copy of hw_params and sw_params configurations, the buffer
-	pointers, mmap records, spinlocks, etc.  Almost everyhing you
+	pointers, mmap records, spinlocks, etc.  Almost everything you
 	need for controlling the PCM can be found there.
 	</para>
 
@@ -2340,7 +2339,7 @@
 
 	<para>
 	  When the PCM substreams can be synchronized (typically,
-	synchorinized start/stop of a playback and a capture streams),
+	synchronized start/stop of a playback and a capture streams),
 	you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
 	too.  In this case, you'll need to check the linked-list of
 	PCM substreams in the trigger callback.  This will be
@@ -3062,8 +3061,7 @@
 	    <title>Interrupt Handler Case #1</title>
             <programlisting>
 <![CDATA[
-  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
-                                          struct pt_regs *regs)
+  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
   {
           struct mychip *chip = dev_id;
           spin_lock(&chip->lock);
@@ -3106,8 +3104,7 @@
 	    <title>Interrupt Handler Case #2</title>
             <programlisting>
 <![CDATA[
-  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
-                                          struct pt_regs *regs)
+  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
   {
           struct mychip *chip = dev_id;
           spin_lock(&chip->lock);
@@ -3247,7 +3244,7 @@
         You can even define your own constraint rules.
         For example, let's suppose my_chip can manage a substream of 1 channel
         if and only if the format is S16_LE, otherwise it supports any format
-        specified in the <structname>snd_pcm_hardware</structname> stucture (or in any
+        specified in the <structname>snd_pcm_hardware</structname> structure (or in any
         other constraint_list). You can build a rule like this:
 
         <example>
@@ -3691,16 +3688,6 @@
         </para>
 
         <para>
-          Here, the chip instance is retrieved via
-        <function>snd_kcontrol_chip()</function> macro.  This macro
-        just accesses to kcontrol-&gt;private_data. The
-        kcontrol-&gt;private_data field is 
-        given as the argument of <function>snd_ctl_new()</function>
-        (see the later subsection
-        <link linkend="control-interface-constructor"><citetitle>Constructor</citetitle></link>).
-        </para>
-
-        <para>
 	The <structfield>value</structfield> field is depending on
         the type of control as well as on info callback.  For example,
 	the sb driver uses this field to store the register offset,
@@ -3780,7 +3767,7 @@
         <para>
 	Like <structfield>get</structfield> callback,
 	when the control has more than one elements,
-	all elemehts must be evaluated in this callback, too.
+	all elements must be evaluated in this callback, too.
         </para>
       </section>
 
@@ -5541,12 +5528,12 @@
   #ifdef CONFIG_PM
   static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
   {
-          .... /* do things for suspsend */
+          .... /* do things for suspend */
           return 0;
   }
   static int snd_my_resume(struct pci_dev *pci)
   {
-          .... /* do things for suspsend */
+          .... /* do things for suspend */
           return 0;
   }
   #endif
@@ -6111,7 +6098,7 @@
 <!-- ****************************************************** -->
 <!-- Acknowledgments  -->
 <!-- ****************************************************** -->
-  <chapter id="acknowledments">
+  <chapter id="acknowledgments">
     <title>Acknowledgments</title>
     <para>
       I would like to thank Phil Kerr for his help for improvement and
diff --git a/Documentation/sound/alsa/hda_codec.txt b/Documentation/sound/alsa/hda_codec.txt
index 0be57ed..4eaae2a 100644
--- a/Documentation/sound/alsa/hda_codec.txt
+++ b/Documentation/sound/alsa/hda_codec.txt
@@ -277,11 +277,11 @@
 snd_hda_get_codec_name() stores the codec name on the given string.
 
 snd_hda_check_board_config() can be used to obtain the configuration
-information matching with the device.  Define the table with struct
-hda_board_config entries (zero-terminated), and pass it to the
-function.  The function checks the modelname given as a module
-parameter, and PCI subsystem IDs.  If the matching entry is found, it
-returns the config field value.
+information matching with the device.  Define the model string table
+and the table with struct snd_pci_quirk entries (zero-terminated),
+and pass it to the function.  The function checks the modelname given
+as a module parameter, and PCI subsystem IDs.  If the matching entry
+is found, it returns the config field value.
 
 snd_hda_add_new_ctls() can be used to create and add control entries.
 Pass the zero-terminated array of struct snd_kcontrol_new.  The same array
diff --git a/Documentation/sound/alsa/soc/DAI.txt b/Documentation/sound/alsa/soc/DAI.txt
new file mode 100644
index 0000000..58cbfd0
--- /dev/null
+++ b/Documentation/sound/alsa/soc/DAI.txt
@@ -0,0 +1,56 @@
+ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
+SoC controllers and portable audio CODECS today, namely AC97, I2S and PCM.
+
+
+AC97
+====
+
+  AC97 is a five wire interface commonly found on many PC sound cards. It is
+now also popular in many portable devices. This DAI has a reset line and time
+multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
+The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
+frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97
+frame is 21uS long and is divided into 13 time slots.
+
+The AC97 specification can be found at :-
+http://www.intel.com/design/chipsets/audio/ac97_r23.pdf
+
+
+I2S
+===
+
+ I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
+Rx lines are used for audio transmision, whilst the bit clock (BCLK) and
+left/right clock (LRC) synchronise the link. I2S is flexible in that either the
+controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
+usually varies depending on the sample rate and the master system clock
+(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate
+ADC and DAC LRCLK's, this allows for similtanious capture and playback at
+different sample rates.
+
+I2S has several different operating modes:-
+
+ o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC
+         transition.
+
+ o Left Justified - MSB is transmitted on transition of LRC.
+
+ o Right Justified - MSB is transmitted sample size BCLK's before LRC
+                     transition.
+
+PCM
+===
+
+PCM is another 4 wire interface, very similar to I2S, that can support a more
+flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used
+to synchronise the link whilst the Tx and Rx lines are used to transmit and
+receive the audio data. Bit clock usually varies depending on sample rate
+whilst sync runs at the sample rate. PCM also supports Time Division
+Multiplexing (TDM) in that several devices can use the bus similtaniuosly (This
+is sometimes referred to as network mode).
+
+Common PCM operating modes:-
+
+ o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
+
+ o Mode B - MSB is transmitted on rising edge of FRAME/SYNC.
diff --git a/Documentation/sound/alsa/soc/clocking.txt b/Documentation/sound/alsa/soc/clocking.txt
new file mode 100644
index 0000000..e93960d
--- /dev/null
+++ b/Documentation/sound/alsa/soc/clocking.txt
@@ -0,0 +1,51 @@
+Audio Clocking
+==============
+
+This text describes the audio clocking terms in ASoC and digital audio in
+general. Note: Audio clocking can be complex !
+
+
+Master Clock
+------------
+
+Every audio subsystem is driven by a master clock (sometimes refered to as MCLK
+or SYSCLK). This audio master clock can be derived from a number of sources
+(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
+audio playback and capture sample rates.
+
+Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that
+their speed can be altered by software (depending on the system use and to save
+power). Other master clocks are fixed at at set frequency (i.e. crystals).
+
+
+DAI Clocks
+----------
+The Digital Audio Interface is usually driven by a Bit Clock (often referred to
+as BCLK). This clock is used to drive the digital audio data across the link
+between the codec and CPU.
+
+The DAI also has a frame clock to signal the start of each audio frame. This
+clock is sometimes referred to as LRC (left right clock) or FRAME. This clock
+runs at exactly the sample rate (LRC = Rate).
+
+Bit Clock can be generated as follows:-
+
+BCLK = MCLK / x
+
+ or
+
+BCLK = LRC * x
+
+ or
+
+BCLK = LRC * Channels * Word Size
+
+This relationship depends on the codec or SoC CPU in particular. In general
+it's best to configure BCLK to the lowest possible speed (depending on your
+rate, number of channels and wordsize) to save on power.
+
+It's also desireable to use the codec (if possible) to drive (or master) the
+audio clocks as it's usually gives more accurate sample rates than the CPU.
+
+
+
diff --git a/Documentation/sound/alsa/soc/codec.txt b/Documentation/sound/alsa/soc/codec.txt
new file mode 100644
index 0000000..48983c7
--- /dev/null
+++ b/Documentation/sound/alsa/soc/codec.txt
@@ -0,0 +1,197 @@
+ASoC Codec Driver
+=================
+
+The codec driver is generic and hardware independent code that configures the
+codec to provide audio capture and playback. It should contain no code that is
+specific to the target platform or machine. All platform and machine specific
+code should be added to the platform and machine drivers respectively.
+
+Each codec driver *must* provide the following features:-
+
+ 1) Codec DAI and PCM configuration
+ 2) Codec control IO - using I2C, 3 Wire(SPI) or both API's
+ 3) Mixers and audio controls
+ 4) Codec audio operations
+
+Optionally, codec drivers can also provide:-
+
+ 5) DAPM description.
+ 6) DAPM event handler.
+ 7) DAC Digital mute control.
+
+It's probably best to use this guide in conjuction with the existing codec
+driver code in sound/soc/codecs/
+
+ASoC Codec driver breakdown
+===========================
+
+1 - Codec DAI and PCM configuration
+-----------------------------------
+Each codec driver must have a struct snd_soc_codec_dai to define it's DAI and
+PCM's capablities and operations. This struct is exported so that it can be
+registered with the core by your machine driver.
+
+e.g.
+
+struct snd_soc_codec_dai wm8731_dai = {
+	.name = "WM8731",
+	/* playback capabilities */
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8731_RATES,
+		.formats = WM8731_FORMATS,},
+	/* capture capabilities */
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8731_RATES,
+		.formats = WM8731_FORMATS,},
+	/* pcm operations - see section 4 below */
+	.ops = {
+		.prepare = wm8731_pcm_prepare,
+		.hw_params = wm8731_hw_params,
+		.shutdown = wm8731_shutdown,
+	},
+	/* DAI operations - see DAI.txt */
+	.dai_ops = {
+		.digital_mute = wm8731_mute,
+		.set_sysclk = wm8731_set_dai_sysclk,
+		.set_fmt = wm8731_set_dai_fmt,
+	}
+};
+EXPORT_SYMBOL_GPL(wm8731_dai);
+
+
+2 - Codec control IO
+--------------------
+The codec can ususally be controlled via an I2C or SPI style interface (AC97
+combines control with data in the DAI). The codec drivers will have to provide
+functions to read and write the codec registers along with supplying a register
+cache:-
+
+	/* IO control data and register cache */
+    void *control_data; /* codec control (i2c/3wire) data */
+    void *reg_cache;
+
+Codec read/write should do any data formatting and call the hardware read write
+below to perform the IO. These functions are called by the core and alsa when
+performing DAPM or changing the mixer:-
+
+    unsigned int (*read)(struct snd_soc_codec *, unsigned int);
+    int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
+
+Codec hardware IO functions - usually points to either the I2C, SPI or AC97
+read/write:-
+
+	hw_write_t hw_write;
+	hw_read_t hw_read;
+
+
+3 - Mixers and audio controls
+-----------------------------
+All the codec mixers and audio controls can be defined using the convenience
+macros defined in soc.h.
+
+    #define SOC_SINGLE(xname, reg, shift, mask, invert)
+
+Defines a single control as follows:-
+
+  xname = Control name e.g. "Playback Volume"
+  reg = codec register
+  shift = control bit(s) offset in register
+  mask = control bit size(s) e.g. mask of 7 = 3 bits
+  invert = the control is inverted
+
+Other macros include:-
+
+    #define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
+
+A stereo control
+
+    #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
+
+A stereo control spanning 2 registers
+
+    #define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
+
+Defines an single enumerated control as follows:-
+
+   xreg = register
+   xshift = control bit(s) offset in register
+   xmask = control bit(s) size
+   xtexts = pointer to array of strings that describe each setting
+
+   #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts)
+
+Defines a stereo enumerated control
+
+
+4 - Codec Audio Operations
+--------------------------
+The codec driver also supports the following alsa operations:-
+
+/* SoC audio ops */
+struct snd_soc_ops {
+	int (*startup)(struct snd_pcm_substream *);
+	void (*shutdown)(struct snd_pcm_substream *);
+	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
+	int (*hw_free)(struct snd_pcm_substream *);
+	int (*prepare)(struct snd_pcm_substream *);
+};
+
+Please refer to the alsa driver PCM documentation for details.
+http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
+
+
+5 - DAPM description.
+---------------------
+The Dynamic Audio Power Management description describes the codec's power
+components, their relationships and registers to the ASoC core. Please read
+dapm.txt for details of building the description.
+
+Please also see the examples in other codec drivers.
+
+
+6 - DAPM event handler
+----------------------
+This function is a callback that handles codec domain PM calls and system
+domain PM calls (e.g. suspend and resume). It's used to put the codec to sleep
+when not in use.
+
+Power states:-
+
+	SNDRV_CTL_POWER_D0: /* full On */
+	/* vref/mid, clk and osc on, active */
+
+	SNDRV_CTL_POWER_D1: /* partial On */
+	SNDRV_CTL_POWER_D2: /* partial On */
+
+	SNDRV_CTL_POWER_D3hot: /* Off, with power */
+	/* everything off except vref/vmid, inactive */
+
+	SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
+
+
+7 - Codec DAC digital mute control.
+------------------------------------
+Most codecs have a digital mute before the DAC's that can be used to minimise
+any system noise.  The mute stops any digital data from entering the DAC.
+
+A callback can be created that is called by the core for each codec DAI when the
+mute is applied or freed.
+
+i.e.
+
+static int wm8974_mute(struct snd_soc_codec *codec,
+	struct snd_soc_codec_dai *dai, int mute)
+{
+	u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf;
+	if(mute)
+		wm8974_write(codec, WM8974_DAC, mute_reg | 0x40);
+	else
+		wm8974_write(codec, WM8974_DAC, mute_reg);
+	return 0;
+}
diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt
new file mode 100644
index 0000000..c11877f
--- /dev/null
+++ b/Documentation/sound/alsa/soc/dapm.txt
@@ -0,0 +1,297 @@
+Dynamic Audio Power Management for Portable Devices
+===================================================
+
+1. Description
+==============
+
+Dynamic Audio Power Management (DAPM) is designed to allow portable Linux devices
+to use the minimum amount of power within the audio subsystem at all times. It
+is independent of other kernel PM and as such, can easily co-exist with the
+other PM systems.
+
+DAPM is also completely transparent to all user space applications as all power
+switching is done within the ASoC core. No code changes or recompiling are
+required for user space applications. DAPM makes power switching descisions based
+upon any audio stream (capture/playback) activity and audio mixer settings
+within the device.
+
+DAPM spans the whole machine. It covers power control within the entire audio
+subsystem, this includes internal codec power blocks and machine level power
+systems.
+
+There are 4 power domains within DAPM
+
+   1. Codec domain - VREF, VMID (core codec and audio power)
+      Usually controlled at codec probe/remove and suspend/resume, although
+      can be set at stream time if power is not needed for sidetone, etc.
+
+   2. Platform/Machine domain - physically connected inputs and outputs
+      Is platform/machine and user action specific, is configured by the
+      machine driver and responds to asynchronous events e.g when HP
+      are inserted
+
+   3. Path domain - audio susbsystem signal paths
+      Automatically set when mixer and mux settings are changed by the user.
+      e.g. alsamixer, amixer.
+
+   4. Stream domain - DAC's and ADC's.
+      Enabled and disabled when stream playback/capture is started and
+      stopped respectively. e.g. aplay, arecord.
+
+All DAPM power switching descisons are made automatically by consulting an audio
+routing map of the whole machine. This map is specific to each machine and
+consists of the interconnections between every audio component (including
+internal codec components). All audio components that effect power are called
+widgets hereafter.
+
+
+2. DAPM Widgets
+===============
+
+Audio DAPM widgets fall into a number of types:-
+
+ o Mixer      - Mixes several analog signals into a single analog signal.
+ o Mux        - An analog switch that outputs only 1 of it's inputs.
+ o PGA        - A programmable gain amplifier or attenuation widget.
+ o ADC        - Analog to Digital Converter
+ o DAC        - Digital to Analog Converter
+ o Switch     - An analog switch
+ o Input      - A codec input pin
+ o Output     - A codec output pin
+ o Headphone  - Headphone (and optional Jack)
+ o Mic        - Mic (and optional Jack)
+ o Line       - Line Input/Output (and optional Jack)
+ o Speaker    - Speaker
+ o Pre        - Special PRE widget (exec before all others)
+ o Post       - Special POST widget (exec after all others)
+
+(Widgets are defined in include/sound/soc-dapm.h)
+
+Widgets are usually added in the codec driver and the machine driver. There are
+convience macros defined in soc-dapm.h that can be used to quickly build a
+list of widgets of the codecs and machines DAPM widgets.
+
+Most widgets have a name, register, shift and invert. Some widgets have extra
+parameters for stream name and kcontrols.
+
+
+2.1 Stream Domain Widgets
+-------------------------
+
+Stream Widgets relate to the stream power domain and only consist of ADC's
+(analog to digital converters) and DAC's (digital to analog converters).
+
+Stream widgets have the following format:-
+
+SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
+
+NOTE: the stream name must match the corresponding stream name in your codecs
+snd_soc_codec_dai.
+
+e.g. stream widgets for HiFi playback and capture
+
+SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
+SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
+
+
+2.2 Path Domain Widgets
+-----------------------
+
+Path domain widgets have a ability to control or effect the audio signal or
+audio paths within the audio subsystem. They have the following form:-
+
+SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
+
+Any widget kcontrols can be set using the controls and num_controls members.
+
+e.g. Mixer widget (the kcontrols are declared first)
+
+/* Output Mixer */
+static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
+SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
+SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
+SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
+};
+
+SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
+	ARRAY_SIZE(wm8731_output_mixer_controls)),
+
+
+2.3 Platform/Machine domain Widgets
+-----------------------------------
+
+Machine widgets are different from codec widgets in that they don't have a
+codec register bit associated with them. A machine widget is assigned to each
+machine audio component (non codec) that can be independently powered. e.g.
+
+ o Speaker Amp
+ o Microphone Bias
+ o Jack connectors
+
+A machine widget can have an optional call back.
+
+e.g. Jack connector widget for an external Mic that enables Mic Bias
+when the Mic is inserted:-
+
+static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
+{
+	if(SND_SOC_DAPM_EVENT_ON(event))
+		set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
+	else
+		reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
+
+	return 0;
+}
+
+SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
+
+
+2.4 Codec Domain
+----------------
+
+The Codec power domain has no widgets and is handled by the codecs DAPM event
+handler. This handler is called when the codec powerstate is changed wrt to any
+stream event or by kernel PM events.
+
+
+2.5 Virtual Widgets
+-------------------
+
+Sometimes widgets exist in the codec or machine audio map that don't have any
+corresponding register bit for power control. In this case it's necessary to
+create a virtual widget - a widget with no control bits e.g.
+
+SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
+
+This can be used to merge to signal paths together in software.
+
+After all the widgets have been defined, they can then be added to the DAPM
+subsystem individually with a call to snd_soc_dapm_new_control().
+
+
+3. Codec Widget Interconnections
+================================
+
+Widgets are connected to each other within the codec and machine by audio
+paths (called interconnections). Each interconnection must be defined in order
+to create a map of all audio paths between widgets.
+This is easiest with a diagram of the codec (and schematic of the machine audio
+system), as it requires joining widgets together via their audio signal paths.
+
+i.e. from the WM8731 codec's output mixer (wm8731.c)
+
+The WM8731 output mixer has 3 inputs (sources)
+
+ 1. Line Bypass Input
+ 2. DAC (HiFi playback)
+ 3. Mic Sidetone Input
+
+Each input in this example has a kcontrol associated with it (defined in example
+above) and is connected to the output mixer via it's kcontrol name. We can now
+connect the destination widget (wrt audio signal) with it's source widgets.
+
+	/* output mixer */
+	{"Output Mixer", "Line Bypass Switch", "Line Input"},
+	{"Output Mixer", "HiFi Playback Switch", "DAC"},
+	{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
+
+So we have :-
+
+	Destination Widget  <=== Path Name <=== Source Widget
+
+Or:-
+
+	Sink, Path, Source
+
+Or :-
+
+	"Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch".
+
+When there is no path name connecting widgets (e.g. a direct connection) we
+pass NULL for the path name.
+
+Interconnections are created with a call to:-
+
+snd_soc_dapm_connect_input(codec, sink, path, source);
+
+Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
+interconnections have been registered with the core. This causes the core to
+scan the codec and machine so that the internal DAPM state matches the
+physical state of the machine.
+
+
+3.1 Machine Widget Interconnections
+-----------------------------------
+Machine widget interconnections are created in the same way as codec ones and
+directly connect the codec pins to machine level widgets.
+
+e.g. connects the speaker out codec pins to the internal speaker.
+
+	/* ext speaker connected to codec pins LOUT2, ROUT2  */
+	{"Ext Spk", NULL , "ROUT2"},
+	{"Ext Spk", NULL , "LOUT2"},
+
+This allows the DAPM to power on and off pins that are connected (and in use)
+and pins that are NC respectively.
+
+
+4 Endpoint Widgets
+===================
+An endpoint is a start or end point (widget) of an audio signal within the
+machine and includes the codec. e.g.
+
+ o Headphone Jack
+ o Internal Speaker
+ o Internal Mic
+ o Mic Jack
+ o Codec Pins
+
+When a codec pin is NC it can be marked as not used with a call to
+
+snd_soc_dapm_set_endpoint(codec, "Widget Name", 0);
+
+The last argument is 0 for inactive and 1 for active. This way the pin and its
+input widget will never be powered up and consume power.
+
+This also applies to machine widgets. e.g. if a headphone is connected to a
+jack then the jack can be marked active. If the headphone is removed, then
+the headphone jack can be marked inactive.
+
+
+5 DAPM Widget Events
+====================
+
+Some widgets can register their interest with the DAPM core in PM events.
+e.g. A Speaker with an amplifier registers a widget so the amplifier can be
+powered only when the spk is in use.
+
+/* turn speaker amplifier on/off depending on use */
+static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
+	else
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
+
+	return 0;
+}
+
+/* corgi machine dapm widgets */
+static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
+	SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
+
+Please see soc-dapm.h for all other widgets that support events.
+
+
+5.1 Event types
+---------------
+
+The following event types are supported by event widgets.
+
+/* dapm event types */
+#define SND_SOC_DAPM_PRE_PMU	0x1 	/* before widget power up */
+#define SND_SOC_DAPM_POST_PMU	0x2		/* after widget power up */
+#define SND_SOC_DAPM_PRE_PMD	0x4 	/* before widget power down */
+#define SND_SOC_DAPM_POST_PMD	0x8		/* after widget power down */
+#define SND_SOC_DAPM_PRE_REG	0x10	/* before audio path setup */
+#define SND_SOC_DAPM_POST_REG	0x20	/* after audio path setup */
diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/alsa/soc/machine.txt
new file mode 100644
index 0000000..72bd222
--- /dev/null
+++ b/Documentation/sound/alsa/soc/machine.txt
@@ -0,0 +1,113 @@
+ASoC Machine Driver
+===================
+
+The ASoC machine (or board) driver is the code that glues together the platform
+and codec drivers.
+
+The machine driver can contain codec and platform specific code. It registers
+the audio subsystem with the kernel as a platform device and is represented by
+the following struct:-
+
+/* SoC machine */
+struct snd_soc_machine {
+	char *name;
+
+	int (*probe)(struct platform_device *pdev);
+	int (*remove)(struct platform_device *pdev);
+
+	/* the pre and post PM functions are used to do any PM work before and
+	 * after the codec and DAI's do any PM work. */
+	int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
+	int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
+	int (*resume_pre)(struct platform_device *pdev);
+	int (*resume_post)(struct platform_device *pdev);
+
+	/* machine stream operations */
+	struct snd_soc_ops *ops;
+
+	/* CPU <--> Codec DAI links  */
+	struct snd_soc_dai_link *dai_link;
+	int num_links;
+};
+
+probe()/remove()
+----------------
+probe/remove are optional. Do any machine specific probe here.
+
+
+suspend()/resume()
+------------------
+The machine driver has pre and post versions of suspend and resume to take care
+of any machine audio tasks that have to be done before or after the codec, DAI's
+and DMA is suspended and resumed. Optional.
+
+
+Machine operations
+------------------
+The machine specific audio operations can be set here. Again this is optional.
+
+
+Machine DAI Configuration
+-------------------------
+The machine DAI configuration glues all the codec and CPU DAI's together. It can
+also be used to set up the DAI system clock and for any machine related DAI
+initialisation e.g. the machine audio map can be connected to the codec audio
+map, unconnnected codec pins can be set as such. Please see corgi.c, spitz.c
+for examples.
+
+struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
+
+/* corgi digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link corgi_dai = {
+	.name = "WM8731",
+	.stream_name = "WM8731",
+	.cpu_dai = &pxa_i2s_dai,
+	.codec_dai = &wm8731_dai,
+	.init = corgi_wm8731_init,
+	.ops = &corgi_ops,
+};
+
+struct snd_soc_machine then sets up the machine with it's DAI's. e.g.
+
+/* corgi audio machine driver */
+static struct snd_soc_machine snd_soc_machine_corgi = {
+	.name = "Corgi",
+	.dai_link = &corgi_dai,
+	.num_links = 1,
+};
+
+
+Machine Audio Subsystem
+-----------------------
+
+The machine soc device glues the platform, machine and codec driver together.
+Private data can also be set here. e.g.
+
+/* corgi audio private data */
+static struct wm8731_setup_data corgi_wm8731_setup = {
+	.i2c_address = 0x1b,
+};
+
+/* corgi audio subsystem */
+static struct snd_soc_device corgi_snd_devdata = {
+	.machine = &snd_soc_machine_corgi,
+	.platform = &pxa2xx_soc_platform,
+	.codec_dev = &soc_codec_dev_wm8731,
+	.codec_data = &corgi_wm8731_setup,
+};
+
+
+Machine Power Map
+-----------------
+
+The machine driver can optionally extend the codec power map and to become an
+audio power map of the audio subsystem. This allows for automatic power up/down
+of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack
+sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for
+details.
+
+
+Machine Controls
+----------------
+
+Machine specific audio mixer controls can be added in the dai init function.
\ No newline at end of file
diff --git a/Documentation/sound/alsa/soc/overview.txt b/Documentation/sound/alsa/soc/overview.txt
new file mode 100644
index 0000000..753c5cc
--- /dev/null
+++ b/Documentation/sound/alsa/soc/overview.txt
@@ -0,0 +1,83 @@
+ALSA SoC Layer
+==============
+
+The overall project goal of the ALSA System on Chip (ASoC) layer is to provide
+better ALSA support for embedded system on chip procesors (e.g. pxa2xx, au1x00,
+iMX, etc) and portable audio codecs. Currently there is some support in the
+kernel for SoC audio, however it has some limitations:-
+
+  * Currently, codec drivers are often tightly coupled to the underlying SoC
+    cpu. This is not ideal and leads to code duplication i.e. Linux now has 4
+    different wm8731 drivers for 4 different SoC platforms.
+
+  * There is no standard method to signal user initiated audio events.
+    e.g. Headphone/Mic insertion, Headphone/Mic detection after an insertion
+    event. These are quite common events on portable devices and ofter require
+    machine specific code to re route audio, enable amps etc after such an event.
+
+  * Current drivers tend to power up the entire codec when playing
+    (or recording) audio. This is fine for a PC, but tends to waste a lot of
+    power on portable devices. There is also no support for saving power via
+    changing codec oversampling rates, bias currents, etc.
+
+
+ASoC Design
+===========
+
+The ASoC layer is designed to address these issues and provide the following
+features :-
+
+  * Codec independence. Allows reuse of codec drivers on other platforms
+    and machines.
+
+  * Easy I2S/PCM audio interface setup between codec and SoC. Each SoC interface
+    and codec registers it's audio interface capabilities with the core and are
+    subsequently matched and configured when the application hw params are known.
+
+  * Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
+    it's minimum power state at all times. This includes powering up/down
+    internal power blocks depending on the internal codec audio routing and any
+    active streams.
+
+  * Pop and click reduction. Pops and clicks can be reduced by powering the
+    codec up/down in the correct sequence (including using digital mute). ASoC
+    signals the codec when to change power states.
+
+  * Machine specific controls: Allow machines to add controls to the sound card
+    e.g. volume control for speaker amp.
+
+To achieve all this, ASoC basically splits an embedded audio system into 3
+components :-
+
+  * Codec driver: The codec driver is platform independent and contains audio
+    controls, audio interface capabilities, codec dapm definition and codec IO
+    functions.
+
+  * Platform driver: The platform driver contains the audio dma engine and audio
+    interface drivers (e.g. I2S, AC97, PCM) for that platform.
+
+  * Machine driver: The machine driver handles any machine specific controls and
+    audio events. i.e. turing on an amp at start of playback.
+
+
+Documentation
+=============
+
+The documentation is spilt into the following sections:-
+
+overview.txt: This file.
+
+codec.txt: Codec driver internals.
+
+DAI.txt: Description of Digital Audio Interface standards and how to configure
+a DAI within your codec and CPU DAI drivers.
+
+dapm.txt: Dynamic Audio Power Management
+
+platform.txt: Platform audio DMA and DAI.
+
+machine.txt: Machine driver internals.
+
+pop_clicks.txt: How to minimise audio artifacts.
+
+clocking.txt: ASoC clocking for best power performance.
\ No newline at end of file
diff --git a/Documentation/sound/alsa/soc/platform.txt b/Documentation/sound/alsa/soc/platform.txt
new file mode 100644
index 0000000..e95b16d
--- /dev/null
+++ b/Documentation/sound/alsa/soc/platform.txt
@@ -0,0 +1,58 @@
+ASoC Platform Driver
+====================
+
+An ASoC platform driver can be divided into audio DMA and SoC DAI configuration
+and control. The platform drivers only target the SoC CPU and must have no board
+specific code.
+
+Audio DMA
+=========
+
+The platform DMA driver optionally supports the following alsa operations:-
+
+/* SoC audio ops */
+struct snd_soc_ops {
+	int (*startup)(struct snd_pcm_substream *);
+	void (*shutdown)(struct snd_pcm_substream *);
+	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
+	int (*hw_free)(struct snd_pcm_substream *);
+	int (*prepare)(struct snd_pcm_substream *);
+	int (*trigger)(struct snd_pcm_substream *, int);
+};
+
+The platform driver exports it's DMA functionailty via struct snd_soc_platform:-
+
+struct snd_soc_platform {
+	char *name;
+
+	int (*probe)(struct platform_device *pdev);
+	int (*remove)(struct platform_device *pdev);
+	int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
+	int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
+
+	/* pcm creation and destruction */
+	int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *);
+	void (*pcm_free)(struct snd_pcm *);
+
+	/* platform stream ops */
+	struct snd_pcm_ops *pcm_ops;
+};
+
+Please refer to the alsa driver documentation for details of audio DMA.
+http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
+
+An example DMA driver is soc/pxa/pxa2xx-pcm.c
+
+
+SoC DAI Drivers
+===============
+
+Each SoC DAI driver must provide the following features:-
+
+ 1) Digital audio interface (DAI) description
+ 2) Digital audio interface configuration
+ 3) PCM's description
+ 4) Sysclk configuration
+ 5) Suspend and resume (optional)
+
+Please see codec.txt for a description of items 1 - 4.
diff --git a/Documentation/sound/alsa/soc/pops_clicks.txt b/Documentation/sound/alsa/soc/pops_clicks.txt
new file mode 100644
index 0000000..2cf7ee5
--- /dev/null
+++ b/Documentation/sound/alsa/soc/pops_clicks.txt
@@ -0,0 +1,52 @@
+Audio Pops and Clicks
+=====================
+
+Pops and clicks are unwanted audio artifacts caused by the powering up and down
+of components within the audio subsystem. This is noticable on PC's when an
+audio module is either loaded or unloaded (at module load time the sound card is
+powered up and causes a popping noise on the speakers).
+
+Pops and clicks can be more frequent on portable systems with DAPM. This is
+because the components within the subsystem are being dynamically powered
+depending on the audio usage and this can subsequently cause a small pop or
+click every time a component power state is changed.
+
+
+Minimising Playback Pops and Clicks
+===================================
+
+Playback pops in portable audio subsystems cannot be completely eliminated atm,
+however future audio codec hardware will have better pop and click supression.
+Pops can be reduced within playback by powering the audio components in a
+specific order. This order is different for startup and shutdown and follows
+some basic rules:-
+
+ Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
+
+ Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
+
+This assumes that the codec PCM output path from the DAC is via a mixer and then
+a PGA (programmable gain amplifier) before being output to the speakers.
+
+
+Minimising Capture Pops and Clicks
+==================================
+
+Capture artifacts are somewhat easier to get rid as we can delay activating the
+ADC until all the pops have occured. This follows similar power rules to
+playback in that components are powered in a sequence depending upon stream
+startup or shutdown.
+
+ Startup Order - Input PGA --> Mixers --> ADC
+
+ Shutdown Order - ADC --> Mixers --> Input PGA
+
+
+Zipper Noise
+============
+An unwanted zipper noise can occur within the audio playback or capture stream
+when a volume control is changed near its maximum gain value. The zipper noise
+is heard when the gain increase or decrease changes the mean audio signal
+amplitude too quickly. It can be minimised by enabling the zero cross setting
+for each volume control. The ZC forces the gain change to occur when the signal
+crosses the zero amplitude line.
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index 7279579..ecc7c9e 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -284,7 +284,6 @@
 	static struct spi_driver CHIP_driver = {
 		.driver = {
 			.name		= "CHIP",
-			.bus		= &spi_bus_type,
 			.owner		= THIS_MODULE,
 		},
 
@@ -312,7 +311,7 @@
 		chip = kzalloc(sizeof *chip, GFP_KERNEL);
 		if (!chip)
 			return -ENOMEM;
-		dev_set_drvdata(&spi->dev, chip);
+		spi_set_drvdata(spi, chip);
 
 		... etc
 		return 0;
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index 6161316..452c0f1 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -64,11 +64,6 @@
 
 *  What are the 'command' keys?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-'r'     - Turns off keyboard raw mode and sets it to XLATE.
-
-'k'     - Secure Access Key (SAK) Kills all programs on the current virtual
-          console. NOTE: See important comments below in SAK section.
-
 'b'     - Will immediately reboot the system without syncing or unmounting
           your disks.
 
@@ -76,21 +71,37 @@
 
 'd'	- Shows all locks that are held.
 
-'o'     - Will shut your system off (if configured and supported).
+'e'     - Send a SIGTERM to all processes, except for init.
 
-'s'     - Will attempt to sync all mounted filesystems.
+'f'	- Will call oom_kill to kill a memory hog process.
 
-'u'     - Will attempt to remount all mounted filesystems read-only.
+'g'	- Used by kgdb on ppc platforms.
 
-'p'     - Will dump the current registers and flags to your console.
+'h'     - Will display help (actually any other key than those listed
+          above will display help. but 'h' is easy to remember :-)
 
-'t'     - Will dump a list of current tasks and their information to your
-          console.
+'i'     - Send a SIGKILL to all processes, except for init.
+
+'k'     - Secure Access Key (SAK) Kills all programs on the current virtual
+          console. NOTE: See important comments below in SAK section.
 
 'm'     - Will dump current memory info to your console.
 
 'n'	- Used to make RT tasks nice-able
 
+'o'     - Will shut your system off (if configured and supported).
+
+'p'     - Will dump the current registers and flags to your console.
+
+'r'     - Turns off keyboard raw mode and sets it to XLATE.
+
+'s'     - Will attempt to sync all mounted filesystems.
+
+'t'     - Will dump a list of current tasks and their information to your
+          console.
+
+'u'     - Will attempt to remount all mounted filesystems read-only.
+
 'v'	- Dumps Voyager SMP processor info to your console.
 
 'w'	- Dumps tasks that are in uninterruptable (blocked) state.
@@ -102,17 +113,6 @@
           it so that only emergency messages like PANICs or OOPSes would
           make it to your console.)
 
-'f'	- Will call oom_kill to kill a memory hog process.
-
-'e'     - Send a SIGTERM to all processes, except for init.
-
-'g'	- Used by kgdb on ppc platforms.
-
-'i'     - Send a SIGKILL to all processes, except for init.
-
-'h'     - Will display help (actually any other key than those listed
-          above will display help. but 'h' is easy to remember :-)
-
 *  Okay, so what can I use them for?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Well, un'R'aw is very handy when your X server or a svgalib program crashes.
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
index 4efa464..fc2fe9b 100644
--- a/Documentation/video4linux/CARDLIST.bttv
+++ b/Documentation/video4linux/CARDLIST.bttv
@@ -126,7 +126,7 @@
 125 -> MATRIX Vision Sigma-SQ
 126 -> MATRIX Vision Sigma-SLC
 127 -> APAC Viewcomp 878(AMAX)
-128 -> DViCO FusionHDTV DVB-T Lite                         [18ac:db10]
+128 -> DViCO FusionHDTV DVB-T Lite                         [18ac:db10,18ac:db11]
 129 -> V-Gear MyVCD
 130 -> Super TV Tuner
 131 -> Tibet Systems 'Progress DVR' CS16
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index f6201cc..a12246a 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -104,3 +104,6 @@
 103 -> Compro Videomate DVB-T200A
 104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid     [0070:6701]
 105 -> Terratec Cinergy HT PCMCIA               [153b:1172]
+106 -> Encore ENLTV                             [1131:2342,1131:2341,3016:2344]
+107 -> Encore ENLTV-FM                          [1131:230f]
+108 -> Terratec Cinergy HT PCI                  [153b:1175]
diff --git a/Documentation/video4linux/CQcam.txt b/Documentation/video4linux/CQcam.txt
index ade8651..04986ef 100644
--- a/Documentation/video4linux/CQcam.txt
+++ b/Documentation/video4linux/CQcam.txt
@@ -197,10 +197,10 @@
 PORT SUPPORT sections
 
 The video4linux page:
-  http://roadrunner.swansea.linux.org.uk/v4l.shtml
+  http://linuxtv.org
 
-The video4linux2 page:
-  http://millennium.diads.com/bdirks/v4l2.htm
+The V4L2 API spec:
+  http://v4l2spec.bytesex.org/
 
 Some web pages about the quickcams:
    http://www.dkfz-heidelberg.de/Macromol/wedemann/mini-HOWTO-cqcam.html
diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran
index deb218f..85c575ac 100644
--- a/Documentation/video4linux/Zoran
+++ b/Documentation/video4linux/Zoran
@@ -339,9 +339,9 @@
 (also see below)
 
 Information - video4linux2:
-http://www.thedirks.org/v4l2/
+http://linuxtv.org
+http://v4l2spec.bytesex.org/
 /usr/include/linux/videodev2.h
-http://www.bytesex.org/v4l/
 
 More information on the video4linux/mjpeg extensions, by Serguei
 Miridonovi and Rainer Johanni:
diff --git a/Documentation/video4linux/bttv/Insmod-options b/Documentation/video4linux/bttv/Insmod-options
index bb7c2ca..5ef7578 100644
--- a/Documentation/video4linux/bttv/Insmod-options
+++ b/Documentation/video4linux/bttv/Insmod-options
@@ -57,7 +57,7 @@
 		i2c_udelay=     Allow reduce I2C speed. Default is 5 usecs
 				(meaning 66,67 Kbps). The default is the
 				maximum supported speed by kernel bitbang
-				algoritm. You may use lower numbers, if I2C
+				algorithm. You may use lower numbers, if I2C
 				messages are lost (16 is known to work on
 				all supported cards).
 
diff --git a/Documentation/video4linux/cx2341x/fw-decoder-api.txt b/Documentation/video4linux/cx2341x/fw-decoder-api.txt
index 78bf5f2..8c317b7 100644
--- a/Documentation/video4linux/cx2341x/fw-decoder-api.txt
+++ b/Documentation/video4linux/cx2341x/fw-decoder-api.txt
@@ -21,7 +21,7 @@
 	0 based frame number in GOP to begin playback from.
 Param[1]
 	Specifies the number of muted audio frames to play before normal
-	audio resumes.
+	audio resumes. (This is not implemented in the firmware, leave at 0)
 
 -------------------------------------------------------------------------------
 
@@ -32,6 +32,10 @@
 	playback stops at specified PTS.
 Param[0]
 	Display 0=last frame, 1=black
+	Note: this takes effect immediately, so if you want to wait for a PTS,
+	then use '0', otherwise the screen goes to black at once.
+	You can call this later (even if there is no playback) with a 1 value
+	to set the screen to black.
 Param[1]
 	PTS low
 Param[2]
@@ -60,8 +64,12 @@
 	    31   Speed:
 		     '0' slow
 		     '1' fast
+	Note: n is limited to 2. Anything higher does not result in
+	faster playback. Instead the host should start dropping frames.
 Param[1]
 	Direction: 0=forward, 1=reverse
+	Note: to make reverse playback work you have to write full GOPs in
+	reverse order.
 Param[2]
 	Picture mask:
 	    1=I frames
@@ -69,13 +77,16 @@
 	    7=I, P, B frames
 Param[3]
 	B frames per GOP (for reverse play only)
+	Note: for reverse playback the Picture Mask should be set to I or I, P.
+	Adding B frames to the mask will result in corrupt video. This field
+	has to be set to the correct value in order to keep the timing correct.
 Param[4]
 	Mute audio: 0=disable, 1=enable
 Param[5]
 	Display 0=frame, 1=field
 Param[6]
 	Specifies the number of muted audio frames to play before normal audio
-	resumes.
+	resumes. (Not implemented in the firmware, leave at 0)
 
 -------------------------------------------------------------------------------
 
@@ -212,6 +223,7 @@
 	Select audio mode
 Param[0]
 	Dual mono mode action
+	    0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged
 Param[1]
 	Stereo mode action:
 	    0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged
@@ -224,7 +236,10 @@
 	Setup firmware to notify the host about a particular event.
 	Counterpart to API 0xD5
 Param[0]
-	Event: 0=Audio mode change between stereo and dual channel
+	Event: 0=Audio mode change between mono, (joint) stereo and dual channel.
+	Event: 3=Decoder started
+	Event: 4=Unknown: goes off 10-15 times per second while decoding.
+	Event: 5=Some sync event: goes off once per frame.
 Param[1]
 	Notification 0=disabled, 1=enabled
 Param[2]
@@ -273,43 +288,6 @@
 
 -------------------------------------------------------------------------------
 
-Name 	CX2341X_DEC_SET_AUDIO_OUTPUT
-Enum 	27/0x1B
-Description
-	Select audio output format
-Param[0]
-	Bitmask:
-	     0:1  Data size:
-		      '00' 16 bit
-		      '01' 20 bit
-		      '10' 24 bit
-	     2:7  Unused
-	     8:9  Mode:
-		      '00' 2 channels
-		      '01' 4 channels
-		      '10' 6 channels
-		      '11' 6 channels with one line data mode
-			   (for left justified MSB first mode, 20 bit only)
-	    10:11 Unused
-	    12:13 Channel format:
-		      '00' right justified MSB first mode
-		      '01' left justified MSB first mode
-		      '10' I2S mode
-	    14:15 Unused
-	    16:21 Right justify bit count
-	    22:31 Unused
-
--------------------------------------------------------------------------------
-
-Name 	CX2341X_DEC_SET_AV_DELAY
-Enum 	28/0x1C
-Description
-	Set audio/video delay in 90Khz ticks
-Param[0]
-	0=A/V in sync, negative=audio lags, positive=video lags
-
--------------------------------------------------------------------------------
-
 Name 	CX2341X_DEC_SET_PREBUFFERING
 Enum 	30/0x1E
 Description
diff --git a/Documentation/video4linux/cx2341x/fw-decoder-regs.txt b/Documentation/video4linux/cx2341x/fw-decoder-regs.txt
new file mode 100644
index 0000000..db2366c
--- /dev/null
+++ b/Documentation/video4linux/cx2341x/fw-decoder-regs.txt
@@ -0,0 +1,815 @@
+PVR350 Video decoder registers 0x02002800 -> 0x02002B00
+=======================================================
+
+This list has been worked out through trial and error. There will be mistakes
+and omissions. Some registers have no obvious effect so it's hard to say what
+they do, while others interact with each other, or require a certain load
+sequence. Horizontal filter setup is one example, with six registers working
+in unison and requiring a certain load sequence to correctly configure. The
+indexed colour palette is much easier to set at just two registers, but again
+it requires a certain load sequence.
+
+Some registers are fussy about what they are set to. Load in a bad value & the
+decoder will fail. A firmware reload will often recover, but sometimes a reset
+is required. For registers containing size information, setting them to 0 is
+generally a bad idea. For other control registers i.e. 2878, you'll only find
+out what values are bad when it hangs.
+
+--------------------------------------------------------------------------------
+2800
+      bit 0
+	Decoder enable
+	  0 = disable
+	  1 = enable
+--------------------------------------------------------------------------------
+2804
+      bits 0:31
+	Decoder horizontal Y alias register 1
+---------------
+2808
+      bits 0:31
+	Decoder horizontal Y alias register 2
+---------------
+280C
+      bits 0:31
+	Decoder horizontal Y alias register 3
+---------------
+2810
+      bits 0:31
+	Decoder horizontal Y alias register 4
+---------------
+2814
+      bits 0:31
+	Decoder horizontal Y alias register 5
+---------------
+2818
+      bits 0:31
+	Decoder horizontal Y alias trigger
+
+     These six registers control the horizontal aliasing filter for the Y plane.
+     The first five registers must all be loaded before accessing the trigger
+     (2818), as this register actually clocks the data through for the first
+     five.
+
+     To correctly program set the filter, this whole procedure must be done 16
+     times. The actual register contents are copied from a lookup-table in the
+     firmware which contains 4 different filter settings.
+
+--------------------------------------------------------------------------------
+281C
+      bits 0:31
+	Decoder horizontal UV alias register 1
+---------------
+2820
+      bits 0:31
+	Decoder horizontal UV alias register 2
+---------------
+2824
+      bits 0:31
+	Decoder horizontal UV alias register 3
+---------------
+2828
+      bits 0:31
+	Decoder horizontal UV alias register 4
+---------------
+282C
+      bits 0:31
+	Decoder horizontal UV alias register 5
+---------------
+2830
+      bits 0:31
+	Decoder horizontal UV alias trigger
+
+     These six registers control the horizontal aliasing for the UV plane.
+     Operation is the same as the Y filter, with 2830 being the trigger
+     register.
+
+--------------------------------------------------------------------------------
+2834
+      bits 0:15
+	Decoder Y source width in pixels
+
+      bits 16:31
+	Decoder Y destination width in pixels
+---------------
+2838
+      bits 0:15
+	Decoder UV source width in pixels
+
+      bits 16:31
+	Decoder UV destination width in pixels
+
+     NOTE: For both registers, the resulting image must be fully visible on
+     screen. If the image exceeds the right edge both the source and destination
+     size must be adjusted to reflect the visible portion. For the source width,
+     you must take into account the scaling when calculating the new value.
+--------------------------------------------------------------------------------
+
+283C
+      bits 0:31
+	Decoder Y horizontal scaling
+		    Normally = Reg 2854 >> 2
+---------------
+2840
+      bits 0:31
+	Decoder ?? unknown - horizontal scaling
+	  Usually 0x00080514
+---------------
+2844
+      bits 0:31
+	Decoder UV horizontal scaling
+	  Normally = Reg 2854 >> 2
+---------------
+2848
+      bits 0:31
+	Decoder ?? unknown - horizontal scaling
+	  Usually 0x00100514
+---------------
+284C
+      bits 0:31
+	Decoder ?? unknown - Y plane
+	  Usually 0x00200020
+---------------
+2850
+      bits 0:31
+	Decoder ?? unknown - UV plane
+	  Usually 0x00200020
+---------------
+2854
+      bits 0:31
+	Decoder 'master' value for horizontal scaling
+---------------
+2858
+      bits 0:31
+	Decoder ?? unknown
+	  Usually 0
+---------------
+285C
+      bits 0:31
+	Decoder ?? unknown
+	  Normally = Reg 2854 >> 1
+---------------
+2860
+      bits 0:31
+	Decoder ?? unknown
+	  Usually 0
+---------------
+2864
+      bits 0:31
+	Decoder ?? unknown
+	  Normally = Reg 2854 >> 1
+---------------
+2868
+      bits 0:31
+	Decoder ?? unknown
+	  Usually 0
+
+     Most of these registers either control horizontal scaling, or appear linked
+     to it in some way. Register 2854 contains the 'master' value & the other
+     registers can be calculated from that one. You must also remember to
+     correctly set the divider in Reg 2874.
+
+     To enlarge:
+	     Reg 2854 = (source_width * 0x00200000) / destination_width
+	     Reg 2874 = No divide
+
+     To reduce from full size down to half size:
+	     Reg 2854 = (source_width/2 * 0x00200000) / destination width
+	     Reg 2874 = Divide by 2
+
+     To reduce from half size down to quarter size:
+	     Reg 2854 = (source_width/4 * 0x00200000) / destination width
+	     Reg 2874 = Divide by 4
+
+     The result is always rounded up.
+
+--------------------------------------------------------------------------------
+286C
+      bits 0:15
+	Decoder horizontal Y buffer offset
+
+      bits 15:31
+	Decoder horizontal UV buffer offset
+
+     Offset into the video image buffer. If the offset is gradually incremented,
+     the on screen image will move left & wrap around higher up on the right.
+
+--------------------------------------------------------------------------------
+2870
+      bits 0:15
+	Decoder horizontal Y output offset
+
+      bits 16:31
+	Decoder horizontal UV output offset
+
+     Offsets the actual video output. Controls output alignment of the Y & UV
+     planes. The higher the value, the greater the shift to the left. Use
+     reg 2890 to move the image right.
+
+--------------------------------------------------------------------------------
+2874
+      bits 0:1
+	Decoder horizontal Y output size divider
+	  00 = No divide
+	  01 = Divide by 2
+	  10 = Divide by 3
+
+      bits 4:5
+	Decoder horizontal UV output size divider
+	  00 = No divide
+	  01 = Divide by 2
+	  10 = Divide by 3
+
+      bit 8
+	Decoder ?? unknown
+	  0 = Normal
+	  1 = Affects video output levels
+
+      bit 16
+	Decoder ?? unknown
+	  0 = Normal
+	  1 = Disable horizontal filter
+
+--------------------------------------------------------------------------------
+2878
+      bit 0
+	?? unknown
+
+      bit 1
+	osd on/off
+	  0 = osd off
+	  1 = osd on
+
+      bit 2
+	Decoder + osd video timing
+	  0 = NTSC
+	  1 = PAL
+
+      bits 3:4
+	?? unknown
+
+      bit 5
+	Decoder + osd
+	  Swaps upper & lower fields
+
+--------------------------------------------------------------------------------
+287C
+      bits 0:10
+	Decoder & osd ?? unknown
+	  Moves entire screen horizontally. Starts at 0x005 with the screen
+	  shifted heavily to the right. Incrementing in steps of 0x004 will
+	  gradually shift the screen to the left.
+
+      bits 11:31
+	?? unknown
+
+     Normally contents are 0x00101111 (NTSC) or 0x1010111d (PAL)
+
+--------------------------------------------------------------------------------
+2880  --------    ?? unknown
+2884  --------    ?? unknown
+--------------------------------------------------------------------------------
+2888
+      bit 0
+	Decoder + osd ?? unknown
+	  0 = Normal
+	  1 = Misaligned fields (Correctable through 289C & 28A4)
+
+      bit 4
+	?? unknown
+
+      bit 8
+	?? unknown
+
+     Warning: Bad values will require a firmware reload to recover.
+		 Known to be bad are 0x000,0x011,0x100,0x111
+--------------------------------------------------------------------------------
+288C
+      bits 0:15
+	osd ?? unknown
+	  Appears to affect the osd position stability. The higher the value the
+	  more unstable it becomes. Decoder output remains stable.
+
+      bits 16:31
+	osd ?? unknown
+	  Same as bits 0:15
+
+--------------------------------------------------------------------------------
+2890
+      bits 0:11
+	Decoder output horizontal offset.
+
+     Horizontal offset moves the video image right. A small left shift is
+     possible, but it's better to use reg 2870 for that due to its greater
+     range.
+
+     NOTE: Video corruption will occur if video window is shifted off the right
+     edge. To avoid this read the notes for 2834 & 2838.
+--------------------------------------------------------------------------------
+2894
+      bits 0:23
+	Decoder output video surround colour.
+
+     Contains the colour (in yuv) used to fill the screen when the video is
+     running in a window.
+--------------------------------------------------------------------------------
+2898
+      bits 0:23
+	Decoder video window colour
+	  Contains the colour (in yuv) used to fill the video window when the
+	  video is turned off.
+
+      bit 24
+	Decoder video output
+	  0 = Video on
+	  1 = Video off
+
+      bit 28
+	Decoder plane order
+	  0 = Y,UV
+	  1 = UV,Y
+
+      bit 29
+	Decoder second plane byte order
+	  0 = Normal (UV)
+	  1 = Swapped (VU)
+
+     In normal usage, the first plane is Y & the second plane is UV. Though the
+     order of the planes can be swapped, only the byte order of the second plane
+     can be swapped. This isn't much use for the Y plane, but can be useful for
+     the UV plane.
+
+--------------------------------------------------------------------------------
+289C
+      bits 0:15
+	Decoder vertical field offset 1
+
+      bits 16:31
+	Decoder vertical field offset 2
+
+     Controls field output vertical alignment. The higher the number, the lower
+     the image on screen. Known starting values are 0x011E0017 (NTSC) &
+     0x01500017 (PAL)
+--------------------------------------------------------------------------------
+28A0
+      bits 0:15
+	Decoder & osd width in pixels
+
+      bits 16:31
+	Decoder & osd height in pixels
+
+     All output from the decoder & osd are disabled beyond this area. Decoder
+     output will simply go black outside of this region. If the osd tries to
+     exceed this area it will become corrupt.
+--------------------------------------------------------------------------------
+28A4
+      bits 0:11
+	osd left shift.
+
+     Has a range of 0x770->0x7FF. With the exception of 0, any value outside of
+     this range corrupts the osd.
+--------------------------------------------------------------------------------
+28A8
+      bits 0:15
+	osd vertical field offset 1
+
+      bits 16:31
+	osd vertical field offset 2
+
+     Controls field output vertical alignment. The higher the number, the lower
+     the image on screen. Known starting values are 0x011E0017 (NTSC) &
+     0x01500017 (PAL)
+--------------------------------------------------------------------------------
+28AC  --------    ?? unknown
+ |
+ V
+28BC  --------    ?? unknown
+--------------------------------------------------------------------------------
+28C0
+      bit 0
+	Current output field
+	  0 = first field
+	  1 = second field
+
+      bits 16:31
+	Current scanline
+	  The scanline counts from the top line of the first field
+	  through to the last line of the second field.
+--------------------------------------------------------------------------------
+28C4  --------    ?? unknown
+ |
+ V
+28F8  --------    ?? unknown
+--------------------------------------------------------------------------------
+28FC
+      bit 0
+	?? unknown
+	  0 = Normal
+	  1 = Breaks decoder & osd output
+--------------------------------------------------------------------------------
+2900
+      bits 0:31
+	Decoder vertical Y alias register 1
+---------------
+2904
+      bits 0:31
+	Decoder vertical Y alias register 2
+---------------
+2908
+      bits 0:31
+	Decoder vertical Y alias trigger
+
+     These three registers control the vertical aliasing filter for the Y plane.
+     Operation is similar to the horizontal Y filter (2804). The only real
+     difference is that there are only two registers to set before accessing
+     the trigger register (2908). As for the horizontal filter, the values are
+     taken from a lookup table in the firmware, and the procedure must be
+     repeated 16 times to fully program the filter.
+--------------------------------------------------------------------------------
+290C
+      bits 0:31
+	Decoder vertical UV alias register 1
+---------------
+2910
+      bits 0:31
+	Decoder vertical UV alias register 2
+---------------
+2914
+      bits 0:31
+	Decoder vertical UV alias trigger
+
+     These three registers control the vertical aliasing filter for the UV
+     plane. Operation is the same as the Y filter, with 2914 being the trigger.
+--------------------------------------------------------------------------------
+2918
+      bits 0:15
+	Decoder Y source height in pixels
+
+      bits 16:31
+	Decoder Y destination height in pixels
+---------------
+291C
+      bits 0:15
+	Decoder UV source height in pixels divided by 2
+
+      bits 16:31
+	Decoder UV destination height in pixels
+
+     NOTE: For both registers, the resulting image must be fully visible on
+     screen. If the image exceeds the bottom edge both the source and
+     destination size must be adjusted to reflect the visible portion. For the
+     source height, you must take into account the scaling when calculating the
+     new value.
+--------------------------------------------------------------------------------
+2920
+      bits 0:31
+	Decoder Y vertical scaling
+	  Normally = Reg 2930 >> 2
+---------------
+2924
+      bits 0:31
+	Decoder Y vertical scaling
+	  Normally = Reg 2920 + 0x514
+---------------
+2928
+      bits 0:31
+	Decoder UV vertical scaling
+	  When enlarging = Reg 2930 >> 2
+	  When reducing = Reg 2930 >> 3
+---------------
+292C
+      bits 0:31
+	Decoder UV vertical scaling
+	  Normally = Reg 2928 + 0x514
+---------------
+2930
+      bits 0:31
+	Decoder 'master' value for vertical scaling
+---------------
+2934
+      bits 0:31
+	Decoder ?? unknown - Y vertical scaling
+---------------
+2938
+      bits 0:31
+	Decoder Y vertical scaling
+	  Normally = Reg 2930
+---------------
+293C
+      bits 0:31
+	Decoder ?? unknown - Y vertical scaling
+---------------
+2940
+      bits 0:31
+	Decoder UV vertical scaling
+	  When enlarging = Reg 2930 >> 1
+	  When reducing = Reg 2930
+---------------
+2944
+      bits 0:31
+	Decoder ?? unknown - UV vertical scaling
+---------------
+2948
+      bits 0:31
+	Decoder UV vertical scaling
+	  Normally = Reg 2940
+---------------
+294C
+      bits 0:31
+	Decoder ?? unknown - UV vertical scaling
+
+     Most of these registers either control vertical scaling, or appear linked
+     to it in some way. Register 2930 contains the 'master' value & all other
+     registers can be calculated from that one. You must also remember to
+     correctly set the divider in Reg 296C
+
+     To enlarge:
+	     Reg 2930 = (source_height * 0x00200000) / destination_height
+	     Reg 296C = No divide
+
+     To reduce from full size down to half size:
+	     Reg 2930 = (source_height/2 * 0x00200000) / destination height
+	     Reg 296C = Divide by 2
+
+      To reduce from half down to quarter.
+	     Reg 2930 = (source_height/4 * 0x00200000) / destination height
+	     Reg 296C = Divide by 4
+
+--------------------------------------------------------------------------------
+2950
+      bits 0:15
+	Decoder Y line index into display buffer, first field
+
+      bits 16:31
+	Decoder Y vertical line skip, first field
+--------------------------------------------------------------------------------
+2954
+      bits 0:15
+	Decoder Y line index into display buffer, second field
+
+      bits 16:31
+	Decoder Y vertical line skip, second field
+--------------------------------------------------------------------------------
+2958
+      bits 0:15
+	Decoder UV line index into display buffer, first field
+
+      bits 16:31
+	Decoder UV vertical line skip, first field
+--------------------------------------------------------------------------------
+295C
+      bits 0:15
+	Decoder UV line index into display buffer, second field
+
+      bits 16:31
+	Decoder UV vertical line skip, second field
+--------------------------------------------------------------------------------
+2960
+      bits 0:15
+	Decoder destination height minus 1
+
+      bits 16:31
+	Decoder destination height divided by 2
+--------------------------------------------------------------------------------
+2964
+      bits 0:15
+	Decoder Y vertical offset, second field
+
+      bits 16:31
+	Decoder Y vertical offset, first field
+
+     These two registers shift the Y plane up. The higher the number, the
+     greater the shift.
+--------------------------------------------------------------------------------
+2968
+      bits 0:15
+	Decoder UV vertical offset, second field
+
+      bits 16:31
+	Decoder UV vertical offset, first field
+
+     These two registers shift the UV plane up. The higher the number, the
+     greater the shift.
+--------------------------------------------------------------------------------
+296C
+      bits 0:1
+	Decoder vertical Y output size divider
+	  00 = No divide
+	  01 = Divide by 2
+	  10 = Divide by 4
+
+      bits 8:9
+	Decoder vertical UV output size divider
+	  00 = No divide
+	  01 = Divide by 2
+	  10 = Divide by 4
+--------------------------------------------------------------------------------
+2970
+      bit 0
+	Decoder ?? unknown
+	  0 = Normal
+	  1 = Affect video output levels
+
+      bit 16
+	Decoder ?? unknown
+	  0 = Normal
+	  1 = Disable vertical filter
+
+--------------------------------------------------------------------------------
+2974  --------   ?? unknown
+ |
+ V
+29EF  --------   ?? unknown
+--------------------------------------------------------------------------------
+2A00
+      bits 0:2
+	osd colour mode
+	  001 = 16 bit (565)
+	  010 = 15 bit (555)
+	  011 = 12 bit (444)
+	  100 = 32 bit (8888)
+	  101 = 8 bit indexed
+
+      bits 4:5
+	osd display bpp
+	  01 = 8 bit
+	  10 = 16 bit
+	  11 = 32 bit
+
+      bit 8
+	osd global alpha
+	  0 = Off
+	  1 = On
+
+      bit 9
+	osd local alpha
+	  0 = Off
+	  1 = On
+
+      bit 10
+	osd colour key
+	  0 = Off
+	  1 = On
+
+      bit 11
+	osd ?? unknown
+	  Must be 1
+
+      bit 13
+	osd colour space
+	  0 = ARGB
+	  1 = AYVU
+
+      bits 16:31
+	osd ?? unknown
+	  Must be 0x001B (some kind of buffer pointer ?)
+
+     When the bits-per-pixel is set to 8, the colour mode is ignored and
+     assumed to be 8 bit indexed. For 16 & 32 bits-per-pixel the colour depth
+     is honoured, and when using a colour depth that requires fewer bytes than
+     allocated the extra bytes are used as padding. So for a 32 bpp with 8 bit
+     index colour, there are 3 padding bytes per pixel. It's also possible to
+     select 16bpp with a 32 bit colour mode. This results in the pixel width
+     being doubled, but the color key will not work as expected in this mode.
+
+     Colour key is as it suggests. You designate a colour which will become
+     completely transparent. When using 565, 555 or 444 colour modes, the
+     colour key is always 16 bits wide. The colour to key on is set in Reg 2A18.
+
+     Local alpha is a per-pixel 256 step transparency, with 0 being transparent
+     and 255 being solid. This is only available in 32 bit & 8 bit indexed
+     colour modes.
+
+     Global alpha is a 256 step transparency that applies to the entire osd,
+     with 0 being transparent & 255 being solid.
+
+     It's possible to combine colour key, local alpha & global alpha.
+--------------------------------------------------------------------------------
+2A04
+      bits 0:15
+	osd x coord for left edge
+
+      bits 16:31
+	osd y coord for top edge
+---------------
+2A08
+      bits 0:15
+	osd x coord for right edge
+
+      bits 16:31
+	osd y coord for bottom edge
+
+     For both registers, (0,0) = top left corner of the display area. These
+     registers do not control the osd size, only where it's positioned & how
+     much is visible. The visible osd area cannot exceed the right edge of the
+     display, otherwise the osd will become corrupt. See reg 2A10 for
+     setting osd width.
+--------------------------------------------------------------------------------
+2A0C
+      bits 0:31
+	osd buffer index
+
+     An index into the osd buffer. Slowly incrementing this moves the osd left,
+     wrapping around onto the right edge
+--------------------------------------------------------------------------------
+2A10
+      bits 0:11
+	osd buffer 32 bit word width
+
+     Contains the width of the osd measured in 32 bit words. This means that all
+     colour modes are restricted to a byte width which is divisible by 4.
+--------------------------------------------------------------------------------
+2A14
+      bits 0:15
+	osd height in pixels
+
+      bits 16:32
+	osd line index into buffer
+	  osd will start displaying from this line.
+--------------------------------------------------------------------------------
+2A18
+      bits 0:31
+	osd colour key
+
+     Contains the colour value which will be transparent.
+--------------------------------------------------------------------------------
+2A1C
+      bits 0:7
+	osd global alpha
+
+     Contains the global alpha value (equiv ivtvfbctl --alpha XX)
+--------------------------------------------------------------------------------
+2A20  --------    ?? unknown
+ |
+ V
+2A2C  --------    ?? unknown
+--------------------------------------------------------------------------------
+2A30
+      bits 0:7
+	osd colour to change in indexed palette
+---------------
+2A34
+      bits 0:31
+	osd colour for indexed palette
+
+     To set the new palette, first load the index of the colour to change into
+     2A30, then load the new colour into 2A34. The full palette is 256 colours,
+     so the index range is 0x00-0xFF
+--------------------------------------------------------------------------------
+2A38  --------    ?? unknown
+2A3C  --------    ?? unknown
+--------------------------------------------------------------------------------
+2A40
+      bits 0:31
+	osd ?? unknown
+
+     Affects overall brightness, wrapping around to black
+--------------------------------------------------------------------------------
+2A44
+      bits 0:31
+	osd ?? unknown
+
+     Green tint
+--------------------------------------------------------------------------------
+2A48
+      bits 0:31
+	osd ?? unknown
+
+     Red tint
+--------------------------------------------------------------------------------
+2A4C
+      bits 0:31
+	osd ?? unknown
+
+     Affects overall brightness, wrapping around to black
+--------------------------------------------------------------------------------
+2A50
+      bits 0:31
+	osd ?? unknown
+
+     Colour shift
+--------------------------------------------------------------------------------
+2A54
+      bits 0:31
+	osd ?? unknown
+
+     Colour shift
+--------------------------------------------------------------------------------
+2A58  --------    ?? unknown
+ |
+ V
+2AFC  --------    ?? unknown
+--------------------------------------------------------------------------------
+2B00
+      bit 0
+	osd filter control
+	  0 = filter off
+	  1 = filter on
+
+      bits 1:4
+	osd ?? unknown
+
+--------------------------------------------------------------------------------
+
+v0.3 - 2 February 2007 - Ian Armstrong (ian@iarmst.demon.co.uk)
+
diff --git a/Documentation/video4linux/cx2341x/fw-dma.txt b/Documentation/video4linux/cx2341x/fw-dma.txt
index 8123e26..be52b6f 100644
--- a/Documentation/video4linux/cx2341x/fw-dma.txt
+++ b/Documentation/video4linux/cx2341x/fw-dma.txt
@@ -22,6 +22,8 @@
 
 Mailbox #10 is reserved for DMA transfer information.
 
+Note: the hardware expects little-endian data ('intel format').
+
 Flow
 ====
 
@@ -64,7 +66,7 @@
 
 Each S-G array element is a struct of three 32-bit words. The first word is
 the source address, the second is the destination address. Both take up the
-entire 32 bits. The lowest 16 bits of the third word is the transfer byte
+entire 32 bits. The lowest 18 bits of the third word is the transfer byte
 count. The high-bit of the third word is the "last" flag. The last-flag tells
 the card to raise the DMA_DONE interrupt. From hard personal experience, if
 you forget to set this bit, the card will still "work" but the stream will
@@ -78,8 +80,8 @@
 
 - 32-bit Source Address
 - 32-bit Destination Address
-- 16-bit reserved (high bit is the last flag)
-- 16-bit byte count
+- 14-bit reserved (high bit is the last flag)
+- 18-bit byte count
 
 DMA Transfer Status
 ===================
@@ -87,8 +89,8 @@
 Register 0x0004 holds the DMA Transfer Status:
 
 Bit
-4   Scatter-Gather array error
-3   DMA write error
-2   DMA read error
-1   write completed
 0   read completed
+1   write completed
+2   DMA read error
+3   DMA write error
+4   Scatter-Gather array error
diff --git a/Documentation/video4linux/cx2341x/fw-encoder-api.txt b/Documentation/video4linux/cx2341x/fw-encoder-api.txt
index 15df0df..242104c 100644
--- a/Documentation/video4linux/cx2341x/fw-encoder-api.txt
+++ b/Documentation/video4linux/cx2341x/fw-encoder-api.txt
@@ -213,16 +213,6 @@
 
 -------------------------------------------------------------------------------
 
-Name 	CX2341X_ENC_SET_3_2_PULLDOWN
-Enum 	177/0xB1
-Description
-	3:2 pulldown properties
-Param[0]
-	0=enabled
-	1=disabled
-
--------------------------------------------------------------------------------
-
 Name 	CX2341X_ENC_SET_VBI_LINE
 Enum 	183/0xB7
 Description
@@ -332,9 +322,7 @@
 		'01'=JointStereo
 		'10'=Dual
 		'11'=Mono
-		Note: testing seems to indicate that Mono and possibly
-		JointStereo are not working (default to stereo).
-		Dual does work, though.
+		Note: the cx23415 cannot decode Joint Stereo properly.
 
 	  10:11 Mode Extension used in joint_stereo mode.
 		In Layer I and II they indicate which subbands are in
@@ -413,16 +401,34 @@
 Enum 	199/0xC7
 Description
 	Sets the Program Index Information.
+	The information is stored as follows:
+
+	struct info {
+		u32 length;		// Length of this frame
+		u32 offset_low;		// Offset in the file of the
+		u32 offset_high;	// start of this frame
+		u32 mask1;		// Bits 0-1 are the type mask:
+					// 1=I, 2=P, 4=B
+		u32 pts;		// The PTS of the frame
+		u32 mask2;		// Bit 0 is bit 32 of the pts.
+	};
+	u32 table_ptr;
+	struct info index[400];
+
+	The table_ptr is the encoder memory address in the table were
+	*new* entries will be written. Note that this is a ringbuffer,
+	so the table_ptr will wraparound.
 Param[0]
 	Picture Mask:
 	    0=No index capture
 	    1=I frames
 	    3=I,P frames
 	    7=I,P,B frames
+	(Seems to be ignored, it always indexes I, P and B frames)
 Param[1]
 	Elements requested (up to 400)
 Result[0]
-	Offset in SDF memory of the table.
+	Offset in the encoder memory of the start of the table.
 Result[1]
 	Number of allocated elements up to a maximum of Param[1]
 
@@ -492,12 +498,14 @@
 Enum 	203/0xCB
 Description
 	Returns information on the previous DMA transfer in conjunction with
-	bit 27 of the interrupt mask. Uses mailbox 9.
+	bit 27 or 18 of the interrupt mask. Uses mailbox 9.
 Result[0]
 	Status bits:
-	    Bit 0 set indicates transfer complete
-	    Bit 2 set indicates transfer error
-	    Bit 4 set indicates linked list error
+		0   read completed
+		1   write completed
+		2   DMA read error
+		3   DMA write error
+		4   Scatter-Gather array error
 Result[1]
 	DMA type
 Result[2]
@@ -672,7 +680,7 @@
 	the value.
 Param[0]
 	Command number:
-	 1=set initial SCR value when starting encoding.
+	 1=set initial SCR value when starting encoding (works).
 	 2=set quality mode (apparently some test setting).
 	 3=setup advanced VIM protection handling (supposedly only for the cx23416
 	   for raw YUV).
@@ -681,7 +689,11 @@
 	 4=generate artificial PTS timestamps
 	 5=USB flush mode
 	 6=something to do with the quantization matrix
-	 7=set navigation pack insertion for DVD
+	 7=set navigation pack insertion for DVD: adds 0xbf (private stream 2)
+	   packets to the MPEG. The size of these packets is 2048 bytes (including
+	   the header of 6 bytes: 0x000001bf + length). The payload is zeroed and
+	   it is up to the application to fill them in. These packets are apparently
+	   inserted every four frames.
 	 8=enable scene change detection (seems to be a failure)
 	 9=set history parameters of the video input module
 	10=set input field order of VIM
diff --git a/Documentation/video4linux/cx2341x/fw-memory.txt b/Documentation/video4linux/cx2341x/fw-memory.txt
index ef0aad3..9d736fe 100644
--- a/Documentation/video4linux/cx2341x/fw-memory.txt
+++ b/Documentation/video4linux/cx2341x/fw-memory.txt
@@ -1,6 +1,8 @@
 This document describes the cx2341x memory map and documents some of the register
 space.
 
+Note: the memory long words are little-endian ('intel format').
+
 Warning! This information was figured out from searching through the memory and
 registers, this information may not be correct and is certainly not complete, and
 was not derived from anything more than searching through the memory space with
@@ -67,7 +69,7 @@
  0x84 - first write linked list reg, for pci memory addr
  0x88 - first write linked list reg, for length of buffer in memory addr
 	(|0x80000000 or this for last link)
- 0x8c-0xcc - rest of write linked list reg, 8 sets of 3 total, DMA goes here
+ 0x8c-0xdc - rest of write linked list reg, 8 sets of 3 total, DMA goes here
 	from linked list addr in reg 0x0c, firmware must push through or
 	something.
  0xe0 - first (and only) read linked list reg, for pci memory addr
@@ -123,12 +125,8 @@
 29 Encoder VBI capture
 28 Encoder Video Input Module reset event
 27 Encoder DMA complete
-26
-25 Decoder copy protect detection event
-24 Decoder audio mode change detection event
-23
+24 Decoder audio mode change detection event (through event notification)
 22 Decoder data request
-21 Decoder I-Frame? done
 20 Decoder DMA complete
 19 Decoder VBI re-insertion
 18 Decoder DMA err (linked-list bad)
diff --git a/Documentation/video4linux/et61x251.txt b/Documentation/video4linux/et61x251.txt
index 1bdee8f..1247566 100644
--- a/Documentation/video4linux/et61x251.txt
+++ b/Documentation/video4linux/et61x251.txt
@@ -23,7 +23,7 @@
 
 1. Copyright
 ============
-Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>
+Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
 
 
 2. Disclaimer
@@ -135,8 +135,9 @@
 6. Module loading
 =================
 To use the driver, it is necessary to load the "et61x251" module into memory
-after every other module required: "videodev", "usbcore" and, depending on
-the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd".
+after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
+"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
+"uhci-hcd" or "ohci-hcd".
 
 Loading can be done as shown below:
 
diff --git a/Documentation/video4linux/sn9c102.txt b/Documentation/video4linux/sn9c102.txt
index 8cda472..2913da3 100644
--- a/Documentation/video4linux/sn9c102.txt
+++ b/Documentation/video4linux/sn9c102.txt
@@ -1,5 +1,5 @@
 
-			 SN9C10x PC Camera Controllers
+			 SN9C1xx PC Camera Controllers
 				Driver for Linux
 			 =============================
 
@@ -53,20 +53,14 @@
 
 4. Overview and features
 ========================
-This driver attempts to support the video interface of the devices mounting the
-SONiX SN9C101, SN9C102 and SN9C103 PC Camera Controllers.
-
-It's worth to note that SONiX has never collaborated with the author during the
-development of this project, despite several requests for enough detailed
-specifications of the register tables, compression engine and video data format
-of the above chips. Nevertheless, these informations are no longer necessary,
-because all the aspects related to these chips are known and have been
-described in detail in this documentation.
+This driver attempts to support the video interface of the devices assembling
+the SONiX SN9C101, SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers
+("SN9C1xx" from now on).
 
 The driver relies on the Video4Linux2 and USB core modules. It has been
 designed to run properly on SMP systems as well.
 
-The latest version of the SN9C10x driver can be found at the following URL:
+The latest version of the SN9C1xx driver can be found at the following URL:
 http://www.linux-projects.org/
 
 Some of the features of the driver are:
@@ -85,11 +79,11 @@
   high compression quality (see also "Notes for V4L2 application developers"
   and "Video frame formats" paragraphs);
 - full support for the capabilities of many of the possible image sensors that
-  can be connected to the SN9C10x bridges, including, for instance, red, green,
+  can be connected to the SN9C1xx bridges, including, for instance, red, green,
   blue and global gain adjustments and exposure (see "Supported devices"
   paragraph for details);
 - use of default color settings for sunlight conditions;
-- dynamic I/O interface for both SN9C10x and image sensor control and
+- dynamic I/O interface for both SN9C1xx and image sensor control and
   monitoring (see "Optional device control through 'sysfs'" paragraph);
 - dynamic driver control thanks to various module parameters (see "Module
   parameters" paragraph);
@@ -130,8 +124,8 @@
 	CONFIG_USB_UHCI_HCD=m
 	CONFIG_USB_OHCI_HCD=m
 
-The SN9C103 controller also provides a built-in microphone interface. It is
-supported by the USB Audio driver thanks to the ALSA API:
+The SN9C103, SN9c105 and SN9C120 controllers also provide a built-in microphone
+interface. It is supported by the USB Audio driver thanks to the ALSA API:
 
 	# Sound
 	#
@@ -155,18 +149,27 @@
 6. Module loading
 =================
 To use the driver, it is necessary to load the "sn9c102" module into memory
-after every other module required: "videodev", "usbcore" and, depending on
-the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd".
+after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
+"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
+"uhci-hcd" or "ohci-hcd".
 
 Loading can be done as shown below:
 
 	[root@localhost home]# modprobe sn9c102
 
-At this point the devices should be recognized. You can invoke "dmesg" to
-analyze kernel messages and verify that the loading process has gone well:
+Note that the module is called "sn9c102" for historic reasons, althought it
+does not just support the SN9C102.
+
+At this point all the devices supported by the driver and connected to the USB
+ports should be recognized. You can invoke "dmesg" to analyze kernel messages
+and verify that the loading process has gone well:
 
 	[user@localhost home]$ dmesg
 
+or, to isolate all the kernel messages generated by the driver:
+
+	[user@localhost home]$ dmesg | grep sn9c102
+
 
 7. Module parameters
 ====================
@@ -198,10 +201,11 @@
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
-Syntax:         <n[,...]>
-Description:    Timeout for a video frame in seconds. This parameter is
-		specific for each detected camera. This parameter can be
-		changed at runtime thanks to the /sys filesystem interface.
+Syntax:         <0|n[,...]>
+Description:    Timeout for a video frame in seconds before returning an I/O
+		error; 0 for infinity. This parameter is specific for each
+		detected camera and can be changed at runtime thanks to the
+		/sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           debug
@@ -223,20 +227,21 @@
 8. Optional device control through "sysfs" [1]
 ==========================================
 If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
-it is possible to read and write both the SN9C10x and the image sensor
+it is possible to read and write both the SN9C1xx and the image sensor
 registers by using the "sysfs" filesystem interface.
 
 Every time a supported device is recognized, a write-only file named "green" is
 created in the /sys/class/video4linux/videoX directory. You can set the green
 channel's gain by writing the desired value to it. The value may range from 0
-to 15 for SN9C101 or SN9C102 bridges, from 0 to 127 for SN9C103 bridges.
-Similarly, only for SN9C103 controllers, blue and red gain control files are
-available in the same directory, for which accepted values may range from 0 to
-127.
+to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103,
+SN9C105 and SN9C120 bridges.
+Similarly, only for the SN9C103, SN9C105 and SN9120 controllers, blue and red
+gain control files are available in the same directory, for which accepted
+values may range from 0 to 127.
 
 There are other four entries in the directory above for each registered camera:
 "reg", "val", "i2c_reg" and "i2c_val". The first two files control the
-SN9C10x bridge, while the other two control the sensor chip. "reg" and
+SN9C1xx bridge, while the other two control the sensor chip. "reg" and
 "i2c_reg" hold the values of the current register index where the following
 reading/writing operations are addressed at through "val" and "i2c_val". Their
 use is not intended for end-users. Note that "i2c_reg" and "i2c_val" will not
@@ -259,61 +264,84 @@
 	[root@localhost #] echo 0x11 > reg
 	[root@localhost #] echo 2 > val
 
-Note that the SN9C10x always returns 0 when some of its registers are read.
+Note that the SN9C1xx always returns 0 when some of its registers are read.
 To avoid race conditions, all the I/O accesses to the above files are
 serialized.
-
 The sysfs interface also provides the "frame_header" entry, which exports the
 frame header of the most recent requested and captured video frame. The header
-is always 18-bytes long and is appended to every video frame by the SN9C10x
+is always 18-bytes long and is appended to every video frame by the SN9C1xx
 controllers. As an example, this additional information can be used by the user
 application for implementing auto-exposure features via software.
 
-The following table describes the frame header:
+The following table describes the frame header exported by the SN9C101 and
+SN9C102:
 
-Byte #  Value         Description
-------  -----         -----------
-0x00    0xFF          Frame synchronisation pattern.
-0x01    0xFF          Frame synchronisation pattern.
-0x02    0x00          Frame synchronisation pattern.
-0x03    0xC4          Frame synchronisation pattern.
-0x04    0xC4          Frame synchronisation pattern.
-0x05    0x96          Frame synchronisation pattern.
-0x06    0xXX          Unknown meaning. The exact value depends on the chip;
-		      possible values are 0x00, 0x01 and 0x20.
-0x07    0xXX          Variable value, whose bits are ff00uzzc, where ff is a
-		      frame counter, u is unknown, zz is a size indicator
-		      (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
-		      "compression enabled" (1 = yes, 0 = no).
-0x08    0xXX          Brightness sum inside Auto-Exposure area (low-byte).
-0x09    0xXX          Brightness sum inside Auto-Exposure area (high-byte).
-		      For a pure white image, this number will be equal to 500
-		      times the area of the specified AE area. For images
-		      that are not pure white, the value scales down according
-		      to relative whiteness.
-0x0A    0xXX          Brightness sum outside Auto-Exposure area (low-byte).
-0x0B    0xXX          Brightness sum outside Auto-Exposure area (high-byte).
-		      For a pure white image, this number will be equal to 125
-		      times the area outside of the specified AE area. For
-		      images that are not pure white, the value scales down
-		      according to relative whiteness.
-		      according to relative whiteness.
+Byte #  Value or bits Description
+------  ------------- -----------
+0x00    0xFF          Frame synchronisation pattern
+0x01    0xFF          Frame synchronisation pattern
+0x02    0x00          Frame synchronisation pattern
+0x03    0xC4          Frame synchronisation pattern
+0x04    0xC4          Frame synchronisation pattern
+0x05    0x96          Frame synchronisation pattern
+0x06    [3:0]         Read channel gain control = (1+R_GAIN/8)
+	[7:4]         Blue channel gain control = (1+B_GAIN/8)
+0x07    [ 0 ]         Compression mode. 0=No compression, 1=Compression enabled
+	[2:1]         Maximum scale factor for compression
+	[ 3 ]         1 = USB fifo(2K bytes) is full
+	[ 4 ]         1 = Digital gain is finish
+	[ 5 ]         1 = Exposure is finish
+	[7:6]         Frame index
+0x08    [7:0]         Y sum inside Auto-Exposure area (low-byte)
+0x09    [7:0]         Y sum inside Auto-Exposure area (high-byte)
+		      where Y sum = (R/4 + 5G/16 + B/8) / 32
+0x0A    [7:0]         Y sum outside Auto-Exposure area (low-byte)
+0x0B    [7:0]         Y sum outside Auto-Exposure area (high-byte)
+		      where Y sum = (R/4 + 5G/16 + B/8) / 128
+0x0C    0xXX          Not used
+0x0D    0xXX          Not used
+0x0E    0xXX          Not used
+0x0F    0xXX          Not used
+0x10    0xXX          Not used
+0x11    0xXX          Not used
 
-The following bytes are used by the SN9C103 bridge only:
+The following table describes the frame header exported by the SN9C103:
 
-0x0C    0xXX          Unknown meaning
-0x0D    0xXX          Unknown meaning
-0x0E    0xXX          Unknown meaning
-0x0F    0xXX          Unknown meaning
-0x10    0xXX          Unknown meaning
-0x11    0xXX          Unknown meaning
+Byte #  Value or bits Description
+------  ------------- -----------
+0x00    0xFF          Frame synchronisation pattern
+0x01    0xFF          Frame synchronisation pattern
+0x02    0x00          Frame synchronisation pattern
+0x03    0xC4          Frame synchronisation pattern
+0x04    0xC4          Frame synchronisation pattern
+0x05    0x96          Frame synchronisation pattern
+0x06    [6:0]         Read channel gain control = (1/2+R_GAIN/64)
+0x07    [6:0]         Blue channel gain control = (1/2+B_GAIN/64)
+	[7:4]
+0x08    [ 0 ]         Compression mode. 0=No compression, 1=Compression enabled
+	[2:1]         Maximum scale factor for compression
+	[ 3 ]         1 = USB fifo(2K bytes) is full
+	[ 4 ]         1 = Digital gain is finish
+	[ 5 ]         1 = Exposure is finish
+	[7:6]         Frame index
+0x09    [7:0]         Y sum inside Auto-Exposure area (low-byte)
+0x0A    [7:0]         Y sum inside Auto-Exposure area (high-byte)
+		      where Y sum = (R/4 + 5G/16 + B/8) / 32
+0x0B    [7:0]         Y sum outside Auto-Exposure area (low-byte)
+0x0C    [7:0]         Y sum outside Auto-Exposure area (high-byte)
+		      where Y sum = (R/4 + 5G/16 + B/8) / 128
+0x0D    [1:0]         Audio frame number
+	[ 2 ]         1 = Audio is recording
+0x0E    [7:0]         Audio summation (low-byte)
+0x0F    [7:0]         Audio summation (high-byte)
+0x10    [7:0]         Audio sample count
+0x11    [7:0]         Audio peak data in audio frame
 
 The AE area (sx, sy, ex, ey) in the active window can be set by programming the
-registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C10x controllers, where one unit
+registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C1xx controllers, where one unit
 corresponds to 32 pixels.
 
-[1] Part of the meaning of the frame header has been documented by Bertrik
-    Sikken.
+[1] The frame headers exported by the SN9C105 and SN9C120 are not described.
 
 
 9. Supported devices
@@ -323,15 +351,19 @@
 
 From the point of view of a driver, what unambiguously identify a device are
 its vendor and product USB identifiers. Below is a list of known identifiers of
-devices mounting the SN9C10x PC camera controllers:
+devices assembling the SN9C1xx PC camera controllers:
 
 Vendor ID  Product ID
 ---------  ----------
+0x0471     0x0327
+0x0471     0x0328
 0x0c45     0x6001
 0x0c45     0x6005
 0x0c45     0x6007
 0x0c45     0x6009
 0x0c45     0x600d
+0x0c45     0x6011
+0x0c45     0x6019
 0x0c45     0x6024
 0x0c45     0x6025
 0x0c45     0x6028
@@ -342,6 +374,7 @@
 0x0c45     0x602d
 0x0c45     0x602e
 0x0c45     0x6030
+0x0c45     0x603f
 0x0c45     0x6080
 0x0c45     0x6082
 0x0c45     0x6083
@@ -368,24 +401,40 @@
 0x0c45     0x60bb
 0x0c45     0x60bc
 0x0c45     0x60be
+0x0c45     0x60c0
+0x0c45     0x60c8
+0x0c45     0x60cc
+0x0c45     0x60ea
+0x0c45     0x60ec
+0x0c45     0x60fa
+0x0c45     0x60fb
+0x0c45     0x60fc
+0x0c45     0x60fe
+0x0c45     0x6130
+0x0c45     0x613a
+0x0c45     0x613b
+0x0c45     0x613c
+0x0c45     0x613e
 
 The list above does not imply that all those devices work with this driver: up
-until now only the ones that mount the following image sensors are supported;
-kernel messages will always tell you whether this is the case:
+until now only the ones that assemble the following image sensors are
+supported; kernel messages will always tell you whether this is the case (see
+"Module loading" paragraph):
 
 Model       Manufacturer
 -----       ------------
 HV7131D     Hynix Semiconductor, Inc.
 MI-0343     Micron Technology, Inc.
 OV7630      OmniVision Technologies, Inc.
+OV7660      OmniVision Technologies, Inc.
 PAS106B     PixArt Imaging, Inc.
 PAS202BCA   PixArt Imaging, Inc.
 PAS202BCB   PixArt Imaging, Inc.
 TAS5110C1B  Taiwan Advanced Sensor Corporation
 TAS5130D1B  Taiwan Advanced Sensor Corporation
 
-All the available control settings of each image sensor are supported through
-the V4L2 interface.
+Some of the available control settings of each image sensor are supported
+through the V4L2 interface.
 
 Donations of new models for further testing and support would be much
 appreciated. Non-available hardware will not be supported by the author of this
@@ -429,12 +478,15 @@
 
 11. Video frame formats [1]
 =======================
-The SN9C10x PC Camera Controllers can send images in two possible video
-formats over the USB: either native "Sequential RGB Bayer" or Huffman
-compressed. The latter is used to achieve high frame rates. The current video
-format may be selected or queried from the user application by calling the
-VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2 API
-specifications.
+The SN9C1xx PC Camera Controllers can send images in two possible video
+formats over the USB: either native "Sequential RGB Bayer" or compressed.
+The compression is used to achieve high frame rates. With regard to the
+SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding
+algorithm described below, while the SN9C105 and SN9C120 the compression is
+based on the JPEG standard.
+The current video format may be selected or queried from the user application
+by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2
+API specifications.
 
 The name "Sequential Bayer" indicates the organization of the red, green and
 blue pixels in one video frame. Each pixel is associated with a 8-bit long
@@ -447,14 +499,14 @@
 ...                                  G[n(m-2)]      R[n(m-1)]
 
 The above matrix also represents the sequential or progressive read-out mode of
-the (n, m) Bayer color filter array used in many CCD/CMOS image sensors.
+the (n, m) Bayer color filter array used in many CCD or CMOS image sensors.
 
-One compressed video frame consists of a bitstream that encodes for every R, G,
-or B pixel the difference between the value of the pixel itself and some
-reference pixel value. Pixels are organised in the Bayer pattern and the Bayer
-sub-pixels are tracked individually and alternatingly. For example, in the
-first line values for the B and G1 pixels are alternatingly encoded, while in
-the second line values for the G2 and R pixels are alternatingly encoded.
+The Huffman compressed video frame consists of a bitstream that encodes for
+every R, G, or B pixel the difference between the value of the pixel itself and
+some reference pixel value. Pixels are organised in the Bayer pattern and the
+Bayer sub-pixels are tracked individually and alternatingly. For example, in
+the first line values for the B and G1 pixels are alternatingly encoded, while
+in the second line values for the G2 and R pixels are alternatingly encoded.
 
 The pixel reference value is calculated as follows:
 - the 4 top left pixels are encoded in raw uncompressed 8-bit format;
@@ -470,8 +522,9 @@
   decoding.
 
 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).
+in the SN9C101, SN9C102 and SN9C103 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)
@@ -506,13 +559,18 @@
 - Philippe Coval for having helped testing the PAS202BCA image sensor;
 - Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
   donation of a webcam;
+- Dennis Heitmann for the donation of a webcam;
 - Jon Hollstrom for the donation of a webcam;
+- Nick McGill for the donation of a webcam;
 - Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB
   image sensor;
 - Stefano Mozzi, who donated 45 EU;
 - Andrew Pearce for the donation of a webcam;
+- John Pullan for the donation of a webcam;
 - Bertrik Sikken, who reverse-engineered and documented the Huffman compression
-  algorithm used in the SN9C10x controllers and implemented the first decoder;
+  algorithm used in the SN9C101, SN9C102 and SN9C103 controllers and
+  implemented the first decoder;
 - Mizuno Takafumi for the donation of a webcam;
 - an "anonymous" donator (who didn't want his name to be revealed) for the
   donation of a webcam.
+- an anonymous donator for the donation of four webcams.
diff --git a/Documentation/video4linux/zc0301.txt b/Documentation/video4linux/zc0301.txt
index f406f5e..befdfdacd 100644
--- a/Documentation/video4linux/zc0301.txt
+++ b/Documentation/video4linux/zc0301.txt
@@ -23,7 +23,7 @@
 
 1. Copyright
 ============
-Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>
+Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
 
 
 2. Disclaimer
@@ -125,8 +125,9 @@
 6. Module loading
 =================
 To use the driver, it is necessary to load the "zc0301" module into memory
-after every other module required: "videodev", "usbcore" and, depending on
-the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd".
+after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
+"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
+"uhci-hcd" or "ohci-hcd".
 
 Loading can be done as shown below:
 
@@ -211,12 +212,11 @@
 0x041e     0x4036
 0x041e     0x403a
 0x0458     0x7007
-0x0458     0x700C
+0x0458     0x700c
 0x0458     0x700f
 0x046d     0x08ae
 0x055f     0xd003
 0x055f     0xd004
-0x046d     0x08ae
 0x0ac8     0x0301
 0x0ac8     0x301b
 0x0ac8     0x303b
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index 5c86ed6..625a21d 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -180,40 +180,81 @@
   pci=lastbus=NUMBER	       Scan upto NUMBER busses, no matter what the mptable says.
   pci=noacpi		Don't use ACPI to set up PCI interrupt routing.
 
-IOMMU
+IOMMU (input/output memory management unit)
 
- iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
-         [,forcesac][,fullflush][,nomerge][,noaperture][,calgary]
-   size  set size of iommu (in bytes)
-   noagp don't initialize the AGP driver and use full aperture.
-   off   don't use the IOMMU
-   leak  turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on)
-   memaper[=order] allocate an own aperture over RAM with size 32MB^order.
-   noforce don't force IOMMU usage. Default.
-   force  Force IOMMU.
-   merge  Do SG merging. Implies force (experimental)
-   nomerge Don't do SG merging.
-   forcesac For SAC mode for masks <40bits  (experimental)
-   fullflush Flush IOMMU on each allocation (default)
-   nofullflush Don't use IOMMU fullflush
-   allowed  overwrite iommu off workarounds for specific chipsets.
-   soft	 Use software bounce buffering (default for Intel machines)
-   noaperture Don't touch the aperture for AGP.
-   allowdac Allow DMA >4GB
-	    When off all DMA over >4GB is forced through an IOMMU or bounce
-	    buffering.
-   nodac    Forbid DMA >4GB
-   panic    Always panic when IOMMU overflows
-   calgary  Use the Calgary IOMMU if it is available
+ Currently four x86-64 PCI-DMA mapping implementations exist:
 
-  swiotlb=pages[,force]
+   1. <arch/x86_64/kernel/pci-nommu.c>: use no hardware/software IOMMU at all
+      (e.g. because you have < 3 GB memory).
+      Kernel boot message: "PCI-DMA: Disabling IOMMU"
 
-  pages  Prereserve that many 128K pages for the software IO bounce buffering.
-  force  Force all IO through the software TLB.
+   2. <arch/x86_64/kernel/pci-gart.c>: AMD GART based hardware IOMMU.
+      Kernel boot message: "PCI-DMA: using GART IOMMU"
 
-  calgary=[64k,128k,256k,512k,1M,2M,4M,8M]
-  calgary=[translate_empty_slots]
-  calgary=[disable=<PCI bus number>]
+   3. <arch/x86_64/kernel/pci-swiotlb.c> : Software IOMMU implementation. Used
+      e.g. if there is no hardware IOMMU in the system and it is need because
+      you have >3GB memory or told the kernel to us it (iommu=soft))
+      Kernel boot message: "PCI-DMA: Using software bounce buffering
+      for IO (SWIOTLB)"
+
+   4. <arch/x86_64/pci-calgary.c> : IBM Calgary hardware IOMMU. Used in IBM
+      pSeries and xSeries servers. This hardware IOMMU supports DMA address
+      mapping with memory protection, etc.
+      Kernel boot message: "PCI-DMA: Using Calgary IOMMU"
+
+ iommu=[<size>][,noagp][,off][,force][,noforce][,leak[=<nr_of_leak_pages>]
+	[,memaper[=<order>]][,merge][,forcesac][,fullflush][,nomerge]
+	[,noaperture][,calgary]
+
+  General iommu options:
+    off                Don't initialize and use any kind of IOMMU.
+    noforce            Don't force hardware IOMMU usage when it is not needed.
+                       (default).
+    force              Force the use of the hardware IOMMU even when it is
+                       not actually needed (e.g. because < 3 GB memory).
+    soft               Use software bounce buffering (SWIOTLB) (default for
+                       Intel machines). This can be used to prevent the usage
+                       of an available hardware IOMMU.
+
+  iommu options only relevant to the AMD GART hardware IOMMU:
+    <size>             Set the size of the remapping area in bytes.
+    allowed            Overwrite iommu off workarounds for specific chipsets.
+    fullflush          Flush IOMMU on each allocation (default).
+    nofullflush        Don't use IOMMU fullflush.
+    leak               Turn on simple iommu leak tracing (only when
+                       CONFIG_IOMMU_LEAK is on). Default number of leak pages
+                       is 20.
+    memaper[=<order>]  Allocate an own aperture over RAM with size 32MB<<order.
+                       (default: order=1, i.e. 64MB)
+    merge              Do scatter-gather (SG) merging. Implies "force"
+                       (experimental).
+    nomerge            Don't do scatter-gather (SG) merging.
+    noaperture         Ask the IOMMU not to touch the aperture for AGP.
+    forcesac           Force single-address cycle (SAC) mode for masks <40bits
+                       (experimental).
+    noagp              Don't initialize the AGP driver and use full aperture.
+    allowdac           Allow double-address cycle (DAC) mode, i.e. DMA >4GB.
+                       DAC is used with 32-bit PCI to push a 64-bit address in
+                       two cycles. When off all DMA over >4GB is forced through
+                       an IOMMU or software bounce buffering.
+    nodac              Forbid DAC mode, i.e. DMA >4GB.
+    panic              Always panic when IOMMU overflows.
+    calgary            Use the Calgary IOMMU if it is available
+
+  iommu options only relevant to the software bounce buffering (SWIOTLB) IOMMU
+  implementation:
+    swiotlb=<pages>[,force]
+    <pages>            Prereserve that many 128K pages for the software IO
+                       bounce buffering.
+    force              Force all IO through the software TLB.
+
+  Settings for the IBM Calgary hardware IOMMU currently found in IBM
+  pSeries and xSeries machines:
+
+    calgary=[64k,128k,256k,512k,1M,2M,4M,8M]
+    calgary=[translate_empty_slots]
+    calgary=[disable=<PCI bus number>]
+    panic              Always panic when IOMMU overflows
 
     64k,...,8M - Set the size of each PCI slot's translation table
     when using the Calgary IOMMU. This is the size of the translation
@@ -234,14 +275,14 @@
 
 Debugging
 
-  oops=panic Always panic on oopses. Default is to just kill the process,
-	     but there is a small probability of deadlocking the machine.
-	     This will also cause panics on machine check exceptions.
-	     Useful together with panic=30 to trigger a reboot.
+  oops=panic	Always panic on oopses. Default is to just kill the process,
+		but there is a small probability of deadlocking the machine.
+		This will also cause panics on machine check exceptions.
+		Useful together with panic=30 to trigger a reboot.
 
-  kstack=N   Print that many words from the kernel stack in oops dumps.
+  kstack=N	Print N words from the kernel stack in oops dumps.
 
-  pagefaulttrace Dump all page faults. Only useful for extreme debugging
+  pagefaulttrace  Dump all page faults. Only useful for extreme debugging
 		and will create a lot of output.
 
   call_trace=[old|both|newfallback|new]
@@ -251,15 +292,8 @@
 		newfallback: use new unwinder but fall back to old if it gets
 			stuck (default)
 
-  call_trace=[old|both|newfallback|new]
-		old: use old inexact backtracer
-		new: use new exact dwarf2 unwinder
- 		both: print entries from both
-		newfallback: use new unwinder but fall back to old if it gets
-			stuck (default)
-
-Misc
+Miscellaneous
 
   noreplacement  Don't replace instructions with more appropriate ones
 		 for the CPU. This may be useful on asymmetric MP systems
-		 where some CPU have less capabilities than the others.
+		 where some CPUs have less capabilities than others.
diff --git a/Documentation/x86_64/cpu-hotplug-spec b/Documentation/x86_64/cpu-hotplug-spec
index 5c0fa34..3c23e05 100644
--- a/Documentation/x86_64/cpu-hotplug-spec
+++ b/Documentation/x86_64/cpu-hotplug-spec
@@ -2,7 +2,7 @@
 ---------------------------------------------------
 
 Linux/x86-64 supports CPU hotplug now. For various reasons Linux wants to
-know in advance boot time the maximum number of CPUs that could be plugged
+know in advance of boot time the maximum number of CPUs that could be plugged
 into the system. ACPI 3.0 currently has no official way to supply
 this information from the firmware to the operating system.
 
diff --git a/Documentation/x86_64/kernel-stacks b/Documentation/x86_64/kernel-stacks
index bddfddd..5ad65d5 100644
--- a/Documentation/x86_64/kernel-stacks
+++ b/Documentation/x86_64/kernel-stacks
@@ -9,9 +9,9 @@
 except for the thread_info structure at the bottom.
 
 In addition to the per thread stacks, there are specialized stacks
-associated with each cpu.  These stacks are only used while the kernel
-is in control on that cpu, when a cpu returns to user space the
-specialized stacks contain no useful data.  The main cpu stacks is
+associated with each CPU.  These stacks are only used while the kernel
+is in control on that CPU; when a CPU returns to user space the
+specialized stacks contain no useful data.  The main CPU stacks are:
 
 * Interrupt stack.  IRQSTACKSIZE
 
@@ -32,17 +32,17 @@
 to automatically switch to a new stack for designated events such as
 double fault or NMI, which makes it easier to handle these unusual
 events on x86_64.  This feature is called the Interrupt Stack Table
-(IST).  There can be up to 7 IST entries per cpu. The IST code is an
-index into the Task State Segment (TSS), the IST entries in the TSS
-point to dedicated stacks, each stack can be a different size.
+(IST).  There can be up to 7 IST entries per CPU. The IST code is an
+index into the Task State Segment (TSS). The IST entries in the TSS
+point to dedicated stacks; each stack can be a different size.
 
-An IST is selected by an non-zero value in the IST field of an
+An IST is selected by a non-zero value in the IST field of an
 interrupt-gate descriptor.  When an interrupt occurs and the hardware
 loads such a descriptor, the hardware automatically sets the new stack
 pointer based on the IST value, then invokes the interrupt handler.  If
 software wants to allow nested IST interrupts then the handler must
 adjust the IST values on entry to and exit from the interrupt handler.
-(this is occasionally done, e.g. for debug exceptions)
+(This is occasionally done, e.g. for debug exceptions.)
 
 Events with different IST codes (i.e. with different stacks) can be
 nested.  For example, a debug interrupt can safely be interrupted by an
@@ -58,17 +58,17 @@
 
   Used for interrupt 12 - Stack Fault Exception (#SS).
 
-  This allows to recover from invalid stack segments. Rarely
+  This allows the CPU to recover from invalid stack segments. Rarely
   happens.
 
 * DOUBLEFAULT_STACK.  EXCEPTION_STKSZ (PAGE_SIZE).
 
   Used for interrupt 8 - Double Fault Exception (#DF).
 
-  Invoked when handling a exception causes another exception. Happens
-  when the kernel is very confused (e.g. kernel stack pointer corrupt)
-  Using a separate stack allows to recover from it well enough in many
-  cases to still output an oops.
+  Invoked when handling one exception causes another exception. Happens
+  when the kernel is very confused (e.g. kernel stack pointer corrupt).
+  Using a separate stack allows the kernel to recover from it well enough
+  in many cases to still output an oops.
 
 * NMI_STACK.  EXCEPTION_STKSZ (PAGE_SIZE).
 
diff --git a/Documentation/x86_64/machinecheck b/Documentation/x86_64/machinecheck
new file mode 100644
index 0000000..068a6d9
--- /dev/null
+++ b/Documentation/x86_64/machinecheck
@@ -0,0 +1,70 @@
+
+Configurable sysfs parameters for the x86-64 machine check code.
+
+Machine checks report internal hardware error conditions detected
+by the CPU. Uncorrected errors typically cause a machine check
+(often with panic), corrected ones cause a machine check log entry.
+
+Machine checks are organized in banks (normally associated with
+a hardware subsystem) and subevents in a bank. The exact meaning
+of the banks and subevent is CPU specific.
+
+mcelog knows how to decode them.
+
+When you see the "Machine check errors logged" message in the system
+log then mcelog should run to collect and decode machine check entries
+from /dev/mcelog. Normally mcelog should be run regularly from a cronjob.
+
+Each CPU has a directory in /sys/devices/system/machinecheck/machinecheckN
+(N = CPU number)
+
+The directory contains some configurable entries:
+
+Entries:
+
+bankNctl
+(N bank number)
+	64bit Hex bitmask enabling/disabling specific subevents for bank N
+	When a bit in the bitmask is zero then the respective
+	subevent will not be reported.
+	By default all events are enabled.
+	Note that BIOS maintain another mask to disable specific events
+	per bank.  This is not visible here
+
+The following entries appear for each CPU, but they are truly shared
+between all CPUs.
+
+check_interval
+	How often to poll for corrected machine check errors, in seconds
+	(Note output is hexademical). Default 5 minutes.
+
+tolerant
+	Tolerance level. When a machine check exception occurs for a non
+	corrected machine check the kernel can take different actions.
+	Since machine check exceptions can happen any time it is sometimes
+	risky for the kernel to kill a process because it defies
+	normal kernel locking rules. The tolerance level configures
+	how hard the kernel tries to recover even at some risk of deadlock.
+
+	0: always panic,
+	1: panic if deadlock possible,
+	2: try to avoid panic,
+   	3: never panic or exit (for testing only)
+
+	Default: 1
+
+	Note this only makes a difference if the CPU allows recovery
+	from a machine check exception. Current x86 CPUs generally do not.
+
+trigger
+	Program to run when a machine check event is detected.
+	This is an alternative to running mcelog regularly from cron
+	and allows to detect events faster.
+
+TBD document entries for AMD threshold interrupt configuration
+
+For more details about the x86 machine check architecture
+see the Intel and AMD architecture manuals from their developer websites.
+
+For more details about the architecture see
+see http://one.firstfloor.org/~andi/mce.pdf
diff --git a/Documentation/x86_64/mm.txt b/Documentation/x86_64/mm.txt
index 133561b..f42798e 100644
--- a/Documentation/x86_64/mm.txt
+++ b/Documentation/x86_64/mm.txt
@@ -3,26 +3,26 @@
 
 Virtual memory map with 4 level page tables:
 
-0000000000000000 - 00007fffffffffff (=47bits) user space, different per mm
+0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
 hole caused by [48:63] sign extension
-ffff800000000000 - ffff80ffffffffff (=40bits) guard hole
-ffff810000000000 - ffffc0ffffffffff (=46bits) direct mapping of all phys. memory
-ffffc10000000000 - ffffc1ffffffffff (=40bits) hole
-ffffc20000000000 - ffffe1ffffffffff (=45bits) vmalloc/ioremap space
+ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
+ffff810000000000 - ffffc0ffffffffff (=46 bits) direct mapping of all phys. memory
+ffffc10000000000 - ffffc1ffffffffff (=40 bits) hole
+ffffc20000000000 - ffffe1ffffffffff (=45 bits) vmalloc/ioremap space
 ... unused hole ...
-ffffffff80000000 - ffffffff82800000 (=40MB)   kernel text mapping, from phys 0
+ffffffff80000000 - ffffffff82800000 (=40 MB)   kernel text mapping, from phys 0
 ... unused hole ...
-ffffffff88000000 - fffffffffff00000 (=1919MB) module mapping space
+ffffffff88000000 - fffffffffff00000 (=1919 MB) module mapping space
 
-The direct mapping covers all memory in the system upto the highest
+The direct mapping covers all memory in the system up to the highest
 memory address (this means in some cases it can also include PCI memory
-holes)
+holes).
 
 vmalloc space is lazily synchronized into the different PML4 pages of
 the processes using the page fault handler, with init_level4_pgt as
 reference.
 
-Current X86-64 implementations only support 40 bit of address space,
-but we support upto 46bits. This expands into MBZ space in the page tables.
+Current X86-64 implementations only support 40 bits of address space,
+but we support up to 46 bits. This expands into MBZ space in the page tables.
 
 -Andi Kleen, Jul 2004
diff --git a/MAINTAINERS b/MAINTAINERS
index fe35f3a..a9c13196 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -247,6 +247,13 @@
 W:	http://acpi.sourceforge.net/
 S:	Supported
 
+ACPI VIDEO DRIVER
+P:	Luming Yu
+M:	luming.yu@intel.com
+L:	linux-acpi@vger.kernel.org
+W:	http://acpi.sourceforge.net/
+S:	Supported
+
 AD1816 SOUND DRIVER
 P:	Thorsten Knabe
 M:	Thorsten Knabe <linux@thorsten-knabe.de>
@@ -268,6 +275,12 @@
 L:	lm-sensors@lm-sensors.org
 S:	Maintained
 
+ADM1029 HARDWARE MONITOR DRIVER
+P:	Corentin Labbe
+M:	corentin.labbe@geomatys.fr
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+
 ADT746X FAN DRIVER
 P:	Colin Leroy
 M:	colin@colino.net
@@ -620,6 +633,11 @@
 M:	hskinnemoen@atmel.com
 S:	Supported
 
+ATMEL SPI DRIVER
+P:	Haavard Skinnemoen
+M:	hskinnemoen@atmel.com
+S:	Supported
+
 ATMEL WIRELESS DRIVER
 P:	Simon Kelley
 M:	simon@thekelleys.org.uk
@@ -635,6 +653,12 @@
 T:	git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
 S:	Maintained
 
+AUXILIARY DISPLAY DRIVERS
+P:	Miguel Ojeda Sandonis
+M:	maxextreme@gmail.com
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
 AVR32 ARCHITECTURE
 P:	Haavard Skinnemoen
 M:	hskinnemoen@atmel.com
@@ -655,6 +679,11 @@
 W:	http://www.linux-ax25.org/
 S:	Maintained
 
+BACKLIGHT CLASS/SUBSYSTEM
+P:	Richard Purdie
+M:	rpurdie@rpsys.net
+S:	Maintained
+
 BAYCOM/HDLCDRV DRIVERS FOR AX.25
 P:	Thomas Sailer
 M:	t.sailer@alumni.ethz.ch
@@ -836,6 +865,18 @@
 L:	discuss@x86-64.org
 S:	Maintained
 
+CFAG12864B LCD DRIVER
+P:	Miguel Ojeda Sandonis
+M:	maxextreme@gmail.com
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
+CFAG12864BFB LCD FRAMEBUFFER DRIVER
+P:	Miguel Ojeda Sandonis
+M:	maxextreme@gmail.com
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
 COMMON INTERNET FILE SYSTEM (CIFS)
 P:	Steve French
 M:	sfrench@samba.org
@@ -984,14 +1025,12 @@
 S:	Maintained
 
 CYCLADES ASYNC MUX DRIVER
-M:	async@cyclades.com
 W:	http://www.cyclades.com/
-S:	Supported
+S:	Orphan
 
 CYCLADES PC300 DRIVER
-M:	pc300@cyclades.com
 W:	http://www.cyclades.com/
-S:	Supported
+S:	Orphan
 
 DAMA SLAVE for AX.25
 P:	Joerg Reuter
@@ -1114,7 +1153,7 @@
 DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
 P:	Tobias Ringstrom
 M:	tori@unhappy.mine.nu
-L:	linux-kernel@vger.kernel.org
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 DOCBOOK FOR DOCUMENTATION
@@ -1267,7 +1306,7 @@
 ETHERNET BRIDGE
 P:	Stephen Hemminger
 M:	shemminger@linux-foundation.org
-L:	bridge@osdl.org
+L:	bridge@lists.osdl.org
 W:	http://bridge.sourceforge.net/
 S:	Maintained
 
@@ -1282,13 +1321,13 @@
 
 EXT3 FILE SYSTEM
 P:	Stephen Tweedie, Andrew Morton
-M:	sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
+M:	sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com
 L:	linux-ext4@vger.kernel.org
 S:	Maintained
 
 EXT4 FILE SYSTEM
 P:	Stephen Tweedie, Andrew Morton
-M:	sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
+M:	sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com
 L:	linux-ext4@vger.kernel.org
 S:	Maintained
 
@@ -1885,7 +1924,7 @@
 
 JOURNALLING LAYER FOR BLOCK DEVICES (JBD)
 P:	Stephen Tweedie, Andrew Morton
-M:	sct@redhat.com, akpm@osdl.org
+M:	sct@redhat.com, akpm@linux-foundation.org
 L:	linux-ext4@vger.kernel.org
 S:	Maintained
 
@@ -1956,7 +1995,7 @@
 M:	ebiederm@xmission.com
 W:	http://www.xmission.com/~ebiederm/files/kexec/
 L:	linux-kernel@vger.kernel.org
-L:	fastboot@osdl.org
+L:	fastboot@lists.osdl.org
 S:	Maintained
 
 KPROBES
@@ -1971,6 +2010,12 @@
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
+KS0108 LCD CONTROLLER DRIVER
+P:	Miguel Ojeda Sandonis
+M:	maxextreme@gmail.com
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
 LAPB module
 L:	linux-x25@vger.kernel.org
 S:	Orphan
@@ -2288,7 +2333,7 @@
 NETEM NETWORK EMULATOR
 P:	Stephen Hemminger
 M:	shemminger@linux-foundation.org
-L:	netem@osdl.org
+L:	netem@lists.osdl.org
 S:	Maintained
 
 NETFILTER/IPTABLES/IPCHAINS
@@ -2327,7 +2372,7 @@
 
 NETWORK DEVICE DRIVERS
 P:	Andrew Morton
-M:	akpm@osdl.org
+M:	akpm@linux-foundation.org
 P:	Jeff Garzik
 M:	jgarzik@pobox.com
 L:	netdev@vger.kernel.org
@@ -2361,7 +2406,7 @@
 NETWORKING [WIRELESS]
 P:	John W. Linville
 M:	linville@tuxdriver.com
-L:	netdev@vger.kernel.org
+L:	linux-wireless@vger.kernel.org
 T:	git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
 S:	Maintained
 
@@ -2501,6 +2546,12 @@
 L:	netdev@vger.kernel.org
 S:	Maintained
 
+PA SEMI SMBUS DRIVER
+P:	Olof Johansson
+M:	olof@lixom.net
+L:	i2c@lm-sensors.org
+S:	Maintained
+
 PARALLEL PORT SUPPORT
 P:	Phil Blundell
 M:	philb@gnu.org
@@ -2590,8 +2641,8 @@
 S:	Maintained
 
 PCNET32 NETWORK DRIVER
-P:	Thomas Bogendörfer
-M:	tsbogend@alpha.franken.de
+P:	Don Fry
+M:	pcnet32@verizon.net
 L:	netdev@vger.kernel.org
 S:	Maintained
 
@@ -2697,7 +2748,7 @@
 PVRUSB2 VIDEO4LINUX DRIVER
 P:	Mike Isely
 M:	isely@pobox.com
-L:	pvrusb2@isely.net
+L:	pvrusb2@isely.net	(subscribers-only)
 L:	video4linux-list@redhat.com
 W:	http://www.isely.net/pvrusb2/
 S:	Maintained
@@ -3016,7 +3067,7 @@
 SOFTWARE SUSPEND:
 P:	Pavel Machek
 M:	pavel@suse.cz
-L:	linux-pm@osdl.org
+L:	linux-pm@lists.osdl.org
 S:	Maintained
 
 SONIC NETWORK DRIVER
@@ -3028,6 +3079,8 @@
 SONY VAIO CONTROL DEVICE DRIVER
 P:	Stelian Pop
 M:	stelian@popies.net
+P:	Mattia Dongili
+M:	malattia@linux.it
 W:	http://popies.net/sonypi/
 S:	Maintained
 
@@ -3037,6 +3090,12 @@
 L:	alsa-devel@alsa-project.org
 S:	Maintained
 
+SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
+P:	Liam Girdwood
+M:	liam.girdwood@wolfsonmicro.com
+L:	alsa-devel@alsa-project.org
+S:	Supported
+
 SPI SUBSYSTEM
 P:	David Brownell
 M:	dbrownell@users.sourceforge.net
@@ -3287,6 +3346,11 @@
 W:	http://vtun.sourceforge.net/tun
 S:	Maintained
 
+TURBOCHANNEL SUBSYSTEM
+P:	Maciej W. Rozycki
+M:	macro@linux-mips.org
+S:	Maintained
+
 U14-34F SCSI DRIVER
 P:	Dario Ballabio
 M:	ballabio_dario@emc.com
@@ -3328,6 +3392,13 @@
 S:	Maintained
 W:	http://www.kroah.com/linux-usb/
 
+USB DAVICOM DM9601 DRIVER
+P:	Peter Korsgaard
+M:	jacmet@sunsite.dk
+L:	linux-usb-devel@lists.sourceforge.net
+W:	http://www.linux-usb.org/usbnet
+S:	Maintained
+
 USB EHCI DRIVER
 P:	David Brownell
 M:	dbrownell@users.sourceforge.net
@@ -3735,6 +3806,7 @@
 M:	ak@suse.de
 L:	discuss@x86-64.org
 W:	http://www.x86-64.org
+T:	quilt ftp://ftp.firstfloor.org/pub/ak/x86_64/quilt-current
 S:	Maintained
 
 YAM DRIVER FOR AX.25
diff --git a/Makefile b/Makefile
index cdeda68..30b66e2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 20
-EXTRAVERSION =
+SUBLEVEL = 21
+EXTRAVERSION = -rc1
 NAME = Homicidal Dwarf Hamster
 
 # *DOCUMENTATION*
@@ -789,7 +789,7 @@
 
 pattern = ".*/localversion[^~]*"
 string  = $(shell cat /dev/null \
-	   `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort`)
+	   `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort -u`)
 
 localver = $(subst $(space),, $(string) \
 			      $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
@@ -825,9 +825,6 @@
 # Listed in dependency order
 PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
 
-# prepare-all is deprecated, use prepare as valid replacement
-PHONY += prepare-all
-
 # prepare3 is used to check if we are building in a separate output directory,
 # and if so do:
 # 1) Check that make has not been executed in the kernel src $(srctree)
@@ -860,7 +857,7 @@
 	$(Q)$(MAKE) $(build)=.
 
 # All the preparing..
-prepare prepare-all: prepare0
+prepare: prepare0
 
 # Leave this as default for preprocessing vmlinux.lds.S, which is now
 # done in arch/$(ARCH)/kernel/Makefile
@@ -931,6 +928,12 @@
 	$(Q)$(MAKE) $(build)=scripts scripts/unifdef
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst obj=include
 
+PHONY += headers_check_all
+headers_check_all: headers_install_all
+	$(Q)for arch in $(HDRARCHES); do \
+	 $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch HDRCHECK=1 ;\
+	 done
+
 PHONY += headers_check
 headers_check: headers_install
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst obj=include HDRCHECK=1
diff --git a/README b/README
index 46a66c6..159912c 100644
--- a/README
+++ b/README
@@ -24,7 +24,7 @@
   today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and
   UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, Cell,
   IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS,
-  Cris, Xtensa, AVR32 and Renesas M32R architectures.
+  Xtensa, AVR32 and Renesas M32R architectures.
 
   Linux is easily portable to most general-purpose 32- or 64-bit architectures
   as long as they have a paged memory management unit (PMMU) and a port of the
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 84caf50..770f717 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -41,6 +41,10 @@
 	bool
 	default y
 
+config ZONE_DMA
+	bool
+	default y
+
 config GENERIC_ISA_DMA
 	bool
 	default y
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 1aea7c7..d352c2b 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -122,7 +122,7 @@
 			 char **, char **);
 static void determine_cpu_caches (unsigned int);
 
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 /*
  * The format of "screen_info" is strange, and due to early
@@ -547,7 +547,7 @@
 	} else {
 		strlcpy(command_line, COMMAND_LINE, sizeof command_line);
 	}
-	strcpy(saved_command_line, command_line);
+	strcpy(boot_command_line, command_line);
 	*cmdline_p = command_line;
 
 	/* 
@@ -589,7 +589,7 @@
 	}
 
 	/* Replace the command line, now that we've killed it with strsep.  */
-	strcpy(command_line, saved_command_line);
+	strcpy(command_line, boot_command_line);
 
 	/* If we want SRM console printk echoing early, do it now. */
 	if (alpha_using_srm && srmcons_output) {
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index d7053eb..4748e14 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -91,17 +91,6 @@
 }
 
 /*
- * Scheduler clock - returns current time in nanosec units.
- *
- * Copied from ARM code for expediency... ;-}
- */
-unsigned long long sched_clock(void)
-{
-        return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
-
-/*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index 76bf071..4cc44bd 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -52,10 +52,12 @@
   }
   __initcall_end = .;
 
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(8192);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
 
   . = ALIGN(8);
   .con_initcall.init : {
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6783c2e..4409561 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -9,6 +9,7 @@
 	bool
 	default y
 	select RTC_LIB
+	select SYS_SUPPORTS_APM_EMULATION
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -17,6 +18,9 @@
 	  Europe.  There is an ARM Linux project with a web page at
 	  <http://www.arm.linux.org.uk/>.
 
+config SYS_SUPPORTS_APM_EMULATION
+	bool
+
 config GENERIC_TIME
 	bool
 	default n
@@ -25,6 +29,10 @@
 	bool
 	default y
 
+config NO_IOPORT
+	bool
+	default n
+
 config EISA
 	bool
 	---help---
@@ -96,6 +104,10 @@
 config ARCH_MAY_HAVE_PC_FDC
 	bool
 
+config ZONE_DMA
+	bool
+	default y
+
 config GENERIC_ISA_DMA
 	bool
 
@@ -233,6 +245,8 @@
 
 config ARCH_IOP13XX
 	bool "IOP13xx-based"
+	depends on MMU
+	select PLAT_IOP
 	select PCI
 	help
 	  Support for Intel's IOP13XX (XScale) family of processors.
@@ -271,6 +285,14 @@
 	  If you have any questions or comments about the Linux kernel port
 	  to this board, send e-mail to <sjhill@cotw.com>.
 
+config ARCH_NS9XXX
+	bool "NetSilicon NS9xxx"
+	help
+	  Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
+	  System.
+
+	  <http://www.digi.com/products/microprocessors/index.jsp>
+
 config ARCH_PNX4008
 	bool "Philips Nexperia PNX4008 Mobile"
 	help
@@ -280,6 +302,7 @@
 	bool "PXA2xx-based"
 	depends on MMU
 	select ARCH_MTD_XIP
+	select GENERIC_TIME
 	help
 	  Support for Intel's PXA2XX processor line.
 
@@ -290,6 +313,7 @@
 	select TIMER_ACORN
 	select ARCH_MAY_HAVE_PC_FDC
 	select ISA_DMA_API
+	select NO_IOPORT
 	help
 	  On the Acorn Risc-PC, Linux can support the internal IDE disk and
 	  CD-ROM interface, serial and parallel port, and the floppy drive.
@@ -303,7 +327,7 @@
 	  Support for StrongARM 11x0 based boards.
 
 config ARCH_S3C2410
-	bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442"
+	bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
 	help
 	  Samsung S3C2410X CPU based systems, such as the Simtec Electronics
 	  BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -363,7 +387,16 @@
 
 source "arch/arm/mach-omap2/Kconfig"
 
+source "arch/arm/plat-s3c24xx/Kconfig"
+
+if ARCH_S3C2410
+source "arch/arm/mach-s3c2400/Kconfig"
 source "arch/arm/mach-s3c2410/Kconfig"
+source "arch/arm/mach-s3c2412/Kconfig"
+source "arch/arm/mach-s3c2440/Kconfig"
+source "arch/arm/mach-s3c2442/Kconfig"
+source "arch/arm/mach-s3c2443/Kconfig"
+endif
 
 source "arch/arm/mach-lh7a40x/Kconfig"
 
@@ -377,10 +410,12 @@
 
 source "arch/arm/mach-realview/Kconfig"
 
-source "arch/arm/mach-at91rm9200/Kconfig"
+source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-netx/Kconfig"
 
+source "arch/arm/mach-ns9xxx/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
@@ -392,7 +427,7 @@
 
 config IWMMXT
 	bool "Enable iWMMXt support"
-	depends CPU_XSCALE || CPU_XSC3
+	depends on CPU_XSCALE || CPU_XSC3
 	default y if PXA27x
 	help
 	  Enable support for iWMMXt context switching at run time if
@@ -738,6 +773,20 @@
 	  be linked for and stored to.  This address is dependent on your
 	  own flash usage.
 
+config KEXEC
+	bool "Kexec system call (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  kexec is a system call that implements the ability to shutdown your
+	  current kernel, and to start another kernel.  It is like a reboot
+	  but it is indepedent of the system firmware.   And like a reboot
+	  you can start any kernel with it, not just Linux.
+
+	  It is an ongoing process to be certain the hardware in a machine
+	  is properly shutdown, so do not be surprised if this code does not
+	  initially work for you.  It may help to enable device hotplugging
+	  support.
+
 endmenu
 
 if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
@@ -856,31 +905,6 @@
 
 source "kernel/power/Kconfig"
 
-config APM
-	tristate "Advanced Power Management Emulation"
-	---help---
-	  APM is a BIOS specification for saving power using several different
-	  techniques. This is mostly useful for battery powered laptops with
-	  APM compliant BIOSes. If you say Y here, the system time will be
-	  reset after a RESUME operation, the /proc/apm device will provide
-	  battery status information, and user-space programs will receive
-	  notification of APM "events" (e.g. battery status change).
-
-	  In order to use APM, you will need supporting software. For location
-	  and more information, read <file:Documentation/pm.txt> and the
-	  Battery Powered Linux mini-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  This driver does not spin down disk drives (see the hdparm(8)
-	  manpage ("man 8 hdparm") for that), and it doesn't turn off
-	  VESA-compliant "green" monitors.
-
-	  Generally, if you don't have a battery in your machine, there isn't
-	  much point in using this driver and you should say N. If you get
-	  random kernel OOPSes or reboots that don't seem to be related to
-	  anything, try disabling/enabling this option (or disabling/enabling
-	  APM in your BIOS).
-
 endmenu
 
 source "net/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 000f110..ab9f2d4 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -124,10 +124,12 @@
  machine-$(CONFIG_ARCH_H720X)	   := h720x
  machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
  machine-$(CONFIG_ARCH_REALVIEW)   := realview
- machine-$(CONFIG_ARCH_AT91)       := at91rm9200
- machine-$(CONFIG_ARCH_EP93XX)     := ep93xx
- machine-$(CONFIG_ARCH_PNX4008)    := pnx4008
- machine-$(CONFIG_ARCH_NETX)       := netx
+ machine-$(CONFIG_ARCH_AT91)	   := at91
+ machine-$(CONFIG_ARCH_EP93XX)	   := ep93xx
+ machine-$(CONFIG_ARCH_PNX4008)	   := pnx4008
+ machine-$(CONFIG_ARCH_NETX)	   := netx
+ machine-$(CONFIG_ARCH_NS9XXX)	   := ns9xxx
+ textofs-$(CONFIG_ARCH_NS9XXX)	   := 0x00108000
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
@@ -149,7 +151,7 @@
 else
 MACHINE  :=
 endif
-  
+
 export	TEXT_OFFSET GZFLAGS MMUEXT
 
 # Do we have FASTFPE?
@@ -161,6 +163,11 @@
 # If we have a machine-specific directory, then include it in the build.
 core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
 core-y				+= $(MACHINE)
+core-$(CONFIG_ARCH_S3C2410)	+= arch/arm/mach-s3c2400/
+core-$(CONFIG_ARCH_S3C2410)	+= arch/arm/mach-s3c2412/
+core-$(CONFIG_ARCH_S3C2410)	+= arch/arm/mach-s3c2440/
+core-$(CONFIG_ARCH_S3C2410)	+= arch/arm/mach-s3c2442/
+core-$(CONFIG_ARCH_S3C2410)	+= arch/arm/mach-s3c2443/
 core-$(CONFIG_FPE_NWFPE)	+= arch/arm/nwfpe/
 core-$(CONFIG_FPE_FASTFPE)	+= $(FASTFPE_OBJ)
 core-$(CONFIG_VFP)		+= arch/arm/vfp/
@@ -168,6 +175,7 @@
 # If we have a common platform directory, then include it in the build.
 core-$(CONFIG_PLAT_IOP)		+= arch/arm/plat-iop/
 core-$(CONFIG_ARCH_OMAP)	+= arch/arm/plat-omap/
+core-$(CONFIG_PLAT_S3C24XX)		+= arch/arm/plat-s3c24xx/
 
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
 drivers-$(CONFIG_ARCH_CLPS7500)	+= drivers/acorn/char/
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
new file mode 100644
index 0000000..171a085
--- /dev/null
+++ b/arch/arm/boot/.gitignore
@@ -0,0 +1,2 @@
+Image
+zImage
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
new file mode 100644
index 0000000..aefee20
--- /dev/null
+++ b/arch/arm/boot/compressed/.gitignore
@@ -0,0 +1 @@
+piggy.gz
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 2e635b8..6fbe772 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -32,7 +32,6 @@
 
 #include <asm/cacheflush.h>
 
-#undef DEBUG
 #undef STATS
 
 #ifdef STATS
@@ -66,14 +65,13 @@
 };
 
 struct dmabounce_device_info {
-	struct list_head node;
-
 	struct device *dev;
 	struct list_head safe_buffers;
 #ifdef STATS
 	unsigned long total_allocs;
 	unsigned long map_op_count;
 	unsigned long bounce_count;
+	int attr_res;
 #endif
 	struct dmabounce_pool	small;
 	struct dmabounce_pool	large;
@@ -81,34 +79,24 @@
 	rwlock_t lock;
 };
 
-static LIST_HEAD(dmabounce_devs);
-
 #ifdef STATS
-static void print_alloc_stats(struct dmabounce_device_info *device_info)
+static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
 {
-	printk(KERN_INFO
-		"%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n",
-		device_info->dev->bus_id,
-		device_info->small.allocs, device_info->large.allocs,
+	struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
+	return sprintf(buf, "%lu %lu %lu %lu %lu %lu\n",
+		device_info->small.allocs,
+		device_info->large.allocs,
 		device_info->total_allocs - device_info->small.allocs -
 			device_info->large.allocs,
-		device_info->total_allocs);
+		device_info->total_allocs,
+		device_info->map_op_count,
+		device_info->bounce_count);
 }
+
+static DEVICE_ATTR(dmabounce_stats, 0400, dmabounce_show, NULL);
 #endif
 
-/* find the given device in the dmabounce device list */
-static inline struct dmabounce_device_info *
-find_dmabounce_dev(struct device *dev)
-{
-	struct dmabounce_device_info *d;
-
-	list_for_each_entry(d, &dmabounce_devs, node)
-		if (d->dev == dev)
-			return d;
-
-	return NULL;
-}
-
 
 /* allocate a 'safe' buffer and keep track of it */
 static inline struct safe_buffer *
@@ -162,8 +150,6 @@
 	if (pool)
 		pool->allocs++;
 	device_info->total_allocs++;
-	if (device_info->total_allocs % 1000 == 0)
-		print_alloc_stats(device_info);
 #endif
 
 	write_lock_irqsave(&device_info->lock, flags);
@@ -218,20 +204,11 @@
 
 /* ************************************************** */
 
-#ifdef STATS
-static void print_map_stats(struct dmabounce_device_info *device_info)
-{
-	dev_info(device_info->dev,
-		"dmabounce: map_op_count=%lu, bounce_count=%lu\n",
-		device_info->map_op_count, device_info->bounce_count);
-}
-#endif
-
 static inline dma_addr_t
 map_single(struct device *dev, void *ptr, size_t size,
 		enum dma_data_direction dir)
 {
-	struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+	struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
 	dma_addr_t dma_addr;
 	int needs_bounce = 0;
 
@@ -281,10 +258,14 @@
 		ptr = buf->safe;
 
 		dma_addr = buf->safe_dma_addr;
+	} else {
+		/*
+		 * We don't need to sync the DMA buffer since
+		 * it was allocated via the coherent allocators.
+		 */
+		consistent_sync(ptr, size, dir);
 	}
 
-	consistent_sync(ptr, size, dir);
-
 	return dma_addr;
 }
 
@@ -292,7 +273,7 @@
 unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		enum dma_data_direction dir)
 {
-	struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+	struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
 	struct safe_buffer *buf = NULL;
 
 	/*
@@ -317,12 +298,12 @@
 		DO_STATS ( device_info->bounce_count++ );
 
 		if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
-			unsigned long ptr;
+			void *ptr = buf->ptr;
 
 			dev_dbg(dev,
 				"%s: copy back safe %p to unsafe %p size %d\n",
-				__func__, buf->safe, buf->ptr, size);
-			memcpy(buf->ptr, buf->safe, size);
+				__func__, buf->safe, ptr, size);
+			memcpy(ptr, buf->safe, size);
 
 			/*
 			 * DMA buffers must have the same cache properties
@@ -332,8 +313,8 @@
 			 * bidirectional case because we know the cache
 			 * lines will be coherent with the data written.
 			 */
-			ptr = (unsigned long)buf->ptr;
 			dmac_clean_range(ptr, ptr + size);
+			outer_clean_range(__pa(ptr), __pa(ptr) + size);
 		}
 		free_safe_buffer(device_info, buf);
 	}
@@ -343,7 +324,7 @@
 sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		enum dma_data_direction dir)
 {
-	struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+	struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
 	struct safe_buffer *buf = NULL;
 
 	if (device_info)
@@ -397,7 +378,10 @@
 		default:
 			BUG();
 		}
-		consistent_sync(buf->safe, size, dir);
+		/*
+		 * No need to sync the safe buffer - it was allocated
+		 * via the coherent allocators.
+		 */
 	} else {
 		consistent_sync(dma_to_virt(dev, dma_addr), size, dir);
 	}
@@ -604,9 +588,10 @@
 	device_info->total_allocs = 0;
 	device_info->map_op_count = 0;
 	device_info->bounce_count = 0;
+	device_info->attr_res = device_create_file(dev, &dev_attr_dmabounce_stats);
 #endif
 
-	list_add(&device_info->node, &dmabounce_devs);
+	dev->archdata.dmabounce = device_info;
 
 	printk(KERN_INFO "dmabounce: registered device %s on %s bus\n",
 		dev->bus_id, dev->bus->name);
@@ -623,7 +608,9 @@
 void
 dmabounce_unregister_dev(struct device *dev)
 {
-	struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+	struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
+
+	dev->archdata.dmabounce = NULL;
 
 	if (!device_info) {
 		printk(KERN_WARNING
@@ -645,12 +632,10 @@
 		dma_pool_destroy(device_info->large.pool);
 
 #ifdef STATS
-	print_alloc_stats(device_info);
-	print_map_stats(device_info);
+	if (device_info->attr_res == 0)
+		device_remove_file(dev, &dev_attr_dmabounce_stats);
 #endif
 
-	list_del(&device_info->node);
-
 	kfree(device_info);
 
 	printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n",
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 09b9d1b..4deece5 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -14,7 +14,9 @@
  *
  * o There is one CPU Interface per CPU, which sends interrupts sent
  *   by the Distributor, and interrupts generated locally, to the
- *   associated CPU.
+ *   associated CPU. The base address of the CPU interface is usually
+ *   aliased so that the same address points to different chips depending
+ *   on the CPU it is accessed from.
  *
  * Note that IRQs 0-31 are special - they are local to each CPU.
  * As such, the enable set/clear, pending set/clear and active bit
@@ -31,10 +33,38 @@
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
 
-static void __iomem *gic_dist_base;
-static void __iomem *gic_cpu_base;
 static DEFINE_SPINLOCK(irq_controller_lock);
 
+struct gic_chip_data {
+	unsigned int irq_offset;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+};
+
+#ifndef MAX_GIC_NR
+#define MAX_GIC_NR	1
+#endif
+
+static struct gic_chip_data gic_data[MAX_GIC_NR];
+
+static inline void __iomem *gic_dist_base(unsigned int irq)
+{
+	struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+	return gic_data->dist_base;
+}
+
+static inline void __iomem *gic_cpu_base(unsigned int irq)
+{
+	struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+	return gic_data->cpu_base;
+}
+
+static inline unsigned int gic_irq(unsigned int irq)
+{
+	struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+	return irq - gic_data->irq_offset;
+}
+
 /*
  * Routines to acknowledge, disable and enable interrupts
  *
@@ -55,8 +85,8 @@
 	u32 mask = 1 << (irq % 32);
 
 	spin_lock(&irq_controller_lock);
-	writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
-	writel(irq, gic_cpu_base + GIC_CPU_EOI);
+	writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
+	writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
 	spin_unlock(&irq_controller_lock);
 }
 
@@ -65,7 +95,7 @@
 	u32 mask = 1 << (irq % 32);
 
 	spin_lock(&irq_controller_lock);
-	writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
+	writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
 	spin_unlock(&irq_controller_lock);
 }
 
@@ -74,14 +104,14 @@
 	u32 mask = 1 << (irq % 32);
 
 	spin_lock(&irq_controller_lock);
-	writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4);
+	writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_SET + (gic_irq(irq) / 32) * 4);
 	spin_unlock(&irq_controller_lock);
 }
 
 #ifdef CONFIG_SMP
 static void gic_set_cpu(unsigned int irq, cpumask_t mask_val)
 {
-	void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3);
+	void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
 	unsigned int shift = (irq % 4) * 8;
 	unsigned int cpu = first_cpu(mask_val);
 	u32 val;
@@ -95,6 +125,37 @@
 }
 #endif
 
+static void fastcall gic_handle_cascade_irq(unsigned int irq,
+					    struct irq_desc *desc)
+{
+	struct gic_chip_data *chip_data = get_irq_data(irq);
+	struct irq_chip *chip = get_irq_chip(irq);
+	unsigned int cascade_irq;
+	unsigned long status;
+
+	/* primary controller ack'ing */
+	chip->ack(irq);
+
+	spin_lock(&irq_controller_lock);
+	status = readl(chip_data->cpu_base + GIC_CPU_INTACK);
+	spin_unlock(&irq_controller_lock);
+
+	cascade_irq = (status & 0x3ff);
+	if (cascade_irq > 1020)
+		goto out;
+	if (cascade_irq < 32 || cascade_irq >= NR_IRQS) {
+		do_bad_IRQ(cascade_irq, desc);
+		goto out;
+	}
+
+	cascade_irq += chip_data->irq_offset;
+	generic_handle_irq(cascade_irq);
+
+ out:
+	/* primary controller unmasking */
+	chip->unmask(irq);
+}
+
 static struct irq_chip gic_chip = {
 	.name		= "GIC",
 	.ack		= gic_ack_irq,
@@ -105,15 +166,29 @@
 #endif
 };
 
-void __init gic_dist_init(void __iomem *base)
+void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
+{
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+	if (set_irq_data(irq, &gic_data[gic_nr]) != 0)
+		BUG();
+	set_irq_chained_handler(irq, gic_handle_cascade_irq);
+}
+
+void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
+			  unsigned int irq_start)
 {
 	unsigned int max_irq, i;
 	u32 cpumask = 1 << smp_processor_id();
 
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
 	cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
 
-	gic_dist_base = base;
+	gic_data[gic_nr].dist_base = base;
+	gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
 
 	writel(0, base + GIC_DIST_CTRL);
 
@@ -158,8 +233,9 @@
 	/*
 	 * Setup the Linux IRQ subsystem.
 	 */
-	for (i = 29; i < max_irq; i++) {
+	for (i = irq_start; i < gic_data[gic_nr].irq_offset + max_irq; i++) {
 		set_irq_chip(i, &gic_chip);
+		set_irq_chip_data(i, &gic_data[gic_nr]);
 		set_irq_handler(i, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
@@ -167,9 +243,13 @@
 	writel(1, base + GIC_DIST_CTRL);
 }
 
-void __cpuinit gic_cpu_init(void __iomem *base)
+void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
 {
-	gic_cpu_base = base;
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	gic_data[gic_nr].cpu_base = base;
+
 	writel(0xf0, base + GIC_CPU_PRIMASK);
 	writel(1, base + GIC_CPU_CTRL);
 }
@@ -179,6 +259,7 @@
 {
 	unsigned long map = *cpus_addr(cpumask);
 
-	writel(map << 16 | irq, gic_dist_base + GIC_DIST_SOFTINT);
+	/* this always happens on GIC0 */
+	writel(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
index 4e5445c..bf1075e 100644
--- a/arch/arm/common/rtctime.c
+++ b/arch/arm/common/rtctime.c
@@ -329,7 +329,7 @@
 	return fasync_helper(fd, file, on, &rtc_async_queue);
 }
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= rtc_read,
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index b359974..a9bc5b5 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -23,11 +23,11 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
+#include <linux/apm-emulation.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
-#include <asm/apm.h>
 #include <asm/arch/pm.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/sharpsl.h>
diff --git a/arch/arm/configs/at91sam9263ek_defconfig b/arch/arm/configs/at91sam9263ek_defconfig
new file mode 100644
index 0000000..c72ab82
--- /dev/null
+++ b/arch/arm/configs/at91sam9263ek_defconfig
@@ -0,0 +1,1184 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20-rc1
+# Mon Jan  8 16:06:54 2007
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# 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 is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=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 is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# 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 is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_CLPS7500 is not set
+# 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_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX 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_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Atmel AT91 System-on-Chip
+#
+# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_AT91SAM9260 is not set
+# CONFIG_ARCH_AT91SAM9261 is not set
+CONFIG_ARCH_AT91SAM9263=y
+
+#
+# AT91SAM9263 Board Type
+#
+CONFIG_MACH_AT91SAM9263EK=y
+
+#
+# AT91 Board Options
+#
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# 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
+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=4096
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# 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 is not set
+# 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_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_DATAFLASH=y
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_AT91=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD 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=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+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=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# 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
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# 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
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_TSDEV=y
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=y
+# 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=y
+CONFIG_TOUCHSCREEN_ADS7846=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_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 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_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_AT91=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_ATMEL=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+
+#
+# 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
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# 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_FIRMWARE_EDID is not set
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX 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
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# 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_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=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM 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_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# 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_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_MII 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_ADUTUX 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_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# 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=y
+CONFIG_USB_AT91=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ETH is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_AT91=m
+# CONFIG_MMC_TIFM_SD is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# 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 is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_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
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# 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_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# 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 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_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=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# 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=y
+# 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
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig
index 3de5c64..baa9769 100644
--- a/arch/arm/configs/ateb9200_defconfig
+++ b/arch/arm/configs/ateb9200_defconfig
@@ -1066,7 +1066,7 @@
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_RS5C372 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_AT91=y
+CONFIG_RTC_DRV_AT91RM9200=y
 # CONFIG_RTC_DRV_TEST is not set
 
 #
diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
index 2cadd51..88e5d28 100644
--- a/arch/arm/configs/csb337_defconfig
+++ b/arch/arm/configs/csb337_defconfig
@@ -355,10 +355,12 @@
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_PLATRAM is not set
-CONFIG_MTD_CSB337=y
 
 #
 # Self-contained MTD device drivers
@@ -986,7 +988,7 @@
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_RS5C372 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_AT91=y
+CONFIG_RTC_DRV_AT91RM9200=y
 # CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig
index 94908c1..669f035 100644
--- a/arch/arm/configs/csb637_defconfig
+++ b/arch/arm/configs/csb637_defconfig
@@ -355,10 +355,12 @@
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_PLATRAM is not set
-CONFIG_MTD_CSB637=y
 
 #
 # Self-contained MTD device drivers
diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig
index a4cdafc..a0f48d5 100644
--- a/arch/arm/configs/kafa_defconfig
+++ b/arch/arm/configs/kafa_defconfig
@@ -718,7 +718,7 @@
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_RS5C372 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_AT91=y
+CONFIG_RTC_DRV_AT91RM9200=y
 # CONFIG_RTC_DRV_TEST is not set
 
 #
diff --git a/arch/arm/configs/ns9xxx_defconfig b/arch/arm/configs/ns9xxx_defconfig
new file mode 100644
index 0000000..0e5794c
--- /dev/null
+++ b/arch/arm/configs/ns9xxx_defconfig
@@ -0,0 +1,621 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+# Thu Feb 15 20:51:47 2007
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# 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_IPC_NS is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_UTS_NS is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_RT_MUTEXES=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=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# 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 is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# 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_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX 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_NS9XXX=y
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# NS9xxx Implementations
+#
+CONFIG_MACH_CC9P9360DEV=y
+CONFIG_PROCESSOR_NS9360=y
+CONFIG_BOARD_A9M9750DEV=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# 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
+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=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+
+#
+# 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_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# 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=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM 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
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# 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 is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# 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_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# 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 is not set
+# 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
+
+#
+# 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_ENABLE_MUST_CHECK is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_ICEDCC=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 3b31a33..df19e36 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc4
-# Fri Nov  3 17:41:31 2006
+# Linux kernel version: 2.6.20
+# Thu Feb 15 11:26:24 2007
 #
 CONFIG_ARM=y
 # CONFIG_GENERIC_TIME is not set
@@ -11,6 +11,8 @@
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_VECTORS_BASE=0xffff0000
@@ -37,13 +39,14 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,7 +79,9 @@
 # Block layer
 #
 CONFIG_BLOCK=y
+# CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -110,6 +115,7 @@
 # CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP23XX is not set
@@ -122,54 +128,73 @@
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_OMAP is not set
+CONFIG_PLAT_S3C24XX=y
+CONFIG_CPU_S3C244X=y
+CONFIG_PM_SIMTEC=y
+# CONFIG_S3C2410_BOOT_WATCHDOG is not set
+# CONFIG_S3C2410_BOOT_ERROR_RESET is not set
+# CONFIG_S3C2410_PM_DEBUG is not set
+# CONFIG_S3C2410_PM_CHECK is not set
+CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
+CONFIG_S3C2410_DMA=y
+# CONFIG_S3C2410_DMA_DEBUG is not set
+CONFIG_MACH_SMDK=y
 
 #
-# S3C24XX Implementations
+# S3C2400 Machines
 #
-# CONFIG_MACH_AML_M5900 is not set
+CONFIG_CPU_S3C2410=y
+CONFIG_CPU_S3C2410_DMA=y
+CONFIG_S3C2410_PM=y
+CONFIG_S3C2410_GPIO=y
+CONFIG_S3C2410_CLOCK=y
+
+#
+# S3C2410 Machines
+#
+CONFIG_ARCH_SMDK2410=y
+CONFIG_ARCH_H1940=y
+CONFIG_PM_H1940=y
+CONFIG_MACH_N30=y
+CONFIG_ARCH_BAST=y
+CONFIG_MACH_OTOM=y
+CONFIG_MACH_AML_M5900=y
+CONFIG_BAST_PC104_IRQ=y
+CONFIG_MACH_VR1000=y
+CONFIG_CPU_S3C2412=y
+CONFIG_S3C2412_DMA=y
+CONFIG_S3C2412_PM=y
+
+#
+# S3C2412 Machines
+#
+CONFIG_MACH_SMDK2413=y
+CONFIG_MACH_S3C2413=y
+CONFIG_MACH_VSTMS=y
+CONFIG_CPU_S3C2440=y
+CONFIG_S3C2440_DMA=y
+
+#
+# S3C2440 Machines
+#
 CONFIG_MACH_ANUBIS=y
 CONFIG_MACH_OSIRIS=y
-CONFIG_ARCH_BAST=y
-CONFIG_BAST_PC104_IRQ=y
-CONFIG_ARCH_H1940=y
-CONFIG_MACH_N30=y
-CONFIG_MACH_SMDK=y
-CONFIG_ARCH_SMDK2410=y
-CONFIG_ARCH_S3C2440=y
-CONFIG_SMDK2440_CPU2440=y
-CONFIG_SMDK2440_CPU2442=y
-CONFIG_MACH_S3C2413=y
-CONFIG_MACH_SMDK2413=y
-CONFIG_MACH_VR1000=y
 CONFIG_MACH_RX3715=y
-CONFIG_MACH_OTOM=y
+CONFIG_ARCH_S3C2440=y
 CONFIG_MACH_NEXCODER_2440=y
-CONFIG_MACH_VSTMS=y
-CONFIG_S3C2410_CLOCK=y
-CONFIG_S3C2410_PM=y
-CONFIG_CPU_S3C2410_DMA=y
-CONFIG_CPU_S3C2410=y
-CONFIG_S3C2412_PM=y
-CONFIG_CPU_S3C2412=y
-CONFIG_CPU_S3C244X=y
-CONFIG_CPU_S3C2440=y
+CONFIG_SMDK2440_CPU2440=y
 CONFIG_CPU_S3C2442=y
 
 #
-# S3C2410 Boot
+# S3C2442 Machines
 #
-# CONFIG_S3C2410_BOOT_WATCHDOG is not set
-# CONFIG_S3C2410_BOOT_ERROR_RESET is not set
+CONFIG_SMDK2440_CPU2442=y
+CONFIG_CPU_S3C2443=y
 
 #
-# S3C2410 Setup
+# S3C2443 Machines
 #
-CONFIG_S3C2410_DMA=y
-# CONFIG_S3C2410_DMA_DEBUG is not set
-# CONFIG_S3C2410_PM_DEBUG is not set
-# CONFIG_S3C2410_PM_CHECK is not set
-CONFIG_PM_SIMTEC=y
-CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
+CONFIG_MACH_SMDK2443=y
 
 #
 # Processor Type
@@ -196,6 +221,7 @@
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
 # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
 
 #
 # Bus support
@@ -303,6 +329,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -385,6 +412,7 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
@@ -531,6 +559,11 @@
 # CONFIG_SCSI_NETLINK is not set
 
 #
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -682,7 +715,7 @@
 # CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
-# CONFIG_ISI is not set
+# CONFIG_MOXA_SMARTIO_NEW is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_RISCOM8 is not set
@@ -700,13 +733,14 @@
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_RSA is not set
 # CONFIG_SERIAL_8250_FOURPORT is not set
 # CONFIG_SERIAL_8250_ACCENT is not set
 # CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set
 # CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
 
 #
 # Non-8250 serial port support
@@ -755,10 +789,6 @@
 # CONFIG_NVRAM is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -863,6 +893,7 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
@@ -870,6 +901,7 @@
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
@@ -952,6 +984,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1028,6 +1065,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1179,9 +1217,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_JFFS_FS=y
-CONFIG_JFFS_FS_VERBOSE=0
-# CONFIG_JFFS_PROC_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1191,7 +1226,7 @@
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -1285,6 +1320,11 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1296,6 +1336,8 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1311,12 +1353,10 @@
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_ERRORS is not set
@@ -1339,6 +1379,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -1346,3 +1387,4 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index ab06a86..bb28087 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -10,7 +10,6 @@
 		   process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
 		   time.o traps.o
 
-obj-$(CONFIG_APM)		+= apm.o
 obj-$(CONFIG_ISA_DMA_API)	+= dma.o
 obj-$(CONFIG_ARCH_ACORN)	+= ecard.o 
 obj-$(CONFIG_FIQ)		+= fiq.o
@@ -19,6 +18,7 @@
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o isa.o
 obj-$(CONFIG_SMP)		+= smp.o
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 
 obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c
deleted file mode 100644
index 2c37b70..0000000
--- a/arch/arm/kernel/apm.c
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * bios-less APM driver for ARM Linux 
- *  Jamey Hicks <jamey@crl.dec.com>
- *  adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
- *
- * APM 1.2 Reference:
- *   Intel Corporation, Microsoft Corporation. Advanced Power Management
- *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
- *
- * [This document is available from Microsoft at:
- *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
- */
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
-#include <linux/apm_bios.h>
-#include <linux/capability.h>
-#include <linux/sched.h>
-#include <linux/pm.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/completion.h>
-#include <linux/kthread.h>
-#include <linux/delay.h>
-
-#include <asm/apm.h> /* apm_power_info */
-#include <asm/system.h>
-
-/*
- * The apm_bios device is one of the misc char devices.
- * This is its minor number.
- */
-#define APM_MINOR_DEV	134
-
-/*
- * See Documentation/Config.help for the configuration options.
- *
- * Various options can be changed at boot time as follows:
- * (We allow underscores for compatibility with the modules code)
- *	apm=on/off			enable/disable APM
- */
-
-/*
- * Maximum number of events stored
- */
-#define APM_MAX_EVENTS		16
-
-struct apm_queue {
-	unsigned int		event_head;
-	unsigned int		event_tail;
-	apm_event_t		events[APM_MAX_EVENTS];
-};
-
-/*
- * The per-file APM data
- */
-struct apm_user {
-	struct list_head	list;
-
-	unsigned int		suser: 1;
-	unsigned int		writer: 1;
-	unsigned int		reader: 1;
-
-	int			suspend_result;
-	unsigned int		suspend_state;
-#define SUSPEND_NONE	0		/* no suspend pending */
-#define SUSPEND_PENDING	1		/* suspend pending read */
-#define SUSPEND_READ	2		/* suspend read, pending ack */
-#define SUSPEND_ACKED	3		/* suspend acked */
-#define SUSPEND_WAIT	4		/* waiting for suspend */
-#define SUSPEND_DONE	5		/* suspend completed */
-
-	struct apm_queue	queue;
-};
-
-/*
- * Local variables
- */
-static int suspends_pending;
-static int apm_disabled;
-static struct task_struct *kapmd_tsk;
-
-static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-
-/*
- * This is a list of everyone who has opened /dev/apm_bios
- */
-static DECLARE_RWSEM(user_list_lock);
-static LIST_HEAD(apm_user_list);
-
-/*
- * kapmd info.  kapmd provides us a process context to handle
- * "APM" events within - specifically necessary if we're going
- * to be suspending the system.
- */
-static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
-static DEFINE_SPINLOCK(kapmd_queue_lock);
-static struct apm_queue kapmd_queue;
-
-static DEFINE_MUTEX(state_lock);
-
-static const char driver_version[] = "1.13";	/* no spaces */
-
-
-
-/*
- * Compatibility cruft until the IPAQ people move over to the new
- * interface.
- */
-static void __apm_get_power_status(struct apm_power_info *info)
-{
-}
-
-/*
- * This allows machines to provide their own "apm get power status" function.
- */
-void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
-EXPORT_SYMBOL(apm_get_power_status);
-
-
-/*
- * APM event queue management.
- */
-static inline int queue_empty(struct apm_queue *q)
-{
-	return q->event_head == q->event_tail;
-}
-
-static inline apm_event_t queue_get_event(struct apm_queue *q)
-{
-	q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
-	return q->events[q->event_tail];
-}
-
-static void queue_add_event(struct apm_queue *q, apm_event_t event)
-{
-	q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
-	if (q->event_head == q->event_tail) {
-		static int notified;
-
-		if (notified++ == 0)
-		    printk(KERN_ERR "apm: an event queue overflowed\n");
-		q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
-	}
-	q->events[q->event_head] = event;
-}
-
-static void queue_event(apm_event_t event)
-{
-	struct apm_user *as;
-
-	down_read(&user_list_lock);
-	list_for_each_entry(as, &apm_user_list, list) {
-		if (as->reader)
-			queue_add_event(&as->queue, event);
-	}
-	up_read(&user_list_lock);
-	wake_up_interruptible(&apm_waitqueue);
-}
-
-/*
- * queue_suspend_event - queue an APM suspend event.
- *
- * Check that we're in a state where we can suspend.  If not,
- * return -EBUSY.  Otherwise, queue an event to all "writer"
- * users.  If there are no "writer" users, return '1' to
- * indicate that we can immediately suspend.
- */
-static int queue_suspend_event(apm_event_t event, struct apm_user *sender)
-{
-	struct apm_user *as;
-	int ret = 1;
-
-	mutex_lock(&state_lock);
-	down_read(&user_list_lock);
-
-	/*
-	 * If a thread is still processing, we can't suspend, so reject
-	 * the request.
-	 */
-	list_for_each_entry(as, &apm_user_list, list) {
-		if (as != sender && as->reader && as->writer && as->suser &&
-		    as->suspend_state != SUSPEND_NONE) {
-			ret = -EBUSY;
-			goto out;
-		}
-	}
-
-	list_for_each_entry(as, &apm_user_list, list) {
-		if (as != sender && as->reader && as->writer && as->suser) {
-			as->suspend_state = SUSPEND_PENDING;
-			suspends_pending++;
-			queue_add_event(&as->queue, event);
-			ret = 0;
-		}
-	}
- out:
-	up_read(&user_list_lock);
-	mutex_unlock(&state_lock);
-	wake_up_interruptible(&apm_waitqueue);
-	return ret;
-}
-
-static void apm_suspend(void)
-{
-	struct apm_user *as;
-	int err = pm_suspend(PM_SUSPEND_MEM);
-
-	/*
-	 * Anyone on the APM queues will think we're still suspended.
-	 * Send a message so everyone knows we're now awake again.
-	 */
-	queue_event(APM_NORMAL_RESUME);
-
-	/*
-	 * Finally, wake up anyone who is sleeping on the suspend.
-	 */
-	mutex_lock(&state_lock);
-	down_read(&user_list_lock);
-	list_for_each_entry(as, &apm_user_list, list) {
-		if (as->suspend_state == SUSPEND_WAIT ||
-		    as->suspend_state == SUSPEND_ACKED) {
-	  		as->suspend_result = err;
-			as->suspend_state = SUSPEND_DONE;
-		}
-	}
-	up_read(&user_list_lock);
-	mutex_unlock(&state_lock);
-
-	wake_up(&apm_suspend_waitqueue);
-}
-
-static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
-{
-	struct apm_user *as = fp->private_data;
-	apm_event_t event;
-	int i = count, ret = 0;
-
-	if (count < sizeof(apm_event_t))
-		return -EINVAL;
-
-	if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
-		return -EAGAIN;
-
-	wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
-
-	while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
-		event = queue_get_event(&as->queue);
-
-		ret = -EFAULT;
-		if (copy_to_user(buf, &event, sizeof(event)))
-			break;
-
-		mutex_lock(&state_lock);
-		if (as->suspend_state == SUSPEND_PENDING &&
-		    (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND))
-			as->suspend_state = SUSPEND_READ;
-		mutex_unlock(&state_lock);
-
-		buf += sizeof(event);
-		i -= sizeof(event);
-	}
-
-	if (i < count)
-		ret = count - i;
-
-	return ret;
-}
-
-static unsigned int apm_poll(struct file *fp, poll_table * wait)
-{
-	struct apm_user *as = fp->private_data;
-
-	poll_wait(fp, &apm_waitqueue, wait);
-	return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
-}
-
-/*
- * apm_ioctl - handle APM ioctl
- *
- * APM_IOC_SUSPEND
- *   This IOCTL is overloaded, and performs two functions.  It is used to:
- *     - initiate a suspend
- *     - acknowledge a suspend read from /dev/apm_bios.
- *   Only when everyone who has opened /dev/apm_bios with write permission
- *   has acknowledge does the actual suspend happen.
- */
-static int
-apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
-{
-	struct apm_user *as = filp->private_data;
-	unsigned long flags;
-	int err = -EINVAL;
-
-	if (!as->suser || !as->writer)
-		return -EPERM;
-
-	switch (cmd) {
-	case APM_IOC_SUSPEND:
-		mutex_lock(&state_lock);
-
-		as->suspend_result = -EINTR;
-
-		if (as->suspend_state == SUSPEND_READ) {
-			int pending;
-
-			/*
-			 * If we read a suspend command from /dev/apm_bios,
-			 * then the corresponding APM_IOC_SUSPEND ioctl is
-			 * interpreted as an acknowledge.
-			 */
-			as->suspend_state = SUSPEND_ACKED;
-			suspends_pending--;
-			pending = suspends_pending == 0;
-			mutex_unlock(&state_lock);
-
-			/*
-			 * If there are no further acknowledges required,
-			 * suspend the system.
-			 */
-			if (pending)
-				apm_suspend();
-
-			/*
-			 * Wait for the suspend/resume to complete.  If there
-			 * are pending acknowledges, we wait here for them.
-			 *
-			 * Note: we need to ensure that the PM subsystem does
-			 * not kick us out of the wait when it suspends the
-			 * threads.
-			 */
-			flags = current->flags;
-			current->flags |= PF_NOFREEZE;
-
-			wait_event(apm_suspend_waitqueue,
-				   as->suspend_state == SUSPEND_DONE);
-		} else {
-			as->suspend_state = SUSPEND_WAIT;
-			mutex_unlock(&state_lock);
-
-			/*
-			 * Otherwise it is a request to suspend the system.
-			 * Queue an event for all readers, and expect an
-			 * acknowledge from all writers who haven't already
-			 * acknowledged.
-			 */
-			err = queue_suspend_event(APM_USER_SUSPEND, as);
-			if (err < 0) {
-				/*
-				 * Avoid taking the lock here - this
-				 * should be fine.
-				 */
-				as->suspend_state = SUSPEND_NONE;
-				break;
-			}
-
-			if (err > 0)
-				apm_suspend();
-
-			/*
-			 * Wait for the suspend/resume to complete.  If there
-			 * are pending acknowledges, we wait here for them.
-			 *
-			 * Note: we need to ensure that the PM subsystem does
-			 * not kick us out of the wait when it suspends the
-			 * threads.
-			 */
-			flags = current->flags;
-			current->flags |= PF_NOFREEZE;
-
-			wait_event_interruptible(apm_suspend_waitqueue,
-					 as->suspend_state == SUSPEND_DONE);
-		}
-
-		current->flags = flags;
-
-		mutex_lock(&state_lock);
-		err = as->suspend_result;
-		as->suspend_state = SUSPEND_NONE;
-		mutex_unlock(&state_lock);
-		break;
-	}
-
-	return err;
-}
-
-static int apm_release(struct inode * inode, struct file * filp)
-{
-	struct apm_user *as = filp->private_data;
-	int pending = 0;
-
-	filp->private_data = NULL;
-
-	down_write(&user_list_lock);
-	list_del(&as->list);
-	up_write(&user_list_lock);
-
-	/*
-	 * We are now unhooked from the chain.  As far as new
-	 * events are concerned, we no longer exist.  However, we
-	 * need to balance suspends_pending, which means the
-	 * possibility of sleeping.
-	 */
-	mutex_lock(&state_lock);
-	if (as->suspend_state != SUSPEND_NONE) {
-		suspends_pending -= 1;
-		pending = suspends_pending == 0;
-	}
-	mutex_unlock(&state_lock);
-	if (pending)
-		apm_suspend();
-
-	kfree(as);
-	return 0;
-}
-
-static int apm_open(struct inode * inode, struct file * filp)
-{
-	struct apm_user *as;
-
-	as = kzalloc(sizeof(*as), GFP_KERNEL);
-	if (as) {
-		/*
-		 * XXX - this is a tiny bit broken, when we consider BSD
-		 * process accounting. If the device is opened by root, we
-		 * instantly flag that we used superuser privs. Who knows,
-		 * we might close the device immediately without doing a
-		 * privileged operation -- cevans
-		 */
-		as->suser = capable(CAP_SYS_ADMIN);
-		as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
-		as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
-
-		down_write(&user_list_lock);
-		list_add(&as->list, &apm_user_list);
-		up_write(&user_list_lock);
-
-		filp->private_data = as;
-	}
-
-	return as ? 0 : -ENOMEM;
-}
-
-static struct file_operations apm_bios_fops = {
-	.owner		= THIS_MODULE,
-	.read		= apm_read,
-	.poll		= apm_poll,
-	.ioctl		= apm_ioctl,
-	.open		= apm_open,
-	.release	= apm_release,
-};
-
-static struct miscdevice apm_device = {
-	.minor		= APM_MINOR_DEV,
-	.name		= "apm_bios",
-	.fops		= &apm_bios_fops
-};
-
-
-#ifdef CONFIG_PROC_FS
-/*
- * Arguments, with symbols from linux/apm_bios.h.
- *
- *   0) Linux driver version (this will change if format changes)
- *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
- *   2) APM flags from APM Installation Check (0x00):
- *	bit 0: APM_16_BIT_SUPPORT
- *	bit 1: APM_32_BIT_SUPPORT
- *	bit 2: APM_IDLE_SLOWS_CLOCK
- *	bit 3: APM_BIOS_DISABLED
- *	bit 4: APM_BIOS_DISENGAGED
- *   3) AC line status
- *	0x00: Off-line
- *	0x01: On-line
- *	0x02: On backup power (BIOS >= 1.1 only)
- *	0xff: Unknown
- *   4) Battery status
- *	0x00: High
- *	0x01: Low
- *	0x02: Critical
- *	0x03: Charging
- *	0x04: Selected battery not present (BIOS >= 1.2 only)
- *	0xff: Unknown
- *   5) Battery flag
- *	bit 0: High
- *	bit 1: Low
- *	bit 2: Critical
- *	bit 3: Charging
- *	bit 7: No system battery
- *	0xff: Unknown
- *   6) Remaining battery life (percentage of charge):
- *	0-100: valid
- *	-1: Unknown
- *   7) Remaining battery life (time units):
- *	Number of remaining minutes or seconds
- *	-1: Unknown
- *   8) min = minutes; sec = seconds
- */
-static int apm_get_info(char *buf, char **start, off_t fpos, int length)
-{
-	struct apm_power_info info;
-	char *units;
-	int ret;
-
-	info.ac_line_status = 0xff;
-	info.battery_status = 0xff;
-	info.battery_flag   = 0xff;
-	info.battery_life   = -1;
-	info.time	    = -1;
-	info.units	    = -1;
-
-	if (apm_get_power_status)
-		apm_get_power_status(&info);
-
-	switch (info.units) {
-	default:	units = "?";	break;
-	case 0: 	units = "min";	break;
-	case 1: 	units = "sec";	break;
-	}
-
-	ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
-		     driver_version, APM_32_BIT_SUPPORT,
-		     info.ac_line_status, info.battery_status,
-		     info.battery_flag, info.battery_life,
-		     info.time, units);
-
- 	return ret;
-}
-#endif
-
-static int kapmd(void *arg)
-{
-	do {
-		apm_event_t event;
-		int ret;
-
-		wait_event_interruptible(kapmd_wait,
-				!queue_empty(&kapmd_queue) || kthread_should_stop());
-
-		if (kthread_should_stop())
-			break;
-
-		spin_lock_irq(&kapmd_queue_lock);
-		event = 0;
-		if (!queue_empty(&kapmd_queue))
-			event = queue_get_event(&kapmd_queue);
-		spin_unlock_irq(&kapmd_queue_lock);
-
-		switch (event) {
-		case 0:
-			break;
-
-		case APM_LOW_BATTERY:
-		case APM_POWER_STATUS_CHANGE:
-			queue_event(event);
-			break;
-
-		case APM_USER_SUSPEND:
-		case APM_SYS_SUSPEND:
-			ret = queue_suspend_event(event, NULL);
-			if (ret < 0) {
-				/*
-				 * We were busy.  Try again in 50ms.
-				 */
-				queue_add_event(&kapmd_queue, event);
-				msleep(50);
-			}
-			if (ret > 0)
-				apm_suspend();
-			break;
-
-		case APM_CRITICAL_SUSPEND:
-			apm_suspend();
-			break;
-		}
-	} while (1);
-
-	return 0;
-}
-
-static int __init apm_init(void)
-{
-	int ret;
-
-	if (apm_disabled) {
-		printk(KERN_NOTICE "apm: disabled on user request.\n");
-		return -ENODEV;
-	}
-
-	kapmd_tsk = kthread_create(kapmd, NULL, "kapmd");
-	if (IS_ERR(kapmd_tsk)) {
-		ret = PTR_ERR(kapmd_tsk);
-		kapmd_tsk = NULL;
-		return ret;
-	}
-	kapmd_tsk->flags |= PF_NOFREEZE;
-	wake_up_process(kapmd_tsk);
-
-#ifdef CONFIG_PROC_FS
-	create_proc_info_entry("apm", 0, NULL, apm_get_info);
-#endif
-
-	ret = misc_register(&apm_device);
-	if (ret != 0) {
-		remove_proc_entry("apm", NULL);
-		kthread_stop(kapmd_tsk);
-	}
-
-	return ret;
-}
-
-static void __exit apm_exit(void)
-{
-	misc_deregister(&apm_device);
-	remove_proc_entry("apm", NULL);
-
-	kthread_stop(kapmd_tsk);
-}
-
-module_init(apm_init);
-module_exit(apm_exit);
-
-MODULE_AUTHOR("Stephen Rothwell");
-MODULE_DESCRIPTION("Advanced Power Management");
-MODULE_LICENSE("GPL");
-
-#ifndef MODULE
-static int __init apm_setup(char *str)
-{
-	while ((str != NULL) && (*str != '\0')) {
-		if (strncmp(str, "off", 3) == 0)
-			apm_disabled = 1;
-		if (strncmp(str, "on", 2) == 0)
-			apm_disabled = 0;
-		str = strchr(str, ',');
-		if (str != NULL)
-			str += strspn(str, ", \t");
-	}
-	return 1;
-}
-
-__setup("apm=", apm_setup);
-#endif
-
-/**
- * apm_queue_event - queue an APM event for kapmd
- * @event: APM event
- *
- * Queue an APM event for kapmd to process and ultimately take the
- * appropriate action.  Only a subset of events are handled:
- *   %APM_LOW_BATTERY
- *   %APM_POWER_STATUS_CHANGE
- *   %APM_USER_SUSPEND
- *   %APM_SYS_SUSPEND
- *   %APM_CRITICAL_SUSPEND
- */
-void apm_queue_event(apm_event_t event)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&kapmd_queue_lock, flags);
-	queue_add_event(&kapmd_queue, event);
-	spin_unlock_irqrestore(&kapmd_queue_lock, flags);
-
-	wake_up_interruptible(&kapmd_wait);
-}
-EXPORT_SYMBOL(apm_queue_event);
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index f7598cb..ae89cdd 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -356,6 +356,7 @@
 		CALL(sys_move_pages)
 /* 345 */	CALL(sys_getcpu)
 		CALL(sys_ni_syscall)		/* eventually epoll_pwait */
+		CALL(sys_kexec_load)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
diff --git a/arch/arm/kernel/crunch.c b/arch/arm/kernel/crunch.c
index cec8378..627d794 100644
--- a/arch/arm/kernel/crunch.c
+++ b/arch/arm/kernel/crunch.c
@@ -75,6 +75,7 @@
 static int __init crunch_init(void)
 {
 	thread_register_notifier(&crunch_notifier_block);
+	elf_hwcap |= HWCAP_CRUNCH;
 
 	return 0;
 }
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 71257e3..f1c0fb9 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -1009,7 +1009,7 @@
 		ec->fiqmask = 4;
 	}
 
-	for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
+	for (i = 0; i < ARRAY_SIZE(blacklist); i++)
 		if (blacklist[i].manufacturer == ec->cid.manufacturer &&
 		    blacklist[i].product == ec->cid.product) {
 			ec->card_desc = blacklist[i].type;
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 8517c3c..d645897 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -27,6 +27,7 @@
  * Interrupt handling.  Preserves r7, r8, r9
  */
 	.macro	irq_handler
+	get_irqnr_preamble r5, lr
 1:	get_irqnr_and_base r0, r6, r5, lr
 	movne	r1, sp
 	@
@@ -99,7 +100,6 @@
 					@ cpsr_<exception>, "old_r0"
 
 	mov	r0, sp
-	and	r2, r6, #0x1f
 	b	bad_mode
 
 /*
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 6f5e7c5..c589dc3 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -9,6 +9,7 @@
  */
 
 #include <asm/unistd.h>
+#include <asm/arch/entry-macro.S>
 
 #include "entry-header.S"
 
@@ -25,6 +26,9 @@
 	tst	r1, #_TIF_WORK_MASK
 	bne	fast_work_pending
 
+	/* perform architecture specific actions before user return */
+	arch_ret_to_user r1, lr
+
 	@ fast_restore_user_regs
 	ldr	r1, [sp, #S_OFF + S_PSR]	@ get calling cpsr
 	ldr	lr, [sp, #S_OFF + S_PC]!	@ get pc
@@ -61,6 +65,9 @@
 	tst	r1, #_TIF_WORK_MASK
 	bne	work_pending
 no_work_pending:
+	/* perform architecture specific actions before user return */
+	arch_ret_to_user r1, lr
+
 	@ slow_restore_user_regs
 	ldr	r1, [sp, #S_PSR]		@ get calling cpsr
 	ldr	lr, [sp, #S_PC]!		@ get pc
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index ec01f08..e101846 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -159,8 +159,7 @@
 	int irq;
 
 	for (irq = 0; irq < NR_IRQS; irq++)
-		irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_DELAYED_DISABLE |
-			IRQ_NOPROBE;
+		irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
 
 #ifdef CONFIG_SMP
 	bad_irq_desc.affinity = CPU_MASK_ALL;
diff --git a/arch/arm/kernel/isa.c b/arch/arm/kernel/isa.c
index 54bbd9f..50a30bc 100644
--- a/arch/arm/kernel/isa.c
+++ b/arch/arm/kernel/isa.c
@@ -70,5 +70,5 @@
 	isa_membase = membase;
 	isa_portbase = portbase;
 	isa_portshift = portshift;
-	isa_sysctl_header = register_sysctl_table(ctl_bus, 0);
+	isa_sysctl_header = register_sysctl_table(ctl_bus);
 }
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
new file mode 100644
index 0000000..863c664
--- /dev/null
+++ b/arch/arm/kernel/machine_kexec.c
@@ -0,0 +1,78 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+#include <asm/mach-types.h>
+
+const extern unsigned char relocate_new_kernel[];
+const extern unsigned int relocate_new_kernel_size;
+
+extern void setup_mm_for_reboot(char mode);
+
+extern unsigned long kexec_start_address;
+extern unsigned long kexec_indirection_page;
+extern unsigned long kexec_mach_type;
+
+/*
+ * Provide a dummy crash_notes definition while crash dump arrives to arm.
+ * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
+ */
+
+int machine_kexec_prepare(struct kimage *image)
+{
+	return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+}
+
+void machine_shutdown(void)
+{
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
+void machine_kexec(struct kimage *image)
+{
+	unsigned long page_list;
+	unsigned long reboot_code_buffer_phys;
+	void *reboot_code_buffer;
+
+
+	page_list = image->head & PAGE_MASK;
+
+	/* we need both effective and real address here */
+	reboot_code_buffer_phys =
+	    page_to_pfn(image->control_code_page) << PAGE_SHIFT;
+	reboot_code_buffer = page_address(image->control_code_page);
+
+	/* Prepare parameters for reboot_code_buffer*/
+	kexec_start_address = image->start;
+	kexec_indirection_page = page_list;
+	kexec_mach_type = machine_arch_type;
+
+	/* copy our kernel relocation code to the control code page */
+	memcpy(reboot_code_buffer,
+	       relocate_new_kernel, relocate_new_kernel_size);
+
+
+	flush_icache_range((unsigned long) reboot_code_buffer,
+			   (unsigned long) reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
+	printk(KERN_INFO "Bye!\n");
+
+	cpu_proc_fin();
+	setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
+	cpu_reset(reboot_code_buffer_phys);
+}
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index a9e8f7e..782af3c 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -36,7 +36,13 @@
 #include <asm/uaccess.h>
 #include <asm/mach/time.h>
 
-extern const char *processor_modes[];
+static const char *processor_modes[] = {
+  "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
+  "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
+  "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
+  "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
+};
+
 extern void setup_mm_for_reboot(char mode);
 
 static volatile int hlt_counter;
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
new file mode 100644
index 0000000..7baadae
--- /dev/null
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -0,0 +1,74 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ */
+
+#include <asm/kexec.h>
+
+	.globl relocate_new_kernel
+relocate_new_kernel:
+
+	ldr	r0,kexec_indirection_page
+	ldr	r1,kexec_start_address
+
+
+0:	/* top, read another word for the indirection page */
+	ldr	r3, [r0],#4
+
+	/* Is it a destination page. Put destination address to r4 */
+	tst	r3,#1,0
+	beq	1f
+	bic	r4,r3,#1
+	b	0b
+1:
+	/* Is it an indirection page */
+	tst	r3,#2,0
+	beq	1f
+	bic	r0,r3,#2
+	b	0b
+1:
+
+	/* are we done ? */
+	tst	r3,#4,0
+	beq	1f
+	b	2f
+
+1:
+	/* is it source ? */
+	tst	r3,#8,0
+	beq	0b
+	bic r3,r3,#8
+	mov r6,#1024
+9:
+	ldr r5,[r3],#4
+	str r5,[r4],#4
+	subs r6,r6,#1
+	bne 9b
+	b 0b
+
+2:
+	/* Jump to relocated kernel */
+	mov lr,r1
+	mov r0,#0
+	ldr r1,kexec_mach_type
+	mov r2,#0
+	mov pc,lr
+
+	.globl kexec_start_address
+kexec_start_address:
+	.long	0x0
+
+	.globl kexec_indirection_page
+kexec_indirection_page:
+	.long	0x0
+
+	.globl kexec_mach_type
+kexec_mach_type:
+	.long	0x0
+
+relocate_new_kernel_end:
+
+	.globl relocate_new_kernel_size
+relocate_new_kernel_size:
+	.long relocate_new_kernel_end - relocate_new_kernel
+
+
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index bbab134..03e37af 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -88,6 +88,9 @@
 #ifdef MULTI_CACHE
 struct cpu_cache_fns cpu_cache;
 #endif
+#ifdef CONFIG_OUTER_CACHE
+struct outer_cache_fns outer_cache;
+#endif
 
 struct stack {
 	u32 irq[3];
@@ -106,7 +109,7 @@
 static struct meminfo meminfo __initdata = { 0, };
 static const char *cpu_name;
 static const char *machine_name;
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
@@ -803,8 +806,8 @@
 	init_mm.end_data   = (unsigned long) &_edata;
 	init_mm.brk	   = (unsigned long) &_end;
 
-	memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 	parse_cmdline(cmdline_p, from);
 	paging_init(&meminfo, mdesc);
 	request_standard_resources(&meminfo, mdesc);
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 3c8cdcf..f61decb 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -40,12 +40,14 @@
  */
 struct sys_timer *system_timer;
 
+#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
 /* this needs a better home */
 DEFINE_SPINLOCK(rtc_lock);
 
-#ifdef CONFIG_SA1100_RTC_MODULE
+#ifdef CONFIG_RTC_DRV_CMOS_MODULE
 EXPORT_SYMBOL(rtc_lock);
 #endif
+#endif	/* pc-style 'CMOS' RTC support */
 
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY	(1000000/HZ)
@@ -78,16 +80,6 @@
 #endif
 
 /*
- * Scheduler clock - returns current time in nanosec units.
- * This is the default implementation.  Sub-architecture
- * implementations can override this.
- */
-unsigned long long __attribute__((weak)) sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
-/*
  * An implementation of printk_clock() independent from
  * sched_clock().  This avoids non-bootable kernels when
  * printk_clock is enabled.
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 9089156..2409560 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -32,13 +32,6 @@
 #include "ptrace.h"
 #include "signal.h"
 
-const char *processor_modes[]=
-{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
-  "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
-  "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
-  "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
-};
-
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
 #ifdef CONFIG_DEBUG_USER
@@ -289,7 +282,10 @@
 	regs->ARM_pc -= correction;
 
 	pc = (void __user *)instruction_pointer(regs);
-	if (thumb_mode(regs)) {
+
+	if (processor_mode(regs) == SVC_MODE) {
+		instr = *(u32 *) pc;
+	} else if (thumb_mode(regs)) {
 		get_user(instr, (u16 __user *)pc);
 	} else {
 		get_user(instr, (u32 __user *)pc);
@@ -337,12 +333,11 @@
  * It never returns, and never tries to sync.  We hope that we can at least
  * dump out some state information...
  */
-asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
+asmlinkage void bad_mode(struct pt_regs *regs, int reason)
 {
 	console_verbose();
 
-	printk(KERN_CRIT "Bad mode in %s handler detected: mode %s\n",
-		handler[reason], processor_modes[proc_mode]);
+	printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]);
 
 	die("Oops - bad mode", regs, 0);
 	local_irq_disable();
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index a8fa75e..b929a60 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -53,10 +53,12 @@
 		__security_initcall_start = .;
 			*(.security_initcall.init)
 		__security_initcall_end = .;
+#ifdef CONFIG_BLK_DEV_INITRD
 		. = ALIGN(32);
 		__initramfs_start = .;
 			usr/built-in.o(.init.ramfs)
 		__initramfs_end = .;
+#endif
 		. = ALIGN(64);
 		__per_cpu_start = .;
 			*(.data.percpu)
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
new file mode 100644
index 0000000..bf0d962
--- /dev/null
+++ b/arch/arm/mach-at91/Kconfig
@@ -0,0 +1,175 @@
+if ARCH_AT91
+
+menu "Atmel AT91 System-on-Chip"
+
+choice
+	prompt "Atmel AT91 Processor"
+
+config ARCH_AT91RM9200
+	bool "AT91RM9200"
+
+config ARCH_AT91SAM9260
+	bool "AT91SAM9260 or AT91SAM9XE"
+
+config ARCH_AT91SAM9261
+	bool "AT91SAM9261"
+
+config ARCH_AT91SAM9263
+	bool "AT91SAM9263"
+
+endchoice
+
+# ----------------------------------------------------------
+
+if ARCH_AT91RM9200
+
+comment "AT91RM9200 Board Type"
+
+config MACH_ONEARM
+	bool "Ajeco 1ARM Single Board Computer"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Ajeco's 1ARM Single Board Computer.
+	  <http://www.ajeco.fi/products.htm>
+
+config ARCH_AT91RM9200DK
+	bool "Atmel AT91RM9200-DK Development board"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Atmel's AT91RM9200-DK Development board.
+	  (Discontinued)
+
+config MACH_AT91RM9200EK
+	bool "Atmel AT91RM9200-EK Evaluation Kit"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Atmel's AT91RM9200-EK Evaluation Kit.
+	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3507>
+
+config MACH_CSB337
+	bool "Cogent CSB337"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Cogent's CSB337 board.
+	  <http://www.cogcomp.com/csb_csb337.htm>
+
+config MACH_CSB637
+	bool "Cogent CSB637"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Cogent's CSB637 board.
+	  <http://www.cogcomp.com/csb_csb637.htm>
+
+config MACH_CARMEVA
+	bool "Conitec ARM&EVA"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Conitec's AT91RM9200-MCU-Module.
+	  <http://www.conitec.net/english/linuxboard.htm>
+
+config MACH_ATEB9200
+	bool "Embest ATEB9200"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Embest's ATEB9200 board.
+	  <http://www.embedinfo.com/english/product/ATEB9200.asp>
+
+config MACH_KB9200
+	bool "KwikByte KB920x"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using KwikByte's KB920x board.
+	  <http://kwikbyte.com/KB9202_description_new.htm>
+
+config MACH_KAFA
+	bool "Sperry-Sun KAFA board"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Sperry-Sun's KAFA board.
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9260
+
+comment "AT91SAM9260 Variants"
+
+config ARCH_AT91SAM9260_SAM9XE
+	bool "AT91SAM9XE"
+	depends on ARCH_AT91SAM9260
+	help
+	  Select this if you are using Atmel's AT91SAM9XE System-on-Chip.
+	  They are basicaly AT91SAM9260s with various sizes of embedded Flash.
+
+comment "AT91SAM9260 / AT91SAM9XE Board Type"
+
+config MACH_AT91SAM9260EK
+	bool "Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit"
+	depends on ARCH_AT91SAM9260
+	help
+	  Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit
+	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9261
+
+comment "AT91SAM9261 Board Type"
+
+config MACH_AT91SAM9261EK
+	bool "Atmel AT91SAM9261-EK Evaluation Kit"
+	depends on ARCH_AT91SAM9261
+	help
+	  Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit.
+	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3820>
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9263
+
+comment "AT91SAM9263 Board Type"
+
+config MACH_AT91SAM9263EK
+	bool "Atmel AT91SAM9263-EK Evaluation Kit"
+	depends on ARCH_AT91SAM9263
+	help
+	  Select this if you are using Atmel's AT91SAM9263-EK Evaluation Kit.
+	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4057>
+
+endif
+
+# ----------------------------------------------------------
+
+comment "AT91 Board Options"
+
+config MTD_AT91_DATAFLASH_CARD
+	bool "Enable DataFlash Card support"
+	depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK)
+	help
+	  Enable support for the DataFlash card.
+
+config MTD_NAND_AT91_BUSWIDTH_16
+	bool "Enable 16-bit data bus interface to NAND flash"
+	depends on (MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK)
+	help
+	  On AT91SAM926x boards both types of NAND flash can be present
+	  (8 and 16 bit data bus width).
+
+# ----------------------------------------------------------
+
+comment "AT91 Feature Selections"
+
+config AT91_PROGRAMMABLE_CLOCKS
+	bool "Programmable Clocks"
+	help
+	  Select this if you need to program one or more of the PCK0..PCK3
+	  programmable clock outputs.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
new file mode 100644
index 0000000..05de6cd
--- /dev/null
+++ b/arch/arm/mach-at91/Makefile
@@ -0,0 +1,53 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y		:= clock.o irq.o gpio.o
+obj-m		:=
+obj-n		:=
+obj-		:=
+
+obj-$(CONFIG_PM)		+= pm.o
+
+# CPU-specific support
+obj-$(CONFIG_ARCH_AT91RM9200)	+= at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9260)	+= at91sam9260.o at91sam926x_time.o at91sam9260_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9261)	+= at91sam9261.o at91sam926x_time.o at91sam9261_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9263)	+= at91sam9263.o at91sam926x_time.o at91sam9263_devices.o
+
+# AT91RM9200 board-specific support
+obj-$(CONFIG_MACH_ONEARM)	+= board-1arm.o
+obj-$(CONFIG_ARCH_AT91RM9200DK)	+= board-dk.o
+obj-$(CONFIG_MACH_AT91RM9200EK)	+= board-ek.o
+obj-$(CONFIG_MACH_CSB337)	+= board-csb337.o
+obj-$(CONFIG_MACH_CSB637)	+= board-csb637.o
+obj-$(CONFIG_MACH_CARMEVA)	+= board-carmeva.o
+obj-$(CONFIG_MACH_KB9200)	+= board-kb9202.o
+obj-$(CONFIG_MACH_ATEB9200)	+= board-eb9200.o
+obj-$(CONFIG_MACH_KAFA)		+= board-kafa.o
+
+# AT91SAM9260 board-specific support
+obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
+
+# AT91SAM9261 board-specific support
+obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
+
+# AT91SAM9263 board-specific support
+obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.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_MACH_KB9200)	+= leds.o
+led-$(CONFIG_MACH_KAFA)		+= leds.o
+obj-$(CONFIG_LEDS) += $(led-y)
+
+# VGA support
+#obj-$(CONFIG_FB_S1D13XXX)	+= ics1523.o
+
+
+ifeq ($(CONFIG_PM_DEBUG),y)
+CFLAGS_pm.o += -DDEBUG
+endif
diff --git a/arch/arm/mach-at91rm9200/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
similarity index 100%
rename from arch/arm/mach-at91rm9200/Makefile.boot
rename to arch/arm/mach-at91/Makefile.boot
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
new file mode 100644
index 0000000..2ddcdd6
--- /dev/null
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -0,0 +1,329 @@
+/*
+ * arch/arm/mach-at91/at91rm9200.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_st.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91rm9200_io_desc[] __initdata = {
+	{
+		.virtual	= AT91_VA_BASE_SYS,
+		.pfn		= __phys_to_pfn(AT91_BASE_SYS),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= AT91_VA_BASE_EMAC,
+		.pfn		= __phys_to_pfn(AT91RM9200_BASE_EMAC),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE,
+		.pfn		= __phys_to_pfn(AT91RM9200_SRAM_BASE),
+		.length		= AT91RM9200_SRAM_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk udc_clk = {
+	.name		= "udc_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_UDP,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+	.name		= "ohci_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_UHP,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk ether_clk = {
+	.name		= "ether_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_EMAC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+	.name		= "mci_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_MCI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+	.name		= "twi_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_TWI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+	.name		= "usart0_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_US0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+	.name		= "usart1_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_US1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+	.name		= "usart2_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_US2,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart3_clk = {
+	.name		= "usart3_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_US3,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi_clk = {
+	.name		= "spi_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_SPI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioA_clk = {
+	.name		= "pioA_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_PIOA,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+	.name		= "pioB_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_PIOB,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+	.name		= "pioC_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_PIOC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioD_clk = {
+	.name		= "pioD_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_PIOD,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc0_clk = {
+	.name		= "tc0_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_TC0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+	.name		= "tc1_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_TC1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+	.name		= "tc2_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_TC2,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc3_clk = {
+	.name		= "tc3_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_TC3,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc4_clk = {
+	.name		= "tc4_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_TC4,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc5_clk = {
+	.name		= "tc5_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_TC5,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+	&pioA_clk,
+	&pioB_clk,
+	&pioC_clk,
+	&pioD_clk,
+	&usart0_clk,
+	&usart1_clk,
+	&usart2_clk,
+	&usart3_clk,
+	&mmc_clk,
+	&udc_clk,
+	&twi_clk,
+	&spi_clk,
+	// ssc 0 .. ssc2
+	&tc0_clk,
+	&tc1_clk,
+	&tc2_clk,
+	&tc3_clk,
+	&tc4_clk,
+	&tc5_clk,
+	&ohci_clk,
+	&ether_clk,
+	// irq0 .. irq6
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+	.name		= "pck0",
+	.pmc_mask	= AT91_PMC_PCK0,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 0,
+};
+static struct clk pck1 = {
+	.name		= "pck1",
+	.pmc_mask	= AT91_PMC_PCK1,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 1,
+};
+static struct clk pck2 = {
+	.name		= "pck2",
+	.pmc_mask	= AT91_PMC_PCK2,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 2,
+};
+static struct clk pck3 = {
+	.name		= "pck3",
+	.pmc_mask	= AT91_PMC_PCK3,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 3,
+};
+
+static void __init at91rm9200_register_clocks(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+		clk_register(periph_clocks[i]);
+
+	clk_register(&pck0);
+	clk_register(&pck1);
+	clk_register(&pck2);
+	clk_register(&pck3);
+}
+
+/* --------------------------------------------------------------------
+ *  GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91rm9200_gpio[] = {
+	{
+		.id		= AT91RM9200_ID_PIOA,
+		.offset		= AT91_PIOA,
+		.clock		= &pioA_clk,
+	}, {
+		.id		= AT91RM9200_ID_PIOB,
+		.offset		= AT91_PIOB,
+		.clock		= &pioB_clk,
+	}, {
+		.id		= AT91RM9200_ID_PIOC,
+		.offset		= AT91_PIOC,
+		.clock		= &pioC_clk,
+	}, {
+		.id		= AT91RM9200_ID_PIOD,
+		.offset		= AT91_PIOD,
+		.clock		= &pioD_clk,
+	}
+};
+
+static void at91rm9200_reset(void)
+{
+	/*
+	 * Perform a hardware reset with the use of the Watchdog timer.
+	 */
+	at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
+	at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+
+/* --------------------------------------------------------------------
+ *  AT91RM9200 processor initialization
+ * -------------------------------------------------------------------- */
+void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks)
+{
+	/* Map peripherals */
+	iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
+
+	at91_arch_reset = at91rm9200_reset;
+	at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1)
+			| (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3)
+			| (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5)
+			| (1 << AT91RM9200_ID_IRQ6);
+
+	/* Init clock subsystem */
+	at91_clock_init(main_clock);
+
+	/* Register the processor-specific clocks */
+	at91rm9200_register_clocks();
+
+	/* Initialize GPIO subsystem */
+	at91_gpio_init(at91rm9200_gpio, banks);
+}
+
+
+/* --------------------------------------------------------------------
+ *  Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
+	7,	/* Advanced Interrupt Controller (FIQ) */
+	7,	/* System Peripherals */
+	0,	/* Parallel IO Controller A */
+	0,	/* Parallel IO Controller B */
+	0,	/* Parallel IO Controller C */
+	0,	/* Parallel IO Controller D */
+	6,	/* USART 0 */
+	6,	/* USART 1 */
+	6,	/* USART 2 */
+	6,	/* USART 3 */
+	0,	/* Multimedia Card Interface */
+	4,	/* USB Device Port */
+	0,	/* Two-Wire Interface */
+	6,	/* Serial Peripheral Interface */
+	5,	/* Serial Synchronous Controller 0 */
+	5,	/* Serial Synchronous Controller 1 */
+	5,	/* Serial Synchronous Controller 2 */
+	0,	/* Timer Counter 0 */
+	0,	/* Timer Counter 1 */
+	0,	/* Timer Counter 2 */
+	0,	/* Timer Counter 3 */
+	0,	/* Timer Counter 4 */
+	0,	/* Timer Counter 5 */
+	3,	/* USB Host port */
+	3,	/* Ethernet MAC */
+	0,	/* Advanced Interrupt Controller (IRQ0) */
+	0,	/* Advanced Interrupt Controller (IRQ1) */
+	0,	/* Advanced Interrupt Controller (IRQ2) */
+	0,	/* Advanced Interrupt Controller (IRQ3) */
+	0,	/* Advanced Interrupt Controller (IRQ4) */
+	0,	/* Advanced Interrupt Controller (IRQ5) */
+	0	/* Advanced Interrupt Controller (IRQ6) */
+};
+
+void __init at91rm9200_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+	if (!priority)
+		priority = at91rm9200_default_irq_priority;
+
+	/* Initialize the AIC interrupt controller */
+	at91_aic_init(priority);
+
+	/* Enable GPIO interrupts */
+	at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
new file mode 100644
index 0000000..2624a4f
--- /dev/null
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -0,0 +1,879 @@
+/*
+ * arch/arm/mach-at91/at91rm9200_devices.c
+ *
+ *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *  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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/at91rm9200_mc.h>
+
+#include "generic.h"
+
+#define SZ_512	0x00000200
+#define SZ_256	0x00000100
+#define SZ_16	0x00000010
+
+/* --------------------------------------------------------------------
+ *  USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+	[0] = {
+		.start	= AT91RM9200_UHP_BASE,
+		.end	= AT91RM9200_UHP_BASE + SZ_1M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91RM9200_ID_UHP,
+		.end	= AT91RM9200_ID_UHP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91rm9200_usbh_device = {
+	.name		= "at91_ohci",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &ohci_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &usbh_data,
+	},
+	.resource	= usbh_resources,
+	.num_resources	= ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+	if (!data)
+		return;
+
+	usbh_data = *data;
+	platform_device_register(&at91rm9200_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+	[0] = {
+		.start	= AT91RM9200_BASE_UDP,
+		.end	= AT91RM9200_BASE_UDP + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91RM9200_ID_UDP,
+		.end	= AT91RM9200_ID_UDP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91rm9200_udc_device = {
+	.name		= "at91_udc",
+	.id		= -1,
+	.dev		= {
+				.platform_data		= &udc_data,
+	},
+	.resource	= udc_resources,
+	.num_resources	= ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+	if (!data)
+		return;
+
+	if (data->vbus_pin) {
+		at91_set_gpio_input(data->vbus_pin, 0);
+		at91_set_deglitch(data->vbus_pin, 1);
+	}
+	if (data->pullup_pin)
+		at91_set_gpio_output(data->pullup_pin, 0);
+
+	udc_data = *data;
+	platform_device_register(&at91rm9200_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE)
+static u64 eth_dmamask = 0xffffffffUL;
+static struct at91_eth_data eth_data;
+
+static struct resource eth_resources[] = {
+	[0] = {
+		.start	= AT91_VA_BASE_EMAC,
+		.end	= AT91_VA_BASE_EMAC + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91RM9200_ID_EMAC,
+		.end	= AT91RM9200_ID_EMAC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91rm9200_eth_device = {
+	.name		= "at91_ether",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &eth_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &eth_data,
+	},
+	.resource	= eth_resources,
+	.num_resources	= ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+	if (!data)
+		return;
+
+	if (data->phy_irq_pin) {
+		at91_set_gpio_input(data->phy_irq_pin, 0);
+		at91_set_deglitch(data->phy_irq_pin, 1);
+	}
+
+	/* Pins used for MII and RMII */
+	at91_set_A_periph(AT91_PIN_PA16, 0);	/* EMDIO */
+	at91_set_A_periph(AT91_PIN_PA15, 0);	/* EMDC */
+	at91_set_A_periph(AT91_PIN_PA14, 0);	/* ERXER */
+	at91_set_A_periph(AT91_PIN_PA13, 0);	/* ERX1 */
+	at91_set_A_periph(AT91_PIN_PA12, 0);	/* ERX0 */
+	at91_set_A_periph(AT91_PIN_PA11, 0);	/* ECRS_ECRSDV */
+	at91_set_A_periph(AT91_PIN_PA10, 0);	/* ETX1 */
+	at91_set_A_periph(AT91_PIN_PA9, 0);	/* ETX0 */
+	at91_set_A_periph(AT91_PIN_PA8, 0);	/* ETXEN */
+	at91_set_A_periph(AT91_PIN_PA7, 0);	/* ETXCK_EREFCK */
+
+	if (!data->is_rmii) {
+		at91_set_B_periph(AT91_PIN_PB19, 0);	/* ERXCK */
+		at91_set_B_periph(AT91_PIN_PB18, 0);	/* ECOL */
+		at91_set_B_periph(AT91_PIN_PB17, 0);	/* ERXDV */
+		at91_set_B_periph(AT91_PIN_PB16, 0);	/* ERX3 */
+		at91_set_B_periph(AT91_PIN_PB15, 0);	/* ERX2 */
+		at91_set_B_periph(AT91_PIN_PB14, 0);	/* ETXER */
+		at91_set_B_periph(AT91_PIN_PB13, 0);	/* ETX3 */
+		at91_set_B_periph(AT91_PIN_PB12, 0);	/* ETX2 */
+	}
+
+	eth_data = *data;
+	platform_device_register(&at91rm9200_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  Compact Flash / PCMCIA
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
+static struct at91_cf_data cf_data;
+
+#define CF_BASE		AT91_CHIPSELECT_4
+
+static struct resource cf_resources[] = {
+	[0] = {
+		.start	= CF_BASE,
+		/* ties up CS4, CS5 and CS6 */
+		.end	= 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,
+	},
+	.resource	= cf_resources,
+	.num_resources	= ARRAY_SIZE(cf_resources),
+};
+
+void __init at91_add_device_cf(struct at91_cf_data *data)
+{
+	unsigned int csa;
+
+	if (!data)
+		return;
+
+	data->chipselect = 4;		/* can only use EBI ChipSelect 4 */
+
+	/* 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);
+
+	/*
+	 * 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 */
+	);
+
+	/* input/irq */
+	if (data->irq_pin) {
+		at91_set_gpio_input(data->irq_pin, 1);
+		at91_set_deglitch(data->irq_pin, 1);
+	}
+	at91_set_gpio_input(data->det_pin, 1);
+	at91_set_deglitch(data->det_pin, 1);
+
+	/* outputs, initially off */
+	if (data->vcc_pin)
+		at91_set_gpio_output(data->vcc_pin, 0);
+	at91_set_gpio_output(data->rst_pin, 0);
+
+	/* force poweron defaults for these pins ... */
+	at91_set_A_periph(AT91_PIN_PC9, 0);	/* A25/CFRNW */
+	at91_set_A_periph(AT91_PIN_PC10, 0);	/* NCS4/CFCS */
+	at91_set_A_periph(AT91_PIN_PC11, 0);	/* NCS5/CFCE1 */
+	at91_set_A_periph(AT91_PIN_PC12, 0);	/* NCS6/CFCE2 */
+
+	/* nWAIT is _not_ a default setting */
+	at91_set_A_periph(AT91_PIN_PC6, 1);	/* nWAIT */
+
+	cf_data = *data;
+	platform_device_register(&at91rm9200_cf_device);
+}
+#else
+void __init at91_add_device_cf(struct at91_cf_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc_data;
+
+static struct resource mmc_resources[] = {
+	[0] = {
+		.start	= AT91RM9200_BASE_MCI,
+		.end	= AT91RM9200_BASE_MCI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91RM9200_ID_MCI,
+		.end	= AT91RM9200_ID_MCI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91rm9200_mmc_device = {
+	.name		= "at91_mci",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &mmc_data,
+	},
+	.resource	= mmc_resources,
+	.num_resources	= ARRAY_SIZE(mmc_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+	if (!data)
+		return;
+
+	/* input/irq */
+	if (data->det_pin) {
+		at91_set_gpio_input(data->det_pin, 1);
+		at91_set_deglitch(data->det_pin, 1);
+	}
+	if (data->wp_pin)
+		at91_set_gpio_input(data->wp_pin, 1);
+	if (data->vcc_pin)
+		at91_set_gpio_output(data->vcc_pin, 0);
+
+	/* CLK */
+	at91_set_A_periph(AT91_PIN_PA27, 0);
+
+	if (data->slot_b) {
+		/* CMD */
+		at91_set_B_periph(AT91_PIN_PA8, 1);
+
+		/* DAT0, maybe DAT1..DAT3 */
+		at91_set_B_periph(AT91_PIN_PA9, 1);
+		if (data->wire4) {
+			at91_set_B_periph(AT91_PIN_PA10, 1);
+			at91_set_B_periph(AT91_PIN_PA11, 1);
+			at91_set_B_periph(AT91_PIN_PA12, 1);
+		}
+	} else {
+		/* CMD */
+		at91_set_A_periph(AT91_PIN_PA28, 1);
+
+		/* DAT0, maybe DAT1..DAT3 */
+		at91_set_A_periph(AT91_PIN_PA29, 1);
+		if (data->wire4) {
+			at91_set_B_periph(AT91_PIN_PB3, 1);
+			at91_set_B_periph(AT91_PIN_PB4, 1);
+			at91_set_B_periph(AT91_PIN_PB5, 1);
+		}
+	}
+
+	mmc_data = *data;
+	platform_device_register(&at91rm9200_mmc_device);
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, 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;
+
+#define NAND_BASE	AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+	{
+		.start	= NAND_BASE,
+		.end	= NAND_BASE + SZ_8M - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device at91rm9200_nand_device = {
+	.name		= "at91_nand",
+	.id		= -1,
+	.dev		= {
+				.platform_data	= &nand_data,
+	},
+	.resource	= nand_resources,
+	.num_resources	= ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+	unsigned int csa;
+
+	if (!data)
+		return;
+
+	/* enable the address range of CS3 */
+	csa = at91_sys_read(AT91_EBI_CSA);
+	at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS3A_SMC_SMARTMEDIA);
+
+	/* set the bus interface characteristics */
+	at91_sys_write(AT91_SMC_CSR(3), AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN
+		| AT91_SMC_NWS_(5)
+		| AT91_SMC_TDF_(1)
+		| AT91_SMC_RWSETUP_(0)	/* tDS Data Set up Time 30 - ns */
+		| AT91_SMC_RWHOLD_(1)	/* tDH Data Hold Time 20 - ns */
+	);
+
+	/* 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(&at91rm9200_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 resource twi_resources[] = {
+	[0] = {
+		.start	= AT91RM9200_BASE_TWI,
+		.end	= AT91RM9200_BASE_TWI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91RM9200_ID_TWI,
+		.end	= AT91RM9200_ID_TWI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91rm9200_twi_device = {
+	.name		= "at91_i2c",
+	.id		= -1,
+	.resource	= twi_resources,
+	.num_resources	= ARRAY_SIZE(twi_resources),
+};
+
+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
+
+
+/* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi_resources[] = {
+	[0] = {
+		.start	= AT91RM9200_BASE_SPI,
+		.end	= AT91RM9200_BASE_SPI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91RM9200_ID_SPI,
+		.end	= AT91RM9200_ID_SPI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91rm9200_spi_device = {
+	.name		= "at91_spi",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &spi_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+	},
+	.resource	= spi_resources,
+	.num_resources	= ARRAY_SIZE(spi_resources),
+};
+
+static const unsigned spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+	int i;
+	unsigned long cs_pin;
+
+	at91_set_A_periph(AT91_PIN_PA0, 0);	/* MISO */
+	at91_set_A_periph(AT91_PIN_PA1, 0);	/* MOSI */
+	at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPCK */
+
+	/* Enable SPI chip-selects */
+	for (i = 0; i < nr_devices; i++) {
+		if (devices[i].controller_data)
+			cs_pin = (unsigned long) devices[i].controller_data;
+		else
+			cs_pin = spi_standard_cs[devices[i].chip_select];
+
+#ifdef CONFIG_SPI_AT91_MANUAL_CS
+		at91_set_gpio_output(cs_pin, 1);
+#else
+		at91_set_A_periph(cs_pin, 0);
+#endif
+
+		/* pass chip-select pin to driver */
+		devices[i].controller_data = (void *) cs_pin;
+	}
+
+	spi_register_board_info(devices, nr_devices);
+	at91_clock_associate("spi_clk", &at91rm9200_spi_device.dev, "spi");
+	platform_device_register(&at91rm9200_spi_device);
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  RTC
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
+static struct platform_device at91rm9200_rtc_device = {
+	.name		= "at91_rtc",
+	.id		= -1,
+	.num_resources	= 0,
+};
+
+static void __init at91_add_device_rtc(void)
+{
+	platform_device_register(&at91rm9200_rtc_device);
+}
+#else
+static void __init at91_add_device_rtc(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  Watchdog
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91RM9200_WATCHDOG) || defined(CONFIG_AT91RM9200_WATCHDOG_MODULE)
+static struct platform_device at91rm9200_wdt_device = {
+	.name		= "at91_wdt",
+	.id		= -1,
+	.num_resources	= 0,
+};
+
+static void __init at91_add_device_watchdog(void)
+{
+	platform_device_register(&at91rm9200_wdt_device);
+}
+#else
+static void __init at91_add_device_watchdog(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)
+{
+	/* Enable GPIO to access the LEDs */
+	at91_set_gpio_output(cpu_led, 1);
+	at91_set_gpio_output(timer_led, 1);
+
+	at91_leds_cpu	= cpu_led;
+	at91_leds_timer	= timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_ATMEL)
+static struct resource dbgu_resources[] = {
+	[0] = {
+		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
+		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_SYS,
+		.end	= AT91_ID_SYS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data dbgu_data = {
+	.use_dma_tx	= 0,
+	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91rm9200_dbgu_device = {
+	.name		= "atmel_usart",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &dbgu_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= dbgu_resources,
+	.num_resources	= ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA30, 0);		/* DRXD */
+	at91_set_A_periph(AT91_PIN_PA31, 1);		/* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+	[0] = {
+		.start	= AT91RM9200_BASE_US0,
+		.end	= AT91RM9200_BASE_US0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91RM9200_ID_US0,
+		.end	= AT91RM9200_ID_US0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart0_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart0_device = {
+	.name		= "atmel_usart",
+	.id		= 1,
+	.dev		= {
+				.platform_data	= &uart0_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart0_resources,
+	.num_resources	= ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA17, 1);		/* TXD0 */
+	at91_set_A_periph(AT91_PIN_PA18, 0);		/* RXD0 */
+	at91_set_A_periph(AT91_PIN_PA20, 0);		/* CTS0 */
+
+	/*
+	 * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21.
+	 *  We need to drive the pin manually.  Default is off (RTS is active low).
+	 */
+	at91_set_gpio_output(AT91_PIN_PA21, 1);
+}
+
+static struct resource uart1_resources[] = {
+	[0] = {
+		.start	= AT91RM9200_BASE_US1,
+		.end	= AT91RM9200_BASE_US1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91RM9200_ID_US1,
+		.end	= AT91RM9200_ID_US1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart1_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart1_device = {
+	.name		= "atmel_usart",
+	.id		= 2,
+	.dev		= {
+				.platform_data	= &uart1_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart1_resources,
+	.num_resources	= ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PB18, 0);		/* RI1 */
+	at91_set_A_periph(AT91_PIN_PB19, 0);		/* DTR1 */
+	at91_set_A_periph(AT91_PIN_PB20, 1);		/* TXD1 */
+	at91_set_A_periph(AT91_PIN_PB21, 0);		/* RXD1 */
+	at91_set_A_periph(AT91_PIN_PB23, 0);		/* DCD1 */
+	at91_set_A_periph(AT91_PIN_PB24, 0);		/* CTS1 */
+	at91_set_A_periph(AT91_PIN_PB25, 0);		/* DSR1 */
+	at91_set_A_periph(AT91_PIN_PB26, 0);		/* RTS1 */
+}
+
+static struct resource uart2_resources[] = {
+	[0] = {
+		.start	= AT91RM9200_BASE_US2,
+		.end	= AT91RM9200_BASE_US2 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91RM9200_ID_US2,
+		.end	= AT91RM9200_ID_US2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart2_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart2_device = {
+	.name		= "atmel_usart",
+	.id		= 3,
+	.dev		= {
+				.platform_data	= &uart2_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart2_resources,
+	.num_resources	= ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA22, 0);		/* RXD2 */
+	at91_set_A_periph(AT91_PIN_PA23, 1);		/* TXD2 */
+}
+
+static struct resource uart3_resources[] = {
+	[0] = {
+		.start	= AT91RM9200_BASE_US3,
+		.end	= AT91RM9200_BASE_US3 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91RM9200_ID_US3,
+		.end	= AT91RM9200_ID_US3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart3_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart3_device = {
+	.name		= "atmel_usart",
+	.id		= 4,
+	.dev		= {
+				.platform_data	= &uart3_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart3_resources,
+	.num_resources	= ARRAY_SIZE(uart3_resources),
+};
+
+static inline void configure_usart3_pins(void)
+{
+	at91_set_B_periph(AT91_PIN_PA5, 1);		/* TXD3 */
+	at91_set_B_periph(AT91_PIN_PA6, 0);		/* RXD3 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
+struct platform_device *atmel_default_console_device;	/* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+	int i;
+
+	/* Fill in list of supported UARTs */
+	for (i = 0; i < config->nr_tty; i++) {
+		switch (config->tty_map[i]) {
+			case 0:
+				configure_usart0_pins();
+				at91_uarts[i] = &at91rm9200_uart0_device;
+				at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart");
+				break;
+			case 1:
+				configure_usart1_pins();
+				at91_uarts[i] = &at91rm9200_uart1_device;
+				at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart");
+				break;
+			case 2:
+				configure_usart2_pins();
+				at91_uarts[i] = &at91rm9200_uart2_device;
+				at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart");
+				break;
+			case 3:
+				configure_usart3_pins();
+				at91_uarts[i] = &at91rm9200_uart3_device;
+				at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart");
+				break;
+			case 4:
+				configure_dbgu_pins();
+				at91_uarts[i] = &at91rm9200_dbgu_device;
+				at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart");
+				break;
+			default:
+				continue;
+		}
+		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
+	}
+
+	/* Set serial console device */
+	if (config->console_tty < ATMEL_MAX_UART)
+		atmel_default_console_device = at91_uarts[config->console_tty];
+	if (!atmel_default_console_device)
+		printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+	int i;
+
+	for (i = 0; i < ATMEL_MAX_UART; i++) {
+		if (at91_uarts[i])
+			platform_device_register(at91_uarts[i]);
+	}
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+	at91_add_device_rtc();
+	at91_add_device_watchdog();
+	return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
new file mode 100644
index 0000000..949199a
--- /dev/null
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -0,0 +1,146 @@
+/*
+ * linux/arch/arm/mach-at91/at91rm9200_time.c
+ *
+ *  Copyright (C) 2003 SAN People
+ *  Copyright (C) 2003 ATMEL
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+
+#include <asm/arch/at91_st.h>
+
+static unsigned long last_crtr;
+
+/*
+ * The ST_CRTR is updated asynchronously to the master clock.  It is therefore
+ *  necessary to read it twice (with the same value) to ensure accuracy.
+ */
+static inline unsigned long read_CRTR(void) {
+	unsigned long x1, x2;
+
+	do {
+		x1 = at91_sys_read(AT91_ST_CRTR);
+		x2 = at91_sys_read(AT91_ST_CRTR);
+	} while (x1 != x2);
+
+	return x1;
+}
+
+/*
+ * Returns number of microseconds since last timer interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeofday()
+ *  'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
+ *  'tick' is usecs per jiffy (linux/timex.h).
+ */
+static unsigned long at91rm9200_gettimeoffset(void)
+{
+	unsigned long elapsed;
+
+	elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV;
+
+	return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
+{
+	if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) {	/* This is a shared interrupt */
+		write_seqlock(&xtime_lock);
+
+		while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) {
+			timer_tick();
+			last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV;
+		}
+
+		write_sequnlock(&xtime_lock);
+
+		return IRQ_HANDLED;
+	}
+	else
+		return IRQ_NONE;		/* not handled */
+}
+
+static struct irqaction at91rm9200_timer_irq = {
+	.name		= "at91_tick",
+	.flags		= IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER,
+	.handler	= at91rm9200_timer_interrupt
+};
+
+void at91rm9200_timer_reset(void)
+{
+	last_crtr = 0;
+
+	/* Real time counter incremented every 30.51758 microseconds */
+	at91_sys_write(AT91_ST_RTMR, 1);
+
+	/* Set Period Interval timer */
+	at91_sys_write(AT91_ST_PIMR, LATCH);
+
+	/* Clear any pending interrupts */
+	(void) at91_sys_read(AT91_ST_SR);
+
+	/* Enable Period Interval Timer interrupt */
+	at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
+}
+
+/*
+ * Set up timer interrupt.
+ */
+void __init at91rm9200_timer_init(void)
+{
+	/* Disable all timer interrupts */
+	at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
+	(void) at91_sys_read(AT91_ST_SR);	/* Clear any pending interrupts */
+
+	/* Make IRQs happen for the system timer */
+	setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
+
+	/* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */
+	tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE;
+
+	/* Initialize and enable the timer interrupt */
+	at91rm9200_timer_reset();
+}
+
+#ifdef CONFIG_PM
+static void at91rm9200_timer_suspend(void)
+{
+	/* disable Period Interval Timer interrupt */
+	at91_sys_write(AT91_ST_IDR, AT91_ST_PITS);
+}
+#else
+#define at91rm9200_timer_suspend	NULL
+#endif
+
+struct sys_timer at91rm9200_timer = {
+	.init		= at91rm9200_timer_init,
+	.offset		= at91rm9200_gettimeoffset,
+	.suspend	= at91rm9200_timer_suspend,
+	.resume		= at91rm9200_timer_reset,
+};
+
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
new file mode 100644
index 0000000..6ea41d8
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -0,0 +1,367 @@
+/*
+ * arch/arm/mach-at91/at91sam9260.c
+ *
+ *  Copyright (C) 2006 SAN People
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/at91sam9260.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91sam9260_io_desc[] __initdata = {
+	{
+		.virtual	= AT91_VA_BASE_SYS,
+		.pfn		= __phys_to_pfn(AT91_BASE_SYS),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}
+};
+
+static struct map_desc at91sam9260_sram_desc[] __initdata = {
+	{
+		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE,
+		.pfn		= __phys_to_pfn(AT91SAM9260_SRAM0_BASE),
+		.length		= AT91SAM9260_SRAM0_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE - AT91SAM9260_SRAM1_SIZE,
+		.pfn		= __phys_to_pfn(AT91SAM9260_SRAM1_BASE),
+		.length		= AT91SAM9260_SRAM1_SIZE,
+		.type		= MT_DEVICE,
+	}
+};
+
+static struct map_desc at91sam9xe_sram_desc[] __initdata = {
+	{
+		.pfn		= __phys_to_pfn(AT91SAM9XE_SRAM_BASE),
+		.type		= MT_DEVICE,
+	}
+};
+
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+	.name		= "pioA_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_PIOA,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+	.name		= "pioB_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_PIOB,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+	.name		= "pioC_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_PIOC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk adc_clk = {
+	.name		= "adc_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_ADC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+	.name		= "usart0_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_US0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+	.name		= "usart1_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_US1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+	.name		= "usart2_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_US2,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+	.name		= "mci_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_MCI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+	.name		= "udc_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_UDP,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+	.name		= "twi_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_TWI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+	.name		= "spi0_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_SPI0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+	.name		= "spi1_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_SPI1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc0_clk = {
+	.name		= "tc0_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_TC0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+	.name		= "tc1_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_TC1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+	.name		= "tc2_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_TC2,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+	.name		= "ohci_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_UHP,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk macb_clk = {
+	.name		= "macb_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_EMAC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk isi_clk = {
+	.name		= "isi_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_ISI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart3_clk = {
+	.name		= "usart3_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_US3,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart4_clk = {
+	.name		= "usart4_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_US4,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart5_clk = {
+	.name		= "usart5_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_US5,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc3_clk = {
+	.name		= "tc3_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_TC3,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc4_clk = {
+	.name		= "tc4_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_TC4,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc5_clk = {
+	.name		= "tc5_clk",
+	.pmc_mask	= 1 << AT91SAM9260_ID_TC5,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+	&pioA_clk,
+	&pioB_clk,
+	&pioC_clk,
+	&adc_clk,
+	&usart0_clk,
+	&usart1_clk,
+	&usart2_clk,
+	&mmc_clk,
+	&udc_clk,
+	&twi_clk,
+	&spi0_clk,
+	&spi1_clk,
+	// ssc
+	&tc0_clk,
+	&tc1_clk,
+	&tc2_clk,
+	&ohci_clk,
+	&macb_clk,
+	&isi_clk,
+	&usart3_clk,
+	&usart4_clk,
+	&usart5_clk,
+	&tc3_clk,
+	&tc4_clk,
+	&tc5_clk,
+	// irq0 .. irq2
+};
+
+/*
+ * The two programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+	.name		= "pck0",
+	.pmc_mask	= AT91_PMC_PCK0,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 0,
+};
+static struct clk pck1 = {
+	.name		= "pck1",
+	.pmc_mask	= AT91_PMC_PCK1,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 1,
+};
+
+static void __init at91sam9260_register_clocks(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+		clk_register(periph_clocks[i]);
+
+	clk_register(&pck0);
+	clk_register(&pck1);
+}
+
+/* --------------------------------------------------------------------
+ *  GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91sam9260_gpio[] = {
+	{
+		.id		= AT91SAM9260_ID_PIOA,
+		.offset		= AT91_PIOA,
+		.clock		= &pioA_clk,
+	}, {
+		.id		= AT91SAM9260_ID_PIOB,
+		.offset		= AT91_PIOB,
+		.clock		= &pioB_clk,
+	}, {
+		.id		= AT91SAM9260_ID_PIOC,
+		.offset		= AT91_PIOC,
+		.clock		= &pioC_clk,
+	}
+};
+
+static void at91sam9260_reset(void)
+{
+	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+}
+
+
+/* --------------------------------------------------------------------
+ *  AT91SAM9260 processor initialization
+ * -------------------------------------------------------------------- */
+
+static void __init at91sam9xe_initialize(void)
+{
+	unsigned long cidr, sram_size;
+
+	cidr = at91_sys_read(AT91_DBGU_CIDR);
+
+	switch (cidr & AT91_CIDR_SRAMSIZ) {
+		case AT91_CIDR_SRAMSIZ_32K:
+			sram_size = 2 * SZ_16K;
+			break;
+		case AT91_CIDR_SRAMSIZ_16K:
+		default:
+			sram_size = SZ_16K;
+	}
+
+	at91sam9xe_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size;
+	at91sam9xe_sram_desc->length = sram_size;
+
+	iotable_init(at91sam9xe_sram_desc, ARRAY_SIZE(at91sam9xe_sram_desc));
+}
+
+void __init at91sam9260_initialize(unsigned long main_clock)
+{
+	/* Map peripherals */
+	iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
+
+	if (cpu_is_at91sam9xe())
+		at91sam9xe_initialize();
+	else
+		iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
+
+	at91_arch_reset = at91sam9260_reset;
+	at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
+			| (1 << AT91SAM9260_ID_IRQ2);
+
+	/* Init clock subsystem */
+	at91_clock_init(main_clock);
+
+	/* Register the processor-specific clocks */
+	at91sam9260_register_clocks();
+
+	/* Register GPIO subsystem */
+	at91_gpio_init(at91sam9260_gpio, 3);
+}
+
+/* --------------------------------------------------------------------
+ *  Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
+	7,	/* Advanced Interrupt Controller */
+	7,	/* System Peripherals */
+	0,	/* Parallel IO Controller A */
+	0,	/* Parallel IO Controller B */
+	0,	/* Parallel IO Controller C */
+	0,	/* Analog-to-Digital Converter */
+	6,	/* USART 0 */
+	6,	/* USART 1 */
+	6,	/* USART 2 */
+	0,	/* Multimedia Card Interface */
+	4,	/* USB Device Port */
+	0,	/* Two-Wire Interface */
+	6,	/* Serial Peripheral Interface 0 */
+	6,	/* Serial Peripheral Interface 1 */
+	5,	/* Serial Synchronous Controller */
+	0,
+	0,
+	0,	/* Timer Counter 0 */
+	0,	/* Timer Counter 1 */
+	0,	/* Timer Counter 2 */
+	3,	/* USB Host port */
+	3,	/* Ethernet */
+	0,	/* Image Sensor Interface */
+	6,	/* USART 3 */
+	6,	/* USART 4 */
+	6,	/* USART 5 */
+	0,	/* Timer Counter 3 */
+	0,	/* Timer Counter 4 */
+	0,	/* Timer Counter 5 */
+	0,	/* Advanced Interrupt Controller */
+	0,	/* Advanced Interrupt Controller */
+	0,	/* Advanced Interrupt Controller */
+};
+
+void __init at91sam9260_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+	if (!priority)
+		priority = at91sam9260_default_irq_priority;
+
+	/* Initialize the AIC interrupt controller */
+	at91_aic_init(priority);
+
+	/* Enable GPIO interrupts */
+	at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
new file mode 100644
index 0000000..f7d342c
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -0,0 +1,871 @@
+/*
+ * arch/arm/mach-at91/at91sam9260_devices.c
+ *
+ *  Copyright (C) 2006 Atmel
+ *
+ * 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/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam9260.h>
+#include <asm/arch/at91sam926x_mc.h>
+#include <asm/arch/at91sam9260_matrix.h>
+
+#include "generic.h"
+
+#define SZ_512	0x00000200
+#define SZ_256	0x00000100
+#define SZ_16	0x00000010
+
+/* --------------------------------------------------------------------
+ *  USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_UHP_BASE,
+		.end	= AT91SAM9260_UHP_BASE + SZ_1M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_UHP,
+		.end	= AT91SAM9260_ID_UHP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_usbh_device = {
+	.name		= "at91_ohci",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &ohci_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &usbh_data,
+	},
+	.resource	= usbh_resources,
+	.num_resources	= ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+	if (!data)
+		return;
+
+	usbh_data = *data;
+	platform_device_register(&at91_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_UDP,
+		.end	= AT91SAM9260_BASE_UDP + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_UDP,
+		.end	= AT91SAM9260_ID_UDP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_udc_device = {
+	.name		= "at91_udc",
+	.id		= -1,
+	.dev		= {
+				.platform_data		= &udc_data,
+	},
+	.resource	= udc_resources,
+	.num_resources	= ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+	if (!data)
+		return;
+
+	if (data->vbus_pin) {
+		at91_set_gpio_input(data->vbus_pin, 0);
+		at91_set_deglitch(data->vbus_pin, 1);
+	}
+
+	/* Pullup pin is handled internally by USB device peripheral */
+
+	udc_data = *data;
+	platform_device_register(&at91_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
+static u64 eth_dmamask = 0xffffffffUL;
+static struct at91_eth_data eth_data;
+
+static struct resource eth_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_EMAC,
+		.end	= AT91SAM9260_BASE_EMAC + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_EMAC,
+		.end	= AT91SAM9260_ID_EMAC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9260_eth_device = {
+	.name		= "macb",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &eth_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &eth_data,
+	},
+	.resource	= eth_resources,
+	.num_resources	= ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+	if (!data)
+		return;
+
+	if (data->phy_irq_pin) {
+		at91_set_gpio_input(data->phy_irq_pin, 0);
+		at91_set_deglitch(data->phy_irq_pin, 1);
+	}
+
+	/* Pins used for MII and RMII */
+	at91_set_A_periph(AT91_PIN_PA19, 0);	/* ETXCK_EREFCK */
+	at91_set_A_periph(AT91_PIN_PA17, 0);	/* ERXDV */
+	at91_set_A_periph(AT91_PIN_PA14, 0);	/* ERX0 */
+	at91_set_A_periph(AT91_PIN_PA15, 0);	/* ERX1 */
+	at91_set_A_periph(AT91_PIN_PA18, 0);	/* ERXER */
+	at91_set_A_periph(AT91_PIN_PA16, 0);	/* ETXEN */
+	at91_set_A_periph(AT91_PIN_PA12, 0);	/* ETX0 */
+	at91_set_A_periph(AT91_PIN_PA13, 0);	/* ETX1 */
+	at91_set_A_periph(AT91_PIN_PA21, 0);	/* EMDIO */
+	at91_set_A_periph(AT91_PIN_PA20, 0);	/* EMDC */
+
+	if (!data->is_rmii) {
+		at91_set_B_periph(AT91_PIN_PA28, 0);	/* ECRS */
+		at91_set_B_periph(AT91_PIN_PA29, 0);	/* ECOL */
+		at91_set_B_periph(AT91_PIN_PA25, 0);	/* ERX2 */
+		at91_set_B_periph(AT91_PIN_PA26, 0);	/* ERX3 */
+		at91_set_B_periph(AT91_PIN_PA27, 0);	/* ERXCK */
+		at91_set_B_periph(AT91_PIN_PA23, 0);	/* ETX2 */
+		at91_set_B_periph(AT91_PIN_PA24, 0);	/* ETX3 */
+		at91_set_B_periph(AT91_PIN_PA22, 0);	/* ETXER */
+	}
+
+	eth_data = *data;
+	platform_device_register(&at91sam9260_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc_data;
+
+static struct resource mmc_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_MCI,
+		.end	= AT91SAM9260_BASE_MCI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_MCI,
+		.end	= AT91SAM9260_ID_MCI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9260_mmc_device = {
+	.name		= "at91_mci",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &mmc_data,
+	},
+	.resource	= mmc_resources,
+	.num_resources	= ARRAY_SIZE(mmc_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+	if (!data)
+		return;
+
+	/* input/irq */
+	if (data->det_pin) {
+		at91_set_gpio_input(data->det_pin, 1);
+		at91_set_deglitch(data->det_pin, 1);
+	}
+	if (data->wp_pin)
+		at91_set_gpio_input(data->wp_pin, 1);
+	if (data->vcc_pin)
+		at91_set_gpio_output(data->vcc_pin, 0);
+
+	/* CLK */
+	at91_set_A_periph(AT91_PIN_PA8, 0);
+
+	if (data->slot_b) {
+		/* CMD */
+		at91_set_B_periph(AT91_PIN_PA1, 1);
+
+		/* DAT0, maybe DAT1..DAT3 */
+		at91_set_B_periph(AT91_PIN_PA0, 1);
+		if (data->wire4) {
+			at91_set_B_periph(AT91_PIN_PA5, 1);
+			at91_set_B_periph(AT91_PIN_PA4, 1);
+			at91_set_B_periph(AT91_PIN_PA3, 1);
+		}
+	} else {
+		/* CMD */
+		at91_set_A_periph(AT91_PIN_PA7, 1);
+
+		/* DAT0, maybe DAT1..DAT3 */
+		at91_set_A_periph(AT91_PIN_PA6, 1);
+		if (data->wire4) {
+			at91_set_A_periph(AT91_PIN_PA9, 1);
+			at91_set_A_periph(AT91_PIN_PA10, 1);
+			at91_set_A_periph(AT91_PIN_PA11, 1);
+		}
+	}
+
+	mmc_data = *data;
+	platform_device_register(&at91sam9260_mmc_device);
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, 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;
+
+#define NAND_BASE	AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+	{
+		.start	= NAND_BASE,
+		.end	= NAND_BASE + SZ_8M - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device at91sam9260_nand_device = {
+	.name		= "at91_nand",
+	.id		= -1,
+	.dev		= {
+				.platform_data	= &nand_data,
+	},
+	.resource	= nand_resources,
+	.num_resources	= ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+	unsigned long csa, mode;
+
+	if (!data)
+		return;
+
+	csa = at91_sys_read(AT91_MATRIX_EBICSA);
+	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC);
+
+	/* set the bus interface characteristics */
+	at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
+			| AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
+
+	at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5)
+			| AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5));
+
+	at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7));
+
+	if (data->bus_width_16)
+		mode = AT91_SMC_DBW_16;
+	else
+		mode = AT91_SMC_DBW_8;
+	at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1));
+
+	/* 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);
+
+	nand_data = *data;
+	platform_device_register(&at91sam9260_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 resource twi_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_TWI,
+		.end	= AT91SAM9260_BASE_TWI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_TWI,
+		.end	= AT91SAM9260_ID_TWI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9260_twi_device = {
+	.name		= "at91_i2c",
+	.id		= -1,
+	.resource	= twi_resources,
+	.num_resources	= ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+	/* pins used for TWI interface */
+	at91_set_A_periph(AT91_PIN_PA23, 0);		/* TWD */
+	at91_set_multi_drive(AT91_PIN_PA23, 1);
+
+	at91_set_A_periph(AT91_PIN_PA24, 0);		/* TWCK */
+	at91_set_multi_drive(AT91_PIN_PA24, 1);
+
+	platform_device_register(&at91sam9260_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi0_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_SPI0,
+		.end	= AT91SAM9260_BASE_SPI0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_SPI0,
+		.end	= AT91SAM9260_ID_SPI0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9260_spi0_device = {
+	.name		= "atmel_spi",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &spi_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+	},
+	.resource	= spi0_resources,
+	.num_resources	= ARRAY_SIZE(spi0_resources),
+};
+
+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PC11, AT91_PIN_PC16, AT91_PIN_PC17 };
+
+static struct resource spi1_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_SPI1,
+		.end	= AT91SAM9260_BASE_SPI1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_SPI1,
+		.end	= AT91SAM9260_ID_SPI1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9260_spi1_device = {
+	.name		= "atmel_spi",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &spi_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+	},
+	.resource	= spi1_resources,
+	.num_resources	= ARRAY_SIZE(spi1_resources),
+};
+
+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PC5, AT91_PIN_PC4, AT91_PIN_PC3 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+	int i;
+	unsigned long cs_pin;
+	short enable_spi0 = 0;
+	short enable_spi1 = 0;
+
+	/* Choose SPI chip-selects */
+	for (i = 0; i < nr_devices; i++) {
+		if (devices[i].controller_data)
+			cs_pin = (unsigned long) devices[i].controller_data;
+		else if (devices[i].bus_num == 0)
+			cs_pin = spi0_standard_cs[devices[i].chip_select];
+		else
+			cs_pin = spi1_standard_cs[devices[i].chip_select];
+
+		if (devices[i].bus_num == 0)
+			enable_spi0 = 1;
+		else
+			enable_spi1 = 1;
+
+		/* enable chip-select pin */
+		at91_set_gpio_output(cs_pin, 1);
+
+		/* pass chip-select pin to driver */
+		devices[i].controller_data = (void *) cs_pin;
+	}
+
+	spi_register_board_info(devices, nr_devices);
+
+	/* Configure SPI bus(es) */
+	if (enable_spi0) {
+		at91_set_A_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */
+		at91_set_A_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */
+		at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPI1_SPCK */
+
+		at91_clock_associate("spi0_clk", &at91sam9260_spi0_device.dev, "spi_clk");
+		platform_device_register(&at91sam9260_spi0_device);
+	}
+	if (enable_spi1) {
+		at91_set_A_periph(AT91_PIN_PB0, 0);	/* SPI1_MISO */
+		at91_set_A_periph(AT91_PIN_PB1, 0);	/* SPI1_MOSI */
+		at91_set_A_periph(AT91_PIN_PB2, 0);	/* SPI1_SPCK */
+
+		at91_clock_associate("spi1_clk", &at91sam9260_spi1_device.dev, "spi_clk");
+		platform_device_register(&at91sam9260_spi1_device);
+	}
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#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)
+{
+	/* Enable GPIO to access the LEDs */
+	at91_set_gpio_output(cpu_led, 1);
+	at91_set_gpio_output(timer_led, 1);
+
+	at91_leds_cpu	= cpu_led;
+	at91_leds_timer	= timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+#if defined(CONFIG_SERIAL_ATMEL)
+static struct resource dbgu_resources[] = {
+	[0] = {
+		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
+		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_SYS,
+		.end	= AT91_ID_SYS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data dbgu_data = {
+	.use_dma_tx	= 0,
+	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91sam9260_dbgu_device = {
+	.name		= "atmel_usart",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &dbgu_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= dbgu_resources,
+	.num_resources	= ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PB14, 0);		/* DRXD */
+	at91_set_A_periph(AT91_PIN_PB15, 1);		/* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_US0,
+		.end	= AT91SAM9260_BASE_US0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_US0,
+		.end	= AT91SAM9260_ID_US0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart0_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9260_uart0_device = {
+	.name		= "atmel_usart",
+	.id		= 1,
+	.dev		= {
+				.platform_data	= &uart0_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart0_resources,
+	.num_resources	= ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PB4, 1);		/* TXD0 */
+	at91_set_A_periph(AT91_PIN_PB5, 0);		/* RXD0 */
+	at91_set_A_periph(AT91_PIN_PB26, 0);		/* RTS0 */
+	at91_set_A_periph(AT91_PIN_PB27, 0);		/* CTS0 */
+	at91_set_A_periph(AT91_PIN_PB24, 0);		/* DTR0 */
+	at91_set_A_periph(AT91_PIN_PB22, 0);		/* DSR0 */
+	at91_set_A_periph(AT91_PIN_PB23, 0);		/* DCD0 */
+	at91_set_A_periph(AT91_PIN_PB25, 0);		/* RI0 */
+}
+
+static struct resource uart1_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_US1,
+		.end	= AT91SAM9260_BASE_US1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_US1,
+		.end	= AT91SAM9260_ID_US1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart1_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9260_uart1_device = {
+	.name		= "atmel_usart",
+	.id		= 2,
+	.dev		= {
+				.platform_data	= &uart1_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart1_resources,
+	.num_resources	= ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PB6, 1);		/* TXD1 */
+	at91_set_A_periph(AT91_PIN_PB7, 0);		/* RXD1 */
+	at91_set_A_periph(AT91_PIN_PB28, 0);		/* RTS1 */
+	at91_set_A_periph(AT91_PIN_PB29, 0);		/* CTS1 */
+}
+
+static struct resource uart2_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_US2,
+		.end	= AT91SAM9260_BASE_US2 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_US2,
+		.end	= AT91SAM9260_ID_US2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart2_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9260_uart2_device = {
+	.name		= "atmel_usart",
+	.id		= 3,
+	.dev		= {
+				.platform_data	= &uart2_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart2_resources,
+	.num_resources	= ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PB8, 1);		/* TXD2 */
+	at91_set_A_periph(AT91_PIN_PB9, 0);		/* RXD2 */
+}
+
+static struct resource uart3_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_US3,
+		.end	= AT91SAM9260_BASE_US3 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_US3,
+		.end	= AT91SAM9260_ID_US3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart3_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9260_uart3_device = {
+	.name		= "atmel_usart",
+	.id		= 4,
+	.dev		= {
+				.platform_data	= &uart3_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart3_resources,
+	.num_resources	= ARRAY_SIZE(uart3_resources),
+};
+
+static inline void configure_usart3_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PB10, 1);		/* TXD3 */
+	at91_set_A_periph(AT91_PIN_PB11, 0);		/* RXD3 */
+}
+
+static struct resource uart4_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_US4,
+		.end	= AT91SAM9260_BASE_US4 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_US4,
+		.end	= AT91SAM9260_ID_US4,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart4_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9260_uart4_device = {
+	.name		= "atmel_usart",
+	.id		= 5,
+	.dev		= {
+				.platform_data	= &uart4_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart4_resources,
+	.num_resources	= ARRAY_SIZE(uart4_resources),
+};
+
+static inline void configure_usart4_pins(void)
+{
+	at91_set_B_periph(AT91_PIN_PA31, 1);		/* TXD4 */
+	at91_set_B_periph(AT91_PIN_PA30, 0);		/* RXD4 */
+}
+
+static struct resource uart5_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_US5,
+		.end	= AT91SAM9260_BASE_US5 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_US5,
+		.end	= AT91SAM9260_ID_US5,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart5_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9260_uart5_device = {
+	.name		= "atmel_usart",
+	.id		= 6,
+	.dev		= {
+				.platform_data	= &uart5_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart5_resources,
+	.num_resources	= ARRAY_SIZE(uart5_resources),
+};
+
+static inline void configure_usart5_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PB12, 1);		/* TXD5 */
+	at91_set_A_periph(AT91_PIN_PB13, 0);		/* RXD5 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
+struct platform_device *atmel_default_console_device;	/* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+	int i;
+
+	/* Fill in list of supported UARTs */
+	for (i = 0; i < config->nr_tty; i++) {
+		switch (config->tty_map[i]) {
+			case 0:
+				configure_usart0_pins();
+				at91_uarts[i] = &at91sam9260_uart0_device;
+				at91_clock_associate("usart0_clk", &at91sam9260_uart0_device.dev, "usart");
+				break;
+			case 1:
+				configure_usart1_pins();
+				at91_uarts[i] = &at91sam9260_uart1_device;
+				at91_clock_associate("usart1_clk", &at91sam9260_uart1_device.dev, "usart");
+				break;
+			case 2:
+				configure_usart2_pins();
+				at91_uarts[i] = &at91sam9260_uart2_device;
+				at91_clock_associate("usart2_clk", &at91sam9260_uart2_device.dev, "usart");
+				break;
+			case 3:
+				configure_usart3_pins();
+				at91_uarts[i] = &at91sam9260_uart3_device;
+				at91_clock_associate("usart3_clk", &at91sam9260_uart3_device.dev, "usart");
+				break;
+			case 4:
+				configure_usart4_pins();
+				at91_uarts[i] = &at91sam9260_uart4_device;
+				at91_clock_associate("usart4_clk", &at91sam9260_uart4_device.dev, "usart");
+				break;
+			case 5:
+				configure_usart5_pins();
+				at91_uarts[i] = &at91sam9260_uart5_device;
+				at91_clock_associate("usart5_clk", &at91sam9260_uart5_device.dev, "usart");
+				break;
+			case 6:
+				configure_dbgu_pins();
+				at91_uarts[i] = &at91sam9260_dbgu_device;
+				at91_clock_associate("mck", &at91sam9260_dbgu_device.dev, "usart");
+				break;
+			default:
+				continue;
+		}
+		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
+	}
+
+	/* Set serial console device */
+	if (config->console_tty < ATMEL_MAX_UART)
+		atmel_default_console_device = at91_uarts[config->console_tty];
+	if (!atmel_default_console_device)
+		printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+	int i;
+
+	for (i = 0; i < ATMEL_MAX_UART; i++) {
+		if (at91_uarts[i])
+			platform_device_register(at91_uarts[i]);
+	}
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+	return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
new file mode 100644
index 0000000..784d1e6
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -0,0 +1,307 @@
+/*
+ * arch/arm/mach-at91/at91sam9261.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/at91sam9261.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91sam9261_io_desc[] __initdata = {
+	{
+		.virtual	= AT91_VA_BASE_SYS,
+		.pfn		= __phys_to_pfn(AT91_BASE_SYS),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE,
+		.pfn		= __phys_to_pfn(AT91SAM9261_SRAM_BASE),
+		.length		= AT91SAM9261_SRAM_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+	.name		= "pioA_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_PIOA,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+	.name		= "pioB_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_PIOB,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+	.name		= "pioC_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_PIOC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+	.name		= "usart0_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_US0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+	.name		= "usart1_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_US1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+	.name		= "usart2_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_US2,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+	.name		= "mci_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_MCI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+	.name		= "udc_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_UDP,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+	.name		= "twi_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_TWI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+	.name		= "spi0_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_SPI0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+	.name		= "spi1_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_SPI1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc0_clk = {
+	.name		= "tc0_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_TC0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+	.name		= "tc1_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_TC1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+	.name		= "tc2_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_TC2,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+	.name		= "ohci_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_UHP,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk lcdc_clk = {
+	.name		= "lcdc_clk",
+	.pmc_mask	= 1 << AT91SAM9261_ID_LCDC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+	&pioA_clk,
+	&pioB_clk,
+	&pioC_clk,
+	&usart0_clk,
+	&usart1_clk,
+	&usart2_clk,
+	&mmc_clk,
+	&udc_clk,
+	&twi_clk,
+	&spi0_clk,
+	&spi1_clk,
+	// ssc 0 .. ssc2
+	&tc0_clk,
+	&tc1_clk,
+	&tc2_clk,
+	&ohci_clk,
+	&lcdc_clk,
+	// irq0 .. irq2
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+	.name		= "pck0",
+	.pmc_mask	= AT91_PMC_PCK0,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 0,
+};
+static struct clk pck1 = {
+	.name		= "pck1",
+	.pmc_mask	= AT91_PMC_PCK1,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 1,
+};
+static struct clk pck2 = {
+	.name		= "pck2",
+	.pmc_mask	= AT91_PMC_PCK2,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 2,
+};
+static struct clk pck3 = {
+	.name		= "pck3",
+	.pmc_mask	= AT91_PMC_PCK3,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 3,
+};
+
+/* HClocks */
+static struct clk hck0 = {
+	.name		= "hck0",
+	.pmc_mask	= AT91_PMC_HCK0,
+	.type		= CLK_TYPE_SYSTEM,
+	.id		= 0,
+};
+static struct clk hck1 = {
+	.name		= "hck1",
+	.pmc_mask	= AT91_PMC_HCK1,
+	.type		= CLK_TYPE_SYSTEM,
+	.id		= 1,
+};
+
+static void __init at91sam9261_register_clocks(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+		clk_register(periph_clocks[i]);
+
+	clk_register(&pck0);
+	clk_register(&pck1);
+	clk_register(&pck2);
+	clk_register(&pck3);
+
+	clk_register(&hck0);
+	clk_register(&hck1);
+}
+
+/* --------------------------------------------------------------------
+ *  GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91sam9261_gpio[] = {
+	{
+		.id		= AT91SAM9261_ID_PIOA,
+		.offset		= AT91_PIOA,
+		.clock		= &pioA_clk,
+	}, {
+		.id		= AT91SAM9261_ID_PIOB,
+		.offset		= AT91_PIOB,
+		.clock		= &pioB_clk,
+	}, {
+		.id		= AT91SAM9261_ID_PIOC,
+		.offset		= AT91_PIOC,
+		.clock		= &pioC_clk,
+	}
+};
+
+static void at91sam9261_reset(void)
+{
+	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+}
+
+
+/* --------------------------------------------------------------------
+ *  AT91SAM9261 processor initialization
+ * -------------------------------------------------------------------- */
+
+void __init at91sam9261_initialize(unsigned long main_clock)
+{
+	/* Map peripherals */
+	iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
+
+	at91_arch_reset = at91sam9261_reset;
+	at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
+			| (1 << AT91SAM9261_ID_IRQ2);
+
+	/* Init clock subsystem */
+	at91_clock_init(main_clock);
+
+	/* Register the processor-specific clocks */
+	at91sam9261_register_clocks();
+
+	/* Register GPIO subsystem */
+	at91_gpio_init(at91sam9261_gpio, 3);
+}
+
+/* --------------------------------------------------------------------
+ *  Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
+	7,	/* Advanced Interrupt Controller */
+	7,	/* System Peripherals */
+	0,	/* Parallel IO Controller A */
+	0,	/* Parallel IO Controller B */
+	0,	/* Parallel IO Controller C */
+	0,
+	6,	/* USART 0 */
+	6,	/* USART 1 */
+	6,	/* USART 2 */
+	0,	/* Multimedia Card Interface */
+	4,	/* USB Device Port */
+	0,	/* Two-Wire Interface */
+	6,	/* Serial Peripheral Interface 0 */
+	6,	/* Serial Peripheral Interface 1 */
+	5,	/* Serial Synchronous Controller 0 */
+	5,	/* Serial Synchronous Controller 1 */
+	5,	/* Serial Synchronous Controller 2 */
+	0,	/* Timer Counter 0 */
+	0,	/* Timer Counter 1 */
+	0,	/* Timer Counter 2 */
+	3,	/* USB Host port */
+	3,	/* LCD Controller */
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,	/* Advanced Interrupt Controller */
+	0,	/* Advanced Interrupt Controller */
+	0,	/* Advanced Interrupt Controller */
+};
+
+void __init at91sam9261_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+	if (!priority)
+		priority = at91sam9261_default_irq_priority;
+
+	/* Initialize the AIC interrupt controller */
+	at91_aic_init(priority);
+
+	/* Enable GPIO interrupts */
+	at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
new file mode 100644
index 0000000..e150476
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -0,0 +1,745 @@
+/*
+ * arch/arm/mach-at91/at91sam9261_devices.c
+ *
+ *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *  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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam9261.h>
+#include <asm/arch/at91sam9261_matrix.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+#define SZ_512	0x00000200
+#define SZ_256	0x00000100
+#define SZ_16	0x00000010
+
+/* --------------------------------------------------------------------
+ *  USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+	[0] = {
+		.start	= AT91SAM9261_UHP_BASE,
+		.end	= AT91SAM9261_UHP_BASE + SZ_1M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9261_ID_UHP,
+		.end	= AT91SAM9261_ID_UHP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9261_usbh_device = {
+	.name		= "at91_ohci",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &ohci_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &usbh_data,
+	},
+	.resource	= usbh_resources,
+	.num_resources	= ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+	if (!data)
+		return;
+
+	usbh_data = *data;
+	platform_device_register(&at91sam9261_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+	[0] = {
+		.start	= AT91SAM9261_BASE_UDP,
+		.end	= AT91SAM9261_BASE_UDP + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9261_ID_UDP,
+		.end	= AT91SAM9261_ID_UDP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9261_udc_device = {
+	.name		= "at91_udc",
+	.id		= -1,
+	.dev		= {
+				.platform_data		= &udc_data,
+	},
+	.resource	= udc_resources,
+	.num_resources	= ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+	unsigned long x;
+
+	if (!data)
+		return;
+
+	if (data->vbus_pin) {
+		at91_set_gpio_input(data->vbus_pin, 0);
+		at91_set_deglitch(data->vbus_pin, 1);
+	}
+
+	/* Pullup pin is handled internally */
+	x = at91_sys_read(AT91_MATRIX_USBPUCR);
+	at91_sys_write(AT91_MATRIX_USBPUCR, x | AT91_MATRIX_USBPUCR_PUON);
+
+	udc_data = *data;
+	platform_device_register(&at91sam9261_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc_data;
+
+static struct resource mmc_resources[] = {
+	[0] = {
+		.start	= AT91SAM9261_BASE_MCI,
+		.end	= AT91SAM9261_BASE_MCI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9261_ID_MCI,
+		.end	= AT91SAM9261_ID_MCI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9261_mmc_device = {
+	.name		= "at91_mci",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &mmc_data,
+	},
+	.resource	= mmc_resources,
+	.num_resources	= ARRAY_SIZE(mmc_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+	if (!data)
+		return;
+
+	/* input/irq */
+	if (data->det_pin) {
+		at91_set_gpio_input(data->det_pin, 1);
+		at91_set_deglitch(data->det_pin, 1);
+	}
+	if (data->wp_pin)
+		at91_set_gpio_input(data->wp_pin, 1);
+	if (data->vcc_pin)
+		at91_set_gpio_output(data->vcc_pin, 0);
+
+	/* CLK */
+	at91_set_B_periph(AT91_PIN_PA2, 0);
+
+	/* CMD */
+	at91_set_B_periph(AT91_PIN_PA1, 1);
+
+	/* DAT0, maybe DAT1..DAT3 */
+	at91_set_B_periph(AT91_PIN_PA0, 1);
+	if (data->wire4) {
+		at91_set_B_periph(AT91_PIN_PA4, 1);
+		at91_set_B_periph(AT91_PIN_PA5, 1);
+		at91_set_B_periph(AT91_PIN_PA6, 1);
+	}
+
+	mmc_data = *data;
+	platform_device_register(&at91sam9261_mmc_device);
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, 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;
+
+#define NAND_BASE	AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+	{
+		.start	= NAND_BASE,
+		.end	= NAND_BASE + SZ_256M - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device at91_nand_device = {
+	.name		= "at91_nand",
+	.id		= -1,
+	.dev		= {
+				.platform_data	= &nand_data,
+	},
+	.resource	= nand_resources,
+	.num_resources	= ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+	unsigned long csa, mode;
+
+	if (!data)
+		return;
+
+	csa = at91_sys_read(AT91_MATRIX_EBICSA);
+	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC);
+
+	/* set the bus interface characteristics */
+	at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
+			| AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
+
+	at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5)
+			| AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5));
+
+	at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7));
+
+	if (data->bus_width_16)
+		mode = AT91_SMC_DBW_16;
+	else
+		mode = AT91_SMC_DBW_8;
+	at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1));
+
+	/* 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_PC0, 0);		/* NANDOE */
+	at91_set_A_periph(AT91_PIN_PC1, 0);		/* NANDWE */
+
+	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 resource twi_resources[] = {
+	[0] = {
+		.start	= AT91SAM9261_BASE_TWI,
+		.end	= AT91SAM9261_BASE_TWI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9261_ID_TWI,
+		.end	= AT91SAM9261_ID_TWI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9261_twi_device = {
+	.name		= "at91_i2c",
+	.id		= -1,
+	.resource	= twi_resources,
+	.num_resources	= ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+	/* pins used for TWI interface */
+	at91_set_A_periph(AT91_PIN_PA7, 0);		/* TWD */
+	at91_set_multi_drive(AT91_PIN_PA7, 1);
+
+	at91_set_A_periph(AT91_PIN_PA8, 0);		/* TWCK */
+	at91_set_multi_drive(AT91_PIN_PA8, 1);
+
+	platform_device_register(&at91sam9261_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi0_resources[] = {
+	[0] = {
+		.start	= AT91SAM9261_BASE_SPI0,
+		.end	= AT91SAM9261_BASE_SPI0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9261_ID_SPI0,
+		.end	= AT91SAM9261_ID_SPI0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9261_spi0_device = {
+	.name		= "atmel_spi",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &spi_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+	},
+	.resource	= spi0_resources,
+	.num_resources	= ARRAY_SIZE(spi0_resources),
+};
+
+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
+
+static struct resource spi1_resources[] = {
+	[0] = {
+		.start	= AT91SAM9261_BASE_SPI1,
+		.end	= AT91SAM9261_BASE_SPI1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9261_ID_SPI1,
+		.end	= AT91SAM9261_ID_SPI1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9261_spi1_device = {
+	.name		= "atmel_spi",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &spi_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+	},
+	.resource	= spi1_resources,
+	.num_resources	= ARRAY_SIZE(spi1_resources),
+};
+
+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB28, AT91_PIN_PA24, AT91_PIN_PA25, AT91_PIN_PA26 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+	int i;
+	unsigned long cs_pin;
+	short enable_spi0 = 0;
+	short enable_spi1 = 0;
+
+	/* Choose SPI chip-selects */
+	for (i = 0; i < nr_devices; i++) {
+		if (devices[i].controller_data)
+			cs_pin = (unsigned long) devices[i].controller_data;
+		else if (devices[i].bus_num == 0)
+			cs_pin = spi0_standard_cs[devices[i].chip_select];
+		else
+			cs_pin = spi1_standard_cs[devices[i].chip_select];
+
+		if (devices[i].bus_num == 0)
+			enable_spi0 = 1;
+		else
+			enable_spi1 = 1;
+
+		/* enable chip-select pin */
+		at91_set_gpio_output(cs_pin, 1);
+
+		/* pass chip-select pin to driver */
+		devices[i].controller_data = (void *) cs_pin;
+	}
+
+	spi_register_board_info(devices, nr_devices);
+
+	/* Configure SPI bus(es) */
+	if (enable_spi0) {
+		at91_set_A_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */
+		at91_set_A_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */
+		at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPI0_SPCK */
+
+		at91_clock_associate("spi0_clk", &at91sam9261_spi0_device.dev, "spi_clk");
+		platform_device_register(&at91sam9261_spi0_device);
+	}
+	if (enable_spi1) {
+		at91_set_A_periph(AT91_PIN_PB30, 0);	/* SPI1_MISO */
+		at91_set_A_periph(AT91_PIN_PB31, 0);	/* SPI1_MOSI */
+		at91_set_A_periph(AT91_PIN_PB29, 0);	/* SPI1_SPCK */
+
+		at91_clock_associate("spi1_clk", &at91sam9261_spi1_device.dev, "spi_clk");
+		platform_device_register(&at91sam9261_spi1_device);
+	}
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  LCD Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE)
+static u64 lcdc_dmamask = 0xffffffffUL;
+static struct at91fb_info lcdc_data;
+
+static struct resource lcdc_resources[] = {
+	[0] = {
+		.start	= AT91SAM9261_LCDC_BASE,
+		.end	= AT91SAM9261_LCDC_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9261_ID_LCDC,
+		.end	= AT91SAM9261_ID_LCDC,
+		.flags	= IORESOURCE_IRQ,
+	},
+#if defined(CONFIG_FB_INTSRAM)
+	[2] = {
+		.start	= AT91SAM9261_SRAM_BASE,
+		.end	= AT91SAM9261_SRAM_BASE + AT91SAM9261_SRAM_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+#endif
+};
+
+static struct platform_device at91_lcdc_device = {
+	.name		= "at91-fb",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &lcdc_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &lcdc_data,
+	},
+	.resource	= lcdc_resources,
+	.num_resources	= ARRAY_SIZE(lcdc_resources),
+};
+
+void __init at91_add_device_lcdc(struct at91fb_info *data)
+{
+	if (!data) {
+		return;
+	}
+
+	at91_set_A_periph(AT91_PIN_PB1, 0);	/* LCDHSYNC */
+	at91_set_A_periph(AT91_PIN_PB2, 0);	/* LCDDOTCK */
+	at91_set_A_periph(AT91_PIN_PB3, 0);	/* LCDDEN */
+	at91_set_A_periph(AT91_PIN_PB4, 0);	/* LCDCC */
+	at91_set_A_periph(AT91_PIN_PB7, 0);	/* LCDD2 */
+	at91_set_A_periph(AT91_PIN_PB8, 0);	/* LCDD3 */
+	at91_set_A_periph(AT91_PIN_PB9, 0);	/* LCDD4 */
+	at91_set_A_periph(AT91_PIN_PB10, 0);	/* LCDD5 */
+	at91_set_A_periph(AT91_PIN_PB11, 0);	/* LCDD6 */
+	at91_set_A_periph(AT91_PIN_PB12, 0);	/* LCDD7 */
+	at91_set_A_periph(AT91_PIN_PB15, 0);	/* LCDD10 */
+	at91_set_A_periph(AT91_PIN_PB16, 0);	/* LCDD11 */
+	at91_set_A_periph(AT91_PIN_PB17, 0);	/* LCDD12 */
+	at91_set_A_periph(AT91_PIN_PB18, 0);	/* LCDD13 */
+	at91_set_A_periph(AT91_PIN_PB19, 0);	/* LCDD14 */
+	at91_set_A_periph(AT91_PIN_PB20, 0);	/* LCDD15 */
+	at91_set_B_periph(AT91_PIN_PB23, 0);	/* LCDD18 */
+	at91_set_B_periph(AT91_PIN_PB24, 0);	/* LCDD19 */
+	at91_set_B_periph(AT91_PIN_PB25, 0);	/* LCDD20 */
+	at91_set_B_periph(AT91_PIN_PB26, 0);	/* LCDD21 */
+	at91_set_B_periph(AT91_PIN_PB27, 0);	/* LCDD22 */
+	at91_set_B_periph(AT91_PIN_PB28, 0);	/* LCDD23 */
+
+	lcdc_data = *data;
+	platform_device_register(&at91_lcdc_device);
+}
+#else
+void __init at91_add_device_lcdc(struct at91fb_info *data) {}
+#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)
+{
+	/* Enable GPIO to access the LEDs */
+	at91_set_gpio_output(cpu_led, 1);
+	at91_set_gpio_output(timer_led, 1);
+
+	at91_leds_cpu	= cpu_led;
+	at91_leds_timer	= timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_ATMEL)
+static struct resource dbgu_resources[] = {
+	[0] = {
+		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
+		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_SYS,
+		.end	= AT91_ID_SYS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data dbgu_data = {
+	.use_dma_tx	= 0,
+	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91sam9261_dbgu_device = {
+	.name		= "atmel_usart",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &dbgu_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= dbgu_resources,
+	.num_resources	= ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA9, 0);		/* DRXD */
+	at91_set_A_periph(AT91_PIN_PA10, 1);		/* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+	[0] = {
+		.start	= AT91SAM9261_BASE_US0,
+		.end	= AT91SAM9261_BASE_US0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9261_ID_US0,
+		.end	= AT91SAM9261_ID_US0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart0_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9261_uart0_device = {
+	.name		= "atmel_usart",
+	.id		= 1,
+	.dev		= {
+				.platform_data	= &uart0_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart0_resources,
+	.num_resources	= ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PC8, 1);		/* TXD0 */
+	at91_set_A_periph(AT91_PIN_PC9, 0);		/* RXD0 */
+	at91_set_A_periph(AT91_PIN_PC10, 0);		/* RTS0 */
+	at91_set_A_periph(AT91_PIN_PC11, 0);		/* CTS0 */
+}
+
+static struct resource uart1_resources[] = {
+	[0] = {
+		.start	= AT91SAM9261_BASE_US1,
+		.end	= AT91SAM9261_BASE_US1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9261_ID_US1,
+		.end	= AT91SAM9261_ID_US1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart1_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9261_uart1_device = {
+	.name		= "atmel_usart",
+	.id		= 2,
+	.dev		= {
+				.platform_data	= &uart1_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart1_resources,
+	.num_resources	= ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PC12, 1);		/* TXD1 */
+	at91_set_A_periph(AT91_PIN_PC13, 0);		/* RXD1 */
+}
+
+static struct resource uart2_resources[] = {
+	[0] = {
+		.start	= AT91SAM9261_BASE_US2,
+		.end	= AT91SAM9261_BASE_US2 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9261_ID_US2,
+		.end	= AT91SAM9261_ID_US2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart2_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9261_uart2_device = {
+	.name		= "atmel_usart",
+	.id		= 3,
+	.dev		= {
+				.platform_data	= &uart2_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart2_resources,
+	.num_resources	= ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PC15, 0);		/* RXD2 */
+	at91_set_A_periph(AT91_PIN_PC14, 1);		/* TXD2 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
+struct platform_device *atmel_default_console_device;	/* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+	int i;
+
+	/* Fill in list of supported UARTs */
+	for (i = 0; i < config->nr_tty; i++) {
+		switch (config->tty_map[i]) {
+			case 0:
+				configure_usart0_pins();
+				at91_uarts[i] = &at91sam9261_uart0_device;
+				at91_clock_associate("usart0_clk", &at91sam9261_uart0_device.dev, "usart");
+				break;
+			case 1:
+				configure_usart1_pins();
+				at91_uarts[i] = &at91sam9261_uart1_device;
+				at91_clock_associate("usart1_clk", &at91sam9261_uart1_device.dev, "usart");
+				break;
+			case 2:
+				configure_usart2_pins();
+				at91_uarts[i] = &at91sam9261_uart2_device;
+				at91_clock_associate("usart2_clk", &at91sam9261_uart2_device.dev, "usart");
+				break;
+			case 3:
+				configure_dbgu_pins();
+				at91_uarts[i] = &at91sam9261_dbgu_device;
+				at91_clock_associate("mck", &at91sam9261_dbgu_device.dev, "usart");
+				break;
+			default:
+				continue;
+		}
+		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
+	}
+
+	/* Set serial console device */
+	if (config->console_tty < ATMEL_MAX_UART)
+		atmel_default_console_device = at91_uarts[config->console_tty];
+	if (!atmel_default_console_device)
+		printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+	int i;
+
+	for (i = 0; i < ATMEL_MAX_UART; i++) {
+		if (at91_uarts[i])
+			platform_device_register(at91_uarts[i]);
+	}
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+	return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
new file mode 100644
index 0000000..6aa342e
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -0,0 +1,313 @@
+/*
+ * arch/arm/mach-at91/at91sam9263.c
+ *
+ *  Copyright (C) 2007 Atmel 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.
+ *
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/at91sam9263.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91sam9263_io_desc[] __initdata = {
+	{
+		.virtual	= AT91_VA_BASE_SYS,
+		.pfn		= __phys_to_pfn(AT91_BASE_SYS),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE,
+		.pfn		= __phys_to_pfn(AT91SAM9263_SRAM0_BASE),
+		.length		= AT91SAM9263_SRAM0_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE - AT91SAM9263_SRAM1_SIZE,
+		.pfn		= __phys_to_pfn(AT91SAM9263_SRAM1_BASE),
+		.length		= AT91SAM9263_SRAM1_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+	.name		= "pioA_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_PIOA,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+	.name		= "pioB_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_PIOB,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioCDE_clk = {
+	.name		= "pioCDE_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_PIOCDE,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+	.name		= "usart0_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_US0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+	.name		= "usart1_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_US1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+	.name		= "usart2_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_US2,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc0_clk = {
+	.name		= "mci0_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_MCI0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc1_clk = {
+	.name		= "mci1_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_MCI1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+	.name		= "twi_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_TWI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+	.name		= "spi0_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_SPI0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+	.name		= "spi1_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_SPI1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tcb_clk = {
+	.name		= "tcb_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_TCB,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk macb_clk = {
+	.name		= "macb_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_EMAC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+	.name		= "udc_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_UDP,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk isi_clk = {
+	.name		= "isi_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_ISI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk lcdc_clk = {
+	.name		= "lcdc_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_ISI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+	.name		= "ohci_clk",
+	.pmc_mask	= 1 << AT91SAM9263_ID_UHP,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+	&pioA_clk,
+	&pioB_clk,
+	&pioCDE_clk,
+	&usart0_clk,
+	&usart1_clk,
+	&usart2_clk,
+	&mmc0_clk,
+	&mmc1_clk,
+	// can
+	&twi_clk,
+	&spi0_clk,
+	&spi1_clk,
+	// ssc0 .. ssc1
+	// ac97
+	&tcb_clk,
+	// pwmc
+	&macb_clk,
+	// 2dge
+	&udc_clk,
+	&isi_clk,
+	&lcdc_clk,
+	// dma
+	&ohci_clk,
+	// irq0 .. irq1
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+	.name		= "pck0",
+	.pmc_mask	= AT91_PMC_PCK0,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 0,
+};
+static struct clk pck1 = {
+	.name		= "pck1",
+	.pmc_mask	= AT91_PMC_PCK1,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 1,
+};
+static struct clk pck2 = {
+	.name		= "pck2",
+	.pmc_mask	= AT91_PMC_PCK2,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 2,
+};
+static struct clk pck3 = {
+	.name		= "pck3",
+	.pmc_mask	= AT91_PMC_PCK3,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 3,
+};
+
+static void __init at91sam9263_register_clocks(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+		clk_register(periph_clocks[i]);
+
+	clk_register(&pck0);
+	clk_register(&pck1);
+	clk_register(&pck2);
+	clk_register(&pck3);
+}
+
+/* --------------------------------------------------------------------
+ *  GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91sam9263_gpio[] = {
+	{
+		.id		= AT91SAM9263_ID_PIOA,
+		.offset		= AT91_PIOA,
+		.clock		= &pioA_clk,
+	}, {
+		.id		= AT91SAM9263_ID_PIOB,
+		.offset		= AT91_PIOB,
+		.clock		= &pioB_clk,
+	}, {
+		.id		= AT91SAM9263_ID_PIOCDE,
+		.offset		= AT91_PIOC,
+		.clock		= &pioCDE_clk,
+	}, {
+		.id		= AT91SAM9263_ID_PIOCDE,
+		.offset		= AT91_PIOD,
+		.clock		= &pioCDE_clk,
+	}, {
+		.id		= AT91SAM9263_ID_PIOCDE,
+		.offset		= AT91_PIOE,
+		.clock		= &pioCDE_clk,
+	}
+};
+
+static void at91sam9263_reset(void)
+{
+	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+}
+
+
+/* --------------------------------------------------------------------
+ *  AT91SAM9263 processor initialization
+ * -------------------------------------------------------------------- */
+
+void __init at91sam9263_initialize(unsigned long main_clock)
+{
+	/* Map peripherals */
+	iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
+
+	at91_arch_reset = at91sam9263_reset;
+	at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
+
+	/* Init clock subsystem */
+	at91_clock_init(main_clock);
+
+	/* Register the processor-specific clocks */
+	at91sam9263_register_clocks();
+
+	/* Register GPIO subsystem */
+	at91_gpio_init(at91sam9263_gpio, 5);
+}
+
+/* --------------------------------------------------------------------
+ *  Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
+	7,	/* Advanced Interrupt Controller (FIQ) */
+	7,	/* System Peripherals */
+	0,	/* Parallel IO Controller A */
+	0,	/* Parallel IO Controller B */
+	0,	/* Parallel IO Controller C, D and E */
+	0,
+	0,
+	6,	/* USART 0 */
+	6,	/* USART 1 */
+	6,	/* USART 2 */
+	0,	/* Multimedia Card Interface 0 */
+	0,	/* Multimedia Card Interface 1 */
+	4,	/* CAN */
+	0,	/* Two-Wire Interface */
+	6,	/* Serial Peripheral Interface 0 */
+	6,	/* Serial Peripheral Interface 1 */
+	5,	/* Serial Synchronous Controller 0 */
+	5,	/* Serial Synchronous Controller 1 */
+	6,	/* AC97 Controller */
+	0,	/* Timer Counter 0, 1 and 2 */
+	0,	/* Pulse Width Modulation Controller */
+	3,	/* Ethernet */
+	0,
+	0,	/* 2D Graphic Engine */
+	3,	/* USB Device Port */
+	0,	/* Image Sensor Interface */
+	3,	/* LDC Controller */
+	0,	/* DMA Controller */
+	0,
+	3,	/* USB Host port */
+	0,	/* Advanced Interrupt Controller (IRQ0) */
+	0,	/* Advanced Interrupt Controller (IRQ1) */
+};
+
+void __init at91sam9263_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+	if (!priority)
+		priority = at91sam9263_default_irq_priority;
+
+	/* Initialize the AIC interrupt controller */
+	at91_aic_init(priority);
+
+	/* Enable GPIO interrupts */
+	at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
new file mode 100644
index 0000000..d9af7ca
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -0,0 +1,818 @@
+/*
+ * arch/arm/mach-at91/at91sam9263_devices.c
+ *
+ *  Copyright (C) 2007 Atmel 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.
+ *
+ */
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam9263.h>
+#include <asm/arch/at91sam926x_mc.h>
+#include <asm/arch/at91sam9263_matrix.h>
+
+#include "generic.h"
+
+#define SZ_512	0x00000200
+#define SZ_256	0x00000100
+#define SZ_16	0x00000010
+
+/* --------------------------------------------------------------------
+ *  USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_UHP_BASE,
+		.end	= AT91SAM9263_UHP_BASE + SZ_1M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_UHP,
+		.end	= AT91SAM9263_ID_UHP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_usbh_device = {
+	.name		= "at91_ohci",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &ohci_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &usbh_data,
+	},
+	.resource	= usbh_resources,
+	.num_resources	= ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+	int i;
+
+	if (!data)
+		return;
+
+	/* Enable VBus control for UHP ports */
+	for (i = 0; i < data->ports; i++) {
+		if (data->vbus_pin[i])
+			at91_set_gpio_output(data->vbus_pin[i], 0);
+	}
+
+	usbh_data = *data;
+	platform_device_register(&at91_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_UDP,
+		.end	= AT91SAM9263_BASE_UDP + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_UDP,
+		.end	= AT91SAM9263_ID_UDP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_udc_device = {
+	.name		= "at91_udc",
+	.id		= -1,
+	.dev		= {
+				.platform_data		= &udc_data,
+	},
+	.resource	= udc_resources,
+	.num_resources	= ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+	if (!data)
+		return;
+
+	if (data->vbus_pin) {
+		at91_set_gpio_input(data->vbus_pin, 0);
+		at91_set_deglitch(data->vbus_pin, 1);
+	}
+
+	/* Pullup pin is handled internally by USB device peripheral */
+
+	udc_data = *data;
+	platform_device_register(&at91_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
+static u64 eth_dmamask = 0xffffffffUL;
+static struct at91_eth_data eth_data;
+
+static struct resource eth_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_EMAC,
+		.end	= AT91SAM9263_BASE_EMAC + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_EMAC,
+		.end	= AT91SAM9263_ID_EMAC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9263_eth_device = {
+	.name		= "macb",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &eth_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &eth_data,
+	},
+	.resource	= eth_resources,
+	.num_resources	= ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+	if (!data)
+		return;
+
+	if (data->phy_irq_pin) {
+		at91_set_gpio_input(data->phy_irq_pin, 0);
+		at91_set_deglitch(data->phy_irq_pin, 1);
+	}
+
+	/* Pins used for MII and RMII */
+	at91_set_A_periph(AT91_PIN_PE21, 0);	/* ETXCK_EREFCK */
+	at91_set_B_periph(AT91_PIN_PC25, 0);	/* ERXDV */
+	at91_set_A_periph(AT91_PIN_PE25, 0);	/* ERX0 */
+	at91_set_A_periph(AT91_PIN_PE26, 0);	/* ERX1 */
+	at91_set_A_periph(AT91_PIN_PE27, 0);	/* ERXER */
+	at91_set_A_periph(AT91_PIN_PE28, 0);	/* ETXEN */
+	at91_set_A_periph(AT91_PIN_PE23, 0);	/* ETX0 */
+	at91_set_A_periph(AT91_PIN_PE24, 0);	/* ETX1 */
+	at91_set_A_periph(AT91_PIN_PE30, 0);	/* EMDIO */
+	at91_set_A_periph(AT91_PIN_PE29, 0);	/* EMDC */
+
+	if (!data->is_rmii) {
+		at91_set_A_periph(AT91_PIN_PE22, 0);	/* ECRS */
+		at91_set_B_periph(AT91_PIN_PC26, 0);	/* ECOL */
+		at91_set_B_periph(AT91_PIN_PC22, 0);	/* ERX2 */
+		at91_set_B_periph(AT91_PIN_PC23, 0);	/* ERX3 */
+		at91_set_B_periph(AT91_PIN_PC27, 0);	/* ERXCK */
+		at91_set_B_periph(AT91_PIN_PC20, 0);	/* ETX2 */
+		at91_set_B_periph(AT91_PIN_PC21, 0);	/* ETX3 */
+		at91_set_B_periph(AT91_PIN_PC24, 0);	/* ETXER */
+	}
+
+	eth_data = *data;
+	platform_device_register(&at91sam9263_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc0_data, mmc1_data;
+
+static struct resource mmc0_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_MCI0,
+		.end	= AT91SAM9263_BASE_MCI0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_MCI0,
+		.end	= AT91SAM9263_ID_MCI0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9263_mmc0_device = {
+	.name		= "at91_mci",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &mmc0_data,
+	},
+	.resource	= mmc0_resources,
+	.num_resources	= ARRAY_SIZE(mmc0_resources),
+};
+
+static struct resource mmc1_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_MCI1,
+		.end	= AT91SAM9263_BASE_MCI1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_MCI1,
+		.end	= AT91SAM9263_ID_MCI1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9263_mmc1_device = {
+	.name		= "at91_mci",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+				.platform_data		= &mmc1_data,
+	},
+	.resource	= mmc1_resources,
+	.num_resources	= ARRAY_SIZE(mmc1_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+	if (!data)
+		return;
+
+	/* input/irq */
+	if (data->det_pin) {
+		at91_set_gpio_input(data->det_pin, 1);
+		at91_set_deglitch(data->det_pin, 1);
+	}
+	if (data->wp_pin)
+		at91_set_gpio_input(data->wp_pin, 1);
+	if (data->vcc_pin)
+		at91_set_gpio_output(data->vcc_pin, 0);
+
+	if (mmc_id == 0) {		/* MCI0 */
+		/* CLK */
+		at91_set_A_periph(AT91_PIN_PA12, 0);
+
+		if (data->slot_b) {
+			/* CMD */
+			at91_set_A_periph(AT91_PIN_PA16, 1);
+
+			/* DAT0, maybe DAT1..DAT3 */
+			at91_set_A_periph(AT91_PIN_PA17, 1);
+			if (data->wire4) {
+				at91_set_A_periph(AT91_PIN_PA18, 1);
+				at91_set_A_periph(AT91_PIN_PA19, 1);
+				at91_set_A_periph(AT91_PIN_PA20, 1);
+			}
+		} else {
+			/* CMD */
+			at91_set_A_periph(AT91_PIN_PA1, 1);
+
+			/* DAT0, maybe DAT1..DAT3 */
+			at91_set_A_periph(AT91_PIN_PA0, 1);
+			if (data->wire4) {
+				at91_set_A_periph(AT91_PIN_PA3, 1);
+				at91_set_A_periph(AT91_PIN_PA4, 1);
+				at91_set_A_periph(AT91_PIN_PA5, 1);
+			}
+		}
+
+		mmc0_data = *data;
+		at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
+		platform_device_register(&at91sam9263_mmc0_device);
+	} else {			/* MCI1 */
+		/* CLK */
+		at91_set_A_periph(AT91_PIN_PA6, 0);
+
+		if (data->slot_b) {
+			/* CMD */
+			at91_set_A_periph(AT91_PIN_PA21, 1);
+
+			/* DAT0, maybe DAT1..DAT3 */
+			at91_set_A_periph(AT91_PIN_PA22, 1);
+			if (data->wire4) {
+				at91_set_A_periph(AT91_PIN_PA23, 1);
+				at91_set_A_periph(AT91_PIN_PA24, 1);
+				at91_set_A_periph(AT91_PIN_PA25, 1);
+			}
+		} else {
+			/* CMD */
+			at91_set_A_periph(AT91_PIN_PA7, 1);
+
+			/* DAT0, maybe DAT1..DAT3 */
+			at91_set_A_periph(AT91_PIN_PA8, 1);
+			if (data->wire4) {
+				at91_set_A_periph(AT91_PIN_PA9, 1);
+				at91_set_A_periph(AT91_PIN_PA10, 1);
+				at91_set_A_periph(AT91_PIN_PA11, 1);
+			}
+		}
+
+		mmc1_data = *data;
+		at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
+		platform_device_register(&at91sam9263_mmc1_device);
+	}
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, 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;
+
+#define NAND_BASE	AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+	{
+		.start	= NAND_BASE,
+		.end	= NAND_BASE + SZ_256M - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device at91sam9263_nand_device = {
+	.name		= "at91_nand",
+	.id		= -1,
+	.dev		= {
+				.platform_data	= &nand_data,
+	},
+	.resource	= nand_resources,
+	.num_resources	= ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+	unsigned long csa, mode;
+
+	if (!data)
+		return;
+
+	csa = at91_sys_read(AT91_MATRIX_EBI0CSA);
+	at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC);
+
+	/* set the bus interface characteristics */
+	at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
+			| AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
+
+	at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3)
+			| AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3));
+
+	at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5));
+
+	if (data->bus_width_16)
+		mode = AT91_SMC_DBW_16;
+	else
+		mode = AT91_SMC_DBW_8;
+	at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2));
+
+	/* 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);
+
+	nand_data = *data;
+	platform_device_register(&at91sam9263_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 resource twi_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_TWI,
+		.end	= AT91SAM9263_BASE_TWI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_TWI,
+		.end	= AT91SAM9263_ID_TWI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9263_twi_device = {
+	.name		= "at91_i2c",
+	.id		= -1,
+	.resource	= twi_resources,
+	.num_resources	= ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+	/* pins used for TWI interface */
+	at91_set_A_periph(AT91_PIN_PB4, 0);		/* TWD */
+	at91_set_multi_drive(AT91_PIN_PB4, 1);
+
+	at91_set_A_periph(AT91_PIN_PB5, 0);		/* TWCK */
+	at91_set_multi_drive(AT91_PIN_PB5, 1);
+
+	platform_device_register(&at91sam9263_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi0_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_SPI0,
+		.end	= AT91SAM9263_BASE_SPI0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_SPI0,
+		.end	= AT91SAM9263_ID_SPI0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9263_spi0_device = {
+	.name		= "atmel_spi",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &spi_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+	},
+	.resource	= spi0_resources,
+	.num_resources	= ARRAY_SIZE(spi0_resources),
+};
+
+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 };
+
+static struct resource spi1_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_SPI1,
+		.end	= AT91SAM9263_BASE_SPI1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_SPI1,
+		.end	= AT91SAM9263_ID_SPI1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9263_spi1_device = {
+	.name		= "atmel_spi",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &spi_dmamask,
+				.coherent_dma_mask	= 0xffffffff,
+	},
+	.resource	= spi1_resources,
+	.num_resources	= ARRAY_SIZE(spi1_resources),
+};
+
+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+	int i;
+	unsigned long cs_pin;
+	short enable_spi0 = 0;
+	short enable_spi1 = 0;
+
+	/* Choose SPI chip-selects */
+	for (i = 0; i < nr_devices; i++) {
+		if (devices[i].controller_data)
+			cs_pin = (unsigned long) devices[i].controller_data;
+		else if (devices[i].bus_num == 0)
+			cs_pin = spi0_standard_cs[devices[i].chip_select];
+		else
+			cs_pin = spi1_standard_cs[devices[i].chip_select];
+
+		if (devices[i].bus_num == 0)
+			enable_spi0 = 1;
+		else
+			enable_spi1 = 1;
+
+		/* enable chip-select pin */
+		at91_set_gpio_output(cs_pin, 1);
+
+		/* pass chip-select pin to driver */
+		devices[i].controller_data = (void *) cs_pin;
+	}
+
+	spi_register_board_info(devices, nr_devices);
+
+	/* Configure SPI bus(es) */
+	if (enable_spi0) {
+		at91_set_B_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */
+		at91_set_B_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */
+		at91_set_B_periph(AT91_PIN_PA2, 0);	/* SPI1_SPCK */
+
+		at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk");
+		platform_device_register(&at91sam9263_spi0_device);
+	}
+	if (enable_spi1) {
+		at91_set_A_periph(AT91_PIN_PB12, 0);	/* SPI1_MISO */
+		at91_set_A_periph(AT91_PIN_PB13, 0);	/* SPI1_MOSI */
+		at91_set_A_periph(AT91_PIN_PB14, 0);	/* SPI1_SPCK */
+
+		at91_clock_associate("spi1_clk", &at91sam9263_spi1_device.dev, "spi_clk");
+		platform_device_register(&at91sam9263_spi1_device);
+	}
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#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)
+{
+	/* Enable GPIO to access the LEDs */
+	at91_set_gpio_output(cpu_led, 1);
+	at91_set_gpio_output(timer_led, 1);
+
+	at91_leds_cpu	= cpu_led;
+	at91_leds_timer	= timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_ATMEL)
+
+static struct resource dbgu_resources[] = {
+	[0] = {
+		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
+		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_SYS,
+		.end	= AT91_ID_SYS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data dbgu_data = {
+	.use_dma_tx	= 0,
+	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91sam9263_dbgu_device = {
+	.name		= "atmel_usart",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &dbgu_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= dbgu_resources,
+	.num_resources	= ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PC30, 0);		/* DRXD */
+	at91_set_A_periph(AT91_PIN_PC31, 1);		/* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_US0,
+		.end	= AT91SAM9263_BASE_US0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_US0,
+		.end	= AT91SAM9263_ID_US0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart0_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9263_uart0_device = {
+	.name		= "atmel_usart",
+	.id		= 1,
+	.dev		= {
+				.platform_data	= &uart0_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart0_resources,
+	.num_resources	= ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA26, 1);		/* TXD0 */
+	at91_set_A_periph(AT91_PIN_PA27, 0);		/* RXD0 */
+	at91_set_A_periph(AT91_PIN_PA28, 0);		/* RTS0 */
+	at91_set_A_periph(AT91_PIN_PA29, 0);		/* CTS0 */
+}
+
+static struct resource uart1_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_US1,
+		.end	= AT91SAM9263_BASE_US1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_US1,
+		.end	= AT91SAM9263_ID_US1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart1_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9263_uart1_device = {
+	.name		= "atmel_usart",
+	.id		= 2,
+	.dev		= {
+				.platform_data	= &uart1_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart1_resources,
+	.num_resources	= ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PD0, 1);		/* TXD1 */
+	at91_set_A_periph(AT91_PIN_PD1, 0);		/* RXD1 */
+	at91_set_B_periph(AT91_PIN_PD7, 0);		/* RTS1 */
+	at91_set_B_periph(AT91_PIN_PD8, 0);		/* CTS1 */
+}
+
+static struct resource uart2_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_US2,
+		.end	= AT91SAM9263_BASE_US2 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_US2,
+		.end	= AT91SAM9263_ID_US2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart2_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91sam9263_uart2_device = {
+	.name		= "atmel_usart",
+	.id		= 3,
+	.dev		= {
+				.platform_data	= &uart2_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart2_resources,
+	.num_resources	= ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PD2, 1);		/* TXD2 */
+	at91_set_A_periph(AT91_PIN_PD3, 0);		/* RXD2 */
+	at91_set_B_periph(AT91_PIN_PD5, 0);		/* RTS2 */
+	at91_set_B_periph(AT91_PIN_PD6, 0);		/* CTS2 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
+struct platform_device *atmel_default_console_device;	/* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+	int i;
+
+	/* Fill in list of supported UARTs */
+	for (i = 0; i < config->nr_tty; i++) {
+		switch (config->tty_map[i]) {
+			case 0:
+				configure_usart0_pins();
+				at91_uarts[i] = &at91sam9263_uart0_device;
+				at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart");
+				break;
+			case 1:
+				configure_usart1_pins();
+				at91_uarts[i] = &at91sam9263_uart1_device;
+				at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart");
+				break;
+			case 2:
+				configure_usart2_pins();
+				at91_uarts[i] = &at91sam9263_uart2_device;
+				at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart");
+				break;
+			case 3:
+				configure_dbgu_pins();
+				at91_uarts[i] = &at91sam9263_dbgu_device;
+				at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart");
+				break;
+			default:
+				continue;
+		}
+		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
+	}
+
+	/* Set serial console device */
+	if (config->console_tty < ATMEL_MAX_UART)
+		atmel_default_console_device = at91_uarts[config->console_tty];
+	if (!atmel_default_console_device)
+		printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+	int i;
+
+	for (i = 0; i < ATMEL_MAX_UART; i++) {
+		if (at91_uarts[i])
+			platform_device_register(at91_uarts[i]);
+	}
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+	return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
new file mode 100644
index 0000000..a4dded2
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -0,0 +1,113 @@
+/*
+ * linux/arch/arm/mach-at91/at91sam926x_time.c
+ *
+ * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
+ * Revision	 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+
+#include <asm/arch/at91_pit.h>
+
+
+#define PIT_CPIV(x)	((x) & AT91_PIT_CPIV)
+#define PIT_PICNT(x)	(((x) & AT91_PIT_PICNT) >> 20)
+
+/*
+ * Returns number of microseconds since last timer interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeofday()
+ *  'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
+ */
+static unsigned long at91sam926x_gettimeoffset(void)
+{
+	unsigned long elapsed;
+	unsigned long t = at91_sys_read(AT91_PIT_PIIR);
+
+	elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t);		/* hardware clock cycles */
+
+	return (unsigned long)(elapsed * jiffies_to_usecs(1)) / LATCH;
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
+{
+	volatile long nr_ticks;
+
+	if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) {	/* This is a shared interrupt */
+		write_seqlock(&xtime_lock);
+
+		/* Get number to ticks performed before interrupt and clear PIT interrupt */
+		nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
+		do {
+			timer_tick();
+			nr_ticks--;
+		} while (nr_ticks);
+
+		write_sequnlock(&xtime_lock);
+		return IRQ_HANDLED;
+	} else
+		return IRQ_NONE;		/* not handled */
+}
+
+static struct irqaction at91sam926x_timer_irq = {
+	.name		= "at91_tick",
+	.flags		= IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER,
+	.handler	= at91sam926x_timer_interrupt
+};
+
+void at91sam926x_timer_reset(void)
+{
+	/* Disable timer */
+	at91_sys_write(AT91_PIT_MR, 0);
+
+	/* Clear any pending interrupts */
+	(void) at91_sys_read(AT91_PIT_PIVR);
+
+	/* Set Period Interval timer and enable its interrupt */
+	at91_sys_write(AT91_PIT_MR, (LATCH & AT91_PIT_PIV) | AT91_PIT_PITIEN | AT91_PIT_PITEN);
+}
+
+/*
+ * Set up timer interrupt.
+ */
+void __init at91sam926x_timer_init(void)
+{
+	/* Initialize and enable the timer */
+	at91sam926x_timer_reset();
+
+	/* Make IRQs happen for the system timer. */
+	setup_irq(AT91_ID_SYS, &at91sam926x_timer_irq);
+}
+
+#ifdef CONFIG_PM
+static void at91sam926x_timer_suspend(void)
+{
+	/* Disable timer */
+	at91_sys_write(AT91_PIT_MR, 0);
+}
+#else
+#define at91sam926x_timer_suspend	NULL
+#endif
+
+struct sys_timer at91sam926x_timer = {
+	.init		= at91sam926x_timer_init,
+	.offset		= at91sam926x_gettimeoffset,
+	.suspend	= at91sam926x_timer_suspend,
+	.resume		= at91sam926x_timer_reset,
+};
+
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
new file mode 100644
index 0000000..2d3d4b6
--- /dev/null
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/mach-at91/board-1arm.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata onearm_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 3,
+	.tty_map	= { 4, 0, 1, -1, -1 },		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init onearm_map_io(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91rm9200_initialize(18432000, AT91RM9200_PQFP);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&onearm_uart_config);
+}
+
+static void __init onearm_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata onearm_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+static struct at91_usbh_data __initdata onearm_usbh_data = {
+	.ports		= 1,
+};
+
+static struct at91_udc_data __initdata onearm_udc_data = {
+	.vbus_pin	= AT91_PIN_PC2,
+	.pullup_pin	= AT91_PIN_PC3,
+};
+
+static void __init onearm_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&onearm_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&onearm_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&onearm_udc_data);
+}
+
+MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= onearm_map_io,
+	.init_irq	= onearm_init_irq,
+	.init_machine	= onearm_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
new file mode 100644
index 0000000..b451861
--- /dev/null
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/arm/mach-at91/board-carmeva.c
+ *
+ *  Copyright (c) 2005 Peer Georgi
+ *  		       Conitec Datasystems
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata carmeva_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init carmeva_map_io(void)
+{
+	/* Initialize processor: 20.000 MHz crystal */
+	at91rm9200_initialize(20000000, AT91RM9200_BGA);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&carmeva_uart_config);
+}
+
+static void __init carmeva_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata carmeva_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+static struct at91_usbh_data __initdata carmeva_usbh_data = {
+	.ports		= 2,
+};
+
+static struct at91_udc_data __initdata carmeva_udc_data = {
+	.vbus_pin	= AT91_PIN_PD12,
+	.pullup_pin	= AT91_PIN_PD9,
+};
+
+/* FIXME: user dependend */
+// static struct at91_cf_data __initdata carmeva_cf_data = {
+//	.det_pin	= AT91_PIN_PB0,
+//	.rst_pin	= AT91_PIN_PC5,
+	// .irq_pin	= ... not connected
+	// .vcc_pin	= ... always powered
+// };
+
+static struct at91_mmc_data __initdata carmeva_mmc_data = {
+	.slot_b		= 0,
+	.wire4		= 1,
+	.det_pin	= AT91_PIN_PB10,
+	.wp_pin		= AT91_PIN_PC14,
+};
+
+static struct spi_board_info carmeva_spi_devices[] = {
+	{ /* DataFlash chip */
+		.modalias = "mtd_dataflash",
+		.chip_select  = 0,
+		.max_speed_hz = 10 * 1000 * 1000,
+	},
+	{ /* User accessable spi - cs1 (250KHz) */
+		.modalias = "spi-cs1",
+		.chip_select  = 1,
+		.max_speed_hz = 250 *  1000,
+	},
+	{ /* User accessable spi - cs2 (1MHz) */
+		.modalias = "spi-cs2",
+		.chip_select  = 2,
+		.max_speed_hz = 1 * 1000 *  1000,
+	},
+	{ /* User accessable spi - cs3 (10MHz) */
+		.modalias = "spi-cs3",
+		.chip_select  = 3,
+		.max_speed_hz = 10 * 1000 *  1000,
+	},
+};
+
+static void __init carmeva_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&carmeva_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&carmeva_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&carmeva_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(carmeva_spi_devices, ARRAY_SIZE(carmeva_spi_devices));
+	/* Compact Flash */
+//	at91_add_device_cf(&carmeva_cf_data);
+	/* MMC */
+	at91_add_device_mmc(0, &carmeva_mmc_data);
+}
+
+MACHINE_START(CARMEVA, "Carmeva")
+	/* Maintainer: Conitec Datasystems */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= carmeva_map_io,
+	.init_irq	= carmeva_init_irq,
+	.init_machine	= carmeva_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
new file mode 100644
index 0000000..e18a41e
--- /dev/null
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -0,0 +1,184 @@
+/*
+ * linux/arch/arm/mach-at91/board-csb337.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata csb337_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init csb337_map_io(void)
+{
+	/* Initialize processor: 3.6864 MHz crystal */
+	at91rm9200_initialize(3686400, AT91RM9200_BGA);
+
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&csb337_uart_config);
+}
+
+static void __init csb337_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata csb337_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC2,
+	.is_rmii	= 0,
+};
+
+static struct at91_usbh_data __initdata csb337_usbh_data = {
+	.ports		= 2,
+};
+
+static struct at91_udc_data __initdata csb337_udc_data = {
+	// this has no VBUS sensing pin
+	.pullup_pin	= AT91_PIN_PA24,
+};
+
+static struct at91_cf_data __initdata csb337_cf_data = {
+	/*
+	 * connector P4 on the CSB 337 mates to
+	 * connector P8 on the CSB 300CF
+	 */
+
+	/* CSB337 specific */
+	.det_pin	= AT91_PIN_PC3,
+
+	/* CSB300CF specific */
+	.irq_pin	= AT91_PIN_PA19,
+	.vcc_pin	= AT91_PIN_PD0,
+	.rst_pin	= AT91_PIN_PD2,
+};
+
+static struct at91_mmc_data __initdata csb337_mmc_data = {
+	.det_pin	= AT91_PIN_PD5,
+	.slot_b		= 0,
+	.wire4		= 1,
+	.wp_pin		= AT91_PIN_PD6,
+};
+
+static struct spi_board_info csb337_spi_devices[] = {
+	{	/* CAN controller */
+		.modalias	= "sak82c900",
+		.chip_select	= 0,
+		.max_speed_hz	= 6 * 1000 * 1000,
+	},
+};
+
+#define CSB_FLASH_BASE	AT91_CHIPSELECT_0
+#define CSB_FLASH_SIZE	0x800000
+
+static struct mtd_partition csb_flash_partitions[] = {
+	{
+		.name		= "uMON flash",
+		.offset		= 0,
+		.size		= MTDPART_SIZ_FULL,
+		.mask_flags	= MTD_WRITEABLE,	/* read only */
+	}
+};
+
+static struct physmap_flash_data csb_flash_data = {
+	.width		= 2,
+	.parts		= csb_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(csb_flash_partitions),
+};
+
+static struct resource csb_flash_resources[] = {
+	{
+		.start	= CSB_FLASH_BASE,
+		.end	= CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device csb_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+				.platform_data = &csb_flash_data,
+			},
+	.resource	= csb_flash_resources,
+	.num_resources	= ARRAY_SIZE(csb_flash_resources),
+};
+
+static void __init csb337_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&csb337_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&csb337_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&csb337_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* Compact Flash */
+	at91_set_gpio_input(AT91_PIN_PB22, 1);		/* IOIS16 */
+	at91_add_device_cf(&csb337_cf_data);
+	/* SPI */
+	at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
+	/* MMC */
+	at91_add_device_mmc(0, &csb337_mmc_data);
+	/* NOR flash */
+	platform_device_register(&csb_flash);
+}
+
+MACHINE_START(CSB337, "Cogent CSB337")
+	/* Maintainer: Bill Gatliff */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= csb337_map_io,
+	.init_irq	= csb337_init_irq,
+	.init_machine	= csb337_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
new file mode 100644
index 0000000..77f04b9
--- /dev/null
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -0,0 +1,148 @@
+/*
+ * linux/arch/arm/mach-at91/board-csb637.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata csb637_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init csb637_map_io(void)
+{
+	/* Initialize processor: 3.6864 MHz crystal */
+	at91rm9200_initialize(3686400, AT91RM9200_BGA);
+
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&csb637_uart_config);
+}
+
+static void __init csb637_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata csb637_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC0,
+	.is_rmii	= 0,
+};
+
+static struct at91_usbh_data __initdata csb637_usbh_data = {
+	.ports		= 2,
+};
+
+static struct at91_udc_data __initdata csb637_udc_data = {
+	.vbus_pin     = AT91_PIN_PB28,
+	.pullup_pin   = AT91_PIN_PB1,
+};
+
+#define CSB_FLASH_BASE	AT91_CHIPSELECT_0
+#define CSB_FLASH_SIZE	0x1000000
+
+static struct mtd_partition csb_flash_partitions[] = {
+	{
+		.name		= "uMON flash",
+		.offset		= 0,
+		.size		= MTDPART_SIZ_FULL,
+		.mask_flags	= MTD_WRITEABLE,	/* read only */
+	}
+};
+
+static struct physmap_flash_data csb_flash_data = {
+	.width		= 2,
+	.parts		= csb_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(csb_flash_partitions),
+};
+
+static struct resource csb_flash_resources[] = {
+	{
+		.start	= CSB_FLASH_BASE,
+		.end	= CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device csb_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+				.platform_data = &csb_flash_data,
+			},
+	.resource	= csb_flash_resources,
+	.num_resources	= ARRAY_SIZE(csb_flash_resources),
+};
+
+static void __init csb637_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&csb637_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&csb637_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&csb637_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
+	/* NOR flash */
+	platform_device_register(&csb_flash);
+}
+
+MACHINE_START(CSB637, "Cogent CSB637")
+	/* Maintainer: Bill Gatliff */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= csb637_map_io,
+	.init_irq	= csb637_init_irq,
+	.init_machine	= csb637_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c
new file mode 100644
index 0000000..6043c38
--- /dev/null
+++ b/arch/arm/mach-at91/board-dk.c
@@ -0,0 +1,216 @@
+/*
+ * linux/arch/arm/mach-at91/board-dk.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ *  Epson S1D framebuffer glue code is:
+ *     Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata dk_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init dk_map_io(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91rm9200_initialize(18432000, AT91RM9200_BGA);
+
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&dk_uart_config);
+}
+
+static void __init dk_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata dk_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+static struct at91_usbh_data __initdata dk_usbh_data = {
+	.ports		= 2,
+};
+
+static struct at91_udc_data __initdata dk_udc_data = {
+	.vbus_pin	= AT91_PIN_PD4,
+	.pullup_pin	= AT91_PIN_PD5,
+};
+
+static struct at91_cf_data __initdata dk_cf_data = {
+	.det_pin	= AT91_PIN_PB0,
+	.rst_pin	= AT91_PIN_PC5,
+	// .irq_pin	= ... not connected
+	// .vcc_pin	= ... always powered
+};
+
+static struct at91_mmc_data __initdata dk_mmc_data = {
+	.slot_b		= 0,
+	.wire4		= 1,
+};
+
+static struct spi_board_info dk_spi_devices[] = {
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	},
+	{	/* UR6HCPS2-SP40 PS2-to-SPI adapter */
+		.modalias	= "ur6hcps2",
+		.chip_select	= 1,
+		.max_speed_hz	= 250 *  1000,
+	},
+	{	/* TLV1504 ADC, 4 channels, 10 bits; one is a temp sensor */
+		.modalias	= "tlv1504",
+		.chip_select	= 2,
+		.max_speed_hz	= 20 * 1000 * 1000,
+	},
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+	{	/* DataFlash card */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 3,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	}
+#endif
+};
+
+static struct mtd_partition __initdata dk_nand_partition[] = {
+	{
+		.name	= "NAND Partition 1",
+		.offset	= 0,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+	*num_partitions = ARRAY_SIZE(dk_nand_partition);
+	return dk_nand_partition;
+}
+
+static struct at91_nand_data __initdata dk_nand_data = {
+	.ale		= 22,
+	.cle		= 21,
+	.det_pin	= AT91_PIN_PB1,
+	.rdy_pin	= AT91_PIN_PC2,
+	// .enable_pin	= ... not there
+	.partition_info	= nand_partitions,
+};
+
+#define DK_FLASH_BASE	AT91_CHIPSELECT_0
+#define DK_FLASH_SIZE	0x200000
+
+static struct physmap_flash_data dk_flash_data = {
+	.width	= 2,
+};
+
+static struct resource dk_flash_resource = {
+	.start		= DK_FLASH_BASE,
+	.end		= DK_FLASH_BASE + DK_FLASH_SIZE - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device dk_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &dk_flash_data,
+			},
+	.resource	= &dk_flash_resource,
+	.num_resources	= 1,
+};
+
+
+static void __init dk_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&dk_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&dk_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&dk_udc_data);
+	at91_set_multi_drive(dk_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
+	/* Compact Flash */
+	at91_add_device_cf(&dk_cf_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(dk_spi_devices, ARRAY_SIZE(dk_spi_devices));
+#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). */
+	at91_add_device_mmc(0, &dk_mmc_data);
+#endif
+	/* NAND */
+	at91_add_device_nand(&dk_nand_data);
+	/* NOR Flash */
+	platform_device_register(&dk_flash);
+	/* VGA */
+//	dk_add_device_video();
+}
+
+MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
+	/* Maintainer: SAN People/Atmel */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= dk_map_io,
+	.init_irq	= dk_init_irq,
+	.init_machine	= dk_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
new file mode 100644
index 0000000..20458b5
--- /dev/null
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -0,0 +1,123 @@
+/*
+ * linux/arch/arm/mach-at91/board-eb9200.c
+ *
+ *  Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest
+ *  by Andrew Patrikalakis
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata eb9200_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init eb9200_map_io(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91rm9200_initialize(18432000, AT91RM9200_BGA);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&eb9200_uart_config);
+}
+
+static void __init eb9200_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata eb9200_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+static struct at91_usbh_data __initdata eb9200_usbh_data = {
+	.ports		= 2,
+};
+
+static struct at91_udc_data __initdata eb9200_udc_data = {
+	.vbus_pin	= AT91_PIN_PD4,
+	.pullup_pin	= AT91_PIN_PD5,
+};
+
+static struct at91_cf_data __initdata eb9200_cf_data = {
+	.det_pin	= AT91_PIN_PB0,
+	.rst_pin	= AT91_PIN_PC5,
+	// .irq_pin	= ... not connected
+	// .vcc_pin	= ... always powered
+};
+
+static struct at91_mmc_data __initdata eb9200_mmc_data = {
+	.slot_b		= 0,
+	.wire4		= 1,
+};
+
+static void __init eb9200_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&eb9200_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&eb9200_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&eb9200_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* Compact Flash */
+	at91_add_device_cf(&eb9200_cf_data);
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
+	/* MMC */
+	/* only supports 1 or 4 bit interface, not wired through to SPI */
+	at91_add_device_mmc(0, &eb9200_mmc_data);
+}
+
+MACHINE_START(ATEB9200, "Embest ATEB9200")
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= eb9200_map_io,
+	.init_irq	= eb9200_init_irq,
+	.init_machine	= eb9200_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-ek.c b/arch/arm/mach-at91/board-ek.c
new file mode 100644
index 0000000..322fdd7
--- /dev/null
+++ b/arch/arm/mach-at91/board-ek.c
@@ -0,0 +1,174 @@
+/*
+ * linux/arch/arm/mach-at91/board-ek.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ *  Epson S1D framebuffer glue code is:
+ *     Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init ek_map_io(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91rm9200_initialize(18432000, AT91RM9200_BGA);
+
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata ek_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+static struct at91_usbh_data __initdata ek_usbh_data = {
+	.ports		= 2,
+};
+
+static struct at91_udc_data __initdata ek_udc_data = {
+	.vbus_pin	= AT91_PIN_PD4,
+	.pullup_pin	= AT91_PIN_PD5,
+};
+
+static struct at91_mmc_data __initdata ek_mmc_data = {
+	.det_pin	= AT91_PIN_PB27,
+	.slot_b		= 0,
+	.wire4		= 1,
+	.wp_pin		= AT91_PIN_PA17,
+};
+
+static struct spi_board_info ek_spi_devices[] = {
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	},
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+	{	/* DataFlash card */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 3,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	},
+#endif
+};
+
+#define EK_FLASH_BASE	AT91_CHIPSELECT_0
+#define EK_FLASH_SIZE	0x200000
+
+static struct physmap_flash_data ek_flash_data = {
+	.width	= 2,
+};
+
+static struct resource ek_flash_resource = {
+	.start		= EK_FLASH_BASE,
+	.end		= EK_FLASH_BASE + EK_FLASH_SIZE - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ek_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &ek_flash_data,
+			},
+	.resource	= &ek_flash_resource,
+	.num_resources	= 1,
+};
+
+
+static void __init ek_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&ek_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&ek_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&ek_udc_data);
+	at91_set_multi_drive(ek_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+#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). */
+	at91_add_device_mmc(0, &ek_mmc_data);
+#endif
+	/* NOR Flash */
+	platform_device_register(&ek_flash);
+	/* VGA */
+//	ek_add_device_video();
+}
+
+MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
+	/* Maintainer: SAN People/Atmel */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= ek_map_io,
+	.init_irq	= ek_init_irq,
+	.init_machine	= ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
new file mode 100644
index 0000000..c77d84c
--- /dev/null
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -0,0 +1,109 @@
+/*
+ * linux/arch/arm/mach-at91/board-kafa.c
+ *
+ *  Copyright (C) 2006 Sperry-Sun
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata kafa_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 0, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init kafa_map_io(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91rm9200_initialize(18432000, AT91RM9200_PQFP);
+
+	/* Set up the LEDs */
+	at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&kafa_uart_config);
+}
+
+static void __init kafa_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata kafa_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 0,
+};
+
+static struct at91_usbh_data __initdata kafa_usbh_data = {
+	.ports		= 1,
+};
+
+static struct at91_udc_data __initdata kafa_udc_data = {
+	.vbus_pin	= AT91_PIN_PB6,
+	.pullup_pin	= AT91_PIN_PB7,
+};
+
+static void __init kafa_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&kafa_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&kafa_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&kafa_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
+}
+
+MACHINE_START(KAFA, "Sperry-Sun KAFA")
+	/* Maintainer: Sergei Sharonov */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= kafa_map_io,
+	.init_irq	= kafa_init_irq,
+	.init_machine	= kafa_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
new file mode 100644
index 0000000..76f6e1e
--- /dev/null
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -0,0 +1,143 @@
+/*
+ * linux/arch/arm/mach-at91/board-kb9202.c
+ *
+ *  Copyright (c) 2005 kb_admin
+ *  		       KwikByte, 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 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata kb9202_uart_config = {
+	.console_tty	= 0,					/* ttyS0 */
+	.nr_tty		= 3,
+	.tty_map	= { 4, 0, 1, -1, -1 }			/* ttyS0, ..., ttyS4 */
+};
+
+static void __init kb9202_map_io(void)
+{
+	/* Initialize processor: 10 MHz crystal */
+	at91rm9200_initialize(10000000, AT91RM9200_PQFP);
+
+	/* Set up the LEDs */
+	at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&kb9202_uart_config);
+}
+
+static void __init kb9202_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata kb9202_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PB29,
+	.is_rmii	= 0,
+};
+
+static struct at91_usbh_data __initdata kb9202_usbh_data = {
+	.ports		= 1,
+};
+
+static struct at91_udc_data __initdata kb9202_udc_data = {
+	.vbus_pin	= AT91_PIN_PB24,
+	.pullup_pin	= AT91_PIN_PB22,
+};
+
+static struct at91_mmc_data __initdata kb9202_mmc_data = {
+	.det_pin	= AT91_PIN_PB2,
+	.slot_b		= 0,
+	.wire4		= 1,
+};
+
+static struct mtd_partition __initdata kb9202_nand_partition[] = {
+	{
+		.name	= "nand_fs",
+		.offset	= 0,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+	*num_partitions = ARRAY_SIZE(kb9202_nand_partition);
+	return kb9202_nand_partition;
+}
+
+static struct at91_nand_data __initdata kb9202_nand_data = {
+	.ale		= 22,
+	.cle		= 21,
+	// .det_pin	= ... not there
+	.rdy_pin	= AT91_PIN_PC29,
+	.enable_pin	= AT91_PIN_PC28,
+	.partition_info	= nand_partitions,
+};
+
+static void __init kb9202_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&kb9202_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&kb9202_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&kb9202_udc_data);
+	/* MMC */
+	at91_add_device_mmc(0, &kb9202_mmc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
+	/* NAND */
+	at91_add_device_nand(&kb9202_nand_data);
+}
+
+MACHINE_START(KB9200, "KB920x")
+	/* Maintainer: KwikByte, Inc. */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= kb9202_map_io,
+	.init_irq	= kb9202_init_irq,
+	.init_machine	= kb9202_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
new file mode 100644
index 0000000..57fb449
--- /dev/null
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -0,0 +1,202 @@
+/*
+ * linux/arch/arm/mach-at91/board-sam9260ek.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2006 Atmel
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 5 = USART0 .. USART5
+ *    6      = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 3,
+	.tty_map	= { 6, 0, 1, -1, -1, -1, -1 }	/* ttyS0, ..., ttyS6 */
+};
+
+static void __init ek_map_io(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91sam9260_initialize(18432000);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+	at91sam9260_init_interrupts(NULL);
+}
+
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+	.ports		= 2,
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+	.vbus_pin	= AT91_PIN_PC5,
+	.pullup_pin	= 0,		/* pull-up driven by UDC */
+};
+
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info ek_spi_devices[] = {
+#if !defined(CONFIG_MMC_AT91)
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 1,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	},
+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+	{	/* DataFlash card */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	},
+#endif
+#endif
+#if defined(CONFIG_SND_AT73C213)
+	{	/* AT73C213 DAC */
+		.modalias	= "snd_at73c213",
+		.chip_select	= 0,
+		.max_speed_hz	= 10 * 1000 * 1000,
+		.bus_num	= 1,
+	},
+#endif
+};
+
+
+/*
+ * MACB Ethernet device
+ */
+static struct __initdata at91_eth_data ek_macb_data = {
+	.phy_irq_pin	= AT91_PIN_PA7,
+	.is_rmii	= 1,
+};
+
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+	{
+		.name	= "Partition 1",
+		.offset	= 0,
+		.size	= 256 * 1024,
+	},
+	{
+		.name	= "Partition 2",
+		.offset	= 256 * 1024,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+	*num_partitions = ARRAY_SIZE(ek_nand_partition);
+	return ek_nand_partition;
+}
+
+static struct at91_nand_data __initdata ek_nand_data = {
+	.ale		= 21,
+	.cle		= 22,
+//	.det_pin	= ... not connected
+	.rdy_pin	= AT91_PIN_PC13,
+	.enable_pin	= AT91_PIN_PC14,
+	.partition_info	= nand_partitions,
+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+	.bus_width_16	= 1,
+#else
+	.bus_width_16	= 0,
+#endif
+};
+
+
+/*
+ * MCI (SD/MMC)
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+	.slot_b		= 1,
+	.wire4		= 1,
+//	.det_pin	= ... not connected
+//	.wp_pin		= ... not connected
+//	.vcc_pin	= ... not connected
+};
+
+static void __init ek_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* USB Host */
+	at91_add_device_usbh(&ek_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&ek_udc_data);
+	/* SPI */
+	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+	/* NAND */
+	at91_add_device_nand(&ek_nand_data);
+	/* Ethernet */
+	at91_add_device_eth(&ek_macb_data);
+	/* MMC */
+	at91_add_device_mmc(0, &ek_mmc_data);
+}
+
+MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
+	/* Maintainer: Atmel */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91sam926x_timer,
+	.map_io		= ek_map_io,
+	.init_irq	= ek_init_irq,
+	.init_machine	= ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
new file mode 100644
index 0000000..b7e7724
--- /dev/null
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -0,0 +1,259 @@
+/*
+ * linux/arch/arm/mach-at91/board-sam9261ek.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2006 Atmel
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/dm9000.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 2 = USART0 .. USART2
+ *    3      = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 1,
+	.tty_map	= { 3, -1, -1, -1 }		/* ttyS0, ..., ttyS3 */
+};
+
+static void __init ek_map_io(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91sam9261_initialize(18432000);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+	at91sam9261_init_interrupts(NULL);
+}
+
+
+/*
+ * DM9000 ethernet device
+ */
+#if defined(CONFIG_DM9000)
+static struct resource at91sam9261_dm9000_resource[] = {
+	[0] = {
+		.start	= AT91_CHIPSELECT_2,
+		.end	= AT91_CHIPSELECT_2 + 3,
+		.flags	= IORESOURCE_MEM
+	},
+	[1] = {
+		.start	= AT91_CHIPSELECT_2 + 0x44,
+		.end	= AT91_CHIPSELECT_2 + 0xFF,
+		.flags	= IORESOURCE_MEM
+	},
+	[2] = {
+		.start	= AT91_PIN_PC11,
+		.end	= AT91_PIN_PC11,
+		.flags	= IORESOURCE_IRQ
+	}
+};
+
+static struct dm9000_plat_data dm9000_platdata = {
+	.flags		= DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device at91sam9261_dm9000_device = {
+	.name		= "dm9000",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(at91sam9261_dm9000_resource),
+	.resource	= at91sam9261_dm9000_resource,
+	.dev		= {
+		.platform_data	= &dm9000_platdata,
+	}
+};
+
+static void __init ek_add_device_dm9000(void)
+{
+	/*
+	 * Configure Chip-Select 2 on SMC for the DM9000.
+	 * Note: These timings were calculated for MASTER_CLOCK = 100000000
+	 *  according to the DM9000 timings.
+	 */
+	at91_sys_write(AT91_SMC_SETUP(2), AT91_SMC_NWESETUP_(2) | AT91_SMC_NCS_WRSETUP_(0) | AT91_SMC_NRDSETUP_(2) | AT91_SMC_NCS_RDSETUP_(0));
+	at91_sys_write(AT91_SMC_PULSE(2), AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(8) | AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(8));
+	at91_sys_write(AT91_SMC_CYCLE(2), AT91_SMC_NWECYCLE_(16) | AT91_SMC_NRDCYCLE_(16));
+	at91_sys_write(AT91_SMC_MODE(2), AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16 | AT91_SMC_TDF_(1));
+
+	/* Configure Reset signal as output */
+	at91_set_gpio_output(AT91_PIN_PC10, 0);
+
+	/* Configure Interrupt pin as input, no pull-up */
+	at91_set_gpio_input(AT91_PIN_PC11, 0);
+
+	platform_device_register(&at91sam9261_dm9000_device);
+}
+#else
+static void __init ek_add_device_dm9000(void) {}
+#endif /* CONFIG_DM9000 */
+
+
+/*
+ * USB Host Port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+	.ports		= 2,
+};
+
+
+/*
+ * USB Device Port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+	.vbus_pin	= AT91_PIN_PB29,
+	.pullup_pin	= 0,		/* pull-up driven by UDC */
+};
+
+
+/*
+ * MCI (SD/MMC)
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+	.wire4		= 1,
+//	.det_pin	= ... not connected
+//	.wp_pin		= ... not connected
+//	.vcc_pin	= ... not connected
+};
+
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+	{
+		.name	= "Partition 1",
+		.offset	= 0,
+		.size	= 256 * 1024,
+	},
+	{
+		.name	= "Partition 2",
+		.offset	= 256 * 1024 ,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+	*num_partitions = ARRAY_SIZE(ek_nand_partition);
+	return ek_nand_partition;
+}
+
+static struct at91_nand_data __initdata ek_nand_data = {
+	.ale		= 22,
+	.cle		= 21,
+//	.det_pin	= ... not connected
+	.rdy_pin	= AT91_PIN_PC15,
+	.enable_pin	= AT91_PIN_PC14,
+	.partition_info	= nand_partitions,
+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+	.bus_width_16	= 1,
+#else
+	.bus_width_16	= 0,
+#endif
+};
+
+/*
+ * SPI devices
+ */
+static struct spi_board_info ek_spi_devices[] = {
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	},
+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+	{	/* DataFlash card - jumper (J12) configurable to CS3 or CS0 */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 3,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	},
+#elif defined(CONFIG_SND_AT73C213)
+	{	/* AT73C213 DAC */
+		.modalias	= "snd_at73c213",
+		.chip_select	= 3,
+		.max_speed_hz	= 10 * 1000 * 1000,
+		.bus_num	= 0,
+	},
+#endif
+};
+
+
+static void __init ek_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* USB Host */
+	at91_add_device_usbh(&ek_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&ek_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* NAND */
+	at91_add_device_nand(&ek_nand_data);
+	/* DM9000 ethernet */
+	ek_add_device_dm9000();
+
+	/* spi0 and mmc/sd share the same PIO pins */
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+	/* SPI */
+	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+#else
+	/* MMC */
+	at91_add_device_mmc(0, &ek_mmc_data);
+#endif
+}
+
+MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
+	/* Maintainer: Atmel */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91sam926x_timer,
+	.map_io		= ek_map_io,
+	.init_irq	= ek_init_irq,
+	.init_machine	= ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
new file mode 100644
index 0000000..8fdce11
--- /dev/null
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -0,0 +1,176 @@
+/*
+ * linux/arch/arm/mach-at91/board-sam9263ek.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2007 Atmel 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
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ *    0 .. 2 = USART0 .. USART2
+ *    3      = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 3, 0, -1, -1, }		/* ttyS0, ..., ttyS3 */
+};
+
+static void __init ek_map_io(void)
+{
+	/* Initialize processor: 16.367 MHz crystal */
+	at91sam9263_initialize(16367660);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+	at91sam9263_init_interrupts(NULL);
+}
+
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+	.ports		= 2,
+	.vbus_pin	= { AT91_PIN_PA24, AT91_PIN_PA21 },
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+	.vbus_pin	= AT91_PIN_PA25,
+	.pullup_pin	= 0,		/* pull-up driven by UDC */
+};
+
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info ek_spi_devices[] = {
+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+	{	/* DataFlash card */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	},
+#endif
+};
+
+
+/*
+ * MCI (SD/MMC)
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+	.wire4		= 1,
+	.det_pin	= AT91_PIN_PE18,
+	.wp_pin		= AT91_PIN_PE19,
+//	.vcc_pin	= ... not connected
+};
+
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+	{
+		.name	= "Partition 1",
+		.offset	= 0,
+		.size	= 64 * 1024 * 1024,
+	},
+	{
+		.name	= "Partition 2",
+		.offset	= 64 * 1024 * 1024,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+	*num_partitions = ARRAY_SIZE(ek_nand_partition);
+	return ek_nand_partition;
+}
+
+static struct at91_nand_data __initdata ek_nand_data = {
+	.ale		= 21,
+	.cle		= 22,
+//	.det_pin	= ... not connected
+	.rdy_pin	= AT91_PIN_PA22,
+	.enable_pin	= AT91_PIN_PD15,
+	.partition_info	= nand_partitions,
+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+	.bus_width_16	= 1,
+#else
+	.bus_width_16	= 0,
+#endif
+};
+
+
+static void __init ek_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* USB Host */
+	at91_add_device_usbh(&ek_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&ek_udc_data);
+	/* SPI */
+	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+	/* MMC */
+	at91_add_device_mmc(1, &ek_mmc_data);
+	/* NAND */
+	at91_add_device_nand(&ek_nand_data);
+}
+
+MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
+	/* Maintainer: Atmel */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91sam926x_timer,
+	.map_io		= ek_map_io,
+	.init_irq	= ek_init_irq,
+	.init_machine	= ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
new file mode 100644
index 0000000..06c9a05
--- /dev/null
+++ b/arch/arm/mach-at91/clock.c
@@ -0,0 +1,640 @@
+/*
+ * linux/arch/arm/mach-at91/clock.c
+ *
+ * Copyright (C) 2005 David Brownell
+ * Copyright (C) 2005 Ivan Kokshaysky
+ *
+ * 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/init.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/cpu.h>
+
+#include "clock.h"
+
+
+/*
+ * There's a lot more which can be done with clocks, including cpufreq
+ * integration, slow clock mode support (for system suspend), letting
+ * PLLB be used at other rates (on boards that don't need USB), etc.
+ */
+
+#define clk_is_primary(x)	((x)->type & CLK_TYPE_PRIMARY)
+#define clk_is_programmable(x)	((x)->type & CLK_TYPE_PROGRAMMABLE)
+#define clk_is_peripheral(x)	((x)->type & CLK_TYPE_PERIPHERAL)
+#define clk_is_sys(x)		((x)->type & CLK_TYPE_SYSTEM)
+
+
+static LIST_HEAD(clocks);
+static DEFINE_SPINLOCK(clk_lock);
+
+static u32 at91_pllb_usb_init;
+
+/*
+ * Four primary clock sources:  two crystal oscillators (32K, main), and
+ * two PLLs.  PLLA usually runs the master clock; and PLLB must run at
+ * 48 MHz (unless no USB function clocks are needed).  The main clock and
+ * both PLLs are turned off to run in "slow clock mode" (system suspend).
+ */
+static struct clk clk32k = {
+	.name		= "clk32k",
+	.rate_hz	= AT91_SLOW_CLOCK,
+	.users		= 1,		/* always on */
+	.id		= 0,
+	.type		= CLK_TYPE_PRIMARY,
+};
+static struct clk main_clk = {
+	.name		= "main",
+	.pmc_mask	= AT91_PMC_MOSCS,	/* in PMC_SR */
+	.id		= 1,
+	.type		= CLK_TYPE_PRIMARY,
+};
+static struct clk plla = {
+	.name		= "plla",
+	.parent		= &main_clk,
+	.pmc_mask	= AT91_PMC_LOCKA,	/* in PMC_SR */
+	.id		= 2,
+	.type		= CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
+};
+
+static void pllb_mode(struct clk *clk, int is_on)
+{
+	u32	value;
+
+	if (is_on) {
+		is_on = AT91_PMC_LOCKB;
+		value = at91_pllb_usb_init;
+	} else
+		value = 0;
+
+	// REVISIT: Add work-around for AT91RM9200 Errata #26 ?
+	at91_sys_write(AT91_CKGR_PLLBR, value);
+
+	do {
+		cpu_relax();
+	} while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != is_on);
+}
+
+static struct clk pllb = {
+	.name		= "pllb",
+	.parent		= &main_clk,
+	.pmc_mask	= AT91_PMC_LOCKB,	/* in PMC_SR */
+	.mode		= pllb_mode,
+	.id		= 3,
+	.type		= CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
+};
+
+static void pmc_sys_mode(struct clk *clk, int is_on)
+{
+	if (is_on)
+		at91_sys_write(AT91_PMC_SCER, clk->pmc_mask);
+	else
+		at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask);
+}
+
+/* USB function clocks (PLLB must be 48 MHz) */
+static struct clk udpck = {
+	.name		= "udpck",
+	.parent		= &pllb,
+	.mode		= pmc_sys_mode,
+};
+static struct clk uhpck = {
+	.name		= "uhpck",
+	.parent		= &pllb,
+	.mode		= pmc_sys_mode,
+};
+
+
+/*
+ * The master clock is divided from the CPU clock (by 1-4).  It's used for
+ * memory, interfaces to on-chip peripherals, the AIC, and sometimes more
+ * (e.g baud rate generation).  It's sourced from one of the primary clocks.
+ */
+static struct clk mck = {
+	.name		= "mck",
+	.pmc_mask	= AT91_PMC_MCKRDY,	/* in PMC_SR */
+};
+
+static void pmc_periph_mode(struct clk *clk, int is_on)
+{
+	if (is_on)
+		at91_sys_write(AT91_PMC_PCER, clk->pmc_mask);
+	else
+		at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask);
+}
+
+static struct clk __init *at91_css_to_clk(unsigned long css)
+{
+	switch (css) {
+		case AT91_PMC_CSS_SLOW:
+			return &clk32k;
+		case AT91_PMC_CSS_MAIN:
+			return &main_clk;
+		case AT91_PMC_CSS_PLLA:
+			return &plla;
+		case AT91_PMC_CSS_PLLB:
+			return &pllb;
+	}
+
+	return NULL;
+}
+
+/*
+ * Associate a particular clock with a function (eg, "uart") and device.
+ * The drivers can then request the same 'function' with several different
+ * devices and not care about which clock name to use.
+ */
+void __init at91_clock_associate(const char *id, struct device *dev, const char *func)
+{
+	struct clk *clk = clk_get(NULL, id);
+
+	if (!dev || !clk || !IS_ERR(clk_get(dev, func)))
+		return;
+
+	clk->function = func;
+	clk->dev = dev;
+}
+
+/* clocks cannot be de-registered no refcounting necessary */
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *clk;
+
+	list_for_each_entry(clk, &clocks, node) {
+		if (strcmp(id, clk->name) == 0)
+			return clk;
+		if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0)
+			return clk;
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+static void __clk_enable(struct clk *clk)
+{
+	if (clk->parent)
+		__clk_enable(clk->parent);
+	if (clk->users++ == 0 && clk->mode)
+		clk->mode(clk, 1);
+}
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long	flags;
+
+	spin_lock_irqsave(&clk_lock, flags);
+	__clk_enable(clk);
+	spin_unlock_irqrestore(&clk_lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+static void __clk_disable(struct clk *clk)
+{
+	BUG_ON(clk->users == 0);
+	if (--clk->users == 0 && clk->mode)
+		clk->mode(clk, 0);
+	if (clk->parent)
+		__clk_disable(clk->parent);
+}
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long	flags;
+
+	spin_lock_irqsave(&clk_lock, flags);
+	__clk_disable(clk);
+	spin_unlock_irqrestore(&clk_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	unsigned long	flags;
+	unsigned long	rate;
+
+	spin_lock_irqsave(&clk_lock, flags);
+	for (;;) {
+		rate = clk->rate_hz;
+		if (rate || !clk->parent)
+			break;
+		clk = clk->parent;
+	}
+	spin_unlock_irqrestore(&clk_lock, flags);
+	return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+/*------------------------------------------------------------------------*/
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+
+/*
+ * For now, only the programmable clocks support reparenting (MCK could
+ * do this too, with care) or rate changing (the PLLs could do this too,
+ * ditto MCK but that's more for cpufreq).  Drivers may reparent to get
+ * a better rate match; we don't.
+ */
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long	flags;
+	unsigned	prescale;
+	unsigned long	actual;
+
+	if (!clk_is_programmable(clk))
+		return -EINVAL;
+	spin_lock_irqsave(&clk_lock, flags);
+
+	actual = clk->parent->rate_hz;
+	for (prescale = 0; prescale < 7; prescale++) {
+		if (actual && actual <= rate)
+			break;
+		actual >>= 1;
+	}
+
+	spin_unlock_irqrestore(&clk_lock, flags);
+	return (prescale < 7) ? actual : -ENOENT;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long	flags;
+	unsigned	prescale;
+	unsigned long	actual;
+
+	if (!clk_is_programmable(clk))
+		return -EINVAL;
+	if (clk->users)
+		return -EBUSY;
+	spin_lock_irqsave(&clk_lock, flags);
+
+	actual = clk->parent->rate_hz;
+	for (prescale = 0; prescale < 7; prescale++) {
+		if (actual && actual <= rate) {
+			u32	pckr;
+
+			pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
+			pckr &= AT91_PMC_CSS_PLLB;	/* clock selection */
+			pckr |= prescale << 2;
+			at91_sys_write(AT91_PMC_PCKR(clk->id), pckr);
+			clk->rate_hz = actual;
+			break;
+		}
+		actual >>= 1;
+	}
+
+	spin_unlock_irqrestore(&clk_lock, flags);
+	return (prescale < 7) ? actual : -ENOENT;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	unsigned long	flags;
+
+	if (clk->users)
+		return -EBUSY;
+	if (!clk_is_primary(parent) || !clk_is_programmable(clk))
+		return -EINVAL;
+	spin_lock_irqsave(&clk_lock, flags);
+
+	clk->rate_hz = parent->rate_hz;
+	clk->parent = parent;
+	at91_sys_write(AT91_PMC_PCKR(clk->id), parent->id);
+
+	spin_unlock_irqrestore(&clk_lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+/* establish PCK0..PCK3 parentage and rate */
+static void init_programmable_clock(struct clk *clk)
+{
+	struct clk	*parent;
+	u32		pckr;
+
+	pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
+	parent = at91_css_to_clk(pckr & AT91_PMC_CSS);
+	clk->parent = parent;
+	clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
+}
+
+#endif	/* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
+
+/*------------------------------------------------------------------------*/
+
+#ifdef CONFIG_DEBUG_FS
+
+static int at91_clk_show(struct seq_file *s, void *unused)
+{
+	u32		scsr, pcsr, sr;
+	struct clk	*clk;
+	unsigned	i;
+
+	seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
+	seq_printf(s, "PCSR = %8x\n", pcsr = at91_sys_read(AT91_PMC_PCSR));
+
+	seq_printf(s, "MOR  = %8x\n", at91_sys_read(AT91_CKGR_MOR));
+	seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR));
+	seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR));
+	seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
+
+	seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR));
+	for (i = 0; i < 4; i++)
+		seq_printf(s, "PCK%d = %8x\n", i, at91_sys_read(AT91_PMC_PCKR(i)));
+	seq_printf(s, "SR   = %8x\n", sr = at91_sys_read(AT91_PMC_SR));
+
+	seq_printf(s, "\n");
+
+	list_for_each_entry(clk, &clocks, node) {
+		char	*state;
+
+		if (clk->mode == pmc_sys_mode)
+			state = (scsr & clk->pmc_mask) ? "on" : "off";
+		else if (clk->mode == pmc_periph_mode)
+			state = (pcsr & clk->pmc_mask) ? "on" : "off";
+		else if (clk->pmc_mask)
+			state = (sr & clk->pmc_mask) ? "on" : "off";
+		else if (clk == &clk32k || clk == &main_clk)
+			state = "on";
+		else
+			state = "";
+
+		seq_printf(s, "%-10s users=%2d %-3s %9ld Hz %s\n",
+			clk->name, clk->users, state, clk_get_rate(clk),
+			clk->parent ? clk->parent->name : "");
+	}
+	return 0;
+}
+
+static int at91_clk_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, at91_clk_show, NULL);
+}
+
+static const struct file_operations at91_clk_operations = {
+	.open		= at91_clk_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init at91_clk_debugfs_init(void)
+{
+	/* /sys/kernel/debug/at91_clk */
+	(void) debugfs_create_file("at91_clk", S_IFREG | S_IRUGO, NULL, NULL, &at91_clk_operations);
+
+	return 0;
+}
+postcore_initcall(at91_clk_debugfs_init);
+
+#endif
+
+/*------------------------------------------------------------------------*/
+
+/* Register a new clock */
+int __init clk_register(struct clk *clk)
+{
+	if (clk_is_peripheral(clk)) {
+		clk->parent = &mck;
+		clk->mode = pmc_periph_mode;
+		list_add_tail(&clk->node, &clocks);
+	}
+	else if (clk_is_sys(clk)) {
+		clk->parent = &mck;
+		clk->mode = pmc_sys_mode;
+
+		list_add_tail(&clk->node, &clocks);
+	}
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+	else if (clk_is_programmable(clk)) {
+		clk->mode = pmc_sys_mode;
+		init_programmable_clock(clk);
+		list_add_tail(&clk->node, &clocks);
+	}
+#endif
+
+	return 0;
+}
+
+
+/*------------------------------------------------------------------------*/
+
+static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
+{
+	unsigned mul, div;
+
+	div = reg & 0xff;
+	mul = (reg >> 16) & 0x7ff;
+	if (div && mul) {
+		freq /= div;
+		freq *= mul + 1;
+	} else
+		freq = 0;
+
+	return freq;
+}
+
+static u32 __init at91_usb_rate(struct clk *pll, u32 freq, u32 reg)
+{
+	if (pll == &pllb && (reg & AT91_PMC_USB96M))
+		return freq / 2;
+	else
+		return freq;
+}
+
+static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq)
+{
+	unsigned i, div = 0, mul = 0, diff = 1 << 30;
+	unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
+
+	/* PLL output max 240 MHz (or 180 MHz per errata) */
+	if (out_freq > 240000000)
+		goto fail;
+
+	for (i = 1; i < 256; i++) {
+		int diff1;
+		unsigned input, mul1;
+
+		/*
+		 * PLL input between 1MHz and 32MHz per spec, but lower
+		 * frequences seem necessary in some cases so allow 100K.
+		 */
+		input = main_freq / i;
+		if (input < 100000)
+			continue;
+		if (input > 32000000)
+			continue;
+
+		mul1 = out_freq / input;
+		if (mul1 > 2048)
+			continue;
+		if (mul1 < 2)
+			goto fail;
+
+		diff1 = out_freq - input * mul1;
+		if (diff1 < 0)
+			diff1 = -diff1;
+		if (diff > diff1) {
+			diff = diff1;
+			div = i;
+			mul = mul1;
+			if (diff == 0)
+				break;
+		}
+	}
+	if (i == 256 && diff > (out_freq >> 5))
+		goto fail;
+	return ret | ((mul - 1) << 16) | div;
+fail:
+	return 0;
+}
+
+static struct clk *const standard_pmc_clocks[] __initdata = {
+	/* four primary clocks */
+	&clk32k,
+	&main_clk,
+	&plla,
+	&pllb,
+
+	/* PLLB children (USB) */
+	&udpck,
+	&uhpck,
+
+	/* MCK */
+	&mck
+};
+
+int __init at91_clock_init(unsigned long main_clock)
+{
+	unsigned tmp, freq, mckr;
+	int i;
+
+	/*
+	 * When the bootloader initialized the main oscillator correctly,
+	 * there's no problem using the cycle counter.  But if it didn't,
+	 * or when using oscillator bypass mode, we must be told the speed
+	 * of the main clock.
+	 */
+	if (!main_clock) {
+		do {
+			tmp = at91_sys_read(AT91_CKGR_MCFR);
+		} while (!(tmp & AT91_PMC_MAINRDY));
+		main_clock = (tmp & AT91_PMC_MAINF) * (AT91_SLOW_CLOCK / 16);
+	}
+	main_clk.rate_hz = main_clock;
+
+	/* report if PLLA is more than mildly overclocked */
+	plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR));
+	if (plla.rate_hz > 209000000)
+		pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
+
+	/*
+	 * USB clock init:  choose 48 MHz PLLB value,
+	 * disable 48MHz clock during usb peripheral suspend.
+	 *
+	 * REVISIT:  assumes MCK doesn't derive from PLLB!
+	 */
+	at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
+	pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
+	if (cpu_is_at91rm9200()) {
+		uhpck.pmc_mask = AT91RM9200_PMC_UHP;
+		udpck.pmc_mask = AT91RM9200_PMC_UDP;
+		at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
+	} else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) {
+		uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
+		udpck.pmc_mask = AT91SAM926x_PMC_UDP;
+	}
+	at91_sys_write(AT91_CKGR_PLLBR, 0);
+
+	udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
+	uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
+
+	/*
+	 * MCK and CPU derive from one of those primary clocks.
+	 * For now, assume this parentage won't change.
+	 */
+	mckr = at91_sys_read(AT91_PMC_MCKR);
+	mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
+	freq = mck.parent->rate_hz;
+	freq /= (1 << ((mckr >> 2) & 3));		/* prescale */
+	mck.rate_hz = freq / (1 + ((mckr >> 8) & 3));	/* mdiv */
+
+	/* Register the PMC's standard clocks */
+	for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
+		list_add_tail(&standard_pmc_clocks[i]->node, &clocks);
+
+	/* MCK and CPU clock are "always on" */
+	clk_enable(&mck);
+
+	printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n",
+		freq / 1000000, (unsigned) mck.rate_hz / 1000000,
+		(unsigned) main_clock / 1000000,
+		((unsigned) main_clock % 1000000) / 1000);
+
+	return 0;
+}
+
+/*
+ * Several unused clocks may be active.  Turn them off.
+ */
+static int __init at91_clock_reset(void)
+{
+	unsigned long pcdr = 0;
+	unsigned long scdr = 0;
+	struct clk *clk;
+
+	list_for_each_entry(clk, &clocks, node) {
+		if (clk->users > 0)
+			continue;
+
+		if (clk->mode == pmc_periph_mode)
+			pcdr |= clk->pmc_mask;
+
+		if (clk->mode == pmc_sys_mode)
+			scdr |= clk->pmc_mask;
+
+		pr_debug("Clocks: disable unused %s\n", clk->name);
+	}
+
+	at91_sys_write(AT91_PMC_PCDR, pcdr);
+	at91_sys_write(AT91_PMC_SCDR, scdr);
+
+	return 0;
+}
+late_initcall(at91_clock_reset);
diff --git a/arch/arm/mach-at91/clock.h b/arch/arm/mach-at91/clock.h
new file mode 100644
index 0000000..1ba3b95
--- /dev/null
+++ b/arch/arm/mach-at91/clock.h
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/arm/mach-at91/clock.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
+ * published by the Free Software Foundation.
+ */
+
+#define CLK_TYPE_PRIMARY	0x1
+#define CLK_TYPE_PLL		0x2
+#define CLK_TYPE_PROGRAMMABLE	0x4
+#define CLK_TYPE_PERIPHERAL	0x8
+#define CLK_TYPE_SYSTEM		0x10
+
+
+struct clk {
+	struct list_head node;
+	const char	*name;		/* unique clock name */
+	const char	*function;	/* function of the clock */
+	struct device	*dev;		/* device associated with function */
+	unsigned long	rate_hz;
+	struct clk	*parent;
+	u32		pmc_mask;
+	void		(*mode)(struct clk *, int);
+	unsigned	id:2;		/* PCK0..3, or 32k/main/a/b */
+	unsigned	type;		/* clock type */
+	u16		users;
+};
+
+
+extern int __init clk_register(struct clk *clk);
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
new file mode 100644
index 0000000..bda2622
--- /dev/null
+++ b/arch/arm/mach-at91/generic.h
@@ -0,0 +1,51 @@
+/*
+ * linux/arch/arm/mach-at91/generic.h
+ *
+ *  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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+ /* Processors */
+extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks);
+extern void __init at91sam9260_initialize(unsigned long main_clock);
+extern void __init at91sam9261_initialize(unsigned long main_clock);
+extern void __init at91sam9263_initialize(unsigned long main_clock);
+
+ /* Interrupts */
+extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
+extern void __init at91sam9260_init_interrupts(unsigned int priority[]);
+extern void __init at91sam9261_init_interrupts(unsigned int priority[]);
+extern void __init at91sam9263_init_interrupts(unsigned int priority[]);
+extern void __init at91_aic_init(unsigned int priority[]);
+
+ /* Timer */
+struct sys_timer;
+extern struct sys_timer at91rm9200_timer;
+extern struct sys_timer at91sam926x_timer;
+
+ /* Clocks */
+extern int __init at91_clock_init(unsigned long main_clock);
+struct device;
+extern void __init at91_clock_associate(const char *id, struct device *dev, const char *func);
+
+ /* Power Management */
+extern void at91_irq_suspend(void);
+extern void at91_irq_resume(void);
+
+ /* GPIO */
+#define AT91RM9200_PQFP		3	/* AT91RM9200 PQFP package has 3 banks */
+#define AT91RM9200_BGA		4	/* AT91RM9200 BGA package has 4 banks */
+
+struct at91_gpio_bank {
+	unsigned short id;		/* peripheral ID */
+	unsigned long offset;		/* offset from system peripheral base */
+	struct clk *clock;		/* associated clock */
+};
+extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks);
+extern void __init at91_gpio_irq_setup(void);
+
+extern void (*at91_arch_reset)(void);
+extern int at91_extern_irq;
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
new file mode 100644
index 0000000..7b87f3f
--- /dev/null
+++ b/arch/arm/mach-at91/gpio.c
@@ -0,0 +1,462 @@
+/*
+ * linux/arch/arm/mach-at91/gpio.c
+ *
+ * Copyright (C) 2005 HP Labs
+ *
+ * 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/clk.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/at91_pio.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+static struct at91_gpio_bank *gpio;
+static int gpio_banks;
+
+
+static inline void __iomem *pin_to_controller(unsigned pin)
+{
+	void __iomem *sys_base = (void __iomem *) AT91_VA_BASE_SYS;
+
+	pin -= PIN_BASE;
+	pin /= 32;
+	if (likely(pin < gpio_banks))
+		return sys_base + gpio[pin].offset;
+
+	return NULL;
+}
+
+static inline unsigned pin_to_mask(unsigned pin)
+{
+	pin -= PIN_BASE;
+	return 1 << (pin % 32);
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+/* Not all hardware capabilities are exposed through these calls; they
+ * only encapsulate the most common features and modes.  (So if you
+ * want to change signals in groups, do it directly.)
+ *
+ * Bootloaders will usually handle some of the pin multiplexing setup.
+ * The intent is certainly that by the time Linux is fully booted, all
+ * pins should have been fully initialized.  These setup calls should
+ * only be used by board setup routines, or possibly in driver probe().
+ *
+ * For bootloaders doing all that setup, these calls could be inlined
+ * as NOPs so Linux won't duplicate any setup code
+ */
+
+
+/*
+ * mux the pin to the "GPIO" peripheral role.
+ */
+int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+	__raw_writel(mask, pio + PIO_IDR);
+	__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+	__raw_writel(mask, pio + PIO_PER);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_GPIO_periph);
+
+
+/*
+ * mux the pin to the "A" internal peripheral role.
+ */
+int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+
+	__raw_writel(mask, pio + PIO_IDR);
+	__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+	__raw_writel(mask, pio + PIO_ASR);
+	__raw_writel(mask, pio + PIO_PDR);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_A_periph);
+
+
+/*
+ * mux the pin to the "B" internal peripheral role.
+ */
+int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+
+	__raw_writel(mask, pio + PIO_IDR);
+	__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+	__raw_writel(mask, pio + PIO_BSR);
+	__raw_writel(mask, pio + PIO_PDR);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_B_periph);
+
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
+ * configure it for an input.
+ */
+int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+
+	__raw_writel(mask, pio + PIO_IDR);
+	__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+	__raw_writel(mask, pio + PIO_ODR);
+	__raw_writel(mask, pio + PIO_PER);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_gpio_input);
+
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
+ * and configure it for an output.
+ */
+int __init_or_module at91_set_gpio_output(unsigned pin, int value)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+
+	__raw_writel(mask, pio + PIO_IDR);
+	__raw_writel(mask, pio + PIO_PUDR);
+	__raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
+	__raw_writel(mask, pio + PIO_OER);
+	__raw_writel(mask, pio + PIO_PER);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_gpio_output);
+
+
+/*
+ * enable/disable the glitch filter; mostly used with IRQ handling.
+ */
+int __init_or_module at91_set_deglitch(unsigned pin, int is_on)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+	__raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_deglitch);
+
+/*
+ * enable/disable the multi-driver; This is only valid for output and
+ * allows the output pin to run as an open collector output.
+ */
+int __init_or_module at91_set_multi_drive(unsigned pin, int is_on)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+
+	__raw_writel(mask, pio + (is_on ? PIO_MDER : PIO_MDDR));
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_multi_drive);
+
+/*--------------------------------------------------------------------------*/
+
+/* new-style GPIO calls; these expect at91_set_GPIO_periph to have been
+ * called, and maybe at91_set_multi_drive() for putout pins.
+ */
+
+int gpio_direction_input(unsigned pin)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
+		return -EINVAL;
+	__raw_writel(mask, pio + PIO_OER);
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned pin)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
+		return -EINVAL;
+	__raw_writel(mask, pio + PIO_OER);
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * assuming the pin is muxed as a gpio output, set its value.
+ */
+int at91_set_gpio_value(unsigned pin, int value)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+	__raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_gpio_value);
+
+
+/*
+ * read the pin's value (works even if it's not muxed as a gpio).
+ */
+int at91_get_gpio_value(unsigned pin)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+	u32		pdsr;
+
+	if (!pio)
+		return -EINVAL;
+	pdsr = __raw_readl(pio + PIO_PDSR);
+	return (pdsr & mask) != 0;
+}
+EXPORT_SYMBOL(at91_get_gpio_value);
+
+/*--------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+
+static u32 wakeups[MAX_GPIO_BANKS];
+static u32 backups[MAX_GPIO_BANKS];
+
+static int gpio_irq_set_wake(unsigned pin, unsigned state)
+{
+	unsigned	mask = pin_to_mask(pin);
+	unsigned	bank = (pin - PIN_BASE) / 32;
+
+	if (unlikely(bank >= MAX_GPIO_BANKS))
+		return -EINVAL;
+
+	if (state)
+		wakeups[bank] |= mask;
+	else
+		wakeups[bank] &= ~mask;
+
+	set_irq_wake(gpio[bank].id, state);
+
+	return 0;
+}
+
+void at91_gpio_suspend(void)
+{
+	int i;
+
+	for (i = 0; i < gpio_banks; i++) {
+		u32 pio = gpio[i].offset;
+
+		backups[i] = at91_sys_read(pio + PIO_IMR);
+		at91_sys_write(pio + PIO_IDR, backups[i]);
+		at91_sys_write(pio + PIO_IER, wakeups[i]);
+
+		if (!wakeups[i])
+			clk_disable(gpio[i].clock);
+		else {
+#ifdef CONFIG_PM_DEBUG
+			printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]);
+#endif
+		}
+	}
+}
+
+void at91_gpio_resume(void)
+{
+	int i;
+
+	for (i = 0; i < gpio_banks; i++) {
+		u32 pio = gpio[i].offset;
+
+		if (!wakeups[i])
+			clk_enable(gpio[i].clock);
+
+		at91_sys_write(pio + PIO_IDR, wakeups[i]);
+		at91_sys_write(pio + PIO_IER, backups[i]);
+	}
+}
+
+#else
+#define gpio_irq_set_wake	NULL
+#endif
+
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * at91_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler, though it always triggers on rising and falling edges.
+ *
+ * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after
+ * configuring them with at91_set_a_periph() or at91_set_b_periph().
+ * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
+ */
+
+static void gpio_irq_mask(unsigned pin)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (pio)
+		__raw_writel(mask, pio + PIO_IDR);
+}
+
+static void gpio_irq_unmask(unsigned pin)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (pio)
+		__raw_writel(mask, pio + PIO_IER);
+}
+
+static int gpio_irq_type(unsigned pin, unsigned type)
+{
+	return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.mask		= gpio_irq_mask,
+	.unmask		= gpio_irq_unmask,
+	.set_type	= gpio_irq_type,
+	.set_wake	= gpio_irq_set_wake,
+};
+
+static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	unsigned	pin;
+	struct irq_desc	*gpio;
+	void __iomem	*pio;
+	u32		isr;
+
+	pio = get_irq_chip_data(irq);
+
+	/* temporarily mask (level sensitive) parent IRQ */
+	desc->chip->ack(irq);
+	for (;;) {
+		/* reading ISR acks the pending (edge triggered) GPIO interrupt */
+		isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
+		if (!isr)
+			break;
+
+		pin = (unsigned) get_irq_data(irq);
+		gpio = &irq_desc[pin];
+
+		while (isr) {
+			if (isr & 1) {
+				if (unlikely(gpio->depth)) {
+					/*
+					 * The core ARM interrupt handler lazily disables IRQs so
+					 * another IRQ must be generated before it actually gets
+					 * here to be disabled on the GPIO controller.
+					 */
+					gpio_irq_mask(pin);
+				}
+				else
+					desc_handle_irq(pin, gpio);
+			}
+			pin++;
+			gpio++;
+			isr >>= 1;
+		}
+	}
+	desc->chip->unmask(irq);
+	/* now it may re-trigger */
+}
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Called from the processor-specific init to enable GPIO interrupt support.
+ */
+void __init at91_gpio_irq_setup(void)
+{
+	unsigned	pioc, pin;
+
+	for (pioc = 0, pin = PIN_BASE;
+			pioc < gpio_banks;
+			pioc++) {
+		void __iomem	*controller;
+		unsigned	id = gpio[pioc].id;
+		unsigned	i;
+
+		clk_enable(gpio[pioc].clock);	/* enable PIO controller's clock */
+
+		controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset;
+		__raw_writel(~0, controller + PIO_IDR);
+
+		set_irq_data(id, (void *) pin);
+		set_irq_chip_data(id, controller);
+
+		for (i = 0; i < 32; i++, pin++) {
+			/*
+			 * Can use the "simple" and not "edge" handler since it's
+			 * shorter, and the AIC handles interupts sanely.
+			 */
+			set_irq_chip(pin, &gpio_irqchip);
+			set_irq_handler(pin, handle_simple_irq);
+			set_irq_flags(pin, IRQF_VALID);
+		}
+
+		set_irq_chained_handler(id, gpio_irq_handler);
+	}
+	pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
+}
+
+/*
+ * Called from the processor-specific init to enable GPIO pin support.
+ */
+void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
+{
+	BUG_ON(nr_banks > MAX_GPIO_BANKS);
+
+	gpio = data;
+	gpio_banks = nr_banks;
+}
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
new file mode 100644
index 0000000..78a5cdb
--- /dev/null
+++ b/arch/arm/mach-at91/irq.c
@@ -0,0 +1,168 @@
+/*
+ * linux/arch/arm/mach-at91/irq.c
+ *
+ *  Copyright (C) 2004 SAN People
+ *  Copyright (C) 2004 ATMEL
+ *  Copyright (C) Rick Bronson
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+
+
+static void at91_aic_mask_irq(unsigned int irq)
+{
+	/* Disable interrupt on AIC */
+	at91_sys_write(AT91_AIC_IDCR, 1 << irq);
+}
+
+static void at91_aic_unmask_irq(unsigned int irq)
+{
+	/* Enable interrupt on AIC */
+	at91_sys_write(AT91_AIC_IECR, 1 << irq);
+}
+
+unsigned int at91_extern_irq;
+
+#define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq)
+
+static int at91_aic_set_type(unsigned irq, unsigned type)
+{
+	unsigned int smr, srctype;
+
+	switch (type) {
+	case IRQT_HIGH:
+		srctype = AT91_AIC_SRCTYPE_HIGH;
+		break;
+	case IRQT_RISING:
+		srctype = AT91_AIC_SRCTYPE_RISING;
+		break;
+	case IRQT_LOW:
+		if ((irq == AT91_ID_FIQ) || is_extern_irq(irq))		/* only supported on external interrupts */
+			srctype = AT91_AIC_SRCTYPE_LOW;
+		else
+			return -EINVAL;
+		break;
+	case IRQT_FALLING:
+		if ((irq == AT91_ID_FIQ) || is_extern_irq(irq))		/* only supported on external interrupts */
+			srctype = AT91_AIC_SRCTYPE_FALLING;
+		else
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	smr = at91_sys_read(AT91_AIC_SMR(irq)) & ~AT91_AIC_SRCTYPE;
+	at91_sys_write(AT91_AIC_SMR(irq), smr | srctype);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static u32 wakeups;
+static u32 backups;
+
+static int at91_aic_set_wake(unsigned irq, unsigned value)
+{
+	if (unlikely(irq >= 32))
+		return -EINVAL;
+
+	if (value)
+		wakeups |= (1 << irq);
+	else
+		wakeups &= ~(1 << irq);
+
+	return 0;
+}
+
+void at91_irq_suspend(void)
+{
+	backups = at91_sys_read(AT91_AIC_IMR);
+	at91_sys_write(AT91_AIC_IDCR, backups);
+	at91_sys_write(AT91_AIC_IECR, wakeups);
+}
+
+void at91_irq_resume(void)
+{
+	at91_sys_write(AT91_AIC_IDCR, wakeups);
+	at91_sys_write(AT91_AIC_IECR, backups);
+}
+
+#else
+#define at91_aic_set_wake	NULL
+#endif
+
+static struct irq_chip at91_aic_chip = {
+	.name		= "AIC",
+	.ack		= at91_aic_mask_irq,
+	.mask		= at91_aic_mask_irq,
+	.unmask		= at91_aic_unmask_irq,
+	.set_type	= at91_aic_set_type,
+	.set_wake	= at91_aic_set_wake,
+};
+
+/*
+ * Initialize the AIC interrupt controller.
+ */
+void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
+{
+	unsigned int i;
+
+	/*
+	 * The IVR is used by macro get_irqnr_and_base to read and verify.
+	 * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
+	 */
+	for (i = 0; i < NR_AIC_IRQS; i++) {
+		/* Put irq number in Source Vector Register: */
+		at91_sys_write(AT91_AIC_SVR(i), i);
+		/* Active Low interrupt, with the specified priority */
+		at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
+
+		set_irq_chip(i, &at91_aic_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+
+		/* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */
+		if (i < 8)
+			at91_sys_write(AT91_AIC_EOICR, 0);
+	}
+
+	/*
+	 * Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS
+	 * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU
+	 */
+	at91_sys_write(AT91_AIC_SPU, NR_AIC_IRQS);
+
+	/* No debugging in AIC: Debug (Protect) Control Register */
+	at91_sys_write(AT91_AIC_DCR, 0);
+
+	/* Disable and clear all interrupts initially */
+	at91_sys_write(AT91_AIC_IDCR, 0xFFFFFFFF);
+	at91_sys_write(AT91_AIC_ICCR, 0xFFFFFFFF);
+}
diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c
new file mode 100644
index 0000000..0d51449
--- /dev/null
+++ b/arch/arm/mach-at91/leds.c
@@ -0,0 +1,95 @@
+/*
+ * 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/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;
+
+	leds_event = at91_leds_event;
+
+	leds_event(led_start);
+	return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
new file mode 100644
index 0000000..b49bfda
--- /dev/null
+++ b/arch/arm/mach-at91/pm.c
@@ -0,0 +1,229 @@
+/*
+ * arch/arm/mach-at91/pm.c
+ * AT91 Power Management
+ *
+ * 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/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 <linux/platform_device.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/at91_pmc.h>
+#include <asm/arch/at91rm9200_mc.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/cpu.h>
+
+#include "generic.h"
+
+
+static int at91_pm_valid_state(suspend_state_t state)
+{
+	switch (state) {
+		case PM_SUSPEND_ON:
+		case PM_SUSPEND_STANDBY:
+		case PM_SUSPEND_MEM:
+			return 1;
+
+		default:
+			return 0;
+	}
+}
+
+
+static suspend_state_t target_state;
+
+/*
+ * Called after processes are frozen, but before we shutdown devices.
+ */
+static int at91_pm_prepare(suspend_state_t state)
+{
+	target_state = state;
+	return 0;
+}
+
+/*
+ * Verify that all the clocks are correct before entering
+ * slow-clock mode.
+ */
+static int at91_pm_verify_clocks(void)
+{
+	unsigned long scsr;
+	int i;
+
+	scsr = at91_sys_read(AT91_PMC_SCSR);
+
+	/* USB must not be using PLLB */
+	if (cpu_is_at91rm9200()) {
+		if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) {
+			pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
+			return 0;
+		}
+	} else if (cpu_is_at91sam9260()) {
+#warning "Check SAM9260 USB clocks"
+	} else if (cpu_is_at91sam9261()) {
+#warning "Check SAM9261 USB clocks"
+	} else if (cpu_is_at91sam9263()) {
+#warning "Check SAM9263 USB clocks"
+	}
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+	/* PCK0..PCK3 must be disabled, or configured to use clk32k */
+	for (i = 0; i < 4; i++) {
+		u32 css;
+
+		if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
+			continue;
+
+		css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
+		if (css != AT91_PMC_CSS_SLOW) {
+			pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
+			return 0;
+		}
+	}
+#endif
+
+	return 1;
+}
+
+/*
+ * Call this from platform driver suspend() to see how deeply to suspend.
+ * For example, some controllers (like OHCI) need one of the PLL clocks
+ * in order to act as a wakeup source, and those are not available when
+ * going into slow clock mode.
+ *
+ * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have
+ * the very same problem (but not using at91 main_clk), and it'd be better
+ * to add one generic API rather than lots of platform-specific ones.
+ */
+int at91_suspend_entering_slow_clock(void)
+{
+	return (target_state == PM_SUSPEND_MEM);
+}
+EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
+
+
+static void (*slow_clock)(void);
+
+
+static int at91_pm_enter(suspend_state_t state)
+{
+	at91_gpio_suspend();
+	at91_irq_suspend();
+
+	pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
+			/* remember all the always-wake irqs */
+			(at91_sys_read(AT91_PMC_PCSR)
+					| (1 << AT91_ID_FIQ)
+					| (1 << AT91_ID_SYS)
+					| (at91_extern_irq))
+				& at91_sys_read(AT91_AIC_IMR),
+			state);
+
+	switch (state) {
+		/*
+		 * Suspend-to-RAM is like STANDBY plus slow clock mode, so
+		 * drivers must suspend more deeply:  only the master clock
+		 * controller may be using the main oscillator.
+		 */
+		case PM_SUSPEND_MEM:
+			/*
+			 * Ensure that clocks are in a valid state.
+			 */
+			if (!at91_pm_verify_clocks())
+				goto error;
+
+			/*
+			 * Enter slow clock mode by switching over to clk32k and
+			 * turning off the main oscillator; reverse on wakeup.
+			 */
+			if (slow_clock) {
+				slow_clock();
+				break;
+			} else {
+				/* DEVELOPMENT ONLY */
+				pr_info("AT91: PM - no slow clock mode yet ...\n");
+				/* FALLTHROUGH leaving master clock alone */
+			}
+
+		/*
+		 * STANDBY mode has *all* drivers suspended; ignores irqs not
+		 * marked as 'wakeup' event sources; and reduces DRAM power.
+		 * But otherwise it's identical to PM_SUSPEND_ON:  cpu idle, and
+		 * nothing fancy done with main or cpu clocks.
+		 */
+		case PM_SUSPEND_STANDBY:
+			/*
+			 * NOTE: the Wait-for-Interrupt instruction needs to be
+			 * in icache so the SDRAM stays in self-refresh mode until
+			 * the wakeup IRQ occurs.
+			 */
+			asm("b 1f; .align 5; 1:");
+			asm("mcr p15, 0, r0, c7, c10, 4");	/* drain write buffer */
+			at91_sys_write(AT91_SDRAMC_SRR, 1);	/* self-refresh mode */
+			/* fall though to next state */
+
+		case PM_SUSPEND_ON:
+			asm("mcr p15, 0, r0, c7, c0, 4");	/* wait for interrupt */
+			break;
+
+		default:
+			pr_debug("AT91: PM - bogus suspend state %d\n", state);
+			goto error;
+	}
+
+	pr_debug("AT91: PM - wakeup %08x\n",
+			at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
+
+error:
+	target_state = PM_SUSPEND_ON;
+	at91_irq_resume();
+	at91_gpio_resume();
+	return 0;
+}
+
+
+static struct pm_ops at91_pm_ops ={
+	.pm_disk_mode	= 0,
+	.valid		= at91_pm_valid_state,
+	.prepare	= at91_pm_prepare,
+	.enter		= at91_pm_enter,
+};
+
+static int __init at91_pm_init(void)
+{
+	printk("AT91: Power Management\n");
+
+#ifdef CONFIG_AT91_PM_SLOW_CLOCK
+	/* REVISIT allocations of SRAM should be dynamically managed.
+	 * FIQ handlers and other components will want SRAM/TCM too...
+	 */
+	slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K));
+	memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz);
+#endif
+
+	/* Disable SDRAM low-power mode.  Cannot be used with self-refresh. */
+	at91_sys_write(AT91_SDRAMC_LPR, 0);
+
+	pm_set_ops(&at91_pm_ops);
+
+	return 0;
+}
+arch_initcall(at91_pm_init);
diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig
deleted file mode 100644
index 9f11db8..0000000
--- a/arch/arm/mach-at91rm9200/Kconfig
+++ /dev/null
@@ -1,148 +0,0 @@
-if ARCH_AT91
-
-menu "Atmel AT91 System-on-Chip"
-
-choice
-	prompt "Atmel AT91 Processor"
-
-config ARCH_AT91RM9200
-	bool "AT91RM9200"
-
-config ARCH_AT91SAM9260
-	bool "AT91SAM9260"
-
-config ARCH_AT91SAM9261
-	bool "AT91SAM9261"
-
-endchoice
-
-# ----------------------------------------------------------
-
-if ARCH_AT91RM9200
-
-comment "AT91RM9200 Board Type"
-
-config MACH_ONEARM
-	bool "Ajeco 1ARM Single Board Computer"
-	depends on ARCH_AT91RM9200
-	help
-	  Select this if you are using Ajeco's 1ARM Single Board Computer.
-	  <http://www.ajeco.fi/products.htm>
-
-config ARCH_AT91RM9200DK
-	bool "Atmel AT91RM9200-DK Development board"
-	depends on ARCH_AT91RM9200
-	help
-	  Select this if you are using Atmel's AT91RM9200-DK Development board.
-	  (Discontinued)
-
-config MACH_AT91RM9200EK
-	bool "Atmel AT91RM9200-EK Evaluation Kit"
-	depends on ARCH_AT91RM9200
-	help
-	  Select this if you are using Atmel's AT91RM9200-EK Evaluation Kit.
-	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3507>
-
-config MACH_CSB337
-	bool "Cogent CSB337"
-	depends on ARCH_AT91RM9200
-	help
-	  Select this if you are using Cogent's CSB337 board.
-	  <http://www.cogcomp.com/csb_csb337.htm>
-
-config MACH_CSB637
-	bool "Cogent CSB637"
-	depends on ARCH_AT91RM9200
-	help
-	  Select this if you are using Cogent's CSB637 board.
-	  <http://www.cogcomp.com/csb_csb637.htm>
-
-config MACH_CARMEVA
-	bool "Conitec ARM&EVA"
-	depends on ARCH_AT91RM9200
-	help
-	  Select this if you are using Conitec's AT91RM9200-MCU-Module.
-	  <http://www.conitec.net/english/linuxboard.htm>
-
-config MACH_ATEB9200
-	bool "Embest ATEB9200"
-	depends on ARCH_AT91RM9200
-	help
-	  Select this if you are using Embest's ATEB9200 board.
-	  <http://www.embedinfo.com/english/product/ATEB9200.asp>
-
-config MACH_KB9200
-	bool "KwikByte KB920x"
-	depends on ARCH_AT91RM9200
-	help
-	  Select this if you are using KwikByte's KB920x board.
-	  <http://kwikbyte.com/KB9202_description_new.htm>
-
-config MACH_KAFA
-	bool "Sperry-Sun KAFA board"
-	depends on ARCH_AT91RM9200
-	help
-	  Select this if you are using Sperry-Sun's KAFA board.
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9260
-
-comment "AT91SAM9260 Board Type"
-
-config MACH_AT91SAM9260EK
-	bool "Atmel AT91SAM9260-EK Evaluation Kit"
-	depends on ARCH_AT91SAM9260
-	help
-	  Select this if you are using Atmel's AT91SAM9260-EK Evaluation Kit.
-	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9261
-
-comment "AT91SAM9261 Board Type"
-
-config MACH_AT91SAM9261EK
-	bool "Atmel AT91SAM9261-EK Evaluation Kit"
-	depends on ARCH_AT91SAM9261
-	help
-	  Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit.
-	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3820>
-
-endif
-
-# ----------------------------------------------------------
-
-comment "AT91 Board Options"
-
-config MTD_AT91_DATAFLASH_CARD
-	bool "Enable DataFlash Card support"
-	depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK)
-	help
-	  Enable support for the DataFlash card.
-
-config MTD_NAND_AT91_BUSWIDTH_16
-	bool "Enable 16-bit data bus interface to NAND flash"
-	depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK)
-	help
-	  On AT91SAM926x boards both types of NAND flash can be present
-	  (8 and 16 bit data bus width).
-
-# ----------------------------------------------------------
-
-comment "AT91 Feature Selections"
-
-config AT91_PROGRAMMABLE_CLOCKS
-	bool "Programmable Clocks"
-	help
-	  Select this if you need to program one or more of the PCK0..PCK3
-	  programmable clock outputs.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile
deleted file mode 100644
index cf77700..0000000
--- a/arch/arm/mach-at91rm9200/Makefile
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-obj-y		:= clock.o irq.o gpio.o
-obj-m		:=
-obj-n		:=
-obj-		:=
-
-obj-$(CONFIG_PM)		+= pm.o
-
-# CPU-specific support
-obj-$(CONFIG_ARCH_AT91RM9200)	+= at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9260)	+= at91sam9260.o at91sam926x_time.o at91sam9260_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9261)	+= at91sam9261.o at91sam926x_time.o at91sam9261_devices.o
-
-# AT91RM9200 board-specific support
-obj-$(CONFIG_MACH_ONEARM)	+= board-1arm.o
-obj-$(CONFIG_ARCH_AT91RM9200DK)	+= board-dk.o
-obj-$(CONFIG_MACH_AT91RM9200EK)	+= board-ek.o
-obj-$(CONFIG_MACH_CSB337)	+= board-csb337.o
-obj-$(CONFIG_MACH_CSB637)	+= board-csb637.o
-obj-$(CONFIG_MACH_CARMEVA)	+= board-carmeva.o
-obj-$(CONFIG_MACH_KB9200)	+= board-kb9202.o
-obj-$(CONFIG_MACH_ATEB9200)	+= board-eb9200.o
-obj-$(CONFIG_MACH_KAFA)		+= board-kafa.o
-
-# AT91SAM9260 board-specific support
-obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
-
-# AT91SAM9261 board-specific support
-obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.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_MACH_KB9200)	+= leds.o
-led-$(CONFIG_MACH_KAFA)		+= leds.o
-obj-$(CONFIG_LEDS) += $(led-y)
-
-# VGA support
-#obj-$(CONFIG_FB_S1D13XXX)	+= ics1523.o
-
-
-ifeq ($(CONFIG_PM_DEBUG),y)
-CFLAGS_pm.o += -DDEBUG
-endif
diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91rm9200/at91rm9200.c
deleted file mode 100644
index a92e9a4..0000000
--- a/arch/arm/mach-at91rm9200/at91rm9200.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * arch/arm/mach-at91rm9200/at91rm9200.c
- *
- *  Copyright (C) 2005 SAN People
- *
- * 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 <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/arch/at91rm9200.h>
-#include <asm/arch/at91_pmc.h>
-#include <asm/arch/at91_st.h>
-
-#include "generic.h"
-#include "clock.h"
-
-static struct map_desc at91rm9200_io_desc[] __initdata = {
-	{
-		.virtual	= AT91_VA_BASE_SYS,
-		.pfn		= __phys_to_pfn(AT91_BASE_SYS),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_VA_BASE_EMAC,
-		.pfn		= __phys_to_pfn(AT91RM9200_BASE_EMAC),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE,
-		.pfn		= __phys_to_pfn(AT91RM9200_SRAM_BASE),
-		.length		= AT91RM9200_SRAM_SIZE,
-		.type		= MT_DEVICE,
-	},
-};
-
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-static struct clk udc_clk = {
-	.name		= "udc_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_UDP,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk ohci_clk = {
-	.name		= "ohci_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_UHP,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk ether_clk = {
-	.name		= "ether_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_EMAC,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc_clk = {
-	.name		= "mci_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_MCI,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi_clk = {
-	.name		= "twi_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_TWI,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-	.name		= "usart0_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_US0,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-	.name		= "usart1_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_US1,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-	.name		= "usart2_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_US2,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart3_clk = {
-	.name		= "usart3_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_US3,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi_clk = {
-	.name		= "spi_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_SPI,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioA_clk = {
-	.name		= "pioA_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_PIOA,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioB_clk = {
-	.name		= "pioB_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_PIOB,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioC_clk = {
-	.name		= "pioC_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_PIOC,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioD_clk = {
-	.name		= "pioD_clk",
-	.pmc_mask	= 1 << AT91RM9200_ID_PIOD,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-	&pioA_clk,
-	&pioB_clk,
-	&pioC_clk,
-	&pioD_clk,
-	&usart0_clk,
-	&usart1_clk,
-	&usart2_clk,
-	&usart3_clk,
-	&mmc_clk,
-	&udc_clk,
-	&twi_clk,
-	&spi_clk,
-	// ssc 0 .. ssc2
-	// tc0 .. tc5
-	&ohci_clk,
-	&ether_clk,
-	// irq0 .. irq6
-};
-
-/*
- * The four programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-	.name		= "pck0",
-	.pmc_mask	= AT91_PMC_PCK0,
-	.type		= CLK_TYPE_PROGRAMMABLE,
-	.id		= 0,
-};
-static struct clk pck1 = {
-	.name		= "pck1",
-	.pmc_mask	= AT91_PMC_PCK1,
-	.type		= CLK_TYPE_PROGRAMMABLE,
-	.id		= 1,
-};
-static struct clk pck2 = {
-	.name		= "pck2",
-	.pmc_mask	= AT91_PMC_PCK2,
-	.type		= CLK_TYPE_PROGRAMMABLE,
-	.id		= 2,
-};
-static struct clk pck3 = {
-	.name		= "pck3",
-	.pmc_mask	= AT91_PMC_PCK3,
-	.type		= CLK_TYPE_PROGRAMMABLE,
-	.id		= 3,
-};
-
-static void __init at91rm9200_register_clocks(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-		clk_register(periph_clocks[i]);
-
-	clk_register(&pck0);
-	clk_register(&pck1);
-	clk_register(&pck2);
-	clk_register(&pck3);
-}
-
-/* --------------------------------------------------------------------
- *  GPIO
- * -------------------------------------------------------------------- */
-
-static struct at91_gpio_bank at91rm9200_gpio[] = {
-	{
-		.id		= AT91RM9200_ID_PIOA,
-		.offset		= AT91_PIOA,
-		.clock		= &pioA_clk,
-	}, {
-		.id		= AT91RM9200_ID_PIOB,
-		.offset		= AT91_PIOB,
-		.clock		= &pioB_clk,
-	}, {
-		.id		= AT91RM9200_ID_PIOC,
-		.offset		= AT91_PIOC,
-		.clock		= &pioC_clk,
-	}, {
-		.id		= AT91RM9200_ID_PIOD,
-		.offset		= AT91_PIOD,
-		.clock		= &pioD_clk,
-	}
-};
-
-static void at91rm9200_reset(void)
-{
-	/*
-	 * Perform a hardware reset with the use of the Watchdog timer.
-	 */
-	at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
-	at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
-}
-
-
-/* --------------------------------------------------------------------
- *  AT91RM9200 processor initialization
- * -------------------------------------------------------------------- */
-void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks)
-{
-	/* Map peripherals */
-	iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
-
-	at91_arch_reset = at91rm9200_reset;
-	at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1)
-			| (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3)
-			| (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5)
-			| (1 << AT91RM9200_ID_IRQ6);
-
-	/* Init clock subsystem */
-	at91_clock_init(main_clock);
-
-	/* Register the processor-specific clocks */
-	at91rm9200_register_clocks();
-
-	/* Initialize GPIO subsystem */
-	at91_gpio_init(at91rm9200_gpio, banks);
-}
-
-
-/* --------------------------------------------------------------------
- *  Interrupt initialization
- * -------------------------------------------------------------------- */
-
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
-	7,	/* Advanced Interrupt Controller (FIQ) */
-	7,	/* System Peripherals */
-	0,	/* Parallel IO Controller A */
-	0,	/* Parallel IO Controller B */
-	0,	/* Parallel IO Controller C */
-	0,	/* Parallel IO Controller D */
-	6,	/* USART 0 */
-	6,	/* USART 1 */
-	6,	/* USART 2 */
-	6,	/* USART 3 */
-	0,	/* Multimedia Card Interface */
-	4,	/* USB Device Port */
-	0,	/* Two-Wire Interface */
-	6,	/* Serial Peripheral Interface */
-	5,	/* Serial Synchronous Controller 0 */
-	5,	/* Serial Synchronous Controller 1 */
-	5,	/* Serial Synchronous Controller 2 */
-	0,	/* Timer Counter 0 */
-	0,	/* Timer Counter 1 */
-	0,	/* Timer Counter 2 */
-	0,	/* Timer Counter 3 */
-	0,	/* Timer Counter 4 */
-	0,	/* Timer Counter 5 */
-	3,	/* USB Host port */
-	3,	/* Ethernet MAC */
-	0,	/* Advanced Interrupt Controller (IRQ0) */
-	0,	/* Advanced Interrupt Controller (IRQ1) */
-	0,	/* Advanced Interrupt Controller (IRQ2) */
-	0,	/* Advanced Interrupt Controller (IRQ3) */
-	0,	/* Advanced Interrupt Controller (IRQ4) */
-	0,	/* Advanced Interrupt Controller (IRQ5) */
-	0	/* Advanced Interrupt Controller (IRQ6) */
-};
-
-void __init at91rm9200_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-	if (!priority)
-		priority = at91rm9200_default_irq_priority;
-
-	/* Initialize the AIC interrupt controller */
-	at91_aic_init(priority);
-
-	/* Enable GPIO interrupts */
-	at91_gpio_irq_setup();
-}
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_devices.c b/arch/arm/mach-at91rm9200/at91rm9200_devices.c
deleted file mode 100644
index 57fac72..0000000
--- a/arch/arm/mach-at91rm9200/at91rm9200_devices.c
+++ /dev/null
@@ -1,875 +0,0 @@
-/*
- * arch/arm/mach-at91rm9200/at91rm9200_devices.c
- *
- *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
- *  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 <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/platform_device.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/at91rm9200.h>
-#include <asm/arch/at91rm9200_mc.h>
-
-#include "generic.h"
-
-#define SZ_512	0x00000200
-#define SZ_256	0x00000100
-#define SZ_16	0x00000010
-
-/* --------------------------------------------------------------------
- *  USB Host
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = 0xffffffffUL;
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_UHP_BASE,
-		.end	= AT91RM9200_UHP_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_UHP,
-		.end	= AT91RM9200_ID_UHP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_usbh_device = {
-	.name		= "at91_ohci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ohci_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-				.platform_data		= &usbh_data,
-	},
-	.resource	= usbh_resources,
-	.num_resources	= ARRAY_SIZE(usbh_resources),
-};
-
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-	if (!data)
-		return;
-
-	usbh_data = *data;
-	platform_device_register(&at91rm9200_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  USB Device (Gadget)
- * -------------------------------------------------------------------- */
-
-#ifdef CONFIG_USB_GADGET_AT91
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_UDP,
-		.end	= AT91RM9200_BASE_UDP + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_UDP,
-		.end	= AT91RM9200_ID_UDP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_udc_device = {
-	.name		= "at91_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data		= &udc_data,
-	},
-	.resource	= udc_resources,
-	.num_resources	= ARRAY_SIZE(udc_resources),
-};
-
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->vbus_pin) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-	}
-	if (data->pullup_pin)
-		at91_set_gpio_output(data->pullup_pin, 0);
-
-	udc_data = *data;
-	platform_device_register(&at91rm9200_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Ethernet
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE)
-static u64 eth_dmamask = 0xffffffffUL;
-static struct at91_eth_data eth_data;
-
-static struct resource eth_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_EMAC,
-		.end	= AT91_VA_BASE_EMAC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_EMAC,
-		.end	= AT91RM9200_ID_EMAC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_eth_device = {
-	.name		= "at91_ether",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &eth_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-				.platform_data		= &eth_data,
-	},
-	.resource	= eth_resources,
-	.num_resources	= ARRAY_SIZE(eth_resources),
-};
-
-void __init at91_add_device_eth(struct at91_eth_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->phy_irq_pin) {
-		at91_set_gpio_input(data->phy_irq_pin, 0);
-		at91_set_deglitch(data->phy_irq_pin, 1);
-	}
-
-	/* Pins used for MII and RMII */
-	at91_set_A_periph(AT91_PIN_PA16, 0);	/* EMDIO */
-	at91_set_A_periph(AT91_PIN_PA15, 0);	/* EMDC */
-	at91_set_A_periph(AT91_PIN_PA14, 0);	/* ERXER */
-	at91_set_A_periph(AT91_PIN_PA13, 0);	/* ERX1 */
-	at91_set_A_periph(AT91_PIN_PA12, 0);	/* ERX0 */
-	at91_set_A_periph(AT91_PIN_PA11, 0);	/* ECRS_ECRSDV */
-	at91_set_A_periph(AT91_PIN_PA10, 0);	/* ETX1 */
-	at91_set_A_periph(AT91_PIN_PA9, 0);	/* ETX0 */
-	at91_set_A_periph(AT91_PIN_PA8, 0);	/* ETXEN */
-	at91_set_A_periph(AT91_PIN_PA7, 0);	/* ETXCK_EREFCK */
-
-	if (!data->is_rmii) {
-		at91_set_B_periph(AT91_PIN_PB19, 0);	/* ERXCK */
-		at91_set_B_periph(AT91_PIN_PB18, 0);	/* ECOL */
-		at91_set_B_periph(AT91_PIN_PB17, 0);	/* ERXDV */
-		at91_set_B_periph(AT91_PIN_PB16, 0);	/* ERX3 */
-		at91_set_B_periph(AT91_PIN_PB15, 0);	/* ERX2 */
-		at91_set_B_periph(AT91_PIN_PB14, 0);	/* ETXER */
-		at91_set_B_periph(AT91_PIN_PB13, 0);	/* ETX3 */
-		at91_set_B_periph(AT91_PIN_PB12, 0);	/* ETX2 */
-	}
-
-	eth_data = *data;
-	platform_device_register(&at91rm9200_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Compact Flash / PCMCIA
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
-static struct at91_cf_data cf_data;
-
-#define CF_BASE		AT91_CHIPSELECT_4
-
-static struct resource cf_resources[] = {
-	[0] = {
-		.start	= CF_BASE,
-		/* ties up CS4, CS5 and CS6 */
-		.end	= 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,
-	},
-	.resource	= cf_resources,
-	.num_resources	= ARRAY_SIZE(cf_resources),
-};
-
-void __init at91_add_device_cf(struct at91_cf_data *data)
-{
-	unsigned int csa;
-
-	if (!data)
-		return;
-
-	data->chipselect = 4;		/* can only use EBI ChipSelect 4 */
-
-	/* 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);
-
-	/*
-	 * 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 */
-	);
-
-	/* input/irq */
-	if (data->irq_pin) {
-		at91_set_gpio_input(data->irq_pin, 1);
-		at91_set_deglitch(data->irq_pin, 1);
-	}
-	at91_set_gpio_input(data->det_pin, 1);
-	at91_set_deglitch(data->det_pin, 1);
-
-	/* outputs, initially off */
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-	at91_set_gpio_output(data->rst_pin, 0);
-
-	/* force poweron defaults for these pins ... */
-	at91_set_A_periph(AT91_PIN_PC9, 0);	/* A25/CFRNW */
-	at91_set_A_periph(AT91_PIN_PC10, 0);	/* NCS4/CFCS */
-	at91_set_A_periph(AT91_PIN_PC11, 0);	/* NCS5/CFCE1 */
-	at91_set_A_periph(AT91_PIN_PC12, 0);	/* NCS6/CFCE2 */
-
-	/* nWAIT is _not_ a default setting */
-	at91_set_A_periph(AT91_PIN_PC6, 1);	/* nWAIT */
-
-	cf_data = *data;
-	platform_device_register(&at91rm9200_cf_device);
-}
-#else
-void __init at91_add_device_cf(struct at91_cf_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  MMC / SD
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = 0xffffffffUL;
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_MCI,
-		.end	= AT91RM9200_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_MCI,
-		.end	= AT91RM9200_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mmc(struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA27, 0);
-
-	if (data->slot_b) {
-		/* CMD */
-		at91_set_B_periph(AT91_PIN_PA8, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_B_periph(AT91_PIN_PA9, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PA10, 1);
-			at91_set_B_periph(AT91_PIN_PA11, 1);
-			at91_set_B_periph(AT91_PIN_PA12, 1);
-		}
-	} else {
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA28, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA29, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PB3, 1);
-			at91_set_B_periph(AT91_PIN_PB4, 1);
-			at91_set_B_periph(AT91_PIN_PB5, 1);
-		}
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91rm9200_mmc_device);
-}
-#else
-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;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	{
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_8M - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at91rm9200_nand_device = {
-	.name		= "at91_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct at91_nand_data *data)
-{
-	unsigned int csa;
-
-	if (!data)
-		return;
-
-	/* enable the address range of CS3 */
-	csa = at91_sys_read(AT91_EBI_CSA);
-	at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS3A_SMC_SMARTMEDIA);
-
-	/* set the bus interface characteristics */
-	at91_sys_write(AT91_SMC_CSR(3), AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN
-		| AT91_SMC_NWS_(5)
-		| AT91_SMC_TDF_(1)
-		| AT91_SMC_RWSETUP_(0)	/* tDS Data Set up Time 30 - ns */
-		| AT91_SMC_RWHOLD_(1)	/* tDH Data Hold Time 20 - ns */
-	);
-
-	/* 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(&at91rm9200_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 resource twi_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_TWI,
-		.end	= AT91RM9200_BASE_TWI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_TWI,
-		.end	= AT91RM9200_ID_TWI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_twi_device = {
-	.name		= "at91_i2c",
-	.id		= -1,
-	.resource	= twi_resources,
-	.num_resources	= ARRAY_SIZE(twi_resources),
-};
-
-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
-
-
-/* --------------------------------------------------------------------
- *  SPI
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE)
-static u64 spi_dmamask = 0xffffffffUL;
-
-static struct resource spi_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_SPI,
-		.end	= AT91RM9200_BASE_SPI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_SPI,
-		.end	= AT91RM9200_ID_SPI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_spi_device = {
-	.name		= "at91_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-	},
-	.resource	= spi_resources,
-	.num_resources	= ARRAY_SIZE(spi_resources),
-};
-
-static const unsigned spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-
-	at91_set_A_periph(AT91_PIN_PA0, 0);	/* MISO */
-	at91_set_A_periph(AT91_PIN_PA1, 0);	/* MOSI */
-	at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPCK */
-
-	/* Enable SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else
-			cs_pin = spi_standard_cs[devices[i].chip_select];
-
-#ifdef CONFIG_SPI_AT91_MANUAL_CS
-		at91_set_gpio_output(cs_pin, 1);
-#else
-		at91_set_A_periph(cs_pin, 0);
-#endif
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-	at91_clock_associate("spi_clk", &at91rm9200_spi_device.dev, "spi");
-	platform_device_register(&at91rm9200_spi_device);
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  RTC
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
-static struct platform_device at91rm9200_rtc_device = {
-	.name		= "at91_rtc",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_rtc(void)
-{
-	platform_device_register(&at91rm9200_rtc_device);
-}
-#else
-static void __init at91_add_device_rtc(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91RM9200_WATCHDOG) || defined(CONFIG_AT91RM9200_WATCHDOG_MODULE)
-static struct platform_device at91rm9200_wdt_device = {
-	.name		= "at91_wdt",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-	platform_device_register(&at91rm9200_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(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
-
-
-/* --------------------------------------------------------------------
- *  UART
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
-
-static struct platform_device at91rm9200_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.platform_data	= &dbgu_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PA30, 0);		/* DRXD */
-	at91_set_A_periph(AT91_PIN_PA31, 1);		/* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_US0,
-		.end	= AT91RM9200_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_US0,
-		.end	= AT91RM9200_ID_US0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91rm9200_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.platform_data	= &uart0_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PA17, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PA18, 0);		/* RXD0 */
-	at91_set_A_periph(AT91_PIN_PA20, 0);		/* CTS0 */
-
-	/*
-	 * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21.
-	 *  We need to drive the pin manually.  Default is off (RTS is active low).
-	 */
-	at91_set_gpio_output(AT91_PIN_PA21, 1);
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_US1,
-		.end	= AT91RM9200_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_US1,
-		.end	= AT91RM9200_ID_US1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91rm9200_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.platform_data	= &uart1_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PB18, 0);		/* RI1 */
-	at91_set_A_periph(AT91_PIN_PB19, 0);		/* DTR1 */
-	at91_set_A_periph(AT91_PIN_PB20, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PB21, 0);		/* RXD1 */
-	at91_set_A_periph(AT91_PIN_PB23, 0);		/* DCD1 */
-	at91_set_A_periph(AT91_PIN_PB24, 0);		/* CTS1 */
-	at91_set_A_periph(AT91_PIN_PB25, 0);		/* DSR1 */
-	at91_set_A_periph(AT91_PIN_PB26, 0);		/* RTS1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_US2,
-		.end	= AT91RM9200_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_US2,
-		.end	= AT91RM9200_ID_US2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91rm9200_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.platform_data	= &uart2_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PA22, 0);		/* RXD2 */
-	at91_set_A_periph(AT91_PIN_PA23, 1);		/* TXD2 */
-}
-
-static struct resource uart3_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_US3,
-		.end	= AT91RM9200_BASE_US3 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_US3,
-		.end	= AT91RM9200_ID_US3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart3_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91rm9200_uart3_device = {
-	.name		= "atmel_usart",
-	.id		= 4,
-	.dev		= {
-				.platform_data	= &uart3_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart3_resources,
-	.num_resources	= ARRAY_SIZE(uart3_resources),
-};
-
-static inline void configure_usart3_pins(void)
-{
-	at91_set_B_periph(AT91_PIN_PA5, 1);		/* TXD3 */
-	at91_set_B_periph(AT91_PIN_PA6, 0);		/* RXD3 */
-}
-
-struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_init_serial(struct at91_uart_config *config)
-{
-	int i;
-
-	/* Fill in list of supported UARTs */
-	for (i = 0; i < config->nr_tty; i++) {
-		switch (config->tty_map[i]) {
-			case 0:
-				configure_usart0_pins();
-				at91_uarts[i] = &at91rm9200_uart0_device;
-				at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart");
-				break;
-			case 1:
-				configure_usart1_pins();
-				at91_uarts[i] = &at91rm9200_uart1_device;
-				at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart");
-				break;
-			case 2:
-				configure_usart2_pins();
-				at91_uarts[i] = &at91rm9200_uart2_device;
-				at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart");
-				break;
-			case 3:
-				configure_usart3_pins();
-				at91_uarts[i] = &at91rm9200_uart3_device;
-				at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart");
-				break;
-			case 4:
-				configure_dbgu_pins();
-				at91_uarts[i] = &at91rm9200_dbgu_device;
-				at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart");
-				break;
-			default:
-				continue;
-		}
-		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
-	}
-
-	/* Set serial console device */
-	if (config->console_tty < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[config->console_tty];
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-}
-#else
-void __init at91_init_serial(struct at91_uart_config *config) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
-
-/* -------------------------------------------------------------------- */
-
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	at91_add_device_rtc();
-	at91_add_device_watchdog();
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91rm9200/at91rm9200_time.c
deleted file mode 100644
index b999e19..0000000
--- a/arch/arm/mach-at91rm9200/at91rm9200_time.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/at91rm9200_time.c
- *
- *  Copyright (C) 2003 SAN People
- *  Copyright (C) 2003 ATMEL
- *
- * 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/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/mach/time.h>
-
-#include <asm/arch/at91_st.h>
-
-static unsigned long last_crtr;
-
-/*
- * The ST_CRTR is updated asynchronously to the master clock.  It is therefore
- *  necessary to read it twice (with the same value) to ensure accuracy.
- */
-static inline unsigned long read_CRTR(void) {
-	unsigned long x1, x2;
-
-	do {
-		x1 = at91_sys_read(AT91_ST_CRTR);
-		x2 = at91_sys_read(AT91_ST_CRTR);
-	} while (x1 != x2);
-
-	return x1;
-}
-
-/*
- * Returns number of microseconds since last timer interrupt.  Note that interrupts
- * will have been disabled by do_gettimeofday()
- *  'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
- *  'tick' is usecs per jiffy (linux/timex.h).
- */
-static unsigned long at91rm9200_gettimeoffset(void)
-{
-	unsigned long elapsed;
-
-	elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV;
-
-	return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
-}
-
-/*
- * IRQ handler for the timer.
- */
-static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
-{
-	if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) {	/* This is a shared interrupt */
-		write_seqlock(&xtime_lock);
-
-		while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) {
-			timer_tick();
-			last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV;
-		}
-
-		write_sequnlock(&xtime_lock);
-
-		return IRQ_HANDLED;
-	}
-	else
-		return IRQ_NONE;		/* not handled */
-}
-
-static struct irqaction at91rm9200_timer_irq = {
-	.name		= "at91_tick",
-	.flags		= IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER,
-	.handler	= at91rm9200_timer_interrupt
-};
-
-void at91rm9200_timer_reset(void)
-{
-	last_crtr = 0;
-
-	/* Real time counter incremented every 30.51758 microseconds */
-	at91_sys_write(AT91_ST_RTMR, 1);
-
-	/* Set Period Interval timer */
-	at91_sys_write(AT91_ST_PIMR, LATCH);
-
-	/* Clear any pending interrupts */
-	(void) at91_sys_read(AT91_ST_SR);
-
-	/* Enable Period Interval Timer interrupt */
-	at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
-}
-
-/*
- * Set up timer interrupt.
- */
-void __init at91rm9200_timer_init(void)
-{
-	/* Disable all timer interrupts */
-	at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
-	(void) at91_sys_read(AT91_ST_SR);	/* Clear any pending interrupts */
-
-	/* Make IRQs happen for the system timer */
-	setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
-
-	/* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */
-	tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE;
-
-	/* Initialize and enable the timer interrupt */
-	at91rm9200_timer_reset();
-}
-
-#ifdef CONFIG_PM
-static void at91rm9200_timer_suspend(void)
-{
-	/* disable Period Interval Timer interrupt */
-	at91_sys_write(AT91_ST_IDR, AT91_ST_PITS);
-}
-#else
-#define at91rm9200_timer_suspend	NULL
-#endif
-
-struct sys_timer at91rm9200_timer = {
-	.init		= at91rm9200_timer_init,
-	.offset		= at91rm9200_gettimeoffset,
-	.suspend	= at91rm9200_timer_suspend,
-	.resume		= at91rm9200_timer_reset,
-};
-
diff --git a/arch/arm/mach-at91rm9200/at91sam9260.c b/arch/arm/mach-at91rm9200/at91sam9260.c
deleted file mode 100644
index b14871a..0000000
--- a/arch/arm/mach-at91rm9200/at91sam9260.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * arch/arm/mach-at91rm9200/at91sam9260.c
- *
- *  Copyright (C) 2006 SAN People
- *
- * 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 <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/arch/at91sam9260.h>
-#include <asm/arch/at91_pmc.h>
-#include <asm/arch/at91_rstc.h>
-
-#include "generic.h"
-#include "clock.h"
-
-static struct map_desc at91sam9260_io_desc[] __initdata = {
-	{
-		.virtual	= AT91_VA_BASE_SYS,
-		.pfn		= __phys_to_pfn(AT91_BASE_SYS),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE,
-		.pfn		= __phys_to_pfn(AT91SAM9260_SRAM0_BASE),
-		.length		= AT91SAM9260_SRAM0_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE - AT91SAM9260_SRAM1_SIZE,
-		.pfn		= __phys_to_pfn(AT91SAM9260_SRAM1_BASE),
-		.length		= AT91SAM9260_SRAM1_SIZE,
-		.type		= MT_DEVICE,
-	},
-};
-
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-static struct clk pioA_clk = {
-	.name		= "pioA_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_PIOA,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioB_clk = {
-	.name		= "pioB_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_PIOB,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioC_clk = {
-	.name		= "pioC_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_PIOC,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk adc_clk = {
-	.name		= "adc_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_ADC,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-	.name		= "usart0_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_US0,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-	.name		= "usart1_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_US1,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-	.name		= "usart2_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_US2,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc_clk = {
-	.name		= "mci_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_MCI,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk udc_clk = {
-	.name		= "udc_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_UDP,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi_clk = {
-	.name		= "twi_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_TWI,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi0_clk = {
-	.name		= "spi0_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_SPI0,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi1_clk = {
-	.name		= "spi1_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_SPI1,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk ohci_clk = {
-	.name		= "ohci_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_UHP,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk ether_clk = {
-	.name		= "ether_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_EMAC,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk isi_clk = {
-	.name		= "isi_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_ISI,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart3_clk = {
-	.name		= "usart3_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_US3,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart4_clk = {
-	.name		= "usart4_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_US4,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart5_clk = {
-	.name		= "usart5_clk",
-	.pmc_mask	= 1 << AT91SAM9260_ID_US5,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-	&pioA_clk,
-	&pioB_clk,
-	&pioC_clk,
-	&adc_clk,
-	&usart0_clk,
-	&usart1_clk,
-	&usart2_clk,
-	&mmc_clk,
-	&udc_clk,
-	&twi_clk,
-	&spi0_clk,
-	&spi1_clk,
-	// ssc
-	// tc0 .. tc2
-	&ohci_clk,
-	&ether_clk,
-	&isi_clk,
-	&usart3_clk,
-	&usart4_clk,
-	&usart5_clk,
-	// tc3 .. tc5
-	// irq0 .. irq2
-};
-
-/*
- * The two programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-	.name		= "pck0",
-	.pmc_mask	= AT91_PMC_PCK0,
-	.type		= CLK_TYPE_PROGRAMMABLE,
-	.id		= 0,
-};
-static struct clk pck1 = {
-	.name		= "pck1",
-	.pmc_mask	= AT91_PMC_PCK1,
-	.type		= CLK_TYPE_PROGRAMMABLE,
-	.id		= 1,
-};
-
-static void __init at91sam9260_register_clocks(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-		clk_register(periph_clocks[i]);
-
-	clk_register(&pck0);
-	clk_register(&pck1);
-}
-
-/* --------------------------------------------------------------------
- *  GPIO
- * -------------------------------------------------------------------- */
-
-static struct at91_gpio_bank at91sam9260_gpio[] = {
-	{
-		.id		= AT91SAM9260_ID_PIOA,
-		.offset		= AT91_PIOA,
-		.clock		= &pioA_clk,
-	}, {
-		.id		= AT91SAM9260_ID_PIOB,
-		.offset		= AT91_PIOB,
-		.clock		= &pioB_clk,
-	}, {
-		.id		= AT91SAM9260_ID_PIOC,
-		.offset		= AT91_PIOC,
-		.clock		= &pioC_clk,
-	}
-};
-
-static void at91sam9260_reset(void)
-{
-	at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
-
-/* --------------------------------------------------------------------
- *  AT91SAM9260 processor initialization
- * -------------------------------------------------------------------- */
-
-void __init at91sam9260_initialize(unsigned long main_clock)
-{
-	/* Map peripherals */
-	iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
-
-	at91_arch_reset = at91sam9260_reset;
-	at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
-			| (1 << AT91SAM9260_ID_IRQ2);
-
-	/* Init clock subsystem */
-	at91_clock_init(main_clock);
-
-	/* Register the processor-specific clocks */
-	at91sam9260_register_clocks();
-
-	/* Register GPIO subsystem */
-	at91_gpio_init(at91sam9260_gpio, 3);
-}
-
-/* --------------------------------------------------------------------
- *  Interrupt initialization
- * -------------------------------------------------------------------- */
-
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
-	7,	/* Advanced Interrupt Controller */
-	7,	/* System Peripherals */
-	0,	/* Parallel IO Controller A */
-	0,	/* Parallel IO Controller B */
-	0,	/* Parallel IO Controller C */
-	0,	/* Analog-to-Digital Converter */
-	6,	/* USART 0 */
-	6,	/* USART 1 */
-	6,	/* USART 2 */
-	0,	/* Multimedia Card Interface */
-	4,	/* USB Device Port */
-	0,	/* Two-Wire Interface */
-	6,	/* Serial Peripheral Interface 0 */
-	6,	/* Serial Peripheral Interface 1 */
-	5,	/* Serial Synchronous Controller */
-	0,
-	0,
-	0,	/* Timer Counter 0 */
-	0,	/* Timer Counter 1 */
-	0,	/* Timer Counter 2 */
-	3,	/* USB Host port */
-	3,	/* Ethernet */
-	0,	/* Image Sensor Interface */
-	6,	/* USART 3 */
-	6,	/* USART 4 */
-	6,	/* USART 5 */
-	0,	/* Timer Counter 3 */
-	0,	/* Timer Counter 4 */
-	0,	/* Timer Counter 5 */
-	0,	/* Advanced Interrupt Controller */
-	0,	/* Advanced Interrupt Controller */
-	0,	/* Advanced Interrupt Controller */
-};
-
-void __init at91sam9260_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-	if (!priority)
-		priority = at91sam9260_default_irq_priority;
-
-	/* Initialize the AIC interrupt controller */
-	at91_aic_init(priority);
-
-	/* Enable GPIO interrupts */
-	at91_gpio_irq_setup();
-}
diff --git a/arch/arm/mach-at91rm9200/at91sam9260_devices.c b/arch/arm/mach-at91rm9200/at91sam9260_devices.c
deleted file mode 100644
index f42d3a4..0000000
--- a/arch/arm/mach-at91rm9200/at91sam9260_devices.c
+++ /dev/null
@@ -1,867 +0,0 @@
-/*
- * arch/arm/mach-at91rm9200/at91sam9260_devices.c
- *
- *  Copyright (C) 2006 Atmel
- *
- * 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/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/platform_device.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/at91sam9260.h>
-#include <asm/arch/at91sam926x_mc.h>
-#include <asm/arch/at91sam9260_matrix.h>
-
-#include "generic.h"
-
-#define SZ_512	0x00000200
-#define SZ_256	0x00000100
-#define SZ_16	0x00000010
-
-/* --------------------------------------------------------------------
- *  USB Host
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = 0xffffffffUL;
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_UHP_BASE,
-		.end	= AT91SAM9260_UHP_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_UHP,
-		.end	= AT91SAM9260_ID_UHP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91_usbh_device = {
-	.name		= "at91_ohci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ohci_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-				.platform_data		= &usbh_data,
-	},
-	.resource	= usbh_resources,
-	.num_resources	= ARRAY_SIZE(usbh_resources),
-};
-
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-	if (!data)
-		return;
-
-	usbh_data = *data;
-	platform_device_register(&at91_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  USB Device (Gadget)
- * -------------------------------------------------------------------- */
-
-#ifdef CONFIG_USB_GADGET_AT91
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_UDP,
-		.end	= AT91SAM9260_BASE_UDP + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_UDP,
-		.end	= AT91SAM9260_ID_UDP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91_udc_device = {
-	.name		= "at91_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data		= &udc_data,
-	},
-	.resource	= udc_resources,
-	.num_resources	= ARRAY_SIZE(udc_resources),
-};
-
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->vbus_pin) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-	}
-
-	/* Pullup pin is handled internally by USB device peripheral */
-
-	udc_data = *data;
-	platform_device_register(&at91_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Ethernet
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
-static u64 eth_dmamask = 0xffffffffUL;
-static struct eth_platform_data eth_data;
-
-static struct resource eth_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_EMAC,
-		.end	= AT91SAM9260_BASE_EMAC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_EMAC,
-		.end	= AT91SAM9260_ID_EMAC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_eth_device = {
-	.name		= "macb",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &eth_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-				.platform_data		= &eth_data,
-	},
-	.resource	= eth_resources,
-	.num_resources	= ARRAY_SIZE(eth_resources),
-};
-
-void __init at91_add_device_eth(struct eth_platform_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->phy_irq_pin) {
-		at91_set_gpio_input(data->phy_irq_pin, 0);
-		at91_set_deglitch(data->phy_irq_pin, 1);
-	}
-
-	/* Pins used for MII and RMII */
-	at91_set_A_periph(AT91_PIN_PA19, 0);	/* ETXCK_EREFCK */
-	at91_set_A_periph(AT91_PIN_PA17, 0);	/* ERXDV */
-	at91_set_A_periph(AT91_PIN_PA14, 0);	/* ERX0 */
-	at91_set_A_periph(AT91_PIN_PA15, 0);	/* ERX1 */
-	at91_set_A_periph(AT91_PIN_PA18, 0);	/* ERXER */
-	at91_set_A_periph(AT91_PIN_PA16, 0);	/* ETXEN */
-	at91_set_A_periph(AT91_PIN_PA12, 0);	/* ETX0 */
-	at91_set_A_periph(AT91_PIN_PA13, 0);	/* ETX1 */
-	at91_set_A_periph(AT91_PIN_PA21, 0);	/* EMDIO */
-	at91_set_A_periph(AT91_PIN_PA20, 0);	/* EMDC */
-
-	if (!data->is_rmii) {
-		at91_set_B_periph(AT91_PIN_PA28, 0);	/* ECRS */
-		at91_set_B_periph(AT91_PIN_PA29, 0);	/* ECOL */
-		at91_set_B_periph(AT91_PIN_PA25, 0);	/* ERX2 */
-		at91_set_B_periph(AT91_PIN_PA26, 0);	/* ERX3 */
-		at91_set_B_periph(AT91_PIN_PA27, 0);	/* ERXCK */
-		at91_set_B_periph(AT91_PIN_PA23, 0);	/* ETX2 */
-		at91_set_B_periph(AT91_PIN_PA24, 0);	/* ETX3 */
-		at91_set_B_periph(AT91_PIN_PA22, 0);	/* ETXER */
-	}
-
-	eth_data = *data;
-	platform_device_register(&at91sam9260_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct eth_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  MMC / SD
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = 0xffffffffUL;
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_MCI,
-		.end	= AT91SAM9260_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_MCI,
-		.end	= AT91SAM9260_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mmc(struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA8, 0);
-
-	if (data->slot_b) {
-		/* CMD */
-		at91_set_B_periph(AT91_PIN_PA1, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_B_periph(AT91_PIN_PA0, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PA5, 1);
-			at91_set_B_periph(AT91_PIN_PA4, 1);
-			at91_set_B_periph(AT91_PIN_PA3, 1);
-		}
-	} else {
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA7, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA6, 1);
-		if (data->wire4) {
-			at91_set_A_periph(AT91_PIN_PA9, 1);
-			at91_set_A_periph(AT91_PIN_PA10, 1);
-			at91_set_A_periph(AT91_PIN_PA11, 1);
-		}
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91sam9260_mmc_device);
-}
-#else
-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;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	{
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_8M - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at91sam9260_nand_device = {
-	.name		= "at91_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct at91_nand_data *data)
-{
-	unsigned long csa, mode;
-
-	if (!data)
-		return;
-
-	csa = at91_sys_read(AT91_MATRIX_EBICSA);
-	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC);
-
-	/* set the bus interface characteristics */
-	at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
-			| AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
-
-	at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5)
-			| AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5));
-
-	at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7));
-
-	if (data->bus_width_16)
-		mode = AT91_SMC_DBW_16;
-	else
-		mode = AT91_SMC_DBW_8;
-	at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1));
-
-	/* 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);
-
-	nand_data = *data;
-	platform_device_register(&at91sam9260_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 resource twi_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_TWI,
-		.end	= AT91SAM9260_BASE_TWI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_TWI,
-		.end	= AT91SAM9260_ID_TWI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_twi_device = {
-	.name		= "at91_i2c",
-	.id		= -1,
-	.resource	= twi_resources,
-	.num_resources	= ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(void)
-{
-	/* pins used for TWI interface */
-	at91_set_A_periph(AT91_PIN_PA23, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PA23, 1);
-
-	at91_set_A_periph(AT91_PIN_PA24, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PA24, 1);
-
-	platform_device_register(&at91sam9260_twi_device);
-}
-#else
-void __init at91_add_device_i2c(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SPI
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = 0xffffffffUL;
-
-static struct resource spi0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_SPI0,
-		.end	= AT91SAM9260_BASE_SPI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_SPI0,
-		.end	= AT91SAM9260_ID_SPI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_spi0_device = {
-	.name		= "atmel_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-	},
-	.resource	= spi0_resources,
-	.num_resources	= ARRAY_SIZE(spi0_resources),
-};
-
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PC11, AT91_PIN_PC16, AT91_PIN_PC17 };
-
-static struct resource spi1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_SPI1,
-		.end	= AT91SAM9260_BASE_SPI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_SPI1,
-		.end	= AT91SAM9260_ID_SPI1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_spi1_device = {
-	.name		= "atmel_spi",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-	},
-	.resource	= spi1_resources,
-	.num_resources	= ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PC5, AT91_PIN_PC4, AT91_PIN_PC3 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-	short enable_spi0 = 0;
-	short enable_spi1 = 0;
-
-	/* Choose SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else if (devices[i].bus_num == 0)
-			cs_pin = spi0_standard_cs[devices[i].chip_select];
-		else
-			cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-		if (devices[i].bus_num == 0)
-			enable_spi0 = 1;
-		else
-			enable_spi1 = 1;
-
-		/* enable chip-select pin */
-		at91_set_gpio_output(cs_pin, 1);
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-
-	/* Configure SPI bus(es) */
-	if (enable_spi0) {
-		at91_set_A_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */
-		at91_set_A_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */
-		at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPI1_SPCK */
-
-		at91_clock_associate("spi0_clk", &at91sam9260_spi0_device.dev, "spi_clk");
-		platform_device_register(&at91sam9260_spi0_device);
-	}
-	if (enable_spi1) {
-		at91_set_A_periph(AT91_PIN_PB0, 0);	/* SPI1_MISO */
-		at91_set_A_periph(AT91_PIN_PB1, 0);	/* SPI1_MOSI */
-		at91_set_A_periph(AT91_PIN_PB2, 0);	/* SPI1_SPCK */
-
-		at91_clock_associate("spi1_clk", &at91sam9260_spi1_device.dev, "spi_clk");
-		platform_device_register(&at91sam9260_spi1_device);
-	}
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#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
-
-
-/* --------------------------------------------------------------------
- *  UART
- * -------------------------------------------------------------------- */
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
-
-static struct platform_device at91sam9260_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.platform_data	= &dbgu_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PB14, 0);		/* DRXD */
-	at91_set_A_periph(AT91_PIN_PB15, 1);		/* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US0,
-		.end	= AT91SAM9260_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US0,
-		.end	= AT91SAM9260_ID_US0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91sam9260_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.platform_data	= &uart0_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PB4, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PB5, 0);		/* RXD0 */
-	at91_set_A_periph(AT91_PIN_PB26, 0);		/* RTS0 */
-	at91_set_A_periph(AT91_PIN_PB27, 0);		/* CTS0 */
-	at91_set_A_periph(AT91_PIN_PB24, 0);		/* DTR0 */
-	at91_set_A_periph(AT91_PIN_PB22, 0);		/* DSR0 */
-	at91_set_A_periph(AT91_PIN_PB23, 0);		/* DCD0 */
-	at91_set_A_periph(AT91_PIN_PB25, 0);		/* RI0 */
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US1,
-		.end	= AT91SAM9260_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US1,
-		.end	= AT91SAM9260_ID_US1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91sam9260_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.platform_data	= &uart1_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PB6, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PB7, 0);		/* RXD1 */
-	at91_set_A_periph(AT91_PIN_PB28, 0);		/* RTS1 */
-	at91_set_A_periph(AT91_PIN_PB29, 0);		/* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US2,
-		.end	= AT91SAM9260_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US2,
-		.end	= AT91SAM9260_ID_US2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91sam9260_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.platform_data	= &uart2_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PB8, 1);		/* TXD2 */
-	at91_set_A_periph(AT91_PIN_PB9, 0);		/* RXD2 */
-}
-
-static struct resource uart3_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US3,
-		.end	= AT91SAM9260_BASE_US3 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US3,
-		.end	= AT91SAM9260_ID_US3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart3_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91sam9260_uart3_device = {
-	.name		= "atmel_usart",
-	.id		= 4,
-	.dev		= {
-				.platform_data	= &uart3_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart3_resources,
-	.num_resources	= ARRAY_SIZE(uart3_resources),
-};
-
-static inline void configure_usart3_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PB10, 1);		/* TXD3 */
-	at91_set_A_periph(AT91_PIN_PB11, 0);		/* RXD3 */
-}
-
-static struct resource uart4_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US4,
-		.end	= AT91SAM9260_BASE_US4 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US4,
-		.end	= AT91SAM9260_ID_US4,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart4_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91sam9260_uart4_device = {
-	.name		= "atmel_usart",
-	.id		= 5,
-	.dev		= {
-				.platform_data	= &uart4_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart4_resources,
-	.num_resources	= ARRAY_SIZE(uart4_resources),
-};
-
-static inline void configure_usart4_pins(void)
-{
-	at91_set_B_periph(AT91_PIN_PA31, 1);		/* TXD4 */
-	at91_set_B_periph(AT91_PIN_PA30, 0);		/* RXD4 */
-}
-
-static struct resource uart5_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US5,
-		.end	= AT91SAM9260_BASE_US5 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US5,
-		.end	= AT91SAM9260_ID_US5,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart5_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91sam9260_uart5_device = {
-	.name		= "atmel_usart",
-	.id		= 6,
-	.dev		= {
-				.platform_data	= &uart5_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart5_resources,
-	.num_resources	= ARRAY_SIZE(uart5_resources),
-};
-
-static inline void configure_usart5_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PB12, 1);		/* TXD5 */
-	at91_set_A_periph(AT91_PIN_PB13, 0);		/* RXD5 */
-}
-
-struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_init_serial(struct at91_uart_config *config)
-{
-	int i;
-
-	/* Fill in list of supported UARTs */
-	for (i = 0; i < config->nr_tty; i++) {
-		switch (config->tty_map[i]) {
-			case 0:
-				configure_usart0_pins();
-				at91_uarts[i] = &at91sam9260_uart0_device;
-				at91_clock_associate("usart0_clk", &at91sam9260_uart0_device.dev, "usart");
-				break;
-			case 1:
-				configure_usart1_pins();
-				at91_uarts[i] = &at91sam9260_uart1_device;
-				at91_clock_associate("usart1_clk", &at91sam9260_uart1_device.dev, "usart");
-				break;
-			case 2:
-				configure_usart2_pins();
-				at91_uarts[i] = &at91sam9260_uart2_device;
-				at91_clock_associate("usart2_clk", &at91sam9260_uart2_device.dev, "usart");
-				break;
-			case 3:
-				configure_usart3_pins();
-				at91_uarts[i] = &at91sam9260_uart3_device;
-				at91_clock_associate("usart3_clk", &at91sam9260_uart3_device.dev, "usart");
-				break;
-			case 4:
-				configure_usart4_pins();
-				at91_uarts[i] = &at91sam9260_uart4_device;
-				at91_clock_associate("usart4_clk", &at91sam9260_uart4_device.dev, "usart");
-				break;
-			case 5:
-				configure_usart5_pins();
-				at91_uarts[i] = &at91sam9260_uart5_device;
-				at91_clock_associate("usart5_clk", &at91sam9260_uart5_device.dev, "usart");
-				break;
-			case 6:
-				configure_dbgu_pins();
-				at91_uarts[i] = &at91sam9260_dbgu_device;
-				at91_clock_associate("mck", &at91sam9260_dbgu_device.dev, "usart");
-				break;
-			default:
-				continue;
-		}
-		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
-	}
-
-	/* Set serial console device */
-	if (config->console_tty < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[config->console_tty];
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-}
-#else
-void __init at91_init_serial(struct at91_uart_config *config) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
-
-/* -------------------------------------------------------------------- */
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91rm9200/at91sam9261.c b/arch/arm/mach-at91rm9200/at91sam9261.c
deleted file mode 100644
index d242bb8..0000000
--- a/arch/arm/mach-at91rm9200/at91sam9261.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * arch/arm/mach-at91rm9200/at91sam9261.c
- *
- *  Copyright (C) 2005 SAN People
- *
- * 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 <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/arch/at91sam9261.h>
-#include <asm/arch/at91_pmc.h>
-#include <asm/arch/at91_rstc.h>
-
-#include "generic.h"
-#include "clock.h"
-
-static struct map_desc at91sam9261_io_desc[] __initdata = {
-	{
-		.virtual	= AT91_VA_BASE_SYS,
-		.pfn		= __phys_to_pfn(AT91_BASE_SYS),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE,
-		.pfn		= __phys_to_pfn(AT91SAM9261_SRAM_BASE),
-		.length		= AT91SAM9261_SRAM_SIZE,
-		.type		= MT_DEVICE,
-	},
-};
-
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-static struct clk pioA_clk = {
-	.name		= "pioA_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_PIOA,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioB_clk = {
-	.name		= "pioB_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_PIOB,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioC_clk = {
-	.name		= "pioC_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_PIOC,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-	.name		= "usart0_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_US0,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-	.name		= "usart1_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_US1,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-	.name		= "usart2_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_US2,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc_clk = {
-	.name		= "mci_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_MCI,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk udc_clk = {
-	.name		= "udc_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_UDP,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi_clk = {
-	.name		= "twi_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_TWI,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi0_clk = {
-	.name		= "spi0_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_SPI0,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi1_clk = {
-	.name		= "spi1_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_SPI1,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk ohci_clk = {
-	.name		= "ohci_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_UHP,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-static struct clk lcdc_clk = {
-	.name		= "lcdc_clk",
-	.pmc_mask	= 1 << AT91SAM9261_ID_LCDC,
-	.type		= CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-	&pioA_clk,
-	&pioB_clk,
-	&pioC_clk,
-	&usart0_clk,
-	&usart1_clk,
-	&usart2_clk,
-	&mmc_clk,
-	&udc_clk,
-	&twi_clk,
-	&spi0_clk,
-	&spi1_clk,
-	// ssc 0 .. ssc2
-	// tc0 .. tc2
-	&ohci_clk,
-	&lcdc_clk,
-	// irq0 .. irq2
-};
-
-/*
- * The four programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-	.name		= "pck0",
-	.pmc_mask	= AT91_PMC_PCK0,
-	.type		= CLK_TYPE_PROGRAMMABLE,
-	.id		= 0,
-};
-static struct clk pck1 = {
-	.name		= "pck1",
-	.pmc_mask	= AT91_PMC_PCK1,
-	.type		= CLK_TYPE_PROGRAMMABLE,
-	.id		= 1,
-};
-static struct clk pck2 = {
-	.name		= "pck2",
-	.pmc_mask	= AT91_PMC_PCK2,
-	.type		= CLK_TYPE_PROGRAMMABLE,
-	.id		= 2,
-};
-static struct clk pck3 = {
-	.name		= "pck3",
-	.pmc_mask	= AT91_PMC_PCK3,
-	.type		= CLK_TYPE_PROGRAMMABLE,
-	.id		= 3,
-};
-
-/* HClocks */
-static struct clk hck0 = {
-	.name		= "hck0",
-	.pmc_mask	= AT91_PMC_HCK0,
-	.type		= CLK_TYPE_SYSTEM,
-	.id		= 0,
-};
-static struct clk hck1 = {
-	.name		= "hck1",
-	.pmc_mask	= AT91_PMC_HCK1,
-	.type		= CLK_TYPE_SYSTEM,
-	.id		= 1,
-};
-
-static void __init at91sam9261_register_clocks(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-		clk_register(periph_clocks[i]);
-
-	clk_register(&pck0);
-	clk_register(&pck1);
-	clk_register(&pck2);
-	clk_register(&pck3);
-
-	clk_register(&hck0);
-	clk_register(&hck1);
-}
-
-/* --------------------------------------------------------------------
- *  GPIO
- * -------------------------------------------------------------------- */
-
-static struct at91_gpio_bank at91sam9261_gpio[] = {
-	{
-		.id		= AT91SAM9261_ID_PIOA,
-		.offset		= AT91_PIOA,
-		.clock		= &pioA_clk,
-	}, {
-		.id		= AT91SAM9261_ID_PIOB,
-		.offset		= AT91_PIOB,
-		.clock		= &pioB_clk,
-	}, {
-		.id		= AT91SAM9261_ID_PIOC,
-		.offset		= AT91_PIOC,
-		.clock		= &pioC_clk,
-	}
-};
-
-static void at91sam9261_reset(void)
-{
-	at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
-
-/* --------------------------------------------------------------------
- *  AT91SAM9261 processor initialization
- * -------------------------------------------------------------------- */
-
-void __init at91sam9261_initialize(unsigned long main_clock)
-{
-	/* Map peripherals */
-	iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
-
-	at91_arch_reset = at91sam9261_reset;
-	at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
-			| (1 << AT91SAM9261_ID_IRQ2);
-
-	/* Init clock subsystem */
-	at91_clock_init(main_clock);
-
-	/* Register the processor-specific clocks */
-	at91sam9261_register_clocks();
-
-	/* Register GPIO subsystem */
-	at91_gpio_init(at91sam9261_gpio, 3);
-}
-
-/* --------------------------------------------------------------------
- *  Interrupt initialization
- * -------------------------------------------------------------------- */
-
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
-	7,	/* Advanced Interrupt Controller */
-	7,	/* System Peripherals */
-	0,	/* Parallel IO Controller A */
-	0,	/* Parallel IO Controller B */
-	0,	/* Parallel IO Controller C */
-	0,
-	6,	/* USART 0 */
-	6,	/* USART 1 */
-	6,	/* USART 2 */
-	0,	/* Multimedia Card Interface */
-	4,	/* USB Device Port */
-	0,	/* Two-Wire Interface */
-	6,	/* Serial Peripheral Interface 0 */
-	6,	/* Serial Peripheral Interface 1 */
-	5,	/* Serial Synchronous Controller 0 */
-	5,	/* Serial Synchronous Controller 1 */
-	5,	/* Serial Synchronous Controller 2 */
-	0,	/* Timer Counter 0 */
-	0,	/* Timer Counter 1 */
-	0,	/* Timer Counter 2 */
-	3,	/* USB Host port */
-	3,	/* LCD Controller */
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,	/* Advanced Interrupt Controller */
-	0,	/* Advanced Interrupt Controller */
-	0,	/* Advanced Interrupt Controller */
-};
-
-void __init at91sam9261_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-	if (!priority)
-		priority = at91sam9261_default_irq_priority;
-
-	/* Initialize the AIC interrupt controller */
-	at91_aic_init(priority);
-
-	/* Enable GPIO interrupts */
-	at91_gpio_irq_setup();
-}
diff --git a/arch/arm/mach-at91rm9200/at91sam9261_devices.c b/arch/arm/mach-at91rm9200/at91sam9261_devices.c
deleted file mode 100644
index ed1d790..0000000
--- a/arch/arm/mach-at91rm9200/at91sam9261_devices.c
+++ /dev/null
@@ -1,741 +0,0 @@
-/*
- * arch/arm/mach-at91rm9200/at91sam9261_devices.c
- *
- *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
- *  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 <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/platform_device.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/at91sam9261.h>
-#include <asm/arch/at91sam9261_matrix.h>
-#include <asm/arch/at91sam926x_mc.h>
-
-#include "generic.h"
-
-#define SZ_512	0x00000200
-#define SZ_256	0x00000100
-#define SZ_16	0x00000010
-
-/* --------------------------------------------------------------------
- *  USB Host
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = 0xffffffffUL;
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_UHP_BASE,
-		.end	= AT91SAM9261_UHP_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_UHP,
-		.end	= AT91SAM9261_ID_UHP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9261_usbh_device = {
-	.name		= "at91_ohci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ohci_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-				.platform_data		= &usbh_data,
-	},
-	.resource	= usbh_resources,
-	.num_resources	= ARRAY_SIZE(usbh_resources),
-};
-
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-	if (!data)
-		return;
-
-	usbh_data = *data;
-	platform_device_register(&at91sam9261_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  USB Device (Gadget)
- * -------------------------------------------------------------------- */
-
-#ifdef CONFIG_USB_GADGET_AT91
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_UDP,
-		.end	= AT91SAM9261_BASE_UDP + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_UDP,
-		.end	= AT91SAM9261_ID_UDP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9261_udc_device = {
-	.name		= "at91_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data		= &udc_data,
-	},
-	.resource	= udc_resources,
-	.num_resources	= ARRAY_SIZE(udc_resources),
-};
-
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-	unsigned long x;
-
-	if (!data)
-		return;
-
-	if (data->vbus_pin) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-	}
-
-	/* Pullup pin is handled internally */
-	x = at91_sys_read(AT91_MATRIX_USBPUCR);
-	at91_sys_write(AT91_MATRIX_USBPUCR, x | AT91_MATRIX_USBPUCR_PUON);
-
-	udc_data = *data;
-	platform_device_register(&at91sam9261_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  MMC / SD
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = 0xffffffffUL;
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_MCI,
-		.end	= AT91SAM9261_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_MCI,
-		.end	= AT91SAM9261_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9261_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mmc(struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_B_periph(AT91_PIN_PA2, 0);
-
-	/* CMD */
-	at91_set_B_periph(AT91_PIN_PA1, 1);
-
-	/* DAT0, maybe DAT1..DAT3 */
-	at91_set_B_periph(AT91_PIN_PA0, 1);
-	if (data->wire4) {
-		at91_set_B_periph(AT91_PIN_PA4, 1);
-		at91_set_B_periph(AT91_PIN_PA5, 1);
-		at91_set_B_periph(AT91_PIN_PA6, 1);
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91sam9261_mmc_device);
-}
-#else
-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;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	{
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at91_nand_device = {
-	.name		= "at91_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct at91_nand_data *data)
-{
-	unsigned long csa, mode;
-
-	if (!data)
-		return;
-
-	csa = at91_sys_read(AT91_MATRIX_EBICSA);
-	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC);
-
-	/* set the bus interface characteristics */
-	at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
-			| AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
-
-	at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5)
-			| AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5));
-
-	at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7));
-
-	if (data->bus_width_16)
-		mode = AT91_SMC_DBW_16;
-	else
-		mode = AT91_SMC_DBW_8;
-	at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1));
-
-	/* 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_PC0, 0);		/* NANDOE */
-	at91_set_A_periph(AT91_PIN_PC1, 0);		/* NANDWE */
-
-	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 resource twi_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_TWI,
-		.end	= AT91SAM9261_BASE_TWI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_TWI,
-		.end	= AT91SAM9261_ID_TWI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9261_twi_device = {
-	.name		= "at91_i2c",
-	.id		= -1,
-	.resource	= twi_resources,
-	.num_resources	= ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(void)
-{
-	/* pins used for TWI interface */
-	at91_set_A_periph(AT91_PIN_PA7, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PA7, 1);
-
-	at91_set_A_periph(AT91_PIN_PA8, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PA8, 1);
-
-	platform_device_register(&at91sam9261_twi_device);
-}
-#else
-void __init at91_add_device_i2c(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SPI
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = 0xffffffffUL;
-
-static struct resource spi0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_SPI0,
-		.end	= AT91SAM9261_BASE_SPI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_SPI0,
-		.end	= AT91SAM9261_ID_SPI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9261_spi0_device = {
-	.name		= "atmel_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-	},
-	.resource	= spi0_resources,
-	.num_resources	= ARRAY_SIZE(spi0_resources),
-};
-
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
-
-static struct resource spi1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_SPI1,
-		.end	= AT91SAM9261_BASE_SPI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_SPI1,
-		.end	= AT91SAM9261_ID_SPI1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9261_spi1_device = {
-	.name		= "atmel_spi",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-	},
-	.resource	= spi1_resources,
-	.num_resources	= ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB28, AT91_PIN_PA24, AT91_PIN_PA25, AT91_PIN_PA26 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-	short enable_spi0 = 0;
-	short enable_spi1 = 0;
-
-	/* Choose SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else if (devices[i].bus_num == 0)
-			cs_pin = spi0_standard_cs[devices[i].chip_select];
-		else
-			cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-		if (devices[i].bus_num == 0)
-			enable_spi0 = 1;
-		else
-			enable_spi1 = 1;
-
-		/* enable chip-select pin */
-		at91_set_gpio_output(cs_pin, 1);
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-
-	/* Configure SPI bus(es) */
-	if (enable_spi0) {
-		at91_set_A_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */
-		at91_set_A_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */
-		at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPI0_SPCK */
-
-		at91_clock_associate("spi0_clk", &at91sam9261_spi0_device.dev, "spi_clk");
-		platform_device_register(&at91sam9261_spi0_device);
-	}
-	if (enable_spi1) {
-		at91_set_A_periph(AT91_PIN_PB30, 0);	/* SPI1_MISO */
-		at91_set_A_periph(AT91_PIN_PB31, 0);	/* SPI1_MOSI */
-		at91_set_A_periph(AT91_PIN_PB29, 0);	/* SPI1_SPCK */
-
-		at91_clock_associate("spi1_clk", &at91sam9261_spi1_device.dev, "spi_clk");
-		platform_device_register(&at91sam9261_spi1_device);
-	}
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  LCD Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE)
-static u64 lcdc_dmamask = 0xffffffffUL;
-static struct at91fb_info lcdc_data;
-
-static struct resource lcdc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_LCDC_BASE,
-		.end	= AT91SAM9261_LCDC_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_LCDC,
-		.end	= AT91SAM9261_ID_LCDC,
-		.flags	= IORESOURCE_IRQ,
-	},
-#if defined(CONFIG_FB_INTSRAM)
-	[2] = {
-		.start	= AT91SAM9261_SRAM_BASE,
-		.end	= AT91SAM9261_SRAM_BASE + AT91SAM9261_SRAM_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-#endif
-};
-
-static struct platform_device at91_lcdc_device = {
-	.name		= "at91-fb",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &lcdc_dmamask,
-				.coherent_dma_mask	= 0xffffffff,
-				.platform_data		= &lcdc_data,
-	},
-	.resource	= lcdc_resources,
-	.num_resources	= ARRAY_SIZE(lcdc_resources),
-};
-
-void __init at91_add_device_lcdc(struct at91fb_info *data)
-{
-	if (!data) {
-		return;
-	}
-
-	at91_set_A_periph(AT91_PIN_PB1, 0);	/* LCDHSYNC */
-	at91_set_A_periph(AT91_PIN_PB2, 0);	/* LCDDOTCK */
-	at91_set_A_periph(AT91_PIN_PB3, 0);	/* LCDDEN */
-	at91_set_A_periph(AT91_PIN_PB4, 0);	/* LCDCC */
-	at91_set_A_periph(AT91_PIN_PB7, 0);	/* LCDD2 */
-	at91_set_A_periph(AT91_PIN_PB8, 0);	/* LCDD3 */
-	at91_set_A_periph(AT91_PIN_PB9, 0);	/* LCDD4 */
-	at91_set_A_periph(AT91_PIN_PB10, 0);	/* LCDD5 */
-	at91_set_A_periph(AT91_PIN_PB11, 0);	/* LCDD6 */
-	at91_set_A_periph(AT91_PIN_PB12, 0);	/* LCDD7 */
-	at91_set_A_periph(AT91_PIN_PB15, 0);	/* LCDD10 */
-	at91_set_A_periph(AT91_PIN_PB16, 0);	/* LCDD11 */
-	at91_set_A_periph(AT91_PIN_PB17, 0);	/* LCDD12 */
-	at91_set_A_periph(AT91_PIN_PB18, 0);	/* LCDD13 */
-	at91_set_A_periph(AT91_PIN_PB19, 0);	/* LCDD14 */
-	at91_set_A_periph(AT91_PIN_PB20, 0);	/* LCDD15 */
-	at91_set_B_periph(AT91_PIN_PB23, 0);	/* LCDD18 */
-	at91_set_B_periph(AT91_PIN_PB24, 0);	/* LCDD19 */
-	at91_set_B_periph(AT91_PIN_PB25, 0);	/* LCDD20 */
-	at91_set_B_periph(AT91_PIN_PB26, 0);	/* LCDD21 */
-	at91_set_B_periph(AT91_PIN_PB27, 0);	/* LCDD22 */
-	at91_set_B_periph(AT91_PIN_PB28, 0);	/* LCDD23 */
-
-	lcdc_data = *data;
-	platform_device_register(&at91_lcdc_device);
-}
-#else
-void __init at91_add_device_lcdc(struct at91fb_info *data) {}
-#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
-
-
-/* --------------------------------------------------------------------
- *  UART
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
-
-static struct platform_device at91sam9261_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.platform_data	= &dbgu_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PA9, 0);		/* DRXD */
-	at91_set_A_periph(AT91_PIN_PA10, 1);		/* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_US0,
-		.end	= AT91SAM9261_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_US0,
-		.end	= AT91SAM9261_ID_US0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91sam9261_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.platform_data	= &uart0_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PC8, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PC9, 0);		/* RXD0 */
-	at91_set_A_periph(AT91_PIN_PC10, 0);		/* RTS0 */
-	at91_set_A_periph(AT91_PIN_PC11, 0);		/* CTS0 */
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_US1,
-		.end	= AT91SAM9261_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_US1,
-		.end	= AT91SAM9261_ID_US1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91sam9261_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.platform_data	= &uart1_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PC12, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PC13, 0);		/* RXD1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_US2,
-		.end	= AT91SAM9261_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_US2,
-		.end	= AT91SAM9261_ID_US2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static struct platform_device at91sam9261_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.platform_data	= &uart2_data,
-				.coherent_dma_mask = 0xffffffff,
-	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PC15, 0);		/* RXD2 */
-	at91_set_A_periph(AT91_PIN_PC14, 1);		/* TXD2 */
-}
-
-struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_init_serial(struct at91_uart_config *config)
-{
-	int i;
-
-	/* Fill in list of supported UARTs */
-	for (i = 0; i < config->nr_tty; i++) {
-		switch (config->tty_map[i]) {
-			case 0:
-				configure_usart0_pins();
-				at91_uarts[i] = &at91sam9261_uart0_device;
-				at91_clock_associate("usart0_clk", &at91sam9261_uart0_device.dev, "usart");
-				break;
-			case 1:
-				configure_usart1_pins();
-				at91_uarts[i] = &at91sam9261_uart1_device;
-				at91_clock_associate("usart1_clk", &at91sam9261_uart1_device.dev, "usart");
-				break;
-			case 2:
-				configure_usart2_pins();
-				at91_uarts[i] = &at91sam9261_uart2_device;
-				at91_clock_associate("usart2_clk", &at91sam9261_uart2_device.dev, "usart");
-				break;
-			case 3:
-				configure_dbgu_pins();
-				at91_uarts[i] = &at91sam9261_dbgu_device;
-				at91_clock_associate("mck", &at91sam9261_dbgu_device.dev, "usart");
-				break;
-			default:
-				continue;
-		}
-		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
-	}
-
-	/* Set serial console device */
-	if (config->console_tty < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[config->console_tty];
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-}
-#else
-void __init at91_init_serial(struct at91_uart_config *config) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
-
-/* -------------------------------------------------------------------- */
-
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91rm9200/at91sam926x_time.c b/arch/arm/mach-at91rm9200/at91sam926x_time.c
deleted file mode 100644
index 99df5f6..0000000
--- a/arch/arm/mach-at91rm9200/at91sam926x_time.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/at91sam926x_time.c
- *
- * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
- * Revision	 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
- *
- * 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/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/mach/time.h>
-
-#include <asm/arch/at91_pit.h>
-
-
-#define PIT_CPIV(x)	((x) & AT91_PIT_CPIV)
-#define PIT_PICNT(x)	(((x) & AT91_PIT_PICNT) >> 20)
-
-/*
- * Returns number of microseconds since last timer interrupt.  Note that interrupts
- * will have been disabled by do_gettimeofday()
- *  'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
- *  'tick' is usecs per jiffy (linux/timex.h).
- */
-static unsigned long at91sam926x_gettimeoffset(void)
-{
-	unsigned long elapsed;
-	unsigned long t = at91_sys_read(AT91_PIT_PIIR);
-
-	elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t);		/* hardware clock cycles */
-
-	return (unsigned long)(elapsed * 1000000) / LATCH;
-}
-
-/*
- * IRQ handler for the timer.
- */
-static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
-{
-	volatile long nr_ticks;
-
-	if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) {	/* This is a shared interrupt */
-		write_seqlock(&xtime_lock);
-
-		/* Get number to ticks performed before interrupt and clear PIT interrupt */
-		nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
-		do {
-			timer_tick();
-			nr_ticks--;
-		} while (nr_ticks);
-
-		write_sequnlock(&xtime_lock);
-		return IRQ_HANDLED;
-	} else
-		return IRQ_NONE;		/* not handled */
-}
-
-static struct irqaction at91sam926x_timer_irq = {
-	.name		= "at91_tick",
-	.flags		= IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER,
-	.handler	= at91sam926x_timer_interrupt
-};
-
-void at91sam926x_timer_reset(void)
-{
-	/* Disable timer */
-	at91_sys_write(AT91_PIT_MR, 0);
-
-	/* Clear any pending interrupts */
-	(void) at91_sys_read(AT91_PIT_PIVR);
-
-	/* Set Period Interval timer and enable its interrupt */
-	at91_sys_write(AT91_PIT_MR, (LATCH & AT91_PIT_PIV) | AT91_PIT_PITIEN | AT91_PIT_PITEN);
-}
-
-/*
- * Set up timer interrupt.
- */
-void __init at91sam926x_timer_init(void)
-{
-	/* Initialize and enable the timer */
-	at91sam926x_timer_reset();
-
-	/* Make IRQs happen for the system timer. */
-	setup_irq(AT91_ID_SYS, &at91sam926x_timer_irq);
-}
-
-#ifdef CONFIG_PM
-static void at91sam926x_timer_suspend(void)
-{
-	/* Disable timer */
-	at91_sys_write(AT91_PIT_MR, 0);
-}
-#else
-#define at91sam926x_timer_suspend	NULL
-#endif
-
-struct sys_timer at91sam926x_timer = {
-	.init		= at91sam926x_timer_init,
-	.offset		= at91sam926x_gettimeoffset,
-	.suspend	= at91sam926x_timer_suspend,
-	.resume		= at91sam926x_timer_reset,
-};
-
diff --git a/arch/arm/mach-at91rm9200/board-1arm.c b/arch/arm/mach-at91rm9200/board-1arm.c
deleted file mode 100644
index 971c3e2..0000000
--- a/arch/arm/mach-at91rm9200/board-1arm.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-1arm.c
- *
- *  Copyright (C) 2005 SAN People
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata onearm_uart_config = {
-	.console_tty	= 0,				/* ttyS0 */
-	.nr_tty		= 3,
-	.tty_map	= { 4, 0, 1, -1, -1 },		/* ttyS0, ..., ttyS4 */
-};
-
-static void __init onearm_map_io(void)
-{
-	/* Initialize processor: 18.432 MHz crystal */
-	at91rm9200_initialize(18432000, AT91RM9200_PQFP);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&onearm_uart_config);
-}
-
-static void __init onearm_init_irq(void)
-{
-	at91rm9200_init_interrupts(NULL);
-}
-
-static struct at91_eth_data __initdata onearm_eth_data = {
-	.phy_irq_pin	= AT91_PIN_PC4,
-	.is_rmii	= 1,
-};
-
-static struct at91_usbh_data __initdata onearm_usbh_data = {
-	.ports		= 1,
-};
-
-static struct at91_udc_data __initdata onearm_udc_data = {
-	.vbus_pin	= AT91_PIN_PC2,
-	.pullup_pin	= AT91_PIN_PC3,
-};
-
-static void __init onearm_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* Ethernet */
-	at91_add_device_eth(&onearm_eth_data);
-	/* USB Host */
-	at91_add_device_usbh(&onearm_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&onearm_udc_data);
-}
-
-MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
-	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
-	.map_io		= onearm_map_io,
-	.init_irq	= onearm_init_irq,
-	.init_machine	= onearm_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c
deleted file mode 100644
index 654f037..0000000
--- a/arch/arm/mach-at91rm9200/board-carmeva.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-carmeva.c
- *
- *  Copyright (c) 2005 Peer Georgi
- *  		       Conitec Datasystems
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata carmeva_uart_config = {
-	.console_tty	= 0,				/* ttyS0 */
-	.nr_tty		= 2,
-	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
-};
-
-static void __init carmeva_map_io(void)
-{
-	/* Initialize processor: 20.000 MHz crystal */
-	at91rm9200_initialize(20000000, AT91RM9200_BGA);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&carmeva_uart_config);
-}
-
-static void __init carmeva_init_irq(void)
-{
-	at91rm9200_init_interrupts(NULL);
-}
-
-static struct at91_eth_data __initdata carmeva_eth_data = {
-	.phy_irq_pin	= AT91_PIN_PC4,
-	.is_rmii	= 1,
-};
-
-static struct at91_usbh_data __initdata carmeva_usbh_data = {
-	.ports		= 2,
-};
-
-static struct at91_udc_data __initdata carmeva_udc_data = {
-	.vbus_pin	= AT91_PIN_PD12,
-	.pullup_pin	= AT91_PIN_PD9,
-};
-
-/* FIXME: user dependend */
-// static struct at91_cf_data __initdata carmeva_cf_data = {
-//	.det_pin	= AT91_PIN_PB0,
-//	.rst_pin	= AT91_PIN_PC5,
-	// .irq_pin	= ... not connected
-	// .vcc_pin	= ... always powered
-// };
-
-static struct at91_mmc_data __initdata carmeva_mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PB10,
-	.wp_pin		= AT91_PIN_PC14,
-};
-
-static struct spi_board_info carmeva_spi_devices[] = {
-	{ /* DataFlash chip */
-		.modalias = "mtd_dataflash",
-		.chip_select  = 0,
-		.max_speed_hz = 10 * 1000 * 1000,
-	},
-	{ /* User accessable spi - cs1 (250KHz) */
-		.modalias = "spi-cs1",
-		.chip_select  = 1,
-		.max_speed_hz = 250 *  1000,
-	},
-	{ /* User accessable spi - cs2 (1MHz) */
-		.modalias = "spi-cs2",
-		.chip_select  = 2,
-		.max_speed_hz = 1 * 1000 *  1000,
-	},
-	{ /* User accessable spi - cs3 (10MHz) */
-		.modalias = "spi-cs3",
-		.chip_select  = 3,
-		.max_speed_hz = 10 * 1000 *  1000,
-	},
-};
-
-static void __init carmeva_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* Ethernet */
-	at91_add_device_eth(&carmeva_eth_data);
-	/* USB Host */
-	at91_add_device_usbh(&carmeva_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&carmeva_udc_data);
-	/* I2C */
-	at91_add_device_i2c();
-	/* SPI */
-	at91_add_device_spi(carmeva_spi_devices, ARRAY_SIZE(carmeva_spi_devices));
-	/* Compact Flash */
-//	at91_add_device_cf(&carmeva_cf_data);
-	/* MMC */
-	at91_add_device_mmc(&carmeva_mmc_data);
-}
-
-MACHINE_START(CARMEVA, "Carmeva")
-	/* Maintainer: Conitec Datasystems */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
-	.map_io		= carmeva_map_io,
-	.init_irq	= carmeva_init_irq,
-	.init_machine	= carmeva_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
deleted file mode 100644
index b8bb805..0000000
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-csb337.c
- *
- *  Copyright (C) 2005 SAN People
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata csb337_uart_config = {
-	.console_tty	= 0,				/* ttyS0 */
-	.nr_tty		= 2,
-	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
-};
-
-static void __init csb337_map_io(void)
-{
-	/* Initialize processor: 3.6864 MHz crystal */
-	at91rm9200_initialize(3686400, AT91RM9200_BGA);
-
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&csb337_uart_config);
-}
-
-static void __init csb337_init_irq(void)
-{
-	at91rm9200_init_interrupts(NULL);
-}
-
-static struct at91_eth_data __initdata csb337_eth_data = {
-	.phy_irq_pin	= AT91_PIN_PC2,
-	.is_rmii	= 0,
-};
-
-static struct at91_usbh_data __initdata csb337_usbh_data = {
-	.ports		= 2,
-};
-
-static struct at91_udc_data __initdata csb337_udc_data = {
-	// this has no VBUS sensing pin
-	.pullup_pin	= AT91_PIN_PA24,
-};
-
-static struct at91_cf_data __initdata csb337_cf_data = {
-	/*
-	 * connector P4 on the CSB 337 mates to
-	 * connector P8 on the CSB 300CF
-	 */
-
-	/* CSB337 specific */
-	.det_pin	= AT91_PIN_PC3,
-
-	/* CSB300CF specific */
-	.irq_pin	= AT91_PIN_PA19,
-	.vcc_pin	= AT91_PIN_PD0,
-	.rst_pin	= AT91_PIN_PD2,
-};
-
-static struct at91_mmc_data __initdata csb337_mmc_data = {
-	.det_pin	= AT91_PIN_PD5,
-	.slot_b		= 0,
-	.wire4		= 1,
-	.wp_pin		= AT91_PIN_PD6,
-};
-
-static struct spi_board_info csb337_spi_devices[] = {
-	{	/* CAN controller */
-		.modalias	= "sak82c900",
-		.chip_select	= 0,
-		.max_speed_hz	= 6 * 1000 * 1000,
-	},
-};
-
-static void __init csb337_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* Ethernet */
-	at91_add_device_eth(&csb337_eth_data);
-	/* USB Host */
-	at91_add_device_usbh(&csb337_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&csb337_udc_data);
-	/* I2C */
-	at91_add_device_i2c();
-	/* Compact Flash */
-	at91_set_gpio_input(AT91_PIN_PB22, 1);		/* IOIS16 */
-	at91_add_device_cf(&csb337_cf_data);
-	/* SPI */
-	at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
-	/* MMC */
-	at91_add_device_mmc(&csb337_mmc_data);
-}
-
-MACHINE_START(CSB337, "Cogent CSB337")
-	/* Maintainer: Bill Gatliff */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
-	.map_io		= csb337_map_io,
-	.init_irq	= csb337_init_irq,
-	.init_machine	= csb337_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
deleted file mode 100644
index a29fa0e8..0000000
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-csb637.c
- *
- *  Copyright (C) 2005 SAN People
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata csb637_uart_config = {
-	.console_tty	= 0,				/* ttyS0 */
-	.nr_tty		= 2,
-	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
-};
-
-static void __init csb637_map_io(void)
-{
-	/* Initialize processor: 3.6864 MHz crystal */
-	at91rm9200_initialize(3686400, AT91RM9200_BGA);
-
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&csb637_uart_config);
-}
-
-static void __init csb637_init_irq(void)
-{
-	at91rm9200_init_interrupts(NULL);
-}
-
-static struct at91_eth_data __initdata csb637_eth_data = {
-	.phy_irq_pin	= AT91_PIN_PC0,
-	.is_rmii	= 0,
-};
-
-static struct at91_usbh_data __initdata csb637_usbh_data = {
-	.ports		= 2,
-};
-
-static struct at91_udc_data __initdata csb637_udc_data = {
-	.vbus_pin     = AT91_PIN_PB28,
-	.pullup_pin   = AT91_PIN_PB1,
-};
-
-static void __init csb637_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* Ethernet */
-	at91_add_device_eth(&csb637_eth_data);
-	/* USB Host */
-	at91_add_device_usbh(&csb637_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&csb637_udc_data);
-	/* I2C */
-	at91_add_device_i2c();
-	/* SPI */
-	at91_add_device_spi(NULL, 0);
-}
-
-MACHINE_START(CSB637, "Cogent CSB637")
-	/* Maintainer: Bill Gatliff */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
-	.map_io		= csb637_map_io,
-	.init_irq	= csb637_init_irq,
-	.init_machine	= csb637_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
deleted file mode 100644
index 7522bf9..0000000
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-dk.c
- *
- *  Copyright (C) 2005 SAN People
- *
- *  Epson S1D framebuffer glue code is:
- *     Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/mtd/physmap.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/at91rm9200_mc.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata dk_uart_config = {
-	.console_tty	= 0,				/* ttyS0 */
-	.nr_tty		= 2,
-	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
-};
-
-static void __init dk_map_io(void)
-{
-	/* Initialize processor: 18.432 MHz crystal */
-	at91rm9200_initialize(18432000, AT91RM9200_BGA);
-
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&dk_uart_config);
-}
-
-static void __init dk_init_irq(void)
-{
-	at91rm9200_init_interrupts(NULL);
-}
-
-static struct at91_eth_data __initdata dk_eth_data = {
-	.phy_irq_pin	= AT91_PIN_PC4,
-	.is_rmii	= 1,
-};
-
-static struct at91_usbh_data __initdata dk_usbh_data = {
-	.ports		= 2,
-};
-
-static struct at91_udc_data __initdata dk_udc_data = {
-	.vbus_pin	= AT91_PIN_PD4,
-	.pullup_pin	= AT91_PIN_PD5,
-};
-
-static struct at91_cf_data __initdata dk_cf_data = {
-	.det_pin	= AT91_PIN_PB0,
-	.rst_pin	= AT91_PIN_PC5,
-	// .irq_pin	= ... not connected
-	// .vcc_pin	= ... always powered
-};
-
-static struct at91_mmc_data __initdata dk_mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-};
-
-static struct spi_board_info dk_spi_devices[] = {
-	{	/* DataFlash chip */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 0,
-		.max_speed_hz	= 15 * 1000 * 1000,
-	},
-	{	/* UR6HCPS2-SP40 PS2-to-SPI adapter */
-		.modalias	= "ur6hcps2",
-		.chip_select	= 1,
-		.max_speed_hz	= 250 *  1000,
-	},
-	{	/* TLV1504 ADC, 4 channels, 10 bits; one is a temp sensor */
-		.modalias	= "tlv1504",
-		.chip_select	= 2,
-		.max_speed_hz	= 20 * 1000 * 1000,
-	},
-#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
-	{	/* DataFlash card */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 3,
-		.max_speed_hz	= 15 * 1000 * 1000,
-	}
-#endif
-};
-
-static struct mtd_partition __initdata dk_nand_partition[] = {
-	{
-		.name	= "NAND Partition 1",
-		.offset	= 0,
-		.size	= MTDPART_SIZ_FULL,
-	},
-};
-
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(dk_nand_partition);
-	return dk_nand_partition;
-}
-
-static struct at91_nand_data __initdata dk_nand_data = {
-	.ale		= 22,
-	.cle		= 21,
-	.det_pin	= AT91_PIN_PB1,
-	.rdy_pin	= AT91_PIN_PC2,
-	// .enable_pin	= ... not there
-	.partition_info	= nand_partitions,
-};
-
-#define DK_FLASH_BASE	AT91_CHIPSELECT_0
-#define DK_FLASH_SIZE	0x200000
-
-static struct physmap_flash_data dk_flash_data = {
-	.width	= 2,
-};
-
-static struct resource dk_flash_resource = {
-	.start		= DK_FLASH_BASE,
-	.end		= DK_FLASH_BASE + DK_FLASH_SIZE - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device dk_flash = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-				.platform_data	= &dk_flash_data,
-			},
-	.resource	= &dk_flash_resource,
-	.num_resources	= 1,
-};
-
-
-static void __init dk_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* Ethernet */
-	at91_add_device_eth(&dk_eth_data);
-	/* USB Host */
-	at91_add_device_usbh(&dk_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&dk_udc_data);
-	at91_set_multi_drive(dk_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
-	/* Compact Flash */
-	at91_add_device_cf(&dk_cf_data);
-	/* I2C */
-	at91_add_device_i2c();
-	/* SPI */
-	at91_add_device_spi(dk_spi_devices, ARRAY_SIZE(dk_spi_devices));
-#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). */
-	at91_add_device_mmc(&dk_mmc_data);
-#endif
-	/* NAND */
-	at91_add_device_nand(&dk_nand_data);
-	/* NOR Flash */
-	platform_device_register(&dk_flash);
-	/* VGA */
-//	dk_add_device_video();
-}
-
-MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
-	/* Maintainer: SAN People/Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
-	.map_io		= dk_map_io,
-	.init_irq	= dk_init_irq,
-	.init_machine	= dk_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c
deleted file mode 100644
index 80b72cf..0000000
--- a/arch/arm/mach-at91rm9200/board-eb9200.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-eb9200.c
- *
- *  Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest
- *  by Andrew Patrikalakis
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/device.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata eb9200_uart_config = {
-	.console_tty	= 0,				/* ttyS0 */
-	.nr_tty		= 2,
-	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
-};
-
-static void __init eb9200_map_io(void)
-{
-	/* Initialize processor: 18.432 MHz crystal */
-	at91rm9200_initialize(18432000, AT91RM9200_BGA);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&eb9200_uart_config);
-}
-
-static void __init eb9200_init_irq(void)
-{
-	at91rm9200_init_interrupts(NULL);
-}
-
-static struct at91_eth_data __initdata eb9200_eth_data = {
-	.phy_irq_pin	= AT91_PIN_PC4,
-	.is_rmii	= 1,
-};
-
-static struct at91_usbh_data __initdata eb9200_usbh_data = {
-	.ports		= 2,
-};
-
-static struct at91_udc_data __initdata eb9200_udc_data = {
-	.vbus_pin	= AT91_PIN_PD4,
-	.pullup_pin	= AT91_PIN_PD5,
-};
-
-static struct at91_cf_data __initdata eb9200_cf_data = {
-	.det_pin	= AT91_PIN_PB0,
-	.rst_pin	= AT91_PIN_PC5,
-	// .irq_pin	= ... not connected
-	// .vcc_pin	= ... always powered
-};
-
-static struct at91_mmc_data __initdata eb9200_mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-};
-
-static void __init eb9200_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* Ethernet */
-	at91_add_device_eth(&eb9200_eth_data);
-	/* USB Host */
-	at91_add_device_usbh(&eb9200_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&eb9200_udc_data);
-	/* I2C */
-	at91_add_device_i2c();
-	/* Compact Flash */
-	at91_add_device_cf(&eb9200_cf_data);
-	/* SPI */
-	at91_add_device_spi(NULL, 0);
-	/* MMC */
-	/* only supports 1 or 4 bit interface, not wired through to SPI */
-	at91_add_device_mmc(&eb9200_mmc_data);
-}
-
-MACHINE_START(ATEB9200, "Embest ATEB9200")
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
-	.map_io		= eb9200_map_io,
-	.init_irq	= eb9200_init_irq,
-	.init_machine	= eb9200_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
deleted file mode 100644
index c4fdb41..0000000
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-ek.c
- *
- *  Copyright (C) 2005 SAN People
- *
- *  Epson S1D framebuffer glue code is:
- *     Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/mtd/physmap.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/at91rm9200_mc.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata ek_uart_config = {
-	.console_tty	= 0,				/* ttyS0 */
-	.nr_tty		= 2,
-	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
-};
-
-static void __init ek_map_io(void)
-{
-	/* Initialize processor: 18.432 MHz crystal */
-	at91rm9200_initialize(18432000, AT91RM9200_BGA);
-
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&ek_uart_config);
-}
-
-static void __init ek_init_irq(void)
-{
-	at91rm9200_init_interrupts(NULL);
-}
-
-static struct at91_eth_data __initdata ek_eth_data = {
-	.phy_irq_pin	= AT91_PIN_PC4,
-	.is_rmii	= 1,
-};
-
-static struct at91_usbh_data __initdata ek_usbh_data = {
-	.ports		= 2,
-};
-
-static struct at91_udc_data __initdata ek_udc_data = {
-	.vbus_pin	= AT91_PIN_PD4,
-	.pullup_pin	= AT91_PIN_PD5,
-};
-
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.det_pin	= AT91_PIN_PB27,
-	.slot_b		= 0,
-	.wire4		= 1,
-	.wp_pin		= AT91_PIN_PA17,
-};
-
-static struct spi_board_info ek_spi_devices[] = {
-	{	/* DataFlash chip */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 0,
-		.max_speed_hz	= 15 * 1000 * 1000,
-	},
-#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
-	{	/* DataFlash card */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 3,
-		.max_speed_hz	= 15 * 1000 * 1000,
-	},
-#endif
-};
-
-#define EK_FLASH_BASE	AT91_CHIPSELECT_0
-#define EK_FLASH_SIZE	0x200000
-
-static struct physmap_flash_data ek_flash_data = {
-	.width	= 2,
-};
-
-static struct resource ek_flash_resource = {
-	.start		= EK_FLASH_BASE,
-	.end		= EK_FLASH_BASE + EK_FLASH_SIZE - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device ek_flash = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-				.platform_data	= &ek_flash_data,
-			},
-	.resource	= &ek_flash_resource,
-	.num_resources	= 1,
-};
-
-
-static void __init ek_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* Ethernet */
-	at91_add_device_eth(&ek_eth_data);
-	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&ek_udc_data);
-	at91_set_multi_drive(ek_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
-	/* I2C */
-	at91_add_device_i2c();
-	/* SPI */
-	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-#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). */
-	at91_add_device_mmc(&ek_mmc_data);
-#endif
-	/* NOR Flash */
-	platform_device_register(&ek_flash);
-	/* VGA */
-//	ek_add_device_video();
-}
-
-MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
-	/* Maintainer: SAN People/Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
-	.map_io		= ek_map_io,
-	.init_irq	= ek_init_irq,
-	.init_machine	= ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c
deleted file mode 100644
index 6ef3c48..0000000
--- a/arch/arm/mach-at91rm9200/board-kafa.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-kafa.c
- *
- *  Copyright (C) 2006 Sperry-Sun
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata kafa_uart_config = {
-	.console_tty	= 0,				/* ttyS0 */
-	.nr_tty		= 2,
-	.tty_map	= { 4, 0, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
-};
-
-static void __init kafa_map_io(void)
-{
-	/* Initialize processor: 18.432 MHz crystal */
-	at91rm9200_initialize(18432000, AT91RM9200_PQFP);
-
-	/* Set up the LEDs */
-	at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&kafa_uart_config);
-}
-
-static void __init kafa_init_irq(void)
-{
-	at91rm9200_init_interrupts(NULL);
-}
-
-static struct at91_eth_data __initdata kafa_eth_data = {
-	.phy_irq_pin	= AT91_PIN_PC4,
-	.is_rmii	= 0,
-};
-
-static struct at91_usbh_data __initdata kafa_usbh_data = {
-	.ports		= 1,
-};
-
-static struct at91_udc_data __initdata kafa_udc_data = {
-	.vbus_pin	= AT91_PIN_PB6,
-	.pullup_pin	= AT91_PIN_PB7,
-};
-
-static void __init kafa_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* Ethernet */
-	at91_add_device_eth(&kafa_eth_data);
-	/* USB Host */
-	at91_add_device_usbh(&kafa_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&kafa_udc_data);
-	/* I2C */
-	at91_add_device_i2c();
-	/* SPI */
-	at91_add_device_spi(NULL, 0);
-}
-
-MACHINE_START(KAFA, "Sperry-Sun KAFA")
-	/* Maintainer: Sergei Sharonov */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
-	.map_io		= kafa_map_io,
-	.init_irq	= kafa_init_irq,
-	.init_machine	= kafa_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c
deleted file mode 100644
index 759d819..0000000
--- a/arch/arm/mach-at91rm9200/board-kb9202.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-kb9202.c
- *
- *  Copyright (c) 2005 kb_admin
- *  		       KwikByte, 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 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 3 = USART0 .. USART3
- *    4      = DBGU
- */
-static struct at91_uart_config __initdata kb9202_uart_config = {
-	.console_tty	= 0,					/* ttyS0 */
-	.nr_tty		= 3,
-	.tty_map	= { 4, 0, 1, -1, -1 }			/* ttyS0, ..., ttyS4 */
-};
-
-static void __init kb9202_map_io(void)
-{
-	/* Initialize processor: 10 MHz crystal */
-	at91rm9200_initialize(10000000, AT91RM9200_PQFP);
-
-	/* Set up the LEDs */
-	at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&kb9202_uart_config);
-}
-
-static void __init kb9202_init_irq(void)
-{
-	at91rm9200_init_interrupts(NULL);
-}
-
-static struct at91_eth_data __initdata kb9202_eth_data = {
-	.phy_irq_pin	= AT91_PIN_PB29,
-	.is_rmii	= 0,
-};
-
-static struct at91_usbh_data __initdata kb9202_usbh_data = {
-	.ports		= 1,
-};
-
-static struct at91_udc_data __initdata kb9202_udc_data = {
-	.vbus_pin	= AT91_PIN_PB24,
-	.pullup_pin	= AT91_PIN_PB22,
-};
-
-static struct at91_mmc_data __initdata kb9202_mmc_data = {
-	.det_pin	= AT91_PIN_PB2,
-	.slot_b		= 0,
-	.wire4		= 1,
-};
-
-static struct mtd_partition __initdata kb9202_nand_partition[] = {
-	{
-		.name	= "nand_fs",
-		.offset	= 0,
-		.size	= MTDPART_SIZ_FULL,
-	},
-};
-
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(kb9202_nand_partition);
-	return kb9202_nand_partition;
-}
-
-static struct at91_nand_data __initdata kb9202_nand_data = {
-	.ale		= 22,
-	.cle		= 21,
-	// .det_pin	= ... not there
-	.rdy_pin	= AT91_PIN_PC29,
-	.enable_pin	= AT91_PIN_PC28,
-	.partition_info	= nand_partitions,
-};
-
-static void __init kb9202_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* Ethernet */
-	at91_add_device_eth(&kb9202_eth_data);
-	/* USB Host */
-	at91_add_device_usbh(&kb9202_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&kb9202_udc_data);
-	/* MMC */
-	at91_add_device_mmc(&kb9202_mmc_data);
-	/* I2C */
-	at91_add_device_i2c();
-	/* SPI */
-	at91_add_device_spi(NULL, 0);
-	/* NAND */
-	at91_add_device_nand(&kb9202_nand_data);
-}
-
-MACHINE_START(KB9200, "KB920x")
-	/* Maintainer: KwikByte, Inc. */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91rm9200_timer,
-	.map_io		= kb9202_map_io,
-	.init_irq	= kb9202_init_irq,
-	.init_machine	= kb9202_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-sam9260ek.c b/arch/arm/mach-at91rm9200/board-sam9260ek.c
deleted file mode 100644
index da5d58a..0000000
--- a/arch/arm/mach-at91rm9200/board-sam9260ek.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-ek.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 Atmel
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/at91sam926x_mc.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 5 = USART0 .. USART5
- *    6      = DBGU
- */
-static struct at91_uart_config __initdata ek_uart_config = {
-	.console_tty	= 0,				/* ttyS0 */
-	.nr_tty		= 3,
-	.tty_map	= { 6, 0, 1, -1, -1, -1, -1 }	/* ttyS0, ..., ttyS6 */
-};
-
-static void __init ek_map_io(void)
-{
-	/* Initialize processor: 18.432 MHz crystal */
-	at91sam9260_initialize(18432000);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&ek_uart_config);
-}
-
-static void __init ek_init_irq(void)
-{
-	at91sam9260_init_interrupts(NULL);
-}
-
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-	.ports		= 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-	.vbus_pin	= AT91_PIN_PC5,
-	.pullup_pin	= 0,		/* pull-up driven by UDC */
-};
-
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
-	{	/* DataFlash chip */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 1,
-		.max_speed_hz	= 15 * 1000 * 1000,
-		.bus_num	= 0,
-	},
-#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
-	{	/* DataFlash card */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 0,
-		.max_speed_hz	= 15 * 1000 * 1000,
-		.bus_num	= 0,
-	},
-#endif
-#endif
-#if defined(CONFIG_SND_AT73C213)
-	{	/* AT73C213 DAC */
-		.modalias	= "snd_at73c213",
-		.chip_select	= 0,
-		.max_speed_hz	= 10 * 1000 * 1000,
-		.bus_num	= 1,
-	},
-#endif
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct __initdata eth_platform_data ek_macb_data = {
-	.phy_irq_pin	= AT91_PIN_PA7,
-	.is_rmii	= 1,
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-	{
-		.name	= "Partition 1",
-		.offset	= 0,
-		.size	= 256 * 1024,
-	},
-	{
-		.name	= "Partition 2",
-		.offset	= 256 * 1024,
-		.size	= MTDPART_SIZ_FULL,
-	},
-};
-
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
-static struct at91_nand_data __initdata ek_nand_data = {
-	.ale		= 21,
-	.cle		= 22,
-//	.det_pin	= ... not connected
-	.rdy_pin	= AT91_PIN_PC13,
-	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
-#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
-	.bus_width_16	= 1,
-#else
-	.bus_width_16	= 0,
-#endif
-};
-
-
-/*
- * MCI (SD/MMC)
- */
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.slot_b		= 1,
-	.wire4		= 1,
-//	.det_pin	= ... not connected
-//	.wp_pin		= ... not connected
-//	.vcc_pin	= ... not connected
-};
-
-static void __init ek_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&ek_udc_data);
-	/* SPI */
-	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-	/* NAND */
-	at91_add_device_nand(&ek_nand_data);
-	/* Ethernet */
-	at91_add_device_eth(&ek_macb_data);
-	/* MMC */
-	at91_add_device_mmc(&ek_mmc_data);
-}
-
-MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
-	/* Maintainer: Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
-	.map_io		= ek_map_io,
-	.init_irq	= ek_init_irq,
-	.init_machine	= ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-sam9261ek.c b/arch/arm/mach-at91rm9200/board-sam9261ek.c
deleted file mode 100644
index 30b490d..0000000
--- a/arch/arm/mach-at91rm9200/board-sam9261ek.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-ek.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 Atmel
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/dm9000.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/board.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/at91sam926x_mc.h>
-
-#include "generic.h"
-
-
-/*
- * Serial port configuration.
- *    0 .. 2 = USART0 .. USART2
- *    3      = DBGU
- */
-static struct at91_uart_config __initdata ek_uart_config = {
-	.console_tty	= 0,				/* ttyS0 */
-	.nr_tty		= 1,
-	.tty_map	= { 3, -1, -1, -1 }		/* ttyS0, ..., ttyS3 */
-};
-
-static void __init ek_map_io(void)
-{
-	/* Initialize processor: 18.432 MHz crystal */
-	at91sam9261_initialize(18432000);
-
-	/* Setup the serial ports and console */
-	at91_init_serial(&ek_uart_config);
-}
-
-static void __init ek_init_irq(void)
-{
-	at91sam9261_init_interrupts(NULL);
-}
-
-
-/*
- * DM9000 ethernet device
- */
-#if defined(CONFIG_DM9000)
-static struct resource at91sam9261_dm9000_resource[] = {
-	[0] = {
-		.start	= AT91_CHIPSELECT_2,
-		.end	= AT91_CHIPSELECT_2 + 3,
-		.flags	= IORESOURCE_MEM
-	},
-	[1] = {
-		.start	= AT91_CHIPSELECT_2 + 0x44,
-		.end	= AT91_CHIPSELECT_2 + 0xFF,
-		.flags	= IORESOURCE_MEM
-	},
-	[2] = {
-		.start	= AT91_PIN_PC11,
-		.end	= AT91_PIN_PC11,
-		.flags	= IORESOURCE_IRQ
-	}
-};
-
-static struct dm9000_plat_data dm9000_platdata = {
-	.flags		= DM9000_PLATF_16BITONLY,
-};
-
-static struct platform_device at91sam9261_dm9000_device = {
-	.name		= "dm9000",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(at91sam9261_dm9000_resource),
-	.resource	= at91sam9261_dm9000_resource,
-	.dev		= {
-		.platform_data	= &dm9000_platdata,
-	}
-};
-
-static void __init ek_add_device_dm9000(void)
-{
-	/*
-	 * Configure Chip-Select 2 on SMC for the DM9000.
-	 * Note: These timings were calculated for MASTER_CLOCK = 100000000
-	 *  according to the DM9000 timings.
-	 */
-	at91_sys_write(AT91_SMC_SETUP(2), AT91_SMC_NWESETUP_(2) | AT91_SMC_NCS_WRSETUP_(0) | AT91_SMC_NRDSETUP_(2) | AT91_SMC_NCS_RDSETUP_(0));
-	at91_sys_write(AT91_SMC_PULSE(2), AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(8) | AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(8));
-	at91_sys_write(AT91_SMC_CYCLE(2), AT91_SMC_NWECYCLE_(16) | AT91_SMC_NRDCYCLE_(16));
-	at91_sys_write(AT91_SMC_MODE(2), AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16 | AT91_SMC_TDF_(1));
-
-	/* Configure Reset signal as output */
-	at91_set_gpio_output(AT91_PIN_PC10, 0);
-
-	/* Configure Interrupt pin as input, no pull-up */
-	at91_set_gpio_input(AT91_PIN_PC11, 0);
-
-	platform_device_register(&at91sam9261_dm9000_device);
-}
-#else
-static void __init ek_add_device_dm9000(void) {}
-#endif /* CONFIG_DM9000 */
-
-
-/*
- * USB Host Port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-	.ports		= 2,
-};
-
-
-/*
- * USB Device Port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-	.vbus_pin	= AT91_PIN_PB29,
-	.pullup_pin	= 0,		/* pull-up driven by UDC */
-};
-
-
-/*
- * MCI (SD/MMC)
- */
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.wire4		= 1,
-//	.det_pin	= ... not connected
-//	.wp_pin		= ... not connected
-//	.vcc_pin	= ... not connected
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-	{
-		.name	= "Partition 1",
-		.offset	= 0,
-		.size	= 256 * 1024,
-	},
-	{
-		.name	= "Partition 2",
-		.offset	= 256 * 1024 ,
-		.size	= MTDPART_SIZ_FULL,
-	},
-};
-
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
-static struct at91_nand_data __initdata ek_nand_data = {
-	.ale		= 22,
-	.cle		= 21,
-//	.det_pin	= ... not connected
-	.rdy_pin	= AT91_PIN_PC15,
-	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
-#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
-	.bus_width_16	= 1,
-#else
-	.bus_width_16	= 0,
-#endif
-};
-
-/*
- * SPI devices
- */
-static struct spi_board_info ek_spi_devices[] = {
-	{	/* DataFlash chip */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 0,
-		.max_speed_hz	= 15 * 1000 * 1000,
-		.bus_num	= 0,
-	},
-#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
-	{	/* DataFlash card - jumper (J12) configurable to CS3 or CS0 */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 3,
-		.max_speed_hz	= 15 * 1000 * 1000,
-		.bus_num	= 0,
-	},
-#elif defined(CONFIG_SND_AT73C213)
-	{	/* AT73C213 DAC */
-		.modalias	= "snd_at73c213",
-		.chip_select	= 3,
-		.max_speed_hz	= 10 * 1000 * 1000,
-		.bus_num	= 0,
-	},
-#endif
-};
-
-
-static void __init ek_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&ek_udc_data);
-	/* I2C */
-	at91_add_device_i2c();
-	/* NAND */
-	at91_add_device_nand(&ek_nand_data);
-	/* DM9000 ethernet */
-	ek_add_device_dm9000();
-
-	/* spi0 and mmc/sd share the same PIO pins */
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-	/* SPI */
-	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-#else
-	/* MMC */
-	at91_add_device_mmc(&ek_mmc_data);
-#endif
-}
-
-MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
-	/* Maintainer: Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
-	.map_io		= ek_map_io,
-	.init_irq	= ek_init_irq,
-	.init_machine	= ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c
deleted file mode 100644
index 4dee21f..0000000
--- a/arch/arm/mach-at91rm9200/clock.c
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/clock.c
- *
- * Copyright (C) 2005 David Brownell
- * Copyright (C) 2005 Ivan Kokshaysky
- *
- * 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/init.h>
-#include <linux/fs.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-
-#include <asm/semaphore.h>
-#include <asm/io.h>
-#include <asm/mach-types.h>
-
-#include <asm/hardware.h>
-#include <asm/arch/at91_pmc.h>
-#include <asm/arch/cpu.h>
-
-#include "clock.h"
-
-
-/*
- * There's a lot more which can be done with clocks, including cpufreq
- * integration, slow clock mode support (for system suspend), letting
- * PLLB be used at other rates (on boards that don't need USB), etc.
- */
-
-#define clk_is_primary(x)	((x)->type & CLK_TYPE_PRIMARY)
-#define clk_is_programmable(x)	((x)->type & CLK_TYPE_PROGRAMMABLE)
-#define clk_is_peripheral(x)	((x)->type & CLK_TYPE_PERIPHERAL)
-#define clk_is_sys(x)		((x)->type & CLK_TYPE_SYSTEM)
-
-
-static LIST_HEAD(clocks);
-static DEFINE_SPINLOCK(clk_lock);
-
-static u32 at91_pllb_usb_init;
-
-/*
- * Four primary clock sources:  two crystal oscillators (32K, main), and
- * two PLLs.  PLLA usually runs the master clock; and PLLB must run at
- * 48 MHz (unless no USB function clocks are needed).  The main clock and
- * both PLLs are turned off to run in "slow clock mode" (system suspend).
- */
-static struct clk clk32k = {
-	.name		= "clk32k",
-	.rate_hz	= AT91_SLOW_CLOCK,
-	.users		= 1,		/* always on */
-	.id		= 0,
-	.type		= CLK_TYPE_PRIMARY,
-};
-static struct clk main_clk = {
-	.name		= "main",
-	.pmc_mask	= AT91_PMC_MOSCS,	/* in PMC_SR */
-	.id		= 1,
-	.type		= CLK_TYPE_PRIMARY,
-};
-static struct clk plla = {
-	.name		= "plla",
-	.parent		= &main_clk,
-	.pmc_mask	= AT91_PMC_LOCKA,	/* in PMC_SR */
-	.id		= 2,
-	.type		= CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
-};
-
-static void pllb_mode(struct clk *clk, int is_on)
-{
-	u32	value;
-
-	if (is_on) {
-		is_on = AT91_PMC_LOCKB;
-		value = at91_pllb_usb_init;
-	} else
-		value = 0;
-
-	// REVISIT: Add work-around for AT91RM9200 Errata #26 ?
-	at91_sys_write(AT91_CKGR_PLLBR, value);
-
-	do {
-		cpu_relax();
-	} while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != is_on);
-}
-
-static struct clk pllb = {
-	.name		= "pllb",
-	.parent		= &main_clk,
-	.pmc_mask	= AT91_PMC_LOCKB,	/* in PMC_SR */
-	.mode		= pllb_mode,
-	.id		= 3,
-	.type		= CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
-};
-
-static void pmc_sys_mode(struct clk *clk, int is_on)
-{
-	if (is_on)
-		at91_sys_write(AT91_PMC_SCER, clk->pmc_mask);
-	else
-		at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask);
-}
-
-/* USB function clocks (PLLB must be 48 MHz) */
-static struct clk udpck = {
-	.name		= "udpck",
-	.parent		= &pllb,
-	.mode		= pmc_sys_mode,
-};
-static struct clk uhpck = {
-	.name		= "uhpck",
-	.parent		= &pllb,
-	.mode		= pmc_sys_mode,
-};
-
-
-/*
- * The master clock is divided from the CPU clock (by 1-4).  It's used for
- * memory, interfaces to on-chip peripherals, the AIC, and sometimes more
- * (e.g baud rate generation).  It's sourced from one of the primary clocks.
- */
-static struct clk mck = {
-	.name		= "mck",
-	.pmc_mask	= AT91_PMC_MCKRDY,	/* in PMC_SR */
-};
-
-static void pmc_periph_mode(struct clk *clk, int is_on)
-{
-	if (is_on)
-		at91_sys_write(AT91_PMC_PCER, clk->pmc_mask);
-	else
-		at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask);
-}
-
-static struct clk __init *at91_css_to_clk(unsigned long css)
-{
-	switch (css) {
-		case AT91_PMC_CSS_SLOW:
-			return &clk32k;
-		case AT91_PMC_CSS_MAIN:
-			return &main_clk;
-		case AT91_PMC_CSS_PLLA:
-			return &plla;
-		case AT91_PMC_CSS_PLLB:
-			return &pllb;
-	}
-
-	return NULL;
-}
-
-/*
- * Associate a particular clock with a function (eg, "uart") and device.
- * The drivers can then request the same 'function' with several different
- * devices and not care about which clock name to use.
- */
-void __init at91_clock_associate(const char *id, struct device *dev, const char *func)
-{
-	struct clk *clk = clk_get(NULL, id);
-
-	if (!dev || !clk || !IS_ERR(clk_get(dev, func)))
-		return;
-
-	clk->function = func;
-	clk->dev = dev;
-}
-
-/* clocks cannot be de-registered no refcounting necessary */
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *clk;
-
-	list_for_each_entry(clk, &clocks, node) {
-		if (strcmp(id, clk->name) == 0)
-			return clk;
-		if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0)
-			return clk;
-	}
-
-	return ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
-
-static void __clk_enable(struct clk *clk)
-{
-	if (clk->parent)
-		__clk_enable(clk->parent);
-	if (clk->users++ == 0 && clk->mode)
-		clk->mode(clk, 1);
-}
-
-int clk_enable(struct clk *clk)
-{
-	unsigned long	flags;
-
-	spin_lock_irqsave(&clk_lock, flags);
-	__clk_enable(clk);
-	spin_unlock_irqrestore(&clk_lock, flags);
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-static void __clk_disable(struct clk *clk)
-{
-	BUG_ON(clk->users == 0);
-	if (--clk->users == 0 && clk->mode)
-		clk->mode(clk, 0);
-	if (clk->parent)
-		__clk_disable(clk->parent);
-}
-
-void clk_disable(struct clk *clk)
-{
-	unsigned long	flags;
-
-	spin_lock_irqsave(&clk_lock, flags);
-	__clk_disable(clk);
-	spin_unlock_irqrestore(&clk_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	unsigned long	flags;
-	unsigned long	rate;
-
-	spin_lock_irqsave(&clk_lock, flags);
-	for (;;) {
-		rate = clk->rate_hz;
-		if (rate || !clk->parent)
-			break;
-		clk = clk->parent;
-	}
-	spin_unlock_irqrestore(&clk_lock, flags);
-	return rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-/*------------------------------------------------------------------------*/
-
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
-
-/*
- * For now, only the programmable clocks support reparenting (MCK could
- * do this too, with care) or rate changing (the PLLs could do this too,
- * ditto MCK but that's more for cpufreq).  Drivers may reparent to get
- * a better rate match; we don't.
- */
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long	flags;
-	unsigned	prescale;
-	unsigned long	actual;
-
-	if (!clk_is_programmable(clk))
-		return -EINVAL;
-	spin_lock_irqsave(&clk_lock, flags);
-
-	actual = clk->parent->rate_hz;
-	for (prescale = 0; prescale < 7; prescale++) {
-		if (actual && actual <= rate)
-			break;
-		actual >>= 1;
-	}
-
-	spin_unlock_irqrestore(&clk_lock, flags);
-	return (prescale < 7) ? actual : -ENOENT;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long	flags;
-	unsigned	prescale;
-	unsigned long	actual;
-
-	if (!clk_is_programmable(clk))
-		return -EINVAL;
-	if (clk->users)
-		return -EBUSY;
-	spin_lock_irqsave(&clk_lock, flags);
-
-	actual = clk->parent->rate_hz;
-	for (prescale = 0; prescale < 7; prescale++) {
-		if (actual && actual <= rate) {
-			u32	pckr;
-
-			pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
-			pckr &= AT91_PMC_CSS_PLLB;	/* clock selection */
-			pckr |= prescale << 2;
-			at91_sys_write(AT91_PMC_PCKR(clk->id), pckr);
-			clk->rate_hz = actual;
-			break;
-		}
-		actual >>= 1;
-	}
-
-	spin_unlock_irqrestore(&clk_lock, flags);
-	return (prescale < 7) ? actual : -ENOENT;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-	return clk->parent;
-}
-EXPORT_SYMBOL(clk_get_parent);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	unsigned long	flags;
-
-	if (clk->users)
-		return -EBUSY;
-	if (!clk_is_primary(parent) || !clk_is_programmable(clk))
-		return -EINVAL;
-	spin_lock_irqsave(&clk_lock, flags);
-
-	clk->rate_hz = parent->rate_hz;
-	clk->parent = parent;
-	at91_sys_write(AT91_PMC_PCKR(clk->id), parent->id);
-
-	spin_unlock_irqrestore(&clk_lock, flags);
-	return 0;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-/* establish PCK0..PCK3 parentage and rate */
-static void init_programmable_clock(struct clk *clk)
-{
-	struct clk	*parent;
-	u32		pckr;
-
-	pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
-	parent = at91_css_to_clk(pckr & AT91_PMC_CSS);
-	clk->parent = parent;
-	clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
-}
-
-#endif	/* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
-
-/*------------------------------------------------------------------------*/
-
-#ifdef CONFIG_DEBUG_FS
-
-static int at91_clk_show(struct seq_file *s, void *unused)
-{
-	u32		scsr, pcsr, sr;
-	struct clk	*clk;
-	unsigned	i;
-
-	seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
-	seq_printf(s, "PCSR = %8x\n", pcsr = at91_sys_read(AT91_PMC_PCSR));
-
-	seq_printf(s, "MOR  = %8x\n", at91_sys_read(AT91_CKGR_MOR));
-	seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR));
-	seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR));
-	seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
-
-	seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR));
-	for (i = 0; i < 4; i++)
-		seq_printf(s, "PCK%d = %8x\n", i, at91_sys_read(AT91_PMC_PCKR(i)));
-	seq_printf(s, "SR   = %8x\n", sr = at91_sys_read(AT91_PMC_SR));
-
-	seq_printf(s, "\n");
-
-	list_for_each_entry(clk, &clocks, node) {
-		char	*state;
-
-		if (clk->mode == pmc_sys_mode)
-			state = (scsr & clk->pmc_mask) ? "on" : "off";
-		else if (clk->mode == pmc_periph_mode)
-			state = (pcsr & clk->pmc_mask) ? "on" : "off";
-		else if (clk->pmc_mask)
-			state = (sr & clk->pmc_mask) ? "on" : "off";
-		else if (clk == &clk32k || clk == &main_clk)
-			state = "on";
-		else
-			state = "";
-
-		seq_printf(s, "%-10s users=%2d %-3s %9ld Hz %s\n",
-			clk->name, clk->users, state, clk_get_rate(clk),
-			clk->parent ? clk->parent->name : "");
-	}
-	return 0;
-}
-
-static int at91_clk_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, at91_clk_show, NULL);
-}
-
-static struct file_operations at91_clk_operations = {
-	.open		= at91_clk_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init at91_clk_debugfs_init(void)
-{
-	/* /sys/kernel/debug/at91_clk */
-	(void) debugfs_create_file("at91_clk", S_IFREG | S_IRUGO, NULL, NULL, &at91_clk_operations);
-
-	return 0;
-}
-postcore_initcall(at91_clk_debugfs_init);
-
-#endif
-
-/*------------------------------------------------------------------------*/
-
-/* Register a new clock */
-int __init clk_register(struct clk *clk)
-{
-	if (clk_is_peripheral(clk)) {
-		clk->parent = &mck;
-		clk->mode = pmc_periph_mode;
-		list_add_tail(&clk->node, &clocks);
-	}
-	else if (clk_is_sys(clk)) {
-		clk->parent = &mck;
-		clk->mode = pmc_sys_mode;
-
-		list_add_tail(&clk->node, &clocks);
-	}
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
-	else if (clk_is_programmable(clk)) {
-		clk->mode = pmc_sys_mode;
-		init_programmable_clock(clk);
-		list_add_tail(&clk->node, &clocks);
-	}
-#endif
-
-	return 0;
-}
-
-
-/*------------------------------------------------------------------------*/
-
-static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
-{
-	unsigned mul, div;
-
-	div = reg & 0xff;
-	mul = (reg >> 16) & 0x7ff;
-	if (div && mul) {
-		freq /= div;
-		freq *= mul + 1;
-	} else
-		freq = 0;
-
-	return freq;
-}
-
-static u32 __init at91_usb_rate(struct clk *pll, u32 freq, u32 reg)
-{
-	if (pll == &pllb && (reg & AT91_PMC_USB96M))
-		return freq / 2;
-	else
-		return freq;
-}
-
-static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq)
-{
-	unsigned i, div = 0, mul = 0, diff = 1 << 30;
-	unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
-
-	/* PLL output max 240 MHz (or 180 MHz per errata) */
-	if (out_freq > 240000000)
-		goto fail;
-
-	for (i = 1; i < 256; i++) {
-		int diff1;
-		unsigned input, mul1;
-
-		/*
-		 * PLL input between 1MHz and 32MHz per spec, but lower
-		 * frequences seem necessary in some cases so allow 100K.
-		 */
-		input = main_freq / i;
-		if (input < 100000)
-			continue;
-		if (input > 32000000)
-			continue;
-
-		mul1 = out_freq / input;
-		if (mul1 > 2048)
-			continue;
-		if (mul1 < 2)
-			goto fail;
-
-		diff1 = out_freq - input * mul1;
-		if (diff1 < 0)
-			diff1 = -diff1;
-		if (diff > diff1) {
-			diff = diff1;
-			div = i;
-			mul = mul1;
-			if (diff == 0)
-				break;
-		}
-	}
-	if (i == 256 && diff > (out_freq >> 5))
-		goto fail;
-	return ret | ((mul - 1) << 16) | div;
-fail:
-	return 0;
-}
-
-/*
- * Several unused clocks may be active.  Turn them off.
- */
-static void __init at91_periphclk_reset(void)
-{
-	unsigned long reg;
-	struct clk *clk;
-
-	reg = at91_sys_read(AT91_PMC_PCSR);
-
-	list_for_each_entry(clk, &clocks, node) {
-		if (clk->mode != pmc_periph_mode)
-			continue;
-
-		if (clk->users > 0)
-			reg &= ~clk->pmc_mask;
-	}
-
-	at91_sys_write(AT91_PMC_PCDR, reg);
-}
-
-static struct clk *const standard_pmc_clocks[] __initdata = {
-	/* four primary clocks */
-	&clk32k,
-	&main_clk,
-	&plla,
-	&pllb,
-
-	/* PLLB children (USB) */
-	&udpck,
-	&uhpck,
-
-	/* MCK */
-	&mck
-};
-
-int __init at91_clock_init(unsigned long main_clock)
-{
-	unsigned tmp, freq, mckr;
-	int i;
-
-	/*
-	 * When the bootloader initialized the main oscillator correctly,
-	 * there's no problem using the cycle counter.  But if it didn't,
-	 * or when using oscillator bypass mode, we must be told the speed
-	 * of the main clock.
-	 */
-	if (!main_clock) {
-		do {
-			tmp = at91_sys_read(AT91_CKGR_MCFR);
-		} while (!(tmp & AT91_PMC_MAINRDY));
-		main_clock = (tmp & AT91_PMC_MAINF) * (AT91_SLOW_CLOCK / 16);
-	}
-	main_clk.rate_hz = main_clock;
-
-	/* report if PLLA is more than mildly overclocked */
-	plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR));
-	if (plla.rate_hz > 209000000)
-		pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
-
-	/*
-	 * USB clock init:  choose 48 MHz PLLB value, turn all clocks off,
-	 * disable 48MHz clock during usb peripheral suspend.
-	 *
-	 * REVISIT:  assumes MCK doesn't derive from PLLB!
-	 */
-	at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
-	pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
-	if (cpu_is_at91rm9200()) {
-		uhpck.pmc_mask = AT91RM9200_PMC_UHP;
-		udpck.pmc_mask = AT91RM9200_PMC_UDP;
-		at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP);
-		at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
-	} else if (cpu_is_at91sam9260()) {
-		uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
-		udpck.pmc_mask = AT91SAM926x_PMC_UDP;
-		at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP);
-	} else if (cpu_is_at91sam9261()) {
-		uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0);
-		udpck.pmc_mask = AT91SAM926x_PMC_UDP;
-		at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP);
-	}
-	at91_sys_write(AT91_CKGR_PLLBR, 0);
-
-	udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
-	uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
-
-	/*
-	 * MCK and CPU derive from one of those primary clocks.
-	 * For now, assume this parentage won't change.
-	 */
-	mckr = at91_sys_read(AT91_PMC_MCKR);
-	mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
-	freq = mck.parent->rate_hz;
-	freq /= (1 << ((mckr >> 2) & 3));		/* prescale */
-	mck.rate_hz = freq / (1 + ((mckr >> 8) & 3));	/* mdiv */
-
-	/* Register the PMC's standard clocks */
-	for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
-		list_add_tail(&standard_pmc_clocks[i]->node, &clocks);
-
-	/* MCK and CPU clock are "always on" */
-	clk_enable(&mck);
-
-	printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n",
-		freq / 1000000, (unsigned) mck.rate_hz / 1000000,
-		(unsigned) main_clock / 1000000,
-		((unsigned) main_clock % 1000000) / 1000);
-
-	/* disable all programmable clocks */
-	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3);
-
-	/* disable all other unused peripheral clocks */
-	at91_periphclk_reset();
-
-	return 0;
-}
diff --git a/arch/arm/mach-at91rm9200/clock.h b/arch/arm/mach-at91rm9200/clock.h
deleted file mode 100644
index b5c7a2e..0000000
--- a/arch/arm/mach-at91rm9200/clock.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/clock.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
- * published by the Free Software Foundation.
- */
-
-#define CLK_TYPE_PRIMARY	0x1
-#define CLK_TYPE_PLL		0x2
-#define CLK_TYPE_PROGRAMMABLE	0x4
-#define CLK_TYPE_PERIPHERAL	0x8
-#define CLK_TYPE_SYSTEM		0x10
-
-
-struct clk {
-	struct list_head node;
-	const char	*name;		/* unique clock name */
-	const char	*function;	/* function of the clock */
-	struct device	*dev;		/* device associated with function */
-	unsigned long	rate_hz;
-	struct clk	*parent;
-	u32		pmc_mask;
-	void		(*mode)(struct clk *, int);
-	unsigned	id:2;		/* PCK0..3, or 32k/main/a/b */
-	unsigned	type;		/* clock type */
-	u16		users;
-};
-
-
-extern int __init clk_register(struct clk *clk);
diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h
deleted file mode 100644
index 8c4d5a7..0000000
--- a/arch/arm/mach-at91rm9200/generic.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/generic.h
- *
- *  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 version 2 as
- * published by the Free Software Foundation.
- */
-
- /* Processors */
-extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks);
-extern void __init at91sam9260_initialize(unsigned long main_clock);
-extern void __init at91sam9261_initialize(unsigned long main_clock);
-
- /* Interrupts */
-extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
-extern void __init at91sam9260_init_interrupts(unsigned int priority[]);
-extern void __init at91sam9261_init_interrupts(unsigned int priority[]);
-extern void __init at91_aic_init(unsigned int priority[]);
-
- /* Timer */
-struct sys_timer;
-extern struct sys_timer at91rm9200_timer;
-extern struct sys_timer at91sam926x_timer;
-
- /* Clocks */
-extern int __init at91_clock_init(unsigned long main_clock);
-struct device;
-extern void __init at91_clock_associate(const char *id, struct device *dev, const char *func);
-
- /* Power Management */
-extern void at91_irq_suspend(void);
-extern void at91_irq_resume(void);
-
- /* GPIO */
-#define AT91RM9200_PQFP		3	/* AT91RM9200 PQFP package has 3 banks */
-#define AT91RM9200_BGA		4	/* AT91RM9200 BGA package has 4 banks */
-
-struct at91_gpio_bank {
-	unsigned short id;		/* peripheral ID */
-	unsigned long offset;		/* offset from system peripheral base */
-	struct clk *clock;		/* associated clock */
-};
-extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks);
-extern void __init at91_gpio_irq_setup(void);
-
-extern void (*at91_arch_reset)(void);
-extern int at91_extern_irq;
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
deleted file mode 100644
index af22659..0000000
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/gpio.c
- *
- * Copyright (C) 2005 HP Labs
- *
- * 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/clk.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/hardware.h>
-#include <asm/arch/at91_pio.h>
-#include <asm/arch/gpio.h>
-
-#include "generic.h"
-
-
-static struct at91_gpio_bank *gpio;
-static int gpio_banks;
-
-
-static inline void __iomem *pin_to_controller(unsigned pin)
-{
-	void __iomem *sys_base = (void __iomem *) AT91_VA_BASE_SYS;
-
-	pin -= PIN_BASE;
-	pin /= 32;
-	if (likely(pin < gpio_banks))
-		return sys_base + gpio[pin].offset;
-
-	return NULL;
-}
-
-static inline unsigned pin_to_mask(unsigned pin)
-{
-	pin -= PIN_BASE;
-	return 1 << (pin % 32);
-}
-
-
-/*--------------------------------------------------------------------------*/
-
-/* Not all hardware capabilities are exposed through these calls; they
- * only encapsulate the most common features and modes.  (So if you
- * want to change signals in groups, do it directly.)
- *
- * Bootloaders will usually handle some of the pin multiplexing setup.
- * The intent is certainly that by the time Linux is fully booted, all
- * pins should have been fully initialized.  These setup calls should
- * only be used by board setup routines, or possibly in driver probe().
- *
- * For bootloaders doing all that setup, these calls could be inlined
- * as NOPs so Linux won't duplicate any setup code
- */
-
-
-/*
- * mux the pin to the "A" internal peripheral role.
- */
-int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio)
-		return -EINVAL;
-
-	__raw_writel(mask, pio + PIO_IDR);
-	__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
-	__raw_writel(mask, pio + PIO_ASR);
-	__raw_writel(mask, pio + PIO_PDR);
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_A_periph);
-
-
-/*
- * mux the pin to the "B" internal peripheral role.
- */
-int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio)
-		return -EINVAL;
-
-	__raw_writel(mask, pio + PIO_IDR);
-	__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
-	__raw_writel(mask, pio + PIO_BSR);
-	__raw_writel(mask, pio + PIO_PDR);
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_B_periph);
-
-
-/*
- * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
- * configure it for an input.
- */
-int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio)
-		return -EINVAL;
-
-	__raw_writel(mask, pio + PIO_IDR);
-	__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
-	__raw_writel(mask, pio + PIO_ODR);
-	__raw_writel(mask, pio + PIO_PER);
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_gpio_input);
-
-
-/*
- * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
- * and configure it for an output.
- */
-int __init_or_module at91_set_gpio_output(unsigned pin, int value)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio)
-		return -EINVAL;
-
-	__raw_writel(mask, pio + PIO_IDR);
-	__raw_writel(mask, pio + PIO_PUDR);
-	__raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
-	__raw_writel(mask, pio + PIO_OER);
-	__raw_writel(mask, pio + PIO_PER);
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_gpio_output);
-
-
-/*
- * enable/disable the glitch filter; mostly used with IRQ handling.
- */
-int __init_or_module at91_set_deglitch(unsigned pin, int is_on)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio)
-		return -EINVAL;
-	__raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_deglitch);
-
-/*
- * enable/disable the multi-driver; This is only valid for output and
- * allows the output pin to run as an open collector output.
- */
-int __init_or_module at91_set_multi_drive(unsigned pin, int is_on)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio)
-		return -EINVAL;
-
-	__raw_writel(mask, pio + (is_on ? PIO_MDER : PIO_MDDR));
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_multi_drive);
-
-/*--------------------------------------------------------------------------*/
-
-/*
- * assuming the pin is muxed as a gpio output, set its value.
- */
-int at91_set_gpio_value(unsigned pin, int value)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio)
-		return -EINVAL;
-	__raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_gpio_value);
-
-
-/*
- * read the pin's value (works even if it's not muxed as a gpio).
- */
-int at91_get_gpio_value(unsigned pin)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-	u32		pdsr;
-
-	if (!pio)
-		return -EINVAL;
-	pdsr = __raw_readl(pio + PIO_PDSR);
-	return (pdsr & mask) != 0;
-}
-EXPORT_SYMBOL(at91_get_gpio_value);
-
-/*--------------------------------------------------------------------------*/
-
-#ifdef CONFIG_PM
-
-static u32 wakeups[MAX_GPIO_BANKS];
-static u32 backups[MAX_GPIO_BANKS];
-
-static int gpio_irq_set_wake(unsigned pin, unsigned state)
-{
-	unsigned	mask = pin_to_mask(pin);
-	unsigned	bank = (pin - PIN_BASE) / 32;
-
-	if (unlikely(bank >= MAX_GPIO_BANKS))
-		return -EINVAL;
-
-	if (state)
-		wakeups[bank] |= mask;
-	else
-		wakeups[bank] &= ~mask;
-
-	set_irq_wake(gpio[bank].id, state);
-
-	return 0;
-}
-
-void at91_gpio_suspend(void)
-{
-	int i;
-
-	for (i = 0; i < gpio_banks; i++) {
-		u32 pio = gpio[i].offset;
-
-		backups[i] = at91_sys_read(pio + PIO_IMR);
-		at91_sys_write(pio + PIO_IDR, backups[i]);
-		at91_sys_write(pio + PIO_IER, wakeups[i]);
-
-		if (!wakeups[i])
-			clk_disable(gpio[i].clock);
-		else {
-#ifdef CONFIG_PM_DEBUG
-			printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]);
-#endif
-		}
-	}
-}
-
-void at91_gpio_resume(void)
-{
-	int i;
-
-	for (i = 0; i < gpio_banks; i++) {
-		u32 pio = gpio[i].offset;
-
-		if (!wakeups[i])
-			clk_enable(gpio[i].clock);
-
-		at91_sys_write(pio + PIO_IDR, wakeups[i]);
-		at91_sys_write(pio + PIO_IER, backups[i]);
-	}
-}
-
-#else
-#define gpio_irq_set_wake	NULL
-#endif
-
-
-/* Several AIC controller irqs are dispatched through this GPIO handler.
- * To use any AT91_PIN_* as an externally triggered IRQ, first call
- * at91_set_gpio_input() then maybe enable its glitch filter.
- * Then just request_irq() with the pin ID; it works like any ARM IRQ
- * handler, though it always triggers on rising and falling edges.
- *
- * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after
- * configuring them with at91_set_a_periph() or at91_set_b_periph().
- * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
- */
-
-static void gpio_irq_mask(unsigned pin)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (pio)
-		__raw_writel(mask, pio + PIO_IDR);
-}
-
-static void gpio_irq_unmask(unsigned pin)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (pio)
-		__raw_writel(mask, pio + PIO_IER);
-}
-
-static int gpio_irq_type(unsigned pin, unsigned type)
-{
-	return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL;
-}
-
-static struct irq_chip gpio_irqchip = {
-	.name		= "GPIO",
-	.mask		= gpio_irq_mask,
-	.unmask		= gpio_irq_unmask,
-	.set_type	= gpio_irq_type,
-	.set_wake	= gpio_irq_set_wake,
-};
-
-static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
-{
-	unsigned	pin;
-	struct irq_desc	*gpio;
-	void __iomem	*pio;
-	u32		isr;
-
-	pio = get_irq_chip_data(irq);
-
-	/* temporarily mask (level sensitive) parent IRQ */
-	desc->chip->ack(irq);
-	for (;;) {
-		/* reading ISR acks the pending (edge triggered) GPIO interrupt */
-		isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
-		if (!isr)
-			break;
-
-		pin = (unsigned) get_irq_data(irq);
-		gpio = &irq_desc[pin];
-
-		while (isr) {
-			if (isr & 1) {
-				if (unlikely(gpio->depth)) {
-					/*
-					 * The core ARM interrupt handler lazily disables IRQs so
-					 * another IRQ must be generated before it actually gets
-					 * here to be disabled on the GPIO controller.
-					 */
-					gpio_irq_mask(pin);
-				}
-				else
-					desc_handle_irq(pin, gpio);
-			}
-			pin++;
-			gpio++;
-			isr >>= 1;
-		}
-	}
-	desc->chip->unmask(irq);
-	/* now it may re-trigger */
-}
-
-/*--------------------------------------------------------------------------*/
-
-/*
- * Called from the processor-specific init to enable GPIO interrupt support.
- */
-void __init at91_gpio_irq_setup(void)
-{
-	unsigned	pioc, pin;
-
-	for (pioc = 0, pin = PIN_BASE;
-			pioc < gpio_banks;
-			pioc++) {
-		void __iomem	*controller;
-		unsigned	id = gpio[pioc].id;
-		unsigned	i;
-
-		clk_enable(gpio[pioc].clock);	/* enable PIO controller's clock */
-
-		controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset;
-		__raw_writel(~0, controller + PIO_IDR);
-
-		set_irq_data(id, (void *) pin);
-		set_irq_chip_data(id, controller);
-
-		for (i = 0; i < 32; i++, pin++) {
-			/*
-			 * Can use the "simple" and not "edge" handler since it's
-			 * shorter, and the AIC handles interupts sanely.
-			 */
-			set_irq_chip(pin, &gpio_irqchip);
-			set_irq_handler(pin, handle_simple_irq);
-			set_irq_flags(pin, IRQF_VALID);
-		}
-
-		set_irq_chained_handler(id, gpio_irq_handler);
-	}
-	pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
-}
-
-/*
- * Called from the processor-specific init to enable GPIO pin support.
- */
-void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
-{
-	BUG_ON(nr_banks > MAX_GPIO_BANKS);
-
-	gpio = data;
-	gpio_banks = nr_banks;
-}
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c
deleted file mode 100644
index 2148daaf..0000000
--- a/arch/arm/mach-at91rm9200/irq.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/irq.c
- *
- *  Copyright (C) 2004 SAN People
- *  Copyright (C) 2004 ATMEL
- *  Copyright (C) Rick Bronson
- *
- * 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/init.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/types.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-#include <asm/setup.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/map.h>
-
-
-static void at91_aic_mask_irq(unsigned int irq)
-{
-	/* Disable interrupt on AIC */
-	at91_sys_write(AT91_AIC_IDCR, 1 << irq);
-}
-
-static void at91_aic_unmask_irq(unsigned int irq)
-{
-	/* Enable interrupt on AIC */
-	at91_sys_write(AT91_AIC_IECR, 1 << irq);
-}
-
-unsigned int at91_extern_irq;
-
-#define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq)
-
-static int at91_aic_set_type(unsigned irq, unsigned type)
-{
-	unsigned int smr, srctype;
-
-	switch (type) {
-	case IRQT_HIGH:
-		srctype = AT91_AIC_SRCTYPE_HIGH;
-		break;
-	case IRQT_RISING:
-		srctype = AT91_AIC_SRCTYPE_RISING;
-		break;
-	case IRQT_LOW:
-		if ((irq == AT91_ID_FIQ) || is_extern_irq(irq))		/* only supported on external interrupts */
-			srctype = AT91_AIC_SRCTYPE_LOW;
-		else
-			return -EINVAL;
-		break;
-	case IRQT_FALLING:
-		if ((irq == AT91_ID_FIQ) || is_extern_irq(irq))		/* only supported on external interrupts */
-			srctype = AT91_AIC_SRCTYPE_FALLING;
-		else
-			return -EINVAL;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	smr = at91_sys_read(AT91_AIC_SMR(irq)) & ~AT91_AIC_SRCTYPE;
-	at91_sys_write(AT91_AIC_SMR(irq), smr | srctype);
-	return 0;
-}
-
-#ifdef CONFIG_PM
-
-static u32 wakeups;
-static u32 backups;
-
-static int at91_aic_set_wake(unsigned irq, unsigned value)
-{
-	if (unlikely(irq >= 32))
-		return -EINVAL;
-
-	if (value)
-		wakeups |= (1 << irq);
-	else
-		wakeups &= ~(1 << irq);
-
-	return 0;
-}
-
-void at91_irq_suspend(void)
-{
-	backups = at91_sys_read(AT91_AIC_IMR);
-	at91_sys_write(AT91_AIC_IDCR, backups);
-	at91_sys_write(AT91_AIC_IECR, wakeups);
-}
-
-void at91_irq_resume(void)
-{
-	at91_sys_write(AT91_AIC_IDCR, wakeups);
-	at91_sys_write(AT91_AIC_IECR, backups);
-}
-
-#else
-#define at91_aic_set_wake	NULL
-#endif
-
-static struct irq_chip at91_aic_chip = {
-	.name		= "AIC",
-	.ack		= at91_aic_mask_irq,
-	.mask		= at91_aic_mask_irq,
-	.unmask		= at91_aic_unmask_irq,
-	.set_type	= at91_aic_set_type,
-	.set_wake	= at91_aic_set_wake,
-};
-
-/*
- * Initialize the AIC interrupt controller.
- */
-void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
-{
-	unsigned int i;
-
-	/*
-	 * The IVR is used by macro get_irqnr_and_base to read and verify.
-	 * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
-	 */
-	for (i = 0; i < NR_AIC_IRQS; i++) {
-		/* Put irq number in Source Vector Register: */
-		at91_sys_write(AT91_AIC_SVR(i), i);
-		/* Active Low interrupt, with the specified priority */
-		at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
-
-		set_irq_chip(i, &at91_aic_chip);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-
-		/* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */
-		if (i < 8)
-			at91_sys_write(AT91_AIC_EOICR, 0);
-	}
-
-	/*
-	 * Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS
-	 * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU
-	 */
-	at91_sys_write(AT91_AIC_SPU, NR_AIC_IRQS);
-
-	/* No debugging in AIC: Debug (Protect) Control Register */
-	at91_sys_write(AT91_AIC_DCR, 0);
-
-	/* Disable and clear all interrupts initially */
-	at91_sys_write(AT91_AIC_IDCR, 0xFFFFFFFF);
-	at91_sys_write(AT91_AIC_ICCR, 0xFFFFFFFF);
-}
diff --git a/arch/arm/mach-at91rm9200/leds.c b/arch/arm/mach-at91rm9200/leds.c
deleted file mode 100644
index 1a33373..0000000
--- a/arch/arm/mach-at91rm9200/leds.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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/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-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c
deleted file mode 100644
index 67aa557..0000000
--- a/arch/arm/mach-at91rm9200/pm.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * arch/arm/mach-at91rm9200/pm.c
- * AT91 Power Management
- *
- * 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/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 <linux/platform_device.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/at91_pmc.h>
-#include <asm/arch/at91rm9200_mc.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/cpu.h>
-
-#include "generic.h"
-
-
-static int at91_pm_valid_state(suspend_state_t state)
-{
-	switch (state) {
-		case PM_SUSPEND_ON:
-		case PM_SUSPEND_STANDBY:
-		case PM_SUSPEND_MEM:
-			return 1;
-
-		default:
-			return 0;
-	}
-}
-
-
-static suspend_state_t target_state;
-
-/*
- * Called after processes are frozen, but before we shutdown devices.
- */
-static int at91_pm_prepare(suspend_state_t state)
-{
-	target_state = state;
-	return 0;
-}
-
-/*
- * Verify that all the clocks are correct before entering
- * slow-clock mode.
- */
-static int at91_pm_verify_clocks(void)
-{
-	unsigned long scsr;
-	int i;
-
-	scsr = at91_sys_read(AT91_PMC_SCSR);
-
-	/* USB must not be using PLLB */
-	if (cpu_is_at91rm9200()) {
-		if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) {
-			pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
-			return 0;
-		}
-	} else if (cpu_is_at91sam9260()) {
-#warning "Check SAM9260 USB clocks"
-	} else if (cpu_is_at91sam9261()) {
-#warning "Check SAM9261 USB clocks"
-	}
-
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
-	/* PCK0..PCK3 must be disabled, or configured to use clk32k */
-	for (i = 0; i < 4; i++) {
-		u32 css;
-
-		if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
-			continue;
-
-		css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
-		if (css != AT91_PMC_CSS_SLOW) {
-			pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
-			return 0;
-		}
-	}
-#endif
-
-	return 1;
-}
-
-/*
- * Call this from platform driver suspend() to see how deeply to suspend.
- * For example, some controllers (like OHCI) need one of the PLL clocks
- * in order to act as a wakeup source, and those are not available when
- * going into slow clock mode.
- *
- * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have
- * the very same problem (but not using at91 main_clk), and it'd be better
- * to add one generic API rather than lots of platform-specific ones.
- */
-int at91_suspend_entering_slow_clock(void)
-{
-	return (target_state == PM_SUSPEND_MEM);
-}
-EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
-
-
-static void (*slow_clock)(void);
-
-
-static int at91_pm_enter(suspend_state_t state)
-{
-	at91_gpio_suspend();
-	at91_irq_suspend();
-
-	pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
-			/* remember all the always-wake irqs */
-			(at91_sys_read(AT91_PMC_PCSR)
-					| (1 << AT91_ID_FIQ)
-					| (1 << AT91_ID_SYS)
-					| (at91_extern_irq))
-				& at91_sys_read(AT91_AIC_IMR),
-			state);
-
-	switch (state) {
-		/*
-		 * Suspend-to-RAM is like STANDBY plus slow clock mode, so
-		 * drivers must suspend more deeply:  only the master clock
-		 * controller may be using the main oscillator.
-		 */
-		case PM_SUSPEND_MEM:
-			/*
-			 * Ensure that clocks are in a valid state.
-			 */
-			if (!at91_pm_verify_clocks())
-				goto error;
-
-			/*
-			 * Enter slow clock mode by switching over to clk32k and
-			 * turning off the main oscillator; reverse on wakeup.
-			 */
-			if (slow_clock) {
-				slow_clock();
-				break;
-			} else {
-				/* DEVELOPMENT ONLY */
-				pr_info("AT91: PM - no slow clock mode yet ...\n");
-				/* FALLTHROUGH leaving master clock alone */
-			}
-
-		/*
-		 * STANDBY mode has *all* drivers suspended; ignores irqs not
-		 * marked as 'wakeup' event sources; and reduces DRAM power.
-		 * But otherwise it's identical to PM_SUSPEND_ON:  cpu idle, and
-		 * nothing fancy done with main or cpu clocks.
-		 */
-		case PM_SUSPEND_STANDBY:
-			/*
-			 * NOTE: the Wait-for-Interrupt instruction needs to be
-			 * in icache so the SDRAM stays in self-refresh mode until
-			 * the wakeup IRQ occurs.
-			 */
-			asm("b 1f; .align 5; 1:");
-			asm("mcr p15, 0, r0, c7, c10, 4");	/* drain write buffer */
-			at91_sys_write(AT91_SDRAMC_SRR, 1);	/* self-refresh mode */
-			/* fall though to next state */
-
-		case PM_SUSPEND_ON:
-			asm("mcr p15, 0, r0, c7, c0, 4");	/* wait for interrupt */
-			break;
-
-		default:
-			pr_debug("AT91: PM - bogus suspend state %d\n", state);
-			goto error;
-	}
-
-	pr_debug("AT91: PM - wakeup %08x\n",
-			at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
-
-error:
-	target_state = PM_SUSPEND_ON;
-	at91_irq_resume();
-	at91_gpio_resume();
-	return 0;
-}
-
-
-static struct pm_ops at91_pm_ops ={
-	.pm_disk_mode	= 0,
-	.valid		= at91_pm_valid_state,
-	.prepare	= at91_pm_prepare,
-	.enter		= at91_pm_enter,
-};
-
-static int __init at91_pm_init(void)
-{
-	printk("AT91: Power Management\n");
-
-#ifdef CONFIG_AT91_PM_SLOW_CLOCK
-	/* REVISIT allocations of SRAM should be dynamically managed.
-	 * FIQ handlers and other components will want SRAM/TCM too...
-	 */
-	slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K));
-	memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz);
-#endif
-
-	/* Disable SDRAM low-power mode.  Cannot be used with self-refresh. */
-	at91_sys_write(AT91_SDRAMC_LPR, 0);
-
-	pm_set_ops(&at91_pm_ops);
-
-	return 0;
-}
-arch_initcall(at91_pm_init);
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index af7904b..575a21d 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -51,6 +51,31 @@
 	  Say 'Y' here if you want your kernel to support the Glomation
 	  GESBC-9312-sx board.
 
+config MACH_MICRO9
+        bool
+        default n
+
+config MACH_MICRO9H
+       bool "Support Contec Hypercontrol Micro9-H"
+       select MACH_MICRO9
+       help
+         Say 'Y' here if you want your kernel to support the
+         Contec Hypercontrol Micro9-H board.
+
+config MACH_MICRO9M
+       bool "Support Contec Hypercontrol Micro9-M"
+       select MACH_MICRO9
+       help
+         Say 'Y' here if you want your kernel to support the
+         Contec Hypercontrol Micro9-M board.
+
+config MACH_MICRO9L
+       bool "Support Contec Hypercontrol Micro9-L"
+       select MACH_MICRO9
+       help
+         Say 'Y' here if you want your kernel to support the
+         Contec Hypercontrol Micro9-L board.
+
 config MACH_TS72XX
 	bool "Support Technologic Systems TS-72xx SBC"
 	help
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index b06641d..0d3bf93 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -13,4 +13,5 @@
 obj-$(CONFIG_MACH_EDB9315)	+= edb9315.o
 obj-$(CONFIG_MACH_EDB9315A)	+= edb9315a.o
 obj-$(CONFIG_MACH_GESBC9312)	+= gesbc9312.o
+obj-$(CONFIG_MACH_MICRO9)	+= micro9.o
 obj-$(CONFIG_MACH_TS72XX)	+= ts72xx.o
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index 08ad782..f174d1a 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/string.h>
 #include <asm/div64.h>
 #include <asm/hardware.h>
@@ -124,7 +125,7 @@
 	return (unsigned long)rate;
 }
 
-void ep93xx_clock_init(void)
+static int __init ep93xx_clock_init(void)
 {
 	u32 value;
 
@@ -153,4 +154,7 @@
 	printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
 		clk_f.rate / 1000000, clk_h.rate / 1000000,
 		clk_p.rate / 1000000);
+
+	return 0;
 }
+arch_initcall(ep93xx_clock_init);
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 6b26346..829aed6 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -152,22 +152,30 @@
 /*************************************************************************
  * GPIO handling for EP93xx
  *************************************************************************/
-static unsigned char gpio_int_enable[2];
-static unsigned char gpio_int_type1[2];
-static unsigned char gpio_int_type2[2];
+static unsigned char gpio_int_unmasked[3];
+static unsigned char gpio_int_enabled[3];
+static unsigned char gpio_int_type1[3];
+static unsigned char gpio_int_type2[3];
 
-static void update_gpio_ab_int_params(int port)
+static void update_gpio_int_params(int abf)
 {
-	if (port == 0) {
+	if (abf == 0) {
 		__raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE);
 		__raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2);
 		__raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1);
-		__raw_writeb(gpio_int_enable[0], EP93XX_GPIO_A_INT_ENABLE);
-	} else if (port == 1) {
+		__raw_writeb(gpio_int_unmasked[0] & gpio_int_enabled[0], EP93XX_GPIO_A_INT_ENABLE);
+	} else if (abf == 1) {
 		__raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE);
 		__raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2);
 		__raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1);
-		__raw_writeb(gpio_int_enable[1], EP93XX_GPIO_B_INT_ENABLE);
+		__raw_writeb(gpio_int_unmasked[1] & gpio_int_enabled[1], EP93XX_GPIO_B_INT_ENABLE);
+	} else if (abf == 2) {
+		__raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE);
+		__raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2);
+		__raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1);
+		__raw_writeb(gpio_int_unmasked[2] & gpio_int_enabled[2], EP93XX_GPIO_F_INT_ENABLE);
+	} else {
+		BUG();
 	}
 }
 
@@ -192,8 +200,13 @@
 	local_irq_save(flags);
 	if (direction == GPIO_OUT) {
 		if (line >= 0 && line < 16) {
-			gpio_int_enable[line >> 3] &= ~(1 << (line & 7));
-			update_gpio_ab_int_params(line >> 3);
+			/* Port A/B.  */
+			gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
+			update_gpio_int_params(line >> 3);
+		} else if (line >= 40 && line < 48) {
+			/* Port F.  */
+			gpio_int_unmasked[2] &= ~(1 << (line & 7));
+			update_gpio_int_params(2);
 		}
 
 		v = __raw_readb(data_direction_register);
@@ -244,8 +257,7 @@
 /*************************************************************************
  * EP93xx IRQ handling
  *************************************************************************/
-static void ep93xx_gpio_ab_irq_handler(unsigned int irq,
-		struct irq_desc *desc)
+static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned char status;
 	int i;
@@ -267,37 +279,46 @@
 	}
 }
 
-static void ep93xx_gpio_ab_irq_mask_ack(unsigned int irq)
+static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4);
+
+	desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
+}
+
+static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
 {
 	int line = irq - IRQ_EP93XX_GPIO(0);
 	int port = line >> 3;
 
-	gpio_int_enable[port] &= ~(1 << (line & 7));
-	update_gpio_ab_int_params(port);
+	gpio_int_unmasked[port] &= ~(1 << (line & 7));
+	update_gpio_int_params(port);
 
-	if (line >> 3) {
-		__raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
-	} else {
+	if (port == 0) {
 		__raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK);
+	} else if (port == 1) {
+		__raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
+	} else if (port == 2) {
+		__raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK);
 	}
 }
 
-static void ep93xx_gpio_ab_irq_mask(unsigned int irq)
+static void ep93xx_gpio_irq_mask(unsigned int irq)
 {
 	int line = irq - IRQ_EP93XX_GPIO(0);
 	int port = line >> 3;
 
-	gpio_int_enable[port] &= ~(1 << (line & 7));
-	update_gpio_ab_int_params(port);
+	gpio_int_unmasked[port] &= ~(1 << (line & 7));
+	update_gpio_int_params(port);
 }
 
-static void ep93xx_gpio_ab_irq_unmask(unsigned int irq)
+static void ep93xx_gpio_irq_unmask(unsigned int irq)
 {
 	int line = irq - IRQ_EP93XX_GPIO(0);
 	int port = line >> 3;
 
-	gpio_int_enable[port] |= 1 << (line & 7);
-	update_gpio_ab_int_params(port);
+	gpio_int_unmasked[port] |= 1 << (line & 7);
+	update_gpio_int_params(port);
 }
 
 
@@ -306,40 +327,51 @@
  * edge (1) triggered, while gpio_int_type2 controls whether it
  * triggers on low/falling (0) or high/rising (1).
  */
-static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type)
+static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
 {
 	int port;
 	int line;
 
 	line = irq - IRQ_EP93XX_GPIO(0);
-	gpio_line_config(line, GPIO_IN);
+	if (line >= 0 && line < 16) {
+		gpio_line_config(line, GPIO_IN);
+	} else {
+		gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN);
+	}
 
 	port = line >> 3;
 	line &= 7;
 
 	if (type & IRQT_RISING) {
+		gpio_int_enabled[port] |= 1 << line;
 		gpio_int_type1[port] |= 1 << line;
 		gpio_int_type2[port] |= 1 << line;
 	} else if (type & IRQT_FALLING) {
+		gpio_int_enabled[port] |= 1 << line;
 		gpio_int_type1[port] |= 1 << line;
 		gpio_int_type2[port] &= ~(1 << line);
 	} else if (type & IRQT_HIGH) {
+		gpio_int_enabled[port] |= 1 << line;
 		gpio_int_type1[port] &= ~(1 << line);
 		gpio_int_type2[port] |= 1 << line;
 	} else if (type & IRQT_LOW) {
+		gpio_int_enabled[port] |= 1 << line;
 		gpio_int_type1[port] &= ~(1 << line);
 		gpio_int_type2[port] &= ~(1 << line);
+	} else {
+		gpio_int_enabled[port] &= ~(1 << line);
 	}
-	update_gpio_ab_int_params(port);
+	update_gpio_int_params(port);
 
 	return 0;
 }
 
-static struct irq_chip ep93xx_gpio_ab_irq_chip = {
-	.ack		= ep93xx_gpio_ab_irq_mask_ack,
-	.mask		= ep93xx_gpio_ab_irq_mask,
-	.unmask		= ep93xx_gpio_ab_irq_unmask,
-	.set_type	= ep93xx_gpio_ab_irq_type,
+static struct irq_chip ep93xx_gpio_irq_chip = {
+	.name		= "GPIO",
+	.ack		= ep93xx_gpio_irq_mask_ack,
+	.mask		= ep93xx_gpio_irq_mask,
+	.unmask		= ep93xx_gpio_irq_unmask,
+	.set_type	= ep93xx_gpio_irq_type,
 };
 
 
@@ -350,12 +382,21 @@
 	vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
 	vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
 
-	for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) {
-		set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip);
+	for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) {
+		set_irq_chip(irq, &ep93xx_gpio_irq_chip);
 		set_irq_handler(irq, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
+
 	set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
+	set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
+	set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
+	set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
+	set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
+	set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
+	set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
+	set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
+	set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
 }
 
 
@@ -461,8 +502,6 @@
 {
 	unsigned int v;
 
-	ep93xx_clock_init();
-
 	/*
 	 * Disallow access to MaverickCrunch initially.
 	 */
@@ -477,8 +516,4 @@
 
 	platform_device_register(&ep93xx_rtc_device);
 	platform_device_register(&ep93xx_ohci_device);
-
-#ifdef CONFIG_CRUNCH
-	elf_hwcap |= HWCAP_CRUNCH;
-#endif
 }
diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c
new file mode 100644
index 0000000..f28c129
--- /dev/null
+++ b/arch/arm/mach-ep93xx/micro9.c
@@ -0,0 +1,157 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/micro9.c
+ *
+ * Copyright (C) 2006 Contec Steuerungstechnik & Automation GmbH
+ *                   Manfred Gruber <manfred.gruber@contec.at>
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+
+#include <linux/mtd/physmap.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+static struct ep93xx_eth_data micro9_eth_data = {
+       .phy_id                 = 0x1f,
+};
+
+static struct resource micro9_eth_resource[] = {
+       {
+               .start  = EP93XX_ETHERNET_PHYS_BASE,
+               .end    = EP93XX_ETHERNET_PHYS_BASE + 0xffff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_EP93XX_ETHERNET,
+               .end    = IRQ_EP93XX_ETHERNET,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device micro9_eth_device = {
+       .name           = "ep93xx-eth",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &micro9_eth_data,
+       },
+       .num_resources = ARRAY_SIZE(micro9_eth_resource),
+       .resource       = micro9_eth_resource,
+};
+
+static void __init micro9_eth_init(void)
+{
+       memcpy(micro9_eth_data.dev_addr,
+               (void *)(EP93XX_ETHERNET_BASE + 0x50), 6);
+       platform_device_register(&micro9_eth_device);
+}
+
+static void __init micro9_init(void)
+{
+       micro9_eth_init();
+}
+
+/*
+ * Micro9-H
+ */
+#ifdef CONFIG_MACH_MICRO9H
+static struct physmap_flash_data micro9h_flash_data = {
+       .width          = 4,
+};
+
+static struct resource micro9h_flash_resource = {
+       .start          = 0x10000000,
+       .end            = 0x13ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device micro9h_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &micro9h_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &micro9h_flash_resource,
+};
+
+static void __init micro9h_init(void)
+{
+       platform_device_register(&micro9h_flash);
+}
+
+static void __init micro9h_init_machine(void)
+{
+       ep93xx_init_devices();
+       micro9_init();
+       micro9h_init();
+}
+
+MACHINE_START(MICRO9, "Contec Hypercontrol Micro9-H")
+       /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = micro9h_init_machine,
+MACHINE_END
+#endif
+
+/*
+ * Micro9-M
+ */
+#ifdef CONFIG_MACH_MICRO9M
+static void __init micro9m_init_machine(void)
+{
+       ep93xx_init_devices();
+       micro9_init();
+}
+
+MACHINE_START(MICRO9M, "Contec Hypercontrol Micro9-M")
+       /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = micro9m_init_machine,
+MACHINE_END
+#endif
+
+/*
+ * Micro9-L
+ */
+#ifdef CONFIG_MACH_MICRO9L
+static void __init micro9l_init_machine(void)
+{
+       ep93xx_init_devices();
+       micro9_init();
+}
+
+MACHINE_START(MICRO9L, "Contec Hypercontrol Micro9-L")
+       /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = micro9l_init_machine,
+MACHINE_END
+#endif
+
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 40039b2..2703a73 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -87,7 +87,7 @@
 	.read		= imx_get_cycles,
 	.mask		= 0xFFFFFFFF,
 	.shift 		= 20,
-	.is_continuous 	= 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init imx_clocksource_init(void)
diff --git a/arch/arm/mach-iop13xx/Makefile b/arch/arm/mach-iop13xx/Makefile
index c3d6c08..4185e05 100644
--- a/arch/arm/mach-iop13xx/Makefile
+++ b/arch/arm/mach-iop13xx/Makefile
@@ -5,7 +5,6 @@
 
 obj-$(CONFIG_ARCH_IOP13XX) += setup.o
 obj-$(CONFIG_ARCH_IOP13XX) += irq.o
-obj-$(CONFIG_ARCH_IOP13XX) += time.o
 obj-$(CONFIG_ARCH_IOP13XX) += pci.o
 obj-$(CONFIG_ARCH_IOP13XX) += io.o
 obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c
index 2a1bbfe..a519d707 100644
--- a/arch/arm/mach-iop13xx/iq81340mc.c
+++ b/arch/arm/mach-iop13xx/iq81340mc.c
@@ -25,6 +25,7 @@
 #include <asm/mach/arch.h>
 #include <asm/arch/pci.h>
 #include <asm/mach/time.h>
+#include <asm/arch/time.h>
 
 extern int init_atu; /* Flag to select which ATU(s) to initialize / disable */
 
@@ -78,12 +79,12 @@
 
 static void __init iq81340mc_timer_init(void)
 {
-	iop13xx_init_time(400000000);
+	iop_init_time(400000000);
 }
 
 static struct sys_timer iq81340mc_timer = {
        .init       = iq81340mc_timer_init,
-       .offset     = iop13xx_gettimeoffset,
+       .offset     = iop_gettimeoffset,
 };
 
 MACHINE_START(IQ81340MC, "Intel IQ81340MC")
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c
index 5ad2b62..0e71fbc 100644
--- a/arch/arm/mach-iop13xx/iq81340sc.c
+++ b/arch/arm/mach-iop13xx/iq81340sc.c
@@ -25,6 +25,7 @@
 #include <asm/mach/arch.h>
 #include <asm/arch/pci.h>
 #include <asm/mach/time.h>
+#include <asm/arch/time.h>
 
 extern int init_atu;
 
@@ -80,12 +81,12 @@
 
 static void __init iq81340sc_timer_init(void)
 {
-	iop13xx_init_time(400000000);
+	iop_init_time(400000000);
 }
 
 static struct sys_timer iq81340sc_timer = {
        .init       = iq81340sc_timer_init,
-       .offset     = iop13xx_gettimeoffset,
+       .offset     = iop_gettimeoffset,
 };
 
 MACHINE_START(IQ81340SC, "Intel IQ81340SC")
diff --git a/arch/arm/mach-iop13xx/irq.c b/arch/arm/mach-iop13xx/irq.c
index dbbc07c..b2eb0b9 100644
--- a/arch/arm/mach-iop13xx/irq.c
+++ b/arch/arm/mach-iop13xx/irq.c
@@ -161,65 +161,49 @@
 static void
 iop13xx_irq_mask0 (unsigned int irq)
 {
-	u32 cp_flags = iop13xx_cp6_save();
 	write_intctl_0(read_intctl_0() & ~(1 << (irq - 0)));
-	iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_mask1 (unsigned int irq)
 {
-	u32 cp_flags = iop13xx_cp6_save();
 	write_intctl_1(read_intctl_1() & ~(1 << (irq - 32)));
-	iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_mask2 (unsigned int irq)
 {
-	u32 cp_flags = iop13xx_cp6_save();
 	write_intctl_2(read_intctl_2() & ~(1 << (irq - 64)));
-	iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_mask3 (unsigned int irq)
 {
-	u32 cp_flags = iop13xx_cp6_save();
 	write_intctl_3(read_intctl_3() & ~(1 << (irq - 96)));
-	iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_unmask0(unsigned int irq)
 {
-	u32 cp_flags = iop13xx_cp6_save();
 	write_intctl_0(read_intctl_0() | (1 << (irq - 0)));
-	iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_unmask1(unsigned int irq)
 {
-	u32 cp_flags = iop13xx_cp6_save();
 	write_intctl_1(read_intctl_1() | (1 << (irq - 32)));
-	iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_unmask2(unsigned int irq)
 {
-	u32 cp_flags = iop13xx_cp6_save();
 	write_intctl_2(read_intctl_2() | (1 << (irq - 64)));
-	iop13xx_cp6_restore(cp_flags);
 }
 
 static void
 iop13xx_irq_unmask3(unsigned int irq)
 {
-	u32 cp_flags = iop13xx_cp6_save();
 	write_intctl_3(read_intctl_3() | (1 << (irq - 96)));
-	iop13xx_cp6_restore(cp_flags);
 }
 
 static struct irq_chip iop13xx_irqchip1 = {
@@ -250,11 +234,13 @@
 	.unmask = iop13xx_irq_unmask3,
 };
 
+extern void iop_init_cp6_handler(void);
+
 void __init iop13xx_init_irq(void)
 {
 	unsigned int i;
 
-	u32 cp_flags = iop13xx_cp6_save();
+	iop_init_cp6_handler();
 
 	/* disable all interrupts */
 	write_intctl_0(0);
@@ -285,6 +271,4 @@
 		set_irq_handler(i, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
-
-	iop13xx_cp6_restore(cp_flags);
 }
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
index 5fbeb28..9a46bcd 100644
--- a/arch/arm/mach-iop13xx/setup.c
+++ b/arch/arm/mach-iop13xx/setup.c
@@ -24,6 +24,7 @@
 #include <asm/mach/map.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/io.h>
 
 #define IOP13XX_UART_XTAL 33334000
 #define IOP13XX_SETUP_DEBUG 0
diff --git a/arch/arm/mach-iop13xx/time.c b/arch/arm/mach-iop13xx/time.c
deleted file mode 100644
index 8b21365..0000000
--- a/arch/arm/mach-iop13xx/time.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * arch/arm/mach-iop13xx/time.c
- *
- * Timer code for IOP13xx (copied from IOP32x/IOP33x implementation)
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright 2002-2003 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-static unsigned long ticks_per_jiffy;
-static unsigned long ticks_per_usec;
-static unsigned long next_jiffy_time;
-
-static inline u32 read_tcr1(void)
-{
-	u32 val;
-	asm volatile("mrc p6, 0, %0, c3, c9, 0" : "=r" (val));
-	return val;
-}
-
-unsigned long iop13xx_gettimeoffset(void)
-{
-	unsigned long offset;
-	u32 cp_flags;
-
-	cp_flags = iop13xx_cp6_save();
-	offset = next_jiffy_time - read_tcr1();
-	iop13xx_cp6_restore(cp_flags);
-
-	return offset / ticks_per_usec;
-}
-
-static irqreturn_t
-iop13xx_timer_interrupt(int irq, void *dev_id)
-{
-	u32 cp_flags = iop13xx_cp6_save();
-
-	write_seqlock(&xtime_lock);
-
-	asm volatile("mcr p6, 0, %0, c6, c9, 0" : : "r" (1));
-
-	while ((signed long)(next_jiffy_time - read_tcr1())
-							>= ticks_per_jiffy) {
-		timer_tick();
-		next_jiffy_time -= ticks_per_jiffy;
-	}
-
-	write_sequnlock(&xtime_lock);
-
-	iop13xx_cp6_restore(cp_flags);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction iop13xx_timer_irq = {
-	.name		= "IOP13XX Timer Tick",
-	.handler	= iop13xx_timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_TIMER,
-};
-
-void __init iop13xx_init_time(unsigned long tick_rate)
-{
-	u32 timer_ctl;
-	u32 cp_flags;
-
-	ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
-	ticks_per_usec = tick_rate / 1000000;
-	next_jiffy_time = 0xffffffff;
-
-	timer_ctl = IOP13XX_TMR_EN | IOP13XX_TMR_PRIVILEGED |
-			IOP13XX_TMR_RELOAD | IOP13XX_TMR_RATIO_1_1;
-
-	/*
-	 * We use timer 0 for our timer interrupt, and timer 1 as
-	 * monotonic counter for tracking missed jiffies.
-	 */
-	cp_flags = iop13xx_cp6_save();
-	asm volatile("mcr p6, 0, %0, c4, c9, 0" : : "r" (ticks_per_jiffy - 1));
-	asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (timer_ctl));
-	asm volatile("mcr p6, 0, %0, c5, c9, 0" : : "r" (0xffffffff));
-	asm volatile("mcr p6, 0, %0, c1, c9, 0" : : "r" (timer_ctl));
-	iop13xx_cp6_restore(cp_flags);
-
-	setup_irq(IRQ_IOP13XX_TIMER0, &iop13xx_timer_irq);
-}
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index b9b7650..45f4f13 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -31,6 +31,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach-types.h>
 #include <asm/page.h>
+#include <asm/arch/time.h>
 
 /*
  * GLAN Tank timer tick configuration.
@@ -38,12 +39,12 @@
 static void __init glantank_timer_init(void)
 {
 	/* 33.333 MHz crystal.  */
-	iop3xx_init_time(200000000);
+	iop_init_time(200000000);
 }
 
 static struct sys_timer glantank_timer = {
 	.init		= glantank_timer_init,
-	.offset		= iop3xx_gettimeoffset,
+	.offset		= iop_gettimeoffset,
 };
 
 
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index be4aedf..571ac35 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -36,7 +36,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-
+#include <asm/arch/time.h>
 
 /*
  * The EP80219 and IQ31244 use the same machine ID.  To find out
@@ -56,16 +56,16 @@
 {
 	if (is_80219()) {
 		/* 33.333 MHz crystal.  */
-		iop3xx_init_time(200000000);
+		iop_init_time(200000000);
 	} else {
 		/* 33.000 MHz crystal.  */
-		iop3xx_init_time(198000000);
+		iop_init_time(198000000);
 	}
 }
 
 static struct sys_timer iq31244_timer = {
 	.init		= iq31244_timer_init,
-	.offset		= iop3xx_gettimeoffset,
+	.offset		= iop_gettimeoffset,
 };
 
 
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index 1f37b55..361c70c 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -33,6 +33,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/arch/time.h>
 
 /*
  * IQ80321 timer tick configuration.
@@ -40,12 +41,12 @@
 static void __init iq80321_timer_init(void)
 {
 	/* 33.333 MHz crystal.  */
-	iop3xx_init_time(200000000);
+	iop_init_time(200000000);
 }
 
 static struct sys_timer iq80321_timer = {
 	.init		= iq80321_timer_init,
-	.offset		= iop3xx_gettimeoffset,
+	.offset		= iop_gettimeoffset,
 };
 
 
diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c
index 3ec1cd5..82598dc1 100644
--- a/arch/arm/mach-iop32x/irq.c
+++ b/arch/arm/mach-iop32x/irq.c
@@ -23,16 +23,12 @@
 
 static inline void intctl_write(u32 val)
 {
-	iop3xx_cp6_enable();
 	asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
-	iop3xx_cp6_disable();
 }
 
 static inline void intstr_write(u32 val)
 {
-	iop3xx_cp6_enable();
 	asm volatile("mcr p6, 0, %0, c4, c0, 0" : : "r" (val));
-	iop3xx_cp6_disable();
 }
 
 static void
@@ -60,6 +56,8 @@
 {
 	int i;
 
+	iop_init_cp6_handler();
+
 	intctl_write(0);
 	intstr_write(0);
 	if (machine_is_glantank() ||
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 2499a77..5f07344 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -37,6 +37,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/arch/time.h>
 
 /*
  * N2100 timer tick configuration.
@@ -44,12 +45,12 @@
 static void __init n2100_timer_init(void)
 {
 	/* 33.000 MHz crystal.  */
-	iop3xx_init_time(198000000);
+	iop_init_time(198000000);
 }
 
 static struct sys_timer n2100_timer = {
 	.init		= n2100_timer_init,
-	.offset		= iop3xx_gettimeoffset,
+	.offset		= iop_gettimeoffset,
 };
 
 
@@ -120,6 +121,20 @@
 	.map_irq	= n2100_pci_map_irq,
 };
 
+/*
+ * Both r8169 chips on the n2100 exhibit PCI parity problems.  Set
+ * the ->broken_parity_status flag for both ports so that the r8169
+ * driver knows it should ignore error interrupts.
+ */
+static void n2100_fixup_r8169(struct pci_dev *dev)
+{
+	if (dev->bus->number == 0 &&
+	    (dev->devfn == PCI_DEVFN(1, 0) ||
+	     dev->devfn == PCI_DEVFN(2, 0)))
+		dev->broken_parity_status = 1;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REALTEK, PCI_ANY_ID, n2100_fixup_r8169);
+
 static int __init n2100_pci_init(void)
 {
 	if (machine_is_n2100())
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
index 97a7b74..1a9e361 100644
--- a/arch/arm/mach-iop33x/iq80331.c
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -32,6 +32,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/arch/time.h>
 
 /*
  * IQ80331 timer tick configuration.
@@ -40,14 +41,14 @@
 {
 	/* D-Step parts run at a higher internal bus frequency */
 	if (*IOP3XX_ATURID >= 0xa)
-		iop3xx_init_time(333000000);
+		iop_init_time(333000000);
 	else
-		iop3xx_init_time(266000000);
+		iop_init_time(266000000);
 }
 
 static struct sys_timer iq80331_timer = {
 	.init		= iq80331_timer_init,
-	.offset		= iop3xx_gettimeoffset,
+	.offset		= iop_gettimeoffset,
 };
 
 
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
index 9887bfc..96d6f0f 100644
--- a/arch/arm/mach-iop33x/iq80332.c
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -32,6 +32,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/arch/time.h>
 
 /*
  * IQ80332 timer tick configuration.
@@ -40,14 +41,14 @@
 {
 	/* D-Step parts and the iop333 run at a higher internal bus frequency */
 	if (*IOP3XX_ATURID >= 0xa || *IOP3XX_ATUDID == 0x374)
-		iop3xx_init_time(333000000);
+		iop_init_time(333000000);
 	else
-		iop3xx_init_time(266000000);
+		iop_init_time(266000000);
 }
 
 static struct sys_timer iq80332_timer = {
 	.init		= iq80332_timer_init,
-	.offset		= iop3xx_gettimeoffset,
+	.offset		= iop_gettimeoffset,
 };
 
 
diff --git a/arch/arm/mach-iop33x/irq.c b/arch/arm/mach-iop33x/irq.c
index 00b37f3..c65ea78 100644
--- a/arch/arm/mach-iop33x/irq.c
+++ b/arch/arm/mach-iop33x/irq.c
@@ -24,44 +24,32 @@
 
 static inline void intctl0_write(u32 val)
 {
-	iop3xx_cp6_enable();
 	asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
-	iop3xx_cp6_disable();
 }
 
 static inline void intctl1_write(u32 val)
 {
-	iop3xx_cp6_enable();
 	asm volatile("mcr p6, 0, %0, c1, c0, 0" : : "r" (val));
-	iop3xx_cp6_disable();
 }
 
 static inline void intstr0_write(u32 val)
 {
-	iop3xx_cp6_enable();
 	asm volatile("mcr p6, 0, %0, c2, c0, 0" : : "r" (val));
-	iop3xx_cp6_disable();
 }
 
 static inline void intstr1_write(u32 val)
 {
-	iop3xx_cp6_enable();
 	asm volatile("mcr p6, 0, %0, c3, c0, 0" : : "r" (val));
-	iop3xx_cp6_disable();
 }
 
 static inline void intbase_write(u32 val)
 {
-	iop3xx_cp6_enable();
 	asm volatile("mcr p6, 0, %0, c12, c0, 0" : : "r" (val));
-	iop3xx_cp6_disable();
 }
 
 static inline void intsize_write(u32 val)
 {
-	iop3xx_cp6_enable();
 	asm volatile("mcr p6, 0, %0, c13, c0, 0" : : "r" (val));
-	iop3xx_cp6_disable();
 }
 
 static void
@@ -110,6 +98,8 @@
 {
 	int i;
 
+	iop_init_cp6_handler();
+
 	intctl0_write(0);
 	intctl1_write(0);
 	intstr0_write(0);
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index e316bd9..8a339cd 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -17,7 +17,7 @@
 	  NSLU2 NAS device. For more information on this platform,
 	  see http://www.nslu2-linux.org
 
-config ARCH_AVILA
+config MACH_AVILA
 	bool "Avila"
 	select PCI
 	help
@@ -25,6 +25,14 @@
 	  Avila Network Platform. For more information on this platform,
 	  see <file:Documentation/arm/IXP4xx>.
 
+config MACH_LOFT
+    bool "Loft"
+    depends on MACH_AVILA
+    help
+	  Say 'Y' here if you want your kernel to support the Giant
+	  Shoulder Inc Loft board (a minor variation on the standard
+	  Gateworks Avila Network Platform).
+
 config ARCH_ADI_COYOTE
 	bool "Coyote"
 	select PCI
@@ -86,7 +94,7 @@
 #
 config	ARCH_IXDP4XX
 	bool
-	depends on ARCH_IXDP425 || ARCH_AVILA || MACH_IXDP465
+	depends on ARCH_IXDP425 || MACH_IXDP465
 	default y
 
 #
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 640315d..746e297 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -6,6 +6,7 @@
 obj-pci-n	:=
 
 obj-pci-$(CONFIG_ARCH_IXDP4XX)		+= ixdp425-pci.o
+obj-pci-$(CONFIG_MACH_AVILA)		+= avila-pci.o
 obj-pci-$(CONFIG_MACH_IXDPG425)		+= ixdpg425-pci.o
 obj-pci-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-pci.o
 obj-pci-$(CONFIG_MACH_GTWX5715)		+= gtwx5715-pci.o
@@ -15,6 +16,7 @@
 obj-y	+= common.o
 
 obj-$(CONFIG_ARCH_IXDP4XX)	+= ixdp425-setup.o
+obj-$(CONFIG_MACH_AVILA)	+= avila-setup.o
 obj-$(CONFIG_MACH_IXDPG425)	+= coyote-setup.o
 obj-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-setup.o
 obj-$(CONFIG_MACH_GTWX5715)	+= gtwx5715-setup.o
diff --git a/arch/arm/mach-ixp4xx/avila-pci.c b/arch/arm/mach-ixp4xx/avila-pci.c
new file mode 100644
index 0000000..3f86769
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/avila-pci.c
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-ixp4xx/avila-pci.c
+ *
+ * Gateworks Avila board-level PCI initialization
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp-pci.c
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * 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/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+void __init avila_pci_preinit(void)
+{
+	set_irq_type(IRQ_AVILA_PCI_INTA, IRQT_LOW);
+	set_irq_type(IRQ_AVILA_PCI_INTB, IRQT_LOW);
+	set_irq_type(IRQ_AVILA_PCI_INTC, IRQT_LOW);
+	set_irq_type(IRQ_AVILA_PCI_INTD, IRQT_LOW);
+
+	ixp4xx_pci_preinit();
+}
+
+static int __init avila_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[AVILA_PCI_IRQ_LINES] = {
+		IRQ_AVILA_PCI_INTA,
+		IRQ_AVILA_PCI_INTB,
+		IRQ_AVILA_PCI_INTC,
+		IRQ_AVILA_PCI_INTD
+	};
+
+	int irq = -1;
+
+	if (slot >= 1 &&
+	slot <= (machine_is_loft() ? LOFT_PCI_MAX_DEV : AVILA_PCI_MAX_DEV) &&
+		pin >= 1 && pin <= AVILA_PCI_IRQ_LINES) {
+		irq = pci_irq_table[(slot + pin - 2) % 4];
+	}
+
+	return irq;
+}
+
+struct hw_pci avila_pci __initdata = {
+	.nr_controllers = 1,
+	.preinit	= avila_pci_preinit,
+	.swizzle	= pci_std_swizzle,
+	.setup		= ixp4xx_setup,
+	.scan		= ixp4xx_scan_bus,
+	.map_irq	= avila_map_irq,
+};
+
+int __init avila_pci_init(void)
+{
+	if (machine_is_avila() || machine_is_loft())
+		pci_common_init(&avila_pci);
+	return 0;
+}
+
+subsys_initcall(avila_pci_init);
+
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
new file mode 100644
index 0000000..d59b8dc
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/avila-setup.c
@@ -0,0 +1,192 @@
+/*
+ * arch/arm/mach-ixp4xx/avila-setup.c
+ *
+ * Gateworks Avila board-setup
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp-setup.c
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data avila_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource avila_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device avila_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &avila_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &avila_flash_resource,
+};
+
+static struct ixp4xx_i2c_pins avila_i2c_gpio_pins = {
+	.sda_pin	= AVILA_SDA_PIN,
+	.scl_pin	= AVILA_SCL_PIN,
+};
+
+static struct platform_device avila_i2c_controller = {
+	.name		= "IXP4XX-I2C",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &avila_i2c_gpio_pins,
+	},
+	.num_resources	= 0
+};
+
+static struct resource avila_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM
+	},
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM
+	}
+};
+
+static struct plat_serial8250_port avila_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device avila_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= avila_uart_data,
+	.num_resources		= 2,
+	.resource		= avila_uart_resources
+};
+
+static struct resource avila_pata_resources[] = {
+	{
+		.flags	= IORESOURCE_MEM
+	},
+	{
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "intrq",
+		.start	= IRQ_IXP4XX_GPIO12,
+		.end	= IRQ_IXP4XX_GPIO12,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct ixp4xx_pata_data avila_pata_data = {
+	.cs0_bits	= 0xbfff0043,
+	.cs1_bits	= 0xbfff0043,
+};
+
+static struct platform_device avila_pata = {
+	.name			= "pata_ixp4xx_cf",
+	.id			= 0,
+	.dev.platform_data      = &avila_pata_data,
+	.num_resources		= ARRAY_SIZE(avila_pata_resources),
+	.resource		= avila_pata_resources,
+};
+
+static struct platform_device *avila_devices[] __initdata = {
+	&avila_i2c_controller,
+	&avila_flash,
+	&avila_uart
+};
+
+static void __init avila_init(void)
+{
+	ixp4xx_sys_init();
+
+	avila_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	avila_flash_resource.end =
+		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+	platform_add_devices(avila_devices, ARRAY_SIZE(avila_devices));
+
+	avila_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(1);
+	avila_pata_resources[0].end = IXP4XX_EXP_BUS_END(1);
+
+	avila_pata_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
+	avila_pata_resources[1].end = IXP4XX_EXP_BUS_END(2);
+
+	avila_pata_data.cs0_cfg = IXP4XX_EXP_CS1;
+	avila_pata_data.cs1_cfg = IXP4XX_EXP_CS2;
+
+	platform_device_register(&avila_pata);
+
+}
+
+MACHINE_START(AVILA, "Gateworks Avila Network Platform")
+	/* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
+	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
+	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer		= &ixp4xx_timer,
+	.boot_params	= 0x0100,
+	.init_machine	= avila_init,
+MACHINE_END
+
+ /*
+  * Loft is functionally equivalent to Avila except that it has a
+  * different number for the maximum PCI devices.  The MACHINE
+  * structure below is identical to Avila except for the comment.
+  */
+#ifdef CONFIG_MACH_LOFT
+MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
+	/* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */
+	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
+	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer		= &ixp4xx_timer,
+	.boot_params	= 0x0100,
+	.init_machine	= avila_init,
+MACHINE_END
+#endif
+
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 2ec9a9e..45068c3 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -395,7 +395,7 @@
 	.read		= ixp4xx_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift 		= 20,
-	.is_continuous 	= 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 unsigned long ixp4xx_timer_freq = FREQ;
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
index d5156c0..99c1dc8 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -66,7 +66,7 @@
 int __init ixdp425_pci_init(void)
 {
 	if (machine_is_ixdp425() || machine_is_ixcdp1100() ||
-			machine_is_avila() || machine_is_ixdp465())
+			machine_is_ixdp465())
 		pci_common_init(&ixdp425_pci);
 	return 0;
 }
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index da72383..04b1d56 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -156,23 +156,3 @@
 	.init_machine	= ixdp425_init,
 MACHINE_END
 #endif
-
-/*
- * Avila is functionally equivalent to IXDP425 except that it adds
- * a CF IDE slot hanging off the expansion bus. When we have a 
- * driver for IXP4xx CF IDE with driver model support we'll move
- * Avila to it's own setup file.
- */
-#ifdef CONFIG_ARCH_AVILA
-MACHINE_START(AVILA, "Gateworks Avila Network Platform")
-	/* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
-	.map_io		= ixp4xx_map_io,
-	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
-	.init_machine	= ixdp425_init,
-MACHINE_END
-#endif
-
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
index 5773b55..7e132fc 100644
--- a/arch/arm/mach-netx/time.c
+++ b/arch/arm/mach-netx/time.c
@@ -62,7 +62,7 @@
 	.read		= netx_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift 		= 20,
-	.is_continuous 	= 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 /*
diff --git a/arch/arm/mach-ns9xxx/Kconfig b/arch/arm/mach-ns9xxx/Kconfig
new file mode 100644
index 0000000..8175ba9
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/Kconfig
@@ -0,0 +1,21 @@
+if ARCH_NS9XXX
+
+menu "NS9xxx Implementations"
+
+config MACH_CC9P9360DEV
+	bool "Connect Core 9P 9360 on an A9M9750 Devboard"
+	select PROCESSOR_NS9360
+	select BOARD_A9M9750DEV
+	help
+	  Say Y here if you are using the Digi Connect Core 9P 9360
+	  on an A9M9750 Development Board.
+
+config PROCESSOR_NS9360
+	bool
+
+config BOARD_A9M9750DEV
+	bool
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ns9xxx/Makefile b/arch/arm/mach-ns9xxx/Makefile
new file mode 100644
index 0000000..91e945f
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/Makefile
@@ -0,0 +1,5 @@
+obj-y := irq.o time.o generic.o
+
+obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
+
+obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o
diff --git a/arch/arm/mach-ns9xxx/Makefile.boot b/arch/arm/mach-ns9xxx/Makefile.boot
new file mode 100644
index 0000000..75ed64e
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/Makefile.boot
@@ -0,0 +1,2 @@
+zreladdr-y := 0x108000
+params_phys-y := 0x100
diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.c b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
new file mode 100644
index 0000000..2528988
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
@@ -0,0 +1,199 @@
+/*
+ * arch/arm/mach-ns9xxx/board-a9m9750dev.c
+ *
+ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/irq.h>
+
+#include <asm/mach/map.h>
+
+#include <asm/arch-ns9xxx/board.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/regs-mem.h>
+#include <asm/arch-ns9xxx/regs-bbu.h>
+#include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
+
+#include "board-a9m9750dev.h"
+
+static struct map_desc board_a9m9750dev_io_desc[] __initdata = {
+	{ /* FPGA on CS0 */
+		.virtual = io_p2v(NS9XXX_CSxSTAT_PHYS(0)),
+		.pfn = __phys_to_pfn(NS9XXX_CSxSTAT_PHYS(0)),
+		.length = NS9XXX_CS0STAT_LENGTH,
+		.type = MT_DEVICE,
+	},
+};
+
+void __init board_a9m9750dev_map_io(void)
+{
+	iotable_init(board_a9m9750dev_io_desc,
+		     ARRAY_SIZE(board_a9m9750dev_io_desc));
+}
+
+static void a9m9750dev_fpga_ack_irq(unsigned int irq)
+{
+	/* nothing */
+}
+
+static void a9m9750dev_fpga_mask_irq(unsigned int irq)
+{
+	FPGA_IER &= ~(1 << (irq - FPGA_IRQ(0)));
+}
+
+static void a9m9750dev_fpga_maskack_irq(unsigned int irq)
+{
+	a9m9750dev_fpga_mask_irq(irq);
+	a9m9750dev_fpga_ack_irq(irq);
+}
+
+static void a9m9750dev_fpga_unmask_irq(unsigned int irq)
+{
+	FPGA_IER |= 1 << (irq - FPGA_IRQ(0));
+}
+
+static struct irq_chip a9m9750dev_fpga_chip = {
+	.ack		= a9m9750dev_fpga_ack_irq,
+	.mask		= a9m9750dev_fpga_mask_irq,
+	.mask_ack	= a9m9750dev_fpga_maskack_irq,
+	.unmask		= a9m9750dev_fpga_unmask_irq,
+};
+
+static void a9m9750dev_fpga_demux_handler(unsigned int irq,
+		struct irq_desc *desc)
+{
+	int stat = FPGA_ISR;
+
+	while (stat != 0) {
+		int irqno = fls(stat) - 1;
+
+		stat &= ~(1 << irqno);
+
+		desc = irq_desc + FPGA_IRQ(irqno);
+
+		desc_handle_irq(irqno, desc);
+	}
+}
+
+void __init board_a9m9750dev_init_irq(void)
+{
+	u32 reg;
+	int i;
+
+	/*
+	 * configure gpio for IRQ_EXT2
+	 * use GPIO 11, because GPIO 32 is used for the LCD
+	 */
+	/* XXX: proper GPIO handling */
+	BBU_GC(2) &= ~0x2000;
+
+	for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) {
+		set_irq_chip(i, &a9m9750dev_fpga_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	/* IRQ_EXT2: level sensitive + active low */
+	reg = SYS_EIC(2);
+	REGSET(reg, SYS_EIC, PLTY, AL);
+	REGSET(reg, SYS_EIC, LVEDG, LEVEL);
+	SYS_EIC(2) = reg;
+
+	set_irq_chained_handler(IRQ_EXT2,
+			a9m9750dev_fpga_demux_handler);
+}
+
+static struct plat_serial8250_port board_a9m9750dev_serial8250_port[] = {
+	{
+		.iobase         = FPGA_UARTA_BASE,
+		.membase        = (unsigned char*)FPGA_UARTA_BASE,
+		.mapbase        = FPGA_UARTA_BASE,
+		.irq            = IRQ_FPGA_UARTA,
+		.iotype         = UPIO_MEM,
+		.uartclk        = 18432000,
+		.regshift       = 0,
+		.flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+	}, {
+		.iobase         = FPGA_UARTB_BASE,
+		.membase        = (unsigned char*)FPGA_UARTB_BASE,
+		.mapbase        = FPGA_UARTB_BASE,
+		.irq            = IRQ_FPGA_UARTB,
+		.iotype         = UPIO_MEM,
+		.uartclk        = 18432000,
+		.regshift       = 0,
+		.flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+	}, {
+		.iobase         = FPGA_UARTC_BASE,
+		.membase        = (unsigned char*)FPGA_UARTC_BASE,
+		.mapbase        = FPGA_UARTC_BASE,
+		.irq            = IRQ_FPGA_UARTC,
+		.iotype         = UPIO_MEM,
+		.uartclk        = 18432000,
+		.regshift       = 0,
+		.flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+	}, {
+		.iobase         = FPGA_UARTD_BASE,
+		.membase        = (unsigned char*)FPGA_UARTD_BASE,
+		.mapbase        = FPGA_UARTD_BASE,
+		.irq            = IRQ_FPGA_UARTD,
+		.iotype         = UPIO_MEM,
+		.uartclk        = 18432000,
+		.regshift       = 0,
+		.flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+	}, {
+		/* end marker */
+	},
+};
+
+static struct platform_device board_a9m9750dev_serial_device = {
+	.name = "serial8250",
+	.dev = {
+		.platform_data = board_a9m9750dev_serial8250_port,
+	},
+};
+
+static struct platform_device *board_a9m9750dev_devices[] __initdata = {
+	&board_a9m9750dev_serial_device,
+};
+
+void __init board_a9m9750dev_init_machine(void)
+{
+	u32 reg;
+
+	/* setup static CS0: memory base ... */
+	REGSETIM(SYS_SMCSSMB(0), SYS_SMCSSMB, CSxB,
+			NS9XXX_CSxSTAT_PHYS(0) >> 12);
+
+	/* ... and mask */
+	reg = SYS_SMCSSMM(0);
+	REGSETIM(reg, SYS_SMCSSMM, CSxM, 0xfffff);
+	REGSET(reg, SYS_SMCSSMM, CSEx, EN);
+	SYS_SMCSSMM(0) = reg;
+
+	/* setup static CS0: memory configuration */
+	reg = MEM_SMC(0);
+	REGSET(reg, MEM_SMC, WSMC, OFF);
+	REGSET(reg, MEM_SMC, BSMC, OFF);
+	REGSET(reg, MEM_SMC, EW, OFF);
+	REGSET(reg, MEM_SMC, PB, 1);
+	REGSET(reg, MEM_SMC, PC, AL);
+	REGSET(reg, MEM_SMC, PM, DIS);
+	REGSET(reg, MEM_SMC, MW, 8);
+	MEM_SMC(0) = reg;
+
+	/* setup static CS0: timing */
+	MEM_SMWED(0) = 0x2;
+	MEM_SMOED(0) = 0x2;
+	MEM_SMRD(0) = 0x6;
+	MEM_SMWD(0) = 0x6;
+
+	platform_add_devices(board_a9m9750dev_devices,
+			ARRAY_SIZE(board_a9m9750dev_devices));
+}
+
diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.h b/arch/arm/mach-ns9xxx/board-a9m9750dev.h
new file mode 100644
index 0000000..edc75ab
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/board-a9m9750dev.h
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-ns9xxx/board-a9m9750dev.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/init.h>
+
+void __init board_a9m9750dev_map_io(void);
+void __init board_a9m9750dev_init_machine(void);
+void __init board_a9m9750dev_init_irq(void);
diff --git a/arch/arm/mach-ns9xxx/generic.c b/arch/arm/mach-ns9xxx/generic.c
new file mode 100644
index 0000000..83e2b65
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/generic.c
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/mach-ns9xxx/generic.c
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/regs-mem.h>
+#include <asm/arch-ns9xxx/board.h>
+
+static struct map_desc standard_io_desc[] __initdata = {
+	{ /* BBus */
+		.virtual = io_p2v(0x90000000),
+		.pfn = __phys_to_pfn(0x90000000),
+		.length = 0x00700000,
+		.type = MT_DEVICE,
+	}, { /* AHB */
+		.virtual = io_p2v(0xa0100000),
+		.pfn = __phys_to_pfn(0xa0100000),
+		.length = 0x00900000,
+		.type = MT_DEVICE,
+	},
+};
+
+void __init ns9xxx_map_io(void)
+{
+	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+}
+
+void __init ns9xxx_init_machine(void)
+{
+}
diff --git a/arch/arm/mach-ns9xxx/generic.h b/arch/arm/mach-ns9xxx/generic.h
new file mode 100644
index 0000000..687e2917
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/generic.h
@@ -0,0 +1,19 @@
+/*
+ * arch/arm/mach-ns9xxx/generic.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/time.h>
+#include <asm/mach/time.h>
+#include <linux/init.h>
+
+void __init ns9xxx_init_irq(void);
+void __init ns9xxx_map_io(void);
+void __init ns9xxx_init_machine(void);
+
+extern struct sys_timer ns9xxx_timer;
diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c
new file mode 100644
index 0000000..83d9272
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/irq.c
@@ -0,0 +1,94 @@
+/*
+ * arch/arm/mach-ns9xxx/irq.c
+ *
+ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/interrupt.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/irqs.h>
+#include <asm/arch-ns9xxx/board.h>
+
+#include "generic.h"
+
+static void ns9xxx_ack_irq_timer(unsigned int irq)
+{
+	u32 tc = SYS_TC(irq - IRQ_TIMER0);
+
+	REGSET(tc, SYS_TCx, INTC, SET);
+	SYS_TC(irq - IRQ_TIMER0) = tc;
+
+	REGSET(tc, SYS_TCx, INTC, UNSET);
+	SYS_TC(irq - IRQ_TIMER0) = tc;
+}
+
+void (*ns9xxx_ack_irq_functions[NR_IRQS])(unsigned int) = {
+	[IRQ_TIMER0] = ns9xxx_ack_irq_timer,
+	[IRQ_TIMER1] = ns9xxx_ack_irq_timer,
+	[IRQ_TIMER2] = ns9xxx_ack_irq_timer,
+	[IRQ_TIMER3] = ns9xxx_ack_irq_timer,
+};
+
+static void ns9xxx_mask_irq(unsigned int irq)
+{
+	/* XXX: better use cpp symbols */
+	SYS_IC(irq / 4) &= ~(1 << (7 + 8 * (3 - (irq & 3))));
+}
+
+static void ns9xxx_ack_irq(unsigned int irq)
+{
+	if (!ns9xxx_ack_irq_functions[irq]) {
+		printk(KERN_ERR "no ack function for irq %u\n", irq);
+		BUG();
+	}
+
+	ns9xxx_ack_irq_functions[irq](irq);
+	SYS_ISRADDR = 0;
+}
+
+static void ns9xxx_maskack_irq(unsigned int irq)
+{
+	ns9xxx_mask_irq(irq);
+	ns9xxx_ack_irq(irq);
+}
+
+static void ns9xxx_unmask_irq(unsigned int irq)
+{
+	/* XXX: better use cpp symbols */
+	SYS_IC(irq / 4) |= 1 << (7 + 8 * (3 - (irq & 3)));
+}
+
+static struct irq_chip ns9xxx_chip = {
+	.ack		= ns9xxx_ack_irq,
+	.mask		= ns9xxx_mask_irq,
+	.mask_ack	= ns9xxx_maskack_irq,
+	.unmask		= ns9xxx_unmask_irq,
+};
+
+void __init ns9xxx_init_irq(void)
+{
+	int i;
+
+	/* disable all IRQs */
+	for (i = 0; i < 8; ++i)
+		SYS_IC(i) = (4 * i) << 24 | (4 * i + 1) << 16 |
+			(4 * i + 2) << 8 | (4 * i + 3);
+
+	/* simple interrupt prio table:
+	 * prio(x) < prio(y) <=> x < y
+	 */
+	for (i = 0; i < 32; ++i)
+		SYS_IVA(i) = i;
+
+	for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) {
+		set_irq_chip(i, &ns9xxx_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+}
diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
new file mode 100644
index 0000000..a193dd9
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
@@ -0,0 +1,41 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "board-a9m9750dev.h"
+#include "generic.h"
+
+static void __init mach_cc9p9360dev_map_io(void)
+{
+	ns9xxx_map_io();
+	board_a9m9750dev_map_io();
+}
+
+static void __init mach_cc9p9360dev_init_irq(void)
+{
+	ns9xxx_init_irq();
+	board_a9m9750dev_init_irq();
+}
+
+static void __init mach_cc9p9360dev_init_machine(void)
+{
+	ns9xxx_init_machine();
+	board_a9m9750dev_init_machine();
+}
+
+MACHINE_START(CC9P9360DEV, "Connect Core 9P 9360 on an A9M9750 Devboard")
+	.map_io = mach_cc9p9360dev_map_io,
+	.init_irq = mach_cc9p9360dev_init_irq,
+	.init_machine = mach_cc9p9360dev_init_machine,
+	.timer = &ns9xxx_timer,
+	.boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/time.c b/arch/arm/mach-ns9xxx/time.c
new file mode 100644
index 0000000..eec05f1
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/time.c
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-ns9xxx/time.c
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/clock.h>
+#include <asm/arch-ns9xxx/irqs.h>
+#include <asm/arch/system.h>
+#include "generic.h"
+
+#define TIMERCLOCKSELECT 64
+
+static u32 usecs_per_tick;
+
+static irqreturn_t
+ns9xxx_timer_interrupt(int irq, void *dev_id)
+{
+	write_seqlock(&xtime_lock);
+	timer_tick();
+	write_sequnlock(&xtime_lock);
+
+	return IRQ_HANDLED;
+}
+
+static unsigned long ns9xxx_timer_gettimeoffset(void)
+{
+	/* return the microseconds which have passed since the last interrupt
+	 * was _serviced_.  That is, if an interrupt is pending or the counter
+	 * reloads, return one periode more. */
+
+	u32 counter1 = SYS_TR(0);
+	int pending = SYS_ISR & (1 << IRQ_TIMER0);
+	u32 counter2 = SYS_TR(0);
+	u32 elapsed;
+
+	if (pending || counter2 > counter1)
+		elapsed = 2 * SYS_TRC(0) - counter2;
+	else
+		elapsed = SYS_TRC(0) - counter1;
+
+	return (elapsed * usecs_per_tick) >> 16;
+
+}
+
+static struct irqaction ns9xxx_timer_irq = {
+	.name = "NS9xxx Timer Tick",
+	.flags = IRQF_DISABLED | IRQF_TIMER,
+	.handler = ns9xxx_timer_interrupt,
+};
+
+static void __init ns9xxx_timer_init(void)
+{
+	int tc;
+
+	usecs_per_tick =
+		SH_DIV(1000000 * TIMERCLOCKSELECT, ns9xxx_cpuclock(), 16);
+
+	/* disable timer */
+	if ((tc = SYS_TC(0)) & SYS_TCx_TEN)
+		SYS_TC(0) = tc & ~SYS_TCx_TEN;
+
+	SYS_TRC(0) = SH_DIV(ns9xxx_cpuclock(), (TIMERCLOCKSELECT * HZ), 0);
+
+	REGSET(tc, SYS_TCx, TEN, EN);
+	REGSET(tc, SYS_TCx, TLCS, DIV64); /* This must match TIMERCLOCKSELECT */
+	REGSET(tc, SYS_TCx, INTS, EN);
+	REGSET(tc, SYS_TCx, UDS, DOWN);
+	REGSET(tc, SYS_TCx, TDBG, STOP);
+	REGSET(tc, SYS_TCx, TSZ, 32);
+	REGSET(tc, SYS_TCx, REN, EN);
+	SYS_TC(0) = tc;
+
+	setup_irq(IRQ_TIMER0, &ns9xxx_timer_irq);
+}
+
+struct sys_timer ns9xxx_timer = {
+	.init = ns9xxx_timer_init,
+	.offset = ns9xxx_timer_gettimeoffset,
+};
diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c
index 4c3de40..165017d 100644
--- a/arch/arm/mach-pxa/corgi_pm.c
+++ b/arch/arm/mach-pxa/corgi_pm.c
@@ -16,7 +16,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <asm/apm.h>
+#include <asm/apm-emulation.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 9de1278..b8cb79f 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -36,6 +36,7 @@
 #include <asm/mach/map.h>
 
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/gpio.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
@@ -106,13 +107,16 @@
  * Handy function to set GPIO alternate functions
  */
 
-void pxa_gpio_mode(int gpio_mode)
+int pxa_gpio_mode(int gpio_mode)
 {
 	unsigned long flags;
 	int gpio = gpio_mode & GPIO_MD_MASK_NR;
 	int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
 	int gafr;
 
+	if (gpio > PXA_LAST_GPIO)
+		return -EINVAL;
+
 	local_irq_save(flags);
 	if (gpio_mode & GPIO_DFLT_LOW)
 		GPCR(gpio) = GPIO_bit(gpio);
@@ -125,11 +129,33 @@
 	gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
 	GAFR(gpio) = gafr |  (fn  << (((gpio) & 0xf)*2));
 	local_irq_restore(flags);
+
+	return 0;
 }
 
 EXPORT_SYMBOL(pxa_gpio_mode);
 
 /*
+ * Return GPIO level
+ */
+int pxa_gpio_get_value(unsigned gpio)
+{
+	return __gpio_get_value(gpio);
+}
+
+EXPORT_SYMBOL(pxa_gpio_get_value);
+
+/*
+ * Set output GPIO level
+ */
+void pxa_gpio_set_value(unsigned gpio, int value)
+{
+	__gpio_set_value(gpio, value);
+}
+
+EXPORT_SYMBOL(pxa_gpio_set_value);
+
+/*
  * Routine to safely enable or disable a clock in the CKEN
  */
 void pxa_set_cken(int clock, int enable)
@@ -338,6 +364,27 @@
 	.num_resources	= ARRAY_SIZE(i2c_resources),
 };
 
+#ifdef CONFIG_PXA27x
+static struct resource i2c_power_resources[] = {
+	{
+		.start	= 0x40f00180,
+		.end	= 0x40f001a3,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_PWRI2C,
+		.end	= IRQ_PWRI2C,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device i2c_power_device = {
+	.name		= "pxa2xx-i2c",
+	.id		= 1,
+	.resource	= i2c_power_resources,
+	.num_resources	= ARRAY_SIZE(i2c_resources),
+};
+#endif
+
 void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
 {
 	i2c_device.dev.platform_data = info;
@@ -392,6 +439,9 @@
 	&stuart_device,
 	&pxaficp_device,
 	&i2c_device,
+#ifdef CONFIG_PXA27x
+	&i2c_power_device,
+#endif
 	&i2s_device,
 	&pxartc_device,
 };
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index db6e8f5..b1d8cfc 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -23,7 +23,7 @@
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/apm.h>
+#include <asm/apm-emulation.h>
 #include <asm/arch/pm.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/sharpsl.h>
diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c
index 40be833..b97d543 100644
--- a/arch/arm/mach-pxa/spitz_pm.c
+++ b/arch/arm/mach-pxa/spitz_pm.c
@@ -16,7 +16,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <asm/apm.h>
+#include <asm/apm-emulation.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index ee2beb4..fc3b82a 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -112,7 +112,7 @@
 	.read           = pxa_get_cycles,
 	.mask           = CLOCKSOURCE_MASK(32),
 	.shift          = 20,
-	.is_continuous  = 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static void __init pxa_timer_init(void)
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index 17f5f44..35156ca 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -10,10 +10,21 @@
 config REALVIEW_MPCORE
 	bool "Support MPcore tile"
 	depends on MACH_REALVIEW_EB
+	select CACHE_L2X0
 	help
 	  Enable support for the MPCore tile on the Realview platform.
 	  Since there are device address and interrupt differences, a
 	  kernel built with this option enabled is not compatible with
 	  other tiles.
 
+config REALVIEW_MPCORE_REVB
+	bool "Support MPcore RevB tile"
+	depends on REALVIEW_MPCORE
+	default n
+	help
+	  Enable support for the MPCore RevB tile on the Realview platform.
+	  Since there are device address differences, a
+	  kernel built with this option enabled is not compatible with
+	  other tiles.
+
 endmenu
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index b8484e1..fce3596 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -52,13 +52,14 @@
 	 * core (e.g. timer irq), then they will not have been enabled
 	 * for us: do so
 	 */
-	gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE));
+	gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
 
 	/*
 	 * let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
 	pen_release = -1;
+	smp_wmb();
 
 	/*
 	 * Synchronise with the boot thread.
@@ -102,6 +103,7 @@
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
+		smp_rmb();
 		if (pen_release == -1)
 			break;
 
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 9741b4d..3dba666 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -31,6 +31,7 @@
 #include <asm/mach-types.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/icst307.h>
+#include <asm/hardware/cache-l2x0.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -57,7 +58,26 @@
 		.pfn		= __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
+	},
+#ifdef CONFIG_REALVIEW_MPCORE
+	{
+		.virtual	= IO_ADDRESS(REALVIEW_GIC1_CPU_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_GIC1_CPU_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
 	}, {
+		.virtual	= IO_ADDRESS(REALVIEW_GIC1_DIST_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_GIC1_DIST_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(REALVIEW_MPCORE_L220_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_MPCORE_L220_BASE),
+		.length		= SZ_8K,
+		.type		= MT_DEVICE,
+	},
+#endif
+	{
 		.virtual	= IO_ADDRESS(REALVIEW_SCTL_BASE),
 		.pfn		= __phys_to_pfn(REALVIEW_SCTL_BASE),
 		.length		= SZ_4K,
@@ -138,19 +158,29 @@
 #ifdef CONFIG_REALVIEW_MPCORE
 	unsigned int pldctrl;
 	writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
-	pldctrl = readl(__io_address(REALVIEW_SYS_BASE)	+ 0xd8);
+	pldctrl = readl(__io_address(REALVIEW_SYS_BASE)	+ REALVIEW_MPCORE_SYS_PLD_CTRL1);
 	pldctrl |= 0x00800000;	/* New irq mode */
-	writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + 0xd8);
+	writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
 	writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 #endif
-	gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE));
-	gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE));
+	gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
+	gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
+#ifdef CONFIG_REALVIEW_MPCORE
+	gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64);
+	gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE));
+	gic_cascade_irq(1, IRQ_EB_IRQ1);
+#endif
 }
 
 static void __init realview_eb_init(void)
 {
 	int i;
 
+#ifdef CONFIG_REALVIEW_MPCORE
+	/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
+	 * Bits:  .... ...0 0111 1001 0000 .... .... .... */
+	l2x0_init(__io_address(REALVIEW_MPCORE_L220_BASE), 0x00790000, 0xfe000fff);
+#endif
 	clk_register(&realview_clcd_clk);
 
 	platform_device_register(&realview_flash_device);
diff --git a/arch/arm/mach-s3c2400/Kconfig b/arch/arm/mach-s3c2400/Kconfig
new file mode 100644
index 0000000..deab0722
--- /dev/null
+++ b/arch/arm/mach-s3c2400/Kconfig
@@ -0,0 +1,13 @@
+# arch/arm/mach-s3c2400/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+
+
+menu "S3C2400 Machines"
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2400/Makefile b/arch/arm/mach-s3c2400/Makefile
new file mode 100644
index 0000000..7e23f4e
--- /dev/null
+++ b/arch/arm/mach-s3c2400/Makefile
@@ -0,0 +1,15 @@
+# arch/arm/mach-s3c2400/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+obj-$(CONFIG_CPU_S3C2400)	+= gpio.o
+
+# Machine support
+
diff --git a/arch/arm/mach-s3c2400/gpio.c b/arch/arm/mach-s3c2400/gpio.c
new file mode 100644
index 0000000..758e1604
--- /dev/null
+++ b/arch/arm/mach-s3c2400/gpio.c
@@ -0,0 +1,42 @@
+/* linux/arch/arm/mach-s3c2400/gpio.c
+ *
+ * Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org>
+ *
+ * S3C2400 GPIO support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-gpio.h>
+
+int s3c2400_gpio_getirq(unsigned int pin)
+{
+	if (pin < S3C2410_GPE0 || pin > S3C2400_GPE7_EINT7)
+		return -1;  /* not valid interrupts */
+
+	return (pin - S3C2410_GPE0) + IRQ_EINT0;
+}
+
+EXPORT_SYMBOL(s3c2400_gpio_getirq);
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index eb4ec41..d4b013b 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -1,30 +1,69 @@
-if ARCH_S3C2410
+# arch/arm/mach-s3c2410/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
 
-menu "S3C24XX Implementations"
+config CPU_S3C2410
+	bool
+	depends on ARCH_S3C2410
+	select S3C2410_CLOCK
+	select S3C2410_GPIO
+	select S3C2410_PM if PM
+	help
+	  Support for S3C2410 and S3C2410A family from the S3C24XX line
+	  of Samsung Mobile CPUs.
 
-config MACH_AML_M5900
-	bool "AML M5900 Series"
+config CPU_S3C2410_DMA
+	bool
+	depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
+	default y if CPU_S3C2410 || CPU_S3C2442
+	help
+	  DMA device selection for S3C2410 and compatible CPUs
+
+config S3C2410_PM
+	bool
+	help
+	  Power Management code common to S3C2410 and better
+
+config S3C2410_GPIO
+	bool
+	help
+	  GPIO code for S3C2410 and similar processors
+
+config S3C2410_CLOCK
+	bool
+	help
+	  Clock code for the S3C2410, and similar processors
+
+
+menu "S3C2410 Machines"
+
+config ARCH_SMDK2410
+	bool "SMDK2410/A9M2410"
 	select CPU_S3C2410
-	select PM_SIMTEC if PM
+	select MACH_SMDK
 	help
-	   Say Y here if you are using the American Microsystems M5900 Series
-           <http://www.amltd.com>
+	   Say Y here if you are using the SMDK2410 or the derived module A9M2410
+           <http://www.fsforth.de>
 
-config MACH_ANUBIS
-	bool "Simtec Electronics ANUBIS"
-	select CPU_S3C2440
-	select PM_SIMTEC if PM
+config ARCH_H1940
+	bool "IPAQ H1940"
+	select CPU_S3C2410
+	select PM_H1940 if PM
 	help
-	  Say Y here if you are using the Simtec Electronics ANUBIS
-	  development system
+	  Say Y here if you are using the HP IPAQ H1940
 
-config MACH_OSIRIS
-	bool "Simtec IM2440D20 (OSIRIS) module"
-	select CPU_S3C2440
-	select PM_SIMTEC if PM
+config PM_H1940
+	bool
 	help
-	  Say Y here if you are using the Simtec IM2440D20 module, also
-	  known as the Osiris.
+	  Internal node for H1940 and related PM
+
+config MACH_N30
+	bool "Acer N30"
+	select CPU_S3C2410
+	help
+	  Say Y here if you are using the Acer N30
 
 config ARCH_BAST
 	bool "Simtec Electronics BAST (EB2410ITX)"
@@ -35,7 +74,19 @@
 	  Say Y here if you are using the Simtec Electronics EB2410ITX
 	  development board (also known as BAST)
 
-	  Product page: <http://www.simtec.co.uk/products/EB2410ITX/>.
+config MACH_OTOM
+ 	bool "NexVision OTOM Board"
+ 	select CPU_S3C2410
+	help
+ 	  Say Y here if you are using the Nex Vision OTOM board
+
+config MACH_AML_M5900
+	bool "AML M5900 Series"
+	select CPU_S3C2410
+	select PM_SIMTEC if PM
+	help
+	   Say Y here if you are using the American Microsystems M5900 Series
+           <http://www.amltd.com>
 
 config BAST_PC104_IRQ
 	bool "BAST PC104 IRQ support"
@@ -45,74 +96,6 @@
 	  Say Y	here to enable the PC104 IRQ routing on the
 	  Simtec BAST (EB2410ITX)
 
-config PM_H1940
-	bool
-	help
-	  Internal node for H1940 and related PM
-
-config ARCH_H1940
-	bool "IPAQ H1940"
-	select CPU_S3C2410
-	select PM_H1940 if PM
-	help
-	  Say Y here if you are using the HP IPAQ H1940
-
-	  <http://www.handhelds.org/projects/h1940.html>.
-
-config MACH_N30
-	bool "Acer N30"
-	select CPU_S3C2410
-	help
-	  Say Y here if you are using the Acer N30
-
-	  <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>
-
-config ARCH_S3C2440
-	bool "SMDK2440"
-	select CPU_S3C2440
-	select MACH_SMDK
-	help
-	  Say Y here if you are using the SMDK2440.
-
-config SMDK2440_CPU2440
-	bool "SMDK2440 with S3C2440 CPU module"
-	depends on ARCH_S3C2440
-	default y if ARCH_S3C2440
-	select CPU_S3C2440
-
-config SMDK2440_CPU2442
-	bool "SMDM2440 with S3C2442 CPU module"
-	depends on ARCH_S3C2440
-	select CPU_S3C2442
-
-config MACH_S3C2413
-	bool
-	help
-	  Internal node for S3C2413 version of SMDK2413, so that
-	  machine_is_s3c2413() will work when MACH_SMDK2413 is
-	  selected
-
-config MACH_SMDK2413
-	bool "SMDK2413"
-	select CPU_S3C2412
-	select MACH_S3C2413
-	select MACH_SMDK
-	help
-	  Say Y here if you are using an SMDK2413
-
 config MACH_VR1000
 	bool "Thorcom VR1000"
 	select PM_SIMTEC if PM
@@ -120,202 +103,11 @@
 	help
 	  Say Y here if you are using the Thorcom VR1000 board.
 
-	  This linux port is currently being maintained by Simtec, on behalf
-	  of Thorcom. Any queries, please contact Thorcom first.
-
-config MACH_RX3715
-	bool "HP iPAQ rx3715"
-	select CPU_S3C2440
-	select PM_H1940 if PM
+config MACH_QT2410
+	bool "QT2410"
+	select CPU_S3C2410
 	help
-	  Say Y here if you are using the HP iPAQ rx3715.
-
-	  See <http://www.handhelds.org/projects/rx3715.html> for more
-	  information on this project
-
-config MACH_OTOM
- 	bool "NexVision OTOM Board"
- 	select CPU_S3C2410
-	help
- 	  Say Y here if you are using the Nex Vision OTOM board
-
-config MACH_NEXCODER_2440
- 	bool "NexVision NEXCODER 2440 Light Board"
- 	select CPU_S3C2440
-	help
- 	  Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
-
-config MACH_VSTMS
-	bool "VMSTMS"
-	select CPU_S3C2412
-	help
-	  Say Y here if you are using an VSTMS board
+	   Say Y here if you are using the Armzone QT2410
 
 endmenu
 
-config S3C2410_CLOCK
-	bool
-	help
-	  Clock code for the S3C2410, and similar processors
-
-config S3C2410_PM
-	bool
-	help
-	  Power Management code common to S3C2410 and better
-
-config CPU_S3C2410_DMA
-	bool
-	depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
-	default y if CPU_S3C2410 || CPU_S3C2442
-	help
-	  DMA device selection for S3C2410 and compatible CPUs
-
-config CPU_S3C2410
-	bool
-	depends on ARCH_S3C2410
-	select S3C2410_CLOCK
-	select S3C2410_PM if PM
-	help
-	  Support for S3C2410 and S3C2410A family from the S3C24XX line
-	  of Samsung Mobile CPUs.
-
-# internal node to signify if we are only dealing with an S3C2412
-
-config CPU_S3C2412_ONLY
-	bool
-	depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
-		   !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
-	default y if CPU_S3C2412
-
-config S3C2412_PM
-	bool
-	help
-	  Internal config node to apply S3C2412 power management
-
-config CPU_S3C2412
-	bool
-	depends on ARCH_S3C2410
-	select S3C2412_PM if PM
-	help
-	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
-
-config CPU_S3C244X
-	bool
-	depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
-	help
-	  Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
-
-config CPU_S3C2440
-	bool
-	depends on ARCH_S3C2410
-	select S3C2410_CLOCK
-	select S3C2410_PM if PM
-	select CPU_S3C244X
-	help
-	  Support for S3C2440 Samsung Mobile CPU based systems.
-
-config CPU_S3C2442
-	bool
-	depends on ARCH_S3C2420
-	select S3C2410_CLOCK
-	select S3C2410_PM if PM
-	select CPU_S3C244X
-	help
-	  Support for S3C2442 Samsung Mobile CPU based systems.
-
-comment "S3C2410 Boot"
-
-config S3C2410_BOOT_WATCHDOG
-	bool "S3C2410 Initialisation watchdog"
-	depends on ARCH_S3C2410 && S3C2410_WATCHDOG
-	help
-	  Say y to enable the watchdog during the kernel decompression
-	  stage. If the kernel fails to uncompress, then the watchdog
-	  will trigger a reset and the system should restart.
-
-	  Although this uses the same hardware unit as the kernel watchdog
-	  driver, it is not a replacement for it. If you use this option,
-	  you will have to use the watchdg driver to either stop the timeout
-	  or restart it. If you do not, then your kernel will reboot after
-	  startup.
-
-	  The driver uses a fixed timeout value, so the exact time till the
-	  system resets depends on the value of PCLK. The timeout on an
-	  200MHz s3c2410 should be about 30 seconds.
-
-config S3C2410_BOOT_ERROR_RESET
-	bool "S3C2410 Reboot on decompression error"
-	depends on ARCH_S3C2410
-	help
-	  Say y here to use the watchdog to reset the system if the
-	  kernel decompressor detects an error during decompression.
-
-
-comment "S3C2410 Setup"
-
-config S3C2410_DMA
-	bool "S3C2410 DMA support"
-	depends on ARCH_S3C2410
-	help
-	  S3C2410 DMA support. This is needed for drivers like sound which
-	  use the S3C2410's DMA system to move data to and from the
-	  peripheral blocks.
-
-config S3C2410_DMA_DEBUG
-	bool "S3C2410 DMA support debug"
-	depends on ARCH_S3C2410 && S3C2410_DMA
-	help
-	  Enable debugging output for the DMA code. This option sends info
-	  to the kernel log, at priority KERN_DEBUG.
-
-	  Note, it is easy to create and fill the log buffer in a small
-	  amount of time, as well as using an significant percentage of
-	  the CPU time doing so.
-
-
-config S3C2410_PM_DEBUG
-	bool "S3C2410 PM Suspend debug"
-	depends on ARCH_S3C2410 && PM
-	help
-	  Say Y here if you want verbose debugging from the PM Suspend and
-	  Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
-	  for more information.
-
-config S3C2410_PM_CHECK
-	bool "S3C2410 PM Suspend Memory CRC"
-	depends on ARCH_S3C2410 && PM && CRC32
-	help
- 	  Enable the PM code's memory area checksum over sleep. This option
-	  will generate CRCs of all blocks of memory, and store them before
-	  going to sleep. The blocks are then checked on resume for any
-	  errors.
-
-config S3C2410_PM_CHECK_CHUNKSIZE
-	int "S3C2410 PM Suspend CRC Chunksize (KiB)"
-	depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
-	default 64
-	help
-	  Set the chunksize in Kilobytes of the CRC for checking memory
-	  corruption over suspend and resume. A smaller value will mean that
-	  the CRC data block will take more memory, but wil identify any
-	  faults with better precision.
-
-config PM_SIMTEC
-	bool
-	help
-	  Common power management code for systems that are
-	  compatible with the Simtec style of power management
-
-config S3C2410_LOWLEVEL_UART_PORT
-	int "S3C2410 UART to use for low-level messages"
-	default 0
-	help
-	  Choice of which UART port to use for the low-level messages,
-	  such as the `Uncompressing...` at start time. The value of
-	  this configuration should be between zero and two. The port
-	  must have been initialised by the boot-loader before use.
-
-	  Note, this does not affect the port used by the debug messages,
-	  which is a separate configuration.
-
-endif
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 27663e2..9a3d3d2 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -1,92 +1,31 @@
-
+# arch/arm/mach-s3c2410/Makefile
 #
-# Makefile for the linux kernel.
+# Copyright 2007 Simtec Electronics
 #
+# Licensed under GPLv2
 
-# Object file lists.
-
-obj-y			:= cpu.o irq.o time.o gpio.o clock.o devs.o
-obj-m			:=
-obj-n			:=
-obj-			:=
-obj-dma-y		:=
-obj-dma-n		:=
-
-# DMA
-obj-$(CONFIG_S3C2410_DMA)	+= dma.o
-
-# S3C2400 support files
-obj-$(CONFIG_CPU_S3C2400)	+= s3c2400-gpio.o
-
-# S3C2410 support files
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
 
 obj-$(CONFIG_CPU_S3C2410)	+= s3c2410.o
-obj-$(CONFIG_CPU_S3C2410)	+= s3c2410-gpio.o
-obj-$(CONFIG_CPU_S3C2410)	+= s3c2410-irq.o
+obj-$(CONFIG_CPU_S3C2410)	+= irq.o
+obj-$(CONFIG_CPU_S3C2410_DMA)	+= dma.o
+obj-$(CONFIG_CPU_S3C2410_DMA)	+= dma.o
+obj-$(CONFIG_S3C2410_PM)	+= pm.o sleep.o
+obj-$(CONFIG_S3C2410_GPIO)	+= gpio.o
+obj-$(CONFIG_S3C2410_CLOCK)	+= clock.o
 
-obj-$(CONFIG_S3C2410_PM)	+= s3c2410-pm.o s3c2410-sleep.o
-obj-$(CONFIG_CPU_S3C2410_DMA)	+= s3c2410-dma.o
+# Machine support
 
-# Power Management support
-
-obj-$(CONFIG_PM)		+= pm.o sleep.o
-obj-$(CONFIG_PM_SIMTEC)		+= pm-simtec.o
-obj-$(CONFIG_PM_H1940)		+= pm-h1940.o
-
-# S3C2412 support
-obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o
-obj-$(CONFIG_CPU_S3C2412)	+= s3c2412-irq.o
-obj-$(CONFIG_CPU_S3C2412)	+= s3c2412-clock.o
-obj-dma-$(CONFIG_CPU_S3C2412)	+= s3c2412-dma.o
-
-obj-$(CONFIG_S3C2412_PM)	+= s3c2412-pm.o
-
-#
-# S3C244X support
-
-obj-$(CONFIG_CPU_S3C244X)	+= s3c244x.o
-obj-$(CONFIG_CPU_S3C244X)	+= s3c244x-irq.o
-
-# Clock control
-
-obj-$(CONFIG_S3C2410_CLOCK)	+= s3c2410-clock.o
-
-# S3C2440 support
-
-obj-$(CONFIG_CPU_S3C2440)	+= s3c2440.o s3c2440-dsc.o
-obj-$(CONFIG_CPU_S3C2440)	+= s3c2440-irq.o
-obj-$(CONFIG_CPU_S3C2440)	+= s3c2440-clock.o
-obj-$(CONFIG_CPU_S3C2440)	+= s3c2410-gpio.o
-obj-dma-$(CONFIG_CPU_S3C2440)	+= s3c2440-dma.o
-
-# S3C2442 support
-
-obj-$(CONFIG_CPU_S3C2442)	+= s3c2442.o
-obj-$(CONFIG_CPU_S3C2442)	+= s3c2442-clock.o
-
-# bast extras
-
-obj-$(CONFIG_BAST_PC104_IRQ)	+= bast-irq.o
-
-# merge in dma objects
-
-obj-y				+= $(obj-dma-y)
-
-# machine specific support
-
-obj-$(CONFIG_MACH_AML_M5900)	+= mach-amlm5900.o
-obj-$(CONFIG_MACH_ANUBIS)	+= mach-anubis.o
-obj-$(CONFIG_MACH_OSIRIS)	+= mach-osiris.o
-obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
-obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
-obj-$(CONFIG_MACH_N30)		+= mach-n30.o
 obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
-obj-$(CONFIG_MACH_SMDK2413)	+= mach-smdk2413.o
-obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
-obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
-obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
+obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
+obj-$(CONFIG_PM_H1940)		+= pm-h1940.o
+obj-$(CONFIG_MACH_N30)		+= mach-n30.o
+obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
 obj-$(CONFIG_MACH_OTOM)		+= mach-otom.o
-obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
-obj-$(CONFIG_MACH_VSTMS)	+= mach-vstms.o
-
-obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
\ No newline at end of file
+obj-$(CONFIG_MACH_AML_M5900)	+= mach-amlm5900.o
+obj-$(CONFIG_BAST_PC104_IRQ)	+= bast-irq.o
+obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
+obj-$(CONFIG_MACH_QT2410)	+= mach-qt2410.o
diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c
index 379efe7..daeba42 100644
--- a/arch/arm/mach-s3c2410/bast-irq.c
+++ b/arch/arm/mach-s3c2410/bast-irq.c
@@ -39,7 +39,7 @@
 #include <asm/arch/bast-map.h>
 #include <asm/arch/bast-irq.h>
 
-#include "irq.h"
+#include <asm/plat-s3c24xx/irq.h>
 
 #if 0
 #include <asm/debug-ll.h>
diff --git a/arch/arm/mach-s3c2410/bast.h b/arch/arm/mach-s3c2410/bast.h
index e5d0331..e985437 100644
--- a/arch/arm/mach-s3c2410/bast.h
+++ b/arch/arm/mach-s3c2410/bast.h
@@ -1,2 +1,2 @@
-
+/* linux/arch/arm/mach-s3c2410/bast.h
 extern void bast_init_irq(void);
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index e13fb67..5b4831c 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -1,15 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/clock.c
  *
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C24XX Core clock control support
- *
- * Based on, and code from linux/arch/arm/mach-versatile/clock.c
- **
- **  Copyright (C) 2004 ARM Limited.
- **  Written by Deep Blue Solutions Limited.
- *
+ * S3C2410,S3C2440,S3C2442 Clock control support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,418 +26,251 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
 #include <linux/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
 #include <linux/clk.h>
 #include <linux/mutex.h>
 #include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/map.h>
 
 #include <asm/hardware.h>
-#include <asm/irq.h>
 #include <asm/io.h>
 
+#include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-/* clock information */
-
-static LIST_HEAD(clocks);
-
-DEFINE_MUTEX(clocks_mutex);
-
-/* enable and disable calls for use with the clk struct */
-
-static int clk_null_enable(struct clk *clk, int enable)
+int s3c2410_clkcon_enable(struct clk *clk, int enable)
 {
-	return 0;
-}
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
 
-/* Clock API calls */
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *p;
-	struct clk *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, list) {
-		if (p->id == idno &&
-		    strcmp(id, p->name) == 0 &&
-		    try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-
-	/* check for the case where a device was supplied, but the
-	 * clock that was being searched for is not device specific */
-
-	if (IS_ERR(clk)) {
-		list_for_each_entry(p, &clocks, list) {
-			if (p->id == -1 && strcmp(id, p->name) == 0 &&
-			    try_module_get(p->owner)) {
-				clk = p;
-				break;
-			}
-		}
-	}
-
-	mutex_unlock(&clocks_mutex);
-	return clk;
-}
-
-void clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-int clk_enable(struct clk *clk)
-{
-	if (IS_ERR(clk) || clk == NULL)
-		return -EINVAL;
-
-	clk_enable(clk->parent);
-
-	mutex_lock(&clocks_mutex);
-
-	if ((clk->usage++) == 0)
-		(clk->enable)(clk, 1);
-
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-void clk_disable(struct clk *clk)
-{
-	if (IS_ERR(clk) || clk == NULL)
-		return;
-
-	mutex_lock(&clocks_mutex);
-
-	if ((--clk->usage) == 0)
-		(clk->enable)(clk, 0);
-
-	mutex_unlock(&clocks_mutex);
-	clk_disable(clk->parent);
-}
-
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	if (IS_ERR(clk))
-		return 0;
-
-	if (clk->rate != 0)
-		return clk->rate;
-
-	if (clk->get_rate != NULL)
-		return (clk->get_rate)(clk);
-
-	if (clk->parent != NULL)
-		return clk_get_rate(clk->parent);
-
-	return clk->rate;
-}
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	if (!IS_ERR(clk) && clk->round_rate)
-		return (clk->round_rate)(clk, rate);
-
-	return rate;
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	int ret;
-
-	if (IS_ERR(clk))
-		return -EINVAL;
-
-	mutex_lock(&clocks_mutex);
-	ret = (clk->set_rate)(clk, rate);
-	mutex_unlock(&clocks_mutex);
-
-	return ret;
-}
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-	return clk->parent;
-}
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	int ret = 0;
-
-	if (IS_ERR(clk))
-		return -EINVAL;
-
-	mutex_lock(&clocks_mutex);
-
-	if (clk->set_parent)
-		ret = (clk->set_parent)(clk, parent);
-
-	mutex_unlock(&clocks_mutex);
-
-	return ret;
-}
-
-EXPORT_SYMBOL(clk_get);
-EXPORT_SYMBOL(clk_put);
-EXPORT_SYMBOL(clk_enable);
-EXPORT_SYMBOL(clk_disable);
-EXPORT_SYMBOL(clk_get_rate);
-EXPORT_SYMBOL(clk_round_rate);
-EXPORT_SYMBOL(clk_set_rate);
-EXPORT_SYMBOL(clk_get_parent);
-EXPORT_SYMBOL(clk_set_parent);
-
-/* base clocks */
-
-struct clk clk_xtal = {
-	.name		= "xtal",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_mpll = {
-	.name		= "mpll",
-	.id		= -1,
-};
-
-struct clk clk_upll = {
-	.name		= "upll",
-	.id		= -1,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_f = {
-	.name		= "fclk",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= &clk_mpll,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_h = {
-	.name		= "hclk",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_p = {
-	.name		= "pclk",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_usb_bus = {
-	.name		= "usb-bus",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= &clk_upll,
-};
-
-/* clocks that could be registered by external code */
-
-static int s3c24xx_dclk_enable(struct clk *clk, int enable)
-{
-	unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
+	clkcon = __raw_readl(S3C2410_CLKCON);
 
 	if (enable)
-		dclkcon |= clk->ctrlbit;
+		clkcon |= clocks;
 	else
-		dclkcon &= ~clk->ctrlbit;
+		clkcon &= ~clocks;
 
-	__raw_writel(dclkcon, S3C24XX_DCLKCON);
+	/* ensure none of the special function bits set */
+	clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
+
+	__raw_writel(clkcon, S3C2410_CLKCON);
 
 	return 0;
 }
 
-static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
+static int s3c2410_upll_enable(struct clk *clk, int enable)
 {
-	unsigned long dclkcon;
-	unsigned int uclk;
+	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+	unsigned long orig = clkslow;
 
-	if (parent == &clk_upll)
-		uclk = 1;
-	else if (parent == &clk_p)
-		uclk = 0;
+	if (enable)
+		clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
 	else
-		return -EINVAL;
+		clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
 
-	clk->parent = parent;
+	__raw_writel(clkslow, S3C2410_CLKSLOW);
 
-	dclkcon = __raw_readl(S3C24XX_DCLKCON);
+	/* if we started the UPLL, then allow to settle */
 
-	if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
-		if (uclk)
-			dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
-		else
-			dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
-	} else {
-		if (uclk)
-			dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
-		else
-			dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
+	if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
+		udelay(200);
+
+	return 0;
+}
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_NAND,
+	}, {
+		.name		= "sdi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_SDI,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_ADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_IIC,
+	}, {
+		.name		= "iis",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_IIS,
+	}, {
+		.name		= "spi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_SPI,
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_LCDC,
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_GPIO,
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_USBH,
+	}, {
+		.name		= "usb-device",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_USBD,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_PWMT,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART2,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= 0,
+	}, {
+		.name		= "usb-bus-host",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+	}, {
+		.name		= "usb-bus-gadget",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+	},
+};
+
+/* s3c2410_baseclk_add()
+ *
+ * Add all the clocks used by the s3c2410 or compatible CPUs
+ * such as the S3C2440 and S3C2442.
+ *
+ * We cannot use a system device as we are needed before any
+ * of the init-calls that initialise the devices are actually
+ * done.
+*/
+
+int __init s3c2410_baseclk_add(void)
+{
+	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+	struct clk *clkp;
+	struct clk *xtal;
+	int ret;
+	int ptr;
+
+	clk_upll.enable = s3c2410_upll_enable;
+
+	if (s3c24xx_register_clock(&clk_usb_bus) < 0)
+		printk(KERN_ERR "failed to register usb bus clock\n");
+
+	/* register clocks from clock array */
+
+	clkp = init_clocks;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+		/* ensure that we note the clock state */
+
+		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
 	}
 
-	__raw_writel(dclkcon, S3C24XX_DCLKCON);
+	/* We must be careful disabling the clocks we are not intending to
+	 * be using at boot time, as subsytems such as the LCD which do
+	 * their own DMA requests to the bus can cause the system to lockup
+	 * if they where in the middle of requesting bus access.
+	 *
+	 * Disabling the LCD clock if the LCD is active is very dangerous,
+	 * and therefore the bootloader should be careful to not enable
+	 * the LCD clock if it is not needed.
+	*/
 
-	return 0;
-}
+	/* install (and disable) the clocks we do not need immediately */
 
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
 
-static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
-{
-	unsigned long mask;
-	unsigned long source;
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
 
-	/* calculate the MISCCR setting for the clock */
-
-	if (parent == &clk_xtal)
-		source = S3C2410_MISCCR_CLK0_MPLL;
-	else if (parent == &clk_upll)
-		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)
-		source = S3C2410_MISCCR_CLK0_DCLK0;
-	else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
-		source = S3C2410_MISCCR_CLK0_DCLK0;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	if (clk == &s3c24xx_dclk0)
-		mask = S3C2410_MISCCR_CLK0_MASK;
-	else {
-		source <<= 4;
-		mask = S3C2410_MISCCR_CLK1_MASK;
+		s3c2410_clkcon_enable(clkp, 0);
 	}
 
-	s3c2410_modify_misccr(mask, source);
-	return 0;
-}
+	/* show the clock-slow value */
 
-/* external clock definitions */
+	xtal = clk_get(NULL, "xtal");
 
-struct clk s3c24xx_dclk0 = {
-	.name		= "dclk0",
-	.id		= -1,
-	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
-	.enable	        = s3c24xx_dclk_enable,
-	.set_parent	= s3c24xx_dclk_setparent,
-};
-
-struct clk s3c24xx_dclk1 = {
-	.name		= "dclk1",
-	.id		= -1,
-	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
-	.enable		= s3c24xx_dclk_enable,
-	.set_parent	= s3c24xx_dclk_setparent,
-};
-
-struct clk s3c24xx_clkout0 = {
-	.name		= "clkout0",
-	.id		= -1,
-	.set_parent	= s3c24xx_clkout_setparent,
-};
-
-struct clk s3c24xx_clkout1 = {
-	.name		= "clkout1",
-	.id		= -1,
-	.set_parent	= s3c24xx_clkout_setparent,
-};
-
-struct clk s3c24xx_uclk = {
-	.name		= "uclk",
-	.id		= -1,
-};
-
-/* initialise the clock system */
-
-int s3c24xx_register_clock(struct clk *clk)
-{
-	clk->owner = THIS_MODULE;
-
-	if (clk->enable == NULL)
-		clk->enable = clk_null_enable;
-
-	/* add to the list of available clocks */
-
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->list, &clocks);
-	mutex_unlock(&clocks_mutex);
-
-	return 0;
-}
-
-/* initalise all the clocks */
-
-int __init s3c24xx_setup_clocks(unsigned long xtal,
-				unsigned long fclk,
-				unsigned long hclk,
-				unsigned long pclk)
-{
-	printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
-
-	/* initialise the main system clocks */
-
-	clk_xtal.rate = xtal;
-	clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
-
-	clk_mpll.rate = fclk;
-	clk_h.rate = hclk;
-	clk_p.rate = pclk;
-	clk_f.rate = fclk;
-
-	/* assume uart clocks are correctly setup */
-
-	/* register our clocks */
-
-	if (s3c24xx_register_clock(&clk_xtal) < 0)
-		printk(KERN_ERR "failed to register master xtal\n");
-
-	if (s3c24xx_register_clock(&clk_mpll) < 0)
-		printk(KERN_ERR "failed to register mpll clock\n");
-
-	if (s3c24xx_register_clock(&clk_upll) < 0)
-		printk(KERN_ERR "failed to register upll clock\n");
-
-	if (s3c24xx_register_clock(&clk_f) < 0)
-		printk(KERN_ERR "failed to register cpu fclk\n");
-
-	if (s3c24xx_register_clock(&clk_h) < 0)
-		printk(KERN_ERR "failed to register cpu hclk\n");
-
-	if (s3c24xx_register_clock(&clk_p) < 0)
-		printk(KERN_ERR "failed to register cpu pclk\n");
+	printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
+	       print_mhz(clk_get_rate(xtal) /
+			 ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
+	       (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
+	       (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
+	       (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
 
 	return 0;
 }
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
deleted file mode 100644
index 7f0ea03..0000000
--- a/arch/arm/mach-s3c2410/clock.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * linux/arch/arm/mach-s3c2410/clock.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	http://www.simtec.co.uk/products/SWLINUX/
- *	Written by Ben Dooks, <ben@simtec.co.uk>
- *
- * 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.
-*/
-
-struct clk {
-	struct list_head      list;
-	struct module        *owner;
-	struct clk           *parent;
-	const char           *name;
-	int		      id;
-	int		      usage;
-	unsigned long         rate;
-	unsigned long         ctrlbit;
-
-	int		    (*enable)(struct clk *, int enable);
-	int		    (*set_rate)(struct clk *c, unsigned long rate);
-	unsigned long	    (*get_rate)(struct clk *c);
-	unsigned long	    (*round_rate)(struct clk *c, unsigned long rate);
-	int		    (*set_parent)(struct clk *c, struct clk *parent);
-};
-
-/* other clocks which may be registered by board support */
-
-extern struct clk s3c24xx_dclk0;
-extern struct clk s3c24xx_dclk1;
-extern struct clk s3c24xx_clkout0;
-extern struct clk s3c24xx_clkout1;
-extern struct clk s3c24xx_uclk;
-
-extern struct clk clk_usb_bus;
-
-/* core clock support */
-
-extern struct clk clk_f;
-extern struct clk clk_h;
-extern struct clk clk_p;
-extern struct clk clk_mpll;
-extern struct clk clk_upll;
-extern struct clk clk_xtal;
-
-/* exports for arch/arm/mach-s3c2410
- *
- * Please DO NOT use these outside of arch/arm/mach-s3c2410
-*/
-
-extern struct mutex clocks_mutex;
-
-extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
-
-extern int s3c24xx_register_clock(struct clk *clk);
-
-extern int s3c24xx_setup_clocks(unsigned long xtal,
-				unsigned long fclk,
-				unsigned long hclk,
-				unsigned long pclk);
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/mach-s3c2410/common-smdk.c
deleted file mode 100644
index a40eaa6..0000000
--- a/arch/arm/mach-s3c2410/common-smdk.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/* 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/leds-gpio.h>
-
-#include <asm/arch/nand.h>
-
-#include "common-smdk.h"
-#include "devs.h"
-#include "pm.h"
-
-/* LED devices */
-
-static struct s3c24xx_led_platdata smdk_pdata_led4 = {
-	.gpio		= S3C2410_GPF4,
-	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
-	.name		= "led4",
-	.def_trigger	= "timer",
-};
-
-static struct s3c24xx_led_platdata smdk_pdata_led5 = {
-	.gpio		= S3C2410_GPF5,
-	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
-	.name		= "led5",
-	.def_trigger	= "nand-disk",
-};
-
-static struct s3c24xx_led_platdata smdk_pdata_led6 = {
-	.gpio		= S3C2410_GPF6,
-	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
-	.name		= "led6",
-};
-
-static struct s3c24xx_led_platdata smdk_pdata_led7 = {
-	.gpio		= S3C2410_GPF7,
-	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
-	.name		= "led7",
-};
-
-static struct platform_device smdk_led4 = {
-	.name		= "s3c24xx_led",
-	.id		= 0,
-	.dev		= {
-		.platform_data = &smdk_pdata_led4,
-	},
-};
-
-static struct platform_device smdk_led5 = {
-	.name		= "s3c24xx_led",
-	.id		= 1,
-	.dev		= {
-		.platform_data = &smdk_pdata_led5,
-	},
-};
-
-static struct platform_device smdk_led6 = {
-	.name		= "s3c24xx_led",
-	.id		= 2,
-	.dev		= {
-		.platform_data = &smdk_pdata_led6,
-	},
-};
-
-static struct platform_device smdk_led7 = {
-	.name		= "s3c24xx_led",
-	.id		= 3,
-	.dev		= {
-		.platform_data = &smdk_pdata_led7,
-	},
-};
-
-/* 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,
-	&smdk_led4,
-	&smdk_led5,
-	&smdk_led6,
-	&smdk_led7,
-};
-
-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
deleted file mode 100644
index 0e3a3be..0000000
--- a/arch/arm/mach-s3c2410/common-smdk.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* 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/cpu.c b/arch/arm/mach-s3c2410/cpu.c
deleted file mode 100644
index ae1f5bb..0000000
--- a/arch/arm/mach-s3c2410/cpu.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/cpu.c
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	http://www.simtec.co.uk/products/SWLINUX/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX CPU Support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/delay.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-serial.h>
-
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
-#include "s3c2400.h"
-#include "s3c2410.h"
-#include "s3c2412.h"
-#include "s3c244x.h"
-#include "s3c2440.h"
-#include "s3c2442.h"
-
-struct cpu_table {
-	unsigned long	idcode;
-	unsigned long	idmask;
-	void		(*map_io)(struct map_desc *mach_desc, int size);
-	void		(*init_uarts)(struct s3c2410_uartcfg *cfg, int no);
-	void		(*init_clocks)(int xtal);
-	int		(*init)(void);
-	const char	*name;
-};
-
-/* table of supported CPUs */
-
-static const char name_s3c2400[]  = "S3C2400";
-static const char name_s3c2410[]  = "S3C2410";
-static const char name_s3c2412[]  = "S3C2412";
-static const char name_s3c2440[]  = "S3C2440";
-static const char name_s3c2442[]  = "S3C2442";
-static const char name_s3c2410a[] = "S3C2410A";
-static const char name_s3c2440a[] = "S3C2440A";
-
-static struct cpu_table cpu_ids[] __initdata = {
-	{
-		.idcode		= 0x32410000,
-		.idmask		= 0xffffffff,
-		.map_io		= s3c2410_map_io,
-		.init_clocks	= s3c2410_init_clocks,
-		.init_uarts	= s3c2410_init_uarts,
-		.init		= s3c2410_init,
-		.name		= name_s3c2410
-	},
-	{
-		.idcode		= 0x32410002,
-		.idmask		= 0xffffffff,
-		.map_io		= s3c2410_map_io,
-		.init_clocks	= s3c2410_init_clocks,
-		.init_uarts	= s3c2410_init_uarts,
-		.init		= s3c2410_init,
-		.name		= name_s3c2410a
-	},
-	{
-		.idcode		= 0x32440000,
-		.idmask		= 0xffffffff,
-		.map_io		= s3c244x_map_io,
-		.init_clocks	= s3c244x_init_clocks,
-		.init_uarts	= s3c244x_init_uarts,
-		.init		= s3c2440_init,
-		.name		= name_s3c2440
-	},
-	{
-		.idcode		= 0x32440001,
-		.idmask		= 0xffffffff,
-		.map_io		= s3c244x_map_io,
-		.init_clocks	= s3c244x_init_clocks,
-		.init_uarts	= s3c244x_init_uarts,
-		.init		= s3c2440_init,
-		.name		= name_s3c2440a
-	},
-	{
-		.idcode		= 0x32440aaa,
-		.idmask		= 0xffffffff,
-		.map_io		= s3c244x_map_io,
-		.init_clocks	= s3c244x_init_clocks,
-		.init_uarts	= s3c244x_init_uarts,
-		.init		= s3c2442_init,
-		.name		= name_s3c2442
-	},
-	{
-		.idcode		= 0x32412001,
-		.idmask		= 0xffffffff,
-		.map_io		= s3c2412_map_io,
-		.init_clocks	= s3c2412_init_clocks,
-		.init_uarts	= s3c2412_init_uarts,
-		.init		= s3c2412_init,
-		.name		= name_s3c2412,
-	},
-	{			/* a newer version of the s3c2412 */
-		.idcode		= 0x32412003,
-		.idmask		= 0xffffffff,
-		.map_io		= s3c2412_map_io,
-		.init_clocks	= s3c2412_init_clocks,
-		.init_uarts	= s3c2412_init_uarts,
-		.init		= s3c2412_init,
-		.name		= name_s3c2412,
-	},
-	{
-		.idcode		= 0x0,   /* S3C2400 doesn't have an idcode */
-		.idmask		= 0xffffffff,
-		.map_io		= s3c2400_map_io,
-		.init_clocks	= s3c2400_init_clocks,
-		.init_uarts	= s3c2400_init_uarts,
-		.init		= s3c2400_init,
-		.name		= name_s3c2400
-	},
-};
-
-/* minimal IO mapping */
-
-static struct map_desc s3c_iodesc[] __initdata = {
-	IODESC_ENT(GPIO),
-	IODESC_ENT(IRQ),
-	IODESC_ENT(MEMCTRL),
-	IODESC_ENT(UART)
-};
-
-
-static struct cpu_table *
-s3c_lookup_cpu(unsigned long idcode)
-{
-	struct cpu_table *tab;
-	int count;
-
-	tab = cpu_ids;
-	for (count = 0; count < ARRAY_SIZE(cpu_ids); count++, tab++) {
-		if ((idcode & tab->idmask) == tab->idcode)
-			return tab;
-	}
-
-	return NULL;
-}
-
-/* board information */
-
-static struct s3c24xx_board *board;
-
-void s3c24xx_set_board(struct s3c24xx_board *b)
-{
-	int i;
-
-	board = b;
-
-	if (b->clocks_count != 0) {
-		struct clk **ptr = b->clocks;
-
-		for (i = b->clocks_count; i > 0; i--, ptr++)
-			s3c24xx_register_clock(*ptr);
-	}
-}
-
-/* cpu information */
-
-static struct cpu_table *cpu;
-
-static unsigned long s3c24xx_read_idcode_v5(void)
-{
-#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
-	return __raw_readl(S3C2412_GSTATUS1);
-#else
-	return 1UL;	/* don't look like an 2400 */
-#endif
-}
-
-static unsigned long s3c24xx_read_idcode_v4(void)
-{
-#ifndef CONFIG_CPU_S3C2400
-	return __raw_readl(S3C2410_GSTATUS1);
-#else
-	return 0UL;
-#endif
-}
-
-void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
-{
-	unsigned long idcode = 0x0;
-
-	/* initialise the io descriptors we need for initialisation */
-	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
-
-	if (cpu_architecture() >= CPU_ARCH_ARMv5) {
-		idcode = s3c24xx_read_idcode_v5();
-	} else {
-		idcode = s3c24xx_read_idcode_v4();
-	}
-
-	cpu = s3c_lookup_cpu(idcode);
-
-	if (cpu == NULL) {
-		printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode);
-		panic("Unknown S3C24XX CPU");
-	}
-
-	printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
-
-	if (cpu->map_io == NULL || cpu->init == NULL) {
-		printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
-		panic("Unsupported S3C24XX CPU");
-	}
-
-	(cpu->map_io)(mach_desc, size);
-}
-
-/* s3c24xx_init_clocks
- *
- * Initialise the clock subsystem and associated information from the
- * given master crystal value.
- *
- * xtal  = 0 -> use default PLL crystal value (normally 12MHz)
- *      != 0 -> PLL crystal value in Hz
-*/
-
-void __init s3c24xx_init_clocks(int xtal)
-{
-	if (xtal == 0)
-		xtal = 12*1000*1000;
-
-	if (cpu == NULL)
-		panic("s3c24xx_init_clocks: no cpu setup?\n");
-
-	if (cpu->init_clocks == NULL)
-		panic("s3c24xx_init_clocks: cpu has no clock init\n");
-	else
-		(cpu->init_clocks)(xtal);
-}
-
-/* uart management */
-
-static int nr_uarts __initdata = 0;
-
-static struct s3c2410_uartcfg uart_cfgs[3];
-
-/* s3c24xx_init_uartdevs
- *
- * copy the specified platform data and configuration into our central
- * set of devices, before the data is thrown away after the init process.
- *
- * This also fills in the array passed to the serial driver for the
- * early initialisation of the console.
-*/
-
-void __init s3c24xx_init_uartdevs(char *name,
-				  struct s3c24xx_uart_resources *res,
-				  struct s3c2410_uartcfg *cfg, int no)
-{
-	struct platform_device *platdev;
-	struct s3c2410_uartcfg *cfgptr = uart_cfgs;
-	struct s3c24xx_uart_resources *resp;
-	int uart;
-
-	memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);
-
-	for (uart = 0; uart < no; uart++, cfg++, cfgptr++) {
-		platdev = s3c24xx_uart_src[cfgptr->hwport];
-
-		resp = res + cfgptr->hwport;
-
-		s3c24xx_uart_devs[uart] = platdev;
-
-		platdev->name = name;
-		platdev->resource = resp->resources;
-		platdev->num_resources = resp->nr_resources;
-
-		platdev->dev.platform_data = cfgptr;
-	}
-
-	nr_uarts = no;
-}
-
-void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	if (cpu == NULL)
-		return;
-
-	if (cpu->init_uarts == NULL) {
-		printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n");
-	} else
-		(cpu->init_uarts)(cfg, no);
-}
-
-static int __init s3c_arch_init(void)
-{
-	int ret;
-
-	// do the correct init for cpu
-
-	if (cpu == NULL)
-		panic("s3c_arch_init: NULL cpu\n");
-
-	ret = (cpu->init)();
-	if (ret != 0)
-		return ret;
-
-	ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts);
-	if (ret != 0)
-		return ret;
-
-	if (board != NULL) {
-		struct platform_device **ptr = board->devices;
-		int i;
-
-		for (i = 0; i < board->devices_count; i++, ptr++) {
-			ret = platform_device_register(*ptr);
-
-			if (ret) {
-				printk(KERN_ERR "s3c24xx: failed to add board device %s (%d) @%p\n", (*ptr)->name, ret, *ptr);
-			}
-		}
-
-		/* mask any error, we may not need all these board
-		 * devices */
-		ret = 0;
-	}
-
-	return ret;
-}
-
-arch_initcall(s3c_arch_init);
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
deleted file mode 100644
index be42e40..0000000
--- a/arch/arm/mach-s3c2410/cpu.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* arch/arm/mach-s3c2410/cpu.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C24XX CPU support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* todo - fix when rmk changes iodescs to use `void __iomem *` */
-
-#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
-
-#ifndef MHZ
-#define MHZ (1000*1000)
-#endif
-
-#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
-
-/* forward declaration */
-struct s3c24xx_uart_resources;
-struct platform_device;
-struct s3c2410_uartcfg;
-struct map_desc;
-
-/* core initialisation functions */
-
-extern void s3c24xx_init_irq(void);
-
-extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
-
-extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c24xx_init_clocks(int xtal);
-
-extern void s3c24xx_init_uartdevs(char *name,
-				  struct s3c24xx_uart_resources *res,
-				  struct s3c2410_uartcfg *cfg, int no);
-
-/* the board structure is used at first initialsation time
- * to get info such as the devices to register for this
- * board. This is done because platfrom_add_devices() cannot
- * be called from the map_io entry.
-*/
-
-struct s3c24xx_board {
-	struct platform_device  **devices;
-	unsigned int              devices_count;
-
-	struct clk		**clocks;
-	unsigned int		  clocks_count;
-};
-
-extern void s3c24xx_set_board(struct s3c24xx_board *board);
-
-/* timer for 2410/2440 */
-
-struct sys_timer;
-extern struct sys_timer s3c24xx_timer;
-
-/* system device classes */
-
-extern struct sysdev_class s3c2410_sysclass;
-extern struct sysdev_class s3c2412_sysclass;
-extern struct sysdev_class s3c2440_sysclass;
-extern struct sysdev_class s3c2442_sysclass;
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
deleted file mode 100644
index faccde2..0000000
--- a/arch/arm/mach-s3c2410/devs.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/devs.c
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Base S3C24XX platform device definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#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/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/arch/fb.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/arch/regs-serial.h>
-
-#include "devs.h"
-#include "cpu.h"
-
-/* Serial port registrations */
-
-static struct resource s3c2410_uart0_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART0,
-		.end   = S3C2410_PA_UART0 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX0,
-		.end   = IRQ_S3CUART_ERR0,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c2410_uart1_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART1,
-		.end   = S3C2410_PA_UART1 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX1,
-		.end   = IRQ_S3CUART_ERR1,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c2410_uart2_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART2,
-		.end   = S3C2410_PA_UART2 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX2,
-		.end   = IRQ_S3CUART_ERR2,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
-	[0] = {
-		.resources	= s3c2410_uart0_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart0_resource),
-	},
-	[1] = {
-		.resources	= s3c2410_uart1_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart1_resource),
-	},
-	[2] = {
-		.resources	= s3c2410_uart2_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart2_resource),
-	},
-};
-
-/* yart devices */
-
-static struct platform_device s3c24xx_uart_device0 = {
-	.id		= 0,
-};
-
-static struct platform_device s3c24xx_uart_device1 = {
-	.id		= 1,
-};
-
-static struct platform_device s3c24xx_uart_device2 = {
-	.id		= 2,
-};
-
-struct platform_device *s3c24xx_uart_src[3] = {
-	&s3c24xx_uart_device0,
-	&s3c24xx_uart_device1,
-	&s3c24xx_uart_device2,
-};
-
-struct platform_device *s3c24xx_uart_devs[3] = {
-};
-
-/* USB Host Controller */
-
-static struct resource s3c_usb_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_USBHOST,
-		.end   = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_USBH,
-		.end   = IRQ_USBH,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_usb_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_usb = {
-	.name		  = "s3c2410-ohci",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_usb_resource),
-	.resource	  = s3c_usb_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_usb_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_usb);
-
-/* LCD Controller */
-
-static struct resource s3c_lcd_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_LCD,
-		.end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_LCD,
-		.end   = IRQ_LCD,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_lcd = {
-	.name		  = "s3c2410-lcd",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_lcd_resource),
-	.resource	  = s3c_lcd_resource,
-	.dev              = {
-		.dma_mask		= &s3c_device_lcd_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_lcd);
-
-void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
-{
-	struct s3c2410fb_mach_info *npd;
-
-	npd = kmalloc(sizeof(*npd), GFP_KERNEL);
-	if (npd) {
-		memcpy(npd, pd, sizeof(*npd));
-		s3c_device_lcd.dev.platform_data = npd;
-	} else {
-		printk(KERN_ERR "no memory for LCD platform data\n");
-	}
-}
-
-/* NAND Controller */
-
-static struct resource s3c_nand_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_NAND,
-		.end   = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1,
-		.flags = IORESOURCE_MEM,
-	}
-};
-
-struct platform_device s3c_device_nand = {
-	.name		  = "s3c2410-nand",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_nand_resource),
-	.resource	  = s3c_nand_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_nand);
-
-/* USB Device (Gadget)*/
-
-static struct resource s3c_usbgadget_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_USBDEV,
-		.end   = S3C24XX_PA_USBDEV + S3C24XX_SZ_USBDEV - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_USBD,
-		.end   = IRQ_USBD,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_usbgadget = {
-	.name		  = "s3c2410-usbgadget",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_usbgadget_resource),
-	.resource	  = s3c_usbgadget_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_usbgadget);
-
-/* Watchdog */
-
-static struct resource s3c_wdt_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_WATCHDOG,
-		.end   = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_WDT,
-		.end   = IRQ_WDT,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_wdt = {
-	.name		  = "s3c2410-wdt",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_wdt_resource),
-	.resource	  = s3c_wdt_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_wdt);
-
-/* I2C */
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_IIC,
-		.end   = S3C24XX_PA_IIC + S3C24XX_SZ_IIC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IIC,
-		.end   = IRQ_IIC,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_i2c = {
-	.name		  = "s3c2410-i2c",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
-	.resource	  = s3c_i2c_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_i2c);
-
-/* IIS */
-
-static struct resource s3c_iis_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_IIS,
-		.end   = S3C24XX_PA_IIS + S3C24XX_SZ_IIS -1,
-		.flags = IORESOURCE_MEM,
-	}
-};
-
-static u64 s3c_device_iis_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_iis = {
-	.name		  = "s3c2410-iis",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_iis_resource),
-	.resource	  = s3c_iis_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_iis_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_iis);
-
-/* RTC */
-
-static struct resource s3c_rtc_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_RTC,
-		.end   = S3C24XX_PA_RTC + 0xff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_RTC,
-		.end   = IRQ_RTC,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start = IRQ_TICK,
-		.end   = IRQ_TICK,
-		.flags = IORESOURCE_IRQ
-	}
-};
-
-struct platform_device s3c_device_rtc = {
-	.name		  = "s3c2410-rtc",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_rtc_resource),
-	.resource	  = s3c_rtc_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_rtc);
-
-/* ADC */
-
-static struct resource s3c_adc_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_ADC,
-		.end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TC,
-		.end   = IRQ_TC,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start = IRQ_ADC,
-		.end   = IRQ_ADC,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_adc = {
-	.name		  = "s3c2410-adc",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_adc_resource),
-	.resource	  = s3c_adc_resource,
-};
-
-/* SDI */
-
-static struct resource s3c_sdi_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_SDI,
-		.end   = S3C2410_PA_SDI + S3C24XX_SZ_SDI - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_SDI,
-		.end   = IRQ_SDI,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_sdi = {
-	.name		  = "s3c2410-sdi",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_sdi_resource),
-	.resource	  = s3c_sdi_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_sdi);
-
-/* SPI (0) */
-
-static struct resource s3c_spi0_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_SPI,
-		.end   = S3C24XX_PA_SPI + 0x1f,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_SPI0,
-		.end   = IRQ_SPI0,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_spi0_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_spi0 = {
-	.name		  = "s3c2410-spi",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s3c_spi0_resource),
-	.resource	  = s3c_spi0_resource,
-        .dev              = {
-                .dma_mask = &s3c_device_spi0_dmamask,
-                .coherent_dma_mask = 0xffffffffUL
-        }
-};
-
-EXPORT_SYMBOL(s3c_device_spi0);
-
-/* SPI (1) */
-
-static struct resource s3c_spi1_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_SPI + 0x20,
-		.end   = S3C24XX_PA_SPI + 0x20 + 0x1f,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_SPI1,
-		.end   = IRQ_SPI1,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_spi1_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_spi1 = {
-	.name		  = "s3c2410-spi",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c_spi1_resource),
-	.resource	  = s3c_spi1_resource,
-        .dev              = {
-                .dma_mask = &s3c_device_spi1_dmamask,
-                .coherent_dma_mask = 0xffffffffUL
-        }
-};
-
-EXPORT_SYMBOL(s3c_device_spi1);
-
-/* pwm timer blocks */
-
-static struct resource s3c_timer0_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_TIMER + 0x0C,
-		.end   = S3C24XX_PA_TIMER + 0x0C + 0xB,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TIMER0,
-		.end   = IRQ_TIMER0,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_timer0 = {
-	.name		  = "s3c2410-timer",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s3c_timer0_resource),
-	.resource	  = s3c_timer0_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_timer0);
-
-/* timer 1 */
-
-static struct resource s3c_timer1_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_TIMER + 0x18,
-		.end   = S3C24XX_PA_TIMER + 0x23,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TIMER1,
-		.end   = IRQ_TIMER1,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_timer1 = {
-	.name		  = "s3c2410-timer",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c_timer1_resource),
-	.resource	  = s3c_timer1_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_timer1);
-
-/* timer 2 */
-
-static struct resource s3c_timer2_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_TIMER + 0x24,
-		.end   = S3C24XX_PA_TIMER + 0x2F,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TIMER2,
-		.end   = IRQ_TIMER2,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_timer2 = {
-	.name		  = "s3c2410-timer",
-	.id		  = 2,
-	.num_resources	  = ARRAY_SIZE(s3c_timer2_resource),
-	.resource	  = s3c_timer2_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_timer2);
-
-/* timer 3 */
-
-static struct resource s3c_timer3_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_TIMER + 0x30,
-		.end   = S3C24XX_PA_TIMER + 0x3B,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TIMER3,
-		.end   = IRQ_TIMER3,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_timer3 = {
-	.name		  = "s3c2410-timer",
-	.id		  = 3,
-	.num_resources	  = ARRAY_SIZE(s3c_timer3_resource),
-	.resource	  = s3c_timer3_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_timer3);
-
-#ifdef CONFIG_CPU_S3C2440
-
-/* Camif Controller */
-
-static struct resource s3c_camif_resource[] = {
-	[0] = {
-		.start = S3C2440_PA_CAMIF,
-		.end   = S3C2440_PA_CAMIF + S3C2440_SZ_CAMIF - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_CAM,
-		.end   = IRQ_CAM,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_camif_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_camif = {
-	.name		  = "s3c2440-camif",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_camif_resource),
-	.resource	  = s3c_camif_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_camif_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_camif);
-
-#endif // CONFIG_CPU_S32440
diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
deleted file mode 100644
index 14fb0ba..0000000
--- a/arch/arm/mach-s3c2410/devs.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* arch/arm/mach-s3c2410/devs.h
- *
- * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2410 standard platform devices
- *
- * 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/platform_device.h>
-
-struct s3c24xx_uart_resources {
-	struct resource		*resources;
-	unsigned long		 nr_resources;
-};
-
-extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
-
-extern struct platform_device *s3c24xx_uart_devs[];
-extern struct platform_device *s3c24xx_uart_src[];
-
-extern struct platform_device s3c_device_usb;
-extern struct platform_device s3c_device_lcd;
-extern struct platform_device s3c_device_wdt;
-extern struct platform_device s3c_device_i2c;
-extern struct platform_device s3c_device_iis;
-extern struct platform_device s3c_device_rtc;
-extern struct platform_device s3c_device_adc;
-extern struct platform_device s3c_device_sdi;
-
-extern struct platform_device s3c_device_spi0;
-extern struct platform_device s3c_device_spi1;
-
-extern struct platform_device s3c_device_nand;
-
-extern struct platform_device s3c_device_timer0;
-extern struct platform_device s3c_device_timer1;
-extern struct platform_device s3c_device_timer2;
-extern struct platform_device s3c_device_timer3;
-
-extern struct platform_device s3c_device_usbgadget;
-
-/* s3c2440 specific devices */
-
-#ifdef CONFIG_CPU_S3C2440
-
-extern struct platform_device s3c_device_camif;
-
-#endif
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index fa860e7..67d1ad3 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -1,9 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/dma.c
  *
- * Copyright (c) 2003-2005,2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C2410 DMA core
+ * S3C2410 DMA selection
  *
  * http://armlinux.simtec.co.uk/
  *
@@ -12,1430 +12,170 @@
  * published by the Free Software Foundation.
 */
 
-
-#ifdef CONFIG_S3C2410_DMA_DEBUG
-#define DEBUG
-#endif
-
-#include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
 #include <linux/sysdev.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
+#include <linux/serial_core.h>
 
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
 #include <asm/dma.h>
+#include <asm/arch/dma.h>
 
-#include <asm/mach/dma.h>
-#include <asm/arch/map.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/dma.h>
 
-#include "dma.h"
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
 
-/* io map for dma */
-static void __iomem *dma_base;
-static struct kmem_cache *dma_kmem;
-
-struct s3c24xx_dma_selection dma_sel;
-
-/* dma channel state information */
-struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
-
-/* debugging functions */
-
-#define BUF_MAGIC (0xcafebabe)
-
-#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
-
-#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
-
-#if 1
-#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
-#else
-static inline void
-dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
-{
-	pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
-	writel(val, dma_regaddr(chan, reg));
-}
-#endif
-
-#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
-
-/* captured register state for debug */
-
-struct s3c2410_dma_regstate {
-	unsigned long         dcsrc;
-	unsigned long         disrc;
-	unsigned long         dstat;
-	unsigned long         dcon;
-	unsigned long         dmsktrig;
+static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
+	[DMACH_XD0] = {
+		.name		= "xdreq0",
+		.channels[0]	= S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
+	},
+	[DMACH_XD1] = {
+		.name		= "xdreq1",
+		.channels[1]	= S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
+	},
+	[DMACH_SDI] = {
+		.name		= "sdi",
+		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
+		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_SPI0] = {
+		.name		= "spi0",
+		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
+	},
+	[DMACH_SPI1] = {
+		.name		= "spi1",
+		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+	},
+	[DMACH_UART0] = {
+		.name		= "uart0",
+		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1] = {
+		.name		= "uart1",
+		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2] = {
+		.name		= "uart2",
+		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+	[DMACH_TIMER] = {
+		.name		= "timer",
+		.channels[0]	= S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
+		.channels[3]	= S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
+	},
+	[DMACH_I2S_IN] = {
+		.name		= "i2s-sdi",
+		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_I2S_OUT] = {
+		.name		= "i2s-sdo",
+		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_USB_EP1] = {
+		.name		= "usb-ep1",
+		.channels[0]	= S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP2] = {
+		.name		= "usb-ep2",
+		.channels[1]	= S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP3] = {
+		.name		= "usb-ep3",
+		.channels[2]	= S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP4] = {
+		.name		= "usb-ep4",
+		.channels[3]	=S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
+	},
 };
 
-#ifdef CONFIG_S3C2410_DMA_DEBUG
-
-/* dmadbg_showregs
- *
- * simple debug routine to print the current state of the dma registers
-*/
-
-static void
-dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
+static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
+			       struct s3c24xx_dma_map *map)
 {
-	regs->dcsrc    = dma_rdreg(chan, S3C2410_DMA_DCSRC);
-	regs->disrc    = dma_rdreg(chan, S3C2410_DMA_DISRC);
-	regs->dstat    = dma_rdreg(chan, S3C2410_DMA_DSTAT);
-	regs->dcon     = dma_rdreg(chan, S3C2410_DMA_DCON);
-	regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+	chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
 }
 
-static void
-dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
-		 struct s3c2410_dma_regstate *regs)
-{
-	printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
-	       chan->number, fname, line,
-	       regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
-	       regs->dcon);
-}
-
-static void
-dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
-{
-	struct s3c2410_dma_regstate state;
-
-	dmadbg_capture(chan, &state);
-
-	printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
-	       chan->number, fname, line, chan->load_state,
-	       chan->curr, chan->next, chan->end);
-
-	dmadbg_dumpregs(fname, line, chan, &state);
-}
-
-static void
-dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
-{
-	struct s3c2410_dma_regstate state;
-
-	dmadbg_capture(chan, &state);
-	dmadbg_dumpregs(fname, line, chan, &state);
-}
-
-#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
-#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
-#else
-#define dbg_showregs(chan) do { } while(0)
-#define dbg_showchan(chan) do { } while(0)
-#endif /* CONFIG_S3C2410_DMA_DEBUG */
-
-static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
-
-/* lookup_dma_channel
- *
- * change the dma channel number given into a real dma channel id
-*/
-
-static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
-{
-	if (channel & DMACH_LOW_LEVEL)
-		return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
-	else
-		return dma_chan_map[channel];
-}
-
-/* s3c2410_dma_stats_timeout
- *
- * Update DMA stats from timeout info
-*/
-
-static void
-s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
-{
-	if (stats == NULL)
-		return;
-
-	if (val > stats->timeout_longest)
-		stats->timeout_longest = val;
-	if (val < stats->timeout_shortest)
-		stats->timeout_shortest = val;
-
-	stats->timeout_avg += val;
-}
-
-/* s3c2410_dma_waitforload
- *
- * wait for the DMA engine to load a buffer, and update the state accordingly
-*/
-
-static int
-s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
-{
-	int timeout = chan->load_timeout;
-	int took;
-
-	if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
-		printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
-		return 0;
-	}
-
-	if (chan->stats != NULL)
-		chan->stats->loads++;
-
-	while (--timeout > 0) {
-		if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
-			took = chan->load_timeout - timeout;
-
-			s3c2410_dma_stats_timeout(chan->stats, took);
-
-			switch (chan->load_state) {
-			case S3C2410_DMALOAD_1LOADED:
-				chan->load_state = S3C2410_DMALOAD_1RUNNING;
-				break;
-
-			default:
-				printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
-			}
-
-			return 1;
-		}
-	}
-
-	if (chan->stats != NULL) {
-		chan->stats->timeout_failed++;
-	}
-
-	return 0;
-}
-
-
-
-/* s3c2410_dma_loadbuffer
- *
- * load a buffer, and update the channel state
-*/
-
-static inline int
-s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
-		       struct s3c2410_dma_buf *buf)
-{
-	unsigned long reload;
-
-	pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
-		 buf, (unsigned long)buf->data, buf->size);
-
-	if (buf == NULL) {
-		dmawarn("buffer is NULL\n");
-		return -EINVAL;
-	}
-
-	/* check the state of the channel before we do anything */
-
-	if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-		dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
-	}
-
-	if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
-		dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
-	}
-
-	/* it would seem sensible if we are the last buffer to not bother
-	 * with the auto-reload bit, so that the DMA engine will not try
-	 * and load another transfer after this one has finished...
-	 */
-	if (chan->load_state == S3C2410_DMALOAD_NONE) {
-		pr_debug("load_state is none, checking for noreload (next=%p)\n",
-			 buf->next);
-		reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
-	} else {
-		//pr_debug("load_state is %d => autoreload\n", chan->load_state);
-		reload = S3C2410_DCON_AUTORELOAD;
-	}
-
-	if ((buf->data & 0xf0000000) != 0x30000000) {
-		dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
-	}
-
-	writel(buf->data, chan->addr_reg);
-
-	dma_wrreg(chan, S3C2410_DMA_DCON,
-		  chan->dcon | reload | (buf->size/chan->xfer_unit));
-
-	chan->next = buf->next;
-
-	/* update the state of the channel */
-
-	switch (chan->load_state) {
-	case S3C2410_DMALOAD_NONE:
-		chan->load_state = S3C2410_DMALOAD_1LOADED;
-		break;
-
-	case S3C2410_DMALOAD_1RUNNING:
-		chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
-		break;
-
-	default:
-		dmawarn("dmaload: unknown state %d in loadbuffer\n",
-			chan->load_state);
-		break;
-	}
-
-	return 0;
-}
-
-/* s3c2410_dma_call_op
- *
- * small routine to call the op routine with the given op if it has been
- * registered
-*/
-
-static void
-s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
-{
-	if (chan->op_fn != NULL) {
-		(chan->op_fn)(chan, op);
-	}
-}
-
-/* s3c2410_dma_buffdone
- *
- * small wrapper to check if callback routine needs to be called, and
- * if so, call it
-*/
-
-static inline void
-s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
-		     enum s3c2410_dma_buffresult result)
-{
-#if 0
-	pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
-		 chan->callback_fn, buf, buf->id, buf->size, result);
-#endif
-
-	if (chan->callback_fn != NULL) {
-		(chan->callback_fn)(chan, buf->id, buf->size, result);
-	}
-}
-
-/* s3c2410_dma_start
- *
- * start a dma channel going
-*/
-
-static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
-{
-	unsigned long tmp;
-	unsigned long flags;
-
-	pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
-
-	local_irq_save(flags);
-
-	if (chan->state == S3C2410_DMA_RUNNING) {
-		pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
-		local_irq_restore(flags);
-		return 0;
-	}
-
-	chan->state = S3C2410_DMA_RUNNING;
-
-	/* check wether there is anything to load, and if not, see
-	 * if we can find anything to load
-	 */
-
-	if (chan->load_state == S3C2410_DMALOAD_NONE) {
-		if (chan->next == NULL) {
-			printk(KERN_ERR "dma%d: channel has nothing loaded\n",
-			       chan->number);
-			chan->state = S3C2410_DMA_IDLE;
-			local_irq_restore(flags);
-			return -EINVAL;
-		}
-
-		s3c2410_dma_loadbuffer(chan, chan->next);
-	}
-
-	dbg_showchan(chan);
-
-	/* enable the channel */
-
-	if (!chan->irq_enabled) {
-		enable_irq(chan->irq);
-		chan->irq_enabled = 1;
-	}
-
-	/* start the channel going */
-
-	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-	tmp &= ~S3C2410_DMASKTRIG_STOP;
-	tmp |= S3C2410_DMASKTRIG_ON;
-	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
-
-	pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
-
-#if 0
-	/* the dma buffer loads should take care of clearing the AUTO
-	 * reloading feature */
-	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
-	tmp &= ~S3C2410_DCON_NORELOAD;
-	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-#endif
-
-	s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
-
-	dbg_showchan(chan);
-
-	/* if we've only loaded one buffer onto the channel, then chec
-	 * to see if we have another, and if so, try and load it so when
-	 * the first buffer is finished, the new one will be loaded onto
-	 * the channel */
-
-	if (chan->next != NULL) {
-		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-
-			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-				pr_debug("%s: buff not yet loaded, no more todo\n",
-					 __FUNCTION__);
-			} else {
-				chan->load_state = S3C2410_DMALOAD_1RUNNING;
-				s3c2410_dma_loadbuffer(chan, chan->next);
-			}
-
-		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
-			s3c2410_dma_loadbuffer(chan, chan->next);
-		}
-	}
-
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-/* s3c2410_dma_canload
- *
- * work out if we can queue another buffer into the DMA engine
-*/
-
-static int
-s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
-{
-	if (chan->load_state == S3C2410_DMALOAD_NONE ||
-	    chan->load_state == S3C2410_DMALOAD_1RUNNING)
-		return 1;
-
-	return 0;
-}
-
-/* s3c2410_dma_enqueue
- *
- * queue an given buffer for dma transfer.
- *
- * id         the device driver's id information for this buffer
- * data       the physical address of the buffer data
- * size       the size of the buffer in bytes
- *
- * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
- * is checked, and if set, the channel is started. If this flag isn't set,
- * then an error will be returned.
- *
- * It is possible to queue more than one DMA buffer onto a channel at
- * once, and the code will deal with the re-loading of the next buffer
- * when necessary.
-*/
-
-int s3c2410_dma_enqueue(unsigned int channel, void *id,
-			dma_addr_t data, int size)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-	struct s3c2410_dma_buf *buf;
-	unsigned long flags;
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: id=%p, data=%08x, size=%d\n",
-		 __FUNCTION__, id, (unsigned int)data, size);
-
-	buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
-	if (buf == NULL) {
-		pr_debug("%s: out of memory (%ld alloc)\n",
-			 __FUNCTION__, (long)sizeof(*buf));
-		return -ENOMEM;
-	}
-
-	//pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
-	//dbg_showchan(chan);
-
-	buf->next  = NULL;
-	buf->data  = buf->ptr = data;
-	buf->size  = size;
-	buf->id    = id;
-	buf->magic = BUF_MAGIC;
-
-	local_irq_save(flags);
-
-	if (chan->curr == NULL) {
-		/* we've got nothing loaded... */
-		pr_debug("%s: buffer %p queued onto empty channel\n",
-			 __FUNCTION__, buf);
-
-		chan->curr = buf;
-		chan->end  = buf;
-		chan->next = NULL;
-	} else {
-		pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
-			 chan->number, __FUNCTION__, buf);
-
-		if (chan->end == NULL)
-			pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
-				 chan->number, __FUNCTION__, chan);
-
-		chan->end->next = buf;
-		chan->end = buf;
-	}
-
-	/* if necessary, update the next buffer field */
-	if (chan->next == NULL)
-		chan->next = buf;
-
-	/* check to see if we can load a buffer */
-	if (chan->state == S3C2410_DMA_RUNNING) {
-		if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
-			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-				printk(KERN_ERR "dma%d: loadbuffer:"
-				       "timeout loading buffer\n",
-				       chan->number);
-				dbg_showchan(chan);
-				local_irq_restore(flags);
-				return -EINVAL;
-			}
-		}
-
-		while (s3c2410_dma_canload(chan) && chan->next != NULL) {
-			s3c2410_dma_loadbuffer(chan, chan->next);
-		}
-	} else if (chan->state == S3C2410_DMA_IDLE) {
-		if (chan->flags & S3C2410_DMAF_AUTOSTART) {
-			s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
-		}
-	}
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-static inline void
-s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
-{
-	int magicok = (buf->magic == BUF_MAGIC);
-
-	buf->magic = -1;
-
-	if (magicok) {
-		kmem_cache_free(dma_kmem, buf);
-	} else {
-		printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
-	}
-}
-
-/* s3c2410_dma_lastxfer
- *
- * called when the system is out of buffers, to ensure that the channel
- * is prepared for shutdown.
-*/
-
-static inline void
-s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
-{
-#if 0
-	pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
-		 chan->number, chan->load_state);
-#endif
-
-	switch (chan->load_state) {
-	case S3C2410_DMALOAD_NONE:
-		break;
-
-	case S3C2410_DMALOAD_1LOADED:
-		if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-				/* flag error? */
-			printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
-			       chan->number, __FUNCTION__);
-			return;
-		}
-		break;
-
-	case S3C2410_DMALOAD_1LOADED_1RUNNING:
-		/* I belive in this case we do not have anything to do
-		 * until the next buffer comes along, and we turn off the
-		 * reload */
-		return;
-
-	default:
-		pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
-			 chan->number, chan->load_state);
-		return;
-
-	}
-
-	/* hopefully this'll shut the damned thing up after the transfer... */
-	dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
-}
-
-
-#define dmadbg2(x...)
-
-static irqreturn_t
-s3c2410_dma_irq(int irq, void *devpw)
-{
-	struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
-	struct s3c2410_dma_buf  *buf;
-
-	buf = chan->curr;
-
-	dbg_showchan(chan);
-
-	/* modify the channel state */
-
-	switch (chan->load_state) {
-	case S3C2410_DMALOAD_1RUNNING:
-		/* TODO - if we are running only one buffer, we probably
-		 * want to reload here, and then worry about the buffer
-		 * callback */
-
-		chan->load_state = S3C2410_DMALOAD_NONE;
-		break;
-
-	case S3C2410_DMALOAD_1LOADED:
-		/* iirc, we should go back to NONE loaded here, we
-		 * had a buffer, and it was never verified as being
-		 * loaded.
-		 */
-
-		chan->load_state = S3C2410_DMALOAD_NONE;
-		break;
-
-	case S3C2410_DMALOAD_1LOADED_1RUNNING:
-		/* we'll worry about checking to see if another buffer is
-		 * ready after we've called back the owner. This should
-		 * ensure we do not wait around too long for the DMA
-		 * engine to start the next transfer
-		 */
-
-		chan->load_state = S3C2410_DMALOAD_1LOADED;
-		break;
-
-	case S3C2410_DMALOAD_NONE:
-		printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
-		       chan->number);
-		break;
-
-	default:
-		printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
-		       chan->number, chan->load_state);
-		break;
-	}
-
-	if (buf != NULL) {
-		/* update the chain to make sure that if we load any more
-		 * buffers when we call the callback function, things should
-		 * work properly */
-
-		chan->curr = buf->next;
-		buf->next  = NULL;
-
-		if (buf->magic != BUF_MAGIC) {
-			printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
-			       chan->number, __FUNCTION__, buf);
-			return IRQ_HANDLED;
-		}
-
-		s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
-
-		/* free resouces */
-		s3c2410_dma_freebuf(buf);
-	} else {
-	}
-
-	/* only reload if the channel is still running... our buffer done
-	 * routine may have altered the state by requesting the dma channel
-	 * to stop or shutdown... */
-
-	/* todo: check that when the channel is shut-down from inside this
-	 * function, we cope with unsetting reload, etc */
-
-	if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
-		unsigned long flags;
-
-		switch (chan->load_state) {
-		case S3C2410_DMALOAD_1RUNNING:
-			/* don't need to do anything for this state */
-			break;
-
-		case S3C2410_DMALOAD_NONE:
-			/* can load buffer immediately */
-			break;
-
-		case S3C2410_DMALOAD_1LOADED:
-			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-				/* flag error? */
-				printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
-				       chan->number, __FUNCTION__);
-				return IRQ_HANDLED;
-			}
-
-			break;
-
-		case S3C2410_DMALOAD_1LOADED_1RUNNING:
-			goto no_load;
-
-		default:
-			printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
-			       chan->number, chan->load_state);
-			return IRQ_HANDLED;
-		}
-
-		local_irq_save(flags);
-		s3c2410_dma_loadbuffer(chan, chan->next);
-		local_irq_restore(flags);
-	} else {
-		s3c2410_dma_lastxfer(chan);
-
-		/* see if we can stop this channel.. */
-		if (chan->load_state == S3C2410_DMALOAD_NONE) {
-			pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
-				 chan->number, jiffies);
-			s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
-					 S3C2410_DMAOP_STOP);
-		}
-	}
-
- no_load:
-	return IRQ_HANDLED;
-}
-
-static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
-
-/* s3c2410_request_dma
- *
- * get control of an dma channel
-*/
-
-int s3c2410_dma_request(unsigned int channel,
-			struct s3c2410_dma_client *client,
-			void *dev)
-{
-	struct s3c2410_dma_chan *chan;
-	unsigned long flags;
-	int err;
-
-	pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
-		 channel, client->name, dev);
-
-	local_irq_save(flags);
-
-	chan = s3c2410_dma_map_channel(channel);
-	if (chan == NULL) {
-		local_irq_restore(flags);
-		return -EBUSY;
-	}
-
-	dbg_showchan(chan);
-
-	chan->client = client;
-	chan->in_use = 1;
-
-	if (!chan->irq_claimed) {
-		pr_debug("dma%d: %s : requesting irq %d\n",
-			 channel, __FUNCTION__, chan->irq);
-
-		chan->irq_claimed = 1;
-		local_irq_restore(flags);
-
-		err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
-				  client->name, (void *)chan);
-
-		local_irq_save(flags);
-
-		if (err) {
-			chan->in_use = 0;
-			chan->irq_claimed = 0;
-			local_irq_restore(flags);
-
-			printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
-			       client->name, chan->irq, chan->number);
-			return err;
-		}
-
-		chan->irq_enabled = 1;
-	}
-
-	local_irq_restore(flags);
-
-	/* need to setup */
-
-	pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-/* s3c2410_dma_free
- *
- * release the given channel back to the system, will stop and flush
- * any outstanding transfers, and ensure the channel is ready for the
- * next claimant.
- *
- * Note, although a warning is currently printed if the freeing client
- * info is not the same as the registrant's client info, the free is still
- * allowed to go through.
-*/
-
-int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-	unsigned long flags;
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	local_irq_save(flags);
-
-	if (chan->client != client) {
-		printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
-		       channel, chan->client, client);
-	}
-
-	/* sort out stopping and freeing the channel */
-
-	if (chan->state != S3C2410_DMA_IDLE) {
-		pr_debug("%s: need to stop dma channel %p\n",
-		       __FUNCTION__, chan);
-
-		/* possibly flush the channel */
-		s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
-	}
-
-	chan->client = NULL;
-	chan->in_use = 0;
-
-	if (chan->irq_claimed)
-		free_irq(chan->irq, (void *)chan);
-
-	chan->irq_claimed = 0;
-
-	if (!(channel & DMACH_LOW_LEVEL))
-		dma_chan_map[channel] = NULL;
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
-{
-	unsigned long flags;
-	unsigned long tmp;
-
-	pr_debug("%s:\n", __FUNCTION__);
-
-	dbg_showchan(chan);
-
-	local_irq_save(flags);
-
-	s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);
-
-	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-	tmp |= S3C2410_DMASKTRIG_STOP;
-	//tmp &= ~S3C2410_DMASKTRIG_ON;
-	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
-
-#if 0
-	/* should also clear interrupts, according to WinCE BSP */
-	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
-	tmp |= S3C2410_DCON_NORELOAD;
-	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-#endif
-
-	/* should stop do this, or should we wait for flush? */
-	chan->state      = S3C2410_DMA_IDLE;
-	chan->load_state = S3C2410_DMALOAD_NONE;
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
-{
-	unsigned long tmp;
-	unsigned int timeout = 0x10000;
-
-	while (timeout-- > 0) {
-		tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-
-		if (!(tmp & S3C2410_DMASKTRIG_ON))
-			return;
-	}
-
-	pr_debug("dma%d: failed to stop?\n", chan->number);
-}
-
-
-/* s3c2410_dma_flush
- *
- * stop the channel, and remove all current and pending transfers
-*/
-
-static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
-{
-	struct s3c2410_dma_buf *buf, *next;
-	unsigned long flags;
-
-	pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
-
-	dbg_showchan(chan);
-
-	local_irq_save(flags);
-
-	if (chan->state != S3C2410_DMA_IDLE) {
-		pr_debug("%s: stopping channel...\n", __FUNCTION__ );
-		s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
-	}
-
-	buf = chan->curr;
-	if (buf == NULL)
-		buf = chan->next;
-
-	chan->curr = chan->next = chan->end = NULL;
-
-	if (buf != NULL) {
-		for ( ; buf != NULL; buf = next) {
-			next = buf->next;
-
-			pr_debug("%s: free buffer %p, next %p\n",
-			       __FUNCTION__, buf, buf->next);
-
-			s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
-			s3c2410_dma_freebuf(buf);
-		}
-	}
-
-	dbg_showregs(chan);
-
-	s3c2410_dma_waitforstop(chan);
-
-#if 0
-	/* should also clear interrupts, according to WinCE BSP */
-	{
-		unsigned long tmp;
-
-		tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
-		tmp |= S3C2410_DCON_NORELOAD;
-		dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-	}
-#endif
-
-	dbg_showregs(chan);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-int
-s3c2410_dma_started(struct s3c2410_dma_chan *chan)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	dbg_showchan(chan);
-
-	/* if we've only loaded one buffer onto the channel, then chec
-	 * to see if we have another, and if so, try and load it so when
-	 * the first buffer is finished, the new one will be loaded onto
-	 * the channel */
-
-	if (chan->next != NULL) {
-		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-
-			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-				pr_debug("%s: buff not yet loaded, no more todo\n",
-					 __FUNCTION__);
-			} else {
-				chan->load_state = S3C2410_DMALOAD_1RUNNING;
-				s3c2410_dma_loadbuffer(chan, chan->next);
-			}
-
-		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
-			s3c2410_dma_loadbuffer(chan, chan->next);
-		}
-	}
-
-
-	local_irq_restore(flags);
-
-	return 0;
-
-}
-
-int
-s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	switch (op) {
-	case S3C2410_DMAOP_START:
-		return s3c2410_dma_start(chan);
-
-	case S3C2410_DMAOP_STOP:
-		return s3c2410_dma_dostop(chan);
-
-	case S3C2410_DMAOP_PAUSE:
-	case S3C2410_DMAOP_RESUME:
-		return -ENOENT;
-
-	case S3C2410_DMAOP_FLUSH:
-		return s3c2410_dma_flush(chan);
-
-	case S3C2410_DMAOP_STARTED:
-		return s3c2410_dma_started(chan);
-
-	case S3C2410_DMAOP_TIMEOUT:
-		return 0;
-
-	}
-
-	return -ENOENT;      /* unknown, don't bother */
-}
-
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-/* DMA configuration for each channel
- *
- * DISRCC -> source of the DMA (AHB,APB)
- * DISRC  -> source address of the DMA
- * DIDSTC -> destination of the DMA (AHB,APD)
- * DIDST  -> destination address of the DMA
-*/
-
-/* s3c2410_dma_config
- *
- * xfersize:     size of unit in bytes (1,2,4)
- * dcon:         base value of the DCONx register
-*/
-
-int s3c2410_dma_config(dmach_t channel,
-		       int xferunit,
-		       int dcon)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
-		 __FUNCTION__, channel, xferunit, dcon);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
-
-	dcon |= chan->dcon & dma_sel.dcon_mask;
-
-	pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
-
-	switch (xferunit) {
-	case 1:
-		dcon |= S3C2410_DCON_BYTE;
-		break;
-
-	case 2:
-		dcon |= S3C2410_DCON_HALFWORD;
-		break;
-
-	case 4:
-		dcon |= S3C2410_DCON_WORD;
-		break;
-
-	default:
-		pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
-		return -EINVAL;
-	}
-
-	dcon |= S3C2410_DCON_HWTRIG;
-	dcon |= S3C2410_DCON_INTREQ;
-
-	pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
-
-	chan->dcon = dcon;
-	chan->xfer_unit = xferunit;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
-
-	chan->flags = flags;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-
-/* do we need to protect the settings of the fields from
- * irq?
-*/
-
-int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
-
-	chan->op_fn = rtn;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_set_opfn);
-
-int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
-
-	chan->callback_fn = rtn;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-/* s3c2410_dma_devconfig
- *
- * configure the dma source/destination hardware type and address
- *
- * source:    S3C2410_DMASRC_HW: source is hardware
- *            S3C2410_DMASRC_MEM: source is memory
- *
- * hwcfg:     the value for xxxSTCn register,
- *            bit 0: 0=increment pointer, 1=leave pointer
- *            bit 1: 0=soucre is AHB, 1=soucre is APB
- *
- * devaddr:   physical address of the source
-*/
-
-int s3c2410_dma_devconfig(int channel,
-			  enum s3c2410_dmasrc source,
-			  int hwcfg,
-			  unsigned long devaddr)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
-		 __FUNCTION__, (int)source, hwcfg, devaddr);
-
-	chan->source = source;
-	chan->dev_addr = devaddr;
-
-	switch (source) {
-	case S3C2410_DMASRC_HW:
-		/* source is hardware */
-		pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
-			 __FUNCTION__, devaddr, hwcfg);
-		dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
-		dma_wrreg(chan, S3C2410_DMA_DISRC,  devaddr);
-		dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
-
-		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
-		return 0;
-
-	case S3C2410_DMASRC_MEM:
-		/* source is memory */
-		pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
-			  __FUNCTION__, devaddr, hwcfg);
-		dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
-		dma_wrreg(chan, S3C2410_DMA_DIDST,  devaddr);
-		dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
-
-		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
-		return 0;
-	}
-
-	printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
-	return -EINVAL;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-/* s3c2410_dma_getposition
- *
- * returns the current transfer points for the dma source and destination
-*/
-
-int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
-{
- 	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	if (src != NULL)
- 		*src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
-
- 	if (dst != NULL)
- 		*dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
-
- 	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-
-/* system device class */
-
-#ifdef CONFIG_PM
-
-static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
-{
-	struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
-
-	printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
-
-	if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
-		/* the dma channel is still working, which is probably
-		 * a bad thing to do over suspend/resume. We stop the
-		 * channel and assume that the client is either going to
-		 * retry after resume, or that it is broken.
-		 */
-
-		printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
-		       cp->number);
-
-		s3c2410_dma_dostop(cp);
-	}
-
-	return 0;
-}
-
-static int s3c2410_dma_resume(struct sys_device *dev)
-{
-	return 0;
-}
-
-#else
-#define s3c2410_dma_suspend NULL
-#define s3c2410_dma_resume  NULL
-#endif /* CONFIG_PM */
-
-struct sysdev_class dma_sysclass = {
-	set_kset_name("s3c24xx-dma"),
-	.suspend	= s3c2410_dma_suspend,
-	.resume		= s3c2410_dma_resume,
+static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
+	.select		= s3c2410_dma_select,
+	.dcon_mask	= 7 << 24,
+	.map		= s3c2410_dma_mappings,
+	.map_size	= ARRAY_SIZE(s3c2410_dma_mappings),
 };
 
-/* kmem cache implementation */
+static struct s3c24xx_dma_order __initdata s3c2410_dma_order = {
+	.channels	= {
+		[DMACH_SDI]	= {
+			.list	= {
+				[0]	= 3 | DMA_CH_VALID,
+				[1]	= 2 | DMA_CH_VALID,
+				[2]	= 0 | DMA_CH_VALID,
+			},
+		},
+		[DMACH_I2S_IN]	= {
+			.list	= {
+				[0]	= 1 | DMA_CH_VALID,
+				[1]	= 2 | DMA_CH_VALID,
+			},
+		},
+	},
+};
 
-static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
+static int s3c2410_dma_add(struct sys_device *sysdev)
 {
-	memset(p, 0, sizeof(struct s3c2410_dma_buf));
+	s3c2410_dma_init();
+	s3c24xx_dma_order_set(&s3c2410_dma_order);
+	return s3c24xx_dma_init_map(&s3c2410_dma_sel);
 }
 
-/* initialisation code */
+#if defined(CONFIG_CPU_S3C2410)
+static struct sysdev_driver s3c2410_dma_driver = {
+	.add	= s3c2410_dma_add,
+};
 
-static int __init s3c2410_init_dma(void)
+static int __init s3c2410_dma_drvinit(void)
 {
-	struct s3c2410_dma_chan *cp;
-	int channel;
-	int ret;
-
-	printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
-
-	dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
-	if (dma_base == NULL) {
-		printk(KERN_ERR "dma failed to remap register block\n");
-		return -ENOMEM;
-	}
-
-	printk("Registering sysclass\n");
-
-	ret = sysdev_class_register(&dma_sysclass);
-	if (ret != 0) {
-		printk(KERN_ERR "dma sysclass registration failed\n");
-		goto err;
-	}
-
-	dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0,
-				     SLAB_HWCACHE_ALIGN,
-				     s3c2410_dma_cache_ctor, NULL);
-
-	if (dma_kmem == NULL) {
-		printk(KERN_ERR "dma failed to make kmem cache\n");
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
-		cp = &s3c2410_chans[channel];
-
-		memset(cp, 0, sizeof(struct s3c2410_dma_chan));
-
-		/* dma channel irqs are in order.. */
-		cp->number = channel;
-		cp->irq    = channel + IRQ_DMA0;
-		cp->regs   = dma_base + (channel*0x40);
-
-		/* point current stats somewhere */
-		cp->stats  = &cp->stats_store;
-		cp->stats_store.timeout_shortest = LONG_MAX;
-
-		/* basic channel configuration */
-
-		cp->load_timeout = 1<<18;
-
-		/* register system device */
-
-		cp->dev.cls = &dma_sysclass;
-		cp->dev.id  = channel;
-		ret = sysdev_register(&cp->dev);
-
-		printk("DMA channel %d at %p, irq %d\n",
-		       cp->number, cp->regs, cp->irq);
-	}
-
-	return 0;
-
- err:
-	kmem_cache_destroy(dma_kmem);
-	iounmap(dma_base);
-	dma_base = NULL;
-	return ret;
+	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
 }
 
-core_initcall(s3c2410_init_dma);
+arch_initcall(s3c2410_dma_drvinit);
+#endif
 
-static inline int is_channel_valid(unsigned int channel)
+#if defined(CONFIG_CPU_S3C2442)
+/* S3C2442 DMA contains the same selection table as the S3C2410 */
+static struct sysdev_driver s3c2442_dma_driver = {
+	.add	= s3c2410_dma_add,
+};
+
+static int __init s3c2442_dma_drvinit(void)
 {
-	return (channel & DMA_CH_VALID);
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
 }
 
-/* s3c2410_dma_map_channel()
- *
- * turn the virtual channel number into a real, and un-used hardware
- * channel.
- *
- * currently this code uses first-free channel from the specified harware
- * map, not taking into account anything that the board setup code may
- * have to say about the likely peripheral set to be in use.
-*/
+arch_initcall(s3c2442_dma_drvinit);
+#endif
 
-struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
-{
-	struct s3c24xx_dma_map *ch_map;
-	struct s3c2410_dma_chan *dmach;
-	int ch;
-
-	if (dma_sel.map == NULL || channel > dma_sel.map_size)
-		return NULL;
-
-	ch_map = dma_sel.map + channel;
-
-	for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
-		if (!is_channel_valid(ch_map->channels[ch]))
-			continue;
-
-		if (s3c2410_chans[ch].in_use == 0) {
-			printk("mapped channel %d to %d\n", channel, ch);
-			break;
-		}
-	}
-
-	if (ch >= S3C2410_DMA_CHANNELS)
-		return NULL;
-
-	/* update our channel mapping */
-
-	dmach = &s3c2410_chans[ch];
-	dma_chan_map[channel] = dmach;
-
-	/* select the channel */
-
-	(dma_sel.select)(dmach, ch_map);
-
-	return dmach;
-}
-
-static void s3c24xx_dma_show_ch(struct s3c24xx_dma_map *map, int ch)
-{
-	/* show the channel configuration */
-
-	printk("%2d: %20s, channels %c%c%c%c\n", ch, map->name,
-	       (is_channel_valid(map->channels[0]) ? '0' : '-'),
-	       (is_channel_valid(map->channels[1]) ? '1' : '-'),
-	       (is_channel_valid(map->channels[2]) ? '2' : '-'),
-	       (is_channel_valid(map->channels[3]) ? '3' : '-'));
-}
-
-static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
-{
-	if (1)
-		s3c24xx_dma_show_ch(map, ch);
-
-	return 0;
-}
-
-int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
-{
-	struct s3c24xx_dma_map *nmap;
-	size_t map_sz = sizeof(*nmap) * sel->map_size;
-	int ptr;
-
-	nmap = kmalloc(map_sz, GFP_KERNEL);
-	if (nmap == NULL)
-		return -ENOMEM;
-
-	memcpy(nmap, sel->map, map_sz);
-	memcpy(&dma_sel, sel, sizeof(*sel));
-
-	dma_sel.map = nmap;
-
-	for (ptr = 0; ptr < sel->map_size; ptr++)
-		s3c24xx_dma_check_entry(nmap+ptr, ptr);
-
-	return 0;
-}
diff --git a/arch/arm/mach-s3c2410/dma.h b/arch/arm/mach-s3c2410/dma.h
deleted file mode 100644
index 0ebfe0a..0000000
--- a/arch/arm/mach-s3c2410/dma.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* arch/arm/mach-s3c2410/dma.h
- *
- * Copyright (C) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C24XX DMA support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-extern struct sysdev_class dma_sysclass;
-extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
-
-#define DMA_CH_VALID		(1<<31)
-
-struct s3c24xx_dma_addr {
-	unsigned long		from;
-	unsigned long		to;
-};
-
-/* struct s3c24xx_dma_map
- *
- * this holds the mapping information for the channel selected
- * to be connected to the specified device
-*/
-
-struct s3c24xx_dma_map {
-	const char		*name;
-	struct s3c24xx_dma_addr  hw_addr;
-
-	unsigned long		 channels[S3C2410_DMA_CHANNELS];
-};
-
-struct s3c24xx_dma_selection {
-	struct s3c24xx_dma_map	*map;
-	unsigned long		 map_size;
-	unsigned long		 dcon_mask;
-
-	void	(*select)(struct s3c2410_dma_chan *chan,
-			  struct s3c24xx_dma_map *map);
-};
-
-extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index f6fb215..01e795d 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -1,9 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/gpio.c
  *
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2004-2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C24XX GPIO support
+ * S3C2410 GPIO support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +18,7 @@
  * 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/init.h>
@@ -33,156 +32,40 @@
 
 #include <asm/arch/regs-gpio.h>
 
-void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
+int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+			   unsigned int config)
 {
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long mask;
-	unsigned long con;
+	void __iomem *reg = S3C24XX_EINFLT0;
 	unsigned long flags;
+	unsigned long val;
 
-	if (pin < S3C2410_GPIO_BANKB) {
-		mask = 1 << S3C2410_GPIO_OFFSET(pin);
-	} else {
-		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
-	}
+	if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
+		return -1;
 
-	switch (function) {
-	case S3C2410_GPIO_LEAVE:
-		mask = 0;
-		function = 0;
-		break;
+	config &= 0xff;
 
-	case S3C2410_GPIO_INPUT:
-	case S3C2410_GPIO_OUTPUT:
-	case S3C2410_GPIO_SFN2:
-	case S3C2410_GPIO_SFN3:
-		if (pin < S3C2410_GPIO_BANKB) {
-			function -= 1;
-			function &= 1;
-			function <<= S3C2410_GPIO_OFFSET(pin);
-		} else {
-			function &= 3;
-			function <<= S3C2410_GPIO_OFFSET(pin)*2;
-		}
-	}
-
-	/* modify the specified register wwith IRQs off */
+	pin -= S3C2410_GPG8;
+	reg += pin & ~3;
 
 	local_irq_save(flags);
 
-	con  = __raw_readl(base + 0x00);
-	con &= ~mask;
-	con |= function;
+	/* update filter width and clock source */
 
-	__raw_writel(con, base + 0x00);
+	val = __raw_readl(reg);
+	val &= ~(0xff << ((pin & 3) * 8));
+	val |= config << ((pin & 3) * 8);
+	__raw_writel(val, reg);
+
+	/* update filter enable */
+
+	val = __raw_readl(S3C24XX_EXTINT2);
+	val &= ~(1 << ((pin * 4) + 3));
+	val |= on << ((pin * 4) + 3);
+	__raw_writel(val, S3C24XX_EXTINT2);
 
 	local_irq_restore(flags);
+
+	return 0;
 }
 
-EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
-
-unsigned int s3c2410_gpio_getcfg(unsigned int pin)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long val = __raw_readl(base);
-
-	if (pin < S3C2410_GPIO_BANKB) {
-		val >>= S3C2410_GPIO_OFFSET(pin);
-		val &= 1;
-		val += 1;
-	} else {
-		val >>= S3C2410_GPIO_OFFSET(pin)*2;
-		val &= 3;
-	}
-
-	return val | S3C2410_GPIO_INPUT;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getcfg);
-
-void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
-	unsigned long flags;
-	unsigned long up;
-
-	if (pin < S3C2410_GPIO_BANKB)
-		return;
-
-	local_irq_save(flags);
-
-	up = __raw_readl(base + 0x08);
-	up &= ~(1L << offs);
-	up |= to << offs;
-	__raw_writel(up, base + 0x08);
-
-	local_irq_restore(flags);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
-
-void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
-	unsigned long flags;
-	unsigned long dat;
-
-	local_irq_save(flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offs);
-	dat |= to << offs;
-	__raw_writel(dat, base + 0x04);
-
-	local_irq_restore(flags);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_setpin);
-
-unsigned int s3c2410_gpio_getpin(unsigned int pin)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
-
-	return __raw_readl(base + 0x04) & (1<< offs);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
-
-unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
-{
-	unsigned long flags;
-	unsigned long misccr;
-
-	local_irq_save(flags);
-	misccr = __raw_readl(S3C24XX_MISCCR);
-	misccr &= ~clear;
-	misccr ^= change;
-	__raw_writel(misccr, S3C24XX_MISCCR);
-	local_irq_restore(flags);
-
-	return misccr;
-}
-
-EXPORT_SYMBOL(s3c2410_modify_misccr);
-
-int s3c2410_gpio_getirq(unsigned int pin)
-{
-	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
-		return -1;	/* not valid interrupts */
-
-	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
-		return -1;	/* not valid pin */
-
-	if (pin < S3C2410_GPF4)
-		return (pin - S3C2410_GPF0) + IRQ_EINT0;
-
-	if (pin < S3C2410_GPG0)
-		return (pin - S3C2410_GPF4) + IRQ_EINT4;
-
-	return (pin - S3C2410_GPG0) + IRQ_EINT8;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getirq);
+EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 3c0ed78..53cbdaa 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/irq.c
  *
- * Copyright (c) 2003,2004 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -17,37 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Changelog:
- *
- *   22-Jul-2004  Ben Dooks <ben@simtec.co.uk>
- *                Fixed compile warnings
- *
- *   22-Jul-2004  Roc Wu <cooloney@yahoo.com.cn>
- *                Fixed s3c_extirq_type
- *
- *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
- *                Addition of ADC/TC demux
- *
- *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
- *		  Fix for set_irq_type() on low EINT numbers
- *
- *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
- *		  Tidy up KF's patch and sort out new release
- *
- *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
- *		  Add support for power management controls
- *
- *   04-Nov-2004  Ben Dooks
- *		  Fix standard IRQ wake for EINT0..4 and RTC
- *
- *   22-Feb-2005  Ben Dooks
- *		  Fixed edge-triggering on ADC IRQ
- *
- *   28-Jun-2005  Ben Dooks
- *		  Mark IRQ_LCD valid
- *
- *   25-Jul-2005  Ben Dooks
- *		  Split the S3C2440 IRQ code to seperate file
 */
 
 #include <linux/init.h>
@@ -57,745 +26,23 @@
 #include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
-#include <asm/mach/irq.h>
-
-#include <asm/arch/regs-irq.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
-
-/* wakeup irq control */
-
-#ifdef CONFIG_PM
-
-/* state for IRQs over sleep */
-
-/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
- *
- * set bit to 1 in allow bitfield to enable the wakeup settings on it
-*/
-
-unsigned long s3c_irqwake_intallow	= 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
-unsigned long s3c_irqwake_intmask	= 0xffffffffL;
-unsigned long s3c_irqwake_eintallow	= 0x0000fff0L;
-unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
-
-int
-s3c_irq_wake(unsigned int irqno, unsigned int state)
+static int s3c2410_irq_add(struct sys_device *sysdev)
 {
-	unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
-
-	if (!(s3c_irqwake_intallow & irqbit))
-		return -ENOENT;
-
-	printk(KERN_INFO "wake %s for irq %d\n",
-	       state ? "enabled" : "disabled", irqno);
-
-	if (!state)
-		s3c_irqwake_intmask |= irqbit;
-	else
-		s3c_irqwake_intmask &= ~irqbit;
-
 	return 0;
 }
 
-static int
-s3c_irqext_wake(unsigned int irqno, unsigned int state)
-{
-	unsigned long bit = 1L << (irqno - EXTINT_OFF);
-
-	if (!(s3c_irqwake_eintallow & bit))
-		return -ENOENT;
-
-	printk(KERN_INFO "wake %s for irq %d\n",
-	       state ? "enabled" : "disabled", irqno);
-
-	if (!state)
-		s3c_irqwake_eintmask |= bit;
-	else
-		s3c_irqwake_eintmask &= ~bit;
-
-	return 0;
-}
-
-#else
-#define s3c_irqext_wake NULL
-#define s3c_irq_wake NULL
-#endif
-
-
-static void
-s3c_irq_mask(unsigned int irqno)
-{
-	unsigned long mask;
-
-	irqno -= IRQ_EINT0;
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	mask |= 1UL << irqno;
-	__raw_writel(mask, S3C2410_INTMSK);
-}
-
-static inline void
-s3c_irq_ack(unsigned int irqno)
-{
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-
-	__raw_writel(bitval, S3C2410_SRCPND);
-	__raw_writel(bitval, S3C2410_INTPND);
-}
-
-static inline void
-s3c_irq_maskack(unsigned int irqno)
-{
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-	unsigned long mask;
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	__raw_writel(mask|bitval, S3C2410_INTMSK);
-
-	__raw_writel(bitval, S3C2410_SRCPND);
-	__raw_writel(bitval, S3C2410_INTPND);
-}
-
-
-static void
-s3c_irq_unmask(unsigned int irqno)
-{
-	unsigned long mask;
-
-	if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
-		irqdbf2("s3c_irq_unmask %d\n", irqno);
-
-	irqno -= IRQ_EINT0;
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	mask &= ~(1UL << irqno);
-	__raw_writel(mask, S3C2410_INTMSK);
-}
-
-struct irq_chip s3c_irq_level_chip = {
-	.name		= "s3c-level",
-	.ack		= s3c_irq_maskack,
-	.mask		= s3c_irq_mask,
-	.unmask		= s3c_irq_unmask,
-	.set_wake	= s3c_irq_wake
+static struct sysdev_driver s3c2410_irq_driver = {
+	.add		= s3c2410_irq_add,
+	.suspend	= s3c24xx_irq_suspend,
+	.resume		= s3c24xx_irq_resume,
 };
 
-static struct irq_chip s3c_irq_chip = {
-	.name		= "s3c",
-	.ack		= s3c_irq_ack,
-	.mask		= s3c_irq_mask,
-	.unmask		= s3c_irq_unmask,
-	.set_wake	= s3c_irq_wake
-};
-
-static void
-s3c_irqext_mask(unsigned int irqno)
+static int s3c2410_irq_init(void)
 {
-	unsigned long mask;
-
-	irqno -= EXTINT_OFF;
-
-	mask = __raw_readl(S3C24XX_EINTMASK);
-	mask |= ( 1UL << irqno);
-	__raw_writel(mask, S3C24XX_EINTMASK);
+	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
 }
 
-static void
-s3c_irqext_ack(unsigned int irqno)
-{
-	unsigned long req;
-	unsigned long bit;
-	unsigned long mask;
-
-	bit = 1UL << (irqno - EXTINT_OFF);
-
-	mask = __raw_readl(S3C24XX_EINTMASK);
-
-	__raw_writel(bit, S3C24XX_EINTPEND);
-
-	req = __raw_readl(S3C24XX_EINTPEND);
-	req &= ~mask;
-
-	/* not sure if we should be acking the parent irq... */
-
-	if (irqno <= IRQ_EINT7 ) {
-		if ((req & 0xf0) == 0)
-			s3c_irq_ack(IRQ_EINT4t7);
-	} else {
-		if ((req >> 8) == 0)
-			s3c_irq_ack(IRQ_EINT8t23);
-	}
-}
-
-static void
-s3c_irqext_unmask(unsigned int irqno)
-{
-	unsigned long mask;
-
-	irqno -= EXTINT_OFF;
-
-	mask = __raw_readl(S3C24XX_EINTMASK);
-	mask &= ~( 1UL << irqno);
-	__raw_writel(mask, S3C24XX_EINTMASK);
-}
-
-int
-s3c_irqext_type(unsigned int irq, unsigned int type)
-{
-	void __iomem *extint_reg;
-	void __iomem *gpcon_reg;
-	unsigned long gpcon_offset, extint_offset;
-	unsigned long newvalue = 0, value;
-
-	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
-	{
-		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C24XX_EXTINT0;
-		gpcon_offset = (irq - IRQ_EINT0) * 2;
-		extint_offset = (irq - IRQ_EINT0) * 4;
-	}
-	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
-	{
-		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C24XX_EXTINT0;
-		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
-		extint_offset = (irq - (EXTINT_OFF)) * 4;
-	}
-	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
-	{
-		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C24XX_EXTINT1;
-		gpcon_offset = (irq - IRQ_EINT8) * 2;
-		extint_offset = (irq - IRQ_EINT8) * 4;
-	}
-	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
-	{
-		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C24XX_EXTINT2;
-		gpcon_offset = (irq - IRQ_EINT8) * 2;
-		extint_offset = (irq - IRQ_EINT16) * 4;
-	} else
-		return -1;
-
-	/* Set the GPIO to external interrupt mode */
-	value = __raw_readl(gpcon_reg);
-	value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
-	__raw_writel(value, gpcon_reg);
-
-	/* Set the external interrupt to pointed trigger type */
-	switch (type)
-	{
-		case IRQT_NOEDGE:
-			printk(KERN_WARNING "No edge setting!\n");
-			break;
-
-		case IRQT_RISING:
-			newvalue = S3C2410_EXTINT_RISEEDGE;
-			break;
-
-		case IRQT_FALLING:
-			newvalue = S3C2410_EXTINT_FALLEDGE;
-			break;
-
-		case IRQT_BOTHEDGE:
-			newvalue = S3C2410_EXTINT_BOTHEDGE;
-			break;
-
-		case IRQT_LOW:
-			newvalue = S3C2410_EXTINT_LOWLEV;
-			break;
-
-		case IRQT_HIGH:
-			newvalue = S3C2410_EXTINT_HILEV;
-			break;
-
-		default:
-			printk(KERN_ERR "No such irq type %d", type);
-			return -1;
-	}
-
-	value = __raw_readl(extint_reg);
-	value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
-	__raw_writel(value, extint_reg);
-
-	return 0;
-}
-
-static struct irq_chip s3c_irqext_chip = {
-	.name		= "s3c-ext",
-	.mask		= s3c_irqext_mask,
-	.unmask		= s3c_irqext_unmask,
-	.ack		= s3c_irqext_ack,
-	.set_type	= s3c_irqext_type,
-	.set_wake	= s3c_irqext_wake
-};
-
-static struct irq_chip s3c_irq_eint0t4 = {
-	.name		= "s3c-ext0",
-	.ack		= s3c_irq_ack,
-	.mask		= s3c_irq_mask,
-	.unmask		= s3c_irq_unmask,
-	.set_wake	= s3c_irq_wake,
-	.set_type	= s3c_irqext_type,
-};
-
-/* mask values for the parent registers for each of the interrupt types */
-
-#define INTMSK_UART0	 (1UL << (IRQ_UART0 - IRQ_EINT0))
-#define INTMSK_UART1	 (1UL << (IRQ_UART1 - IRQ_EINT0))
-#define INTMSK_UART2	 (1UL << (IRQ_UART2 - IRQ_EINT0))
-#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
-
-
-/* UART0 */
-
-static void
-s3c_irq_uart0_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
-}
-
-static void
-s3c_irq_uart0_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_UART0);
-}
-
-static void
-s3c_irq_uart0_ack(unsigned int irqno)
-{
-	s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
-}
-
-static struct irq_chip s3c_irq_uart0 = {
-	.name		= "s3c-uart0",
-	.mask		= s3c_irq_uart0_mask,
-	.unmask		= s3c_irq_uart0_unmask,
-	.ack		= s3c_irq_uart0_ack,
-};
-
-/* UART1 */
-
-static void
-s3c_irq_uart1_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
-}
-
-static void
-s3c_irq_uart1_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_UART1);
-}
-
-static void
-s3c_irq_uart1_ack(unsigned int irqno)
-{
-	s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
-}
-
-static struct irq_chip s3c_irq_uart1 = {
-	.name		= "s3c-uart1",
-	.mask		= s3c_irq_uart1_mask,
-	.unmask		= s3c_irq_uart1_unmask,
-	.ack		= s3c_irq_uart1_ack,
-};
-
-/* UART2 */
-
-static void
-s3c_irq_uart2_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
-}
-
-static void
-s3c_irq_uart2_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_UART2);
-}
-
-static void
-s3c_irq_uart2_ack(unsigned int irqno)
-{
-	s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
-}
-
-static struct irq_chip s3c_irq_uart2 = {
-	.name		= "s3c-uart2",
-	.mask		= s3c_irq_uart2_mask,
-	.unmask		= s3c_irq_uart2_unmask,
-	.ack		= s3c_irq_uart2_ack,
-};
-
-/* ADC and Touchscreen */
-
-static void
-s3c_irq_adc_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
-}
-
-static void
-s3c_irq_adc_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
-}
-
-static void
-s3c_irq_adc_ack(unsigned int irqno)
-{
-	s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
-}
-
-static struct irq_chip s3c_irq_adc = {
-	.name		= "s3c-adc",
-	.mask		= s3c_irq_adc_mask,
-	.unmask		= s3c_irq_adc_unmask,
-	.ack		= s3c_irq_adc_ack,
-};
-
-/* irq demux for adc */
-static void s3c_irq_demux_adc(unsigned int irq,
-			      struct irq_desc *desc)
-{
-	unsigned int subsrc, submsk;
-	unsigned int offset = 9;
-	struct irq_desc *mydesc;
-
-	/* read the current pending interrupts, and the mask
-	 * for what it is available */
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	subsrc &= ~submsk;
-	subsrc >>= offset;
-	subsrc &= 3;
-
-	if (subsrc != 0) {
-		if (subsrc & 1) {
-			mydesc = irq_desc + IRQ_TC;
-			desc_handle_irq(IRQ_TC, mydesc);
-		}
-		if (subsrc & 2) {
-			mydesc = irq_desc + IRQ_ADC;
-			desc_handle_irq(IRQ_ADC, mydesc);
-		}
-	}
-}
-
-static void s3c_irq_demux_uart(unsigned int start)
-{
-	unsigned int subsrc, submsk;
-	unsigned int offset = start - IRQ_S3CUART_RX0;
-	struct irq_desc *desc;
-
-	/* read the current pending interrupts, and the mask
-	 * for what it is available */
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
-		start, offset, subsrc, submsk);
-
-	subsrc &= ~submsk;
-	subsrc >>= offset;
-	subsrc &= 7;
-
-	if (subsrc != 0) {
-		desc = irq_desc + start;
-
-		if (subsrc & 1)
-			desc_handle_irq(start, desc);
-
-		desc++;
-
-		if (subsrc & 2)
-			desc_handle_irq(start+1, desc);
-
-		desc++;
-
-		if (subsrc & 4)
-			desc_handle_irq(start+2, desc);
-	}
-}
-
-/* uart demux entry points */
-
-static void
-s3c_irq_demux_uart0(unsigned int irq,
-		    struct irq_desc *desc)
-{
-	irq = irq;
-	s3c_irq_demux_uart(IRQ_S3CUART_RX0);
-}
-
-static void
-s3c_irq_demux_uart1(unsigned int irq,
-		    struct irq_desc *desc)
-{
-	irq = irq;
-	s3c_irq_demux_uart(IRQ_S3CUART_RX1);
-}
-
-static void
-s3c_irq_demux_uart2(unsigned int irq,
-		    struct irq_desc *desc)
-{
-	irq = irq;
-	s3c_irq_demux_uart(IRQ_S3CUART_RX2);
-}
-
-static void
-s3c_irq_demux_extint8(unsigned int irq,
-		      struct irq_desc *desc)
-{
-	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
-	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
-
-	eintpnd &= ~eintmsk;
-	eintpnd &= ~0xff;	/* ignore lower irqs */
-
-	/* we may as well handle all the pending IRQs here */
-
-	while (eintpnd) {
-		irq = __ffs(eintpnd);
-		eintpnd &= ~(1<<irq);
-
-		irq += (IRQ_EINT4 - 4);
-		desc_handle_irq(irq, irq_desc + irq);
-	}
-
-}
-
-static void
-s3c_irq_demux_extint4t7(unsigned int irq,
-			struct irq_desc *desc)
-{
-	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
-	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
-
-	eintpnd &= ~eintmsk;
-	eintpnd &= 0xff;	/* only lower irqs */
-
-	/* we may as well handle all the pending IRQs here */
-
-	while (eintpnd) {
-		irq = __ffs(eintpnd);
-		eintpnd &= ~(1<<irq);
-
-		irq += (IRQ_EINT4 - 4);
-
-		desc_handle_irq(irq, irq_desc + irq);
-	}
-}
-
-#ifdef CONFIG_PM
-
-static struct sleep_save irq_save[] = {
-	SAVE_ITEM(S3C2410_INTMSK),
-	SAVE_ITEM(S3C2410_INTSUBMSK),
-};
-
-/* the extint values move between the s3c2410/s3c2440 and the s3c2412
- * so we use an array to hold them, and to calculate the address of
- * the register at run-time
-*/
-
-static unsigned long save_extint[3];
-static unsigned long save_eintflt[4];
-static unsigned long save_eintmask;
-
-int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
-		save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
-
-	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
-		save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
-
-	s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
-	save_eintmask = __raw_readl(S3C24XX_EINTMASK);
-
-	return 0;
-}
-
-int s3c24xx_irq_resume(struct sys_device *dev)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
-		__raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
-
-	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
-		__raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
-
-	s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
-	__raw_writel(save_eintmask, S3C24XX_EINTMASK);
-
-	return 0;
-}
-
-#else
-#define s3c24xx_irq_suspend NULL
-#define s3c24xx_irq_resume  NULL
-#endif
-
-/* s3c24xx_init_irq
- *
- * Initialise S3C2410 IRQ system
-*/
-
-void __init s3c24xx_init_irq(void)
-{
-	unsigned long pend;
-	unsigned long last;
-	int irqno;
-	int i;
-
-	irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
-
-	/* first, clear all interrupts pending... */
-
-	last = 0;
-	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(S3C24XX_EINTPEND);
-
-		if (pend == 0 || pend == last)
-			break;
-
-		__raw_writel(pend, S3C24XX_EINTPEND);
-		printk("irq: clearing pending ext status %08x\n", (int)pend);
-		last = pend;
-	}
-
-	last = 0;
-	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(S3C2410_INTPND);
-
-		if (pend == 0 || pend == last)
-			break;
-
-		__raw_writel(pend, S3C2410_SRCPND);
-		__raw_writel(pend, S3C2410_INTPND);
-		printk("irq: clearing pending status %08x\n", (int)pend);
-		last = pend;
-	}
-
-	last = 0;
-	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(S3C2410_SUBSRCPND);
-
-		if (pend == 0 || pend == last)
-			break;
-
-		printk("irq: clearing subpending status %08x\n", (int)pend);
-		__raw_writel(pend, S3C2410_SUBSRCPND);
-		last = pend;
-	}
-
-	/* register the main interrupts */
-
-	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
-
-	for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
-		/* set all the s3c2410 internal irqs */
-
-		switch (irqno) {
-			/* deal with the special IRQs (cascaded) */
-
-		case IRQ_EINT4t7:
-		case IRQ_EINT8t23:
-		case IRQ_UART0:
-		case IRQ_UART1:
-		case IRQ_UART2:
-		case IRQ_ADCPARENT:
-			set_irq_chip(irqno, &s3c_irq_level_chip);
-			set_irq_handler(irqno, handle_level_irq);
-			break;
-
-		case IRQ_RESERVED6:
-		case IRQ_RESERVED24:
-			/* no IRQ here */
-			break;
-
-		default:
-			//irqdbf("registering irq %d (s3c irq)\n", irqno);
-			set_irq_chip(irqno, &s3c_irq_chip);
-			set_irq_handler(irqno, handle_edge_irq);
-			set_irq_flags(irqno, IRQF_VALID);
-		}
-	}
-
-	/* setup the cascade irq handlers */
-
-	set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
-	set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
-
-	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
-	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
-	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
-	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
-
-	/* external interrupts */
-
-	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
-		irqdbf("registering irq %d (ext int)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_eint0t4);
-		set_irq_handler(irqno, handle_edge_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
-		irqdbf("registering irq %d (extended s3c irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irqext_chip);
-		set_irq_handler(irqno, handle_edge_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	/* register the uart interrupts */
-
-	irqdbf("s3c2410: registering external interrupts\n");
-
-	for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
-		irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_uart0);
-		set_irq_handler(irqno, handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
-		irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_uart1);
-		set_irq_handler(irqno, handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
-		irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_uart2);
-		set_irq_handler(irqno, handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
-		irqdbf("registering irq %d (s3c adc irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_adc);
-		set_irq_handler(irqno, handle_edge_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	irqdbf("s3c2410: registered interrupt handlers\n");
-}
+arch_initcall(s3c2410_irq_init);
diff --git a/arch/arm/mach-s3c2410/irq.h b/arch/arm/mach-s3c2410/irq.h
deleted file mode 100644
index e5913da..0000000
--- a/arch/arm/mach-s3c2410/irq.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* arch/arm/mach-s3c2410/irq.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C24XX CPU IRQ support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define irqdbf(x...)
-#define irqdbf2(x...)
-
-#define EXTINT_OFF (IRQ_EINT4 - 4)
-
-extern struct irq_chip s3c_irq_level_chip;
-
-static inline void
-s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
-		int subcheck)
-{
-	unsigned long mask;
-	unsigned long submask;
-
-	submask = __raw_readl(S3C2410_INTSUBMSK);
-	mask = __raw_readl(S3C2410_INTMSK);
-
-	submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
-
-	/* check to see if we need to mask the parent IRQ */
-
-	if ((submask  & subcheck) == subcheck) {
-		__raw_writel(mask | parentbit, S3C2410_INTMSK);
-	}
-
-	/* write back masks */
-	__raw_writel(submask, S3C2410_INTSUBMSK);
-
-}
-
-static inline void
-s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
-{
-	unsigned long mask;
-	unsigned long submask;
-
-	submask = __raw_readl(S3C2410_INTSUBMSK);
-	mask = __raw_readl(S3C2410_INTMSK);
-
-	submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
-	mask &= ~parentbit;
-
-	/* write back masks */
-	__raw_writel(submask, S3C2410_INTSUBMSK);
-	__raw_writel(mask, S3C2410_INTMSK);
-}
-
-
-static inline void
-s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
-{
-	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
-
-	s3c_irqsub_mask(irqno, parentmask, group);
-
-	__raw_writel(bit, S3C2410_SUBSRCPND);
-
-	/* only ack parent if we've got all the irqs (seems we must
-	 * ack, all and hope that the irq system retriggers ok when
-	 * the interrupt goes off again)
-	 */
-
-	if (1) {
-		__raw_writel(parentmask, S3C2410_SRCPND);
-		__raw_writel(parentmask, S3C2410_INTPND);
-	}
-}
-
-static inline void
-s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
-{
-	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
-
-	__raw_writel(bit, S3C2410_SUBSRCPND);
-
-	/* only ack parent if we've got all the irqs (seems we must
-	 * ack, all and hope that the irq system retriggers ok when
-	 * the interrupt goes off again)
-	 */
-
-	if (1) {
-		__raw_writel(parentmask, S3C2410_SRCPND);
-		__raw_writel(parentmask, S3C2410_INTPND);
-	}
-}
-
-/* exported for use in arch/arm/mach-s3c2410 */
-
-#ifdef CONFIG_PM
-extern int s3c_irq_wake(unsigned int irqno, unsigned int state);
-#else
-#define s3c_irq_wake NULL
-#endif
-
-extern int s3c_irqext_type(unsigned int irq, unsigned int type);
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index 817e2c6..72f2cc4 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -1,4 +1,4 @@
-/***********************************************************************
+/* linux/arch/arm/mach-s3c2410/mach-amlm5900.c
  *
  * linux/arch/arm/mach-s3c2410/mach-amlm5900.c
  *
@@ -35,7 +35,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/proc_fs.h>
-
+#include <linux/serial_core.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -52,8 +52,8 @@
 #include <asm/arch/regs-lcd.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 #ifdef CONFIG_MTD_PARTITIONS
 
@@ -113,12 +113,6 @@
 #endif
 
 static struct map_desc amlm5900_iodesc[] __initdata = {
-	{
-		.virtual	= (u32)S3C24XX_VA_SPI,
-		.pfn		= __phys_to_pfn(S3C2410_PA_SPI),
-		.length		= SZ_1M,
-		.type		= MT_DEVICE
-	}
 };
 
 #define UCON S3C2410_UCON_DEFAULT
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
deleted file mode 100644
index 0fad0c2..0000000
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/mach-anubis.c
- *
- * Copyright (c) 2003-2005 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * 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/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/anubis-map.h>
-#include <asm/arch/anubis-irq.h>
-#include <asm/arch/anubis-cpld.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-lcd.h>
-#include <asm/arch/nand.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/partitions.h>
-
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-
-#define COPYRIGHT ", (c) 2005 Simtec Electronics"
-
-static struct map_desc anubis_iodesc[] __initdata = {
-  /* ISA IO areas */
-
-  {
-	.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
-	.pfn		= __phys_to_pfn(0x0),
-	.length		= SZ_4M,
-	.type		= MT_DEVICE,
-  }, {
-	.virtual	= (u32)S3C24XX_VA_ISA_WORD,
-	.pfn		= __phys_to_pfn(0x0),
-	.length 	= SZ_4M,
-	.type		= MT_DEVICE,
-  },
-
-  /* we could possibly compress the next set down into a set of smaller tables
-   * pagetables, but that would mean using an L2 section, and it still means
-   * we cannot actually feed the same register to an LDR due to 16K spacing
-   */
-
-  /* CPLD control registers */
-
-  {
-	.virtual	= (u32)ANUBIS_VA_CTRL1,
-	.pfn		= __phys_to_pfn(ANUBIS_PA_CTRL1),
-	.length		= SZ_4K,
-	.type		= MT_DEVICE,
-  }, {
-	.virtual	= (u32)ANUBIS_VA_CTRL2,
-	.pfn		= __phys_to_pfn(ANUBIS_PA_CTRL2),
-	.length		= SZ_4K,
-	.type		= MT_DEVICE,
-  },
-};
-
-#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
-#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
-#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
-
-static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
-	[0] = {
-		.name		= "uclk",
-		.divisor	= 1,
-		.min_baud	= 0,
-		.max_baud	= 0,
-	},
-	[1] = {
-		.name		= "pclk",
-		.divisor	= 1,
-		.min_baud	= 0,
-		.max_baud	= 0,
-	}
-};
-
-
-static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-		.clocks	     = anubis_serial_clocks,
-		.clocks_size = ARRAY_SIZE(anubis_serial_clocks),
-	},
-	[1] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-		.clocks	     = anubis_serial_clocks,
-		.clocks_size = ARRAY_SIZE(anubis_serial_clocks),
-	},
-};
-
-/* NAND Flash on Anubis board */
-
-static int external_map[]   = { 2 };
-static int chip0_map[]      = { 0 };
-static int chip1_map[]      = { 1 };
-
-static struct mtd_partition anubis_default_nand_part[] = {
-	[0] = {
-		.name	= "Boot Agent",
-		.size	= SZ_16K,
-		.offset	= 0,
-	},
-	[1] = {
-		.name	= "/boot",
-		.size	= SZ_4M - SZ_16K,
-		.offset	= SZ_16K,
-	},
-	[2] = {
-		.name	= "user1",
-		.offset	= SZ_4M,
-		.size	= SZ_32M - SZ_4M,
-	},
-	[3] = {
-		.name	= "user2",
-		.offset	= SZ_32M,
-		.size	= MTDPART_SIZ_FULL,
-	}
-};
-
-/* the Anubis has 3 selectable slots for nand-flash, the two
- * on-board chip areas, as well as the external slot.
- *
- * Note, there is no current hot-plug support for the External
- * socket.
-*/
-
-static struct s3c2410_nand_set anubis_nand_sets[] = {
-	[1] = {
-		.name		= "External",
-		.nr_chips	= 1,
-		.nr_map		= external_map,
-		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
-		.partitions	= anubis_default_nand_part,
-	},
-	[0] = {
-		.name		= "chip0",
-		.nr_chips	= 1,
-		.nr_map		= chip0_map,
-		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
-		.partitions	= anubis_default_nand_part,
-	},
-	[2] = {
-		.name		= "chip1",
-		.nr_chips	= 1,
-		.nr_map		= chip1_map,
-		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
-		.partitions	= anubis_default_nand_part,
-	},
-};
-
-static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
-{
-	unsigned int tmp;
-
-	slot = set->nr_map[slot] & 3;
-
-	pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n",
-		 slot, set, set->nr_map);
-
-	tmp = __raw_readb(ANUBIS_VA_CTRL1);
-	tmp &= ~ANUBIS_CTRL1_NANDSEL;
-	tmp |= slot;
-
-	pr_debug("anubis_nand: ctrl1 now %02x\n", tmp);
-
-	__raw_writeb(tmp, ANUBIS_VA_CTRL1);
-}
-
-static struct s3c2410_platform_nand anubis_nand_info = {
-	.tacls		= 25,
-	.twrph0		= 55,
-	.twrph1		= 40,
-	.nr_sets	= ARRAY_SIZE(anubis_nand_sets),
-	.sets		= anubis_nand_sets,
-	.select_chip	= anubis_nand_select,
-};
-
-/* IDE channels */
-
-static struct resource anubis_ide0_resource[] = {
-	{
-		.start	= S3C2410_CS3,
-		.end	= S3C2410_CS3 + (8*32) - 1,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= S3C2410_CS3 + (1<<26),
-		.end	= S3C2410_CS3 + (1<<26) + (8*32) - 1,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= IRQ_IDE0,
-		.end	= IRQ_IDE0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device anubis_device_ide0 = {
-	.name		= "simtec-ide",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(anubis_ide0_resource),
-	.resource	= anubis_ide0_resource,
-};
-
-static struct resource anubis_ide1_resource[] = {
-	{
-		.start	= S3C2410_CS4,
-		.end	= S3C2410_CS4 + (8*32) - 1,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= S3C2410_CS4 + (1<<26),
-		.end	= S3C2410_CS4 + (1<<26) + (8*32) - 1,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= IRQ_IDE0,
-		.end	= IRQ_IDE0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-
-static struct platform_device anubis_device_ide1 = {
-	.name		= "simtec-ide",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(anubis_ide1_resource),
-	.resource	= anubis_ide1_resource,
-};
-
-/* Standard Anubis devices */
-
-static struct platform_device *anubis_devices[] __initdata = {
-	&s3c_device_usb,
-	&s3c_device_wdt,
-	&s3c_device_adc,
-	&s3c_device_i2c,
- 	&s3c_device_rtc,
-	&s3c_device_nand,
-	&anubis_device_ide0,
-	&anubis_device_ide1,
-};
-
-static struct clk *anubis_clocks[] = {
-	&s3c24xx_dclk0,
-	&s3c24xx_dclk1,
-	&s3c24xx_clkout0,
-	&s3c24xx_clkout1,
-	&s3c24xx_uclk,
-};
-
-static struct s3c24xx_board anubis_board __initdata = {
-	.devices       = anubis_devices,
-	.devices_count = ARRAY_SIZE(anubis_devices),
-	.clocks	       = anubis_clocks,
-	.clocks_count  = ARRAY_SIZE(anubis_clocks),
-};
-
-static void __init anubis_map_io(void)
-{
-	/* initialise the clocks */
-
-	s3c24xx_dclk0.parent = NULL;
-	s3c24xx_dclk0.rate   = 12*1000*1000;
-
-	s3c24xx_dclk1.parent = NULL;
-	s3c24xx_dclk1.rate   = 24*1000*1000;
-
-	s3c24xx_clkout0.parent  = &s3c24xx_dclk0;
-	s3c24xx_clkout1.parent  = &s3c24xx_dclk1;
-
-	s3c24xx_uclk.parent  = &s3c24xx_clkout1;
-
-	s3c_device_nand.dev.platform_data = &anubis_nand_info;
-
-	s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
-	s3c24xx_init_clocks(0);
-	s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
-	s3c24xx_set_board(&anubis_board);
-
-	/* ensure that the GPIO is setup */
-	s3c2410_gpio_setpin(S3C2410_GPA0, 1);
-}
-
-MACHINE_START(ANUBIS, "Simtec-Anubis")
-	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
-	.map_io		= anubis_map_io,
-	.init_irq	= s3c24xx_init_irq,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index b8b7675..7b81296 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -50,9 +50,9 @@
 
 #include <linux/serial_8250.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 #include "usb-simtec.h"
 
 #define COPYRIGHT ", (c) 2004-2005 Simtec Electronics"
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 15b625e..01c60d0 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -25,23 +25,24 @@
 #include <asm/mach/irq.h>
 
 #include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
 
 #include <asm/arch/h1940.h>
 #include <asm/arch/h1940-latch.h>
 #include <asm/arch/fb.h>
+#include <asm/arch/udc.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 static struct map_desc h1940_iodesc[] __initdata = {
 	[0] = {
@@ -102,6 +103,32 @@
 
 EXPORT_SYMBOL_GPL(h1940_latch_control);
 
+static void h1940_udc_pullup(enum s3c2410_udc_cmd_e cmd)
+{
+	printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
+
+	switch (cmd)
+	{
+		case S3C2410_UDC_P_ENABLE :
+			h1940_latch_control(0, H1940_LATCH_USB_DP);
+			break;
+		case S3C2410_UDC_P_DISABLE :
+			h1940_latch_control(H1940_LATCH_USB_DP, 0);
+			break;
+		case S3C2410_UDC_P_RESET :
+			break;
+		default:
+			break;
+	}
+}
+
+static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
+	.udc_command		= h1940_udc_pullup,
+	.vbus_pin		= S3C2410_GPG5,
+	.vbus_pin_inverted	= 1,
+};
+
+
 
 /**
  * Set lcd on or off
@@ -146,12 +173,19 @@
 	.bpp=		{16,16,16},
 };
 
+static struct platform_device s3c_device_leds = {
+	.name             = "h1940-leds",
+	.id               = -1,
+};
+
 static struct platform_device *h1940_devices[] __initdata = {
 	&s3c_device_usb,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c,
 	&s3c_device_iis,
+	&s3c_device_usbgadget,
+	&s3c_device_leds,
 };
 
 static struct s3c24xx_board h1940_board __initdata = {
@@ -179,7 +213,23 @@
 
 static void __init h1940_init(void)
 {
+	u32 tmp;
+
 	s3c24xx_fb_set_platdata(&h1940_lcdcfg);
+ 	s3c24xx_udc_set_platdata(&h1940_udc_cfg);
+
+	/* Turn off suspend on both USB ports, and switch the
+	 * selectable USB port to USB device mode. */
+
+	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
+			      S3C2410_MISCCR_USBSUSPND0 |
+			      S3C2410_MISCCR_USBSUSPND1, 0x0);
+
+	tmp = (
+		 0x78 << S3C2410_PLLCON_MDIVSHIFT)
+	      | (0x02 << S3C2410_PLLCON_PDIVSHIFT)
+	      | (0x03 << S3C2410_PLLCON_SDIVSHIFT);
+	writel(tmp, S3C2410_UPLLCON);
 }
 
 MACHINE_START(H1940, "IPAQ-H1940")
@@ -189,6 +239,6 @@
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= h1940_map_io,
 	.init_irq	= h1940_init_irq,
-	.init_machine   = h1940_init,
+	.init_machine	= h1940_init,
 	.timer		= &s3c24xx_timer,
 MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 0411e9a..261aa4c 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -29,7 +29,6 @@
 #include <asm/mach/irq.h>
 
 #include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
@@ -38,10 +37,10 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/iic.h>
 
-#include "s3c2410.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct map_desc n30_iodesc[] __initdata = {
 	/* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c
deleted file mode 100644
index d6dfdad..0000000
--- a/arch/arm/mach-s3c2410/mach-nexcoder.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/mach-nexcoder.c
- *
- * Copyright (c) 2004 Nex Vision
- *   Guillaume GOURAT <guillaume.gourat@nexvision.tv>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Modifications:
- *     15-10-2004 GG  Created initial version
- *     12-03-2005 BJD Updated for release
- */
-
-#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/string.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <linux/mtd/map.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/setup.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-//#include <asm/debug-ll.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-serial.h>
-
-#include "s3c2410.h"
-#include "s3c2440.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-
-static struct map_desc nexcoder_iodesc[] __initdata = {
-	/* nothing here yet */
-};
-
-#define UCON S3C2410_UCON_DEFAULT
-#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
-#define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
-
-static struct s3c2410_uartcfg nexcoder_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-	[2] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	}
-};
-
-/* NOR Flash on NexVision NexCoder 2440 board */
-
-static struct resource nexcoder_nor_resource[] = {
-	[0] = {
-		.start = S3C2410_CS0,
-		.end   = S3C2410_CS0 + (8*1024*1024) - 1,
-		.flags = IORESOURCE_MEM,
-	}
-};
-
-static struct map_info nexcoder_nor_map = {
-	.bankwidth = 2,
-};
-
-static struct platform_device nexcoder_device_nor = {
-	.name		= "mtd-flash",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(nexcoder_nor_resource),
-	.resource	= nexcoder_nor_resource,
-	.dev =
-	{
-		.platform_data = &nexcoder_nor_map,
-	}
-};
-
-/* Standard Nexcoder devices */
-
-static struct platform_device *nexcoder_devices[] __initdata = {
-	&s3c_device_usb,
-	&s3c_device_lcd,
-	&s3c_device_wdt,
-	&s3c_device_i2c,
-	&s3c_device_iis,
- 	&s3c_device_rtc,
-	&s3c_device_camif,
-	&s3c_device_spi0,
-	&s3c_device_spi1,
-	&nexcoder_device_nor,
-};
-
-static struct s3c24xx_board nexcoder_board __initdata = {
-	.devices       = nexcoder_devices,
-	.devices_count = ARRAY_SIZE(nexcoder_devices),
-};
-
-
-static void __init nexcoder_sensorboard_init(void)
-{
-	// Initialize SCCB bus
-	s3c2410_gpio_setpin(S3C2410_GPE14, 1); // IICSCL
-	s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_OUTP);
-	s3c2410_gpio_setpin(S3C2410_GPE15, 1); // IICSDA
-	s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_OUTP);
-
-	// Power up the sensor board
-	s3c2410_gpio_setpin(S3C2410_GPF1, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPF1, S3C2410_GPF1_OUTP); // CAM_GPIO7 => nLDO_PWRDN
-	s3c2410_gpio_setpin(S3C2410_GPF2, 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP); // CAM_GPIO6 => CAM_PWRDN
-}
-
-static void __init nexcoder_map_io(void)
-{
-	s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc));
-	s3c24xx_init_clocks(0);
-	s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs));
-	s3c24xx_set_board(&nexcoder_board);
-	nexcoder_sensorboard_init();
-}
-
-
-MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
-	/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
-	.map_io		= nexcoder_map_io,
-	.init_irq	= s3c24xx_init_irq,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2410/mach-osiris.c
deleted file mode 100644
index 37b4085..0000000
--- a/arch/arm/mach-s3c2410/mach-osiris.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/mach-osiris.c
- *
- * Copyright (c) 2005 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * 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/device.h>
-#include <linux/serial_core.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/osiris-map.h>
-#include <asm/arch/osiris-cpld.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-lcd.h>
-#include <asm/arch/nand.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/partitions.h>
-
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-
-/* onboard perihpheral map */
-
-static struct map_desc osiris_iodesc[] __initdata = {
-  /* ISA IO areas (may be over-written later) */
-
-  {
-	  .virtual	= (u32)S3C24XX_VA_ISA_BYTE,
-	  .pfn		= __phys_to_pfn(S3C2410_CS5),
-	  .length	= SZ_16M,
-	  .type		= MT_DEVICE,
-  }, {
-	  .virtual	= (u32)S3C24XX_VA_ISA_WORD,
-	  .pfn		= __phys_to_pfn(S3C2410_CS5),
-	  .length	= SZ_16M,
-	  .type		= MT_DEVICE,
-  },
-
-  /* CPLD control registers */
-
-  {
-	  .virtual	= (u32)OSIRIS_VA_CTRL1,
-	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL1),
-	  .length	= SZ_16K,
-	  .type		= MT_DEVICE,
-  }, {
-	  .virtual	= (u32)OSIRIS_VA_CTRL2,
-	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL2),
-	  .length	= SZ_16K,
-	  .type		= MT_DEVICE,
-  },
-};
-
-#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
-#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
-#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
-
-static struct s3c24xx_uart_clksrc osiris_serial_clocks[] = {
-	[0] = {
-		.name		= "uclk",
-		.divisor	= 1,
-		.min_baud	= 0,
-		.max_baud	= 0,
-	},
-	[1] = {
-		.name		= "pclk",
-		.divisor	= 1,
-		.min_baud	= 0,
-		.max_baud	= 0,
-	}
-};
-
-static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-		.clocks	     = osiris_serial_clocks,
-		.clocks_size = ARRAY_SIZE(osiris_serial_clocks),
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-		.clocks	     = osiris_serial_clocks,
-		.clocks_size = ARRAY_SIZE(osiris_serial_clocks),
-	},
-	[2] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-		.clocks	     = osiris_serial_clocks,
-		.clocks_size = ARRAY_SIZE(osiris_serial_clocks),
-	}
-};
-
-/* NAND Flash on Osiris board */
-
-static int external_map[]   = { 2 };
-static int chip0_map[]      = { 0 };
-static int chip1_map[]      = { 1 };
-
-static struct mtd_partition osiris_default_nand_part[] = {
-	[0] = {
-		.name	= "Boot Agent",
-		.size	= SZ_16K,
-		.offset	= 0,
-	},
-	[1] = {
-		.name	= "/boot",
-		.size	= SZ_4M - SZ_16K,
-		.offset	= SZ_16K,
-	},
-	[2] = {
-		.name	= "user1",
-		.offset	= SZ_4M,
-		.size	= SZ_32M - SZ_4M,
-	},
-	[3] = {
-		.name	= "user2",
-		.offset	= SZ_32M,
-		.size	= MTDPART_SIZ_FULL,
-	}
-};
-
-/* the Osiris has 3 selectable slots for nand-flash, the two
- * on-board chip areas, as well as the external slot.
- *
- * Note, there is no current hot-plug support for the External
- * socket.
-*/
-
-static struct s3c2410_nand_set osiris_nand_sets[] = {
-	[1] = {
-		.name		= "External",
-		.nr_chips	= 1,
-		.nr_map		= external_map,
-		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
-		.partitions	= osiris_default_nand_part,
-	},
-	[0] = {
-		.name		= "chip0",
-		.nr_chips	= 1,
-		.nr_map		= chip0_map,
-		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
-		.partitions	= osiris_default_nand_part,
-	},
-	[2] = {
-		.name		= "chip1",
-		.nr_chips	= 1,
-		.nr_map		= chip1_map,
-		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
-		.partitions	= osiris_default_nand_part,
-	},
-};
-
-static void osiris_nand_select(struct s3c2410_nand_set *set, int slot)
-{
-	unsigned int tmp;
-
-	slot = set->nr_map[slot] & 3;
-
-	pr_debug("osiris_nand: selecting slot %d (set %p,%p)\n",
-		 slot, set, set->nr_map);
-
-	tmp = __raw_readb(OSIRIS_VA_CTRL1);
-	tmp &= ~OSIRIS_CTRL1_NANDSEL;
-	tmp |= slot;
-
-	pr_debug("osiris_nand: ctrl1 now %02x\n", tmp);
-
-	__raw_writeb(tmp, OSIRIS_VA_CTRL1);
-}
-
-static struct s3c2410_platform_nand osiris_nand_info = {
-	.tacls		= 25,
-	.twrph0		= 60,
-	.twrph1		= 60,
-	.nr_sets	= ARRAY_SIZE(osiris_nand_sets),
-	.sets		= osiris_nand_sets,
-	.select_chip	= osiris_nand_select,
-};
-
-/* PCMCIA control and configuration */
-
-static struct resource osiris_pcmcia_resource[] = {
-	[0] = {
-		.start	= 0x0f000000,
-		.end	= 0x0f100000,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 0x0c000000,
-		.end	= 0x0c100000,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device osiris_pcmcia = {
-	.name		= "osiris-pcmcia",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(osiris_pcmcia_resource),
-	.resource	= osiris_pcmcia_resource,
-};
-
-/* Standard Osiris devices */
-
-static struct platform_device *osiris_devices[] __initdata = {
-	&s3c_device_i2c,
-	&s3c_device_nand,
-	&osiris_pcmcia,
-};
-
-static struct clk *osiris_clocks[] = {
-	&s3c24xx_dclk0,
-	&s3c24xx_dclk1,
-	&s3c24xx_clkout0,
-	&s3c24xx_clkout1,
-	&s3c24xx_uclk,
-};
-
-static struct s3c24xx_board osiris_board __initdata = {
-	.devices       = osiris_devices,
-	.devices_count = ARRAY_SIZE(osiris_devices),
-	.clocks	       = osiris_clocks,
-	.clocks_count  = ARRAY_SIZE(osiris_clocks),
-};
-
-static void __init osiris_map_io(void)
-{
-	unsigned long flags;
-
-	/* initialise the clocks */
-
-	s3c24xx_dclk0.parent = NULL;
-	s3c24xx_dclk0.rate   = 12*1000*1000;
-
-	s3c24xx_dclk1.parent = NULL;
-	s3c24xx_dclk1.rate   = 24*1000*1000;
-
-	s3c24xx_clkout0.parent  = &s3c24xx_dclk0;
-	s3c24xx_clkout1.parent  = &s3c24xx_dclk1;
-
-	s3c24xx_uclk.parent  = &s3c24xx_clkout1;
-
-	s3c_device_nand.dev.platform_data = &osiris_nand_info;
-
-	s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
-	s3c24xx_init_clocks(0);
-	s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
-	s3c24xx_set_board(&osiris_board);
-
-	/* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
-
-	local_irq_save(flags);
-	__raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON);
-	local_irq_restore(flags);
-
-	/* write-protect line to the NAND */
-	s3c2410_gpio_setpin(S3C2410_GPA0, 1);
-}
-
-MACHINE_START(OSIRIS, "Simtec-OSIRIS")
-	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
-	.map_io		= osiris_map_io,
-	.init_irq	= s3c24xx_init_irq,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index 2c738b3..c78ab75 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -32,10 +32,10 @@
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "s3c2410.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct map_desc otom11_iodesc[] __initdata = {
   /* Device area */
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
new file mode 100644
index 0000000..c6a4159
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -0,0 +1,448 @@
+/* linux/arch/arm/mach-s3c2410/mach-qt2410.c
+ *
+ * Copyright (C) 2006 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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/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/serial_core.h>
+#include <linux/mmc/protocol.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.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/mach-types.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/leds-gpio.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/fb.h>
+#include <asm/arch/nand.h>
+#include <asm/arch/udc.h>
+#include <asm/arch/spi.h>
+#include <asm/arch/spi-gpio.h>
+
+#include <asm/plat-s3c24xx/common-smdk.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+
+static struct map_desc qt2410_iodesc[] __initdata = {
+	{ 0xe0000000, __phys_to_pfn(S3C2410_CS3+0x01000000), SZ_1M, MT_DEVICE }
+};
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	}
+};
+
+/* LCD driver info */
+
+/* Configuration for 640x480 SHARP LQ080V3DG01 */
+static struct s3c2410fb_mach_info qt2410_biglcd_cfg __initdata = {
+	.regs	= {
+
+		.lcdcon1	= S3C2410_LCDCON1_TFT16BPP |
+				  S3C2410_LCDCON1_TFT |
+				  S3C2410_LCDCON1_CLKVAL(0x01),	/* HCLK/4 */
+
+		.lcdcon2	= S3C2410_LCDCON2_VBPD(18) |	/* 19 */
+				  S3C2410_LCDCON2_LINEVAL(479) |
+				  S3C2410_LCDCON2_VFPD(10) |	/* 11 */
+				  S3C2410_LCDCON2_VSPW(14),	/* 15 */
+
+		.lcdcon3	= S3C2410_LCDCON3_HBPD(43) |	/* 44 */
+				  S3C2410_LCDCON3_HOZVAL(639) |	/* 640 */
+				  S3C2410_LCDCON3_HFPD(115),	/* 116 */
+
+		.lcdcon4	= S3C2410_LCDCON4_MVAL(0) |
+				  S3C2410_LCDCON4_HSPW(95),	/* 96 */
+
+		.lcdcon5	= S3C2410_LCDCON5_FRM565 |
+				  S3C2410_LCDCON5_INVVLINE |
+				  S3C2410_LCDCON5_INVVFRAME |
+				  S3C2410_LCDCON5_PWREN |
+				  S3C2410_LCDCON5_HWSWP,
+	},
+
+	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
+
+	.width		= 640,
+	.height		= 480,
+
+	.xres		= {
+		.min	= 640,
+		.max	= 640,
+		.defval	= 640,
+	},
+
+	.yres		= {
+		.min	= 480,
+		.max	= 480,
+		.defval = 480,
+	},
+
+	.bpp		= {
+		.min	= 16,
+		.max	= 16,
+		.defval = 16,
+	},
+};
+
+/* Configuration for 480x640 toppoly TD028TTEC1 */
+static struct s3c2410fb_mach_info qt2410_prodlcd_cfg __initdata = {
+	.regs	= {
+
+		.lcdcon1	= S3C2410_LCDCON1_TFT16BPP |
+				  S3C2410_LCDCON1_TFT |
+				  S3C2410_LCDCON1_CLKVAL(0x01),	/* HCLK/4 */
+
+		.lcdcon2	= S3C2410_LCDCON2_VBPD(1) |	/* 2 */
+				  S3C2410_LCDCON2_LINEVAL(639) |/* 640 */
+				  S3C2410_LCDCON2_VFPD(3) |	/* 4 */
+				  S3C2410_LCDCON2_VSPW(1),	/* 2 */
+
+		.lcdcon3	= S3C2410_LCDCON3_HBPD(7) |	/* 8 */
+				  S3C2410_LCDCON3_HOZVAL(479) |	/* 479 */
+				  S3C2410_LCDCON3_HFPD(23),	/* 24 */
+
+		.lcdcon4	= S3C2410_LCDCON4_MVAL(0) |
+				  S3C2410_LCDCON4_HSPW(7),	/* 8 */
+
+		.lcdcon5	= S3C2410_LCDCON5_FRM565 |
+				  S3C2410_LCDCON5_INVVLINE |
+				  S3C2410_LCDCON5_INVVFRAME |
+				  S3C2410_LCDCON5_PWREN |
+				  S3C2410_LCDCON5_HWSWP,
+	},
+
+	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
+
+	.width		= 480,
+	.height		= 640,
+
+	.xres		= {
+		.min	= 480,
+		.max	= 480,
+		.defval	= 480,
+	},
+
+	.yres		= {
+		.min	= 640,
+		.max	= 640,
+		.defval = 640,
+	},
+
+	.bpp		= {
+		.min	= 16,
+		.max	= 16,
+		.defval = 16,
+	},
+};
+
+/* Config for 240x320 LCD */
+static struct s3c2410fb_mach_info qt2410_lcd_cfg __initdata = {
+	.regs	= {
+
+		.lcdcon1	= S3C2410_LCDCON1_TFT16BPP |
+				  S3C2410_LCDCON1_TFT |
+				  S3C2410_LCDCON1_CLKVAL(0x04),
+
+		.lcdcon2	= S3C2410_LCDCON2_VBPD(1) |
+				  S3C2410_LCDCON2_LINEVAL(319) |
+				  S3C2410_LCDCON2_VFPD(6) |
+				  S3C2410_LCDCON2_VSPW(3),
+
+		.lcdcon3	= S3C2410_LCDCON3_HBPD(12) |
+				  S3C2410_LCDCON3_HOZVAL(239) |
+				  S3C2410_LCDCON3_HFPD(7),
+
+		.lcdcon4	= S3C2410_LCDCON4_MVAL(0) |
+				  S3C2410_LCDCON4_HSPW(3),
+
+		.lcdcon5	= S3C2410_LCDCON5_FRM565 |
+				  S3C2410_LCDCON5_INVVLINE |
+				  S3C2410_LCDCON5_INVVFRAME |
+				  S3C2410_LCDCON5_PWREN |
+				  S3C2410_LCDCON5_HWSWP,
+	},
+
+	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
+
+	.width		= 240,
+	.height		= 320,
+
+	.xres		= {
+		.min	= 240,
+		.max	= 240,
+		.defval	= 240,
+	},
+
+	.yres		= {
+		.min	= 320,
+		.max	= 320,
+		.defval = 320,
+	},
+
+	.bpp		= {
+		.min	= 16,
+		.max	= 16,
+		.defval = 16,
+	},
+};
+
+/* CS8900 */
+
+static struct resource qt2410_cs89x0_resources[] = {
+	[0] = {
+		.start	= 0x19000000,
+		.end	= 0x19000000 + 16,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EINT9,
+		.end	= IRQ_EINT9,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device qt2410_cs89x0 = {
+	.name		= "cirrus-cs89x0",
+	.num_resources	= ARRAY_SIZE(qt2410_cs89x0_resources),
+	.resource	= qt2410_cs89x0_resources,
+};
+
+/* LED */
+
+static struct s3c24xx_led_platdata qt2410_pdata_led = {
+	.gpio		= S3C2410_GPB0,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led",
+	.def_trigger	= "timer",
+};
+
+static struct platform_device qt2410_led = {
+	.name		= "s3c24xx_led",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &qt2410_pdata_led,
+	},
+};
+
+/* SPI */
+
+static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
+{
+	switch (cs) {
+	case BITBANG_CS_ACTIVE:
+		s3c2410_gpio_setpin(S3C2410_GPB5, 0);
+		break;
+	case BITBANG_CS_INACTIVE:
+		s3c2410_gpio_setpin(S3C2410_GPB5, 1);
+		break;
+	}
+}
+
+static struct s3c2410_spigpio_info spi_gpio_cfg = {
+	.pin_clk	= S3C2410_GPG7,
+	.pin_mosi	= S3C2410_GPG6,
+	.pin_miso	= S3C2410_GPG5,
+	.chip_select	= &spi_gpio_cs,
+};
+
+
+static struct platform_device qt2410_spi = {
+	.name		  = "s3c24xx-spi-gpio",
+	.id		  = 1,
+	.dev = {
+		.platform_data = &spi_gpio_cfg,
+	},
+};
+
+/* Board devices */
+
+static struct platform_device *qt2410_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+	&s3c_device_sdi,
+	&s3c_device_usbgadget,
+	&qt2410_spi,
+	&qt2410_cs89x0,
+	&qt2410_led,
+};
+
+static struct s3c24xx_board qt2410_board __initdata = {
+	.devices       = qt2410_devices,
+	.devices_count = ARRAY_SIZE(qt2410_devices)
+};
+
+static struct mtd_partition qt2410_nand_part[] = {
+	[0] = {
+		.name	= "U-Boot",
+		.size	= 0x30000,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "U-Boot environment",
+		.offset = 0x30000,
+		.size	= 0x4000,
+	},
+	[2] = {
+		.name	= "kernel",
+		.offset = 0x34000,
+		.size	= SZ_2M,
+	},
+	[3] = {
+		.name	= "initrd",
+		.offset	= 0x234000,
+		.size	= SZ_4M,
+	},
+	[4] = {
+		.name	= "jffs2",
+		.offset = 0x634000,
+		.size	= 0x39cc000,
+	},
+};
+
+static struct s3c2410_nand_set qt2410_nand_sets[] = {
+	[0] = {
+		.name		= "NAND",
+		.nr_chips	= 1,
+		.nr_partitions	= ARRAY_SIZE(qt2410_nand_part),
+		.partitions	= qt2410_nand_part,
+	},
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+ */
+
+static struct s3c2410_platform_nand qt2410_nand_info = {
+	.tacls		= 20,
+	.twrph0		= 60,
+	.twrph1		= 20,
+	.nr_sets	= ARRAY_SIZE(qt2410_nand_sets),
+	.sets		= qt2410_nand_sets,
+};
+
+/* UDC */
+
+static struct s3c2410_udc_mach_info qt2410_udc_cfg = {
+};
+
+static char tft_type = 's';
+
+static int __init qt2410_tft_setup(char *str)
+{
+	tft_type = str[0];
+	return 1;
+}
+
+__setup("tft=", qt2410_tft_setup);
+
+static void __init qt2410_map_io(void)
+{
+	s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
+	s3c24xx_init_clocks(12*1000*1000);
+	s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
+	s3c24xx_set_board(&qt2410_board);
+}
+
+static void __init qt2410_machine_init(void)
+{
+	s3c_device_nand.dev.platform_data = &qt2410_nand_info;
+
+	switch (tft_type) {
+	case 'p': /* production */
+		s3c24xx_fb_set_platdata(&qt2410_prodlcd_cfg);
+		break;
+	case 'b': /* big */
+		s3c24xx_fb_set_platdata(&qt2410_biglcd_cfg);
+		break;
+	case 's': /* small */
+	default:
+		s3c24xx_fb_set_platdata(&qt2410_lcd_cfg);
+		break;
+	}
+
+	s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPB0, 1);
+
+	s3c24xx_udc_set_platdata(&qt2410_udc_cfg);
+
+	s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
+
+	s3c2410_pm_init();
+}
+
+MACHINE_START(QT2410, "QT2410")
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.map_io		= qt2410_map_io,
+	.init_irq	= s3c24xx_init_irq,
+	.init_machine	= qt2410_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
+
+
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
deleted file mode 100644
index ecbcdf7..0000000
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/mach-rx3715.c
- *
- * Copyright (c) 2003,2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * http://www.handhelds.org/projects/rx3715.html
- *
- * 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/tty.h>
-#include <linux/console.h>
-#include <linux/platform_device.h>
-#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>
-
-#include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-lcd.h>
-
-#include <asm/arch/h1940.h>
-#include <asm/arch/nand.h>
-#include <asm/arch/fb.h>
-
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
-
-static struct map_desc rx3715_iodesc[] __initdata = {
-	/* dump ISA space somewhere unused */
-
-	{
-		.virtual	= (u32)S3C24XX_VA_ISA_WORD,
-		.pfn		= __phys_to_pfn(S3C2410_CS3),
-		.length		= SZ_1M,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
-		.pfn		= __phys_to_pfn(S3C2410_CS3),
-		.length		= SZ_1M,
-		.type		= MT_DEVICE,
-	},
-};
-
-
-static struct s3c24xx_uart_clksrc rx3715_serial_clocks[] = {
-	[0] = {
-		.name		= "fclk",
-		.divisor	= 0,
-		.min_baud	= 0,
-		.max_baud	= 0,
-	}
-};
-
-static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-		.clocks	     = rx3715_serial_clocks,
-		.clocks_size = ARRAY_SIZE(rx3715_serial_clocks),
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x00,
-		.clocks	     = rx3715_serial_clocks,
-		.clocks_size = ARRAY_SIZE(rx3715_serial_clocks),
-	},
-	/* IR port */
-	[2] = {
-		.hwport	     = 2,
-		.uart_flags  = UPF_CONS_FLOW,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x43,
-		.ufcon	     = 0x51,
-		.clocks	     = rx3715_serial_clocks,
-		.clocks_size = ARRAY_SIZE(rx3715_serial_clocks),
-	}
-};
-
-/* framebuffer lcd controller information */
-
-static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = {
-	.regs	= {
-		.lcdcon1 =	S3C2410_LCDCON1_TFT16BPP | \
-				S3C2410_LCDCON1_TFT | \
-				S3C2410_LCDCON1_CLKVAL(0x0C),
-
-		.lcdcon2 =	S3C2410_LCDCON2_VBPD(5) | \
-				S3C2410_LCDCON2_LINEVAL(319) | \
-				S3C2410_LCDCON2_VFPD(6) | \
-				S3C2410_LCDCON2_VSPW(2),
-
-		.lcdcon3 =	S3C2410_LCDCON3_HBPD(35) | \
-				S3C2410_LCDCON3_HOZVAL(239) | \
-				S3C2410_LCDCON3_HFPD(35),
-
-		.lcdcon4 =	S3C2410_LCDCON4_MVAL(0) | \
-				S3C2410_LCDCON4_HSPW(7),
-
-		.lcdcon5 =	S3C2410_LCDCON5_INVVLINE |
-				S3C2410_LCDCON5_FRM565 |
-				S3C2410_LCDCON5_HWSWP,
-	},
-
-	.lpcsel =	0xf82,
-
-	.gpccon =	0xaa955699,
-	.gpccon_mask =	0xffc003cc,
-	.gpcup =	0x0000ffff,
-	.gpcup_mask =	0xffffffff,
-
-	.gpdcon =	0xaa95aaa1,
-	.gpdcon_mask =	0xffc0fff0,
-	.gpdup =	0x0000faff,
-	.gpdup_mask =	0xffffffff,
-
-	.fixed_syncs =	1,
-	.width  =	240,
-	.height =	320,
-
-	.xres	= {
-		.min =		240,
-		.max =		240,
-		.defval =	240,
-	},
-
-	.yres	= {
-		.max =		320,
-		.min =		320,
-		.defval	=	320,
-	},
-
-	.bpp	= {
-		.min =		16,
-		.max =		16,
-		.defval =	16,
-	},
-};
-
-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 = {
-	.devices       = rx3715_devices,
-	.devices_count = ARRAY_SIZE(rx3715_devices)
-};
-
-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));
-	s3c24xx_set_board(&rx3715_board);
-}
-
-static void __init rx3715_init_irq(void)
-{
-	s3c24xx_init_irq();
-}
-
-static void __init rx3715_init_machine(void)
-{
-	memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
-	s3c2410_pm_init();
-
-	s3c24xx_fb_set_platdata(&rx3715_lcdcfg);
-}
-
-
-MACHINE_START(RX3715, "IPAQ-RX3715")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
-	.map_io		= rx3715_map_io,
-	.init_irq	= rx3715_init_irq,
-	.init_machine	= rx3715_init_machine,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 01c0c98..57b8a80 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -1,4 +1,4 @@
-/***********************************************************************
+/* linux/arch/arm/mach-s3c2410/mach-smdk2410.c
  *
  * linux/arch/arm/mach-s3c2410/mach-smdk2410.c
  *
@@ -49,10 +49,10 @@
 
 #include <asm/arch/regs-serial.h>
 
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-#include "common-smdk.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
 
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2410/mach-smdk2413.c
deleted file mode 100644
index 4f89abd7..0000000
--- a/arch/arm/mach-s3c2410/mach-smdk2413.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the
- * loans of SMDK2413 to work with.
- *
- * 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/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
-#include <asm/setup.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-//#include <asm/debug-ll.h>
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-lcd.h>
-
-#include <asm/arch/idle.h>
-#include <asm/arch/fb.h>
-
-#include "s3c2410.h"
-#include "s3c2412.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-
-#include "common-smdk.h"
-
-static struct map_desc smdk2413_iodesc[] __initdata = {
-};
-
-static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	},
-	/* IR port */
-	[2] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x43,
-		.ufcon	     = 0x51,
-	}
-};
-
-static struct platform_device *smdk2413_devices[] __initdata = {
-	&s3c_device_usb,
-	//&s3c_device_lcd,
-	&s3c_device_wdt,
-	&s3c_device_i2c,
-	&s3c_device_iis,
-};
-
-static struct s3c24xx_board smdk2413_board __initdata = {
-	.devices       = smdk2413_devices,
-	.devices_count = ARRAY_SIZE(smdk2413_devices)
-};
-
-static void __init smdk2413_fixup(struct machine_desc *desc,
-				  struct tag *tags, char **cmdline,
-				  struct meminfo *mi)
-{
-	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
-		mi->nr_banks=1;
-		mi->bank[0].start = 0x30000000;
-		mi->bank[0].size = SZ_64M;
-		mi->bank[0].node = 0;
-	}
-}
-
-static void __init smdk2413_map_io(void)
-{
-	s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
-	s3c24xx_set_board(&smdk2413_board);
-}
-
-static void __init smdk2413_machine_init(void)
-{
-	smdk_machine_init();
-}
-
-MACHINE_START(S3C2413, "S3C2413")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
-
-	.fixup		= smdk2413_fixup,
-	.init_irq	= s3c24xx_init_irq,
-	.map_io		= smdk2413_map_io,
-	.init_machine	= smdk2413_machine_init,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
-
-MACHINE_START(SMDK2413, "SMDK2413")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
-
-	.fixup		= smdk2413_fixup,
-	.init_irq	= s3c24xx_init_irq,
-	.map_io		= smdk2413_map_io,
-	.init_machine	= smdk2413_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
deleted file mode 100644
index 2b61f4e..0000000
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/mach-smdk2440.c
- *
- * Copyright (c) 2004,2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * http://www.fluff.org/ben/smdk2440/
- *
- * Thanks to Dimity Andric and TomTom for the loan of an 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/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-//#include <asm/debug-ll.h>
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-lcd.h>
-
-#include <asm/arch/idle.h>
-#include <asm/arch/fb.h>
-
-#include "s3c2410.h"
-#include "s3c2440.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-
-#include "common-smdk.h"
-
-static struct map_desc smdk2440_iodesc[] __initdata = {
-	/* ISA IO Space map (memory space selected by A24) */
-
-	{
-		.virtual	= (u32)S3C24XX_VA_ISA_WORD,
-		.pfn		= __phys_to_pfn(S3C2410_CS2),
-		.length		= 0x10000,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (u32)S3C24XX_VA_ISA_WORD + 0x10000,
-		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
-		.length		= SZ_4M,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
-		.pfn		= __phys_to_pfn(S3C2410_CS2),
-		.length		= 0x10000,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
-		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
-		.length		= SZ_4M,
-		.type		= MT_DEVICE,
-	}
-};
-
-#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
-#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
-#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
-
-static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	},
-	/* IR port */
-	[2] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x43,
-		.ufcon	     = 0x51,
-	}
-};
-
-/* LCD driver info */
-
-static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {
-	.regs	= {
-
-		.lcdcon1	= S3C2410_LCDCON1_TFT16BPP |
-				  S3C2410_LCDCON1_TFT |
-				  S3C2410_LCDCON1_CLKVAL(0x04),
-
-		.lcdcon2	= S3C2410_LCDCON2_VBPD(7) |
-				  S3C2410_LCDCON2_LINEVAL(319) |
-				  S3C2410_LCDCON2_VFPD(6) |
-				  S3C2410_LCDCON2_VSPW(3),
-
-		.lcdcon3	= S3C2410_LCDCON3_HBPD(19) |
-				  S3C2410_LCDCON3_HOZVAL(239) |
-				  S3C2410_LCDCON3_HFPD(7),
-
-		.lcdcon4	= S3C2410_LCDCON4_MVAL(0) |
-				  S3C2410_LCDCON4_HSPW(3),
-
-		.lcdcon5	= S3C2410_LCDCON5_FRM565 |
-				  S3C2410_LCDCON5_INVVLINE |
-				  S3C2410_LCDCON5_INVVFRAME |
-				  S3C2410_LCDCON5_PWREN |
-				  S3C2410_LCDCON5_HWSWP,
-	},
-
-#if 0
-	/* currently setup by downloader */
-	.gpccon		= 0xaa940659,
-	.gpccon_mask	= 0xffffffff,
-	.gpcup		= 0x0000ffff,
-	.gpcup_mask	= 0xffffffff,
-	.gpdcon		= 0xaa84aaa0,
-	.gpdcon_mask	= 0xffffffff,
-	.gpdup		= 0x0000faff,
-	.gpdup_mask	= 0xffffffff,
-#endif
-
-	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
-
-	.width		= 240,
-	.height		= 320,
-
-	.xres		= {
-		.min	= 240,
-		.max	= 240,
-		.defval	= 240,
-	},
-
-	.yres		= {
-		.min	= 320,
-		.max	= 320,
-		.defval = 320,
-	},
-
-	.bpp		= {
-		.min	= 16,
-		.max	= 16,
-		.defval = 16,
-	},
-};
-
-static struct platform_device *smdk2440_devices[] __initdata = {
-	&s3c_device_usb,
-	&s3c_device_lcd,
-	&s3c_device_wdt,
-	&s3c_device_i2c,
-	&s3c_device_iis,
-};
-
-static struct s3c24xx_board smdk2440_board __initdata = {
-	.devices       = smdk2440_devices,
-	.devices_count = ARRAY_SIZE(smdk2440_devices)
-};
-
-static void __init smdk2440_map_io(void)
-{
-	s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
-	s3c24xx_init_clocks(16934400);
-	s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
-	s3c24xx_set_board(&smdk2440_board);
-}
-
-static void __init smdk2440_machine_init(void)
-{
-	s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
-
-	smdk_machine_init();
-}
-
-MACHINE_START(S3C2440, "SMDK2440")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
-
-	.init_irq	= s3c24xx_init_irq,
-	.map_io		= smdk2440_map_io,
-	.init_machine	= smdk2440_machine_init,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index a382fc0..c947c75 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -43,9 +43,9 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/leds-gpio.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 #include "usb-simtec.h"
 
 /* macros for virtual address mods for the io space entries */
diff --git a/arch/arm/mach-s3c2410/mach-vstms.c b/arch/arm/mach-s3c2410/mach-vstms.c
deleted file mode 100644
index 0360e10..0000000
--- a/arch/arm/mach-s3c2410/mach-vstms.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/mach-vstms.c
- *
- * (C) 2006 Thomas Gleixner <tglx@linutronix.de>
- *
- * Derived from mach-smdk2413.c - (C) 2006 Simtec Electronics
- *
- * 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/serial_core.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/hardware/iomd.h>
-#include <asm/setup.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-lcd.h>
-
-#include <asm/arch/idle.h>
-#include <asm/arch/fb.h>
-
-#include <asm/arch/nand.h>
-
-#include "s3c2410.h"
-#include "s3c2412.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-
-
-static struct map_desc vstms_iodesc[] __initdata = {
-};
-
-static struct s3c2410_uartcfg vstms_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	},
-	[2] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	}
-};
-
-static struct mtd_partition vstms_nand_part[] = {
-	[0] = {
-		.name	= "Boot Agent",
-		.size	= 0x7C000,
-		.offset	= 0,
-	},
-	[1] = {
-		.name	= "UBoot Config",
-		.offset = 0x7C000,
-		.size	= 0x4000,
-	},
-	[2] = {
-		.name	= "Kernel",
-		.offset = 0x80000,
-		.size	= 0x200000,
-	},
-	[3] = {
-		.name	= "RFS",
-		.offset	= 0x280000,
-		.size	= 0x3d80000,
-	},
-};
-
-static struct s3c2410_nand_set vstms_nand_sets[] = {
-	[0] = {
-		.name		= "NAND",
-		.nr_chips	= 1,
-		.nr_partitions	= ARRAY_SIZE(vstms_nand_part),
-		.partitions	= vstms_nand_part,
-	},
-};
-
-/* choose a set of timings which should suit most 512Mbit
- * chips and beyond.
-*/
-
-static struct s3c2410_platform_nand vstms_nand_info = {
-	.tacls		= 20,
-	.twrph0		= 60,
-	.twrph1		= 20,
-	.nr_sets	= ARRAY_SIZE(vstms_nand_sets),
-	.sets		= vstms_nand_sets,
-};
-
-static struct platform_device *vstms_devices[] __initdata = {
-	&s3c_device_usb,
-	&s3c_device_wdt,
-	&s3c_device_i2c,
-	&s3c_device_iis,
-	&s3c_device_rtc,
-	&s3c_device_nand,
-};
-
-static struct s3c24xx_board vstms_board __initdata = {
-	.devices       = vstms_devices,
-	.devices_count = ARRAY_SIZE(vstms_devices)
-};
-
-static void __init vstms_fixup(struct machine_desc *desc,
-				  struct tag *tags, char **cmdline,
-				  struct meminfo *mi)
-{
-	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
-		mi->nr_banks=1;
-		mi->bank[0].start = 0x30000000;
-		mi->bank[0].size = SZ_64M;
-		mi->bank[0].node = 0;
-	}
-}
-
-static void __init vstms_map_io(void)
-{
-	s3c_device_nand.dev.platform_data = &vstms_nand_info;
-
-	s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
-	s3c24xx_set_board(&vstms_board);
-}
-
-MACHINE_START(VSTMS, "VSTMS")
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
-
-	.fixup		= vstms_fixup,
-	.init_irq	= s3c24xx_init_irq,
-	.map_io		= vstms_map_io,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/mach-s3c2410/pm-simtec.c
deleted file mode 100644
index 619133e..0000000
--- a/arch/arm/mach-s3c2410/pm-simtec.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/pm-simtec.c
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * http://armlinux.simtec.co.uk/
- *
- * Power Management helpers for Simtec S3C24XX implementations
- *
- * 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/device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/arch/map.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-mem.h>
-
-#include <asm/mach-types.h>
-
-#include "pm.h"
-
-#define COPYRIGHT ", (c) 2005 Simtec Electronics"
-
-/* pm_simtec_init
- *
- * enable the power management functions
-*/
-
-static __init int pm_simtec_init(void)
-{
-	unsigned long gstatus4;
-
-	/* check which machine we are running on */
-
-	if (!machine_is_bast() && !machine_is_vr1000() &&
-	    !machine_is_anubis() && !machine_is_osiris() &&
-	    !machine_is_aml_m5900())
-		return 0;
-
-	printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
-
-	gstatus4  = (__raw_readl(S3C2410_BANKCON7) & 0x3) << 30;
-	gstatus4 |= (__raw_readl(S3C2410_BANKCON6) & 0x3) << 28;
-	gstatus4 |= (__raw_readl(S3C2410_BANKSIZE) & S3C2410_BANKSIZE_MASK);
-
-	__raw_writel(gstatus4, S3C2410_GSTATUS4);
-
-	return s3c2410_pm_init();
-}
-
-arch_initcall(pm_simtec_init);
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index ebf294d..3b3a7db 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -1,11 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/pm.c
  *
- * Copyright (c) 2004,2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C24XX Power Manager (Suspend-To-RAM) support
- *
- * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
+ * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,640 +18,139 @@
  * 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
- *
- * Parts based on arch/arm/mach-pxa/pm.c
- *
- * Thanks to Dimitry Andric for debugging
 */
 
 #include <linux/init.h>
 #include <linux/suspend.h>
 #include <linux/errno.h>
 #include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/crc32.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
+#include <linux/sysdev.h>
 
-#include <asm/cacheflush.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-clock.h>
+#include <asm/mach-types.h>
+
 #include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-irq.h>
+#include <asm/arch/h1940.h>
 
-#include <asm/mach/time.h>
-
-#include "pm.h"
-
-/* for external use */
-
-unsigned long s3c_pm_flags;
-
-#define PFX "s3c24xx-pm: "
-
-static struct sleep_save core_save[] = {
-	SAVE_ITEM(S3C2410_LOCKTIME),
-	SAVE_ITEM(S3C2410_CLKCON),
-
-	/* we restore the timings here, with the proviso that the board
-	 * brings the system up in an slower, or equal frequency setting
-	 * to the original system.
-	 *
-	 * if we cannot guarantee this, then things are going to go very
-	 * wrong here, as we modify the refresh and both pll settings.
-	 */
-
-	SAVE_ITEM(S3C2410_BWSCON),
-	SAVE_ITEM(S3C2410_BANKCON0),
-	SAVE_ITEM(S3C2410_BANKCON1),
-	SAVE_ITEM(S3C2410_BANKCON2),
-	SAVE_ITEM(S3C2410_BANKCON3),
-	SAVE_ITEM(S3C2410_BANKCON4),
-	SAVE_ITEM(S3C2410_BANKCON5),
-
-	SAVE_ITEM(S3C2410_CLKDIVN),
-	SAVE_ITEM(S3C2410_MPLLCON),
-	SAVE_ITEM(S3C2410_UPLLCON),
-	SAVE_ITEM(S3C2410_CLKSLOW),
-	SAVE_ITEM(S3C2410_REFRESH),
-};
-
-static struct sleep_save gpio_save[] = {
-	SAVE_ITEM(S3C2410_GPACON),
-	SAVE_ITEM(S3C2410_GPADAT),
-
-	SAVE_ITEM(S3C2410_GPBCON),
-	SAVE_ITEM(S3C2410_GPBDAT),
-	SAVE_ITEM(S3C2410_GPBUP),
-
-	SAVE_ITEM(S3C2410_GPCCON),
-	SAVE_ITEM(S3C2410_GPCDAT),
-	SAVE_ITEM(S3C2410_GPCUP),
-
-	SAVE_ITEM(S3C2410_GPDCON),
-	SAVE_ITEM(S3C2410_GPDDAT),
-	SAVE_ITEM(S3C2410_GPDUP),
-
-	SAVE_ITEM(S3C2410_GPECON),
-	SAVE_ITEM(S3C2410_GPEDAT),
-	SAVE_ITEM(S3C2410_GPEUP),
-
-	SAVE_ITEM(S3C2410_GPFCON),
-	SAVE_ITEM(S3C2410_GPFDAT),
-	SAVE_ITEM(S3C2410_GPFUP),
-
-	SAVE_ITEM(S3C2410_GPGCON),
-	SAVE_ITEM(S3C2410_GPGDAT),
-	SAVE_ITEM(S3C2410_GPGUP),
-
-	SAVE_ITEM(S3C2410_GPHCON),
-	SAVE_ITEM(S3C2410_GPHDAT),
-	SAVE_ITEM(S3C2410_GPHUP),
-
-	SAVE_ITEM(S3C2410_DCLKCON),
-};
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 #ifdef CONFIG_S3C2410_PM_DEBUG
-
-#define SAVE_UART(va) \
-	SAVE_ITEM((va) + S3C2410_ULCON), \
-	SAVE_ITEM((va) + S3C2410_UCON), \
-	SAVE_ITEM((va) + S3C2410_UFCON), \
-	SAVE_ITEM((va) + S3C2410_UMCON), \
-	SAVE_ITEM((va) + S3C2410_UBRDIV)
-
-static struct sleep_save uart_save[] = {
-	SAVE_UART(S3C24XX_VA_UART0),
-	SAVE_UART(S3C24XX_VA_UART1),
-#ifndef CONFIG_CPU_S3C2400
-	SAVE_UART(S3C24XX_VA_UART2),
-#endif
-};
-
-/* debug
- *
- * we send the debug to printascii() to allow it to be seen if the
- * system never wakes up from the sleep
-*/
-
-extern void printascii(const char *);
-
-void pm_dbg(const char *fmt, ...)
-{
-	va_list va;
-	char buff[256];
-
-	va_start(va, fmt);
-	vsprintf(buff, fmt, va);
-	va_end(va);
-
-	printascii(buff);
-}
-
-static void s3c2410_pm_debug_init(void)
-{
-	unsigned long tmp = __raw_readl(S3C2410_CLKCON);
-
-	/* re-start uart clocks */
-	tmp |= S3C2410_CLKCON_UART0;
-	tmp |= S3C2410_CLKCON_UART1;
-	tmp |= S3C2410_CLKCON_UART2;
-
-	__raw_writel(tmp, S3C2410_CLKCON);
-	udelay(10);
-}
-
+extern void pm_dbg(const char *fmt, ...);
 #define DBG(fmt...) pm_dbg(fmt)
 #else
 #define DBG(fmt...) printk(KERN_DEBUG fmt)
-
-#define s3c2410_pm_debug_init() do { } while(0)
-
-static struct sleep_save uart_save[] = {};
 #endif
 
-#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
-
-/* suspend checking code...
- *
- * this next area does a set of crc checks over all the installed
- * memory, so the system can verify if the resume was ok.
- *
- * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
- * increasing it will mean that the area corrupted will be less easy to spot,
- * and reducing the size will cause the CRC save area to grow
-*/
-
-#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
-
-static u32 crc_size;	/* size needed for the crc block */
-static u32 *crcs;	/* allocated over suspend/resume */
-
-typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
-
-/* s3c2410_pm_run_res
- *
- * go thorugh the given resource list, and look for system ram
-*/
-
-static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
+static void s3c2410_pm_prepare(void)
 {
-	while (ptr != NULL) {
-		if (ptr->child != NULL)
-			s3c2410_pm_run_res(ptr->child, fn, arg);
+	/* ensure at least GSTATUS3 has the resume address */
 
-		if ((ptr->flags & IORESOURCE_MEM) &&
-		    strcmp(ptr->name, "System RAM") == 0) {
-			DBG("Found system RAM at %08lx..%08lx\n",
-			    ptr->start, ptr->end);
-			arg = (fn)(ptr, arg);
-		}
+	__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
 
-		ptr = ptr->sibling;
-	}
-}
+	DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
+	DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
 
-static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
-{
-	s3c2410_pm_run_res(&iomem_resource, fn, arg);
-}
+	if (machine_is_h1940()) {
+		void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+		unsigned long ptr;
+		unsigned long calc = 0;
 
-static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
-{
-	u32 size = (u32)(res->end - res->start)+1;
+		/* generate check for the bootloader to check on resume */
 
-	size += CHECK_CHUNKSIZE-1;
-	size /= CHECK_CHUNKSIZE;
+		for (ptr = 0; ptr < 0x40000; ptr += 0x400)
+			calc += __raw_readl(base+ptr);
 
-	DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
-
-	*val += size * sizeof(u32);
-	return val;
-}
-
-/* s3c2410_pm_prepare_check
- *
- * prepare the necessary information for creating the CRCs. This
- * must be done before the final save, as it will require memory
- * allocating, and thus touching bits of the kernel we do not
- * know about.
-*/
-
-static void s3c2410_pm_check_prepare(void)
-{
-	crc_size = 0;
-
-	s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
-
-	DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
-
-	crcs = kmalloc(crc_size+4, GFP_KERNEL);
-	if (crcs == NULL)
-		printk(KERN_ERR "Cannot allocated CRC save area\n");
-}
-
-static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
-{
-	unsigned long addr, left;
-
-	for (addr = res->start; addr < res->end;
-	     addr += CHECK_CHUNKSIZE) {
-		left = res->end - addr;
-
-		if (left > CHECK_CHUNKSIZE)
-			left = CHECK_CHUNKSIZE;
-
-		*val = crc32_le(~0, phys_to_virt(addr), left);
-		val++;
+		__raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
 	}
 
-	return val;
+	/* the RX3715 uses similar code and the same H1940 and the
+	 * same offsets for resume and checksum pointers */
+
+	if (machine_is_rx3715()) {
+		void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+		unsigned long ptr;
+		unsigned long calc = 0;
+
+		/* generate check for the bootloader to check on resume */
+
+		for (ptr = 0; ptr < 0x40000; ptr += 0x4)
+			calc += __raw_readl(base+ptr);
+
+		__raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
+	}
+
+	if ( machine_is_aml_m5900() )
+		s3c2410_gpio_setpin(S3C2410_GPF2, 1);
+
 }
 
-/* s3c2410_pm_check_store
- *
- * compute the CRC values for the memory blocks before the final
- * sleep.
-*/
-
-static void s3c2410_pm_check_store(void)
+static int s3c2410_pm_resume(struct sys_device *dev)
 {
-	if (crcs != NULL)
-		s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
-}
+	unsigned long tmp;
 
-/* in_region
- *
- * return TRUE if the area defined by ptr..ptr+size contatins the
- * what..what+whatsz
-*/
+	/* unset the return-from-sleep flag, to ensure reset */
 
-static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
-{
-	if ((what+whatsz) < ptr)
-		return 0;
+	tmp = __raw_readl(S3C2410_GSTATUS2);
+	tmp &= S3C2410_GSTATUS2_OFFRESET;
+	__raw_writel(tmp, S3C2410_GSTATUS2);
 
-	if (what > (ptr+size))
-		return 0;
-
-	return 1;
-}
-
-static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
-{
-	void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
-	unsigned long addr;
-	unsigned long left;
-	void *ptr;
-	u32 calc;
-
-	for (addr = res->start; addr < res->end;
-	     addr += CHECK_CHUNKSIZE) {
-		left = res->end - addr;
-
-		if (left > CHECK_CHUNKSIZE)
-			left = CHECK_CHUNKSIZE;
-
-		ptr = phys_to_virt(addr);
-
-		if (in_region(ptr, left, crcs, crc_size)) {
-			DBG("skipping %08lx, has crc block in\n", addr);
-			goto skip_check;
-		}
-
-		if (in_region(ptr, left, save_at, 32*4 )) {
-			DBG("skipping %08lx, has save block in\n", addr);
-			goto skip_check;
-		}
-
-		/* calculate and check the checksum */
-
-		calc = crc32_le(~0, ptr, left);
-		if (calc != *val) {
-			printk(KERN_ERR PFX "Restore CRC error at "
-			       "%08lx (%08x vs %08x)\n", addr, calc, *val);
-
-			DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
-			    addr, calc, *val);
-		}
-
-	skip_check:
-		val++;
-	}
-
-	return val;
-}
-
-/* s3c2410_pm_check_restore
- *
- * check the CRCs after the restore event and free the memory used
- * to hold them
-*/
-
-static void s3c2410_pm_check_restore(void)
-{
-	if (crcs != NULL) {
-		s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
-		kfree(crcs);
-		crcs = NULL;
-	}
-}
-
-#else
-
-#define s3c2410_pm_check_prepare() do { } while(0)
-#define s3c2410_pm_check_restore() do { } while(0)
-#define s3c2410_pm_check_store()   do { } while(0)
-#endif
-
-/* helper functions to save and restore register state */
-
-void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		ptr->val = __raw_readl(ptr->reg);
-		DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
-	}
-}
-
-/* s3c2410_pm_do_restore
- *
- * restore the system from the given list of saved registers
- *
- * Note, we do not use DBG() in here, as the system may not have
- * restore the UARTs state yet
-*/
-
-void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
-		       ptr->reg, ptr->val, __raw_readl(ptr->reg));
-
-		__raw_writel(ptr->val, ptr->reg);
-	}
-}
-
-/* s3c2410_pm_do_restore_core
- *
- * similar to s3c2410_pm_do_restore_core
- *
- * WARNING: Do not put any debug in here that may effect memory or use
- * peripherals, as things may be changing!
-*/
-
-static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		__raw_writel(ptr->val, ptr->reg);
-	}
-}
-
-/* s3c2410_pm_show_resume_irqs
- *
- * print any IRQs asserted at resume time (ie, we woke from)
-*/
-
-static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
-					unsigned long mask)
-{
-	int i;
-
-	which &= ~mask;
-
-	for (i = 0; i <= 31; i++) {
-		if ((which) & (1L<<i)) {
-			DBG("IRQ %d asserted at resume\n", start+i);
-		}
-	}
-}
-
-/* s3c2410_pm_check_resume_pin
- *
- * check to see if the pin is configured correctly for sleep mode, and
- * make any necessary adjustments if it is not
-*/
-
-static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
-{
-	unsigned long irqstate;
-	unsigned long pinstate;
-	int irq = s3c2410_gpio_getirq(pin);
-
-	if (irqoffs < 4)
-		irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
-	else
-		irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
-
-	pinstate = s3c2410_gpio_getcfg(pin);
-
-	if (!irqstate) {
-		if (pinstate == S3C2410_GPIO_IRQ)
-			DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
-	} else {
-		if (pinstate == S3C2410_GPIO_IRQ) {
-			DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
-			s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
-		}
-	}
-}
-
-/* s3c2410_pm_configure_extint
- *
- * configure all external interrupt pins
-*/
-
-static void s3c2410_pm_configure_extint(void)
-{
-	int pin;
-
-	/* for each of the external interrupts (EINT0..EINT15) we
-	 * need to check wether it is an external interrupt source,
-	 * and then configure it as an input if it is not
-	*/
-
-	for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
-		s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
-	}
-
-	for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
-		s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
-	}
-}
-
-void (*pm_cpu_prep)(void);
-void (*pm_cpu_sleep)(void);
-
-#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
-
-/* s3c2410_pm_enter
- *
- * central control for sleep/resume process
-*/
-
-static int s3c2410_pm_enter(suspend_state_t state)
-{
-	unsigned long regs_save[16];
-
-	/* ensure the debug is initialised (if enabled) */
-
-	s3c2410_pm_debug_init();
-
-	DBG("s3c2410_pm_enter(%d)\n", state);
-
-	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
-		printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
-		return -EINVAL;
-	}
-
-	if (state != PM_SUSPEND_MEM) {
-		printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
-		return -EINVAL;
-	}
-
-	/* check if we have anything to wake-up with... bad things seem
-	 * to happen if you suspend with no wakeup (system will often
-	 * require a full power-cycle)
-	*/
-
-	if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
-	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
-		printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
-		printk(KERN_ERR PFX "Aborting sleep\n");
-		return -EINVAL;
-	}
-
-	/* prepare check area if configured */
-
-	s3c2410_pm_check_prepare();
-
-	/* store the physical address of the register recovery block */
-
-	s3c2410_sleep_save_phys = virt_to_phys(regs_save);
-
-	DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
-
-	/* save all necessary core registers not covered by the drivers */
-
-	s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
-	s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
-	s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
-
-	/* set the irq configuration for wake */
-
-	s3c2410_pm_configure_extint();
-
-	DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
-	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
-
-	__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
-	__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
-
-	/* ack any outstanding external interrupts before we go to sleep */
-
-	__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
-	__raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
-	__raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
-
-	/* call cpu specific preperation */
-
-	pm_cpu_prep();
-
-	/* flush cache back to ram */
-
-	flush_cache_all();
-
-	s3c2410_pm_check_store();
-
-	/* send the cpu to sleep... */
-
-	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
-
-	/* s3c2410_cpu_save will also act as our return point from when
-	 * we resume as it saves its own register state, so use the return
-	 * code to differentiate return from save and return from sleep */
-
-	if (s3c2410_cpu_save(regs_save) == 0) {
-		flush_cache_all();
-		pm_cpu_sleep();
-	}
-
-	/* restore the cpu state */
-
-	cpu_init();
-
-	/* restore the system state */
-
-	s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
-	s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
-	s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
-
-	s3c2410_pm_debug_init();
-
-	/* check what irq (if any) restored the system */
-
-	DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
-	    __raw_readl(S3C2410_SRCPND),
-	    __raw_readl(S3C2410_EINTPEND));
-
-	s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
-				    s3c_irqwake_intmask);
-
-	s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
-				    s3c_irqwake_eintmask);
-
-	DBG("post sleep, preparing to return\n");
-
-	s3c2410_pm_check_restore();
-
-	/* ok, let's return from sleep */
+	if ( machine_is_aml_m5900() )
+		s3c2410_gpio_setpin(S3C2410_GPF2, 0);
 
-	DBG("S3C2410 PM Resume (post-restore)\n");
 	return 0;
 }
 
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-static int s3c2410_pm_prepare(suspend_state_t state)
+static int s3c2410_pm_add(struct sys_device *dev)
 {
+	pm_cpu_prep = s3c2410_pm_prepare;
+	pm_cpu_sleep = s3c2410_cpu_suspend;
+
 	return 0;
 }
 
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-static int s3c2410_pm_finish(suspend_state_t state)
-{
-	return 0;
-}
-
-/*
- * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
- */
-static struct pm_ops s3c2410_pm_ops = {
-	.pm_disk_mode	= PM_DISK_FIRMWARE,
-	.prepare	= s3c2410_pm_prepare,
-	.enter		= s3c2410_pm_enter,
-	.finish		= s3c2410_pm_finish,
+#if defined(CONFIG_CPU_S3C2410)
+static struct sysdev_driver s3c2410_pm_driver = {
+	.add		= s3c2410_pm_add,
+	.resume		= s3c2410_pm_resume,
 };
 
-/* s3c2410_pm_init
- *
- * Attach the power management functions. This should be called
- * from the board specific initialisation if the board supports
- * it.
-*/
+/* register ourselves */
 
-int __init s3c2410_pm_init(void)
+static int __init s3c2410_pm_drvinit(void)
 {
-	printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
-
-	pm_set_ops(&s3c2410_pm_ops);
-	return 0;
+	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
 }
+
+arch_initcall(s3c2410_pm_drvinit);
+#endif
+
+#if defined(CONFIG_CPU_S3C2440)
+static struct sysdev_driver s3c2440_pm_driver = {
+	.add		= s3c2410_pm_add,
+	.resume		= s3c2410_pm_resume,
+};
+
+static int __init s3c2440_pm_drvinit(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
+}
+
+arch_initcall(s3c2440_pm_drvinit);
+#endif
+
+#if defined(CONFIG_CPU_S3C2442)
+static struct sysdev_driver s3c2442_pm_driver = {
+	.add		= s3c2410_pm_add,
+	.resume		= s3c2410_pm_resume,
+};
+
+static int __init s3c2442_pm_drvinit(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
+}
+
+arch_initcall(s3c2442_pm_drvinit);
+#endif
diff --git a/arch/arm/mach-s3c2410/pm.h b/arch/arm/mach-s3c2410/pm.h
deleted file mode 100644
index ffe197a..0000000
--- a/arch/arm/mach-s3c2410/pm.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/pm.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Written by Ben Dooks, <ben@simtec.co.uk>
- *
- * 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.
-*/
-
-/* s3c2410_pm_init
- *
- * called from board at initialisation time to setup the power
- * management
-*/
-
-#ifdef CONFIG_PM
-
-extern __init int s3c2410_pm_init(void);
-
-#else
-
-static inline int s3c2410_pm_init(void)
-{
-	return 0;
-}
-#endif
-
-/* configuration for the IRQ mask over sleep */
-extern unsigned long s3c_irqwake_intmask;
-extern unsigned long s3c_irqwake_eintmask;
-
-/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
-extern unsigned long s3c_irqwake_intallow;
-extern unsigned long s3c_irqwake_eintallow;
-
-/* per-cpu sleep functions */
-
-extern void (*pm_cpu_prep)(void);
-extern void (*pm_cpu_sleep)(void);
-
-/* Flags for PM Control */
-
-extern unsigned long s3c_pm_flags;
-
-/* from sleep.S */
-
-extern int  s3c2410_cpu_save(unsigned long *saveblk);
-extern void s3c2410_cpu_suspend(void);
-extern void s3c2410_cpu_resume(void);
-
-extern unsigned long s3c2410_sleep_save_phys;
-
-/* sleep save info */
-
-struct sleep_save {
-	void __iomem	*reg;
-	unsigned long	val;
-};
-
-#define SAVE_ITEM(x) \
-	{ .reg = (x) }
-
-extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
-extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
-
-#ifdef CONFIG_PM
-extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
-extern int s3c24xx_irq_resume(struct sys_device *dev);
-#else
-#define s3c24xx_irq_suspend NULL
-#define s3c24xx_irq_resume  NULL
-#endif
diff --git a/arch/arm/mach-s3c2410/s3c2400-gpio.c b/arch/arm/mach-s3c2410/s3c2400-gpio.c
deleted file mode 100644
index 1576d01..0000000
--- a/arch/arm/mach-s3c2410/s3c2400-gpio.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2400-gpio.c
- *
- * Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org>
- *
- * S3C2400 GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-gpio.h>
-
-int s3c2400_gpio_getirq(unsigned int pin)
-{
-	if (pin < S3C2410_GPE0 || pin > S3C2400_GPE7_EINT7)
-		return -1;  /* not valid interrupts */
-
-	return (pin - S3C2410_GPE0) + IRQ_EINT0;
-}
-
-EXPORT_SYMBOL(s3c2400_gpio_getirq);
diff --git a/arch/arm/mach-s3c2410/s3c2400.h b/arch/arm/mach-s3c2410/s3c2400.h
deleted file mode 100644
index 8b2394e..0000000
--- a/arch/arm/mach-s3c2410/s3c2400.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* arch/arm/mach-s3c2410/s3c2400.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C2400 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Modifications:
- *     09-Fev-2006 LCVR  First version, based on s3c2410.h
-*/
-
-#ifdef CONFIG_CPU_S3C2400
-
-extern  int s3c2400_init(void);
-
-extern void s3c2400_map_io(struct map_desc *mach_desc, int size);
-
-extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2400_init_clocks(int xtal);
-
-#else
-#define s3c2400_init_clocks NULL
-#define s3c2400_init_uarts NULL
-#define s3c2400_map_io NULL
-#define s3c2400_init NULL
-#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c
deleted file mode 100644
index 992cc6a..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-clock.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-clock.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410,S3C2440,S3C2442 Clock control support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/sysdev.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
-
-#include <asm/mach/map.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "s3c2410.h"
-#include "clock.h"
-#include "cpu.h"
-
-int s3c2410_clkcon_enable(struct clk *clk, int enable)
-{
-	unsigned int clocks = clk->ctrlbit;
-	unsigned long clkcon;
-
-	clkcon = __raw_readl(S3C2410_CLKCON);
-
-	if (enable)
-		clkcon |= clocks;
-	else
-		clkcon &= ~clocks;
-
-	/* ensure none of the special function bits set */
-	clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
-
-	__raw_writel(clkcon, S3C2410_CLKCON);
-
-	return 0;
-}
-
-static int s3c2410_upll_enable(struct clk *clk, int enable)
-{
-	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
-	unsigned long orig = clkslow;
-
-	if (enable)
-		clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
-	else
-		clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
-
-	__raw_writel(clkslow, S3C2410_CLKSLOW);
-
-	/* if we started the UPLL, then allow to settle */
-
-	if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
-		udelay(200);
-
-	return 0;
-}
-
-/* standard clock definitions */
-
-static struct clk init_clocks_disable[] = {
-	{
-		.name		= "nand",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_NAND,
-	}, {
-		.name		= "sdi",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_SDI,
-	}, {
-		.name		= "adc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_ADC,
-	}, {
-		.name		= "i2c",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_IIC,
-	}, {
-		.name		= "iis",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_IIS,
-	}, {
-		.name		= "spi",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_SPI,
-	}
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "lcd",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_LCDC,
-	}, {
-		.name		= "gpio",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_GPIO,
-	}, {
-		.name		= "usb-host",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_USBH,
-	}, {
-		.name		= "usb-device",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_USBD,
-	}, {
-		.name		= "timers",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_PWMT,
-	}, {
-		.name		= "uart",
-		.id		= 0,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART0,
-	}, {
-		.name		= "uart",
-		.id		= 1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART1,
-	}, {
-		.name		= "uart",
-		.id		= 2,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART2,
-	}, {
-		.name		= "rtc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_RTC,
-	}, {
-		.name		= "watchdog",
-		.id		= -1,
-		.parent		= &clk_p,
-		.ctrlbit	= 0,
-	}, {
-		.name		= "usb-bus-host",
-		.id		= -1,
-		.parent		= &clk_usb_bus,
-	}, {
-		.name		= "usb-bus-gadget",
-		.id		= -1,
-		.parent		= &clk_usb_bus,
-	},
-};
-
-/* s3c2410_baseclk_add()
- *
- * Add all the clocks used by the s3c2410 or compatible CPUs
- * such as the S3C2440 and S3C2442.
- *
- * We cannot use a system device as we are needed before any
- * of the init-calls that initialise the devices are actually
- * done.
-*/
-
-int __init s3c2410_baseclk_add(void)
-{
-	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
-	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
-	struct clk *clkp;
-	struct clk *xtal;
-	int ret;
-	int ptr;
-
-	clk_upll.enable = s3c2410_upll_enable;
-
-	if (s3c24xx_register_clock(&clk_usb_bus) < 0)
-		printk(KERN_ERR "failed to register usb bus clock\n");
-
-	/* register clocks from clock array */
-
-	clkp = init_clocks;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
-		/* ensure that we note the clock state */
-
-		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-
-	/* We must be careful disabling the clocks we are not intending to
-	 * be using at boot time, as subsytems such as the LCD which do
-	 * their own DMA requests to the bus can cause the system to lockup
-	 * if they where in the middle of requesting bus access.
-	 *
-	 * Disabling the LCD clock if the LCD is active is very dangerous,
-	 * and therefore the bootloader should be careful to not enable
-	 * the LCD clock if it is not needed.
-	*/
-
-	/* install (and disable) the clocks we do not need immediately */
-
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-
-		s3c2410_clkcon_enable(clkp, 0);
-	}
-
-	/* show the clock-slow value */
-
-	xtal = clk_get(NULL, "xtal");
-
-	printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
-	       print_mhz(clk_get_rate(xtal) /
-			 ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
-	       (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
-	       (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
-	       (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
-
-	return 0;
-}
diff --git a/arch/arm/mach-s3c2410/s3c2410-dma.c b/arch/arm/mach-s3c2410/s3c2410-dma.c
deleted file mode 100644
index e67ba39..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-dma.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-dma.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 DMA selection
- *
- * http://armlinux.simtec.co.uk/
- *
- * 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/sysdev.h>
-#include <linux/serial_core.h>
-
-#include <asm/dma.h>
-#include <asm/arch/dma.h>
-#include "dma.h"
-
-#include "cpu.h"
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-ac97.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-lcd.h>
-#include <asm/arch/regs-sdi.h>
-#include <asm/arch/regs-iis.h>
-#include <asm/arch/regs-spi.h>
-
-static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
-	[DMACH_XD0] = {
-		.name		= "xdreq0",
-		.channels[0]	= S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
-	},
-	[DMACH_XD1] = {
-		.name		= "xdreq1",
-		.channels[1]	= S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
-	},
-	[DMACH_SDI] = {
-		.name		= "sdi",
-		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
-		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
-		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_SPI0] = {
-		.name		= "spi0",
-		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
-	},
-	[DMACH_SPI1] = {
-		.name		= "spi1",
-		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
-	},
-	[DMACH_UART0] = {
-		.name		= "uart0",
-		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
-	},
-	[DMACH_UART1] = {
-		.name		= "uart1",
-		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
-	},
-      	[DMACH_UART2] = {
-		.name		= "uart2",
-		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
-	},
-	[DMACH_TIMER] = {
-		.name		= "timer",
-		.channels[0]	= S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
-		.channels[2]	= S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
-		.channels[3]	= S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
-	},
-	[DMACH_I2S_IN] = {
-		.name		= "i2s-sdi",
-		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
-		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_I2S_OUT] = {
-		.name		= "i2s-sdo",
-		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_USB_EP1] = {
-		.name		= "usb-ep1",
-		.channels[0]	= S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
-	},
-	[DMACH_USB_EP2] = {
-		.name		= "usb-ep2",
-		.channels[1]	= S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
-	},
-	[DMACH_USB_EP3] = {
-		.name		= "usb-ep3",
-		.channels[2]	= S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
-	},
-	[DMACH_USB_EP4] = {
-		.name		= "usb-ep4",
-		.channels[3]	=S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
-	},
-};
-
-static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
-			       struct s3c24xx_dma_map *map)
-{
-	chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
-}
-
-static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
-	.select		= s3c2410_dma_select,
-	.dcon_mask	= 7 << 24,
-	.map		= s3c2410_dma_mappings,
-	.map_size	= ARRAY_SIZE(s3c2410_dma_mappings),
-};
-
-static int s3c2410_dma_add(struct sys_device *sysdev)
-{
-	return s3c24xx_dma_init_map(&s3c2410_dma_sel);
-}
-
-#if defined(CONFIG_CPU_S3C2410)
-static struct sysdev_driver s3c2410_dma_driver = {
-	.add	= s3c2410_dma_add,
-};
-
-static int __init s3c2410_dma_init(void)
-{
-	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
-}
-
-arch_initcall(s3c2410_dma_init);
-#endif
-
-#if defined(CONFIG_CPU_S3C2442)
-/* S3C2442 DMA contains the same selection table as the S3C2410 */
-static struct sysdev_driver s3c2442_dma_driver = {
-	.add	= s3c2410_dma_add,
-};
-
-static int __init s3c2442_dma_init(void)
-{
-	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
-}
-
-arch_initcall(s3c2442_dma_init);
-#endif
-
diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c
deleted file mode 100644
index ec3a276..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-gpio.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-gpio.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-gpio.h>
-
-int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-			   unsigned int config)
-{
-	void __iomem *reg = S3C24XX_EINFLT0;
-	unsigned long flags;
-	unsigned long val;
-
-	if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
-		return -1;
-
-	config &= 0xff;
-
-	pin -= S3C2410_GPG8;
-	reg += pin & ~3;
-
-	local_irq_save(flags);
-
-	/* update filter width and clock source */
-
-	val = __raw_readl(reg);
-	val &= ~(0xff << ((pin & 3) * 8));
-	val |= config << ((pin & 3) * 8);
-	__raw_writel(val, reg);
-
-	/* update filter enable */
-
-	val = __raw_readl(S3C24XX_EXTINT2);
-	val &= ~(1 << ((pin * 4) + 3));
-	val |= on << ((pin * 4) + 3);
-	__raw_writel(val, S3C24XX_EXTINT2);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/s3c2410-irq.c b/arch/arm/mach-s3c2410/s3c2410-irq.c
deleted file mode 100644
index c796c9c..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-irq.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-irq.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * 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/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-
-#include "cpu.h"
-#include "pm.h"
-
-static int s3c2410_irq_add(struct sys_device *sysdev)
-{
-	return 0;
-}
-
-static struct sysdev_driver s3c2410_irq_driver = {
-	.add		= s3c2410_irq_add,
-	.suspend	= s3c24xx_irq_suspend,
-	.resume		= s3c24xx_irq_resume,
-};
-
-static int s3c2410_irq_init(void)
-{
-	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
-}
-
-arch_initcall(s3c2410_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c2410-pm.c b/arch/arm/mach-s3c2410/s3c2410-pm.c
deleted file mode 100644
index 8bb6e5e..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-pm.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-pm.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/suspend.h>
-#include <linux/errno.h>
-#include <linux/time.h>
-#include <linux/sysdev.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/h1940.h>
-
-#include "cpu.h"
-#include "pm.h"
-
-#ifdef CONFIG_S3C2410_PM_DEBUG
-extern void pm_dbg(const char *fmt, ...);
-#define DBG(fmt...) pm_dbg(fmt)
-#else
-#define DBG(fmt...) printk(KERN_DEBUG fmt)
-#endif
-
-static void s3c2410_pm_prepare(void)
-{
-	/* ensure at least GSTATUS3 has the resume address */
-
-	__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
-
-	DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
-	DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
-
-	if (machine_is_h1940()) {
-		void *base = phys_to_virt(H1940_SUSPEND_CHECK);
-		unsigned long ptr;
-		unsigned long calc = 0;
-
-		/* generate check for the bootloader to check on resume */
-
-		for (ptr = 0; ptr < 0x40000; ptr += 0x400)
-			calc += __raw_readl(base+ptr);
-
-		__raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
-	}
-
-	/* the RX3715 uses similar code and the same H1940 and the
-	 * same offsets for resume and checksum pointers */
-
-	if (machine_is_rx3715()) {
-		void *base = phys_to_virt(H1940_SUSPEND_CHECK);
-		unsigned long ptr;
-		unsigned long calc = 0;
-
-		/* generate check for the bootloader to check on resume */
-
-		for (ptr = 0; ptr < 0x40000; ptr += 0x4)
-			calc += __raw_readl(base+ptr);
-
-		__raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
-	}
-
-	if ( machine_is_aml_m5900() )
-		s3c2410_gpio_setpin(S3C2410_GPF2, 1);
-
-}
-
-static int s3c2410_pm_resume(struct sys_device *dev)
-{
-	unsigned long tmp;
-
-	/* unset the return-from-sleep flag, to ensure reset */
-
-	tmp = __raw_readl(S3C2410_GSTATUS2);
-	tmp &= S3C2410_GSTATUS2_OFFRESET;
-	__raw_writel(tmp, S3C2410_GSTATUS2);
-
-	if ( machine_is_aml_m5900() )
-		s3c2410_gpio_setpin(S3C2410_GPF2, 0);
-
-	return 0;
-}
-
-static int s3c2410_pm_add(struct sys_device *dev)
-{
-	pm_cpu_prep = s3c2410_pm_prepare;
-	pm_cpu_sleep = s3c2410_cpu_suspend;
-
-	return 0;
-}
-
-#if defined(CONFIG_CPU_S3C2410)
-static struct sysdev_driver s3c2410_pm_driver = {
-	.add		= s3c2410_pm_add,
-	.resume		= s3c2410_pm_resume,
-};
-
-/* register ourselves */
-
-static int __init s3c2410_pm_drvinit(void)
-{
-	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
-}
-
-arch_initcall(s3c2410_pm_drvinit);
-#endif
-
-#if defined(CONFIG_CPU_S3C2440)
-static struct sysdev_driver s3c2440_pm_driver = {
-	.add		= s3c2410_pm_add,
-	.resume		= s3c2410_pm_resume,
-};
-
-static int __init s3c2440_pm_drvinit(void)
-{
-	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
-}
-
-arch_initcall(s3c2440_pm_drvinit);
-#endif
-
-#if defined(CONFIG_CPU_S3C2442)
-static struct sysdev_driver s3c2442_pm_driver = {
-	.add		= s3c2410_pm_add,
-	.resume		= s3c2410_pm_resume,
-};
-
-static int __init s3c2442_pm_drvinit(void)
-{
-	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
-}
-
-arch_initcall(s3c2442_pm_drvinit);
-#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-sleep.S b/arch/arm/mach-s3c2410/s3c2410-sleep.S
deleted file mode 100644
index 9179a10..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-sleep.S
+++ /dev/null
@@ -1,68 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 Power Manager (Suspend-To-RAM) support
- *
- * Based on PXA/SA1100 sleep code by:
- *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
- *	Cliff Brake, (c) 2001
- *
- * 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/linkage.h>
-#include <asm/assembler.h>
-#include <asm/hardware.h>
-#include <asm/arch/map.h>
-
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-serial.h>
-
-	/* s3c2410_cpu_suspend
-	 *
-	 * put the cpu into sleep mode
-	*/
-
-ENTRY(s3c2410_cpu_suspend)
-	@@ prepare cpu to sleep
-
-	ldr	r4, =S3C2410_REFRESH
-	ldr	r5, =S3C24XX_MISCCR
-	ldr	r6, =S3C2410_CLKCON
-	ldr	r7, [ r4 ]		@ get REFRESH (and ensure in TLB)
-	ldr	r8, [ r5 ]		@ get MISCCR (and ensure in TLB)
-	ldr	r9, [ r6 ]		@ get CLKCON (and ensure in TLB)
-
-	orr	r7, r7, #S3C2410_REFRESH_SELF	@ SDRAM sleep command
-	orr	r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
-	orr	r9, r9, #S3C2410_CLKCON_POWER	@ power down command
-
-	teq	pc, #0			@ first as a trial-run to load cache
-	bl	s3c2410_do_sleep
-	teq	r0, r0			@ now do it for real
-	b	s3c2410_do_sleep	@
-
-	@@ align next bit of code to cache line
-	.align	8
-s3c2410_do_sleep:
-	streq	r7, [ r4 ]			@ SDRAM sleep command
-	streq	r8, [ r5 ]			@ SDRAM power-down config
-	streq	r9, [ r6 ]			@ CPU sleep
-1:	beq	1b
-	mov	pc, r14
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index 4cdc0d7..1a86a98 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -31,10 +31,10 @@
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-serial.h>
 
-#include "s3c2410.h"
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
 
 /* Initial IO mappings */
 
@@ -110,7 +110,7 @@
 
 /* need to register class before we actually register the device, and
  * we also need to ensure that it has been initialised before any of the
- * drivers even try to use it (even if not on an s3c2440 based system)
+ * drivers even try to use it (even if not on an s3c2410 based system)
  * as a driver which may support both 2410 and 2440 may try and use it.
 */
 
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
deleted file mode 100644
index fbed084..0000000
--- a/arch/arm/mach-s3c2410/s3c2410.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* arch/arm/mach-s3c2410/s3c2410.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2410 machine directory
- *
- * 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.
- *
-*/
-
-#ifdef CONFIG_CPU_S3C2410
-
-extern  int s3c2410_init(void);
-
-extern void s3c2410_map_io(struct map_desc *mach_desc, int size);
-
-extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2410_init_clocks(int xtal);
-
-extern  int s3c2410_baseclk_add(void);
-
-#else
-#define s3c2410_init_clocks NULL
-#define s3c2410_init_uarts NULL
-#define s3c2410_map_io NULL
-#define s3c2410_init NULL
-#endif
diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2410/s3c2412-clock.c
deleted file mode 100644
index 8f94ad8..0000000
--- a/arch/arm/mach-s3c2410/s3c2412-clock.c
+++ /dev/null
@@ -1,716 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2412,S3C2413 Clock control support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/sysdev.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
-
-#include <asm/mach/map.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "s3c2412.h"
-#include "clock.h"
-#include "cpu.h"
-
-/* We currently have to assume that the system is running
- * from the XTPll input, and that all ***REFCLKs are being
- * fed from it, as we cannot read the state of OM[4] from
- * software.
- *
- * It would be possible for each board initialisation to
- * set the correct muxing at initialisation
-*/
-
-static int s3c2412_clkcon_enable(struct clk *clk, int enable)
-{
-	unsigned int clocks = clk->ctrlbit;
-	unsigned long clkcon;
-
-	clkcon = __raw_readl(S3C2410_CLKCON);
-
-	if (enable)
-		clkcon |= clocks;
-	else
-		clkcon &= ~clocks;
-
-	__raw_writel(clkcon, S3C2410_CLKCON);
-
-	return 0;
-}
-
-static int s3c2412_upll_enable(struct clk *clk, int enable)
-{
-	unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
-	unsigned long orig = upllcon;
-
-	if (!enable)
-		upllcon |= S3C2412_PLLCON_OFF;
-	else
-		upllcon &= ~S3C2412_PLLCON_OFF;
-
-	__raw_writel(upllcon, S3C2410_UPLLCON);
-
-	/* allow ~150uS for the PLL to settle and lock */
-
-	if (enable && (orig & S3C2412_PLLCON_OFF))
-		udelay(150);
-
-	return 0;
-}
-
-/* clock selections */
-
-/* CPU EXTCLK input */
-static struct clk clk_ext = {
-	.name		= "extclk",
-	.id		= -1,
-};
-
-static struct clk clk_erefclk = {
-	.name		= "erefclk",
-	.id		= -1,
-};
-
-static struct clk clk_urefclk = {
-	.name		= "urefclk",
-	.id		= -1,
-};
-
-static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_urefclk)
-		clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL;
-	else if (parent == &clk_upll)
-		clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-
-static struct clk clk_usysclk = {
-	.name		= "usysclk",
-	.id		= -1,
-	.parent		= &clk_xtal,
-	.set_parent	= s3c2412_setparent_usysclk,
-};
-
-static struct clk clk_mrefclk = {
-	.name		= "mrefclk",
-	.parent		= &clk_xtal,
-	.id		= -1,
-};
-
-static struct clk clk_mdivclk = {
-	.name		= "mdivclk",
-	.parent		= &clk_xtal,
-	.id		= -1,
-};
-
-static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_usysclk)
-		clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK;
-	else if (parent == &clk_h)
-		clksrc |= S3C2412_CLKSRC_USBCLK_HCLK;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-
-static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int div;
-
-	if (rate > parent_rate)
-		return parent_rate;
-
-	div = parent_rate / rate;
-	if (div > 2)
-		div = 2;
-
-	return parent_rate / div;
-}
-
-static unsigned long s3c2412_getrate_usbsrc(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
-
-	return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1);
-}
-
-static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
-
-	rate = s3c2412_roundrate_usbsrc(clk, rate);
-
-	if ((parent_rate / rate) == 2)
-		clkdivn |= S3C2412_CLKDIVN_USB48DIV;
-	else
-		clkdivn &= ~S3C2412_CLKDIVN_USB48DIV;
-
-	__raw_writel(clkdivn, S3C2410_CLKDIVN);
-	return 0;
-}
-
-static struct clk clk_usbsrc = {
-	.name		= "usbsrc",
-	.id		= -1,
-	.get_rate	= s3c2412_getrate_usbsrc,
-	.set_rate	= s3c2412_setrate_usbsrc,
-	.round_rate	= s3c2412_roundrate_usbsrc,
-	.set_parent	= s3c2412_setparent_usbsrc,
-};
-
-static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_mdivclk)
-		clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL;
-	else if (parent == &clk_upll)
-		clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-
-static struct clk clk_msysclk = {
-	.name		= "msysclk",
-	.id		= -1,
-	.set_parent	= s3c2412_setparent_msysclk,
-};
-
-/* these next clocks have an divider immediately after them,
- * so we can register them with their divider and leave out the
- * intermediate clock stage
-*/
-static unsigned long s3c2412_roundrate_clksrc(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int div;
-
-	if (rate > parent_rate)
-		return parent_rate;
-
-	/* note, we remove the +/- 1 calculations as they cancel out */
-
-	div = (rate / parent_rate);
-
-	if (div < 1)
-		div = 1;
-	else if (div > 16)
-		div = 16;
-
-	return parent_rate / div;
-}
-
-static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_erefclk)
-		clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL;
-	else if (parent == &clk_mpll)
-		clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-
-static unsigned long s3c2412_getrate_uart(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
-
-	div &= S3C2412_CLKDIVN_UARTDIV_MASK;
-	div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
-
-	rate = s3c2412_roundrate_clksrc(clk, rate);
-
-	clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK;
-	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2410_CLKDIVN);
-	return 0;
-}
-
-static struct clk clk_uart = {
-	.name		= "uartclk",
-	.id		= -1,
-	.get_rate	= s3c2412_getrate_uart,
-	.set_rate	= s3c2412_setrate_uart,
-	.set_parent	= s3c2412_setparent_uart,
-	.round_rate	= s3c2412_roundrate_clksrc,
-};
-
-static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_erefclk)
-		clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL;
-	else if (parent == &clk_mpll)
-		clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-
-static unsigned long s3c2412_getrate_i2s(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
-
-	div &= S3C2412_CLKDIVN_I2SDIV_MASK;
-	div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
-
-	rate = s3c2412_roundrate_clksrc(clk, rate);
-
-	clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK;
-	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2410_CLKDIVN);
-	return 0;
-}
-
-static struct clk clk_i2s = {
-	.name		= "i2sclk",
-	.id		= -1,
-	.get_rate	= s3c2412_getrate_i2s,
-	.set_rate	= s3c2412_setrate_i2s,
-	.set_parent	= s3c2412_setparent_i2s,
-	.round_rate	= s3c2412_roundrate_clksrc,
-};
-
-static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-
-	if (parent == &clk_usysclk)
-		clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK;
-	else if (parent == &clk_h)
-		clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	__raw_writel(clksrc, S3C2412_CLKSRC);
-	return 0;
-}
-static unsigned long s3c2412_getrate_cam(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
-
-	div &= S3C2412_CLKDIVN_CAMDIV_MASK;
-	div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
-
-	rate = s3c2412_roundrate_clksrc(clk, rate);
-
-	clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK;
-	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2410_CLKDIVN);
-	return 0;
-}
-
-static struct clk clk_cam = {
-	.name		= "camif-upll",	/* same as 2440 name */
-	.id		= -1,
-	.get_rate	= s3c2412_getrate_cam,
-	.set_rate	= s3c2412_setrate_cam,
-	.set_parent	= s3c2412_setparent_cam,
-	.round_rate	= s3c2412_roundrate_clksrc,
-};
-
-/* standard clock definitions */
-
-static struct clk init_clocks_disable[] = {
-	{
-		.name		= "nand",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_NAND,
-	}, {
-		.name		= "sdi",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_SDI,
-	}, {
-		.name		= "adc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_ADC,
-	}, {
-		.name		= "i2c",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_IIC,
-	}, {
-		.name		= "iis",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_IIS,
-	}, {
-		.name		= "spi",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_SPI,
-	}
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "dma",
-		.id		= 0,
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_DMA0,
-	}, {
-		.name		= "dma",
-		.id		= 1,
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_DMA1,
-	}, {
-		.name		= "dma",
-		.id		= 2,
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_DMA2,
-	}, {
-		.name		= "dma",
-		.id		= 3,
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_DMA3,
-	}, {
-		.name		= "lcd",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_LCDC,
-	}, {
-		.name		= "gpio",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_GPIO,
-	}, {
-		.name		= "usb-host",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_USBH,
-	}, {
-		.name		= "usb-device",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_USBD,
-	}, {
-		.name		= "timers",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_PWMT,
-	}, {
-		.name		= "uart",
-		.id		= 0,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_UART0,
-	}, {
-		.name		= "uart",
-		.id		= 1,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_UART1,
-	}, {
-		.name		= "uart",
-		.id		= 2,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_UART2,
-	}, {
-		.name		= "rtc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_RTC,
-	}, {
-		.name		= "watchdog",
-		.id		= -1,
-		.parent		= &clk_p,
-		.ctrlbit	= 0,
-	}, {
-		.name		= "usb-bus-gadget",
-		.id		= -1,
-		.parent		= &clk_usb_bus,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_USB_DEV48,
-	}, {
-		.name		= "usb-bus-host",
-		.id		= -1,
-		.parent		= &clk_usb_bus,
-		.enable		= s3c2412_clkcon_enable,
-		.ctrlbit	= S3C2412_CLKCON_USB_HOST48,
-	}
-};
-
-/* clocks to add where we need to check their parentage */
-
-struct clk_init {
-	struct clk	*clk;
-	unsigned int	 bit;
-	struct clk	*src_0;
-	struct clk	*src_1;
-};
-
-static struct clk_init clks_src[] __initdata = {
-	{
-		.clk	= &clk_usysclk,
-		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
-		.src_0	= &clk_urefclk,
-		.src_1	= &clk_upll,
-	}, {
-		.clk	= &clk_i2s,
-		.bit	= S3C2412_CLKSRC_I2SCLK_MPLL,
-		.src_0	= &clk_erefclk,
-		.src_1	= &clk_mpll,
-	}, {
-		.clk	= &clk_cam,
-		.bit	= S3C2412_CLKSRC_CAMCLK_HCLK,
-		.src_0	= &clk_usysclk,
-		.src_1	= &clk_h,
-	}, {
-		.clk	= &clk_msysclk,
-		.bit	= S3C2412_CLKSRC_MSYSCLK_MPLL,
-		.src_0	= &clk_mdivclk,
-		.src_1	= &clk_mpll,
-	}, {
-		.clk	= &clk_uart,
-		.bit	= S3C2412_CLKSRC_UARTCLK_MPLL,
-		.src_0	= &clk_erefclk,
-		.src_1	= &clk_mpll,
-	}, {
-		.clk	= &clk_usbsrc,
-		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
-		.src_0	= &clk_usysclk,
-		.src_1	= &clk_h,
-	},
-};
-
-/* s3c2412_clk_initparents
- *
- * Initialise the parents for the clocks that we get at start-time
-*/
-
-static void __init s3c2412_clk_initparents(void)
-{
-	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
-	struct clk_init *cip = clks_src;
-	struct clk *src;
-	int ptr;
-	int ret;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) {
-		ret = s3c24xx_register_clock(cip->clk);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       cip->clk->name, ret);
-		}
-
-		src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0;
-
-		printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name);
-		clk_set_parent(cip->clk, src);
-	}
-}
-
-/* clocks to add straight away */
-
-static struct clk *clks[] __initdata = {
-	&clk_ext,
-	&clk_usb_bus,
-	&clk_erefclk,
-	&clk_urefclk,
-	&clk_mrefclk,
-};
-
-int __init s3c2412_baseclk_add(void)
-{
-	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
-	struct clk *clkp;
-	int ret;
-	int ptr;
-
-	clk_upll.enable = s3c2412_upll_enable;
-	clk_usb_bus.parent = &clk_usbsrc;
-	clk_usb_bus.rate = 0x0;
-
-	s3c2412_clk_initparents();
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
-		clkp = clks[ptr];
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-
-	/* ensure usb bus clock is within correct rate of 48MHz */
-
-	if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) {
-		printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n");
-
-		/* for the moment, let's use the UPLL, and see if we can
-		 * get 48MHz */
-
-		clk_set_parent(&clk_usysclk, &clk_upll);
-		clk_set_parent(&clk_usbsrc, &clk_usysclk);
-		clk_set_rate(&clk_usbsrc, 48*1000*1000);
-	}
-
-	printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
-	       (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on",
-	       print_mhz(clk_get_rate(&clk_upll)),
-	       print_mhz(clk_get_rate(&clk_usb_bus)));
-
-	/* register clocks from clock array */
-
-	clkp = init_clocks;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
-		/* ensure that we note the clock state */
-
-		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-
-	/* We must be careful disabling the clocks we are not intending to
-	 * be using at boot time, as subsytems such as the LCD which do
-	 * their own DMA requests to the bus can cause the system to lockup
-	 * if they where in the middle of requesting bus access.
-	 *
-	 * Disabling the LCD clock if the LCD is active is very dangerous,
-	 * and therefore the bootloader should be careful to not enable
-	 * the LCD clock if it is not needed.
-	*/
-
-	/* install (and disable) the clocks we do not need immediately */
-
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-
-		s3c2412_clkcon_enable(clkp, 0);
-	}
-
-	return 0;
-}
diff --git a/arch/arm/mach-s3c2410/s3c2412-dma.c b/arch/arm/mach-s3c2410/s3c2412-dma.c
deleted file mode 100644
index 138f726..0000000
--- a/arch/arm/mach-s3c2410/s3c2412-dma.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-dma.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2412 DMA selection
- *
- * http://armlinux.simtec.co.uk/
- *
- * 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/sysdev.h>
-#include <linux/serial_core.h>
-
-#include <asm/dma.h>
-#include <asm/arch/dma.h>
-#include <asm/io.h>
-
-#include "dma.h"
-#include "cpu.h"
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-ac97.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-lcd.h>
-#include <asm/arch/regs-sdi.h>
-#include <asm/arch/regs-iis.h>
-#include <asm/arch/regs-spi.h>
-
-#define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
-
-static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
-	[DMACH_XD0] = {
-		.name		= "xdreq0",
-		.channels	= MAP(S3C2412_DMAREQSEL_XDREQ0),
-	},
-	[DMACH_XD1] = {
-		.name		= "xdreq1",
-		.channels	= MAP(S3C2412_DMAREQSEL_XDREQ1),
-	},
-	[DMACH_SDI] = {
-		.name		= "sdi",
-		.channels	= MAP(S3C2412_DMAREQSEL_SDI),
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_SPI0] = {
-		.name		= "spi0",
-		.channels	= MAP(S3C2412_DMAREQSEL_SPI0TX),
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
-	},
-	[DMACH_SPI1] = {
-		.name		= "spi1",
-		.channels	= MAP(S3C2412_DMAREQSEL_SPI1TX),
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
-	},
-	[DMACH_UART0] = {
-		.name		= "uart0",
-		.channels	= MAP(S3C2412_DMAREQSEL_UART0_0),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
-	},
-	[DMACH_UART1] = {
-		.name		= "uart1",
-		.channels	= MAP(S3C2412_DMAREQSEL_UART1_0),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
-	},
-      	[DMACH_UART2] = {
-		.name		= "uart2",
-		.channels	= MAP(S3C2412_DMAREQSEL_UART2_0),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
-	},
-	[DMACH_UART0_SRC2] = {
-		.name		= "uart0",
-		.channels	= MAP(S3C2412_DMAREQSEL_UART0_1),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
-	},
-	[DMACH_UART1_SRC2] = {
-		.name		= "uart1",
-		.channels	= MAP(S3C2412_DMAREQSEL_UART1_1),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
-	},
-      	[DMACH_UART2_SRC2] = {
-		.name		= "uart2",
-		.channels	= MAP(S3C2412_DMAREQSEL_UART2_1),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
-	},
-	[DMACH_TIMER] = {
-		.name		= "timer",
-		.channels	= MAP(S3C2412_DMAREQSEL_TIMER),
-	},
-	[DMACH_I2S_IN] = {
-		.name		= "i2s-sdi",
-		.channels	= MAP(S3C2412_DMAREQSEL_I2SRX),
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_I2S_OUT] = {
-		.name		= "i2s-sdo",
-		.channels	= MAP(S3C2412_DMAREQSEL_I2STX),
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_USB_EP1] = {
-		.name		= "usb-ep1",
-		.channels	= MAP(S3C2412_DMAREQSEL_USBEP1),
-	},
-	[DMACH_USB_EP2] = {
-		.name		= "usb-ep2",
-		.channels	= MAP(S3C2412_DMAREQSEL_USBEP2),
-	},
-	[DMACH_USB_EP3] = {
-		.name		= "usb-ep3",
-		.channels	= MAP(S3C2412_DMAREQSEL_USBEP3),
-	},
-	[DMACH_USB_EP4] = {
-		.name		= "usb-ep4",
-		.channels	= MAP(S3C2412_DMAREQSEL_USBEP4),
-	},
-};
-
-static void s3c2412_dma_select(struct s3c2410_dma_chan *chan,
-			       struct s3c24xx_dma_map *map)
-{
-	writel(map->channels[0] | S3C2412_DMAREQSEL_HW,
-	       chan->regs + S3C2412_DMA_DMAREQSEL);
-}
-
-static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
-	.select		= s3c2412_dma_select,
-	.dcon_mask	= 0,
-	.map		= s3c2412_dma_mappings,
-	.map_size	= ARRAY_SIZE(s3c2412_dma_mappings),
-};
-
-static int s3c2412_dma_add(struct sys_device *sysdev)
-{
-	return s3c24xx_dma_init_map(&s3c2412_dma_sel);
-}
-
-static struct sysdev_driver s3c2412_dma_driver = {
-	.add	= s3c2412_dma_add,
-};
-
-static int __init s3c2412_dma_init(void)
-{
-	return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_dma_driver);
-}
-
-arch_initcall(s3c2412_dma_init);
diff --git a/arch/arm/mach-s3c2410/s3c2412-irq.c b/arch/arm/mach-s3c2410/s3c2412-irq.c
deleted file mode 100644
index ffcc30b..0000000
--- a/arch/arm/mach-s3c2410/s3c2412-irq.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/* linux/arch/arm/mach-s3c2412/s3c2412-irq.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * 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/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/mach/irq.h>
-
-#include <asm/arch/regs-irq.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "cpu.h"
-#include "irq.h"
-#include "pm.h"
-
-/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
- * having them turn up in both the INT* and the EINT* registers. Whilst
- * both show the status, they both now need to be acked when the IRQs
- * go off.
-*/
-
-static void
-s3c2412_irq_mask(unsigned int irqno)
-{
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-	unsigned long mask;
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	__raw_writel(mask | bitval, S3C2410_INTMSK);
-
-	mask = __raw_readl(S3C2412_EINTMASK);
-	__raw_writel(mask | bitval, S3C2412_EINTMASK);
-}
-
-static inline void
-s3c2412_irq_ack(unsigned int irqno)
-{
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-
-	__raw_writel(bitval, S3C2412_EINTPEND);
-	__raw_writel(bitval, S3C2410_SRCPND);
-	__raw_writel(bitval, S3C2410_INTPND);
-}
-
-static inline void
-s3c2412_irq_maskack(unsigned int irqno)
-{
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-	unsigned long mask;
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	__raw_writel(mask|bitval, S3C2410_INTMSK);
-
-	mask = __raw_readl(S3C2412_EINTMASK);
-	__raw_writel(mask | bitval, S3C2412_EINTMASK);
-
-	__raw_writel(bitval, S3C2412_EINTPEND);
-	__raw_writel(bitval, S3C2410_SRCPND);
-	__raw_writel(bitval, S3C2410_INTPND);
-}
-
-static void
-s3c2412_irq_unmask(unsigned int irqno)
-{
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-	unsigned long mask;
-
-	mask = __raw_readl(S3C2412_EINTMASK);
-	__raw_writel(mask & ~bitval, S3C2412_EINTMASK);
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	__raw_writel(mask & ~bitval, S3C2410_INTMSK);
-}
-
-static struct irq_chip s3c2412_irq_eint0t4 = {
-	.ack	   = s3c2412_irq_ack,
-	.mask	   = s3c2412_irq_mask,
-	.unmask	   = s3c2412_irq_unmask,
-	.set_wake  = s3c_irq_wake,
-	.set_type  = s3c_irqext_type,
-};
-
-static int s3c2412_irq_add(struct sys_device *sysdev)
-{
-	unsigned int irqno;
-
-	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
-		set_irq_chip(irqno, &s3c2412_irq_eint0t4);
-		set_irq_handler(irqno, handle_edge_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	return 0;
-}
-
-static struct sysdev_driver s3c2412_irq_driver = {
-	.add		= s3c2412_irq_add,
-	.suspend	= s3c24xx_irq_suspend,
-	.resume		= s3c24xx_irq_resume,
-};
-
-static int s3c2412_irq_init(void)
-{
-	return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_irq_driver);
-}
-
-arch_initcall(s3c2412_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c2412-pm.c b/arch/arm/mach-s3c2410/s3c2412-pm.c
deleted file mode 100644
index 19b6332..0000000
--- a/arch/arm/mach-s3c2410/s3c2412-pm.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-pm.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * http://armlinux.simtec.co.uk/.
- *
- * 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/sysdev.h>
-#include <linux/platform_device.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/arch/regs-power.h>
-#include <asm/arch/regs-gpioj.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-dsc.h>
-
-#include "cpu.h"
-#include "pm.h"
-
-#include "s3c2412.h"
-
-static void s3c2412_cpu_suspend(void)
-{
-	unsigned long tmp;
-
-	/* set our standby method to sleep */
-
-	tmp = __raw_readl(S3C2412_PWRCFG);
-	tmp |= S3C2412_PWRCFG_STANDBYWFI_SLEEP;
-	__raw_writel(tmp, S3C2412_PWRCFG);
-
-	/* issue the standby signal into the pm unit. Note, we
-	 * issue a write-buffer drain just in case */
-
-	tmp = 0;
-
-	asm("b 1f\n\t"
-	    ".align 5\n\t"
-	    "1:\n\t"
-	    "mcr p15, 0, %0, c7, c10, 4\n\t"
-	    "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
-
-	/* we should never get past here */
-
-	panic("sleep resumed to originator?");
-}
-
-static void s3c2412_pm_prepare(void)
-{
-}
-
-static int s3c2412_pm_add(struct sys_device *sysdev)
-{
-	pm_cpu_prep = s3c2412_pm_prepare;
-	pm_cpu_sleep = s3c2412_cpu_suspend;
-
-	return 0;
-}
-
-static struct sleep_save s3c2412_sleep[] = {
-	SAVE_ITEM(S3C2412_DSC0),
-	SAVE_ITEM(S3C2412_DSC1),
-	SAVE_ITEM(S3C2413_GPJDAT),
-	SAVE_ITEM(S3C2413_GPJCON),
-	SAVE_ITEM(S3C2413_GPJUP),
-
-	/* save the PWRCFG to get back to original sleep method */
-
-	SAVE_ITEM(S3C2412_PWRCFG),
-
-	/* save the sleep configuration anyway, just in case these
-	 * get damaged during wakeup */
-
-	SAVE_ITEM(S3C2412_GPBSLPCON),
-	SAVE_ITEM(S3C2412_GPCSLPCON),
-	SAVE_ITEM(S3C2412_GPDSLPCON),
-	SAVE_ITEM(S3C2412_GPESLPCON),
-	SAVE_ITEM(S3C2412_GPFSLPCON),
-	SAVE_ITEM(S3C2412_GPGSLPCON),
-	SAVE_ITEM(S3C2412_GPHSLPCON),
-	SAVE_ITEM(S3C2413_GPJSLPCON),
-};
-
-static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state)
-{
-	s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
-	return 0;
-}
-
-static int s3c2412_pm_resume(struct sys_device *dev)
-{
-	unsigned long tmp;
-
-	tmp = __raw_readl(S3C2412_PWRCFG);
-	tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK;
-	tmp |=  S3C2412_PWRCFG_STANDBYWFI_IDLE;
-	__raw_writel(tmp, S3C2412_PWRCFG);
-
-	s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
-	return 0;
-}
-
-static struct sysdev_driver s3c2412_pm_driver = {
-	.add		= s3c2412_pm_add,
-	.suspend	= s3c2412_pm_suspend,
-	.resume		= s3c2412_pm_resume,
-};
-
-static __init int s3c2412_pm_init(void)
-{
-	return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver);
-}
-
-arch_initcall(s3c2412_pm_init);
diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2410/s3c2412.c
deleted file mode 100644
index 2f651a8..0000000
--- a/arch/arm/mach-s3c2410/s3c2412.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * http://armlinux.simtec.co.uk/.
- *
- * 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/sysdev.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/hardware.h>
-#include <asm/proc-fns.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/arch/idle.h>
-
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-power.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-gpioj.h>
-#include <asm/arch/regs-dsc.h>
-
-#include "s3c2412.h"
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
-#include "pm.h"
-
-#ifndef CONFIG_CPU_S3C2412_ONLY
-void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
-
-static inline void s3c2412_init_gpio2(void)
-{
-	s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
-}
-#else
-#define s3c2412_init_gpio2() do { } while(0)
-#endif
-
-/* Initial IO mappings */
-
-static struct map_desc s3c2412_iodesc[] __initdata = {
-	IODESC_ENT(CLKPWR),
-	IODESC_ENT(LCD),
-	IODESC_ENT(TIMER),
-	IODESC_ENT(WATCHDOG),
-};
-
-/* uart registration process */
-
-void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	s3c24xx_init_uartdevs("s3c2412-uart", s3c2410_uart_resources, cfg, no);
-
-	/* rename devices that are s3c2412/s3c2413 specific */
-	s3c_device_sdi.name  = "s3c2412-sdi";
-	s3c_device_lcd.name  = "s3c2412-lcd";
-	s3c_device_nand.name = "s3c2412-nand";
-}
-
-/* s3c2412_idle
- *
- * use the standard idle call by ensuring the idle mode
- * in power config, then issuing the idle co-processor
- * instruction
-*/
-
-static void s3c2412_idle(void)
-{
-	unsigned long tmp;
-
-	/* ensure our idle mode is to go to idle */
-
-	tmp = __raw_readl(S3C2412_PWRCFG);
-	tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK;
-	tmp |= S3C2412_PWRCFG_STANDBYWFI_IDLE;
-	__raw_writel(tmp, S3C2412_PWRCFG);
-
-	cpu_do_idle();
-}
-
-/* s3c2412_map_io
- *
- * register the standard cpu IO areas, and any passed in from the
- * machine specific initialisation.
-*/
-
-void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size)
-{
-	/* move base of IO */
-
-	s3c2412_init_gpio2();
-
-	/* set our idle function */
-
-	s3c24xx_idle = s3c2412_idle;
-
-	/* register our io-tables */
-
-	iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
-	iotable_init(mach_desc, mach_size);
-}
-
-void __init s3c2412_init_clocks(int xtal)
-{
-	unsigned long tmp;
-	unsigned long fclk;
-	unsigned long hclk;
-	unsigned long pclk;
-
-	/* now we've got our machine bits initialised, work out what
-	 * clocks we've got */
-
-	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2);
-
-	tmp = __raw_readl(S3C2410_CLKDIVN);
-
-	/* work out clock scalings */
-
-	hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
-	hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1);
-	pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
-
-	/* print brieft summary of clocks, etc */
-
-	printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
-	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
-
-	/* initialise the clocks here, to allow other things like the
-	 * console to use them
-	 */
-
-	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
-	s3c2412_baseclk_add();
-}
-
-/* need to register class before we actually register the device, and
- * we also need to ensure that it has been initialised before any of the
- * drivers even try to use it (even if not on an s3c2412 based system)
- * as a driver which may support both 2410 and 2440 may try and use it.
-*/
-
-struct sysdev_class s3c2412_sysclass = {
-	set_kset_name("s3c2412-core"),
-};
-
-static int __init s3c2412_core_init(void)
-{
-	return sysdev_class_register(&s3c2412_sysclass);
-}
-
-core_initcall(s3c2412_core_init);
-
-static struct sys_device s3c2412_sysdev = {
-	.cls		= &s3c2412_sysclass,
-};
-
-int __init s3c2412_init(void)
-{
-	printk("S3C2412: Initialising architecture\n");
-
-	return sysdev_register(&s3c2412_sysdev);
-}
diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/arch/arm/mach-s3c2410/s3c2412.h
deleted file mode 100644
index c6e5603..0000000
--- a/arch/arm/mach-s3c2410/s3c2412.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* arch/arm/mach-s3c2410/s3c2412.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2412 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifdef CONFIG_CPU_S3C2412
-
-extern  int s3c2412_init(void);
-
-extern void s3c2412_map_io(struct map_desc *mach_desc, int size);
-
-extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2412_init_clocks(int xtal);
-
-extern  int s3c2412_baseclk_add(void);
-#else
-#define s3c2412_init_clocks NULL
-#define s3c2412_init_uarts NULL
-#define s3c2412_map_io NULL
-#define s3c2412_init NULL
-#endif
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
deleted file mode 100644
index ba13c1d..0000000
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-clock.c
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2440 Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mutex.h>
-#include <linux/clk.h>
-
-#include <asm/hardware.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-clock.h>
-
-#include "clock.h"
-#include "cpu.h"
-
-/* S3C2440 extended clock support */
-
-static unsigned long s3c2440_camif_upll_round(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int div;
-
-	if (rate > parent_rate)
-		return parent_rate;
-
-	/* note, we remove the +/- 1 calculations for the divisor */
-
-	div = (parent_rate / rate) / 2;
-
-	if (div < 1)
-		div = 1;
-	else if (div > 16)
-		div = 16;
-
-	return parent_rate / (div * 2);
-}
-
-static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
-
-	rate = s3c2440_camif_upll_round(clk, rate);
-
-	camdivn &= ~(S3C2440_CAMDIVN_CAMCLK_SEL | S3C2440_CAMDIVN_CAMCLK_MASK);
-
-	if (rate != parent_rate) {
-		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
-		camdivn |= (((parent_rate / rate) / 2) - 1);
-	}
-
-	__raw_writel(camdivn, S3C2440_CAMDIVN);
-
-	return 0;
-}
-
-/* Extra S3C2440 clocks */
-
-static struct clk s3c2440_clk_cam = {
-	.name		= "camif",
-	.id		= -1,
-	.enable		= s3c2410_clkcon_enable,
-	.ctrlbit	= S3C2440_CLKCON_CAMERA,
-};
-
-static struct clk s3c2440_clk_cam_upll = {
-	.name		= "camif-upll",
-	.id		= -1,
-	.set_rate	= s3c2440_camif_upll_setrate,
-	.round_rate	= s3c2440_camif_upll_round,
-};
-
-static struct clk s3c2440_clk_ac97 = {
-	.name		= "ac97",
-	.id		= -1,
-	.enable		= s3c2410_clkcon_enable,
-	.ctrlbit	= S3C2440_CLKCON_CAMERA,
-};
-
-static int s3c2440_clk_add(struct sys_device *sysdev)
-{
-	unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
-	unsigned long clkdivn;
-	struct clk *clock_h;
-	struct clk *clock_p;
-	struct clk *clock_upll;
-
-	printk("S3C2440: Clock Support, DVS %s\n",
-	       (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
-
-	clock_p = clk_get(NULL, "pclk");
-	clock_h = clk_get(NULL, "hclk");
-	clock_upll = clk_get(NULL, "upll");
-
-	if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
-		printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
-		return -EINVAL;
-	}
-
-	/* check rate of UPLL, and if it is near 96MHz, then change
-	 * to using half the UPLL rate for the system */
-
-	if (clk_get_rate(clock_upll) > (94 * MHZ)) {
-		clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
-
-		mutex_lock(&clocks_mutex);
-
-		clkdivn = __raw_readl(S3C2410_CLKDIVN);
-		clkdivn |= S3C2440_CLKDIVN_UCLK;
-		__raw_writel(clkdivn, S3C2410_CLKDIVN);
-
-		mutex_unlock(&clocks_mutex);
-	}
-
-	s3c2440_clk_cam.parent = clock_h;
-	s3c2440_clk_ac97.parent = clock_p;
-	s3c2440_clk_cam_upll.parent = clock_upll;
-
-	s3c24xx_register_clock(&s3c2440_clk_ac97);
-	s3c24xx_register_clock(&s3c2440_clk_cam);
-	s3c24xx_register_clock(&s3c2440_clk_cam_upll);
-
-	clk_disable(&s3c2440_clk_ac97);
-	clk_disable(&s3c2440_clk_cam);
-
-	return 0;
-}
-
-static struct sysdev_driver s3c2440_clk_driver = {
-	.add	= s3c2440_clk_add,
-};
-
-static __init int s3c24xx_clk_driver(void)
-{
-	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
-}
-
-arch_initcall(s3c24xx_clk_driver);
diff --git a/arch/arm/mach-s3c2410/s3c2440-dma.c b/arch/arm/mach-s3c2410/s3c2440-dma.c
deleted file mode 100644
index 47b861b..0000000
--- a/arch/arm/mach-s3c2410/s3c2440-dma.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-dma.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2440 DMA selection
- *
- * http://armlinux.simtec.co.uk/
- *
- * 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/sysdev.h>
-#include <linux/serial_core.h>
-
-#include <asm/dma.h>
-#include <asm/arch/dma.h>
-#include "dma.h"
-
-#include "cpu.h"
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-ac97.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-lcd.h>
-#include <asm/arch/regs-sdi.h>
-#include <asm/arch/regs-iis.h>
-#include <asm/arch/regs-spi.h>
-
-static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
-	[DMACH_XD0] = {
-		.name		= "xdreq0",
-		.channels[0]	= S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
-	},
-	[DMACH_XD1] = {
-		.name		= "xdreq1",
-		.channels[1]	= S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
-	},
-	[DMACH_SDI] = {
-		.name		= "sdi",
-		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
-		.channels[1]	= S3C2440_DCON_CH1_SDI | DMA_CH_VALID,
-		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
-		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_SPI0] = {
-		.name		= "spi0",
-		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
-	},
-	[DMACH_SPI1] = {
-		.name		= "spi1",
-		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
-	},
-	[DMACH_UART0] = {
-		.name		= "uart0",
-		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
-	},
-	[DMACH_UART1] = {
-		.name		= "uart1",
-		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
-	},
-      	[DMACH_UART2] = {
-		.name		= "uart2",
-		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
-	},
-	[DMACH_TIMER] = {
-		.name		= "timer",
-		.channels[0]	= S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
-		.channels[2]	= S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
-		.channels[3]	= S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
-	},
-	[DMACH_I2S_IN] = {
-		.name		= "i2s-sdi",
-		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
-		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_I2S_OUT] = {
-		.name		= "i2s-sdo",
-		.channels[0]	= S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID,
-		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_PCM_IN] = {
-		.name		= "pcm-in",
-		.channels[0]	= S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID,
-		.channels[2]	= S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID,
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
-	},
-	[DMACH_PCM_OUT] = {
-		.name		= "pcm-out",
-		.channels[1]	= S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID,
-		.channels[3]	= S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID,
-		.hw_addr.to	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
-	},
-	[DMACH_MIC_IN] = {
-		.name		= "mic-in",
-		.channels[2]	= S3C2440_DCON_CH2_MICIN | DMA_CH_VALID,
-		.channels[3]	= S3C2440_DCON_CH3_MICIN | DMA_CH_VALID,
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
-	},
-	[DMACH_USB_EP1] = {
-		.name		= "usb-ep1",
-		.channels[0]	= S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
-	},
-	[DMACH_USB_EP2] = {
-		.name		= "usb-ep2",
-		.channels[1]	= S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
-	},
-	[DMACH_USB_EP3] = {
-		.name		= "usb-ep3",
-		.channels[2]	= S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
-	},
-	[DMACH_USB_EP4] = {
-		.name		= "usb-ep4",
-		.channels[3]	= S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
-	},
-};
-
-static void s3c2440_dma_select(struct s3c2410_dma_chan *chan,
-			       struct s3c24xx_dma_map *map)
-{
-	chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
-}
-
-static struct s3c24xx_dma_selection __initdata s3c2440_dma_sel = {
-	.select		= s3c2440_dma_select,
-	.dcon_mask	= 7 << 24,
-	.map		= s3c2440_dma_mappings,
-	.map_size	= ARRAY_SIZE(s3c2440_dma_mappings),
-};
-
-static int s3c2440_dma_add(struct sys_device *sysdev)
-{
-	return s3c24xx_dma_init_map(&s3c2440_dma_sel);
-}
-
-static struct sysdev_driver s3c2440_dma_driver = {
-	.add	= s3c2440_dma_add,
-};
-
-static int __init s3c2440_dma_init(void)
-{
-	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_dma_driver);
-}
-
-arch_initcall(s3c2440_dma_init);
-
diff --git a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2410/s3c2440-dsc.c
deleted file mode 100644
index c92ea66..0000000
--- a/arch/arm/mach-s3c2410/s3c2440-dsc.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-dsc.c
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *   Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C2440 Drive Strength Control support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/module.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/regs-dsc.h>
-
-#include "cpu.h"
-#include "s3c2440.h"
-
-int s3c2440_set_dsc(unsigned int pin, unsigned int value)
-{
-	void __iomem *base;
-	unsigned long val;
-	unsigned long flags;
-	unsigned long mask;
-
-	base = (pin & S3C2440_SELECT_DSC1) ? S3C2440_DSC1 : S3C2440_DSC0;
-	mask = 3 << S3C2440_DSC_GETSHIFT(pin);
-
-	local_irq_save(flags);
-
-	val = __raw_readl(base);
-	val &= ~mask;
-	val |= value & mask;
-	__raw_writel(val, base);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2440_set_dsc);
diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2410/s3c2440-irq.c
deleted file mode 100644
index 1ba19b2..0000000
--- a/arch/arm/mach-s3c2410/s3c2440-irq.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
- *
- * Copyright (c) 2003,2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * 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/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/mach/irq.h>
-
-#include <asm/arch/regs-irq.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
-
-/* WDT/AC97 */
-
-static void s3c_irq_demux_wdtac97(unsigned int irq,
-				  struct irq_desc *desc)
-{
-	unsigned int subsrc, submsk;
-	struct irq_desc *mydesc;
-
-	/* read the current pending interrupts, and the mask
-	 * for what it is available */
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	subsrc &= ~submsk;
-	subsrc >>= 13;
-	subsrc &= 3;
-
-	if (subsrc != 0) {
-		if (subsrc & 1) {
-			mydesc = irq_desc + IRQ_S3C2440_WDT;
-			desc_handle_irq(IRQ_S3C2440_WDT, mydesc);
-		}
-		if (subsrc & 2) {
-			mydesc = irq_desc + IRQ_S3C2440_AC97;
-			desc_handle_irq(IRQ_S3C2440_AC97, mydesc);
-		}
-	}
-}
-
-
-#define INTMSK_WDT	 (1UL << (IRQ_WDT - IRQ_EINT0))
-
-static void
-s3c_irq_wdtac97_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
-}
-
-static void
-s3c_irq_wdtac97_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_WDT);
-}
-
-static void
-s3c_irq_wdtac97_ack(unsigned int irqno)
-{
-	s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
-}
-
-static struct irq_chip s3c_irq_wdtac97 = {
-	.mask	    = s3c_irq_wdtac97_mask,
-	.unmask	    = s3c_irq_wdtac97_unmask,
-	.ack	    = s3c_irq_wdtac97_ack,
-};
-
-static int s3c2440_irq_add(struct sys_device *sysdev)
-{
-	unsigned int irqno;
-
-	printk("S3C2440: IRQ Support\n");
-
-	/* add new chained handler for wdt, ac7 */
-
-	set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
-	set_irq_handler(IRQ_WDT, handle_level_irq);
-	set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
-
-	for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
-		set_irq_chip(irqno, &s3c_irq_wdtac97);
-		set_irq_handler(irqno, handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	return 0;
-}
-
-static struct sysdev_driver s3c2440_irq_driver = {
-	.add		= s3c2440_irq_add,
-};
-
-static int s3c2440_irq_init(void)
-{
-	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
-}
-
-arch_initcall(s3c2440_irq_init);
-
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
deleted file mode 100644
index 344eb27..0000000
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- *   Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C2440 Mobile CPU support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#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/serial_core.h>
-#include <linux/sysdev.h>
-#include <linux/clk.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 "s3c2440.h"
-#include "devs.h"
-#include "cpu.h"
-
-static struct sys_device s3c2440_sysdev = {
-	.cls		= &s3c2440_sysclass,
-};
-
-int __init s3c2440_init(void)
-{
-	printk("S3C2440: Initialising architecture\n");
-
-	/* change irq for watchdog */
-
-	s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
-	s3c_device_wdt.resource[1].end   = IRQ_S3C2440_WDT;
-
-	/* register our system device for everything else */
-
-	return sysdev_register(&s3c2440_sysdev);
-}
diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/arch/arm/mach-s3c2410/s3c2440.h
deleted file mode 100644
index dcd3160..0000000
--- a/arch/arm/mach-s3c2410/s3c2440.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* arch/arm/mach-s3c2410/s3c2440.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2440 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifdef CONFIG_CPU_S3C2440
-extern  int s3c2440_init(void);
-#else
-#define s3c2440_init NULL
-#endif
diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2410/s3c2442-clock.c
deleted file mode 100644
index 4e292ca..0000000
--- a/arch/arm/mach-s3c2410/s3c2442-clock.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2442 Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mutex.h>
-#include <linux/clk.h>
-
-#include <asm/hardware.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-clock.h>
-
-#include "clock.h"
-#include "cpu.h"
-
-/* S3C2442 extended clock support */
-
-static unsigned long s3c2442_camif_upll_round(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int div;
-
-	if (rate > parent_rate)
-		return parent_rate;
-
-	div = parent_rate / rate;
-
-	if (div == 3)
-		return parent_rate / 3;
-
-	/* note, we remove the +/- 1 calculations for the divisor */
-
-	div /= 2;
-
-	if (div < 1)
-		div = 1;
-	else if (div > 16)
-		div = 16;
-
-	return parent_rate / (div * 2);
-}
-
-static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
-
-	rate = s3c2442_camif_upll_round(clk, rate);
-
-	camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
-
-	if (rate == parent_rate) {
-		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
-	} else if ((parent_rate / rate) == 3) {
-		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
-		camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
-	} else {
-		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
-		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
-		camdivn |= (((parent_rate / rate) / 2) - 1);
-	}
-
-	__raw_writel(camdivn, S3C2440_CAMDIVN);
-
-	return 0;
-}
-
-/* Extra S3C2442 clocks */
-
-static struct clk s3c2442_clk_cam = {
-	.name		= "camif",
-	.id		= -1,
-	.enable		= s3c2410_clkcon_enable,
-	.ctrlbit	= S3C2440_CLKCON_CAMERA,
-};
-
-static struct clk s3c2442_clk_cam_upll = {
-	.name		= "camif-upll",
-	.id		= -1,
-	.set_rate	= s3c2442_camif_upll_setrate,
-	.round_rate	= s3c2442_camif_upll_round,
-};
-
-static int s3c2442_clk_add(struct sys_device *sysdev)
-{
-	unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
-	unsigned long clkdivn;
-	struct clk *clock_h;
-	struct clk *clock_p;
-	struct clk *clock_upll;
-
-	printk("S3C2442: Clock Support, DVS %s\n",
-	       (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
-
-	clock_p = clk_get(NULL, "pclk");
-	clock_h = clk_get(NULL, "hclk");
-	clock_upll = clk_get(NULL, "upll");
-
-	if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
-		printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
-		return -EINVAL;
-	}
-
-	/* check rate of UPLL, and if it is near 96MHz, then change
-	 * to using half the UPLL rate for the system */
-
-	if (clk_get_rate(clock_upll) > (94 * MHZ)) {
-		clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
-
-		mutex_lock(&clocks_mutex);
-
-		clkdivn = __raw_readl(S3C2410_CLKDIVN);
-		clkdivn |= S3C2440_CLKDIVN_UCLK;
-		__raw_writel(clkdivn, S3C2410_CLKDIVN);
-
-		mutex_unlock(&clocks_mutex);
-	}
-
-	s3c2442_clk_cam.parent = clock_h;
-	s3c2442_clk_cam_upll.parent = clock_upll;
-
-	s3c24xx_register_clock(&s3c2442_clk_cam);
-	s3c24xx_register_clock(&s3c2442_clk_cam_upll);
-
-	clk_disable(&s3c2442_clk_cam);
-
-	return 0;
-}
-
-static struct sysdev_driver s3c2442_clk_driver = {
-	.add	= s3c2442_clk_add,
-};
-
-static __init int s3c2442_clk_init(void)
-{
-	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver);
-}
-
-arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2410/s3c2442.c
deleted file mode 100644
index 428732e..0000000
--- a/arch/arm/mach-s3c2410/s3c2442.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2442.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *   Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C2442 Mobile CPU support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#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/serial_core.h>
-#include <linux/sysdev.h>
-
-#include "s3c2442.h"
-#include "cpu.h"
-
-static struct sys_device s3c2442_sysdev = {
-	.cls		= &s3c2442_sysclass,
-};
-
-int __init s3c2442_init(void)
-{
-	printk("S3C2442: Initialising architecture\n");
-
-	return sysdev_register(&s3c2442_sysdev);
-}
diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/arch/arm/mach-s3c2410/s3c2442.h
deleted file mode 100644
index 0ae37d2..0000000
--- a/arch/arm/mach-s3c2410/s3c2442.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* arch/arm/mach-s3c2410/s3c2442.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2442 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifdef CONFIG_CPU_S3C2442
-extern  int s3c2442_init(void);
-#else
-#define s3c2442_init NULL
-#endif
diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c
deleted file mode 100644
index ede9463..0000000
--- a/arch/arm/mach-s3c2410/s3c244x-irq.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c244x-irq.c
- *
- * Copyright (c) 2003,2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * 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/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/mach/irq.h>
-
-#include <asm/arch/regs-irq.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
-
-/* camera irq */
-
-static void s3c_irq_demux_cam(unsigned int irq,
-			      struct irq_desc *desc)
-{
-	unsigned int subsrc, submsk;
-	struct irq_desc *mydesc;
-
-	/* read the current pending interrupts, and the mask
-	 * for what it is available */
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	subsrc &= ~submsk;
-	subsrc >>= 11;
-	subsrc &= 3;
-
-	if (subsrc != 0) {
-		if (subsrc & 1) {
-			mydesc = irq_desc + IRQ_S3C2440_CAM_C;
-			desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc);
-		}
-		if (subsrc & 2) {
-			mydesc = irq_desc + IRQ_S3C2440_CAM_P;
-			desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc);
-		}
-	}
-}
-
-#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
-
-static void
-s3c_irq_cam_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
-}
-
-static void
-s3c_irq_cam_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_CAM);
-}
-
-static void
-s3c_irq_cam_ack(unsigned int irqno)
-{
-	s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
-}
-
-static struct irq_chip s3c_irq_cam = {
-	.mask	    = s3c_irq_cam_mask,
-	.unmask	    = s3c_irq_cam_unmask,
-	.ack	    = s3c_irq_cam_ack,
-};
-
-static int s3c244x_irq_add(struct sys_device *sysdev)
-{
-	unsigned int irqno;
-
-	set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
-	set_irq_handler(IRQ_NFCON, handle_level_irq);
-	set_irq_flags(IRQ_NFCON, IRQF_VALID);
-
-	/* add chained handler for camera */
-
-	set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
-	set_irq_handler(IRQ_CAM, handle_level_irq);
-	set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
-
-	for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
-		set_irq_chip(irqno, &s3c_irq_cam);
-		set_irq_handler(irqno, handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	return 0;
-}
-
-static struct sysdev_driver s3c2440_irq_driver = {
-	.add		= s3c244x_irq_add,
-	.suspend	= s3c24xx_irq_suspend,
-	.resume		= s3c24xx_irq_resume,
-};
-
-static int s3c2440_irq_init(void)
-{
-	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
-}
-
-arch_initcall(s3c2440_irq_init);
-
-static struct sysdev_driver s3c2442_irq_driver = {
-	.add		= s3c244x_irq_add,
-	.suspend	= s3c24xx_irq_suspend,
-	.resume		= s3c24xx_irq_resume,
-};
-
-
-static int s3c2442_irq_init(void)
-{
-	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_irq_driver);
-}
-
-arch_initcall(s3c2442_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/mach-s3c2410/s3c244x.c
deleted file mode 100644
index 23c7494..0000000
--- a/arch/arm/mach-s3c2410/s3c244x.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c244x.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- *   Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C2440 and S3C2442 Mobile CPU support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#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/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/sysdev.h>
-#include <linux/clk.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-clock.h>
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-gpioj.h>
-#include <asm/arch/regs-dsc.h>
-
-#include "s3c2410.h"
-#include "s3c2440.h"
-#include "s3c244x.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
-
-static struct map_desc s3c244x_iodesc[] __initdata = {
-	IODESC_ENT(CLKPWR),
-	IODESC_ENT(TIMER),
-	IODESC_ENT(WATCHDOG),
-	IODESC_ENT(LCD),
-};
-
-/* uart initialisation */
-
-void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
-}
-
-void __init s3c244x_map_io(struct map_desc *mach_desc, int size)
-{
-	/* register our io-tables */
-
-	iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));
-	iotable_init(mach_desc, size);
-
-	/* rename any peripherals used differing from the s3c2410 */
-
-	s3c_device_i2c.name  = "s3c2440-i2c";
-	s3c_device_nand.name = "s3c2440-nand";
-	s3c_device_usbgadget.name = "s3c2440-usbgadget";
-}
-
-void __init s3c244x_init_clocks(int xtal)
-{
-	unsigned long clkdiv;
-	unsigned long camdiv;
-	unsigned long hclk, fclk, pclk;
-	int hdiv = 1;
-
-	/* now we've got our machine bits initialised, work out what
-	 * clocks we've got */
-
-	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
-
-	clkdiv = __raw_readl(S3C2410_CLKDIVN);
-	camdiv = __raw_readl(S3C2440_CAMDIVN);
-
-	/* work out clock scalings */
-
-	switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
-	case S3C2440_CLKDIVN_HDIVN_1:
-		hdiv = 1;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_2:
-		hdiv = 2;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_4_8:
-		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_3_6:
-		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
-		break;
-	}
-
-	hclk = fclk / hdiv;
-	pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
-
-	/* print brief summary of clocks, etc */
-
-	printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
-	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
-
-	/* initialise the clocks here, to allow other things like the
-	 * console to use them, and to add new ones after the initialisation
-	 */
-
-	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
-	s3c2410_baseclk_add();
-}
-
-#ifdef CONFIG_PM
-
-static struct sleep_save s3c244x_sleep[] = {
-	SAVE_ITEM(S3C2440_DSC0),
-	SAVE_ITEM(S3C2440_DSC1),
-	SAVE_ITEM(S3C2440_GPJDAT),
-	SAVE_ITEM(S3C2440_GPJCON),
-	SAVE_ITEM(S3C2440_GPJUP)
-};
-
-static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
-{
-	s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
-	return 0;
-}
-
-static int s3c244x_resume(struct sys_device *dev)
-{
-	s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
-	return 0;
-}
-
-#else
-#define s3c244x_suspend NULL
-#define s3c244x_resume  NULL
-#endif
-
-/* Since the S3C2442 and S3C2440 share  items, put both sysclasses here */
-
-struct sysdev_class s3c2440_sysclass = {
-	set_kset_name("s3c2440-core"),
-	.suspend	= s3c244x_suspend,
-	.resume		= s3c244x_resume
-};
-
-struct sysdev_class s3c2442_sysclass = {
-	set_kset_name("s3c2442-core"),
-	.suspend	= s3c244x_suspend,
-	.resume		= s3c244x_resume
-};
-
-/* need to register class before we actually register the device, and
- * we also need to ensure that it has been initialised before any of the
- * drivers even try to use it (even if not on an s3c2440 based system)
- * as a driver which may support both 2410 and 2440 may try and use it.
-*/
-
-static int __init s3c2440_core_init(void)
-{
-	return sysdev_class_register(&s3c2440_sysclass);
-}
-
-core_initcall(s3c2440_core_init);
-
-static int __init s3c2442_core_init(void)
-{
-	return sysdev_class_register(&s3c2442_sysclass);
-}
-
-core_initcall(s3c2442_core_init);
diff --git a/arch/arm/mach-s3c2410/s3c244x.h b/arch/arm/mach-s3c2410/s3c244x.h
deleted file mode 100644
index 1488c1e..0000000
--- a/arch/arm/mach-s3c2410/s3c244x.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* arch/arm/mach-s3c2410/s3c244x.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C2440 and S3C2442 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
-
-extern void s3c244x_map_io(struct map_desc *mach_desc, int size);
-
-extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c244x_init_clocks(int xtal);
-
-#else
-#define s3c244x_init_clocks NULL
-#define s3c244x_init_uarts NULL
-#define s3c244x_map_io NULL
-#endif
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index 2018c2e..637aaba 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/sleep.S
+/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
  *
  * Copyright (c) 2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -34,126 +34,35 @@
 #include <asm/arch/regs-mem.h>
 #include <asm/arch/regs-serial.h>
 
-/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
- * reset the UART configuration, only enable if you really need this!
-*/
-//#define CONFIG_DEBUG_RESUME
-
-	.text
-
-	/* s3c2410_cpu_save
+	/* s3c2410_cpu_suspend
 	 *
-	 * save enough of the CPU state to allow us to re-start
-	 * pm.c code. as we store items like the sp/lr, we will
-	 * end up returning from this function when the cpu resumes
-	 * so the return value is set to mark this.
-	 *
-	 * This arangement means we avoid having to flush the cache
-	 * from this code.
-	 *
-	 * entry:
-	 *	r0 = pointer to save block
-	 *
-	 * exit:
-	 *	r0 = 0 => we stored everything
-	 *	     1 => resumed from sleep
+	 * put the cpu into sleep mode
 	*/
 
-ENTRY(s3c2410_cpu_save)
-	stmfd	sp!, { r4 - r12, lr }
+ENTRY(s3c2410_cpu_suspend)
+	@@ prepare cpu to sleep
 
-	@@ store co-processor registers
+	ldr	r4, =S3C2410_REFRESH
+	ldr	r5, =S3C24XX_MISCCR
+	ldr	r6, =S3C2410_CLKCON
+	ldr	r7, [ r4 ]		@ get REFRESH (and ensure in TLB)
+	ldr	r8, [ r5 ]		@ get MISCCR (and ensure in TLB)
+	ldr	r9, [ r6 ]		@ get CLKCON (and ensure in TLB)
 
-	mrc	p15, 0, r4, c15, c1, 0	@ CP access register
-	mrc	p15, 0, r5, c13, c0, 0	@ PID
-	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r7, c2, c0, 0	@ translation table base address
-	mrc	p15, 0, r8, c1, c0, 0	@ control register
+	orr	r7, r7, #S3C2410_REFRESH_SELF	@ SDRAM sleep command
+	orr	r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
+	orr	r9, r9, #S3C2410_CLKCON_POWER	@ power down command
 
-	stmia	r0, { r4 - r13 }
+	teq	pc, #0			@ first as a trial-run to load cache
+	bl	s3c2410_do_sleep
+	teq	r0, r0			@ now do it for real
+	b	s3c2410_do_sleep	@
 
-	mov	r0, #0
-	ldmfd	sp, { r4 - r12, pc }
-
-	@@ return to the caller, after having the MMU
-	@@ turned on, this restores the last bits from the
-	@@ stack
-resume_with_mmu:
-	mov	r0, #1
-	ldmfd	sp!, { r4 - r12, pc }
-
-	.ltorg
-
-	@@ the next bits sit in the .data segment, even though they
-	@@ happen to be code... the s3c2410_sleep_save_phys needs to be
-	@@ accessed by the resume code before it can restore the MMU.
-	@@ This means that the variable has to be close enough for the
-	@@ code to read it... since the .text segment needs to be RO,
-	@@ the data segment can be the only place to put this code.
-
-	.data
-
-	.global	s3c2410_sleep_save_phys
-s3c2410_sleep_save_phys:
-	.word	0
-
-	/* s3c2410_cpu_resume
-	 *
-	 * resume code entry for bootloader to call
-	 *
-	 * we must put this code here in the data segment as we have no
-	 * other way of restoring the stack pointer after sleep, and we
-	 * must not write to the code segment (code is read-only)
-	*/
-
-ENTRY(s3c2410_cpu_resume)
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
-	msr	cpsr_c, r0
-
-	@@ load UART to allow us to print the two characters for
-	@@ resume debug
-
-	mov	r2, #S3C24XX_PA_UART & 0xff000000
-	orr	r2, r2, #S3C24XX_PA_UART & 0xff000
-
-#if 0
-	/* SMDK2440 LED set */
-	mov	r14, #S3C24XX_PA_GPIO
-	ldr	r12, [ r14, #0x54 ]
-	bic	r12, r12, #3<<4
-	orr	r12, r12, #1<<7
-	str	r12, [ r14, #0x54 ]
-#endif
-
-#ifdef CONFIG_DEBUG_RESUME
-	mov	r3, #'L'
-	strb	r3, [ r2, #S3C2410_UTXH ]
-1001:
-	ldrb	r14, [ r3, #S3C2410_UTRSTAT ]
-	tst	r14, #S3C2410_UTRSTAT_TXE
-	beq	1001b
-#endif /* CONFIG_DEBUG_RESUME */
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0		@@ invalidate I & D TLBs
-	mcr	p15, 0, r1, c7, c7, 0		@@ invalidate I & D caches
-
-	ldr	r0, s3c2410_sleep_save_phys	@ address of restore block
-	ldmia	r0, { r4 - r13 }
-
-	mcr	p15, 0, r4, c15, c1, 0		@ CP access register
-	mcr	p15, 0, r5, c13, c0, 0		@ PID
-	mcr	p15, 0, r6, c3, c0, 0		@ Domain ID
-	mcr	p15, 0, r7, c2, c0, 0		@ translation table base
-
-#ifdef CONFIG_DEBUG_RESUME
-	mov	r3, #'R'
-	strb	r3, [ r2, #S3C2410_UTXH ]
-#endif
-
-	ldr	r2, =resume_with_mmu
-	mcr	p15, 0, r8, c1, c0, 0		@ turn on MMU, etc
-	nop					@ second-to-last before mmu
-	mov	pc, r2				@ go back to virtual address
-
-	.ltorg
+	@@ align next bit of code to cache line
+	.align	5
+s3c2410_do_sleep:
+	streq	r7, [ r4 ]			@ SDRAM sleep command
+	streq	r8, [ r5 ]			@ SDRAM power-down config
+	streq	r9, [ r6 ]			@ CPU sleep
+1:	beq	1b
+	mov	pc, r14
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
deleted file mode 100644
index 9910bf0..0000000
--- a/arch/arm/mach-s3c2410/time.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/time.c
- *
- * Copyright (C) 2003-2005 Simtec Electronics
- *	Ben Dooks, <ben@simtec.co.uk>
- *
- * 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/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-
-#include <asm/system.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/arch/map.h>
-#include <asm/arch/regs-timer.h>
-#include <asm/arch/regs-irq.h>
-#include <asm/mach/time.h>
-
-#include "clock.h"
-#include "cpu.h"
-
-static unsigned long timer_startval;
-static unsigned long timer_usec_ticks;
-
-#define TIMER_USEC_SHIFT 16
-
-/* we use the shifted arithmetic to work out the ratio of timer ticks
- * to usecs, as often the peripheral clock is not a nice even multiple
- * of 1MHz.
- *
- * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok
- * for the current HZ value of 200 without producing overflows.
- *
- * Original patch by Dimitry Andric, updated by Ben Dooks
-*/
-
-
-/* timer_mask_usec_ticks
- *
- * given a clock and divisor, make the value to pass into timer_ticks_to_usec
- * to scale the ticks into usecs
-*/
-
-static inline unsigned long
-timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk)
-{
-	unsigned long den = pclk / 1000;
-
-	return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den;
-}
-
-/* timer_ticks_to_usec
- *
- * convert timer ticks to usec.
-*/
-
-static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
-{
-	unsigned long res;
-
-	res = ticks * timer_usec_ticks;
-	res += 1 << (TIMER_USEC_SHIFT - 4);	/* round up slightly */
-
-	return res >> TIMER_USEC_SHIFT;
-}
-
-/***
- * Returns microsecond  since last clock interrupt.  Note that interrupts
- * will have been disabled by do_gettimeoffset()
- * IRQs are disabled before entering here from do_gettimeofday()
- */
-
-#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0))
-
-static unsigned long s3c2410_gettimeoffset (void)
-{
-	unsigned long tdone;
-	unsigned long irqpend;
-	unsigned long tval;
-
-	/* work out how many ticks have gone since last timer interrupt */
-
-        tval =  __raw_readl(S3C2410_TCNTO(4));
-	tdone = timer_startval - tval;
-
-	/* check to see if there is an interrupt pending */
-
-	irqpend = __raw_readl(S3C2410_SRCPND);
-	if (irqpend & SRCPND_TIMER4) {
-		/* re-read the timer, and try and fix up for the missed
-		 * interrupt. Note, the interrupt may go off before the
-		 * timer has re-loaded from wrapping.
-		 */
-
-		tval =  __raw_readl(S3C2410_TCNTO(4));
-		tdone = timer_startval - tval;
-
-		if (tval != 0)
-			tdone += timer_startval;
-	}
-
-	return timer_ticks_to_usec(tdone);
-}
-
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-s3c2410_timer_interrupt(int irq, void *dev_id)
-{
-	write_seqlock(&xtime_lock);
-	timer_tick();
-	write_sequnlock(&xtime_lock);
-	return IRQ_HANDLED;
-}
-
-static struct irqaction s3c2410_timer_irq = {
-	.name		= "S3C2410 Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER,
-	.handler	= s3c2410_timer_interrupt,
-};
-
-#define use_tclk1_12() ( \
-	machine_is_bast()	|| \
-	machine_is_vr1000()	|| \
-	machine_is_anubis()	|| \
-	machine_is_osiris() )
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- *
- * Currently we only use timer4, as it is the only timer which has no
- * other function that can be exploited externally
- */
-static void s3c2410_timer_setup (void)
-{
-	unsigned long tcon;
-	unsigned long tcnt;
-	unsigned long tcfg1;
-	unsigned long tcfg0;
-
-	tcnt = 0xffff;  /* default value for tcnt */
-
-	/* read the current timer configuration bits */
-
-	tcon = __raw_readl(S3C2410_TCON);
-	tcfg1 = __raw_readl(S3C2410_TCFG1);
-	tcfg0 = __raw_readl(S3C2410_TCFG0);
-
-	/* configure the system for whichever machine is in use */
-
-	if (use_tclk1_12()) {
-		/* timer is at 12MHz, scaler is 1 */
-		timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
-		tcnt = 12000000 / HZ;
-
-		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
-		tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
-	} else {
-		unsigned long pclk;
-		struct clk *clk;
-
-		/* for the h1940 (and others), we use the pclk from the core
-		 * to generate the timer values. since values around 50 to
-		 * 70MHz are not values we can directly generate the timer
-		 * value from, we need to pre-scale and divide before using it.
-		 *
-		 * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz
-		 * (8.45 ticks per usec)
-		 */
-
-		/* this is used as default if no other timer can be found */
-
-		clk = clk_get(NULL, "timers");
-		if (IS_ERR(clk))
-			panic("failed to get clock for system timer");
-
-		clk_enable(clk);
-
-		pclk = clk_get_rate(clk);
-
-		/* configure clock tick */
-
-		timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
-
-		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
-		tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
-
-		tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
-		tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
-
-		tcnt = (pclk / 6) / HZ;
-	}
-
-	/* timers reload after counting zero, so reduce the count by 1 */
-
-	tcnt--;
-
-	printk("timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n",
-	       tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks);
-
-	/* check to see if timer is within 16bit range... */
-	if (tcnt > 0xffff) {
-		panic("setup_timer: HZ is too small, cannot configure timer!");
-		return;
-	}
-
-	__raw_writel(tcfg1, S3C2410_TCFG1);
-	__raw_writel(tcfg0, S3C2410_TCFG0);
-
-	timer_startval = tcnt;
-	__raw_writel(tcnt, S3C2410_TCNTB(4));
-
-	/* ensure timer is stopped... */
-
-	tcon &= ~(7<<20);
-	tcon |= S3C2410_TCON_T4RELOAD;
-	tcon |= S3C2410_TCON_T4MANUALUPD;
-
-	__raw_writel(tcon, S3C2410_TCON);
-	__raw_writel(tcnt, S3C2410_TCNTB(4));
-	__raw_writel(tcnt, S3C2410_TCMPB(4));
-
-	/* start the timer running */
-	tcon |= S3C2410_TCON_T4START;
-	tcon &= ~S3C2410_TCON_T4MANUALUPD;
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void __init s3c2410_timer_init (void)
-{
-	s3c2410_timer_setup();
-	setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
-}
-
-struct sys_timer s3c24xx_timer = {
-	.init		= s3c2410_timer_init,
-	.offset		= s3c2410_gettimeoffset,
-	.resume		= s3c2410_timer_setup
-};
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index 22b0e1c..bcd562a 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -35,7 +35,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "devs.h"
+#include <asm/plat-s3c24xx/devs.h>
 #include "usb-simtec.h"
 
 /* control power and monitor over-current events on various Simtec
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
new file mode 100644
index 0000000..befc5fd
--- /dev/null
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -0,0 +1,58 @@
+# arch/arm/mach-s3c2412/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2412
+	bool
+	depends on ARCH_S3C2410
+	select S3C2412_PM if PM
+	select S3C2412_DMA if S3C2410_DMA
+	help
+	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
+
+config CPU_S3C2412_ONLY
+	bool
+	depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
+		   !CPU_S3C2440 && !CPU_S3C2442 && !CPU_S3C2443 && CPU_S3C2412
+	default y if CPU_S3C2412
+
+config S3C2412_DMA
+	bool
+	depends on CPU_S3C2412
+	help
+	  Internal config node for S3C2412 DMA support
+
+config S3C2412_PM
+	bool
+	help
+	  Internal config node to apply S3C2412 power management
+
+
+menu "S3C2412 Machines"
+
+config MACH_SMDK2413
+	bool "SMDK2413"
+	select CPU_S3C2412
+	select MACH_S3C2413
+	select MACH_SMDK
+	help
+	  Say Y here if you are using an SMDK2413
+
+config MACH_S3C2413
+	bool
+	help
+	  Internal node for S3C2413 version of SMDK2413, so that
+	  machine_is_s3c2413() will work when MACH_SMDK2413 is
+	  selected
+
+config MACH_VSTMS
+	bool "VMSTMS"
+	select CPU_S3C2412
+	help
+	  Say Y here if you are using an VSTMS board
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile
new file mode 100644
index 0000000..f8e0116
--- /dev/null
+++ b/arch/arm/mach-s3c2412/Makefile
@@ -0,0 +1,21 @@
+# arch/arm/mach-s3c2412/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o
+obj-$(CONFIG_CPU_S3C2412)	+= irq.o
+obj-$(CONFIG_CPU_S3C2412)	+= clock.o
+obj-$(CONFIG_S3C2412_DMA)	+= dma.o
+obj-$(CONFIG_S3C2412_PM)	+= pm.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_SMDK2413)	+= mach-smdk2413.o
+obj-$(CONFIG_MACH_VSTMS)	+= mach-vstms.o
diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c
new file mode 100644
index 0000000..6a8e444
--- /dev/null
+++ b/arch/arm/mach-s3c2412/clock.c
@@ -0,0 +1,716 @@
+/* linux/arch/arm/mach-s3c2412/clock.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2412,S3C2413 Clock control support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/map.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* We currently have to assume that the system is running
+ * from the XTPll input, and that all ***REFCLKs are being
+ * fed from it, as we cannot read the state of OM[4] from
+ * software.
+ *
+ * It would be possible for each board initialisation to
+ * set the correct muxing at initialisation
+*/
+
+static int s3c2412_clkcon_enable(struct clk *clk, int enable)
+{
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
+
+	clkcon = __raw_readl(S3C2410_CLKCON);
+
+	if (enable)
+		clkcon |= clocks;
+	else
+		clkcon &= ~clocks;
+
+	__raw_writel(clkcon, S3C2410_CLKCON);
+
+	return 0;
+}
+
+static int s3c2412_upll_enable(struct clk *clk, int enable)
+{
+	unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
+	unsigned long orig = upllcon;
+
+	if (!enable)
+		upllcon |= S3C2412_PLLCON_OFF;
+	else
+		upllcon &= ~S3C2412_PLLCON_OFF;
+
+	__raw_writel(upllcon, S3C2410_UPLLCON);
+
+	/* allow ~150uS for the PLL to settle and lock */
+
+	if (enable && (orig & S3C2412_PLLCON_OFF))
+		udelay(150);
+
+	return 0;
+}
+
+/* clock selections */
+
+/* CPU EXTCLK input */
+static struct clk clk_ext = {
+	.name		= "extclk",
+	.id		= -1,
+};
+
+static struct clk clk_erefclk = {
+	.name		= "erefclk",
+	.id		= -1,
+};
+
+static struct clk clk_urefclk = {
+	.name		= "urefclk",
+	.id		= -1,
+};
+
+static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_urefclk)
+		clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL;
+	else if (parent == &clk_upll)
+		clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static struct clk clk_usysclk = {
+	.name		= "usysclk",
+	.id		= -1,
+	.parent		= &clk_xtal,
+	.set_parent	= s3c2412_setparent_usysclk,
+};
+
+static struct clk clk_mrefclk = {
+	.name		= "mrefclk",
+	.parent		= &clk_xtal,
+	.id		= -1,
+};
+
+static struct clk clk_mdivclk = {
+	.name		= "mdivclk",
+	.parent		= &clk_xtal,
+	.id		= -1,
+};
+
+static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_usysclk)
+		clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK;
+	else if (parent == &clk_h)
+		clksrc |= S3C2412_CLKSRC_USBCLK_HCLK;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	div = parent_rate / rate;
+	if (div > 2)
+		div = 2;
+
+	return parent_rate / div;
+}
+
+static unsigned long s3c2412_getrate_usbsrc(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1);
+}
+
+static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_usbsrc(clk, rate);
+
+	if ((parent_rate / rate) == 2)
+		clkdivn |= S3C2412_CLKDIVN_USB48DIV;
+	else
+		clkdivn &= ~S3C2412_CLKDIVN_USB48DIV;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_usbsrc = {
+	.name		= "usbsrc",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_usbsrc,
+	.set_rate	= s3c2412_setrate_usbsrc,
+	.round_rate	= s3c2412_roundrate_usbsrc,
+	.set_parent	= s3c2412_setparent_usbsrc,
+};
+
+static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_mdivclk)
+		clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL;
+	else if (parent == &clk_upll)
+		clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static struct clk clk_msysclk = {
+	.name		= "msysclk",
+	.id		= -1,
+	.set_parent	= s3c2412_setparent_msysclk,
+};
+
+/* these next clocks have an divider immediately after them,
+ * so we can register them with their divider and leave out the
+ * intermediate clock stage
+*/
+static unsigned long s3c2412_roundrate_clksrc(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	/* note, we remove the +/- 1 calculations as they cancel out */
+
+	div = (rate / parent_rate);
+
+	if (div < 1)
+		div = 1;
+	else if (div > 16)
+		div = 16;
+
+	return parent_rate / div;
+}
+
+static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_erefclk)
+		clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL;
+	else if (parent == &clk_mpll)
+		clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_getrate_uart(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_UARTDIV_MASK;
+	div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_uart = {
+	.name		= "uartclk",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_uart,
+	.set_rate	= s3c2412_setrate_uart,
+	.set_parent	= s3c2412_setparent_uart,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_erefclk)
+		clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL;
+	else if (parent == &clk_mpll)
+		clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_getrate_i2s(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_I2SDIV_MASK;
+	div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_i2s = {
+	.name		= "i2sclk",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_i2s,
+	.set_rate	= s3c2412_setrate_i2s,
+	.set_parent	= s3c2412_setparent_i2s,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_usysclk)
+		clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK;
+	else if (parent == &clk_h)
+		clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+static unsigned long s3c2412_getrate_cam(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_CAMDIV_MASK;
+	div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_cam = {
+	.name		= "camif-upll",	/* same as 2440 name */
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_cam,
+	.set_rate	= s3c2412_setrate_cam,
+	.set_parent	= s3c2412_setparent_cam,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_NAND,
+	}, {
+		.name		= "sdi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_SDI,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_ADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_IIC,
+	}, {
+		.name		= "iis",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_IIS,
+	}, {
+		.name		= "spi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_SPI,
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "dma",
+		.id		= 0,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA0,
+	}, {
+		.name		= "dma",
+		.id		= 1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA1,
+	}, {
+		.name		= "dma",
+		.id		= 2,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA2,
+	}, {
+		.name		= "dma",
+		.id		= 3,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA3,
+	}, {
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_LCDC,
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_GPIO,
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USBH,
+	}, {
+		.name		= "usb-device",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USBD,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_PWMT,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART2,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= 0,
+	}, {
+		.name		= "usb-bus-gadget",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USB_DEV48,
+	}, {
+		.name		= "usb-bus-host",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USB_HOST48,
+	}
+};
+
+/* clocks to add where we need to check their parentage */
+
+struct clk_init {
+	struct clk	*clk;
+	unsigned int	 bit;
+	struct clk	*src_0;
+	struct clk	*src_1;
+};
+
+static struct clk_init clks_src[] __initdata = {
+	{
+		.clk	= &clk_usysclk,
+		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
+		.src_0	= &clk_urefclk,
+		.src_1	= &clk_upll,
+	}, {
+		.clk	= &clk_i2s,
+		.bit	= S3C2412_CLKSRC_I2SCLK_MPLL,
+		.src_0	= &clk_erefclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_cam,
+		.bit	= S3C2412_CLKSRC_CAMCLK_HCLK,
+		.src_0	= &clk_usysclk,
+		.src_1	= &clk_h,
+	}, {
+		.clk	= &clk_msysclk,
+		.bit	= S3C2412_CLKSRC_MSYSCLK_MPLL,
+		.src_0	= &clk_mdivclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_uart,
+		.bit	= S3C2412_CLKSRC_UARTCLK_MPLL,
+		.src_0	= &clk_erefclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_usbsrc,
+		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
+		.src_0	= &clk_usysclk,
+		.src_1	= &clk_h,
+	},
+};
+
+/* s3c2412_clk_initparents
+ *
+ * Initialise the parents for the clocks that we get at start-time
+*/
+
+static void __init s3c2412_clk_initparents(void)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+	struct clk_init *cip = clks_src;
+	struct clk *src;
+	int ptr;
+	int ret;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) {
+		ret = s3c24xx_register_clock(cip->clk);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       cip->clk->name, ret);
+		}
+
+		src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0;
+
+		printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name);
+		clk_set_parent(cip->clk, src);
+	}
+}
+
+/* clocks to add straight away */
+
+static struct clk *clks[] __initdata = {
+	&clk_ext,
+	&clk_usb_bus,
+	&clk_erefclk,
+	&clk_urefclk,
+	&clk_mrefclk,
+};
+
+int __init s3c2412_baseclk_add(void)
+{
+	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+	struct clk *clkp;
+	int ret;
+	int ptr;
+
+	clk_upll.enable = s3c2412_upll_enable;
+	clk_usb_bus.parent = &clk_usbsrc;
+	clk_usb_bus.rate = 0x0;
+
+	s3c2412_clk_initparents();
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
+		clkp = clks[ptr];
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* ensure usb bus clock is within correct rate of 48MHz */
+
+	if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) {
+		printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n");
+
+		/* for the moment, let's use the UPLL, and see if we can
+		 * get 48MHz */
+
+		clk_set_parent(&clk_usysclk, &clk_upll);
+		clk_set_parent(&clk_usbsrc, &clk_usysclk);
+		clk_set_rate(&clk_usbsrc, 48*1000*1000);
+	}
+
+	printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
+	       (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on",
+	       print_mhz(clk_get_rate(&clk_upll)),
+	       print_mhz(clk_get_rate(&clk_usb_bus)));
+
+	/* register clocks from clock array */
+
+	clkp = init_clocks;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+		/* ensure that we note the clock state */
+
+		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* We must be careful disabling the clocks we are not intending to
+	 * be using at boot time, as subsytems such as the LCD which do
+	 * their own DMA requests to the bus can cause the system to lockup
+	 * if they where in the middle of requesting bus access.
+	 *
+	 * Disabling the LCD clock if the LCD is active is very dangerous,
+	 * and therefore the bootloader should be careful to not enable
+	 * the LCD clock if it is not needed.
+	*/
+
+	/* install (and disable) the clocks we do not need immediately */
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+
+		s3c2412_clkcon_enable(clkp, 0);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
new file mode 100644
index 0000000..d0f4695
--- /dev/null
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -0,0 +1,162 @@
+/* linux/arch/arm/mach-s3c2412/dma.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2412 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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/sysdev.h>
+#include <linux/serial_core.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include <asm/io.h>
+
+#include <asm/plat-s3c24xx/dma.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+#define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
+
+static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
+	[DMACH_XD0] = {
+		.name		= "xdreq0",
+		.channels	= MAP(S3C2412_DMAREQSEL_XDREQ0),
+	},
+	[DMACH_XD1] = {
+		.name		= "xdreq1",
+		.channels	= MAP(S3C2412_DMAREQSEL_XDREQ1),
+	},
+	[DMACH_SDI] = {
+		.name		= "sdi",
+		.channels	= MAP(S3C2412_DMAREQSEL_SDI),
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_SPI0] = {
+		.name		= "spi0",
+		.channels	= MAP(S3C2412_DMAREQSEL_SPI0TX),
+		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
+	},
+	[DMACH_SPI1] = {
+		.name		= "spi1",
+		.channels	= MAP(S3C2412_DMAREQSEL_SPI1TX),
+		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+	},
+	[DMACH_UART0] = {
+		.name		= "uart0",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART0_0),
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1] = {
+		.name		= "uart1",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART1_0),
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2] = {
+		.name		= "uart2",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART2_0),
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+	[DMACH_UART0_SRC2] = {
+		.name		= "uart0",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART0_1),
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1_SRC2] = {
+		.name		= "uart1",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART1_1),
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2_SRC2] = {
+		.name		= "uart2",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART2_1),
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+	[DMACH_TIMER] = {
+		.name		= "timer",
+		.channels	= MAP(S3C2412_DMAREQSEL_TIMER),
+	},
+	[DMACH_I2S_IN] = {
+		.name		= "i2s-sdi",
+		.channels	= MAP(S3C2412_DMAREQSEL_I2SRX),
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_I2S_OUT] = {
+		.name		= "i2s-sdo",
+		.channels	= MAP(S3C2412_DMAREQSEL_I2STX),
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_USB_EP1] = {
+		.name		= "usb-ep1",
+		.channels	= MAP(S3C2412_DMAREQSEL_USBEP1),
+	},
+	[DMACH_USB_EP2] = {
+		.name		= "usb-ep2",
+		.channels	= MAP(S3C2412_DMAREQSEL_USBEP2),
+	},
+	[DMACH_USB_EP3] = {
+		.name		= "usb-ep3",
+		.channels	= MAP(S3C2412_DMAREQSEL_USBEP3),
+	},
+	[DMACH_USB_EP4] = {
+		.name		= "usb-ep4",
+		.channels	= MAP(S3C2412_DMAREQSEL_USBEP4),
+	},
+};
+
+static void s3c2412_dma_select(struct s3c2410_dma_chan *chan,
+			       struct s3c24xx_dma_map *map)
+{
+	writel(map->channels[0] | S3C2412_DMAREQSEL_HW,
+	       chan->regs + S3C2412_DMA_DMAREQSEL);
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
+	.select		= s3c2412_dma_select,
+	.dcon_mask	= 0,
+	.map		= s3c2412_dma_mappings,
+	.map_size	= ARRAY_SIZE(s3c2412_dma_mappings),
+};
+
+static int s3c2412_dma_add(struct sys_device *sysdev)
+{
+	s3c2410_dma_init();
+	return s3c24xx_dma_init_map(&s3c2412_dma_sel);
+}
+
+static struct sysdev_driver s3c2412_dma_driver = {
+	.add	= s3c2412_dma_add,
+};
+
+static int __init s3c2412_dma_init(void)
+{
+	return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_dma_driver);
+}
+
+arch_initcall(s3c2412_dma_init);
diff --git a/arch/arm/mach-s3c2412/irq.c b/arch/arm/mach-s3c2412/irq.c
new file mode 100644
index 0000000..e89dbdc
--- /dev/null
+++ b/arch/arm/mach-s3c2412/irq.c
@@ -0,0 +1,133 @@
+/* linux/arch/arm/mach-s3c2412/irq.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/irq.h>
+#include <asm/plat-s3c24xx/pm.h>
+
+/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
+ * having them turn up in both the INT* and the EINT* registers. Whilst
+ * both show the status, they both now need to be acked when the IRQs
+ * go off.
+*/
+
+static void
+s3c2412_irq_mask(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long mask;
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	__raw_writel(mask | bitval, S3C2410_INTMSK);
+
+	mask = __raw_readl(S3C2412_EINTMASK);
+	__raw_writel(mask | bitval, S3C2412_EINTMASK);
+}
+
+static inline void
+s3c2412_irq_ack(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+
+	__raw_writel(bitval, S3C2412_EINTPEND);
+	__raw_writel(bitval, S3C2410_SRCPND);
+	__raw_writel(bitval, S3C2410_INTPND);
+}
+
+static inline void
+s3c2412_irq_maskack(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long mask;
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	__raw_writel(mask|bitval, S3C2410_INTMSK);
+
+	mask = __raw_readl(S3C2412_EINTMASK);
+	__raw_writel(mask | bitval, S3C2412_EINTMASK);
+
+	__raw_writel(bitval, S3C2412_EINTPEND);
+	__raw_writel(bitval, S3C2410_SRCPND);
+	__raw_writel(bitval, S3C2410_INTPND);
+}
+
+static void
+s3c2412_irq_unmask(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long mask;
+
+	mask = __raw_readl(S3C2412_EINTMASK);
+	__raw_writel(mask & ~bitval, S3C2412_EINTMASK);
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	__raw_writel(mask & ~bitval, S3C2410_INTMSK);
+}
+
+static struct irq_chip s3c2412_irq_eint0t4 = {
+	.ack	   = s3c2412_irq_ack,
+	.mask	   = s3c2412_irq_mask,
+	.unmask	   = s3c2412_irq_unmask,
+	.set_wake  = s3c_irq_wake,
+	.set_type  = s3c_irqext_type,
+};
+
+static int s3c2412_irq_add(struct sys_device *sysdev)
+{
+	unsigned int irqno;
+
+	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+		set_irq_chip(irqno, &s3c2412_irq_eint0t4);
+		set_irq_handler(irqno, handle_edge_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2412_irq_driver = {
+	.add		= s3c2412_irq_add,
+	.suspend	= s3c24xx_irq_suspend,
+	.resume		= s3c24xx_irq_resume,
+};
+
+static int s3c2412_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_irq_driver);
+}
+
+arch_initcall(s3c2412_irq_init);
diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c
new file mode 100644
index 0000000..b5befce
--- /dev/null
+++ b/arch/arm/mach-s3c2412/mach-smdk2413.c
@@ -0,0 +1,192 @@
+/* linux/arch/arm/mach-s3c2412/mach-smdk2413.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the
+ * loans of SMDK2413 to work with.
+ *
+ * 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/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+//#include <asm/debug-ll.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/udc.h>
+#include <asm/arch/fb.h>
+
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/plat-s3c24xx/common-smdk.h>
+
+static struct map_desc smdk2413_iodesc[] __initdata = {
+};
+
+static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	/* IR port */
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x43,
+		.ufcon	     = 0x51,
+	}
+};
+
+static void smdk2413_udc_pullup(enum s3c2410_udc_cmd_e cmd)
+{
+	printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
+
+	switch (cmd)
+	{
+		case S3C2410_UDC_P_ENABLE :
+			s3c2410_gpio_setpin(S3C2410_GPF2, 1);
+			break;
+		case S3C2410_UDC_P_DISABLE :
+			s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+			break;
+		case S3C2410_UDC_P_RESET :
+			break;
+		default:
+			break;
+	}
+}
+
+
+static struct s3c2410_udc_mach_info smdk2413_udc_cfg __initdata = {
+	.udc_command		= smdk2413_udc_pullup,
+};
+
+
+static struct platform_device *smdk2413_devices[] __initdata = {
+	&s3c_device_usb,
+	//&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+	&s3c_device_usbgadget,
+};
+
+static struct s3c24xx_board smdk2413_board __initdata = {
+	.devices       = smdk2413_devices,
+	.devices_count = ARRAY_SIZE(smdk2413_devices)
+};
+
+static void __init smdk2413_fixup(struct machine_desc *desc,
+				  struct tag *tags, char **cmdline,
+				  struct meminfo *mi)
+{
+	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
+		mi->nr_banks=1;
+		mi->bank[0].start = 0x30000000;
+		mi->bank[0].size = SZ_64M;
+		mi->bank[0].node = 0;
+	}
+}
+
+static void __init smdk2413_map_io(void)
+{
+	s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
+	s3c24xx_set_board(&smdk2413_board);
+}
+
+static void __init smdk2413_machine_init(void)
+{	/* Turn off suspend on both USB ports, and switch the
+	 * selectable USB port to USB device mode. */
+
+	s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+	s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPIO_OUTPUT);
+
+	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
+			      S3C2410_MISCCR_USBSUSPND0 |
+			      S3C2410_MISCCR_USBSUSPND1, 0x0);
+
+
+ 	s3c24xx_udc_set_platdata(&smdk2413_udc_cfg);
+
+	smdk_machine_init();
+}
+
+MACHINE_START(S3C2413, "S3C2413")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.fixup		= smdk2413_fixup,
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= smdk2413_map_io,
+	.init_machine	= smdk2413_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
+
+MACHINE_START(SMDK2412, "SMDK2412")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.fixup		= smdk2413_fixup,
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= smdk2413_map_io,
+	.init_machine	= smdk2413_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
+
+MACHINE_START(SMDK2413, "SMDK2413")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.fixup		= smdk2413_fixup,
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= smdk2413_map_io,
+	.init_machine	= smdk2413_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2412/mach-vstms.c b/arch/arm/mach-s3c2412/mach-vstms.c
new file mode 100644
index 0000000..4231b54
--- /dev/null
+++ b/arch/arm/mach-s3c2412/mach-vstms.c
@@ -0,0 +1,168 @@
+/* linux/arch/arm/mach-s3c2412/mach-vstms.c
+ *
+ * (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Derived from mach-smdk2413.c - (C) 2006 Simtec Electronics
+ *
+ * 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/serial_core.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/setup.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include <asm/arch/nand.h>
+
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+
+static struct map_desc vstms_iodesc[] __initdata = {
+};
+
+static struct s3c2410_uartcfg vstms_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	}
+};
+
+static struct mtd_partition vstms_nand_part[] = {
+	[0] = {
+		.name	= "Boot Agent",
+		.size	= 0x7C000,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "UBoot Config",
+		.offset = 0x7C000,
+		.size	= 0x4000,
+	},
+	[2] = {
+		.name	= "Kernel",
+		.offset = 0x80000,
+		.size	= 0x200000,
+	},
+	[3] = {
+		.name	= "RFS",
+		.offset	= 0x280000,
+		.size	= 0x3d80000,
+	},
+};
+
+static struct s3c2410_nand_set vstms_nand_sets[] = {
+	[0] = {
+		.name		= "NAND",
+		.nr_chips	= 1,
+		.nr_partitions	= ARRAY_SIZE(vstms_nand_part),
+		.partitions	= vstms_nand_part,
+	},
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+*/
+
+static struct s3c2410_platform_nand vstms_nand_info = {
+	.tacls		= 20,
+	.twrph0		= 60,
+	.twrph1		= 20,
+	.nr_sets	= ARRAY_SIZE(vstms_nand_sets),
+	.sets		= vstms_nand_sets,
+};
+
+static struct platform_device *vstms_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+	&s3c_device_rtc,
+	&s3c_device_nand,
+};
+
+static struct s3c24xx_board vstms_board __initdata = {
+	.devices       = vstms_devices,
+	.devices_count = ARRAY_SIZE(vstms_devices)
+};
+
+static void __init vstms_fixup(struct machine_desc *desc,
+				  struct tag *tags, char **cmdline,
+				  struct meminfo *mi)
+{
+	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
+		mi->nr_banks=1;
+		mi->bank[0].start = 0x30000000;
+		mi->bank[0].size = SZ_64M;
+		mi->bank[0].node = 0;
+	}
+}
+
+static void __init vstms_map_io(void)
+{
+	s3c_device_nand.dev.platform_data = &vstms_nand_info;
+
+	s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
+	s3c24xx_set_board(&vstms_board);
+}
+
+MACHINE_START(VSTMS, "VSTMS")
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.fixup		= vstms_fixup,
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= vstms_map_io,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c
new file mode 100644
index 0000000..8988dac
--- /dev/null
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -0,0 +1,128 @@
+/* linux/arch/arm/mach-s3c2412/pm.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/.
+ *
+ * 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/sysdev.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-dsc.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+
+#include <asm/plat-s3c24xx/s3c2412.h>
+
+static void s3c2412_cpu_suspend(void)
+{
+	unsigned long tmp;
+
+	/* set our standby method to sleep */
+
+	tmp = __raw_readl(S3C2412_PWRCFG);
+	tmp |= S3C2412_PWRCFG_STANDBYWFI_SLEEP;
+	__raw_writel(tmp, S3C2412_PWRCFG);
+
+	/* issue the standby signal into the pm unit. Note, we
+	 * issue a write-buffer drain just in case */
+
+	tmp = 0;
+
+	asm("b 1f\n\t"
+	    ".align 5\n\t"
+	    "1:\n\t"
+	    "mcr p15, 0, %0, c7, c10, 4\n\t"
+	    "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
+
+	/* we should never get past here */
+
+	panic("sleep resumed to originator?");
+}
+
+static void s3c2412_pm_prepare(void)
+{
+}
+
+static int s3c2412_pm_add(struct sys_device *sysdev)
+{
+	pm_cpu_prep = s3c2412_pm_prepare;
+	pm_cpu_sleep = s3c2412_cpu_suspend;
+
+	return 0;
+}
+
+static struct sleep_save s3c2412_sleep[] = {
+	SAVE_ITEM(S3C2412_DSC0),
+	SAVE_ITEM(S3C2412_DSC1),
+	SAVE_ITEM(S3C2413_GPJDAT),
+	SAVE_ITEM(S3C2413_GPJCON),
+	SAVE_ITEM(S3C2413_GPJUP),
+
+	/* save the PWRCFG to get back to original sleep method */
+
+	SAVE_ITEM(S3C2412_PWRCFG),
+
+	/* save the sleep configuration anyway, just in case these
+	 * get damaged during wakeup */
+
+	SAVE_ITEM(S3C2412_GPBSLPCON),
+	SAVE_ITEM(S3C2412_GPCSLPCON),
+	SAVE_ITEM(S3C2412_GPDSLPCON),
+	SAVE_ITEM(S3C2412_GPESLPCON),
+	SAVE_ITEM(S3C2412_GPFSLPCON),
+	SAVE_ITEM(S3C2412_GPGSLPCON),
+	SAVE_ITEM(S3C2412_GPHSLPCON),
+	SAVE_ITEM(S3C2413_GPJSLPCON),
+};
+
+static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state)
+{
+	s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	return 0;
+}
+
+static int s3c2412_pm_resume(struct sys_device *dev)
+{
+	unsigned long tmp;
+
+	tmp = __raw_readl(S3C2412_PWRCFG);
+	tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK;
+	tmp |=  S3C2412_PWRCFG_STANDBYWFI_IDLE;
+	__raw_writel(tmp, S3C2412_PWRCFG);
+
+	s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	return 0;
+}
+
+static struct sysdev_driver s3c2412_pm_driver = {
+	.add		= s3c2412_pm_add,
+	.suspend	= s3c2412_pm_suspend,
+	.resume		= s3c2412_pm_resume,
+};
+
+static __init int s3c2412_pm_init(void)
+{
+	return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver);
+}
+
+arch_initcall(s3c2412_pm_init);
diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
new file mode 100644
index 0000000..aafe0bc
--- /dev/null
+++ b/arch/arm/mach-s3c2412/s3c2412.c
@@ -0,0 +1,181 @@
+/* linux/arch/arm/mach-s3c2412/s3c2412.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/.
+ *
+ * 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/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/proc-fns.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/idle.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/pm.h>
+
+#ifndef CONFIG_CPU_S3C2412_ONLY
+void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
+
+static inline void s3c2412_init_gpio2(void)
+{
+	s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
+}
+#else
+#define s3c2412_init_gpio2() do { } while(0)
+#endif
+
+/* Initial IO mappings */
+
+static struct map_desc s3c2412_iodesc[] __initdata = {
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(LCD),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(WATCHDOG),
+};
+
+/* uart registration process */
+
+void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c24xx_init_uartdevs("s3c2412-uart", s3c2410_uart_resources, cfg, no);
+
+	/* rename devices that are s3c2412/s3c2413 specific */
+	s3c_device_sdi.name  = "s3c2412-sdi";
+	s3c_device_lcd.name  = "s3c2412-lcd";
+	s3c_device_nand.name = "s3c2412-nand";
+}
+
+/* s3c2412_idle
+ *
+ * use the standard idle call by ensuring the idle mode
+ * in power config, then issuing the idle co-processor
+ * instruction
+*/
+
+static void s3c2412_idle(void)
+{
+	unsigned long tmp;
+
+	/* ensure our idle mode is to go to idle */
+
+	tmp = __raw_readl(S3C2412_PWRCFG);
+	tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK;
+	tmp |= S3C2412_PWRCFG_STANDBYWFI_IDLE;
+	__raw_writel(tmp, S3C2412_PWRCFG);
+
+	cpu_do_idle();
+}
+
+/* s3c2412_map_io
+ *
+ * register the standard cpu IO areas, and any passed in from the
+ * machine specific initialisation.
+*/
+
+void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size)
+{
+	/* move base of IO */
+
+	s3c2412_init_gpio2();
+
+	/* set our idle function */
+
+	s3c24xx_idle = s3c2412_idle;
+
+	/* register our io-tables */
+
+	iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
+	iotable_init(mach_desc, mach_size);
+}
+
+void __init s3c2412_init_clocks(int xtal)
+{
+	unsigned long tmp;
+	unsigned long fclk;
+	unsigned long hclk;
+	unsigned long pclk;
+
+	/* now we've got our machine bits initialised, work out what
+	 * clocks we've got */
+
+	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2);
+
+	tmp = __raw_readl(S3C2410_CLKDIVN);
+
+	/* work out clock scalings */
+
+	hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
+	hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1);
+	pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
+
+	/* print brieft summary of clocks, etc */
+
+	printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+	/* initialise the clocks here, to allow other things like the
+	 * console to use them
+	 */
+
+	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+	s3c2412_baseclk_add();
+}
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2412 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+struct sysdev_class s3c2412_sysclass = {
+	set_kset_name("s3c2412-core"),
+};
+
+static int __init s3c2412_core_init(void)
+{
+	return sysdev_class_register(&s3c2412_sysclass);
+}
+
+core_initcall(s3c2412_core_init);
+
+static struct sys_device s3c2412_sysdev = {
+	.cls		= &s3c2412_sysclass,
+};
+
+int __init s3c2412_init(void)
+{
+	printk("S3C2412: Initialising architecture\n");
+
+	return sysdev_register(&s3c2412_sysdev);
+}
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
new file mode 100644
index 0000000..e3bfda0
--- /dev/null
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -0,0 +1,71 @@
+# arch/arm/mach-s3c2440/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2440
+	bool
+	depends on ARCH_S3C2410
+	select S3C2410_CLOCK
+	select S3C2410_PM if PM
+	select S3C2410_GPIO
+	select S3C2440_DMA if S3C2410_DMA
+	select CPU_S3C244X
+	help
+	  Support for S3C2440 Samsung Mobile CPU based systems.
+
+config S3C2440_DMA
+	bool
+	depends on ARCH_S3C2410 && CPU_S3C24405B
+	help
+	  Support for S3C2440 specific DMA code5A
+
+
+menu "S3C2440 Machines"
+
+config MACH_ANUBIS
+	bool "Simtec Electronics ANUBIS"
+	select CPU_S3C2440
+	select PM_SIMTEC if PM
+	help
+	  Say Y here if you are using the Simtec Electronics ANUBIS
+	  development system
+
+config MACH_OSIRIS
+	bool "Simtec IM2440D20 (OSIRIS) module"
+	select CPU_S3C2440
+	select PM_SIMTEC if PM
+	help
+	  Say Y here if you are using the Simtec IM2440D20 module, also
+	  known as the Osiris.
+
+config MACH_RX3715
+	bool "HP iPAQ rx3715"
+	select CPU_S3C2440
+	select PM_H1940 if PM
+	help
+	  Say Y here if you are using the HP iPAQ rx3715.
+
+config ARCH_S3C2440
+	bool "SMDK2440"
+	select CPU_S3C2440
+	select MACH_SMDK
+	help
+	  Say Y here if you are using the SMDK2440.
+
+config MACH_NEXCODER_2440
+ 	bool "NexVision NEXCODER 2440 Light Board"
+ 	select CPU_S3C2440
+	help
+ 	  Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
+
+config SMDK2440_CPU2440
+	bool "SMDK2440 with S3C2440 CPU module"
+	depends on ARCH_S3C2440
+	default y if ARCH_S3C2440
+	select CPU_S3C2440
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
new file mode 100644
index 0000000..c81ed62
--- /dev/null
+++ b/arch/arm/mach-s3c2440/Makefile
@@ -0,0 +1,23 @@
+# arch/arm/mach-s3c2440/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+obj-$(CONFIG_CPU_S3C2440)	+= s3c2440.o dsc.o
+obj-$(CONFIG_CPU_S3C2440)	+= irq.o
+obj-$(CONFIG_CPU_S3C2440)	+= clock.o
+obj-$(CONFIG_S3C2440_DMA)	+= dma.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_ANUBIS)	+= mach-anubis.o
+obj-$(CONFIG_MACH_OSIRIS)	+= mach-osiris.o
+obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
+obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
+obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
diff --git a/arch/arm/mach-s3c2440/clock.c b/arch/arm/mach-s3c2440/clock.c
new file mode 100644
index 0000000..79e2ea4
--- /dev/null
+++ b/arch/arm/mach-s3c2440/clock.c
@@ -0,0 +1,170 @@
+/* linux/arch/arm/mach-s3c2440/clock.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2440 Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+
+#include <asm/hardware.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* S3C2440 extended clock support */
+
+static unsigned long s3c2440_camif_upll_round(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	/* note, we remove the +/- 1 calculations for the divisor */
+
+	div = (parent_rate / rate) / 2;
+
+	if (div < 1)
+		div = 1;
+	else if (div > 16)
+		div = 16;
+
+	return parent_rate / (div * 2);
+}
+
+static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
+
+	rate = s3c2440_camif_upll_round(clk, rate);
+
+	camdivn &= ~(S3C2440_CAMDIVN_CAMCLK_SEL | S3C2440_CAMDIVN_CAMCLK_MASK);
+
+	if (rate != parent_rate) {
+		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+		camdivn |= (((parent_rate / rate) / 2) - 1);
+	}
+
+	__raw_writel(camdivn, S3C2440_CAMDIVN);
+
+	return 0;
+}
+
+/* Extra S3C2440 clocks */
+
+static struct clk s3c2440_clk_cam = {
+	.name		= "camif",
+	.id		= -1,
+	.enable		= s3c2410_clkcon_enable,
+	.ctrlbit	= S3C2440_CLKCON_CAMERA,
+};
+
+static struct clk s3c2440_clk_cam_upll = {
+	.name		= "camif-upll",
+	.id		= -1,
+	.set_rate	= s3c2440_camif_upll_setrate,
+	.round_rate	= s3c2440_camif_upll_round,
+};
+
+static struct clk s3c2440_clk_ac97 = {
+	.name		= "ac97",
+	.id		= -1,
+	.enable		= s3c2410_clkcon_enable,
+	.ctrlbit	= S3C2440_CLKCON_CAMERA,
+};
+
+static int s3c2440_clk_add(struct sys_device *sysdev)
+{
+	unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
+	unsigned long clkdivn;
+	struct clk *clock_h;
+	struct clk *clock_p;
+	struct clk *clock_upll;
+
+	printk("S3C2440: Clock Support, DVS %s\n",
+	       (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
+
+	clock_p = clk_get(NULL, "pclk");
+	clock_h = clk_get(NULL, "hclk");
+	clock_upll = clk_get(NULL, "upll");
+
+	if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
+		printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
+		return -EINVAL;
+	}
+
+	/* check rate of UPLL, and if it is near 96MHz, then change
+	 * to using half the UPLL rate for the system */
+
+	if (clk_get_rate(clock_upll) > (94 * MHZ)) {
+		clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
+
+		mutex_lock(&clocks_mutex);
+
+		clkdivn = __raw_readl(S3C2410_CLKDIVN);
+		clkdivn |= S3C2440_CLKDIVN_UCLK;
+		__raw_writel(clkdivn, S3C2410_CLKDIVN);
+
+		mutex_unlock(&clocks_mutex);
+	}
+
+	s3c2440_clk_cam.parent = clock_h;
+	s3c2440_clk_ac97.parent = clock_p;
+	s3c2440_clk_cam_upll.parent = clock_upll;
+
+	s3c24xx_register_clock(&s3c2440_clk_ac97);
+	s3c24xx_register_clock(&s3c2440_clk_cam);
+	s3c24xx_register_clock(&s3c2440_clk_cam_upll);
+
+	clk_disable(&s3c2440_clk_ac97);
+	clk_disable(&s3c2440_clk_cam);
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2440_clk_driver = {
+	.add	= s3c2440_clk_add,
+};
+
+static __init int s3c24xx_clk_driver(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
+}
+
+arch_initcall(s3c24xx_clk_driver);
diff --git a/arch/arm/mach-s3c2440/dma.c b/arch/arm/mach-s3c2440/dma.c
new file mode 100644
index 0000000..cd035a3
--- /dev/null
+++ b/arch/arm/mach-s3c2440/dma.c
@@ -0,0 +1,210 @@
+/* linux/arch/arm/mach-s3c2440/dma.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2440 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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/sysdev.h>
+#include <linux/serial_core.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+
+#include <asm/plat-s3c24xx/dma.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
+	[DMACH_XD0] = {
+		.name		= "xdreq0",
+		.channels[0]	= S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
+	},
+	[DMACH_XD1] = {
+		.name		= "xdreq1",
+		.channels[1]	= S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
+	},
+	[DMACH_SDI] = {
+		.name		= "sdi",
+		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
+		.channels[1]	= S3C2440_DCON_CH1_SDI | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
+		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_SPI0] = {
+		.name		= "spi0",
+		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
+	},
+	[DMACH_SPI1] = {
+		.name		= "spi1",
+		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+	},
+	[DMACH_UART0] = {
+		.name		= "uart0",
+		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1] = {
+		.name		= "uart1",
+		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2] = {
+		.name		= "uart2",
+		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+	[DMACH_TIMER] = {
+		.name		= "timer",
+		.channels[0]	= S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
+		.channels[3]	= S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
+	},
+	[DMACH_I2S_IN] = {
+		.name		= "i2s-sdi",
+		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_I2S_OUT] = {
+		.name		= "i2s-sdo",
+		.channels[0]	= S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_PCM_IN] = {
+		.name		= "pcm-in",
+		.channels[0]	= S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID,
+		.channels[2]	= S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID,
+		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+	},
+	[DMACH_PCM_OUT] = {
+		.name		= "pcm-out",
+		.channels[1]	= S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID,
+		.channels[3]	= S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID,
+		.hw_addr.to	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+	},
+	[DMACH_MIC_IN] = {
+		.name		= "mic-in",
+		.channels[2]	= S3C2440_DCON_CH2_MICIN | DMA_CH_VALID,
+		.channels[3]	= S3C2440_DCON_CH3_MICIN | DMA_CH_VALID,
+		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
+	},
+	[DMACH_USB_EP1] = {
+		.name		= "usb-ep1",
+		.channels[0]	= S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP2] = {
+		.name		= "usb-ep2",
+		.channels[1]	= S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP3] = {
+		.name		= "usb-ep3",
+		.channels[2]	= S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP4] = {
+		.name		= "usb-ep4",
+		.channels[3]	= S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
+	},
+};
+
+static void s3c2440_dma_select(struct s3c2410_dma_chan *chan,
+			       struct s3c24xx_dma_map *map)
+{
+	chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2440_dma_sel = {
+	.select		= s3c2440_dma_select,
+	.dcon_mask	= 7 << 24,
+	.map		= s3c2440_dma_mappings,
+	.map_size	= ARRAY_SIZE(s3c2440_dma_mappings),
+};
+
+static struct s3c24xx_dma_order __initdata s3c2440_dma_order = {
+	.channels	= {
+		[DMACH_SDI]	= {
+			.list	= {
+				[0]	= 3 | DMA_CH_VALID,
+				[1]	= 2 | DMA_CH_VALID,
+				[2]	= 1 | DMA_CH_VALID,
+				[3]	= 0 | DMA_CH_VALID,
+			},
+		},
+		[DMACH_I2S_IN]	= {
+			.list	= {
+				[0]	= 1 | DMA_CH_VALID,
+				[1]	= 2 | DMA_CH_VALID,
+			},
+		},
+		[DMACH_I2S_OUT]	= {
+			.list	= {
+				[0]	= 2 | DMA_CH_VALID,
+				[1]	= 1 | DMA_CH_VALID,
+			},
+		},
+		[DMACH_PCM_IN] = {
+			.list	= {
+				[0]	= 2 | DMA_CH_VALID,
+				[1]	= 1 | DMA_CH_VALID,
+			},
+		},
+		[DMACH_PCM_OUT] = {
+			.list	= {
+				[0]	= 1 | DMA_CH_VALID,
+				[1]	= 3 | DMA_CH_VALID,
+			},
+		},
+		[DMACH_MIC_IN] = {
+			.list	= {
+				[0]	= 3 | DMA_CH_VALID,
+				[1]	= 2 | DMA_CH_VALID,
+			},
+		},
+	},
+};
+
+static int s3c2440_dma_add(struct sys_device *sysdev)
+{
+	s3c2410_dma_init();
+	s3c24xx_dma_order_set(&s3c2440_dma_order);
+	return s3c24xx_dma_init_map(&s3c2440_dma_sel);
+}
+
+static struct sysdev_driver s3c2440_dma_driver = {
+	.add	= s3c2440_dma_add,
+};
+
+static int __init s3c2440_dma_init(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_dma_driver);
+}
+
+arch_initcall(s3c2440_dma_init);
+
diff --git a/arch/arm/mach-s3c2440/dsc.c b/arch/arm/mach-s3c2440/dsc.c
new file mode 100644
index 0000000..2995ff5
--- /dev/null
+++ b/arch/arm/mach-s3c2440/dsc.c
@@ -0,0 +1,54 @@
+/* linux/arch/arm/mach-s3c2440/dsc.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 Drive Strength Control support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/module.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/regs-dsc.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+
+int s3c2440_set_dsc(unsigned int pin, unsigned int value)
+{
+	void __iomem *base;
+	unsigned long val;
+	unsigned long flags;
+	unsigned long mask;
+
+	base = (pin & S3C2440_SELECT_DSC1) ? S3C2440_DSC1 : S3C2440_DSC0;
+	mask = 3 << S3C2440_DSC_GETSHIFT(pin);
+
+	local_irq_save(flags);
+
+	val = __raw_readl(base);
+	val &= ~mask;
+	val |= value & mask;
+	__raw_writel(val, base);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2440_set_dsc);
diff --git a/arch/arm/mach-s3c2440/irq.c b/arch/arm/mach-s3c2440/irq.c
new file mode 100644
index 0000000..1069d13
--- /dev/null
+++ b/arch/arm/mach-s3c2440/irq.c
@@ -0,0 +1,130 @@
+/* linux/arch/arm/mach-s3c2440/irq.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
+
+/* WDT/AC97 */
+
+static void s3c_irq_demux_wdtac97(unsigned int irq,
+				  struct irq_desc *desc)
+{
+	unsigned int subsrc, submsk;
+	struct irq_desc *mydesc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	subsrc &= ~submsk;
+	subsrc >>= 13;
+	subsrc &= 3;
+
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_S3C2440_WDT;
+			desc_handle_irq(IRQ_S3C2440_WDT, mydesc);
+		}
+		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_S3C2440_AC97;
+			desc_handle_irq(IRQ_S3C2440_AC97, mydesc);
+		}
+	}
+}
+
+
+#define INTMSK_WDT	 (1UL << (IRQ_WDT - IRQ_EINT0))
+
+static void
+s3c_irq_wdtac97_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
+}
+
+static void
+s3c_irq_wdtac97_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_WDT);
+}
+
+static void
+s3c_irq_wdtac97_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
+}
+
+static struct irq_chip s3c_irq_wdtac97 = {
+	.mask	    = s3c_irq_wdtac97_mask,
+	.unmask	    = s3c_irq_wdtac97_unmask,
+	.ack	    = s3c_irq_wdtac97_ack,
+};
+
+static int s3c2440_irq_add(struct sys_device *sysdev)
+{
+	unsigned int irqno;
+
+	printk("S3C2440: IRQ Support\n");
+
+	/* add new chained handler for wdt, ac7 */
+
+	set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
+	set_irq_handler(IRQ_WDT, handle_level_irq);
+	set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
+
+	for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
+		set_irq_chip(irqno, &s3c_irq_wdtac97);
+		set_irq_handler(irqno, handle_level_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2440_irq_driver = {
+	.add		= s3c2440_irq_add,
+};
+
+static int s3c2440_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
+}
+
+arch_initcall(s3c2440_irq_init);
+
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
new file mode 100644
index 0000000..3f0288e
--- /dev/null
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -0,0 +1,325 @@
+/* linux/arch/arm/mach-s3c2440/mach-anubis.c
+ *
+ * Copyright (c) 2003-2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/anubis-map.h>
+#include <asm/arch/anubis-irq.h>
+#include <asm/arch/anubis-cpld.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/nand.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#define COPYRIGHT ", (c) 2005 Simtec Electronics"
+
+static struct map_desc anubis_iodesc[] __initdata = {
+  /* ISA IO areas */
+
+  {
+	.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
+	.pfn		= __phys_to_pfn(0x0),
+	.length		= SZ_4M,
+	.type		= MT_DEVICE,
+  }, {
+	.virtual	= (u32)S3C24XX_VA_ISA_WORD,
+	.pfn		= __phys_to_pfn(0x0),
+	.length 	= SZ_4M,
+	.type		= MT_DEVICE,
+  },
+
+  /* we could possibly compress the next set down into a set of smaller tables
+   * pagetables, but that would mean using an L2 section, and it still means
+   * we cannot actually feed the same register to an LDR due to 16K spacing
+   */
+
+  /* CPLD control registers */
+
+  {
+	.virtual	= (u32)ANUBIS_VA_CTRL1,
+	.pfn		= __phys_to_pfn(ANUBIS_PA_CTRL1),
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+  }, {
+	.virtual	= (u32)ANUBIS_VA_CTRL2,
+	.pfn		= __phys_to_pfn(ANUBIS_PA_CTRL2),
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+  },
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
+	[0] = {
+		.name		= "uclk",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+	[1] = {
+		.name		= "pclk",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	}
+};
+
+
+static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+		.clocks	     = anubis_serial_clocks,
+		.clocks_size = ARRAY_SIZE(anubis_serial_clocks),
+	},
+	[1] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+		.clocks	     = anubis_serial_clocks,
+		.clocks_size = ARRAY_SIZE(anubis_serial_clocks),
+	},
+};
+
+/* NAND Flash on Anubis board */
+
+static int external_map[]   = { 2 };
+static int chip0_map[]      = { 0 };
+static int chip1_map[]      = { 1 };
+
+static struct mtd_partition anubis_default_nand_part[] = {
+	[0] = {
+		.name	= "Boot Agent",
+		.size	= SZ_16K,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "/boot",
+		.size	= SZ_4M - SZ_16K,
+		.offset	= SZ_16K,
+	},
+	[2] = {
+		.name	= "user1",
+		.offset	= SZ_4M,
+		.size	= SZ_32M - SZ_4M,
+	},
+	[3] = {
+		.name	= "user2",
+		.offset	= SZ_32M,
+		.size	= MTDPART_SIZ_FULL,
+	}
+};
+
+/* the Anubis has 3 selectable slots for nand-flash, the two
+ * on-board chip areas, as well as the external slot.
+ *
+ * Note, there is no current hot-plug support for the External
+ * socket.
+*/
+
+static struct s3c2410_nand_set anubis_nand_sets[] = {
+	[1] = {
+		.name		= "External",
+		.nr_chips	= 1,
+		.nr_map		= external_map,
+		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
+		.partitions	= anubis_default_nand_part,
+	},
+	[0] = {
+		.name		= "chip0",
+		.nr_chips	= 1,
+		.nr_map		= chip0_map,
+		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
+		.partitions	= anubis_default_nand_part,
+	},
+	[2] = {
+		.name		= "chip1",
+		.nr_chips	= 1,
+		.nr_map		= chip1_map,
+		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
+		.partitions	= anubis_default_nand_part,
+	},
+};
+
+static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
+{
+	unsigned int tmp;
+
+	slot = set->nr_map[slot] & 3;
+
+	pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n",
+		 slot, set, set->nr_map);
+
+	tmp = __raw_readb(ANUBIS_VA_CTRL1);
+	tmp &= ~ANUBIS_CTRL1_NANDSEL;
+	tmp |= slot;
+
+	pr_debug("anubis_nand: ctrl1 now %02x\n", tmp);
+
+	__raw_writeb(tmp, ANUBIS_VA_CTRL1);
+}
+
+static struct s3c2410_platform_nand anubis_nand_info = {
+	.tacls		= 25,
+	.twrph0		= 55,
+	.twrph1		= 40,
+	.nr_sets	= ARRAY_SIZE(anubis_nand_sets),
+	.sets		= anubis_nand_sets,
+	.select_chip	= anubis_nand_select,
+};
+
+/* IDE channels */
+
+static struct resource anubis_ide0_resource[] = {
+	{
+		.start	= S3C2410_CS3,
+		.end	= S3C2410_CS3 + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= S3C2410_CS3 + (1<<26),
+		.end	= S3C2410_CS3 + (1<<26) + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_IDE0,
+		.end	= IRQ_IDE0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device anubis_device_ide0 = {
+	.name		= "simtec-ide",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(anubis_ide0_resource),
+	.resource	= anubis_ide0_resource,
+};
+
+static struct resource anubis_ide1_resource[] = {
+	{
+		.start	= S3C2410_CS4,
+		.end	= S3C2410_CS4 + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= S3C2410_CS4 + (1<<26),
+		.end	= S3C2410_CS4 + (1<<26) + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_IDE0,
+		.end	= IRQ_IDE0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+
+static struct platform_device anubis_device_ide1 = {
+	.name		= "simtec-ide",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(anubis_ide1_resource),
+	.resource	= anubis_ide1_resource,
+};
+
+/* Standard Anubis devices */
+
+static struct platform_device *anubis_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_wdt,
+	&s3c_device_adc,
+	&s3c_device_i2c,
+ 	&s3c_device_rtc,
+	&s3c_device_nand,
+	&anubis_device_ide0,
+	&anubis_device_ide1,
+};
+
+static struct clk *anubis_clocks[] = {
+	&s3c24xx_dclk0,
+	&s3c24xx_dclk1,
+	&s3c24xx_clkout0,
+	&s3c24xx_clkout1,
+	&s3c24xx_uclk,
+};
+
+static struct s3c24xx_board anubis_board __initdata = {
+	.devices       = anubis_devices,
+	.devices_count = ARRAY_SIZE(anubis_devices),
+	.clocks	       = anubis_clocks,
+	.clocks_count  = ARRAY_SIZE(anubis_clocks),
+};
+
+static void __init anubis_map_io(void)
+{
+	/* initialise the clocks */
+
+	s3c24xx_dclk0.parent = NULL;
+	s3c24xx_dclk0.rate   = 12*1000*1000;
+
+	s3c24xx_dclk1.parent = NULL;
+	s3c24xx_dclk1.rate   = 24*1000*1000;
+
+	s3c24xx_clkout0.parent  = &s3c24xx_dclk0;
+	s3c24xx_clkout1.parent  = &s3c24xx_dclk1;
+
+	s3c24xx_uclk.parent  = &s3c24xx_clkout1;
+
+	s3c_device_nand.dev.platform_data = &anubis_nand_info;
+
+	s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
+	s3c24xx_init_clocks(0);
+	s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
+	s3c24xx_set_board(&anubis_board);
+
+	/* ensure that the GPIO is setup */
+	s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+}
+
+MACHINE_START(ANUBIS, "Simtec-Anubis")
+	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.map_io		= anubis_map_io,
+	.init_irq	= s3c24xx_init_irq,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2440/mach-nexcoder.c b/arch/arm/mach-s3c2440/mach-nexcoder.c
new file mode 100644
index 0000000..6d551d8
--- /dev/null
+++ b/arch/arm/mach-s3c2440/mach-nexcoder.c
@@ -0,0 +1,158 @@
+/* linux/arch/arm/mach-s3c2440/mach-nexcoder.c
+ *
+ * Copyright (c) 2004 Nex Vision
+ *   Guillaume GOURAT <guillaume.gourat@nexvision.tv>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Modifications:
+ *     15-10-2004 GG  Created initial version
+ *     12-03-2005 BJD Updated for release
+ */
+
+#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/string.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/map.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/setup.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+//#include <asm/debug-ll.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-serial.h>
+
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+static struct map_desc nexcoder_iodesc[] __initdata = {
+	/* nothing here yet */
+};
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg nexcoder_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	}
+};
+
+/* NOR Flash on NexVision NexCoder 2440 board */
+
+static struct resource nexcoder_nor_resource[] = {
+	[0] = {
+		.start = S3C2410_CS0,
+		.end   = S3C2410_CS0 + (8*1024*1024) - 1,
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+static struct map_info nexcoder_nor_map = {
+	.bankwidth = 2,
+};
+
+static struct platform_device nexcoder_device_nor = {
+	.name		= "mtd-flash",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(nexcoder_nor_resource),
+	.resource	= nexcoder_nor_resource,
+	.dev =
+	{
+		.platform_data = &nexcoder_nor_map,
+	}
+};
+
+/* Standard Nexcoder devices */
+
+static struct platform_device *nexcoder_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+ 	&s3c_device_rtc,
+	&s3c_device_camif,
+	&s3c_device_spi0,
+	&s3c_device_spi1,
+	&nexcoder_device_nor,
+};
+
+static struct s3c24xx_board nexcoder_board __initdata = {
+	.devices       = nexcoder_devices,
+	.devices_count = ARRAY_SIZE(nexcoder_devices),
+};
+
+
+static void __init nexcoder_sensorboard_init(void)
+{
+	// Initialize SCCB bus
+	s3c2410_gpio_setpin(S3C2410_GPE14, 1); // IICSCL
+	s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_OUTP);
+	s3c2410_gpio_setpin(S3C2410_GPE15, 1); // IICSDA
+	s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_OUTP);
+
+	// Power up the sensor board
+	s3c2410_gpio_setpin(S3C2410_GPF1, 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPF1, S3C2410_GPF1_OUTP); // CAM_GPIO7 => nLDO_PWRDN
+	s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+	s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP); // CAM_GPIO6 => CAM_PWRDN
+}
+
+static void __init nexcoder_map_io(void)
+{
+	s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc));
+	s3c24xx_init_clocks(0);
+	s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs));
+	s3c24xx_set_board(&nexcoder_board);
+	nexcoder_sensorboard_init();
+}
+
+
+MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
+	/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.map_io		= nexcoder_map_io,
+	.init_irq	= s3c24xx_init_irq,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
new file mode 100644
index 0000000..2ed8e51
--- /dev/null
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -0,0 +1,303 @@
+/* linux/arch/arm/mach-s3c2440/mach-osiris.c
+ *
+ * Copyright (c) 2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/device.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/osiris-map.h>
+#include <asm/arch/osiris-cpld.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/nand.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* onboard perihpheral map */
+
+static struct map_desc osiris_iodesc[] __initdata = {
+  /* ISA IO areas (may be over-written later) */
+
+  {
+	  .virtual	= (u32)S3C24XX_VA_ISA_BYTE,
+	  .pfn		= __phys_to_pfn(S3C2410_CS5),
+	  .length	= SZ_16M,
+	  .type		= MT_DEVICE,
+  }, {
+	  .virtual	= (u32)S3C24XX_VA_ISA_WORD,
+	  .pfn		= __phys_to_pfn(S3C2410_CS5),
+	  .length	= SZ_16M,
+	  .type		= MT_DEVICE,
+  },
+
+  /* CPLD control registers */
+
+  {
+	  .virtual	= (u32)OSIRIS_VA_CTRL1,
+	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL1),
+	  .length	= SZ_16K,
+	  .type		= MT_DEVICE,
+  }, {
+	  .virtual	= (u32)OSIRIS_VA_CTRL2,
+	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL2),
+	  .length	= SZ_16K,
+	  .type		= MT_DEVICE,
+  },
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c24xx_uart_clksrc osiris_serial_clocks[] = {
+	[0] = {
+		.name		= "uclk",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+	[1] = {
+		.name		= "pclk",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	}
+};
+
+static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+		.clocks	     = osiris_serial_clocks,
+		.clocks_size = ARRAY_SIZE(osiris_serial_clocks),
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+		.clocks	     = osiris_serial_clocks,
+		.clocks_size = ARRAY_SIZE(osiris_serial_clocks),
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+		.clocks	     = osiris_serial_clocks,
+		.clocks_size = ARRAY_SIZE(osiris_serial_clocks),
+	}
+};
+
+/* NAND Flash on Osiris board */
+
+static int external_map[]   = { 2 };
+static int chip0_map[]      = { 0 };
+static int chip1_map[]      = { 1 };
+
+static struct mtd_partition osiris_default_nand_part[] = {
+	[0] = {
+		.name	= "Boot Agent",
+		.size	= SZ_16K,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "/boot",
+		.size	= SZ_4M - SZ_16K,
+		.offset	= SZ_16K,
+	},
+	[2] = {
+		.name	= "user1",
+		.offset	= SZ_4M,
+		.size	= SZ_32M - SZ_4M,
+	},
+	[3] = {
+		.name	= "user2",
+		.offset	= SZ_32M,
+		.size	= MTDPART_SIZ_FULL,
+	}
+};
+
+/* the Osiris has 3 selectable slots for nand-flash, the two
+ * on-board chip areas, as well as the external slot.
+ *
+ * Note, there is no current hot-plug support for the External
+ * socket.
+*/
+
+static struct s3c2410_nand_set osiris_nand_sets[] = {
+	[1] = {
+		.name		= "External",
+		.nr_chips	= 1,
+		.nr_map		= external_map,
+		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
+		.partitions	= osiris_default_nand_part,
+	},
+	[0] = {
+		.name		= "chip0",
+		.nr_chips	= 1,
+		.nr_map		= chip0_map,
+		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
+		.partitions	= osiris_default_nand_part,
+	},
+	[2] = {
+		.name		= "chip1",
+		.nr_chips	= 1,
+		.nr_map		= chip1_map,
+		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
+		.partitions	= osiris_default_nand_part,
+	},
+};
+
+static void osiris_nand_select(struct s3c2410_nand_set *set, int slot)
+{
+	unsigned int tmp;
+
+	slot = set->nr_map[slot] & 3;
+
+	pr_debug("osiris_nand: selecting slot %d (set %p,%p)\n",
+		 slot, set, set->nr_map);
+
+	tmp = __raw_readb(OSIRIS_VA_CTRL1);
+	tmp &= ~OSIRIS_CTRL1_NANDSEL;
+	tmp |= slot;
+
+	pr_debug("osiris_nand: ctrl1 now %02x\n", tmp);
+
+	__raw_writeb(tmp, OSIRIS_VA_CTRL1);
+}
+
+static struct s3c2410_platform_nand osiris_nand_info = {
+	.tacls		= 25,
+	.twrph0		= 60,
+	.twrph1		= 60,
+	.nr_sets	= ARRAY_SIZE(osiris_nand_sets),
+	.sets		= osiris_nand_sets,
+	.select_chip	= osiris_nand_select,
+};
+
+/* PCMCIA control and configuration */
+
+static struct resource osiris_pcmcia_resource[] = {
+	[0] = {
+		.start	= 0x0f000000,
+		.end	= 0x0f100000,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 0x0c000000,
+		.end	= 0x0c100000,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device osiris_pcmcia = {
+	.name		= "osiris-pcmcia",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(osiris_pcmcia_resource),
+	.resource	= osiris_pcmcia_resource,
+};
+
+/* Standard Osiris devices */
+
+static struct platform_device *osiris_devices[] __initdata = {
+	&s3c_device_i2c,
+	&s3c_device_nand,
+	&osiris_pcmcia,
+};
+
+static struct clk *osiris_clocks[] = {
+	&s3c24xx_dclk0,
+	&s3c24xx_dclk1,
+	&s3c24xx_clkout0,
+	&s3c24xx_clkout1,
+	&s3c24xx_uclk,
+};
+
+static struct s3c24xx_board osiris_board __initdata = {
+	.devices       = osiris_devices,
+	.devices_count = ARRAY_SIZE(osiris_devices),
+	.clocks	       = osiris_clocks,
+	.clocks_count  = ARRAY_SIZE(osiris_clocks),
+};
+
+static void __init osiris_map_io(void)
+{
+	unsigned long flags;
+
+	/* initialise the clocks */
+
+	s3c24xx_dclk0.parent = NULL;
+	s3c24xx_dclk0.rate   = 12*1000*1000;
+
+	s3c24xx_dclk1.parent = NULL;
+	s3c24xx_dclk1.rate   = 24*1000*1000;
+
+	s3c24xx_clkout0.parent  = &s3c24xx_dclk0;
+	s3c24xx_clkout1.parent  = &s3c24xx_dclk1;
+
+	s3c24xx_uclk.parent  = &s3c24xx_clkout1;
+
+	s3c_device_nand.dev.platform_data = &osiris_nand_info;
+
+	s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
+	s3c24xx_init_clocks(0);
+	s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
+	s3c24xx_set_board(&osiris_board);
+
+	/* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
+
+	local_irq_save(flags);
+	__raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON);
+	local_irq_restore(flags);
+
+	/* write-protect line to the NAND */
+	s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+}
+
+MACHINE_START(OSIRIS, "Simtec-OSIRIS")
+	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.map_io		= osiris_map_io,
+	.init_irq	= s3c24xx_init_irq,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
new file mode 100644
index 0000000..480ccde
--- /dev/null
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -0,0 +1,243 @@
+/* linux/arch/arm/mach-s3c2440/mach-rx3715.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.handhelds.org/projects/rx3715.html
+ *
+ * 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/tty.h>
+#include <linux/console.h>
+#include <linux/platform_device.h>
+#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>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/h1940.h>
+#include <asm/arch/nand.h>
+#include <asm/arch/fb.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+
+static struct map_desc rx3715_iodesc[] __initdata = {
+	/* dump ISA space somewhere unused */
+
+	{
+		.virtual	= (u32)S3C24XX_VA_ISA_WORD,
+		.pfn		= __phys_to_pfn(S3C2410_CS3),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
+		.pfn		= __phys_to_pfn(S3C2410_CS3),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE,
+	},
+};
+
+
+static struct s3c24xx_uart_clksrc rx3715_serial_clocks[] = {
+	[0] = {
+		.name		= "fclk",
+		.divisor	= 0,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	}
+};
+
+static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+		.clocks	     = rx3715_serial_clocks,
+		.clocks_size = ARRAY_SIZE(rx3715_serial_clocks),
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x00,
+		.clocks	     = rx3715_serial_clocks,
+		.clocks_size = ARRAY_SIZE(rx3715_serial_clocks),
+	},
+	/* IR port */
+	[2] = {
+		.hwport	     = 2,
+		.uart_flags  = UPF_CONS_FLOW,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x43,
+		.ufcon	     = 0x51,
+		.clocks	     = rx3715_serial_clocks,
+		.clocks_size = ARRAY_SIZE(rx3715_serial_clocks),
+	}
+};
+
+/* framebuffer lcd controller information */
+
+static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = {
+	.regs	= {
+		.lcdcon1 =	S3C2410_LCDCON1_TFT16BPP | \
+				S3C2410_LCDCON1_TFT | \
+				S3C2410_LCDCON1_CLKVAL(0x0C),
+
+		.lcdcon2 =	S3C2410_LCDCON2_VBPD(5) | \
+				S3C2410_LCDCON2_LINEVAL(319) | \
+				S3C2410_LCDCON2_VFPD(6) | \
+				S3C2410_LCDCON2_VSPW(2),
+
+		.lcdcon3 =	S3C2410_LCDCON3_HBPD(35) | \
+				S3C2410_LCDCON3_HOZVAL(239) | \
+				S3C2410_LCDCON3_HFPD(35),
+
+		.lcdcon4 =	S3C2410_LCDCON4_MVAL(0) | \
+				S3C2410_LCDCON4_HSPW(7),
+
+		.lcdcon5 =	S3C2410_LCDCON5_INVVLINE |
+				S3C2410_LCDCON5_FRM565 |
+				S3C2410_LCDCON5_HWSWP,
+	},
+
+	.lpcsel =	0xf82,
+
+	.gpccon =	0xaa955699,
+	.gpccon_mask =	0xffc003cc,
+	.gpcup =	0x0000ffff,
+	.gpcup_mask =	0xffffffff,
+
+	.gpdcon =	0xaa95aaa1,
+	.gpdcon_mask =	0xffc0fff0,
+	.gpdup =	0x0000faff,
+	.gpdup_mask =	0xffffffff,
+
+	.fixed_syncs =	1,
+	.width  =	240,
+	.height =	320,
+
+	.xres	= {
+		.min =		240,
+		.max =		240,
+		.defval =	240,
+	},
+
+	.yres	= {
+		.max =		320,
+		.min =		320,
+		.defval	=	320,
+	},
+
+	.bpp	= {
+		.min =		16,
+		.max =		16,
+		.defval =	16,
+	},
+};
+
+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 = {
+	.devices       = rx3715_devices,
+	.devices_count = ARRAY_SIZE(rx3715_devices)
+};
+
+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));
+	s3c24xx_set_board(&rx3715_board);
+}
+
+static void __init rx3715_init_irq(void)
+{
+	s3c24xx_init_irq();
+}
+
+static void __init rx3715_init_machine(void)
+{
+	memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
+	s3c2410_pm_init();
+
+	s3c24xx_fb_set_platdata(&rx3715_lcdcfg);
+}
+
+
+MACHINE_START(RX3715, "IPAQ-RX3715")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.map_io		= rx3715_map_io,
+	.init_irq	= rx3715_init_irq,
+	.init_machine	= rx3715_init_machine,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c
new file mode 100644
index 0000000..c17eb5b
--- /dev/null
+++ b/arch/arm/mach-s3c2440/mach-smdk2440.c
@@ -0,0 +1,207 @@
+/* linux/arch/arm/mach-s3c2440/mach-smdk2440.c
+ *
+ * Copyright (c) 2004,2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * Thanks to Dimity Andric and TomTom for the loan of an 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/serial_core.h>
+#include <linux/platform_device.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/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/plat-s3c24xx/common-smdk.h>
+
+static struct map_desc smdk2440_iodesc[] __initdata = {
+	/* ISA IO Space map (memory space selected by A24) */
+
+	{
+		.virtual	= (u32)S3C24XX_VA_ISA_WORD,
+		.pfn		= __phys_to_pfn(S3C2410_CS2),
+		.length		= 0x10000,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (u32)S3C24XX_VA_ISA_WORD + 0x10000,
+		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+		.length		= SZ_4M,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
+		.pfn		= __phys_to_pfn(S3C2410_CS2),
+		.length		= 0x10000,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
+		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+		.length		= SZ_4M,
+		.type		= MT_DEVICE,
+	}
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	/* IR port */
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x43,
+		.ufcon	     = 0x51,
+	}
+};
+
+/* LCD driver info */
+
+static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {
+	.regs	= {
+
+		.lcdcon1	= S3C2410_LCDCON1_TFT16BPP |
+				  S3C2410_LCDCON1_TFT |
+				  S3C2410_LCDCON1_CLKVAL(0x04),
+
+		.lcdcon2	= S3C2410_LCDCON2_VBPD(7) |
+				  S3C2410_LCDCON2_LINEVAL(319) |
+				  S3C2410_LCDCON2_VFPD(6) |
+				  S3C2410_LCDCON2_VSPW(3),
+
+		.lcdcon3	= S3C2410_LCDCON3_HBPD(19) |
+				  S3C2410_LCDCON3_HOZVAL(239) |
+				  S3C2410_LCDCON3_HFPD(7),
+
+		.lcdcon4	= S3C2410_LCDCON4_MVAL(0) |
+				  S3C2410_LCDCON4_HSPW(3),
+
+		.lcdcon5	= S3C2410_LCDCON5_FRM565 |
+				  S3C2410_LCDCON5_INVVLINE |
+				  S3C2410_LCDCON5_INVVFRAME |
+				  S3C2410_LCDCON5_PWREN |
+				  S3C2410_LCDCON5_HWSWP,
+	},
+
+#if 0
+	/* currently setup by downloader */
+	.gpccon		= 0xaa940659,
+	.gpccon_mask	= 0xffffffff,
+	.gpcup		= 0x0000ffff,
+	.gpcup_mask	= 0xffffffff,
+	.gpdcon		= 0xaa84aaa0,
+	.gpdcon_mask	= 0xffffffff,
+	.gpdup		= 0x0000faff,
+	.gpdup_mask	= 0xffffffff,
+#endif
+
+	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
+	.type		= S3C2410_LCDCON1_TFT16BPP,
+
+	.width		= 240,
+	.height		= 320,
+
+	.xres		= {
+		.min	= 240,
+		.max	= 240,
+		.defval	= 240,
+	},
+
+	.yres		= {
+		.min	= 320,
+		.max	= 320,
+		.defval = 320,
+	},
+
+	.bpp		= {
+		.min	= 16,
+		.max	= 16,
+		.defval = 16,
+	},
+};
+
+static struct platform_device *smdk2440_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c24xx_board smdk2440_board __initdata = {
+	.devices       = smdk2440_devices,
+	.devices_count = ARRAY_SIZE(smdk2440_devices)
+};
+
+static void __init smdk2440_map_io(void)
+{
+	s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
+	s3c24xx_init_clocks(16934400);
+	s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
+	s3c24xx_set_board(&smdk2440_board);
+}
+
+static void __init smdk2440_machine_init(void)
+{
+	s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
+
+	smdk_machine_init();
+}
+
+MACHINE_START(S3C2440, "SMDK2440")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= smdk2440_map_io,
+	.init_machine	= smdk2440_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2440/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c
new file mode 100644
index 0000000..90e1da6
--- /dev/null
+++ b/arch/arm/mach-s3c2440/s3c2440.c
@@ -0,0 +1,52 @@
+/* linux/arch/arm/mach-s3c2440/s3c2440.c
+ *
+ * Copyright (c) 2004-2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#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/serial_core.h>
+#include <linux/sysdev.h>
+#include <linux/clk.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/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+static struct sys_device s3c2440_sysdev = {
+	.cls		= &s3c2440_sysclass,
+};
+
+int __init s3c2440_init(void)
+{
+	printk("S3C2440: Initialising architecture\n");
+
+	/* change irq for watchdog */
+
+	s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
+	s3c_device_wdt.resource[1].end   = IRQ_S3C2440_WDT;
+
+	/* register our system device for everything else */
+
+	return sysdev_register(&s3c2440_sysdev);
+}
diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig
new file mode 100644
index 0000000..bf8d87a
--- /dev/null
+++ b/arch/arm/mach-s3c2442/Kconfig
@@ -0,0 +1,27 @@
+# arch/arm/mach-s3c2442/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2442
+	bool
+	depends on ARCH_S3C2420
+	select S3C2410_CLOCK
+	select S3C2410_GPIO
+	select S3C2410_PM if PM
+	select CPU_S3C244X
+	help
+	  Support for S3C2442 Samsung Mobile CPU based systems.
+
+
+menu "S3C2442 Machines"
+
+config SMDK2440_CPU2442
+	bool "SMDM2440 with S3C2442 CPU module"
+	depends on ARCH_S3C2440
+	select CPU_S3C2442
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2442/Makefile b/arch/arm/mach-s3c2442/Makefile
new file mode 100644
index 0000000..2a909c6
--- /dev/null
+++ b/arch/arm/mach-s3c2442/Makefile
@@ -0,0 +1,16 @@
+# arch/arm/mach-s3c2442/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+obj-$(CONFIG_CPU_S3C2442)	+= s3c2442.o
+obj-$(CONFIG_CPU_S3C2442)	+= clock.o
+
+# Machine support
+
diff --git a/arch/arm/mach-s3c2442/clock.c b/arch/arm/mach-s3c2442/clock.c
new file mode 100644
index 0000000..5b9e830
--- /dev/null
+++ b/arch/arm/mach-s3c2442/clock.c
@@ -0,0 +1,171 @@
+/* linux/arch/arm/mach-s3c2442/clock.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2442 Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+
+#include <asm/hardware.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* S3C2442 extended clock support */
+
+static unsigned long s3c2442_camif_upll_round(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	div = parent_rate / rate;
+
+	if (div == 3)
+		return parent_rate / 3;
+
+	/* note, we remove the +/- 1 calculations for the divisor */
+
+	div /= 2;
+
+	if (div < 1)
+		div = 1;
+	else if (div > 16)
+		div = 16;
+
+	return parent_rate / (div * 2);
+}
+
+static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
+
+	rate = s3c2442_camif_upll_round(clk, rate);
+
+	camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
+
+	if (rate == parent_rate) {
+		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
+	} else if ((parent_rate / rate) == 3) {
+		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+		camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
+	} else {
+		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
+		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+		camdivn |= (((parent_rate / rate) / 2) - 1);
+	}
+
+	__raw_writel(camdivn, S3C2440_CAMDIVN);
+
+	return 0;
+}
+
+/* Extra S3C2442 clocks */
+
+static struct clk s3c2442_clk_cam = {
+	.name		= "camif",
+	.id		= -1,
+	.enable		= s3c2410_clkcon_enable,
+	.ctrlbit	= S3C2440_CLKCON_CAMERA,
+};
+
+static struct clk s3c2442_clk_cam_upll = {
+	.name		= "camif-upll",
+	.id		= -1,
+	.set_rate	= s3c2442_camif_upll_setrate,
+	.round_rate	= s3c2442_camif_upll_round,
+};
+
+static int s3c2442_clk_add(struct sys_device *sysdev)
+{
+	unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
+	unsigned long clkdivn;
+	struct clk *clock_h;
+	struct clk *clock_p;
+	struct clk *clock_upll;
+
+	printk("S3C2442: Clock Support, DVS %s\n",
+	       (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
+
+	clock_p = clk_get(NULL, "pclk");
+	clock_h = clk_get(NULL, "hclk");
+	clock_upll = clk_get(NULL, "upll");
+
+	if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
+		printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
+		return -EINVAL;
+	}
+
+	/* check rate of UPLL, and if it is near 96MHz, then change
+	 * to using half the UPLL rate for the system */
+
+	if (clk_get_rate(clock_upll) > (94 * MHZ)) {
+		clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
+
+		mutex_lock(&clocks_mutex);
+
+		clkdivn = __raw_readl(S3C2410_CLKDIVN);
+		clkdivn |= S3C2440_CLKDIVN_UCLK;
+		__raw_writel(clkdivn, S3C2410_CLKDIVN);
+
+		mutex_unlock(&clocks_mutex);
+	}
+
+	s3c2442_clk_cam.parent = clock_h;
+	s3c2442_clk_cam_upll.parent = clock_upll;
+
+	s3c24xx_register_clock(&s3c2442_clk_cam);
+	s3c24xx_register_clock(&s3c2442_clk_cam_upll);
+
+	clk_disable(&s3c2442_clk_cam);
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2442_clk_driver = {
+	.add	= s3c2442_clk_add,
+};
+
+static __init int s3c2442_clk_init(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver);
+}
+
+arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/mach-s3c2442/s3c2442.c b/arch/arm/mach-s3c2442/s3c2442.c
new file mode 100644
index 0000000..fbf8264
--- /dev/null
+++ b/arch/arm/mach-s3c2442/s3c2442.c
@@ -0,0 +1,34 @@
+/* linux/arch/arm/mach-s3c2442/s3c2442.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2442 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#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/serial_core.h>
+#include <linux/sysdev.h>
+
+#include <asm/plat-s3c24xx/s3c2442.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+static struct sys_device s3c2442_sysdev = {
+	.cls		= &s3c2442_sysclass,
+};
+
+int __init s3c2442_init(void)
+{
+	printk("S3C2442: Initialising architecture\n");
+
+	return sysdev_register(&s3c2442_sysdev);
+}
diff --git a/arch/arm/mach-s3c2443/Kconfig b/arch/arm/mach-s3c2443/Kconfig
new file mode 100644
index 0000000..c649bb2
--- /dev/null
+++ b/arch/arm/mach-s3c2443/Kconfig
@@ -0,0 +1,29 @@
+# arch/arm/mach-s3c2443/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2443
+	bool
+	depends on ARCH_S3C2410
+	select S3C2443_DMA if S3C2410_DMA
+	help
+	  Support for the S3C2443 SoC from the S3C24XX line
+
+config S3C2443_DMA
+	bool
+	depends on CPU_S3C2443
+	help
+	  Internal config node for S3C2443 DMA support
+
+menu "S3C2443 Machines"
+
+config MACH_SMDK2443
+	bool "SMDK2443"
+	select CPU_S3C2443
+	select MACH_SMDK
+	help
+	  Say Y here if you are using an SMDK2443
+
+endmenu
diff --git a/arch/arm/mach-s3c2443/Makefile b/arch/arm/mach-s3c2443/Makefile
new file mode 100644
index 0000000..d1843c9
--- /dev/null
+++ b/arch/arm/mach-s3c2443/Makefile
@@ -0,0 +1,20 @@
+# arch/arm/mach-s3c2443/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+obj-$(CONFIG_CPU_S3C2443)	+= s3c2443.o
+obj-$(CONFIG_CPU_S3C2443)	+= irq.o
+obj-$(CONFIG_CPU_S3C2443)	+= clock.o
+
+obj-$(CONFIG_S3C2443_DMA)	+= dma.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_SMDK2443)	+= mach-smdk2443.o
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
new file mode 100644
index 0000000..dd2272f
--- /dev/null
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -0,0 +1,1007 @@
+/* linux/arch/arm/mach-s3c2443/clock.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2443 Clock control support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/map.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-s3c2443-clock.h>
+
+#include <asm/plat-s3c24xx/s3c2443.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* We currently have to assume that the system is running
+ * from the XTPll input, and that all ***REFCLKs are being
+ * fed from it, as we cannot read the state of OM[4] from
+ * software.
+ *
+ * It would be possible for each board initialisation to
+ * set the correct muxing at initialisation
+*/
+
+static int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
+{
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
+
+	clkcon = __raw_readl(S3C2443_HCLKCON);
+
+	if (enable)
+		clkcon |= clocks;
+	else
+		clkcon &= ~clocks;
+
+	__raw_writel(clkcon, S3C2443_HCLKCON);
+
+	return 0;
+}
+
+static int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
+{
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
+
+	clkcon = __raw_readl(S3C2443_PCLKCON);
+
+	if (enable)
+		clkcon |= clocks;
+	else
+		clkcon &= ~clocks;
+
+	__raw_writel(clkcon, S3C2443_HCLKCON);
+
+	return 0;
+}
+
+static int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
+{
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
+
+	clkcon = __raw_readl(S3C2443_SCLKCON);
+
+	if (enable)
+		clkcon |= clocks;
+	else
+		clkcon &= ~clocks;
+
+	__raw_writel(clkcon, S3C2443_SCLKCON);
+
+	return 0;
+}
+
+static unsigned long s3c2443_roundrate_clksrc(struct clk *clk,
+					      unsigned long rate,
+					      unsigned int max)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	/* note, we remove the +/- 1 calculations as they cancel out */
+
+	div = (rate / parent_rate);
+
+	if (div < 1)
+		div = 1;
+	else if (div > max)
+		div = max;
+
+	return parent_rate / div;
+}
+
+static unsigned long s3c2443_roundrate_clksrc4(struct clk *clk,
+					       unsigned long rate)
+{
+	return s3c2443_roundrate_clksrc(clk, rate, 4);
+}
+
+static unsigned long s3c2443_roundrate_clksrc16(struct clk *clk,
+						unsigned long rate)
+{
+	return s3c2443_roundrate_clksrc(clk, rate, 16);
+}
+
+static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk,
+						 unsigned long rate)
+{
+	return s3c2443_roundrate_clksrc(clk, rate, 256);
+}
+
+/* clock selections */
+
+/* CPU EXTCLK input */
+static struct clk clk_ext = {
+	.name		= "ext",
+	.id		= -1,
+};
+
+static struct clk clk_mpllref = {
+	.name		= "mpllref",
+	.parent		= &clk_xtal,
+	.id		= -1,
+};
+
+#if 0
+static struct clk clk_mpll = {
+	.name		= "mpll",
+	.parent		= &clk_mpllref,
+	.id		= -1,
+};
+#endif
+
+static struct clk clk_epllref;
+
+static struct clk clk_epll = {
+	.name		= "epll",
+	.parent		= &clk_epllref,
+	.id		= -1,
+};
+
+static struct clk clk_i2s_ext = {
+	.name		= "i2s-ext",
+	.id		= -1,
+};
+
+static int s3c2443_setparent_epllref(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+	clksrc &= ~S3C2443_CLKSRC_EPLLREF_MASK;
+
+	if (parent == &clk_xtal)
+		clksrc |= S3C2443_CLKSRC_EPLLREF_XTAL;
+	else if (parent == &clk_ext)
+		clksrc |= S3C2443_CLKSRC_EPLLREF_EXTCLK;
+	else if (parent != &clk_mpllref)
+		return -EINVAL;
+
+	__raw_writel(clksrc, S3C2443_CLKSRC);
+	clk->parent = parent;
+
+	return 0;
+}
+
+static struct clk clk_epllref = {
+	.name		= "epllref",
+	.id		= -1,
+	.set_parent	= s3c2443_setparent_epllref,
+};
+
+static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2443_CLKDIV0);
+
+	div  &= S3C2443_CLKDIV0_EXTDIV_MASK;
+	div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1);	/* x2 */
+
+	return parent_rate / (div + 1);
+}
+
+static struct clk clk_mdivclk = {
+	.name		= "mdivclk",
+	.parent		= &clk_mpllref,
+	.id		= -1,
+	.get_rate	= s3c2443_getrate_mdivclk,
+};
+
+
+static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+	clksrc &= ~(S3C2443_CLKSRC_MSYSCLK_MPLL |
+		    S3C2443_CLKSRC_EXTCLK_DIV);
+
+	if (parent == &clk_mpll)
+		clksrc |= S3C2443_CLKSRC_MSYSCLK_MPLL;
+	else if (parent == &clk_mdivclk)
+		clksrc |= S3C2443_CLKSRC_EXTCLK_DIV;
+	else if (parent != &clk_mpllref)
+		return -EINVAL;
+
+	__raw_writel(clksrc, S3C2443_CLKSRC);
+	clk->parent = parent;
+
+	return 0;
+}
+
+static struct clk clk_msysclk = {
+	.name		= "msysclk",
+	.parent		= &clk_xtal,
+	.id		= -1,
+	.set_parent	= s3c2443_setparent_msysclk,
+};
+
+
+/* esysclk
+ *
+ * this is sourced from either the EPLL or the EPLLref clock
+*/
+
+static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+	if (parent == &clk_epll)
+		clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL;
+	else if (parent == &clk_epllref)
+		clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL;
+	else
+		return -EINVAL;
+
+	__raw_writel(clksrc, S3C2443_CLKSRC);
+	clk->parent = parent;
+
+	return 0;
+}
+
+static struct clk clk_esysclk = {
+	.name		= "esysclk",
+	.parent		= &clk_epll,
+	.id		= -1,
+	.set_parent	= s3c2443_setparent_esysclk,
+};
+
+/* uartclk
+ *
+ * UART baud-rate clock sourced from esysclk via a divisor
+*/
+
+static unsigned long s3c2443_getrate_uart(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+	div &= S3C2443_CLKDIV1_UARTDIV_MASK;
+	div >>= S3C2443_CLKDIV1_UARTDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+
+static int s3c2443_setrate_uart(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+	rate = s3c2443_roundrate_clksrc16(clk, rate);
+	rate = parent_rate / rate;
+
+	clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
+	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2443_CLKDIV1);
+	return 0;
+}
+
+static struct clk clk_uart = {
+	.name		= "uartclk",
+	.id		= -1,
+	.parent		= &clk_esysclk,
+	.get_rate	= s3c2443_getrate_uart,
+	.set_rate	= s3c2443_setrate_uart,
+	.round_rate	= s3c2443_roundrate_clksrc16,
+};
+
+/* hsspi
+ *
+ * high-speed spi clock, sourced from esysclk
+*/
+
+static unsigned long s3c2443_getrate_hsspi(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+	div &= S3C2443_CLKDIV1_HSSPIDIV_MASK;
+	div >>= S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+
+static int s3c2443_setrate_hsspi(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+	rate = s3c2443_roundrate_clksrc4(clk, rate);
+	rate = parent_rate / rate;
+
+	clkdivn &= ~S3C2443_CLKDIV1_HSSPIDIV_MASK;
+	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2443_CLKDIV1);
+	return 0;
+}
+
+static struct clk clk_hsspi = {
+	.name		= "hsspi",
+	.id		= -1,
+	.parent		= &clk_esysclk,
+	.ctrlbit	= S3C2443_SCLKCON_HSSPICLK,
+	.enable		= s3c2443_clkcon_enable_s,
+	.get_rate	= s3c2443_getrate_hsspi,
+	.set_rate	= s3c2443_setrate_hsspi,
+	.round_rate	= s3c2443_roundrate_clksrc4,
+};
+
+/* usbhost
+ *
+ * usb host bus-clock, usually 48MHz to provide USB bus clock timing
+*/
+
+static unsigned long s3c2443_getrate_usbhost(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+	div &= S3C2443_CLKDIV1_USBHOSTDIV_MASK;
+	div >>= S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_usbhost(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+	rate = s3c2443_roundrate_clksrc4(clk, rate);
+	rate = parent_rate / rate;
+
+	clkdivn &= ~S3C2443_CLKDIV1_USBHOSTDIV_MASK;
+	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2443_CLKDIV1);
+	return 0;
+}
+
+struct clk clk_usb_bus_host = {
+	.name		= "usb-bus-host-parent",
+	.id		= -1,
+	.parent		= &clk_esysclk,
+	.ctrlbit	= S3C2443_SCLKCON_USBHOST,
+	.enable		= s3c2443_clkcon_enable_s,
+	.get_rate	= s3c2443_getrate_usbhost,
+	.set_rate	= s3c2443_setrate_usbhost,
+	.round_rate	= s3c2443_roundrate_clksrc4,
+};
+
+/* clk_hsmcc_div
+ *
+ * this clock is sourced from epll, and is fed through a divider,
+ * to a mux controlled by sclkcon where either it or a extclk can
+ * be fed to the hsmmc block
+*/
+
+static unsigned long s3c2443_getrate_hsmmc_div(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+	div &= S3C2443_CLKDIV1_HSMMCDIV_MASK;
+	div >>= S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_hsmmc_div(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+	rate = s3c2443_roundrate_clksrc4(clk, rate);
+	rate = parent_rate / rate;
+
+	clkdivn &= ~S3C2443_CLKDIV1_HSMMCDIV_MASK;
+	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2443_CLKDIV1);
+	return 0;
+}
+
+static struct clk clk_hsmmc_div = {
+	.name		= "hsmmc-div",
+	.id		= -1,
+	.parent		= &clk_esysclk,
+	.get_rate	= s3c2443_getrate_hsmmc_div,
+	.set_rate	= s3c2443_setrate_hsmmc_div,
+	.round_rate	= s3c2443_roundrate_clksrc4,
+};
+
+static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
+
+	clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
+		    S3C2443_SCLKCON_HSMMCCLK_EPLL);
+
+	if (parent == &clk_epll)
+		clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
+	else if (parent == &clk_ext)
+		clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
+	else
+		return -EINVAL;
+
+	if (clk->usage > 0) {
+		__raw_writel(clksrc, S3C2443_SCLKCON);
+	}
+
+	clk->parent = parent;
+	return 0;
+}
+
+static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
+{
+	return s3c2443_setparent_hsmmc(clk, clk->parent);
+}
+
+static struct clk clk_hsmmc = {
+	.name		= "hsmmc-if",
+	.id		= -1,
+	.parent		= &clk_hsmmc_div,
+	.enable		= s3c2443_enable_hsmmc,
+	.set_parent	= s3c2443_setparent_hsmmc,
+};
+
+/* i2s_eplldiv
+ *
+ * this clock is the output from the i2s divisor of esysclk
+*/
+
+static unsigned long s3c2443_getrate_i2s_eplldiv(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+	div &= S3C2443_CLKDIV1_I2SDIV_MASK;
+	div >>= S3C2443_CLKDIV1_I2SDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_i2s_eplldiv(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+	rate = s3c2443_roundrate_clksrc16(clk, rate);
+	rate = parent_rate / rate;
+
+	clkdivn &= ~S3C2443_CLKDIV1_I2SDIV_MASK;
+	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_I2SDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2443_CLKDIV1);
+	return 0;
+}
+
+static struct clk clk_i2s_eplldiv = {
+	.name		= "i2s-eplldiv",
+	.id		= -1,
+	.parent		= &clk_esysclk,
+	.get_rate	= s3c2443_getrate_i2s_eplldiv,
+	.set_rate	= s3c2443_setrate_i2s_eplldiv,
+	.round_rate	= s3c2443_roundrate_clksrc16,
+};
+
+/* i2s-ref
+ *
+ * i2s bus reference clock, selectable from external, esysclk or epllref
+*/
+
+static int s3c2443_setparent_i2s(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+	clksrc &= ~S3C2443_CLKSRC_I2S_MASK;
+
+	if (parent == &clk_epllref)
+		clksrc |= S3C2443_CLKSRC_I2S_EPLLREF;
+	else if (parent == &clk_i2s_ext)
+		clksrc |= S3C2443_CLKSRC_I2S_EXT;
+	else if (parent != &clk_i2s_eplldiv)
+		return -EINVAL;
+
+	clk->parent = parent;
+	__raw_writel(clksrc, S3C2443_CLKSRC);
+
+	return 0;
+}
+
+static struct clk clk_i2s = {
+	.name		= "i2s-if",
+	.id		= -1,
+	.parent		= &clk_i2s_eplldiv,
+	.ctrlbit	= S3C2443_SCLKCON_I2SCLK,
+	.enable		= s3c2443_clkcon_enable_s,
+	.set_parent	= s3c2443_setparent_i2s,
+};
+
+/* cam-if
+ *
+ * camera interface bus-clock, divided down from esysclk
+*/
+
+static unsigned long s3c2443_getrate_cam(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+	div  &= S3C2443_CLKDIV1_CAMDIV_MASK;
+	div >>= S3C2443_CLKDIV1_CAMDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_cam(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdiv1 = __raw_readl(S3C2443_CLKDIV1);
+
+	rate = s3c2443_roundrate_clksrc16(clk, rate);
+	rate = parent_rate / rate;
+
+	clkdiv1 &= ~S3C2443_CLKDIV1_CAMDIV_MASK;
+	clkdiv1 |= (rate - 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT;
+
+	__raw_writel(clkdiv1, S3C2443_CLKDIV1);
+	return 0;
+}
+
+static struct clk clk_cam = {
+	.name		= "camif-upll",		/* same as 2440 name */
+	.id		= -1,
+	.parent		= &clk_esysclk,
+	.ctrlbit	= S3C2443_SCLKCON_CAMCLK,
+	.enable		= s3c2443_clkcon_enable_s,
+	.get_rate	= s3c2443_getrate_cam,
+	.set_rate	= s3c2443_setrate_cam,
+	.round_rate	= s3c2443_roundrate_clksrc16,
+};
+
+/* display-if
+ *
+ * display interface clock, divided from esysclk
+*/
+
+static unsigned long s3c2443_getrate_display(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+	div &= S3C2443_CLKDIV1_DISPDIV_MASK;
+	div >>= S3C2443_CLKDIV1_DISPDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_display(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+	rate = s3c2443_roundrate_clksrc256(clk, rate);
+	rate = parent_rate / rate;
+
+	clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
+	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2443_CLKDIV1);
+	return 0;
+}
+
+static struct clk clk_display = {
+	.name		= "display-if",
+	.id		= -1,
+	.parent		= &clk_esysclk,
+	.ctrlbit	= S3C2443_SCLKCON_DISPCLK,
+	.enable		= s3c2443_clkcon_enable_s,
+	.get_rate	= s3c2443_getrate_display,
+	.set_rate	= s3c2443_setrate_display,
+	.round_rate	= s3c2443_roundrate_clksrc256,
+};
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+	}, {
+		.name		= "sdi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_SDI,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_ADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_IIC,
+	}, {
+		.name		= "iis",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_IIS,
+	}, {
+		.name		= "spi",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_SPI0,
+	}, {
+		.name		= "spi",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_SPI1,
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "dma",
+		.id		= 0,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_DMA0,
+	}, {
+		.name		= "dma",
+		.id		= 1,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_DMA1,
+	}, {
+		.name		= "dma",
+		.id		= 2,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_DMA2,
+	}, {
+		.name		= "dma",
+		.id		= 3,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_DMA3,
+	}, {
+		.name		= "dma",
+		.id		= 4,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_DMA4,
+	}, {
+		.name		= "dma",
+		.id		= 5,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_DMA5,
+	}, {
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_LCDC,
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_GPIO,
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_USBH,
+	}, {
+		.name		= "usb-device",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2443_clkcon_enable_h,
+		.ctrlbit	= S3C2443_HCLKCON_USBD,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_PWMT,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_UART2,
+	}, {
+		.name		= "uart",
+		.id		= 3,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_UART3,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= S3C2443_PCLKCON_WDT,
+	}, {
+		.name		= "usb-bus-host",
+		.id		= -1,
+		.parent		= &clk_usb_bus_host,
+	}
+};
+
+/* clocks to add where we need to check their parentage */
+
+/* s3c2443_clk_initparents
+ *
+ * Initialise the parents for the clocks that we get at start-time
+*/
+
+static int __init clk_init_set_parent(struct clk *clk, struct clk *parent)
+{
+	printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name);
+	return clk_set_parent(clk, parent);
+}
+
+static void __init s3c2443_clk_initparents(void)
+{
+	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+	struct clk *parent;
+
+	switch (clksrc & S3C2443_CLKSRC_EPLLREF_MASK) {
+	case S3C2443_CLKSRC_EPLLREF_EXTCLK:
+		parent = &clk_ext;
+		break;
+
+	case S3C2443_CLKSRC_EPLLREF_XTAL:
+	default:
+		parent = &clk_xtal;
+		break;
+
+	case S3C2443_CLKSRC_EPLLREF_MPLLREF:
+	case S3C2443_CLKSRC_EPLLREF_MPLLREF2:
+		parent = &clk_mpllref;
+		break;
+	}
+
+	clk_init_set_parent(&clk_epllref, parent);
+
+	switch (clksrc & S3C2443_CLKSRC_I2S_MASK) {
+	case S3C2443_CLKSRC_I2S_EXT:
+		parent = &clk_i2s_ext;
+		break;
+
+	case S3C2443_CLKSRC_I2S_EPLLDIV:
+	default:
+		parent = &clk_i2s_eplldiv;
+		break;
+
+	case S3C2443_CLKSRC_I2S_EPLLREF:
+	case S3C2443_CLKSRC_I2S_EPLLREF3:
+		parent = &clk_epllref;
+	}
+
+	clk_init_set_parent(&clk_i2s, &clk_epllref);
+
+	/* esysclk source */
+
+	parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?
+		&clk_epll : &clk_epllref;
+
+	clk_init_set_parent(&clk_esysclk, parent);
+
+	/* msysclk source */
+
+	if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) {
+		parent = &clk_mpll;
+	} else {
+		parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ?
+			&clk_mdivclk : &clk_mpllref;
+	}
+
+	clk_init_set_parent(&clk_msysclk, parent);
+}
+
+/* armdiv divisor table */
+
+static unsigned int armdiv[16] = {
+	[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 1,
+	[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 2,
+	[S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 3,
+	[S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 4,
+	[S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 6,
+	[S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 8,
+	[S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 12,
+	[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 16,
+};
+
+static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
+{
+	clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
+
+	return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
+}
+
+static inline unsigned long s3c2443_get_prediv(unsigned long clkcon0)
+{
+	clkcon0 &= S3C2443_CLKDIV0_PREDIV_MASK;
+	clkcon0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;
+
+	return clkcon0 + 1;
+}
+
+/* clocks to add straight away */
+
+static struct clk *clks[] __initdata = {
+	&clk_ext,
+	&clk_epll,
+	&clk_usb_bus_host,
+	&clk_usb_bus,
+	&clk_esysclk,
+	&clk_epllref,
+	&clk_mpllref,
+	&clk_msysclk,
+	&clk_uart,
+	&clk_display,
+	&clk_cam,
+	&clk_i2s_eplldiv,
+	&clk_i2s,
+	&clk_hsspi,
+	&clk_hsmmc_div,
+	&clk_hsmmc,
+};
+
+void __init s3c2443_init_clocks(int xtal)
+{
+	unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
+	unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
+	unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
+	unsigned long pll;
+	unsigned long fclk;
+	unsigned long hclk;
+	unsigned long pclk;
+	struct clk *clkp;
+	int ret;
+	int ptr;
+
+	pll = s3c2443_get_mpll(mpllcon, xtal);
+
+	fclk = pll / s3c2443_fclk_div(clkdiv0);
+	hclk = fclk / s3c2443_get_prediv(clkdiv0);
+	hclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_HCLK) ? 2 : 1);
+ 	pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
+
+	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+
+	printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
+	       (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on",
+	       print_mhz(pll), print_mhz(fclk),
+	       print_mhz(hclk), print_mhz(pclk));
+
+	s3c2443_clk_initparents();
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
+		clkp = clks[ptr];
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
+
+	clk_usb_bus.parent = &clk_usb_bus_host;
+
+	/* ensure usb bus clock is within correct rate of 48MHz */
+
+	if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) {
+		printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
+		clk_set_rate(&clk_usb_bus_host, 48*1000*1000);
+	}
+
+	printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
+	       (epllcon & S3C2443_PLLCON_OFF) ? "off":"on",
+	       print_mhz(clk_get_rate(&clk_epll)),
+	       print_mhz(clk_get_rate(&clk_usb_bus)));
+
+	/* register clocks from clock array */
+
+	clkp = init_clocks;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* We must be careful disabling the clocks we are not intending to
+	 * be using at boot time, as subsytems such as the LCD which do
+	 * their own DMA requests to the bus can cause the system to lockup
+	 * if they where in the middle of requesting bus access.
+	 *
+	 * Disabling the LCD clock if the LCD is active is very dangerous,
+	 * and therefore the bootloader should be careful to not enable
+	 * the LCD clock if it is not needed.
+	*/
+
+	/* install (and disable) the clocks we do not need immediately */
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+
+		(clkp->enable)(clkp, 0);
+	}
+}
diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c
new file mode 100644
index 0000000..f70e8cc
--- /dev/null
+++ b/arch/arm/mach-s3c2443/dma.c
@@ -0,0 +1,180 @@
+/* linux/arch/arm/mach-s3c2443/dma.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2443 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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/sysdev.h>
+#include <linux/serial_core.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include <asm/io.h>
+
+#include <asm/plat-s3c24xx/dma.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+#define MAP(x) { \
+		[0]	= (x) | DMA_CH_VALID,	\
+		[1]	= (x) | DMA_CH_VALID,	\
+		[2]	= (x) | DMA_CH_VALID,	\
+		[3]	= (x) | DMA_CH_VALID,	\
+		[4]	= (x) | DMA_CH_VALID,	\
+		[5]     = (x) | DMA_CH_VALID,	\
+	}
+
+static struct s3c24xx_dma_map __initdata s3c2443_dma_mappings[] = {
+	[DMACH_XD0] = {
+		.name		= "xdreq0",
+		.channels	= MAP(S3C2443_DMAREQSEL_XDREQ0),
+	},
+	[DMACH_XD1] = {
+		.name		= "xdreq1",
+		.channels	= MAP(S3C2443_DMAREQSEL_XDREQ1),
+	},
+	[DMACH_SDI] = {
+		.name		= "sdi",
+		.channels	= MAP(S3C2443_DMAREQSEL_SDI),
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_SPI0] = {
+		.name		= "spi0",
+		.channels	= MAP(S3C2443_DMAREQSEL_SPI0TX),
+		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
+	},
+	[DMACH_SPI1] = {
+		.name		= "spi1",
+		.channels	= MAP(S3C2443_DMAREQSEL_SPI1TX),
+		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+	},
+	[DMACH_UART0] = {
+		.name		= "uart0",
+		.channels	= MAP(S3C2443_DMAREQSEL_UART0_0),
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1] = {
+		.name		= "uart1",
+		.channels	= MAP(S3C2443_DMAREQSEL_UART1_0),
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2] = {
+		.name		= "uart2",
+		.channels	= MAP(S3C2443_DMAREQSEL_UART2_0),
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+      	[DMACH_UART3] = {
+		.name		= "uart3",
+		.channels	= MAP(S3C2443_DMAREQSEL_UART3_0),
+		.hw_addr.to	= S3C2443_PA_UART3 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2443_PA_UART3 + S3C2410_URXH,
+	},
+	[DMACH_UART0_SRC2] = {
+		.name		= "uart0",
+		.channels	= MAP(S3C2443_DMAREQSEL_UART0_1),
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1_SRC2] = {
+		.name		= "uart1",
+		.channels	= MAP(S3C2443_DMAREQSEL_UART1_1),
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2_SRC2] = {
+		.name		= "uart2",
+		.channels	= MAP(S3C2443_DMAREQSEL_UART2_1),
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+      	[DMACH_UART3_SRC2] = {
+		.name		= "uart3",
+		.channels	= MAP(S3C2443_DMAREQSEL_UART3_1),
+		.hw_addr.to	= S3C2443_PA_UART3 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2443_PA_UART3 + S3C2410_URXH,
+	},
+	[DMACH_TIMER] = {
+		.name		= "timer",
+		.channels	= MAP(S3C2443_DMAREQSEL_TIMER),
+	},
+	[DMACH_I2S_IN] = {
+		.name		= "i2s-sdi",
+		.channels	= MAP(S3C2443_DMAREQSEL_I2SRX),
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_I2S_OUT] = {
+		.name		= "i2s-sdo",
+		.channels	= MAP(S3C2443_DMAREQSEL_I2STX),
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_PCM_IN] = {
+		.name		= "pcm-in",
+		.channels	= MAP(S3C2443_DMAREQSEL_PCMIN),
+		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+	},
+	[DMACH_PCM_OUT] = {
+		.name		= "pcm-out",
+		.channels	= MAP(S3C2443_DMAREQSEL_PCMOUT),
+		.hw_addr.to	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+	},
+	[DMACH_MIC_IN] = {
+		.name		= "mic-in",
+		.channels	= MAP(S3C2443_DMAREQSEL_MICIN),
+		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
+	},
+};
+
+static void s3c2443_dma_select(struct s3c2410_dma_chan *chan,
+			       struct s3c24xx_dma_map *map)
+{
+	writel(map->channels[0] | S3C2443_DMAREQSEL_HW,
+	       chan->regs + S3C2443_DMA_DMAREQSEL);
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2443_dma_sel = {
+	.select		= s3c2443_dma_select,
+	.dcon_mask	= 0,
+	.map		= s3c2443_dma_mappings,
+	.map_size	= ARRAY_SIZE(s3c2443_dma_mappings),
+};
+
+static int s3c2443_dma_add(struct sys_device *sysdev)
+{
+	s3c24xx_dma_init(6, IRQ_S3C2443_DMA0, 0x100);
+	return s3c24xx_dma_init_map(&s3c2443_dma_sel);
+}
+
+static struct sysdev_driver s3c2443_dma_driver = {
+	.add	= s3c2443_dma_add,
+};
+
+static int __init s3c2443_dma_init(void)
+{
+	return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_dma_driver);
+}
+
+arch_initcall(s3c2443_dma_init);
diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c
new file mode 100644
index 0000000..7a45b6d
--- /dev/null
+++ b/arch/arm/mach-s3c2443/irq.c
@@ -0,0 +1,290 @@
+/* linux/arch/arm/mach-s3c2443/irq.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
+
+#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
+
+static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len)
+{
+	unsigned int subsrc, submsk;
+	unsigned int end;
+	struct irq_desc *mydesc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	subsrc  &= ~submsk;
+	subsrc >>= (irq - S3C2410_IRQSUB(0));
+	subsrc  &= (1 << len)-1;
+
+	end = len + irq;
+	mydesc = irq_desc + irq;
+
+	for (; irq < end && subsrc; irq++) {
+		if (subsrc & 1)
+			desc_handle_irq(irq, mydesc);
+
+		mydesc++;
+		subsrc >>= 1;
+	}
+}
+
+/* WDT/AC97 sub interrupts */
+
+static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc)
+{
+	s3c2443_irq_demux(IRQ_S3C2443_WDT, 4);
+}
+
+#define INTMSK_WDTAC97	(1UL << (IRQ_WDT - IRQ_EINT0))
+#define SUBMSK_WDTAC97	INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
+
+static void s3c2443_irq_wdtac97_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+}
+
+static void s3c2443_irq_wdtac97_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_WDTAC97);
+}
+
+static void s3c2443_irq_wdtac97_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+}
+
+static struct irq_chip s3c2443_irq_wdtac97 = {
+	.mask	    = s3c2443_irq_wdtac97_mask,
+	.unmask	    = s3c2443_irq_wdtac97_unmask,
+	.ack	    = s3c2443_irq_wdtac97_ack,
+};
+
+
+/* LCD sub interrupts */
+
+static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
+{
+	s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4);
+}
+
+#define INTMSK_LCD	(1UL << (IRQ_LCD - IRQ_EINT0))
+#define SUBMSK_LCD	INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
+
+static void s3c2443_irq_lcd_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_LCD, SUBMSK_LCD);
+}
+
+static void s3c2443_irq_lcd_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_LCD);
+}
+
+static void s3c2443_irq_lcd_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_LCD, SUBMSK_LCD);
+}
+
+static struct irq_chip s3c2443_irq_lcd = {
+	.mask	    = s3c2443_irq_lcd_mask,
+	.unmask	    = s3c2443_irq_lcd_unmask,
+	.ack	    = s3c2443_irq_lcd_ack,
+};
+
+
+/* DMA sub interrupts */
+
+static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
+{
+	s3c2443_irq_demux(IRQ_S3C2443_DMA1, 6);
+}
+
+#define INTMSK_DMA	(1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
+#define SUBMSK_DMA	INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
+
+
+static void s3c2443_irq_dma_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_DMA, SUBMSK_DMA);
+}
+
+static void s3c2443_irq_dma_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_DMA);
+}
+
+static void s3c2443_irq_dma_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_DMA, SUBMSK_DMA);
+}
+
+static struct irq_chip s3c2443_irq_dma = {
+	.mask	    = s3c2443_irq_dma_mask,
+	.unmask	    = s3c2443_irq_dma_unmask,
+	.ack	    = s3c2443_irq_dma_ack,
+};
+
+
+/* UART3 sub interrupts */
+
+static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
+{
+	s3c2443_irq_demux(IRQ_S3C2443_UART3, 3);
+}
+
+#define INTMSK_UART3	(1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
+#define SUBMSK_UART3	(0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
+
+
+static void s3c2443_irq_uart3_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_UART3, SUBMSK_UART3);
+}
+
+static void s3c2443_irq_uart3_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_UART3);
+}
+
+static void s3c2443_irq_uart3_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_UART3, SUBMSK_UART3);
+}
+
+static struct irq_chip s3c2443_irq_uart3 = {
+	.mask	    = s3c2443_irq_uart3_mask,
+	.unmask	    = s3c2443_irq_uart3_unmask,
+	.ack	    = s3c2443_irq_uart3_ack,
+};
+
+
+/* CAM sub interrupts */
+
+static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc)
+{
+	s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4);
+}
+
+#define INTMSK_CAM	(1UL << (IRQ_CAM - IRQ_EINT0))
+#define SUBMSK_CAM	INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P)
+
+static void s3c2443_irq_cam_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_CAM, SUBMSK_CAM);
+}
+
+static void s3c2443_irq_cam_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_CAM);
+}
+
+static void s3c2443_irq_cam_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_CAM, SUBMSK_CAM);
+}
+
+static struct irq_chip s3c2443_irq_cam = {
+	.mask	    = s3c2443_irq_cam_mask,
+	.unmask	    = s3c2443_irq_cam_unmask,
+	.ack	    = s3c2443_irq_cam_ack,
+};
+
+/* IRQ initialisation code */
+
+static int __init s3c2443_add_sub(unsigned int base,
+				   void (*demux)(unsigned int,
+						 struct irq_desc *),
+				   struct irq_chip *chip,
+				   unsigned int start, unsigned int end)
+{
+	unsigned int irqno;
+
+	set_irq_chip(base, &s3c_irq_level_chip);
+	set_irq_handler(base, handle_level_irq);
+	set_irq_chained_handler(base, demux);
+
+	for (irqno = start; irqno <= end; irqno++) {
+		set_irq_chip(irqno, chip);
+		set_irq_handler(irqno, handle_level_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	return 0;
+}
+
+static int s3c2443_irq_add(struct sys_device *sysdev)
+{
+	printk("S3C2443: IRQ Support\n");
+
+	s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam,
+			IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P);
+
+	s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd,
+			IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4);
+
+	s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma,
+			&s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5);
+
+	s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3,
+			&s3c2443_irq_uart3,
+			IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3);
+
+	s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97,
+			&s3c2443_irq_wdtac97,
+			IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2443_irq_driver = {
+	.add		= s3c2443_irq_add,
+};
+
+static int s3c2443_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_irq_driver);
+}
+
+arch_initcall(s3c2443_irq_init);
+
diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c
new file mode 100644
index 0000000..e82aaff
--- /dev/null
+++ b/arch/arm/mach-s3c2443/mach-smdk2443.c
@@ -0,0 +1,137 @@
+/* linux/arch/arm/mach-s3c2443/mach-smdk2443.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.fluff.org/ben/smdk2443/
+ *
+ * Thanks to Samsung for the loan of an SMDK2443
+ *
+ * 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/serial_core.h>
+#include <linux/platform_device.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/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/plat-s3c24xx/common-smdk.h>
+
+static struct map_desc smdk2443_iodesc[] __initdata = {
+	/* ISA IO Space map (memory space selected by A24) */
+
+	{
+		.virtual	= (u32)S3C24XX_VA_ISA_WORD,
+		.pfn		= __phys_to_pfn(S3C2410_CS2),
+		.length		= 0x10000,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (u32)S3C24XX_VA_ISA_WORD + 0x10000,
+		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+		.length		= SZ_4M,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
+		.pfn		= __phys_to_pfn(S3C2410_CS2),
+		.length		= 0x10000,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
+		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+		.length		= SZ_4M,
+		.type		= MT_DEVICE,
+	}
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk2443_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	/* IR port */
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x43,
+		.ufcon	     = 0x51,
+	}
+};
+
+static struct platform_device *smdk2443_devices[] __initdata = {
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+};
+
+static struct s3c24xx_board smdk2443_board __initdata = {
+	.devices       = smdk2443_devices,
+	.devices_count = ARRAY_SIZE(smdk2443_devices)
+};
+
+static void __init smdk2443_map_io(void)
+{
+	s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
+	s3c24xx_set_board(&smdk2443_board);
+}
+
+static void __init smdk2443_machine_init(void)
+{
+	smdk_machine_init();
+}
+
+MACHINE_START(SMDK2443, "SMDK2443")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= smdk2443_map_io,
+	.init_machine	= smdk2443_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c
new file mode 100644
index 0000000..11b1d0b
--- /dev/null
+++ b/arch/arm/mach-s3c2443/s3c2443.c
@@ -0,0 +1,97 @@
+/* linux/arch/arm/mach-s3c2443/s3c2443.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2443 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#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/serial_core.h>
+#include <linux/sysdev.h>
+#include <linux/clk.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-s3c2443-clock.h>
+#include <asm/arch/reset.h>
+
+#include <asm/plat-s3c24xx/s3c2443.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+static struct map_desc s3c2443_iodesc[] __initdata = {
+	IODESC_ENT(WATCHDOG),
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(TIMER),
+};
+
+struct sysdev_class s3c2443_sysclass = {
+	set_kset_name("s3c2443-core"),
+};
+
+static struct sys_device s3c2443_sysdev = {
+	.cls		= &s3c2443_sysclass,
+};
+
+static void s3c2443_hard_reset(void)
+{
+	__raw_writel(S3C2443_SWRST_RESET, S3C2443_SWRST);
+}
+
+int __init s3c2443_init(void)
+{
+	printk("S3C2443: Initialising architecture\n");
+
+	s3c24xx_reset_hook = s3c2443_hard_reset;
+
+	s3c_device_nand.name = "s3c2412-nand";
+
+	return sysdev_register(&s3c2443_sysdev);
+}
+
+void __init s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
+}
+
+/* s3c2443_map_io
+ *
+ * register the standard cpu IO areas, and any passed in from the
+ * machine specific initialisation.
+ */
+
+void __init s3c2443_map_io(struct map_desc *mach_desc, int mach_size)
+{
+	iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
+	iotable_init(mach_desc, mach_size);
+}
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2443 based system)
+ * as a driver which may support both 2443 and 2440 may try and use it.
+*/
+
+static int __init s3c2443_core_init(void)
+{
+	return sysdev_class_register(&s3c2443_sysclass);
+}
+
+core_initcall(s3c2443_core_init);
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index e510295..192a5a2 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -138,6 +138,36 @@
 	return v;
 }
 
+int gpio_direction_input(unsigned gpio)
+{
+	unsigned long flags;
+
+	if (gpio > GPIO_MAX)
+		return -EINVAL;
+
+	local_irq_save(flags);
+	GPDR &= ~GPIO_GPIO(gpio);
+	local_irq_restore(flags);
+	return 0;
+}
+
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio)
+{
+	unsigned long flags;
+
+	if (gpio > GPIO_MAX)
+		return -EINVAL;
+
+	local_irq_save(flags);
+	GPDR |= GPIO_GPIO(gpio);
+	local_irq_restore(flags);
+	return 0;
+}
+
+EXPORT_SYMBOL(gpio_direction_output);
+
 /*
  * Default power-off for SA1100
  */
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 54ecdaa..64067cd 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -231,12 +231,6 @@
 	&s1d13xxxfb_device,
 };
 
-/* a stub for now, we theoretically cannot suspend without a flashboard */
-int pm_suspend(suspend_state_t state)
-{
-	return -1;
-}
-
 static int __init jornada720_init(void)
 {
 	int ret = -ENODEV;
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index aade2f7..e684e9b 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -171,8 +171,8 @@
 # ARM926T
 config CPU_ARM926T
 	bool "Support ARM926T processor"
-	depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261
-	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261
+	depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_NS9XXX
+	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_NS9XXX
 	select CPU_32v5
 	select CPU_ABRT_EV5TJ
 	select CPU_CACHE_VIVT
@@ -525,7 +525,7 @@
 	  of your chipset/board/processor.
 
 config CPU_HIGH_VECTOR
-	depends !MMU && CPU_CP15 && !CPU_ARM740T
+	depends on !MMU && CPU_CP15 && !CPU_ARM740T
 	bool "Select the High exception vector"
 	default n
 	help
@@ -609,3 +609,10 @@
 	  Forget about fast user space cmpxchg support.
 	  It is just not possible.
 
+config OUTER_CACHE
+	bool
+	default n
+
+config CACHE_L2X0
+	bool
+	select OUTER_CACHE
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index d2f5672..2f8b959 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -66,3 +66,5 @@
 obj-$(CONFIG_CPU_XSCALE)	+= proc-xscale.o
 obj-$(CONFIG_CPU_XSC3)		+= proc-xsc3.o
 obj-$(CONFIG_CPU_V6)		+= proc-v6.o
+
+obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
new file mode 100644
index 0000000..08a36f1
--- /dev/null
+++ b/arch/arm/mm/cache-l2x0.c
@@ -0,0 +1,104 @@
+/*
+ * arch/arm/mm/cache-l2x0.c - L210/L220 cache controller support
+ *
+ * Copyright (C) 2007 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#define CACHE_LINE_SIZE		32
+
+static void __iomem *l2x0_base;
+
+static inline void sync_writel(unsigned long val, unsigned long reg,
+			       unsigned long complete_mask)
+{
+	writel(val, l2x0_base + reg);
+	/* wait for the operation to complete */
+	while (readl(l2x0_base + reg) & complete_mask)
+		;
+}
+
+static inline void cache_sync(void)
+{
+	sync_writel(0, L2X0_CACHE_SYNC, 1);
+}
+
+static inline void l2x0_inv_all(void)
+{
+	/* invalidate all ways */
+	sync_writel(0xff, L2X0_INV_WAY, 0xff);
+	cache_sync();
+}
+
+static void l2x0_inv_range(unsigned long start, unsigned long end)
+{
+	unsigned long addr;
+
+	start &= ~(CACHE_LINE_SIZE - 1);
+	for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
+		sync_writel(addr, L2X0_INV_LINE_PA, 1);
+	cache_sync();
+}
+
+static void l2x0_clean_range(unsigned long start, unsigned long end)
+{
+	unsigned long addr;
+
+	start &= ~(CACHE_LINE_SIZE - 1);
+	for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
+		sync_writel(addr, L2X0_CLEAN_LINE_PA, 1);
+	cache_sync();
+}
+
+static void l2x0_flush_range(unsigned long start, unsigned long end)
+{
+	unsigned long addr;
+
+	start &= ~(CACHE_LINE_SIZE - 1);
+	for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
+		sync_writel(addr, L2X0_CLEAN_INV_LINE_PA, 1);
+	cache_sync();
+}
+
+void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
+{
+	__u32 aux;
+
+	l2x0_base = base;
+
+	/* disable L2X0 */
+	writel(0, l2x0_base + L2X0_CTRL);
+
+	aux = readl(l2x0_base + L2X0_AUX_CTRL);
+	aux &= aux_mask;
+	aux |= aux_val;
+	writel(aux, l2x0_base + L2X0_AUX_CTRL);
+
+	l2x0_inv_all();
+
+	/* enable L2X0 */
+	writel(1, l2x0_base + L2X0_CTRL);
+
+	outer_cache.inv_range = l2x0_inv_range;
+	outer_cache.clean_range = l2x0_clean_range;
+	outer_cache.flush_range = l2x0_flush_range;
+
+	printk(KERN_INFO "L2X0 cache controller enabled\n");
+}
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 6a9c362..1f9f94f 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -205,9 +205,10 @@
 	 * kernel direct-mapped region for device DMA.
 	 */
 	{
-		unsigned long kaddr = (unsigned long)page_address(page);
-		memset(page_address(page), 0, size);
-		dmac_flush_range(kaddr, kaddr + size);
+		void *ptr = page_address(page);
+		memset(ptr, 0, size);
+		dmac_flush_range(ptr, ptr + size);
+		outer_flush_range(__pa(ptr), __pa(ptr) + size);
 	}
 
 	/*
@@ -480,20 +481,24 @@
  * platforms with CONFIG_DMABOUNCE.
  * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
  */
-void consistent_sync(void *vaddr, size_t size, int direction)
+void consistent_sync(const void *start, size_t size, int direction)
 {
-	unsigned long start = (unsigned long)vaddr;
-	unsigned long end   = start + size;
+	const void *end = start + size;
+
+	BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end - 1));
 
 	switch (direction) {
 	case DMA_FROM_DEVICE:		/* invalidate only */
 		dmac_inv_range(start, end);
+		outer_inv_range(__pa(start), __pa(end));
 		break;
 	case DMA_TO_DEVICE:		/* writeback only */
 		dmac_clean_range(start, end);
+		outer_clean_range(__pa(start), __pa(end));
 		break;
 	case DMA_BIDIRECTIONAL:		/* writeback and invalidate */
 		dmac_flush_range(start, end);
+		outer_flush_range(__pa(start), __pa(end));
 		break;
 	default:
 		BUG();
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 79e8002..9da43a0 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -19,7 +19,8 @@
 /*
  * We fork()ed a process, and we need a new context for the child
  * to run in.  We reserve version 0 for initial tasks so we will
- * always allocate an ASID.
+ * always allocate an ASID. The ASID 0 is reserved for the TTBR
+ * register changing sequence.
  */
 void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
@@ -38,8 +39,15 @@
 	 * If we've used up all our ASIDs, we need
 	 * to start a new version and flush the TLB.
 	 */
-	if ((asid & ~ASID_MASK) == 0)
+	if ((asid & ~ASID_MASK) == 0) {
+		asid = ++cpu_last_asid;
+		/* set the reserved ASID before flushing the TLB */
+		asm("mcr	p15, 0, %0, c13, c0, 1	@ set reserved context ID\n"
+		    :
+		    : "r" (0));
+		isb();
 		flush_tlb_all();
+	}
 
 	mm->context.id = asid;
 }
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index cf95c5d..44558d5 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -119,8 +119,6 @@
 		flush_cache_page(vma, addr, pfn);
 }
 
-void __flush_dcache_page(struct address_space *mapping, struct page *page);
-
 /*
  * Take care of architecture specific things when placing a new PTE into
  * a page table, or changing an existing PTE.  Basically, there are two
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 655c837..94fd4bf 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -49,8 +49,10 @@
 
 static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
 static unsigned int ecc_mask __initdata = 0;
+pgprot_t pgprot_user;
 pgprot_t pgprot_kernel;
 
+EXPORT_SYMBOL(pgprot_user);
 EXPORT_SYMBOL(pgprot_kernel);
 
 struct cachepolicy {
@@ -345,6 +347,7 @@
 		mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
 	}
 
+	pgprot_user   = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
 	pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
 				 L_PTE_DIRTY | L_PTE_WRITE |
 				 L_PTE_EXEC | kern_pgprot);
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 7b1843b..eb42e5b 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -14,10 +14,13 @@
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/elf.h>
-#include <asm/hardware/arm_scu.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
 
+#ifdef CONFIG_SMP
+#include <asm/hardware/arm_scu.h>
+#endif
+
 #include "proc-macros.S"
 
 #define D_CACHE_LINE_SIZE	32
@@ -30,6 +33,12 @@
 #define TTB_RGN_WT	(2 << 3)
 #define TTB_RGN_WB	(3 << 3)
 
+#ifndef CONFIG_SMP
+#define TTB_FLAGS	TTB_RGN_WBWA
+#else
+#define TTB_FLAGS	TTB_RGN_WBWA|TTB_S
+#endif
+
 ENTRY(cpu_v6_proc_init)
 	mov	pc, lr
 
@@ -92,9 +101,7 @@
 #ifdef CONFIG_MMU
 	mov	r2, #0
 	ldr	r1, [r1, #MM_CONTEXT_ID]	@ get mm->context.id
-#ifdef CONFIG_SMP
-	orr	r0, r0, #TTB_RGN_WBWA|TTB_S	@ mark PTWs shared, outer cacheable
-#endif
+	orr	r0, r0, #TTB_FLAGS
 	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
 	mcr	p15, 0, r2, c7, c10, 4		@ drain write buffer
 	mcr	p15, 0, r0, c2, c0, 0		@ set TTB 0
@@ -183,8 +190,7 @@
 	/* Set up the SCU on core 0 only */
 	mrc	p15, 0, r0, c0, c0, 5		@ CPU core number
 	ands	r0, r0, #15
-	moveq	r0, #0x10000000 @ SCU_BASE
-	orreq	r0, r0, #0x00100000
+	ldreq	r0, =SCU_BASE
 	ldreq	r5, [r0, #SCU_CTRL]
 	orreq	r5, r5, #1
 	streq	r5, [r0, #SCU_CTRL]
@@ -204,9 +210,7 @@
 #ifdef CONFIG_MMU
 	mcr	p15, 0, r0, c8, c7, 0		@ invalidate I + D TLBs
 	mcr	p15, 0, r0, c2, c0, 2		@ TTB control register
-#ifdef CONFIG_SMP
-	orr	r4, r4, #TTB_RGN_WBWA|TTB_S	@ mark PTWs shared, outer cacheable
-#endif
+	orr	r4, r4, #TTB_FLAGS
 	mcr	p15, 0, r4, c2, c0, 1		@ load TTB1
 #endif /* CONFIG_MMU */
 	adr	r5, v6_crval
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 94a5845..d95921a 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -5,23 +5,23 @@
  * Current Maintainer: Lennert Buytenhek <buytenh@wantstofly.org>
  *
  * Copyright 2004 (C) Intel Corp.
- * Copyright 2005 (c) MontaVista Software, Inc.
+ * Copyright 2005 (C) 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 version 2 as
  * published by the Free Software Foundation.
  *
- * MMU functions for the Intel XScale3 Core (XSC3).  The XSC3 core is an
- * extension to Intel's original XScale core that adds the following
+ * MMU functions for the Intel XScale3 Core (XSC3).  The XSC3 core is
+ * an extension to Intel's original XScale core that adds the following
  * features:
  *
  * - ARMv6 Supersections
  * - Low Locality Reference pages (replaces mini-cache)
  * - 36-bit addressing
  * - L2 cache
- * - Cache-coherency if chipset supports it
+ * - Cache coherency if chipset supports it
  *
- * Based on orignal XScale code by Nicolas Pitre
+ * Based on original XScale code by Nicolas Pitre.
  */
 
 #include <linux/linkage.h>
@@ -42,12 +42,12 @@
 #define MAX_AREA_SIZE	32768
 
 /*
- * The cache line size of the I and D cache.
+ * The cache line size of the L1 I, L1 D and unified L2 cache.
  */
 #define CACHELINESIZE	32
 
 /*
- * The size of the data cache.
+ * The size of the L1 D cache.
  */
 #define CACHESIZE	32768
 
@@ -57,9 +57,9 @@
 #define L2_CACHE_ENABLE	1
 
 /*
- * This macro is used to wait for a CP15 write and is needed
- * when we have to ensure that the last operation to the co-pro
- * was completed before continuing with operation.
+ * This macro is used to wait for a CP15 write and is needed when we
+ * have to ensure that the last operation to the coprocessor was
+ * completed before continuing with operation.
  */
 	.macro	cpwait_ret, lr, rd
 	mrc	p15, 0, \rd, c2, c0, 0		@ arbitrary read of cp15
@@ -68,13 +68,13 @@
 	.endm
 
 /*
- * This macro cleans & invalidates the entire xsc3 dcache by set & way.
+ * This macro cleans and invalidates the entire L1 D cache.
  */
 
  	.macro  clean_d_cache rd, rs
 	mov	\rd, #0x1f00
 	orr	\rd, \rd, #0x00e0
-1:	mcr	p15, 0, \rd, c7, c14, 2		@ clean/inv set/way
+1:	mcr	p15, 0, \rd, c7, c14, 2		@ clean/invalidate L1 D line
 	adds	\rd, \rd, #0x40000000
 	bcc	1b
 	subs	\rd, \rd, #0x20
@@ -119,15 +119,15 @@
 	mov	r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
 	msr	cpsr_c, r1			@ reset CPSR
 	mrc	p15, 0, r1, c1, c0, 0		@ ctrl register
-	bic	r1, r1, #0x0086			@ ........B....CA.
 	bic	r1, r1, #0x3900			@ ..VIZ..S........
+	bic	r1, r1, #0x0086			@ ........B....CA.
 	mcr	p15, 0, r1, c1, c0, 0		@ ctrl register
-	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches & BTB
+	mcr	p15, 0, ip, c7, c7, 0		@ invalidate L1 caches and BTB
 	bic	r1, r1, #0x0001			@ ...............M
 	mcr	p15, 0, r1, c1, c0, 0		@ ctrl register
 	@ CAUTION: MMU turned off from this point.  We count on the pipeline
 	@ already containing those two last instructions to survive.
-	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I and D TLBs
 	mov	pc, r0
 
 /*
@@ -139,14 +139,12 @@
  *
  * XScale supports clock switching, but using idle mode support
  * allows external hardware to react to system state changes.
-
- MMG: Come back to this one.
  */
 	.align	5
 
 ENTRY(cpu_xsc3_do_idle)
 	mov	r0, #1
-	mcr	p14, 0, r0, c7, c0, 0		@ Go to IDLE
+	mcr	p14, 0, r0, c7, c0, 0		@ go to idle
 	mov	pc, lr
 
 /* ================================= CACHE ================================ */
@@ -171,9 +169,9 @@
 __flush_whole_cache:
 	clean_d_cache r0, r1
 	tst	r2, #VM_EXEC
-	mcrne	p15, 0, ip, c7, c5, 0		@ Invalidate I cache & BTB
-	mcrne	p15, 0, ip, c7, c10, 4		@ Drain Write Buffer
-	mcrne	p15, 0, ip, c7, c5, 4		@ Prefetch Flush
+	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate L1 I cache and BTB
+	mcrne	p15, 0, ip, c7, c10, 4		@ data write barrier
+	mcrne	p15, 0, ip, c7, c5, 4		@ prefetch flush
 	mov	pc, lr
 
 /*
@@ -194,21 +192,21 @@
 	bhs	__flush_whole_cache
 
 1:	tst	r2, #VM_EXEC
-	mcrne	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
-	mcr	p15, 0, r0, c7, c14, 1		@ Clean/invalidate D cache line
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate L1 I line
+	mcr	p15, 0, r0, c7, c14, 1		@ clean/invalidate L1 D line
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
 	tst	r2, #VM_EXEC
-	mcrne	p15, 0, ip, c7, c5, 6		@ Invalidate BTB
-	mcrne	p15, 0, ip, c7, c10, 4		@ Drain Write Buffer
-	mcrne	p15, 0, ip, c7, c5, 4		@ Prefetch Flush
+	mcrne	p15, 0, ip, c7, c5, 6		@ invalidate BTB
+	mcrne	p15, 0, ip, c7, c10, 4		@ data write barrier
+	mcrne	p15, 0, ip, c7, c5, 4		@ prefetch flush
 	mov	pc, lr
 
 /*
  *	coherent_kern_range(start, end)
  *
- *	Ensure coherency between the Icache and the Dcache in the
+ *	Ensure coherency between the I cache and the D cache in the
  *	region described by start.  If you have non-snooping
  *	Harvard caches, you need to implement this function.
  *
@@ -222,34 +220,34 @@
 /* FALLTHROUGH */
 ENTRY(xsc3_coherent_user_range)
 	bic	r0, r0, #CACHELINESIZE - 1
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean L1 D line
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
 	mov	r0, #0
-	mcr	p15, 0, r0, c7, c5, 0		@ Invalidate I cache & BTB
-	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write Buffer
-	mcr	p15, 0, r0, c7, c5, 4		@ Prefetch Flush
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate L1 I cache and BTB
+	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
+	mcr	p15, 0, r0, c7, c5, 4		@ prefetch flush
 	mov	pc, lr
 
 /*
  *	flush_kern_dcache_page(void *page)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
- *	the I cache
+ *	the I cache.
  *
  *	- addr	- page aligned address
  */
 ENTRY(xsc3_flush_kern_dcache_page)
 	add	r1, r0, #PAGE_SZ
-1:	mcr	p15, 0, r0, c7, c14, 1		@ Clean/Invalidate D Cache line
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean/invalidate L1 D line
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
 	mov	r0, #0
-	mcr	p15, 0, r0, c7, c5, 0		@ Invalidate I cache & BTB
-	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write Buffer
-	mcr	p15, 0, r0, c7, c5, 4		@ Prefetch Flush
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate L1 I cache and BTB
+	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
+	mcr	p15, 0, r0, c7, c5, 4		@ prefetch flush
 	mov	pc, lr
 
 /*
@@ -266,17 +264,17 @@
 ENTRY(xsc3_dma_inv_range)
 	tst	r0, #CACHELINESIZE - 1
 	bic	r0, r0, #CACHELINESIZE - 1
-	mcrne	p15, 0, r0, c7, c10, 1		@ clean L1 D entry
-	mcrne	p15, 1, r0, c7, c11, 1		@ clean L2 D entry
+	mcrne	p15, 0, r0, c7, c10, 1		@ clean L1 D line
+	mcrne	p15, 1, r0, c7, c11, 1		@ clean L2 line
 	tst	r1, #CACHELINESIZE - 1
-	mcrne	p15, 0, r1, c7, c10, 1		@ clean L1 D entry
-	mcrne	p15, 1, r1, c7, c11, 1		@ clean L2 D entry
-1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate L1 D entry
-	mcr	p15, 1, r0, c7, c7, 1		@ Invalidate L2 D cache line
+	mcrne	p15, 0, r1, c7, c10, 1		@ clean L1 D line
+	mcrne	p15, 1, r1, c7, c11, 1		@ clean L2 line
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate L1 D line
+	mcr	p15, 1, r0, c7, c7, 1		@ invalidate L2 line
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
-	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write Buffer
+	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
 	mov	pc, lr
 
 /*
@@ -289,12 +287,12 @@
  */
 ENTRY(xsc3_dma_clean_range)
 	bic	r0, r0, #CACHELINESIZE - 1
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean L1 D entry
-	mcr	p15, 1, r0, c7, c11, 1		@ clean L2 D entry
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean L1 D line
+	mcr	p15, 1, r0, c7, c11, 1		@ clean L2 line
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
-	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write Buffer
+	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
 	mov	pc, lr
 
 /*
@@ -307,13 +305,13 @@
  */
 ENTRY(xsc3_dma_flush_range)
 	bic	r0, r0, #CACHELINESIZE - 1
-1:	mcr	p15, 0, r0, c7, c14, 1	@ Clean/invalidate L1 D cache line
-	mcr	p15, 1, r0, c7, c11, 1	@ Clean L2 D cache line
-	mcr	p15, 1, r0, c7, c7, 1	@ Invalidate L2 D cache line
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean/invalidate L1 D line
+	mcr	p15, 1, r0, c7, c11, 1		@ clean L2 line
+	mcr	p15, 1, r0, c7, c7, 1		@ invalidate L2 line
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
-	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write Buffer
+	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
 	mov	pc, lr
 
 ENTRY(xsc3_cache_fns)
@@ -328,7 +326,7 @@
 	.long	xsc3_dma_flush_range
 
 ENTRY(cpu_xsc3_dcache_clean_area)
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean L1 D line
 	add	r0, r0, #CACHELINESIZE
 	subs	r1, r1, #CACHELINESIZE
 	bhi	1b
@@ -346,14 +344,14 @@
 	.align	5
 ENTRY(cpu_xsc3_switch_mm)
 	clean_d_cache r1, r2
-	mcr	p15, 0, ip, c7, c5, 0		@ Invalidate I cache & BTB
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write Buffer
-	mcr	p15, 0, ip, c7, c5, 4		@ Prefetch Flush
+	mcr	p15, 0, ip, c7, c5, 0		@ invalidate L1 I cache and BTB
+	mcr	p15, 0, ip, c7, c10, 4		@ data write barrier
+	mcr	p15, 0, ip, c7, c5, 4		@ prefetch flush
 #ifdef L2_CACHE_ENABLE
 	orr	r0, r0, #0x18			@ cache the page table in L2
 #endif
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
-	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I and D TLBs
 	cpwait_ret lr, ip
 
 /*
@@ -366,34 +364,34 @@
 ENTRY(cpu_xsc3_set_pte_ext)
 	str	r1, [r0], #-2048		@ linux version
 
-	bic	r2, r1, #0xff0			@ Keep C, B bits
+	bic	r2, r1, #0xff0			@ keep C, B bits
 	orr	r2, r2, #PTE_TYPE_EXT		@ extended page
-	tst	r1, #L_PTE_SHARED		@ Shared?
+	tst	r1, #L_PTE_SHARED		@ shared?
 	orrne	r2, r2, #0x200
 
 	eor	r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
 
-	tst	r3, #L_PTE_USER			@ User?
+	tst	r3, #L_PTE_USER			@ user?
 	orrne	r2, r2, #PTE_EXT_AP_URO_SRW	@ yes -> user r/o, system r/w
 
-	tst	r3, #L_PTE_WRITE | L_PTE_DIRTY	@ Write and Dirty?
+	tst	r3, #L_PTE_WRITE | L_PTE_DIRTY	@ write and dirty?
 	orreq	r2, r2, #PTE_EXT_AP_UNO_SRW	@ yes -> user n/a, system r/w
 						@ combined with user -> user r/w
 
 #if L2_CACHE_ENABLE
-	@ If its cacheable it needs to be in L2 also.
+	@ If it's cacheable, it needs to be in L2 also.
 	eor	ip, r1, #L_PTE_CACHEABLE
 	tst	ip, #L_PTE_CACHEABLE
 	orreq	r2, r2, #PTE_EXT_TEX(0x5)
 #endif
 
-	tst	r3, #L_PTE_PRESENT | L_PTE_YOUNG	@ Present and Young?
+	tst	r3, #L_PTE_PRESENT | L_PTE_YOUNG	@ present and young?
 	movne	r2, #0				@ no -> fault
 
 	str	r2, [r0]			@ hardware version
 	mov	ip, #0
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line mcr
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write Buffer
+	mcr	p15, 0, r0, c7, c10, 1		@ clean L1 D line
+	mcr	p15, 0, ip, c7, c10, 4		@ data write barrier
 	mov	pc, lr
 
 	.ltorg
@@ -406,17 +404,18 @@
 __xsc3_setup:
 	mov	r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
 	msr	cpsr_c, r0
-	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I, D caches & BTB
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write Buffer
-	mcr	p15, 0, ip, c7, c5, 4		@ Prefetch Flush
-	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I, D TLBs
+	mcr	p15, 0, ip, c7, c7, 0		@ invalidate L1 caches and BTB
+	mcr	p15, 0, ip, c7, c10, 4		@ data write barrier
+	mcr	p15, 0, ip, c7, c5, 4		@ prefetch flush
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I and D TLBs
 #if L2_CACHE_ENABLE
 	orr	r4, r4, #0x18			@ cache the page table in L2
 #endif
 	mcr	p15, 0, r4, c2, c0, 0		@ load page table pointer
-	mov	r0, #1				@ Allow access to CP0 and CP13
-	orr	r0, r0, #1 << 13		@ Its undefined whether this
-	mcr	p15, 0, r0, c15, c1, 0		@ affects USR or SVC modes
+
+	mov	r0, #0				@ don't allow CP access
+	mcr	p15, 0, r0, c15, c1, 0		@ write CP access register
+
 	mrc	p15, 0, r0, c1, c0, 1		@ get auxiliary control reg
 	and	r0, r0, #2			@ preserve bit P bit setting
 #if L2_CACHE_ENABLE
@@ -427,9 +426,9 @@
 	adr	r5, xsc3_crval
 	ldmia	r5, {r5, r6}
 	mrc	p15, 0, r0, c1, c0, 0		@ get control register
-	bic	r0, r0, r5			@ .... .... .... ..A.
-	orr	r0, r0, r6			@ .... .... .... .C.M
-	orr	r0, r0, #0x00000800		@ ..VI Z..S .... ....
+	bic	r0, r0, r5			@ ..V. ..R. .... ..A.
+	orr	r0, r0, r6			@ ..VI Z..S .... .C.M (mmu)
+						@ ...I Z..S .... .... (uc)
 #if L2_CACHE_ENABLE
 	orr 	r0, r0, #0x04000000		@ L2 enable
 #endif
@@ -439,7 +438,7 @@
 
 	.type	xsc3_crval, #object
 xsc3_crval:
-	crval	clear=0x04003b02, mmuset=0x00003105, ucset=0x00001100
+	crval	clear=0x04002202, mmuset=0x00003905, ucset=0x00001900
 
 	__INITDATA
 
@@ -474,7 +473,7 @@
 
 	.type	cpu_xsc3_name, #object
 cpu_xsc3_name:
-	.asciz	"XScale-Core3"
+	.asciz	"XScale-V3 based processor"
 	.size	cpu_xsc3_name, . - cpu_xsc3_name
 
 	.align
@@ -490,7 +489,7 @@
 		PMD_SECT_CACHEABLE | \
 		PMD_SECT_AP_WRITE | \
 		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
+	.long	PMD_TYPE_SECT | \
 		PMD_SECT_AP_WRITE | \
 		PMD_SECT_AP_READ
 	b	__xsc3_setup
diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S
index fd6adde..20f84bb 100644
--- a/arch/arm/mm/tlb-v6.S
+++ b/arch/arm/mm/tlb-v6.S
@@ -53,6 +53,8 @@
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
+	mcr	p15, 0, ip, c7, c5, 6		@ flush BTAC/BTB
+	mcr	p15, 0, ip, c7, c10, 4		@ data synchronization barrier
 	mov	pc, lr
 
 /*
@@ -80,7 +82,9 @@
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
+	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
 	mcr	p15, 0, r2, c7, c10, 4		@ data synchronization barrier
+	mcr	p15, 0, r2, c7, c5, 4		@ prefetch flush
 	mov	pc, lr
 
 	.section ".text.init", #alloc, #execinstr
diff --git a/arch/arm/oprofile/Kconfig b/arch/arm/oprofile/Kconfig
index 19d3773..afd93ad 100644
--- a/arch/arm/oprofile/Kconfig
+++ b/arch/arm/oprofile/Kconfig
@@ -19,5 +19,24 @@
 
 	  If unsure, say N.
 
+if OPROFILE
+
+config OPROFILE_ARMV6
+	bool
+	depends on CPU_V6 && !SMP
+	default y
+	select OPROFILE_ARM11_CORE
+
+config OPROFILE_MPCORE
+	bool
+	depends on CPU_V6 && SMP
+	default y
+	select OPROFILE_ARM11_CORE
+
+config OPROFILE_ARM11_CORE
+	bool
+
+endif
+
 endmenu
 
diff --git a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile
index 6a94e54..e61d0cc 100644
--- a/arch/arm/oprofile/Makefile
+++ b/arch/arm/oprofile/Makefile
@@ -8,4 +8,6 @@
 
 oprofile-y				:= $(DRIVER_OBJS) common.o backtrace.o
 oprofile-$(CONFIG_CPU_XSCALE)		+= op_model_xscale.o
-
+oprofile-$(CONFIG_OPROFILE_ARM11_CORE)	+= op_model_arm11_core.o
+oprofile-$(CONFIG_OPROFILE_ARMV6)	+= op_model_v6.o
+oprofile-$(CONFIG_OPROFILE_MPCORE)	+= op_model_mpcore.o
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
index 6f83335..0a007b9 100644
--- a/arch/arm/oprofile/common.c
+++ b/arch/arm/oprofile/common.c
@@ -135,6 +135,14 @@
 	spec = &op_xscale_spec;
 #endif
 
+#ifdef CONFIG_OPROFILE_ARMV6
+	spec = &op_armv6_spec;
+#endif
+
+#ifdef CONFIG_OPROFILE_MPCORE
+	spec = &op_mpcore_spec;
+#endif
+
 	if (spec) {
 		ret = spec->init();
 		if (ret < 0)
diff --git a/arch/arm/oprofile/op_arm_model.h b/arch/arm/oprofile/op_arm_model.h
index 38c6ad1..4899c62 100644
--- a/arch/arm/oprofile/op_arm_model.h
+++ b/arch/arm/oprofile/op_arm_model.h
@@ -24,6 +24,9 @@
 extern struct op_arm_model_spec op_xscale_spec;
 #endif
 
+extern struct op_arm_model_spec op_armv6_spec;
+extern struct op_arm_model_spec op_mpcore_spec;
+
 extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth);
 
 extern int __init op_arm_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec);
diff --git a/arch/arm/oprofile/op_model_arm11_core.c b/arch/arm/oprofile/op_model_arm11_core.c
new file mode 100644
index 0000000..ad80752
--- /dev/null
+++ b/arch/arm/oprofile/op_model_arm11_core.c
@@ -0,0 +1,162 @@
+/**
+ * @file op_model_arm11_core.c
+ * ARM11 Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+
+#include "op_counter.h"
+#include "op_arm_model.h"
+#include "op_model_arm11_core.h"
+
+/*
+ * ARM11 PMU support
+ */
+static inline void arm11_write_pmnc(u32 val)
+{
+	/* upper 4bits and 7, 11 are write-as-0 */
+	val &= 0x0ffff77f;
+	asm volatile("mcr p15, 0, %0, c15, c12, 0" : : "r" (val));
+}
+
+static inline u32 arm11_read_pmnc(void)
+{
+	u32 val;
+	asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r" (val));
+	return val;
+}
+
+static void arm11_reset_counter(unsigned int cnt)
+{
+	u32 val = -(u32)counter_config[CPU_COUNTER(smp_processor_id(), cnt)].count;
+	switch (cnt) {
+	case CCNT:
+		asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r" (val));
+		break;
+
+	case PMN0:
+		asm volatile("mcr p15, 0, %0, c15, c12, 2" : : "r" (val));
+		break;
+
+	case PMN1:
+		asm volatile("mcr p15, 0, %0, c15, c12, 3" : : "r" (val));
+		break;
+	}
+}
+
+int arm11_setup_pmu(void)
+{
+	unsigned int cnt;
+	u32 pmnc;
+
+	if (arm11_read_pmnc() & PMCR_E) {
+		printk(KERN_ERR "oprofile: CPU%u PMU still enabled when setup new event counter.\n", smp_processor_id());
+		return -EBUSY;
+	}
+
+	/* initialize PMNC, reset overflow, D bit, C bit and P bit. */
+	arm11_write_pmnc(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT |
+			 PMCR_C | PMCR_P);
+
+	for (pmnc = 0, cnt = PMN0; cnt <= CCNT; cnt++) {
+		unsigned long event;
+
+		if (!counter_config[CPU_COUNTER(smp_processor_id(), cnt)].enabled)
+			continue;
+
+		event = counter_config[CPU_COUNTER(smp_processor_id(), cnt)].event & 255;
+
+		/*
+		 * Set event (if destined for PMNx counters)
+		 */
+		if (cnt == PMN0) {
+			pmnc |= event << 20;
+		} else if (cnt == PMN1) {
+			pmnc |= event << 12;
+		}
+
+		/*
+		 * We don't need to set the event if it's a cycle count
+		 * Enable interrupt for this counter
+		 */
+		pmnc |= PMCR_IEN_PMN0 << cnt;
+		arm11_reset_counter(cnt);
+	}
+	arm11_write_pmnc(pmnc);
+
+	return 0;
+}
+
+int arm11_start_pmu(void)
+{
+	arm11_write_pmnc(arm11_read_pmnc() | PMCR_E);
+	return 0;
+}
+
+int arm11_stop_pmu(void)
+{
+	unsigned int cnt;
+
+	arm11_write_pmnc(arm11_read_pmnc() & ~PMCR_E);
+
+	for (cnt = PMN0; cnt <= CCNT; cnt++)
+		arm11_reset_counter(cnt);
+
+	return 0;
+}
+
+/*
+ * CPU counters' IRQ handler (one IRQ per CPU)
+ */
+static irqreturn_t arm11_pmu_interrupt(int irq, void *arg)
+{
+	struct pt_regs *regs = get_irq_regs();
+	unsigned int cnt;
+	u32 pmnc;
+
+	pmnc = arm11_read_pmnc();
+
+	for (cnt = PMN0; cnt <= CCNT; cnt++) {
+		if ((pmnc & (PMCR_OFL_PMN0 << cnt)) && (pmnc & (PMCR_IEN_PMN0 << cnt))) {
+			arm11_reset_counter(cnt);
+			oprofile_add_sample(regs, CPU_COUNTER(smp_processor_id(), cnt));
+		}
+	}
+	/* Clear counter flag(s) */
+	arm11_write_pmnc(pmnc);
+	return IRQ_HANDLED;
+}
+
+int arm11_request_interrupts(int *irqs, int nr)
+{
+	unsigned int i;
+	int ret = 0;
+
+	for(i = 0; i < nr; i++) {
+		ret = request_irq(irqs[i], arm11_pmu_interrupt, IRQF_DISABLED, "CP15 PMU", NULL);
+		if (ret != 0) {
+			printk(KERN_ERR "oprofile: unable to request IRQ%u for MPCORE-EM\n",
+			       irqs[i]);
+			break;
+		}
+	}
+
+	if (i != nr)
+		while (i-- != 0)
+			free_irq(irqs[i], NULL);
+
+	return ret;
+}
+
+void arm11_release_interrupts(int *irqs, int nr)
+{
+	unsigned int i;
+
+	for (i = 0; i < nr; i++)
+		free_irq(irqs[i], NULL);
+}
diff --git a/arch/arm/oprofile/op_model_arm11_core.h b/arch/arm/oprofile/op_model_arm11_core.h
new file mode 100644
index 0000000..6f8538e
--- /dev/null
+++ b/arch/arm/oprofile/op_model_arm11_core.h
@@ -0,0 +1,45 @@
+/**
+ * @file op_model_arm11_core.h
+ * ARM11 Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 Oprofile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Zwane Mwaikambo
+ */
+#ifndef OP_MODEL_ARM11_CORE_H
+#define OP_MODEL_ARM11_CORE_H
+
+/*
+ * Per-CPU PMCR
+ */
+#define PMCR_E		(1 << 0)	/* Enable */
+#define PMCR_P		(1 << 1)	/* Count reset */
+#define PMCR_C		(1 << 2)	/* Cycle counter reset */
+#define PMCR_D		(1 << 3)	/* Cycle counter counts every 64th cpu cycle */
+#define PMCR_IEN_PMN0	(1 << 4)	/* Interrupt enable count reg 0 */
+#define PMCR_IEN_PMN1	(1 << 5)	/* Interrupt enable count reg 1 */
+#define PMCR_IEN_CCNT	(1 << 6)	/* Interrupt enable cycle counter */
+#define PMCR_OFL_PMN0	(1 << 8)	/* Count reg 0 overflow */
+#define PMCR_OFL_PMN1	(1 << 9)	/* Count reg 1 overflow */
+#define PMCR_OFL_CCNT	(1 << 10)	/* Cycle counter overflow */
+
+#define PMN0 0
+#define PMN1 1
+#define CCNT 2
+
+#define CPU_COUNTER(cpu, counter)	((cpu) * 3 + (counter))
+
+int arm11_setup_pmu(void);
+int arm11_start_pmu(void);
+int arm11_stop_pmu(void);
+int arm11_request_interrupts(int *, int);
+void arm11_release_interrupts(int *, int);
+
+#endif
diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c
new file mode 100644
index 0000000..8985007
--- /dev/null
+++ b/arch/arm/oprofile/op_model_mpcore.c
@@ -0,0 +1,296 @@
+/**
+ * @file op_model_mpcore.c
+ * MPCORE Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 Oprofile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Zwane Mwaikambo
+ *
+ *  Counters:
+ *    0: PMN0 on CPU0, per-cpu configurable event counter
+ *    1: PMN1 on CPU0, per-cpu configurable event counter
+ *    2: CCNT on CPU0
+ *    3: PMN0 on CPU1
+ *    4: PMN1 on CPU1
+ *    5: CCNT on CPU1
+ *    6: PMN0 on CPU1
+ *    7: PMN1 on CPU1
+ *    8: CCNT on CPU1
+ *    9: PMN0 on CPU1
+ *   10: PMN1 on CPU1
+ *   11: CCNT on CPU1
+ *   12-19: configurable SCU event counters
+ */
+
+/* #define DEBUG */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/hardware.h>
+#include <asm/system.h>
+
+#include "op_counter.h"
+#include "op_arm_model.h"
+#include "op_model_arm11_core.h"
+#include "op_model_mpcore.h"
+
+/*
+ * MPCore SCU event monitor support
+ */
+#define SCU_EVENTMONITORS_VA_BASE __io_address(REALVIEW_MPCORE_SCU_BASE + 0x10)
+
+/*
+ * Bitmask of used SCU counters
+ */
+static unsigned int scu_em_used;
+
+/*
+ * 2 helper fns take a counter number from 0-7 (not the userspace-visible counter number)
+ */
+static inline void scu_reset_counter(struct eventmonitor __iomem *emc, unsigned int n)
+{
+	writel(-(u32)counter_config[SCU_COUNTER(n)].count, &emc->MC[n]);
+}
+
+static inline void scu_set_event(struct eventmonitor __iomem *emc, unsigned int n, u32 event)
+{
+	event &= 0xff;
+	writeb(event, &emc->MCEB[n]);
+}
+
+/*
+ * SCU counters' IRQ handler (one IRQ per counter => 2 IRQs per CPU)
+ */
+static irqreturn_t scu_em_interrupt(int irq, void *arg)
+{
+	struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+	unsigned int cnt;
+
+	cnt = irq - IRQ_PMU_SCU0;
+	oprofile_add_sample(get_irq_regs(), SCU_COUNTER(cnt));
+	scu_reset_counter(emc, cnt);
+
+	/* Clear overflow flag for this counter */
+	writel(1 << (cnt + 16), &emc->PMCR);
+
+	return IRQ_HANDLED;
+}
+
+/* Configure just the SCU counters that the user has requested */
+static void scu_setup(void)
+{
+	struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+	unsigned int i;
+
+	scu_em_used = 0;
+
+	for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+		if (counter_config[SCU_COUNTER(i)].enabled &&
+		    counter_config[SCU_COUNTER(i)].event) {
+			scu_set_event(emc, i, 0); /* disable counter for now */
+			scu_em_used |= 1 << i;
+		}
+	}
+}
+
+static int scu_start(void)
+{
+	struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+	unsigned int temp, i;
+	unsigned long event;
+	int ret = 0;
+
+	/*
+	 * request the SCU counter interrupts that we need
+	 */
+	for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+		if (scu_em_used & (1 << i)) {
+			ret = request_irq(IRQ_PMU_SCU0 + i, scu_em_interrupt, IRQF_DISABLED, "SCU PMU", NULL);
+			if (ret) {
+				printk(KERN_ERR "oprofile: unable to request IRQ%u for SCU Event Monitor\n",
+				       IRQ_PMU_SCU0 + i);
+				goto err_free_scu;
+			}
+		}
+	}
+
+	/*
+	 * clear overflow and enable interrupt for all used counters
+	 */
+	temp = readl(&emc->PMCR);
+	for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+		if (scu_em_used & (1 << i)) {
+			scu_reset_counter(emc, i);
+			event = counter_config[SCU_COUNTER(i)].event;
+			scu_set_event(emc, i, event);
+
+			/* clear overflow/interrupt */
+			temp |= 1 << (i + 16);
+			/* enable interrupt*/
+			temp |= 1 << (i + 8);
+		}
+	}
+
+	/* Enable all 8 counters */
+	temp |= PMCR_E;
+	writel(temp, &emc->PMCR);
+
+	return 0;
+
+ err_free_scu:
+	while (i--)
+		free_irq(IRQ_PMU_SCU0 + i, NULL);
+	return ret;
+}
+
+static void scu_stop(void)
+{
+	struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+	unsigned int temp, i;
+
+	/* Disable counter interrupts */
+	/* Don't disable all 8 counters (with the E bit) as they may be in use */
+	temp = readl(&emc->PMCR);
+	for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+		if (scu_em_used & (1 << i))
+			temp &= ~(1 << (i + 8));
+	}
+	writel(temp, &emc->PMCR);
+
+	/* Free counter interrupts and reset counters */
+	for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+		if (scu_em_used & (1 << i)) {
+			scu_reset_counter(emc, i);
+			free_irq(IRQ_PMU_SCU0 + i, NULL);
+		}
+	}
+}
+
+struct em_function_data {
+	int (*fn)(void);
+	int ret;
+};
+
+static void em_func(void *data)
+{
+	struct em_function_data *d = data;
+	int ret = d->fn();
+	if (ret)
+		d->ret = ret;
+}
+
+static int em_call_function(int (*fn)(void))
+{
+	struct em_function_data data;
+
+	data.fn = fn;
+	data.ret = 0;
+
+	smp_call_function(em_func, &data, 1, 1);
+	em_func(&data);
+
+	return data.ret;
+}
+
+/*
+ * Glue to stick the individual ARM11 PMUs and the SCU
+ * into the oprofile framework.
+ */
+static int em_setup_ctrs(void)
+{
+	int ret;
+
+	/* Configure CPU counters by cross-calling to the other CPUs */
+	ret = em_call_function(arm11_setup_pmu);
+	if (ret == 0)
+		scu_setup();
+
+	return 0;
+}
+
+static int arm11_irqs[] = {
+	[0]	= IRQ_PMU_CPU0,
+	[1]	= IRQ_PMU_CPU1,
+	[2]	= IRQ_PMU_CPU2,
+	[3]	= IRQ_PMU_CPU3
+};
+
+static int em_start(void)
+{
+	int ret;
+
+	ret = arm11_request_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs));
+	if (ret == 0) {
+		em_call_function(arm11_start_pmu);
+
+		ret = scu_start();
+		if (ret)
+			arm11_release_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs));
+	}
+	return ret;
+}
+
+static void em_stop(void)
+{
+	em_call_function(arm11_stop_pmu);
+	arm11_release_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs));
+	scu_stop();
+}
+
+/*
+ * Why isn't there a function to route an IRQ to a specific CPU in
+ * genirq?
+ */
+static void em_route_irq(int irq, unsigned int cpu)
+{
+	irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+	irq_desc[irq].chip->set_affinity(irq, cpumask_of_cpu(cpu));
+}
+
+static int em_setup(void)
+{
+	/*
+	 * Send SCU PMU interrupts to the "owner" CPU.
+	 */
+	em_route_irq(IRQ_PMU_SCU0, 0);
+	em_route_irq(IRQ_PMU_SCU1, 0);
+	em_route_irq(IRQ_PMU_SCU2, 1);
+	em_route_irq(IRQ_PMU_SCU3, 1);
+	em_route_irq(IRQ_PMU_SCU4, 2);
+	em_route_irq(IRQ_PMU_SCU5, 2);
+	em_route_irq(IRQ_PMU_SCU6, 3);
+	em_route_irq(IRQ_PMU_SCU7, 3);
+
+	/*
+	 * Send CP15 PMU interrupts to the owner CPU.
+	 */
+	em_route_irq(IRQ_PMU_CPU0, 0);
+	em_route_irq(IRQ_PMU_CPU1, 1);
+	em_route_irq(IRQ_PMU_CPU2, 2);
+	em_route_irq(IRQ_PMU_CPU3, 3);
+
+	return 0;
+}
+
+struct op_arm_model_spec op_mpcore_spec = {
+	.init		= em_setup,
+	.num_counters	= MPCORE_NUM_COUNTERS,
+	.setup_ctrs	= em_setup_ctrs,
+	.start		= em_start,
+	.stop		= em_stop,
+	.name		= "arm/mpcore",
+};
diff --git a/arch/arm/oprofile/op_model_mpcore.h b/arch/arm/oprofile/op_model_mpcore.h
new file mode 100644
index 0000000..73d8110
--- /dev/null
+++ b/arch/arm/oprofile/op_model_mpcore.h
@@ -0,0 +1,61 @@
+/**
+ * @file op_model_mpcore.c
+ * MPCORE Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 Oprofile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Zwane Mwaikambo
+ */
+#ifndef OP_MODEL_MPCORE_H
+#define OP_MODEL_MPCORE_H
+
+struct eventmonitor {
+	unsigned long PMCR;
+	unsigned char MCEB[8];
+	unsigned long MC[8];
+};
+
+/*
+ * List of userspace counter numbers: note that the structure is important.
+ * The code relies on CPUn's counters being CPU0's counters + 3n
+ * and on CPU0's counters starting at 0
+ */
+
+#define COUNTER_CPU0_PMN0 0
+#define COUNTER_CPU0_PMN1 1
+#define COUNTER_CPU0_CCNT 2
+
+#define COUNTER_CPU1_PMN0 3
+#define COUNTER_CPU1_PMN1 4
+#define COUNTER_CPU1_CCNT 5
+
+#define COUNTER_CPU2_PMN0 6
+#define COUNTER_CPU2_PMN1 7
+#define COUNTER_CPU2_CCNT 8
+
+#define COUNTER_CPU3_PMN0 9
+#define COUNTER_CPU3_PMN1 10
+#define COUNTER_CPU3_CCNT 11
+
+#define COUNTER_SCU_MN0 12
+#define COUNTER_SCU_MN1 13
+#define COUNTER_SCU_MN2 14
+#define COUNTER_SCU_MN3 15
+#define COUNTER_SCU_MN4 16
+#define COUNTER_SCU_MN5 17
+#define COUNTER_SCU_MN6 18
+#define COUNTER_SCU_MN7 19
+#define NUM_SCU_COUNTERS 8
+
+#define SCU_COUNTER(number)	((number) + COUNTER_SCU_MN0)
+
+#define MPCORE_NUM_COUNTERS	SCU_COUNTER(NUM_SCU_COUNTERS)
+
+#endif
diff --git a/arch/arm/oprofile/op_model_v6.c b/arch/arm/oprofile/op_model_v6.c
new file mode 100644
index 0000000..fe58138
--- /dev/null
+++ b/arch/arm/oprofile/op_model_v6.c
@@ -0,0 +1,67 @@
+/**
+ * @file op_model_v6.c
+ * ARM11 Performance Monitor Driver
+ *
+ * Based on op_model_xscale.c
+ *
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 OProfile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Tony Lindgren <tony@atomide.com>
+ */
+
+/* #define DEBUG */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "op_counter.h"
+#include "op_arm_model.h"
+#include "op_model_arm11_core.h"
+
+static int irqs[] = {
+#ifdef CONFIG_ARCH_OMAP2
+	3,
+#endif
+};
+
+static void armv6_pmu_stop(void)
+{
+	arm11_stop_pmu();
+	arm11_release_interrupts(irqs, ARRAY_SIZE(irqs));
+}
+
+static int armv6_pmu_start(void)
+{
+	int ret;
+
+	ret = arm11_request_interrupts(irqs, ARRAY_SIZE(irqs));
+	if (ret >= 0)
+		ret = arm11_start_pmu();
+
+	return ret;
+}
+
+static int armv6_detect_pmu(void)
+{
+	return 0;
+}
+
+struct op_arm_model_spec op_armv6_spec = {
+	.init		= armv6_detect_pmu,
+	.num_counters	= 3,
+	.setup_ctrs	= arm11_setup_pmu,
+	.start		= armv6_pmu_start,
+	.stop		= armv6_pmu_stop,
+	.name		= "arm/armv6",
+};
diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile
index 23da00b..4d2b1da 100644
--- a/arch/arm/plat-iop/Makefile
+++ b/arch/arm/plat-iop/Makefile
@@ -2,7 +2,30 @@
 # Makefile for the linux kernel.
 #
 
-obj-y			:= gpio.o i2c.o pci.o setup.o time.o
-obj-m			:=
-obj-n			:=
-obj-			:=
+obj-y :=
+
+# IOP32X
+obj-$(CONFIG_ARCH_IOP32X) += gpio.o
+obj-$(CONFIG_ARCH_IOP32X) += i2c.o
+obj-$(CONFIG_ARCH_IOP32X) += pci.o
+obj-$(CONFIG_ARCH_IOP32X) += setup.o
+obj-$(CONFIG_ARCH_IOP32X) += time.o
+obj-$(CONFIG_ARCH_IOP32X) += io.o
+obj-$(CONFIG_ARCH_IOP32X) += cp6.o
+
+# IOP33X
+obj-$(CONFIG_ARCH_IOP33X) += gpio.o
+obj-$(CONFIG_ARCH_IOP33X) += i2c.o
+obj-$(CONFIG_ARCH_IOP33X) += pci.o
+obj-$(CONFIG_ARCH_IOP33X) += setup.o
+obj-$(CONFIG_ARCH_IOP33X) += time.o
+obj-$(CONFIG_ARCH_IOP33X) += io.o
+obj-$(CONFIG_ARCH_IOP33X) += cp6.o
+
+# IOP13XX
+obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
+obj-$(CONFIG_ARCH_IOP13XX) += time.o
+
+obj-m                  :=
+obj-n                  :=
+obj-                   :=
diff --git a/arch/arm/plat-iop/cp6.c b/arch/arm/plat-iop/cp6.c
new file mode 100644
index 0000000..9612a87
--- /dev/null
+++ b/arch/arm/plat-iop/cp6.c
@@ -0,0 +1,50 @@
+/*
+ * IOP Coprocessor-6 access handler
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions 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/init.h>
+#include <asm/traps.h>
+
+static int cp6_trap(struct pt_regs *regs, unsigned int instr)
+{
+	u32 temp;
+
+        /* enable cp6 access */
+        asm volatile (
+		"mrc	p15, 0, %0, c15, c1, 0\n\t"
+		"orr	%0, %0, #(1 << 6)\n\t"
+		"mcr	p15, 0, %0, c15, c1, 0\n\t"
+		: "=r"(temp));
+
+	return 0;
+}
+
+/* permit kernel space cp6 access
+ * deny user space cp6 access
+ */
+static struct undef_hook cp6_hook = {
+	.instr_mask     = 0x0f000ff0,
+	.instr_val      = 0x0e000610,
+	.cpsr_mask      = MODE_MASK,
+	.cpsr_val       = SVC_MODE,
+	.fn             = cp6_trap,
+};
+
+void __init iop_init_cp6_handler(void)
+{
+	register_undef_hook(&cp6_hook);
+}
diff --git a/arch/arm/plat-iop/io.c b/arch/arm/plat-iop/io.c
new file mode 100644
index 0000000..f7eccec
--- /dev/null
+++ b/arch/arm/plat-iop/io.c
@@ -0,0 +1,58 @@
+/*
+ * iop3xx custom ioremap implementation
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions 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 <asm/hardware.h>
+#include <asm/io.h>
+
+void * __iomem __iop3xx_ioremap(unsigned long cookie, size_t size,
+	unsigned long flags)
+{
+	void __iomem * retval;
+
+	switch (cookie) {
+	case IOP3XX_PCI_LOWER_IO_PA ... IOP3XX_PCI_UPPER_IO_PA:
+		retval = (void *) IOP3XX_PCI_IO_PHYS_TO_VIRT(cookie);
+		break;
+	case IOP3XX_PERIPHERAL_PHYS_BASE ... IOP3XX_PERIPHERAL_UPPER_PA:
+		retval = (void *) IOP3XX_PMMR_PHYS_TO_VIRT(cookie);
+		break;
+	default:
+		retval = __ioremap(cookie, size, flags);
+	}
+
+	return retval;
+}
+EXPORT_SYMBOL(__iop3xx_ioremap);
+
+void __iop3xx_iounmap(void __iomem *addr)
+{
+	extern void __iounmap(volatile void __iomem *addr);
+
+	switch ((u32) addr) {
+	case IOP3XX_PCI_LOWER_IO_VA ... IOP3XX_PCI_UPPER_IO_VA:
+	case IOP3XX_PERIPHERAL_VIRT_BASE ... IOP3XX_PERIPHERAL_UPPER_VA:
+		goto skip;
+	}
+	__iounmap(addr);
+
+skip:
+	return;
+}
+EXPORT_SYMBOL(__iop3xx_iounmap);
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
index e647812..b5f6ec3 100644
--- a/arch/arm/plat-iop/pci.c
+++ b/arch/arm/plat-iop/pci.c
@@ -196,8 +196,8 @@
 	if (!res)
 		panic("PCI: unable to alloc resources");
 
-	res[0].start = IOP3XX_PCI_LOWER_IO_VA;
-	res[0].end   = IOP3XX_PCI_LOWER_IO_VA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
+	res[0].start = IOP3XX_PCI_LOWER_IO_PA;
+	res[0].end   = IOP3XX_PCI_LOWER_IO_PA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
 	res[0].name  = "IOP3XX PCI I/O Space";
 	res[0].flags = IORESOURCE_IO;
 	request_resource(&ioport_resource, &res[0]);
@@ -209,7 +209,7 @@
 	request_resource(&iomem_resource, &res[1]);
 
 	sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - IOP3XX_PCI_LOWER_MEM_BA;
-	sys->io_offset  = IOP3XX_PCI_LOWER_IO_VA - IOP3XX_PCI_LOWER_IO_BA;
+	sys->io_offset  = IOP3XX_PCI_LOWER_IO_PA - IOP3XX_PCI_LOWER_IO_BA;
 
 	sys->resource[0] = &res[0];
 	sys->resource[1] = &res[1];
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c
index f530abd..16300ad 100644
--- a/arch/arm/plat-iop/time.c
+++ b/arch/arm/plat-iop/time.c
@@ -24,39 +24,45 @@
 #include <asm/uaccess.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
-
-#ifdef CONFIG_ARCH_IOP32X
-#define IRQ_IOP3XX_TIMER0	IRQ_IOP32X_TIMER0
-#else
-#ifdef CONFIG_ARCH_IOP33X
-#define IRQ_IOP3XX_TIMER0	IRQ_IOP33X_TIMER0
-#endif
-#endif
+#include <asm/arch/time.h>
 
 static unsigned long ticks_per_jiffy;
 static unsigned long ticks_per_usec;
 static unsigned long next_jiffy_time;
 
-unsigned long iop3xx_gettimeoffset(void)
+unsigned long iop_gettimeoffset(void)
 {
-	unsigned long offset;
+	unsigned long offset, temp1, temp2;
 
-	offset = next_jiffy_time - *IOP3XX_TU_TCR1;
+	/* enable cp6, if necessary, to avoid taking the overhead of an
+	 * undefined instruction trap
+	 */
+	asm volatile (
+	"mrc	p15, 0, %0, c15, c1, 0\n\t"
+	"ands	%1, %0, #(1 << 6)\n\t"
+	"orreq	%0, %0, #(1 << 6)\n\t"
+	"mcreq	p15, 0, %0, c15, c1, 0\n\t"
+#ifdef CONFIG_XSCALE
+	"mrceq	p15, 0, %0, c15, c1, 0\n\t"
+	"moveq	%0, %0\n\t"
+	"subeq	pc, pc, #4\n\t"
+#endif
+	: "=r"(temp1), "=r"(temp2) : : "cc");
+
+	offset = next_jiffy_time - read_tcr1();
 
 	return offset / ticks_per_usec;
 }
 
 static irqreturn_t
-iop3xx_timer_interrupt(int irq, void *dev_id)
+iop_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
-	iop3xx_cp6_enable();
-	asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (1));
-	iop3xx_cp6_disable();
+	write_tisr(1);
 
-	while ((signed long)(next_jiffy_time - *IOP3XX_TU_TCR1)
-							>= ticks_per_jiffy) {
+	while ((signed long)(next_jiffy_time - read_tcr1())
+		>= ticks_per_jiffy) {
 		timer_tick();
 		next_jiffy_time -= ticks_per_jiffy;
 	}
@@ -66,13 +72,13 @@
 	return IRQ_HANDLED;
 }
 
-static struct irqaction iop3xx_timer_irq = {
-	.name		= "IOP3XX Timer Tick",
-	.handler	= iop3xx_timer_interrupt,
+static struct irqaction iop_timer_irq = {
+	.name		= "IOP Timer Tick",
+	.handler	= iop_timer_interrupt,
 	.flags		= IRQF_DISABLED | IRQF_TIMER,
 };
 
-void __init iop3xx_init_time(unsigned long tick_rate)
+void __init iop_init_time(unsigned long tick_rate)
 {
 	u32 timer_ctl;
 
@@ -80,19 +86,17 @@
 	ticks_per_usec = tick_rate / 1000000;
 	next_jiffy_time = 0xffffffff;
 
-	timer_ctl = IOP3XX_TMR_EN | IOP3XX_TMR_PRIVILEGED |
-			IOP3XX_TMR_RELOAD | IOP3XX_TMR_RATIO_1_1;
+	timer_ctl = IOP_TMR_EN | IOP_TMR_PRIVILEGED |
+			IOP_TMR_RELOAD | IOP_TMR_RATIO_1_1;
 
 	/*
 	 * We use timer 0 for our timer interrupt, and timer 1 as
 	 * monotonic counter for tracking missed jiffies.
 	 */
-	iop3xx_cp6_enable();
-	asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (ticks_per_jiffy - 1));
-	asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
-	asm volatile("mcr p6, 0, %0, c5, c1, 0" : : "r" (0xffffffff));
-	asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl));
-	iop3xx_cp6_disable();
+	write_trr0(ticks_per_jiffy - 1);
+	write_tmr0(timer_ctl);
+	write_trr1(0xffffffff);
+	write_tmr1(timer_ctl);
 
-	setup_irq(IRQ_IOP3XX_TIMER0, &iop3xx_timer_irq);
+	setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq);
 }
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
new file mode 100644
index 0000000..8608695
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -0,0 +1,100 @@
+# arch/arm/plat-s3c24xx/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config PLAT_S3C24XX
+	bool
+	depends on ARCH_S3C2410
+	default y if ARCH_S3C2410
+	select NO_IOPORT
+	help
+	  Base platform code for any Samsung S3C device
+
+if PLAT_S3C24XX
+
+config CPU_S3C244X
+	bool
+	depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
+	help
+	  Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
+
+config PM_SIMTEC
+	bool
+	help
+	  Common power management code for systems that are
+	  compatible with the Simtec style of power management
+
+config S3C2410_BOOT_WATCHDOG
+	bool "S3C2410 Initialisation watchdog"
+	depends on ARCH_S3C2410 && S3C2410_WATCHDOG
+	help
+	  Say y to enable the watchdog during the kernel decompression
+	  stage. If the kernel fails to uncompress, then the watchdog
+	  will trigger a reset and the system should restart.
+
+config S3C2410_BOOT_ERROR_RESET
+	bool "S3C2410 Reboot on decompression error"
+	depends on ARCH_S3C2410
+	help
+	  Say y here to use the watchdog to reset the system if the
+	  kernel decompressor detects an error during decompression.
+
+config S3C2410_PM_DEBUG
+	bool "S3C2410 PM Suspend debug"
+	depends on ARCH_S3C2410 && PM
+	help
+	  Say Y here if you want verbose debugging from the PM Suspend and
+	  Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
+	  for more information.
+
+config S3C2410_PM_CHECK
+	bool "S3C2410 PM Suspend Memory CRC"
+	depends on ARCH_S3C2410 && PM && CRC32
+	help
+ 	  Enable the PM code's memory area checksum over sleep. This option
+	  will generate CRCs of all blocks of memory, and store them before
+	  going to sleep. The blocks are then checked on resume for any
+	  errors.
+
+config S3C2410_PM_CHECK_CHUNKSIZE
+	int "S3C2410 PM Suspend CRC Chunksize (KiB)"
+	depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
+	default 64
+	help
+	  Set the chunksize in Kilobytes of the CRC for checking memory
+	  corruption over suspend and resume. A smaller value will mean that
+	  the CRC data block will take more memory, but wil identify any
+	  faults with better precision.
+
+config S3C2410_LOWLEVEL_UART_PORT
+	int "S3C2410 UART to use for low-level messages"
+	default 0
+	help
+	  Choice of which UART port to use for the low-level messages,
+	  such as the `Uncompressing...` at start time. The value of
+	  this configuration should be between zero and two. The port
+	  must have been initialised by the boot-loader before use.
+
+config S3C2410_DMA
+	bool "S3C2410 DMA support"
+	depends on ARCH_S3C2410
+	help
+	  S3C2410 DMA support. This is needed for drivers like sound which
+	  use the S3C2410's DMA system to move data to and from the
+	  peripheral blocks.
+
+config S3C2410_DMA_DEBUG
+	bool "S3C2410 DMA support debug"
+	depends on ARCH_S3C2410 && S3C2410_DMA
+	help
+	  Enable debugging output for the DMA code. This option sends info
+	  to the kernel log, at priority KERN_DEBUG.
+
+config MACH_SMDK
+	bool
+	help
+	  Common machine code for SMDK2410 and SMDK2440
+
+endif
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
new file mode 100644
index 0000000..8e5ccaa
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -0,0 +1,30 @@
+# arch/arm/plat-s3c24xx/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+
+# Core files
+
+obj-y				+= cpu.o
+obj-y				+= irq.o
+obj-y				+= devs.o
+obj-y				+= gpio.o
+obj-y				+= time.o
+obj-y				+= clock.o
+
+# Architecture dependant builds
+
+obj-$(CONFIG_CPU_S3C244X)	+= s3c244x.o
+obj-$(CONFIG_CPU_S3C244X)	+= s3c244x-irq.o
+obj-$(CONFIG_PM_SIMTEC)		+= pm-simtec.o
+obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_PM)		+= sleep.o
+obj-$(CONFIG_S3C2410_DMA)	+= dma.o
+obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c
new file mode 100644
index 0000000..d3dc03a
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/clock.c
@@ -0,0 +1,449 @@
+/* linux/arch/arm/plat-s3c24xx/clock.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX Core clock control support
+ *
+ * Based on, and code from linux/arch/arm/mach-versatile/clock.c
+ **
+ **  Copyright (C) 2004 ARM Limited.
+ **  Written by Deep Blue Solutions Limited.
+ *
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* clock information */
+
+static LIST_HEAD(clocks);
+
+DEFINE_MUTEX(clocks_mutex);
+
+/* enable and disable calls for use with the clk struct */
+
+static int clk_null_enable(struct clk *clk, int enable)
+{
+	return 0;
+}
+
+/* Clock API calls */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p;
+	struct clk *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, list) {
+		if (p->id == idno &&
+		    strcmp(id, p->name) == 0 &&
+		    try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+
+	/* check for the case where a device was supplied, but the
+	 * clock that was being searched for is not device specific */
+
+	if (IS_ERR(clk)) {
+		list_for_each_entry(p, &clocks, list) {
+			if (p->id == -1 && strcmp(id, p->name) == 0 &&
+			    try_module_get(p->owner)) {
+				clk = p;
+				break;
+			}
+		}
+	}
+
+	mutex_unlock(&clocks_mutex);
+	return clk;
+}
+
+void clk_put(struct clk *clk)
+{
+	module_put(clk->owner);
+}
+
+int clk_enable(struct clk *clk)
+{
+	if (IS_ERR(clk) || clk == NULL)
+		return -EINVAL;
+
+	clk_enable(clk->parent);
+
+	mutex_lock(&clocks_mutex);
+
+	if ((clk->usage++) == 0)
+		(clk->enable)(clk, 1);
+
+	mutex_unlock(&clocks_mutex);
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+	if (IS_ERR(clk) || clk == NULL)
+		return;
+
+	mutex_lock(&clocks_mutex);
+
+	if ((--clk->usage) == 0)
+		(clk->enable)(clk, 0);
+
+	mutex_unlock(&clocks_mutex);
+	clk_disable(clk->parent);
+}
+
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (IS_ERR(clk))
+		return 0;
+
+	if (clk->rate != 0)
+		return clk->rate;
+
+	if (clk->get_rate != NULL)
+		return (clk->get_rate)(clk);
+
+	if (clk->parent != NULL)
+		return clk_get_rate(clk->parent);
+
+	return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (!IS_ERR(clk) && clk->round_rate)
+		return (clk->round_rate)(clk, rate);
+
+	return rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret;
+
+	if (IS_ERR(clk))
+		return -EINVAL;
+
+	mutex_lock(&clocks_mutex);
+	ret = (clk->set_rate)(clk, rate);
+	mutex_unlock(&clocks_mutex);
+
+	return ret;
+}
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return clk->parent;
+}
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = 0;
+
+	if (IS_ERR(clk))
+		return -EINVAL;
+
+	mutex_lock(&clocks_mutex);
+
+	if (clk->set_parent)
+		ret = (clk->set_parent)(clk, parent);
+
+	mutex_unlock(&clocks_mutex);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_get);
+EXPORT_SYMBOL(clk_put);
+EXPORT_SYMBOL(clk_enable);
+EXPORT_SYMBOL(clk_disable);
+EXPORT_SYMBOL(clk_get_rate);
+EXPORT_SYMBOL(clk_round_rate);
+EXPORT_SYMBOL(clk_set_rate);
+EXPORT_SYMBOL(clk_get_parent);
+EXPORT_SYMBOL(clk_set_parent);
+
+/* base clocks */
+
+struct clk clk_xtal = {
+	.name		= "xtal",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_mpll = {
+	.name		= "mpll",
+	.id		= -1,
+};
+
+struct clk clk_upll = {
+	.name		= "upll",
+	.id		= -1,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_f = {
+	.name		= "fclk",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= &clk_mpll,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_h = {
+	.name		= "hclk",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_p = {
+	.name		= "pclk",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_usb_bus = {
+	.name		= "usb-bus",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= &clk_upll,
+};
+
+/* clocks that could be registered by external code */
+
+static int s3c24xx_dclk_enable(struct clk *clk, int enable)
+{
+	unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
+
+	if (enable)
+		dclkcon |= clk->ctrlbit;
+	else
+		dclkcon &= ~clk->ctrlbit;
+
+	__raw_writel(dclkcon, S3C24XX_DCLKCON);
+
+	return 0;
+}
+
+static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
+{
+	unsigned long dclkcon;
+	unsigned int uclk;
+
+	if (parent == &clk_upll)
+		uclk = 1;
+	else if (parent == &clk_p)
+		uclk = 0;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	dclkcon = __raw_readl(S3C24XX_DCLKCON);
+
+	if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
+		if (uclk)
+			dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
+		else
+			dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
+	} else {
+		if (uclk)
+			dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
+		else
+			dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
+	}
+
+	__raw_writel(dclkcon, S3C24XX_DCLKCON);
+
+	return 0;
+}
+
+
+static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
+{
+	unsigned long mask;
+	unsigned long source;
+
+	/* calculate the MISCCR setting for the clock */
+
+	if (parent == &clk_xtal)
+		source = S3C2410_MISCCR_CLK0_MPLL;
+	else if (parent == &clk_upll)
+		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)
+		source = S3C2410_MISCCR_CLK0_DCLK0;
+	else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
+		source = S3C2410_MISCCR_CLK0_DCLK0;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	if (clk == &s3c24xx_dclk0)
+		mask = S3C2410_MISCCR_CLK0_MASK;
+	else {
+		source <<= 4;
+		mask = S3C2410_MISCCR_CLK1_MASK;
+	}
+
+	s3c2410_modify_misccr(mask, source);
+	return 0;
+}
+
+/* external clock definitions */
+
+struct clk s3c24xx_dclk0 = {
+	.name		= "dclk0",
+	.id		= -1,
+	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
+	.enable	        = s3c24xx_dclk_enable,
+	.set_parent	= s3c24xx_dclk_setparent,
+};
+
+struct clk s3c24xx_dclk1 = {
+	.name		= "dclk1",
+	.id		= -1,
+	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
+	.enable		= s3c24xx_dclk_enable,
+	.set_parent	= s3c24xx_dclk_setparent,
+};
+
+struct clk s3c24xx_clkout0 = {
+	.name		= "clkout0",
+	.id		= -1,
+	.set_parent	= s3c24xx_clkout_setparent,
+};
+
+struct clk s3c24xx_clkout1 = {
+	.name		= "clkout1",
+	.id		= -1,
+	.set_parent	= s3c24xx_clkout_setparent,
+};
+
+struct clk s3c24xx_uclk = {
+	.name		= "uclk",
+	.id		= -1,
+};
+
+/* initialise the clock system */
+
+int s3c24xx_register_clock(struct clk *clk)
+{
+	clk->owner = THIS_MODULE;
+
+	if (clk->enable == NULL)
+		clk->enable = clk_null_enable;
+
+	/* add to the list of available clocks */
+
+	mutex_lock(&clocks_mutex);
+	list_add(&clk->list, &clocks);
+	mutex_unlock(&clocks_mutex);
+
+	return 0;
+}
+
+/* initalise all the clocks */
+
+int __init s3c24xx_setup_clocks(unsigned long xtal,
+				unsigned long fclk,
+				unsigned long hclk,
+				unsigned long pclk)
+{
+	printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
+
+	/* initialise the main system clocks */
+
+	clk_xtal.rate = xtal;
+	clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
+
+	clk_mpll.rate = fclk;
+	clk_h.rate = hclk;
+	clk_p.rate = pclk;
+	clk_f.rate = fclk;
+
+	/* assume uart clocks are correctly setup */
+
+	/* register our clocks */
+
+	if (s3c24xx_register_clock(&clk_xtal) < 0)
+		printk(KERN_ERR "failed to register master xtal\n");
+
+	if (s3c24xx_register_clock(&clk_mpll) < 0)
+		printk(KERN_ERR "failed to register mpll clock\n");
+
+	if (s3c24xx_register_clock(&clk_upll) < 0)
+		printk(KERN_ERR "failed to register upll clock\n");
+
+	if (s3c24xx_register_clock(&clk_f) < 0)
+		printk(KERN_ERR "failed to register cpu fclk\n");
+
+	if (s3c24xx_register_clock(&clk_h) < 0)
+		printk(KERN_ERR "failed to register cpu hclk\n");
+
+	if (s3c24xx_register_clock(&clk_p) < 0)
+		printk(KERN_ERR "failed to register cpu pclk\n");
+
+	return 0;
+}
diff --git a/arch/arm/plat-s3c24xx/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c
new file mode 100644
index 0000000..908efa7
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/common-smdk.c
@@ -0,0 +1,200 @@
+/* linux/arch/arm/plat-s3c24xx/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/leds-gpio.h>
+
+#include <asm/arch/nand.h>
+
+#include <asm/plat-s3c24xx/common-smdk.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/pm.h>
+
+/* LED devices */
+
+static struct s3c24xx_led_platdata smdk_pdata_led4 = {
+	.gpio		= S3C2410_GPF4,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led4",
+	.def_trigger	= "timer",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led5 = {
+	.gpio		= S3C2410_GPF5,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led5",
+	.def_trigger	= "nand-disk",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led6 = {
+	.gpio		= S3C2410_GPF6,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led6",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led7 = {
+	.gpio		= S3C2410_GPF7,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led7",
+};
+
+static struct platform_device smdk_led4 = {
+	.name		= "s3c24xx_led",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &smdk_pdata_led4,
+	},
+};
+
+static struct platform_device smdk_led5 = {
+	.name		= "s3c24xx_led",
+	.id		= 1,
+	.dev		= {
+		.platform_data = &smdk_pdata_led5,
+	},
+};
+
+static struct platform_device smdk_led6 = {
+	.name		= "s3c24xx_led",
+	.id		= 2,
+	.dev		= {
+		.platform_data = &smdk_pdata_led6,
+	},
+};
+
+static struct platform_device smdk_led7 = {
+	.name		= "s3c24xx_led",
+	.id		= 3,
+	.dev		= {
+		.platform_data = &smdk_pdata_led7,
+	},
+};
+
+/* 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,
+	&smdk_led4,
+	&smdk_led5,
+	&smdk_led6,
+	&smdk_led7,
+};
+
+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/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
new file mode 100644
index 0000000..6a2d107
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -0,0 +1,368 @@
+/* linux/arch/arm/plat-s3c24xx/cpu.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	http://www.simtec.co.uk/products/SWLINUX/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX CPU Support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-serial.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/s3c2400.h>
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include "s3c244x.h"
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/s3c2442.h>
+#include <asm/plat-s3c24xx/s3c2443.h>
+
+struct cpu_table {
+	unsigned long	idcode;
+	unsigned long	idmask;
+	void		(*map_io)(struct map_desc *mach_desc, int size);
+	void		(*init_uarts)(struct s3c2410_uartcfg *cfg, int no);
+	void		(*init_clocks)(int xtal);
+	int		(*init)(void);
+	const char	*name;
+};
+
+/* table of supported CPUs */
+
+static const char name_s3c2400[]  = "S3C2400";
+static const char name_s3c2410[]  = "S3C2410";
+static const char name_s3c2412[]  = "S3C2412";
+static const char name_s3c2440[]  = "S3C2440";
+static const char name_s3c2442[]  = "S3C2442";
+static const char name_s3c2443[]  = "S3C2443";
+static const char name_s3c2410a[] = "S3C2410A";
+static const char name_s3c2440a[] = "S3C2440A";
+
+static struct cpu_table cpu_ids[] __initdata = {
+	{
+		.idcode		= 0x32410000,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2410_map_io,
+		.init_clocks	= s3c2410_init_clocks,
+		.init_uarts	= s3c2410_init_uarts,
+		.init		= s3c2410_init,
+		.name		= name_s3c2410
+	},
+	{
+		.idcode		= 0x32410002,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2410_map_io,
+		.init_clocks	= s3c2410_init_clocks,
+		.init_uarts	= s3c2410_init_uarts,
+		.init		= s3c2410_init,
+		.name		= name_s3c2410a
+	},
+	{
+		.idcode		= 0x32440000,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c244x_map_io,
+		.init_clocks	= s3c244x_init_clocks,
+		.init_uarts	= s3c244x_init_uarts,
+		.init		= s3c2440_init,
+		.name		= name_s3c2440
+	},
+	{
+		.idcode		= 0x32440001,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c244x_map_io,
+		.init_clocks	= s3c244x_init_clocks,
+		.init_uarts	= s3c244x_init_uarts,
+		.init		= s3c2440_init,
+		.name		= name_s3c2440a
+	},
+	{
+		.idcode		= 0x32440aaa,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c244x_map_io,
+		.init_clocks	= s3c244x_init_clocks,
+		.init_uarts	= s3c244x_init_uarts,
+		.init		= s3c2442_init,
+		.name		= name_s3c2442
+	},
+	{
+		.idcode		= 0x32412001,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2412_map_io,
+		.init_clocks	= s3c2412_init_clocks,
+		.init_uarts	= s3c2412_init_uarts,
+		.init		= s3c2412_init,
+		.name		= name_s3c2412,
+	},
+	{			/* a newer version of the s3c2412 */
+		.idcode		= 0x32412003,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2412_map_io,
+		.init_clocks	= s3c2412_init_clocks,
+		.init_uarts	= s3c2412_init_uarts,
+		.init		= s3c2412_init,
+		.name		= name_s3c2412,
+	},
+	{
+		.idcode		= 0x32443001,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2443_map_io,
+		.init_clocks	= s3c2443_init_clocks,
+		.init_uarts	= s3c2443_init_uarts,
+		.init		= s3c2443_init,
+		.name		= name_s3c2443,
+	},
+	{
+		.idcode		= 0x0,   /* S3C2400 doesn't have an idcode */
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2400_map_io,
+		.init_clocks	= s3c2400_init_clocks,
+		.init_uarts	= s3c2400_init_uarts,
+		.init		= s3c2400_init,
+		.name		= name_s3c2400
+	},
+};
+
+/* minimal IO mapping */
+
+static struct map_desc s3c_iodesc[] __initdata = {
+	IODESC_ENT(GPIO),
+	IODESC_ENT(IRQ),
+	IODESC_ENT(MEMCTRL),
+	IODESC_ENT(UART)
+};
+
+
+static struct cpu_table *
+s3c_lookup_cpu(unsigned long idcode)
+{
+	struct cpu_table *tab;
+	int count;
+
+	tab = cpu_ids;
+	for (count = 0; count < ARRAY_SIZE(cpu_ids); count++, tab++) {
+		if ((idcode & tab->idmask) == tab->idcode)
+			return tab;
+	}
+
+	return NULL;
+}
+
+/* board information */
+
+static struct s3c24xx_board *board;
+
+void s3c24xx_set_board(struct s3c24xx_board *b)
+{
+	int i;
+
+	board = b;
+
+	if (b->clocks_count != 0) {
+		struct clk **ptr = b->clocks;
+
+		for (i = b->clocks_count; i > 0; i--, ptr++)
+			s3c24xx_register_clock(*ptr);
+	}
+}
+
+/* cpu information */
+
+static struct cpu_table *cpu;
+
+static unsigned long s3c24xx_read_idcode_v5(void)
+{
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+	return __raw_readl(S3C2412_GSTATUS1);
+#else
+	return 1UL;	/* don't look like an 2400 */
+#endif
+}
+
+static unsigned long s3c24xx_read_idcode_v4(void)
+{
+#ifndef CONFIG_CPU_S3C2400
+	return __raw_readl(S3C2410_GSTATUS1);
+#else
+	return 0UL;
+#endif
+}
+
+void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
+{
+	unsigned long idcode = 0x0;
+
+	/* initialise the io descriptors we need for initialisation */
+	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
+
+	if (cpu_architecture() >= CPU_ARCH_ARMv5) {
+		idcode = s3c24xx_read_idcode_v5();
+	} else {
+		idcode = s3c24xx_read_idcode_v4();
+	}
+
+	cpu = s3c_lookup_cpu(idcode);
+
+	if (cpu == NULL) {
+		printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode);
+		panic("Unknown S3C24XX CPU");
+	}
+
+	printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
+
+	if (cpu->map_io == NULL || cpu->init == NULL) {
+		printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
+		panic("Unsupported S3C24XX CPU");
+	}
+
+	(cpu->map_io)(mach_desc, size);
+}
+
+/* s3c24xx_init_clocks
+ *
+ * Initialise the clock subsystem and associated information from the
+ * given master crystal value.
+ *
+ * xtal  = 0 -> use default PLL crystal value (normally 12MHz)
+ *      != 0 -> PLL crystal value in Hz
+*/
+
+void __init s3c24xx_init_clocks(int xtal)
+{
+	if (xtal == 0)
+		xtal = 12*1000*1000;
+
+	if (cpu == NULL)
+		panic("s3c24xx_init_clocks: no cpu setup?\n");
+
+	if (cpu->init_clocks == NULL)
+		panic("s3c24xx_init_clocks: cpu has no clock init\n");
+	else
+		(cpu->init_clocks)(xtal);
+}
+
+/* uart management */
+
+static int nr_uarts __initdata = 0;
+
+static struct s3c2410_uartcfg uart_cfgs[3];
+
+/* s3c24xx_init_uartdevs
+ *
+ * copy the specified platform data and configuration into our central
+ * set of devices, before the data is thrown away after the init process.
+ *
+ * This also fills in the array passed to the serial driver for the
+ * early initialisation of the console.
+*/
+
+void __init s3c24xx_init_uartdevs(char *name,
+				  struct s3c24xx_uart_resources *res,
+				  struct s3c2410_uartcfg *cfg, int no)
+{
+	struct platform_device *platdev;
+	struct s3c2410_uartcfg *cfgptr = uart_cfgs;
+	struct s3c24xx_uart_resources *resp;
+	int uart;
+
+	memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);
+
+	for (uart = 0; uart < no; uart++, cfg++, cfgptr++) {
+		platdev = s3c24xx_uart_src[cfgptr->hwport];
+
+		resp = res + cfgptr->hwport;
+
+		s3c24xx_uart_devs[uart] = platdev;
+
+		platdev->name = name;
+		platdev->resource = resp->resources;
+		platdev->num_resources = resp->nr_resources;
+
+		platdev->dev.platform_data = cfgptr;
+	}
+
+	nr_uarts = no;
+}
+
+void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	if (cpu == NULL)
+		return;
+
+	if (cpu->init_uarts == NULL) {
+		printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n");
+	} else
+		(cpu->init_uarts)(cfg, no);
+}
+
+static int __init s3c_arch_init(void)
+{
+	int ret;
+
+	// do the correct init for cpu
+
+	if (cpu == NULL)
+		panic("s3c_arch_init: NULL cpu\n");
+
+	ret = (cpu->init)();
+	if (ret != 0)
+		return ret;
+
+	ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts);
+	if (ret != 0)
+		return ret;
+
+	if (board != NULL) {
+		struct platform_device **ptr = board->devices;
+		int i;
+
+		for (i = 0; i < board->devices_count; i++, ptr++) {
+			ret = platform_device_register(*ptr);
+
+			if (ret) {
+				printk(KERN_ERR "s3c24xx: failed to add board device %s (%d) @%p\n", (*ptr)->name, ret, *ptr);
+			}
+		}
+
+		/* mask any error, we may not need all these board
+		 * devices */
+		ret = 0;
+	}
+
+	return ret;
+}
+
+arch_initcall(s3c_arch_init);
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
new file mode 100644
index 0000000..0fe53b3
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -0,0 +1,600 @@
+/* linux/arch/arm/plat-s3c24xx/devs.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Base S3C24XX platform device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#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/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/arch/fb.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/udc.h>
+
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* Serial port registrations */
+
+static struct resource s3c2410_uart0_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART0,
+		.end   = S3C2410_PA_UART0 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX0,
+		.end   = IRQ_S3CUART_ERR0,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart1_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART1,
+		.end   = S3C2410_PA_UART1 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX1,
+		.end   = IRQ_S3CUART_ERR1,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart2_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART2,
+		.end   = S3C2410_PA_UART2 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX2,
+		.end   = IRQ_S3CUART_ERR2,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
+	[0] = {
+		.resources	= s3c2410_uart0_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart0_resource),
+	},
+	[1] = {
+		.resources	= s3c2410_uart1_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart1_resource),
+	},
+	[2] = {
+		.resources	= s3c2410_uart2_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart2_resource),
+	},
+};
+
+/* yart devices */
+
+static struct platform_device s3c24xx_uart_device0 = {
+	.id		= 0,
+};
+
+static struct platform_device s3c24xx_uart_device1 = {
+	.id		= 1,
+};
+
+static struct platform_device s3c24xx_uart_device2 = {
+	.id		= 2,
+};
+
+struct platform_device *s3c24xx_uart_src[3] = {
+	&s3c24xx_uart_device0,
+	&s3c24xx_uart_device1,
+	&s3c24xx_uart_device2,
+};
+
+struct platform_device *s3c24xx_uart_devs[3] = {
+};
+
+/* USB Host Controller */
+
+static struct resource s3c_usb_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_USBHOST,
+		.end   = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBH,
+		.end   = IRQ_USBH,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static u64 s3c_device_usb_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb = {
+	.name		  = "s3c2410-ohci",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_usb_resource),
+	.resource	  = s3c_usb_resource,
+	.dev              = {
+		.dma_mask = &s3c_device_usb_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+
+EXPORT_SYMBOL(s3c_device_usb);
+
+/* LCD Controller */
+
+static struct resource s3c_lcd_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_LCD,
+		.end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_LCD,
+		.end   = IRQ_LCD,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_lcd = {
+	.name		  = "s3c2410-lcd",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_lcd_resource),
+	.resource	  = s3c_lcd_resource,
+	.dev              = {
+		.dma_mask		= &s3c_device_lcd_dmamask,
+		.coherent_dma_mask	= 0xffffffffUL
+	}
+};
+
+EXPORT_SYMBOL(s3c_device_lcd);
+
+void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
+{
+	struct s3c2410fb_mach_info *npd;
+
+	npd = kmalloc(sizeof(*npd), GFP_KERNEL);
+	if (npd) {
+		memcpy(npd, pd, sizeof(*npd));
+		s3c_device_lcd.dev.platform_data = npd;
+	} else {
+		printk(KERN_ERR "no memory for LCD platform data\n");
+	}
+}
+
+/* NAND Controller */
+
+static struct resource s3c_nand_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_NAND,
+		.end   = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1,
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+struct platform_device s3c_device_nand = {
+	.name		  = "s3c2410-nand",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_nand_resource),
+	.resource	  = s3c_nand_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_nand);
+
+/* USB Device (Gadget)*/
+
+static struct resource s3c_usbgadget_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_USBDEV,
+		.end   = S3C24XX_PA_USBDEV + S3C24XX_SZ_USBDEV - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBD,
+		.end   = IRQ_USBD,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_usbgadget = {
+	.name		  = "s3c2410-usbgadget",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_usbgadget_resource),
+	.resource	  = s3c_usbgadget_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_usbgadget);
+
+void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
+{
+	struct s3c2410_udc_mach_info *npd;
+
+	npd = kmalloc(sizeof(*npd), GFP_KERNEL);
+	if (npd) {
+		memcpy(npd, pd, sizeof(*npd));
+		s3c_device_usbgadget.dev.platform_data = npd;
+	} else {
+		printk(KERN_ERR "no memory for udc platform data\n");
+	}
+}
+
+
+/* Watchdog */
+
+static struct resource s3c_wdt_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_WATCHDOG,
+		.end   = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_WDT,
+		.end   = IRQ_WDT,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_wdt = {
+	.name		  = "s3c2410-wdt",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_wdt_resource),
+	.resource	  = s3c_wdt_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_wdt);
+
+/* I2C */
+
+static struct resource s3c_i2c_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_IIC,
+		.end   = S3C24XX_PA_IIC + S3C24XX_SZ_IIC - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_IIC,
+		.end   = IRQ_IIC,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_i2c = {
+	.name		  = "s3c2410-i2c",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
+	.resource	  = s3c_i2c_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_i2c);
+
+/* IIS */
+
+static struct resource s3c_iis_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_IIS,
+		.end   = S3C24XX_PA_IIS + S3C24XX_SZ_IIS -1,
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+static u64 s3c_device_iis_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_iis = {
+	.name		  = "s3c2410-iis",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_iis_resource),
+	.resource	  = s3c_iis_resource,
+	.dev              = {
+		.dma_mask = &s3c_device_iis_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+
+EXPORT_SYMBOL(s3c_device_iis);
+
+/* RTC */
+
+static struct resource s3c_rtc_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_RTC,
+		.end   = S3C24XX_PA_RTC + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_RTC,
+		.end   = IRQ_RTC,
+		.flags = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start = IRQ_TICK,
+		.end   = IRQ_TICK,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+struct platform_device s3c_device_rtc = {
+	.name		  = "s3c2410-rtc",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_rtc_resource),
+	.resource	  = s3c_rtc_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_rtc);
+
+/* ADC */
+
+static struct resource s3c_adc_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_ADC,
+		.end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TC,
+		.end   = IRQ_TC,
+		.flags = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start = IRQ_ADC,
+		.end   = IRQ_ADC,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_adc = {
+	.name		  = "s3c2410-adc",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_adc_resource),
+	.resource	  = s3c_adc_resource,
+};
+
+/* SDI */
+
+static struct resource s3c_sdi_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_SDI,
+		.end   = S3C2410_PA_SDI + S3C24XX_SZ_SDI - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_SDI,
+		.end   = IRQ_SDI,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_sdi = {
+	.name		  = "s3c2410-sdi",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_sdi_resource),
+	.resource	  = s3c_sdi_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_sdi);
+
+/* SPI (0) */
+
+static struct resource s3c_spi0_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_SPI,
+		.end   = S3C24XX_PA_SPI + 0x1f,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_SPI0,
+		.end   = IRQ_SPI0,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+static u64 s3c_device_spi0_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_spi0 = {
+	.name		  = "s3c2410-spi",
+	.id		  = 0,
+	.num_resources	  = ARRAY_SIZE(s3c_spi0_resource),
+	.resource	  = s3c_spi0_resource,
+        .dev              = {
+                .dma_mask = &s3c_device_spi0_dmamask,
+                .coherent_dma_mask = 0xffffffffUL
+        }
+};
+
+EXPORT_SYMBOL(s3c_device_spi0);
+
+/* SPI (1) */
+
+static struct resource s3c_spi1_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_SPI + 0x20,
+		.end   = S3C24XX_PA_SPI + 0x20 + 0x1f,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_SPI1,
+		.end   = IRQ_SPI1,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+static u64 s3c_device_spi1_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_spi1 = {
+	.name		  = "s3c2410-spi",
+	.id		  = 1,
+	.num_resources	  = ARRAY_SIZE(s3c_spi1_resource),
+	.resource	  = s3c_spi1_resource,
+        .dev              = {
+                .dma_mask = &s3c_device_spi1_dmamask,
+                .coherent_dma_mask = 0xffffffffUL
+        }
+};
+
+EXPORT_SYMBOL(s3c_device_spi1);
+
+/* pwm timer blocks */
+
+static struct resource s3c_timer0_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_TIMER + 0x0C,
+		.end   = S3C24XX_PA_TIMER + 0x0C + 0xB,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TIMER0,
+		.end   = IRQ_TIMER0,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_timer0 = {
+	.name		  = "s3c2410-timer",
+	.id		  = 0,
+	.num_resources	  = ARRAY_SIZE(s3c_timer0_resource),
+	.resource	  = s3c_timer0_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer0);
+
+/* timer 1 */
+
+static struct resource s3c_timer1_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_TIMER + 0x18,
+		.end   = S3C24XX_PA_TIMER + 0x23,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TIMER1,
+		.end   = IRQ_TIMER1,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_timer1 = {
+	.name		  = "s3c2410-timer",
+	.id		  = 1,
+	.num_resources	  = ARRAY_SIZE(s3c_timer1_resource),
+	.resource	  = s3c_timer1_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer1);
+
+/* timer 2 */
+
+static struct resource s3c_timer2_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_TIMER + 0x24,
+		.end   = S3C24XX_PA_TIMER + 0x2F,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TIMER2,
+		.end   = IRQ_TIMER2,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_timer2 = {
+	.name		  = "s3c2410-timer",
+	.id		  = 2,
+	.num_resources	  = ARRAY_SIZE(s3c_timer2_resource),
+	.resource	  = s3c_timer2_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer2);
+
+/* timer 3 */
+
+static struct resource s3c_timer3_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_TIMER + 0x30,
+		.end   = S3C24XX_PA_TIMER + 0x3B,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TIMER3,
+		.end   = IRQ_TIMER3,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_timer3 = {
+	.name		  = "s3c2410-timer",
+	.id		  = 3,
+	.num_resources	  = ARRAY_SIZE(s3c_timer3_resource),
+	.resource	  = s3c_timer3_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer3);
+
+#ifdef CONFIG_CPU_S3C2440
+
+/* Camif Controller */
+
+static struct resource s3c_camif_resource[] = {
+	[0] = {
+		.start = S3C2440_PA_CAMIF,
+		.end   = S3C2440_PA_CAMIF + S3C2440_SZ_CAMIF - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_CAM,
+		.end   = IRQ_CAM,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+static u64 s3c_device_camif_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_camif = {
+	.name		  = "s3c2440-camif",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_camif_resource),
+	.resource	  = s3c_camif_resource,
+	.dev              = {
+		.dma_mask = &s3c_device_camif_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+
+EXPORT_SYMBOL(s3c_device_camif);
+
+#endif // CONFIG_CPU_S32440
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
new file mode 100644
index 0000000..4540a80
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -0,0 +1,1499 @@
+/* linux/arch/arm/plat-s3c24xx/dma.c
+ *
+ * Copyright (c) 2003-2005,2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 DMA core
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+*/
+
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <asm/mach/dma.h>
+#include <asm/arch/map.h>
+
+#include <asm/plat-s3c24xx/dma.h>
+
+/* io map for dma */
+static void __iomem *dma_base;
+static struct kmem_cache *dma_kmem;
+
+static int dma_channels;
+
+struct s3c24xx_dma_selection dma_sel;
+
+/* dma channel state information */
+struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
+
+/* debugging functions */
+
+#define BUF_MAGIC (0xcafebabe)
+
+#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
+
+#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
+
+#if 1
+#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
+#else
+static inline void
+dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
+{
+	pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
+	writel(val, dma_regaddr(chan, reg));
+}
+#endif
+
+#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
+
+/* captured register state for debug */
+
+struct s3c2410_dma_regstate {
+	unsigned long         dcsrc;
+	unsigned long         disrc;
+	unsigned long         dstat;
+	unsigned long         dcon;
+	unsigned long         dmsktrig;
+};
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+
+/* dmadbg_showregs
+ *
+ * simple debug routine to print the current state of the dma registers
+*/
+
+static void
+dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
+{
+	regs->dcsrc    = dma_rdreg(chan, S3C2410_DMA_DCSRC);
+	regs->disrc    = dma_rdreg(chan, S3C2410_DMA_DISRC);
+	regs->dstat    = dma_rdreg(chan, S3C2410_DMA_DSTAT);
+	regs->dcon     = dma_rdreg(chan, S3C2410_DMA_DCON);
+	regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+}
+
+static void
+dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
+		 struct s3c2410_dma_regstate *regs)
+{
+	printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
+	       chan->number, fname, line,
+	       regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
+	       regs->dcon);
+}
+
+static void
+dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
+{
+	struct s3c2410_dma_regstate state;
+
+	dmadbg_capture(chan, &state);
+
+	printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
+	       chan->number, fname, line, chan->load_state,
+	       chan->curr, chan->next, chan->end);
+
+	dmadbg_dumpregs(fname, line, chan, &state);
+}
+
+static void
+dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
+{
+	struct s3c2410_dma_regstate state;
+
+	dmadbg_capture(chan, &state);
+	dmadbg_dumpregs(fname, line, chan, &state);
+}
+
+#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
+#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
+#else
+#define dbg_showregs(chan) do { } while(0)
+#define dbg_showchan(chan) do { } while(0)
+#endif /* CONFIG_S3C2410_DMA_DEBUG */
+
+static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
+
+/* lookup_dma_channel
+ *
+ * change the dma channel number given into a real dma channel id
+*/
+
+static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
+{
+	if (channel & DMACH_LOW_LEVEL)
+		return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
+	else
+		return dma_chan_map[channel];
+}
+
+/* s3c2410_dma_stats_timeout
+ *
+ * Update DMA stats from timeout info
+*/
+
+static void
+s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
+{
+	if (stats == NULL)
+		return;
+
+	if (val > stats->timeout_longest)
+		stats->timeout_longest = val;
+	if (val < stats->timeout_shortest)
+		stats->timeout_shortest = val;
+
+	stats->timeout_avg += val;
+}
+
+/* s3c2410_dma_waitforload
+ *
+ * wait for the DMA engine to load a buffer, and update the state accordingly
+*/
+
+static int
+s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
+{
+	int timeout = chan->load_timeout;
+	int took;
+
+	if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
+		printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
+		return 0;
+	}
+
+	if (chan->stats != NULL)
+		chan->stats->loads++;
+
+	while (--timeout > 0) {
+		if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
+			took = chan->load_timeout - timeout;
+
+			s3c2410_dma_stats_timeout(chan->stats, took);
+
+			switch (chan->load_state) {
+			case S3C2410_DMALOAD_1LOADED:
+				chan->load_state = S3C2410_DMALOAD_1RUNNING;
+				break;
+
+			default:
+				printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
+			}
+
+			return 1;
+		}
+	}
+
+	if (chan->stats != NULL) {
+		chan->stats->timeout_failed++;
+	}
+
+	return 0;
+}
+
+
+
+/* s3c2410_dma_loadbuffer
+ *
+ * load a buffer, and update the channel state
+*/
+
+static inline int
+s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
+		       struct s3c2410_dma_buf *buf)
+{
+	unsigned long reload;
+
+	pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
+		 buf, (unsigned long)buf->data, buf->size);
+
+	if (buf == NULL) {
+		dmawarn("buffer is NULL\n");
+		return -EINVAL;
+	}
+
+	/* check the state of the channel before we do anything */
+
+	if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+		dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
+	}
+
+	if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
+		dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
+	}
+
+	/* it would seem sensible if we are the last buffer to not bother
+	 * with the auto-reload bit, so that the DMA engine will not try
+	 * and load another transfer after this one has finished...
+	 */
+	if (chan->load_state == S3C2410_DMALOAD_NONE) {
+		pr_debug("load_state is none, checking for noreload (next=%p)\n",
+			 buf->next);
+		reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
+	} else {
+		//pr_debug("load_state is %d => autoreload\n", chan->load_state);
+		reload = S3C2410_DCON_AUTORELOAD;
+	}
+
+	if ((buf->data & 0xf0000000) != 0x30000000) {
+		dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
+	}
+
+	writel(buf->data, chan->addr_reg);
+
+	dma_wrreg(chan, S3C2410_DMA_DCON,
+		  chan->dcon | reload | (buf->size/chan->xfer_unit));
+
+	chan->next = buf->next;
+
+	/* update the state of the channel */
+
+	switch (chan->load_state) {
+	case S3C2410_DMALOAD_NONE:
+		chan->load_state = S3C2410_DMALOAD_1LOADED;
+		break;
+
+	case S3C2410_DMALOAD_1RUNNING:
+		chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
+		break;
+
+	default:
+		dmawarn("dmaload: unknown state %d in loadbuffer\n",
+			chan->load_state);
+		break;
+	}
+
+	return 0;
+}
+
+/* s3c2410_dma_call_op
+ *
+ * small routine to call the op routine with the given op if it has been
+ * registered
+*/
+
+static void
+s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
+{
+	if (chan->op_fn != NULL) {
+		(chan->op_fn)(chan, op);
+	}
+}
+
+/* s3c2410_dma_buffdone
+ *
+ * small wrapper to check if callback routine needs to be called, and
+ * if so, call it
+*/
+
+static inline void
+s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
+		     enum s3c2410_dma_buffresult result)
+{
+#if 0
+	pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
+		 chan->callback_fn, buf, buf->id, buf->size, result);
+#endif
+
+	if (chan->callback_fn != NULL) {
+		(chan->callback_fn)(chan, buf->id, buf->size, result);
+	}
+}
+
+/* s3c2410_dma_start
+ *
+ * start a dma channel going
+*/
+
+static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
+{
+	unsigned long tmp;
+	unsigned long flags;
+
+	pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
+
+	local_irq_save(flags);
+
+	if (chan->state == S3C2410_DMA_RUNNING) {
+		pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
+		local_irq_restore(flags);
+		return 0;
+	}
+
+	chan->state = S3C2410_DMA_RUNNING;
+
+	/* check wether there is anything to load, and if not, see
+	 * if we can find anything to load
+	 */
+
+	if (chan->load_state == S3C2410_DMALOAD_NONE) {
+		if (chan->next == NULL) {
+			printk(KERN_ERR "dma%d: channel has nothing loaded\n",
+			       chan->number);
+			chan->state = S3C2410_DMA_IDLE;
+			local_irq_restore(flags);
+			return -EINVAL;
+		}
+
+		s3c2410_dma_loadbuffer(chan, chan->next);
+	}
+
+	dbg_showchan(chan);
+
+	/* enable the channel */
+
+	if (!chan->irq_enabled) {
+		enable_irq(chan->irq);
+		chan->irq_enabled = 1;
+	}
+
+	/* start the channel going */
+
+	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+	tmp &= ~S3C2410_DMASKTRIG_STOP;
+	tmp |= S3C2410_DMASKTRIG_ON;
+	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+	pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
+
+#if 0
+	/* the dma buffer loads should take care of clearing the AUTO
+	 * reloading feature */
+	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+	tmp &= ~S3C2410_DCON_NORELOAD;
+	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+	s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
+
+	dbg_showchan(chan);
+
+	/* if we've only loaded one buffer onto the channel, then chec
+	 * to see if we have another, and if so, try and load it so when
+	 * the first buffer is finished, the new one will be loaded onto
+	 * the channel */
+
+	if (chan->next != NULL) {
+		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				pr_debug("%s: buff not yet loaded, no more todo\n",
+					 __FUNCTION__);
+			} else {
+				chan->load_state = S3C2410_DMALOAD_1RUNNING;
+				s3c2410_dma_loadbuffer(chan, chan->next);
+			}
+
+		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+			s3c2410_dma_loadbuffer(chan, chan->next);
+		}
+	}
+
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+/* s3c2410_dma_canload
+ *
+ * work out if we can queue another buffer into the DMA engine
+*/
+
+static int
+s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
+{
+	if (chan->load_state == S3C2410_DMALOAD_NONE ||
+	    chan->load_state == S3C2410_DMALOAD_1RUNNING)
+		return 1;
+
+	return 0;
+}
+
+/* s3c2410_dma_enqueue
+ *
+ * queue an given buffer for dma transfer.
+ *
+ * id         the device driver's id information for this buffer
+ * data       the physical address of the buffer data
+ * size       the size of the buffer in bytes
+ *
+ * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
+ * is checked, and if set, the channel is started. If this flag isn't set,
+ * then an error will be returned.
+ *
+ * It is possible to queue more than one DMA buffer onto a channel at
+ * once, and the code will deal with the re-loading of the next buffer
+ * when necessary.
+*/
+
+int s3c2410_dma_enqueue(unsigned int channel, void *id,
+			dma_addr_t data, int size)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+	struct s3c2410_dma_buf *buf;
+	unsigned long flags;
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: id=%p, data=%08x, size=%d\n",
+		 __FUNCTION__, id, (unsigned int)data, size);
+
+	buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
+	if (buf == NULL) {
+		pr_debug("%s: out of memory (%ld alloc)\n",
+			 __FUNCTION__, (long)sizeof(*buf));
+		return -ENOMEM;
+	}
+
+	//pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
+	//dbg_showchan(chan);
+
+	buf->next  = NULL;
+	buf->data  = buf->ptr = data;
+	buf->size  = size;
+	buf->id    = id;
+	buf->magic = BUF_MAGIC;
+
+	local_irq_save(flags);
+
+	if (chan->curr == NULL) {
+		/* we've got nothing loaded... */
+		pr_debug("%s: buffer %p queued onto empty channel\n",
+			 __FUNCTION__, buf);
+
+		chan->curr = buf;
+		chan->end  = buf;
+		chan->next = NULL;
+	} else {
+		pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
+			 chan->number, __FUNCTION__, buf);
+
+		if (chan->end == NULL)
+			pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
+				 chan->number, __FUNCTION__, chan);
+
+		chan->end->next = buf;
+		chan->end = buf;
+	}
+
+	/* if necessary, update the next buffer field */
+	if (chan->next == NULL)
+		chan->next = buf;
+
+	/* check to see if we can load a buffer */
+	if (chan->state == S3C2410_DMA_RUNNING) {
+		if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				printk(KERN_ERR "dma%d: loadbuffer:"
+				       "timeout loading buffer\n",
+				       chan->number);
+				dbg_showchan(chan);
+				local_irq_restore(flags);
+				return -EINVAL;
+			}
+		}
+
+		while (s3c2410_dma_canload(chan) && chan->next != NULL) {
+			s3c2410_dma_loadbuffer(chan, chan->next);
+		}
+	} else if (chan->state == S3C2410_DMA_IDLE) {
+		if (chan->flags & S3C2410_DMAF_AUTOSTART) {
+			s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
+		}
+	}
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_enqueue);
+
+static inline void
+s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
+{
+	int magicok = (buf->magic == BUF_MAGIC);
+
+	buf->magic = -1;
+
+	if (magicok) {
+		kmem_cache_free(dma_kmem, buf);
+	} else {
+		printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
+	}
+}
+
+/* s3c2410_dma_lastxfer
+ *
+ * called when the system is out of buffers, to ensure that the channel
+ * is prepared for shutdown.
+*/
+
+static inline void
+s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
+{
+#if 0
+	pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
+		 chan->number, chan->load_state);
+#endif
+
+	switch (chan->load_state) {
+	case S3C2410_DMALOAD_NONE:
+		break;
+
+	case S3C2410_DMALOAD_1LOADED:
+		if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				/* flag error? */
+			printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+			       chan->number, __FUNCTION__);
+			return;
+		}
+		break;
+
+	case S3C2410_DMALOAD_1LOADED_1RUNNING:
+		/* I belive in this case we do not have anything to do
+		 * until the next buffer comes along, and we turn off the
+		 * reload */
+		return;
+
+	default:
+		pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
+			 chan->number, chan->load_state);
+		return;
+
+	}
+
+	/* hopefully this'll shut the damned thing up after the transfer... */
+	dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
+}
+
+
+#define dmadbg2(x...)
+
+static irqreturn_t
+s3c2410_dma_irq(int irq, void *devpw)
+{
+	struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
+	struct s3c2410_dma_buf  *buf;
+
+	buf = chan->curr;
+
+	dbg_showchan(chan);
+
+	/* modify the channel state */
+
+	switch (chan->load_state) {
+	case S3C2410_DMALOAD_1RUNNING:
+		/* TODO - if we are running only one buffer, we probably
+		 * want to reload here, and then worry about the buffer
+		 * callback */
+
+		chan->load_state = S3C2410_DMALOAD_NONE;
+		break;
+
+	case S3C2410_DMALOAD_1LOADED:
+		/* iirc, we should go back to NONE loaded here, we
+		 * had a buffer, and it was never verified as being
+		 * loaded.
+		 */
+
+		chan->load_state = S3C2410_DMALOAD_NONE;
+		break;
+
+	case S3C2410_DMALOAD_1LOADED_1RUNNING:
+		/* we'll worry about checking to see if another buffer is
+		 * ready after we've called back the owner. This should
+		 * ensure we do not wait around too long for the DMA
+		 * engine to start the next transfer
+		 */
+
+		chan->load_state = S3C2410_DMALOAD_1LOADED;
+		break;
+
+	case S3C2410_DMALOAD_NONE:
+		printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
+		       chan->number);
+		break;
+
+	default:
+		printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
+		       chan->number, chan->load_state);
+		break;
+	}
+
+	if (buf != NULL) {
+		/* update the chain to make sure that if we load any more
+		 * buffers when we call the callback function, things should
+		 * work properly */
+
+		chan->curr = buf->next;
+		buf->next  = NULL;
+
+		if (buf->magic != BUF_MAGIC) {
+			printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
+			       chan->number, __FUNCTION__, buf);
+			return IRQ_HANDLED;
+		}
+
+		s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
+
+		/* free resouces */
+		s3c2410_dma_freebuf(buf);
+	} else {
+	}
+
+	/* only reload if the channel is still running... our buffer done
+	 * routine may have altered the state by requesting the dma channel
+	 * to stop or shutdown... */
+
+	/* todo: check that when the channel is shut-down from inside this
+	 * function, we cope with unsetting reload, etc */
+
+	if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
+		unsigned long flags;
+
+		switch (chan->load_state) {
+		case S3C2410_DMALOAD_1RUNNING:
+			/* don't need to do anything for this state */
+			break;
+
+		case S3C2410_DMALOAD_NONE:
+			/* can load buffer immediately */
+			break;
+
+		case S3C2410_DMALOAD_1LOADED:
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				/* flag error? */
+				printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+				       chan->number, __FUNCTION__);
+				return IRQ_HANDLED;
+			}
+
+			break;
+
+		case S3C2410_DMALOAD_1LOADED_1RUNNING:
+			goto no_load;
+
+		default:
+			printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
+			       chan->number, chan->load_state);
+			return IRQ_HANDLED;
+		}
+
+		local_irq_save(flags);
+		s3c2410_dma_loadbuffer(chan, chan->next);
+		local_irq_restore(flags);
+	} else {
+		s3c2410_dma_lastxfer(chan);
+
+		/* see if we can stop this channel.. */
+		if (chan->load_state == S3C2410_DMALOAD_NONE) {
+			pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
+				 chan->number, jiffies);
+			s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
+					 S3C2410_DMAOP_STOP);
+		}
+	}
+
+ no_load:
+	return IRQ_HANDLED;
+}
+
+static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
+
+/* s3c2410_request_dma
+ *
+ * get control of an dma channel
+*/
+
+int s3c2410_dma_request(unsigned int channel,
+			struct s3c2410_dma_client *client,
+			void *dev)
+{
+	struct s3c2410_dma_chan *chan;
+	unsigned long flags;
+	int err;
+
+	pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
+		 channel, client->name, dev);
+
+	local_irq_save(flags);
+
+	chan = s3c2410_dma_map_channel(channel);
+	if (chan == NULL) {
+		local_irq_restore(flags);
+		return -EBUSY;
+	}
+
+	dbg_showchan(chan);
+
+	chan->client = client;
+	chan->in_use = 1;
+
+	if (!chan->irq_claimed) {
+		pr_debug("dma%d: %s : requesting irq %d\n",
+			 channel, __FUNCTION__, chan->irq);
+
+		chan->irq_claimed = 1;
+		local_irq_restore(flags);
+
+		err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
+				  client->name, (void *)chan);
+
+		local_irq_save(flags);
+
+		if (err) {
+			chan->in_use = 0;
+			chan->irq_claimed = 0;
+			local_irq_restore(flags);
+
+			printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
+			       client->name, chan->irq, chan->number);
+			return err;
+		}
+
+		chan->irq_enabled = 1;
+	}
+
+	local_irq_restore(flags);
+
+	/* need to setup */
+
+	pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_request);
+
+/* s3c2410_dma_free
+ *
+ * release the given channel back to the system, will stop and flush
+ * any outstanding transfers, and ensure the channel is ready for the
+ * next claimant.
+ *
+ * Note, although a warning is currently printed if the freeing client
+ * info is not the same as the registrant's client info, the free is still
+ * allowed to go through.
+*/
+
+int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+	unsigned long flags;
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	if (chan->client != client) {
+		printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
+		       channel, chan->client, client);
+	}
+
+	/* sort out stopping and freeing the channel */
+
+	if (chan->state != S3C2410_DMA_IDLE) {
+		pr_debug("%s: need to stop dma channel %p\n",
+		       __FUNCTION__, chan);
+
+		/* possibly flush the channel */
+		s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
+	}
+
+	chan->client = NULL;
+	chan->in_use = 0;
+
+	if (chan->irq_claimed)
+		free_irq(chan->irq, (void *)chan);
+
+	chan->irq_claimed = 0;
+
+	if (!(channel & DMACH_LOW_LEVEL))
+		dma_chan_map[channel] = NULL;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_free);
+
+static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
+{
+	unsigned long flags;
+	unsigned long tmp;
+
+	pr_debug("%s:\n", __FUNCTION__);
+
+	dbg_showchan(chan);
+
+	local_irq_save(flags);
+
+	s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);
+
+	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+	tmp |= S3C2410_DMASKTRIG_STOP;
+	//tmp &= ~S3C2410_DMASKTRIG_ON;
+	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+#if 0
+	/* should also clear interrupts, according to WinCE BSP */
+	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+	tmp |= S3C2410_DCON_NORELOAD;
+	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+	/* should stop do this, or should we wait for flush? */
+	chan->state      = S3C2410_DMA_IDLE;
+	chan->load_state = S3C2410_DMALOAD_NONE;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
+{
+	unsigned long tmp;
+	unsigned int timeout = 0x10000;
+
+	while (timeout-- > 0) {
+		tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+
+		if (!(tmp & S3C2410_DMASKTRIG_ON))
+			return;
+	}
+
+	pr_debug("dma%d: failed to stop?\n", chan->number);
+}
+
+
+/* s3c2410_dma_flush
+ *
+ * stop the channel, and remove all current and pending transfers
+*/
+
+static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
+{
+	struct s3c2410_dma_buf *buf, *next;
+	unsigned long flags;
+
+	pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
+
+	dbg_showchan(chan);
+
+	local_irq_save(flags);
+
+	if (chan->state != S3C2410_DMA_IDLE) {
+		pr_debug("%s: stopping channel...\n", __FUNCTION__ );
+		s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+	}
+
+	buf = chan->curr;
+	if (buf == NULL)
+		buf = chan->next;
+
+	chan->curr = chan->next = chan->end = NULL;
+
+	if (buf != NULL) {
+		for ( ; buf != NULL; buf = next) {
+			next = buf->next;
+
+			pr_debug("%s: free buffer %p, next %p\n",
+			       __FUNCTION__, buf, buf->next);
+
+			s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
+			s3c2410_dma_freebuf(buf);
+		}
+	}
+
+	dbg_showregs(chan);
+
+	s3c2410_dma_waitforstop(chan);
+
+#if 0
+	/* should also clear interrupts, according to WinCE BSP */
+	{
+		unsigned long tmp;
+
+		tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+		tmp |= S3C2410_DCON_NORELOAD;
+		dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+	}
+#endif
+
+	dbg_showregs(chan);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+int
+s3c2410_dma_started(struct s3c2410_dma_chan *chan)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	dbg_showchan(chan);
+
+	/* if we've only loaded one buffer onto the channel, then chec
+	 * to see if we have another, and if so, try and load it so when
+	 * the first buffer is finished, the new one will be loaded onto
+	 * the channel */
+
+	if (chan->next != NULL) {
+		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				pr_debug("%s: buff not yet loaded, no more todo\n",
+					 __FUNCTION__);
+			} else {
+				chan->load_state = S3C2410_DMALOAD_1RUNNING;
+				s3c2410_dma_loadbuffer(chan, chan->next);
+			}
+
+		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+			s3c2410_dma_loadbuffer(chan, chan->next);
+		}
+	}
+
+
+	local_irq_restore(flags);
+
+	return 0;
+
+}
+
+int
+s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	switch (op) {
+	case S3C2410_DMAOP_START:
+		return s3c2410_dma_start(chan);
+
+	case S3C2410_DMAOP_STOP:
+		return s3c2410_dma_dostop(chan);
+
+	case S3C2410_DMAOP_PAUSE:
+	case S3C2410_DMAOP_RESUME:
+		return -ENOENT;
+
+	case S3C2410_DMAOP_FLUSH:
+		return s3c2410_dma_flush(chan);
+
+	case S3C2410_DMAOP_STARTED:
+		return s3c2410_dma_started(chan);
+
+	case S3C2410_DMAOP_TIMEOUT:
+		return 0;
+
+	}
+
+	return -ENOENT;      /* unknown, don't bother */
+}
+
+EXPORT_SYMBOL(s3c2410_dma_ctrl);
+
+/* DMA configuration for each channel
+ *
+ * DISRCC -> source of the DMA (AHB,APB)
+ * DISRC  -> source address of the DMA
+ * DIDSTC -> destination of the DMA (AHB,APD)
+ * DIDST  -> destination address of the DMA
+*/
+
+/* s3c2410_dma_config
+ *
+ * xfersize:     size of unit in bytes (1,2,4)
+ * dcon:         base value of the DCONx register
+*/
+
+int s3c2410_dma_config(dmach_t channel,
+		       int xferunit,
+		       int dcon)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
+		 __FUNCTION__, channel, xferunit, dcon);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
+
+	dcon |= chan->dcon & dma_sel.dcon_mask;
+
+	pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
+
+	switch (xferunit) {
+	case 1:
+		dcon |= S3C2410_DCON_BYTE;
+		break;
+
+	case 2:
+		dcon |= S3C2410_DCON_HALFWORD;
+		break;
+
+	case 4:
+		dcon |= S3C2410_DCON_WORD;
+		break;
+
+	default:
+		pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
+		return -EINVAL;
+	}
+
+	dcon |= S3C2410_DCON_HWTRIG;
+	dcon |= S3C2410_DCON_INTREQ;
+
+	pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
+
+	chan->dcon = dcon;
+	chan->xfer_unit = xferunit;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_config);
+
+int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
+
+	chan->flags = flags;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_setflags);
+
+
+/* do we need to protect the settings of the fields from
+ * irq?
+*/
+
+int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
+
+	chan->op_fn = rtn;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_set_opfn);
+
+int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
+
+	chan->callback_fn = rtn;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
+
+/* s3c2410_dma_devconfig
+ *
+ * configure the dma source/destination hardware type and address
+ *
+ * source:    S3C2410_DMASRC_HW: source is hardware
+ *            S3C2410_DMASRC_MEM: source is memory
+ *
+ * hwcfg:     the value for xxxSTCn register,
+ *            bit 0: 0=increment pointer, 1=leave pointer
+ *            bit 1: 0=soucre is AHB, 1=soucre is APB
+ *
+ * devaddr:   physical address of the source
+*/
+
+int s3c2410_dma_devconfig(int channel,
+			  enum s3c2410_dmasrc source,
+			  int hwcfg,
+			  unsigned long devaddr)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
+		 __FUNCTION__, (int)source, hwcfg, devaddr);
+
+	chan->source = source;
+	chan->dev_addr = devaddr;
+
+	switch (source) {
+	case S3C2410_DMASRC_HW:
+		/* source is hardware */
+		pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
+			 __FUNCTION__, devaddr, hwcfg);
+		dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
+		dma_wrreg(chan, S3C2410_DMA_DISRC,  devaddr);
+		dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
+
+		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
+		return 0;
+
+	case S3C2410_DMASRC_MEM:
+		/* source is memory */
+		pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
+			  __FUNCTION__, devaddr, hwcfg);
+		dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
+		dma_wrreg(chan, S3C2410_DMA_DIDST,  devaddr);
+		dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
+
+		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
+		return 0;
+	}
+
+	printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
+	return -EINVAL;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_devconfig);
+
+/* s3c2410_dma_getposition
+ *
+ * returns the current transfer points for the dma source and destination
+*/
+
+int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
+{
+ 	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	if (src != NULL)
+ 		*src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
+
+ 	if (dst != NULL)
+ 		*dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
+
+ 	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_getposition);
+
+
+/* system device class */
+
+#ifdef CONFIG_PM
+
+static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
+
+	printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
+
+	if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
+		/* the dma channel is still working, which is probably
+		 * a bad thing to do over suspend/resume. We stop the
+		 * channel and assume that the client is either going to
+		 * retry after resume, or that it is broken.
+		 */
+
+		printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
+		       cp->number);
+
+		s3c2410_dma_dostop(cp);
+	}
+
+	return 0;
+}
+
+static int s3c2410_dma_resume(struct sys_device *dev)
+{
+	return 0;
+}
+
+#else
+#define s3c2410_dma_suspend NULL
+#define s3c2410_dma_resume  NULL
+#endif /* CONFIG_PM */
+
+struct sysdev_class dma_sysclass = {
+	set_kset_name("s3c24xx-dma"),
+	.suspend	= s3c2410_dma_suspend,
+	.resume		= s3c2410_dma_resume,
+};
+
+/* kmem cache implementation */
+
+static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
+{
+	memset(p, 0, sizeof(struct s3c2410_dma_buf));
+}
+
+/* initialisation code */
+
+int __init s3c24xx_dma_sysclass_init(void)
+{
+	int ret = sysdev_class_register(&dma_sysclass);
+
+	if (ret != 0)
+		printk(KERN_ERR "dma sysclass registration failed\n");
+
+	return ret;
+}
+
+core_initcall(s3c24xx_dma_sysclass_init);
+
+int __init s3c24xx_dma_sysdev_register(void)
+{
+	struct s3c2410_dma_chan *cp = s3c2410_chans;
+	int channel, ret;
+
+	for (channel = 0; channel < dma_channels; cp++, channel++) {
+		cp->dev.cls = &dma_sysclass;
+		cp->dev.id  = channel;
+		ret = sysdev_register(&cp->dev);
+
+		if (ret) {
+			printk(KERN_ERR "error registering dev for dma %d\n",
+			       channel);
+ 			return ret;
+		}
+	}
+
+	return 0;
+}
+
+late_initcall(s3c24xx_dma_sysdev_register);
+
+int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,
+			    unsigned int stride)
+{
+	struct s3c2410_dma_chan *cp;
+	int channel;
+	int ret;
+
+	printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
+
+	dma_channels = channels;
+
+	dma_base = ioremap(S3C24XX_PA_DMA, stride * channels);
+	if (dma_base == NULL) {
+		printk(KERN_ERR "dma failed to remap register block\n");
+		return -ENOMEM;
+	}
+
+	dma_kmem = kmem_cache_create("dma_desc",
+				     sizeof(struct s3c2410_dma_buf), 0,
+				     SLAB_HWCACHE_ALIGN,
+				     s3c2410_dma_cache_ctor, NULL);
+
+	if (dma_kmem == NULL) {
+		printk(KERN_ERR "dma failed to make kmem cache\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (channel = 0; channel < channels;  channel++) {
+		cp = &s3c2410_chans[channel];
+
+		memset(cp, 0, sizeof(struct s3c2410_dma_chan));
+
+		/* dma channel irqs are in order.. */
+		cp->number = channel;
+		cp->irq    = channel + irq;
+		cp->regs   = dma_base + (channel * stride);
+
+		/* point current stats somewhere */
+		cp->stats  = &cp->stats_store;
+		cp->stats_store.timeout_shortest = LONG_MAX;
+
+		/* basic channel configuration */
+
+		cp->load_timeout = 1<<18;
+
+		printk("DMA channel %d at %p, irq %d\n",
+		       cp->number, cp->regs, cp->irq);
+	}
+
+	return 0;
+
+ err:
+	kmem_cache_destroy(dma_kmem);
+	iounmap(dma_base);
+	dma_base = NULL;
+	return ret;
+}
+
+int s3c2410_dma_init(void)
+{
+	return s3c24xx_dma_init(4, IRQ_DMA0, 0x40);
+}
+
+static inline int is_channel_valid(unsigned int channel)
+{
+	return (channel & DMA_CH_VALID);
+}
+
+static struct s3c24xx_dma_order *dma_order;
+
+
+/* s3c2410_dma_map_channel()
+ *
+ * turn the virtual channel number into a real, and un-used hardware
+ * channel.
+ *
+ * first, try the dma ordering given to us by either the relevant
+ * dma code, or the board. Then just find the first usable free
+ * channel
+*/
+
+struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
+{
+	struct s3c24xx_dma_order_ch *ord = NULL;
+	struct s3c24xx_dma_map *ch_map;
+	struct s3c2410_dma_chan *dmach;
+	int ch;
+
+	if (dma_sel.map == NULL || channel > dma_sel.map_size)
+		return NULL;
+
+	ch_map = dma_sel.map + channel;
+
+	/* first, try the board mapping */
+
+	if (dma_order) {
+		ord = &dma_order->channels[channel];
+
+		for (ch = 0; ch < dma_channels; ch++) {
+			if (!is_channel_valid(ord->list[ch]))
+				continue;
+
+			if (s3c2410_chans[ord->list[ch]].in_use == 0) {
+				ch = ord->list[ch] & ~DMA_CH_VALID;
+				goto found;
+			}
+		}
+
+		if (ord->flags & DMA_CH_NEVER)
+			return NULL;
+	}
+
+	/* second, search the channel map for first free */
+
+	for (ch = 0; ch < dma_channels; ch++) {
+		if (!is_channel_valid(ch_map->channels[ch]))
+			continue;
+
+		if (s3c2410_chans[ch].in_use == 0) {
+			printk("mapped channel %d to %d\n", channel, ch);
+			break;
+		}
+	}
+
+	if (ch >= dma_channels)
+		return NULL;
+
+	/* update our channel mapping */
+
+ found:
+	dmach = &s3c2410_chans[ch];
+	dma_chan_map[channel] = dmach;
+
+	/* select the channel */
+
+	(dma_sel.select)(dmach, ch_map);
+
+	return dmach;
+}
+
+static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
+{
+	return 0;
+}
+
+int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
+{
+	struct s3c24xx_dma_map *nmap;
+	size_t map_sz = sizeof(*nmap) * sel->map_size;
+	int ptr;
+
+	nmap = kmalloc(map_sz, GFP_KERNEL);
+	if (nmap == NULL)
+		return -ENOMEM;
+
+	memcpy(nmap, sel->map, map_sz);
+	memcpy(&dma_sel, sel, sizeof(*sel));
+
+	dma_sel.map = nmap;
+
+	for (ptr = 0; ptr < sel->map_size; ptr++)
+		s3c24xx_dma_check_entry(nmap+ptr, ptr);
+
+	return 0;
+}
+
+int __init s3c24xx_dma_order_set(struct s3c24xx_dma_order *ord)
+{
+	struct s3c24xx_dma_order *nord = dma_order;
+
+	if (nord == NULL)
+		nord = kmalloc(sizeof(struct s3c24xx_dma_order), GFP_KERNEL);
+
+	if (nord == NULL) {
+		printk(KERN_ERR "no memory to store dma channel order\n");
+		return -ENOMEM;
+	}
+
+	dma_order = nord;
+	memcpy(nord, ord, sizeof(struct s3c24xx_dma_order));
+	return 0;
+}
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
new file mode 100644
index 0000000..ec3a09c
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/gpio.c
@@ -0,0 +1,188 @@
+/* linux/arch/arm/plat-s3c24xx/gpio.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX GPIO support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-gpio.h>
+
+void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
+	unsigned long mask;
+	unsigned long con;
+	unsigned long flags;
+
+	if (pin < S3C2410_GPIO_BANKB) {
+		mask = 1 << S3C2410_GPIO_OFFSET(pin);
+	} else {
+		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
+	}
+
+	switch (function) {
+	case S3C2410_GPIO_LEAVE:
+		mask = 0;
+		function = 0;
+		break;
+
+	case S3C2410_GPIO_INPUT:
+	case S3C2410_GPIO_OUTPUT:
+	case S3C2410_GPIO_SFN2:
+	case S3C2410_GPIO_SFN3:
+		if (pin < S3C2410_GPIO_BANKB) {
+			function -= 1;
+			function &= 1;
+			function <<= S3C2410_GPIO_OFFSET(pin);
+		} else {
+			function &= 3;
+			function <<= S3C2410_GPIO_OFFSET(pin)*2;
+		}
+	}
+
+	/* modify the specified register wwith IRQs off */
+
+	local_irq_save(flags);
+
+	con  = __raw_readl(base + 0x00);
+	con &= ~mask;
+	con |= function;
+
+	__raw_writel(con, base + 0x00);
+
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
+
+unsigned int s3c2410_gpio_getcfg(unsigned int pin)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
+	unsigned long val = __raw_readl(base);
+
+	if (pin < S3C2410_GPIO_BANKB) {
+		val >>= S3C2410_GPIO_OFFSET(pin);
+		val &= 1;
+		val += 1;
+	} else {
+		val >>= S3C2410_GPIO_OFFSET(pin)*2;
+		val &= 3;
+	}
+
+	return val | S3C2410_GPIO_INPUT;
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getcfg);
+
+void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
+	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+	unsigned long flags;
+	unsigned long up;
+
+	if (pin < S3C2410_GPIO_BANKB)
+		return;
+
+	local_irq_save(flags);
+
+	up = __raw_readl(base + 0x08);
+	up &= ~(1L << offs);
+	up |= to << offs;
+	__raw_writel(up, base + 0x08);
+
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_pullup);
+
+void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
+	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+	unsigned long flags;
+	unsigned long dat;
+
+	local_irq_save(flags);
+
+	dat = __raw_readl(base + 0x04);
+	dat &= ~(1 << offs);
+	dat |= to << offs;
+	__raw_writel(dat, base + 0x04);
+
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_setpin);
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
+	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+
+	return __raw_readl(base + 0x04) & (1<< offs);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getpin);
+
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+	unsigned long flags;
+	unsigned long misccr;
+
+	local_irq_save(flags);
+	misccr = __raw_readl(S3C24XX_MISCCR);
+	misccr &= ~clear;
+	misccr ^= change;
+	__raw_writel(misccr, S3C24XX_MISCCR);
+	local_irq_restore(flags);
+
+	return misccr;
+}
+
+EXPORT_SYMBOL(s3c2410_modify_misccr);
+
+int s3c2410_gpio_getirq(unsigned int pin)
+{
+	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
+		return -1;	/* not valid interrupts */
+
+	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
+		return -1;	/* not valid pin */
+
+	if (pin < S3C2410_GPF4)
+		return (pin - S3C2410_GPF0) + IRQ_EINT0;
+
+	if (pin < S3C2410_GPG0)
+		return (pin - S3C2410_GPF4) + IRQ_EINT4;
+
+	return (pin - S3C2410_GPG0) + IRQ_EINT8;
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getirq);
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
new file mode 100644
index 0000000..ce18639
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -0,0 +1,801 @@
+/* linux/arch/arm/plat-s3c24xx/irq.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Changelog:
+ *
+ *   22-Jul-2004  Ben Dooks <ben@simtec.co.uk>
+ *                Fixed compile warnings
+ *
+ *   22-Jul-2004  Roc Wu <cooloney@yahoo.com.cn>
+ *                Fixed s3c_extirq_type
+ *
+ *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
+ *                Addition of ADC/TC demux
+ *
+ *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
+ *		  Fix for set_irq_type() on low EINT numbers
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *		  Tidy up KF's patch and sort out new release
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *		  Add support for power management controls
+ *
+ *   04-Nov-2004  Ben Dooks
+ *		  Fix standard IRQ wake for EINT0..4 and RTC
+ *
+ *   22-Feb-2005  Ben Dooks
+ *		  Fixed edge-triggering on ADC IRQ
+ *
+ *   28-Jun-2005  Ben Dooks
+ *		  Mark IRQ_LCD valid
+ *
+ *   25-Jul-2005  Ben Dooks
+ *		  Split the S3C2440 IRQ code to seperate file
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
+
+/* wakeup irq control */
+
+#ifdef CONFIG_PM
+
+/* state for IRQs over sleep */
+
+/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
+ *
+ * set bit to 1 in allow bitfield to enable the wakeup settings on it
+*/
+
+unsigned long s3c_irqwake_intallow	= 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
+unsigned long s3c_irqwake_intmask	= 0xffffffffL;
+unsigned long s3c_irqwake_eintallow	= 0x0000fff0L;
+unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
+
+int
+s3c_irq_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
+
+	if (!(s3c_irqwake_intallow & irqbit))
+		return -ENOENT;
+
+	printk(KERN_INFO "wake %s for irq %d\n",
+	       state ? "enabled" : "disabled", irqno);
+
+	if (!state)
+		s3c_irqwake_intmask |= irqbit;
+	else
+		s3c_irqwake_intmask &= ~irqbit;
+
+	return 0;
+}
+
+static int
+s3c_irqext_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long bit = 1L << (irqno - EXTINT_OFF);
+
+	if (!(s3c_irqwake_eintallow & bit))
+		return -ENOENT;
+
+	printk(KERN_INFO "wake %s for irq %d\n",
+	       state ? "enabled" : "disabled", irqno);
+
+	if (!state)
+		s3c_irqwake_eintmask |= bit;
+	else
+		s3c_irqwake_eintmask &= ~bit;
+
+	return 0;
+}
+
+#else
+#define s3c_irqext_wake NULL
+#define s3c_irq_wake NULL
+#endif
+
+
+static void
+s3c_irq_mask(unsigned int irqno)
+{
+	unsigned long mask;
+
+	irqno -= IRQ_EINT0;
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	mask |= 1UL << irqno;
+	__raw_writel(mask, S3C2410_INTMSK);
+}
+
+static inline void
+s3c_irq_ack(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+
+	__raw_writel(bitval, S3C2410_SRCPND);
+	__raw_writel(bitval, S3C2410_INTPND);
+}
+
+static inline void
+s3c_irq_maskack(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long mask;
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	__raw_writel(mask|bitval, S3C2410_INTMSK);
+
+	__raw_writel(bitval, S3C2410_SRCPND);
+	__raw_writel(bitval, S3C2410_INTPND);
+}
+
+
+static void
+s3c_irq_unmask(unsigned int irqno)
+{
+	unsigned long mask;
+
+	if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
+		irqdbf2("s3c_irq_unmask %d\n", irqno);
+
+	irqno -= IRQ_EINT0;
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	mask &= ~(1UL << irqno);
+	__raw_writel(mask, S3C2410_INTMSK);
+}
+
+struct irq_chip s3c_irq_level_chip = {
+	.name		= "s3c-level",
+	.ack		= s3c_irq_maskack,
+	.mask		= s3c_irq_mask,
+	.unmask		= s3c_irq_unmask,
+	.set_wake	= s3c_irq_wake
+};
+
+static struct irq_chip s3c_irq_chip = {
+	.name		= "s3c",
+	.ack		= s3c_irq_ack,
+	.mask		= s3c_irq_mask,
+	.unmask		= s3c_irq_unmask,
+	.set_wake	= s3c_irq_wake
+};
+
+static void
+s3c_irqext_mask(unsigned int irqno)
+{
+	unsigned long mask;
+
+	irqno -= EXTINT_OFF;
+
+	mask = __raw_readl(S3C24XX_EINTMASK);
+	mask |= ( 1UL << irqno);
+	__raw_writel(mask, S3C24XX_EINTMASK);
+}
+
+static void
+s3c_irqext_ack(unsigned int irqno)
+{
+	unsigned long req;
+	unsigned long bit;
+	unsigned long mask;
+
+	bit = 1UL << (irqno - EXTINT_OFF);
+
+	mask = __raw_readl(S3C24XX_EINTMASK);
+
+	__raw_writel(bit, S3C24XX_EINTPEND);
+
+	req = __raw_readl(S3C24XX_EINTPEND);
+	req &= ~mask;
+
+	/* not sure if we should be acking the parent irq... */
+
+	if (irqno <= IRQ_EINT7 ) {
+		if ((req & 0xf0) == 0)
+			s3c_irq_ack(IRQ_EINT4t7);
+	} else {
+		if ((req >> 8) == 0)
+			s3c_irq_ack(IRQ_EINT8t23);
+	}
+}
+
+static void
+s3c_irqext_unmask(unsigned int irqno)
+{
+	unsigned long mask;
+
+	irqno -= EXTINT_OFF;
+
+	mask = __raw_readl(S3C24XX_EINTMASK);
+	mask &= ~( 1UL << irqno);
+	__raw_writel(mask, S3C24XX_EINTMASK);
+}
+
+int
+s3c_irqext_type(unsigned int irq, unsigned int type)
+{
+	void __iomem *extint_reg;
+	void __iomem *gpcon_reg;
+	unsigned long gpcon_offset, extint_offset;
+	unsigned long newvalue = 0, value;
+
+	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
+	{
+		gpcon_reg = S3C2410_GPFCON;
+		extint_reg = S3C24XX_EXTINT0;
+		gpcon_offset = (irq - IRQ_EINT0) * 2;
+		extint_offset = (irq - IRQ_EINT0) * 4;
+	}
+	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
+	{
+		gpcon_reg = S3C2410_GPFCON;
+		extint_reg = S3C24XX_EXTINT0;
+		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
+		extint_offset = (irq - (EXTINT_OFF)) * 4;
+	}
+	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
+	{
+		gpcon_reg = S3C2410_GPGCON;
+		extint_reg = S3C24XX_EXTINT1;
+		gpcon_offset = (irq - IRQ_EINT8) * 2;
+		extint_offset = (irq - IRQ_EINT8) * 4;
+	}
+	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
+	{
+		gpcon_reg = S3C2410_GPGCON;
+		extint_reg = S3C24XX_EXTINT2;
+		gpcon_offset = (irq - IRQ_EINT8) * 2;
+		extint_offset = (irq - IRQ_EINT16) * 4;
+	} else
+		return -1;
+
+	/* Set the GPIO to external interrupt mode */
+	value = __raw_readl(gpcon_reg);
+	value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
+	__raw_writel(value, gpcon_reg);
+
+	/* Set the external interrupt to pointed trigger type */
+	switch (type)
+	{
+		case IRQT_NOEDGE:
+			printk(KERN_WARNING "No edge setting!\n");
+			break;
+
+		case IRQT_RISING:
+			newvalue = S3C2410_EXTINT_RISEEDGE;
+			break;
+
+		case IRQT_FALLING:
+			newvalue = S3C2410_EXTINT_FALLEDGE;
+			break;
+
+		case IRQT_BOTHEDGE:
+			newvalue = S3C2410_EXTINT_BOTHEDGE;
+			break;
+
+		case IRQT_LOW:
+			newvalue = S3C2410_EXTINT_LOWLEV;
+			break;
+
+		case IRQT_HIGH:
+			newvalue = S3C2410_EXTINT_HILEV;
+			break;
+
+		default:
+			printk(KERN_ERR "No such irq type %d", type);
+			return -1;
+	}
+
+	value = __raw_readl(extint_reg);
+	value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
+	__raw_writel(value, extint_reg);
+
+	return 0;
+}
+
+static struct irq_chip s3c_irqext_chip = {
+	.name		= "s3c-ext",
+	.mask		= s3c_irqext_mask,
+	.unmask		= s3c_irqext_unmask,
+	.ack		= s3c_irqext_ack,
+	.set_type	= s3c_irqext_type,
+	.set_wake	= s3c_irqext_wake
+};
+
+static struct irq_chip s3c_irq_eint0t4 = {
+	.name		= "s3c-ext0",
+	.ack		= s3c_irq_ack,
+	.mask		= s3c_irq_mask,
+	.unmask		= s3c_irq_unmask,
+	.set_wake	= s3c_irq_wake,
+	.set_type	= s3c_irqext_type,
+};
+
+/* mask values for the parent registers for each of the interrupt types */
+
+#define INTMSK_UART0	 (1UL << (IRQ_UART0 - IRQ_EINT0))
+#define INTMSK_UART1	 (1UL << (IRQ_UART1 - IRQ_EINT0))
+#define INTMSK_UART2	 (1UL << (IRQ_UART2 - IRQ_EINT0))
+#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
+
+
+/* UART0 */
+
+static void
+s3c_irq_uart0_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
+}
+
+static void
+s3c_irq_uart0_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_UART0);
+}
+
+static void
+s3c_irq_uart0_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
+}
+
+static struct irq_chip s3c_irq_uart0 = {
+	.name		= "s3c-uart0",
+	.mask		= s3c_irq_uart0_mask,
+	.unmask		= s3c_irq_uart0_unmask,
+	.ack		= s3c_irq_uart0_ack,
+};
+
+/* UART1 */
+
+static void
+s3c_irq_uart1_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
+}
+
+static void
+s3c_irq_uart1_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_UART1);
+}
+
+static void
+s3c_irq_uart1_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
+}
+
+static struct irq_chip s3c_irq_uart1 = {
+	.name		= "s3c-uart1",
+	.mask		= s3c_irq_uart1_mask,
+	.unmask		= s3c_irq_uart1_unmask,
+	.ack		= s3c_irq_uart1_ack,
+};
+
+/* UART2 */
+
+static void
+s3c_irq_uart2_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
+}
+
+static void
+s3c_irq_uart2_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_UART2);
+}
+
+static void
+s3c_irq_uart2_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
+}
+
+static struct irq_chip s3c_irq_uart2 = {
+	.name		= "s3c-uart2",
+	.mask		= s3c_irq_uart2_mask,
+	.unmask		= s3c_irq_uart2_unmask,
+	.ack		= s3c_irq_uart2_ack,
+};
+
+/* ADC and Touchscreen */
+
+static void
+s3c_irq_adc_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
+}
+
+static void
+s3c_irq_adc_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
+}
+
+static void
+s3c_irq_adc_ack(unsigned int irqno)
+{
+	s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
+}
+
+static struct irq_chip s3c_irq_adc = {
+	.name		= "s3c-adc",
+	.mask		= s3c_irq_adc_mask,
+	.unmask		= s3c_irq_adc_unmask,
+	.ack		= s3c_irq_adc_ack,
+};
+
+/* irq demux for adc */
+static void s3c_irq_demux_adc(unsigned int irq,
+			      struct irq_desc *desc)
+{
+	unsigned int subsrc, submsk;
+	unsigned int offset = 9;
+	struct irq_desc *mydesc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	subsrc &= ~submsk;
+	subsrc >>= offset;
+	subsrc &= 3;
+
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_TC;
+			desc_handle_irq(IRQ_TC, mydesc);
+		}
+		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_ADC;
+			desc_handle_irq(IRQ_ADC, mydesc);
+		}
+	}
+}
+
+static void s3c_irq_demux_uart(unsigned int start)
+{
+	unsigned int subsrc, submsk;
+	unsigned int offset = start - IRQ_S3CUART_RX0;
+	struct irq_desc *desc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+		start, offset, subsrc, submsk);
+
+	subsrc &= ~submsk;
+	subsrc >>= offset;
+	subsrc &= 7;
+
+	if (subsrc != 0) {
+		desc = irq_desc + start;
+
+		if (subsrc & 1)
+			desc_handle_irq(start, desc);
+
+		desc++;
+
+		if (subsrc & 2)
+			desc_handle_irq(start+1, desc);
+
+		desc++;
+
+		if (subsrc & 4)
+			desc_handle_irq(start+2, desc);
+	}
+}
+
+/* uart demux entry points */
+
+static void
+s3c_irq_demux_uart0(unsigned int irq,
+		    struct irq_desc *desc)
+{
+	irq = irq;
+	s3c_irq_demux_uart(IRQ_S3CUART_RX0);
+}
+
+static void
+s3c_irq_demux_uart1(unsigned int irq,
+		    struct irq_desc *desc)
+{
+	irq = irq;
+	s3c_irq_demux_uart(IRQ_S3CUART_RX1);
+}
+
+static void
+s3c_irq_demux_uart2(unsigned int irq,
+		    struct irq_desc *desc)
+{
+	irq = irq;
+	s3c_irq_demux_uart(IRQ_S3CUART_RX2);
+}
+
+static void
+s3c_irq_demux_extint8(unsigned int irq,
+		      struct irq_desc *desc)
+{
+	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+	eintpnd &= ~eintmsk;
+	eintpnd &= ~0xff;	/* ignore lower irqs */
+
+	/* we may as well handle all the pending IRQs here */
+
+	while (eintpnd) {
+		irq = __ffs(eintpnd);
+		eintpnd &= ~(1<<irq);
+
+		irq += (IRQ_EINT4 - 4);
+		desc_handle_irq(irq, irq_desc + irq);
+	}
+
+}
+
+static void
+s3c_irq_demux_extint4t7(unsigned int irq,
+			struct irq_desc *desc)
+{
+	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+	eintpnd &= ~eintmsk;
+	eintpnd &= 0xff;	/* only lower irqs */
+
+	/* we may as well handle all the pending IRQs here */
+
+	while (eintpnd) {
+		irq = __ffs(eintpnd);
+		eintpnd &= ~(1<<irq);
+
+		irq += (IRQ_EINT4 - 4);
+
+		desc_handle_irq(irq, irq_desc + irq);
+	}
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save irq_save[] = {
+	SAVE_ITEM(S3C2410_INTMSK),
+	SAVE_ITEM(S3C2410_INTSUBMSK),
+};
+
+/* the extint values move between the s3c2410/s3c2440 and the s3c2412
+ * so we use an array to hold them, and to calculate the address of
+ * the register at run-time
+*/
+
+static unsigned long save_extint[3];
+static unsigned long save_eintflt[4];
+static unsigned long save_eintmask;
+
+int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+		save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
+
+	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+		save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
+
+	s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+	save_eintmask = __raw_readl(S3C24XX_EINTMASK);
+
+	return 0;
+}
+
+int s3c24xx_irq_resume(struct sys_device *dev)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+		__raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
+
+	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+		__raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
+
+	s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+	__raw_writel(save_eintmask, S3C24XX_EINTMASK);
+
+	return 0;
+}
+
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
+
+/* s3c24xx_init_irq
+ *
+ * Initialise S3C2410 IRQ system
+*/
+
+void __init s3c24xx_init_irq(void)
+{
+	unsigned long pend;
+	unsigned long last;
+	int irqno;
+	int i;
+
+	irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
+
+	/* first, clear all interrupts pending... */
+
+	last = 0;
+	for (i = 0; i < 4; i++) {
+		pend = __raw_readl(S3C24XX_EINTPEND);
+
+		if (pend == 0 || pend == last)
+			break;
+
+		__raw_writel(pend, S3C24XX_EINTPEND);
+		printk("irq: clearing pending ext status %08x\n", (int)pend);
+		last = pend;
+	}
+
+	last = 0;
+	for (i = 0; i < 4; i++) {
+		pend = __raw_readl(S3C2410_INTPND);
+
+		if (pend == 0 || pend == last)
+			break;
+
+		__raw_writel(pend, S3C2410_SRCPND);
+		__raw_writel(pend, S3C2410_INTPND);
+		printk("irq: clearing pending status %08x\n", (int)pend);
+		last = pend;
+	}
+
+	last = 0;
+	for (i = 0; i < 4; i++) {
+		pend = __raw_readl(S3C2410_SUBSRCPND);
+
+		if (pend == 0 || pend == last)
+			break;
+
+		printk("irq: clearing subpending status %08x\n", (int)pend);
+		__raw_writel(pend, S3C2410_SUBSRCPND);
+		last = pend;
+	}
+
+	/* register the main interrupts */
+
+	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
+
+	for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
+		/* set all the s3c2410 internal irqs */
+
+		switch (irqno) {
+			/* deal with the special IRQs (cascaded) */
+
+		case IRQ_EINT4t7:
+		case IRQ_EINT8t23:
+		case IRQ_UART0:
+		case IRQ_UART1:
+		case IRQ_UART2:
+		case IRQ_ADCPARENT:
+			set_irq_chip(irqno, &s3c_irq_level_chip);
+			set_irq_handler(irqno, handle_level_irq);
+			break;
+
+		case IRQ_RESERVED6:
+		case IRQ_RESERVED24:
+			/* no IRQ here */
+			break;
+
+		default:
+			//irqdbf("registering irq %d (s3c irq)\n", irqno);
+			set_irq_chip(irqno, &s3c_irq_chip);
+			set_irq_handler(irqno, handle_edge_irq);
+			set_irq_flags(irqno, IRQF_VALID);
+		}
+	}
+
+	/* setup the cascade irq handlers */
+
+	set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
+	set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
+
+	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
+	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
+	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
+	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
+
+	/* external interrupts */
+
+	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+		irqdbf("registering irq %d (ext int)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_eint0t4);
+		set_irq_handler(irqno, handle_edge_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
+		irqdbf("registering irq %d (extended s3c irq)\n", irqno);
+		set_irq_chip(irqno, &s3c_irqext_chip);
+		set_irq_handler(irqno, handle_edge_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	/* register the uart interrupts */
+
+	irqdbf("s3c2410: registering external interrupts\n");
+
+	for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
+		irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_uart0);
+		set_irq_handler(irqno, handle_level_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
+		irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_uart1);
+		set_irq_handler(irqno, handle_level_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
+		irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_uart2);
+		set_irq_handler(irqno, handle_level_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
+		irqdbf("registering irq %d (s3c adc irq)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_adc);
+		set_irq_handler(irqno, handle_edge_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	irqdbf("s3c2410: registered interrupt handlers\n");
+}
diff --git a/arch/arm/plat-s3c24xx/pm-simtec.c b/arch/arm/plat-s3c24xx/pm-simtec.c
new file mode 100644
index 0000000..bd965f2
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/pm-simtec.c
@@ -0,0 +1,66 @@
+/* linux/arch/arm/plat-s3c24xx/pm-simtec.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * Power Management helpers for Simtec S3C24XX implementations
+ *
+ * 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/device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/map.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/plat-s3c24xx/pm.h>
+
+#define COPYRIGHT ", (c) 2005 Simtec Electronics"
+
+/* pm_simtec_init
+ *
+ * enable the power management functions
+*/
+
+static __init int pm_simtec_init(void)
+{
+	unsigned long gstatus4;
+
+	/* check which machine we are running on */
+
+	if (!machine_is_bast() && !machine_is_vr1000() &&
+	    !machine_is_anubis() && !machine_is_osiris() &&
+	    !machine_is_aml_m5900())
+		return 0;
+
+	printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
+
+	gstatus4  = (__raw_readl(S3C2410_BANKCON7) & 0x3) << 30;
+	gstatus4 |= (__raw_readl(S3C2410_BANKCON6) & 0x3) << 28;
+	gstatus4 |= (__raw_readl(S3C2410_BANKSIZE) & S3C2410_BANKSIZE_MASK);
+
+	__raw_writel(gstatus4, S3C2410_GSTATUS4);
+
+	return s3c2410_pm_init();
+}
+
+arch_initcall(pm_simtec_init);
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
new file mode 100644
index 0000000..ecf68d6
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/pm.c
@@ -0,0 +1,659 @@
+/* linux/arch/arm/plat-s3c24xx/pm.c
+ *
+ * Copyright (c) 2004,2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX Power Manager (Suspend-To-RAM) support
+ *
+ * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
+ *
+ * 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
+ *
+ * Parts based on arch/arm/mach-pxa/pm.c
+ *
+ * Thanks to Dimitry Andric for debugging
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/crc32.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-irq.h>
+
+#include <asm/mach/time.h>
+
+#include <asm/plat-s3c24xx/pm.h>
+
+/* for external use */
+
+unsigned long s3c_pm_flags;
+
+#define PFX "s3c24xx-pm: "
+
+static struct sleep_save core_save[] = {
+	SAVE_ITEM(S3C2410_LOCKTIME),
+	SAVE_ITEM(S3C2410_CLKCON),
+
+	/* we restore the timings here, with the proviso that the board
+	 * brings the system up in an slower, or equal frequency setting
+	 * to the original system.
+	 *
+	 * if we cannot guarantee this, then things are going to go very
+	 * wrong here, as we modify the refresh and both pll settings.
+	 */
+
+	SAVE_ITEM(S3C2410_BWSCON),
+	SAVE_ITEM(S3C2410_BANKCON0),
+	SAVE_ITEM(S3C2410_BANKCON1),
+	SAVE_ITEM(S3C2410_BANKCON2),
+	SAVE_ITEM(S3C2410_BANKCON3),
+	SAVE_ITEM(S3C2410_BANKCON4),
+	SAVE_ITEM(S3C2410_BANKCON5),
+
+	SAVE_ITEM(S3C2410_CLKDIVN),
+	SAVE_ITEM(S3C2410_MPLLCON),
+	SAVE_ITEM(S3C2410_UPLLCON),
+	SAVE_ITEM(S3C2410_CLKSLOW),
+	SAVE_ITEM(S3C2410_REFRESH),
+};
+
+static struct sleep_save gpio_save[] = {
+	SAVE_ITEM(S3C2410_GPACON),
+	SAVE_ITEM(S3C2410_GPADAT),
+
+	SAVE_ITEM(S3C2410_GPBCON),
+	SAVE_ITEM(S3C2410_GPBDAT),
+	SAVE_ITEM(S3C2410_GPBUP),
+
+	SAVE_ITEM(S3C2410_GPCCON),
+	SAVE_ITEM(S3C2410_GPCDAT),
+	SAVE_ITEM(S3C2410_GPCUP),
+
+	SAVE_ITEM(S3C2410_GPDCON),
+	SAVE_ITEM(S3C2410_GPDDAT),
+	SAVE_ITEM(S3C2410_GPDUP),
+
+	SAVE_ITEM(S3C2410_GPECON),
+	SAVE_ITEM(S3C2410_GPEDAT),
+	SAVE_ITEM(S3C2410_GPEUP),
+
+	SAVE_ITEM(S3C2410_GPFCON),
+	SAVE_ITEM(S3C2410_GPFDAT),
+	SAVE_ITEM(S3C2410_GPFUP),
+
+	SAVE_ITEM(S3C2410_GPGCON),
+	SAVE_ITEM(S3C2410_GPGDAT),
+	SAVE_ITEM(S3C2410_GPGUP),
+
+	SAVE_ITEM(S3C2410_GPHCON),
+	SAVE_ITEM(S3C2410_GPHDAT),
+	SAVE_ITEM(S3C2410_GPHUP),
+
+	SAVE_ITEM(S3C2410_DCLKCON),
+};
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+
+#define SAVE_UART(va) \
+	SAVE_ITEM((va) + S3C2410_ULCON), \
+	SAVE_ITEM((va) + S3C2410_UCON), \
+	SAVE_ITEM((va) + S3C2410_UFCON), \
+	SAVE_ITEM((va) + S3C2410_UMCON), \
+	SAVE_ITEM((va) + S3C2410_UBRDIV)
+
+static struct sleep_save uart_save[] = {
+	SAVE_UART(S3C24XX_VA_UART0),
+	SAVE_UART(S3C24XX_VA_UART1),
+#ifndef CONFIG_CPU_S3C2400
+	SAVE_UART(S3C24XX_VA_UART2),
+#endif
+};
+
+/* debug
+ *
+ * we send the debug to printascii() to allow it to be seen if the
+ * system never wakes up from the sleep
+*/
+
+extern void printascii(const char *);
+
+void pm_dbg(const char *fmt, ...)
+{
+	va_list va;
+	char buff[256];
+
+	va_start(va, fmt);
+	vsprintf(buff, fmt, va);
+	va_end(va);
+
+	printascii(buff);
+}
+
+static void s3c2410_pm_debug_init(void)
+{
+	unsigned long tmp = __raw_readl(S3C2410_CLKCON);
+
+	/* re-start uart clocks */
+	tmp |= S3C2410_CLKCON_UART0;
+	tmp |= S3C2410_CLKCON_UART1;
+	tmp |= S3C2410_CLKCON_UART2;
+
+	__raw_writel(tmp, S3C2410_CLKCON);
+	udelay(10);
+}
+
+#define DBG(fmt...) pm_dbg(fmt)
+#else
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
+
+#define s3c2410_pm_debug_init() do { } while(0)
+
+static struct sleep_save uart_save[] = {};
+#endif
+
+#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
+
+/* suspend checking code...
+ *
+ * this next area does a set of crc checks over all the installed
+ * memory, so the system can verify if the resume was ok.
+ *
+ * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
+ * increasing it will mean that the area corrupted will be less easy to spot,
+ * and reducing the size will cause the CRC save area to grow
+*/
+
+#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
+
+static u32 crc_size;	/* size needed for the crc block */
+static u32 *crcs;	/* allocated over suspend/resume */
+
+typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
+
+/* s3c2410_pm_run_res
+ *
+ * go thorugh the given resource list, and look for system ram
+*/
+
+static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
+{
+	while (ptr != NULL) {
+		if (ptr->child != NULL)
+			s3c2410_pm_run_res(ptr->child, fn, arg);
+
+		if ((ptr->flags & IORESOURCE_MEM) &&
+		    strcmp(ptr->name, "System RAM") == 0) {
+			DBG("Found system RAM at %08lx..%08lx\n",
+			    ptr->start, ptr->end);
+			arg = (fn)(ptr, arg);
+		}
+
+		ptr = ptr->sibling;
+	}
+}
+
+static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
+{
+	s3c2410_pm_run_res(&iomem_resource, fn, arg);
+}
+
+static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
+{
+	u32 size = (u32)(res->end - res->start)+1;
+
+	size += CHECK_CHUNKSIZE-1;
+	size /= CHECK_CHUNKSIZE;
+
+	DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
+
+	*val += size * sizeof(u32);
+	return val;
+}
+
+/* s3c2410_pm_prepare_check
+ *
+ * prepare the necessary information for creating the CRCs. This
+ * must be done before the final save, as it will require memory
+ * allocating, and thus touching bits of the kernel we do not
+ * know about.
+*/
+
+static void s3c2410_pm_check_prepare(void)
+{
+	crc_size = 0;
+
+	s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
+
+	DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
+
+	crcs = kmalloc(crc_size+4, GFP_KERNEL);
+	if (crcs == NULL)
+		printk(KERN_ERR "Cannot allocated CRC save area\n");
+}
+
+static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
+{
+	unsigned long addr, left;
+
+	for (addr = res->start; addr < res->end;
+	     addr += CHECK_CHUNKSIZE) {
+		left = res->end - addr;
+
+		if (left > CHECK_CHUNKSIZE)
+			left = CHECK_CHUNKSIZE;
+
+		*val = crc32_le(~0, phys_to_virt(addr), left);
+		val++;
+	}
+
+	return val;
+}
+
+/* s3c2410_pm_check_store
+ *
+ * compute the CRC values for the memory blocks before the final
+ * sleep.
+*/
+
+static void s3c2410_pm_check_store(void)
+{
+	if (crcs != NULL)
+		s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
+}
+
+/* in_region
+ *
+ * return TRUE if the area defined by ptr..ptr+size contatins the
+ * what..what+whatsz
+*/
+
+static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
+{
+	if ((what+whatsz) < ptr)
+		return 0;
+
+	if (what > (ptr+size))
+		return 0;
+
+	return 1;
+}
+
+static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
+{
+	void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
+	unsigned long addr;
+	unsigned long left;
+	void *ptr;
+	u32 calc;
+
+	for (addr = res->start; addr < res->end;
+	     addr += CHECK_CHUNKSIZE) {
+		left = res->end - addr;
+
+		if (left > CHECK_CHUNKSIZE)
+			left = CHECK_CHUNKSIZE;
+
+		ptr = phys_to_virt(addr);
+
+		if (in_region(ptr, left, crcs, crc_size)) {
+			DBG("skipping %08lx, has crc block in\n", addr);
+			goto skip_check;
+		}
+
+		if (in_region(ptr, left, save_at, 32*4 )) {
+			DBG("skipping %08lx, has save block in\n", addr);
+			goto skip_check;
+		}
+
+		/* calculate and check the checksum */
+
+		calc = crc32_le(~0, ptr, left);
+		if (calc != *val) {
+			printk(KERN_ERR PFX "Restore CRC error at "
+			       "%08lx (%08x vs %08x)\n", addr, calc, *val);
+
+			DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
+			    addr, calc, *val);
+		}
+
+	skip_check:
+		val++;
+	}
+
+	return val;
+}
+
+/* s3c2410_pm_check_restore
+ *
+ * check the CRCs after the restore event and free the memory used
+ * to hold them
+*/
+
+static void s3c2410_pm_check_restore(void)
+{
+	if (crcs != NULL) {
+		s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
+		kfree(crcs);
+		crcs = NULL;
+	}
+}
+
+#else
+
+#define s3c2410_pm_check_prepare() do { } while(0)
+#define s3c2410_pm_check_restore() do { } while(0)
+#define s3c2410_pm_check_store()   do { } while(0)
+#endif
+
+/* helper functions to save and restore register state */
+
+void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		ptr->val = __raw_readl(ptr->reg);
+		DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
+	}
+}
+
+/* s3c2410_pm_do_restore
+ *
+ * restore the system from the given list of saved registers
+ *
+ * Note, we do not use DBG() in here, as the system may not have
+ * restore the UARTs state yet
+*/
+
+void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
+		       ptr->reg, ptr->val, __raw_readl(ptr->reg));
+
+		__raw_writel(ptr->val, ptr->reg);
+	}
+}
+
+/* s3c2410_pm_do_restore_core
+ *
+ * similar to s3c2410_pm_do_restore_core
+ *
+ * WARNING: Do not put any debug in here that may effect memory or use
+ * peripherals, as things may be changing!
+*/
+
+static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		__raw_writel(ptr->val, ptr->reg);
+	}
+}
+
+/* s3c2410_pm_show_resume_irqs
+ *
+ * print any IRQs asserted at resume time (ie, we woke from)
+*/
+
+static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
+					unsigned long mask)
+{
+	int i;
+
+	which &= ~mask;
+
+	for (i = 0; i <= 31; i++) {
+		if ((which) & (1L<<i)) {
+			DBG("IRQ %d asserted at resume\n", start+i);
+		}
+	}
+}
+
+/* s3c2410_pm_check_resume_pin
+ *
+ * check to see if the pin is configured correctly for sleep mode, and
+ * make any necessary adjustments if it is not
+*/
+
+static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
+{
+	unsigned long irqstate;
+	unsigned long pinstate;
+	int irq = s3c2410_gpio_getirq(pin);
+
+	if (irqoffs < 4)
+		irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
+	else
+		irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
+
+	pinstate = s3c2410_gpio_getcfg(pin);
+
+	if (!irqstate) {
+		if (pinstate == S3C2410_GPIO_IRQ)
+			DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
+	} else {
+		if (pinstate == S3C2410_GPIO_IRQ) {
+			DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
+			s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
+		}
+	}
+}
+
+/* s3c2410_pm_configure_extint
+ *
+ * configure all external interrupt pins
+*/
+
+static void s3c2410_pm_configure_extint(void)
+{
+	int pin;
+
+	/* for each of the external interrupts (EINT0..EINT15) we
+	 * need to check wether it is an external interrupt source,
+	 * and then configure it as an input if it is not
+	*/
+
+	for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
+		s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
+	}
+
+	for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
+		s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
+	}
+}
+
+void (*pm_cpu_prep)(void);
+void (*pm_cpu_sleep)(void);
+
+#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
+
+/* s3c2410_pm_enter
+ *
+ * central control for sleep/resume process
+*/
+
+static int s3c2410_pm_enter(suspend_state_t state)
+{
+	unsigned long regs_save[16];
+
+	/* ensure the debug is initialised (if enabled) */
+
+	s3c2410_pm_debug_init();
+
+	DBG("s3c2410_pm_enter(%d)\n", state);
+
+	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
+		printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
+		return -EINVAL;
+	}
+
+	if (state != PM_SUSPEND_MEM) {
+		printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
+		return -EINVAL;
+	}
+
+	/* check if we have anything to wake-up with... bad things seem
+	 * to happen if you suspend with no wakeup (system will often
+	 * require a full power-cycle)
+	*/
+
+	if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
+	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
+		printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
+		printk(KERN_ERR PFX "Aborting sleep\n");
+		return -EINVAL;
+	}
+
+	/* prepare check area if configured */
+
+	s3c2410_pm_check_prepare();
+
+	/* store the physical address of the register recovery block */
+
+	s3c2410_sleep_save_phys = virt_to_phys(regs_save);
+
+	DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
+
+	/* save all necessary core registers not covered by the drivers */
+
+	s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
+	s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
+	s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
+
+	/* set the irq configuration for wake */
+
+	s3c2410_pm_configure_extint();
+
+	DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
+	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
+
+	__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
+	__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
+
+	/* ack any outstanding external interrupts before we go to sleep */
+
+	__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
+	__raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
+	__raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
+
+	/* call cpu specific preperation */
+
+	pm_cpu_prep();
+
+	/* flush cache back to ram */
+
+	flush_cache_all();
+
+	s3c2410_pm_check_store();
+
+	/* send the cpu to sleep... */
+
+	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
+
+	/* s3c2410_cpu_save will also act as our return point from when
+	 * we resume as it saves its own register state, so use the return
+	 * code to differentiate return from save and return from sleep */
+
+	if (s3c2410_cpu_save(regs_save) == 0) {
+		flush_cache_all();
+		pm_cpu_sleep();
+	}
+
+	/* restore the cpu state */
+
+	cpu_init();
+
+	/* restore the system state */
+
+	s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+	s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
+	s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
+
+	s3c2410_pm_debug_init();
+
+	/* check what irq (if any) restored the system */
+
+	DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
+	    __raw_readl(S3C2410_SRCPND),
+	    __raw_readl(S3C2410_EINTPEND));
+
+	s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
+				    s3c_irqwake_intmask);
+
+	s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
+				    s3c_irqwake_eintmask);
+
+	DBG("post sleep, preparing to return\n");
+
+	s3c2410_pm_check_restore();
+
+	/* ok, let's return from sleep */
+
+	DBG("S3C2410 PM Resume (post-restore)\n");
+	return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int s3c2410_pm_prepare(suspend_state_t state)
+{
+	return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static int s3c2410_pm_finish(suspend_state_t state)
+{
+	return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops s3c2410_pm_ops = {
+	.pm_disk_mode	= PM_DISK_FIRMWARE,
+	.prepare	= s3c2410_pm_prepare,
+	.enter		= s3c2410_pm_enter,
+	.finish		= s3c2410_pm_finish,
+};
+
+/* s3c2410_pm_init
+ *
+ * Attach the power management functions. This should be called
+ * from the board specific initialisation if the board supports
+ * it.
+*/
+
+int __init s3c2410_pm_init(void)
+{
+	printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
+
+	pm_set_ops(&s3c2410_pm_ops);
+	return 0;
+}
diff --git a/arch/arm/plat-s3c24xx/s3c244x-irq.c b/arch/arm/plat-s3c24xx/s3c244x-irq.c
new file mode 100644
index 0000000..a0e39d8
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/s3c244x-irq.c
@@ -0,0 +1,146 @@
+/* linux/arch/arm/plat-s3c24xx/s3c244x-irq.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
+
+/* camera irq */
+
+static void s3c_irq_demux_cam(unsigned int irq,
+			      struct irq_desc *desc)
+{
+	unsigned int subsrc, submsk;
+	struct irq_desc *mydesc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	subsrc &= ~submsk;
+	subsrc >>= 11;
+	subsrc &= 3;
+
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_S3C2440_CAM_C;
+			desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc);
+		}
+		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_S3C2440_CAM_P;
+			desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc);
+		}
+	}
+}
+
+#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
+
+static void
+s3c_irq_cam_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
+}
+
+static void
+s3c_irq_cam_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_CAM);
+}
+
+static void
+s3c_irq_cam_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
+}
+
+static struct irq_chip s3c_irq_cam = {
+	.mask	    = s3c_irq_cam_mask,
+	.unmask	    = s3c_irq_cam_unmask,
+	.ack	    = s3c_irq_cam_ack,
+};
+
+static int s3c244x_irq_add(struct sys_device *sysdev)
+{
+	unsigned int irqno;
+
+	set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
+	set_irq_handler(IRQ_NFCON, handle_level_irq);
+	set_irq_flags(IRQ_NFCON, IRQF_VALID);
+
+	/* add chained handler for camera */
+
+	set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
+	set_irq_handler(IRQ_CAM, handle_level_irq);
+	set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
+
+	for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
+		set_irq_chip(irqno, &s3c_irq_cam);
+		set_irq_handler(irqno, handle_level_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2440_irq_driver = {
+	.add		= s3c244x_irq_add,
+	.suspend	= s3c24xx_irq_suspend,
+	.resume		= s3c24xx_irq_resume,
+};
+
+static int s3c2440_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
+}
+
+arch_initcall(s3c2440_irq_init);
+
+static struct sysdev_driver s3c2442_irq_driver = {
+	.add		= s3c244x_irq_add,
+	.suspend	= s3c24xx_irq_suspend,
+	.resume		= s3c24xx_irq_resume,
+};
+
+
+static int s3c2442_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_irq_driver);
+}
+
+arch_initcall(s3c2442_irq_init);
diff --git a/arch/arm/plat-s3c24xx/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c
new file mode 100644
index 0000000..767f2e9
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/s3c244x.c
@@ -0,0 +1,184 @@
+/* linux/arch/arm/plat-s3c24xx/s3c244x.c
+ *
+ * Copyright (c) 2004-2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 and S3C2442 Mobile CPU support (not S3C2443)
+ *
+ * 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/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/clk.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-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include "s3c244x.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+
+static struct map_desc s3c244x_iodesc[] __initdata = {
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(WATCHDOG),
+	IODESC_ENT(LCD),
+};
+
+/* uart initialisation */
+
+void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
+}
+
+void __init s3c244x_map_io(struct map_desc *mach_desc, int size)
+{
+	/* register our io-tables */
+
+	iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));
+	iotable_init(mach_desc, size);
+
+	/* rename any peripherals used differing from the s3c2410 */
+
+	s3c_device_i2c.name  = "s3c2440-i2c";
+	s3c_device_nand.name = "s3c2440-nand";
+	s3c_device_usbgadget.name = "s3c2440-usbgadget";
+}
+
+void __init s3c244x_init_clocks(int xtal)
+{
+	unsigned long clkdiv;
+	unsigned long camdiv;
+	unsigned long hclk, fclk, pclk;
+	int hdiv = 1;
+
+	/* now we've got our machine bits initialised, work out what
+	 * clocks we've got */
+
+	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
+
+	clkdiv = __raw_readl(S3C2410_CLKDIVN);
+	camdiv = __raw_readl(S3C2440_CAMDIVN);
+
+	/* work out clock scalings */
+
+	switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
+	case S3C2440_CLKDIVN_HDIVN_1:
+		hdiv = 1;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_2:
+		hdiv = 2;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_4_8:
+		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_3_6:
+		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
+		break;
+	}
+
+	hclk = fclk / hdiv;
+	pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
+
+	/* print brief summary of clocks, etc */
+
+	printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+	/* initialise the clocks here, to allow other things like the
+	 * console to use them, and to add new ones after the initialisation
+	 */
+
+	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+	s3c2410_baseclk_add();
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save s3c244x_sleep[] = {
+	SAVE_ITEM(S3C2440_DSC0),
+	SAVE_ITEM(S3C2440_DSC1),
+	SAVE_ITEM(S3C2440_GPJDAT),
+	SAVE_ITEM(S3C2440_GPJCON),
+	SAVE_ITEM(S3C2440_GPJUP)
+};
+
+static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
+{
+	s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+	return 0;
+}
+
+static int s3c244x_resume(struct sys_device *dev)
+{
+	s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+	return 0;
+}
+
+#else
+#define s3c244x_suspend NULL
+#define s3c244x_resume  NULL
+#endif
+
+/* Since the S3C2442 and S3C2440 share  items, put both sysclasses here */
+
+struct sysdev_class s3c2440_sysclass = {
+	set_kset_name("s3c2440-core"),
+	.suspend	= s3c244x_suspend,
+	.resume		= s3c244x_resume
+};
+
+struct sysdev_class s3c2442_sysclass = {
+	set_kset_name("s3c2442-core"),
+	.suspend	= s3c244x_suspend,
+	.resume		= s3c244x_resume
+};
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2440 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+static int __init s3c2440_core_init(void)
+{
+	return sysdev_class_register(&s3c2440_sysclass);
+}
+
+core_initcall(s3c2440_core_init);
+
+static int __init s3c2442_core_init(void)
+{
+	return sysdev_class_register(&s3c2442_sysclass);
+}
+
+core_initcall(s3c2442_core_init);
diff --git a/arch/arm/plat-s3c24xx/s3c244x.h b/arch/arm/plat-s3c24xx/s3c244x.h
new file mode 100644
index 0000000..f8ed176
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/s3c244x.h
@@ -0,0 +1,25 @@
+/* linux/arch/arm/plat-s3c24xx/s3c244x.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2440 and S3C2442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+
+extern void s3c244x_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c244x_init_clocks(int xtal);
+
+#else
+#define s3c244x_init_clocks NULL
+#define s3c244x_init_uarts NULL
+#define s3c244x_map_io NULL
+#endif
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
new file mode 100644
index 0000000..435349d
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/sleep.S
@@ -0,0 +1,157 @@
+/* linux/arch/arm/mach-s3c2410/sleep.S
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Power Manager (Suspend-To-RAM) support
+ *
+ * Based on PXA/SA1100 sleep code by:
+ *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ *	Cliff Brake, (c) 2001
+ *
+ * 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/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+#include <asm/arch/map.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-serial.h>
+
+/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
+ * reset the UART configuration, only enable if you really need this!
+*/
+//#define CONFIG_DEBUG_RESUME
+
+	.text
+
+	/* s3c2410_cpu_save
+	 *
+	 * save enough of the CPU state to allow us to re-start
+	 * pm.c code. as we store items like the sp/lr, we will
+	 * end up returning from this function when the cpu resumes
+	 * so the return value is set to mark this.
+	 *
+	 * This arangement means we avoid having to flush the cache
+	 * from this code.
+	 *
+	 * entry:
+	 *	r0 = pointer to save block
+	 *
+	 * exit:
+	 *	r0 = 0 => we stored everything
+	 *	     1 => resumed from sleep
+	*/
+
+ENTRY(s3c2410_cpu_save)
+	stmfd	sp!, { r4 - r12, lr }
+
+	@@ store co-processor registers
+
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ translation table base address
+	mrc	p15, 0, r7, c1, c0, 0	@ control register
+
+	stmia	r0, { r4 - r13 }
+
+	mov	r0, #0
+	ldmfd	sp, { r4 - r12, pc }
+
+	@@ return to the caller, after having the MMU
+	@@ turned on, this restores the last bits from the
+	@@ stack
+resume_with_mmu:
+	mov	r0, #1
+	ldmfd	sp!, { r4 - r12, pc }
+
+	.ltorg
+
+	@@ the next bits sit in the .data segment, even though they
+	@@ happen to be code... the s3c2410_sleep_save_phys needs to be
+	@@ accessed by the resume code before it can restore the MMU.
+	@@ This means that the variable has to be close enough for the
+	@@ code to read it... since the .text segment needs to be RO,
+	@@ the data segment can be the only place to put this code.
+
+	.data
+
+	.global	s3c2410_sleep_save_phys
+s3c2410_sleep_save_phys:
+	.word	0
+
+	/* s3c2410_cpu_resume
+	 *
+	 * resume code entry for bootloader to call
+	 *
+	 * we must put this code here in the data segment as we have no
+	 * other way of restoring the stack pointer after sleep, and we
+	 * must not write to the code segment (code is read-only)
+	*/
+
+ENTRY(s3c2410_cpu_resume)
+	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+	msr	cpsr_c, r0
+
+	@@ load UART to allow us to print the two characters for
+	@@ resume debug
+
+	mov	r2, #S3C24XX_PA_UART & 0xff000000
+	orr	r2, r2, #S3C24XX_PA_UART & 0xff000
+
+#if 0
+	/* SMDK2440 LED set */
+	mov	r14, #S3C24XX_PA_GPIO
+	ldr	r12, [ r14, #0x54 ]
+	bic	r12, r12, #3<<4
+	orr	r12, r12, #1<<7
+	str	r12, [ r14, #0x54 ]
+#endif
+
+#ifdef CONFIG_DEBUG_RESUME
+	mov	r3, #'L'
+	strb	r3, [ r2, #S3C2410_UTXH ]
+1001:
+	ldrb	r14, [ r3, #S3C2410_UTRSTAT ]
+	tst	r14, #S3C2410_UTRSTAT_TXE
+	beq	1001b
+#endif /* CONFIG_DEBUG_RESUME */
+
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c7, 0		@@ invalidate I & D TLBs
+	mcr	p15, 0, r1, c7, c7, 0		@@ invalidate I & D caches
+
+	ldr	r0, s3c2410_sleep_save_phys	@ address of restore block
+	ldmia	r0, { r4 - r13 }
+
+	mcr	p15, 0, r4, c13, c0, 0		@ PID
+	mcr	p15, 0, r5, c3, c0, 0		@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0		@ translation table base
+
+#ifdef CONFIG_DEBUG_RESUME
+	mov	r3, #'R'
+	strb	r3, [ r2, #S3C2410_UTXH ]
+#endif
+
+	ldr	r2, =resume_with_mmu
+	mcr	p15, 0, r7, c1, c0, 0		@ turn on MMU, etc
+	nop					@ second-to-last before mmu
+	mov	pc, r2				@ go back to virtual address
+
+	.ltorg
diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c
new file mode 100644
index 0000000..c523d1c
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/time.c
@@ -0,0 +1,262 @@
+/* linux/arch/arm/plat-s3c24xx/time.c
+ *
+ * Copyright (C) 2003-2005 Simtec Electronics
+ *	Ben Dooks, <ben@simtec.co.uk>
+ *
+ * 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/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/arch/map.h>
+#include <asm/arch/regs-timer.h>
+#include <asm/arch/regs-irq.h>
+#include <asm/mach/time.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+static unsigned long timer_startval;
+static unsigned long timer_usec_ticks;
+
+#define TIMER_USEC_SHIFT 16
+
+/* we use the shifted arithmetic to work out the ratio of timer ticks
+ * to usecs, as often the peripheral clock is not a nice even multiple
+ * of 1MHz.
+ *
+ * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok
+ * for the current HZ value of 200 without producing overflows.
+ *
+ * Original patch by Dimitry Andric, updated by Ben Dooks
+*/
+
+
+/* timer_mask_usec_ticks
+ *
+ * given a clock and divisor, make the value to pass into timer_ticks_to_usec
+ * to scale the ticks into usecs
+*/
+
+static inline unsigned long
+timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk)
+{
+	unsigned long den = pclk / 1000;
+
+	return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den;
+}
+
+/* timer_ticks_to_usec
+ *
+ * convert timer ticks to usec.
+*/
+
+static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
+{
+	unsigned long res;
+
+	res = ticks * timer_usec_ticks;
+	res += 1 << (TIMER_USEC_SHIFT - 4);	/* round up slightly */
+
+	return res >> TIMER_USEC_SHIFT;
+}
+
+/***
+ * Returns microsecond  since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ * IRQs are disabled before entering here from do_gettimeofday()
+ */
+
+#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0))
+
+static unsigned long s3c2410_gettimeoffset (void)
+{
+	unsigned long tdone;
+	unsigned long irqpend;
+	unsigned long tval;
+
+	/* work out how many ticks have gone since last timer interrupt */
+
+        tval =  __raw_readl(S3C2410_TCNTO(4));
+	tdone = timer_startval - tval;
+
+	/* check to see if there is an interrupt pending */
+
+	irqpend = __raw_readl(S3C2410_SRCPND);
+	if (irqpend & SRCPND_TIMER4) {
+		/* re-read the timer, and try and fix up for the missed
+		 * interrupt. Note, the interrupt may go off before the
+		 * timer has re-loaded from wrapping.
+		 */
+
+		tval =  __raw_readl(S3C2410_TCNTO(4));
+		tdone = timer_startval - tval;
+
+		if (tval != 0)
+			tdone += timer_startval;
+	}
+
+	return timer_ticks_to_usec(tdone);
+}
+
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+s3c2410_timer_interrupt(int irq, void *dev_id)
+{
+	write_seqlock(&xtime_lock);
+	timer_tick();
+	write_sequnlock(&xtime_lock);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction s3c2410_timer_irq = {
+	.name		= "S3C2410 Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER,
+	.handler	= s3c2410_timer_interrupt,
+};
+
+#define use_tclk1_12() ( \
+	machine_is_bast()	|| \
+	machine_is_vr1000()	|| \
+	machine_is_anubis()	|| \
+	machine_is_osiris() )
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ *
+ * Currently we only use timer4, as it is the only timer which has no
+ * other function that can be exploited externally
+ */
+static void s3c2410_timer_setup (void)
+{
+	unsigned long tcon;
+	unsigned long tcnt;
+	unsigned long tcfg1;
+	unsigned long tcfg0;
+
+	tcnt = 0xffff;  /* default value for tcnt */
+
+	/* read the current timer configuration bits */
+
+	tcon = __raw_readl(S3C2410_TCON);
+	tcfg1 = __raw_readl(S3C2410_TCFG1);
+	tcfg0 = __raw_readl(S3C2410_TCFG0);
+
+	/* configure the system for whichever machine is in use */
+
+	if (use_tclk1_12()) {
+		/* timer is at 12MHz, scaler is 1 */
+		timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
+		tcnt = 12000000 / HZ;
+
+		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
+		tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
+	} else {
+		unsigned long pclk;
+		struct clk *clk;
+
+		/* for the h1940 (and others), we use the pclk from the core
+		 * to generate the timer values. since values around 50 to
+		 * 70MHz are not values we can directly generate the timer
+		 * value from, we need to pre-scale and divide before using it.
+		 *
+		 * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz
+		 * (8.45 ticks per usec)
+		 */
+
+		/* this is used as default if no other timer can be found */
+
+		clk = clk_get(NULL, "timers");
+		if (IS_ERR(clk))
+			panic("failed to get clock for system timer");
+
+		clk_enable(clk);
+
+		pclk = clk_get_rate(clk);
+
+		/* configure clock tick */
+
+		timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
+
+		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
+		tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
+
+		tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
+		tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
+
+		tcnt = (pclk / 6) / HZ;
+	}
+
+	/* timers reload after counting zero, so reduce the count by 1 */
+
+	tcnt--;
+
+	printk("timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n",
+	       tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks);
+
+	/* check to see if timer is within 16bit range... */
+	if (tcnt > 0xffff) {
+		panic("setup_timer: HZ is too small, cannot configure timer!");
+		return;
+	}
+
+	__raw_writel(tcfg1, S3C2410_TCFG1);
+	__raw_writel(tcfg0, S3C2410_TCFG0);
+
+	timer_startval = tcnt;
+	__raw_writel(tcnt, S3C2410_TCNTB(4));
+
+	/* ensure timer is stopped... */
+
+	tcon &= ~(7<<20);
+	tcon |= S3C2410_TCON_T4RELOAD;
+	tcon |= S3C2410_TCON_T4MANUALUPD;
+
+	__raw_writel(tcon, S3C2410_TCON);
+	__raw_writel(tcnt, S3C2410_TCNTB(4));
+	__raw_writel(tcnt, S3C2410_TCMPB(4));
+
+	/* start the timer running */
+	tcon |= S3C2410_TCON_T4START;
+	tcon &= ~S3C2410_TCON_T4MANUALUPD;
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void __init s3c2410_timer_init (void)
+{
+	s3c2410_timer_setup();
+	setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
+}
+
+struct sys_timer s3c24xx_timer = {
+	.init		= s3c2410_timer_init,
+	.offset		= s3c2410_gettimeoffset,
+	.resume		= s3c2410_timer_setup
+};
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index 74eba8b..989113d 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -60,6 +60,10 @@
 config GENERIC_BUST_SPINLOCK
 	bool
 
+config ZONE_DMA
+	bool
+	default y
+
 config GENERIC_ISA_DMA
 	bool
 
diff --git a/arch/arm26/kernel/ecard.c b/arch/arm26/kernel/ecard.c
index 9dbc1724..e2bcefc 100644
--- a/arch/arm26/kernel/ecard.c
+++ b/arch/arm26/kernel/ecard.c
@@ -665,7 +665,7 @@
 		ec->fiqmask = 4;
 	}
 
-	for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
+	for (i = 0; i < ARRAY_SIZE(blacklist); i++)
 		if (blacklist[i].manufacturer == ec->cid.manufacturer &&
 		    blacklist[i].product == ec->cid.product) {
 			ec->card_desc = blacklist[i].type;
diff --git a/arch/arm26/kernel/setup.c b/arch/arm26/kernel/setup.c
index 466ddb5..0e006c6 100644
--- a/arch/arm26/kernel/setup.c
+++ b/arch/arm26/kernel/setup.c
@@ -80,7 +80,7 @@
 static struct meminfo meminfo __initdata = { 0, };
 static struct proc_info_item proc_info;
 static const char *machine_name;
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 
@@ -492,8 +492,8 @@
 	init_mm.end_data   = (unsigned long) &_edata;
 	init_mm.brk	   = (unsigned long) &_end;
 
-	memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 	parse_cmdline(&meminfo, cmdline_p, from);
 	bootmem_init(&meminfo);
 	paging_init(&meminfo);
diff --git a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c
index 1206469..0f1d57f 100644
--- a/arch/arm26/kernel/time.c
+++ b/arch/arm26/kernel/time.c
@@ -89,14 +89,6 @@
         return (offset + LATCH/2) / LATCH;
 }
 
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
 static unsigned long next_rtc_update;
 
 /*
diff --git a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
index ca61ec8..046a850 100644
--- a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
+++ b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
@@ -46,10 +46,12 @@
 		__con_initcall_start = .;
 			*(.con_initcall.init)
 		__con_initcall_end = .;
+#ifdef CONFIG_BLK_DEV_INITRD
 		. = ALIGN(32);
 		__initramfs_start = .;
 			usr/built-in.o(.init.ramfs)
 		__initramfs_end = .;
+#endif
 		. = ALIGN(32768);
 		__init_end = .;
 	}
diff --git a/arch/arm26/kernel/vmlinux-arm26.lds.in b/arch/arm26/kernel/vmlinux-arm26.lds.in
index d1d3418..1d2949e 100644
--- a/arch/arm26/kernel/vmlinux-arm26.lds.in
+++ b/arch/arm26/kernel/vmlinux-arm26.lds.in
@@ -47,10 +47,12 @@
 		__con_initcall_start = .;
 			*(.con_initcall.init)
 		__con_initcall_end = .;
+#ifdef CONFIG_BLK_DEV_INITRD
 		. = ALIGN(32);
 		__initramfs_start = .;
 			usr/built-in.o(.init.ramfs)
 		__initramfs_end = .;
+#endif
 		. = ALIGN(32768);
 		__init_end = .;
 	}
diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile
index df94994..8e09922 100644
--- a/arch/avr32/boards/atstk1000/Makefile
+++ b/arch/avr32/boards/atstk1000/Makefile
@@ -1,2 +1,2 @@
-obj-y				+= setup.o spi.o flash.o
+obj-y				+= setup.o flash.o
 obj-$(CONFIG_BOARD_ATSTK1002)	+= atstk1002.o
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index 32b361f..5974768 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -14,11 +14,17 @@
 #include <linux/platform_device.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/spi/spi.h>
 
 #include <asm/io.h>
 #include <asm/setup.h>
+#include <asm/arch/at32ap7000.h>
 #include <asm/arch/board.h>
 #include <asm/arch/init.h>
+#include <asm/arch/portmux.h>
+
+
+#define	SW2_DEFAULT		/* MMCI and UART_A available */
 
 struct eth_addr {
 	u8 addr[6];
@@ -29,6 +35,15 @@
 static struct eth_platform_data __initdata eth_data[2];
 extern struct lcdc_platform_data atstk1000_fb0_data;
 
+static struct spi_board_info spi0_board_info[] __initdata = {
+	{
+		/* QVGA display */
+		.modalias	= "ltv350qv",
+		.max_speed_hz	= 16000000,
+		.chip_select	= 1,
+	},
+};
+
 /*
  * The next two functions should go away as the boot loader is
  * supposed to initialize the macb address registers with a valid
@@ -86,24 +101,53 @@
 
 void __init setup_board(void)
 {
-	at32_map_usart(1, 0);	/* /dev/ttyS0 */
-	at32_map_usart(2, 1);	/* /dev/ttyS1 */
-	at32_map_usart(3, 2);	/* /dev/ttyS2 */
+#ifdef	SW2_DEFAULT
+	at32_map_usart(1, 0);	/* USART 1/A: /dev/ttyS0, DB9 */
+#else
+	at32_map_usart(0, 1);	/* USART 0/B: /dev/ttyS1, IRDA */
+#endif
+	/* USART 2/unused: expansion connector */
+	at32_map_usart(3, 2);	/* USART 3/C: /dev/ttyS2, DB9 */
 
 	at32_setup_serial_console(0);
 }
 
 static int __init atstk1002_init(void)
 {
+	/*
+	 * ATSTK1000 uses 32-bit SDRAM interface. Reserve the
+	 * SDRAM-specific pins so that nobody messes with them.
+	 */
+	at32_reserve_pin(GPIO_PIN_PE(0));	/* DATA[16]	*/
+	at32_reserve_pin(GPIO_PIN_PE(1));	/* DATA[17]	*/
+	at32_reserve_pin(GPIO_PIN_PE(2));	/* DATA[18]	*/
+	at32_reserve_pin(GPIO_PIN_PE(3));	/* DATA[19]	*/
+	at32_reserve_pin(GPIO_PIN_PE(4));	/* DATA[20]	*/
+	at32_reserve_pin(GPIO_PIN_PE(5));	/* DATA[21]	*/
+	at32_reserve_pin(GPIO_PIN_PE(6));	/* DATA[22]	*/
+	at32_reserve_pin(GPIO_PIN_PE(7));	/* DATA[23]	*/
+	at32_reserve_pin(GPIO_PIN_PE(8));	/* DATA[24]	*/
+	at32_reserve_pin(GPIO_PIN_PE(9));	/* DATA[25]	*/
+	at32_reserve_pin(GPIO_PIN_PE(10));	/* DATA[26]	*/
+	at32_reserve_pin(GPIO_PIN_PE(11));	/* DATA[27]	*/
+	at32_reserve_pin(GPIO_PIN_PE(12));	/* DATA[28]	*/
+	at32_reserve_pin(GPIO_PIN_PE(13));	/* DATA[29]	*/
+	at32_reserve_pin(GPIO_PIN_PE(14));	/* DATA[30]	*/
+	at32_reserve_pin(GPIO_PIN_PE(15));	/* DATA[31]	*/
+	at32_reserve_pin(GPIO_PIN_PE(26));	/* SDCS		*/
+
 	at32_add_system_devices();
 
+#ifdef	SW2_DEFAULT
 	at32_add_device_usart(0);
+#else
 	at32_add_device_usart(1);
+#endif
 	at32_add_device_usart(2);
 
 	set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
 
-	at32_add_device_spi(0);
+	at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
 	at32_add_device_lcdc(0, &atstk1000_fb0_data);
 
 	return 0;
diff --git a/arch/avr32/boards/atstk1000/spi.c b/arch/avr32/boards/atstk1000/spi.c
deleted file mode 100644
index 567726c..0000000
--- a/arch/avr32/boards/atstk1000/spi.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * ATSTK1000 SPI devices
- *
- * Copyright (C) 2005 Atmel Norway
- *
- * 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/device.h>
-#include <linux/spi/spi.h>
-
-static struct spi_board_info spi_board_info[] __initdata = {
-	{
-		.modalias	= "ltv350qv",
-		.max_speed_hz	= 16000000,
-		.bus_num	= 0,
-		.chip_select	= 1,
-	},
-};
-
-static int board_init_spi(void)
-{
-	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
-	return 0;
-}
-arch_initcall(board_init_spi);
diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c
index 342452b..2e72fd2 100644
--- a/arch/avr32/kernel/cpu.c
+++ b/arch/avr32/kernel/cpu.c
@@ -9,6 +9,7 @@
 #include <linux/sysdev.h>
 #include <linux/seq_file.h>
 #include <linux/cpu.h>
+#include <linux/module.h>
 #include <linux/percpu.h>
 #include <linux/param.h>
 #include <linux/errno.h>
diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c
index 856f354..fd31124 100644
--- a/arch/avr32/kernel/irq.c
+++ b/arch/avr32/kernel/irq.c
@@ -57,6 +57,7 @@
 		seq_printf(p, "%3d: ", i);
 		for_each_online_cpu(cpu)
 			seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+		seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-");
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
index a342116..a1a7c3c 100644
--- a/arch/avr32/kernel/setup.c
+++ b/arch/avr32/kernel/setup.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
+#include <linux/kernel.h>
 
 #include <asm/sections.h>
 #include <asm/processor.h>
@@ -44,7 +45,7 @@
 };
 EXPORT_SYMBOL(boot_cpu_data);
 
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 /*
  * Should be more than enough, but if you have a _really_ complex
@@ -174,8 +175,7 @@
 	 * Copy the data so the bootmem init code doesn't need to care
 	 * about it.
 	 */
-	if (mem_range_next_free >=
-	    (sizeof(mem_range_cache) / sizeof(mem_range_cache[0])))
+	if (mem_range_next_free >= ARRAY_SIZE(mem_range_cache))
 		panic("Physical memory map too complex!\n");
 
 	new = &mem_range_cache[mem_range_next_free++];
@@ -202,7 +202,7 @@
 
 static int __init parse_tag_cmdline(struct tag *tag)
 {
-	strlcpy(saved_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
 	return 0;
 }
 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
@@ -294,7 +294,7 @@
 	init_mm.end_data = (unsigned long) &_edata;
 	init_mm.brk = (unsigned long) &_end;
 
-	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 	parse_early_param();
 
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
index db8f8b5..7c27958 100644
--- a/arch/avr32/kernel/syscall_table.S
+++ b/arch/avr32/kernel/syscall_table.S
@@ -8,14 +8,6 @@
  * published by the Free Software Foundation.
  */
 
-#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
-#define sys_nfsservctl sys_ni_syscall
-#endif
-
-#if !defined(CONFIG_SYSV_IPC)
-# define sys_ipc	sys_ni_syscall
-#endif
-
 	.section .rodata,"a",@progbits
 	.type	sys_call_table,@object
 	.global	sys_call_table
@@ -129,7 +121,7 @@
 	.long	sys_getitimer		/* 105 */
 	.long	sys_swapoff
 	.long	sys_sysinfo
-	.long	sys_ipc
+	.long	sys_ni_syscall		/* was sys_ipc briefly */
 	.long	sys_sendfile
 	.long	sys_setdomainname	/* 110 */
 	.long	sys_newuname
@@ -287,4 +279,16 @@
 	.long	sys_tee
 	.long	sys_vmsplice
 	.long	__sys_epoll_pwait	/* 265 */
+	.long	sys_msgget
+	.long	sys_msgsnd
+	.long	sys_msgrcv
+	.long	sys_msgctl
+	.long	sys_semget		/* 270 */
+	.long	sys_semop
+	.long	sys_semctl
+	.long	sys_semtimedop
+	.long	sys_shmat
+	.long	sys_shmget		/* 275 */
+	.long	sys_shmdt
+	.long	sys_shmctl
 	.long	sys_ni_syscall		/* r8 is saturated at nr_syscalls */
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
index 5a247ba..c10833f 100644
--- a/arch/avr32/kernel/time.c
+++ b/arch/avr32/kernel/time.c
@@ -37,7 +37,7 @@
 	.read		= read_cycle_count,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift		= 16,
-	.is_continuous	= 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 /*
@@ -110,15 +110,6 @@
 }
 
 /*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-	/* There must be better ways...? */
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
-/*
  * local_timer_interrupt() does profiling and process accounting on a
  * per-CPU basis.
  *
diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.c
index 5c4424e..ef13b7c7 100644
--- a/arch/avr32/kernel/vmlinux.lds.c
+++ b/arch/avr32/kernel/vmlinux.lds.c
@@ -46,10 +46,12 @@
 		__security_initcall_start = .;
 			*(.security_initcall.init)
 		__security_initcall_end = .;
+#ifdef CONFIG_BLK_DEV_INITRD
 		. = ALIGN(32);
 		__initramfs_start = .;
 			*(.init.ramfs)
 		__initramfs_end = .;
+#endif
 		. = ALIGN(4096);
 		__init_end = .;
 	}
diff --git a/arch/avr32/lib/libgcc.h b/arch/avr32/lib/libgcc.h
deleted file mode 100644
index 5a091b5..0000000
--- a/arch/avr32/lib/libgcc.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Definitions for various functions 'borrowed' from gcc-3.4.3 */
-
-#define BITS_PER_UNIT	8
-
-typedef		 int QItype	__attribute__ ((mode (QI)));
-typedef unsigned int UQItype	__attribute__ ((mode (QI)));
-typedef		 int HItype	__attribute__ ((mode (HI)));
-typedef unsigned int UHItype	__attribute__ ((mode (HI)));
-typedef 	 int SItype	__attribute__ ((mode (SI)));
-typedef unsigned int USItype	__attribute__ ((mode (SI)));
-typedef		 int DItype	__attribute__ ((mode (DI)));
-typedef unsigned int UDItype	__attribute__ ((mode (DI)));
-typedef 	float SFtype	__attribute__ ((mode (SF)));
-typedef		float DFtype	__attribute__ ((mode (DF)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
-#define Wtype	SItype
-#define UWtype	USItype
-#define HWtype	SItype
-#define UHWtype	USItype
-#define DWtype	DItype
-#define UDWtype	UDItype
-#define __NW(a,b)	__ ## a ## si ## b
-#define __NDW(a,b)	__ ## a ## di ## b
-
-struct DWstruct {Wtype high, low;};
-
-typedef union
-{
-  struct DWstruct s;
-  DWtype ll;
-} DWunion;
diff --git a/arch/avr32/lib/longlong.h b/arch/avr32/lib/longlong.h
deleted file mode 100644
index cd5e369..0000000
--- a/arch/avr32/lib/longlong.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
-   Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000
-   Free Software Foundation, Inc.
-
-   This definition file 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 definition file 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.  */
-
-/* Borrowed from gcc-3.4.3 */
-
-#define __BITS4 (W_TYPE_SIZE / 4)
-#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
-#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
-
-#define count_leading_zeros(count, x) ((count) = __builtin_clz(x))
-
-#define __udiv_qrnnd_c(q, r, n1, n0, d) \
-  do {									\
-    UWtype __d1, __d0, __q1, __q0;					\
-    UWtype __r1, __r0, __m;						\
-    __d1 = __ll_highpart (d);						\
-    __d0 = __ll_lowpart (d);						\
-									\
-    __r1 = (n1) % __d1;							\
-    __q1 = (n1) / __d1;							\
-    __m = (UWtype) __q1 * __d0;						\
-    __r1 = __r1 * __ll_B | __ll_highpart (n0);				\
-    if (__r1 < __m)							\
-      {									\
-	__q1--, __r1 += (d);						\
-	if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
-	  if (__r1 < __m)						\
-	    __q1--, __r1 += (d);					\
-      }									\
-    __r1 -= __m;							\
-									\
-    __r0 = __r1 % __d1;							\
-    __q0 = __r1 / __d1;							\
-    __m = (UWtype) __q0 * __d0;						\
-    __r0 = __r0 * __ll_B | __ll_lowpart (n0);				\
-    if (__r0 < __m)							\
-      {									\
-	__q0--, __r0 += (d);						\
-	if (__r0 >= (d))						\
-	  if (__r0 < __m)						\
-	    __q0--, __r0 += (d);					\
-      }									\
-    __r0 -= __m;							\
-									\
-    (q) = (UWtype) __q1 * __ll_B | __q0;				\
-    (r) = __r0;								\
-  } while (0)
-
-#define udiv_qrnnd __udiv_qrnnd_c
-
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-  do {									\
-    UWtype __x;								\
-    __x = (al) - (bl);							\
-    (sh) = (ah) - (bh) - (__x > (al));					\
-    (sl) = __x;								\
-  } while (0)
-
-#define umul_ppmm(w1, w0, u, v)						\
-  do {									\
-    UWtype __x0, __x1, __x2, __x3;					\
-    UHWtype __ul, __vl, __uh, __vh;					\
-									\
-    __ul = __ll_lowpart (u);						\
-    __uh = __ll_highpart (u);						\
-    __vl = __ll_lowpart (v);						\
-    __vh = __ll_highpart (v);						\
-									\
-    __x0 = (UWtype) __ul * __vl;					\
-    __x1 = (UWtype) __ul * __vh;					\
-    __x2 = (UWtype) __uh * __vl;					\
-    __x3 = (UWtype) __uh * __vh;					\
-									\
-    __x1 += __ll_highpart (__x0);/* this can't give carry */		\
-    __x1 += __x2;		/* but this indeed can */		\
-    if (__x1 < __x2)		/* did we get it? */			\
-      __x3 += __ll_B;		/* yes, add it in the proper pos.  */	\
-									\
-    (w1) = __x3 + __ll_highpart (__x1);					\
-    (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);		\
-  } while (0)
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile
index f62eb69..b21bea9 100644
--- a/arch/avr32/mach-at32ap/Makefile
+++ b/arch/avr32/mach-at32ap/Makefile
@@ -1,2 +1,2 @@
-obj-y				+= at32ap.o clock.o pio.o intc.o extint.o hsmc.o
+obj-y				+= at32ap.o clock.o intc.o extint.o pio.o hsmc.o
 obj-$(CONFIG_CPU_AT32AP7000)	+= at32ap7000.o
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index 48f4ef3..bc23550 100644
--- a/arch/avr32/mach-at32ap/at32ap7000.c
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -8,6 +8,7 @@
 #include <linux/clk.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 
 #include <asm/io.h>
 
@@ -310,8 +311,6 @@
 {
 	u32 control;
 
-	BUG_ON(clk->index > 7);
-
 	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
 	if (enabled)
 		control |= SM_BIT(CEN);
@@ -325,11 +324,6 @@
 	u32 control;
 	unsigned long div = 1;
 
-	BUG_ON(clk->index > 7);
-
-	if (!clk->parent)
-		return 0;
-
 	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
 	if (control & SM_BIT(DIVEN))
 		div = 2 * (SM_BFEXT(DIV, control) + 1);
@@ -342,11 +336,6 @@
 	u32 control;
 	unsigned long parent_rate, actual_rate, div;
 
-	BUG_ON(clk->index > 7);
-
-	if (!clk->parent)
-		return 0;
-
 	parent_rate = clk->parent->get_rate(clk->parent);
 	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
 
@@ -373,11 +362,8 @@
 {
 	u32 control;
 
-	BUG_ON(clk->index > 7);
-
 	printk("clk %s: new parent %s (was %s)\n",
-	       clk->name, parent->name,
-	       clk->parent ? clk->parent->name : "(null)");
+	       clk->name, parent->name, clk->parent->name);
 
 	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
 
@@ -399,6 +385,22 @@
 	return 0;
 }
 
+static void __init genclk_init_parent(struct clk *clk)
+{
+	u32 control;
+	struct clk *parent;
+
+	BUG_ON(clk->index > 7);
+
+	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+	if (control & SM_BIT(OSCSEL))
+		parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1;
+	else
+		parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0;
+
+	clk->parent = parent;
+}
+
 /* --------------------------------------------------------------------
  *  System peripherals
  * -------------------------------------------------------------------- */
@@ -496,9 +498,16 @@
 DEFINE_DEV(pio, 3);
 DEV_CLK(mck, pio3, pba, 13);
 
+static struct resource pio4_resource[] = {
+	PBMEM(0xffe03800),
+	IRQ(17),
+};
+DEFINE_DEV(pio, 4);
+DEV_CLK(mck, pio4, pba, 14);
+
 void __init at32_add_system_devices(void)
 {
-	system_manager.eim_first_irq = NR_INTERNAL_IRQS;
+	system_manager.eim_first_irq = EIM_IRQ_BASE;
 
 	platform_device_register(&at32_sm_device);
 	platform_device_register(&at32_intc0_device);
@@ -509,6 +518,7 @@
 	platform_device_register(&pio1_device);
 	platform_device_register(&pio2_device);
 	platform_device_register(&pio3_device);
+	platform_device_register(&pio4_device);
 }
 
 /* --------------------------------------------------------------------
@@ -521,7 +531,7 @@
 };
 static struct resource atmel_usart0_resource[] = {
 	PBMEM(0xffe00c00),
-	IRQ(7),
+	IRQ(6),
 };
 DEFINE_DEV_DATA(atmel_usart, 0);
 DEV_CLK(usart, atmel_usart0, pba, 4);
@@ -583,7 +593,7 @@
 	select_peripheral(PB(17), PERIPH_B, 0);	/* TXD	*/
 }
 
-static struct platform_device *at32_usarts[4];
+static struct platform_device *__initdata at32_usarts[4];
 
 void __init at32_map_usart(unsigned int hw_id, unsigned int line)
 {
@@ -728,32 +738,79 @@
 /* --------------------------------------------------------------------
  *  SPI
  * -------------------------------------------------------------------- */
-static struct resource spi0_resource[] = {
+static struct resource atmel_spi0_resource[] = {
 	PBMEM(0xffe00000),
 	IRQ(3),
 };
-DEFINE_DEV(spi, 0);
-DEV_CLK(mck, spi0, pba, 0);
+DEFINE_DEV(atmel_spi, 0);
+DEV_CLK(spi_clk, atmel_spi0, pba, 0);
 
-struct platform_device *__init at32_add_device_spi(unsigned int id)
+static struct resource atmel_spi1_resource[] = {
+	PBMEM(0xffe00400),
+	IRQ(4),
+};
+DEFINE_DEV(atmel_spi, 1);
+DEV_CLK(spi_clk, atmel_spi1, pba, 1);
+
+static void
+at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b,
+		      unsigned int n, const u8 *pins)
 {
+	unsigned int pin, mode;
+
+	for (; n; n--, b++) {
+		b->bus_num = bus_num;
+		if (b->chip_select >= 4)
+			continue;
+		pin = (unsigned)b->controller_data;
+		if (!pin) {
+			pin = pins[b->chip_select];
+			b->controller_data = (void *)pin;
+		}
+		mode = AT32_GPIOF_OUTPUT;
+		if (!(b->mode & SPI_CS_HIGH))
+			mode |= AT32_GPIOF_HIGH;
+		at32_select_gpio(pin, mode);
+	}
+}
+
+struct platform_device *__init
+at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
+{
+	/*
+	 * Manage the chipselects as GPIOs, normally using the same pins
+	 * the SPI controller expects; but boards can use other pins.
+	 */
+	static u8 __initdata spi0_pins[] =
+		{ GPIO_PIN_PA(3), GPIO_PIN_PA(4),
+		  GPIO_PIN_PA(5), GPIO_PIN_PA(20), };
+	static u8 __initdata spi1_pins[] =
+		{ GPIO_PIN_PB(2), GPIO_PIN_PB(3),
+		  GPIO_PIN_PB(4), GPIO_PIN_PA(27), };
 	struct platform_device *pdev;
 
 	switch (id) {
 	case 0:
-		pdev = &spi0_device;
+		pdev = &atmel_spi0_device;
 		select_peripheral(PA(0),  PERIPH_A, 0);	/* MISO	 */
 		select_peripheral(PA(1),  PERIPH_A, 0);	/* MOSI	 */
 		select_peripheral(PA(2),  PERIPH_A, 0);	/* SCK	 */
-		select_peripheral(PA(3),  PERIPH_A, 0);	/* NPCS0 */
-		select_peripheral(PA(4),  PERIPH_A, 0);	/* NPCS1 */
-		select_peripheral(PA(5),  PERIPH_A, 0);	/* NPCS2 */
+		at32_spi_setup_slaves(0, b, n, spi0_pins);
+		break;
+
+	case 1:
+		pdev = &atmel_spi1_device;
+		select_peripheral(PB(0),  PERIPH_B, 0);	/* MISO  */
+		select_peripheral(PB(1),  PERIPH_B, 0);	/* MOSI  */
+		select_peripheral(PB(5),  PERIPH_B, 0);	/* SCK   */
+		at32_spi_setup_slaves(1, b, n, spi1_pins);
 		break;
 
 	default:
 		return NULL;
 	}
 
+	spi_register_board_info(b, n);
 	platform_device_register(pdev);
 	return pdev;
 }
@@ -837,6 +894,50 @@
 	return pdev;
 }
 
+/* --------------------------------------------------------------------
+ *  GCLK
+ * -------------------------------------------------------------------- */
+static struct clk gclk0 = {
+	.name		= "gclk0",
+	.mode		= genclk_mode,
+	.get_rate	= genclk_get_rate,
+	.set_rate	= genclk_set_rate,
+	.set_parent	= genclk_set_parent,
+	.index		= 0,
+};
+static struct clk gclk1 = {
+	.name		= "gclk1",
+	.mode		= genclk_mode,
+	.get_rate	= genclk_get_rate,
+	.set_rate	= genclk_set_rate,
+	.set_parent	= genclk_set_parent,
+	.index		= 1,
+};
+static struct clk gclk2 = {
+	.name		= "gclk2",
+	.mode		= genclk_mode,
+	.get_rate	= genclk_get_rate,
+	.set_rate	= genclk_set_rate,
+	.set_parent	= genclk_set_parent,
+	.index		= 2,
+};
+static struct clk gclk3 = {
+	.name		= "gclk3",
+	.mode		= genclk_mode,
+	.get_rate	= genclk_get_rate,
+	.set_rate	= genclk_set_rate,
+	.set_parent	= genclk_set_parent,
+	.index		= 3,
+};
+static struct clk gclk4 = {
+	.name		= "gclk4",
+	.mode		= genclk_mode,
+	.get_rate	= genclk_get_rate,
+	.set_rate	= genclk_set_rate,
+	.set_parent	= genclk_set_parent,
+	.index		= 4,
+};
+
 struct clk *at32_clock_list[] = {
 	&osc32k,
 	&osc0,
@@ -860,6 +961,7 @@
 	&pio1_mck,
 	&pio2_mck,
 	&pio3_mck,
+	&pio4_mck,
 	&atmel_usart0_usart,
 	&atmel_usart1_usart,
 	&atmel_usart2_usart,
@@ -868,9 +970,15 @@
 	&macb0_pclk,
 	&macb1_hclk,
 	&macb1_pclk,
-	&spi0_mck,
+	&atmel_spi0_spi_clk,
+	&atmel_spi1_spi_clk,
 	&lcdc0_hclk,
 	&lcdc0_pixclk,
+	&gclk0,
+	&gclk1,
+	&gclk2,
+	&gclk3,
+	&gclk4,
 };
 unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
 
@@ -880,6 +988,7 @@
 	at32_init_pio(&pio1_device);
 	at32_init_pio(&pio2_device);
 	at32_init_pio(&pio3_device);
+	at32_init_pio(&pio4_device);
 }
 
 void __init at32_clock_init(void)
@@ -898,6 +1007,13 @@
 	if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC))
 		pll1.parent = &osc1;
 
+	genclk_init_parent(&gclk0);
+	genclk_init_parent(&gclk1);
+	genclk_init_parent(&gclk2);
+	genclk_init_parent(&gclk3);
+	genclk_init_parent(&gclk4);
+	genclk_init_parent(&lcdc0_pixclk);
+
 	/*
 	 * Turn on all clocks that have at least one user already, and
 	 * turn off everything else. We only do this for module
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 3d0d109..00c4354 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2006 Atmel Corporation
  *
- * Based on arch/arm/mach-at91rm9200/clock.c
+ * Based on arch/arm/mach-at91/clock.c
  *   Copyright (C) 2005 David Brownell
  *   Copyright (C) 2005 Ivan Kokshaysky
  *
@@ -63,7 +63,11 @@
 
 static void __clk_disable(struct clk *clk)
 {
-	BUG_ON(clk->users == 0);
+	if (clk->users == 0) {
+		printk(KERN_ERR "%s: mismatched disable\n", clk->name);
+		WARN_ON(1);
+		return;
+	}
 
 	if (--clk->users == 0 && clk->mode)
 		clk->mode(clk, 0);
diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h
index f953f04..bb8e1f2 100644
--- a/arch/avr32/mach-at32ap/clock.h
+++ b/arch/avr32/mach-at32ap/clock.h
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2006 Atmel Corporation
  *
- * Based on arch/arm/mach-at91rm9200/clock.c
+ * Based on arch/arm/mach-at91/clock.c
  *   Copyright (C) 2005 David Brownell
  *   Copyright (C) 2005 Ivan Kokshaysky
  *
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
index b59272e..4a60ecc 100644
--- a/arch/avr32/mach-at32ap/extint.c
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -55,20 +55,11 @@
 	unsigned long flags;
 	int ret = 0;
 
+	flow_type &= IRQ_TYPE_SENSE_MASK;
 	if (flow_type == IRQ_TYPE_NONE)
 		flow_type = IRQ_TYPE_LEVEL_LOW;
 
 	desc = &irq_desc[irq];
-	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-
-	if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
-		desc->status |= IRQ_LEVEL;
-		set_irq_handler(irq, handle_level_irq);
-	} else {
-		set_irq_handler(irq, handle_edge_irq);
-	}
-
 	spin_lock_irqsave(&sm->lock, flags);
 
 	mode = sm_readl(sm, EIM_MODE);
@@ -97,9 +88,16 @@
 		break;
 	}
 
-	sm_writel(sm, EIM_MODE, mode);
-	sm_writel(sm, EIM_EDGE, edge);
-	sm_writel(sm, EIM_LEVEL, level);
+	if (ret == 0) {
+		sm_writel(sm, EIM_MODE, mode);
+		sm_writel(sm, EIM_EDGE, edge);
+		sm_writel(sm, EIM_LEVEL, level);
+
+		if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+			flow_type |= IRQ_LEVEL;
+		desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+		desc->status |= flow_type;
+	}
 
 	spin_unlock_irqrestore(&sm->lock, flags);
 
@@ -122,8 +120,6 @@
 	unsigned long status, pending;
 	unsigned int i, ext_irq;
 
-	spin_lock(&sm->lock);
-
 	status = sm_readl(sm, EIM_ISR);
 	pending = status & sm_readl(sm, EIM_IMR);
 
@@ -133,10 +129,11 @@
 
 		ext_irq = i + sm->eim_first_irq;
 		ext_desc = irq_desc + ext_irq;
-		ext_desc->handle_irq(ext_irq, ext_desc);
+		if (ext_desc->status & IRQ_LEVEL)
+			handle_level_irq(ext_irq, ext_desc);
+		else
+			handle_edge_irq(ext_irq, ext_desc);
 	}
-
-	spin_unlock(&sm->lock);
 }
 
 static int __init eim_init(void)
@@ -168,8 +165,9 @@
 	sm->eim_chip = &eim_chip;
 
 	for (i = 0; i < nr_irqs; i++) {
+		/* NOTE the handler we set here is ignored by the demux */
 		set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
-					 handle_edge_irq);
+					 handle_level_irq);
 		set_irq_chip_data(sm->eim_first_irq + i, sm);
 	}
 
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index f1280ed..9ba5654 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -12,7 +12,9 @@
 #include <linux/debugfs.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
+#include <linux/irq.h>
 
+#include <asm/gpio.h>
 #include <asm/io.h>
 
 #include <asm/arch/portmux.h>
@@ -26,7 +28,8 @@
 	const struct platform_device *pdev;
 	struct clk *clk;
 	u32 pinmux_mask;
-	char name[32];
+	u32 gpio_mask;
+	char name[8];
 };
 
 static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
@@ -76,6 +79,9 @@
 	if (!(flags & AT32_GPIOF_PULLUP))
 		pio_writel(pio, PUDR, mask);
 
+	/* gpio_request NOT allowed */
+	set_bit(pin_index, &pio->gpio_mask);
+
 	return;
 
 fail:
@@ -99,19 +105,29 @@
 		goto fail;
 	}
 
-	pio_writel(pio, PUER, mask);
-	if (flags & AT32_GPIOF_HIGH)
-		pio_writel(pio, SODR, mask);
-	else
-		pio_writel(pio, CODR, mask);
-	if (flags & AT32_GPIOF_OUTPUT)
+	if (flags & AT32_GPIOF_OUTPUT) {
+		if (flags & AT32_GPIOF_HIGH)
+			pio_writel(pio, SODR, mask);
+		else
+			pio_writel(pio, CODR, mask);
+		pio_writel(pio, PUDR, mask);
 		pio_writel(pio, OER, mask);
-	else
+	} else {
+		if (flags & AT32_GPIOF_PULLUP)
+			pio_writel(pio, PUER, mask);
+		else
+			pio_writel(pio, PUDR, mask);
+		if (flags & AT32_GPIOF_DEGLITCH)
+			pio_writel(pio, IFER, mask);
+		else
+			pio_writel(pio, IFDR, mask);
 		pio_writel(pio, ODR, mask);
+	}
 
 	pio_writel(pio, PER, mask);
-	if (!(flags & AT32_GPIOF_PULLUP))
-		pio_writel(pio, PUDR, mask);
+
+	/* gpio_request now allowed */
+	clear_bit(pin_index, &pio->gpio_mask);
 
 	return;
 
@@ -119,20 +135,220 @@
 	dump_stack();
 }
 
+/* Reserve a pin, preventing anyone else from changing its configuration. */
+void __init at32_reserve_pin(unsigned int pin)
+{
+	struct pio_device *pio;
+	unsigned int pin_index = pin & 0x1f;
+
+	pio = gpio_to_pio(pin);
+	if (unlikely(!pio)) {
+		printk("pio: invalid pin %u\n", pin);
+		goto fail;
+	}
+
+	if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+		printk("%s: pin %u is busy\n", pio->name, pin_index);
+		goto fail;
+	}
+
+	return;
+
+fail:
+	dump_stack();
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* GPIO API */
+
+int gpio_request(unsigned int gpio, const char *label)
+{
+	struct pio_device *pio;
+	unsigned int pin;
+
+	pio = gpio_to_pio(gpio);
+	if (!pio)
+		return -ENODEV;
+
+	pin = gpio & 0x1f;
+	if (test_and_set_bit(pin, &pio->gpio_mask))
+		return -EBUSY;
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned int gpio)
+{
+	struct pio_device *pio;
+	unsigned int pin;
+
+	pio = gpio_to_pio(gpio);
+	if (!pio) {
+		printk(KERN_ERR
+		       "gpio: attempted to free invalid pin %u\n", gpio);
+		return;
+	}
+
+	pin = gpio & 0x1f;
+	if (!test_and_clear_bit(pin, &pio->gpio_mask))
+		printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n",
+		       pio->name, pin);
+}
+EXPORT_SYMBOL(gpio_free);
+
+int gpio_direction_input(unsigned int gpio)
+{
+	struct pio_device *pio;
+	unsigned int pin;
+
+	pio = gpio_to_pio(gpio);
+	if (!pio)
+		return -ENODEV;
+
+	pin = gpio & 0x1f;
+	pio_writel(pio, ODR, 1 << pin);
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned int gpio)
+{
+	struct pio_device *pio;
+	unsigned int pin;
+
+	pio = gpio_to_pio(gpio);
+	if (!pio)
+		return -ENODEV;
+
+	pin = gpio & 0x1f;
+	pio_writel(pio, OER, 1 << pin);
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+int gpio_get_value(unsigned int gpio)
+{
+	struct pio_device *pio = &pio_dev[gpio >> 5];
+
+	return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1;
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+void gpio_set_value(unsigned int gpio, int value)
+{
+	struct pio_device *pio = &pio_dev[gpio >> 5];
+	u32 mask;
+
+	mask = 1 << (gpio & 0x1f);
+	if (value)
+		pio_writel(pio, SODR, mask);
+	else
+		pio_writel(pio, CODR, mask);
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+/*--------------------------------------------------------------------------*/
+
+/* GPIO IRQ support */
+
+static void gpio_irq_mask(unsigned irq)
+{
+	unsigned		gpio = irq_to_gpio(irq);
+	struct pio_device	*pio = &pio_dev[gpio >> 5];
+
+	pio_writel(pio, IDR, 1 << (gpio & 0x1f));
+}
+
+static void gpio_irq_unmask(unsigned irq)
+{
+	unsigned		gpio = irq_to_gpio(irq);
+	struct pio_device	*pio = &pio_dev[gpio >> 5];
+
+	pio_writel(pio, IER, 1 << (gpio & 0x1f));
+}
+
+static int gpio_irq_type(unsigned irq, unsigned type)
+{
+	if (type != IRQ_TYPE_EDGE_BOTH && type != IRQ_TYPE_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "gpio",
+	.mask		= gpio_irq_mask,
+	.unmask		= gpio_irq_unmask,
+	.set_type	= gpio_irq_type,
+};
+
+static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct pio_device	*pio = get_irq_chip_data(irq);
+	unsigned		gpio_irq;
+
+	gpio_irq = (unsigned) get_irq_data(irq);
+	for (;;) {
+		u32		isr;
+		struct irq_desc	*d;
+
+		/* ack pending GPIO interrupts */
+		isr = pio_readl(pio, ISR) & pio_readl(pio, IMR);
+		if (!isr)
+			break;
+		do {
+			int i;
+
+			i = ffs(isr) - 1;
+			isr &= ~(1 << i);
+
+			i += gpio_irq;
+			d = &irq_desc[i];
+
+			d->handle_irq(i, d);
+		} while (isr);
+	}
+}
+
+static void __init
+gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
+{
+	unsigned	i;
+
+	set_irq_chip_data(irq, pio);
+	set_irq_data(irq, (void *) gpio_irq);
+
+	for (i = 0; i < 32; i++, gpio_irq++) {
+		set_irq_chip_data(gpio_irq, pio);
+		set_irq_chip_and_handler(gpio_irq, &gpio_irqchip,
+				handle_simple_irq);
+	}
+
+	set_irq_chained_handler(irq, gpio_irq_handler);
+}
+
+/*--------------------------------------------------------------------------*/
+
 static int __init pio_probe(struct platform_device *pdev)
 {
 	struct pio_device *pio = NULL;
+	int irq = platform_get_irq(pdev, 0);
+	int gpio_irq_base = GPIO_IRQ_BASE + pdev->id * 32;
 
 	BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES);
 	pio = &pio_dev[pdev->id];
 	BUG_ON(!pio->regs);
 
-	/* TODO: Interrupts */
+	gpio_irq_setup(pio, irq, gpio_irq_base);
 
 	platform_set_drvdata(pdev, pio);
 
-	printk(KERN_INFO "%s: Atmel Port Multiplexer at 0x%p (irq %d)\n",
-	       pio->name, pio->regs, platform_get_irq(pdev, 0));
+	printk(KERN_DEBUG "%s: base 0x%p, irq %d chains %d..%d\n",
+	       pio->name, pio->regs, irq, gpio_irq_base, gpio_irq_base + 31);
 
 	return 0;
 }
@@ -148,7 +364,7 @@
 {
 	return platform_driver_register(&pio_driver);
 }
-subsys_initcall(pio_init);
+postcore_initcall(pio_init);
 
 void __init at32_init_pio(struct platform_device *pdev)
 {
@@ -184,6 +400,13 @@
 	pio->pdev = pdev;
 	pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
 
-	pio_writel(pio, ODR, ~0UL);
-	pio_writel(pio, PER, ~0UL);
+	/*
+	 * request_gpio() is only valid for pins that have been
+	 * explicitly configured as GPIO and not previously requested
+	 */
+	pio->gpio_mask = ~0UL;
+
+	/* start with irqs disabled and acked */
+	pio_writel(pio, IDR, ~0UL);
+	(void) pio_readl(pio, ISR);
 }
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c
index 450515b..fb13f72 100644
--- a/arch/avr32/mm/cache.c
+++ b/arch/avr32/mm/cache.c
@@ -22,18 +22,34 @@
 
 void invalidate_dcache_region(void *start, size_t size)
 {
-	unsigned long v, begin, end, linesz;
+	unsigned long v, begin, end, linesz, mask;
+	int flush = 0;
 
 	linesz = boot_cpu_data.dcache.linesz;
+	mask = linesz - 1;
 
-	//printk("invalidate dcache: %p + %u\n", start, size);
+	/* when first and/or last cachelines are shared, flush them
+	 * instead of invalidating ... never discard valid data!
+	 */
+	begin = (unsigned long)start;
+	end = begin + size - 1;
 
-	/* You asked for it, you got it */
-	begin = (unsigned long)start & ~(linesz - 1);
-	end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
+	if (begin & mask) {
+		flush_dcache_line(start);
+		begin += linesz;
+		flush = 1;
+	}
+	if ((end & mask) != mask) {
+		flush_dcache_line((void *)end);
+		end -= linesz;
+		flush = 1;
+	}
 
-	for (v = begin; v < end; v += linesz)
+	/* remaining cachelines only need invalidation */
+	for (v = begin; v <= end; v += linesz)
 		invalidate_dcache_line((void *)v);
+	if (flush)
+		flush_write_buffer();
 }
 
 void clean_dcache_region(void *start, size_t size)
diff --git a/arch/avr32/mm/tlb.c b/arch/avr32/mm/tlb.c
index 7b07305..5667201 100644
--- a/arch/avr32/mm/tlb.c
+++ b/arch/avr32/mm/tlb.c
@@ -360,7 +360,7 @@
 	return seq_open(file, &tlb_ops);
 }
 
-static struct file_operations proc_tlb_operations = {
+static const struct file_operations proc_tlb_operations = {
 	.open		= tlb_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 3474309..4b41248 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -9,6 +9,10 @@
 	bool
 	default y
 
+config ZONE_DMA
+	bool
+	default y
+
 config RWSEM_GENERIC_SPINLOCK
 	bool
 	default y
@@ -40,6 +44,9 @@
 	bool
 	default y
 
+config NO_IOPORT
+	def_bool y
+
 config CRIS
 	bool
 	default y
diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c
index ffade19..efd7b0f 100644
--- a/arch/cris/arch-v10/drivers/axisflashmap.c
+++ b/arch/cris/arch-v10/drivers/axisflashmap.c
@@ -359,8 +359,7 @@
 		 * So we use the MTD concatenation layer instead of further
 		 * complicating the probing procedure.
 		 */
-		mtd_cse = mtd_concat_create(mtds,
-					    sizeof(mtds) / sizeof(mtds[0]),
+		mtd_cse = mtd_concat_create(mtds, ARRAY_SIZE(mtds),
 					    "cse0+cse1");
 #else
 		printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c
index 3cf4f23..88eff7f 100644
--- a/arch/cris/arch-v10/drivers/ds1302.c
+++ b/arch/cris/arch-v10/drivers/ds1302.c
@@ -499,7 +499,7 @@
 
 /* The various file operations we support. */
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.owner =	THIS_MODULE,
 	.ioctl =	rtc_ioctl,
 }; 
diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c
index 284ebfd..be35a707 100644
--- a/arch/cris/arch-v10/drivers/eeprom.c
+++ b/arch/cris/arch-v10/drivers/eeprom.c
@@ -172,7 +172,7 @@
 static struct eeprom_type eeprom;
 
 /* This is the exported file-operations structure for this device. */
-struct file_operations eeprom_fops =
+const struct file_operations eeprom_fops =
 {
   .llseek  = eeprom_lseek,
   .read    = eeprom_read,
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index 9aba18b..f389ed6 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -838,7 +838,7 @@
 	return 0;
 }
 
-struct file_operations gpio_fops = {
+const struct file_operations gpio_fops = {
 	.owner       = THIS_MODULE,
 	.poll        = gpio_poll,
 	.ioctl       = gpio_ioctl,
diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c
index 092c724..aca81dd 100644
--- a/arch/cris/arch-v10/drivers/i2c.c
+++ b/arch/cris/arch-v10/drivers/i2c.c
@@ -692,7 +692,7 @@
 	return 0;
 }
 
-static struct file_operations i2c_fops = {
+static const struct file_operations i2c_fops = {
 	.owner    = THIS_MODULE,
 	.ioctl    = i2c_ioctl,
 	.open     = i2c_open,
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
index 8c830ee..d47cfbf 100644
--- a/arch/cris/arch-v10/drivers/pcf8563.c
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -56,7 +56,7 @@
 
 int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 
-static struct file_operations pcf8563_fops = {
+static const struct file_operations pcf8563_fops = {
 	.owner = THIS_MODULE,
 	.ioctl = pcf8563_ioctl,
 };
@@ -311,7 +311,7 @@
 {
 	pcf8563_init();
 	if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
-		printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n",
+		printk(KERN_INFO "%s: Unable to get major number %d for RTC device.\n",
 		       PCF8563_NAME, PCF8563_MAJOR);
 		return -1;
 	}
diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c
index ebacf14..077e973 100644
--- a/arch/cris/arch-v10/kernel/time.c
+++ b/arch/cris/arch-v10/kernel/time.c
@@ -38,7 +38,6 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	local_irq_disable();
 	timer_count = *R_TIMER0_DATA;
 	presc_count = *R_TIM_PRESC_STATUS;  
 	/* presc_count might be wrapped */
diff --git a/arch/cris/arch-v10/mm/tlb.c b/arch/cris/arch-v10/mm/tlb.c
index 70a5523..7d9fec8 100644
--- a/arch/cris/arch-v10/mm/tlb.c
+++ b/arch/cris/arch-v10/mm/tlb.c
@@ -42,8 +42,7 @@
 	 * in the same 4-way entry group. details.. 
 	 */
 
-	local_save_flags(flags);
-	local_irq_disable();
+	local_irq_save(flags);
 	for(i = 0; i < NUM_TLB_ENTRIES; i++) {
 		*R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
 		*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
@@ -78,8 +77,7 @@
 	 * global pages. is it worth the extra I/O ? 
 	 */
 
-	local_save_flags(flags);
-	local_irq_disable();
+	local_irq_save(flags);
 	for(i = 0; i < NUM_TLB_ENTRIES; i++) {
 		*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
 		if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) {
@@ -118,8 +116,7 @@
 	 * and the virtual address requested 
 	 */
 
-	local_save_flags(flags);
-	local_irq_disable();
+	local_irq_save(flags);
 	for(i = 0; i < NUM_TLB_ENTRIES; i++) {
 		unsigned long tlb_hi;
 		*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
diff --git a/arch/cris/arch-v10/vmlinux.lds.S b/arch/cris/arch-v10/vmlinux.lds.S
index 689729a..4b348b3 100644
--- a/arch/cris/arch-v10/vmlinux.lds.S
+++ b/arch/cris/arch-v10/vmlinux.lds.S
@@ -82,7 +82,8 @@
 		__con_initcall_end = .;
 	}	
 	SECURITY_INIT
-		
+
+#ifdef CONFIG_BLK_DEV_INITRD
 	.init.ramfs : {
 		__initramfs_start = .;
 		*(.init.ramfs)
@@ -93,6 +94,7 @@
 		FILL (0); 
 		. = ALIGN (8192);
 	}
+#endif
 	
 	__vmlinux_end = .;            /* last address of the physical file */
   	__init_end = .;
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index 2449637..1a071f1 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -266,7 +266,7 @@
 
 
 
-struct file_operations cryptocop_fops = {
+const struct file_operations cryptocop_fops = {
 	owner: THIS_MODULE,
 	open: cryptocop_open,
 	release: cryptocop_release,
diff --git a/arch/cris/arch-v32/drivers/gpio.c b/arch/cris/arch-v32/drivers/gpio.c
index 08d36f0..d82c5c5 100644
--- a/arch/cris/arch-v32/drivers/gpio.c
+++ b/arch/cris/arch-v32/drivers/gpio.c
@@ -705,7 +705,7 @@
 	return 0;
 }
 
-struct file_operations gpio_fops = {
+const struct file_operations gpio_fops = {
 	.owner       = THIS_MODULE,
 	.poll        = gpio_poll,
 	.ioctl       = gpio_ioctl,
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index 95f0018..5d6c527 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -573,7 +573,7 @@
 	return 0;
 }
 
-static struct file_operations i2c_fops = {
+static const struct file_operations i2c_fops = {
 	owner:    THIS_MODULE,
 	ioctl:    i2c_ioctl,
 	open:     i2c_open,
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index 2fc7d75..24b919b 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -50,7 +50,7 @@
 int pcf8563_open(struct inode *, struct file *);
 int pcf8563_release(struct inode *, struct file *);
 
-static struct file_operations pcf8563_fops = {
+static const struct file_operations pcf8563_fops = {
 	owner: THIS_MODULE,
 	ioctl: pcf8563_ioctl,
 	open: pcf8563_open,
@@ -171,7 +171,7 @@
 		goto err;
 
 	if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
-		printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n",
+		printk(KERN_INFO "%s: Unable to get major number %d for RTC device.\n",
 		       PCF8563_NAME, PCF8563_MAJOR);
 		return -1;
 	}
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
index 424eb0e..df89298 100644
--- a/arch/cris/arch-v32/drivers/sync_serial.c
+++ b/arch/cris/arch-v32/drivers/sync_serial.c
@@ -187,7 +187,7 @@
 
 #define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
 
-static struct file_operations sync_serial_fops = {
+static const struct file_operations sync_serial_fops = {
 	.owner   = THIS_MODULE,
 	.write   = sync_serial_write,
 	.read    = sync_serial_read,
diff --git a/arch/cris/arch-v32/mm/tlb.c b/arch/cris/arch-v32/mm/tlb.c
index 9d75d76..c2d12e9 100644
--- a/arch/cris/arch-v32/mm/tlb.c
+++ b/arch/cris/arch-v32/mm/tlb.c
@@ -54,8 +54,7 @@
 	 * Mask with 0xf so similar TLB entries aren't written in the same 4-way
 	 * entry group.
 	 */
-	local_save_flags(flags);
-	local_irq_disable();
+	local_irq_save(flags);
 
 	for (mmu = 1; mmu <= 2; mmu++) {
 		SUPP_BANK_SEL(mmu); /* Select the MMU */
@@ -92,8 +91,7 @@
 		return;
 
 	/* Mark the TLB entries that match the page_id as invalid. */
-	local_save_flags(flags);
-	local_irq_disable();
+	local_irq_save(flags);
 
 	for (mmu = 1; mmu <= 2; mmu++) {
 		SUPP_BANK_SEL(mmu);
@@ -140,8 +138,7 @@
 	 * Invalidate those TLB entries that match both the mm context and the
 	 * requested virtual address.
 	 */
-	local_save_flags(flags);
-	local_irq_disable();
+	local_irq_save(flags);
 
 	for (mmu = 1; mmu <= 2; mmu++) {
 		SUPP_BANK_SEL(mmu);
diff --git a/arch/cris/arch-v32/vmlinux.lds.S b/arch/cris/arch-v32/vmlinux.lds.S
index 472d4b3..e124fcd 100644
--- a/arch/cris/arch-v32/vmlinux.lds.S
+++ b/arch/cris/arch-v32/vmlinux.lds.S
@@ -95,6 +95,7 @@
 	.data.percpu  : { *(.data.percpu) }
 	__per_cpu_end = .;
 
+#ifdef CONFIG_BLK_DEV_INITRD
 	.init.ramfs : {
 		__initramfs_start = .;
 		*(.init.ramfs)
@@ -107,6 +108,7 @@
 		FILL (0);
 		. = ALIGN (8192);
 	}
+#endif
 
 	__vmlinux_end = .;	/* Last address of the physical file. */
   	__init_end = .;
diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c
index f60ab78..4cfcae6 100644
--- a/arch/cris/kernel/profile.c
+++ b/arch/cris/kernel/profile.c
@@ -50,7 +50,7 @@
   memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE);
 }
 
-static struct file_operations cris_proc_profile_operations = {
+static const struct file_operations cris_proc_profile_operations = {
 	.read		= read_cris_profile,
 	.write		= write_cris_profile,
 };
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index ca8b45a..65466c4 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -29,7 +29,7 @@
 extern int root_mountflags;
 extern char _etext, _edata, _end;
 
-char cris_command_line[COMMAND_LINE_SIZE] = { 0, };
+char __initdata cris_command_line[COMMAND_LINE_SIZE] = { 0, };
 
 extern const unsigned long text_start, edata; /* set by the linker script */
 extern unsigned long dram_start, dram_end;
@@ -153,8 +153,8 @@
 #endif
 
 	/* Save command line for future references. */
-	memcpy(saved_command_line, cris_command_line, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+	memcpy(boot_command_line, cris_command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
 
 	/* give credit for the CRIS port */
 	show_etrax_copyright();
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index 0f9213c..acfd045 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -55,7 +55,6 @@
 	unsigned long flags;
 	signed long usec, sec;
 	local_irq_save(flags);
-	local_irq_disable();
 	usec = do_gettimeoffset();
 
         /*
@@ -217,14 +216,6 @@
 #endif
 }
 
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
 static int
 __init init_udelay(void)
 {
diff --git a/arch/cris/mm/tlb.c b/arch/cris/mm/tlb.c
index 0df390a..c4a98e2 100644
--- a/arch/cris/mm/tlb.c
+++ b/arch/cris/mm/tlb.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <asm/tlb.h>
 
 #define D(x)
@@ -100,7 +101,7 @@
 
 	/* clear the page_id map */
 
-	for (i = 1; i < sizeof (page_id_map) / sizeof (page_id_map[0]); i++)
+	for (i = 1; i < ARRAY_SIZE(page_id_map); i++)
 		page_id_map[i] = NULL;
 	
 	/* invalidate the entire TLB */
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 7561d7b..cea2374 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -6,6 +6,10 @@
 	bool
 	default y
 
+config ZONE_DMA
+	bool
+	default y
+
 config RWSEM_GENERIC_SPINLOCK
 	bool
 	default y
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index ee677ce..c57ce3f 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -125,7 +125,6 @@
  * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
  * when all the PM interfaces exist nicely.
  */
-#define CTL_PM 9899
 #define CTL_PM_SUSPEND 1
 #define CTL_PM_CMODE 2
 #define CTL_PM_P0 4
@@ -402,17 +401,53 @@
 
 static struct ctl_table pm_table[] =
 {
-	{CTL_PM_SUSPEND, "suspend", NULL, 0, 0200, NULL, &sysctl_pm_do_suspend},
-	{CTL_PM_CMODE, "cmode", &clock_cmode_current, sizeof(int), 0644, NULL, &cmode_procctl, &cmode_sysctl, NULL},
-	{CTL_PM_P0, "p0", &clock_p0_current, sizeof(int), 0644, NULL, &p0_procctl, &p0_sysctl, NULL},
-	{CTL_PM_CM, "cm", &clock_cm_current, sizeof(int), 0644, NULL, &cm_procctl, &cm_sysctl, NULL},
-	{0}
+	{
+		.ctl_name	= CTL_PM_SUSPEND,
+		.procname	= "suspend",
+		.data		= NULL,
+		.maxlen		= 0,
+		.mode		= 0200,
+		.proc_handler	= &sysctl_pm_do_suspend,
+	},
+	{
+		.ctl_name	= CTL_PM_CMODE,
+		.procname	= "cmode",
+		.data		= &clock_cmode_current,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &cmode_procctl,
+		.strategy	= &cmode_sysctl,
+	},
+	{
+		.ctl_name	= CTL_PM_P0,
+		.procname	= "p0",
+		.data		= &clock_p0_current,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &p0_procctl,
+		.strategy	= &p0_sysctl,
+	},
+	{
+		.ctl_name	= CTL_PM_CM,
+		.procname	= "cm",
+		.data		= &clock_cm_current,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &cm_procctl,
+		.strategy	= &cm_sysctl,
+	},
+	{ .ctl_name = 0}
 };
 
 static struct ctl_table pm_dir_table[] =
 {
-	{CTL_PM, "pm", NULL, 0, 0555, pm_table},
-	{0}
+	{
+		.ctl_name	= CTL_PM,
+		.procname	= "pm",
+		.mode		= 0555,
+		.child		= pm_table,
+	},
+	{ .ctl_name = 0}
 };
 
 /*
@@ -420,7 +455,7 @@
  */
 static int __init pm_init(void)
 {
-	register_sysctl_table(pm_dir_table, 1);
+	register_sysctl_table(pm_dir_table);
 	return 0;
 }
 
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 1a5eb6c..8ea3ca2 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -110,7 +110,7 @@
 
 struct cpuinfo_frv __nongprelbss boot_cpu_data;
 
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
 char __initdata redboot_command_line[COMMAND_LINE_SIZE];
 
 #ifdef CONFIG_PM
@@ -762,7 +762,7 @@
 	printk("uClinux FR-V port done by Red Hat Inc <dhowells@redhat.com>\n");
 #endif
 
-	memcpy(saved_command_line, redboot_command_line, COMMAND_LINE_SIZE);
+	memcpy(boot_command_line, redboot_command_line, COMMAND_LINE_SIZE);
 
 	determine_cpu();
 	determine_clocks(1);
@@ -803,7 +803,7 @@
 #endif
 
 	/* deal with the command line - RedBoot may have passed one to the kernel */
-	memcpy(command_line, saved_command_line, sizeof(command_line));
+	memcpy(command_line, boot_command_line, sizeof(command_line));
 	*cmdline_p = &command_line[0];
 	parse_cmdline_early(command_line);
 
diff --git a/arch/frv/kernel/sysctl.c b/arch/frv/kernel/sysctl.c
index ce67680..3e9d7e0 100644
--- a/arch/frv/kernel/sysctl.c
+++ b/arch/frv/kernel/sysctl.c
@@ -175,22 +175,40 @@
  */
 static struct ctl_table frv_table[] =
 {
-	{ 1, "cache-mode",	NULL, 0, 0644, NULL, &procctl_frv_cachemode },
+	{
+		.ctl_name 	= 1,
+		.procname 	= "cache-mode",
+		.data		= NULL,
+		.maxlen		= 0,
+		.mode		= 0644,
+		.proc_handler	= &procctl_frv_cachemode,
+	},
 #ifdef CONFIG_MMU
-	{ 2, "pin-cxnr",	NULL, 0, 0644, NULL, &procctl_frv_pin_cxnr },
+	{
+		.ctl_name	= 2,
+		.procname	= "pin-cxnr",
+		.data		= NULL,
+		.maxlen		= 0,
+		.mode		= 0644,
+		.proc_handler	= &procctl_frv_pin_cxnr
+	},
 #endif
-	{ 0 }
+	{}
 };
 
 /*
  * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
  * when all the PM interfaces exist nicely.
  */
-#define CTL_FRV 9898
 static struct ctl_table frv_dir_table[] =
 {
-	{CTL_FRV, "frv", NULL, 0, 0555, frv_table},
-	{0}
+	{
+		.ctl_name	= CTL_FRV,
+		.procname	= "frv",
+		.mode 		= 0555,
+		.child		= frv_table
+	},
+	{}
 };
 
 /*
@@ -198,7 +216,7 @@
  */
 static int __init frv_sysctl_init(void)
 {
-	register_sysctl_table(frv_dir_table, 1);
+	register_sysctl_table(frv_dir_table);
 	return 0;
 }
 
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index 9c1fb12..97910e0 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -61,10 +61,12 @@
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
 
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
 
   . = ALIGN(THREAD_SIZE);
   __init_end = .;
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 34a84bc..1734d96 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -17,6 +17,10 @@
 	bool
 	default n
 
+config ZONE_DMA
+	bool
+	default y
+
 config FPU
 	bool
 	default n
@@ -53,6 +57,9 @@
 	bool
 	default y
 
+config NO_IOPORT
+	def_bool y
+
 config ISA
 	bool
 	default y
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
index 71b6131..4edbc2e 100644
--- a/arch/h8300/kernel/Makefile
+++ b/arch/h8300/kernel/Makefile
@@ -6,6 +6,8 @@
 
 obj-y := process.o traps.o ptrace.o ints.o \
 	 sys_h8300.o time.o semaphore.o signal.o \
-         setup.o gpio.o init_task.o syscalls.o
+         setup.o gpio.o init_task.o syscalls.o devres.o
+
+devres-y = ../../../kernel/irq/devres.o
 
 obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o 
diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c
index 587ef7f..3e4f479 100644
--- a/arch/h8300/kernel/ints.c
+++ b/arch/h8300/kernel/ints.c
@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/random.h>
 #include <linux/bootmem.h>
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c
index 6adf8f4..313cd80 100644
--- a/arch/h8300/kernel/setup.c
+++ b/arch/h8300/kernel/setup.c
@@ -54,7 +54,7 @@
 unsigned long memory_start;
 unsigned long memory_end;
 
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
 
 extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
 extern int _ramstart, _ramend;
@@ -154,8 +154,8 @@
 #endif
 	/* Keep a copy of command line */
 	*cmdline_p = &command_line[0];
-	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = 0;
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = 0;
 
 #ifdef DEBUG
 	if (strlen(*cmdline_p)) 
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
index 8abab3b..d1ef615 100644
--- a/arch/h8300/kernel/time.c
+++ b/arch/h8300/kernel/time.c
@@ -118,9 +118,3 @@
 }
 
 EXPORT_SYMBOL(do_settimeofday);
-
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-
-}
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
index f05288b..65f1cdc 100644
--- a/arch/h8300/kernel/vmlinux.lds.S
+++ b/arch/h8300/kernel/vmlinux.lds.S
@@ -126,10 +126,12 @@
 	___con_initcall_end = .;
 		*(.exit.text)
 		*(.exit.data)
+#if defined(CONFIG_BLK_DEV_INITRD)
 		. = ALIGN(4);
 	___initramfs_start = .;
   		*(.init.ramfs)
   	___initramfs_end = .;
+#endif
 	. = ALIGN(0x4) ;
 	___init_end = .;
 	__edata = . ;
diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c
index 567f681..a71d6e2 100644
--- a/arch/h8300/platform/h8s/ints.c
+++ b/arch/h8300/platform/h8s/ints.c
@@ -20,6 +20,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/bootmem.h>
 #include <linux/random.h>
 #include <linux/hardirq.h>
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 0dfee81..2f76725 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -18,6 +18,19 @@
 	bool
 	default y
 
+config CLOCKSOURCE_WATCHDOG
+	bool
+	default y
+
+config GENERIC_CLOCKEVENTS
+	bool
+	default y
+
+config GENERIC_CLOCKEVENTS_BROADCAST
+	bool
+	default y
+	depends on X86_LOCAL_APIC
+
 config LOCKDEP_SUPPORT
 	bool
 	default y
@@ -38,6 +51,10 @@
 	bool
 	default y
 
+config ZONE_DMA
+	bool
+	default y
+
 config SBUS
 	bool
 
@@ -70,6 +87,8 @@
 
 menu "Processor type and features"
 
+source "kernel/time/Kconfig"
+
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
@@ -199,6 +218,15 @@
 	  However, when run without a hypervisor the kernel is
 	  theoretically slower.  If in doubt, say N.
 
+config VMI
+	bool "VMI Paravirt-ops support"
+	depends on PARAVIRT && !NO_HZ
+	default y
+	help
+	  VMI provides a paravirtualized interface to multiple hypervisors
+	  include VMware ESX server and Xen by connecting to a ROM module
+	  provided by the hypervisor.
+
 config ACPI_SRAT
 	bool
 	default y
@@ -1259,3 +1287,12 @@
 config KTIME_SCALAR
 	bool
 	default y
+
+config NO_IDLE_HZ
+	bool
+	depends on PARAVIRT
+	default y
+	help
+	  Switches the regular HZ timer off when the system is going idle.
+	  This helps a hypervisor detect that the Linux system is idle,
+	  reducing the overhead of idle systems.
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index 2aecfba..b99c0e2 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -226,11 +226,6 @@
 	depends on !M386
 	default y
 
-config X86_XADD
-	bool
-	depends on !M386
-	default y
-
 config X86_L1_CACHE_SHIFT
 	int
 	default "7" if MPENTIUM4 || X86_GENERIC
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
index f68cc6f..458bc16 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/i386/Kconfig.debug
@@ -87,7 +87,7 @@
 
 config DEBUG_PARAVIRT
 	bool "Enable some paravirtualization debugging"
-	default y
+	default n
 	depends on PARAVIRT && DEBUG_KERNEL
 	help
 	  Currently deliberately clobbers regs which are allowed to be
diff --git a/arch/i386/boot/compressed/relocs.c b/arch/i386/boot/compressed/relocs.c
index 881951c..ce4fda2 100644
--- a/arch/i386/boot/compressed/relocs.c
+++ b/arch/i386/boot/compressed/relocs.c
@@ -11,6 +11,7 @@
 #include <endian.h>
 
 #define MAX_SHDRS 100
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 static Elf32_Ehdr ehdr;
 static Elf32_Shdr shdr[MAX_SHDRS];
 static Elf32_Sym  *symtab[MAX_SHDRS];
@@ -71,7 +72,7 @@
 #undef SYM_TYPE
 	};
 	const char *name = "unknown sym type name";
-	if (type < sizeof(type_name)/sizeof(type_name[0])) {
+	if (type < ARRAY_SIZE(type_name)) {
 		name = type_name[type];
 	}
 	return name;
@@ -87,7 +88,7 @@
 #undef SYM_BIND
 	};
 	const char *name = "unknown sym bind name";
-	if (bind < sizeof(bind_name)/sizeof(bind_name[0])) {
+	if (bind < ARRAY_SIZE(bind_name)) {
 		name = bind_name[bind];
 	}
 	return name;
@@ -104,7 +105,7 @@
 #undef SYM_VISIBILITY
 	};
 	const char *name = "unknown sym visibility name";
-	if (visibility < sizeof(visibility_name)/sizeof(visibility_name[0])) {
+	if (visibility < ARRAY_SIZE(visibility_name)) {
 		name = visibility_name[visibility];
 	}
 	return name;
@@ -128,7 +129,7 @@
 #undef REL_TYPE
 	};
 	const char *name = "unknown type rel type name";
-	if (type < sizeof(type_name)/sizeof(type_name[0])) {
+	if (type < ARRAY_SIZE(type_name)) {
 		name = type_name[type];
 	}
 	return name;
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index bb0c376..5ae1e0b 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc3
-# Fri Jan  5 11:54:46 2007
+# Linux kernel version: 2.6.20-git8
+# Tue Feb 13 11:25:18 2007
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -10,6 +10,7 @@
 CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_X86=y
 CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
 CONFIG_GENERIC_BUG=y
@@ -139,7 +140,6 @@
 # CONFIG_MVIAC3_2 is not set
 CONFIG_X86_GENERIC=y
 CONFIG_X86_CMPXCHG=y
-CONFIG_X86_XADD=y
 CONFIG_X86_L1_CACHE_SHIFT=7
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -198,6 +198,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HIGHPTE is not set
 # CONFIG_MATH_EMULATION is not set
 CONFIG_MTRR=y
@@ -211,6 +212,7 @@
 CONFIG_HZ=250
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x100000
 # CONFIG_RELOCATABLE is not set
 CONFIG_PHYSICAL_ALIGN=0x100000
 # CONFIG_HOTPLUG_CPU is not set
@@ -229,13 +231,14 @@
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
+CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_AC=y
 CONFIG_ACPI_BATTERY=y
 CONFIG_ACPI_BUTTON=y
-# CONFIG_ACPI_VIDEO is not set
 # CONFIG_ACPI_HOTKEY is not set
 CONFIG_ACPI_FAN=y
 # CONFIG_ACPI_DOCK is not set
+# CONFIG_ACPI_BAY is not set
 CONFIG_ACPI_PROCESSOR=y
 CONFIG_ACPI_THERMAL=y
 # CONFIG_ACPI_ASUS is not set
@@ -306,7 +309,6 @@
 CONFIG_PCI_MMCONFIG=y
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_PCI_MSI=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_HT_IRQ is not set
 CONFIG_ISA_DMA_API=y
@@ -347,6 +349,7 @@
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -446,6 +449,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -466,8 +470,7 @@
 #
 # Plug and Play support
 #
-CONFIG_PNP=y
-CONFIG_PNPACPI=y
+# CONFIG_PNP is not set
 
 #
 # Block devices
@@ -515,6 +518,7 @@
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_BLK_DEV_IDEACPI=y
 # CONFIG_IDE_TASK_IOCTL is not set
 
 #
@@ -547,6 +551,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT8213 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
@@ -557,6 +562,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -655,6 +661,7 @@
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_SVW=y
 CONFIG_ATA_PIIX=y
@@ -670,6 +677,7 @@
 # CONFIG_SATA_ULI is not set
 CONFIG_SATA_VIA=y
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 CONFIG_SATA_INTEL_COMBINED=y
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
@@ -687,6 +695,7 @@
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -739,9 +748,7 @@
 # Subsystem Options
 #
 # CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
 # CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
 
 #
 # Device Drivers
@@ -767,6 +774,11 @@
 # CONFIG_I2O is not set
 
 #
+# Macintosh device drivers
+#
+# CONFIG_MAC_EMUMOUSEBTN is not set
+
+#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -833,6 +845,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -855,11 +868,13 @@
 CONFIG_TIGON3=y
 CONFIG_BNX2=y
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
@@ -1090,6 +1105,7 @@
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
+CONFIG_OBSOLETE_OSS=y
 # CONFIG_SOUND_BT878 is not set
 # CONFIG_SOUND_ES1371 is not set
 CONFIG_SOUND_ICH=y
@@ -1103,6 +1119,7 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -1117,10 +1134,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1130,9 +1145,11 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
@@ -1183,6 +1200,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1288,6 +1306,10 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
 # Virtualization
 #
 # CONFIG_KVM is not set
@@ -1480,6 +1502,7 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
@@ -1488,7 +1511,6 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -1533,7 +1555,8 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_PENDING_IRQ=y
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 1e8988e..4ae3dcf 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -18,7 +18,7 @@
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 obj-$(CONFIG_MICROCODE)		+= microcode.o
 obj-$(CONFIG_APM)		+= apm.o
-obj-$(CONFIG_X86_SMP)		+= smp.o smpboot.o
+obj-$(CONFIG_X86_SMP)		+= smp.o smpboot.o tsc_sync.o
 obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o nmi.o
@@ -32,7 +32,6 @@
 obj-$(CONFIG_MODULES)		+= module.o
 obj-y				+= sysenter.o vsyscall.o
 obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
-obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
 obj-$(CONFIG_DOUBLEFAULT) 	+= doublefault.o
 obj-$(CONFIG_VM86)		+= vm86.o
@@ -40,8 +39,9 @@
 obj-$(CONFIG_HPET_TIMER) 	+= hpet.o
 obj-$(CONFIG_K8_NB)		+= k8.o
 
-# Make sure this is linked after any other paravirt_ops structs: see head.S
+obj-$(CONFIG_VMI)		+= vmi.o vmitime.o
 obj-$(CONFIG_PARAVIRT)		+= paravirt.o
+obj-y				+= pcspeaker.o
 
 EXTRA_AFLAGS   := -traditional
 
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index e94aff6..e5eb97a 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -25,6 +25,7 @@
 
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/acpi_pmtmr.h>
 #include <linux/efi.h>
 #include <linux/cpumask.h>
 #include <linux/module.h>
@@ -615,6 +616,7 @@
 }
 
 #ifdef CONFIG_HPET_TIMER
+#include <asm/hpet.h>
 
 static int __init acpi_parse_hpet(struct acpi_table_header *table)
 {
@@ -645,24 +647,11 @@
 		hpet_res->end = (1 * 1024) - 1;
 	}
 
-#ifdef CONFIG_X86_64
-	vxtime.hpet_address = hpet_tbl->address.address;
-
+	hpet_address = hpet_tbl->address.address;
 	printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
-		hpet_tbl->id, vxtime.hpet_address);
+	       hpet_tbl->id, hpet_address);
 
-	res_start = vxtime.hpet_address;
-#else                          /* X86 */
-	{
-		extern unsigned long hpet_address;
-
-		hpet_address = hpet_tbl->address.address;
-		printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
-			hpet_tbl->id, hpet_address);
-
-		res_start = hpet_address;
-	}
-#endif                         /* X86 */
+	res_start = hpet_address;
 
 	if (hpet_res) {
 		hpet_res->start = res_start;
@@ -676,10 +665,6 @@
 #define	acpi_parse_hpet	NULL
 #endif
 
-#ifdef CONFIG_X86_PM_TIMER
-extern u32 pmtmr_ioport;
-#endif
-
 static int __init acpi_parse_fadt(struct acpi_table_header *table)
 {
 
@@ -865,10 +850,9 @@
 static void __init acpi_process_madt(void)
 {
 #ifdef CONFIG_X86_LOCAL_APIC
-	int count, error;
+	int error;
 
-	count = acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt);
-	if (count >= 1) {
+	if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
 
 		/*
 		 * Parse MADT LAPIC entries
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 776d9be..7a2c9cb 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -25,6 +25,8 @@
 #include <linux/kernel_stat.h>
 #include <linux/sysdev.h>
 #include <linux/cpu.h>
+#include <linux/clockchips.h>
+#include <linux/acpi_pmtmr.h>
 #include <linux/module.h>
 
 #include <asm/atomic.h>
@@ -44,128 +46,548 @@
 #include "io_ports.h"
 
 /*
- * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
- * IPIs in place of local APIC timers
+ * Sanity check
  */
-static cpumask_t timer_bcast_ipi;
+#if (SPURIOUS_APIC_VECTOR & 0x0F) != 0x0F
+# error SPURIOUS_APIC_VECTOR definition error
+#endif
 
 /*
  * Knob to control our willingness to enable the local APIC.
+ *
+ * -1=force-disable, +1=force-enable
  */
-static int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
+static int enable_local_apic __initdata = 0;
 
-static inline void lapic_disable(void)
-{
-	enable_local_apic = -1;
-	clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-}
-
-static inline void lapic_enable(void)
-{
-	enable_local_apic = 1;
-}
+/* Local APIC timer verification ok */
+static int local_apic_timer_verify_ok;
 
 /*
- * Debug level
+ * Debug level, exported for io_apic.c
  */
 int apic_verbosity;
 
+static unsigned int calibration_result;
 
+static int lapic_next_event(unsigned long delta,
+			    struct clock_event_device *evt);
+static void lapic_timer_setup(enum clock_event_mode mode,
+			      struct clock_event_device *evt);
+static void lapic_timer_broadcast(cpumask_t mask);
 static void apic_pm_activate(void);
 
-static int modern_apic(void)
+/*
+ * The local apic timer can be used for any function which is CPU local.
+ */
+static struct clock_event_device lapic_clockevent = {
+	.name		= "lapic",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
+			| CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
+	.shift		= 32,
+	.set_mode	= lapic_timer_setup,
+	.set_next_event	= lapic_next_event,
+	.broadcast	= lapic_timer_broadcast,
+	.rating		= 100,
+	.irq		= -1,
+};
+static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
+
+/* Local APIC was disabled by the BIOS and enabled by the kernel */
+static int enabled_via_apicbase;
+
+/*
+ * Get the LAPIC version
+ */
+static inline int lapic_get_version(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;
+	return GET_APIC_VERSION(apic_read(APIC_LVR));
 }
 
 /*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves.
+ * Check, if the APIC is integrated or a seperate chip
  */
-void ack_bad_irq(unsigned int irq)
+static inline int lapic_is_integrated(void)
 {
-	printk("unexpected IRQ trap at vector %02x\n", irq);
-	/*
-	 * Currently unexpected vectors happen only on SMP and APIC.
-	 * We _must_ ack these because every local APIC has only N
-	 * irq slots per priority level, and a 'hanging, unacked' IRQ
-	 * holds up an irq slot - in excessive cases (when multiple
-	 * unexpected vectors occur) that might lock up the APIC
-	 * completely.
-	 * But only ack when the APIC is enabled -AK
-	 */
-	if (cpu_has_apic)
-		ack_APIC_irq();
+	return APIC_INTEGRATED(lapic_get_version());
 }
 
-void __init apic_intr_init(void)
+/*
+ * Check, whether this is a modern or a first generation APIC
+ */
+static int modern_apic(void)
 {
-#ifdef CONFIG_SMP
-	smp_intr_init();
-#endif
-	/* self generated IPI for local APIC timer */
-	set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
-	/* IPI vectors for APIC spurious and error interrupts */
-	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
-	set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-
-	/* thermal monitor LVT interrupt */
-#ifdef CONFIG_X86_MCE_P4THERMAL
-	set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
-#endif
+	/* 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;
+	return lapic_get_version() >= 0x14;
 }
 
-/* Using APIC to generate smp_local_timer_interrupt? */
-int using_apic_timer __read_mostly = 0;
-
-static int enabled_via_apicbase;
-
+/**
+ * enable_NMI_through_LVT0 - enable NMI through local vector table 0
+ */
 void enable_NMI_through_LVT0 (void * dummy)
 {
-	unsigned int v, ver;
+	unsigned int v = APIC_DM_NMI;
 
-	ver = apic_read(APIC_LVR);
-	ver = GET_APIC_VERSION(ver);
-	v = APIC_DM_NMI;			/* unmask and set to NMI */
-	if (!APIC_INTEGRATED(ver))		/* 82489DX */
+	/* Level triggered for 82489DX */
+	if (!lapic_is_integrated())
 		v |= APIC_LVT_LEVEL_TRIGGER;
 	apic_write_around(APIC_LVT0, v);
 }
 
+/**
+ * get_physical_broadcast - Get number of physical broadcast IDs
+ */
 int get_physical_broadcast(void)
 {
-	if (modern_apic())
-		return 0xff;
-	else
-		return 0xf;
+	return modern_apic() ? 0xff : 0xf;
 }
 
-int get_maxlvt(void)
+/**
+ * lapic_get_maxlvt - get the maximum number of local vector table entries
+ */
+int lapic_get_maxlvt(void)
 {
-	unsigned int v, ver, maxlvt;
+	unsigned int v = apic_read(APIC_LVR);
 
-	v = apic_read(APIC_LVR);
-	ver = GET_APIC_VERSION(v);
 	/* 82489DXs do not report # of LVT entries. */
-	maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(v) : 2;
-	return maxlvt;
+	return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2;
 }
 
+/*
+ * Local APIC timer
+ */
+
+/* Clock divisor is set to 16 */
+#define APIC_DIVISOR 16
+
+/*
+ * This function sets up the local APIC timer, with a timeout of
+ * 'clocks' APIC bus clock. During calibration we actually call
+ * this function twice on the boot CPU, once with a bogus timeout
+ * value, second time for real. The other (noncalibrating) CPUs
+ * call this function only once, with the real, calibrated value.
+ *
+ * We do reads before writes even if unnecessary, to get around the
+ * P5 APIC double write bug.
+ */
+static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
+{
+	unsigned int lvtt_value, tmp_value;
+
+	lvtt_value = LOCAL_TIMER_VECTOR;
+	if (!oneshot)
+		lvtt_value |= APIC_LVT_TIMER_PERIODIC;
+	if (!lapic_is_integrated())
+		lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
+
+	if (!irqen)
+		lvtt_value |= APIC_LVT_MASKED;
+
+	apic_write_around(APIC_LVTT, lvtt_value);
+
+	/*
+	 * Divide PICLK by 16
+	 */
+	tmp_value = apic_read(APIC_TDCR);
+	apic_write_around(APIC_TDCR, (tmp_value
+				& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
+				| APIC_TDR_DIV_16);
+
+	if (!oneshot)
+		apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
+}
+
+/*
+ * Program the next event, relative to now
+ */
+static int lapic_next_event(unsigned long delta,
+			    struct clock_event_device *evt)
+{
+	apic_write_around(APIC_TMICT, delta);
+	return 0;
+}
+
+/*
+ * Setup the lapic timer in periodic or oneshot mode
+ */
+static void lapic_timer_setup(enum clock_event_mode mode,
+			      struct clock_event_device *evt)
+{
+	unsigned long flags;
+	unsigned int v;
+
+	/* Lapic used for broadcast ? */
+	if (!local_apic_timer_verify_ok)
+		return;
+
+	local_irq_save(flags);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+	case CLOCK_EVT_MODE_ONESHOT:
+		__setup_APIC_LVTT(calibration_result,
+				  mode != CLOCK_EVT_MODE_PERIODIC, 1);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		v = apic_read(APIC_LVTT);
+		v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+		apic_write_around(APIC_LVTT, v);
+		break;
+	}
+
+	local_irq_restore(flags);
+}
+
+/*
+ * Local APIC timer broadcast function
+ */
+static void lapic_timer_broadcast(cpumask_t mask)
+{
+#ifdef CONFIG_SMP
+	send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
+#endif
+}
+
+/*
+ * Setup the local APIC timer for this CPU. Copy the initilized values
+ * of the boot CPU and register the clock event in the framework.
+ */
+static void __devinit setup_APIC_timer(void)
+{
+	struct clock_event_device *levt = &__get_cpu_var(lapic_events);
+
+	memcpy(levt, &lapic_clockevent, sizeof(*levt));
+	levt->cpumask = cpumask_of_cpu(smp_processor_id());
+
+	clockevents_register_device(levt);
+}
+
+/*
+ * In this functions we calibrate APIC bus clocks to the external timer.
+ *
+ * We want to do the calibration only once since we want to have local timer
+ * irqs syncron. CPUs connected by the same APIC bus have the very same bus
+ * frequency.
+ *
+ * This was previously done by reading the PIT/HPET and waiting for a wrap
+ * around to find out, that a tick has elapsed. I have a box, where the PIT
+ * readout is broken, so it never gets out of the wait loop again. This was
+ * also reported by others.
+ *
+ * Monitoring the jiffies value is inaccurate and the clockevents
+ * infrastructure allows us to do a simple substitution of the interrupt
+ * handler.
+ *
+ * The calibration routine also uses the pm_timer when possible, as the PIT
+ * happens to run way too slow (factor 2.3 on my VAIO CoreDuo, which goes
+ * back to normal later in the boot process).
+ */
+
+#define LAPIC_CAL_LOOPS		(HZ/10)
+
+static __initdata volatile int lapic_cal_loops = -1;
+static __initdata long lapic_cal_t1, lapic_cal_t2;
+static __initdata unsigned long long lapic_cal_tsc1, lapic_cal_tsc2;
+static __initdata unsigned long lapic_cal_pm1, lapic_cal_pm2;
+static __initdata unsigned long lapic_cal_j1, lapic_cal_j2;
+
+/*
+ * Temporary interrupt handler.
+ */
+static void __init lapic_cal_handler(struct clock_event_device *dev)
+{
+	unsigned long long tsc = 0;
+	long tapic = apic_read(APIC_TMCCT);
+	unsigned long pm = acpi_pm_read_early();
+
+	if (cpu_has_tsc)
+		rdtscll(tsc);
+
+	switch (lapic_cal_loops++) {
+	case 0:
+		lapic_cal_t1 = tapic;
+		lapic_cal_tsc1 = tsc;
+		lapic_cal_pm1 = pm;
+		lapic_cal_j1 = jiffies;
+		break;
+
+	case LAPIC_CAL_LOOPS:
+		lapic_cal_t2 = tapic;
+		lapic_cal_tsc2 = tsc;
+		if (pm < lapic_cal_pm1)
+			pm += ACPI_PM_OVRRUN;
+		lapic_cal_pm2 = pm;
+		lapic_cal_j2 = jiffies;
+		break;
+	}
+}
+
+/*
+ * Setup the boot APIC
+ *
+ * Calibrate and verify the result.
+ */
+void __init setup_boot_APIC_clock(void)
+{
+	struct clock_event_device *levt = &__get_cpu_var(lapic_events);
+	const long pm_100ms = PMTMR_TICKS_PER_SEC/10;
+	const long pm_thresh = pm_100ms/100;
+	void (*real_handler)(struct clock_event_device *dev);
+	unsigned long deltaj;
+	long delta, deltapm;
+
+	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
+		    "calibrating APIC timer ...\n");
+
+	local_irq_disable();
+
+	/* Replace the global interrupt handler */
+	real_handler = global_clock_event->event_handler;
+	global_clock_event->event_handler = lapic_cal_handler;
+
+	/*
+	 * Setup the APIC counter to 1e9. There is no way the lapic
+	 * can underflow in the 100ms detection time frame
+	 */
+	__setup_APIC_LVTT(1000000000, 0, 0);
+
+	/* Let the interrupts run */
+	local_irq_enable();
+
+	while(lapic_cal_loops <= LAPIC_CAL_LOOPS);
+
+	local_irq_disable();
+
+	/* Restore the real event handler */
+	global_clock_event->event_handler = real_handler;
+
+	/* Build delta t1-t2 as apic timer counts down */
+	delta = lapic_cal_t1 - lapic_cal_t2;
+	apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta);
+
+	/* Check, if the PM timer is available */
+	deltapm = lapic_cal_pm2 - lapic_cal_pm1;
+	apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm);
+
+	if (deltapm) {
+		unsigned long mult;
+		u64 res;
+
+		mult = clocksource_hz2mult(PMTMR_TICKS_PER_SEC, 22);
+
+		if (deltapm > (pm_100ms - pm_thresh) &&
+		    deltapm < (pm_100ms + pm_thresh)) {
+			apic_printk(APIC_VERBOSE, "... PM timer result ok\n");
+		} else {
+			res = (((u64) deltapm) *  mult) >> 22;
+			do_div(res, 1000000);
+			printk(KERN_WARNING "APIC calibration not consistent "
+			       "with PM Timer: %ldms instead of 100ms\n",
+			       (long)res);
+			/* Correct the lapic counter value */
+			res = (((u64) delta ) * pm_100ms);
+			do_div(res, deltapm);
+			printk(KERN_INFO "APIC delta adjusted to PM-Timer: "
+			       "%lu (%ld)\n", (unsigned long) res, delta);
+			delta = (long) res;
+		}
+	}
+
+	/* Calculate the scaled math multiplication factor */
+	lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, 32);
+	lapic_clockevent.max_delta_ns =
+		clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+	lapic_clockevent.min_delta_ns =
+		clockevent_delta2ns(0xF, &lapic_clockevent);
+
+	calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
+
+	apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
+	apic_printk(APIC_VERBOSE, "..... mult: %ld\n", lapic_clockevent.mult);
+	apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
+		    calibration_result);
+
+	if (cpu_has_tsc) {
+		delta = (long)(lapic_cal_tsc2 - lapic_cal_tsc1);
+		apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
+			    "%ld.%04ld MHz.\n",
+			    (delta / LAPIC_CAL_LOOPS) / (1000000 / HZ),
+			    (delta / LAPIC_CAL_LOOPS) % (1000000 / HZ));
+	}
+
+	apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
+		    "%u.%04u MHz.\n",
+		    calibration_result / (1000000 / HZ),
+		    calibration_result % (1000000 / HZ));
+
+
+	apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
+
+	/*
+	 * Setup the apic timer manually
+	 */
+	local_apic_timer_verify_ok = 1;
+	levt->event_handler = lapic_cal_handler;
+	lapic_timer_setup(CLOCK_EVT_MODE_PERIODIC, levt);
+	lapic_cal_loops = -1;
+
+	/* Let the interrupts run */
+	local_irq_enable();
+
+	while(lapic_cal_loops <= LAPIC_CAL_LOOPS);
+
+	local_irq_disable();
+
+	/* Stop the lapic timer */
+	lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, levt);
+
+	local_irq_enable();
+
+	/* Jiffies delta */
+	deltaj = lapic_cal_j2 - lapic_cal_j1;
+	apic_printk(APIC_VERBOSE, "... jiffies delta = %lu\n", deltaj);
+
+	/* Check, if the PM timer is available */
+	deltapm = lapic_cal_pm2 - lapic_cal_pm1;
+	apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm);
+
+	local_apic_timer_verify_ok = 0;
+
+	if (deltapm) {
+		if (deltapm > (pm_100ms - pm_thresh) &&
+		    deltapm < (pm_100ms + pm_thresh)) {
+			apic_printk(APIC_VERBOSE, "... PM timer result ok\n");
+			/* Check, if the jiffies result is consistent */
+			if (deltaj < LAPIC_CAL_LOOPS-2 ||
+			    deltaj > LAPIC_CAL_LOOPS+2) {
+				/*
+				 * Not sure, what we can do about this one.
+				 * When high resultion timers are active
+				 * and the lapic timer does not stop in C3
+				 * we are fine. Otherwise more trouble might
+				 * be waiting. -- tglx
+				 */
+				printk(KERN_WARNING "Global event device %s "
+				       "has wrong frequency "
+				       "(%lu ticks instead of %d)\n",
+				       global_clock_event->name, deltaj,
+				       LAPIC_CAL_LOOPS);
+			}
+			local_apic_timer_verify_ok = 1;
+		}
+	} else {
+		/* Check, if the jiffies result is consistent */
+		if (deltaj >= LAPIC_CAL_LOOPS-2 &&
+		    deltaj <= LAPIC_CAL_LOOPS+2) {
+			apic_printk(APIC_VERBOSE, "... jiffies result ok\n");
+			local_apic_timer_verify_ok = 1;
+		}
+	}
+
+	if (!local_apic_timer_verify_ok) {
+		printk(KERN_WARNING
+		       "APIC timer disabled due to verification failure.\n");
+		/* No broadcast on UP ! */
+		if (num_possible_cpus() == 1)
+			return;
+	} else
+		lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+
+	/* Setup the lapic or request the broadcast */
+	setup_APIC_timer();
+}
+
+void __devinit setup_secondary_APIC_clock(void)
+{
+	setup_APIC_timer();
+}
+
+/*
+ * The guts of the apic timer interrupt
+ */
+static void local_apic_timer_interrupt(void)
+{
+	int cpu = smp_processor_id();
+	struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
+
+	/*
+	 * Normally we should not be here till LAPIC has been initialized but
+	 * in some cases like kdump, its possible that there is a pending LAPIC
+	 * timer interrupt from previous kernel's context and is delivered in
+	 * new kernel the moment interrupts are enabled.
+	 *
+	 * Interrupts are enabled early and LAPIC is setup much later, hence
+	 * its possible that when we get here evt->event_handler is NULL.
+	 * Check for event_handler being NULL and discard the interrupt as
+	 * spurious.
+	 */
+	if (!evt->event_handler) {
+		printk(KERN_WARNING
+		       "Spurious LAPIC timer interrupt on cpu %d\n", cpu);
+		/* Switch it off */
+		lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt);
+		return;
+	}
+
+	per_cpu(irq_stat, cpu).apic_timer_irqs++;
+
+	evt->event_handler(evt);
+}
+
+/*
+ * Local APIC timer interrupt. This is the most natural way for doing
+ * local interrupts, but local timer interrupts can be emulated by
+ * broadcast interrupts too. [in case the hw doesn't support APIC timers]
+ *
+ * [ if a single-CPU system runs an SMP kernel then we call the local
+ *   interrupt as well. Thus we cannot inline the local irq ... ]
+ */
+
+void fastcall smp_apic_timer_interrupt(struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	/*
+	 * NOTE! We'd better ACK the irq immediately,
+	 * because timer handling can be slow.
+	 */
+	ack_APIC_irq();
+	/*
+	 * update_process_times() expects us to have done irq_enter().
+	 * Besides, if we don't timer interrupts ignore the global
+	 * interrupt lock, which is the WrongThing (tm) to do.
+	 */
+	irq_enter();
+	local_apic_timer_interrupt();
+	irq_exit();
+
+	set_irq_regs(old_regs);
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
+
+/*
+ * Local APIC start and shutdown
+ */
+
+/**
+ * clear_local_APIC - shutdown the local APIC
+ *
+ * This is called, when a CPU is disabled and before rebooting, so the state of
+ * the local APIC has no dangling leftovers. Also used to cleanout any BIOS
+ * leftovers during boot.
+ */
 void clear_local_APIC(void)
 {
-	int maxlvt;
+	int maxlvt = lapic_get_maxlvt();
 	unsigned long v;
 
-	maxlvt = get_maxlvt();
-
 	/*
 	 * Masking an LVT entry can trigger a local APIC error
 	 * if the vector is zero. Mask LVTERR first to prevent this.
@@ -189,7 +611,7 @@
 		apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
 	}
 
-/* lets not touch this if we didn't frob it */
+	/* lets not touch this if we didn't frob it */
 #ifdef CONFIG_X86_MCE_P4THERMAL
 	if (maxlvt >= 5) {
 		v = apic_read(APIC_LVTTHMR);
@@ -211,85 +633,18 @@
 	if (maxlvt >= 5)
 		apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
 #endif
-	v = GET_APIC_VERSION(apic_read(APIC_LVR));
-	if (APIC_INTEGRATED(v)) {	/* !82489DX */
-		if (maxlvt > 3)		/* Due to Pentium errata 3AP and 11AP. */
+	/* Integrated APIC (!82489DX) ? */
+	if (lapic_is_integrated()) {
+		if (maxlvt > 3)
+			/* Clear ESR due to Pentium errata 3AP and 11AP */
 			apic_write(APIC_ESR, 0);
 		apic_read(APIC_ESR);
 	}
 }
 
-void __init connect_bsp_APIC(void)
-{
-	if (pic_mode) {
-		/*
-		 * Do not trust the local APIC being empty at bootup.
-		 */
-		clear_local_APIC();
-		/*
-		 * PIC mode, enable APIC mode in the IMCR, i.e.
-		 * connect BSP's local APIC to INT and NMI lines.
-		 */
-		apic_printk(APIC_VERBOSE, "leaving PIC mode, "
-				"enabling APIC mode.\n");
-		outb(0x70, 0x22);
-		outb(0x01, 0x23);
-	}
-	enable_apic_mode();
-}
-
-void disconnect_bsp_APIC(int virt_wire_setup)
-{
-	if (pic_mode) {
-		/*
-		 * Put the board back into PIC mode (has an effect
-		 * only on certain older boards).  Note that APIC
-		 * interrupts, including IPIs, won't work beyond
-		 * this point!  The only exception are INIT IPIs.
-		 */
-		apic_printk(APIC_VERBOSE, "disabling APIC mode, "
-				"entering PIC mode.\n");
-		outb(0x70, 0x22);
-		outb(0x00, 0x23);
-	}
-	else {
-		/* Go back to Virtual Wire compatibility mode */
-		unsigned long value;
-
-		/* For the spurious interrupt use vector F, and enable it */
-		value = apic_read(APIC_SPIV);
-		value &= ~APIC_VECTOR_MASK;
-		value |= APIC_SPIV_APIC_ENABLED;
-		value |= 0xf;
-		apic_write_around(APIC_SPIV, value);
-
-		if (!virt_wire_setup) {
-			/* For LVT0 make it edge triggered, active high, external and enabled */
-			value = apic_read(APIC_LVT0);
-			value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
-				APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
-				APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
-			value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
-			value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
-			apic_write_around(APIC_LVT0, value);
-		}
-		else {
-			/* Disable LVT0 */
-			apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
-		}
-
-		/* For LVT1 make it edge triggered, active high, nmi and enabled */
-		value = apic_read(APIC_LVT1);
-		value &= ~(
-			APIC_MODE_MASK | APIC_SEND_PENDING |
-			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
-			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
-		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
-		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
-		apic_write_around(APIC_LVT1, value);
-	}
-}
-
+/**
+ * disable_local_APIC - clear and disable the local APIC
+ */
 void disable_local_APIC(void)
 {
 	unsigned long value;
@@ -304,8 +659,13 @@
 	value &= ~APIC_SPIV_APIC_ENABLED;
 	apic_write_around(APIC_SPIV, value);
 
+	/*
+	 * When LAPIC was disabled by the BIOS and enabled by the kernel,
+	 * restore the disabled state.
+	 */
 	if (enabled_via_apicbase) {
 		unsigned int l, h;
+
 		rdmsr(MSR_IA32_APICBASE, l, h);
 		l &= ~MSR_IA32_APICBASE_ENABLE;
 		wrmsr(MSR_IA32_APICBASE, l, h);
@@ -313,6 +673,28 @@
 }
 
 /*
+ * If Linux enabled the LAPIC against the BIOS default disable it down before
+ * re-entering the BIOS on shutdown.  Otherwise the BIOS may get confused and
+ * not power-off.  Additionally clear all LVT entries before disable_local_APIC
+ * for the case where Linux didn't enable the LAPIC.
+ */
+void lapic_shutdown(void)
+{
+	unsigned long flags;
+
+	if (!cpu_has_apic)
+		return;
+
+	local_irq_save(flags);
+	clear_local_APIC();
+
+	if (enabled_via_apicbase)
+		disable_local_APIC();
+
+	local_irq_restore(flags);
+}
+
+/*
  * This is to verify that we're looking at a real local APIC.
  * Check these against your board if the CPUs aren't getting
  * started for no apparent reason.
@@ -344,7 +726,7 @@
 	reg1 = GET_APIC_VERSION(reg0);
 	if (reg1 == 0x00 || reg1 == 0xff)
 		return 0;
-	reg1 = get_maxlvt();
+	reg1 = lapic_get_maxlvt();
 	if (reg1 < 0x02 || reg1 == 0xff)
 		return 0;
 
@@ -367,10 +749,15 @@
 	return 1;
 }
 
+/**
+ * sync_Arb_IDs - synchronize APIC bus arbitration IDs
+ */
 void __init sync_Arb_IDs(void)
 {
-	/* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1
-	   And not needed on AMD */
+	/*
+	 * Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 And not
+	 * needed on AMD.
+	 */
 	if (modern_apic())
 		return;
 	/*
@@ -383,14 +770,12 @@
 				| APIC_DM_INIT);
 }
 
-extern void __error_in_apic_c (void);
-
 /*
  * An initial setup of the virtual wire mode.
  */
 void __init init_bsp_APIC(void)
 {
-	unsigned long value, ver;
+	unsigned long value;
 
 	/*
 	 * Don't do the setup now if we have a SMP BIOS as the
@@ -399,9 +784,6 @@
 	if (smp_found_config || !cpu_has_apic)
 		return;
 
-	value = apic_read(APIC_LVR);
-	ver = GET_APIC_VERSION(value);
-
 	/*
 	 * Do not trust the local APIC being empty at bootup.
 	 */
@@ -413,9 +795,10 @@
 	value = apic_read(APIC_SPIV);
 	value &= ~APIC_VECTOR_MASK;
 	value |= APIC_SPIV_APIC_ENABLED;
-	
+
 	/* This bit is reserved on P4/Xeon and should be cleared */
-	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 15))
+	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+	    (boot_cpu_data.x86 == 15))
 		value &= ~APIC_SPIV_FOCUS_DISABLED;
 	else
 		value |= APIC_SPIV_FOCUS_DISABLED;
@@ -427,14 +810,17 @@
 	 */
 	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
 	value = APIC_DM_NMI;
-	if (!APIC_INTEGRATED(ver))		/* 82489DX */
+	if (!lapic_is_integrated())		/* 82489DX */
 		value |= APIC_LVT_LEVEL_TRIGGER;
 	apic_write_around(APIC_LVT1, value);
 }
 
+/**
+ * setup_local_APIC - setup the local APIC
+ */
 void __devinit setup_local_APIC(void)
 {
-	unsigned long oldvalue, value, ver, maxlvt;
+	unsigned long oldvalue, value, maxlvt, integrated;
 	int i, j;
 
 	/* Pound the ESR really hard over the head with a big hammer - mbligh */
@@ -445,11 +831,7 @@
 		apic_write(APIC_ESR, 0);
 	}
 
-	value = apic_read(APIC_LVR);
-	ver = GET_APIC_VERSION(value);
-
-	if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
-		__error_in_apic_c();
+	integrated = lapic_is_integrated();
 
 	/*
 	 * Double-check whether this APIC is really registered.
@@ -520,13 +902,10 @@
 	 * like LRU than MRU (the short-term load is more even across CPUs).
 	 * See also the comment in end_level_ioapic_irq().  --macro
 	 */
-#if 1
+
 	/* Enable focus processor (bit==0) */
 	value &= ~APIC_SPIV_FOCUS_DISABLED;
-#else
-	/* Disable focus processor (bit==1) */
-	value |= APIC_SPIV_FOCUS_DISABLED;
-#endif
+
 	/*
 	 * Set spurious IRQ vector
 	 */
@@ -562,17 +941,18 @@
 		value = APIC_DM_NMI;
 	else
 		value = APIC_DM_NMI | APIC_LVT_MASKED;
-	if (!APIC_INTEGRATED(ver))		/* 82489DX */
+	if (!integrated)		/* 82489DX */
 		value |= APIC_LVT_LEVEL_TRIGGER;
 	apic_write_around(APIC_LVT1, value);
 
-	if (APIC_INTEGRATED(ver) && !esr_disable) {		/* !82489DX */
-		maxlvt = get_maxlvt();
+	if (integrated && !esr_disable) {		/* !82489DX */
+		maxlvt = lapic_get_maxlvt();
 		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
 			apic_write(APIC_ESR, 0);
 		oldvalue = apic_read(APIC_ESR);
 
-		value = ERROR_APIC_VECTOR;      // enables sending errors
+		/* enables sending errors */
+		value = ERROR_APIC_VECTOR;
 		apic_write_around(APIC_LVTERR, value);
 		/*
 		 * spec says clear errors after enabling vector.
@@ -585,45 +965,415 @@
 				"vector: 0x%08lx  after: 0x%08lx\n",
 				oldvalue, value);
 	} else {
-		if (esr_disable)	
-			/* 
-			 * Something untraceble is creating bad interrupts on 
+		if (esr_disable)
+			/*
+			 * Something untraceble is creating bad interrupts on
 			 * secondary quads ... for the moment, just leave the
 			 * ESR disabled - we can't do anything useful with the
 			 * errors anyway - mbligh
 			 */
-			printk("Leaving ESR disabled.\n");
-		else 
-			printk("No ESR for 82489DX.\n");
+			printk(KERN_INFO "Leaving ESR disabled.\n");
+		else
+			printk(KERN_INFO "No ESR for 82489DX.\n");
 	}
 
+	/* Disable the local apic timer */
+	value = apic_read(APIC_LVTT);
+	value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+	apic_write_around(APIC_LVTT, value);
+
 	setup_apic_nmi_watchdog(NULL);
 	apic_pm_activate();
 }
 
 /*
- * If Linux enabled the LAPIC against the BIOS default
- * disable it down before re-entering the BIOS on shutdown.
- * Otherwise the BIOS may get confused and not power-off.
- * Additionally clear all LVT entries before disable_local_APIC
- * for the case where Linux didn't enable the LAPIC.
+ * Detect and initialize APIC
  */
-void lapic_shutdown(void)
+static int __init detect_init_APIC (void)
 {
-	unsigned long flags;
+	u32 h, l, features;
 
-	if (!cpu_has_apic)
-		return;
+	/* Disabled by kernel option? */
+	if (enable_local_apic < 0)
+		return -1;
 
-	local_irq_save(flags);
-	clear_local_APIC();
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_AMD:
+		if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
+		    (boot_cpu_data.x86 == 15))
+			break;
+		goto no_apic;
+	case X86_VENDOR_INTEL:
+		if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||
+		    (boot_cpu_data.x86 == 5 && cpu_has_apic))
+			break;
+		goto no_apic;
+	default:
+		goto no_apic;
+	}
 
-	if (enabled_via_apicbase)
-		disable_local_APIC();
+	if (!cpu_has_apic) {
+		/*
+		 * Over-ride BIOS and try to enable the local APIC only if
+		 * "lapic" specified.
+		 */
+		if (enable_local_apic <= 0) {
+			printk(KERN_INFO "Local APIC disabled by BIOS -- "
+			       "you can enable it with \"lapic\"\n");
+			return -1;
+		}
+		/*
+		 * Some BIOSes disable the local APIC in the APIC_BASE
+		 * MSR. This can only be done in software for Intel P6 or later
+		 * and AMD K7 (Model > 1) or later.
+		 */
+		rdmsr(MSR_IA32_APICBASE, l, h);
+		if (!(l & MSR_IA32_APICBASE_ENABLE)) {
+			printk(KERN_INFO
+			       "Local APIC disabled by BIOS -- reenabling.\n");
+			l &= ~MSR_IA32_APICBASE_BASE;
+			l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+			wrmsr(MSR_IA32_APICBASE, l, h);
+			enabled_via_apicbase = 1;
+		}
+	}
+	/*
+	 * The APIC feature bit should now be enabled
+	 * in `cpuid'
+	 */
+	features = cpuid_edx(1);
+	if (!(features & (1 << X86_FEATURE_APIC))) {
+		printk(KERN_WARNING "Could not enable APIC!\n");
+		return -1;
+	}
+	set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
 
-	local_irq_restore(flags);
+	/* The BIOS may have set up the APIC at some other address */
+	rdmsr(MSR_IA32_APICBASE, l, h);
+	if (l & MSR_IA32_APICBASE_ENABLE)
+		mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
+
+	if (nmi_watchdog != NMI_NONE)
+		nmi_watchdog = NMI_LOCAL_APIC;
+
+	printk(KERN_INFO "Found and enabled local APIC!\n");
+
+	apic_pm_activate();
+
+	return 0;
+
+no_apic:
+	printk(KERN_INFO "No local APIC present or hardware disabled\n");
+	return -1;
 }
 
+/**
+ * init_apic_mappings - initialize APIC mappings
+ */
+void __init init_apic_mappings(void)
+{
+	unsigned long apic_phys;
+
+	/*
+	 * If no local APIC can be found then set up a fake all
+	 * zeroes page to simulate the local APIC and another
+	 * one for the IO-APIC.
+	 */
+	if (!smp_found_config && detect_init_APIC()) {
+		apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
+		apic_phys = __pa(apic_phys);
+	} else
+		apic_phys = mp_lapic_addr;
+
+	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
+	printk(KERN_DEBUG "mapped APIC to %08lx (%08lx)\n", APIC_BASE,
+	       apic_phys);
+
+	/*
+	 * Fetch the APIC ID of the BSP in case we have a
+	 * default configuration (or the MP table is broken).
+	 */
+	if (boot_cpu_physical_apicid == -1U)
+		boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+
+#ifdef CONFIG_X86_IO_APIC
+	{
+		unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
+		int i;
+
+		for (i = 0; i < nr_ioapics; i++) {
+			if (smp_found_config) {
+				ioapic_phys = mp_ioapics[i].mpc_apicaddr;
+				if (!ioapic_phys) {
+					printk(KERN_ERR
+					       "WARNING: bogus zero IO-APIC "
+					       "address found in MPTABLE, "
+					       "disabling IO/APIC support!\n");
+					smp_found_config = 0;
+					skip_ioapic_setup = 1;
+					goto fake_ioapic_page;
+				}
+			} else {
+fake_ioapic_page:
+				ioapic_phys = (unsigned long)
+					      alloc_bootmem_pages(PAGE_SIZE);
+				ioapic_phys = __pa(ioapic_phys);
+			}
+			set_fixmap_nocache(idx, ioapic_phys);
+			printk(KERN_DEBUG "mapped IOAPIC to %08lx (%08lx)\n",
+			       __fix_to_virt(idx), ioapic_phys);
+			idx++;
+		}
+	}
+#endif
+}
+
+/*
+ * This initializes the IO-APIC and APIC hardware if this is
+ * a UP kernel.
+ */
+int __init APIC_init_uniprocessor (void)
+{
+	if (enable_local_apic < 0)
+		clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+
+	if (!smp_found_config && !cpu_has_apic)
+		return -1;
+
+	/*
+	 * Complain if the BIOS pretends there is one.
+	 */
+	if (!cpu_has_apic &&
+	    APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
+		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+		       boot_cpu_physical_apicid);
+		clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+		return -1;
+	}
+
+	verify_local_APIC();
+
+	connect_bsp_APIC();
+
+	/*
+	 * Hack: In case of kdump, after a crash, kernel might be booting
+	 * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
+	 * might be zero if read from MP tables. Get it from LAPIC.
+	 */
+#ifdef CONFIG_CRASH_DUMP
+	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+#endif
+	phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
+
+	setup_local_APIC();
+
+#ifdef CONFIG_X86_IO_APIC
+	if (smp_found_config)
+		if (!skip_ioapic_setup && nr_ioapics)
+			setup_IO_APIC();
+#endif
+	setup_boot_clock();
+
+	return 0;
+}
+
+/*
+ * APIC command line parameters
+ */
+static int __init parse_lapic(char *arg)
+{
+	enable_local_apic = 1;
+	return 0;
+}
+early_param("lapic", parse_lapic);
+
+static int __init parse_nolapic(char *arg)
+{
+	enable_local_apic = -1;
+	clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+	return 0;
+}
+early_param("nolapic", parse_nolapic);
+
+static int __init apic_set_verbosity(char *str)
+{
+	if (strcmp("debug", str) == 0)
+		apic_verbosity = APIC_DEBUG;
+	else if (strcmp("verbose", str) == 0)
+		apic_verbosity = APIC_VERBOSE;
+	return 1;
+}
+
+__setup("apic=", apic_set_verbosity);
+
+
+/*
+ * Local APIC interrupts
+ */
+
+/*
+ * This interrupt should _never_ happen with our APIC/SMP architecture
+ */
+void smp_spurious_interrupt(struct pt_regs *regs)
+{
+	unsigned long v;
+
+	irq_enter();
+	/*
+	 * Check if this really is a spurious interrupt and ACK it
+	 * if it is a vectored one.  Just in case...
+	 * Spurious interrupts should not be ACKed.
+	 */
+	v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
+	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
+		ack_APIC_irq();
+
+	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
+	printk(KERN_INFO "spurious APIC interrupt on CPU#%d, "
+	       "should never happen.\n", smp_processor_id());
+	irq_exit();
+}
+
+/*
+ * This interrupt should never happen with our APIC/SMP architecture
+ */
+void smp_error_interrupt(struct pt_regs *regs)
+{
+	unsigned long v, v1;
+
+	irq_enter();
+	/* First tickle the hardware, only then report what went on. -- REW */
+	v = apic_read(APIC_ESR);
+	apic_write(APIC_ESR, 0);
+	v1 = apic_read(APIC_ESR);
+	ack_APIC_irq();
+	atomic_inc(&irq_err_count);
+
+	/* Here is what the APIC error bits mean:
+	   0: Send CS error
+	   1: Receive CS error
+	   2: Send accept error
+	   3: Receive accept error
+	   4: Reserved
+	   5: Send illegal vector
+	   6: Received illegal vector
+	   7: Illegal register address
+	*/
+	printk (KERN_DEBUG "APIC error on CPU%d: %02lx(%02lx)\n",
+		smp_processor_id(), v , v1);
+	irq_exit();
+}
+
+/*
+ * Initialize APIC interrupts
+ */
+void __init apic_intr_init(void)
+{
+#ifdef CONFIG_SMP
+	smp_intr_init();
+#endif
+	/* self generated IPI for local APIC timer */
+	set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
+
+	/* IPI vectors for APIC spurious and error interrupts */
+	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+	set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+
+	/* thermal monitor LVT interrupt */
+#ifdef CONFIG_X86_MCE_P4THERMAL
+	set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
+#endif
+}
+
+/**
+ * connect_bsp_APIC - attach the APIC to the interrupt system
+ */
+void __init connect_bsp_APIC(void)
+{
+	if (pic_mode) {
+		/*
+		 * Do not trust the local APIC being empty at bootup.
+		 */
+		clear_local_APIC();
+		/*
+		 * PIC mode, enable APIC mode in the IMCR, i.e.  connect BSP's
+		 * local APIC to INT and NMI lines.
+		 */
+		apic_printk(APIC_VERBOSE, "leaving PIC mode, "
+				"enabling APIC mode.\n");
+		outb(0x70, 0x22);
+		outb(0x01, 0x23);
+	}
+	enable_apic_mode();
+}
+
+/**
+ * disconnect_bsp_APIC - detach the APIC from the interrupt system
+ * @virt_wire_setup:	indicates, whether virtual wire mode is selected
+ *
+ * Virtual wire mode is necessary to deliver legacy interrupts even when the
+ * APIC is disabled.
+ */
+void disconnect_bsp_APIC(int virt_wire_setup)
+{
+	if (pic_mode) {
+		/*
+		 * Put the board back into PIC mode (has an effect only on
+		 * certain older boards).  Note that APIC interrupts, including
+		 * IPIs, won't work beyond this point!  The only exception are
+		 * INIT IPIs.
+		 */
+		apic_printk(APIC_VERBOSE, "disabling APIC mode, "
+				"entering PIC mode.\n");
+		outb(0x70, 0x22);
+		outb(0x00, 0x23);
+	} else {
+		/* Go back to Virtual Wire compatibility mode */
+		unsigned long value;
+
+		/* For the spurious interrupt use vector F, and enable it */
+		value = apic_read(APIC_SPIV);
+		value &= ~APIC_VECTOR_MASK;
+		value |= APIC_SPIV_APIC_ENABLED;
+		value |= 0xf;
+		apic_write_around(APIC_SPIV, value);
+
+		if (!virt_wire_setup) {
+			/*
+			 * For LVT0 make it edge triggered, active high,
+			 * external and enabled
+			 */
+			value = apic_read(APIC_LVT0);
+			value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
+				APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+				APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
+			value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+			value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
+			apic_write_around(APIC_LVT0, value);
+		} else {
+			/* Disable LVT0 */
+			apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
+		}
+
+		/*
+		 * For LVT1 make it edge triggered, active high, nmi and
+		 * enabled
+		 */
+		value = apic_read(APIC_LVT1);
+		value &= ~(
+			APIC_MODE_MASK | APIC_SEND_PENDING |
+			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
+		apic_write_around(APIC_LVT1, value);
+	}
+}
+
+/*
+ * Power management
+ */
 #ifdef CONFIG_PM
 
 static struct {
@@ -652,7 +1402,7 @@
 	if (!apic_pm_state.active)
 		return 0;
 
-	maxlvt = get_maxlvt();
+	maxlvt = lapic_get_maxlvt();
 
 	apic_pm_state.apic_id = apic_read(APIC_ID);
 	apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
@@ -671,7 +1421,7 @@
 	if (maxlvt >= 5)
 		apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
 #endif
-	
+
 	local_irq_save(flags);
 	disable_local_APIC();
 	local_irq_restore(flags);
@@ -687,7 +1437,7 @@
 	if (!apic_pm_state.active)
 		return 0;
 
-	maxlvt = get_maxlvt();
+	maxlvt = lapic_get_maxlvt();
 
 	local_irq_save(flags);
 
@@ -769,648 +1519,3 @@
 static void apic_pm_activate(void) { }
 
 #endif	/* CONFIG_PM */
-
-/*
- * Detect and enable local APICs on non-SMP boards.
- * Original code written by Keir Fraser.
- */
-
-static int __init apic_set_verbosity(char *str)
-{
-	if (strcmp("debug", str) == 0)
-		apic_verbosity = APIC_DEBUG;
-	else if (strcmp("verbose", str) == 0)
-		apic_verbosity = APIC_VERBOSE;
-	return 1;
-}
-
-__setup("apic=", apic_set_verbosity);
-
-static int __init detect_init_APIC (void)
-{
-	u32 h, l, features;
-
-	/* Disabled by kernel option? */
-	if (enable_local_apic < 0)
-		return -1;
-
-	switch (boot_cpu_data.x86_vendor) {
-	case X86_VENDOR_AMD:
-		if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
-		    (boot_cpu_data.x86 == 15))	    
-			break;
-		goto no_apic;
-	case X86_VENDOR_INTEL:
-		if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||
-		    (boot_cpu_data.x86 == 5 && cpu_has_apic))
-			break;
-		goto no_apic;
-	default:
-		goto no_apic;
-	}
-
-	if (!cpu_has_apic) {
-		/*
-		 * Over-ride BIOS and try to enable the local
-		 * APIC only if "lapic" specified.
-		 */
-		if (enable_local_apic <= 0) {
-			printk("Local APIC disabled by BIOS -- "
-			       "you can enable it with \"lapic\"\n");
-			return -1;
-		}
-		/*
-		 * Some BIOSes disable the local APIC in the
-		 * APIC_BASE MSR. This can only be done in
-		 * software for Intel P6 or later and AMD K7
-		 * (Model > 1) or later.
-		 */
-		rdmsr(MSR_IA32_APICBASE, l, h);
-		if (!(l & MSR_IA32_APICBASE_ENABLE)) {
-			printk("Local APIC disabled by BIOS -- reenabling.\n");
-			l &= ~MSR_IA32_APICBASE_BASE;
-			l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
-			wrmsr(MSR_IA32_APICBASE, l, h);
-			enabled_via_apicbase = 1;
-		}
-	}
-	/*
-	 * The APIC feature bit should now be enabled
-	 * in `cpuid'
-	 */
-	features = cpuid_edx(1);
-	if (!(features & (1 << X86_FEATURE_APIC))) {
-		printk("Could not enable APIC!\n");
-		return -1;
-	}
-	set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-
-	/* The BIOS may have set up the APIC at some other address */
-	rdmsr(MSR_IA32_APICBASE, l, h);
-	if (l & MSR_IA32_APICBASE_ENABLE)
-		mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
-
-	if (nmi_watchdog != NMI_NONE)
-		nmi_watchdog = NMI_LOCAL_APIC;
-
-	printk("Found and enabled local APIC!\n");
-
-	apic_pm_activate();
-
-	return 0;
-
-no_apic:
-	printk("No local APIC present or hardware disabled\n");
-	return -1;
-}
-
-void __init init_apic_mappings(void)
-{
-	unsigned long apic_phys;
-
-	/*
-	 * If no local APIC can be found then set up a fake all
-	 * zeroes page to simulate the local APIC and another
-	 * one for the IO-APIC.
-	 */
-	if (!smp_found_config && detect_init_APIC()) {
-		apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
-		apic_phys = __pa(apic_phys);
-	} else
-		apic_phys = mp_lapic_addr;
-
-	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
-	printk(KERN_DEBUG "mapped APIC to %08lx (%08lx)\n", APIC_BASE,
-	       apic_phys);
-
-	/*
-	 * Fetch the APIC ID of the BSP in case we have a
-	 * default configuration (or the MP table is broken).
-	 */
-	if (boot_cpu_physical_apicid == -1U)
-		boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
-
-#ifdef CONFIG_X86_IO_APIC
-	{
-		unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
-		int i;
-
-		for (i = 0; i < nr_ioapics; i++) {
-			if (smp_found_config) {
-				ioapic_phys = mp_ioapics[i].mpc_apicaddr;
-				if (!ioapic_phys) {
-					printk(KERN_ERR
-					       "WARNING: bogus zero IO-APIC "
-					       "address found in MPTABLE, "
-					       "disabling IO/APIC support!\n");
-					smp_found_config = 0;
-					skip_ioapic_setup = 1;
-					goto fake_ioapic_page;
-				}
-			} else {
-fake_ioapic_page:
-				ioapic_phys = (unsigned long)
-					      alloc_bootmem_pages(PAGE_SIZE);
-				ioapic_phys = __pa(ioapic_phys);
-			}
-			set_fixmap_nocache(idx, ioapic_phys);
-			printk(KERN_DEBUG "mapped IOAPIC to %08lx (%08lx)\n",
-			       __fix_to_virt(idx), ioapic_phys);
-			idx++;
-		}
-	}
-#endif
-}
-
-/*
- * This part sets up the APIC 32 bit clock in LVTT1, with HZ interrupts
- * per second. We assume that the caller has already set up the local
- * APIC.
- *
- * The APIC timer is not exactly sync with the external timer chip, it
- * closely follows bus clocks.
- */
-
-/*
- * The timer chip is already set up at HZ interrupts per second here,
- * but we do not accept timer interrupts yet. We only allow the BP
- * to calibrate.
- */
-static unsigned int __devinit get_8254_timer_count(void)
-{
-	unsigned long flags;
-
-	unsigned int count;
-
-	spin_lock_irqsave(&i8253_lock, flags);
-
-	outb_p(0x00, PIT_MODE);
-	count = inb_p(PIT_CH0);
-	count |= inb_p(PIT_CH0) << 8;
-
-	spin_unlock_irqrestore(&i8253_lock, flags);
-
-	return count;
-}
-
-/* next tick in 8254 can be caught by catching timer wraparound */
-static void __devinit wait_8254_wraparound(void)
-{
-	unsigned int curr_count, prev_count;
-
-	curr_count = get_8254_timer_count();
-	do {
-		prev_count = curr_count;
-		curr_count = get_8254_timer_count();
-
-		/* workaround for broken Mercury/Neptune */
-		if (prev_count >= curr_count + 0x100)
-			curr_count = get_8254_timer_count();
-
-	} while (prev_count >= curr_count);
-}
-
-/*
- * Default initialization for 8254 timers. If we use other timers like HPET,
- * we override this later
- */
-void (*wait_timer_tick)(void) __devinitdata = wait_8254_wraparound;
-
-/*
- * This function sets up the local APIC timer, with a timeout of
- * 'clocks' APIC bus clock. During calibration we actually call
- * this function twice on the boot CPU, once with a bogus timeout
- * value, second time for real. The other (noncalibrating) CPUs
- * call this function only once, with the real, calibrated value.
- *
- * We do reads before writes even if unnecessary, to get around the
- * P5 APIC double write bug.
- */
-
-#define APIC_DIVISOR 16
-
-static void __setup_APIC_LVTT(unsigned int clocks)
-{
-	unsigned int lvtt_value, tmp_value, ver;
-	int cpu = smp_processor_id();
-
-	ver = GET_APIC_VERSION(apic_read(APIC_LVR));
-	lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
-	if (!APIC_INTEGRATED(ver))
-		lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
-
-	if (cpu_isset(cpu, timer_bcast_ipi))
-		lvtt_value |= APIC_LVT_MASKED;
-
-	apic_write_around(APIC_LVTT, lvtt_value);
-
-	/*
-	 * Divide PICLK by 16
-	 */
-	tmp_value = apic_read(APIC_TDCR);
-	apic_write_around(APIC_TDCR, (tmp_value
-				& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
-				| APIC_TDR_DIV_16);
-
-	apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
-}
-
-static void __devinit setup_APIC_timer(unsigned int clocks)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	/*
-	 * Wait for IRQ0's slice:
-	 */
-	wait_timer_tick();
-
-	__setup_APIC_LVTT(clocks);
-
-	local_irq_restore(flags);
-}
-
-/*
- * In this function we calibrate APIC bus clocks to the external
- * timer. Unfortunately we cannot use jiffies and the timer irq
- * to calibrate, since some later bootup code depends on getting
- * the first irq? Ugh.
- *
- * We want to do the calibration only once since we
- * want to have local timer irqs syncron. CPUs connected
- * by the same APIC bus have the very same bus frequency.
- * And we want to have irqs off anyways, no accidental
- * APIC irq that way.
- */
-
-static int __init calibrate_APIC_clock(void)
-{
-	unsigned long long t1 = 0, t2 = 0;
-	long tt1, tt2;
-	long result;
-	int i;
-	const int LOOPS = HZ/10;
-
-	apic_printk(APIC_VERBOSE, "calibrating APIC timer ...\n");
-
-	/*
-	 * Put whatever arbitrary (but long enough) timeout
-	 * value into the APIC clock, we just want to get the
-	 * counter running for calibration.
-	 */
-	__setup_APIC_LVTT(1000000000);
-
-	/*
-	 * The timer chip counts down to zero. Let's wait
-	 * for a wraparound to start exact measurement:
-	 * (the current tick might have been already half done)
-	 */
-
-	wait_timer_tick();
-
-	/*
-	 * We wrapped around just now. Let's start:
-	 */
-	if (cpu_has_tsc)
-		rdtscll(t1);
-	tt1 = apic_read(APIC_TMCCT);
-
-	/*
-	 * Let's wait LOOPS wraprounds:
-	 */
-	for (i = 0; i < LOOPS; i++)
-		wait_timer_tick();
-
-	tt2 = apic_read(APIC_TMCCT);
-	if (cpu_has_tsc)
-		rdtscll(t2);
-
-	/*
-	 * The APIC bus clock counter is 32 bits only, it
-	 * might have overflown, but note that we use signed
-	 * longs, thus no extra care needed.
-	 *
-	 * underflown to be exact, as the timer counts down ;)
-	 */
-
-	result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
-
-	if (cpu_has_tsc)
-		apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
-			"%ld.%04ld MHz.\n",
-			((long)(t2-t1)/LOOPS)/(1000000/HZ),
-			((long)(t2-t1)/LOOPS)%(1000000/HZ));
-
-	apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
-		"%ld.%04ld MHz.\n",
-		result/(1000000/HZ),
-		result%(1000000/HZ));
-
-	return result;
-}
-
-static unsigned int calibration_result;
-
-void __init setup_boot_APIC_clock(void)
-{
-	unsigned long flags;
-	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n");
-	using_apic_timer = 1;
-
-	local_irq_save(flags);
-
-	calibration_result = calibrate_APIC_clock();
-	/*
-	 * Now set up the timer for real.
-	 */
-	setup_APIC_timer(calibration_result);
-
-	local_irq_restore(flags);
-}
-
-void __devinit setup_secondary_APIC_clock(void)
-{
-	setup_APIC_timer(calibration_result);
-}
-
-void disable_APIC_timer(void)
-{
-	if (using_apic_timer) {
-		unsigned long v;
-
-		v = apic_read(APIC_LVTT);
-		/*
-		 * When an illegal vector value (0-15) is written to an LVT
-		 * entry and delivery mode is Fixed, the APIC may signal an
-		 * illegal vector error, with out regard to whether the mask
-		 * bit is set or whether an interrupt is actually seen on input.
-		 *
-		 * Boot sequence might call this function when the LVTT has
-		 * '0' vector value. So make sure vector field is set to
-		 * valid value.
-		 */
-		v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
-		apic_write_around(APIC_LVTT, v);
-	}
-}
-
-void enable_APIC_timer(void)
-{
-	int cpu = smp_processor_id();
-
-	if (using_apic_timer &&
-	    !cpu_isset(cpu, timer_bcast_ipi)) {
-		unsigned long v;
-
-		v = apic_read(APIC_LVTT);
-		apic_write_around(APIC_LVTT, v & ~APIC_LVT_MASKED);
-	}
-}
-
-void switch_APIC_timer_to_ipi(void *cpumask)
-{
-	cpumask_t mask = *(cpumask_t *)cpumask;
-	int cpu = smp_processor_id();
-
-	if (cpu_isset(cpu, mask) &&
-	    !cpu_isset(cpu, timer_bcast_ipi)) {
-		disable_APIC_timer();
-		cpu_set(cpu, timer_bcast_ipi);
-	}
-}
-EXPORT_SYMBOL(switch_APIC_timer_to_ipi);
-
-void switch_ipi_to_APIC_timer(void *cpumask)
-{
-	cpumask_t mask = *(cpumask_t *)cpumask;
-	int cpu = smp_processor_id();
-
-	if (cpu_isset(cpu, mask) &&
-	    cpu_isset(cpu, timer_bcast_ipi)) {
-		cpu_clear(cpu, timer_bcast_ipi);
-		enable_APIC_timer();
-	}
-}
-EXPORT_SYMBOL(switch_ipi_to_APIC_timer);
-
-#undef APIC_DIVISOR
-
-/*
- * Local timer interrupt handler. It does both profiling and
- * process statistics/rescheduling.
- *
- * We do profiling in every local tick, statistics/rescheduling
- * happen only every 'profiling multiplier' ticks. The default
- * multiplier is 1 and it can be changed by writing the new multiplier
- * value into /proc/profile.
- */
-
-inline void smp_local_timer_interrupt(void)
-{
-	profile_tick(CPU_PROFILING);
-#ifdef CONFIG_SMP
-	update_process_times(user_mode_vm(get_irq_regs()));
-#endif
-
-	/*
-	 * We take the 'long' return path, and there every subsystem
-	 * grabs the apropriate locks (kernel lock/ irq lock).
-	 *
-	 * we might want to decouple profiling from the 'long path',
-	 * and do the profiling totally in assembly.
-	 *
-	 * Currently this isn't too much of an issue (performance wise),
-	 * we can take more than 100K local irqs per second on a 100 MHz P5.
-	 */
-}
-
-/*
- * Local APIC timer interrupt. This is the most natural way for doing
- * local interrupts, but local timer interrupts can be emulated by
- * broadcast interrupts too. [in case the hw doesn't support APIC timers]
- *
- * [ if a single-CPU system runs an SMP kernel then we call the local
- *   interrupt as well. Thus we cannot inline the local irq ... ]
- */
-
-fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
-{
-	struct pt_regs *old_regs = set_irq_regs(regs);
-	int cpu = smp_processor_id();
-
-	/*
-	 * the NMI deadlock-detector uses this.
-	 */
-	per_cpu(irq_stat, cpu).apic_timer_irqs++;
-
-	/*
-	 * NOTE! We'd better ACK the irq immediately,
-	 * because timer handling can be slow.
-	 */
-	ack_APIC_irq();
-	/*
-	 * update_process_times() expects us to have done irq_enter().
-	 * Besides, if we don't timer interrupts ignore the global
-	 * interrupt lock, which is the WrongThing (tm) to do.
-	 */
-	irq_enter();
-	smp_local_timer_interrupt();
-	irq_exit();
-	set_irq_regs(old_regs);
-}
-
-#ifndef CONFIG_SMP
-static void up_apic_timer_interrupt_call(void)
-{
-	int cpu = smp_processor_id();
-
-	/*
-	 * the NMI deadlock-detector uses this.
-	 */
-	per_cpu(irq_stat, cpu).apic_timer_irqs++;
-
-	smp_local_timer_interrupt();
-}
-#endif
-
-void smp_send_timer_broadcast_ipi(void)
-{
-	cpumask_t mask;
-
-	cpus_and(mask, cpu_online_map, timer_bcast_ipi);
-	if (!cpus_empty(mask)) {
-#ifdef CONFIG_SMP
-		send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
-#else
-		/*
-		 * We can directly call the apic timer interrupt handler
-		 * in UP case. Minus all irq related functions
-		 */
-		up_apic_timer_interrupt_call();
-#endif
-	}
-}
-
-int setup_profiling_timer(unsigned int multiplier)
-{
-	return -EINVAL;
-}
-
-/*
- * This interrupt should _never_ happen with our APIC/SMP architecture
- */
-fastcall void smp_spurious_interrupt(struct pt_regs *regs)
-{
-	unsigned long v;
-
-	irq_enter();
-	/*
-	 * Check if this really is a spurious interrupt and ACK it
-	 * if it is a vectored one.  Just in case...
-	 * Spurious interrupts should not be ACKed.
-	 */
-	v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
-	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
-		ack_APIC_irq();
-
-	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
-	printk(KERN_INFO "spurious APIC interrupt on CPU#%d, should never happen.\n",
-			smp_processor_id());
-	irq_exit();
-}
-
-/*
- * This interrupt should never happen with our APIC/SMP architecture
- */
-
-fastcall void smp_error_interrupt(struct pt_regs *regs)
-{
-	unsigned long v, v1;
-
-	irq_enter();
-	/* First tickle the hardware, only then report what went on. -- REW */
-	v = apic_read(APIC_ESR);
-	apic_write(APIC_ESR, 0);
-	v1 = apic_read(APIC_ESR);
-	ack_APIC_irq();
-	atomic_inc(&irq_err_count);
-
-	/* Here is what the APIC error bits mean:
-	   0: Send CS error
-	   1: Receive CS error
-	   2: Send accept error
-	   3: Receive accept error
-	   4: Reserved
-	   5: Send illegal vector
-	   6: Received illegal vector
-	   7: Illegal register address
-	*/
-	printk (KERN_DEBUG "APIC error on CPU%d: %02lx(%02lx)\n",
-	        smp_processor_id(), v , v1);
-	irq_exit();
-}
-
-/*
- * This initializes the IO-APIC and APIC hardware if this is
- * a UP kernel.
- */
-int __init APIC_init_uniprocessor (void)
-{
-	if (enable_local_apic < 0)
-		clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-
-	if (!smp_found_config && !cpu_has_apic)
-		return -1;
-
-	/*
-	 * Complain if the BIOS pretends there is one.
-	 */
-	if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
-		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
-			boot_cpu_physical_apicid);
-		clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-		return -1;
-	}
-
-	verify_local_APIC();
-
-	connect_bsp_APIC();
-
-	/*
-	 * Hack: In case of kdump, after a crash, kernel might be booting
-	 * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
-	 * might be zero if read from MP tables. Get it from LAPIC.
-	 */
-#ifdef CONFIG_CRASH_DUMP
-	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
-#endif
-	phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
-
-	setup_local_APIC();
-
-#ifdef CONFIG_X86_IO_APIC
-	if (smp_found_config)
-		if (!skip_ioapic_setup && nr_ioapics)
-			setup_IO_APIC();
-#endif
-	setup_boot_APIC_clock();
-
-	return 0;
-}
-
-static int __init parse_lapic(char *arg)
-{
-	lapic_enable();
-	return 0;
-}
-early_param("lapic", parse_lapic);
-
-static int __init parse_nolapic(char *arg)
-{
-	lapic_disable();
-	return 0;
-}
-early_param("nolapic", parse_nolapic);
-
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 19901692..064bbf2 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -211,6 +211,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/miscdevice.h>
 #include <linux/apm_bios.h>
 #include <linux/init.h>
@@ -235,7 +236,6 @@
 
 #include "io_ports.h"
 
-extern unsigned long get_cmos_time(void);
 extern void machine_real_restart(unsigned char *, int);
 
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
@@ -1175,28 +1175,6 @@
 	spin_unlock(&user_list_lock);
 }
 
-static void set_time(void)
-{
-	struct timespec ts;
-	if (got_clock_diff) {	/* Must know time zone in order to set clock */
-		ts.tv_sec = get_cmos_time() + clock_cmos_diff;
-		ts.tv_nsec = 0;
-		do_settimeofday(&ts);
-	} 
-}
-
-static void get_time_diff(void)
-{
-#ifndef CONFIG_APM_RTC_IS_GMT
-	/*
-	 * Estimate time zone so that set_time can update the clock
-	 */
-	clock_cmos_diff = -get_cmos_time();
-	clock_cmos_diff += get_seconds();
-	got_clock_diff = 1;
-#endif
-}
-
 static void reinit_timer(void)
 {
 #ifdef INIT_TIMER_AFTER_SUSPEND
@@ -1236,19 +1214,6 @@
 	local_irq_disable();
 	device_power_down(PMSG_SUSPEND);
 
-	/* serialize with the timer interrupt */
-	write_seqlock(&xtime_lock);
-
-	/* protect against access to timer chip registers */
-	spin_lock(&i8253_lock);
-
-	get_time_diff();
-	/*
-	 * Irq spinlock must be dropped around set_system_power_state.
-	 * We'll undo any timer changes due to interrupts below.
-	 */
-	spin_unlock(&i8253_lock);
-	write_sequnlock(&xtime_lock);
 	local_irq_enable();
 
 	save_processor_state();
@@ -1257,7 +1222,6 @@
 	restore_processor_state();
 
 	local_irq_disable();
-	set_time();
 	reinit_timer();
 
 	if (err == APM_NO_ERROR)
@@ -1287,11 +1251,6 @@
 
 	local_irq_disable();
 	device_power_down(PMSG_SUSPEND);
-	/* serialize with the timer interrupt */
-	write_seqlock(&xtime_lock);
-	/* If needed, notify drivers here */
-	get_time_diff();
-	write_sequnlock(&xtime_lock);
 	local_irq_enable();
 
 	err = set_system_power_state(APM_STATE_STANDBY);
@@ -1385,7 +1344,6 @@
 			ignore_bounce = 1;
 			if ((event != APM_NORMAL_RESUME)
 			    || (ignore_normal_resume == 0)) {
-				set_time();
 				device_resume();
 				pm_send_all(PM_RESUME, (void *)0);
 				queue_event(event, NULL);
@@ -1401,7 +1359,6 @@
 			break;
 
 		case APM_UPDATE_TIME:
-			set_time();
 			break;
 
 		case APM_CRITICAL_SUSPEND:
@@ -1636,9 +1593,8 @@
 	return 0;
 }
 
-static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+static int proc_apm_show(struct seq_file *m, void *v)
 {
-	char *		p;
 	unsigned short	bx;
 	unsigned short	cx;
 	unsigned short	dx;
@@ -1650,8 +1606,6 @@
 	int             time_units     = -1;
 	char            *units         = "?";
 
-	p = buf;
-
 	if ((num_online_cpus() == 1) &&
 	    !(error = apm_get_power_status(&bx, &cx, &dx))) {
 		ac_line_status = (bx >> 8) & 0xff;
@@ -1705,7 +1659,7 @@
 	      -1: Unknown
 	   8) min = minutes; sec = seconds */
 
-	p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+	seq_printf(m, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
 		     driver_version,
 		     (apm_info.bios.version >> 8) & 0xff,
 		     apm_info.bios.version & 0xff,
@@ -1716,10 +1670,22 @@
 		     percentage,
 		     time_units,
 		     units);
-
-	return p - buf;
+	return 0;
 }
 
+static int proc_apm_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_apm_show, NULL);
+}
+
+static const struct file_operations apm_file_ops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_apm_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static int apm(void *unused)
 {
 	unsigned short	bx;
@@ -1894,7 +1860,7 @@
 __setup("apm=", apm_setup);
 #endif
 
-static struct file_operations apm_bios_fops = {
+static const struct file_operations apm_bios_fops = {
 	.owner		= THIS_MODULE,
 	.read		= do_read,
 	.poll		= do_poll,
@@ -2341,9 +2307,9 @@
 	set_base(gdt[APM_DS >> 3],
 		 __va((unsigned long)apm_info.bios.dseg << 4));
 
-	apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info);
+	apm_proc = create_proc_entry("apm", 0, NULL);
 	if (apm_proc)
-		apm_proc->owner = THIS_MODULE;
+		apm_proc->proc_fops = &apm_file_ops;
 
 	kapmd_task = kthread_create(apm, NULL, "kapmd");
 	if (IS_ERR(kapmd_task)) {
diff --git a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c
index 1b2f3cd..c375351 100644
--- a/arch/i386/kernel/asm-offsets.c
+++ b/arch/i386/kernel/asm-offsets.c
@@ -72,7 +72,7 @@
 	OFFSET(PT_EAX, pt_regs, eax);
 	OFFSET(PT_DS,  pt_regs, xds);
 	OFFSET(PT_ES,  pt_regs, xes);
-	OFFSET(PT_GS,  pt_regs, xgs);
+	OFFSET(PT_FS,  pt_regs, xfs);
 	OFFSET(PT_ORIG_EAX, pt_regs, orig_eax);
 	OFFSET(PT_EIP, pt_regs, eip);
 	OFFSET(PT_CS,  pt_regs, xcs);
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 8a8bbda..dcbbd0a 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -605,7 +605,7 @@
 struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
 {
 	memset(regs, 0, sizeof(struct pt_regs));
-	regs->xgs = __KERNEL_PDA;
+	regs->xfs = __KERNEL_PDA;
 	return regs;
 }
 
@@ -662,12 +662,12 @@
 	.pcurrent = &init_task,
 };
 
-static inline void set_kernel_gs(void)
+static inline void set_kernel_fs(void)
 {
-	/* Set %gs for this CPU's PDA.  Memory clobber is to create a
+	/* Set %fs for this CPU's PDA.  Memory clobber is to create a
 	   barrier with respect to any PDA operations, so the compiler
 	   doesn't move any before here. */
-	asm volatile ("mov %0, %%gs" : : "r" (__KERNEL_PDA) : "memory");
+	asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_PDA) : "memory");
 }
 
 /* Initialize the CPU's GDT and PDA.  The boot CPU does this for
@@ -718,7 +718,7 @@
 	   the boot CPU, this will transition from the boot gdt+pda to
 	   the real ones). */
 	load_gdt(cpu_gdt_descr);
-	set_kernel_gs();
+	set_kernel_fs();
 }
 
 /* Common CPU init for both boot and secondary CPUs */
@@ -764,8 +764,8 @@
 	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
 #endif
 
-	/* Clear %fs. */
-	asm volatile ("mov %0, %%fs" : : "r" (0));
+	/* Clear %gs. */
+	asm volatile ("mov %0, %%gs" : : "r" (0));
 
 	/* Clear all 6 debug registers: */
 	set_debugreg(0, 0);
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index 5299c5b..6c52182 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -217,6 +217,15 @@
 
 	  If in doubt, say N.
 
+config X86_E_POWERSAVER
+	tristate "VIA C7 Enhanced PowerSaver (EXPERIMENTAL)"
+	select CPU_FREQ_TABLE
+	depends on EXPERIMENTAL
+	help
+	  This adds the CPUFreq driver for VIA C7 processors.
+
+	  If in doubt, say N.
+
 comment "shared options"
 
 config X86_ACPI_CPUFREQ_PROC_INTF
diff --git a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile
index 8de3abe..560f776 100644
--- a/arch/i386/kernel/cpu/cpufreq/Makefile
+++ b/arch/i386/kernel/cpu/cpufreq/Makefile
@@ -2,6 +2,7 @@
 obj-$(CONFIG_X86_POWERNOW_K7)		+= powernow-k7.o
 obj-$(CONFIG_X86_POWERNOW_K8)		+= powernow-k8.o
 obj-$(CONFIG_X86_LONGHAUL)		+= longhaul.o
+obj-$(CONFIG_X86_E_POWERSAVER)		+= e_powersaver.o
 obj-$(CONFIG_ELAN_CPUFREQ)		+= elanfreq.o
 obj-$(CONFIG_SC520_CPUFREQ)		+= sc520_freq.o
 obj-$(CONFIG_X86_LONGRUN)		+= longrun.o  
diff --git a/arch/i386/kernel/cpu/cpufreq/e_powersaver.c b/arch/i386/kernel/cpu/cpufreq/e_powersaver.c
new file mode 100644
index 0000000..f43d98e
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/e_powersaver.c
@@ -0,0 +1,334 @@
+/*
+ *  Based on documentation provided by Dave Jones. Thanks!
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+#include <asm/msr.h>
+#include <asm/tsc.h>
+#include <asm/timex.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#define EPS_BRAND_C7M	0
+#define EPS_BRAND_C7	1
+#define EPS_BRAND_EDEN	2
+#define EPS_BRAND_C3	3
+
+struct eps_cpu_data {
+	u32 fsb;
+	struct cpufreq_frequency_table freq_table[];
+};
+
+static struct eps_cpu_data *eps_cpu[NR_CPUS];
+
+
+static unsigned int eps_get(unsigned int cpu)
+{
+	struct eps_cpu_data *centaur;
+	u32 lo, hi;
+
+	if (cpu)
+		return 0;
+	centaur = eps_cpu[cpu];
+	if (centaur == NULL)
+		return 0;
+
+	/* Return current frequency */
+	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+	return centaur->fsb * ((lo >> 8) & 0xff);
+}
+
+static int eps_set_state(struct eps_cpu_data *centaur,
+			 unsigned int cpu,
+			 u32 dest_state)
+{
+	struct cpufreq_freqs freqs;
+	u32 lo, hi;
+	int err = 0;
+	int i;
+
+	freqs.old = eps_get(cpu);
+	freqs.new = centaur->fsb * ((dest_state >> 8) & 0xff);
+	freqs.cpu = cpu;
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	/* Wait while CPU is busy */
+	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+	i = 0;
+	while (lo & ((1 << 16) | (1 << 17))) {
+		udelay(16);
+		rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+		i++;
+		if (unlikely(i > 64)) {
+			err = -ENODEV;
+			goto postchange;
+		}
+	}
+	/* Set new multiplier and voltage */
+	wrmsr(MSR_IA32_PERF_CTL, dest_state & 0xffff, 0);
+	/* Wait until transition end */
+	i = 0;
+	do {
+		udelay(16);
+		rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+		i++;
+		if (unlikely(i > 64)) {
+			err = -ENODEV;
+			goto postchange;
+		}
+	} while (lo & ((1 << 16) | (1 << 17)));
+
+	/* Return current frequency */
+postchange:
+	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+	freqs.new = centaur->fsb * ((lo >> 8) & 0xff);
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	return err;
+}
+
+static int eps_target(struct cpufreq_policy *policy,
+			       unsigned int target_freq,
+			       unsigned int relation)
+{
+	struct eps_cpu_data *centaur;
+	unsigned int newstate = 0;
+	unsigned int cpu = policy->cpu;
+	unsigned int dest_state;
+	int ret;
+
+	if (unlikely(eps_cpu[cpu] == NULL))
+		return -ENODEV;
+	centaur = eps_cpu[cpu];
+
+	if (unlikely(cpufreq_frequency_table_target(policy,
+			&eps_cpu[cpu]->freq_table[0],
+			target_freq,
+			relation,
+			&newstate))) {
+		return -EINVAL;
+	}
+
+	/* Make frequency transition */
+	dest_state = centaur->freq_table[newstate].index & 0xffff;
+	ret = eps_set_state(centaur, cpu, dest_state);
+	if (ret)
+		printk(KERN_ERR "eps: Timeout!\n");
+	return ret;
+}
+
+static int eps_verify(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy,
+			&eps_cpu[policy->cpu]->freq_table[0]);
+}
+
+static int eps_cpu_init(struct cpufreq_policy *policy)
+{
+	unsigned int i;
+	u32 lo, hi;
+	u64 val;
+	u8 current_multiplier, current_voltage;
+	u8 max_multiplier, max_voltage;
+	u8 min_multiplier, min_voltage;
+	u8 brand;
+	u32 fsb;
+	struct eps_cpu_data *centaur;
+	struct cpufreq_frequency_table *f_table;
+	int k, step, voltage;
+	int ret;
+	int states;
+
+	if (policy->cpu != 0)
+		return -ENODEV;
+
+	/* Check brand */
+	printk("eps: Detected VIA ");
+	rdmsr(0x1153, lo, hi);
+	brand = (((lo >> 2) ^ lo) >> 18) & 3;
+	switch(brand) {
+	case EPS_BRAND_C7M:
+		printk("C7-M\n");
+		break;
+	case EPS_BRAND_C7:
+		printk("C7\n");
+		break;
+	case EPS_BRAND_EDEN:
+		printk("Eden\n");
+		break;
+	case EPS_BRAND_C3:
+		printk("C3\n");
+		return -ENODEV;
+		break;
+	}
+	/* Enable Enhanced PowerSaver */
+	rdmsrl(MSR_IA32_MISC_ENABLE, val);
+	if (!(val & 1 << 16)) {
+		val |= 1 << 16;
+		wrmsrl(MSR_IA32_MISC_ENABLE, val);
+		/* Can be locked at 0 */
+		rdmsrl(MSR_IA32_MISC_ENABLE, val);
+		if (!(val & 1 << 16)) {
+			printk("eps: Can't enable Enhanced PowerSaver\n");
+			return -ENODEV;
+		}
+	}
+
+	/* Print voltage and multiplier */
+	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+	current_voltage = lo & 0xff;
+	printk("eps: Current voltage = %dmV\n", current_voltage * 16 + 700);
+	current_multiplier = (lo >> 8) & 0xff;
+	printk("eps: Current multiplier = %d\n", current_multiplier);
+
+	/* Print limits */
+	max_voltage = hi & 0xff;
+	printk("eps: Highest voltage = %dmV\n", max_voltage * 16 + 700);
+	max_multiplier = (hi >> 8) & 0xff;
+	printk("eps: Highest multiplier = %d\n", max_multiplier);
+	min_voltage = (hi >> 16) & 0xff;
+	printk("eps: Lowest voltage = %dmV\n", min_voltage * 16 + 700);
+	min_multiplier = (hi >> 24) & 0xff;
+	printk("eps: Lowest multiplier = %d\n", min_multiplier);
+
+	/* Sanity checks */
+	if (current_multiplier == 0 || max_multiplier == 0
+	    || min_multiplier == 0)
+		return -EINVAL;
+	if (current_multiplier > max_multiplier
+	    || max_multiplier <= min_multiplier)
+		return -EINVAL;
+	if (current_voltage > 0x1c || max_voltage > 0x1c)
+		return -EINVAL;
+	if (max_voltage < min_voltage)
+		return -EINVAL;
+
+	/* Calc FSB speed */
+	fsb = cpu_khz / current_multiplier;
+	/* Calc number of p-states supported */
+	if (brand == EPS_BRAND_C7M)
+		states = max_multiplier - min_multiplier + 1;
+	else
+		states = 2;
+
+	/* Allocate private data and frequency table for current cpu */
+	centaur = kzalloc(sizeof(struct eps_cpu_data)
+		    + (states + 1) * sizeof(struct cpufreq_frequency_table),
+		    GFP_KERNEL);
+	if (!centaur)
+		return -ENOMEM;
+	eps_cpu[0] = centaur;
+
+	/* Copy basic values */
+	centaur->fsb = fsb;
+
+	/* Fill frequency and MSR value table */
+	f_table = &centaur->freq_table[0];
+	if (brand != EPS_BRAND_C7M) {
+		f_table[0].frequency = fsb * min_multiplier;
+		f_table[0].index = (min_multiplier << 8) | min_voltage;
+		f_table[1].frequency = fsb * max_multiplier;
+		f_table[1].index = (max_multiplier << 8) | max_voltage;
+		f_table[2].frequency = CPUFREQ_TABLE_END;
+	} else {
+		k = 0;
+		step = ((max_voltage - min_voltage) * 256)
+			/ (max_multiplier - min_multiplier);
+		for (i = min_multiplier; i <= max_multiplier; i++) {
+			voltage = (k * step) / 256 + min_voltage;
+			f_table[k].frequency = fsb * i;
+			f_table[k].index = (i << 8) | voltage;
+			k++;
+		}
+		f_table[k].frequency = CPUFREQ_TABLE_END;
+	}
+
+	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+	policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */
+	policy->cur = fsb * current_multiplier;
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, &centaur->freq_table[0]);
+	if (ret) {
+		kfree(centaur);
+		return ret;
+	}
+
+	cpufreq_frequency_table_get_attr(&centaur->freq_table[0], policy->cpu);
+	return 0;
+}
+
+static int eps_cpu_exit(struct cpufreq_policy *policy)
+{
+	unsigned int cpu = policy->cpu;
+	struct eps_cpu_data *centaur;
+	u32 lo, hi;
+
+	if (eps_cpu[cpu] == NULL)
+		return -ENODEV;
+	centaur = eps_cpu[cpu];
+
+	/* Get max frequency */
+	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+	/* Set max frequency */
+	eps_set_state(centaur, cpu, hi & 0xffff);
+	/* Bye */
+	cpufreq_frequency_table_put_attr(policy->cpu);
+	kfree(eps_cpu[cpu]);
+	eps_cpu[cpu] = NULL;
+	return 0;
+}
+
+static struct freq_attr* eps_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+static struct cpufreq_driver eps_driver = {
+	.verify		= eps_verify,
+	.target		= eps_target,
+	.init		= eps_cpu_init,
+	.exit		= eps_cpu_exit,
+	.get		= eps_get,
+	.name		= "e_powersaver",
+	.owner		= THIS_MODULE,
+	.attr		= eps_attr,
+};
+
+static int __init eps_init(void)
+{
+	struct cpuinfo_x86 *c = cpu_data;
+
+	/* This driver will work only on Centaur C7 processors with
+	 * Enhanced SpeedStep/PowerSaver registers */
+	if (c->x86_vendor != X86_VENDOR_CENTAUR
+	    || c->x86 != 6 || c->x86_model != 10)
+		return -ENODEV;
+	if (!cpu_has(c, X86_FEATURE_EST))
+		return -ENODEV;
+
+	if (cpufreq_register_driver(&eps_driver))
+		return -EINVAL;
+	return 0;
+}
+
+static void __exit eps_exit(void)
+{
+	cpufreq_unregister_driver(&eps_driver);
+}
+
+MODULE_AUTHOR("Rafa³ Bilski <rafalbilski@interia.pl>");
+MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's.");
+MODULE_LICENSE("GPL");
+
+module_init(eps_init);
+module_exit(eps_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index a3db933..b59878a 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -8,12 +8,11 @@
  *  VIA have currently 3 different versions of Longhaul.
  *  Version 1 (Longhaul) uses the BCR2 MSR at 0x1147.
  *   It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0.
- *  Version 2 of longhaul is the same as v1, but adds voltage scaling.
- *   Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C)
- *   voltage scaling support has currently been disabled in this driver
- *   until we have code that gets it right.
+ *  Version 2 of longhaul is backward compatible with v1, but adds
+ *   LONGHAUL MSR for purpose of both frequency and voltage scaling.
+ *   Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C).
  *  Version 3 of longhaul got renamed to Powersaver and redesigned
- *   to use the POWERSAVER MSR at 0x110a.
+ *   to use only the POWERSAVER MSR at 0x110a.
  *   It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
  *   It's pretty much the same feature wise to longhaul v2, though
  *   there is provision for scaling FSB too, but this doesn't work
@@ -51,10 +50,12 @@
 #define	CPU_EZRA	3
 #define	CPU_EZRA_T	4
 #define	CPU_NEHEMIAH	5
+#define	CPU_NEHEMIAH_C	6
 
 /* Flags */
 #define USE_ACPI_C3		(1 << 1)
 #define USE_NORTHBRIDGE		(1 << 2)
+#define USE_VT8235		(1 << 3)
 
 static int cpu_model;
 static unsigned int numscales=16;
@@ -63,7 +64,8 @@
 static struct mV_pos *vrm_mV_table;
 static unsigned char *mV_vrm_table;
 struct f_msr {
-	unsigned char vrm;
+	u8 vrm;
+	u8 pos;
 };
 static struct f_msr f_msr_table[32];
 
@@ -73,10 +75,10 @@
 static struct acpi_processor *pr = NULL;
 static struct acpi_processor_cx *cx = NULL;
 static u8 longhaul_flags;
+static u8 longhaul_pos;
 
 /* Module parameters */
 static int scale_voltage;
-static int ignore_latency;
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
 
@@ -164,26 +166,47 @@
 static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
 {
 	union msr_longhaul longhaul;
+	u8 dest_pos;
 	u32 t;
 
+	dest_pos = f_msr_table[clock_ratio_index].pos;
+
 	rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+	/* Setup new frequency */
 	longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
 	longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
 	longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
-	longhaul.bits.EnableSoftBusRatio = 1;
-
-	if (can_scale_voltage) {
+	/* Setup new voltage */
+	if (can_scale_voltage)
 		longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
-		longhaul.bits.EnableSoftVID = 1;
-	}
-
 	/* Sync to timer tick */
 	safe_halt();
+	/* Raise voltage if necessary */
+	if (can_scale_voltage && longhaul_pos < dest_pos) {
+		longhaul.bits.EnableSoftVID = 1;
+		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+		/* Change voltage */
+		if (!cx_address) {
+			ACPI_FLUSH_CPU_CACHE();
+			halt();
+		} else {
+			ACPI_FLUSH_CPU_CACHE();
+			/* Invoke C3 */
+			inb(cx_address);
+			/* Dummy op - must do something useless after P_LVL3
+			 * read */
+			t = inl(acpi_gbl_FADT.xpm_timer_block.address);
+		}
+		longhaul.bits.EnableSoftVID = 0;
+		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+		longhaul_pos = dest_pos;
+	}
+
 	/* Change frequency on next halt or sleep */
+	longhaul.bits.EnableSoftBusRatio = 1;
 	wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 	if (!cx_address) {
 		ACPI_FLUSH_CPU_CACHE();
-		/* Invoke C1 */
 		halt();
 	} else {
 		ACPI_FLUSH_CPU_CACHE();
@@ -193,12 +216,29 @@
 		t = inl(acpi_gbl_FADT.xpm_timer_block.address);
 	}
 	/* Disable bus ratio bit */
-	local_irq_disable();
-	longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
 	longhaul.bits.EnableSoftBusRatio = 0;
-	longhaul.bits.EnableSoftBSEL = 0;
-	longhaul.bits.EnableSoftVID = 0;
 	wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+
+	/* Reduce voltage if necessary */
+	if (can_scale_voltage && longhaul_pos > dest_pos) {
+		longhaul.bits.EnableSoftVID = 1;
+		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+		/* Change voltage */
+		if (!cx_address) {
+			ACPI_FLUSH_CPU_CACHE();
+			halt();
+		} else {
+			ACPI_FLUSH_CPU_CACHE();
+			/* Invoke C3 */
+			inb(cx_address);
+			/* Dummy op - must do something useless after P_LVL3
+			 * read */
+			t = inl(acpi_gbl_FADT.xpm_timer_block.address);
+		}
+		longhaul.bits.EnableSoftVID = 0;
+		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+		longhaul_pos = dest_pos;
+	}
 }
 
 /**
@@ -257,26 +297,19 @@
 	/*
 	 * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
 	 * Software controlled multipliers only.
-	 *
-	 * *NB* Until we get voltage scaling working v1 & v2 are the same code.
-	 * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C]
 	 */
 	case TYPE_LONGHAUL_V1:
-	case TYPE_LONGHAUL_V2:
 		do_longhaul1(clock_ratio_index);
 		break;
 
 	/*
+	 * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5B] and Ezra [C5C]
+	 *
 	 * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
-	 * We can scale voltage with this too, but that's currently
-	 * disabled until we come up with a decent 'match freq to voltage'
-	 * algorithm.
-	 * When we add voltage scaling, we will also need to do the
-	 * voltage/freq setting in order depending on the direction
-	 * of scaling (like we do in powernow-k7.c)
 	 * Nehemiah can do FSB scaling too, but this has never been proven
 	 * to work in practice.
 	 */
+	case TYPE_LONGHAUL_V2:
 	case TYPE_POWERSAVER:
 		if (longhaul_flags & USE_ACPI_C3) {
 			/* Don't allow wakeup */
@@ -301,6 +334,7 @@
 	local_irq_restore(flags);
 	preempt_enable();
 
+	freqs.new = calc_speed(longhaul_get_cpu_mult());
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 }
 
@@ -315,31 +349,19 @@
 
 #define ROUNDING	0xf
 
-static int _guess(int guess, int mult)
-{
-	int target;
-
-	target = ((mult/10)*guess);
-	if (mult%10 != 0)
-		target += (guess/2);
-	target += ROUNDING/2;
-	target &= ~ROUNDING;
-	return target;
-}
-
-
 static int guess_fsb(int mult)
 {
-	int speed = (cpu_khz/1000);
+	int speed = cpu_khz / 1000;
 	int i;
-	int speeds[] = { 66, 100, 133, 200 };
+	int speeds[] = { 666, 1000, 1333, 2000 };
+	int f_max, f_min;
 
-	speed += ROUNDING/2;
-	speed &= ~ROUNDING;
-
-	for (i=0; i<4; i++) {
-		if (_guess(speeds[i], mult) == speed)
-			return speeds[i];
+	for (i = 0; i < 4; i++) {
+		f_max = ((speeds[i] * mult) + 50) / 100;
+		f_max += (ROUNDING / 2);
+		f_min = f_max - ROUNDING;
+		if ((speed <= f_max) && (speed >= f_min))
+			return speeds[i] / 10;
 	}
 	return 0;
 }
@@ -347,67 +369,40 @@
 
 static int __init longhaul_get_ranges(void)
 {
-	unsigned long invalue;
-	unsigned int ezra_t_multipliers[32]= {
-			90,  30,  40, 100,  55,  35,  45,  95,
-			50,  70,  80,  60, 120,  75,  85,  65,
-			-1, 110, 120,  -1, 135, 115, 125, 105,
-			130, 150, 160, 140,  -1, 155,  -1, 145 };
 	unsigned int j, k = 0;
-	union msr_longhaul longhaul;
-	int mult = 0;
+	int mult;
 
-	switch (longhaul_version) {
-	case TYPE_LONGHAUL_V1:
-	case TYPE_LONGHAUL_V2:
-		/* Ugh, Longhaul v1 didn't have the min/max MSRs.
-		   Assume min=3.0x & max = whatever we booted at. */
-		minmult = 30;
-		maxmult = mult = longhaul_get_cpu_mult();
-		break;
-
-	case TYPE_POWERSAVER:
-		/* Ezra-T */
-		if (cpu_model==CPU_EZRA_T) {
-			minmult = 30;
-			rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-			invalue = longhaul.bits.MaxMHzBR;
-			if (longhaul.bits.MaxMHzBR4)
-				invalue += 16;
-			maxmult = mult = ezra_t_multipliers[invalue];
-			break;
-		}
-
-		/* Nehemiah */
-		if (cpu_model==CPU_NEHEMIAH) {
-			rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-
-			/*
-			 * TODO: This code works, but raises a lot of questions.
-			 * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
-			 *   We get around this by using a hardcoded multiplier of 4.0x
-			 *   for the minimimum speed, and the speed we booted up at for the max.
-			 *   This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
-			 * - According to some VIA documentation EBLCR is only
-			 *   in pre-Nehemiah C3s. How this still works is a mystery.
-			 *   We're possibly using something undocumented and unsupported,
-			 *   But it works, so we don't grumble.
-			 */
-			minmult=40;
-			maxmult = mult = longhaul_get_cpu_mult();
-			break;
-		}
+	/* Get current frequency */
+	mult = longhaul_get_cpu_mult();
+	if (mult == -1) {
+		printk(KERN_INFO PFX "Invalid (reserved) multiplier!\n");
+		return -EINVAL;
 	}
 	fsb = guess_fsb(mult);
+	if (fsb == 0) {
+		printk(KERN_INFO PFX "Invalid (reserved) FSB!\n");
+		return -EINVAL;
+	}
+	/* Get max multiplier - as we always did.
+	 * Longhaul MSR is usefull only when voltage scaling is enabled.
+	 * C3 is booting at max anyway. */
+	maxmult = mult;
+	/* Get min multiplier */
+	switch (cpu_model) {
+	case CPU_NEHEMIAH:
+		minmult = 50;
+		break;
+	case CPU_NEHEMIAH_C:
+		minmult = 40;
+		break;
+	default:
+		minmult = 30;
+		break;
+	}
 
 	dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
 		 minmult/10, minmult%10, maxmult/10, maxmult%10);
 
-	if (fsb == 0) {
-		printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
-		return -EINVAL;
-	}
-
 	highest_speed = calc_speed(maxmult);
 	lowest_speed = calc_speed(minmult);
 	dprintk ("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
@@ -455,6 +450,7 @@
 	union msr_longhaul longhaul;
 	struct mV_pos minvid, maxvid;
 	unsigned int j, speed, pos, kHz_step, numvscales;
+	int min_vid_speed;
 
 	rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 	if (!(longhaul.bits.RevisionID & 1)) {
@@ -468,14 +464,14 @@
 		mV_vrm_table = &mV_vrm85[0];
 	} else {
 		printk (KERN_INFO PFX "Mobile VRM\n");
+		if (cpu_model < CPU_NEHEMIAH)
+			return;
 		vrm_mV_table = &mobilevrm_mV[0];
 		mV_vrm_table = &mV_mobilevrm[0];
 	}
 
 	minvid = vrm_mV_table[longhaul.bits.MinimumVID];
 	maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
-	numvscales = maxvid.pos - minvid.pos + 1;
-	kHz_step = (highest_speed - lowest_speed) / numvscales;
 
 	if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
 		printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
@@ -491,20 +487,59 @@
 		return;
 	}
 
-	printk(KERN_INFO PFX "Max VID=%d.%03d  Min VID=%d.%03d, %d possible voltage scales\n",
+	/* How many voltage steps */
+	numvscales = maxvid.pos - minvid.pos + 1;
+	printk(KERN_INFO PFX
+		"Max VID=%d.%03d  "
+		"Min VID=%d.%03d, "
+		"%d possible voltage scales\n",
 		maxvid.mV/1000, maxvid.mV%1000,
 		minvid.mV/1000, minvid.mV%1000,
 		numvscales);
 
+	/* Calculate max frequency at min voltage */
+	j = longhaul.bits.MinMHzBR;
+	if (longhaul.bits.MinMHzBR4)
+		j += 16;
+	min_vid_speed = eblcr_table[j];
+	if (min_vid_speed == -1)
+		return;
+	switch (longhaul.bits.MinMHzFSB) {
+	case 0:
+		min_vid_speed *= 13333;
+		break;
+	case 1:
+		min_vid_speed *= 10000;
+		break;
+	case 3:
+		min_vid_speed *= 6666;
+		break;
+	default:
+		return;
+		break;
+	}
+	if (min_vid_speed >= highest_speed)
+		return;
+	/* Calculate kHz for one voltage step */
+	kHz_step = (highest_speed - min_vid_speed) / numvscales;
+
+
 	j = 0;
 	while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
 		speed = longhaul_table[j].frequency;
-		pos = (speed - lowest_speed) / kHz_step + minvid.pos;
+		if (speed > min_vid_speed)
+			pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
+		else
+			pos = minvid.pos;
 		f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos];
+		f_msr_table[longhaul_table[j].index].pos = pos;
 		j++;
 	}
 
+	longhaul_pos = maxvid.pos;
 	can_scale_voltage = 1;
+	printk(KERN_INFO PFX "Voltage scaling enabled. "
+		"Use of \"conservative\" governor is highly recommended.\n");
 }
 
 
@@ -573,20 +608,51 @@
 	if (dev != NULL) {
 		/* Enable access to port 0x22 */
 		pci_read_config_byte(dev, reg, &pci_cmd);
-		if ( !(pci_cmd & 1<<7) ) {
+		if (!(pci_cmd & 1<<7)) {
 			pci_cmd |= 1<<7;
 			pci_write_config_byte(dev, reg, pci_cmd);
+			pci_read_config_byte(dev, reg, &pci_cmd);
+			if (!(pci_cmd & 1<<7)) {
+				printk(KERN_ERR PFX
+					"Can't enable access to port 0x22.\n");
+				return 0;
+			}
 		}
 		return 1;
 	}
 	return 0;
 }
 
+static int longhaul_setup_vt8235(void)
+{
+	struct pci_dev *dev;
+	u8 pci_cmd;
+
+	/* Find VT8235 southbridge */
+	dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
+	if (dev != NULL) {
+		/* Set transition time to max */
+		pci_read_config_byte(dev, 0xec, &pci_cmd);
+		pci_cmd &= ~(1 << 2);
+		pci_write_config_byte(dev, 0xec, pci_cmd);
+		pci_read_config_byte(dev, 0xe4, &pci_cmd);
+		pci_cmd &= ~(1 << 7);
+		pci_write_config_byte(dev, 0xe4, pci_cmd);
+		pci_read_config_byte(dev, 0xe5, &pci_cmd);
+		pci_cmd |= 1 << 7;
+		pci_write_config_byte(dev, 0xe5, pci_cmd);
+		return 1;
+	}
+	return 0;
+}
+
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
 	struct cpuinfo_x86 *c = cpu_data;
 	char *cpuname=NULL;
 	int ret;
+	u32 lo, hi;
+	int vt8235_present;
 
 	/* Check what we have on this motherboard */
 	switch (c->x86_model) {
@@ -599,16 +665,20 @@
 		break;
 
 	case 7:
-		longhaul_version = TYPE_LONGHAUL_V1;
 		switch (c->x86_mask) {
 		case 0:
+			longhaul_version = TYPE_LONGHAUL_V1;
 			cpu_model = CPU_SAMUEL2;
 			cpuname = "C3 'Samuel 2' [C5B]";
-			/* Note, this is not a typo, early Samuel2's had Samuel1 ratios. */
-			memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
-			memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr));
+			/* Note, this is not a typo, early Samuel2's had
+			 * Samuel1 ratios. */
+			memcpy(clock_ratio, samuel1_clock_ratio,
+				sizeof(samuel1_clock_ratio));
+			memcpy(eblcr_table, samuel2_eblcr,
+				sizeof(samuel2_eblcr));
 			break;
 		case 1 ... 15:
+			longhaul_version = TYPE_LONGHAUL_V2;
 			if (c->x86_mask < 8) {
 				cpu_model = CPU_SAMUEL2;
 				cpuname = "C3 'Samuel 2' [C5B]";
@@ -616,8 +686,10 @@
 				cpu_model = CPU_EZRA;
 				cpuname = "C3 'Ezra' [C5C]";
 			}
-			memcpy (clock_ratio, ezra_clock_ratio, sizeof(ezra_clock_ratio));
-			memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr));
+			memcpy(clock_ratio, ezra_clock_ratio,
+				sizeof(ezra_clock_ratio));
+			memcpy(eblcr_table, ezra_eblcr,
+				sizeof(ezra_eblcr));
 			break;
 		}
 		break;
@@ -632,24 +704,24 @@
 		break;
 
 	case 9:
-		cpu_model = CPU_NEHEMIAH;
 		longhaul_version = TYPE_POWERSAVER;
-		numscales=32;
+		numscales = 32;
+		memcpy(clock_ratio,
+		       nehemiah_clock_ratio,
+		       sizeof(nehemiah_clock_ratio));
+		memcpy(eblcr_table, nehemiah_eblcr, sizeof(nehemiah_eblcr));
 		switch (c->x86_mask) {
 		case 0 ... 1:
-			cpuname = "C3 'Nehemiah A' [C5N]";
-			memcpy (clock_ratio, nehemiah_a_clock_ratio, sizeof(nehemiah_a_clock_ratio));
-			memcpy (eblcr_table, nehemiah_a_eblcr, sizeof(nehemiah_a_eblcr));
+			cpu_model = CPU_NEHEMIAH;
+			cpuname = "C3 'Nehemiah A' [C5XLOE]";
 			break;
 		case 2 ... 4:
-			cpuname = "C3 'Nehemiah B' [C5N]";
-			memcpy (clock_ratio, nehemiah_b_clock_ratio, sizeof(nehemiah_b_clock_ratio));
-			memcpy (eblcr_table, nehemiah_b_eblcr, sizeof(nehemiah_b_eblcr));
+			cpu_model = CPU_NEHEMIAH;
+			cpuname = "C3 'Nehemiah B' [C5XLOH]";
 			break;
 		case 5 ... 15:
-			cpuname = "C3 'Nehemiah C' [C5N]";
-			memcpy (clock_ratio, nehemiah_c_clock_ratio, sizeof(nehemiah_c_clock_ratio));
-			memcpy (eblcr_table, nehemiah_c_eblcr, sizeof(nehemiah_c_eblcr));
+			cpu_model = CPU_NEHEMIAH_C;
+			cpuname = "C3 'Nehemiah C' [C5P]";
 			break;
 		}
 		break;
@@ -658,6 +730,13 @@
 		cpuname = "Unknown";
 		break;
 	}
+	/* Check Longhaul ver. 2 */
+	if (longhaul_version == TYPE_LONGHAUL_V2) {
+		rdmsr(MSR_VIA_LONGHAUL, lo, hi);
+		if (lo == 0 && hi == 0)
+			/* Looks like MSR isn't present */
+			longhaul_version = TYPE_LONGHAUL_V1;
+	}
 
 	printk (KERN_INFO PFX "VIA %s CPU detected.  ", cpuname);
 	switch (longhaul_version) {
@@ -670,15 +749,18 @@
 		break;
 	};
 
+	/* Doesn't hurt */
+	vt8235_present = longhaul_setup_vt8235();
+
 	/* Find ACPI data for processor */
-	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
-			    &longhaul_walk_callback, NULL, (void *)&pr);
+	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
+				ACPI_UINT32_MAX, &longhaul_walk_callback,
+				NULL, (void *)&pr);
 
 	/* Check ACPI support for C3 state */
-	if ((pr != NULL) && (longhaul_version == TYPE_POWERSAVER)) {
+	if (pr != NULL && longhaul_version != TYPE_LONGHAUL_V1) {
 		cx = &pr->power.states[ACPI_STATE_C3];
-		if (cx->address > 0 &&
-		   (cx->latency <= 1000 || ignore_latency != 0) ) {
+		if (cx->address > 0 && cx->latency <= 1000) {
 			longhaul_flags |= USE_ACPI_C3;
 			goto print_support_type;
 		}
@@ -688,8 +770,11 @@
 		longhaul_flags |= USE_NORTHBRIDGE;
 		goto print_support_type;
 	}
-
-	/* No ACPI C3 or we can't use it */
+	/* Use VT8235 southbridge if present */
+	if (longhaul_version == TYPE_POWERSAVER && vt8235_present) {
+		longhaul_flags |= USE_VT8235;
+		goto print_support_type;
+	}
 	/* Check ACPI support for bus master arbiter disable */
 	if ((pr == NULL) || !(pr->flags.bm_control)) {
 		printk(KERN_ERR PFX
@@ -698,18 +783,18 @@
 	}
 
 print_support_type:
-	if (!(longhaul_flags & USE_NORTHBRIDGE)) {
-		printk (KERN_INFO PFX "Using ACPI support.\n");
-	} else {
+	if (longhaul_flags & USE_NORTHBRIDGE)
 		printk (KERN_INFO PFX "Using northbridge support.\n");
-	}
+	else if (longhaul_flags & USE_VT8235)
+		printk (KERN_INFO PFX "Using VT8235 support.\n");
+	else
+		printk (KERN_INFO PFX "Using ACPI support.\n");
 
 	ret = longhaul_get_ranges();
 	if (ret != 0)
 		return ret;
 
-	if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) &&
-		 (scale_voltage != 0))
+	if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0))
 		longhaul_setup_voltagescaling();
 
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
@@ -797,8 +882,6 @@
 
 module_param (scale_voltage, int, 0644);
 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
-module_param(ignore_latency, int, 0644);
-MODULE_PARM_DESC(ignore_latency, "Skip ACPI C3 latency test");
 
 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
 MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h
index bc4682a..bb0a04b 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.h
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h
@@ -235,49 +235,14 @@
 /*
  * VIA C3 Nehemiah */
 
-static int __initdata nehemiah_a_clock_ratio[32] = {
+static int __initdata  nehemiah_clock_ratio[32] = {
 	100, /* 0000 -> 10.0x */
 	160, /* 0001 -> 16.0x */
-	-1,  /* 0010 ->  RESERVED */
+	40,  /* 0010 ->  4.0x */
 	90,  /* 0011 ->  9.0x */
 	95,  /* 0100 ->  9.5x */
 	-1,  /* 0101 ->  RESERVED */
-	-1,  /* 0110 ->  RESERVED */
-	55,  /* 0111 ->  5.5x */
-	60,  /* 1000 ->  6.0x */
-	70,  /* 1001 ->  7.0x */
-	80,  /* 1010 ->  8.0x */
-	50,  /* 1011 ->  5.0x */
-	65,  /* 1100 ->  6.5x */
-	75,  /* 1101 ->  7.5x */
-	85,  /* 1110 ->  8.5x */
-	120, /* 1111 -> 12.0x */
-	100, /* 0000 -> 10.0x */
-	-1,  /* 0001 -> RESERVED */
-	120, /* 0010 -> 12.0x */
-	90,  /* 0011 ->  9.0x */
-	105, /* 0100 -> 10.5x */
-	115, /* 0101 -> 11.5x */
-	125, /* 0110 -> 12.5x */
-	135, /* 0111 -> 13.5x */
-	140, /* 1000 -> 14.0x */
-	150, /* 1001 -> 15.0x */
-	160, /* 1010 -> 16.0x */
-	130, /* 1011 -> 13.0x */
-	145, /* 1100 -> 14.5x */
-	155, /* 1101 -> 15.5x */
-	-1,  /* 1110 -> RESERVED (13.0x) */
-	120, /* 1111 -> 12.0x */
-};
-
-static int __initdata  nehemiah_b_clock_ratio[32] = {
-	100, /* 0000 -> 10.0x */
-	160, /* 0001 -> 16.0x */
-	-1,  /* 0010 ->  RESERVED */
-	90,  /* 0011 ->  9.0x */
-	95,  /* 0100 ->  9.5x */
-	-1,  /* 0101 ->  RESERVED */
-	-1,  /* 0110 ->  RESERVED */
+	45,  /* 0110 ->  4.5x */
 	55,  /* 0111 ->  5.5x */
 	60,  /* 1000 ->  6.0x */
 	70,  /* 1001 ->  7.0x */
@@ -305,84 +270,14 @@
 	120, /* 1111 -> 12.0x */
 };
 
-static int __initdata  nehemiah_c_clock_ratio[32] = {
-	100, /* 0000 -> 10.0x */
-	160, /* 0001 -> 16.0x */
-	40,  /* 0010 ->  RESERVED */
-	90,  /* 0011 ->  9.0x */
-	95,  /* 0100 ->  9.5x */
-	-1,  /* 0101 ->  RESERVED */
-	45,  /* 0110 ->  RESERVED */
-	55,  /* 0111 ->  5.5x */
-	60,  /* 1000 ->  6.0x */
-	70,  /* 1001 ->  7.0x */
-	80,  /* 1010 ->  8.0x */
-	50,  /* 1011 ->  5.0x */
-	65,  /* 1100 ->  6.5x */
-	75,  /* 1101 ->  7.5x */
-	85,  /* 1110 ->  8.5x */
-	120, /* 1111 -> 12.0x */
-	100, /* 0000 -> 10.0x */
-	110, /* 0001 -> 11.0x */
-	120, /* 0010 -> 12.0x */
-	90,  /* 0011 ->  9.0x */
-	105, /* 0100 -> 10.5x */
-	115, /* 0101 -> 11.5x */
-	125, /* 0110 -> 12.5x */
-	135, /* 0111 -> 13.5x */
-	140, /* 1000 -> 14.0x */
-	150, /* 1001 -> 15.0x */
-	160, /* 1010 -> 16.0x */
-	130, /* 1011 -> 13.0x */
-	145, /* 1100 -> 14.5x */
-	155, /* 1101 -> 15.5x */
-	-1,  /* 1110 -> RESERVED (13.0x) */
-	120, /* 1111 -> 12.0x */
-};
-
-static int __initdata nehemiah_a_eblcr[32] = {
+static int __initdata nehemiah_eblcr[32] = {
 	50,  /* 0000 ->  5.0x */
 	160, /* 0001 -> 16.0x */
-	-1,  /* 0010 ->  RESERVED */
+	40,  /* 0010 ->  4.0x */
 	100, /* 0011 -> 10.0x */
 	55,  /* 0100 ->  5.5x */
 	-1,  /* 0101 ->  RESERVED */
-	-1,  /* 0110 ->  RESERVED */
-	95,  /* 0111 ->  9.5x */
-	90,  /* 1000 ->  9.0x */
-	70,  /* 1001 ->  7.0x */
-	80,  /* 1010 ->  8.0x */
-	60,  /* 1011 ->  6.0x */
-	120, /* 1100 -> 12.0x */
-	75,  /* 1101 ->  7.5x */
-	85,  /* 1110 ->  8.5x */
-	65,  /* 1111 ->  6.5x */
-	90,  /* 0000 ->  9.0x */
-	-1,  /* 0001 -> RESERVED */
-	120, /* 0010 -> 12.0x */
-	100, /* 0011 -> 10.0x */
-	135, /* 0100 -> 13.5x */
-	115, /* 0101 -> 11.5x */
-	125, /* 0110 -> 12.5x */
-	105, /* 0111 -> 10.5x */
-	130, /* 1000 -> 13.0x */
-	150, /* 1001 -> 15.0x */
-	160, /* 1010 -> 16.0x */
-	140, /* 1011 -> 14.0x */
-	120, /* 1100 -> 12.0x */
-	155, /* 1101 -> 15.5x */
-	-1,  /* 1110 -> RESERVED (13.0x) */
-	145 /* 1111 -> 14.5x */
-   /* end of table  */
-};
-static int __initdata nehemiah_b_eblcr[32] = {
-	50,  /* 0000 ->  5.0x */
-	160, /* 0001 -> 16.0x */
-	-1,  /* 0010 ->  RESERVED */
-	100, /* 0011 -> 10.0x */
-	55,  /* 0100 ->  5.5x */
-	-1,  /* 0101 ->  RESERVED */
-	-1,  /* 0110 ->  RESERVED */
+	45,  /* 0110 ->  4.5x */
 	95,  /* 0111 ->  9.5x */
 	90,  /* 1000 ->  9.0x */
 	70,  /* 1001 ->  7.0x */
@@ -408,42 +303,6 @@
 	155, /* 1101 -> 15.5x */
 	-1,  /* 1110 -> RESERVED (13.0x) */
 	145 /* 1111 -> 14.5x */
-	   /* end of table  */
-};
-static int __initdata nehemiah_c_eblcr[32] = {
-	50,  /* 0000 ->  5.0x */
-	160, /* 0001 -> 16.0x */
-	40,  /* 0010 ->  RESERVED */
-	100, /* 0011 -> 10.0x */
-	55,  /* 0100 ->  5.5x */
-	-1,  /* 0101 ->  RESERVED */
-	45,  /* 0110 ->  RESERVED */
-	95,  /* 0111 ->  9.5x */
-	90,  /* 1000 ->  9.0x */
-	70,  /* 1001 ->  7.0x */
-	80,  /* 1010 ->  8.0x */
-	60,  /* 1011 ->  6.0x */
-	120, /* 1100 -> 12.0x */
-	75,  /* 1101 ->  7.5x */
-	85,  /* 1110 ->  8.5x */
-	65,  /* 1111 ->  6.5x */
-	90,  /* 0000 ->  9.0x */
-	110, /* 0001 -> 11.0x */
-	120, /* 0010 -> 12.0x */
-	100, /* 0011 -> 10.0x */
-	135, /* 0100 -> 13.5x */
-	115, /* 0101 -> 11.5x */
-	125, /* 0110 -> 12.5x */
-	105, /* 0111 -> 10.5x */
-	130, /* 1000 -> 13.0x */
-	150, /* 1001 -> 15.0x */
-	160, /* 1010 -> 16.0x */
-	140, /* 1011 -> 14.0x */
-	120, /* 1100 -> 12.0x */
-	155, /* 1101 -> 15.5x */
-	-1,  /* 1110 -> RESERVED (13.0x) */
-	145 /* 1111 -> 14.5x */
-	  /* end of table  */
 };
 
 /*
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 2d64916..fe3b670 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -1289,7 +1289,11 @@
 	if (query_current_values_with_pending_wait(data))
 		goto out;
 
-	khz = find_khz_freq_from_fid(data->currfid);
+	if (cpu_family == CPU_HW_PSTATE)
+		khz = find_khz_freq_from_fiddid(data->currfid, data->currdid);
+	else
+		khz = find_khz_freq_from_fid(data->currfid);
+
 
 out:
 	set_cpus_allowed(current, oldmask);
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index c0c3b59..de27bd0 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -6,6 +6,7 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/timer.h>
+#include <asm/pci-direct.h>
 
 #include "cpu.h"
 
@@ -161,19 +162,19 @@
 static void __cpuinit geode_configure(void)
 {
 	unsigned long flags;
-	u8 ccr3, ccr4;
+	u8 ccr3;
 	local_irq_save(flags);
 
 	/* Suspend on halt power saving and enable #SUSP pin */
 	setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88);
 
 	ccr3 = getCx86(CX86_CCR3);
-	setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);	/* Enable */
+	setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);	/* enable MAPEN */
 	
-	ccr4 = getCx86(CX86_CCR4);
-	ccr4 |= 0x38;		/* FPU fast, DTE cache, Mem bypass */
-	
-	setCx86(CX86_CCR3, ccr3);
+
+	/* FPU fast, DTE cache, Mem bypass */
+	setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x38);
+	setCx86(CX86_CCR3, ccr3);			/* disable MAPEN */
 	
 	set_cx86_memwb();
 	set_cx86_reorder();	
@@ -183,14 +184,6 @@
 }
 
 
-#ifdef CONFIG_PCI
-static struct pci_device_id __cpuinitdata cyrix_55x0[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520) },
-	{ },
-};
-#endif
-
 static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
 {
 	unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
@@ -258,6 +251,8 @@
 
 	case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
 #ifdef CONFIG_PCI
+	{
+		u32 vendor, device;
 		/* It isn't really a PCI quirk directly, but the cure is the
 		   same. The MediaGX has deep magic SMM stuff that handles the
 		   SB emulation. It thows away the fifo on disable_dma() which
@@ -273,22 +268,34 @@
 		printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
 		isa_dma_bridge_buggy = 2;
 
+		/* We do this before the PCI layer is running. However we
+		   are safe here as we know the bridge must be a Cyrix
+		   companion and must be present */
+		vendor = read_pci_config_16(0, 0, 0x12, PCI_VENDOR_ID);
+		device = read_pci_config_16(0, 0, 0x12, PCI_DEVICE_ID);
 
 		/*
 		 *  The 5510/5520 companion chips have a funky PIT.
 		 */  
-		if (pci_dev_present(cyrix_55x0))
+		if (vendor == PCI_VENDOR_ID_CYRIX &&
+	 (device == PCI_DEVICE_ID_CYRIX_5510 || device == PCI_DEVICE_ID_CYRIX_5520))
 			pit_latch_buggy = 1;
+	}
 #endif
 		c->x86_cache_size=16;	/* Yep 16K integrated cache thats it */
 
 		/* GXm supports extended cpuid levels 'ala' AMD */
 		if (c->cpuid_level == 2) {
 			/* Enable cxMMX extensions (GX1 Datasheet 54) */
-			setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
+			setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1);
 			
-			/* GXlv/GXm/GX1 */
-			if((dir1 >= 0x50 && dir1 <= 0x54) || dir1 >= 0x63)
+			/*
+			 * GXm : 0x30 ... 0x5f GXm  datasheet 51
+			 * GXlv: 0x6x          GXlv datasheet 54
+			 *  ?  : 0x7x
+			 * GX1 : 0x8x          GX1  datasheet 56
+			 */
+			if((0x30 <= dir1 && dir1 <= 0x6f) || (0x80 <=dir1 && dir1 <= 0x8f))
 				geode_configure();
 			get_model_name(c);  /* get CPU marketing name */
 			return;
@@ -415,15 +422,14 @@
 		
    	        if (dir0 == 5 || dir0 == 3)
    	        {
-			unsigned char ccr3, ccr4;
+			unsigned char ccr3;
 			unsigned long flags;
 			printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
 			local_irq_save(flags);
 			ccr3 = getCx86(CX86_CCR3);
-			setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
-			ccr4 = getCx86(CX86_CCR4);
-			setCx86(CX86_CCR4, ccr4 | 0x80);          /* enable cpuid  */
-			setCx86(CX86_CCR3, ccr3);                 /* disable MAPEN */
+			setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);       /* enable MAPEN  */
+			setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x80);  /* enable cpuid  */
+			setCx86(CX86_CCR3, ccr3);                       /* disable MAPEN */
 			local_irq_restore(flags);
 		}
 	}
diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c
index d555bec..4f10c62 100644
--- a/arch/i386/kernel/cpu/mcheck/mce.c
+++ b/arch/i386/kernel/cpu/mcheck/mce.c
@@ -12,6 +12,7 @@
 
 #include <asm/processor.h> 
 #include <asm/system.h>
+#include <asm/mce.h>
 
 #include "mce.h"
 
diff --git a/arch/i386/kernel/cpu/mcheck/mce.h b/arch/i386/kernel/cpu/mcheck/mce.h
index 84fd4cf..81fb6e2 100644
--- a/arch/i386/kernel/cpu/mcheck/mce.h
+++ b/arch/i386/kernel/cpu/mcheck/mce.h
@@ -1,4 +1,5 @@
 #include <linux/init.h>
+#include <asm/mce.h>
 
 void amd_mcheck_init(struct cpuinfo_x86 *c);
 void intel_p4_mcheck_init(struct cpuinfo_x86 *c);
@@ -9,6 +10,5 @@
 /* Call the installed machine check handler for this CPU setup. */
 extern fastcall void (*machine_check_vector)(struct pt_regs *, long error_code);
 
-extern int mce_disabled;
 extern int nr_mce_banks;
 
diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c
index 5ae1705..c7d8f17 100644
--- a/arch/i386/kernel/cpu/mtrr/if.c
+++ b/arch/i386/kernel/cpu/mtrr/if.c
@@ -211,6 +211,9 @@
 	default:
 		return -ENOTTY;
 	case MTRRIOC_ADD_ENTRY:
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_ADD_ENTRY:
+#endif
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		err =
@@ -218,21 +221,33 @@
 				  file, 0);
 		break;
 	case MTRRIOC_SET_ENTRY:
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_SET_ENTRY:
+#endif
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		err = mtrr_add(sentry.base, sentry.size, sentry.type, 0);
 		break;
 	case MTRRIOC_DEL_ENTRY:
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_DEL_ENTRY:
+#endif
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		err = mtrr_file_del(sentry.base, sentry.size, file, 0);
 		break;
 	case MTRRIOC_KILL_ENTRY:
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_KILL_ENTRY:
+#endif
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		err = mtrr_del(-1, sentry.base, sentry.size);
 		break;
 	case MTRRIOC_GET_ENTRY:
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_GET_ENTRY:
+#endif
 		if (gentry.regnum >= num_var_ranges)
 			return -EINVAL;
 		mtrr_if->get(gentry.regnum, &gentry.base, &size, &type);
@@ -249,6 +264,9 @@
 
 		break;
 	case MTRRIOC_ADD_PAGE_ENTRY:
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_ADD_PAGE_ENTRY:
+#endif
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		err =
@@ -256,21 +274,33 @@
 				  file, 1);
 		break;
 	case MTRRIOC_SET_PAGE_ENTRY:
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_SET_PAGE_ENTRY:
+#endif
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		err = mtrr_add_page(sentry.base, sentry.size, sentry.type, 0);
 		break;
 	case MTRRIOC_DEL_PAGE_ENTRY:
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_DEL_PAGE_ENTRY:
+#endif
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		err = mtrr_file_del(sentry.base, sentry.size, file, 1);
 		break;
 	case MTRRIOC_KILL_PAGE_ENTRY:
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_KILL_PAGE_ENTRY:
+#endif
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		err = mtrr_del_page(-1, sentry.base, sentry.size);
 		break;
 	case MTRRIOC_GET_PAGE_ENTRY:
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_GET_PAGE_ENTRY:
+#endif
 		if (gentry.regnum >= num_var_ranges)
 			return -EINVAL;
 		mtrr_if->get(gentry.regnum, &gentry.base, &size, &type);
@@ -339,7 +369,7 @@
 	return single_open(file, mtrr_seq_show, NULL);
 }
 
-static struct file_operations mtrr_fops = {
+static const struct file_operations mtrr_fops = {
 	.owner   = THIS_MODULE,
 	.open	 = mtrr_open, 
 	.read    = seq_read,
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index 16bb7ea..0acfb6a 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -50,7 +50,7 @@
 unsigned int *usage_table;
 static DEFINE_MUTEX(mtrr_mutex);
 
-u32 size_or_mask, size_and_mask;
+u64 size_or_mask, size_and_mask;
 
 static struct mtrr_ops * mtrr_ops[X86_VENDOR_NUM] = {};
 
@@ -662,8 +662,8 @@
 			     boot_cpu_data.x86_mask == 0x4))
 				phys_addr = 36;
 
-			size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
-			size_and_mask = ~size_or_mask & 0xfff00000;
+			size_or_mask = ~((1ULL << (phys_addr - PAGE_SHIFT)) - 1);
+			size_and_mask = ~size_or_mask & 0xfffff00000ULL;
 		} else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR &&
 			   boot_cpu_data.x86 == 6) {
 			/* VIA C* family have Intel style MTRRs, but
diff --git a/arch/i386/kernel/cpu/mtrr/mtrr.h b/arch/i386/kernel/cpu/mtrr/mtrr.h
index d61ea9d..289dfe6 100644
--- a/arch/i386/kernel/cpu/mtrr/mtrr.h
+++ b/arch/i386/kernel/cpu/mtrr/mtrr.h
@@ -84,7 +84,7 @@
 
 extern void set_mtrr_ops(struct mtrr_ops * ops);
 
-extern u32 size_or_mask, size_and_mask;
+extern u64 size_or_mask, size_and_mask;
 extern struct mtrr_ops * mtrr_if;
 
 #define is_cpu(vnd)	(mtrr_if && mtrr_if->vendor == X86_VENDOR_##vnd)
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 6624d85..47e3ebb 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -29,7 +29,7 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
-		NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow",
+		NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow",
 
 		/* Transmeta-defined */
 		"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -47,7 +47,7 @@
 		/* Intel-defined (#2) */
 		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
 		"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
-		NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* VIA/Cyrix/Centaur-defined */
@@ -57,8 +57,9 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* AMD-defined (#2) */
-		"lahf_lm", "cmp_legacy", "svm", NULL, "cr8legacy", NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		"lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm",
+		"sse4a", "misalignsse",
+		"3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	};
@@ -69,8 +70,11 @@
 		"ttp",  /* thermal trip */
 		"tm",
 		"stc",
+		"100mhzsteps",
+		"hwpstate",
 		NULL,
-		/* nothing */	/* constant_tsc - moved to flags */
+		NULL,	/* constant_tsc - moved to flags */
+		/* nothing */
 	};
 	struct cpuinfo_x86 *c = v;
 	int i, n = c - cpu_data;
diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c
index 4056fb7..5678d46 100644
--- a/arch/i386/kernel/cpu/transmeta.c
+++ b/arch/i386/kernel/cpu/transmeta.c
@@ -9,7 +9,7 @@
 {
 	unsigned int cap_mask, uk, max, dummy;
 	unsigned int cms_rev1, cms_rev2;
-	unsigned int cpu_rev, cpu_freq, cpu_flags, new_cpu_rev;
+	unsigned int cpu_rev, cpu_freq = 0, cpu_flags, new_cpu_rev;
 	char cpu_info[65];
 
 	get_model_name(c);	/* Same as AMD/Cyrix */
@@ -72,6 +72,9 @@
 	wrmsr(0x80860004, ~0, uk);
 	c->x86_capability[0] = cpuid_edx(0x00000001);
 	wrmsr(0x80860004, cap_mask, uk);
+
+	/* All Transmeta CPUs have a constant TSC */
+	set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
 	
 	/* If we can run i686 user-space code, call us an i686 */
 #define USER686 (X86_FEATURE_TSC|X86_FEATURE_CX8|X86_FEATURE_CMOV)
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 51130b3..eeae0d9 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -48,7 +48,6 @@
 #ifdef CONFIG_SMP
 
 struct cpuid_command {
-	int cpu;
 	u32 reg;
 	u32 *data;
 };
@@ -57,8 +56,7 @@
 {
 	struct cpuid_command *cmd = (struct cpuid_command *)cmd_block;
 
-	if (cmd->cpu == smp_processor_id())
-		cpuid(cmd->reg, &cmd->data[0], &cmd->data[1], &cmd->data[2],
+	cpuid(cmd->reg, &cmd->data[0], &cmd->data[1], &cmd->data[2],
 		      &cmd->data[3]);
 }
 
@@ -70,11 +68,10 @@
 	if (cpu == smp_processor_id()) {
 		cpuid(reg, &data[0], &data[1], &data[2], &data[3]);
 	} else {
-		cmd.cpu = cpu;
 		cmd.reg = reg;
 		cmd.data = data;
 
-		smp_call_function(cpuid_smp_cpuid, &cmd, 1, 1);
+		smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1, 1);
 	}
 	preempt_enable();
 }
@@ -148,7 +145,7 @@
 /*
  * File operations we support
  */
-static struct file_operations cpuid_fops = {
+static const struct file_operations cpuid_fops = {
 	.owner = THIS_MODULE,
 	.llseek = cpuid_seek,
 	.read = cpuid_read,
diff --git a/arch/i386/kernel/e820.c b/arch/i386/kernel/e820.c
index f391abc..70f3956 100644
--- a/arch/i386/kernel/e820.c
+++ b/arch/i386/kernel/e820.c
@@ -14,6 +14,7 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/e820.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_EFI
 int efi_enabled = 0;
@@ -156,21 +157,22 @@
 	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
 } };
 
-static int romsignature(const unsigned char *x)
+#define ROMSIGNATURE 0xaa55
+
+static int __init romsignature(const unsigned char *rom)
 {
 	unsigned short sig;
-	int ret = 0;
-	if (probe_kernel_address((const unsigned short *)x, sig) == 0)
-		ret = (sig == 0xaa55);
-	return ret;
+
+	return probe_kernel_address((const unsigned short *)rom, sig) == 0 &&
+	       sig == ROMSIGNATURE;
 }
 
 static int __init romchecksum(unsigned char *rom, unsigned long length)
 {
-	unsigned char *p, sum = 0;
+	unsigned char sum;
 
-	for (p = rom; p < rom + length; p++)
-		sum += *p;
+	for (sum = 0; length; length--)
+		sum += *rom++;
 	return sum == 0;
 }
 
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 5e47683..18bddcb 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -30,7 +30,7 @@
  *	18(%esp) - %eax
  *	1C(%esp) - %ds
  *	20(%esp) - %es
- *	24(%esp) - %gs
+ *	24(%esp) - %fs
  *	28(%esp) - orig_eax
  *	2C(%esp) - %eip
  *	30(%esp) - %cs
@@ -99,9 +99,9 @@
 
 #define SAVE_ALL \
 	cld; \
-	pushl %gs; \
+	pushl %fs; \
 	CFI_ADJUST_CFA_OFFSET 4;\
-	/*CFI_REL_OFFSET gs, 0;*/\
+	/*CFI_REL_OFFSET fs, 0;*/\
 	pushl %es; \
 	CFI_ADJUST_CFA_OFFSET 4;\
 	/*CFI_REL_OFFSET es, 0;*/\
@@ -133,7 +133,7 @@
 	movl %edx, %ds; \
 	movl %edx, %es; \
 	movl $(__KERNEL_PDA), %edx; \
-	movl %edx, %gs
+	movl %edx, %fs
 
 #define RESTORE_INT_REGS \
 	popl %ebx;	\
@@ -166,9 +166,9 @@
 2:	popl %es;	\
 	CFI_ADJUST_CFA_OFFSET -4;\
 	/*CFI_RESTORE es;*/\
-3:	popl %gs;	\
+3:	popl %fs;	\
 	CFI_ADJUST_CFA_OFFSET -4;\
-	/*CFI_RESTORE gs;*/\
+	/*CFI_RESTORE fs;*/\
 .pushsection .fixup,"ax";	\
 4:	movl $0,(%esp);	\
 	jmp 1b;		\
@@ -227,6 +227,7 @@
 	CFI_ADJUST_CFA_OFFSET -4
 	jmp syscall_exit
 	CFI_ENDPROC
+END(ret_from_fork)
 
 /*
  * Return to user mode is not as complex as all this looks,
@@ -258,6 +259,7 @@
 					# int/exception return?
 	jne work_pending
 	jmp restore_all
+END(ret_from_exception)
 
 #ifdef CONFIG_PREEMPT
 ENTRY(resume_kernel)
@@ -272,6 +274,7 @@
 	jz restore_all
 	call preempt_schedule_irq
 	jmp need_resched
+END(resume_kernel)
 #endif
 	CFI_ENDPROC
 
@@ -349,16 +352,17 @@
 	movl PT_OLDESP(%esp), %ecx
 	xorl %ebp,%ebp
 	TRACE_IRQS_ON
-1:	mov  PT_GS(%esp), %gs
+1:	mov  PT_FS(%esp), %fs
 	ENABLE_INTERRUPTS_SYSEXIT
 	CFI_ENDPROC
 .pushsection .fixup,"ax"
-2:	movl $0,PT_GS(%esp)
+2:	movl $0,PT_FS(%esp)
 	jmp 1b
 .section __ex_table,"a"
 	.align 4
 	.long 1b,2b
 .popsection
+ENDPROC(sysenter_entry)
 
 	# system call handler stub
 ENTRY(system_call)
@@ -459,6 +463,7 @@
 	CFI_ADJUST_CFA_OFFSET -8
 	jmp restore_nocheck
 	CFI_ENDPROC
+ENDPROC(system_call)
 
 	# perform work that needs to be done immediately before resumption
 	ALIGN
@@ -504,6 +509,7 @@
 	xorl %edx, %edx
 	call do_notify_resume
 	jmp resume_userspace_sig
+END(work_pending)
 
 	# perform syscall exit tracing
 	ALIGN
@@ -519,6 +525,7 @@
 	cmpl $(nr_syscalls), %eax
 	jnae syscall_call
 	jmp syscall_exit
+END(syscall_trace_entry)
 
 	# perform syscall exit tracing
 	ALIGN
@@ -532,6 +539,7 @@
 	movl $1, %edx
 	call do_syscall_trace
 	jmp resume_userspace
+END(syscall_exit_work)
 	CFI_ENDPROC
 
 	RING0_INT_FRAME			# can't unwind into user space anyway
@@ -542,15 +550,17 @@
 	GET_THREAD_INFO(%ebp)
 	movl $-EFAULT,PT_EAX(%esp)
 	jmp resume_userspace
+END(syscall_fault)
 
 syscall_badsys:
 	movl $-ENOSYS,PT_EAX(%esp)
 	jmp resume_userspace
+END(syscall_badsys)
 	CFI_ENDPROC
 
 #define FIXUP_ESPFIX_STACK \
 	/* since we are on a wrong stack, we cant make it a C code :( */ \
-	movl %gs:PDA_cpu, %ebx; \
+	movl %fs:PDA_cpu, %ebx; \
 	PER_CPU(cpu_gdt_descr, %ebx); \
 	movl GDS_address(%ebx), %ebx; \
 	GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
@@ -581,9 +591,9 @@
 ENTRY(interrupt)
 .text
 
-vector=0
 ENTRY(irq_entries_start)
 	RING0_INT_FRAME
+vector=0
 .rept NR_IRQS
 	ALIGN
  .if vector
@@ -592,11 +602,16 @@
 1:	pushl $~(vector)
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp common_interrupt
-.data
+ .previous
 	.long 1b
-.text
+ .text
 vector=vector+1
 .endr
+END(irq_entries_start)
+
+.previous
+END(interrupt)
+.previous
 
 /*
  * the CPU automatically disables interrupts when executing an IRQ vector,
@@ -609,6 +624,7 @@
 	movl %esp,%eax
 	call do_IRQ
 	jmp ret_from_intr
+ENDPROC(common_interrupt)
 	CFI_ENDPROC
 
 #define BUILD_INTERRUPT(name, nr)	\
@@ -621,18 +637,24 @@
 	movl %esp,%eax;			\
 	call smp_/**/name;		\
 	jmp ret_from_intr;		\
-	CFI_ENDPROC
+	CFI_ENDPROC;			\
+ENDPROC(name)
 
 /* The include is where all of the SMP etc. interrupts come from */
 #include "entry_arch.h"
 
+/* This alternate entry is needed because we hijack the apic LVTT */
+#if defined(CONFIG_VMI) && defined(CONFIG_X86_LOCAL_APIC)
+BUILD_INTERRUPT(apic_vmi_timer_interrupt,LOCAL_TIMER_VECTOR)
+#endif
+
 KPROBE_ENTRY(page_fault)
 	RING0_EC_FRAME
 	pushl $do_page_fault
 	CFI_ADJUST_CFA_OFFSET 4
 	ALIGN
 error_code:
-	/* the function address is in %gs's slot on the stack */
+	/* the function address is in %fs's slot on the stack */
 	pushl %es
 	CFI_ADJUST_CFA_OFFSET 4
 	/*CFI_REL_OFFSET es, 0*/
@@ -661,20 +683,20 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	CFI_REL_OFFSET ebx, 0
 	cld
-	pushl %gs
+	pushl %fs
 	CFI_ADJUST_CFA_OFFSET 4
-	/*CFI_REL_OFFSET gs, 0*/
+	/*CFI_REL_OFFSET fs, 0*/
 	movl $(__KERNEL_PDA), %ecx
-	movl %ecx, %gs
+	movl %ecx, %fs
 	UNWIND_ESPFIX_STACK
 	popl %ecx
 	CFI_ADJUST_CFA_OFFSET -4
 	/*CFI_REGISTER es, ecx*/
-	movl PT_GS(%esp), %edi		# get the function address
+	movl PT_FS(%esp), %edi		# get the function address
 	movl PT_ORIG_EAX(%esp), %edx	# get the error code
 	movl $-1, PT_ORIG_EAX(%esp)	# no syscall to restart
-	mov  %ecx, PT_GS(%esp)
-	/*CFI_REL_OFFSET gs, ES*/
+	mov  %ecx, PT_FS(%esp)
+	/*CFI_REL_OFFSET fs, ES*/
 	movl $(__USER_DS), %ecx
 	movl %ecx, %ds
 	movl %ecx, %es
@@ -692,6 +714,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(coprocessor_error)
 
 ENTRY(simd_coprocessor_error)
 	RING0_INT_FRAME
@@ -701,6 +724,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(simd_coprocessor_error)
 
 ENTRY(device_not_available)
 	RING0_INT_FRAME
@@ -721,6 +745,7 @@
 	CFI_ADJUST_CFA_OFFSET -4
 	jmp ret_from_exception
 	CFI_ENDPROC
+END(device_not_available)
 
 /*
  * Debug traps and NMI can happen at the one SYSENTER instruction
@@ -864,10 +889,12 @@
 	.align 4
 	.long 1b,iret_exc
 .previous
+END(native_iret)
 
 ENTRY(native_irq_enable_sysexit)
 	sti
 	sysexit
+END(native_irq_enable_sysexit)
 #endif
 
 KPROBE_ENTRY(int3)
@@ -890,6 +917,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(overflow)
 
 ENTRY(bounds)
 	RING0_INT_FRAME
@@ -899,6 +927,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(bounds)
 
 ENTRY(invalid_op)
 	RING0_INT_FRAME
@@ -908,6 +937,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(invalid_op)
 
 ENTRY(coprocessor_segment_overrun)
 	RING0_INT_FRAME
@@ -917,6 +947,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(coprocessor_segment_overrun)
 
 ENTRY(invalid_TSS)
 	RING0_EC_FRAME
@@ -924,6 +955,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(invalid_TSS)
 
 ENTRY(segment_not_present)
 	RING0_EC_FRAME
@@ -931,6 +963,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(segment_not_present)
 
 ENTRY(stack_segment)
 	RING0_EC_FRAME
@@ -938,6 +971,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(stack_segment)
 
 KPROBE_ENTRY(general_protection)
 	RING0_EC_FRAME
@@ -953,6 +987,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(alignment_check)
 
 ENTRY(divide_error)
 	RING0_INT_FRAME
@@ -962,6 +997,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(divide_error)
 
 #ifdef CONFIG_X86_MCE
 ENTRY(machine_check)
@@ -972,6 +1008,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(machine_check)
 #endif
 
 ENTRY(spurious_interrupt_bug)
@@ -982,6 +1019,7 @@
 	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
+END(spurious_interrupt_bug)
 
 ENTRY(kernel_thread_helper)
 	pushl $0		# fake return address for unwinder
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index edef508..3fa7f93 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -53,6 +53,7 @@
  * any particular GDT layout, because we load our own as soon as we
  * can.
  */
+.section .text.head,"ax",@progbits
 ENTRY(startup_32)
 
 #ifdef CONFIG_PARAVIRT
@@ -103,7 +104,7 @@
 	movzwl OLD_CL_OFFSET,%esi
 	addl $(OLD_CL_BASE_ADDR),%esi
 2:
-	movl $(saved_command_line - __PAGE_OFFSET),%edi
+	movl $(boot_command_line - __PAGE_OFFSET),%edi
 	movl $(COMMAND_LINE_SIZE/4),%ecx
 	rep
 	movsl
@@ -141,16 +142,25 @@
 	jb 10b
 	movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
 
-#ifdef CONFIG_SMP
 	xorl %ebx,%ebx				/* This is the boot CPU (BSP) */
 	jmp 3f
-
 /*
  * Non-boot CPU entry point; entered from trampoline.S
  * We can't lgdt here, because lgdt itself uses a data segment, but
  * we know the trampoline has already loaded the boot_gdt_table GDT
  * for us.
+ *
+ * If cpu hotplug is not supported then this code can go in init section
+ * which will be freed later
  */
+
+#ifdef CONFIG_HOTPLUG_CPU
+.section .text,"ax",@progbits
+#else
+.section .init.text,"ax",@progbits
+#endif
+
+#ifdef CONFIG_SMP
 ENTRY(startup_32_smp)
 	cld
 	movl $(__BOOT_DS),%eax
@@ -208,8 +218,8 @@
 	xorl %ebx,%ebx
 	incl %ebx
 
-3:
 #endif /* CONFIG_SMP */
+3:
 
 /*
  * Enable paging
@@ -309,7 +319,7 @@
 
 	call check_x87
 	call setup_pda
-	lgdt cpu_gdt_descr
+	lgdt early_gdt_descr
 	lidt idt_descr
 	ljmp $(__KERNEL_CS),$1f
 1:	movl $(__KERNEL_DS),%eax	# reload all the segment registers
@@ -319,12 +329,12 @@
 	movl %eax,%ds
 	movl %eax,%es
 
-	xorl %eax,%eax			# Clear FS and LDT
-	movl %eax,%fs
+	xorl %eax,%eax			# Clear GS and LDT
+	movl %eax,%gs
 	lldt %ax
 
 	movl $(__KERNEL_PDA),%eax
-	mov  %eax,%gs
+	mov  %eax,%fs
 
 	cld			# gcc2 wants the direction flag cleared at all times
 	pushl $0		# fake return address for unwinder
@@ -360,12 +370,12 @@
  * cpu_gdt_table and boot_pda; for secondary CPUs, these will be
  * that CPU's GDT and PDA.
  */
-setup_pda:
+ENTRY(setup_pda)
 	/* get the PDA pointer */
 	movl start_pda, %eax
 
 	/* slot the PDA address into the GDT */
-	mov cpu_gdt_descr+2, %ecx
+	mov early_gdt_descr+2, %ecx
 	mov %ax, (__KERNEL_PDA+0+2)(%ecx)		/* base & 0x0000ffff */
 	shr $16, %eax
 	mov %al, (__KERNEL_PDA+4+0)(%ecx)		/* base & 0x00ff0000 */
@@ -492,6 +502,7 @@
 #endif
 	iret
 
+.section .text
 #ifdef CONFIG_PARAVIRT
 startup_paravirt:
 	cld
@@ -502,10 +513,11 @@
 	pushl	%ecx
 	pushl	%eax
 
-	/* paravirt.o is last in link, and that probe fn never returns */
 	pushl	$__start_paravirtprobe
 1:
 	movl	0(%esp), %eax
+	cmpl	$__stop_paravirtprobe, %eax
+	je	unhandled_paravirt
 	pushl	(%eax)
 	movl	8(%esp), %eax
 	call	*(%esp)
@@ -517,6 +529,10 @@
 
 	addl	$4, (%esp)
 	jmp	1b
+
+unhandled_paravirt:
+	/* Nothing wanted us: we're screwed. */
+	ud2
 #endif
 
 /*
@@ -581,7 +597,7 @@
 
 # boot GDT descriptor (later on used by CPU#0):
 	.word 0				# 32 bit align gdt_desc.address
-ENTRY(cpu_gdt_descr)
+ENTRY(early_gdt_descr)
 	.word GDT_ENTRIES*8-1
 	.long cpu_gdt_table
 
diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c
index 45a8685..e1006b7 100644
--- a/arch/i386/kernel/hpet.c
+++ b/arch/i386/kernel/hpet.c
@@ -1,4 +1,5 @@
 #include <linux/clocksource.h>
+#include <linux/clockchips.h>
 #include <linux/errno.h>
 #include <linux/hpet.h>
 #include <linux/init.h>
@@ -6,17 +7,278 @@
 #include <asm/hpet.h>
 #include <asm/io.h>
 
+extern struct clock_event_device *global_clock_event;
+
 #define HPET_MASK	CLOCKSOURCE_MASK(32)
 #define HPET_SHIFT	22
 
 /* FSEC = 10^-15 NSEC = 10^-9 */
 #define FSEC_PER_NSEC	1000000
 
-static void *hpet_ptr;
+/*
+ * HPET address is set in acpi/boot.c, when an ACPI entry exists
+ */
+unsigned long hpet_address;
+static void __iomem * hpet_virt_address;
 
+static inline unsigned long hpet_readl(unsigned long a)
+{
+	return readl(hpet_virt_address + a);
+}
+
+static inline void hpet_writel(unsigned long d, unsigned long a)
+{
+	writel(d, hpet_virt_address + a);
+}
+
+/*
+ * HPET command line enable / disable
+ */
+static int boot_hpet_disable;
+
+static int __init hpet_setup(char* str)
+{
+	if (str) {
+		if (!strncmp("disable", str, 7))
+			boot_hpet_disable = 1;
+	}
+	return 1;
+}
+__setup("hpet=", hpet_setup);
+
+static inline int is_hpet_capable(void)
+{
+	return (!boot_hpet_disable && hpet_address);
+}
+
+/*
+ * HPET timer interrupt enable / disable
+ */
+static int hpet_legacy_int_enabled;
+
+/**
+ * is_hpet_enabled - check whether the hpet timer interrupt is enabled
+ */
+int is_hpet_enabled(void)
+{
+	return is_hpet_capable() && hpet_legacy_int_enabled;
+}
+
+/*
+ * When the hpet driver (/dev/hpet) is enabled, we need to reserve
+ * timer 0 and timer 1 in case of RTC emulation.
+ */
+#ifdef CONFIG_HPET
+static void hpet_reserve_platform_timers(unsigned long id)
+{
+	struct hpet __iomem *hpet = hpet_virt_address;
+	struct hpet_timer __iomem *timer = &hpet->hpet_timers[2];
+	unsigned int nrtimers, i;
+	struct hpet_data hd;
+
+	nrtimers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
+
+	memset(&hd, 0, sizeof (hd));
+	hd.hd_phys_address = hpet_address;
+	hd.hd_address = hpet_virt_address;
+	hd.hd_nirqs = nrtimers;
+	hd.hd_flags = HPET_DATA_PLATFORM;
+	hpet_reserve_timer(&hd, 0);
+
+#ifdef CONFIG_HPET_EMULATE_RTC
+	hpet_reserve_timer(&hd, 1);
+#endif
+
+	hd.hd_irq[0] = HPET_LEGACY_8254;
+	hd.hd_irq[1] = HPET_LEGACY_RTC;
+
+	for (i = 2; i < nrtimers; timer++, i++)
+		hd.hd_irq[i] = (timer->hpet_config & Tn_INT_ROUTE_CNF_MASK) >>
+			Tn_INT_ROUTE_CNF_SHIFT;
+
+	hpet_alloc(&hd);
+
+}
+#else
+static void hpet_reserve_platform_timers(unsigned long id) { }
+#endif
+
+/*
+ * Common hpet info
+ */
+static unsigned long hpet_period;
+
+static void hpet_set_mode(enum clock_event_mode mode,
+			  struct clock_event_device *evt);
+static int hpet_next_event(unsigned long delta,
+			   struct clock_event_device *evt);
+
+/*
+ * The hpet clock event device
+ */
+static struct clock_event_device hpet_clockevent = {
+	.name		= "hpet",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode	= hpet_set_mode,
+	.set_next_event = hpet_next_event,
+	.shift		= 32,
+	.irq		= 0,
+};
+
+static void hpet_start_counter(void)
+{
+	unsigned long cfg = hpet_readl(HPET_CFG);
+
+	cfg &= ~HPET_CFG_ENABLE;
+	hpet_writel(cfg, HPET_CFG);
+	hpet_writel(0, HPET_COUNTER);
+	hpet_writel(0, HPET_COUNTER + 4);
+	cfg |= HPET_CFG_ENABLE;
+	hpet_writel(cfg, HPET_CFG);
+}
+
+static void hpet_enable_int(void)
+{
+	unsigned long cfg = hpet_readl(HPET_CFG);
+
+	cfg |= HPET_CFG_LEGACY;
+	hpet_writel(cfg, HPET_CFG);
+	hpet_legacy_int_enabled = 1;
+}
+
+static void hpet_set_mode(enum clock_event_mode mode,
+			  struct clock_event_device *evt)
+{
+	unsigned long cfg, cmp, now;
+	uint64_t delta;
+
+	switch(mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * hpet_clockevent.mult;
+		delta >>= hpet_clockevent.shift;
+		now = hpet_readl(HPET_COUNTER);
+		cmp = now + (unsigned long) delta;
+		cfg = hpet_readl(HPET_T0_CFG);
+		cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
+		       HPET_TN_SETVAL | HPET_TN_32BIT;
+		hpet_writel(cfg, HPET_T0_CFG);
+		/*
+		 * The first write after writing TN_SETVAL to the
+		 * config register sets the counter value, the second
+		 * write sets the period.
+		 */
+		hpet_writel(cmp, HPET_T0_CMP);
+		udelay(1);
+		hpet_writel((unsigned long) delta, HPET_T0_CMP);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		cfg = hpet_readl(HPET_T0_CFG);
+		cfg &= ~HPET_TN_PERIODIC;
+		cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+		hpet_writel(cfg, HPET_T0_CFG);
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		cfg = hpet_readl(HPET_T0_CFG);
+		cfg &= ~HPET_TN_ENABLE;
+		hpet_writel(cfg, HPET_T0_CFG);
+		break;
+	}
+}
+
+static int hpet_next_event(unsigned long delta,
+			   struct clock_event_device *evt)
+{
+	unsigned long cnt;
+
+	cnt = hpet_readl(HPET_COUNTER);
+	cnt += delta;
+	hpet_writel(cnt, HPET_T0_CMP);
+
+	return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0);
+}
+
+/*
+ * Try to setup the HPET timer
+ */
+int __init hpet_enable(void)
+{
+	unsigned long id;
+	uint64_t hpet_freq;
+
+	if (!is_hpet_capable())
+		return 0;
+
+	hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
+
+	/*
+	 * Read the period and check for a sane value:
+	 */
+	hpet_period = hpet_readl(HPET_PERIOD);
+	if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD)
+		goto out_nohpet;
+
+	/*
+	 * The period is a femto seconds value. We need to calculate the
+	 * scaled math multiplication factor for nanosecond to hpet tick
+	 * conversion.
+	 */
+	hpet_freq = 1000000000000000ULL;
+	do_div(hpet_freq, hpet_period);
+	hpet_clockevent.mult = div_sc((unsigned long) hpet_freq,
+				      NSEC_PER_SEC, 32);
+	/* Calculate the min / max delta */
+	hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
+							   &hpet_clockevent);
+	hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30,
+							   &hpet_clockevent);
+
+	/*
+	 * Read the HPET ID register to retrieve the IRQ routing
+	 * information and the number of channels
+	 */
+	id = hpet_readl(HPET_ID);
+
+#ifdef CONFIG_HPET_EMULATE_RTC
+	/*
+	 * The legacy routing mode needs at least two channels, tick timer
+	 * and the rtc emulation channel.
+	 */
+	if (!(id & HPET_ID_NUMBER))
+		goto out_nohpet;
+#endif
+
+	/* Start the counter */
+	hpet_start_counter();
+
+	if (id & HPET_ID_LEGSUP) {
+		hpet_enable_int();
+		hpet_reserve_platform_timers(id);
+		/*
+		 * Start hpet with the boot cpu mask and make it
+		 * global after the IO_APIC has been initialized.
+		 */
+		hpet_clockevent.cpumask =cpumask_of_cpu(0);
+		clockevents_register_device(&hpet_clockevent);
+		global_clock_event = &hpet_clockevent;
+		return 1;
+	}
+	return 0;
+
+out_nohpet:
+	iounmap(hpet_virt_address);
+	hpet_virt_address = NULL;
+	return 0;
+}
+
+/*
+ * Clock source related code
+ */
 static cycle_t read_hpet(void)
 {
-	return (cycle_t)readl(hpet_ptr);
+	return (cycle_t)hpet_readl(HPET_COUNTER);
 }
 
 static struct clocksource clocksource_hpet = {
@@ -24,29 +286,17 @@
 	.rating		= 250,
 	.read		= read_hpet,
 	.mask		= HPET_MASK,
-	.mult		= 0, /* set below */
 	.shift		= HPET_SHIFT,
-	.is_continuous	= 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init init_hpet_clocksource(void)
 {
-	unsigned long hpet_period;
-	void __iomem* hpet_base;
 	u64 tmp;
-	int err;
 
-	if (!is_hpet_enabled())
+	if (!hpet_virt_address)
 		return -ENODEV;
 
-	/* calculate the hpet address: */
-	hpet_base =
-		(void __iomem*)ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
-	hpet_ptr = hpet_base + HPET_COUNTER;
-
-	/* calculate the frequency: */
-	hpet_period = readl(hpet_base + HPET_PERIOD);
-
 	/*
 	 * hpet period is in femto seconds per cycle
 	 * so we need to convert this to ns/cyc units
@@ -62,11 +312,218 @@
 	do_div(tmp, FSEC_PER_NSEC);
 	clocksource_hpet.mult = (u32)tmp;
 
-	err = clocksource_register(&clocksource_hpet);
-	if (err)
-		iounmap(hpet_base);
-
-	return err;
+	return clocksource_register(&clocksource_hpet);
 }
 
 module_init(init_hpet_clocksource);
+
+#ifdef CONFIG_HPET_EMULATE_RTC
+
+/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
+ * is enabled, we support RTC interrupt functionality in software.
+ * RTC has 3 kinds of interrupts:
+ * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
+ *    is updated
+ * 2) Alarm Interrupt - generate an interrupt at a specific time of day
+ * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
+ *    2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
+ * (1) and (2) above are implemented using polling at a frequency of
+ * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
+ * overhead. (DEFAULT_RTC_INT_FREQ)
+ * For (3), we use interrupts at 64Hz or user specified periodic
+ * frequency, whichever is higher.
+ */
+#include <linux/mc146818rtc.h>
+#include <linux/rtc.h>
+
+#define DEFAULT_RTC_INT_FREQ	64
+#define DEFAULT_RTC_SHIFT	6
+#define RTC_NUM_INTS		1
+
+static unsigned long hpet_rtc_flags;
+static unsigned long hpet_prev_update_sec;
+static struct rtc_time hpet_alarm_time;
+static unsigned long hpet_pie_count;
+static unsigned long hpet_t1_cmp;
+static unsigned long hpet_default_delta;
+static unsigned long hpet_pie_delta;
+static unsigned long hpet_pie_limit;
+
+/*
+ * Timer 1 for RTC emulation. We use one shot mode, as periodic mode
+ * is not supported by all HPET implementations for timer 1.
+ *
+ * hpet_rtc_timer_init() is called when the rtc is initialized.
+ */
+int hpet_rtc_timer_init(void)
+{
+	unsigned long cfg, cnt, delta, flags;
+
+	if (!is_hpet_enabled())
+		return 0;
+
+	if (!hpet_default_delta) {
+		uint64_t clc;
+
+		clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC;
+		clc >>= hpet_clockevent.shift + DEFAULT_RTC_SHIFT;
+		hpet_default_delta = (unsigned long) clc;
+	}
+
+	if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit)
+		delta = hpet_default_delta;
+	else
+		delta = hpet_pie_delta;
+
+	local_irq_save(flags);
+
+	cnt = delta + hpet_readl(HPET_COUNTER);
+	hpet_writel(cnt, HPET_T1_CMP);
+	hpet_t1_cmp = cnt;
+
+	cfg = hpet_readl(HPET_T1_CFG);
+	cfg &= ~HPET_TN_PERIODIC;
+	cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+	hpet_writel(cfg, HPET_T1_CFG);
+
+	local_irq_restore(flags);
+
+	return 1;
+}
+
+/*
+ * The functions below are called from rtc driver.
+ * Return 0 if HPET is not being used.
+ * Otherwise do the necessary changes and return 1.
+ */
+int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
+{
+	if (!is_hpet_enabled())
+		return 0;
+
+	hpet_rtc_flags &= ~bit_mask;
+	return 1;
+}
+
+int hpet_set_rtc_irq_bit(unsigned long bit_mask)
+{
+	unsigned long oldbits = hpet_rtc_flags;
+
+	if (!is_hpet_enabled())
+		return 0;
+
+	hpet_rtc_flags |= bit_mask;
+
+	if (!oldbits)
+		hpet_rtc_timer_init();
+
+	return 1;
+}
+
+int hpet_set_alarm_time(unsigned char hrs, unsigned char min,
+			unsigned char sec)
+{
+	if (!is_hpet_enabled())
+		return 0;
+
+	hpet_alarm_time.tm_hour = hrs;
+	hpet_alarm_time.tm_min = min;
+	hpet_alarm_time.tm_sec = sec;
+
+	return 1;
+}
+
+int hpet_set_periodic_freq(unsigned long freq)
+{
+	uint64_t clc;
+
+	if (!is_hpet_enabled())
+		return 0;
+
+	if (freq <= DEFAULT_RTC_INT_FREQ)
+		hpet_pie_limit = DEFAULT_RTC_INT_FREQ / freq;
+	else {
+		clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC;
+		do_div(clc, freq);
+		clc >>= hpet_clockevent.shift;
+		hpet_pie_delta = (unsigned long) clc;
+	}
+	return 1;
+}
+
+int hpet_rtc_dropped_irq(void)
+{
+	return is_hpet_enabled();
+}
+
+static void hpet_rtc_timer_reinit(void)
+{
+	unsigned long cfg, delta;
+	int lost_ints = -1;
+
+	if (unlikely(!hpet_rtc_flags)) {
+		cfg = hpet_readl(HPET_T1_CFG);
+		cfg &= ~HPET_TN_ENABLE;
+		hpet_writel(cfg, HPET_T1_CFG);
+		return;
+	}
+
+	if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit)
+		delta = hpet_default_delta;
+	else
+		delta = hpet_pie_delta;
+
+	/*
+	 * Increment the comparator value until we are ahead of the
+	 * current count.
+	 */
+	do {
+		hpet_t1_cmp += delta;
+		hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
+		lost_ints++;
+	} while ((long)(hpet_readl(HPET_COUNTER) - hpet_t1_cmp) > 0);
+
+	if (lost_ints) {
+		if (hpet_rtc_flags & RTC_PIE)
+			hpet_pie_count += lost_ints;
+		if (printk_ratelimit())
+			printk(KERN_WARNING "rtc: lost %d interrupts\n",
+				lost_ints);
+	}
+}
+
+irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
+{
+	struct rtc_time curr_time;
+	unsigned long rtc_int_flag = 0;
+
+	hpet_rtc_timer_reinit();
+
+	if (hpet_rtc_flags & (RTC_UIE | RTC_AIE))
+		rtc_get_rtc_time(&curr_time);
+
+	if (hpet_rtc_flags & RTC_UIE &&
+	    curr_time.tm_sec != hpet_prev_update_sec) {
+		rtc_int_flag = RTC_UF;
+		hpet_prev_update_sec = curr_time.tm_sec;
+	}
+
+	if (hpet_rtc_flags & RTC_PIE &&
+	    ++hpet_pie_count >= hpet_pie_limit) {
+		rtc_int_flag |= RTC_PF;
+		hpet_pie_count = 0;
+	}
+
+	if (hpet_rtc_flags & RTC_PIE &&
+	    (curr_time.tm_sec == hpet_alarm_time.tm_sec) &&
+	    (curr_time.tm_min == hpet_alarm_time.tm_min) &&
+	    (curr_time.tm_hour == hpet_alarm_time.tm_hour))
+			rtc_int_flag |= RTC_AF;
+
+	if (rtc_int_flag) {
+		rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
+		rtc_interrupt(rtc_int_flag, dev_id);
+	}
+	return IRQ_HANDLED;
+}
+#endif
diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c
index 9a0060b..a6bc7bb 100644
--- a/arch/i386/kernel/i8253.c
+++ b/arch/i386/kernel/i8253.c
@@ -2,7 +2,7 @@
  * i8253.c  8253/PIT functions
  *
  */
-#include <linux/clocksource.h>
+#include <linux/clockchips.h>
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
 #include <linux/sysdev.h>
@@ -19,20 +19,100 @@
 DEFINE_SPINLOCK(i8253_lock);
 EXPORT_SYMBOL(i8253_lock);
 
-void setup_pit_timer(void)
+/*
+ * HPET replaces the PIT, when enabled. So we need to know, which of
+ * the two timers is used
+ */
+struct clock_event_device *global_clock_event;
+
+/*
+ * Initialize the PIT timer.
+ *
+ * This is also called after resume to bring the PIT into operation again.
+ */
+static void init_pit_timer(enum clock_event_mode mode,
+			   struct clock_event_device *evt)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&i8253_lock, flags);
-	outb_p(0x34,PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
-	udelay(10);
-	outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
-	udelay(10);
-	outb(LATCH >> 8 , PIT_CH0);	/* MSB */
+
+	switch(mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		/* binary, mode 2, LSB/MSB, ch 0 */
+		outb_p(0x34, PIT_MODE);
+		udelay(10);
+		outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
+		udelay(10);
+		outb(LATCH >> 8 , PIT_CH0);	/* MSB */
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+		/* One shot setup */
+		outb_p(0x38, PIT_MODE);
+		udelay(10);
+		break;
+	}
 	spin_unlock_irqrestore(&i8253_lock, flags);
 }
 
 /*
+ * Program the next event in oneshot mode
+ *
+ * Delta is given in PIT ticks
+ */
+static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8253_lock, flags);
+	outb_p(delta & 0xff , PIT_CH0);	/* LSB */
+	outb(delta >> 8 , PIT_CH0);	/* MSB */
+	spin_unlock_irqrestore(&i8253_lock, flags);
+
+	return 0;
+}
+
+/*
+ * On UP the PIT can serve all of the possible timer functions. On SMP systems
+ * it can be solely used for the global tick.
+ *
+ * The profiling and update capabilites are switched off once the local apic is
+ * registered. This mechanism replaces the previous #ifdef LOCAL_APIC -
+ * !using_apic_timer decisions in do_timer_interrupt_hook()
+ */
+struct clock_event_device pit_clockevent = {
+	.name		= "pit",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode	= init_pit_timer,
+	.set_next_event = pit_next_event,
+	.shift		= 32,
+	.irq		= 0,
+};
+
+/*
+ * Initialize the conversion factor and the min/max deltas of the clock event
+ * structure and register the clock event source with the framework.
+ */
+void __init setup_pit_timer(void)
+{
+	/*
+	 * Start pit with the boot cpu mask and make it global after the
+	 * IO_APIC has been initialized.
+	 */
+	pit_clockevent.cpumask = cpumask_of_cpu(0);
+	pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
+	pit_clockevent.max_delta_ns =
+		clockevent_delta2ns(0x7FFF, &pit_clockevent);
+	pit_clockevent.min_delta_ns =
+		clockevent_delta2ns(0xF, &pit_clockevent);
+	clockevents_register_device(&pit_clockevent);
+	global_clock_event = &pit_clockevent;
+}
+
+/*
  * Since the PIT overflows every tick, its not very useful
  * to just read by itself. So use jiffies to emulate a free
  * running counter:
@@ -46,7 +126,7 @@
 	static u32 old_jifs;
 
 	spin_lock_irqsave(&i8253_lock, flags);
-        /*
+	/*
 	 * Although our caller may have the read side of xtime_lock,
 	 * this is now a seqlock, and we are cheating in this routine
 	 * by having side effects on state that we cannot undo if
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index c8d4582..03abfdb 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -41,6 +41,7 @@
 static struct irq_chip i8259A_chip = {
 	.name		= "XT-PIC",
 	.mask		= disable_8259A_irq,
+	.disable	= disable_8259A_irq,
 	.unmask		= enable_8259A_irq,
 	.mask_ack	= mask_and_ack_8259A,
 };
@@ -410,12 +411,6 @@
 	intr_init_hook();
 
 	/*
-	 * Set the clock to HZ Hz, we already have a valid
-	 * vector now:
-	 */
-	setup_pit_timer();
-
-	/*
 	 * External FPU? Set up irq13 if so, for
 	 * original braindamaged IBM FERR coupling.
 	 */
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 5592fa6..6fec4da 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -126,7 +126,7 @@
  */
 static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
 {
-	volatile struct io_apic *io_apic = io_apic_base(apic);
+	volatile struct io_apic __iomem *io_apic = io_apic_base(apic);
 	if (sis_apic_bug)
 		writel(reg, &io_apic->index);
 	writel(value, &io_apic->data);
@@ -343,7 +343,7 @@
 			break;
 		entry = irq_2_pin + entry->next;
 	}
-	set_native_irq_info(irq, cpumask);
+	irq_desc[irq].affinity = cpumask;
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
@@ -482,8 +482,8 @@
 		package_index = CPU_TO_PACKAGEINDEX(i);
 		for (j = 0; j < NR_IRQS; j++) {
 			unsigned long value_now, delta;
-			/* Is this an active IRQ? */
-			if (!irq_desc[j].action)
+			/* Is this an active IRQ or balancing disabled ? */
+			if (!irq_desc[j].action || irq_balancing_disabled(j))
 				continue;
 			if ( package_index == i )
 				IRQ_DELTA(package_index,j) = 0;
@@ -1281,11 +1281,9 @@
 			trigger == IOAPIC_LEVEL)
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
 					 handle_fasteoi_irq, "fasteoi");
-	else {
-		irq_desc[irq].status |= IRQ_DELAYED_DISABLE;
+	else
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
 					 handle_edge_irq, "edge");
-	}
 	set_intr_gate(vector, interrupt[irq]);
 }
 
@@ -1356,7 +1354,7 @@
 		}
 		spin_lock_irqsave(&ioapic_lock, flags);
 		__ioapic_write_entry(apic, pin, entry);
-		set_native_irq_info(irq, TARGET_CPUS);
+		irq_desc[irq].affinity = TARGET_CPUS;
 		spin_unlock_irqrestore(&ioapic_lock, flags);
 	}
 	}
@@ -1588,7 +1586,7 @@
 	v = apic_read(APIC_LVR);
 	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
 	ver = GET_APIC_VERSION(v);
-	maxlvt = get_maxlvt();
+	maxlvt = lapic_get_maxlvt();
 
 	v = apic_read(APIC_TASKPRI);
 	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
@@ -1920,7 +1918,7 @@
 static void __init setup_ioapic_ids_from_mpc(void) { }
 #endif
 
-static int no_timer_check __initdata;
+int no_timer_check __initdata;
 
 static int __init notimercheck(char *s)
 {
@@ -2310,7 +2308,7 @@
 
 	disable_8259A_irq(0);
 	set_irq_chip_and_handler_name(0, &lapic_chip, handle_fasteoi_irq,
-				      "fasteio");
+				      "fasteoi");
 	apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
 	enable_8259A_irq(0);
 
@@ -2587,7 +2585,7 @@
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
 	write_msi_msg(irq, &msg);
-	set_native_irq_info(irq, mask);
+	irq_desc[irq].affinity = mask;
 }
 #endif /* CONFIG_SMP */
 
@@ -2671,7 +2669,7 @@
 	dest = cpu_mask_to_apicid(mask);
 
 	target_ht_irq(irq, dest);
-	set_native_irq_info(irq, mask);
+	irq_desc[irq].affinity = mask;
 }
 #endif
 
@@ -2877,7 +2875,7 @@
 
 	spin_lock_irqsave(&ioapic_lock, flags);
 	__ioapic_write_entry(ioapic, pin, entry);
-	set_native_irq_info(irq, TARGET_CPUS);
+	irq_desc[irq].affinity = TARGET_CPUS;
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	return 0;
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 3201d42..8db8d51 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -10,7 +10,6 @@
  * io_apic.c.)
  */
 
-#include <asm/uaccess.h>
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
@@ -19,19 +18,34 @@
 #include <linux/cpu.h>
 #include <linux/delay.h>
 
+#include <asm/apic.h>
+#include <asm/uaccess.h>
+
 DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp;
 EXPORT_PER_CPU_SYMBOL(irq_stat);
 
-#ifndef CONFIG_X86_LOCAL_APIC
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves.
  */
 void ack_bad_irq(unsigned int irq)
 {
-	printk("unexpected IRQ trap at vector %02x\n", irq);
-}
+	printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	/*
+	 * Currently unexpected vectors happen only on SMP and APIC.
+	 * We _must_ ack these because every local APIC has only N
+	 * irq slots per priority level, and a 'hanging, unacked' IRQ
+	 * holds up an irq slot - in excessive cases (when multiple
+	 * unexpected vectors occur) that might lock up the APIC
+	 * completely.
+	 * But only ack when the APIC is enabled -AK
+	 */
+	if (cpu_has_apic)
+		ack_APIC_irq();
 #endif
+}
 
 #ifdef CONFIG_4KSTACKS
 /*
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index af1d533..b545bc7 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -363,7 +363,7 @@
 			"	pushf\n"
 			/* skip cs, eip, orig_eax */
 			"	subl $12, %esp\n"
-			"	pushl %gs\n"
+			"	pushl %fs\n"
 			"	pushl %ds\n"
 			"	pushl %es\n"
 			"	pushl %eax\n"
@@ -387,7 +387,7 @@
 			"	popl %edi\n"
 			"	popl %ebp\n"
 			"	popl %eax\n"
-			/* skip eip, orig_eax, es, ds, gs */
+			/* skip eip, orig_eax, es, ds, fs */
 			"	addl $20, %esp\n"
 			"	popf\n"
 			"	ret\n");
@@ -408,7 +408,7 @@
 	spin_lock_irqsave(&kretprobe_lock, flags);
 	head = kretprobe_inst_table_head(current);
 	/* fixup registers */
-	regs->xcs = __KERNEL_CS;
+	regs->xcs = __KERNEL_CS | get_kernel_rpl();
 	regs->eip = trampoline_address;
 	regs->orig_eax = 0xffffffff;
 
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index c8fa137..b8f1663 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -384,7 +384,7 @@
 {
 	long cursor = 0;
 	int error = 0;
-	void *new_mc;
+	void *new_mc = NULL;
 	int cpu;
 	cpumask_t old;
 
@@ -451,7 +451,7 @@
 	return ret;
 }
 
-static struct file_operations microcode_fops = {
+static const struct file_operations microcode_fops = {
 	.owner		= THIS_MODULE,
 	.write		= microcode_write,
 	.open		= microcode_open,
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 4a472a1..bcaa6e9 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -68,7 +68,6 @@
 #ifdef CONFIG_SMP
 
 struct msr_command {
-	int cpu;
 	int err;
 	u32 reg;
 	u32 data[2];
@@ -78,16 +77,14 @@
 {
 	struct msr_command *cmd = (struct msr_command *)cmd_block;
 
-	if (cmd->cpu == smp_processor_id())
-		cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
+	cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
 }
 
 static void msr_smp_rdmsr(void *cmd_block)
 {
 	struct msr_command *cmd = (struct msr_command *)cmd_block;
 
-	if (cmd->cpu == smp_processor_id())
-		cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
+	cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
 }
 
 static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
@@ -99,12 +96,11 @@
 	if (cpu == smp_processor_id()) {
 		ret = wrmsr_eio(reg, eax, edx);
 	} else {
-		cmd.cpu = cpu;
 		cmd.reg = reg;
 		cmd.data[0] = eax;
 		cmd.data[1] = edx;
 
-		smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
+		smp_call_function_single(cpu, msr_smp_wrmsr, &cmd, 1, 1);
 		ret = cmd.err;
 	}
 	preempt_enable();
@@ -120,10 +116,9 @@
 	if (cpu == smp_processor_id()) {
 		ret = rdmsr_eio(reg, eax, edx);
 	} else {
-		cmd.cpu = cpu;
 		cmd.reg = reg;
 
-		smp_call_function(msr_smp_rdmsr, &cmd, 1, 1);
+		smp_call_function_single(cpu, msr_smp_rdmsr, &cmd, 1, 1);
 
 		*eax = cmd.data[0];
 		*edx = cmd.data[1];
@@ -230,7 +225,7 @@
 /*
  * File operations we support
  */
-static struct file_operations msr_fops = {
+static const struct file_operations msr_fops = {
 	.owner = THIS_MODULE,
 	.llseek = msr_seek,
 	.read = msr_read,
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 1a6f8bb..821df34 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -23,6 +23,7 @@
 #include <linux/dmi.h>
 #include <linux/kprobes.h>
 #include <linux/cpumask.h>
+#include <linux/kernel_stat.h>
 
 #include <asm/smp.h>
 #include <asm/nmi.h>
@@ -185,7 +186,8 @@
 {
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
-		return ((boot_cpu_data.x86 == 15) || (boot_cpu_data.x86 == 6));
+		return ((boot_cpu_data.x86 == 15) || (boot_cpu_data.x86 == 6)
+			|| (boot_cpu_data.x86 == 16));
 	case X86_VENDOR_INTEL:
 		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
 			return 1;
@@ -216,6 +218,28 @@
 }
 #endif
 
+static unsigned int adjust_for_32bit_ctr(unsigned int hz)
+{
+	u64 counter_val;
+	unsigned int retval = hz;
+
+	/*
+	 * On Intel CPUs with P6/ARCH_PERFMON only 32 bits in the counter
+	 * are writable, with higher bits sign extending from bit 31.
+	 * So, we can only program the counter with 31 bit values and
+	 * 32nd bit should be 1, for 33.. to be 1.
+	 * Find the appropriate nmi_hz
+	 */
+	counter_val = (u64)cpu_khz * 1000;
+	do_div(counter_val, retval);
+ 	if (counter_val > 0x7fffffffULL) {
+		u64 count = (u64)cpu_khz * 1000;
+		do_div(count, 0x7fffffffUL);
+		retval = count + 1;
+	}
+	return retval;
+}
+
 static int __init check_nmi_watchdog(void)
 {
 	unsigned int *prev_nmi_count;
@@ -281,18 +305,10 @@
 		struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
 		nmi_hz = 1;
-		/*
-		 * On Intel CPUs with ARCH_PERFMON only 32 bits in the counter
-		 * are writable, with higher bits sign extending from bit 31.
-		 * So, we can only program the counter with 31 bit values and
-		 * 32nd bit should be 1, for 33.. to be 1.
-		 * Find the appropriate nmi_hz
-		 */
-	 	if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0 &&
-			((u64)cpu_khz * 1000) > 0x7fffffffULL) {
-			u64 count = (u64)cpu_khz * 1000;
-			do_div(count, 0x7fffffffUL);
-			nmi_hz = count + 1;
+
+		if (wd->perfctr_msr == MSR_P6_PERFCTR0 ||
+		    wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
+			nmi_hz = adjust_for_32bit_ctr(nmi_hz);
 		}
 	}
 
@@ -369,6 +385,34 @@
 	}
 }
 
+static void __acpi_nmi_disable(void *__unused)
+{
+	apic_write_around(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
+}
+
+/*
+ * Disable timer based NMIs on all CPUs:
+ */
+void acpi_nmi_disable(void)
+{
+	if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
+		on_each_cpu(__acpi_nmi_disable, NULL, 0, 1);
+}
+
+static void __acpi_nmi_enable(void *__unused)
+{
+	apic_write_around(APIC_LVT0, APIC_DM_NMI);
+}
+
+/*
+ * Enable timer based NMIs on all CPUs:
+ */
+void acpi_nmi_enable(void)
+{
+	if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
+		on_each_cpu(__acpi_nmi_enable, NULL, 0, 1);
+}
+
 #ifdef CONFIG_PM
 
 static int nmi_pm_active; /* nmi_active before suspend */
@@ -442,6 +486,17 @@
 	wrmsrl(perfctr_msr, 0 - count);
 }
 
+static void write_watchdog_counter32(unsigned int perfctr_msr,
+		const char *descr)
+{
+	u64 count = (u64)cpu_khz * 1000;
+
+	do_div(count, nmi_hz);
+	if(descr)
+		Dprintk("setting %s to -0x%08Lx\n", descr, count);
+	wrmsr(perfctr_msr, (u32)(-count), 0);
+}
+
 /* Note that these events don't tick when the CPU idles. This means
    the frequency varies with CPU load. */
 
@@ -531,7 +586,8 @@
 
 	/* setup the timer */
 	wrmsr(evntsel_msr, evntsel, 0);
-	write_watchdog_counter(perfctr_msr, "P6_PERFCTR0");
+	nmi_hz = adjust_for_32bit_ctr(nmi_hz);
+	write_watchdog_counter32(perfctr_msr, "P6_PERFCTR0");
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	evntsel |= P6_EVNTSEL0_ENABLE;
 	wrmsr(evntsel_msr, evntsel, 0);
@@ -704,7 +760,8 @@
 
 	/* setup the timer */
 	wrmsr(evntsel_msr, evntsel, 0);
-	write_watchdog_counter(perfctr_msr, "INTEL_ARCH_PERFCTR0");
+	nmi_hz = adjust_for_32bit_ctr(nmi_hz);
+	write_watchdog_counter32(perfctr_msr, "INTEL_ARCH_PERFCTR0");
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
 	wrmsr(evntsel_msr, evntsel, 0);
@@ -762,7 +819,8 @@
 	if (nmi_watchdog == NMI_LOCAL_APIC) {
 		switch (boot_cpu_data.x86_vendor) {
 		case X86_VENDOR_AMD:
-			if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15)
+			if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 &&
+				boot_cpu_data.x86 != 16)
 				return;
 			if (!setup_k7_watchdog())
 				return;
@@ -916,9 +974,13 @@
 		cpu_clear(cpu, backtrace_mask);
 	}
 
-	sum = per_cpu(irq_stat, cpu).apic_timer_irqs;
+	/*
+	 * Take the local apic timer and PIT/HPET into account. We don't
+	 * know which one is active, when we have highres/dyntick on
+	 */
+	sum = per_cpu(irq_stat, cpu).apic_timer_irqs + kstat_irqs(0);
 
-	/* if the apic timer isn't firing, this cpu isn't doing much */
+	/* if the none of the timers isn't firing, this cpu isn't doing much */
 	if (!touched && last_irq_sums[cpu] == sum) {
 		/*
 		 * Ayiee, looks like this CPU is stuck ...
@@ -956,6 +1018,8 @@
 				dummy &= ~P4_CCCR_OVF;
 	 			wrmsrl(wd->cccr_msr, dummy);
 	 			apic_write(APIC_LVTPC, APIC_DM_NMI);
+				/* start the cycle over again */
+				write_watchdog_counter(wd->perfctr_msr, NULL);
 	 		}
 			else if (wd->perfctr_msr == MSR_P6_PERFCTR0 ||
 				 wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
@@ -964,9 +1028,12 @@
 				 * other P6 variant.
 				 * ArchPerfom/Core Duo also needs this */
 				apic_write(APIC_LVTPC, APIC_DM_NMI);
+				/* P6/ARCH_PERFMON has 32 bit counter write */
+				write_watchdog_counter32(wd->perfctr_msr, NULL);
+			} else {
+				/* start the cycle over again */
+				write_watchdog_counter(wd->perfctr_msr, NULL);
 			}
-			/* start the cycle over again */
-			write_watchdog_counter(wd->perfctr_msr, NULL);
 			rc = 1;
 		} else if (nmi_watchdog == NMI_IO_APIC) {
 			/* don't know how to accurately check for this.
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c
index e55fd05..c156ecf 100644
--- a/arch/i386/kernel/paravirt.c
+++ b/arch/i386/kernel/paravirt.c
@@ -92,7 +92,7 @@
 	return insn_len;
 }
 
-static fastcall unsigned long native_get_debugreg(int regno)
+static unsigned long native_get_debugreg(int regno)
 {
 	unsigned long val = 0; 	/* Damn you, gcc! */
 
@@ -115,7 +115,7 @@
 	return val;
 }
 
-static fastcall void native_set_debugreg(int regno, unsigned long value)
+static void native_set_debugreg(int regno, unsigned long value)
 {
 	switch (regno) {
 	case 0:
@@ -146,55 +146,55 @@
 	paravirt_ops.init_IRQ();
 }
 
-static fastcall void native_clts(void)
+static void native_clts(void)
 {
 	asm volatile ("clts");
 }
 
-static fastcall unsigned long native_read_cr0(void)
+static unsigned long native_read_cr0(void)
 {
 	unsigned long val;
 	asm volatile("movl %%cr0,%0\n\t" :"=r" (val));
 	return val;
 }
 
-static fastcall void native_write_cr0(unsigned long val)
+static void native_write_cr0(unsigned long val)
 {
 	asm volatile("movl %0,%%cr0": :"r" (val));
 }
 
-static fastcall unsigned long native_read_cr2(void)
+static unsigned long native_read_cr2(void)
 {
 	unsigned long val;
 	asm volatile("movl %%cr2,%0\n\t" :"=r" (val));
 	return val;
 }
 
-static fastcall void native_write_cr2(unsigned long val)
+static void native_write_cr2(unsigned long val)
 {
 	asm volatile("movl %0,%%cr2": :"r" (val));
 }
 
-static fastcall unsigned long native_read_cr3(void)
+static unsigned long native_read_cr3(void)
 {
 	unsigned long val;
 	asm volatile("movl %%cr3,%0\n\t" :"=r" (val));
 	return val;
 }
 
-static fastcall void native_write_cr3(unsigned long val)
+static void native_write_cr3(unsigned long val)
 {
 	asm volatile("movl %0,%%cr3": :"r" (val));
 }
 
-static fastcall unsigned long native_read_cr4(void)
+static unsigned long native_read_cr4(void)
 {
 	unsigned long val;
 	asm volatile("movl %%cr4,%0\n\t" :"=r" (val));
 	return val;
 }
 
-static fastcall unsigned long native_read_cr4_safe(void)
+static unsigned long native_read_cr4_safe(void)
 {
 	unsigned long val;
 	/* This could fault if %cr4 does not exist */
@@ -207,51 +207,51 @@
 	return val;
 }
 
-static fastcall void native_write_cr4(unsigned long val)
+static void native_write_cr4(unsigned long val)
 {
 	asm volatile("movl %0,%%cr4": :"r" (val));
 }
 
-static fastcall unsigned long native_save_fl(void)
+static unsigned long native_save_fl(void)
 {
 	unsigned long f;
 	asm volatile("pushfl ; popl %0":"=g" (f): /* no input */);
 	return f;
 }
 
-static fastcall void native_restore_fl(unsigned long f)
+static void native_restore_fl(unsigned long f)
 {
 	asm volatile("pushl %0 ; popfl": /* no output */
 			     :"g" (f)
 			     :"memory", "cc");
 }
 
-static fastcall void native_irq_disable(void)
+static void native_irq_disable(void)
 {
 	asm volatile("cli": : :"memory");
 }
 
-static fastcall void native_irq_enable(void)
+static void native_irq_enable(void)
 {
 	asm volatile("sti": : :"memory");
 }
 
-static fastcall void native_safe_halt(void)
+static void native_safe_halt(void)
 {
 	asm volatile("sti; hlt": : :"memory");
 }
 
-static fastcall void native_halt(void)
+static void native_halt(void)
 {
 	asm volatile("hlt": : :"memory");
 }
 
-static fastcall void native_wbinvd(void)
+static void native_wbinvd(void)
 {
 	asm volatile("wbinvd": : :"memory");
 }
 
-static fastcall unsigned long long native_read_msr(unsigned int msr, int *err)
+static unsigned long long native_read_msr(unsigned int msr, int *err)
 {
 	unsigned long long val;
 
@@ -270,7 +270,7 @@
 	return val;
 }
 
-static fastcall int native_write_msr(unsigned int msr, unsigned long long val)
+static int native_write_msr(unsigned int msr, unsigned long long val)
 {
 	int err;
 	asm volatile("2: wrmsr ; xorl %0,%0\n"
@@ -288,53 +288,53 @@
 	return err;
 }
 
-static fastcall unsigned long long native_read_tsc(void)
+static unsigned long long native_read_tsc(void)
 {
 	unsigned long long val;
 	asm volatile("rdtsc" : "=A" (val));
 	return val;
 }
 
-static fastcall unsigned long long native_read_pmc(void)
+static unsigned long long native_read_pmc(void)
 {
 	unsigned long long val;
 	asm volatile("rdpmc" : "=A" (val));
 	return val;
 }
 
-static fastcall void native_load_tr_desc(void)
+static void native_load_tr_desc(void)
 {
 	asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
 }
 
-static fastcall void native_load_gdt(const struct Xgt_desc_struct *dtr)
+static void native_load_gdt(const struct Xgt_desc_struct *dtr)
 {
 	asm volatile("lgdt %0"::"m" (*dtr));
 }
 
-static fastcall void native_load_idt(const struct Xgt_desc_struct *dtr)
+static void native_load_idt(const struct Xgt_desc_struct *dtr)
 {
 	asm volatile("lidt %0"::"m" (*dtr));
 }
 
-static fastcall void native_store_gdt(struct Xgt_desc_struct *dtr)
+static void native_store_gdt(struct Xgt_desc_struct *dtr)
 {
 	asm ("sgdt %0":"=m" (*dtr));
 }
 
-static fastcall void native_store_idt(struct Xgt_desc_struct *dtr)
+static void native_store_idt(struct Xgt_desc_struct *dtr)
 {
 	asm ("sidt %0":"=m" (*dtr));
 }
 
-static fastcall unsigned long native_store_tr(void)
+static unsigned long native_store_tr(void)
 {
 	unsigned long tr;
 	asm ("str %0":"=r" (tr));
 	return tr;
 }
 
-static fastcall void native_load_tls(struct thread_struct *t, unsigned int cpu)
+static void native_load_tls(struct thread_struct *t, unsigned int cpu)
 {
 #define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
 	C(0); C(1); C(2);
@@ -348,22 +348,22 @@
 	lp[1] = entry_high;
 }
 
-static fastcall void native_write_ldt_entry(void *dt, int entrynum, u32 low, u32 high)
+static void native_write_ldt_entry(void *dt, int entrynum, u32 low, u32 high)
 {
 	native_write_dt_entry(dt, entrynum, low, high);
 }
 
-static fastcall void native_write_gdt_entry(void *dt, int entrynum, u32 low, u32 high)
+static void native_write_gdt_entry(void *dt, int entrynum, u32 low, u32 high)
 {
 	native_write_dt_entry(dt, entrynum, low, high);
 }
 
-static fastcall void native_write_idt_entry(void *dt, int entrynum, u32 low, u32 high)
+static void native_write_idt_entry(void *dt, int entrynum, u32 low, u32 high)
 {
 	native_write_dt_entry(dt, entrynum, low, high);
 }
 
-static fastcall void native_load_esp0(struct tss_struct *tss,
+static void native_load_esp0(struct tss_struct *tss,
 				      struct thread_struct *thread)
 {
 	tss->esp0 = thread->esp0;
@@ -375,12 +375,12 @@
 	}
 }
 
-static fastcall void native_io_delay(void)
+static void native_io_delay(void)
 {
 	asm volatile("outb %al,$0x80");
 }
 
-static fastcall void native_flush_tlb(void)
+static void native_flush_tlb(void)
 {
 	__native_flush_tlb();
 }
@@ -389,49 +389,49 @@
  * Global pages have to be flushed a bit differently. Not a real
  * performance problem because this does not happen often.
  */
-static fastcall void native_flush_tlb_global(void)
+static void native_flush_tlb_global(void)
 {
 	__native_flush_tlb_global();
 }
 
-static fastcall void native_flush_tlb_single(u32 addr)
+static void native_flush_tlb_single(u32 addr)
 {
 	__native_flush_tlb_single(addr);
 }
 
 #ifndef CONFIG_X86_PAE
-static fastcall void native_set_pte(pte_t *ptep, pte_t pteval)
+static void native_set_pte(pte_t *ptep, pte_t pteval)
 {
 	*ptep = pteval;
 }
 
-static fastcall void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval)
+static void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval)
 {
 	*ptep = pteval;
 }
 
-static fastcall void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
+static void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
 {
 	*pmdp = pmdval;
 }
 
 #else /* CONFIG_X86_PAE */
 
-static fastcall void native_set_pte(pte_t *ptep, pte_t pte)
+static void native_set_pte(pte_t *ptep, pte_t pte)
 {
 	ptep->pte_high = pte.pte_high;
 	smp_wmb();
 	ptep->pte_low = pte.pte_low;
 }
 
-static fastcall void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte)
+static void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte)
 {
 	ptep->pte_high = pte.pte_high;
 	smp_wmb();
 	ptep->pte_low = pte.pte_low;
 }
 
-static fastcall void native_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+static void native_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
 {
 	ptep->pte_low = 0;
 	smp_wmb();
@@ -440,29 +440,29 @@
 	ptep->pte_low = pte.pte_low;
 }
 
-static fastcall void native_set_pte_atomic(pte_t *ptep, pte_t pteval)
+static void native_set_pte_atomic(pte_t *ptep, pte_t pteval)
 {
 	set_64bit((unsigned long long *)ptep,pte_val(pteval));
 }
 
-static fastcall void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
+static void native_set_pmd(pmd_t *pmdp, pmd_t pmdval)
 {
 	set_64bit((unsigned long long *)pmdp,pmd_val(pmdval));
 }
 
-static fastcall void native_set_pud(pud_t *pudp, pud_t pudval)
+static void native_set_pud(pud_t *pudp, pud_t pudval)
 {
 	*pudp = pudval;
 }
 
-static fastcall void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+static void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	ptep->pte_low = 0;
 	smp_wmb();
 	ptep->pte_high = 0;
 }
 
-static fastcall void native_pmd_clear(pmd_t *pmd)
+static void native_pmd_clear(pmd_t *pmd)
 {
 	u32 *tmp = (u32 *)pmd;
 	*tmp = 0;
@@ -472,8 +472,8 @@
 #endif /* CONFIG_X86_PAE */
 
 /* These are in entry.S */
-extern fastcall void native_iret(void);
-extern fastcall void native_irq_enable_sysexit(void);
+extern void native_iret(void);
+extern void native_irq_enable_sysexit(void);
 
 static int __init print_banner(void)
 {
@@ -482,9 +482,6 @@
 }
 core_initcall(print_banner);
 
-/* We simply declare start_kernel to be the paravirt probe of last resort. */
-paravirt_probe(start_kernel);
-
 struct paravirt_ops paravirt_ops = {
 	.name = "bare hardware",
 	.paravirt_enabled = 0,
@@ -544,12 +541,21 @@
 	.apic_write = native_apic_write,
 	.apic_write_atomic = native_apic_write_atomic,
 	.apic_read = native_apic_read,
+	.setup_boot_clock = setup_boot_APIC_clock,
+	.setup_secondary_clock = setup_secondary_APIC_clock,
 #endif
+	.set_lazy_mode = (void *)native_nop,
 
 	.flush_tlb_user = native_flush_tlb,
 	.flush_tlb_kernel = native_flush_tlb_global,
 	.flush_tlb_single = native_flush_tlb_single,
 
+	.alloc_pt = (void *)native_nop,
+	.alloc_pd = (void *)native_nop,
+	.alloc_pd_clone = (void *)native_nop,
+	.release_pt = (void *)native_nop,
+	.release_pd = (void *)native_nop,
+
 	.set_pte = native_set_pte,
 	.set_pte_at = native_set_pte_at,
 	.set_pmd = native_set_pmd,
@@ -565,6 +571,8 @@
 
 	.irq_enable_sysexit = native_irq_enable_sysexit,
 	.iret = native_iret,
+
+	.startup_ipi_hook = (void *)native_nop,
 };
 
 /*
diff --git a/arch/i386/kernel/pcspeaker.c b/arch/i386/kernel/pcspeaker.c
new file mode 100644
index 0000000..bc1f2d3
--- /dev/null
+++ b/arch/i386/kernel/pcspeaker.c
@@ -0,0 +1,20 @@
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+static __init int add_pcspkr(void)
+{
+	struct platform_device *pd;
+	int ret;
+
+	pd = platform_device_alloc("pcspkr", -1);
+	if (!pd)
+		return -ENOMEM;
+
+	ret = platform_device_add(pd);
+	if (ret)
+		platform_device_put(pd);
+
+	return ret;
+}
+device_initcall(add_pcspkr);
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index c641056..393a67d 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -38,6 +38,7 @@
 #include <linux/ptrace.h>
 #include <linux/random.h>
 #include <linux/personality.h>
+#include <linux/tick.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -173,6 +174,7 @@
 
 	/* endless idle loop with no priority at all */
 	while (1) {
+		tick_nohz_stop_sched_tick();
 		while (!need_resched()) {
 			void (*idle)(void);
 
@@ -191,6 +193,7 @@
 			__get_cpu_var(irq_stat).idle_timestamp = jiffies;
 			idle();
 		}
+		tick_nohz_restart_sched_tick();
 		preempt_enable_no_resched();
 		schedule();
 		preempt_disable();
@@ -308,8 +311,8 @@
 		regs->eax,regs->ebx,regs->ecx,regs->edx);
 	printk("ESI: %08lx EDI: %08lx EBP: %08lx",
 		regs->esi, regs->edi, regs->ebp);
-	printk(" DS: %04x ES: %04x GS: %04x\n",
-	       0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xgs);
+	printk(" DS: %04x ES: %04x FS: %04x\n",
+	       0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xfs);
 
 	cr0 = read_cr0();
 	cr2 = read_cr2();
@@ -340,7 +343,7 @@
 
 	regs.xds = __USER_DS;
 	regs.xes = __USER_DS;
-	regs.xgs = __KERNEL_PDA;
+	regs.xfs = __KERNEL_PDA;
 	regs.orig_eax = -1;
 	regs.eip = (unsigned long) kernel_thread_helper;
 	regs.xcs = __KERNEL_CS | get_kernel_rpl();
@@ -425,7 +428,7 @@
 
 	p->thread.eip = (unsigned long) ret_from_fork;
 
-	savesegment(fs,p->thread.fs);
+	savesegment(gs,p->thread.gs);
 
 	tsk = current;
 	if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
@@ -501,8 +504,8 @@
 	dump->regs.eax = regs->eax;
 	dump->regs.ds = regs->xds;
 	dump->regs.es = regs->xes;
-	savesegment(fs,dump->regs.fs);
-	dump->regs.gs = regs->xgs;
+	dump->regs.fs = regs->xfs;
+	savesegment(gs,dump->regs.gs);
 	dump->regs.orig_eax = regs->orig_eax;
 	dump->regs.eip = regs->eip;
 	dump->regs.cs = regs->xcs;
@@ -653,7 +656,7 @@
 	load_esp0(tss, next);
 
 	/*
-	 * Save away %fs. No need to save %gs, as it was saved on the
+	 * Save away %gs. No need to save %fs, as it was saved on the
 	 * stack on entry.  No need to save %es and %ds, as those are
 	 * always kernel segments while inside the kernel.  Doing this
 	 * before setting the new TLS descriptors avoids the situation
@@ -662,7 +665,7 @@
 	 * used %fs or %gs (it does not today), or if the kernel is
 	 * running inside of a hypervisor layer.
 	 */
-	savesegment(fs, prev->fs);
+	savesegment(gs, prev->gs);
 
 	/*
 	 * Load the per-thread Thread-Local Storage descriptor.
@@ -670,14 +673,13 @@
 	load_TLS(next, cpu);
 
 	/*
-	 * Restore %fs if needed.
-	 *
-	 * Glibc normally makes %fs be zero.
+	 * Restore IOPL if needed.  In normal use, the flags restore
+	 * in the switch assembly will handle this.  But if the kernel
+	 * is running virtualized at a non-zero CPL, the popf will
+	 * not restore flags, so it must be done in a separate step.
 	 */
-	if (unlikely(prev->fs | next->fs))
-		loadsegment(fs, next->fs);
-
-	write_pda(pcurrent, next_p);
+	if (get_kernel_rpl() && unlikely(prev->iopl != next->iopl))
+		set_iopl_mask(next->iopl);
 
 	/*
 	 * Now maybe handle debug registers and/or IO bitmaps
@@ -688,6 +690,15 @@
 
 	disable_tsc(prev_p, next_p);
 
+	/*
+	 * Leave lazy mode, flushing any hypercalls made here.
+	 * This must be done before restoring TLS segments so
+	 * the GDT and LDT are properly updated, and must be
+	 * done before math_state_restore, so the TS bit is up
+	 * to date.
+	 */
+	arch_leave_lazy_cpu_mode();
+
 	/* If the task has used fpu the last 5 timeslices, just do a full
 	 * restore of the math state immediately to avoid the trap; the
 	 * chances of needing FPU soon are obviously high now
@@ -695,6 +706,14 @@
 	if (next_p->fpu_counter > 5)
 		math_state_restore();
 
+	/*
+	 * Restore %gs if needed (which is common)
+	 */
+	if (prev->gs | next->gs)
+		loadsegment(gs, next->gs);
+
+	write_pda(pcurrent, next_p);
+
 	return prev_p;
 }
 
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index af8aabe..4a8f8a2 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -89,14 +89,14 @@
 	unsigned long regno, unsigned long value)
 {
 	switch (regno >> 2) {
-		case FS:
+		case GS:
 			if (value && (value & 3) != 3)
 				return -EIO;
-			child->thread.fs = value;
+			child->thread.gs = value;
 			return 0;
 		case DS:
 		case ES:
-		case GS:
+		case FS:
 			if (value && (value & 3) != 3)
 				return -EIO;
 			value &= 0xffff;
@@ -112,7 +112,7 @@
 			value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
 			break;
 	}
-	if (regno > ES*4)
+	if (regno > FS*4)
 		regno -= 1*4;
 	put_stack_long(child, regno, value);
 	return 0;
@@ -124,18 +124,18 @@
 	unsigned long retval = ~0UL;
 
 	switch (regno >> 2) {
-		case FS:
-			retval = child->thread.fs;
+		case GS:
+			retval = child->thread.gs;
 			break;
 		case DS:
 		case ES:
-		case GS:
+		case FS:
 		case SS:
 		case CS:
 			retval = 0xffff;
 			/* fall through */
 		default:
-			if (regno > ES*4)
+			if (regno > FS*4)
 				regno -= 1*4;
 			retval &= get_stack_long(child, regno);
 	}
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 4b31ad7..122623d 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -33,7 +33,6 @@
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
-#include <linux/platform_device.h>
 #include <linux/console.h>
 #include <linux/mca.h>
 #include <linux/root_dev.h>
@@ -60,6 +59,7 @@
 #include <asm/io_apic.h>
 #include <asm/ist.h>
 #include <asm/io.h>
+#include <asm/vmi.h>
 #include <setup_arch.h>
 #include <bios_ebda.h>
 
@@ -132,7 +132,7 @@
 #define RAMDISK_PROMPT_FLAG		0x8000
 #define RAMDISK_LOAD_FLAG		0x4000	
 
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 unsigned char __initdata boot_params[PARAM_SIZE];
 
@@ -576,11 +576,19 @@
 		print_memory_map("user");
 	}
 
-	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 
 	max_low_pfn = setup_memory();
 
+#ifdef CONFIG_VMI
+	/*
+	 * Must be after max_low_pfn is determined, and before kernel
+	 * pagetables are setup.
+	 */
+	vmi_init();
+#endif
+
 	/*
 	 * NOTE: before this point _nobody_ is allowed to allocate
 	 * any memory using the bootmem allocator.  Although the
@@ -651,28 +659,3 @@
 #endif
 	tsc_init();
 }
-
-static __init int add_pcspkr(void)
-{
-	struct platform_device *pd;
-	int ret;
-
-	pd = platform_device_alloc("pcspkr", -1);
-	if (!pd)
-		return -ENOMEM;
-
-	ret = platform_device_add(pd);
-	if (ret)
-		platform_device_put(pd);
-
-	return ret;
-}
-device_initcall(add_pcspkr);
-
-/*
- * Local Variables:
- * mode:c
- * c-file-style:"k&r"
- * c-basic-offset:8
- * End:
- */
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 65d7620..4f99e87 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -21,6 +21,7 @@
 #include <linux/suspend.h>
 #include <linux/ptrace.h>
 #include <linux/elf.h>
+#include <linux/binfmts.h>
 #include <asm/processor.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -128,8 +129,8 @@
 			 X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \
 			 X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF)
 
-	COPY_SEG(gs);
-	GET_SEG(fs);
+	GET_SEG(gs);
+	COPY_SEG(fs);
 	COPY_SEG(es);
 	COPY_SEG(ds);
 	COPY(edi);
@@ -244,9 +245,9 @@
 {
 	int tmp, err = 0;
 
-	err |= __put_user(regs->xgs, (unsigned int __user *)&sc->gs);
-	savesegment(fs, tmp);
-	err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
+	err |= __put_user(regs->xfs, (unsigned int __user *)&sc->fs);
+	savesegment(gs, tmp);
+	err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
 
 	err |= __put_user(regs->xes, (unsigned int __user *)&sc->es);
 	err |= __put_user(regs->xds, (unsigned int __user *)&sc->ds);
@@ -349,7 +350,10 @@
 			goto give_sigsegv;
 	}
 
-	restorer = (void *)VDSO_SYM(&__kernel_sigreturn);
+	if (current->binfmt->hasvdso)
+		restorer = (void *)VDSO_SYM(&__kernel_sigreturn);
+	else
+		restorer = (void *)&frame->retcode;
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 5285aff..0e89778 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -374,8 +374,7 @@
 	/*
 	 * i'm not happy about this global shared spinlock in the
 	 * MM hot path, but we'll see how contended it is.
-	 * Temporarily this turns IRQs off, so that lockups are
-	 * detected by the NMI watchdog.
+	 * AK: x86-64 has a faster method that could be ported.
 	 */
 	spin_lock(&tlbstate_lock);
 	
@@ -400,7 +399,7 @@
 
 	while (!cpus_empty(flush_cpumask))
 		/* nothing. lockup detection does not belong here */
-		mb();
+		cpu_relax();
 
 	flush_mm = NULL;
 	flush_va = 0;
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 8c6c8c5..48bfcaa1 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -63,6 +63,7 @@
 #include <mach_apic.h>
 #include <mach_wakecpu.h>
 #include <smpboot_hooks.h>
+#include <asm/vmi.h>
 
 /* Set if we find a B stepping CPU */
 static int __devinitdata smp_b_stepping;
@@ -93,12 +94,6 @@
 EXPORT_SYMBOL(cpu_possible_map);
 static cpumask_t smp_commenced_mask;
 
-/* TSC's upper 32 bits can't be written in eariler CPU (before prescott), there
- * is no way to resync one AP against BP. TBD: for prescott and above, we
- * should use IA64's algorithm
- */
-static int __devinitdata tsc_sync_disabled;
-
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
 EXPORT_SYMBOL(cpu_data);
@@ -215,151 +210,6 @@
 	;
 }
 
-/*
- * TSC synchronization.
- *
- * We first check whether all CPUs have their TSC's synchronized,
- * then we print a warning if not, and always resync.
- */
-
-static struct {
-	atomic_t start_flag;
-	atomic_t count_start;
-	atomic_t count_stop;
-	unsigned long long values[NR_CPUS];
-} tsc __cpuinitdata = {
-	.start_flag = ATOMIC_INIT(0),
-	.count_start = ATOMIC_INIT(0),
-	.count_stop = ATOMIC_INIT(0),
-};
-
-#define NR_LOOPS 5
-
-static void __init synchronize_tsc_bp(void)
-{
-	int i;
-	unsigned long long t0;
-	unsigned long long sum, avg;
-	long long delta;
-	unsigned int one_usec;
-	int buggy = 0;
-
-	printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus());
-
-	/* convert from kcyc/sec to cyc/usec */
-	one_usec = cpu_khz / 1000;
-
-	atomic_set(&tsc.start_flag, 1);
-	wmb();
-
-	/*
-	 * We loop a few times to get a primed instruction cache,
-	 * then the last pass is more or less synchronized and
-	 * the BP and APs set their cycle counters to zero all at
-	 * once. This reduces the chance of having random offsets
-	 * between the processors, and guarantees that the maximum
-	 * delay between the cycle counters is never bigger than
-	 * the latency of information-passing (cachelines) between
-	 * two CPUs.
-	 */
-	for (i = 0; i < NR_LOOPS; i++) {
-		/*
-		 * all APs synchronize but they loop on '== num_cpus'
-		 */
-		while (atomic_read(&tsc.count_start) != num_booting_cpus()-1)
-			cpu_relax();
-		atomic_set(&tsc.count_stop, 0);
-		wmb();
-		/*
-		 * this lets the APs save their current TSC:
-		 */
-		atomic_inc(&tsc.count_start);
-
-		rdtscll(tsc.values[smp_processor_id()]);
-		/*
-		 * We clear the TSC in the last loop:
-		 */
-		if (i == NR_LOOPS-1)
-			write_tsc(0, 0);
-
-		/*
-		 * Wait for all APs to leave the synchronization point:
-		 */
-		while (atomic_read(&tsc.count_stop) != num_booting_cpus()-1)
-			cpu_relax();
-		atomic_set(&tsc.count_start, 0);
-		wmb();
-		atomic_inc(&tsc.count_stop);
-	}
-
-	sum = 0;
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_isset(i, cpu_callout_map)) {
-			t0 = tsc.values[i];
-			sum += t0;
-		}
-	}
-	avg = sum;
-	do_div(avg, num_booting_cpus());
-
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_isset(i, cpu_callout_map))
-			continue;
-		delta = tsc.values[i] - avg;
-		if (delta < 0)
-			delta = -delta;
-		/*
-		 * We report bigger than 2 microseconds clock differences.
-		 */
-		if (delta > 2*one_usec) {
-			long long realdelta;
-
-			if (!buggy) {
-				buggy = 1;
-				printk("\n");
-			}
-			realdelta = delta;
-			do_div(realdelta, one_usec);
-			if (tsc.values[i] < avg)
-				realdelta = -realdelta;
-
-			if (realdelta)
-				printk(KERN_INFO "CPU#%d had %Ld usecs TSC "
-					"skew, fixed it up.\n", i, realdelta);
-		}
-	}
-	if (!buggy)
-		printk("passed.\n");
-}
-
-static void __cpuinit synchronize_tsc_ap(void)
-{
-	int i;
-
-	/*
-	 * Not every cpu is online at the time
-	 * this gets called, so we first wait for the BP to
-	 * finish SMP initialization:
-	 */
-	while (!atomic_read(&tsc.start_flag))
-		cpu_relax();
-
-	for (i = 0; i < NR_LOOPS; i++) {
-		atomic_inc(&tsc.count_start);
-		while (atomic_read(&tsc.count_start) != num_booting_cpus())
-			cpu_relax();
-
-		rdtscll(tsc.values[smp_processor_id()]);
-		if (i == NR_LOOPS-1)
-			write_tsc(0, 0);
-
-		atomic_inc(&tsc.count_stop);
-		while (atomic_read(&tsc.count_stop) != num_booting_cpus())
-			cpu_relax();
-	}
-}
-#undef NR_LOOPS
-
 extern void calibrate_delay(void);
 
 static atomic_t init_deasserted;
@@ -437,20 +287,12 @@
 	/*
 	 * Save our processor parameters
 	 */
- 	smp_store_cpu_info(cpuid);
-
-	disable_APIC_timer();
+	smp_store_cpu_info(cpuid);
 
 	/*
 	 * Allow the master to continue.
 	 */
 	cpu_set(cpuid, cpu_callin_map);
-
-	/*
-	 *      Synchronize the TSC with the BP
-	 */
-	if (cpu_has_tsc && cpu_khz && !tsc_sync_disabled)
-		synchronize_tsc_ap();
 }
 
 static int cpucount;
@@ -545,18 +387,25 @@
 	 * booting is too fragile that we want to limit the
 	 * things done here to the most necessary things.
 	 */
+#ifdef CONFIG_VMI
+	vmi_bringup();
+#endif
 	secondary_cpu_init();
 	preempt_disable();
 	smp_callin();
 	while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
 		rep_nop();
-	setup_secondary_APIC_clock();
+	/*
+	 * Check TSC synchronization with the BP:
+	 */
+	check_tsc_sync_target();
+
+	setup_secondary_clock();
 	if (nmi_watchdog == NMI_IO_APIC) {
 		disable_8259A_irq(0);
 		enable_NMI_through_LVT0(NULL);
 		enable_8259A_irq(0);
 	}
-	enable_APIC_timer();
 	/*
 	 * low-memory mappings have been cleared, flush them from
 	 * the local TLBs too.
@@ -619,7 +468,6 @@
 	unsigned short ss;
 } stack_start;
 extern struct i386_pda *start_pda;
-extern struct Xgt_desc_struct cpu_gdt_descr;
 
 #ifdef CONFIG_NUMA
 
@@ -749,7 +597,7 @@
 	/*
 	 * Due to the Pentium erratum 3AP.
 	 */
-	maxlvt = get_maxlvt();
+	maxlvt = lapic_get_maxlvt();
 	if (maxlvt > 3) {
 		apic_read_around(APIC_SPIV);
 		apic_write(APIC_ESR, 0);
@@ -835,11 +683,18 @@
 		num_starts = 0;
 
 	/*
+	 * Paravirt / VMI wants a startup IPI hook here to set up the
+	 * target processor state.
+	 */
+	startup_ipi_hook(phys_apicid, (unsigned long) start_secondary,
+		         (unsigned long) stack_start.esp);
+
+	/*
 	 * Run STARTUP IPI loop.
 	 */
 	Dprintk("#startup loops: %d.\n", num_starts);
 
-	maxlvt = get_maxlvt();
+	maxlvt = lapic_get_maxlvt();
 
 	for (j = 1; j <= num_starts; j++) {
 		Dprintk("Sending STARTUP #%d.\n",j);
@@ -1115,8 +970,6 @@
 	info.cpu = cpu;
 	INIT_WORK(&info.task, do_warm_boot_cpu);
 
-	tsc_sync_disabled = 1;
-
 	/* init low mem mapping */
 	clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
 			min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
@@ -1124,7 +977,6 @@
 	schedule_work(&info.task);
 	wait_for_completion(&done);
 
-	tsc_sync_disabled = 0;
 	zap_low_mappings();
 	ret = 0;
 exit:
@@ -1320,13 +1172,7 @@
 
 	smpboot_setup_io_apic();
 
-	setup_boot_APIC_clock();
-
-	/*
-	 * Synchronize the TSC with the AP
-	 */
-	if (cpu_has_tsc && cpucount && cpu_khz)
-		synchronize_tsc_bp();
+	setup_boot_clock();
 }
 
 /* These are wrappers to interface to the new boot process.  Someone
@@ -1461,9 +1307,16 @@
 	}
 
 	local_irq_enable();
+
 	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
 	/* Unleash the CPU! */
 	cpu_set(cpu, smp_commenced_mask);
+
+	/*
+	 * Check TSC synchronization with the AP:
+	 */
+	check_tsc_sync_source(cpu);
+
 	while (!cpu_isset(cpu, cpu_online_map))
 		cpu_relax();
 
diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
index 5da7442..13ca54a 100644
--- a/arch/i386/kernel/sysenter.c
+++ b/arch/i386/kernel/sysenter.c
@@ -70,14 +70,15 @@
  */
 extern const char vsyscall_int80_start, vsyscall_int80_end;
 extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
-static void *syscall_page;
+static struct page *syscall_pages[1];
 
 int __init sysenter_setup(void)
 {
-	syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+	void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+	syscall_pages[0] = virt_to_page(syscall_page);
 
 #ifdef CONFIG_COMPAT_VDSO
-	__set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY);
+	__set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY_EXEC);
 	printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO));
 #endif
 
@@ -96,31 +97,12 @@
 }
 
 #ifndef CONFIG_COMPAT_VDSO
-static struct page *syscall_nopage(struct vm_area_struct *vma,
-				unsigned long adr, int *type)
-{
-	struct page *p = virt_to_page(adr - vma->vm_start + syscall_page);
-	get_page(p);
-	return p;
-}
-
-/* Prevent VMA merging */
-static void syscall_vma_close(struct vm_area_struct *vma)
-{
-}
-
-static struct vm_operations_struct syscall_vm_ops = {
-	.close = syscall_vma_close,
-	.nopage = syscall_nopage,
-};
-
 /* Defined in vsyscall-sysenter.S */
 extern void SYSENTER_RETURN;
 
 /* Setup a VMA at program startup for the vsyscall page */
 int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
 {
-	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
 	unsigned long addr;
 	int ret;
@@ -132,38 +114,25 @@
 		goto up_fail;
 	}
 
-	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
-	if (!vma) {
-		ret = -ENOMEM;
-		goto up_fail;
-	}
-
-	vma->vm_start = addr;
-	vma->vm_end = addr + PAGE_SIZE;
-	/* MAYWRITE to allow gdb to COW and set breakpoints */
-	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
 	/*
+	 * MAYWRITE to allow gdb to COW and set breakpoints
+	 *
 	 * Make sure the vDSO gets into every core dump.
 	 * Dumping its contents makes post-mortem fully interpretable later
 	 * without matching up the same kernel and hardware config to see
 	 * what PC values meant.
 	 */
-	vma->vm_flags |= VM_ALWAYSDUMP;
-	vma->vm_flags |= mm->def_flags;
-	vma->vm_page_prot = protection_map[vma->vm_flags & 7];
-	vma->vm_ops = &syscall_vm_ops;
-	vma->vm_mm = mm;
-
-	ret = insert_vm_struct(mm, vma);
-	if (unlikely(ret)) {
-		kmem_cache_free(vm_area_cachep, vma);
+	ret = install_special_mapping(mm, addr, PAGE_SIZE,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+				      VM_ALWAYSDUMP,
+				      syscall_pages);
+	if (ret)
 		goto up_fail;
-	}
 
 	current->mm->context.vdso = (void *)addr;
 	current_thread_info()->sysenter_return =
 				    (void *)VDSO_SYM(&SYSENTER_RETURN);
-	mm->total_vm++;
 up_fail:
 	up_write(&mm->mmap_sem);
 	return ret;
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index c505b16..a535005 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -131,15 +131,13 @@
 	unsigned long pc = instruction_pointer(regs);
 
 #ifdef CONFIG_SMP
-	if (!user_mode_vm(regs) && in_lock_functions(pc)) {
+	if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->xcs) &&
+	    in_lock_functions(pc)) {
 #ifdef CONFIG_FRAME_POINTER
 		return *(unsigned long *)(regs->ebp + 4);
 #else
-		unsigned long *sp;
-		if ((regs->xcs & 3) == 0)
-			sp = (unsigned long *)&regs->esp;
-		else
-			sp = (unsigned long *)regs->esp;
+		unsigned long *sp = (unsigned long *)&regs->esp;
+
 		/* Return address is either directly at stack pointer
 		   or above a saved eflags. Eflags has bits 22-31 zero,
 		   kernel addresses don't. */
@@ -161,15 +159,6 @@
  */
 irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
-	/*
-	 * Here we are in the timer irq handler. We just have irqs locally
-	 * disabled but we don't know if the timer_bh is running on the other
-	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
-	 * the irq version of write_lock because as just said we have irq
-	 * locally disabled. -arca
-	 */
-	write_seqlock(&xtime_lock);
-
 #ifdef CONFIG_X86_IO_APIC
 	if (timer_ack) {
 		/*
@@ -188,7 +177,6 @@
 
 	do_timer_interrupt_hook();
 
-
 	if (MCA_bus) {
 		/* The PS/2 uses level-triggered interrupts.  You can't
 		turn them off, nor would you want to (any attempt to
@@ -203,18 +191,11 @@
 		outb_p( irq_v|0x80, 0x61 );	/* reset the IRQ */
 	}
 
-	write_sequnlock(&xtime_lock);
-
-#ifdef CONFIG_X86_LOCAL_APIC
-	if (using_apic_timer)
-		smp_send_timer_broadcast_ipi();
-#endif
-
 	return IRQ_HANDLED;
 }
 
 /* not static: needed by APM */
-unsigned long get_cmos_time(void)
+unsigned long read_persistent_clock(void)
 {
 	unsigned long retval;
 	unsigned long flags;
@@ -227,11 +208,11 @@
 
 	return retval;
 }
-EXPORT_SYMBOL(get_cmos_time);
 
 static void sync_cmos_clock(unsigned long dummy);
 
 static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
+int no_sync_cmos_clock;
 
 static void sync_cmos_clock(unsigned long dummy)
 {
@@ -275,117 +256,20 @@
 
 void notify_arch_cmos_timer(void)
 {
-	mod_timer(&sync_cmos_timer, jiffies + 1);
+	if (!no_sync_cmos_clock)
+		mod_timer(&sync_cmos_timer, jiffies + 1);
 }
 
-static long clock_cmos_diff;
-static unsigned long sleep_start;
-
-static int timer_suspend(struct sys_device *dev, pm_message_t state)
-{
-	/*
-	 * Estimate time zone so that set_time can update the clock
-	 */
-	unsigned long ctime =  get_cmos_time();
-
-	clock_cmos_diff = -ctime;
-	clock_cmos_diff += get_seconds();
-	sleep_start = ctime;
-	return 0;
-}
-
-static int timer_resume(struct sys_device *dev)
-{
-	unsigned long flags;
-	unsigned long sec;
-	unsigned long ctime = get_cmos_time();
-	long sleep_length = (ctime - sleep_start) * HZ;
-	struct timespec ts;
-
-	if (sleep_length < 0) {
-		printk(KERN_WARNING "CMOS clock skew detected in timer resume!\n");
-		/* The time after the resume must not be earlier than the time
-		 * before the suspend or some nasty things will happen
-		 */
-		sleep_length = 0;
-		ctime = sleep_start;
-	}
-#ifdef CONFIG_HPET_TIMER
-	if (is_hpet_enabled())
-		hpet_reenable();
-#endif
-	setup_pit_timer();
-
-	sec = ctime + clock_cmos_diff;
-	ts.tv_sec = sec;
-	ts.tv_nsec = 0;
-	do_settimeofday(&ts);
-	write_seqlock_irqsave(&xtime_lock, flags);
-	jiffies_64 += sleep_length;
-	write_sequnlock_irqrestore(&xtime_lock, flags);
-	touch_softlockup_watchdog();
-	return 0;
-}
-
-static struct sysdev_class timer_sysclass = {
-	.resume = timer_resume,
-	.suspend = timer_suspend,
-	set_kset_name("timer"),
-};
-
-
-/* XXX this driverfs stuff should probably go elsewhere later -john */
-static struct sys_device device_timer = {
-	.id	= 0,
-	.cls	= &timer_sysclass,
-};
-
-static int time_init_device(void)
-{
-	int error = sysdev_class_register(&timer_sysclass);
-	if (!error)
-		error = sysdev_register(&device_timer);
-	return error;
-}
-
-device_initcall(time_init_device);
-
-#ifdef CONFIG_HPET_TIMER
 extern void (*late_time_init)(void);
 /* Duplicate of time_init() below, with hpet_enable part added */
 static void __init hpet_time_init(void)
 {
-	struct timespec ts;
-	ts.tv_sec = get_cmos_time();
-	ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
-
-	do_settimeofday(&ts);
-
-	if ((hpet_enable() >= 0) && hpet_use_timer) {
-		printk("Using HPET for base-timer\n");
-	}
-
+	if (!hpet_enable())
+		setup_pit_timer();
 	do_time_init();
 }
-#endif
 
 void __init time_init(void)
 {
-	struct timespec ts;
-#ifdef CONFIG_HPET_TIMER
-	if (is_hpet_capable()) {
-		/*
-		 * HPET initialization needs to do memory-mapped io. So, let
-		 * us do a late initialization after mem_init().
-		 */
-		late_time_init = hpet_time_init;
-		return;
-	}
-#endif
-	ts.tv_sec = get_cmos_time();
-	ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
-
-	do_settimeofday(&ts);
-
-	do_time_init();
+	late_time_init = hpet_time_init;
 }
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
deleted file mode 100644
index 1e4702d..0000000
--- a/arch/i386/kernel/time_hpet.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- *  linux/arch/i386/kernel/time_hpet.c
- *  This code largely copied from arch/x86_64/kernel/time.c
- *  See that file for credits.
- *
- *  2003-06-30    Venkatesh Pallipadi - Additional changes for HPET support
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-
-#include <asm/timer.h>
-#include <asm/fixmap.h>
-#include <asm/apic.h>
-
-#include <linux/timex.h>
-
-#include <asm/hpet.h>
-#include <linux/hpet.h>
-
-static unsigned long hpet_period;	/* fsecs / HPET clock */
-unsigned long hpet_tick;		/* hpet clks count per tick */
-unsigned long hpet_address;		/* hpet memory map physical address */
-int hpet_use_timer;
-
-static int use_hpet; 		/* can be used for runtime check of hpet */
-static int boot_hpet_disable; 	/* boottime override for HPET timer */
-static void __iomem * hpet_virt_address;	/* hpet kernel virtual address */
-
-#define FSEC_TO_USEC (1000000000UL)
-
-int hpet_readl(unsigned long a)
-{
-	return readl(hpet_virt_address + a);
-}
-
-static void hpet_writel(unsigned long d, unsigned long a)
-{
-	writel(d, hpet_virt_address + a);
-}
-
-#ifdef CONFIG_X86_LOCAL_APIC
-/*
- * HPET counters dont wrap around on every tick. They just change the
- * comparator value and continue. Next tick can be caught by checking
- * for a change in the comparator value. Used in apic.c.
- */
-static void __devinit wait_hpet_tick(void)
-{
-	unsigned int start_cmp_val, end_cmp_val;
-
-	start_cmp_val = hpet_readl(HPET_T0_CMP);
-	do {
-		end_cmp_val = hpet_readl(HPET_T0_CMP);
-	} while (start_cmp_val == end_cmp_val);
-}
-#endif
-
-static int hpet_timer_stop_set_go(unsigned long tick)
-{
-	unsigned int cfg;
-
-	/*
-	 * Stop the timers and reset the main counter.
-	 */
-	cfg = hpet_readl(HPET_CFG);
-	cfg &= ~HPET_CFG_ENABLE;
-	hpet_writel(cfg, HPET_CFG);
-	hpet_writel(0, HPET_COUNTER);
-	hpet_writel(0, HPET_COUNTER + 4);
-
-	if (hpet_use_timer) {
-		/*
-		 * Set up timer 0, as periodic with first interrupt to happen at
-		 * hpet_tick, and period also hpet_tick.
-		 */
-		cfg = hpet_readl(HPET_T0_CFG);
-		cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
-		       HPET_TN_SETVAL | HPET_TN_32BIT;
-		hpet_writel(cfg, HPET_T0_CFG);
-
-		/*
-		 * The first write after writing TN_SETVAL to the config register sets
-		 * the counter value, the second write sets the threshold.
-		 */
-		hpet_writel(tick, HPET_T0_CMP);
-		hpet_writel(tick, HPET_T0_CMP);
-	}
-	/*
- 	 * Go!
- 	 */
-	cfg = hpet_readl(HPET_CFG);
-	if (hpet_use_timer)
-		cfg |= HPET_CFG_LEGACY;
-	cfg |= HPET_CFG_ENABLE;
-	hpet_writel(cfg, HPET_CFG);
-
-	return 0;
-}
-
-/*
- * Check whether HPET was found by ACPI boot parse. If yes setup HPET
- * counter 0 for kernel base timer.
- */
-int __init hpet_enable(void)
-{
-	unsigned int id;
-	unsigned long tick_fsec_low, tick_fsec_high; /* tick in femto sec */
-	unsigned long hpet_tick_rem;
-
-	if (boot_hpet_disable)
-		return -1;
-
-	if (!hpet_address) {
-		return -1;
-	}
-	hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
-	/*
-	 * Read the period, compute tick and quotient.
-	 */
-	id = hpet_readl(HPET_ID);
-
-	/*
-	 * We are checking for value '1' or more in number field if
-	 * CONFIG_HPET_EMULATE_RTC is set because we will need an
-	 * additional timer for RTC emulation.
-	 * However, we can do with one timer otherwise using the
-	 * the single HPET timer for system time.
-	 */
-#ifdef CONFIG_HPET_EMULATE_RTC
-	if (!(id & HPET_ID_NUMBER)) {
-		iounmap(hpet_virt_address);
-		hpet_virt_address = NULL;
-		return -1;
-	}
-#endif
-
-
-	hpet_period = hpet_readl(HPET_PERIOD);
-	if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD)) {
-		iounmap(hpet_virt_address);
-		hpet_virt_address = NULL;
-		return -1;
-	}
-
-	/*
-	 * 64 bit math
-	 * First changing tick into fsec
-	 * Then 64 bit div to find number of hpet clk per tick
-	 */
-	ASM_MUL64_REG(tick_fsec_low, tick_fsec_high,
-			KERNEL_TICK_USEC, FSEC_TO_USEC);
-	ASM_DIV64_REG(hpet_tick, hpet_tick_rem,
-			hpet_period, tick_fsec_low, tick_fsec_high);
-
-	if (hpet_tick_rem > (hpet_period >> 1))
-		hpet_tick++; /* rounding the result */
-
-	hpet_use_timer = id & HPET_ID_LEGSUP;
-
-	if (hpet_timer_stop_set_go(hpet_tick)) {
-		iounmap(hpet_virt_address);
-		hpet_virt_address = NULL;
-		return -1;
-	}
-
-	use_hpet = 1;
-
-#ifdef	CONFIG_HPET
-	{
-		struct hpet_data	hd;
-		unsigned int 		ntimer;
-
-		memset(&hd, 0, sizeof (hd));
-
-		ntimer = hpet_readl(HPET_ID);
-		ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
-		ntimer++;
-
-		/*
-		 * Register with driver.
-		 * Timer0 and Timer1 is used by platform.
-		 */
-		hd.hd_phys_address = hpet_address;
-		hd.hd_address = hpet_virt_address;
-		hd.hd_nirqs = ntimer;
-		hd.hd_flags = HPET_DATA_PLATFORM;
-		hpet_reserve_timer(&hd, 0);
-#ifdef	CONFIG_HPET_EMULATE_RTC
-		hpet_reserve_timer(&hd, 1);
-#endif
-		hd.hd_irq[0] = HPET_LEGACY_8254;
-		hd.hd_irq[1] = HPET_LEGACY_RTC;
-		if (ntimer > 2) {
-			struct hpet __iomem	*hpet;
-			struct hpet_timer __iomem *timer;
-			int			i;
-
-			hpet = hpet_virt_address;
-
-			for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer;
-				timer++, i++)
-				hd.hd_irq[i] = (timer->hpet_config &
-					Tn_INT_ROUTE_CNF_MASK) >>
-					Tn_INT_ROUTE_CNF_SHIFT;
-
-		}
-
-		hpet_alloc(&hd);
-	}
-#endif
-
-#ifdef CONFIG_X86_LOCAL_APIC
-	if (hpet_use_timer)
-		wait_timer_tick = wait_hpet_tick;
-#endif
-	return 0;
-}
-
-int hpet_reenable(void)
-{
-	return hpet_timer_stop_set_go(hpet_tick);
-}
-
-int is_hpet_enabled(void)
-{
-	return use_hpet;
-}
-
-int is_hpet_capable(void)
-{
-	if (!boot_hpet_disable && hpet_address)
-		return 1;
-	return 0;
-}
-
-static int __init hpet_setup(char* str)
-{
-	if (str) {
-		if (!strncmp("disable", str, 7))
-			boot_hpet_disable = 1;
-	}
-	return 1;
-}
-
-__setup("hpet=", hpet_setup);
-
-#ifdef CONFIG_HPET_EMULATE_RTC
-/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
- * is enabled, we support RTC interrupt functionality in software.
- * RTC has 3 kinds of interrupts:
- * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
- *    is updated
- * 2) Alarm Interrupt - generate an interrupt at a specific time of day
- * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
- *    2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
- * (1) and (2) above are implemented using polling at a frequency of
- * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
- * overhead. (DEFAULT_RTC_INT_FREQ)
- * For (3), we use interrupts at 64Hz or user specified periodic
- * frequency, whichever is higher.
- */
-#include <linux/mc146818rtc.h>
-#include <linux/rtc.h>
-
-#define DEFAULT_RTC_INT_FREQ 	64
-#define RTC_NUM_INTS 		1
-
-static unsigned long UIE_on;
-static unsigned long prev_update_sec;
-
-static unsigned long AIE_on;
-static struct rtc_time alarm_time;
-
-static unsigned long PIE_on;
-static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ;
-static unsigned long PIE_count;
-
-static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
-static unsigned int hpet_t1_cmp; /* cached comparator register */
-
-/*
- * Timer 1 for RTC, we do not use periodic interrupt feature,
- * even if HPET supports periodic interrupts on Timer 1.
- * The reason being, to set up a periodic interrupt in HPET, we need to
- * stop the main counter. And if we do that everytime someone diables/enables
- * RTC, we will have adverse effect on main kernel timer running on Timer 0.
- * So, for the time being, simulate the periodic interrupt in software.
- *
- * hpet_rtc_timer_init() is called for the first time and during subsequent
- * interuppts reinit happens through hpet_rtc_timer_reinit().
- */
-int hpet_rtc_timer_init(void)
-{
-	unsigned int cfg, cnt;
-	unsigned long flags;
-
-	if (!is_hpet_enabled())
-		return 0;
-	/*
-	 * Set the counter 1 and enable the interrupts.
-	 */
-	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
-		hpet_rtc_int_freq = PIE_freq;
-	else
-		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
-
-	local_irq_save(flags);
-
-	cnt = hpet_readl(HPET_COUNTER);
-	cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
-	hpet_writel(cnt, HPET_T1_CMP);
-	hpet_t1_cmp = cnt;
-
-	cfg = hpet_readl(HPET_T1_CFG);
-	cfg &= ~HPET_TN_PERIODIC;
-	cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_T1_CFG);
-
-	local_irq_restore(flags);
-
-	return 1;
-}
-
-static void hpet_rtc_timer_reinit(void)
-{
-	unsigned int cfg, cnt, ticks_per_int, lost_ints;
-
-	if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
-		cfg = hpet_readl(HPET_T1_CFG);
-		cfg &= ~HPET_TN_ENABLE;
-		hpet_writel(cfg, HPET_T1_CFG);
-		return;
-	}
-
-	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
-		hpet_rtc_int_freq = PIE_freq;
-	else
-		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
-
-	/* It is more accurate to use the comparator value than current count.*/
-	ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq;
-	hpet_t1_cmp += ticks_per_int;
-	hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
-
-	/*
-	 * If the interrupt handler was delayed too long, the write above tries
-	 * to schedule the next interrupt in the past and the hardware would
-	 * not interrupt until the counter had wrapped around.
-	 * So we have to check that the comparator wasn't set to a past time.
-	 */
-	cnt = hpet_readl(HPET_COUNTER);
-	if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) {
-		lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1;
-		/* Make sure that, even with the time needed to execute
-		 * this code, the next scheduled interrupt has been moved
-		 * back to the future: */
-		lost_ints++;
-
-		hpet_t1_cmp += lost_ints * ticks_per_int;
-		hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
-
-		if (PIE_on)
-			PIE_count += lost_ints;
-
-		printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
-		       hpet_rtc_int_freq);
-	}
-}
-
-/*
- * The functions below are called from rtc driver.
- * Return 0 if HPET is not being used.
- * Otherwise do the necessary changes and return 1.
- */
-int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	if (bit_mask & RTC_UIE)
-		UIE_on = 0;
-	if (bit_mask & RTC_PIE)
-		PIE_on = 0;
-	if (bit_mask & RTC_AIE)
-		AIE_on = 0;
-
-	return 1;
-}
-
-int hpet_set_rtc_irq_bit(unsigned long bit_mask)
-{
-	int timer_init_reqd = 0;
-
-	if (!is_hpet_enabled())
-		return 0;
-
-	if (!(PIE_on | AIE_on | UIE_on))
-		timer_init_reqd = 1;
-
-	if (bit_mask & RTC_UIE) {
-		UIE_on = 1;
-	}
-	if (bit_mask & RTC_PIE) {
-		PIE_on = 1;
-		PIE_count = 0;
-	}
-	if (bit_mask & RTC_AIE) {
-		AIE_on = 1;
-	}
-
-	if (timer_init_reqd)
-		hpet_rtc_timer_init();
-
-	return 1;
-}
-
-int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	alarm_time.tm_hour = hrs;
-	alarm_time.tm_min = min;
-	alarm_time.tm_sec = sec;
-
-	return 1;
-}
-
-int hpet_set_periodic_freq(unsigned long freq)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	PIE_freq = freq;
-	PIE_count = 0;
-
-	return 1;
-}
-
-int hpet_rtc_dropped_irq(void)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	return 1;
-}
-
-irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
-{
-	struct rtc_time curr_time;
-	unsigned long rtc_int_flag = 0;
-	int call_rtc_interrupt = 0;
-
-	hpet_rtc_timer_reinit();
-
-	if (UIE_on | AIE_on) {
-		rtc_get_rtc_time(&curr_time);
-	}
-	if (UIE_on) {
-		if (curr_time.tm_sec != prev_update_sec) {
-			/* Set update int info, call real rtc int routine */
-			call_rtc_interrupt = 1;
-			rtc_int_flag = RTC_UF;
-			prev_update_sec = curr_time.tm_sec;
-		}
-	}
-	if (PIE_on) {
-		PIE_count++;
-		if (PIE_count >= hpet_rtc_int_freq/PIE_freq) {
-			/* Set periodic int info, call real rtc int routine */
-			call_rtc_interrupt = 1;
-			rtc_int_flag |= RTC_PF;
-			PIE_count = 0;
-		}
-	}
-	if (AIE_on) {
-		if ((curr_time.tm_sec == alarm_time.tm_sec) &&
-		    (curr_time.tm_min == alarm_time.tm_min) &&
-		    (curr_time.tm_hour == alarm_time.tm_hour)) {
-			/* Set alarm int info, call real rtc int routine */
-			call_rtc_interrupt = 1;
-			rtc_int_flag |= RTC_AF;
-		}
-	}
-	if (call_rtc_interrupt) {
-		rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
-		rtc_interrupt(rtc_int_flag, dev_id);
-	}
-	return IRQ_HANDLED;
-}
-#endif
-
diff --git a/arch/i386/kernel/topology.c b/arch/i386/kernel/topology.c
index 79cf608..4578235 100644
--- a/arch/i386/kernel/topology.c
+++ b/arch/i386/kernel/topology.c
@@ -1,5 +1,5 @@
 /*
- * arch/i386/kernel/topology.c - Populate driverfs with topology information
+ * arch/i386/kernel/topology.c - Populate sysfs with topology information
  *
  * Written by: Matthew Dobson, IBM Corporation
  * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 0efad8a..af0d3f7 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -94,6 +94,7 @@
 asmlinkage void machine_check(void);
 
 int kstack_depth_to_print = 24;
+static unsigned int code_bytes = 64;
 ATOMIC_NOTIFIER_HEAD(i386die_chain);
 
 int register_die_notifier(struct notifier_block *nb)
@@ -291,10 +292,11 @@
 	int i;
 	int in_kernel = 1;
 	unsigned long esp;
-	unsigned short ss;
+	unsigned short ss, gs;
 
 	esp = (unsigned long) (&regs->esp);
 	savesegment(ss, ss);
+	savesegment(gs, gs);
 	if (user_mode_vm(regs)) {
 		in_kernel = 0;
 		esp = regs->esp;
@@ -313,8 +315,8 @@
 		regs->eax, regs->ebx, regs->ecx, regs->edx);
 	printk(KERN_EMERG "esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
 		regs->esi, regs->edi, regs->ebp, esp);
-	printk(KERN_EMERG "ds: %04x   es: %04x   ss: %04x\n",
-		regs->xds & 0xffff, regs->xes & 0xffff, ss);
+	printk(KERN_EMERG "ds: %04x   es: %04x   fs: %04x  gs: %04x  ss: %04x\n",
+	       regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss);
 	printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
 		TASK_COMM_LEN, current->comm, current->pid,
 		current_thread_info(), current, current->thread_info);
@@ -324,7 +326,8 @@
 	 */
 	if (in_kernel) {
 		u8 *eip;
-		int code_bytes = 64;
+		unsigned int code_prologue = code_bytes * 43 / 64;
+		unsigned int code_len = code_bytes;
 		unsigned char c;
 
 		printk("\n" KERN_EMERG "Stack: ");
@@ -332,14 +335,14 @@
 
 		printk(KERN_EMERG "Code: ");
 
-		eip = (u8 *)regs->eip - 43;
+		eip = (u8 *)regs->eip - code_prologue;
 		if (eip < (u8 *)PAGE_OFFSET ||
 			probe_kernel_address(eip, c)) {
 			/* try starting at EIP */
 			eip = (u8 *)regs->eip;
-			code_bytes = 32;
+			code_len = code_len - code_prologue + 1;
 		}
-		for (i = 0; i < code_bytes; i++, eip++) {
+		for (i = 0; i < code_len; i++, eip++) {
 			if (eip < (u8 *)PAGE_OFFSET ||
 				probe_kernel_address(eip, c)) {
 				printk(" Bad EIP value.");
@@ -1191,3 +1194,13 @@
 	return 1;
 }
 __setup("kstack=", kstack_setup);
+
+static int __init code_bytes_setup(char *s)
+{
+	code_bytes = simple_strtoul(s, NULL, 0);
+	if (code_bytes > 8192)
+		code_bytes = 8192;
+
+	return 1;
+}
+__setup("code_bytes=", code_bytes_setup);
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index 2cfc7b0..3082a41 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -23,6 +23,7 @@
  * an extra value to store the TSC freq
  */
 unsigned int tsc_khz;
+unsigned long long (*custom_sched_clock)(void);
 
 int tsc_disable;
 
@@ -59,12 +60,6 @@
 	return tsc_unstable;
 }
 
-void mark_tsc_unstable(void)
-{
-	tsc_unstable = 1;
-}
-EXPORT_SYMBOL_GPL(mark_tsc_unstable);
-
 /* Accellerators for sched_clock()
  * convert from cycles(64bits) => nanoseconds (64bits)
  *  basic equation:
@@ -107,14 +102,14 @@
 {
 	unsigned long long this_offset;
 
+	if (unlikely(custom_sched_clock))
+		return (*custom_sched_clock)();
+
 	/*
-	 * in the NUMA case we dont use the TSC as they are not
-	 * synchronized across all CPUs.
+	 * Fall back to jiffies if there's no TSC available:
 	 */
-#ifndef CONFIG_NUMA
-	if (!cpu_khz || check_tsc_unstable())
-#endif
-		/* no locking but a rare wrong value is not a big deal */
+	if (unlikely(tsc_disable))
+		/* No locking but a rare wrong value is not a big deal: */
 		return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
 
 	/* read the Time Stamp Counter: */
@@ -194,13 +189,13 @@
 void __init tsc_init(void)
 {
 	if (!cpu_has_tsc || tsc_disable)
-		return;
+		goto out_no_tsc;
 
 	cpu_khz = calculate_cpu_khz();
 	tsc_khz = cpu_khz;
 
 	if (!cpu_khz)
-		return;
+		goto out_no_tsc;
 
 	printk("Detected %lu.%03lu MHz processor.\n",
 				(unsigned long)cpu_khz / 1000,
@@ -208,38 +203,19 @@
 
 	set_cyc2ns_scale(cpu_khz);
 	use_tsc_delay();
+	return;
+
+out_no_tsc:
+	/*
+	 * Set the tsc_disable flag if there's no TSC support, this
+	 * makes it a fast flag for the kernel to see whether it
+	 * should be using the TSC.
+	 */
+	tsc_disable = 1;
 }
 
 #ifdef CONFIG_CPU_FREQ
 
-static unsigned int cpufreq_delayed_issched = 0;
-static unsigned int cpufreq_init = 0;
-static struct work_struct cpufreq_delayed_get_work;
-
-static void handle_cpufreq_delayed_get(struct work_struct *work)
-{
-	unsigned int cpu;
-
-	for_each_online_cpu(cpu)
-		cpufreq_get(cpu);
-
-	cpufreq_delayed_issched = 0;
-}
-
-/*
- * if we notice cpufreq oddness, schedule a call to cpufreq_get() as it tries
- * to verify the CPU frequency the timing core thinks the CPU is running
- * at is still correct.
- */
-static inline void cpufreq_delayed_get(void)
-{
-	if (cpufreq_init && !cpufreq_delayed_issched) {
-		cpufreq_delayed_issched = 1;
-		printk(KERN_DEBUG "Checking if CPU frequency changed.\n");
-		schedule_work(&cpufreq_delayed_get_work);
-	}
-}
-
 /*
  * if the CPU frequency is scaled, TSC-based delays will need a different
  * loops_per_jiffy value to function properly.
@@ -303,17 +279,9 @@
 
 static int __init cpufreq_tsc(void)
 {
-	int ret;
-
-	INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get);
-	ret = cpufreq_register_notifier(&time_cpufreq_notifier_block,
-					CPUFREQ_TRANSITION_NOTIFIER);
-	if (!ret)
-		cpufreq_init = 1;
-
-	return ret;
+	return cpufreq_register_notifier(&time_cpufreq_notifier_block,
+					 CPUFREQ_TRANSITION_NOTIFIER);
 }
-
 core_initcall(cpufreq_tsc);
 
 #endif
@@ -321,7 +289,6 @@
 /* clock source code */
 
 static unsigned long current_tsc_khz = 0;
-static int tsc_update_callback(void);
 
 static cycle_t read_tsc(void)
 {
@@ -339,37 +306,28 @@
 	.mask			= CLOCKSOURCE_MASK(64),
 	.mult			= 0, /* to be set */
 	.shift			= 22,
-	.update_callback	= tsc_update_callback,
-	.is_continuous		= 1,
+	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
+				  CLOCK_SOURCE_MUST_VERIFY,
 };
 
-static int tsc_update_callback(void)
+void mark_tsc_unstable(void)
 {
-	int change = 0;
-
-	/* check to see if we should switch to the safe clocksource: */
-	if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
-		clocksource_tsc.rating = 0;
-		clocksource_reselect();
-		change = 1;
+	if (!tsc_unstable) {
+		tsc_unstable = 1;
+		/* Can be called before registration */
+		if (clocksource_tsc.mult)
+			clocksource_change_rating(&clocksource_tsc, 0);
+		else
+			clocksource_tsc.rating = 0;
 	}
-
-	/* only update if tsc_khz has changed: */
-	if (current_tsc_khz != tsc_khz) {
-		current_tsc_khz = tsc_khz;
-		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
-							clocksource_tsc.shift);
-		change = 1;
-	}
-
-	return change;
 }
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d)
 {
 	printk(KERN_NOTICE "%s detected: marking TSC unstable.\n",
 		       d->ident);
-	mark_tsc_unstable();
+	tsc_unstable = 1;
 	return 0;
 }
 
@@ -386,66 +344,45 @@
 	 {}
 };
 
-#define TSC_FREQ_CHECK_INTERVAL (10*MSEC_PER_SEC) /* 10sec in MS */
-static struct timer_list verify_tsc_freq_timer;
-
-/* XXX - Probably should add locking */
-static void verify_tsc_freq(unsigned long unused)
-{
-	static u64 last_tsc;
-	static unsigned long last_jiffies;
-
-	u64 now_tsc, interval_tsc;
-	unsigned long now_jiffies, interval_jiffies;
-
-
-	if (check_tsc_unstable())
-		return;
-
-	rdtscll(now_tsc);
-	now_jiffies = jiffies;
-
-	if (!last_jiffies) {
-		goto out;
-	}
-
-	interval_jiffies = now_jiffies - last_jiffies;
-	interval_tsc = now_tsc - last_tsc;
-	interval_tsc *= HZ;
-	do_div(interval_tsc, cpu_khz*1000);
-
-	if (interval_tsc < (interval_jiffies * 3 / 4)) {
-		printk("TSC appears to be running slowly. "
-			"Marking it as unstable\n");
-		mark_tsc_unstable();
-		return;
-	}
-
-out:
-	last_tsc = now_tsc;
-	last_jiffies = now_jiffies;
-	/* set us up to go off on the next interval: */
-	mod_timer(&verify_tsc_freq_timer,
-		jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL));
-}
-
 /*
  * Make an educated guess if the TSC is trustworthy and synchronized
  * over all CPUs.
  */
-static __init int unsynchronized_tsc(void)
+__cpuinit int unsynchronized_tsc(void)
 {
+	if (!cpu_has_tsc || tsc_unstable)
+		return 1;
 	/*
 	 * Intel systems are normally all synchronized.
 	 * Exceptions must mark TSC as unstable:
 	 */
-	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
- 		return 0;
-
-	/* assume multi socket systems are not synchronized: */
- 	return num_possible_cpus() > 1;
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
+		/* assume multi socket systems are not synchronized: */
+		if (num_possible_cpus() > 1)
+			tsc_unstable = 1;
+	}
+	return tsc_unstable;
 }
 
+/*
+ * Geode_LX - the OLPC CPU has a possibly a very reliable TSC
+ */
+#ifdef CONFIG_MGEODE_LX
+/* RTSC counts during suspend */
+#define RTSC_SUSP 0x100
+
+static void __init check_geode_tsc_reliable(void)
+{
+	unsigned long val;
+
+	rdmsrl(MSR_GEODE_BUSCONT_CONF0, val);
+	if ((val & RTSC_SUSP))
+		clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
+}
+#else
+static inline void check_geode_tsc_reliable(void) { }
+#endif
+
 static int __init init_tsc_clocksource(void)
 {
 
@@ -453,20 +390,16 @@
 		/* check blacklist */
 		dmi_check_system(bad_tsc_dmi_table);
 
-		if (unsynchronized_tsc()) /* mark unstable if unsynced */
-			mark_tsc_unstable();
+		unsynchronized_tsc();
+		check_geode_tsc_reliable();
 		current_tsc_khz = tsc_khz;
 		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
 							clocksource_tsc.shift);
 		/* lower the rating if we already know its unstable: */
-		if (check_tsc_unstable())
+		if (check_tsc_unstable()) {
 			clocksource_tsc.rating = 0;
-
-		init_timer(&verify_tsc_freq_timer);
-		verify_tsc_freq_timer.function = verify_tsc_freq;
-		verify_tsc_freq_timer.expires =
-			jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL);
-		add_timer(&verify_tsc_freq_timer);
+			clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
+		}
 
 		return clocksource_register(&clocksource_tsc);
 	}
diff --git a/arch/i386/kernel/tsc_sync.c b/arch/i386/kernel/tsc_sync.c
new file mode 100644
index 0000000..1242462
--- /dev/null
+++ b/arch/i386/kernel/tsc_sync.c
@@ -0,0 +1 @@
+#include "../../x86_64/kernel/tsc_sync.c"
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index be2f96e..d1b8f2b 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -96,12 +96,12 @@
 {
 	int ret = 0;
 
-	/* kernel_vm86_regs is missing xfs, so copy everything up to
-	   (but not including) xgs, and then rest after xgs. */
-	ret += copy_to_user(user, regs, offsetof(struct kernel_vm86_regs, pt.xgs));
-	ret += copy_to_user(&user->__null_gs, &regs->pt.xgs,
+	/* kernel_vm86_regs is missing xgs, so copy everything up to
+	   (but not including) orig_eax, and then rest including orig_eax. */
+	ret += copy_to_user(user, regs, offsetof(struct kernel_vm86_regs, pt.orig_eax));
+	ret += copy_to_user(&user->orig_eax, &regs->pt.orig_eax,
 			    sizeof(struct kernel_vm86_regs) -
-			    offsetof(struct kernel_vm86_regs, pt.xgs));
+			    offsetof(struct kernel_vm86_regs, pt.orig_eax));
 
 	return ret;
 }
@@ -113,12 +113,13 @@
 {
 	int ret = 0;
 
-	ret += copy_from_user(regs, user, offsetof(struct kernel_vm86_regs, pt.xgs));
-	ret += copy_from_user(&regs->pt.xgs, &user->__null_gs,
+	/* copy eax-xfs inclusive */
+	ret += copy_from_user(regs, user, offsetof(struct kernel_vm86_regs, pt.orig_eax));
+	/* copy orig_eax-__gsh+extra */
+	ret += copy_from_user(&regs->pt.orig_eax, &user->orig_eax,
 			      sizeof(struct kernel_vm86_regs) -
-			      offsetof(struct kernel_vm86_regs, pt.xgs) +
+			      offsetof(struct kernel_vm86_regs, pt.orig_eax) +
 			      extra);
-
 	return ret;
 }
 
@@ -157,8 +158,8 @@
 
 	ret = KVM86->regs32;
 
-	loadsegment(fs, current->thread.saved_fs);
-	ret->xgs = current->thread.saved_gs;
+	ret->xfs = current->thread.saved_fs;
+	loadsegment(gs, current->thread.saved_gs);
 
 	return ret;
 }
@@ -285,9 +286,9 @@
  */
 	info->regs.pt.xds = 0;
 	info->regs.pt.xes = 0;
-	info->regs.pt.xgs = 0;
+	info->regs.pt.xfs = 0;
 
-/* we are clearing fs later just before "jmp resume_userspace",
+/* we are clearing gs later just before "jmp resume_userspace",
  * because it is not saved/restored.
  */
 
@@ -321,8 +322,8 @@
  */
 	info->regs32->eax = 0;
 	tsk->thread.saved_esp0 = tsk->thread.esp0;
-	savesegment(fs, tsk->thread.saved_fs);
-	tsk->thread.saved_gs = info->regs32->xgs;
+	tsk->thread.saved_fs = info->regs32->xfs;
+	savesegment(gs, tsk->thread.saved_gs);
 
 	tss = &per_cpu(init_tss, get_cpu());
 	tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
@@ -342,7 +343,7 @@
 	__asm__ __volatile__(
 		"movl %0,%%esp\n\t"
 		"movl %1,%%ebp\n\t"
-		"mov  %2, %%fs\n\t"
+		"mov  %2, %%gs\n\t"
 		"jmp resume_userspace"
 		: /* no outputs */
 		:"r" (&info->regs), "r" (task_thread_info(tsk)), "r" (0));
diff --git a/arch/i386/kernel/vmi.c b/arch/i386/kernel/vmi.c
new file mode 100644
index 0000000..bb5a7ab
--- /dev/null
+++ b/arch/i386/kernel/vmi.c
@@ -0,0 +1,949 @@
+/*
+ * VMI specific paravirt-ops implementation
+ *
+ * Copyright (C) 2005, VMware, 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to zach@vmware.com
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/license.h>
+#include <linux/cpu.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <asm/vmi.h>
+#include <asm/io.h>
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+#include <asm/apic.h>
+#include <asm/processor.h>
+#include <asm/timer.h>
+#include <asm/vmi_time.h>
+
+/* Convenient for calling VMI functions indirectly in the ROM */
+typedef u32 __attribute__((regparm(1))) (VROMFUNC)(void);
+typedef u64 __attribute__((regparm(2))) (VROMLONGFUNC)(int);
+
+#define call_vrom_func(rom,func) \
+   (((VROMFUNC *)(rom->func))())
+
+#define call_vrom_long_func(rom,func,arg) \
+   (((VROMLONGFUNC *)(rom->func)) (arg))
+
+static struct vrom_header *vmi_rom;
+static int license_gplok;
+static int disable_nodelay;
+static int disable_pge;
+static int disable_pse;
+static int disable_sep;
+static int disable_tsc;
+static int disable_mtrr;
+
+/* Cached VMI operations */
+struct {
+	void (*cpuid)(void /* non-c */);
+	void (*_set_ldt)(u32 selector);
+	void (*set_tr)(u32 selector);
+	void (*set_kernel_stack)(u32 selector, u32 esp0);
+	void (*allocate_page)(u32, u32, u32, u32, u32);
+	void (*release_page)(u32, u32);
+	void (*set_pte)(pte_t, pte_t *, unsigned);
+	void (*update_pte)(pte_t *, unsigned);
+	void (*set_linear_mapping)(int, u32, u32, u32);
+	void (*flush_tlb)(int);
+	void (*set_initial_ap_state)(int, int);
+	void (*halt)(void);
+} vmi_ops;
+
+/* XXX move this to alternative.h */
+extern struct paravirt_patch __start_parainstructions[],
+	__stop_parainstructions[];
+
+/*
+ * VMI patching routines.
+ */
+#define MNEM_CALL 0xe8
+#define MNEM_JMP  0xe9
+#define MNEM_RET  0xc3
+
+static char irq_save_disable_callout[] = {
+	MNEM_CALL, 0, 0, 0, 0,
+	MNEM_CALL, 0, 0, 0, 0,
+	MNEM_RET
+};
+#define IRQ_PATCH_INT_MASK 0
+#define IRQ_PATCH_DISABLE  5
+
+static inline void patch_offset(unsigned char *eip, unsigned char *dest)
+{
+        *(unsigned long *)(eip+1) = dest-eip-5;
+}
+
+static unsigned patch_internal(int call, unsigned len, void *insns)
+{
+	u64 reloc;
+	struct vmi_relocation_info *const rel = (struct vmi_relocation_info *)&reloc;
+	reloc = call_vrom_long_func(vmi_rom, get_reloc,	call);
+	switch(rel->type) {
+		case VMI_RELOCATION_CALL_REL:
+			BUG_ON(len < 5);
+			*(char *)insns = MNEM_CALL;
+			patch_offset(insns, rel->eip);
+			return 5;
+
+		case VMI_RELOCATION_JUMP_REL:
+			BUG_ON(len < 5);
+			*(char *)insns = MNEM_JMP;
+			patch_offset(insns, rel->eip);
+			return 5;
+
+		case VMI_RELOCATION_NOP:
+			/* obliterate the whole thing */
+			return 0;
+
+		case VMI_RELOCATION_NONE:
+			/* leave native code in place */
+			break;
+
+		default:
+			BUG();
+	}
+	return len;
+}
+
+/*
+ * Apply patch if appropriate, return length of new instruction
+ * sequence.  The callee does nop padding for us.
+ */
+static unsigned vmi_patch(u8 type, u16 clobbers, void *insns, unsigned len)
+{
+	switch (type) {
+		case PARAVIRT_IRQ_DISABLE:
+			return patch_internal(VMI_CALL_DisableInterrupts, len, insns);
+		case PARAVIRT_IRQ_ENABLE:
+			return patch_internal(VMI_CALL_EnableInterrupts, len, insns);
+		case PARAVIRT_RESTORE_FLAGS:
+			return patch_internal(VMI_CALL_SetInterruptMask, len, insns);
+		case PARAVIRT_SAVE_FLAGS:
+			return patch_internal(VMI_CALL_GetInterruptMask, len, insns);
+        	case PARAVIRT_SAVE_FLAGS_IRQ_DISABLE:
+			if (len >= 10) {
+				patch_internal(VMI_CALL_GetInterruptMask, len, insns);
+				patch_internal(VMI_CALL_DisableInterrupts, len-5, insns+5);
+				return 10;
+			} else {
+				/*
+				 * You bastards didn't leave enough room to
+				 * patch save_flags_irq_disable inline.  Patch
+				 * to a helper
+				 */
+				BUG_ON(len < 5);
+				*(char *)insns = MNEM_CALL;
+				patch_offset(insns, irq_save_disable_callout);
+				return 5;
+			}
+		case PARAVIRT_INTERRUPT_RETURN:
+			return patch_internal(VMI_CALL_IRET, len, insns);
+		case PARAVIRT_STI_SYSEXIT:
+			return patch_internal(VMI_CALL_SYSEXIT, len, insns);
+		default:
+			break;
+	}
+	return len;
+}
+
+/* CPUID has non-C semantics, and paravirt-ops API doesn't match hardware ISA */
+static void vmi_cpuid(unsigned int *eax, unsigned int *ebx,
+                               unsigned int *ecx, unsigned int *edx)
+{
+	int override = 0;
+	if (*eax == 1)
+		override = 1;
+        asm volatile ("call *%6"
+                      : "=a" (*eax),
+                        "=b" (*ebx),
+                        "=c" (*ecx),
+                        "=d" (*edx)
+                      : "0" (*eax), "2" (*ecx), "r" (vmi_ops.cpuid));
+	if (override) {
+		if (disable_pse)
+			*edx &= ~X86_FEATURE_PSE;
+		if (disable_pge)
+			*edx &= ~X86_FEATURE_PGE;
+		if (disable_sep)
+			*edx &= ~X86_FEATURE_SEP;
+		if (disable_tsc)
+			*edx &= ~X86_FEATURE_TSC;
+		if (disable_mtrr)
+			*edx &= ~X86_FEATURE_MTRR;
+	}
+}
+
+static inline void vmi_maybe_load_tls(struct desc_struct *gdt, int nr, struct desc_struct *new)
+{
+	if (gdt[nr].a != new->a || gdt[nr].b != new->b)
+		write_gdt_entry(gdt, nr, new->a, new->b);
+}
+
+static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
+{
+	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+	vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 0, &t->tls_array[0]);
+	vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 1, &t->tls_array[1]);
+	vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 2, &t->tls_array[2]);
+}
+
+static void vmi_set_ldt(const void *addr, unsigned entries)
+{
+	unsigned cpu = smp_processor_id();
+	u32 low, high;
+
+	pack_descriptor(&low, &high, (unsigned long)addr,
+			entries * sizeof(struct desc_struct) - 1,
+			DESCTYPE_LDT, 0);
+	write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, low, high);
+	vmi_ops._set_ldt(entries ? GDT_ENTRY_LDT*sizeof(struct desc_struct) : 0);
+}
+
+static void vmi_set_tr(void)
+{
+	vmi_ops.set_tr(GDT_ENTRY_TSS*sizeof(struct desc_struct));
+}
+
+static void vmi_load_esp0(struct tss_struct *tss,
+				   struct thread_struct *thread)
+{
+	tss->esp0 = thread->esp0;
+
+	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
+	if (unlikely(tss->ss1 != thread->sysenter_cs)) {
+		tss->ss1 = thread->sysenter_cs;
+		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+	}
+	vmi_ops.set_kernel_stack(__KERNEL_DS, tss->esp0);
+}
+
+static void vmi_flush_tlb_user(void)
+{
+	vmi_ops.flush_tlb(VMI_FLUSH_TLB);
+}
+
+static void vmi_flush_tlb_kernel(void)
+{
+	vmi_ops.flush_tlb(VMI_FLUSH_TLB | VMI_FLUSH_GLOBAL);
+}
+
+/* Stub to do nothing at all; used for delays and unimplemented calls */
+static void vmi_nop(void)
+{
+}
+
+/* For NO_IDLE_HZ, we stop the clock when halting the kernel */
+#ifdef CONFIG_NO_IDLE_HZ
+static fastcall void vmi_safe_halt(void)
+{
+	int idle = vmi_stop_hz_timer();
+	vmi_ops.halt();
+	if (idle) {
+		local_irq_disable();
+		vmi_account_time_restart_hz_timer();
+		local_irq_enable();
+	}
+}
+#endif
+
+#ifdef CONFIG_DEBUG_PAGE_TYPE
+
+#ifdef CONFIG_X86_PAE
+#define MAX_BOOT_PTS (2048+4+1)
+#else
+#define MAX_BOOT_PTS (1024+1)
+#endif
+
+/*
+ * During boot, mem_map is not yet available in paging_init, so stash
+ * all the boot page allocations here.
+ */
+static struct {
+	u32 pfn;
+	int type;
+} boot_page_allocations[MAX_BOOT_PTS];
+static int num_boot_page_allocations;
+static int boot_allocations_applied;
+
+void vmi_apply_boot_page_allocations(void)
+{
+	int i;
+	BUG_ON(!mem_map);
+	for (i = 0; i < num_boot_page_allocations; i++) {
+		struct page *page = pfn_to_page(boot_page_allocations[i].pfn);
+		page->type = boot_page_allocations[i].type;
+		page->type = boot_page_allocations[i].type &
+				~(VMI_PAGE_ZEROED | VMI_PAGE_CLONE);
+	}
+	boot_allocations_applied = 1;
+}
+
+static void record_page_type(u32 pfn, int type)
+{
+	BUG_ON(num_boot_page_allocations >= MAX_BOOT_PTS);
+	boot_page_allocations[num_boot_page_allocations].pfn = pfn;
+	boot_page_allocations[num_boot_page_allocations].type = type;
+	num_boot_page_allocations++;
+}
+
+static void check_zeroed_page(u32 pfn, int type, struct page *page)
+{
+	u32 *ptr;
+	int i;
+	int limit = PAGE_SIZE / sizeof(int);
+
+	if (page_address(page))
+		ptr = (u32 *)page_address(page);
+	else
+		ptr = (u32 *)__va(pfn << PAGE_SHIFT);
+	/*
+	 * When cloning the root in non-PAE mode, only the userspace
+	 * pdes need to be zeroed.
+	 */
+	if (type & VMI_PAGE_CLONE)
+		limit = USER_PTRS_PER_PGD;
+	for (i = 0; i < limit; i++)
+		BUG_ON(ptr[i]);
+}
+
+/*
+ * We stash the page type into struct page so we can verify the page
+ * types are used properly.
+ */
+static void vmi_set_page_type(u32 pfn, int type)
+{
+	/* PAE can have multiple roots per page - don't track */
+	if (PTRS_PER_PMD > 1 && (type & VMI_PAGE_PDP))
+		return;
+
+	if (boot_allocations_applied) {
+		struct page *page = pfn_to_page(pfn);
+		if (type != VMI_PAGE_NORMAL)
+			BUG_ON(page->type);
+		else
+			BUG_ON(page->type == VMI_PAGE_NORMAL);
+		page->type = type & ~(VMI_PAGE_ZEROED | VMI_PAGE_CLONE);
+		if (type & VMI_PAGE_ZEROED)
+			check_zeroed_page(pfn, type, page);
+	} else {
+		record_page_type(pfn, type);
+	}
+}
+
+static void vmi_check_page_type(u32 pfn, int type)
+{
+	/* PAE can have multiple roots per page - skip checks */
+	if (PTRS_PER_PMD > 1 && (type & VMI_PAGE_PDP))
+		return;
+
+	type &= ~(VMI_PAGE_ZEROED | VMI_PAGE_CLONE);
+	if (boot_allocations_applied) {
+		struct page *page = pfn_to_page(pfn);
+		BUG_ON((page->type ^ type) & VMI_PAGE_PAE);
+		BUG_ON(type == VMI_PAGE_NORMAL && page->type);
+		BUG_ON((type & page->type) == 0);
+	}
+}
+#else
+#define vmi_set_page_type(p,t) do { } while (0)
+#define vmi_check_page_type(p,t) do { } while (0)
+#endif
+
+static void vmi_allocate_pt(u32 pfn)
+{
+	vmi_set_page_type(pfn, VMI_PAGE_L1);
+	vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
+}
+
+static void vmi_allocate_pd(u32 pfn)
+{
+ 	/*
+	 * This call comes in very early, before mem_map is setup.
+	 * It is called only for swapper_pg_dir, which already has
+	 * data on it.
+	 */
+ 	vmi_set_page_type(pfn, VMI_PAGE_L2);
+	vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0);
+}
+
+static void vmi_allocate_pd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count)
+{
+ 	vmi_set_page_type(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE);
+	vmi_check_page_type(clonepfn, VMI_PAGE_L2);
+	vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count);
+}
+
+static void vmi_release_pt(u32 pfn)
+{
+	vmi_ops.release_page(pfn, VMI_PAGE_L1);
+	vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
+}
+
+static void vmi_release_pd(u32 pfn)
+{
+	vmi_ops.release_page(pfn, VMI_PAGE_L2);
+	vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
+}
+
+/*
+ * Helper macros for MMU update flags.  We can defer updates until a flush
+ * or page invalidation only if the update is to the current address space
+ * (otherwise, there is no flush).  We must check against init_mm, since
+ * this could be a kernel update, which usually passes init_mm, although
+ * sometimes this check can be skipped if we know the particular function
+ * is only called on user mode PTEs.  We could change the kernel to pass
+ * current->active_mm here, but in particular, I was unsure if changing
+ * mm/highmem.c to do this would still be correct on other architectures.
+ */
+#define is_current_as(mm, mustbeuser) ((mm) == current->active_mm ||    \
+                                       (!mustbeuser && (mm) == &init_mm))
+#define vmi_flags_addr(mm, addr, level, user)                           \
+        ((level) | (is_current_as(mm, user) ?                           \
+                (VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
+#define vmi_flags_addr_defer(mm, addr, level, user)                     \
+        ((level) | (is_current_as(mm, user) ?                           \
+                (VMI_PAGE_DEFER | VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
+
+static void vmi_update_pte(struct mm_struct *mm, u32 addr, pte_t *ptep)
+{
+	vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
+	vmi_ops.update_pte(ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
+}
+
+static void vmi_update_pte_defer(struct mm_struct *mm, u32 addr, pte_t *ptep)
+{
+	vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
+	vmi_ops.update_pte(ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 0));
+}
+
+static void vmi_set_pte(pte_t *ptep, pte_t pte)
+{
+	/* XXX because of set_pmd_pte, this can be called on PT or PD layers */
+	vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE | VMI_PAGE_PD);
+	vmi_ops.set_pte(pte, ptep, VMI_PAGE_PT);
+}
+
+static void vmi_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte)
+{
+	vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
+	vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
+}
+
+static void vmi_set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+#ifdef CONFIG_X86_PAE
+	const pte_t pte = { pmdval.pmd, pmdval.pmd >> 32 };
+	vmi_check_page_type(__pa(pmdp) >> PAGE_SHIFT, VMI_PAGE_PMD);
+#else
+	const pte_t pte = { pmdval.pud.pgd.pgd };
+	vmi_check_page_type(__pa(pmdp) >> PAGE_SHIFT, VMI_PAGE_PGD);
+#endif
+	vmi_ops.set_pte(pte, (pte_t *)pmdp, VMI_PAGE_PD);
+}
+
+#ifdef CONFIG_X86_PAE
+
+static void vmi_set_pte_atomic(pte_t *ptep, pte_t pteval)
+{
+	/*
+	 * XXX This is called from set_pmd_pte, but at both PT
+	 * and PD layers so the VMI_PAGE_PT flag is wrong.  But
+	 * it is only called for large page mapping changes,
+	 * the Xen backend, doesn't support large pages, and the
+	 * ESX backend doesn't depend on the flag.
+	 */
+	set_64bit((unsigned long long *)ptep,pte_val(pteval));
+	vmi_ops.update_pte(ptep, VMI_PAGE_PT);
+}
+
+static void vmi_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+{
+	vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
+	vmi_ops.set_pte(pte, ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 1));
+}
+
+static void vmi_set_pud(pud_t *pudp, pud_t pudval)
+{
+	/* Um, eww */
+	const pte_t pte = { pudval.pgd.pgd, pudval.pgd.pgd >> 32 };
+	vmi_check_page_type(__pa(pudp) >> PAGE_SHIFT, VMI_PAGE_PGD);
+	vmi_ops.set_pte(pte, (pte_t *)pudp, VMI_PAGE_PDP);
+}
+
+static void vmi_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	const pte_t pte = { 0 };
+	vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
+	vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
+}
+
+void vmi_pmd_clear(pmd_t *pmd)
+{
+	const pte_t pte = { 0 };
+	vmi_check_page_type(__pa(pmd) >> PAGE_SHIFT, VMI_PAGE_PMD);
+	vmi_ops.set_pte(pte, (pte_t *)pmd, VMI_PAGE_PD);
+}
+#endif
+
+#ifdef CONFIG_SMP
+struct vmi_ap_state ap;
+extern void setup_pda(void);
+
+static void __init /* XXX cpu hotplug */
+vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
+		     unsigned long start_esp)
+{
+	/* Default everything to zero.  This is fine for most GPRs. */
+	memset(&ap, 0, sizeof(struct vmi_ap_state));
+
+	ap.gdtr_limit = GDT_SIZE - 1;
+	ap.gdtr_base = (unsigned long) get_cpu_gdt_table(phys_apicid);
+
+	ap.idtr_limit = IDT_ENTRIES * 8 - 1;
+	ap.idtr_base = (unsigned long) idt_table;
+
+	ap.ldtr = 0;
+
+	ap.cs = __KERNEL_CS;
+	ap.eip = (unsigned long) start_eip;
+	ap.ss = __KERNEL_DS;
+	ap.esp = (unsigned long) start_esp;
+
+	ap.ds = __USER_DS;
+	ap.es = __USER_DS;
+	ap.fs = __KERNEL_PDA;
+	ap.gs = 0;
+
+	ap.eflags = 0;
+
+	setup_pda();
+
+#ifdef CONFIG_X86_PAE
+	/* efer should match BSP efer. */
+	if (cpu_has_nx) {
+		unsigned l, h;
+		rdmsr(MSR_EFER, l, h);
+		ap.efer = (unsigned long long) h << 32 | l;
+	}
+#endif
+
+	ap.cr3 = __pa(swapper_pg_dir);
+	/* Protected mode, paging, AM, WP, NE, MP. */
+	ap.cr0 = 0x80050023;
+	ap.cr4 = mmu_cr4_features;
+	vmi_ops.set_initial_ap_state(__pa(&ap), phys_apicid);
+}
+#endif
+
+static inline int __init check_vmi_rom(struct vrom_header *rom)
+{
+	struct pci_header *pci;
+	struct pnp_header *pnp;
+	const char *manufacturer = "UNKNOWN";
+	const char *product = "UNKNOWN";
+	const char *license = "unspecified";
+
+	if (rom->rom_signature != 0xaa55)
+		return 0;
+	if (rom->vrom_signature != VMI_SIGNATURE)
+		return 0;
+	if (rom->api_version_maj != VMI_API_REV_MAJOR ||
+	    rom->api_version_min+1 < VMI_API_REV_MINOR+1) {
+		printk(KERN_WARNING "VMI: Found mismatched rom version %d.%d\n",
+				rom->api_version_maj,
+				rom->api_version_min);
+		return 0;
+	}
+
+	/*
+	 * Relying on the VMI_SIGNATURE field is not 100% safe, so check
+	 * the PCI header and device type to make sure this is really a
+	 * VMI device.
+	 */
+	if (!rom->pci_header_offs) {
+		printk(KERN_WARNING "VMI: ROM does not contain PCI header.\n");
+		return 0;
+	}
+
+	pci = (struct pci_header *)((char *)rom+rom->pci_header_offs);
+	if (pci->vendorID != PCI_VENDOR_ID_VMWARE ||
+	    pci->deviceID != PCI_DEVICE_ID_VMWARE_VMI) {
+		/* Allow it to run... anyways, but warn */
+		printk(KERN_WARNING "VMI: ROM from unknown manufacturer\n");
+	}
+
+	if (rom->pnp_header_offs) {
+		pnp = (struct pnp_header *)((char *)rom+rom->pnp_header_offs);
+		if (pnp->manufacturer_offset)
+			manufacturer = (const char *)rom+pnp->manufacturer_offset;
+		if (pnp->product_offset)
+			product = (const char *)rom+pnp->product_offset;
+	}
+
+	if (rom->license_offs)
+		license = (char *)rom+rom->license_offs;
+
+	printk(KERN_INFO "VMI: Found %s %s, API version %d.%d, ROM version %d.%d\n",
+		manufacturer, product,
+		rom->api_version_maj, rom->api_version_min,
+		pci->rom_version_maj, pci->rom_version_min);
+
+        license_gplok = license_is_gpl_compatible(license);
+        if (!license_gplok) {
+                printk(KERN_WARNING "VMI: ROM license '%s' taints kernel... "
+		       "inlining disabled\n",
+                       license);
+                add_taint(TAINT_PROPRIETARY_MODULE);
+        }
+	return 1;
+}
+
+/*
+ * Probe for the VMI option ROM
+ */
+static inline int __init probe_vmi_rom(void)
+{
+	unsigned long base;
+
+	/* VMI ROM is in option ROM area, check signature */
+	for (base = 0xC0000; base < 0xE0000; base += 2048) {
+		struct vrom_header *romstart;
+		romstart = (struct vrom_header *)isa_bus_to_virt(base);
+		if (check_vmi_rom(romstart)) {
+			vmi_rom = romstart;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * VMI setup common to all processors
+ */
+void vmi_bringup(void)
+{
+ 	/* We must establish the lowmem mapping for MMU ops to work */
+	if (vmi_rom)
+		vmi_ops.set_linear_mapping(0, __PAGE_OFFSET, max_low_pfn, 0);
+}
+
+/*
+ * Return a pointer to the VMI function or a NOP stub
+ */
+static void *vmi_get_function(int vmicall)
+{
+	u64 reloc;
+	const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
+	reloc = call_vrom_long_func(vmi_rom, get_reloc,	vmicall);
+	BUG_ON(rel->type == VMI_RELOCATION_JUMP_REL);
+	if (rel->type == VMI_RELOCATION_CALL_REL)
+		return (void *)rel->eip;
+	else
+		return (void *)vmi_nop;
+}
+
+/*
+ * Helper macro for making the VMI paravirt-ops fill code readable.
+ * For unimplemented operations, fall back to default.
+ */
+#define para_fill(opname, vmicall)				\
+do {								\
+	reloc = call_vrom_long_func(vmi_rom, get_reloc,		\
+				    VMI_CALL_##vmicall);	\
+	if (rel->type != VMI_RELOCATION_NONE) {			\
+		BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);	\
+		paravirt_ops.opname = (void *)rel->eip;		\
+	}							\
+} while (0)
+
+/*
+ * Activate the VMI interface and switch into paravirtualized mode
+ */
+static inline int __init activate_vmi(void)
+{
+	short kernel_cs;
+	u64 reloc;
+	const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
+
+	if (call_vrom_func(vmi_rom, vmi_init) != 0) {
+		printk(KERN_ERR "VMI ROM failed to initialize!");
+		return 0;
+	}
+	savesegment(cs, kernel_cs);
+
+	paravirt_ops.paravirt_enabled = 1;
+	paravirt_ops.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK;
+
+	paravirt_ops.patch = vmi_patch;
+	paravirt_ops.name = "vmi";
+
+	/*
+	 * Many of these operations are ABI compatible with VMI.
+	 * This means we can fill in the paravirt-ops with direct
+	 * pointers into the VMI ROM.  If the calling convention for
+	 * these operations changes, this code needs to be updated.
+	 *
+	 * Exceptions
+	 *  CPUID paravirt-op uses pointers, not the native ISA
+	 *  halt has no VMI equivalent; all VMI halts are "safe"
+	 *  no MSR support yet - just trap and emulate.  VMI uses the
+	 *    same ABI as the native ISA, but Linux wants exceptions
+	 *    from bogus MSR read / write handled
+	 *  rdpmc is not yet used in Linux
+	 */
+
+	/* CPUID is special, so very special */
+	reloc = call_vrom_long_func(vmi_rom, get_reloc,	VMI_CALL_CPUID);
+	if (rel->type != VMI_RELOCATION_NONE) {
+		BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
+		vmi_ops.cpuid = (void *)rel->eip;
+		paravirt_ops.cpuid = vmi_cpuid;
+	}
+
+	para_fill(clts, CLTS);
+	para_fill(get_debugreg, GetDR);
+	para_fill(set_debugreg, SetDR);
+	para_fill(read_cr0, GetCR0);
+	para_fill(read_cr2, GetCR2);
+	para_fill(read_cr3, GetCR3);
+	para_fill(read_cr4, GetCR4);
+	para_fill(write_cr0, SetCR0);
+	para_fill(write_cr2, SetCR2);
+	para_fill(write_cr3, SetCR3);
+	para_fill(write_cr4, SetCR4);
+	para_fill(save_fl, GetInterruptMask);
+	para_fill(restore_fl, SetInterruptMask);
+	para_fill(irq_disable, DisableInterrupts);
+	para_fill(irq_enable, EnableInterrupts);
+	/* irq_save_disable !!! sheer pain */
+	patch_offset(&irq_save_disable_callout[IRQ_PATCH_INT_MASK],
+		     (char *)paravirt_ops.save_fl);
+	patch_offset(&irq_save_disable_callout[IRQ_PATCH_DISABLE],
+		     (char *)paravirt_ops.irq_disable);
+#ifndef CONFIG_NO_IDLE_HZ
+	para_fill(safe_halt, Halt);
+#else
+	vmi_ops.halt = vmi_get_function(VMI_CALL_Halt);
+	paravirt_ops.safe_halt = vmi_safe_halt;
+#endif
+	para_fill(wbinvd, WBINVD);
+	/* paravirt_ops.read_msr = vmi_rdmsr */
+	/* paravirt_ops.write_msr = vmi_wrmsr */
+	para_fill(read_tsc, RDTSC);
+	/* paravirt_ops.rdpmc = vmi_rdpmc */
+
+	/* TR interface doesn't pass TR value */
+	reloc = call_vrom_long_func(vmi_rom, get_reloc,	VMI_CALL_SetTR);
+	if (rel->type != VMI_RELOCATION_NONE) {
+		BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
+		vmi_ops.set_tr = (void *)rel->eip;
+		paravirt_ops.load_tr_desc = vmi_set_tr;
+	}
+
+	/* LDT is special, too */
+	reloc = call_vrom_long_func(vmi_rom, get_reloc,	VMI_CALL_SetLDT);
+	if (rel->type != VMI_RELOCATION_NONE) {
+		BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
+		vmi_ops._set_ldt = (void *)rel->eip;
+		paravirt_ops.set_ldt = vmi_set_ldt;
+	}
+
+	para_fill(load_gdt, SetGDT);
+	para_fill(load_idt, SetIDT);
+	para_fill(store_gdt, GetGDT);
+	para_fill(store_idt, GetIDT);
+	para_fill(store_tr, GetTR);
+	paravirt_ops.load_tls = vmi_load_tls;
+	para_fill(write_ldt_entry, WriteLDTEntry);
+	para_fill(write_gdt_entry, WriteGDTEntry);
+	para_fill(write_idt_entry, WriteIDTEntry);
+	reloc = call_vrom_long_func(vmi_rom, get_reloc,
+				    VMI_CALL_UpdateKernelStack);
+	if (rel->type != VMI_RELOCATION_NONE) {
+		BUG_ON(rel->type != VMI_RELOCATION_CALL_REL);
+		vmi_ops.set_kernel_stack = (void *)rel->eip;
+		paravirt_ops.load_esp0 = vmi_load_esp0;
+	}
+
+	para_fill(set_iopl_mask, SetIOPLMask);
+	paravirt_ops.io_delay = (void *)vmi_nop;
+	if (!disable_nodelay) {
+		paravirt_ops.const_udelay = (void *)vmi_nop;
+	}
+
+	para_fill(set_lazy_mode, SetLazyMode);
+
+	reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_FlushTLB);
+	if (rel->type != VMI_RELOCATION_NONE) {
+		vmi_ops.flush_tlb = (void *)rel->eip;
+		paravirt_ops.flush_tlb_user = vmi_flush_tlb_user;
+		paravirt_ops.flush_tlb_kernel = vmi_flush_tlb_kernel;
+	}
+	para_fill(flush_tlb_single, InvalPage);
+
+	/*
+	 * Until a standard flag format can be agreed on, we need to
+	 * implement these as wrappers in Linux.  Get the VMI ROM
+	 * function pointers for the two backend calls.
+	 */
+#ifdef CONFIG_X86_PAE
+	vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxELong);
+	vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxELong);
+#else
+	vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxE);
+	vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxE);
+#endif
+	vmi_ops.set_linear_mapping = vmi_get_function(VMI_CALL_SetLinearMapping);
+	vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
+	vmi_ops.release_page = vmi_get_function(VMI_CALL_ReleasePage);
+
+	paravirt_ops.alloc_pt = vmi_allocate_pt;
+	paravirt_ops.alloc_pd = vmi_allocate_pd;
+	paravirt_ops.alloc_pd_clone = vmi_allocate_pd_clone;
+	paravirt_ops.release_pt = vmi_release_pt;
+	paravirt_ops.release_pd = vmi_release_pd;
+	paravirt_ops.set_pte = vmi_set_pte;
+	paravirt_ops.set_pte_at = vmi_set_pte_at;
+	paravirt_ops.set_pmd = vmi_set_pmd;
+	paravirt_ops.pte_update = vmi_update_pte;
+	paravirt_ops.pte_update_defer = vmi_update_pte_defer;
+#ifdef CONFIG_X86_PAE
+	paravirt_ops.set_pte_atomic = vmi_set_pte_atomic;
+	paravirt_ops.set_pte_present = vmi_set_pte_present;
+	paravirt_ops.set_pud = vmi_set_pud;
+	paravirt_ops.pte_clear = vmi_pte_clear;
+	paravirt_ops.pmd_clear = vmi_pmd_clear;
+#endif
+	/*
+	 * These MUST always be patched.  Don't support indirect jumps
+	 * through these operations, as the VMI interface may use either
+	 * a jump or a call to get to these operations, depending on
+	 * the backend.  They are performance critical anyway, so requiring
+	 * a patch is not a big problem.
+	 */
+	paravirt_ops.irq_enable_sysexit = (void *)0xfeedbab0;
+	paravirt_ops.iret = (void *)0xbadbab0;
+
+#ifdef CONFIG_SMP
+	paravirt_ops.startup_ipi_hook = vmi_startup_ipi_hook;
+	vmi_ops.set_initial_ap_state = vmi_get_function(VMI_CALL_SetInitialAPState);
+#endif
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	paravirt_ops.apic_read = vmi_get_function(VMI_CALL_APICRead);
+	paravirt_ops.apic_write = vmi_get_function(VMI_CALL_APICWrite);
+	paravirt_ops.apic_write_atomic = vmi_get_function(VMI_CALL_APICWrite);
+#endif
+
+	/*
+	 * Check for VMI timer functionality by probing for a cycle frequency method
+	 */
+	reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_GetCycleFrequency);
+	if (rel->type != VMI_RELOCATION_NONE) {
+		vmi_timer_ops.get_cycle_frequency = (void *)rel->eip;
+		vmi_timer_ops.get_cycle_counter =
+			vmi_get_function(VMI_CALL_GetCycleCounter);
+		vmi_timer_ops.get_wallclock =
+			vmi_get_function(VMI_CALL_GetWallclockTime);
+		vmi_timer_ops.wallclock_updated =
+			vmi_get_function(VMI_CALL_WallclockUpdated);
+		vmi_timer_ops.set_alarm = vmi_get_function(VMI_CALL_SetAlarm);
+		vmi_timer_ops.cancel_alarm =
+			 vmi_get_function(VMI_CALL_CancelAlarm);
+		paravirt_ops.time_init = vmi_time_init;
+		paravirt_ops.get_wallclock = vmi_get_wallclock;
+		paravirt_ops.set_wallclock = vmi_set_wallclock;
+#ifdef CONFIG_X86_LOCAL_APIC
+		paravirt_ops.setup_boot_clock = vmi_timer_setup_boot_alarm;
+		paravirt_ops.setup_secondary_clock = vmi_timer_setup_secondary_alarm;
+#endif
+		custom_sched_clock = vmi_sched_clock;
+	}
+
+	/*
+	 * Alternative instruction rewriting doesn't happen soon enough
+	 * to convert VMI_IRET to a call instead of a jump; so we have
+	 * to do this before IRQs get reenabled.  Fortunately, it is
+	 * idempotent.
+	 */
+	apply_paravirt(__start_parainstructions, __stop_parainstructions);
+
+	vmi_bringup();
+
+	return 1;
+}
+
+#undef para_fill
+
+void __init vmi_init(void)
+{
+	unsigned long flags;
+
+	if (!vmi_rom)
+		probe_vmi_rom();
+	else
+		check_vmi_rom(vmi_rom);
+
+	/* In case probing for or validating the ROM failed, basil */
+	if (!vmi_rom)
+		return;
+
+	reserve_top_address(-vmi_rom->virtual_top);
+
+	local_irq_save(flags);
+	activate_vmi();
+#ifdef CONFIG_SMP
+	no_timer_check = 1;
+#endif
+	local_irq_restore(flags & X86_EFLAGS_IF);
+}
+
+static int __init parse_vmi(char *arg)
+{
+	if (!arg)
+		return -EINVAL;
+
+	if (!strcmp(arg, "disable_nodelay"))
+		disable_nodelay = 1;
+	else if (!strcmp(arg, "disable_pge")) {
+		clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
+		disable_pge = 1;
+	} else if (!strcmp(arg, "disable_pse")) {
+		clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+		disable_pse = 1;
+	} else if (!strcmp(arg, "disable_sep")) {
+		clear_bit(X86_FEATURE_SEP, boot_cpu_data.x86_capability);
+		disable_sep = 1;
+	} else if (!strcmp(arg, "disable_tsc")) {
+		clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
+		disable_tsc = 1;
+	} else if (!strcmp(arg, "disable_mtrr")) {
+		clear_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability);
+		disable_mtrr = 1;
+	}
+	return 0;
+}
+
+early_param("vmi", parse_vmi);
diff --git a/arch/i386/kernel/vmitime.c b/arch/i386/kernel/vmitime.c
new file mode 100644
index 0000000..76d2adc
--- /dev/null
+++ b/arch/i386/kernel/vmitime.c
@@ -0,0 +1,499 @@
+/*
+ * VMI paravirtual timer support routines.
+ *
+ * Copyright (C) 2005, VMware, 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to dhecht@vmware.com
+ *
+ */
+
+/*
+ * Portions of this code from arch/i386/kernel/timers/timer_tsc.c.
+ * Portions of the CONFIG_NO_IDLE_HZ code from arch/s390/kernel/time.c.
+ * See comments there for proper credits.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/rcupdate.h>
+#include <linux/clocksource.h>
+
+#include <asm/timer.h>
+#include <asm/io.h>
+#include <asm/apic.h>
+#include <asm/div64.h>
+#include <asm/timer.h>
+#include <asm/desc.h>
+
+#include <asm/vmi.h>
+#include <asm/vmi_time.h>
+
+#include <mach_timer.h>
+#include <io_ports.h>
+
+#ifdef CONFIG_X86_LOCAL_APIC
+#define VMI_ALARM_WIRING VMI_ALARM_WIRED_LVTT
+#else
+#define VMI_ALARM_WIRING VMI_ALARM_WIRED_IRQ0
+#endif
+
+/* Cached VMI operations */
+struct vmi_timer_ops vmi_timer_ops;
+
+#ifdef CONFIG_NO_IDLE_HZ
+
+/* /proc/sys/kernel/hz_timer state. */
+int sysctl_hz_timer;
+
+/* Some stats */
+static DEFINE_PER_CPU(unsigned long, vmi_idle_no_hz_irqs);
+static DEFINE_PER_CPU(unsigned long, vmi_idle_no_hz_jiffies);
+static DEFINE_PER_CPU(unsigned long, idle_start_jiffies);
+
+#endif /* CONFIG_NO_IDLE_HZ */
+
+/* Number of alarms per second. By default this is CONFIG_VMI_ALARM_HZ. */
+static int alarm_hz = CONFIG_VMI_ALARM_HZ;
+
+/* Cache of the value get_cycle_frequency / HZ. */
+static signed long long cycles_per_jiffy;
+
+/* Cache of the value get_cycle_frequency / alarm_hz. */
+static signed long long cycles_per_alarm;
+
+/* The number of cycles accounted for by the 'jiffies'/'xtime' count.
+ * Protected by xtime_lock. */
+static unsigned long long real_cycles_accounted_system;
+
+/* The number of cycles accounted for by update_process_times(), per cpu. */
+static DEFINE_PER_CPU(unsigned long long, process_times_cycles_accounted_cpu);
+
+/* The number of stolen cycles accounted, per cpu. */
+static DEFINE_PER_CPU(unsigned long long, stolen_cycles_accounted_cpu);
+
+/* Clock source. */
+static cycle_t read_real_cycles(void)
+{
+	return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
+}
+
+static cycle_t read_available_cycles(void)
+{
+	return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE);
+}
+
+#if 0
+static cycle_t read_stolen_cycles(void)
+{
+	return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_STOLEN);
+}
+#endif  /*  0  */
+
+static struct clocksource clocksource_vmi = {
+	.name			= "vmi-timer",
+	.rating			= 450,
+	.read			= read_real_cycles,
+	.mask			= CLOCKSOURCE_MASK(64),
+	.mult			= 0, /* to be set */
+	.shift			= 22,
+	.flags			= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+
+/* Timer interrupt handler. */
+static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id);
+
+static struct irqaction vmi_timer_irq  = {
+	vmi_timer_interrupt,
+	SA_INTERRUPT,
+	CPU_MASK_NONE,
+	"VMI-alarm",
+	NULL,
+	NULL
+};
+
+/* Alarm rate */
+static int __init vmi_timer_alarm_rate_setup(char* str)
+{
+	int alarm_rate;
+	if (get_option(&str, &alarm_rate) == 1 && alarm_rate > 0) {
+		alarm_hz = alarm_rate;
+		printk(KERN_WARNING "VMI timer alarm HZ set to %d\n", alarm_hz);
+	}
+	return 1;
+}
+__setup("vmi_timer_alarm_hz=", vmi_timer_alarm_rate_setup);
+
+
+/* Initialization */
+static void vmi_get_wallclock_ts(struct timespec *ts)
+{
+	unsigned long long wallclock;
+	wallclock = vmi_timer_ops.get_wallclock(); // nsec units
+	ts->tv_nsec = do_div(wallclock, 1000000000);
+	ts->tv_sec = wallclock;
+}
+
+static void update_xtime_from_wallclock(void)
+{
+	struct timespec ts;
+	vmi_get_wallclock_ts(&ts);
+	do_settimeofday(&ts);
+}
+
+unsigned long vmi_get_wallclock(void)
+{
+	struct timespec ts;
+	vmi_get_wallclock_ts(&ts);
+	return ts.tv_sec;
+}
+
+int vmi_set_wallclock(unsigned long now)
+{
+	return -1;
+}
+
+unsigned long long vmi_sched_clock(void)
+{
+	return read_available_cycles();
+}
+
+void __init vmi_time_init(void)
+{
+	unsigned long long cycles_per_sec, cycles_per_msec;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	setup_irq(0, &vmi_timer_irq);
+#ifdef CONFIG_X86_LOCAL_APIC
+	set_intr_gate(LOCAL_TIMER_VECTOR, apic_vmi_timer_interrupt);
+#endif
+
+	no_sync_cmos_clock = 1;
+
+	vmi_get_wallclock_ts(&xtime);
+	set_normalized_timespec(&wall_to_monotonic,
+		-xtime.tv_sec, -xtime.tv_nsec);
+
+	real_cycles_accounted_system = read_real_cycles();
+	update_xtime_from_wallclock();
+	per_cpu(process_times_cycles_accounted_cpu, 0) = read_available_cycles();
+
+	cycles_per_sec = vmi_timer_ops.get_cycle_frequency();
+
+	cycles_per_jiffy = cycles_per_sec;
+	(void)do_div(cycles_per_jiffy, HZ);
+	cycles_per_alarm = cycles_per_sec;
+	(void)do_div(cycles_per_alarm, alarm_hz);
+	cycles_per_msec = cycles_per_sec;
+	(void)do_div(cycles_per_msec, 1000);
+	cpu_khz = cycles_per_msec;
+
+	printk(KERN_WARNING "VMI timer cycles/sec = %llu ; cycles/jiffy = %llu ;"
+	       "cycles/alarm = %llu\n", cycles_per_sec, cycles_per_jiffy,
+	       cycles_per_alarm);
+
+	clocksource_vmi.mult = clocksource_khz2mult(cycles_per_msec,
+						    clocksource_vmi.shift);
+	if (clocksource_register(&clocksource_vmi))
+		printk(KERN_WARNING "Error registering VMITIME clocksource.");
+
+	/* Disable PIT. */
+	outb_p(0x3a, PIT_MODE); /* binary, mode 5, LSB/MSB, ch 0 */
+
+	/* schedule the alarm. do this in phase with process_times_cycles_accounted_cpu
+	 * reduce the latency calling update_process_times. */
+	vmi_timer_ops.set_alarm(
+		      VMI_ALARM_WIRED_IRQ0 | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
+		      per_cpu(process_times_cycles_accounted_cpu, 0) + cycles_per_alarm,
+		      cycles_per_alarm);
+
+	local_irq_restore(flags);
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+
+void __init vmi_timer_setup_boot_alarm(void)
+{
+	local_irq_disable();
+
+	/* Route the interrupt to the correct vector. */
+	apic_write_around(APIC_LVTT, LOCAL_TIMER_VECTOR);
+
+	/* Cancel the IRQ0 wired alarm, and setup the LVTT alarm. */
+	vmi_timer_ops.cancel_alarm(VMI_CYCLES_AVAILABLE);
+	vmi_timer_ops.set_alarm(
+		      VMI_ALARM_WIRED_LVTT | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
+		      per_cpu(process_times_cycles_accounted_cpu, 0) + cycles_per_alarm,
+		      cycles_per_alarm);
+	local_irq_enable();
+}
+
+/* Initialize the time accounting variables for an AP on an SMP system.
+ * Also, set the local alarm for the AP. */
+void __init vmi_timer_setup_secondary_alarm(void)
+{
+	int cpu = smp_processor_id();
+
+	/* Route the interrupt to the correct vector. */
+	apic_write_around(APIC_LVTT, LOCAL_TIMER_VECTOR);
+
+	per_cpu(process_times_cycles_accounted_cpu, cpu) = read_available_cycles();
+
+	vmi_timer_ops.set_alarm(
+		      VMI_ALARM_WIRED_LVTT | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
+		      per_cpu(process_times_cycles_accounted_cpu, cpu) + cycles_per_alarm,
+		      cycles_per_alarm);
+}
+
+#endif
+
+/* Update system wide (real) time accounting (e.g. jiffies, xtime). */
+static void vmi_account_real_cycles(unsigned long long cur_real_cycles)
+{
+	long long cycles_not_accounted;
+
+	write_seqlock(&xtime_lock);
+
+	cycles_not_accounted = cur_real_cycles - real_cycles_accounted_system;
+	while (cycles_not_accounted >= cycles_per_jiffy) {
+		/* systems wide jiffies and wallclock. */
+		do_timer(1);
+
+		cycles_not_accounted -= cycles_per_jiffy;
+		real_cycles_accounted_system += cycles_per_jiffy;
+	}
+
+	if (vmi_timer_ops.wallclock_updated())
+		update_xtime_from_wallclock();
+
+	write_sequnlock(&xtime_lock);
+}
+
+/* Update per-cpu process times. */
+static void vmi_account_process_times_cycles(struct pt_regs *regs, int cpu,
+					     unsigned long long cur_process_times_cycles)
+{
+	long long cycles_not_accounted;
+	cycles_not_accounted = cur_process_times_cycles -
+		per_cpu(process_times_cycles_accounted_cpu, cpu);
+
+	while (cycles_not_accounted >= cycles_per_jiffy) {
+		/* Account time to the current process.  This includes
+		 * calling into the scheduler to decrement the timeslice
+		 * and possibly reschedule.*/
+		update_process_times(user_mode(regs));
+		/* XXX handle /proc/profile multiplier.  */
+		profile_tick(CPU_PROFILING);
+
+		cycles_not_accounted -= cycles_per_jiffy;
+		per_cpu(process_times_cycles_accounted_cpu, cpu) += cycles_per_jiffy;
+	}
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+/* Update per-cpu idle times.  Used when a no-hz halt is ended. */
+static void vmi_account_no_hz_idle_cycles(int cpu,
+					  unsigned long long cur_process_times_cycles)
+{
+	long long cycles_not_accounted;
+	unsigned long no_idle_hz_jiffies = 0;
+
+	cycles_not_accounted = cur_process_times_cycles -
+		per_cpu(process_times_cycles_accounted_cpu, cpu);
+
+	while (cycles_not_accounted >= cycles_per_jiffy) {
+		no_idle_hz_jiffies++;
+		cycles_not_accounted -= cycles_per_jiffy;
+		per_cpu(process_times_cycles_accounted_cpu, cpu) += cycles_per_jiffy;
+	}
+	/* Account time to the idle process. */
+	account_steal_time(idle_task(cpu), jiffies_to_cputime(no_idle_hz_jiffies));
+}
+#endif
+
+/* Update per-cpu stolen time. */
+static void vmi_account_stolen_cycles(int cpu,
+				      unsigned long long cur_real_cycles,
+				      unsigned long long cur_avail_cycles)
+{
+	long long stolen_cycles_not_accounted;
+	unsigned long stolen_jiffies = 0;
+
+	if (cur_real_cycles < cur_avail_cycles)
+		return;
+
+	stolen_cycles_not_accounted = cur_real_cycles - cur_avail_cycles -
+		per_cpu(stolen_cycles_accounted_cpu, cpu);
+
+	while (stolen_cycles_not_accounted >= cycles_per_jiffy) {
+		stolen_jiffies++;
+		stolen_cycles_not_accounted -= cycles_per_jiffy;
+		per_cpu(stolen_cycles_accounted_cpu, cpu) += cycles_per_jiffy;
+	}
+	/* HACK: pass NULL to force time onto cpustat->steal. */
+	account_steal_time(NULL, jiffies_to_cputime(stolen_jiffies));
+}
+
+/* Body of either IRQ0 interrupt handler (UP no local-APIC) or
+ * local-APIC LVTT interrupt handler (UP & local-APIC or SMP). */
+static void vmi_local_timer_interrupt(int cpu)
+{
+	unsigned long long cur_real_cycles, cur_process_times_cycles;
+
+	cur_real_cycles = read_real_cycles();
+	cur_process_times_cycles = read_available_cycles();
+	/* Update system wide (real) time state (xtime, jiffies). */
+	vmi_account_real_cycles(cur_real_cycles);
+	/* Update per-cpu process times. */
+	vmi_account_process_times_cycles(get_irq_regs(), cpu, cur_process_times_cycles);
+        /* Update time stolen from this cpu by the hypervisor. */
+	vmi_account_stolen_cycles(cpu, cur_real_cycles, cur_process_times_cycles);
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+
+/* Must be called only from idle loop, with interrupts disabled. */
+int vmi_stop_hz_timer(void)
+{
+	/* Note that cpu_set, cpu_clear are (SMP safe) atomic on x86. */
+
+	unsigned long seq, next;
+	unsigned long long real_cycles_expiry;
+	int cpu = smp_processor_id();
+	int idle;
+
+	BUG_ON(!irqs_disabled());
+	if (sysctl_hz_timer != 0)
+		return 0;
+
+	cpu_set(cpu, nohz_cpu_mask);
+	smp_mb();
+	if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
+	    (next = next_timer_interrupt(), time_before_eq(next, jiffies))) {
+		cpu_clear(cpu, nohz_cpu_mask);
+		next = jiffies;
+		idle = 0;
+	} else
+		idle = 1;
+
+	/* Convert jiffies to the real cycle counter. */
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		real_cycles_expiry = real_cycles_accounted_system +
+			(long)(next - jiffies) * cycles_per_jiffy;
+	} while (read_seqretry(&xtime_lock, seq));
+
+	/* This cpu is going idle. Disable the periodic alarm. */
+	if (idle) {
+		vmi_timer_ops.cancel_alarm(VMI_CYCLES_AVAILABLE);
+		per_cpu(idle_start_jiffies, cpu) = jiffies;
+	}
+
+	/* Set the real time alarm to expire at the next event. */
+	vmi_timer_ops.set_alarm(
+		      VMI_ALARM_WIRING | VMI_ALARM_IS_ONESHOT | VMI_CYCLES_REAL,
+		      real_cycles_expiry, 0);
+
+	return idle;
+}
+
+static void vmi_reenable_hz_timer(int cpu)
+{
+	/* For /proc/vmi/info idle_hz stat. */
+	per_cpu(vmi_idle_no_hz_jiffies, cpu) += jiffies - per_cpu(idle_start_jiffies, cpu);
+	per_cpu(vmi_idle_no_hz_irqs, cpu)++;
+
+	/* Don't bother explicitly cancelling the one-shot alarm -- at
+	 * worse we will receive a spurious timer interrupt. */
+	vmi_timer_ops.set_alarm(
+		      VMI_ALARM_WIRING | VMI_ALARM_IS_PERIODIC | VMI_CYCLES_AVAILABLE,
+		      per_cpu(process_times_cycles_accounted_cpu, cpu) + cycles_per_alarm,
+		      cycles_per_alarm);
+	/* Indicate this cpu is no longer nohz idle. */
+	cpu_clear(cpu, nohz_cpu_mask);
+}
+
+/* Called from interrupt handlers when (local) HZ timer is disabled. */
+void vmi_account_time_restart_hz_timer(void)
+{
+	unsigned long long cur_real_cycles, cur_process_times_cycles;
+	int cpu = smp_processor_id();
+
+	BUG_ON(!irqs_disabled());
+	/* Account the time during which the HZ timer was disabled. */
+	cur_real_cycles = read_real_cycles();
+	cur_process_times_cycles = read_available_cycles();
+	/* Update system wide (real) time state (xtime, jiffies). */
+	vmi_account_real_cycles(cur_real_cycles);
+	/* Update per-cpu idle times. */
+	vmi_account_no_hz_idle_cycles(cpu, cur_process_times_cycles);
+        /* Update time stolen from this cpu by the hypervisor. */
+	vmi_account_stolen_cycles(cpu, cur_real_cycles, cur_process_times_cycles);
+	/* Reenable the hz timer. */
+	vmi_reenable_hz_timer(cpu);
+}
+
+#endif /* CONFIG_NO_IDLE_HZ */
+
+/* UP (and no local-APIC) VMI-timer alarm interrupt handler.
+ * Handler for IRQ0. Not used when SMP or X86_LOCAL_APIC after
+ * APIC setup and setup_boot_vmi_alarm() is called.  */
+static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id)
+{
+	vmi_local_timer_interrupt(smp_processor_id());
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+
+/* SMP VMI-timer alarm interrupt handler. Handler for LVTT vector.
+ * Also used in UP when CONFIG_X86_LOCAL_APIC.
+ * The wrapper code is from arch/i386/kernel/apic.c#smp_apic_timer_interrupt. */
+void smp_apic_vmi_timer_interrupt(struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+	int cpu = smp_processor_id();
+
+	/*
+	 * the NMI deadlock-detector uses this.
+	 */
+        per_cpu(irq_stat,cpu).apic_timer_irqs++;
+
+	/*
+	 * NOTE! We'd better ACK the irq immediately,
+	 * because timer handling can be slow.
+	 */
+	ack_APIC_irq();
+
+	/*
+	 * update_process_times() expects us to have done irq_enter().
+	 * Besides, if we don't timer interrupts ignore the global
+	 * interrupt lock, which is the WrongThing (tm) to do.
+	 */
+	irq_enter();
+	vmi_local_timer_interrupt(cpu);
+	irq_exit();
+	set_irq_regs(old_regs);
+}
+
+#endif  /* CONFIG_X86_LOCAL_APIC */
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index a53c8b1..ca516109 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -37,9 +37,14 @@
 {
   . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
   phys_startup_32 = startup_32 - LOAD_OFFSET;
+
+  .text.head : AT(ADDR(.text.head) - LOAD_OFFSET) {
+  	_text = .;			/* Text and read-only data */
+	*(.text.head)
+  } :text = 0x9090
+
   /* read-only */
   .text : AT(ADDR(.text) - LOAD_OFFSET) {
-  	_text = .;			/* Text and read-only data */
 	*(.text)
 	SCHED_TEXT
 	LOCK_TEXT
@@ -181,12 +186,14 @@
      from .altinstructions and .eh_frame */
   .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
   .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
+#if defined(CONFIG_BLK_DEV_INITRD)
   . = ALIGN(4096);
   .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
 	__initramfs_start = .;
 	*(.init.ramfs)
 	__initramfs_end = .;
   }
+#endif
   . = ALIGN(L1_CACHE_BYTES);
   .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) {
 	__per_cpu_start = .;
diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c
index cc2f519..c788162 100644
--- a/arch/i386/mach-default/setup.c
+++ b/arch/i386/mach-default/setup.c
@@ -79,7 +79,12 @@
 {
 }
 
-static struct irqaction irq0  = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL};
+static struct irqaction irq0  = {
+	.handler = timer_interrupt,
+	.flags = IRQF_DISABLED | IRQF_NOBALANCING,
+	.mask = CPU_MASK_NONE,
+	.name = "timer"
+};
 
 /**
  * time_init_hook - do any specific initialisations for the system timer.
@@ -90,6 +95,7 @@
  **/
 void __init time_init_hook(void)
 {
+	irq0.mask = cpumask_of_cpu(0);
 	setup_irq(0, &irq0);
 }
 
diff --git a/arch/i386/math-emu/get_address.c b/arch/i386/math-emu/get_address.c
index 9819b70..2e2c51a 100644
--- a/arch/i386/math-emu/get_address.c
+++ b/arch/i386/math-emu/get_address.c
@@ -56,15 +56,14 @@
 #define VM86_REG_(x) (*(unsigned short *) \
 		      (reg_offset_vm86[((unsigned)x)]+(u_char *) FPU_info))
 
-/* These are dummy, fs and gs are not saved on the stack. */
-#define ___FS ___ds
+/* This dummy, gs is not saved on the stack. */
 #define ___GS ___ds
 
 static int reg_offset_pm[] = {
 	offsetof(struct info,___cs),
 	offsetof(struct info,___ds),
 	offsetof(struct info,___es),
-	offsetof(struct info,___FS),
+	offsetof(struct info,___fs),
 	offsetof(struct info,___GS),
 	offsetof(struct info,___ss),
 	offsetof(struct info,___ds)
@@ -169,13 +168,10 @@
 
   switch ( segment )
     {
-      /* fs and gs aren't used by the kernel, so they still have their
-	 user-space values. */
-    case PREFIX_FS_-1:
-      /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */
-      savesegment(fs, addr->selector);
-      break;
+      /* gs isn't used by the kernel, so it still has its
+	 user-space value. */
     case PREFIX_GS_-1:
+      /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */
       savesegment(gs, addr->selector);
       break;
     default:
diff --git a/arch/i386/math-emu/status_w.h b/arch/i386/math-emu/status_w.h
index 78d7b76..59e7330 100644
--- a/arch/i386/math-emu/status_w.h
+++ b/arch/i386/math-emu/status_w.h
@@ -48,9 +48,11 @@
 
 #define status_word() \
   ((partial_status & ~SW_Top & 0xffff) | ((top << SW_Top_Shift) & SW_Top))
-#define setcc(cc) ({ \
-  partial_status &= ~(SW_C0|SW_C1|SW_C2|SW_C3); \
-  partial_status |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3); })
+static inline void setcc(int cc)
+{
+	partial_status &= ~(SW_C0|SW_C1|SW_C2|SW_C3);
+	partial_status |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3);
+}
 
 #ifdef PECULIAR_486
    /* Default, this conveys no information, but an 80486 does it. */
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index e0c390d..aa58720 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -101,7 +101,6 @@
 extern void add_one_highpage_init(struct page *, int, int);
 
 extern struct e820map e820;
-extern unsigned long init_pg_tables_end;
 extern unsigned long highend_pfn, highstart_pfn;
 extern unsigned long max_low_pfn;
 extern unsigned long totalram_pages;
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index aaaa4d2..b8c4e25 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -46,43 +46,17 @@
 }
 EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
 
-static inline int notify_page_fault(enum die_val val, const char *str,
-			struct pt_regs *regs, long err, int trap, int sig)
+static inline int notify_page_fault(struct pt_regs *regs, long err)
 {
 	struct die_args args = {
 		.regs = regs,
-		.str = str,
+		.str = "page fault",
 		.err = err,
-		.trapnr = trap,
-		.signr = sig
+		.trapnr = 14,
+		.signr = SIGSEGV
 	};
-	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
-}
-
-/*
- * Unlock any spinlocks which will prevent us from getting the
- * message out 
- */
-void bust_spinlocks(int yes)
-{
-	int loglevel_save = console_loglevel;
-
-	if (yes) {
-		oops_in_progress = 1;
-		return;
-	}
-#ifdef CONFIG_VT
-	unblank_screen();
-#endif
-	oops_in_progress = 0;
-	/*
-	 * OK, the message is on the console.  Now we call printk()
-	 * without oops_in_progress set so that printk will give klogd
-	 * a poke.  Hold onto your hats...
-	 */
-	console_loglevel = 15;		/* NMI oopser may have shut the console up */
-	printk(" ");
-	console_loglevel = loglevel_save;
+	return atomic_notifier_call_chain(&notify_page_fault_chain,
+	                                  DIE_PAGE_FAULT, &args);
 }
 
 /*
@@ -353,8 +327,7 @@
 	if (unlikely(address >= TASK_SIZE)) {
 		if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0)
 			return;
-		if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-						SIGSEGV) == NOTIFY_STOP)
+		if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
 			return;
 		/*
 		 * Don't take the mm semaphore here. If we fixup a prefetch
@@ -363,8 +336,7 @@
 		goto bad_area_nosemaphore;
 	}
 
-	if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-					SIGSEGV) == NOTIFY_STOP)
+	if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
 		return;
 
 	/* It's safe to allow irq's after cr2 has been saved and the vmalloc
diff --git a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c
index e0fa6cb..bb2de10 100644
--- a/arch/i386/mm/highmem.c
+++ b/arch/i386/mm/highmem.c
@@ -33,13 +33,14 @@
 
 	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
 	pagefault_disable();
+
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	BUG_ON(!pte_none(*(kmap_pte-idx)));
+
 	if (!PageHighMem(page))
 		return page_address(page);
 
-	idx = type + KM_TYPE_NR*smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-	if (!pte_none(*(kmap_pte-idx)))
-		BUG();
 	set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
 
 	return (void*) vaddr;
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index c5c5ea7..ae43688 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -62,6 +62,7 @@
 		
 #ifdef CONFIG_X86_PAE
 	pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+	paravirt_alloc_pd(__pa(pmd_table) >> PAGE_SHIFT);
 	set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
 	pud = pud_offset(pgd, 0);
 	if (pmd_table != pmd_offset(pud, 0)) 
@@ -82,6 +83,7 @@
 {
 	if (pmd_none(*pmd)) {
 		pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+		paravirt_alloc_pt(__pa(page_table) >> PAGE_SHIFT);
 		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
 		if (page_table != pte_offset_kernel(pmd, 0))
 			BUG();	
@@ -345,6 +347,8 @@
 	/* Init entries of the first-level page table to the zero page */
 	for (i = 0; i < PTRS_PER_PGD; i++)
 		set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
+#else
+	paravirt_alloc_pd(__pa(swapper_pg_dir) >> PAGE_SHIFT);
 #endif
 
 	/* Enable PSE if available */
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index ad91528..412ebbd 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -60,6 +60,7 @@
 	address = __pa(address);
 	addr = address & LARGE_PAGE_MASK; 
 	pbase = (pte_t *)page_address(base);
+	paravirt_alloc_pt(page_to_pfn(base));
 	for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
                set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT,
                                           addr == address ? prot : ref_prot));
@@ -172,6 +173,7 @@
 	if (!PageReserved(kpte_page)) {
 		if (cpu_has_pse && (page_private(kpte_page) == 0)) {
 			ClearPagePrivate(kpte_page);
+			paravirt_release_pt(page_to_pfn(kpte_page));
 			list_add(&kpte_page->lru, &df_list);
 			revert_page(kpte_page, address);
 		}
@@ -224,7 +226,7 @@
 	list_replace_init(&df_list, &l);
 	spin_unlock_irq(&cpa_lock);
 	if (!cpu_has_clflush)
-		flush_map(0);
+		flush_map(NULL);
 	list_for_each_entry_safe(pg, next, &l, lru) {
 		if (cpu_has_clflush)
 			flush_map(page_address(pg));
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index f349eaf..fa0cfbd 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -171,6 +171,8 @@
 void reserve_top_address(unsigned long reserve)
 {
 	BUG_ON(fixmaps > 0);
+	printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
+	       (int)-reserve);
 #ifdef CONFIG_COMPAT_VDSO
 	BUG_ON(reserve != 0);
 #else
@@ -248,9 +250,15 @@
 	clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
 			swapper_pg_dir + USER_PTRS_PER_PGD,
 			KERNEL_PGD_PTRS);
+
 	if (PTRS_PER_PMD > 1)
 		return;
 
+	/* must happen under lock */
+	paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
+			__pa(swapper_pg_dir) >> PAGE_SHIFT,
+			USER_PTRS_PER_PGD, PTRS_PER_PGD - USER_PTRS_PER_PGD);
+
 	pgd_list_add(pgd);
 	spin_unlock_irqrestore(&pgd_lock, flags);
 }
@@ -260,6 +268,7 @@
 {
 	unsigned long flags; /* can be called from interrupt context */
 
+	paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT);
 	spin_lock_irqsave(&pgd_lock, flags);
 	pgd_list_del(pgd);
 	spin_unlock_irqrestore(&pgd_lock, flags);
@@ -277,13 +286,18 @@
 		pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
 		if (!pmd)
 			goto out_oom;
+		paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT);
 		set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
 	}
 	return pgd;
 
 out_oom:
-	for (i--; i >= 0; i--)
-		kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
+	for (i--; i >= 0; i--) {
+		pgd_t pgdent = pgd[i];
+		void* pmd = (void *)__va(pgd_val(pgdent)-1);
+		paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+		kmem_cache_free(pmd_cache, pmd);
+	}
 	kmem_cache_free(pgd_cache, pgd);
 	return NULL;
 }
@@ -294,8 +308,12 @@
 
 	/* in the PAE case user pgd entries are overwritten before usage */
 	if (PTRS_PER_PMD > 1)
-		for (i = 0; i < USER_PTRS_PER_PGD; ++i)
-			kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
+		for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
+			pgd_t pgdent = pgd[i];
+			void* pmd = (void *)__va(pgd_val(pgdent)-1);
+			paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+			kmem_cache_free(pmd_cache, pmd);
+		}
 	/* in the non-PAE case, free_pgtables() clears user pgd entries */
 	kmem_cache_free(pgd_cache, pgd);
 }
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index 3700eef..8fda7be 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -63,7 +63,7 @@
 };
 
 
-static int __init init_driverfs(void)
+static int __init init_sysfs(void)
 {
 	int error;
 	if (!(error = sysdev_class_register(&oprofile_sysclass)))
@@ -72,15 +72,15 @@
 }
 
 
-static void exit_driverfs(void)
+static void exit_sysfs(void)
 {
 	sysdev_unregister(&device_oprofile);
 	sysdev_class_unregister(&oprofile_sysclass);
 }
 
 #else
-#define init_driverfs() do { } while (0)
-#define exit_driverfs() do { } while (0)
+#define init_sysfs() do { } while (0)
+#define exit_sysfs() do { } while (0)
 #endif /* CONFIG_PM */
 
 static int profile_exceptions_notify(struct notifier_block *self,
@@ -385,7 +385,7 @@
 	return 1;
 }
 
-/* in order to get driverfs right */
+/* in order to get sysfs right */
 static int using_nmi;
 
 int __init op_nmi_init(struct oprofile_operations *ops)
@@ -440,7 +440,7 @@
 			return -ENODEV;
 	}
 
-	init_driverfs();
+	init_sysfs();
 	using_nmi = 1;
 	ops->create_files = nmi_create_files;
 	ops->setup = nmi_setup;
@@ -456,5 +456,5 @@
 void op_nmi_exit(void)
 {
 	if (using_nmi)
-		exit_driverfs();
+		exit_sysfs();
 }
diff --git a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c
index ca2447e..c554f52 100644
--- a/arch/i386/oprofile/op_model_ppro.c
+++ b/arch/i386/oprofile/op_model_ppro.c
@@ -24,7 +24,8 @@
 
 #define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
 #define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0)
-#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), -1);} while (0)
+#define CTR_32BIT_WRITE(l,msrs,c)	\
+	do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), 0);} while (0)
 #define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
 
 #define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
@@ -79,7 +80,7 @@
 	for (i = 0; i < NUM_COUNTERS; ++i) {
 		if (unlikely(!CTR_IS_RESERVED(msrs,i)))
 			continue;
-		CTR_WRITE(1, msrs, i);
+		CTR_32BIT_WRITE(1, msrs, i);
 	}
 
 	/* enable active counters */
@@ -87,7 +88,7 @@
 		if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs,i))) {
 			reset_value[i] = counter_config[i].count;
 
-			CTR_WRITE(counter_config[i].count, msrs, i);
+			CTR_32BIT_WRITE(counter_config[i].count, msrs, i);
 
 			CTRL_READ(low, high, msrs, i);
 			CTRL_CLEAR(low);
@@ -116,7 +117,7 @@
 		CTR_READ(low, high, msrs, i);
 		if (CTR_OVERFLOWED(low)) {
 			oprofile_add_sample(regs, i);
-			CTR_WRITE(reset_value[i], msrs, i);
+			CTR_32BIT_WRITE(reset_value[i], msrs, i);
 		}
 	}
 
diff --git a/arch/i386/pci/Makefile b/arch/i386/pci/Makefile
index 1594d2f..44650e0 100644
--- a/arch/i386/pci/Makefile
+++ b/arch/i386/pci/Makefile
@@ -1,7 +1,7 @@
 obj-y				:= i386.o init.o
 
 obj-$(CONFIG_PCI_BIOS)		+= pcbios.o
-obj-$(CONFIG_PCI_MMCONFIG)	+= mmconfig.o direct.o
+obj-$(CONFIG_PCI_MMCONFIG)	+= mmconfig.o direct.o mmconfig-shared.o
 obj-$(CONFIG_PCI_DIRECT)	+= direct.o
 
 pci-y				:= fixup.o
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 53ca6e8..1bb0693 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -191,6 +191,94 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"),
 		},
 	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL20p G3",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL20p G4",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL30p G1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL25p G1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL35p G1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL45p G1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL45p G2",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL460c G1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL465c G1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL480c G1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "HP ProLiant BL685c G1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
+		},
+	},
 	{}
 };
 
diff --git a/arch/i386/pci/mmconfig-shared.c b/arch/i386/pci/mmconfig-shared.c
new file mode 100644
index 0000000..747d8c6
--- /dev/null
+++ b/arch/i386/pci/mmconfig-shared.c
@@ -0,0 +1,264 @@
+/*
+ * mmconfig-shared.c - Low-level direct PCI config space access via
+ *                     MMCONFIG - common code between i386 and x86-64.
+ *
+ * This code does:
+ * - known chipset handling
+ * - ACPI decoding and validation
+ *
+ * Per-architecture code takes care of the mappings and accesses
+ * themselves.
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/bitmap.h>
+#include <asm/e820.h>
+
+#include "pci.h"
+
+/* aperture is up to 256MB but BIOS may reserve less */
+#define MMCONFIG_APER_MIN	(2 * 1024*1024)
+#define MMCONFIG_APER_MAX	(256 * 1024*1024)
+
+DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
+
+/* K8 systems have some devices (typically in the builtin northbridge)
+   that are only accessible using type1
+   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. */
+static void __init unreachable_devices(void)
+{
+	int i, bus;
+	/* Use the max bus number from ACPI here? */
+	for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
+		for (i = 0; i < 32; i++) {
+			unsigned int devfn = PCI_DEVFN(i, 0);
+			u32 val1, val2;
+
+			pci_conf1_read(0, bus, devfn, 0, 4, &val1);
+			if (val1 == 0xffffffff)
+				continue;
+
+			if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
+				raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
+				if (val1 == val2)
+					continue;
+			}
+			set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
+			printk(KERN_NOTICE "PCI: No mmconfig possible on device"
+			       " %02x:%02x\n", bus, i);
+		}
+	}
+}
+
+static const char __init *pci_mmcfg_e7520(void)
+{
+	u32 win;
+	pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
+
+	pci_mmcfg_config_num = 1;
+	pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
+	if (!pci_mmcfg_config)
+		return NULL;
+	pci_mmcfg_config[0].address = (win & 0xf000) << 16;
+	pci_mmcfg_config[0].pci_segment = 0;
+	pci_mmcfg_config[0].start_bus_number = 0;
+	pci_mmcfg_config[0].end_bus_number = 255;
+
+	return "Intel Corporation E7520 Memory Controller Hub";
+}
+
+static const char __init *pci_mmcfg_intel_945(void)
+{
+	u32 pciexbar, mask = 0, len = 0;
+
+	pci_mmcfg_config_num = 1;
+
+	pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
+
+	/* Enable bit */
+	if (!(pciexbar & 1))
+		pci_mmcfg_config_num = 0;
+
+	/* Size bits */
+	switch ((pciexbar >> 1) & 3) {
+	case 0:
+		mask = 0xf0000000U;
+		len  = 0x10000000U;
+		break;
+	case 1:
+		mask = 0xf8000000U;
+		len  = 0x08000000U;
+		break;
+	case 2:
+		mask = 0xfc000000U;
+		len  = 0x04000000U;
+		break;
+	default:
+		pci_mmcfg_config_num = 0;
+	}
+
+	/* Errata #2, things break when not aligned on a 256Mb boundary */
+	/* Can only happen in 64M/128M mode */
+
+	if ((pciexbar & mask) & 0x0fffffffU)
+		pci_mmcfg_config_num = 0;
+
+	if (pci_mmcfg_config_num) {
+		pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
+		if (!pci_mmcfg_config)
+			return NULL;
+		pci_mmcfg_config[0].address = pciexbar & mask;
+		pci_mmcfg_config[0].pci_segment = 0;
+		pci_mmcfg_config[0].start_bus_number = 0;
+		pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
+	}
+
+	return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
+}
+
+struct pci_mmcfg_hostbridge_probe {
+	u32 vendor;
+	u32 device;
+	const char *(*probe)(void);
+};
+
+static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
+};
+
+static int __init pci_mmcfg_check_hostbridge(void)
+{
+	u32 l;
+	u16 vendor, device;
+	int i;
+	const char *name;
+
+	pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
+	vendor = l & 0xffff;
+	device = (l >> 16) & 0xffff;
+
+	pci_mmcfg_config_num = 0;
+	pci_mmcfg_config = NULL;
+	name = NULL;
+
+	for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
+		if (pci_mmcfg_probes[i].vendor == vendor &&
+		    pci_mmcfg_probes[i].device == device)
+			name = pci_mmcfg_probes[i].probe();
+	}
+
+	if (name) {
+		printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
+		       name, pci_mmcfg_config_num ? "with" : "without");
+	}
+
+	return name != NULL;
+}
+
+static void __init pci_mmcfg_insert_resources(void)
+{
+#define PCI_MMCFG_RESOURCE_NAME_LEN 19
+	int i;
+	struct resource *res;
+	char *names;
+	unsigned num_buses;
+
+	res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
+			pci_mmcfg_config_num, GFP_KERNEL);
+	if (!res) {
+		printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
+		return;
+	}
+
+	names = (void *)&res[pci_mmcfg_config_num];
+	for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
+		struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
+		num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
+		res->name = names;
+		snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
+			 cfg->pci_segment);
+		res->start = cfg->address;
+		res->end = res->start + (num_buses << 20) - 1;
+		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+		insert_resource(&iomem_resource, res);
+		names += PCI_MMCFG_RESOURCE_NAME_LEN;
+	}
+}
+
+static void __init pci_mmcfg_reject_broken(int type)
+{
+	typeof(pci_mmcfg_config[0]) *cfg;
+
+	if ((pci_mmcfg_config_num == 0) ||
+	    (pci_mmcfg_config == NULL) ||
+	    (pci_mmcfg_config[0].address == 0))
+		return;
+
+	cfg = &pci_mmcfg_config[0];
+
+	/*
+	 * Handle more broken MCFG tables on Asus etc.
+	 * They only contain a single entry for bus 0-0.
+	 */
+	if (pci_mmcfg_config_num == 1 &&
+	    cfg->pci_segment == 0 &&
+	    (cfg->start_bus_number | cfg->end_bus_number) == 0) {
+		printk(KERN_ERR "PCI: start and end of bus number is 0. "
+		       "Rejected as broken MCFG.\n");
+		goto reject;
+	}
+
+	/*
+	 * Only do this check when type 1 works. If it doesn't work
+	 * assume we run on a Mac and always use MCFG
+	 */
+	if (type == 1 && !e820_all_mapped(cfg->address,
+					  cfg->address + MMCONFIG_APER_MIN,
+					  E820_RESERVED)) {
+		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
+		       " E820-reserved\n", cfg->address);
+		goto reject;
+	}
+	return;
+
+reject:
+	printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+	kfree(pci_mmcfg_config);
+	pci_mmcfg_config = NULL;
+	pci_mmcfg_config_num = 0;
+}
+
+void __init pci_mmcfg_init(int type)
+{
+	int known_bridge = 0;
+
+	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+		return;
+
+	if (type == 1 && pci_mmcfg_check_hostbridge())
+		known_bridge = 1;
+
+	if (!known_bridge) {
+		acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
+		pci_mmcfg_reject_broken(type);
+	}
+
+	if ((pci_mmcfg_config_num == 0) ||
+	    (pci_mmcfg_config == NULL) ||
+	    (pci_mmcfg_config[0].address == 0))
+		return;
+
+	if (pci_mmcfg_arch_init()) {
+		if (type == 1)
+			unreachable_devices();
+		if (known_bridge)
+			pci_mmcfg_insert_resources();
+		pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+	}
+}
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 5700220..bb1afd9 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -15,55 +15,33 @@
 #include <asm/e820.h>
 #include "pci.h"
 
-/* aperture is up to 256MB but BIOS may reserve less */
-#define MMCONFIG_APER_MIN	(2 * 1024*1024)
-#define MMCONFIG_APER_MAX	(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 int mmcfg_last_accessed_cpu;
 
-static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
-
 /*
  * Functions for accessing PCI configuration space with MMCONFIG accesses
  */
 static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
 {
-	int cfg_num = -1;
 	struct acpi_mcfg_allocation *cfg;
+	int cfg_num;
 
-	if (seg == 0 && bus < MAX_CHECK_BUS &&
-	    test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
+	if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
+	    test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
 		return 0;
 
-	while (1) {
-		++cfg_num;
-		if (cfg_num >= pci_mmcfg_config_num) {
-			break;
-		}
+	for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
 		cfg = &pci_mmcfg_config[cfg_num];
-		if (cfg->pci_segment != seg)
-			continue;
-		if ((cfg->start_bus_number <= bus) &&
+		if (cfg->pci_segment == seg &&
+		    (cfg->start_bus_number <= bus) &&
 		    (cfg->end_bus_number >= bus))
 			return cfg->address;
 	}
 
-	/* Handle more broken MCFG tables on Asus etc.
-	   They only contain a single entry for bus 0-0. Assume
- 	   this applies to all busses. */
-	cfg = &pci_mmcfg_config[0];
-	if (pci_mmcfg_config_num == 1 &&
-		cfg->pci_segment == 0 &&
-		(cfg->start_bus_number | cfg->end_bus_number) == 0)
-		return cfg->address;
-
 	/* Fall back to type 0 */
 	return 0;
 }
@@ -158,67 +136,15 @@
 	.write =	pci_mmcfg_write,
 };
 
-/* K8 systems have some devices (typically in the builtin northbridge)
-   that are only accessible using type1
-   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. */
-static __init void unreachable_devices(void)
+int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+				    unsigned int devfn)
 {
-	int i, k;
-	unsigned long flags;
-
-	for (k = 0; k < MAX_CHECK_BUS; k++) {
-		for (i = 0; i < 32; i++) {
-			u32 val1;
-			u32 addr;
-
-			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, 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 + 32*k, fallback_slots);
-				printk(KERN_NOTICE
-			"PCI: No mmconfig possible on %x:%x\n", k, i);
-			}
-			spin_unlock_irqrestore(&pci_config_lock, flags);
-		}
-	}
+	return get_base_addr(seg, bus, devfn) != 0;
 }
 
-void __init pci_mmcfg_init(int type)
+int __init pci_mmcfg_arch_init(void)
 {
-	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
-		return;
-
-	acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
-	if ((pci_mmcfg_config_num == 0) ||
-	    (pci_mmcfg_config == NULL) ||
-	    (pci_mmcfg_config[0].address == 0))
-		return;
-
-	/* Only do this check when type 1 works. If it doesn't work
-	   assume we run on a Mac and always use MCFG */
-	if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address,
-			pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
-			E820_RESERVED)) {
-		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n",
-				(unsigned long)pci_mmcfg_config[0].address);
-		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;
-
-	unreachable_devices();
+	return 1;
 }
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index a0a2518..e58bae2 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -94,3 +94,13 @@
 extern void pci_mmcfg_init(int type);
 extern void pcibios_sort(void);
 
+/* pci-mmconfig.c */
+
+/* Verify the first 16 busses. We assume that systems with more busses
+   get MCFG right. */
+#define PCI_MMCFG_MAX_CHECK_BUS 16
+extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
+
+extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+					   unsigned int devfn);
+extern int __init pci_mmcfg_arch_init(void);
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index f1d2899..d51f0f1 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -22,8 +22,13 @@
 
 config 64BIT
 	bool
+	select ATA_NONSTANDARD if ATA
 	default y
 
+config ZONE_DMA
+	def_bool y
+	depends on !IA64_SGI_SN2
+
 config MMU
 	bool
 	default y
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index ce49fe3..c1dca22 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1881,7 +1881,7 @@
 	return seq_open(file, &ioc_seq_ops);
 }
 
-static struct file_operations ioc_fops = {
+static const struct file_operations ioc_fops = {
 	.open    = ioc_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index 578737e..c05bda6 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -91,9 +91,8 @@
 	 * it with privilege level 3 because the IVE uses non-privileged accesses to these
 	 * tables.  IA-32 segmentation is used to protect against IA-32 accesses to them.
 	 */
-	vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 	if (vma) {
-		memset(vma, 0, sizeof(*vma));
 		vma->vm_mm = current->mm;
 		vma->vm_start = IA32_GDT_OFFSET;
 		vma->vm_end = vma->vm_start + PAGE_SIZE;
@@ -117,9 +116,8 @@
 	 * code is locked in specific gate page, which is pointed by pretcode
 	 * when setup_frame_ia32
 	 */
-	vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 	if (vma) {
-		memset(vma, 0, sizeof(*vma));
 		vma->vm_mm = current->mm;
 		vma->vm_start = IA32_GATE_OFFSET;
 		vma->vm_end = vma->vm_start + PAGE_SIZE;
@@ -142,9 +140,8 @@
 	 * Install LDT as anonymous memory.  This gives us all-zero segment descriptors
 	 * until a task modifies them via modify_ldt().
 	 */
-	vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 	if (vma) {
-		memset(vma, 0, sizeof(*vma));
 		vma->vm_mm = current->mm;
 		vma->vm_start = IA32_LDT_OFFSET;
 		vma->vm_end = vma->vm_start + PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
@@ -214,12 +211,10 @@
 		bprm->loader += stack_base;
 	bprm->exec += stack_base;
 
-	mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+	mpnt = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 	if (!mpnt)
 		return -ENOMEM;
 
-	memset(mpnt, 0, sizeof(*mpnt));
-
 	down_write(&current->mm->mmap_sem);
 	{
 		mpnt->vm_mm = current->mm;
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index a32cd59..687e5fd 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -326,7 +326,7 @@
 	data8 sys_ni_syscall
 	data8 compat_sys_wait4
 	data8 sys_swapoff	  /* 115 */
-	data8 sys32_sysinfo
+	data8 compat_sys_sysinfo
 	data8 sys32_ipc
 	data8 sys_fsync
 	data8 sys32_sigreturn
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 957681c..d430d36 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -2209,74 +2209,6 @@
 	return ret;
 }
 
-struct sysinfo32 {
-	s32 uptime;
-	u32 loads[3];
-	u32 totalram;
-	u32 freeram;
-	u32 sharedram;
-	u32 bufferram;
-	u32 totalswap;
-	u32 freeswap;
-	u16 procs;
-	u16 pad;
-	u32 totalhigh;
-	u32 freehigh;
-	u32 mem_unit;
-	char _f[8];
-};
-
-asmlinkage long
-sys32_sysinfo (struct sysinfo32 __user *info)
-{
-	struct sysinfo s;
-	long ret, err;
-	int bitcount = 0;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs(KERNEL_DS);
-	ret = sys_sysinfo((struct sysinfo __user *) &s);
-	set_fs(old_fs);
-	/* Check to see if any memory value is too large for 32-bit and
-	 * scale down if needed.
-	 */
-	if ((s.totalram >> 32) || (s.totalswap >> 32)) {
-		while (s.mem_unit < PAGE_SIZE) {
-			s.mem_unit <<= 1;
-			bitcount++;
-		}
-		s.totalram >>= bitcount;
-		s.freeram >>= bitcount;
-		s.sharedram >>= bitcount;
-		s.bufferram >>= bitcount;
-		s.totalswap >>= bitcount;
-		s.freeswap >>= bitcount;
-		s.totalhigh >>= bitcount;
-		s.freehigh >>= bitcount;
-	}
-
-	if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
-		return -EFAULT;
-
-	err  = __put_user(s.uptime, &info->uptime);
-	err |= __put_user(s.loads[0], &info->loads[0]);
-	err |= __put_user(s.loads[1], &info->loads[1]);
-	err |= __put_user(s.loads[2], &info->loads[2]);
-	err |= __put_user(s.totalram, &info->totalram);
-	err |= __put_user(s.freeram, &info->freeram);
-	err |= __put_user(s.sharedram, &info->sharedram);
-	err |= __put_user(s.bufferram, &info->bufferram);
-	err |= __put_user(s.totalswap, &info->totalswap);
-	err |= __put_user(s.freeswap, &info->freeswap);
-	err |= __put_user(s.procs, &info->procs);
-	err |= __put_user (s.totalhigh, &info->totalhigh);
-	err |= __put_user (s.freehigh, &info->freehigh);
-	err |= __put_user (s.mem_unit, &info->mem_unit);
-	if (err)
-		return -EFAULT;
-	return ret;
-}
-
 asmlinkage long
 sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec __user *interval)
 {
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 9197d7b..3549c94 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -651,7 +651,7 @@
 	 * information -- the successor to MPS tables.
 	 */
 
-	if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt) < 1) {
+	if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
 		printk(KERN_ERR PREFIX "Can't find MADT\n");
 		goto skip_madt;
 	}
@@ -702,7 +702,7 @@
 	 * gets interrupts such as power and sleep buttons.  If it's not
 	 * on a Legacy interrupt, it needs to be setup.
 	 */
-	if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt) < 1)
+	if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt))
 		printk(KERN_ERR PREFIX "Can't find FADT\n");
 
 #ifdef CONFIG_SMP
diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
index 9d92097..5cdd2f5 100644
--- a/arch/ia64/kernel/crash.c
+++ b/arch/ia64/kernel/crash.c
@@ -52,7 +52,7 @@
 static DEFINE_PER_CPU(struct elf_prstatus, elf_prstatus);
 
 void
-crash_save_this_cpu()
+crash_save_this_cpu(void)
 {
 	void *buf;
 	unsigned long cfm, sof, sol;
@@ -222,7 +222,7 @@
 	if((ret = register_die_notifier(&kdump_init_notifier_nb)) != 0)
 		return ret;
 #ifdef CONFIG_SYSCTL
-	register_sysctl_table(sys_table, 0);
+	register_sysctl_table(sys_table);
 #endif
 	return 0;
 }
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 6c03928..772ba6f 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -413,11 +413,10 @@
 	efi_char16_t *c16;
 	u64 efi_desc_size;
 	char *cp, vendor[100] = "unknown";
-	extern char saved_command_line[];
 	int i;
 
 	/* it's too early to be able to use the standard kernel command line support... */
-	for (cp = saved_command_line; *cp; ) {
+	for (cp = boot_command_line; *cp; ) {
 		if (memcmp(cp, "mem=", 4) == 0) {
 			mem_limit = memparse(cp + 4, &cp);
 		} else if (memcmp(cp, "max_addr=", 9) == 0) {
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index ba3ba8b..456f57b 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -275,7 +275,7 @@
 
 static struct irqaction resched_irqaction = {
 	.handler =	dummy_handler,
-	.flags =	SA_INTERRUPT,
+	.flags =	IRQF_DISABLED,
 	.name =		"resched"
 };
 #endif
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 0d05450..e722090 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -60,7 +60,7 @@
 	msg.address_lo = addr;
 
 	write_msi_msg(irq, &msg);
-	set_native_irq_info(irq, cpu_mask);
+	irq_desc[irq].affinity = cpu_mask;
 }
 #endif /* CONFIG_SMP */
 
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index aa94f60..9ddf896 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -147,7 +147,7 @@
  * in UP:
  * 	- we need to protect against PMU overflow interrupts (local_irq_disable)
  *
- * spin_lock_irqsave()/spin_lock_irqrestore():
+ * spin_lock_irqsave()/spin_unlock_irqrestore():
  * 	in SMP: local_irq_disable + spin_lock
  * 	in UP : local_irq_disable
  *
@@ -521,19 +521,57 @@
 EXPORT_SYMBOL(pfm_sysctl);
 
 static ctl_table pfm_ctl_table[]={
-	{1, "debug", &pfm_sysctl.debug, sizeof(int), 0666, NULL, &proc_dointvec, NULL,},
-	{2, "debug_ovfl", &pfm_sysctl.debug_ovfl, sizeof(int), 0666, NULL, &proc_dointvec, NULL,},
-	{3, "fastctxsw", &pfm_sysctl.fastctxsw, sizeof(int), 0600, NULL, &proc_dointvec, NULL,},
-	{4, "expert_mode", &pfm_sysctl.expert_mode, sizeof(int), 0600, NULL, &proc_dointvec, NULL,},
-	{ 0, },
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "debug",
+		.data		= &pfm_sysctl.debug,
+		.maxlen		= sizeof(int),
+		.mode		= 0666,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "debug_ovfl",
+		.data		= &pfm_sysctl.debug_ovfl,
+		.maxlen		= sizeof(int),
+		.mode		= 0666,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "fastctxsw",
+		.data		= &pfm_sysctl.fastctxsw,
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	=  &proc_dointvec,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "expert_mode",
+		.data		= &pfm_sysctl.expert_mode,
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= &proc_dointvec,
+	},
+	{}
 };
 static ctl_table pfm_sysctl_dir[] = {
-	{1, "perfmon", NULL, 0, 0755, pfm_ctl_table, },
- 	{0,},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "perfmon",
+		.mode		= 0755,
+		.child		= pfm_ctl_table,
+	},
+ 	{}
 };
 static ctl_table pfm_sysctl_root[] = {
-	{1, "kernel", NULL, 0, 0755, pfm_sysctl_dir, },
- 	{0,},
+	{
+		.ctl_name	= CTL_KERN,
+		.procname	= "kernel",
+		.mode		= 0755,
+		.child		= pfm_sysctl_dir,
+	},
+ 	{}
 };
 static struct ctl_table_header *pfm_sysctl_header;
 
@@ -621,7 +659,7 @@
 
 
 /* forward declaration */
-static struct file_operations pfm_file_ops;
+static const struct file_operations pfm_file_ops;
 
 /*
  * forward declarations
@@ -2126,7 +2164,7 @@
 
 
 
-static struct file_operations pfm_file_ops = {
+static const struct file_operations pfm_file_ops = {
 	.llseek   = no_llseek,
 	.read     = pfm_read,
 	.write    = pfm_write,
@@ -2301,12 +2339,11 @@
 	DPRINT(("smpl_buf @%p\n", smpl_buf));
 
 	/* allocate vma */
-	vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 	if (!vma) {
 		DPRINT(("Cannot allocate vma\n"));
 		goto error_kmem;
 	}
-	memset(vma, 0, sizeof(*vma));
 
 	/*
 	 * partially initialize the vma for the sampling buffer
@@ -6597,7 +6634,7 @@
 	return 0;
 }
 
-static struct file_operations pfm_proc_fops = {
+static const struct file_operations pfm_proc_fops = {
 	.open		= pfm_proc_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -6689,7 +6726,7 @@
 	/*
 	 * create /proc/sys/kernel/perfmon (for debugging purposes)
 	 */
-	pfm_sysctl_header = register_sysctl_table(pfm_sysctl_root, 0);
+	pfm_sysctl_header = register_sysctl_table(pfm_sysctl_root);
 
 	/*
 	 * initialize all our spinlocks
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
index 20bad78..37c876f 100644
--- a/arch/ia64/kernel/sal.c
+++ b/arch/ia64/kernel/sal.c
@@ -194,9 +194,8 @@
 chk_nointroute_opt(void)
 {
 	char *cp;
-	extern char saved_command_line[];
 
-	for (cp = saved_command_line; *cp; ) {
+	for (cp = boot_command_line; *cp; ) {
 		if (memcmp(cp, "nointroute", 10) == 0) {
 			no_int_routing = 1;
 			printk ("no_int_routing on\n");
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index e375a2f..af9f875 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -352,7 +352,7 @@
 	return size;
 }
 
-static struct file_operations salinfo_event_fops = {
+static const struct file_operations salinfo_event_fops = {
 	.open  = salinfo_event_open,
 	.read  = salinfo_event_read,
 };
@@ -568,7 +568,7 @@
 	return count;
 }
 
-static struct file_operations salinfo_data_fops = {
+static const struct file_operations salinfo_data_fops = {
 	.open    = salinfo_log_open,
 	.release = salinfo_log_release,
 	.read    = salinfo_log_read,
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 83c2629..5fa09d1 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -262,7 +262,7 @@
 	 * appropriate after a kernel panic.
 	 */
 	{
-		char *from = strstr(saved_command_line, "crashkernel=");
+		char *from = strstr(boot_command_line, "crashkernel=");
 		unsigned long base, size;
 		if (from) {
 			size = memparse(from + 12, &from);
@@ -463,7 +463,7 @@
 	ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist);
 
 	*cmdline_p = __va(ia64_boot_param->command_line);
-	strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
 
 	efi_init();
 	io_port_init();
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index f4c7f77..55ddd80 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -221,13 +221,13 @@
 
 #ifdef CONFIG_KEXEC
 void
-kdump_smp_send_stop()
+kdump_smp_send_stop(void)
 {
  	send_IPI_allbutself(IPI_KDUMP_CPU_STOP);
 }
 
 void
-kdump_smp_send_init()
+kdump_smp_send_init(void)
 {
 	unsigned int cpu, self_cpu;
 	self_cpu = smp_processor_id();
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index ab68474..765cbe5 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -24,8 +24,6 @@
 #include <asm/uaccess.h>
 #include <asm/kdebug.h>
 
-extern spinlock_t timerlist_lock;
-
 fpswa_interface_t *fpswa_interface;
 EXPORT_SYMBOL(fpswa_interface);
 
@@ -53,34 +51,6 @@
 		fpswa_interface = __va(ia64_boot_param->fpswa);
 }
 
-/*
- * Unlock any spinlocks which will prevent us from getting the message out (timerlist_lock
- * is acquired through the console unblank code)
- */
-void
-bust_spinlocks (int yes)
-{
-	int loglevel_save = console_loglevel;
-
-	if (yes) {
-		oops_in_progress = 1;
-		return;
-	}
-
-#ifdef CONFIG_VT
-	unblank_screen();
-#endif
-	oops_in_progress = 0;
-	/*
-	 * OK, the message is on the console.  Now we call printk() without
-	 * oops_in_progress set so that printk will give klogd a poke.  Hold onto
-	 * your hats...
-	 */
-	console_loglevel = 15;		/* NMI oopser may have shut the console up */
-	printk(" ");
-	console_loglevel = loglevel_save;
-}
-
 void
 die (const char *str, struct pt_regs *regs, long err)
 {
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 8f3d006..25dd55e 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -111,12 +111,14 @@
   .init.data : AT(ADDR(.init.data) - LOAD_OFFSET)
 	{ *(.init.data) }
 
+#ifdef CONFIG_BLK_DEV_INITRD
   .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET)
 	{
 	  __initramfs_start = .;
 	  *(.init.ramfs)
 	  __initramfs_end = .;
 	}
+#endif
 
    . = ALIGN(16);
   .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET)
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 63e6d49..ca4d41e 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -259,9 +259,11 @@
 	num_physpages = 0;
 	efi_memmap_walk(count_pages, &num_physpages);
 
-	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+#ifdef CONFIG_ZONE_DMA
+	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 	max_zone_pfns[ZONE_DMA] = max_dma;
+#endif
 	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 6eae596..1683510 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -37,7 +37,9 @@
 	unsigned long pernode_size;
 	struct bootmem_data bootmem_data;
 	unsigned long num_physpages;
+#ifdef CONFIG_ZONE_DMA
 	unsigned long num_dma_physpages;
+#endif
 	unsigned long min_pfn;
 	unsigned long max_pfn;
 };
@@ -633,9 +635,11 @@
 	unsigned long end = start + len;
 
 	mem_data[node].num_physpages += len >> PAGE_SHIFT;
+#ifdef CONFIG_ZONE_DMA
 	if (start <= __pa(MAX_DMA_ADDRESS))
 		mem_data[node].num_dma_physpages +=
 			(min(end, __pa(MAX_DMA_ADDRESS)) - start) >>PAGE_SHIFT;
+#endif
 	start = GRANULEROUNDDOWN(start);
 	start = ORDERROUNDDOWN(start);
 	end = GRANULEROUNDUP(end);
@@ -688,7 +692,9 @@
 	}
 
 	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+#ifdef CONFIG_ZONE_DMA
 	max_zone_pfns[ZONE_DMA] = max_dma;
+#endif
 	max_zone_pfns[ZONE_NORMAL] = max_pfn;
 	free_area_init_nodes(max_zone_pfns);
 
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index faaca21..f225dd7 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -68,7 +68,7 @@
 #ifndef	CONFIG_NUMA
 	node_free_pages = nr_free_pages();
 #else
-	node_free_pages = nr_free_pages_pgdat(NODE_DATA(numa_node_id()));
+	node_free_pages = node_page_state(numa_node_id(), NR_FREE_PAGES);
 #endif
 	max_pgt_pages = node_free_pages / PGT_FRACTION_OF_NODE_MEM;
 	max_pgt_pages = max(max_pgt_pages, MIN_PGT_PAGES);
@@ -176,9 +176,8 @@
 	 * the problem.  When the process attempts to write to the register backing store
 	 * for the first time, it will get a SEGFAULT in this case.
 	 */
-	vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 	if (vma) {
-		memset(vma, 0, sizeof(*vma));
 		vma->vm_mm = current->mm;
 		vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
 		vma->vm_end = vma->vm_start + PAGE_SIZE;
@@ -195,9 +194,8 @@
 
 	/* map NaT-page at address zero to speed up speculative dereferencing of NULL: */
 	if (!(current->personality & MMAP_PAGE_ZERO)) {
-		vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+		vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 		if (vma) {
-			memset(vma, 0, sizeof(*vma));
 			vma->vm_mm = current->mm;
 			vma->vm_end = PAGE_SIZE;
 			vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT);
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
index ea3dc38..49873aa 100644
--- a/arch/ia64/sn/kernel/msi_sn.c
+++ b/arch/ia64/sn/kernel/msi_sn.c
@@ -204,7 +204,7 @@
 	msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
 
 	write_msi_msg(irq, &msg);
-	set_native_irq_info(irq, cpu_mask);
+	irq_desc[irq].affinity = cpu_mask;
 }
 #endif /* CONFIG_SMP */
 
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index d9d306c..601747b 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -455,7 +455,7 @@
 	return seq_open(file, &sn2_ptc_seq_ops);
 }
 
-static struct file_operations proc_sn2_ptc_operations = {
+static const struct file_operations proc_sn2_ptc_operations = {
 	.open = sn2_ptc_proc_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 3336799..6da9854 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -865,7 +865,7 @@
 	return r;
 }
 
-static struct file_operations sn_hwperf_fops = {
+static const struct file_operations sn_hwperf_fops = {
 	.ioctl = sn_hwperf_ioctl,
 };
 
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
index 43ddc2e..62b3e9a 100644
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
@@ -89,61 +89,80 @@
 	return single_open(file, coherence_id_show, NULL);
 }
 
-static struct proc_dir_entry
-*sn_procfs_create_entry(const char *name, struct proc_dir_entry *parent,
-			int (*openfunc)(struct inode *, struct file *),
-	int (*releasefunc)(struct inode *, struct file *),
-	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *))
-{
-	struct proc_dir_entry *e = create_proc_entry(name, 0444, parent);
-
-	if (e) {
-		struct file_operations *f;
-
-		f = kzalloc(sizeof(*f), GFP_KERNEL);
-		if (f) {
-			f->open = openfunc;
-			f->read = seq_read;
-			f->llseek = seq_lseek;
-			f->release = releasefunc;
-			f->write = write;
-			e->proc_fops = f;
-		}
-	}
-
-	return e;
-}
-
 /* /proc/sgi_sn/sn_topology uses seq_file, see sn_hwperf.c */
 extern int sn_topology_open(struct inode *, struct file *);
 extern int sn_topology_release(struct inode *, struct file *);
 
+static const struct file_operations proc_partition_id_fops = {
+	.open		= partition_id_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_system_sn_fops = {
+	.open		= system_serial_number_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_license_id_fops = {
+	.open		= licenseID_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_sn_force_intr_fops = {
+	.open		= sn_force_interrupt_open,
+	.read		= seq_read,
+	.write		= sn_force_interrupt_write_proc,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_coherence_id_fops = {
+	.open		= coherence_id_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_sn_topo_fops = {
+	.open		= sn_topology_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= sn_topology_release,
+};
+
 void register_sn_procfs(void)
 {
 	static struct proc_dir_entry *sgi_proc_dir = NULL;
+	struct proc_dir_entry *pde;
 
 	BUG_ON(sgi_proc_dir != NULL);
 	if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL)))
 		return;
 
-	sn_procfs_create_entry("partition_id", sgi_proc_dir,
-		partition_id_open, single_release, NULL);
-
-	sn_procfs_create_entry("system_serial_number", sgi_proc_dir,
-		system_serial_number_open, single_release, NULL);
-
-	sn_procfs_create_entry("licenseID", sgi_proc_dir, 
-		licenseID_open, single_release, NULL);
-
-	sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir,
-		sn_force_interrupt_open, single_release,
-		sn_force_interrupt_write_proc);
-
-	sn_procfs_create_entry("coherence_id", sgi_proc_dir, 
-		coherence_id_open, single_release, NULL);
-	
-	sn_procfs_create_entry("sn_topology", sgi_proc_dir,
-		sn_topology_open, sn_topology_release, NULL);
+	pde = create_proc_entry("partition_id", 0444, sgi_proc_dir);
+	if (pde)
+		pde->proc_fops = &proc_partition_id_fops;
+	pde = create_proc_entry("system_serial_number", 0444, sgi_proc_dir);
+	if (pde)
+		pde->proc_fops = &proc_system_sn_fops;
+	pde = create_proc_entry("licenseID", 0444, sgi_proc_dir);
+	if (pde)
+		pde->proc_fops = &proc_license_id_fops;
+	pde = create_proc_entry("sn_force_interrupt", 0644, sgi_proc_dir);
+	if (pde)
+		pde->proc_fops = &proc_sn_force_intr_fops;
+	pde = create_proc_entry("coherence_id", 0444, sgi_proc_dir);
+	if (pde)
+		pde->proc_fops = &proc_coherence_id_fops;
+	pde = create_proc_entry("sn_topology", 0444, sgi_proc_dir);
+	if (pde)
+		pde->proc_fops = &proc_sn_topo_fops;
 }
 
 #endif /* CONFIG_PROC_FS */
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index 7a387d2..68355ef 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -101,67 +101,57 @@
 
 static ctl_table xpc_sys_xpc_hb_dir[] = {
 	{
-		1,
-		"hb_interval",
-		&xpc_hb_interval,
-		sizeof(int),
-		0644,
-		NULL,
-		&proc_dointvec_minmax,
-		&sysctl_intvec,
-		NULL,
-		&xpc_hb_min_interval,
-		&xpc_hb_max_interval
+		.ctl_name 	= CTL_UNNUMBERED,
+		.procname	= "hb_interval",
+		.data		= &xpc_hb_interval,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xpc_hb_min_interval,
+		.extra2		= &xpc_hb_max_interval
 	},
 	{
-		2,
-		"hb_check_interval",
-		&xpc_hb_check_interval,
-		sizeof(int),
-		0644,
-		NULL,
-		&proc_dointvec_minmax,
-		&sysctl_intvec,
-		NULL,
-		&xpc_hb_check_min_interval,
-		&xpc_hb_check_max_interval
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "hb_check_interval",
+		.data		= &xpc_hb_check_interval,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xpc_hb_check_min_interval,
+		.extra2		= &xpc_hb_check_max_interval
 	},
-	{0}
+	{}
 };
 static ctl_table xpc_sys_xpc_dir[] = {
 	{
-		1,
-		"hb",
-		NULL,
-		0,
-		0555,
-		xpc_sys_xpc_hb_dir
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "hb",
+		.mode		= 0555,
+		.child		= xpc_sys_xpc_hb_dir
 	},
 	{
-		2,
-		"disengage_request_timelimit",
-		&xpc_disengage_request_timelimit,
-		sizeof(int),
-		0644,
-		NULL,
-		&proc_dointvec_minmax,
-		&sysctl_intvec,
-		NULL,
-		&xpc_disengage_request_min_timelimit,
-		&xpc_disengage_request_max_timelimit
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "disengage_request_timelimit",
+		.data		= &xpc_disengage_request_timelimit,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xpc_disengage_request_min_timelimit,
+		.extra2		= &xpc_disengage_request_max_timelimit
 	},
-	{0}
+	{}
 };
 static ctl_table xpc_sys_dir[] = {
 	{
-		1,
-		"xpc",
-		NULL,
-		0,
-		0555,
-		xpc_sys_xpc_dir
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "xpc",
+		.mode		= 0555,
+		.child		= xpc_sys_xpc_dir
 	},
-	{0}
+	{}
 };
 static struct ctl_table_header *xpc_sysctl;
 
@@ -1251,7 +1241,7 @@
 	snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
 	snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
 
-	xpc_sysctl = register_sysctl_table(xpc_sys_dir, 1);
+	xpc_sysctl = register_sysctl_table(xpc_sys_dir);
 
 	/*
 	 * The first few fields of each entry of xpc_partitions[] need to
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index f383dab..9740d6b 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -16,6 +16,10 @@
 	bool
 	default y
 
+config ZONE_DMA
+	bool
+	default y
+
 config GENERIC_HARDIRQS
 	bool
 	default y
@@ -24,6 +28,9 @@
 	bool
 	default y
 
+config NO_IOPORT
+	def_bool y
+
 source "init/Kconfig"
 
 
diff --git a/arch/m32r/Makefile b/arch/m32r/Makefile
index f219c47..cdf63b2 100644
--- a/arch/m32r/Makefile
+++ b/arch/m32r/Makefile
@@ -7,7 +7,7 @@
 
 LDFLAGS		:=
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
-LDFLAGS_vmlinux	:= -e startup_32
+LDFLAGS_vmlinux	:=
 
 CFLAGS += -pipe -fno-schedule-insns
 CFLAGS_KERNEL += -mmodel=medium
diff --git a/arch/m32r/defconfig b/arch/m32r/defconfig
index 8530930..1357991 100644
--- a/arch/m32r/defconfig
+++ b/arch/m32r/defconfig
@@ -1,20 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc5
-# Fri Jun  3 16:20:11 2005
+# Linux kernel version: 2.6.19
+# Tue Dec 12 17:52:38 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -22,32 +20,40 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
-# CONFIG_IKCONFIG_PROC is not set
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -55,10 +61,29 @@
 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
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
 
 #
 # Processor type and features
@@ -70,8 +95,10 @@
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
 # CONFIG_PLAT_MAPPI3 is not set
+# CONFIG_PLAT_M32104UT is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_M32104 is not set
 # CONFIG_CHIP_VDEC2 is not set
 # CONFIG_CHIP_OPSP is not set
 CONFIG_MMU=y
@@ -85,34 +112,39 @@
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_NOHIGHMEM=y
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PREEMPT=y
-# CONFIG_HAVE_DEC_LOCK is not set
-# CONFIG_SMP is not set
+CONFIG_SMP=y
+# CONFIG_CHIP_M32700_TS1 is not set
+CONFIG_NR_CPUS=2
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ISA is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-CONFIG_PCCARD=y
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_PCMCIA=y
-
-#
-# PC-card bridges
-#
-# CONFIG_TCIC is not set
-# CONFIG_M32R_PCC is not set
-CONFIG_M32R_CFC=y
-CONFIG_M32R_CFC_NUM=1
+# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -125,6 +157,94 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
 #
 
@@ -133,12 +253,100 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+# CONFIG_MTD_CFI_NOSWAP is not set
+CONFIG_MTD_CFI_BE_BYTE_SWAP=y
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=m
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
 
 #
 # Parallel port support
@@ -152,7 +360,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -160,23 +367,21 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
+CONFIG_ATA_OVER_ETH=m
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -185,7 +390,6 @@
 # CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECS=y
 CONFIG_BLK_DEV_IDECD=m
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -204,7 +408,9 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=m
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -216,6 +422,7 @@
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -225,26 +432,23 @@
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
 #
-# CONFIG_SCSI_SATA is not set
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
-# PCMCIA SCSI adapter support
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
-# 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)
@@ -254,6 +458,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -264,69 +469,8 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -334,6 +478,11 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -359,11 +508,6 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
@@ -371,6 +515,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -386,6 +532,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -414,7 +561,6 @@
 # CONFIG_SERIO_LIBPS2 is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -422,6 +568,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -450,8 +597,8 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 CONFIG_DS1302=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -459,17 +606,12 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -477,34 +619,51 @@
 # 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
 
 #
-# Misc devices
+# Hardware Monitoring support
 #
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
 #
-CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
 
 #
-# Video For Linux
+# Video Capture Adapters
 #
 
 #
-# Video Adapters
+# Video Capture Adapters
 #
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
 # CONFIG_VIDEO_CPIA is not set
-CONFIG_VIDEO_M32R_AR=y
-CONFIG_VIDEO_M32R_AR_M64278=y
+CONFIG_VIDEO_M32R_AR=m
+CONFIG_VIDEO_M32R_AR_M64278=m
 
 #
 # Radio Adapters
 #
-# CONFIG_RADIO_MAESTRO is not set
 
 #
 # Digital Video Broadcasting Devices
@@ -514,15 +673,16 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_SOFT_CURSOR is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_S1D13XXX=y
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -531,6 +691,7 @@
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -542,6 +703,7 @@
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_M32R_CLUT224=y
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -554,6 +716,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -563,23 +730,62 @@
 #
 # MMC/SD Card support
 #
-# CONFIG_MMC is not set
+CONFIG_MMC=y
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_TIFM_SD 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=m
+# 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=m
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
 CONFIG_JBD_DEBUG=y
 CONFIG_FS_MBCACHE=y
 CONFIG_REISERFS_FS=m
@@ -587,17 +793,19 @@
 # CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -623,15 +831,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -643,6 +849,8 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -655,12 +863,14 @@
 #
 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
@@ -669,6 +879,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -723,16 +934,23 @@
 #
 # Profiling support
 #
-# CONFIG_PROFILING is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
 
 #
 # Security options
@@ -746,12 +964,9 @@
 # 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
diff --git a/arch/m32r/kernel/head.S b/arch/m32r/kernel/head.S
index 0d3c8ee..dab7436 100644
--- a/arch/m32r/kernel/head.S
+++ b/arch/m32r/kernel/head.S
@@ -7,8 +7,6 @@
  *                            Hitoshi Yamamoto
  */
 
-/* $Id$ */
-
 #include <linux/init.h>
 __INIT
 __INITDATA
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index 44cbe0c..a689e29 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -174,7 +174,7 @@
 	  regs->acc1h, regs->acc1l);
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
 	printk("ACCH[%08lx]:ACCL[%08lx]\n", \
-	  regs->acch, regs->accl);
+	  regs->acc0h, regs->acc0l);
 #else
 #error unknown isa configuration
 #endif
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index 936205f..d648143 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -64,7 +64,7 @@
 
 extern int root_mountflags;
 
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 static struct resource data_resource = {
 	.name   = "Kernel data",
@@ -95,8 +95,8 @@
 	int usermem = 0;
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
 	memory_start = (unsigned long)CONFIG_MEMORY_START+PAGE_OFFSET;
 	memory_end = memory_start+(unsigned long)CONFIG_MEMORY_SIZE;
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index 092ea86..4b15605 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -109,19 +109,10 @@
 	COPY(r10);
 	COPY(r11);
 	COPY(r12);
-#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
 	COPY(acc0h);
 	COPY(acc0l);
-	COPY(acc1h);
-	COPY(acc1l);
-#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
+	COPY(acc1h);		/* ISA_DSP_LEVEL2 only */
+	COPY(acc1l);		/* ISA_DSP_LEVEL2 only */
 	COPY(psw);
 	COPY(bpc);
 	COPY(bbpsw);
@@ -196,19 +187,10 @@
 	COPY(r10);
 	COPY(r11);
 	COPY(r12);
-#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
 	COPY(acc0h);
 	COPY(acc0l);
-	COPY(acc1h);
-	COPY(acc1l);
-#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
+	COPY(acc1h);		/* ISA_DSP_LEVEL2 only */
+	COPY(acc1l);		/* ISA_DSP_LEVEL2 only */
 	COPY(psw);
 	COPY(bpc);
 	COPY(bbpsw);
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
index a090382..3858c9f 100644
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -286,11 +286,3 @@
 #error no chip configuration
 #endif
 }
-
-/*
- *  Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
index 358b9ce..439cc25 100644
--- a/arch/m32r/kernel/vmlinux.lds.S
+++ b/arch/m32r/kernel/vmlinux.lds.S
@@ -6,12 +6,15 @@
 #include <asm/page.h>
 
 OUTPUT_ARCH(m32r)
-ENTRY(startup_32)
 #if defined(__LITTLE_ENDIAN__)
        jiffies = jiffies_64;
 #else
        jiffies = jiffies_64 + 4;
 #endif
+
+kernel_entry = boot - 0x80000000;
+ENTRY(kernel_entry)
+
 SECTIONS
 {
   . = CONFIG_MEMORY_START + __PAGE_OFFSET;
@@ -99,10 +102,14 @@
      from .altinstructions and .eh_frame */
   .exit.text : { *(.exit.text) }
   .exit.data : { *(.exit.data) }
+
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
+
   . = ALIGN(32);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
diff --git a/arch/m32r/lib/ashxdi3.S b/arch/m32r/lib/ashxdi3.S
index 107594b..7fc0c19 100644
--- a/arch/m32r/lib/ashxdi3.S
+++ b/arch/m32r/lib/ashxdi3.S
@@ -4,8 +4,6 @@
  * Copyright (C) 2001,2002  Hiroyuki Kondo, and Hirokazu Takata
  *
  */
-/* $Id$ */
-
 
 ;
 ;      input   (r0,r1)  src
@@ -293,4 +291,3 @@
 #endif /* not CONFIG_ISA_DUAL_ISSUE */
 
 	.end
-
diff --git a/arch/m32r/lib/checksum.S b/arch/m32r/lib/checksum.S
index cfbe00e..0af0360 100644
--- a/arch/m32r/lib/checksum.S
+++ b/arch/m32r/lib/checksum.S
@@ -25,8 +25,6 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  */
-/* $Id$ */
-
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
@@ -319,3 +317,4 @@
 	nop
 	nop
 
+	.end
diff --git a/arch/m32r/lib/delay.c b/arch/m32r/lib/delay.c
index 06382a3..59bfc34 100644
--- a/arch/m32r/lib/delay.c
+++ b/arch/m32r/lib/delay.c
@@ -5,8 +5,6 @@
  * Copyright (c) 2004  Hirokazu Takata
  */
 
-/* $Id$ */
-
 #include <linux/param.h>
 #ifdef CONFIG_SMP
 #include <linux/sched.h>
diff --git a/arch/m32r/lib/memcpy.S b/arch/m32r/lib/memcpy.S
index 2089a21..05987cd 100644
--- a/arch/m32r/lib/memcpy.S
+++ b/arch/m32r/lib/memcpy.S
@@ -10,8 +10,6 @@
  *        src: r1
  *        n  : r2
  */
-/* $Id$ */
-
 
 	.text
 #include <linux/linkage.h>
diff --git a/arch/m32r/lib/memset.S b/arch/m32r/lib/memset.S
index b47fa35..2b2831a 100644
--- a/arch/m32r/lib/memset.S
+++ b/arch/m32r/lib/memset.S
@@ -12,8 +12,6 @@
  *        ret: r0
  *
  */
-/* $Id$ */
-
 
 	.text
 	.global	memset
diff --git a/arch/m32r/lib/strlen.S b/arch/m32r/lib/strlen.S
index 5f41aac..916de9e 100644
--- a/arch/m32r/lib/strlen.S
+++ b/arch/m32r/lib/strlen.S
@@ -6,8 +6,6 @@
  *  size_t strlen(const char *s);
  *
  */
-/* $Id$ */
-
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
diff --git a/arch/m32r/lib/usercopy.c b/arch/m32r/lib/usercopy.c
index 896cef1..82abd15 100644
--- a/arch/m32r/lib/usercopy.c
+++ b/arch/m32r/lib/usercopy.c
@@ -293,7 +293,7 @@
 		: "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
 		: "r0", "r1", "cbit");
 
-	/* NOTE: strnlen_user() algorism:
+	/* NOTE: strnlen_user() algorithm:
 	 * {
 	 *   char *p;
 	 *   for (p = s; n-- && *p != '\0'; ++p)
@@ -369,7 +369,7 @@
 		: "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
 		: "r0", "r1", "r2", "r3", "cbit");
 
-	/* NOTE: strnlen_user() algorism:
+	/* NOTE: strnlen_user() algorithm:
 	 * {
 	 *   char *p;
 	 *   for (p = s; n-- && *p != '\0'; ++p)
diff --git a/arch/m32r/m32104ut/defconfig.m32104ut b/arch/m32r/m32104ut/defconfig.m32104ut
index 454de33..7b68fe8 100644
--- a/arch/m32r/m32104ut/defconfig.m32104ut
+++ b/arch/m32r/m32104ut/defconfig.m32104ut
@@ -1,20 +1,20 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14
-# Wed Nov  9 16:04:51 2005
+# Linux kernel version: 2.6.19
+# Wed Dec 13 17:22:20 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
@@ -22,33 +22,66 @@
 #
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-# CONFIG_KOBJECT_UEVENT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE 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"
 
 #
 # Processor type and features
@@ -70,40 +103,40 @@
 CONFIG_BUS_CLOCK=54000000
 CONFIG_TIMER_DIVIDE=128
 # CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_MEMORY_START=04000000
-CONFIG_MEMORY_SIZE=01000000
+CONFIG_MEMORY_START=0x04000000
+CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_NOHIGHMEM=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
 # CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
+CONFIG_DISCONTIGMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
 # CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_IRAM_START=0x00700000
+CONFIG_IRAM_SIZE=0x00010000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT=y
 # CONFIG_SMP is not set
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_ISA is not set
+CONFIG_ISA=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-CONFIG_PCCARD=y
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_PCMCIA=y
-CONFIG_PCMCIA_LOAD_CIS=y
-CONFIG_PCMCIA_IOCTL=y
-
-#
-# PC-card bridges
-#
+# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -112,10 +145,8 @@
 #
 # Executable file formats
 #
-CONFIG_BINFMT_FLAT=y
-# CONFIG_BINFMT_ZFLAT is not set
-# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
+# CONFIG_BINFMT_FLAT is not set
+CONFIG_BINFMT_MISC=y
 
 #
 # Networking
@@ -125,17 +156,19 @@
 #
 # Networking options
 #
-# CONFIG_PACKET is not set
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
+# CONFIG_IP_PNP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
@@ -143,13 +176,87 @@
 # 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_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+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_QUOTA is not set
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
 
 #
 # DCCP Configuration (EXPERIMENTAL)
@@ -160,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
@@ -169,11 +281,14 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
 # CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -193,8 +308,8 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -209,11 +324,21 @@
 #
 # Parallel port support
 #
-# CONFIG_PARPORT is not set
+CONFIG_PARPORT=m
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
 
 #
 # Plug and Play support
 #
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
 
 #
 # Block devices
@@ -221,37 +346,130 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CDROM_PKTCDVD is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+CONFIG_CDROM_PKTCDVD_WCACHE=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # 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 is not set
+CONFIG_BLK_DEV_IDECD=y
+# 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_IDEPNP is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
 
 #
 # Multi-device support (RAID and LVM)
 #
-# CONFIG_MD is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID456 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
 
 #
 # Fusion MPT device support
@@ -270,10 +488,16 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
+CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
 
 #
 # PHY device support
@@ -285,8 +509,33 @@
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-CONFIG_SMC91X=y
-# CONFIG_NE2000 is not set
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X 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=y
+# CONFIG_E2100 is not set
+# CONFIG_EWRK3 is not set
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -299,6 +548,7 @@
 #
 # Token Ring devices
 #
+# CONFIG_TR is not set
 
 #
 # Wireless LAN (non-hamradio)
@@ -306,14 +556,10 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+# CONFIG_PLIP is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
@@ -334,35 +580,83 @@
 #
 # Input device support
 #
-# CONFIG_INPUT is not set
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# 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_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=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA 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_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
 
 #
 # Character devices
 #
-# CONFIG_VT is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
 # Serial drivers
 #
-# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_PNP=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_M32R_SIO=y
-CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_SIO_CONSOLE is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
 
 #
 # IPMI
@@ -372,13 +666,8 @@
 #
 # Watchdog Cards
 #
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-CONFIG_SOFT_WATCHDOG=y
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
 # CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -386,21 +675,57 @@
 #
 # Ftape, the floppy tape device driver
 #
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
 #
-# CONFIG_I2C is not set
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ELEKTOR=m
+CONFIG_I2C_ISA=m
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
 
 #
 # Dallas's 1-wire bus
@@ -410,21 +735,89 @@
 #
 # Hardware Monitoring support
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
-#
+CONFIG_HWMON=y
+CONFIG_HWMON_VID=m
+# CONFIG_SENSORS_ABITUGURU is not set
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+# CONFIG_SENSORS_ADM1026 is not set
+CONFIG_SENSORS_ADM1031=m
+# CONFIG_SENSORS_ADM9240 is not set
+CONFIG_SENSORS_ASB100=m
+# CONFIG_SENSORS_ATXP1 is not set
+CONFIG_SENSORS_DS1621=m
+# CONFIG_SENSORS_F71805F is not set
+CONFIG_SENSORS_FSCHER=m
+# CONFIG_SENSORS_FSCPOS is not set
+CONFIG_SENSORS_GL518SM=m
+# CONFIG_SENSORS_GL520SM is not set
+CONFIG_SENSORS_IT87=m
+# CONFIG_SENSORS_LM63 is not set
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+# CONFIG_SENSORS_LM87 is not set
+CONFIG_SENSORS_LM90=m
+# CONFIG_SENSORS_LM92 is not set
+CONFIG_SENSORS_MAX1619=m
+# CONFIG_SENSORS_PC87360 is not set
+CONFIG_SENSORS_SMSC47M1=m
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+CONFIG_SENSORS_W83781D=m
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
 #
-# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_PMS is not set
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_M32R_AR is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
 
 #
 # Digital Video Broadcasting Devices
@@ -434,9 +827,19 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
 
 #
+# 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_BACKLIGHT_LCD_SUPPORT is not set
+
+#
 # Sound
 #
 # CONFIG_SOUND is not set
@@ -446,6 +849,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -458,33 +866,69 @@
 # 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
 #
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
-# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD_DEBUG=y
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_INOTIFY is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -494,8 +938,11 @@
 #
 # CD-ROM/DVD Filesystems
 #
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -503,7 +950,7 @@
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=932
+CONFIG_FAT_DEFAULT_CODEPAGE=437
 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
@@ -511,11 +958,13 @@
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -527,7 +976,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_CRAMFS=y
+# CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -542,10 +991,14 @@
 # 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_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
@@ -567,7 +1020,7 @@
 # Native Language Support
 #
 CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_DEFAULT="cp437"
 CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
@@ -592,7 +1045,7 @@
 # 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_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -605,32 +1058,28 @@
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
-CONFIG_NLS_UTF8=y
+# CONFIG_NLS_UTF8 is not set
 
 #
 # Profiling support
 #
-# CONFIG_PROFILING is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_MAGIC_SYSRQ=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_FS is not set
 # CONFIG_FRAME_POINTER is not set
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
 
 #
 # Security options
@@ -641,7 +1090,38 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=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 is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+# 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=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -650,8 +1130,12 @@
 #
 # Library routines
 #
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
+CONFIG_LIBCRC32C=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
diff --git a/arch/m32r/m32700ut/defconfig.m32700ut.smp b/arch/m32r/m32700ut/defconfig.m32700ut.smp
index 3e607d9..1357991 100644
--- a/arch/m32r/m32700ut/defconfig.m32700ut.smp
+++ b/arch/m32r/m32700ut/defconfig.m32700ut.smp
@@ -1,19 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc5
-# Fri Jun  3 16:20:58 2005
+# Linux kernel version: 2.6.19
+# Tue Dec 12 17:52:38 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -21,33 +20,40 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
-# CONFIG_IKCONFIG_PROC is not set
+CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -55,13 +61,31 @@
 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
 CONFIG_STOP_MACHINE=y
 
 #
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # Processor type and features
 #
 # CONFIG_PLAT_MAPPI is not set
@@ -71,8 +95,10 @@
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
 # CONFIG_PLAT_MAPPI3 is not set
+# CONFIG_PLAT_M32104UT is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_M32104 is not set
 # CONFIG_CHIP_VDEC2 is not set
 # CONFIG_CHIP_OPSP is not set
 CONFIG_MMU=y
@@ -86,37 +112,39 @@
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_NOHIGHMEM=y
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PREEMPT=y
-# CONFIG_HAVE_DEC_LOCK is not set
 CONFIG_SMP=y
-CONFIG_CHIP_M32700_TS1=y
+# CONFIG_CHIP_M32700_TS1 is not set
 CONFIG_NR_CPUS=2
-# CONFIG_NUMA is not set
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ISA is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-CONFIG_PCCARD=y
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_PCMCIA=y
-
-#
-# PC-card bridges
-#
-# CONFIG_TCIC is not set
-# CONFIG_M32R_PCC is not set
-CONFIG_M32R_CFC=y
-CONFIG_M32R_CFC_NUM=1
+# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -129,6 +157,94 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
 #
 
@@ -137,12 +253,100 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+# CONFIG_MTD_CFI_NOSWAP is not set
+CONFIG_MTD_CFI_BE_BYTE_SWAP=y
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=m
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
 
 #
 # Parallel port support
@@ -156,7 +360,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -164,23 +367,21 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
+CONFIG_ATA_OVER_ETH=m
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -189,7 +390,6 @@
 # CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECS=y
 CONFIG_BLK_DEV_IDECD=m
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -208,7 +408,9 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=m
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -220,6 +422,7 @@
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -229,26 +432,23 @@
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
 #
-# CONFIG_SCSI_SATA is not set
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
-# PCMCIA SCSI adapter support
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
-# 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)
@@ -258,6 +458,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -268,69 +469,8 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -338,6 +478,11 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -363,11 +508,6 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
@@ -375,6 +515,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -390,6 +532,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -418,7 +561,6 @@
 # CONFIG_SERIO_LIBPS2 is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -426,6 +568,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -454,8 +597,8 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 CONFIG_DS1302=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -463,17 +606,12 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -481,34 +619,51 @@
 # 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
 
 #
-# Misc devices
+# Hardware Monitoring support
 #
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
 #
-CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
 
 #
-# Video For Linux
+# Video Capture Adapters
 #
 
 #
-# Video Adapters
+# Video Capture Adapters
 #
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
 # CONFIG_VIDEO_CPIA is not set
-CONFIG_VIDEO_M32R_AR=y
-CONFIG_VIDEO_M32R_AR_M64278=y
+CONFIG_VIDEO_M32R_AR=m
+CONFIG_VIDEO_M32R_AR_M64278=m
 
 #
 # Radio Adapters
 #
-# CONFIG_RADIO_MAESTRO is not set
 
 #
 # Digital Video Broadcasting Devices
@@ -518,15 +673,16 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_SOFT_CURSOR is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_S1D13XXX=y
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -535,6 +691,7 @@
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -546,6 +703,7 @@
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_M32R_CLUT224=y
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -558,6 +716,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -567,23 +730,62 @@
 #
 # MMC/SD Card support
 #
-# CONFIG_MMC is not set
+CONFIG_MMC=y
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_TIFM_SD 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=m
+# 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=m
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
 CONFIG_JBD_DEBUG=y
 CONFIG_FS_MBCACHE=y
 CONFIG_REISERFS_FS=m
@@ -591,17 +793,19 @@
 # CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -627,15 +831,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -647,6 +849,8 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -659,12 +863,14 @@
 #
 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
@@ -673,6 +879,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -727,16 +934,23 @@
 #
 # Profiling support
 #
-# CONFIG_PROFILING is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
 
 #
 # Security options
@@ -750,12 +964,9 @@
 # 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
diff --git a/arch/m32r/m32700ut/defconfig.m32700ut.up b/arch/m32r/m32700ut/defconfig.m32700ut.up
index 2d3e7cd..190f961 100644
--- a/arch/m32r/m32700ut/defconfig.m32700ut.up
+++ b/arch/m32r/m32700ut/defconfig.m32700ut.up
@@ -1,19 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc5
-# Fri Jun  3 16:21:34 2005
+# Linux kernel version: 2.6.19
+# Tue Dec 12 12:07:08 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -22,32 +21,39 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
-# CONFIG_IKCONFIG_PROC is not set
+CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -55,12 +61,30 @@
 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
 
 #
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # Processor type and features
 #
 # CONFIG_PLAT_MAPPI is not set
@@ -70,8 +94,10 @@
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
 # CONFIG_PLAT_MAPPI3 is not set
+# CONFIG_PLAT_M32104UT is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_M32104 is not set
 # CONFIG_CHIP_VDEC2 is not set
 # CONFIG_CHIP_OPSP is not set
 CONFIG_MMU=y
@@ -85,34 +111,37 @@
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_NOHIGHMEM=y
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PREEMPT=y
-# CONFIG_HAVE_DEC_LOCK is not set
 # CONFIG_SMP is not set
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ISA is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-CONFIG_PCCARD=y
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_PCMCIA=y
-
-#
-# PC-card bridges
-#
-# CONFIG_TCIC is not set
-# CONFIG_M32R_PCC is not set
-CONFIG_M32R_CFC=y
-CONFIG_M32R_CFC_NUM=1
+# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -125,6 +154,94 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
 #
 
@@ -133,12 +250,100 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+# CONFIG_MTD_CFI_NOSWAP is not set
+CONFIG_MTD_CFI_BE_BYTE_SWAP=y
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=m
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
 
 #
 # Parallel port support
@@ -152,7 +357,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -160,23 +364,21 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
+CONFIG_ATA_OVER_ETH=m
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -185,7 +387,6 @@
 # CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECS=y
 CONFIG_BLK_DEV_IDECD=m
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -204,7 +405,9 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=m
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -216,6 +419,7 @@
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -225,26 +429,23 @@
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
 #
-# CONFIG_SCSI_SATA is not set
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
-# PCMCIA SCSI adapter support
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
-# 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)
@@ -254,6 +455,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -264,69 +466,8 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -334,6 +475,11 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -359,11 +505,6 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
@@ -371,6 +512,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -386,6 +529,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -414,7 +558,6 @@
 # CONFIG_SERIO_LIBPS2 is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -422,6 +565,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -450,8 +594,8 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 CONFIG_DS1302=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -459,17 +603,12 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -477,34 +616,51 @@
 # 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
 
 #
-# Misc devices
+# Hardware Monitoring support
 #
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
 #
-CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
 
 #
-# Video For Linux
+# Video Capture Adapters
 #
 
 #
-# Video Adapters
+# Video Capture Adapters
 #
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
 # CONFIG_VIDEO_CPIA is not set
-CONFIG_VIDEO_M32R_AR=y
-CONFIG_VIDEO_M32R_AR_M64278=y
+CONFIG_VIDEO_M32R_AR=m
+CONFIG_VIDEO_M32R_AR_M64278=m
 
 #
 # Radio Adapters
 #
-# CONFIG_RADIO_MAESTRO is not set
 
 #
 # Digital Video Broadcasting Devices
@@ -514,15 +670,16 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_SOFT_CURSOR is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_S1D13XXX=y
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -531,6 +688,7 @@
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -542,6 +700,7 @@
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_M32R_CLUT224=y
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -554,6 +713,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -563,23 +727,62 @@
 #
 # MMC/SD Card support
 #
-# CONFIG_MMC is not set
+CONFIG_MMC=y
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_TIFM_SD 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=m
+# 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=m
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
 CONFIG_JBD_DEBUG=y
 CONFIG_FS_MBCACHE=y
 CONFIG_REISERFS_FS=m
@@ -587,17 +790,19 @@
 # CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -623,15 +828,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -643,6 +846,8 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -655,12 +860,14 @@
 #
 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
@@ -669,6 +876,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -723,16 +931,23 @@
 #
 # Profiling support
 #
-# CONFIG_PROFILING is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
 
 #
 # Security options
@@ -746,12 +961,9 @@
 # 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
diff --git a/arch/m32r/mappi/defconfig.nommu b/arch/m32r/mappi/defconfig.nommu
index a8425fb..fbf6c38 100644
--- a/arch/m32r/mappi/defconfig.nommu
+++ b/arch/m32r/mappi/defconfig.nommu
@@ -1,19 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc5
-# Fri Jun  3 16:21:46 2005
+# Linux kernel version: 2.6.19
+# Wed Dec 13 17:57:45 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -22,29 +21,36 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE 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_VM_EVENT_COUNTERS=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -52,12 +58,30 @@
 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
 
 #
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # Processor type and features
 #
 CONFIG_PLAT_MAPPI=y
@@ -67,8 +91,10 @@
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
 # CONFIG_PLAT_MAPPI3 is not set
+# CONFIG_PLAT_M32104UT is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_M32104 is not set
 # CONFIG_CHIP_VDEC2 is not set
 # CONFIG_CHIP_OPSP is not set
 # CONFIG_MMU is not set
@@ -82,18 +108,31 @@
 CONFIG_MEMORY_START=0x00000000
 CONFIG_MEMORY_SIZE=0x00E00000
 CONFIG_NOHIGHMEM=y
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PREEMPT=y
-# CONFIG_HAVE_DEC_LOCK is not set
 # CONFIG_SMP is not set
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ISA is not set
 
 #
@@ -102,12 +141,14 @@
 CONFIG_PCCARD=y
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 
 #
 # PC-card bridges
 #
-# CONFIG_TCIC is not set
 CONFIG_M32R_PCC=y
+CONFIG_PCCARD_NONSTATIC=y
 
 #
 # PCI Hotplug Support
@@ -122,6 +163,94 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
 #
 
@@ -130,7 +259,13 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -149,7 +284,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -157,18 +291,15 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -178,7 +309,13 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
 
 #
 # Multi-device support (RAID and LVM)
@@ -188,6 +325,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -198,69 +336,8 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -268,6 +345,10 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+
+#
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
@@ -303,6 +384,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -318,6 +401,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -346,7 +430,6 @@
 # CONFIG_SERIO_LIBPS2 is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -366,7 +449,6 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_M32R_SIO=y
 CONFIG_SERIAL_M32R_SIO_CONSOLE=y
-# CONFIG_SERIAL_M32R_PLDSIO is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -380,25 +462,27 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # 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
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -406,13 +490,25 @@
 # 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
 
 #
-# Misc devices
+# Hardware Monitoring support
 #
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
@@ -427,7 +523,9 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -439,6 +537,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -451,30 +554,72 @@
 # 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD 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_EXT4DEV_FS 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
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -493,15 +638,12 @@
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -525,12 +667,14 @@
 #
 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
@@ -539,6 +683,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -599,10 +744,16 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
 
 #
 # Security options
@@ -616,12 +767,9 @@
 # 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
diff --git a/arch/m32r/mappi/defconfig.smp b/arch/m32r/mappi/defconfig.smp
index 1a7f3cd..16866920 100644
--- a/arch/m32r/mappi/defconfig.smp
+++ b/arch/m32r/mappi/defconfig.smp
@@ -1,21 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc5
-# Fri Jun  3 16:21:52 2005
+# Linux kernel version: 2.6.19
+# Wed Dec 13 17:50:59 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
-CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -23,32 +20,39 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -56,13 +60,31 @@
 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
 CONFIG_STOP_MACHINE=y
 
 #
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # Processor type and features
 #
 CONFIG_PLAT_MAPPI=y
@@ -72,8 +94,10 @@
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
 # CONFIG_PLAT_MAPPI3 is not set
+# CONFIG_PLAT_M32104UT is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_M32104 is not set
 # CONFIG_CHIP_VDEC2 is not set
 # CONFIG_CHIP_OPSP is not set
 CONFIG_MMU=y
@@ -87,23 +111,33 @@
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_NOHIGHMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
 CONFIG_IRAM_START=0x00f00000
 CONFIG_IRAM_SIZE=0x00080000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PREEMPT=y
-# CONFIG_HAVE_DEC_LOCK is not set
 CONFIG_SMP=y
 CONFIG_CHIP_M32700_TS1=y
 CONFIG_NR_CPUS=2
-# CONFIG_NUMA is not set
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ISA is not set
 
 #
@@ -112,12 +146,14 @@
 CONFIG_PCCARD=y
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 
 #
 # PC-card bridges
 #
-# CONFIG_TCIC is not set
 CONFIG_M32R_PCC=y
+CONFIG_PCCARD_NONSTATIC=y
 
 #
 # PCI Hotplug Support
@@ -130,6 +166,93 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
 #
 
@@ -138,7 +261,13 @@
 #
 # CONFIG_STANDALONE is not set
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -161,6 +290,8 @@
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -186,6 +317,7 @@
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -193,7 +325,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
 
 #
@@ -209,6 +340,11 @@
 # CONFIG_MTD_NAND is not set
 
 #
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
@@ -220,7 +356,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -228,23 +363,21 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=m
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=m
 
 #
@@ -271,7 +404,13 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
 
 #
 # Multi-device support (RAID and LVM)
@@ -281,79 +420,19 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -361,6 +440,10 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+
+#
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
@@ -396,6 +479,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -411,6 +496,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -442,7 +528,6 @@
 # CONFIG_SERIO_LIBPS2 is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -462,7 +547,6 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_M32R_SIO=y
 CONFIG_SERIAL_M32R_SIO_CONSOLE=y
-# CONFIG_SERIAL_M32R_PLDSIO is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -476,25 +560,27 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # 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
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -502,13 +588,25 @@
 # 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
 
 #
-# Misc devices
+# Hardware Monitoring support
 #
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
@@ -523,7 +621,9 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -535,6 +635,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -547,30 +652,73 @@
 # 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD 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_EXT4DEV_FS 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
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -595,16 +743,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLBFS is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -621,8 +766,9 @@
 CONFIG_JFFS_PROC_FS=y
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -639,12 +785,14 @@
 #
 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
@@ -653,6 +801,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -713,10 +862,16 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
 
 #
 # Security options
@@ -730,13 +885,10 @@
 # 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=y
diff --git a/arch/m32r/mappi/defconfig.up b/arch/m32r/mappi/defconfig.up
index 38910fb..5ba0060 100644
--- a/arch/m32r/mappi/defconfig.up
+++ b/arch/m32r/mappi/defconfig.up
@@ -1,20 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc5
-# Fri Jun  3 16:21:59 2005
+# Linux kernel version: 2.6.19
+# Wed Dec 13 17:51:20 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -23,31 +21,38 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -55,12 +60,30 @@
 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
 
 #
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # Processor type and features
 #
 CONFIG_PLAT_MAPPI=y
@@ -70,8 +93,10 @@
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
 # CONFIG_PLAT_MAPPI3 is not set
+# CONFIG_PLAT_M32104UT is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_M32104 is not set
 # CONFIG_CHIP_VDEC2 is not set
 # CONFIG_CHIP_OPSP is not set
 CONFIG_MMU=y
@@ -85,20 +110,31 @@
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_NOHIGHMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
 CONFIG_IRAM_START=0x00f00000
 CONFIG_IRAM_SIZE=0x00080000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PREEMPT=y
-# CONFIG_HAVE_DEC_LOCK is not set
 # CONFIG_SMP is not set
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ISA is not set
 
 #
@@ -107,12 +143,14 @@
 CONFIG_PCCARD=y
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 
 #
 # PC-card bridges
 #
-# CONFIG_TCIC is not set
 CONFIG_M32R_PCC=y
+CONFIG_PCCARD_NONSTATIC=y
 
 #
 # PCI Hotplug Support
@@ -125,6 +163,93 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
 #
 
@@ -133,7 +258,13 @@
 #
 # CONFIG_STANDALONE is not set
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -156,6 +287,8 @@
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -181,6 +314,7 @@
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -188,7 +322,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
 
 #
@@ -204,6 +337,11 @@
 # CONFIG_MTD_NAND is not set
 
 #
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
@@ -215,7 +353,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -223,23 +360,21 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=m
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=m
 
 #
@@ -266,7 +401,13 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
 
 #
 # Multi-device support (RAID and LVM)
@@ -276,79 +417,19 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -356,6 +437,10 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+
+#
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
@@ -391,6 +476,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -406,6 +493,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -437,7 +525,6 @@
 # CONFIG_SERIO_LIBPS2 is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -457,7 +544,6 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_M32R_SIO=y
 CONFIG_SERIAL_M32R_SIO_CONSOLE=y
-# CONFIG_SERIAL_M32R_PLDSIO is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -471,25 +557,27 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # 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
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -497,13 +585,25 @@
 # 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
 
 #
-# Misc devices
+# Hardware Monitoring support
 #
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
@@ -518,7 +618,9 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -530,6 +632,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -542,30 +649,73 @@
 # 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD 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_EXT4DEV_FS 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
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -590,16 +740,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLBFS is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -616,8 +763,9 @@
 CONFIG_JFFS_PROC_FS=y
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -634,12 +782,14 @@
 #
 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
@@ -648,6 +798,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -708,10 +859,16 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
 
 #
 # Security options
@@ -725,13 +882,10 @@
 # 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=y
diff --git a/arch/m32r/mappi2/defconfig.opsp b/arch/m32r/mappi2/defconfig.opsp
new file mode 100644
index 0000000..b379ae9
--- /dev/null
+++ b/arch/m32r/mappi2/defconfig.opsp
@@ -0,0 +1,883 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19
+# Wed Dec 13 19:40:30 2006
+#
+CONFIG_M32R=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=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 is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+CONFIG_PLAT_MAPPI2=y
+# CONFIG_PLAT_MAPPI3 is not set
+# CONFIG_PLAT_M32104UT is not set
+# CONFIG_CHIP_M32700 is not set
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_M32104 is not set
+# CONFIG_CHIP_VDEC2 is not set
+CONFIG_CHIP_OPSP=y
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=16
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_NOHIGHMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00008000
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PREEMPT=y
+# CONFIG_SMP is not set
+CONFIG_NODES_SHIFT=1
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_ISA is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+# CONFIG_M32R_CFC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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=y
+# CONFIG_SYS_HYPERVISOR 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_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+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_IDECS=y
+CONFIG_BLK_DEV_IDECD=m
+# 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_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA 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=m
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transports
+#
+# 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# 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
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# 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
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_NE2000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA 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
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# 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=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# 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_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+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_HW_RANDOM=y
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# 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
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_M32R_AR is not set
+
+#
+# Radio Adapters
+#
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# 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'
+#
+
+#
+# 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
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# 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_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_JBD_DEBUG=y
+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 is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# 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_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# 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 is not set
+# 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=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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/m32r/mappi2/defconfig.vdec2 b/arch/m32r/mappi2/defconfig.vdec2
index 56f287b..fe5b2a6 100644
--- a/arch/m32r/mappi2/defconfig.vdec2
+++ b/arch/m32r/mappi2/defconfig.vdec2
@@ -1,19 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc5
-# Fri Jun  3 16:22:02 2005
+# Linux kernel version: 2.6.19
+# Wed Dec 13 19:31:44 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -22,32 +21,39 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -55,12 +61,30 @@
 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
 
 #
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # Processor type and features
 #
 # CONFIG_PLAT_MAPPI is not set
@@ -70,8 +94,10 @@
 # CONFIG_PLAT_OAKS32R is not set
 CONFIG_PLAT_MAPPI2=y
 # CONFIG_PLAT_MAPPI3 is not set
+# CONFIG_PLAT_M32104UT is not set
 # CONFIG_CHIP_M32700 is not set
 # CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_M32104 is not set
 CONFIG_CHIP_VDEC2=y
 # CONFIG_CHIP_OPSP is not set
 CONFIG_MMU=y
@@ -83,18 +109,31 @@
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_NOHIGHMEM=y
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00008000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PREEMPT=y
-# CONFIG_HAVE_DEC_LOCK is not set
 # CONFIG_SMP is not set
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ISA is not set
 
 #
@@ -103,11 +142,12 @@
 CONFIG_PCCARD=y
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 
 #
 # PC-card bridges
 #
-# CONFIG_TCIC is not set
 # CONFIG_M32R_CFC is not set
 
 #
@@ -121,6 +161,94 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
 #
 
@@ -129,7 +257,13 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -148,7 +282,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -156,23 +289,21 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -200,7 +331,9 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=m
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -212,6 +345,7 @@
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -221,16 +355,18 @@
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
 #
-# CONFIG_SCSI_SATA is not set
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
@@ -243,6 +379,10 @@
 # CONFIG_PCMCIA_SYM53C500 is not set
 
 #
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+
+#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -250,6 +390,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -260,69 +401,8 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -330,6 +410,11 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -367,6 +452,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -382,6 +469,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -410,7 +498,6 @@
 # CONFIG_SERIO_LIBPS2 is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -418,6 +505,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -432,7 +520,6 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_M32R_SIO=y
 CONFIG_SERIAL_M32R_SIO_CONSOLE=y
-# CONFIG_SERIAL_M32R_PLDSIO is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -446,25 +533,27 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # 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
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -472,33 +561,50 @@
 # 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
 
 #
-# Misc devices
+# Hardware Monitoring support
 #
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
 #
 CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
 
 #
-# Video For Linux
+# Video Capture Adapters
 #
 
 #
-# Video Adapters
+# Video Capture Adapters
 #
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
 # CONFIG_VIDEO_CPIA is not set
 # CONFIG_VIDEO_M32R_AR is not set
 
 #
 # Radio Adapters
 #
-# CONFIG_RADIO_MAESTRO is not set
 
 #
 # Digital Video Broadcasting Devices
@@ -508,6 +614,7 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
 
 #
@@ -515,6 +622,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -526,6 +634,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -538,38 +651,73 @@
 # 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=m
+# 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=m
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
 CONFIG_JBD_DEBUG=y
 CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -595,15 +743,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -627,12 +773,14 @@
 #
 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
@@ -641,6 +789,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -701,10 +850,16 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
 
 #
 # Security options
@@ -718,12 +873,9 @@
 # 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
diff --git a/arch/m32r/mappi3/defconfig.smp b/arch/m32r/mappi3/defconfig.smp
index 2eebe75f..2f35226 100644
--- a/arch/m32r/mappi3/defconfig.smp
+++ b/arch/m32r/mappi3/defconfig.smp
@@ -1,21 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc5
-# Tue May 31 17:55:34 2005
+# Linux kernel version: 2.6.19
+# Mon Dec 11 19:57:33 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
-CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -23,32 +20,39 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -56,13 +60,31 @@
 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
 CONFIG_STOP_MACHINE=y
 
 #
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # Processor type and features
 #
 # CONFIG_PLAT_MAPPI is not set
@@ -72,8 +94,10 @@
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
 CONFIG_PLAT_MAPPI3=y
+# CONFIG_PLAT_M32104UT is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_M32104 is not set
 # CONFIG_CHIP_VDEC2 is not set
 # CONFIG_CHIP_OPSP is not set
 CONFIG_MMU=y
@@ -87,23 +111,33 @@
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 CONFIG_NOHIGHMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
 CONFIG_IRAM_START=0x00f00000
 CONFIG_IRAM_SIZE=0x00080000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PREEMPT=y
-# CONFIG_HAVE_DEC_LOCK is not set
 CONFIG_SMP=y
 # CONFIG_CHIP_M32700_TS1 is not set
 CONFIG_NR_CPUS=2
-# CONFIG_NUMA is not set
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ISA is not set
 
 #
@@ -112,11 +146,12 @@
 CONFIG_PCCARD=y
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 
 #
 # PC-card bridges
 #
-# CONFIG_TCIC is not set
 # CONFIG_M32R_PCC is not set
 # CONFIG_M32R_CFC is not set
 
@@ -131,6 +166,93 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
 #
 
@@ -140,6 +262,12 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -162,6 +290,8 @@
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -187,6 +317,7 @@
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -194,7 +325,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
 
 #
@@ -210,6 +340,11 @@
 # CONFIG_MTD_NAND is not set
 
 #
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
@@ -221,7 +356,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -229,23 +363,21 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -254,7 +386,7 @@
 # CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECS=m
 CONFIG_BLK_DEV_IDECD=m
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -272,7 +404,13 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
 
 #
 # Multi-device support (RAID and LVM)
@@ -282,79 +420,19 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -362,6 +440,11 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -399,6 +482,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -414,6 +499,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -445,7 +531,6 @@
 # CONFIG_SERIO_LIBPS2 is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -465,7 +550,6 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_M32R_SIO=y
 CONFIG_SERIAL_M32R_SIO_CONSOLE=y
-# CONFIG_SERIAL_M32R_PLDSIO is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -479,25 +563,27 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # 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
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -505,13 +591,25 @@
 # 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
 
 #
-# Misc devices
+# Hardware Monitoring support
 #
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
@@ -526,7 +624,9 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -538,6 +638,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -550,35 +655,73 @@
 # 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
 
 #
 # 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_EXT4DEV_FS 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
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -603,16 +746,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLBFS is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -629,8 +769,9 @@
 CONFIG_JFFS_PROC_FS=y
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -647,12 +788,14 @@
 #
 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
@@ -661,6 +804,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -721,10 +865,16 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
 
 #
 # Security options
@@ -738,13 +888,10 @@
 # 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=y
diff --git a/arch/m32r/mm/fault-nommu.c b/arch/m32r/mm/fault-nommu.c
index 03fc4c8..9880aba 100644
--- a/arch/m32r/mm/fault-nommu.c
+++ b/arch/m32r/mm/fault-nommu.c
@@ -7,8 +7,6 @@
  *    Copyright (C) 1995  Linus Torvalds
  */
 
-/* $Id: fault-nommu.c,v 1.1 2004/03/30 06:40:59 sakugawa Exp $ */
-
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -46,32 +44,6 @@
 #define tlb_entry_d tlb_entry_d_dat[smp_processor_id()]
 #endif
 
-/*
- * Unlock any spinlocks which will prevent us from getting the
- * message out
- */
-void bust_spinlocks(int yes)
-{
-	int loglevel_save = console_loglevel;
-
-	if (yes) {
-		oops_in_progress = 1;
-		return;
-	}
-#ifdef CONFIG_VT
-	unblank_screen();
-#endif
-	oops_in_progress = 0;
-	/*
-	 * OK, the message is on the console.  Now we call printk()
-	 * without oops_in_progress set so that printk will give klogd
-	 * a poke.  Hold onto your hats...
-	 */
-	console_loglevel = 15;		/* NMI oopser may have shut the console up */
-	printk(" ");
-	console_loglevel = loglevel_save;
-}
-
 void do_BUG(const char *file, int line)
 {
 	bust_spinlocks(1);
@@ -161,4 +133,3 @@
 {
 	BUG();
 }
-
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c
index 9b9feb0..037d58e 100644
--- a/arch/m32r/mm/fault.c
+++ b/arch/m32r/mm/fault.c
@@ -49,32 +49,6 @@
 
 extern void init_tlb(void);
 
-/*
- * Unlock any spinlocks which will prevent us from getting the
- * message out
- */
-void bust_spinlocks(int yes)
-{
-	int loglevel_save = console_loglevel;
-
-	if (yes) {
-		oops_in_progress = 1;
-		return;
-	}
-#ifdef CONFIG_VT
-	unblank_screen();
-#endif
-	oops_in_progress = 0;
-	/*
-	 * OK, the message is on the console.  Now we call printk()
-	 * without oops_in_progress set so that printk will give klogd
-	 * a poke.  Hold onto your hats...
-	 */
-	console_loglevel = 15;		/* NMI oopser may have shut the console up */
-	printk(" ");
-	console_loglevel = loglevel_save;
-}
-
 /*======================================================================*
  * do_page_fault()
  *======================================================================*
@@ -362,8 +336,10 @@
 		if (!pte_present(*pte_k))
 			goto no_context;
 
-		addr = (address & PAGE_MASK) | (error_code & ACE_INSTRUCTION);
+		addr = (address & PAGE_MASK);
+		set_thread_fault_code(error_code);
 		update_mmu_cache(NULL, addr, *pte_k);
+		set_thread_fault_code(0);
 		return;
 	}
 }
@@ -377,7 +353,7 @@
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr,
 	pte_t pte)
 {
-	unsigned long *entry1, *entry2;
+	volatile unsigned long *entry1, *entry2;
 	unsigned long pte_data, flags;
 	unsigned int *entry_dat;
 	int inst = get_thread_fault_code() & ACE_INSTRUCTION;
@@ -391,30 +367,26 @@
 
 	vaddr = (vaddr & PAGE_MASK) | get_asid();
 
-#ifdef CONFIG_CHIP_OPSP
-	entry1 = (unsigned long *)ITLB_BASE;
-	for(i = 0 ; i < NR_TLB_ENTRIES; i++) {
-	        if(*entry1++ == vaddr) {
-	                pte_data = pte_val(pte);
-	                set_tlb_data(entry1, pte_data);
-	                break;
-	        }
-	        entry1++;
-	}
-	entry2 = (unsigned long *)DTLB_BASE;
-	for(i = 0 ; i < NR_TLB_ENTRIES ; i++) {
-	        if(*entry2++ == vaddr) {
-	                pte_data = pte_val(pte);
-	                set_tlb_data(entry2, pte_data);
-	                break;
-	        }
-	        entry2++;
-	}
-	local_irq_restore(flags);
-	return;
-#else
 	pte_data = pte_val(pte);
 
+#ifdef CONFIG_CHIP_OPSP
+	entry1 = (unsigned long *)ITLB_BASE;
+	for (i = 0; i < NR_TLB_ENTRIES; i++) {
+		if (*entry1++ == vaddr) {
+			set_tlb_data(entry1, pte_data);
+			break;
+		}
+		entry1++;
+	}
+	entry2 = (unsigned long *)DTLB_BASE;
+	for (i = 0; i < NR_TLB_ENTRIES; i++) {
+		if (*entry2++ == vaddr) {
+			set_tlb_data(entry2, pte_data);
+			break;
+		}
+		entry2++;
+	}
+#else
 	/*
 	 * Update TLB entries
 	 *  entry1: ITLB entry address
@@ -439,6 +411,7 @@
 		"i" (MSVA_offset), "i" (MTOP_offset), "i" (MIDXI_offset)
 		: "r4", "memory"
 	);
+#endif
 
 	if ((!inst && entry2 >= DTLB_END) || (inst && entry1 >= ITLB_END))
 		goto notfound;
@@ -482,7 +455,6 @@
 	set_tlb_data(entry1, pte_data);
 
 	goto found;
-#endif
 }
 
 /*======================================================================*
diff --git a/arch/m32r/mm/mmu.S b/arch/m32r/mm/mmu.S
index 9a4d40b..8bb74b1 100644
--- a/arch/m32r/mm/mmu.S
+++ b/arch/m32r/mm/mmu.S
@@ -4,8 +4,6 @@
  *  Copyright (C) 2001 by Hiroyuki Kondo
  */
 
-/* $Id: mmu.S,v 1.15 2004/03/16 02:56:27 takata Exp $ */
-
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/smp.h>
@@ -345,5 +343,4 @@
 
 #endif  /* CONFIG_MMU */
 
-.end
-
+	.end
diff --git a/arch/m32r/oaks32r/defconfig.nommu b/arch/m32r/oaks32r/defconfig.nommu
index 3f9fe51..aaa0082 100644
--- a/arch/m32r/oaks32r/defconfig.nommu
+++ b/arch/m32r/oaks32r/defconfig.nommu
@@ -1,19 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc5
-# Fri Jun  3 16:22:04 2005
+# Linux kernel version: 2.6.19
+# Tue Dec 12 12:09:17 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -22,28 +21,35 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE 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_VM_EVENT_COUNTERS=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -51,12 +57,30 @@
 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
 
 #
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # Processor type and features
 #
 # CONFIG_PLAT_MAPPI is not set
@@ -66,8 +90,10 @@
 CONFIG_PLAT_OAKS32R=y
 # CONFIG_PLAT_MAPPI2 is not set
 # CONFIG_PLAT_MAPPI3 is not set
+# CONFIG_PLAT_M32104UT is not set
 # CONFIG_CHIP_M32700 is not set
 CONFIG_CHIP_M32102=y
+# CONFIG_CHIP_M32104 is not set
 # CONFIG_CHIP_VDEC2 is not set
 # CONFIG_CHIP_OPSP is not set
 CONFIG_ISA_M32R=y
@@ -77,18 +103,31 @@
 CONFIG_MEMORY_START=0x01000000
 CONFIG_MEMORY_SIZE=0x00800000
 CONFIG_NOHIGHMEM=y
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00010000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PREEMPT=y
-# CONFIG_HAVE_DEC_LOCK is not set
 # CONFIG_SMP is not set
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ISA is not set
 
 #
@@ -109,6 +148,94 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
 #
 
@@ -118,6 +245,12 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -136,7 +269,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -144,18 +276,15 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -165,7 +294,13 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
 
 #
 # Multi-device support (RAID and LVM)
@@ -175,6 +310,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -185,69 +321,8 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -255,6 +330,10 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+
+#
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
@@ -285,6 +364,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -300,6 +381,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -328,7 +410,6 @@
 # CONFIG_SERIO_LIBPS2 is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -348,7 +429,6 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_M32R_SIO=y
 CONFIG_SERIAL_M32R_SIO_CONSOLE=y
-# CONFIG_SERIAL_M32R_PLDSIO is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -362,20 +442,20 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -383,13 +463,25 @@
 # 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
 
 #
-# Misc devices
+# Hardware Monitoring support
 #
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
@@ -404,7 +496,9 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -416,6 +510,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -428,9 +527,43 @@
 # 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
 
 #
 # File systems
@@ -438,20 +571,22 @@
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -470,13 +605,12 @@
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -500,12 +634,14 @@
 #
 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
@@ -514,6 +650,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -574,10 +711,16 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
 
 #
 # Security options
@@ -591,12 +734,9 @@
 # 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
diff --git a/arch/m32r/opsput/defconfig.opsput b/arch/m32r/opsput/defconfig.opsput
index 66adec6..461f95e 100644
--- a/arch/m32r/opsput/defconfig.opsput
+++ b/arch/m32r/opsput/defconfig.opsput
@@ -1,19 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc5
-# Fri Jun  3 16:22:06 2005
+# Linux kernel version: 2.6.19
+# Wed Dec 13 18:34:36 2006
 #
 CONFIG_M32R=y
-# CONFIG_UID16 is not set
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -21,32 +20,39 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -54,12 +60,30 @@
 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
 
 #
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # Processor type and features
 #
 # CONFIG_PLAT_MAPPI is not set
@@ -69,8 +93,10 @@
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
 # CONFIG_PLAT_MAPPI3 is not set
+# CONFIG_PLAT_M32104UT is not set
 # CONFIG_CHIP_M32700 is not set
 # CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_M32104 is not set
 # CONFIG_CHIP_VDEC2 is not set
 CONFIG_CHIP_OPSP=y
 CONFIG_MMU=y
@@ -84,17 +110,31 @@
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_NOHIGHMEM=y
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00010000
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 # CONFIG_PREEMPT is not set
 # CONFIG_SMP is not set
+CONFIG_NODES_SHIFT=1
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ISA is not set
 
 #
@@ -103,13 +143,15 @@
 CONFIG_PCCARD=y
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 
 #
 # PC-card bridges
 #
-# CONFIG_TCIC is not set
 CONFIG_M32R_CFC=y
 CONFIG_M32R_CFC_NUM=1
+CONFIG_PCCARD_NONSTATIC=y
 
 #
 # PCI Hotplug Support
@@ -122,6 +164,94 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
 #
 
@@ -130,8 +260,14 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -150,7 +286,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -158,18 +293,15 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
-# IO Schedulers
+# Misc devices
 #
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_TIFM_CORE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -179,7 +311,9 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=m
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -191,6 +325,7 @@
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -200,16 +335,18 @@
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
 #
-# CONFIG_SCSI_SATA is not set
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
@@ -222,6 +359,10 @@
 # CONFIG_PCMCIA_SYM53C500 is not set
 
 #
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+
+#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -229,6 +370,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -239,69 +381,8 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -309,6 +390,11 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -346,6 +432,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -361,6 +449,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -389,7 +478,6 @@
 # CONFIG_SERIO_LIBPS2 is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -423,8 +511,8 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 CONFIG_DS1302=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -432,17 +520,19 @@
 #
 # 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
 
 #
 # TPM devices
 #
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -450,13 +540,25 @@
 # 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
 
 #
-# Misc devices
+# Hardware Monitoring support
 #
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
@@ -471,7 +573,9 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -483,6 +587,11 @@
 #
 # 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'
+#
 
 #
 # USB Gadget Support
@@ -495,38 +604,73 @@
 # 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=m
+# 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=m
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
 CONFIG_JBD_DEBUG=y
 CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -552,15 +696,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -584,12 +726,14 @@
 #
 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
@@ -598,6 +742,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -658,21 +803,32 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
 
 #
 # Security options
@@ -686,12 +842,9 @@
 # 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
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 70a577c..a8e1e60 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -42,6 +42,9 @@
 	depends on Q40 || (BROKEN && SUN3X)
 	default y
 
+config NO_IOPORT
+	def_bool y
+
 mainmenu "Linux/68k Kernel Configuration"
 
 source "init/Kconfig"
@@ -439,6 +442,10 @@
 	depends on Q40 || AMIGA_PCMCIA || GG2
 	default y
 
+config ZONE_DMA
+	bool
+	default y
+
 source "drivers/pci/Kconfig"
 
 source "drivers/zorro/Kconfig"
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index d01deb4..ab3fd52 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -174,7 +174,7 @@
 void __init stdma_init(void)
 {
 	stdma_isr = NULL;
-	request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | SA_SHIRQ,
+	request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
 	            "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int);
 }
 
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
index 15c16b6..a812d03 100644
--- a/arch/m68k/bvme6000/rtc.c
+++ b/arch/m68k/bvme6000/rtc.c
@@ -159,7 +159,7 @@
  *	The various file operations we support.
  */
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.ioctl =	rtc_ioctl,
 	.open =		rtc_open,
 	.release =	rtc_release,
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 1c9ecaa..0b68ab8 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -10,7 +10,9 @@
 extra-y	+= vmlinux.lds
 
 obj-y	:= entry.o process.o traps.o ints.o signal.o ptrace.o \
-	   sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
+	   sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o
+
+devres-y = ../../../kernel/irq/devres.o
 
 obj-$(CONFIG_PCI)	+= bios32.o
 obj-$(CONFIG_MODULES)	+= module.o
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 84aceca..b66c97c 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/errno.h>
 #include <linux/init.h>
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index ef89060..7fd2720 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -76,7 +76,7 @@
 
 	if (regno == PT_USP)
 		addr = &task->thread.usp;
-	else if (regno < sizeof(regoff)/sizeof(regoff[0]))
+	else if (regno < ARRAY_SIZE(regoff))
 		addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
 	else
 		return 0;
@@ -93,7 +93,7 @@
 
 	if (regno == PT_USP)
 		addr = &task->thread.usp;
-	else if (regno < sizeof(regoff)/sizeof(regoff[0]))
+	else if (regno < ARRAY_SIZE(regoff))
 		addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
 	else
 		return -1;
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 9af3ee0..42b8fd0 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -256,7 +256,7 @@
 	init_mm.brk = (unsigned long) &_end;
 
 	*cmdline_p = m68k_command_line;
-	memcpy(saved_command_line, *cmdline_p, CL_SIZE);
+	memcpy(boot_command_line, *cmdline_p, CL_SIZE);
 
 	/* Parse the command line for arch-specific options.
 	 * For the m68k, this is currently only "debug=xxx" to enable printing
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 2a599c3..4c065f9 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -159,12 +159,3 @@
 }
 
 EXPORT_SYMBOL(do_settimeofday);
-
-/*
- * Scheduler clock - returns current time in ns units.
- */
-unsigned long long sched_clock(void)
-{
-       return (unsigned long long)jiffies*(1000000000/HZ);
-}
-
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 759fa244..a27a4fa 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -1011,7 +1011,7 @@
 void bad_super_trap (struct frame *fp)
 {
 	console_verbose();
-	if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
+	if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
 		printk ("*** %s ***   FORMAT=%X\n",
 			vec_names[(fp->ptregs.vector) >> 2],
 			fp->ptregs.format);
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index d279445..437b4f8 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -61,10 +61,12 @@
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
   SECURITY_INIT
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(8192);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
   . = ALIGN(8192);
   __init_end = .;
 
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index 8c7eccb..2868e20 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -55,10 +55,12 @@
 	.con_initcall.init : { *(.con_initcall.init) }
 	__con_initcall_end = .;
 	SECURITY_INIT
+#ifdef CONFIG_BLK_DEV_INITRD
 	. = ALIGN(8192);
 	__initramfs_start = .;
 	.init.ramfs : { *(.init.ramfs) }
 	__initramfs_end = .;
+#endif
 	. = ALIGN(8192);
 	__init_end = .;
 	.data.init.task : { *(.data.init_task) }
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index b0e4c08..272d47e 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -147,7 +147,7 @@
  *	The various file operations we support.
  */
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.ioctl =	rtc_ioctl,
 	.open =		rtc_open,
 	.release =	rtc_release,
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 25993c2..823f737 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -17,6 +17,10 @@
 	bool
 	default n
 
+config ZONE_DMA
+	bool
+	default y
+
 config RWSEM_GENERIC_SPINLOCK
 	bool
 	default y
@@ -49,6 +53,9 @@
 	bool
 	default y
 
+config NO_IOPORT
+	def_bool y
+
 source "init/Kconfig"
 
 menu "Processor type and features"
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index 9130119..72d3496 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -62,7 +62,7 @@
 
 	if (regno == PT_USP)
 		addr = &task->thread.usp;
-	else if (regno < sizeof(regoff)/sizeof(regoff[0]))
+	else if (regno < ARRAY_SIZE(regoff))
 		addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
 	else
 		return 0;
@@ -79,7 +79,7 @@
 
 	if (regno == PT_USP)
 		addr = &task->thread.usp;
-	else if (regno < sizeof(regoff)/sizeof(regoff[0]))
+	else if (regno < ARRAY_SIZE(regoff))
 		addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
 	else
 		return -1;
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 9cf2e4d..d5c25d2 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -44,7 +44,7 @@
 EXPORT_SYMBOL(memory_start);
 EXPORT_SYMBOL(memory_end);
 
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
 
 /* setup some dummy routines */
 static void dummy_waitbut(void)
@@ -231,8 +231,8 @@
 
 	/* Keep a copy of command line */
 	*cmdline_p = &command_line[0];
-	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = 0;
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = 0;
 
 #ifdef DEBUG
 	if (strlen(*cmdline_p))
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index 9226264..467053d 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -23,6 +23,7 @@
 
 #include <asm/machdep.h>
 #include <asm/io.h>
+#include <asm/irq_regs.h>
 
 #define	TICK_SIZE (tick_nsec / 1000)
 
@@ -38,7 +39,7 @@
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
+static irqreturn_t timer_interrupt(int irq, void *dummy)
 {
 	/* last time the cmos clock got updated */
 	static long last_rtc_update=0;
@@ -51,7 +52,7 @@
 
 	do_timer(1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
 	if (current->pid)
 		profile_tick(CPU_PROFILING);
@@ -173,13 +174,4 @@
 	clock_was_set();
 	return 0;
 }
-
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
 EXPORT_SYMBOL(do_settimeofday);
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index 9129b3a..bed5f47 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -158,7 +158,7 @@
 void bad_super_trap(struct frame *fp)
 {
 	console_verbose();
-	if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
+	if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
 		printk (KERN_WARNING "*** %s ***   FORMAT=%X\n",
 			vec_names[(fp->ptregs.vector) >> 2],
 			fp->ptregs.format);
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 2b2a10d..c86a1bf 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -87,6 +87,16 @@
 		*(__ksymtab_gpl)
 		__stop___ksymtab_gpl = .;
 
+		/* Kernel symbol table: Normal unused symbols */
+		__start___ksymtab_unused = .;
+		*(__ksymtab_unused)
+		__stop___ksymtab_unused = .;
+
+		/* Kernel symbol table: GPL-only unused symbols */
+		__start___ksymtab_unused_gpl = .;
+		*(__ksymtab_unused_gpl)
+		__stop___ksymtab_unused_gpl = .;
+
 		/* Kernel symbol table: GPL-future symbols */
 		__start___ksymtab_gpl_future = .;
 		*(__ksymtab_gpl_future)
@@ -149,10 +159,12 @@
 		__security_initcall_start = .;
 		*(.security_initcall.init)
 		__security_initcall_end = .;
+#ifdef CONFIG_BLK_DEV_INITRD
 		. = ALIGN(4);
 		__initramfs_start = .;
 		*(.init.ramfs)
 		__initramfs_end = .;
+#endif
 		. = ALIGN(4096);
 		__init_end = .;
 	} > INIT
diff --git a/arch/m68knommu/platform/5206/config.c b/arch/m68knommu/platform/5206/config.c
index 34657f8..3343830 100644
--- a/arch/m68knommu/platform/5206/config.c
+++ b/arch/m68knommu/platform/5206/config.c
@@ -26,7 +26,7 @@
 /***************************************************************************/
 
 void coldfire_tick(void);
-void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_timer_init(irq_handler_t handler);
 unsigned long coldfire_timer_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c
index 48e4d62..0f67320 100644
--- a/arch/m68knommu/platform/5206e/config.c
+++ b/arch/m68knommu/platform/5206e/config.c
@@ -25,7 +25,7 @@
 /***************************************************************************/
 
 void coldfire_tick(void);
-void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_timer_init(irq_handler_t handler);
 unsigned long coldfire_timer_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/520x/config.c b/arch/m68knommu/platform/520x/config.c
index 823f561..58b2878 100644
--- a/arch/m68knommu/platform/520x/config.c
+++ b/arch/m68knommu/platform/520x/config.c
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/param.h>
+#include <linux/interrupt.h>
 #include <asm/machdep.h>
 #include <asm/dma.h>
 
@@ -27,7 +28,7 @@
 /***************************************************************************/
 
 void coldfire_pit_tick(void);
-void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_pit_init(irq_handler_t handler);
 unsigned long coldfire_pit_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/523x/config.c b/arch/m68knommu/platform/523x/config.c
index 85de817..9b054e6 100644
--- a/arch/m68knommu/platform/523x/config.c
+++ b/arch/m68knommu/platform/523x/config.c
@@ -27,7 +27,7 @@
 /***************************************************************************/
 
 void coldfire_pit_tick(void);
-void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_pit_init(irq_handler_t handler);
 unsigned long coldfire_pit_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/5249/config.c b/arch/m68knommu/platform/5249/config.c
index 9d19d5b..d670607 100644
--- a/arch/m68knommu/platform/5249/config.c
+++ b/arch/m68knommu/platform/5249/config.c
@@ -12,6 +12,7 @@
 #include <linux/sched.h>
 #include <linux/param.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
 #include <asm/traps.h>
@@ -24,7 +25,7 @@
 /***************************************************************************/
 
 void coldfire_tick(void);
-void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_timer_init(irq_handler_t handler);
 unsigned long coldfire_timer_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c
index d500e27..6b437cc 100644
--- a/arch/m68knommu/platform/5272/config.c
+++ b/arch/m68knommu/platform/5272/config.c
@@ -26,7 +26,7 @@
 /***************************************************************************/
 
 void coldfire_tick(void);
-void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_timer_init(irq_handler_t handler);
 unsigned long coldfire_timer_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/527x/config.c b/arch/m68knommu/platform/527x/config.c
index bbae515..28e7d96 100644
--- a/arch/m68knommu/platform/527x/config.c
+++ b/arch/m68knommu/platform/527x/config.c
@@ -27,7 +27,7 @@
 /***************************************************************************/
 
 void coldfire_pit_tick(void);
-void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_pit_init(irq_handler_t handler);
 unsigned long coldfire_pit_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/528x/config.c b/arch/m68knommu/platform/528x/config.c
index 18dad90..805b4f7 100644
--- a/arch/m68knommu/platform/528x/config.c
+++ b/arch/m68knommu/platform/528x/config.c
@@ -27,7 +27,7 @@
 /***************************************************************************/
 
 void coldfire_pit_tick(void);
-void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_pit_init(irq_handler_t handler);
 unsigned long coldfire_pit_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c
index 8074ac5..e04b84d 100644
--- a/arch/m68knommu/platform/5307/config.c
+++ b/arch/m68knommu/platform/5307/config.c
@@ -27,7 +27,7 @@
 /***************************************************************************/
 
 void coldfire_tick(void);
-void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_timer_init(irq_handler_t handler);
 unsigned long coldfire_timer_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/5307/ints.c b/arch/m68knommu/platform/5307/ints.c
index a57239e..20f12a1 100644
--- a/arch/m68knommu/platform/5307/ints.c
+++ b/arch/m68knommu/platform/5307/ints.c
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/errno.h>
 #include <linux/seq_file.h>
diff --git a/arch/m68knommu/platform/5307/pit.c b/arch/m68knommu/platform/5307/pit.c
index 9dc5688..aa15bee 100644
--- a/arch/m68knommu/platform/5307/pit.c
+++ b/arch/m68knommu/platform/5307/pit.c
@@ -43,7 +43,7 @@
 
 /***************************************************************************/
 
-void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
+void coldfire_pit_init(irq_handler_t handler)
 {
 	volatile unsigned char *icrp;
 	volatile unsigned long *imrp;
diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
index e5668af..92e5807 100644
--- a/arch/m68knommu/platform/5307/timers.c
+++ b/arch/m68knommu/platform/5307/timers.c
@@ -62,7 +62,7 @@
 
 /***************************************************************************/
 
-void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
+void coldfire_timer_init(irq_handler_t handler)
 {
 	__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
 	__raw_writetrr(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
@@ -104,19 +104,20 @@
 
 /*
  *	Choose a reasonably fast profile timer. Make it an odd value to
- *	try and get good coverage of kernal operations.
+ *	try and get good coverage of kernel operations.
  */
 #define	PROFILEHZ	1013
 
 /*
  *	Use the other timer to provide high accuracy profiling info.
  */
-void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
+irqreturn_t coldfire_profile_tick(int irq, void *dummy)
 {
 	/* Reset ColdFire timer2 */
 	__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER));
 	if (current->pid)
 		profile_tick(CPU_PROFILING, regs);
+	return IRQ_HANDLED;
 }
 
 /***************************************************************************/
diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c
index c7d6ad5..664c3a12 100644
--- a/arch/m68knommu/platform/532x/config.c
+++ b/arch/m68knommu/platform/532x/config.c
@@ -35,7 +35,7 @@
 /***************************************************************************/
 
 void coldfire_tick(void);
-void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_timer_init(irq_handler_t handler);
 unsigned long coldfire_timer_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/5407/config.c b/arch/m68knommu/platform/5407/config.c
index 5aad264..036f628 100644
--- a/arch/m68knommu/platform/5407/config.c
+++ b/arch/m68knommu/platform/5407/config.c
@@ -26,7 +26,7 @@
 /***************************************************************************/
 
 void coldfire_tick(void);
-void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void coldfire_timer_init(irq_handler_t handler);
 unsigned long coldfire_timer_offset(void);
 void coldfire_trap_init(void);
 void coldfire_reset(void);
diff --git a/arch/m68knommu/platform/68328/config.c b/arch/m68knommu/platform/68328/config.c
index 26ffeba..e5c537d 100644
--- a/arch/m68knommu/platform/68328/config.c
+++ b/arch/m68knommu/platform/68328/config.c
@@ -34,7 +34,7 @@
 
 /***************************************************************************/
 
-void m68328_timer_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *));
+void m68328_timer_init(irq_handler_t timer_routine);
 void m68328_timer_tick(void);
 unsigned long m68328_timer_gettimeoffset(void);
 void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 44a0224..58e9788 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -8,6 +8,10 @@
 
 menu "Machine selection"
 
+config ZONE_DMA
+	bool
+	default y
+
 choice
 	prompt "System type"
 	default SGI_IP22
@@ -140,6 +144,7 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_KGDB
 	help
 	  The eXcite is a smart camera platform manufactured by
 	  Basler Vision Technologies AG
@@ -206,6 +211,7 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_KGDB
 	help
 	  This is an evaluation board based on the Galileo GT-64120
 	  single-chip system controller that contains a MIPS R5000 compatible
@@ -268,6 +274,7 @@
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_MULTITHREADING if EXPERIMENTAL
+	select SYS_SUPPORTS_SMARTMIPS
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 	help
 	  This enables support for the MIPS Technologies Atlas evaluation
@@ -299,6 +306,7 @@
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_MULTITHREADING
+	select SYS_SUPPORTS_SMARTMIPS
 	help
 	  This enables support for the MIPS Technologies Malta evaluation
 	  board.
@@ -316,6 +324,7 @@
 	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_SMARTMIPS
 	help
 	  This enables support for the MIPS Technologies SEAD evaluation
 	  board.
@@ -370,6 +379,7 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_KGDB
 	help
 	  The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by
 	  Momentum Computer <http://www.momenco.com/>.
@@ -387,6 +397,7 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_KGDB
 	help
 	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
 	  Momentum Computer <http://www.momenco.com/>.
@@ -476,6 +487,8 @@
 	select SYS_HAS_CPU_R5432
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_KGDB
+	select SYS_SUPPORTS_KGDB
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	help
 	  This enables support for the R5432-based NEC DDB Vrc-5477,
@@ -504,6 +517,7 @@
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_KGDB
 	select SYS_SUPPORTS_SMP
 	help
 	  Yosemite is an evaluation board for the RM9000x2 processor
@@ -580,6 +594,7 @@
 	select SYS_HAS_CPU_R10000
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_KGDB
 	select SYS_SUPPORTS_NUMA
 	select SYS_SUPPORTS_SMP
 	select GENERIC_HARDIRQS_NO__DO_IRQ
@@ -594,8 +609,6 @@
 	select ARC
 	select ARC32
 	select BOOT_ELF32
-	select OWN_DMA
-	select DMA_IP32
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select R5000_CPU_SCACHE
@@ -631,6 +644,7 @@
 	select SYS_HAS_CPU_SB1
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_KGDB
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config SIBYTE_SENTOSA
@@ -724,15 +738,16 @@
 	select BOOT_ELF32
 	select DMA_NONCOHERENT
 	select GENERIC_ISA_DMA
-	select HAVE_STD_PC_SERIAL_PORT
 	select HW_HAS_EISA
 	select HW_HAS_PCI
+	select IRQ_CPU
 	select I8253
 	select I8259
 	select ISA
 	select SWAP_IO_SPACE if CPU_BIG_ENDIAN
 	select SYS_HAS_CPU_R4X00
 	select SYS_HAS_CPU_R5000
+	select SYS_HAS_CPU_R10000
 	select R5000_CPU_SCACHE
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
@@ -753,6 +768,7 @@
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_TX39XX
 	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select TOSHIBA_BOARDS
 
@@ -767,7 +783,9 @@
 	select SYS_HAS_CPU_TX49XX
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_KGDB
 	select TOSHIBA_BOARDS
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 	help
@@ -788,6 +806,7 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_KGDB
 	select TOSHIBA_BOARDS
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 	help
@@ -877,9 +896,6 @@
 config DMA_NEED_PCI_MAP_STATE
 	bool
 
-config OWN_DMA
-	bool
-
 config EARLY_PRINTK
 	bool
 
@@ -934,6 +950,9 @@
 
 endchoice
 
+config SYS_SUPPORTS_APM_EMULATION
+	bool
+
 config SYS_SUPPORTS_BIG_ENDIAN
 	bool
 
@@ -954,6 +973,7 @@
 
 config DDB5XXX_COMMON
 	bool
+	select SYS_SUPPORTS_KGDB
 
 config MIPS_BOARDS_GEN
 	bool
@@ -1001,6 +1021,8 @@
 	bool
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_APM_EMULATION
+	select SYS_SUPPORTS_KGDB
 
 config PNX8550
 	bool
@@ -1013,6 +1035,7 @@
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select SYS_SUPPORTS_KGDB
 
 config SWAP_IO_SPACE
 	bool
@@ -1061,7 +1084,7 @@
 
 config MIPS_L1_CACHE_SHIFT
 	int
-	default "4" if MACH_DECSTATION
+	default "4" if MACH_DECSTATION || SNI_RM
 	default "7" if SGI_IP27
 	default "5"
 
@@ -1621,6 +1644,18 @@
 config CPU_HAS_LLSC
 	bool
 
+config CPU_HAS_SMARTMIPS
+	depends on SYS_SUPPORTS_SMARTMIPS
+	bool "Support for the SmartMIPS ASE"
+	help
+	  SmartMIPS is a extension of the MIPS32 architecture aimed at
+	  increased security at both hardware and software level for
+	  smartcards.  Enabling this option will allow proper use of the
+	  SmartMIPS instructions by Linux applications.  However a kernel with
+	  this option will not work on a MIPS core without SmartMIPS core.  If
+	  you don't know you probably don't have SmartMIPS and should say N
+	  here.
+
 config CPU_HAS_WB
 	bool
 
@@ -1684,6 +1719,9 @@
 config SYS_SUPPORTS_HIGHMEM
 	bool
 
+config SYS_SUPPORTS_SMARTMIPS
+	bool
+
 config ARCH_FLATMEM_ENABLE
 	def_bool y
 	depends on !NUMA
@@ -2071,35 +2109,11 @@
 	bool
 	default y if MIPS32_O32 || MIPS32_N32
 
-config PM
-	bool "Power Management support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && SOC_AU1X00
+endmenu
 
-config APM
-        tristate "Advanced Power Management Emulation"
-	depends on PM
-        ---help---
-	  APM is a BIOS specification for saving power using several different
-	  techniques. This is mostly useful for battery powered systems with
-	  APM compliant BIOSes. If you say Y here, the system time will be
-	  reset after a RESUME operation, the /proc/apm device will provide
-	  battery status information, and user-space programs will receive
-	  notification of APM "events" (e.g. battery status change).
+menu "Power management options"
 
-	  In order to use APM, you will need supporting software. For location
-	  and more information, read <file:Documentation/pm.txt> and the
-	  Battery Powered Linux mini-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  This driver does not spin down disk drives (see the hdparm(8)
-	  manpage ("man 8 hdparm") for that), and it doesn't turn off
-	  VESA-compliant "green" monitors.
-
-	  Generally, if you don't have a battery in your machine, there isn't
-	  much point in using this driver and you should say N. If you get
-	  random kernel OOPSes or reboots that don't seem to be related to
-	  anything, try disabling/enabling this option (or disabling/enabling
-	  APM in your BIOS).
+source "kernel/power/Kconfig"
 
 endmenu
 
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 9351f1c..d5e60a0 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -39,7 +39,7 @@
 
 config KGDB
 	bool "Remote GDB kernel debugging"
-	depends on DEBUG_KERNEL
+	depends on DEBUG_KERNEL && SYS_SUPPORTS_KGDB
 	select DEBUG_INFO
 	help
 	  If you say Y here, it will be possible to remotely debug the MIPS
@@ -48,6 +48,9 @@
 	  better 32 MB RAM to avoid excessive linking time. This is only
 	  useful for kernel hackers. If unsure, say N.
 
+config SYS_SUPPORTS_KGDB
+	bool
+
 config GDB_CONSOLE
 	bool "Console output to GDB"
 	depends on KGDB
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index c68b5d3..92bca6a 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -103,6 +103,8 @@
 cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB $(undef-all) $(predef-be))
 cflags-$(CONFIG_CPU_LITTLE_ENDIAN)	+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le))
 
+cflags-$(CONFIG_CPU_HAS_SMARTMIPS)	+= $(call cc-option,-msmartmips)
+
 cflags-$(CONFIG_SB1XXX_CORELIS)	+= $(call cc-option,-mno-sched-prolog) \
 				   -fno-omit-frame-pointer
 
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c
index 7504a63..3901e8e 100644
--- a/arch/mips/au1000/common/power.c
+++ b/arch/mips/au1000/common/power.c
@@ -62,12 +62,6 @@
 extern void restore_local_and_enable(int controller, unsigned long mask);
 extern void local_enable_irq(unsigned int irq_nr);
 
-/* Quick acpi hack. This will have to change! */
-#define	CTL_ACPI 9999
-#define	ACPI_S1_SLP_TYP 19
-#define	ACPI_SLEEP 21
-
-
 static DEFINE_SPINLOCK(pm_lock);
 
 /* We need to save/restore a bunch of core registers that are
@@ -425,15 +419,41 @@
 
 
 static struct ctl_table pm_table[] = {
-	{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend},
-	{ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep},
-	{CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq},
-	{0}
+	{
+		.ctl_name 	= CTL_UNNUMBERED,
+		.procname	= "suspend",
+		.data		= NULL,
+		.maxlen		= 0,
+		.mode		= 0600,
+		.proc_handler	= &pm_do_suspend
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sleep",
+		.data		= NULL,
+		.maxlen		= 0,
+		.mode		= 0600,
+		.proc_handler	= &pm_do_sleep
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "freq",
+		.data		= NULL,
+		.maxlen		= 0,
+		.mode		= 0600,
+		.proc_handler	= &pm_do_freq
+	},
+	{}
 };
 
 static struct ctl_table pm_dir_table[] = {
-	{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
-	{0}
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "pm",
+		.mode		= 0555,
+		.child		= pm_table
+	},
+	{}
 };
 
 /*
@@ -441,7 +461,7 @@
  */
 static int __init pm_init(void)
 {
-	register_sysctl_table(pm_dir_table, 1);
+	register_sysctl_table(pm_dir_table);
 	return 0;
 }
 
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 225ac8f..12589a1 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -5,5 +5,6 @@
 obj-y	 := irq.o reset.o setup.o
 
 obj-$(CONFIG_EARLY_PRINTK)	+= console.o
+obj-$(CONFIG_MTD_PHYSMAP)	+= mtd.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/cobalt/mtd.c b/arch/mips/cobalt/mtd.c
new file mode 100644
index 0000000..2b088ef
--- /dev/null
+++ b/arch/mips/cobalt/mtd.c
@@ -0,0 +1,61 @@
+/*
+ *  Registration of Cobalt MTD device.
+ *
+ *  Copyright (C) 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+static struct mtd_partition cobalt_mtd_partitions[] = {
+	{
+		.name	= "firmware",
+		.offset	= 0x0,
+		.size	= 0x80000,
+	},
+};
+
+static struct physmap_flash_data cobalt_flash_data = {
+	.width		= 1,
+	.nr_parts	= 1,
+	.parts		= cobalt_mtd_partitions,
+};
+
+static struct resource cobalt_mtd_resource = {
+	.start	= 0x1fc00000,
+	.end	= 0x1fc7ffff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device cobalt_mtd = {
+	.name		= "physmap-flash",
+	.dev		= {
+		.platform_data	= &cobalt_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &cobalt_mtd_resource,
+};
+
+static int __init cobalt_mtd_init(void)
+{
+	platform_device_register(&cobalt_mtd);
+
+	return 0;
+}
+
+module_init(cobalt_mtd_init);
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index a4b69b5..415ff87 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -130,7 +130,7 @@
 
 	set_io_port_base(CKSEG1ADDR(GT_DEF_PCI0_IO_BASE));
 
-	/* I/O port resource must include UART and LCD/buttons */
+	/* I/O port resource must include LCD/buttons */
 	ioport_resource.end = 0x0fffffff;
 
 	/* request I/O space for devices used on all i[345]86 PCs */
@@ -149,24 +149,24 @@
 	register_pci_controller(&cobalt_pci_controller);
 #endif
 
-#ifdef CONFIG_SERIAL_8250
 	if (cobalt_board_id > COBALT_BRD_ID_RAQ1) {
-
 #ifdef CONFIG_EARLY_PRINTK
 		cobalt_early_console();
 #endif
 
+#ifdef CONFIG_SERIAL_8250
 		uart.line	= 0;
 		uart.type	= PORT_UNKNOWN;
 		uart.uartclk	= 18432000;
 		uart.irq	= COBALT_SERIAL_IRQ;
-		uart.flags	= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-		uart.iobase	= 0xc800000;
-		uart.iotype	= UPIO_PORT;
+		uart.flags	= UPF_IOREMAP | UPF_BOOT_AUTOCONF |
+				  UPF_SKIP_TEST;
+		uart.iotype	= UPIO_MEM;
+		uart.mapbase	= 0x1c800000;
 
 		early_serial_setup(&uart);
-	}
 #endif
+	}
 }
 
 /*
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index ac18916..4588949 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 09:59:39 2006
+# Linux kernel version: 2.6.20
+# Sun Feb 18 21:27:35 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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=y
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,10 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_MIPS_BONITO64=y
@@ -129,16 +133,18 @@
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_SYS_SUPPORTS_MULTITHREADING=y
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_SMARTMIPS is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_SMARTMIPS=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -149,6 +155,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 CONFIG_HZ_100=y
 # CONFIG_HZ_128 is not set
@@ -161,6 +168,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -179,15 +187,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -195,12 +208,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -218,6 +231,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -260,6 +274,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -273,7 +295,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
@@ -281,7 +306,6 @@
 # CONFIG_IP_FIB_TRIE is not set
 CONFIG_IP_FIB_HASH=y
 CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
 CONFIG_IP_ROUTE_MULTIPATH=y
 # CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
 CONFIG_IP_ROUTE_VERBOSE=y
@@ -304,10 +328,13 @@
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -349,11 +376,17 @@
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=y
 CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -365,19 +398,43 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
@@ -395,60 +452,45 @@
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_SECMARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CONNTRACK_NETLINK=m
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_PPTP=m
-CONFIG_IP_NF_H323=m
-CONFIG_IP_NF_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=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=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_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_SAME=m
-# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-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_NAT_SIP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_TTL=m
 # CONFIG_IP_NF_TARGET_CLUSTERIP is not set
 CONFIG_IP_NF_RAW=m
@@ -459,6 +501,7 @@
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
+CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_RT=m
@@ -468,6 +511,7 @@
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
@@ -527,13 +571,12 @@
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 CONFIG_ATALK=m
-CONFIG_DEV_APPLETALK=y
+CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
 CONFIG_IPDDP_DECAP=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -541,6 +584,7 @@
 # QoS and/or fair queueing
 #
 CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FIFO=y
 CONFIG_NET_SCH_CLK_JIFFIES=y
 # CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
 # CONFIG_NET_SCH_CLK_CPU is not set
@@ -595,6 +639,7 @@
 CONFIG_IEEE80211_SOFTMAC=m
 # CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
 CONFIG_WIRELESS_EXT=y
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -642,6 +687,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -649,9 +695,16 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -681,6 +734,8 @@
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -700,14 +755,17 @@
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_ISCSI_ATTRS=m
 CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_LIBSAS_DEBUG=y
 
 #
 # SCSI low-level drivers
@@ -720,30 +778,39 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR 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_HPTIOP 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_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 CONFIG_SCSI_SYM53C8XX_MMIO=y
-# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI 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
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -759,6 +826,7 @@
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -813,6 +881,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -832,6 +902,7 @@
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
@@ -850,6 +921,7 @@
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 CONFIG_LAN_SAA9730=y
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -868,14 +940,18 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -915,6 +991,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -995,10 +1072,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -1006,7 +1079,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -1031,14 +1103,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -1056,6 +1123,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -1063,6 +1131,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1125,6 +1199,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1134,6 +1216,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1154,6 +1237,7 @@
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 CONFIG_MINIX_FS=m
 CONFIG_ROMFS_FS=m
@@ -1167,6 +1251,7 @@
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1174,7 +1259,6 @@
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=m
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1193,11 +1277,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1242,7 +1328,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1299,6 +1384,14 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1308,11 +1401,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -1326,18 +1421,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1349,6 +1456,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1358,6 +1466,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1369,9 +1478,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
-CONFIG_RIO=n
-CONFIG_I2C_OCORES=n
-CONFIG_DEBUG_RT_MUTEXES=n
-CONFIG_RT_MUTEX_TESTER=n
-CONFIG_DEBUG_RWSEMS=n
-CONFIG_DEBUG_LOCKING_API_SELFTESTS=n
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 9554257..aa05e29 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc1
-# Wed Oct 11 01:41:41 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:22 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -40,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -78,11 +80,14 @@
 # CONFIG_SIBYTE_SB1250_PROF is not set
 # CONFIG_SIBYTE_TBPROF is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_COHERENT=y
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
@@ -115,6 +120,7 @@
 # CONFIG_CPU_RM9000 is not set
 CONFIG_CPU_SB1=y
 CONFIG_SYS_HAS_CPU_SB1=y
+CONFIG_WEAK_ORDERING=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
@@ -150,8 +156,10 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_SMP=y
 CONFIG_SYS_SUPPORTS_SMP=y
+CONFIG_NR_CPUS_DEFAULT_4=y
 CONFIG_NR_CPUS=4
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
@@ -166,6 +174,7 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_PREEMPT_BKL is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -185,6 +194,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -193,6 +203,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -253,7 +264,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 CONFIG_PCI_DEBUG=y
 CONFIG_MMU=y
 
@@ -273,11 +283,20 @@
 # CONFIG_BUILD_ELF64 is not set
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
 CONFIG_MIPS32_O32=y
 CONFIG_MIPS32_N32=y
 CONFIG_BINFMT_ELF32=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -292,7 +311,9 @@
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -318,6 +339,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -374,6 +396,7 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -394,6 +417,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -413,6 +437,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -455,6 +485,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -464,6 +495,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_BLK_DEV_IDE_SWARM is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
@@ -558,14 +590,17 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -627,6 +662,7 @@
 # CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
+CONFIG_MOXA_SMARTIO_NEW=m
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_SYNCLINK_GT is not set
@@ -667,10 +703,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -678,7 +710,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -707,6 +738,7 @@
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 CONFIG_I2C_SIBYTE=y
@@ -743,6 +775,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -751,11 +784,6 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -840,6 +868,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -848,6 +884,7 @@
 CONFIG_EXT2_FS_SECURITY=y
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
@@ -889,7 +926,7 @@
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -946,6 +983,10 @@
 #
 # Distributed Lock Manager
 #
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
 
 #
 # Profiling support
@@ -960,23 +1001,25 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
@@ -984,7 +1027,6 @@
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_KGDB is not set
 # CONFIG_SB1XXX_CORELIS is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
@@ -1002,8 +1044,9 @@
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=m
 CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
@@ -1012,9 +1055,13 @@
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_TWOFISH_COMMON=y
@@ -1029,6 +1076,7 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 # CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1038,6 +1086,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -1045,3 +1094,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 49590d4..b2594fa 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:03:24 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:22 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -70,12 +70,15 @@
 # CONFIG_VICTOR_MPC30X is not set
 CONFIG_ZAO_CAPCELLA=y
 CONFIG_PCI_VR41XX=y
-# CONFIG_VRC4173 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -108,6 +111,7 @@
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_VR41XX=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
@@ -121,8 +125,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -137,6 +141,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -149,6 +154,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -167,15 +173,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -183,12 +194,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -206,6 +217,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -248,6 +260,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -261,7 +281,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -282,10 +305,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -315,7 +341,6 @@
 # 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
 
@@ -363,6 +388,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -378,14 +404,22 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -414,6 +448,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -464,6 +504,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -504,7 +546,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -523,14 +565,18 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -569,6 +615,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -635,10 +682,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
@@ -647,7 +690,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -672,14 +714,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -697,6 +734,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -704,6 +742,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -754,6 +797,7 @@
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
 CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
 
 #
 # RTC interfaces
@@ -787,16 +831,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -807,6 +861,7 @@
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -826,11 +881,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -868,7 +925,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -886,6 +942,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -895,11 +959,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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"
 
@@ -912,7 +978,44 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=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 is not set
+CONFIG_CRYPTO_CAMELLIA=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -921,8 +1024,13 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 0607fc2..9090a7a 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:03:25 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:24 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 CONFIG_MIPS_COBALT=y
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -65,10 +65,14 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_I8259=y
@@ -117,8 +121,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
@@ -134,6 +138,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -146,6 +151,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -164,15 +170,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -180,12 +191,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -198,6 +209,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -240,6 +252,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -253,7 +273,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -270,10 +293,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -303,7 +329,6 @@
 # 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
 
@@ -348,7 +373,87 @@
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
 
 #
 # Parallel port support
@@ -358,6 +463,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -379,9 +485,16 @@
 CONFIG_ATA_OVER_ETH=y
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=y
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -417,8 +530,10 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_IT8213=y
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -428,6 +543,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 CONFIG_BLK_DEV_VIA82CXXX=y
+CONFIG_BLK_DEV_TC86C001=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -439,6 +555,12 @@
 #
 CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -489,6 +611,8 @@
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -533,14 +657,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=y
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=y
 
 #
 # Token Ring devices
@@ -579,6 +707,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -656,10 +785,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -667,7 +792,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -692,14 +816,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -717,6 +836,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -724,6 +844,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -786,6 +911,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -794,11 +927,13 @@
 CONFIG_EXT2_FS_SECURITY=y
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -809,6 +944,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=y
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -828,22 +964,26 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=y
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -866,7 +1006,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -884,6 +1023,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=y
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -893,12 +1040,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -913,7 +1061,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
@@ -922,9 +1075,16 @@
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_WP512=y
 CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_LRW=y
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
 CONFIG_CRYPTO_BLOWFISH=y
 CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
 CONFIG_CRYPTO_SERPENT=y
 CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_CAST5=y
@@ -936,6 +1096,7 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_CAMELLIA=y
 
 #
 # Hardware crypto devices
@@ -944,6 +1105,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=y
 CONFIG_CRC32=y
@@ -951,3 +1113,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 1a57b33..4cb8cf4 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:03:33 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:24 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,14 +64,19 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 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_APM_EMULATION=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SOC_AU1000=y
 CONFIG_SOC_AU1X00=y
@@ -116,8 +121,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_64BIT_PHYS_ADDR=y
 CONFIG_CPU_HAS_LLSC=y
@@ -135,6 +140,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -147,6 +153,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -165,15 +172,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -181,12 +193,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -204,6 +216,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -252,6 +265,10 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
 # CONFIG_PM is not set
 
 #
@@ -268,7 +285,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -289,10 +309,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -311,15 +334,42 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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
@@ -330,14 +380,17 @@
 CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -365,7 +418,6 @@
 # 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
 
@@ -421,11 +473,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -494,6 +548,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -510,6 +565,10 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -519,6 +578,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -562,6 +627,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -616,6 +683,7 @@
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -635,6 +703,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -714,10 +783,6 @@
 # CONFIG_R3964 is not set
 
 #
-# Ftape, the floppy tape device driver
-#
-
-#
 # PCMCIA character devices
 #
 CONFIG_SYNCLINK_CS=m
@@ -729,7 +794,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -754,14 +818,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -779,6 +838,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -786,6 +846,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -847,6 +912,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -858,6 +931,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -870,6 +944,7 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -880,6 +955,7 @@
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -899,23 +975,25 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
@@ -944,7 +1022,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1001,6 +1078,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1010,13 +1095,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1029,18 +1117,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1052,6 +1152,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1061,6 +1162,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1072,3 +1174,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 0055ec4..d86dedf 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:03:34 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:24 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,14 +64,19 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 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_APM_EMULATION=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SOC_AU1100=y
 CONFIG_SOC_AU1X00=y
@@ -116,8 +121,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_64BIT_PHYS_ADDR=y
 CONFIG_CPU_HAS_LLSC=y
@@ -135,6 +140,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -147,6 +153,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -165,15 +172,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -181,12 +193,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -204,6 +216,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -241,6 +254,10 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
 # CONFIG_PM is not set
 
 #
@@ -257,7 +274,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -278,10 +298,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -300,15 +323,42 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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
@@ -319,14 +369,17 @@
 CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -354,7 +407,6 @@
 # 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
 
@@ -410,11 +462,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -483,6 +537,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -499,6 +554,10 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -508,6 +567,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -551,6 +616,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -592,6 +659,7 @@
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -611,6 +679,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -687,17 +756,12 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -722,14 +786,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -744,6 +803,7 @@
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
@@ -786,6 +846,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -847,6 +912,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -858,6 +931,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -870,6 +944,7 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -880,6 +955,7 @@
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -899,23 +975,25 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
@@ -944,7 +1022,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1001,6 +1078,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1010,13 +1095,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1029,18 +1117,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1052,6 +1152,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1061,6 +1162,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1072,3 +1174,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index c41823b..c24b600 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:03:43 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:25 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,14 +64,19 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_COHERENT=y
 CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SOC_AU1200=y
 CONFIG_SOC_AU1X00=y
@@ -116,8 +121,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_64BIT_PHYS_ADDR=y
 CONFIG_CPU_HAS_LLSC=y
@@ -135,6 +140,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -147,6 +153,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -165,16 +172,21 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -182,12 +194,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -205,6 +217,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -251,6 +264,10 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
 # CONFIG_PM is not set
 
 #
@@ -267,7 +284,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -285,10 +305,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -305,15 +328,41 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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
@@ -324,14 +373,17 @@
 CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -359,7 +411,6 @@
 # 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
 
@@ -409,11 +460,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -488,6 +541,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -499,14 +553,20 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -540,6 +600,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -559,20 +621,21 @@
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
 #
 # CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
@@ -585,6 +648,11 @@
 # CONFIG_PCMCIA_SYM53C500 is not set
 
 #
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -672,6 +740,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -751,10 +820,6 @@
 # CONFIG_R3964 is not set
 
 #
-# Ftape, the floppy tape device driver
-#
-
-#
 # PCMCIA character devices
 #
 # CONFIG_SYNCLINK_CS is not set
@@ -766,7 +831,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -782,6 +846,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -790,14 +855,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -812,6 +872,7 @@
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
@@ -843,6 +904,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -916,6 +983,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -927,6 +1002,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -938,6 +1014,7 @@
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -948,6 +1025,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -955,7 +1033,6 @@
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=m
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -974,23 +1051,25 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1025,7 +1104,6 @@
 CONFIG_SMB_FS=y
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1082,6 +1160,14 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1091,13 +1177,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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"
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1109,7 +1198,44 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=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_CAMELLIA=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -1118,6 +1244,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -1129,3 +1256,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 7d6d921..baad2c5 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:03:56 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:26 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,15 +64,20 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SOC_AU1500=y
@@ -118,8 +123,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_64BIT_PHYS_ADDR=y
 CONFIG_CPU_HAS_LLSC=y
@@ -136,7 +141,8 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -149,6 +155,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -167,15 +174,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -183,12 +195,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -206,6 +218,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -259,6 +272,10 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
 # CONFIG_PM is not set
 
 #
@@ -275,7 +292,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -296,10 +316,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -318,15 +341,42 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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
@@ -337,14 +387,17 @@
 CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -372,7 +425,6 @@
 # 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
 
@@ -428,11 +480,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -502,6 +556,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -524,9 +579,16 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -536,6 +598,7 @@
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
 CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_DELKIN is not set
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -556,6 +619,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -606,6 +675,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -643,14 +714,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -683,6 +758,7 @@
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -702,6 +778,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -780,10 +857,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 
 #
@@ -798,7 +871,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -823,14 +895,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -843,6 +910,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -873,7 +941,6 @@
 # Generic devices
 #
 CONFIG_SND_AC97_CODEC=m
-CONFIG_SND_AC97_BUS=m
 # CONFIG_SND_DUMMY is not set
 CONFIG_SND_VIRMIDI=m
 CONFIG_SND_MTPAV=m
@@ -938,6 +1005,7 @@
 # CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
 # CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
 
 #
 # ALSA MIPS devices
@@ -956,18 +1024,28 @@
 # CONFIG_SND_PDAUDIOCF is not set
 
 #
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
+# CONFIG_OBSOLETE_OSS is not set
 # CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ICH 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_AC97_BUS=m
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -982,7 +1060,6 @@
 # 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
 
@@ -992,7 +1069,8 @@
 # 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -1010,14 +1088,12 @@
 #
 # may also be needed; see USB_STORAGE Help for more information
 #
-# CONFIG_USB_STORAGE is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 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
@@ -1033,6 +1109,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1046,6 +1123,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1063,18 +1141,21 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX 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_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 CONFIG_USB_LD=m
+# CONFIG_USB_TRANCEVIBRATOR is not set
 
 #
 # USB DSL modem support
@@ -1131,6 +1212,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1142,6 +1231,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1154,6 +1244,7 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1164,6 +1255,7 @@
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1183,23 +1275,25 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
@@ -1228,7 +1322,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1285,6 +1378,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1294,13 +1395,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1313,18 +1417,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1336,6 +1452,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1345,6 +1462,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1356,3 +1474,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index c681c91..c29fdab 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:03:59 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:27 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,15 +64,20 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SOC_AU1550=y
 CONFIG_SOC_AU1X00=y
@@ -117,8 +122,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_64BIT_PHYS_ADDR=y
 CONFIG_CPU_HAS_LLSC=y
@@ -135,7 +140,8 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -148,6 +154,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -166,15 +173,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -182,12 +194,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -205,6 +217,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -258,6 +271,10 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
 # CONFIG_PM is not set
 
 #
@@ -274,7 +291,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -295,10 +315,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -317,15 +340,42 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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
@@ -336,14 +386,17 @@
 CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -371,7 +424,6 @@
 # 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
 
@@ -427,11 +479,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -492,6 +546,7 @@
 CONFIG_MTD_NAND_IDS=m
 CONFIG_MTD_NAND_AU1550=m
 # CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
 # CONFIG_MTD_NAND_NANDSIM is not set
 
 #
@@ -507,6 +562,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -528,9 +584,16 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -540,6 +603,7 @@
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
 CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_DELKIN is not set
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -567,8 +631,10 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -578,6 +644,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -589,6 +656,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -639,6 +712,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -676,14 +751,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -724,6 +803,7 @@
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -743,6 +823,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -821,10 +902,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 
 #
@@ -839,7 +916,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -864,14 +940,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -883,6 +954,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -890,6 +962,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -952,6 +1029,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -963,6 +1048,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -975,6 +1061,7 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -985,6 +1072,7 @@
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1004,23 +1092,25 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
@@ -1049,7 +1139,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1106,6 +1195,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1115,13 +1212,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1134,18 +1234,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1157,6 +1269,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1166,6 +1279,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1177,3 +1291,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index dd4bb00..f4b316d 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:00 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:28 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 CONFIG_DDB5477=y
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -65,10 +65,14 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_DDB5477_BUS_FREQUENCY=0
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_I8259=y
@@ -117,8 +121,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
@@ -134,6 +138,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -146,6 +151,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -164,15 +170,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -180,12 +191,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -198,6 +209,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -240,6 +252,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -253,7 +273,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -273,10 +296,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -306,7 +332,6 @@
 # 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
 
@@ -361,6 +386,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -381,6 +407,12 @@
 CONFIG_ATA_OVER_ETH=y
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=y
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -390,6 +422,12 @@
 #
 CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -440,6 +478,8 @@
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -459,6 +499,7 @@
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
@@ -476,7 +517,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -495,14 +536,18 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=y
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=y
 
 #
 # Token Ring devices
@@ -541,6 +586,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -618,10 +664,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -629,7 +671,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -654,14 +695,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -679,6 +715,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -686,6 +723,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -748,16 +790,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -787,17 +839,19 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=y
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -829,7 +883,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -847,6 +900,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=y
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -856,14 +917,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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"
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -876,7 +939,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
@@ -885,9 +953,16 @@
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_WP512=y
 CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_LRW=y
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
 CONFIG_CRYPTO_BLOWFISH=y
 CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
 CONFIG_CRYPTO_SERPENT=y
 CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_CAST5=y
@@ -899,6 +974,7 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_CAMELLIA=y
 
 #
 # Hardware crypto devices
@@ -907,6 +983,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=y
 CONFIG_CRC32=y
@@ -914,3 +991,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 8a31ce4..9c38e5c 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct  3 11:57:53 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:28 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 CONFIG_MACH_DECSTATION=y
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -65,10 +65,14 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -116,8 +120,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_WB=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -133,6 +137,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_128=y
@@ -147,6 +152,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -165,13 +171,16 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -246,6 +255,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -260,7 +277,9 @@
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -281,11 +300,13 @@
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -298,10 +319,12 @@
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
 CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
 # CONFIG_IPV6_TUNNEL is not set
-CONFIG_IPV6_SUBTREES=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 # CONFIG_NETFILTER is not set
 
@@ -375,6 +398,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -389,6 +413,10 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -398,6 +426,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
 # CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
@@ -418,6 +447,7 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
 # SCSI Transports
@@ -502,6 +532,9 @@
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+CONFIG_FDDI=y
+CONFIG_DEFXX=m
+CONFIG_DEFXX_MMIO=y
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
@@ -565,17 +598,12 @@
 CONFIG_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -600,14 +628,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -622,6 +645,7 @@
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
@@ -709,6 +733,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -720,6 +752,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -727,6 +760,7 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -737,6 +771,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -806,7 +841,6 @@
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
 # CONFIG_9P_FS is not set
-CONFIG_GENERIC_ACL=y
 
 #
 # Partition Types
@@ -835,6 +869,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -847,9 +889,10 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -866,19 +909,24 @@
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=m
 CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -893,6 +941,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -902,6 +951,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -909,3 +959,5 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index 6fa4f91..922af37 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc2
-# Tue Jul 25 23:15:03 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:28 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -70,10 +70,14 @@
 # CONFIG_VICTOR_MPC30X is not set
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -106,6 +110,7 @@
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_VR41XX=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
@@ -119,8 +124,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -135,6 +140,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -147,6 +153,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -165,13 +172,17 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -179,12 +190,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -202,6 +213,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -241,6 +253,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 # CONFIG_NET is not set
@@ -274,6 +294,7 @@
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -288,9 +309,14 @@
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -319,6 +345,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Old CD-ROM drivers (not SCSI, not IDE)
@@ -356,6 +388,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -436,10 +469,6 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
 
@@ -447,7 +476,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -463,6 +491,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -471,14 +500,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -496,6 +520,7 @@
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -503,6 +528,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -563,16 +594,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -582,6 +623,7 @@
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -601,8 +643,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -645,11 +689,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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 ide0=0x1f0,0x3f6,40 mem=8M"
 
@@ -665,10 +711,6 @@
 # CONFIG_CRYPTO is not set
 
 #
-# Hardware crypto devices
-#
-
-#
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
@@ -676,3 +718,5 @@
 # CONFIG_CRC32 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
index 4c9d040..c0db8f1 100644
--- a/arch/mips/configs/emma2rh_defconfig
+++ b/arch/mips/configs/emma2rh_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:05 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:29 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,10 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -116,8 +120,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -134,6 +138,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -147,6 +152,7 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_PREEMPT_BKL=y
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -166,17 +172,22 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -184,12 +195,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -207,6 +218,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 CONFIG_LBD=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -249,6 +261,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -262,7 +282,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
@@ -270,7 +293,6 @@
 # CONFIG_IP_FIB_TRIE is not set
 CONFIG_IP_FIB_HASH=y
 CONFIG_IP_MULTIPLE_TABLES=y
-# CONFIG_IP_ROUTE_FWMARK is not set
 CONFIG_IP_ROUTE_MULTIPATH=y
 # CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
 CONFIG_IP_ROUTE_VERBOSE=y
@@ -287,13 +309,16 @@
 # 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_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -305,11 +330,17 @@
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+CONFIG_IPV6_MIP6=y
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
 # CONFIG_IPV6_TUNNEL is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -318,19 +349,125 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
-# CONFIG_NF_CONNTRACK is not set
-# CONFIG_NETFILTER_XTABLES is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
 
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
+CONFIG_NF_CONNTRACK_IPV6=m
 # CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
 
 #
 # DCCP Configuration (EXPERIMENTAL)
@@ -360,7 +497,6 @@
 # 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
 
@@ -368,6 +504,7 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -377,6 +514,7 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_IEEE80211 is not set
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -387,7 +525,7 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -409,11 +547,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -485,6 +625,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -504,6 +645,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -513,6 +660,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=m
+CONFIG_SCSI_TGT=m
+# CONFIG_SCSI_NETLINK is not set
 # CONFIG_SCSI_PROC_FS is not set
 
 #
@@ -531,14 +680,17 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # 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
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -551,26 +703,35 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR 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_HPTIOP 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_STEX 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_QLA_ISCSI 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
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -649,7 +810,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -668,14 +829,18 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -703,6 +868,7 @@
 # CONFIG_PPP_MPPE is not set
 # CONFIG_PPPOE is not set
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
@@ -723,6 +889,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -790,10 +957,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -801,7 +964,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -830,6 +992,7 @@
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 # CONFIG_I2C_SIS5595 is not set
@@ -865,6 +1028,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -875,6 +1039,7 @@
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -898,29 +1063,27 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -932,6 +1095,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -939,6 +1103,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1001,6 +1170,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1012,6 +1189,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=m
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1023,6 +1201,7 @@
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1033,6 +1212,7 @@
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=m
 # CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1057,11 +1237,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1073,7 +1255,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1118,7 +1299,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1175,6 +1355,14 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1184,11 +1372,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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 mem=192m ip=bootp root=/dev/nfs rw"
 
@@ -1202,7 +1392,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
@@ -1211,7 +1406,13 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1225,6 +1426,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1234,10 +1436,17 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
index d5b4973..ce088b36 100644
--- a/arch/mips/configs/ev64120_defconfig
+++ b/arch/mips/configs/ev64120_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:05 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:30 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 CONFIG_MIPS_EV64120=y
-# 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -65,10 +65,14 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 # CONFIG_EVB_PCI1 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -118,8 +122,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -136,6 +140,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -148,6 +153,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -166,15 +172,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -182,12 +193,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -205,6 +216,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -247,6 +259,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -259,7 +279,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -279,10 +302,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -312,7 +338,6 @@
 # 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
 
@@ -366,6 +391,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -386,6 +412,12 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -395,6 +427,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -445,6 +483,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -480,14 +520,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -515,6 +559,7 @@
 CONFIG_PPP_MPPE=m
 # CONFIG_PPPOE is not set
 # CONFIG_SLIP is not set
+CONFIG_SLHC=y
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -534,6 +579,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -611,10 +657,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -622,7 +664,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -647,14 +688,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -672,6 +708,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -679,6 +716,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -741,16 +783,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -780,17 +832,19 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -819,7 +873,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -837,6 +890,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -846,13 +907,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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::"
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -865,18 +929,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -888,6 +964,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -897,6 +974,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=m
 CONFIG_CRC_CCITT=y
 CONFIG_CRC16=m
 CONFIG_CRC32=m
@@ -904,3 +982,5 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
index 697140c..82f204d 100644
--- a/arch/mips/configs/excite_defconfig
+++ b/arch/mips/configs/excite_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:09 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:31 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -26,8 +27,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -43,6 +42,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -65,10 +65,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_COHERENT=y
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
@@ -76,6 +80,10 @@
 CONFIG_IRQ_CPU=y
 CONFIG_IRQ_CPU_RM7K=y
 CONFIG_IRQ_CPU_RM9K=y
+CONFIG_MIPS_RM9122=y
+CONFIG_SERIAL_RM9000=y
+CONFIG_GPI_RM9000=y
+CONFIG_WDT_RM9000=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
@@ -101,6 +109,7 @@
 CONFIG_CPU_RM9000=y
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_RM9000=y
+CONFIG_WEAK_ORDERING=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
@@ -117,8 +126,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -136,6 +145,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -149,6 +159,7 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_PREEMPT_BKL=y
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -168,15 +179,20 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -184,12 +200,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -207,6 +223,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -249,6 +266,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -262,6 +287,8 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -282,10 +309,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -315,7 +345,6 @@
 # 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
 
@@ -342,7 +371,7 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -364,11 +393,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -420,6 +451,8 @@
 # CONFIG_MTD_NAND_ECC_SMC is not set
 CONFIG_MTD_NAND_IDS=y
 # CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_BASLER_EXCITE is not set
+# CONFIG_MTD_NAND_CAFE is not set
 # CONFIG_MTD_NAND_NANDSIM is not set
 
 #
@@ -435,6 +468,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -455,6 +489,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -464,6 +504,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+# CONFIG_SCSI_NETLINK is not set
 # CONFIG_SCSI_PROC_FS is not set
 
 #
@@ -482,14 +524,17 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # 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
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -502,26 +547,35 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR 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_HPTIOP 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_STEX 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_QLA_ISCSI 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
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -585,14 +639,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -632,6 +690,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -707,6 +766,7 @@
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
+CONFIG_WDT_RM9K_GPI=m
 
 #
 # PCI-based Watchdog Cards
@@ -724,10 +784,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -735,7 +791,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -751,6 +806,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -759,14 +815,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -782,6 +833,7 @@
 # CONFIG_FB_CFB_FILLRECT is not set
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
@@ -798,6 +850,7 @@
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -831,6 +884,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -843,8 +902,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -854,9 +913,11 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -884,14 +945,13 @@
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
-# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA 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
@@ -913,6 +973,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -927,6 +988,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 # CONFIG_USB_MON is not set
 
@@ -944,19 +1006,22 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX 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_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1014,16 +1079,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1034,6 +1109,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1056,11 +1132,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1072,7 +1150,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1107,7 +1184,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1179,6 +1255,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1188,13 +1272,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1206,16 +1293,27 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
 # CONFIG_CRYPTO_HMAC is not set
+CONFIG_CRYPTO_XCBC=m
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MD5=y
 # 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_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 # CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_FCRYPT=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1229,6 +1327,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1238,6 +1337,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -1245,3 +1345,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index f9812d1..cb81f13 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:10 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:32 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,13 +64,18 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_ARC=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN=y
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
@@ -123,8 +128,8 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_IP22_CPU_SCACHE=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -141,6 +146,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -153,6 +159,7 @@
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -171,16 +178,21 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -188,12 +200,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -211,6 +223,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -238,7 +251,6 @@
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -252,6 +264,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -265,7 +285,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -286,10 +309,13 @@
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -331,11 +357,17 @@
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=y
 CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -346,19 +378,43 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
@@ -375,60 +431,45 @@
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_SECMARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CONNTRACK_NETLINK=m
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_PPTP=m
-CONFIG_IP_NF_H323=m
-CONFIG_IP_NF_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=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=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_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-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_NAT_SIP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_RAW=m
@@ -439,6 +480,7 @@
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
+CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_RT=m
@@ -448,6 +490,7 @@
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
@@ -484,7 +527,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -492,6 +534,7 @@
 # QoS and/or fair queueing
 #
 CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FIFO=y
 # CONFIG_NET_SCH_CLK_JIFFIES is not set
 CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
 # CONFIG_NET_SCH_CLK_CPU is not set
@@ -546,6 +589,7 @@
 CONFIG_IEEE80211_SOFTMAC=m
 # CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
 CONFIG_WIRELESS_EXT=y
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -556,7 +600,6 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -577,6 +620,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -592,6 +636,10 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -601,6 +649,8 @@
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -620,24 +670,30 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=m
 # CONFIG_SCSI_FC_ATTRS is not set
 CONFIG_SCSI_ISCSI_ATTRS=m
 CONFIG_SCSI_SAS_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
 #
 CONFIG_ISCSI_TCP=m
 CONFIG_SGIWD93_SCSI=y
-# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -679,6 +735,8 @@
 CONFIG_CICADA_PHY=m
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -730,6 +788,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -752,6 +811,7 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=m
 CONFIG_MOUSE_SERIAL=m
@@ -815,10 +875,6 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 CONFIG_RAW_DRIVER=m
 CONFIG_MAX_RAW_DEVS=256
 
@@ -826,7 +882,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -851,14 +906,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -887,6 +937,7 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_SGI_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -894,6 +945,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -954,6 +1011,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=m
@@ -963,6 +1028,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -974,6 +1040,7 @@
 CONFIG_XFS_SECURITY=y
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 CONFIG_MINIX_FS=m
 # CONFIG_ROMFS_FS is not set
@@ -987,6 +1054,7 @@
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -994,7 +1062,6 @@
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=m
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1013,17 +1080,20 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -1142,6 +1212,14 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1151,11 +1229,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -1170,18 +1250,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1193,6 +1285,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1202,6 +1295,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=m
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=m
 CONFIG_CRC32=m
@@ -1213,3 +1307,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 96090f2..46f6ac4 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:10 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:32 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -70,10 +70,14 @@
 # CONFIG_REPLICATE_EXHANDLERS is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_ARC=y
 CONFIG_DMA_IP27=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -121,8 +125,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
@@ -145,8 +149,10 @@
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_SMP=y
 CONFIG_SYS_SUPPORTS_SMP=y
+CONFIG_NR_CPUS_DEFAULT_64=y
 CONFIG_NR_CPUS=64
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
@@ -162,6 +168,7 @@
 # CONFIG_PREEMPT is not set
 CONFIG_PREEMPT_BKL=y
 # CONFIG_MIPS_INSANE_LARGE is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -180,17 +187,22 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CPUSETS=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -198,12 +210,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -222,6 +234,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -263,11 +276,20 @@
 # CONFIG_BUILD_ELF64 is not set
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
 CONFIG_MIPS32_O32=y
-# CONFIG_MIPS32_N32 is not set
+CONFIG_MIPS32_N32=y
 CONFIG_BINFMT_ELF32=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -281,7 +303,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -302,10 +327,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -335,7 +363,6 @@
 # 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
 
@@ -343,6 +370,7 @@
 # QoS and/or fair queueing
 #
 CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FIFO=y
 # CONFIG_NET_SCH_CLK_JIFFIES is not set
 CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
 # CONFIG_NET_SCH_CLK_CPU is not set
@@ -374,6 +402,7 @@
 CONFIG_NET_CLS_FW=m
 CONFIG_NET_CLS_U32=m
 # CONFIG_CLS_U32_PERF is not set
+CONFIG_CLS_U32_MARK=y
 CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
 # CONFIG_NET_EMATCH is not set
@@ -427,6 +456,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -448,6 +478,12 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -457,6 +493,8 @@
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -476,14 +514,17 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_ISCSI_ATTRS=m
 CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -496,24 +537,33 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
+# CONFIG_SCSI_ARCMSR 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_HPTIOP 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_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_QLOGIC_1280=y
 # CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -529,6 +579,7 @@
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -583,6 +634,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -619,14 +672,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -724,10 +781,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -735,7 +788,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -760,14 +812,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -779,6 +826,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -848,6 +896,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -859,6 +915,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 CONFIG_JBD_DEBUG=y
 CONFIG_FS_MBCACHE=y
@@ -870,6 +927,7 @@
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -881,6 +939,7 @@
 CONFIG_AUTOFS_FS=m
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -900,17 +959,20 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -942,7 +1004,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -975,6 +1036,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -984,13 +1053,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1003,7 +1075,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
@@ -1012,9 +1089,16 @@
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1026,6 +1110,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1035,6 +1120,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1042,3 +1128,5 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 61e069a..d9e5000 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:11 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:33 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,15 +64,17 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_ARC=y
-CONFIG_DMA_IP32=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_OWN_DMA=y
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
@@ -124,8 +126,8 @@
 CONFIG_R5000_CPU_SCACHE=y
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
@@ -141,6 +143,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -153,6 +156,7 @@
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -171,16 +175,21 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -188,12 +197,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -206,6 +215,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -246,11 +256,20 @@
 # CONFIG_BUILD_ELF64 is not set
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
 CONFIG_MIPS32_O32=y
 # CONFIG_MIPS32_N32 is not set
 CONFIG_BINFMT_ELF32=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -264,7 +283,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -284,10 +306,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -317,7 +342,6 @@
 # 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
 
@@ -372,6 +396,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -393,6 +418,12 @@
 CONFIG_ATA_OVER_ETH=y
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=y
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -402,6 +433,8 @@
 #
 CONFIG_RAID_ATTRS=y
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -421,14 +454,17 @@
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 CONFIG_SCSI_SAS_ATTRS=y
+CONFIG_SCSI_SAS_LIBSAS=y
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -446,24 +482,33 @@
 CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_AIC94XX=y
+# CONFIG_AIC94XX_DEBUG is not set
+# CONFIG_SCSI_ARCMSR 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_HPTIOP 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_STEX 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_QLA_ISCSI is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -517,6 +562,8 @@
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -553,14 +600,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=y
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=y
 
 #
 # Token Ring devices
@@ -600,6 +651,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -678,10 +730,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -689,7 +737,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -714,14 +761,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -739,6 +781,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -746,6 +789,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -808,16 +857,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -828,6 +887,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=y
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -847,17 +907,20 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=y
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -888,7 +951,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -917,6 +979,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=y
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -926,12 +996,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -946,7 +1017,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
@@ -955,9 +1031,16 @@
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_WP512=y
 CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_LRW=y
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
 CONFIG_CRYPTO_BLOWFISH=y
 CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
 CONFIG_CRYPTO_SERPENT=y
 CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_CAST5=y
@@ -969,6 +1052,7 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_CAMELLIA=y
 
 #
 # Hardware crypto devices
@@ -977,6 +1061,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=y
 CONFIG_CRC32=y
@@ -984,3 +1069,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index 8896666..57ef0c4 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:12 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:33 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -65,10 +65,14 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_JAGUAR_DMALOW=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_LIMITED_DMA=y
@@ -106,6 +110,7 @@
 CONFIG_CPU_RM9000=y
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_RM9000=y
+CONFIG_WEAK_ORDERING=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
@@ -124,8 +129,8 @@
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -141,6 +146,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -171,14 +177,19 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -186,12 +197,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -208,6 +219,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -249,6 +261,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -277,13 +297,15 @@
 # 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_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -294,6 +316,8 @@
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETWORK_SECMARK=y
 # CONFIG_NETFILTER is not set
@@ -351,6 +375,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -369,6 +394,11 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -378,6 +408,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -428,6 +464,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -475,22 +513,23 @@
 # CONFIG_R8169 is not set
 # CONFIG_SIS190 is not set
 # 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
 CONFIG_MV643XX_ETH=y
-CONFIG_MV643XX_ETH_0=y
-CONFIG_MV643XX_ETH_1=y
-CONFIG_MV643XX_ETH_2=y
+CONFIG_QLA3XXX=m
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -574,10 +613,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -608,14 +643,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -627,6 +657,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -695,14 +726,23 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS 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
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -712,6 +752,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -731,8 +772,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -752,6 +795,7 @@
 #
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
@@ -759,7 +803,6 @@
 CONFIG_SUNRPC=y
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 
@@ -779,13 +822,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -798,6 +844,10 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
@@ -807,9 +857,14 @@
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -821,6 +876,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -830,6 +886,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=m
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=m
 CONFIG_CRC32=m
@@ -837,3 +894,5 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index 835764d8..21d979f 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc1
-# Sun Oct  8 19:03:07 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:33 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -40,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -65,11 +67,14 @@
 # CONFIG_MIPS_MAGNUM_4000 is not set
 CONFIG_OLIVETTI_M700=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_ARC=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_DMA_NONCOHERENT=y
@@ -140,6 +145,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 CONFIG_HZ_100=y
 # CONFIG_HZ_128 is not set
@@ -152,6 +158,7 @@
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -171,6 +178,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
@@ -179,8 +187,8 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -257,6 +265,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -271,7 +287,9 @@
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -298,6 +316,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -317,8 +336,8 @@
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_BEET=m
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
-# CONFIG_IPV6_SUBTREES is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
@@ -331,16 +350,39 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 # CONFIG_NETFILTER_XT_TARGET_DSCP is not set
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 # CONFIG_NETFILTER_XT_TARGET_CONNSECMARK is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
@@ -362,25 +404,13 @@
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_SECMARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CONNTRACK_NETLINK=m
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_PPTP=m
-CONFIG_IP_NF_H323=m
-CONFIG_IP_NF_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -391,26 +421,25 @@
 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_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-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_NAT_SIP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -424,6 +453,7 @@
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
+CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_RT=m
@@ -433,6 +463,7 @@
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
@@ -502,6 +533,7 @@
 # QoS and/or fair queueing
 #
 CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FIFO=y
 CONFIG_NET_SCH_CLK_JIFFIES=y
 # CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
 # CONFIG_NET_SCH_CLK_CPU is not set
@@ -614,13 +646,13 @@
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
 #
 CONFIG_BLK_DEV_FD=m
 CONFIG_PARIDE=m
-CONFIG_PARIDE_PARPORT=m
 
 #
 # Parallel IDE high-level drivers
@@ -665,6 +697,10 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -674,6 +710,7 @@
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
 CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -694,6 +731,7 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
 # SCSI Transports
@@ -802,6 +840,7 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -832,7 +871,6 @@
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
-# CONFIG_LAN_SAA9730 is not set
 # CONFIG_NET_POCKET is not set
 
 #
@@ -972,17 +1010,12 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -1019,11 +1052,6 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -1054,6 +1082,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -1114,6 +1148,15 @@
 #
 
 #
+# Auxiliary Display support
+#
+# CONFIG_KS0108 is not set
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=m
@@ -1123,6 +1166,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1158,7 +1202,6 @@
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=m
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1185,7 +1228,7 @@
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1321,6 +1364,10 @@
 #
 # Distributed Lock Manager
 #
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
 
 #
 # Profiling support
@@ -1335,9 +1382,10 @@
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -1355,19 +1403,24 @@
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=m
 CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1382,6 +1435,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1391,6 +1445,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1402,3 +1457,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 50fd955..9ebb522 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:12 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:34 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,15 +64,20 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_MIPS_TX3927=y
 CONFIG_SWAP_IO_SPACE=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -114,8 +119,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -130,6 +135,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -143,6 +149,7 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_RTC_DS1742=y
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -161,15 +168,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -177,12 +189,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -195,6 +207,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -237,6 +250,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -250,7 +271,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -270,10 +294,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -303,7 +330,6 @@
 # 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
 
@@ -358,6 +384,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -378,6 +405,12 @@
 CONFIG_ATA_OVER_ETH=y
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=y
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -387,6 +420,12 @@
 #
 CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -437,6 +476,8 @@
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -472,14 +513,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=y
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=y
 
 #
 # Token Ring devices
@@ -518,6 +563,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -565,6 +611,7 @@
 # CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
+CONFIG_MOXA_SMARTIO_NEW=y
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_SYNCLINK_GT is not set
@@ -586,6 +633,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_TXX9=y
 CONFIG_HAS_TXX9_SERIAL=y
+CONFIG_SERIAL_TXX9_NR_UARTS=6
 # CONFIG_SERIAL_TXX9_CONSOLE is not set
 # CONFIG_SERIAL_TXX9_STDSERIAL is not set
 # CONFIG_SERIAL_JSM is not set
@@ -608,10 +656,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -619,7 +663,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -644,14 +687,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -666,6 +704,7 @@
 # CONFIG_FB_CFB_FILLRECT is not set
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
@@ -682,6 +721,7 @@
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -711,6 +751,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -773,14 +818,24 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -810,17 +865,19 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=y
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -849,7 +906,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -867,6 +923,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=y
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -876,12 +940,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -896,7 +961,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
@@ -905,9 +975,16 @@
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_WP512=y
 CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_LRW=y
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
 CONFIG_CRYPTO_BLOWFISH=y
 CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
 CONFIG_CRYPTO_SERPENT=y
 CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_CAST5=y
@@ -919,6 +996,7 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_CAMELLIA=y
 
 #
 # Hardware crypto devices
@@ -927,6 +1005,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=y
 CONFIG_CRC32=y
@@ -934,3 +1013,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
index 05f539f..b3f767f 100644
--- a/arch/mips/configs/lasat200_defconfig
+++ b/arch/mips/configs/lasat200_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:12 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:34 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
 CONFIG_LASAT=y
 # CONFIG_MIPS_ATLAS is not set
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -68,10 +68,14 @@
 CONFIG_DS1603=y
 CONFIG_LASAT_SYSCTL=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_MIPS_NILE4=y
@@ -121,8 +125,8 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_R5000_CPU_SCACHE=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -139,6 +143,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -151,6 +156,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -169,15 +175,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -185,12 +196,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -208,6 +219,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -250,6 +262,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -262,7 +282,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -279,10 +302,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -312,7 +338,6 @@
 # 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
 
@@ -367,11 +392,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -441,6 +468,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -461,9 +489,16 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -500,8 +535,10 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -511,6 +548,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -522,6 +560,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -572,6 +616,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -607,14 +653,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -653,6 +703,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -730,10 +781,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -741,7 +788,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -766,14 +812,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -791,6 +832,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -798,6 +840,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -860,6 +907,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -869,13 +924,15 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS 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_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -886,6 +943,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -905,23 +963,25 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
@@ -947,7 +1007,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -965,6 +1024,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -974,11 +1041,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -993,18 +1062,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1016,6 +1097,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1025,6 +1107,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1032,3 +1115,5 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 96e9410..a5f379d 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc1
-# Fri Oct  6 17:34:55 2006
+# Linux kernel version: 2.6.20
+# Sun Feb 18 21:27:55 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -40,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -62,11 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -132,14 +137,15 @@
 CONFIG_MIPS_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT_DISABLED is not set
-# CONFIG_MIPS_MT_SMTC is not set
 CONFIG_MIPS_MT_SMP=y
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_MIPS_MT=y
 CONFIG_SYS_SUPPORTS_MULTITHREADING=y
 CONFIG_MIPS_MT_FPAFF=y
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_SMARTMIPS is not set
 CONFIG_CPU_MIPSR2_IRQ_VI=y
 CONFIG_CPU_MIPSR2_SRS=y
 CONFIG_CPU_HAS_SYNC=y
@@ -147,6 +153,7 @@
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_SMARTMIPS=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -157,6 +164,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_SMP=y
 CONFIG_SYS_SUPPORTS_SMP=y
 CONFIG_NR_CPUS=2
@@ -173,6 +181,7 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_PREEMPT_BKL=y
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -192,6 +201,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -199,8 +209,8 @@
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -259,7 +269,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 CONFIG_MMU=y
 
 #
@@ -280,6 +289,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -294,7 +311,9 @@
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
@@ -302,7 +321,6 @@
 # CONFIG_IP_FIB_TRIE is not set
 CONFIG_IP_FIB_HASH=y
 CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
 CONFIG_IP_ROUTE_MULTIPATH=y
 # CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
 CONFIG_IP_ROUTE_VERBOSE=y
@@ -331,6 +349,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -379,8 +398,8 @@
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_BEET=m
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
-# CONFIG_IPV6_SUBTREES is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
@@ -393,15 +412,37 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 # CONFIG_NETFILTER_XT_TARGET_DSCP is not set
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 # CONFIG_NETFILTER_XT_TARGET_CONNSECMARK is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
@@ -425,25 +466,13 @@
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_SECMARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CONNTRACK_NETLINK=m
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_PPTP=m
-CONFIG_IP_NF_H323=m
-CONFIG_IP_NF_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -454,26 +483,25 @@
 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_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-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_NAT_SIP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -487,6 +515,7 @@
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
+CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_RT=m
@@ -496,6 +525,7 @@
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
@@ -568,6 +598,7 @@
 # QoS and/or fair queueing
 #
 CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FIFO=y
 CONFIG_NET_SCH_CLK_JIFFIES=y
 # CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
 # CONFIG_NET_SCH_CLK_CPU is not set
@@ -655,6 +686,7 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
@@ -718,6 +750,7 @@
 # NAND Flash Device Drivers
 #
 # CONFIG_MTD_NAND is not set
+# CONFIG_MTD_NAND_CAFE is not set
 
 #
 # OneNAND Flash Device Drivers
@@ -757,6 +790,12 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -801,6 +840,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -810,6 +850,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -821,6 +862,7 @@
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=m
+CONFIG_SCSI_TGT=m
 CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -841,6 +883,7 @@
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
 # SCSI Transports
@@ -889,6 +932,7 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -964,6 +1008,7 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -1002,7 +1047,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -1022,14 +1067,17 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -1146,10 +1194,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -1157,7 +1201,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -1182,11 +1225,6 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -1215,6 +1253,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1277,6 +1321,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1286,6 +1338,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1327,7 +1380,6 @@
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=m
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1365,6 +1417,20 @@
 # CONFIG_BEFS_DEBUG is not set
 CONFIG_BFS_FS=m
 CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
 CONFIG_CRAMFS=m
 CONFIG_VXFS_FS=m
 # CONFIG_HPFS_FS is not set
@@ -1470,9 +1536,10 @@
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -1489,19 +1556,24 @@
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=m
 CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1516,6 +1588,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1525,6 +1598,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1536,3 +1610,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index 03efcfd..5ff53e1 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:13 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:35 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,10 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -117,8 +121,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -136,6 +140,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -148,6 +153,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -166,15 +172,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -183,12 +194,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -206,6 +217,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_LSF is not set
 
@@ -244,6 +256,13 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -257,7 +276,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
@@ -286,10 +308,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -324,7 +349,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -332,6 +356,7 @@
 # QoS and/or fair queueing
 #
 CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FIFO=y
 CONFIG_NET_SCH_CLK_JIFFIES=y
 # CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
 # CONFIG_NET_SCH_CLK_CPU is not set
@@ -377,6 +402,7 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_IEEE80211 is not set
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -389,6 +415,7 @@
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -409,6 +436,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -423,6 +451,10 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -432,6 +464,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -468,7 +506,6 @@
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
-# CONFIG_MIPS_SIM_NET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -512,6 +549,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -579,17 +617,12 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -605,6 +638,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -613,14 +647,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -639,6 +668,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -699,16 +733,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
 # CONFIG_INOTIFY is not set
@@ -736,6 +780,7 @@
 #
 CONFIG_PROC_FS=y
 # CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
 # CONFIG_SYSFS is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
@@ -776,7 +821,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -794,6 +838,10 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -803,29 +851,34 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="nfsroot=192.168.192.169:/u1/mipsel,timeo=20 ip=dhcp"
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_KGDB is not set
 # CONFIG_RUNTIME_DEBUG is not set
 # CONFIG_MIPS_UNCACHED is not set
 
@@ -838,7 +891,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
@@ -847,7 +905,13 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 # CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_FCRYPT=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -861,6 +925,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -870,8 +935,11 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=y
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index e4221aa..750e644 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc2
-# Tue Jul 25 23:16:46 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:35 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -71,10 +71,14 @@
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_PCI_VR41XX=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -107,6 +111,7 @@
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_VR41XX=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
@@ -120,8 +125,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -136,6 +141,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -148,6 +154,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -166,16 +173,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -183,12 +194,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -206,6 +217,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -261,6 +273,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -274,7 +294,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -292,10 +315,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -325,7 +351,6 @@
 # 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
 
@@ -380,6 +405,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -399,9 +425,16 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -431,6 +464,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -492,14 +531,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -594,6 +637,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -665,10 +709,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 
 #
@@ -684,7 +724,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -709,14 +748,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -735,6 +769,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -742,6 +777,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -754,8 +795,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -764,7 +805,8 @@
 # CONFIG_USB_EHCI_HCD 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -782,7 +824,6 @@
 #
 # may also be needed; see USB_STORAGE Help for more information
 #
-# CONFIG_USB_STORAGE is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
@@ -807,6 +848,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -820,6 +862,7 @@
 # CONFIG_USB_KAWETH is not set
 CONFIG_USB_PEGASUS=m
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 # CONFIG_USB_MON is not set
 
@@ -837,18 +880,21 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX 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_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -906,16 +952,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -945,17 +1001,19 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -1000,6 +1058,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1009,11 +1075,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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 ide0=0x170,0x376,73"
 
@@ -1028,18 +1096,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1051,6 +1131,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1060,6 +1141,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1067,3 +1149,5 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
index 32b1afd..2febd0a 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:15 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:35 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,10 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -104,6 +108,7 @@
 CONFIG_CPU_RM9000=y
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_RM9000=y
+CONFIG_WEAK_ORDERING=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
@@ -122,8 +127,8 @@
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -141,6 +146,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -153,6 +159,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -171,16 +178,21 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -188,12 +200,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -211,6 +223,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -253,6 +266,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -266,7 +287,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -283,13 +307,16 @@
 # 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_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -302,11 +329,17 @@
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+CONFIG_IPV6_MIP6=y
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
 # CONFIG_IPV6_TUNNEL is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -317,15 +350,42 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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
@@ -336,14 +396,17 @@
 CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -351,6 +414,7 @@
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
+CONFIG_NF_CONNTRACK_IPV6=m
 # CONFIG_IP6_NF_QUEUE is not set
 # CONFIG_IP6_NF_IPTABLES is not set
 
@@ -377,7 +441,6 @@
 # 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
 
@@ -401,6 +464,7 @@
 CONFIG_IEEE80211_SOFTMAC=m
 # CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
 CONFIG_WIRELESS_EXT=y
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -432,6 +496,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -451,6 +516,12 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -460,6 +531,8 @@
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=m
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -478,14 +551,17 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # CONFIG_SCSI_SPI_ATTRS is not set
 CONFIG_SCSI_FC_ATTRS=m
 CONFIG_SCSI_ISCSI_ATTRS=m
 CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -498,26 +574,35 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR 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_HPTIOP 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_STEX 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_QLA_ISCSI 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
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -571,6 +656,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -607,7 +694,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -627,17 +714,18 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_MV643XX_ETH=y
-CONFIG_MV643XX_ETH_0=y
-CONFIG_MV643XX_ETH_1=y
-CONFIG_MV643XX_ETH_2=y
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -665,6 +753,7 @@
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
@@ -685,6 +774,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -758,10 +848,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -769,7 +855,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -794,14 +879,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -816,6 +896,7 @@
 # CONFIG_FB_CFB_FILLRECT is not set
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
@@ -832,6 +913,7 @@
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -868,6 +950,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -930,6 +1018,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -939,6 +1035,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=m
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -947,12 +1044,13 @@
 # CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -963,6 +1061,7 @@
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -982,11 +1081,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1029,7 +1130,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1086,6 +1186,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1095,11 +1203,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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"
 
@@ -1113,18 +1223,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1136,6 +1258,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1145,6 +1268,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1156,3 +1280,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index ebe75c1..b8f4573 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:16 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:36 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,10 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -120,8 +124,8 @@
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
@@ -138,6 +142,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -150,6 +155,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -168,15 +174,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -184,12 +195,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -202,6 +213,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -242,11 +254,20 @@
 # CONFIG_BUILD_ELF64 is not set
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
 CONFIG_MIPS32_O32=y
 CONFIG_MIPS32_N32=y
 CONFIG_BINFMT_ELF32=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -259,7 +280,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -279,10 +303,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -312,7 +339,6 @@
 # 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
 
@@ -367,6 +393,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -387,6 +414,12 @@
 CONFIG_ATA_OVER_ETH=y
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=y
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -396,6 +429,12 @@
 #
 CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -446,6 +485,8 @@
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -482,14 +523,18 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_MV643XX_ETH is not set
+CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=y
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=y
 
 #
 # Token Ring devices
@@ -528,6 +573,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -605,10 +651,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -616,7 +658,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -641,14 +682,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -666,6 +702,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -673,6 +710,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -735,16 +777,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -755,6 +807,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=y
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -774,17 +827,20 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=y
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -816,7 +872,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -834,6 +889,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=y
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -843,12 +906,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -863,7 +927,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
@@ -872,9 +941,16 @@
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_WP512=y
 CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_LRW=y
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
 CONFIG_CRYPTO_BLOWFISH=y
 CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
 CONFIG_CRYPTO_SERPENT=y
 CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_CAST5=y
@@ -886,6 +962,7 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_CAMELLIA=y
 
 #
 # Hardware crypto devices
@@ -894,6 +971,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=y
 CONFIG_CRC32=y
@@ -901,3 +979,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index 5a9603c..8ade072 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:16 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:36 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,10 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -123,8 +127,8 @@
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -142,6 +146,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -154,6 +159,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -172,15 +178,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -188,12 +199,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -206,6 +217,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -233,7 +245,6 @@
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -247,6 +258,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -259,7 +278,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -279,10 +301,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -312,7 +337,6 @@
 # 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
 
@@ -345,7 +369,6 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -367,6 +390,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -382,6 +406,10 @@
 CONFIG_ATA_OVER_ETH=y
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -391,6 +419,12 @@
 #
 CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -434,6 +468,8 @@
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -484,6 +520,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -557,17 +594,12 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -592,14 +624,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -617,6 +644,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -624,6 +652,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -684,16 +717,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -704,6 +747,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=y
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -723,17 +767,20 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=y
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -765,7 +812,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -783,6 +829,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=y
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -792,14 +846,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -812,7 +868,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
@@ -821,9 +882,16 @@
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_WP512=y
 CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_LRW=y
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
 CONFIG_CRYPTO_BLOWFISH=y
 CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
 CONFIG_CRYPTO_SERPENT=y
 CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_CAST5=y
@@ -835,6 +903,7 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_CAMELLIA=y
 
 #
 # Hardware crypto devices
@@ -843,6 +912,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=y
 CONFIG_CRC32=y
@@ -850,3 +920,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
index 46a942c..d20a221 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:16 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:36 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,10 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -106,15 +110,14 @@
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_RM7000=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
 #
-# CONFIG_32BIT is not set
-CONFIG_64BIT=y
+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
@@ -123,9 +126,10 @@
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -141,6 +145,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -153,6 +158,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -171,15 +177,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -187,12 +198,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -205,7 +216,10 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_LSF=y
 
 #
 # IO Schedulers
@@ -242,12 +256,15 @@
 #
 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
-CONFIG_MIPS32_N32=y
-CONFIG_BINFMT_ELF32=y
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
 
 #
 # Networking
@@ -262,7 +279,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -282,10 +302,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -315,7 +338,6 @@
 # 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
 
@@ -370,6 +392,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -390,6 +413,12 @@
 CONFIG_ATA_OVER_ETH=y
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=y
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -399,6 +428,12 @@
 #
 CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -449,6 +484,8 @@
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -485,14 +522,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=y
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=y
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=y
 
 #
 # Token Ring devices
@@ -531,6 +572,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -608,10 +650,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -619,7 +657,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -644,14 +681,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -669,6 +701,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -676,6 +709,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -738,16 +776,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -758,6 +806,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=y
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -777,17 +826,20 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=y
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -819,7 +871,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -837,6 +888,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=y
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -846,12 +905,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -866,7 +926,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
@@ -875,9 +940,16 @@
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_WP512=y
 CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_LRW=y
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
 CONFIG_CRYPTO_BLOWFISH=y
 CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
 CONFIG_CRYPTO_SERPENT=y
 CONFIG_CRYPTO_AES=y
 CONFIG_CRYPTO_CAST5=y
@@ -889,6 +961,7 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_CAMELLIA=y
 
 #
 # Hardware crypto devices
@@ -897,6 +970,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=y
 CONFIG_CRC32=y
@@ -904,3 +978,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 7d3c688..33fcc81 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:17 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:37 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,14 +64,19 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 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_APM_EMULATION=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SOC_AU1100=y
 CONFIG_SOC_AU1X00=y
@@ -117,8 +122,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_64BIT_PHYS_ADDR=y
 CONFIG_CPU_HAS_LLSC=y
@@ -136,6 +141,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -148,6 +154,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -166,15 +173,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -182,12 +194,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -205,6 +217,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -253,6 +266,10 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
 # CONFIG_PM is not set
 
 #
@@ -269,7 +286,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -290,10 +310,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -312,15 +335,42 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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
@@ -331,14 +381,17 @@
 CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -366,7 +419,6 @@
 # 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
 
@@ -422,11 +474,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -495,6 +549,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -511,6 +566,10 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -520,6 +579,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -563,6 +628,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -609,6 +676,7 @@
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -628,6 +696,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -707,10 +776,6 @@
 # CONFIG_R3964 is not set
 
 #
-# Ftape, the floppy tape device driver
-#
-
-#
 # PCMCIA character devices
 #
 CONFIG_SYNCLINK_CS=m
@@ -722,7 +787,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -747,14 +811,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -772,6 +831,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -779,6 +839,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -840,6 +905,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -851,6 +924,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -863,6 +937,7 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -873,6 +948,7 @@
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -892,23 +968,25 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
@@ -937,7 +1015,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -994,6 +1071,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1003,13 +1088,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1022,18 +1110,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1045,6 +1145,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1054,6 +1155,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1065,3 +1167,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index a77805a..e07c55d 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:17 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:37 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,14 +64,19 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 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_APM_EMULATION=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SOC_AU1500=y
 CONFIG_SOC_AU1X00=y
@@ -116,8 +121,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_64BIT_PHYS_ADDR=y
 CONFIG_CPU_HAS_LLSC=y
@@ -134,7 +139,8 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -147,6 +153,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -165,15 +172,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -181,12 +193,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -204,6 +216,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -258,6 +271,10 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
 # CONFIG_PM is not set
 
 #
@@ -274,7 +291,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -295,10 +315,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -317,15 +340,42 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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
@@ -336,14 +386,17 @@
 CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -371,7 +424,6 @@
 # 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
 
@@ -427,11 +479,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -501,6 +555,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -522,9 +577,16 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -534,6 +596,7 @@
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
 CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_DELKIN is not set
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -561,8 +624,10 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -572,6 +637,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -583,6 +649,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -633,6 +705,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -670,14 +744,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -718,6 +796,7 @@
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -737,6 +816,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -815,10 +895,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 
 #
@@ -833,7 +909,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -858,14 +933,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -877,6 +947,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -884,6 +955,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -946,6 +1022,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -957,6 +1041,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -969,6 +1054,7 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -979,6 +1065,7 @@
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -998,23 +1085,25 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
@@ -1043,7 +1132,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1100,6 +1188,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1109,13 +1205,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1128,18 +1227,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1151,6 +1262,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1160,6 +1272,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1171,3 +1284,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 8318d74..df210dd 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:17 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:37 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,15 +64,20 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SOC_AU1550=y
 CONFIG_SOC_AU1X00=y
@@ -117,8 +122,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_64BIT_PHYS_ADDR=y
 CONFIG_CPU_HAS_LLSC=y
@@ -135,7 +140,8 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -148,6 +154,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -166,15 +173,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -182,12 +194,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -205,6 +217,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -259,6 +272,10 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
 # CONFIG_PM is not set
 
 #
@@ -275,7 +292,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -296,10 +316,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -318,15 +341,42 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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
@@ -337,14 +387,17 @@
 CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -372,7 +425,6 @@
 # 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
 
@@ -428,11 +480,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -502,6 +556,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -523,9 +578,16 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -535,6 +597,7 @@
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
 CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_DELKIN is not set
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -562,8 +625,10 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -573,6 +638,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -584,6 +650,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -634,6 +706,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -671,14 +745,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -711,6 +789,7 @@
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -730,6 +809,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -808,10 +888,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 
 #
@@ -826,7 +902,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -851,14 +926,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -870,6 +940,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -877,6 +948,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -939,6 +1015,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -950,6 +1034,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -962,6 +1047,7 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -972,6 +1058,7 @@
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -991,23 +1078,25 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
@@ -1036,7 +1125,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1093,6 +1181,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1102,13 +1198,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1121,18 +1220,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1144,6 +1255,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1153,6 +1265,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1164,3 +1277,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index fcb8fea..106a164 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2
-# Sat Oct 14 23:01:16 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:38 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -40,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 CONFIG_PNX8550_JBS=y
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -62,11 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -134,6 +139,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -146,6 +152,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -165,6 +172,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -172,6 +180,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -231,7 +240,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 CONFIG_MMU=y
 
@@ -253,6 +261,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -267,6 +283,7 @@
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -293,6 +310,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -350,6 +368,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -370,6 +389,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -393,6 +413,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -436,6 +462,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -445,6 +472,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -456,6 +484,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
 CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -475,6 +504,7 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
 # SCSI Transports
@@ -518,6 +548,7 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -605,7 +636,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -625,14 +656,17 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -720,7 +754,10 @@
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_IP3106 is not set
+CONFIG_SERIAL_PNX8XXX=y
+CONFIG_SERIAL_PNX8XXX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
@@ -741,10 +778,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -752,7 +785,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -768,6 +800,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -776,15 +809,11 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -814,6 +843,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -826,8 +860,8 @@
 # Miscellaneous USB options
 #
 # CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -836,7 +870,8 @@
 # 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -890,7 +925,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -905,6 +940,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -927,6 +963,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -935,6 +972,7 @@
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 
 #
 # USB DSL modem support
@@ -991,6 +1029,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1041,7 +1087,7 @@
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1137,6 +1183,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1149,33 +1203,35 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 CONFIG_DEBUG_SLAB=y
 # CONFIG_DEBUG_SLAB_LEAK is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_KGDB is not set
+CONFIG_SYS_SUPPORTS_KGDB=y
 # CONFIG_RUNTIME_DEBUG is not set
 # CONFIG_MIPS_UNCACHED is not set
 
@@ -1189,21 +1245,27 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
 CONFIG_CRYPTO_MANAGER=m
 # CONFIG_CRYPTO_HMAC is not set
+CONFIG_CRYPTO_XCBC=m
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 # 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_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 # CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_FCRYPT=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1217,6 +1279,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1226,8 +1289,11 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig
index f38a2c1..8caa2cd 100644
--- a/arch/mips/configs/pnx8550-stb810_defconfig
+++ b/arch/mips/configs/pnx8550-stb810_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19
-# Thu Dec  7 16:35:12 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:38 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -58,17 +59,19 @@
 # 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_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
-# CONFIG_KEXEC is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -136,6 +139,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -148,6 +152,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -167,6 +172,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -234,7 +240,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 CONFIG_MMU=y
 
@@ -254,6 +259,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -268,6 +281,7 @@
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -351,6 +365,7 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -371,6 +386,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -443,6 +459,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -452,6 +469,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -463,6 +481,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
 # CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
@@ -482,6 +501,7 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
 # SCSI Transports
@@ -525,6 +545,7 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -608,6 +629,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -627,11 +649,13 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
@@ -775,6 +799,7 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
@@ -808,6 +833,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -820,9 +850,8 @@
 # Miscellaneous USB options
 #
 # CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -831,7 +860,8 @@
 # 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -885,6 +915,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -922,6 +953,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -987,6 +1019,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1037,7 +1077,7 @@
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1133,6 +1173,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1145,33 +1193,35 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 CONFIG_DEBUG_SLAB=y
 # CONFIG_DEBUG_SLAB_LEAK is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
-CONFIG_HEADERS_CHECK=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_KGDB is not set
+CONFIG_SYS_SUPPORTS_KGDB=y
 # CONFIG_RUNTIME_DEBUG is not set
 # CONFIG_MIPS_UNCACHED is not set
 
@@ -1187,8 +1237,10 @@
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=m
 CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
 CONFIG_CRYPTO_MANAGER=m
 # CONFIG_CRYPTO_HMAC is not set
+CONFIG_CRYPTO_XCBC=m
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=m
@@ -1197,9 +1249,13 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 # CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_FCRYPT=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1213,6 +1269,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1222,8 +1279,11 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
index 5bc3248..43f1bec 100644
--- a/arch/mips/configs/pnx8550-v2pci_defconfig
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2
-# Sat Oct 14 23:12:15 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:39 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -40,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 CONFIG_PNX8550_V2PCI=y
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -62,11 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -134,6 +139,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -146,6 +152,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -165,6 +172,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -172,6 +180,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -230,7 +239,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 CONFIG_MMU=y
 
 #
@@ -251,6 +259,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -265,6 +281,7 @@
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -282,7 +299,7 @@
 # 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_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
@@ -291,6 +308,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -312,7 +330,6 @@
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_SIT=m
 # CONFIG_IPV6_TUNNEL is not set
-# CONFIG_IPV6_SUBTREES is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
@@ -322,15 +339,38 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
 # CONFIG_NETFILTER_XT_MATCH_DSCP is not set
 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
@@ -341,14 +381,17 @@
 # CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 # CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -356,6 +399,7 @@
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
+CONFIG_NF_CONNTRACK_IPV6=m
 # CONFIG_IP6_NF_QUEUE is not set
 # CONFIG_IP6_NF_IPTABLES is not set
 
@@ -430,6 +474,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -453,6 +498,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -497,6 +548,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -506,6 +558,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -517,6 +570,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
 CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -536,6 +590,7 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
 # SCSI Transports
@@ -584,6 +639,7 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -671,7 +727,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -691,14 +747,17 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -804,6 +863,7 @@
 # CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
+CONFIG_MOXA_SMARTIO_NEW=m
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_SYNCLINK_GT is not set
@@ -822,7 +882,10 @@
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_IP3106 is not set
+CONFIG_SERIAL_PNX8XXX=y
+CONFIG_SERIAL_PNX8XXX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
@@ -843,10 +906,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -854,7 +913,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -883,6 +941,7 @@
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 # CONFIG_I2C_SIS5595 is not set
@@ -918,6 +977,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -928,6 +988,7 @@
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
@@ -951,6 +1012,7 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
@@ -961,17 +1023,13 @@
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -991,6 +1049,7 @@
 # CONFIG_FB_CFB_FILLRECT is not set
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
@@ -1007,6 +1066,7 @@
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -1036,6 +1096,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1048,8 +1114,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1085,7 +1151,6 @@
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
-# CONFIG_USB_STORAGE_ONETOUCH is not set
 # CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
@@ -1093,7 +1158,6 @@
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
@@ -1109,7 +1173,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1124,6 +1188,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1146,6 +1211,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1154,6 +1220,7 @@
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1211,6 +1278,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1271,7 +1346,7 @@
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1368,6 +1443,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1380,12 +1463,13 @@
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1397,21 +1481,27 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
 CONFIG_CRYPTO_MANAGER=m
 # CONFIG_CRYPTO_HMAC is not set
+CONFIG_CRYPTO_XCBC=m
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 # 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_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 # CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_FCRYPT=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -1425,6 +1515,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1434,6 +1525,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -1445,3 +1537,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index aa61f0f..f68396d 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:18 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:39 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,16 +64,21 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_COHERENT=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_I8259=y
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SWAP_IO_SPACE=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 CONFIG_HAVE_STD_PC_SERIAL_PORT=y
@@ -117,8 +122,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -130,9 +135,10 @@
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 CONFIG_HZ_100=y
 # CONFIG_HZ_128 is not set
@@ -164,12 +170,15 @@
 # CONFIG_SWAP is not set
 # CONFIG_SYSVIPC is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -194,6 +203,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -221,7 +231,6 @@
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -235,6 +244,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -268,10 +285,12 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -307,7 +326,6 @@
 #
 CONFIG_STANDALONE=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_FW_LOADER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -330,6 +348,7 @@
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -343,6 +362,10 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -352,6 +375,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Old CD-ROM drivers (not SCSI, not IDE)
@@ -459,6 +488,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -525,10 +555,6 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -558,14 +584,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -585,6 +606,7 @@
 # CONFIG_VGACON_SOFT_SCROLLBACK is not set
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -592,6 +614,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -651,14 +679,23 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS 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
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -668,6 +705,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=y
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -687,8 +725,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -709,6 +749,7 @@
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_DIRECTIO=y
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
@@ -717,7 +758,6 @@
 CONFIG_SUNRPC=y
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 
@@ -737,12 +777,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -758,13 +799,12 @@
 # CONFIG_CRYPTO is not set
 
 #
-# Hardware crypto devices
-#
-
-#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index f9e8f41..a6a824f 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:19 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:39 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -71,10 +71,14 @@
 # CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND is not set
 # CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_GENERIC_ISA_DMA=y
@@ -126,8 +130,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
@@ -143,6 +147,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -155,6 +160,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -173,16 +179,22 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -211,6 +223,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -254,6 +267,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -267,6 +288,8 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -285,13 +308,16 @@
 # 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_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -304,11 +330,17 @@
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+CONFIG_IPV6_MIP6=y
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
 # CONFIG_IPV6_TUNNEL is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -319,15 +351,42 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-# CONFIG_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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
@@ -338,14 +397,17 @@
 CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -353,6 +415,7 @@
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
+CONFIG_NF_CONNTRACK_IPV6=m
 # CONFIG_IP6_NF_QUEUE is not set
 # CONFIG_IP6_NF_IPTABLES is not set
 
@@ -379,7 +442,6 @@
 # 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
 
@@ -404,6 +466,7 @@
 CONFIG_IEEE80211_SOFTMAC=m
 # CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
 CONFIG_WIRELESS_EXT=y
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -436,11 +499,13 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -510,6 +575,7 @@
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -527,14 +593,22 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -570,8 +644,10 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_IT8213=m
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -581,6 +657,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
 # CONFIG_IDE_ARM is not set
 # CONFIG_IDE_CHIPSETS is not set
 CONFIG_BLK_DEV_IDEDMA=y
@@ -593,6 +670,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Old CD-ROM drivers (not SCSI, not IDE)
@@ -648,6 +731,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -702,7 +787,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -721,14 +806,18 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -785,6 +874,7 @@
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -804,6 +894,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -826,6 +917,7 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
@@ -868,6 +960,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_TXX9=y
 CONFIG_HAS_TXX9_SERIAL=y
+CONFIG_SERIAL_TXX9_NR_UARTS=6
 # CONFIG_SERIAL_TXX9_CONSOLE is not set
 # CONFIG_SERIAL_TXX9_STDSERIAL is not set
 # CONFIG_SERIAL_JSM is not set
@@ -890,10 +983,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -901,7 +990,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -926,17 +1014,14 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -952,6 +1037,7 @@
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
@@ -971,6 +1057,7 @@
 CONFIG_FB_ATY_CT=y
 # CONFIG_FB_ATY_GENERIC_LCD is not set
 # CONFIG_FB_ATY_GX is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -1002,6 +1089,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1014,8 +1107,8 @@
 # Miscellaneous USB options
 #
 # CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1040,14 +1133,12 @@
 #
 # may also be needed; see USB_STORAGE Help for more information
 #
-# CONFIG_USB_STORAGE is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
@@ -1063,6 +1154,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1076,6 +1168,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1093,18 +1186,21 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX 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_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 
 #
 # USB DSL modem support
@@ -1161,6 +1257,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1170,6 +1274,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=m
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1178,12 +1283,13 @@
 # CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1194,6 +1300,7 @@
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1218,11 +1325,13 @@
 #
 CONFIG_PROC_FS=y
 # CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1234,7 +1343,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1273,7 +1381,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1330,6 +1437,14 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1339,13 +1454,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
@@ -1357,18 +1475,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1380,6 +1510,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1389,6 +1520,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1399,3 +1531,5 @@
 CONFIG_TEXTSEARCH_KMP=m
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 496aa67..bee3702 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:19 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:40 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,10 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_ARC=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_DMA_NONCOHERENT=y
@@ -78,10 +82,10 @@
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
 CONFIG_ARC32=y
 CONFIG_BOOT_ELF32=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-CONFIG_HAVE_STD_PC_SERIAL_PORT=y
+CONFIG_MIPS_L1_CACHE_SHIFT=4
 CONFIG_ARC_CONSOLE=y
 CONFIG_ARC_MEMORY=y
 CONFIG_ARC_PROMLIB=y
@@ -110,6 +114,7 @@
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_R4X00=y
 CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_HAS_CPU_R10000=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
@@ -127,8 +132,8 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_R5000_CPU_SCACHE=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -146,6 +151,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -158,6 +164,7 @@
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -176,17 +183,22 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -194,12 +206,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -217,6 +229,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -263,6 +276,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -276,7 +297,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -297,10 +321,13 @@
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -313,11 +340,17 @@
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=y
 CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -329,18 +362,43 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 # CONFIG_NETFILTER_XT_TARGET_CONNSECMARK is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
@@ -358,60 +416,45 @@
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_SECMARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CONNTRACK_NETLINK=m
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_PPTP=m
-CONFIG_IP_NF_H323=m
-CONFIG_IP_NF_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=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=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_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-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_NAT_SIP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_RAW=m
@@ -422,6 +465,7 @@
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
+CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_RT=m
@@ -431,6 +475,7 @@
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
@@ -493,7 +538,6 @@
 # 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
 
@@ -501,6 +545,7 @@
 # QoS and/or fair queueing
 #
 CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FIFO=y
 CONFIG_NET_SCH_CLK_JIFFIES=y
 # CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
 # CONFIG_NET_SCH_CLK_CPU is not set
@@ -575,6 +620,7 @@
 CONFIG_IEEE80211_SOFTMAC=m
 # CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
 CONFIG_WIRELESS_EXT=y
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -606,22 +652,22 @@
 CONFIG_PARPORT_SERIAL=m
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
-CONFIG_PARPORT_NOT_PC=y
 # CONFIG_PARPORT_GSC is not set
 # CONFIG_PARPORT_AX88796 is not set
 CONFIG_PARPORT_1284=y
+CONFIG_PARPORT_NOT_PC=y
 
 #
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
 #
 CONFIG_BLK_DEV_FD=m
 CONFIG_PARIDE=m
-CONFIG_PARIDE_PARPORT=m
 
 #
 # Parallel IDE high-level drivers
@@ -664,6 +710,7 @@
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -671,6 +718,12 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -680,6 +733,8 @@
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -699,14 +754,17 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_ISCSI_ATTRS=m
 CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -720,14 +778,16 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
 CONFIG_MEGARAID_NEWGEN=y
 CONFIG_MEGARAID_MM=m
 CONFIG_MEGARAID_MAILBOX=m
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
@@ -742,17 +802,19 @@
 # CONFIG_SCSI_IZIP_EPP16 is not set
 # CONFIG_SCSI_IZIP_SLOW_CTR is not set
 # CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SNI_53C710 is not set
+# CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 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_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC395x is not set
@@ -760,6 +822,12 @@
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Old CD-ROM drivers (not SCSI, not IDE)
@@ -780,6 +848,7 @@
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
 # CONFIG_DM_CRYPT is not set
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -834,6 +903,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -868,6 +939,7 @@
 # CONFIG_SEEQ8005 is not set
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_AC3200 is not set
@@ -888,7 +960,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 # CONFIG_NET_POCKET is not set
 
 #
@@ -908,14 +980,18 @@
 CONFIG_VIA_VELOCITY=m
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -956,6 +1032,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
 
 #
 # Userland interfaces
@@ -978,6 +1055,7 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
@@ -1051,10 +1129,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -1062,7 +1136,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -1101,14 +1174,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -1129,6 +1197,7 @@
 # CONFIG_VGACON_SOFT_SCROLLBACK is not set
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -1136,6 +1205,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1148,8 +1223,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1159,9 +1234,11 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=m
 # CONFIG_USB_SL811_HCD is not set
@@ -1189,18 +1266,20 @@
 CONFIG_USB_STORAGE_SDDR55=y
 CONFIG_USB_STORAGE_JUMPSHOT=y
 # CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA 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=y
 CONFIG_HID_PID=y
 CONFIG_LOGITECH_FF=y
+# CONFIG_PANTHERLORD_FF is not set
 CONFIG_THRUSTMASTER_FF=y
+# CONFIG_ZEROPLUS_FF is not set
 CONFIG_USB_HIDDEV=y
 
 #
@@ -1220,6 +1299,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1234,12 +1314,14 @@
 CONFIG_USB_KAWETH=m
 CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET_MII=m
 CONFIG_USB_USBNET=m
 CONFIG_USB_NET_AX8817X=m
 CONFIG_USB_NET_CDCETHER=m
 # CONFIG_USB_NET_GL620A is not set
 CONFIG_USB_NET_NET1080=m
 # CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 CONFIG_USB_NET_ZAURUS=m
@@ -1255,8 +1337,8 @@
 #
 CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
 CONFIG_USB_SERIAL_AIRPRIME=m
-CONFIG_USB_SERIAL_ANYDATA=m
 # CONFIG_USB_SERIAL_ARK3116 is not set
 CONFIG_USB_SERIAL_BELKIN=m
 CONFIG_USB_SERIAL_WHITEHEAT=m
@@ -1290,16 +1372,20 @@
 CONFIG_USB_SERIAL_KLSI=m
 CONFIG_USB_SERIAL_KOBIL_SCT=m
 CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
 # CONFIG_USB_SERIAL_NAVMAN is not set
 CONFIG_USB_SERIAL_PL2303=m
 CONFIG_USB_SERIAL_HP4X=m
 CONFIG_USB_SERIAL_SAFE=m
 CONFIG_USB_SERIAL_SAFE_PADDED=y
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
 # CONFIG_USB_SERIAL_TI is not set
 CONFIG_USB_SERIAL_CYBERJACK=m
 CONFIG_USB_SERIAL_XIRCOM=m
 # CONFIG_USB_SERIAL_OPTION is not set
 CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_DEBUG is not set
 CONFIG_USB_EZUSB=y
 
 #
@@ -1307,20 +1393,23 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
 CONFIG_USB_AUERSWALD=m
 CONFIG_USB_RIO500=m
 CONFIG_USB_LEGOTOWER=m
 CONFIG_USB_LCD=m
+# CONFIG_USB_BERRY_CHARGE is not set
 CONFIG_USB_LED=m
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 CONFIG_USB_CYTHERM=m
-CONFIG_USB_PHIDGETKIT=m
-CONFIG_USB_PHIDGETSERVO=m
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 CONFIG_USB_SISUSBVGA=m
 # CONFIG_USB_SISUSBVGA_CON is not set
 CONFIG_USB_LD=m
+# CONFIG_USB_TRANCEVIBRATOR is not set
 CONFIG_USB_TEST=m
 
 #
@@ -1378,6 +1467,15 @@
 #
 
 #
+# Auxiliary Display support
+#
+# CONFIG_KS0108 is not set
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=m
@@ -1387,6 +1485,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1403,6 +1502,7 @@
 CONFIG_XFS_SECURITY=y
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 CONFIG_MINIX_FS=m
 CONFIG_ROMFS_FS=m
@@ -1414,6 +1514,7 @@
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1421,7 +1522,6 @@
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=m
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1442,11 +1542,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1454,6 +1556,7 @@
 CONFIG_ADFS_FS=m
 # CONFIG_ADFS_FS_RW is not set
 CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
 CONFIG_HFS_FS=m
 # CONFIG_HFSPLUS_FS is not set
 CONFIG_BEFS_FS=m
@@ -1579,6 +1682,14 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1588,11 +1699,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -1607,18 +1720,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1630,6 +1755,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1639,6 +1765,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -1650,3 +1777,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index e33c172..3c891ed 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:19 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:40 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -81,10 +81,14 @@
 # CONFIG_SIBYTE_SB1250_PROF is not set
 # CONFIG_SIBYTE_TBPROF is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_COHERENT=y
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
@@ -117,6 +121,7 @@
 # CONFIG_CPU_RM9000 is not set
 CONFIG_CPU_SB1=y
 CONFIG_SYS_HAS_CPU_SB1=y
+CONFIG_WEAK_ORDERING=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
@@ -134,8 +139,8 @@
 # CONFIG_SIBYTE_DMA_PAGEOPS is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_SB1_PASS_1_WORKAROUNDS=y
 CONFIG_CPU_HAS_LLSC=y
@@ -155,8 +160,10 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_SMP=y
 CONFIG_SYS_SUPPORTS_SMP=y
+CONFIG_NR_CPUS_DEFAULT_2=y
 CONFIG_NR_CPUS=2
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
@@ -171,6 +178,7 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_PREEMPT_BKL=y
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -189,16 +197,22 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_CPUSETS=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -206,12 +220,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -230,6 +244,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -270,11 +285,20 @@
 # CONFIG_BUILD_ELF64 is not set
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
 CONFIG_MIPS32_O32=y
 # CONFIG_MIPS32_N32 is not set
 CONFIG_BINFMT_ELF32=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -288,7 +312,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -308,10 +335,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -341,7 +371,6 @@
 # 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
 
@@ -395,6 +424,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -410,6 +440,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=9220
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -417,9 +448,16 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -449,6 +487,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -499,6 +543,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -535,14 +581,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -604,6 +654,7 @@
 # CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
+CONFIG_MOXA_SMARTIO_NEW=m
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_SYNCLINK_GT is not set
@@ -643,10 +694,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -654,7 +701,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -679,14 +725,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -698,6 +739,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -767,6 +809,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -775,11 +825,13 @@
 CONFIG_EXT2_FS_SECURITY=y
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -809,17 +861,19 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -850,7 +904,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -868,6 +921,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -877,13 +938,16 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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_SYS_SUPPORTS_KGDB=y
 # CONFIG_SB1XXX_CORELIS is not set
 
 #
@@ -897,18 +961,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -920,6 +996,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -929,6 +1006,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=m
 CONFIG_CRC32=y
@@ -936,3 +1014,5 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 83fb932..e31d964 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:20 2006
+# Linux kernel version: 2.6.20
+# Sun Feb 18 21:28:10 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,10 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -120,15 +124,17 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_SMARTMIPS is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_SMARTMIPS=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -139,6 +145,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -151,6 +158,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -169,13 +177,18 @@
 CONFIG_LOCALVERSION_AUTO=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -183,12 +196,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -201,6 +214,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -226,7 +240,6 @@
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -240,6 +253,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 # CONFIG_NET is not set
@@ -253,7 +274,6 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -283,10 +303,15 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=18432
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -296,6 +321,12 @@
 #
 CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -373,17 +404,12 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -399,6 +425,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -407,14 +434,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -425,6 +447,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -492,16 +515,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -530,6 +563,7 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
@@ -585,12 +619,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -606,10 +641,6 @@
 # CONFIG_CRYPTO is not set
 
 #
-# Hardware crypto devices
-#
-
-#
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
@@ -617,3 +648,5 @@
 # CONFIG_CRC32 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index e9d4eae..5771c1a 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:20 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:41 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -72,12 +72,15 @@
 # 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_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -110,6 +113,7 @@
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_VR41XX=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
@@ -123,8 +127,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -139,6 +143,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -151,6 +156,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -169,15 +175,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -185,12 +196,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -208,6 +219,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -250,6 +262,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -263,6 +283,8 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -290,10 +312,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -323,7 +348,6 @@
 # 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
 
@@ -340,6 +364,7 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_IEEE80211 is not set
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -371,6 +396,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -388,11 +414,18 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -402,6 +435,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -420,14 +455,17 @@
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # 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
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -440,26 +478,35 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR 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_HPTIOP 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_STEX 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_QLA_ISCSI 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
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -513,6 +560,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -549,7 +598,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -568,14 +617,18 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -615,6 +668,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -682,10 +736,6 @@
 # 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
@@ -694,7 +744,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -719,14 +768,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -745,6 +789,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -752,6 +797,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -764,8 +815,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -775,9 +826,11 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -805,6 +858,7 @@
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
@@ -829,6 +883,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -843,6 +898,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 # CONFIG_USB_MON is not set
 
@@ -860,19 +916,22 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX 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_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -918,6 +977,7 @@
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
 CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
 
 #
 # RTC interfaces
@@ -951,16 +1011,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=m
@@ -971,6 +1041,7 @@
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -990,11 +1061,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1036,7 +1109,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1054,6 +1126,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1063,11 +1143,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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"
 
@@ -1080,7 +1162,44 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=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_CAMELLIA=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -1092,6 +1211,9 @@
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 # CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
index c19597f..a8eb4b1 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0229_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:20 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:41 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -72,12 +72,15 @@
 # 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_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -110,6 +113,7 @@
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_VR41XX=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
@@ -123,8 +127,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -139,6 +143,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -151,6 +156,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -169,15 +175,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -185,12 +196,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -208,6 +219,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -250,6 +262,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -263,6 +283,8 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -291,10 +313,13 @@
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -324,7 +349,6 @@
 # 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
 
@@ -341,6 +365,7 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_IEEE80211 is not set
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -372,6 +397,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -389,11 +415,18 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -403,6 +436,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -453,6 +492,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -489,14 +530,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -535,6 +580,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -602,10 +648,6 @@
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 CONFIG_TANBAC_TB0219=y
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
@@ -614,7 +656,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -630,6 +671,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -638,14 +680,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -664,6 +701,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -671,6 +709,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -683,8 +727,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -694,9 +738,11 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -714,7 +760,6 @@
 #
 # may also be needed; see USB_STORAGE Help for more information
 #
-# CONFIG_USB_STORAGE is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
@@ -739,6 +784,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -752,6 +798,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -769,19 +816,22 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX 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_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -827,6 +877,7 @@
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
 CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
 
 #
 # RTC interfaces
@@ -860,16 +911,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=m
@@ -880,6 +941,7 @@
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -899,11 +961,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -945,7 +1009,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -963,6 +1026,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -972,11 +1043,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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"
 
@@ -989,7 +1062,44 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=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_CAMELLIA=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -998,9 +1108,13 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index 97d94f9..69b8730 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2
-# Wed Oct 18 12:57:11 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:41 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -40,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -71,11 +73,14 @@
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_PCI_VR41XX=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -108,6 +113,7 @@
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_VR41XX=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
@@ -137,6 +143,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -149,6 +156,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -168,14 +176,15 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -233,7 +242,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 CONFIG_MMU=y
 
 #
@@ -252,6 +260,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -266,6 +282,7 @@
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -315,6 +332,7 @@
 # CONFIG_DEFAULT_WESTWOOD is not set
 # CONFIG_DEFAULT_RENO is not set
 CONFIG_DEFAULT_TCP_CONG="bic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -391,6 +409,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -414,6 +433,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -423,6 +448,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
 # CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
@@ -442,6 +468,7 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
 # SCSI Transports
@@ -486,11 +513,13 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SVW is not set
 # CONFIG_ATA_PIIX is not set
@@ -506,6 +535,7 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
@@ -521,8 +551,10 @@
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
 # CONFIG_PATA_MPIIX is not set
 # CONFIG_PATA_OLDPIIX is not set
 # CONFIG_PATA_NETCELL is not set
@@ -539,6 +571,7 @@
 # CONFIG_PATA_SIS is not set
 # CONFIG_PATA_VIA is not set
 # CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -562,10 +595,8 @@
 # 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
@@ -645,14 +676,17 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -760,10 +794,6 @@
 # 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
@@ -787,6 +817,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -795,11 +826,6 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -818,6 +844,7 @@
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
@@ -834,6 +861,7 @@
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -863,6 +891,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -875,8 +909,8 @@
 # Miscellaneous USB options
 #
 # CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -886,9 +920,11 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
@@ -923,7 +959,6 @@
 # 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
@@ -945,7 +980,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -960,6 +995,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -982,6 +1018,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -991,6 +1028,7 @@
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 
 #
 # USB DSL modem support
@@ -1047,6 +1085,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1105,7 +1151,7 @@
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1159,6 +1205,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1171,10 +1225,10 @@
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
 
@@ -1187,14 +1241,59 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=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_CAMELLIA=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
 
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 553734a..2abbd68 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc2
-# Tue Jul 25 23:13:04 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:42 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -70,10 +70,14 @@
 # CONFIG_VICTOR_MPC30X is not set
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -106,6 +110,7 @@
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_VR41XX=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
@@ -119,8 +124,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -135,6 +140,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -147,6 +153,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -165,16 +172,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -182,12 +193,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -205,6 +216,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -257,6 +269,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -270,7 +290,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -288,10 +311,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -321,7 +347,6 @@
 # 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
 
@@ -371,6 +396,7 @@
 # Plug and Play support
 #
 # CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -387,9 +413,14 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -419,6 +450,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Old CD-ROM drivers (not SCSI, not IDE)
@@ -472,6 +509,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -575,6 +614,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -641,10 +681,6 @@
 # CONFIG_R3964 is not set
 
 #
-# Ftape, the floppy tape device driver
-#
-
-#
 # PCMCIA character devices
 #
 # CONFIG_SYNCLINK_CS is not set
@@ -657,7 +693,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -682,14 +717,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -708,6 +738,7 @@
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -715,6 +746,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -775,6 +812,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -783,11 +828,13 @@
 CONFIG_EXT2_FS_SECURITY=y
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -798,6 +845,7 @@
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -817,11 +865,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -875,6 +925,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -884,11 +942,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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 ide0=0x170,0x376,49 mem=16M"
 
@@ -901,7 +961,44 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=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_CAMELLIA=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -910,8 +1007,13 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
index d3dfb70..44b6b7c 100644
--- a/arch/mips/configs/wrppmc_defconfig
+++ b/arch/mips/configs/wrppmc_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:21 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:42 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,10 +64,14 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -124,8 +128,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -143,6 +147,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -155,6 +160,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -173,16 +179,22 @@
 CONFIG_LOCALVERSION_AUTO=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_HOTPLUG=y
@@ -190,12 +202,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 # CONFIG_EPOLL is not set
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -213,6 +225,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -258,6 +271,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -271,6 +292,8 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -294,10 +317,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -327,7 +353,6 @@
 # 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
 
@@ -375,6 +400,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -390,11 +416,18 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -404,6 +437,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -454,6 +493,8 @@
 # CONFIG_CICADA_PHY is not set
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -490,7 +531,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -509,14 +550,18 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_QLA3XXX=m
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -602,10 +647,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -613,7 +654,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -629,6 +669,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -637,17 +678,14 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -659,6 +697,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -728,14 +767,24 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS 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_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -746,6 +795,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -765,11 +815,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -806,7 +858,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -824,6 +875,14 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -833,11 +892,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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,115200n8"
 
@@ -850,7 +911,44 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=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_CAMELLIA=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -859,8 +957,13 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=y
 CONFIG_CRC16=y
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index b9f74d6..f24e1c6 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:21 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:42 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 CONFIG_PMC_YOSEMITE=y
@@ -65,10 +65,14 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 # CONFIG_HYPERTRANSPORT is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_DMA_COHERENT=y
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
@@ -102,6 +106,7 @@
 CONFIG_CPU_RM9000=y
 # CONFIG_CPU_SB1 is not set
 CONFIG_SYS_HAS_CPU_RM9000=y
+CONFIG_WEAK_ORDERING=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
@@ -118,8 +123,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -136,6 +141,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_SMP=y
 CONFIG_SYS_SUPPORTS_SMP=y
 CONFIG_NR_CPUS=2
@@ -170,15 +176,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -187,12 +198,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -210,6 +221,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -252,6 +264,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -281,13 +301,15 @@
 # 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_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -298,6 +320,8 @@
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETWORK_SECMARK=y
 # CONFIG_NETFILTER is not set
@@ -336,6 +360,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -356,6 +381,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -374,6 +400,11 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+CONFIG_SGI_IOC4=m
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -383,6 +414,12 @@
 #
 CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -433,6 +470,8 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -463,18 +502,22 @@
 # CONFIG_R8169 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
 CONFIG_TITAN_GE=y
+CONFIG_QLA3XXX=m
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+CONFIG_NETXEN_NIC=m
 
 #
 # Token Ring devices
@@ -559,10 +602,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -593,14 +632,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -612,6 +646,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -680,14 +715,23 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS 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
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -697,6 +741,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -716,8 +761,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -737,6 +784,7 @@
 #
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
@@ -744,7 +792,6 @@
 CONFIG_SUNRPC=y
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 
@@ -764,31 +811,38 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_HIGHMEM is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_KGDB is not set
+CONFIG_SYS_SUPPORTS_KGDB=y
 # CONFIG_RUNTIME_DEBUG is not set
 
 #
@@ -802,6 +856,10 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
@@ -811,9 +869,14 @@
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -825,6 +888,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -834,6 +898,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=m
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=m
 CONFIG_CRC32=m
@@ -841,3 +906,5 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile
index ed181fd..8b790c2 100644
--- a/arch/mips/dec/Makefile
+++ b/arch/mips/dec/Makefile
@@ -6,6 +6,7 @@
 		   kn02-irq.o kn02xa-berr.o reset.o setup.o time.o
 
 obj-$(CONFIG_PROM_CONSOLE)	+= promcon.o
+obj-$(CONFIG_TC)		+= tc.o
 obj-$(CONFIG_CPU_HAS_WB)	+= wbflush.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index b251ef8..00cecdc 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -264,9 +264,6 @@
 		 srlv	t3,t1,t2
 
 handle_it:
-		LONG_L	s0, TI_REGS($28)
-		LONG_S	sp, TI_REGS($28)
-		PTR_LA	ra, ret_from_irq
 		j	dec_irq_dispatch
 		 nop
 
@@ -277,7 +274,6 @@
 #endif
 
 spurious:
-		PTR_LA	ra, _ret_from_irq
 		j	spurious_interrupt
 		 nop
 		END(plat_irq_dispatch)
diff --git a/arch/mips/dec/prom/identify.c b/arch/mips/dec/prom/identify.c
index 81d5e87..c4e3c1e 100644
--- a/arch/mips/dec/prom/identify.c
+++ b/arch/mips/dec/prom/identify.c
@@ -88,6 +88,7 @@
 {
 	dec_kn_slot_base = KN02_SLOT_BASE;
 	dec_kn_slot_size = KN02_SLOT_SIZE;
+	dec_tc_bus = 1;
 
 	dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN02_RTC);
 }
@@ -96,6 +97,7 @@
 {
 	dec_kn_slot_base = KN02XA_SLOT_BASE;
 	dec_kn_slot_size = IOASIC_SLOT_SIZE;
+	dec_tc_bus = 1;
 
 	ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
 	dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
@@ -105,6 +107,7 @@
 {
 	dec_kn_slot_base = KN03_SLOT_BASE;
 	dec_kn_slot_size = IOASIC_SLOT_SIZE;
+	dec_tc_bus = 1;
 
 	ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
 	dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 1058e2f..b8a5e75 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -53,6 +53,8 @@
 EXPORT_SYMBOL(dec_kn_slot_base);
 EXPORT_SYMBOL(dec_kn_slot_size);
 
+int dec_tc_bus;
+
 spinlock_t ioasic_ssr_lock;
 
 volatile u32 *ioasic_base;
diff --git a/arch/mips/dec/tc.c b/arch/mips/dec/tc.c
new file mode 100644
index 0000000..732027c
--- /dev/null
+++ b/arch/mips/dec/tc.c
@@ -0,0 +1,95 @@
+/*
+ *	TURBOchannel architecture calls.
+ *
+ *	Copyright (c) Harald Koerfgen, 1998
+ *	Copyright (c) 2001, 2003, 2005, 2006  Maciej W. Rozycki
+ *	Copyright (c) 2005  James Simmons
+ *
+ *	This file is subject to the terms and conditions of the GNU
+ *	General Public License.  See the file "COPYING" in the main
+ *	directory of this archive for more details.
+ */
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/tc.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/paccess.h>
+
+#include <asm/dec/interrupts.h>
+#include <asm/dec/prom.h>
+#include <asm/dec/system.h>
+
+/*
+ * Protected read byte from TURBOchannel slot space.
+ */
+int tc_preadb(u8 *valp, void __iomem *addr)
+{
+	return get_dbe(*valp, (u8 *)addr);
+}
+
+/*
+ * Get TURBOchannel bus information as specified by the spec, plus
+ * the slot space base address and the number of slots.
+ */
+int __init tc_bus_get_info(struct tc_bus *tbus)
+{
+	if (!dec_tc_bus)
+		return -ENXIO;
+
+	memcpy(&tbus->info, rex_gettcinfo(), sizeof(tbus->info));
+	tbus->slot_base = CPHYSADDR((long)rex_slot_address(0));
+
+	switch (mips_machtype) {
+	case MACH_DS5000_200:
+		tbus->num_tcslots = 7;
+		break;
+	case MACH_DS5000_2X0:
+	case MACH_DS5900:
+		tbus->ext_slot_base = 0x20000000;
+		tbus->ext_slot_size = 0x20000000;
+		/* fall through */
+	case MACH_DS5000_1XX:
+		tbus->num_tcslots = 3;
+		break;
+	case MACH_DS5000_XX:
+		tbus->num_tcslots = 2;
+	default:
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Get the IRQ for the specified slot.
+ */
+void __init tc_device_get_irq(struct tc_dev *tdev)
+{
+	switch (tdev->slot) {
+	case 0:
+		tdev->interrupt = dec_interrupt[DEC_IRQ_TC0];
+		break;
+	case 1:
+		tdev->interrupt = dec_interrupt[DEC_IRQ_TC1];
+		break;
+	case 2:
+		tdev->interrupt = dec_interrupt[DEC_IRQ_TC2];
+		break;
+	/*
+	 * Yuck! DS5000/200 onboard devices
+	 */
+	case 5:
+		tdev->interrupt = dec_interrupt[DEC_IRQ_TC5];
+		break;
+	case 6:
+		tdev->interrupt = dec_interrupt[DEC_IRQ_TC6];
+		break;
+	default:
+		tdev->interrupt = -1;
+		break;
+	}
+}
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index f9812d1..8cb8f59 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:10 2006
+# Linux kernel version: 2.6.20
+# Tue Feb 20 21:47:14 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
+CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -25,8 +26,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 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
@@ -42,6 +41,7 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,13 +64,18 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
 CONFIG_ARC=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN=y
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
@@ -123,8 +128,8 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_IP22_CPU_SCACHE=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
@@ -141,6 +146,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -153,6 +159,7 @@
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -171,16 +178,21 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -188,12 +200,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -211,6 +223,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -238,7 +251,6 @@
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -252,6 +264,14 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
 # Networking
 #
 CONFIG_NET=y
@@ -265,7 +285,10 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -286,10 +309,13 @@
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
 
 #
 # IP: Virtual Server Configuration
@@ -331,11 +357,17 @@
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=y
 CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -346,19 +378,43 @@
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
@@ -375,60 +431,45 @@
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_SECMARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CONNTRACK_NETLINK=m
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_PPTP=m
-CONFIG_IP_NF_H323=m
-CONFIG_IP_NF_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=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=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_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-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_NAT_SIP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_RAW=m
@@ -439,6 +480,7 @@
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
+CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_RT=m
@@ -448,6 +490,7 @@
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
@@ -484,7 +527,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -492,6 +534,7 @@
 # QoS and/or fair queueing
 #
 CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FIFO=y
 # CONFIG_NET_SCH_CLK_JIFFIES is not set
 CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
 # CONFIG_NET_SCH_CLK_CPU is not set
@@ -546,6 +589,7 @@
 CONFIG_IEEE80211_SOFTMAC=m
 # CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
 CONFIG_WIRELESS_EXT=y
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -556,7 +600,6 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -577,6 +620,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -592,6 +636,10 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -601,6 +649,8 @@
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -620,24 +670,30 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=m
 # CONFIG_SCSI_FC_ATTRS is not set
 CONFIG_SCSI_ISCSI_ATTRS=m
 CONFIG_SCSI_SAS_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
 #
 CONFIG_ISCSI_TCP=m
 CONFIG_SGIWD93_SCSI=y
-# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -679,6 +735,8 @@
 CONFIG_CICADA_PHY=m
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -730,6 +788,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -752,6 +811,7 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=m
 CONFIG_MOUSE_SERIAL=m
@@ -815,10 +875,6 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 CONFIG_RAW_DRIVER=m
 CONFIG_MAX_RAW_DEVS=256
 
@@ -826,7 +882,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -851,14 +906,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -887,6 +937,7 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_SGI_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -894,6 +945,12 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -954,6 +1011,14 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=m
@@ -963,6 +1028,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -974,6 +1040,7 @@
 CONFIG_XFS_SECURITY=y
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 CONFIG_MINIX_FS=m
 # CONFIG_ROMFS_FS is not set
@@ -987,6 +1054,7 @@
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -994,7 +1062,6 @@
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=m
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1013,17 +1080,20 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -1142,6 +1212,14 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1151,11 +1229,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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=""
 
@@ -1170,18 +1250,30 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
@@ -1193,6 +1285,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -1202,6 +1295,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=m
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC16=m
 CONFIG_CRC32=m
@@ -1213,3 +1307,5 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/emma2rh/common/irq.c b/arch/mips/emma2rh/common/irq.c
index c191b3e..d956047 100644
--- a/arch/mips/emma2rh/common/irq.c
+++ b/arch/mips/emma2rh/common/irq.c
@@ -27,7 +27,6 @@
 #include <linux/irq.h>
 #include <linux/types.h>
 
-#include <asm/i8259.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
 #include <asm/debug.h>
diff --git a/arch/mips/emma2rh/markeins/irq.c b/arch/mips/emma2rh/markeins/irq.c
index 3299b6d..e266300 100644
--- a/arch/mips/emma2rh/markeins/irq.c
+++ b/arch/mips/emma2rh/markeins/irq.c
@@ -29,7 +29,6 @@
 #include <linux/ptrace.h>
 #include <linux/delay.h>
 
-#include <asm/i8259.h>
 #include <asm/irq_cpu.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index bbbb8d7..8faf1b4 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -14,8 +14,6 @@
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
-obj-$(CONFIG_APM)		+= apm.o
-
 obj-$(CONFIG_CPU_R3000)		+= r2300_fpu.o r2300_switch.o
 obj-$(CONFIG_CPU_TX39XX)	+= r2300_fpu.o r2300_switch.o
 obj-$(CONFIG_CPU_TX49XX)	+= r4k_fpu.o r4k_switch.o
@@ -55,9 +53,9 @@
 obj-$(CONFIG_32BIT)		+= scall32-o32.o
 obj-$(CONFIG_64BIT)		+= scall64-64.o
 obj-$(CONFIG_BINFMT_IRIX)	+= binfmt_irix.o
-obj-$(CONFIG_MIPS32_COMPAT)	+= linux32.o signal32.o
+obj-$(CONFIG_MIPS32_COMPAT)	+= linux32.o ptrace32.o signal32.o
 obj-$(CONFIG_MIPS32_N32)	+= binfmt_elfn32.o scall64-n32.o signal_n32.o
-obj-$(CONFIG_MIPS32_O32)	+= binfmt_elfo32.o scall64-o32.o ptrace32.o
+obj-$(CONFIG_MIPS32_O32)	+= binfmt_elfo32.o scall64-o32.o
 
 obj-$(CONFIG_KGDB)		+= gdb-low.o gdb-stub.o
 obj-$(CONFIG_PROC_FS)		+= proc.o
diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c
deleted file mode 100644
index ba16d07..0000000
--- a/arch/mips/kernel/apm.c
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * bios-less APM driver for MIPS Linux
- *  Jamey Hicks <jamey@crl.dec.com>
- *  adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
- *
- * APM 1.2 Reference:
- *   Intel Corporation, Microsoft Corporation. Advanced Power Management
- *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
- *
- * [This document is available from Microsoft at:
- *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
- */
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
-#include <linux/apm_bios.h>
-#include <linux/capability.h>
-#include <linux/sched.h>
-#include <linux/pm.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/completion.h>
-
-#include <asm/apm.h> /* apm_power_info */
-#include <asm/system.h>
-
-/*
- * The apm_bios device is one of the misc char devices.
- * This is its minor number.
- */
-#define APM_MINOR_DEV	134
-
-/*
- * See Documentation/Config.help for the configuration options.
- *
- * Various options can be changed at boot time as follows:
- * (We allow underscores for compatibility with the modules code)
- *	apm=on/off			enable/disable APM
- */
-
-/*
- * Maximum number of events stored
- */
-#define APM_MAX_EVENTS		16
-
-struct apm_queue {
-	unsigned int		event_head;
-	unsigned int		event_tail;
-	apm_event_t		events[APM_MAX_EVENTS];
-};
-
-/*
- * The per-file APM data
- */
-struct apm_user {
-	struct list_head	list;
-
-	unsigned int		suser: 1;
-	unsigned int		writer: 1;
-	unsigned int		reader: 1;
-
-	int			suspend_result;
-	unsigned int		suspend_state;
-#define SUSPEND_NONE	0		/* no suspend pending */
-#define SUSPEND_PENDING	1		/* suspend pending read */
-#define SUSPEND_READ	2		/* suspend read, pending ack */
-#define SUSPEND_ACKED	3		/* suspend acked */
-#define SUSPEND_DONE	4		/* suspend completed */
-
-	struct apm_queue	queue;
-};
-
-/*
- * Local variables
- */
-static int suspends_pending;
-static int apm_disabled;
-static int mips_apm_active;
-
-static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-
-/*
- * This is a list of everyone who has opened /dev/apm_bios
- */
-static DECLARE_RWSEM(user_list_lock);
-static LIST_HEAD(apm_user_list);
-
-/*
- * kapmd info.  kapmd provides us a process context to handle
- * "APM" events within - specifically necessary if we're going
- * to be suspending the system.
- */
-static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
-static DECLARE_COMPLETION(kapmd_exit);
-static DEFINE_SPINLOCK(kapmd_queue_lock);
-static struct apm_queue kapmd_queue;
-
-
-static const char driver_version[] = "1.13";	/* no spaces */
-
-
-
-/*
- * Compatibility cruft until the IPAQ people move over to the new
- * interface.
- */
-static void __apm_get_power_status(struct apm_power_info *info)
-{
-}
-
-/*
- * This allows machines to provide their own "apm get power status" function.
- */
-void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
-EXPORT_SYMBOL(apm_get_power_status);
-
-
-/*
- * APM event queue management.
- */
-static inline int queue_empty(struct apm_queue *q)
-{
-	return q->event_head == q->event_tail;
-}
-
-static inline apm_event_t queue_get_event(struct apm_queue *q)
-{
-	q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
-	return q->events[q->event_tail];
-}
-
-static void queue_add_event(struct apm_queue *q, apm_event_t event)
-{
-	q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
-	if (q->event_head == q->event_tail) {
-		static int notified;
-
-		if (notified++ == 0)
-		    printk(KERN_ERR "apm: an event queue overflowed\n");
-		q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
-	}
-	q->events[q->event_head] = event;
-}
-
-static void queue_event_one_user(struct apm_user *as, apm_event_t event)
-{
-	if (as->suser && as->writer) {
-		switch (event) {
-		case APM_SYS_SUSPEND:
-		case APM_USER_SUSPEND:
-			/*
-			 * If this user already has a suspend pending,
-			 * don't queue another one.
-			 */
-			if (as->suspend_state != SUSPEND_NONE)
-				return;
-
-			as->suspend_state = SUSPEND_PENDING;
-			suspends_pending++;
-			break;
-		}
-	}
-	queue_add_event(&as->queue, event);
-}
-
-static void queue_event(apm_event_t event, struct apm_user *sender)
-{
-	struct apm_user *as;
-
-	down_read(&user_list_lock);
-	list_for_each_entry(as, &apm_user_list, list) {
-		if (as != sender && as->reader)
-			queue_event_one_user(as, event);
-	}
-	up_read(&user_list_lock);
-	wake_up_interruptible(&apm_waitqueue);
-}
-
-static void apm_suspend(void)
-{
-	struct apm_user *as;
-	int err = pm_suspend(PM_SUSPEND_MEM);
-
-	/*
-	 * Anyone on the APM queues will think we're still suspended.
-	 * Send a message so everyone knows we're now awake again.
-	 */
-	queue_event(APM_NORMAL_RESUME, NULL);
-
-	/*
-	 * Finally, wake up anyone who is sleeping on the suspend.
-	 */
-	down_read(&user_list_lock);
-	list_for_each_entry(as, &apm_user_list, list) {
-		as->suspend_result = err;
-		as->suspend_state = SUSPEND_DONE;
-	}
-	up_read(&user_list_lock);
-
-	wake_up(&apm_suspend_waitqueue);
-}
-
-static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
-{
-	struct apm_user *as = fp->private_data;
-	apm_event_t event;
-	int i = count, ret = 0;
-
-	if (count < sizeof(apm_event_t))
-		return -EINVAL;
-
-	if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
-		return -EAGAIN;
-
-	wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
-
-	while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
-		event = queue_get_event(&as->queue);
-
-		ret = -EFAULT;
-		if (copy_to_user(buf, &event, sizeof(event)))
-			break;
-
-		if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
-			as->suspend_state = SUSPEND_READ;
-
-		buf += sizeof(event);
-		i -= sizeof(event);
-	}
-
-	if (i < count)
-		ret = count - i;
-
-	return ret;
-}
-
-static unsigned int apm_poll(struct file *fp, poll_table * wait)
-{
-	struct apm_user *as = fp->private_data;
-
-	poll_wait(fp, &apm_waitqueue, wait);
-	return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
-}
-
-/*
- * apm_ioctl - handle APM ioctl
- *
- * APM_IOC_SUSPEND
- *   This IOCTL is overloaded, and performs two functions.  It is used to:
- *     - initiate a suspend
- *     - acknowledge a suspend read from /dev/apm_bios.
- *   Only when everyone who has opened /dev/apm_bios with write permission
- *   has acknowledge does the actual suspend happen.
- */
-static int
-apm_ioctl(struct inode * inode, struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	struct apm_user *as = filp->private_data;
-	unsigned long flags;
-	int err = -EINVAL;
-
-	if (!as->suser || !as->writer)
-		return -EPERM;
-
-	switch (cmd) {
-	case APM_IOC_SUSPEND:
-		as->suspend_result = -EINTR;
-
-		if (as->suspend_state == SUSPEND_READ) {
-			/*
-			 * If we read a suspend command from /dev/apm_bios,
-			 * then the corresponding APM_IOC_SUSPEND ioctl is
-			 * interpreted as an acknowledge.
-			 */
-			as->suspend_state = SUSPEND_ACKED;
-			suspends_pending--;
-		} else {
-			/*
-			 * Otherwise it is a request to suspend the system.
-			 * Queue an event for all readers, and expect an
-			 * acknowledge from all writers who haven't already
-			 * acknowledged.
-			 */
-			queue_event(APM_USER_SUSPEND, as);
-		}
-
-		/*
-		 * If there are no further acknowledges required, suspend
-		 * the system.
-		 */
-		if (suspends_pending == 0)
-			apm_suspend();
-
-		/*
-		 * Wait for the suspend/resume to complete.  If there are
-		 * pending acknowledges, we wait here for them.
-		 *
-		 * Note that we need to ensure that the PM subsystem does
-		 * not kick us out of the wait when it suspends the threads.
-		 */
-		flags = current->flags;
-		current->flags |= PF_NOFREEZE;
-
-		/*
-		 * Note: do not allow a thread which is acking the suspend
-		 * to escape until the resume is complete.
-		 */
-		if (as->suspend_state == SUSPEND_ACKED)
-			wait_event(apm_suspend_waitqueue,
-					 as->suspend_state == SUSPEND_DONE);
-		else
-			wait_event_interruptible(apm_suspend_waitqueue,
-					 as->suspend_state == SUSPEND_DONE);
-
-		current->flags = flags;
-		err = as->suspend_result;
-		as->suspend_state = SUSPEND_NONE;
-		break;
-	}
-
-	return err;
-}
-
-static int apm_release(struct inode * inode, struct file * filp)
-{
-	struct apm_user *as = filp->private_data;
-	filp->private_data = NULL;
-
-	down_write(&user_list_lock);
-	list_del(&as->list);
-	up_write(&user_list_lock);
-
-	/*
-	 * We are now unhooked from the chain.  As far as new
-	 * events are concerned, we no longer exist.  However, we
-	 * need to balance suspends_pending, which means the
-	 * possibility of sleeping.
-	 */
-	if (as->suspend_state != SUSPEND_NONE) {
-		suspends_pending -= 1;
-		if (suspends_pending == 0)
-			apm_suspend();
-	}
-
-	kfree(as);
-	return 0;
-}
-
-static int apm_open(struct inode * inode, struct file * filp)
-{
-	struct apm_user *as;
-
-	as = kzalloc(sizeof(*as), GFP_KERNEL);
-	if (as) {
-		/*
-		 * XXX - this is a tiny bit broken, when we consider BSD
-		 * process accounting. If the device is opened by root, we
-		 * instantly flag that we used superuser privs. Who knows,
-		 * we might close the device immediately without doing a
-		 * privileged operation -- cevans
-		 */
-		as->suser = capable(CAP_SYS_ADMIN);
-		as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
-		as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
-
-		down_write(&user_list_lock);
-		list_add(&as->list, &apm_user_list);
-		up_write(&user_list_lock);
-
-		filp->private_data = as;
-	}
-
-	return as ? 0 : -ENOMEM;
-}
-
-static struct file_operations apm_bios_fops = {
-	.owner		= THIS_MODULE,
-	.read		= apm_read,
-	.poll		= apm_poll,
-	.ioctl		= apm_ioctl,
-	.open		= apm_open,
-	.release	= apm_release,
-};
-
-static struct miscdevice apm_device = {
-	.minor		= APM_MINOR_DEV,
-	.name		= "apm_bios",
-	.fops		= &apm_bios_fops
-};
-
-
-#ifdef CONFIG_PROC_FS
-/*
- * Arguments, with symbols from linux/apm_bios.h.
- *
- *   0) Linux driver version (this will change if format changes)
- *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
- *   2) APM flags from APM Installation Check (0x00):
- *	bit 0: APM_16_BIT_SUPPORT
- *	bit 1: APM_32_BIT_SUPPORT
- *	bit 2: APM_IDLE_SLOWS_CLOCK
- *	bit 3: APM_BIOS_DISABLED
- *	bit 4: APM_BIOS_DISENGAGED
- *   3) AC line status
- *	0x00: Off-line
- *	0x01: On-line
- *	0x02: On backup power (BIOS >= 1.1 only)
- *	0xff: Unknown
- *   4) Battery status
- *	0x00: High
- *	0x01: Low
- *	0x02: Critical
- *	0x03: Charging
- *	0x04: Selected battery not present (BIOS >= 1.2 only)
- *	0xff: Unknown
- *   5) Battery flag
- *	bit 0: High
- *	bit 1: Low
- *	bit 2: Critical
- *	bit 3: Charging
- *	bit 7: No system battery
- *	0xff: Unknown
- *   6) Remaining battery life (percentage of charge):
- *	0-100: valid
- *	-1: Unknown
- *   7) Remaining battery life (time units):
- *	Number of remaining minutes or seconds
- *	-1: Unknown
- *   8) min = minutes; sec = seconds
- */
-static int apm_get_info(char *buf, char **start, off_t fpos, int length)
-{
-	struct apm_power_info info;
-	char *units;
-	int ret;
-
-	info.ac_line_status = 0xff;
-	info.battery_status = 0xff;
-	info.battery_flag   = 0xff;
-	info.battery_life   = -1;
-	info.time	    = -1;
-	info.units	    = -1;
-
-	if (apm_get_power_status)
-		apm_get_power_status(&info);
-
-	switch (info.units) {
-	default:	units = "?";	break;
-	case 0: 	units = "min";	break;
-	case 1: 	units = "sec";	break;
-	}
-
-	ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
-		     driver_version, APM_32_BIT_SUPPORT,
-		     info.ac_line_status, info.battery_status,
-		     info.battery_flag, info.battery_life,
-		     info.time, units);
-
- 	return ret;
-}
-#endif
-
-static int kapmd(void *arg)
-{
-	daemonize("kapmd");
-	current->flags |= PF_NOFREEZE;
-
-	do {
-		apm_event_t event;
-
-		wait_event_interruptible(kapmd_wait,
-				!queue_empty(&kapmd_queue) || !mips_apm_active);
-
-		if (!mips_apm_active)
-			break;
-
-		spin_lock_irq(&kapmd_queue_lock);
-		event = 0;
-		if (!queue_empty(&kapmd_queue))
-			event = queue_get_event(&kapmd_queue);
-		spin_unlock_irq(&kapmd_queue_lock);
-
-		switch (event) {
-		case 0:
-			break;
-
-		case APM_LOW_BATTERY:
-		case APM_POWER_STATUS_CHANGE:
-			queue_event(event, NULL);
-			break;
-
-		case APM_USER_SUSPEND:
-		case APM_SYS_SUSPEND:
-			queue_event(event, NULL);
-			if (suspends_pending == 0)
-				apm_suspend();
-			break;
-
-		case APM_CRITICAL_SUSPEND:
-			apm_suspend();
-			break;
-		}
-	} while (1);
-
-	complete_and_exit(&kapmd_exit, 0);
-}
-
-static int __init apm_init(void)
-{
-	int ret;
-
-	if (apm_disabled) {
-		printk(KERN_NOTICE "apm: disabled on user request.\n");
-		return -ENODEV;
-	}
-
-	mips_apm_active = 1;
-
-	ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
-	if (ret < 0) {
-		mips_apm_active = 0;
-		return ret;
-	}
-
-#ifdef CONFIG_PROC_FS
-	create_proc_info_entry("apm", 0, NULL, apm_get_info);
-#endif
-
-	ret = misc_register(&apm_device);
-	if (ret != 0) {
-		remove_proc_entry("apm", NULL);
-
-		mips_apm_active = 0;
-		wake_up(&kapmd_wait);
-		wait_for_completion(&kapmd_exit);
-	}
-
-	return ret;
-}
-
-static void __exit apm_exit(void)
-{
-	misc_deregister(&apm_device);
-	remove_proc_entry("apm", NULL);
-
-	mips_apm_active = 0;
-	wake_up(&kapmd_wait);
-	wait_for_completion(&kapmd_exit);
-}
-
-module_init(apm_init);
-module_exit(apm_exit);
-
-MODULE_AUTHOR("Stephen Rothwell");
-MODULE_DESCRIPTION("Advanced Power Management");
-MODULE_LICENSE("GPL");
-
-#ifndef MODULE
-static int __init apm_setup(char *str)
-{
-	while ((str != NULL) && (*str != '\0')) {
-		if (strncmp(str, "off", 3) == 0)
-			apm_disabled = 1;
-		if (strncmp(str, "on", 2) == 0)
-			apm_disabled = 0;
-		str = strchr(str, ',');
-		if (str != NULL)
-			str += strspn(str, ", \t");
-	}
-	return 1;
-}
-
-__setup("apm=", apm_setup);
-#endif
-
-/**
- * apm_queue_event - queue an APM event for kapmd
- * @event: APM event
- *
- * Queue an APM event for kapmd to process and ultimately take the
- * appropriate action.  Only a subset of events are handled:
- *   %APM_LOW_BATTERY
- *   %APM_POWER_STATUS_CHANGE
- *   %APM_USER_SUSPEND
- *   %APM_SYS_SUSPEND
- *   %APM_CRITICAL_SUSPEND
- */
-void apm_queue_event(apm_event_t event)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&kapmd_queue_lock, flags);
-	queue_add_event(&kapmd_queue, event);
-	spin_unlock_irqrestore(&kapmd_queue_lock, flags);
-
-	wake_up_interruptible(&kapmd_wait);
-}
-EXPORT_SYMBOL(apm_queue_event);
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index ea7df4b..222de46 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -64,6 +64,9 @@
 	offset("#define PT_R31    ", struct pt_regs, regs[31]);
 	offset("#define PT_LO     ", struct pt_regs, lo);
 	offset("#define PT_HI     ", struct pt_regs, hi);
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+	offset("#define PT_ACX    ", struct pt_regs, acx);
+#endif
 	offset("#define PT_EPC    ", struct pt_regs, cp0_epc);
 	offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
 	offset("#define PT_STATUS ", struct pt_regs, cp0_status);
@@ -246,10 +249,10 @@
 	text("/* Linux sigcontext offsets. */");
 	offset("#define SC_REGS       ", struct sigcontext, sc_regs);
 	offset("#define SC_FPREGS     ", struct sigcontext, sc_fpregs);
+	offset("#define SC_ACX        ", struct sigcontext, sc_acx);
 	offset("#define SC_MDHI       ", struct sigcontext, sc_mdhi);
 	offset("#define SC_MDLO       ", struct sigcontext, sc_mdlo);
 	offset("#define SC_PC         ", struct sigcontext, sc_pc);
-	offset("#define SC_STATUS     ", struct sigcontext, sc_status);
 	offset("#define SC_FPC_CSR    ", struct sigcontext, sc_fpc_csr);
 	offset("#define SC_FPC_EIR    ", struct sigcontext, sc_fpc_eir);
 	offset("#define SC_HI1        ", struct sigcontext, sc_hi1);
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index f59ef27..ab755ea 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -16,6 +16,7 @@
 #include <linux/ptrace.h>
 #include <linux/stddef.h>
 
+#include <asm/bugs.h>
 #include <asm/cpu.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
@@ -97,7 +98,7 @@
 
 static int __initdata nowait = 0;
 
-int __init wait_disable(char *s)
+static int __init wait_disable(char *s)
 {
 	nowait = 1;
 
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index f10b6a1..0b78fcb 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -21,24 +21,21 @@
 #endif
 
 #ifndef CONFIG_PREEMPT
-	.macro	preempt_stop
-	local_irq_disable
-	.endm
 #define resume_kernel	restore_all
+#else
+#define __ret_from_irq	ret_from_exception
 #endif
 
 	.text
 	.align	5
+#ifndef CONFIG_PREEMPT
+FEXPORT(ret_from_exception)
+	local_irq_disable			# preempt stop
+	b	__ret_from_irq
+#endif
 FEXPORT(ret_from_irq)
 	LONG_S	s0, TI_REGS($28)
-#ifdef CONFIG_PREEMPT
-FEXPORT(ret_from_exception)
-#else
-	b	_ret_from_irq
-FEXPORT(ret_from_exception)
-	preempt_stop
-#endif
-FEXPORT(_ret_from_irq)
+FEXPORT(__ret_from_irq)
 	LONG_L	t0, PT_STATUS(sp)		# returning to kernel mode?
 	andi	t0, t0, KU_USER
 	beqz	t0, resume_kernel
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index b33ba6c..9c79703 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -28,7 +28,7 @@
  * moves to arch independent land
  */
 
-static int i8259A_auto_eoi;
+static int i8259A_auto_eoi = -1;
 DEFINE_SPINLOCK(i8259A_lock);
 /* some platforms call this... */
 void mask_and_ack_8259A(unsigned int);
@@ -216,7 +216,8 @@
 
 static int i8259A_resume(struct sys_device *dev)
 {
-	init_8259A(i8259A_auto_eoi);
+	if (i8259A_auto_eoi >= 0)
+		init_8259A(i8259A_auto_eoi);
 	return 0;
 }
 
@@ -226,8 +227,10 @@
 	 * the kernel initialization code can get it
 	 * out of.
 	 */
-	outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */
-	outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-1 */
+	if (i8259A_auto_eoi >= 0) {
+		outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */
+		outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-1 */
+	}
 	return 0;
 }
 
@@ -252,7 +255,7 @@
 
 device_initcall(i8259A_init_sysfs);
 
-void __init init_8259A(int auto_eoi)
+void init_8259A(int auto_eoi)
 {
 	unsigned long flags;
 
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 0b8ce59..fc4dd6c 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -39,6 +39,7 @@
 #include <net/sock.h>
 #include <net/scm.h>
 
+#include <asm/compat-signal.h>
 #include <asm/ipc.h>
 #include <asm/sim.h>
 #include <asm/uaccess.h>
@@ -193,50 +194,6 @@
 	return ret;
 }
 
-struct sysinfo32 {
-	s32 uptime;
-	u32 loads[3];
-	u32 totalram;
-	u32 freeram;
-	u32 sharedram;
-	u32 bufferram;
-	u32 totalswap;
-	u32 freeswap;
-	u16 procs;
-	u32 totalhigh;
-	u32 freehigh;
-	u32 mem_unit;
-	char _f[8];
-};
-
-asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info)
-{
-	struct sysinfo s;
-	int ret, err;
-	mm_segment_t old_fs = get_fs ();
-
-	set_fs (KERNEL_DS);
-	ret = sys_sysinfo((struct sysinfo __user *)&s);
-	set_fs (old_fs);
-	err = put_user (s.uptime, &info->uptime);
-	err |= __put_user (s.loads[0], &info->loads[0]);
-	err |= __put_user (s.loads[1], &info->loads[1]);
-	err |= __put_user (s.loads[2], &info->loads[2]);
-	err |= __put_user (s.totalram, &info->totalram);
-	err |= __put_user (s.freeram, &info->freeram);
-	err |= __put_user (s.sharedram, &info->sharedram);
-	err |= __put_user (s.bufferram, &info->bufferram);
-	err |= __put_user (s.totalswap, &info->totalswap);
-	err |= __put_user (s.freeswap, &info->freeswap);
-	err |= __put_user (s.procs, &info->procs);
-	err |= __put_user (s.totalhigh, &info->totalhigh);
-	err |= __put_user (s.freehigh, &info->freehigh);
-	err |= __put_user (s.mem_unit, &info->mem_unit);
-	if (err)
-		return -EFAULT;
-	return ret;
-}
-
 #define RLIM_INFINITY32	0x7fffffff
 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
 
@@ -780,3 +737,49 @@
 	return do_fork(clone_flags, newsp, &regs, 0,
 	               parent_tidptr, child_tidptr);
 }
+
+/*
+ * Implement the event wait interface for the eventpoll file. It is the kernel
+ * part of the user space epoll_pwait(2).
+ */
+asmlinkage long compat_sys_epoll_pwait(int epfd,
+	struct epoll_event __user *events, int maxevents, int timeout,
+	const compat_sigset_t __user *sigmask, size_t sigsetsize)
+{
+	int error;
+	sigset_t ksigmask, sigsaved;
+
+	/*
+	 * If the caller wants a certain signal mask to be set during the wait,
+	 * we apply it here.
+	 */
+	if (sigmask) {
+		if (sigsetsize != sizeof(sigset_t))
+			return -EINVAL;
+		if (!access_ok(VERIFY_READ, sigmask, sizeof(ksigmask)))
+			return -EFAULT;
+		if (__copy_conv_sigset_from_user(&ksigmask, sigmask))
+			return -EFAULT;
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	error = sys_epoll_wait(epfd, events, maxevents, timeout);
+
+	/*
+	 * If we changed the signal mask, we need to restore the original one.
+	 * In case we've got a signal while waiting, we do not restore the
+	 * signal mask yet, and we allow do_signal() to deliver the signal on
+	 * the way back to userspace, before the signal mask is restored.
+	 */
+	if (sigmask) {
+		if (error == -EINTR) {
+			memcpy(&current->saved_sigmask, &sigsaved,
+				sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		} else
+			sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+	}
+
+	return error;
+}
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
index e0ad754..8f42fa8 100644
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -13,8 +13,8 @@
 #include <asm/cacheflush.h>
 #include <asm/page.h>
 
-const extern unsigned char relocate_new_kernel[];
-const extern unsigned int relocate_new_kernel_size;
+extern const unsigned char relocate_new_kernel[];
+extern const unsigned int relocate_new_kernel_size;
 
 extern unsigned long kexec_start_address;
 extern unsigned long kexec_indirection_page;
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index a32f679..ba01800 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -3,9 +3,11 @@
  * Copyright (C) 2005 Mips Technologies, Inc
  */
 
+#include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/cpumask.h>
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/security.h>
 
@@ -453,3 +455,20 @@
 #endif /* CONFIG_MIPS_MT_SMTC */
 	/* FILL IN VSMP and AP/SP VERSIONS HERE */
 }
+
+struct class *mt_class;
+
+static int __init mt_init(void)
+{
+	struct class *mtc;
+
+	mtc = class_create(THIS_MODULE, "mt");
+	if (IS_ERR(mtc))
+		return PTR_ERR(mtc);
+
+	mt_class = mtc;
+
+	return 0;
+}
+
+subsys_initcall(mt_init);
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 04e5b38..a669089 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -26,7 +26,6 @@
 #include <linux/completion.h>
 #include <linux/kallsyms.h>
 
-#include <asm/abi.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
 #include <asm/dsp.h>
@@ -66,38 +65,6 @@
 	}
 }
 
-/*
- * Native o32 and N64 ABI without DSP ASE
- */
-struct mips_abi mips_abi = {
-	.do_signal	= do_signal,
-#ifdef CONFIG_TRAD_SIGNALS
-	.setup_frame	= setup_frame,
-#endif
-	.setup_rt_frame	= setup_rt_frame
-};
-
-#ifdef CONFIG_MIPS32_O32
-/*
- * o32 compatibility on 64-bit kernels, without DSP ASE
- */
-struct mips_abi mips_abi_32 = {
-	.do_signal	= do_signal32,
-	.setup_frame	= setup_frame_32,
-	.setup_rt_frame	= setup_rt_frame_32
-};
-#endif /* CONFIG_MIPS32_O32 */
-
-#ifdef CONFIG_MIPS32_N32
-/*
- * N32 on 64-bit kernels, without DSP ASE
- */
-struct mips_abi mips_abi_n32 = {
-	.do_signal	= do_signal,
-	.setup_rt_frame	= setup_rt_frame_n32
-};
-#endif /* CONFIG_MIPS32_N32 */
-
 asmlinkage void ret_from_fork(void);
 
 void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
@@ -246,7 +213,7 @@
 /*
  * Create a kernel thread
  */
-ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *))
+static ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *))
 {
 	do_exit(fn(arg));
 }
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 258d74f..201ae19 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -236,6 +236,11 @@
 		case MMLO:
 			tmp = regs->lo;
 			break;
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+		case ACX:
+			tmp = regs->acx;
+			break;
+#endif
 		case FPC_CSR:
 			tmp = child->thread.fpu.fcr31;
 			break;
@@ -362,6 +367,11 @@
 		case MMLO:
 			regs->lo = data;
 			break;
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+		case ACX:
+			regs->acx = data;
+			break;
+#endif
 		case FPC_CSR:
 			child->thread.fpu.fcr31 = data;
 			break;
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 8610f4a..d92c48e 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -17,6 +17,7 @@
  *
  */
 
+#include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -34,6 +35,7 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <asm/mipsmtregs.h>
+#include <asm/mips_mt.h>
 #include <asm/cacheflush.h>
 #include <asm/atomic.h>
 #include <asm/cpu.h>
@@ -476,7 +478,7 @@
 	return rtlx_write(minor, (void *)buffer, count, 1);
 }
 
-static struct file_operations rtlx_fops = {
+static const struct file_operations rtlx_fops = {
 	.owner =   THIS_MODULE,
 	.open =    file_open,
 	.release = file_release,
@@ -498,7 +500,8 @@
 
 static int rtlx_module_init(void)
 {
-	int i;
+	struct device *dev;
+	int i, err;
 
 	major = register_chrdev(0, module_name, &rtlx_fops);
 	if (major < 0) {
@@ -511,6 +514,13 @@
 		init_waitqueue_head(&channel_wqs[i].rt_queue);
 		init_waitqueue_head(&channel_wqs[i].lx_queue);
 		channel_wqs[i].in_open = 0;
+
+		dev = device_create(mt_class, NULL, MKDEV(major, i),
+		                    "%s%d", module_name, i);
+		if (IS_ERR(dev)) {
+			err = PTR_ERR(dev);
+			goto out_chrdev;
+		}
 	}
 
 	/* set up notifiers */
@@ -525,10 +535,21 @@
 	setup_irq(rtlx_irq_num, &rtlx_irq);
 
 	return 0;
+
+out_chrdev:
+	for (i = 0; i < RTLX_CHANNELS; i++)
+		device_destroy(mt_class, MKDEV(major, i));
+
+	return err;
 }
 
 static void __exit rtlx_module_exit(void)
 {
+	int i;
+
+	for (i = 0; i < RTLX_CHANNELS; i++)
+		device_destroy(mt_class, MKDEV(major, i));
+
 	unregister_chrdev(major, module_name);
 }
 
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index e569b84..10e9a18 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -470,4 +470,4 @@
 	PTR	sys_get_robust_list
 	PTR	sys_kexec_load			/* 5270 */
 	PTR	sys_getcpu
-	PTR	sys_epoll_pwait
+	PTR	compat_sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 39add23..2ceda46 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -217,7 +217,7 @@
 	PTR	sys32_gettimeofday
 	PTR	compat_sys_getrlimit		/* 6095 */
 	PTR	compat_sys_getrusage
-	PTR	sys32_sysinfo
+	PTR	compat_sys_sysinfo
 	PTR	compat_sys_times
 	PTR	sys32_ptrace
 	PTR	sys_getuid			/* 6100 */
@@ -396,4 +396,4 @@
 	PTR	compat_sys_get_robust_list
 	PTR	compat_sys_kexec_load
 	PTR	sys_getcpu
-	PTR	sys_epoll_pwait
+	PTR	compat_sys_epoll_pwait
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index c58b8e0..c5f590c 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -321,7 +321,7 @@
 	PTR	sys_ni_syscall			/* sys_vm86 */
 	PTR	compat_sys_wait4
 	PTR	sys_swapoff			/* 4115 */
-	PTR	sys32_sysinfo
+	PTR	compat_sys_sysinfo
 	PTR	sys32_ipc
 	PTR	sys_fsync
 	PTR	sys32_sigreturn
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index d2e01e7..11ab222 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -452,7 +452,7 @@
 	print_memory_map();
 
 	strlcpy(command_line, arcs_cmdline, sizeof(command_line));
-	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 
 	*cmdline_p = command_line;
 
@@ -543,7 +543,7 @@
 #endif
 }
 
-int __init fpu_disable(char *s)
+static int __init fpu_disable(char *s)
 {
 	int i;
 
@@ -555,7 +555,7 @@
 
 __setup("nofpu", fpu_disable);
 
-int __init dsp_disable(char *s)
+static int __init dsp_disable(char *s)
 {
 	cpu_data[0].ases &= ~MIPS_ASE_DSP;
 
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
index b1f09d5..fdbdbdc 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -8,169 +8,27 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 
+#ifndef __SIGNAL_COMMON_H
+#define __SIGNAL_COMMON_H
 
-static inline int
-setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
-{
-	int err = 0;
+/* #define DEBUG_SIG */
 
-	err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+#ifdef DEBUG_SIG
+#  define DEBUGP(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
+#else
+#  define DEBUGP(fmt, args...)
+#endif
 
-#define save_gp_reg(i) do {						\
-	err |= __put_user(regs->regs[i], &sc->sc_regs[i]);		\
-} while(0)
-	__put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
-	save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
-	save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
-	save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
-	save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
-	save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
-	save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
-	save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
-	save_gp_reg(31);
-#undef save_gp_reg
-
-	err |= __put_user(regs->hi, &sc->sc_mdhi);
-	err |= __put_user(regs->lo, &sc->sc_mdlo);
-	if (cpu_has_dsp) {
-		err |= __put_user(mfhi1(), &sc->sc_hi1);
-		err |= __put_user(mflo1(), &sc->sc_lo1);
-		err |= __put_user(mfhi2(), &sc->sc_hi2);
-		err |= __put_user(mflo2(), &sc->sc_lo2);
-		err |= __put_user(mfhi3(), &sc->sc_hi3);
-		err |= __put_user(mflo3(), &sc->sc_lo3);
-		err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
-	}
-
-	err |= __put_user(!!used_math(), &sc->sc_used_math);
-
-	if (!used_math())
-		goto out;
-
-	/*
-	 * Save FPU state to signal context.  Signal handler will "inherit"
-	 * current FPU state.
-	 */
-	preempt_disable();
-
-	if (!is_fpu_owner()) {
-		own_fpu();
-		restore_fp(current);
-	}
-	err |= save_fp_context(sc);
-
-	preempt_enable();
-
-out:
-	return err;
-}
-
-static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
-{
-	unsigned int used_math;
-	unsigned long treg;
-	int err = 0;
-
-	/* Always make any pending restarted system calls return -EINTR */
-	current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
-	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
-	err |= __get_user(regs->hi, &sc->sc_mdhi);
-	err |= __get_user(regs->lo, &sc->sc_mdlo);
-	if (cpu_has_dsp) {
-		err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
-		err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
-		err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
-		err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
-		err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
-		err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
-		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
-	}
-
-#define restore_gp_reg(i) do {						\
-	err |= __get_user(regs->regs[i], &sc->sc_regs[i]);		\
-} while(0)
-	restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
-	restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
-	restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
-	restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
-	restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
-	restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
-	restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
-	restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
-	restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
-	restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
-	restore_gp_reg(31);
-#undef restore_gp_reg
-
-	err |= __get_user(used_math, &sc->sc_used_math);
-	conditional_used_math(used_math);
-
-	preempt_disable();
-
-	if (used_math()) {
-		/* restore fpu context if we have used it before */
-		own_fpu();
-		err |= restore_fp_context(sc);
-	} else {
-		/* signal handler may have used FPU.  Give it up. */
-		lose_fpu();
-	}
-
-	preempt_enable();
-
-	return err;
-}
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 /*
  * Determine which stack to use..
  */
-static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
-{
-	unsigned long sp;
+extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+				 size_t frame_size);
+/*
+ * install trampoline code to get back from the sig handler
+ */
+extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall);
 
-	/* Default to using normal stack */
-	sp = regs->regs[29];
-
-	/*
-	 * FPU emulator may have it's own trampoline active just
-	 * above the user stack, 16-bytes before the next lowest
-	 * 16 byte boundary.  Try to avoid trashing it.
-	 */
-	sp -= 32;
-
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
-		sp = current->sas_ss_sp + current->sas_ss_size;
-
-	return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
-}
-
-static inline int install_sigtramp(unsigned int __user *tramp,
-	unsigned int syscall)
-{
-	int err;
-
-	/*
-	 * Set up the return code ...
-	 *
-	 *         li      v0, __NR__foo_sigreturn
-	 *         syscall
-	 */
-
-	err = __put_user(0x24020000 + syscall, tramp + 0);
-	err |= __put_user(0x0000000c          , tramp + 1);
-	if (ICACHE_REFILLS_WORKAROUND_WAR) {
-		err |= __put_user(0, tramp + 2);
-		err |= __put_user(0, tramp + 3);
-		err |= __put_user(0, tramp + 4);
-		err |= __put_user(0, tramp + 5);
-		err |= __put_user(0, tramp + 6);
-		err |= __put_user(0, tramp + 7);
-	}
-	flush_cache_sigtramp((unsigned long) tramp);
-
-	return err;
-}
+#endif	/* __SIGNAL_COMMON_H */
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 9a44053..f091786 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -34,18 +34,199 @@
 
 #include "signal-common.h"
 
-#define DEBUG_SIG 0
+/*
+ * Horribly complicated - with the bloody RM9000 workarounds enabled
+ * the signal trampolines is moving to the end of the structure so we can
+ * increase the alignment without breaking software compatibility.
+ */
+#if ICACHE_REFILLS_WORKAROUND_WAR == 0
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+struct sigframe {
+	u32 sf_ass[4];		/* argument save space for o32 */
+	u32 sf_code[2];		/* signal trampoline */
+	struct sigcontext sf_sc;
+	sigset_t sf_mask;
+};
+
+struct rt_sigframe {
+	u32 rs_ass[4];		/* argument save space for o32 */
+	u32 rs_code[2];		/* signal trampoline */
+	struct siginfo rs_info;
+	struct ucontext rs_uc;
+};
+
+#else
+
+struct sigframe {
+	u32 sf_ass[4];			/* argument save space for o32 */
+	u32 sf_pad[2];
+	struct sigcontext sf_sc;	/* hw context */
+	sigset_t sf_mask;
+	u32 sf_code[8] ____cacheline_aligned;	/* signal trampoline */
+};
+
+struct rt_sigframe {
+	u32 rs_ass[4];			/* argument save space for o32 */
+	u32 rs_pad[2];
+	struct siginfo rs_info;
+	struct ucontext rs_uc;
+	u32 rs_code[8] ____cacheline_aligned;	/* signal trampoline */
+};
+
+#endif
+
+/*
+ * Helper routines
+ */
+int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+	int err = 0;
+	int i;
+
+	err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+
+	err |= __put_user(0, &sc->sc_regs[0]);
+	for (i = 1; i < 32; i++)
+		err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
+
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+	err |= __put_user(regs->acx, &sc->sc_acx);
+#endif
+	err |= __put_user(regs->hi, &sc->sc_mdhi);
+	err |= __put_user(regs->lo, &sc->sc_mdlo);
+	if (cpu_has_dsp) {
+		err |= __put_user(mfhi1(), &sc->sc_hi1);
+		err |= __put_user(mflo1(), &sc->sc_lo1);
+		err |= __put_user(mfhi2(), &sc->sc_hi2);
+		err |= __put_user(mflo2(), &sc->sc_lo2);
+		err |= __put_user(mfhi3(), &sc->sc_hi3);
+		err |= __put_user(mflo3(), &sc->sc_lo3);
+		err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+	}
+
+	err |= __put_user(!!used_math(), &sc->sc_used_math);
+
+	if (used_math()) {
+		/*
+		 * Save FPU state to signal context. Signal handler
+		 * will "inherit" current FPU state.
+		 */
+		preempt_disable();
+
+		if (!is_fpu_owner()) {
+			own_fpu();
+			restore_fp(current);
+		}
+		err |= save_fp_context(sc);
+
+		preempt_enable();
+	}
+	return err;
+}
+
+int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+	unsigned int used_math;
+	unsigned long treg;
+	int err = 0;
+	int i;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
+
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+	err |= __get_user(regs->acx, &sc->sc_acx);
+#endif
+	err |= __get_user(regs->hi, &sc->sc_mdhi);
+	err |= __get_user(regs->lo, &sc->sc_mdlo);
+	if (cpu_has_dsp) {
+		err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
+		err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
+		err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
+		err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
+		err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
+		err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
+		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+	}
+
+	for (i = 1; i < 32; i++)
+		err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
+
+	err |= __get_user(used_math, &sc->sc_used_math);
+	conditional_used_math(used_math);
+
+	preempt_disable();
+
+	if (used_math()) {
+		/* restore fpu context if we have used it before */
+		own_fpu();
+		err |= restore_fp_context(sc);
+	} else {
+		/* signal handler may have used FPU.  Give it up. */
+		lose_fpu();
+	}
+
+	preempt_enable();
+
+	return err;
+}
+
+void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+			  size_t frame_size)
+{
+	unsigned long sp;
+
+	/* Default to using normal stack */
+	sp = regs->regs[29];
+
+	/*
+	 * FPU emulator may have it's own trampoline active just
+	 * above the user stack, 16-bytes before the next lowest
+	 * 16 byte boundary.  Try to avoid trashing it.
+	 */
+	sp -= 32;
+
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
+}
+
+int install_sigtramp(unsigned int __user *tramp, unsigned int syscall)
+{
+	int err;
+
+	/*
+	 * Set up the return code ...
+	 *
+	 *         li      v0, __NR__foo_sigreturn
+	 *         syscall
+	 */
+
+	err = __put_user(0x24020000 + syscall, tramp + 0);
+	err |= __put_user(0x0000000c         , tramp + 1);
+	if (ICACHE_REFILLS_WORKAROUND_WAR) {
+		err |= __put_user(0, tramp + 2);
+		err |= __put_user(0, tramp + 3);
+		err |= __put_user(0, tramp + 4);
+		err |= __put_user(0, tramp + 5);
+		err |= __put_user(0, tramp + 6);
+		err |= __put_user(0, tramp + 7);
+	}
+	flush_cache_sigtramp((unsigned long) tramp);
+
+	return err;
+}
 
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 
 #ifdef CONFIG_TRAD_SIGNALS
-save_static_function(sys_sigsuspend);
-__attribute_used__ noinline static int
-_sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
+asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
 	sigset_t newset;
 	sigset_t __user *uset;
@@ -68,9 +249,7 @@
 }
 #endif
 
-save_static_function(sys_rt_sigsuspend);
-__attribute_used__ noinline static int
-_sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
 	sigset_t newset;
 	sigset_t __user *unewset;
@@ -148,45 +327,8 @@
 	return do_sigaltstack(uss, uoss, usp);
 }
 
-/*
- * Horribly complicated - with the bloody RM9000 workarounds enabled
- * the signal trampolines is moving to the end of the structure so we can
- * increase the alignment without breaking software compatibility.
- */
 #ifdef CONFIG_TRAD_SIGNALS
-struct sigframe {
-	u32 sf_ass[4];			/* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
-	u32 sf_pad[2];
-#else
-	u32 sf_code[2];			/* signal trampoline */
-#endif
-	struct sigcontext sf_sc;
-	sigset_t sf_mask;
-#if ICACHE_REFILLS_WORKAROUND_WAR
-	u32 sf_code[8] ____cacheline_aligned;	/* signal trampoline */
-#endif
-};
-#endif
-
-struct rt_sigframe {
-	u32 rs_ass[4];			/* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
-	u32 rs_pad[2];
-#else
-	u32 rs_code[2];			/* signal trampoline */
-#endif
-	struct siginfo rs_info;
-	struct ucontext rs_uc;
-#if ICACHE_REFILLS_WORKAROUND_WAR
-	u32 rs_code[8] ____cacheline_aligned;	/* signal trampoline */
-#endif
-};
-
-#ifdef CONFIG_TRAD_SIGNALS
-save_static_function(sys_sigreturn);
-__attribute_used__ noinline static void
-_sys_sigreturn(nabi_no_regargs struct pt_regs regs)
+asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
 	struct sigframe __user *frame;
 	sigset_t blocked;
@@ -221,9 +363,7 @@
 }
 #endif /* CONFIG_TRAD_SIGNALS */
 
-save_static_function(sys_rt_sigreturn);
-__attribute_used__ noinline static void
-_sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
 	struct rt_sigframe __user *frame;
 	sigset_t set;
@@ -265,7 +405,7 @@
 }
 
 #ifdef CONFIG_TRAD_SIGNALS
-int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
+static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
 	int signr, sigset_t *set)
 {
 	struct sigframe __user *frame;
@@ -275,7 +415,7 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 		goto give_sigsegv;
 
-	install_sigtramp(frame->sf_code, __NR_sigreturn);
+	err |= install_sigtramp(frame->sf_code, __NR_sigreturn);
 
 	err |= setup_sigcontext(regs, &frame->sf_sc);
 	err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
@@ -299,11 +439,9 @@
 	regs->regs[31] = (unsigned long) frame->sf_code;
 	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
 
-#if DEBUG_SIG
-	printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 	       current->comm, current->pid,
-	       frame, regs->cp0_epc, frame->regs[31]);
-#endif
+	       frame, regs->cp0_epc, regs->regs[31]);
 	return 0;
 
 give_sigsegv:
@@ -312,7 +450,7 @@
 }
 #endif
 
-int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
+static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
 	int signr, sigset_t *set, siginfo_t *info)
 {
 	struct rt_sigframe __user *frame;
@@ -322,7 +460,7 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 		goto give_sigsegv;
 
-	install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
+	err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
 
 	/* Create siginfo.  */
 	err |= copy_siginfo_to_user(&frame->rs_info, info);
@@ -359,11 +497,10 @@
 	regs->regs[31] = (unsigned long) frame->rs_code;
 	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
 
-#if DEBUG_SIG
-	printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
-#endif
+
 	return 0;
 
 give_sigsegv:
@@ -371,7 +508,15 @@
 	return -EFAULT;
 }
 
-static inline int handle_signal(unsigned long sig, siginfo_t *info,
+struct mips_abi mips_abi = {
+#ifdef CONFIG_TRAD_SIGNALS
+	.setup_frame	= setup_frame,
+#endif
+	.setup_rt_frame	= setup_rt_frame,
+	.restart	= __NR_restart_syscall
+};
+
+static int handle_signal(unsigned long sig, siginfo_t *info,
 	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
 {
 	int ret;
@@ -409,7 +554,7 @@
 	return ret;
 }
 
-void do_signal(struct pt_regs *regs)
+static void do_signal(struct pt_regs *regs)
 {
 	struct k_sigaction ka;
 	sigset_t *oldset;
@@ -459,7 +604,7 @@
 			regs->cp0_epc -= 8;
 		}
 		if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
-			regs->regs[2] = __NR_restart_syscall;
+			regs->regs[2] = current->thread.abi->restart;
 			regs->regs[7] = regs->regs[26];
 			regs->cp0_epc -= 4;
 		}
@@ -485,5 +630,5 @@
 {
 	/* deal with pending signal delivery */
 	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
-		current->thread.abi->do_signal(regs);
+		do_signal(regs);
 }
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index c86a5dd..19bbef0 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -8,6 +8,7 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <linux/cache.h>
+#include <linux/compat.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -24,6 +25,7 @@
 
 #include <asm/abi.h>
 #include <asm/asm.h>
+#include <asm/compat-signal.h>
 #include <linux/bitops.h>
 #include <asm/cacheflush.h>
 #include <asm/sim.h>
@@ -33,6 +35,8 @@
 #include <asm/fpu.h>
 #include <asm/war.h>
 
+#include "signal-common.h"
+
 #define SI_PAD_SIZE32   ((SI_MAX_SIZE/sizeof(int)) - 3)
 
 typedef struct compat_siginfo {
@@ -100,21 +104,10 @@
  */
 #define __NR_O32_sigreturn		4119
 #define __NR_O32_rt_sigreturn		4193
-#define __NR_O32_restart_syscall	4253
-
-#define DEBUG_SIG 0
-
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+#define __NR_O32_restart_syscall        4253
 
 /* 32-bit compatibility types */
 
-#define _NSIG_BPW32	32
-#define _NSIG_WORDS32	(_NSIG / _NSIG_BPW32)
-
-typedef struct {
-	unsigned int sig[_NSIG_WORDS32];
-} sigset_t32;
-
 typedef unsigned int __sighandler32_t;
 typedef void (*vfptr_t)(void);
 
@@ -136,9 +129,146 @@
 	s32                 uc_link;
 	stack32_t           uc_stack;
 	struct sigcontext32 uc_mcontext;
-	sigset_t32          uc_sigmask;   /* mask last for extensibility */
+	compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
 };
 
+/*
+ * Horribly complicated - with the bloody RM9000 workarounds enabled
+ * the signal trampolines is moving to the end of the structure so we can
+ * increase the alignment without breaking software compatibility.
+ */
+#if ICACHE_REFILLS_WORKAROUND_WAR == 0
+
+struct sigframe32 {
+	u32 sf_ass[4];		/* argument save space for o32 */
+	u32 sf_code[2];		/* signal trampoline */
+	struct sigcontext32 sf_sc;
+	compat_sigset_t sf_mask;
+};
+
+struct rt_sigframe32 {
+	u32 rs_ass[4];			/* argument save space for o32 */
+	u32 rs_code[2];			/* signal trampoline */
+	compat_siginfo_t rs_info;
+	struct ucontext32 rs_uc;
+};
+
+#else  /* ICACHE_REFILLS_WORKAROUND_WAR */
+
+struct sigframe32 {
+	u32 sf_ass[4];			/* argument save space for o32 */
+	u32 sf_pad[2];
+	struct sigcontext32 sf_sc;	/* hw context */
+	compat_sigset_t sf_mask;
+	u32 sf_code[8] ____cacheline_aligned;	/* signal trampoline */
+};
+
+struct rt_sigframe32 {
+	u32 rs_ass[4];			/* argument save space for o32 */
+	u32 rs_pad[2];
+	compat_siginfo_t rs_info;
+	struct ucontext32 rs_uc;
+	u32 rs_code[8] __attribute__((aligned(32)));	/* signal trampoline */
+};
+
+#endif	/* !ICACHE_REFILLS_WORKAROUND_WAR */
+
+/*
+ * sigcontext handlers
+ */
+static int setup_sigcontext32(struct pt_regs *regs,
+			      struct sigcontext32 __user *sc)
+{
+	int err = 0;
+	int i;
+
+	err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+
+	err |= __put_user(0, &sc->sc_regs[0]);
+	for (i = 1; i < 32; i++)
+		err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
+
+	err |= __put_user(regs->hi, &sc->sc_mdhi);
+	err |= __put_user(regs->lo, &sc->sc_mdlo);
+	if (cpu_has_dsp) {
+		err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+		err |= __put_user(mfhi1(), &sc->sc_hi1);
+		err |= __put_user(mflo1(), &sc->sc_lo1);
+		err |= __put_user(mfhi2(), &sc->sc_hi2);
+		err |= __put_user(mflo2(), &sc->sc_lo2);
+		err |= __put_user(mfhi3(), &sc->sc_hi3);
+		err |= __put_user(mflo3(), &sc->sc_lo3);
+	}
+
+	err |= __put_user(!!used_math(), &sc->sc_used_math);
+
+	if (used_math()) {
+		/*
+		 * Save FPU state to signal context.  Signal handler
+		 * will "inherit" current FPU state.
+		 */
+		preempt_disable();
+
+		if (!is_fpu_owner()) {
+			own_fpu();
+			restore_fp(current);
+		}
+		err |= save_fp_context32(sc);
+
+		preempt_enable();
+	}
+	return err;
+}
+
+static int restore_sigcontext32(struct pt_regs *regs,
+				struct sigcontext32 __user *sc)
+{
+	u32 used_math;
+	int err = 0;
+	s32 treg;
+	int i;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
+	err |= __get_user(regs->hi, &sc->sc_mdhi);
+	err |= __get_user(regs->lo, &sc->sc_mdlo);
+	if (cpu_has_dsp) {
+		err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
+		err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
+		err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
+		err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
+		err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
+		err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
+		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+	}
+
+	for (i = 1; i < 32; i++)
+		err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
+
+	err |= __get_user(used_math, &sc->sc_used_math);
+	conditional_used_math(used_math);
+
+	preempt_disable();
+
+	if (used_math()) {
+		/* restore fpu context if we have used it before */
+		own_fpu();
+		err |= restore_fp_context32(sc);
+	} else {
+		/* signal handler may have used FPU.  Give it up. */
+		lose_fpu();
+	}
+
+	preempt_enable();
+
+	return err;
+}
+
+/*
+ *
+ */
 extern void __put_sigset_unknown_nsig(void);
 extern void __get_sigset_unknown_nsig(void);
 
@@ -191,9 +321,7 @@
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 
-save_static_function(sys32_sigsuspend);
-__attribute_used__ noinline static int
-_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
+asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
 	compat_sigset_t __user *uset;
 	sigset_t newset;
@@ -215,9 +343,7 @@
 	return -ERESTARTNOHAND;
 }
 
-save_static_function(sys32_rt_sigsuspend);
-__attribute_used__ noinline static int
-_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
 	compat_sigset_t __user *uset;
 	sigset_t newset;
@@ -326,91 +452,6 @@
 	return ret;
 }
 
-static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 __user *sc)
-{
-	u32 used_math;
-	int err = 0;
-	s32 treg;
-
-	/* Always make any pending restarted system calls return -EINTR */
-	current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
-	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
-	err |= __get_user(regs->hi, &sc->sc_mdhi);
-	err |= __get_user(regs->lo, &sc->sc_mdlo);
-	if (cpu_has_dsp) {
-		err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
-		err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
-		err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
-		err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
-		err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
-		err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
-		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
-	}
-
-#define restore_gp_reg(i) do {						\
-	err |= __get_user(regs->regs[i], &sc->sc_regs[i]);		\
-} while(0)
-	restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
-	restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
-	restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
-	restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
-	restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
-	restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
-	restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
-	restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
-	restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
-	restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
-	restore_gp_reg(31);
-#undef restore_gp_reg
-
-	err |= __get_user(used_math, &sc->sc_used_math);
-	conditional_used_math(used_math);
-
-	preempt_disable();
-
-	if (used_math()) {
-		/* restore fpu context if we have used it before */
-		own_fpu();
-		err |= restore_fp_context32(sc);
-	} else {
-		/* signal handler may have used FPU.  Give it up. */
-		lose_fpu();
-	}
-
-	preempt_enable();
-
-	return err;
-}
-
-struct sigframe {
-	u32 sf_ass[4];			/* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
-	u32 sf_pad[2];
-#else
-	u32 sf_code[2];			/* signal trampoline */
-#endif
-	struct sigcontext32 sf_sc;
-	sigset_t sf_mask;
-#if ICACHE_REFILLS_WORKAROUND_WAR
-	u32 sf_code[8] ____cacheline_aligned;	/* signal trampoline */
-#endif
-};
-
-struct rt_sigframe32 {
-	u32 rs_ass[4];			/* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
-	u32 rs_pad[2];
-#else
-	u32 rs_code[2];			/* signal trampoline */
-#endif
-	compat_siginfo_t rs_info;
-	struct ucontext32 rs_uc;
-#if ICACHE_REFILLS_WORKAROUND_WAR
-	u32 rs_code[8] __attribute__((aligned(32)));	/* signal trampoline */
-#endif
-};
-
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
 	int err;
@@ -463,17 +504,15 @@
 	return err;
 }
 
-save_static_function(sys32_sigreturn);
-__attribute_used__ noinline static void
-_sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
+asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
-	struct sigframe __user *frame;
+	struct sigframe32 __user *frame;
 	sigset_t blocked;
 
-	frame = (struct sigframe __user *) regs.regs[29];
+	frame = (struct sigframe32 __user *) regs.regs[29];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
-	if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
+	if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
 		goto badframe;
 
 	sigdelsetmask(&blocked, ~_BLOCKABLE);
@@ -499,9 +538,7 @@
 	force_sig(SIGSEGV, current);
 }
 
-save_static_function(sys32_rt_sigreturn);
-__attribute_used__ noinline static void
-_sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
 	struct rt_sigframe32 __user *frame;
 	mm_segment_t old_fs;
@@ -512,7 +549,7 @@
 	frame = (struct rt_sigframe32 __user *) regs.regs[29];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
-	if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+	if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
@@ -554,111 +591,21 @@
 	force_sig(SIGSEGV, current);
 }
 
-static inline int setup_sigcontext32(struct pt_regs *regs,
-				     struct sigcontext32 __user *sc)
-{
-	int err = 0;
-
-	err |= __put_user(regs->cp0_epc, &sc->sc_pc);
-	err |= __put_user(regs->cp0_status, &sc->sc_status);
-
-#define save_gp_reg(i) {						\
-	err |= __put_user(regs->regs[i], &sc->sc_regs[i]);		\
-} while(0)
-	__put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
-	save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
-	save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
-	save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
-	save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
-	save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
-	save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
-	save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
-	save_gp_reg(31);
-#undef save_gp_reg
-
-	err |= __put_user(regs->hi, &sc->sc_mdhi);
-	err |= __put_user(regs->lo, &sc->sc_mdlo);
-	if (cpu_has_dsp) {
-		err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
-		err |= __put_user(mfhi1(), &sc->sc_hi1);
-		err |= __put_user(mflo1(), &sc->sc_lo1);
-		err |= __put_user(mfhi2(), &sc->sc_hi2);
-		err |= __put_user(mflo2(), &sc->sc_lo2);
-		err |= __put_user(mfhi3(), &sc->sc_hi3);
-		err |= __put_user(mflo3(), &sc->sc_lo3);
-	}
-
-	err |= __put_user(!!used_math(), &sc->sc_used_math);
-
-	if (!used_math())
-		goto out;
-
-	/*
-	 * Save FPU state to signal context.  Signal handler will "inherit"
-	 * current FPU state.
-	 */
-	preempt_disable();
-
-	if (!is_fpu_owner()) {
-		own_fpu();
-		restore_fp(current);
-	}
-	err |= save_fp_context32(sc);
-
-	preempt_enable();
-
-out:
-	return err;
-}
-
-/*
- * Determine which stack to use..
- */
-static inline void __user *get_sigframe(struct k_sigaction *ka,
-					struct pt_regs *regs,
-					size_t frame_size)
-{
-	unsigned long sp;
-
-	/* Default to using normal stack */
-	sp = regs->regs[29];
-
-	/*
-	 * FPU emulator may have it's own trampoline active just
-	 * above the user stack, 16-bytes before the next lowest
-	 * 16 byte boundary.  Try to avoid trashing it.
-	 */
-	sp -= 32;
-
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
-		sp = current->sas_ss_sp + current->sas_ss_size;
-
-	return (void __user *)((sp - frame_size) & ALMASK);
-}
-
-int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
+static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
 	int signr, sigset_t *set)
 {
-	struct sigframe __user *frame;
+	struct sigframe32 __user *frame;
 	int err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 		goto give_sigsegv;
 
-	/*
-	 * Set up the return code ...
-	 *
-	 *         li      v0, __NR_O32_sigreturn
-	 *         syscall
-	 */
-	err |= __put_user(0x24020000 + __NR_O32_sigreturn, frame->sf_code + 0);
-	err |= __put_user(0x0000000c                     , frame->sf_code + 1);
-	flush_cache_sigtramp((unsigned long) frame->sf_code);
+	err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
 
 	err |= setup_sigcontext32(regs, &frame->sf_sc);
-	err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
+	err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
+
 	if (err)
 		goto give_sigsegv;
 
@@ -679,11 +626,10 @@
 	regs->regs[31] = (unsigned long) frame->sf_code;
 	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
 
-#if DEBUG_SIG
-	printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 	       current->comm, current->pid,
-	       frame, regs->cp0_epc, frame->sf_code);
-#endif
+	       frame, regs->cp0_epc, regs->regs[31]);
+
 	return 0;
 
 give_sigsegv:
@@ -691,7 +637,7 @@
 	return -EFAULT;
 }
 
-int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
+static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
 	int signr, sigset_t *set, siginfo_t *info)
 {
 	struct rt_sigframe32 __user *frame;
@@ -702,17 +648,7 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 		goto give_sigsegv;
 
-	/* Set up to return from userspace.  If provided, use a stub already
-	   in userspace.  */
-	/*
-	 * Set up the return code ...
-	 *
-	 *         li      v0, __NR_O32_rt_sigreturn
-	 *         syscall
-	 */
-	err |= __put_user(0x24020000 + __NR_O32_rt_sigreturn, frame->rs_code + 0);
-	err |= __put_user(0x0000000c                      , frame->rs_code + 1);
-	flush_cache_sigtramp((unsigned long) frame->rs_code);
+	err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
 
 	/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
 	err |= copy_siginfo_to_user32(&frame->rs_info, info);
@@ -728,7 +664,7 @@
 	err |= __put_user(current->sas_ss_size,
 	                  &frame->rs_uc.uc_stack.ss_size);
 	err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
-	err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+	err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 
 	if (err)
 		goto give_sigsegv;
@@ -750,11 +686,10 @@
 	regs->regs[31] = (unsigned long) frame->rs_code;
 	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
 
-#if DEBUG_SIG
-	printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 	       current->comm, current->pid,
-	       frame, regs->cp0_epc, frame->rs_code);
-#endif
+	       frame, regs->cp0_epc, regs->regs[31]);
+
 	return 0;
 
 give_sigsegv:
@@ -762,110 +697,14 @@
 	return -EFAULT;
 }
 
-static inline int handle_signal(unsigned long sig, siginfo_t *info,
-	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
-{
-	int ret;
-
-	switch (regs->regs[0]) {
-	case ERESTART_RESTARTBLOCK:
-	case ERESTARTNOHAND:
-		regs->regs[2] = EINTR;
-		break;
-	case ERESTARTSYS:
-		if (!(ka->sa.sa_flags & SA_RESTART)) {
-			regs->regs[2] = EINTR;
-			break;
-		}
-	/* fallthrough */
-	case ERESTARTNOINTR:		/* Userland will reload $v0.  */
-		regs->regs[7] = regs->regs[26];
-		regs->cp0_epc -= 8;
-	}
-
-	regs->regs[0] = 0;		/* Don't deal with this again.  */
-
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
-	else
-		ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
-
-	spin_lock_irq(&current->sighand->siglock);
-	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-	if (!(ka->sa.sa_flags & SA_NODEFER))
-		sigaddset(&current->blocked,sig);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	return ret;
-}
-
-void do_signal32(struct pt_regs *regs)
-{
-	struct k_sigaction ka;
-	sigset_t *oldset;
-	siginfo_t info;
-	int signr;
-
-	/*
-	 * We want the common case to go fast, which is why we may in certain
-	 * cases get here from kernel mode. Just return without doing anything
-	 * if so.
-	 */
-	if (!user_mode(regs))
-		return;
-
-	if (test_thread_flag(TIF_RESTORE_SIGMASK))
-		oldset = &current->saved_sigmask;
-	else
-		oldset = &current->blocked;
-
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		/* Whee! Actually deliver the signal. */
-		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
-			/*
-			* A signal was successfully delivered; the saved
-			* sigmask will have been stored in the signal frame,
-			* and will be restored by sigreturn, so we can simply
-			* clear the TIF_RESTORE_SIGMASK flag.
-			*/
-			if (test_thread_flag(TIF_RESTORE_SIGMASK))
-				clear_thread_flag(TIF_RESTORE_SIGMASK);
-		}
-
-		return;
-	}
-
-	/*
-	 * Who's code doesn't conform to the restartable syscall convention
-	 * dies here!!!  The li instruction, a single machine instruction,
-	 * must directly be followed by the syscall instruction.
-	 */
-	if (regs->regs[0]) {
-		if (regs->regs[2] == ERESTARTNOHAND ||
-		    regs->regs[2] == ERESTARTSYS ||
-		    regs->regs[2] == ERESTARTNOINTR) {
-			regs->regs[7] = regs->regs[26];
-			regs->cp0_epc -= 8;
-		}
-		if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
-			regs->regs[2] = __NR_O32_restart_syscall;
-			regs->regs[7] = regs->regs[26];
-			regs->cp0_epc -= 4;
-		}
-		regs->regs[0] = 0;	/* Don't deal with this again.  */
-	}
-
-	/*
-	* If there's no signal to deliver, we just put the saved sigmask
-	* back
-	*/
-	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-		clear_thread_flag(TIF_RESTORE_SIGMASK);
-		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-	}
-}
+/*
+ * o32 compatibility on 64-bit kernels, without DSP ASE
+ */
+struct mips_abi mips_abi_32 = {
+	.setup_frame	= setup_frame_32,
+	.setup_rt_frame	= setup_rt_frame_32,
+	.restart	= __NR_O32_restart_syscall
+};
 
 asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
 				  struct sigaction32 __user *oact,
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index b28646b..ecf1f7e 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -29,8 +29,10 @@
 #include <linux/compat.h>
 #include <linux/bitops.h>
 
+#include <asm/abi.h>
 #include <asm/asm.h>
 #include <asm/cacheflush.h>
+#include <asm/compat-signal.h>
 #include <asm/sim.h>
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
@@ -47,9 +49,9 @@
 #define __NR_N32_rt_sigreturn		6211
 #define __NR_N32_restart_syscall	6214
 
-#define DEBUG_SIG 0
+extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
+extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 /* IRIX compatible stack_t  */
 typedef struct sigaltstack32 {
@@ -63,28 +65,33 @@
 	s32                 uc_link;
 	stack32_t           uc_stack;
 	struct sigcontext   uc_mcontext;
-	sigset_t            uc_sigmask;   /* mask last for extensibility */
+	compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
 };
 
+#if ICACHE_REFILLS_WORKAROUND_WAR == 0
+
 struct rt_sigframe_n32 {
 	u32 rs_ass[4];			/* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
-	u32 rs_pad[2];
-#else
 	u32 rs_code[2];			/* signal trampoline */
-#endif
 	struct siginfo rs_info;
 	struct ucontextn32 rs_uc;
-#if ICACHE_REFILLS_WORKAROUND_WAR
-	u32 rs_code[8] ____cacheline_aligned;		/* signal trampoline */
-#endif
 };
 
+#else  /* ICACHE_REFILLS_WORKAROUND_WAR */
+
+struct rt_sigframe_n32 {
+	u32 rs_ass[4];			/* argument save space for o32 */
+	u32 rs_pad[2];
+	struct siginfo rs_info;
+	struct ucontextn32 rs_uc;
+	u32 rs_code[8] ____cacheline_aligned;		/* signal trampoline */
+};
+
+#endif	/* !ICACHE_REFILLS_WORKAROUND_WAR */
+
 extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat);
 
-save_static_function(sysn32_rt_sigsuspend);
-__attribute_used__ noinline static int
-_sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
 	compat_sigset_t __user *unewset;
 	compat_sigset_t uset;
@@ -114,9 +121,7 @@
 	return -ERESTARTNOHAND;
 }
 
-save_static_function(sysn32_rt_sigreturn);
-__attribute_used__ noinline static void
-_sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
 	struct rt_sigframe_n32 __user *frame;
 	sigset_t set;
@@ -126,7 +131,7 @@
 	frame = (struct rt_sigframe_n32 __user *) regs.regs[29];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
-	if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+	if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
@@ -165,7 +170,7 @@
 	force_sig(SIGSEGV, current);
 }
 
-int setup_rt_frame_n32(struct k_sigaction * ka,
+static int setup_rt_frame_n32(struct k_sigaction * ka,
 	struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
 {
 	struct rt_sigframe_n32 __user *frame;
@@ -192,7 +197,7 @@
 	err |= __put_user(current->sas_ss_size,
 	                  &frame->rs_uc.uc_stack.ss_size);
 	err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
-	err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+	err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 
 	if (err)
 		goto give_sigsegv;
@@ -214,14 +219,18 @@
 	regs->regs[31] = (unsigned long) frame->rs_code;
 	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
 
-#if DEBUG_SIG
-	printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
-#endif
+
 	return 0;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
 	return -EFAULT;
 }
+
+struct mips_abi mips_abi_n32 = {
+	.setup_rt_frame	= setup_rt_frame_n32,
+	.restart	= __NR_N32_restart_syscall
+};
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 0555fc5..c46e479 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -51,31 +51,14 @@
 EXPORT_SYMBOL(phys_cpu_present_map);
 EXPORT_SYMBOL(cpu_online_map);
 
+/* This happens early in bootup, can't really do it better */
 static void smp_tune_scheduling (void)
 {
 	struct cache_desc *cd = &current_cpu_data.scache;
-	unsigned long cachesize;       /* kB   */
-	unsigned long cpu_khz;
+	unsigned long cachesize = cd->linesz * cd->sets * cd->ways;
 
-	/*
-	 * Crude estimate until we actually meassure ...
-	 */
-	cpu_khz = loops_per_jiffy * 2 * HZ / 1000;
-
-	/*
-	 * Rough estimation for SMP scheduling, this is the number of
-	 * cycles it takes for a fully memory-limited process to flush
-	 * the SMP-local cache.
-	 *
-	 * (For a P5 this pretty much means we will choose another idle
-	 *  CPU almost always at wakeup time (this is due to the small
-	 *  L1 cache), on PIIs it's around 50-100 usecs, depending on
-	 *  the cache size)
-	 */
-	if (!cpu_khz)
-		return;
-
-	cachesize = cd->linesz * cd->sets * cd->ways;
+	if (cachesize > max_cache_size)
+		max_cache_size = cachesize;
 }
 
 extern void __init calibrate_delay(void);
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 8aa544f7..e5e56bd 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -307,7 +307,7 @@
 struct clocksource clocksource_mips = {
 	.name		= "MIPS",
 	.mask		= 0xffffffff,
-	.is_continuous	= 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static void __init init_mips_clocksource(void)
@@ -455,8 +455,3 @@
 EXPORT_SYMBOL(to_tm);
 EXPORT_SYMBOL(rtc_mips_set_time);
 EXPORT_SYMBOL(rtc_mips_get_time);
-
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies*(1000000000/HZ);
-}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 2a932cad..18f56a9 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -229,6 +229,9 @@
 			printk("\n");
 	}
 
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+	printk("Acx    : %0*lx\n", field, regs->acx);
+#endif
 	printk("Hi    : %0*lx\n", field, regs->hi);
 	printk("Lo    : %0*lx\n", field, regs->lo);
 
@@ -340,13 +343,9 @@
 extern const struct exception_table_entry __start___dbe_table[];
 extern const struct exception_table_entry __stop___dbe_table[];
 
-void __declare_dbe_table(void)
-{
-	__asm__ __volatile__(
-	".section\t__dbe_table,\"a\"\n\t"
-	".previous"
-	);
-}
+__asm__(
+"	.section	__dbe_table, \"a\"\n"
+"	.previous			\n");
 
 /* Given an address, look for it in the exception tables. */
 static const struct exception_table_entry *search_dbe_tables(unsigned long addr)
@@ -708,6 +707,7 @@
 		die_if_kernel("Break instruction in kernel code", regs);
 		force_sig(SIGTRAP, current);
 	}
+	return;
 
 out_sigsegv:
 	force_sig(SIGSEGV, current);
@@ -751,6 +751,7 @@
 		die_if_kernel("Trap instruction in kernel code", regs);
 		force_sig(SIGTRAP, current);
 	}
+	return;
 
 out_sigsegv:
 	force_sig(SIGSEGV, current);
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index cecff24..c76b793 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -113,10 +113,12 @@
      references from .rodata */
   .exit.text : { *(.exit.text) }
   .exit.data : { *(.exit.data) }
+#if defined(CONFIG_BLK_DEV_INITRD)
   . = ALIGN(_PAGE_SIZE);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
   . = ALIGN(32);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 4596249..9aca871 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -29,6 +29,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/device.h>
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/init.h>
@@ -48,6 +49,7 @@
 #include <asm/cacheflush.h>
 #include <asm/atomic.h>
 #include <asm/cpu.h>
+#include <asm/mips_mt.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/vpe.h>
@@ -64,6 +66,7 @@
 
 static char module_name[] = "vpe";
 static int major;
+static const int minor = 1;	/* fixed for now  */
 
 #ifdef CONFIG_MIPS_APSP_KSPD
  static struct kspd_notifications kspd_events;
@@ -1205,7 +1208,7 @@
 	return ret;
 }
 
-static struct file_operations vpe_fops = {
+static const struct file_operations vpe_fops = {
 	.owner = THIS_MODULE,
 	.open = vpe_open,
 	.release = vpe_release,
@@ -1365,12 +1368,15 @@
 }
 #endif
 
+static struct device *vpe_dev;
+
 static int __init vpe_module_init(void)
 {
 	struct vpe *v = NULL;
+	struct device *dev;
 	struct tc *t;
 	unsigned long val;
-	int i;
+	int i, err;
 
 	if (!cpu_has_mipsmt) {
 		printk("VPE loader: not a MIPS MT capable processor\n");
@@ -1383,6 +1389,14 @@
 		return major;
 	}
 
+	dev = device_create(mt_class, NULL, MKDEV(major, minor),
+	                    "tc%d", minor);
+	if (IS_ERR(dev)) {
+		err = PTR_ERR(dev);
+		goto out_chrdev;
+	}
+	vpe_dev = dev;
+
 	dmt();
 	dvpe();
 
@@ -1478,6 +1492,11 @@
 	kspd_events.kspd_sp_exit = kspd_sp_exit;
 #endif
 	return 0;
+
+out_chrdev:
+	unregister_chrdev(major, module_name);
+
+	return err;
 }
 
 static void __exit vpe_module_exit(void)
@@ -1490,6 +1509,7 @@
 		}
 	}
 
+	device_destroy(mt_class, MKDEV(major, minor));
 	unregister_chrdev(major, module_name);
 }
 
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index 1287835..699ab18 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -302,42 +302,129 @@
 #ifdef CONFIG_SYSCTL
 
 static ctl_table lasat_table[] = {
-	{LASAT_CPU_HZ, "cpu-hz", &lasat_board_info.li_cpu_hz, sizeof(int),
-	 0444, NULL, &proc_dointvec, &sysctl_intvec},
-	{LASAT_BUS_HZ, "bus-hz", &lasat_board_info.li_bus_hz, sizeof(int),
-	 0444, NULL, &proc_dointvec, &sysctl_intvec},
-	{LASAT_MODEL, "bmid", &lasat_board_info.li_bmid, sizeof(int),
-	 0444, NULL, &proc_dointvec, &sysctl_intvec},
-	{LASAT_PRID, "prid", &lasat_board_info.li_prid, sizeof(int),
-	 0644, NULL, &proc_lasat_eeprom_value, &sysctl_lasat_eeprom_value},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "cpu-hz",
+		.data		= &lasat_board_info.li_cpu_hz,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "bus-hz",
+		.data		= &lasat_board_info.li_bus_hz,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "bmid",
+		.data		= &lasat_board_info.li_bmid,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "prid",
+		.data		= &lasat_board_info.li_prid,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_lasat_eeprom_value,
+		.strategy	= &sysctl_lasat_eeprom_value
+	},
 #ifdef CONFIG_INET
-	{LASAT_IPADDR, "ipaddr", &lasat_board_info.li_eeprom_info.ipaddr, sizeof(int),
-	 0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec},
-	{LASAT_NETMASK, "netmask", &lasat_board_info.li_eeprom_info.netmask, sizeof(int),
-	 0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec},
-	{LASAT_BCAST, "bcastaddr", &lasat_bcastaddr,
-		sizeof(lasat_bcastaddr), 0600, NULL,
-		&proc_dostring, &sysctl_string},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "ipaddr",
+		.data		= &lasat_board_info.li_eeprom_info.ipaddr,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_lasat_ip,
+		.strategy	= &sysctl_lasat_intvec
+	},
+	{
+		.ctl_name	= LASAT_NETMASK,
+		.procname	= "netmask",
+		.data		= &lasat_board_info.li_eeprom_info.netmask,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_lasat_ip,
+		.strategy	= &sysctl_lasat_intvec
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "bcastaddr",
+		.data		= &lasat_bcastaddr,
+		.maxlen		= sizeof(lasat_bcastaddr),
+		.mode		= 0600,
+		.proc_handler	= &proc_dostring,
+		.strategy	= &sysctl_string
+	},
 #endif
-	{LASAT_PASSWORD, "passwd_hash", &lasat_board_info.li_eeprom_info.passwd_hash, sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
-	 0600, NULL, &proc_dolasatstring, &sysctl_lasatstring},
-	{LASAT_SBOOT, "boot-service", &lasat_boot_to_service, sizeof(int),
-	 0644, NULL, &proc_dointvec, &sysctl_intvec},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "passwd_hash",
+		.data		= &lasat_board_info.li_eeprom_info.passwd_hash,
+		.maxlen		= sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
+		.mode		= 0600,
+		.proc_handler	= &proc_dolasatstring,
+		.strategy	= &sysctl_lasatstring
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "boot-service",
+		.data		= &lasat_boot_to_service,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec
+	},
 #ifdef CONFIG_DS1603
-	{LASAT_RTC, "rtc", &rtctmp, sizeof(int),
-	 0644, NULL, &proc_dolasatrtc, &sysctl_lasat_rtc},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "rtc",
+		.data		= &rtctmp,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dolasatrtc,
+		.strategy	= &sysctl_lasat_rtc
+	},
 #endif
-	{LASAT_NAMESTR, "namestr", &lasat_board_info.li_namestr, sizeof(lasat_board_info.li_namestr),
-	 0444, NULL, &proc_dostring, &sysctl_string},
-	{LASAT_TYPESTR, "typestr", &lasat_board_info.li_typestr, sizeof(lasat_board_info.li_typestr),
-	 0444, NULL, &proc_dostring, &sysctl_string},
-	{0}
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "namestr",
+		.data		= &lasat_board_info.li_namestr,
+		.maxlen		= sizeof(lasat_board_info.li_namestr),
+		.mode		= 0444,
+		.proc_handler	=  &proc_dostring,
+		.strategy	= &sysctl_string
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "typestr",
+		.data		= &lasat_board_info.li_typestr,
+		.maxlen		= sizeof(lasat_board_info.li_typestr),
+		.mode		= 0444,
+		.proc_handler	= &proc_dostring,
+		.strategy	= &sysctl_string
+	},
+	{}
 };
 
-#define CTL_LASAT 1	// CTL_ANY ???
 static ctl_table lasat_root_table[] = {
-	{ CTL_LASAT, "lasat", NULL, 0, 0555, lasat_table },
-	{ 0 }
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "lasat",
+		.mode		=  0555,
+		.child		= lasat_table
+	},
+	{}
 };
 
 static int __init lasat_register_sysctl(void)
@@ -345,7 +432,7 @@
 	struct ctl_table_header *lasat_table_header;
 
 	lasat_table_header =
-		register_sysctl_table(lasat_root_table, 0);
+		register_sysctl_table(lasat_root_table);
 
 	return 0;
 }
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 5ad501b..2453ea2 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -2,10 +2,11 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y	+= csum_partial.o memcpy.o memset.o promlib.o \
+lib-y	+= csum_partial.o memcpy.o memcpy-inatomic.o memset.o promlib.o \
 	   strlen_user.o strncpy_user.o strnlen_user.o uncached.o
 
-obj-y	+= iomap.o
+obj-y			+= iomap.o
+obj-$(CONFIG_PCI)	+= iomap-pci.o
 
 # libgcc-style stuff needed in the kernel
 lib-y += ashldi3.o ashrdi3.o lshrdi3.o
diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c
new file mode 100644
index 0000000..c11b249
--- /dev/null
+++ b/arch/mips/lib/iomap-pci.c
@@ -0,0 +1,74 @@
+/*
+ * Implement the default iomap interfaces
+ *
+ * (C) Copyright 2004 Linus Torvalds
+ * (C) Copyright 2006 Ralf Baechle <ralf@linux-mips.org>
+ * (C) Copyright 2007 MIPS Technologies, Inc.
+ *     written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+static void __iomem *ioport_map_pci(struct pci_dev *dev,
+                                     unsigned long port, unsigned int nr)
+{
+	struct pci_controller *ctrl = dev->bus->sysdata;
+	unsigned long base = ctrl->io_map_base;
+
+	/* This will eventually become a BUG_ON but for now be gentle */
+	if (unlikely(!ctrl->io_map_base)) {
+		struct pci_bus *bus = dev->bus;
+		char name[8];
+
+		while (bus->parent)
+			bus = bus->parent;
+
+		ctrl->io_map_base = base = mips_io_port_base;
+
+		sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
+		printk(KERN_WARNING "io_map_base of root PCI bus %s unset.  "
+		       "Trying to continue but you better\nfix this issue or "
+		       "report it to linux-mips@linux-mips.org or your "
+		       "vendor.\n", name);
+#ifdef CONFIG_PCI_DOMAINS
+		panic("To avoid data corruption io_map_base MUST be set with "
+		      "multiple PCI domains.");
+#endif
+	}
+
+	return (void __iomem *) (ctrl->io_map_base + port);
+}
+
+/*
+ * Create a virtual mapping cookie for a PCI BAR (memory or IO)
+ */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len || !start)
+		return NULL;
+	if (maxlen && len > maxlen)
+		len = maxlen;
+	if (flags & IORESOURCE_IO)
+		return ioport_map_pci(dev, start, len);
+	if (flags & IORESOURCE_MEM) {
+		if (flags & IORESOURCE_CACHEABLE)
+			return ioremap(start, len);
+		return ioremap_nocache(start, len);
+	}
+	/* What? */
+	return NULL;
+}
+
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+	iounmap(addr);
+}
+
+EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/mips/lib/iomap.c b/arch/mips/lib/iomap.c
index f4ac5bb..d51d5cb 100644
--- a/arch/mips/lib/iomap.c
+++ b/arch/mips/lib/iomap.c
@@ -1,78 +1,227 @@
 /*
- *  iomap.c, Memory Mapped I/O routines for MIPS architecture.
+ * Implement the default iomap interfaces
  *
- *  This code is based on lib/iomap.c, by Linus Torvalds.
- *
- *  Copyright (C) 2004-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
+ * (C) Copyright 2004 Linus Torvalds
+ * (C) Copyright 2006 Ralf Baechle <ralf@linux-mips.org>
+ * (C) Copyright 2007 MIPS Technologies, Inc.
+ *     written by Ralf Baechle <ralf@linux-mips.org>
  */
-#include <linux/ioport.h>
-#include <linux/module.h>
 #include <linux/pci.h>
-
+#include <linux/module.h>
 #include <asm/io.h>
 
+/*
+ * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
+ * access or a MMIO access, these functions don't care. The info is
+ * encoded in the hardware mapping set up by the mapping functions
+ * (or the cookie itself, depending on implementation and hw).
+ *
+ * The generic routines don't assume any hardware mappings, and just
+ * encode the PIO/MMIO as part of the cookie. They coldly assume that
+ * the MMIO IO mappings are not in the low address range.
+ *
+ * Architectures for which this is not true can't use this generic
+ * implementation and should do their own copy.
+ */
+
+#define PIO_MASK	0x0ffffUL
+
+unsigned int ioread8(void __iomem *addr)
+{
+	return readb(addr);
+}
+
+EXPORT_SYMBOL(ioread8);
+
+unsigned int ioread16(void __iomem *addr)
+{
+	return readw(addr);
+}
+
+EXPORT_SYMBOL(ioread16);
+
+unsigned int ioread16be(void __iomem *addr)
+{
+	return be16_to_cpu(__raw_readw(addr));
+}
+
+EXPORT_SYMBOL(ioread16be);
+
+unsigned int ioread32(void __iomem *addr)
+{
+	return readl(addr);
+}
+
+EXPORT_SYMBOL(ioread32);
+
+unsigned int ioread32be(void __iomem *addr)
+{
+	return be32_to_cpu(__raw_readl(addr));
+}
+
+EXPORT_SYMBOL(ioread32be);
+
+void iowrite8(u8 val, void __iomem *addr)
+{
+	writeb(val, addr);
+}
+
+EXPORT_SYMBOL(iowrite8);
+
+void iowrite16(u16 val, void __iomem *addr)
+{
+	writew(val, addr);
+}
+
+EXPORT_SYMBOL(iowrite16);
+
+void iowrite16be(u16 val, void __iomem *addr)
+{
+	__raw_writew(cpu_to_be16(val), addr);
+}
+
+EXPORT_SYMBOL(iowrite16be);
+
+void iowrite32(u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+}
+
+EXPORT_SYMBOL(iowrite32);
+
+void iowrite32be(u32 val, void __iomem *addr)
+{
+	__raw_writel(cpu_to_be32(val), addr);
+}
+
+EXPORT_SYMBOL(iowrite32be);
+
+/*
+ * These are the "repeat MMIO read/write" functions.
+ * Note the "__raw" accesses, since we don't want to
+ * convert to CPU byte order. We write in "IO byte
+ * order" (we also don't have IO barriers).
+ */
+static inline void mmio_insb(void __iomem *addr, u8 *dst, int count)
+{
+	while (--count >= 0) {
+		u8 data = __raw_readb(addr);
+		*dst = data;
+		dst++;
+	}
+}
+
+static inline void mmio_insw(void __iomem *addr, u16 *dst, int count)
+{
+	while (--count >= 0) {
+		u16 data = __raw_readw(addr);
+		*dst = data;
+		dst++;
+	}
+}
+
+static inline void mmio_insl(void __iomem *addr, u32 *dst, int count)
+{
+	while (--count >= 0) {
+		u32 data = __raw_readl(addr);
+		*dst = data;
+		dst++;
+	}
+}
+
+static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writeb(*src, addr);
+		src++;
+	}
+}
+
+static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writew(*src, addr);
+		src++;
+	}
+}
+
+static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writel(*src, addr);
+		src++;
+	}
+}
+
+void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	mmio_insb(addr, dst, count);
+}
+
+EXPORT_SYMBOL(ioread8_rep);
+
+void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	mmio_insw(addr, dst, count);
+}
+
+EXPORT_SYMBOL(ioread16_rep);
+
+void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	mmio_insl(addr, dst, count);
+}
+
+EXPORT_SYMBOL(ioread32_rep);
+
+void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	mmio_outsb(addr, src, count);
+}
+
+EXPORT_SYMBOL(iowrite8_rep);
+
+void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	mmio_outsw(addr, src, count);
+}
+
+EXPORT_SYMBOL(iowrite16_rep);
+
+void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	mmio_outsl(addr, src, count);
+}
+
+EXPORT_SYMBOL(iowrite32_rep);
+
+/*
+ * Create a virtual mapping cookie for an IO port range
+ *
+ * This uses the same mapping are as the in/out family which has to be setup
+ * by the platform initialization code.
+ *
+ * Just to make matters somewhat more interesting on MIPS systems with
+ * multiple host bridge each will have it's own ioport address space.
+ */
+static void __iomem *ioport_map_legacy(unsigned long port, unsigned int nr)
+{
+	return (void __iomem *) (mips_io_port_base + port);
+}
+
 void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
-	unsigned long end;
-
-	end = port + nr - 1UL;
-	if (ioport_resource.start > port ||
-	    ioport_resource.end < end || port > end)
+	if (port > PIO_MASK)
 		return NULL;
 
-	return (void __iomem *)(mips_io_port_base + port);
+	return ioport_map_legacy(port, nr);
 }
 
+EXPORT_SYMBOL(ioport_map);
+
 void ioport_unmap(void __iomem *addr)
 {
+	/* Nothing to do */
 }
-EXPORT_SYMBOL(ioport_map);
+
 EXPORT_SYMBOL(ioport_unmap);
-
-void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
-{
-	unsigned long start, len, flags;
-
-	if (dev == NULL)
-		return NULL;
-
-	start = pci_resource_start(dev, bar);
-	len = pci_resource_len(dev, bar);
-	if (!start || !len)
-		return NULL;
-
-	if (maxlen != 0 && len > maxlen)
-		len = maxlen;
-
-	flags = pci_resource_flags(dev, bar);
-	if (flags & IORESOURCE_IO)
-		return ioport_map(start, len);
-	if (flags & IORESOURCE_MEM) {
-		if (flags & IORESOURCE_CACHEABLE)
-			return ioremap_cachable(start, len);
-		return ioremap_nocache(start, len);
-	}
-
-	return NULL;
-}
-
-void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
-{
-	iounmap(addr);
-}
-EXPORT_SYMBOL(pci_iomap);
-EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/mips/lib/memcpy-inatomic.S b/arch/mips/lib/memcpy-inatomic.S
new file mode 100644
index 0000000..3a534b2
--- /dev/null
+++ b/arch/mips/lib/memcpy-inatomic.S
@@ -0,0 +1,436 @@
+/*
+ * 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.
+ *
+ * Unified implementation of memcpy, memmove and the __copy_user backend.
+ *
+ * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc.
+ * Copyright (C) 2002 Broadcom, Inc.
+ *   memcpy/copy_user author: Mark Vandevoorde
+ *
+ * Mnemonic names for arguments to memcpy/__copy_user
+ */
+
+/*
+ * Hack to resolve longstanding prefetch issue
+ *
+ * Prefetching may be fatal on some systems if we're prefetching beyond the
+ * end of memory on some systems.  It's also a seriously bad idea on non
+ * dma-coherent systems.
+ */
+#if !defined(CONFIG_DMA_COHERENT) || !defined(CONFIG_DMA_IP27)
+#undef CONFIG_CPU_HAS_PREFETCH
+#endif
+#ifdef CONFIG_MIPS_MALTA
+#undef CONFIG_CPU_HAS_PREFETCH
+#endif
+
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/regdef.h>
+
+#define dst a0
+#define src a1
+#define len a2
+
+/*
+ * Spec
+ *
+ * memcpy copies len bytes from src to dst and sets v0 to dst.
+ * It assumes that
+ *   - src and dst don't overlap
+ *   - src is readable
+ *   - dst is writable
+ * memcpy uses the standard calling convention
+ *
+ * __copy_user copies up to len bytes from src to dst and sets a2 (len) to
+ * the number of uncopied bytes due to an exception caused by a read or write.
+ * __copy_user assumes that src and dst don't overlap, and that the call is
+ * implementing one of the following:
+ *   copy_to_user
+ *     - src is readable  (no exceptions when reading src)
+ *   copy_from_user
+ *     - dst is writable  (no exceptions when writing dst)
+ * __copy_user uses a non-standard calling convention; see
+ * include/asm-mips/uaccess.h
+ *
+ * When an exception happens on a load, the handler must
+ # ensure that all of the destination buffer is overwritten to prevent
+ * leaking information to user mode programs.
+ */
+
+/*
+ * Implementation
+ */
+
+/*
+ * The exception handler for loads requires that:
+ *  1- AT contain the address of the byte just past the end of the source
+ *     of the copy,
+ *  2- src_entry <= src < AT, and
+ *  3- (dst - src) == (dst_entry - src_entry),
+ * The _entry suffix denotes values when __copy_user was called.
+ *
+ * (1) is set up up by uaccess.h and maintained by not writing AT in copy_user
+ * (2) is met by incrementing src by the number of bytes copied
+ * (3) is met by not doing loads between a pair of increments of dst and src
+ *
+ * The exception handlers for stores adjust len (if necessary) and return.
+ * These handlers do not need to overwrite any data.
+ *
+ * For __rmemcpy and memmove an exception is always a kernel bug, therefore
+ * they're not protected.
+ */
+
+#define EXC(inst_reg,addr,handler)		\
+9:	inst_reg, addr;				\
+	.section __ex_table,"a";		\
+	PTR	9b, handler;			\
+	.previous
+
+/*
+ * Only on the 64-bit kernel we can made use of 64-bit registers.
+ */
+#ifdef CONFIG_64BIT
+#define USE_DOUBLE
+#endif
+
+#ifdef USE_DOUBLE
+
+#define LOAD   ld
+#define LOADL  ldl
+#define LOADR  ldr
+#define STOREL sdl
+#define STORER sdr
+#define STORE  sd
+#define ADD    daddu
+#define SUB    dsubu
+#define SRL    dsrl
+#define SRA    dsra
+#define SLL    dsll
+#define SLLV   dsllv
+#define SRLV   dsrlv
+#define NBYTES 8
+#define LOG_NBYTES 3
+
+/*
+ * As we are sharing code base with the mips32 tree (which use the o32 ABI
+ * register definitions). We need to redefine the register definitions from
+ * the n64 ABI register naming to the o32 ABI register naming.
+ */
+#undef t0
+#undef t1
+#undef t2
+#undef t3
+#define t0	$8
+#define t1	$9
+#define t2	$10
+#define t3	$11
+#define t4	$12
+#define t5	$13
+#define t6	$14
+#define t7	$15
+
+#else
+
+#define LOAD   lw
+#define LOADL  lwl
+#define LOADR  lwr
+#define STOREL swl
+#define STORER swr
+#define STORE  sw
+#define ADD    addu
+#define SUB    subu
+#define SRL    srl
+#define SLL    sll
+#define SRA    sra
+#define SLLV   sllv
+#define SRLV   srlv
+#define NBYTES 4
+#define LOG_NBYTES 2
+
+#endif /* USE_DOUBLE */
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define LDFIRST LOADR
+#define LDREST  LOADL
+#define STFIRST STORER
+#define STREST  STOREL
+#define SHIFT_DISCARD SLLV
+#else
+#define LDFIRST LOADL
+#define LDREST  LOADR
+#define STFIRST STOREL
+#define STREST  STORER
+#define SHIFT_DISCARD SRLV
+#endif
+
+#define FIRST(unit) ((unit)*NBYTES)
+#define REST(unit)  (FIRST(unit)+NBYTES-1)
+#define UNIT(unit)  FIRST(unit)
+
+#define ADDRMASK (NBYTES-1)
+
+	.text
+	.set	noreorder
+	.set	noat
+
+/*
+ * A combined memcpy/__copy_user
+ * __copy_user sets len to 0 for success; else to an upper bound of
+ * the number of uncopied bytes.
+ * memcpy sets v0 to dst.
+ */
+	.align	5
+LEAF(__copy_user_inatomic)
+	/*
+	 * Note: dst & src may be unaligned, len may be 0
+	 * Temps
+	 */
+#define rem t8
+
+	/*
+	 * The "issue break"s below are very approximate.
+	 * Issue delays for dcache fills will perturb the schedule, as will
+	 * load queue full replay traps, etc.
+	 *
+	 * If len < NBYTES use byte operations.
+	 */
+	PREF(	0, 0(src) )
+	PREF(	1, 0(dst) )
+	sltu	t2, len, NBYTES
+	and	t1, dst, ADDRMASK
+	PREF(	0, 1*32(src) )
+	PREF(	1, 1*32(dst) )
+	bnez	t2, copy_bytes_checklen
+	 and	t0, src, ADDRMASK
+	PREF(	0, 2*32(src) )
+	PREF(	1, 2*32(dst) )
+	bnez	t1, dst_unaligned
+	 nop
+	bnez	t0, src_unaligned_dst_aligned
+	/*
+	 * use delay slot for fall-through
+	 * src and dst are aligned; need to compute rem
+	 */
+both_aligned:
+	 SRL	t0, len, LOG_NBYTES+3    # +3 for 8 units/iter
+	beqz	t0, cleanup_both_aligned # len < 8*NBYTES
+	 and	rem, len, (8*NBYTES-1)	 # rem = len % (8*NBYTES)
+	PREF(	0, 3*32(src) )
+	PREF(	1, 3*32(dst) )
+	.align	4
+1:
+EXC(	LOAD	t0, UNIT(0)(src),	l_exc)
+EXC(	LOAD	t1, UNIT(1)(src),	l_exc_copy)
+EXC(	LOAD	t2, UNIT(2)(src),	l_exc_copy)
+EXC(	LOAD	t3, UNIT(3)(src),	l_exc_copy)
+	SUB	len, len, 8*NBYTES
+EXC(	LOAD	t4, UNIT(4)(src),	l_exc_copy)
+EXC(	LOAD	t7, UNIT(5)(src),	l_exc_copy)
+	STORE	t0, UNIT(0)(dst)
+	STORE	t1, UNIT(1)(dst)
+EXC(	LOAD	t0, UNIT(6)(src),	l_exc_copy)
+EXC(	LOAD	t1, UNIT(7)(src),	l_exc_copy)
+	ADD	src, src, 8*NBYTES
+	ADD	dst, dst, 8*NBYTES
+	STORE	t2, UNIT(-6)(dst)
+	STORE	t3, UNIT(-5)(dst)
+	STORE	t4, UNIT(-4)(dst)
+	STORE	t7, UNIT(-3)(dst)
+	STORE	t0, UNIT(-2)(dst)
+	STORE	t1, UNIT(-1)(dst)
+	PREF(	0, 8*32(src) )
+	PREF(	1, 8*32(dst) )
+	bne	len, rem, 1b
+	 nop
+
+	/*
+	 * len == rem == the number of bytes left to copy < 8*NBYTES
+	 */
+cleanup_both_aligned:
+	beqz	len, done
+	 sltu	t0, len, 4*NBYTES
+	bnez	t0, less_than_4units
+	 and	rem, len, (NBYTES-1)	# rem = len % NBYTES
+	/*
+	 * len >= 4*NBYTES
+	 */
+EXC(	LOAD	t0, UNIT(0)(src),	l_exc)
+EXC(	LOAD	t1, UNIT(1)(src),	l_exc_copy)
+EXC(	LOAD	t2, UNIT(2)(src),	l_exc_copy)
+EXC(	LOAD	t3, UNIT(3)(src),	l_exc_copy)
+	SUB	len, len, 4*NBYTES
+	ADD	src, src, 4*NBYTES
+	STORE	t0, UNIT(0)(dst)
+	STORE	t1, UNIT(1)(dst)
+	STORE	t2, UNIT(2)(dst)
+	STORE	t3, UNIT(3)(dst)
+	beqz	len, done
+	 ADD	dst, dst, 4*NBYTES
+less_than_4units:
+	/*
+	 * rem = len % NBYTES
+	 */
+	beq	rem, len, copy_bytes
+	 nop
+1:
+EXC(	LOAD	t0, 0(src),		l_exc)
+	ADD	src, src, NBYTES
+	SUB	len, len, NBYTES
+	STORE	t0, 0(dst)
+	bne	rem, len, 1b
+	 ADD	dst, dst, NBYTES
+
+	/*
+	 * src and dst are aligned, need to copy rem bytes (rem < NBYTES)
+	 * A loop would do only a byte at a time with possible branch
+	 * mispredicts.  Can't do an explicit LOAD dst,mask,or,STORE
+	 * because can't assume read-access to dst.  Instead, use
+	 * STREST dst, which doesn't require read access to dst.
+	 *
+	 * This code should perform better than a simple loop on modern,
+	 * wide-issue mips processors because the code has fewer branches and
+	 * more instruction-level parallelism.
+	 */
+#define bits t2
+	beqz	len, done
+	 ADD	t1, dst, len	# t1 is just past last byte of dst
+	li	bits, 8*NBYTES
+	SLL	rem, len, 3	# rem = number of bits to keep
+EXC(	LOAD	t0, 0(src),		l_exc)
+	SUB	bits, bits, rem	# bits = number of bits to discard
+	SHIFT_DISCARD t0, t0, bits
+	STREST	t0, -1(t1)
+	jr	ra
+	 move	len, zero
+dst_unaligned:
+	/*
+	 * dst is unaligned
+	 * t0 = src & ADDRMASK
+	 * t1 = dst & ADDRMASK; T1 > 0
+	 * len >= NBYTES
+	 *
+	 * Copy enough bytes to align dst
+	 * Set match = (src and dst have same alignment)
+	 */
+#define match rem
+EXC(	LDFIRST	t3, FIRST(0)(src),	l_exc)
+	ADD	t2, zero, NBYTES
+EXC(	LDREST	t3, REST(0)(src),	l_exc_copy)
+	SUB	t2, t2, t1	# t2 = number of bytes copied
+	xor	match, t0, t1
+	STFIRST t3, FIRST(0)(dst)
+	beq	len, t2, done
+	 SUB	len, len, t2
+	ADD	dst, dst, t2
+	beqz	match, both_aligned
+	 ADD	src, src, t2
+
+src_unaligned_dst_aligned:
+	SRL	t0, len, LOG_NBYTES+2    # +2 for 4 units/iter
+	PREF(	0, 3*32(src) )
+	beqz	t0, cleanup_src_unaligned
+	 and	rem, len, (4*NBYTES-1)   # rem = len % 4*NBYTES
+	PREF(	1, 3*32(dst) )
+1:
+/*
+ * Avoid consecutive LD*'s to the same register since some mips
+ * implementations can't issue them in the same cycle.
+ * It's OK to load FIRST(N+1) before REST(N) because the two addresses
+ * are to the same unit (unless src is aligned, but it's not).
+ */
+EXC(	LDFIRST	t0, FIRST(0)(src),	l_exc)
+EXC(	LDFIRST	t1, FIRST(1)(src),	l_exc_copy)
+	SUB     len, len, 4*NBYTES
+EXC(	LDREST	t0, REST(0)(src),	l_exc_copy)
+EXC(	LDREST	t1, REST(1)(src),	l_exc_copy)
+EXC(	LDFIRST	t2, FIRST(2)(src),	l_exc_copy)
+EXC(	LDFIRST	t3, FIRST(3)(src),	l_exc_copy)
+EXC(	LDREST	t2, REST(2)(src),	l_exc_copy)
+EXC(	LDREST	t3, REST(3)(src),	l_exc_copy)
+	PREF(	0, 9*32(src) )		# 0 is PREF_LOAD  (not streamed)
+	ADD	src, src, 4*NBYTES
+#ifdef CONFIG_CPU_SB1
+	nop				# improves slotting
+#endif
+	STORE	t0, UNIT(0)(dst)
+	STORE	t1, UNIT(1)(dst)
+	STORE	t2, UNIT(2)(dst)
+	STORE	t3, UNIT(3)(dst)
+	PREF(	1, 9*32(dst) )     	# 1 is PREF_STORE (not streamed)
+	bne	len, rem, 1b
+	 ADD	dst, dst, 4*NBYTES
+
+cleanup_src_unaligned:
+	beqz	len, done
+	 and	rem, len, NBYTES-1  # rem = len % NBYTES
+	beq	rem, len, copy_bytes
+	 nop
+1:
+EXC(	LDFIRST t0, FIRST(0)(src),	l_exc)
+EXC(	LDREST	t0, REST(0)(src),	l_exc_copy)
+	ADD	src, src, NBYTES
+	SUB	len, len, NBYTES
+	STORE	t0, 0(dst)
+	bne	len, rem, 1b
+	 ADD	dst, dst, NBYTES
+
+copy_bytes_checklen:
+	beqz	len, done
+	 nop
+copy_bytes:
+	/* 0 < len < NBYTES  */
+#define COPY_BYTE(N)			\
+EXC(	lb	t0, N(src), l_exc);	\
+	SUB	len, len, 1;		\
+	beqz	len, done;		\
+	 sb	t0, N(dst)
+
+	COPY_BYTE(0)
+	COPY_BYTE(1)
+#ifdef USE_DOUBLE
+	COPY_BYTE(2)
+	COPY_BYTE(3)
+	COPY_BYTE(4)
+	COPY_BYTE(5)
+#endif
+EXC(	lb	t0, NBYTES-2(src), l_exc)
+	SUB	len, len, 1
+	jr	ra
+	 sb	t0, NBYTES-2(dst)
+done:
+	jr	ra
+	 nop
+	END(__copy_user_inatomic)
+
+l_exc_copy:
+	/*
+	 * Copy bytes from src until faulting load address (or until a
+	 * lb faults)
+	 *
+	 * When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28)
+	 * may be more than a byte beyond the last address.
+	 * Hence, the lb below may get an exception.
+	 *
+	 * Assumes src < THREAD_BUADDR($28)
+	 */
+	LOAD	t0, TI_TASK($28)
+	 nop
+	LOAD	t0, THREAD_BUADDR(t0)
+1:
+EXC(	lb	t1, 0(src),	l_exc)
+	ADD	src, src, 1
+	sb	t1, 0(dst)	# can't fault -- we're copy_from_user
+	bne	src, t0, 1b
+	 ADD	dst, dst, 1
+l_exc:
+	LOAD	t0, TI_TASK($28)
+	 nop
+	LOAD	t0, THREAD_BUADDR(t0)	# t0 is just past last good address
+	 nop
+	SUB	len, AT, t0		# len number of uncopied bytes
+	jr	ra
+	 nop
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 19e41fd..de57273 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -2,8 +2,8 @@
 # Makefile for the Linux/MIPS-specific parts of the memory manager.
 #
 
-obj-y				+= cache.o extable.o fault.o init.o pgtable.o \
-				   tlbex.o tlbex-fault.o
+obj-y				+= cache.o dma-default.o extable.o fault.o \
+				   init.o pgtable.o tlbex.o tlbex-fault.o
 
 obj-$(CONFIG_32BIT)		+= ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)		+= pgtable-64.o
@@ -32,14 +32,4 @@
 obj-$(CONFIG_RM7000_CPU_SCACHE)	+= sc-rm7k.o
 obj-$(CONFIG_MIPS_CPU_SCACHE)	+= sc-mips.o
 
-#
-# Choose one DMA coherency model
-#
-ifndef CONFIG_OWN_DMA
-obj-$(CONFIG_DMA_COHERENT)	+= dma-coherent.o
-obj-$(CONFIG_DMA_NONCOHERENT)	+= dma-noncoherent.o
-endif
-obj-$(CONFIG_DMA_IP27)		+= dma-ip27.o
-obj-$(CONFIG_DMA_IP32)		+= dma-ip32.o
-
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 3a8afd4..9ea460b 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -259,6 +259,12 @@
 		on_each_cpu(sb1_flush_cache_data_page_ipi, (void *) addr, 1, 1);
 }
 #else
+
+static void local_sb1_flush_cache_data_page(unsigned long addr)
+{
+	__sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE);
+}
+
 void sb1_flush_cache_data_page(unsigned long)
 	__attribute__((alias("local_sb1_flush_cache_data_page")));
 #endif
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 1f954a2..31819c5 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -107,8 +107,6 @@
 	}
 }
 
-#define __weak __attribute__((weak))
-
 static char cache_panic[] __initdata = "Yeee, unsupported cache architecture.";
 
 void __init cpu_cache_init(void)
diff --git a/arch/mips/mm/dma-coherent.c b/arch/mips/mm/dma-coherent.c
deleted file mode 100644
index 5697c6e..0000000
--- a/arch/mips/mm/dma-coherent.c
+++ /dev/null
@@ -1,254 +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) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-#include <linux/types.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, gfp_t gfp)
-{
-	void *ret;
-	/* ignore region specifiers */
-	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
-		gfp |= GFP_DMA;
-	ret = (void *) __get_free_pages(gfp, get_order(size));
-
-	if (ret != NULL) {
-		memset(ret, 0, size);
-		*dma_handle = virt_to_phys(ret);
-	}
-
-	return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, gfp_t gfp)
-	__attribute__((alias("dma_alloc_noncoherent")));
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
-	dma_addr_t dma_handle)
-{
-	unsigned long addr = (unsigned long) vaddr;
-
-	free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
-	dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent")));
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-	enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	return __pa(ptr);
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-		 enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	enum dma_data_direction direction)
-{
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	for (i = 0; i < nents; i++, sg++) {
-		sg->dma_address = (dma_addr_t)page_to_phys(sg->page) + sg->offset;
-	}
-
-	return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	return page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-	       enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	     enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-	size_t size, enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-	size_t size, enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
-		      unsigned long offset, size_t size,
-		      enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
-		      unsigned long offset, size_t size,
-		      enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-		 enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-		 enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
-	/*
-	 * we fall back to GFP_DMA when the mask isn't all 1s,
-	 * so we can't guarantee allocations that must be
-	 * within a tighter range than GFP_DMA..
-	 */
-	if (mask < 0x00ffffff)
-		return 0;
-
-	return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
-	return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-	       enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
-/* The DAC routines are a PCIism.. */
-
-#ifdef CONFIG_PCI
-
-#include <linux/pci.h>
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-	struct page *page, unsigned long offset, int direction)
-{
-	return (dma64_addr_t)page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-	dma64_addr_t dma_addr)
-{
-	return mem_map + (dma_addr >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-	dma64_addr_t dma_addr)
-{
-	return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
-
-#endif /* CONFIG_PCI */
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
new file mode 100644
index 0000000..4a32e93
--- /dev/null
+++ b/arch/mips/mm/dma-default.c
@@ -0,0 +1,363 @@
+/*
+ * 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  Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001, 06  Ralf Baechle <ralf@linux-mips.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+
+#include <dma-coherence.h>
+
+/*
+ * Warning on the terminology - Linux calls an uncached area coherent;
+ * MIPS terminology calls memory areas with hardware maintained coherency
+ * coherent.
+ */
+
+static inline int cpu_is_noncoherent_r10000(struct device *dev)
+{
+	return !plat_device_is_coherent(dev) &&
+	       (current_cpu_data.cputype == CPU_R10000 &&
+	       current_cpu_data.cputype == CPU_R12000);
+}
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+	dma_addr_t * dma_handle, gfp_t gfp)
+{
+	void *ret;
+
+	/* ignore region specifiers */
+	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+		gfp |= GFP_DMA;
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*dma_handle = plat_map_dma_mem(dev, ret, size);
+	}
+
+	return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_noncoherent);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+	dma_addr_t * dma_handle, gfp_t gfp)
+{
+	void *ret;
+
+	/* ignore region specifiers */
+	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+		gfp |= GFP_DMA;
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret) {
+		memset(ret, 0, size);
+		*dma_handle = plat_map_dma_mem(dev, ret, size);
+
+		if (!plat_device_is_coherent(dev)) {
+			dma_cache_wback_inv((unsigned long) ret, size);
+			ret = UNCAC_ADDR(ret);
+		}
+	}
+
+	return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+	dma_addr_t dma_handle)
+{
+	free_pages((unsigned long) vaddr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_noncoherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+	dma_addr_t dma_handle)
+{
+	unsigned long addr = (unsigned long) vaddr;
+
+	if (!plat_device_is_coherent(dev))
+		addr = CAC_ADDR(addr);
+
+	free_pages(addr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_coherent);
+
+static inline void __dma_sync(unsigned long addr, size_t size,
+	enum dma_data_direction direction)
+{
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		dma_cache_wback(addr, size);
+		break;
+
+	case DMA_FROM_DEVICE:
+		dma_cache_inv(addr, size);
+		break;
+
+	case DMA_BIDIRECTIONAL:
+		dma_cache_wback_inv(addr, size);
+		break;
+
+	default:
+		BUG();
+	}
+}
+
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+	enum dma_data_direction direction)
+{
+	unsigned long addr = (unsigned long) ptr;
+
+	if (!plat_device_is_coherent(dev))
+		__dma_sync(addr, size, direction);
+
+	return plat_map_dma_mem(dev, ptr, size);
+}
+
+EXPORT_SYMBOL(dma_map_single);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+	enum dma_data_direction direction)
+{
+	if (cpu_is_noncoherent_r10000(dev))
+		__dma_sync(plat_dma_addr_to_phys(dma_addr) + PAGE_OFFSET, size,
+		           direction);
+
+	plat_unmap_dma_mem(dma_addr);
+}
+
+EXPORT_SYMBOL(dma_unmap_single);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	enum dma_data_direction direction)
+{
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	for (i = 0; i < nents; i++, sg++) {
+		unsigned long addr;
+
+		addr = (unsigned long) page_address(sg->page);
+		if (!plat_device_is_coherent(dev) && addr)
+			__dma_sync(addr + sg->offset, sg->length, direction);
+		sg->dma_address = plat_map_dma_mem_page(dev, sg->page) +
+		                  sg->offset;
+	}
+
+	return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+	unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	if (!plat_device_is_coherent(dev)) {
+		unsigned long addr;
+
+		addr = (unsigned long) page_address(page) + offset;
+		dma_cache_wback_inv(addr, size);
+	}
+
+	return plat_map_dma_mem_page(dev, page) + offset;
+}
+
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	if (!plat_device_is_coherent(dev) && direction != DMA_TO_DEVICE) {
+		unsigned long addr;
+
+		addr = plat_dma_addr_to_phys(dma_address);
+		dma_cache_wback_inv(addr, size);
+	}
+
+	plat_unmap_dma_mem(dma_address);
+}
+
+EXPORT_SYMBOL(dma_unmap_page);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	enum dma_data_direction direction)
+{
+	unsigned long addr;
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	for (i = 0; i < nhwentries; i++, sg++) {
+		if (!plat_device_is_coherent(dev) &&
+		    direction != DMA_TO_DEVICE) {
+			addr = (unsigned long) page_address(sg->page);
+			if (addr)
+				__dma_sync(addr + sg->offset, sg->length,
+				           direction);
+		}
+		plat_unmap_dma_mem(sg->dma_address);
+	}
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+	size_t size, enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	if (cpu_is_noncoherent_r10000(dev)) {
+		unsigned long addr;
+
+		addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
+		__dma_sync(addr, size, direction);
+	}
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_cpu);
+
+void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+	size_t size, enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	if (cpu_is_noncoherent_r10000(dev)) {
+		unsigned long addr;
+
+		addr = plat_dma_addr_to_phys(dma_handle);
+		__dma_sync(addr, size, direction);
+	}
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+	unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	if (cpu_is_noncoherent_r10000(dev)) {
+		unsigned long addr;
+
+		addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
+		__dma_sync(addr + offset, size, direction);
+	}
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
+
+void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+	unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	if (cpu_is_noncoherent_r10000(dev)) {
+		unsigned long addr;
+
+		addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle);
+		__dma_sync(addr + offset, size, direction);
+	}
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_device);
+
+void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+	enum dma_data_direction direction)
+{
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	/* Make sure that gcc doesn't leave the empty loop body.  */
+	for (i = 0; i < nelems; i++, sg++) {
+		if (!plat_device_is_coherent(dev))
+			__dma_sync((unsigned long)page_address(sg->page),
+			           sg->length, direction);
+		plat_unmap_dma_mem(sg->dma_address);
+	}
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_cpu);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+	enum dma_data_direction direction)
+{
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	/* Make sure that gcc doesn't leave the empty loop body.  */
+	for (i = 0; i < nelems; i++, sg++) {
+		if (!plat_device_is_coherent(dev))
+			__dma_sync((unsigned long)page_address(sg->page),
+			           sg->length, direction);
+		plat_unmap_dma_mem(sg->dma_address);
+	}
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+int dma_mapping_error(dma_addr_t dma_addr)
+{
+	return 0;
+}
+
+EXPORT_SYMBOL(dma_mapping_error);
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < 0x00ffffff)
+		return 0;
+
+	return 1;
+}
+
+EXPORT_SYMBOL(dma_supported);
+
+int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
+{
+	return plat_device_is_coherent(dev);
+}
+
+EXPORT_SYMBOL(dma_is_consistent);
+
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	if (!plat_device_is_coherent(dev))
+		dma_cache_wback_inv((unsigned long)vaddr, size);
+}
+
+EXPORT_SYMBOL(dma_cache_sync);
diff --git a/arch/mips/mm/dma-ip27.c b/arch/mips/mm/dma-ip27.c
deleted file mode 100644
index f088344..0000000
--- a/arch/mips/mm/dma-ip27.c
+++ /dev/null
@@ -1,257 +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) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-
-#include <asm/cache.h>
-#include <asm/pci/bridge.h>
-
-#define pdev_to_baddr(pdev, addr) \
-	(BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr))
-#define dev_to_baddr(dev, addr) \
-	pdev_to_baddr(to_pci_dev(dev), (addr))
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, gfp_t gfp)
-{
-	void *ret;
-
-	/* ignore region specifiers */
-	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
-		gfp |= GFP_DMA;
-	ret = (void *) __get_free_pages(gfp, get_order(size));
-
-	if (ret != NULL) {
-		memset(ret, 0, size);
-		*dma_handle = dev_to_baddr(dev, virt_to_phys(ret));
-	}
-
-	return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, gfp_t gfp)
-	__attribute__((alias("dma_alloc_noncoherent")));
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
-	dma_addr_t dma_handle)
-{
-	unsigned long addr = (unsigned long) vaddr;
-
-	free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
-	dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent")));
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-	enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	return dev_to_baddr(dev, __pa(ptr));
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-		 enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	enum dma_data_direction direction)
-{
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	for (i = 0; i < nents; i++, sg++) {
-		sg->dma_address = (dma_addr_t) dev_to_baddr(dev,
-			page_to_phys(sg->page) + sg->offset);
-	}
-
-	return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	return dev_to_baddr(dev, page_to_phys(page) + offset);
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-	       enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	     enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
-		enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
-		enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
-		      unsigned long offset, size_t size,
-		      enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
-		      unsigned long offset, size_t size,
-		      enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-		 enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-		 enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
-	/*
-	 * we fall back to GFP_DMA when the mask isn't all 1s,
-	 * so we can't guarantee allocations that must be
-	 * within a tighter range than GFP_DMA..
-	 */
-	if (mask < 0x00ffffff)
-		return 0;
-
-	return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
-	return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-	       enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-	struct page *page, unsigned long offset, int direction)
-{
-	dma64_addr_t addr = page_to_phys(page) + offset;
-
-	return (dma64_addr_t) pdev_to_baddr(pdev, addr);
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-	dma64_addr_t dma_addr)
-{
-	struct bridge_controller *bc = BRIDGE_CONTROLLER(pdev->bus);
-
-	return pfn_to_page((dma_addr - bc->baddr) >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-	dma64_addr_t dma_addr)
-{
-	return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
diff --git a/arch/mips/mm/dma-ip32.c b/arch/mips/mm/dma-ip32.c
deleted file mode 100644
index b42b6f7..0000000
--- a/arch/mips/mm/dma-ip32.c
+++ /dev/null
@@ -1,383 +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) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
- * Copyright (C) 2005 Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- * IP32 changes by Ilya.
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-#include <asm/ip32/crime.h>
-
-/*
- * Warning on the terminology - Linux calls an uncached area coherent;
- * MIPS terminology calls memory areas with hardware maintained coherency
- * coherent.
- */
-
-/*
- * Few notes.
- * 1. CPU sees memory as two chunks: 0-256M@0x0, and the rest @0x40000000+256M
- * 2. PCI sees memory as one big chunk @0x0 (or we could use 0x40000000 for native-endian)
- * 3. All other devices see memory as one big chunk at 0x40000000
- * 4. Non-PCI devices will pass NULL as struct device*
- * Thus we translate differently, depending on device.
- */
-
-#define RAM_OFFSET_MASK	0x3fffffff
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, gfp_t gfp)
-{
-	void *ret;
-	/* ignore region specifiers */
-	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
-		gfp |= GFP_DMA;
-	ret = (void *) __get_free_pages(gfp, get_order(size));
-
-	if (ret != NULL) {
-		unsigned long addr = virt_to_phys(ret)&RAM_OFFSET_MASK;
-		memset(ret, 0, size);
-		if(dev==NULL)
-		    addr+= CRIME_HI_MEM_BASE;
-		*dma_handle = addr;
-	}
-
-	return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, gfp_t gfp)
-{
-	void *ret;
-
-	ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
-	if (ret) {
-		dma_cache_wback_inv((unsigned long) ret, size);
-		ret = UNCAC_ADDR(ret);
-	}
-
-	return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
-	dma_addr_t dma_handle)
-{
-	free_pages((unsigned long) vaddr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
-	dma_addr_t dma_handle)
-{
-	unsigned long addr = (unsigned long) vaddr;
-
-	addr = CAC_ADDR(addr);
-	free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-static inline void __dma_sync(unsigned long addr, size_t size,
-	enum dma_data_direction direction)
-{
-	switch (direction) {
-	case DMA_TO_DEVICE:
-		dma_cache_wback(addr, size);
-		break;
-
-	case DMA_FROM_DEVICE:
-		dma_cache_inv(addr, size);
-		break;
-
-	case DMA_BIDIRECTIONAL:
-		dma_cache_wback_inv(addr, size);
-		break;
-
-	default:
-		BUG();
-	}
-}
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-	enum dma_data_direction direction)
-{
-	unsigned long addr = (unsigned long) ptr;
-
-	switch (direction) {
-	case DMA_TO_DEVICE:
-		dma_cache_wback(addr, size);
-		break;
-
-	case DMA_FROM_DEVICE:
-		dma_cache_inv(addr, size);
-		break;
-
-	case DMA_BIDIRECTIONAL:
-		dma_cache_wback_inv(addr, size);
-		break;
-
-	default:
-		BUG();
-	}
-
-	addr = virt_to_phys(ptr)&RAM_OFFSET_MASK;
-	if(dev == NULL)
-	    addr+=CRIME_HI_MEM_BASE;
-	return (dma_addr_t)addr;
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-	enum dma_data_direction direction)
-{
-	switch (direction) {
-	case DMA_TO_DEVICE:
-		break;
-
-	case DMA_FROM_DEVICE:
-		break;
-
-	case DMA_BIDIRECTIONAL:
-		break;
-
-	default:
-		BUG();
-	}
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	enum dma_data_direction direction)
-{
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	for (i = 0; i < nents; i++, sg++) {
-		unsigned long addr;
-
-		addr = (unsigned long) page_address(sg->page)+sg->offset;
-		if (addr)
-			__dma_sync(addr, sg->length, direction);
-		addr = __pa(addr)&RAM_OFFSET_MASK;
-		if(dev == NULL)
-			addr +=  CRIME_HI_MEM_BASE;
-		sg->dma_address = (dma_addr_t)addr;
-	}
-
-	return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	addr = (unsigned long) page_address(page) + offset;
-	dma_cache_wback_inv(addr, size);
-	addr = __pa(addr)&RAM_OFFSET_MASK;
-	if(dev == NULL)
-		addr +=  CRIME_HI_MEM_BASE;
-
-	return (dma_addr_t)addr;
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-	enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	if (direction != DMA_TO_DEVICE) {
-		unsigned long addr;
-
-		dma_address&=RAM_OFFSET_MASK;
-		addr = dma_address + PAGE_OFFSET;
-		if(dma_address>=256*1024*1024)
-			addr+=CRIME_HI_MEM_BASE;
-		dma_cache_wback_inv(addr, size);
-	}
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	enum dma_data_direction direction)
-{
-	unsigned long addr;
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	if (direction == DMA_TO_DEVICE)
-		return;
-
-	for (i = 0; i < nhwentries; i++, sg++) {
-		addr = (unsigned long) page_address(sg->page);
-		if (!addr)
-			continue;
-		dma_cache_wback_inv(addr + sg->offset, sg->length);
-	}
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-	size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	dma_handle&=RAM_OFFSET_MASK;
-	addr = dma_handle + PAGE_OFFSET;
-	if(dma_handle>=256*1024*1024)
-	    addr+=CRIME_HI_MEM_BASE;
-	__dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-	size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	dma_handle&=RAM_OFFSET_MASK;
-	addr = dma_handle + PAGE_OFFSET;
-	if(dma_handle>=256*1024*1024)
-	    addr+=CRIME_HI_MEM_BASE;
-	__dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	dma_handle&=RAM_OFFSET_MASK;
-	addr = dma_handle + offset + PAGE_OFFSET;
-	if(dma_handle>=256*1024*1024)
-	    addr+=CRIME_HI_MEM_BASE;
-	__dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	dma_handle&=RAM_OFFSET_MASK;
-	addr = dma_handle + offset + PAGE_OFFSET;
-	if(dma_handle>=256*1024*1024)
-	    addr+=CRIME_HI_MEM_BASE;
-	__dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-	enum dma_data_direction direction)
-{
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	/* Make sure that gcc doesn't leave the empty loop body.  */
-	for (i = 0; i < nelems; i++, sg++)
-		__dma_sync((unsigned long)page_address(sg->page),
-		           sg->length, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-	enum dma_data_direction direction)
-{
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	/* Make sure that gcc doesn't leave the empty loop body.  */
-	for (i = 0; i < nelems; i++, sg++)
-		__dma_sync((unsigned long)page_address(sg->page),
-		           sg->length, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
-	/*
-	 * we fall back to GFP_DMA when the mask isn't all 1s,
-	 * so we can't guarantee allocations that must be
-	 * within a tighter range than GFP_DMA..
-	 */
-	if (mask < 0x00ffffff)
-		return 0;
-
-	return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
-	return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-	enum dma_data_direction direction)
-{
-	if (direction == DMA_NONE)
-		return;
-
-	dma_cache_wback_inv((unsigned long)vaddr, size);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c
deleted file mode 100644
index 8cecef0..0000000
--- a/arch/mips/mm/dma-noncoherent.c
+++ /dev/null
@@ -1,370 +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) 2000  Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-
-/*
- * Warning on the terminology - Linux calls an uncached area coherent;
- * MIPS terminology calls memory areas with hardware maintained coherency
- * coherent.
- */
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, gfp_t gfp)
-{
-	void *ret;
-	/* ignore region specifiers */
-	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
-		gfp |= GFP_DMA;
-	ret = (void *) __get_free_pages(gfp, get_order(size));
-
-	if (ret != NULL) {
-		memset(ret, 0, size);
-		*dma_handle = virt_to_phys(ret);
-	}
-
-	return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_noncoherent);
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, gfp_t gfp)
-{
-	void *ret;
-
-	ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
-	if (ret) {
-		dma_cache_wback_inv((unsigned long) ret, size);
-		ret = UNCAC_ADDR(ret);
-	}
-
-	return ret;
-}
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
-	dma_addr_t dma_handle)
-{
-	free_pages((unsigned long) vaddr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_noncoherent);
-
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
-	dma_addr_t dma_handle)
-{
-	unsigned long addr = (unsigned long) vaddr;
-
-	addr = CAC_ADDR(addr);
-	free_pages(addr, get_order(size));
-}
-
-EXPORT_SYMBOL(dma_free_coherent);
-
-static inline void __dma_sync(unsigned long addr, size_t size,
-	enum dma_data_direction direction)
-{
-	switch (direction) {
-	case DMA_TO_DEVICE:
-		dma_cache_wback(addr, size);
-		break;
-
-	case DMA_FROM_DEVICE:
-		dma_cache_inv(addr, size);
-		break;
-
-	case DMA_BIDIRECTIONAL:
-		dma_cache_wback_inv(addr, size);
-		break;
-
-	default:
-		BUG();
-	}
-}
-
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-	enum dma_data_direction direction)
-{
-	unsigned long addr = (unsigned long) ptr;
-
-	__dma_sync(addr, size, direction);
-
-	return virt_to_phys(ptr);
-}
-
-EXPORT_SYMBOL(dma_map_single);
-
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-	enum dma_data_direction direction)
-{
-	unsigned long addr;
-	addr = dma_addr + PAGE_OFFSET;
-
-	//__dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_unmap_single);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	enum dma_data_direction direction)
-{
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	for (i = 0; i < nents; i++, sg++) {
-		unsigned long addr;
-
-		addr = (unsigned long) page_address(sg->page);
-		if (addr) {
-			__dma_sync(addr + sg->offset, sg->length, direction);
-			sg->dma_address = (dma_addr_t)page_to_phys(sg->page)
-					  + sg->offset;
-		}
-	}
-
-	return nents;
-}
-
-EXPORT_SYMBOL(dma_map_sg);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	addr = (unsigned long) page_address(page) + offset;
-	dma_cache_wback_inv(addr, size);
-
-	return page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(dma_map_page);
-
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-	enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	if (direction != DMA_TO_DEVICE) {
-		unsigned long addr;
-
-		addr = dma_address + PAGE_OFFSET;
-		dma_cache_wback_inv(addr, size);
-	}
-}
-
-EXPORT_SYMBOL(dma_unmap_page);
-
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	enum dma_data_direction direction)
-{
-	unsigned long addr;
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	if (direction == DMA_TO_DEVICE)
-		return;
-
-	for (i = 0; i < nhwentries; i++, sg++) {
-		addr = (unsigned long) page_address(sg->page);
-		if (addr)
-			__dma_sync(addr + sg->offset, sg->length, direction);
-	}
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-	size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	addr = dma_handle + PAGE_OFFSET;
-	__dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-	size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	addr = dma_handle + PAGE_OFFSET;
-	__dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	addr = dma_handle + offset + PAGE_OFFSET;
-	__dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
-	unsigned long offset, size_t size, enum dma_data_direction direction)
-{
-	unsigned long addr;
-
-	BUG_ON(direction == DMA_NONE);
-
-	addr = dma_handle + offset + PAGE_OFFSET;
-	__dma_sync(addr, size, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-	enum dma_data_direction direction)
-{
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	/* Make sure that gcc doesn't leave the empty loop body.  */
-	for (i = 0; i < nelems; i++, sg++)
-		__dma_sync((unsigned long)page_address(sg->page),
-		           sg->length, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-	enum dma_data_direction direction)
-{
-	int i;
-
-	BUG_ON(direction == DMA_NONE);
-
-	/* Make sure that gcc doesn't leave the empty loop body.  */
-	for (i = 0; i < nelems; i++, sg++)
-		__dma_sync((unsigned long)page_address(sg->page),
-		           sg->length, direction);
-}
-
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-int dma_mapping_error(dma_addr_t dma_addr)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(dma_mapping_error);
-
-int dma_supported(struct device *dev, u64 mask)
-{
-	/*
-	 * we fall back to GFP_DMA when the mask isn't all 1s,
-	 * so we can't guarantee allocations that must be
-	 * within a tighter range than GFP_DMA..
-	 */
-	if (mask < 0x00ffffff)
-		return 0;
-
-	return 1;
-}
-
-EXPORT_SYMBOL(dma_supported);
-
-int dma_is_consistent(struct device *dev, dma_addr_t dma_addr)
-{
-	return 1;
-}
-
-EXPORT_SYMBOL(dma_is_consistent);
-
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-	enum dma_data_direction direction)
-{
-	if (direction == DMA_NONE)
-		return;
-
-	dma_cache_wback_inv((unsigned long)vaddr, size);
-}
-
-EXPORT_SYMBOL(dma_cache_sync);
-
-/* The DAC routines are a PCIism.. */
-
-#ifdef CONFIG_PCI
-
-#include <linux/pci.h>
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
-	struct page *page, unsigned long offset, int direction)
-{
-	return (dma64_addr_t)page_to_phys(page) + offset;
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
-	dma64_addr_t dma_addr)
-{
-	return mem_map + (dma_addr >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
-	dma64_addr_t dma_addr)
-{
-	return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-
-	dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
-	dma64_addr_t dma_addr, size_t len, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-
-	dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
-
-#endif /* CONFIG_PCI */
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 125a4a8..f08ae71c 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -61,8 +61,6 @@
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
-unsigned long highstart_pfn, highend_pfn;
-
 /*
  * We have up to 8 empty zeroed pages so we can map one of the right colour
  * when needed.  This is necessary only on R4000 / R4400 SC and MC versions
@@ -261,6 +259,8 @@
 
 
 #ifdef CONFIG_HIGHMEM
+unsigned long highstart_pfn, highend_pfn;
+
 pte_t *kmap_pte;
 pgprot_t kmap_prot;
 
@@ -314,8 +314,6 @@
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-extern void pagetable_init(void);
-
 static int __init page_is_ram(unsigned long pagenr)
 {
 	int i;
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c
index fc2c96f..cea7d0e 100644
--- a/arch/mips/mm/ioremap.c
+++ b/arch/mips/mm/ioremap.c
@@ -6,13 +6,98 @@
  * (C) Copyright 1995 1996 Linus Torvalds
  * (C) Copyright 2001, 2002 Ralf Baechle
  */
-#include <linux/mm.h>
 #include <linux/module.h>
 #include <asm/addrspace.h>
 #include <asm/byteorder.h>
 
 #include <linux/vmalloc.h>
-#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/tlbflush.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address,
+	phys_t size, phys_t phys_addr, unsigned long flags)
+{
+	phys_t end;
+	unsigned long pfn;
+	pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
+	                           | __WRITEABLE | flags);
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	if (address >= end)
+		BUG();
+	pfn = phys_addr >> PAGE_SHIFT;
+	do {
+		if (!pte_none(*pte)) {
+			printk("remap_area_pte: page already exists\n");
+			BUG();
+		}
+		set_pte(pte, pfn_pte(pfn, pgprot));
+		address += PAGE_SIZE;
+		pfn++;
+		pte++;
+	} while (address && (address < end));
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
+	phys_t size, phys_t phys_addr, unsigned long flags)
+{
+	phys_t end;
+
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	if (address >= end)
+		BUG();
+	do {
+		pte_t * pte = pte_alloc_kernel(pmd, address);
+		if (!pte)
+			return -ENOMEM;
+		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address && (address < end));
+	return 0;
+}
+
+static int remap_area_pages(unsigned long address, phys_t phys_addr,
+	phys_t size, unsigned long flags)
+{
+	int error;
+	pgd_t * dir;
+	unsigned long end = address + size;
+
+	phys_addr -= address;
+	dir = pgd_offset(&init_mm, address);
+	flush_cache_all();
+	if (address >= end)
+		BUG();
+	do {
+		pud_t *pud;
+		pmd_t *pmd;
+
+		error = -ENOMEM;
+		pud = pud_alloc(&init_mm, dir, address);
+		if (!pud)
+			break;
+		pmd = pmd_alloc(&init_mm, pud, address);
+		if (!pmd)
+			break;
+		if (remap_area_pmd(pmd, address, end - address,
+					 phys_addr + address, flags))
+			break;
+		error = 0;
+		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	} while (address && (address < end));
+	flush_tlb_all();
+	return error;
+}
 
 /*
  * Generic mapping function (not visible outside):
@@ -36,7 +121,6 @@
 	unsigned long offset;
 	phys_t last_addr;
 	void * addr;
-	pgprot_t pgprot;
 
 	phys_addr = fixup_bigphys_addr(phys_addr, size);
 
@@ -68,9 +152,6 @@
 				return NULL;
 	}
 
-	pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
-			  | __WRITEABLE | flags);
-
 	/*
 	 * Mappings have to be page-aligned
 	 */
@@ -85,8 +166,7 @@
 	if (!area)
 		return NULL;
 	addr = area->addr;
-	if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
-			       phys_addr, pgprot)) {
+	if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
 		vunmap(addr);
 		return NULL;
 	}
diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c
index 4a61e62..575e401 100644
--- a/arch/mips/mm/pgtable-32.c
+++ b/arch/mips/mm/pgtable-32.c
@@ -11,6 +11,7 @@
 #include <linux/highmem.h>
 #include <asm/fixmap.h>
 #include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 
 void pgd_init(unsigned long page)
 {
diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c
index c46eb65..e4b565a 100644
--- a/arch/mips/mm/pgtable-64.c
+++ b/arch/mips/mm/pgtable-64.c
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <asm/fixmap.h>
 #include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 
 void pgd_init(unsigned long page)
 {
diff --git a/arch/mips/momentum/jaguar_atx/platform.c b/arch/mips/momentum/jaguar_atx/platform.c
index 035ea51..3df36ed 100644
--- a/arch/mips/momentum/jaguar_atx/platform.c
+++ b/arch/mips/momentum/jaguar_atx/platform.c
@@ -38,8 +38,6 @@
 #define MV64x60_IRQ_ETH_1 49
 #define MV64x60_IRQ_ETH_2 50
 
-#ifdef CONFIG_MV643XX_ETH_0
-
 static struct resource mv64x60_eth0_resources[] = {
 	[0] = {
 		.name	= "eth0 irq",
@@ -72,9 +70,6 @@
 		.platform_data = &eth0_pd,
 	},
 };
-#endif /* CONFIG_MV643XX_ETH_0 */
-
-#ifdef CONFIG_MV643XX_ETH_1
 
 static struct resource mv64x60_eth1_resources[] = {
 	[0] = {
@@ -108,9 +103,6 @@
 		.platform_data = &eth1_pd,
 	},
 };
-#endif /* CONFIG_MV643XX_ETH_1 */
-
-#ifdef CONFIG_MV643XX_ETH_2
 
 static struct resource mv64x60_eth2_resources[] = {
 	[0] = {
@@ -129,26 +121,19 @@
 
 static struct platform_device eth2_device = {
 	.name		= MV643XX_ETH_NAME,
-	.id		= 1,
+	.id		= 2,
 	.num_resources	= ARRAY_SIZE(mv64x60_eth2_resources),
 	.resource	= mv64x60_eth2_resources,
 	.dev = {
 		.platform_data = &eth2_pd,
 	},
 };
-#endif /* CONFIG_MV643XX_ETH_2 */
 
 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
 	&mv643xx_eth_shared_device,
-#ifdef CONFIG_MV643XX_ETH_0
 	&eth0_device,
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
 	&eth1_device,
-#endif
-#ifdef CONFIG_MV643XX_ETH_2
 	&eth2_device,
-#endif
 };
 
 static u8 __init exchange_bit(u8 val, u8 cs)
@@ -215,15 +200,9 @@
 	int ret;
 
 	get_mac(mac);
-#ifdef CONFIG_MV643XX_ETH_0
-	eth_mac_add(eth1_mac_addr, mac, 0);
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
+	eth_mac_add(eth0_mac_addr, mac, 0);
 	eth_mac_add(eth1_mac_addr, mac, 1);
-#endif
-#ifdef CONFIG_MV643XX_ETH_2
 	eth_mac_add(eth2_mac_addr, mac, 2);
-#endif
 	ret = platform_add_devices(mv643xx_eth_pd_devs,
 			ARRAY_SIZE(mv643xx_eth_pd_devs));
 
diff --git a/arch/mips/momentum/ocelot_3/platform.c b/arch/mips/momentum/ocelot_3/platform.c
index eefe584..024aef2 100644
--- a/arch/mips/momentum/ocelot_3/platform.c
+++ b/arch/mips/momentum/ocelot_3/platform.c
@@ -38,8 +38,6 @@
 #define MV64x60_IRQ_ETH_1 49
 #define MV64x60_IRQ_ETH_2 50
 
-#ifdef CONFIG_MV643XX_ETH_0
-
 static struct resource mv64x60_eth0_resources[] = {
 	[0] = {
 		.name	= "eth0 irq",
@@ -72,9 +70,6 @@
 		.platform_data = &eth0_pd,
 	},
 };
-#endif /* CONFIG_MV643XX_ETH_0 */
-
-#ifdef CONFIG_MV643XX_ETH_1
 
 static struct resource mv64x60_eth1_resources[] = {
 	[0] = {
@@ -108,9 +103,6 @@
 		.platform_data = &eth1_pd,
 	},
 };
-#endif /* CONFIG_MV643XX_ETH_1 */
-
-#ifdef CONFIG_MV643XX_ETH_2
 
 static struct resource mv64x60_eth2_resources[] = {
 	[0] = {
@@ -129,26 +121,19 @@
 
 static struct platform_device eth2_device = {
 	.name		= MV643XX_ETH_NAME,
-	.id		= 1,
+	.id		= 2,
 	.num_resources	= ARRAY_SIZE(mv64x60_eth2_resources),
 	.resource	= mv64x60_eth2_resources,
 	.dev = {
 		.platform_data = &eth2_pd,
 	},
 };
-#endif /* CONFIG_MV643XX_ETH_2 */
 
 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
 	&mv643xx_eth_shared_device,
-#ifdef CONFIG_MV643XX_ETH_0
 	&eth0_device,
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
 	&eth1_device,
-#endif
-#ifdef CONFIG_MV643XX_ETH_2
 	&eth2_device,
-#endif
 };
 
 static u8 __init exchange_bit(u8 val, u8 cs)
@@ -215,15 +200,9 @@
 	int ret;
 
 	get_mac(mac);
-#ifdef CONFIG_MV643XX_ETH_0
-	eth_mac_add(eth1_mac_addr, mac, 0);
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
+	eth_mac_add(eth0_mac_addr, mac, 0);
 	eth_mac_add(eth1_mac_addr, mac, 1);
-#endif
-#ifdef CONFIG_MV643XX_ETH_2
 	eth_mac_add(eth2_mac_addr, mac, 2);
-#endif
 	ret = platform_add_devices(mv643xx_eth_pd_devs,
 			ARRAY_SIZE(mv643xx_eth_pd_devs));
 
diff --git a/arch/mips/momentum/ocelot_c/platform.c b/arch/mips/momentum/ocelot_c/platform.c
index 6c495b2..fac8b24 100644
--- a/arch/mips/momentum/ocelot_c/platform.c
+++ b/arch/mips/momentum/ocelot_c/platform.c
@@ -37,8 +37,6 @@
 #define MV64x60_IRQ_ETH_0 48
 #define MV64x60_IRQ_ETH_1 49
 
-#ifdef CONFIG_MV643XX_ETH_0
-
 static struct resource mv64x60_eth0_resources[] = {
 	[0] = {
 		.name	= "eth0 irq",
@@ -71,9 +69,6 @@
 		.platform_data = &eth0_pd,
 	},
 };
-#endif /* CONFIG_MV643XX_ETH_0 */
-
-#ifdef CONFIG_MV643XX_ETH_1
 
 static struct resource mv64x60_eth1_resources[] = {
 	[0] = {
@@ -107,16 +102,11 @@
 		.platform_data = &eth1_pd,
 	},
 };
-#endif /* CONFIG_MV643XX_ETH_1 */
 
 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
 	&mv643xx_eth_shared_device,
-#ifdef CONFIG_MV643XX_ETH_0
 	&eth0_device,
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
 	&eth1_device,
-#endif
 	/* The third port is not wired up on the Ocelot C */
 };
 
@@ -184,12 +174,8 @@
 	int ret;
 
 	get_mac(mac);
-#ifdef CONFIG_MV643XX_ETH_0
-	eth_mac_add(eth1_mac_addr, mac, 0);
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
+	eth_mac_add(eth0_mac_addr, mac, 0);
 	eth_mac_add(eth1_mac_addr, mac, 1);
-#endif
 	ret = platform_add_devices(mv643xx_eth_pd_devs,
 			ARRAY_SIZE(mv643xx_eth_pd_devs));
 
diff --git a/arch/mips/oprofile/Kconfig b/arch/mips/oprofile/Kconfig
index ca395ef..fb6f235 100644
--- a/arch/mips/oprofile/Kconfig
+++ b/arch/mips/oprofile/Kconfig
@@ -11,7 +11,7 @@
 
 config OPROFILE
 	tristate "OProfile system profiling (EXPERIMENTAL)"
-	depends on PROFILING && !!MIPS_MT_SMTC && EXPERIMENTAL
+	depends on PROFILING && !MIPS_MT_SMTC && EXPERIMENTAL
 	help
 	  OProfile is a profiling system capable of profiling the
 	  whole system, include the kernel, kernel modules, libraries,
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 82b20c2..bf85995 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the PCI specific kernel interface routines under Linux.
 #
 
-obj-y				+= pci.o
+obj-y				+= pci.o pci-dac.o
 
 #
 # PCI bus host bridge specific code
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
index a176f2c..0c9a473 100644
--- a/arch/mips/pci/fixup-sni.c
+++ b/arch/mips/pci/fixup-sni.c
@@ -15,7 +15,7 @@
 #include <asm/sni.h>
 
 /*
- * Shortcuts ...
+ * PCIMT Shortcuts ...
  */
 #define SCSI	PCIMT_IRQ_SCSI
 #define ETH	PCIMT_IRQ_ETHERNET
@@ -67,6 +67,50 @@
 	{     0, INTD, INTA, INTB, INTC },	/* Slot 4 */
 };
 
+static char irq_tab_rm300e[5][5] __initdata = {
+	/*       INTA  INTB  INTC  INTD */
+	{     0,    0,    0,    0,    0 },	/* HOST bridge */
+	{  SCSI, SCSI, SCSI, SCSI, SCSI },	/* SCSI */
+	{     0, INTC, INTD, INTA, INTB },	/* Bridge/i960 */
+	{     0, INTD, INTA, INTB, INTC },	/* Slot 1 */
+	{     0, INTA, INTB, INTC, INTD },	/* Slot 2 */
+};
+#undef SCSI
+#undef ETH
+#undef INTA
+#undef INTB
+#undef INTC
+#undef INTD
+
+
+/*
+ * PCIT Shortcuts ...
+ */
+#define SCSI0	PCIT_IRQ_SCSI0
+#define SCSI1	PCIT_IRQ_SCSI1
+#define ETH	PCIT_IRQ_ETHERNET
+#define INTA	PCIT_IRQ_INTA
+#define INTB	PCIT_IRQ_INTB
+#define INTC	PCIT_IRQ_INTC
+#define INTD	PCIT_IRQ_INTD
+
+static char irq_tab_pcit[13][5] __initdata = {
+	/*       INTA  INTB  INTC  INTD */
+	{     0,     0,     0,     0,     0 },	/* HOST bridge */
+	{ SCSI0, SCSI0, SCSI0, SCSI0, SCSI0 },	/* SCSI */
+	{ SCSI1, SCSI1, SCSI1, SCSI1, SCSI1 },	/* SCSI */
+	{   ETH,   ETH,   ETH,   ETH,   ETH },	/* Ethernet */
+	{     0,  INTA,  INTB,  INTC,  INTD },	/* PCI-PCI bridge */
+	{     0,     0,     0,     0,     0 },	/* Unused */
+	{     0,     0,     0,     0,     0 },	/* Unused */
+	{     0,     0,     0,     0,     0 },	/* Unused */
+	{     0,  INTA,  INTB,  INTC,  INTD },	/* Slot 1 */
+	{     0,  INTB,  INTC,  INTD,  INTA },	/* Slot 2 */
+	{     0,  INTC,  INTD,  INTA,  INTB },	/* Slot 3 */
+	{     0,  INTD,  INTA,  INTB,  INTC },	/* Slot 4 */
+	{     0,  INTA,  INTB,  INTC,  INTD },	/* Slot 5 */
+};
+
 static inline int is_rm300_revd(void)
 {
 	unsigned char csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
@@ -76,10 +120,24 @@
 
 int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	if (is_rm300_revd())
-		return irq_tab_rm300d[slot][pin];
+	switch (sni_brd_type) {
+	case SNI_BRD_PCI_TOWER:
+	case SNI_BRD_PCI_TOWER_CPLUS:
+	        return irq_tab_pcit[slot][pin];
 
-	return irq_tab_rm200[slot][pin];
+	case SNI_BRD_PCI_MTOWER:
+	        if (is_rm300_revd())
+		        return irq_tab_rm300d[slot][pin];
+	        /* fall through */
+
+	case SNI_BRD_PCI_DESKTOP:
+	        return irq_tab_rm200[slot][pin];
+
+	case SNI_BRD_PCI_MTOWER_CPLUS:
+	        return irq_tab_rm300e[slot][pin];
+	}
+
+	return 0;
 }
 
 /* Do platform specific device initialization at pci_enable_device() time */
diff --git a/arch/mips/pci/ops-sni.c b/arch/mips/pci/ops-sni.c
index 2b0ccd6..fa2d2c6 100644
--- a/arch/mips/pci/ops-sni.c
+++ b/arch/mips/pci/ops-sni.c
@@ -83,7 +83,82 @@
 	return 0;
 }
 
-struct pci_ops sni_pci_ops = {
+struct pci_ops sni_pcimt_ops = {
 	.read = pcimt_read,
 	.write = pcimt_write,
 };
+
+static int pcit_set_config_address(unsigned int busno, unsigned int devfn, int reg)
+{
+	if ((devfn > 255) || (reg > 255) || (busno > 255))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	outl ((1 << 31) | ((busno & 0xff) << 16) | ((devfn & 0xff) << 8) | (reg & 0xfc), 0xcf8);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pcit_read(struct pci_bus *bus, unsigned int devfn, int reg,
+		      int size, u32 * val)
+{
+	int res;
+
+	/*
+	 * on bus 0 we need to check, whether there is a device answering
+	 * for the devfn by doing a config write and checking the result. If
+	 * we don't do it, we will get a data bus error
+	 */
+	if (bus->number == 0) {
+		pcit_set_config_address (0, 0, 0x68);
+		outl (inl (0xcfc) | 0xc0000000, 0xcfc);
+		if ((res = pcit_set_config_address(0, devfn, 0)))
+			return res;
+		outl (0xffffffff, 0xcfc);
+		pcit_set_config_address (0, 0, 0x68);
+		if (inl(0xcfc) & 0x100000)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+	if ((res = pcit_set_config_address(bus->number, devfn, reg)))
+		return res;
+
+	switch (size) {
+	case 1:
+		*val = inb(PCIMT_CONFIG_DATA + (reg & 3));
+		break;
+	case 2:
+		*val = inw(PCIMT_CONFIG_DATA + (reg & 2));
+		break;
+	case 4:
+		*val = inl(PCIMT_CONFIG_DATA);
+		break;
+	}
+	return 0;
+}
+
+static int pcit_write(struct pci_bus *bus, unsigned int devfn, int reg,
+		       int size, u32 val)
+{
+	int res;
+
+	if ((res = pcit_set_config_address(bus->number, devfn, reg)))
+		return res;
+
+	switch (size) {
+	case 1:
+		outb (val, PCIMT_CONFIG_DATA + (reg & 3));
+		break;
+	case 2:
+		outw (val, PCIMT_CONFIG_DATA + (reg & 2));
+		break;
+	case 4:
+		outl (val, PCIMT_CONFIG_DATA);
+		break;
+	}
+
+	return 0;
+}
+
+
+struct pci_ops sni_pcit_ops = {
+	.read = pcit_read,
+	.write = pcit_write,
+};
diff --git a/arch/mips/pci/pci-dac.c b/arch/mips/pci/pci-dac.c
new file mode 100644
index 0000000..0f0ea1b
--- /dev/null
+++ b/arch/mips/pci/pci-dac.c
@@ -0,0 +1,79 @@
+/*
+ * 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  Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001, 06  Ralf Baechle <ralf@linux-mips.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+
+#include <dma-coherence.h>
+
+#include <linux/pci.h>
+
+dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+	struct page *page, unsigned long offset, int direction)
+{
+	struct device *dev = &pdev->dev;
+
+	BUG_ON(direction == DMA_NONE);
+
+	if (!plat_device_is_coherent(dev)) {
+		unsigned long addr;
+
+		addr = (unsigned long) page_address(page) + offset;
+		dma_cache_wback_inv(addr, PAGE_SIZE);
+	}
+
+	return plat_map_dma_mem_page(dev, page) + offset;
+}
+
+EXPORT_SYMBOL(pci_dac_page_to_dma);
+
+struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+	dma64_addr_t dma_addr)
+{
+	return pfn_to_page(plat_dma_addr_to_phys(dma_addr) >> PAGE_SHIFT);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_page);
+
+unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+	dma64_addr_t dma_addr)
+{
+	return dma_addr & ~PAGE_MASK;
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_offset);
+
+void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
+	dma64_addr_t dma_addr, size_t len, int direction)
+{
+	BUG_ON(direction == PCI_DMA_NONE);
+
+	if (!plat_device_is_coherent(&pdev->dev))
+		dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
+
+void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
+	dma64_addr_t dma_addr, size_t len, int direction)
+{
+	BUG_ON(direction == PCI_DMA_NONE);
+
+	if (!plat_device_is_coherent(&pdev->dev))
+		dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 5ace3686..697a7e4 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -79,6 +79,14 @@
 {
 	*hose_tail = hose;
 	hose_tail = &hose->next;
+
+	/*
+	 * Do not panic here but later - this might hapen before console init.
+	 */
+	if (!hose->io_map_base) {
+		printk(KERN_WARNING
+		       "registering PCI controller with io_map_base unset\n");
+	}
 }
 
 /* Most MIPS systems have straight-forward swizzling needs.  */
diff --git a/arch/mips/philips/pnx8550/common/proc.c b/arch/mips/philips/pnx8550/common/proc.c
index 72a0167..3f09755 100644
--- a/arch/mips/philips/pnx8550/common/proc.c
+++ b/arch/mips/philips/pnx8550/common/proc.c
@@ -79,10 +79,7 @@
 
 	// Create /proc/pnx8550
         pnx8550_dir = create_proc_entry("pnx8550", S_IFDIR|S_IRUGO, NULL);
-        if (pnx8550_dir){
-                pnx8550_dir->nlink = 1;
-        }
-        else {
+        if (!pnx8550_dir) {
                 printk(KERN_ERR "Can't create pnx8550 proc dir\n");
                 return -1;
         }
@@ -90,7 +87,6 @@
 	// Create /proc/pnx8550/timers
         pnx8550_timers = create_proc_entry("timers", S_IFREG|S_IRUGO, pnx8550_dir );
         if (pnx8550_timers){
-                pnx8550_timers->nlink = 1;
                 pnx8550_timers->read_proc = pnx8550_timers_read;
         }
         else {
@@ -100,7 +96,6 @@
 	// Create /proc/pnx8550/registers
         pnx8550_registers = create_proc_entry("registers", S_IFREG|S_IRUGO, pnx8550_dir );
         if (pnx8550_registers){
-                pnx8550_registers->nlink = 1;
                 pnx8550_registers->read_proc = pnx8550_registers_read;
         }
         else {
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index 0e3d535..fe8a106 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -21,6 +21,7 @@
 #include <linux/pfn.h>
 #include <linux/highmem.h>
 #include <asm/page.h>
+#include <asm/pgalloc.h>
 #include <asm/sections.h>
 
 #include <asm/sn/arch.h>
@@ -503,7 +504,6 @@
 	/* We got nothing to free here ...  */
 }
 
-extern void pagetable_init(void);
 extern unsigned long setup_zero_pages(void);
 
 void __init paging_init(void)
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index 9ce5136..8c3c78c 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -190,7 +190,7 @@
 };
 
 static struct irqaction rt_irqaction = {
-	.handler	= ip27_rt_timer_interrupt,
+	.handler	= (irq_handler_t) ip27_rt_timer_interrupt,
 	.flags		= IRQF_DISABLED,
 	.mask		= CPU_MASK_NONE,
 	.name		= "timer"
diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
index d1a906e..212547c 100644
--- a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
+++ b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
@@ -374,7 +374,7 @@
 	return error;
 }
 
-static struct file_operations sbprof_tb_fops = {
+static const struct file_operations sbprof_tb_fops = {
 	.owner		= THIS_MODULE,
 	.open		= sbprof_tb_open,
 	.release	= sbprof_tb_release,
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index a5eb0ad..e30809a 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the SNI specific part of the kernel
 #
 
-obj-y	 	+= irq.o pcimt_scache.o reset.o setup.o
+obj-y += irq.o reset.o setup.o ds1216.o a20r.o rm200.o pcimt.o pcit.o time.o
 obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
new file mode 100644
index 0000000..31ab80f
--- /dev/null
+++ b/arch/mips/sni/a20r.c
@@ -0,0 +1,227 @@
+/*
+ * A20R specific code
+ *
+ * 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 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <asm/sni.h>
+#include <asm/time.h>
+#include <asm/ds1216.h>
+
+#define PORT(_base,_irq)				\
+	{						\
+		.iobase		= _base,		\
+		.irq		= _irq,			\
+		.uartclk	= 1843200,		\
+		.iotype		= UPIO_PORT,		\
+		.flags		= UPF_BOOT_AUTOCONF,	\
+	}
+
+static struct plat_serial8250_port a20r_data[] = {
+	PORT(0x3f8, 4),
+	PORT(0x2f8, 3),
+	{ },
+};
+
+static struct platform_device a20r_serial8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= a20r_data,
+	},
+};
+
+static struct resource snirm_82596_rsrc[] = {
+	{
+		.start = 0xb8000000,
+		.end   = 0xb8000004,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 0xb8010000,
+		.end   = 0xb8010004,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 0xbff00000,
+		.end   = 0xbff00020,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 22,
+		.end   = 22,
+		.flags = IORESOURCE_IRQ
+	},
+	{
+		.flags = 0x01                /* 16bit mpu port access */
+	}
+};
+
+static struct platform_device snirm_82596_pdev = {
+	.name           = "snirm_82596",
+	.num_resources  = ARRAY_SIZE(snirm_82596_rsrc),
+	.resource       = snirm_82596_rsrc
+};
+
+static struct resource snirm_53c710_rsrc[] = {
+	{
+		.start = 0xb9000000,
+		.end   = 0xb90fffff,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 19,
+		.end   = 19,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device snirm_53c710_pdev = {
+	.name           = "snirm_53c710",
+	.num_resources  = ARRAY_SIZE(snirm_53c710_rsrc),
+	.resource       = snirm_53c710_rsrc
+};
+
+static struct resource sc26xx_rsrc[] = {
+	{
+		.start = 0xbc070000,
+		.end   = 0xbc0700ff,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 20,
+		.end   = 20,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device sc26xx_pdev = {
+	.name           = "SC26xx",
+	.num_resources  = ARRAY_SIZE(sc26xx_rsrc),
+	.resource       = sc26xx_rsrc
+};
+
+static u32 a20r_ack_hwint(void)
+{
+	u32 status = read_c0_status();
+
+	write_c0_status (status | 0x00010000);
+	asm volatile(
+	"	.set	push			\n"
+	"	.set	noat			\n"
+	"	.set	noreorder		\n"
+	"	lw	$1, 0(%0)		\n"
+	"	sb	$0, 0(%1)		\n"
+	"	sync				\n"
+	"	lb	%1, 0(%1)		\n"
+	"	b	1f			\n"
+	"	ori	%1, $1, 2		\n"
+	"	.align	8			\n"
+	"1:					\n"
+	"	nop				\n"
+	"	sw	%1, 0(%0)		\n"
+	"	sync				\n"
+	"	li	%1, 0x20		\n"
+	"2:					\n"
+	"	nop				\n"
+	"	bnez	%1,2b			\n"
+	"	addiu	%1, -1			\n"
+	"	sw	$1, 0(%0)		\n"
+	"	sync				\n"
+		".set   pop			\n"
+	:
+	: "Jr" (PCIMT_UCONF), "Jr" (0xbc000000));
+	write_c0_status(status);
+
+	return status;
+}
+
+static inline void unmask_a20r_irq(unsigned int irq)
+{
+	set_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE));
+	irq_enable_hazard();
+}
+
+static inline void mask_a20r_irq(unsigned int irq)
+{
+	clear_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE));
+	irq_disable_hazard();
+}
+
+static void end_a20r_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		a20r_ack_hwint();
+		unmask_a20r_irq(irq);
+	}
+}
+
+static struct irq_chip a20r_irq_type = {
+	.typename	= "A20R",
+	.ack		= mask_a20r_irq,
+	.mask		= mask_a20r_irq,
+	.mask_ack	= mask_a20r_irq,
+	.unmask		= unmask_a20r_irq,
+	.end		= end_a20r_irq,
+};
+
+/*
+ * hwint 0 receive all interrupts
+ */
+static void a20r_hwint(void)
+{
+	u32 cause, status;
+	int irq;
+
+	clear_c0_status (IE_IRQ0);
+	status = a20r_ack_hwint();
+	cause = read_c0_cause();
+
+	irq = ffs(((cause & status) >> 8) & 0xf8);
+	if (likely(irq > 0))
+		do_IRQ(SNI_A20R_IRQ_BASE + irq - 1);
+	set_c0_status(IE_IRQ0);
+}
+
+void __init sni_a20r_irq_init(void)
+{
+	int i;
+
+	for (i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8; i++)
+		set_irq_chip(i, &a20r_irq_type);
+	sni_hwint = a20r_hwint;
+	change_c0_status(ST0_IM, IE_IRQ0);
+	setup_irq (SNI_A20R_IRQ_BASE + 3, &sni_isa_irq);
+}
+
+void sni_a20r_init(void)
+{
+	ds1216_base = (volatile unsigned char *) SNI_DS1216_A20R_BASE;
+	rtc_mips_get_time = ds1216_get_cmos_time;
+}
+
+static int __init snirm_a20r_setup_devinit(void)
+{
+	switch (sni_brd_type) {
+	case SNI_BRD_TOWER_OASIC:
+	case SNI_BRD_MINITOWER:
+	        platform_device_register(&snirm_82596_pdev);
+	        platform_device_register(&snirm_53c710_pdev);
+	        platform_device_register(&sc26xx_pdev);
+	        platform_device_register(&a20r_serial8250_device);
+	        break;
+	}
+
+	return 0;
+}
+
+device_initcall(snirm_a20r_setup_devinit);
diff --git a/arch/mips/sni/ds1216.c b/arch/mips/sni/ds1216.c
new file mode 100644
index 0000000..1d92732
--- /dev/null
+++ b/arch/mips/sni/ds1216.c
@@ -0,0 +1,81 @@
+
+#include <linux/bcd.h>
+#include <linux/time.h>
+
+#include <asm/ds1216.h>
+
+volatile unsigned char *ds1216_base;
+
+/*
+ * Read the 64 bit we'd like to have - It a series
+ * of 64 bits showing up in the LSB of the base register.
+ *
+ */
+static unsigned char *ds1216_read(void)
+{
+	static unsigned char	rdbuf[8];
+	unsigned char		c;
+	int			i, j;
+
+	for (i = 0; i < 8; i++) {
+		c = 0x0;
+		for (j = 0; j < 8; j++) {
+			c |= (*ds1216_base & 0x1) << j;
+		}
+		rdbuf[i] = c;
+	}
+
+	return rdbuf;
+}
+
+static void ds1216_switch_ds_to_clock(void)
+{
+	unsigned char magic[] = {
+		0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
+	};
+	int i,j,c;
+
+	/* Reset magic pointer */
+	c = *ds1216_base;
+
+	/* Write 64 bit magic to DS1216 */
+	for (i = 0; i < 8; i++) {
+		c = magic[i];
+		for (j = 0; j < 8; j++) {
+			*ds1216_base = c;
+			c = c >> 1;
+		}
+	}
+}
+
+unsigned long ds1216_get_cmos_time(void)
+{
+	unsigned char	*rdbuf;
+	unsigned int	year, month, date, hour, min, sec;
+
+	ds1216_switch_ds_to_clock();
+	rdbuf = ds1216_read();
+
+	sec = BCD2BIN(DS1216_SEC(rdbuf));
+	min = BCD2BIN(DS1216_MIN(rdbuf));
+	hour = BCD2BIN(DS1216_HOUR(rdbuf));
+	date = BCD2BIN(DS1216_DATE(rdbuf));
+	month = BCD2BIN(DS1216_MONTH(rdbuf));
+	year = BCD2BIN(DS1216_YEAR(rdbuf));
+
+	if (DS1216_1224(rdbuf) && DS1216_AMPM(rdbuf))
+		hour+=12;
+
+	if (year < 70)
+		year += 2000;
+	else
+		year += 1900;
+
+	return mktime(year, month, date, hour, min, sec);
+}
+
+int ds1216_set_rtc_mmss(unsigned long nowtime)
+{
+	printk("ds1216_set_rtc_mmss called but not implemented\n");
+	return -1;
+}
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index 039e8e5..ad5fc47 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 1992 Linus Torvalds
  * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 2006 Thomas Bogendoerfer
  */
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -15,153 +16,35 @@
 #include <asm/i8259.h>
 #include <asm/io.h>
 #include <asm/sni.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
 
-static void enable_pciasic_irq(unsigned int irq)
-{
-	unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
-
-	*(volatile u8 *) PCIMT_IRQSEL |= mask;
-}
-
-void disable_pciasic_irq(unsigned int irq)
-{
-	unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2));
-
-	*(volatile u8 *) PCIMT_IRQSEL &= mask;
-}
-
-static void end_pciasic_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_pciasic_irq(irq);
-}
-
-static struct irq_chip pciasic_irq_type = {
-	.name = "ASIC-PCI",
-	.ack = disable_pciasic_irq,
-	.mask = disable_pciasic_irq,
-	.mask_ack = disable_pciasic_irq,
-	.unmask = enable_pciasic_irq,
-	.end = end_pciasic_irq,
-};
-
-/*
- * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
- * button interrupts.  Later ...
- */
-static void pciasic_hwint0(void)
-{
-	panic("Received int0 but no handler yet ...");
-}
-
-/* This interrupt was used for the com1 console on the first prototypes.  */
-static void pciasic_hwint2(void)
-{
-	/* I think this shouldn't happen on production machines.  */
-	panic("hwint2 and no handler yet");
-}
-
-/* hwint5 is the r4k count / compare interrupt  */
-static void pciasic_hwint5(void)
-{
-	panic("hwint5 and no handler yet");
-}
-
-static unsigned int ls1bit8(unsigned int x)
-{
-	int b = 7, s;
-
-	s = 4; if ((x & 0x0f) == 0) s = 0; b -= s; x <<= s;
-	s = 2; if ((x & 0x30) == 0) s = 0; b -= s; x <<= s;
-	s = 1; if ((x & 0x40) == 0) s = 0; b -= s;
-
-	return b;
-}
-
-/*
- * hwint 1 deals with EISA and SCSI interrupts,
- *
- * The EISA_INT bit in CSITPEND is high active, all others are low active.
- */
-static void pciasic_hwint1(void)
-{
-	u8 pend = *(volatile char *)PCIMT_CSITPEND;
-	unsigned long flags;
-
-	if (pend & IT_EISA) {
-		int irq;
-		/*
-		 * Note: ASIC PCI's builtin interrupt achknowledge feature is
-		 * broken.  Using it may result in loss of some or all i8259
-		 * interupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
-		 */
-		irq = i8259_irq();
-		if (unlikely(irq < 0))
-			return;
-
-		do_IRQ(irq);
-	}
-
-	if (!(pend & IT_SCSI)) {
-		flags = read_c0_status();
-		clear_c0_status(ST0_IM);
-		do_IRQ(PCIMT_IRQ_SCSI);
-		write_c0_status(flags);
-	}
-}
-
-/*
- * hwint 3 should deal with the PCI A - D interrupts,
- */
-static void pciasic_hwint3(void)
-{
-	u8 pend = *(volatile char *)PCIMT_CSITPEND;
-	int irq;
-
-	pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
-	clear_c0_status(IE_IRQ3);
-	irq = PCIMT_IRQ_INT2 + ls1bit8(pend);
-	do_IRQ(irq);
-	set_c0_status(IE_IRQ3);
-}
-
-/*
- * hwint 4 is used for only the onboard PCnet 32.
- */
-static void pciasic_hwint4(void)
-{
-	clear_c0_status(IE_IRQ4);
-	do_IRQ(PCIMT_IRQ_ETHERNET);
-	set_c0_status(IE_IRQ4);
-}
+void (*sni_hwint)(void);
 
 asmlinkage void plat_irq_dispatch(void)
 {
-	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();
-	else if (pending & 0x4000)
-		pciasic_hwint4();
-	else if (pending & 0x2000)
-		pciasic_hwint3();
-	else if (pending & 0x1000)
-		pciasic_hwint2();
-	else if (pending & 0x8000)
-		pciasic_hwint5();
-	else if (pending & 0x0400)
-		pciasic_hwint0();
+	sni_hwint();
 }
 
-void __init init_pciasic(void)
+/* ISA irq handler */
+static irqreturn_t sni_isa_irq_handler(int dummy, void *p)
 {
-	* (volatile u8 *) PCIMT_IRQSEL =
-		IT_EISA | IT_INTA | IT_INTB | IT_INTC | IT_INTD;
+	int irq;
+
+	irq = i8259_irq();
+	if (unlikely(irq < 0))
+		return IRQ_NONE;
+
+	do_IRQ(irq);
+	return IRQ_HANDLED;
 }
 
+struct irqaction sni_isa_irq = {
+	.handler = sni_isa_irq_handler,
+	.name = "ISA",
+	.flags = SA_SHIRQ
+};
+
 /*
  * On systems with i8259-style interrupt controllers we assume for
  * driver compatibility reasons interrupts 0 - 15 to be the i8295
@@ -169,14 +52,31 @@
  */
 void __init arch_init_irq(void)
 {
-	int i;
-
 	init_i8259_irqs();			/* Integrated i8259  */
-	init_pciasic();
+	switch (sni_brd_type) {
+	case SNI_BRD_10:
+	case SNI_BRD_10NEW:
+	case SNI_BRD_TOWER_OASIC:
+	case SNI_BRD_MINITOWER:
+	        sni_a20r_irq_init();
+	        break;
 
-	/* Actually we've got more interrupts to handle ...  */
-	for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++)
-		set_irq_chip(i, &pciasic_irq_type);
+	case SNI_BRD_PCI_TOWER:
+	        sni_pcit_irq_init();
+	        break;
 
-	change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ2|IE_IRQ3|IE_IRQ4);
+	case SNI_BRD_PCI_TOWER_CPLUS:
+	        sni_pcit_cplus_irq_init();
+	        break;
+
+	case SNI_BRD_RM200:
+	        sni_rm200_irq_init();
+	        break;
+
+	case SNI_BRD_PCI_MTOWER:
+	case SNI_BRD_PCI_DESKTOP:
+	case SNI_BRD_PCI_MTOWER_CPLUS:
+	        sni_pcimt_irq_init();
+	        break;
+	}
 }
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
new file mode 100644
index 0000000..6c0dad7
--- /dev/null
+++ b/arch/mips/sni/pcimt.c
@@ -0,0 +1,390 @@
+/*
+ * PCIMT specific code
+ *
+ * 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) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+
+#include <asm/mc146818-time.h>
+#include <asm/sni.h>
+#include <asm/time.h>
+#include <asm/i8259.h>
+#include <asm/irq_cpu.h>
+
+#define cacheconf (*(volatile unsigned int *)PCIMT_CACHECONF)
+#define invspace (*(volatile unsigned int *)PCIMT_INVSPACE)
+
+static void __init sni_pcimt_sc_init(void)
+{
+	unsigned int scsiz, sc_size;
+
+	scsiz = cacheconf & 7;
+	if (scsiz == 0) {
+		printk("Second level cache is deactived.\n");
+		return;
+	}
+	if (scsiz >= 6) {
+		printk("Invalid second level cache size configured, "
+		       "deactivating second level cache.\n");
+		cacheconf = 0;
+		return;
+	}
+
+	sc_size = 128 << scsiz;
+	printk("%dkb second level cache detected, deactivating.\n", sc_size);
+	cacheconf = 0;
+}
+
+
+/*
+ * A bit more gossip about the iron we're running on ...
+ */
+static inline void sni_pcimt_detect(void)
+{
+	char boardtype[80];
+	unsigned char csmsr;
+	char *p = boardtype;
+	unsigned int asic;
+
+	csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
+
+	p += sprintf(p, "%s PCI", (csmsr & 0x80) ? "RM200" : "RM300");
+	if ((csmsr & 0x80) == 0)
+		p += sprintf(p, ", board revision %s",
+		             (csmsr & 0x20) ? "D" : "C");
+	asic = csmsr & 0x80;
+	asic = (csmsr & 0x08) ? asic : !asic;
+	p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1");
+	printk("%s.\n", boardtype);
+}
+
+#define PORT(_base,_irq)				\
+	{						\
+		.iobase		= _base,		\
+		.irq		= _irq,			\
+		.uartclk	= 1843200,		\
+		.iotype		= UPIO_PORT,		\
+		.flags		= UPF_BOOT_AUTOCONF,	\
+	}
+
+static struct plat_serial8250_port pcimt_data[] = {
+	PORT(0x3f8, 4),
+	PORT(0x2f8, 3),
+	{ },
+};
+
+static struct platform_device pcimt_serial8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= pcimt_data,
+	},
+};
+
+static struct resource sni_io_resource = {
+	.start	= 0x00001000UL,
+	.end	= 0x03bfffffUL,
+	.name	= "PCIMT IO MEM",
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource pcimt_io_resources[] = {
+	{
+		.start	= 0x00,
+		.end	= 0x1f,
+		.name	= "dma1",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x40,
+		.end	= 0x5f,
+		.name	= "timer",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x60,
+		.end	= 0x6f,
+		.name	= "keyboard",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x80,
+		.end	= 0x8f,
+		.name	= "dma page reg",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0xc0,
+		.end	= 0xdf,
+		.name	= "dma2",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0xcfc,
+		.end	= 0xcff,
+		.name	= "PCI config data",
+		.flags	= IORESOURCE_BUSY
+	}
+};
+
+static struct resource sni_mem_resource = {
+	.start	= 0x10000000UL,
+	.end	= 0xffffffffUL,
+	.name	= "PCIMT PCI MEM",
+	.flags	= IORESOURCE_MEM
+};
+
+/*
+ * The RM200/RM300 has a few holes in it's PCI/EISA memory address space used
+ * for other purposes.  Be paranoid and allocate all of the before the PCI
+ * code gets a chance to to map anything else there ...
+ *
+ * This leaves the following areas available:
+ *
+ * 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory
+ * 0x10100000 - 0x13ffffff ( 15MB) PCI/EISA/ISA Bus Memory
+ * 0x18000000 - 0x1fbfffff (124MB) PCI/EISA Bus Memory
+ * 0x1ff08000 - 0x1ffeffff (816kB) PCI/EISA Bus Memory
+ * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory
+ */
+static struct resource pcimt_mem_resources[] = {
+	{
+		.start	= 0x100a0000,
+		.end	= 0x100bffff,
+		.name	= "Video RAM area",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x100c0000,
+		.end	= 0x100fffff,
+		.name	= "ISA Reserved",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x14000000,
+		.end	= 0x17bfffff,
+		.name	= "PCI IO",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x17c00000,
+		.end	= 0x17ffffff,
+		.name	= "Cache Replacement Area",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1a000000,
+		.end	= 0x1a000003,
+		.name	= "PCI INT Acknowledge",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fc00000,
+		.end	= 0x1fc7ffff,
+		.name	= "Boot PROM",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fc80000,
+		.end	= 0x1fcfffff,
+		.name	= "Diag PROM",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fd00000,
+		.end	= 0x1fdfffff,
+		.name	= "X-Bus",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fe00000,
+		.end	= 0x1fefffff,
+		.name	= "BIOS map",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1ff00000,
+		.end	= 0x1ff7ffff,
+		.name	= "NVRAM / EEPROM",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fff0000,
+		.end	= 0x1fffefff,
+		.name	= "ASIC PCI",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1ffff000,
+		.end	= 0x1fffffff,
+		.name	= "MP Agent",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x20000000,
+		.end	= 0x9fffffff,
+		.name	= "Main Memory",
+		.flags	= IORESOURCE_BUSY
+	}
+};
+
+static void __init sni_pcimt_resource_init(void)
+{
+	int i;
+
+	/* request I/O space for devices used on all i[345]86 PCs */
+	for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++)
+		request_resource(&ioport_resource, pcimt_io_resources + i);
+
+	/* request mem space for pcimt-specific devices */
+	for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++)
+		request_resource(&sni_mem_resource, pcimt_mem_resources + i);
+
+	ioport_resource.end = sni_io_resource.end;
+}
+
+extern struct pci_ops sni_pcimt_ops;
+
+static struct pci_controller sni_controller = {
+	.pci_ops	= &sni_pcimt_ops,
+	.mem_resource	= &sni_mem_resource,
+	.mem_offset	= 0x10000000UL,
+	.io_resource	= &sni_io_resource,
+	.io_offset	= 0x00000000UL
+};
+
+static void enable_pcimt_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
+
+	*(volatile u8 *) PCIMT_IRQSEL |= mask;
+}
+
+void disable_pcimt_irq(unsigned int irq)
+{
+	unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2));
+
+	*(volatile u8 *) PCIMT_IRQSEL &= mask;
+}
+
+static void end_pcimt_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_pcimt_irq(irq);
+}
+
+static struct irq_chip pcimt_irq_type = {
+	.typename = "PCIMT",
+	.ack = disable_pcimt_irq,
+	.mask = disable_pcimt_irq,
+	.mask_ack = disable_pcimt_irq,
+	.unmask = enable_pcimt_irq,
+	.end = end_pcimt_irq,
+};
+
+/*
+ * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
+ * button interrupts.  Later ...
+ */
+static void pcimt_hwint0(void)
+{
+	panic("Received int0 but no handler yet ...");
+}
+
+/*
+ * hwint 1 deals with EISA and SCSI interrupts,
+ *
+ * The EISA_INT bit in CSITPEND is high active, all others are low active.
+ */
+static void pcimt_hwint1(void)
+{
+	u8 pend = *(volatile char *)PCIMT_CSITPEND;
+	unsigned long flags;
+
+	if (pend & IT_EISA) {
+		int irq;
+		/*
+		 * Note: ASIC PCI's builtin interrupt achknowledge feature is
+		 * broken.  Using it may result in loss of some or all i8259
+		 * interupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
+		 */
+		irq = i8259_irq();
+		if (unlikely(irq < 0))
+			return;
+
+		do_IRQ(irq);
+	}
+
+	if (!(pend & IT_SCSI)) {
+		flags = read_c0_status();
+		clear_c0_status(ST0_IM);
+		do_IRQ(PCIMT_IRQ_SCSI);
+		write_c0_status(flags);
+	}
+}
+
+/*
+ * hwint 3 should deal with the PCI A - D interrupts,
+ */
+static void pcimt_hwint3(void)
+{
+	u8 pend = *(volatile char *)PCIMT_CSITPEND;
+	int irq;
+
+	pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
+	pend ^= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
+	clear_c0_status(IE_IRQ3);
+	irq = PCIMT_IRQ_INT2 + ffs(pend) - 1;
+	do_IRQ(irq);
+	set_c0_status(IE_IRQ3);
+}
+
+static void sni_pcimt_hwint(void)
+{
+	u32 pending = (read_c0_cause() & read_c0_status());
+
+	if (pending & C_IRQ5)
+		do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
+	else if (pending & C_IRQ4)
+		do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 6);
+	else if (pending & C_IRQ3)
+		pcimt_hwint3();
+	else if (pending & C_IRQ1)
+		pcimt_hwint1();
+	else if (pending & C_IRQ0) {
+		pcimt_hwint0();
+	}
+}
+
+void __init sni_pcimt_irq_init(void)
+{
+	int i;
+
+	*(volatile u8 *) PCIMT_IRQSEL = IT_ETH | IT_EISA;
+	mips_cpu_irq_init();
+	/* Actually we've got more interrupts to handle ...  */
+	for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_SCSI; i++)
+		set_irq_chip(i, &pcimt_irq_type);
+	sni_hwint = sni_pcimt_hwint;
+	change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3);
+}
+
+void sni_pcimt_init(void)
+{
+	sni_pcimt_resource_init();
+	sni_pcimt_detect();
+	sni_pcimt_sc_init();
+	rtc_mips_get_time = mc146818_get_cmos_time;
+	rtc_mips_set_time = mc146818_set_rtc_mmss;
+	board_time_init = sni_cpu_time_init;
+#ifdef CONFIG_PCI
+	register_pci_controller(&sni_controller);
+#endif
+}
+
+static int __init snirm_pcimt_setup_devinit(void)
+{
+	switch (sni_brd_type) {
+	case SNI_BRD_PCI_MTOWER:
+	case SNI_BRD_PCI_DESKTOP:
+	case SNI_BRD_PCI_MTOWER_CPLUS:
+	        platform_device_register(&pcimt_serial8250_device);
+	        break;
+	}
+
+	return 0;
+}
+
+device_initcall(snirm_pcimt_setup_devinit);
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
new file mode 100644
index 0000000..3921096
--- /dev/null
+++ b/arch/mips/sni/pcit.c
@@ -0,0 +1,351 @@
+/*
+ * PCI Tower specific code
+ *
+ * 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 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+
+#include <asm/mc146818-time.h>
+#include <asm/sni.h>
+#include <asm/time.h>
+#include <asm/irq_cpu.h>
+
+
+#define PORT(_base,_irq)				\
+	{						\
+		.iobase		= _base,		\
+		.irq		= _irq,			\
+		.uartclk	= 1843200,		\
+		.iotype		= UPIO_PORT,		\
+		.flags		= UPF_BOOT_AUTOCONF,	\
+	}
+
+static struct plat_serial8250_port pcit_data[] = {
+	PORT(0x3f8, 0),
+	PORT(0x2f8, 3),
+	{ },
+};
+
+static struct platform_device pcit_serial8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= pcit_data,
+	},
+};
+
+static struct plat_serial8250_port pcit_cplus_data[] = {
+	PORT(0x3f8, 4),
+	PORT(0x2f8, 3),
+	PORT(0x3e8, 4),
+	PORT(0x2e8, 3),
+	{ },
+};
+
+static struct platform_device pcit_cplus_serial8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= pcit_cplus_data,
+	},
+};
+
+static struct resource sni_io_resource = {
+	.start	= 0x00001000UL,
+	.end	= 0x03bfffffUL,
+	.name	= "PCIT IO MEM",
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource pcit_io_resources[] = {
+	{
+		.start	= 0x00,
+		.end	= 0x1f,
+		.name	= "dma1",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x40,
+		.end	= 0x5f,
+		.name	= "timer",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x60,
+		.end	= 0x6f,
+		.name	= "keyboard",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x80,
+		.end	= 0x8f,
+		.name	= "dma page reg",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0xc0,
+		.end	= 0xdf,
+		.name	= "dma2",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0xcfc,
+		.end	= 0xcff,
+		.name	= "PCI config data",
+		.flags	= IORESOURCE_BUSY
+	}
+};
+
+static struct resource sni_mem_resource = {
+	.start	= 0x10000000UL,
+	.end	= 0xffffffffUL,
+	.name	= "PCIT PCI MEM",
+	.flags	= IORESOURCE_MEM
+};
+
+/*
+ * The RM200/RM300 has a few holes in it's PCI/EISA memory address space used
+ * for other purposes.  Be paranoid and allocate all of the before the PCI
+ * code gets a chance to to map anything else there ...
+ *
+ * This leaves the following areas available:
+ *
+ * 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory
+ * 0x10100000 - 0x13ffffff ( 15MB) PCI/EISA/ISA Bus Memory
+ * 0x18000000 - 0x1fbfffff (124MB) PCI/EISA Bus Memory
+ * 0x1ff08000 - 0x1ffeffff (816kB) PCI/EISA Bus Memory
+ * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory
+ */
+static struct resource pcit_mem_resources[] = {
+	{
+		.start	= 0x14000000,
+		.end	= 0x17bfffff,
+		.name	= "PCI IO",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x17c00000,
+		.end	= 0x17ffffff,
+		.name	= "Cache Replacement Area",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x180a0000,
+		.end	= 0x180bffff,
+		.name	= "Video RAM area",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x180c0000,
+		.end	= 0x180fffff,
+		.name	= "ISA Reserved",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x19000000,
+		.end	= 0x1fbfffff,
+		.name	= "PCI MEM",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fc00000,
+		.end	= 0x1fc7ffff,
+		.name	= "Boot PROM",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fc80000,
+		.end	= 0x1fcfffff,
+		.name	= "Diag PROM",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fd00000,
+		.end	= 0x1fdfffff,
+		.name	= "X-Bus",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fe00000,
+		.end	= 0x1fefffff,
+		.name	= "BIOS map",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1ff00000,
+		.end	= 0x1ff7ffff,
+		.name	= "NVRAM / EEPROM",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fff0000,
+		.end	= 0x1fffefff,
+		.name	= "MAUI ASIC",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1ffff000,
+		.end	= 0x1fffffff,
+		.name	= "MP Agent",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x20000000,
+		.end	= 0x9fffffff,
+		.name	= "Main Memory",
+		.flags	= IORESOURCE_BUSY
+	}
+};
+
+static void __init sni_pcit_resource_init(void)
+{
+	int i;
+
+	/* request I/O space for devices used on all i[345]86 PCs */
+	for (i = 0; i < ARRAY_SIZE(pcit_io_resources); i++)
+		request_resource(&ioport_resource, pcit_io_resources + i);
+
+	/* request mem space for pcimt-specific devices */
+	for (i = 0; i < ARRAY_SIZE(pcit_mem_resources); i++)
+		request_resource(&sni_mem_resource, pcit_mem_resources + i);
+
+	ioport_resource.end = sni_io_resource.end;
+}
+
+
+extern struct pci_ops sni_pcit_ops;
+
+static struct pci_controller sni_pcit_controller = {
+	.pci_ops	= &sni_pcit_ops,
+	.mem_resource	= &sni_mem_resource,
+	.mem_offset	= 0x10000000UL,
+	.io_resource	= &sni_io_resource,
+	.io_offset	= 0x00000000UL
+};
+
+static void enable_pcit_irq(unsigned int irq)
+{
+	u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24);
+
+	*(volatile u32 *)SNI_PCIT_INT_REG |= mask;
+}
+
+void disable_pcit_irq(unsigned int irq)
+{
+	u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24);
+
+	*(volatile u32 *)SNI_PCIT_INT_REG &= ~mask;
+}
+
+void end_pcit_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_pcit_irq(irq);
+}
+
+static struct irq_chip pcit_irq_type = {
+	.typename = "PCIT",
+	.ack = disable_pcit_irq,
+	.mask = disable_pcit_irq,
+	.mask_ack = disable_pcit_irq,
+	.unmask = enable_pcit_irq,
+	.end = end_pcit_irq,
+};
+
+static void pcit_hwint1(void)
+{
+	u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
+	int irq;
+
+	clear_c0_status(IE_IRQ1);
+	irq = ffs((pending >> 16) & 0x7f);
+
+	if (likely(irq > 0))
+		do_IRQ (irq + SNI_PCIT_INT_START - 1);
+	set_c0_status (IE_IRQ1);
+}
+
+static void pcit_hwint0(void)
+{
+	u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
+	int irq;
+
+	clear_c0_status(IE_IRQ0);
+	irq = ffs((pending >> 16) & 0x7f);
+
+	if (likely(irq > 0))
+		do_IRQ (irq + SNI_PCIT_INT_START - 1);
+	set_c0_status (IE_IRQ0);
+}
+
+static void sni_pcit_hwint(void)
+{
+	u32 pending = (read_c0_cause() & read_c0_status());
+
+	if (pending & C_IRQ1)
+		pcit_hwint1();
+	else if (pending & C_IRQ2)
+		do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 4);
+	else if (pending & C_IRQ3)
+		do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 5);
+	else if (pending & C_IRQ5)
+		do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
+}
+
+static void sni_pcit_hwint_cplus(void)
+{
+	u32 pending = (read_c0_cause() & read_c0_status());
+
+	if (pending & C_IRQ0)
+		pcit_hwint0();
+	else if (pending & C_IRQ2)
+		do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 4);
+	else if (pending & C_IRQ3)
+		do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 5);
+	else if (pending & C_IRQ5)
+		do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
+}
+
+void __init sni_pcit_irq_init(void)
+{
+	int i;
+
+	mips_cpu_irq_init();
+	for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
+		set_irq_chip(i, &pcit_irq_type);
+	*(volatile u32 *)SNI_PCIT_INT_REG = 0;
+	sni_hwint = sni_pcit_hwint;
+	change_c0_status(ST0_IM, IE_IRQ1);
+	setup_irq (SNI_PCIT_INT_START + 6, &sni_isa_irq);
+}
+
+void __init sni_pcit_cplus_irq_init(void)
+{
+	int i;
+
+	mips_cpu_irq_init();
+	for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
+		set_irq_chip(i, &pcit_irq_type);
+	*(volatile u32 *)SNI_PCIT_INT_REG = 0;
+	sni_hwint = sni_pcit_hwint_cplus;
+	change_c0_status(ST0_IM, IE_IRQ0);
+	setup_irq (SNI_PCIT_INT_START + 6, &sni_isa_irq);
+}
+
+void sni_pcit_init(void)
+{
+	sni_pcit_resource_init();
+	rtc_mips_get_time = mc146818_get_cmos_time;
+	rtc_mips_set_time = mc146818_set_rtc_mmss;
+	board_time_init = sni_cpu_time_init;
+#ifdef CONFIG_PCI
+	register_pci_controller(&sni_pcit_controller);
+#endif
+}
+
+static int __init snirm_pcit_setup_devinit(void)
+{
+	switch (sni_brd_type) {
+	case SNI_BRD_PCI_TOWER:
+	        platform_device_register(&pcit_serial8250_device);
+	        break;
+
+	case SNI_BRD_PCI_TOWER_CPLUS:
+	        platform_device_register(&pcit_cplus_serial8250_device);
+	        break;
+	}
+	return 0;
+}
+
+device_initcall(snirm_pcit_setup_devinit);
diff --git a/arch/mips/sni/reset.c b/arch/mips/sni/reset.c
index be85bec..2eada8a 100644
--- a/arch/mips/sni/reset.c
+++ b/arch/mips/sni/reset.c
@@ -13,12 +13,11 @@
  * controller to pulse the reset-line low. We try that for a while,
  * and if it doesn't work, we do some other stupid things.
  */
-static inline void
-kb_wait(void)
+static inline void kb_wait(void)
 {
 	int i;
 
-	for (i=0; i<0x10000; i++)
+	for (i = 0; i < 0x10000; i++)
 		if ((inb_p(0x64) & 0x02) == 0)
 			break;
 }
@@ -32,9 +31,9 @@
 	   We can do that easier ...  */
 	local_irq_disable();
 	for (;;) {
-		for (i=0; i<100; i++) {
+		for (i = 0; i < 100; i++) {
 			kb_wait();
-			for(j = 0; j < 100000 ; j++)
+			for (j = 0; j < 100000 ; j++)
 				/* nothing */;
 			outb_p(0xfe,0x64);	 /* pulse reset low */
 		}
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
new file mode 100644
index 0000000..517dc69
--- /dev/null
+++ b/arch/mips/sni/rm200.c
@@ -0,0 +1,186 @@
+/*
+ * RM200 specific code
+ *
+ * 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 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <asm/sni.h>
+#include <asm/time.h>
+#include <asm/ds1216.h>
+#include <asm/irq_cpu.h>
+
+#define PORT(_base,_irq)				\
+	{						\
+		.iobase		= _base,		\
+		.irq		= _irq,			\
+		.uartclk	= 1843200,		\
+		.iotype		= UPIO_PORT,		\
+		.flags		= UPF_BOOT_AUTOCONF,	\
+	}
+
+static struct plat_serial8250_port rm200_data[] = {
+	PORT(0x3f8, 4),
+	PORT(0x2f8, 3),
+	{ },
+};
+
+static struct platform_device rm200_serial8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= rm200_data,
+	},
+};
+
+static struct resource snirm_82596_rm200_rsrc[] = {
+	{
+		.start = 0xb8000000,
+		.end   = 0xb80fffff,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 0xbb000000,
+		.end   = 0xbb000004,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 0xbff00000,
+		.end   = 0xbff00020,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 27,
+		.end   = 27,
+		.flags = IORESOURCE_IRQ
+	},
+	{
+		.flags = 0x00
+	}
+};
+
+static struct platform_device snirm_82596_rm200_pdev = {
+	.name           = "snirm_82596",
+	.num_resources  = ARRAY_SIZE(snirm_82596_rm200_rsrc),
+	.resource       = snirm_82596_rm200_rsrc
+};
+
+static struct resource snirm_53c710_rm200_rsrc[] = {
+	{
+		.start = 0xb9000000,
+		.end   = 0xb90fffff,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 26,
+		.end   = 26,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device snirm_53c710_rm200_pdev = {
+	.name           = "snirm_53c710",
+	.num_resources  = ARRAY_SIZE(snirm_53c710_rm200_rsrc),
+	.resource       = snirm_53c710_rm200_rsrc
+};
+
+static int __init snirm_setup_devinit(void)
+{
+	if (sni_brd_type == SNI_BRD_RM200) {
+		platform_device_register(&rm200_serial8250_device);
+		platform_device_register(&snirm_82596_rm200_pdev);
+		platform_device_register(&snirm_53c710_rm200_pdev);
+	}
+	return 0;
+}
+
+device_initcall(snirm_setup_devinit);
+
+
+#define SNI_RM200_INT_STAT_REG  0xbc000000
+#define SNI_RM200_INT_ENA_REG   0xbc080000
+
+#define SNI_RM200_INT_START  24
+#define SNI_RM200_INT_END    28
+
+static void enable_rm200_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
+
+	*(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask;
+}
+
+void disable_rm200_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
+
+	*(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask;
+}
+
+void end_rm200_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_rm200_irq(irq);
+}
+
+static struct irq_chip rm200_irq_type = {
+	.typename = "RM200",
+	.ack = disable_rm200_irq,
+	.mask = disable_rm200_irq,
+	.mask_ack = disable_rm200_irq,
+	.unmask = enable_rm200_irq,
+	.end = end_rm200_irq,
+};
+
+static void sni_rm200_hwint(void)
+{
+	u32 pending = read_c0_cause() & read_c0_status();
+	u8 mask;
+	u8 stat;
+	int irq;
+
+	if (pending & C_IRQ5)
+		do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
+	else if (pending & C_IRQ0) {
+		clear_c0_status (IE_IRQ0);
+		mask = *(volatile u8 *)SNI_RM200_INT_ENA_REG ^ 0x1f;
+		stat = *(volatile u8 *)SNI_RM200_INT_STAT_REG ^ 0x14;
+		irq = ffs(stat & mask & 0x1f);
+
+		if (likely(irq > 0))
+			do_IRQ (irq + SNI_RM200_INT_START - 1);
+		set_c0_status (IE_IRQ0);
+	}
+}
+
+void __init sni_rm200_irq_init(void)
+{
+	int i;
+
+	* (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f;
+
+	mips_cpu_irq_init();
+	/* Actually we've got more interrupts to handle ...  */
+	for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++)
+		set_irq_chip(i, &rm200_irq_type);
+	sni_hwint = sni_rm200_hwint;
+	change_c0_status(ST0_IM, IE_IRQ0);
+	setup_irq (SNI_RM200_INT_START + 0, &sni_isa_irq);
+}
+
+void sni_rm200_init(void)
+{
+	set_io_port_base(SNI_PORT_BASE + 0x02000000);
+	ioport_resource.end += 0x02000000;
+	ds1216_base = (volatile unsigned char *) SNI_DS1216_RM200_BASE;
+	rtc_mips_get_time = ds1216_get_cmos_time;
+	board_time_init = sni_cpu_time_init;
+}
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index afeb7f1..68d7cf6 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -6,16 +6,10 @@
  * for more details.
  *
  * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  */
 #include <linux/eisa.h>
-#include <linux/hdreg.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mc146818rtc.h>
-#include <linux/pm.h>
-#include <linux/pci.h>
 #include <linux/console.h>
 #include <linux/fb.h>
 #include <linux/screen_info.h>
@@ -25,52 +19,16 @@
 #include <asm/sgialib.h>
 #endif
 
-#include <asm/bcache.h>
-#include <asm/bootinfo.h>
 #include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mc146818-time.h>
-#include <asm/processor.h>
 #include <asm/reboot.h>
 #include <asm/sni.h>
-#include <asm/time.h>
-#include <asm/traps.h>
+
+unsigned int sni_brd_type;
 
 extern void sni_machine_restart(char *command);
 extern void sni_machine_halt(void);
 extern void sni_machine_power_off(void);
 
-void __init plat_timer_setup(struct irqaction *irq)
-{
-	/* set the clock to 100 Hz */
-	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
-	outb_p(LATCH & 0xff , 0x40);	/* LSB */
-	outb(LATCH >> 8 , 0x40);	/* MSB */
-	setup_irq(0, irq);
-}
-
-/*
- * A bit more gossip about the iron we're running on ...
- */
-static inline void sni_pcimt_detect(void)
-{
-	char boardtype[80];
-	unsigned char csmsr;
-	char *p = boardtype;
-	unsigned int asic;
-
-	csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
-
-	p += sprintf(p, "%s PCI", (csmsr & 0x80) ? "RM200" : "RM300");
-	if ((csmsr & 0x80) == 0)
-		p += sprintf(p, ", board revision %s",
-		             (csmsr & 0x20) ? "D" : "C");
-	asic = csmsr & 0x80;
-	asic = (csmsr & 0x08) ? asic : !asic;
-	p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1");
-	printk("%s.\n", boardtype);
-}
-
 static void __init sni_display_setup(void)
 {
 #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_ARC)
@@ -90,175 +48,11 @@
 #endif
 }
 
-static struct resource sni_io_resource = {
-	.start	= 0x00001000UL,
-	.end	= 0x03bfffffUL,
-	.name	= "PCIMT IO MEM",
-	.flags	= IORESOURCE_IO,
-};
-
-static struct resource pcimt_io_resources[] = {
-	{
-		.start	= 0x00,
-		.end	= 0x1f,
-		.name	= "dma1",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	=  0x40,
-		.end	= 0x5f,
-		.name	= "timer",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	=  0x60,
-		.end	= 0x6f,
-		.name	= "keyboard",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	=  0x80,
-		.end	= 0x8f,
-		.name	= "dma page reg",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	=  0xc0,
-		.end	= 0xdf,
-		.name	= "dma2",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	=  0xcfc,
-		.end	= 0xcff,
-		.name	= "PCI config data",
-		.flags	= IORESOURCE_BUSY
-	}
-};
-
-static struct resource sni_mem_resource = {
-	.start	= 0x10000000UL,
-	.end	= 0xffffffffUL,
-	.name	= "PCIMT PCI MEM",
-	.flags	= IORESOURCE_MEM
-};
-
-/*
- * The RM200/RM300 has a few holes in it's PCI/EISA memory address space used
- * for other purposes.  Be paranoid and allocate all of the before the PCI
- * code gets a chance to to map anything else there ...
- *
- * This leaves the following areas available:
- *
- * 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory
- * 0x10100000 - 0x13ffffff ( 15MB) PCI/EISA/ISA Bus Memory
- * 0x18000000 - 0x1fbfffff (124MB) PCI/EISA Bus Memory
- * 0x1ff08000 - 0x1ffeffff (816kB) PCI/EISA Bus Memory
- * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory
- */
-static struct resource pcimt_mem_resources[] = {
-	{
-		.start	= 0x100a0000,
-		.end	= 0x100bffff,
-		.name	= "Video RAM area",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x100c0000,
-		.end	= 0x100fffff,
-		.name	= "ISA Reserved",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x14000000,
-		.end	= 0x17bfffff,
-		.name	= "PCI IO",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x17c00000,
-		.end	= 0x17ffffff,
-		.name	= "Cache Replacement Area",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x1a000000,
-		.end	= 0x1a000003,
-		.name	= "PCI INT Acknowledge",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x1fc00000,
-		.end	= 0x1fc7ffff,
-		.name	= "Boot PROM",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x1fc80000,
-		.end	= 0x1fcfffff,
-		.name	= "Diag PROM",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x1fd00000,
-		.end	= 0x1fdfffff,
-		.name	= "X-Bus",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x1fe00000,
-		.end	= 0x1fefffff,
-		.name	= "BIOS map",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x1ff00000,
-		.end	= 0x1ff7ffff,
-		.name	= "NVRAM / EEPROM",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x1fff0000,
-		.end	= 0x1fffefff,
-		.name	= "ASIC PCI",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x1ffff000,
-		.end	= 0x1fffffff,
-		.name	= "MP Agent",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x20000000,
-		.end	= 0x9fffffff,
-		.name	= "Main Memory",
-		.flags	= IORESOURCE_BUSY
-	}
-};
-
-static void __init sni_resource_init(void)
-{
-	int i;
-
-	/* request I/O space for devices used on all i[345]86 PCs */
-	for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++)
-		request_resource(&ioport_resource, pcimt_io_resources + i);
-
-	/* request mem space for pcimt-specific devices */
-	for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++)
-		request_resource(&sni_mem_resource, pcimt_mem_resources + i);
-
-	ioport_resource.end = sni_io_resource.end;
-}
-
-extern struct pci_ops sni_pci_ops;
-
-static struct pci_controller sni_controller = {
-	.pci_ops	= &sni_pci_ops,
-	.mem_resource	= &sni_mem_resource,
-	.mem_offset	= 0x10000000UL,
-	.io_resource	= &sni_io_resource,
-	.io_offset	= 0x00000000UL
-};
-
-static inline void sni_pcimt_time_init(void)
-{
-	rtc_mips_get_time = mc146818_get_cmos_time;
-	rtc_mips_set_time = mc146818_set_rtc_mmss;
-}
 
 void __init plat_mem_setup(void)
 {
-	sni_pcimt_detect();
-	sni_pcimt_sc_init();
-	sni_pcimt_time_init();
-
 	set_io_port_base(SNI_PORT_BASE);
-	ioport_resource.end = sni_io_resource.end;
+//	ioport_resource.end = sni_io_resource.end;
 
 	/*
 	 * Setup (E)ISA I/O memory access stuff
@@ -268,15 +62,33 @@
 	EISA_bus = 1;
 #endif
 
-	sni_resource_init();
+	switch (sni_brd_type) {
+	case SNI_BRD_10:
+	case SNI_BRD_10NEW:
+	case SNI_BRD_TOWER_OASIC:
+	case SNI_BRD_MINITOWER:
+	        sni_a20r_init();
+	        break;
+
+	case SNI_BRD_PCI_TOWER:
+	case SNI_BRD_PCI_TOWER_CPLUS:
+	        sni_pcit_init();
+		break;
+
+	case SNI_BRD_RM200:
+	        sni_rm200_init();
+	        break;
+
+	case SNI_BRD_PCI_MTOWER:
+	case SNI_BRD_PCI_DESKTOP:
+	case SNI_BRD_PCI_MTOWER_CPLUS:
+	        sni_pcimt_init();
+	        break;
+	}
 
 	_machine_restart = sni_machine_restart;
 	_machine_halt = sni_machine_halt;
 	pm_power_off = sni_machine_power_off;
 
 	sni_display_setup();
-
-#ifdef CONFIG_PCI
-	register_pci_controller(&sni_controller);
-#endif
 }
diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c
index 1213d16..6a44bbf 100644
--- a/arch/mips/sni/sniprom.c
+++ b/arch/mips/sni/sniprom.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <linux/console.h>
 
 #include <asm/addrspace.h>
 #include <asm/sni.h>
@@ -31,7 +32,7 @@
 #define PROM_ENTRY(x)		(PROM_VEC + (x))
 
 
-#undef DEBUG
+#define DEBUG
 #ifdef DEBUG
 #define DBG_PRINTF(x...)     prom_printf(x)
 #else
@@ -93,14 +94,14 @@
 {
 	int	i;
 
-	prom_printf("SNI IDProm dump (first 128byte):\n");
-	for(i=0;i<128;i++) {
+	prom_printf("SNI IDProm dump:\n");
+	for (i = 0; i < 256; i++) {
 		if (i%16 == 0)
 			prom_printf("%04x ", i);
 
-		prom_printf("%02x ", *(unsigned char *) (SNI_IDPROM_BASE+i));
+		prom_printf("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i));
 
-		if (i%16 == 15)
+		if (i % 16 == 15)
 			prom_printf("\n");
 	}
 }
@@ -118,7 +119,7 @@
 	} memconf[8];
 
 	/* MemSIZE from prom in 16MByte chunks */
-	memsize=*((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
+	memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
 
 	DBG_PRINTF("IDProm memsize: %lu MByte\n", memsize);
 
@@ -126,26 +127,134 @@
 	__prom_get_memconf(&memconf);
 
 	DBG_PRINTF("prom_get_mem_conf memory configuration:\n");
-	for(i=0;i<8 && memconf[i].size;i++) {
-		prom_printf("Bank%d: %08x @ %08x\n", i,
+	for (i = 0;i < 8 && memconf[i].size; i++) {
+		if (sni_brd_type == SNI_BRD_PCI_TOWER ||
+		    sni_brd_type == SNI_BRD_PCI_TOWER_CPLUS) {
+			if (memconf[i].base >= 0x20000000 &&
+			    memconf[i].base <  0x30000000) {
+				memconf[i].base -= 0x20000000;
+			}
+	}
+		DBG_PRINTF("Bank%d: %08x @ %08x\n", i,
 			memconf[i].size, memconf[i].base);
 		add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM);
 	}
 }
 
+static void __init sni_console_setup(void)
+{
+	char *ctype;
+	char *cdev;
+	char *baud;
+	int port;
+	static char options[8];
+
+	cdev = prom_getenv ("console_dev");
+	if (strncmp (cdev, "tty", 3) == 0) {
+		ctype = prom_getenv ("console");
+		switch (*ctype) {
+		default:
+		case 'l':
+	                port = 0;
+	                baud = prom_getenv("lbaud");
+	                break;
+		case 'r':
+	                port = 1;
+	                baud = prom_getenv("rbaud");
+	                break;
+		}
+		if (baud)
+			strcpy(options, baud);
+		add_preferred_console("ttyS", port, baud ? options : NULL);
+	}
+}
+
 void __init prom_init(void)
 {
 	int argc = fw_arg0;
 	char **argv = (void *)fw_arg1;
-	unsigned int sni_brd_type = *(unsigned char *) SNI_IDPROM_BRDTYPE;
 	int i;
+	int cputype;
 
-	DBG_PRINTF("Found SNI brdtype %02x\n", sni_brd_type);
+	sni_brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE;
+	cputype = *(unsigned char *)SNI_IDPROM_CPUTYPE;
+	switch (sni_brd_type) {
+	case SNI_BRD_TOWER_OASIC:
+	        switch (cputype) {
+		case SNI_CPU_M8030:
+		        systype = "RM400-330";
+		        break;
+		case SNI_CPU_M8031:
+		        systype = "RM400-430";
+		        break;
+		case SNI_CPU_M8037:
+		        systype = "RM400-530";
+		        break;
+		case SNI_CPU_M8034:
+		        systype = "RM400-730";
+		        break;
+		default:
+			systype = "RM400-xxx";
+			break;
+		}
+	        break;
+	case SNI_BRD_MINITOWER:
+	        switch (cputype) {
+		case SNI_CPU_M8021:
+		case SNI_CPU_M8043:
+		        systype = "RM400-120";
+		        break;
+		case SNI_CPU_M8040:
+		        systype = "RM400-220";
+		        break;
+		case SNI_CPU_M8053:
+		        systype = "RM400-225";
+		        break;
+		case SNI_CPU_M8050:
+		        systype = "RM400-420";
+		        break;
+		default:
+			systype = "RM400-xxx";
+			break;
+		}
+	        break;
+	case SNI_BRD_PCI_TOWER:
+	        systype = "RM400-Cxx";
+	        break;
+	case SNI_BRD_RM200:
+	        systype = "RM200-xxx";
+	        break;
+	case SNI_BRD_PCI_MTOWER:
+	        systype = "RM300-Cxx";
+	        break;
+	case SNI_BRD_PCI_DESKTOP:
+	        switch (read_c0_prid() & 0xff00) {
+		case PRID_IMP_R4600:
+		case PRID_IMP_R4700:
+		        systype = "RM200-C20";
+		        break;
+		case PRID_IMP_R5000:
+		        systype = "RM200-C40";
+		        break;
+		default:
+		        systype = "RM200-Cxx";
+		        break;
+		}
+	        break;
+	case SNI_BRD_PCI_TOWER_CPLUS:
+	        systype = "RM400-Exx";
+	        break;
+	case SNI_BRD_PCI_MTOWER_CPLUS:
+	        systype = "RM300-Exx";
+	        break;
+	}
+	DBG_PRINTF("Found SNI brdtype %02x name %s\n", sni_brd_type,systype);
 
 #ifdef DEBUG
 	sni_idprom_dump();
 #endif
 	sni_mem_init();
+	sni_console_setup();
 
 	/* copy prom cmdline parameters to kernel cmdline */
 	for (i = 1; i < argc; i++) {
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
new file mode 100644
index 0000000..20028fc
--- /dev/null
+++ b/arch/mips/sni/time.c
@@ -0,0 +1,148 @@
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+
+#include <asm/sni.h>
+#include <asm/time.h>
+
+#define SNI_CLOCK_TICK_RATE     3686400
+#define SNI_COUNTER2_DIV        64
+#define SNI_COUNTER0_DIV        ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ)
+
+static void sni_a20r_timer_ack(void)
+{
+        *(volatile u8 *)A20R_PT_TIM0_ACK = 0x0; wmb();
+}
+
+/*
+ * a20r platform uses 2 counters to divide the input frequency.
+ * Counter 2 output is connected to Counter 0 & 1 input.
+ */
+static void __init sni_a20r_timer_setup(struct irqaction *irq)
+{
+        *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; wmb();
+        *(volatile u8 *)(A20R_PT_CLOCK_BASE +  0) = (SNI_COUNTER0_DIV) & 0xff; wmb();
+        *(volatile u8 *)(A20R_PT_CLOCK_BASE +  0) = (SNI_COUNTER0_DIV >> 8) & 0xff; wmb();
+
+        *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; wmb();
+        *(volatile u8 *)(A20R_PT_CLOCK_BASE +  8) = (SNI_COUNTER2_DIV) & 0xff; wmb();
+        *(volatile u8 *)(A20R_PT_CLOCK_BASE +  8) = (SNI_COUNTER2_DIV >> 8) & 0xff; wmb();
+
+        setup_irq(SNI_A20R_IRQ_TIMER, irq);
+        mips_timer_ack = sni_a20r_timer_ack;
+}
+
+#define SNI_8254_TICK_RATE        1193182UL
+
+#define SNI_8254_TCSAMP_COUNTER   ((SNI_8254_TICK_RATE / HZ) + 255)
+
+static __init unsigned long dosample(void)
+{
+	u32 ct0, ct1;
+	volatile u8 msb, lsb;
+
+	/* Start the counter. */
+	outb_p (0x34, 0x43);
+	outb_p(SNI_8254_TCSAMP_COUNTER & 0xff, 0x40);
+	outb (SNI_8254_TCSAMP_COUNTER >> 8, 0x40);
+
+	/* Get initial counter invariant */
+	ct0 = read_c0_count();
+
+	/* Latch and spin until top byte of counter0 is zero */
+	do {
+		outb (0x00, 0x43);
+		lsb = inb (0x40);
+		msb = inb (0x40);
+		ct1 = read_c0_count();
+	} while (msb);
+
+	/* Stop the counter. */
+	outb (0x38, 0x43);
+	/*
+	 * Return the difference, this is how far the r4k counter increments
+	 * for every 1/HZ seconds. We round off the nearest 1 MHz of master
+	 * clock (= 1000000 / HZ / 2).
+	 */
+	/*return (ct1 - ct0 + (500000/HZ/2)) / (500000/HZ) * (500000/HZ);*/
+	return (ct1 - ct0) / (500000/HZ) * (500000/HZ);
+}
+
+/*
+ * Here we need to calibrate the cycle counter to at least be close.
+ */
+__init void sni_cpu_time_init(void)
+{
+	unsigned long r4k_ticks[3];
+	unsigned long r4k_tick;
+
+	/*
+	 * Figure out the r4k offset, the algorithm is very simple and works in
+	 * _all_ cases as long as the 8254 counter register itself works ok (as
+	 * an interrupt driving timer it does not because of bug, this is why
+	 * we are using the onchip r4k counter/compare register to serve this
+	 * purpose, but for r4k_offset calculation it will work ok for us).
+	 * There are other very complicated ways of performing this calculation
+	 * but this one works just fine so I am not going to futz around. ;-)
+	 */
+	printk(KERN_INFO "Calibrating system timer... ");
+	dosample();	/* Prime cache. */
+	dosample();	/* Prime cache. */
+	/* Zero is NOT an option. */
+	do {
+		r4k_ticks[0] = dosample();
+	} while (!r4k_ticks[0]);
+	do {
+		r4k_ticks[1] = dosample();
+	} while (!r4k_ticks[1]);
+
+	if (r4k_ticks[0] != r4k_ticks[1]) {
+		printk("warning: timer counts differ, retrying... ");
+		r4k_ticks[2] = dosample();
+		if (r4k_ticks[2] == r4k_ticks[0]
+		    || r4k_ticks[2] == r4k_ticks[1])
+			r4k_tick = r4k_ticks[2];
+		else {
+			printk("disagreement, using average... ");
+			r4k_tick = (r4k_ticks[0] + r4k_ticks[1]
+				   + r4k_ticks[2]) / 3;
+		}
+	} else
+		r4k_tick = r4k_ticks[0];
+
+	printk("%d [%d.%04d MHz CPU]\n", (int) r4k_tick,
+		(int) (r4k_tick / (500000 / HZ)),
+		(int) (r4k_tick % (500000 / HZ)));
+
+	mips_hpt_frequency = r4k_tick * HZ;
+}
+
+/*
+ * R4k counter based timer interrupt. Works on RM200-225 and possibly
+ * others but not on RM400
+ */
+static void __init sni_cpu_timer_setup(struct irqaction *irq)
+{
+        setup_irq(SNI_MIPS_IRQ_CPU_TIMER, irq);
+}
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+	switch (sni_brd_type) {
+	case SNI_BRD_10:
+	case SNI_BRD_10NEW:
+	case SNI_BRD_TOWER_OASIC:
+	case SNI_BRD_MINITOWER:
+	        sni_a20r_timer_setup (irq);
+	        break;
+
+	case SNI_BRD_PCI_TOWER:
+	case SNI_BRD_RM200:
+	case SNI_BRD_PCI_MTOWER:
+	case SNI_BRD_PCI_DESKTOP:
+	case SNI_BRD_PCI_TOWER_CPLUS:
+	case SNI_BRD_PCI_MTOWER_CPLUS:
+	        sni_cpu_timer_setup (irq);
+	        break;
+	}
+}
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index 735cb87..7316a78 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -137,6 +137,8 @@
 extern void gt64120_time_init(void);
 extern void toshiba_rbtx4927_irq_setup(void);
 
+char *prom_getcmdline(void);
+
 #ifdef CONFIG_PCI
 #define CONFIG_TX4927BUG_WORKAROUND
 #undef TX4927_SUPPORT_COMMAND_IO
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 0f9ff61..28da4e7 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -50,9 +50,6 @@
 	depends on SMP
 	default y
 
-config GENERIC_ISA_DMA
-	bool
-
 config GENERIC_HARDIRQS
 	def_bool y
 
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index ac8ee20..a46bc62b 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -479,7 +479,7 @@
 	return error;
 }
 
-static struct file_operations perf_fops = {
+static const struct file_operations perf_fops = {
 	.llseek = no_llseek,
 	.read = perf_read,
 	.write = perf_write,
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 3c7a3fa..74b3686 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -45,7 +45,7 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 
-char	command_line[COMMAND_LINE_SIZE] __read_mostly;
+char	__initdata command_line[COMMAND_LINE_SIZE] __read_mostly;
 
 /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
 struct proc_dir_entry * proc_runway_root __read_mostly = NULL;
@@ -71,9 +71,9 @@
 	/* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */
 	if (boot_args[0] < 64) {
 		/* called from hpux boot loader */
-		saved_command_line[0] = '\0';
+		boot_command_line[0] = '\0';
 	} else {
-		strcpy(saved_command_line, (char *)__va(boot_args[1]));
+		strcpy(boot_command_line, (char *)__va(boot_args[1]));
 
 #ifdef CONFIG_BLK_DEV_INITRD
 		if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
@@ -84,7 +84,7 @@
 #endif
 	}
 
-	strcpy(command_line, saved_command_line);
+	strcpy(command_line, boot_command_line);
 	*cmdline_p = command_line;
 }
 
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index 29be437..ce3245f 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -579,70 +579,6 @@
 }
 
 
-struct sysinfo32 {
-	s32 uptime;
-	u32 loads[3];
-	u32 totalram;
-	u32 freeram;
-	u32 sharedram;
-	u32 bufferram;
-	u32 totalswap;
-	u32 freeswap;
-	unsigned short procs;
-	u32 totalhigh;
-	u32 freehigh;
-	u32 mem_unit;
-	char _f[12];
-};
-
-/* We used to call sys_sysinfo and translate the result.  But sys_sysinfo
- * undoes the good work done elsewhere, and rather than undoing the
- * damage, I decided to just duplicate the code from sys_sysinfo here.
- */
-
-asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info)
-{
-	struct sysinfo val;
-	int err;
-	unsigned long seq;
-
-	/* We don't need a memset here because we copy the
-	 * struct to userspace once element at a time.
-	 */
-
-	do {
-		seq = read_seqbegin(&xtime_lock);
-		val.uptime = jiffies / HZ;
-
-		val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
-		val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
-		val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
-
-		val.procs = nr_threads;
-	} while (read_seqretry(&xtime_lock, seq));
-
-
-	si_meminfo(&val);
-	si_swapinfo(&val);
-	
-	err = put_user (val.uptime, &info->uptime);
-	err |= __put_user (val.loads[0], &info->loads[0]);
-	err |= __put_user (val.loads[1], &info->loads[1]);
-	err |= __put_user (val.loads[2], &info->loads[2]);
-	err |= __put_user (val.totalram, &info->totalram);
-	err |= __put_user (val.freeram, &info->freeram);
-	err |= __put_user (val.sharedram, &info->sharedram);
-	err |= __put_user (val.bufferram, &info->bufferram);
-	err |= __put_user (val.totalswap, &info->totalswap);
-	err |= __put_user (val.freeswap, &info->freeswap);
-	err |= __put_user (val.procs, &info->procs);
-	err |= __put_user (val.totalhigh, &info->totalhigh);
-	err |= __put_user (val.freehigh, &info->freehigh);
-	err |= __put_user (val.mem_unit, &info->mem_unit);
-	return err ? -EFAULT : 0;
-}
-
-
 /* lseek() needs a wrapper because 'offset' can be negative, but the top
  * half of the argument has been zeroed by syscall.S.
  */
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 701d66a..be8eb9a 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -197,7 +197,7 @@
 	/* struct rusage contains longs... */
 	ENTRY_COMP(wait4)
 	ENTRY_SAME(swapoff)		/* 115 */
-	ENTRY_DIFF(sysinfo)
+	ENTRY_COMP(sysinfo)
 	ENTRY_SAME(shutdown)
 	ENTRY_SAME(fsync)
 	ENTRY_SAME(madvise)
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index bad7d1e..5f1b51a 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -288,17 +288,6 @@
 }
 EXPORT_SYMBOL(do_settimeofday);
 
-/*
- * XXX: We can do better than this.
- * Returns nanoseconds
- */
-
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
-
 void __init start_cpu_itimer(void)
 {
 	unsigned int cpu = smp_processor_id();
diff --git a/arch/parisc/kernel/topology.c b/arch/parisc/kernel/topology.c
index 068b20d..d71cb01 100644
--- a/arch/parisc/kernel/topology.c
+++ b/arch/parisc/kernel/topology.c
@@ -1,5 +1,5 @@
 /*
- * arch/parisc/kernel/topology.c - Populate driverfs with topology information
+ * arch/parisc/kernel/topology.c - Populate sysfs with topology information
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 7b943b4..3b78c27 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -173,10 +173,12 @@
      from .altinstructions and .eh_frame */
   .exit.text : { *(.exit.text) }
   .exit.data : { *(.exit.data) }
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(ASM_PAGE_SIZE);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
   . = ALIGN(32);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 0667f2b..12117db 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -77,12 +77,11 @@
 {
 	char *cp, *end;
 	unsigned long limit;
-	extern char saved_command_line[];
 
 	/* We need this before __setup() functions are called */
 
 	limit = MAX_MEM;
-	for (cp = saved_command_line; *cp; ) {
+	for (cp = boot_command_line; *cp; ) {
 		if (memcmp(cp, "mem=", 4) == 0) {
 			cp += 4;
 			limit = memparse(cp, &end);
@@ -808,9 +807,7 @@
 	for (i = 0; i < npmem_ranges; i++) {
 		unsigned long zones_size[MAX_NR_ZONES] = { 0, };
 
-		/* We have an IOMMU, so all memory can go into a single
-		   ZONE_DMA zone. */
-		zones_size[ZONE_DMA] = pmem_ranges[i].pages;
+		zones_size[ZONE_NORMAL] = pmem_ranges[i].pages;
 
 #ifdef CONFIG_DISCONTIGMEM
 		/* Need to initialize the pfnnid_map before we can initialize
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index f08e80a..6dfbd52 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -620,6 +620,15 @@
 	tristate "Firmware flash interface"
 	depends on PPC64 && RTAS_PROC
 
+config PPC_PMI
+	tristate "Support for PMI"
+	depends PPC_IBM_CELL_BLADE
+	help
+	  PMI (Platform Management Interrupt) is a way to
+	  communicate with the BMC (Baseboard Mangement Controller).
+	  It is used in some IBM Cell blades.
+	default m
+
 config MMIO_NVRAM
 	bool
 	default n
@@ -876,7 +885,7 @@
 
 config ARCH_SPARSEMEM_DEFAULT
 	def_bool y
-	depends on (SMP && PPC_PSERIES) || PPC_CELL
+	depends on (SMP && PPC_PSERIES) || PPC_PS3
 
 config ARCH_POPULATES_NODE_MAP
 	def_bool y
@@ -977,6 +986,10 @@
 	  have an IBM RS/6000 or pSeries machine or a PReP machine, say Y.  If
 	  you have an embedded board, consult your board documentation.
 
+config ZONE_DMA
+	bool
+	default y
+
 config GENERIC_ISA_DMA
 	bool
 	depends on PPC64 || POWER4 || 6xx && !CPM2
diff --git a/arch/powerpc/boot/dts/kuroboxHD.dts b/arch/powerpc/boot/dts/kuroboxHD.dts
new file mode 100644
index 0000000..b897918
--- /dev/null
+++ b/arch/powerpc/boot/dts/kuroboxHD.dts
@@ -0,0 +1,147 @@
+/*
+ * Device Tree Souce for Buffalo KuroboxHD
+ *
+ * Choose CONFIG_LINKSTATION to build a kernel for KuroboxHD, or use
+ * the default configuration linkstation_defconfig.
+ *
+ * Based on sandpoint.dts
+ *
+ * 2006 (c) G. Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * 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.
+
+XXXX add flash parts, rtc, ??
+
+build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts"
+
+
+ */
+
+/ {
+	linux,phandle = <1000>;
+	model = "KuroboxHD";
+	compatible = "linkstation";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		linux,phandle = <2000>;
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,603e { /* Really 8241 */
+			linux,phandle = <2100>;
+			device_type = "cpu";
+			reg = <0>;
+			clock-frequency = <bebc200>;	/* Fixed by bootwrapper */
+			timebase-frequency = <1743000>; /* Fixed by bootwrapper */
+			bus-frequency = <0>;		/* From bootloader */
+			/* Following required by dtc but not used */
+			i-cache-line-size = <0>;
+			d-cache-line-size = <0>;
+			i-cache-size = <4000>;
+			d-cache-size = <4000>;
+		};
+	};
+
+	memory {
+		linux,phandle = <3000>;
+		device_type = "memory";
+		reg = <00000000 04000000>;
+	};
+
+	soc10x { /* AFAICT need to make soc for 8245's uarts to be defined */
+		linux,phandle = <4000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		compatible = "mpc10x";
+		store-gathering = <0>; /* 0 == off, !0 == on */
+		reg = <80000000 00100000>;
+		ranges = <80000000 80000000 70000000	/* pci mem space */
+			  fc000000 fc000000 00100000	/* EUMB */
+			  fe000000 fe000000 00c00000	/* pci i/o space */
+			  fec00000 fec00000 00300000	/* pci cfg regs */
+			  fef00000 fef00000 00100000>;	/* pci iack */
+
+		i2c@80003000 {
+			linux,phandle = <4300>;
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <80003000 1000>;
+			interrupts = <5 2>;
+			interrupt-parent = <4400>;
+		};
+
+		serial@80004500 {
+			linux,phandle = <4511>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <80004500 8>;
+			clock-frequency = <5d08d88>;
+			current-speed = <2580>;
+			interrupts = <9 2>;
+			interrupt-parent = <4400>;
+		};
+
+		serial@80004600 {
+			linux,phandle = <4512>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <80004600 8>;
+			clock-frequency = <5d08d88>;
+			current-speed = <e100>;
+			interrupts = <a 0>;
+			interrupt-parent = <4400>;
+		};
+
+		pic@80040000 {
+			linux,phandle = <4400>;
+			#interrupt-cells = <2>;
+			#address-cells = <0>;
+			device_type = "open-pic";
+			compatible = "chrp,open-pic";
+			interrupt-controller;
+			reg = <80040000 40000>;
+			built-in;
+		};
+
+		pci@fec00000 {
+			linux,phandle = <4500>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			device_type = "pci";
+			compatible = "mpc10x-pci";
+			reg = <fec00000 400000>;
+			ranges = <01000000 0        0 fe000000 0 00c00000
+				  02000000 0 80000000 80000000 0 70000000>;
+			bus-range = <0 ff>;
+			clock-frequency = <7f28155>;
+			interrupt-parent = <4400>;
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x11 - IRQ0 ETH */
+				5800 0 0 1 4400 0 1
+				5800 0 0 2 4400 1 1
+				5800 0 0 3 4400 2 1
+				5800 0 0 4 4400 3 1
+				/* IDSEL 0x12 - IRQ1 IDE0 */
+				6000 0 0 1 4400 1 1
+				6000 0 0 2 4400 2 1
+				6000 0 0 3 4400 3 1
+				6000 0 0 4 4400 0 1
+				/* IDSEL 0x14 - IRQ3 USB2.0 */
+				7000 0 0 1 4400 3 1
+				7000 0 0 2 4400 3 1
+				7000 0 0 3 4400 3 1
+				7000 0 0 4 4400 3 1
+			>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts
index d06b0b0..7531027 100644
--- a/arch/powerpc/boot/dts/kuroboxHG.dts
+++ b/arch/powerpc/boot/dts/kuroboxHG.dts
@@ -35,7 +35,6 @@
 
 		PowerPC,603e { /* Really 8241 */
 			linux,phandle = <2100>;
-			linux,boot-cpu;
 			device_type = "cpu";
 			reg = <0>;
 			clock-frequency = <fdad680>;	/* Fixed by bootwrapper */
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index 1868707..c03103c 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -1,7 +1,7 @@
 /*
  * Lite5200 board Device Tree Source
  *
- * Copyright 2006 Secret Lab Technologies Ltd.
+ * Copyright 2006-2007 Secret Lab Technologies Ltd.
  * Grant Likely <grant.likely@secretlab.ca>
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -17,8 +17,9 @@
  */
 
 / {
-	model = "Lite5200";
-	compatible = "lite5200\0lite52xx\0mpc5200\0mpc52xx";
+	model = "fsl,lite5200";
+	// revision = "1.0";
+	compatible = "fsl,lite5200\0generic-mpc5200";
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -47,14 +48,17 @@
 	};
 
 	soc5200@f0000000 {
+		model = "fsl,mpc5200";
+		revision = ""			// from bootloader
 		#interrupt-cells = <3>;
 		device_type = "soc";
 		ranges = <0 f0000000 f0010000>;
 		reg = <f0000000 00010000>;
 		bus-frequency = <0>;		// from bootloader
+		system-frequency = <0>;		// from bootloader
 
 		cdm@200 {
-			compatible = "mpc5200-cdm\0mpc52xx-cdm";
+			compatible = "mpc5200-cdm";
 			reg = <200 38>;
 		};
 
@@ -64,77 +68,86 @@
 			interrupt-controller;
 			#interrupt-cells = <3>;
 			device_type = "interrupt-controller";
-			compatible = "mpc5200-pic\0mpc52xx-pic";
+			compatible = "mpc5200-pic";
 			reg = <500 80>;
 			built-in;
 		};
 
 		gpt@600 {	// General Purpose Timer
-			compatible = "mpc5200-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <0>;
 			reg = <600 10>;
 			interrupts = <1 9 0>;
 			interrupt-parent = <500>;
+			has-wdt;
 		};
 
 		gpt@610 {	// General Purpose Timer
-			compatible = "mpc5200-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <1>;
 			reg = <610 10>;
 			interrupts = <1 a 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@620 {	// General Purpose Timer
-			compatible = "mpc5200-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <2>;
 			reg = <620 10>;
 			interrupts = <1 b 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@630 {	// General Purpose Timer
-			compatible = "mpc5200-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <3>;
 			reg = <630 10>;
 			interrupts = <1 c 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@640 {	// General Purpose Timer
-			compatible = "mpc5200-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <4>;
 			reg = <640 10>;
 			interrupts = <1 d 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@650 {	// General Purpose Timer
-			compatible = "mpc5200-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <5>;
 			reg = <650 10>;
 			interrupts = <1 e 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@660 {	// General Purpose Timer
-			compatible = "mpc5200-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <6>;
 			reg = <660 10>;
 			interrupts = <1 f 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@670 {	// General Purpose Timer
-			compatible = "mpc5200-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <7>;
 			reg = <670 10>;
 			interrupts = <1 10 0>;
 			interrupt-parent = <500>;
 		};
 
 		rtc@800 {	// Real time clock
-			compatible = "mpc5200-rtc\0mpc52xx-rtc";
+			compatible = "mpc5200-rtc";
 			device_type = "rtc";
 			reg = <800 100>;
 			interrupts = <1 5 0 1 6 0>;
@@ -143,7 +156,8 @@
 
 		mscan@900 {
 			device_type = "mscan";
-			compatible = "mpc5200-mscan\0mpc52xx-mscan";
+			compatible = "mpc5200-mscan";
+			cell-index = <0>;
 			interrupts = <2 11 0>;
 			interrupt-parent = <500>;
 			reg = <900 80>;
@@ -151,21 +165,22 @@
 
 		mscan@980 {
 			device_type = "mscan";
-			compatible = "mpc5200-mscan\0mpc52xx-mscan";
+			compatible = "mpc5200-mscan";
+			cell-index = <1>;
 			interrupts = <1 12 0>;
 			interrupt-parent = <500>;
 			reg = <980 80>;
 		};
 
 		gpio@b00 {
-			compatible = "mpc5200-gpio\0mpc52xx-gpio";
+			compatible = "mpc5200-gpio";
 			reg = <b00 40>;
 			interrupts = <1 7 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpio-wkup@b00 {
-			compatible = "mpc5200-gpio-wkup\0mpc52xx-gpio-wkup";
+			compatible = "mpc5200-gpio-wkup";
 			reg = <c00 40>;
 			interrupts = <1 8 0 0 3 0>;
 			interrupt-parent = <500>;
@@ -176,7 +191,7 @@
 			#size-cells = <2>;
 			#address-cells = <3>;
 			device_type = "pci";
-			compatible = "mpc5200-pci\0mpc52xx-pci";
+			compatible = "mpc5200-pci";
 			reg = <d00 100>;
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <c000 0 0 1 500 0 0 3
@@ -194,7 +209,7 @@
 
 		spi@f00 {
 			device_type = "spi";
-			compatible = "mpc5200-spi\0mpc52xx-spi";
+			compatible = "mpc5200-spi";
 			reg = <f00 20>;
 			interrupts = <2 d 0 2 e 0>;
 			interrupt-parent = <500>;
@@ -202,7 +217,7 @@
 
 		usb@1000 {
 			device_type = "usb-ohci-be";
-			compatible = "mpc5200-ohci\0mpc52xx-ohci\0ohci-be";
+			compatible = "mpc5200-ohci\0ohci-be";
 			reg = <1000 ff>;
 			interrupts = <2 6 0>;
 			interrupt-parent = <500>;
@@ -210,7 +225,7 @@
 
 		bestcomm@1200 {
 			device_type = "dma-controller";
-			compatible = "mpc5200-bestcomm\0mpc52xx-bestcomm";
+			compatible = "mpc5200-bestcomm";
 			reg = <1200 80>;
 			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
 			              3 4 0  3 5 0  3 6 0  3 7 0
@@ -220,67 +235,73 @@
 		};
 
 		xlb@1f00 {
-			compatible = "mpc5200-xlb\0mpc52xx-xlb";
+			compatible = "mpc5200-xlb";
 			reg = <1f00 100>;
 		};
 
 		serial@2000 {		// PSC1
 			device_type = "serial";
-			compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart";
+			compatible = "mpc5200-psc-uart";
 			port-number = <0>;  // Logical port assignment
+			cell-index = <0>;
 			reg = <2000 100>;
 			interrupts = <2 1 0>;
 			interrupt-parent = <500>;
 		};
 
-		// PSC2 in spi mode example
-		spi@2200 {		// PSC2
-			device_type = "spi";
-			compatible = "mpc5200-psc-spi\0mpc52xx-psc-spi";
-			reg = <2200 100>;
-			interrupts = <2 2 0>;
-			interrupt-parent = <500>;
-		};
+		// PSC2 in ac97 mode example
+		//ac97@2200 {		// PSC2
+		//	device_type = "sound";
+		//	compatible = "mpc5200-psc-ac97";
+		//	cell-index = <1>;
+		//	reg = <2200 100>;
+		//	interrupts = <2 2 0>;
+		//	interrupt-parent = <500>;
+		//};
 
 		// PSC3 in CODEC mode example
-		i2s@2400 {		// PSC3
-			device_type = "sound";
-			compatible = "mpc5200-psc-i2s\0mpc52xx-psc-i2s";
-			reg = <2400 100>;
-			interrupts = <2 3 0>;
-			interrupt-parent = <500>;
-		};
+		//i2s@2400 {		// PSC3
+		//	device_type = "sound";
+		//	compatible = "mpc5200-psc-i2s";
+		//	cell-index = <2>;
+		//	reg = <2400 100>;
+		//	interrupts = <2 3 0>;
+		//	interrupt-parent = <500>;
+		//};
 
-		// PSC4 unconfigured
+		// PSC4 in uart mode example
 		//serial@2600 {		// PSC4
 		//	device_type = "serial";
-		//	compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart";
+		//	compatible = "mpc5200-psc-uart";
+		//	cell-index = <3>;
 		//	reg = <2600 100>;
 		//	interrupts = <2 b 0>;
 		//	interrupt-parent = <500>;
 		//};
 
-		// PSC5 unconfigured
+		// PSC5 in uart mode example
 		//serial@2800 {		// PSC5
 		//	device_type = "serial";
-		//	compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart";
+		//	compatible = "mpc5200-psc-uart";
+		//	cell-index = <4>;
 		//	reg = <2800 100>;
 		//	interrupts = <2 c 0>;
 		//	interrupt-parent = <500>;
 		//};
 
-		// PSC6 in AC97 mode example
-		ac97@2c00 {		// PSC6
-			device_type = "sound";
-			compatible = "mpc5200-psc-ac97\0mpc52xx-psc-ac97";
-			reg = <2c00 100>;
-			interrupts = <2 4 0>;
-			interrupt-parent = <500>;
-		};
+		// PSC6 in spi mode example
+		//spi@2c00 {		// PSC6
+		//	device_type = "spi";
+		//	compatible = "mpc5200-psc-spi";
+		//	cell-index = <5>;
+		//	reg = <2c00 100>;
+		//	interrupts = <2 4 0>;
+		//	interrupt-parent = <500>;
+		//};
 
 		ethernet@3000 {
 			device_type = "network";
-			compatible = "mpc5200-fec\0mpc52xx-fec";
+			compatible = "mpc5200-fec";
 			reg = <3000 800>;
 			mac-address = [ 02 03 04 05 06 07 ]; // Bad!
 			interrupts = <2 5 0>;
@@ -289,7 +310,7 @@
 
 		ata@3a00 {
 			device_type = "ata";
-			compatible = "mpc5200-ata\0mpc52xx-ata";
+			compatible = "mpc5200-ata";
 			reg = <3a00 100>;
 			interrupts = <2 7 0>;
 			interrupt-parent = <500>;
@@ -297,7 +318,8 @@
 
 		i2c@3d00 {
 			device_type = "i2c";
-			compatible = "mpc5200-i2c\0mpc52xx-i2c";
+			compatible = "mpc5200-i2c";
+			cell-index = <0>;
 			reg = <3d00 40>;
 			interrupts = <2 f 0>;
 			interrupt-parent = <500>;
@@ -305,14 +327,15 @@
 
 		i2c@3d40 {
 			device_type = "i2c";
-			compatible = "mpc5200-i2c\0mpc52xx-i2c";
+			compatible = "mpc5200-i2c";
+			cell-index = <1>;
 			reg = <3d40 40>;
 			interrupts = <2 10 0>;
 			interrupt-parent = <500>;
 		};
 		sram@8000 {
 			device_type = "sram";
-			compatible = "mpc5200-sram\0mpc52xx-sram\0sram";
+			compatible = "mpc5200-sram\0sram";
 			reg = <8000 4000>;
 		};
 	};
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index 5bb2760..3875ca9 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -1,7 +1,7 @@
 /*
  * Lite5200B board Device Tree Source
  *
- * Copyright 2006 Secret Lab Technologies Ltd.
+ * Copyright 2006-2007 Secret Lab Technologies Ltd.
  * Grant Likely <grant.likely@secretlab.ca>
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -17,8 +17,9 @@
  */
 
 / {
-	model = "Lite5200b";
-	compatible = "lite5200b\0lite52xx\0mpc5200b\0mpc52xx";
+	model = "fsl,lite5200b";
+	// revision = "1.0";
+	compatible = "fsl,lite5200b\0generic-mpc5200";
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -47,14 +48,17 @@
 	};
 
 	soc5200@f0000000 {
+		model = "fsl,mpc5200b";
+		revision = "";			// from bootloader
 		#interrupt-cells = <3>;
 		device_type = "soc";
 		ranges = <0 f0000000 f0010000>;
 		reg = <f0000000 00010000>;
 		bus-frequency = <0>;		// from bootloader
+		system-frequency = <0>;		// from bootloader
 
 		cdm@200 {
-			compatible = "mpc5200b-cdm\0mpc52xx-cdm";
+			compatible = "mpc5200b-cdm\0mpc5200-cdm";
 			reg = <200 38>;
 		};
 
@@ -64,77 +68,86 @@
 			interrupt-controller;
 			#interrupt-cells = <3>;
 			device_type = "interrupt-controller";
-			compatible = "mpc5200b-pic\0mpc52xx-pic";
+			compatible = "mpc5200b-pic\0mpc5200-pic";
 			reg = <500 80>;
 			built-in;
 		};
 
 		gpt@600 {	// General Purpose Timer
-			compatible = "mpc5200b-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200b-gpt\0mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <0>;
 			reg = <600 10>;
 			interrupts = <1 9 0>;
 			interrupt-parent = <500>;
+			has-wdt;
 		};
 
 		gpt@610 {	// General Purpose Timer
-			compatible = "mpc5200b-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200b-gpt\0mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <1>;
 			reg = <610 10>;
 			interrupts = <1 a 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@620 {	// General Purpose Timer
-			compatible = "mpc5200b-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200b-gpt\0mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <2>;
 			reg = <620 10>;
 			interrupts = <1 b 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@630 {	// General Purpose Timer
-			compatible = "mpc5200b-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200b-gpt\0mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <3>;
 			reg = <630 10>;
 			interrupts = <1 c 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@640 {	// General Purpose Timer
-			compatible = "mpc5200b-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200b-gpt\0mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <4>;
 			reg = <640 10>;
 			interrupts = <1 d 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@650 {	// General Purpose Timer
-			compatible = "mpc5200b-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200b-gpt\0mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <5>;
 			reg = <650 10>;
 			interrupts = <1 e 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@660 {	// General Purpose Timer
-			compatible = "mpc5200b-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200b-gpt\0mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <6>;
 			reg = <660 10>;
 			interrupts = <1 f 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpt@670 {	// General Purpose Timer
-			compatible = "mpc5200b-gpt\0mpc52xx-gpt";
+			compatible = "mpc5200b-gpt\0mpc5200-gpt";
 			device_type = "gpt";
+			cell-index = <7>;
 			reg = <670 10>;
 			interrupts = <1 10 0>;
 			interrupt-parent = <500>;
 		};
 
 		rtc@800 {	// Real time clock
-			compatible = "mpc5200b-rtc\0mpc52xx-rtc";
+			compatible = "mpc5200b-rtc\0mpc5200-rtc";
 			device_type = "rtc";
 			reg = <800 100>;
 			interrupts = <1 5 0 1 6 0>;
@@ -143,7 +156,8 @@
 
 		mscan@900 {
 			device_type = "mscan";
-			compatible = "mpc5200b-mscan\0mpc52xx-mscan";
+			compatible = "mpc5200b-mscan\0mpc5200-mscan";
+			cell-index = <0>;
 			interrupts = <2 11 0>;
 			interrupt-parent = <500>;
 			reg = <900 80>;
@@ -151,21 +165,22 @@
 
 		mscan@980 {
 			device_type = "mscan";
-			compatible = "mpc5200b-mscan\0mpc52xx-mscan";
+			compatible = "mpc5200b-mscan\0mpc5200-mscan";
+			cell-index = <1>;
 			interrupts = <1 12 0>;
 			interrupt-parent = <500>;
 			reg = <980 80>;
 		};
 
 		gpio@b00 {
-			compatible = "mpc5200b-gpio\0mpc52xx-gpio";
+			compatible = "mpc5200b-gpio\0mpc5200-gpio";
 			reg = <b00 40>;
 			interrupts = <1 7 0>;
 			interrupt-parent = <500>;
 		};
 
 		gpio-wkup@b00 {
-			compatible = "mpc5200b-gpio-wkup\0mpc52xx-gpio-wkup";
+			compatible = "mpc5200b-gpio-wkup\0mpc5200-gpio-wkup";
 			reg = <c00 40>;
 			interrupts = <1 8 0 0 3 0>;
 			interrupt-parent = <500>;
@@ -176,7 +191,7 @@
 			#size-cells = <2>;
 			#address-cells = <3>;
 			device_type = "pci";
-			compatible = "mpc5200b-pci\0mpc52xx-pci";
+			compatible = "mpc5200b-pci\0mpc5200-pci";
 			reg = <d00 100>;
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <c000 0 0 1 500 0 0 3 // 1st slot
@@ -199,7 +214,7 @@
 
 		spi@f00 {
 			device_type = "spi";
-			compatible = "mpc5200b-spi\0mpc52xx-spi";
+			compatible = "mpc5200b-spi\0mpc5200-spi";
 			reg = <f00 20>;
 			interrupts = <2 d 0 2 e 0>;
 			interrupt-parent = <500>;
@@ -207,7 +222,7 @@
 
 		usb@1000 {
 			device_type = "usb-ohci-be";
-			compatible = "mpc5200b-ohci\0mpc52xx-ohci\0ohci-be";
+			compatible = "mpc5200b-ohci\0mpc5200-ohci\0ohci-be";
 			reg = <1000 ff>;
 			interrupts = <2 6 0>;
 			interrupt-parent = <500>;
@@ -215,7 +230,7 @@
 
 		bestcomm@1200 {
 			device_type = "dma-controller";
-			compatible = "mpc5200b-bestcomm\0mpc52xx-bestcomm";
+			compatible = "mpc5200b-bestcomm\0mpc5200-bestcomm";
 			reg = <1200 80>;
 			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
 			              3 4 0  3 5 0  3 6 0  3 7 0
@@ -225,67 +240,73 @@
 		};
 
 		xlb@1f00 {
-			compatible = "mpc5200b-xlb\0mpc52xx-xlb";
+			compatible = "mpc5200b-xlb\0mpc5200-xlb";
 			reg = <1f00 100>;
 		};
 
 		serial@2000 {		// PSC1
 			device_type = "serial";
-			compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart";
+			compatible = "mpc5200b-psc-uart\0mpc5200-psc-uart";
 			port-number = <0>;  // Logical port assignment
+			cell-index = <0>;
 			reg = <2000 100>;
 			interrupts = <2 1 0>;
 			interrupt-parent = <500>;
 		};
 
-		// PSC2 in spi mode example
-		spi@2200 {		// PSC2
-			device_type = "spi";
-			compatible = "mpc5200b-psc-spi\0mpc52xx-psc-spi";
-			reg = <2200 100>;
-			interrupts = <2 2 0>;
-			interrupt-parent = <500>;
-		};
+		// PSC2 in ac97 mode example
+		//ac97@2200 {		// PSC2
+		//	device_type = "sound";
+		//	compatible = "mpc5200b-psc-ac97\0mpc5200-psc-ac97";
+		//	cell-index = <1>;
+		//	reg = <2200 100>;
+		//	interrupts = <2 2 0>;
+		//	interrupt-parent = <500>;
+		//};
 
 		// PSC3 in CODEC mode example
-		i2s@2400 {		// PSC3
-			device_type = "sound";
-			compatible = "mpc5200b-psc-i2s\0mpc52xx-psc-i2s";
-			reg = <2400 100>;
-			interrupts = <2 3 0>;
-			interrupt-parent = <500>;
-		};
+		//i2s@2400 {		// PSC3
+		//	device_type = "sound";
+		//	compatible = "mpc5200b-psc-i2s"; //not 5200 compatible
+		//	cell-index = <2>;
+		//	reg = <2400 100>;
+		//	interrupts = <2 3 0>;
+		//	interrupt-parent = <500>;
+		//};
 
-		// PSC4 unconfigured
+		// PSC4 in uart mode example
 		//serial@2600 {		// PSC4
 		//	device_type = "serial";
-		//	compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart";
+		//	compatible = "mpc5200b-psc-uart\0mpc5200-psc-uart";
+		//	cell-index = <3>;
 		//	reg = <2600 100>;
 		//	interrupts = <2 b 0>;
 		//	interrupt-parent = <500>;
 		//};
 
-		// PSC5 unconfigured
+		// PSC5 in uart mode example
 		//serial@2800 {		// PSC5
 		//	device_type = "serial";
-		//	compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart";
+		//	compatible = "mpc5200b-psc-uart\0mpc5200-psc-uart";
+		//	cell-index = <4>;
 		//	reg = <2800 100>;
 		//	interrupts = <2 c 0>;
 		//	interrupt-parent = <500>;
 		//};
 
-		// PSC6 in AC97 mode example
-		ac97@2c00 {		// PSC6
-			device_type = "sound";
-			compatible = "mpc5200b-psc-ac97\0mpc52xx-psc-ac97";
-			reg = <2c00 100>;
-			interrupts = <2 4 0>;
-			interrupt-parent = <500>;
-		};
+		// PSC6 in spi mode example
+		//spi@2c00 {		// PSC6
+		//	device_type = "spi";
+		//	compatible = "mpc5200b-psc-spi\0mpc5200-psc-spi";
+		//	cell-index = <5>;
+		//	reg = <2c00 100>;
+		//	interrupts = <2 4 0>;
+		//	interrupt-parent = <500>;
+		//};
 
 		ethernet@3000 {
 			device_type = "network";
-			compatible = "mpc5200b-fec\0mpc52xx-fec";
+			compatible = "mpc5200b-fec\0mpc5200-fec";
 			reg = <3000 800>;
 			mac-address = [ 02 03 04 05 06 07 ]; // Bad!
 			interrupts = <2 5 0>;
@@ -294,7 +315,7 @@
 
 		ata@3a00 {
 			device_type = "ata";
-			compatible = "mpc5200b-ata\0mpc52xx-ata";
+			compatible = "mpc5200b-ata\0mpc5200-ata";
 			reg = <3a00 100>;
 			interrupts = <2 7 0>;
 			interrupt-parent = <500>;
@@ -302,7 +323,8 @@
 
 		i2c@3d00 {
 			device_type = "i2c";
-			compatible = "mpc5200b-i2c\0mpc52xx-i2c";
+			compatible = "mpc5200b-i2c\0mpc5200-i2c";
+			cell-index = <0>;
 			reg = <3d00 40>;
 			interrupts = <2 f 0>;
 			interrupt-parent = <500>;
@@ -310,14 +332,15 @@
 
 		i2c@3d40 {
 			device_type = "i2c";
-			compatible = "mpc5200b-i2c\0mpc52xx-i2c";
+			compatible = "mpc5200b-i2c\0mpc5200-i2c";
+			cell-index = <1>;
 			reg = <3d40 40>;
 			interrupts = <2 10 0>;
 			interrupt-parent = <500>;
 		};
 		sram@8000 {
 			device_type = "sram";
-			compatible = "mpc5200b-sram\0mpc52xx-sram\0sram";
+			compatible = "mpc5200b-sram\0mpc5200-sram\0sram";
 			reg = <8000 4000>;
 		};
 	};
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
index c4d9562..41d0720 100644
--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -36,7 +36,6 @@
 			bus-frequency = <0>;		// From U-Boot
 			32-bit;
 			linux,phandle = <201>;
-			linux,boot-cpu;
 		};
 	};
 
diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts
index 26b44f7..260b2e4 100644
--- a/arch/powerpc/boot/dts/mpc8272ads.dts
+++ b/arch/powerpc/boot/dts/mpc8272ads.dts
@@ -34,7 +34,6 @@
                        clock-frequency = <0>;
                        32-bit;
                        linux,phandle = <201>;
-                       linux,boot-cpu;
                };
        };
 
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
new file mode 100644
index 0000000..6d72190
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -0,0 +1,215 @@
+/*
+ * MPC8313E RDB Device Tree Source
+ *
+ * Copyright 2005, 2006, 2007 Freescale Semiconductor 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.
+ */
+
+/ {
+	model = "MPC8313ERDB";
+	compatible = "MPC8313ERDB", "MPC831xRDB", "MPC83xxRDB";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8313@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <4000>;		// L1, 16K
+			i-cache-size = <4000>;		// L1, 16K
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 08000000>;	// 128MB at 0
+	};
+
+	soc8313@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00000200>;
+		bus-frequency = <0>;
+
+		wdt@200 {
+			device_type = "watchdog";
+			compatible = "mpc83xx_wdt";
+			reg = <200 100>;
+		};
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <e 8>;
+			interrupt-parent = < &ipic >;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <f 8>;
+			interrupt-parent = < &ipic >;
+			dfsrr;
+		};
+
+		spi@7000 {
+			device_type = "spi";
+			compatible = "mpc83xx_spi";
+			reg = <7000 1000>;
+			interrupts = <10 8>;
+			interrupt-parent = < &ipic >;
+			mode = <0>;
+		};
+
+		/* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
+		usb@23000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-dr";
+			reg = <23000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = < &ipic >;
+			interrupts = <26 8>;
+			phy_type = "utmi_wide";
+		};
+
+		mdio@24520 {
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			phy1: ethernet-phy@1 {
+				interrupt-parent = < &ipic >;
+				interrupts = <13 8>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+			phy4: ethernet-phy@4 {
+				interrupt-parent = < &ipic >;
+				interrupts = <14 8>;
+				reg = <4>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <25 8 24 8 23 8>;
+			interrupt-parent = < &ipic >;
+			phy-handle = < &phy1 >;
+		};
+
+		ethernet@25000 {
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <22 8 21 8 20 8>;
+			interrupt-parent = < &ipic >;
+			phy-handle = < &phy4 >;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;
+			interrupts = <9 8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <0>;
+			interrupts = <a 8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		pci@8500 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+					/* IDSEL 0x0E -mini PCI */
+					 7000 0 0 1 &ipic 12 8
+					 7000 0 0 2 &ipic 12 8
+					 7000 0 0 3 &ipic 12 8
+					 7000 0 0 4 &ipic 12 8
+
+					/* IDSEL 0x0F - PCI slot */
+					 7800 0 0 1 &ipic 11 8
+					 7800 0 0 2 &ipic 12 8
+					 7800 0 0 3 &ipic 11 8
+					 7800 0 0 4 &ipic 12 8>;
+			interrupt-parent = < &ipic >;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 90000000 90000000 0 10000000
+			          42000000 0 80000000 80000000 0 10000000
+			          01000000 0 00000000 e2000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8500 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		crypto@30000 {
+			device_type = "crypto";
+			model = "SEC2";
+			compatible = "talitos";
+			reg = <30000 7000>;
+			interrupts = <b 8>;
+			interrupt-parent = < &ipic >;
+			/* Rev. 2.2 */
+			num-channels = <1>;
+			channel-fifo-len = <18>;
+			exec-units-mask = <0000004c>;
+			descriptor-types-mask = <0122003f>;
+		};
+
+		/* IPIC
+		 * interrupts cell = <intr #, sense>
+		 * sense values match linux IORESOURCE_IRQ_* defines:
+		 * sense == 8: Level, low assertion
+		 * sense == 2: Edge, high-to-low change
+		 */
+		ipic: pic@700 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <700 100>;
+			built-in;
+			device_type = "ipic";
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8323emds.dts b/arch/powerpc/boot/dts/mpc8323emds.dts
deleted file mode 100644
index fa7ef24..0000000
--- a/arch/powerpc/boot/dts/mpc8323emds.dts
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * MPC8323E EMDS Device Tree Source
- *
- * Copyright 2006 Freescale Semiconductor 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.
- */
-
-/ {
-	model = "MPC8323EMDS";
-	compatible = "MPC83xx";
-	#address-cells = <1>;
-	#size-cells = <1>;
-	linux,phandle = <100>;
-
-	cpus {
-		#cpus = <1>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		linux,phandle = <200>;
-
-		PowerPC,8323@0 {
-			device_type = "cpu";
-			reg = <0>;
-			d-cache-line-size = <20>;	// 32 bytes
-			i-cache-line-size = <20>;	// 32 bytes
-			d-cache-size = <4000>;		// L1, 16K
-			i-cache-size = <4000>;		// L1, 16K
-			timebase-frequency = <0>;
-			bus-frequency = <0>;
-			clock-frequency = <0>;
-			32-bit;
-			linux,phandle = <201>;
-			linux,boot-cpu;
-		};
-	};
-
-	memory {
-		device_type = "memory";
-		linux,phandle = <300>;
-		reg = <00000000 08000000>;
-	};
-
-	bcsr@f8000000 {
-		device_type = "board-control";
-		reg = <f8000000 8000>;
-	};
-
-	soc8323@e0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		#interrupt-cells = <2>;
-		device_type = "soc";
-		ranges = <0 e0000000 00100000>;
-		reg = <e0000000 00000200>;
-		bus-frequency = <7DE2900>;
-
-		wdt@200 {
-			device_type = "watchdog";
-			compatible = "mpc83xx_wdt";
-			reg = <200 100>;
-		};
-
-		i2c@3000 {
-			device_type = "i2c";
-			compatible = "fsl-i2c";
-			reg = <3000 100>;
-			interrupts = <e 8>;
-			interrupt-parent = <700>;
-			dfsrr;
-		};
-
-		serial@4500 {
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <4500 100>;
-			clock-frequency = <0>;
-			interrupts = <9 8>;
-			interrupt-parent = <700>;
-		};
-
-		serial@4600 {
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <4600 100>;
-			clock-frequency = <0>;
-			interrupts = <a 8>;
-			interrupt-parent = <700>;
-		};
-
-		crypto@30000 {
-			device_type = "crypto";
-			model = "SEC2";
-			compatible = "talitos";
-			reg = <30000 7000>;
-			interrupts = <b 8>;
-			interrupt-parent = <700>;
-			/* Rev. 2.2 */
-			num-channels = <1>;
-			channel-fifo-len = <18>;
-			exec-units-mask = <0000004c>;
-			descriptor-types-mask = <0122003f>;
-		};
-
-		pci@8500 {
-			linux,phandle = <8500>;
-			interrupt-map-mask = <f800 0 0 7>;
-			interrupt-map = <
-					/* IDSEL 0x11 AD17 */
-					 8800 0 0 1 700 14 8
-					 8800 0 0 2 700 15 8
-					 8800 0 0 3 700 16 8
-					 8800 0 0 4 700 17 8
-
-					/* IDSEL 0x12 AD18 */
-					 9000 0 0 1 700 16 8
-					 9000 0 0 2 700 17 8
-					 9000 0 0 3 700 14 8
-					 9000 0 0 4 700 15 8
-
-					/* IDSEL 0x13 AD19 */
-					 9800 0 0 1 700 17 8
-					 9800 0 0 2 700 14 8
-					 9800 0 0 3 700 15 8
-					 9800 0 0 4 700 16 8
-
-					/* IDSEL 0x15 AD21*/
-					 a800 0 0 1 700 14 8
-					 a800 0 0 2 700 15 8
-					 a800 0 0 3 700 16 8
-					 a800 0 0 4 700 17 8
-
-					/* IDSEL 0x16 AD22*/
-					 b000 0 0 1 700 17 8
-					 b000 0 0 2 700 14 8
-					 b000 0 0 3 700 15 8
-					 b000 0 0 4 700 16 8
-
-					/* IDSEL 0x17 AD23*/
-					 b800 0 0 1 700 16 8
-					 b800 0 0 2 700 17 8
-					 b800 0 0 3 700 14 8
-					 b800 0 0 4 700 15 8
-
-					/* IDSEL 0x18 AD24*/
-					 c000 0 0 1 700 15 8
-					 c000 0 0 2 700 16 8
-					 c000 0 0 3 700 17 8
-					 c000 0 0 4 700 14 8>;
-			interrupt-parent = <700>;
-			interrupts = <42 8>;
-			bus-range = <0 0>;
-			ranges = <02000000 0 a0000000 90000000 0 10000000
-			          42000000 0 80000000 80000000 0 10000000
-			          01000000 0 00000000 d0000000 0 00100000>;
-			clock-frequency = <0>;
-			#interrupt-cells = <1>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			reg = <8500 100>;
-			compatible = "83xx";
-			device_type = "pci";
-		};
-
-		pic@700 {
-			linux,phandle = <700>;
-			interrupt-controller;
-			#address-cells = <0>;
-			#interrupt-cells = <2>;
-			reg = <700 100>;
-			built-in;
-			device_type = "ipic";
-		};
-		
-		par_io@1400 {
-			reg = <1400 100>;
-			device_type = "par_io";
-			num-ports = <7>;
-
-			ucc_pin@03 {
-				linux,phandle = <140003>;
-				pio-map = <
-			/* port  pin  dir  open_drain  assignment  has_irq */
-					3  4  3  0  2  0  /* MDIO */
-					3  5  1  0  2  0  /* MDC */
-					0  d  2  0  1  0 	/* RX_CLK (CLK9) */
-					3 18  2  0  1  0 	/* TX_CLK (CLK10) */
-					1  1  1  0  1  0 	/* TxD1 */
-					1  0  1  0  1  0 	/* TxD0 */
-					1  1  1  0  1  0 	/* TxD1 */
-					1  2  1  0  1  0 	/* TxD2 */
-					1  3  1  0  1  0 	/* TxD3 */
-					1  4  2  0  1  0 	/* RxD0 */
-					1  5  2  0  1  0 	/* RxD1 */
-					1  6  2  0  1  0 	/* RxD2 */
-					1  7  2  0  1  0 	/* RxD3 */
-					1  8  2  0  1  0 	/* RX_ER */
-					1  9  1  0  1  0 	/* TX_ER */
-					1  a  2  0  1  0 	/* RX_DV */
-					1  b  2  0  1  0 	/* COL */
-					1  c  1  0  1  0 	/* TX_EN */
-					1  d  2  0  1  0>;/* CRS */
-			};
-			ucc_pin@04 {
-				linux,phandle = <140004>;
-				pio-map = <
-			/* port  pin  dir  open_drain  assignment  has_irq */
-					3 1f  2  0  1  0 	/* RX_CLK (CLK7) */
-					3  6  2  0  1  0 	/* TX_CLK (CLK8) */
-					1 12  1  0  1  0 	/* TxD0 */
-					1 13  1  0  1  0 	/* TxD1 */
-					1 14  1  0  1  0 	/* TxD2 */
-					1 15  1  0  1  0 	/* TxD3 */
-					1 16  2  0  1  0 	/* RxD0 */
-					1 17  2  0  1  0 	/* RxD1 */
-					1 18  2  0  1  0 	/* RxD2 */
-					1 19  2  0  1  0 	/* RxD3 */
-					1 1a  2  0  1  0 	/* RX_ER */
-					1 1b  1  0  1  0 	/* TX_ER */
-					1 1c  2  0  1  0 	/* RX_DV */
-					1 1d  2  0  1  0 	/* COL */
-					1 1e  1  0  1  0 	/* TX_EN */
-					1 1f  2  0  1  0>;/* CRS */
-			};
-		};
-	};
-
-	qe@e0100000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		device_type = "qe";
-		model = "QE";
-		ranges = <0 e0100000 00100000>;
-		reg = <e0100000 480>;
-		brg-frequency = <0>;
-		bus-frequency = <BCD3D80>;
-		
-		muram@10000 {
-			device_type = "muram";
-			ranges = <0 00010000 00004000>;
-	
-			data-only@0 {
-				reg = <0 4000>;
-			};
-		};
-
-		spi@4c0 {
-			device_type = "spi";
-			compatible = "fsl_spi";
-			reg = <4c0 40>;
-			interrupts = <2>;
-			interrupt-parent = <80>;
-			mode = "cpu";
-		};
-
-		spi@500 {
-			device_type = "spi";
-			compatible = "fsl_spi";
-			reg = <500 40>;
-			interrupts = <1>;
-			interrupt-parent = <80>;
-			mode = "cpu";
-		};
-
-		usb@6c0 {
-			device_type = "usb";
-			compatible = "qe_udc";
-			reg = <6c0 40 8B00 100>;
-			interrupts = <b>;
-			interrupt-parent = <80>;
-			mode = "slave";
-		};
-
-		ucc@2200 {
-			device_type = "network";
-			compatible = "ucc_geth";
-			model = "UCC";
-			device-id = <3>;
-			reg = <2200 200>;
-			interrupts = <22>;
-			interrupt-parent = <80>;
-			mac-address = [ 00 04 9f 00 23 23 ];
-			rx-clock = <19>;
-			tx-clock = <1a>;
-			phy-handle = <212003>;
-			pio-handle = <140003>;
-		};
-
-		ucc@3200 {
-			device_type = "network";
-			compatible = "ucc_geth";
-			model = "UCC";
-			device-id = <4>;
-			reg = <3000 200>;
-			interrupts = <23>;
-			interrupt-parent = <80>;
-			mac-address = [ 00 11 22 33 44 55 ];
-			rx-clock = <17>;
-			tx-clock = <18>;
-			phy-handle = <212004>;
-			pio-handle = <140004>;
-		};
-
-		mdio@2320 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <2320 18>;
-			device_type = "mdio";
-			compatible = "ucc_geth_phy";
-
-			ethernet-phy@03 {
-				linux,phandle = <212003>;
-				interrupt-parent = <700>;
-				interrupts = <11 2>;
-				reg = <3>;
-				device_type = "ethernet-phy";
-				interface = <3>; //ENET_100_MII
-			};
-			ethernet-phy@04 {
-				linux,phandle = <212004>;
-				interrupt-parent = <700>;
-				interrupts = <12 2>;
-				reg = <4>;
-				device_type = "ethernet-phy";
-				interface = <3>;
-			};
-		};
-
-		qeic@80 {
-			linux,phandle = <80>;
-			interrupt-controller;
-			device_type = "qeic";
-			#address-cells = <0>;
-			#interrupt-cells = <1>;
-			reg = <80 80>;
-			built-in;
-			big-endian;
-			interrupts = <20 8 21 8>; //high:32 low:33
-			interrupt-parent = <700>;
-		};
-	};
-};
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
new file mode 100644
index 0000000..06b3106
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -0,0 +1,333 @@
+/*
+ * MPC8323E EMDS Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor 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.
+ */
+
+/ {
+	model = "MPC8323EMDS";
+	compatible = "MPC8323EMDS", "MPC832xMDS", "MPC83xxMDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8323@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <4000>;		// L1, 16K
+			i-cache-size = <4000>;		// L1, 16K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 08000000>;
+	};
+
+	bcsr@f8000000 {
+		device_type = "board-control";
+		reg = <f8000000 8000>;
+	};
+
+	soc8323@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00000200>;
+		bus-frequency = <7DE2900>;
+
+		wdt@200 {
+			device_type = "watchdog";
+			compatible = "mpc83xx_wdt";
+			reg = <200 100>;
+		};
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <e 8>;
+			interrupt-parent = < &ipic >;
+			dfsrr;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;
+			interrupts = <9 8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <0>;
+			interrupts = <a 8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		crypto@30000 {
+			device_type = "crypto";
+			model = "SEC2";
+			compatible = "talitos";
+			reg = <30000 7000>;
+			interrupts = <b 8>;
+			interrupt-parent = < &ipic >;
+			/* Rev. 2.2 */
+			num-channels = <1>;
+			channel-fifo-len = <18>;
+			exec-units-mask = <0000004c>;
+			descriptor-types-mask = <0122003f>;
+		};
+
+		pci@8500 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+					/* IDSEL 0x11 AD17 */
+					 8800 0 0 1 &ipic 14 8
+					 8800 0 0 2 &ipic 15 8
+					 8800 0 0 3 &ipic 16 8
+					 8800 0 0 4 &ipic 17 8
+
+					/* IDSEL 0x12 AD18 */
+					 9000 0 0 1 &ipic 16 8
+					 9000 0 0 2 &ipic 17 8
+					 9000 0 0 3 &ipic 14 8
+					 9000 0 0 4 &ipic 15 8
+
+					/* IDSEL 0x13 AD19 */
+					 9800 0 0 1 &ipic 17 8
+					 9800 0 0 2 &ipic 14 8
+					 9800 0 0 3 &ipic 15 8
+					 9800 0 0 4 &ipic 16 8
+
+					/* IDSEL 0x15 AD21*/
+					 a800 0 0 1 &ipic 14 8
+					 a800 0 0 2 &ipic 15 8
+					 a800 0 0 3 &ipic 16 8
+					 a800 0 0 4 &ipic 17 8
+
+					/* IDSEL 0x16 AD22*/
+					 b000 0 0 1 &ipic 17 8
+					 b000 0 0 2 &ipic 14 8
+					 b000 0 0 3 &ipic 15 8
+					 b000 0 0 4 &ipic 16 8
+
+					/* IDSEL 0x17 AD23*/
+					 b800 0 0 1 &ipic 16 8
+					 b800 0 0 2 &ipic 17 8
+					 b800 0 0 3 &ipic 14 8
+					 b800 0 0 4 &ipic 15 8
+
+					/* IDSEL 0x18 AD24*/
+					 c000 0 0 1 &ipic 15 8
+					 c000 0 0 2 &ipic 16 8
+					 c000 0 0 3 &ipic 17 8
+					 c000 0 0 4 &ipic 14 8>;
+			interrupt-parent = < &ipic >;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 a0000000 90000000 0 10000000
+			          42000000 0 80000000 80000000 0 10000000
+			          01000000 0 00000000 d0000000 0 00100000>;
+			clock-frequency = <0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8500 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		ipic: pic@700 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <700 100>;
+			built-in;
+			device_type = "ipic";
+		};
+		
+		par_io@1400 {
+			reg = <1400 100>;
+			device_type = "par_io";
+			num-ports = <7>;
+
+			pio3: ucc_pin@03 {
+				pio-map = <
+			/* port  pin  dir  open_drain  assignment  has_irq */
+					3  4  3  0  2  0  /* MDIO */
+					3  5  1  0  2  0  /* MDC */
+					0  d  2  0  1  0 	/* RX_CLK (CLK9) */
+					3 18  2  0  1  0 	/* TX_CLK (CLK10) */
+					1  1  1  0  1  0 	/* TxD1 */
+					1  0  1  0  1  0 	/* TxD0 */
+					1  1  1  0  1  0 	/* TxD1 */
+					1  2  1  0  1  0 	/* TxD2 */
+					1  3  1  0  1  0 	/* TxD3 */
+					1  4  2  0  1  0 	/* RxD0 */
+					1  5  2  0  1  0 	/* RxD1 */
+					1  6  2  0  1  0 	/* RxD2 */
+					1  7  2  0  1  0 	/* RxD3 */
+					1  8  2  0  1  0 	/* RX_ER */
+					1  9  1  0  1  0 	/* TX_ER */
+					1  a  2  0  1  0 	/* RX_DV */
+					1  b  2  0  1  0 	/* COL */
+					1  c  1  0  1  0 	/* TX_EN */
+					1  d  2  0  1  0>;/* CRS */
+			};
+			pio4: ucc_pin@04 {
+				pio-map = <
+			/* port  pin  dir  open_drain  assignment  has_irq */
+					3 1f  2  0  1  0 	/* RX_CLK (CLK7) */
+					3  6  2  0  1  0 	/* TX_CLK (CLK8) */
+					1 12  1  0  1  0 	/* TxD0 */
+					1 13  1  0  1  0 	/* TxD1 */
+					1 14  1  0  1  0 	/* TxD2 */
+					1 15  1  0  1  0 	/* TxD3 */
+					1 16  2  0  1  0 	/* RxD0 */
+					1 17  2  0  1  0 	/* RxD1 */
+					1 18  2  0  1  0 	/* RxD2 */
+					1 19  2  0  1  0 	/* RxD3 */
+					1 1a  2  0  1  0 	/* RX_ER */
+					1 1b  1  0  1  0 	/* TX_ER */
+					1 1c  2  0  1  0 	/* RX_DV */
+					1 1d  2  0  1  0 	/* COL */
+					1 1e  1  0  1  0 	/* TX_EN */
+					1 1f  2  0  1  0>;/* CRS */
+			};
+		};
+	};
+
+	qe@e0100000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "qe";
+		model = "QE";
+		ranges = <0 e0100000 00100000>;
+		reg = <e0100000 480>;
+		brg-frequency = <0>;
+		bus-frequency = <BCD3D80>;
+		
+		muram@10000 {
+			device_type = "muram";
+			ranges = <0 00010000 00004000>;
+	
+			data-only@0 {
+				reg = <0 4000>;
+			};
+		};
+
+		spi@4c0 {
+			device_type = "spi";
+			compatible = "fsl_spi";
+			reg = <4c0 40>;
+			interrupts = <2>;
+			interrupt-parent = < &qeic >;
+			mode = "cpu";
+		};
+
+		spi@500 {
+			device_type = "spi";
+			compatible = "fsl_spi";
+			reg = <500 40>;
+			interrupts = <1>;
+			interrupt-parent = < &qeic >;
+			mode = "cpu";
+		};
+
+		usb@6c0 {
+			device_type = "usb";
+			compatible = "qe_udc";
+			reg = <6c0 40 8B00 100>;
+			interrupts = <b>;
+			interrupt-parent = < &qeic >;
+			mode = "slave";
+		};
+
+		ucc@2200 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			model = "UCC";
+			device-id = <3>;
+			reg = <2200 200>;
+			interrupts = <22>;
+			interrupt-parent = < &qeic >;
+			mac-address = [ 00 04 9f 00 23 23 ];
+			rx-clock = <19>;
+			tx-clock = <1a>;
+			phy-handle = < &phy3 >;
+			pio-handle = < &pio3 >;
+		};
+
+		ucc@3200 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			model = "UCC";
+			device-id = <4>;
+			reg = <3000 200>;
+			interrupts = <23>;
+			interrupt-parent = < &qeic >;
+			mac-address = [ 00 11 22 33 44 55 ];
+			rx-clock = <17>;
+			tx-clock = <18>;
+			phy-handle = < &phy4 >;
+			pio-handle = < &pio4 >;
+		};
+
+		mdio@2320 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2320 18>;
+			device_type = "mdio";
+			compatible = "ucc_geth_phy";
+
+			phy3: ethernet-phy@03 {
+				interrupt-parent = < &ipic >;
+				interrupts = <11 8>;
+				reg = <3>;
+				device_type = "ethernet-phy";
+				interface = <3>; //ENET_100_MII
+			};
+			phy4: ethernet-phy@04 {
+				interrupt-parent = < &ipic >;
+				interrupts = <12 8>;
+				reg = <4>;
+				device_type = "ethernet-phy";
+				interface = <3>;
+			};
+		};
+
+		qeic: qeic@80 {
+			interrupt-controller;
+			device_type = "qeic";
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			reg = <80 80>;
+			built-in;
+			big-endian;
+			interrupts = <20 8 21 8>; //high:32 low:33
+			interrupt-parent = < &ipic >;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8349emds.dts b/arch/powerpc/boot/dts/mpc8349emds.dts
deleted file mode 100644
index efceb34..0000000
--- a/arch/powerpc/boot/dts/mpc8349emds.dts
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * MPC8349E MDS Device Tree Source
- *
- * Copyright 2005, 2006 Freescale Semiconductor 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.
- */
-
-/ {
-	model = "MPC8349EMDS";
-	compatible = "MPC834xMDS";
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	cpus {
-		#cpus = <1>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		PowerPC,8349@0 {
-			device_type = "cpu";
-			reg = <0>;
-			d-cache-line-size = <20>;	// 32 bytes
-			i-cache-line-size = <20>;	// 32 bytes
-			d-cache-size = <8000>;		// L1, 32K
-			i-cache-size = <8000>;		// L1, 32K
-			timebase-frequency = <0>;	// from bootloader
-			bus-frequency = <0>;		// from bootloader
-			clock-frequency = <0>;		// from bootloader
-			32-bit;
-		};
-	};
-
-	memory {
-		device_type = "memory";
-		reg = <00000000 10000000>;	// 256MB at 0
-	};
-
-	soc8349@e0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		#interrupt-cells = <2>;
-		device_type = "soc";
-		ranges = <0 e0000000 00100000>;
-		reg = <e0000000 00000200>;
-		bus-frequency = <0>;
-
-		wdt@200 {
-			device_type = "watchdog";
-			compatible = "mpc83xx_wdt";
-			reg = <200 100>;
-		};
-
-		i2c@3000 {
-			device_type = "i2c";
-			compatible = "fsl-i2c";
-			reg = <3000 100>;
-			interrupts = <e 8>;
-			interrupt-parent = <700>;
-			dfsrr;
-		};
-
-		i2c@3100 {
-			device_type = "i2c";
-			compatible = "fsl-i2c";
-			reg = <3100 100>;
-			interrupts = <f 8>;
-			interrupt-parent = <700>;
-			dfsrr;
-		};
-
-		spi@7000 {
-			device_type = "spi";
-			compatible = "mpc83xx_spi";
-			reg = <7000 1000>;
-			interrupts = <10 8>;
-			interrupt-parent = <700>;
-			mode = <0>;
-		};
-
-		/* phy type (ULPI or SERIAL) are only types supportted for MPH */
-		/* port = 0 or 1 */
-		usb@22000 {
-			device_type = "usb";
-			compatible = "fsl-usb2-mph";
-			reg = <22000 1000>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupt-parent = <700>;
-			interrupts = <27 2>;
-			phy_type = "ulpi";
-			port1;
-		};
-		/* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
-		usb@23000 {
-			device_type = "usb";
-			compatible = "fsl-usb2-dr";
-			reg = <23000 1000>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupt-parent = <700>;
-			interrupts = <26 2>;
-			phy_type = "ulpi";
-		};
-
-		mdio@24520 {
-			device_type = "mdio";
-			compatible = "gianfar";
-			reg = <24520 20>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			linux,phandle = <24520>;
-			ethernet-phy@0 {
-				linux,phandle = <2452000>;
-				interrupt-parent = <700>;
-				interrupts = <11 2>;
-				reg = <0>;
-				device_type = "ethernet-phy";
-			};
-			ethernet-phy@1 {
-				linux,phandle = <2452001>;
-				interrupt-parent = <700>;
-				interrupts = <12 2>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-		};
-
-		ethernet@24000 {
-			device_type = "network";
-			model = "TSEC";
-			compatible = "gianfar";
-			reg = <24000 1000>;
-			address = [ 00 00 00 00 00 00 ];
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <20 8 21 8 22 8>;
-			interrupt-parent = <700>;
-			phy-handle = <2452000>;
-		};
-
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			device_type = "network";
-			model = "TSEC";
-			compatible = "gianfar";
-			reg = <25000 1000>;
-			address = [ 00 00 00 00 00 00 ];
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <23 8 24 8 25 8>;
-			interrupt-parent = <700>;
-			phy-handle = <2452001>;
-		};
-
-		serial@4500 {
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <4500 100>;
-			clock-frequency = <0>;
-			interrupts = <9 8>;
-			interrupt-parent = <700>;
-		};
-
-		serial@4600 {
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <4600 100>;
-			clock-frequency = <0>;
-			interrupts = <a 8>;
-			interrupt-parent = <700>;
-		};
-
-		pci@8500 {
-			interrupt-map-mask = <f800 0 0 7>;
-			interrupt-map = <
-
-					/* IDSEL 0x11 */
-					 8800 0 0 1 700 14 8
-					 8800 0 0 2 700 15 8
-					 8800 0 0 3 700 16 8
-					 8800 0 0 4 700 17 8
-
-					/* IDSEL 0x12 */
-					 9000 0 0 1 700 16 8
-					 9000 0 0 2 700 17 8
-					 9000 0 0 3 700 14 8
-					 9000 0 0 4 700 15 8
-
-					/* IDSEL 0x13 */
-					 9800 0 0 1 700 17 8
-					 9800 0 0 2 700 14 8
-					 9800 0 0 3 700 15 8
-					 9800 0 0 4 700 16 8
-
-					/* IDSEL 0x15 */
-					 a800 0 0 1 700 14 8
-					 a800 0 0 2 700 15 8
-					 a800 0 0 3 700 16 8
-					 a800 0 0 4 700 17 8
-
-					/* IDSEL 0x16 */
-					 b000 0 0 1 700 17 8
-					 b000 0 0 2 700 14 8
-					 b000 0 0 3 700 15 8
-					 b000 0 0 4 700 16 8
-
-					/* IDSEL 0x17 */
-					 b800 0 0 1 700 16 8
-					 b800 0 0 2 700 17 8
-					 b800 0 0 3 700 14 8
-					 b800 0 0 4 700 15 8
-
-					/* IDSEL 0x18 */
-					 c000 0 0 1 700 15 8
-					 c000 0 0 2 700 16 8
-					 c000 0 0 3 700 17 8
-					 c000 0 0 4 700 14 8>;
-			interrupt-parent = <700>;
-			interrupts = <42 8>;
-			bus-range = <0 0>;
-			ranges = <02000000 0 a0000000 a0000000 0 10000000
-				  42000000 0 80000000 80000000 0 10000000
-				  01000000 0 00000000 e2000000 0 00100000>;
-			clock-frequency = <3f940aa>;
-			#interrupt-cells = <1>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			reg = <8500 100>;
-			compatible = "83xx";
-			device_type = "pci";
-		};
-
-		pci@8600 {
-			interrupt-map-mask = <f800 0 0 7>;
-			interrupt-map = <
-
-					/* IDSEL 0x11 */
-					 8800 0 0 1 700 14 8
-					 8800 0 0 2 700 15 8
-					 8800 0 0 3 700 16 8
-					 8800 0 0 4 700 17 8
-
-					/* IDSEL 0x12 */
-					 9000 0 0 1 700 16 8
-					 9000 0 0 2 700 17 8
-					 9000 0 0 3 700 14 8
-					 9000 0 0 4 700 15 8
-
-					/* IDSEL 0x13 */
-					 9800 0 0 1 700 17 8
-					 9800 0 0 2 700 14 8
-					 9800 0 0 3 700 15 8
-					 9800 0 0 4 700 16 8
-
-					/* IDSEL 0x15 */
-					 a800 0 0 1 700 14 8
-					 a800 0 0 2 700 15 8
-					 a800 0 0 3 700 16 8
-					 a800 0 0 4 700 17 8
-
-					/* IDSEL 0x16 */
-					 b000 0 0 1 700 17 8
-					 b000 0 0 2 700 14 8
-					 b000 0 0 3 700 15 8
-					 b000 0 0 4 700 16 8
-
-					/* IDSEL 0x17 */
-					 b800 0 0 1 700 16 8
-					 b800 0 0 2 700 17 8
-					 b800 0 0 3 700 14 8
-					 b800 0 0 4 700 15 8
-
-					/* IDSEL 0x18 */
-					 c000 0 0 1 700 15 8
-					 c000 0 0 2 700 16 8
-					 c000 0 0 3 700 17 8
-					 c000 0 0 4 700 14 8>;
-			interrupt-parent = <700>;
-			interrupts = <42 8>;
-			bus-range = <0 0>;
-			ranges = <02000000 0 b0000000 b0000000 0 10000000
-				  42000000 0 90000000 90000000 0 10000000
-				  01000000 0 00000000 e2100000 0 00100000>;
-			clock-frequency = <3f940aa>;
-			#interrupt-cells = <1>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			reg = <8600 100>;
-			compatible = "83xx";
-			device_type = "pci";
-		};
-
-		/* May need to remove if on a part without crypto engine */
-		crypto@30000 {
-			device_type = "crypto";
-			model = "SEC2";
-			compatible = "talitos";
-			reg = <30000 10000>;
-			interrupts = <b 8>;
-			interrupt-parent = <700>;
-			num-channels = <4>;
-			channel-fifo-len = <18>;
-			exec-units-mask = <0000007e>;
-			/* desc mask is for rev2.0,
-			 * we need runtime fixup for >2.0 */
-			descriptor-types-mask = <01010ebf>;
-		};
-
-		/* IPIC
-		 * interrupts cell = <intr #, sense>
-		 * sense values match linux IORESOURCE_IRQ_* defines:
-		 * sense == 8: Level, low assertion
-		 * sense == 2: Edge, high-to-low change
-		 */
-		pic@700 {
-			linux,phandle = <700>;
-			interrupt-controller;
-			#address-cells = <0>;
-			#interrupt-cells = <2>;
-			reg = <700 100>;
-			built-in;
-			device_type = "ipic";
-		};
-	};
-};
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 27807fc..61b550b 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -10,7 +10,7 @@
  */
 / {
 	model = "MPC8349EMITX";
-	compatible = "MPC834xMITX";
+	compatible = "MPC8349EMITX", "MPC834xMITX", "MPC83xxMITX";
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -58,7 +58,7 @@
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <e 8>;
-			interrupt-parent = <700>;
+			interrupt-parent = < &ipic >;
 			dfsrr;
 		};
 
@@ -67,7 +67,7 @@
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <f 8>;
-			interrupt-parent = <700>;
+			interrupt-parent = < &ipic >;
 			dfsrr;
 		};
 
@@ -76,7 +76,7 @@
 			compatible = "mpc83xx_spi";
 			reg = <7000 1000>;
 			interrupts = <10 8>;
-			interrupt-parent = <700>;
+			interrupt-parent = < &ipic >;
 			mode = <0>;
 		};
 
@@ -86,8 +86,8 @@
 			reg = <22000 1000>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			interrupt-parent = <700>;
-			interrupts = <27 2>;
+			interrupt-parent = < &ipic >;
+			interrupts = <27 8>;
 			phy_type = "ulpi";
 			port1;
 		};
@@ -98,8 +98,8 @@
 			reg = <23000 1000>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			interrupt-parent = <700>;
-			interrupts = <26 2>;
+			interrupt-parent = < &ipic >;
+			interrupts = <26 8>;
 			phy_type = "ulpi";
 		};
 
@@ -109,22 +109,19 @@
 			reg = <24520 20>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			linux,phandle = <24520>;
 
 			/* Vitesse 8201 */
-			ethernet-phy@1c {
-				linux,phandle = <245201c>;
-				interrupt-parent = <700>;
-				interrupts = <12 2>;
+			phy1c: ethernet-phy@1c {
+				interrupt-parent = < &ipic >;
+				interrupts = <12 8>;
 				reg = <1c>;
 				device_type = "ethernet-phy";
 			};
 
 			/* Vitesse 7385 */
-			ethernet-phy@1f {
-				linux,phandle = <245201f>;
-				interrupt-parent = <700>;
-				interrupts = <12 2>;
+			phy1f: ethernet-phy@1f {
+				interrupt-parent = < &ipic >;
+				interrupts = <12 8>;
 				reg = <1f>;
 				device_type = "ethernet-phy";
 			};
@@ -138,8 +135,8 @@
 			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <20 8 21 8 22 8>;
-			interrupt-parent = <700>;
-			phy-handle = <245201c>;
+			interrupt-parent = < &ipic >;
+			phy-handle = < &phy1c >;
 		};
 
 		ethernet@25000 {
@@ -152,8 +149,8 @@
 			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 8 24 8 25 8>;
-			interrupt-parent = <700>;
-			phy-handle = <245201f>;
+			interrupt-parent = < &ipic >;
+			phy-handle = < &phy1f >;
 		};
 
 		serial@4500 {
@@ -162,7 +159,7 @@
 			reg = <4500 100>;
 			clock-frequency = <0>;		// from bootloader
 			interrupts = <9 8>;
-			interrupt-parent = <700>;
+			interrupt-parent = < &ipic >;
 		};
 
 		serial@4600 {
@@ -171,16 +168,16 @@
 			reg = <4600 100>;
 			clock-frequency = <0>;		// from bootloader
 			interrupts = <a 8>;
-			interrupt-parent = <700>;
+			interrupt-parent = < &ipic >;
 		};
 
 		pci@8500 {
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <
 					/* IDSEL 0x10 - SATA */
-					8000 0 0 1 700 16 8 /* SATA_INTA */
+					8000 0 0 1 &ipic 16 8 /* SATA_INTA */
 					>;
-			interrupt-parent = <700>;
+			interrupt-parent = < &ipic >;
 			interrupts = <42 8>;
 			bus-range = <0 0>;
 			ranges = <42000000 0 80000000 80000000 0 10000000
@@ -199,13 +196,13 @@
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <
 					/* IDSEL 0x0E - MiniPCI Slot */
-					7000 0 0 1 700 15 8 /* PCI_INTA */
+					7000 0 0 1 &ipic 15 8 /* PCI_INTA */
 
 					/* IDSEL 0x0F - PCI Slot */
-					7800 0 0 1 700 14 8 /* PCI_INTA */
-					7800 0 0 2 700 15 8 /* PCI_INTB */
+					7800 0 0 1 &ipic 14 8 /* PCI_INTA */
+					7800 0 0 2 &ipic 15 8 /* PCI_INTB */
 					 >;
-			interrupt-parent = <700>;
+			interrupt-parent = < &ipic >;
 			interrupts = <43 8>;
 			bus-range = <1 1>;
 			ranges = <42000000 0 a0000000 a0000000 0 10000000
@@ -226,15 +223,14 @@
 			compatible = "talitos";
 			reg = <30000 10000>;
 			interrupts = <b 8>;
-			interrupt-parent = <700>;
+			interrupt-parent = < &ipic >;
 			num-channels = <4>;
 			channel-fifo-len = <18>;
 			exec-units-mask = <0000007e>;
 			descriptor-types-mask = <01010ebf>;
 		};
 
-		pic@700 {
-			linux,phandle = <700>;
+		ipic: pic@700 {
 			interrupt-controller;
 			#address-cells = <0>;
 			#interrupt-cells = <2>;
diff --git a/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
new file mode 100644
index 0000000..b2e1a5e
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
@@ -0,0 +1,184 @@
+/*
+ * MPC8349E-mITX-GP Device Tree Source
+ *
+ * Copyright 2007 Freescale Semiconductor 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.
+ */
+/ {
+	model = "MPC8349EMITXGP";
+	compatible = "MPC8349EMITXGP", "MPC834xMITX", "MPC83xxMITX";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8349@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;
+			i-cache-line-size = <20>;
+			d-cache-size = <8000>;
+			i-cache-size = <8000>;
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 10000000>;
+	};
+
+	soc8349@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00000200>;
+		bus-frequency = <0>;                    // from bootloader
+
+		wdt@200 {
+			device_type = "watchdog";
+			compatible = "mpc83xx_wdt";
+			reg = <200 100>;
+		};
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <e 8>;
+			interrupt-parent = < &ipic >;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <f 8>;
+			interrupt-parent = < &ipic >;
+			dfsrr;
+		};
+
+		spi@7000 {
+			device_type = "spi";
+			compatible = "mpc83xx_spi";
+			reg = <7000 1000>;
+			interrupts = <10 8>;
+			interrupt-parent = < &ipic >;
+			mode = <0>;
+		};
+
+		usb@23000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-dr";
+			reg = <23000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = < &ipic >;
+			interrupts = <26 8>;
+			dr_mode = "otg";
+			phy_type = "ulpi";
+		};
+
+		mdio@24520 {
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* Vitesse 8201 */
+			phy1c: ethernet-phy@1c {
+				interrupt-parent = < &ipic >;
+				interrupts = <12 8>;
+				reg = <1c>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <20 8 21 8 22 8>;
+			interrupt-parent = < &ipic >;
+			phy-handle = < &phy1c >;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;		// from bootloader
+			interrupts = <9 8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <0>;		// from bootloader
+			interrupts = <a 8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		pci@8600 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+					/* IDSEL 0x0F - PCI Slot */
+					7800 0 0 1 &ipic 14 8 /* PCI_INTA */
+					7800 0 0 2 &ipic 15 8 /* PCI_INTB */
+					 >;
+			interrupt-parent = < &ipic >;
+			interrupts = <43 8>;
+			bus-range = <1 1>;
+			ranges = <42000000 0 a0000000 a0000000 0 10000000
+				  02000000 0 b0000000 b0000000 0 10000000
+				  01000000 0 00000000 e3000000 0 01000000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8600 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		crypto@30000 {
+			device_type = "crypto";
+			model = "SEC2";
+			compatible = "talitos";
+			reg = <30000 10000>;
+			interrupts = <b 8>;
+			interrupt-parent = < &ipic >;
+			num-channels = <4>;
+			channel-fifo-len = <18>;
+			exec-units-mask = <0000007e>;
+			descriptor-types-mask = <01010ebf>;
+		};
+
+		ipic: pic@700 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <700 100>;
+			built-in;
+			device_type = "ipic";
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
new file mode 100644
index 0000000..e4b43c2
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -0,0 +1,330 @@
+/*
+ * MPC8349E MDS Device Tree Source
+ *
+ * Copyright 2005, 2006 Freescale Semiconductor 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.
+ */
+
+/ {
+	model = "MPC8349EMDS";
+	compatible = "MPC8349EMDS", "MPC834xMDS", "MPC83xxMDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8349@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 10000000>;	// 256MB at 0
+	};
+
+	bcsr@e2400000 {
+		device_type = "board-control";
+		reg = <e2400000 8000>;
+	};
+
+	soc8349@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00000200>;
+		bus-frequency = <0>;
+
+		wdt@200 {
+			device_type = "watchdog";
+			compatible = "mpc83xx_wdt";
+			reg = <200 100>;
+		};
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <e 8>;
+			interrupt-parent = < &ipic >;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <f 8>;
+			interrupt-parent = < &ipic >;
+			dfsrr;
+		};
+
+		spi@7000 {
+			device_type = "spi";
+			compatible = "mpc83xx_spi";
+			reg = <7000 1000>;
+			interrupts = <10 8>;
+			interrupt-parent = < &ipic >;
+			mode = <0>;
+		};
+
+		/* phy type (ULPI or SERIAL) are only types supportted for MPH */
+		/* port = 0 or 1 */
+		usb@22000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-mph";
+			reg = <22000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = < &ipic >;
+			interrupts = <27 8>;
+			phy_type = "ulpi";
+			port1;
+		};
+		/* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
+		usb@23000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-dr";
+			reg = <23000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = < &ipic >;
+			interrupts = <26 8>;
+			dr_mode = "otg";
+			phy_type = "ulpi";
+		};
+
+		mdio@24520 {
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			phy0: ethernet-phy@0 {
+				interrupt-parent = < &ipic >;
+				interrupts = <11 8>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			phy1: ethernet-phy@1 {
+				interrupt-parent = < &ipic >;
+				interrupts = <12 8>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <20 8 21 8 22 8>;
+			interrupt-parent = < &ipic >;
+			phy-handle = < &phy0 >;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 8 24 8 25 8>;
+			interrupt-parent = < &ipic >;
+			phy-handle = < &phy1 >;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;
+			interrupts = <9 8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <0>;
+			interrupts = <a 8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		pci@8500 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+					/* IDSEL 0x11 */
+					 8800 0 0 1 &ipic 14 8
+					 8800 0 0 2 &ipic 15 8
+					 8800 0 0 3 &ipic 16 8
+					 8800 0 0 4 &ipic 17 8
+
+					/* IDSEL 0x12 */
+					 9000 0 0 1 &ipic 16 8
+					 9000 0 0 2 &ipic 17 8
+					 9000 0 0 3 &ipic 14 8
+					 9000 0 0 4 &ipic 15 8
+
+					/* IDSEL 0x13 */
+					 9800 0 0 1 &ipic 17 8
+					 9800 0 0 2 &ipic 14 8
+					 9800 0 0 3 &ipic 15 8
+					 9800 0 0 4 &ipic 16 8
+
+					/* IDSEL 0x15 */
+					 a800 0 0 1 &ipic 14 8
+					 a800 0 0 2 &ipic 15 8
+					 a800 0 0 3 &ipic 16 8
+					 a800 0 0 4 &ipic 17 8
+
+					/* IDSEL 0x16 */
+					 b000 0 0 1 &ipic 17 8
+					 b000 0 0 2 &ipic 14 8
+					 b000 0 0 3 &ipic 15 8
+					 b000 0 0 4 &ipic 16 8
+
+					/* IDSEL 0x17 */
+					 b800 0 0 1 &ipic 16 8
+					 b800 0 0 2 &ipic 17 8
+					 b800 0 0 3 &ipic 14 8
+					 b800 0 0 4 &ipic 15 8
+
+					/* IDSEL 0x18 */
+					 c000 0 0 1 &ipic 15 8
+					 c000 0 0 2 &ipic 16 8
+					 c000 0 0 3 &ipic 17 8
+					 c000 0 0 4 &ipic 14 8>;
+			interrupt-parent = < &ipic >;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 a0000000 a0000000 0 10000000
+				  42000000 0 80000000 80000000 0 10000000
+				  01000000 0 00000000 e2000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8500 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		pci@8600 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+					/* IDSEL 0x11 */
+					 8800 0 0 1 &ipic 14 8
+					 8800 0 0 2 &ipic 15 8
+					 8800 0 0 3 &ipic 16 8
+					 8800 0 0 4 &ipic 17 8
+
+					/* IDSEL 0x12 */
+					 9000 0 0 1 &ipic 16 8
+					 9000 0 0 2 &ipic 17 8
+					 9000 0 0 3 &ipic 14 8
+					 9000 0 0 4 &ipic 15 8
+
+					/* IDSEL 0x13 */
+					 9800 0 0 1 &ipic 17 8
+					 9800 0 0 2 &ipic 14 8
+					 9800 0 0 3 &ipic 15 8
+					 9800 0 0 4 &ipic 16 8
+
+					/* IDSEL 0x15 */
+					 a800 0 0 1 &ipic 14 8
+					 a800 0 0 2 &ipic 15 8
+					 a800 0 0 3 &ipic 16 8
+					 a800 0 0 4 &ipic 17 8
+
+					/* IDSEL 0x16 */
+					 b000 0 0 1 &ipic 17 8
+					 b000 0 0 2 &ipic 14 8
+					 b000 0 0 3 &ipic 15 8
+					 b000 0 0 4 &ipic 16 8
+
+					/* IDSEL 0x17 */
+					 b800 0 0 1 &ipic 16 8
+					 b800 0 0 2 &ipic 17 8
+					 b800 0 0 3 &ipic 14 8
+					 b800 0 0 4 &ipic 15 8
+
+					/* IDSEL 0x18 */
+					 c000 0 0 1 &ipic 15 8
+					 c000 0 0 2 &ipic 16 8
+					 c000 0 0 3 &ipic 17 8
+					 c000 0 0 4 &ipic 14 8>;
+			interrupt-parent = < &ipic >;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 b0000000 b0000000 0 10000000
+				  42000000 0 90000000 90000000 0 10000000
+				  01000000 0 00000000 e2100000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8600 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		/* May need to remove if on a part without crypto engine */
+		crypto@30000 {
+			device_type = "crypto";
+			model = "SEC2";
+			compatible = "talitos";
+			reg = <30000 10000>;
+			interrupts = <b 8>;
+			interrupt-parent = < &ipic >;
+			num-channels = <4>;
+			channel-fifo-len = <18>;
+			exec-units-mask = <0000007e>;
+			/* desc mask is for rev2.0,
+			 * we need runtime fixup for >2.0 */
+			descriptor-types-mask = <01010ebf>;
+		};
+
+		/* IPIC
+		 * interrupts cell = <intr #, sense>
+		 * sense values match linux IORESOURCE_IRQ_* defines:
+		 * sense == 8: Level, low assertion
+		 * sense == 2: Edge, high-to-low change
+		 */
+		ipic: pic@700 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <700 100>;
+			built-in;
+			device_type = "ipic";
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8360emds.dts b/arch/powerpc/boot/dts/mpc8360emds.dts
deleted file mode 100644
index 9022192..0000000
--- a/arch/powerpc/boot/dts/mpc8360emds.dts
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * MPC8360E EMDS Device Tree Source
- *
- * Copyright 2006 Freescale Semiconductor 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.
- */
-
-
-/*
-/memreserve/	00000000 1000000;
-*/
-
-/ {
-	model = "MPC8360EPB";
-	compatible = "MPC83xx";
-	#address-cells = <1>;
-	#size-cells = <1>;
-	linux,phandle = <100>;
-
-	cpus {
-		#cpus = <1>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		linux,phandle = <200>;
-
-		PowerPC,8360@0 {
-			device_type = "cpu";
-			reg = <0>;
-			d-cache-line-size = <20>;	// 32 bytes
-			i-cache-line-size = <20>;	// 32 bytes
-			d-cache-size = <8000>;		// L1, 32K
-			i-cache-size = <8000>;		// L1, 32K
-			timebase-frequency = <3EF1480>;
-			bus-frequency = <FBC5200>;
-			clock-frequency = <1F78A400>;
-			32-bit;
-			linux,phandle = <201>;
-			linux,boot-cpu;
-		};
-	};
-
-	memory {
-		device_type = "memory";
-		linux,phandle = <300>;
-		reg = <00000000 10000000>;
-	};
-
-	bcsr@f8000000 {
-		device_type = "board-control";
-		reg = <f8000000 8000>;
-	};
-
-	soc8360@e0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		#interrupt-cells = <2>;
-		device_type = "soc";
-		ranges = <0 e0000000 00100000>;
-		reg = <e0000000 00000200>;
-		bus-frequency = <FBC5200>;
-
-		wdt@200 {
-			device_type = "watchdog";
-			compatible = "mpc83xx_wdt";
-			reg = <200 100>;
-		};
-
-		i2c@3000 {
-			device_type = "i2c";
-			compatible = "fsl-i2c";
-			reg = <3000 100>;
-			interrupts = <e 8>;
-			interrupt-parent = <700>;
-			dfsrr;
-		};
-
-		i2c@3100 {
-			device_type = "i2c";
-			compatible = "fsl-i2c";
-			reg = <3100 100>;
-			interrupts = <f 8>;
-			interrupt-parent = <700>;
-			dfsrr;
-		};
-
-		serial@4500 {
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <4500 100>;
-			clock-frequency = <FBC5200>;
-			interrupts = <9 8>;
-			interrupt-parent = <700>;
-		};
-
-		serial@4600 {
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <4600 100>;
-			clock-frequency = <FBC5200>;
-			interrupts = <a 8>;
-			interrupt-parent = <700>;
-		};
-
-		crypto@30000 {
-			device_type = "crypto";
-			model = "SEC2";
-			compatible = "talitos";
-			reg = <30000 10000>;
-			interrupts = <b 8>;
-			interrupt-parent = <700>;
-			num-channels = <4>;
-			channel-fifo-len = <18>;
-			exec-units-mask = <0000007e>;
-			/* desc mask is for rev1.x, we need runtime fixup for >=2.x */
-			descriptor-types-mask = <01010ebf>;
-		};
-
-		pci@8500 {
-			linux,phandle = <8500>;
-			interrupt-map-mask = <f800 0 0 7>;
-			interrupt-map = <
-
-					/* IDSEL 0x11 AD17 */
-					 8800 0 0 1 700 14 8
-					 8800 0 0 2 700 15 8
-					 8800 0 0 3 700 16 8
-					 8800 0 0 4 700 17 8
-
-					/* IDSEL 0x12 AD18 */
-					 9000 0 0 1 700 16 8
-					 9000 0 0 2 700 17 8
-					 9000 0 0 3 700 14 8
-					 9000 0 0 4 700 15 8
-
-					/* IDSEL 0x13 AD19 */
-					 9800 0 0 1 700 17 8
-					 9800 0 0 2 700 14 8
-					 9800 0 0 3 700 15 8
-					 9800 0 0 4 700 16 8
-
-					/* IDSEL 0x15 AD21*/
-					 a800 0 0 1 700 14 8
-					 a800 0 0 2 700 15 8
-					 a800 0 0 3 700 16 8
-					 a800 0 0 4 700 17 8
-
-					/* IDSEL 0x16 AD22*/
-					 b000 0 0 1 700 17 8
-					 b000 0 0 2 700 14 8
-					 b000 0 0 3 700 15 8
-					 b000 0 0 4 700 16 8
-
-					/* IDSEL 0x17 AD23*/
-					 b800 0 0 1 700 16 8
-					 b800 0 0 2 700 17 8
-					 b800 0 0 3 700 14 8
-					 b800 0 0 4 700 15 8
-
-					/* IDSEL 0x18 AD24*/
-					 c000 0 0 1 700 15 8
-					 c000 0 0 2 700 16 8
-					 c000 0 0 3 700 17 8
-					 c000 0 0 4 700 14 8>;
-			interrupt-parent = <700>;
-			interrupts = <42 8>;
-			bus-range = <0 0>;
-			ranges = <02000000 0 a0000000 a0000000 0 10000000
-				  42000000 0 80000000 80000000 0 10000000
-				  01000000 0 00000000 e2000000 0 00100000>;
-			clock-frequency = <3f940aa>;
-			#interrupt-cells = <1>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			reg = <8500 100>;
-			compatible = "83xx";
-			device_type = "pci";
-		};
-
-		pic@700 {
-			linux,phandle = <700>;
-			interrupt-controller;
-			#address-cells = <0>;
-			#interrupt-cells = <2>;
-			reg = <700 100>;
-			built-in;
-			device_type = "ipic";
-		};
-
-		par_io@1400 {
-			reg = <1400 100>;
-			device_type = "par_io";
-			num-ports = <7>;
-
-			ucc_pin@01 {
-				linux,phandle = <140001>;
-				pio-map = <
-			/* port  pin  dir  open_drain  assignment  has_irq */
-					0  3  1  0  1  0 	/* TxD0 */
-					0  4  1  0  1  0 	/* TxD1 */
-					0  5  1  0  1  0 	/* TxD2 */
-					0  6  1  0  1  0 	/* TxD3 */
-					1  6  1  0  3  0 	/* TxD4 */
-					1  7  1  0  1  0 	/* TxD5 */
-					1  9  1  0  2  0 	/* TxD6 */
-					1  a  1  0  2  0 	/* TxD7 */
-					0  9  2  0  1  0 	/* RxD0 */
-					0  a  2  0  1  0 	/* RxD1 */
-					0  b  2  0  1  0 	/* RxD2 */
-					0  c  2  0  1  0 	/* RxD3 */
-					0  d  2  0  1  0 	/* RxD4 */
-					1  1  2  0  2  0 	/* RxD5 */
-					1  0  2  0  2  0 	/* RxD6 */
-					1  4  2  0  2  0 	/* RxD7 */
-					0  7  1  0  1  0 	/* TX_EN */
-					0  8  1  0  1  0 	/* TX_ER */
-					0  f  2  0  1  0 	/* RX_DV */
-					0  10 2  0  1  0 	/* RX_ER */
-					0  0  2  0  1  0 	/* RX_CLK */
-					2  9  1  0  3  0 	/* GTX_CLK - CLK10 */
-					2  8  2  0  1  0>;	/* GTX125 - CLK9 */
-			};
-			ucc_pin@02 {
-				linux,phandle = <140002>;
-				pio-map = <
-			/* port  pin  dir  open_drain  assignment  has_irq */
-					0  11 1  0  1  0   /* TxD0 */
-					0  12 1  0  1  0   /* TxD1 */
-					0  13 1  0  1  0   /* TxD2 */
-					0  14 1  0  1  0   /* TxD3 */
-					1  2  1  0  1  0   /* TxD4 */
-					1  3  1  0  2  0   /* TxD5 */
-					1  5  1  0  3  0   /* TxD6 */
-					1  8  1  0  3  0   /* TxD7 */
-					0  17 2  0  1  0   /* RxD0 */
-					0  18 2  0  1  0   /* RxD1 */
-					0  19 2  0  1  0   /* RxD2 */
-					0  1a 2  0  1  0   /* RxD3 */
-					0  1b 2  0  1  0   /* RxD4 */
-					1  c  2  0  2  0   /* RxD5 */
-					1  d  2  0  3  0   /* RxD6 */
-					1  b  2  0  2  0   /* RxD7 */
-					0  15 1  0  1  0   /* TX_EN */
-					0  16 1  0  1  0   /* TX_ER */
-					0  1d 2  0  1  0   /* RX_DV */
-					0  1e 2  0  1  0   /* RX_ER */
-					0  1f 2  0  1  0   /* RX_CLK */
-					2  2  1  0  2  0   /* GTX_CLK - CLK10 */
-					2  3  2  0  1  0   /* GTX125 - CLK4 */
-					0  1  3  0  2  0   /* MDIO */
-					0  2  1  0  1  0>; /* MDC */
-			};
-
-		};
-	};
-
-	qe@e0100000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		device_type = "qe";
-		model = "QE";
-		ranges = <0 e0100000 00100000>;
-		reg = <e0100000 480>;
-		brg-frequency = <0>;
-		bus-frequency = <179A7B00>;
-
-		muram@10000 {
-			device_type = "muram";
-			ranges = <0 00010000 0000c000>;
-
-			data-only@0{
-				reg = <0 c000>;
-			};
-		};
-
-		spi@4c0 {
-			device_type = "spi";
-			compatible = "fsl_spi";
-			reg = <4c0 40>;
-			interrupts = <2>;
-			interrupt-parent = <80>;
-			mode = "cpu";
-		};
-
-		spi@500 {
-			device_type = "spi";
-			compatible = "fsl_spi";
-			reg = <500 40>;
-			interrupts = <1>;
-			interrupt-parent = <80>;
-			mode = "cpu";
-		};
-
-		usb@6c0 {
-			device_type = "usb";
-			compatible = "qe_udc";
-			reg = <6c0 40 8B00 100>;
-			interrupts = <b>;
-			interrupt-parent = <80>;
-			mode = "slave";
-		};
-
-		ucc@2000 {
-			device_type = "network";
-			compatible = "ucc_geth";
-			model = "UCC";
-			device-id = <1>;
-			reg = <2000 200>;
-			interrupts = <20>;
-			interrupt-parent = <80>;
-			mac-address = [ 00 04 9f 00 23 23 ];
-			rx-clock = <0>;
-			tx-clock = <19>;
-			phy-handle = <212000>;
-			pio-handle = <140001>;
-		};
-
-		ucc@3000 {
-			device_type = "network";
-			compatible = "ucc_geth";
-			model = "UCC";
-			device-id = <2>;
-			reg = <3000 200>;
-			interrupts = <21>;
-			interrupt-parent = <80>;
-			mac-address = [ 00 11 22 33 44 55 ];
-			rx-clock = <0>;
-			tx-clock = <14>;
-			phy-handle = <212001>;
-			pio-handle = <140002>;
-		};
-
-		mdio@2120 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <2120 18>;
-			device_type = "mdio";
-			compatible = "ucc_geth_phy";
-
-			ethernet-phy@00 {
-				linux,phandle = <212000>;
-				interrupt-parent = <700>;
-				interrupts = <11 2>;
-				reg = <0>;
-				device_type = "ethernet-phy";
-				interface = <6>; //ENET_1000_GMII
-			};
-			ethernet-phy@01 {
-				linux,phandle = <212001>;
-				interrupt-parent = <700>;
-				interrupts = <12 2>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-				interface = <6>;
-			};
-		};
-
-		qeic@80 {
-			linux,phandle = <80>;
-			interrupt-controller;
-			device_type = "qeic";
-			#address-cells = <0>;
-			#interrupt-cells = <1>;
-			reg = <80 80>;
-			built-in;
-			big-endian;
-			interrupts = <20 8 21 8>; //high:32 low:33
-			interrupt-parent = <700>;
-		};
-
-	};
-};
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
new file mode 100644
index 0000000..4fe45c0
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -0,0 +1,363 @@
+/*
+ * MPC8360E EMDS Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor 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.
+ */
+
+
+/*
+/memreserve/	00000000 1000000;
+*/
+
+/ {
+	model = "MPC8360MDS";
+	compatible = "MPC8360EMDS", "MPC836xMDS", "MPC83xxMDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8360@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <3EF1480>;
+			bus-frequency = <FBC5200>;
+			clock-frequency = <1F78A400>;
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 10000000>;
+	};
+
+	bcsr@f8000000 {
+		device_type = "board-control";
+		reg = <f8000000 8000>;
+	};
+
+	soc8360@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00000200>;
+		bus-frequency = <FBC5200>;
+
+		wdt@200 {
+			device_type = "watchdog";
+			compatible = "mpc83xx_wdt";
+			reg = <200 100>;
+		};
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <e 8>;
+			interrupt-parent = < &ipic >;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <f 8>;
+			interrupt-parent = < &ipic >;
+			dfsrr;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <FBC5200>;
+			interrupts = <9 8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <FBC5200>;
+			interrupts = <a 8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		crypto@30000 {
+			device_type = "crypto";
+			model = "SEC2";
+			compatible = "talitos";
+			reg = <30000 10000>;
+			interrupts = <b 8>;
+			interrupt-parent = < &ipic >;
+			num-channels = <4>;
+			channel-fifo-len = <18>;
+			exec-units-mask = <0000007e>;
+			/* desc mask is for rev1.x, we need runtime fixup for >=2.x */
+			descriptor-types-mask = <01010ebf>;
+		};
+
+		pci@8500 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+					/* IDSEL 0x11 AD17 */
+					 8800 0 0 1 &ipic 14 8
+					 8800 0 0 2 &ipic 15 8
+					 8800 0 0 3 &ipic 16 8
+					 8800 0 0 4 &ipic 17 8
+
+					/* IDSEL 0x12 AD18 */
+					 9000 0 0 1 &ipic 16 8
+					 9000 0 0 2 &ipic 17 8
+					 9000 0 0 3 &ipic 14 8
+					 9000 0 0 4 &ipic 15 8
+
+					/* IDSEL 0x13 AD19 */
+					 9800 0 0 1 &ipic 17 8
+					 9800 0 0 2 &ipic 14 8
+					 9800 0 0 3 &ipic 15 8
+					 9800 0 0 4 &ipic 16 8
+
+					/* IDSEL 0x15 AD21*/
+					 a800 0 0 1 &ipic 14 8
+					 a800 0 0 2 &ipic 15 8
+					 a800 0 0 3 &ipic 16 8
+					 a800 0 0 4 &ipic 17 8
+
+					/* IDSEL 0x16 AD22*/
+					 b000 0 0 1 &ipic 17 8
+					 b000 0 0 2 &ipic 14 8
+					 b000 0 0 3 &ipic 15 8
+					 b000 0 0 4 &ipic 16 8
+
+					/* IDSEL 0x17 AD23*/
+					 b800 0 0 1 &ipic 16 8
+					 b800 0 0 2 &ipic 17 8
+					 b800 0 0 3 &ipic 14 8
+					 b800 0 0 4 &ipic 15 8
+
+					/* IDSEL 0x18 AD24*/
+					 c000 0 0 1 &ipic 15 8
+					 c000 0 0 2 &ipic 16 8
+					 c000 0 0 3 &ipic 17 8
+					 c000 0 0 4 &ipic 14 8>;
+			interrupt-parent = < &ipic >;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 a0000000 a0000000 0 10000000
+				  42000000 0 80000000 80000000 0 10000000
+				  01000000 0 00000000 e2000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8500 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		ipic: pic@700 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <700 100>;
+			built-in;
+			device_type = "ipic";
+		};
+
+		par_io@1400 {
+			reg = <1400 100>;
+			device_type = "par_io";
+			num-ports = <7>;
+
+			pio1: ucc_pin@01 {
+				pio-map = <
+			/* port  pin  dir  open_drain  assignment  has_irq */
+					0  3  1  0  1  0 	/* TxD0 */
+					0  4  1  0  1  0 	/* TxD1 */
+					0  5  1  0  1  0 	/* TxD2 */
+					0  6  1  0  1  0 	/* TxD3 */
+					1  6  1  0  3  0 	/* TxD4 */
+					1  7  1  0  1  0 	/* TxD5 */
+					1  9  1  0  2  0 	/* TxD6 */
+					1  a  1  0  2  0 	/* TxD7 */
+					0  9  2  0  1  0 	/* RxD0 */
+					0  a  2  0  1  0 	/* RxD1 */
+					0  b  2  0  1  0 	/* RxD2 */
+					0  c  2  0  1  0 	/* RxD3 */
+					0  d  2  0  1  0 	/* RxD4 */
+					1  1  2  0  2  0 	/* RxD5 */
+					1  0  2  0  2  0 	/* RxD6 */
+					1  4  2  0  2  0 	/* RxD7 */
+					0  7  1  0  1  0 	/* TX_EN */
+					0  8  1  0  1  0 	/* TX_ER */
+					0  f  2  0  1  0 	/* RX_DV */
+					0  10 2  0  1  0 	/* RX_ER */
+					0  0  2  0  1  0 	/* RX_CLK */
+					2  9  1  0  3  0 	/* GTX_CLK - CLK10 */
+					2  8  2  0  1  0>;	/* GTX125 - CLK9 */
+			};
+			pio2: ucc_pin@02 {
+				pio-map = <
+			/* port  pin  dir  open_drain  assignment  has_irq */
+					0  11 1  0  1  0   /* TxD0 */
+					0  12 1  0  1  0   /* TxD1 */
+					0  13 1  0  1  0   /* TxD2 */
+					0  14 1  0  1  0   /* TxD3 */
+					1  2  1  0  1  0   /* TxD4 */
+					1  3  1  0  2  0   /* TxD5 */
+					1  5  1  0  3  0   /* TxD6 */
+					1  8  1  0  3  0   /* TxD7 */
+					0  17 2  0  1  0   /* RxD0 */
+					0  18 2  0  1  0   /* RxD1 */
+					0  19 2  0  1  0   /* RxD2 */
+					0  1a 2  0  1  0   /* RxD3 */
+					0  1b 2  0  1  0   /* RxD4 */
+					1  c  2  0  2  0   /* RxD5 */
+					1  d  2  0  3  0   /* RxD6 */
+					1  b  2  0  2  0   /* RxD7 */
+					0  15 1  0  1  0   /* TX_EN */
+					0  16 1  0  1  0   /* TX_ER */
+					0  1d 2  0  1  0   /* RX_DV */
+					0  1e 2  0  1  0   /* RX_ER */
+					0  1f 2  0  1  0   /* RX_CLK */
+					2  2  1  0  2  0   /* GTX_CLK - CLK10 */
+					2  3  2  0  1  0   /* GTX125 - CLK4 */
+					0  1  3  0  2  0   /* MDIO */
+					0  2  1  0  1  0>; /* MDC */
+			};
+
+		};
+	};
+
+	qe@e0100000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "qe";
+		model = "QE";
+		ranges = <0 e0100000 00100000>;
+		reg = <e0100000 480>;
+		brg-frequency = <0>;
+		bus-frequency = <179A7B00>;
+
+		muram@10000 {
+			device_type = "muram";
+			ranges = <0 00010000 0000c000>;
+
+			data-only@0{
+				reg = <0 c000>;
+			};
+		};
+
+		spi@4c0 {
+			device_type = "spi";
+			compatible = "fsl_spi";
+			reg = <4c0 40>;
+			interrupts = <2>;
+			interrupt-parent = < &qeic >;
+			mode = "cpu";
+		};
+
+		spi@500 {
+			device_type = "spi";
+			compatible = "fsl_spi";
+			reg = <500 40>;
+			interrupts = <1>;
+			interrupt-parent = < &qeic >;
+			mode = "cpu";
+		};
+
+		usb@6c0 {
+			device_type = "usb";
+			compatible = "qe_udc";
+			reg = <6c0 40 8B00 100>;
+			interrupts = <b>;
+			interrupt-parent = < &qeic >;
+			mode = "slave";
+		};
+
+		ucc@2000 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			model = "UCC";
+			device-id = <1>;
+			reg = <2000 200>;
+			interrupts = <20>;
+			interrupt-parent = < &qeic >;
+			mac-address = [ 00 04 9f 00 23 23 ];
+			rx-clock = <0>;
+			tx-clock = <19>;
+			phy-handle = < &phy0 >;
+			pio-handle = < &pio1 >;
+		};
+
+		ucc@3000 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			model = "UCC";
+			device-id = <2>;
+			reg = <3000 200>;
+			interrupts = <21>;
+			interrupt-parent = < &qeic >;
+			mac-address = [ 00 11 22 33 44 55 ];
+			rx-clock = <0>;
+			tx-clock = <14>;
+			phy-handle = < &phy1 >;
+			pio-handle = < &pio2 >;
+		};
+
+		mdio@2120 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2120 18>;
+			device_type = "mdio";
+			compatible = "ucc_geth_phy";
+
+			phy0: ethernet-phy@00 {
+				interrupt-parent = < &ipic >;
+				interrupts = <11 8>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+				interface = <6>; //ENET_1000_GMII
+			};
+			phy1: ethernet-phy@01 {
+				interrupt-parent = < &ipic >;
+				interrupts = <12 8>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+				interface = <6>;
+			};
+		};
+
+		qeic: qeic@80 {
+			interrupt-controller;
+			device_type = "qeic";
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			reg = <80 80>;
+			built-in;
+			big-endian;
+			interrupts = <20 8 21 8>; //high:32 low:33
+			interrupt-parent = < &ipic >;
+		};
+
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
index 5f41c1f..3c0917f 100644
--- a/arch/powerpc/boot/dts/mpc8540ads.dts
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -12,16 +12,14 @@
 
 / {
 	model = "MPC8540ADS";
-	compatible = "MPC85xxADS";
+	compatible = "MPC8540ADS", "MPC85xxADS";
 	#address-cells = <1>;
 	#size-cells = <1>;
-	linux,phandle = <100>;
 
 	cpus {
 		#cpus = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		linux,phandle = <200>;
 
 		PowerPC,8540@0 {
 			device_type = "cpu";
@@ -34,13 +32,11 @@
 			bus-frequency = <0>;	// 166 MHz
 			clock-frequency = <0>;	// 825 MHz, from uboot
 			32-bit;
-			linux,phandle = <201>;
 		};
 	};
 
 	memory {
 		device_type = "memory";
-		linux,phandle = <300>;
 		reg = <00000000 08000000>;	// 128M at 0x0
 	};
 
@@ -58,7 +54,7 @@
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <1b 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
 
@@ -68,24 +64,20 @@
 			device_type = "mdio";
 			compatible = "gianfar";
 			reg = <24520 20>;
-			linux,phandle = <24520>;
-			ethernet-phy@0 {
-				linux,phandle = <2452000>;
-				interrupt-parent = <40000>;
+			phy0: ethernet-phy@0 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@1 {
-				linux,phandle = <2452001>;
-				interrupt-parent = <40000>;
+			phy1: ethernet-phy@1 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@3 {
-				linux,phandle = <2452003>;
-				interrupt-parent = <40000>;
+			phy3: ethernet-phy@3 {
+				interrupt-parent = <&mpic>;
 				interrupts = <37 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
@@ -102,8 +94,8 @@
 			address = [ 00 E0 0C 00 73 00 ];
 			local-mac-address = [ 00 E0 0C 00 73 00 ];
 			interrupts = <d 2 e 2 12 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452000>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy0>;
 		};
 
 		ethernet@25000 {
@@ -116,8 +108,8 @@
 			address = [ 00 E0 0C 00 73 01 ];
 			local-mac-address = [ 00 E0 0C 00 73 01 ];
 			interrupts = <13 2 14 2 18 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452001>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy1>;
 		};
 
 		ethernet@26000 {
@@ -130,8 +122,8 @@
 			address = [ 00 E0 0C 00 73 02 ];
 			local-mac-address = [ 00 E0 0C 00 73 02 ];
 			interrupts = <19 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452003>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy3>;
 		};
 
 		serial@4500 {
@@ -140,7 +132,7 @@
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
 			interrupts = <1a 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 		};
 
 		serial@4600 {
@@ -149,85 +141,84 @@
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
 			interrupts = <1a 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 		};
 		pci@8000 {
-			linux,phandle = <8000>;
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <
 
 				/* IDSEL 0x02 */
-				1000 0 0 1 40000 31 1
-				1000 0 0 2 40000 32 1
-				1000 0 0 3 40000 33 1
-				1000 0 0 4 40000 34 1
+				1000 0 0 1 &mpic 31 1
+				1000 0 0 2 &mpic 32 1
+				1000 0 0 3 &mpic 33 1
+				1000 0 0 4 &mpic 34 1
 
 				/* IDSEL 0x03 */
-				1800 0 0 1 40000 34 1
-				1800 0 0 2 40000 31 1
-				1800 0 0 3 40000 32 1
-				1800 0 0 4 40000 33 1
+				1800 0 0 1 &mpic 34 1
+				1800 0 0 2 &mpic 31 1
+				1800 0 0 3 &mpic 32 1
+				1800 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x04 */
-				2000 0 0 1 40000 33 1
-				2000 0 0 2 40000 34 1
-				2000 0 0 3 40000 31 1
-				2000 0 0 4 40000 32 1
+				2000 0 0 1 &mpic 33 1
+				2000 0 0 2 &mpic 34 1
+				2000 0 0 3 &mpic 31 1
+				2000 0 0 4 &mpic 32 1
 
 				/* IDSEL 0x05 */
-				2800 0 0 1 40000 32 1
-				2800 0 0 2 40000 33 1
-				2800 0 0 3 40000 34 1
-				2800 0 0 4 40000 31 1
+				2800 0 0 1 &mpic 32 1
+				2800 0 0 2 &mpic 33 1
+				2800 0 0 3 &mpic 34 1
+				2800 0 0 4 &mpic 31 1
 
 				/* IDSEL 0x0c */
-				6000 0 0 1 40000 31 1
-				6000 0 0 2 40000 32 1
-				6000 0 0 3 40000 33 1
-				6000 0 0 4 40000 34 1
+				6000 0 0 1 &mpic 31 1
+				6000 0 0 2 &mpic 32 1
+				6000 0 0 3 &mpic 33 1
+				6000 0 0 4 &mpic 34 1
 
 				/* IDSEL 0x0d */
-				6800 0 0 1 40000 34 1
-				6800 0 0 2 40000 31 1
-				6800 0 0 3 40000 32 1
-				6800 0 0 4 40000 33 1
+				6800 0 0 1 &mpic 34 1
+				6800 0 0 2 &mpic 31 1
+				6800 0 0 3 &mpic 32 1
+				6800 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x0e */
-				7000 0 0 1 40000 33 1
-				7000 0 0 2 40000 34 1
-				7000 0 0 3 40000 31 1
-				7000 0 0 4 40000 32 1
+				7000 0 0 1 &mpic 33 1
+				7000 0 0 2 &mpic 34 1
+				7000 0 0 3 &mpic 31 1
+				7000 0 0 4 &mpic 32 1
 
 				/* IDSEL 0x0f */
-				7800 0 0 1 40000 32 1
-				7800 0 0 2 40000 33 1
-				7800 0 0 3 40000 34 1
-				7800 0 0 4 40000 31 1
+				7800 0 0 1 &mpic 32 1
+				7800 0 0 2 &mpic 33 1
+				7800 0 0 3 &mpic 34 1
+				7800 0 0 4 &mpic 31 1
 
 				/* IDSEL 0x12 */
-				9000 0 0 1 40000 31 1
-				9000 0 0 2 40000 32 1
-				9000 0 0 3 40000 33 1
-				9000 0 0 4 40000 34 1
+				9000 0 0 1 &mpic 31 1
+				9000 0 0 2 &mpic 32 1
+				9000 0 0 3 &mpic 33 1
+				9000 0 0 4 &mpic 34 1
 
 				/* IDSEL 0x13 */
-				9800 0 0 1 40000 34 1
-				9800 0 0 2 40000 31 1
-				9800 0 0 3 40000 32 1
-				9800 0 0 4 40000 33 1
+				9800 0 0 1 &mpic 34 1
+				9800 0 0 2 &mpic 31 1
+				9800 0 0 3 &mpic 32 1
+				9800 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x14 */
-				a000 0 0 1 40000 33 1
-				a000 0 0 2 40000 34 1
-				a000 0 0 3 40000 31 1
-				a000 0 0 4 40000 32 1
+				a000 0 0 1 &mpic 33 1
+				a000 0 0 2 &mpic 34 1
+				a000 0 0 3 &mpic 31 1
+				a000 0 0 4 &mpic 32 1
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 40000 32 1
-				a800 0 0 2 40000 33 1
-				a800 0 0 3 40000 34 1
-				a800 0 0 4 40000 31 1>;
-			interrupt-parent = <40000>;
+				a800 0 0 1 &mpic 32 1
+				a800 0 0 2 &mpic 33 1
+				a800 0 0 3 &mpic 34 1
+				a800 0 0 4 &mpic 31 1>;
+			interrupt-parent = <&mpic>;
 			interrupts = <08 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
@@ -241,8 +232,7 @@
 			device_type = "pci";
 		};
 
-		pic@40000 {
-			linux,phandle = <40000>;
+		mpic: pic@40000 {
 			clock-frequency = <0>;
 			interrupt-controller;
 			#address-cells = <0>;
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
index 7be0bc6..2a1ae76 100644
--- a/arch/powerpc/boot/dts/mpc8541cds.dts
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -12,16 +12,14 @@
 
 / {
 	model = "MPC8541CDS";
-	compatible = "MPC85xxCDS";
+	compatible = "MPC8541CDS", "MPC85xxCDS";
 	#address-cells = <1>;
 	#size-cells = <1>;
-	linux,phandle = <100>;
 
 	cpus {
 		#cpus = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		linux,phandle = <200>;
 
 		PowerPC,8541@0 {
 			device_type = "cpu";
@@ -34,13 +32,11 @@
 			bus-frequency = <0>;	// 166 MHz
 			clock-frequency = <0>;	// 825 MHz, from uboot
 			32-bit;
-			linux,phandle = <201>;
 		};
 	};
 
 	memory {
 		device_type = "memory";
-		linux,phandle = <300>;
 		reg = <00000000 08000000>;	// 128M at 0x0
 	};
 
@@ -58,7 +54,7 @@
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <1b 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
 
@@ -68,17 +64,14 @@
 			device_type = "mdio";
 			compatible = "gianfar";
 			reg = <24520 20>;
-			linux,phandle = <24520>;
-			ethernet-phy@0 {
-				linux,phandle = <2452000>;
-				interrupt-parent = <40000>;
+			phy0: ethernet-phy@0 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 0>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@1 {
-				linux,phandle = <2452001>;
-				interrupt-parent = <40000>;
+			phy1: ethernet-phy@1 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 0>;
 				reg = <1>;
 				device_type = "ethernet-phy";
@@ -94,8 +87,8 @@
 			reg = <24000 1000>;
 			local-mac-address = [ 00 E0 0C 00 73 00 ];
 			interrupts = <d 2 e 2 12 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452000>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy0>;
 		};
 
 		ethernet@25000 {
@@ -107,8 +100,8 @@
 			reg = <25000 1000>;
 			local-mac-address = [ 00 E0 0C 00 73 01 ];
 			interrupts = <13 2 14 2 18 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452001>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy1>;
 		};
 
 		serial@4500 {
@@ -117,7 +110,7 @@
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
 			interrupts = <1a 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 		};
 
 		serial@4600 {
@@ -126,57 +119,56 @@
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
 			interrupts = <1a 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 		};
 
-		pci@8000 {
-			linux,phandle = <8000>;
+		pci1: pci@8000 {
 			interrupt-map-mask = <1f800 0 0 7>;
 			interrupt-map = <
 
 				/* IDSEL 0x10 */
-				08000 0 0 1 40000 30 1
-				08000 0 0 2 40000 31 1
-				08000 0 0 3 40000 32 1
-				08000 0 0 4 40000 33 1
+				08000 0 0 1 &mpic 30 1
+				08000 0 0 2 &mpic 31 1
+				08000 0 0 3 &mpic 32 1
+				08000 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x11 */
-				08800 0 0 1 40000 30 1
-				08800 0 0 2 40000 31 1
-				08800 0 0 3 40000 32 1
-				08800 0 0 4 40000 33 1
+				08800 0 0 1 &mpic 30 1
+				08800 0 0 2 &mpic 31 1
+				08800 0 0 3 &mpic 32 1
+				08800 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x12 (Slot 1) */
-				09000 0 0 1 40000 30 1
-				09000 0 0 2 40000 31 1
-				09000 0 0 3 40000 32 1
-				09000 0 0 4 40000 33 1
+				09000 0 0 1 &mpic 30 1
+				09000 0 0 2 &mpic 31 1
+				09000 0 0 3 &mpic 32 1
+				09000 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x13 (Slot 2) */
-				09800 0 0 1 40000 31 1
-				09800 0 0 2 40000 32 1
-				09800 0 0 3 40000 33 1
-				09800 0 0 4 40000 30 1
+				09800 0 0 1 &mpic 31 1
+				09800 0 0 2 &mpic 32 1
+				09800 0 0 3 &mpic 33 1
+				09800 0 0 4 &mpic 30 1
 
 				/* IDSEL 0x14 (Slot 3) */
-				0a000 0 0 1 40000 32 1
-				0a000 0 0 2 40000 33 1
-				0a000 0 0 3 40000 30 1
-				0a000 0 0 4 40000 31 1
+				0a000 0 0 1 &mpic 32 1
+				0a000 0 0 2 &mpic 33 1
+				0a000 0 0 3 &mpic 30 1
+				0a000 0 0 4 &mpic 31 1
 
 				/* IDSEL 0x15 (Slot 4) */
-				0a800 0 0 1 40000 33 1
-				0a800 0 0 2 40000 30 1
-				0a800 0 0 3 40000 31 1
-				0a800 0 0 4 40000 32 1
+				0a800 0 0 1 &mpic 33 1
+				0a800 0 0 2 &mpic 30 1
+				0a800 0 0 3 &mpic 31 1
+				0a800 0 0 4 &mpic 32 1
 
 				/* Bus 1 (Tundra Bridge) */
 				/* IDSEL 0x12 (ISA bridge) */
-				19000 0 0 1 40000 30 1
-				19000 0 0 2 40000 31 1
-				19000 0 0 3 40000 32 1
-				19000 0 0 4 40000 33 1>;
-			interrupt-parent = <40000>;
+				19000 0 0 1 &mpic 30 1
+				19000 0 0 2 &mpic 31 1
+				19000 0 0 3 &mpic 32 1
+				19000 0 0 4 &mpic 33 1>;
+			interrupt-parent = <&mpic>;
 			interrupts = <08 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
@@ -200,21 +192,20 @@
 				compatible = "chrp,iic";
 				big-endian;
 				interrupts = <1>;
-				interrupt-parent = <8000>;
+				interrupt-parent = <&pci1>;
 			};
 		};
 
 		pci@9000 {
-			linux,phandle = <9000>;
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 40000 3b 1
-				a800 0 0 2 40000 3b 1
-				a800 0 0 3 40000 3b 1
-				a800 0 0 4 40000 3b 1>;
-			interrupt-parent = <40000>;
+				a800 0 0 1 &mpic 3b 1
+				a800 0 0 2 &mpic 3b 1
+				a800 0 0 3 &mpic 3b 1
+				a800 0 0 4 &mpic 3b 1>;
+			interrupt-parent = <&mpic>;
 			interrupts = <09 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 a0000000 a0000000 0 20000000
@@ -228,8 +219,7 @@
 			device_type = "pci";
 		};
 
-		pic@40000 {
-			linux,phandle = <40000>;
+		mpic: pic@40000 {
 			clock-frequency = <0>;
 			interrupt-controller;
 			#address-cells = <0>;
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
index 893d795..7eb5d81 100644
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -12,16 +12,14 @@
 
 / {
 	model = "MPC8548CDS";
-	compatible = "MPC85xxCDS";
+	compatible = "MPC8548CDS", "MPC85xxCDS";
 	#address-cells = <1>;
 	#size-cells = <1>;
-	linux,phandle = <100>;
 
 	cpus {
 		#cpus = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		linux,phandle = <200>;
 
 		PowerPC,8548@0 {
 			device_type = "cpu";
@@ -34,13 +32,11 @@
 			bus-frequency = <0>;	// 166 MHz
 			clock-frequency = <0>;	// 825 MHz, from uboot
 			32-bit;
-			linux,phandle = <201>;
 		};
 	};
 
 	memory {
 		device_type = "memory";
-		linux,phandle = <300>;
 		reg = <00000000 08000000>;	// 128M at 0x0
 	};
 
@@ -58,7 +54,7 @@
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <1b 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
 
@@ -68,32 +64,26 @@
 			device_type = "mdio";
 			compatible = "gianfar";
 			reg = <24520 20>;
-			linux,phandle = <24520>;
-			ethernet-phy@0 {
-				linux,phandle = <2452000>;
-				interrupt-parent = <40000>;
+			phy0: ethernet-phy@0 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 0>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@1 {
-				linux,phandle = <2452001>;
-				interrupt-parent = <40000>;
+			phy1: ethernet-phy@1 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 0>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
-
-			ethernet-phy@2 {
-				linux,phandle = <2452002>;
-				interrupt-parent = <40000>;
+			phy2: ethernet-phy@2 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 0>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@3 {
-				linux,phandle = <2452003>;
-				interrupt-parent = <40000>;
+			phy3: ethernet-phy@3 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 0>;
 				reg = <3>;
 				device_type = "ethernet-phy";
@@ -109,8 +99,8 @@
 			reg = <24000 1000>;
 			local-mac-address = [ 00 E0 0C 00 73 00 ];
 			interrupts = <d 2 e 2 12 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452000>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy0>;
 		};
 
 		ethernet@25000 {
@@ -122,10 +112,11 @@
 			reg = <25000 1000>;
 			local-mac-address = [ 00 E0 0C 00 73 01 ];
 			interrupts = <13 2 14 2 18 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452001>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy1>;
 		};
 
+/* eTSEC 3/4 are currently broken
 		ethernet@26000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -135,11 +126,10 @@
 			reg = <26000 1000>;
 			local-mac-address = [ 00 E0 0C 00 73 02 ];
 			interrupts = <f 2 10 2 11 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452001>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy2>;
 		};
 
-/* eTSEC 4 is currently broken
 		ethernet@27000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -149,8 +139,8 @@
 			reg = <27000 1000>;
 			local-mac-address = [ 00 E0 0C 00 73 03 ];
 			interrupts = <15 2 16 2 17 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452001>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy3>;
 		};
  */
 
@@ -160,7 +150,7 @@
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
 			interrupts = <1a 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 		};
 
 		serial@4600 {
@@ -169,57 +159,56 @@
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
 			interrupts = <1a 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 		};
 
-		pci@8000 {
-			linux,phandle = <8000>;
+		pci1: pci@8000 {
 			interrupt-map-mask = <1f800 0 0 7>;
 			interrupt-map = <
 
 				/* IDSEL 0x10 */
-				08000 0 0 1 40000 30 1
-				08000 0 0 2 40000 31 1
-				08000 0 0 3 40000 32 1
-				08000 0 0 4 40000 33 1
+				08000 0 0 1 &mpic 30 1
+				08000 0 0 2 &mpic 31 1
+				08000 0 0 3 &mpic 32 1
+				08000 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x11 */
-				08800 0 0 1 40000 30 1
-				08800 0 0 2 40000 31 1
-				08800 0 0 3 40000 32 1
-				08800 0 0 4 40000 33 1
+				08800 0 0 1 &mpic 30 1
+				08800 0 0 2 &mpic 31 1
+				08800 0 0 3 &mpic 32 1
+				08800 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x12 (Slot 1) */
-				09000 0 0 1 40000 30 1
-				09000 0 0 2 40000 31 1
-				09000 0 0 3 40000 32 1
-				09000 0 0 4 40000 33 1
+				09000 0 0 1 &mpic 30 1
+				09000 0 0 2 &mpic 31 1
+				09000 0 0 3 &mpic 32 1
+				09000 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x13 (Slot 2) */
-				09800 0 0 1 40000 31 1
-				09800 0 0 2 40000 32 1
-				09800 0 0 3 40000 33 1
-				09800 0 0 4 40000 30 1
+				09800 0 0 1 &mpic 31 1
+				09800 0 0 2 &mpic 32 1
+				09800 0 0 3 &mpic 33 1
+				09800 0 0 4 &mpic 30 1
 
 				/* IDSEL 0x14 (Slot 3) */
-				0a000 0 0 1 40000 32 1
-				0a000 0 0 2 40000 33 1
-				0a000 0 0 3 40000 30 1
-				0a000 0 0 4 40000 31 1
+				0a000 0 0 1 &mpic 32 1
+				0a000 0 0 2 &mpic 33 1
+				0a000 0 0 3 &mpic 30 1
+				0a000 0 0 4 &mpic 31 1
 
 				/* IDSEL 0x15 (Slot 4) */
-				0a800 0 0 1 40000 33 1
-				0a800 0 0 2 40000 30 1
-				0a800 0 0 3 40000 31 1
-				0a800 0 0 4 40000 32 1
+				0a800 0 0 1 &mpic 33 1
+				0a800 0 0 2 &mpic 30 1
+				0a800 0 0 3 &mpic 31 1
+				0a800 0 0 4 &mpic 32 1
 
 				/* Bus 1 (Tundra Bridge) */
 				/* IDSEL 0x12 (ISA bridge) */
-				19000 0 0 1 40000 30 1
-				19000 0 0 2 40000 31 1
-				19000 0 0 3 40000 32 1
-				19000 0 0 4 40000 33 1>;
-			interrupt-parent = <40000>;
+				19000 0 0 1 &mpic 30 1
+				19000 0 0 2 &mpic 31 1
+				19000 0 0 3 &mpic 32 1
+				19000 0 0 4 &mpic 33 1>;
+			interrupt-parent = <&mpic>;
 			interrupts = <08 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
@@ -243,21 +232,20 @@
 				compatible = "chrp,iic";
 				big-endian;
 				interrupts = <1>;
-				interrupt-parent = <8000>;
+				interrupt-parent = <&pci1>;
 			};
 		};
 
 		pci@9000 {
-			linux,phandle = <9000>;
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 40000 3b 1
-				a800 0 0 2 40000 3b 1
-				a800 0 0 3 40000 3b 1
-				a800 0 0 4 40000 3b 1>;
-			interrupt-parent = <40000>;
+				a800 0 0 1 &mpic 3b 1
+				a800 0 0 2 &mpic 3b 1
+				a800 0 0 3 &mpic 3b 1
+				a800 0 0 4 &mpic 3b 1>;
+			interrupt-parent = <&mpic>;
 			interrupts = <09 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 a0000000 a0000000 0 20000000
@@ -271,8 +259,7 @@
 			device_type = "pci";
 		};
 
-		pic@40000 {
-			linux,phandle = <40000>;
+		mpic: pic@40000 {
 			clock-frequency = <0>;
 			interrupt-controller;
 			#address-cells = <0>;
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
index 118f5a8..5f9c102 100644
--- a/arch/powerpc/boot/dts/mpc8555cds.dts
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -12,16 +12,14 @@
 
 / {
 	model = "MPC8555CDS";
-	compatible = "MPC85xxCDS";
+	compatible = "MPC8555CDS", "MPC85xxCDS";
 	#address-cells = <1>;
 	#size-cells = <1>;
-	linux,phandle = <100>;
 
 	cpus {
 		#cpus = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		linux,phandle = <200>;
 
 		PowerPC,8555@0 {
 			device_type = "cpu";
@@ -34,13 +32,11 @@
 			bus-frequency = <0>;	// 166 MHz
 			clock-frequency = <0>;	// 825 MHz, from uboot
 			32-bit;
-			linux,phandle = <201>;
 		};
 	};
 
 	memory {
 		device_type = "memory";
-		linux,phandle = <300>;
 		reg = <00000000 08000000>;	// 128M at 0x0
 	};
 
@@ -58,7 +54,7 @@
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <1b 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
 
@@ -68,17 +64,14 @@
 			device_type = "mdio";
 			compatible = "gianfar";
 			reg = <24520 20>;
-			linux,phandle = <24520>;
-			ethernet-phy@0 {
-				linux,phandle = <2452000>;
-				interrupt-parent = <40000>;
+			phy0: ethernet-phy@0 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 0>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@1 {
-				linux,phandle = <2452001>;
-				interrupt-parent = <40000>;
+			phy1: ethernet-phy@1 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 0>;
 				reg = <1>;
 				device_type = "ethernet-phy";
@@ -94,8 +87,8 @@
 			reg = <24000 1000>;
 			local-mac-address = [ 00 E0 0C 00 73 00 ];
 			interrupts = <0d 2 0e 2 12 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452000>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy0>;
 		};
 
 		ethernet@25000 {
@@ -107,8 +100,8 @@
 			reg = <25000 1000>;
 			local-mac-address = [ 00 E0 0C 00 73 01 ];
 			interrupts = <13 2 14 2 18 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452001>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy1>;
 		};
 
 		serial@4500 {
@@ -117,7 +110,7 @@
 			reg = <4500 100>; 	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
 			interrupts = <1a 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 		};
 
 		serial@4600 {
@@ -126,57 +119,56 @@
 			reg = <4600 100>;	// reg base, size
 			clock-frequency = <0>; 	// should we fill in in uboot?
 			interrupts = <1a 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 		};
 
-		pci@8000 {
-			linux,phandle = <8000>;
+		pci1: pci@8000 {
 			interrupt-map-mask = <1f800 0 0 7>;
 			interrupt-map = <
 
 				/* IDSEL 0x10 */
-				08000 0 0 1 40000 30 1
-				08000 0 0 2 40000 31 1
-				08000 0 0 3 40000 32 1
-				08000 0 0 4 40000 33 1
+				08000 0 0 1 &mpic 30 1
+				08000 0 0 2 &mpic 31 1
+				08000 0 0 3 &mpic 32 1
+				08000 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x11 */
-				08800 0 0 1 40000 30 1
-				08800 0 0 2 40000 31 1
-				08800 0 0 3 40000 32 1
-				08800 0 0 4 40000 33 1
+				08800 0 0 1 &mpic 30 1
+				08800 0 0 2 &mpic 31 1
+				08800 0 0 3 &mpic 32 1
+				08800 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x12 (Slot 1) */
-				09000 0 0 1 40000 30 1
-				09000 0 0 2 40000 31 1
-				09000 0 0 3 40000 32 1
-				09000 0 0 4 40000 33 1
+				09000 0 0 1 &mpic 30 1
+				09000 0 0 2 &mpic 31 1
+				09000 0 0 3 &mpic 32 1
+				09000 0 0 4 &mpic 33 1
 
 				/* IDSEL 0x13 (Slot 2) */
-				09800 0 0 1 40000 31 1
-				09800 0 0 2 40000 32 1
-				09800 0 0 3 40000 33 1
-				09800 0 0 4 40000 30 1
+				09800 0 0 1 &mpic 31 1
+				09800 0 0 2 &mpic 32 1
+				09800 0 0 3 &mpic 33 1
+				09800 0 0 4 &mpic 30 1
 
 				/* IDSEL 0x14 (Slot 3) */
-				0a000 0 0 1 40000 32 1
-				0a000 0 0 2 40000 33 1
-				0a000 0 0 3 40000 30 1
-				0a000 0 0 4 40000 31 1
+				0a000 0 0 1 &mpic 32 1
+				0a000 0 0 2 &mpic 33 1
+				0a000 0 0 3 &mpic 30 1
+				0a000 0 0 4 &mpic 31 1
 
 				/* IDSEL 0x15 (Slot 4) */
-				0a800 0 0 1 40000 33 1
-				0a800 0 0 2 40000 30 1
-				0a800 0 0 3 40000 31 1
-				0a800 0 0 4 40000 32 1
+				0a800 0 0 1 &mpic 33 1
+				0a800 0 0 2 &mpic 30 1
+				0a800 0 0 3 &mpic 31 1
+				0a800 0 0 4 &mpic 32 1
 
 				/* Bus 1 (Tundra Bridge) */
 				/* IDSEL 0x12 (ISA bridge) */
-				19000 0 0 1 40000 30 1
-				19000 0 0 2 40000 31 1
-				19000 0 0 3 40000 32 1
-				19000 0 0 4 40000 33 1>;
-			interrupt-parent = <40000>;
+				19000 0 0 1 &mpic 30 1
+				19000 0 0 2 &mpic 31 1
+				19000 0 0 3 &mpic 32 1
+				19000 0 0 4 &mpic 33 1>;
+			interrupt-parent = <&mpic>;
 			interrupts = <08 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
@@ -200,21 +192,20 @@
 				compatible = "chrp,iic";
 				big-endian;
 				interrupts = <1>;
-				interrupt-parent = <8000>;
+				interrupt-parent = <&pci1>;
 			};
 		};
 
 		pci@9000 {
-			linux,phandle = <9000>;
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 40000 3b 1
-				a800 0 0 2 40000 3b 1
-				a800 0 0 3 40000 3b 1
-				a800 0 0 4 40000 3b 1>;
-			interrupt-parent = <40000>;
+				a800 0 0 1 &mpic 3b 1
+				a800 0 0 2 &mpic 3b 1
+				a800 0 0 3 &mpic 3b 1
+				a800 0 0 4 &mpic 3b 1>;
+			interrupt-parent = <&mpic>;
 			interrupts = <09 2>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 a0000000 a0000000 0 20000000
@@ -228,8 +219,7 @@
 			device_type = "pci";
 		};
 
-		pic@40000 {
-			linux,phandle = <40000>;
+		mpic: pic@40000 {
 			clock-frequency = <0>;
 			interrupt-controller;
 			#address-cells = <0>;
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
index 119bd5d..1050263 100644
--- a/arch/powerpc/boot/dts/mpc8560ads.dts
+++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -12,16 +12,14 @@
 
 / {
 	model = "MPC8560ADS";
-	compatible = "MPC85xxADS";
+	compatible = "MPC8560ADS", "MPC85xxADS";
 	#address-cells = <1>;
 	#size-cells = <1>;
-	linux,phandle = <100>;
 
 	cpus {
 		#cpus = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		linux,phandle = <200>;
 
 		PowerPC,8560@0 {
 			device_type = "cpu";
@@ -34,14 +32,11 @@
 			bus-frequency = <13ab6680>;
 			clock-frequency = <312c8040>;
 			32-bit;
-			linux,phandle = <201>;
-			linux,boot-cpu;
 		};
 	};
 
 	memory {
 		device_type = "memory";
-		linux,phandle = <300>;
 		reg = <00000000 10000000>;
 	};
 
@@ -58,33 +53,28 @@
 			device_type = "mdio";
 			compatible = "gianfar";
 			reg = <24520 20>;
-			linux,phandle = <24520>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			ethernet-phy@0 {
-				linux,phandle = <2452000>;
-				interrupt-parent = <40000>;
+			phy0: ethernet-phy@0 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@1 {
-				linux,phandle = <2452001>;
-				interrupt-parent = <40000>;
+			phy1: ethernet-phy@1 {
+				interrupt-parent = <&mpic>;
 				interrupts = <35 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@2 {
-				linux,phandle = <2452002>;
-				interrupt-parent = <40000>;
+			phy2: ethernet-phy@2 {
+				interrupt-parent = <&mpic>;
 				interrupts = <37 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@3 {
-				linux,phandle = <2452003>;
-				interrupt-parent = <40000>;
+			phy3: ethernet-phy@3 {
+				interrupt-parent = <&mpic>;
 				interrupts = <37 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
@@ -98,8 +88,8 @@
 			reg = <24000 1000>;
 			address = [ 00 00 0C 00 00 FD ];
 			interrupts = <d 2 e 2 12 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452000>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy0>;
 		};
 
 		ethernet@25000 {
@@ -111,12 +101,11 @@
 			reg = <25000 1000>;
 			address = [ 00 00 0C 00 01 FD ];
 			interrupts = <13 2 14 2 18 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452001>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy1>;
 		};
 
 		pci@8000 {
-			linux,phandle = <8000>;
 			#interrupt-cells = <1>;
 			#size-cells = <2>;
 			#address-cells = <3>;
@@ -128,96 +117,94 @@
 			interrupt-map = <
 
 					/* IDSEL 0x2 */
-					 1000 0 0 1 40000 31 1
-					 1000 0 0 2 40000 32 1
-					 1000 0 0 3 40000 33 1
-					 1000 0 0 4 40000 34 1
+					 1000 0 0 1 &mpic 31 1
+					 1000 0 0 2 &mpic 32 1
+					 1000 0 0 3 &mpic 33 1
+					 1000 0 0 4 &mpic 34 1
 
 					/* IDSEL 0x3 */
-					 1800 0 0 1 40000 34 1
-					 1800 0 0 2 40000 31 1
-					 1800 0 0 3 40000 32 1
-					 1800 0 0 4 40000 33 1
+					 1800 0 0 1 &mpic 34 1
+					 1800 0 0 2 &mpic 31 1
+					 1800 0 0 3 &mpic 32 1
+					 1800 0 0 4 &mpic 33 1
 
 					/* IDSEL 0x4 */
-					 2000 0 0 1 40000 33 1
-					 2000 0 0 2 40000 34 1
-					 2000 0 0 3 40000 31 1
-					 2000 0 0 4 40000 32 1
+					 2000 0 0 1 &mpic 33 1
+					 2000 0 0 2 &mpic 34 1
+					 2000 0 0 3 &mpic 31 1
+					 2000 0 0 4 &mpic 32 1
 
 					/* IDSEL 0x5  */
-					 2800 0 0 1 40000 32 1
-					 2800 0 0 2 40000 33 1
-					 2800 0 0 3 40000 34 1
-					 2800 0 0 4 40000 31 1
+					 2800 0 0 1 &mpic 32 1
+					 2800 0 0 2 &mpic 33 1
+					 2800 0 0 3 &mpic 34 1
+					 2800 0 0 4 &mpic 31 1
 
 					/* IDSEL 12 */
-					 6000 0 0 1 40000 31 1
-					 6000 0 0 2 40000 32 1
-					 6000 0 0 3 40000 33 1
-					 6000 0 0 4 40000 34 1
+					 6000 0 0 1 &mpic 31 1
+					 6000 0 0 2 &mpic 32 1
+					 6000 0 0 3 &mpic 33 1
+					 6000 0 0 4 &mpic 34 1
 
 					/* IDSEL 13 */
-					 6800 0 0 1 40000 34 1
-					 6800 0 0 2 40000 31 1
-					 6800 0 0 3 40000 32 1
-					 6800 0 0 4 40000 33 1
+					 6800 0 0 1 &mpic 34 1
+					 6800 0 0 2 &mpic 31 1
+					 6800 0 0 3 &mpic 32 1
+					 6800 0 0 4 &mpic 33 1
 
 					/* IDSEL 14*/
-					 7000 0 0 1 40000 33 1
-					 7000 0 0 2 40000 34 1
-					 7000 0 0 3 40000 31 1
-					 7000 0 0 4 40000 32 1
+					 7000 0 0 1 &mpic 33 1
+					 7000 0 0 2 &mpic 34 1
+					 7000 0 0 3 &mpic 31 1
+					 7000 0 0 4 &mpic 32 1
 
 					/* IDSEL 15 */
-					 7800 0 0 1 40000 32 1
-					 7800 0 0 2 40000 33 1
-					 7800 0 0 3 40000 34 1
-					 7800 0 0 4 40000 31 1
+					 7800 0 0 1 &mpic 32 1
+					 7800 0 0 2 &mpic 33 1
+					 7800 0 0 3 &mpic 34 1
+					 7800 0 0 4 &mpic 31 1
 
 					/* IDSEL 18 */
-					 9000 0 0 1 40000 31 1
-					 9000 0 0 2 40000 32 1
-					 9000 0 0 3 40000 33 1
-					 9000 0 0 4 40000 34 1
+					 9000 0 0 1 &mpic 31 1
+					 9000 0 0 2 &mpic 32 1
+					 9000 0 0 3 &mpic 33 1
+					 9000 0 0 4 &mpic 34 1
 
 					/* IDSEL 19 */
-					 9800 0 0 1 40000 34 1
-					 9800 0 0 2 40000 31 1
-					 9800 0 0 3 40000 32 1
-					 9800 0 0 4 40000 33 1
+					 9800 0 0 1 &mpic 34 1
+					 9800 0 0 2 &mpic 31 1
+					 9800 0 0 3 &mpic 32 1
+					 9800 0 0 4 &mpic 33 1
 
 					/* IDSEL 20 */
-					 a000 0 0 1 40000 33 1
-					 a000 0 0 2 40000 34 1
-					 a000 0 0 3 40000 31 1
-					 a000 0 0 4 40000 32 1
+					 a000 0 0 1 &mpic 33 1
+					 a000 0 0 2 &mpic 34 1
+					 a000 0 0 3 &mpic 31 1
+					 a000 0 0 4 &mpic 32 1
 
 					/* IDSEL 21 */
-					 a800 0 0 1 40000 32 1
-					 a800 0 0 2 40000 33 1
-					 a800 0 0 3 40000 34 1
-					 a800 0 0 4 40000 31 1>;
+					 a800 0 0 1 &mpic 32 1
+					 a800 0 0 2 &mpic 33 1
+					 a800 0 0 3 &mpic 34 1
+					 a800 0 0 4 &mpic 31 1>;
 
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 			interrupts = <8 0>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 01000000>;
 		};
 
-		pic@40000 {
-			linux,phandle = <40000>;
+		mpic: pic@40000 {
 			interrupt-controller;
 			#address-cells = <0>;
 			#interrupt-cells = <2>;
-			reg = <40000 20100>;
+			reg = <40000 40000>;
 			built-in;
 			device_type = "open-pic";
 		};
 
 		cpm@e0000000 {
-			linux,phandle = <e0000000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			#interrupt-cells = <2>;
@@ -228,13 +215,12 @@
 			command-proc = <919c0>;
 			brg-frequency = <9d5b340>;
 
-			pic@90c00 {
-				linux,phandle = <90c00>;
+			cpmpic: pic@90c00 {
 				interrupt-controller;
 				#address-cells = <0>;
 				#interrupt-cells = <2>;
 				interrupts = <1e 0>;
-				interrupt-parent = <40000>;
+				interrupt-parent = <&mpic>;
 				reg = <90c00 80>;
 				built-in;
 				device_type = "cpm-pic";
@@ -251,7 +237,7 @@
 				tx-clock = <1>;
 				current-speed = <1c200>;
 				interrupts = <28 8>;
-				interrupt-parent = <90c00>;
+				interrupt-parent = <&cpmpic>;
 			};
 
 			scc@91a20 {
@@ -265,7 +251,7 @@
 				tx-clock = <2>;
 				current-speed = <1c200>;
 				interrupts = <29 8>;
-				interrupt-parent = <90c00>;
+				interrupt-parent = <&cpmpic>;
 			};
 
 			fcc@91320 {
@@ -279,8 +265,8 @@
 				rx-clock = <15>;
 				tx-clock = <16>;
 				interrupts = <21 8>;
-				interrupt-parent = <90c00>;
-				phy-handle = <2452002>;
+				interrupt-parent = <&cpmpic>;
+				phy-handle = <&phy2>;
 			};
 
 			fcc@91340 {
@@ -294,8 +280,8 @@
 				rx-clock = <17>;
 				tx-clock = <18>;
 				interrupts = <22 8>;
-				interrupt-parent = <90c00>;
-				phy-handle = <2452003>;
+				interrupt-parent = <&cpmpic>;
+				phy-handle = <&phy3>;
 			};
 		};
 	};
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
new file mode 100644
index 0000000..bf49d8c
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -0,0 +1,362 @@
+/*
+ * MPC8568E MDS Device Tree Source
+ *
+ * Copyright 2007 Freescale Semiconductor 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.
+ */
+
+
+/*
+/memreserve/	00000000 1000000;
+*/
+
+/ {
+	model = "MPC8568EMDS";
+	compatible = "MPC8568EMDS", "MPC85xxMDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8568@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 10000000>;
+	};
+
+	bcsr@f8000000 {
+		device_type = "board-control";
+		reg = <f8000000 8000>;
+	};
+
+	soc8568@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00100000>;
+		bus-frequency = <0>;
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <1b 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <1b 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		mdio@24520 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			phy0: ethernet-phy@0 {
+				interrupt-parent = <&mpic>;
+				interrupts = <31 1>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			phy1: ethernet-phy@1 {
+				interrupt-parent = <&mpic>;
+				interrupts = <32 1>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+			phy2: ethernet-phy@2 {
+				interrupt-parent = <&mpic>;
+				interrupts = <31 1>;
+				reg = <2>;
+				device_type = "ethernet-phy";
+			};
+			phy3: ethernet-phy@3 {
+				interrupt-parent = <&mpic>;
+				interrupts = <32 1>;
+				reg = <3>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <d 2 e 2 12 2>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy2>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			mac-address = [ 00 00 00 00 00 00];
+			interrupts = <13 2 14 2 18 2>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy3>;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;
+			interrupts = <1a 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <0>;
+			interrupts = <1a 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		crypto@30000 {
+			device_type = "crypto";
+			model = "SEC2";
+			compatible = "talitos";
+			reg = <30000 f000>;
+			interrupts = <1d 2>;
+			interrupt-parent = <&mpic>;
+			num-channels = <4>;
+			channel-fifo-len = <18>;
+			exec-units-mask = <000000fe>;
+			descriptor-types-mask = <012b0ebf>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <40000 40000>;
+			built-in;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+                        big-endian;
+		};
+		par_io@e0100 {
+			reg = <e0100 100>;
+			device_type = "par_io";
+			num-ports = <7>;
+
+			pio1: ucc_pin@01 {
+				pio-map = <
+			/* port  pin  dir  open_drain  assignment  has_irq */
+					4  0a  1  0  2  0 	/* TxD0 */
+					4  09  1  0  2  0 	/* TxD1 */
+					4  08  1  0  2  0 	/* TxD2 */
+					4  07  1  0  2  0 	/* TxD3 */
+					4  17  1  0  2  0 	/* TxD4 */
+					4  16  1  0  2  0 	/* TxD5 */
+					4  15  1  0  2  0 	/* TxD6 */
+					4  14  1  0  2  0 	/* TxD7 */
+					4  0f  2  0  2  0 	/* RxD0 */
+					4  0e  2  0  2  0 	/* RxD1 */
+					4  0d  2  0  2  0 	/* RxD2 */
+					4  0c  2  0  2  0 	/* RxD3 */
+					4  1d  2  0  2  0 	/* RxD4 */
+					4  1c  2  0  2  0 	/* RxD5 */
+					4  1b  2  0  2  0 	/* RxD6 */
+					4  1a  2  0  2  0 	/* RxD7 */
+					4  0b  1  0  2  0 	/* TX_EN */
+					4  18  1  0  2  0 	/* TX_ER */
+					4  0f  2  0  2  0 	/* RX_DV */
+					4  1e  2  0  2  0 	/* RX_ER */
+					4  11  2  0  2  0 	/* RX_CLK */
+					4  13  1  0  2  0 	/* GTX_CLK */
+					1  1f  2  0  3  0>;	/* GTX125 */
+			};
+			pio2: ucc_pin@02 {
+				pio-map = <
+			/* port  pin  dir  open_drain  assignment  has_irq */
+					5  0a 1  0  2  0   /* TxD0 */
+					5  09 1  0  2  0   /* TxD1 */
+					5  08 1  0  2  0   /* TxD2 */
+					5  07 1  0  2  0   /* TxD3 */
+					5  17 1  0  2  0   /* TxD4 */
+					5  16 1  0  2  0   /* TxD5 */
+					5  15 1  0  2  0   /* TxD6 */
+					5  14 1  0  2  0   /* TxD7 */
+					5  0f 2  0  2  0   /* RxD0 */
+					5  0e 2  0  2  0   /* RxD1 */
+					5  0d 2  0  2  0   /* RxD2 */
+					5  0c 2  0  2  0   /* RxD3 */
+					5  1d 2  0  2  0   /* RxD4 */
+					5  1c 2  0  2  0   /* RxD5 */
+					5  1b 2  0  2  0   /* RxD6 */
+					5  1a 2  0  2  0   /* RxD7 */
+					5  0b 1  0  2  0   /* TX_EN */
+					5  18 1  0  2  0   /* TX_ER */
+					5  10 2  0  2  0   /* RX_DV */
+					5  1e 2  0  2  0   /* RX_ER */
+					5  11 2  0  2  0   /* RX_CLK */
+					5  13 1  0  2  0   /* GTX_CLK */
+					1  1f 2  0  3  0   /* GTX125 */
+					4  06 3  0  2  0   /* MDIO */
+					4  05 1  0  2  0>; /* MDC */
+			};
+		};
+	};
+
+	qe@e0080000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "qe";
+		model = "QE";
+		ranges = <0 e0080000 00040000>;
+		reg = <e0080000 480>;
+		brg-frequency = <0>;
+		bus-frequency = <179A7B00>;
+
+		muram@10000 {
+			device_type = "muram";
+			ranges = <0 00010000 0000c000>;
+
+			data-only@0{
+				reg = <0 c000>;
+			};
+		};
+
+		spi@4c0 {
+			device_type = "spi";
+			compatible = "fsl_spi";
+			reg = <4c0 40>;
+			interrupts = <2>;
+			interrupt-parent = <&qeic>;
+			mode = "cpu";
+		};
+
+		spi@500 {
+			device_type = "spi";
+			compatible = "fsl_spi";
+			reg = <500 40>;
+			interrupts = <1>;
+			interrupt-parent = <&qeic>;
+			mode = "cpu";
+		};
+
+		ucc@2000 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			model = "UCC";
+			device-id = <1>;
+			reg = <2000 200>;
+			interrupts = <20>;
+			interrupt-parent = <&qeic>;
+			mac-address = [ 00 04 9f 00 23 23 ];
+			rx-clock = <0>;
+			tx-clock = <19>;
+			phy-handle = <&qe_phy0>;
+			pio-handle = <&pio1>;
+		};
+
+		ucc@3000 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			model = "UCC";
+			device-id = <2>;
+			reg = <3000 200>;
+			interrupts = <21>;
+			interrupt-parent = <&qeic>;
+			mac-address = [ 00 11 22 33 44 55 ];
+			rx-clock = <0>;
+			tx-clock = <14>;
+			phy-handle = <&qe_phy1>;
+			pio-handle = <&pio2>;
+		};
+
+		mdio@2120 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2120 18>;
+			device_type = "mdio";
+			compatible = "ucc_geth_phy";
+
+			/* These are the same PHYs as on
+			 * gianfar's MDIO bus */
+			qe_phy0: ethernet-phy@00 {
+				interrupt-parent = <&mpic>;
+				interrupts = <31 1>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+				interface = <6>; //ENET_1000_GMII
+			};
+			qe_phy1: ethernet-phy@01 {
+				interrupt-parent = <&mpic>;
+				interrupts = <32 1>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+				interface = <6>;
+			};
+			qe_phy2: ethernet-phy@02 {
+				interrupt-parent = <&mpic>;
+				interrupts = <31 1>;
+				reg = <2>;
+				device_type = "ethernet-phy";
+				interface = <6>; //ENET_1000_GMII
+			};
+			qe_phy3: ethernet-phy@03 {
+				interrupt-parent = <&mpic>;
+				interrupts = <32 1>;
+				reg = <3>;
+				device_type = "ethernet-phy";
+				interface = <6>; //ENET_1000_GMII
+			};
+		};
+
+		qeic: qeic@80 {
+			interrupt-controller;
+			device_type = "qeic";
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			reg = <80 80>;
+			built-in;
+			big-endian;
+			interrupts = <1e 2 1e 2>; //high:30 low:30
+			interrupt-parent = <&mpic>;
+		};
+
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index f0c7731..8a4995a 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -32,7 +32,6 @@
 			bus-frequency = <0>;		// From uboot
 			clock-frequency = <0>;		// From uboot
 			32-bit;
-			linux,boot-cpu;
 		};
 		PowerPC,8641@1 {
 			device_type = "cpu";
@@ -67,7 +66,7 @@
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <2b 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
 
@@ -76,7 +75,7 @@
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <2b 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
 
@@ -86,31 +85,26 @@
 			device_type = "mdio";
 			compatible = "gianfar";
 			reg = <24520 20>;
-			linux,phandle = <24520>;
-			ethernet-phy@0 {
-				linux,phandle = <2452000>;
-				interrupt-parent = <40000>;
+			phy0: ethernet-phy@0 {
+				interrupt-parent = <&mpic>;
 				interrupts = <4a 1>;
 				reg = <0>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@1 {
-				linux,phandle = <2452001>;
-				interrupt-parent = <40000>;
+			phy1: ethernet-phy@1 {
+				interrupt-parent = <&mpic>;
 				interrupts = <4a 1>;
 				reg = <1>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@2 {
-				linux,phandle = <2452002>;
-				interrupt-parent = <40000>;
+			phy2: ethernet-phy@2 {
+				interrupt-parent = <&mpic>;
 				interrupts = <4a 1>;
 				reg = <2>;
 				device_type = "ethernet-phy";
 			};
-			ethernet-phy@3 {
-				linux,phandle = <2452003>;
-				interrupt-parent = <40000>;
+			phy3: ethernet-phy@3 {
+				interrupt-parent = <&mpic>;
 				interrupts = <4a 1>;
 				reg = <3>;
 				device_type = "ethernet-phy";
@@ -126,8 +120,8 @@
 			reg = <24000 1000>;
 			mac-address = [ 00 E0 0C 00 73 00 ];
 			interrupts = <1d 2 1e 2 22 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452000>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy0>;
 		};
 
 		ethernet@25000 {
@@ -139,8 +133,8 @@
 			reg = <25000 1000>;
 			mac-address = [ 00 E0 0C 00 73 01 ];
 			interrupts = <23 2 24 2 28 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452001>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy1>;
 		};
 		
 		ethernet@26000 {
@@ -152,8 +146,8 @@
 			reg = <26000 1000>;
 			mac-address = [ 00 E0 0C 00 02 FD ];
 			interrupts = <1F 2 20 2 21 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452002>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy2>;
 		};
 
 		ethernet@27000 {
@@ -165,8 +159,8 @@
 			reg = <27000 1000>;
 			mac-address = [ 00 E0 0C 00 03 FD ];
 			interrupts = <25 2 26 2 27 2>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452003>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy3>;
 		};
 		serial@4500 {
 			device_type = "serial";
@@ -174,7 +168,7 @@
 			reg = <4500 100>;
 			clock-frequency = <0>;
 			interrupts = <2a 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 		};
 
 		serial@4600 {
@@ -183,7 +177,7 @@
 			reg = <4600 100>;
 			clock-frequency = <0>;
 			interrupts = <1c 2>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 		};
 
 		pci@8000 {
@@ -197,103 +191,102 @@
 			ranges = <02000000 0 80000000 80000000 0 20000000
 				  01000000 0 00000000 e2000000 0 00100000>;
 			clock-frequency = <1fca055>;
-			interrupt-parent = <40000>;
+			interrupt-parent = <&mpic>;
 			interrupts = <18 2>;
 			interrupt-map-mask = <f800 0 0 7>;
 			interrupt-map = <
 				/* IDSEL 0x11 */
-				8800 0 0 1 4d0 3 2
-				8800 0 0 2 4d0 4 2
-				8800 0 0 3 4d0 5 2
-				8800 0 0 4 4d0 6 2
+				8800 0 0 1 &i8259 3 2
+				8800 0 0 2 &i8259 4 2
+				8800 0 0 3 &i8259 5 2
+				8800 0 0 4 &i8259 6 2
 
 				/* IDSEL 0x12 */
-				9000 0 0 1 4d0 4 2
-				9000 0 0 2 4d0 5 2
-				9000 0 0 3 4d0 6 2
-				9000 0 0 4 4d0 3 2
+				9000 0 0 1 &i8259 4 2
+				9000 0 0 2 &i8259 5 2
+				9000 0 0 3 &i8259 6 2
+				9000 0 0 4 &i8259 3 2
 
 				/* IDSEL 0x13 */
-				9800 0 0 1 4d0 0 0
-				9800 0 0 2 4d0 0 0
-				9800 0 0 3 4d0 0 0
-				9800 0 0 4 4d0 0 0
+				9800 0 0 1 &i8259 0 0
+				9800 0 0 2 &i8259 0 0
+				9800 0 0 3 &i8259 0 0
+				9800 0 0 4 &i8259 0 0
 
 				/* IDSEL 0x14 */
-				a000 0 0 1 4d0 0 0
-				a000 0 0 2 4d0 0 0
-				a000 0 0 3 4d0 0 0
-				a000 0 0 4 4d0 0 0
+				a000 0 0 1 &i8259 0 0
+				a000 0 0 2 &i8259 0 0
+				a000 0 0 3 &i8259 0 0
+				a000 0 0 4 &i8259 0 0
 
 				/* IDSEL 0x15 */
-				a800 0 0 1 4d0 0 0
-				a800 0 0 2 4d0 0 0
-				a800 0 0 3 4d0 0 0
-				a800 0 0 4 4d0 0 0
+				a800 0 0 1 &i8259 0 0
+				a800 0 0 2 &i8259 0 0
+				a800 0 0 3 &i8259 0 0
+				a800 0 0 4 &i8259 0 0
 
 				/* IDSEL 0x16 */
-				b000 0 0 1 4d0 0 0
-				b000 0 0 2 4d0 0 0
-				b000 0 0 3 4d0 0 0
-				b000 0 0 4 4d0 0 0
+				b000 0 0 1 &i8259 0 0
+				b000 0 0 2 &i8259 0 0
+				b000 0 0 3 &i8259 0 0
+				b000 0 0 4 &i8259 0 0
 
 				/* IDSEL 0x17 */
-				b800 0 0 1 4d0 0 0
-				b800 0 0 2 4d0 0 0
-				b800 0 0 3 4d0 0 0
-				b800 0 0 4 4d0 0 0
+				b800 0 0 1 &i8259 0 0
+				b800 0 0 2 &i8259 0 0
+				b800 0 0 3 &i8259 0 0
+				b800 0 0 4 &i8259 0 0
 
 				/* IDSEL 0x18 */
-				c000 0 0 1 4d0 0 0
-				c000 0 0 2 4d0 0 0
-				c000 0 0 3 4d0 0 0
-				c000 0 0 4 4d0 0 0
+				c000 0 0 1 &i8259 0 0
+				c000 0 0 2 &i8259 0 0
+				c000 0 0 3 &i8259 0 0
+				c000 0 0 4 &i8259 0 0
 
 				/* IDSEL 0x19 */
-				c800 0 0 1 4d0 0 0
-				c800 0 0 2 4d0 0 0
-				c800 0 0 3 4d0 0 0
-				c800 0 0 4 4d0 0 0
+				c800 0 0 1 &i8259 0 0
+				c800 0 0 2 &i8259 0 0
+				c800 0 0 3 &i8259 0 0
+				c800 0 0 4 &i8259 0 0
 
 				/* IDSEL 0x1a */
-				d000 0 0 1 4d0 6 2
-				d000 0 0 2 4d0 3 2
-				d000 0 0 3 4d0 4 2
-				d000 0 0 4 4d0 5 2
+				d000 0 0 1 &i8259 6 2
+				d000 0 0 2 &i8259 3 2
+				d000 0 0 3 &i8259 4 2
+				d000 0 0 4 &i8259 5 2
 
 
 				/* IDSEL 0x1b */
-				d800 0 0 1 4d0 5 2
-				d800 0 0 2 4d0 0 0
-				d800 0 0 3 4d0 0 0
-				d800 0 0 4 4d0 0 0
+				d800 0 0 1 &i8259 5 2
+				d800 0 0 2 &i8259 0 0
+				d800 0 0 3 &i8259 0 0
+				d800 0 0 4 &i8259 0 0
 
 				/* IDSEL 0x1c */
-				e000 0 0 1 4d0 9 2
-				e000 0 0 2 4d0 a 2
-				e000 0 0 3 4d0 c 2
-				e000 0 0 4 4d0 7 2
+				e000 0 0 1 &i8259 9 2
+				e000 0 0 2 &i8259 a 2
+				e000 0 0 3 &i8259 c 2
+				e000 0 0 4 &i8259 7 2
 
 				/* IDSEL 0x1d */
-				e800 0 0 1 4d0 9 2
-				e800 0 0 2 4d0 a 2
-				e800 0 0 3 4d0 b 2
-				e800 0 0 4 4d0 0 0
+				e800 0 0 1 &i8259 9 2
+				e800 0 0 2 &i8259 a 2
+				e800 0 0 3 &i8259 b 2
+				e800 0 0 4 &i8259 0 0
 
 				/* IDSEL 0x1e */
-				f000 0 0 1 4d0 c 2
-				f000 0 0 2 4d0 0 0
-				f000 0 0 3 4d0 0 0
-				f000 0 0 4 4d0 0 0
+				f000 0 0 1 &i8259 c 2
+				f000 0 0 2 &i8259 0 0
+				f000 0 0 3 &i8259 0 0
+				f000 0 0 4 &i8259 0 0
 
 				/* IDSEL 0x1f */
-				f800 0 0 1 4d0 6 2
-				f800 0 0 2 4d0 0 0
-				f800 0 0 3 4d0 0 0
-				f800 0 0 4 4d0 0 0
+				f800 0 0 1 &i8259 6 2
+				f800 0 0 2 &i8259 0 0
+				f800 0 0 3 &i8259 0 0
+				f800 0 0 4 &i8259 0 0
 				>;
-			i8259@4d0 {
-				linux,phandle = <4d0>;
+			i8259: i8259@4d0 {
 				clock-frequency = <0>;
 				interrupt-controller;
 				device_type = "interrupt-controller";
@@ -303,12 +296,11 @@
 				compatible = "chrp,iic";
                 	        big-endian;
 				interrupts = <49 2>;
-				interrupt-parent = <40000>;
+				interrupt-parent = <&mpic>;
 			};
 
 		};
-		pic@40000 {
-			linux,phandle = <40000>;
+		mpic: pic@40000 {
 			clock-frequency = <0>;
 			interrupt-controller;
 			#address-cells = <0>;
@@ -317,23 +309,7 @@
 			built-in;
 			compatible = "chrp,open-pic";
 			device_type = "open-pic";
-                        big-endian;
-			interrupts = <
-				10 2 11 2 12 2 13 2
-				14 2 15 2 16 2 17 2
-				18 2 19 2 1a 2 1b 2
-				1c 2 1d 2 1e 2 1f 2
-				20 2 21 2 22 2 23 2
-				24 2 25 2 26 2 27 2
-				28 2 29 2 2a 2 2b 2
-				2c 2 2d 2 2e 2 2f 2
-				30 2 31 2 32 2 33 2
-				34 2 35 2 36 2 37 2
-				38 2 39 2 2a 2 3b 2
-				3c 2 3d 2 3e 2 3f 2
-				48 1 49 2 4a 1
-				>;
-			interrupt-parent = <40000>;
+			big-endian;
 		};
 	};
 };
diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts
index 5d40052..2b56b5d 100644
--- a/arch/powerpc/boot/dts/mpc866ads.dts
+++ b/arch/powerpc/boot/dts/mpc866ads.dts
@@ -37,7 +37,6 @@
 			interrupts = <f 2>;	// decrementer interrupt
 			interrupt-parent = <ff000000>;
 			linux,phandle = <201>;
-			linux,boot-cpu;
 		};
 	};
 
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
index cf1a19f..faecd08 100644
--- a/arch/powerpc/boot/dts/mpc885ads.dts
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -37,7 +37,6 @@
 			interrupts = <f 2>;	// decrementer interrupt
 			interrupt-parent = <ff000000>;
 			linux,phandle = <201>;
-			linux,boot-cpu;
 		};
 	};
 
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index e956548..2436731 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -147,6 +147,7 @@
 # CONFIG_RTAS_ERROR_LOGGING is not set
 CONFIG_RTAS_PROC=y
 CONFIG_RTAS_FLASH=y
+CONFIG_PPC_PMI=m
 CONFIG_MMIO_NVRAM=y
 # CONFIG_PPC_MPC106 is not set
 # CONFIG_PPC_970_NAP is not set
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index 405c1c9..dde66a5 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:17:58 2007
+# Linux kernel version: 2.6.20-rc6
+# Sun Jan 28 23:13:56 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -58,7 +58,7 @@
 #
 # General setup
 #
-CONFIG_LOCALVERSION="-kuroboxHG"
+CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
@@ -206,7 +206,7 @@
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
-# CONFIG_SECCOMP is not set
+CONFIG_SECCOMP=y
 CONFIG_ISA_DMA_API=y
 
 #
@@ -312,39 +312,40 @@
 # CONFIG_NF_CT_ACCT is not set
 # CONFIG_NF_CONNTRACK_MARK is not set
 # CONFIG_NF_CONNTRACK_EVENTS is not set
-# CONFIG_NF_CT_PROTO_SCTP is not set
-# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
-# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
-# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
-# CONFIG_NF_CONNTRACK_PPTP is not set
-# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
 # CONFIG_NETFILTER_XT_TARGET_DSCP is not set
-CONFIG_NETFILTER_XT_TARGET_MARK=m
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
 # CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
 # CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
 # CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
 # CONFIG_NETFILTER_XT_MATCH_DCCP is not set
 # CONFIG_NETFILTER_XT_MATCH_DSCP is not set
-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_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
 CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
 # CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 # CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
 # CONFIG_NETFILTER_XT_MATCH_REALM is not set
 # CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=m
 # CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
 # CONFIG_NETFILTER_XT_MATCH_STRING is not set
 # CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
@@ -359,12 +360,12 @@
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
 # CONFIG_IP_NF_MATCH_TOS is not set
-# CONFIG_IP_NF_MATCH_RECENT is not set
+CONFIG_IP_NF_MATCH_RECENT=m
 # CONFIG_IP_NF_MATCH_ECN is not set
 # CONFIG_IP_NF_MATCH_AH is not set
 # CONFIG_IP_NF_MATCH_TTL is not set
-# CONFIG_IP_NF_MATCH_OWNER is not set
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 # CONFIG_IP_NF_TARGET_LOG is not set
@@ -374,16 +375,17 @@
 CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
 # CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_PROTO_GRE=m
 CONFIG_NF_NAT_FTP=m
 CONFIG_NF_NAT_IRC=m
 CONFIG_NF_NAT_TFTP=m
-# CONFIG_NF_NAT_AMANDA is not set
-# CONFIG_NF_NAT_PPTP is not set
-# CONFIG_NF_NAT_H323 is not set
-# CONFIG_NF_NAT_SIP is not set
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -472,6 +474,7 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
@@ -518,6 +521,7 @@
 CONFIG_MTD_PHYSMAP_START=0xffc00000
 CONFIG_MTD_PHYSMAP_LEN=0x400000
 CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PHYSMAP_OF is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
@@ -540,6 +544,7 @@
 # NAND Flash Device Drivers
 #
 # CONFIG_MTD_NAND is not set
+# CONFIG_MTD_NAND_CAFE is not set
 
 #
 # OneNAND Flash Device Drivers
@@ -696,7 +701,7 @@
 # CONFIG_PATA_HPT37X is not set
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
-# CONFIG_PATA_IT821X is not set
+CONFIG_PATA_IT821X=y
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -763,11 +768,33 @@
 #
 # PHY device support
 #
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
-# CONFIG_NET_ETHERNET is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -829,7 +856,8 @@
 # CONFIG_USB_ZD1201 is not set
 # CONFIG_HOSTAP is not set
 # CONFIG_BCM43XX is not set
-# CONFIG_ZD1211RW is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
 CONFIG_NET_WIRELESS=y
 
 #
@@ -1098,7 +1126,7 @@
 #
 # HID Devices
 #
-CONFIG_HID=y
+CONFIG_HID=m
 
 #
 # USB support
@@ -1115,7 +1143,6 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1136,7 +1163,7 @@
 # USB Device Class drivers
 #
 # CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
+CONFIG_USB_PRINTER=m
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -1371,7 +1398,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1461,7 +1492,12 @@
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 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
@@ -1495,7 +1531,7 @@
 # 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_932=m
 # CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_874 is not set
 # CONFIG_NLS_ISO8859_8 is not set
@@ -1526,12 +1562,14 @@
 # Library routines
 #
 CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
+CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
 CONFIG_PLIST=y
 CONFIG_IOMAP_COPY=y
 
diff --git a/arch/powerpc/configs/mpc8313_rdb_defconfig b/arch/powerpc/configs/mpc8313_rdb_defconfig
new file mode 100644
index 0000000..f875237
--- /dev/null
+++ b/arch/powerpc/configs/mpc8313_rdb_defconfig
@@ -0,0 +1,1409 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+# Wed Feb  7 22:08:04 2007
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_82xx is not set
+CONFIG_PPC_83xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_83xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# 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_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=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 is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# 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"
+CONFIG_PPC_GEN550=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Platform support
+#
+CONFIG_MPC8313_RDB=y
+# CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC834x_SYS is not set
+# CONFIG_MPC834x_ITX is not set
+# CONFIG_MPC8360E_PB is not set
+CONFIG_PPC_MPC831x=y
+# CONFIG_MPIC is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=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_RESOURCES_64BIT is not set
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+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=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_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 is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xfe000000
+CONFIG_MTD_PHYSMAP_LEN=0x1000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_OF is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_NAND_CAFE is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# 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=32768
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# 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=y
+# 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
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS 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_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI 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
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID456 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+# CONFIG_BLK_DEV_DM 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 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_MAC_EMUMOUSEBTN is not set
+# CONFIG_WINDFARM is not set
+
+#
+# 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=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+CONFIG_CICADA_PHY=y
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY 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
+
+#
+# Tulip family network device support
+#
+# 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 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO 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
+
+#
+# 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 is not set
+# CONFIG_SIS190 is not set
+# 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
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+# CONFIG_QLA3XXX is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC 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
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+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
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+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
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_83xx_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM 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_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_MPC83xx=y
+
+#
+# SPI Protocol Masters
+#
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# 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
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# 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_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# 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
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# 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=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED 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=y
+# 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=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM 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_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# 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_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_MII 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_ADUTUX 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_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+CONFIG_USB_GADGET_NET2280=y
+CONFIG_USB_NET2280=y
+# CONFIG_USB_GADGET_PXA2XX is not set
+# 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=y
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_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_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=y
+
+#
+# Virtualization
+#
+
+#
+# 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_EXT4DEV_FS 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 is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# 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_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# 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_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# 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=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# 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=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUGGER is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# 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_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# 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
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/mpc832xemds_defconfig b/arch/powerpc/configs/mpc832x_mds_defconfig
similarity index 100%
rename from arch/powerpc/configs/mpc832xemds_defconfig
rename to arch/powerpc/configs/mpc832x_mds_defconfig
diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig
index 7902806..23d8964 100644
--- a/arch/powerpc/configs/mpc834x_itx_defconfig
+++ b/arch/powerpc/configs/mpc834x_itx_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Fri Jan 26 00:19:02 2007
+# Linux kernel version: 2.6.20
+# Wed Feb  7 13:12:18 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -34,9 +34,9 @@
 CONFIG_PPC_83xx=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_83xx=y
@@ -178,7 +178,6 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -303,7 +302,6 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -523,6 +521,7 @@
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SVW is not set
 # CONFIG_ATA_PIIX is not set
@@ -647,37 +646,7 @@
 #
 # 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
-
-#
-# Tulip family network device support
-#
-# 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 is not set
-CONFIG_E100=y
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO 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_NET_ETHERNET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -693,7 +662,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
 CONFIG_GIANFAR=y
@@ -746,26 +714,7 @@
 #
 # Input device support
 #
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# 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
+# CONFIG_INPUT is not set
 
 #
 # Hardware I/O ports
@@ -784,7 +733,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
+# CONFIG_SERIAL_8250_PCI is not set
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -887,7 +836,7 @@
 # CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_DS1374 is not set
 # CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
+CONFIG_SENSORS_PCF8574=y
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_M41T00 is not set
@@ -901,7 +850,6 @@
 # SPI support
 #
 CONFIG_SPI=y
-# CONFIG_SPI_DEBUG is not set
 CONFIG_SPI_MASTER=y
 
 #
@@ -922,52 +870,8 @@
 #
 # Hardware Monitoring support
 #
-CONFIG_HWMON=y
+# CONFIG_HWMON is not set
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# 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
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_VT8231 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Multimedia devices
@@ -983,7 +887,7 @@
 #
 # Graphics support
 #
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
@@ -994,11 +898,6 @@
 # CONFIG_SOUND is not set
 
 #
-# HID Devices
-#
-CONFIG_HID=y
-
-#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1023,10 +922,8 @@
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED 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=y
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 
 #
@@ -1058,25 +955,10 @@
 #
 # 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_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
@@ -1133,25 +1015,7 @@
 #
 # USB Gadget Support
 #
-CONFIG_USB_GADGET=y
-# CONFIG_USB_GADGET_DEBUG_FILES is not set
-CONFIG_USB_GADGET_SELECTED=y
-CONFIG_USB_GADGET_NET2280=y
-CONFIG_USB_NET2280=y
-# CONFIG_USB_GADGET_PXA2XX is not set
-# 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=y
-# CONFIG_USB_ZERO is not set
-CONFIG_USB_ETH=y
-CONFIG_USB_ETH_RNDIS=y
-# CONFIG_USB_GADGETFS is not set
-# CONFIG_USB_FILE_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
-# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_GADGET is not set
 
 #
 # MMC/SD Card support
@@ -1273,8 +1137,11 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1340,7 +1207,7 @@
 # CONFIG_OSF_PARTITION is not set
 # CONFIG_AMIGA_PARTITION is not set
 # CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
+CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
 # CONFIG_MINIX_SUBPARTITION is not set
@@ -1356,7 +1223,46 @@
 #
 # Native Language Support
 #
-# CONFIG_NLS is not set
+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
 
 #
 # Distributed Lock Manager
@@ -1388,27 +1294,9 @@
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-# CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_LIST is not set
-CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_DEBUGGER is not set
-# CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
diff --git a/arch/powerpc/configs/mpc834x_itxgp_defconfig b/arch/powerpc/configs/mpc834x_itxgp_defconfig
new file mode 100644
index 0000000..4aa666c
--- /dev/null
+++ b/arch/powerpc/configs/mpc834x_itxgp_defconfig
@@ -0,0 +1,1174 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+# Fri Feb  9 13:28:19 2007
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_82xx is not set
+CONFIG_PPC_83xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_83xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# 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_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=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 is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# 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"
+CONFIG_PPC_GEN550=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Platform support
+#
+# CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC834x_SYS is not set
+CONFIG_MPC834x_ITX=y
+# CONFIG_MPC8360E_PB is not set
+CONFIG_MPC834x=y
+# CONFIG_MPIC is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=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_RESOURCES_64BIT is not set
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+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=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_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 is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xfe000000
+CONFIG_MTD_PHYSMAP_LEN=0x800000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_OF is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_NAND_CAFE is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+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=y
+# 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
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS 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_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI 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
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA 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 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_MAC_EMUMOUSEBTN is not set
+# CONFIG_WINDFARM is not set
+
+#
+# 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=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+CONFIG_CICADA_PHY=y
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET 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 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
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+# CONFIG_QLA3XXX is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC 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 is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+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
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_83xx_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM 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_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+CONFIG_SENSORS_PCF8574=y
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_MPC83xx=y
+
+#
+# SPI Protocol Masters
+#
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 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 is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk 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_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=y
+
+#
+# Virtualization
+#
+
+#
+# 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_EXT4DEV_FS 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 is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# 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_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# 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=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# 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=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+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
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# 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_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# 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
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
index 9eaed3a..2e3f8ef 100644
--- a/arch/powerpc/configs/mpc834x_mds_defconfig
+++ b/arch/powerpc/configs/mpc834x_mds_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Fri Jan 26 00:19:27 2007
+# Linux kernel version: 2.6.20
+# Thu Feb  8 01:00:48 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -34,9 +34,9 @@
 CONFIG_PPC_83xx=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
-# CONFIG_8xx is not set
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_83xx=y
@@ -128,8 +128,9 @@
 #
 # Platform support
 #
+# CONFIG_MPC8313_RDB is not set
 # CONFIG_MPC832x_MDS is not set
-CONFIG_MPC834x_SYS=y
+CONFIG_MPC834x_MDS=y
 # CONFIG_MPC834x_ITX is not set
 # CONFIG_MPC8360E_PB is not set
 CONFIG_MPC834x=y
diff --git a/arch/powerpc/configs/mpc8360emds_defconfig b/arch/powerpc/configs/mpc8360emds_defconfig
deleted file mode 100644
index bbe38cc..0000000
--- a/arch/powerpc/configs/mpc8360emds_defconfig
+++ /dev/null
@@ -1,1082 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Fri Jan 26 00:19:45 2007
-#
-# CONFIG_PPC64 is not set
-CONFIG_PPC32=y
-CONFIG_PPC_MERGE=y
-CONFIG_MMU=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_IRQ_PER_CPU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_ARCH_HAS_ILOG2_U32=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_PPC=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_PPC_OF=y
-CONFIG_PPC_UDBG_16550=y
-# CONFIG_GENERIC_TBSYNC is not set
-CONFIG_AUDIT_ARCH=y
-CONFIG_GENERIC_BUG=y
-CONFIG_DEFAULT_UIMAGE=y
-
-#
-# Processor support
-#
-# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_82xx is not set
-CONFIG_PPC_83xx=y
-# CONFIG_PPC_85xx is not set
-# CONFIG_PPC_86xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_8xx is not set
-# CONFIG_E200 is not set
-CONFIG_6xx=y
-CONFIG_83xx=y
-CONFIG_PPC_FPU=y
-# CONFIG_PPC_DCR_NATIVE is not set
-# CONFIG_PPC_DCR_MMIO is not set
-CONFIG_PPC_STD_MMU=y
-CONFIG_PPC_STD_MMU_32=y
-# CONFIG_SMP is not set
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# 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_IPC_NS is not set
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-# CONFIG_KALLSYMS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=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 is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# 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"
-CONFIG_QUICC_ENGINE=y
-CONFIG_PPC_GEN550=y
-# CONFIG_WANT_EARLY_SERIAL is not set
-
-#
-# Platform support
-#
-# CONFIG_MPC832x_MDS is not set
-# CONFIG_MPC834x_SYS is not set
-# CONFIG_MPC834x_ITX is not set
-CONFIG_MPC8360E_PB=y
-CONFIG_PPC_MPC836x=y
-# CONFIG_MPIC is not set
-
-#
-# Kernel options
-#
-# CONFIG_HIGHMEM is not set
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_300 is not set
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_POPULATES_NODE_MAP=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_RESOURCES_64BIT is not set
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_CMDLINE_BOOL is not set
-# CONFIG_PM is not set
-CONFIG_SECCOMP=y
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
-CONFIG_PPC_INDIRECT_PCI=y
-CONFIG_FSL_SOC=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-# CONFIG_PCIEPORTBUS is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_HIGHMEM_START=0xfe000000
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# 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 is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_NET_KEY is not set
-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=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_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 is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-# CONFIG_NETWORK_SECMARK 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_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
-# CONFIG_SYS_HYPERVISOR 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_DEV_FD is not set
-# 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=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=y
-# CONFIG_SCSI_TGT is not set
-# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-# CONFIG_BLK_DEV_SD is not set
-# 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
-# CONFIG_SCSI_SCAN_ASYNC is not set
-
-#
-# SCSI Transports
-#
-# 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
-# CONFIG_SCSI_SAS_LIBSAS 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_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI 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
-# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA 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 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
-
-#
-# 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 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
-
-#
-# 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 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
-# CONFIG_GIANFAR is not set
-CONFIG_UCC_GETH=y
-# CONFIG_UGETH_NAPI is not set
-# CONFIG_UGETH_MAGIC_PACKET is not set
-# CONFIG_UGETH_FILTERING is not set
-# CONFIG_UGETH_TX_ON_DEMOND is not set
-# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-# CONFIG_NETXEN_NIC 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
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# 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 is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-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
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_UARTLITE is not set
-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
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_83xx_WDT=y
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-CONFIG_HW_RANDOM=y
-# CONFIG_NVRAM is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_M41T00 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# 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
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_VT8231 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB is not set
-# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-CONFIG_HID=y
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk 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
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Virtualization
-#
-
-#
-# 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_EXT4DEV_FS 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 is not set
-# CONFIG_GFS2_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_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# 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_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# 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 is not set
-# 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=y
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
-# 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=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-# CONFIG_DLM is not set
-
-#
-# QE Options
-#
-CONFIG_UCC_SLOW=y
-CONFIG_UCC_FAST=y
-CONFIG_UCC=y
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
-
-#
-# Instrumentation Support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
-# CONFIG_PPC_EARLY_DEBUG is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_MANAGER=y
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# 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_GF128MUL is not set
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_DES=y
-# 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
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/mpc836x_mds_defconfig b/arch/powerpc/configs/mpc836x_mds_defconfig
new file mode 100644
index 0000000..8eb475c
--- /dev/null
+++ b/arch/powerpc/configs/mpc836x_mds_defconfig
@@ -0,0 +1,1099 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+# Sat Feb 17 10:09:26 2007
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_82xx is not set
+CONFIG_PPC_83xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_83xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# 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_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=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 is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# 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"
+CONFIG_QUICC_ENGINE=y
+CONFIG_PPC_GEN550=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Platform support
+#
+# CONFIG_MPC8313_RDB is not set
+# CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC834x_MDS is not set
+# CONFIG_MPC834x_ITX is not set
+CONFIG_MPC836x_MDS=y
+CONFIG_PPC_MPC836x=y
+# CONFIG_MPIC is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=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_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+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=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_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 is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
+# CONFIG_SYS_HYPERVISOR 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_DEV_FD is not set
+# 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=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# 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
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# 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
+# CONFIG_SCSI_SAS_LIBSAS 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_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI 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
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA 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 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_MAC_EMUMOUSEBTN is not set
+# CONFIG_WINDFARM is not set
+
+#
+# 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 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
+
+#
+# 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 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
+# CONFIG_GIANFAR is not set
+CONFIG_UCC_GETH=y
+# CONFIG_UGETH_NAPI is not set
+# CONFIG_UGETH_MAGIC_PACKET is not set
+# CONFIG_UGETH_FILTERING is not set
+# CONFIG_UGETH_TX_ON_DEMOND is not set
+# CONFIG_QLA3XXX is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC 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
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+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
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM 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=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_83xx_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# 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
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG 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 is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# 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_EXT4DEV_FS 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 is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# 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_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# 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 is not set
+# 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=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# 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=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# QE Options
+#
+CONFIG_UCC_SLOW=y
+CONFIG_UCC_FAST=y
+CONFIG_UCC=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# 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_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT 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_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/mpc8568mds_defconfig b/arch/powerpc/configs/mpc8568mds_defconfig
new file mode 100644
index 0000000..7b38006
--- /dev/null
+++ b/arch/powerpc/configs/mpc8568mds_defconfig
@@ -0,0 +1,1010 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+# Sat Feb 17 16:26:53 2007
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_85xx=y
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_85xx=y
+CONFIG_E500=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_SPE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# 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_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=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 is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# 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"
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Platform support
+#
+# CONFIG_MPC8540_ADS is not set
+# CONFIG_MPC8560_ADS is not set
+# CONFIG_MPC85xx_CDS is not set
+CONFIG_MPC85xx_MDS=y
+CONFIG_MPC85xx=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPIC=y
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=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_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+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=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_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 is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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_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
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR 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_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# 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
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+# CONFIG_MAC_EMUMOUSEBTN is not set
+# CONFIG_WINDFARM is not set
+
+#
+# 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
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# 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
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM 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=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_BOOKE_WDT is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# 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
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+# 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'
+#
+
+#
+# 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
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# 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_EXT4DEV_FS 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 is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# 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_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# 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 is not set
+# 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=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# 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=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUGGER=y
+# CONFIG_XMON is not set
+# CONFIG_BDI_SWITCH is not set
+CONFIG_BOOTX_TEXT=y
+CONFIG_PPC_EARLY_DEBUG=y
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# 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_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT 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_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index debac66..a8da0ae 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -500,7 +500,7 @@
 # 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_SL82C105=y
+# CONFIG_BLK_DEV_SL82C105 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -646,7 +646,7 @@
 # CONFIG_PATA_SIL680 is not set
 # CONFIG_PATA_SIS is not set
 # CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_WINBOND=y
 
 #
 # Multi-device support (RAID and LVM)
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index ec644b3..0345a2c 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -163,6 +163,7 @@
 # CONFIG_PS3_DYNAMIC_DMA is not set
 CONFIG_PS3_USE_LPAR_ADDR=y
 CONFIG_PS3_VUART=y
+CONFIG_PS3_PS3AV=y
 
 #
 # Kernel options
@@ -611,14 +612,40 @@
 # Graphics support
 #
 # CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
+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_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_PS3=y
+CONFIG_FB_PS3_DEFAULT_SIZE_M=18
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 1c794fe..6e96e50 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -483,7 +483,7 @@
 # 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_SL82C105=y
+# CONFIG_BLK_DEV_SL82C105 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -628,7 +628,7 @@
 # CONFIG_PATA_SIL680 is not set
 # CONFIG_PATA_SIS is not set
 # CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_WINBOND=y
 
 #
 # Multi-device support (RAID and LVM)
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index 93f21aa..3678997 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -18,6 +18,7 @@
 #include <asm/io.h>
 #include <asm/lmb.h>
 #include <asm/processor.h>
+#include <asm/udbg.h>
 
 #define NO_SCROLL
 
@@ -912,3 +913,11 @@
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 };
+
+void __init udbg_init_btext(void)
+{
+	/* If btext is enabled, we might have a BAT setup for early display,
+	 * thus we do enable some very basic udbg output
+	 */
+	udbg_putc = btext_drawchar;
+}
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index dd17dff..7ec4ac7 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -44,7 +44,7 @@
 extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_pa6t(unsigned long offset, struct cpu_spec* spec);
-extern void __restore_cpu_pa6t(unsigned long offset, struct cpu_spec* spec);
+extern void __restore_cpu_pa6t(void);
 extern void __restore_cpu_ppc970(void);
 #endif /* CONFIG_PPC64 */
 
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index accb39d..a15d4b8 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -32,8 +32,6 @@
 #include <asm/page.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
-#include <asm/ibm4xx.h>
-#include <asm/ibm44x.h>
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 66877bd..1f155d3 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -206,7 +206,8 @@
 	rlwimi	r7,r3,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r3) */
 	mtspr	SPRN_MAS0,r7
 	tlbre
-	li	r6,0
+	mfspr	r6,SPRN_MAS1
+	rlwinm	r6,r6,0,2,0	/* clear IPROT */
 	mtspr	SPRN_MAS1,r6
 	tlbwe
 	/* Invalidate TLB1 */
@@ -248,6 +249,8 @@
 	rlwimi	r7,r5,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r5) */
 	mtspr	SPRN_MAS0,r7
 	tlbre
+	mfspr	r8,SPRN_MAS1
+	rlwinm	r8,r8,0,2,0	/* clear IPROT */
 	mtspr	SPRN_MAS1,r8
 	tlbwe
 	/* Invalidate TLB1 */
@@ -889,7 +892,6 @@
 	REST_GPR(9, r11)
 	REST_GPR(12, r11)
 	lwz	r11,GPR11(r11)
-	SYNC
 	rfi
 
 /*
@@ -953,7 +955,6 @@
 _GLOBAL(giveup_spe)
 	mfmsr	r5
 	oris	r5,r5,MSR_SPE@h
-	SYNC
 	mtmsr	r5			/* enable use of SPE now */
 	isync
 	cmpi	0,r3,0
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index 8994af3..6e7f509 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -110,17 +110,22 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
-	{ 0, },
+	{}
 };
 static ctl_table powersave_nap_sysctl_root[] = {
-	{ 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
- 	{ 0,},
+	{
+		.ctl_name	= CTL_KERN,
+		.procname	= "kernel",
+		.mode		= 0755,
+		.child		= powersave_nap_ctl_table,
+	},
+	{}
 };
 
 static int __init
 register_powersave_nap_sysctl(void)
 {
-	register_sysctl_table(powersave_nap_sysctl_root, 0);
+	register_sysctl_table(powersave_nap_sysctl_root);
 
 	return 0;
 }
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 5e6ddfa..325f490 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -124,6 +124,10 @@
 	if (get_property(np, "clock-frequency", NULL) == NULL)
 		return -1;
 
+	/* if rtas uses this device, don't try to use it as well */
+	if (get_property(np, "used-by-rtas", NULL) != NULL)
+		return -1;
+
 	/* Get the address */
 	addrp = of_get_address(soc_dev, 0, NULL, NULL);
 	if (addrp == NULL)
@@ -334,6 +338,17 @@
 		of_node_put(tsi);
 	}
 
+	/* First fill our array with opb bus ports */
+	for (np = NULL; (np = of_find_compatible_node(np, "serial", "ns16750")) != NULL;) {
+		struct device_node *opb = of_get_parent(np);
+		if (opb && !strcmp(opb->type, "opb")) {
+			index = add_legacy_soc_port(np, np);
+			if (index >= 0 && np == stdout)
+				legacy_serial_console = index;
+		}
+		of_node_put(opb);
+	}
+
 #ifdef CONFIG_PCI
 	/* Next, try to locate PCI ports */
 	for (np = NULL; (np = of_find_all_nodes(np));) {
@@ -498,7 +513,7 @@
 	DBG(" -> check_legacy_serial_console()\n");
 
 	/* The user has requested a console so this is already set up. */
-	if (strstr(saved_command_line, "console=")) {
+	if (strstr(boot_command_line, "console=")) {
 		DBG(" console was specified !\n");
 		return -EBUSY;
 	}
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 0de5a08..89486b6 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -571,7 +571,7 @@
 	return single_open(file, lparcfg_data, NULL);
 }
 
-struct file_operations lparcfg_fops = {
+const struct file_operations lparcfg_fops = {
 	.owner		= THIS_MODULE,
 	.read		= seq_read,
 	.write		= lparcfg_write,
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 869cebb..f9676f5 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -179,7 +179,7 @@
 	}
 }
 
-struct file_operations nvram_fops = {
+const struct file_operations nvram_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	dev_nvram_llseek,
 	.read =		dev_nvram_read,
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index dd7001c..f78dfce 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -33,7 +33,7 @@
 			      loff_t *ppos);
 static int     page_map_mmap( struct file *file, struct vm_area_struct *vma );
 
-static struct file_operations page_map_fops = {
+static const struct file_operations page_map_fops = {
 	.llseek	= page_map_seek,
 	.read	= page_map_read,
 	.mmap	= page_map_mmap
@@ -71,7 +71,6 @@
 	pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL);
 	if (!pde)
 		return 1;
-	pde->nlink = 1;
 	pde->data = vdso_data;
 	pde->size = PAGE_SIZE;
 	pde->proc_fops = &page_map_fops;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 3be52d6..8d52b23 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -991,7 +991,7 @@
 	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
 
 	/* Save command line for /proc/cmdline and then parse parameters */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
 	parse_early_param();
 
 	/* Reserve LMB regions used by kernel, initrd, dt, etc... */
@@ -1599,6 +1599,7 @@
 
 	return pp;
 }
+EXPORT_SYMBOL(of_find_property);
 
 /*
  * Find a property with a given name for a given node
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 520ef42f..4fb5938 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2117,11 +2117,92 @@
 #define fixup_device_tree_pmac()
 #endif
 
+#ifdef CONFIG_PPC_EFIKA
+/* The current fw of the Efika has a device tree needs quite a few
+ * fixups to be compliant with the mpc52xx bindings. It's currently
+ * unknown if it will ever be compliant (come on bPlan ...) so we do fixups.
+ * NOTE that we (barely) tolerate it because the EFIKA was out before
+ * the bindings were finished, for any new boards -> RTFM ! */
+
+struct subst_entry {
+	char *path;
+	char *property;
+	void *value;
+	int value_len;
+};
+
+static void __init fixup_device_tree_efika(void)
+{
+	/* Substitution table */
+	#define prop_cstr(x) x, sizeof(x)
+	int prop_sound_irq[3] = { 2, 2, 0 };
+	int prop_bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
+	                             3,4,0, 3,5,0, 3,6,0, 3,7,0,
+	                             3,8,0, 3,9,0, 3,10,0, 3,11,0,
+	                             3,12,0, 3,13,0, 3,14,0, 3,15,0 };
+	struct subst_entry efika_subst_table[] = {
+		{ "/",			"device_type",	prop_cstr("efika") },
+		{ "/builtin",		"compatible",	prop_cstr("soc") },
+		{ "/builtin/ata",	"compatible",	prop_cstr("mpc5200b-ata\0mpc5200-ata"), },
+		{ "/builtin/bestcomm",	"compatible",	prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") },
+		{ "/builtin/bestcomm",	"interrupts",	prop_bcomm_irq, sizeof(prop_bcomm_irq) },
+		{ "/builtin/ethernet",	"compatible",	prop_cstr("mpc5200b-fec\0mpc5200-fec") },
+		{ "/builtin/pic",	"compatible",	prop_cstr("mpc5200b-pic\0mpc5200-pic") },
+		{ "/builtin/serial",	"compatible",	prop_cstr("mpc5200b-psc-uart\0mpc5200-psc-uart") },
+		{ "/builtin/sound",	"compatible",	prop_cstr("mpc5200b-psc-ac97\0mpc5200-psc-ac97") },
+		{ "/builtin/sound",	"interrupts",	prop_sound_irq, sizeof(prop_sound_irq) },
+		{ "/builtin/sram",	"compatible",	prop_cstr("mpc5200b-sram\0mpc5200-sram") },
+		{ "/builtin/sram",	"device_type",	prop_cstr("sram") },
+		{}
+	};
+	#undef prop_cstr
+
+	/* Vars */
+	u32 node;
+	char prop[64];
+	int rv, i;
+
+	/* Check if we're really running on a EFIKA */
+	node = call_prom("finddevice", 1, 1, ADDR("/"));
+	if (!PHANDLE_VALID(node))
+		return;
+
+	rv = prom_getprop(node, "model", prop, sizeof(prop));
+	if (rv == PROM_ERROR)
+		return;
+	if (strcmp(prop, "EFIKA5K2"))
+		return;
+
+	prom_printf("Applying EFIKA device tree fixups\n");
+
+	/* Process substitution table */
+	for (i=0; efika_subst_table[i].path; i++) {
+		struct subst_entry *se = &efika_subst_table[i];
+
+		node = call_prom("finddevice", 1, 1, ADDR(se->path));
+		if (!PHANDLE_VALID(node)) {
+			prom_printf("fixup_device_tree_efika: ",
+				"skipped entry %x - not found\n", i);
+			continue;
+		}
+
+		rv = prom_setprop(node, se->path, se->property,
+					se->value, se->value_len );
+		if (rv == PROM_ERROR)
+			prom_printf("fixup_device_tree_efika: ",
+				"skipped entry %x - setprop error\n", i);
+	}
+}
+#else
+#define fixup_device_tree_efika()
+#endif
+
 static void __init fixup_device_tree(void)
 {
 	fixup_device_tree_maple();
 	fixup_device_tree_chrp();
 	fixup_device_tree_pmac();
+	fixup_device_tree_efika();
 }
 
 static void __init prom_find_boot_cpu(void)
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 12c51e4..ea6fd55 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -5,6 +5,7 @@
 #include <linux/pci_regs.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
+#include <linux/etherdevice.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 
@@ -1003,3 +1004,42 @@
 	return res;
 }
 EXPORT_SYMBOL_GPL(of_irq_map_one);
+
+/**
+ * Search the device tree for the best MAC address to use.  'mac-address' is
+ * checked first, because that is supposed to contain to "most recent" MAC
+ * address. If that isn't set, then 'local-mac-address' is checked next,
+ * because that is the default address.  If that isn't set, then the obsolete
+ * 'address' is checked, just in case we're using an old device tree.
+ *
+ * Note that the 'address' property is supposed to contain a virtual address of
+ * the register set, but some DTS files have redefined that property to be the
+ * MAC address.
+ *
+ * All-zero MAC addresses are rejected, because those could be properties that
+ * exist in the device tree, but were not set by U-Boot.  For example, the
+ * DTS could define 'mac-address' and 'local-mac-address', with zero MAC
+ * addresses.  Some older U-Boots only initialized 'local-mac-address'.  In
+ * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
+ * but is all zeros.
+*/
+const void *of_get_mac_address(struct device_node *np)
+{
+	struct property *pp;
+
+	pp = of_find_property(np, "mac-address", NULL);
+	if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+		return pp->value;
+
+	pp = of_find_property(np, "local-mac-address", NULL);
+	if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+		return pp->value;
+
+	pp = of_find_property(np, "address", NULL);
+	if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+		return pp->value;
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_get_mac_address);
+
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 2fe82ab..6cbf2ae 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -160,7 +160,7 @@
 	return single_open(file, ppc_rtas_sensors_show, NULL);
 }
 
-struct file_operations ppc_rtas_sensors_operations = {
+const struct file_operations ppc_rtas_sensors_operations = {
 	.open		= sensors_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -172,7 +172,7 @@
 	return single_open(file, ppc_rtas_poweron_show, NULL);
 }
 
-struct file_operations ppc_rtas_poweron_operations = {
+const struct file_operations ppc_rtas_poweron_operations = {
 	.open		= poweron_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -185,7 +185,7 @@
 	return single_open(file, ppc_rtas_progress_show, NULL);
 }
 
-struct file_operations ppc_rtas_progress_operations = {
+const struct file_operations ppc_rtas_progress_operations = {
 	.open		= progress_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -198,7 +198,7 @@
 	return single_open(file, ppc_rtas_clock_show, NULL);
 }
 
-struct file_operations ppc_rtas_clock_operations = {
+const struct file_operations ppc_rtas_clock_operations = {
 	.open		= clock_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -211,7 +211,7 @@
 	return single_open(file, ppc_rtas_tone_freq_show, NULL);
 }
 
-struct file_operations ppc_rtas_tone_freq_operations = {
+const struct file_operations ppc_rtas_tone_freq_operations = {
 	.open		= tone_freq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -224,7 +224,7 @@
 	return single_open(file, ppc_rtas_tone_volume_show, NULL);
 }
 
-struct file_operations ppc_rtas_tone_volume_operations = {
+const struct file_operations ppc_rtas_tone_volume_operations = {
 	.open		= tone_volume_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -237,7 +237,7 @@
 	return single_open(file, ppc_rtas_rmo_buf_show, NULL);
 }
 
-struct file_operations ppc_rtas_rmo_buf_ops = {
+const struct file_operations ppc_rtas_rmo_buf_ops = {
 	.open		= rmo_buf_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 76b5d7e..9d0735a 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -182,7 +182,7 @@
 	char *os;
 	static int display_character, set_indicator;
 	static int display_width, display_lines, form_feed;
-	const static int *row_width;
+	static const int *row_width;
 	static DEFINE_SPINLOCK(progress_lock);
 	static int current_line;
 	static int pending_newline = 0;  /* did last write end with unprinted newline? */
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 0c4fcd3..f72118c 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -702,13 +702,12 @@
 }
 
 static struct proc_dir_entry *create_flash_pde(const char *filename,
-					       struct file_operations *fops)
+					       const struct file_operations *fops)
 {
 	struct proc_dir_entry *ent = NULL;
 
 	ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL);
 	if (ent != NULL) {
-		ent->nlink = 1;
 		ent->proc_fops = fops;
 		ent->owner = THIS_MODULE;
 	}
@@ -716,21 +715,21 @@
 	return ent;
 }
 
-static struct file_operations rtas_flash_operations = {
+static const struct file_operations rtas_flash_operations = {
 	.read		= rtas_flash_read,
 	.write		= rtas_flash_write,
 	.open		= rtas_excl_open,
 	.release	= rtas_flash_release,
 };
 
-static struct file_operations manage_flash_operations = {
+static const struct file_operations manage_flash_operations = {
 	.read		= manage_flash_read,
 	.write		= manage_flash_write,
 	.open		= rtas_excl_open,
 	.release	= rtas_excl_release,
 };
 
-static struct file_operations validate_flash_operations = {
+static const struct file_operations validate_flash_operations = {
 	.read		= validate_flash_read,
 	.write		= validate_flash_write,
 	.open		= rtas_excl_open,
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 6a19fa4..44a6a3c 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -116,12 +116,8 @@
  */
 void __init machine_init(unsigned long dt_ptr, unsigned long phys)
 {
-	/* If btext is enabled, we might have a BAT setup for early display,
-	 * thus we do enable some very basic udbg output
-	 */
-#ifdef CONFIG_BOOTX_TEXT
-	udbg_putc = btext_drawchar;
-#endif
+	/* Enable early debugging if any specified (see udbg.h) */
+	udbg_early_init();
 
 	/* Do some early initialization based on the flat device tree */
 	early_init_devtree(__va(dt_ptr));
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 0e8beca..924d692 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -78,29 +78,6 @@
 
 static void (*crash_ipi_function_ptr)(struct pt_regs *) = NULL;
 
-#ifdef CONFIG_MPIC
-int __init smp_mpic_probe(void)
-{
-	int nr_cpus;
-
-	DBG("smp_mpic_probe()...\n");
-
-	nr_cpus = cpus_weight(cpu_possible_map);
-
-	DBG("nr_cpus: %d\n", nr_cpus);
-
-	if (nr_cpus > 1)
-		mpic_request_ipis();
-
-	return nr_cpus;
-}
-
-void __devinit smp_mpic_setup_cpu(int cpu)
-{
-	mpic_setup_this_cpu();
-}
-#endif /* CONFIG_MPIC */
-
 #ifdef CONFIG_PPC64
 void __devinit smp_generic_kick_cpu(int nr)
 {
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 03a2a2f..673e8d9 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -198,73 +198,6 @@
 		 __put_user(i->tv_usec, &o->tv_usec)));
 }
 
-struct sysinfo32 {
-        s32 uptime;
-        u32 loads[3];
-        u32 totalram;
-        u32 freeram;
-        u32 sharedram;
-        u32 bufferram;
-        u32 totalswap;
-        u32 freeswap;
-        unsigned short procs;
-	unsigned short pad;
-	u32 totalhigh;
-	u32 freehigh;
-	u32 mem_unit;
-	char _f[20-2*sizeof(int)-sizeof(int)];
-};
-
-asmlinkage long compat_sys_sysinfo(struct sysinfo32 __user *info)
-{
-	struct sysinfo s;
-	int ret, err;
-	int bitcount=0;
-	mm_segment_t old_fs = get_fs ();
-	
-	/* The __user cast is valid due to set_fs() */
-	set_fs (KERNEL_DS);
-	ret = sys_sysinfo((struct sysinfo __user *)&s);
-	set_fs (old_fs);
-
-	/* Check to see if any memory value is too large for 32-bit and
-         * scale down if needed.
-         */
-	if ((s.totalram >> 32) || (s.totalswap >> 32)) {
-	    while (s.mem_unit < PAGE_SIZE) {
-		s.mem_unit <<= 1;
-		bitcount++;
-	    }
-	    s.totalram >>=bitcount;
-	    s.freeram >>= bitcount;
-	    s.sharedram >>= bitcount;
-	    s.bufferram >>= bitcount;
-	    s.totalswap >>= bitcount;
-	    s.freeswap >>= bitcount;
-	    s.totalhigh >>= bitcount;
-	    s.freehigh >>= bitcount;
-	}
-
-	err = put_user (s.uptime, &info->uptime);
-	err |= __put_user (s.loads[0], &info->loads[0]);
-	err |= __put_user (s.loads[1], &info->loads[1]);
-	err |= __put_user (s.loads[2], &info->loads[2]);
-	err |= __put_user (s.totalram, &info->totalram);
-	err |= __put_user (s.freeram, &info->freeram);
-	err |= __put_user (s.sharedram, &info->sharedram);
-	err |= __put_user (s.bufferram, &info->bufferram);
-	err |= __put_user (s.totalswap, &info->totalswap);
-	err |= __put_user (s.freeswap, &info->freeswap);
-	err |= __put_user (s.procs, &info->procs);
-	err |= __put_user (s.totalhigh, &info->totalhigh);
-	err |= __put_user (s.freehigh, &info->freehigh);
-	err |= __put_user (s.mem_unit, &info->mem_unit);
-	if (err)
-		return -EFAULT;
-	
-	return ret;
-}
-
 
 
 
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index dcc6f15..17724fb 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -107,12 +107,10 @@
 	if (machine_is(powermac) && pmac_backlight) {
 		struct backlight_properties *props;
 
-		down(&pmac_backlight->sem);
-		props = pmac_backlight->props;
+		props = &pmac_backlight->props;
 		props->brightness = props->max_brightness;
 		props->power = FB_BLANK_UNBLANK;
-		props->update_status(pmac_backlight);
-		up(&pmac_backlight->sem);
+		backlight_update_status(pmac_backlight);
 	}
 	mutex_unlock(&pmac_backlight_mutex);
 #endif
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 8f5afdb..7e09718 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -49,6 +49,8 @@
 	udbg_init_debug_beat();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE)
 	udbg_init_pas_realmode();
+#elif defined(CONFIG_BOOTX_TEXT)
+	udbg_init_btext();
 #endif
 }
 
@@ -150,7 +152,7 @@
 {
 	if (!early_console_initialized)
 		return;
-	if (strstr(saved_command_line, "udbg-immortal")) {
+	if (strstr(boot_command_line, "udbg-immortal")) {
 		printk(KERN_INFO "early console immortal !\n");
 		return;
 	}
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index ae0ede1..e46c31b 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -51,17 +51,21 @@
 
 extern char vdso32_start, vdso32_end;
 static void *vdso32_kbase = &vdso32_start;
-unsigned int vdso32_pages;
+static unsigned int vdso32_pages;
+static struct page **vdso32_pagelist;
 unsigned long vdso32_sigtramp;
 unsigned long vdso32_rt_sigtramp;
 
 #ifdef CONFIG_PPC64
 extern char vdso64_start, vdso64_end;
 static void *vdso64_kbase = &vdso64_start;
-unsigned int vdso64_pages;
+static unsigned int vdso64_pages;
+static struct page **vdso64_pagelist;
 unsigned long vdso64_rt_sigtramp;
 #endif /* CONFIG_PPC64 */
 
+static int vdso_ready;
+
 /*
  * The vdso data page (aka. systemcfg for old ppc64 fans) is here.
  * Once the early boot kernel code no longer needs to muck around
@@ -165,55 +169,6 @@
 #endif /* DEBUG */
 
 /*
- * Keep a dummy vma_close for now, it will prevent VMA merging.
- */
-static void vdso_vma_close(struct vm_area_struct * vma)
-{
-}
-
-/*
- * Our nopage() function, maps in the actual vDSO kernel pages, they will
- * be mapped read-only by do_no_page(), and eventually COW'ed, either
- * right away for an initial write access, or by do_wp_page().
- */
-static struct page * vdso_vma_nopage(struct vm_area_struct * vma,
-				     unsigned long address, int *type)
-{
-	unsigned long offset = address - vma->vm_start;
-	struct page *pg;
-#ifdef CONFIG_PPC64
-	void *vbase = (vma->vm_mm->task_size > TASK_SIZE_USER32) ?
-		vdso64_kbase : vdso32_kbase;
-#else
-	void *vbase = vdso32_kbase;
-#endif
-
-	DBG("vdso_vma_nopage(current: %s, address: %016lx, off: %lx)\n",
-	    current->comm, address, offset);
-
-	if (address < vma->vm_start || address > vma->vm_end)
-		return NOPAGE_SIGBUS;
-
-	/*
-	 * Last page is systemcfg.
-	 */
-	if ((vma->vm_end - address) <= PAGE_SIZE)
-		pg = virt_to_page(vdso_data);
-	else
-		pg = virt_to_page(vbase + offset);
-
-	get_page(pg);
-	DBG(" ->page count: %d\n", page_count(pg));
-
-	return pg;
-}
-
-static struct vm_operations_struct vdso_vmops = {
-	.close	= vdso_vma_close,
-	.nopage	= vdso_vma_nopage,
-};
-
-/*
  * This is called from binfmt_elf, we create the special vma for the
  * vDSO and insert it into the mm struct tree
  */
@@ -221,20 +176,26 @@
 				int executable_stack)
 {
 	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma;
+	struct page **vdso_pagelist;
 	unsigned long vdso_pages;
 	unsigned long vdso_base;
 	int rc;
 
+	if (!vdso_ready)
+		return 0;
+
 #ifdef CONFIG_PPC64
 	if (test_thread_flag(TIF_32BIT)) {
+		vdso_pagelist = vdso32_pagelist;
 		vdso_pages = vdso32_pages;
 		vdso_base = VDSO32_MBASE;
 	} else {
+		vdso_pagelist = vdso64_pagelist;
 		vdso_pages = vdso64_pages;
 		vdso_base = VDSO64_MBASE;
 	}
 #else
+	vdso_pagelist = vdso32_pagelist;
 	vdso_pages = vdso32_pages;
 	vdso_base = VDSO32_MBASE;
 #endif
@@ -262,17 +223,6 @@
 		goto fail_mmapsem;
 	}
 
-
-	/* Allocate a VMA structure and fill it up */
-	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
-	if (vma == NULL) {
-		rc = -ENOMEM;
-		goto fail_mmapsem;
-	}
-	vma->vm_mm = mm;
-	vma->vm_start = vdso_base;
-	vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT);
-
 	/*
 	 * our vma flags don't have VM_WRITE so by default, the process isn't
 	 * allowed to write those pages.
@@ -282,32 +232,26 @@
 	 * and your nice userland gettimeofday will be totally dead.
 	 * It's fine to use that for setting breakpoints in the vDSO code
 	 * pages though
-	 */
-	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC;
-	/*
+	 *
 	 * Make sure the vDSO gets into every core dump.
 	 * Dumping its contents makes post-mortem fully interpretable later
 	 * without matching up the same kernel and hardware config to see
 	 * what PC values meant.
 	 */
-	vma->vm_flags |= VM_ALWAYSDUMP;
-	vma->vm_flags |= mm->def_flags;
-	vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
-	vma->vm_ops = &vdso_vmops;
-
-	/* Insert new VMA */
-	rc = insert_vm_struct(mm, vma);
+	rc = install_special_mapping(mm, vdso_base, vdso_pages << PAGE_SHIFT,
+				     VM_READ|VM_EXEC|
+				     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+				     VM_ALWAYSDUMP,
+				     vdso_pagelist);
 	if (rc)
-		goto fail_vma;
+		goto fail_mmapsem;
 
-	/* Put vDSO base into mm struct and account for memory usage */
+	/* Put vDSO base into mm struct */
 	current->mm->context.vdso_base = vdso_base;
-	mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+
 	up_write(&mm->mmap_sem);
 	return 0;
 
- fail_vma:
-	kmem_cache_free(vm_area_cachep, vma);
  fail_mmapsem:
 	up_write(&mm->mmap_sem);
 	return rc;
@@ -719,7 +663,7 @@
 }
 
 
-void __init vdso_init(void)
+static int __init vdso_init(void)
 {
 	int i;
 
@@ -774,26 +718,44 @@
 #ifdef CONFIG_PPC64
 		vdso64_pages = 0;
 #endif
-		return;
+		return 0;
 	}
 
 	/* Make sure pages are in the correct state */
+	vdso32_pagelist = kzalloc(sizeof(struct page *) * (vdso32_pages + 2),
+				  GFP_KERNEL);
+	BUG_ON(vdso32_pagelist == NULL);
 	for (i = 0; i < vdso32_pages; i++) {
 		struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE);
 		ClearPageReserved(pg);
 		get_page(pg);
-
+		vdso32_pagelist[i] = pg;
 	}
+	vdso32_pagelist[i++] = virt_to_page(vdso_data);
+	vdso32_pagelist[i] = NULL;
+
 #ifdef CONFIG_PPC64
+	vdso64_pagelist = kzalloc(sizeof(struct page *) * (vdso64_pages + 2),
+				  GFP_KERNEL);
+	BUG_ON(vdso64_pagelist == NULL);
 	for (i = 0; i < vdso64_pages; i++) {
 		struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE);
 		ClearPageReserved(pg);
 		get_page(pg);
+		vdso64_pagelist[i] = pg;
 	}
+	vdso64_pagelist[i++] = virt_to_page(vdso_data);
+	vdso64_pagelist[i] = NULL;
 #endif /* CONFIG_PPC64 */
 
 	get_page(virt_to_page(vdso_data));
+
+	smp_wmb();
+	vdso_ready = 1;
+
+	return 0;
 }
+arch_initcall(vdso_init);
 
 int in_gate_area_no_task(unsigned long addr)
 {
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 04b8e71..7eefeb4 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -131,14 +131,14 @@
 		__stop___fw_ftr_fixup = .;
 	}
 #endif
-
+#ifdef CONFIG_BLK_DEV_INITRD
 	. = ALIGN(PAGE_SIZE);
 	.init.ramfs : {
 		__initramfs_start = .;
 		*(.init.ramfs)
 		__initramfs_end = .;
 	}
-
+#endif
 #ifdef CONFIG_PPC32
 	. = ALIGN(32);
 #else
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 77b4637..52f397c1 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -384,9 +384,6 @@
 		initsize >> 10);
 
 	mem_init_done = 1;
-
-	/* Initialize the vDSO */
-	vdso_init();
 }
 
 /*
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 2627909..e86c37c 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -154,7 +154,7 @@
  * characteristics relative to its multiple connections.  We ignore
  * this for now.  We also assume that all cpu and memory sets have
  * their distances represented at a common level.  This won't be
- * true for heirarchical NUMA.
+ * true for hierarchical NUMA.
  *
  * In any case the ibm,associativity-reference-points should give
  * the correct depth for a normal NUMA system.
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index bd02272..c284bda 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -295,7 +295,7 @@
 }
 
 /* is x a power of 4? */
-#define is_power_of_4(x)	is_power_of_2(x) && (ffs(x) & 1))
+#define is_power_of_4(x)	is_power_of_2(x) && (ffs(x) & 1)
 
 /*
  * Set up a mapping for a block of I/O.
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 16e4ee1..1d44340 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -103,7 +103,7 @@
 		 *
 		 */
 		if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
-				      mmu_virtual_psize)) {
+				      mmu_io_psize)) {
 			printk(KERN_ERR "Failed to do bolted mapping IO "
 			       "memory at %016lx !\n", pa);
 			return -ENOMEM;
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c
index 2eb15f3..e08e1d7 100644
--- a/arch/powerpc/oprofile/op_model_cell.c
+++ b/arch/powerpc/oprofile/op_model_cell.c
@@ -39,10 +39,17 @@
 #include "../platforms/cell/interrupt.h"
 
 #define PPU_CYCLES_EVENT_NUM 1	/*  event number for CYCLES */
+#define PPU_CYCLES_GRP_NUM   1  /* special group number for identifying
+                                 * PPU_CYCLES event
+                                 */
 #define CBE_COUNT_ALL_CYCLES 0x42800000	/* PPU cycle event specifier */
 
-#define NUM_THREADS 2
-#define VIRT_CNTR_SW_TIME_NS 100000000	// 0.5 seconds
+#define NUM_THREADS 2         /* number of physical threads in
+			       * physical processor
+			       */
+#define NUM_TRACE_BUS_WORDS 4
+#define NUM_INPUT_BUS_WORDS 2
+
 
 struct pmc_cntrl_data {
 	unsigned long vcntr;
@@ -58,7 +65,7 @@
 struct pm_signal {
 	u16 cpu;		/* Processor to modify */
 	u16 sub_unit;		/* hw subunit this applies to (if applicable) */
-	u16 signal_group;	/* Signal Group to Enable/Disable */
+	short int signal_group;	/* Signal Group to Enable/Disable */
 	u8 bus_word;		/* Enable/Disable on this Trace/Trigger/Event
 				 * Bus Word(s) (bitmask)
 				 */
@@ -93,7 +100,6 @@
 	u32 pm07_cntrl[NR_PHYS_CTRS];
 } pm_regs;
 
-
 #define GET_SUB_UNIT(x) ((x & 0x0000f000) >> 12)
 #define GET_BUS_WORD(x) ((x & 0x000000f0) >> 4)
 #define GET_BUS_TYPE(x) ((x & 0x00000300) >> 8)
@@ -101,7 +107,6 @@
 #define GET_COUNT_CYCLES(x) (x & 0x00000001)
 #define GET_INPUT_CONTROL(x) ((x & 0x00000004) >> 2)
 
-
 static DEFINE_PER_CPU(unsigned long[NR_PHYS_CTRS], pmc_values);
 
 static struct pmc_cntrl_data pmc_cntrl[NUM_THREADS][NR_PHYS_CTRS];
@@ -129,8 +134,8 @@
 
 static u32 ctr_enabled;
 
-static unsigned char trace_bus[4];
-static unsigned char input_bus[2];
+static unsigned char trace_bus[NUM_TRACE_BUS_WORDS];
+static unsigned char input_bus[NUM_INPUT_BUS_WORDS];
 
 /*
  * Firmware interface functions
@@ -177,25 +182,40 @@
 static void pm_rtas_activate_signals(u32 node, u32 count)
 {
 	int ret;
-	int j;
+	int i, j;
 	struct pm_signal pm_signal_local[NR_PHYS_CTRS];
 
+	/* There is no debug setup required for the cycles event.
+	 * Note that only events in the same group can be used.
+	 * Otherwise, there will be conflicts in correctly routing
+	 * the signals on the debug bus.  It is the responsiblity
+	 * of the OProfile user tool to check the events are in
+	 * the same group.
+	 */
+	i = 0;
 	for (j = 0; j < count; j++) {
-		/* fw expects physical cpu # */
-		pm_signal_local[j].cpu = node;
-		pm_signal_local[j].signal_group = pm_signal[j].signal_group;
-		pm_signal_local[j].bus_word = pm_signal[j].bus_word;
-		pm_signal_local[j].sub_unit = pm_signal[j].sub_unit;
-		pm_signal_local[j].bit = pm_signal[j].bit;
+		if (pm_signal[j].signal_group != PPU_CYCLES_GRP_NUM) {
+
+			/* fw expects physical cpu # */
+			pm_signal_local[i].cpu = node;
+			pm_signal_local[i].signal_group
+				= pm_signal[j].signal_group;
+			pm_signal_local[i].bus_word = pm_signal[j].bus_word;
+			pm_signal_local[i].sub_unit = pm_signal[j].sub_unit;
+			pm_signal_local[i].bit = pm_signal[j].bit;
+			i++;
+		}
 	}
 
-	ret = rtas_ibm_cbe_perftools(SUBFUNC_ACTIVATE, PASSTHRU_ENABLE,
-				     pm_signal_local,
-				     count * sizeof(struct pm_signal));
+	if (i != 0) {
+		ret = rtas_ibm_cbe_perftools(SUBFUNC_ACTIVATE, PASSTHRU_ENABLE,
+					     pm_signal_local,
+					     i * sizeof(struct pm_signal));
 
-	if (ret)
-		printk(KERN_WARNING "%s: rtas returned: %d\n",
-		       __FUNCTION__, ret);
+		if (ret)
+			printk(KERN_WARNING "%s: rtas returned: %d\n",
+			       __FUNCTION__, ret);
+	}
 }
 
 /*
@@ -212,7 +232,7 @@
 		/* Special Event: Count all cpu cycles */
 		pm_regs.pm07_cntrl[ctr] = CBE_COUNT_ALL_CYCLES;
 		p = &(pm_signal[ctr]);
-		p->signal_group = 21;
+		p->signal_group = PPU_CYCLES_GRP_NUM;
 		p->bus_word = 1;
 		p->sub_unit = 0;
 		p->bit = 0;
@@ -232,13 +252,21 @@
 
 	p->signal_group = event / 100;
 	p->bus_word = bus_word;
-	p->sub_unit = unit_mask & 0x0000f000;
+	p->sub_unit = (unit_mask & 0x0000f000) >> 12;
 
 	pm_regs.pm07_cntrl[ctr] = 0;
 	pm_regs.pm07_cntrl[ctr] |= PM07_CTR_COUNT_CYCLES(count_cycles);
 	pm_regs.pm07_cntrl[ctr] |= PM07_CTR_POLARITY(polarity);
 	pm_regs.pm07_cntrl[ctr] |= PM07_CTR_INPUT_CONTROL(input_control);
 
+	/* Some of the islands signal selection is based on 64 bit words.
+	 * The debug bus words are 32 bits, the input words to the performance
+	 * counters are defined as 32 bits.  Need to convert the 64 bit island
+	 * specification to the appropriate 32 input bit and bus word for the
+	 * performance counter event selection.  See the CELL Performance
+	 * monitoring signals manual and the Perf cntr hardware descriptions
+	 * for the details.
+	 */
 	if (input_control == 0) {
 		if (signal_bit > 31) {
 			signal_bit -= 32;
@@ -259,12 +287,12 @@
 		p->bit = signal_bit;
 	}
 
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < NUM_TRACE_BUS_WORDS; i++) {
 		if (bus_word & (1 << i)) {
 			pm_regs.debug_bus_control |=
 			    (bus_type << (31 - (2 * i) + 1));
 
-			for (j = 0; j < 2; j++) {
+			for (j = 0; j < NUM_INPUT_BUS_WORDS; j++) {
 				if (input_bus[j] == 0xff) {
 					input_bus[j] = i;
 					pm_regs.group_control |=
@@ -278,52 +306,58 @@
 	;
 }
 
-static void write_pm_cntrl(int cpu, struct pm_cntrl *pm_cntrl)
+static void write_pm_cntrl(int cpu)
 {
-	/* Oprofile will use 32 bit counters, set bits 7:10 to 0 */
+	/* Oprofile will use 32 bit counters, set bits 7:10 to 0
+	 * pmregs.pm_cntrl is a global
+	 */
+
 	u32 val = 0;
-	if (pm_cntrl->enable == 1)
+	if (pm_regs.pm_cntrl.enable == 1)
 		val |= CBE_PM_ENABLE_PERF_MON;
 
-	if (pm_cntrl->stop_at_max == 1)
+	if (pm_regs.pm_cntrl.stop_at_max == 1)
 		val |= CBE_PM_STOP_AT_MAX;
 
-	if (pm_cntrl->trace_mode == 1)
-		val |= CBE_PM_TRACE_MODE_SET(pm_cntrl->trace_mode);
+	if (pm_regs.pm_cntrl.trace_mode == 1)
+		val |= CBE_PM_TRACE_MODE_SET(pm_regs.pm_cntrl.trace_mode);
 
-	if (pm_cntrl->freeze == 1)
+	if (pm_regs.pm_cntrl.freeze == 1)
 		val |= CBE_PM_FREEZE_ALL_CTRS;
 
 	/* Routine set_count_mode must be called previously to set
 	 * the count mode based on the user selection of user and kernel.
 	 */
-	val |= CBE_PM_COUNT_MODE_SET(pm_cntrl->count_mode);
+	val |= CBE_PM_COUNT_MODE_SET(pm_regs.pm_cntrl.count_mode);
 	cbe_write_pm(cpu, pm_control, val);
 }
 
 static inline void
-set_count_mode(u32 kernel, u32 user, struct pm_cntrl *pm_cntrl)
+set_count_mode(u32 kernel, u32 user)
 {
 	/* The user must specify user and kernel if they want them. If
-	 *  neither is specified, OProfile will count in hypervisor mode
+	 *  neither is specified, OProfile will count in hypervisor mode.
+	 *  pm_regs.pm_cntrl is a global
 	 */
 	if (kernel) {
 		if (user)
-			pm_cntrl->count_mode = CBE_COUNT_ALL_MODES;
+			pm_regs.pm_cntrl.count_mode = CBE_COUNT_ALL_MODES;
 		else
-			pm_cntrl->count_mode = CBE_COUNT_SUPERVISOR_MODE;
+			pm_regs.pm_cntrl.count_mode =
+				CBE_COUNT_SUPERVISOR_MODE;
 	} else {
 		if (user)
-			pm_cntrl->count_mode = CBE_COUNT_PROBLEM_MODE;
+			pm_regs.pm_cntrl.count_mode = CBE_COUNT_PROBLEM_MODE;
 		else
-			pm_cntrl->count_mode = CBE_COUNT_HYPERVISOR_MODE;
+			pm_regs.pm_cntrl.count_mode =
+				CBE_COUNT_HYPERVISOR_MODE;
 	}
 }
 
 static inline void enable_ctr(u32 cpu, u32 ctr, u32 * pm07_cntrl)
 {
 
-	pm07_cntrl[ctr] |= PM07_CTR_ENABLE(1);
+	pm07_cntrl[ctr] |= CBE_PM_CTR_ENABLE;
 	cbe_write_pm07_control(cpu, ctr, pm07_cntrl[ctr]);
 }
 
@@ -365,6 +399,14 @@
 	hdw_thread = 1 ^ hdw_thread;
 	next_hdw_thread = hdw_thread;
 
+	for (i = 0; i < num_counters; i++)
+	/* There are some per thread events.  Must do the
+	 * set event, for the thread that is being started
+	 */
+		set_pm_event(i,
+			pmc_cntrl[next_hdw_thread][i].evnts,
+			pmc_cntrl[next_hdw_thread][i].masks);
+
 	/* The following is done only once per each node, but
 	 * we need cpu #, not node #, to pass to the cbe_xxx functions.
 	 */
@@ -385,12 +427,13 @@
 			    == 0xFFFFFFFF)
 				/* If the cntr value is 0xffffffff, we must
 				 * reset that to 0xfffffff0 when the current
-				 * thread is restarted.  This will generate a new
-				 * interrupt and make sure that we never restore
-				 * the counters to the max value.  If the counters
-				 * were restored to the max value, they do not
-				 * increment and no interrupts are generated.  Hence
-				 * no more samples will be collected on that cpu.
+				 * thread is restarted.  This will generate a
+				 * new interrupt and make sure that we never
+				 * restore the counters to the max value.  If
+				 * the counters were restored to the max value,
+				 * they do not increment and no interrupts are
+				 * generated.  Hence no more samples will be
+				 * collected on that cpu.
 				 */
 				cbe_write_ctr(cpu, i, 0xFFFFFFF0);
 			else
@@ -410,9 +453,6 @@
 				 * Must do the set event, enable_cntr
 				 * for each cpu.
 				 */
-				set_pm_event(i,
-				     pmc_cntrl[next_hdw_thread][i].evnts,
-				     pmc_cntrl[next_hdw_thread][i].masks);
 				enable_ctr(cpu, i,
 					   pm_regs.pm07_cntrl);
 			} else {
@@ -465,8 +505,7 @@
 	pm_regs.pm_cntrl.trace_mode = 0;
 	pm_regs.pm_cntrl.freeze = 1;
 
-	set_count_mode(sys->enable_kernel, sys->enable_user,
-		       &pm_regs.pm_cntrl);
+	set_count_mode(sys->enable_kernel, sys->enable_user);
 
 	/* Setup the thread 0 events */
 	for (i = 0; i < num_ctrs; ++i) {
@@ -498,10 +537,10 @@
 		pmc_cntrl[1][i].vcntr = i;
 	}
 
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < NUM_TRACE_BUS_WORDS; i++)
 		trace_bus[i] = 0xff;
 
-	for (i = 0; i < 2; i++)
+	for (i = 0; i < NUM_INPUT_BUS_WORDS; i++)
 		input_bus[i] = 0xff;
 
 	/* Our counters count up, and "count" refers to
@@ -560,7 +599,7 @@
 	cbe_write_pm(cpu, pm_start_stop, 0);
 	cbe_write_pm(cpu, group_control, pm_regs.group_control);
 	cbe_write_pm(cpu, debug_bus_control, pm_regs.debug_bus_control);
-	write_pm_cntrl(cpu, &pm_regs.pm_cntrl);
+	write_pm_cntrl(cpu);
 
 	for (i = 0; i < num_counters; ++i) {
 		if (ctr_enabled & (1 << i)) {
@@ -602,7 +641,7 @@
 			}
 		}
 
-		cbe_clear_pm_interrupts(cpu);
+		cbe_get_and_clear_pm_interrupts(cpu);
 		cbe_enable_pm_interrupts(cpu, hdw_thread, interrupt_mask);
 		cbe_enable_pm(cpu);
 	}
@@ -672,7 +711,7 @@
 
 	cbe_disable_pm(cpu);
 
-	interrupt_mask = cbe_clear_pm_interrupts(cpu);
+	interrupt_mask = cbe_get_and_clear_pm_interrupts(cpu);
 
 	/* If the interrupt mask has been cleared, then the virt cntr
 	 * has cleared the interrupt.  When the thread that generated
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
index 795b713..07cdbca 100644
--- a/arch/powerpc/platforms/52xx/Makefile
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -6,5 +6,5 @@
 obj-$(CONFIG_PCI)		+= mpc52xx_pci.o
 endif
 
-obj-$(CONFIG_PPC_EFIKA)		+= efika-setup.o efika-pci.o
+obj-$(CONFIG_PPC_EFIKA)		+= efika.o
 obj-$(CONFIG_PPC_LITE5200)	+= lite5200.o
diff --git a/arch/powerpc/platforms/52xx/efika-pci.c b/arch/powerpc/platforms/52xx/efika-pci.c
deleted file mode 100644
index 62e05b2..0000000
--- a/arch/powerpc/platforms/52xx/efika-pci.c
+++ /dev/null
@@ -1,119 +0,0 @@
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/sections.h>
-#include <asm/pci-bridge.h>
-#include <asm/rtas.h>
-
-#include "efika.h"
-
-#ifdef CONFIG_PCI
-/*
- * Access functions for PCI config space using RTAS calls.
- */
-static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
-			    int len, u32 * val)
-{
-	struct pci_controller *hose = bus->sysdata;
-	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
-	    | (((bus->number - hose->first_busno) & 0xff) << 16)
-	    | (hose->index << 24);
-	int ret = -1;
-	int rval;
-
-	rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len);
-	*val = ret;
-	return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
-}
-
-static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
-			     int offset, int len, u32 val)
-{
-	struct pci_controller *hose = bus->sysdata;
-	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
-	    | (((bus->number - hose->first_busno) & 0xff) << 16)
-	    | (hose->index << 24);
-	int rval;
-
-	rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
-			 addr, len, val);
-	return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops rtas_pci_ops = {
-	rtas_read_config,
-	rtas_write_config
-};
-
-void __init efika_pcisetup(void)
-{
-	const int *bus_range;
-	int len;
-	struct pci_controller *hose;
-	struct device_node *root;
-	struct device_node *pcictrl;
-
-	root = of_find_node_by_path("/");
-	if (root == NULL) {
-		printk(KERN_WARNING EFIKA_PLATFORM_NAME
-		       ": Unable to find the root node\n");
-		return;
-	}
-
-	for (pcictrl = NULL;;) {
-		pcictrl = of_get_next_child(root, pcictrl);
-		if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0))
-			break;
-	}
-
-	of_node_put(root);
-
-	if (pcictrl == NULL) {
-		printk(KERN_WARNING EFIKA_PLATFORM_NAME
-		       ": Unable to find the PCI bridge node\n");
-		return;
-	}
-
-	bus_range = get_property(pcictrl, "bus-range", &len);
-	if (bus_range == NULL || len < 2 * sizeof(int)) {
-		printk(KERN_WARNING EFIKA_PLATFORM_NAME
-		       ": Can't get bus-range for %s\n", pcictrl->full_name);
-		return;
-	}
-
-	if (bus_range[1] == bus_range[0])
-		printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
-		       bus_range[0]);
-	else
-		printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
-		       bus_range[0], bus_range[1]);
-	printk(" controlled by %s\n", pcictrl->full_name);
-	printk("\n");
-
-	hose = pcibios_alloc_controller();
-	if (!hose) {
-		printk(KERN_WARNING EFIKA_PLATFORM_NAME
-		       ": Can't allocate PCI controller structure for %s\n",
-		       pcictrl->full_name);
-		return;
-	}
-
-	hose->arch_data = of_node_get(pcictrl);
-	hose->first_busno = bus_range[0];
-	hose->last_busno = bus_range[1];
-	hose->ops = &rtas_pci_ops;
-
-	pci_process_bridge_OF_ranges(hose, pcictrl, 0);
-}
-
-#else
-void __init efika_pcisetup(void)
-{}
-#endif
diff --git a/arch/powerpc/platforms/52xx/efika-setup.c b/arch/powerpc/platforms/52xx/efika-setup.c
deleted file mode 100644
index 110c980..0000000
--- a/arch/powerpc/platforms/52xx/efika-setup.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- *
- * Efika 5K2 platform setup
- * Some code really inspired from the lite5200b platform.
- * 
- * Copyright (C) 2006 bplan GmbH
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- *
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/utsrelease.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-#include <linux/initrd.h>
-#include <linux/timer.h>
-#include <linux/pci.h>
-
-#include <asm/pgtable.h>
-#include <asm/prom.h>
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/rtas.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
-#include <asm/mpc52xx.h>
-
-#include "efika.h"
-
-static void efika_show_cpuinfo(struct seq_file *m)
-{
-	struct device_node *root;
-	const char *revision = NULL;
-	const char *codegendescription = NULL;
-	const char *codegenvendor = NULL;
-
-	root = of_find_node_by_path("/");
-	if (root) {
-		revision = get_property(root, "revision", NULL);
-		codegendescription =
-		    get_property(root, "CODEGEN,description", NULL);
-		codegenvendor = get_property(root, "CODEGEN,vendor", NULL);
-
-		of_node_put(root);
-	}
-
-	if (codegendescription)
-		seq_printf(m, "machine\t\t: %s\n", codegendescription);
-	else
-		seq_printf(m, "machine\t\t: Efika\n");
-
-	if (revision)
-		seq_printf(m, "revision\t: %s\n", revision);
-
-	if (codegenvendor)
-		seq_printf(m, "vendor\t\t: %s\n", codegenvendor);
-
-	of_node_put(root);
-}
-
-static void __init efika_setup_arch(void)
-{
-	rtas_initialize();
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	initrd_below_start_ok = 1;
-
-	if (initrd_start)
-		ROOT_DEV = Root_RAM0;
-	else
-#endif
-		ROOT_DEV = Root_SDA2;	/* sda2 (sda1 is for the kernel) */
-
-	efika_pcisetup();
-
-	if (ppc_md.progress)
-		ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0);
-}
-
-static void __init efika_init(void)
-{
-	struct device_node *np;
-	struct device_node *cnp = NULL;
-	const u32 *base;
-
-	/* Find every child of the SOC node and add it to of_platform */
-	np = of_find_node_by_name(NULL, "builtin");
-	if (np) {
-		char name[BUS_ID_SIZE];
-		while ((cnp = of_get_next_child(np, cnp))) {
-			strcpy(name, cnp->name);
-
-			base = get_property(cnp, "reg", NULL);
-			if (base == NULL)
-				continue;
-
-			snprintf(name+strlen(name), BUS_ID_SIZE, "@%x", *base);
-			of_platform_device_create(cnp, name, NULL);
-
-			printk(KERN_INFO EFIKA_PLATFORM_NAME" : Added %s (type '%s' at '%s') to the known devices\n", name, cnp->type, cnp->full_name);
-		}
-	}
-
-	if (ppc_md.progress)
-		ppc_md.progress("  Have fun with your Efika!    ", 0x7777);
-}
-
-static int __init efika_probe(void)
-{
-	char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
-					  "model", NULL);
-
-	if (model == NULL)
-		return 0;
-	if (strcmp(model, "EFIKA5K2"))
-		return 0;
-
-	ISA_DMA_THRESHOLD = ~0L;
-	DMA_MODE_READ = 0x44;
-	DMA_MODE_WRITE = 0x48;
-
-	return 1;
-}
-
-define_machine(efika)
-{
-	.name = EFIKA_PLATFORM_NAME,
-	.probe = efika_probe,
-	.setup_arch = efika_setup_arch,
-	.init = efika_init,
-	.show_cpuinfo = efika_show_cpuinfo,
-	.init_IRQ = mpc52xx_init_irq,
-	.get_irq = mpc52xx_get_irq,
-	.restart = rtas_restart,
-	.power_off = rtas_power_off,
-	.halt = rtas_halt,
-	.set_rtc_time = rtas_set_rtc_time,
-	.get_rtc_time = rtas_get_rtc_time,
-	.progress = rtas_progress,
-	.get_boot_time = rtas_get_boot_time,
-	.calibrate_decr = generic_calibrate_decr,
-	.phys_mem_access_prot = pci_phys_mem_access_prot,
-};
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
new file mode 100644
index 0000000..8de0341
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -0,0 +1,243 @@
+/*
+ * Efika 5K2 platform code
+ * Some code really inspired from the lite5200b platform.
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/utsrelease.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sections.h>
+#include <asm/pci-bridge.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/rtas.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+#include <asm/mpc52xx.h>
+
+
+#define EFIKA_PLATFORM_NAME "Efika"
+
+
+/* ------------------------------------------------------------------------ */
+/* PCI accesses thru RTAS                                                   */
+/* ------------------------------------------------------------------------ */
+
+#ifdef CONFIG_PCI
+
+/*
+ * Access functions for PCI config space using RTAS calls.
+ */
+static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+			    int len, u32 * val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+	    | (((bus->number - hose->first_busno) & 0xff) << 16)
+	    | (hose->index << 24);
+	int ret = -1;
+	int rval;
+
+	rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len);
+	*val = ret;
+	return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+}
+
+static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
+			     int offset, int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+	    | (((bus->number - hose->first_busno) & 0xff) << 16)
+	    | (hose->index << 24);
+	int rval;
+
+	rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
+			 addr, len, val);
+	return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops rtas_pci_ops = {
+	rtas_read_config,
+	rtas_write_config
+};
+
+
+void __init efika_pcisetup(void)
+{
+	const int *bus_range;
+	int len;
+	struct pci_controller *hose;
+	struct device_node *root;
+	struct device_node *pcictrl;
+
+	root = of_find_node_by_path("/");
+	if (root == NULL) {
+		printk(KERN_WARNING EFIKA_PLATFORM_NAME
+		       ": Unable to find the root node\n");
+		return;
+	}
+
+	for (pcictrl = NULL;;) {
+		pcictrl = of_get_next_child(root, pcictrl);
+		if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0))
+			break;
+	}
+
+	of_node_put(root);
+
+	if (pcictrl == NULL) {
+		printk(KERN_WARNING EFIKA_PLATFORM_NAME
+		       ": Unable to find the PCI bridge node\n");
+		return;
+	}
+
+	bus_range = get_property(pcictrl, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		printk(KERN_WARNING EFIKA_PLATFORM_NAME
+		       ": Can't get bus-range for %s\n", pcictrl->full_name);
+		return;
+	}
+
+	if (bus_range[1] == bus_range[0])
+		printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
+		       bus_range[0]);
+	else
+		printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
+		       bus_range[0], bus_range[1]);
+	printk(" controlled by %s\n", pcictrl->full_name);
+	printk("\n");
+
+	hose = pcibios_alloc_controller();
+	if (!hose) {
+		printk(KERN_WARNING EFIKA_PLATFORM_NAME
+		       ": Can't allocate PCI controller structure for %s\n",
+		       pcictrl->full_name);
+		return;
+	}
+
+	hose->arch_data = of_node_get(pcictrl);
+	hose->first_busno = bus_range[0];
+	hose->last_busno = bus_range[1];
+	hose->ops = &rtas_pci_ops;
+
+	pci_process_bridge_OF_ranges(hose, pcictrl, 0);
+}
+
+#else
+void __init efika_pcisetup(void)
+{}
+#endif
+
+
+
+/* ------------------------------------------------------------------------ */
+/* Platform setup                                                           */
+/* ------------------------------------------------------------------------ */
+
+static void efika_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	const char *revision = NULL;
+	const char *codegendescription = NULL;
+	const char *codegenvendor = NULL;
+
+	root = of_find_node_by_path("/");
+	if (!root)
+		return;
+
+	revision = get_property(root, "revision", NULL);
+	codegendescription =
+		    get_property(root, "CODEGEN,description", NULL);
+	codegenvendor = get_property(root, "CODEGEN,vendor", NULL);
+
+	if (codegendescription)
+		seq_printf(m, "machine\t\t: %s\n", codegendescription);
+	else
+		seq_printf(m, "machine\t\t: Efika\n");
+
+	if (revision)
+		seq_printf(m, "revision\t: %s\n", revision);
+
+	if (codegenvendor)
+		seq_printf(m, "vendor\t\t: %s\n", codegenvendor);
+
+	of_node_put(root);
+}
+
+static void __init efika_setup_arch(void)
+{
+	rtas_initialize();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	initrd_below_start_ok = 1;
+
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+		ROOT_DEV = Root_SDA2;	/* sda2 (sda1 is for the kernel) */
+
+	efika_pcisetup();
+
+	if (ppc_md.progress)
+		ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0);
+}
+
+static int __init efika_probe(void)
+{
+	char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
+					  "model", NULL);
+
+	if (model == NULL)
+		return 0;
+	if (strcmp(model, "EFIKA5K2"))
+		return 0;
+
+	ISA_DMA_THRESHOLD = ~0L;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	return 1;
+}
+
+define_machine(efika)
+{
+	.name			= EFIKA_PLATFORM_NAME,
+	.probe			= efika_probe,
+	.setup_arch		= efika_setup_arch,
+	.init			= mpc52xx_declare_of_platform_devices,
+	.show_cpuinfo		= efika_show_cpuinfo,
+	.init_IRQ		= mpc52xx_init_irq,
+	.get_irq		= mpc52xx_get_irq,
+	.restart		= rtas_restart,
+	.power_off		= rtas_power_off,
+	.halt			= rtas_halt,
+	.set_rtc_time		= rtas_set_rtc_time,
+	.get_rtc_time		= rtas_get_rtc_time,
+	.progress		= rtas_progress,
+	.get_boot_time		= rtas_get_boot_time,
+	.calibrate_decr		= generic_calibrate_decr,
+	.phys_mem_access_prot	= pci_phys_mem_access_prot,
+};
+
diff --git a/arch/powerpc/platforms/52xx/efika.h b/arch/powerpc/platforms/52xx/efika.h
deleted file mode 100644
index 2f060fd..0000000
--- a/arch/powerpc/platforms/52xx/efika.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Efika 5K2 platform setup - Header file
- *
- * Copyright (C) 2006 bplan GmbH
- *
- * 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.
- *
- */
-
-#ifndef __ARCH_POWERPC_EFIKA__
-#define __ARCH_POWERPC_EFIKA__
-
-#define EFIKA_PLATFORM_NAME "Efika"
-
-extern void __init efika_pcisetup(void);
-
-#endif
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index cdb16bf..cc3b40d 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -51,13 +51,13 @@
  */
 
 static void __init
-lite52xx_setup_cpu(void)
+lite5200_setup_cpu(void)
 {
 	struct mpc52xx_gpio __iomem *gpio;
 	u32 port_config;
 
 	/* Map zones */
-	gpio = mpc52xx_find_and_map("mpc52xx-gpio");
+	gpio = mpc52xx_find_and_map("mpc5200-gpio");
 	if (!gpio) {
 		printk(KERN_ERR __FILE__ ": "
 			"Error while mapping GPIO register for port config. "
@@ -85,12 +85,12 @@
 	iounmap(gpio);
 }
 
-static void __init lite52xx_setup_arch(void)
+static void __init lite5200_setup_arch(void)
 {
 	struct device_node *np;
 
 	if (ppc_md.progress)
-		ppc_md.progress("lite52xx_setup_arch()", 0);
+		ppc_md.progress("lite5200_setup_arch()", 0);
 
 	np = of_find_node_by_type(NULL, "cpu");
 	if (np) {
@@ -105,7 +105,7 @@
 
 	/* CPU & Port mux setup */
 	mpc52xx_setup_cpu();	/* Generic */
-	lite52xx_setup_cpu();	/* Platorm specific */
+	lite5200_setup_cpu();	/* Platorm specific */
 
 #ifdef CONFIG_PCI
 	np = of_find_node_by_type(np, "pci");
@@ -126,7 +126,7 @@
 
 }
 
-void lite52xx_show_cpuinfo(struct seq_file *m)
+void lite5200_show_cpuinfo(struct seq_file *m)
 {
 	struct device_node* np = of_find_all_nodes(NULL);
 	const char *model = NULL;
@@ -143,25 +143,26 @@
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
-static int __init lite52xx_probe(void)
+static int __init lite5200_probe(void)
 {
 	unsigned long node = of_get_flat_dt_root();
 	const char *model = of_get_flat_dt_prop(node, "model", NULL);
 
-	if (!of_flat_dt_is_compatible(node, "lite52xx"))
+	if (!of_flat_dt_is_compatible(node, "fsl,lite5200") &&
+	    !of_flat_dt_is_compatible(node, "fsl,lite5200b"))
 		return 0;
-	pr_debug("%s board w/ mpc52xx found\n", model ? model : "unknown");
+	pr_debug("%s board found\n", model ? model : "unknown");
 
 	return 1;
 }
 
-define_machine(lite52xx) {
-	.name 		= "lite52xx",
-	.probe 		= lite52xx_probe,
-	.setup_arch 	= lite52xx_setup_arch,
+define_machine(lite5200) {
+	.name 		= "lite5200",
+	.probe 		= lite5200_probe,
+	.setup_arch 	= lite5200_setup_arch,
 	.init		= mpc52xx_declare_of_platform_devices,
 	.init_IRQ 	= mpc52xx_init_irq,
 	.get_irq 	= mpc52xx_get_irq,
-	.show_cpuinfo	= lite52xx_show_cpuinfo,
+	.show_cpuinfo	= lite5200_show_cpuinfo,
 	.calibrate_decr	= generic_calibrate_decr,
 };
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index cc40889..ed0cb69 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -83,8 +83,8 @@
 	struct mpc52xx_xlb  __iomem *xlb;
 
 	/* Map zones */
-	cdm = mpc52xx_find_and_map("mpc52xx-cdm");
-	xlb = mpc52xx_find_and_map("mpc52xx-xlb");
+	cdm = mpc52xx_find_and_map("mpc5200-cdm");
+	xlb = mpc52xx_find_and_map("mpc5200-xlb");
 
 	if (!cdm || !xlb) {
 		printk(KERN_ERR __FILE__ ": "
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index cd91a6c..c751925 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -383,16 +383,16 @@
 	struct device_node *picnode;
 
 	/* Remap the necessary zones */
-	picnode = of_find_compatible_node(NULL, NULL, "mpc52xx-pic");
+	picnode = of_find_compatible_node(NULL, NULL, "mpc5200-pic");
 
-	intr = mpc52xx_find_and_map("mpc52xx-pic");
+	intr = mpc52xx_find_and_map("mpc5200-pic");
 	if (!intr)
-		panic(__FILE__	": find_and_map failed on 'mpc52xx-pic'. "
+		panic(__FILE__	": find_and_map failed on 'mpc5200-pic'. "
 				"Check node !");
 
-	sdma = mpc52xx_find_and_map("mpc52xx-bestcomm");
+	sdma = mpc52xx_find_and_map("mpc5200-bestcomm");
 	if (!sdma)
-		panic(__FILE__	": find_and_map failed on 'mpc52xx-bestcomm'. "
+		panic(__FILE__	": find_and_map failed on 'mpc5200-bestcomm'. "
 				"Check node !");
 
 	/* Disable all interrupt sources. */
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index edcd5b8..713b31a 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -3,7 +3,13 @@
 
 choice
 	prompt "Machine Type"
-	default MPC834x_SYS
+	default MPC834x_MDS
+
+config MPC8313_RDB
+	bool "Freescale MPC8313 RDB"
+	select DEFAULT_UIMAGE
+	help
+	  This option enables support for the MPC8313 RDB board.
 
 config MPC832x_MDS
 	bool "Freescale MPC832x MDS"
@@ -12,13 +18,13 @@
 	help
 	  This option enables support for the MPC832x MDS evaluation board.
 
-config MPC834x_SYS
-	bool "Freescale MPC834x SYS"
+config MPC834x_MDS
+	bool "Freescale MPC834x MDS"
 	select DEFAULT_UIMAGE
 	help
-	  This option enables support for the MPC 834x SYS evaluation board.
+	  This option enables support for the MPC 834x MDS evaluation board.
 
-	  Be aware that PCI buses can only function when SYS board is plugged
+	  Be aware that PCI buses can only function when MDS board is plugged
 	  into the PIB (Platform IO Board) board from Freescale which provide
 	  3 PCI slots.  The PIBs PCI initialization is the bootloader's
 	  responsibility.
@@ -32,15 +38,21 @@
 	  Be aware that PCI initialization is the bootloader's
 	  responsibility.
 
-config MPC8360E_PB
-	bool "Freescale MPC8360E PB"
+config MPC836x_MDS
+	bool "Freescale MPC836x MDS"
 	select DEFAULT_UIMAGE
 	select QUICC_ENGINE
 	help
-	  This option enables support for the MPC836x EMDS Processor Board.
+	  This option enables support for the MPC836x MDS Processor Board.
 
 endchoice
 
+config PPC_MPC831x
+	bool
+	select PPC_UDBG_16550
+	select PPC_INDIRECT_PCI
+	default y if MPC8313_RDB
+
 config PPC_MPC832x
 	bool
 	select PPC_UDBG_16550
@@ -51,12 +63,12 @@
 	bool
 	select PPC_UDBG_16550
 	select PPC_INDIRECT_PCI
-	default y if MPC834x_SYS || MPC834x_ITX
+	default y if MPC834x_MDS || MPC834x_ITX
 
 config PPC_MPC836x
 	bool
 	select PPC_UDBG_16550
 	select PPC_INDIRECT_PCI
-	default y if MPC8360E_PB
+	default y if MPC836x_MDS
 
 endmenu
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index f1aa7e2..dfc970d 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -3,7 +3,8 @@
 #
 obj-y				:= misc.o
 obj-$(CONFIG_PCI)		+= pci.o
-obj-$(CONFIG_MPC834x_SYS)	+= mpc834x_sys.o
+obj-$(CONFIG_MPC8313_RDB)	+= mpc8313_rdb.o
+obj-$(CONFIG_MPC834x_MDS)	+= mpc834x_mds.o
 obj-$(CONFIG_MPC834x_ITX)	+= mpc834x_itx.o
-obj-$(CONFIG_MPC8360E_PB)	+= mpc8360e_pb.o
+obj-$(CONFIG_MPC836x_MDS)	+= mpc836x_mds.o
 obj-$(CONFIG_MPC832x_MDS)	+= mpc832x_mds.o
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
new file mode 100644
index 0000000..32e9e94
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -0,0 +1,92 @@
+/*
+ * arch/powerpc/platforms/83xx/mpc8313_rdb.c
+ *
+ * Description: MPC8313x RDB board specific routines.
+ * This file is based on mpc834x_sys.c
+ * Author: Lo Wlison <r43300@freescale.com>
+ *
+ * Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/pci.h>
+
+#include <asm/time.h>
+#include <asm/ipic.h>
+#include <asm/udbg.h>
+
+#include "mpc83xx.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc8313_rdb_setup_arch(void)
+{
+	struct device_node *np;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc8313_rdb_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+		add_bridge(np);
+
+	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+#endif
+}
+
+void __init mpc8313_rdb_init_IRQ(void)
+{
+	struct device_node *np;
+
+	np = of_find_node_by_type(NULL, "ipic");
+	if (!np)
+		return;
+
+	ipic_init(np, 0);
+
+	/* Initialize the default interrupt mapping priorities,
+	 * in case the boot rom changed something on us.
+	 */
+	ipic_set_default_priority();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc8313_rdb_probe(void)
+{
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC8313ERDB");
+}
+
+define_machine(mpc8313_rdb) {
+	.name			= "MPC8313 RDB",
+	.probe			= mpc8313_rdb_probe,
+	.setup_arch		= mpc8313_rdb_setup_arch,
+	.init_IRQ		= mpc8313_rdb_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/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 3ecb55f..17e3a3c 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -57,11 +57,6 @@
 
 static u8 *bcsr_regs = NULL;
 
-u8 *get_bcsr(void)
-{
-	return bcsr_regs;
-}
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -74,17 +69,6 @@
 	if (ppc_md.progress)
 		ppc_md.progress("mpc832x_sys_setup_arch()", 0);
 
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np != 0) {
-		unsigned int *fp =
-		    (int *)get_property(np, "clock-frequency", NULL);
-		if (fp != 0)
-			loops_per_jiffy = *fp / HZ;
-		else
-			loops_per_jiffy = 50000000 / HZ;
-		of_node_put(np);
-	}
-
 	/* Map BCSR area */
 	np = of_find_node_by_name(NULL, "bcsr");
 	if (np != 0) {
@@ -121,34 +105,23 @@
 		iounmap(bcsr_regs);
 		of_node_put(np);
 	}
-
 #endif				/* CONFIG_QUICC_ENGINE */
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
-		ROOT_DEV = Root_RAM0;
-	else
-#endif
-#ifdef  CONFIG_ROOT_NFS
-		ROOT_DEV = Root_NFS;
-#else
-		ROOT_DEV = Root_HDA1;
-#endif
 }
 
+static struct of_device_id mpc832x_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{ .type = "qe", },
+	{},
+};
+
 static int __init mpc832x_declare_of_platform_devices(void)
 {
-	struct device_node *np;
+	if (!machine_is(mpc832x_mds))
+		return 0;
 
-	for (np = NULL; (np = of_find_compatible_node(np, "network",
-					"ucc_geth")) != NULL;) {
-		int ucc_num;
-		char bus_id[BUS_ID_SIZE];
-
-		ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1;
-		snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num);
-		of_platform_device_create(np, bus_id, NULL);
-	}
+	/* Publish the QE devices */
+	of_platform_bus_probe(NULL, mpc832x_ids, NULL);
 
 	return 0;
 }
@@ -156,7 +129,6 @@
 
 static void __init mpc832x_sys_init_IRQ(void)
 {
-
 	struct device_node *np;
 
 	np = of_find_node_by_type(NULL, "ipic");
@@ -189,6 +161,9 @@
 {
 	struct timespec tv;
 
+	if (!machine_is(mpc832x_mds))
+		return 0;
+
 	ppc_md.get_rtc_time = ds1374_get_rtc_time;
 	ppc_md.set_rtc_time = ds1374_set_rtc_time;
 
@@ -207,17 +182,9 @@
  */
 static int __init mpc832x_sys_probe(void)
 {
-	char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
-					  "model", NULL);
+        unsigned long root = of_get_flat_dt_root();
 
-	if (model == NULL)
-		return 0;
-	if (strcmp(model, "MPC8323EMDS"))
-		return 0;
-
-	DBG("%s found\n", model);
-
-	return 1;
+        return of_flat_dt_is_compatible(root, "MPC832xMDS");
 }
 
 define_machine(mpc832x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 2446dea..3c009f6 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -38,8 +38,6 @@
 
 #include "mpc83xx.h"
 
-#include <platforms/83xx/mpc834x_sys.h>
-
 #ifndef CONFIG_PCI
 unsigned long isa_io_base = 0;
 unsigned long isa_mem_base = 0;
@@ -57,28 +55,12 @@
 	if (ppc_md.progress)
 		ppc_md.progress("mpc834x_itx_setup_arch()", 0);
 
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np != 0) {
-		const unsigned int *fp =
-			get_property(np, "clock-frequency", NULL);
-		if (fp != 0)
-			loops_per_jiffy = *fp / HZ;
-		else
-			loops_per_jiffy = 50000000 / HZ;
-		of_node_put(np);
-	}
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
 		add_bridge(np);
 
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
-
-#ifdef  CONFIG_ROOT_NFS
-	ROOT_DEV = Root_NFS;
-#else
-	ROOT_DEV = Root_HDA1;
-#endif
 }
 
 static void __init mpc834x_itx_init_IRQ(void)
@@ -102,10 +84,9 @@
  */
 static int __init mpc834x_itx_probe(void)
 {
-	/* 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;
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC834xMITX");
 }
 
 define_machine(mpc834x_itx) {
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
new file mode 100644
index 0000000..e5d8191
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -0,0 +1,198 @@
+/*
+ * arch/powerpc/platforms/83xx/mpc834x_mds.c
+ *
+ * MPC834x MDS board specific routines
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc83xx.h"
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+#define BCSR5_INT_USB		0x02
+/* Note: This is only for PB, not for PB+PIB
+ * On PB only port0 is connected using ULPI */
+static int mpc834x_usb_cfg(void)
+{
+	unsigned long sccr, sicrl;
+	void __iomem *immap;
+	void __iomem *bcsr_regs = NULL;
+	u8 bcsr5;
+	struct device_node *np = NULL;
+	int port0_is_dr = 0;
+
+	if ((np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL)
+		port0_is_dr = 1;
+	if ((np = of_find_compatible_node(np, "usb", "fsl-usb2-mph")) != NULL){
+		if (port0_is_dr) {
+			printk(KERN_WARNING
+				"There is only one USB port on PB board! \n");
+			return -1;
+		} else if (!port0_is_dr)
+			/* No usb port enabled */
+			return -1;
+	}
+
+	immap = ioremap(get_immrbase(), 0x1000);
+	if (!immap)
+		return -1;
+
+	/* Configure clock */
+	sccr = in_be32(immap + MPC83XX_SCCR_OFFS);
+	if (port0_is_dr)
+		sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
+	else
+		sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
+	out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
+
+	/* Configure Pin */
+	sicrl = in_be32(immap + MPC83XX_SICRL_OFFS);
+	/* set port0 only */
+	if (port0_is_dr)
+		sicrl |= MPC83XX_SICRL_USB0;
+	else
+		sicrl &= ~(MPC83XX_SICRL_USB0);
+	out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
+
+	iounmap(immap);
+
+	/* Map BCSR area */
+	np = of_find_node_by_name(NULL, "bcsr");
+	if (np != 0) {
+		struct resource res;
+
+		of_address_to_resource(np, 0, &res);
+		bcsr_regs = ioremap(res.start, res.end - res.start + 1);
+		of_node_put(np);
+	}
+	if (!bcsr_regs)
+		return -1;
+
+	/*
+	 * if MDS board is plug into PIB board,
+	 * force to use the PHY on MDS board
+	 */
+	bcsr5 = in_8(bcsr_regs + 5);
+	if (!(bcsr5 & BCSR5_INT_USB))
+		out_8(bcsr_regs + 5, (bcsr5 | BCSR5_INT_USB));
+	iounmap(bcsr_regs);
+	return 0;
+}
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc834x_mds_setup_arch(void)
+{
+	struct device_node *np;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc834x_mds_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+		add_bridge(np);
+
+	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+#endif
+
+	mpc834x_usb_cfg();
+}
+
+static void __init mpc834x_mds_init_IRQ(void)
+{
+	struct device_node *np;
+
+	np = of_find_node_by_type(NULL, "ipic");
+	if (!np)
+		return;
+
+	ipic_init(np, 0);
+
+	/* Initialize the default interrupt mapping priorities,
+	 * in case the boot rom changed something on us.
+	 */
+	ipic_set_default_priority();
+}
+
+#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
+extern ulong ds1374_get_rtc_time(void);
+extern int ds1374_set_rtc_time(ulong);
+
+static int __init mpc834x_rtc_hookup(void)
+{
+	struct timespec tv;
+
+	if (!machine_is(mpc834x_mds))
+		return 0;
+
+	ppc_md.get_rtc_time = ds1374_get_rtc_time;
+	ppc_md.set_rtc_time = ds1374_set_rtc_time;
+
+	tv.tv_nsec = 0;
+	tv.tv_sec = (ppc_md.get_rtc_time) ();
+	do_settimeofday(&tv);
+
+	return 0;
+}
+
+late_initcall(mpc834x_rtc_hookup);
+#endif
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc834x_mds_probe(void)
+{
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC834xMDS");
+}
+
+define_machine(mpc834x_mds) {
+	.name			= "MPC834x MDS",
+	.probe			= mpc834x_mds_probe,
+	.setup_arch		= mpc834x_mds_setup_arch,
+	.init_IRQ		= mpc834x_mds_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/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
deleted file mode 100644
index f30393f..0000000
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * arch/powerpc/platforms/83xx/mpc834x_sys.c
- *
- * MPC834x SYS board specific routines
- *
- * Maintainer: Kumar Gala <galak@kernel.crashing.org>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/system.h>
-#include <asm/atomic.h>
-#include <asm/time.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/ipic.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <sysdev/fsl_soc.h>
-
-#include "mpc83xx.h"
-
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
-/* ************************************************************************
- *
- * Setup the architecture
- *
- */
-static void __init mpc834x_sys_setup_arch(void)
-{
-	struct device_node *np;
-
-	if (ppc_md.progress)
-		ppc_md.progress("mpc834x_sys_setup_arch()", 0);
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np != 0) {
-		const unsigned int *fp =
-			get_property(np, "clock-frequency", NULL);
-		if (fp != 0)
-			loops_per_jiffy = *fp / HZ;
-		else
-			loops_per_jiffy = 50000000 / HZ;
-		of_node_put(np);
-	}
-#ifdef CONFIG_PCI
-	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
-
-	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
-#endif
-
-#ifdef  CONFIG_ROOT_NFS
-	ROOT_DEV = Root_NFS;
-#else
-	ROOT_DEV = Root_HDA1;
-#endif
-}
-
-static void __init mpc834x_sys_init_IRQ(void)
-{
-	struct device_node *np;
-
-	np = of_find_node_by_type(NULL, "ipic");
-	if (!np)
-		return;
-
-	ipic_init(np, 0);
-
-	/* Initialize the default interrupt mapping priorities,
-	 * in case the boot rom changed something on us.
-	 */
-	ipic_set_default_priority();
-}
-
-#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
-extern ulong ds1374_get_rtc_time(void);
-extern int ds1374_set_rtc_time(ulong);
-
-static int __init mpc834x_rtc_hookup(void)
-{
-	struct timespec tv;
-
-	ppc_md.get_rtc_time = ds1374_get_rtc_time;
-	ppc_md.set_rtc_time = ds1374_set_rtc_time;
-
-	tv.tv_nsec = 0;
-	tv.tv_sec = (ppc_md.get_rtc_time) ();
-	do_settimeofday(&tv);
-
-	return 0;
-}
-
-late_initcall(mpc834x_rtc_hookup);
-#endif
-
-/*
- * Called very early, MMU is off, device-tree isn't unflattened
- */
-static int __init mpc834x_sys_probe(void)
-{
-	/* 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/83xx/mpc834x_sys.h b/arch/powerpc/platforms/83xx/mpc834x_sys.h
deleted file mode 100644
index 7d5bbef..0000000
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * arch/powerpc/platforms/83xx/mpc834x_sys.h
- *
- * MPC834X SYS common board definitions
- *
- * Maintainer: Kumar Gala <galak@kernel.crashing.org>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-#ifndef __MACH_MPC83XX_SYS_H__
-#define __MACH_MPC83XX_SYS_H__
-
-#define PIRQA	MPC83xx_IRQ_EXT4
-#define PIRQB	MPC83xx_IRQ_EXT5
-#define PIRQC	MPC83xx_IRQ_EXT6
-#define PIRQD	MPC83xx_IRQ_EXT7
-
-#endif				/* __MACH_MPC83XX_SYS_H__ */
diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
deleted file mode 100644
index ccce2f9..0000000
--- a/arch/powerpc/platforms/83xx/mpc8360e_pb.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
- *
- * Author: Li Yang <LeoLi@freescale.com>
- *	   Yin Olivia <Hong-hua.Yin@freescale.com>
- *
- * Description:
- * MPC8360E MDS PB board specific routines.
- *
- * Changelog:
- * Jun 21, 2006	Initial version
- *
- * 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/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-#include <linux/initrd.h>
-
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
-#include <asm/system.h>
-#include <asm/atomic.h>
-#include <asm/time.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/ipic.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <sysdev/fsl_soc.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
-
-#include "mpc83xx.h"
-
-#undef DEBUG
-#ifdef DEBUG
-#define DBG(fmt...) udbg_printf(fmt)
-#else
-#define DBG(fmt...)
-#endif
-
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
-static u8 *bcsr_regs = NULL;
-
-u8 *get_bcsr(void)
-{
-	return bcsr_regs;
-}
-
-/* ************************************************************************
- *
- * Setup the architecture
- *
- */
-static void __init mpc8360_sys_setup_arch(void)
-{
-	struct device_node *np;
-
-	if (ppc_md.progress)
-		ppc_md.progress("mpc8360_sys_setup_arch()", 0);
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np != 0) {
-		const unsigned int *fp =
-		    get_property(np, "clock-frequency", NULL);
-		if (fp != 0)
-			loops_per_jiffy = *fp / HZ;
-		else
-			loops_per_jiffy = 50000000 / HZ;
-		of_node_put(np);
-	}
-
-	/* Map BCSR area */
-	np = of_find_node_by_name(NULL, "bcsr");
-	if (np != 0) {
-		struct resource res;
-
-		of_address_to_resource(np, 0, &res);
-		bcsr_regs = ioremap(res.start, res.end - res.start +1);
-		of_node_put(np);
-	}
-
-#ifdef CONFIG_PCI
-	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-		add_bridge(np);
-	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
-#endif
-
-#ifdef CONFIG_QUICC_ENGINE
-	qe_reset();
-
-	if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
-		par_io_init(np);
-		of_node_put(np);
-
-		for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
-			par_io_of_config(np);
-	}
-
-	if ((np = of_find_compatible_node(NULL, "network", "ucc_geth"))
-			!= NULL){
-		/* Reset the Ethernet PHY */
-		bcsr_regs[9] &= ~0x20;
-		udelay(1000);
-		bcsr_regs[9] |= 0x20;
-		iounmap(bcsr_regs);
-		of_node_put(np);
-	}
-
-#endif				/* CONFIG_QUICC_ENGINE */
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
-		ROOT_DEV = Root_RAM0;
-	else
-#endif
-#ifdef  CONFIG_ROOT_NFS
-		ROOT_DEV = Root_NFS;
-#else
-		ROOT_DEV = Root_HDA1;
-#endif
-}
-
-static int __init mpc8360_declare_of_platform_devices(void)
-{
-	struct device_node *np;
-
-	for (np = NULL; (np = of_find_compatible_node(np, "network",
-					"ucc_geth")) != NULL;) {
-		int ucc_num;
-		char bus_id[BUS_ID_SIZE];
-
-		ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1;
-		snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num);
-		of_platform_device_create(np, bus_id, NULL);
-	}
-
-	return 0;
-}
-device_initcall(mpc8360_declare_of_platform_devices);
-
-static void __init mpc8360_sys_init_IRQ(void)
-{
-
-	struct device_node *np;
-
-	np = of_find_node_by_type(NULL, "ipic");
-	if (!np)
-		return;
-
-	ipic_init(np, 0);
-
-	/* Initialize the default interrupt mapping priorities,
-	 * in case the boot rom changed something on us.
-	 */
-	ipic_set_default_priority();
-	of_node_put(np);
-
-#ifdef CONFIG_QUICC_ENGINE
-	np = of_find_node_by_type(NULL, "qeic");
-	if (!np)
-		return;
-
-	qe_ic_init(np, 0);
-	of_node_put(np);
-#endif				/* CONFIG_QUICC_ENGINE */
-}
-
-#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
-extern ulong ds1374_get_rtc_time(void);
-extern int ds1374_set_rtc_time(ulong);
-
-static int __init mpc8360_rtc_hookup(void)
-{
-	struct timespec tv;
-
-	ppc_md.get_rtc_time = ds1374_get_rtc_time;
-	ppc_md.set_rtc_time = ds1374_set_rtc_time;
-
-	tv.tv_nsec = 0;
-	tv.tv_sec = (ppc_md.get_rtc_time) ();
-	do_settimeofday(&tv);
-
-	return 0;
-}
-
-late_initcall(mpc8360_rtc_hookup);
-#endif
-
-/*
- * Called very early, MMU is off, device-tree isn't unflattened
- */
-static int __init mpc8360_sys_probe(void)
-{
-	char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
-					  "model", NULL);
-	if (model == NULL)
-		return 0;
-	if (strcmp(model, "MPC8360EPB"))
-		return 0;
-
-	DBG("MPC8360EMDS-PB found\n");
-
-	return 1;
-}
-
-define_machine(mpc8360_sys) {
-	.name 		= "MPC8360E PB",
-	.probe 		= mpc8360_sys_probe,
-	.setup_arch 	= mpc8360_sys_setup_arch,
-	.init_IRQ 	= mpc8360_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/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
new file mode 100644
index 0000000..526ed09
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Li Yang <LeoLi@freescale.com>
+ *	   Yin Olivia <Hong-hua.Yin@freescale.com>
+ *
+ * Description:
+ * MPC8360E MDS board specific routines.
+ *
+ * Changelog:
+ * Jun 21, 2006	Initial version
+ *
+ * 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <sysdev/fsl_soc.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+
+#include "mpc83xx.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+static u8 *bcsr_regs = NULL;
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc836x_mds_setup_arch(void)
+{
+	struct device_node *np;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc836x_mds_setup_arch()", 0);
+
+	/* Map BCSR area */
+	np = of_find_node_by_name(NULL, "bcsr");
+	if (np != 0) {
+		struct resource res;
+
+		of_address_to_resource(np, 0, &res);
+		bcsr_regs = ioremap(res.start, res.end - res.start +1);
+		of_node_put(np);
+	}
+
+#ifdef CONFIG_PCI
+	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+		add_bridge(np);
+	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+#endif
+
+#ifdef CONFIG_QUICC_ENGINE
+	qe_reset();
+
+	if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
+		par_io_init(np);
+		of_node_put(np);
+
+		for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
+			par_io_of_config(np);
+	}
+
+	if ((np = of_find_compatible_node(NULL, "network", "ucc_geth"))
+			!= NULL){
+		/* Reset the Ethernet PHY */
+		bcsr_regs[9] &= ~0x20;
+		udelay(1000);
+		bcsr_regs[9] |= 0x20;
+		iounmap(bcsr_regs);
+		of_node_put(np);
+	}
+
+#endif				/* CONFIG_QUICC_ENGINE */
+}
+
+static struct of_device_id mpc836x_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{ .type = "qe", },
+	{},
+};
+
+static int __init mpc836x_declare_of_platform_devices(void)
+{
+	if (!machine_is(mpc836x_mds))
+		return 0;
+
+	/* Publish the QE devices */
+	of_platform_bus_probe(NULL, mpc836x_ids, NULL);
+
+	return 0;
+}
+device_initcall(mpc836x_declare_of_platform_devices);
+
+static void __init mpc836x_mds_init_IRQ(void)
+{
+	struct device_node *np;
+
+	np = of_find_node_by_type(NULL, "ipic");
+	if (!np)
+		return;
+
+	ipic_init(np, 0);
+
+	/* Initialize the default interrupt mapping priorities,
+	 * in case the boot rom changed something on us.
+	 */
+	ipic_set_default_priority();
+	of_node_put(np);
+
+#ifdef CONFIG_QUICC_ENGINE
+	np = of_find_node_by_type(NULL, "qeic");
+	if (!np)
+		return;
+
+	qe_ic_init(np, 0);
+	of_node_put(np);
+#endif				/* CONFIG_QUICC_ENGINE */
+}
+
+#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
+extern ulong ds1374_get_rtc_time(void);
+extern int ds1374_set_rtc_time(ulong);
+
+static int __init mpc8360_rtc_hookup(void)
+{
+	struct timespec tv;
+
+	if (!machine_is(mpc836x_mds))
+		return 0;
+
+	ppc_md.get_rtc_time = ds1374_get_rtc_time;
+	ppc_md.set_rtc_time = ds1374_set_rtc_time;
+
+	tv.tv_nsec = 0;
+	tv.tv_sec = (ppc_md.get_rtc_time) ();
+	do_settimeofday(&tv);
+
+	return 0;
+}
+
+late_initcall(mpc8360_rtc_hookup);
+#endif
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc836x_mds_probe(void)
+{
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC836xMDS");
+}
+
+define_machine(mpc836x_mds) {
+	.name		= "MPC836x MDS",
+	.probe		= mpc836x_mds_probe,
+	.setup_arch	= mpc836x_mds_setup_arch,
+	.init_IRQ	= mpc836x_mds_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/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 01cae10..9cd03b5 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -4,6 +4,24 @@
 #include <linux/init.h>
 #include <linux/device.h>
 
+/* System Clock Control Register */
+#define MPC83XX_SCCR_OFFS          0xA08
+#define MPC83XX_SCCR_USB_MPHCM_11  0x00c00000
+#define MPC83XX_SCCR_USB_MPHCM_01  0x00400000
+#define MPC83XX_SCCR_USB_MPHCM_10  0x00800000
+#define MPC83XX_SCCR_USB_DRCM_11   0x00300000
+#define MPC83XX_SCCR_USB_DRCM_01   0x00100000
+#define MPC83XX_SCCR_USB_DRCM_10   0x00200000
+
+/* system i/o configuration register low */
+#define MPC83XX_SICRL_OFFS         0x114
+#define MPC83XX_SICRL_USB0         0x40000000
+#define MPC83XX_SICRL_USB1         0x20000000
+
+/* system i/o configuration register high */
+#define MPC83XX_SICRH_OFFS         0x118
+#define MPC83XX_SICRH_USB_UTMI     0x00020000
+
 /*
  * Declaration for the various functions exported by the
  * mpc83xx_* files. Mostly for use by mpc83xx_setup
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 0584f3c..eb661cc 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -23,6 +23,13 @@
 	help
 	  This option enables support for the MPC85xx CDS board
 
+config MPC85xx_MDS
+	bool "Freescale MPC85xx MDS"
+	select DEFAULT_UIMAGE
+#	select QUICC_ENGINE
+	help
+	  This option enables support for the MPC85xx MDS board
+
 endchoice
 
 config MPC8540
@@ -36,6 +43,12 @@
 	select PPC_INDIRECT_PCI
 	default y if MPC8560_ADS
 
+config MPC85xx
+	bool
+	select PPC_UDBG_16550
+	select PPC_INDIRECT_PCI
+	default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS || MPC85xx_MDS
+
 config PPC_INDIRECT_PCI_BE
 	bool
 	depends on PPC_85xx
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 282f5d0..4e63917 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
+obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index bda2e55..8ed034a 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -17,7 +17,6 @@
 #include <linux/kdev_t.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
-#include <linux/root_dev.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
@@ -45,8 +44,7 @@
 #endif
 
 #ifdef CONFIG_PCI
-int
-mpc85xx_exclude_device(u_char bus, u_char devfn)
+static int mpc85xx_exclude_device(u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -69,7 +67,7 @@
 
 #endif /* CONFIG_CPM2 */
 
-void __init mpc85xx_ads_pic_init(void)
+static void __init mpc85xx_ads_pic_init(void)
 {
 	struct mpic *mpic;
 	struct resource r;
@@ -246,15 +244,9 @@
 		add_bridge(np);
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
-
-#ifdef  CONFIG_ROOT_NFS
-	ROOT_DEV = Root_NFS;
-#else
-	ROOT_DEV = Root_HDA1;
-#endif
 }
 
-void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
+static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
 {
 	uint pvid, svid, phid1;
 	uint memsize = total_memory;
@@ -280,10 +272,9 @@
  */
 static int __init mpc85xx_ads_probe(void)
 {
-	/* 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;
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC85xxADS");
 }
 
 define_machine(mpc85xx_ads) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 953cd5d..4232686 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -22,7 +22,6 @@
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
-#include <linux/root_dev.h>
 #include <linux/initrd.h>
 #include <linux/module.h>
 #include <linux/fsl_devices.h>
@@ -56,7 +55,6 @@
 static int cds_pci_slot = 2;
 static volatile u8 *cadmus;
 
-
 #ifdef CONFIG_PCI
 
 #define ARCADIA_HOST_BRIDGE_IDSEL	17
@@ -64,8 +62,7 @@
 
 extern int mpc85xx_pci2_busno;
 
-int
-mpc85xx_exclude_device(u_char bus, u_char devfn)
+static int mpc85xx_exclude_device(u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -81,8 +78,7 @@
 		return PCIBIOS_SUCCESSFUL;
 }
 
-void __init
-mpc85xx_cds_pcibios_fixup(void)
+static void __init mpc85xx_cds_pcibios_fixup(void)
 {
 	struct pci_dev *dev;
 	u_char		c;
@@ -144,7 +140,7 @@
 #endif /* PPC_I8259 */
 #endif /* CONFIG_PCI */
 
-void __init mpc85xx_cds_pic_init(void)
+static void __init mpc85xx_cds_pic_init(void)
 {
 	struct mpic *mpic;
 	struct resource r;
@@ -224,12 +220,10 @@
 #endif /* CONFIG_PPC_I8259 */
 }
 
-
 /*
  * Setup the architecture
  */
-static void __init
-mpc85xx_cds_setup_arch(void)
+static void __init mpc85xx_cds_setup_arch(void)
 {
 	struct device_node *cpu;
 #ifdef CONFIG_PCI
@@ -268,17 +262,9 @@
 	ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
-
-#ifdef  CONFIG_ROOT_NFS
-	ROOT_DEV = Root_NFS;
-#else
-	ROOT_DEV = Root_HDA1;
-#endif
 }
 
-
-void
-mpc85xx_cds_show_cpuinfo(struct seq_file *m)
+static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
 {
 	uint pvid, svid, phid1;
 	uint memsize = total_memory;
@@ -305,11 +291,9 @@
  */
 static int __init mpc85xx_cds_probe(void)
 {
-	/* We always match for now, eventually we should look at
-	 * the flat dev tree to ensure this is the board we are
-	 * supposed to run on
-	 */
-	return 1;
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC85xxCDS");
 }
 
 define_machine(mpc85xx_cds) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
new file mode 100644
index 0000000..81144d2
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006-2007. All rights reserved.
+ *
+ * Author: Andy Fleming <afleming@freescale.com>
+ *
+ * Based on 83xx/mpc8360e_pb.c by:
+ *	   Li Yang <LeoLi@freescale.com>
+ *	   Yin Olivia <Hong-hua.Yin@freescale.com>
+ *
+ * Description:
+ * MPC85xx MDS board specific routines.
+ *
+ * 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <sysdev/fsl_soc.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+#include <asm/mpic.h>
+
+#include "mpc85xx.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc85xx_mds_setup_arch(void)
+{
+	struct device_node *np;
+	static u8 *bcsr_regs = NULL;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
+
+	np = of_find_node_by_type(NULL, "cpu");
+	if (np != NULL) {
+		const unsigned int *fp =
+		    get_property(np, "clock-frequency", NULL);
+		if (fp != NULL)
+			loops_per_jiffy = *fp / HZ;
+		else
+			loops_per_jiffy = 50000000 / HZ;
+		of_node_put(np);
+	}
+
+	/* Map BCSR area */
+	np = of_find_node_by_name(NULL, "bcsr");
+	if (np != NULL) {
+		struct resource res;
+
+		of_address_to_resource(np, 0, &res);
+		bcsr_regs = ioremap(res.start, res.end - res.start +1);
+		of_node_put(np);
+	}
+
+#ifdef CONFIG_PCI
+	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) {
+		add_bridge(np);
+	}
+	of_node_put(np);
+#endif
+
+#ifdef CONFIG_QUICC_ENGINE
+	if ((np = of_find_node_by_name(NULL, "qe")) != NULL) {
+		qe_reset();
+		of_node_put(np);
+	}
+
+	if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
+		struct device_node *ucc = NULL;
+
+		par_io_init(np);
+		of_node_put(np);
+
+		for ( ;(ucc = of_find_node_by_name(ucc, "ucc")) != NULL;)
+			par_io_of_config(ucc);
+
+		of_node_put(ucc);
+	}
+
+	if (bcsr_regs) {
+		u8 bcsr_phy;
+
+		/* Reset the Ethernet PHY */
+		bcsr_phy = in_be8(&bcsr_regs[9]);
+		bcsr_phy &= ~0x20;
+		out_be8(&bcsr_regs[9], bcsr_phy);
+
+		udelay(1000);
+
+		bcsr_phy = in_be8(&bcsr_regs[9]);
+		bcsr_phy |= 0x20;
+		out_be8(&bcsr_regs[9], bcsr_phy);
+
+		iounmap(bcsr_regs);
+	}
+
+#endif	/* CONFIG_QUICC_ENGINE */
+}
+
+static struct of_device_id mpc85xx_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{ .type = "qe", },
+	{},
+};
+
+static int __init mpc85xx_publish_devices(void)
+{
+	if (!machine_is(mpc85xx_mds))
+		return 0;
+
+	/* Publish the QE devices */
+	of_platform_bus_probe(NULL,mpc85xx_ids,NULL);
+
+	return 0;
+}
+device_initcall(mpc85xx_publish_devices);
+
+static void __init mpc85xx_mds_pic_init(void)
+{
+	struct mpic *mpic;
+	struct resource r;
+	struct device_node *np = NULL;
+
+	np = of_find_node_by_type(NULL, "open-pic");
+	if (!np)
+		return;
+
+	if (of_address_to_resource(np, 0, &r)) {
+		printk(KERN_ERR "Failed to map mpic register space\n");
+		of_node_put(np);
+		return;
+	}
+
+	mpic = mpic_alloc(np, r.start,
+			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+			4, 0, " OpenPIC  ");
+	BUG_ON(mpic == NULL);
+	of_node_put(np);
+
+	/* Internal Interrupts */
+	mpic_assign_isu(mpic, 0, r.start + 0x10200);
+	mpic_assign_isu(mpic, 1, r.start + 0x10280);
+	mpic_assign_isu(mpic, 2, r.start + 0x10300);
+	mpic_assign_isu(mpic, 3, r.start + 0x10380);
+	mpic_assign_isu(mpic, 4, r.start + 0x10400);
+	mpic_assign_isu(mpic, 5, r.start + 0x10480);
+	mpic_assign_isu(mpic, 6, r.start + 0x10500);
+	mpic_assign_isu(mpic, 7, r.start + 0x10580);
+	mpic_assign_isu(mpic, 8, r.start + 0x10600);
+	mpic_assign_isu(mpic, 9, r.start + 0x10680);
+	mpic_assign_isu(mpic, 10, r.start + 0x10700);
+	mpic_assign_isu(mpic, 11, r.start + 0x10780);
+
+	/* External Interrupts */
+	mpic_assign_isu(mpic, 12, r.start + 0x10000);
+	mpic_assign_isu(mpic, 13, r.start + 0x10080);
+	mpic_assign_isu(mpic, 14, r.start + 0x10100);
+
+	mpic_init(mpic);
+
+#ifdef CONFIG_QUICC_ENGINE
+	np = of_find_node_by_type(NULL, "qeic");
+	if (!np)
+		return;
+
+	qe_ic_init(np, 0);
+	of_node_put(np);
+#endif				/* CONFIG_QUICC_ENGINE */
+}
+
+static int __init mpc85xx_mds_probe(void)
+{
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "MPC85xxMDS");
+}
+
+define_machine(mpc85xx_mds) {
+	.name		= "MPC85xx MDS",
+	.probe		= mpc85xx_mds_probe,
+	.setup_arch	= mpc85xx_mds_setup_arch,
+	.init_IRQ	= mpc85xx_mds_pic_init,
+	.get_irq	= mpic_get_irq,
+	.restart	= mpc85xx_restart,
+	.calibrate_decr	= generic_calibrate_decr,
+	.progress	= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index f4dd5f2..f42f801 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -18,7 +18,6 @@
 #include <linux/kdev_t.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
-#include <linux/root_dev.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
@@ -120,6 +119,8 @@
 	DBG("mpc86xxhpcn: cascade mapped to irq %d\n", cascade_irq);
 
 	i8259_init(cascade_node, 0);
+	of_node_put(cascade_node);
+
 	set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
 #endif
 }
@@ -365,12 +366,6 @@
 
 	printk("MPC86xx HPCN board from Freescale Semiconductor\n");
 
-#ifdef  CONFIG_ROOT_NFS
-	ROOT_DEV = Root_NFS;
-#else
-	ROOT_DEV = Root_HDA1;
-#endif
-
 #ifdef CONFIG_SMP
 	mpc86xx_smp_init();
 #endif
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 65e6123..4520042 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -5,9 +5,9 @@
 obj-$(CONFIG_PPC_PMAC)		+= powermac/
 endif
 endif
-obj-$(CONFIG_PPC_MPC52xx)	+= 52xx/
 obj-$(CONFIG_PPC_CHRP)		+= chrp/
 obj-$(CONFIG_4xx)		+= 4xx/
+obj-$(CONFIG_PPC_MPC52xx)	+= 52xx/
 obj-$(CONFIG_PPC_8xx)		+= 8xx/
 obj-$(CONFIG_PPC_82xx)		+= 82xx/
 obj-$(CONFIG_PPC_83xx)		+= 83xx/
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index b43466b..67d617b 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -149,7 +149,8 @@
 static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte,
 		long n_ptes)
 {
-	unsigned long *reg, val;
+	unsigned long __iomem *reg;
+	unsigned long val;
 	long n;
 
 	reg = iommu->xlate_regs + IOC_IOPT_CacheInvd;
@@ -592,7 +593,7 @@
 	/* Init base fields */
 	i = cbe_nr_iommus++;
 	iommu = &iommus[i];
-	iommu->stab = 0;
+	iommu->stab = NULL;
 	iommu->nid = nid;
 	snprintf(iommu->name, sizeof(iommu->name), "iommu%d", i);
 	INIT_LIST_HEAD(&iommu->windows);
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
index d04ae16..66ca4b5 100644
--- a/arch/powerpc/platforms/cell/pmu.c
+++ b/arch/powerpc/platforms/cell/pmu.c
@@ -345,18 +345,12 @@
  * Enabling/disabling interrupts for the entire performance monitoring unit.
  */
 
-u32 cbe_query_pm_interrupts(u32 cpu)
-{
-	return cbe_read_pm(cpu, pm_status);
-}
-EXPORT_SYMBOL_GPL(cbe_query_pm_interrupts);
-
-u32 cbe_clear_pm_interrupts(u32 cpu)
+u32 cbe_get_and_clear_pm_interrupts(u32 cpu)
 {
 	/* Reading pm_status clears the interrupt bits. */
-	return cbe_query_pm_interrupts(cpu);
+	return cbe_read_pm(cpu, pm_status);
 }
-EXPORT_SYMBOL_GPL(cbe_clear_pm_interrupts);
+EXPORT_SYMBOL_GPL(cbe_get_and_clear_pm_interrupts);
 
 void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask)
 {
@@ -371,7 +365,7 @@
 
 void cbe_disable_pm_interrupts(u32 cpu)
 {
-	cbe_clear_pm_interrupts(cpu);
+	cbe_get_and_clear_pm_interrupts(cpu);
 	cbe_write_pm(cpu, pm_status, 0);
 }
 EXPORT_SYMBOL_GPL(cbe_disable_pm_interrupts);
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index d8b39fe..e34599f 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -59,63 +59,6 @@
 	return 0;
 }
 
-static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe,
-		const char *prop)
-{
-	const struct address_prop {
-		unsigned long address;
-		unsigned int len;
-	} __attribute__((packed)) *p;
-	int proplen;
-
-	unsigned long start_pfn, nr_pages;
-	struct pglist_data *pgdata;
-	struct zone *zone;
-	int ret;
-
-	p = get_property(spe, prop, &proplen);
-	WARN_ON(proplen != sizeof (*p));
-
-	start_pfn = p->address >> PAGE_SHIFT;
-	nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
-	pgdata = NODE_DATA(spu->node);
-	zone = pgdata->node_zones;
-
-	ret = __add_pages(zone, start_pfn, nr_pages);
-
-	return ret;
-}
-
-static void __iomem * __init map_spe_prop(struct spu *spu,
-		struct device_node *n, const char *name)
-{
-	const struct address_prop {
-		unsigned long address;
-		unsigned int len;
-	} __attribute__((packed)) *prop;
-
-	const void *p;
-	int proplen;
-	void __iomem *ret = NULL;
-	int err = 0;
-
-	p = get_property(n, name, &proplen);
-	if (proplen != sizeof (struct address_prop))
-		return NULL;
-
-	prop = p;
-
-	err = cell_spuprop_present(spu, n, name);
-	if (err && (err != -EEXIST))
-		goto out;
-
-	ret = ioremap(prop->address, prop->len);
-
- out:
-	return ret;
-}
-
 static void spu_unmap(struct spu *spu)
 {
 	if (!firmware_has_feature(FW_FEATURE_LPAR))
@@ -157,6 +100,23 @@
 	return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
 }
 
+static void __iomem * __init spu_map_prop_old(struct spu *spu,
+					      struct device_node *n,
+					      const char *name)
+{
+	const struct address_prop {
+		unsigned long address;
+		unsigned int len;
+	} __attribute__((packed)) *prop;
+	int proplen;
+
+	prop = get_property(n, name, &proplen);
+	if (prop == NULL || proplen != sizeof (struct address_prop))
+		return NULL;
+
+	return ioremap(prop->address, prop->len);
+}
+
 static int __init spu_map_device_old(struct spu *spu)
 {
 	struct device_node *node = spu->devnode;
@@ -175,7 +135,7 @@
 
 	/* we use local store as ram, not io memory */
 	spu->local_store = (void __force *)
-		map_spe_prop(spu, node, "local-store");
+		spu_map_prop_old(spu, node, "local-store");
 	if (!spu->local_store)
 		goto out;
 
@@ -184,16 +144,16 @@
 		goto out_unmap;
 	spu->problem_phys = *(unsigned long *)prop;
 
-	spu->problem = map_spe_prop(spu, node, "problem");
+	spu->problem = spu_map_prop_old(spu, node, "problem");
 	if (!spu->problem)
 		goto out_unmap;
 
-	spu->priv2 = map_spe_prop(spu, node, "priv2");
+	spu->priv2 = spu_map_prop_old(spu, node, "priv2");
 	if (!spu->priv2)
 		goto out_unmap;
 
 	if (!firmware_has_feature(FW_FEATURE_LPAR)) {
-		spu->priv1 = map_spe_prop(spu, node, "priv1");
+		spu->priv1 = spu_map_prop_old(spu, node, "priv1");
 		if (!spu->priv1)
 			goto out_unmap;
 	}
@@ -245,34 +205,20 @@
 			    void __iomem** virt, unsigned long *phys)
 {
 	struct device_node *np = spu->devnode;
-	unsigned long start_pfn, nr_pages;
-	struct pglist_data *pgdata;
-	struct zone *zone;
 	struct resource resource = { };
 	unsigned long len;
 	int ret;
 
 	ret = of_address_to_resource(np, nr, &resource);
 	if (ret)
-		goto out;
-
+		return ret;
 	if (phys)
 		*phys = resource.start;
 	len = resource.end - resource.start + 1;
 	*virt = ioremap(resource.start, len);
 	if (!*virt)
-		ret = -EINVAL;
-
-	start_pfn = resource.start >> PAGE_SHIFT;
-	nr_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
-	pgdata = NODE_DATA(spu->node);
-	zone = pgdata->node_zones;
-
-	ret = __add_pages(zone, start_pfn, nr_pages);
-
-out:
-	return ret;
+		return -EINVAL;
+	return 0;
 }
 
 static int __init spu_map_device(struct spu *spu)
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 0870009..04ad2e3 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -42,7 +42,7 @@
 	}
 	spin_lock_init(&ctx->mmio_lock);
 	kref_init(&ctx->kref);
-	init_rwsem(&ctx->state_sema);
+	mutex_init(&ctx->state_mutex);
 	init_MUTEX(&ctx->run_sema);
 	init_waitqueue_head(&ctx->ibox_wq);
 	init_waitqueue_head(&ctx->wbox_wq);
@@ -53,6 +53,10 @@
 	ctx->owner = get_task_mm(current);
 	if (gang)
 		spu_gang_add_ctx(gang, ctx);
+	ctx->rt_priority = current->rt_priority;
+	ctx->policy = current->policy;
+	ctx->prio = current->prio;
+	INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick);
 	goto out;
 out_free:
 	kfree(ctx);
@@ -65,9 +69,9 @@
 {
 	struct spu_context *ctx;
 	ctx = container_of(kref, struct spu_context, kref);
-	down_write(&ctx->state_sema);
+	mutex_lock(&ctx->state_mutex);
 	spu_deactivate(ctx);
-	up_write(&ctx->state_sema);
+	mutex_unlock(&ctx->state_mutex);
 	spu_fini_csa(&ctx->csa);
 	if (ctx->gang)
 		spu_gang_remove_ctx(ctx->gang, ctx);
@@ -96,107 +100,102 @@
 	spu_release(ctx);
 }
 
-void spu_acquire(struct spu_context *ctx)
-{
-	down_read(&ctx->state_sema);
-}
-
-void spu_release(struct spu_context *ctx)
-{
-	up_read(&ctx->state_sema);
-}
-
 void spu_unmap_mappings(struct spu_context *ctx)
 {
 	if (ctx->local_store)
 		unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
 	if (ctx->mfc)
-		unmap_mapping_range(ctx->mfc, 0, 0x4000, 1);
+		unmap_mapping_range(ctx->mfc, 0, 0x1000, 1);
 	if (ctx->cntl)
-		unmap_mapping_range(ctx->cntl, 0, 0x4000, 1);
+		unmap_mapping_range(ctx->cntl, 0, 0x1000, 1);
 	if (ctx->signal1)
-		unmap_mapping_range(ctx->signal1, 0, 0x4000, 1);
+		unmap_mapping_range(ctx->signal1, 0, PAGE_SIZE, 1);
 	if (ctx->signal2)
-		unmap_mapping_range(ctx->signal2, 0, 0x4000, 1);
+		unmap_mapping_range(ctx->signal2, 0, PAGE_SIZE, 1);
+	if (ctx->mss)
+		unmap_mapping_range(ctx->mss, 0, 0x1000, 1);
+	if (ctx->psmap)
+		unmap_mapping_range(ctx->psmap, 0, 0x20000, 1);
 }
 
+/**
+ * spu_acquire_exclusive - lock spu contex and protect against userspace access
+ * @ctx:	spu contex to lock
+ *
+ * Note:
+ *	Returns 0 and with the context locked on success
+ *	Returns negative error and with the context _unlocked_ on failure.
+ */
 int spu_acquire_exclusive(struct spu_context *ctx)
 {
-	int ret = 0;
+	int ret = -EINVAL;
 
-	down_write(&ctx->state_sema);
-	/* ctx is about to be freed, can't acquire any more */
-	if (!ctx->owner) {
-		ret = -EINVAL;
-		goto out;
-	}
+	spu_acquire(ctx);
+	/*
+	 * Context is about to be freed, so we can't acquire it anymore.
+	 */
+	if (!ctx->owner)
+		goto out_unlock;
 
 	if (ctx->state == SPU_STATE_SAVED) {
 		ret = spu_activate(ctx, 0);
 		if (ret)
-			goto out;
-		ctx->state = SPU_STATE_RUNNABLE;
+			goto out_unlock;
 	} else {
-		/* We need to exclude userspace access to the context. */
+		/*
+		 * We need to exclude userspace access to the context.
+		 *
+		 * To protect against memory access we invalidate all ptes
+		 * and make sure the pagefault handlers block on the mutex.
+		 */
 		spu_unmap_mappings(ctx);
 	}
 
-out:
-	if (ret)
-		up_write(&ctx->state_sema);
+	return 0;
+
+ out_unlock:
+	spu_release(ctx);
 	return ret;
 }
 
-int spu_acquire_runnable(struct spu_context *ctx)
+/**
+ * spu_acquire_runnable - lock spu contex and make sure it is in runnable state
+ * @ctx:	spu contex to lock
+ *
+ * Note:
+ *	Returns 0 and with the context locked on success
+ *	Returns negative error and with the context _unlocked_ on failure.
+ */
+int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags)
 {
-	int ret = 0;
+	int ret = -EINVAL;
 
-	down_read(&ctx->state_sema);
-	if (ctx->state == SPU_STATE_RUNNABLE) {
-		ctx->spu->prio = current->prio;
-		return 0;
-	}
-	up_read(&ctx->state_sema);
-
-	down_write(&ctx->state_sema);
-	/* ctx is about to be freed, can't acquire any more */
-	if (!ctx->owner) {
-		ret = -EINVAL;
-		goto out;
-	}
-
+	spu_acquire(ctx);
 	if (ctx->state == SPU_STATE_SAVED) {
-		ret = spu_activate(ctx, 0);
+		/*
+		 * Context is about to be freed, so we can't acquire it anymore.
+		 */
+		if (!ctx->owner)
+			goto out_unlock;
+		ret = spu_activate(ctx, flags);
 		if (ret)
-			goto out;
-		ctx->state = SPU_STATE_RUNNABLE;
+			goto out_unlock;
 	}
 
-	downgrade_write(&ctx->state_sema);
-	/* On success, we return holding the lock */
+	return 0;
 
-	return ret;
-out:
-	/* Release here, to simplify calling code. */
-	up_write(&ctx->state_sema);
-
+ out_unlock:
+	spu_release(ctx);
 	return ret;
 }
 
+/**
+ * spu_acquire_saved - lock spu contex and make sure it is in saved state
+ * @ctx:	spu contex to lock
+ */
 void spu_acquire_saved(struct spu_context *ctx)
 {
-	down_read(&ctx->state_sema);
-
-	if (ctx->state == SPU_STATE_SAVED)
-		return;
-
-	up_read(&ctx->state_sema);
-	down_write(&ctx->state_sema);
-
-	if (ctx->state == SPU_STATE_RUNNABLE) {
+	spu_acquire(ctx);
+	if (ctx->state != SPU_STATE_SAVED)
 		spu_deactivate(ctx);
-		ctx->state = SPU_STATE_SAVED;
-	}
-
-	downgrade_write(&ctx->state_sema);
 }
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 347eff5..b00653d 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -45,8 +45,8 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 	file->private_data = ctx;
-	file->f_mapping = inode->i_mapping;
 	ctx->local_store = inode->i_mapping;
+	smp_wmb();
 	return 0;
 }
 
@@ -95,39 +95,38 @@
 	return ret;
 }
 
-static struct page *
-spufs_mem_mmap_nopage(struct vm_area_struct *vma,
-		      unsigned long address, int *type)
+static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma,
+					  unsigned long address)
 {
-	struct page *page = NOPAGE_SIGBUS;
-
 	struct spu_context *ctx = vma->vm_file->private_data;
-	unsigned long offset = address - vma->vm_start;
+	unsigned long pfn, offset = address - vma->vm_start;
+
 	offset += vma->vm_pgoff << PAGE_SHIFT;
 
+	if (offset >= LS_SIZE)
+		return NOPFN_SIGBUS;
+
 	spu_acquire(ctx);
 
 	if (ctx->state == SPU_STATE_SAVED) {
 		vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 							& ~_PAGE_NO_CACHE);
-		page = vmalloc_to_page(ctx->csa.lscsa->ls + offset);
+		pfn = vmalloc_to_pfn(ctx->csa.lscsa->ls + offset);
 	} else {
 		vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
-							| _PAGE_NO_CACHE);
-		page = pfn_to_page((ctx->spu->local_store_phys + offset)
-				   >> PAGE_SHIFT);
+					     | _PAGE_NO_CACHE);
+		pfn = (ctx->spu->local_store_phys + offset) >> PAGE_SHIFT;
 	}
+	vm_insert_pfn(vma, address, pfn);
+
 	spu_release(ctx);
 
-	if (type)
-		*type = VM_FAULT_MINOR;
-
-	page_cache_get(page);
-	return page;
+	return NOPFN_REFAULT;
 }
 
+
 static struct vm_operations_struct spufs_mem_mmap_vmops = {
-	.nopage = spufs_mem_mmap_nopage,
+	.nopfn = spufs_mem_mmap_nopfn,
 };
 
 static int
@@ -136,7 +135,7 @@
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	vma->vm_flags |= VM_IO;
+	vma->vm_flags |= VM_IO | VM_PFNMAP;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE);
 
@@ -144,7 +143,7 @@
 	return 0;
 }
 
-static struct file_operations spufs_mem_fops = {
+static const struct file_operations spufs_mem_fops = {
 	.open	 = spufs_mem_open,
 	.read    = spufs_mem_read,
 	.write   = spufs_mem_write,
@@ -152,49 +151,42 @@
 	.mmap    = spufs_mem_mmap,
 };
 
-static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
+static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
 				    unsigned long address,
-				    int *type, unsigned long ps_offs,
+				    unsigned long ps_offs,
 				    unsigned long ps_size)
 {
-	struct page *page = NOPAGE_SIGBUS;
-	int fault_type = VM_FAULT_SIGBUS;
 	struct spu_context *ctx = vma->vm_file->private_data;
-	unsigned long offset = address - vma->vm_start;
-	unsigned long area;
+	unsigned long area, offset = address - vma->vm_start;
 	int ret;
 
 	offset += vma->vm_pgoff << PAGE_SHIFT;
 	if (offset >= ps_size)
-		goto out;
+		return NOPFN_SIGBUS;
 
-	ret = spu_acquire_runnable(ctx);
+	/* error here usually means a signal.. we might want to test
+	 * the error code more precisely though
+	 */
+	ret = spu_acquire_runnable(ctx, 0);
 	if (ret)
-		goto out;
+		return NOPFN_REFAULT;
 
 	area = ctx->spu->problem_phys + ps_offs;
-	page = pfn_to_page((area + offset) >> PAGE_SHIFT);
-	fault_type = VM_FAULT_MINOR;
-	page_cache_get(page);
-
+	vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
 	spu_release(ctx);
 
-      out:
-	if (type)
-		*type = fault_type;
-
-	return page;
+	return NOPFN_REFAULT;
 }
 
 #if SPUFS_MMAP_4K
-static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma,
-					   unsigned long address, int *type)
+static unsigned long spufs_cntl_mmap_nopfn(struct vm_area_struct *vma,
+					   unsigned long address)
 {
-	return spufs_ps_nopage(vma, address, type, 0x4000, 0x1000);
+	return spufs_ps_nopfn(vma, address, 0x4000, 0x1000);
 }
 
 static struct vm_operations_struct spufs_cntl_mmap_vmops = {
-	.nopage = spufs_cntl_mmap_nopage,
+	.nopfn = spufs_cntl_mmap_nopfn,
 };
 
 /*
@@ -205,7 +197,7 @@
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	vma->vm_flags |= VM_IO;
+	vma->vm_flags |= VM_IO | VM_PFNMAP;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
@@ -243,13 +235,13 @@
 	struct spu_context *ctx = i->i_ctx;
 
 	file->private_data = ctx;
-	file->f_mapping = inode->i_mapping;
 	ctx->cntl = inode->i_mapping;
+	smp_wmb();
 	return simple_attr_open(inode, file, spufs_cntl_get,
 					spufs_cntl_set, "0x%08lx");
 }
 
-static struct file_operations spufs_cntl_fops = {
+static const struct file_operations spufs_cntl_fops = {
 	.open = spufs_cntl_open,
 	.release = simple_attr_close,
 	.read = simple_attr_read,
@@ -309,7 +301,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_regs_fops = {
+static const struct file_operations spufs_regs_fops = {
 	.open	 = spufs_regs_open,
 	.read    = spufs_regs_read,
 	.write   = spufs_regs_write,
@@ -360,7 +352,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_fpcr_fops = {
+static const struct file_operations spufs_fpcr_fops = {
 	.open = spufs_regs_open,
 	.read = spufs_fpcr_read,
 	.write = spufs_fpcr_write,
@@ -426,7 +418,7 @@
 	return count;
 }
 
-static struct file_operations spufs_mbox_fops = {
+static const struct file_operations spufs_mbox_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_mbox_read,
 };
@@ -452,7 +444,7 @@
 	return 4;
 }
 
-static struct file_operations spufs_mbox_stat_fops = {
+static const struct file_operations spufs_mbox_stat_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_mbox_stat_read,
 };
@@ -559,7 +551,7 @@
 	return mask;
 }
 
-static struct file_operations spufs_ibox_fops = {
+static const struct file_operations spufs_ibox_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_ibox_read,
 	.poll	= spufs_ibox_poll,
@@ -585,7 +577,7 @@
 	return 4;
 }
 
-static struct file_operations spufs_ibox_stat_fops = {
+static const struct file_operations spufs_ibox_stat_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_ibox_stat_read,
 };
@@ -692,7 +684,7 @@
 	return mask;
 }
 
-static struct file_operations spufs_wbox_fops = {
+static const struct file_operations spufs_wbox_fops = {
 	.open	= spufs_pipe_open,
 	.write	= spufs_wbox_write,
 	.poll	= spufs_wbox_poll,
@@ -718,7 +710,7 @@
 	return 4;
 }
 
-static struct file_operations spufs_wbox_stat_fops = {
+static const struct file_operations spufs_wbox_stat_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_wbox_stat_read,
 };
@@ -728,8 +720,8 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 	file->private_data = ctx;
-	file->f_mapping = inode->i_mapping;
 	ctx->signal1 = inode->i_mapping;
+	smp_wmb();
 	return nonseekable_open(inode, file);
 }
 
@@ -791,23 +783,23 @@
 	return 4;
 }
 
-static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma,
-					      unsigned long address, int *type)
+static unsigned long spufs_signal1_mmap_nopfn(struct vm_area_struct *vma,
+					      unsigned long address)
 {
 #if PAGE_SIZE == 0x1000
-	return spufs_ps_nopage(vma, address, type, 0x14000, 0x1000);
+	return spufs_ps_nopfn(vma, address, 0x14000, 0x1000);
 #elif PAGE_SIZE == 0x10000
 	/* For 64k pages, both signal1 and signal2 can be used to mmap the whole
 	 * signal 1 and 2 area
 	 */
-	return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
+	return spufs_ps_nopfn(vma, address, 0x10000, 0x10000);
 #else
 #error unsupported page size
 #endif
 }
 
 static struct vm_operations_struct spufs_signal1_mmap_vmops = {
-	.nopage = spufs_signal1_mmap_nopage,
+	.nopfn = spufs_signal1_mmap_nopfn,
 };
 
 static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
@@ -815,7 +807,7 @@
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	vma->vm_flags |= VM_IO;
+	vma->vm_flags |= VM_IO | VM_PFNMAP;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
@@ -823,7 +815,7 @@
 	return 0;
 }
 
-static struct file_operations spufs_signal1_fops = {
+static const struct file_operations spufs_signal1_fops = {
 	.open = spufs_signal1_open,
 	.read = spufs_signal1_read,
 	.write = spufs_signal1_write,
@@ -835,8 +827,8 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 	file->private_data = ctx;
-	file->f_mapping = inode->i_mapping;
 	ctx->signal2 = inode->i_mapping;
+	smp_wmb();
 	return nonseekable_open(inode, file);
 }
 
@@ -899,23 +891,23 @@
 }
 
 #if SPUFS_MMAP_4K
-static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma,
-					      unsigned long address, int *type)
+static unsigned long spufs_signal2_mmap_nopfn(struct vm_area_struct *vma,
+					      unsigned long address)
 {
 #if PAGE_SIZE == 0x1000
-	return spufs_ps_nopage(vma, address, type, 0x1c000, 0x1000);
+	return spufs_ps_nopfn(vma, address, 0x1c000, 0x1000);
 #elif PAGE_SIZE == 0x10000
 	/* For 64k pages, both signal1 and signal2 can be used to mmap the whole
 	 * signal 1 and 2 area
 	 */
-	return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
+	return spufs_ps_nopfn(vma, address, 0x10000, 0x10000);
 #else
 #error unsupported page size
 #endif
 }
 
 static struct vm_operations_struct spufs_signal2_mmap_vmops = {
-	.nopage = spufs_signal2_mmap_nopage,
+	.nopfn = spufs_signal2_mmap_nopfn,
 };
 
 static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
@@ -923,7 +915,7 @@
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	vma->vm_flags |= VM_IO;
+	vma->vm_flags |= VM_IO | VM_PFNMAP;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
@@ -934,7 +926,7 @@
 #define spufs_signal2_mmap NULL
 #endif /* !SPUFS_MMAP_4K */
 
-static struct file_operations spufs_signal2_fops = {
+static const struct file_operations spufs_signal2_fops = {
 	.open = spufs_signal2_open,
 	.read = spufs_signal2_read,
 	.write = spufs_signal2_write,
@@ -1000,14 +992,14 @@
 					spufs_signal2_type_set, "%llu");
 
 #if SPUFS_MMAP_4K
-static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma,
-					   unsigned long address, int *type)
+static unsigned long spufs_mss_mmap_nopfn(struct vm_area_struct *vma,
+					  unsigned long address)
 {
-	return spufs_ps_nopage(vma, address, type, 0x0000, 0x1000);
+	return spufs_ps_nopfn(vma, address, 0x0000, 0x1000);
 }
 
 static struct vm_operations_struct spufs_mss_mmap_vmops = {
-	.nopage = spufs_mss_mmap_nopage,
+	.nopfn = spufs_mss_mmap_nopfn,
 };
 
 /*
@@ -1018,7 +1010,7 @@
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	vma->vm_flags |= VM_IO;
+	vma->vm_flags |= VM_IO | VM_PFNMAP;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
@@ -1032,24 +1024,27 @@
 static int spufs_mss_open(struct inode *inode, struct file *file)
 {
 	struct spufs_inode_info *i = SPUFS_I(inode);
+	struct spu_context *ctx = i->i_ctx;
 
 	file->private_data = i->i_ctx;
+	ctx->mss = inode->i_mapping;
+	smp_wmb();
 	return nonseekable_open(inode, file);
 }
 
-static struct file_operations spufs_mss_fops = {
+static const struct file_operations spufs_mss_fops = {
 	.open	 = spufs_mss_open,
 	.mmap	 = spufs_mss_mmap,
 };
 
-static struct page *spufs_psmap_mmap_nopage(struct vm_area_struct *vma,
-					   unsigned long address, int *type)
+static unsigned long spufs_psmap_mmap_nopfn(struct vm_area_struct *vma,
+					    unsigned long address)
 {
-	return spufs_ps_nopage(vma, address, type, 0x0000, 0x20000);
+	return spufs_ps_nopfn(vma, address, 0x0000, 0x20000);
 }
 
 static struct vm_operations_struct spufs_psmap_mmap_vmops = {
-	.nopage = spufs_psmap_mmap_nopage,
+	.nopfn = spufs_psmap_mmap_nopfn,
 };
 
 /*
@@ -1060,7 +1055,7 @@
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	vma->vm_flags |= VM_IO;
+	vma->vm_flags |= VM_IO | VM_PFNMAP;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
@@ -1071,26 +1066,29 @@
 static int spufs_psmap_open(struct inode *inode, struct file *file)
 {
 	struct spufs_inode_info *i = SPUFS_I(inode);
+	struct spu_context *ctx = i->i_ctx;
 
 	file->private_data = i->i_ctx;
+	ctx->psmap = inode->i_mapping;
+	smp_wmb();
 	return nonseekable_open(inode, file);
 }
 
-static struct file_operations spufs_psmap_fops = {
+static const struct file_operations spufs_psmap_fops = {
 	.open	 = spufs_psmap_open,
 	.mmap	 = spufs_psmap_mmap,
 };
 
 
 #if SPUFS_MMAP_4K
-static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
-					   unsigned long address, int *type)
+static unsigned long spufs_mfc_mmap_nopfn(struct vm_area_struct *vma,
+					  unsigned long address)
 {
-	return spufs_ps_nopage(vma, address, type, 0x3000, 0x1000);
+	return spufs_ps_nopfn(vma, address, 0x3000, 0x1000);
 }
 
 static struct vm_operations_struct spufs_mfc_mmap_vmops = {
-	.nopage = spufs_mfc_mmap_nopage,
+	.nopfn = spufs_mfc_mmap_nopfn,
 };
 
 /*
@@ -1101,7 +1099,7 @@
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	vma->vm_flags |= VM_IO;
+	vma->vm_flags |= VM_IO | VM_PFNMAP;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
@@ -1125,6 +1123,8 @@
 		return -EBUSY;
 
 	file->private_data = ctx;
+	ctx->mfc = inode->i_mapping;
+	smp_wmb();
 	return nonseekable_open(inode, file);
 }
 
@@ -1309,7 +1309,7 @@
 	if (ret)
 		goto out;
 
-	spu_acquire_runnable(ctx);
+	spu_acquire_runnable(ctx, 0);
 	if (file->f_flags & O_NONBLOCK) {
 		ret = ctx->ops->send_mfc_command(ctx, &cmd);
 	} else {
@@ -1393,7 +1393,7 @@
 	return fasync_helper(fd, file, on, &ctx->mfc_fasync);
 }
 
-static struct file_operations spufs_mfc_fops = {
+static const struct file_operations spufs_mfc_fops = {
 	.open	 = spufs_mfc_open,
 	.read	 = spufs_mfc_read,
 	.write	 = spufs_mfc_write,
@@ -1650,7 +1650,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_mbox_info_fops = {
+static const struct file_operations spufs_mbox_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_mbox_info_read,
 	.llseek  = generic_file_llseek,
@@ -1688,7 +1688,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_ibox_info_fops = {
+static const struct file_operations spufs_ibox_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_ibox_info_read,
 	.llseek  = generic_file_llseek,
@@ -1729,7 +1729,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_wbox_info_fops = {
+static const struct file_operations spufs_wbox_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_wbox_info_read,
 	.llseek  = generic_file_llseek,
@@ -1779,7 +1779,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_dma_info_fops = {
+static const struct file_operations spufs_dma_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_dma_info_read,
 };
@@ -1830,7 +1830,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_proxydma_info_fops = {
+static const struct file_operations spufs_proxydma_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_proxydma_info_read,
 };
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 738b924..8079983 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -220,11 +220,11 @@
 	return dcache_dir_close(inode, file);
 }
 
-struct inode_operations spufs_dir_inode_operations = {
+const struct inode_operations spufs_dir_inode_operations = {
 	.lookup = simple_lookup,
 };
 
-struct file_operations spufs_context_fops = {
+const struct file_operations spufs_context_fops = {
 	.open		= dcache_dir_open,
 	.release	= spufs_dir_close,
 	.llseek		= dcache_dir_lseek,
@@ -372,7 +372,7 @@
 	return dcache_dir_close(inode, file);
 }
 
-struct file_operations spufs_gang_fops = {
+const struct file_operations spufs_gang_fops = {
 	.open		= dcache_dir_open,
 	.release	= spufs_gang_close,
 	.llseek		= dcache_dir_lseek,
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 1acc2ff..353a8fa 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -133,7 +133,7 @@
 	spu_mfc_sr1_set(ctx->spu, sr1);
 
 out_unlock:
-	spu_release_exclusive(ctx);
+	spu_release(ctx);
 out:
 	return ret;
 }
@@ -143,7 +143,7 @@
 	int ret;
 	unsigned long runcntl = SPU_RUNCNTL_RUNNABLE;
 
-	ret = spu_acquire_runnable(ctx);
+	ret = spu_acquire_runnable(ctx, SPU_ACTIVATE_NOWAKE);
 	if (ret)
 		return ret;
 
@@ -155,7 +155,7 @@
 			spu_release(ctx);
 			ret = spu_setup_isolated(ctx);
 			if (!ret)
-				ret = spu_acquire_runnable(ctx);
+				ret = spu_acquire_runnable(ctx, SPU_ACTIVATE_NOWAKE);
 		}
 
 		/* if userspace has set the runcntrl register (eg, to issue an
@@ -164,8 +164,10 @@
 			(SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
 		if (runcntl == 0)
 			runcntl = SPU_RUNCNTL_RUNNABLE;
-	} else
+	} else {
+		spu_start_tick(ctx);
 		ctx->ops->npc_write(ctx, *npc);
+	}
 
 	ctx->ops->runcntl_write(ctx, runcntl);
 	return ret;
@@ -176,6 +178,7 @@
 {
 	int ret = 0;
 
+	spu_stop_tick(ctx);
 	*status = ctx->ops->status_read(ctx);
 	*npc = ctx->ops->npc_read(ctx);
 	spu_release(ctx);
@@ -329,8 +332,10 @@
 		}
 		if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
 			ret = spu_reacquire_runnable(ctx, npc, &status);
-			if (ret)
+			if (ret) {
+				spu_stop_tick(ctx);
 				goto out2;
+			}
 			continue;
 		}
 		ret = spu_process_events(ctx);
@@ -361,4 +366,3 @@
 	up(&ctx->run_sema);
 	return ret;
 }
-
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index bd6fe4b..2f25e68 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -44,17 +44,18 @@
 #include <asm/spu_priv1.h>
 #include "spufs.h"
 
-#define SPU_MIN_TIMESLICE 	(100 * HZ / 1000)
+#define SPU_TIMESLICE	(HZ)
 
-#define SPU_BITMAP_SIZE (((MAX_PRIO+BITS_PER_LONG)/BITS_PER_LONG)+1)
 struct spu_prio_array {
-	unsigned long bitmap[SPU_BITMAP_SIZE];
-	wait_queue_head_t waitq[MAX_PRIO];
+	DECLARE_BITMAP(bitmap, MAX_PRIO);
+	struct list_head runq[MAX_PRIO];
+	spinlock_t runq_lock;
 	struct list_head active_list[MAX_NUMNODES];
 	struct mutex active_mutex[MAX_NUMNODES];
 };
 
 static struct spu_prio_array *spu_prio;
+static struct workqueue_struct *spu_sched_wq;
 
 static inline int node_allowed(int node)
 {
@@ -68,6 +69,64 @@
 	return 1;
 }
 
+void spu_start_tick(struct spu_context *ctx)
+{
+	if (ctx->policy == SCHED_RR)
+		queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE);
+}
+
+void spu_stop_tick(struct spu_context *ctx)
+{
+	if (ctx->policy == SCHED_RR)
+		cancel_delayed_work(&ctx->sched_work);
+}
+
+void spu_sched_tick(struct work_struct *work)
+{
+	struct spu_context *ctx =
+		container_of(work, struct spu_context, sched_work.work);
+	struct spu *spu;
+	int rearm = 1;
+
+	mutex_lock(&ctx->state_mutex);
+	spu = ctx->spu;
+	if (spu) {
+		int best = sched_find_first_bit(spu_prio->bitmap);
+		if (best <= ctx->prio) {
+			spu_deactivate(ctx);
+			rearm = 0;
+		}
+	}
+	mutex_unlock(&ctx->state_mutex);
+
+	if (rearm)
+		spu_start_tick(ctx);
+}
+
+/**
+ * spu_add_to_active_list - add spu to active list
+ * @spu:	spu to add to the active list
+ */
+static void spu_add_to_active_list(struct spu *spu)
+{
+	mutex_lock(&spu_prio->active_mutex[spu->node]);
+	list_add_tail(&spu->list, &spu_prio->active_list[spu->node]);
+	mutex_unlock(&spu_prio->active_mutex[spu->node]);
+}
+
+/**
+ * spu_remove_from_active_list - remove spu from active list
+ * @spu:       spu to remove from the active list
+ */
+static void spu_remove_from_active_list(struct spu *spu)
+{
+	int node = spu->node;
+
+	mutex_lock(&spu_prio->active_mutex[node]);
+	list_del_init(&spu->list);
+	mutex_unlock(&spu_prio->active_mutex[node]);
+}
+
 static inline void mm_needs_global_tlbie(struct mm_struct *mm)
 {
 	int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1;
@@ -94,8 +153,12 @@
 	return blocking_notifier_chain_unregister(&spu_switch_notifier, n);
 }
 
-
-static inline void bind_context(struct spu *spu, struct spu_context *ctx)
+/**
+ * spu_bind_context - bind spu context to physical spu
+ * @spu:	physical spu to bind to
+ * @ctx:	context to bind
+ */
+static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
 {
 	pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
 		 spu->number, spu->node);
@@ -104,7 +167,6 @@
 	ctx->spu = spu;
 	ctx->ops = &spu_hw_ops;
 	spu->pid = current->pid;
-	spu->prio = current->prio;
 	spu->mm = ctx->owner;
 	mm_needs_global_tlbie(spu->mm);
 	spu->ibox_callback = spufs_ibox_callback;
@@ -118,12 +180,21 @@
 	spu->timestamp = jiffies;
 	spu_cpu_affinity_set(spu, raw_smp_processor_id());
 	spu_switch_notify(spu, ctx);
+	spu_add_to_active_list(spu);
+	ctx->state = SPU_STATE_RUNNABLE;
 }
 
-static inline void unbind_context(struct spu *spu, struct spu_context *ctx)
+/**
+ * spu_unbind_context - unbind spu context from physical spu
+ * @spu:	physical spu to unbind from
+ * @ctx:	context to unbind
+ */
+static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
 {
 	pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
 		 spu->pid, spu->number, spu->node);
+
+	spu_remove_from_active_list(spu);
 	spu_switch_notify(spu, NULL);
 	spu_unmap_mappings(ctx);
 	spu_save(&ctx->csa, spu);
@@ -136,95 +207,98 @@
 	spu->dma_callback = NULL;
 	spu->mm = NULL;
 	spu->pid = 0;
-	spu->prio = MAX_PRIO;
 	ctx->ops = &spu_backing_ops;
 	ctx->spu = NULL;
 	spu->flags = 0;
 	spu->ctx = NULL;
 }
 
-static inline void spu_add_wq(wait_queue_head_t * wq, wait_queue_t * wait,
-			      int prio)
+/**
+ * spu_add_to_rq - add a context to the runqueue
+ * @ctx:       context to add
+ */
+static void spu_add_to_rq(struct spu_context *ctx)
 {
-	prepare_to_wait_exclusive(wq, wait, TASK_INTERRUPTIBLE);
-	set_bit(prio, spu_prio->bitmap);
+	spin_lock(&spu_prio->runq_lock);
+	list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]);
+	set_bit(ctx->prio, spu_prio->bitmap);
+	spin_unlock(&spu_prio->runq_lock);
 }
 
-static inline void spu_del_wq(wait_queue_head_t * wq, wait_queue_t * wait,
-			      int prio)
+/**
+ * spu_del_from_rq - remove a context from the runqueue
+ * @ctx:       context to remove
+ */
+static void spu_del_from_rq(struct spu_context *ctx)
 {
-	u64 flags;
-
-	__set_current_state(TASK_RUNNING);
-
-	spin_lock_irqsave(&wq->lock, flags);
-
-	remove_wait_queue_locked(wq, wait);
-	if (list_empty(&wq->task_list))
-		clear_bit(prio, spu_prio->bitmap);
-
-	spin_unlock_irqrestore(&wq->lock, flags);
+	spin_lock(&spu_prio->runq_lock);
+	list_del_init(&ctx->rq);
+	if (list_empty(&spu_prio->runq[ctx->prio]))
+		clear_bit(ctx->prio, spu_prio->bitmap);
+	spin_unlock(&spu_prio->runq_lock);
 }
 
-static void spu_prio_wait(struct spu_context *ctx, u64 flags)
+/**
+ * spu_grab_context - remove one context from the runqueue
+ * @prio:      priority of the context to be removed
+ *
+ * This function removes one context from the runqueue for priority @prio.
+ * If there is more than one context with the given priority the first
+ * task on the runqueue will be taken.
+ *
+ * Returns the spu_context it just removed.
+ *
+ * Must be called with spu_prio->runq_lock held.
+ */
+static struct spu_context *spu_grab_context(int prio)
 {
-	int prio = current->prio;
-	wait_queue_head_t *wq = &spu_prio->waitq[prio];
+	struct list_head *rq = &spu_prio->runq[prio];
+
+	if (list_empty(rq))
+		return NULL;
+	return list_entry(rq->next, struct spu_context, rq);
+}
+
+static void spu_prio_wait(struct spu_context *ctx)
+{
 	DEFINE_WAIT(wait);
 
-	if (ctx->spu)
-		return;
-
-	spu_add_wq(wq, &wait, prio);
-
+	set_bit(SPU_SCHED_WAKE, &ctx->sched_flags);
+	prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE);
 	if (!signal_pending(current)) {
-		up_write(&ctx->state_sema);
-		pr_debug("%s: pid=%d prio=%d\n", __FUNCTION__,
-			 current->pid, current->prio);
+		mutex_unlock(&ctx->state_mutex);
 		schedule();
-		down_write(&ctx->state_sema);
+		mutex_lock(&ctx->state_mutex);
 	}
-
-	spu_del_wq(wq, &wait, prio);
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&ctx->stop_wq, &wait);
+	clear_bit(SPU_SCHED_WAKE, &ctx->sched_flags);
 }
 
-static void spu_prio_wakeup(void)
+/**
+ * spu_reschedule - try to find a runnable context for a spu
+ * @spu:       spu available
+ *
+ * This function is called whenever a spu becomes idle.  It looks for the
+ * most suitable runnable spu context and schedules it for execution.
+ */
+static void spu_reschedule(struct spu *spu)
 {
-	int best = sched_find_first_bit(spu_prio->bitmap);
+	int best;
+
+	spu_free(spu);
+
+	spin_lock(&spu_prio->runq_lock);
+	best = sched_find_first_bit(spu_prio->bitmap);
 	if (best < MAX_PRIO) {
-		wait_queue_head_t *wq = &spu_prio->waitq[best];
-		wake_up_interruptible_nr(wq, 1);
+		struct spu_context *ctx = spu_grab_context(best);
+		if (ctx && test_bit(SPU_SCHED_WAKE, &ctx->sched_flags))
+			wake_up(&ctx->stop_wq);
 	}
+	spin_unlock(&spu_prio->runq_lock);
 }
 
-static int get_active_spu(struct spu *spu)
-{
-	int node = spu->node;
-	struct spu *tmp;
-	int rc = 0;
-
-	mutex_lock(&spu_prio->active_mutex[node]);
-	list_for_each_entry(tmp, &spu_prio->active_list[node], list) {
-		if (tmp == spu) {
-			list_del_init(&spu->list);
-			rc = 1;
-			break;
-		}
-	}
-	mutex_unlock(&spu_prio->active_mutex[node]);
-	return rc;
-}
-
-static void put_active_spu(struct spu *spu)
-{
-	int node = spu->node;
-
-	mutex_lock(&spu_prio->active_mutex[node]);
-	list_add_tail(&spu->list, &spu_prio->active_list[node]);
-	mutex_unlock(&spu_prio->active_mutex[node]);
-}
-
-static struct spu *spu_get_idle(struct spu_context *ctx, u64 flags)
+static struct spu *spu_get_idle(struct spu_context *ctx)
 {
 	struct spu *spu = NULL;
 	int node = cpu_to_node(raw_smp_processor_id());
@@ -241,87 +315,154 @@
 	return spu;
 }
 
-static inline struct spu *spu_get(struct spu_context *ctx, u64 flags)
-{
-	/* Future: spu_get_idle() if possible,
-	 * otherwise try to preempt an active
-	 * context.
-	 */
-	return spu_get_idle(ctx, flags);
-}
-
-/* The three externally callable interfaces
- * for the scheduler begin here.
+/**
+ * find_victim - find a lower priority context to preempt
+ * @ctx:	canidate context for running
  *
- *	spu_activate	- bind a context to SPU, waiting as needed.
- *	spu_deactivate	- unbind a context from its SPU.
- *	spu_yield	- yield an SPU if others are waiting.
+ * Returns the freed physical spu to run the new context on.
  */
-
-int spu_activate(struct spu_context *ctx, u64 flags)
+static struct spu *find_victim(struct spu_context *ctx)
 {
+	struct spu_context *victim = NULL;
 	struct spu *spu;
-	int ret = 0;
+	int node, n;
 
-	for (;;) {
-		if (ctx->spu)
-			return 0;
-		spu = spu_get(ctx, flags);
-		if (spu != NULL) {
-			if (ctx->spu != NULL) {
-				spu_free(spu);
-				spu_prio_wakeup();
-				break;
-			}
-			bind_context(spu, ctx);
-			put_active_spu(spu);
-			break;
+	/*
+	 * Look for a possible preemption candidate on the local node first.
+	 * If there is no candidate look at the other nodes.  This isn't
+	 * exactly fair, but so far the whole spu schedule tries to keep
+	 * a strong node affinity.  We might want to fine-tune this in
+	 * the future.
+	 */
+ restart:
+	node = cpu_to_node(raw_smp_processor_id());
+	for (n = 0; n < MAX_NUMNODES; n++, node++) {
+		node = (node < MAX_NUMNODES) ? node : 0;
+		if (!node_allowed(node))
+			continue;
+
+		mutex_lock(&spu_prio->active_mutex[node]);
+		list_for_each_entry(spu, &spu_prio->active_list[node], list) {
+			struct spu_context *tmp = spu->ctx;
+
+			if (tmp->rt_priority < ctx->rt_priority &&
+			    (!victim || tmp->rt_priority < victim->rt_priority))
+				victim = spu->ctx;
 		}
-		spu_prio_wait(ctx, flags);
-		if (signal_pending(current)) {
-			ret = -ERESTARTSYS;
-			spu_prio_wakeup();
-			break;
+		mutex_unlock(&spu_prio->active_mutex[node]);
+
+		if (victim) {
+			/*
+			 * This nests ctx->state_mutex, but we always lock
+			 * higher priority contexts before lower priority
+			 * ones, so this is safe until we introduce
+			 * priority inheritance schemes.
+			 */
+			if (!mutex_trylock(&victim->state_mutex)) {
+				victim = NULL;
+				goto restart;
+			}
+
+			spu = victim->spu;
+			if (!spu) {
+				/*
+				 * This race can happen because we've dropped
+				 * the active list mutex.  No a problem, just
+				 * restart the search.
+				 */
+				mutex_unlock(&victim->state_mutex);
+				victim = NULL;
+				goto restart;
+			}
+			spu_unbind_context(spu, victim);
+			mutex_unlock(&victim->state_mutex);
+			return spu;
 		}
 	}
-	return ret;
+
+	return NULL;
 }
 
+/**
+ * spu_activate - find a free spu for a context and execute it
+ * @ctx:	spu context to schedule
+ * @flags:	flags (currently ignored)
+ *
+ * Tries to find a free spu to run @ctx.  If no free spu is availble
+ * add the context to the runqueue so it gets woken up once an spu
+ * is available.
+ */
+int spu_activate(struct spu_context *ctx, unsigned long flags)
+{
+
+	if (ctx->spu)
+		return 0;
+
+	do {
+		struct spu *spu;
+
+		spu = spu_get_idle(ctx);
+		/*
+		 * If this is a realtime thread we try to get it running by
+		 * preempting a lower priority thread.
+		 */
+		if (!spu && ctx->rt_priority)
+			spu = find_victim(ctx);
+		if (spu) {
+			spu_bind_context(spu, ctx);
+			return 0;
+		}
+
+		spu_add_to_rq(ctx);
+		if (!(flags & SPU_ACTIVATE_NOWAKE))
+			spu_prio_wait(ctx);
+		spu_del_from_rq(ctx);
+	} while (!signal_pending(current));
+
+	return -ERESTARTSYS;
+}
+
+/**
+ * spu_deactivate - unbind a context from it's physical spu
+ * @ctx:	spu context to unbind
+ *
+ * Unbind @ctx from the physical spu it is running on and schedule
+ * the highest priority context to run on the freed physical spu.
+ */
 void spu_deactivate(struct spu_context *ctx)
 {
-	struct spu *spu;
-	int needs_idle;
+	struct spu *spu = ctx->spu;
 
-	spu = ctx->spu;
-	if (!spu)
-		return;
-	needs_idle = get_active_spu(spu);
-	unbind_context(spu, ctx);
-	if (needs_idle) {
-		spu_free(spu);
-		spu_prio_wakeup();
+	if (spu) {
+		spu_unbind_context(spu, ctx);
+		spu_reschedule(spu);
 	}
 }
 
+/**
+ * spu_yield -  yield a physical spu if others are waiting
+ * @ctx:	spu context to yield
+ *
+ * Check if there is a higher priority context waiting and if yes
+ * unbind @ctx from the physical spu and schedule the highest
+ * priority context to run on the freed physical spu instead.
+ */
 void spu_yield(struct spu_context *ctx)
 {
 	struct spu *spu;
 	int need_yield = 0;
 
-	if (down_write_trylock(&ctx->state_sema)) {
+	if (mutex_trylock(&ctx->state_mutex)) {
 		if ((spu = ctx->spu) != NULL) {
 			int best = sched_find_first_bit(spu_prio->bitmap);
 			if (best < MAX_PRIO) {
 				pr_debug("%s: yielding SPU %d NODE %d\n",
 					 __FUNCTION__, spu->number, spu->node);
 				spu_deactivate(ctx);
-				ctx->state = SPU_STATE_SAVED;
 				need_yield = 1;
-			} else {
-				spu->prio = MAX_PRIO;
 			}
 		}
-		up_write(&ctx->state_sema);
+		mutex_unlock(&ctx->state_mutex);
 	}
 	if (unlikely(need_yield))
 		yield();
@@ -331,14 +472,19 @@
 {
 	int i;
 
+	spu_sched_wq = create_singlethread_workqueue("spusched");
+	if (!spu_sched_wq)
+		return 1;
+
 	spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
 	if (!spu_prio) {
 		printk(KERN_WARNING "%s: Unable to allocate priority queue.\n",
 		       __FUNCTION__);
+		       destroy_workqueue(spu_sched_wq);
 		return 1;
 	}
 	for (i = 0; i < MAX_PRIO; i++) {
-		init_waitqueue_head(&spu_prio->waitq[i]);
+		INIT_LIST_HEAD(&spu_prio->runq[i]);
 		__clear_bit(i, spu_prio->bitmap);
 	}
 	__set_bit(MAX_PRIO, spu_prio->bitmap);
@@ -346,6 +492,7 @@
 		mutex_init(&spu_prio->active_mutex[i]);
 		INIT_LIST_HEAD(&spu_prio->active_list[i]);
 	}
+	spin_lock_init(&spu_prio->runq_lock);
 	return 0;
 }
 
@@ -364,4 +511,5 @@
 		mutex_unlock(&spu_prio->active_mutex[node]);
 	}
 	kfree(spu_prio);
+	destroy_workqueue(spu_sched_wq);
 }
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 70fb133..0c43789 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -23,7 +23,7 @@
 #define SPUFS_H
 
 #include <linux/kref.h>
-#include <linux/rwsem.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/fs.h>
 
@@ -37,11 +37,13 @@
 };
 
 struct spu_context_ops;
-
-#define SPU_CONTEXT_PREEMPT          0UL
-
 struct spu_gang;
 
+/* ctx->sched_flags */
+enum {
+	SPU_SCHED_WAKE = 0,
+};
+
 struct spu_context {
 	struct spu *spu;		  /* pointer to a physical SPU */
 	struct spu_state csa;		  /* SPU context save area. */
@@ -51,10 +53,12 @@
 	struct address_space *cntl; 	   /* 'control' area mappings. */
 	struct address_space *signal1; 	   /* 'signal1' area mappings. */
 	struct address_space *signal2; 	   /* 'signal2' area mappings. */
+	struct address_space *mss; 	   /* 'mss' area mappings. */
+	struct address_space *psmap; 	   /* 'psmap' area mappings. */
 	u64 object_id;		   /* user space pointer for oprofile */
 
 	enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
-	struct rw_semaphore state_sema;
+	struct mutex state_mutex;
 	struct semaphore run_sema;
 
 	struct mm_struct *owner;
@@ -75,6 +79,14 @@
 
 	struct list_head gang_list;
 	struct spu_gang *gang;
+
+	/* scheduler fields */
+ 	struct list_head rq;
+	struct delayed_work sched_work;
+	unsigned long sched_flags;
+	unsigned long rt_priority;
+	int policy;
+	int prio;
 };
 
 struct spu_gang {
@@ -149,7 +161,7 @@
 		   struct spu_context *ctx, u32 *npc, u32 *status);
 long spufs_create(struct nameidata *nd,
 			 unsigned int flags, mode_t mode);
-extern struct file_operations spufs_context_fops;
+extern const struct file_operations spufs_context_fops;
 
 /* gang management */
 struct spu_gang *alloc_spu_gang(void);
@@ -159,6 +171,16 @@
 void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx);
 
 /* context management */
+static inline void spu_acquire(struct spu_context *ctx)
+{
+	mutex_lock(&ctx->state_mutex);
+}
+
+static inline void spu_release(struct spu_context *ctx)
+{
+	mutex_unlock(&ctx->state_mutex);
+}
+
 struct spu_context * alloc_spu_context(struct spu_gang *gang);
 void destroy_spu_context(struct kref *kref);
 struct spu_context * get_spu_context(struct spu_context *ctx);
@@ -166,20 +188,18 @@
 void spu_unmap_mappings(struct spu_context *ctx);
 
 void spu_forget(struct spu_context *ctx);
-void spu_acquire(struct spu_context *ctx);
-void spu_release(struct spu_context *ctx);
-int spu_acquire_runnable(struct spu_context *ctx);
+int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags);
 void spu_acquire_saved(struct spu_context *ctx);
 int spu_acquire_exclusive(struct spu_context *ctx);
-
-static inline void spu_release_exclusive(struct spu_context *ctx)
-{
-	up_write(&ctx->state_sema);
-}
-
-int spu_activate(struct spu_context *ctx, u64 flags);
+enum {
+	SPU_ACTIVATE_NOWAKE = 1,
+};
+int spu_activate(struct spu_context *ctx, unsigned long flags);
 void spu_deactivate(struct spu_context *ctx);
 void spu_yield(struct spu_context *ctx);
+void spu_start_tick(struct spu_context *ctx);
+void spu_stop_tick(struct spu_context *ctx);
+void spu_sched_tick(struct work_struct *work);
 int __init spu_sched_init(void);
 void __exit spu_sched_exit(void);
 
diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile
index 3baf658..f4f8252 100644
--- a/arch/powerpc/platforms/celleb/Makefile
+++ b/arch/powerpc/platforms/celleb/Makefile
@@ -1,9 +1,8 @@
 obj-y				+= interrupt.o iommu.o setup.o \
 				   htab.o beat.o pci.o \
-				   scc_epci.o hvCall.o
+				   scc_epci.o scc_uhc.o hvCall.o
 
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_PPC_UDBG_BEAT)	+= udbg_beat.o
-obj-$(CONFIG_USB)		+= scc_uhc.o
 obj-$(CONFIG_HAS_TXX9_SERIAL)	+= scc_sio.o
 obj-$(CONFIG_SPU_BASE)		+= spu_priv1.o
diff --git a/arch/powerpc/platforms/celleb/htab.c b/arch/powerpc/platforms/celleb/htab.c
index ffa7c2c..279d733 100644
--- a/arch/powerpc/platforms/celleb/htab.c
+++ b/arch/powerpc/platforms/celleb/htab.c
@@ -95,7 +95,6 @@
 	unsigned long lpar_rc;
 	unsigned long slot;
 	unsigned long hpte_v, hpte_r;
-	unsigned long flags;
 
 	/* same as iseries */
 	if (vflags & HPTE_V_SECONDARY)
@@ -115,17 +114,17 @@
 	if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
 		hpte_r &= ~_PAGE_COHERENT;
 
-	spin_lock_irqsave(&beat_htab_lock, flags);
+	spin_lock(&beat_htab_lock);
 	if ((lpar_rc = beat_read_mask(hpte_group)) == 0) {
 		if (!(vflags & HPTE_V_BOLTED))
 			DBG_LOW(" full\n");
-		spin_unlock_irqrestore(&beat_htab_lock, flags);
+		spin_unlock(&beat_htab_lock);
 		return -1;
 	}
 
 	lpar_rc = beat_insert_htab_entry(0, hpte_group, lpar_rc << 48,
 		hpte_v, hpte_r, &slot);
-	spin_unlock_irqrestore(&beat_htab_lock, flags);
+	spin_unlock(&beat_htab_lock);
 
 	/*
 	 * Since we try and ioremap PHBs we don't own, the pte insert
@@ -189,7 +188,6 @@
 {
 	unsigned long lpar_rc;
 	unsigned long dummy0, dummy1, want_v;
-	unsigned long flags;
 
 	want_v = hpte_encode_v(va, psize);
 
@@ -197,17 +195,17 @@
 		"avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
 		want_v & HPTE_V_AVPN, slot, psize, newpp);
 
-	spin_lock_irqsave(&beat_htab_lock, flags);
+	spin_lock(&beat_htab_lock);
 	dummy0 = beat_lpar_hpte_getword0(slot);
 	if ((dummy0 & ~0x7FUL) != (want_v & ~0x7FUL)) {
 		DBG_LOW("not found !\n");
-		spin_unlock_irqrestore(&beat_htab_lock, flags);
+		spin_unlock(&beat_htab_lock);
 		return -1;
 	}
 
 	lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7, &dummy0,
 					&dummy1);
-	spin_unlock_irqrestore(&beat_htab_lock, flags);
+	spin_unlock(&beat_htab_lock);
 	if (lpar_rc != 0 || dummy0 == 0) {
 		DBG_LOW("not found !\n");
 		return -1;
@@ -256,18 +254,17 @@
 					  int psize)
 {
 	unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1;
-	unsigned long flags;
 
 	vsid = get_kernel_vsid(ea);
 	va = (vsid << 28) | (ea & 0x0fffffff);
 
-	spin_lock_irqsave(&beat_htab_lock, flags);
+	spin_lock(&beat_htab_lock);
 	slot = beat_lpar_hpte_find(va, psize);
 	BUG_ON(slot == -1);
 
 	lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7,
 		&dummy0, &dummy1);
-	spin_unlock_irqrestore(&beat_htab_lock, flags);
+	spin_unlock(&beat_htab_lock);
 
 	BUG_ON(lpar_rc != 0);
 }
diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c
index 867f83a..98de836 100644
--- a/arch/powerpc/platforms/celleb/pci.c
+++ b/arch/powerpc/platforms/celleb/pci.c
@@ -65,13 +65,13 @@
 
 static inline u16 celleb_fake_config_readw(void *addr)
 {
-	u16 *p = addr;
+	__le16 *p = addr;
 	return le16_to_cpu(*p);
 }
 
 static inline u32 celleb_fake_config_readl(void *addr)
 {
-	u32 *p = addr;
+	__le32 *p = addr;
 	return le32_to_cpu(*p);
 }
 
@@ -83,16 +83,16 @@
 
 static inline void celleb_fake_config_writew(u32 val, void *addr)
 {
-	u16 val16;
-	u16 *p = addr;
+	__le16 val16;
+	__le16 *p = addr;
 	val16 = cpu_to_le16(val);
 	*p = val16;
 }
 
 static inline void celleb_fake_config_writel(u32 val, void *addr)
 {
-	u32 val32;
-	u32 *p = addr;
+	__le32 val32;
+	__le32 *p = addr;
 	val32 = cpu_to_le32(val);
 	*p = val32;
 }
diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c
index 0edbc0c..c11b39c 100644
--- a/arch/powerpc/platforms/celleb/scc_epci.c
+++ b/arch/powerpc/platforms/celleb/scc_epci.c
@@ -47,7 +47,7 @@
 #if 0 /* test code for epci dummy read */
 static void celleb_epci_dummy_read(struct pci_dev *dev)
 {
-	void *epci_base;
+	void __iomem *epci_base;
 	struct device_node *node;
 	struct pci_controller *hose;
 	u32 val;
@@ -58,7 +58,7 @@
 	if (!hose)
 		return;
 
-	epci_base = (void *)hose->cfg_addr;
+	epci_base = hose->cfg_addr;
 
 	val = in_be32(epci_base + SCC_EPCI_WATRP);
 	iosync();
@@ -71,18 +71,18 @@
 					struct pci_controller *hose)
 {
 	void __iomem *addr;
-	addr = (void *)hose->cfg_addr + PCI_COMMAND;
+	addr = hose->cfg_addr + PCI_COMMAND;
 	out_be32(addr, in_be32(addr) | (PCI_STATUS_REC_MASTER_ABORT << 16));
 }
 
 static int celleb_epci_check_abort(struct pci_controller *hose,
-				   unsigned long addr)
+				   void __iomem *addr)
 {
 	void __iomem *reg, *epci_base;
 	u32 val;
 
 	iob();
-	epci_base = (void *)hose->cfg_addr;
+	epci_base = hose->cfg_addr;
 
 	reg = epci_base + PCI_COMMAND;
 	val = in_be32(reg);
@@ -108,23 +108,23 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static unsigned long celleb_epci_make_config_addr(struct pci_controller *hose,
+static void __iomem *celleb_epci_make_config_addr(struct pci_controller *hose,
 					unsigned int devfn, int where)
 {
-	unsigned long addr;
+	void __iomem *addr;
 	struct pci_bus *bus = hose->bus;
 
 	if (bus->self)
-		addr = (unsigned long)hose->cfg_data +
+		addr = hose->cfg_data +
 		       (((bus->number & 0xff) << 16)
 		        | ((devfn & 0xff) << 8)
 		        | (where & 0xff)
 		        | 0x01000000);
 	else
-		addr = (unsigned long)hose->cfg_data +
+		addr = hose->cfg_data +
 		       (((devfn & 0xff) << 8) | (where & 0xff));
 
-	pr_debug("EPCI: config_addr = 0x%016lx\n", addr);
+	pr_debug("EPCI: config_addr = 0x%p\n", addr);
 
 	return addr;
 }
@@ -132,7 +132,7 @@
 static int celleb_epci_read_config(struct pci_bus *bus,
 			unsigned int devfn, int where, int size, u32 * val)
 {
-	unsigned long addr;
+	void __iomem *addr;
 	struct device_node *node;
 	struct pci_controller *hose;
 
@@ -148,17 +148,17 @@
 	if (bus->number == hose->first_busno && devfn == 0) {
 		/* EPCI controller self */
 
-		addr = (unsigned long)hose->cfg_addr + where;
+		addr = hose->cfg_addr + where;
 
 		switch (size) {
 		case 1:
-			*val = in_8((u8 *)addr);
+			*val = in_8(addr);
 			break;
 		case 2:
-			*val = in_be16((u16 *)addr);
+			*val = in_be16(addr);
 			break;
 		case 4:
-			*val = in_be32((u32 *)addr);
+			*val = in_be32(addr);
 			break;
 		default:
 			return PCIBIOS_DEVICE_NOT_FOUND;
@@ -171,13 +171,13 @@
 
 		switch (size) {
 		case 1:
-			*val = in_8((u8 *)addr);
+			*val = in_8(addr);
 			break;
 		case 2:
-			*val = in_le16((u16 *)addr);
+			*val = in_le16(addr);
 			break;
 		case 4:
-			*val = in_le32((u32 *)addr);
+			*val = in_le32(addr);
 			break;
 		default:
 			return PCIBIOS_DEVICE_NOT_FOUND;
@@ -188,13 +188,13 @@
 		 "addr=0x%lx, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
 		 addr, devfn, where, size, *val);
 
-	return celleb_epci_check_abort(hose, 0);
+	return celleb_epci_check_abort(hose, NULL);
 }
 
 static int celleb_epci_write_config(struct pci_bus *bus,
 			unsigned int devfn, int where, int size, u32 val)
 {
-	unsigned long addr;
+	void __iomem *addr;
 	struct device_node *node;
 	struct pci_controller *hose;
 
@@ -210,17 +210,17 @@
 	if (bus->number == hose->first_busno && devfn == 0) {
 		/* EPCI controller self */
 
-		addr = (unsigned long)hose->cfg_addr + where;
+		addr = hose->cfg_addr + where;
 
 		switch (size) {
 		case 1:
-			out_8((u8 *)addr, val);
+			out_8(addr, val);
 			break;
 		case 2:
-			out_be16((u16 *)addr, val);
+			out_be16(addr, val);
 			break;
 		case 4:
-			out_be32((u32 *)addr, val);
+			out_be32(addr, val);
 			break;
 		default:
 			return PCIBIOS_DEVICE_NOT_FOUND;
@@ -233,13 +233,13 @@
 
 		switch (size) {
 		case 1:
-			out_8((u8 *)addr, val);
+			out_8(addr, val);
 			break;
 		case 2:
-			out_le16((u16 *)addr, val);
+			out_le16(addr, val);
 			break;
 		case 4:
-			out_le32((u32 *)addr, val);
+			out_le32(addr, val);
 			break;
 		default:
 			return PCIBIOS_DEVICE_NOT_FOUND;
@@ -261,7 +261,7 @@
 	void __iomem *reg, *epci_base;
 	int hwres = 0;
 
-	epci_base = (void *)hose->cfg_addr;
+	epci_base = hose->cfg_addr;
 
 	/* PCI core reset(Internal bus and PCI clock) */
 	reg = epci_base + SCC_EPCI_CKCTRL;
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index 1de63ac..5f4d0d9 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -137,10 +137,12 @@
 	return -ENODEV;
 }
 
+#ifdef CONFIG_KEXEC
 static void celleb_kexec_cpu_down(int crash, int secondary)
 {
 	beatic_deinit_IRQ();
 }
+#endif
 
 static struct of_device_id celleb_bus_ids[] = {
 	{ .type = "scc", },
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index e1f51d4..117c9a0 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -75,7 +75,7 @@
 extern unsigned long loops_per_jiffy;
 
 /* To be replaced by RTAS when available */
-static unsigned int *briq_SPOR;
+static unsigned int __iomem *briq_SPOR;
 
 #ifdef CONFIG_SMP
 extern struct smp_ops_t chrp_smp_ops;
@@ -267,7 +267,7 @@
 	} else if (machine && strncmp(machine, "TotalImpact,BRIQ-1", 18) == 0) {
 		_chrp_type = _CHRP_briq;
 		/* Map the SPOR register on briq and change the restart hook */
-		briq_SPOR = (unsigned int *)ioremap(0xff0000e8, 4);
+		briq_SPOR = ioremap(0xff0000e8, 4);
 		ppc_md.restart = briq_restart;
 	} else {
 		/* Let's assume it is an IBM chrp if all else fails */
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index 61599d9..3f6c411 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -13,7 +13,6 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/initrd.h>
-#include <linux/root_dev.h>
 #include <linux/mtd/physmap.h>
 
 #include <asm/time.h>
@@ -91,17 +90,6 @@
 			       ARRAY_SIZE(linkstation_physmap_partitions));
 #endif
 
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
-		ROOT_DEV = Root_RAM0;
-	else
-#endif
-#ifdef	CONFIG_ROOT_NFS
-		ROOT_DEV = Root_NFS;
-#else
-		ROOT_DEV = Root_HDA1;
-#endif
-
 	/* Lookup PCI host bridges */
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
 		add_bridge(np);
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index c1f4502..91df52a 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -308,7 +308,7 @@
 	return single_open(file, proc_lpevents_show, NULL);
 }
 
-static struct file_operations proc_lpevents_operations = {
+static const struct file_operations proc_lpevents_operations = {
 	.open		= proc_lpevents_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index 1ad0e4a..b1187d9 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -1224,7 +1224,7 @@
 	return rc;
 }
 
-static struct file_operations proc_vmlinux_operations = {
+static const struct file_operations proc_vmlinux_operations = {
 	.write		= proc_mf_change_vmlinux,
 };
 
@@ -1253,7 +1253,6 @@
 		ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf);
 		if (!ent)
 			return 1;
-		ent->nlink = 1;
 		ent->data = (void *)(long)i;
 		ent->read_proc = proc_mf_dump_cmdline;
 		ent->write_proc = proc_mf_change_cmdline;
@@ -1264,7 +1263,6 @@
 		ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf);
 		if (!ent)
 			return 1;
-		ent->nlink = 1;
 		ent->data = (void *)(long)i;
 		ent->proc_fops = &proc_vmlinux_operations;
 	}
@@ -1272,7 +1270,6 @@
 	ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
 	if (!ent)
 		return 1;
-	ent->nlink = 1;
 	ent->data = (void *)0;
 	ent->read_proc = proc_mf_dump_side;
 	ent->write_proc = proc_mf_change_side;
@@ -1280,7 +1277,6 @@
 	ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
 	if (!ent)
 		return 1;
-	ent->nlink = 1;
 	ent->data = (void *)0;
 	ent->read_proc = proc_mf_dump_src;
 	ent->write_proc = proc_mf_change_src;
diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c
index b54e371..f2cde41 100644
--- a/arch/powerpc/platforms/iseries/proc.c
+++ b/arch/powerpc/platforms/iseries/proc.c
@@ -101,7 +101,7 @@
 	return single_open(file, proc_titantod_show, NULL);
 }
 
-static struct file_operations proc_titantod_operations = {
+static const struct file_operations proc_titantod_operations = {
 	.open		= proc_titantod_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index a6799ed..e2100ec 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -173,7 +173,7 @@
 	return single_open(file, proc_viopath_show, NULL);
 }
 
-static struct file_operations proc_viopath_operations = {
+static const struct file_operations proc_viopath_operations = {
 	.open		= proc_viopath_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index c3a8941..de7440e 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -37,21 +37,20 @@
  */
 static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);
 
-/* Protect the pmac_backlight variable */
+/* Protect the pmac_backlight variable below.
+   You should hold this lock when using the pmac_backlight pointer to
+   prevent its potential removal. */
 DEFINE_MUTEX(pmac_backlight_mutex);
 
 /* Main backlight storage
  *
- * Backlight drivers in this variable are required to have the "props"
+ * Backlight drivers in this variable are required to have the "ops"
  * attribute set and to have an update_status function.
  *
  * We can only store one backlight here, but since Apple laptops have only one
  * internal display, it doesn't matter. Other backlight drivers can be used
  * independently.
  *
- * Lock ordering:
- * pmac_backlight_mutex (global, main backlight)
- *   pmac_backlight->sem (backlight class)
  */
 struct backlight_device *pmac_backlight;
 
@@ -104,8 +103,7 @@
 		struct backlight_properties *props;
 		int brightness;
 
-		down(&pmac_backlight->sem);
-		props = pmac_backlight->props;
+		props = &pmac_backlight->props;
 
 		brightness = props->brightness +
 			((pmac_backlight_key_queued?-1:1) *
@@ -117,9 +115,7 @@
 			brightness = props->max_brightness;
 
 		props->brightness = brightness;
-		props->update_status(pmac_backlight);
-
-		up(&pmac_backlight->sem);
+		backlight_update_status(pmac_backlight);
 	}
 	mutex_unlock(&pmac_backlight_mutex);
 }
@@ -145,8 +141,7 @@
 	if (pmac_backlight) {
 		struct backlight_properties *props;
 
-		down(&pmac_backlight->sem);
-		props = pmac_backlight->props;
+		props = &pmac_backlight->props;
 		props->brightness = brightness *
 			(props->max_brightness + 1) /
 			(OLD_BACKLIGHT_MAX + 1);
@@ -156,8 +151,7 @@
 		else if (props->brightness < 0)
 			props->brightness = 0;
 
-		props->update_status(pmac_backlight);
-		up(&pmac_backlight->sem);
+		backlight_update_status(pmac_backlight);
 
 		error = 0;
 	}
@@ -196,14 +190,11 @@
 	if (pmac_backlight) {
 		struct backlight_properties *props;
 
-		down(&pmac_backlight->sem);
-		props = pmac_backlight->props;
+		props = &pmac_backlight->props;
 
 		result = props->brightness *
 			(OLD_BACKLIGHT_MAX + 1) /
 			(props->max_brightness + 1);
-
-		up(&pmac_backlight->sem);
 	}
 	mutex_unlock(&pmac_backlight_mutex);
 
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 39db128..5e5c0e4 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -305,8 +305,6 @@
 	level = !!(level_mask[hw >> 5] & (1UL << (hw & 0x1f)));
 	if (level)
 		desc->status |= IRQ_LEVEL;
-	else
-		desc->status |= IRQ_DELAYED_DISABLE;
 	set_irq_chip_and_handler(virq, &pmac_pic, level ?
 				 handle_level_irq : handle_edge_irq);
 	return 0;
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index d949e9df..651fa42 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -506,8 +506,8 @@
 	if ((goodness <= current_root_goodness) &&
 	    ROOT_DEV != DEFAULT_ROOT_DEVICE)
 		return;
-	p = strstr(saved_command_line, "root=");
-	if (p != NULL && (p == saved_command_line || p[-1] == ' '))
+	p = strstr(boot_command_line, "root=");
+	if (p != NULL && (p == boot_command_line || p[-1] == ' '))
 		return;
 
 	if (!found_boot) {
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index de52ec4..d270a1e 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -51,4 +51,25 @@
 	  including the System Manager and AV Settings.  In
 	  general, all users will say Y.
 
+config PS3_PS3AV
+	tristate "PS3 AV settings driver"
+	depends on PPC_PS3
+	select PS3_VUART
+	default y
+	help
+	  Include support for the PS3 AV Settings driver.
+
+	  This support is required for graphics and sound. In
+	  general, all users will say Y or M.
+
+config PS3_SYS_MANAGER
+	bool "PS3 System Manager driver"
+	select PS3_VUART
+	default y
+	help
+	  Include support for the PS3 System Manager.
+
+	  This support is required for system control.  In
+	  general, all users will say Y.
+
 endmenu
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index a4b5a1b..e12e59f 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -2,7 +2,7 @@
  *  PS3 pagetable management routines.
  *
  *  Copyright (C) 2006 Sony Computer Entertainment Inc.
- *  Copyright 2006 Sony Corp.
+ *  Copyright 2006, 2007 Sony 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
@@ -24,6 +24,7 @@
 #include <asm/lmb.h>
 #include <asm/udbg.h>
 #include <asm/lv1call.h>
+#include <asm/ps3fb.h>
 
 #include "platform.h"
 
@@ -233,6 +234,9 @@
 
 static void ps3_hpte_clear(void)
 {
+	/* Make sure to clean up the frame buffer device first */
+	ps3fb_cleanup();
+
 	lv1_unmap_htab(htab_addr);
 }
 
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index bb17283..631c300 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -194,6 +194,7 @@
 
 	return result;
 }
+EXPORT_SYMBOL_GPL(ps3_alloc_io_irq);
 
 int ps3_free_io_irq(unsigned int virq)
 {
@@ -209,6 +210,7 @@
 
 	return result;
 }
+EXPORT_SYMBOL_GPL(ps3_free_io_irq);
 
 /**
  * ps3_alloc_event_irq - Allocate a virq for use with a system event.
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index e62505e..ac5df96 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -24,6 +24,7 @@
 #include <linux/root_dev.h>
 #include <linux/console.h>
 #include <linux/kexec.h>
+#include <linux/bootmem.h>
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
@@ -41,6 +42,10 @@
 #define DBG(fmt...) do{if(0)printk(fmt);}while(0)
 #endif
 
+#if !defined(CONFIG_SMP)
+static void smp_send_stop(void) {}
+#endif
+
 int ps3_get_firmware_version(union ps3_firmware_version *v)
 {
 	int result = lv1_get_version_info(&v->raw);
@@ -65,21 +70,74 @@
 	lv1_pause(0);
 }
 
+static void ps3_restart(char *cmd)
+{
+	DBG("%s:%d cmd '%s'\n", __func__, __LINE__, cmd);
+
+	smp_send_stop();
+	ps3_sys_manager_restart(); /* never returns */
+}
+
+static void ps3_power_off(void)
+{
+	DBG("%s:%d\n", __func__, __LINE__);
+
+	smp_send_stop();
+	ps3_sys_manager_power_off(); /* never returns */
+}
+
 static void ps3_panic(char *str)
 {
 	DBG("%s:%d %s\n", __func__, __LINE__, str);
 
-#ifdef CONFIG_SMP
 	smp_send_stop();
-#endif
 	printk("\n");
 	printk("   System does not reboot automatically.\n");
 	printk("   Please press POWER button.\n");
 	printk("\n");
 
-	for (;;) ;
+	while(1);
 }
 
+static void prealloc(struct ps3_prealloc *p)
+{
+	if (!p->size)
+		return;
+
+	p->address = __alloc_bootmem(p->size, p->align, __pa(MAX_DMA_ADDRESS));
+	if (!p->address) {
+		printk(KERN_ERR "%s: Cannot allocate %s\n", __FUNCTION__,
+		       p->name);
+		return;
+	}
+
+	printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size,
+	       p->address);
+}
+
+#ifdef CONFIG_FB_PS3
+struct ps3_prealloc ps3fb_videomemory = {
+    .name = "ps3fb videomemory",
+    .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
+    .align = 1024*1024			/* the GPU requires 1 MiB alignment */
+};
+#define prealloc_ps3fb_videomemory()	prealloc(&ps3fb_videomemory)
+
+static int __init early_parse_ps3fb(char *p)
+{
+	if (!p)
+		return 1;
+
+	ps3fb_videomemory.size = _ALIGN_UP(memparse(p, &p),
+					   ps3fb_videomemory.align);
+	return 0;
+}
+early_param("ps3fb", early_parse_ps3fb);
+#else
+#define prealloc_ps3fb_videomemory()	do { } while (0)
+#endif
+
+
 static void __init ps3_setup_arch(void)
 {
 	union ps3_firmware_version v;
@@ -101,6 +159,7 @@
 	conswitchp = &dummy_con;
 #endif
 
+	prealloc_ps3fb_videomemory();
 	ppc_md.power_save = ps3_power_save;
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
@@ -177,6 +236,8 @@
 	.get_rtc_time			= ps3_get_rtc_time,
 	.calibrate_decr			= ps3_calibrate_decr,
 	.progress			= ps3_progress,
+	.restart			= ps3_restart,
+	.power_off			= ps3_power_off,
 #if defined(CONFIG_KEXEC)
 	.kexec_cpu_down			= ps3_kexec_cpu_down,
 	.machine_kexec			= ps3_machine_kexec,
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
index d192972..a397e4e 100644
--- a/arch/powerpc/platforms/ps3/spu.c
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -170,31 +170,6 @@
 	return result;
 }
 
-static int __init add_spu_pages(unsigned long start_addr, unsigned long size)
-{
-	int result;
-	unsigned long start_pfn;
-	unsigned long nr_pages;
-	struct pglist_data *pgdata;
-	struct zone *zone;
-
-	BUG_ON(!mem_init_done);
-
-	start_pfn = start_addr >> PAGE_SHIFT;
-	nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
-	pgdata = NODE_DATA(0);
-	zone = pgdata->node_zones;
-
-	result = __add_pages(zone, start_pfn, nr_pages);
-
-	if (result)
-		pr_debug("%s:%d: __add_pages failed: (%d)\n",
-			__func__, __LINE__, result);
-
-	return result;
-}
-
 static void spu_unmap(struct spu *spu)
 {
 	iounmap(spu->priv2);
@@ -206,19 +181,6 @@
 static int __init setup_areas(struct spu *spu)
 {
 	struct table {char* name; unsigned long addr; unsigned long size;};
-	int result;
-
-	/* setup pages */
-
-	result = add_spu_pages(spu->local_store_phys, LS_SIZE);
-	if (result)
-		goto fail_add;
-
-	result = add_spu_pages(spu->problem_phys, sizeof(struct spu_problem));
-	if (result)
-		goto fail_add;
-
-	/* ioremap */
 
 	spu_pdata(spu)->shadow = __ioremap(
 		spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow),
@@ -260,8 +222,8 @@
 
 fail_ioremap:
 	spu_unmap(spu);
-fail_add:
-	return result;
+
+	return -ENOMEM;
 }
 
 static int __init setup_interrupts(struct spu *spu)
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index bce6136..a9f7e4a 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -57,6 +57,7 @@
 	dump_mmio_region(r);
 	return result;
 }
+EXPORT_SYMBOL_GPL(ps3_mmio_region_create);
 
 int ps3_free_mmio_region(struct ps3_mmio_region *r)
 {
@@ -72,6 +73,7 @@
 	r->lpar_addr = 0;
 	return result;
 }
+EXPORT_SYMBOL_GPL(ps3_free_mmio_region);
 
 static int ps3_system_bus_match(struct device *_dev,
 	struct device_driver *_drv)
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 69590fb..2dfd050 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -4,11 +4,12 @@
 
 obj-y			:= pci.o lpar.o hvCall.o nvram.o reconfig.o \
 			   setup.o iommu.o ras.o rtasd.o pci_dlpar.o \
-			   firmware.o
+			   firmware.o power.o
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_XICS)	+= xics.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
 obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o
+obj-$(CONFIG_KEXEC)	+= kexec.o
 
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug-cpu.o
 
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 9437f48..6cedbc0 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -1078,7 +1078,7 @@
 	return single_open(file, proc_eeh_show, NULL);
 }
 
-static struct file_operations proc_eeh_operations = {
+static const struct file_operations proc_eeh_operations = {
 	.open      = proc_eeh_open,
 	.read      = seq_read,
 	.llseek    = seq_lseek,
diff --git a/arch/powerpc/platforms/pseries/firmware.h b/arch/powerpc/platforms/pseries/firmware.h
deleted file mode 100644
index 714f56f..0000000
--- a/arch/powerpc/platforms/pseries/firmware.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2006 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.
- */
-
-#ifndef _PSERIES_FIRMWARE_H
-#define _PSERIES_FIRMWARE_H
-
-#include <asm/firmware.h>
-
-extern void __init fw_feature_init(void);
-
-#endif /* _PSERIES_FIRMWARE_H */
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
index 3ddc049..eae51ef 100644
--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
+++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -90,7 +90,7 @@
 	return rc;
 }
 
-static struct file_operations hcall_inst_seq_fops = {
+static const struct file_operations hcall_inst_seq_fops = {
 	.open = hcall_inst_seq_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c
new file mode 100644
index 0000000..af26856
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/kexec.c
@@ -0,0 +1,72 @@
+/*
+ *  Copyright 2006 Michael Ellerman, 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.
+ */
+
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/firmware.h>
+#include <asm/kexec.h>
+#include <asm/mpic.h>
+
+#include "pseries.h"
+#include "xics.h"
+#include "plpar_wrappers.h"
+
+static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
+{
+	/* Don't risk a hypervisor call if we're crashing */
+	if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
+		unsigned long addr;
+
+		addr = __pa(get_slb_shadow());
+		if (unregister_slb_shadow(hard_smp_processor_id(), addr))
+			printk("SLB shadow buffer deregistration of "
+			       "cpu %u (hw_cpu_id %d) failed\n",
+			       smp_processor_id(),
+			       hard_smp_processor_id());
+
+		addr = __pa(get_lppaca());
+		if (unregister_vpa(hard_smp_processor_id(), addr)) {
+			printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
+					"failed\n", smp_processor_id(),
+					hard_smp_processor_id());
+		}
+	}
+}
+
+static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary)
+{
+	pseries_kexec_cpu_down(crash_shutdown, secondary);
+	mpic_teardown_this_cpu(secondary);
+}
+
+void __init setup_kexec_cpu_down_mpic(void)
+{
+	ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_mpic;
+}
+
+static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary)
+{
+	pseries_kexec_cpu_down(crash_shutdown, secondary);
+	xics_teardown_cpu(secondary);
+}
+
+void __init setup_kexec_cpu_down_xics(void)
+{
+	ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics;
+}
+
+static int __init pseries_kexec_setup(void)
+{
+	ppc_md.machine_kexec = default_machine_kexec;
+	ppc_md.machine_kexec_prepare = default_machine_kexec_prepare;
+	ppc_md.machine_crash_shutdown = default_machine_crash_shutdown;
+
+	return 0;
+}
+__initcall(pseries_kexec_setup);
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index c69bd15..fa59124 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -98,6 +98,10 @@
 		if (dev->resource[i].flags & IORESOURCE_IO
 		    && dev->bus->number == 0 && dev->devfn == 0x81)
 			dev->resource[i].flags &= ~IORESOURCE_IO;
+		if (dev->resource[i].start == 0 && dev->resource[i].end) {
+			dev->resource[i].flags = 0;
+			dev->resource[i].end = 0;
+		}
 	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c
new file mode 100644
index 0000000..2624b71
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/power.c
@@ -0,0 +1,87 @@
+/*
+ *  Interface for power-management for ppc64 compliant platform
+ *
+ *  Manish Ahuja <mahuja@us.ibm.com>
+ *
+ *  Feb 2007
+ *
+ *  Copyright (C) 2007 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; version 2 of the License.
+ *
+ *  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/kobject.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+unsigned long rtas_poweron_auto; /* default and normal state is 0 */
+
+static ssize_t auto_poweron_show(struct subsystem *subsys, char *buf)
+{
+        return sprintf(buf, "%lu\n", rtas_poweron_auto);
+}
+
+static ssize_t
+auto_poweron_store(struct subsystem *subsys, const char *buf, size_t n)
+{
+	int ret;
+	unsigned long ups_restart;
+	ret = sscanf(buf, "%lu", &ups_restart);
+
+	if ((ret == 1) && ((ups_restart == 1) || (ups_restart == 0))){
+		rtas_poweron_auto = ups_restart;
+		return n;
+	}
+	return -EINVAL;
+}
+
+static struct subsys_attribute auto_poweron_attr = {
+        .attr   = {
+                .name = __stringify(auto_poweron),
+                .mode = 0644,
+        },
+        .show   = auto_poweron_show,
+        .store  = auto_poweron_store,
+};
+
+#ifndef CONFIG_PM
+decl_subsys(power,NULL,NULL);
+
+static struct attribute *g[] = {
+        &auto_poweron_attr.attr,
+        NULL,
+};
+
+static struct attribute_group attr_group = {
+        .attrs = g,
+};
+
+static int __init pm_init(void)
+{
+        int error = subsystem_register(&power_subsys);
+        if (!error)
+                error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+        return error;
+}
+core_initcall(pm_init);
+#else
+extern struct subsystem power_subsys;
+
+static int __init apo_pm_init(void)
+{
+	return (subsys_create_file(&power_subsys, &auto_poweron_attr));
+}
+__initcall(apo_pm_init);
+#endif
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
new file mode 100644
index 0000000..22bc019
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2006 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.
+ */
+
+#ifndef _PSERIES_PSERIES_H
+#define _PSERIES_PSERIES_H
+
+extern void __init fw_feature_init(void);
+
+struct pt_regs;
+
+extern int pSeries_system_reset_exception(struct pt_regs *regs);
+extern int pSeries_machine_check_exception(struct pt_regs *regs);
+
+#ifdef CONFIG_SMP
+extern void smp_init_pseries_mpic(void);
+extern void smp_init_pseries_xics(void);
+#else
+static inline smp_init_pseries_mpic(void) { };
+static inline smp_init_pseries_xics(void) { };
+#endif
+
+#ifdef CONFIG_KEXEC
+extern void setup_kexec_cpu_down_xics(void);
+extern void setup_kexec_cpu_down_mpic(void);
+#else
+static inline void setup_kexec_cpu_down_xics(void) { }
+static inline void setup_kexec_cpu_down_mpic(void) { }
+#endif
+
+/* Poweron flag used for enabling auto ups restart */
+extern unsigned long rtas_poweron_auto;
+
+#endif /* _PSERIES_PSERIES_H */
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index b1d3d16..edc0388 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -51,7 +51,7 @@
 #include <asm/udbg.h>
 #include <asm/firmware.h>
 
-#include "ras.h"
+#include "pseries.h"
 
 static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
 static DEFINE_SPINLOCK(ras_log_buf_lock);
diff --git a/arch/powerpc/platforms/pseries/ras.h b/arch/powerpc/platforms/pseries/ras.h
deleted file mode 100644
index 0e66b0d..0000000
--- a/arch/powerpc/platforms/pseries/ras.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _PSERIES_RAS_H
-#define _PSERIES_RAS_H
-
-struct pt_regs;
-
-extern int pSeries_system_reset_exception(struct pt_regs *regs);
-extern int pSeries_machine_check_exception(struct pt_regs *regs);
-
-#endif /* _PSERIES_RAS_H */
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 4ad33e4..5aa97af 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -499,7 +499,7 @@
 	return rv ? rv : count;
 }
 
-static struct file_operations ofdt_fops = {
+static const struct file_operations ofdt_fops = {
 	.write = ofdt_write
 };
 
@@ -513,7 +513,6 @@
 
 	ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
 	if (ent) {
-		ent->nlink = 1;
 		ent->data = NULL;
 		ent->size = 0;
 		ent->proc_fops = &ofdt_fops;
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index 8ca2612..77d0937 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -331,7 +331,7 @@
 	return 0;
 }
 
-struct file_operations proc_rtas_log_operations = {
+const struct file_operations proc_rtas_log_operations = {
 	.read =		rtas_log_read,
 	.poll =		rtas_log_poll,
 	.open =		rtas_log_open,
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 45368a5..8e1ef16 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -184,7 +184,7 @@
 	return 0;
 }
 
-struct file_operations scanlog_fops = {
+const struct file_operations scanlog_fops = {
 	.owner		= THIS_MODULE,
 	.read		= scanlog_read,
 	.write		= scanlog_write,
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 042ecae..34aff47 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -55,7 +55,6 @@
 #include <asm/dma.h>
 #include <asm/machdep.h>
 #include <asm/irq.h>
-#include <asm/kexec.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
 #include "xics.h"
@@ -65,10 +64,10 @@
 #include <asm/i8259.h>
 #include <asm/udbg.h>
 #include <asm/smp.h>
+#include <asm/firmware.h>
 
 #include "plpar_wrappers.h"
-#include "ras.h"
-#include "firmware.h"
+#include "pseries.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -77,8 +76,6 @@
 #endif
 
 /* move those away to a .h */
-extern void smp_init_pseries_mpic(void);
-extern void smp_init_pseries_xics(void);
 extern void find_udbg_vterm(void);
 
 int fwnmi_active;  /* TRUE if an FWNMI handler is present */
@@ -221,42 +218,6 @@
 		get_lppaca()->pmcregs_in_use = 1;
 }
 
-#ifdef CONFIG_KEXEC
-static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
-{
-	/* Don't risk a hypervisor call if we're crashing */
-	if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
-		unsigned long addr;
-
-		addr = __pa(get_slb_shadow());
-		if (unregister_slb_shadow(hard_smp_processor_id(), addr))
-			printk("SLB shadow buffer deregistration of "
-			       "cpu %u (hw_cpu_id %d) failed\n",
-			       smp_processor_id(),
-			       hard_smp_processor_id());
-
-		addr = __pa(get_lppaca());
-		if (unregister_vpa(hard_smp_processor_id(), addr)) {
-			printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
-					"failed\n", smp_processor_id(),
-					hard_smp_processor_id());
-		}
-	}
-}
-
-static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary)
-{
-	pseries_kexec_cpu_down(crash_shutdown, secondary);
-	mpic_teardown_this_cpu(secondary);
-}
-
-static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary)
-{
-	pseries_kexec_cpu_down(crash_shutdown, secondary);
-	xics_teardown_cpu(secondary);
-}
-#endif /* CONFIG_KEXEC */
-
 static void __init pseries_discover_pic(void)
 {
 	struct device_node *np;
@@ -269,21 +230,13 @@
 			pSeries_mpic_node = of_node_get(np);
 			ppc_md.init_IRQ       = pseries_mpic_init_IRQ;
 			ppc_md.get_irq        = mpic_get_irq;
-#ifdef CONFIG_KEXEC
-			ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_mpic;
-#endif
-#ifdef CONFIG_SMP
+			setup_kexec_cpu_down_mpic();
 			smp_init_pseries_mpic();
-#endif
 			return;
 		} else if (strstr(typep, "ppc-xicp")) {
 			ppc_md.init_IRQ       = xics_init_IRQ;
-#ifdef CONFIG_KEXEC
-			ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics;
-#endif
-#ifdef CONFIG_SMP
+			setup_kexec_cpu_down_xics();
 			smp_init_pseries_xics();
-#endif
 			return;
 		}
 	}
@@ -533,6 +486,34 @@
 	return PCI_PROBE_NORMAL;
 }
 
+/**
+ * pSeries_power_off - tell firmware about how to power off the system.
+ *
+ * This function calls either the power-off rtas token in normal cases
+ * or the ibm,power-off-ups token (if present & requested) in case of
+ * a power failure. If power-off token is used, power on will only be
+ * possible with power button press. If ibm,power-off-ups token is used
+ * it will allow auto poweron after power is restored.
+ */
+void pSeries_power_off(void)
+{
+	int rc;
+	int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups");
+
+	if (rtas_flash_term_hook)
+		rtas_flash_term_hook(SYS_POWER_OFF);
+
+	if (rtas_poweron_auto == 0 ||
+		rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) {
+		rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1);
+		printk(KERN_INFO "RTAS power-off returned %d\n", rc);
+	} else {
+		rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL);
+		printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc);
+	}
+	for (;;);
+}
+
 define_machine(pseries) {
 	.name			= "pSeries",
 	.probe			= pSeries_probe,
@@ -543,7 +524,7 @@
 	.pcibios_fixup		= pSeries_final_fixup,
 	.pci_probe_mode		= pSeries_pci_probe_mode,
 	.restart		= rtas_restart,
-	.power_off		= rtas_power_off,
+	.power_off		= pSeries_power_off,
 	.halt			= rtas_halt,
 	.panic			= rtas_os_term,
 	.get_boot_time		= rtas_get_boot_time,
@@ -554,9 +535,4 @@
 	.check_legacy_ioport	= pSeries_check_legacy_ioport,
 	.system_reset_exception = pSeries_system_reset_exception,
 	.machine_check_exception = pSeries_machine_check_exception,
-#ifdef CONFIG_KEXEC
-	.machine_kexec		= default_machine_kexec,
-	.machine_kexec_prepare	= default_machine_kexec_prepare,
-	.machine_crash_shutdown	= default_machine_crash_shutdown,
-#endif
 };
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 4408518..116305b 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -48,6 +48,7 @@
 #include <asm/vdso_datapage.h>
 
 #include "plpar_wrappers.h"
+#include "pseries.h"
 
 #ifdef DEBUG
 #include <asm/udbg.h>
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 85dcdf1..26ca3ff 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -7,6 +7,7 @@
 obj-$(CONFIG_PPC_MPC106)	+= grackle.o
 obj-$(CONFIG_PPC_DCR)		+= dcr.o
 obj-$(CONFIG_PPC_DCR_NATIVE)	+= dcr-low.o
+obj-$(CONFIG_PPC_PMI)		+= pmi.o
 obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 9f2a9a4..d20f0292 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -233,14 +233,7 @@
 			goto err;
 		}
 
-		mac_addr = get_property(np, "local-mac-address", NULL);
-		if (mac_addr == NULL)
-			mac_addr = get_property(np, "mac-address", NULL);
-		if (mac_addr == NULL) {
-			/* Obsolete */
-			mac_addr = get_property(np, "address", NULL);
-		}
-
+		mac_addr = of_get_mac_address(np);
 		if (mac_addr)
 			memcpy(gfar_data.mac_addr, mac_addr, 6);
 
@@ -441,7 +434,8 @@
 {
 	struct device_node *np;
 	unsigned int i;
-	struct platform_device *usb_dev_mph = NULL, *usb_dev_dr = NULL;
+	struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
+		*usb_dev_dr_client = NULL;
 	int ret;
 
 	for (np = NULL, i = 0;
@@ -507,33 +501,72 @@
 
 		of_irq_to_resource(np, 0, &r[1]);
 
-		usb_dev_dr =
-		    platform_device_register_simple("fsl-ehci", i, r, 2);
-		if (IS_ERR(usb_dev_dr)) {
-			ret = PTR_ERR(usb_dev_dr);
+		prop = get_property(np, "dr_mode", NULL);
+
+		if (!prop || !strcmp(prop, "host")) {
+			usb_data.operating_mode = FSL_USB2_DR_HOST;
+			usb_dev_dr_host = platform_device_register_simple(
+					"fsl-ehci", i, r, 2);
+			if (IS_ERR(usb_dev_dr_host)) {
+				ret = PTR_ERR(usb_dev_dr_host);
+				goto err;
+			}
+		} else if (prop && !strcmp(prop, "peripheral")) {
+			usb_data.operating_mode = FSL_USB2_DR_DEVICE;
+			usb_dev_dr_client = platform_device_register_simple(
+					"fsl-usb2-udc", i, r, 2);
+			if (IS_ERR(usb_dev_dr_client)) {
+				ret = PTR_ERR(usb_dev_dr_client);
+				goto err;
+			}
+		} else if (prop && !strcmp(prop, "otg")) {
+			usb_data.operating_mode = FSL_USB2_DR_OTG;
+			usb_dev_dr_host = platform_device_register_simple(
+					"fsl-ehci", i, r, 2);
+			if (IS_ERR(usb_dev_dr_host)) {
+				ret = PTR_ERR(usb_dev_dr_host);
+				goto err;
+			}
+			usb_dev_dr_client = platform_device_register_simple(
+					"fsl-usb2-udc", i, r, 2);
+			if (IS_ERR(usb_dev_dr_client)) {
+				ret = PTR_ERR(usb_dev_dr_client);
+				goto err;
+			}
+		} else {
+			ret = -EINVAL;
 			goto err;
 		}
 
-		usb_dev_dr->dev.coherent_dma_mask = 0xffffffffUL;
-		usb_dev_dr->dev.dma_mask = &usb_dev_dr->dev.coherent_dma_mask;
-
-		usb_data.operating_mode = FSL_USB2_DR_HOST;
-
 		prop = get_property(np, "phy_type", NULL);
 		usb_data.phy_mode = determine_usb_phy(prop);
 
-		ret =
-		    platform_device_add_data(usb_dev_dr, &usb_data,
-					     sizeof(struct
-						    fsl_usb2_platform_data));
-		if (ret)
-			goto unreg_dr;
+		if (usb_dev_dr_host) {
+			usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
+			usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
+				dev.coherent_dma_mask;
+			if ((ret = platform_device_add_data(usb_dev_dr_host,
+						&usb_data, sizeof(struct
+						fsl_usb2_platform_data))))
+				goto unreg_dr;
+		}
+		if (usb_dev_dr_client) {
+			usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
+			usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
+				dev.coherent_dma_mask;
+			if ((ret = platform_device_add_data(usb_dev_dr_client,
+						&usb_data, sizeof(struct
+						fsl_usb2_platform_data))))
+				goto unreg_dr;
+		}
 	}
 	return 0;
 
 unreg_dr:
-	if (usb_dev_dr)
-		platform_device_unregister(usb_dev_dr);
+	if (usb_dev_dr_host)
+		platform_device_unregister(usb_dev_dr_host);
+	if (usb_dev_dr_client)
+		platform_device_unregister(usb_dev_dr_client);
 unreg_mph:
 	if (usb_dev_mph)
 		platform_device_unregister(usb_dev_mph);
@@ -606,8 +639,9 @@
 			goto unreg;
 		}
 
-		mac_addr = get_property(np, "mac-address", NULL);
-		memcpy(fs_enet_data.macaddr, mac_addr, 6);
+		mac_addr = of_get_mac_address(np);
+		if (mac_addr)
+			memcpy(fs_enet_data.macaddr, mac_addr, 6);
 
 		ph = get_property(np, "phy-handle", NULL);
 		phy = of_find_node_by_phandle(*ph);
@@ -699,7 +733,7 @@
 				if (ret)
 					goto unreg;
 			}
-			
+
 			of_node_put(phy);
 			of_node_put(mdio);
 
@@ -891,8 +925,9 @@
 			goto err;
 		r[0].name = enet_regs;
 
-		mac_addr = (void *)get_property(np, "mac-address", NULL);
-		memcpy(fs_enet_data.macaddr, mac_addr, 6);
+		mac_addr = of_get_mac_address(np);
+		if (mac_addr)
+			memcpy(fs_enet_data.macaddr, mac_addr, 6);
 
 		ph = (phandle *) get_property(np, "phy-handle", NULL);
 		if (ph != NULL)
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index aa701cc..bcfb900 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1370,7 +1370,7 @@
 			printk(KERN_ERR "Failed to map IPI %d\n", i);
 			break;
 		}
-		request_irq(vipi, mpic_ipi_action, IRQF_DISABLED,
+		request_irq(vipi, mpic_ipi_action, IRQF_DISABLED|IRQF_PERCPU,
 			    ipi_names[i], mpic);
 	}
 }
@@ -1395,4 +1395,25 @@
 		break;
 	}
 }
+
+int __init smp_mpic_probe(void)
+{
+	int nr_cpus;
+
+	DBG("smp_mpic_probe()...\n");
+
+	nr_cpus = cpus_weight(cpu_possible_map);
+
+	DBG("nr_cpus: %d\n", nr_cpus);
+
+	if (nr_cpus > 1)
+		mpic_request_ipis();
+
+	return nr_cpus;
+}
+
+void __devinit smp_mpic_setup_cpu(int cpu)
+{
+	mpic_setup_this_cpu();
+}
 #endif /* CONFIG_SMP */
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
new file mode 100644
index 0000000..a528201
--- /dev/null
+++ b/arch/powerpc/sysdev/pmi.c
@@ -0,0 +1,305 @@
+/*
+ * pmi driver
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * PMI (Platform Management Interrupt) is a way to communicate
+ * with the BMC (Baseboard Management Controller) via interrupts.
+ * Unlike IPMI it is bidirectional and has a low latency.
+ *
+ * Author: Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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/interrupt.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+#include <asm/io.h>
+#include <asm/pmi.h>
+
+
+struct pmi_data {
+	struct list_head	handler;
+	spinlock_t		handler_spinlock;
+	spinlock_t		pmi_spinlock;
+	struct mutex		msg_mutex;
+	pmi_message_t		msg;
+	struct completion	*completion;
+	struct of_device	*dev;
+	int			irq;
+	u8 __iomem		*pmi_reg;
+	struct work_struct	work;
+};
+
+
+
+static void __iomem *of_iomap(struct device_node *np)
+{
+	struct resource res;
+
+	if (of_address_to_resource(np, 0, &res))
+		return NULL;
+
+	pr_debug("Resource start: 0x%lx\n", res.start);
+	pr_debug("Resource end: 0x%lx\n", res.end);
+
+	return ioremap(res.start, 1 + res.end - res.start);
+}
+
+
+static int pmi_irq_handler(int irq, void *dev_id)
+{
+	struct pmi_data *data;
+	u8 type;
+	int rc;
+
+	data = dev_id;
+
+	spin_lock(&data->pmi_spinlock);
+
+	type = ioread8(data->pmi_reg + PMI_READ_TYPE);
+	pr_debug("pmi: got message of type %d\n", type);
+
+	if (type & PMI_ACK && !data->completion) {
+		printk(KERN_WARNING "pmi: got unexpected ACK message.\n");
+		rc = -EIO;
+		goto unlock;
+	}
+
+	if (data->completion && !(type & PMI_ACK)) {
+		printk(KERN_WARNING "pmi: expected ACK, but got %d\n", type);
+		rc = -EIO;
+		goto unlock;
+	}
+
+	data->msg.type = type;
+	data->msg.data0 = ioread8(data->pmi_reg + PMI_READ_DATA0);
+	data->msg.data1 = ioread8(data->pmi_reg + PMI_READ_DATA1);
+	data->msg.data2 = ioread8(data->pmi_reg + PMI_READ_DATA2);
+	rc = 0;
+unlock:
+	spin_unlock(&data->pmi_spinlock);
+
+	if (rc == -EIO) {
+		rc = IRQ_HANDLED;
+		goto out;
+	}
+
+	if (data->msg.type & PMI_ACK) {
+		complete(data->completion);
+		rc = IRQ_HANDLED;
+		goto out;
+	}
+
+	schedule_work(&data->work);
+
+	rc = IRQ_HANDLED;
+out:
+	return rc;
+}
+
+
+static struct of_device_id pmi_match[] = {
+	{ .type = "ibm,pmi", .name = "ibm,pmi" },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, pmi_match);
+
+static void pmi_notify_handlers(struct work_struct *work)
+{
+	struct pmi_data *data;
+	struct pmi_handler *handler;
+
+	data = container_of(work, struct pmi_data, work);
+
+	spin_lock(&data->handler_spinlock);
+	list_for_each_entry(handler, &data->handler, node) {
+		pr_debug(KERN_INFO "pmi: notifying handler %p\n", handler);
+		if (handler->type == data->msg.type)
+			handler->handle_pmi_message(data->dev, data->msg);
+	}
+	spin_unlock(&data->handler_spinlock);
+}
+
+static int pmi_of_probe(struct of_device *dev,
+			const struct of_device_id *match)
+{
+	struct device_node *np = dev->node;
+	struct pmi_data *data;
+	int rc;
+
+	data = kzalloc(sizeof(struct pmi_data), GFP_KERNEL);
+	if (!data) {
+		printk(KERN_ERR "pmi: could not allocate memory.\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	data->pmi_reg = of_iomap(np);
+	if (!data->pmi_reg) {
+		printk(KERN_ERR "pmi: invalid register address.\n");
+		rc = -EFAULT;
+		goto error_cleanup_data;
+	}
+
+	INIT_LIST_HEAD(&data->handler);
+
+	mutex_init(&data->msg_mutex);
+	spin_lock_init(&data->pmi_spinlock);
+	spin_lock_init(&data->handler_spinlock);
+
+	INIT_WORK(&data->work, pmi_notify_handlers);
+
+	dev->dev.driver_data = data;
+	data->dev = dev;
+
+	data->irq = irq_of_parse_and_map(np, 0);
+	if (data->irq == NO_IRQ) {
+		printk(KERN_ERR "pmi: invalid interrupt.\n");
+		rc = -EFAULT;
+		goto error_cleanup_iomap;
+	}
+
+	rc = request_irq(data->irq, pmi_irq_handler, 0, "pmi", data);
+	if (rc) {
+		printk(KERN_ERR "pmi: can't request IRQ %d: returned %d\n",
+				data->irq, rc);
+		goto error_cleanup_iomap;
+	}
+
+	printk(KERN_INFO "pmi: found pmi device at addr %p.\n", data->pmi_reg);
+
+	goto out;
+
+error_cleanup_iomap:
+	iounmap(data->pmi_reg);
+
+error_cleanup_data:
+	kfree(data);
+
+out:
+	return rc;
+}
+
+static int pmi_of_remove(struct of_device *dev)
+{
+	struct pmi_data *data;
+	struct pmi_handler *handler, *tmp;
+
+	data = dev->dev.driver_data;
+
+	free_irq(data->irq, data);
+	iounmap(data->pmi_reg);
+
+	spin_lock(&data->handler_spinlock);
+
+	list_for_each_entry_safe(handler, tmp, &data->handler, node)
+		list_del(&handler->node);
+
+	spin_unlock(&data->handler_spinlock);
+
+	kfree(dev->dev.driver_data);
+
+	return 0;
+}
+
+static struct of_platform_driver pmi_of_platform_driver = {
+	.name		= "pmi",
+	.match_table	= pmi_match,
+	.probe		= pmi_of_probe,
+	.remove		= pmi_of_remove
+};
+
+static int __init pmi_module_init(void)
+{
+	return of_register_platform_driver(&pmi_of_platform_driver);
+}
+module_init(pmi_module_init);
+
+static void __exit pmi_module_exit(void)
+{
+	of_unregister_platform_driver(&pmi_of_platform_driver);
+}
+module_exit(pmi_module_exit);
+
+void pmi_send_message(struct of_device *device, pmi_message_t msg)
+{
+	struct pmi_data *data;
+	unsigned long flags;
+	DECLARE_COMPLETION_ONSTACK(completion);
+
+	data = device->dev.driver_data;
+
+	mutex_lock(&data->msg_mutex);
+
+	data->msg = msg;
+	pr_debug("pmi_send_message: msg is %08x\n", *(u32*)&msg);
+
+	data->completion = &completion;
+
+	spin_lock_irqsave(&data->pmi_spinlock, flags);
+	iowrite8(msg.data0, data->pmi_reg + PMI_WRITE_DATA0);
+	iowrite8(msg.data1, data->pmi_reg + PMI_WRITE_DATA1);
+	iowrite8(msg.data2, data->pmi_reg + PMI_WRITE_DATA2);
+	iowrite8(msg.type, data->pmi_reg + PMI_WRITE_TYPE);
+	spin_unlock_irqrestore(&data->pmi_spinlock, flags);
+
+	pr_debug("pmi_send_message: wait for completion\n");
+
+	wait_for_completion_interruptible_timeout(data->completion,
+						  PMI_TIMEOUT);
+
+	data->completion = NULL;
+
+	mutex_unlock(&data->msg_mutex);
+}
+EXPORT_SYMBOL_GPL(pmi_send_message);
+
+void pmi_register_handler(struct of_device *device,
+			  struct pmi_handler *handler)
+{
+	struct pmi_data *data;
+	data = device->dev.driver_data;
+
+	spin_lock(&data->handler_spinlock);
+	list_add_tail(&handler->node, &data->handler);
+	spin_unlock(&data->handler_spinlock);
+}
+EXPORT_SYMBOL_GPL(pmi_register_handler);
+
+void pmi_unregister_handler(struct of_device *device,
+			    struct pmi_handler *handler)
+{
+	struct pmi_data *data;
+
+	pr_debug("pmi: unregistering handler %p\n", handler);
+
+	data = device->dev.driver_data;
+
+	spin_lock(&data->handler_spinlock);
+	list_del(&handler->node);
+	spin_unlock(&data->handler_spinlock);
+}
+EXPORT_SYMBOL_GPL(pmi_unregister_handler);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
+MODULE_DESCRIPTION("IBM Platform Management Interrupt driver");
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index e657559..a457ac1 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -1,13 +1,12 @@
 /*
- * arch/powerpc/sysdev/qe_lib/ucc_fast.c
- *
- * QE UCC Fast API Set - UCC Fast specific routines implementations.
- *
  * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
  *
+ * Description:
+ * QE UCC Fast API Set - UCC Fast specific routines implementations.
+ *
  * 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
@@ -27,79 +26,61 @@
 #include <asm/ucc.h>
 #include <asm/ucc_fast.h>
 
-#define uccf_printk(level, format, arg...) \
-	printk(level format "\n", ## arg)
-
-#define uccf_dbg(format, arg...) \
-	uccf_printk(KERN_DEBUG , format , ## arg)
-#define uccf_err(format, arg...) \
-	uccf_printk(KERN_ERR , format , ## arg)
-#define uccf_info(format, arg...) \
-	uccf_printk(KERN_INFO , format , ## arg)
-#define uccf_warn(format, arg...) \
-	uccf_printk(KERN_WARNING , format , ## arg)
-
-#ifdef UCCF_VERBOSE_DEBUG
-#define uccf_vdbg uccf_dbg
-#else
-#define uccf_vdbg(fmt, args...) do { } while (0)
-#endif				/* UCCF_VERBOSE_DEBUG */
-
 void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
 {
-	uccf_info("UCC%d Fast registers:", uccf->uf_info->ucc_num);
-	uccf_info("Base address: 0x%08x", (u32) uccf->uf_regs);
+	printk(KERN_INFO "UCC%d Fast registers:", uccf->uf_info->ucc_num);
+	printk(KERN_INFO "Base address: 0x%08x", (u32) uccf->uf_regs);
 
-	uccf_info("gumr  : addr - 0x%08x, val - 0x%08x",
+	printk(KERN_INFO "gumr  : addr - 0x%08x, val - 0x%08x",
 		  (u32) & uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr));
-	uccf_info("upsmr : addr - 0x%08x, val - 0x%08x",
+	printk(KERN_INFO "upsmr : addr - 0x%08x, val - 0x%08x",
 		  (u32) & uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr));
-	uccf_info("utodr : addr - 0x%08x, val - 0x%04x",
+	printk(KERN_INFO "utodr : addr - 0x%08x, val - 0x%04x",
 		  (u32) & uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr));
-	uccf_info("udsr  : addr - 0x%08x, val - 0x%04x",
+	printk(KERN_INFO "udsr  : addr - 0x%08x, val - 0x%04x",
 		  (u32) & uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr));
-	uccf_info("ucce  : addr - 0x%08x, val - 0x%08x",
+	printk(KERN_INFO "ucce  : addr - 0x%08x, val - 0x%08x",
 		  (u32) & uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce));
-	uccf_info("uccm  : addr - 0x%08x, val - 0x%08x",
+	printk(KERN_INFO "uccm  : addr - 0x%08x, val - 0x%08x",
 		  (u32) & uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
-	uccf_info("uccs  : addr - 0x%08x, val - 0x%02x",
+	printk(KERN_INFO "uccs  : addr - 0x%08x, val - 0x%02x",
 		  (u32) & uccf->uf_regs->uccs, uccf->uf_regs->uccs);
-	uccf_info("urfb  : addr - 0x%08x, val - 0x%08x",
+	printk(KERN_INFO "urfb  : addr - 0x%08x, val - 0x%08x",
 		  (u32) & uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
-	uccf_info("urfs  : addr - 0x%08x, val - 0x%04x",
+	printk(KERN_INFO "urfs  : addr - 0x%08x, val - 0x%04x",
 		  (u32) & uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs));
-	uccf_info("urfet : addr - 0x%08x, val - 0x%04x",
+	printk(KERN_INFO "urfet : addr - 0x%08x, val - 0x%04x",
 		  (u32) & uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet));
-	uccf_info("urfset: addr - 0x%08x, val - 0x%04x",
+	printk(KERN_INFO "urfset: addr - 0x%08x, val - 0x%04x",
 		  (u32) & uccf->uf_regs->urfset,
 		  in_be16(&uccf->uf_regs->urfset));
-	uccf_info("utfb  : addr - 0x%08x, val - 0x%08x",
+	printk(KERN_INFO "utfb  : addr - 0x%08x, val - 0x%08x",
 		  (u32) & uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb));
-	uccf_info("utfs  : addr - 0x%08x, val - 0x%04x",
+	printk(KERN_INFO "utfs  : addr - 0x%08x, val - 0x%04x",
 		  (u32) & uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs));
-	uccf_info("utfet : addr - 0x%08x, val - 0x%04x",
+	printk(KERN_INFO "utfet : addr - 0x%08x, val - 0x%04x",
 		  (u32) & uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet));
-	uccf_info("utftt : addr - 0x%08x, val - 0x%04x",
+	printk(KERN_INFO "utftt : addr - 0x%08x, val - 0x%04x",
 		  (u32) & uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt));
-	uccf_info("utpt  : addr - 0x%08x, val - 0x%04x",
+	printk(KERN_INFO "utpt  : addr - 0x%08x, val - 0x%04x",
 		  (u32) & uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt));
-	uccf_info("urtry : addr - 0x%08x, val - 0x%08x",
+	printk(KERN_INFO "urtry : addr - 0x%08x, val - 0x%08x",
 		  (u32) & uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
-	uccf_info("guemr : addr - 0x%08x, val - 0x%02x",
+	printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x",
 		  (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
 }
 
 u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
 {
 	switch (uccf_num) {
-	case 0:	return QE_CR_SUBBLOCK_UCCFAST1;
+	case 0: return QE_CR_SUBBLOCK_UCCFAST1;
 	case 1: return QE_CR_SUBBLOCK_UCCFAST2;
 	case 2: return QE_CR_SUBBLOCK_UCCFAST3;
 	case 3: return QE_CR_SUBBLOCK_UCCFAST4;
 	case 4: return QE_CR_SUBBLOCK_UCCFAST5;
 	case 5: return QE_CR_SUBBLOCK_UCCFAST6;
 	case 6: return QE_CR_SUBBLOCK_UCCFAST7;
-	case 7:	return QE_CR_SUBBLOCK_UCCFAST8;
+	case 7: return QE_CR_SUBBLOCK_UCCFAST8;
 	default: return QE_CR_SUBBLOCK_INVALID;
 	}
 }
@@ -153,84 +134,72 @@
 {
 	struct ucc_fast_private *uccf;
 	struct ucc_fast *uf_regs;
-	u32 gumr = 0;
+	u32 gumr;
 	int ret;
 
-	uccf_vdbg("%s: IN", __FUNCTION__);
-
 	if (!uf_info)
 		return -EINVAL;
 
 	/* check if the UCC port number is in range. */
 	if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
-		uccf_err("ucc_fast_init: Illegal UCC number!");
+		printk(KERN_ERR "%s: illegal UCC number", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	/* Check that 'max_rx_buf_length' is properly aligned (4). */
 	if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
-		uccf_err("ucc_fast_init: max_rx_buf_length not aligned.");
+		printk(KERN_ERR "%s: max_rx_buf_length not aligned", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	/* Validate Virtual Fifo register values */
 	if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
-		uccf_err
-		    ("ucc_fast_init: Virtual Fifo register urfs too small.");
+		printk(KERN_ERR "%s: urfs is too small", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		uccf_err
-		    ("ucc_fast_init: Virtual Fifo register urfs not aligned.");
+		printk(KERN_ERR "%s: urfs is not aligned", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		uccf_err
-		    ("ucc_fast_init: Virtual Fifo register urfet not aligned.");
+		printk(KERN_ERR "%s: urfet is not aligned.", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		uccf_err
-		   ("ucc_fast_init: Virtual Fifo register urfset not aligned.");
+		printk(KERN_ERR "%s: urfset is not aligned", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		uccf_err
-		    ("ucc_fast_init: Virtual Fifo register utfs not aligned.");
+		printk(KERN_ERR "%s: utfs is not aligned", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		uccf_err
-		    ("ucc_fast_init: Virtual Fifo register utfet not aligned.");
+		printk(KERN_ERR "%s: utfet is not aligned", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		uccf_err
-		    ("ucc_fast_init: Virtual Fifo register utftt not aligned.");
+		printk(KERN_ERR "%s: utftt is not aligned", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
 	if (!uccf) {
-		uccf_err
-		    ("ucc_fast_init: No memory for UCC slow data structure!");
+		printk(KERN_ERR "%s: Cannot allocate private data", __FUNCTION__);
 		return -ENOMEM;
 	}
 
 	/* Fill fast UCC structure */
 	uccf->uf_info = uf_info;
 	/* Set the PHY base address */
-	uccf->uf_regs =
-	    (struct ucc_fast *) ioremap(uf_info->regs, sizeof(struct ucc_fast));
+	uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast));
 	if (uccf->uf_regs == NULL) {
-		uccf_err
-		    ("ucc_fast_init: No memory map for UCC slow controller!");
+		printk(KERN_ERR "%s: Cannot map UCC registers", __FUNCTION__);
 		return -ENOMEM;
 	}
 
@@ -249,7 +218,7 @@
 
 	/* Init Guemr register */
 	if ((ret = ucc_init_guemr((struct ucc_common *) (uf_regs)))) {
-		uccf_err("ucc_fast_init: Could not init the guemr register.");
+		printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__);
 		ucc_fast_free(uccf);
 		return ret;
 	}
@@ -258,7 +227,7 @@
 	if ((ret = ucc_set_type(uf_info->ucc_num,
 				(struct ucc_common *) (uf_regs),
 				UCC_SPEED_TYPE_FAST))) {
-		uccf_err("ucc_fast_init: Could not set type to fast.");
+		printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
 		ucc_fast_free(uccf);
 		return ret;
 	}
@@ -267,10 +236,9 @@
 
 	/* Set GUMR */
 	/* For more details see the hardware spec. */
-	/* gumr starts as zero. */
+	gumr = uf_info->ttx_trx;
 	if (uf_info->tci)
 		gumr |= UCC_FAST_GUMR_TCI;
-	gumr |= uf_info->ttx_trx;
 	if (uf_info->cdp)
 		gumr |= UCC_FAST_GUMR_CDP;
 	if (uf_info->ctsp)
@@ -298,9 +266,7 @@
 	uccf->ucc_fast_tx_virtual_fifo_base_offset =
 	    qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
 	if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
-		uccf_err
-		    ("ucc_fast_init: Can not allocate MURAM memory for "
-			"struct ucc_fastx_virtual_fifo_base_offset.");
+		printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO", __FUNCTION__);
 		uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
 		ucc_fast_free(uccf);
 		return -ENOMEM;
@@ -308,14 +274,11 @@
 
 	/* Allocate memory for Rx Virtual Fifo */
 	uccf->ucc_fast_rx_virtual_fifo_base_offset =
-	    qe_muram_alloc(uf_info->urfs +
-			   (u32)
+		qe_muram_alloc(uf_info->urfs +
 			   UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
 			   UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
 	if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
-		uccf_err
-		    ("ucc_fast_init: Can not allocate MURAM memory for "
-			"ucc_fast_rx_virtual_fifo_base_offset.");
+		printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO", __FUNCTION__);
 		uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
 		ucc_fast_free(uccf);
 		return -ENOMEM;
@@ -342,26 +305,22 @@
 	/* If NMSI (not Tsa), set Tx and Rx clock. */
 	if (!uf_info->tsa) {
 		/* Rx clock routing */
-		if (uf_info->rx_clock != QE_CLK_NONE) {
-			if (ucc_set_qe_mux_rxtx
-			    (uf_info->ucc_num, uf_info->rx_clock,
-			     COMM_DIR_RX)) {
-				uccf_err
-		("ucc_fast_init: Illegal value for parameter 'RxClock'.");
-				ucc_fast_free(uccf);
-				return -EINVAL;
-			}
+		if ((uf_info->rx_clock != QE_CLK_NONE) &&
+		    ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock,
+					COMM_DIR_RX)) {
+			printk(KERN_ERR "%s: illegal value for RX clock",
+			       __FUNCTION__);
+			ucc_fast_free(uccf);
+			return -EINVAL;
 		}
 		/* Tx clock routing */
-		if (uf_info->tx_clock != QE_CLK_NONE) {
-			if (ucc_set_qe_mux_rxtx
-			    (uf_info->ucc_num, uf_info->tx_clock,
-			     COMM_DIR_TX)) {
-				uccf_err
-		("ucc_fast_init: Illegal value for parameter 'TxClock'.");
-				ucc_fast_free(uccf);
-				return -EINVAL;
-			}
+		if ((uf_info->tx_clock != QE_CLK_NONE) &&
+		    ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock,
+					COMM_DIR_TX)) {
+			printk(KERN_ERR "%s: illegal value for TX clock",
+			       __FUNCTION__);
+			ucc_fast_free(uccf);
+			return -EINVAL;
 		}
 	}
 
@@ -370,9 +329,9 @@
 
 	/* First, clear anything pending at UCC level,
 	 * otherwise, old garbage may come through
-	 * as soon as the dam is opened
-	 * Writing '1' clears
-	 */
+	 * as soon as the dam is opened. */
+
+	/* Writing '1' clears */
 	out_be32(&uf_regs->ucce, 0xffffffff);
 
 	*uccf_ret = uccf;
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index 47b5620..817df73 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -19,7 +19,6 @@
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 
-#include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/immap_qe.h>
 #include <asm/qe.h>
@@ -27,24 +26,6 @@
 #include <asm/ucc.h>
 #include <asm/ucc_slow.h>
 
-#define uccs_printk(level, format, arg...) \
-        printk(level format "\n", ## arg)
-
-#define uccs_dbg(format, arg...) \
-	uccs_printk(KERN_DEBUG , format , ## arg)
-#define uccs_err(format, arg...) \
-	uccs_printk(KERN_ERR , format , ## arg)
-#define uccs_info(format, arg...) \
-	uccs_printk(KERN_INFO , format , ## arg)
-#define uccs_warn(format, arg...) \
-	uccs_printk(KERN_WARNING , format , ## arg)
-
-#ifdef UCCS_VERBOSE_DEBUG
-#define uccs_vdbg uccs_dbg
-#else
-#define uccs_vdbg(fmt, args...) do { } while (0)
-#endif				/* UCCS_VERBOSE_DEBUG */
-
 u32 ucc_slow_get_qe_cr_subblock(int uccs_num)
 {
 	switch (uccs_num) {
@@ -135,51 +116,53 @@
 
 int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret)
 {
+	struct ucc_slow_private *uccs;
 	u32 i;
 	struct ucc_slow *us_regs;
 	u32 gumr;
-	u8 function_code = 0;
-	u8 *bd;
-	struct ucc_slow_private *uccs;
+	struct qe_bd *bd;
 	u32 id;
 	u32 command;
-	int ret;
-
-	uccs_vdbg("%s: IN", __FUNCTION__);
+	int ret = 0;
 
 	if (!us_info)
 		return -EINVAL;
 
 	/* check if the UCC port number is in range. */
 	if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
-		uccs_err("ucc_slow_init: Illegal UCC number!");
+		printk(KERN_ERR "%s: illegal UCC number", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	/*
 	 * Set mrblr
 	 * Check that 'max_rx_buf_length' is properly aligned (4), unless
- 	 * rfw is 1, meaning that QE accepts one byte at a time, unlike normal
+	 * rfw is 1, meaning that QE accepts one byte at a time, unlike normal
 	 * case when QE accepts 32 bits at a time.
 	 */
 	if ((!us_info->rfw) &&
 		(us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) {
-		uccs_err("max_rx_buf_length not aligned.");
+		printk(KERN_ERR "max_rx_buf_length not aligned.");
 		return -EINVAL;
 	}
 
 	uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
 	if (!uccs) {
-		uccs_err
-		    ("ucc_slow_init: No memory for UCC slow data structure!");
+		printk(KERN_ERR "%s: Cannot allocate private data", __FUNCTION__);
 		return -ENOMEM;
 	}
 
 	/* Fill slow UCC structure */
 	uccs->us_info = us_info;
+	/* Set the PHY base address */
+	uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow));
+	if (uccs->us_regs == NULL) {
+		printk(KERN_ERR "%s: Cannot map UCC registers", __FUNCTION__);
+		return -ENOMEM;
+	}
+
 	uccs->saved_uccm = 0;
 	uccs->p_rx_frame = 0;
-	uccs->us_regs = us_info->us_regs;
 	us_regs = uccs->us_regs;
 	uccs->p_ucce = (u16 *) & (us_regs->ucce);
 	uccs->p_uccm = (u16 *) & (us_regs->uccm);
@@ -190,33 +173,31 @@
 #endif				/* STATISTICS */
 
 	/* Get PRAM base */
-	uccs->us_pram_offset = qe_muram_alloc(UCC_SLOW_PRAM_SIZE,
-						 ALIGNMENT_OF_UCC_SLOW_PRAM);
+	uccs->us_pram_offset =
+		qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
 	if (IS_MURAM_ERR(uccs->us_pram_offset)) {
-		uccs_err
-		    ("ucc_slow_init: Can not allocate MURAM memory "
-			"for Slow UCC.");
+		printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __FUNCTION__);
 		ucc_slow_free(uccs);
 		return -ENOMEM;
 	}
 	id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
 	qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, QE_CR_PROTOCOL_UNSPECIFIED,
-			(u32) uccs->us_pram_offset);
+		     uccs->us_pram_offset);
 
 	uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
 
 	/* Init Guemr register */
-	if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->us_regs)))) {
-		uccs_err("ucc_slow_init: Could not init the guemr register.");
+	if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->regs)))) {
+		printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__);
 		ucc_slow_free(uccs);
 		return ret;
 	}
 
 	/* Set UCC to slow type */
 	if ((ret = ucc_set_type(us_info->ucc_num,
-				(struct ucc_common *) (us_info->us_regs),
+				(struct ucc_common *) (us_info->regs),
 				UCC_SPEED_TYPE_SLOW))) {
-		uccs_err("ucc_slow_init: Could not init the guemr register.");
+		printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
 		ucc_slow_free(uccs);
 		return ret;
 	}
@@ -230,7 +211,7 @@
 		qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
 				QE_ALIGNMENT_OF_BD);
 	if (IS_MURAM_ERR(uccs->rx_base_offset)) {
-		uccs_err("ucc_slow_init: No memory for Rx BD's.");
+		printk(KERN_ERR "%s: cannot allocate RX BDs", __FUNCTION__);
 		uccs->rx_base_offset = 0;
 		ucc_slow_free(uccs);
 		return -ENOMEM;
@@ -240,7 +221,7 @@
 		qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
 			QE_ALIGNMENT_OF_BD);
 	if (IS_MURAM_ERR(uccs->tx_base_offset)) {
-		uccs_err("ucc_slow_init: No memory for Tx BD's.");
+		printk(KERN_ERR "%s: cannot allocate TX BDs", __FUNCTION__);
 		uccs->tx_base_offset = 0;
 		ucc_slow_free(uccs);
 		return -ENOMEM;
@@ -248,34 +229,33 @@
 
 	/* Init Tx bds */
 	bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset);
-	for (i = 0; i < us_info->tx_bd_ring_len; i++) {
+	for (i = 0; i < us_info->tx_bd_ring_len - 1; i++) {
 		/* clear bd buffer */
-		out_be32(&(((struct qe_bd *)bd)->buf), 0);
+		out_be32(&bd->buf, 0);
 		/* set bd status and length */
-		out_be32((u32*)bd, 0);
-		bd += sizeof(struct qe_bd);
+		out_be32((u32 *) bd, 0);
+		bd++;
 	}
-	bd -= sizeof(struct qe_bd);
-	/* set bd status and length */
-	out_be32((u32*)bd, T_W);	/* for last BD set Wrap bit */
+	/* for last BD set Wrap bit */
+	out_be32(&bd->buf, 0);
+	out_be32((u32 *) bd, cpu_to_be32(T_W));
 
 	/* Init Rx bds */
 	bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);
-	for (i = 0; i < us_info->rx_bd_ring_len; i++) {
+	for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) {
 		/* set bd status and length */
 		out_be32((u32*)bd, 0);
 		/* clear bd buffer */
-		out_be32(&(((struct qe_bd *)bd)->buf), 0);
-		bd += sizeof(struct qe_bd);
+		out_be32(&bd->buf, 0);
+		bd++;
 	}
-	bd -= sizeof(struct qe_bd);
-	/* set bd status and length */
-	out_be32((u32*)bd, R_W);	/* for last BD set Wrap bit */
+	/* for last BD set Wrap bit */
+	out_be32((u32*)bd, cpu_to_be32(R_W));
+	out_be32(&bd->buf, 0);
 
 	/* Set GUMR (For more details see the hardware spec.). */
 	/* gumr_h */
-	gumr = 0;
-	gumr |= us_info->tcrc;
+	gumr = us_info->tcrc;
 	if (us_info->cdp)
 		gumr |= UCC_SLOW_GUMR_H_CDP;
 	if (us_info->ctsp)
@@ -295,7 +275,8 @@
 	out_be32(&us_regs->gumr_h, gumr);
 
 	/* gumr_l */
-	gumr = 0;
+	gumr = us_info->tdcr | us_info->rdcr | us_info->tenc | us_info->renc |
+		us_info->diag | us_info->mode;
 	if (us_info->tci)
 		gumr |= UCC_SLOW_GUMR_L_TCI;
 	if (us_info->rinv)
@@ -304,23 +285,14 @@
 		gumr |= UCC_SLOW_GUMR_L_TINV;
 	if (us_info->tend)
 		gumr |= UCC_SLOW_GUMR_L_TEND;
-	gumr |= us_info->tdcr;
-	gumr |= us_info->rdcr;
-	gumr |= us_info->tenc;
-	gumr |= us_info->renc;
-	gumr |= us_info->diag;
-	gumr |= us_info->mode;
 	out_be32(&us_regs->gumr_l, gumr);
 
 	/* Function code registers */
-	/* function_code has initial value 0 */
 
 	/* if the data is in cachable memory, the 'global' */
 	/* in the function code should be set. */
-	function_code |= us_info->data_mem_part;
-	function_code |= QE_BMR_BYTE_ORDER_BO_MOT;	/* Required for QE */
-	uccs->us_pram->tfcr = function_code;
-	uccs->us_pram->rfcr = function_code;
+	uccs->us_pram->tfcr = uccs->us_pram->rfcr =
+		us_info->data_mem_part | QE_BMR_BYTE_ORDER_BO_MOT;
 
 	/* rbase, tbase are offsets from MURAM base */
 	out_be16(&uccs->us_pram->rbase, uccs->us_pram_offset);
@@ -336,34 +308,29 @@
 	/* If NMSI (not Tsa), set Tx and Rx clock. */
 	if (!us_info->tsa) {
 		/* Rx clock routing */
-		if (ucc_set_qe_mux_rxtx
-		    (us_info->ucc_num, us_info->rx_clock, COMM_DIR_RX)) {
-			uccs_err
-			    ("ucc_slow_init: Illegal value for parameter"
-				" 'RxClock'.");
+		if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock,
+					COMM_DIR_RX)) {
+			printk(KERN_ERR "%s: illegal value for RX clock",
+			       __FUNCTION__);
 			ucc_slow_free(uccs);
 			return -EINVAL;
 		}
 		/* Tx clock routing */
-		if (ucc_set_qe_mux_rxtx(us_info->ucc_num,
-				 us_info->tx_clock, COMM_DIR_TX)) {
-			uccs_err
-			    ("ucc_slow_init: Illegal value for parameter "
-				"'TxClock'.");
+		if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock,
+					COMM_DIR_TX)) {
+			printk(KERN_ERR "%s: illegal value for TX clock",
+			       __FUNCTION__);
 			ucc_slow_free(uccs);
 			return -EINVAL;
 		}
 	}
 
-	/*
-	 * INTERRUPTS
-	 */
 	/* Set interrupt mask register at UCC level. */
 	out_be16(&us_regs->uccm, us_info->uccm_mask);
 
-	/* First, clear anything pending at UCC level, */
-	/* otherwise, old garbage may come through */
-	/* as soon as the dam is opened. */
+	/* First, clear anything pending at UCC level,
+	 * otherwise, old garbage may come through
+	 * as soon as the dam is opened. */
 
 	/* Writing '1' clears */
 	out_be16(&us_regs->ucce, 0xffff);
@@ -400,3 +367,5 @@
 
 	kfree(uccs);
 }
+
+
diff --git a/arch/powerpc/xmon/spu-dis.c b/arch/powerpc/xmon/spu-dis.c
index ee929c6..e5f8983 100644
--- a/arch/powerpc/xmon/spu-dis.c
+++ b/arch/powerpc/xmon/spu-dis.c
@@ -85,7 +85,7 @@
   if ((index = spu_disassemble_table[opcode & 0x7ff]) != 0)
     return index;
 
-  return 0;
+  return NULL;
 }
 
 /* Print a Spu instruction.  */
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 77540a2..0183e5f 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2811,7 +2811,6 @@
 	DUMP_FIELD(spu, "0x%lx", irqs[2]);
 	DUMP_FIELD(spu, "0x%x", slb_replace);
 	DUMP_FIELD(spu, "%d", pid);
-	DUMP_FIELD(spu, "%d", prio);
 	DUMP_FIELD(spu, "0x%p", mm);
 	DUMP_FIELD(spu, "0x%p", ctx);
 	DUMP_FIELD(spu, "0x%p", rq);
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index 684ed04..a956f28 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -1711,7 +1711,7 @@
 }
 
 
-static struct file_operations mixer_fops =
+static const struct file_operations mixer_fops =
 {
 	.owner =	THIS_MODULE,
 	.llseek =	sound_lseek,
@@ -2298,7 +2298,7 @@
 
 
 
-static struct file_operations sq_fops =
+static const struct file_operations sq_fops =
 {
 	.owner =	THIS_MODULE,
 	.llseek =	sound_lseek,
@@ -2433,7 +2433,7 @@
 }
 
 
-static struct file_operations state_fops =
+static const struct file_operations state_fops =
 {
 	.owner =	THIS_MODULE,
 	.llseek =	sound_lseek,
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index c22e606..ccce2a4 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -845,6 +845,21 @@
 	select PPC_INDIRECT_PCI
 	default y
 
+config MV643XX_ETH_0
+	bool
+	depends on MV643XX_ETH && (KATANA || RADSTONE_PPC7D || EV64360 || HDPU)
+	default y
+
+config MV643XX_ETH_1
+	bool
+	depends on MV643XX_ETH && (KATANA || RADSTONE_PPC7D || EV64360)
+	default y
+
+config MV643XX_ETH_2
+	bool
+	depends on MV643XX_ETH && (KATANA || RADSTONE_PPC7D || EV64360)
+	default y
+
 menu "Set bridge options"
 	depends on MV64X60
 
@@ -1177,6 +1192,10 @@
 	  have an IBM RS/6000 or pSeries machine or a PReP machine, say Y.  If
 	  you have an embedded board, consult your board documentation.
 
+config ZONE_DMA
+	bool
+	default y
+
 config GENERIC_ISA_DMA
 	bool
 	depends on 6xx && !CPM2
diff --git a/arch/ppc/configs/taishan_defconfig b/arch/ppc/configs/taishan_defconfig
new file mode 100644
index 0000000..1ca0204
--- /dev/null
+++ b/arch/ppc/configs/taishan_defconfig
@@ -0,0 +1,1077 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+# Mon Feb 12 11:11:58 2007
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# 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_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=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 is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# 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"
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+CONFIG_44x=y
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+# CONFIG_E500 is not set
+CONFIG_PPC_DCR_NATIVE=y
+CONFIG_PPC_DCR=y
+CONFIG_BOOKE=y
+CONFIG_PTE_64BIT=y
+CONFIG_PHYS_64BIT=y
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+CONFIG_WANT_EARLY_SERIAL=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_BAMBOO is not set
+# CONFIG_EBONY is not set
+# CONFIG_LUAN is not set
+# CONFIG_YUCCA is not set
+# CONFIG_OCOTEA is not set
+CONFIG_TAISHAN=y
+CONFIG_440GX=y
+CONFIG_440A=y
+CONFIG_IBM_OCP=y
+CONFIG_IBM_EMAC4=y
+CONFIG_PPC4xx_DMA=y
+CONFIG_PPC4xx_EDMA=y
+CONFIG_PPC_GEN550=y
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on console=ttyS0,115200"
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x01000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# 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 is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+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 is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+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 is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK 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=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# 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_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 is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_NAND_CAFE is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# 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 is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_MAC_EMUMOUSEBTN is not set
+# CONFIG_WINDFARM is not set
+
+#
+# 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 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
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=128
+CONFIG_IBM_EMAC_TXB=128
+CONFIG_IBM_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_EMAC_RX_SKB_HEADROOM=0
+CONFIG_IBM_EMAC_PHY_RX_CLK_FIX=y
+# CONFIG_IBM_EMAC_DEBUG is not set
+CONFIG_IBM_EMAC_ZMII=y
+CONFIG_IBM_EMAC_RGMII=y
+CONFIG_IBM_EMAC_TAH=y
+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 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO 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_SC92031 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 is not set
+# CONFIG_SIS190 is not set
+# 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
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC 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=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=y
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# 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 is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+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
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+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
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM 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_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_IBM_IIC=y
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# 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
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 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 is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk 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
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_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_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# 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_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# 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_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# 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 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_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
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
+CONFIG_BDI_SWITCH=y
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_PPC_OCP=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S
index 66877bd..1f155d3 100644
--- a/arch/ppc/kernel/head_fsl_booke.S
+++ b/arch/ppc/kernel/head_fsl_booke.S
@@ -206,7 +206,8 @@
 	rlwimi	r7,r3,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r3) */
 	mtspr	SPRN_MAS0,r7
 	tlbre
-	li	r6,0
+	mfspr	r6,SPRN_MAS1
+	rlwinm	r6,r6,0,2,0	/* clear IPROT */
 	mtspr	SPRN_MAS1,r6
 	tlbwe
 	/* Invalidate TLB1 */
@@ -248,6 +249,8 @@
 	rlwimi	r7,r5,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r5) */
 	mtspr	SPRN_MAS0,r7
 	tlbre
+	mfspr	r8,SPRN_MAS1
+	rlwinm	r8,r8,0,2,0	/* clear IPROT */
 	mtspr	SPRN_MAS1,r8
 	tlbwe
 	/* Invalidate TLB1 */
@@ -889,7 +892,6 @@
 	REST_GPR(9, r11)
 	REST_GPR(12, r11)
 	lwz	r11,GPR11(r11)
-	SYNC
 	rfi
 
 /*
@@ -953,7 +955,6 @@
 _GLOBAL(giveup_spe)
 	mfmsr	r5
 	oris	r5,r5,MSR_SPE@h
-	SYNC
 	mtmsr	r5			/* enable use of SPE now */
 	isync
 	cmpi	0,r3,0
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index bd129d3..0a7e42d 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -442,17 +442,22 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dol2crvec,
 	},
-	{ 0, },
+	{}
 };
 static ctl_table htab_sysctl_root[] = {
-	{ 1, "kernel", NULL, 0, 0755, htab_ctl_table, },
- 	{ 0,},
+	{
+		.ctl_name	= CTL_KERN,
+		.procname	= "kernel",
+		.mode		= 0555,
+		.child		= htab_ctl_table,
+	},
+	{}
 };
 
 static int __init
 register_ppc_htab_sysctl(void)
 {
-	register_sysctl_table(htab_sysctl_root, 0);
+	register_sysctl_table(htab_sysctl_root);
 
 	return 0;
 }
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 1f49503..1318b6f 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -271,7 +271,7 @@
 extern long *intercept_table;
 EXPORT_SYMBOL(intercept_table);
 #endif /* CONFIG_PPC_STD_MMU */
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_DCR_NATIVE
 EXPORT_SYMBOL(__mtdcr);
 EXPORT_SYMBOL(__mfdcr);
 #endif
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 3c506af..c79704f 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -543,7 +543,7 @@
 	init_mm.brk = (unsigned long) klimit;
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
 	*cmdline_p = cmd_line;
 
 	parse_early_param();
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 6192126..a062556 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -135,10 +135,12 @@
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
 
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
 
   . = ALIGN(4096);
   __init_end = .;
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index 82b06a1..c023b72 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -314,7 +314,7 @@
 }
 
 /* is x a power of 4? */
-#define is_power_of_4(x)	is_power_of_2(x) && (ffs(x) & 1))
+#define is_power_of_4(x)	is_power_of_2(x) && (ffs(x) & 1)
 
 /*
  * Set up a mapping for a block of I/O.
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index 6980de4..705ae56 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -98,6 +98,12 @@
 	help
 	  This option enables support for the IBM PPC440GX evaluation board.
 
+config TAISHAN
+	bool "Taishan"
+	select WANT_EARLY_SERIAL
+	help
+	  This option enables support for the AMCC PPC440GX evaluation board.
+
 endchoice
 
 config EP405PC
@@ -126,7 +132,7 @@
 
 config 440GX
 	bool
-	depends on OCOTEA
+	depends on OCOTEA || TAISHAN
 	default y
 
 config 440SP
@@ -173,7 +179,7 @@
 
 config IBM_OCP
 	bool
-	depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || YUCCA || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+	depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || YUCCA || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || TAISHAN || WALNUT
 	default y
 
 config IBM_EMAC4
diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile
index a04a0d0..fa6610b 100644
--- a/arch/ppc/platforms/4xx/Makefile
+++ b/arch/ppc/platforms/4xx/Makefile
@@ -12,6 +12,7 @@
 obj-$(CONFIG_REDWOOD_5)		+= redwood5.o
 obj-$(CONFIG_REDWOOD_6)		+= redwood6.o
 obj-$(CONFIG_SYCAMORE)		+= sycamore.o
+obj-$(CONFIG_TAISHAN)		+= taishan.o
 obj-$(CONFIG_WALNUT)		+= walnut.o
 obj-$(CONFIG_XILINX_ML300)	+= xilinx_ml300.o
 obj-$(CONFIG_XILINX_ML403)	+= xilinx_ml403.o
diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c
new file mode 100644
index 0000000..bb0253e
--- /dev/null
+++ b/arch/ppc/platforms/4xx/taishan.c
@@ -0,0 +1,395 @@
+/*
+ * arch/ppc/platforms/4xx/taishan.c
+ *
+ * AMCC Taishan board specific routines
+ *
+ * Copyright 2007 DENX Software Engineering, Stefan Roese <sr@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/initrd.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/ndfc.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/bootinfo.h>
+#include <asm/ppcboot.h>
+
+#include <syslib/gen550.h>
+#include <syslib/ibm440gx_common.h>
+
+extern bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
+
+/*
+ * NOR FLASH configuration (using mtd physmap driver)
+ */
+
+/* start will be added dynamically, end is always fixed */
+static struct resource taishan_nor_resource = {
+	.start = TAISHAN_FLASH_ADDR,
+	.end   = 0x1ffffffffULL,
+	.flags = IORESOURCE_MEM,
+};
+
+#define RW_PART0_OF	0
+#define RW_PART0_SZ	0x180000
+#define RW_PART1_SZ	0x200000
+/* Partition 2 will be autosized dynamically... */
+#define RW_PART3_SZ	0x80000
+#define RW_PART4_SZ	0x40000
+
+static struct mtd_partition taishan_nor_parts[] = {
+	{
+		.name = "kernel",
+		.offset = 0,
+		.size = RW_PART0_SZ
+	},
+	{
+		.name = "root",
+		.offset = MTDPART_OFS_APPEND,
+		.size = RW_PART1_SZ,
+	},
+	{
+		.name = "user",
+		.offset = MTDPART_OFS_APPEND,
+/*		.size = RW_PART2_SZ */ /* will be adjusted dynamically */
+	},
+	{
+		.name = "env",
+		.offset = MTDPART_OFS_APPEND,
+		.size = RW_PART3_SZ,
+	},
+	{
+		.name = "u-boot",
+		.offset = MTDPART_OFS_APPEND,
+		.size = RW_PART4_SZ,
+	}
+};
+
+static struct physmap_flash_data taishan_nor_data = {
+	.width		= 4,
+	.parts		= taishan_nor_parts,
+	.nr_parts	= ARRAY_SIZE(taishan_nor_parts),
+};
+
+static struct platform_device taishan_nor_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev = {
+			.platform_data = &taishan_nor_data,
+		},
+	.num_resources	= 1,
+	.resource	= &taishan_nor_resource,
+};
+
+static int taishan_setup_flash(void)
+{
+	/*
+	 * Adjust partition 2 to flash size
+	 */
+	taishan_nor_parts[2].size = __res.bi_flashsize -
+		RW_PART0_SZ - RW_PART1_SZ - RW_PART3_SZ - RW_PART4_SZ;
+
+	platform_device_register(&taishan_nor_device);
+
+	return 0;
+}
+arch_initcall(taishan_setup_flash);
+
+static void __init
+taishan_calibrate_decr(void)
+{
+	unsigned int freq;
+
+	if (mfspr(SPRN_CCR1) & CCR1_TCS)
+		freq = TAISHAN_TMR_CLK;
+	else
+		freq = clocks.cpu;
+
+	ibm44x_calibrate_decr(freq);
+}
+
+static int
+taishan_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: AMCC\n");
+	seq_printf(m, "machine\t\t: PPC440GX EVB (Taishan)\n");
+	ibm440gx_show_cpuinfo(m);
+	return 0;
+}
+
+static inline int
+taishan_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *	PCI IDSEL/INTPIN->INTLINE
+	 * 	   A   B   C   D
+	 */
+	{
+		{ 23, 24, 25, 26 },	/* IDSEL 1 - PCI Slot 0 */
+		{ 24, 25, 26, 23 },	/* IDSEL 2 - PCI Slot 1 */
+	};
+
+	const long min_idsel = 1, max_idsel = 2, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init taishan_set_emacdata(void)
+{
+	struct ocp_def *def;
+	struct ocp_func_emac_data *emacdata;
+	int i;
+
+	/* Set phy_map, phy_mode, and mac_addr for each EMAC */
+	for (i=2; i<4; i++) {
+		def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i);
+		emacdata = def->additions;
+		if (i < 2) {
+			emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
+			emacdata->phy_mode = PHY_MODE_SMII;
+		} else {
+			emacdata->phy_map = 0x00000001; /* Skip 0x00 */
+			emacdata->phy_mode = PHY_MODE_RGMII;
+		}
+		if (i == 0)
+			memcpy(emacdata->mac_addr, "\0\0\0\0\0\0", 6);
+		else if (i == 1)
+			memcpy(emacdata->mac_addr, "\0\0\0\0\0\0", 6);
+		else if (i == 2)
+			memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+		else if (i == 3)
+			memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
+	}
+}
+
+#define PCIX_READW(offset) \
+	(readw(pcix_reg_base+offset))
+
+#define PCIX_WRITEW(value, offset) \
+	(writew(value, pcix_reg_base+offset))
+
+#define PCIX_WRITEL(value, offset) \
+	(writel(value, pcix_reg_base+offset))
+
+/*
+ * FIXME: This is only here to "make it work".  This will move
+ * to a ibm_pcix.c which will contain a generic IBM PCIX bridge
+ * configuration library. -Matt
+ */
+static void __init
+taishan_setup_pcix(void)
+{
+	void *pcix_reg_base;
+
+	pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX_REG_SIZE);
+
+	/* Enable PCIX0 I/O, Mem, and Busmaster cycles */
+	PCIX_WRITEW(PCIX_READW(PCIX0_COMMAND) | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, PCIX0_COMMAND);
+
+	/* Disable all windows */
+	PCIX_WRITEL(0, PCIX0_POM0SA);
+	PCIX_WRITEL(0, PCIX0_POM1SA);
+	PCIX_WRITEL(0, PCIX0_POM2SA);
+	PCIX_WRITEL(0, PCIX0_PIM0SA);
+	PCIX_WRITEL(0, PCIX0_PIM0SAH);
+	PCIX_WRITEL(0, PCIX0_PIM1SA);
+	PCIX_WRITEL(0, PCIX0_PIM2SA);
+	PCIX_WRITEL(0, PCIX0_PIM2SAH);
+
+	/* Setup 2GB PLB->PCI outbound mem window (3_8000_0000->0_8000_0000) */
+	PCIX_WRITEL(0x00000003, PCIX0_POM0LAH);
+	PCIX_WRITEL(0x80000000, PCIX0_POM0LAL);
+	PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH);
+	PCIX_WRITEL(0x80000000, PCIX0_POM0PCIAL);
+	PCIX_WRITEL(0x80000001, PCIX0_POM0SA);
+
+	/* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
+	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
+	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
+	PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA);
+	PCIX_WRITEL(0xffffffff, PCIX0_PIM0SAH);
+
+	iounmap(pcix_reg_base);
+
+	eieio();
+}
+
+static void __init
+taishan_setup_hose(void)
+{
+	struct pci_controller *hose;
+
+	/* Configure windows on the PCI-X host bridge */
+	taishan_setup_pcix();
+
+	hose = pcibios_alloc_controller();
+
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	hose->pci_mem_offset = TAISHAN_PCI_MEM_OFFSET;
+
+	pci_init_resource(&hose->io_resource,
+			TAISHAN_PCI_LOWER_IO,
+			TAISHAN_PCI_UPPER_IO,
+			IORESOURCE_IO,
+			"PCI host bridge");
+
+	pci_init_resource(&hose->mem_resources[0],
+			TAISHAN_PCI_LOWER_MEM,
+			TAISHAN_PCI_UPPER_MEM,
+			IORESOURCE_MEM,
+			"PCI host bridge");
+
+	hose->io_space.start = TAISHAN_PCI_LOWER_IO;
+	hose->io_space.end = TAISHAN_PCI_UPPER_IO;
+	hose->mem_space.start = TAISHAN_PCI_LOWER_MEM;
+	hose->mem_space.end = TAISHAN_PCI_UPPER_MEM;
+	hose->io_base_virt = ioremap64(TAISHAN_PCI_IO_BASE, TAISHAN_PCI_IO_SIZE);
+	isa_io_base = (unsigned long) hose->io_base_virt;
+
+	setup_indirect_pci(hose,
+			TAISHAN_PCI_CFGA_PLB32,
+			TAISHAN_PCI_CFGD_PLB32);
+	hose->set_cfg_type = 1;
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = taishan_map_irq;
+}
+
+
+static void __init
+taishan_early_serial_map(void)
+{
+	struct uart_port port;
+
+	/* Setup ioremapped serial port access */
+	memset(&port, 0, sizeof(port));
+	port.membase = ioremap64(PPC440GX_UART0_ADDR, 8);
+	port.irq = UART0_INT;
+	port.uartclk = clocks.uart0;
+	port.regshift = 0;
+	port.iotype = UPIO_MEM;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	port.line = 0;
+
+	if (early_serial_setup(&port) != 0)
+		printk("Early serial init of port 0 failed\n");
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	/* Configure debug serial access */
+	gen550_init(0, &port);
+
+	/* Purge TLB entry added in head_44x.S for early serial access */
+	_tlbie(UART0_IO_BASE);
+#endif
+
+	port.membase = ioremap64(PPC440GX_UART1_ADDR, 8);
+	port.irq = UART1_INT;
+	port.uartclk = clocks.uart1;
+	port.line = 1;
+
+	if (early_serial_setup(&port) != 0)
+		printk("Early serial init of port 1 failed\n");
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	/* Configure debug serial access */
+	gen550_init(1, &port);
+#endif
+}
+
+static void __init
+taishan_setup_arch(void)
+{
+	taishan_set_emacdata();
+
+	ibm440gx_tah_enable();
+
+	/*
+	 * Determine various clocks.
+	 * To be completely correct we should get SysClk
+	 * from FPGA, because it can be changed by on-board switches
+	 * --ebs
+	 */
+	ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+	ocp_sys_info.opb_bus_freq = clocks.opb;
+
+	/* init to some ~sane value until calibrate_delay() runs */
+        loops_per_jiffy = 50000000/HZ;
+
+	/* Setup PCI host bridge */
+	taishan_setup_hose();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+
+	taishan_early_serial_map();
+
+	/* Identify the system */
+	printk("AMCC PowerPC 440GX Taishan Platform\n");
+}
+
+static void __init taishan_init(void)
+{
+	ibm440gx_l2c_setup(&clocks);
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+		unsigned long r5, unsigned long r6, unsigned long r7)
+{
+	ibm44x_platform_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = taishan_setup_arch;
+	ppc_md.show_cpuinfo = taishan_show_cpuinfo;
+	ppc_md.get_irq = NULL;		/* Set in ppc4xx_pic_init() */
+
+	ppc_md.calibrate_decr = taishan_calibrate_decr;
+
+#ifdef CONFIG_KGDB
+	ppc_md.early_serial_map = taishan_early_serial_map;
+#endif
+	ppc_md.init = taishan_init;
+}
+
diff --git a/arch/ppc/platforms/4xx/taishan.h b/arch/ppc/platforms/4xx/taishan.h
new file mode 100644
index 0000000..ea7561a
--- /dev/null
+++ b/arch/ppc/platforms/4xx/taishan.h
@@ -0,0 +1,67 @@
+/*
+ * arch/ppc/platforms/4xx/taishan.h
+ *
+ * AMCC Taishan board definitions
+ *
+ * Copyright 2007 DENX Software Engineering, Stefan Roese <sr@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_TAISHAN_H__
+#define __ASM_TAISHAN_H__
+
+#include <platforms/4xx/ibm440gx.h>
+
+/* External timer clock frequency */
+#define TAISHAN_TMR_CLK	25000000
+
+/* Flash */
+#define TAISHAN_FPGA_ADDR		0x0000000141000000ULL
+#define TAISHAN_LCM_ADDR		0x0000000142000000ULL
+#define TAISHAN_FLASH_ADDR		0x00000001fc000000ULL
+#define TAISHAN_FLASH_SIZE		0x4000000
+
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE	2
+
+/* head_44x.S created UART mapping, used before early_serial_setup.
+ * We cannot use default OpenBIOS UART mappings because they
+ * don't work for configurations with more than 512M RAM.    --ebs
+ */
+#define UART0_IO_BASE	0xF0000200
+#define UART1_IO_BASE	0xF0000300
+
+#define BASE_BAUD	11059200/16
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: (void*)UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+
+/* PCI support */
+#define TAISHAN_PCI_LOWER_IO	0x00000000
+#define TAISHAN_PCI_UPPER_IO	0x0000ffff
+#define TAISHAN_PCI_LOWER_MEM	0x80000000
+#define TAISHAN_PCI_UPPER_MEM	0xffffefff
+
+#define TAISHAN_PCI_CFGA_PLB32	0x0ec00000
+#define TAISHAN_PCI_CFGD_PLB32	0x0ec00004
+
+#define TAISHAN_PCI_IO_BASE	0x0000000208000000ULL
+#define TAISHAN_PCI_IO_SIZE	0x00010000
+#define TAISHAN_PCI_MEM_OFFSET	0x00000000
+
+#endif				/* __ASM_TAISHAN_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
index 18dc6e8..b947c77 100644
--- a/arch/ppc/platforms/lopec.c
+++ b/arch/ppc/platforms/lopec.c
@@ -344,7 +344,7 @@
 		 if (bootargs != NULL) {
 			 strcpy(cmd_line, bootargs);
 			 /* again.. */
-			 strcpy(saved_command_line, cmd_line);
+			 strcpy(boot_command_line, cmd_line);
 		}
 	}
 #endif
diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
index 9778105..8a1788c 100644
--- a/arch/ppc/platforms/pplus.c
+++ b/arch/ppc/platforms/pplus.c
@@ -592,7 +592,7 @@
 		if (bootargs != NULL) {
 			strcpy(cmd_line, bootargs);
 			/* again.. */
-			strcpy(saved_command_line, cmd_line);
+			strcpy(boot_command_line, cmd_line);
 		}
 	}
 #endif
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 1cb75a1..f166299 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -634,7 +634,7 @@
 	/*
 	 * Find a way to push these informations to the cs4232 driver
 	 * Give it out with printk, when not in cmd_line?
-	 * Append it to  cmd_line and saved_command_line?
+	 * Append it to  cmd_line and boot_command_line?
 	 * Format is cs4232=io,irq,dma,dma2
 	 */
 }
@@ -897,7 +897,7 @@
 		 if (bootargs != NULL) {
 			 strcpy(cmd_line, bootargs);
 			 /* again.. */
-			 strcpy(saved_command_line, cmd_line);
+			 strcpy(boot_command_line, cmd_line);
 		}
 	}
 
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index d84f0466..0991111 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -69,6 +69,7 @@
 obj-$(CONFIG_SBC82xx)		+= todc_time.o
 obj-$(CONFIG_SPRUCE)		+= cpc700_pic.o pci_auto.o \
 				   todc_time.o
+obj-$(CONFIG_TAISHAN)		+= pci_auto.o
 obj-$(CONFIG_8260)		+= m8260_setup.o pq2_devices.o pq2_sys.o \
 				   ppc_sys.o
 obj-$(CONFIG_PCI_8260)		+= m82xx_pci.o pci_auto.o
diff --git a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c
index a43dda5..1e5a00a4 100644
--- a/arch/ppc/syslib/i8259.c
+++ b/arch/ppc/syslib/i8259.c
@@ -154,7 +154,7 @@
 
 static struct irqaction i8259_irqaction = {
 	.handler = no_action,
-	.flags = SA_INTERRUPT,
+	.flags = IRQF_DISABLED,
 	.mask = CPU_MASK_NONE,
 	.name = "82c59 secondary cascade",
 };
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index eaed402..d9425f5 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -7,6 +7,10 @@
 	bool
 	default y
 
+config ZONE_DMA
+	def_bool y
+	depends on 64BIT
+
 config LOCKDEP_SUPPORT
 	bool
 	default y
@@ -37,6 +41,9 @@
 config GENERIC_TIME
 	def_bool y
 
+config NO_IOMEM
+	def_bool y
+
 mainmenu "Linux Kernel Configuration"
 
 config S390
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 6598e52..b1e5584 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -82,18 +82,18 @@
 OBJCOPYFLAGS	:= -O binary
 LDFLAGS_vmlinux := -e start
 
-head-y		:= arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
+head-y		:= arch/s390/kernel/head.o arch/s390/kernel/init_task.o
 
-core-y		+= arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \
-		   arch/$(ARCH)/appldata/ arch/$(ARCH)/hypfs/
-libs-y		+= arch/$(ARCH)/lib/
+core-y		+= arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
+		   arch/s390/appldata/ arch/s390/hypfs/
+libs-y		+= arch/s390/lib/
 drivers-y	+= drivers/s390/
-drivers-$(CONFIG_MATHEMU) += arch/$(ARCH)/math-emu/
+drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
 
 # must be linked after kernel
 drivers-$(CONFIG_OPROFILE)	+= arch/s390/oprofile/
 
-boot		:= arch/$(ARCH)/boot
+boot		:= arch/s390/boot
 
 all: image
 
diff --git a/arch/s390/appldata/appldata.h b/arch/s390/appldata/appldata.h
index 0429481..4069b81 100644
--- a/arch/s390/appldata/appldata.h
+++ b/arch/s390/appldata/appldata.h
@@ -21,8 +21,7 @@
 #define APPLDATA_RECORD_NET_SUM_ID	0x03	/* must be < 256 !     */
 #define APPLDATA_RECORD_PROC_ID		0x04
 
-#define CTL_APPLDATA 		2120	/* sysctl IDs, must be unique */
-#define CTL_APPLDATA_TIMER 	2121
+#define CTL_APPLDATA_TIMER 	2121	/* sysctl IDs, must be unique */
 #define CTL_APPLDATA_INTERVAL 	2122
 #define CTL_APPLDATA_MEM	2123
 #define CTL_APPLDATA_OS		2124
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index c9da7d1..0c3cf4b 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -506,7 +506,7 @@
 
 	ops->ctl_table[3].ctl_name = 0;
 
-	ops->sysctl_header = register_sysctl_table(ops->ctl_table,1);
+	ops->sysctl_header = register_sysctl_table(ops->ctl_table);
 
 	P_INFO("%s-ops registered!\n", ops->name);
 	return 0;
@@ -606,7 +606,7 @@
 	/* Register cpu hotplug notifier */
 	register_hotcpu_notifier(&appldata_nb);
 
-	appldata_sysctl_header = register_sysctl_table(appldata_dir_table, 1);
+	appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
 #ifdef MODULE
 	appldata_dir_table[0].de->owner = THIS_MODULE;
 	appldata_table[0].de->owner = THIS_MODULE;
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 7c621b8..741d2bbb 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,9 +1,10 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc1
-# Fri Dec 15 16:52:28 2006
+# Linux kernel version: 2.6.21-rc1
+# Wed Feb 21 10:44:30 2007
 #
 CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -11,6 +12,7 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_TIME=y
+CONFIG_NO_IOMEM=y
 CONFIG_S390=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -29,6 +31,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -133,6 +136,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_HOLES_IN_ZONE=y
 
 #
@@ -178,7 +182,11 @@
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_IUCV=m
+CONFIG_AFIUCV=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -193,7 +201,7 @@
 # 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_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
@@ -311,6 +319,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 CONFIG_SYS_HYPERVISOR=y
 
 #
@@ -508,7 +517,6 @@
 #
 CONFIG_LCS=m
 CONFIG_CTC=m
-CONFIG_IUCV=m
 # CONFIG_NETIUCV is not set
 # CONFIG_SMSGIUCV is not set
 # CONFIG_CLAW is not set
@@ -685,13 +693,13 @@
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_DEBUG_PREEMPT=y
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
@@ -701,10 +709,10 @@
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
-# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
 
 #
 # Security options
@@ -732,8 +740,10 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
 # CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_FCRYPT=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
@@ -747,6 +757,7 @@
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -767,4 +778,3 @@
 CONFIG_CRC32=m
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index a4fda7b..ba5d316 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -34,7 +34,7 @@
 	struct mutex lock;		/* lock to protect update process */
 };
 
-static struct file_operations hypfs_file_ops;
+static const struct file_operations hypfs_file_ops;
 static struct file_system_type hypfs_type;
 static struct super_operations hypfs_s_ops;
 
@@ -440,7 +440,7 @@
 	return dentry;
 }
 
-static struct file_operations hypfs_file_ops = {
+static const struct file_operations hypfs_file_ops = {
 	.open		= hypfs_open,
 	.release	= hypfs_release,
 	.read		= do_sync_read,
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 666bb6d..664c669 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -398,51 +398,6 @@
 	return err;
 }
 
-struct sysinfo32 {
-        s32 uptime;
-        u32 loads[3];
-        u32 totalram;
-        u32 freeram;
-        u32 sharedram;
-        u32 bufferram;
-        u32 totalswap;
-        u32 freeswap;
-        unsigned short procs;
-	unsigned short pads;
-	u32 totalhigh;
-	u32 freehigh;
-	unsigned int mem_unit;
-        char _f[8];
-};
-
-asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info)
-{
-	struct sysinfo s;
-	int ret, err;
-	mm_segment_t old_fs = get_fs ();
-	
-	set_fs (KERNEL_DS);
-	ret = sys_sysinfo((struct sysinfo __force __user *) &s);
-	set_fs (old_fs);
-	err = put_user (s.uptime, &info->uptime);
-	err |= __put_user (s.loads[0], &info->loads[0]);
-	err |= __put_user (s.loads[1], &info->loads[1]);
-	err |= __put_user (s.loads[2], &info->loads[2]);
-	err |= __put_user (s.totalram, &info->totalram);
-	err |= __put_user (s.freeram, &info->freeram);
-	err |= __put_user (s.sharedram, &info->sharedram);
-	err |= __put_user (s.bufferram, &info->bufferram);
-	err |= __put_user (s.totalswap, &info->totalswap);
-	err |= __put_user (s.freeswap, &info->freeswap);
-	err |= __put_user (s.procs, &info->procs);
-	err |= __put_user (s.totalhigh, &info->totalhigh);
-	err |= __put_user (s.freehigh, &info->freehigh);
-	err |= __put_user (s.mem_unit, &info->mem_unit);
-	if (err)
-		return -EFAULT;
-	return ret;
-}
-
 asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid,
 				struct compat_timespec __user *interval)
 {
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 71e54ef..9790129 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -517,10 +517,10 @@
 	llgtr	%r2,%r2			# const char *
 	jg	sys_swapoff		# branch to system call
 
-	.globl	sys32_sysinfo_wrapper
-sys32_sysinfo_wrapper:
+	.globl	compat_sys_sysinfo_wrapper
+compat_sys_sysinfo_wrapper:
 	llgtr	%r2,%r2			# struct sysinfo_emu31 *
-	jg	sys32_sysinfo		# branch to system call
+	jg	compat_sys_sysinfo	# branch to system call
 
 	.globl	sys32_ipc_wrapper
 sys32_ipc_wrapper:
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index f4b62df..eca3fe5 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -167,7 +167,7 @@
 
 static int initialized;
 
-static struct file_operations debug_file_ops = {
+static const struct file_operations debug_file_ops = {
 	.owner   = THIS_MODULE,
 	.read    = debug_output,
 	.write   = debug_input,
@@ -852,7 +852,6 @@
 static int debug_stoppable=1;
 static int debug_active=1;
 
-#define CTL_S390DBF 5677
 #define CTL_S390DBF_STOPPABLE 5678
 #define CTL_S390DBF_ACTIVE 5679
 
@@ -1054,7 +1053,7 @@
 {
 	int rc = 0;
 
-	s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table, 1);
+	s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
 	down(&debug_lock);
 	debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
 	printk(KERN_INFO "debug: Initialization complete\n");
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index e518dd5..afca1c6 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/pfn.h>
 #include <linux/uaccess.h>
+#include <asm/ipl.h>
 #include <asm/lowcore.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
@@ -109,7 +110,7 @@
  */
 static noinline __init void clear_bss_section(void)
 {
-	memset(__bss_start, 0, _end - __bss_start);
+	memset(__bss_start, 0, __bss_stop - __bss_start);
 }
 
 /*
@@ -129,7 +130,7 @@
 {
 	struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
 
-	asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id));
+	get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
 
 	/* Running under z/VM ? */
 	if (cpuinfo->cpu_id.version == 0xff)
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index 453fd3b..da7c8bb 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -148,20 +148,9 @@
 .Lstartup_init:
 	    .long startup_init
 
-	.globl ipl_schib
-ipl_schib:
-	.rept 13
-	.long 0
-	.endr
-
-	.globl ipl_flags
-ipl_flags:
-	.long 0
-	.globl ipl_devno
-ipl_devno:
-	.word 0
-
 	.org	0x12000
+	.globl	_ehead
+_ehead:
 #ifdef CONFIG_SHARED_KERNEL
 	.org	0x100000
 #endif
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index b8fec4e..af09e18 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -154,21 +154,9 @@
 .Lparmaddr:
 	.quad	PARMAREA
 
-	.globl	ipl_schib
-ipl_schib:
-	.rept 13
-	.long 0
-	.endr
-
-	.globl	ipl_flags
-ipl_flags:
-	.long	0
-	.globl	ipl_devno
-ipl_devno:
-	.word 0
-
 	.org	0x12000
-
+	.globl	_ehead
+_ehead:
 #ifdef CONFIG_SHARED_KERNEL
 	.org	0x100000
 #endif
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 0522595..5a863a3 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/ctype.h>
+#include <asm/ipl.h>
 #include <asm/smp.h>
 #include <asm/setup.h>
 #include <asm/cpcmd.h>
@@ -42,6 +43,13 @@
 #define IPL_FCP_STR	 "fcp"
 #define IPL_NSS_STR	 "nss"
 
+/*
+ * Must be in data section since the bss section
+ * is not cleared when these are accessed.
+ */
+u16 ipl_devno __attribute__((__section__(".data"))) = 0;
+u32 ipl_flags __attribute__((__section__(".data"))) = 0;
+
 static char *ipl_type_str(enum ipl_type type)
 {
 	switch (type) {
@@ -90,31 +98,10 @@
 	case SHUTDOWN_STOP:
 		return SHUTDOWN_STOP_STR;
 	default:
-		BUG();
+		return NULL;
 	}
 }
 
-enum diag308_subcode  {
-	DIAG308_IPL   = 3,
-	DIAG308_DUMP  = 4,
-	DIAG308_SET   = 5,
-	DIAG308_STORE = 6,
-};
-
-enum diag308_ipl_type {
-	DIAG308_IPL_TYPE_FCP = 0,
-	DIAG308_IPL_TYPE_CCW = 2,
-};
-
-enum diag308_opt {
-	DIAG308_IPL_OPT_IPL  = 0x10,
-	DIAG308_IPL_OPT_DUMP = 0x20,
-};
-
-enum diag308_rc {
-	DIAG308_RC_OK = 1,
-};
-
 static int diag308_set_works = 0;
 
 static int reipl_capabilities = IPL_TYPE_UNKNOWN;
@@ -134,7 +121,7 @@
 
 static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
 
-static int diag308(unsigned long subcode, void *addr)
+int diag308(unsigned long subcode, void *addr)
 {
 	register unsigned long _addr asm("0") = (unsigned long) addr;
 	register unsigned long _rc asm("1") = 0;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 0373981..863c8d0 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -41,6 +41,7 @@
 #include <linux/ctype.h>
 #include <linux/reboot.h>
 
+#include <asm/ipl.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/smp.h>
@@ -106,7 +107,7 @@
         /*
          * Store processor id in lowcore (used e.g. in timer_interrupt)
          */
-	asm volatile("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
+	get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
         S390_lowcore.cpu_data.cpu_addr = addr;
 
         /*
@@ -689,9 +690,14 @@
 	psw_set_key(PAGE_DEFAULT_KEY);
 
 	free_bootmem_with_active_regions(0, max_pfn);
-	reserve_bootmem(0, PFN_PHYS(start_pfn));
 
 	/*
+	 * Reserve memory used for lowcore/command line/kernel image.
+	 */
+	reserve_bootmem(0, (unsigned long)_ehead);
+	reserve_bootmem((unsigned long)_stext,
+			PFN_PHYS(start_pfn) - (unsigned long)_stext);
+	/*
 	 * Reserve the bootmem bitmap itself as well. We do this in two
 	 * steps (first step was init_bootmem()) because this catches
 	 * the (very unlikely) case of us accidentally initializing the
@@ -740,7 +746,7 @@
 #endif /* CONFIG_64BIT */
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
 
 	*cmdline_p = COMMAND_LINE;
 	*(*cmdline_p + COMMAND_LINE_SIZE - 1) = '\0';
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 65b5232..ecaa432 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/cpu.h>
 #include <linux/timex.h>
+#include <asm/ipl.h>
 #include <asm/setup.h>
 #include <asm/sigp.h>
 #include <asm/pgalloc.h>
@@ -54,19 +55,18 @@
 static struct task_struct *current_set[NR_CPUS];
 
 static void smp_ext_bitcall(int, ec_bit_sig);
-static void smp_ext_bitcall_others(ec_bit_sig);
 
 /*
-5B * Structure and data for smp_call_function(). This is designed to minimise
- * static memory requirements. It also looks cleaner.
+ * Structure and data for __smp_call_function_map(). This is designed to
+ * minimise static memory requirements. It also looks cleaner.
  */
 static DEFINE_SPINLOCK(call_lock);
 
 struct call_data_struct {
 	void (*func) (void *info);
 	void *info;
-	atomic_t started;
-	atomic_t finished;
+	cpumask_t started;
+	cpumask_t finished;
 	int wait;
 };
 
@@ -81,115 +81,113 @@
 	void *info = call_data->info;
 	int wait = call_data->wait;
 
-	atomic_inc(&call_data->started);
+	cpu_set(smp_processor_id(), call_data->started);
 	(*func)(info);
 	if (wait)
-		atomic_inc(&call_data->finished);
+		cpu_set(smp_processor_id(), call_data->finished);;
 }
 
-/*
- * this function sends a 'generic call function' IPI to all other CPUs
- * in the system.
- */
-
-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
-			int wait)
-/*
- * [SUMMARY] 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.
- */
+static void __smp_call_function_map(void (*func) (void *info), void *info,
+				    int nonatomic, int wait, cpumask_t map)
 {
 	struct call_data_struct data;
-	int cpus = num_online_cpus()-1;
+	int cpu, local = 0;
 
-	if (cpus <= 0)
-		return 0;
+	/*
+	 * Can deadlock when interrupts are disabled or if in wrong context,
+	 * caller must disable preemption
+	 */
+	WARN_ON(irqs_disabled() || in_irq() || preemptible());
 
-	/* Can deadlock when called with interrupts disabled */
-	WARN_ON(irqs_disabled());
-
-	data.func = func;
-	data.info = info;
-	atomic_set(&data.started, 0);
-	data.wait = wait;
-	if (wait)
-		atomic_set(&data.finished, 0);
-
-	spin_lock(&call_lock);
-	call_data = &data;
-	/* Send a message to all other CPUs and wait for them to respond */
-        smp_ext_bitcall_others(ec_call_function);
-
-	/* Wait for response */
-	while (atomic_read(&data.started) != cpus)
-		cpu_relax();
-
-	if (wait)
-		while (atomic_read(&data.finished) != cpus)
-			cpu_relax();
-	spin_unlock(&call_lock);
-
-	return 0;
-}
-
-/*
- * Call a function on one CPU
- * cpu : the CPU the function should be executed on
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler. You may call it from a bottom half.
- *
- * It is guaranteed that the called function runs on the specified CPU,
- * preemption is disabled.
- */
-int smp_call_function_on(void (*func) (void *info), void *info,
-			 int nonatomic, int wait, int cpu)
-{
-	struct call_data_struct data;
-	int curr_cpu;
-
-	if (!cpu_online(cpu))
-		return -EINVAL;
-
-	/* disable preemption for local function call */
-	curr_cpu = get_cpu();
-
-	if (curr_cpu == cpu) {
-		/* direct call to function */
-		func(info);
-		put_cpu();
-		return 0;
+	/*
+	 * Check for local function call. We have to have the same call order
+	 * as in on_each_cpu() because of machine_restart_smp().
+	 */
+	if (cpu_isset(smp_processor_id(), map)) {
+		local = 1;
+		cpu_clear(smp_processor_id(), map);
 	}
 
+	cpus_and(map, map, cpu_online_map);
+	if (cpus_empty(map))
+		goto out;
+
 	data.func = func;
 	data.info = info;
-	atomic_set(&data.started, 0);
+	data.started = CPU_MASK_NONE;
 	data.wait = wait;
 	if (wait)
-		atomic_set(&data.finished, 0);
+		data.finished = CPU_MASK_NONE;
 
 	spin_lock_bh(&call_lock);
 	call_data = &data;
-	smp_ext_bitcall(cpu, ec_call_function);
+
+	for_each_cpu_mask(cpu, map)
+		smp_ext_bitcall(cpu, ec_call_function);
 
 	/* Wait for response */
-	while (atomic_read(&data.started) != 1)
+	while (!cpus_equal(map, data.started))
 		cpu_relax();
 
 	if (wait)
-		while (atomic_read(&data.finished) != 1)
+		while (!cpus_equal(map, data.finished))
 			cpu_relax();
 
 	spin_unlock_bh(&call_lock);
-	put_cpu();
+
+out:
+	local_irq_disable();
+	if (local)
+		func(info);
+	local_irq_enable();
+}
+
+/*
+ * smp_call_function:
+ * @func: the function to run; this must be fast and non-blocking
+ * @info: an arbitrary pointer to pass to the function
+ * @nonatomic: unused
+ * @wait: if true, wait (atomically) until function has completed on other CPUs
+ *
+ * Run a function on all other CPUs.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler. Must be called with preemption disabled.
+ * You may call it from a bottom half.
+ */
+int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
+		      int wait)
+{
+	cpumask_t map;
+
+	map = cpu_online_map;
+	cpu_clear(smp_processor_id(), map);
+	__smp_call_function_map(func, info, nonatomic, wait, map);
+	return 0;
+}
+EXPORT_SYMBOL(smp_call_function);
+
+/*
+ * smp_call_function_on:
+ * @func: the function to run; this must be fast and non-blocking
+ * @info: an arbitrary pointer to pass to the function
+ * @nonatomic: unused
+ * @wait: if true, wait (atomically) until function has completed on other CPUs
+ * @cpu: the CPU where func should run
+ *
+ * Run a function on one processor.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler. Must be called with preemption disabled.
+ * You may call it from a bottom half.
+ */
+int smp_call_function_on(void (*func) (void *info), void *info, int nonatomic,
+			  int wait, int cpu)
+{
+	cpumask_t map = CPU_MASK_NONE;
+
+	cpu_set(cpu, map);
+	__smp_call_function_map(func, info, nonatomic, wait, map);
 	return 0;
 }
 EXPORT_SYMBOL(smp_call_function_on);
@@ -322,26 +320,6 @@
 		udelay(10);
 }
 
-/*
- * Send an external call sigp to every other cpu in the system and
- * return without waiting for its completion.
- */
-static void smp_ext_bitcall_others(ec_bit_sig sig)
-{
-        int cpu;
-
-	for_each_online_cpu(cpu) {
-		if (cpu == smp_processor_id())
-                        continue;
-                /*
-                 * Set signaling bit in lowcore of target cpu and kick it
-                 */
-		set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
-		while (signal_processor(cpu, sigp_emergency_signal) == sigp_busy)
-			udelay(10);
-        }
-}
-
 #ifndef CONFIG_64BIT
 /*
  * this function sends a 'purge tlb' signal to another CPU.
@@ -804,6 +782,5 @@
 EXPORT_SYMBOL(lowcore_ptr);
 EXPORT_SYMBOL(smp_ctl_set_bit);
 EXPORT_SYMBOL(smp_ctl_clear_bit);
-EXPORT_SYMBOL(smp_call_function);
 EXPORT_SYMBOL(smp_get_cpu);
 EXPORT_SYMBOL(smp_put_cpu);
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index a4ceae3..a52c444 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -124,7 +124,7 @@
 NI_SYSCALL							/* vm86old for i386 */
 SYSCALL(sys_wait4,sys_wait4,compat_sys_wait4_wrapper)
 SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper)		/* 115 */
-SYSCALL(sys_sysinfo,sys_sysinfo,sys32_sysinfo_wrapper)
+SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper)
 SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper)
 SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper)
 SYSCALL(sys_sigreturn_glue,sys_sigreturn_glue,sys32_sigreturn_glue)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 3b91f27..e1ad464 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -312,7 +312,7 @@
 	.mask		= -1ULL,
 	.mult		= 1000,
 	.shift		= 12,
-	.is_continuous	= 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 
@@ -747,6 +747,7 @@
 	}
 }
 
+#ifdef CONFIG_SMP
 static void etr_sync_cpu_start(void *dummy)
 {
 	int *in_sync = dummy;
@@ -758,8 +759,14 @@
 	 * __udelay will stop the cpu on an enabled wait psw until the
 	 * TOD is running again.
 	 */
-	while (*in_sync == 0)
+	while (*in_sync == 0) {
 		__udelay(1);
+		/*
+		 * A different cpu changes *in_sync. Therefore use
+		 * barrier() to force memory access.
+		 */
+		barrier();
+	}
 	if (*in_sync != 1)
 		/* Didn't work. Clear per-cpu in sync bit again. */
 		etr_disable_sync_clock(NULL);
@@ -773,6 +780,7 @@
 static void etr_sync_cpu_end(void *dummy)
 {
 }
+#endif /* CONFIG_SMP */
 
 /*
  * Sync the TOD clock using the port refered to by aibp. This port
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index a489073..c30716a 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -91,11 +91,14 @@
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
   SECURITY_INIT
+
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(256);
   __initramfs_start = .;
   .init.ramfs : { *(.init.initramfs) }
   . = ALIGN(2);
   __initramfs_end = .;
+#endif
   . = ALIGN(256);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 0285444..70f2a86 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/timex.h>
 #include <linux/irqflags.h>
+#include <linux/interrupt.h>
 
 void __delay(unsigned long loops)
 {
@@ -35,7 +36,11 @@
 {
 	u64 end, time, jiffy_timer = 0;
 	unsigned long flags, cr0, mask, dummy;
+	int irq_context;
 
+	irq_context = in_interrupt();
+	if (!irq_context)
+		local_bh_disable();
 	local_irq_save(flags);
 	if (raw_irqs_disabled_flags(flags)) {
 		jiffy_timer = S390_lowcore.jiffy_timer;
@@ -62,6 +67,8 @@
 		__ctl_load(cr0, 0, 0);
 		S390_lowcore.jiffy_timer = jiffy_timer;
 	}
+	if (!irq_context)
+		_local_bh_enable();
 	set_clock_comparator(S390_lowcore.jiffy_timer);
 	local_irq_restore(flags);
 }
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index 8e09db1..f95449b 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -2,6 +2,6 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-obj-y	 := init.o fault.o ioremap.o extmem.o mmap.o vmem.o
+obj-y	 := init.o fault.o extmem.o mmap.o vmem.o
 obj-$(CONFIG_CMM) += cmm.o
 
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index f93a056..c5b2f4f 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -256,10 +256,6 @@
 }
 
 #ifdef CONFIG_CMM_PROC
-/* These will someday get removed. */
-#define VM_CMM_PAGES		1111
-#define VM_CMM_TIMED_PAGES	1112
-#define VM_CMM_TIMEOUT		1113
 
 static struct ctl_table cmm_table[];
 
@@ -422,7 +418,7 @@
 	int rc = -ENOMEM;
 
 #ifdef CONFIG_CMM_PROC
-	cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1);
+	cmm_sysctl_header = register_sysctl_table(cmm_dir_table);
 	if (!cmm_sysctl_header)
 		goto out;
 #endif
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 9ff143e..641aef3 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -83,12 +83,10 @@
 }
 #endif
 
-extern spinlock_t timerlist_lock;
 
 /*
  * Unlock any spinlocks which will prevent us from getting the
- * message out (timerlist_lock is acquired through the
- * console unblank code)
+ * message out.
  */
 void bust_spinlocks(int yes)
 {
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index b3e7c45..916b72a 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -141,7 +141,9 @@
 	__raw_local_irq_ssm(ssm_mask);
 
 	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+#ifdef CONFIG_ZONE_DMA
 	max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
+#endif
 	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 	free_area_init_nodes(max_zone_pfns);
 }
diff --git a/arch/s390/mm/ioremap.c b/arch/s390/mm/ioremap.c
deleted file mode 100644
index 3d2100a..0000000
--- a/arch/s390/mm/ioremap.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *  arch/s390/mm/ioremap.c
- *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Hartmut Penner (hp@de.ibm.com)
- *
- *  Derived from "arch/i386/mm/extable.c"
- *    (C) Copyright 1995 1996 Linus Torvalds
- *
- * Re-map IO memory to kernel address space so that we can access it.
- * This is needed for high PCI addresses that aren't mapped in the
- * 640k-1MB IO memory area on PC's
- */
-
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/io.h>
-#include <asm/pgalloc.h>
-
-/*
- * Generic mapping function (not visible outside):
- */
-
-/*
- * Remap an arbitrary physical address space into the kernel virtual
- * address space. Needed when the kernel wants to access high addresses
- * directly.
- */
-void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
-{
-	void * addr;
-	struct vm_struct * area;
-
-	if (phys_addr < virt_to_phys(high_memory))
-		return phys_to_virt(phys_addr);
-	if (phys_addr & ~PAGE_MASK)
-		return NULL;
-	size = PAGE_ALIGN(size);
-	if (!size || size > phys_addr + size)
-		return NULL;
-	area = get_vm_area(size, VM_IOREMAP);
-	if (!area)
-		return NULL;
-	addr = area->addr;
-	if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
-			       phys_addr, __pgprot(flags))) {
-		vfree(addr);
-		return NULL;
-	}
-	return addr;
-}
-
-void iounmap(void *addr)
-{
-	if (addr > high_memory)
-		vfree(addr);
-}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 3aa3b88..4d16d89 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -48,6 +48,9 @@
 config GENERIC_TIME
 	def_bool n
 
+config SYS_SUPPORTS_APM_EMULATION
+	bool
+
 config ARCH_MAY_HAVE_PC_FDC
 	bool
 
@@ -126,17 +129,12 @@
 
 config SH_HP6XX
 	bool "HP6XX"
+	select SYS_SUPPORTS_APM_EMULATION
 	help
 	  Select HP6XX if configuring for a HP jornada HP6xx.
 	  More information (hardware only) at
 	  <http://www.hp.com/jornada/>.
 
-config SH_EC3104
-	bool "EC3104"
-	help
-	  Select EC3104 if configuring for a system with an Eclipse
-	  International EC3104 chip, e.g. the Harris AD2000.
-
 config SH_SATURN
 	bool "Saturn"
 	select CPU_SUBTYPE_SH7604
@@ -152,9 +150,6 @@
 	  <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
 	  Dreamcast project is at <http://linuxdc.sourceforge.net/>.
 
-config SH_BIGSUR
-	bool "BigSur"
-
 config SH_MPC1211
 	bool "Interface MPC1211"
 	help
@@ -477,6 +472,7 @@
 
 config SH_CLK_MD
 	int "CPU Mode Pin Setting"
+	default 0
 	depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
 	help
 	  MD2 - MD0 pin setting.
@@ -506,8 +502,9 @@
 config HEARTBEAT
 	bool "Heartbeat LED"
 	depends on SH_MPC1211 || SH_SH03 || \
-		   SH_BIGSUR || SOLUTION_ENGINE || \
-		   SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK
+		   SOLUTION_ENGINE || \
+		   SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK || \
+		   SH_R7780RP
 	help
 	  Use the power-on LED on your machine as a load meter.  The exact
 	  behavior is platform-dependent, but normally the flash frequency is
@@ -592,6 +589,8 @@
 config ZERO_PAGE_OFFSET
 	hex "Zero page offset"
 	default "0x00004000" if SH_MPC1211 || SH_SH03
+	default "0x00010000" if PAGE_SIZE_64KB
+	default "0x00002000" if PAGE_SIZE_8KB
 	default "0x00001000"
 	help
 	  This sets the default offset of zero page.
@@ -694,9 +693,6 @@
 
 source kernel/power/Kconfig
 
-config APM
-	bool "Advanced Power Management Emulation"
-	depends on PM
 endmenu
 
 source "net/Kconfig"
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index c1dbef2..bd9b172 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -35,6 +35,7 @@
 endif
 
 cflags-$(CONFIG_CPU_SH2)		:= -m2
+cflags-$(CONFIG_CPU_SH2A)		:= -m2a $(call cc-option,-m2a-nofpu,)
 cflags-$(CONFIG_CPU_SH3)		:= -m3
 cflags-$(CONFIG_CPU_SH4)		:= -m4 \
 	$(call cc-option,-mno-implicit-fp,-m4-nofpu)
@@ -93,10 +94,8 @@
 machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE)	:= se/7343
 machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)	:= se/73180
 machdir-$(CONFIG_SH_HP6XX)			:= hp6xx
-machdir-$(CONFIG_SH_EC3104)			:= ec3104
 machdir-$(CONFIG_SH_SATURN)			:= saturn
 machdir-$(CONFIG_SH_DREAMCAST)			:= dreamcast
-machdir-$(CONFIG_SH_BIGSUR)			:= bigsur
 machdir-$(CONFIG_SH_MPC1211)			:= mpc1211
 machdir-$(CONFIG_SH_SH03)			:= sh03
 machdir-$(CONFIG_SH_SECUREEDGE5410)		:= snapgear
diff --git a/arch/sh/boards/bigsur/Makefile b/arch/sh/boards/bigsur/Makefile
deleted file mode 100644
index 0ff9497..0000000
--- a/arch/sh/boards/bigsur/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the BigSur specific parts of the kernel
-#
-
-obj-y	 := setup.o io.o irq.o led.o
-
diff --git a/arch/sh/boards/bigsur/io.c b/arch/sh/boards/bigsur/io.c
deleted file mode 100644
index 23071f9..0000000
--- a/arch/sh/boards/bigsur/io.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * arch/sh/boards/bigsur/io.c
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- * Derived from io_hd64465.h, which bore the message:
- * By Greg Banks <gbanks@pocketpenguins.com>
- * (c) 2000 PocketPenguins Inc. 
- * and from io_hd64461.h, which bore the message:
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for a Hitachi Big Sur Evaluation Board.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/machvec.h>
-#include <asm/io.h>
-#include <asm/bigsur/bigsur.h>
-
-/* Low iomap maps port 0-1K to addresses in 8byte chunks */
-#define BIGSUR_IOMAP_LO_THRESH 0x400
-#define BIGSUR_IOMAP_LO_SHIFT	3
-#define BIGSUR_IOMAP_LO_MASK	((1<<BIGSUR_IOMAP_LO_SHIFT)-1)
-#define BIGSUR_IOMAP_LO_NMAP	(BIGSUR_IOMAP_LO_THRESH>>BIGSUR_IOMAP_LO_SHIFT)
-static u32 bigsur_iomap_lo[BIGSUR_IOMAP_LO_NMAP];
-static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP];
-
-/* High iomap maps port 1K-64K to addresses in 1K chunks */
-#define BIGSUR_IOMAP_HI_THRESH 0x10000
-#define BIGSUR_IOMAP_HI_SHIFT	10
-#define BIGSUR_IOMAP_HI_MASK	((1<<BIGSUR_IOMAP_HI_SHIFT)-1)
-#define BIGSUR_IOMAP_HI_NMAP	(BIGSUR_IOMAP_HI_THRESH>>BIGSUR_IOMAP_HI_SHIFT)
-static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP];
-static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP];
-
-void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
-{
-	u32 port, endport = baseport + nports;
-
-	pr_debug("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n",
-		 baseport, nports, addr);
-	    
-	for (port = baseport ;
-	     port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
-	     port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
-	    	pr_debug("    maplo[0x%x] = 0x%08x\n", port, addr);
-    	    bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = addr;
-    	    bigsur_iomap_lo_shift[port>>BIGSUR_IOMAP_LO_SHIFT] = shift;
-	    	addr += (1<<(BIGSUR_IOMAP_LO_SHIFT));
-	}
-
-	for (port = max_t(u32, baseport, BIGSUR_IOMAP_LO_THRESH);
-	     port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
-	     port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
-	    	pr_debug("    maphi[0x%x] = 0x%08x\n", port, addr);
-    	    bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = addr;
-    	    bigsur_iomap_hi_shift[port>>BIGSUR_IOMAP_HI_SHIFT] = shift;
-	    	addr += (1<<(BIGSUR_IOMAP_HI_SHIFT));
-	}
-}
-EXPORT_SYMBOL(bigsur_port_map);
-
-void bigsur_port_unmap(u32 baseport, u32 nports)
-{
-	u32 port, endport = baseport + nports;
-	
-	pr_debug("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports);
-
-	for (port = baseport ;
-	     port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
-	     port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
-		bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = 0;
-	}
-
-	for (port = max_t(u32, baseport, BIGSUR_IOMAP_LO_THRESH);
-	     port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
-	     port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
-		bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = 0;
-	}
-}
-EXPORT_SYMBOL(bigsur_port_unmap);
-
-unsigned long bigsur_isa_port2addr(unsigned long port)
-{
-	unsigned long addr = 0;
-	unsigned char shift;
-
-	/* Physical address not in P0, do nothing */
-	if (PXSEG(port)) {
-		addr = port;
-	/* physical address in P0, map to P2 */
-	} else if (port >= 0x30000) {
-		addr = P2SEGADDR(port);
-	/* Big Sur I/O + HD64465 registers 0x10000-0x30000 */
-	} else if (port >= BIGSUR_IOMAP_HI_THRESH) {
-		addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH);
-	/* Handle remapping of high IO/PCI IO ports */
-	} else if (port >= BIGSUR_IOMAP_LO_THRESH) {
-		addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT];
-		shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT];
-
-		if (addr != 0)
-			addr += (port & BIGSUR_IOMAP_HI_MASK) << shift;
-	} else {
-		/* Handle remapping of low IO ports */
-		addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT];
-		shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT];
-
-		if (addr != 0)
-			addr += (port & BIGSUR_IOMAP_LO_MASK) << shift;
-	}
-
-	pr_debug("%s(0x%08lx) = 0x%08lx\n", __FUNCTION__, port, addr);
-
-	return addr;
-}
-
diff --git a/arch/sh/boards/bigsur/irq.c b/arch/sh/boards/bigsur/irq.c
deleted file mode 100644
index 1ab04da..0000000
--- a/arch/sh/boards/bigsur/irq.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- *
- * Setup and IRQ handling code for the HD64465 companion chip.
- * by Greg Banks <gbanks@pocketpenguins.com>
- * Copyright (c) 2000 PocketPenguins Inc
- *
- * Derived from setup_hd64465.c which bore the message:
- * Greg Banks <gbanks@pocketpenguins.com>
- * Copyright (c) 2000 PocketPenguins Inc and
- * Copyright (C) 2000 YAEGASHI Takeshi
- * and setup_cqreek.c which bore message:
- * Copyright (C) 2000  Niibe Yutaka
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IRQ functions for a Hitachi Big Sur Evaluation Board.
- *
- */
-#undef DEBUG
-
-#include <linux/sched.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/bigsur/io.h>
-#include <asm/hd64465/hd64465.h>
-#include <asm/bigsur/bigsur.h>
-
-//#define BIGSUR_DEBUG 3
-#undef BIGSUR_DEBUG
-
-#ifdef BIGSUR_DEBUG
-#define DIPRINTK(n, args...)    if (BIGSUR_DEBUG>(n)) printk(args)
-#else
-#define DIPRINTK(n, args...)
-#endif /* BIGSUR_DEBUG */
-
-#ifdef CONFIG_HD64465
-extern int hd64465_irq_demux(int irq);
-#endif /* CONFIG_HD64465 */
-
-
-/*===========================================================*/
-//              Big Sur CPLD IRQ Routines
-/*===========================================================*/
-
-/* Level 1 IRQ routines */
-static void disable_bigsur_l1irq(unsigned int irq)
-{
-        unsigned char mask;
-        unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
-        unsigned char bit =  (1 << ((irq - MGATE_IRQ_LOW)%8) );
-
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                pr_debug("Disable L1 IRQ %d\n", irq);
-                DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
-                        mask_port, bit);
-
-                /* Disable IRQ - set mask bit */
-                mask = inb(mask_port) | bit;
-                outb(mask, mask_port);
-                return;
-        }
-        pr_debug("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);
-}
-
-static void enable_bigsur_l1irq(unsigned int irq)
-{
-        unsigned char mask;
-        unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
-        unsigned char bit =  (1 << ((irq - MGATE_IRQ_LOW)%8) );
-
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                pr_debug("Enable L1 IRQ %d\n", irq);
-                DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
-                        mask_port, bit);
-                /* Enable L1 IRQ - clear mask bit */
-                mask = inb(mask_port) & ~bit;
-                outb(mask, mask_port);
-                return;
-        }
-        pr_debug("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);
-}
-
-
-/* Level 2 irq masks and registers for L2 decoding */
-/* Level2 bitmasks for each level 1 IRQ */
-const u32 bigsur_l2irq_mask[] =
-    {0x40,0x80,0x08,0x01,0x01,0x3C,0x3E,0xFF,0x40,0x80,0x06,0x03};
-/* Level2 to ISR[n] map for each level 1 IRQ */
-const u32 bigsur_l2irq_reg[]  =
-    {   2,   2,   3,   3,   1,   2,   1,   0,   1,   1,   3,   2};
-/* Level2 to Level 1 IRQ map */
-const u32 bigsur_l2_l1_map[]  =
-    {7,7,7,7,7,7,7,7, 4,6,6,6,6,6,8,9, 11,11,5,5,5,5,0,1, 3,10,10,2,-1,-1,-1,-1};
-/* IRQ inactive level (high or low) */
-const u32 bigsur_l2_inactv_state[]  =   {0x00, 0xBE, 0xFC, 0xF7};
-
-/* CPLD external status and mask registers base and offsets */
-static const u32 isr_base = BIGSUR_IRQ0;
-static const u32 isr_offset = BIGSUR_IRQ0 - BIGSUR_IRQ1;
-static const u32 imr_base = BIGSUR_IMR0;
-static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1;
-
-#define REG_NUM(irq)  ((irq-BIGSUR_2NDLVL_IRQ_LOW)/8 )
-
-/* Level 2 IRQ routines */
-static void disable_bigsur_l2irq(unsigned int irq)
-{
-        unsigned char mask;
-        unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
-        unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
-
-	if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
-                pr_debug("Disable L2 IRQ %d\n", irq);
-                DIPRINTK(2,"disable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
-                        mask_port, bit);
-
-                /* Disable L2 IRQ - set mask bit */
-                mask = inb(mask_port) | bit;
-                outb(mask, mask_port);
-                return;
-        }
-        pr_debug("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);
-}
-
-static void enable_bigsur_l2irq(unsigned int irq)
-{
-        unsigned char mask;
-        unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
-        unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
-
-	if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
-                pr_debug("Enable L2 IRQ %d\n", irq);
-                DIPRINTK(2,"enable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
-                        mask_port, bit);
-
-                /* Enable L2 IRQ - clear mask bit */
-                mask = inb(mask_port) & ~bit;
-                outb(mask, mask_port);
-                return;
-        }
-        pr_debug("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
-}
-
-static void mask_and_ack_bigsur(unsigned int irq)
-{
-        pr_debug("mask_and_ack_bigsur IRQ %d\n", irq);
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
-                disable_bigsur_l1irq(irq);
-        else
-                disable_bigsur_l2irq(irq);
-}
-
-static void end_bigsur_irq(unsigned int irq)
-{
-        pr_debug("end_bigsur_irq IRQ %d\n", irq);
-        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
-                if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
-                        enable_bigsur_l1irq(irq);
-                else
-                        enable_bigsur_l2irq(irq);
-        }
-}
-
-static unsigned int startup_bigsur_irq(unsigned int irq)
-{
-        u8 mask;
-        u32 reg;
-
-        pr_debug("startup_bigsur_irq IRQ %d\n", irq);
-
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                /* Enable the L1 IRQ */
-                enable_bigsur_l1irq(irq);
-                /* Enable all L2 IRQs in this L1 IRQ */
-                mask = ~(bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]);
-                reg = imr_base - bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW] * imr_offset;
-                mask &= inb(reg);
-                outb(mask,reg);
-                DIPRINTK(2,"startup_bigsur_irq: IMR=0x%08x mask=0x%x\n",reg,inb(reg));
-        }
-        else {
-                /* Enable the L2 IRQ - clear mask bit */
-                enable_bigsur_l2irq(irq);
-                /* Enable the L1 bit masking this L2 IRQ */
-                enable_bigsur_l1irq(bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW]);
-                DIPRINTK(2,"startup_bigsur_irq: L1=%d L2=%d\n",
-                        bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW],irq);
-        }
-        return 0;
-}
-
-static void shutdown_bigsur_irq(unsigned int irq)
-{
-        pr_debug("shutdown_bigsur_irq IRQ %d\n", irq);
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
-                disable_bigsur_l1irq(irq);
-        else
-                disable_bigsur_l2irq(irq);
-}
-
-/* Define the IRQ structures for the L1 and L2 IRQ types */
-static struct hw_interrupt_type bigsur_l1irq_type = {
-	.typename  = "BigSur-CPLD-Level1-IRQ",
-	.startup = startup_bigsur_irq,
-	.shutdown = shutdown_bigsur_irq,
-	.enable = enable_bigsur_l1irq,
-	.disable = disable_bigsur_l1irq,
-	.ack = mask_and_ack_bigsur,
-	.end = end_bigsur_irq
-};
-
-static struct hw_interrupt_type bigsur_l2irq_type = {
-	.typename  = "BigSur-CPLD-Level2-IRQ",
-	.startup = startup_bigsur_irq,
-	.shutdown  =shutdown_bigsur_irq,
-	.enable = enable_bigsur_l2irq,
-	.disable = disable_bigsur_l2irq,
-	.ack = mask_and_ack_bigsur,
-	.end = end_bigsur_irq
-};
-
-
-static void make_bigsur_l1isr(unsigned int irq) {
-
-        /* sanity check first */
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                /* save the handler in the main description table */
-                irq_desc[irq].chip = &bigsur_l1irq_type;
-                irq_desc[irq].status = IRQ_DISABLED;
-                irq_desc[irq].action = 0;
-                irq_desc[irq].depth = 1;
-
-                disable_bigsur_l1irq(irq);
-                return;
-        }
-        pr_debug("make_bigsur_l1isr: bad irq, %d\n", irq);
-        return;
-}
-
-static void make_bigsur_l2isr(unsigned int irq) {
-
-        /* sanity check first */
-        if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
-                /* save the handler in the main description table */
-                irq_desc[irq].chip = &bigsur_l2irq_type;
-                irq_desc[irq].status = IRQ_DISABLED;
-                irq_desc[irq].action = 0;
-                irq_desc[irq].depth = 1;
-
-                disable_bigsur_l2irq(irq);
-                return;
-        }
-        pr_debug("make_bigsur_l2isr: bad irq, %d\n", irq);
-        return;
-}
-
-/* The IRQ's will be decoded as follows:
- * If a level 2 handler exists and there is an unmasked active
- * IRQ, the 2nd level handler will be called.
- * If a level 2 handler does not exist for the active IRQ
- * the 1st level handler will be called.
- */
-
-int bigsur_irq_demux(int irq)
-{
-        int dmux_irq = irq;
-        u8 mask, actv_irqs;
-        u32 reg_num;
-
-        DIPRINTK(3,"bigsur_irq_demux, irq=%d\n", irq);
-        /* decode the 1st level IRQ */
-        if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                /* Get corresponding L2 ISR bitmask and ISR number */
-                mask = bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW];
-                reg_num = bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW];
-                /* find the active IRQ's (XOR with inactive level)*/
-                actv_irqs = inb(isr_base-reg_num*isr_offset) ^
-                                        bigsur_l2_inactv_state[reg_num];
-                /* decode active IRQ's */
-                actv_irqs = actv_irqs & mask & ~(inb(imr_base-reg_num*imr_offset));
-                /* if NEZ then we have an active L2 IRQ */
-                if(actv_irqs) dmux_irq = ffz(~actv_irqs) + reg_num*8+BIGSUR_2NDLVL_IRQ_LOW;
-                /* if no 2nd level IRQ action, but has 1st level, use 1st level handler */
-                if(!irq_desc[dmux_irq].action && irq_desc[irq].action)
-                        dmux_irq = irq;
-                DIPRINTK(1,"bigsur_irq_demux: irq=%d dmux_irq=%d mask=0x%04x reg=%d\n",
-                        irq, dmux_irq, mask, reg_num);
-        }
-#ifdef CONFIG_HD64465
-        dmux_irq = hd64465_irq_demux(dmux_irq);
-#endif /* CONFIG_HD64465 */
-        DIPRINTK(3,"bigsur_irq_demux, demux_irq=%d\n", dmux_irq);
-
-        return dmux_irq;
-}
-
-/*===========================================================*/
-//              Big Sur Init Routines
-/*===========================================================*/
-void __init init_bigsur_IRQ(void)
-{
-        int i;
-
-        if (!MACH_BIGSUR) return;
-
-        /* Create ISR's for Big Sur CPLD IRQ's */
-        /*==============================================================*/
-        for(i=BIGSUR_IRQ_LOW;i<BIGSUR_IRQ_HIGH;i++)
-                make_bigsur_l1isr(i);
-
-        printk(KERN_INFO "Big Sur CPLD L1 interrupts %d to %d.\n",
-                BIGSUR_IRQ_LOW,BIGSUR_IRQ_HIGH);
-
-        for(i=BIGSUR_2NDLVL_IRQ_LOW;i<BIGSUR_2NDLVL_IRQ_HIGH;i++)
-                make_bigsur_l2isr(i);
-
-        printk(KERN_INFO "Big Sur CPLD L2 interrupts %d to %d.\n",
-                BIGSUR_2NDLVL_IRQ_LOW,BIGSUR_2NDLVL_IRQ_HIGH);
-
-}
diff --git a/arch/sh/boards/bigsur/led.c b/arch/sh/boards/bigsur/led.c
deleted file mode 100644
index d221439..0000000
--- a/arch/sh/boards/bigsur/led.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/sh/boards/bigsur/led.c
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- * Derived from led_se.c and led.c, which bore the message:
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Big Sur specific LED code.
- */
-
-#include <asm/io.h>
-#include <asm/bigsur/bigsur.h>
-
-static void mach_led(int position, int value)
-{
-	int word;
-	
-	word = bigsur_inl(BIGSUR_CSLR);
-	if (value) {
-		bigsur_outl(word & ~BIGSUR_LED, BIGSUR_CSLR);
-	} else {
-		bigsur_outl(word | BIGSUR_LED, BIGSUR_CSLR);
-	}
-}
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* Cycle the LED on/off */
-void heartbeat_bigsur(void)
-{
-	static unsigned cnt = 0, period = 0, dist = 0;
-
-	if (cnt == 0 || cnt == dist)
-		mach_led( -1, 1);
-	else if (cnt == 7 || cnt == dist+7)
-		mach_led( -1, 0);
-
-	if (++cnt > period) {
-		cnt = 0;
-		/* The hyperbolic function below modifies the heartbeat period
-		 * length in dependency of the current (5min) load. It goes
-		 * through the points f(0)=126, f(1)=86, f(5)=51,
-		 * f(inf)->30. */
-		period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
-		dist = period / 4;
-	}
-}
-#endif /* CONFIG_HEARTBEAT */
-
diff --git a/arch/sh/boards/bigsur/setup.c b/arch/sh/boards/bigsur/setup.c
deleted file mode 100644
index 9711c20..0000000
--- a/arch/sh/boards/bigsur/setup.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- * 
- * Setup and IRQ handling code for the HD64465 companion chip.
- * by Greg Banks <gbanks@pocketpenguins.com>
- * Copyright (c) 2000 PocketPenguins Inc
- *
- * Derived from setup_hd64465.c which bore the message:
- * Greg Banks <gbanks@pocketpenguins.com>
- * Copyright (c) 2000 PocketPenguins Inc and
- * Copyright (C) 2000 YAEGASHI Takeshi
- * and setup_cqreek.c which bore message:
- * Copyright (C) 2000  Niibe Yutaka
- * 
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Setup functions for a Hitachi Big Sur Evaluation Board.
- * 
- */
-
-#include <linux/sched.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/machvec.h>
-#include <asm/bigsur/io.h>
-#include <asm/hd64465/hd64465.h>
-#include <asm/bigsur/bigsur.h>
-
-/*===========================================================*/
-//		Big Sur Init Routines	
-/*===========================================================*/
-
-static void __init bigsur_setup(char **cmdline_p)
-{
-	/* Mask all 2nd level IRQ's */
-	outb(-1,BIGSUR_IMR0);
-	outb(-1,BIGSUR_IMR1);
-	outb(-1,BIGSUR_IMR2);
-	outb(-1,BIGSUR_IMR3);
-
-	/* Mask 1st level interrupts */
-	outb(-1,BIGSUR_IRLMR0);
-	outb(-1,BIGSUR_IRLMR1);
-
-#if defined (CONFIG_HD64465) && defined (CONFIG_SERIAL) 
-	/* remap IO ports for first ISA serial port to HD64465 UART */
-	bigsur_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1);
-#endif /* CONFIG_HD64465 && CONFIG_SERIAL */
-	/* TODO: setup IDE registers */
-	bigsur_port_map(BIGSUR_IDECTL_IOPORT, 2, BIGSUR_ICTL, 8);
-	/* Setup the Ethernet port to BIGSUR_ETHER_IOPORT */
-	bigsur_port_map(BIGSUR_ETHER_IOPORT, 16, BIGSUR_ETHR+BIGSUR_ETHER_IOPORT, 0);
-	/* set page to 1 */
-	outw(1, BIGSUR_ETHR+0xe);
-	/* set the IO port to BIGSUR_ETHER_IOPORT */
-	outw(BIGSUR_ETHER_IOPORT<<3, BIGSUR_ETHR+0x2);
-}
-
-/*
- * The Machine Vector
- */
-extern void heartbeat_bigsur(void);
-extern void init_bigsur_IRQ(void);
-
-struct sh_machine_vector mv_bigsur __initmv = {
-	.mv_name		= "Big Sur",
-	.mv_setup		= bigsur_setup,
-
-	.mv_isa_port2addr	= bigsur_isa_port2addr,
-	.mv_irq_demux       	= bigsur_irq_demux,
-
-	.mv_init_irq		= init_bigsur_IRQ,
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat		= heartbeat_bigsur,
-#endif
-};
-ALIAS_MV(bigsur)
diff --git a/arch/sh/boards/ec3104/Makefile b/arch/sh/boards/ec3104/Makefile
deleted file mode 100644
index 1788915..0000000
--- a/arch/sh/boards/ec3104/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the EC3104 specific parts of the kernel
-#
-
-obj-y	 := setup.o io.o irq.o
-
diff --git a/arch/sh/boards/ec3104/io.c b/arch/sh/boards/ec3104/io.c
deleted file mode 100644
index 2f86394..0000000
--- a/arch/sh/boards/ec3104/io.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * linux/arch/sh/boards/ec3104/io.c
- *  EC3104 companion chip support
- *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *
- */
-/* EC3104 note:
- * This code was written without any documentation about the EC3104 chip.  While
- * I hope I got most of the basic functionality right, the register names I use
- * are most likely completely different from those in the chip documentation.
- *
- * If you have any further information about the EC3104, please tell me
- * (prumpf@tux.org).
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/io.h>
-#include <asm/page.h>
-#include <asm/ec3104/ec3104.h>
-
-/*
- * EC3104 has a real ISA bus which we redirect low port accesses to (the
- * actual device on mine is a ESS 1868, and I don't want to hack the driver
- * more than strictly necessary).  I am not going to duplicate the
- * hard coding of PC addresses (for the 16550s aso) here though;  it's just
- * too ugly.
- */
-
-#define low_port(port) ((port) < 0x10000)
-
-static inline unsigned long port2addr(unsigned long port)
-{
-	switch(port >> 16) {
-	case 0:
-		return EC3104_ISA_BASE + port * 2;
-
-		/* XXX hack. it's unclear what to do about the serial ports */
-	case 1:
-		return EC3104_BASE + (port&0xffff) * 4;
-
-	default:
-		/* XXX PCMCIA */
-		return 0;
-	}
-}
-
-unsigned char ec3104_inb(unsigned long port)
-{
-	u8 ret;
-
-	ret = *(volatile u8 *)port2addr(port);
-
-	return ret;
-}
-
-unsigned short ec3104_inw(unsigned long port)
-{
-	BUG();
-}
-
-unsigned long ec3104_inl(unsigned long port)
-{
-	BUG();
-}
-
-void ec3104_outb(unsigned char data, unsigned long port)
-{
-	*(volatile u8 *)port2addr(port) = data;
-}
-
-void ec3104_outw(unsigned short data, unsigned long port)
-{
-	BUG();
-}
-
-void ec3104_outl(unsigned long data, unsigned long port)
-{
-	BUG();
-}
diff --git a/arch/sh/boards/ec3104/irq.c b/arch/sh/boards/ec3104/irq.c
deleted file mode 100644
index ffa4ff1..0000000
--- a/arch/sh/boards/ec3104/irq.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * linux/arch/sh/boards/ec3104/irq.c
- * EC3104 companion chip support
- *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *
- */
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/ec3104/ec3104.h>
-
-/* This is for debugging mostly;  here's the table that I intend to keep
- * in here:
- *
- *   index      function        base addr       power           interrupt bit
- *       0      power           b0ec0000        ---             00000001 (unused)
- *       1      irqs            b0ec1000        ---             00000002 (unused)
- *       2      ??              b0ec2000        b0ec0008        00000004
- *       3      PS2 (1)         b0ec3000        b0ec000c        00000008
- *       4      PS2 (2)         b0ec4000        b0ec0010        00000010
- *       5      ??              b0ec5000        b0ec0014        00000020
- *       6      I2C             b0ec6000        b0ec0018        00000040
- *       7      serial (1)      b0ec7000        b0ec001c        00000080
- *       8      serial (2)      b0ec8000        b0ec0020        00000100
- *       9      serial (3)      b0ec9000        b0ec0024        00000200
- *      10      serial (4)      b0eca000        b0ec0028        00000400
- *      12      GPIO (1)        b0ecc000        b0ec0030
- *      13      GPIO (2)        b0ecc000        b0ec0030
- *      16      pcmcia (1)      b0ed0000        b0ec0040        00010000
- *      17      pcmcia (2)      b0ed1000        b0ec0044        00020000
- */
-
-/* I used the register names from another interrupt controller I worked with,
- * since it seems to be identical to the ec3104 except that all bits are
- * inverted:
- *
- * IRR: Interrupt Request Register (pending and enabled interrupts)
- * IMR: Interrupt Mask Register (which interrupts are enabled)
- * IPR: Interrupt Pending Register (pending interrupts, even disabled ones)
- *
- * 0 bits mean pending or enabled, 1 bits mean not pending or disabled.  all
- * IRQs seem to be level-triggered.
- */
-
-#define EC3104_IRR (EC3104_BASE + 0x1000)
-#define EC3104_IMR (EC3104_BASE + 0x1004)
-#define EC3104_IPR (EC3104_BASE + 0x1008)
-
-#define ctrl_readl(addr) (*(volatile u32 *)(addr))
-#define ctrl_writel(data,addr) (*(volatile u32 *)(addr) = (data))
-#define ctrl_readb(addr) (*(volatile u8 *)(addr))
-
-static char *ec3104_name(unsigned index)
-{
-        switch(index) {
-        case 0:
-                return "power management";
-        case 1:
-                return "interrupts";
-        case 3:
-                return "PS2 (1)";
-        case 4:
-                return "PS2 (2)";
-        case 5:
-                return "I2C (1)";
-        case 6:
-                return "I2C (2)";
-        case 7:
-                return "serial (1)";
-        case 8:
-                return "serial (2)";
-        case 9:
-                return "serial (3)";
-        case 10:
-                return "serial (4)";
-        case 16:
-                return "pcmcia (1)";
-        case 17:
-                return "pcmcia (2)";
-        default: {
-                static char buf[32];
-
-                sprintf(buf, "unknown (%d)", index);
-
-                return buf;
-                }
-        }
-}
-
-int get_pending_interrupts(char *buf)
-{
-        u32 ipr;
-        u32 bit;
-        char *p = buf;
-
-        p += sprintf(p, "pending: (");
-
-        ipr = ctrl_inl(EC3104_IPR);
-
-        for (bit = 1; bit < 32; bit++)
-                if (!(ipr & (1<<bit)))
-                        p += sprintf(p, "%s ", ec3104_name(bit));
-
-        p += sprintf(p, ")\n");
-
-        return p - buf;
-}
-
-static inline u32 ec3104_irq2mask(unsigned int irq)
-{
-        return (1 << (irq - EC3104_IRQBASE));
-}
-
-static inline void mask_ec3104_irq(unsigned int irq)
-{
-        u32 mask;
-
-        mask = ctrl_readl(EC3104_IMR);
-
-        mask |= ec3104_irq2mask(irq);
-
-        ctrl_writel(mask, EC3104_IMR);
-}
-
-static inline void unmask_ec3104_irq(unsigned int irq)
-{
-        u32 mask;
-
-        mask = ctrl_readl(EC3104_IMR);
-
-        mask &= ~ec3104_irq2mask(irq);
-
-        ctrl_writel(mask, EC3104_IMR);
-}
-
-static void disable_ec3104_irq(unsigned int irq)
-{
-        mask_ec3104_irq(irq);
-}
-
-static void enable_ec3104_irq(unsigned int irq)
-{
-        unmask_ec3104_irq(irq);
-}
-
-static void mask_and_ack_ec3104_irq(unsigned int irq)
-{
-        mask_ec3104_irq(irq);
-}
-
-static void end_ec3104_irq(unsigned int irq)
-{
-        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-                unmask_ec3104_irq(irq);
-}
-
-static unsigned int startup_ec3104_irq(unsigned int irq)
-{
-        unmask_ec3104_irq(irq);
-
-        return 0;
-}
-
-static void shutdown_ec3104_irq(unsigned int irq)
-{
-        mask_ec3104_irq(irq);
-
-}
-
-static struct hw_interrupt_type ec3104_int = {
-        .typename       = "EC3104",
-        .enable         = enable_ec3104_irq,
-        .disable        = disable_ec3104_irq,
-        .ack            = mask_and_ack_ec3104_irq,
-        .end            = end_ec3104_irq,
-        .startup        = startup_ec3104_irq,
-        .shutdown       = shutdown_ec3104_irq,
-};
-
-/* Yuck.  the _demux API is ugly */
-int ec3104_irq_demux(int irq)
-{
-        if (irq == EC3104_IRQ) {
-                unsigned int mask;
-
-                mask = ctrl_readl(EC3104_IRR);
-
-                if (mask == 0xffffffff)
-                        return EC3104_IRQ;
-                else
-                        return EC3104_IRQBASE + ffz(mask);
-        }
-
-        return irq;
-}
diff --git a/arch/sh/boards/ec3104/setup.c b/arch/sh/boards/ec3104/setup.c
deleted file mode 100644
index 902bc97..0000000
--- a/arch/sh/boards/ec3104/setup.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * linux/arch/sh/boards/ec3104/setup.c
- *  EC3104 companion chip support
- *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *
- */
-/* EC3104 note:
- * This code was written without any documentation about the EC3104 chip.  While
- * I hope I got most of the basic functionality right, the register names I use
- * are most likely completely different from those in the chip documentation.
- *
- * If you have any further information about the EC3104, please tell me
- * (prumpf@tux.org).
- */
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/types.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/machvec.h>
-#include <asm/mach/ec3104.h>
-
-static void __init ec3104_setup(char **cmdline_p)
-{
-	char str[8];
-	int i;
-
-	for (i=0; i<8; i++)
-		str[i] = ctrl_readb(EC3104_BASE + i);
-
-	for (i = EC3104_IRQBASE; i < EC3104_IRQBASE + 32; i++)
-		irq_desc[i].handler = &ec3104_int;
-
-	printk("initializing EC3104 \"%.8s\" at %08x, IRQ %d, IRQ base %d\n",
-	       str, EC3104_BASE, EC3104_IRQ, EC3104_IRQBASE);
-
-	/* mask all interrupts.  this should have been done by the boot
-	 * loader for us but we want to be sure ... */
-	ctrl_writel(0xffffffff, EC3104_IMR);
-}
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_ec3104 __initmv = {
-	.mv_name	= "EC3104",
-	.mv_setup	= ec3104_setup,
-	.mv_nr_irqs	= 96,
-
-	.mv_inb		= ec3104_inb,
-	.mv_inw		= ec3104_inw,
-	.mv_inl		= ec3104_inl,
-	.mv_outb	= ec3104_outb,
-	.mv_outw	= ec3104_outw,
-	.mv_outl	= ec3104_outl,
-
-	.mv_irq_demux	= ec3104_irq_demux,
-};
-ALIAS_MV(ec3104)
diff --git a/arch/sh/boards/hp6xx/hp6xx_apm.c b/arch/sh/boards/hp6xx/hp6xx_apm.c
index d146cda..d1c1460 100644
--- a/arch/sh/boards/hp6xx/hp6xx_apm.c
+++ b/arch/sh/boards/hp6xx/hp6xx_apm.c
@@ -7,12 +7,11 @@
  * modify it under the terms of the GNU General Public License.
  */
 #include <linux/module.h>
-#include <linux/apm_bios.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <asm/io.h>
-#include <asm/apm.h>
+#include <linux/apm-emulation.h>
+#include <linux/io.h>
 #include <asm/adc.h>
 #include <asm/hp6xx.h>
 
@@ -27,60 +26,41 @@
 
 #define MODNAME "hp6x0_apm"
 
-static int hp6x0_apm_get_info(char *buf, char **start, off_t fpos, int length)
+static void hp6x0_apm_get_power_status(struct apm_power_info *info)
 {
+	int battery, backup, charging, percentage;
 	u8 pgdr;
-	char *p;
-	int battery_status;
-	int battery_flag;
-	int ac_line_status;
-	int time_units = APM_BATTERY_LIFE_UNKNOWN;
 
-	int battery = adc_single(ADC_CHANNEL_BATTERY);
-	int backup = adc_single(ADC_CHANNEL_BACKUP);
-	int charging = adc_single(ADC_CHANNEL_CHARGE);
-	int percentage;
+	battery		= adc_single(ADC_CHANNEL_BATTERY);
+	backup		= adc_single(ADC_CHANNEL_BACKUP);
+	charging	= adc_single(ADC_CHANNEL_CHARGE);
 
 	percentage = 100 * (battery - HP680_BATTERY_MIN) /
 			   (HP680_BATTERY_MAX - HP680_BATTERY_MIN);
 
-	ac_line_status = (battery > HP680_BATTERY_AC_ON) ?
+	info->ac_line_status = (battery > HP680_BATTERY_AC_ON) ?
 			 APM_AC_ONLINE : APM_AC_OFFLINE;
 
-	p = buf;
-
 	pgdr = ctrl_inb(SH7709_PGDR);
 	if (pgdr & PGDR_MAIN_BATTERY_OUT) {
-		battery_status = APM_BATTERY_STATUS_NOT_PRESENT;
-		battery_flag = 0x80;
-		percentage = -1;
-	} else if (charging < 8 ) {
-		battery_status = APM_BATTERY_STATUS_CHARGING;
-		battery_flag = 0x08;
-		ac_line_status = 0xff;
+		info->battery_status	= APM_BATTERY_STATUS_NOT_PRESENT;
+		info->battery_flag	= 0x80;
+	} else if (charging < 8) {
+		info->battery_status	= APM_BATTERY_STATUS_CHARGING;
+		info->battery_flag	= 0x08;
+		info->ac_line_status = 0xff;
 	} else if (percentage <= APM_CRITICAL) {
-		battery_status = APM_BATTERY_STATUS_CRITICAL;
-		battery_flag = 0x04;
+		info->battery_status	= APM_BATTERY_STATUS_CRITICAL;
+		info->battery_flag	= 0x04;
 	} else if (percentage <= APM_LOW) {
-		battery_status = APM_BATTERY_STATUS_LOW;
-		battery_flag = 0x02;
+		info->battery_status	= APM_BATTERY_STATUS_LOW;
+		info->battery_flag	= 0x02;
 	} else {
-		battery_status = APM_BATTERY_STATUS_HIGH;
-		battery_flag = 0x01;
+		info->battery_status	= APM_BATTERY_STATUS_HIGH;
+		info->battery_flag	= 0x01;
 	}
 
-	p += sprintf(p, "1.0 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
-		     APM_32_BIT_SUPPORT,
-		     ac_line_status,
-		     battery_status,
-		     battery_flag,
-		     percentage,
-		     time_units,
-		     "min");
-	p += sprintf(p, "bat=%d backup=%d charge=%d\n",
-		     battery, backup, charging);
-
-	return p - buf;
+	info->units = 0;
 }
 
 static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev)
@@ -96,14 +76,14 @@
 	int ret;
 
 	ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
-			  IRQF_DISABLED, MODNAME, 0);
+			  IRQF_DISABLED, MODNAME, NULL);
 	if (unlikely(ret < 0)) {
 		printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
 		       HP680_BTN_IRQ);
 		return ret;
 	}
 
-	apm_get_info = hp6x0_apm_get_info;
+	apm_get_power_status = hp6x0_apm_get_power_status;
 
 	return ret;
 }
@@ -111,7 +91,7 @@
 static void __exit hp6x0_apm_exit(void)
 {
 	free_irq(HP680_BTN_IRQ, 0);
-	apm_get_info = 0;
+	apm_get_info = NULL;
 }
 
 module_init(hp6x0_apm_init);
diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c
index e625249..47a63c6 100644
--- a/arch/sh/boards/landisk/landisk_pwb.c
+++ b/arch/sh/boards/landisk/landisk_pwb.c
@@ -150,7 +150,7 @@
 	return IRQ_HANDLED;
 }
 
-static struct file_operations swdrv_fops = {
+static const struct file_operations swdrv_fops = {
 	.read = swdrv_read,	/* read */
 	.write = swdrv_write,	/* write */
 	.open = swdrv_open,	/* open */
diff --git a/arch/sh/boards/mpc1211/Makefile b/arch/sh/boards/mpc1211/Makefile
index 1644ebe..8cd31b5 100644
--- a/arch/sh/boards/mpc1211/Makefile
+++ b/arch/sh/boards/mpc1211/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel
 #
 
-obj-y	 := setup.o rtc.o led.o
+obj-y	 := setup.o rtc.o
 
 obj-$(CONFIG_PCI) += pci.o
 
diff --git a/arch/sh/boards/mpc1211/led.c b/arch/sh/boards/mpc1211/led.c
deleted file mode 100644
index 8df1591..0000000
--- a/arch/sh/boards/mpc1211/led.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * linux/arch/sh/boards/mpc1211/led.c
- *
- * Copyright (C) 2001  Saito.K & Jeanne
- *
- * This file contains Interface MPC-1211 specific LED code.
- */
-
-
-static void mach_led(int position, int value)
-{
-	volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
-
-	if (value) {
-		*p |= 1;
-	} else {
-		*p &= ~1;
-	}
-}
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_mpc1211(void)
-{
-	static unsigned int cnt = 0, period = 0;
-	volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
-	static unsigned bit = 0, up = 1;
-
-	cnt += 1;
-	if (cnt < period) {
-		return;
-	}
-
-	cnt = 0;
-
-	/* Go through the points (roughly!):
-	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-	 */
-	period = 110 - ( (300<<FSHIFT)/
-			 ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-	if (up) {
-		if (bit == 7) {
-			bit--;
-			up=0;
-		} else {
-			bit ++;
-		}
-	} else {
-		if (bit == 0) {
-			bit++;
-			up=1;
-		} else {
-			bit--;
-		}
-	}
-	*p = 1<<bit;
-
-}
-#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
index 7c3d1d3..1a0604b 100644
--- a/arch/sh/boards/mpc1211/setup.c
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -10,6 +10,7 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/interrupt.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/machvec.h>
 #include <asm/mpc1211/mpc1211.h>
@@ -281,6 +282,32 @@
 	return 0;
 }
 
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= 0xa2000000,
+		.end	= 0xa2000000 + 8 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(heartbeat_resources),
+	.resource	= heartbeat_resources,
+};
+
+static struct platform_device *mpc1211_devices[] __initdata = {
+	&heartbeat_device,
+};
+
+static int __init mpc1211_devices_setup(void)
+{
+	return platform_add_devices(mpc1211_devices,
+				    ARRAY_SIZE(mpc1211_devices));
+}
+__initcall(mpc1211_devices_setup);
+
 /* arch/sh/boards/mpc1211/rtc.c */
 void mpc1211_time_init(void);
 
@@ -317,9 +344,5 @@
 	.mv_nr_irqs		= 48,
 	.mv_irq_demux		= mpc1211_irq_demux,
 	.mv_init_irq		= init_mpc1211_IRQ,
-
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat		= heartbeat_mpc1211,
-#endif
 };
 ALIAS_MV(mpc1211)
diff --git a/arch/sh/boards/renesas/r7780rp/Makefile b/arch/sh/boards/renesas/r7780rp/Makefile
index 574b031..3c93012 100644
--- a/arch/sh/boards/renesas/r7780rp/Makefile
+++ b/arch/sh/boards/renesas/r7780rp/Makefile
@@ -4,5 +4,4 @@
 
 obj-y	 := setup.o io.o irq.o
 
-obj-$(CONFIG_HEARTBEAT)		+= led.o
 obj-$(CONFIG_PUSH_SWITCH)	+= psw.o
diff --git a/arch/sh/boards/renesas/r7780rp/io.c b/arch/sh/boards/renesas/r7780rp/io.c
index 311cccc..f74d2ff 100644
--- a/arch/sh/boards/renesas/r7780rp/io.c
+++ b/arch/sh/boards/renesas/r7780rp/io.c
@@ -11,22 +11,9 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/io.h>
 #include <asm/r7780rp.h>
 #include <asm/addrspace.h>
-#include <asm/io.h>
-
-static inline unsigned long port2adr(unsigned int port)
-{
-	if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
-		if (port == 0x3f6)
-			return (PA_AREA5_IO + 0x80c);
-		else
-			return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
-	else
-		maybebadio((unsigned long)port);
-
-	return port;
-}
 
 static inline unsigned long port88796l(unsigned int port, int flag)
 {
@@ -40,18 +27,6 @@
 	return addr;
 }
 
-/* The 7780 R7780RP-1 seems to have everything hooked */
-/* up pretty normally (nothing on high-bytes only...) so this */
-/* shouldn't be needed */
-static inline int shifted_port(unsigned long port)
-{
-	/* For IDE registers, value is not shifted */
-	if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
-		return 0;
-	else
-		return 1;
-}
-
 #if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
 #define CHECK_AX88796L_PORT(port) \
   ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
@@ -70,12 +45,10 @@
 {
 	if (CHECK_AX88796L_PORT(port))
 		return ctrl_inw(port88796l(port, 0)) & 0xff;
-	else if (PXSEG(port))
-		return ctrl_inb(port);
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	else if (is_pci_ioaddr(port))
 		return ctrl_inb(pci_ioaddr(port));
 
-	return ctrl_inw(port2adr(port)) & 0xff;
+	return ctrl_inw(port) & 0xff;
 }
 
 u8 r7780rp_inb_p(unsigned long port)
@@ -84,12 +57,10 @@
 
 	if (CHECK_AX88796L_PORT(port))
 		v = ctrl_inw(port88796l(port, 0)) & 0xff;
-	else if (PXSEG(port))
-		v = ctrl_inb(port);
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	else if (is_pci_ioaddr(port))
 		v = ctrl_inb(pci_ioaddr(port));
 	else
-		v = ctrl_inw(port2adr(port)) & 0xff;
+		v = ctrl_inw(port) & 0xff;
 
 	ctrl_delay();
 
@@ -98,80 +69,56 @@
 
 u16 r7780rp_inw(unsigned long port)
 {
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-	else if (PXSEG(port))
-		return ctrl_inw(port);
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	if (is_pci_ioaddr(port))
 		return ctrl_inw(pci_ioaddr(port));
-	else
-		maybebadio(port);
 
-	return 0;
+	return ctrl_inw(port);
 }
 
 u32 r7780rp_inl(unsigned long port)
 {
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-	else if (PXSEG(port))
-		return ctrl_inl(port);
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	if (is_pci_ioaddr(port))
 		return ctrl_inl(pci_ioaddr(port));
-	else
-		maybebadio(port);
 
-	return 0;
+	return ctrl_inl(port);
 }
 
 void r7780rp_outb(u8 value, unsigned long port)
 {
 	if (CHECK_AX88796L_PORT(port))
 		ctrl_outw(value, port88796l(port, 0));
-	else if (PXSEG(port))
-		ctrl_outb(value, port);
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	else if (is_pci_ioaddr(port))
 		ctrl_outb(value, pci_ioaddr(port));
 	else
-		ctrl_outw(value, port2adr(port));
+		ctrl_outb(value, port);
 }
 
 void r7780rp_outb_p(u8 value, unsigned long port)
 {
 	if (CHECK_AX88796L_PORT(port))
 		ctrl_outw(value, port88796l(port, 0));
-	else if (PXSEG(port))
-		ctrl_outb(value, port);
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	else if (is_pci_ioaddr(port))
 		ctrl_outb(value, pci_ioaddr(port));
 	else
-		ctrl_outw(value, port2adr(port));
+		ctrl_outb(value, port);
 
 	ctrl_delay();
 }
 
 void r7780rp_outw(u16 value, unsigned long port)
 {
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-	else if (PXSEG(port))
-		ctrl_outw(value, port);
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	if (is_pci_ioaddr(port))
 		ctrl_outw(value, pci_ioaddr(port));
 	else
-		maybebadio(port);
+		ctrl_outw(value, port);
 }
 
 void r7780rp_outl(u32 value, unsigned long port)
 {
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-	else if (PXSEG(port))
-		ctrl_outl(value, port);
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	if (is_pci_ioaddr(port))
 		ctrl_outl(value, pci_ioaddr(port));
 	else
-		maybebadio(port);
+		ctrl_outl(value, port);
 }
 
 void r7780rp_insb(unsigned long port, void *dst, unsigned long count)
@@ -183,16 +130,13 @@
 		p = (volatile u16 *)port88796l(port, 0);
 		while (count--)
 			*buf++ = *p & 0xff;
-	} else if (PXSEG(port)) {
-		while (count--)
-			*buf++ = *(volatile u8 *)port;
-	} else if (is_pci_ioaddr(port) || shifted_port(port)) {
+	} else if (is_pci_ioaddr(port)) {
 		volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
 
 		while (count--)
 			*buf++ = *bp;
 	} else {
-		p = (volatile u16 *)port2adr(port);
+		p = (volatile u16 *)port;
 		while (count--)
 			*buf++ = *p & 0xff;
 	}
@@ -205,30 +149,26 @@
 
 	if (CHECK_AX88796L_PORT(port))
 		p = (volatile u16 *)port88796l(port, 1);
-	else if (PXSEG(port))
-		p = (volatile u16 *)port;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	else if (is_pci_ioaddr(port))
 		p = (volatile u16 *)pci_ioaddr(port);
 	else
-		p = (volatile u16 *)port2adr(port);
+		p = (volatile u16 *)port;
 
 	while (count--)
 		*buf++ = *p;
+
+	flush_dcache_all();
 }
 
 void r7780rp_insl(unsigned long port, void *dst, unsigned long count)
 {
-	u32 *buf = dst;
-
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-	else if (is_pci_ioaddr(port) || shifted_port(port)) {
+	if (is_pci_ioaddr(port)) {
 		volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+		u32 *buf = dst;
 
 		while (count--)
 			*buf++ = *p;
-	} else
-		maybebadio(port);
+	}
 }
 
 void r7780rp_outsb(unsigned long port, const void *src, unsigned long count)
@@ -240,19 +180,14 @@
 		p = (volatile u16 *)port88796l(port, 0);
 		while (count--)
 			*p = *buf++;
-	} else if (PXSEG(port))
-		while (count--)
-			ctrl_outb(*buf++, port);
-	else if (is_pci_ioaddr(port) || shifted_port(port)) {
+	} else if (is_pci_ioaddr(port)) {
 		volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
 
 		while (count--)
 			*bp = *buf++;
-	} else {
-		p = (volatile u16 *)port2adr(port);
+	} else
 		while (count--)
-			*p = *buf++;
-	}
+			ctrl_outb(*buf++, port);
 }
 
 void r7780rp_outsw(unsigned long port, const void *src, unsigned long count)
@@ -262,40 +197,37 @@
 
 	if (CHECK_AX88796L_PORT(port))
 		p = (volatile u16 *)port88796l(port, 1);
-	else if (PXSEG(port))
-		p = (volatile u16 *)port;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	else if (is_pci_ioaddr(port))
 		p = (volatile u16 *)pci_ioaddr(port);
 	else
-		p = (volatile u16 *)port2adr(port);
+		p = (volatile u16 *)port;
 
 	while (count--)
 		*p = *buf++;
+
+	flush_dcache_all();
 }
 
 void r7780rp_outsl(unsigned long port, const void *src, unsigned long count)
 {
 	const u32 *buf = src;
+	u32 *p;
 
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-	else if (is_pci_ioaddr(port) || shifted_port(port)) {
-		volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+	if (is_pci_ioaddr(port))
+		p = (u32 *)pci_ioaddr(port);
+	else
+		p = (u32 *)port;
 
-		while (count--)
-			*p = *buf++;
-	} else
-		maybebadio(port);
+	while (count--)
+		ctrl_outl(*buf++, (unsigned long)p);
 }
 
 void __iomem *r7780rp_ioport_map(unsigned long port, unsigned int size)
 {
 	if (CHECK_AX88796L_PORT(port))
 		return (void __iomem *)port88796l(port, size > 1);
-	else if (PXSEG(port))
-		return (void __iomem *)port;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
+	else if (is_pci_ioaddr(port))
 		return (void __iomem *)pci_ioaddr(port);
 
-	return (void __iomem *)port2adr(port);
+	return (void __iomem *)port;
 }
diff --git a/arch/sh/boards/renesas/r7780rp/led.c b/arch/sh/boards/renesas/r7780rp/led.c
deleted file mode 100644
index 6a00a25..0000000
--- a/arch/sh/boards/renesas/r7780rp/led.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) Atom Create Engineering Co., Ltd.
- *
- * May be copied or modified under the terms of GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Renesas Solutions HIGHLANDER R7780RP-1 specific LED code.
- */
-#include <linux/sched.h>
-#include <asm/io.h>
-#include <asm/r7780rp/r7780rp.h>
-
-/* Cycle the LED's in the clasic Knightriger/Sun pattern */
-void heartbeat_r7780rp(void)
-{
-	static unsigned int cnt = 0, period = 0;
-	volatile unsigned short *p = (volatile unsigned short *)PA_OBLED;
-	static unsigned bit = 0, up = 1;
-	unsigned bit_pos[] = {2, 1, 0, 3, 6, 5, 4, 7};
-
-	cnt += 1;
-	if (cnt < period)
-		return;
-
-	cnt = 0;
-
-	/* Go through the points (roughly!):
-	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35, f(int)->110
-	 */
-	period = 110 - ((300 << FSHIFT)/((avenrun[0]/5) + (3<<FSHIFT)));
-
-	*p = 1 << bit_pos[bit];
-	if (up)
-		if (bit == 7) {
-			bit--;
-			up = 0;
-		} else
-			bit++;
-	else if (bit == 0)
-		up = 1;
-	else
-		bit--;
-}
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index 9f89c8d..0d74db9 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -2,7 +2,7 @@
  * arch/sh/boards/renesas/r7780rp/setup.c
  *
  * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
- * Copyright (C) 2005, 2006 Paul Mundt
+ * Copyright (C) 2005 - 2007 Paul Mundt
  *
  * Renesas Solutions Highlander R7780RP-1 Support.
  *
@@ -12,12 +12,12 @@
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/pata_platform.h>
 #include <asm/machvec.h>
 #include <asm/r7780rp.h>
 #include <asm/clock.h>
 #include <asm/io.h>
 
-extern void heartbeat_r7780rp(void);
 extern void init_r7780rp_IRQ(void);
 
 static struct resource m66596_usb_host_resources[] = {
@@ -46,14 +46,14 @@
 
 static struct resource cf_ide_resources[] = {
 	[0] = {
-		.start	= 0x1f0,
-		.end	= 0x1f0 + 8,
-		.flags	= IORESOURCE_IO,
+		.start	= PA_AREA5_IO + 0x1000,
+		.end	= PA_AREA5_IO + 0x1000 + 0x08 - 1,
+		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= 0x1f0 + 0x206,
-		.end	= 0x1f0 + 8 + 0x206 + 8,
-		.flags	= IORESOURCE_IO,
+		.start	= PA_AREA5_IO + 0x80c,
+		.end	= PA_AREA5_IO + 0x80c + 0x16 - 1,
+		.flags	= IORESOURCE_MEM,
 	},
 	[2] = {
 #ifdef CONFIG_SH_R7780MP
@@ -65,16 +65,44 @@
 	},
 };
 
+static struct pata_platform_info pata_info = {
+	.ioport_shift	= 1,
+};
+
 static struct platform_device cf_ide_device  = {
 	.name		= "pata_platform",
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(cf_ide_resources),
 	.resource	= cf_ide_resources,
+	.dev	= {
+		.platform_data	= &pata_info,
+	},
+};
+
+static unsigned char heartbeat_bit_pos[] = { 2, 1, 0, 3, 6, 5, 4, 7 };
+
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= PA_OBLED,
+		.end	= PA_OBLED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.dev	= {
+		.platform_data	= heartbeat_bit_pos,
+	},
+	.num_resources	= ARRAY_SIZE(heartbeat_resources),
+	.resource	= heartbeat_resources,
 };
 
 static struct platform_device *r7780rp_devices[] __initdata = {
 	&m66596_usb_host_device,
 	&cf_ide_device,
+	&heartbeat_device,
 };
 
 static int __init r7780rp_devices_setup(void)
@@ -148,7 +176,7 @@
 #ifndef CONFIG_SH_R7780MP
 	ctrl_outw(0x0001, PA_SDPOW);	/* SD Power ON */
 #endif
-	ctrl_outw(ctrl_inw(PA_IVDRCTL) | 0x0100, PA_IVDRCTL);	/* Si13112 */
+	ctrl_outw(ctrl_inw(PA_IVDRCTL) | 0x01, PA_IVDRCTL);	/* Si13112 */
 
 	pm_power_off = r7780rp_power_off;
 }
@@ -185,8 +213,5 @@
 
 	.mv_ioport_map		= r7780rp_ioport_map,
 	.mv_init_irq		= init_r7780rp_IRQ,
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat		= heartbeat_r7780rp,
-#endif
 };
 ALIAS_MV(r7780rp)
diff --git a/arch/sh/boards/renesas/rts7751r2d/Makefile b/arch/sh/boards/renesas/rts7751r2d/Makefile
index 686fc9e..0d4c75a 100644
--- a/arch/sh/boards/renesas/rts7751r2d/Makefile
+++ b/arch/sh/boards/renesas/rts7751r2d/Makefile
@@ -2,5 +2,4 @@
 # Makefile for the RTS7751R2D specific parts of the kernel
 #
 
-obj-y	 := setup.o io.o irq.o
-obj-$(CONFIG_HEARTBEAT) += led.o
+obj-y	 := setup.o irq.o
diff --git a/arch/sh/boards/renesas/rts7751r2d/io.c b/arch/sh/boards/renesas/rts7751r2d/io.c
deleted file mode 100644
index f2507a8..0000000
--- a/arch/sh/boards/renesas/rts7751r2d/io.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
- * Based largely on io_se.c.
- *
- * I/O routine for Renesas Technology sales RTS7751R2D.
- *
- * Initial version only to support LAN access; some
- * placeholder code from io_rts7751r2d.c left in with the
- * expectation of later SuperIO and PCMCIA access.
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <asm/rts7751r2d.h>
-#include <asm/addrspace.h>
-
-/*
- * The 7751R RTS7751R2D uses the built-in PCI controller (PCIC)
- * of the 7751R processor, and has a SuperIO accessible via the PCI.
- * The board also includes a PCMCIA controller on its memory bus,
- * like the other Solution Engine boards.
- */
-
-static inline unsigned long port2adr(unsigned int port)
-{
-	if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
-		if (port == 0x3f6)
-			return (PA_AREA5_IO + 0x80c);
-		else
-			return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
-	else
-		maybebadio((unsigned long)port);
-
-	return port;
-}
-
-static inline unsigned long port88796l(unsigned int port, int flag)
-{
-	unsigned long addr;
-
-	if (flag)
-		addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1);
-	else
-		addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1) + 0x1000;
-
-	return addr;
-}
-
-/* The 7751R RTS7751R2D seems to have everything hooked */
-/* up pretty normally (nothing on high-bytes only...) so this */
-/* shouldn't be needed */
-static inline int shifted_port(unsigned long port)
-{
-	/* For IDE registers, value is not shifted */
-	if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
-		return 0;
-	else
-		return 1;
-}
-
-#if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
-#define CHECK_AX88796L_PORT(port) \
-  ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
-#else
-#define CHECK_AX88796L_PORT(port) (0)
-#endif
-
-/*
- * General outline: remap really low stuff [eventually] to SuperIO,
- * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
- * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
- * should be way beyond the window, and is used  w/o translation for
- * compatibility.
- */
-unsigned char rts7751r2d_inb(unsigned long port)
-{
-	if (CHECK_AX88796L_PORT(port))
-		return (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
-	else if (PXSEG(port))
-		return *(volatile unsigned char *)port;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
-		return *(volatile unsigned char *)pci_ioaddr(port);
-	else
-		return (*(volatile unsigned short *)port2adr(port) & 0xff);
-}
-
-unsigned char rts7751r2d_inb_p(unsigned long port)
-{
-	unsigned char v;
-
-	if (CHECK_AX88796L_PORT(port))
-		v = (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
-        else if (PXSEG(port))
-		v = *(volatile unsigned char *)port;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
-		v = *(volatile unsigned char *)pci_ioaddr(port);
-	else
-		v = (*(volatile unsigned short *)port2adr(port) & 0xff);
-
-	ctrl_delay();
-
-	return v;
-}
-
-unsigned short rts7751r2d_inw(unsigned long port)
-{
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-        else if (PXSEG(port))
-		return *(volatile unsigned short *)port;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
-		return *(volatile unsigned short *)pci_ioaddr(port);
-	else
-		maybebadio(port);
-
-	return 0;
-}
-
-unsigned int rts7751r2d_inl(unsigned long port)
-{
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-        else if (PXSEG(port))
-		return *(volatile unsigned long *)port;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
-		return *(volatile unsigned long *)pci_ioaddr(port);
-	else
-		maybebadio(port);
-
-	return 0;
-}
-
-void rts7751r2d_outb(unsigned char value, unsigned long port)
-{
-	if (CHECK_AX88796L_PORT(port))
-		*((volatile unsigned short *)port88796l(port, 0)) = value;
-        else if (PXSEG(port))
-		*(volatile unsigned char *)port = value;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
-		*(volatile unsigned char *)pci_ioaddr(port) = value;
-	else
-		*(volatile unsigned short *)port2adr(port) = value;
-}
-
-void rts7751r2d_outb_p(unsigned char value, unsigned long port)
-{
-	if (CHECK_AX88796L_PORT(port))
-		*((volatile unsigned short *)port88796l(port, 0)) = value;
-        else if (PXSEG(port))
-		*(volatile unsigned char *)port = value;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
-		*(volatile unsigned char *)pci_ioaddr(port) = value;
-	else
-		*(volatile unsigned short *)port2adr(port) = value;
-
-	ctrl_delay();
-}
-
-void rts7751r2d_outw(unsigned short value, unsigned long port)
-{
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-        else if (PXSEG(port))
-		*(volatile unsigned short *)port = value;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
-		*(volatile unsigned short *)pci_ioaddr(port) = value;
-	else
-		maybebadio(port);
-}
-
-void rts7751r2d_outl(unsigned int value, unsigned long port)
-{
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-        else if (PXSEG(port))
-		*(volatile unsigned long *)port = value;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
-		*(volatile unsigned long *)pci_ioaddr(port) = value;
-	else
-		maybebadio(port);
-}
-
-void rts7751r2d_insb(unsigned long port, void *addr, unsigned long count)
-{
-	unsigned long a = (unsigned long)addr;
-	volatile __u8 *bp;
-	volatile __u16 *p;
-
-	if (CHECK_AX88796L_PORT(port)) {
-		p = (volatile unsigned short *)port88796l(port, 0);
-		while (count--)
-			ctrl_outb(*p & 0xff, a++);
-	} else if (PXSEG(port))
-		while (count--)
-			ctrl_outb(ctrl_inb(port), a++);
-	else if (is_pci_ioaddr(port) || shifted_port(port)) {
-		bp = (__u8 *)pci_ioaddr(port);
-		while (count--)
-			ctrl_outb(*bp, a++);
-	} else {
-		p = (volatile unsigned short *)port2adr(port);
-		while (count--)
-			ctrl_outb(*p & 0xff, a++);
-	}
-}
-
-void rts7751r2d_insw(unsigned long port, void *addr, unsigned long count)
-{
-	unsigned long a = (unsigned long)addr;
-	volatile __u16 *p;
-
-	if (CHECK_AX88796L_PORT(port))
-		p = (volatile unsigned short *)port88796l(port, 1);
-	else if (PXSEG(port))
-		p = (volatile unsigned short *)port;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
-		p = (volatile unsigned short *)pci_ioaddr(port);
-	else
-		p = (volatile unsigned short *)port2adr(port);
-	while (count--)
-		ctrl_outw(*p, a++);
-}
-
-void rts7751r2d_insl(unsigned long port, void *addr, unsigned long count)
-{
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-	else if (is_pci_ioaddr(port) || shifted_port(port)) {
-		unsigned long a = (unsigned long)addr;
-
-		while (count--) {
-			ctrl_outl(ctrl_inl(pci_ioaddr(port)), a);
-			a += 4;
-		}
-	} else
-		maybebadio(port);
-}
-
-void rts7751r2d_outsb(unsigned long port, const void *addr, unsigned long count)
-{
-	unsigned long a = (unsigned long)addr;
-	volatile __u8 *bp;
-	volatile __u16 *p;
-
-	if (CHECK_AX88796L_PORT(port)) {
-		p = (volatile unsigned short *)port88796l(port, 0);
-		while (count--)
-			*p = ctrl_inb(a++);
-	} else if (PXSEG(port))
-		while (count--)
-			ctrl_outb(a++, port);
-	else if (is_pci_ioaddr(port) || shifted_port(port)) {
-		bp = (__u8 *)pci_ioaddr(port);
-		while (count--)
-			*bp = ctrl_inb(a++);
-	} else {
-		p = (volatile unsigned short *)port2adr(port);
-		while (count--)
-			*p = ctrl_inb(a++);
-	}
-}
-
-void rts7751r2d_outsw(unsigned long port, const void *addr, unsigned long count)
-{
-	unsigned long a = (unsigned long)addr;
-	volatile __u16 *p;
-
-	if (CHECK_AX88796L_PORT(port))
-		p = (volatile unsigned short *)port88796l(port, 1);
-	else if (PXSEG(port))
-		p = (volatile unsigned short *)port;
-	else if (is_pci_ioaddr(port) || shifted_port(port))
-		p = (volatile unsigned short *)pci_ioaddr(port);
-	else
-		p = (volatile unsigned short *)port2adr(port);
-
-	while (count--) {
-		ctrl_outw(*p, a);
-		a += 2;
-	}
-}
-
-void rts7751r2d_outsl(unsigned long port, const void *addr, unsigned long count)
-{
-	if (CHECK_AX88796L_PORT(port))
-		maybebadio(port);
-	else if (is_pci_ioaddr(port) || shifted_port(port)) {
-		unsigned long a = (unsigned long)addr;
-
-		while (count--) {
-			ctrl_outl(ctrl_inl(a), pci_ioaddr(port));
-			a += 4;
-		}
-	} else
-		maybebadio(port);
-}
-
-unsigned long rts7751r2d_isa_port2addr(unsigned long offset)
-{
-	return port2adr(offset);
-}
diff --git a/arch/sh/boards/renesas/rts7751r2d/irq.c b/arch/sh/boards/renesas/rts7751r2d/irq.c
index cb0eb20..0bae904 100644
--- a/arch/sh/boards/renesas/rts7751r2d/irq.c
+++ b/arch/sh/boards/renesas/rts7751r2d/irq.c
@@ -9,7 +9,9 @@
  * Atom Create Engineering Co., Ltd. 2002.
  */
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/rts7751r2d.h>
 
@@ -22,79 +24,31 @@
 extern int voyagergx_irq_demux(int irq);
 extern void setup_voyagergx_irq(void);
 
-static void enable_rts7751r2d_irq(unsigned int irq);
-static void disable_rts7751r2d_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_rts7751r2d_irq disable_rts7751r2d_irq
-
-static void ack_rts7751r2d_irq(unsigned int irq);
-static void end_rts7751r2d_irq(unsigned int irq);
-
-static unsigned int startup_rts7751r2d_irq(unsigned int irq)
+static void enable_rts7751r2d_irq(unsigned int irq)
 {
-	enable_rts7751r2d_irq(irq);
-	return 0; /* never anything pending */
+	/* Set priority in IPR back to original value */
+	ctrl_outw(ctrl_inw(IRLCNTR1) | (1 << mask_pos[irq]), IRLCNTR1);
 }
 
 static void disable_rts7751r2d_irq(unsigned int irq)
 {
-	unsigned short val;
-	unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
-
 	/* Set the priority in IPR to 0 */
-	val = ctrl_inw(IRLCNTR1);
-	val &= mask;
-	ctrl_outw(val, IRLCNTR1);
-}
-
-static void enable_rts7751r2d_irq(unsigned int irq)
-{
-	unsigned short val;
-	unsigned short value = (0x0001 << mask_pos[irq]);
-
-	/* Set priority in IPR back to original value */
-	val = ctrl_inw(IRLCNTR1);
-	val |= value;
-	ctrl_outw(val, IRLCNTR1);
+	ctrl_outw(ctrl_inw(IRLCNTR1) & (0xffff ^ (1 << mask_pos[irq])),
+		  IRLCNTR1);
 }
 
 int rts7751r2d_irq_demux(int irq)
 {
-	int demux_irq;
-
-	demux_irq = voyagergx_irq_demux(irq);
-	return demux_irq;
+	return voyagergx_irq_demux(irq);
 }
 
-static void ack_rts7751r2d_irq(unsigned int irq)
-{
-	disable_rts7751r2d_irq(irq);
-}
-
-static void end_rts7751r2d_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_rts7751r2d_irq(irq);
-}
-
-static struct hw_interrupt_type rts7751r2d_irq_type = {
-	.typename = "RTS7751R2D IRQ",
-	.startup = startup_rts7751r2d_irq,
-	.shutdown = shutdown_rts7751r2d_irq,
-	.enable = enable_rts7751r2d_irq,
-	.disable = disable_rts7751r2d_irq,
-	.ack = ack_rts7751r2d_irq,
-	.end = end_rts7751r2d_irq,
+static struct irq_chip rts7751r2d_irq_chip __read_mostly = {
+	.name		= "rts7751r2d",
+	.mask		= disable_rts7751r2d_irq,
+	.unmask		= enable_rts7751r2d_irq,
+	.mask_ack	= disable_rts7751r2d_irq,
 };
 
-static void make_rts7751r2d_irq(unsigned int irq)
-{
-	disable_irq_nosync(irq);
-	irq_desc[irq].chip = &rts7751r2d_irq_type;
-	disable_rts7751r2d_irq(irq);
-}
-
 /*
  * Initialize IRQ setting
  */
@@ -119,8 +73,12 @@
 	 * IRL14=Extention #3
 	 */
 
-	for (i=0; i<15; i++)
-		make_rts7751r2d_irq(i);
+	for (i=0; i<15; i++) {
+		disable_irq_nosync(i);
+		set_irq_chip_and_handler_name(i, &rts7751r2d_irq_chip,
+					      handle_level_irq, "level");
+		enable_rts7751r2d_irq(i);
+	}
 
 	setup_voyagergx_irq();
 }
diff --git a/arch/sh/boards/renesas/rts7751r2d/led.c b/arch/sh/boards/renesas/rts7751r2d/led.c
deleted file mode 100644
index 509f548..0000000
--- a/arch/sh/boards/renesas/rts7751r2d/led.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * linux/arch/sh/boards/renesas/rts7751r2d/led.c
- *
- * Copyright (C) Atom Create Engineering Co., Ltd.
- *
- * May be copied or modified under the terms of GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Renesas Technology Sales RTS7751R2D specific LED code.
- */
-#include <linux/io.h>
-#include <linux/sched.h>
-#include <asm/rts7751r2d.h>
-
-/* Cycle the LED's in the clasic Knightriger/Sun pattern */
-void heartbeat_rts7751r2d(void)
-{
-	static unsigned int cnt = 0, period = 0;
-	volatile unsigned short *p = (volatile unsigned short *)PA_OUTPORT;
-	static unsigned bit = 0, up = 1;
-
-	cnt += 1;
-	if (cnt < period)
-		return;
-
-	cnt = 0;
-
-	/* Go through the points (roughly!):
-	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35, f(int)->110
-	 */
-	period = 110 - ((300 << FSHIFT)/((avenrun[0]/5) + (3<<FSHIFT)));
-
-	*p = 1 << bit;
-	if (up)
-		if (bit == 7) {
-			bit--;
-			up = 0;
-		} else
-			bit++;
-	else if (bit == 0)
-		up = 1;
-	else
-		bit--;
-}
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
index 5c042d3..44b4208 100644
--- a/arch/sh/boards/renesas/rts7751r2d/setup.c
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -1,8 +1,8 @@
 /*
  * Renesas Technology Sales RTS7751R2D Support.
  *
- * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
- * Copyright (C) 2004 - 2006 Paul Mundt
+ * Copyright (C) 2002 - 2006 Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2004 - 2007 Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -10,33 +10,13 @@
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/pata_platform.h>
 #include <linux/serial_8250.h>
 #include <linux/pm.h>
 #include <asm/machvec.h>
-#include <asm/mach/rts7751r2d.h>
-#include <asm/io.h>
+#include <asm/rts7751r2d.h>
 #include <asm/voyagergx.h>
-
-extern void heartbeat_rts7751r2d(void);
-extern void init_rts7751r2d_IRQ(void);
-extern int rts7751r2d_irq_demux(int irq);
-
-extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
-extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
-
-static struct plat_serial8250_port uart_platform_data[] = {
-	{
-		.membase	= (void *)VOYAGER_UART_BASE,
-		.mapbase	= VOYAGER_UART_BASE,
-		.iotype		= UPIO_MEM,
-		.irq		= VOYAGER_UART0_IRQ,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.regshift	= 2,
-		.uartclk	= (9600 * 16),
-	}, {
-		.flags		= 0,
-	},
-};
+#include <asm/io.h>
 
 static void __init voyagergx_serial_init(void)
 {
@@ -45,32 +25,96 @@
 	/*
 	 * GPIO Control
 	 */
-	val = inl(GPIO_MUX_HIGH);
+	val = readl((void __iomem *)GPIO_MUX_HIGH);
 	val |= 0x00001fe0;
-	outl(val, GPIO_MUX_HIGH);
+	writel(val, (void __iomem *)GPIO_MUX_HIGH);
 
 	/*
 	 * Power Mode Gate
 	 */
-	val = inl(POWER_MODE0_GATE);
+	val = readl((void __iomem *)POWER_MODE0_GATE);
 	val |= (POWER_MODE0_GATE_U0 | POWER_MODE0_GATE_U1);
-	outl(val, POWER_MODE0_GATE);
+	writel(val, (void __iomem *)POWER_MODE0_GATE);
 
-	val = inl(POWER_MODE1_GATE);
+	val = readl((void __iomem *)POWER_MODE1_GATE);
 	val |= (POWER_MODE1_GATE_U0 | POWER_MODE1_GATE_U1);
-	outl(val, POWER_MODE1_GATE);
+	writel(val, (void __iomem *)POWER_MODE1_GATE);
 }
 
+static struct resource cf_ide_resources[] = {
+	[0] = {
+		.start	= PA_AREA5_IO + 0x1000,
+		.end	= PA_AREA5_IO + 0x1000 + 0x08 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= PA_AREA5_IO + 0x80c,
+		.end	= PA_AREA5_IO + 0x80c + 0x16 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+#ifdef CONFIG_RTS7751R2D_REV11
+		.start	= 1,
+#else
+		.start	= 2,
+#endif
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct pata_platform_info pata_info = {
+	.ioport_shift	= 1,
+};
+
+static struct platform_device cf_ide_device  = {
+	.name		= "pata_platform",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(cf_ide_resources),
+	.resource	= cf_ide_resources,
+	.dev	= {
+		.platform_data	= &pata_info,
+	},
+};
+
+static struct plat_serial8250_port uart_platform_data[] = {
+	{
+		.membase	= (void __iomem *)VOYAGER_UART_BASE,
+		.mapbase	= VOYAGER_UART_BASE,
+		.iotype		= UPIO_MEM,
+		.irq		= VOYAGER_UART0_IRQ,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.regshift	= 2,
+		.uartclk	= (9600 * 16),
+	}
+};
+
 static struct platform_device uart_device = {
 	.name		= "serial8250",
-	.id		= -1,
+	.id		= PLAT8250_DEV_PLATFORM,
 	.dev		= {
 		.platform_data	= uart_platform_data,
 	},
 };
 
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= PA_OUTPORT,
+		.end	= PA_OUTPORT + 8 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(heartbeat_resources),
+	.resource	= heartbeat_resources,
+};
+
 static struct platform_device *rts7751r2d_devices[] __initdata = {
 	&uart_device,
+	&heartbeat_device,
+	&cf_ide_device,
 };
 
 static int __init rts7751r2d_devices_setup(void)
@@ -78,6 +122,7 @@
 	return platform_add_devices(rts7751r2d_devices,
 				    ARRAY_SIZE(rts7751r2d_devices));
 }
+__initcall(rts7751r2d_devices_setup);
 
 static void rts7751r2d_power_off(void)
 {
@@ -89,14 +134,17 @@
  */
 static void __init rts7751r2d_setup(char **cmdline_p)
 {
-	device_initcall(rts7751r2d_devices_setup);
+	u16 ver = ctrl_inw(PA_VERREG);
+
+	printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
+
+	printk(KERN_INFO "FPGA version:%d (revision:%d)\n",
+					(ver >> 4) & 0xf, ver & 0xf);
 
 	ctrl_outw(0x0000, PA_OUTPORT);
 	pm_power_off = rts7751r2d_power_off;
 
 	voyagergx_serial_init();
-
-	printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
 }
 
 /*
@@ -107,31 +155,7 @@
 	.mv_setup		= rts7751r2d_setup,
 	.mv_nr_irqs		= 72,
 
-	.mv_inb			= rts7751r2d_inb,
-	.mv_inw			= rts7751r2d_inw,
-	.mv_inl			= rts7751r2d_inl,
-	.mv_outb		= rts7751r2d_outb,
-	.mv_outw		= rts7751r2d_outw,
-	.mv_outl		= rts7751r2d_outl,
-
-	.mv_inb_p		= rts7751r2d_inb_p,
-	.mv_inw_p		= rts7751r2d_inw,
-	.mv_inl_p		= rts7751r2d_inl,
-	.mv_outb_p		= rts7751r2d_outb_p,
-	.mv_outw_p		= rts7751r2d_outw,
-	.mv_outl_p		= rts7751r2d_outl,
-
-	.mv_insb		= rts7751r2d_insb,
-	.mv_insw		= rts7751r2d_insw,
-	.mv_insl		= rts7751r2d_insl,
-	.mv_outsb		= rts7751r2d_outsb,
-	.mv_outsw		= rts7751r2d_outsw,
-	.mv_outsl		= rts7751r2d_outsl,
-
 	.mv_init_irq		= init_rts7751r2d_IRQ,
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat		= heartbeat_rts7751r2d,
-#endif
 	.mv_irq_demux		= rts7751r2d_irq_demux,
 
 #ifdef CONFIG_USB_SM501
diff --git a/arch/sh/boards/se/7206/Makefile b/arch/sh/boards/se/7206/Makefile
index 63950f4f..63e7ed6 100644
--- a/arch/sh/boards/se/7206/Makefile
+++ b/arch/sh/boards/se/7206/Makefile
@@ -3,5 +3,3 @@
 #
 
 obj-y	 := setup.o io.o irq.o
-obj-$(CONFIG_HEARTBEAT) += led.o
-
diff --git a/arch/sh/boards/se/7206/led.c b/arch/sh/boards/se/7206/led.c
deleted file mode 100644
index ef79460..0000000
--- a/arch/sh/boards/se/7206/led.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * linux/arch/sh/kernel/led_se.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Solution Engine specific LED code.
- */
-
-#include <linux/config.h>
-#include <asm/se7206.h>
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_se(void)
-{
-	static unsigned int cnt = 0, period = 0;
-	volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-	static unsigned bit = 0, up = 1;
-
-	cnt += 1;
-	if (cnt < period) {
-		return;
-	}
-
-	cnt = 0;
-
-	/* Go through the points (roughly!):
-	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-	 */
-	period = 110 - ( (300<<FSHIFT)/
-			 ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-	if (up) {
-		if (bit == 7) {
-			bit--;
-			up=0;
-		} else {
-			bit ++;
-		}
-	} else {
-		if (bit == 0) {
-			bit++;
-			up=1;
-		} else {
-			bit--;
-		}
-	}
-	*p = 1<<(bit+8);
-
-}
-#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/7206/setup.c b/arch/sh/boards/se/7206/setup.c
index 0f42e91..ca71487 100644
--- a/arch/sh/boards/se/7206/setup.c
+++ b/arch/sh/boards/se/7206/setup.c
@@ -3,6 +3,7 @@
  * linux/arch/sh/boards/se/7206/setup.c
  *
  * Copyright (C) 2006  Yoshinori Sato
+ * Copyright (C) 2007  Paul Mundt
  *
  * Hitachi 7206 SolutionEngine Support.
  *
@@ -34,15 +35,37 @@
 	.resource	= smc91x_resources,
 };
 
+static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
+
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= PA_LED,
+		.end	= PA_LED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.dev	= {
+		.platform_data	= heartbeat_bit_pos,
+	},
+	.num_resources	= ARRAY_SIZE(heartbeat_resources),
+	.resource	= heartbeat_resources,
+};
+
+static struct platform_device *se7206_devices[] __initdata = {
+	&smc91x_device,
+	&heartbeat_device,
+};
+
 static int __init se7206_devices_setup(void)
 {
-	return platform_device_register(&smc91x_device);
+	return platform_add_devices(se7206_devices, ARRAY_SIZE(se7206_devices));
 }
-
 __initcall(se7206_devices_setup);
 
-void heartbeat_se(void);
-
 /*
  * The Machine Vector
  */
@@ -72,8 +95,5 @@
 	.mv_outsl		= se7206_outsl,
 
 	.mv_init_irq		= init_se7206_IRQ,
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat		= heartbeat_se,
-#endif
 };
 ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7300/Makefile b/arch/sh/boards/se/7300/Makefile
index 0fbd4f4..4624736 100644
--- a/arch/sh/boards/se/7300/Makefile
+++ b/arch/sh/boards/se/7300/Makefile
@@ -3,5 +3,3 @@
 #
 
 obj-y	 := setup.o io.o irq.o
-
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7300/led.c b/arch/sh/boards/se/7300/led.c
deleted file mode 100644
index 4d03bb7..0000000
--- a/arch/sh/boards/se/7300/led.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/sh/boards/se/7300/led.c
- *
- * Derived from linux/arch/sh/boards/se/770x/led.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Solution Engine specific LED code.
- */
-
-#include <linux/sched.h>
-#include <asm/se7300.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_7300se(void)
-{
-	static unsigned int cnt = 0, period = 0;
-	volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-	static unsigned bit = 0, up = 1;
-
-	cnt += 1;
-	if (cnt < period) {
-		return;
-	}
-
-	cnt = 0;
-
-	/* Go through the points (roughly!):
-	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-	 */
-	period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
-
-	if (up) {
-		if (bit == 7) {
-			bit--;
-			up = 0;
-		} else {
-			bit++;
-		}
-	} else {
-		if (bit == 0) {
-			bit++;
-			up = 1;
-		} else {
-			bit--;
-		}
-	}
-	*p = 1 << (bit + 8);
-
-}
-
diff --git a/arch/sh/boards/se/7300/setup.c b/arch/sh/boards/se/7300/setup.c
index 6f082a72..f196095 100644
--- a/arch/sh/boards/se/7300/setup.c
+++ b/arch/sh/boards/se/7300/setup.c
@@ -6,14 +6,43 @@
  * SH-Mobile SolutionEngine 7300 Support.
  *
  */
-
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/machvec.h>
 #include <asm/se7300.h>
 
-void heartbeat_7300se(void);
 void init_7300se_IRQ(void);
 
+static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
+
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= PA_LED,
+		.end	= PA_LED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.dev	= {
+		.platform_data	= heartbeat_bit_pos,
+	},
+	.num_resources	= ARRAY_SIZE(heartbeat_resources),
+	.resource	= heartbeat_resources,
+};
+
+static struct platform_device *se7300_devices[] __initdata = {
+	&heartbeat_device,
+};
+
+static int __init se7300_devices_setup(void)
+{
+	return platform_add_devices(se7300_devices, ARRAY_SIZE(se7300_devices));
+}
+__initcall(se7300_devices_setup);
+
 /*
  * The Machine Vector
  */
@@ -42,8 +71,5 @@
 	.mv_outsl = sh7300se_outsl,
 
 	.mv_init_irq = init_7300se_IRQ,
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat = heartbeat_7300se,
-#endif
 };
 ALIAS_MV(7300se)
diff --git a/arch/sh/boards/se/73180/Makefile b/arch/sh/boards/se/73180/Makefile
index 8f63886..e7c0996 100644
--- a/arch/sh/boards/se/73180/Makefile
+++ b/arch/sh/boards/se/73180/Makefile
@@ -3,5 +3,3 @@
 #
 
 obj-y	 := setup.o io.o irq.o
-
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/73180/led.c b/arch/sh/boards/se/73180/led.c
deleted file mode 100644
index 4b72e9a..0000000
--- a/arch/sh/boards/se/73180/led.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/sh/boards/se/73180/led.c
- *
- * Derived from arch/sh/boards/se/770x/led.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Solution Engine specific LED code.
- */
-
-#include <linux/sched.h>
-#include <asm/mach/se73180.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_73180se(void)
-{
-	static unsigned int cnt = 0, period = 0;
-	volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-	static unsigned bit = 0, up = 1;
-
-	cnt += 1;
-	if (cnt < period) {
-		return;
-	}
-
-	cnt = 0;
-
-	/* Go through the points (roughly!):
-	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-	 */
-	period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
-
-	if (up) {
-		if (bit == 7) {
-			bit--;
-			up = 0;
-		} else {
-			bit++;
-		}
-	} else {
-		if (bit == 0) {
-			bit++;
-			up = 1;
-		} else {
-			bit--;
-		}
-	}
-	*p = 1 << (bit + LED_SHIFT);
-
-}
diff --git a/arch/sh/boards/se/73180/setup.c b/arch/sh/boards/se/73180/setup.c
index b38ef50..911ce1c 100644
--- a/arch/sh/boards/se/73180/setup.c
+++ b/arch/sh/boards/se/73180/setup.c
@@ -10,13 +10,39 @@
  */
 
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/machvec.h>
 #include <asm/se73180.h>
 #include <asm/irq.h>
 
-void heartbeat_73180se(void);
 void init_73180se_IRQ(void);
 
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= PA_LED,
+		.end	= PA_LED + 8 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(heartbeat_resources),
+	.resource	= heartbeat_resources,
+};
+
+static struct platform_device *se73180_devices[] __initdata = {
+	&heartbeat_device,
+};
+
+static int __init se73180_devices_setup(void)
+{
+	return platform_add_devices(sh7343se_platform_devices,
+				    ARRAY_SIZE(sh7343se_platform_devices));
+}
+__initcall(se73180_devices_setup);
+
 /*
  * The Machine Vector
  */
@@ -46,8 +72,5 @@
 
 	.mv_init_irq = init_73180se_IRQ,
 	.mv_irq_demux = shmse_irq_demux,
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat = heartbeat_73180se,
-#endif
 };
 ALIAS_MV(73180se)
diff --git a/arch/sh/boards/se/7343/Makefile b/arch/sh/boards/se/7343/Makefile
index 4291069..3024796 100644
--- a/arch/sh/boards/se/7343/Makefile
+++ b/arch/sh/boards/se/7343/Makefile
@@ -3,5 +3,3 @@
 #
 
 obj-y	 := setup.o io.o irq.o
-
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7343/led.c b/arch/sh/boards/se/7343/led.c
deleted file mode 100644
index 6b39e19..0000000
--- a/arch/sh/boards/se/7343/led.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * arch/sh/boards/se/7343/led.c
- *
- */
-#include <linux/sched.h>
-#include <asm/mach/se7343.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_7343se(void)
-{
-	static unsigned int cnt = 0, period = 0;
-	volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-	static unsigned bit = 0, up = 1;
-
-	cnt += 1;
-	if (cnt < period) {
-		return;
-	}
-
-	cnt = 0;
-
-	/* Go through the points (roughly!):
-	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-	 */
-	period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
-
-	if (up) {
-		if (bit == 7) {
-			bit--;
-			up = 0;
-		} else {
-			bit++;
-		}
-	} else {
-		if (bit == 0) {
-			bit++;
-			up = 1;
-		} else {
-			bit--;
-		}
-	}
-	*p = 1 << (bit + LED_SHIFT);
-
-}
diff --git a/arch/sh/boards/se/7343/setup.c b/arch/sh/boards/se/7343/setup.c
index c7d17fe..3fdb16f 100644
--- a/arch/sh/boards/se/7343/setup.c
+++ b/arch/sh/boards/se/7343/setup.c
@@ -4,7 +4,6 @@
 #include <asm/mach/se7343.h>
 #include <asm/irq.h>
 
-void heartbeat_7343se(void);
 void init_7343se_IRQ(void);
 
 static struct resource smc91x_resources[] = {
@@ -31,14 +30,30 @@
 	.resource	= smc91x_resources,
 };
 
-static struct platform_device *smc91x_platform_devices[] __initdata = {
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= PA_LED,
+		.end	= PA_LED + 8 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(heartbeat_resources),
+	.resource	= heartbeat_resources,
+};
+
+static struct platform_device *sh7343se_platform_devices[] __initdata = {
 	&smc91x_device,
+	&heartbeat_device,
 };
 
 static int __init sh7343se_devices_setup(void)
 {
-	return platform_add_devices(smc91x_platform_devices,
-				    ARRAY_SIZE(smc91x_platform_devices));
+	return platform_add_devices(sh7343se_platform_devices,
+				    ARRAY_SIZE(sh7343se_platform_devices));
 }
 
 static void __init sh7343se_setup(char **cmdline_p)
@@ -76,8 +91,5 @@
 
 	.mv_init_irq = init_7343se_IRQ,
 	.mv_irq_demux = shmse_irq_demux,
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat = heartbeat_7343se,
-#endif
 };
 ALIAS_MV(7343se)
diff --git a/arch/sh/boards/se/770x/Makefile b/arch/sh/boards/se/770x/Makefile
index 9a5035f..8e624b0 100644
--- a/arch/sh/boards/se/770x/Makefile
+++ b/arch/sh/boards/se/770x/Makefile
@@ -3,4 +3,3 @@
 #
 
 obj-y	 := setup.o io.o irq.o
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c
index fcd7cd7..307ca5d 100644
--- a/arch/sh/boards/se/770x/irq.c
+++ b/arch/sh/boards/se/770x/irq.c
@@ -2,56 +2,96 @@
  * linux/arch/sh/boards/se/770x/irq.c
  *
  * Copyright (C) 2000  Kazumoto Kojima
+ * Copyright (C) 2006  Nobuhiro Iwamatsu
  *
  * Hitachi SolutionEngine Support.
  *
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/se.h>
 
+/* 
+ * If the problem of make_ipr_irq is solved, 
+ * this code will become unnecessary. :-) 
+ */
+static void se770x_disable_ipr_irq(unsigned int irq)
+{
+	struct ipr_data *p = get_irq_chip_data(irq);
+
+	ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
+}
+
+static void se770x_enable_ipr_irq(unsigned int irq)
+{
+	struct ipr_data *p = get_irq_chip_data(irq);
+
+	ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
+}
+
+static struct irq_chip se770x_irq_chip = {
+	.name           = "MS770xSE-FPGA",
+	.mask           = se770x_disable_ipr_irq,
+	.unmask         = se770x_enable_ipr_irq,
+	.mask_ack       = se770x_disable_ipr_irq,
+};
+
+void make_se770x_irq(struct ipr_data *table, unsigned int nr_irqs)
+{
+	int i;
+
+	for (i = 0; i < nr_irqs; i++) {
+		unsigned int irq = table[i].irq;
+		disable_irq_nosync(irq);
+		set_irq_chip_and_handler_name(irq, &se770x_irq_chip,
+			handle_level_irq, "level");
+		set_irq_chip_data(irq, &table[i]);
+		se770x_enable_ipr_irq(irq);
+	}
+}
+
 static struct ipr_data se770x_ipr_map[] = {
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
 	/* This is default value */
-	{ 0xf-0x2, BCR_ILCRA, 2, 0x2 },
-	{ 0xf-0xa, BCR_ILCRA, 1, 0xa },
-	{ 0xf-0x5, BCR_ILCRB, 0, 0x5 },
-	{ 0xf-0x8, BCR_ILCRC, 1, 0x8 },
-	{ 0xf-0xc, BCR_ILCRC, 0, 0xc },
-	{ 0xf-0xe, BCR_ILCRD, 3, 0xe },
-	{ 0xf-0x3, BCR_ILCRD, 1, 0x3 }, /* LAN */
-	{ 0xf-0xd, BCR_ILCRE, 2, 0xd },
-	{ 0xf-0x9, BCR_ILCRE, 1, 0x9 },
-	{ 0xf-0x1, BCR_ILCRE, 0, 0x1 },
-	{ 0xf-0xf, BCR_ILCRF, 3, 0xf },
-	{ 0xf-0xb, BCR_ILCRF, 1, 0xb },
-	{ 0xf-0x7, BCR_ILCRG, 3, 0x7 },
-	{ 0xf-0x6, BCR_ILCRG, 2, 0x6 },
-	{ 0xf-0x4, BCR_ILCRG, 1, 0x4 },
+	{ 0xf-0x2, 0, 8,  0x2 , BCR_ILCRA},
+	{ 0xf-0xa, 0, 4,  0xa , BCR_ILCRA},
+	{ 0xf-0x5, 0, 0,  0x5 , BCR_ILCRB},
+	{ 0xf-0x8, 0, 4,  0x8 , BCR_ILCRC},
+	{ 0xf-0xc, 0, 0,  0xc , BCR_ILCRC},
+	{ 0xf-0xe, 0, 12, 0xe , BCR_ILCRD},
+	{ 0xf-0x3, 0, 4,  0x3 , BCR_ILCRD}, /* LAN */
+	{ 0xf-0xd, 0, 8,  0xd , BCR_ILCRE},
+	{ 0xf-0x9, 0, 4,  0x9 , BCR_ILCRE},
+	{ 0xf-0x1, 0, 0,  0x1 , BCR_ILCRE},
+	{ 0xf-0xf, 0, 12, 0xf , BCR_ILCRF},
+	{ 0xf-0xb, 0, 4,  0xb , BCR_ILCRF},
+	{ 0xf-0x7, 0, 12, 0x7 , BCR_ILCRG},
+	{ 0xf-0x6, 0, 8,  0x6 , BCR_ILCRG},
+	{ 0xf-0x4, 0, 4,  0x4 , BCR_ILCRG},
 #else
-	{ 14, BCR_ILCRA, 2, 0x0f-14 },
-	{ 12, BCR_ILCRA, 1, 0x0f-12 },
-	{  8, BCR_ILCRB, 1, 0x0f- 8 },
-	{  6, BCR_ILCRC, 3, 0x0f- 6 },
-	{  5, BCR_ILCRC, 2, 0x0f- 5 },
-	{  4, BCR_ILCRC, 1, 0x0f- 4 },
-	{  3, BCR_ILCRC, 0, 0x0f- 3 },
-	{  1, BCR_ILCRD, 3, 0x0f- 1 },
-
-	{ 10, BCR_ILCRD, 1, 0x0f-10 }, /* LAN */
-
-	{  0, BCR_ILCRE, 3, 0x0f- 0 }, /* PCIRQ3 */
-	{ 11, BCR_ILCRE, 2, 0x0f-11 }, /* PCIRQ2 */
-	{  9, BCR_ILCRE, 1, 0x0f- 9 }, /* PCIRQ1 */
-	{  7, BCR_ILCRE, 0, 0x0f- 7 }, /* PCIRQ0 */
-
+	{ 14, 0,  8, 0x0f-14 ,BCR_ILCRA},
+	{ 12, 0,  4, 0x0f-12 ,BCR_ILCRA},
+	{  8, 0,  4, 0x0f- 8 ,BCR_ILCRB},
+	{  6, 0, 12, 0x0f- 6 ,BCR_ILCRC},
+	{  5, 0,  8, 0x0f- 5 ,BCR_ILCRC},
+	{  4, 0,  4, 0x0f- 4 ,BCR_ILCRC},
+	{  3, 0,  0, 0x0f- 3 ,BCR_ILCRC},
+	{  1, 0, 12, 0x0f- 1 ,BCR_ILCRD},
+	/* ST NIC */
+	{ 10, 0,  4, 0x0f-10 ,BCR_ILCRD}, 	/* LAN */
+	/* MRSHPC IRQs setting */
+	{  0, 0, 12, 0x0f- 0 ,BCR_ILCRE},	/* PCIRQ3 */
+	{ 11, 0,  8, 0x0f-11 ,BCR_ILCRE}, 	/* PCIRQ2 */
+	{  9, 0,  4, 0x0f- 9 ,BCR_ILCRE}, 	/* PCIRQ1 */
+	{  7, 0,  0, 0x0f- 7 ,BCR_ILCRE}, 	/* PCIRQ0 */
 	/* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
 	/* NOTE: #2 and #13 are not used on PC */
-	{ 13, BCR_ILCRG, 1, 0x0f-13 }, /* SLOTIRQ2 */
-	{  2, BCR_ILCRG, 0, 0x0f- 2 }, /* SLOTIRQ1 */
+	{ 13, 0,  4, 0x0f-13 ,BCR_ILCRG}, 	/* SLOTIRQ2 */
+	{  2, 0,  0, 0x0f- 2 ,BCR_ILCRG}, 	/* SLOTIRQ1 */
 #endif
 };
 
@@ -81,5 +121,5 @@
 	ctrl_outw(0, BCR_ILCRF);
 	ctrl_outw(0, BCR_ILCRG);
 #endif
-	make_ipr_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map));
+	make_se770x_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map));
 }
diff --git a/arch/sh/boards/se/770x/led.c b/arch/sh/boards/se/770x/led.c
deleted file mode 100644
index d93dd83..0000000
--- a/arch/sh/boards/se/770x/led.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * linux/arch/sh/boards/se/770x/led.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Solution Engine specific LED code.
- */
-
-#include <linux/sched.h>
-#include <asm/se.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_se(void)
-{
-	static unsigned int cnt = 0, period = 0;
-	volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-	static unsigned bit = 0, up = 1;
-
-	cnt += 1;
-	if (cnt < period) {
-		return;
-	}
-
-	cnt = 0;
-
-	/* Go through the points (roughly!):
-	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-	 */
-	period = 110 - ( (300<<FSHIFT)/
-			 ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-	if (up) {
-		if (bit == 7) {
-			bit--;
-			up=0;
-		} else {
-			bit ++;
-		}
-	} else {
-		if (bit == 0) {
-			bit++;
-			up=1;
-		} else {
-			bit--;
-		}
-	}
-	*p = 1<<(bit+8);
-
-}
diff --git a/arch/sh/boards/se/770x/setup.c b/arch/sh/boards/se/770x/setup.c
index a1d51d5..45cbc36 100644
--- a/arch/sh/boards/se/770x/setup.c
+++ b/arch/sh/boards/se/770x/setup.c
@@ -1,5 +1,4 @@
-/* $Id: setup.c,v 1.1.2.4 2002/03/02 21:57:07 lethal Exp $
- *
+/*
  * linux/arch/sh/boards/se/770x/setup.c
  *
  * Copyright (C) 2000  Kazumoto Kojima
@@ -8,12 +7,12 @@
  *
  */
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/machvec.h>
 #include <asm/se.h>
 #include <asm/io.h>
 #include <asm/smc37c93x.h>
 
-void heartbeat_se(void);
 void init_se_IRQ(void);
 
 /*
@@ -36,11 +35,6 @@
 	smsc_config(ACTIVATE_INDEX, 0x01);
 	smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
 
-	/* IDE1 */
-	smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
-	smsc_config(ACTIVATE_INDEX, 0x01);
-	smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
-
 	/* AUXIO (GPIO): to use IDE1 */
 	smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
 	smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
@@ -69,6 +63,36 @@
 	outb_p(CONFIG_EXIT, CONFIG_PORT);
 }
 
+static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
+
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= PA_LED,
+		.end	= PA_LED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.dev	= {
+		.platform_data	= heartbeat_bit_pos,
+	},
+	.num_resources	= ARRAY_SIZE(heartbeat_resources),
+	.resource	= heartbeat_resources,
+};
+
+static struct platform_device *se_devices[] __initdata = {
+	&heartbeat_device,
+};
+
+static int __init se_devices_setup(void)
+{
+	return platform_add_devices(se_devices, ARRAY_SIZE(se_devices));
+}
+__initcall(se_devices_setup);
+
 /*
  * The Machine Vector
  */
@@ -107,8 +131,5 @@
 	.mv_outsl		= se_outsl,
 
 	.mv_init_irq		= init_se_IRQ,
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat		= heartbeat_se,
-#endif
 };
 ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7751/Makefile b/arch/sh/boards/se/7751/Makefile
index 188900c..dbc29f3 100644
--- a/arch/sh/boards/se/7751/Makefile
+++ b/arch/sh/boards/se/7751/Makefile
@@ -5,4 +5,3 @@
 obj-y	 := setup.o io.o irq.o
 
 obj-$(CONFIG_PCI) += pci.o
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7751/led.c b/arch/sh/boards/se/7751/led.c
deleted file mode 100644
index de4194d..0000000
--- a/arch/sh/boards/se/7751/led.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * linux/arch/sh/boards/se/7751/led.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains Solution Engine specific LED code.
- */
-#include <linux/sched.h>
-#include <asm/se7751.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_7751se(void)
-{
-	static unsigned int cnt = 0, period = 0;
-	volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-	static unsigned bit = 0, up = 1;
-
-	cnt += 1;
-	if (cnt < period) {
-		return;
-	}
-
-	cnt = 0;
-
-	/* Go through the points (roughly!):
-	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-	 */
-	period = 110 - ( (300<<FSHIFT)/
-			 ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-	if (up) {
-		if (bit == 7) {
-			bit--;
-			up=0;
-		} else {
-			bit ++;
-		}
-	} else {
-		if (bit == 0) {
-			bit++;
-			up=1;
-		} else {
-			bit--;
-		}
-	}
-	*p = 1<<(bit+8);
-
-}
diff --git a/arch/sh/boards/se/7751/setup.c b/arch/sh/boards/se/7751/setup.c
index f7e1dd3..e3feae6 100644
--- a/arch/sh/boards/se/7751/setup.c
+++ b/arch/sh/boards/se/7751/setup.c
@@ -9,11 +9,11 @@
  * Ian da Silva and Jeremy Siegel, 2001.
  */
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/machvec.h>
 #include <asm/se7751.h>
 #include <asm/io.h>
 
-void heartbeat_7751se(void);
 void init_7751se_IRQ(void);
 
 #ifdef CONFIG_SH_KGDB
@@ -161,11 +161,40 @@
 }
 #endif /* CONFIG_SH_KGDB */
 
+static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
+
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= PA_LED,
+		.end	= PA_LED + ARRAY_SIZE(heartbeat_bit_pos) - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.dev	= {
+		.platform_data	= heartbeat_bit_pos,
+	},
+	.num_resources	= ARRAY_SIZE(heartbeat_resources),
+	.resource	= heartbeat_resources,
+};
+
+static struct platform_device *se7751_devices[] __initdata = {
+	&smc91x_device,
+	&heartbeat_device,
+};
+
+static int __init se7751_devices_setup(void)
+{
+	return platform_add_devices(se7751_devices, ARRAY_SIZE(se7751_devices));
+}
+__initcall(se7751_devices_setup);
 
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_7751se __initmv = {
 	.mv_name		= "7751 SolutionEngine",
 	.mv_setup		= sh7751se_setup,
@@ -189,8 +218,5 @@
 	.mv_outsl		= sh7751se_outsl,
 
 	.mv_init_irq		= init_7751se_IRQ,
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat		= heartbeat_7751se,
-#endif
 };
 ALIAS_MV(7751se)
diff --git a/arch/sh/boards/sh03/Makefile b/arch/sh/boards/sh03/Makefile
index 321be50..400306a 100644
--- a/arch/sh/boards/sh03/Makefile
+++ b/arch/sh/boards/sh03/Makefile
@@ -3,4 +3,3 @@
 #
 
 obj-y	 := setup.o rtc.o
-obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/sh03/led.c b/arch/sh/boards/sh03/led.c
deleted file mode 100644
index d38562a..0000000
--- a/arch/sh/boards/sh03/led.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * linux/arch/sh/boards/sh03/led.c
- *
- * Copyright (C) 2004  Saito.K Interface Corporation.
- *
- * This file contains Interface CTP/PCI-SH03 specific LED code.
- */
-
-#include <linux/sched.h>
-
-/* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void heartbeat_sh03(void)
-{
-	static unsigned int cnt = 0, period = 0;
-	volatile unsigned char* p = (volatile unsigned char*)0xa0800000;
-	static unsigned bit = 0, up = 1;
-
-	cnt += 1;
-	if (cnt < period) {
-		return;
-	}
-
-	cnt = 0;
-
-	/* Go through the points (roughly!):
-	 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-	 */
-	period = 110 - ( (300<<FSHIFT)/
-			 ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-	if (up) {
-		if (bit == 7) {
-			bit--;
-			up=0;
-		} else {
-			bit ++;
-		}
-	} else {
-		if (bit == 0) {
-			bit++;
-			up=1;
-		} else {
-			bit--;
-		}
-	}
-	*p = 1<<bit;
-
-}
diff --git a/arch/sh/boards/sh03/setup.c b/arch/sh/boards/sh03/setup.c
index 5ad1e19..c069c44 100644
--- a/arch/sh/boards/sh03/setup.c
+++ b/arch/sh/boards/sh03/setup.c
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/rtc.h>
 #include <asm/sh03/io.h>
@@ -48,15 +49,36 @@
 	board_time_init = sh03_time_init;
 }
 
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start	= 0xa0800000,
+		.end	= 0xa0800000 + 8 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(heartbeat_resources),
+	.resource	= heartbeat_resources,
+};
+
+static struct platform_device *sh03_devices[] __initdata = {
+	&heartbeat_device,
+};
+
+static int __init sh03_devices_setup(void)
+{
+	return platform_add_devices(sh03_devices, ARRAY_SIZE(sh03_devices));
+}
+__initcall(sh03_devices_setup);
+
 struct sh_machine_vector mv_sh03 __initmv = {
 	.mv_name		= "Interface (CTP/PCI-SH03)",
 	.mv_setup		= sh03_setup,
 	.mv_nr_irqs		= 48,
 	.mv_ioport_map		= sh03_ioport_map,
 	.mv_init_irq		= init_sh03_IRQ,
-
-#ifdef CONFIG_HEARTBEAT
-	.mv_heartbeat		= heartbeat_sh03,
-#endif
 };
 ALIAS_MV(sh03)
diff --git a/arch/sh/boards/shmin/setup.c b/arch/sh/boards/shmin/setup.c
index a31a1d1..4a9df4a 100644
--- a/arch/sh/boards/shmin/setup.c
+++ b/arch/sh/boards/shmin/setup.c
@@ -12,12 +12,22 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 
-#define PFC_PHCR	0xa400010e
+#define PFC_PHCR	0xa400010eUL
+#define INTC_ICR1	0xa4000010UL
+#define INTC_IPRC	0xa4000016UL
+
+static struct ipr_data shmin_ipr_map[] = {
+	{ .irq=32, .addr=INTC_IPRC, .shift= 0, .priority=0 },
+	{ .irq=33, .addr=INTC_IPRC, .shift= 4, .priority=0 },
+	{ .irq=34, .addr=INTC_IPRC, .shift= 8, .priority=8 },
+	{ .irq=35, .addr=INTC_IPRC, .shift=12, .priority=0 },
+};
 
 static void __init init_shmin_irq(void)
 {
 	ctrl_outw(0x2a00, PFC_PHCR);	// IRQ0-3=IRQ
 	ctrl_outw(0x0aaa, INTC_ICR1);	// IRQ0-3=IRQ-mode,Low-active.
+	make_ipr_irq(shmin_ipr_map, ARRAY_SIZE(shmin_ipr_map));
 }
 
 static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size)
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
index f7ea700..70f1290 100644
--- a/arch/sh/cchips/voyagergx/irq.c
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -28,21 +28,21 @@
 	unsigned long val;
 	unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
 
-    	pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
-        val = inl(VOYAGER_INT_MASK);
-        val &= ~mask;
-        outl(val, VOYAGER_INT_MASK);
+	pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+	val = readl((void __iomem *)VOYAGER_INT_MASK);
+	val &= ~mask;
+	writel(val, (void __iomem *)VOYAGER_INT_MASK);
 }
 
 static void enable_voyagergx_irq(unsigned int irq)
 {
-        unsigned long val;
-        unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
+	unsigned long val;
+	unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
 
-        pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
-        val = inl(VOYAGER_INT_MASK);
-        val |= mask;
-        outl(val, VOYAGER_INT_MASK);
+	pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+	val = readl((void __iomem *)VOYAGER_INT_MASK);
+	val |= mask;
+	writel(val, (void __iomem *)VOYAGER_INT_MASK);
 }
 
 static void mask_and_ack_voyagergx(unsigned int irq)
@@ -68,20 +68,20 @@
 }
 
 static struct hw_interrupt_type voyagergx_irq_type = {
-	.typename = "VOYAGERGX-IRQ",
-	.startup = startup_voyagergx_irq,
-	.shutdown = shutdown_voyagergx_irq,
-	.enable = enable_voyagergx_irq,
-	.disable = disable_voyagergx_irq,
-	.ack = mask_and_ack_voyagergx,
-	.end = end_voyagergx_irq,
+	.typename	= "VOYAGERGX-IRQ",
+	.startup	= startup_voyagergx_irq,
+	.shutdown	= shutdown_voyagergx_irq,
+	.enable		= enable_voyagergx_irq,
+	.disable	= disable_voyagergx_irq,
+	.ack		= mask_and_ack_voyagergx,
+	.end		= end_voyagergx_irq,
 };
 
 static irqreturn_t voyagergx_interrupt(int irq, void *dev_id)
 {
 	printk(KERN_INFO
 	       "VoyagerGX: spurious interrupt, status: 0x%x\n",
-	       		inl(INT_STATUS));
+			(unsigned int)readl((void __iomem *)INT_STATUS));
 	return IRQ_HANDLED;
 }
 
@@ -93,13 +93,13 @@
 void voyagergx_register_irq_demux(int irq,
 		int (*demux)(int irq, void *dev), void *dev)
 {
-    	voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux;
-    	voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev;
+	voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux;
+	voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev;
 }
 
 void voyagergx_unregister_irq_demux(int irq)
 {
-    	voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0;
+	voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0;
 }
 
 int voyagergx_irq_demux(int irq)
@@ -107,31 +107,25 @@
 
 	if (irq == IRQ_VOYAGER ) {
 		unsigned long i = 0, bit __attribute__ ((unused));
-		unsigned long val  = inl(INT_STATUS);
-#if 1
-		if ( val & ( 1 << 1 )){
+		unsigned long val  = readl((void __iomem *)INT_STATUS);
+
+		if (val & (1 << 1))
 			i = 1;
-		} else if ( val & ( 1 << 2 )){
+		else if (val & (1 << 2))
 			i = 2;
-		} else if ( val & ( 1 << 6 )){
+		else if (val & (1 << 6))
 			i = 6;
-		} else if( val & ( 1 << 10 )){
+		else if (val & (1 << 10))
 			i = 10;
-		} else if( val & ( 1 << 11 )){
+		else if (val & (1 << 11))
 			i = 11;
-		} else if( val & ( 1 << 12 )){
+		else if (val & (1 << 12))
 			i = 12;
-		} else if( val & ( 1 << 17 )){
+		else if (val & (1 << 17))
 			i = 17;
-		} else {
+		else
 			printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
-		}
-		pr_debug("voyagergx_irq_demux %ld\n", i);
-#else
-		for (bit = 1, i = 0 ; i < VOYAGER_IRQ_NUM ; bit <<= 1, i++)
-			if (val & bit)
-				break;
-#endif
+		pr_debug("voyagergx_irq_demux %d \n", i);
     	    	if (i < VOYAGER_IRQ_NUM) {
 			irq = VOYAGER_IRQ_BASE + i;
     	    		if (voyagergx_demux[i].func != 0)
diff --git a/arch/sh/cchips/voyagergx/setup.c b/arch/sh/cchips/voyagergx/setup.c
index 66b2fed..33f0302 100644
--- a/arch/sh/cchips/voyagergx/setup.c
+++ b/arch/sh/cchips/voyagergx/setup.c
@@ -19,7 +19,7 @@
 {
 	unsigned long val;
 
-	val = inl(DRAM_CTRL);
+	val = readl((void __iomem *)DRAM_CTRL);
 	val |= (DRAM_CTRL_CPU_COLUMN_SIZE_256	|
 		DRAM_CTRL_CPU_ACTIVE_PRECHARGE	|
 		DRAM_CTRL_CPU_RESET		|
@@ -29,7 +29,7 @@
 		DRAM_CTRL_ACTIVE_PRECHARGE	|
 		DRAM_CTRL_RESET			|
 		DRAM_CTRL_REMAIN_ACTIVE);
-	outl(val, DRAM_CTRL);
+	writel(val, (void __iomem *)DRAM_CTRL);
 
 	return 0;
 }
diff --git a/arch/sh/configs/rts7751r2d_defconfig b/arch/sh/configs/rts7751r2d_defconfig
index 099e98f..db6a02d 100644
--- a/arch/sh/configs/rts7751r2d_defconfig
+++ b/arch/sh/configs/rts7751r2d_defconfig
@@ -1,15 +1,21 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct  3 11:38:36 2006
+# Linux kernel version: 2.6.20
+# Thu Feb 15 17:17:29 2007
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -33,8 +39,8 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -97,10 +103,8 @@
 # CONFIG_SH_73180_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
 # CONFIG_SH_SATURN is not set
 # CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_BIGSUR is not set
 # CONFIG_SH_MPC1211 is not set
 # CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
@@ -113,6 +117,9 @@
 # CONFIG_SH_LANDISK is not set
 # CONFIG_SH_TITAN is not set
 # CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
+# CONFIG_SH_ASDAP310 is not set
 # CONFIG_SH_UNKNOWN is not set
 
 #
@@ -124,6 +131,12 @@
 # SH-2 Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
 
 #
 # SH-3 Processor Support
@@ -159,12 +172,14 @@
 #
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
 
 #
 # SH4AL-DSP Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
@@ -174,6 +189,9 @@
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_VSYSCALL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -183,6 +201,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 
 #
 # Cache configuration
@@ -195,11 +214,14 @@
 # Processor features
 #
 CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_SH_FPU=y
 # CONFIG_SH_DSP is not set
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
 
 #
 # Timer support
@@ -210,6 +232,8 @@
 # RTS7751R2D options
 #
 CONFIG_RTS7751R2D_REV11=y
+CONFIG_SH_TIMER_IRQ=16
+# CONFIG_NO_IDLE_HZ is not set
 CONFIG_SH_PCLK_FREQ=60000000
 
 #
@@ -232,10 +256,16 @@
 CONFIG_HEARTBEAT=y
 
 #
+# Additional SuperH Device Drivers
+#
+# CONFIG_PUSH_SWITCH is not set
+
+#
 # Kernel features
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 # CONFIG_KEXEC is not set
@@ -251,7 +281,7 @@
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="mem=64M console=ttySC0,115200 root=/dev/hda1"
+CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
 
 #
 # Bus options
@@ -260,7 +290,6 @@
 CONFIG_SH_PCIDMA_NONCOHERENT=y
 CONFIG_PCI_AUTO=y
 CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -302,6 +331,7 @@
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -319,11 +349,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -380,7 +412,7 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -422,44 +454,145 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-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_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_IDE_ARM is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
+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
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# 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
+# CONFIG_SCSI_SAS_LIBSAS 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_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP 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_STEX 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_QLA_ISCSI 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
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
-# CONFIG_ATA is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_PLATFORM=y
 
 #
 # Multi-device support (RAID and LVM)
@@ -470,6 +603,9 @@
 # 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
@@ -540,6 +676,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -559,14 +696,17 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -611,6 +751,7 @@
 # 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
@@ -646,14 +787,23 @@
 #
 # Serial drivers
 #
-# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE 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
 
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=1
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 
@@ -671,10 +821,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -682,7 +828,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -698,6 +843,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -706,18 +852,14 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -759,7 +901,6 @@
 CONFIG_SND_MPU401_UART=m
 CONFIG_SND_OPL3_LIB=m
 CONFIG_SND_AC97_CODEC=m
-CONFIG_SND_AC97_BUS=m
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
@@ -782,6 +923,18 @@
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
 # CONFIG_SND_ENS1370 is not set
@@ -801,6 +954,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
@@ -813,17 +967,22 @@
 # CONFIG_SND_AC97_POWER_SAVE is not set
 
 #
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=m
-# CONFIG_OSS_OBSOLETE_DRIVER is not set
+# CONFIG_OBSOLETE_OSS is not set
 # CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ICH 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_AC97_BUS=m
 
 #
 # USB support
@@ -872,7 +1031,29 @@
 #
 # Real Time Clock
 #
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
 
 #
 # DMA Engine support
@@ -888,16 +1069,26 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 CONFIG_MINIX_FS=y
 # CONFIG_ROMFS_FS is not set
@@ -932,7 +1123,8 @@
 CONFIG_PROC_KCORE=y
 CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
@@ -1018,6 +1210,11 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Profiling support
 #
 CONFIG_PROFILING=y
@@ -1026,16 +1223,20 @@
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_SH_STANDARD_BIOS is not set
-# CONFIG_EARLY_SCIF_CONSOLE is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
+CONFIG_EARLY_PRINTK=y
 # CONFIG_KGDB is not set
 
 #
@@ -1052,8 +1253,11 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/sh/configs/se7750_defconfig b/arch/sh/configs/se7750_defconfig
index 5d357d6..4e6e77f 100644
--- a/arch/sh/configs/se7750_defconfig
+++ b/arch/sh/configs/se7750_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct  3 11:49:01 2006
+# Linux kernel version: 2.6.20-rc2
+# Thu Dec 28 23:15:49 2006
 #
 CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -10,6 +10,11 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -35,6 +40,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -116,6 +122,8 @@
 # CONFIG_SH_LANDISK is not set
 # CONFIG_SH_TITAN is not set
 # CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
 # CONFIG_SH_UNKNOWN is not set
 
 #
@@ -127,6 +135,12 @@
 # SH-2 Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
 
 #
 # SH-3 Processor Support
@@ -162,12 +176,14 @@
 #
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
 
 #
 # SH4AL-DSP Processor Support
 #
 # CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
 
 #
 # Memory management options
@@ -177,6 +193,9 @@
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x02000000
 CONFIG_VSYSCALL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -202,17 +221,22 @@
 # Processor features
 #
 CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_SH_FPU=y
 # CONFIG_SH_DSP is not set
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
 
 #
 # Timer support
 #
 CONFIG_SH_TMU=y
-CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_SH_TIMER_IRQ=16
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_SH_PCLK_FREQ=33333333
 
 #
 # CPU Frequency scaling
@@ -231,10 +255,16 @@
 CONFIG_HEARTBEAT=y
 
 #
+# Additional SuperH Device Drivers
+#
+# CONFIG_PUSH_SWITCH is not set
+
+#
 # Kernel features
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 # CONFIG_KEXEC is not set
@@ -249,8 +279,7 @@
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 # CONFIG_UBC_WAKEUP is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttySC1,38400 root=/dev/nfs ip=bootp"
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Bus options
@@ -313,11 +342,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -480,16 +511,79 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+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 is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA 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 is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# 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
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# 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
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -633,17 +727,12 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -659,6 +748,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -667,18 +757,14 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -758,14 +844,20 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -814,7 +906,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -875,6 +966,11 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -882,14 +978,16 @@
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_KGDB is not set
@@ -908,6 +1006,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -915,3 +1014,4 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile
index bf18dbf..6cb9267 100644
--- a/arch/sh/drivers/Makefile
+++ b/arch/sh/drivers/Makefile
@@ -6,3 +6,4 @@
 obj-$(CONFIG_SH_DMA)		+= dma/
 obj-$(CONFIG_SUPERHYWAY)	+= superhyway/
 obj-$(CONFIG_PUSH_SWITCH)	+= push-switch.o
+obj-$(CONFIG_HEARTBEAT)		+= heartbeat.o
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index f63721e..06ed060 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -19,34 +19,26 @@
 #include <asm/io.h>
 #include "dma-sh.h"
 
-
-
-#ifdef CONFIG_CPU_SH4
-static struct ipr_data dmae_ipr_map[] = {
-	{ DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-};
+static int dmte_irq_map[] = {
+	DMTE0_IRQ,
+	DMTE1_IRQ,
+	DMTE2_IRQ,
+	DMTE3_IRQ,
+#if defined(CONFIG_CPU_SUBTYPE_SH7751R) ||	\
+    defined(CONFIG_CPU_SUBTYPE_SH7760)  ||	\
+    defined(CONFIG_CPU_SUBTYPE_SH7780)
+	DMTE4_IRQ,
+	DMTE5_IRQ,
+	DMTE6_IRQ,
+	DMTE7_IRQ,    
 #endif
-static struct ipr_data dmte_ipr_map[] = {
-	/*
-	 * Normally we could just do DMTE0_IRQ + chan outright, though in the
-	 * case of the 7751R, the DMTE IRQs for channels > 4 start right above
-	 * the SCIF
-	 */
-	{ DMTE0_IRQ + 0, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-	{ DMTE0_IRQ + 1, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-	{ DMTE0_IRQ + 2, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-	{ DMTE0_IRQ + 3, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-	{ DMTE4_IRQ + 0, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-	{ DMTE4_IRQ + 1, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-	{ DMTE4_IRQ + 2, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
-	{ DMTE4_IRQ + 3, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY },
 };
 
 static inline unsigned int get_dmte_irq(unsigned int chan)
 {
 	unsigned int irq = 0;
-	if (chan < ARRAY_SIZE(dmte_ipr_map))
-		irq = dmte_ipr_map[chan].irq;
+	if (chan < ARRAY_SIZE(dmte_irq_map))
+		irq = dmte_irq_map[chan];
 	return irq;
 }
 
@@ -103,7 +95,7 @@
 	free_irq(get_dmte_irq(chan->chan), chan);
 }
 
-static void
+static int
 sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
 {
 	if (!chcr)
@@ -119,6 +111,7 @@
 	ctrl_outl(chcr, CHCR[chan->chan]);
 
 	chan->flags |= DMA_CONFIGURED;
+	return 0;
 }
 
 static void sh_dmac_enable_dma(struct dma_channel *chan)
@@ -262,17 +255,11 @@
 	int i;
 
 #ifdef CONFIG_CPU_SH4
-	make_ipr_irq(dmae_ipr_map, ARRAY_SIZE(dmae_ipr_map));
 	i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0);
 	if (unlikely(i < 0))
 		return i;
 #endif
 
-	i = info->nr_channels;
-	if (i > ARRAY_SIZE(dmte_ipr_map))
-		i = ARRAY_SIZE(dmte_ipr_map);
-	make_ipr_irq(dmte_ipr_map, i);
-
 	/*
 	 * Initialize DMAOR, and clean up any error flags that may have
 	 * been set.
diff --git a/arch/sh/drivers/heartbeat.c b/arch/sh/drivers/heartbeat.c
new file mode 100644
index 0000000..bc59cb6
--- /dev/null
+++ b/arch/sh/drivers/heartbeat.c
@@ -0,0 +1,132 @@
+/*
+ * Generic heartbeat driver for regular LED banks
+ *
+ * Copyright (C) 2007  Paul Mundt
+ *
+ * Most SH reference boards include a number of individual LEDs that can
+ * be independently controlled (either via a pre-defined hardware
+ * function or via the LED class, if desired -- the hardware tends to
+ * encapsulate some of the same "triggers" that the LED class supports,
+ * so there's not too much value in it).
+ *
+ * Additionally, most of these boards also have a LED bank that we've
+ * traditionally used for strobing the load average. This use case is
+ * handled by this driver, rather than giving each LED bit position its
+ * own struct device.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/io.h>
+
+#define DRV_NAME "heartbeat"
+#define DRV_VERSION "0.1.0"
+
+struct heartbeat_data {
+	void __iomem *base;
+	unsigned char bit_pos[8];
+	struct timer_list timer;
+};
+
+static void heartbeat_timer(unsigned long data)
+{
+	struct heartbeat_data *hd = (struct heartbeat_data *)data;
+	static unsigned bit = 0, up = 1;
+
+	ctrl_outw(1 << hd->bit_pos[bit], (unsigned long)hd->base);
+	if (up)
+		if (bit == (ARRAY_SIZE(hd->bit_pos) - 1)) {
+			bit--;
+			up = 0;
+		} else
+			bit++;
+	else if (bit == 0)
+		up = 1;
+	else
+		bit--;
+
+	mod_timer(&hd->timer, jiffies + (110 - ((300 << FSHIFT) /
+			((avenrun[0] / 5) + (3 << FSHIFT)))));
+}
+
+static int heartbeat_drv_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct heartbeat_data *hd;
+
+	if (unlikely(pdev->num_resources != 1)) {
+		dev_err(&pdev->dev, "invalid number of resources\n");
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(res == NULL)) {
+		dev_err(&pdev->dev, "invalid resource\n");
+		return -EINVAL;
+	}
+
+	hd = kmalloc(sizeof(struct heartbeat_data), GFP_KERNEL);
+	if (unlikely(!hd))
+		return -ENOMEM;
+
+	if (pdev->dev.platform_data) {
+		memcpy(hd->bit_pos, pdev->dev.platform_data,
+		       ARRAY_SIZE(hd->bit_pos));
+	} else {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(hd->bit_pos); i++)
+			hd->bit_pos[i] = i;
+	}
+
+	hd->base = (void __iomem *)res->start;
+
+	setup_timer(&hd->timer, heartbeat_timer, (unsigned long)hd);
+	platform_set_drvdata(pdev, hd);
+
+	return mod_timer(&hd->timer, jiffies + 1);
+}
+
+static int heartbeat_drv_remove(struct platform_device *pdev)
+{
+	struct heartbeat_data *hd = platform_get_drvdata(pdev);
+
+	del_timer_sync(&hd->timer);
+
+	platform_set_drvdata(pdev, NULL);
+
+	kfree(hd);
+
+	return 0;
+}
+
+static struct platform_driver heartbeat_driver = {
+	.probe		= heartbeat_drv_probe,
+	.remove		= heartbeat_drv_remove,
+	.driver		= {
+		.name	= DRV_NAME,
+	},
+};
+
+static int __init heartbeat_init(void)
+{
+	printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
+	return platform_driver_register(&heartbeat_driver);
+}
+
+static void __exit heartbeat_exit(void)
+{
+	platform_driver_unregister(&heartbeat_driver);
+}
+module_init(heartbeat_init);
+module_exit(heartbeat_exit);
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Paul Mundt");
+MODULE_LICENSE("GPLv2");
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
index 9e00cb8..cc8d0d0 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -12,7 +12,6 @@
 obj-$(CONFIG_SH_DREAMCAST)		+= ops-dreamcast.o fixups-dreamcast.o \
 					   dma-dreamcast.o
 obj-$(CONFIG_SH_SECUREEDGE5410)		+= ops-snapgear.o
-obj-$(CONFIG_SH_BIGSUR)			+= ops-bigsur.o
 obj-$(CONFIG_SH_RTS7751R2D)		+= ops-rts7751r2d.o fixups-rts7751r2d.o
 obj-$(CONFIG_SH_SH03)			+= ops-sh03.o fixups-sh03.o
 obj-$(CONFIG_SH_R7780RP)		+= ops-r7780rp.o fixups-r7780rp.o
diff --git a/arch/sh/drivers/pci/ops-bigsur.c b/arch/sh/drivers/pci/ops-bigsur.c
deleted file mode 100644
index eb31be7..0000000
--- a/arch/sh/drivers/pci/ops-bigsur.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-bigsur.c
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- *
- * Ported to new API by Paul Mundt <lethal@linux-sh.org>.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * PCI initialization for the Hitachi Big Sur Evaluation Board
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-#include <asm/bigsur/bigsur.h>
-
-#define BIGSUR_PCI_IO	0x4000
-#define BIGSUR_PCI_MEM	0xfd000000
-
-static struct resource sh7751_io_resource = {
-	.name		= "SH7751 IO",
-	.start		= BIGSUR_PCI_IO,
-	.end		= BIGSUR_PCI_IO + (64*1024) - 1,
-	.flags		= IORESOURCE_IO,
-};
-
-static struct resource sh7751_mem_resource = {
-	.name		= "SH7751 mem",
-	.start		= BIGSUR_PCI_MEM,
-	.end		= BIGSUR_PCI_MEM + (64*1024*1024) - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-extern struct pci_ops sh7751_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
-	{ 0, }
-};
-
-static struct sh4_pci_address_map sh7751_pci_map = {
-	.window0	= {
-		.base	= SH7751_CS3_BASE_ADDR,
-		.size	= BIGSUR_LSR0_SIZE,
-	},
-
-	.window1	= {
-		.base	= SH7751_CS3_BASE_ADDR,
-		.size	= BIGSUR_LSR1_SIZE,
-	},
-};
-
-/*
- * Initialize the Big Sur PCI interface
- * Setup hardware to be Central Funtion
- * Copy the BSR regs to the PCI interface
- * Setup PCI windows into local RAM
- */
-int __init pcibios_init_platform(void)
-{
-	return sh7751_pcic_init(&sh7751_pci_map);
-}
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-	/*
-	 * The Big Sur can be used in a CPCI chassis, but the SH7751 PCI
-	 * interface is on the wrong end of the board so that it can also
-	 * support a V320 CPI interface chip...  Therefor the IRQ mapping is
-	 * somewhat use dependent... I'l assume a linear map for now, i.e.
-	 * INTA=slot0,pin0... INTD=slot3,pin0...
-	 */
-	int irq = (slot + pin-1) % 4 + BIGSUR_SH7751_PCI_IRQ_BASE;
-
-	PCIDBG(2, "PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n",
-	       slot, pin-1+'A', irq);
-
-	return irq;
-}
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index 85e1ee2..9ddff76 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -157,15 +157,6 @@
 		 PCIBIOS_MIN_IO, (64 << 10),
 		 SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO);
 
-	/*
-	 * XXX: For now, leave this board-specific. In the event we have other
-	 * boards that need to do similar work, this can be wrapped.
-	 */
-#ifdef CONFIG_SH_BIGSUR
-	bigsur_port_map(PCIBIOS_MIN_IO, (64 << 10),
-			SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO, 0);
-#endif
-
 	/* Make sure the MSB's of IO window are set to access PCI space
 	 * correctly */
 	word = PCIBIOS_MIN_IO & SH4_PCIIOBR_MASK;
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 99c7e52..ff30d7f 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -6,7 +6,8 @@
 
 obj-y	:= process.o signal.o traps.o irq.o \
 	ptrace.o setup.o time.o sys_sh.o semaphore.o \
-	io.o io_generic.o sh_ksyms.o syscalls.o
+	io.o io_generic.o sh_ksyms.o syscalls.o \
+	debugtraps.o
 
 obj-y				+= cpu/ timers/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
@@ -19,6 +20,5 @@
 obj-$(CONFIG_MODULES)		+= module.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
-obj-$(CONFIG_APM)		+= apm.o
 obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
diff --git a/arch/sh/kernel/apm.c b/arch/sh/kernel/apm.c
deleted file mode 100644
index 4f66f91..0000000
--- a/arch/sh/kernel/apm.c
+++ /dev/null
@@ -1,538 +0,0 @@
-/*
- * bios-less APM driver for hp680
- *
- * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
- *
- * based on ARM APM driver by
- *  Jamey Hicks <jamey@crl.dec.com>
- *
- * adapted from the APM BIOS driver for Linux by
- *  Stephen Rothwell (sfr@linuxcare.com)
- *
- * APM 1.2 Reference:
- *   Intel Corporation, Microsoft Corporation. Advanced Power Management
- *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
- *
- * [This document is available from Microsoft at:
- *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
- */
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
-#include <linux/apm_bios.h>
-#include <linux/pm.h>
-#include <linux/pm_legacy.h>
-#include <asm/apm.h>
-
-#define MODNAME "apm"
-
-/*
- * The apm_bios device is one of the misc char devices.
- * This is its minor number.
- */
-#define APM_MINOR_DEV			134
-
-/*
- * Maximum number of events stored
- */
-#define APM_MAX_EVENTS			16
-
-struct apm_queue {
-	unsigned int		event_head;
-	unsigned int		event_tail;
-	apm_event_t		events[APM_MAX_EVENTS];
-};
-
-/*
- * The per-file APM data
- */
-struct apm_user {
-	struct list_head	list;
-
-	unsigned int		suser: 1;
-	unsigned int		writer: 1;
-	unsigned int		reader: 1;
-
-	int			suspend_result;
-	unsigned int		suspend_state;
-#define SUSPEND_NONE	0		/* no suspend pending */
-#define SUSPEND_PENDING	1		/* suspend pending read */
-#define SUSPEND_READ	2		/* suspend read, pending ack */
-#define SUSPEND_ACKED	3		/* suspend acked */
-#define SUSPEND_DONE	4		/* suspend completed */
-
-	struct apm_queue	queue;
-};
-
-/*
- * Local variables
- */
-static int suspends_pending;
-
-static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-
-/*
- * This is a list of everyone who has opened /dev/apm_bios
- */
-static DECLARE_RWSEM(user_list_lock);
-static LIST_HEAD(apm_user_list);
-
-/*
- * kapmd info.  kapmd provides us a process context to handle
- * "APM" events within - specifically necessary if we're going
- * to be suspending the system.
- */
-static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
-static DECLARE_COMPLETION(kapmd_exit);
-static DEFINE_SPINLOCK(kapmd_queue_lock);
-static struct apm_queue kapmd_queue;
-
-int apm_suspended;
-EXPORT_SYMBOL(apm_suspended);
-
-/* Platform-specific apm_read_proc(). */
-int (*apm_get_info)(char *buf, char **start, off_t fpos, int length);
-EXPORT_SYMBOL(apm_get_info);
-
-/*
- * APM event queue management.
- */
-static inline int queue_empty(struct apm_queue *q)
-{
-	return q->event_head == q->event_tail;
-}
-
-static inline apm_event_t queue_get_event(struct apm_queue *q)
-{
-	q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
-	return q->events[q->event_tail];
-}
-
-static void queue_add_event(struct apm_queue *q, apm_event_t event)
-{
-	q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
-	if (q->event_head == q->event_tail) {
-		static int notified;
-
-		if (notified++ == 0)
-			printk(KERN_ERR "apm: an event queue overflowed\n");
-
-		q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
-	}
-	q->events[q->event_head] = event;
-}
-
-static void queue_event_one_user(struct apm_user *as, apm_event_t event)
-{
-	if (as->suser && as->writer) {
-		switch (event) {
-		case APM_SYS_SUSPEND:
-		case APM_USER_SUSPEND:
-			/*
-			 * If this user already has a suspend pending,
-			 * don't queue another one.
-			 */
-			if (as->suspend_state != SUSPEND_NONE)
-				return;
-
-			as->suspend_state = SUSPEND_PENDING;
-			suspends_pending++;
-			break;
-		}
-	}
-	queue_add_event(&as->queue, event);
-}
-
-static void queue_event(apm_event_t event, struct apm_user *sender)
-{
-	struct apm_user *as;
-
-	down_read(&user_list_lock);
-
-	list_for_each_entry(as, &apm_user_list, list)
-		if (as != sender && as->reader)
-			queue_event_one_user(as, event);
-
-	up_read(&user_list_lock);
-	wake_up_interruptible(&apm_waitqueue);
-}
-
-/**
- * apm_queue_event - queue an APM event for kapmd
- * @event: APM event
- *
- * Queue an APM event for kapmd to process and ultimately take the
- * appropriate action.  Only a subset of events are handled:
- *   %APM_LOW_BATTERY
- *   %APM_POWER_STATUS_CHANGE
- *   %APM_USER_SUSPEND
- *   %APM_SYS_SUSPEND
- *   %APM_CRITICAL_SUSPEND
- */
-void apm_queue_event(apm_event_t event)
-{
-	spin_lock_irq(&kapmd_queue_lock);
-	queue_add_event(&kapmd_queue, event);
-	spin_unlock_irq(&kapmd_queue_lock);
-
-	wake_up_interruptible(&kapmd_wait);
-}
-EXPORT_SYMBOL(apm_queue_event);
-
-static void apm_suspend(void)
-{
-	struct apm_user *as;
-	int err;
-
-	apm_suspended = 1;
-	err = pm_suspend(PM_SUSPEND_MEM);
-
-	/*
-	 * Anyone on the APM queues will think we're still suspended.
-	 * Send a message so everyone knows we're now awake again.
-	 */
-	queue_event(APM_NORMAL_RESUME, NULL);
-
-	/*
-	 * Finally, wake up anyone who is sleeping on the suspend.
-	 */
-	down_read(&user_list_lock);
-	list_for_each_entry(as, &apm_user_list, list) {
-		as->suspend_result = err;
-		as->suspend_state = SUSPEND_DONE;
-	}
-	up_read(&user_list_lock);
-
-	wake_up(&apm_suspend_waitqueue);
-	apm_suspended = 0;
-}
-
-static ssize_t apm_read(struct file *fp, char __user *buf,
-			size_t count, loff_t *ppos)
-{
-	struct apm_user *as = fp->private_data;
-	apm_event_t event;
-	int i = count, ret = 0;
-
-	if (count < sizeof(apm_event_t))
-		return -EINVAL;
-
-	if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
-		return -EAGAIN;
-
-	wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
-
-	while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
-		event = queue_get_event(&as->queue);
-
-		ret = -EFAULT;
-		if (copy_to_user(buf, &event, sizeof(event)))
-			break;
-
-		if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
-			as->suspend_state = SUSPEND_READ;
-
-		buf += sizeof(event);
-		i -= sizeof(event);
-	}
-
-	if (i < count)
-		ret = count - i;
-
-	return ret;
-}
-
-static unsigned int apm_poll(struct file *fp, poll_table * wait)
-{
-	struct apm_user *as = fp->private_data;
-
-	poll_wait(fp, &apm_waitqueue, wait);
-	return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
-}
-
-/*
- * apm_ioctl - handle APM ioctl
- *
- * APM_IOC_SUSPEND
- *   This IOCTL is overloaded, and performs two functions.  It is used to:
- *     - initiate a suspend
- *     - acknowledge a suspend read from /dev/apm_bios.
- *   Only when everyone who has opened /dev/apm_bios with write permission
- *   has acknowledge does the actual suspend happen.
- */
-static int
-apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
-{
-	struct apm_user *as = filp->private_data;
-	unsigned long flags;
-	int err = -EINVAL;
-
-	if (!as->suser || !as->writer)
-		return -EPERM;
-
-	switch (cmd) {
-	case APM_IOC_SUSPEND:
-		as->suspend_result = -EINTR;
-
-		if (as->suspend_state == SUSPEND_READ) {
-			/*
-			 * If we read a suspend command from /dev/apm_bios,
-			 * then the corresponding APM_IOC_SUSPEND ioctl is
-			 * interpreted as an acknowledge.
-			 */
-			as->suspend_state = SUSPEND_ACKED;
-			suspends_pending--;
-		} else {
-			/*
-			 * Otherwise it is a request to suspend the system.
-			 * Queue an event for all readers, and expect an
-			 * acknowledge from all writers who haven't already
-			 * acknowledged.
-			 */
-			queue_event(APM_USER_SUSPEND, as);
-		}
-
-		/*
-		 * If there are no further acknowledges required, suspend
-		 * the system.
-		 */
-		if (suspends_pending == 0)
-			apm_suspend();
-
-		/*
-		 * Wait for the suspend/resume to complete.  If there are
-		 * pending acknowledges, we wait here for them.
-		 *
-		 * Note that we need to ensure that the PM subsystem does
-		 * not kick us out of the wait when it suspends the threads.
-		 */
-		flags = current->flags;
-		current->flags |= PF_NOFREEZE;
-
-		/*
-		 * Note: do not allow a thread which is acking the suspend
-		 * to escape until the resume is complete.
-		 */
-		if (as->suspend_state == SUSPEND_ACKED)
-			wait_event(apm_suspend_waitqueue,
-					 as->suspend_state == SUSPEND_DONE);
-		else
-			wait_event_interruptible(apm_suspend_waitqueue,
-					 as->suspend_state == SUSPEND_DONE);
-
-		current->flags = flags;
-		err = as->suspend_result;
-		as->suspend_state = SUSPEND_NONE;
-		break;
-	}
-
-	return err;
-}
-
-static int apm_release(struct inode * inode, struct file * filp)
-{
-	struct apm_user *as = filp->private_data;
-	filp->private_data = NULL;
-
-	down_write(&user_list_lock);
-	list_del(&as->list);
-	up_write(&user_list_lock);
-
-	/*
-	 * We are now unhooked from the chain.  As far as new
-	 * events are concerned, we no longer exist.  However, we
-	 * need to balance suspends_pending, which means the
-	 * possibility of sleeping.
-	 */
-	if (as->suspend_state != SUSPEND_NONE) {
-		suspends_pending -= 1;
-		if (suspends_pending == 0)
-			apm_suspend();
-	}
-
-	kfree(as);
-	return 0;
-}
-
-static int apm_open(struct inode * inode, struct file * filp)
-{
-	struct apm_user *as;
-
-	as = kzalloc(sizeof(*as), GFP_KERNEL);
-	if (as) {
-		/*
-		 * XXX - this is a tiny bit broken, when we consider BSD
-		 * process accounting. If the device is opened by root, we
-		 * instantly flag that we used superuser privs. Who knows,
-		 * we might close the device immediately without doing a
-		 * privileged operation -- cevans
-		 */
-		as->suser = capable(CAP_SYS_ADMIN);
-		as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
-		as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
-
-		down_write(&user_list_lock);
-		list_add(&as->list, &apm_user_list);
-		up_write(&user_list_lock);
-
-		filp->private_data = as;
-	}
-
-	return as ? 0 : -ENOMEM;
-}
-
-static struct file_operations apm_bios_fops = {
-	.owner		= THIS_MODULE,
-	.read		= apm_read,
-	.poll		= apm_poll,
-	.ioctl		= apm_ioctl,
-	.open		= apm_open,
-	.release	= apm_release,
-};
-
-static struct miscdevice apm_device = {
-	.minor		= APM_MINOR_DEV,
-	.name		= "apm_bios",
-	.fops		= &apm_bios_fops
-};
-
-
-#ifdef CONFIG_PROC_FS
-/*
- * Arguments, with symbols from linux/apm_bios.h.
- *
- *   0) Linux driver version (this will change if format changes)
- *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
- *   2) APM flags from APM Installation Check (0x00):
- *	bit 0: APM_16_BIT_SUPPORT
- *	bit 1: APM_32_BIT_SUPPORT
- *	bit 2: APM_IDLE_SLOWS_CLOCK
- *	bit 3: APM_BIOS_DISABLED
- *	bit 4: APM_BIOS_DISENGAGED
- *   3) AC line status
- *	0x00: Off-line
- *	0x01: On-line
- *	0x02: On backup power (BIOS >= 1.1 only)
- *	0xff: Unknown
- *   4) Battery status
- *	0x00: High
- *	0x01: Low
- *	0x02: Critical
- *	0x03: Charging
- *	0x04: Selected battery not present (BIOS >= 1.2 only)
- *	0xff: Unknown
- *   5) Battery flag
- *	bit 0: High
- *	bit 1: Low
- *	bit 2: Critical
- *	bit 3: Charging
- *	bit 7: No system battery
- *	0xff: Unknown
- *   6) Remaining battery life (percentage of charge):
- *	0-100: valid
- *	-1: Unknown
- *   7) Remaining battery life (time units):
- *	Number of remaining minutes or seconds
- *	-1: Unknown
- *   8) min = minutes; sec = seconds
- */
-static int apm_read_proc(char *buf, char **start, off_t fpos, int length)
-{
-	if (likely(apm_get_info))
-		return apm_get_info(buf, start, fpos, length);
-
-	return -EINVAL;
-}
-#endif
-
-static int kapmd(void *arg)
-{
-	daemonize("kapmd");
-	current->flags |= PF_NOFREEZE;
-
-	do {
-		apm_event_t event;
-
-		wait_event_interruptible(kapmd_wait,
-				!queue_empty(&kapmd_queue) || !pm_active);
-
-		if (!pm_active)
-			break;
-
-		spin_lock_irq(&kapmd_queue_lock);
-		event = 0;
-		if (!queue_empty(&kapmd_queue))
-			event = queue_get_event(&kapmd_queue);
-		spin_unlock_irq(&kapmd_queue_lock);
-
-		switch (event) {
-		case 0:
-			break;
-
-		case APM_LOW_BATTERY:
-		case APM_POWER_STATUS_CHANGE:
-			queue_event(event, NULL);
-			break;
-
-		case APM_USER_SUSPEND:
-		case APM_SYS_SUSPEND:
-			queue_event(event, NULL);
-			if (suspends_pending == 0)
-				apm_suspend();
-			break;
-
-		case APM_CRITICAL_SUSPEND:
-			apm_suspend();
-			break;
-		}
-	} while (1);
-
-	complete_and_exit(&kapmd_exit, 0);
-}
-
-static int __init apm_init(void)
-{
-	int ret;
-
-	pm_active = 1;
-
-	ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
-	if (unlikely(ret < 0)) {
-		pm_active = 0;
-		return ret;
-	}
-
-	create_proc_info_entry("apm", 0, NULL, apm_read_proc);
-
-	ret = misc_register(&apm_device);
-	if (unlikely(ret != 0)) {
-		remove_proc_entry("apm", NULL);
-
-		pm_active = 0;
-		wake_up(&kapmd_wait);
-		wait_for_completion(&kapmd_exit);
-	}
-
-	return ret;
-}
-
-static void __exit apm_exit(void)
-{
-	misc_deregister(&apm_device);
-	remove_proc_entry("apm", NULL);
-
-	pm_active = 0;
-	wake_up(&kapmd_wait);
-	wait_for_completion(&kapmd_exit);
-}
-
-module_init(apm_init);
-module_exit(apm_exit);
-
-MODULE_AUTHOR("Stephen Rothwell, Andriy Skulysh");
-MODULE_DESCRIPTION("Advanced Power Management");
-MODULE_LICENSE("GPL");
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 4812176..4b339a6 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -3,7 +3,7 @@
  *
  * CPU init code
  *
- * Copyright (C) 2002, 2003  Paul Mundt
+ * Copyright (C) 2002 - 2006  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -12,6 +12,8 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/mmu_context.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -46,7 +48,7 @@
 {
 	unsigned long ccr, flags;
 
-	if (cpu_data->type == CPU_SH_NONE)
+	if (current_cpu_data.type == CPU_SH_NONE)
 		panic("Unknown CPU");
 
 	jump_to_P2();
@@ -66,7 +68,7 @@
 	if (ccr & CCR_CACHE_ENABLE) {
 		unsigned long ways, waysize, addrstart;
 
-		waysize = cpu_data->dcache.sets;
+		waysize = current_cpu_data.dcache.sets;
 
 #ifdef CCR_CACHE_ORA
 		/*
@@ -77,7 +79,7 @@
 			waysize >>= 1;
 #endif
 
-		waysize <<= cpu_data->dcache.entry_shift;
+		waysize <<= current_cpu_data.dcache.entry_shift;
 
 #ifdef CCR_CACHE_EMODE
 		/* If EMODE is not set, we only have 1 way to flush. */
@@ -85,7 +87,7 @@
 			ways = 1;
 		else
 #endif
-			ways = cpu_data->dcache.ways;
+			ways = current_cpu_data.dcache.ways;
 
 		addrstart = CACHE_OC_ADDRESS_ARRAY;
 		do {
@@ -93,10 +95,10 @@
 
 			for (addr = addrstart;
 			     addr < addrstart + waysize;
-			     addr += cpu_data->dcache.linesz)
+			     addr += current_cpu_data.dcache.linesz)
 				ctrl_outl(0, addr);
 
-			addrstart += cpu_data->dcache.way_incr;
+			addrstart += current_cpu_data.dcache.way_incr;
 		} while (--ways);
 	}
 
@@ -108,7 +110,7 @@
 
 #ifdef CCR_CACHE_EMODE
 	/* Force EMODE if possible */
-	if (cpu_data->dcache.ways > 1)
+	if (current_cpu_data.dcache.ways > 1)
 		flags |= CCR_CACHE_EMODE;
 	else
 		flags &= ~CCR_CACHE_EMODE;
@@ -125,10 +127,10 @@
 #ifdef CONFIG_SH_OCRAM
 	/* Turn on OCRAM -- halve the OC */
 	flags |= CCR_CACHE_ORA;
-	cpu_data->dcache.sets >>= 1;
+	current_cpu_data.dcache.sets >>= 1;
 
-	cpu_data->dcache.way_size = cpu_data->dcache.sets *
-				    cpu_data->dcache.linesz;
+	current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets *
+				    current_cpu_data.dcache.linesz;
 #endif
 
 	ctrl_outl(flags, CCR);
@@ -170,7 +172,7 @@
 
 	/* If the DSP bit is still set, this CPU has a DSP */
 	if (sr & SR_DSP)
-		cpu_data->flags |= CPU_HAS_DSP;
+		current_cpu_data.flags |= CPU_HAS_DSP;
 
 	/* Now that we've determined the DSP status, clear the DSP bit. */
 	release_dsp();
@@ -202,22 +204,28 @@
 	cache_init();
 
 	shm_align_mask = max_t(unsigned long,
-			       cpu_data->dcache.way_size - 1,
+			       current_cpu_data.dcache.way_size - 1,
 			       PAGE_SIZE - 1);
 
 	/* Disable the FPU */
 	if (fpu_disabled) {
 		printk("FPU Disabled\n");
-		cpu_data->flags &= ~CPU_HAS_FPU;
+		current_cpu_data.flags &= ~CPU_HAS_FPU;
 		disable_fpu();
 	}
 
 	/* FPU initialization */
-	if ((cpu_data->flags & CPU_HAS_FPU)) {
+	if ((current_cpu_data.flags & CPU_HAS_FPU)) {
 		clear_thread_flag(TIF_USEDFPU);
 		clear_used_math();
 	}
 
+	/*
+	 * Initialize the per-CPU ASID cache very early, since the
+	 * TLB flushing routines depend on this being setup.
+	 */
+	current_cpu_data.asid_cache = NO_CONTEXT;
+
 #ifdef CONFIG_SH_DSP
 	/* Probe for DSP */
 	dsp_init();
@@ -225,7 +233,7 @@
 	/* Disable the DSP */
 	if (dsp_disabled) {
 		printk("DSP Disabled\n");
-		cpu_data->flags &= ~CPU_HAS_DSP;
+		current_cpu_data.flags &= ~CPU_HAS_DSP;
 		release_dsp();
 	}
 #endif
@@ -240,4 +248,3 @@
 	ubc_wakeup();
 #endif
 }
-
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 35eb575..210280b 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -43,16 +43,29 @@
 	.mask_ack	= disable_ipr_irq,
 };
 
+unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak));
+unsigned int map_ipridx_to_addr(int idx)
+{
+	return 0;
+}
+
 void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
 {
 	int i;
 
 	for (i = 0; i < nr_irqs; i++) {
 		unsigned int irq = table[i].irq;
-		table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
+
+		if (!irq)
+			irq = table[i].irq = i;
+
 		/* could the IPR index be mapped, if not we ignore this */
-		if (table[i].addr == 0)
-			continue;
+		if (!table[i].addr) {
+			table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
+			if (!table[i].addr)
+				continue;
+		}
+
 		disable_irq_nosync(irq);
 		set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
 				      handle_level_irq, "level");
diff --git a/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
index d0440b2..d2c1579 100644
--- a/arch/sh/kernel/cpu/sh2/clock-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
@@ -18,8 +18,8 @@
 #include <asm/freq.h>
 #include <asm/io.h>
 
-const static int pll1rate[]={1,2};
-const static int pfc_divisors[]={1,2,0,4};
+static const int pll1rate[] = {1,2};
+static const int pfc_divisors[] = {1,2,0,4};
 
 #if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2)
 #define PLL2 (4)
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index d51fa5e9..7f7d292 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -178,12 +178,10 @@
 8:	.long	do_exception_error
 	
 trap_entry:
-	/* verbose BUG trapa entry check */
-	mov	#0x3e,r8
-	cmp/ge	r8,r9
-	bf/s	1f
-	 add	#-0x10,r9
-	add	#0x10,r9
+	mov	#0x30,r8
+	cmp/ge	r8,r9		! vector 0x20-0x2f is systemcall
+	bt	1f
+	add	#-0x10,r9	! convert SH2 to SH3/4 ABI
 1:	
 	shll2	r9			! TRA
 	mov	#OFF_TRA,r8
@@ -206,7 +204,7 @@
 
 #if defined(CONFIG_SH_STANDARD_BIOS)
 	/* Unwind the stack and jmp to the debug entry */
-debug_kernel_fw:
+ENTRY(sh_bios_handler)
 	mov	r15,r0
 	add	#(22-4)*4-4,r0
 	ldc.l	@r0+,gbr
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c
index ba527d9..108e81b 100644
--- a/arch/sh/kernel/cpu/sh2/probe.c
+++ b/arch/sh/kernel/cpu/sh2/probe.c
@@ -18,27 +18,27 @@
 int __init detect_cpu_and_cache_system(void)
 {
 #if defined(CONFIG_CPU_SUBTYPE_SH7604)
-	cpu_data->type			= CPU_SH7604;
-	cpu_data->dcache.ways		= 4;
-	cpu_data->dcache.way_incr	= (1<<10);
-	cpu_data->dcache.sets		= 64;
-	cpu_data->dcache.entry_shift	= 4;
-	cpu_data->dcache.linesz		= L1_CACHE_BYTES;
-	cpu_data->dcache.flags		= 0;
+	current_cpu_data.type			= CPU_SH7604;
+	current_cpu_data.dcache.ways		= 4;
+	current_cpu_data.dcache.way_incr	= (1<<10);
+	current_cpu_data.dcache.sets		= 64;
+	current_cpu_data.dcache.entry_shift	= 4;
+	current_cpu_data.dcache.linesz		= L1_CACHE_BYTES;
+	current_cpu_data.dcache.flags		= 0;
 #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
-	cpu_data->type			= CPU_SH7619;
-	cpu_data->dcache.ways		= 4;
-	cpu_data->dcache.way_incr	= (1<<12);
-	cpu_data->dcache.sets		= 256;
-	cpu_data->dcache.entry_shift	= 4;
-	cpu_data->dcache.linesz		= L1_CACHE_BYTES;
-	cpu_data->dcache.flags		= 0;
+	current_cpu_data.type			= CPU_SH7619;
+	current_cpu_data.dcache.ways		= 4;
+	current_cpu_data.dcache.way_incr	= (1<<12);
+	current_cpu_data.dcache.sets		= 256;
+	current_cpu_data.dcache.entry_shift	= 4;
+	current_cpu_data.dcache.linesz		= L1_CACHE_BYTES;
+	current_cpu_data.dcache.flags		= 0;
 #endif
 	/*
 	 * SH-2 doesn't have separate caches
 	 */
-	cpu_data->dcache.flags |= SH_CACHE_COMBINED;
-	cpu_data->icache = cpu_data->dcache;
+	current_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
+	current_cpu_data.icache = current_cpu_data.dcache;
 
 	return 0;
 }
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index 79283e6..f83ff8a 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -52,42 +52,38 @@
 }
 __initcall(sh7619_devices_setup);
 
-#define INTC_IPRC      0xf8080000UL
-#define INTC_IPRD      0xf8080002UL
-
-#define CMI0_IRQ       86
-
-#define SCIF0_ERI_IRQ  88
-#define SCIF0_RXI_IRQ  89
-#define SCIF0_BRI_IRQ  90
-#define SCIF0_TXI_IRQ  91
-
-#define SCIF1_ERI_IRQ  92
-#define SCIF1_RXI_IRQ  93
-#define SCIF1_BRI_IRQ  94
-#define SCIF1_TXI_IRQ  95
-
-#define SCIF2_BRI_IRQ  96
-#define SCIF2_ERI_IRQ  97
-#define SCIF2_RXI_IRQ  98
-#define SCIF2_TXI_IRQ  99
-
 static struct ipr_data sh7619_ipr_map[] = {
-	{ CMI0_IRQ,      INTC_IPRC, 1, 2 },
-	{ SCIF0_ERI_IRQ, INTC_IPRD, 3, 3 },
-	{ SCIF0_RXI_IRQ, INTC_IPRD, 3, 3 },
-	{ SCIF0_BRI_IRQ, INTC_IPRD, 3, 3 },
-	{ SCIF0_TXI_IRQ, INTC_IPRD, 3, 3 },
-	{ SCIF1_ERI_IRQ, INTC_IPRD, 2, 3 },
-	{ SCIF1_RXI_IRQ, INTC_IPRD, 2, 3 },
-	{ SCIF1_BRI_IRQ, INTC_IPRD, 2, 3 },
-	{ SCIF1_TXI_IRQ, INTC_IPRD, 2, 3 },
-	{ SCIF2_ERI_IRQ, INTC_IPRD, 1, 3 },
-	{ SCIF2_RXI_IRQ, INTC_IPRD, 1, 3 },
-	{ SCIF2_BRI_IRQ, INTC_IPRD, 1, 3 },
-	{ SCIF2_TXI_IRQ, INTC_IPRD, 1, 3 },
+	{ 86, 0,  4, 2 },	/* CMI0 */
+	{ 88, 1, 12, 3 },	/* SCIF0_ERI */
+	{ 89, 1, 12, 3 },	/* SCIF0_RXI */
+	{ 90, 1, 12, 3 },	/* SCIF0_BRI */
+	{ 91, 1, 12, 3 },	/* SCIF0_TXI */
+	{ 92, 1,  8, 3 },	/* SCIF1_ERI */
+	{ 93, 1,  8, 3 },	/* SCIF1_RXI */
+	{ 94, 1,  8, 3 },	/* SCIF1_BRI */
+	{ 95, 1,  8, 3 },	/* SCIF1_TXI */
+	{ 96, 1,  4, 3 },	/* SCIF2_ERI */
+	{ 97, 1,  4, 3 },	/* SCIF2_RXI */
+	{ 98, 1,  4, 3 },	/* SCIF2_BRI */
+	{ 99, 1,  4, 3 },	/* SCIF2_TXI */
 };
 
+static unsigned int ipr_offsets[] = {
+	0xf8080000,	/* IPRC */
+	0xf8080002,	/* IPRD */
+	0xf8080004,	/* IPRE */
+	0xf8080006,	/* IPRF */
+	0xf8080008,	/* IPRG */
+};
+
+/* given the IPR index return the address of the IPR register */
+unsigned int map_ipridx_to_addr(int idx)
+{
+	if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
+		return 0;
+	return ipr_offsets[idx];
+}
+
 void __init init_IRQ_ipr(void)
 {
 	make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map));
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
index a9ad309..82d7f99 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
@@ -18,8 +18,8 @@
 #include <asm/freq.h>
 #include <asm/io.h>
 
-const static int pll1rate[]={1,2,3,4,6,8};
-const static int pfc_divisors[]={1,2,3,4,6,8,12};
+static const int pll1rate[]={1,2,3,4,6,8};
+static const int pfc_divisors[]={1,2,3,4,6,8,12};
 #define ifc_divisors pfc_divisors
 
 #if (CONFIG_SH_CLK_MD == 2)
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
index 87c6c054..426f6db 100644
--- a/arch/sh/kernel/cpu/sh2a/probe.c
+++ b/arch/sh/kernel/cpu/sh2a/probe.c
@@ -17,14 +17,14 @@
 int __init detect_cpu_and_cache_system(void)
 {
 	/* Just SH7206 for now .. */
-	cpu_data->type			= CPU_SH7206;
+	current_cpu_data.type			= CPU_SH7206;
 
-	cpu_data->dcache.ways		= 4;
-	cpu_data->dcache.way_incr	= (1 << 11);
-	cpu_data->dcache.sets		= 128;
-	cpu_data->dcache.entry_shift	= 4;
-	cpu_data->dcache.linesz		= L1_CACHE_BYTES;
-	cpu_data->dcache.flags		= 0;
+	current_cpu_data.dcache.ways		= 4;
+	current_cpu_data.dcache.way_incr	= (1 << 11);
+	current_cpu_data.dcache.sets		= 128;
+	current_cpu_data.dcache.entry_shift	= 4;
+	current_cpu_data.dcache.linesz		= L1_CACHE_BYTES;
+	current_cpu_data.dcache.flags		= 0;
 
 	/*
 	 * The icache is the same as the dcache as far as this setup is
@@ -32,7 +32,7 @@
 	 * lacks the U bit that the dcache has, none of this has any bearing
 	 * on the cache info.
 	 */
-	cpu_data->icache		= cpu_data->dcache;
+	current_cpu_data.icache		= current_cpu_data.dcache;
 
 	return 0;
 }
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index 4b60fcc..4ed9110 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -57,55 +57,52 @@
 }
 __initcall(sh7206_devices_setup);
 
-#define INTC_IPR08     0xfffe0c04UL
-#define INTC_IPR09     0xfffe0c06UL
-#define INTC_IPR14     0xfffe0c10UL
-
-#define CMI0_IRQ       140
-
-#define MTU1_TGI1A     164
-
-#define SCIF0_BRI_IRQ  240
-#define SCIF0_ERI_IRQ  241
-#define SCIF0_RXI_IRQ  242
-#define SCIF0_TXI_IRQ  243
-
-#define SCIF1_BRI_IRQ  244
-#define SCIF1_ERI_IRQ  245
-#define SCIF1_RXI_IRQ  246
-#define SCIF1_TXI_IRQ  247
-
-#define SCIF2_BRI_IRQ  248
-#define SCIF2_ERI_IRQ  249
-#define SCIF2_RXI_IRQ  250
-#define SCIF2_TXI_IRQ  251
-
-#define SCIF3_BRI_IRQ  252
-#define SCIF3_ERI_IRQ  253
-#define SCIF3_RXI_IRQ  254
-#define SCIF3_TXI_IRQ  255
-
 static struct ipr_data sh7206_ipr_map[] = {
-	{ CMI0_IRQ,      INTC_IPR08, 3, 2 },
-	{ MTU2_TGI1A,    INTC_IPR09, 1, 2 },
-	{ SCIF0_ERI_IRQ, INTC_IPR14, 3, 3 },
-	{ SCIF0_RXI_IRQ, INTC_IPR14, 3, 3 },
-	{ SCIF0_BRI_IRQ, INTC_IPR14, 3, 3 },
-	{ SCIF0_TXI_IRQ, INTC_IPR14, 3, 3 },
-	{ SCIF1_ERI_IRQ, INTC_IPR14, 2, 3 },
-	{ SCIF1_RXI_IRQ, INTC_IPR14, 2, 3 },
-	{ SCIF1_BRI_IRQ, INTC_IPR14, 2, 3 },
-	{ SCIF1_TXI_IRQ, INTC_IPR14, 2, 3 },
-	{ SCIF2_ERI_IRQ, INTC_IPR14, 1, 3 },
-	{ SCIF2_RXI_IRQ, INTC_IPR14, 1, 3 },
-	{ SCIF2_BRI_IRQ, INTC_IPR14, 1, 3 },
-	{ SCIF2_TXI_IRQ, INTC_IPR14, 1, 3 },
-	{ SCIF3_ERI_IRQ, INTC_IPR14, 0, 3 },
-	{ SCIF3_RXI_IRQ, INTC_IPR14, 0, 3 },
-	{ SCIF3_BRI_IRQ, INTC_IPR14, 0, 3 },
-	{ SCIF3_TXI_IRQ, INTC_IPR14, 0, 3 },
+	{ 140,  7, 12, 2 },	/* CMI0 */
+	{ 164,  8,  4, 2 },	/* MTU2_TGI1A */
+	{ 240, 13, 12, 3 },	/* SCIF0_BRI */
+	{ 241, 13, 12, 3 },	/* SCIF0_ERI */
+	{ 242, 13, 12, 3 },	/* SCIF0_RXI */
+	{ 243, 13, 12, 3 },	/* SCIF0_TXI */
+	{ 244, 13,  8, 3 },	/* SCIF1_BRI */
+	{ 245, 13,  8, 3 },	/* SCIF1_ERI */
+	{ 246, 13,  8, 3 },	/* SCIF1_RXI */
+	{ 247, 13,  8, 3 },	/* SCIF1_TXI */
+	{ 248, 13,  4, 3 },	/* SCIF2_BRI */
+	{ 249, 13,  4, 3 },	/* SCIF2_ERI */
+	{ 250, 13,  4, 3 },	/* SCIF2_RXI */
+	{ 251, 13,  4, 3 },	/* SCIF2_TXI */
+	{ 252, 13,  0, 3 },	/* SCIF3_BRI */
+	{ 253, 13,  0, 3 },	/* SCIF3_ERI */
+	{ 254, 13,  0, 3 },	/* SCIF3_RXI */
+	{ 255, 13,  0, 3 },	/* SCIF3_TXI */
 };
 
+static unsigned int ipr_offsets[] = {
+	0xfffe0818,	/* IPR01 */
+	0xfffe081a,	/* IPR02 */
+	0,		/* unused */
+	0,		/* unused */
+	0xfffe0820,	/* IPR05 */
+	0xfffe0c00,	/* IPR06 */
+	0xfffe0c02,	/* IPR07 */
+	0xfffe0c04,	/* IPR08 */
+	0xfffe0c06,	/* IPR09 */
+	0xfffe0c08,	/* IPR10 */
+	0xfffe0c0a,	/* IPR11 */
+	0xfffe0c0c,	/* IPR12 */
+	0xfffe0c0e,	/* IPR13 */
+	0xfffe0c10,	/* IPR14 */
+};
+
+/* given the IPR index return the address of the IPR register */
+unsigned int map_ipridx_to_addr(int idx)
+{
+	if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
+		return 0;
+	return ipr_offsets[idx];
+}
+
 void __init init_IRQ_ipr(void)
 {
 	make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map));
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 8c0dc27..c19205b 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -13,10 +13,8 @@
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
-#include <asm/unistd.h>
 #include <asm/cpu/mmu_context.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <asm/unistd.h>
 
 ! NOTE:
 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -138,14 +136,29 @@
 
 call_dpf:
 	mov.l	1f, r0
- 	mov.l	@r0, r6		! address
+	mov	r5, r8
+	mov.l	@r0, r6
+	mov	r6, r9
+	mov.l	2f, r0
+	sts	pr, r10
+	jsr	@r0
+	 mov	r15, r4
+	!
+	tst	r0, r0
+	bf/s	0f
+	 lds	r10, pr
+	rts
+	 nop
+0:	sti
 	mov.l	3f, r0
-
+	mov	r9, r6
+	mov	r8, r5
 	jmp	@r0
- 	 mov	r15, r4		! regs
+	 mov	r15, r4
 
 	.align 2
 1:	.long	MMU_TEA
+2:	.long	__do_page_fault
 3:	.long	do_page_fault
 
 	.align	2
@@ -173,7 +186,7 @@
 
 #if defined(CONFIG_SH_STANDARD_BIOS)
 	/* Unwind the stack and jmp to the debug entry */
-debug_kernel_fw:
+ENTRY(sh_bios_handler)
 	mov.l	@r15+, r0
 	mov.l	@r15+, r1
 	mov.l	@r15+, r2
@@ -332,175 +345,9 @@
 !
 !
 
-/* This code makes some assumptions to improve performance.
- * Make sure they are stil true. */
-#if PTRS_PER_PGD != PTRS_PER_PTE
-#error PGD and PTE sizes don't match
-#endif
-
-/* gas doesn't flag impossible values for mov #immediate as an error */
-#if (_PAGE_PRESENT >> 2) > 0x7f
-#error cannot load PAGE_PRESENT as an immediate
-#endif
-#if _PAGE_DIRTY > 0x7f
-#error cannot load PAGE_DIRTY as an immediate
-#endif
-#if (_PAGE_PRESENT << 2) != _PAGE_ACCESSED
-#error cannot derive PAGE_ACCESSED from PAGE_PRESENT
-#endif
-
-#if defined(CONFIG_CPU_SH4)
-#define ldmmupteh(r)	mov.l	8f, r
-#else
-#define ldmmupteh(r)	mov	#MMU_PTEH, r
-#endif
-
 	.balign 	1024,0,1024
 tlb_miss:
-#ifdef COUNT_EXCEPTIONS
-	! Increment the counts
-	mov.l	9f, k1
-	mov.l	@k1, k2
-	add	#1, k2
-	mov.l	k2, @k1
-#endif
-
-	! k0 scratch
-	! k1 pgd and pte pointers
-	! k2 faulting address
-	! k3 pgd and pte index masks
-	! k4 shift
-
-	! Load up the pgd entry (k1)
-
-	ldmmupteh(k0)			!  9 LS (latency=2)	MMU_PTEH
-
-	mov.w	4f, k3			!  8 LS (latency=2)	(PTRS_PER_PGD-1) << 2
-	mov	#-(PGDIR_SHIFT-2), k4	!  6 EX
-
-	mov.l	@(MMU_TEA-MMU_PTEH,k0), k2	! 18 LS (latency=2)
-
-	mov.l	@(MMU_TTB-MMU_PTEH,k0), k1	! 18 LS (latency=2)
-
-	mov	k2, k0			!   5 MT (latency=0)
-	shld	k4, k0			!  99 EX
-
-	and	k3, k0			!  78 EX
-
-	mov.l	@(k0, k1), k1		!  21 LS (latency=2)
-	mov	#-(PAGE_SHIFT-2), k4	!   6 EX
-
-	! Load up the pte entry (k2)
-
-	mov	k2, k0			!   5 MT (latency=0)
-	shld	k4, k0			!  99 EX
-
-	tst	k1, k1			!  86 MT
-
-	bt	20f			! 110 BR
-
-	and	k3, k0			!  78 EX
-	mov.w	5f, k4			!   8 LS (latency=2)	_PAGE_PRESENT
-
-	mov.l	@(k0, k1), k2		!  21 LS (latency=2)
-	add	k0, k1			!  49 EX
-
-#ifdef CONFIG_CPU_HAS_PTEA
-	! Test the entry for present and _PAGE_ACCESSED
-
-	mov	#-28, k3		!   6 EX
-	mov	k2, k0			!   5 MT (latency=0)
-
-	tst	k4, k2			!  68 MT
-	shld	k3, k0			!  99 EX
-
-	bt	20f			! 110 BR
-
-	! Set PTEA register
-	! MMU_PTEA = ((pteval >> 28) & 0xe) | (pteval & 0x1)
-	!
-	! k0=pte>>28, k1=pte*, k2=pte, k3=<unused>, k4=_PAGE_PRESENT
-
-	and	#0xe, k0		!  79 EX
-
-	mov	k0, k3			!   5 MT (latency=0)
-	mov	k2, k0			!   5 MT (latency=0)
-
-	and	#1, k0			!  79 EX
-
-	or	k0, k3			!  82 EX
-
-	ldmmupteh(k0)			!   9 LS (latency=2)
-	shll2	k4			! 101 EX		_PAGE_ACCESSED
-
-	tst	k4, k2			!  68 MT
-
-	mov.l	k3, @(MMU_PTEA-MMU_PTEH,k0)	! 27 LS
-
-	mov.l	7f, k3			!   9 LS (latency=2)	_PAGE_FLAGS_HARDWARE_MASK
-
-	! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
-#else
-
-	! Test the entry for present and _PAGE_ACCESSED
-
-	mov.l	7f, k3			!   9 LS (latency=2)	_PAGE_FLAGS_HARDWARE_MASK
-	tst	k4, k2			!  68 MT
-
-	shll2	k4			! 101 EX		_PAGE_ACCESSED
-	ldmmupteh(k0)			!   9 LS (latency=2)
-
-	bt	20f			! 110 BR
-	tst	k4, k2			!  68 MT
-
-	! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
-
-#endif
-
-	! Set up the entry
-
-	and	k2, k3			!  78 EX
-	bt/s	10f			! 108 BR
-
-	 mov.l	k3, @(MMU_PTEL-MMU_PTEH,k0)	! 27 LS
-
-	ldtlb				! 128 CO
-
-	! At least one instruction between ldtlb and rte
-	nop				! 119 NOP
-
-	rte				! 126 CO
-
-	 nop				! 119 NOP
-
-
-10:	or	k4, k2			!  82 EX
-
-	ldtlb				! 128 CO
-
-	! At least one instruction between ldtlb and rte
-	mov.l	k2, @k1			!  27 LS
-
-	rte				! 126 CO
-
-	! Note we cannot execute mov here, because it is executed after
-	! restoring SSR, so would be executed in user space.
-	 nop				! 119 NOP
-
-
-	.align 5
-	! Once cache line if possible...
-1:	.long	swapper_pg_dir
-4:	.short	(PTRS_PER_PGD-1) << 2
-5:	.short	_PAGE_PRESENT
-7:	.long	_PAGE_FLAGS_HARDWARE_MASK
-8:	.long	MMU_PTEH
-#ifdef COUNT_EXCEPTIONS
-9:	.long	exception_count_miss
-#endif
-
-	! Either pgd or pte not present
-20:	mov.l	1f, k2
+	mov.l	1f, k2
 	mov.l	4f, k3
 	bra	handle_exception
 	 mov.l	@k2, k2
@@ -651,15 +498,6 @@
 	bf	interrupt_exception
 	shlr2	r8
 	shlr	r8
-
-#ifdef COUNT_EXCEPTIONS
-	mov.l	5f, r9
-	add	r8, r9
-	mov.l	@r9, r10
-	add	#1, r10
-	mov.l	r10, @r9
-#endif
-
 	mov.l	4f, r9
 	add	r8, r9
 	mov.l	@r9, r9
@@ -673,9 +511,6 @@
 2:	.long	0x000080f0	! FD=1, IMASK=15
 3:	.long	0xcfffffff	! RB=0, BL=0
 4:	.long	exception_handling_table
-#ifdef COUNT_EXCEPTIONS
-5:	.long	exception_count_table
-#endif
 
 interrupt_exception:
 	mov.l	1f, r9
diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c
index e670988..821b0ab 100644
--- a/arch/sh/kernel/cpu/sh3/probe.c
+++ b/arch/sh/kernel/cpu/sh3/probe.c
@@ -50,41 +50,41 @@
 
 	back_to_P1();
 
-	cpu_data->dcache.ways		= 4;
-	cpu_data->dcache.entry_shift	= 4;
-	cpu_data->dcache.linesz		= L1_CACHE_BYTES;
-	cpu_data->dcache.flags		= 0;
+	current_cpu_data.dcache.ways		= 4;
+	current_cpu_data.dcache.entry_shift	= 4;
+	current_cpu_data.dcache.linesz		= L1_CACHE_BYTES;
+	current_cpu_data.dcache.flags		= 0;
 
 	/*
 	 * 7709A/7729 has 16K cache (256-entry), while 7702 has only
 	 * 2K(direct) 7702 is not supported (yet)
 	 */
 	if (data0 == data1 && data2 == data3) {	/* Shadow */
-		cpu_data->dcache.way_incr	= (1 << 11);
-		cpu_data->dcache.entry_mask	= 0x7f0;
-		cpu_data->dcache.sets		= 128;
-		cpu_data->type = CPU_SH7708;
+		current_cpu_data.dcache.way_incr	= (1 << 11);
+		current_cpu_data.dcache.entry_mask	= 0x7f0;
+		current_cpu_data.dcache.sets		= 128;
+		current_cpu_data.type = CPU_SH7708;
 
-		cpu_data->flags |= CPU_HAS_MMU_PAGE_ASSOC;
+		current_cpu_data.flags |= CPU_HAS_MMU_PAGE_ASSOC;
 	} else {				/* 7709A or 7729  */
-		cpu_data->dcache.way_incr	= (1 << 12);
-		cpu_data->dcache.entry_mask	= 0xff0;
-		cpu_data->dcache.sets		= 256;
-		cpu_data->type = CPU_SH7729;
+		current_cpu_data.dcache.way_incr	= (1 << 12);
+		current_cpu_data.dcache.entry_mask	= 0xff0;
+		current_cpu_data.dcache.sets		= 256;
+		current_cpu_data.type = CPU_SH7729;
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7706)
-		cpu_data->type = CPU_SH7706;
+		current_cpu_data.type = CPU_SH7706;
 #endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7710)
-		cpu_data->type = CPU_SH7710;
+		current_cpu_data.type = CPU_SH7710;
 #endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
-		cpu_data->type = CPU_SH7705;
+		current_cpu_data.type = CPU_SH7705;
 
 #if defined(CONFIG_SH7705_CACHE_32KB)
-		cpu_data->dcache.way_incr	= (1 << 13);
-		cpu_data->dcache.entry_mask	= 0x1ff0;
-		cpu_data->dcache.sets		= 512;
+		current_cpu_data.dcache.way_incr	= (1 << 13);
+		current_cpu_data.dcache.entry_mask	= 0x1ff0;
+		current_cpu_data.dcache.sets		= 512;
 		ctrl_outl(CCR_CACHE_32KB, CCR3);
 #else
 		ctrl_outl(CCR_CACHE_16KB, CCR3);
@@ -95,8 +95,8 @@
 	/*
 	 * SH-3 doesn't have separate caches
 	 */
-	cpu_data->dcache.flags |= SH_CACHE_COMBINED;
-	cpu_data->icache = cpu_data->dcache;
+	current_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
+	current_cpu_data.icache = current_cpu_data.dcache;
 
 	return 0;
 }
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7709.c b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
index ff43ef2..dc9b211 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7709.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
@@ -51,3 +51,24 @@
 				    ARRAY_SIZE(sh7709_devices));
 }
 __initcall(sh7709_devices_setup);
+
+#define IPRx(A,N) .addr=A, .shift=0*N*-1
+#define IPRA(N)	IPRx(0xfffffee2UL,N)
+#define IPRB(N)	IPRx(0xfffffee4UL,N)
+#define IPRE(N)	IPRx(0xa400001aUL,N)
+
+static struct ipr_data sh7709_ipr_map[] = {
+	[16]		= { IPRA(15-12), 2 }, /* TMU TUNI0 */
+	[17]		= { IPRA(11-8),  4 }, /* TMU TUNI1 */
+	[22]		= { IPRA(3-0),   2 }, /* RTC CUI */
+	[23 ... 26]	= { IPRB(7-4),   3 }, /* SCI */
+	[27]		= { IPRB(15-12), 2 }, /* WDT ITI */
+	[48 ... 51]	= { IPRE(15-12), 7 }, /* DMA */
+	[52 ... 55]	= { IPRE(11-8),  3 }, /* IRDA */
+	[56 ... 59]	= { IPRE(7-4),   3 }, /* SCIF */
+};
+
+void __init init_IRQ_ipr()
+{
+	make_ipr_irq(sh7709_ipr_map, ARRAY_SIZE(sh7709_ipr_map));
+}
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 9031a22..9d28c88 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -10,11 +10,10 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #include <linux/init.h>
+#include <linux/io.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
-#include <asm/io.h>
 
 int __init detect_cpu_and_cache_system(void)
 {
@@ -36,20 +35,20 @@
 	/*
 	 * Setup some sane SH-4 defaults for the icache
 	 */
-	cpu_data->icache.way_incr	= (1 << 13);
-	cpu_data->icache.entry_shift	= 5;
-	cpu_data->icache.sets		= 256;
-	cpu_data->icache.ways		= 1;
-	cpu_data->icache.linesz		= L1_CACHE_BYTES;
+	current_cpu_data.icache.way_incr	= (1 << 13);
+	current_cpu_data.icache.entry_shift	= 5;
+	current_cpu_data.icache.sets		= 256;
+	current_cpu_data.icache.ways		= 1;
+	current_cpu_data.icache.linesz		= L1_CACHE_BYTES;
 
 	/*
 	 * And again for the dcache ..
 	 */
-	cpu_data->dcache.way_incr	= (1 << 14);
-	cpu_data->dcache.entry_shift	= 5;
-	cpu_data->dcache.sets		= 512;
-	cpu_data->dcache.ways		= 1;
-	cpu_data->dcache.linesz		= L1_CACHE_BYTES;
+	current_cpu_data.dcache.way_incr	= (1 << 14);
+	current_cpu_data.dcache.entry_shift	= 5;
+	current_cpu_data.dcache.sets		= 512;
+	current_cpu_data.dcache.ways		= 1;
+	current_cpu_data.dcache.linesz		= L1_CACHE_BYTES;
 
 	/*
 	 * Setup some generic flags we can probe
@@ -57,16 +56,16 @@
 	 */
 	if (((pvr >> 16) & 0xff) == 0x10) {
 		if ((cvr & 0x02000000) == 0)
-			cpu_data->flags |= CPU_HAS_L2_CACHE;
+			current_cpu_data.flags |= CPU_HAS_L2_CACHE;
 		if ((cvr & 0x10000000) == 0)
-			cpu_data->flags |= CPU_HAS_DSP;
+			current_cpu_data.flags |= CPU_HAS_DSP;
 
-		cpu_data->flags |= CPU_HAS_LLSC;
+		current_cpu_data.flags |= CPU_HAS_LLSC;
 	}
 
 	/* FPU detection works for everyone */
 	if ((cvr & 0x20000000) == 1)
-		cpu_data->flags |= CPU_HAS_FPU;
+		current_cpu_data.flags |= CPU_HAS_FPU;
 
 	/* Mask off the upper chip ID */
 	pvr &= 0xffff;
@@ -77,151 +76,151 @@
 	 */
 	switch (pvr) {
 	case 0x205:
-		cpu_data->type = CPU_SH7750;
-		cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
+		current_cpu_data.type = CPU_SH7750;
+		current_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
 				   CPU_HAS_PERF_COUNTER;
 		break;
 	case 0x206:
-		cpu_data->type = CPU_SH7750S;
-		cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
+		current_cpu_data.type = CPU_SH7750S;
+		current_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
 				   CPU_HAS_PERF_COUNTER;
 		break;
 	case 0x1100:
-		cpu_data->type = CPU_SH7751;
-		cpu_data->flags |= CPU_HAS_FPU;
+		current_cpu_data.type = CPU_SH7751;
+		current_cpu_data.flags |= CPU_HAS_FPU;
 		break;
 	case 0x2000:
-		cpu_data->type = CPU_SH73180;
-		cpu_data->icache.ways = 4;
-		cpu_data->dcache.ways = 4;
-		cpu_data->flags |= CPU_HAS_LLSC;
+		current_cpu_data.type = CPU_SH73180;
+		current_cpu_data.icache.ways = 4;
+		current_cpu_data.dcache.ways = 4;
+		current_cpu_data.flags |= CPU_HAS_LLSC;
 		break;
 	case 0x2001:
 	case 0x2004:
-		cpu_data->type = CPU_SH7770;
-		cpu_data->icache.ways = 4;
-		cpu_data->dcache.ways = 4;
+		current_cpu_data.type = CPU_SH7770;
+		current_cpu_data.icache.ways = 4;
+		current_cpu_data.dcache.ways = 4;
 
-		cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_LLSC;
+		current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_LLSC;
 		break;
 	case 0x2006:
 	case 0x200A:
 		if (prr == 0x61)
-			cpu_data->type = CPU_SH7781;
+			current_cpu_data.type = CPU_SH7781;
 		else
-			cpu_data->type = CPU_SH7780;
+			current_cpu_data.type = CPU_SH7780;
 
-		cpu_data->icache.ways = 4;
-		cpu_data->dcache.ways = 4;
+		current_cpu_data.icache.ways = 4;
+		current_cpu_data.dcache.ways = 4;
 
-		cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
+		current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
 				   CPU_HAS_LLSC;
 		break;
 	case 0x3000:
 	case 0x3003:
 	case 0x3009:
-		cpu_data->type = CPU_SH7343;
-		cpu_data->icache.ways = 4;
-		cpu_data->dcache.ways = 4;
-		cpu_data->flags |= CPU_HAS_LLSC;
+		current_cpu_data.type = CPU_SH7343;
+		current_cpu_data.icache.ways = 4;
+		current_cpu_data.dcache.ways = 4;
+		current_cpu_data.flags |= CPU_HAS_LLSC;
 		break;
 	case 0x3008:
 		if (prr == 0xa0) {
-			cpu_data->type = CPU_SH7722;
-			cpu_data->icache.ways = 4;
-			cpu_data->dcache.ways = 4;
-			cpu_data->flags |= CPU_HAS_LLSC;
+			current_cpu_data.type = CPU_SH7722;
+			current_cpu_data.icache.ways = 4;
+			current_cpu_data.dcache.ways = 4;
+			current_cpu_data.flags |= CPU_HAS_LLSC;
 		}
 		break;
 	case 0x8000:
-		cpu_data->type = CPU_ST40RA;
-		cpu_data->flags |= CPU_HAS_FPU;
+		current_cpu_data.type = CPU_ST40RA;
+		current_cpu_data.flags |= CPU_HAS_FPU;
 		break;
 	case 0x8100:
-		cpu_data->type = CPU_ST40GX1;
-		cpu_data->flags |= CPU_HAS_FPU;
+		current_cpu_data.type = CPU_ST40GX1;
+		current_cpu_data.flags |= CPU_HAS_FPU;
 		break;
 	case 0x700:
-		cpu_data->type = CPU_SH4_501;
-		cpu_data->icache.ways = 2;
-		cpu_data->dcache.ways = 2;
+		current_cpu_data.type = CPU_SH4_501;
+		current_cpu_data.icache.ways = 2;
+		current_cpu_data.dcache.ways = 2;
 		break;
 	case 0x600:
-		cpu_data->type = CPU_SH4_202;
-		cpu_data->icache.ways = 2;
-		cpu_data->dcache.ways = 2;
-		cpu_data->flags |= CPU_HAS_FPU;
+		current_cpu_data.type = CPU_SH4_202;
+		current_cpu_data.icache.ways = 2;
+		current_cpu_data.dcache.ways = 2;
+		current_cpu_data.flags |= CPU_HAS_FPU;
 		break;
 	case 0x500 ... 0x501:
 		switch (prr) {
 		case 0x10:
-			cpu_data->type = CPU_SH7750R;
+			current_cpu_data.type = CPU_SH7750R;
 			break;
 		case 0x11:
-			cpu_data->type = CPU_SH7751R;
+			current_cpu_data.type = CPU_SH7751R;
 			break;
 		case 0x50 ... 0x5f:
-			cpu_data->type = CPU_SH7760;
+			current_cpu_data.type = CPU_SH7760;
 			break;
 		}
 
-		cpu_data->icache.ways = 2;
-		cpu_data->dcache.ways = 2;
+		current_cpu_data.icache.ways = 2;
+		current_cpu_data.dcache.ways = 2;
 
-		cpu_data->flags |= CPU_HAS_FPU;
+		current_cpu_data.flags |= CPU_HAS_FPU;
 
 		break;
 	default:
-		cpu_data->type = CPU_SH_NONE;
+		current_cpu_data.type = CPU_SH_NONE;
 		break;
 	}
 
 #ifdef CONFIG_SH_DIRECT_MAPPED
-	cpu_data->icache.ways = 1;
-	cpu_data->dcache.ways = 1;
+	current_cpu_data.icache.ways = 1;
+	current_cpu_data.dcache.ways = 1;
 #endif
 
 #ifdef CONFIG_CPU_HAS_PTEA
-	cpu_data->flags |= CPU_HAS_PTEA;
+	current_cpu_data.flags |= CPU_HAS_PTEA;
 #endif
 
 	/*
 	 * On anything that's not a direct-mapped cache, look to the CVR
 	 * for I/D-cache specifics.
 	 */
-	if (cpu_data->icache.ways > 1) {
+	if (current_cpu_data.icache.ways > 1) {
 		size = sizes[(cvr >> 20) & 0xf];
-		cpu_data->icache.way_incr	= (size >> 1);
-		cpu_data->icache.sets		= (size >> 6);
+		current_cpu_data.icache.way_incr	= (size >> 1);
+		current_cpu_data.icache.sets		= (size >> 6);
 
 	}
 
 	/* Setup the rest of the I-cache info */
-	cpu_data->icache.entry_mask = cpu_data->icache.way_incr -
-				      cpu_data->icache.linesz;
+	current_cpu_data.icache.entry_mask = current_cpu_data.icache.way_incr -
+				      current_cpu_data.icache.linesz;
 
-	cpu_data->icache.way_size = cpu_data->icache.sets *
-				    cpu_data->icache.linesz;
+	current_cpu_data.icache.way_size = current_cpu_data.icache.sets *
+				    current_cpu_data.icache.linesz;
 
 	/* And the rest of the D-cache */
-	if (cpu_data->dcache.ways > 1) {
+	if (current_cpu_data.dcache.ways > 1) {
 		size = sizes[(cvr >> 16) & 0xf];
-		cpu_data->dcache.way_incr	= (size >> 1);
-		cpu_data->dcache.sets		= (size >> 6);
+		current_cpu_data.dcache.way_incr	= (size >> 1);
+		current_cpu_data.dcache.sets		= (size >> 6);
 	}
 
-	cpu_data->dcache.entry_mask = cpu_data->dcache.way_incr -
-				      cpu_data->dcache.linesz;
+	current_cpu_data.dcache.entry_mask = current_cpu_data.dcache.way_incr -
+				      current_cpu_data.dcache.linesz;
 
-	cpu_data->dcache.way_size = cpu_data->dcache.sets *
-				    cpu_data->dcache.linesz;
+	current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets *
+				    current_cpu_data.dcache.linesz;
 
 	/*
 	 * Setup the L2 cache desc
 	 *
 	 * SH-4A's have an optional PIPT L2.
 	 */
-	if (cpu_data->flags & CPU_HAS_L2_CACHE) {
+	if (current_cpu_data.flags & CPU_HAS_L2_CACHE) {
 		/*
 		 * Size calculation is much more sensible
 		 * than it is for the L1.
@@ -232,16 +231,22 @@
 
 		BUG_ON(!size);
 
-		cpu_data->scache.way_incr	= (1 << 16);
-		cpu_data->scache.entry_shift	= 5;
-		cpu_data->scache.ways		= 4;
-		cpu_data->scache.linesz		= L1_CACHE_BYTES;
-		cpu_data->scache.entry_mask	=
-			(cpu_data->scache.way_incr - cpu_data->scache.linesz);
-		cpu_data->scache.sets		= size /
-			(cpu_data->scache.linesz * cpu_data->scache.ways);
-		cpu_data->scache.way_size	=
-			(cpu_data->scache.sets * cpu_data->scache.linesz);
+		current_cpu_data.scache.way_incr	= (1 << 16);
+		current_cpu_data.scache.entry_shift	= 5;
+		current_cpu_data.scache.ways		= 4;
+		current_cpu_data.scache.linesz		= L1_CACHE_BYTES;
+
+		current_cpu_data.scache.entry_mask	=
+			(current_cpu_data.scache.way_incr -
+			 current_cpu_data.scache.linesz);
+
+		current_cpu_data.scache.sets		= size /
+			(current_cpu_data.scache.linesz *
+			 current_cpu_data.scache.ways);
+
+		current_cpu_data.scache.way_size	=
+			(current_cpu_data.scache.sets *
+			 current_cpu_data.scache.linesz);
 	}
 
 	return 0;
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index cbac276..6f8f458 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -46,11 +46,13 @@
 
 static struct plat_sci_port sci_platform_data[] = {
 	{
+#ifndef CONFIG_SH_RTS7751R2D
 		.mapbase	= 0xffe00000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCI,
 		.irqs		= { 23, 24, 25, 0 },
 	}, {
+#endif
 		.mapbase	= 0xffe80000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
@@ -101,7 +103,7 @@
 	{ 35, 2,  8, 7 }, /* DMAC DMTE1 */
 	{ 36, 2,  8, 7 }, /* DMAC DMTE2 */
 	{ 37, 2,  8, 7 }, /* DMAC DMTE3 */
-	{ 28, 2,  8, 7 }, /* DMAC DMAE */
+	{ 38, 2,  8, 7 }, /* DMAC DMAE */
 };
 
 static struct ipr_data sh7751_ipr_map[] = {
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index 07e5377..b7c7028 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -52,17 +52,11 @@
 }
 __initcall(sh7760_devices_setup);
 
-/*
- * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0
- */
 static struct intc2_data intc2_irq_table[] = {
-	/* INTPRIO0 | INTMSK0 */
 	{48,  0, 28, 0, 31,  3},	/* IRQ 4 */
 	{49,  0, 24, 0, 30,  3},	/* IRQ 3 */
 	{50,  0, 20, 0, 29,  3},	/* IRQ 2 */
 	{51,  0, 16, 0, 28,  3},	/* IRQ 1 */
-	/* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */
-	/* INTPRIO4 | INTMSK0 */
 	{56,  4, 28, 0, 25,  3},	/* HCAN2_CHAN0 */
 	{57,  4, 24, 0, 24,  3},	/* HCAN2_CHAN1 */
 	{58,  4, 20, 0, 23,  3},	/* I2S_CHAN0   */
@@ -71,18 +65,15 @@
 	{61,  4,  8, 0, 20,  3},	/* AC97_CHAN1  */
 	{62,  4,  4, 0, 19,  3},	/* I2C_CHAN0   */
 	{63,  4,  0, 0, 18,  3},	/* I2C_CHAN1   */
-	/* INTPRIO8 | INTMSK0 */
 	{52,  8, 16, 0, 11,  3},	/* SCIF0_ERI_IRQ */
 	{53,  8, 16, 0, 10,  3},	/* SCIF0_RXI_IRQ */
 	{54,  8, 16, 0,  9,  3},	/* SCIF0_BRI_IRQ */
 	{55,  8, 16, 0,  8,  3},	/* SCIF0_TXI_IRQ */
 	{64,  8, 28, 0, 17,  3},	/* USBHI_IRQ */
 	{65,  8, 24, 0, 16,  3},	/* LCDC      */
-	/* 66, 67 unused */
 	{68,  8, 20, 0, 14, 13},	/* DMABRGI0_IRQ */
 	{69,  8, 20, 0, 13, 13},	/* DMABRGI1_IRQ */
 	{70,  8, 20, 0, 12, 13},	/* DMABRGI2_IRQ */
-	/* 71 unused */
 	{72,  8, 12, 0,  7,  3},	/* SCIF1_ERI_IRQ */
 	{73,  8, 12, 0,  6,  3},	/* SCIF1_RXI_IRQ */
 	{74,  8, 12, 0,  5,  3},	/* SCIF1_BRI_IRQ */
@@ -91,26 +82,71 @@
 	{77,  8,  8, 0,  2,  3},	/* SCIF2_RXI_IRQ */
 	{78,  8,  8, 0,  1,  3},	/* SCIF2_BRI_IRQ */
 	{79,  8,  8, 0,  0,  3},	/* SCIF2_TXI_IRQ */
-	/*          | INTMSK4 */
 	{80,  8,  4, 4, 23,  3},	/* SIM_ERI */
 	{81,  8,  4, 4, 22,  3},	/* SIM_RXI */
 	{82,  8,  4, 4, 21,  3},	/* SIM_TXI */
 	{83,  8,  4, 4, 20,  3},	/* SIM_TEI */
 	{84,  8,  0, 4, 19,  3},	/* HSPII */
-	/* INTPRIOC | INTMSK4 */
-	/* 85-87 unused/reserved */
 	{88, 12, 20, 4, 18,  3},	/* MMCI0 */
 	{89, 12, 20, 4, 17,  3},	/* MMCI1 */
 	{90, 12, 20, 4, 16,  3},	/* MMCI2 */
 	{91, 12, 20, 4, 15,  3},	/* MMCI3 */
-	{92, 12, 12, 4,  6,  3},	/* MFI (unsure, bug? in my 7760 manual*/
-	/* 93-107 reserved/undocumented */
+	{92, 12, 12, 4,  6,  3},	/* MFI */
 	{108,12,  4, 4,  1,  3},	/* ADC  */
 	{109,12,  0, 4,  0,  3},	/* CMTI */
-	/* 110-111 reserved/unused */
 };
 
+static struct ipr_data sh7760_ipr_map[] = {
+	/* IRQ, IPR-idx, shift, priority */
+	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
+	{ 17, 0,  8, 2 }, /* TMU1 TUNI */
+	{ 18, 0,  4, 2 }, /* TMU2 TUNI */
+	{ 19, 0,  4, 2 }, /* TMU2 TIPCI */
+	{ 27, 1, 12, 2 }, /* WDT ITI */
+	{ 28, 1,  8, 2 }, /* REF RCMI */
+	{ 29, 1,  8, 2 }, /* REF ROVI */
+	{ 32, 2,  0, 7 }, /* HUDI */
+	{ 33, 2, 12, 7 }, /* GPIOI */
+	{ 34, 2,  8, 7 }, /* DMAC DMTE0 */
+	{ 35, 2,  8, 7 }, /* DMAC DMTE1 */
+	{ 36, 2,  8, 7 }, /* DMAC DMTE2 */
+	{ 37, 2,  8, 7 }, /* DMAC DMTE3 */
+	{ 38, 2,  8, 7 }, /* DMAC DMAE */
+	{ 44, 2,  8, 7 }, /* DMAC DMTE4 */
+	{ 45, 2,  8, 7 }, /* DMAC DMTE5 */
+	{ 46, 2,  8, 7 }, /* DMAC DMTE6 */
+	{ 47, 2,  8, 7 }, /* DMAC DMTE7 */
+/* these here are only valid if INTC_ICR bit 7 is set to 1!
+ * XXX: maybe CONFIG_SH_IRLMODE symbol? SH7751 could use it too */
+#if 0
+	{  2, 3, 12, 3 }, /* IRL0 */
+	{  5, 3,  8, 3 }, /* IRL1 */
+	{  8, 3,  4, 3 }, /* IRL2 */
+	{ 11, 3,  0, 3 }, /* IRL3 */
+#endif
+};
+
+static unsigned long ipr_offsets[] = {
+	0xffd00004UL,	/* 0: IPRA */
+	0xffd00008UL,	/* 1: IPRB */
+	0xffd0000cUL,	/* 2: IPRC */
+	0xffd00010UL,	/* 3: IPRD */
+};
+
+/* given the IPR index return the address of the IPR register */
+unsigned int map_ipridx_to_addr(int idx)
+{
+	if (idx >= ARRAY_SIZE(ipr_offsets))
+		return 0;
+	return ipr_offsets[idx];
+}
+
 void __init init_IRQ_intc2(void)
 {
 	make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
 }
+
+void __init  init_IRQ_ipr(void)
+{
+	make_ipr_irq(sh7760_ipr_map, ARRAY_SIZE(sh7760_ipr_map));
+}
diff --git a/arch/sh/kernel/debugtraps.S b/arch/sh/kernel/debugtraps.S
new file mode 100644
index 0000000..13b6674
--- /dev/null
+++ b/arch/sh/kernel/debugtraps.S
@@ -0,0 +1,41 @@
+/*
+ * arch/sh/kernel/debugtraps.S
+ *
+ * Debug trap jump tables for SuperH
+ *
+ *  Copyright (C) 2006  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+
+#if !defined(CONFIG_SH_KGDB)
+#define kgdb_handle_exception	debug_trap_handler
+#endif
+
+#if !defined(CONFIG_SH_STANDARD_BIOS)
+#define sh_bios_handler		debug_trap_handler
+#endif
+
+	.data
+
+ENTRY(debug_trap_table)
+	.long debug_trap_handler	/* 0x30 */
+	.long debug_trap_handler	/* 0x31 */
+	.long debug_trap_handler	/* 0x32 */
+	.long debug_trap_handler	/* 0x33 */
+	.long debug_trap_handler	/* 0x34 */
+	.long debug_trap_handler	/* 0x35 */
+	.long debug_trap_handler	/* 0x36 */
+	.long debug_trap_handler	/* 0x37 */
+	.long debug_trap_handler	/* 0x38 */
+	.long debug_trap_handler	/* 0x39 */
+	.long debug_trap_handler	/* 0x3a */
+	.long debug_trap_handler	/* 0x3b */
+	.long kgdb_handle_exception	/* 0x3c */
+	.long debug_trap_handler	/* 0x3d */
+	.long bug_trap_handler		/* 0x3e */
+	.long sh_bios_handler		/* 0x3f */
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index 560b91c..9048c03 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -106,12 +106,32 @@
 };
 
 #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
+#define DEFAULT_BAUD 115200
 /*
  * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
  * devices that aren't using sh-ipl+g.
  */
-static void scif_sercon_init(int baud)
+static void scif_sercon_init(char *s)
 {
+	unsigned baud = DEFAULT_BAUD;
+	char *e;
+
+	if (*s == ',')
+		++s;
+
+	if (*s) {
+		/* ignore ioport/device name */
+		s += strcspn(s, ",");
+		if (*s == ',')
+			s++;
+	}
+
+	if (*s) {
+		baud = simple_strtoul(s, &e, 0);
+		if (baud == 0 || s == e)
+			baud = DEFAULT_BAUD;
+	}
+
 	ctrl_outw(0, scif_port.mapbase + 8);
 	ctrl_outw(0, scif_port.mapbase);
 
@@ -167,7 +187,7 @@
 		early_console = &scif_console;
 
 #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
-		scif_sercon_init(115200);
+		scif_sercon_init(buf + 6);
 #endif
 	}
 #endif
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index fc279ae..ab4ebb8 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -54,79 +54,24 @@
 #  define resume_kernel		__restore_all
 #endif
 
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
-! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
-! If both are configured, handle the debug traps (breakpoints) in SW,
-! but still allow BIOS traps to FW.
-
-	.align	2
-debug_kernel:
-#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
-	/* Force BIOS call to FW (debug_trap put TRA in r8) */
-	mov	r8,r0
-	shlr2	r0
-	cmp/eq	#0x3f,r0
-	bt	debug_kernel_fw
-#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
-
-debug_enter:		
-#if defined(CONFIG_SH_KGDB)
-	/* Jump to kgdb, pass stacked regs as arg */
-debug_kernel_sw:
-	mov.l	3f, r0
-	jmp	@r0
-	 mov	r15, r4
-	.align	2
-3:	.long	kgdb_handle_exception
-#endif /* CONFIG_SH_KGDB */
-#ifdef CONFIG_SH_STANDARD_BIOS
-	bra	debug_kernel_fw
-	 nop
-#endif
-#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
-
-	.align	2
-debug_trap:	
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
-	mov	r8, r0
-	shlr2	r0
-	cmp/eq	#0x3f, r0		! sh_bios() trap
-	bf	1f
-#ifdef CONFIG_SH_KGDB
-	cmp/eq	#0xff, r0		! XXX: KGDB trap, fix for SH-2.
-	bf	1f
-#endif
-	mov	#OFF_SR, r0
-	mov.l	@(r0,r15), r0		! get status register
-	shll	r0
-	shll	r0			! kernel space?
-	bt/s	debug_kernel
-1:
-#endif
-	 mov.l	@r15, r0		! Restore R0 value
-	mov.l	1f, r8
-	jmp	@r8
-	 nop
 
 	.align	2
 ENTRY(exception_error)
 	!
 #ifdef CONFIG_TRACE_IRQFLAGS
-	mov.l	3f, r0
+	mov.l	2f, r0
 	jsr	@r0
 	 nop
 #endif
 	sti
-	mov.l	2f, r0
+	mov.l	1f, r0
 	jmp	@r0
 	 nop
 
-!
 	.align	2
-1:	.long	break_point_trap_software
-2:	.long	do_exception_error
+1:	.long	do_exception_error
 #ifdef CONFIG_TRACE_IRQFLAGS
-3:	.long	trace_hardirqs_on
+2:	.long	trace_hardirqs_on
 #endif
 
 	.align	2
@@ -331,16 +276,31 @@
 1:	.long	restore_all
 
 	.align	2
-not_syscall_tra:	
-	bra	debug_trap
-	 nop
-
-	.align	2
 syscall_badsys:			! Bad syscall number
 	mov	#-ENOSYS, r0
 	bra	resume_userspace
 	 mov.l	r0, @(OFF_R0,r15)	! Return value
-	
+
+/*
+ * The main debug trap handler.
+ *
+ * r8=TRA (not the trap number!)
+ *
+ * Note: This assumes that the trapa value is left in its original
+ * form (without the shlr2 shift) so the calculation for the jump
+ * call table offset remains a simple in place mask.
+ */
+debug_trap:
+	mov	r8, r0
+	and	#(0xf << 2), r0
+	mov.l	1f, r8
+	add	r0, r8
+	mov.l	@r8, r8
+	jmp	@r8
+	 nop
+
+	.align	2
+1:	.long	debug_trap_table
 
 /*
  * Syscall interface:
@@ -348,17 +308,19 @@
  *	Syscall #: R3
  *	Arguments #0 to #3: R4--R7
  *	Arguments #4 to #6: R0, R1, R2
- *	TRA: (number of arguments + 0x10) x 4
+ *	TRA: (number of arguments + ABI revision) x 4
  *
  * This code also handles delegating other traps to the BIOS/gdb stub
  * according to:
  *
  * Trap number
- * (TRA>>2) 	    Purpose
- * -------- 	    -------
- * 0x0-0xf  	    old syscall ABI
- * 0x10-0x1f  	    new syscall ABI
- * 0x20-0xff  	    delegated through debug_trap to BIOS/gdb stub.
+ * (TRA>>2)	Purpose
+ * --------	-------
+ * 0x00-0x0f	original SH-3/4 syscall ABI (not in general use).
+ * 0x10-0x1f	general SH-3/4 syscall ABI.
+ * 0x20-0x2f	syscall ABI for SH-2 parts.
+ * 0x30-0x3f	debug traps used by the kernel.
+ * 0x40-0xff	Not supported by all parts, so left unhandled.
  *
  * Note: When we're first called, the TRA value must be shifted
  * right 2 bits in order to get the value that was used as the "trapa"
@@ -375,17 +337,22 @@
 	 nop
 	.align	2
 1:	.long	schedule_tail
-	!
+
+/*
+ * The poorly named main trapa decode and dispatch routine, for
+ * system calls and debug traps through their respective jump tables.
+ */
 ENTRY(system_call)
 #if !defined(CONFIG_CPU_SH2)
 	mov.l	1f, r9
 	mov.l	@r9, r8		! Read from TRA (Trap Address) Register
 #endif
-	!
-	! Is the trap argument >= 0x20? (TRA will be >= 0x80)
-	mov	#0x7f, r9
+	/*
+	 * Check the trap type
+	 */
+	mov	#((0x20 << 2) - 1), r9
 	cmp/hi	r9, r8
-	bt/s	not_syscall_tra
+	bt/s	debug_trap		! it's a debug trap..
 	 mov	#OFF_TRA, r9
 	add	r15, r9
 	mov.l	r8, @r9			! set TRA value to tra
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c
index 28ec748..66626c0 100644
--- a/arch/sh/kernel/io_generic.c
+++ b/arch/sh/kernel/io_generic.c
@@ -1,9 +1,8 @@
-/* $Id: io_generic.c,v 1.2 2003/05/04 19:29:53 lethal Exp $
- *
- * linux/arch/sh/kernel/io_generic.c
+/*
+ * arch/sh/kernel/io_generic.c
  *
  * Copyright (C) 2000  Niibe Yutaka
- * Copyright (C) 2005  Paul Mundt
+ * Copyright (C) 2005 - 2007 Paul Mundt
  *
  * Generic I/O routine. These can be used where a machine specific version
  * is not required.
@@ -13,8 +12,9 @@
  * for more details.
  */
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/machvec.h>
+#include <asm/cacheflush.h>
 
 #ifdef CONFIG_CPU_SH3
 /* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a
@@ -96,6 +96,7 @@
 	while (count--)
 		*buf++ = *port_addr;
 
+	flush_dcache_all();
 	dummy_read();
 }
 
@@ -170,6 +171,7 @@
 	while (count--)
 		*port_addr = *buf++;
 
+	flush_dcache_all();
 	dummy_read();
 }
 
diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c
index 9c6315f..d8927d8 100644
--- a/arch/sh/kernel/kgdb_stub.c
+++ b/arch/sh/kernel/kgdb_stub.c
@@ -1323,8 +1323,11 @@
 }
 
 /* There has been an exception, most likely a breakpoint. */
-void kgdb_handle_exception(struct pt_regs *regs)
+asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5,
+				      unsigned long r6, unsigned long r7,
+				      struct pt_regs __regs)
 {
+	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 	int excep_code, vbr_val;
 	int count;
 	int trapa_value = ctrl_inl(TRA);
@@ -1368,8 +1371,6 @@
 
 	vbr_val = trap_registers.vbr;
 	asm("ldc %0, vbr": :"r"(vbr_val));
-
-	return;
 }
 
 /* Trigger a breakpoint by function */
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 486c06e..9d6a438 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -1,42 +1,30 @@
-/* $Id: process.c,v 1.28 2004/05/05 16:54:23 lethal Exp $
+/*
+ * arch/sh/kernel/process.c
  *
- *  linux/arch/sh/kernel/process.c
+ * This file handles the architecture-dependent parts of process handling..
  *
  *  Copyright (C) 1995  Linus Torvalds
  *
  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
  *		     Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
+ *		     Copyright (C) 2002 - 2006  Paul Mundt
  */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
- */
-
 #include <linux/module.h>
-#include <linux/unistd.h>
 #include <linux/mm.h>
 #include <linux/elfcore.h>
-#include <linux/a.out.h>
-#include <linux/slab.h>
 #include <linux/pm.h>
-#include <linux/ptrace.h>
 #include <linux/kallsyms.h>
 #include <linux/kexec.h>
-
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
-#include <asm/elf.h>
 #include <asm/ubc.h>
 
-static int hlt_counter=0;
-
+static int hlt_counter;
 int ubc_usercnt = 0;
 
 #define HARD_IDLE_TIMEOUT (HZ / 3)
 
 void (*pm_idle)(void);
-
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
@@ -44,14 +32,12 @@
 {
 	hlt_counter++;
 }
-
 EXPORT_SYMBOL(disable_hlt);
 
 void enable_hlt(void)
 {
 	hlt_counter--;
 }
-
 EXPORT_SYMBOL(enable_hlt);
 
 void default_idle(void)
@@ -152,19 +138,21 @@
 	".align 2\n\t"
 	"1:.long do_exit");
 
+/* Don't use this in BL=1(cli).  Or else, CPU resets! */
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{	/* Don't use this in BL=1(cli).  Or else, CPU resets! */
+{
 	struct pt_regs regs;
 
 	memset(&regs, 0, sizeof(regs));
-	regs.regs[4] = (unsigned long) arg;
-	regs.regs[5] = (unsigned long) fn;
+	regs.regs[4] = (unsigned long)arg;
+	regs.regs[5] = (unsigned long)fn;
 
-	regs.pc = (unsigned long) kernel_thread_helper;
+	regs.pc = (unsigned long)kernel_thread_helper;
 	regs.sr = (1 << 30);
 
 	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
+		       &regs, 0, NULL, NULL);
 }
 
 /*
@@ -211,21 +199,20 @@
 	return fpvalid;
 }
 
-/* 
+/*
  * Capture the user space registers if the task is not running (in user space)
  */
 int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
 {
 	struct pt_regs ptregs;
-	
+
 	ptregs = *task_pt_regs(tsk);
 	elf_core_copy_regs(regs, &ptregs);
 
 	return 1;
 }
 
-int
-dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu)
+int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpu)
 {
 	int fpvalid = 0;
 
@@ -263,12 +250,14 @@
 		childregs->regs[15] = usp;
 		ti->addr_limit = USER_DS;
 	} else {
-		childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+		childregs->regs[15] = (unsigned long)task_stack_page(p) +
+							THREAD_SIZE;
 		ti->addr_limit = KERNEL_DS;
 	}
-        if (clone_flags & CLONE_SETTLS) {
+
+        if (clone_flags & CLONE_SETTLS)
 		childregs->gbr = childregs->regs[0];
-	}
+
 	childregs->regs[0] = 0; /* Set return value for child */
 
 	p->thread.sp = (unsigned long) childregs;
@@ -280,8 +269,7 @@
 }
 
 /* Tracing by user break controller.  */
-static void
-ubc_set_tracing(int asid, unsigned long pc)
+static void ubc_set_tracing(int asid, unsigned long pc)
 {
 #if defined(CONFIG_CPU_SH4A)
 	unsigned long val;
@@ -297,7 +285,7 @@
 	val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);
 	ctrl_outl(val, UBC_CRR0);
 
-	/* Read UBC register that we writed last. For chekking UBC Register changed */
+	/* Read UBC register that we wrote last, for checking update */
 	val = ctrl_inl(UBC_CRR0);
 
 #else	/* CONFIG_CPU_SH4A */
@@ -305,13 +293,14 @@
 
 #ifdef CONFIG_MMU
 	/* We don't have any ASID settings for the SH-2! */
-	if (cpu_data->type != CPU_SH7604)
+	if (current_cpu_data.type != CPU_SH7604)
 		ctrl_outb(asid, UBC_BASRA);
 #endif
 
 	ctrl_outl(0, UBC_BAMRA);
 
-	if (cpu_data->type == CPU_SH7729 || cpu_data->type == CPU_SH7710) {
+	if (current_cpu_data.type == CPU_SH7729 ||
+	    current_cpu_data.type == CPU_SH7710) {
 		ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
 		ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
 	} else {
@@ -325,7 +314,8 @@
  *	switch_to(x,y) should switch tasks from x to y.
  *
  */
-struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next)
+struct task_struct *__switch_to(struct task_struct *prev,
+				struct task_struct *next)
 {
 #if defined(CONFIG_SH_FPU)
 	unlazy_fpu(prev, task_pt_regs(prev));
@@ -354,7 +344,7 @@
 #ifdef CONFIG_MMU
 	/*
 	 * Restore the kernel mode register
-	 *   	k7 (r7_bank1)
+	 *	k7 (r7_bank1)
 	 */
 	asm volatile("ldc	%0, r7_bank"
 		     : /* no output */
@@ -367,7 +357,7 @@
 	else if (next->thread.ubc_pc && next->mm) {
 		int asid = 0;
 #ifdef CONFIG_MMU
-		asid |= next->mm->context.id & MMU_CONTEXT_ASID_MASK;
+		asid |= cpu_asid(smp_processor_id(), next->mm);
 #endif
 		ubc_set_tracing(asid, next->thread.ubc_pc);
 	} else {
@@ -405,7 +395,8 @@
 	if (!newsp)
 		newsp = regs->regs[15];
 	return do_fork(clone_flags, newsp, regs, 0,
-			(int __user *)parent_tidptr, (int __user *)child_tidptr);
+			(int __user *)parent_tidptr,
+			(int __user *)child_tidptr);
 }
 
 /*
@@ -493,9 +484,27 @@
 	force_sig(SIGTRAP, current);
 }
 
-asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
-					  unsigned long r6, unsigned long r7,
-					  struct pt_regs __regs)
+/*
+ * Generic trap handler.
+ */
+asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
+				   unsigned long r6, unsigned long r7,
+				   struct pt_regs __regs)
+{
+	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+
+	/* Rewind */
+	regs->pc -= 2;
+
+	force_sig(SIGTRAP, current);
+}
+
+/*
+ * Special handler for BUG() traps.
+ */
+asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
+				 unsigned long r6, unsigned long r7,
+				 struct pt_regs __regs)
 {
 	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 225f9ea..98802ab 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -1,14 +1,11 @@
 /*
- *  linux/arch/sh/kernel/setup.c
+ * arch/sh/kernel/setup.c
+ *
+ * This file handles the architecture-dependent parts of initialization
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2002, 2003  Paul Mundt
+ *  Copyright (C) 2002 - 2006 Paul Mundt
  */
-
-/*
- * This file handles the architecture-dependent parts of initialization
- */
-
 #include <linux/screen_info.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
@@ -75,7 +72,7 @@
 #define RAMDISK_PROMPT_FLAG		0x8000
 #define RAMDISK_LOAD_FLAG		0x4000
 
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
+static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, };
 
 static struct resource code_resource = { .name = "Kernel code", };
 static struct resource data_resource = { .name = "Kernel data", };
@@ -90,8 +87,8 @@
 	int len = 0;
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
 	memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
 	memory_end = memory_start + __MEMORY_SIZE;
@@ -395,9 +392,9 @@
 	[CPU_SH_NONE]	= "Unknown"
 };
 
-const char *get_cpu_subtype(void)
+const char *get_cpu_subtype(struct sh_cpuinfo *c)
 {
-	return cpu_name[boot_cpu_data.type];
+	return cpu_name[c->type];
 }
 
 #ifdef CONFIG_PROC_FS
@@ -407,19 +404,19 @@
 	"ptea", "llsc", "l2", NULL
 };
 
-static void show_cpuflags(struct seq_file *m)
+static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
 {
 	unsigned long i;
 
 	seq_printf(m, "cpu flags\t:");
 
-	if (!cpu_data->flags) {
+	if (!c->flags) {
 		seq_printf(m, " %s\n", cpu_flags[0]);
 		return;
 	}
 
 	for (i = 0; cpu_flags[i]; i++)
-		if ((cpu_data->flags & (1 << i)))
+		if ((c->flags & (1 << i)))
 			seq_printf(m, " %s", cpu_flags[i+1]);
 
 	seq_printf(m, "\n");
@@ -441,16 +438,20 @@
  */
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-	unsigned int cpu = smp_processor_id();
+	struct sh_cpuinfo *c = v;
+	unsigned int cpu = c - cpu_data;
 
-	if (!cpu && cpu_online(cpu))
+	if (!cpu_online(cpu))
+		return 0;
+
+	if (cpu == 0)
 		seq_printf(m, "machine\t\t: %s\n", get_system_type());
 
 	seq_printf(m, "processor\t: %d\n", cpu);
 	seq_printf(m, "cpu family\t: %s\n", init_utsname()->machine);
-	seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype());
+	seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype(c));
 
-	show_cpuflags(m);
+	show_cpuflags(m, c);
 
 	seq_printf(m, "cache type\t: ");
 
@@ -459,22 +460,22 @@
 	 * unified cache on the SH-2 and SH-3, as well as the harvard
 	 * style cache on the SH-4.
 	 */
-	if (boot_cpu_data.icache.flags & SH_CACHE_COMBINED) {
+	if (c->icache.flags & SH_CACHE_COMBINED) {
 		seq_printf(m, "unified\n");
-		show_cacheinfo(m, "cache", boot_cpu_data.icache);
+		show_cacheinfo(m, "cache", c->icache);
 	} else {
 		seq_printf(m, "split (harvard)\n");
-		show_cacheinfo(m, "icache", boot_cpu_data.icache);
-		show_cacheinfo(m, "dcache", boot_cpu_data.dcache);
+		show_cacheinfo(m, "icache", c->icache);
+		show_cacheinfo(m, "dcache", c->dcache);
 	}
 
 	/* Optional secondary cache */
-	if (boot_cpu_data.flags & CPU_HAS_L2_CACHE)
-		show_cacheinfo(m, "scache", boot_cpu_data.scache);
+	if (c->flags & CPU_HAS_L2_CACHE)
+		show_cacheinfo(m, "scache", c->scache);
 
 	seq_printf(m, "bogomips\t: %lu.%02lu\n",
-		     boot_cpu_data.loops_per_jiffy/(500000/HZ),
-		     (boot_cpu_data.loops_per_jiffy/(5000/HZ)) % 100);
+		     c->loops_per_jiffy/(500000/HZ),
+		     (c->loops_per_jiffy/(5000/HZ)) % 100);
 
 	return show_clocks(m);
 }
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index e610623..fe1b276 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -105,7 +105,6 @@
 EXPORT_SYMBOL(clear_user_page);
 #endif
 
-EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(__down_trylock);
 
 #ifdef CONFIG_SMP
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index 379c88b..32f10a0 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -127,7 +127,7 @@
 {
 	struct task_struct *tsk = current;
 
-	if (!(cpu_data->flags & CPU_HAS_FPU))
+	if (!(current_cpu_data.flags & CPU_HAS_FPU))
 		return 0;
 
 	set_used_math();
@@ -140,7 +140,7 @@
 {
 	struct task_struct *tsk = current;
 
-	if (!(cpu_data->flags & CPU_HAS_FPU))
+	if (!(current_cpu_data.flags & CPU_HAS_FPU))
 		return 0;
 
 	if (!used_math()) {
@@ -181,7 +181,7 @@
 #undef COPY
 
 #ifdef CONFIG_SH_FPU
-	if (cpu_data->flags & CPU_HAS_FPU) {
+	if (current_cpu_data.flags & CPU_HAS_FPU) {
 		int owned_fp;
 		struct task_struct *tsk = current;
 
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
index ca81976..38fc8cd 100644
--- a/arch/sh/kernel/syscalls.S
+++ b/arch/sh/kernel/syscalls.S
@@ -319,15 +319,15 @@
 	.long sys_mq_getsetattr
 	.long sys_kexec_load
 	.long sys_waitid
-	.long sys_ni_syscall		/* 285 */
-	.long sys_add_key
+	.long sys_add_key		/* 285 */
 	.long sys_request_key
 	.long sys_keyctl
 	.long sys_ioprio_set
-	.long sys_ioprio_get		/* 290 */
-	.long sys_inotify_init
+	.long sys_ioprio_get
+	.long sys_inotify_init		/* 290 */
 	.long sys_inotify_add_watch
 	.long sys_inotify_rm_watch
+	.long sys_ni_syscall
 	.long sys_migrate_pages
 	.long sys_openat		/* 295 */
 	.long sys_mkdirat
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index c206c95..d47e775 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -41,14 +41,6 @@
 void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
 int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
 
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long __attribute__ ((weak)) sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
 #ifndef CONFIG_GENERIC_TIME
 void do_gettimeofday(struct timeval *tv)
 {
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index ec11015..e9f168f 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -156,13 +156,13 @@
 {
 }
 #endif /* CONFIG_DEBUG_BUGVERBOSE */
-#endif /* CONFIG_BUG */
 
 void handle_BUG(struct pt_regs *regs)
 {
 	do_bug_verbose(regs);
 	die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
 }
+#endif /* CONFIG_BUG */
 
 /*
  * handle an instruction that does an unaligned memory access by emulating the
@@ -641,7 +641,7 @@
 	 * Safe guard if DSP mode is already enabled or we're lacking
 	 * the DSP altogether.
 	 */
-	if (!(cpu_data->flags & CPU_HAS_DSP) || (regs->sr & SR_DSP))
+	if (!(current_cpu_data.flags & CPU_HAS_DSP) || (regs->sr & SR_DSP))
 		return 0;
 
 	get_user(inst, ((unsigned short *) regs->pc));
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index f34bdcc..75de165 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -83,9 +83,13 @@
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
   SECURITY_INIT
+
+#ifdef CONFIG_BLK_DEV_INITRD
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
+
   __machvec_start = .;
   .init.machvec : { *(.init.machvec) }
   __machvec_end = .;
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c
index deb4694..7b0f66f 100644
--- a/arch/sh/kernel/vsyscall/vsyscall.c
+++ b/arch/sh/kernel/vsyscall/vsyscall.c
@@ -37,11 +37,12 @@
  * of the ELF DSO images included therein.
  */
 extern const char vsyscall_trapa_start, vsyscall_trapa_end;
-static void *syscall_page;
+static struct page *syscall_pages[1];
 
 int __init vsyscall_init(void)
 {
-	syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+	void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+	syscall_pages[0] = virt_to_page(syscall_page);
 
 	/*
 	 * XXX: Map this page to a fixmap entry if we get around
@@ -55,37 +56,10 @@
 	return 0;
 }
 
-static struct page *syscall_vma_nopage(struct vm_area_struct *vma,
-				       unsigned long address, int *type)
-{
-	unsigned long offset = address - vma->vm_start;
-	struct page *page;
-
-	if (address < vma->vm_start || address > vma->vm_end)
-		return NOPAGE_SIGBUS;
-
-	page = virt_to_page(syscall_page + offset);
-
-	get_page(page);
-
-	return page;
-}
-
-/* Prevent VMA merging */
-static void syscall_vma_close(struct vm_area_struct *vma)
-{
-}
-
-static struct vm_operations_struct syscall_vm_ops = {
-	.nopage	= syscall_vma_nopage,
-	.close	= syscall_vma_close,
-};
-
 /* Setup a VMA at program startup for the vsyscall page */
 int arch_setup_additional_pages(struct linux_binprm *bprm,
 				int executable_stack)
 {
-	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
 	unsigned long addr;
 	int ret;
@@ -97,30 +71,16 @@
 		goto up_fail;
 	}
 
-	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
-	if (!vma) {
-		ret = -ENOMEM;
+	ret = install_special_mapping(mm, addr, PAGE_SIZE,
+				      VM_READ | VM_EXEC |
+				      VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC |
+				      VM_ALWAYSDUMP,
+				      syscall_pages);
+	if (unlikely(ret))
 		goto up_fail;
-	}
-
-	vma->vm_start = addr;
-	vma->vm_end = addr + PAGE_SIZE;
-	/* MAYWRITE to allow gdb to COW and set breakpoints */
-	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
-	vma->vm_flags |= mm->def_flags;
-	vma->vm_page_prot = protection_map[vma->vm_flags & 7];
-	vma->vm_ops = &syscall_vm_ops;
-	vma->vm_mm = mm;
-
-	ret = insert_vm_struct(mm, vma);
-	if (unlikely(ret)) {
-		kmem_cache_free(vm_area_cachep, vma);
-		goto up_fail;
-	}
 
 	current->mm->context.vdso = (void *)addr;
 
-	mm->total_vm++;
 up_fail:
 	up_write(&mm->mmap_sem);
 	return ret;
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 29f4ee3..6b0d28a 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -20,7 +20,7 @@
 	bool
 	select CPU_HAS_INTEVT
 	select CPU_HAS_SR_RB
-	select CPU_HAS_PTEA if !CPU_SUBTYPE_ST40
+	select CPU_HAS_PTEA if (!CPU_SUBTYPE_ST40 && !CPU_SH4A) || CPU_SHX2
 
 config CPU_SH4A
 	bool
@@ -72,6 +72,7 @@
 config CPU_SUBTYPE_SH7706
 	bool "Support SH7706 processor"
 	select CPU_SH3
+	select CPU_HAS_IPR_IRQ
 	help
 	  Select SH7706 if you have a 133 Mhz SH-3 HD6417706 CPU.
 
@@ -92,6 +93,7 @@
 config CPU_SUBTYPE_SH7709
 	bool "Support SH7709 processor"
 	select CPU_SH3
+	select CPU_HAS_IPR_IRQ
 	select CPU_HAS_PINT_IRQ
 	help
 	  Select SH7709 if you have a  80 Mhz SH-3 HD6417709 CPU.
@@ -149,6 +151,7 @@
 	bool "Support SH7760 processor"
 	select CPU_SH4
 	select CPU_HAS_INTC2_IRQ
+	select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH4_202
 	bool "Support SH4-202 processor"
diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
index e0122bd..de6d2c9 100644
--- a/arch/sh/mm/cache-debugfs.c
+++ b/arch/sh/mm/cache-debugfs.c
@@ -46,10 +46,10 @@
 
 	if (cache_type == CACHE_TYPE_DCACHE) {
 		base = CACHE_OC_ADDRESS_ARRAY;
-		cache = &cpu_data->dcache;
+		cache = &current_cpu_data.dcache;
 	} else {
 		base = CACHE_IC_ADDRESS_ARRAY;
-		cache = &cpu_data->icache;
+		cache = &current_cpu_data.icache;
 	}
 
 	/*
@@ -114,7 +114,7 @@
 	return single_open(file, cache_seq_show, inode->i_private);
 }
 
-static struct file_operations cache_debugfs_fops = {
+static const struct file_operations cache_debugfs_fops = {
 	.owner		= THIS_MODULE,
 	.open		= cache_debugfs_open,
 	.read		= seq_read,
diff --git a/arch/sh/mm/cache-sh3.c b/arch/sh/mm/cache-sh3.c
index 838731f..6d1dbec 100644
--- a/arch/sh/mm/cache-sh3.c
+++ b/arch/sh/mm/cache-sh3.c
@@ -44,11 +44,11 @@
 
 	for (v = begin; v < end; v+=L1_CACHE_BYTES) {
 		unsigned long addrstart = CACHE_OC_ADDRESS_ARRAY;
-		for (j = 0; j < cpu_data->dcache.ways; j++) {
+		for (j = 0; j < current_cpu_data.dcache.ways; j++) {
 			unsigned long data, addr, p;
 
 			p = __pa(v);
-			addr = addrstart | (v & cpu_data->dcache.entry_mask);
+			addr = addrstart | (v & current_cpu_data.dcache.entry_mask);
 			local_irq_save(flags);
 			data = ctrl_inl(addr);
 
@@ -60,7 +60,7 @@
 				break;
 			}
 			local_irq_restore(flags);
-			addrstart += cpu_data->dcache.way_incr;
+			addrstart += current_cpu_data.dcache.way_incr;
 		}
 	}
 }
@@ -85,7 +85,7 @@
 
 		data = (v & 0xfffffc00); /* _Virtual_ address, ~U, ~V */
 		addr = CACHE_OC_ADDRESS_ARRAY |
-			(v & cpu_data->dcache.entry_mask) | SH_CACHE_ASSOC;
+			(v & current_cpu_data.dcache.entry_mask) | SH_CACHE_ASSOC;
 		ctrl_outl(data, addr);
 	}
 }
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index c695515..e0cd4b7 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -54,21 +54,21 @@
 		ctrl_inl(CCN_CVR),
 		ctrl_inl(CCN_PRR));
 	printk("I-cache : n_ways=%d n_sets=%d way_incr=%d\n",
-		cpu_data->icache.ways,
-		cpu_data->icache.sets,
-		cpu_data->icache.way_incr);
+		current_cpu_data.icache.ways,
+		current_cpu_data.icache.sets,
+		current_cpu_data.icache.way_incr);
 	printk("I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
-		cpu_data->icache.entry_mask,
-		cpu_data->icache.alias_mask,
-		cpu_data->icache.n_aliases);
+		current_cpu_data.icache.entry_mask,
+		current_cpu_data.icache.alias_mask,
+		current_cpu_data.icache.n_aliases);
 	printk("D-cache : n_ways=%d n_sets=%d way_incr=%d\n",
-		cpu_data->dcache.ways,
-		cpu_data->dcache.sets,
-		cpu_data->dcache.way_incr);
+		current_cpu_data.dcache.ways,
+		current_cpu_data.dcache.sets,
+		current_cpu_data.dcache.way_incr);
 	printk("D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
-		cpu_data->dcache.entry_mask,
-		cpu_data->dcache.alias_mask,
-		cpu_data->dcache.n_aliases);
+		current_cpu_data.dcache.entry_mask,
+		current_cpu_data.dcache.alias_mask,
+		current_cpu_data.dcache.n_aliases);
 
 	if (!__flush_dcache_segment_fn)
 		panic("unknown number of cache ways\n");
@@ -87,10 +87,10 @@
 {
 	int i;
 
-	compute_alias(&cpu_data->icache);
-	compute_alias(&cpu_data->dcache);
+	compute_alias(&current_cpu_data.icache);
+	compute_alias(&current_cpu_data.dcache);
 
-	switch (cpu_data->dcache.ways) {
+	switch (current_cpu_data.dcache.ways) {
 	case 1:
 		__flush_dcache_segment_fn = __flush_dcache_segment_1way;
 		break;
@@ -110,7 +110,7 @@
 	if (ioremap_page_range(P3SEG, P3SEG + (PAGE_SIZE * 4), 0, PAGE_KERNEL))
 		panic("%s failed.", __FUNCTION__);
 
-	for (i = 0; i < cpu_data->dcache.n_aliases; i++)
+	for (i = 0; i < current_cpu_data.dcache.n_aliases; i++)
 		mutex_init(&p3map_mutex[i]);
 }
 
@@ -200,13 +200,14 @@
 		     : /* no output */
 		     : "m" (__m(v)));
 
-	index = CACHE_IC_ADDRESS_ARRAY | (v & cpu_data->icache.entry_mask);
+	index = CACHE_IC_ADDRESS_ARRAY |
+			(v & current_cpu_data.icache.entry_mask);
 
 	local_irq_save(flags);
 	jump_to_P2();
 
-	for (i = 0; i < cpu_data->icache.ways;
-	     i++, index += cpu_data->icache.way_incr)
+	for (i = 0; i < current_cpu_data.icache.ways;
+	     i++, index += current_cpu_data.icache.way_incr)
 		ctrl_outl(0, index);	/* Clear out Valid-bit */
 
 	back_to_P1();
@@ -223,7 +224,7 @@
 	 * All types of SH-4 require PC to be in P2 to operate on the I-cache.
 	 * Some types of SH-4 require PC to be in P2 to operate on the D-cache.
 	 */
-	if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) ||
+	if ((current_cpu_data.flags & CPU_HAS_P2_FLUSH_BUG) ||
 	    (start < CACHE_OC_ADDRESS_ARRAY))
 		exec_offset = 0x20000000;
 
@@ -236,16 +237,26 @@
 /*
  * Write back & invalidate the D-cache of the page.
  * (To avoid "alias" issues)
+ *
+ * This uses a lazy write-back on UP, which is explicitly
+ * disabled on SMP.
  */
 void flush_dcache_page(struct page *page)
 {
-	if (test_bit(PG_mapped, &page->flags)) {
+#ifndef CONFIG_SMP
+	struct address_space *mapping = page_mapping(page);
+
+	if (mapping && !mapping_mapped(mapping))
+		set_bit(PG_dcache_dirty, &page->flags);
+	else
+#endif
+	{
 		unsigned long phys = PHYSADDR(page_address(page));
 		unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
 		int i, n;
 
 		/* Loop all the D-cache */
-		n = cpu_data->dcache.n_aliases;
+		n = current_cpu_data.dcache.n_aliases;
 		for (i = 0; i < n; i++, addr += 4096)
 			flush_cache_4096(addr, phys);
 	}
@@ -277,7 +288,7 @@
 
 void flush_dcache_all(void)
 {
-	(*__flush_dcache_segment_fn)(0UL, cpu_data->dcache.way_size);
+	(*__flush_dcache_segment_fn)(0UL, current_cpu_data.dcache.way_size);
 	wmb();
 }
 
@@ -291,8 +302,8 @@
 			     unsigned long end)
 {
 	unsigned long d = 0, p = start & PAGE_MASK;
-	unsigned long alias_mask = cpu_data->dcache.alias_mask;
-	unsigned long n_aliases = cpu_data->dcache.n_aliases;
+	unsigned long alias_mask = current_cpu_data.dcache.alias_mask;
+	unsigned long n_aliases = current_cpu_data.dcache.n_aliases;
 	unsigned long select_bit;
 	unsigned long all_aliases_mask;
 	unsigned long addr_offset;
@@ -379,7 +390,7 @@
 	 * If cache is only 4k-per-way, there are never any 'aliases'.  Since
 	 * the cache is physically tagged, the data can just be left in there.
 	 */
-	if (cpu_data->dcache.n_aliases == 0)
+	if (current_cpu_data.dcache.n_aliases == 0)
 		return;
 
 	/*
@@ -416,7 +427,7 @@
 	unsigned long phys = pfn << PAGE_SHIFT;
 	unsigned int alias_mask;
 
-	alias_mask = cpu_data->dcache.alias_mask;
+	alias_mask = current_cpu_data.dcache.alias_mask;
 
 	/* We only need to flush D-cache when we have alias */
 	if ((address^phys) & alias_mask) {
@@ -430,7 +441,7 @@
 			phys);
 	}
 
-	alias_mask = cpu_data->icache.alias_mask;
+	alias_mask = current_cpu_data.icache.alias_mask;
 	if (vma->vm_flags & VM_EXEC) {
 		/*
 		 * Evict entries from the portion of the cache from which code
@@ -462,7 +473,7 @@
 	 * If cache is only 4k-per-way, there are never any 'aliases'.  Since
 	 * the cache is physically tagged, the data can just be left in there.
 	 */
-	if (cpu_data->dcache.n_aliases == 0)
+	if (current_cpu_data.dcache.n_aliases == 0)
 		return;
 
 	/*
@@ -523,7 +534,7 @@
 	unsigned long a, ea, p;
 	unsigned long temp_pc;
 
-	dcache = &cpu_data->dcache;
+	dcache = &current_cpu_data.dcache;
 	/* Write this way for better assembly. */
 	way_count = dcache->ways;
 	way_incr = dcache->way_incr;
@@ -598,7 +609,7 @@
 	base_addr = ((base_addr >> 16) << 16);
 	base_addr |= start;
 
-	dcache = &cpu_data->dcache;
+	dcache = &current_cpu_data.dcache;
 	linesz = dcache->linesz;
 	way_incr = dcache->way_incr;
 	way_size = dcache->way_size;
@@ -640,7 +651,7 @@
 	base_addr = ((base_addr >> 16) << 16);
 	base_addr |= start;
 
-	dcache = &cpu_data->dcache;
+	dcache = &current_cpu_data.dcache;
 	linesz = dcache->linesz;
 	way_incr = dcache->way_incr;
 	way_size = dcache->way_size;
@@ -699,7 +710,7 @@
 	base_addr = ((base_addr >> 16) << 16);
 	base_addr |= start;
 
-	dcache = &cpu_data->dcache;
+	dcache = &current_cpu_data.dcache;
 	linesz = dcache->linesz;
 	way_incr = dcache->way_incr;
 	way_size = dcache->way_size;
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
index 045abdf..31f8deb 100644
--- a/arch/sh/mm/cache-sh7705.c
+++ b/arch/sh/mm/cache-sh7705.c
@@ -3,11 +3,11 @@
  *
  * Copyright (C) 1999, 2000  Niibe Yutaka
  * Copyright (C) 2004  Alex Song
+ * Copyright (C) 2006  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
- *
  */
 #include <linux/init.h>
 #include <linux/mman.h>
@@ -32,9 +32,9 @@
 {
 	unsigned long ways, waysize, addrstart;
 
-	ways = cpu_data->dcache.ways;
-	waysize = cpu_data->dcache.sets;
-	waysize <<= cpu_data->dcache.entry_shift;
+	ways = current_cpu_data.dcache.ways;
+	waysize = current_cpu_data.dcache.sets;
+	waysize <<= current_cpu_data.dcache.entry_shift;
 
 	addrstart = CACHE_OC_ADDRESS_ARRAY;
 
@@ -43,7 +43,7 @@
 
 		for (addr = addrstart;
 		     addr < addrstart + waysize;
-		     addr += cpu_data->dcache.linesz) {
+		     addr += current_cpu_data.dcache.linesz) {
 			unsigned long data;
 			int v = SH_CACHE_UPDATED | SH_CACHE_VALID;
 
@@ -51,10 +51,9 @@
 
 			if ((data & v) == v)
 				ctrl_outl(data & ~v, addr);
-
 		}
 
-		addrstart += cpu_data->dcache.way_incr;
+		addrstart += current_cpu_data.dcache.way_incr;
 	} while (--ways);
 }
 
@@ -94,9 +93,9 @@
 	local_irq_save(flags);
 	jump_to_P2();
 
-	ways = cpu_data->dcache.ways;
-	waysize = cpu_data->dcache.sets;
-	waysize <<= cpu_data->dcache.entry_shift;
+	ways = current_cpu_data.dcache.ways;
+	waysize = current_cpu_data.dcache.sets;
+	waysize <<= current_cpu_data.dcache.entry_shift;
 
 	addrstart = CACHE_OC_ADDRESS_ARRAY;
 
@@ -105,7 +104,7 @@
 
 		for (addr = addrstart;
 		     addr < addrstart + waysize;
-		     addr += cpu_data->dcache.linesz) {
+		     addr += current_cpu_data.dcache.linesz) {
 			unsigned long data;
 
 			data = ctrl_inl(addr) & (0x1ffffC00 | SH_CACHE_VALID);
@@ -115,7 +114,7 @@
 			}
 		}
 
-		addrstart += cpu_data->dcache.way_incr;
+		addrstart += current_cpu_data.dcache.way_incr;
 	} while (--ways);
 
 	back_to_P1();
@@ -128,7 +127,11 @@
  */
 void flush_dcache_page(struct page *page)
 {
-	if (test_bit(PG_mapped, &page->flags))
+	struct address_space *mapping = page_mapping(page);
+
+	if (mapping && !mapping_mapped(mapping))
+		set_bit(PG_dcache_dirty, &page->flags);
+	else
 		__flush_dcache_page(PHYSADDR(page_address(page)));
 }
 
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 716ebf5..fa5d7f0 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -17,6 +17,7 @@
 #include <linux/kprobes.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
 #include <asm/kgdb.h>
 
 extern void die(const char *,struct pt_regs *,long);
@@ -224,3 +225,89 @@
 	if (!user_mode(regs))
 		goto no_context;
 }
+
+#ifdef CONFIG_SH_STORE_QUEUES
+/*
+ * This is a special case for the SH-4 store queues, as pages for this
+ * space still need to be faulted in before it's possible to flush the
+ * store queue cache for writeout to the remapped region.
+ */
+#define P3_ADDR_MAX		(P4SEG_STORE_QUE + 0x04000000)
+#else
+#define P3_ADDR_MAX		P4SEG
+#endif
+
+/*
+ * Called with interrupts disabled.
+ */
+asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
+					 unsigned long writeaccess,
+					 unsigned long address)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+	pte_t entry;
+	struct mm_struct *mm = current->mm;
+	spinlock_t *ptl;
+	int ret = 1;
+
+#ifdef CONFIG_SH_KGDB
+	if (kgdb_nofault && kgdb_bus_err_hook)
+		kgdb_bus_err_hook();
+#endif
+
+	/*
+	 * We don't take page faults for P1, P2, and parts of P4, these
+	 * are always mapped, whether it be due to legacy behaviour in
+	 * 29-bit mode, or due to PMB configuration in 32-bit mode.
+	 */
+	if (address >= P3SEG && address < P3_ADDR_MAX) {
+		pgd = pgd_offset_k(address);
+		mm = NULL;
+	} else {
+		if (unlikely(address >= TASK_SIZE || !mm))
+			return 1;
+
+		pgd = pgd_offset(mm, address);
+	}
+
+	pud = pud_offset(pgd, address);
+	if (pud_none_or_clear_bad(pud))
+		return 1;
+	pmd = pmd_offset(pud, address);
+	if (pmd_none_or_clear_bad(pmd))
+		return 1;
+
+	if (mm)
+		pte = pte_offset_map_lock(mm, pmd, address, &ptl);
+	else
+		pte = pte_offset_kernel(pmd, address);
+
+	entry = *pte;
+	if (unlikely(pte_none(entry) || pte_not_present(entry)))
+		goto unlock;
+	if (unlikely(writeaccess && !pte_write(entry)))
+		goto unlock;
+
+	if (writeaccess)
+		entry = pte_mkdirty(entry);
+	entry = pte_mkyoung(entry);
+
+#ifdef CONFIG_CPU_SH4
+	/*
+	 * ITLB is not affected by "ldtlb" instruction.
+	 * So, we need to flush the entry by ourselves.
+	 */
+	local_flush_tlb_one(get_asid(), address & PAGE_MASK);
+#endif
+
+	set_pte(pte, entry);
+	update_mmu_cache(NULL, address, entry);
+	ret = 0;
+unlock:
+	if (mm)
+		pte_unmap_unlock(pte, ptl);
+	return ret;
+}
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 29bd37b..ae957a9 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -39,11 +39,6 @@
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
-/*
- * Cache of MMU context last used.
- */
-unsigned long mmu_context_cache = NO_CONTEXT;
-
 #ifdef CONFIG_MMU
 /* It'd be good if these lines were in the standard header file. */
 #define START_PFN	(NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
@@ -111,7 +106,7 @@
 
 	set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
 
-	__flush_tlb_page(get_asid(), addr);
+	flush_tlb_one(get_asid(), addr);
 }
 
 /*
@@ -158,7 +153,6 @@
 	 * Setup some defaults for the zone sizes.. these should be safe
 	 * regardless of distcontiguous memory or MMU settings.
 	 */
-	zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
 	zones_size[ZONE_NORMAL] = __MEMORY_SIZE >> PAGE_SHIFT;
 #ifdef CONFIG_HIGHMEM
 	zones_size[ZONE_HIGHMEM] = 0 >> PAGE_SHIFT;
@@ -170,8 +164,6 @@
 	 * the zone sizes accordingly, in addition to turning it on.
 	 */
 	{
-		unsigned long max_dma, low, start_pfn;
-
 		/* We don't need to map the kernel through the TLB, as
 		 * it is permanatly mapped using P1. So clear the
 		 * entire pgd. */
@@ -179,19 +171,7 @@
 
 		/* Turn on the MMU */
 		enable_mmu();
-
-		/* Fixup the zone sizes */
-		start_pfn = START_PFN;
-		max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-		low = MAX_LOW_PFN;
-
-		if (low < max_dma) {
-			zones_size[ZONE_DMA] = low - start_pfn;
-			zones_size[ZONE_NORMAL] = 0;
-		} else {
-			zones_size[ZONE_DMA] = max_dma - start_pfn;
-			zones_size[ZONE_NORMAL] = low - max_dma;
-		}
+		zones_size[ZONE_NORMAL] = MAX_LOW_PFN - START_PFN;
 	}
 
 	/* Set an initial value for the MMU.TTB so we don't have to
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index 90b494a..be03d74 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -45,12 +45,6 @@
 		return NULL;
 
 	/*
-	 * Don't remap the low PCI/ISA area, it's always mapped..
-	 */
-	if (phys_addr >= 0xA0000 && last_addr < 0x100000)
-		return (void __iomem *)phys_to_virt(phys_addr);
-
-	/*
 	 * If we're on an SH7751 or SH7780 PCI controller, PCI memory is
 	 * mapped at the end of the address space (typically 0xfd000000)
 	 * in a non-translatable area, so mapping through page tables for
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index 3f98d2a..969efece 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -13,7 +13,7 @@
 
 extern struct mutex p3map_mutex[];
 
-#define CACHE_ALIAS (cpu_data->dcache.alias_mask)
+#define CACHE_ALIAS (current_cpu_data.dcache.alias_mask)
 
 /*
  * clear_user_page
@@ -23,7 +23,6 @@
  */
 void clear_user_page(void *to, unsigned long address, struct page *page)
 {
-	__set_bit(PG_mapped, &page->flags);
 	if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
 		clear_page(to);
 	else {
@@ -40,7 +39,7 @@
 		mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
 		set_pte(pte, entry);
 		local_irq_save(flags);
-		__flush_tlb_page(get_asid(), p3_addr);
+		flush_tlb_one(get_asid(), p3_addr);
 		local_irq_restore(flags);
 		update_mmu_cache(NULL, p3_addr, entry);
 		__clear_user_page((void *)p3_addr, to);
@@ -59,7 +58,6 @@
 void copy_user_page(void *to, void *from, unsigned long address,
 		    struct page *page)
 {
-	__set_bit(PG_mapped, &page->flags);
 	if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
 		copy_page(to, from);
 	else {
@@ -76,7 +74,7 @@
 		mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
 		set_pte(pte, entry);
 		local_irq_save(flags);
-		__flush_tlb_page(get_asid(), p3_addr);
+		flush_tlb_one(get_asid(), p3_addr);
 		local_irq_restore(flags);
 		update_mmu_cache(NULL, p3_addr, entry);
 		__copy_user_page((void *)p3_addr, from, to);
@@ -84,23 +82,3 @@
 		mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
 	}
 }
-
-/*
- * For SH-4, we have our own implementation for ptep_get_and_clear
- */
-inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-	pte_t pte = *ptep;
-
-	pte_clear(mm, addr, ptep);
-	if (!pte_not_present(pte)) {
-		unsigned long pfn = pte_pfn(pte);
-		if (pfn_valid(pfn)) {
-			struct page *page = pfn_to_page(pfn);
-			struct address_space *mapping = page_mapping(page);
-			if (!mapping || !mapping_writably_mapped(mapping))
-				__clear_bit(PG_mapped, &page->flags);
-		}
-	}
-	return pte;
-}
diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c
index ff9ece9..887ab9d 100644
--- a/arch/sh/mm/pg-sh7705.c
+++ b/arch/sh/mm/pg-sh7705.c
@@ -7,9 +7,7 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
- *
  */
-
 #include <linux/init.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
@@ -45,13 +43,13 @@
 
 		p = __pa(p1_begin);
 
-	        ways = cpu_data->dcache.ways;
+	        ways = current_cpu_data.dcache.ways;
 		addr = CACHE_OC_ADDRESS_ARRAY;
 
 		do {
 			unsigned long data;
 
-			addr |= (v & cpu_data->dcache.entry_mask);
+			addr |= (v & current_cpu_data.dcache.entry_mask);
 
 			data = ctrl_inl(addr);
 			if ((data & CACHE_PHYSADDR_MASK) ==
@@ -60,7 +58,7 @@
 				ctrl_outl(data, addr);
 			}
 
-			addr += cpu_data->dcache.way_incr;
+			addr += current_cpu_data.dcache.way_incr;
 		} while (--ways);
 
 		p1_begin += L1_CACHE_BYTES;
@@ -76,7 +74,6 @@
 {
 	struct page *page = virt_to_page(to);
 
-	__set_bit(PG_mapped, &page->flags);
 	if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
 		clear_page(to);
 		__flush_wback_region(to, PAGE_SIZE);
@@ -95,12 +92,11 @@
  * @from: P1 address
  * @address: U0 address to be mapped
  */
-void copy_user_page(void *to, void *from, unsigned long address, struct page *pg)
+void copy_user_page(void *to, void *from, unsigned long address,
+		    struct page *pg)
 {
 	struct page *page = virt_to_page(to);
 
-
-	__set_bit(PG_mapped, &page->flags);
 	if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
 		copy_page(to, from);
 		__flush_wback_region(to, PAGE_SIZE);
@@ -112,26 +108,3 @@
 		__flush_wback_region(to, PAGE_SIZE);
 	}
 }
-
-/*
- * For SH7705, we have our own implementation for ptep_get_and_clear
- * Copied from pg-sh4.c
- */
-inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-	pte_t pte = *ptep;
-
-	pte_clear(mm, addr, ptep);
-	if (!pte_not_present(pte)) {
-		unsigned long pfn = pte_pfn(pte);
-		if (pfn_valid(pfn)) {
-			struct page *page = pfn_to_page(pfn);
-			struct address_space *mapping = page_mapping(page);
-			if (!mapping || !mapping_writably_mapped(mapping))
-				__clear_bit(PG_mapped, &page->flags);
-		}
-	}
-
-	return pte;
-}
-
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index b60ad83..d0d45e2 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -378,7 +378,7 @@
 	return single_open(file, pmb_seq_show, NULL);
 }
 
-static struct file_operations pmb_debugfs_fops = {
+static const struct file_operations pmb_debugfs_fops = {
 	.owner		= THIS_MODULE,
 	.open		= pmb_debugfs_open,
 	.read		= seq_read,
diff --git a/arch/sh/mm/tlb-flush.c b/arch/sh/mm/tlb-flush.c
index 73ec7f6..d2f7b4a 100644
--- a/arch/sh/mm/tlb-flush.c
+++ b/arch/sh/mm/tlb-flush.c
@@ -2,24 +2,28 @@
  * TLB flushing operations for SH with an MMU.
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2003  Paul Mundt
+ *  Copyright (C) 2003 - 2006  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
 #include <linux/mm.h>
+#include <linux/io.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
 
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
-	if (vma->vm_mm && vma->vm_mm->context.id != NO_CONTEXT) {
+	unsigned int cpu = smp_processor_id();
+
+	if (vma->vm_mm && cpu_context(cpu, vma->vm_mm) != NO_CONTEXT) {
 		unsigned long flags;
 		unsigned long asid;
 		unsigned long saved_asid = MMU_NO_ASID;
 
-		asid = vma->vm_mm->context.id & MMU_CONTEXT_ASID_MASK;
+		asid = cpu_asid(cpu, vma->vm_mm);
 		page &= PAGE_MASK;
 
 		local_irq_save(flags);
@@ -27,33 +31,34 @@
 			saved_asid = get_asid();
 			set_asid(asid);
 		}
-		__flush_tlb_page(asid, page);
+		local_flush_tlb_one(asid, page);
 		if (saved_asid != MMU_NO_ASID)
 			set_asid(saved_asid);
 		local_irq_restore(flags);
 	}
 }
 
-void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
-		     unsigned long end)
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+			   unsigned long end)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	unsigned int cpu = smp_processor_id();
 
-	if (mm->context.id != NO_CONTEXT) {
+	if (cpu_context(cpu, mm) != NO_CONTEXT) {
 		unsigned long flags;
 		int size;
 
 		local_irq_save(flags);
 		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 		if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
-			mm->context.id = NO_CONTEXT;
+			cpu_context(cpu, mm) = NO_CONTEXT;
 			if (mm == current->mm)
-				activate_context(mm);
+				activate_context(mm, cpu);
 		} else {
 			unsigned long asid;
 			unsigned long saved_asid = MMU_NO_ASID;
 
-			asid = mm->context.id & MMU_CONTEXT_ASID_MASK;
+			asid = cpu_asid(cpu, mm);
 			start &= PAGE_MASK;
 			end += (PAGE_SIZE - 1);
 			end &= PAGE_MASK;
@@ -62,7 +67,7 @@
 				set_asid(asid);
 			}
 			while (start < end) {
-				__flush_tlb_page(asid, start);
+				local_flush_tlb_one(asid, start);
 				start += PAGE_SIZE;
 			}
 			if (saved_asid != MMU_NO_ASID)
@@ -72,26 +77,27 @@
 	}
 }
 
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
+	unsigned int cpu = smp_processor_id();
 	unsigned long flags;
 	int size;
 
 	local_irq_save(flags);
 	size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 	if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
-		flush_tlb_all();
+		local_flush_tlb_all();
 	} else {
 		unsigned long asid;
 		unsigned long saved_asid = get_asid();
 
-		asid = init_mm.context.id & MMU_CONTEXT_ASID_MASK;
+		asid = cpu_asid(cpu, &init_mm);
 		start &= PAGE_MASK;
 		end += (PAGE_SIZE - 1);
 		end &= PAGE_MASK;
 		set_asid(asid);
 		while (start < end) {
-			__flush_tlb_page(asid, start);
+			local_flush_tlb_one(asid, start);
 			start += PAGE_SIZE;
 		}
 		set_asid(saved_asid);
@@ -99,22 +105,24 @@
 	local_irq_restore(flags);
 }
 
-void flush_tlb_mm(struct mm_struct *mm)
+void local_flush_tlb_mm(struct mm_struct *mm)
 {
+	unsigned int cpu = smp_processor_id();
+
 	/* Invalidate all TLB of this process. */
 	/* Instead of invalidating each TLB, we get new MMU context. */
-	if (mm->context.id != NO_CONTEXT) {
+	if (cpu_context(cpu, mm) != NO_CONTEXT) {
 		unsigned long flags;
 
 		local_irq_save(flags);
-		mm->context.id = NO_CONTEXT;
+		cpu_context(cpu, mm) = NO_CONTEXT;
 		if (mm == current->mm)
-			activate_context(mm);
+			activate_context(mm, cpu);
 		local_irq_restore(flags);
 	}
 }
 
-void flush_tlb_all(void)
+void local_flush_tlb_all(void)
 {
 	unsigned long flags, status;
 
@@ -132,3 +140,54 @@
 	ctrl_barrier();
 	local_irq_restore(flags);
 }
+
+void update_mmu_cache(struct vm_area_struct *vma,
+		      unsigned long address, pte_t pte)
+{
+	unsigned long flags;
+	unsigned long pteval;
+	unsigned long vpn;
+	struct page *page;
+	unsigned long pfn = pte_pfn(pte);
+	struct address_space *mapping;
+
+	if (!pfn_valid(pfn))
+		return;
+
+	page = pfn_to_page(pfn);
+	mapping = page_mapping(page);
+	if (mapping) {
+		unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+		int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
+
+		if (dirty)
+			__flush_wback_region((void *)P1SEGADDR(phys),
+					     PAGE_SIZE);
+	}
+
+	local_irq_save(flags);
+
+	/* Set PTEH register */
+	vpn = (address & MMU_VPN_MASK) | get_asid();
+	ctrl_outl(vpn, MMU_PTEH);
+
+	pteval = pte_val(pte);
+
+#ifdef CONFIG_CPU_HAS_PTEA
+	/* Set PTEA register */
+	/* TODO: make this look less hacky */
+	ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA);
+#endif
+
+	/* Set PTEL register */
+	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+#if defined(CONFIG_SH_WRITETHROUGH) && defined(CONFIG_CPU_SH4)
+	pteval |= _PAGE_WT;
+#endif
+	/* conveniently, we want all the software flags to be 0 anyway */
+	ctrl_outl(pteval, MMU_PTEL);
+
+	/* Load the TLB */
+	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+	local_irq_restore(flags);
+}
diff --git a/arch/sh/mm/tlb-nommu.c b/arch/sh/mm/tlb-nommu.c
index e55cfea..1ccca7c 100644
--- a/arch/sh/mm/tlb-nommu.c
+++ b/arch/sh/mm/tlb-nommu.c
@@ -13,39 +13,33 @@
 /*
  * Nothing too terribly exciting here ..
  */
-
-void flush_tlb(void)
+void local_flush_tlb_all(void)
 {
 	BUG();
 }
 
-void flush_tlb_all(void)
+void local_flush_tlb_mm(struct mm_struct *mm)
 {
 	BUG();
 }
 
-void flush_tlb_mm(struct mm_struct *mm)
-{
-	BUG();
-}
-
-void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 			    unsigned long end)
 {
 	BUG();
 }
 
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
 	BUG();
 }
 
-void __flush_tlb_page(unsigned long asid, unsigned long page)
+void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
 	BUG();
 }
 
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
 	BUG();
 }
@@ -55,4 +49,3 @@
 {
 	BUG();
 }
-
diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c
index 46b09e2..e5e76eb 100644
--- a/arch/sh/mm/tlb-sh3.c
+++ b/arch/sh/mm/tlb-sh3.c
@@ -8,71 +8,11 @@
  *
  * Released under the terms of the GNU GPL v2.0.
  */
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-
+#include <linux/io.h>
 #include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
-#include <asm/cacheflush.h>
 
-void update_mmu_cache(struct vm_area_struct * vma,
-		      unsigned long address, pte_t pte)
-{
-	unsigned long flags;
-	unsigned long pteval;
-	unsigned long vpn;
-
-	/* Ptrace may call this routine. */
-	if (vma && current->active_mm != vma->vm_mm)
-		return;
-
-#if defined(CONFIG_SH7705_CACHE_32KB)
-	{
-		struct page *page = pte_page(pte);
-		unsigned long pfn = pte_pfn(pte);
-
-		if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) {
-			unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
-
-			__flush_wback_region((void *)P1SEGADDR(phys),
-					     PAGE_SIZE);
-			__set_bit(PG_mapped, &page->flags);
-		}
-	}
-#endif
-
-	local_irq_save(flags);
-
-	/* Set PTEH register */
-	vpn = (address & MMU_VPN_MASK) | get_asid();
-	ctrl_outl(vpn, MMU_PTEH);
-
-	pteval = pte_val(pte);
-
-	/* Set PTEL register */
-	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
-	/* conveniently, we want all the software flags to be 0 anyway */
-	ctrl_outl(pteval, MMU_PTEL);
-
-	/* Load the TLB */
-	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
-	local_irq_restore(flags);
-}
-
-void __flush_tlb_page(unsigned long asid, unsigned long page)
+void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
 	unsigned long addr, data;
 	int i, ways = MMU_NTLB_WAYS;
@@ -86,7 +26,7 @@
 	addr = MMU_TLB_ADDRESS_ARRAY | (page & 0x1F000);
 	data = (page & 0xfffe0000) | asid; /* VALID bit is off */
 
-	if ((cpu_data->flags & CPU_HAS_MMU_PAGE_ASSOC)) {
+	if ((current_cpu_data.flags & CPU_HAS_MMU_PAGE_ASSOC)) {
 		addr |= MMU_PAGE_ASSOC_BIT;
 		ways = 1;	/* we already know the way .. */
 	}
@@ -94,4 +34,3 @@
 	for (i = 0; i < ways; i++)
 		ctrl_outl(data, addr + (i << 8));
 }
-
diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c
index 812b2d5..221e709 100644
--- a/arch/sh/mm/tlb-sh4.c
+++ b/arch/sh/mm/tlb-sh4.c
@@ -8,76 +8,11 @@
  *
  * Released under the terms of the GNU GPL v2.0.
  */
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-
+#include <linux/io.h>
 #include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
-#include <asm/cacheflush.h>
 
-void update_mmu_cache(struct vm_area_struct * vma,
-		      unsigned long address, pte_t pte)
-{
-	unsigned long flags;
-	unsigned long pteval;
-	unsigned long vpn;
-	struct page *page;
-	unsigned long pfn;
-
-	/* Ptrace may call this routine. */
-	if (vma && current->active_mm != vma->vm_mm)
-		return;
-
-	pfn = pte_pfn(pte);
-	if (pfn_valid(pfn)) {
-		page = pfn_to_page(pfn);
-		if (!test_bit(PG_mapped, &page->flags)) {
-			unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
-			__flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE);
-			__set_bit(PG_mapped, &page->flags);
-		}
-	}
-
-	local_irq_save(flags);
-
-	/* Set PTEH register */
-	vpn = (address & MMU_VPN_MASK) | get_asid();
-	ctrl_outl(vpn, MMU_PTEH);
-
-	pteval = pte_val(pte);
-
-	/* Set PTEA register */
-	if (cpu_data->flags & CPU_HAS_PTEA)
-		/* TODO: make this look less hacky */
-		ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA);
-
-	/* Set PTEL register */
-	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
-#ifdef CONFIG_SH_WRITETHROUGH
-	pteval |= _PAGE_WT;
-#endif
-	/* conveniently, we want all the software flags to be 0 anyway */
-	ctrl_outl(pteval, MMU_PTEL);
-
-	/* Load the TLB */
-	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
-	local_irq_restore(flags);
-}
-
-void __flush_tlb_page(unsigned long asid, unsigned long page)
+void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
 	unsigned long addr, data;
 
@@ -93,4 +28,3 @@
 	ctrl_outl(data, addr);
 	back_to_P1();
 }
-
diff --git a/arch/sh/oprofile/op_model_sh7750.c b/arch/sh/oprofile/op_model_sh7750.c
index 60402ee..ebee7e2 100644
--- a/arch/sh/oprofile/op_model_sh7750.c
+++ b/arch/sh/oprofile/op_model_sh7750.c
@@ -187,7 +187,7 @@
 	return count;
 }
 
-static struct file_operations count_fops = {
+static const struct file_operations count_fops = {
 	.read		= sh7750_read_count,
 	.write		= sh7750_write_count,
 };
@@ -259,7 +259,7 @@
 
 int __init oprofile_arch_init(struct oprofile_operations **ops)
 {
-	if (!(cpu_data->flags & CPU_HAS_PERF_COUNTER))
+	if (!(current_cpu_data.flags & CPU_HAS_PERF_COUNTER))
 		return -ENODEV;
 
 	sh7750_perf_counter_ops.cpu_type = (char *)get_cpu_subtype();
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index 0571755..4fe0f94 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -16,7 +16,6 @@
 HD64465			HD64465
 SATURN			SH_SATURN
 DREAMCAST		SH_DREAMCAST
-BIGSUR			SH_BIGSUR
 MPC1211			SH_MPC1211
 SNAPGEAR		SH_SECUREEDGE5410
 HS7751RVOIP		SH_HS7751RVOIP
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index 7bc0744..e14b533 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -36,9 +36,6 @@
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
-config GENERIC_ISA_DMA
-	bool
-
 config ARCH_HAS_ILOG2_U32
 	bool
 	default n
diff --git a/arch/sh64/kernel/setup.c b/arch/sh64/kernel/setup.c
index b9e7d54..53e9d20 100644
--- a/arch/sh64/kernel/setup.c
+++ b/arch/sh64/kernel/setup.c
@@ -83,7 +83,7 @@
 #define RAMDISK_PROMPT_FLAG		0x8000
 #define RAMDISK_LOAD_FLAG		0x4000
 
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
+static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, };
 unsigned long long memory_start = CONFIG_MEMORY_START;
 unsigned long long memory_end = CONFIG_MEMORY_START + (CONFIG_MEMORY_SIZE_IN_MB * 1024 * 1024);
 
@@ -95,8 +95,8 @@
 	int len = 0;
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
 	for (;;) {
 	  /*
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
index 9c4a38a..390b40d 100644
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -579,12 +579,3 @@
 	asm __volatile__ ("nop");
 	panic("Unexpected wakeup!\n");
 }
-
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
diff --git a/arch/sh64/kernel/traps.c b/arch/sh64/kernel/traps.c
index 224b7f5..c346d7e 100644
--- a/arch/sh64/kernel/traps.c
+++ b/arch/sh64/kernel/traps.c
@@ -910,30 +910,57 @@
 }
 
 static ctl_table unaligned_table[] = {
-	{1, "kernel_reports", &kernel_mode_unaligned_fixup_count,
-		sizeof(int), 0644, NULL, &proc_dointvec},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "kernel_reports",
+		.data		= &kernel_mode_unaligned_fixup_count,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
 #if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
-	{2, "user_reports", &user_mode_unaligned_fixup_count,
-		sizeof(int), 0644, NULL, &proc_dointvec},
-	{3, "user_enable", &user_mode_unaligned_fixup_enable,
-		sizeof(int), 0644, NULL, &proc_dointvec},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "user_reports",
+		.data		= &user_mode_unaligned_fixup_count,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "user_enable",
+		.data		= &user_mode_unaligned_fixup_enable,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec},
 #endif
-	{0}
+	{}
 };
 
 static ctl_table unaligned_root[] = {
-	{1, "unaligned_fixup", NULL, 0, 0555, unaligned_table},
-	{0}
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "unaligned_fixup",
+		.mode		= 0555,
+		unaligned_table
+	},
+	{}
 };
 
 static ctl_table sh64_root[] = {
-	{1, "sh64", NULL, 0, 0555, unaligned_root},
-	{0}
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sh64",
+		.mode		= 0555,
+		.child		= unaligned_root
+	},
+	{}
 };
 static struct ctl_table_header *sysctl_header;
 static int __init init_sysctl(void)
 {
-	sysctl_header = register_sysctl_table(sh64_root, 0);
+	sysctl_header = register_sysctl_table(sh64_root);
 	return 0;
 }
 
diff --git a/arch/sh64/kernel/vmlinux.lds.S b/arch/sh64/kernel/vmlinux.lds.S
index 95c4d75..a59c5e998 100644
--- a/arch/sh64/kernel/vmlinux.lds.S
+++ b/arch/sh64/kernel/vmlinux.lds.S
@@ -115,9 +115,13 @@
   .con_initcall.init : C_PHYS(.con_initcall.init) { *(.con_initcall.init) }
   __con_initcall_end = .;
   SECURITY_INIT
+
+#ifdef CONFIG_BLK_DEV_INITRD
   __initramfs_start = .;
   .init.ramfs : C_PHYS(.init.ramfs) { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
+
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
diff --git a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c
index 83295bd..5dc0878 100644
--- a/arch/sh64/mm/init.c
+++ b/arch/sh64/mm/init.c
@@ -118,10 +118,7 @@
 
 	mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
 
-        /*
-	 * All memory is good as ZONE_NORMAL (fall-through) and ZONE_DMA.
-         */
-	zones_size[ZONE_DMA] = MAX_LOW_PFN - START_PFN;
+	zones_size[ZONE_NORMAL] = MAX_LOW_PFN - START_PFN;
 	NODE_DATA(0)->node_mem_map = NULL;
 	free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
 }
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index d0dec1e..bd992c0 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -13,6 +13,10 @@
 	bool
 	default y
 
+config ZONE_DMA
+	bool
+	default y
+
 config GENERIC_ISA_DMA
 	bool
 	default y
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 6616ee0..e795f28 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -12,7 +12,9 @@
 	    sys_sparc.o sunos_asm.o systbls.o \
 	    time.o windows.o cpu.o devices.o sclow.o \
 	    tadpole.o tick14.o ptrace.o sys_solaris.o \
-	    unaligned.o muldiv.o semaphore.o prom.o of_device.o
+	    unaligned.o muldiv.o semaphore.o prom.o of_device.o devres.o
+
+devres-y = ../../../kernel/irq/devres.o
 
 obj-$(CONFIG_PCI) += pcic.o
 obj-$(CONFIG_SUN4) += sun4setup.o
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c
index 406dd94..d06a405 100644
--- a/arch/sparc/kernel/apc.c
+++ b/arch/sparc/kernel/apc.c
@@ -127,7 +127,7 @@
 	return 0;
 }
 
-static struct file_operations apc_fops = {
+static const struct file_operations apc_fops = {
 	.ioctl =	apc_ioctl,
 	.open =		apc_open,
 	.release =	apc_release,
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 383526a..eccd8e8 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -246,7 +246,7 @@
 
 	/* Initialize PROM console and command line. */
 	*cmdline_p = prom_getbootargs();
-	strcpy(saved_command_line, *cmdline_p);
+	strcpy(boot_command_line, *cmdline_p);
 
 	/* Set sparc_cpu_model */
 	sparc_cpu_model = sun_unknown;
diff --git a/arch/sparc/kernel/sunos_ioctl.c b/arch/sparc/kernel/sunos_ioctl.c
index a6ba3d2..32e8274 100644
--- a/arch/sparc/kernel/sunos_ioctl.c
+++ b/arch/sparc/kernel/sunos_ioctl.c
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/termios.h>
+#include <linux/tty.h>
 #include <linux/ioctl.h>
 #include <linux/route.h>
 #include <linux/sockios.h>
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index 0bf8c16..da6606f 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -859,14 +859,16 @@
 	return ret;
 }
 
-extern int kill_pg(int, int, int);
 asmlinkage int sunos_killpg(int pgrp, int sig)
 {
 	int ret;
 
-	lock_kernel();
-	ret = kill_pg(pgrp, sig, 0);
-	unlock_kernel();
+	rcu_read_lock();
+	ret = -EINVAL;
+	if (pgrp > 0)
+		ret = kill_pgrp(find_pid(pgrp), sig, 0);
+	rcu_read_unlock();
+
 	return ret;
 }
 
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 2fcce00..9bb1240aa 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -436,15 +436,6 @@
 	return (*master_l10_counter >> 10) & 0x1fffff;
 }
 
-/*
- * Returns nanoseconds
- * XXX This is a suboptimal implementation.
- */
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
 /* Ok, my cute asm atomicity trick doesn't work anymore.
  * There are just too many variables that need to be protected
  * now (both members of xtime, et al.)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index b73e6b9..e5c24e0 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -57,10 +57,14 @@
   .con_initcall.init : { *(.con_initcall.init) }
   __con_initcall_end = .;
   SECURITY_INIT
+
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
+
   . = ALIGN(32);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index d41f66a..f75a686 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -232,10 +232,6 @@
 
 source "mm/Kconfig"
 
-config GENERIC_ISA_DMA
-	bool
-	default y
-
 config ISA
 	bool
 	help
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 5a9e68b..0f44a6a 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.20-rc2
-# Thu Dec 28 15:09:49 2006
+# Linux kernel version: 2.6.20
+# Sun Feb 11 23:47:40 2007
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -49,7 +49,6 @@
 # CONFIG_IKCONFIG is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
@@ -144,14 +143,14 @@
 CONFIG_SPARSEMEM_EXTREME=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
-CONFIG_GENERIC_ISA_DMA=y
+CONFIG_ZONE_DMA_FLAG=0
 CONFIG_SBUS=y
 CONFIG_SBUSCHAR=y
 CONFIG_SUN_AUXIO=y
 CONFIG_SUN_IO=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_DEBUG is not set
 CONFIG_SUN_OPENPROMFS=m
 CONFIG_SPARC32_COMPAT=y
@@ -182,7 +181,9 @@
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -300,6 +301,7 @@
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -393,6 +395,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 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
@@ -402,6 +405,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -579,6 +583,7 @@
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -601,11 +606,13 @@
 CONFIG_TIGON3=m
 CONFIG_BNX2=m
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
@@ -627,8 +634,17 @@
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_PPP 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 is not set
+CONFIG_SLHC=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
@@ -1043,6 +1059,11 @@
 # CONFIG_SND_SUN_DBRI is not set
 
 #
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
 # Open Sound System
 #
 # CONFIG_SOUND_PRIME is not set
@@ -1052,6 +1073,7 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -1066,9 +1088,7 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1078,9 +1098,11 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=m
 # CONFIG_USB_SL811_HCD is not set
@@ -1132,6 +1154,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1236,6 +1259,10 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
 # Virtualization
 #
 
@@ -1426,7 +1453,6 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -1473,8 +1499,10 @@
 CONFIG_CRYPTO_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1489,6 +1517,7 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_TEST=m
 
 #
@@ -1506,4 +1535,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index c3d068c..b5ff3ee 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -22,6 +22,7 @@
 #include <linux/seq_file.h>
 #include <linux/bootmem.h>
 #include <linux/irq.h>
+#include <linux/msi.h>
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -87,7 +88,6 @@
 #define irq_work(__cpu)	&(trap_block[(__cpu)].irq_worklist)
 
 static unsigned int virt_to_real_irq_table[NR_IRQS];
-static unsigned char virt_irq_cur = 1;
 
 static unsigned char virt_irq_alloc(unsigned int real_irq)
 {
@@ -95,26 +95,32 @@
 
 	BUILD_BUG_ON(NR_IRQS >= 256);
 
-	ent = virt_irq_cur;
+	for (ent = 1; ent < NR_IRQS; ent++) {
+		if (!virt_to_real_irq_table[ent])
+			break;
+	}
 	if (ent >= NR_IRQS) {
 		printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
 		return 0;
 	}
 
-	virt_irq_cur = ent + 1;
 	virt_to_real_irq_table[ent] = real_irq;
 
 	return ent;
 }
 
-#if 0 /* Currently unused. */
-static unsigned char real_to_virt_irq(unsigned int real_irq)
+static void virt_irq_free(unsigned int virt_irq)
 {
-	struct ino_bucket *bucket = __bucket(real_irq);
+	unsigned int real_irq;
 
-	return bucket->virt_irq;
+	if (virt_irq >= NR_IRQS)
+		return;
+
+	real_irq = virt_to_real_irq_table[virt_irq];
+	virt_to_real_irq_table[virt_irq] = 0;
+
+	__bucket(real_irq)->virt_irq = 0;
 }
-#endif
 
 static unsigned int virt_to_real_irq(unsigned char virt_irq)
 {
@@ -268,8 +274,7 @@
 
 static void sun4u_irq_enable(unsigned int virt_irq)
 {
-	irq_desc_t *desc = irq_desc + virt_irq;
-	struct irq_handler_data *data = desc->handler_data;
+	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
 
 	if (likely(data)) {
 		unsigned long cpuid, imap;
@@ -286,8 +291,7 @@
 
 static void sun4u_irq_disable(unsigned int virt_irq)
 {
-	irq_desc_t *desc = irq_desc + virt_irq;
-	struct irq_handler_data *data = desc->handler_data;
+	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
 
 	if (likely(data)) {
 		unsigned long imap = data->imap;
@@ -300,8 +304,7 @@
 
 static void sun4u_irq_end(unsigned int virt_irq)
 {
-	irq_desc_t *desc = irq_desc + virt_irq;
-	struct irq_handler_data *data = desc->handler_data;
+	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
 
 	if (likely(data))
 		upa_writel(ICLR_IDLE, data->iclr);
@@ -344,6 +347,20 @@
 	}
 }
 
+#ifdef CONFIG_PCI_MSI
+static void sun4v_msi_enable(unsigned int virt_irq)
+{
+	sun4v_irq_enable(virt_irq);
+	unmask_msi_irq(virt_irq);
+}
+
+static void sun4v_msi_disable(unsigned int virt_irq)
+{
+	mask_msi_irq(virt_irq);
+	sun4v_irq_disable(virt_irq);
+}
+#endif
+
 static void sun4v_irq_end(unsigned int virt_irq)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -362,8 +379,7 @@
 static void run_pre_handler(unsigned int virt_irq)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
-	irq_desc_t *desc = irq_desc + virt_irq;
-	struct irq_handler_data *data = desc->handler_data;
+	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
 
 	if (likely(data->pre_handler)) {
 		data->pre_handler(__irq_ino(__irq(bucket)),
@@ -402,30 +418,47 @@
 	.end		= sun4v_irq_end,
 };
 
+#ifdef CONFIG_PCI_MSI
+static struct irq_chip sun4v_msi = {
+	.typename	= "sun4v+msi",
+	.mask		= mask_msi_irq,
+	.unmask		= unmask_msi_irq,
+	.enable		= sun4v_msi_enable,
+	.disable	= sun4v_msi_disable,
+	.ack		= run_pre_handler,
+	.end		= sun4v_irq_end,
+};
+#endif
+
 void irq_install_pre_handler(int virt_irq,
 			     void (*func)(unsigned int, void *, void *),
 			     void *arg1, void *arg2)
 {
-	irq_desc_t *desc = irq_desc + virt_irq;
-	struct irq_handler_data *data = desc->handler_data;
+	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+	struct irq_chip *chip;
 
 	data->pre_handler = func;
 	data->pre_handler_arg1 = arg1;
 	data->pre_handler_arg2 = arg2;
 
-	if (desc->chip == &sun4u_irq_ack ||
-	    desc->chip == &sun4v_irq_ack)
+	chip = get_irq_chip(virt_irq);
+	if (chip == &sun4u_irq_ack ||
+	    chip == &sun4v_irq_ack
+#ifdef CONFIG_PCI_MSI
+	    || chip == &sun4v_msi
+#endif
+	    )
 		return;
 
-	desc->chip = (desc->chip == &sun4u_irq ?
-		      &sun4u_irq_ack : &sun4v_irq_ack);
+	chip = (chip == &sun4u_irq ?
+		&sun4u_irq_ack : &sun4v_irq_ack);
+	set_irq_chip(virt_irq, chip);
 }
 
 unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
 {
 	struct ino_bucket *bucket;
 	struct irq_handler_data *data;
-	irq_desc_t *desc;
 	int ino;
 
 	BUG_ON(tlb_type == hypervisor);
@@ -434,11 +467,11 @@
 	bucket = &ivector_table[ino];
 	if (!bucket->virt_irq) {
 		bucket->virt_irq = virt_irq_alloc(__irq(bucket));
-		irq_desc[bucket->virt_irq].chip = &sun4u_irq;
+		set_irq_chip(bucket->virt_irq, &sun4u_irq);
 	}
 
-	desc = irq_desc + bucket->virt_irq;
-	if (unlikely(desc->handler_data))
+	data = get_irq_chip_data(bucket->virt_irq);
+	if (unlikely(data))
 		goto out;
 
 	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
@@ -446,7 +479,7 @@
 		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
 		prom_halt();
 	}
-	desc->handler_data = data;
+	set_irq_chip_data(bucket->virt_irq, data);
 
 	data->imap  = imap;
 	data->iclr  = iclr;
@@ -460,7 +493,6 @@
 	struct ino_bucket *bucket;
 	struct irq_handler_data *data;
 	unsigned long sysino;
-	irq_desc_t *desc;
 
 	BUG_ON(tlb_type != hypervisor);
 
@@ -468,11 +500,11 @@
 	bucket = &ivector_table[sysino];
 	if (!bucket->virt_irq) {
 		bucket->virt_irq = virt_irq_alloc(__irq(bucket));
-		irq_desc[bucket->virt_irq].chip = &sun4v_irq;
+		set_irq_chip(bucket->virt_irq, &sun4v_irq);
 	}
 
-	desc = irq_desc + bucket->virt_irq;
-	if (unlikely(desc->handler_data))
+	data = get_irq_chip_data(bucket->virt_irq);
+	if (unlikely(data))
 		goto out;
 
 	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
@@ -480,7 +512,7 @@
 		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
 		prom_halt();
 	}
-	desc->handler_data = data;
+	set_irq_chip_data(bucket->virt_irq, data);
 
 	/* Catch accidental accesses to these things.  IMAP/ICLR handling
 	 * is done by hypervisor calls on sun4v platforms, not by direct
@@ -493,6 +525,56 @@
 	return bucket->virt_irq;
 }
 
+#ifdef CONFIG_PCI_MSI
+unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
+			     unsigned int msi_start, unsigned int msi_end)
+{
+	struct ino_bucket *bucket;
+	struct irq_handler_data *data;
+	unsigned long sysino;
+	unsigned int devino;
+
+	BUG_ON(tlb_type != hypervisor);
+
+	/* Find a free devino in the given range.  */
+	for (devino = msi_start; devino < msi_end; devino++) {
+		sysino = sun4v_devino_to_sysino(devhandle, devino);
+		bucket = &ivector_table[sysino];
+		if (!bucket->virt_irq)
+			break;
+	}
+	if (devino >= msi_end)
+		return 0;
+
+	sysino = sun4v_devino_to_sysino(devhandle, devino);
+	bucket = &ivector_table[sysino];
+	bucket->virt_irq = virt_irq_alloc(__irq(bucket));
+	*virt_irq_p = bucket->virt_irq;
+	set_irq_chip(bucket->virt_irq, &sun4v_msi);
+
+	data = get_irq_chip_data(bucket->virt_irq);
+	if (unlikely(data))
+		return devino;
+
+	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!data)) {
+		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
+		prom_halt();
+	}
+	set_irq_chip_data(bucket->virt_irq, data);
+
+	data->imap = ~0UL;
+	data->iclr = ~0UL;
+
+	return devino;
+}
+
+void sun4v_destroy_msi(unsigned int virt_irq)
+{
+	virt_irq_free(virt_irq);
+}
+#endif
+
 void ack_bad_irq(unsigned int virt_irq)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index dfc41cd..6b740eb 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -13,6 +13,8 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/smp_lock.h>
+#include <linux/msi.h>
+#include <linux/irq.h>
 #include <linux/init.h>
 
 #include <asm/uaccess.h>
@@ -646,4 +648,37 @@
 }
 EXPORT_SYMBOL(pci_domain_nr);
 
+#ifdef CONFIG_PCI_MSI
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_pbm_info *pbm = pcp->pbm;
+	struct pci_controller_info *p = pbm->parent;
+	int virt_irq, err;
+
+	if (!pbm->msi_num || !p->setup_msi_irq)
+		return -EINVAL;
+
+	err = p->setup_msi_irq(&virt_irq, pdev, desc);
+	if (err < 0)
+		return err;
+
+	return virt_irq;
+}
+
+void arch_teardown_msi_irq(unsigned int virt_irq)
+{
+	struct msi_desc *entry = get_irq_data(virt_irq);
+	struct pci_dev *pdev = entry->dev;
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_pbm_info *pbm = pcp->pbm;
+	struct pci_controller_info *p = pbm->parent;
+
+	if (!pbm->msi_num || !p->setup_msi_irq)
+		return;
+
+	return p->teardown_msi_irq(virt_irq, pdev);
+}
+#endif /* !(CONFIG_PCI_MSI) */
+
 #endif /* !(CONFIG_PCI) */
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 827ae30..5a92cb9 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -7,6 +7,8 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/device.h>
 
 #include <asm/pbm.h>
 #include <asm/prom.h>
@@ -129,6 +131,20 @@
 	}
 }
 
+static ssize_t
+show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char * buf)
+{
+	struct pci_dev *pdev;
+	struct pcidev_cookie *sysdata;
+
+	pdev = to_pci_dev(dev);
+	sysdata = pdev->sysdata;
+
+	return snprintf (buf, PAGE_SIZE, "%s\n", sysdata->prom_node->full_name);
+}
+
+static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL);
+
 /* Fill in the PCI device cookie sysdata for the given
  * PCI device.  This cookie is the means by which one
  * can get to OBP and PCI controller specific information
@@ -142,7 +158,7 @@
 	struct pcidev_cookie *pcp;
 	struct device_node *dp;
 	struct property *prop;
-	int nregs, len;
+	int nregs, len, err;
 
 	dp = find_device_prom_node(pbm, pdev, bus_node,
 				   &pregs, &nregs);
@@ -215,6 +231,13 @@
 	fixup_obp_assignments(pdev, pcp);
 
 	pdev->sysdata = pcp;
+
+	/* we don't really care if we can create this file or not,
+	 * but we need to assign the result of the call or the world will fall
+	 * under alien invasion and everybody will be frozen on a spaceship
+	 * ready to be eaten on alpha centauri by some green and jelly humanoid.
+	 */
+	err = sysfs_create_file(&pdev->dev.kobj, &dev_attr_obppath.attr);
 }
 
 void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 6b04794..ec22cd6 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -10,6 +10,8 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
+#include <linux/irq.h>
+#include <linux/msi.h>
 
 #include <asm/pbm.h>
 #include <asm/iommu.h>
@@ -1074,6 +1076,443 @@
 
 }
 
+#ifdef CONFIG_PCI_MSI
+struct pci_sun4v_msiq_entry {
+	u64		version_type;
+#define MSIQ_VERSION_MASK		0xffffffff00000000UL
+#define MSIQ_VERSION_SHIFT		32
+#define MSIQ_TYPE_MASK			0x00000000000000ffUL
+#define MSIQ_TYPE_SHIFT			0
+#define MSIQ_TYPE_NONE			0x00
+#define MSIQ_TYPE_MSG			0x01
+#define MSIQ_TYPE_MSI32			0x02
+#define MSIQ_TYPE_MSI64			0x03
+#define MSIQ_TYPE_INTX			0x08
+#define MSIQ_TYPE_NONE2			0xff
+
+	u64		intx_sysino;
+	u64		reserved1;
+	u64		stick;
+	u64		req_id;  /* bus/device/func */
+#define MSIQ_REQID_BUS_MASK		0xff00UL
+#define MSIQ_REQID_BUS_SHIFT		8
+#define MSIQ_REQID_DEVICE_MASK		0x00f8UL
+#define MSIQ_REQID_DEVICE_SHIFT		3
+#define MSIQ_REQID_FUNC_MASK		0x0007UL
+#define MSIQ_REQID_FUNC_SHIFT		0
+
+	u64		msi_address;
+
+	/* The format of this value is message type dependant.
+	 * For MSI bits 15:0 are the data from the MSI packet.
+	 * For MSI-X bits 31:0 are the data from the MSI packet.
+	 * For MSG, the message code and message routing code where:
+	 * 	bits 39:32 is the bus/device/fn of the msg target-id
+	 *	bits 18:16 is the message routing code
+	 *	bits 7:0 is the message code
+	 * For INTx the low order 2-bits are:
+	 *	00 - INTA
+	 *	01 - INTB
+	 *	10 - INTC
+	 *	11 - INTD
+	 */
+	u64		msi_data;
+
+	u64		reserved2;
+};
+
+/* For now this just runs as a pre-handler for the real interrupt handler.
+ * So we just walk through the queue and ACK all the entries, update the
+ * head pointer, and return.
+ *
+ * In the longer term it would be nice to do something more integrated
+ * wherein we can pass in some of this MSI info to the drivers.  This
+ * would be most useful for PCIe fabric error messages, although we could
+ * invoke those directly from the loop here in order to pass the info around.
+ */
+static void pci_sun4v_msi_prehandler(unsigned int ino, void *data1, void *data2)
+{
+	struct pci_pbm_info *pbm = data1;
+	struct pci_sun4v_msiq_entry *base, *ep;
+	unsigned long msiqid, orig_head, head, type, err;
+
+	msiqid = (unsigned long) data2;
+
+	head = 0xdeadbeef;
+	err = pci_sun4v_msiq_gethead(pbm->devhandle, msiqid, &head);
+	if (unlikely(err))
+		goto hv_error_get;
+
+	if (unlikely(head >= (pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry))))
+		goto bad_offset;
+
+	head /= sizeof(struct pci_sun4v_msiq_entry);
+	orig_head = head;
+	base = (pbm->msi_queues + ((msiqid - pbm->msiq_first) *
+				   (pbm->msiq_ent_count *
+				    sizeof(struct pci_sun4v_msiq_entry))));
+	ep = &base[head];
+	while ((ep->version_type & MSIQ_TYPE_MASK) != 0) {
+		type = (ep->version_type & MSIQ_TYPE_MASK) >> MSIQ_TYPE_SHIFT;
+		if (unlikely(type != MSIQ_TYPE_MSI32 &&
+			     type != MSIQ_TYPE_MSI64))
+			goto bad_type;
+
+		pci_sun4v_msi_setstate(pbm->devhandle,
+				       ep->msi_data /* msi_num */,
+				       HV_MSISTATE_IDLE);
+
+		/* Clear the entry.  */
+		ep->version_type &= ~MSIQ_TYPE_MASK;
+
+		/* Go to next entry in ring.  */
+		head++;
+		if (head >= pbm->msiq_ent_count)
+			head = 0;
+		ep = &base[head];
+	}
+
+	if (likely(head != orig_head)) {
+		/* ACK entries by updating head pointer.  */
+		head *= sizeof(struct pci_sun4v_msiq_entry);
+		err = pci_sun4v_msiq_sethead(pbm->devhandle, msiqid, head);
+		if (unlikely(err))
+			goto hv_error_set;
+	}
+	return;
+
+hv_error_set:
+	printk(KERN_EMERG "MSI: Hypervisor set head gives error %lu\n", err);
+	goto hv_error_cont;
+
+hv_error_get:
+	printk(KERN_EMERG "MSI: Hypervisor get head gives error %lu\n", err);
+
+hv_error_cont:
+	printk(KERN_EMERG "MSI: devhandle[%x] msiqid[%lx] head[%lu]\n",
+	       pbm->devhandle, msiqid, head);
+	return;
+
+bad_offset:
+	printk(KERN_EMERG "MSI: Hypervisor gives bad offset %lx max(%lx)\n",
+	       head, pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry));
+	return;
+
+bad_type:
+	printk(KERN_EMERG "MSI: Entry has bad type %lx\n", type);
+	return;
+}
+
+static int msi_bitmap_alloc(struct pci_pbm_info *pbm)
+{
+	unsigned long size, bits_per_ulong;
+
+	bits_per_ulong = sizeof(unsigned long) * 8;
+	size = (pbm->msi_num + (bits_per_ulong - 1)) & ~(bits_per_ulong - 1);
+	size /= 8;
+	BUG_ON(size % sizeof(unsigned long));
+
+	pbm->msi_bitmap = kzalloc(size, GFP_KERNEL);
+	if (!pbm->msi_bitmap)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void msi_bitmap_free(struct pci_pbm_info *pbm)
+{
+	kfree(pbm->msi_bitmap);
+	pbm->msi_bitmap = NULL;
+}
+
+static int msi_queue_alloc(struct pci_pbm_info *pbm)
+{
+	unsigned long q_size, alloc_size, pages, order;
+	int i;
+
+	q_size = pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry);
+	alloc_size = (pbm->msiq_num * q_size);
+	order = get_order(alloc_size);
+	pages = __get_free_pages(GFP_KERNEL | __GFP_COMP, order);
+	if (pages == 0UL) {
+		printk(KERN_ERR "MSI: Cannot allocate MSI queues (o=%lu).\n",
+		       order);
+		return -ENOMEM;
+	}
+	memset((char *)pages, 0, PAGE_SIZE << order);
+	pbm->msi_queues = (void *) pages;
+
+	for (i = 0; i < pbm->msiq_num; i++) {
+		unsigned long err, base = __pa(pages + (i * q_size));
+		unsigned long ret1, ret2;
+
+		err = pci_sun4v_msiq_conf(pbm->devhandle,
+					  pbm->msiq_first + i,
+					  base, pbm->msiq_ent_count);
+		if (err) {
+			printk(KERN_ERR "MSI: msiq register fails (err=%lu)\n",
+			       err);
+			goto h_error;
+		}
+
+		err = pci_sun4v_msiq_info(pbm->devhandle,
+					  pbm->msiq_first + i,
+					  &ret1, &ret2);
+		if (err) {
+			printk(KERN_ERR "MSI: Cannot read msiq (err=%lu)\n",
+			       err);
+			goto h_error;
+		}
+		if (ret1 != base || ret2 != pbm->msiq_ent_count) {
+			printk(KERN_ERR "MSI: Bogus qconf "
+			       "expected[%lx:%x] got[%lx:%lx]\n",
+			       base, pbm->msiq_ent_count,
+			       ret1, ret2);
+			goto h_error;
+		}
+	}
+
+	return 0;
+
+h_error:
+	free_pages(pages, order);
+	return -EINVAL;
+}
+
+static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
+{
+	u32 *val;
+	int len;
+
+	val = of_get_property(pbm->prom_node, "#msi-eqs", &len);
+	if (!val || len != 4)
+		goto no_msi;
+	pbm->msiq_num = *val;
+	if (pbm->msiq_num) {
+		struct msiq_prop {
+			u32 first_msiq;
+			u32 num_msiq;
+			u32 first_devino;
+		} *mqp;
+		struct msi_range_prop {
+			u32 first_msi;
+			u32 num_msi;
+		} *mrng;
+		struct addr_range_prop {
+			u32 msi32_high;
+			u32 msi32_low;
+			u32 msi32_len;
+			u32 msi64_high;
+			u32 msi64_low;
+			u32 msi64_len;
+		} *arng;
+
+		val = of_get_property(pbm->prom_node, "msi-eq-size", &len);
+		if (!val || len != 4)
+			goto no_msi;
+
+		pbm->msiq_ent_count = *val;
+
+		mqp = of_get_property(pbm->prom_node,
+				      "msi-eq-to-devino", &len);
+		if (!mqp || len != sizeof(struct msiq_prop))
+			goto no_msi;
+
+		pbm->msiq_first = mqp->first_msiq;
+		pbm->msiq_first_devino = mqp->first_devino;
+
+		val = of_get_property(pbm->prom_node, "#msi", &len);
+		if (!val || len != 4)
+			goto no_msi;
+		pbm->msi_num = *val;
+
+		mrng = of_get_property(pbm->prom_node, "msi-ranges", &len);
+		if (!mrng || len != sizeof(struct msi_range_prop))
+			goto no_msi;
+		pbm->msi_first = mrng->first_msi;
+
+		val = of_get_property(pbm->prom_node, "msi-data-mask", &len);
+		if (!val || len != 4)
+			goto no_msi;
+		pbm->msi_data_mask = *val;
+
+		val = of_get_property(pbm->prom_node, "msix-data-width", &len);
+		if (!val || len != 4)
+			goto no_msi;
+		pbm->msix_data_width = *val;
+
+		arng = of_get_property(pbm->prom_node, "msi-address-ranges",
+				       &len);
+		if (!arng || len != sizeof(struct addr_range_prop))
+			goto no_msi;
+		pbm->msi32_start = ((u64)arng->msi32_high << 32) |
+			(u64) arng->msi32_low;
+		pbm->msi64_start = ((u64)arng->msi64_high << 32) |
+			(u64) arng->msi64_low;
+		pbm->msi32_len = arng->msi32_len;
+		pbm->msi64_len = arng->msi64_len;
+
+		if (msi_bitmap_alloc(pbm))
+			goto no_msi;
+
+		if (msi_queue_alloc(pbm)) {
+			msi_bitmap_free(pbm);
+			goto no_msi;
+		}
+
+		printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] "
+		       "devino[0x%x]\n",
+		       pbm->name,
+		       pbm->msiq_first, pbm->msiq_num,
+		       pbm->msiq_ent_count,
+		       pbm->msiq_first_devino);
+		printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] "
+		       "width[%u]\n",
+		       pbm->name,
+		       pbm->msi_first, pbm->msi_num, pbm->msi_data_mask,
+		       pbm->msix_data_width);
+		printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] "
+		       "addr64[0x%lx:0x%x]\n",
+		       pbm->name,
+		       pbm->msi32_start, pbm->msi32_len,
+		       pbm->msi64_start, pbm->msi64_len);
+		printk(KERN_INFO "%s: MSI queues at RA [%p]\n",
+		       pbm->name,
+		       pbm->msi_queues);
+	}
+
+	return;
+
+no_msi:
+	pbm->msiq_num = 0;
+	printk(KERN_INFO "%s: No MSI support.\n", pbm->name);
+}
+
+static int alloc_msi(struct pci_pbm_info *pbm)
+{
+	int i;
+
+	for (i = 0; i < pbm->msi_num; i++) {
+		if (!test_and_set_bit(i, pbm->msi_bitmap))
+			return i + pbm->msi_first;
+	}
+
+	return -ENOENT;
+}
+
+static void free_msi(struct pci_pbm_info *pbm, int msi_num)
+{
+	msi_num -= pbm->msi_first;
+	clear_bit(msi_num, pbm->msi_bitmap);
+}
+
+static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p,
+				   struct pci_dev *pdev,
+				   struct msi_desc *entry)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_pbm_info *pbm = pcp->pbm;
+	unsigned long devino, msiqid;
+	struct msi_msg msg;
+	int msi_num, err;
+
+	*virt_irq_p = 0;
+
+	msi_num = alloc_msi(pbm);
+	if (msi_num < 0)
+		return msi_num;
+
+	devino = sun4v_build_msi(pbm->devhandle, virt_irq_p,
+				 pbm->msiq_first_devino,
+				 (pbm->msiq_first_devino +
+				  pbm->msiq_num));
+	err = -ENOMEM;
+	if (!devino)
+		goto out_err;
+
+	set_irq_msi(*virt_irq_p, entry);
+
+	msiqid = ((devino - pbm->msiq_first_devino) +
+		  pbm->msiq_first);
+
+	err = -EINVAL;
+	if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
+	if (err)
+		goto out_err;
+
+	if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID))
+		goto out_err;
+
+	if (pci_sun4v_msi_setmsiq(pbm->devhandle,
+				  msi_num, msiqid,
+				  (entry->msi_attrib.is_64 ?
+				   HV_MSITYPE_MSI64 : HV_MSITYPE_MSI32)))
+		goto out_err;
+
+	if (pci_sun4v_msi_setstate(pbm->devhandle, msi_num, HV_MSISTATE_IDLE))
+		goto out_err;
+
+	if (pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_VALID))
+		goto out_err;
+
+	pcp->msi_num = msi_num;
+
+	if (entry->msi_attrib.is_64) {
+		msg.address_hi = pbm->msi64_start >> 32;
+		msg.address_lo = pbm->msi64_start & 0xffffffff;
+	} else {
+		msg.address_hi = 0;
+		msg.address_lo = pbm->msi32_start;
+	}
+	msg.data = msi_num;
+	write_msi_msg(*virt_irq_p, &msg);
+
+	irq_install_pre_handler(*virt_irq_p,
+				pci_sun4v_msi_prehandler,
+				pbm, (void *) msiqid);
+
+	return 0;
+
+out_err:
+	free_msi(pbm, msi_num);
+	sun4v_destroy_msi(*virt_irq_p);
+	*virt_irq_p = 0;
+	return err;
+
+}
+
+static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq,
+				       struct pci_dev *pdev)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_pbm_info *pbm = pcp->pbm;
+	unsigned long msiqid, err;
+	unsigned int msi_num;
+
+	msi_num = pcp->msi_num;
+	err = pci_sun4v_msi_getmsiq(pbm->devhandle, msi_num, &msiqid);
+	if (err) {
+		printk(KERN_ERR "%s: getmsiq gives error %lu\n",
+		       pbm->name, err);
+		return;
+	}
+
+	pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_INVALID);
+	pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_INVALID);
+
+	free_msi(pbm, msi_num);
+
+	/* The sun4v_destroy_msi() will liberate the devino and thus the MSIQ
+	 * allocation.
+	 */
+	sun4v_destroy_msi(virt_irq);
+}
+#else /* CONFIG_PCI_MSI */
+static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
+{
+}
+#endif /* !(CONFIG_PCI_MSI) */
+
 static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
 {
 	struct pci_pbm_info *pbm;
@@ -1119,6 +1558,7 @@
 
 	pci_sun4v_get_bus_range(pbm);
 	pci_sun4v_iommu_init(pbm);
+	pci_sun4v_msi_init(pbm);
 
 	pdev_htab_populate(pbm);
 }
@@ -1187,6 +1627,10 @@
 	p->scan_bus = pci_sun4v_scan_bus;
 	p->base_address_update = pci_sun4v_base_address_update;
 	p->resource_adjust = pci_sun4v_resource_adjust;
+#ifdef CONFIG_PCI_MSI
+	p->setup_msi_irq = pci_sun4v_setup_msi_irq;
+	p->teardown_msi_irq = pci_sun4v_teardown_msi_irq;
+#endif
 	p->pci_ops = &pci_sun4v_ops;
 
 	/* Like PSYCHO and SCHIZO we have a 2GB aligned area
diff --git a/arch/sparc64/kernel/pci_sun4v.h b/arch/sparc64/kernel/pci_sun4v.h
index 884d25f..8e9fc3a 100644
--- a/arch/sparc64/kernel/pci_sun4v.h
+++ b/arch/sparc64/kernel/pci_sun4v.h
@@ -28,4 +28,65 @@
 				unsigned long size,
 				unsigned long data);
 
+extern unsigned long pci_sun4v_msiq_conf(unsigned long devhandle,
+					 unsigned long msiqid,
+					 unsigned long msiq_paddr,
+					 unsigned long num_entries);
+extern unsigned long pci_sun4v_msiq_info(unsigned long devhandle,
+					 unsigned long msiqid,
+					 unsigned long *msiq_paddr,
+					 unsigned long *num_entries);
+extern unsigned long pci_sun4v_msiq_getvalid(unsigned long devhandle,
+					     unsigned long msiqid,
+					     unsigned long *valid);
+extern unsigned long pci_sun4v_msiq_setvalid(unsigned long devhandle,
+					     unsigned long msiqid,
+					     unsigned long valid);
+extern unsigned long pci_sun4v_msiq_getstate(unsigned long devhandle,
+					     unsigned long msiqid,
+					     unsigned long *state);
+extern unsigned long pci_sun4v_msiq_setstate(unsigned long devhandle,
+					     unsigned long msiqid,
+					     unsigned long state);
+extern unsigned long pci_sun4v_msiq_gethead(unsigned long devhandle,
+					     unsigned long msiqid,
+					     unsigned long *head);
+extern unsigned long pci_sun4v_msiq_sethead(unsigned long devhandle,
+					     unsigned long msiqid,
+					     unsigned long head);
+extern unsigned long pci_sun4v_msiq_gettail(unsigned long devhandle,
+					     unsigned long msiqid,
+					     unsigned long *head);
+extern unsigned long pci_sun4v_msi_getvalid(unsigned long devhandle,
+					    unsigned long msinum,
+					    unsigned long *valid);
+extern unsigned long pci_sun4v_msi_setvalid(unsigned long devhandle,
+					    unsigned long msinum,
+					    unsigned long valid);
+extern unsigned long pci_sun4v_msi_getmsiq(unsigned long devhandle,
+					   unsigned long msinum,
+					   unsigned long *msiq);
+extern unsigned long pci_sun4v_msi_setmsiq(unsigned long devhandle,
+					   unsigned long msinum,
+					   unsigned long msiq,
+					   unsigned long msitype);
+extern unsigned long pci_sun4v_msi_getstate(unsigned long devhandle,
+					    unsigned long msinum,
+					    unsigned long *state);
+extern unsigned long pci_sun4v_msi_setstate(unsigned long devhandle,
+					    unsigned long msinum,
+					    unsigned long state);
+extern unsigned long pci_sun4v_msg_getmsiq(unsigned long devhandle,
+					   unsigned long msinum,
+					   unsigned long *msiq);
+extern unsigned long pci_sun4v_msg_setmsiq(unsigned long devhandle,
+					   unsigned long msinum,
+					   unsigned long msiq);
+extern unsigned long pci_sun4v_msg_getvalid(unsigned long devhandle,
+					    unsigned long msinum,
+					    unsigned long *valid);
+extern unsigned long pci_sun4v_msg_setvalid(unsigned long devhandle,
+					    unsigned long msinum,
+					    unsigned long valid);
+
 #endif /* !(_PCI_SUN4V_H) */
diff --git a/arch/sparc64/kernel/pci_sun4v_asm.S b/arch/sparc64/kernel/pci_sun4v_asm.S
index 6604fdb..ecb81f3 100644
--- a/arch/sparc64/kernel/pci_sun4v_asm.S
+++ b/arch/sparc64/kernel/pci_sun4v_asm.S
@@ -93,3 +93,269 @@
 	 mov	-1, %o1
 1:	retl
 	 mov	%o1, %o0
+
+	/* %o0: devhandle
+	 * %o1: msiqid
+	 * %o2: msiq phys address
+	 * %o3: num entries
+	 *
+	 * returns %o0: status
+	 *
+	 * status will be zero if the operation completed
+	 * successfully, else -1 if not
+	 */
+	.globl	pci_sun4v_msiq_conf
+pci_sun4v_msiq_conf:
+	mov	HV_FAST_PCI_MSIQ_CONF, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msiqid
+	 * %o2:	&msiq_phys_addr
+	 * %o3:	&msiq_num_entries
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msiq_info
+pci_sun4v_msiq_info:
+	mov	%o2, %o4
+	mov	HV_FAST_PCI_MSIQ_INFO, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o4]
+	stx	%o2, [%o3]
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msiqid
+	 * %o2:	&valid
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msiq_getvalid
+pci_sun4v_msiq_getvalid:
+	mov	HV_FAST_PCI_MSIQ_GETVALID, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o2]
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msiqid
+	 * %o2:	valid
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msiq_setvalid
+pci_sun4v_msiq_setvalid:
+	mov	HV_FAST_PCI_MSIQ_SETVALID, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msiqid
+	 * %o2:	&state
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msiq_getstate
+pci_sun4v_msiq_getstate:
+	mov	HV_FAST_PCI_MSIQ_GETSTATE, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o2]
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msiqid
+	 * %o2:	state
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msiq_setstate
+pci_sun4v_msiq_setstate:
+	mov	HV_FAST_PCI_MSIQ_SETSTATE, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msiqid
+	 * %o2:	&head
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msiq_gethead
+pci_sun4v_msiq_gethead:
+	mov	HV_FAST_PCI_MSIQ_GETHEAD, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o2]
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msiqid
+	 * %o2:	head
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msiq_sethead
+pci_sun4v_msiq_sethead:
+	mov	HV_FAST_PCI_MSIQ_SETHEAD, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msiqid
+	 * %o2:	&tail
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msiq_gettail
+pci_sun4v_msiq_gettail:
+	mov	HV_FAST_PCI_MSIQ_GETTAIL, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o2]
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msinum
+	 * %o2:	&valid
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msi_getvalid
+pci_sun4v_msi_getvalid:
+	mov	HV_FAST_PCI_MSI_GETVALID, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o2]
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msinum
+	 * %o2:	valid
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msi_setvalid
+pci_sun4v_msi_setvalid:
+	mov	HV_FAST_PCI_MSI_SETVALID, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msinum
+	 * %o2:	&msiq
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msi_getmsiq
+pci_sun4v_msi_getmsiq:
+	mov	HV_FAST_PCI_MSI_GETMSIQ, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o2]
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msinum
+	 * %o2:	msitype
+	 * %o3:	msiq
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msi_setmsiq
+pci_sun4v_msi_setmsiq:
+	mov	HV_FAST_PCI_MSI_SETMSIQ, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msinum
+	 * %o2:	&state
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msi_getstate
+pci_sun4v_msi_getstate:
+	mov	HV_FAST_PCI_MSI_GETSTATE, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o2]
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msinum
+	 * %o2:	state
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msi_setstate
+pci_sun4v_msi_setstate:
+	mov	HV_FAST_PCI_MSI_SETSTATE, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msinum
+	 * %o2:	&msiq
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msg_getmsiq
+pci_sun4v_msg_getmsiq:
+	mov	HV_FAST_PCI_MSG_GETMSIQ, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o2]
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msinum
+	 * %o2:	msiq
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msg_setmsiq
+pci_sun4v_msg_setmsiq:
+	mov	HV_FAST_PCI_MSG_SETMSIQ, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msinum
+	 * %o2:	&valid
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msg_getvalid
+pci_sun4v_msg_getvalid:
+	mov	HV_FAST_PCI_MSG_GETVALID, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o2]
+	retl
+	 mov	%o0, %o0
+
+	/* %o0: devhandle
+	 * %o1: msinum
+	 * %o2:	valid
+	 *
+	 * returns %o0: status
+	 */
+	.globl	pci_sun4v_msg_setvalid
+pci_sun4v_msg_setvalid:
+	mov	HV_FAST_PCI_MSG_SETVALID, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 mov	%o0, %o0
+
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index bf033b3..4510283 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -315,7 +315,7 @@
 {
 	/* Initialize PROM console and command line. */
 	*cmdline_p = prom_getbootargs();
-	strcpy(saved_command_line, *cmdline_p);
+	strcpy(boot_command_line, *cmdline_p);
 
 	if (tlb_type == hypervisor)
 		printk("ARCH: SUN4V\n");
diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c
index 3f619ea..a05e43d 100644
--- a/arch/sparc64/kernel/sunos_ioctl32.c
+++ b/arch/sparc64/kernel/sunos_ioctl32.c
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/termios.h>
+#include <linux/tty.h>
 #include <linux/ioctl.h>
 #include <linux/route.h>
 #include <linux/sockios.h>
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index e27cb71..7876a02 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -459,70 +459,6 @@
 	return sys_sysfs(option, arg1, arg2);
 }
 
-struct sysinfo32 {
-        s32 uptime;
-        u32 loads[3];
-        u32 totalram;
-        u32 freeram;
-        u32 sharedram;
-        u32 bufferram;
-        u32 totalswap;
-        u32 freeswap;
-        unsigned short procs;
-	unsigned short pad;
-	u32 totalhigh;
-	u32 freehigh;
-	u32 mem_unit;
-	char _f[20-2*sizeof(int)-sizeof(int)];
-};
-
-asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info)
-{
-	struct sysinfo s;
-	int ret, err;
-	int bitcount = 0;
-	mm_segment_t old_fs = get_fs ();
-	
-	set_fs(KERNEL_DS);
-	ret = sys_sysinfo((struct sysinfo __user *) &s);
-	set_fs(old_fs);
-	/* Check to see if any memory value is too large for 32-bit and
-         * scale down if needed.
-         */
-	if ((s.totalram >> 32) || (s.totalswap >> 32)) {
-		while (s.mem_unit < PAGE_SIZE) {
-			s.mem_unit <<= 1;
-			bitcount++;
-		}
-		s.totalram >>= bitcount;
-		s.freeram >>= bitcount;
-		s.sharedram >>= bitcount;
-		s.bufferram >>= bitcount;
-		s.totalswap >>= bitcount;
-		s.freeswap >>= bitcount;
-		s.totalhigh >>= bitcount;
-		s.freehigh >>= bitcount;
-	}
-
-	err = put_user (s.uptime, &info->uptime);
-	err |= __put_user (s.loads[0], &info->loads[0]);
-	err |= __put_user (s.loads[1], &info->loads[1]);
-	err |= __put_user (s.loads[2], &info->loads[2]);
-	err |= __put_user (s.totalram, &info->totalram);
-	err |= __put_user (s.freeram, &info->freeram);
-	err |= __put_user (s.sharedram, &info->sharedram);
-	err |= __put_user (s.bufferram, &info->bufferram);
-	err |= __put_user (s.totalswap, &info->totalswap);
-	err |= __put_user (s.freeswap, &info->freeswap);
-	err |= __put_user (s.procs, &info->procs);
-	err |= __put_user (s.totalhigh, &info->totalhigh);
-	err |= __put_user (s.freehigh, &info->freehigh);
-	err |= __put_user (s.mem_unit, &info->mem_unit);
-	if (err)
-		return -EFAULT;
-	return ret;
-}
-
 asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval)
 {
 	struct timespec t;
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 2ebc2c0..4cff95b 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -824,10 +824,17 @@
 	return ret;
 }
 
-extern int kill_pg(int, int, int);
 asmlinkage int sunos_killpg(int pgrp, int sig)
 {
-	return kill_pg(pgrp, sig, 0);
+	int ret;
+
+	rcu_read_lock();
+	ret = -EINVAL;
+	if (pgrp > 0)
+		ret = kill_pgrp(find_pid(pgrp), sig, 0);
+	rcu_read_unlock();
+
+	return ret;
 }
 
 asmlinkage int sunos_audit(void)
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 9a80267..948b7d2 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -61,7 +61,7 @@
 	.word sys32_epoll_wait, sys32_ioprio_set, sys_getppid, sys32_sigaction, sys_sgetmask
 /*200*/	.word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir
 	.word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64
-/*210*/	.word sys32_fadvise64_64, sys32_tgkill, sys32_waitpid, sys_swapoff, sys32_sysinfo
+/*210*/	.word sys32_fadvise64_64, sys32_tgkill, sys32_waitpid, sys_swapoff, compat_sys_sysinfo
 	.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
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 061e1b1..f84da4f 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -1327,7 +1327,7 @@
 }
 
 
-static struct file_operations mini_rtc_fops = {
+static const struct file_operations mini_rtc_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= mini_rtc_ioctl,
 	.open		= mini_rtc_open,
diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
index 4a6063f..13fa2a2 100644
--- a/arch/sparc64/kernel/vmlinux.lds.S
+++ b/arch/sparc64/kernel/vmlinux.lds.S
@@ -81,10 +81,14 @@
   __sun4v_2insn_patch = .;
   .sun4v_2insn_patch : { *(.sun4v_2insn_patch) }
   __sun4v_2insn_patch_end = .;
+
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(8192); 
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
+
   . = ALIGN(8192);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 054822a..b1a1ee0 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -416,7 +416,7 @@
 	printk("Free swap:       %6ldkB\n",
 	       nr_swap_pages << (PAGE_SHIFT-10));
 	printk("%ld pages of RAM\n", num_physpages);
-	printk("%d free pages\n", nr_free_pages());
+	printk("%lu free pages\n", nr_free_pages());
 }
 
 void mmu_info(struct seq_file *m)
@@ -1467,8 +1467,8 @@
 		for (znum = 0; znum < MAX_NR_ZONES; znum++)
 			zones_size[znum] = zholes_size[znum] = 0;
 
-		zones_size[ZONE_DMA] = end_pfn;
-		zholes_size[ZONE_DMA] = end_pfn - pages_avail;
+		zones_size[ZONE_NORMAL] = end_pfn;
+		zholes_size[ZONE_NORMAL] = end_pfn - pages_avail;
 
 		free_area_init_node(0, &contig_page_data, zones_size,
 				    __pa(PAGE_OFFSET) >> PAGE_SHIFT,
@@ -1593,7 +1593,7 @@
 	initpages = (((unsigned long) __init_end) - ((unsigned long) __init_begin));
 	initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT;
 
-	printk("Memory: %uk available (%ldk kernel code, %ldk data, %ldk init) [%016lx,%016lx]\n",
+	printk("Memory: %luk available (%ldk kernel code, %ldk data, %ldk init) [%016lx,%016lx]\n",
 	       nr_free_pages() << (PAGE_SHIFT-10),
 	       codepages << (PAGE_SHIFT-10),
 	       datapages << (PAGE_SHIFT-10), 
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index 89a4757..c286444 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -163,7 +163,7 @@
 	return mask;
 }
 	
-static struct file_operations socksys_fops = {
+static const struct file_operations socksys_fops = {
 	.open =		socksys_open,
 	.release =	socksys_release,
 };
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index d32a80e..b3a21ba 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -16,6 +16,9 @@
 	bool
 	default y
 
+config NO_IOMEM
+	def_bool y
+
 mainmenu "Linux/Usermode Kernel Configuration"
 
 config ISA
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 7d4190e..7b8baf1 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -19,44 +19,11 @@
 #include "line.h"
 #include "os.h"
 
-/* XXX: could well be moved to somewhere else, if needed. */
-static int my_printf(const char * fmt, ...)
-	__attribute__ ((format (printf, 1, 2)));
-
-static int my_printf(const char * fmt, ...)
-{
-	/* Yes, can be called on atomic context.*/
-	char *buf = kmalloc(4096, GFP_ATOMIC);
-	va_list args;
-	int r;
-
-	if (!buf) {
-		/* We print directly fmt.
-		 * Yes, yes, yes, feel free to complain. */
-		r = strlen(fmt);
-	} else {
-		va_start(args, fmt);
-		r = vsprintf(buf, fmt, args);
-		va_end(args);
-		fmt = buf;
-	}
-
-	if (r)
-		r = os_write_file(1, fmt, r);
-	return r;
-
-}
-
 #ifdef CONFIG_NOCONFIG_CHAN
-/* Despite its name, there's no added trailing newline. */
-static int my_puts(const char * buf)
+static void *not_configged_init(char *str, int device,
+				const struct chan_opts *opts)
 {
-	return os_write_file(1, buf, strlen(buf));
-}
-
-static void *not_configged_init(char *str, int device, struct chan_opts *opts)
-{
-	my_puts("Using a channel type which is configured out of "
+	printk("Using a channel type which is configured out of "
 	       "UML\n");
 	return NULL;
 }
@@ -64,34 +31,34 @@
 static int not_configged_open(int input, int output, int primary, void *data,
 			      char **dev_out)
 {
-	my_puts("Using a channel type which is configured out of "
+	printk("Using a channel type which is configured out of "
 	       "UML\n");
 	return -ENODEV;
 }
 
 static void not_configged_close(int fd, void *data)
 {
-	my_puts("Using a channel type which is configured out of "
+	printk("Using a channel type which is configured out of "
 	       "UML\n");
 }
 
 static int not_configged_read(int fd, char *c_out, void *data)
 {
-	my_puts("Using a channel type which is configured out of "
+	printk("Using a channel type which is configured out of "
 	       "UML\n");
 	return -EIO;
 }
 
 static int not_configged_write(int fd, const char *buf, int len, void *data)
 {
-	my_puts("Using a channel type which is configured out of "
+	printk("Using a channel type which is configured out of "
 	       "UML\n");
 	return -EIO;
 }
 
 static int not_configged_console_write(int fd, const char *buf, int len)
 {
-	my_puts("Using a channel type which is configured out of "
+	printk("Using a channel type which is configured out of "
 	       "UML\n");
 	return -EIO;
 }
@@ -99,14 +66,14 @@
 static int not_configged_window_size(int fd, void *data, unsigned short *rows,
 				     unsigned short *cols)
 {
-	my_puts("Using a channel type which is configured out of "
+	printk("Using a channel type which is configured out of "
 	       "UML\n");
 	return -ENODEV;
 }
 
 static void not_configged_free(void *data)
 {
-	my_puts("Using a channel type which is configured out of "
+	printk("Using a channel type which is configured out of "
 	       "UML\n");
 }
 
@@ -255,15 +222,28 @@
 	}
 }
 
+/* Items are added in IRQ context, when free_irq can't be called, and
+ * removed in process context, when it can.
+ * This handles interrupt sources which disappear, and which need to
+ * be permanently disabled.  This is discovered in IRQ context, but
+ * the freeing of the IRQ must be done later.
+ */
+static DEFINE_SPINLOCK(irqs_to_free_lock);
 static LIST_HEAD(irqs_to_free);
 
 void free_irqs(void)
 {
 	struct chan *chan;
+	LIST_HEAD(list);
+	struct list_head *ele;
 
-	while(!list_empty(&irqs_to_free)){
-		chan = list_entry(irqs_to_free.next, struct chan, free_list);
-		list_del(&chan->free_list);
+	spin_lock_irq(&irqs_to_free_lock);
+	list_splice_init(&irqs_to_free, &list);
+	INIT_LIST_HEAD(&irqs_to_free);
+	spin_unlock_irq(&irqs_to_free_lock);
+
+	list_for_each(ele, &list){
+		chan = list_entry(ele, struct chan, free_list);
 
 		if(chan->input)
 			free_irq(chan->line->driver->read_irq, chan);
@@ -279,7 +259,9 @@
 		return;
 
 	if(delay_free_irq){
+		spin_lock_irq(&irqs_to_free_lock);
 		list_add(&chan->free_list, &irqs_to_free);
+		spin_unlock_irq(&irqs_to_free_lock);
 	}
 	else {
 		if(chan->input)
@@ -372,8 +354,7 @@
 	return ret;
 }
 
-int console_open_chan(struct line *line, struct console *co,
-		      const struct chan_opts *opts)
+int console_open_chan(struct line *line, struct console *co)
 {
 	int err;
 
@@ -381,7 +362,7 @@
 	if(err)
 		return err;
 
-	printk("Console initialized on /dev/%s%d\n",co->name,co->index);
+	printk("Console initialized on /dev/%s%d\n", co->name, co->index);
 	return 0;
 }
 
@@ -534,7 +515,7 @@
 };
 
 static struct chan *parse_chan(struct line *line, char *str, int device,
-			       const struct chan_opts *opts)
+			       const struct chan_opts *opts, char **error_out)
 {
 	const struct chan_type *entry;
 	const struct chan_ops *ops;
@@ -553,19 +534,21 @@
 		}
 	}
 	if(ops == NULL){
-		my_printf("parse_chan couldn't parse \"%s\"\n",
-		       str);
+		*error_out = "No match for configured backends";
 		return NULL;
 	}
-	if(ops->init == NULL)
-		return NULL;
+
 	data = (*ops->init)(str, device, opts);
-	if(data == NULL)
+	if(data == NULL){
+		*error_out = "Configuration failed";
 		return NULL;
+	}
 
 	chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
-	if(chan == NULL)
+	if(chan == NULL){
+		*error_out = "Memory allocation failed";
 		return NULL;
+	}
 	*chan = ((struct chan) { .list	 	= LIST_HEAD_INIT(chan->list),
 				 .free_list 	=
 				 	LIST_HEAD_INIT(chan->free_list),
@@ -582,7 +565,7 @@
 }
 
 int parse_chan_pair(char *str, struct line *line, int device,
-		    const struct chan_opts *opts)
+		    const struct chan_opts *opts, char **error_out)
 {
 	struct list_head *chans = &line->chan_list;
 	struct chan *new, *chan;
@@ -599,14 +582,14 @@
 		in = str;
 		*out = '\0';
 		out++;
-		new = parse_chan(line, in, device, opts);
+		new = parse_chan(line, in, device, opts, error_out);
 		if(new == NULL)
 			return -1;
 
 		new->input = 1;
 		list_add(&new->list, chans);
 
-		new = parse_chan(line, out, device, opts);
+		new = parse_chan(line, out, device, opts, error_out);
 		if(new == NULL)
 			return -1;
 
@@ -614,7 +597,7 @@
 		new->output = 1;
 	}
 	else {
-		new = parse_chan(line, str, device, opts);
+		new = parse_chan(line, str, device, opts, error_out);
 		if(new == NULL)
 			return -1;
 
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index 64ff22a..5560168 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -9,10 +9,10 @@
  *	modify it under the terms of the GNU General Public License
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
- *	
- *	Neither Alan Cox nor CymruNet Ltd. admit liability nor provide 
- *	warranty for any of this software. This material is provided 
- *	"AS-IS" and at no charge.	
+ *
+ *	Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *	warranty for any of this software. This material is provided
+ *	"AS-IS" and at no charge.
  *
  *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
@@ -29,11 +29,11 @@
  *	Made SMP safe for 2.3.x
  *
  *  20011127 Joel Becker (jlbec@evilplan.org>
- *	Added soft_noboot; Allows testing the softdog trigger without 
+ *	Added soft_noboot; Allows testing the softdog trigger without
  *	requiring a recompile.
  *	Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
  */
- 
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -44,12 +44,13 @@
 #include <linux/reboot.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/spinlock.h>
 #include <asm/uaccess.h>
 #include "mconsole.h"
 
 MODULE_LICENSE("GPL");
 
-/* Locked by the BKL in harddog_open and harddog_release */
+static DEFINE_SPINLOCK(lock);
 static int timer_alive;
 static int harddog_in_fd = -1;
 static int harddog_out_fd = -1;
@@ -57,18 +58,18 @@
 /*
  *	Allow only one person to hold it open
  */
- 
+
 extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock);
 
 static int harddog_open(struct inode *inode, struct file *file)
 {
-	int err;
+	int err = -EBUSY;
 	char *sock = NULL;
 
-	lock_kernel();
+	spin_lock(&lock);
 	if(timer_alive)
-		return -EBUSY;
-#ifdef CONFIG_HARDDOG_NOWAYOUT	 
+		goto err;
+#ifdef CONFIG_HARDDOG_NOWAYOUT
 	__module_get(THIS_MODULE);
 #endif
 
@@ -76,11 +77,15 @@
 	sock = mconsole_notify_socket();
 #endif
 	err = start_watchdog(&harddog_in_fd, &harddog_out_fd, sock);
-	if(err) return(err);
+	if(err)
+		goto err;
 
 	timer_alive = 1;
-	unlock_kernel();
+	spin_unlock(&lock);
 	return nonseekable_open(inode, file);
+err:
+	spin_unlock(&lock);
+	return err;
 }
 
 extern void stop_watchdog(int in_fd, int out_fd);
@@ -90,14 +95,16 @@
 	/*
 	 *	Shut off the timer.
 	 */
-	lock_kernel();
+
+	spin_lock(&lock);
 
 	stop_watchdog(harddog_in_fd, harddog_out_fd);
 	harddog_in_fd = -1;
 	harddog_out_fd = -1;
 
 	timer_alive=0;
-	unlock_kernel();
+	spin_unlock(&lock);
+
 	return 0;
 }
 
@@ -110,7 +117,7 @@
 	 *	Refresh the timer.
 	 */
 	if(len)
-		return(ping_watchdog(harddog_out_fd));
+		return ping_watchdog(harddog_out_fd);
 	return 0;
 }
 
@@ -134,11 +141,11 @@
 		case WDIOC_GETBOOTSTATUS:
 			return put_user(0,(int __user *)argp);
 		case WDIOC_KEEPALIVE:
-			return(ping_watchdog(harddog_out_fd));
+			return ping_watchdog(harddog_out_fd);
 	}
 }
 
-static struct file_operations harddog_fops = {
+static const struct file_operations harddog_fops = {
 	.owner		= THIS_MODULE,
 	.write		= harddog_write,
 	.ioctl		= harddog_ioctl,
@@ -165,7 +172,7 @@
 
 	printk(banner);
 
-	return(0);
+	return 0;
 }
 
 static void __exit harddog_exit(void)
@@ -175,14 +182,3 @@
 
 module_init(harddog_init);
 module_exit(harddog_exit);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index def013b..c495ecf 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -38,7 +38,7 @@
 	int in_fds[2], out_fds[2], pid, n, err;
 	char pid_buf[sizeof("nnnnn\0")], c;
 	char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
-	char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, 
+	char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
 				  NULL };
 	char **args = NULL;
 
@@ -96,7 +96,7 @@
 	}
 	*in_fd_ret = in_fds[0];
 	*out_fd_ret = out_fds[1];
-	return(0);
+	return 0;
 
  out_close_in:
 	os_close_file(in_fds[0]);
@@ -105,7 +105,7 @@
 	os_close_file(out_fds[0]);
 	os_close_file(out_fds[1]);
  out:
-	return(err);
+	return err;
 }
 
 void stop_watchdog(int in_fd, int out_fd)
@@ -123,20 +123,9 @@
 	if(n != sizeof(c)){
 		printk("ping_watchdog - write failed, err = %d\n", -n);
 		if(n < 0)
-			return(n);
-		return(-EIO);
+			return n;
+		return -EIO;
 	}
 	return 1;
 
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index a0d148ea..10e08a8 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -15,19 +15,22 @@
 #include "os.h"
 
 struct hostaudio_state {
-  int fd;
+	int fd;
 };
 
 struct hostmixer_state {
-  int fd;
+	int fd;
 };
 
 #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
 #define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
 
-/* Only changed from linux_main at boot time */
-char *dsp = HOSTAUDIO_DEV_DSP;
-char *mixer = HOSTAUDIO_DEV_MIXER;
+/* Changed either at boot time or module load time.  At boot, this is
+ * single-threaded; at module load, multiple modules would each have
+ * their own copy of these variables.
+ */
+static char *dsp = HOSTAUDIO_DEV_DSP;
+static char *mixer = HOSTAUDIO_DEV_MIXER;
 
 #define DSP_HELP \
 "    This is used to specify the host dsp device to the hostaudio driver.\n" \
@@ -69,12 +72,12 @@
 static ssize_t hostaudio_read(struct file *file, char __user *buffer,
 			      size_t count, loff_t *ppos)
 {
-        struct hostaudio_state *state = file->private_data;
+	struct hostaudio_state *state = file->private_data;
 	void *kbuf;
 	int err;
 
 #ifdef DEBUG
-        printk("hostaudio: read called, count = %d\n", count);
+	printk("hostaudio: read called, count = %d\n", count);
 #endif
 
 	kbuf = kmalloc(count, GFP_KERNEL);
@@ -88,7 +91,7 @@
 	if(copy_to_user(buffer, kbuf, err))
 		err = -EFAULT;
 
- out:
+out:
 	kfree(kbuf);
 	return(err);
 }
@@ -96,12 +99,12 @@
 static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
 			       size_t count, loff_t *ppos)
 {
-        struct hostaudio_state *state = file->private_data;
+	struct hostaudio_state *state = file->private_data;
 	void *kbuf;
 	int err;
 
 #ifdef DEBUG
-        printk("hostaudio: write called, count = %d\n", count);
+	printk("hostaudio: write called, count = %d\n", count);
 #endif
 
 	kbuf = kmalloc(count, GFP_KERNEL);
@@ -125,24 +128,24 @@
 static unsigned int hostaudio_poll(struct file *file, 
 				   struct poll_table_struct *wait)
 {
-        unsigned int mask = 0;
+	unsigned int mask = 0;
 
 #ifdef DEBUG
-        printk("hostaudio: poll called (unimplemented)\n");
+	printk("hostaudio: poll called (unimplemented)\n");
 #endif
 
-        return(mask);
+	return(mask);
 }
 
 static int hostaudio_ioctl(struct inode *inode, struct file *file, 
 			   unsigned int cmd, unsigned long arg)
 {
-        struct hostaudio_state *state = file->private_data;
+	struct hostaudio_state *state = file->private_data;
 	unsigned long data = 0;
 	int err;
 
 #ifdef DEBUG
-        printk("hostaudio: ioctl called, cmd = %u\n", cmd);
+	printk("hostaudio: ioctl called, cmd = %u\n", cmd);
 #endif
 	switch(cmd){
 	case SNDCTL_DSP_SPEED:
@@ -179,42 +182,40 @@
 
 static int hostaudio_open(struct inode *inode, struct file *file)
 {
-        struct hostaudio_state *state;
-        int r = 0, w = 0;
-        int ret;
+	struct hostaudio_state *state;
+	int r = 0, w = 0;
+	int ret;
 
 #ifdef DEBUG
-        printk("hostaudio: open called (host: %s)\n", dsp);
+	printk("hostaudio: open called (host: %s)\n", dsp);
 #endif
 
-        state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
-        if(state == NULL)
+	state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
+	if(state == NULL)
 		return(-ENOMEM);
 
-        if(file->f_mode & FMODE_READ) r = 1;
-        if(file->f_mode & FMODE_WRITE) w = 1;
+	if(file->f_mode & FMODE_READ) r = 1;
+	if(file->f_mode & FMODE_WRITE) w = 1;
 
 	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
-        if(ret < 0){
+	if(ret < 0){
 		kfree(state);
 		return(ret);
-        }
-
+	}
 	state->fd = ret;
-        file->private_data = state;
-        return(0);
+	file->private_data = state;
+	return(0);
 }
 
 static int hostaudio_release(struct inode *inode, struct file *file)
 {
-        struct hostaudio_state *state = file->private_data;
+	struct hostaudio_state *state = file->private_data;
 
 #ifdef DEBUG
-        printk("hostaudio: release called\n");
+	printk("hostaudio: release called\n");
 #endif
-
-		os_close_file(state->fd);
-        kfree(state);
+	os_close_file(state->fd);
+	kfree(state);
 
 	return(0);
 }
@@ -224,10 +225,10 @@
 static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, 
 				  unsigned int cmd, unsigned long arg)
 {
-        struct hostmixer_state *state = file->private_data;
+	struct hostmixer_state *state = file->private_data;
 
 #ifdef DEBUG
-        printk("hostmixer: ioctl called\n");
+	printk("hostmixer: ioctl called\n");
 #endif
 
 	return(os_ioctl_generic(state->fd, cmd, arg));
@@ -235,68 +236,67 @@
 
 static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
 {
-        struct hostmixer_state *state;
-        int r = 0, w = 0;
-        int ret;
+	struct hostmixer_state *state;
+	int r = 0, w = 0;
+	int ret;
 
 #ifdef DEBUG
-        printk("hostmixer: open called (host: %s)\n", mixer);
+	printk("hostmixer: open called (host: %s)\n", mixer);
 #endif
 
-        state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL);
-        if(state == NULL) return(-ENOMEM);
+	state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL);
+	if(state == NULL) return(-ENOMEM);
 
-        if(file->f_mode & FMODE_READ) r = 1;
-        if(file->f_mode & FMODE_WRITE) w = 1;
+	if(file->f_mode & FMODE_READ) r = 1;
+	if(file->f_mode & FMODE_WRITE) w = 1;
 
 	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
         
-        if(ret < 0){
+	if(ret < 0){
 		printk("hostaudio_open_mixdev failed to open '%s', err = %d\n",
 		       dsp, -ret);
 		kfree(state);
 		return(ret);
-        }
+	}
 
-        file->private_data = state;
-        return(0);
+	file->private_data = state;
+	return(0);
 }
 
 static int hostmixer_release(struct inode *inode, struct file *file)
 {
-        struct hostmixer_state *state = file->private_data;
+	struct hostmixer_state *state = file->private_data;
 
 #ifdef DEBUG
-        printk("hostmixer: release called\n");
+	printk("hostmixer: release called\n");
 #endif
 
-		os_close_file(state->fd);
-        kfree(state);
+	os_close_file(state->fd);
+	kfree(state);
 
 	return(0);
 }
 
-
 /* kernel module operations */
 
 static const struct file_operations hostaudio_fops = {
-        .owner          = THIS_MODULE,
-        .llseek         = no_llseek,
-        .read           = hostaudio_read,
-        .write          = hostaudio_write,
-        .poll           = hostaudio_poll,
-        .ioctl          = hostaudio_ioctl,
-        .mmap           = NULL,
-        .open           = hostaudio_open,
-        .release        = hostaudio_release,
+	.owner          = THIS_MODULE,
+	.llseek         = no_llseek,
+	.read           = hostaudio_read,
+	.write          = hostaudio_write,
+	.poll           = hostaudio_poll,
+	.ioctl          = hostaudio_ioctl,
+	.mmap           = NULL,
+	.open           = hostaudio_open,
+	.release        = hostaudio_release,
 };
 
 static const struct file_operations hostmixer_fops = {
-        .owner          = THIS_MODULE,
-        .llseek         = no_llseek,
-        .ioctl          = hostmixer_ioctl_mixdev,
-        .open           = hostmixer_open_mixdev,
-        .release        = hostmixer_release,
+	.owner          = THIS_MODULE,
+	.llseek         = no_llseek,
+	.ioctl          = hostmixer_ioctl_mixdev,
+	.open           = hostmixer_open_mixdev,
+	.release        = hostmixer_release,
 };
 
 struct {
@@ -310,42 +310,31 @@
 
 static int __init hostaudio_init_module(void)
 {
-        printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
+	printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
 	       dsp, mixer);
 
 	module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
-        if(module_data.dev_audio < 0){
-                printk(KERN_ERR "hostaudio: couldn't register DSP device!\n");
-                return -ENODEV;
-        }
+	if(module_data.dev_audio < 0){
+		printk(KERN_ERR "hostaudio: couldn't register DSP device!\n");
+		return -ENODEV;
+	}
 
 	module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1);
-        if(module_data.dev_mixer < 0){
-                printk(KERN_ERR "hostmixer: couldn't register mixer "
+	if(module_data.dev_mixer < 0){
+		printk(KERN_ERR "hostmixer: couldn't register mixer "
 		       "device!\n");
-                unregister_sound_dsp(module_data.dev_audio);
-                return -ENODEV;
-        }
+		unregister_sound_dsp(module_data.dev_audio);
+		return -ENODEV;
+	}
 
-        return 0;
+	return 0;
 }
 
 static void __exit hostaudio_cleanup_module (void)
 {
-       unregister_sound_mixer(module_data.dev_mixer);
-       unregister_sound_dsp(module_data.dev_audio);
+	unregister_sound_mixer(module_data.dev_mixer);
+	unregister_sound_dsp(module_data.dev_audio);
 }
 
 module_init(hostaudio_init_module);
 module_exit(hostaudio_cleanup_module);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 83301e1..01d4ab6 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -191,7 +191,6 @@
 	/*XXX: copied from line_write, verify if it is correct!*/
 	if(tty->stopped)
 		return;
-		//return 0;
 
 	spin_lock_irqsave(&line->lock, flags);
 	err = flush_buffer(line);
@@ -421,42 +420,55 @@
 	return err;
 }
 
+/* Normally, a driver like this can rely mostly on the tty layer
+ * locking, particularly when it comes to the driver structure.
+ * However, in this case, mconsole requests can come in "from the
+ * side", and race with opens and closes.
+ *
+ * mconsole config requests will want to be sure the device isn't in
+ * use, and get_config, open, and close will want a stable
+ * configuration.  The checking and modification of the configuration
+ * is done under a spinlock.  Checking whether the device is in use is
+ * line->tty->count > 1, also under the spinlock.
+ *
+ * tty->count serves to decide whether the device should be enabled or
+ * disabled on the host.  If it's equal to 1, then we are doing the
+ * first open or last close.  Otherwise, open and close just return.
+ */
+
 int line_open(struct line *lines, struct tty_struct *tty)
 {
-	struct line *line;
+	struct line *line = &lines[tty->index];
 	int err = -ENODEV;
 
-	line = &lines[tty->index];
-	tty->driver_data = line;
+	spin_lock(&line->count_lock);
+	if(!line->valid)
+		goto out_unlock;
 
-	/* The IRQ which takes this lock is not yet enabled and won't be run
-	 * before the end, so we don't need to use spin_lock_irq.*/
-	spin_lock(&line->lock);
+	err = 0;
+	if(tty->count > 1)
+		goto out_unlock;
+
+	spin_unlock(&line->count_lock);
 
 	tty->driver_data = line;
 	line->tty = tty;
-	if(!line->valid)
-		goto out;
 
-	if(tty->count == 1){
-		/* Here the device is opened, if necessary, and interrupt
-		 * is registered.
-		 */
-		enable_chan(line);
-		INIT_DELAYED_WORK(&line->task, line_timer_cb);
+	enable_chan(line);
+	INIT_DELAYED_WORK(&line->task, line_timer_cb);
 
-		if(!line->sigio){
-			chan_enable_winch(&line->chan_list, tty);
-			line->sigio = 1;
-		}
-
-		chan_window_size(&line->chan_list, &tty->winsize.ws_row,
-				 &tty->winsize.ws_col);
+	if(!line->sigio){
+		chan_enable_winch(&line->chan_list, tty);
+		line->sigio = 1;
 	}
 
-	err = 0;
-out:
-	spin_unlock(&line->lock);
+	chan_window_size(&line->chan_list, &tty->winsize.ws_row,
+			 &tty->winsize.ws_col);
+
+	return err;
+
+out_unlock:
+	spin_unlock(&line->count_lock);
 	return err;
 }
 
@@ -466,25 +478,36 @@
 {
 	struct line *line = tty->driver_data;
 
-	/* XXX: I assume this should be called in process context, not with
-         *  interrupts disabled!
-         */
-	spin_lock_irq(&line->lock);
+	/* If line_open fails (and tty->driver_data is never set),
+	 * tty_open will call line_close.  So just return in this case.
+	 */
+	if(line == NULL)
+		return;
 
 	/* We ignore the error anyway! */
 	flush_buffer(line);
 
-	if(tty->count == 1){
-		line->tty = NULL;
-		tty->driver_data = NULL;
+	spin_lock(&line->count_lock);
+	if(!line->valid)
+		goto out_unlock;
 
-		if(line->sigio){
-			unregister_winch(tty);
-			line->sigio = 0;
-		}
+	if(tty->count > 1)
+		goto out_unlock;
+
+	spin_unlock(&line->count_lock);
+
+	line->tty = NULL;
+	tty->driver_data = NULL;
+
+	if(line->sigio){
+		unregister_winch(tty);
+		line->sigio = 0;
         }
 
-	spin_unlock_irq(&line->lock);
+	return;
+
+out_unlock:
+	spin_unlock(&line->count_lock);
 }
 
 void close_lines(struct line *lines, int nlines)
@@ -495,14 +518,44 @@
 		close_chan(&lines[i].chan_list, 0);
 }
 
+static int setup_one_line(struct line *lines, int n, char *init, int init_prio,
+			  char **error_out)
+{
+	struct line *line = &lines[n];
+	int err = -EINVAL;
+
+	spin_lock(&line->count_lock);
+
+	if(line->tty != NULL){
+		*error_out = "Device is already open";
+		goto out;
+	}
+
+	if (line->init_pri <= init_prio){
+		line->init_pri = init_prio;
+		if (!strcmp(init, "none"))
+			line->valid = 0;
+		else {
+			line->init_str = init;
+			line->valid = 1;
+		}
+	}
+	err = 0;
+out:
+	spin_unlock(&line->count_lock);
+	return err;
+}
+
 /* Common setup code for both startup command line and mconsole initialization.
  * @lines contains the array (of size @num) to modify;
  * @init is the setup string;
+ * @error_out is an error string in the case of failure;
  */
 
-int line_setup(struct line *lines, unsigned int num, char *init)
+int line_setup(struct line *lines, unsigned int num, char *init,
+	       char **error_out)
 {
-	int i, n;
+	int i, n, err;
 	char *end;
 
 	if(*init == '=') {
@@ -513,73 +566,56 @@
 	else {
 		n = simple_strtoul(init, &end, 0);
 		if(*end != '='){
-			printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
-			       init);
-			return 0;
+			*error_out = "Couldn't parse device number";
+			return -EINVAL;
 		}
 		init = end;
 	}
 	init++;
 
 	if (n >= (signed int) num) {
-		printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
-		       n, num - 1);
-		return 0;
+		*error_out = "Device number out of range";
+		return -EINVAL;
 	}
 	else if (n >= 0){
-		if (lines[n].tty != NULL) {
-			printk("line_setup - device %d is open\n", n);
-			return 0;
-		}
-		if (lines[n].init_pri <= INIT_ONE){
-			lines[n].init_pri = INIT_ONE;
-			if (!strcmp(init, "none"))
-				lines[n].valid = 0;
-			else {
-				lines[n].init_str = init;
-				lines[n].valid = 1;
-			}
-		}
+		err = setup_one_line(lines, n, init, INIT_ONE, error_out);
+		if(err)
+			return err;
 	}
 	else {
 		for(i = 0; i < num; i++){
-			if(lines[i].init_pri <= INIT_ALL){
-				lines[i].init_pri = INIT_ALL;
-				if(!strcmp(init, "none")) lines[i].valid = 0;
-				else {
-					lines[i].init_str = init;
-					lines[i].valid = 1;
-				}
-			}
+			err = setup_one_line(lines, i, init, INIT_ALL,
+					     error_out);
+			if(err)
+				return err;
 		}
 	}
 	return n == -1 ? num : n;
 }
 
 int line_config(struct line *lines, unsigned int num, char *str,
-		const struct chan_opts *opts)
+		const struct chan_opts *opts, char **error_out)
 {
 	struct line *line;
 	char *new;
 	int n;
 
 	if(*str == '='){
-		printk("line_config - can't configure all devices from "
-		       "mconsole\n");
-		return 1;
+		*error_out = "Can't configure all devices from mconsole";
+		return -EINVAL;
 	}
 
 	new = kstrdup(str, GFP_KERNEL);
 	if(new == NULL){
-		printk("line_config - kstrdup failed\n");
-		return 1;
+		*error_out = "Failed to allocate memory";
+		return -ENOMEM;
 	}
-	n = line_setup(lines, num, new);
+	n = line_setup(lines, num, new, error_out);
 	if(n < 0)
-		return 1;
+		return n;
 
 	line = &lines[n];
-	return parse_chan_pair(line->init_str, line, n, opts);
+	return parse_chan_pair(line->init_str, line, n, opts, error_out);
 }
 
 int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
@@ -602,13 +638,13 @@
 
 	line = &lines[dev];
 
-	spin_lock(&line->lock);
+	spin_lock(&line->count_lock);
 	if(!line->valid)
 		CONFIG_CHUNK(str, size, n, "none", 1);
 	else if(line->tty == NULL)
 		CONFIG_CHUNK(str, size, n, line->init_str, 1);
 	else n = chan_config_string(&line->chan_list, str, size, error_out);
-	spin_unlock(&line->lock);
+	spin_unlock(&line->count_lock);
 
 	return n;
 }
@@ -628,22 +664,21 @@
         return n;
 }
 
-int line_remove(struct line *lines, unsigned int num, int n)
+int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
 {
 	int err;
 	char config[sizeof("conxxxx=none\0")];
 
 	sprintf(config, "%d=none", n);
-	err = line_setup(lines, num, config);
+	err = line_setup(lines, num, config, error_out);
 	if(err >= 0)
 		err = 0;
 	return err;
 }
 
-struct tty_driver *line_register_devfs(struct lines *set,
-				       struct line_driver *line_driver,
-				       const struct tty_operations *ops,
-				       struct line *lines, int nlines)
+struct tty_driver *register_lines(struct line_driver *line_driver,
+				  const struct tty_operations *ops,
+				  struct line *lines, int nlines)
 {
 	int i;
 	struct tty_driver *driver = alloc_tty_driver(nlines);
@@ -683,6 +718,7 @@
 void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
 {
 	struct line *line;
+	char *error;
 	int i;
 
 	for(i = 0; i < nlines; i++){
@@ -696,8 +732,9 @@
 		if(line->init_str == NULL)
 			printk("lines_init - kstrdup returned NULL\n");
 
-		if(parse_chan_pair(line->init_str, line, i, opts)){
-			printk("parse_chan_pair failed for device %d\n", i);
+		if(parse_chan_pair(line->init_str, line, i, opts, &error)){
+			printk("parse_chan_pair failed for device %d : %s\n",
+			       i, error);
 			line->valid = 0;
 		}
 	}
@@ -737,7 +774,7 @@
 		line = tty->driver_data;
 		chan_window_size(&line->chan_list, &tty->winsize.ws_row,
 				 &tty->winsize.ws_col);
-		kill_pg(tty->pgrp, SIGWINCH, 1);
+		kill_pgrp(tty->pgrp, SIGWINCH, 1);
 	}
  out:
 	if(winch->fd != -1)
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 96f0189..178b2ef 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -33,7 +33,6 @@
 #include "irq_user.h"
 #include "init.h"
 #include "os.h"
-#include "umid.h"
 #include "irq_kern.h"
 #include "choose-mode.h"
 
@@ -337,13 +336,15 @@
 	mconsole_reply(req, "", 0, 0);
 }
 
-/* This list is populated by __initcall routines. */
-
+static DEFINE_SPINLOCK(mc_devices_lock);
 static LIST_HEAD(mconsole_devices);
 
 void mconsole_register_dev(struct mc_device *new)
 {
+	spin_lock(&mc_devices_lock);
+	BUG_ON(!list_empty(&new->list));
 	list_add(&new->list, &mconsole_devices);
+	spin_unlock(&mc_devices_lock);
 }
 
 static struct mc_device *mconsole_find_dev(char *name)
@@ -367,18 +368,21 @@
 	void *pages[UNPLUGGED_PER_PAGE];
 };
 
+static DECLARE_MUTEX(plug_mem_mutex);
 static unsigned long long unplugged_pages_count = 0;
-static struct list_head unplugged_pages = LIST_HEAD_INIT(unplugged_pages);
+static LIST_HEAD(unplugged_pages);
 static int unplug_index = UNPLUGGED_PER_PAGE;
 
-static int mem_config(char *str)
+static int mem_config(char *str, char **error_out)
 {
 	unsigned long long diff;
 	int err = -EINVAL, i, add;
 	char *ret;
 
-	if(str[0] != '=')
+	if(str[0] != '='){
+		*error_out = "Expected '=' after 'mem'";
 		goto out;
+	}
 
 	str++;
 	if(str[0] == '-')
@@ -386,15 +390,21 @@
 	else if(str[0] == '+'){
 		add = 1;
 	}
-	else goto out;
+	else {
+		*error_out = "Expected increment to start with '-' or '+'";
+		goto out;
+	}
 
 	str++;
 	diff = memparse(str, &ret);
-	if(*ret != '\0')
+	if(*ret != '\0'){
+		*error_out = "Failed to parse memory increment";
 		goto out;
+	}
 
 	diff /= PAGE_SIZE;
 
+	down(&plug_mem_mutex);
 	for(i = 0; i < diff; i++){
 		struct unplugged_pages *unplugged;
 		void *addr;
@@ -435,11 +445,14 @@
 				unplugged = list_entry(entry,
 						       struct unplugged_pages,
 						       list);
-				unplugged->pages[unplug_index++] = addr;
 				err = os_drop_memory(addr, PAGE_SIZE);
-				if(err)
+				if(err){
 					printk("Failed to release memory - "
 					       "errno = %d\n", err);
+					*error_out = "Failed to release memory";
+					goto out_unlock;
+				}
+				unplugged->pages[unplug_index++] = addr;
 			}
 
 			unplugged_pages_count++;
@@ -447,6 +460,8 @@
 	}
 
 	err = 0;
+out_unlock:
+	up(&plug_mem_mutex);
 out:
 	return err;
 }
@@ -470,12 +485,14 @@
 	return 0;
 }
 
-static int mem_remove(int n)
+static int mem_remove(int n, char **error_out)
 {
+	*error_out = "Memory doesn't support the remove operation";
 	return -EBUSY;
 }
 
 static struct mc_device mem_mc = {
+	.list		= LIST_HEAD_INIT(mem_mc.list),
 	.name		= "mem",
 	.config		= mem_config,
 	.get_config	= mem_get_config,
@@ -542,7 +559,7 @@
 void mconsole_config(struct mc_request *req)
 {
 	struct mc_device *dev;
-	char *ptr = req->request.data, *name;
+	char *ptr = req->request.data, *name, *error_string = "";
 	int err;
 
 	ptr += strlen("config");
@@ -559,8 +576,8 @@
 		ptr++;
 
 	if(*ptr == '='){
-		err = (*dev->config)(name);
-		mconsole_reply(req, "", err, 0);
+		err = (*dev->config)(name, &error_string);
+		mconsole_reply(req, error_string, err, 0);
 	}
 	else mconsole_get_config(dev->get_config, req, name);
 }
@@ -595,13 +612,16 @@
 		goto out;
 	}
 
-	err = (*dev->remove)(n);
+	err_msg = NULL;
+	err = (*dev->remove)(n, &err_msg);
 	switch(err){
 	case -ENODEV:
-		err_msg = "Device doesn't exist";
+		if(err_msg == NULL)
+			err_msg = "Device doesn't exist";
 		break;
 	case -EBUSY:
-		err_msg = "Device is currently open";
+		if(err_msg == NULL)
+			err_msg = "Device is currently open";
 		break;
 	default:
 		break;
@@ -615,7 +635,7 @@
 	struct mc_request *req;
 };
 
-static DEFINE_SPINLOCK(console_lock);
+static DEFINE_SPINLOCK(client_lock);
 static LIST_HEAD(clients);
 static char console_buf[MCONSOLE_MAX_DATA];
 static int console_index = 0;
@@ -670,16 +690,18 @@
 	unsigned long flags;
 
 	entry.req = req;
+	spin_lock_irqsave(&client_lock, flags);
 	list_add(&entry.list, &clients);
-	spin_lock_irqsave(&console_lock, flags);
+	spin_unlock_irqrestore(&client_lock, flags);
 
 	(*proc)(arg);
 
 	mconsole_reply_len(req, console_buf, console_index, 0, 0);
 	console_index = 0;
 
-	spin_unlock_irqrestore(&console_lock, flags);
+	spin_lock_irqsave(&client_lock, flags);
 	list_del(&entry.list);
+	spin_unlock_irqrestore(&client_lock, flags);
 }
 
 #ifdef CONFIG_MAGIC_SYSRQ
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 75aef6f..f02634f 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -16,7 +16,7 @@
 #include "user.h"
 #include "sysdep/ptrace.h"
 #include "mconsole.h"
-#include "umid.h"
+#include "os.h"
 #include "user_util.h"
 
 static struct mconsole_command commands[] = {
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index afe3d42..04e31f8 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 
+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
  * James Leu (jleu@mindspring.net).
  * Copyright (C) 2001 by various other people who didn't put their name here.
  * Licensed under the GPL.
@@ -91,8 +91,8 @@
 	spin_lock(&lp->lock);
 	while((err = uml_net_rx(dev)) > 0) ;
 	if(err < 0) {
-		printk(KERN_ERR 
-		       "Device '%s' read returned %d, shutting it down\n", 
+		printk(KERN_ERR
+		       "Device '%s' read returned %d, shutting it down\n",
 		       dev->name, err);
 		/* dev_close can't be called in interrupt context, and takes
 		 * again lp->lock.
@@ -108,7 +108,7 @@
 
 out:
 	spin_unlock(&lp->lock);
-	return(IRQ_HANDLED);
+	return IRQ_HANDLED;
 }
 
 static int uml_net_open(struct net_device *dev)
@@ -159,7 +159,7 @@
 static int uml_net_close(struct net_device *dev)
 {
 	struct uml_net_private *lp = dev->priv;
-	
+
 	netif_stop_queue(dev);
 
 	free_irq(dev->irq, dev);
@@ -194,7 +194,7 @@
 
 		/* this is normally done in the interrupt when tx finishes */
 		netif_wake_queue(dev);
-	} 
+	}
 	else if(len == 0){
 		netif_start_queue(dev);
 		lp->stats.tx_dropped++;
@@ -239,7 +239,7 @@
 	set_ether_mac(dev, hwaddr->sa_data);
 	spin_unlock_irq(&lp->lock);
 
-	return(0);
+	return 0;
 }
 
 static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
@@ -333,7 +333,7 @@
 	struct uml_net_private *lp;
 	int save, err, size;
 
-	size = transport->private_size + sizeof(struct uml_net_private) + 
+	size = transport->private_size + sizeof(struct uml_net_private) +
 		sizeof(((struct uml_net_private *) 0)->user);
 
 	device = kzalloc(sizeof(*device), GFP_KERNEL);
@@ -438,7 +438,7 @@
 	lp->tl.function = uml_net_user_timer_expire;
 	memcpy(lp->mac, device->mac, sizeof(lp->mac));
 
-	if (transport->user->init) 
+	if (transport->user->init)
 		(*transport->user->init)(&lp->user, dev);
 
 	set_ether_mac(dev, device->mac);
@@ -460,38 +460,36 @@
 	device = NULL;
  out:
 	spin_unlock(&devices_lock);
-	return(device);
+	return device;
 }
 
-static int eth_parse(char *str, int *index_out, char **str_out)
+static int eth_parse(char *str, int *index_out, char **str_out,
+		     char **error_out)
 {
 	char *end;
-	int n;
+	int n, err = -EINVAL;;
 
 	n = simple_strtoul(str, &end, 0);
 	if(end == str){
-		printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str);
-		return(1);
+		*error_out = "Bad device number";
+		return err;
 	}
-	if(n < 0){
-		printk(KERN_ERR "eth_setup: device %d is negative\n", n);
-		return(1);
-	}
+
 	str = end;
 	if(*str != '='){
-		printk(KERN_ERR 
-		       "eth_setup: expected '=' after device number\n");
-		return(1);
+		*error_out = "Expected '=' after device number";
+		return err;
 	}
+
 	str++;
 	if(find_device(n)){
-		printk(KERN_ERR "eth_setup: Device %d already configured\n",
-		       n);
-		return(1);
+		*error_out = "Device already configured";
+		return err;
 	}
-	if(index_out) *index_out = n;
+
+	*index_out = n;
 	*str_out = str;
-	return(0);
+	return 0;
 }
 
 struct eth_init {
@@ -500,13 +498,11 @@
 	int index;
 };
 
-/* Filled in at boot time.  Will need locking if the transports become
- * modular.
- */
-struct list_head transports = LIST_HEAD_INIT(transports);
+static DEFINE_SPINLOCK(transports_lock);
+static LIST_HEAD(transports);
 
 /* Filled in during early boot */
-struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
+static LIST_HEAD(eth_cmd_line);
 
 static int check_transport(struct transport *transport, char *eth, int n,
 			   void **init_out, char **mac_out)
@@ -515,23 +511,23 @@
 
 	len = strlen(transport->name);
 	if(strncmp(eth, transport->name, len))
-		return(0);
+		return 0;
 
 	eth += len;
 	if(*eth == ',')
 		eth++;
 	else if(*eth != '\0')
-		return(0);
+		return 0;
 
 	*init_out = kmalloc(transport->setup_size, GFP_KERNEL);
 	if(*init_out == NULL)
-		return(1);
+		return 1;
 
 	if(!transport->setup(eth, mac_out, *init_out)){
 		kfree(*init_out);
 		*init_out = NULL;
 	}
-	return(1);
+	return 1;
 }
 
 void register_transport(struct transport *new)
@@ -542,7 +538,10 @@
 	char *mac = NULL;
 	int match;
 
+	spin_lock(&transports_lock);
+	BUG_ON(!list_empty(&new->list));
 	list_add(&new->list, &transports);
+	spin_unlock(&transports_lock);
 
 	list_for_each_safe(ele, next, &eth_cmd_line){
 		eth = list_entry(ele, struct eth_init, list);
@@ -564,7 +563,9 @@
 	struct transport *transport;
 	void *init;
 	char *mac = NULL;
+	int found = 0;
 
+	spin_lock(&transports_lock);
 	list_for_each(ele, &transports){
 		transport = list_entry(ele, struct transport, list);
 	        if(!check_transport(transport, str, index, &init, &mac))
@@ -573,19 +574,26 @@
 			eth_configure(index, init, mac, transport);
 			kfree(init);
 		}
-		return(1);
+		found = 1;
+		break;
 	}
-	return(0);
+
+	spin_unlock(&transports_lock);
+	return found;
 }
 
 static int eth_setup(char *str)
 {
 	struct eth_init *new;
+	char *error;
 	int n, err;
 
-	err = eth_parse(str, &n, &str);
-	if(err)
+	err = eth_parse(str, &n, &str, &error);
+	if(err){
+		printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n",
+		       str, error);
 		return 1;
+	}
 
 	new = alloc_bootmem(sizeof(*new));
 	if (new == NULL){
@@ -607,38 +615,24 @@
 "    Configure a network device.\n\n"
 );
 
-#if 0
-static int eth_init(void)
-{
-	struct list_head *ele, *next;
-	struct eth_init *eth;
-
-	list_for_each_safe(ele, next, &eth_cmd_line){
-		eth = list_entry(ele, struct eth_init, list);
-
-		if(eth_setup_common(eth->init, eth->index))
-			list_del(&eth->list);
-	}
-	
-	return(1);
-}
-__initcall(eth_init);
-#endif
-
-static int net_config(char *str)
+static int net_config(char *str, char **error_out)
 {
 	int n, err;
 
-	err = eth_parse(str, &n, &str);
-	if(err) return(err);
+	err = eth_parse(str, &n, &str, error_out);
+	if(err)
+		return err;
 
+	/* This string is broken up and the pieces used by the underlying
+	 * driver.  So, it is freed only if eth_setup_common fails.
+	 */
 	str = kstrdup(str, GFP_KERNEL);
 	if(str == NULL){
-		printk(KERN_ERR "net_config failed to strdup string\n");
-		return(-1);
+	        *error_out = "net_config failed to strdup string";
+		return -ENOMEM;
 	}
 	err = !eth_setup_common(str, n);
-	if(err) 
+	if(err)
 		kfree(str);
 	return(err);
 }
@@ -658,7 +652,7 @@
         return n;
 }
 
-static int net_remove(int n)
+static int net_remove(int n, char **error_out)
 {
 	struct uml_net *device;
 	struct net_device *dev;
@@ -671,7 +665,7 @@
 	dev = device->dev;
 	lp = dev->priv;
 	if(lp->fd > 0)
-                return -EBUSY;
+		return -EBUSY;
 	if(lp->remove != NULL) (*lp->remove)(&lp->user);
 	unregister_netdev(dev);
 	platform_device_unregister(&device->pdev);
@@ -683,10 +677,11 @@
 }
 
 static struct mc_device net_mc = {
+	.list		= LIST_HEAD_INIT(net_mc.list),
 	.name		= "eth",
 	.config		= net_config,
 	.get_config	= NULL,
-        .id		= net_id,
+	.id		= net_id,
 	.remove		= net_remove,
 };
 
@@ -699,7 +694,8 @@
 	void (*proc)(unsigned char *, unsigned char *, void *);
 	unsigned char addr_buf[4], netmask_buf[4];
 
-	if(dev->open != uml_net_open) return(NOTIFY_DONE);
+	if(dev->open != uml_net_open)
+		return NOTIFY_DONE;
 
 	lp = dev->priv;
 
@@ -717,9 +713,10 @@
 		memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf));
 		(*proc)(addr_buf, netmask_buf, &lp->user);
 	}
-	return(NOTIFY_DONE);
+	return NOTIFY_DONE;
 }
 
+/* uml_net_init shouldn't be called twice on two CPUs at the same time */
 struct notifier_block uml_inetaddr_notifier = {
 	.notifier_call		= uml_inetaddr_event,
 };
@@ -727,7 +724,7 @@
 static int uml_net_init(void)
 {
 	struct list_head *ele;
-	struct uml_net_private *lp;	
+	struct uml_net_private *lp;
 	struct in_device *ip;
 	struct in_ifaddr *in;
 
@@ -738,18 +735,21 @@
 	 * didn't get a chance to run for them.  This fakes it so that
 	 * addresses which have already been set up get handled properly.
 	 */
+	spin_lock(&opened_lock);
 	list_for_each(ele, &opened){
 		lp = list_entry(ele, struct uml_net_private, list);
 		ip = lp->dev->ip_ptr;
-		if(ip == NULL) continue;
+		if(ip == NULL)
+			continue;
 		in = ip->ifa_list;
 		while(in != NULL){
 			uml_inetaddr_event(NULL, NETDEV_UP, in);
 			in = in->ifa_next;
 		}
-	}	
+	}
+	spin_unlock(&opened_lock);
 
-	return(0);
+	return 0;
 }
 
 __initcall(uml_net_init);
@@ -759,13 +759,16 @@
 	struct list_head *ele;
 	struct uml_net_private *lp;
 
+	spin_lock(&opened_lock);
 	list_for_each(ele, &opened){
 		lp = list_entry(ele, struct uml_net_private, list);
 		free_irq(lp->dev->irq, lp->dev);
 		if((lp->close != NULL) && (lp->fd >= 0))
 			(*lp->close)(lp->fd, &lp->user);
-		if(lp->remove != NULL) (*lp->remove)(&lp->user);
+		if(lp->remove != NULL)
+			(*lp->remove)(&lp->user);
 	}
+	spin_unlock(&opened_lock);
 }
 
 __uml_exitcall(close_devices);
@@ -783,8 +786,8 @@
 	return(skb);
 }
 
-void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, 
-					void *), 
+void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
+					void *),
 		    void *arg)
 {
 	struct net_device *dev = d;
@@ -809,11 +812,11 @@
 	struct in_ifaddr *in;
 	__be32 *mask_out = m;
 
-	if(ip == NULL) 
+	if(ip == NULL)
 		return(1);
 
 	in = ip->ifa_list;
-	if(in == NULL) 
+	if(in == NULL)
 		return(1);
 
 	*mask_out = in->ifa_mask;
@@ -827,7 +830,7 @@
 	ret = (void *) __get_free_pages(GFP_KERNEL, 0);
 	if(ret) *len_out = PAGE_SIZE;
 	else *len_out = 0;
-	return(ret);
+	return ret;
 }
 
 void free_output_buffer(void *buffer)
@@ -835,7 +838,7 @@
 	free_pages((unsigned long) buffer, 0);
 }
 
-int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, 
+int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out,
 		     char **gate_addr)
 {
 	char *remain;
@@ -854,14 +857,3 @@
 {
 	return(eth_type_trans(skb, skb->dev));
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 6dfe632..1c8efd9 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -55,9 +55,9 @@
 	fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
 	if(fd < 0){
 		if(fd == -EAGAIN)
-			return(IRQ_NONE);
+			return IRQ_NONE;
 
-		printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", 
+		printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n",
 		       -fd);
 		os_close_file(conn->fd);
 	}
@@ -68,7 +68,7 @@
 	list_add(&conn->list, &conn->port->connections);
 
 	complete(&conn->port->done);
-	return(IRQ_HANDLED);
+	return IRQ_HANDLED;
 }
 
 #define NO_WAITER_MSG \
@@ -97,14 +97,14 @@
 		       "connection\n");
 		goto out_close;
 	}
-	*conn = ((struct connection) 
+	*conn = ((struct connection)
 		{ .list 	= LIST_HEAD_INIT(conn->list),
 		  .fd 		= fd,
 		  .socket  	= { socket[0], socket[1] },
 		  .telnetd_pid 	= pid,
 		  .port 	= port });
 
-	if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, 
+	if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
 			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			  "telnetd", conn)){
 		printk(KERN_ERR "port_accept : failed to get IRQ for "
@@ -117,20 +117,20 @@
 		printk("No one waiting for port\n");
 	}
 	list_add(&conn->list, &port->pending);
-	return(1);
+	return 1;
 
  out_free:
 	kfree(conn);
  out_close:
 	os_close_file(fd);
-	if(pid != -1) 
+	if(pid != -1)
 		os_kill_process(pid, 1);
  out:
-	return(ret);
-} 
+	return ret;
+}
 
-DECLARE_MUTEX(ports_sem);
-struct list_head ports = LIST_HEAD_INIT(ports);
+static DECLARE_MUTEX(ports_sem);
+static LIST_HEAD(ports);
 
 void port_work_proc(struct work_struct *unused)
 {
@@ -158,8 +158,8 @@
 
 	port->has_connection = 1;
 	schedule_work(&port_work);
-	return(IRQ_HANDLED);
-} 
+	return IRQ_HANDLED;
+}
 
 void *port_data(int port_num)
 {
@@ -185,14 +185,14 @@
 		       port_num, -fd);
 		goto out_free;
 	}
-	if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, 
-			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "port",
-			  port)){
+	if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
+			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			  "port", port)){
 		printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
 		goto out_close;
 	}
 
-	*port = ((struct port_list) 
+	*port = ((struct port_list)
 		{ .list 	 	= LIST_HEAD_INIT(port->list),
 		  .wait_count		= ATOMIC_INIT(0),
 		  .has_connection 	= 0,
@@ -222,7 +222,7 @@
 	os_close_file(fd);
  out:
 	up(&ports_sem);
-	return(dev);
+	return dev;
 }
 
 int port_wait(void *data)
@@ -232,15 +232,15 @@
 	struct port_list *port = dev->port;
 	int fd;
 
-        atomic_inc(&port->wait_count);
+	atomic_inc(&port->wait_count);
 	while(1){
 		fd = -ERESTARTSYS;
-                if(wait_for_completion_interruptible(&port->done))
-                        goto out;
+		if(wait_for_completion_interruptible(&port->done))
+			goto out;
 
 		spin_lock(&port->lock);
 
-		conn = list_entry(port->connections.next, struct connection, 
+		conn = list_entry(port->connections.next, struct connection,
 				  list);
 		list_del(&conn->list);
 		spin_unlock(&port->lock);
@@ -248,12 +248,12 @@
 		os_shutdown_socket(conn->socket[0], 1, 1);
 		os_close_file(conn->socket[0]);
 		os_shutdown_socket(conn->socket[1], 1, 1);
-		os_close_file(conn->socket[1]);	
+		os_close_file(conn->socket[1]);
 
 		/* This is done here because freeing an IRQ can't be done
 		 * within the IRQ handler.  So, pipe_interrupt always ups
 		 * the semaphore regardless of whether it got a successful
-		 * connection.  Then we loop here throwing out failed 
+		 * connection.  Then we loop here throwing out failed
 		 * connections until a good one is found.
 		 */
 		free_irq(TELNETD_IRQ, conn);
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index bc6afaf..8050802 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -38,18 +38,18 @@
 	if(*str != ':'){
 		printk("port_init : channel type 'port' must specify a "
 		       "port number\n");
-		return(NULL);
+		return NULL;
 	}
 	str++;
 	port = strtoul(str, &end, 0);
 	if((*end != '\0') || (end == str)){
 		printk("port_init : couldn't parse port '%s'\n", str);
-		return(NULL);
+		return NULL;
 	}
 
 	kern_data = port_data(port);
 	if(kern_data == NULL)
-		return(NULL);
+		return NULL;
 
 	data = um_kmalloc(sizeof(*data));
 	if(data == NULL)
@@ -59,10 +59,10 @@
 				      .kernel_data 	= kern_data });
 	sprintf(data->dev, "%d", port);
 
-	return(data);
+	return data;
  err:
 	port_kern_free(kern_data);
-	return(NULL);
+	return NULL;
 }
 
 static void port_free(void *d)
@@ -83,14 +83,14 @@
 	if((fd >= 0) && data->raw){
 		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
 		if(err)
-			return(err);
+			return err;
 
 		err = raw(fd);
 		if(err)
-			return(err);
+			return err;
 	}
 	*dev_out = data->dev;
-	return(fd);
+	return fd;
 }
 
 static void port_close(int fd, void *d)
@@ -120,8 +120,8 @@
 	int fd, err, arg;
 
 	fd = socket(PF_INET, SOCK_STREAM, 0);
-	if(fd == -1) 
-		return(-errno);
+	if(fd == -1)
+		return -errno;
 
 	arg = 1;
 	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){
@@ -136,7 +136,7 @@
 		err = -errno;
 		goto out;
 	}
-  
+
 	if(listen(fd, 1) < 0){
 		err = -errno;
 		goto out;
@@ -146,10 +146,10 @@
 	if(err < 0)
 		goto out;
 
-	return(fd);
+	return fd;
  out:
 	os_close_file(fd);
-	return(err);
+	return err;
 }
 
 struct port_pre_exec_data {
@@ -173,13 +173,13 @@
 int port_connection(int fd, int *socket, int *pid_out)
 {
 	int new, err;
-	char *argv[] = { "/usr/sbin/in.telnetd", "-L", 
+	char *argv[] = { "/usr/sbin/in.telnetd", "-L",
 			 "/usr/lib/uml/port-helper", NULL };
 	struct port_pre_exec_data data;
 
 	new = os_accept_connection(fd);
 	if(new < 0)
-		return(new);
+		return new;
 
 	err = os_pipe(socket, 0, 0);
 	if(err < 0)
@@ -190,29 +190,18 @@
 		  .pipe_fd 		= socket[1] });
 
 	err = run_helper(port_pre_exec, &data, argv, NULL);
-	if(err < 0) 
+	if(err < 0)
 		goto out_shutdown;
 
 	*pid_out = err;
-	return(new);
+	return new;
 
  out_shutdown:
 	os_shutdown_socket(socket[0], 1, 1);
 	os_close_file(socket[0]);
-	os_shutdown_socket(socket[1], 1, 1);	
+	os_shutdown_socket(socket[1], 1, 1);
 	os_close_file(socket[1]);
  out_close:
 	os_close_file(new);
-	return(err);
+	return err;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 73b2bdd..e942e83 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -78,6 +78,7 @@
 	.read		= rng_dev_read,
 };
 
+/* rng_init shouldn't be called more than once at boot time */
 static struct miscdevice rng_miscdev = {
 	RNG_MISCDEV_MINOR,
 	RNG_MODULE_NAME,
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index ed9c590..fc22b9b 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -38,6 +38,7 @@
 	       dev_name);
 }
 
+/* Almost const, except that xterm_title may be changed in an initcall */
 static struct chan_opts opts = {
 	.announce 	= ssl_announce,
 	.xterm_title	= "Serial Line #%d",
@@ -46,10 +47,12 @@
 	.in_kernel 	= 1,
 };
 
-static int ssl_config(char *str);
+static int ssl_config(char *str, char **error_out);
 static int ssl_get_config(char *dev, char *str, int size, char **error_out);
-static int ssl_remove(int n);
+static int ssl_remove(int n, char **error_out);
 
+
+/* Const, except for .mc.list */
 static struct line_driver driver = {
 	.name 			= "UML serial line",
 	.device_name 		= "ttyS",
@@ -61,9 +64,8 @@
 	.read_irq_name 		= "ssl",
 	.write_irq 		= SSL_WRITE_IRQ,
 	.write_irq_name 	= "ssl-write",
-	.symlink_from 		= "serial",
-	.symlink_to 		= "tts",
 	.mc  = {
+		.list		= LIST_HEAD_INIT(driver.mc.list),
 		.name  		= "ssl",
 		.config 	= ssl_config,
 		.get_config 	= ssl_get_config,
@@ -72,17 +74,16 @@
 	},
 };
 
-/* The array is initialized by line_init, which is an initcall.  The 
- * individual elements are protected by individual semaphores.
+/* The array is initialized by line_init, at initcall time.  The
+ * elements are locked individually as needed.
  */
 static struct line serial_lines[NR_PORTS] =
 	{ [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) };
 
-static struct lines lines = LINES_INIT(NR_PORTS);
-
-static int ssl_config(char *str)
+static int ssl_config(char *str, char **error_out)
 {
-	return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts);
+	return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts,
+			   error_out);
 }
 
 static int ssl_get_config(char *dev, char *str, int size, char **error_out)
@@ -91,9 +92,10 @@
 			       size, error_out);
 }
 
-static int ssl_remove(int n)
+static int ssl_remove(int n, char **error_out)
 {
-	return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n);
+	return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n,
+			   error_out);
 }
 
 static int ssl_open(struct tty_struct *tty, struct file *filp)
@@ -168,9 +170,10 @@
 {
 	struct line *line = &serial_lines[co->index];
 
-	return console_open_chan(line, co, &opts);
+	return console_open_chan(line, co);
 }
 
+/* No locking for register_console call - relies on single-threaded initcalls */
 static struct console ssl_cons = {
 	.name		= "ttyS",
 	.write		= ssl_console_write,
@@ -186,9 +189,8 @@
 
 	printk(KERN_INFO "Initializing software serial port version %d\n",
 	       ssl_version);
-	ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops,
-					 serial_lines,
-					 ARRAY_SIZE(serial_lines));
+	ssl_driver = register_lines(&driver, &ssl_ops, serial_lines,
+				    ARRAY_SIZE(serial_lines));
 
 	lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
 
@@ -212,7 +214,15 @@
 
 static int ssl_chan_setup(char *str)
 {
-	return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str);
+	char *error;
+	int ret;
+
+	ret = line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, &error);
+	if(ret < 0)
+		printk(KERN_ERR "Failed to set up serial line with "
+		       "configuration string \"%s\" : %s\n", str, error);
+
+	return 1;
 }
 
 __setup("ssl", ssl_chan_setup);
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 7a4897e..7ff0b0f 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -30,8 +30,6 @@
 
 #define MAX_TTYS (16)
 
-/* ----------------------------------------------------------------------------- */
-
 /* Referenced only by tty_driver below - presumably it's locked correctly
  * by the tty driver.
  */
@@ -44,6 +42,7 @@
 	       dev_name);
 }
 
+/* Almost const, except that xterm_title may be changed in an initcall */
 static struct chan_opts opts = {
 	.announce 	= stdio_announce,
 	.xterm_title	= "Virtual Console #%d",
@@ -52,10 +51,12 @@
 	.in_kernel 	= 1,
 };
 
-static int con_config(char *str);
+static int con_config(char *str, char **error_out);
 static int con_get_config(char *dev, char *str, int size, char **error_out);
-static int con_remove(int n);
+static int con_remove(int n, char **con_remove);
 
+
+/* Const, except for .mc.list */
 static struct line_driver driver = {
 	.name 			= "UML console",
 	.device_name 		= "tty",
@@ -67,9 +68,8 @@
 	.read_irq_name 		= "console",
 	.write_irq 		= CONSOLE_WRITE_IRQ,
 	.write_irq_name 	= "console-write",
-	.symlink_from 		= "ttys",
-	.symlink_to 		= "vc",
 	.mc  = {
+		.list		= LIST_HEAD_INIT(driver.mc.list),
 		.name  		= "con",
 		.config 	= con_config,
 		.get_config 	= con_get_config,
@@ -78,18 +78,16 @@
 	},
 };
 
-static struct lines console_lines = LINES_INIT(MAX_TTYS);
-
-/* The array is initialized by line_init, which is an initcall.  The 
- * individual elements are protected by individual semaphores.
+/* The array is initialized by line_init, at initcall time.  The
+ * elements are locked individually as needed.
  */
-struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
-			      [ 1 ... MAX_TTYS - 1 ] =
-			      LINE_INIT(CONFIG_CON_CHAN, &driver) };
+static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
+				     [ 1 ... MAX_TTYS - 1 ] =
+				     LINE_INIT(CONFIG_CON_CHAN, &driver) };
 
-static int con_config(char *str)
+static int con_config(char *str, char **error_out)
 {
-	return line_config(vts, ARRAY_SIZE(vts), str, &opts);
+	return line_config(vts, ARRAY_SIZE(vts), str, &opts, error_out);
 }
 
 static int con_get_config(char *dev, char *str, int size, char **error_out)
@@ -97,9 +95,9 @@
 	return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out);
 }
 
-static int con_remove(int n)
+static int con_remove(int n, char **error_out)
 {
-	return line_remove(vts, ARRAY_SIZE(vts), n);
+	return line_remove(vts, ARRAY_SIZE(vts), n, error_out);
 }
 
 static int con_open(struct tty_struct *tty, struct file *filp)
@@ -146,9 +144,10 @@
 {
 	struct line *line = &vts[co->index];
 
-	return console_open_chan(line, co, &opts);
+	return console_open_chan(line, co);
 }
 
+/* No locking for register_console call - relies on single-threaded initcalls */
 static struct console stdiocons = {
 	.name		= "tty",
 	.write		= uml_console_write,
@@ -156,16 +155,14 @@
 	.setup		= uml_console_setup,
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
-	.data		= &vts,
 };
 
 int stdio_init(void)
 {
 	char *new_title;
 
-	console_driver = line_register_devfs(&console_lines, &driver,
-					     &console_ops, vts,
-					     ARRAY_SIZE(vts));
+	console_driver = register_lines(&driver, &console_ops, vts,
+					ARRAY_SIZE(vts));
 	if (console_driver == NULL)
 		return -1;
 	printk(KERN_INFO "Initialized stdio console driver\n");
@@ -192,7 +189,15 @@
 
 static int console_chan_setup(char *str)
 {
-	return line_setup(vts, ARRAY_SIZE(vts), str);
+	char *error;
+	int ret;
+
+	ret = line_setup(vts, ARRAY_SIZE(vts), str, &error);
+	if(ret < 0)
+		printk(KERN_ERR "Failed to set up console with "
+		       "configuration string \"%s\" : %s\n", str, error);
+
+	return 1;
 }
 __setup("con", console_chan_setup);
 __channel_help(console_chan_setup, "con");
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 49c047b..f98d26e 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -56,6 +56,7 @@
 enum ubd_req { UBD_READ, UBD_WRITE };
 
 struct io_thread_req {
+	struct request *req;
 	enum ubd_req op;
 	int fds[2];
 	unsigned long offsets[2];
@@ -106,10 +107,6 @@
 
 #define DRIVER_NAME "uml-blkdev"
 
-/* Can be taken in interrupt context, and is passed to the block layer to lock
- * the request queue. Kernel side code knows that. */
-static DEFINE_SPINLOCK(ubd_io_lock);
-
 static DEFINE_MUTEX(ubd_lock);
 
 /* XXX - this made sense in 2.4 days, now it's only used as a boolean, and
@@ -132,12 +129,8 @@
 	.getgeo		= ubd_getgeo,
 };
 
-/* Protected by the queue_lock */
-static request_queue_t *ubd_queue;
-
 /* Protected by ubd_lock */
 static int fake_major = MAJOR_NR;
-
 static struct gendisk *ubd_gendisk[MAX_DEV];
 static struct gendisk *fake_gendisk[MAX_DEV];
 
@@ -148,10 +141,6 @@
 #define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0, \
 					 .cl = 1 })
 #endif
-
-/* Not protected - changed only in ubd_setup_common and then only to
- * to enable O_SYNC.
- */
 static struct openflags global_openflags = OPEN_FLAGS;
 
 struct cow {
@@ -178,6 +167,8 @@
 	unsigned no_cow:1;
 	struct cow cow;
 	struct platform_device pdev;
+	struct request_queue *queue;
+	spinlock_t lock;
 };
 
 #define DEFAULT_COW { \
@@ -198,8 +189,10 @@
         .no_cow =               0, \
 	.shared =		0, \
         .cow =			DEFAULT_COW, \
+	.lock =			SPIN_LOCK_UNLOCKED,	\
 }
 
+/* Protected by ubd_lock */
 struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
 
 /* Only changed by fake_ide_setup which is a setup */
@@ -242,7 +235,6 @@
 
 	ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir);
 	if(!ent) return;
-	ent->nlink = 1;
 	ent->data = NULL;
 	ent->read_proc = proc_ide_read_media;
 	ent->write_proc = NULL;
@@ -286,12 +278,12 @@
  * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it
  * should not be freed on exit.
  */
-static int ubd_setup_common(char *str, int *index_out)
+static int ubd_setup_common(char *str, int *index_out, char **error_out)
 {
 	struct ubd *ubd_dev;
 	struct openflags flags = global_openflags;
 	char *backing_file;
-	int n, err, i;
+	int n, err = 0, i;
 
 	if(index_out) *index_out = -1;
 	n = *str;
@@ -302,56 +294,55 @@
 		str++;
 		if(!strcmp(str, "sync")){
 			global_openflags = of_sync(global_openflags);
-			return(0);
+			goto out1;
 		}
+
+		err = -EINVAL;
 		major = simple_strtoul(str, &end, 0);
 		if((*end != '\0') || (end == str)){
-			printk(KERN_ERR
-			       "ubd_setup : didn't parse major number\n");
-			return(1);
+			*error_out = "Didn't parse major number";
+			goto out1;
 		}
 
-		err = 1;
- 		mutex_lock(&ubd_lock);
- 		if(fake_major != MAJOR_NR){
- 			printk(KERN_ERR "Can't assign a fake major twice\n");
- 			goto out1;
- 		}
+		mutex_lock(&ubd_lock);
+		if(fake_major != MAJOR_NR){
+			*error_out = "Can't assign a fake major twice";
+			goto out1;
+		}
 
- 		fake_major = major;
+		fake_major = major;
 
 		printk(KERN_INFO "Setting extra ubd major number to %d\n",
 		       major);
- 		err = 0;
- 	out1:
- 		mutex_unlock(&ubd_lock);
-		return(err);
+		err = 0;
+	out1:
+		mutex_unlock(&ubd_lock);
+		return err;
 	}
 
 	n = parse_unit(&str);
 	if(n < 0){
-		printk(KERN_ERR "ubd_setup : couldn't parse unit number "
-		       "'%s'\n", str);
-		return(1);
+		*error_out = "Couldn't parse device number";
+		return -EINVAL;
 	}
 	if(n >= MAX_DEV){
-		printk(KERN_ERR "ubd_setup : index %d out of range "
-		       "(%d devices, from 0 to %d)\n", n, MAX_DEV, MAX_DEV - 1);
-		return(1);
+		*error_out = "Device number out of range";
+		return 1;
 	}
 
-	err = 1;
+	err = -EBUSY;
 	mutex_lock(&ubd_lock);
 
 	ubd_dev = &ubd_devs[n];
 	if(ubd_dev->file != NULL){
-		printk(KERN_ERR "ubd_setup : device already configured\n");
+		*error_out = "Device is already configured";
 		goto out;
 	}
 
 	if (index_out)
 		*index_out = n;
 
+	err = -EINVAL;
 	for (i = 0; i < sizeof("rscd="); i++) {
 		switch (*str) {
 		case 'r':
@@ -370,47 +361,54 @@
 			str++;
 			goto break_loop;
 		default:
-			printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r, s, c, or d)\n");
+			*error_out = "Expected '=' or flag letter "
+				"(r, s, c, or d)";
 			goto out;
 		}
 		str++;
 	}
 
-        if (*str == '=')
-		printk(KERN_ERR "ubd_setup : Too many flags specified\n");
-        else
-		printk(KERN_ERR "ubd_setup : Expected '='\n");
+	if (*str == '=')
+		*error_out = "Too many flags specified";
+	else
+		*error_out = "Missing '='";
 	goto out;
 
 break_loop:
-	err = 0;
 	backing_file = strchr(str, ',');
 
-	if (!backing_file) {
+	if (backing_file == NULL)
 		backing_file = strchr(str, ':');
-	}
 
-	if(backing_file){
-		if(ubd_dev->no_cow)
-			printk(KERN_ERR "Can't specify both 'd' and a "
-			       "cow file\n");
+	if(backing_file != NULL){
+		if(ubd_dev->no_cow){
+			*error_out = "Can't specify both 'd' and a cow file";
+			goto out;
+		}
 		else {
 			*backing_file = '\0';
 			backing_file++;
 		}
 	}
+	err = 0;
 	ubd_dev->file = str;
 	ubd_dev->cow.file = backing_file;
 	ubd_dev->boot_openflags = flags;
 out:
 	mutex_unlock(&ubd_lock);
-	return(err);
+	return err;
 }
 
 static int ubd_setup(char *str)
 {
-	ubd_setup_common(str, NULL);
-	return(1);
+	char *error;
+	int err;
+
+	err = ubd_setup_common(str, NULL, &error);
+	if(err)
+		printk(KERN_ERR "Failed to initialize device with \"%s\" : "
+		       "%s\n", str, error);
+	return 1;
 }
 
 __setup("ubd", ubd_setup);
@@ -422,7 +420,7 @@
 "    use either a ':' or a ',': the first one allows writing things like;\n"
 "	ubd0=~/Uml/root_cow:~/Uml/root_backing_file\n"
 "    while with a ',' the shell would not expand the 2nd '~'.\n"
-"    When using only one filename, UML will detect whether to thread it like\n"
+"    When using only one filename, UML will detect whether to treat it like\n"
 "    a COW file or a backing file. To override this detection, add the 'd'\n"
 "    flag:\n"
 "	ubd0d=BackingFile\n"
@@ -471,12 +469,6 @@
 /* Only changed by ubd_init, which is an initcall. */
 int thread_fd = -1;
 
-/* Changed by ubd_handler, which is serialized because interrupts only
- * happen on CPU 0.
- * XXX: currently unused.
- */
-static int intr_count = 0;
-
 /* call ubd_finish if you need to serialize */
 static void __ubd_finish(struct request *req, int error)
 {
@@ -499,36 +491,38 @@
  * spin_lock_irq()/spin_lock_irqsave() */
 static inline void ubd_finish(struct request *req, int error)
 {
- 	spin_lock(&ubd_io_lock);
+	struct ubd *dev = req->rq_disk->private_data;
+
+	spin_lock(&dev->lock);
 	__ubd_finish(req, error);
-	spin_unlock(&ubd_io_lock);
+	spin_unlock(&dev->lock);
 }
 
 /* XXX - move this inside ubd_intr. */
-/* Called without ubd_io_lock held, and only in interrupt context. */
+/* Called without dev->lock held, and only in interrupt context. */
 static void ubd_handler(void)
 {
 	struct io_thread_req req;
-	struct request *rq = elv_next_request(ubd_queue);
+	struct request *rq;
+	struct ubd *dev;
 	int n;
 
 	do_ubd = 0;
-	intr_count++;
 	n = os_read_file(thread_fd, &req, sizeof(req));
 	if(n != sizeof(req)){
 		printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
 		       "err = %d\n", os_getpid(), -n);
-		spin_lock(&ubd_io_lock);
-		end_request(rq, 0);
-		spin_unlock(&ubd_io_lock);
 		return;
 	}
 
+	rq = req.req;
+	dev = rq->rq_disk->private_data;
+
 	ubd_finish(rq, req.error);
-	reactivate_fd(thread_fd, UBD_IRQ);	
-	spin_lock(&ubd_io_lock);
-	do_ubd_request(ubd_queue);
-	spin_unlock(&ubd_io_lock);
+	reactivate_fd(thread_fd, UBD_IRQ);
+	spin_lock(&dev->lock);
+	do_ubd_request(dev->queue);
+	spin_unlock(&dev->lock);
 }
 
 static irqreturn_t ubd_intr(int irq, void *dev)
@@ -632,8 +626,7 @@
 }
 
 static int ubd_disk_register(int major, u64 size, int unit,
-			struct gendisk **disk_out)
-			
+			     struct gendisk **disk_out)
 {
 	struct gendisk *disk;
 
@@ -659,7 +652,7 @@
 	}
 
 	disk->private_data = &ubd_devs[unit];
-	disk->queue = ubd_queue;
+	disk->queue = ubd_devs[unit].queue;
 	add_disk(disk);
 
 	*disk_out = disk;
@@ -668,28 +661,39 @@
 
 #define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9))
 
-static int ubd_add(int n)
+static int ubd_add(int n, char **error_out)
 {
 	struct ubd *ubd_dev = &ubd_devs[n];
-	int err;
+	int err = 0;
 
-	err = -ENODEV;
 	if(ubd_dev->file == NULL)
 		goto out;
 
 	err = ubd_file_size(ubd_dev, &ubd_dev->size);
-	if(err < 0)
+	if(err < 0){
+		*error_out = "Couldn't determine size of device's file";
 		goto out;
+	}
 
 	ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
 
-	err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
-	if(err)
+	err = -ENOMEM;
+	ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock);
+	if (ubd_dev->queue == NULL) {
+		*error_out = "Failed to initialize device queue";
 		goto out;
+	}
+	ubd_dev->queue->queuedata = ubd_dev;
+
+	err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
+	if(err){
+		*error_out = "Failed to register device";
+		goto out_cleanup;
+	}
 
 	if(fake_major != MAJOR_NR)
 		ubd_disk_register(fake_major, ubd_dev->size, n,
-			     &fake_gendisk[n]);
+				  &fake_gendisk[n]);
 
 	/* perhaps this should also be under the "if (fake_major)" above */
 	/* using the fake_disk->disk_name and also the fakehd_set name */
@@ -699,30 +703,37 @@
 	err = 0;
 out:
 	return err;
+
+out_cleanup:
+	blk_cleanup_queue(ubd_dev->queue);
+	goto out;
 }
 
-static int ubd_config(char *str)
+static int ubd_config(char *str, char **error_out)
 {
 	int n, ret;
 
+	/* This string is possibly broken up and stored, so it's only
+	 * freed if ubd_setup_common fails, or if only general options
+	 * were set.
+	 */
 	str = kstrdup(str, GFP_KERNEL);
 	if (str == NULL) {
-		printk(KERN_ERR "ubd_config failed to strdup string\n");
-		ret = 1;
-		goto out;
+		*error_out = "Failed to allocate memory";
+		return -ENOMEM;
 	}
-	ret = ubd_setup_common(str, &n);
-	if (ret) {
-		ret = -1;
+
+	ret = ubd_setup_common(str, &n, error_out);
+	if (ret)
 		goto err_free;
-	}
+
 	if (n == -1) {
 		ret = 0;
 		goto err_free;
 	}
 
  	mutex_lock(&ubd_lock);
-	ret = ubd_add(n);
+	ret = ubd_add(n, error_out);
 	if (ret)
 		ubd_devs[n].file = NULL;
  	mutex_unlock(&ubd_lock);
@@ -777,7 +788,7 @@
         return n;
 }
 
-static int ubd_remove(int n)
+static int ubd_remove(int n, char **error_out)
 {
 	struct ubd *ubd_dev;
 	int err = -ENODEV;
@@ -807,6 +818,7 @@
 		fake_gendisk[n] = NULL;
 	}
 
+	blk_cleanup_queue(ubd_dev->queue);
 	platform_device_unregister(&ubd_dev->pdev);
 	*ubd_dev = ((struct ubd) DEFAULT_UBD);
 	err = 0;
@@ -815,8 +827,11 @@
 	return err;
 }
 
-/* All these are called by mconsole in process context and without ubd-specific locks. */
+/* All these are called by mconsole in process context and without
+ * ubd-specific locks.  The structure itself is const except for .list.
+ */
 static struct mc_device ubd_mc = {
+	.list		= LIST_HEAD_INIT(ubd_mc.list),
 	.name		= "ubd",
 	.config		= ubd_config,
  	.get_config	= ubd_get_config,
@@ -836,13 +851,17 @@
 {
 	struct ubd *ubd_dev = &ubd_devs[0];
 
+	mutex_lock(&ubd_lock);
 	if(ubd_dev->file == NULL)
 		ubd_dev->file = "root_fs";
+	mutex_unlock(&ubd_lock);
+
 	return(0);
 }
 
 __initcall(ubd0_init);
 
+/* Used in ubd_init, which is an initcall */
 static struct platform_driver ubd_driver = {
 	.driver = {
 		.name  = DRIVER_NAME,
@@ -851,17 +870,12 @@
 
 static int __init ubd_init(void)
 {
-        int i;
+	char *error;
+	int i, err;
 
 	if (register_blkdev(MAJOR_NR, "ubd"))
 		return -1;
 
-	ubd_queue = blk_init_queue(do_ubd_request, &ubd_io_lock);
-	if (!ubd_queue) {
-		unregister_blkdev(MAJOR_NR, "ubd");
-		return -1;
-	}
-		
 	if (fake_major != MAJOR_NR) {
 		char name[sizeof("ubd_nnn\0")];
 
@@ -870,8 +884,14 @@
 			return -1;
 	}
 	platform_driver_register(&ubd_driver);
-	for (i = 0; i < MAX_DEV; i++)
-		ubd_add(i);
+ 	mutex_lock(&ubd_lock);
+	for (i = 0; i < MAX_DEV; i++){
+		err = ubd_add(i, &error);
+		if(err)
+			printk(KERN_ERR "Failed to initialize ubd device %d :"
+			       "%s\n", i, error);
+	}
+ 	mutex_unlock(&ubd_lock);
 	return 0;
 }
 
@@ -1003,7 +1023,7 @@
 			   req->bitmap_words, bitmap_len);
 }
 
-/* Called with ubd_io_lock held */
+/* Called with dev->lock held */
 static int prepare_request(struct request *req, struct io_thread_req *io_req)
 {
 	struct gendisk *disk = req->rq_disk;
@@ -1022,6 +1042,7 @@
 	offset = ((__u64) req->sector) << 9;
 	len = req->current_nr_sectors << 9;
 
+	io_req->req = req;
 	io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd;
 	io_req->fds[1] = ubd_dev->fd;
 	io_req->cow_offset = -1;
@@ -1043,7 +1064,7 @@
 	return(0);
 }
 
-/* Called with ubd_io_lock held */
+/* Called with dev->lock held */
 static void do_ubd_request(request_queue_t *q)
 {
 	struct io_thread_req io_req;
@@ -1102,7 +1123,7 @@
 				 sizeof(ubd_id)))
 			return(-EFAULT);
 		return(0);
-		
+
 	case CDROMVOLREAD:
 		if(copy_from_user(&volume, (char __user *) arg, sizeof(volume)))
 			return(-EFAULT);
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index 9003a34..c4b41bb 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -30,14 +30,13 @@
 extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
 			   struct tty_struct *tty, int irq);
 extern int parse_chan_pair(char *str, struct line *line, int device,
-			   const struct chan_opts *opts);
+			   const struct chan_opts *opts, char **error_out);
 extern int open_chan(struct list_head *chans);
 extern int write_chan(struct list_head *chans, const char *buf, int len,
 			     int write_irq);
 extern int console_write_chan(struct list_head *chans, const char *buf, 
 			      int len);
-extern int console_open_chan(struct line *line, struct console *co,
-			     const struct chan_opts *opts);
+extern int console_open_chan(struct line *line, struct console *co);
 extern void deactivate_chan(struct list_head *chans, int irq);
 extern void reactivate_chan(struct list_head *chans, int irq);
 extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index a795547..38f16d8 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -9,11 +9,11 @@
 #include "init.h"
 
 struct chan_opts {
-	void (*announce)(char *dev_name, int dev);
+	void (*const announce)(char *dev_name, int dev);
 	char *xterm_title;
-	int raw;
-	unsigned long tramp_stack;
-	int in_kernel;
+	const int raw;
+	const unsigned long tramp_stack;
+	const int in_kernel;
 };
 
 enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
@@ -54,14 +54,3 @@
 );
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index cec9fcc..173af02 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -61,7 +61,6 @@
 extern void force_sigbus(void);
 extern int pid_to_processor_id(int pid);
 extern void deliver_signals(void *t);
-extern int next_syscall_index(int max);
 extern int next_trap_index(int max);
 extern void default_idle(void);
 extern void finish_fork(void);
@@ -88,7 +87,6 @@
 extern void unprotect_stack(unsigned long stack);
 extern void do_uml_exitcalls(void);
 extern int attach_debugger(int idle_pid, int pid, int stop);
-extern void bad_segv(struct faultinfo fi, unsigned long ip);
 extern int config_gdb(char *str);
 extern int remove_gdb(void);
 extern char *uml_strdup(char *string);
@@ -104,8 +102,6 @@
 extern int copy_to_user_proc(void *to, void *from, int size);
 extern int copy_from_user_proc(void *to, void *from, int size);
 extern int strlen_user_proc(char *str);
-extern void bus_handler(int sig, union uml_pt_regs *regs);
-extern void winch(int sig, union uml_pt_regs *regs);
 extern long execute_syscall(void *r);
 extern int smp_sigio_handler(void);
 extern void *get_current(void);
@@ -120,7 +116,6 @@
 
 /* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
 extern int __cant_sleep(void);
-extern void segv_handler(int sig, union uml_pt_regs *regs);
 extern void sigio_handler(int sig, union uml_pt_regs *regs);
 
 #endif
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 5f232ae..1223f2c 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -11,36 +11,37 @@
 #include "linux/tty.h"
 #include "linux/interrupt.h"
 #include "linux/spinlock.h"
+#include "linux/mutex.h"
 #include "chan_user.h"
 #include "mconsole_kern.h"
 
+/* There's only one modifiable field in this - .mc.list */
 struct line_driver {
-	char *name;
-	char *device_name;
-	short major;
-	short minor_start;
-	short type;
-	short subtype;
-	int read_irq;
-	char *read_irq_name;
-	int write_irq;
-	char *write_irq_name;
-	char *symlink_from;
-	char *symlink_to;
+	const char *name;
+	const char *device_name;
+	const short major;
+	const short minor_start;
+	const short type;
+	const short subtype;
+	const int read_irq;
+	const char *read_irq_name;
+	const int write_irq;
+	const char *write_irq_name;
 	struct mc_device mc;
 };
 
 struct line {
 	struct tty_struct *tty;
+	spinlock_t count_lock;
+	int valid;
+
 	char *init_str;
 	int init_pri;
 	struct list_head chan_list;
-	int valid;
-	int count;
-	int throttled;
+
 	/*This lock is actually, mostly, local to*/
 	spinlock_t lock;
-
+	int throttled;
 	/* Yes, this is a real circular buffer.
 	 * XXX: And this should become a struct kfifo!
 	 *
@@ -57,22 +58,17 @@
 };
 
 #define LINE_INIT(str, d) \
-	{ .init_str =	str, \
+	{ .count_lock =	SPIN_LOCK_UNLOCKED, \
+	  .init_str =	str,	\
 	  .init_pri =	INIT_STATIC, \
 	  .valid =	1, \
 	  .lock =	SPIN_LOCK_UNLOCKED, \
 	  .driver =	d }
 
-struct lines {
-	int num;
-};
-
-#define LINES_INIT(n) {  .num =	n }
-
 extern void line_close(struct tty_struct *tty, struct file * filp);
 extern int line_open(struct line *lines, struct tty_struct *tty);
 extern int line_setup(struct line *lines, unsigned int sizeof_lines,
-		      char *init);
+		      char *init, char **error_out);
 extern int line_write(struct tty_struct *tty, const unsigned char *buf,
 		      int len);
 extern void line_put_char(struct tty_struct *tty, unsigned char ch);
@@ -90,17 +86,18 @@
 extern int line_setup_irq(int fd, int input, int output, struct line *line,
 			  void *data);
 extern void line_close_chan(struct line *line);
-extern struct tty_driver * line_register_devfs(struct lines *set,
-					       struct line_driver *line_driver,
-					       const struct tty_operations *driver,
-					       struct line *lines, int nlines);
+extern struct tty_driver *register_lines(struct line_driver *line_driver,
+					 const struct tty_operations *driver,
+					 struct line *lines, int nlines);
 extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
 extern void close_lines(struct line *lines, int nlines);
 
 extern int line_config(struct line *lines, unsigned int sizeof_lines,
-		       char *str, const struct chan_opts *opts);
+		       char *str, const struct chan_opts *opts,
+		       char **error_out);
 extern int line_id(char **str, int *start_out, int *end_out);
-extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
+extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n,
+		       char **error_out);
 extern int line_get_config(char *dev, struct line *lines,
 			   unsigned int sizeof_lines, char *str,
 			   int size, char **error_out);
diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h
index 1ea6d928..d2fe07e 100644
--- a/arch/um/include/mconsole_kern.h
+++ b/arch/um/include/mconsole_kern.h
@@ -18,10 +18,10 @@
 struct mc_device {
 	struct list_head list;
 	char *name;
-	int (*config)(char *);
+	int (*config)(char *, char **);
 	int (*get_config)(char *, char *, int, char **);
-        int (*id)(char **, int *, int *);
-	int (*remove)(int);
+	int (*id)(char **, int *, int *);
+	int (*remove)(int, char **);
 };
 
 #define CONFIG_CHUNK(str, size, current, chunk, end) \
@@ -50,14 +50,3 @@
 #endif
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index 218f8b4..125ab42 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -36,7 +36,7 @@
 	void (*remove)(void *);
 	int (*read)(int, struct sk_buff **skb, struct uml_net_private *);
 	int (*write)(int, struct sk_buff **skb, struct uml_net_private *);
-	
+
 	void (*add_address)(unsigned char *, unsigned char *, void *);
 	void (*delete_address)(unsigned char *, unsigned char *, void *);
 	int (*set_mtu)(int mtu, void *);
@@ -52,18 +52,18 @@
 
 struct transport {
 	struct list_head list;
-	char *name;
-	int (*setup)(char *, char **, void *);
+	const char *name;
+	int (* const setup)(char *, char **, void *);
 	const struct net_user_info *user;
 	const struct net_kern_info *kern;
-	int private_size;
-	int setup_size;
+	const int private_size;
+	const int setup_size;
 };
 
 extern struct net_device *ether_init(int);
 extern unsigned short ether_protocol(struct sk_buff *);
 extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra);
-extern int tap_setup_common(char *str, char *type, char **dev_name, 
+extern int tap_setup_common(char *str, char *type, char **dev_name,
 			    char **mac_out, char **gate_addr);
 extern void register_transport(struct transport *new);
 extern unsigned short eth_protocol(struct sk_buff *skb);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 13a86bd..8629bd1 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -137,7 +137,6 @@
 extern int os_get_ifname(int fd, char *namebuf);
 extern int os_set_slip(int fd);
 extern int os_set_owner(int fd, int pid);
-extern int os_sigio_async(int master, int slave);
 extern int os_mode_fd(int fd, int mode);
 
 extern int os_seek_file(int fd, __u64 offset);
@@ -341,4 +340,6 @@
 extern void sig_handler_common_skas(int sig, void *sc_ptr);
 extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
 
+extern int os_arch_prctl(int pid, int code, unsigned long *addr);
+
 #endif
diff --git a/arch/um/include/sigio.h b/arch/um/include/sigio.h
index fe99ea1..434f1a9 100644
--- a/arch/um/include/sigio.h
+++ b/arch/um/include/sigio.h
@@ -12,14 +12,3 @@
 extern void sigio_unlock(void);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/tempfile.h b/arch/um/include/tempfile.h
index e36d9e0..d441eac 100644
--- a/arch/um/include/tempfile.h
+++ b/arch/um/include/tempfile.h
@@ -9,13 +9,3 @@
 extern int make_tempfile(const char *template, char **tempname, int do_unlink);
 
 #endif
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/umid.h b/arch/um/include/umid.h
deleted file mode 100644
index 11373c8..0000000
--- a/arch/um/include/umid.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __UMID_H__
-#define __UMID_H__
-
-extern int umid_file_name(char *name, char *buf, int len);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index 06625fe..023575f 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -38,8 +38,6 @@
 
 extern char host_info[];
 
-extern char saved_command_line[];
-
 extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
 extern unsigned long _unprotected_end;
 extern unsigned long brk_start;
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 6fa63a2..c5cf4a0 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,7 +7,7 @@
 clean-files :=
 
 obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
-	physmem.o process.o ptrace.o reboot.o resource.o sigio.o \
+	physmem.o process.o ptrace.o reboot.o sigio.o \
 	signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
 	um_arch.o umid.o
 
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 8d56ec6..1211664 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -39,9 +39,9 @@
 		    char __user *__user *env)
 {
         long error;
+#ifdef CONFIG_TTY_LOG
 	struct tty_struct *tty;
 
-#ifdef CONFIG_TTY_LOG
 	mutex_lock(&tty_mutex);
 	tty = get_current_tty();
 	if (tty)
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 5c1e611..50a288b 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -79,7 +79,7 @@
 	return 0;
 }
 
-struct irq_fd *active_fds = NULL;
+static struct irq_fd *active_fds = NULL;
 static struct irq_fd **last_irq_ptr = &active_fds;
 
 extern void free_irqs(void);
@@ -124,8 +124,8 @@
 	if (err < 0)
 		goto out;
 
-	new_fd = um_kmalloc(sizeof(*new_fd));
 	err = -ENOMEM;
+	new_fd = kmalloc(sizeof(struct irq_fd), GFP_KERNEL);
 	if (new_fd == NULL)
 		goto out;
 
@@ -176,9 +176,8 @@
 		 */
 		spin_unlock_irqrestore(&irq_lock, flags);
 		kfree(tmp_pfd);
-		tmp_pfd = NULL;
 
-		tmp_pfd = um_kmalloc(n);
+		tmp_pfd = kmalloc(n, GFP_KERNEL);
 		if (tmp_pfd == NULL)
 			goto out_kfree;
 
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index c95855b..e85d65d 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -24,8 +24,9 @@
 #include "init.h"
 #include "kern_constants.h"
 
-/* Changed during early boot */
+/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
 unsigned long *empty_zero_page = NULL;
+/* allocated in paging_init and unchanged thereafter */
 unsigned long *empty_bad_page = NULL;
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 unsigned long long highmem;
@@ -65,8 +66,8 @@
 {
 	max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT;
 
-        /* clear the zero-page */
-        memset((void *) empty_zero_page, 0, PAGE_SIZE);
+	/* clear the zero-page */
+	memset((void *) empty_zero_page, 0, PAGE_SIZE);
 
 	/* Map in the area just after the brk now that kmalloc is about
 	 * to be turned on.
@@ -253,8 +254,10 @@
 	int i;
 
  again:
-	if(page == NULL) return(page);
-	if(PageHighMem(page)) return(page);
+	if(page == NULL)
+		return page;
+	if(PageHighMem(page))
+		return page;
 
 	addr = (unsigned long) page_address(page);
 	for(i = 0; i < (1 << order); i++){
@@ -263,13 +266,15 @@
 				     sizeof(zero),
 				     &current->thread.fault_addr,
 				     &current->thread.fault_catcher)){
-			if(!(mask & __GFP_WAIT)) return(NULL);
+			if(!(mask & __GFP_WAIT))
+				return NULL;
 			else break;
 		}
 		addr += PAGE_SIZE;
 	}
 
-	if(i == (1 << order)) return(page);
+	if(i == (1 << order))
+		return page;
 	page = alloc_pages(mask, order);
 	goto again;
 }
@@ -283,7 +288,6 @@
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
 	if (start < end)
@@ -296,37 +300,36 @@
 		totalram_pages++;
 	}
 }
-	
 #endif
 
 void show_mem(void)
 {
-        int pfn, total = 0, reserved = 0;
-        int shared = 0, cached = 0;
-        int highmem = 0;
+	int pfn, total = 0, reserved = 0;
+	int shared = 0, cached = 0;
+	int highmem = 0;
 	struct page *page;
 
-        printk("Mem-info:\n");
-        show_free_areas();
-        printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-        pfn = max_mapnr;
-        while(pfn-- > 0) {
+	printk("Mem-info:\n");
+	show_free_areas();
+	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+	pfn = max_mapnr;
+	while(pfn-- > 0) {
 		page = pfn_to_page(pfn);
-                total++;
-                if(PageHighMem(page))
-                        highmem++;
-                if(PageReserved(page))
-                        reserved++;
-                else if(PageSwapCache(page))
-                        cached++;
-                else if(page_count(page))
-                        shared += page_count(page) - 1;
-        }
-        printk("%d pages of RAM\n", total);
-        printk("%d pages of HIGHMEM\n", highmem);
-        printk("%d reserved pages\n", reserved);
-        printk("%d pages shared\n", shared);
-        printk("%d pages swap cached\n", cached);
+		total++;
+		if(PageHighMem(page))
+			highmem++;
+		if(PageReserved(page))
+			reserved++;
+		else if(PageSwapCache(page))
+			cached++;
+		else if(page_count(page))
+			shared += page_count(page) - 1;
+	}
+	printk("%d pages of RAM\n", total);
+	printk("%d pages of HIGHMEM\n", highmem);
+	printk("%d reserved pages\n", reserved);
+	printk("%d pages shared\n", shared);
+	printk("%d pages swap cached\n", cached);
 }
 
 /*
@@ -362,28 +365,7 @@
 struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
 	struct page *pte;
-   
+
 	pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
 	return pte;
 }
-
-struct iomem_region *iomem_regions = NULL;
-int iomem_size = 0;
-
-extern int parse_iomem(char *str, int *add) __init;
-
-__uml_setup("iomem=", parse_iomem,
-"iomem=<name>,<file>\n"
-"    Configure <file> as an IO memory region named <name>.\n\n"
-);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index abafa64..638f3b5 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -40,7 +40,7 @@
 	while(*n != NULL){
 		d = rb_entry(*n, struct phys_desc, rb);
 		if(d->virt == virt)
-			return(n);
+			return n;
 
 		if(d->virt > virt)
 			n = &(*n)->rb_left;
@@ -48,7 +48,7 @@
 			n = &(*n)->rb_right;
 	}
 
-	return(n);
+	return n;
 }
 
 static struct phys_desc *find_phys_mapping(void *virt)
@@ -56,9 +56,9 @@
 	struct rb_node **n = find_rb(virt);
 
 	if(*n == NULL)
-		return(NULL);
+		return NULL;
 
-	return(rb_entry(*n, struct phys_desc, rb));
+	return rb_entry(*n, struct phys_desc, rb);
 }
 
 static void insert_phys_mapping(struct phys_desc *desc)
@@ -89,10 +89,10 @@
 	list_for_each(ele, &descriptor_mappings){
 		desc = list_entry(ele, struct desc_mapping, list);
 		if(desc->fd == fd)
-			return(desc);
+			return desc;
 	}
 
-	return(NULL);
+	return NULL;
 }
 
 static struct desc_mapping *descriptor_mapping(int fd)
@@ -101,11 +101,11 @@
 
 	desc = find_mapping(fd);
 	if(desc != NULL)
-		return(desc);
+		return desc;
 
 	desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
 	if(desc == NULL)
-		return(NULL);
+		return NULL;
 
 	*desc = ((struct desc_mapping)
 		{ .fd =		fd,
@@ -113,7 +113,7 @@
 		  .pages =	LIST_HEAD_INIT(desc->pages) });
 	list_add(&desc->list, &descriptor_mappings);
 
-	return(desc);
+	return desc;
 }
 
 int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
@@ -125,11 +125,11 @@
 
 	fd_maps = descriptor_mapping(fd);
 	if(fd_maps == NULL)
-		return(-ENOMEM);
+		return -ENOMEM;
 
 	phys = __pa(virt);
 	desc = find_phys_mapping(virt);
-  	if(desc != NULL)
+	if(desc != NULL)
 		panic("Address 0x%p is already substituted\n", virt);
 
 	err = -ENOMEM;
@@ -155,7 +155,7 @@
 	rb_erase(&desc->rb, &phys_mappings);
 	kfree(desc);
  out:
-	return(err);
+	return err;
 }
 
 static int physmem_fd = -1;
@@ -182,10 +182,10 @@
 	virt = (void *) ((unsigned long) virt & PAGE_MASK);
 	desc = find_phys_mapping(virt);
 	if(desc == NULL)
-		return(0);
+		return 0;
 
 	remove_mapping(desc);
-	return(1);
+	return 1;
 }
 
 void physmem_forget_descriptor(int fd)
@@ -239,9 +239,9 @@
 
 int is_remapped(void *virt)
 {
-  	struct phys_desc *desc = find_phys_mapping(virt);
+ 	struct phys_desc *desc = find_phys_mapping(virt);
 
-	return(desc != NULL);
+	return desc != NULL;
 }
 
 /* Changed during early boot */
@@ -276,7 +276,7 @@
 	else map = alloc_bootmem_low_pages(total_len);
 
 	if(map == NULL)
-		return(-ENOMEM);
+		return -ENOMEM;
 
 	for(i = 0; i < total_pages; i++){
 		p = &map[i];
@@ -286,7 +286,7 @@
 	}
 
 	max_mapnr = total_pages;
-	return(0);
+	return 0;
 }
 
 /* Changed during early boot */
@@ -296,7 +296,7 @@
 {
 	if(kmem_top == 0)
 		kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
-	return(kmem_top);
+	return kmem_top;
 }
 
 void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
@@ -379,7 +379,7 @@
 		*offset_out = phys - iomem_size;
 	}
 
-	return(fd);
+	return fd;
 }
 
 static int __init uml_mem_setup(char *line, int *add)
@@ -398,6 +398,23 @@
 "	Example: mem=64M\n\n"
 );
 
+extern int __init parse_iomem(char *str, int *add);
+
+__uml_setup("iomem=", parse_iomem,
+"iomem=<name>,<file>\n"
+"    Configure <file> as an IO memory region named <name>.\n\n"
+);
+
+/*
+ * This list is constructed in parse_iomem and addresses filled in in
+ * setup_iomem, both of which run during early boot.  Afterwards, it's
+ * unchanged.
+ */
+struct iomem_region *iomem_regions = NULL;
+
+/* Initialized in parse_iomem */
+int iomem_size = 0;
+
 unsigned long find_iomem(char *driver, unsigned long *len_out)
 {
 	struct iomem_region *region = iomem_regions;
@@ -405,13 +422,13 @@
 	while(region != NULL){
 		if(!strcmp(region->driver, driver)){
 			*len_out = region->size;
-			return(region->virt);
+			return region->virt;
 		}
 
 		region = region->next;
 	}
 
-	return(0);
+	return 0;
 }
 
 int setup_iomem(void)
@@ -435,18 +452,7 @@
 		region = region->next;
 	}
 
-	return(0);
+	return 0;
 }
 
 __initcall(setup_iomem);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 9a77fb3..627742d 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -18,6 +18,7 @@
 #include "kern_util.h"
 #include "skas_ptrace.h"
 #include "sysdep/ptrace.h"
+#include "os.h"
 
 static inline void set_singlestepping(struct task_struct *child, int on)
 {
@@ -241,6 +242,12 @@
 		break;
 	}
 #endif
+#ifdef PTRACE_ARCH_PRCTL
+        case PTRACE_ARCH_PRCTL:
+                /* XXX Calls ptrace on the host - needs some SMP thinking */
+                ret = arch_prctl_skas(child, data, (void *) addr);
+                break;
+#endif
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
diff --git a/arch/um/kernel/resource.c b/arch/um/kernel/resource.c
deleted file mode 100644
index 32188e1..0000000
--- a/arch/um/kernel/resource.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/pci.h"
-
-unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
-			     unsigned long start, unsigned long size)
-{
-	return start;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
index 2b0ab43..89f9866 100644
--- a/arch/um/kernel/sigio.c
+++ b/arch/um/kernel/sigio.c
@@ -23,7 +23,7 @@
 
 	os_read_file(sigio_irq_fd, &c, sizeof(c));
 	reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
-	return(IRQ_HANDLED);
+	return IRQ_HANDLED;
 }
 
 int write_sigio_irq(int fd)
@@ -36,12 +36,13 @@
 	if(err){
 		printk("write_sigio_irq : um_request_irq failed, err = %d\n",
 		       err);
-		return(-1);
+		return -1;
 	}
 	sigio_irq_fd = fd;
-	return(0);
+	return 0;
 }
 
+/* These are called from os-Linux/sigio.c to protect its pollfds arrays. */
 static DEFINE_SPINLOCK(sigio_spinlock);
 
 void sigio_lock(void)
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
index 0d2cce6..7c18dfc 100644
--- a/arch/um/kernel/skas/mem.c
+++ b/arch/um/kernel/skas/mem.c
@@ -14,13 +14,9 @@
 	unsigned long host_task_size = ROUND_4M((unsigned long)
 						&host_task_size);
 
-#ifdef CONFIG_HOST_TASK_SIZE
-	*host_size_out = ROUND_4M(CONFIG_HOST_TASK_SIZE);
-	*task_size_out = CONFIG_HOST_TASK_SIZE;
-#else
 	if (!skas_needs_stub)
 		*task_size_out = host_task_size;
 	else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
-#endif
+
 	return host_task_size;
 }
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index f5ed862..2828c52 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -149,22 +149,6 @@
 	return error;
 }
 
-DEFINE_SPINLOCK(syscall_lock);
-
-static int syscall_index = 0;
-
-int next_syscall_index(int limit)
-{
-	int ret;
-
-	spin_lock(&syscall_lock);
-	ret = syscall_index;
-	if(++syscall_index == limit)
-		syscall_index = 0;
-	spin_unlock(&syscall_lock);
-	return(ret);
-}
-
 int kernel_execve(const char *filename, char *const argv[], char *const envp[])
 {
 	mm_segment_t fs;
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 239c980..f9e02b3 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -50,7 +50,7 @@
 EXPORT_SYMBOL(dump_stack);
 
 /*Stolen from arch/i386/kernel/traps.c */
-static int kstack_depth_to_print = 24;
+static const int kstack_depth_to_print = 24;
 
 /* This recently started being used in arch-independent code too, as in
  * kernel/sched.c.*/
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 2e354b3..b1f8b07 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -35,31 +35,31 @@
 	return (unsigned long long)jiffies_64 * (1000000000 / HZ);
 }
 
-static unsigned long long prev_nsecs;
+static unsigned long long prev_nsecs[NR_CPUS];
 #ifdef CONFIG_UML_REAL_TIME_CLOCK
-static long long delta;   		/* Deviation per interval */
+static long long delta[NR_CPUS];		/* Deviation per interval */
 #endif
 
 void timer_irq(union uml_pt_regs *regs)
 {
 	unsigned long long ticks = 0;
-
 #ifdef CONFIG_UML_REAL_TIME_CLOCK
-	if(prev_nsecs){
+	int c = cpu();
+	if(prev_nsecs[c]){
 		/* We've had 1 tick */
 		unsigned long long nsecs = os_nsecs();
 
-		delta += nsecs - prev_nsecs;
-		prev_nsecs = nsecs;
+		delta[c] += nsecs - prev_nsecs[c];
+		prev_nsecs[c] = nsecs;
 
 		/* Protect against the host clock being set backwards */
-		if(delta < 0)
-			delta = 0;
+		if(delta[c] < 0)
+			delta[c] = 0;
 
-		ticks += (delta * HZ) / BILLION;
-		delta -= (ticks * BILLION) / HZ;
+		ticks += (delta[c] * HZ) / BILLION;
+		delta[c] -= (ticks * BILLION) / HZ;
 	}
-	else prev_nsecs = os_nsecs();
+	else prev_nsecs[c] = os_nsecs();
 #else
 	ticks = 1;
 #endif
@@ -69,8 +69,8 @@
 	}
 }
 
+/* Protects local_offset */
 static DEFINE_SPINLOCK(timer_spinlock);
-
 static unsigned long long local_offset = 0;
 
 static inline unsigned long long get_time(void)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index b5f124a..26f15c4 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -128,7 +128,18 @@
 	goto out;
 }
 
-void segv_handler(int sig, union uml_pt_regs *regs)
+static void bad_segv(struct faultinfo fi, unsigned long ip)
+{
+	struct siginfo si;
+
+	si.si_signo = SIGSEGV;
+	si.si_code = SEGV_ACCERR;
+	si.si_addr = (void __user *) FAULT_ADDRESS(fi);
+	current->thread.arch.faultinfo = fi;
+	force_sig_info(SIGSEGV, &si, current);
+}
+
+static void segv_handler(int sig, union uml_pt_regs *regs)
 {
 	struct faultinfo * fi = UPT_FAULTINFO(regs);
 
@@ -205,17 +216,6 @@
 	return(0);
 }
 
-void bad_segv(struct faultinfo fi, unsigned long ip)
-{
-	struct siginfo si;
-
-	si.si_signo = SIGSEGV;
-	si.si_code = SEGV_ACCERR;
-	si.si_addr = (void __user *) FAULT_ADDRESS(fi);
-	current->thread.arch.faultinfo = fi;
-	force_sig_info(SIGSEGV, &si, current);
-}
-
 void relay_signal(int sig, union uml_pt_regs *regs)
 {
 	if(arch_handle_signal(sig, regs))
@@ -232,14 +232,14 @@
 	force_sig(sig, current);
 }
 
-void bus_handler(int sig, union uml_pt_regs *regs)
+static void bus_handler(int sig, union uml_pt_regs *regs)
 {
 	if(current->thread.fault_catcher != NULL)
 		do_longjmp(current->thread.fault_catcher, 1);
 	else relay_signal(sig, regs);
 }
 
-void winch(int sig, union uml_pt_regs *regs)
+static void winch(int sig, union uml_pt_regs *regs)
 {
 	do_IRQ(WINCH_IRQ, regs);
 }
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 786e4ed..8eba8f7 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -139,7 +139,7 @@
 	init_proxy(debugger_pid, 0, 0);
 }
 
-int gdb_config(char *str)
+int gdb_config(char *str, char **error_out)
 {
 	struct gdb_data data;
 
@@ -154,7 +154,7 @@
 	exit_debugger_cb(NULL);
 }
 
-int gdb_remove(int unused)
+int gdb_remove(int unused, char **error_out)
 {
 	initial_thread_cb(remove_gdb_cb, NULL);
         return 0;
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c
index 68e1bf6..03b06bc 100644
--- a/arch/um/kernel/tt/gdb_kern.c
+++ b/arch/um/kernel/tt/gdb_kern.c
@@ -8,10 +8,11 @@
 
 #ifdef CONFIG_MCONSOLE
 
-extern int gdb_config(char *str);
-extern int gdb_remove(int n);
+extern int gdb_config(char *str, char **error_out);
+extern int gdb_remove(int n, char **error_out);
 
 static struct mc_device gdb_mc = {
+	.list		= INIT_LIST_HEAD(gdb_mc.list),
 	.name		= "gdb",
 	.config		= gdb_config,
 	.remove		= gdb_remove,
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 66f43c9..89c6dba 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -30,7 +30,6 @@
 #include "kern.h"
 #include "mem_user.h"
 #include "mem.h"
-#include "umid.h"
 #include "initrd.h"
 #include "init.h"
 #include "os.h"
@@ -44,9 +43,9 @@
 #define DEFAULT_COMMAND_LINE "root=98:0"
 
 /* Changed in linux_main and setup_arch, which run before SMP is started */
-static char command_line[COMMAND_LINE_SIZE] = { 0 };
+static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };
 
-static void add_arg(char *arg)
+static void __init add_arg(char *arg)
 {
 	if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
 		printf("add_arg: Too many command line arguments!\n");
@@ -331,7 +330,7 @@
 
 extern char __binary_start;
 
-int linux_main(int argc, char **argv)
+int __init linux_main(int argc, char **argv)
 {
 	unsigned long avail, diff;
 	unsigned long virtmem_size, max_physmem;
@@ -482,7 +481,7 @@
 	atomic_notifier_chain_register(&panic_notifier_list,
 			&panic_exit_notifier);
 	paging_init();
-        strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
  	*cmdline_p = command_line;
 	setup_hostinfo();
 }
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 4eaee82..039e16e 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -16,8 +16,10 @@
 {
 	int err;
 
-	if(umid_inited)
+	if(umid_inited){
+		printf("umid already set\n");
 		return 0;
+	}
 
 	*add = 0;
 	err = set_umid(name);
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index f897140..6ff1274 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -24,9 +24,6 @@
 	struct aio_context *aio;
 };
 
-static int aio_req_fd_r = -1;
-static int aio_req_fd_w = -1;
-
 #if defined(HAVE_AIO_ABI)
 #include <linux/aio_abi.h>
 
@@ -111,6 +108,7 @@
 	return err;
 }
 
+/* Initialized in an initcall and unchanged thereafter */
 static aio_context_t ctx = 0;
 
 static int aio_thread(void *arg)
@@ -137,7 +135,7 @@
 			err = os_write_file(reply_fd, &reply, sizeof(reply));
 			if(err != sizeof(reply))
 				printk("aio_thread - write failed, fd = %d, "
-				       "err = %d\n", aio_req_fd_r, -err);
+				       "err = %d\n", reply_fd, -err);
 		}
 	}
 	return 0;
@@ -182,6 +180,11 @@
 	return err;
 }
 
+/* These are initialized in initcalls and not changed */
+static int aio_req_fd_r = -1;
+static int aio_req_fd_w = -1;
+static int aio_pid = -1;
+
 static int not_aio_thread(void *arg)
 {
 	struct aio_thread_req req;
@@ -208,14 +211,12 @@
 		err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply));
 		if(err != sizeof(reply))
 			printk("not_aio_thread - write failed, fd = %d, "
-			       "err = %d\n", aio_req_fd_r, -err);
+			       "err = %d\n", req.aio->reply_fd, -err);
 	}
 
 	return 0;
 }
 
-static int aio_pid = -1;
-
 static int init_aio_24(void)
 {
 	unsigned long stack;
@@ -308,6 +309,7 @@
 }
 #endif
 
+/* Initialized in an initcall and unchanged thereafter */
 static int aio_24 = DEFAULT_24_AIO;
 
 static int __init set_aio_24(char *name, int *add)
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 5a99dd3..3a8d7e3 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -21,12 +21,11 @@
 typedef Elf64_auxv_t elf_auxv_t;
 #endif
 
+/* These are initialized very early in boot and never changed */
 char * elf_aux_platform;
 long elf_aux_hwcap;
-
 unsigned long vsyscall_ehdr;
 unsigned long vsyscall_end;
-
 unsigned long __kernel_vsyscall;
 
 __init void scan_elf_aux( char **envp)
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 189fa67..371b433 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -162,25 +162,6 @@
 	return 0;
 }
 
-/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */
-int os_sigio_async(int master, int slave)
-{
-	int flags;
-
-	flags = fcntl(master, F_GETFL);
-	if(flags < 0)
-		return -errno;
-
-	if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
-	   (fcntl(master, F_SETOWN, os_getpid()) < 0))
-		return -errno;
-
-	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
-		return -errno;
-
-	return(0);
-}
-
 int os_mode_fd(int fd, int mode)
 {
 	int err;
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index d46b818..d1b61d4 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -20,6 +20,10 @@
 #include "os.h"
 #include "um_malloc.h"
 
+/*
+ * Locked by irq_lock in arch/um/kernel/irq.c.  Changed by os_create_pollfd
+ * and os_free_irq_by_cb, which are called under irq_lock.
+ */
 static struct pollfd *pollfds = NULL;
 static int pollfds_num = 0;
 static int pollfds_size = 0;
@@ -58,7 +62,7 @@
 	if (pollfds_num == pollfds_size) {
 		if (size_tmpfds <= pollfds_size * sizeof(pollfds[0])) {
 			/* return min size needed for new pollfds area */
-			return((pollfds_size + 1) * sizeof(pollfds[0]));
+			return (pollfds_size + 1) * sizeof(pollfds[0]);
 		}
 
 		if (pollfds != NULL) {
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 4203681..f1ea169 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -20,7 +20,13 @@
 
 #include <sys/param.h>
 
+/* Modified by which_tmpdir, which is called during early boot */
 static char *default_tmpdir = "/tmp";
+
+/*
+ *  Modified when creating the physical memory file and when checking
+ * the tmp filesystem for usability, both happening during early boot.
+ */
 static char *tempdir = NULL;
 
 static void __init find_tempdir(void)
@@ -29,7 +35,8 @@
 	int i;
 	char *dir = NULL;
 
-	if(tempdir != NULL) return;	/* We've already been called */
+	if(tempdir != NULL) /* We've already been called */
+		return;
 	for(i = 0; dirs[i]; i++){
 		dir = getenv(dirs[i]);
 		if((dir != NULL) && (*dir != '\0'))
@@ -83,6 +90,7 @@
 	return 1;
 }
 
+/* which_tmpdir is called only during early boot */
 static int checked_tmpdir = 0;
 
 /* Look for a tmpfs mounted at /dev/shm.  I couldn't find a cleaner
@@ -186,7 +194,7 @@
 	} else {
 		free(tempname);
 	}
-	return(fd);
+	return fd;
 out:
 	free(tempname);
 	return -1;
@@ -231,7 +239,7 @@
 		exit(1);
 	}
 
-	return(fd);
+	return fd;
 }
 
 int create_mem_file(unsigned long long len)
@@ -245,7 +253,7 @@
 		errno = -err;
 		perror("exec_close");
 	}
-	return(fd);
+	return fd;
 }
 
 
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 925a652..b2e1fd8 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -97,20 +97,22 @@
 
 static int need_poll(struct pollfds *polls, int n)
 {
-	if(n <= polls->size){
-		polls->used = n;
+	struct pollfd *new;
+
+	if(n <= polls->size)
 		return 0;
-	}
-	kfree(polls->poll);
-	polls->poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
-	if(polls->poll == NULL){
+
+	new = um_kmalloc_atomic(n * sizeof(struct pollfd));
+	if(new == NULL){
 		printk("need_poll : failed to allocate new pollfds\n");
-		polls->size = 0;
-		polls->used = 0;
 		return -ENOMEM;
 	}
+
+	memcpy(new, polls->poll, polls->used * sizeof(struct pollfd));
+	kfree(polls->poll);
+
+	polls->poll = new;
 	polls->size = n;
-	polls->used = n;
 	return 0;
 }
 
@@ -171,15 +173,15 @@
 			goto out;
 	}
 
-	n = current_poll.used + 1;
-	err = need_poll(&next_poll, n);
+	n = current_poll.used;
+	err = need_poll(&next_poll, n + 1);
 	if(err)
 		goto out;
 
-	for(i = 0; i < current_poll.used; i++)
-		next_poll.poll[i] = current_poll.poll[i];
-
-	next_poll.poll[n - 1] = *p;
+	memcpy(next_poll.poll, current_poll.poll,
+	       current_poll.used * sizeof(struct pollfd));
+	next_poll.poll[n] = *p;
+	next_poll.used = n + 1;
 	update_thread();
  out:
 	sigio_unlock();
@@ -214,6 +216,7 @@
 		if(p->fd != fd)
 			next_poll.poll[n++] = *p;
 	}
+	next_poll.used = current_poll.used - 1;
 
 	update_thread();
  out:
@@ -331,10 +334,9 @@
 
 	sigio_lock();
 	err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
-	if(err){
-		printk("maybe_sigio_broken - failed to add pollfd\n");
+	if(err)
 		goto out;
-	}
+
 	all_sigio_fds.poll[all_sigio_fds.used++] =
 		((struct pollfd) { .fd  	= fd,
 				   .events 	= read ? POLLIN : POLLOUT,
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 7fe9268..5178eba 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -54,7 +54,7 @@
 		perror("ptrace");
 		os_kill_process(pid, 0);
 	}
-	os_stop_process(pid);
+	kill(pid, SIGSTOP);
 
 	/*This syscall will be intercepted by the parent. Don't call more than
 	 * once, please.*/
@@ -73,6 +73,34 @@
 	_exit(ret);
 }
 
+static void fatal_perror(char *str)
+{
+	perror(str);
+	exit(1);
+}
+
+static void fatal(char *fmt, ...)
+{
+	va_list list;
+
+	va_start(list, fmt);
+	vprintf(fmt, list);
+	va_end(list);
+	fflush(stdout);
+
+	exit(1);
+}
+
+static void non_fatal(char *fmt, ...)
+{
+	va_list list;
+
+	va_start(list, fmt);
+	vprintf(fmt, list);
+	va_end(list);
+	fflush(stdout);
+}
+
 static int start_ptraced_child(void **stack_out)
 {
 	void *stack;
@@ -82,20 +110,20 @@
 	stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
 		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 	if(stack == MAP_FAILED)
-		panic("check_ptrace : mmap failed, errno = %d", errno);
+		fatal_perror("check_ptrace : mmap failed");
 	sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
 	pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
 	if(pid < 0)
-		panic("start_ptraced_child : clone failed, errno = %d", errno);
+		fatal_perror("start_ptraced_child : clone failed");
 	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if(n < 0)
-		panic("check_ptrace : clone failed, errno = %d", errno);
+		fatal_perror("check_ptrace : clone failed");
 	if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
-		panic("check_ptrace : expected SIGSTOP, got status = %d",
+		fatal("check_ptrace : expected SIGSTOP, got status = %d",
 		      status);
 
 	*stack_out = stack;
-	return(pid);
+	return pid;
 }
 
 /* When testing for SYSEMU support, if it is one of the broken versions, we
@@ -105,34 +133,34 @@
  * must work anyway!
  */
 static int stop_ptraced_child(int pid, void *stack, int exitcode,
-			      int mustpanic)
+			      int mustexit)
 {
 	int status, n, ret = 0;
 
 	if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
-		panic("check_ptrace : ptrace failed, errno = %d", errno);
+		fatal_perror("stop_ptraced_child : ptrace failed");
 	CATCH_EINTR(n = waitpid(pid, &status, 0));
 	if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
 		int exit_with = WEXITSTATUS(status);
 		if (exit_with == 2)
-			printf("check_ptrace : child exited with status 2. "
-			       "Serious trouble happening! Try updating your "
-			       "host skas patch!\nDisabling SYSEMU support.");
-		printf("check_ptrace : child exited with exitcode %d, while "
-		      "expecting %d; status 0x%x", exit_with,
-		      exitcode, status);
-		if (mustpanic)
-			panic("\n");
-		else
-			printf("\n");
+			non_fatal("check_ptrace : child exited with status 2. "
+				  "Serious trouble happening! Try updating "
+				  "your host skas patch!\nDisabling SYSEMU "
+				  "support.");
+		non_fatal("check_ptrace : child exited with exitcode %d, while "
+			  "expecting %d; status 0x%x\n", exit_with,
+			  exitcode, status);
+		if (mustexit)
+			exit(1);
 		ret = -1;
 	}
 
 	if(munmap(stack, PAGE_SIZE) < 0)
-		panic("check_ptrace : munmap failed, errno = %d", errno);
+		fatal_perror("check_ptrace : munmap failed");
 	return ret;
 }
 
+/* Changed only during early boot */
 int ptrace_faultinfo = 1;
 int ptrace_ldt = 1;
 int proc_mm = 1;
@@ -160,6 +188,7 @@
 		"    specify mode=tt. Note that this was recently added - on \n"
 		"    older kernels you must use simply \"skas0\".\n\n");
 
+/* Changed only during early boot */
 static int force_sysemu_disabled = 0;
 
 static int __init nosysemu_cmd_param(char *str, int* add)
@@ -180,9 +209,9 @@
 static void __init check_sysemu(void)
 {
 	void *stack;
- 	int pid, n, status, count=0;
+	int pid, n, status, count=0;
 
-	printf("Checking syscall emulation patch for ptrace...");
+	non_fatal("Checking syscall emulation patch for ptrace...");
 	sysemu_supported = 0;
 	pid = start_ptraced_child(&stack);
 
@@ -191,31 +220,30 @@
 
 	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if (n < 0)
-		panic("check_sysemu : wait failed, errno = %d", errno);
+		fatal_perror("check_sysemu : wait failed");
 	if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
-		panic("check_sysemu : expected SIGTRAP, "
-		      "got status = %d", status);
+		fatal("check_sysemu : expected SIGTRAP, got status = %d",
+		      status);
 
 	n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
 		   os_getpid());
 	if(n < 0)
-		panic("check_sysemu : failed to modify system "
-		      "call return, errno = %d", errno);
+		fatal_perror("check_sysemu : failed to modify system call "
+			     "return");
 
 	if (stop_ptraced_child(pid, stack, 0, 0) < 0)
 		goto fail_stopped;
 
 	sysemu_supported = 1;
-	printf("OK\n");
+	non_fatal("OK\n");
 	set_using_sysemu(!force_sysemu_disabled);
 
-	printf("Checking advanced syscall emulation patch for ptrace...");
+	non_fatal("Checking advanced syscall emulation patch for ptrace...");
 	pid = start_ptraced_child(&stack);
 
-	if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
-		  (void *) PTRACE_O_TRACESYSGOOD) < 0)
-		panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d",
-		      errno);
+	if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
+		   (void *) PTRACE_O_TRACESYSGOOD) < 0))
+		fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");
 
 	while(1){
 		count++;
@@ -223,29 +251,30 @@
 			goto fail;
 		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 		if(n < 0)
-			panic("check_ptrace : wait failed, errno = %d", errno);
+			fatal_perror("check_ptrace : wait failed");
+
 		if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){
 			if (!count)
-				panic("check_ptrace : SYSEMU_SINGLESTEP "
+				fatal("check_ptrace : SYSEMU_SINGLESTEP "
 				      "doesn't singlestep");
 			n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
 				   os_getpid());
 			if(n < 0)
-				panic("check_sysemu : failed to modify system "
-				      "call return, errno = %d", errno);
+				fatal_perror("check_sysemu : failed to modify "
+					     "system call return");
 			break;
 		}
 		else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
 			count++;
 		else
-			panic("check_ptrace : expected SIGTRAP or "
-			      "(SIGTRAP|0x80), got status = %d", status);
+			fatal("check_ptrace : expected SIGTRAP or "
+			      "(SIGTRAP | 0x80), got status = %d", status);
 	}
 	if (stop_ptraced_child(pid, stack, 0, 0) < 0)
 		goto fail_stopped;
 
 	sysemu_supported = 2;
-	printf("OK\n");
+	non_fatal("OK\n");
 
 	if ( !force_sysemu_disabled )
 		set_using_sysemu(sysemu_supported);
@@ -254,7 +283,7 @@
 fail:
 	stop_ptraced_child(pid, stack, 1, 0);
 fail_stopped:
-	printf("missing\n");
+	non_fatal("missing\n");
 }
 
 static void __init check_ptrace(void)
@@ -262,22 +291,25 @@
 	void *stack;
 	int pid, syscall, n, status;
 
-	printf("Checking that ptrace can change system call numbers...");
+	non_fatal("Checking that ptrace can change system call numbers...");
 	pid = start_ptraced_child(&stack);
 
-	if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
-		panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d", errno);
+	if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
+		   (void *) PTRACE_O_TRACESYSGOOD) < 0))
+		fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");
 
 	while(1){
 		if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
-			panic("check_ptrace : ptrace failed, errno = %d",
-			      errno);
+			fatal_perror("check_ptrace : ptrace failed");
+
 		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 		if(n < 0)
-			panic("check_ptrace : wait failed, errno = %d", errno);
-		if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|0x80)))
-			panic("check_ptrace : expected (SIGTRAP|0x80), "
-			      "got status = %d", status);
+			fatal_perror("check_ptrace : wait failed");
+
+		if(!WIFSTOPPED(status) ||
+		   (WSTOPSIG(status) != (SIGTRAP | 0x80)))
+			fatal("check_ptrace : expected (SIGTRAP|0x80), "
+			       "got status = %d", status);
 
 		syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
 				 0);
@@ -285,13 +317,13 @@
 			n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
 				   __NR_getppid);
 			if(n < 0)
-				panic("check_ptrace : failed to modify system "
-				      "call, errno = %d", errno);
+				fatal_perror("check_ptrace : failed to modify "
+					     "system call");
 			break;
 		}
 	}
 	stop_ptraced_child(pid, stack, 0, 1);
-	printf("OK\n");
+	non_fatal("OK\n");
 	check_sysemu();
 }
 
@@ -350,22 +382,22 @@
 	void *stack;
 	int pid, n;
 
-	printf("  - PTRACE_FAULTINFO...");
+	non_fatal("  - PTRACE_FAULTINFO...");
 	pid = start_ptraced_child(&stack);
 
 	n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
 	if (n < 0) {
 		ptrace_faultinfo = 0;
 		if(errno == EIO)
-			printf("not found\n");
+			non_fatal("not found\n");
 		else
 			perror("not found");
 	}
 	else {
 		if (!ptrace_faultinfo)
-			printf("found but disabled on command line\n");
+			non_fatal("found but disabled on command line\n");
 		else
-			printf("found\n");
+			non_fatal("found\n");
 	}
 
 	init_registers(pid);
@@ -383,13 +415,13 @@
 		.ptr = ldtbuf,
 		.bytecount = sizeof(ldtbuf)};
 
-	printf("  - PTRACE_LDT...");
+	non_fatal("  - PTRACE_LDT...");
 	pid = start_ptraced_child(&stack);
 
 	n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op);
 	if (n < 0) {
 		if(errno == EIO)
-			printf("not found\n");
+			non_fatal("not found\n");
 		else {
 			perror("not found");
 		}
@@ -397,9 +429,9 @@
 	}
 	else {
 		if(ptrace_ldt)
-			printf("found\n");
+			non_fatal("found\n");
 		else
-			printf("found, but use is disabled\n");
+			non_fatal("found, but use is disabled\n");
 	}
 
 	stop_ptraced_child(pid, stack, 1, 1);
@@ -414,22 +446,22 @@
 
 static inline void check_skas3_proc_mm(void)
 {
-	printf("  - /proc/mm...");
-	if (os_access("/proc/mm", OS_ACC_W_OK) < 0) {
- 		proc_mm = 0;
-		printf("not found\n");
+	non_fatal("  - /proc/mm...");
+	if (access("/proc/mm", W_OK) < 0) {
+		proc_mm = 0;
+		perror("not found");
 	}
 	else {
 		if (!proc_mm)
-			printf("found but disabled on command line\n");
+			non_fatal("found but disabled on command line\n");
 		else
-			printf("found\n");
+			non_fatal("found\n");
 	}
 }
 
 int can_do_skas(void)
 {
-	printf("Checking for the skas3 patch in the host:\n");
+	non_fatal("Checking for the skas3 patch in the host:\n");
 
 	check_skas3_proc_mm();
 	check_skas3_ptrace_faultinfo();
@@ -443,16 +475,16 @@
 #else
 int can_do_skas(void)
 {
-	return(0);
+	return 0;
 }
 #endif
 
 int __init parse_iomem(char *str, int *add)
 {
 	struct iomem_region *new;
-	struct uml_stat buf;
+	struct stat64 buf;
 	char *file, *driver;
-	int fd, err, size;
+	int fd, size;
 
 	driver = str;
 	file = strchr(str,',');
@@ -462,15 +494,14 @@
 	}
 	*file = '\0';
 	file++;
-	fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
+	fd = open(file, O_RDWR, 0);
 	if(fd < 0){
 		os_print_error(fd, "parse_iomem - Couldn't open io file");
 		goto out;
 	}
 
-	err = os_stat_fd(fd, &buf);
-	if(err < 0){
-		os_print_error(err, "parse_iomem - cannot stat_fd file");
+	if(fstat64(fd, &buf) < 0){
+		perror("parse_iomem - cannot stat_fd file");
 		goto out_close;
 	}
 
@@ -480,7 +511,7 @@
 		goto out_close;
 	}
 
-	size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
+	size = (buf.st_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
 
 	*new = ((struct iomem_region) { .next		= iomem_regions,
 					.driver		= driver,
@@ -491,11 +522,11 @@
 	iomem_regions = new;
 	iomem_size += new->size + UM_KERN_PAGE_SIZE;
 
-	return(0);
+	return 0;
  out_close:
-	os_close_file(fd);
+	close(fd);
  out:
-	return(1);
+	return 1;
 }
 
 
@@ -526,6 +557,24 @@
 		info->err = -errno;
 }
 
+static int async_pty(int master, int slave)
+{
+	int flags;
+
+	flags = fcntl(master, F_GETFL);
+	if(flags < 0)
+		return -errno;
+
+	if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
+	   (fcntl(master, F_SETOWN, os_getpid()) < 0))
+		return -errno;
+
+	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
+		return -errno;
+
+	return(0);
+}
+
 static void __init check_one_sigio(void (*proc)(int, int))
 {
 	struct sigaction old, new;
@@ -551,7 +600,7 @@
 	if (err < 0)
 		panic("check_sigio : __raw failed, errno = %d\n", -err);
 
-	err = os_sigio_async(master, slave);
+	err = async_pty(master, slave);
 	if(err < 0)
 		panic("tty_fds : sigio_async failed, err = %d\n", -err);
 
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 7cd0369..79cd93c 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -34,27 +34,27 @@
 int save_fp_registers(int pid, unsigned long *fp_regs)
 {
 	if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
-		return(-errno);
-	return(0);
+		return -errno;
+	return 0;
 }
 
 int restore_fp_registers(int pid, unsigned long *fp_regs)
 {
 	if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
-		return(-errno);
-	return(0);
+		return -errno;
+	return 0;
 }
 
 static int move_registers(int pid, int int_op, union uml_pt_regs *regs,
 			  int fp_op, unsigned long *fp_regs)
 {
 	if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
-		return(-errno);
+		return -errno;
 
 	if(ptrace(fp_op, pid, 0, fp_regs) < 0)
-		return(-errno);
+		return -errno;
 
-	return(0);
+	return 0;
 }
 
 void save_registers(int pid, union uml_pt_regs *regs)
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
index f67842a..7955e06 100644
--- a/arch/um/os-Linux/sys-x86_64/Makefile
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -3,7 +3,7 @@
 # Licensed under the GPL
 #
 
-obj-$(CONFIG_MODE_SKAS) = registers.o signal.o
+obj-$(CONFIG_MODE_SKAS) = registers.o prctl.o signal.o
 
 USER_OBJS := $(obj-y)
 
diff --git a/arch/um/os-Linux/sys-x86_64/prctl.c b/arch/um/os-Linux/sys-x86_64/prctl.c
new file mode 100644
index 0000000..9d34edd
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/prctl.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com})
+ * Licensed under the GPL
+ */
+
+#include <sys/ptrace.h>
+#include <linux/ptrace.h>
+
+int os_arch_prctl(int pid, int code, unsigned long *addr)
+{
+        return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code);
+}
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index cb8e8a2..a2d7e0c 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -27,12 +27,12 @@
 			  union uml_pt_regs *regs)
 {
 	if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
-		return(-errno);
+		return -errno;
 
 	if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0)
-		return(-errno);
+		return -errno;
 
-	return(0);
+	return 0;
 }
 
 void save_registers(int pid, union uml_pt_regs *regs)
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 48092b9..b462863 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -18,7 +18,7 @@
 #define UMID_LEN 64
 
 /* Changed by set_umid, which is run early in boot */
-char umid[UMID_LEN] = { 0 };
+static char umid[UMID_LEN] = { 0 };
 
 /* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
 static char *uml_dir = UML_DIR;
@@ -235,6 +235,7 @@
 	return 0;
 }
 
+/* Changed in make_umid, which is called during early boot */
 static int umid_setup = 0;
 
 int __init make_umid(void)
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index 147bbf0..55b66e0 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -71,8 +71,6 @@
 
         if (addr < MAX_REG_OFFSET)
                 return putreg(child, addr, data);
-
-#if 0 /* Need x86_64 debugregs handling */
         else if((addr >= offsetof(struct user, u_debugreg[0])) &&
                 (addr <= offsetof(struct user, u_debugreg[7]))){
                 addr -= offsetof(struct user, u_debugreg[0]);
@@ -81,7 +79,6 @@
                 child->thread.arch.debugregs[addr] = data;
                 return 0;
         }
-#endif
         return -EIO;
 }
 
@@ -119,14 +116,12 @@
         if(addr < MAX_REG_OFFSET){
                 tmp = getreg(child, addr);
         }
-#if 0 /* Need x86_64 debugregs handling */
         else if((addr >= offsetof(struct user, u_debugreg[0])) &&
                 (addr <= offsetof(struct user, u_debugreg[7]))){
                 addr -= offsetof(struct user, u_debugreg[0]);
                 addr = addr >> 2;
                 tmp = child->thread.arch.debugregs[addr];
         }
-#endif
         return put_user(tmp, (unsigned long *) data);
 }
 
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 73ce446..01b91f9 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -16,6 +16,7 @@
 #include "asm/prctl.h" /* XXX This should get the constants from libc */
 #include "choose-mode.h"
 #include "kern.h"
+#include "os.h"
 
 asmlinkage long sys_uname64(struct new_utsname __user * name)
 {
@@ -58,40 +59,69 @@
 
 #ifdef CONFIG_MODE_SKAS
 
-/* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */
-static long arch_prctl_skas(int code, unsigned long addr)
+long arch_prctl_skas(struct task_struct *task, int code,
+                     unsigned long __user *addr)
 {
-	long ret = 0;
+        unsigned long *ptr = addr, tmp;
+	long ret;
+	int pid = task->mm->context.skas.id.u.pid;
 
+	/*
+	 * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
+	 * be safe), we need to call arch_prctl on the host because
+	 * setting %fs may result in something else happening (like a
+	 * GDT or thread.fs being set instead).  So, we let the host
+	 * fiddle the registers and thread struct and restore the
+	 * registers afterwards.
+	 *
+	 * So, the saved registers are stored to the process (this
+	 * needed because a stub may have been the last thing to run),
+	 * arch_prctl is run on the host, then the registers are read
+	 * back.
+	 */
 	switch(code){
 	case ARCH_SET_FS:
-		current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr;
-		break;
 	case ARCH_SET_GS:
-		current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
+                restore_registers(pid, &current->thread.regs.regs);
+                break;
+        case ARCH_GET_FS:
+        case ARCH_GET_GS:
+                /*
+                 * With these two, we read to a local pointer and
+                 * put_user it to the userspace pointer that we were
+                 * given.  If addr isn't valid (because it hasn't been
+                 * faulted in or is just bogus), we want put_user to
+                 * fault it in (or return -EFAULT) instead of having
+                 * the host return -EFAULT.
+                 */
+                ptr = &tmp;
+        }
+
+        ret = os_arch_prctl(pid, code, ptr);
+        if(ret)
+                return ret;
+
+        switch(code){
+	case ARCH_SET_FS:
+	case ARCH_SET_GS:
+                save_registers(pid, &current->thread.regs.regs);
 		break;
 	case ARCH_GET_FS:
-		ret = put_user(current->thread.regs.regs.skas.
-				regs[FS_BASE / sizeof(unsigned long)],
-				(unsigned long __user *)addr);
+		ret = put_user(tmp, addr);
 	        break;
 	case ARCH_GET_GS:
-		ret = put_user(current->thread.regs.regs.skas.
-				regs[GS_BASE / sizeof(unsigned long)],
-				(unsigned long __user *)addr);
+		ret = put_user(tmp, addr);
 	        break;
-	default:
-		ret = -EINVAL;
-		break;
 	}
 
-	return(ret);
+	return ret;
 }
 #endif
 
 long sys_arch_prctl(int code, unsigned long addr)
 {
-	return(CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, addr));
+	return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, current, code,
+                                (unsigned long __user *) addr);
 }
 
 long sys_clone(unsigned long clone_flags, unsigned long newsp,
@@ -105,5 +135,14 @@
 	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
 		      child_tid);
 	current->thread.forking = 0;
-	return(ret);
+	return ret;
 }
+
+void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
+{
+        if(to->thread.arch.fs == 0)
+                return;
+
+        arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
+}
+
diff --git a/arch/um/sys-x86_64/tls.c b/arch/um/sys-x86_64/tls.c
index ce1bf1b..febbc94 100644
--- a/arch/um/sys-x86_64/tls.c
+++ b/arch/um/sys-x86_64/tls.c
@@ -1,14 +1,17 @@
 #include "linux/sched.h"
 
-void debug_arch_force_load_TLS(void)
-{
-}
-
 void clear_flushed_tls(struct task_struct *task)
 {
 }
 
 int arch_copy_tls(struct task_struct *t)
 {
+	/*
+	 * If CLONE_SETTLS is set, we need to save the thread id
+	 * (which is argument 5, child_tid, of clone) so it can be set
+	 * during context switches.
+	 */
+	t->thread.arch.fs = t->thread.regs.regs.skas.regs[R8 / sizeof(long)];
+
         return 0;
 }
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index f0d4d72..50ccc7f 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -10,6 +10,9 @@
 config MMU
        	bool
 	default n
+config ZONE_DMA
+	bool
+	default y
 config RWSEM_GENERIC_SPINLOCK
 	bool
 	default y
@@ -214,7 +217,7 @@
    # Some platforms pre-zero memory, in which case the kernel doesn't need to
    config ZERO_BSS
    	  bool
-	  depends !V850E2_SIM85E2C
+	  depends on !V850E2_SIM85E2C
 	  default y
 
    # The crappy-ass zone allocator requires that the start of allocatable
diff --git a/arch/v850/kernel/anna.c b/arch/v850/kernel/anna.c
index 40892d3..0e42904 100644
--- a/arch/v850/kernel/anna.c
+++ b/arch/v850/kernel/anna.c
@@ -114,7 +114,7 @@
 	{ "ST",  IRQ_INTST(0), 	IRQ_INTST_NUM, 	3, 5 },
 	{ 0 }
 };
-#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
+#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
 
 static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
 
diff --git a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c
index 5352f8a..18437bc 100644
--- a/arch/v850/kernel/as85ep1.c
+++ b/arch/v850/kernel/as85ep1.c
@@ -142,7 +142,7 @@
 	{ "ST",  IRQ_INTST(0), 	IRQ_INTST_NUM, 	3, 5 },
 	{ 0 }
 };
-#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
+#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
 
 static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
 
diff --git a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c
index cb04a69..5c49235 100644
--- a/arch/v850/kernel/fpga85e2c.c
+++ b/arch/v850/kernel/fpga85e2c.c
@@ -138,7 +138,7 @@
 	{ "RPU", IRQ_RPU(0),	IRQ_RPU_NUM,	1, 6 },
 	{ 0 }
 };
-#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
+#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
 
 struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
 
diff --git a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c
index 25d636e..b2bcc25 100644
--- a/arch/v850/kernel/gbus_int.c
+++ b/arch/v850/kernel/gbus_int.c
@@ -16,6 +16,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/signal.h>
+#include <linux/kernel.h>
 
 #include <asm/machdep.h>
 
@@ -36,7 +37,7 @@
 	{ 1, GBUS_INT_PRIORITY_HIGH },
 	{ 3, GBUS_INT_PRIORITY_LOW }
 };
-#define NUM_USED_GINTS	(sizeof used_gint / sizeof used_gint[0])
+#define NUM_USED_GINTS ARRAY_SIZE(used_gint)
 
 /* A table of which GINT is used by each GBUS interrupts (they are
    assigned based on priority).  */
@@ -231,8 +232,7 @@
 	{ "GBUS_INT", IRQ_GBUS_INT(0), IRQ_GBUS_INT_NUM, 1, 6},
 	{ 0 }
 };
-#define NUM_GBUS_IRQ_INITS  \
-   ((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1)
+#define NUM_GBUS_IRQ_INITS (ARRAY_SIZE(gbus_irq_inits) - 1)
 
 static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
 
diff --git a/arch/v850/kernel/ma.c b/arch/v850/kernel/ma.c
index 2aa8ab0..143774d 100644
--- a/arch/v850/kernel/ma.c
+++ b/arch/v850/kernel/ma.c
@@ -43,7 +43,7 @@
 	{ "ST",  IRQ_INTST(0), 	IRQ_INTST_NUM, 	4, 5 },
 	{ 0 }
 };
-#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
+#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
 
 static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
 
diff --git a/arch/v850/kernel/me2.c b/arch/v850/kernel/me2.c
index 14b0c88..38be5c1 100644
--- a/arch/v850/kernel/me2.c
+++ b/arch/v850/kernel/me2.c
@@ -44,7 +44,7 @@
 	{ "UBTITO", IRQ_INTUBTITO(0), IRQ_INTUBTITO_NUM, 5, 4 },
 	{ 0 }
 };
-#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
+#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
 
 static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
 
diff --git a/arch/v850/kernel/rte_cb.c b/arch/v850/kernel/rte_cb.c
index 0f7f6cd..43018e1 100644
--- a/arch/v850/kernel/rte_cb.c
+++ b/arch/v850/kernel/rte_cb.c
@@ -15,6 +15,7 @@
 #include <linux/irq.h>
 #include <linux/fs.h>
 #include <linux/module.h>
+#include <linux/kernel.h>
 
 #include <asm/machdep.h>
 #include <asm/v850e_uart.h>
@@ -176,8 +177,7 @@
 #endif
 	{ 0 }
 };
-#define NUM_GBUS_IRQ_INITS  \
-   ((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1)
+#define NUM_GBUS_IRQ_INITS (ARRAY_SIZE(gbus_irq_inits) - 1)
 
 static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
 
diff --git a/arch/v850/kernel/rte_cb_leds.c b/arch/v850/kernel/rte_cb_leds.c
index 996bd4f..aa47ab1 100644
--- a/arch/v850/kernel/rte_cb_leds.c
+++ b/arch/v850/kernel/rte_cb_leds.c
@@ -117,7 +117,7 @@
 	return 0;
 }
 
-static struct file_operations leds_fops = {
+static const struct file_operations leds_fops = {
 	.read		= leds_dev_read,
 	.write		= leds_dev_write,
 	.llseek		= leds_dev_lseek
diff --git a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c
index 35213fa..35a4bd5 100644
--- a/arch/v850/kernel/rte_mb_a_pci.c
+++ b/arch/v850/kernel/rte_mb_a_pci.c
@@ -70,8 +70,7 @@
 	/* PCI slot 2 */
 	{ 9, 	IRQ_MB_A_PCI2(0),	1 }
 };
-#define NUM_MB_PCI_DEV_IRQS \
-  (sizeof mb_pci_dev_irqs / sizeof mb_pci_dev_irqs[0])
+#define NUM_MB_PCI_DEV_IRQS ARRAY_SIZE(mb_pci_dev_irqs)
 
 
 /* PCI configuration primitives.  */
diff --git a/arch/v850/kernel/rte_me2_cb.c b/arch/v850/kernel/rte_me2_cb.c
index 3be355a..46803d4 100644
--- a/arch/v850/kernel/rte_me2_cb.c
+++ b/arch/v850/kernel/rte_me2_cb.c
@@ -170,8 +170,7 @@
 	{ "CB_EXTTM2",       IRQ_CB_EXTTM2,       1, 1, 6 },
 	{ 0 }
 };
-#define NUM_CB_PIC_IRQ_INITS  \
-   ((sizeof cb_pic_irq_inits / sizeof cb_pic_irq_inits[0]) - 1)
+#define NUM_CB_PIC_IRQ_INITS (ARRAY_SIZE(cb_pic_irq_inits) - 1)
 
 static struct hw_interrupt_type cb_pic_hw_itypes[NUM_CB_PIC_IRQ_INITS];
 static unsigned char cb_pic_active_irqs = 0;
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
index 1bf672a..a914f24 100644
--- a/arch/v850/kernel/setup.c
+++ b/arch/v850/kernel/setup.c
@@ -42,7 +42,7 @@
 extern char _root_fs_image_end __attribute__ ((__weak__));
 
 
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
 
 /* Memory not used by the kernel.  */
 static unsigned long total_ram_pages;
@@ -64,8 +64,8 @@
 {
 	/* Keep a copy of command line */
 	*cmdline = command_line;
-	memcpy (saved_command_line, command_line, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+	memcpy (boot_command_line, command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
 
 	console_verbose ();
 
diff --git a/arch/v850/kernel/teg.c b/arch/v850/kernel/teg.c
index 290d506..699248f 100644
--- a/arch/v850/kernel/teg.c
+++ b/arch/v850/kernel/teg.c
@@ -43,7 +43,7 @@
 	{ "ST",	 IRQ_INTST(0),	IRQ_INTST_NUM,	1, 5 },
 	{ 0 }
 };
-#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
+#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
 
 static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
 
diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
index cd06f47..486e3a4 100644
--- a/arch/v850/kernel/time.c
+++ b/arch/v850/kernel/time.c
@@ -28,14 +28,6 @@
 #define TICK_SIZE	(tick_nsec / 1000)
 
 /*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
-/*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
index 3a5fd07..3563082 100644
--- a/arch/v850/kernel/vmlinux.lds.S
+++ b/arch/v850/kernel/vmlinux.lds.S
@@ -190,12 +190,16 @@
 		__root_fs_image_start = . ;				      \
 		*(.root)						      \
 		__root_fs_image_end = . ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
 /* The initramfs archive.  */
 #define INITRAMFS_CONTENTS						      \
 		. = ALIGN (4) ;						      \
 		___initramfs_start = . ;				      \
 			*(.init.ramfs)					      \
 		___initramfs_end = . ;
+#endif
+
 /* Where the initial bootmap (bitmap for the boot-time memory allocator) 
    should be place.  */
 #define BOOTMAP_CONTENTS						      \
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index d427553..56eb14c 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -24,6 +24,14 @@
 	bool
 	default y
 
+config GENERIC_TIME
+	bool
+	default y
+
+config GENERIC_TIME_VSYSCALL
+	bool
+	default y
+
 config ZONE_DMA32
 	bool
 	default y
@@ -44,6 +52,10 @@
 	bool
 	default y
 
+config ZONE_DMA
+	bool
+	default y
+
 config ISA
 	bool
 
@@ -148,18 +160,18 @@
 	  Optimize for Intel Pentium 4 and older Nocona/Dempsey Xeon CPUs
 	  with Intel Extended Memory 64 Technology(EM64T). For details see
 	  <http://www.intel.com/technology/64bitextensions/>.
-	  Note the the latest Xeons (Xeon 51xx and 53xx) are not based on the
-          Netburst core and shouldn't use this option. You can distingush them
+	  Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the
+          Netburst core and shouldn't use this option. You can distinguish them
 	  using the cpu family field
-	  in /proc/cpuinfo. Family 15 is a older Xeon, Family 6 a newer one
-	  (this rule only applies to system that support EM64T)
+	  in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one
+	  (this rule only applies to systems that support EM64T)
 
 config MCORE2
 	bool "Intel Core2 / newer Xeon"
 	help
 	  Optimize for Intel Core2 and newer Xeons (51xx)
-	  You can distingush the newer Xeons from the older ones using
-	  the cpu family field in /proc/cpuinfo. 15 is a older Xeon
+	  You can distinguish the newer Xeons from the older ones using
+	  the cpu family field in /proc/cpuinfo. 15 is an older Xeon
 	  (use CONFIG_MPSC then), 6 is a newer one. This rule only
 	  applies to CPUs that support EM64T.
 
@@ -454,8 +466,8 @@
 	  on systems with more than 3GB. This is usually needed for USB,
 	  sound, many IDE/SATA chipsets and some other devices.
 	  Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART
-	  based IOMMU and a software bounce buffer based IOMMU used on Intel
-	  systems and as fallback.
+	  based hardware IOMMU and a software bounce buffer based IOMMU used
+	  on Intel systems and as fallback.
 	  The code is only active when needed (enough memory and limited
 	  device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified
 	  too.
@@ -492,6 +504,12 @@
 # need this always selected by IOMMU for the VIA workaround
 config SWIOTLB
 	bool
+	help
+	  Support for software bounce buffers used on x86-64 systems
+	  which don't have a hardware IOMMU (e.g. the current generation
+	  of Intel's x86-64 CPUs). Using this PCI devices which can only
+	  access 32-bits of memory can be used on systems with more than
+	  3 GB of memory. If unsure, say Y.
 
 config X86_MCE
 	bool "Machine check support" if EMBEDDED
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 69584c2..293a4a4 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.20-rc3
-# Fri Jan  5 11:54:41 2007
+# Linux kernel version: 2.6.20-git8
+# Tue Feb 13 11:25:16 2007
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -11,6 +11,7 @@
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -153,6 +154,7 @@
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
 CONFIG_OUT_OF_LINE_PFN_TO_PAGE=y
 CONFIG_NR_CPUS=32
@@ -201,13 +203,14 @@
 CONFIG_ACPI_SLEEP=y
 CONFIG_ACPI_SLEEP_PROC_FS=y
 CONFIG_ACPI_SLEEP_PROC_SLEEP=y
+CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_AC=y
 CONFIG_ACPI_BATTERY=y
 CONFIG_ACPI_BUTTON=y
-# CONFIG_ACPI_VIDEO is not set
 # CONFIG_ACPI_HOTKEY is not set
 CONFIG_ACPI_FAN=y
 # CONFIG_ACPI_DOCK is not set
+# CONFIG_ACPI_BAY is not set
 CONFIG_ACPI_PROCESSOR=y
 CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=y
@@ -263,7 +266,6 @@
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
 CONFIG_PCI_MSI=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_HT_IRQ is not set
 
@@ -398,6 +400,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -466,6 +469,7 @@
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_BLK_DEV_IDEACPI=y
 # CONFIG_IDE_TASK_IOCTL is not set
 
 #
@@ -497,6 +501,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT8213 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
@@ -507,6 +512,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -599,6 +605,7 @@
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
 #
 CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_SVW=y
 CONFIG_ATA_PIIX=y
@@ -614,6 +621,7 @@
 # CONFIG_SATA_ULI is not set
 CONFIG_SATA_VIA=y
 # CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
 CONFIG_SATA_INTEL_COMBINED=y
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
@@ -630,6 +638,7 @@
 # CONFIG_PATA_HPT3X2N is not set
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MARVELL is not set
@@ -682,9 +691,7 @@
 # Subsystem Options
 #
 # CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
 # CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
 
 #
 # Device Drivers
@@ -707,6 +714,11 @@
 # CONFIG_I2O is not set
 
 #
+# Macintosh device drivers
+#
+# CONFIG_MAC_EMUMOUSEBTN is not set
+
+#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -774,6 +786,7 @@
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -795,11 +808,13 @@
 CONFIG_TIGON3=y
 CONFIG_BNX2=y
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
@@ -1115,6 +1130,7 @@
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
+CONFIG_OBSOLETE_OSS=y
 # CONFIG_SOUND_BT878 is not set
 # CONFIG_SOUND_ES1371 is not set
 CONFIG_SOUND_ICH=y
@@ -1128,6 +1144,7 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
 
 #
 # USB support
@@ -1142,10 +1159,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1155,9 +1170,11 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO 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_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
@@ -1208,6 +1225,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1313,6 +1331,10 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
 # Virtualization
 #
 # CONFIG_KVM is not set
@@ -1512,6 +1534,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
@@ -1520,7 +1543,6 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -1560,4 +1582,5 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 5ce0bd4..071100e 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -300,12 +300,10 @@
 		bprm->loader += stack_base;
 	bprm->exec += stack_base;
 
-	mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+	mpnt = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 	if (!mpnt) 
 		return -ENOMEM; 
 
-	memset(mpnt, 0, sizeof(*mpnt));
-
 	down_write(&mm->mmap_sem);
 	{
 		mpnt->vm_mm = mm;
@@ -346,20 +344,30 @@
 #include <linux/sysctl.h>
 
 static ctl_table abi_table2[] = {
-	{ 99, "vsyscall32", &sysctl_vsyscall32, sizeof(int), 0644, NULL,
-	  proc_dointvec },
-	{ 0, }
-}; 
+	{
+		.ctl_name	= 99,
+		.procname	= "vsyscall32",
+		.data		= &sysctl_vsyscall32,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec
+	},
+	{}
+};
 
-static ctl_table abi_root_table2[] = { 
-	{ .ctl_name = CTL_ABI, .procname = "abi", .mode = 0555, 
-	  .child = abi_table2 }, 
-	{ 0 }, 
-}; 
+static ctl_table abi_root_table2[] = {
+	{
+		.ctl_name = CTL_ABI,
+		.procname = "abi",
+		.mode = 0555,
+		.child = abi_table2
+	},
+	{}
+};
 
 static __init int ia32_binfmt_init(void)
 { 
-	register_sysctl_table(abi_root_table2, 1);
+	register_sysctl_table(abi_root_table2);
 	return 0;
 }
 __initcall(ia32_binfmt_init);
diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
index ff499ef..359eacc 100644
--- a/arch/x86_64/ia32/ia32_signal.c
+++ b/arch/x86_64/ia32/ia32_signal.c
@@ -21,6 +21,7 @@
 #include <linux/stddef.h>
 #include <linux/personality.h>
 #include <linux/compat.h>
+#include <linux/binfmts.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/i387.h>
@@ -449,7 +450,11 @@
 
 	/* Return stub is in 32bit vsyscall page */
 	{ 
-		void __user *restorer = VSYSCALL32_SIGRETURN; 
+		void __user *restorer;
+		if (current->binfmt->hasvdso)
+			restorer = VSYSCALL32_SIGRETURN;
+		else
+			restorer = (void *)&frame->retcode;
 		if (ka->sa.sa_flags & SA_RESTORER)
 			restorer = ka->sa.sa_restorer;       
 		err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
@@ -495,7 +500,7 @@
 		ptrace_notify(SIGTRAP);
 
 #if DEBUG_SIG
-	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+	printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
 		current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
@@ -601,7 +606,7 @@
 		ptrace_notify(SIGTRAP);
 
 #if DEBUG_SIG
-	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+	printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
 		current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index b4aa875..eda7a0d 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -515,7 +515,7 @@
 	.quad sys32_vm86_warning	/* vm86old */ 
 	.quad compat_sys_wait4
 	.quad sys_swapoff		/* 115 */
-	.quad sys32_sysinfo
+	.quad compat_sys_sysinfo
 	.quad sys32_ipc
 	.quad sys_fsync
 	.quad stub32_sigreturn
@@ -718,4 +718,5 @@
 	.quad compat_sys_vmsplice
 	.quad compat_sys_move_pages
 	.quad sys_getcpu
+	.quad sys_epoll_pwait
 ia32_syscall_end:		
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index c9bac3a..200fdde 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -523,72 +523,6 @@
 	return sys_sysfs(option, arg1, arg2);
 }
 
-struct sysinfo32 {
-        s32 uptime;
-        u32 loads[3];
-        u32 totalram;
-        u32 freeram;
-        u32 sharedram;
-        u32 bufferram;
-        u32 totalswap;
-        u32 freeswap;
-        unsigned short procs;
-	unsigned short pad; 
-        u32 totalhigh;
-        u32 freehigh;
-        u32 mem_unit;
-        char _f[20-2*sizeof(u32)-sizeof(int)];
-};
-
-asmlinkage long
-sys32_sysinfo(struct sysinfo32 __user *info)
-{
-	struct sysinfo s;
-	int ret;
-	mm_segment_t old_fs = get_fs ();
-	int bitcount = 0;
-	
-	set_fs (KERNEL_DS);
-	ret = sys_sysinfo((struct sysinfo __user *)&s);
-	set_fs (old_fs);
-
-        /* Check to see if any memory value is too large for 32-bit and scale
-	 *  down if needed
-	 */
-	if ((s.totalram >> 32) || (s.totalswap >> 32)) {
-		while (s.mem_unit < PAGE_SIZE) {
-			s.mem_unit <<= 1;
-			bitcount++;
-		}
-		s.totalram >>= bitcount;
-		s.freeram >>= bitcount;
-		s.sharedram >>= bitcount;
-		s.bufferram >>= bitcount;
-		s.totalswap >>= bitcount;
-		s.freeswap >>= bitcount;
-		s.totalhigh >>= bitcount;
-		s.freehigh >>= bitcount;
-	}
-
-	if (!access_ok(VERIFY_WRITE, info, sizeof(struct sysinfo32)) ||
-	    __put_user (s.uptime, &info->uptime) ||
-	    __put_user (s.loads[0], &info->loads[0]) ||
-	    __put_user (s.loads[1], &info->loads[1]) ||
-	    __put_user (s.loads[2], &info->loads[2]) ||
-	    __put_user (s.totalram, &info->totalram) ||
-	    __put_user (s.freeram, &info->freeram) ||
-	    __put_user (s.sharedram, &info->sharedram) ||
-	    __put_user (s.bufferram, &info->bufferram) ||
-	    __put_user (s.totalswap, &info->totalswap) ||
-	    __put_user (s.freeswap, &info->freeswap) ||
-	    __put_user (s.procs, &info->procs) ||
-	    __put_user (s.totalhigh, &info->totalhigh) || 
-	    __put_user (s.freehigh, &info->freehigh) ||
-	    __put_user (s.mem_unit, &info->mem_unit))
-		return -EFAULT;
-	return 0;
-}
-                
 asmlinkage long
 sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval)
 {
diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c
index 59f1fa1..568ff0d 100644
--- a/arch/x86_64/ia32/syscall32.c
+++ b/arch/x86_64/ia32/syscall32.c
@@ -18,68 +18,34 @@
 extern unsigned char syscall32_sysenter[], syscall32_sysenter_end[];
 extern int sysctl_vsyscall32;
 
-char *syscall32_page; 
+static struct page *syscall32_pages[1];
 static int use_sysenter = -1;
 
-static struct page *
-syscall32_nopage(struct vm_area_struct *vma, unsigned long adr, int *type)
-{
-	struct page *p = virt_to_page(adr - vma->vm_start + syscall32_page);
-	get_page(p);
-	return p;
-}
-
-/* Prevent VMA merging */
-static void syscall32_vma_close(struct vm_area_struct *vma)
-{
-}
-
-static struct vm_operations_struct syscall32_vm_ops = {
-	.close = syscall32_vma_close,
-	.nopage = syscall32_nopage,
-};
-
 struct linux_binprm;
 
 /* Setup a VMA at program startup for the vsyscall page */
 int syscall32_setup_pages(struct linux_binprm *bprm, int exstack)
 {
-	int npages = (VSYSCALL32_END - VSYSCALL32_BASE) >> PAGE_SHIFT;
-	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
 	int ret;
 
-	vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
-	if (!vma)
-		return -ENOMEM;
-
-	memset(vma, 0, sizeof(struct vm_area_struct));
-	/* Could randomize here */
-	vma->vm_start = VSYSCALL32_BASE;
-	vma->vm_end = VSYSCALL32_END;
-	/* MAYWRITE to allow gdb to COW and set breakpoints */
-	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
+	down_write(&mm->mmap_sem);
 	/*
+	 * MAYWRITE to allow gdb to COW and set breakpoints
+	 *
 	 * Make sure the vDSO gets into every core dump.
 	 * Dumping its contents makes post-mortem fully interpretable later
 	 * without matching up the same kernel and hardware config to see
 	 * what PC values meant.
 	 */
-	vma->vm_flags |= VM_ALWAYSDUMP;
-	vma->vm_flags |= mm->def_flags;
-	vma->vm_page_prot = protection_map[vma->vm_flags & 7];
-	vma->vm_ops = &syscall32_vm_ops;
-	vma->vm_mm = mm;
-
-	down_write(&mm->mmap_sem);
-	if ((ret = insert_vm_struct(mm, vma))) {
-		up_write(&mm->mmap_sem);
-		kmem_cache_free(vm_area_cachep, vma);
-		return ret;
-	}
-	mm->total_vm += npages;
+	/* Could randomize here */
+	ret = install_special_mapping(mm, VSYSCALL32_BASE, PAGE_SIZE,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+				      VM_ALWAYSDUMP,
+				      syscall32_pages);
 	up_write(&mm->mmap_sem);
-	return 0;
+	return ret;
 }
 
 const char *arch_vma_name(struct vm_area_struct *vma)
@@ -92,9 +58,10 @@
 
 static int __init init_syscall32(void)
 { 
-	syscall32_page = (void *)get_zeroed_page(GFP_KERNEL); 
+	char *syscall32_page = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!syscall32_page) 
 		panic("Cannot allocate syscall32 page"); 
+	syscall32_pages[0] = virt_to_page(syscall32_page);
  	if (use_sysenter > 0) {
  		memcpy(syscall32_page, syscall32_sysenter,
  		       syscall32_sysenter_end - syscall32_sysenter);
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index 3c7cbff..bb47e86 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 \
-		pci-dma.o pci-nommu.o alternative.o
+		pci-dma.o pci-nommu.o alternative.o hpet.o tsc.o
 
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_X86_MCE)		+= mce.o therm_throt.o
@@ -19,7 +19,7 @@
 obj-$(CONFIG_X86_MSR)		+= msr.o
 obj-$(CONFIG_MICROCODE)		+= microcode.o
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
-obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
+obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o tsc_sync.o
 obj-y				+= apic.o  nmi.o
 obj-y				+= io_apic.o mpparse.o \
 		genapic.o genapic_cluster.o genapic_flat.o
@@ -43,6 +43,7 @@
 
 obj-y				+= topology.o
 obj-y				+= intel_cacheinfo.o
+obj-y				+= pcspeaker.o
 
 CFLAGS_vsyscall.o		:= $(PROFILING) -g0
 
@@ -56,3 +57,4 @@
 i8237-y				+= ../../i386/kernel/i8237.o
 msr-$(subst m,y,$(CONFIG_X86_MSR))  += ../../i386/kernel/msr.o
 alternative-y			+= ../../i386/kernel/alternative.o
+pcspeaker-y			+= ../../i386/kernel/pcspeaker.o
diff --git a/arch/x86_64/kernel/acpi/sleep.c b/arch/x86_64/kernel/acpi/sleep.c
index 5ebf62c..23178ce 100644
--- a/arch/x86_64/kernel/acpi/sleep.c
+++ b/arch/x86_64/kernel/acpi/sleep.c
@@ -58,7 +58,7 @@
 unsigned long acpi_video_flags;
 extern char wakeup_start, wakeup_end;
 
-extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
+extern unsigned long acpi_copy_wakeup_routine(unsigned long);
 
 static pgd_t low_ptr;
 
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 124b2d2..723417d 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -37,6 +37,7 @@
 #include <asm/idle.h>
 #include <asm/proto.h>
 #include <asm/timex.h>
+#include <asm/hpet.h>
 #include <asm/apic.h>
 
 int apic_mapped;
@@ -763,7 +764,7 @@
 	local_irq_save(flags);
 
 	/* wait for irq slice */
- 	if (vxtime.hpet_address && hpet_use_timer) {
+ 	if (hpet_address && hpet_use_timer) {
  		int trigger = hpet_readl(HPET_T0_CMP);
  		while (hpet_readl(HPET_COUNTER) >= trigger)
  			/* do nothing */ ;
@@ -785,7 +786,7 @@
 	/* Turn off PIT interrupt if we use APIC timer as main timer.
 	   Only works with the PM timer right now
 	   TBD fix it for HPET too. */
-	if (vxtime.mode == VXTIME_PMTMR &&
+	if ((pmtmr_ioport != 0) &&
 		smp_processor_id() == boot_cpu_id &&
 		apic_runs_main_timer == 1 &&
 		!cpu_isset(boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) {
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 6fe191c..4651fd2 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -83,6 +83,13 @@
 		return 1;
 	}
 
+#ifdef CONFIG_NUMA
+	/* NUMA memory to node map */
+	if (last >= nodemap_addr && addr < nodemap_addr + nodemap_size) {
+		*addrp = nodemap_addr + nodemap_size;
+		return 1;
+	}
+#endif
 	/* XXX ramdisk image here? */ 
 	return 0;
 } 
@@ -184,6 +191,37 @@
 }
 
 /*
+ * Find the hole size in the range.
+ */
+unsigned long __init e820_hole_size(unsigned long start, unsigned long end)
+{
+	unsigned long ram = 0;
+	int i;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		unsigned long last, addr;
+
+		if (ei->type != E820_RAM ||
+		    ei->addr+ei->size <= start ||
+		    ei->addr >= end)
+			continue;
+
+		addr = round_up(ei->addr, PAGE_SIZE);
+		if (addr < start)
+			addr = start;
+
+		last = round_down(ei->addr + ei->size, PAGE_SIZE);
+		if (last >= end)
+			last = end;
+
+		if (last > addr)
+			ram += last - addr;
+	}
+	return ((end - start) - ram);
+}
+
+/*
  * Mark e820 reserved areas as busy for the resource manager.
  */
 void __init e820_reserve_resources(void)
diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c
index bd30d13..8047ea8 100644
--- a/arch/x86_64/kernel/early-quirks.c
+++ b/arch/x86_64/kernel/early-quirks.c
@@ -53,7 +53,9 @@
 		return;
 
 	nvidia_hpet_detected = 0;
-	acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check);
+	if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check))
+		return;
+
 	if (nvidia_hpet_detected == 0) {
 		acpi_skip_timer_override = 1;
 		printk(KERN_INFO "Nvidia board "
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 9f5dac6..ed4350c 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -675,6 +675,9 @@
 ENTRY(call_function_interrupt)
 	apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
 END(call_function_interrupt)
+ENTRY(irq_move_cleanup_interrupt)
+	apicinterrupt IRQ_MOVE_CLEANUP_VECTOR,smp_irq_move_cleanup_interrupt
+END(irq_move_cleanup_interrupt)
 #endif
 
 ENTRY(apic_timer_interrupt)
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 1e6f808..598a4d0 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -163,6 +163,20 @@
 	 */
 	lgdt	cpu_gdt_descr
 
+	/* set up data segments. actually 0 would do too */
+	movl $__KERNEL_DS,%eax
+	movl %eax,%ds
+	movl %eax,%ss
+	movl %eax,%es
+
+	/*
+	 * We don't really need to load %fs or %gs, but load them anyway
+	 * to kill any stale realmode selectors.  This allows execution
+	 * under VT hardware.
+	 */
+	movl %eax,%fs
+	movl %eax,%gs
+
 	/* 
 	 * Setup up a dummy PDA. this is just for some early bootup code
 	 * that does in_interrupt() 
@@ -173,12 +187,6 @@
 	shrq	$32,%rdx
 	wrmsr	
 
-	/* set up data segments. actually 0 would do too */
-	movl $__KERNEL_DS,%eax
-	movl %eax,%ds	
-	movl %eax,%ss
-	movl %eax,%es
-			
 	/* esi is pointer to real mode structure with interesting info.
 	   pass it to C */
 	movl	%esi, %edi
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index cc230b9..5f197b0 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -34,8 +34,6 @@
 #define OLD_CL_BASE_ADDR        0x90000
 #define OLD_CL_OFFSET           0x90022
 
-extern char saved_command_line[];
-
 static void __init copy_bootdata(char *real_mode_data)
 {
 	int new_data;
@@ -50,7 +48,7 @@
 		new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
 	}
 	command_line = (char *) ((u64)(new_data));
-	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 }
 
 void __init x86_64_start_kernel(char * real_mode_data)
diff --git a/arch/x86_64/kernel/hpet.c b/arch/x86_64/kernel/hpet.c
new file mode 100644
index 0000000..65a0edd
--- /dev/null
+++ b/arch/x86_64/kernel/hpet.c
@@ -0,0 +1,511 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+#include <linux/time.h>
+#include <linux/clocksource.h>
+#include <linux/ioport.h>
+#include <linux/acpi.h>
+#include <linux/hpet.h>
+#include <asm/pgtable.h>
+#include <asm/vsyscall.h>
+#include <asm/timex.h>
+#include <asm/hpet.h>
+
+int nohpet __initdata;
+
+unsigned long hpet_address;
+unsigned long hpet_period;	/* fsecs / HPET clock */
+unsigned long hpet_tick;	/* HPET clocks / interrupt */
+
+int hpet_use_timer;		/* Use counter of hpet for time keeping,
+				 * otherwise PIT
+				 */
+
+#ifdef	CONFIG_HPET
+static __init int late_hpet_init(void)
+{
+	struct hpet_data	hd;
+	unsigned int 		ntimer;
+
+	if (!hpet_address)
+        	return 0;
+
+	memset(&hd, 0, sizeof(hd));
+
+	ntimer = hpet_readl(HPET_ID);
+	ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
+	ntimer++;
+
+	/*
+	 * Register with driver.
+	 * Timer0 and Timer1 is used by platform.
+	 */
+	hd.hd_phys_address = hpet_address;
+	hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE);
+	hd.hd_nirqs = ntimer;
+	hd.hd_flags = HPET_DATA_PLATFORM;
+	hpet_reserve_timer(&hd, 0);
+#ifdef	CONFIG_HPET_EMULATE_RTC
+	hpet_reserve_timer(&hd, 1);
+#endif
+	hd.hd_irq[0] = HPET_LEGACY_8254;
+	hd.hd_irq[1] = HPET_LEGACY_RTC;
+	if (ntimer > 2) {
+		struct hpet		*hpet;
+		struct hpet_timer	*timer;
+		int			i;
+
+		hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE);
+		timer = &hpet->hpet_timers[2];
+		for (i = 2; i < ntimer; timer++, i++)
+			hd.hd_irq[i] = (timer->hpet_config &
+					Tn_INT_ROUTE_CNF_MASK) >>
+				Tn_INT_ROUTE_CNF_SHIFT;
+
+	}
+
+	hpet_alloc(&hd);
+	return 0;
+}
+fs_initcall(late_hpet_init);
+#endif
+
+int hpet_timer_stop_set_go(unsigned long tick)
+{
+	unsigned int cfg;
+
+/*
+ * Stop the timers and reset the main counter.
+ */
+
+	cfg = hpet_readl(HPET_CFG);
+	cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
+	hpet_writel(cfg, HPET_CFG);
+	hpet_writel(0, HPET_COUNTER);
+	hpet_writel(0, HPET_COUNTER + 4);
+
+/*
+ * Set up timer 0, as periodic with first interrupt to happen at hpet_tick,
+ * and period also hpet_tick.
+ */
+	if (hpet_use_timer) {
+		hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
+		    HPET_TN_32BIT, HPET_T0_CFG);
+		hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */
+		hpet_writel(hpet_tick, HPET_T0_CMP); /* period */
+		cfg |= HPET_CFG_LEGACY;
+	}
+/*
+ * Go!
+ */
+
+	cfg |= HPET_CFG_ENABLE;
+	hpet_writel(cfg, HPET_CFG);
+
+	return 0;
+}
+
+int hpet_arch_init(void)
+{
+	unsigned int id;
+
+	if (!hpet_address)
+		return -1;
+	set_fixmap_nocache(FIX_HPET_BASE, hpet_address);
+	__set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
+
+/*
+ * Read the period, compute tick and quotient.
+ */
+
+	id = hpet_readl(HPET_ID);
+
+	if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER))
+		return -1;
+
+	hpet_period = hpet_readl(HPET_PERIOD);
+	if (hpet_period < 100000 || hpet_period > 100000000)
+		return -1;
+
+	hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period;
+
+	hpet_use_timer = (id & HPET_ID_LEGSUP);
+
+	return hpet_timer_stop_set_go(hpet_tick);
+}
+
+int hpet_reenable(void)
+{
+	return hpet_timer_stop_set_go(hpet_tick);
+}
+
+/*
+ * calibrate_tsc() calibrates the processor TSC in a very simple way, comparing
+ * it to the HPET timer of known frequency.
+ */
+
+#define TICK_COUNT 100000000
+#define TICK_MIN   5000
+
+/*
+ * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none
+ * occurs between the reads of the hpet & TSC.
+ */
+static void __init read_hpet_tsc(int *hpet, int *tsc)
+{
+	int tsc1, tsc2, hpet1;
+
+	do {
+		tsc1 = get_cycles_sync();
+		hpet1 = hpet_readl(HPET_COUNTER);
+		tsc2 = get_cycles_sync();
+	} while (tsc2 - tsc1 > TICK_MIN);
+	*hpet = hpet1;
+	*tsc = tsc2;
+}
+
+unsigned int __init hpet_calibrate_tsc(void)
+{
+	int tsc_start, hpet_start;
+	int tsc_now, hpet_now;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	read_hpet_tsc(&hpet_start, &tsc_start);
+
+	do {
+		local_irq_disable();
+		read_hpet_tsc(&hpet_now, &tsc_now);
+		local_irq_restore(flags);
+	} while ((tsc_now - tsc_start) < TICK_COUNT &&
+		(hpet_now - hpet_start) < TICK_COUNT);
+
+	return (tsc_now - tsc_start) * 1000000000L
+		/ ((hpet_now - hpet_start) * hpet_period / 1000);
+}
+
+#ifdef CONFIG_HPET_EMULATE_RTC
+/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
+ * is enabled, we support RTC interrupt functionality in software.
+ * RTC has 3 kinds of interrupts:
+ * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
+ *    is updated
+ * 2) Alarm Interrupt - generate an interrupt at a specific time of day
+ * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
+ *    2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
+ * (1) and (2) above are implemented using polling at a frequency of
+ * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
+ * overhead. (DEFAULT_RTC_INT_FREQ)
+ * For (3), we use interrupts at 64Hz or user specified periodic
+ * frequency, whichever is higher.
+ */
+#include <linux/rtc.h>
+
+#define DEFAULT_RTC_INT_FREQ 	64
+#define RTC_NUM_INTS 		1
+
+static unsigned long UIE_on;
+static unsigned long prev_update_sec;
+
+static unsigned long AIE_on;
+static struct rtc_time alarm_time;
+
+static unsigned long PIE_on;
+static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ;
+static unsigned long PIE_count;
+
+static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
+static unsigned int hpet_t1_cmp; /* cached comparator register */
+
+int is_hpet_enabled(void)
+{
+	return hpet_address != 0;
+}
+
+/*
+ * Timer 1 for RTC, we do not use periodic interrupt feature,
+ * even if HPET supports periodic interrupts on Timer 1.
+ * The reason being, to set up a periodic interrupt in HPET, we need to
+ * stop the main counter. And if we do that everytime someone diables/enables
+ * RTC, we will have adverse effect on main kernel timer running on Timer 0.
+ * So, for the time being, simulate the periodic interrupt in software.
+ *
+ * hpet_rtc_timer_init() is called for the first time and during subsequent
+ * interuppts reinit happens through hpet_rtc_timer_reinit().
+ */
+int hpet_rtc_timer_init(void)
+{
+	unsigned int cfg, cnt;
+	unsigned long flags;
+
+	if (!is_hpet_enabled())
+		return 0;
+	/*
+	 * Set the counter 1 and enable the interrupts.
+	 */
+	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
+		hpet_rtc_int_freq = PIE_freq;
+	else
+		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
+
+	local_irq_save(flags);
+
+	cnt = hpet_readl(HPET_COUNTER);
+	cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
+	hpet_writel(cnt, HPET_T1_CMP);
+	hpet_t1_cmp = cnt;
+
+	cfg = hpet_readl(HPET_T1_CFG);
+	cfg &= ~HPET_TN_PERIODIC;
+	cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+	hpet_writel(cfg, HPET_T1_CFG);
+
+	local_irq_restore(flags);
+
+	return 1;
+}
+
+static void hpet_rtc_timer_reinit(void)
+{
+	unsigned int cfg, cnt, ticks_per_int, lost_ints;
+
+	if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
+		cfg = hpet_readl(HPET_T1_CFG);
+		cfg &= ~HPET_TN_ENABLE;
+		hpet_writel(cfg, HPET_T1_CFG);
+		return;
+	}
+
+	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
+		hpet_rtc_int_freq = PIE_freq;
+	else
+		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
+
+	/* It is more accurate to use the comparator value than current count.*/
+	ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq;
+	hpet_t1_cmp += ticks_per_int;
+	hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
+
+	/*
+	 * If the interrupt handler was delayed too long, the write above tries
+	 * to schedule the next interrupt in the past and the hardware would
+	 * not interrupt until the counter had wrapped around.
+	 * So we have to check that the comparator wasn't set to a past time.
+	 */
+	cnt = hpet_readl(HPET_COUNTER);
+	if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) {
+		lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1;
+		/* Make sure that, even with the time needed to execute
+		 * this code, the next scheduled interrupt has been moved
+		 * back to the future: */
+		lost_ints++;
+
+		hpet_t1_cmp += lost_ints * ticks_per_int;
+		hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
+
+		if (PIE_on)
+			PIE_count += lost_ints;
+
+		if (printk_ratelimit())
+			printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
+			       hpet_rtc_int_freq);
+	}
+}
+
+/*
+ * The functions below are called from rtc driver.
+ * Return 0 if HPET is not being used.
+ * Otherwise do the necessary changes and return 1.
+ */
+int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
+{
+	if (!is_hpet_enabled())
+		return 0;
+
+	if (bit_mask & RTC_UIE)
+		UIE_on = 0;
+	if (bit_mask & RTC_PIE)
+		PIE_on = 0;
+	if (bit_mask & RTC_AIE)
+		AIE_on = 0;
+
+	return 1;
+}
+
+int hpet_set_rtc_irq_bit(unsigned long bit_mask)
+{
+	int timer_init_reqd = 0;
+
+	if (!is_hpet_enabled())
+		return 0;
+
+	if (!(PIE_on | AIE_on | UIE_on))
+		timer_init_reqd = 1;
+
+	if (bit_mask & RTC_UIE) {
+		UIE_on = 1;
+	}
+	if (bit_mask & RTC_PIE) {
+		PIE_on = 1;
+		PIE_count = 0;
+	}
+	if (bit_mask & RTC_AIE) {
+		AIE_on = 1;
+	}
+
+	if (timer_init_reqd)
+		hpet_rtc_timer_init();
+
+	return 1;
+}
+
+int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
+{
+	if (!is_hpet_enabled())
+		return 0;
+
+	alarm_time.tm_hour = hrs;
+	alarm_time.tm_min = min;
+	alarm_time.tm_sec = sec;
+
+	return 1;
+}
+
+int hpet_set_periodic_freq(unsigned long freq)
+{
+	if (!is_hpet_enabled())
+		return 0;
+
+	PIE_freq = freq;
+	PIE_count = 0;
+
+	return 1;
+}
+
+int hpet_rtc_dropped_irq(void)
+{
+	if (!is_hpet_enabled())
+		return 0;
+
+	return 1;
+}
+
+irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct rtc_time curr_time;
+	unsigned long rtc_int_flag = 0;
+	int call_rtc_interrupt = 0;
+
+	hpet_rtc_timer_reinit();
+
+	if (UIE_on | AIE_on) {
+		rtc_get_rtc_time(&curr_time);
+	}
+	if (UIE_on) {
+		if (curr_time.tm_sec != prev_update_sec) {
+			/* Set update int info, call real rtc int routine */
+			call_rtc_interrupt = 1;
+			rtc_int_flag = RTC_UF;
+			prev_update_sec = curr_time.tm_sec;
+		}
+	}
+	if (PIE_on) {
+		PIE_count++;
+		if (PIE_count >= hpet_rtc_int_freq/PIE_freq) {
+			/* Set periodic int info, call real rtc int routine */
+			call_rtc_interrupt = 1;
+			rtc_int_flag |= RTC_PF;
+			PIE_count = 0;
+		}
+	}
+	if (AIE_on) {
+		if ((curr_time.tm_sec == alarm_time.tm_sec) &&
+		    (curr_time.tm_min == alarm_time.tm_min) &&
+		    (curr_time.tm_hour == alarm_time.tm_hour)) {
+			/* Set alarm int info, call real rtc int routine */
+			call_rtc_interrupt = 1;
+			rtc_int_flag |= RTC_AF;
+		}
+	}
+	if (call_rtc_interrupt) {
+		rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
+		rtc_interrupt(rtc_int_flag, dev_id);
+	}
+	return IRQ_HANDLED;
+}
+#endif
+
+static int __init nohpet_setup(char *s)
+{
+	nohpet = 1;
+	return 1;
+}
+
+__setup("nohpet", nohpet_setup);
+
+#define HPET_MASK	0xFFFFFFFF
+#define HPET_SHIFT	22
+
+/* FSEC = 10^-15 NSEC = 10^-9 */
+#define FSEC_PER_NSEC	1000000
+
+static void *hpet_ptr;
+
+static cycle_t read_hpet(void)
+{
+	return (cycle_t)readl(hpet_ptr);
+}
+
+static cycle_t __vsyscall_fn vread_hpet(void)
+{
+	return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
+}
+
+struct clocksource clocksource_hpet = {
+	.name		= "hpet",
+	.rating		= 250,
+	.read		= read_hpet,
+	.mask		= (cycle_t)HPET_MASK,
+	.mult		= 0, /* set below */
+	.shift		= HPET_SHIFT,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+	.vread		= vread_hpet,
+};
+
+static int __init init_hpet_clocksource(void)
+{
+	unsigned long hpet_period;
+	void __iomem *hpet_base;
+	u64 tmp;
+
+	if (!hpet_address)
+		return -ENODEV;
+
+	/* calculate the hpet address: */
+	hpet_base = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
+	hpet_ptr = hpet_base + HPET_COUNTER;
+
+	/* calculate the frequency: */
+	hpet_period = readl(hpet_base + HPET_PERIOD);
+
+	/*
+	 * hpet period is in femto seconds per cycle
+	 * so we need to convert this to ns/cyc units
+	 * aproximated by mult/2^shift
+	 *
+	 *  fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
+	 *  fsec/cyc * 1ns/1000000fsec * 2^shift = mult
+	 *  fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
+	 *  (fsec/cyc << shift)/1000000 = mult
+	 *  (hpet_period << shift)/FSEC_PER_NSEC = mult
+	 */
+	tmp = (u64)hpet_period << HPET_SHIFT;
+	do_div(tmp, FSEC_PER_NSEC);
+	clocksource_hpet.mult = (u32)tmp;
+
+	return clocksource_register(&clocksource_hpet);
+}
+
+module_init(init_hpet_clocksource);
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index d73c79e..21d95b7 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -103,6 +103,7 @@
 static struct irq_chip i8259A_chip = {
 	.name		= "XT-PIC",
 	.mask		= disable_8259A_irq,
+	.disable	= disable_8259A_irq,
 	.unmask		= enable_8259A_irq,
 	.mask_ack	= mask_and_ack_8259A,
 };
@@ -298,7 +299,7 @@
 	 * outb_p - this has to work on a wide range of PC hardware.
 	 */
 	outb_p(0x11, 0x20);	/* ICW1: select 8259A-1 init */
-	outb_p(0x20 + 0, 0x21);	/* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
+	outb_p(IRQ0_VECTOR, 0x21);	/* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
 	outb_p(0x04, 0x21);	/* 8259A-1 (the master) has a slave on IR2 */
 	if (auto_eoi)
 		outb_p(0x03, 0x21);	/* master does Auto EOI */
@@ -306,7 +307,7 @@
 		outb_p(0x01, 0x21);	/* master expects normal EOI */
 
 	outb_p(0x11, 0xA0);	/* ICW1: select 8259A-2 init */
-	outb_p(0x20 + 8, 0xA1);	/* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
+	outb_p(IRQ8_VECTOR, 0xA1);	/* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
 	outb_p(0x02, 0xA1);	/* 8259A-2 is a slave on master's IR2 */
 	outb_p(0x01, 0xA1);	/* (slave's support for AEOI in flat mode
 				    is to be investigated) */
@@ -397,24 +398,24 @@
 
 static struct irqaction irq2 = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL};
 DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
-	[0 ... FIRST_EXTERNAL_VECTOR - 1] = -1,
-	[FIRST_EXTERNAL_VECTOR + 0] = 0,
-	[FIRST_EXTERNAL_VECTOR + 1] = 1,
-	[FIRST_EXTERNAL_VECTOR + 2] = 2,
-	[FIRST_EXTERNAL_VECTOR + 3] = 3,
-	[FIRST_EXTERNAL_VECTOR + 4] = 4,
-	[FIRST_EXTERNAL_VECTOR + 5] = 5,
-	[FIRST_EXTERNAL_VECTOR + 6] = 6,
-	[FIRST_EXTERNAL_VECTOR + 7] = 7,
-	[FIRST_EXTERNAL_VECTOR + 8] = 8,
-	[FIRST_EXTERNAL_VECTOR + 9] = 9,
-	[FIRST_EXTERNAL_VECTOR + 10] = 10,
-	[FIRST_EXTERNAL_VECTOR + 11] = 11,
-	[FIRST_EXTERNAL_VECTOR + 12] = 12,
-	[FIRST_EXTERNAL_VECTOR + 13] = 13,
-	[FIRST_EXTERNAL_VECTOR + 14] = 14,
-	[FIRST_EXTERNAL_VECTOR + 15] = 15,
-	[FIRST_EXTERNAL_VECTOR + 16 ... NR_VECTORS - 1] = -1
+	[0 ... IRQ0_VECTOR - 1] = -1,
+	[IRQ0_VECTOR] = 0,
+	[IRQ1_VECTOR] = 1,
+	[IRQ2_VECTOR] = 2,
+	[IRQ3_VECTOR] = 3,
+	[IRQ4_VECTOR] = 4,
+	[IRQ5_VECTOR] = 5,
+	[IRQ6_VECTOR] = 6,
+	[IRQ7_VECTOR] = 7,
+	[IRQ8_VECTOR] = 8,
+	[IRQ9_VECTOR] = 9,
+	[IRQ10_VECTOR] = 10,
+	[IRQ11_VECTOR] = 11,
+	[IRQ12_VECTOR] = 12,
+	[IRQ13_VECTOR] = 13,
+	[IRQ14_VECTOR] = 14,
+	[IRQ15_VECTOR] = 15,
+	[IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
 };
 
 void __init init_ISA_irqs (void)
@@ -449,6 +450,7 @@
 void error_interrupt(void);
 void reschedule_interrupt(void);
 void call_function_interrupt(void);
+void irq_move_cleanup_interrupt(void);
 void invalidate_interrupt0(void);
 void invalidate_interrupt1(void);
 void invalidate_interrupt2(void);
@@ -519,12 +521,6 @@
 
 #ifdef CONFIG_SMP
 	/*
-	 * IRQ0 must be given a fixed assignment and initialized,
-	 * because it's used before the IO-APIC is set up.
-	 */
-	__get_cpu_var(vector_irq)[FIRST_DEVICE_VECTOR] = 0;
-
-	/*
 	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
 	 * IPI, driven by wakeup.
 	 */
@@ -542,7 +538,10 @@
 
 	/* IPI for generic function call */
 	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-#endif	
+
+	/* Low priority IPI to cleanup after moving an irq */
+	set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
+#endif
 	set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
 	set_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
 
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 6be6730..48593f6 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -36,6 +36,7 @@
 #include <acpi/acpi_bus.h>
 #endif
 
+#include <asm/idle.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/desc.h>
@@ -47,7 +48,35 @@
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
 
-static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result);
+struct irq_cfg {
+	cpumask_t domain;
+	cpumask_t old_domain;
+	unsigned move_cleanup_count;
+	u8 vector;
+	u8 move_in_progress : 1;
+};
+
+/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
+struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {
+	[0]  = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR,  },
+	[1]  = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR,  },
+	[2]  = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR,  },
+	[3]  = { .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR,  },
+	[4]  = { .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR,  },
+	[5]  = { .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR,  },
+	[6]  = { .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR,  },
+	[7]  = { .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR,  },
+	[8]  = { .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR,  },
+	[9]  = { .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR,  },
+	[10] = { .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, },
+	[11] = { .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, },
+	[12] = { .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, },
+	[13] = { .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, },
+	[14] = { .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, },
+	[15] = { .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
+};
+
+static int assign_irq_vector(int irq, cpumask_t mask);
 
 #define __apicdebuginit  __init
 
@@ -74,7 +103,7 @@
  * Rough estimation of how many shared IRQs there are, can
  * be changed anytime.
  */
-#define MAX_PLUS_SHARED_IRQS NR_IRQ_VECTORS
+#define MAX_PLUS_SHARED_IRQS NR_IRQS
 #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
 
 /*
@@ -149,11 +178,11 @@
 		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
 		reg ACTION;						\
 		io_apic_modify(entry->apic, reg);			\
+		FINAL;							\
 		if (!entry->next)					\
 			break;						\
 		entry = irq_2_pin + entry->next;			\
 	}								\
-	FINAL;								\
 }
 
 union entry_union {
@@ -237,21 +266,19 @@
 
 static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
 {
+	struct irq_cfg *cfg = irq_cfg + irq;
 	unsigned long flags;
 	unsigned int dest;
 	cpumask_t tmp;
-	int vector;
 
 	cpus_and(tmp, mask, cpu_online_map);
 	if (cpus_empty(tmp))
-		tmp = TARGET_CPUS;
-
-	cpus_and(mask, tmp, CPU_MASK_ALL);
-
-	vector = assign_irq_vector(irq, mask, &tmp);
-	if (vector < 0)
 		return;
 
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cpus_and(tmp, cfg->domain, mask);
 	dest = cpu_mask_to_apicid(tmp);
 
 	/*
@@ -260,8 +287,8 @@
 	dest = SET_APIC_LOGICAL_ID(dest);
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	__target_IO_APIC_irq(irq, dest, vector);
-	set_native_irq_info(irq, mask);
+	__target_IO_APIC_irq(irq, dest, cfg->vector);
+	irq_desc[irq].affinity = mask;
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 #endif
@@ -615,63 +642,7 @@
 	return irq;
 }
 
-static inline int IO_APIC_irq_trigger(int irq)
-{
-	int apic, idx, pin;
-
-	for (apic = 0; apic < nr_ioapics; apic++) {
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-			idx = find_irq_entry(apic,pin,mp_INT);
-			if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
-				return irq_trigger(idx);
-		}
-	}
-	/*
-	 * nonexistent IRQs are edge default
-	 */
-	return 0;
-}
-
-/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = {
-	[0] = FIRST_EXTERNAL_VECTOR + 0,
-	[1] = FIRST_EXTERNAL_VECTOR + 1,
-	[2] = FIRST_EXTERNAL_VECTOR + 2,
-	[3] = FIRST_EXTERNAL_VECTOR + 3,
-	[4] = FIRST_EXTERNAL_VECTOR + 4,
-	[5] = FIRST_EXTERNAL_VECTOR + 5,
-	[6] = FIRST_EXTERNAL_VECTOR + 6,
-	[7] = FIRST_EXTERNAL_VECTOR + 7,
-	[8] = FIRST_EXTERNAL_VECTOR + 8,
-	[9] = FIRST_EXTERNAL_VECTOR + 9,
-	[10] = FIRST_EXTERNAL_VECTOR + 10,
-	[11] = FIRST_EXTERNAL_VECTOR + 11,
-	[12] = FIRST_EXTERNAL_VECTOR + 12,
-	[13] = FIRST_EXTERNAL_VECTOR + 13,
-	[14] = FIRST_EXTERNAL_VECTOR + 14,
-	[15] = FIRST_EXTERNAL_VECTOR + 15,
-};
-
-static cpumask_t irq_domain[NR_IRQ_VECTORS] __read_mostly = {
-	[0] = CPU_MASK_ALL,
-	[1] = CPU_MASK_ALL,
-	[2] = CPU_MASK_ALL,
-	[3] = CPU_MASK_ALL,
-	[4] = CPU_MASK_ALL,
-	[5] = CPU_MASK_ALL,
-	[6] = CPU_MASK_ALL,
-	[7] = CPU_MASK_ALL,
-	[8] = CPU_MASK_ALL,
-	[9] = CPU_MASK_ALL,
-	[10] = CPU_MASK_ALL,
-	[11] = CPU_MASK_ALL,
-	[12] = CPU_MASK_ALL,
-	[13] = CPU_MASK_ALL,
-	[14] = CPU_MASK_ALL,
-	[15] = CPU_MASK_ALL,
-};
-
-static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
+static int __assign_irq_vector(int irq, cpumask_t mask)
 {
 	/*
 	 * NOTE! The local APIC isn't very good at handling
@@ -685,20 +656,25 @@
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
 	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
-	int old_vector = -1;
+	unsigned int old_vector;
 	int cpu;
+	struct irq_cfg *cfg;
 
-	BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
+	BUG_ON((unsigned)irq >= NR_IRQS);
+	cfg = &irq_cfg[irq];
 
 	/* Only try and allocate irqs on cpus that are present */
 	cpus_and(mask, mask, cpu_online_map);
 
-	if (irq_vector[irq] > 0)
-		old_vector = irq_vector[irq];
-	if (old_vector > 0) {
-		cpus_and(*result, irq_domain[irq], mask);
-		if (!cpus_empty(*result))
-			return old_vector;
+	if ((cfg->move_in_progress) || cfg->move_cleanup_count)
+		return -EBUSY;
+
+	old_vector = cfg->vector;
+	if (old_vector) {
+		cpumask_t tmp;
+		cpus_and(tmp, cfg->domain, mask);
+		if (!cpus_empty(tmp))
+			return 0;
 	}
 
 	for_each_cpu_mask(cpu, mask) {
@@ -728,48 +704,47 @@
 		/* Found one! */
 		current_vector = vector;
 		current_offset = offset;
-		if (old_vector >= 0) {
-			cpumask_t old_mask;
-			int old_cpu;
-			cpus_and(old_mask, irq_domain[irq], cpu_online_map);
-			for_each_cpu_mask(old_cpu, old_mask)
-				per_cpu(vector_irq, old_cpu)[old_vector] = -1;
+		if (old_vector) {
+			cfg->move_in_progress = 1;
+			cfg->old_domain = cfg->domain;
 		}
 		for_each_cpu_mask(new_cpu, new_mask)
 			per_cpu(vector_irq, new_cpu)[vector] = irq;
-		irq_vector[irq] = vector;
-		irq_domain[irq] = domain;
-		cpus_and(*result, domain, mask);
-		return vector;
+		cfg->vector = vector;
+		cfg->domain = domain;
+		return 0;
 	}
 	return -ENOSPC;
 }
 
-static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
+static int assign_irq_vector(int irq, cpumask_t mask)
 {
-	int vector;
+	int err;
 	unsigned long flags;
 
 	spin_lock_irqsave(&vector_lock, flags);
-	vector = __assign_irq_vector(irq, mask, result);
+	err = __assign_irq_vector(irq, mask);
 	spin_unlock_irqrestore(&vector_lock, flags);
-	return vector;
+	return err;
 }
 
 static void __clear_irq_vector(int irq)
 {
+	struct irq_cfg *cfg;
 	cpumask_t mask;
 	int cpu, vector;
 
-	BUG_ON(!irq_vector[irq]);
+	BUG_ON((unsigned)irq >= NR_IRQS);
+	cfg = &irq_cfg[irq];
+	BUG_ON(!cfg->vector);
 
-	vector = irq_vector[irq];
-	cpus_and(mask, irq_domain[irq], cpu_online_map);
+	vector = cfg->vector;
+	cpus_and(mask, cfg->domain, cpu_online_map);
 	for_each_cpu_mask(cpu, mask)
 		per_cpu(vector_irq, cpu)[vector] = -1;
 
-	irq_vector[irq] = 0;
-	irq_domain[irq] = CPU_MASK_NONE;
+	cfg->vector = 0;
+	cfg->domain = CPU_MASK_NONE;
 }
 
 void __setup_vector_irq(int cpu)
@@ -779,10 +754,10 @@
 	int irq, vector;
 
 	/* Mark the inuse vectors */
-	for (irq = 0; irq < NR_IRQ_VECTORS; ++irq) {
-		if (!cpu_isset(cpu, irq_domain[irq]))
+	for (irq = 0; irq < NR_IRQS; ++irq) {
+		if (!cpu_isset(cpu, irq_cfg[irq].domain))
 			continue;
-		vector = irq_vector[irq];
+		vector = irq_cfg[irq].vector;
 		per_cpu(vector_irq, cpu)[vector] = irq;
 	}
 	/* Mark the free vectors */
@@ -790,38 +765,46 @@
 		irq = per_cpu(vector_irq, cpu)[vector];
 		if (irq < 0)
 			continue;
-		if (!cpu_isset(cpu, irq_domain[irq]))
+		if (!cpu_isset(cpu, irq_cfg[irq].domain))
 			per_cpu(vector_irq, cpu)[vector] = -1;
 	}
 }
 
 
-extern void (*interrupt[NR_IRQS])(void);
-
 static struct irq_chip ioapic_chip;
 
-#define IOAPIC_AUTO	-1
-#define IOAPIC_EDGE	0
-#define IOAPIC_LEVEL	1
-
-static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
+static void ioapic_register_intr(int irq, unsigned long trigger)
 {
-	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-			trigger == IOAPIC_LEVEL)
+	if (trigger)
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
 					      handle_fasteoi_irq, "fasteoi");
-	else {
-		irq_desc[irq].status |= IRQ_DELAYED_DISABLE;
+	else
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
 					      handle_edge_irq, "edge");
-	}
 }
-static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
+
+static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
+			      int trigger, int polarity)
 {
+	struct irq_cfg *cfg = irq_cfg + irq;
 	struct IO_APIC_route_entry entry;
-	int vector;
+	cpumask_t mask;
 	unsigned long flags;
 
+	if (!IO_APIC_IRQ(irq))
+		return;
+
+	mask = TARGET_CPUS;
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cpus_and(mask, cfg->domain, mask);
+
+	apic_printk(APIC_VERBOSE,KERN_DEBUG
+		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
+		    "IRQ %d Mode:%i Active:%i)\n",
+		    apic, mp_ioapics[apic].mpc_apicid, pin, cfg->vector,
+		    irq, trigger, polarity);
 
 	/*
 	 * add it to the IO-APIC irq-routing table:
@@ -830,41 +813,27 @@
 
 	entry.delivery_mode = INT_DELIVERY_MODE;
 	entry.dest_mode = INT_DEST_MODE;
+	entry.dest = cpu_mask_to_apicid(mask);
 	entry.mask = 0;				/* enable IRQ */
-	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+	entry.trigger = trigger;
+	entry.polarity = polarity;
+	entry.vector = cfg->vector;
 
-	entry.trigger = irq_trigger(idx);
-	entry.polarity = irq_polarity(idx);
-
-	if (irq_trigger(idx)) {
-		entry.trigger = 1;
+	/* Mask level triggered irqs.
+	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+	 */
+	if (trigger)
 		entry.mask = 1;
-		entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
-	}
 
-	if (!apic && !IO_APIC_IRQ(irq))
-		return;
-
-	if (IO_APIC_IRQ(irq)) {
-		cpumask_t mask;
-		vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
-		if (vector < 0)
-			return;
-
-		entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
-		entry.vector = vector;
-
-		ioapic_register_intr(irq, vector, IOAPIC_AUTO);
-		if (!apic && (irq < 16))
-			disable_8259A_irq(irq);
-	}
+	ioapic_register_intr(irq, trigger);
+	if (irq < 16)
+		disable_8259A_irq(irq);
 
 	ioapic_write_entry(apic, pin, entry);
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	set_native_irq_info(irq, TARGET_CPUS);
+	irq_desc[irq].affinity = TARGET_CPUS;
 	spin_unlock_irqrestore(&ioapic_lock, flags);
-
 }
 
 static void __init setup_IO_APIC_irqs(void)
@@ -889,8 +858,8 @@
 		irq = pin_2_irq(idx, apic, pin);
 		add_pin_to_irq(irq, apic, pin);
 
-		setup_IO_APIC_irq(apic, pin, idx, irq);
-
+		setup_IO_APIC_irq(apic, pin, irq,
+				  irq_trigger(idx), irq_polarity(idx));
 	}
 	}
 
@@ -920,7 +889,7 @@
 	 */
 	entry.dest_mode = INT_DEST_MODE;
 	entry.mask = 0;					/* unmask IRQ now */
-	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
 	entry.delivery_mode = INT_DELIVERY_MODE;
 	entry.polarity = 0;
 	entry.trigger = 0;
@@ -1020,18 +989,17 @@
 
 	printk(KERN_DEBUG ".... IRQ redirection table:\n");
 
-	printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
-			  " Stat Dest Deli Vect:   \n");
+	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
+			  " Stat Dmod Deli Vect:   \n");
 
 	for (i = 0; i <= reg_01.bits.entries; i++) {
 		struct IO_APIC_route_entry entry;
 
 		entry = ioapic_read_entry(apic, i);
 
-		printk(KERN_DEBUG " %02x %03X %02X  ",
+		printk(KERN_DEBUG " %02x %03X ",
 			i,
-			entry.dest.logical.logical_dest,
-			entry.dest.physical.physical_dest
+			entry.dest
 		);
 
 		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
@@ -1293,8 +1261,7 @@
 		entry.dest_mode       = 0; /* Physical */
 		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
 		entry.vector          = 0;
-		entry.dest.physical.physical_dest =
-					GET_APIC_ID(apic_read(APIC_ID));
+		entry.dest          = GET_APIC_ID(apic_read(APIC_ID));
 
 		/*
 		 * Add it to the IO-APIC irq-routing table:
@@ -1377,16 +1344,15 @@
 
 static int ioapic_retrigger_irq(unsigned int irq)
 {
+	struct irq_cfg *cfg = &irq_cfg[irq];
 	cpumask_t mask;
-	unsigned vector;
 	unsigned long flags;
 
 	spin_lock_irqsave(&vector_lock, flags);
-	vector = irq_vector[irq];
 	cpus_clear(mask);
-	cpu_set(first_cpu(irq_domain[irq]), mask);
+	cpu_set(first_cpu(cfg->domain), mask);
 
-	send_IPI_mask(mask, vector);
+	send_IPI_mask(mask, cfg->vector);
 	spin_unlock_irqrestore(&vector_lock, flags);
 
 	return 1;
@@ -1401,8 +1367,68 @@
  * races.
  */
 
+#ifdef CONFIG_SMP
+asmlinkage void smp_irq_move_cleanup_interrupt(void)
+{
+	unsigned vector, me;
+	ack_APIC_irq();
+	exit_idle();
+	irq_enter();
+
+	me = smp_processor_id();
+	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
+		unsigned int irq;
+		struct irq_desc *desc;
+		struct irq_cfg *cfg;
+		irq = __get_cpu_var(vector_irq)[vector];
+		if (irq >= NR_IRQS)
+			continue;
+
+		desc = irq_desc + irq;
+		cfg = irq_cfg + irq;
+		spin_lock(&desc->lock);
+		if (!cfg->move_cleanup_count)
+			goto unlock;
+
+		if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
+			goto unlock;
+
+		__get_cpu_var(vector_irq)[vector] = -1;
+		cfg->move_cleanup_count--;
+unlock:
+		spin_unlock(&desc->lock);
+	}
+
+	irq_exit();
+}
+
+static void irq_complete_move(unsigned int irq)
+{
+	struct irq_cfg *cfg = irq_cfg + irq;
+	unsigned vector, me;
+
+	if (likely(!cfg->move_in_progress))
+		return;
+
+	vector = ~get_irq_regs()->orig_rax;
+	me = smp_processor_id();
+	if ((vector == cfg->vector) &&
+	    cpu_isset(smp_processor_id(), cfg->domain)) {
+		cpumask_t cleanup_mask;
+
+		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+		cfg->move_in_progress = 0;
+	}
+}
+#else
+static inline void irq_complete_move(unsigned int irq) {}
+#endif
+
 static void ack_apic_edge(unsigned int irq)
 {
+	irq_complete_move(irq);
 	move_native_irq(irq);
 	ack_APIC_irq();
 }
@@ -1411,6 +1437,7 @@
 {
 	int do_unmask_irq = 0;
 
+	irq_complete_move(irq);
 #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
 	/* If we are moving the irq we need to mask it */
 	if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
@@ -1461,7 +1488,7 @@
 	 */
 	for (irq = 0; irq < NR_IRQS ; irq++) {
 		int tmp = irq;
-		if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
+		if (IO_APIC_IRQ(tmp) && !irq_cfg[tmp].vector) {
 			/*
 			 * Hmm.. We don't have an entry for this,
 			 * so default to an old-fashioned 8259
@@ -1556,7 +1583,7 @@
 
 	entry1.dest_mode = 0;			/* physical delivery */
 	entry1.mask = 0;			/* unmask IRQ now */
-	entry1.dest.physical.physical_dest = hard_smp_processor_id();
+	entry1.dest = hard_smp_processor_id();
 	entry1.delivery_mode = dest_ExtINT;
 	entry1.polarity = entry0.polarity;
 	entry1.trigger = 0;
@@ -1600,15 +1627,14 @@
  */
 static inline void check_timer(void)
 {
+	struct irq_cfg *cfg = irq_cfg + 0;
 	int apic1, pin1, apic2, pin2;
-	int vector;
-	cpumask_t mask;
 
 	/*
 	 * get/set the timer IRQ vector:
 	 */
 	disable_8259A_irq(0);
-	vector = assign_irq_vector(0, TARGET_CPUS, &mask);
+	assign_irq_vector(0, TARGET_CPUS);
 
 	/*
 	 * Subtle, code in do_timer_interrupt() expects an AEOI
@@ -1628,7 +1654,7 @@
 	apic2 = ioapic_i8259.apic;
 
 	apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
-		vector, apic1, pin1, apic2, pin2);
+		cfg->vector, apic1, pin1, apic2, pin2);
 
 	if (pin1 != -1) {
 		/*
@@ -1659,7 +1685,7 @@
 		/*
 		 * legacy devices should be connected to IO APIC #0
 		 */
-		setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
+		setup_ExtINT_IRQ0_pin(apic2, pin2, cfg->vector);
 		if (timer_irq_works()) {
 			apic_printk(APIC_VERBOSE," works.\n");
 			nmi_watchdog_default();
@@ -1684,14 +1710,14 @@
 
 	disable_8259A_irq(0);
 	irq_desc[0].chip = &lapic_irq_type;
-	apic_write(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
+	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
 	enable_8259A_irq(0);
 
 	if (timer_irq_works()) {
 		apic_printk(APIC_VERBOSE," works.\n");
 		return;
 	}
-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
+	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
 	apic_printk(APIC_VERBOSE," failed.\n");
 
 	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
@@ -1838,19 +1864,16 @@
 	/* Allocate an unused irq */
 	int irq;
 	int new;
-	int vector = 0;
 	unsigned long flags;
-	cpumask_t mask;
 
 	irq = -ENOSPC;
 	spin_lock_irqsave(&vector_lock, flags);
 	for (new = (NR_IRQS - 1); new >= 0; new--) {
 		if (platform_legacy_irq(new))
 			continue;
-		if (irq_vector[new] != 0)
+		if (irq_cfg[new].vector != 0)
 			continue;
-		vector = __assign_irq_vector(new, TARGET_CPUS, &mask);
-		if (likely(vector > 0))
+		if (__assign_irq_vector(new, TARGET_CPUS) == 0)
 			irq = new;
 		break;
 	}
@@ -1879,12 +1902,15 @@
 #ifdef CONFIG_PCI_MSI
 static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
 {
-	int vector;
+	struct irq_cfg *cfg = irq_cfg + irq;
+	int err;
 	unsigned dest;
 	cpumask_t tmp;
 
-	vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
-	if (vector >= 0) {
+	tmp = TARGET_CPUS;
+	err = assign_irq_vector(irq, tmp);
+	if (!err) {
+		cpus_and(tmp, cfg->domain, tmp);
 		dest = cpu_mask_to_apicid(tmp);
 
 		msg->address_hi = MSI_ADDR_BASE_HI;
@@ -1904,40 +1930,38 @@
 			((INT_DELIVERY_MODE != dest_LowestPrio) ?
 				MSI_DATA_DELIVERY_FIXED:
 				MSI_DATA_DELIVERY_LOWPRI) |
-			MSI_DATA_VECTOR(vector);
+			MSI_DATA_VECTOR(cfg->vector);
 	}
-	return vector;
+	return err;
 }
 
 #ifdef CONFIG_SMP
 static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
 {
+	struct irq_cfg *cfg = irq_cfg + irq;
 	struct msi_msg msg;
 	unsigned int dest;
 	cpumask_t tmp;
-	int vector;
 
 	cpus_and(tmp, mask, cpu_online_map);
 	if (cpus_empty(tmp))
-		tmp = TARGET_CPUS;
-
-	cpus_and(mask, tmp, CPU_MASK_ALL);
-
-	vector = assign_irq_vector(irq, mask, &tmp);
-	if (vector < 0)
 		return;
 
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cpus_and(tmp, cfg->domain, mask);
 	dest = cpu_mask_to_apicid(tmp);
 
 	read_msi_msg(irq, &msg);
 
 	msg.data &= ~MSI_DATA_VECTOR_MASK;
-	msg.data |= MSI_DATA_VECTOR(vector);
+	msg.data |= MSI_DATA_VECTOR(cfg->vector);
 	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
 	write_msi_msg(irq, &msg);
-	set_native_irq_info(irq, mask);
+	irq_desc[irq].affinity = mask;
 }
 #endif /* CONFIG_SMP */
 
@@ -2008,24 +2032,22 @@
 
 static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
 {
+	struct irq_cfg *cfg = irq_cfg + irq;
 	unsigned int dest;
 	cpumask_t tmp;
-	int vector;
 
 	cpus_and(tmp, mask, cpu_online_map);
 	if (cpus_empty(tmp))
-		tmp = TARGET_CPUS;
-
-	cpus_and(mask, tmp, CPU_MASK_ALL);
-
-	vector = assign_irq_vector(irq, mask, &tmp);
-	if (vector < 0)
 		return;
 
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cpus_and(tmp, cfg->domain, mask);
 	dest = cpu_mask_to_apicid(tmp);
 
-	target_ht_irq(irq, dest, vector);
-	set_native_irq_info(irq, mask);
+	target_ht_irq(irq, dest, cfg->vector);
+	irq_desc[irq].affinity = mask;
 }
 #endif
 
@@ -2042,14 +2064,17 @@
 
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 {
-	int vector;
+	struct irq_cfg *cfg = irq_cfg + irq;
+	int err;
 	cpumask_t tmp;
 
-	vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
-	if (vector >= 0) {
+	tmp = TARGET_CPUS;
+	err = assign_irq_vector(irq, tmp);
+	if (!err) {
 		struct ht_irq_msg msg;
 		unsigned dest;
 
+		cpus_and(tmp, cfg->domain, tmp);
 		dest = cpu_mask_to_apicid(tmp);
 
 		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
@@ -2057,7 +2082,7 @@
 		msg.address_lo =
 			HT_IRQ_LOW_BASE |
 			HT_IRQ_LOW_DEST_ID(dest) |
-			HT_IRQ_LOW_VECTOR(vector) |
+			HT_IRQ_LOW_VECTOR(cfg->vector) |
 			((INT_DEST_MODE == 0) ?
 				HT_IRQ_LOW_DM_PHYSICAL :
 				HT_IRQ_LOW_DM_LOGICAL) |
@@ -2072,7 +2097,7 @@
 		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
 					      handle_edge_irq, "edge");
 	}
-	return vector;
+	return err;
 }
 #endif /* CONFIG_HT_IRQ */
 
@@ -2099,11 +2124,6 @@
 
 int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
 {
-	struct IO_APIC_route_entry entry;
-	unsigned long flags;
-	int vector;
-	cpumask_t mask;
-
 	if (!IO_APIC_IRQ(irq)) {
 		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
 			ioapic);
@@ -2116,42 +2136,7 @@
 	if (irq >= 16)
 		add_pin_to_irq(irq, ioapic, pin);
 
-
-	vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
-	if (vector < 0)
-		return vector;
-
-	/*
-	 * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
-	 * Note that we mask (disable) IRQs now -- these get enabled when the
-	 * corresponding device driver registers for this IRQ.
-	 */
-
-	memset(&entry,0,sizeof(entry));
-
-	entry.delivery_mode = INT_DELIVERY_MODE;
-	entry.dest_mode = INT_DEST_MODE;
-	entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
-	entry.trigger = triggering;
-	entry.polarity = polarity;
-	entry.mask = 1;					 /* Disabled (masked) */
-	entry.vector = vector & 0xff;
-
-	apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
-		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
-	       mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
-	       triggering, polarity);
-
-	ioapic_register_intr(irq, entry.vector, triggering);
-
-	if (!ioapic && (irq < 16))
-		disable_8259A_irq(irq);
-
-	ioapic_write_entry(ioapic, pin, entry);
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	set_native_irq_info(irq, TARGET_CPUS);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity);
 
 	return 0;
 }
@@ -2183,8 +2168,10 @@
 			 * when you have too many devices, because at that time only boot
 			 * cpu is online.
 			 */
-			if(!irq_vector[irq])
-				setup_IO_APIC_irq(ioapic, pin, irq_entry, irq);
+			if (!irq_cfg[irq].vector)
+				setup_IO_APIC_irq(ioapic, pin, irq,
+						  irq_trigger(irq_entry),
+						  irq_polarity(irq_entry));
 			else
 				set_ioapic_affinity_irq(irq, TARGET_CPUS);
 		}
diff --git a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c
index fe063d3..745b1f0 100644
--- a/arch/x86_64/kernel/ioport.c
+++ b/arch/x86_64/kernel/ioport.c
@@ -114,6 +114,6 @@
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 	}
-	regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12);
+	regs->eflags = (regs->eflags &~ X86_EFLAGS_IOPL) | (level << 12);
 	return 0;
 }
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 0c06af6..3bc30d2 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -18,6 +18,7 @@
 #include <asm/uaccess.h>
 #include <asm/io_apic.h>
 #include <asm/idle.h>
+#include <asm/smp.h>
 
 atomic_t irq_err_count;
 
@@ -120,9 +121,14 @@
 
 	if (likely(irq < NR_IRQS))
 		generic_handle_irq(irq);
-	else if (printk_ratelimit())
-		printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n",
-			__func__, smp_processor_id(), vector);
+	else {
+		if (!disable_apic)
+			ack_APIC_irq();
+
+		if (printk_ratelimit())
+			printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n",
+				__func__, smp_processor_id(), vector);
+	}
 
 	irq_exit();
 
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index ac08503..8011a8e 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -19,6 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/percpu.h>
 #include <linux/ctype.h>
+#include <linux/kmod.h>
 #include <asm/processor.h> 
 #include <asm/msr.h>
 #include <asm/mce.h>
@@ -42,6 +43,10 @@
 static int notify_user;
 static int rip_msr;
 static int mce_bootlog = 1;
+static atomic_t mce_events;
+
+static char trigger[128];
+static char *trigger_argv[2] = { trigger, NULL };
 
 /*
  * Lockless MCE logging infrastructure.
@@ -57,6 +62,7 @@
 void mce_log(struct mce *mce)
 {
 	unsigned next, entry;
+	atomic_inc(&mce_events);
 	mce->finished = 0;
 	wmb();
 	for (;;) {
@@ -161,6 +167,17 @@
 	}
 }
 
+static void do_mce_trigger(void)
+{
+	static atomic_t mce_logged;
+	int events = atomic_read(&mce_events);
+	if (events != atomic_read(&mce_logged) && trigger[0]) {
+		/* Small race window, but should be harmless.  */
+		atomic_set(&mce_logged, events);
+		call_usermodehelper(trigger, trigger_argv, NULL, -1);
+	}
+}
+
 /* 
  * The actual machine check handler
  */
@@ -234,8 +251,12 @@
 	}
 
 	/* Never do anything final in the polling timer */
-	if (!regs)
+	if (!regs) {
+		/* Normal interrupt context here. Call trigger for any new
+		   events. */
+		do_mce_trigger();
 		goto out;
+	}
 
 	/* If we didn't find an uncorrectable error, pick
 	   the last one (shouldn't happen, just being safe). */
@@ -516,7 +537,7 @@
 	} 
 }
 
-static struct file_operations mce_chrdev_ops = {
+static const struct file_operations mce_chrdev_ops = {
 	.read = mce_read,
 	.ioctl = mce_ioctl,
 };
@@ -606,17 +627,42 @@
 	}									   \
 	static SYSDEV_ATTR(name, 0644, show_ ## name, set_ ## name);
 
+/* TBD should generate these dynamically based on number of available banks */
 ACCESSOR(bank0ctl,bank[0],mce_restart())
 ACCESSOR(bank1ctl,bank[1],mce_restart())
 ACCESSOR(bank2ctl,bank[2],mce_restart())
 ACCESSOR(bank3ctl,bank[3],mce_restart())
 ACCESSOR(bank4ctl,bank[4],mce_restart())
 ACCESSOR(bank5ctl,bank[5],mce_restart())
-static struct sysdev_attribute * bank_attributes[NR_BANKS] = {
-	&attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl,
-	&attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl};
+
+static ssize_t show_trigger(struct sys_device *s, char *buf)
+{
+	strcpy(buf, trigger);
+	strcat(buf, "\n");
+	return strlen(trigger) + 1;
+}
+
+static ssize_t set_trigger(struct sys_device *s,const char *buf,size_t siz)
+{
+	char *p;
+	int len;
+	strncpy(trigger, buf, sizeof(trigger));
+	trigger[sizeof(trigger)-1] = 0;
+	len = strlen(trigger);
+	p = strchr(trigger, '\n');
+	if (*p) *p = 0;
+	return len;
+}
+
+static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger);
 ACCESSOR(tolerant,tolerant,)
 ACCESSOR(check_interval,check_interval,mce_restart())
+static struct sysdev_attribute *mce_attributes[] = {
+	&attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl,
+	&attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl,
+	&attr_tolerant, &attr_check_interval, &attr_trigger,
+	NULL
+};
 
 /* Per cpu sysdev init.  All of the cpus still share the same ctl bank */
 static __cpuinit int mce_create_device(unsigned int cpu)
@@ -632,11 +678,9 @@
 	err = sysdev_register(&per_cpu(device_mce,cpu));
 
 	if (!err) {
-		for (i = 0; i < banks; i++)
+		for (i = 0; mce_attributes[i]; i++)
 			sysdev_create_file(&per_cpu(device_mce,cpu),
-				bank_attributes[i]);
-		sysdev_create_file(&per_cpu(device_mce,cpu), &attr_tolerant);
-		sysdev_create_file(&per_cpu(device_mce,cpu), &attr_check_interval);
+				mce_attributes[i]);
 	}
 	return err;
 }
@@ -645,11 +689,9 @@
 {
 	int i;
 
-	for (i = 0; i < banks; i++)
+	for (i = 0; mce_attributes[i]; i++)
 		sysdev_remove_file(&per_cpu(device_mce,cpu),
-			bank_attributes[i]);
-	sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_tolerant);
-	sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval);
+			mce_attributes[i]);
 	sysdev_unregister(&per_cpu(device_mce,cpu));
 	memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject));
 }
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index fa09deb..d0bd5d6 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -37,6 +37,8 @@
 #define THRESHOLD_MAX     0xFFF
 #define INT_TYPE_APIC     0x00020000
 #define MASK_VALID_HI     0x80000000
+#define MASK_CNTP_HI      0x40000000
+#define MASK_LOCKED_HI    0x20000000
 #define MASK_LVTOFF_HI    0x00F00000
 #define MASK_COUNT_EN_HI  0x00080000
 #define MASK_INT_TYPE_HI  0x00060000
@@ -122,14 +124,17 @@
 		for (block = 0; block < NR_BLOCKS; ++block) {
 			if (block == 0)
 				address = MSR_IA32_MC0_MISC + bank * 4;
-			else if (block == 1)
-				address = MCG_XBLK_ADDR
-					+ ((low & MASK_BLKPTR_LO) >> 21);
+			else if (block == 1) {
+				address = (low & MASK_BLKPTR_LO) >> 21;
+				if (!address)
+					break;
+				address += MCG_XBLK_ADDR;
+			}
 			else
 				++address;
 
 			if (rdmsr_safe(address, &low, &high))
-				continue;
+				break;
 
 			if (!(high & MASK_VALID_HI)) {
 				if (block)
@@ -138,8 +143,8 @@
 					break;
 			}
 
-			if (!(high & MASK_VALID_HI >> 1)  ||
-			     (high & MASK_VALID_HI >> 2))
+			if (!(high & MASK_CNTP_HI)  ||
+			     (high & MASK_LOCKED_HI))
 				continue;
 
 			if (!block)
@@ -187,17 +192,22 @@
 
 	/* assume first bank caused it */
 	for (bank = 0; bank < NR_BANKS; ++bank) {
+		if (!(per_cpu(bank_map, m.cpu) & (1 << bank)))
+			continue;
 		for (block = 0; block < NR_BLOCKS; ++block) {
 			if (block == 0)
 				address = MSR_IA32_MC0_MISC + bank * 4;
-			else if (block == 1)
-				address = MCG_XBLK_ADDR
-					+ ((low & MASK_BLKPTR_LO) >> 21);
+			else if (block == 1) {
+				address = (low & MASK_BLKPTR_LO) >> 21;
+				if (!address)
+					break;
+				address += MCG_XBLK_ADDR;
+			}
 			else
 				++address;
 
 			if (rdmsr_safe(address, &low, &high))
-				continue;
+				break;
 
 			if (!(high & MASK_VALID_HI)) {
 				if (block)
@@ -206,10 +216,14 @@
 					break;
 			}
 
-			if (!(high & MASK_VALID_HI >> 1)  ||
-			     (high & MASK_VALID_HI >> 2))
+			if (!(high & MASK_CNTP_HI)  ||
+			     (high & MASK_LOCKED_HI))
 				continue;
 
+			/* Log the machine check that caused the threshold
+			   event. */
+			do_machine_check(NULL, 0);
+
 			if (high & MASK_OVERFLOW_HI) {
 				rdmsrl(address, m.misc);
 				rdmsrl(MSR_IA32_MC0_STATUS + bank * 4,
@@ -385,7 +399,7 @@
 		return 0;
 
 	if (rdmsr_safe(address, &low, &high))
-		goto recurse;
+		return 0;
 
 	if (!(high & MASK_VALID_HI)) {
 		if (block)
@@ -394,14 +408,13 @@
 			return 0;
 	}
 
-	if (!(high & MASK_VALID_HI >> 1)  ||
-	     (high & MASK_VALID_HI >> 2))
+	if (!(high & MASK_CNTP_HI)  ||
+	     (high & MASK_LOCKED_HI))
 		goto recurse;
 
 	b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL);
 	if (!b)
 		return -ENOMEM;
-	memset(b, 0, sizeof(struct threshold_block));
 
 	b->block = block;
 	b->bank = bank;
@@ -490,7 +503,6 @@
 		err = -ENOMEM;
 		goto out;
 	}
-	memset(b, 0, sizeof(struct threshold_bank));
 
 	kobject_set_name(&b->kobj, "threshold_bank%i", bank);
 	b->kobj.parent = &per_cpu(device_mce, cpu).kobj;
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 9cb42ec..486f4c6 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -172,7 +172,7 @@
 {
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
-		return boot_cpu_data.x86 == 15;
+		return boot_cpu_data.x86 == 15 || boot_cpu_data.x86 == 16;
 	case X86_VENDOR_INTEL:
 		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
 			return 1;
@@ -214,6 +214,23 @@
 }
 #endif
 
+static unsigned int adjust_for_32bit_ctr(unsigned int hz)
+{
+	unsigned int retval = hz;
+
+	/*
+	 * On Intel CPUs with ARCH_PERFMON only 32 bits in the counter
+	 * are writable, with higher bits sign extending from bit 31.
+	 * So, we can only program the counter with 31 bit values and
+	 * 32nd bit should be 1, for 33.. to be 1.
+	 * Find the appropriate nmi_hz
+	 */
+ 	if ((((u64)cpu_khz * 1000) / retval) > 0x7fffffffULL) {
+		retval = ((u64)cpu_khz * 1000) / 0x7fffffffUL + 1;
+	}
+	return retval;
+}
+
 int __init check_nmi_watchdog (void)
 {
 	int *counts;
@@ -268,17 +285,8 @@
 		struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
 		nmi_hz = 1;
-		/*
-		 * On Intel CPUs with ARCH_PERFMON only 32 bits in the counter
-		 * are writable, with higher bits sign extending from bit 31.
-		 * So, we can only program the counter with 31 bit values and
-		 * 32nd bit should be 1, for 33.. to be 1.
-		 * Find the appropriate nmi_hz
-		 */
-	 	if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0 &&
-			((u64)cpu_khz * 1000) > 0x7fffffffULL) {
-			nmi_hz = ((u64)cpu_khz * 1000) / 0x7fffffffUL + 1;
-		}
+	 	if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0)
+			nmi_hz = adjust_for_32bit_ctr(nmi_hz);
 	}
 
 	kfree(counts);
@@ -360,6 +368,33 @@
 	}
 }
 
+static void __acpi_nmi_disable(void *__unused)
+{
+	apic_write(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
+}
+
+/*
+ * Disable timer based NMIs on all CPUs:
+ */
+void acpi_nmi_disable(void)
+{
+	if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
+		on_each_cpu(__acpi_nmi_disable, NULL, 0, 1);
+}
+
+static void __acpi_nmi_enable(void *__unused)
+{
+	apic_write(APIC_LVT0, APIC_DM_NMI);
+}
+
+/*
+ * Enable timer based NMIs on all CPUs:
+ */
+void acpi_nmi_enable(void)
+{
+	if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
+		on_each_cpu(__acpi_nmi_enable, NULL, 0, 1);
+}
 #ifdef CONFIG_PM
 
 static int nmi_pm_active; /* nmi_active before suspend */
@@ -634,7 +669,9 @@
 
 	/* setup the timer */
 	wrmsr(evntsel_msr, evntsel, 0);
-	wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
+
+	nmi_hz = adjust_for_32bit_ctr(nmi_hz);
+	wrmsr(perfctr_msr, (u32)(-((u64)cpu_khz * 1000 / nmi_hz)), 0);
 
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
@@ -855,15 +892,23 @@
 				dummy &= ~P4_CCCR_OVF;
 	 			wrmsrl(wd->cccr_msr, dummy);
 	 			apic_write(APIC_LVTPC, APIC_DM_NMI);
+				/* start the cycle over again */
+				wrmsrl(wd->perfctr_msr,
+				       -((u64)cpu_khz * 1000 / nmi_hz));
 	 		} else if (wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
 				/*
 				 * ArchPerfom/Core Duo needs to re-unmask
 				 * the apic vector
 				 */
 				apic_write(APIC_LVTPC, APIC_DM_NMI);
+				/* ARCH_PERFMON has 32 bit counter writes */
+				wrmsr(wd->perfctr_msr,
+				     (u32)(-((u64)cpu_khz * 1000 / nmi_hz)), 0);
+			} else {
+				/* start the cycle over again */
+				wrmsrl(wd->perfctr_msr,
+				       -((u64)cpu_khz * 1000 / nmi_hz));
 			}
-			/* start the cycle over again */
-			wrmsrl(wd->perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
 			rc = 1;
 		} else 	if (nmi_watchdog == NMI_IO_APIC) {
 			/* don't know how to accurately check for this.
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index 3d65b1d..04480c3 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -138,6 +138,8 @@
 
 #define PHB_DEBUG_STUFF_OFFSET	0x0020
 
+#define EMERGENCY_PAGES 32 /* = 128KB */
+
 unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
 static int translate_empty_slots __read_mostly = 0;
 static int calgary_detected __read_mostly = 0;
@@ -296,6 +298,16 @@
 {
 	unsigned long entry;
 	unsigned long badbit;
+	unsigned long badend;
+
+	/* were we called with bad_dma_address? */
+	badend = bad_dma_address + (EMERGENCY_PAGES * PAGE_SIZE);
+	if (unlikely((dma_addr >= bad_dma_address) && (dma_addr < badend))) {
+		printk(KERN_ERR "Calgary: driver tried unmapping bad DMA "
+		       "address 0x%Lx\n", dma_addr);
+		WARN_ON(1);
+		return;
+	}
 
 	entry = dma_addr >> PAGE_SHIFT;
 
@@ -656,8 +668,8 @@
 	u64 start;
 	struct iommu_table *tbl = dev->sysdata;
 
-	/* reserve bad_dma_address in case it's a legal address */
-	iommu_range_reserve(tbl, bad_dma_address, 1);
+	/* reserve EMERGENCY_PAGES from bad_dma_address and up */
+	iommu_range_reserve(tbl, bad_dma_address, EMERGENCY_PAGES);
 
 	/* avoid the BIOS/VGA first 640KB-1MB region */
 	start = (640 * 1024);
@@ -1176,6 +1188,7 @@
 	}
 
 	force_iommu = 1;
+	bad_dma_address = 0x0;
 	dma_ops = &calgary_dma_ops;
 
 	return 0;
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index 683b7a5..651ccfb 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -223,30 +223,10 @@
 }
 EXPORT_SYMBOL(dma_set_mask);
 
-/* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
-         [,forcesac][,fullflush][,nomerge][,biomerge]
-   size  set size of iommu (in bytes)
-   noagp don't initialize the AGP driver and use full aperture.
-   off   don't use the IOMMU
-   leak  turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on)
-   memaper[=order] allocate an own aperture over RAM with size 32MB^order.
-   noforce don't force IOMMU usage. Default.
-   force  Force IOMMU.
-   merge  Do lazy merging. This may improve performance on some block devices.
-          Implies force (experimental)
-   biomerge Do merging at the BIO layer. This is more efficient than merge,
-            but should be only done with very big IOMMUs. Implies merge,force.
-   nomerge Don't do SG merging.
-   forcesac For SAC mode for masks <40bits  (experimental)
-   fullflush Flush IOMMU on each allocation (default)
-   nofullflush Don't use IOMMU fullflush
-   allowed  overwrite iommu off workarounds for specific chipsets.
-   soft	 Use software bounce buffering (default for Intel machines)
-   noaperture Don't touch the aperture for AGP.
-   allowdac Allow DMA >4GB
-   nodac    Forbid DMA >4GB
-   panic    Force panic when IOMMU overflows
-*/
+/*
+ * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
+ * documentation.
+ */
 __init int iommu_setup(char *p)
 {
 	iommu_merge = 1;
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index fc1960f..030eb37 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -185,7 +185,7 @@
 static inline int need_iommu(struct device *dev, unsigned long addr, size_t size)
 { 
 	u64 mask = *dev->dma_mask;
-	int high = addr + size >= mask;
+	int high = addr + size > mask;
 	int mmu = high;
 	if (force_iommu) 
 		mmu = 1; 
@@ -195,7 +195,7 @@
 static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
 { 
 	u64 mask = *dev->dma_mask;
-	int high = addr + size >= mask;
+	int high = addr + size > mask;
 	int mmu = high;
 	return mmu; 
 }
diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c
index 7554458..ae8f912 100644
--- a/arch/x86_64/kernel/pmtimer.c
+++ b/arch/x86_64/kernel/pmtimer.c
@@ -24,15 +24,6 @@
 #include <asm/msr.h>
 #include <asm/vsyscall.h>
 
-/* The I/O port the PMTMR resides at.
- * The location is detected during setup_arch(),
- * in arch/i386/kernel/acpi/boot.c */
-u32 pmtmr_ioport __read_mostly;
-
-/* value of the Power timer at last timer interrupt */
-static u32 offset_delay;
-static u32 last_pmtmr_tick;
-
 #define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
 
 static inline u32 cyc2us(u32 cycles)
@@ -48,38 +39,6 @@
 	return (cycles >> 10);
 }
 
-int pmtimer_mark_offset(void)
-{
-	static int first_run = 1;
-	unsigned long tsc;
-	u32 lost;
-
-	u32 tick = inl(pmtmr_ioport);
-	u32 delta;
-
-	delta = cyc2us((tick - last_pmtmr_tick) & ACPI_PM_MASK);
-
-	last_pmtmr_tick = tick;
-	monotonic_base += delta * NSEC_PER_USEC;
-
-	delta += offset_delay;
-
-	lost = delta / (USEC_PER_SEC / HZ);
-	offset_delay = delta % (USEC_PER_SEC / HZ);
-
-	rdtscll(tsc);
-	vxtime.last_tsc = tsc - offset_delay * (u64)cpu_khz / 1000;
-
-	/* don't calculate delay for first run,
-	   or if we've got less then a tick */
-	if (first_run || (lost < 1)) {
-		first_run = 0;
-		offset_delay = 0;
-	}
-
-	return lost - 1;
-}
-
 static unsigned pmtimer_wait_tick(void)
 {
 	u32 a, b;
@@ -101,23 +60,6 @@
 	} while (cyc2us(b - a) < us);
 }
 
-void pmtimer_resume(void)
-{
-	last_pmtmr_tick = inl(pmtmr_ioport);
-}
-
-unsigned int do_gettimeoffset_pm(void)
-{
-	u32 now, offset, delta = 0;
-
-	offset = last_pmtmr_tick;
-	now = inl(pmtmr_ioport);
-	delta = (now - offset) & ACPI_PM_MASK;
-
-	return offset_delay + cyc2us(delta);
-}
-
-
 static int __init nopmtimer_setup(char *s)
 {
 	pmtmr_ioport = 0;
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index addc14a..4326a69 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -536,8 +536,12 @@
 		}
 		ret = 0;
 		for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) {
-			ret |= __get_user(tmp, (unsigned long __user *) data);
-			putreg(child, ui, tmp);
+			ret = __get_user(tmp, (unsigned long __user *) data);
+			if (ret)
+				break;
+			ret = putreg(child, ui, tmp);
+			if (ret)
+				break;
 			data += sizeof(long);
 		}
 		break;
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index af425a8..3d98b69 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -100,7 +100,7 @@
 
 extern int root_mountflags;
 
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
 
 struct resource standard_io_resources[] = {
 	{ .name = "dma1", .start = 0x00, .end = 0x1f,
@@ -138,128 +138,6 @@
 	.flags = IORESOURCE_RAM,
 };
 
-#define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM)
-
-static struct resource system_rom_resource = {
-	.name = "System ROM",
-	.start = 0xf0000,
-	.end = 0xfffff,
-	.flags = IORESOURCE_ROM,
-};
-
-static struct resource extension_rom_resource = {
-	.name = "Extension ROM",
-	.start = 0xe0000,
-	.end = 0xeffff,
-	.flags = IORESOURCE_ROM,
-};
-
-static struct resource adapter_rom_resources[] = {
-	{ .name = "Adapter ROM", .start = 0xc8000, .end = 0,
-		.flags = IORESOURCE_ROM },
-	{ .name = "Adapter ROM", .start = 0, .end = 0,
-		.flags = IORESOURCE_ROM },
-	{ .name = "Adapter ROM", .start = 0, .end = 0,
-		.flags = IORESOURCE_ROM },
-	{ .name = "Adapter ROM", .start = 0, .end = 0,
-		.flags = IORESOURCE_ROM },
-	{ .name = "Adapter ROM", .start = 0, .end = 0,
-		.flags = IORESOURCE_ROM },
-	{ .name = "Adapter ROM", .start = 0, .end = 0,
-		.flags = IORESOURCE_ROM }
-};
-
-static struct resource video_rom_resource = {
-	.name = "Video ROM",
-	.start = 0xc0000,
-	.end = 0xc7fff,
-	.flags = IORESOURCE_ROM,
-};
-
-static struct resource video_ram_resource = {
-	.name = "Video RAM area",
-	.start = 0xa0000,
-	.end = 0xbffff,
-	.flags = IORESOURCE_RAM,
-};
-
-#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
-
-static int __init romchecksum(unsigned char *rom, unsigned long length)
-{
-	unsigned char *p, sum = 0;
-
-	for (p = rom; p < rom + length; p++)
-		sum += *p;
-	return sum == 0;
-}
-
-static void __init probe_roms(void)
-{
-	unsigned long start, length, upper;
-	unsigned char *rom;
-	int	      i;
-
-	/* video rom */
-	upper = adapter_rom_resources[0].start;
-	for (start = video_rom_resource.start; start < upper; start += 2048) {
-		rom = isa_bus_to_virt(start);
-		if (!romsignature(rom))
-			continue;
-
-		video_rom_resource.start = start;
-
-		/* 0 < length <= 0x7f * 512, historically */
-		length = rom[2] * 512;
-
-		/* if checksum okay, trust length byte */
-		if (length && romchecksum(rom, length))
-			video_rom_resource.end = start + length - 1;
-
-		request_resource(&iomem_resource, &video_rom_resource);
-		break;
-			}
-
-	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
-	if (start < upper)
-		start = upper;
-
-	/* system rom */
-	request_resource(&iomem_resource, &system_rom_resource);
-	upper = system_rom_resource.start;
-
-	/* check for extension rom (ignore length byte!) */
-	rom = isa_bus_to_virt(extension_rom_resource.start);
-	if (romsignature(rom)) {
-		length = extension_rom_resource.end - extension_rom_resource.start + 1;
-		if (romchecksum(rom, length)) {
-			request_resource(&iomem_resource, &extension_rom_resource);
-			upper = extension_rom_resource.start;
-		}
-	}
-
-	/* check for adapter roms on 2k boundaries */
-	for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper;
-	     start += 2048) {
-		rom = isa_bus_to_virt(start);
-		if (!romsignature(rom))
-			continue;
-
-		/* 0 < length <= 0x7f * 512, historically */
-		length = rom[2] * 512;
-
-		/* but accept any length that fits if checksum okay */
-		if (!length || start + length > upper || !romchecksum(rom, length))
-			continue;
-
-		adapter_rom_resources[i].start = start;
-		adapter_rom_resources[i].end = start + length - 1;
-		request_resource(&iomem_resource, &adapter_rom_resources[i]);
-
-		start = adapter_rom_resources[i++].end & ~2047UL;
-	}
-}
-
 #ifdef CONFIG_PROC_VMCORE
 /* elfcorehdr= specifies the location of elf core header
  * stored by the crashed kernel. This option will be passed
@@ -343,7 +221,7 @@
 
 void __init setup_arch(char **cmdline_p)
 {
-	printk(KERN_INFO "Command line: %s\n", saved_command_line);
+	printk(KERN_INFO "Command line: %s\n", boot_command_line);
 
  	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
  	screen_info = SCREEN_INFO;
@@ -373,7 +251,7 @@
 
 	early_identify_cpu(&boot_cpu_data);
 
-	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 
 	parse_early_param();
@@ -444,6 +322,11 @@
 	/* reserve ebda region */
 	if (ebda_addr)
 		reserve_bootmem_generic(ebda_addr, ebda_size);
+#ifdef CONFIG_NUMA
+	/* reserve nodemap region */
+	if (nodemap_addr)
+		reserve_bootmem_generic(nodemap_addr, nodemap_size);
+#endif
 
 #ifdef CONFIG_SMP
 	/*
@@ -519,15 +402,11 @@
 	init_apic_mappings();
 
 	/*
-	 * Request address space for all standard RAM and ROM resources
-	 * and also for regions reported as reserved by the e820.
-	 */
-	probe_roms();
+	 * We trust e820 completely. No explicit ROM probing in memory.
+ 	 */
 	e820_reserve_resources(); 
 	e820_mark_nosave_regions();
 
-	request_resource(&iomem_resource, &video_ram_resource);
-
 	{
 	unsigned i;
 	/* request I/O space for devices used on all i[345]86 PCs */
@@ -1063,7 +942,8 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
-		NULL, "fxsr_opt", NULL, "rdtscp", NULL, "lm", "3dnowext", "3dnow",
+		NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm",
+		"3dnowext", "3dnow",
 
 		/* Transmeta-defined */
 		"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -1081,7 +961,7 @@
 		/* Intel-defined (#2) */
 		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
 		"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
-		NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* VIA/Cyrix/Centaur-defined */
@@ -1091,8 +971,10 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* AMD-defined (#2) */
-		"lahf_lm", "cmp_legacy", "svm", NULL, "cr8_legacy", NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		"lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy",
+		"altmovcr8", "abm", "sse4a",
+		"misalignsse", "3dnowprefetch",
+		"osvw", "ibs", NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	};
@@ -1103,6 +985,9 @@
 		"ttp",  /* thermal trip */
 		"tm",
 		"stc",
+		"100mhzsteps",
+		"hwpstate",
+		NULL,	/* tsc invariant mapped to constant_tsc */
 		NULL,
 		/* nothing */	/* constant_tsc - moved to flags */
 	};
@@ -1219,23 +1104,3 @@
 	.stop =	c_stop,
 	.show =	show_cpuinfo,
 };
-
-#if defined(CONFIG_INPUT_PCSPKR) || defined(CONFIG_INPUT_PCSPKR_MODULE)
-#include <linux/platform_device.h>
-static __init int add_pcspkr(void)
-{
-	struct platform_device *pd;
-	int ret;
-
-	pd = platform_device_alloc("pcspkr", -1);
-	if (!pd)
-		return -ENOMEM;
-
-	ret = platform_device_add(pd);
-	if (ret)
-		platform_device_put(pd);
-
-	return ret;
-}
-device_initcall(add_pcspkr);
-#endif
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 8c4b80f..6a70b55 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -37,7 +37,6 @@
 char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
 
 unsigned long __supported_pte_mask __read_mostly = ~0UL;
-EXPORT_SYMBOL(__supported_pte_mask);
 static int do_not_nx __cpuinitdata = 0;
 
 /* noexec=on|off
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index daf1933..3544372 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -148,217 +148,6 @@
 	print_cpu_info(c);
 }
 
-/*
- * New Funky TSC sync algorithm borrowed from IA64.
- * Main advantage is that it doesn't reset the TSCs fully and
- * in general looks more robust and it works better than my earlier
- * attempts. I believe it was written by David Mosberger. Some minor
- * adjustments for x86-64 by me -AK
- *
- * Original comment reproduced below.
- *
- * Synchronize TSC of the current (slave) CPU with the TSC of the
- * MASTER CPU (normally the time-keeper CPU).  We use a closed loop to
- * eliminate the possibility of unaccounted-for errors (such as
- * getting a machine check in the middle of a calibration step).  The
- * basic idea is for the slave to ask the master what itc value it has
- * and to read its own itc before and after the master responds.  Each
- * iteration gives us three timestamps:
- *
- *	slave		master
- *
- *	t0 ---\
- *             ---\
- *		   --->
- *			tm
- *		   /---
- *	       /---
- *	t1 <---
- *
- *
- * The goal is to adjust the slave's TSC such that tm falls exactly
- * half-way between t0 and t1.  If we achieve this, the clocks are
- * synchronized provided the interconnect between the slave and the
- * master is symmetric.  Even if the interconnect were asymmetric, we
- * would still know that the synchronization error is smaller than the
- * roundtrip latency (t0 - t1).
- *
- * When the interconnect is quiet and symmetric, this lets us
- * synchronize the TSC to within one or two cycles.  However, we can
- * only *guarantee* that the synchronization is accurate to within a
- * round-trip time, which is typically in the range of several hundred
- * cycles (e.g., ~500 cycles).  In practice, this means that the TSCs
- * are usually almost perfectly synchronized, but we shouldn't assume
- * that the accuracy is much better than half a micro second or so.
- *
- * [there are other errors like the latency of RDTSC and of the
- * WRMSR. These can also account to hundreds of cycles. So it's
- * probably worse. It claims 153 cycles error on a dual Opteron,
- * but I suspect the numbers are actually somewhat worse -AK]
- */
-
-#define MASTER	0
-#define SLAVE	(SMP_CACHE_BYTES/8)
-
-/* Intentionally don't use cpu_relax() while TSC synchronization
-   because we don't want to go into funky power save modi or cause
-   hypervisors to schedule us away.  Going to sleep would likely affect
-   latency and low latency is the primary objective here. -AK */
-#define no_cpu_relax() barrier()
-
-static __cpuinitdata DEFINE_SPINLOCK(tsc_sync_lock);
-static volatile __cpuinitdata unsigned long go[SLAVE + 1];
-static int notscsync __cpuinitdata;
-
-#undef DEBUG_TSC_SYNC
-
-#define NUM_ROUNDS	64	/* magic value */
-#define NUM_ITERS	5	/* likewise */
-
-/* Callback on boot CPU */
-static __cpuinit void sync_master(void *arg)
-{
-	unsigned long flags, i;
-
-	go[MASTER] = 0;
-
-	local_irq_save(flags);
-	{
-		for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
-			while (!go[MASTER])
-				no_cpu_relax();
-			go[MASTER] = 0;
-			rdtscll(go[SLAVE]);
-		}
-	}
-	local_irq_restore(flags);
-}
-
-/*
- * Return the number of cycles by which our tsc differs from the tsc
- * on the master (time-keeper) CPU.  A positive number indicates our
- * tsc is ahead of the master, negative that it is behind.
- */
-static inline long
-get_delta(long *rt, long *master)
-{
-	unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
-	unsigned long tcenter, t0, t1, tm;
-	int i;
-
-	for (i = 0; i < NUM_ITERS; ++i) {
-		rdtscll(t0);
-		go[MASTER] = 1;
-		while (!(tm = go[SLAVE]))
-			no_cpu_relax();
-		go[SLAVE] = 0;
-		rdtscll(t1);
-
-		if (t1 - t0 < best_t1 - best_t0)
-			best_t0 = t0, best_t1 = t1, best_tm = tm;
-	}
-
-	*rt = best_t1 - best_t0;
-	*master = best_tm - best_t0;
-
-	/* average best_t0 and best_t1 without overflow: */
-	tcenter = (best_t0/2 + best_t1/2);
-	if (best_t0 % 2 + best_t1 % 2 == 2)
-		++tcenter;
-	return tcenter - best_tm;
-}
-
-static __cpuinit void sync_tsc(unsigned int master)
-{
-	int i, done = 0;
-	long delta, adj, adjust_latency = 0;
-	unsigned long flags, rt, master_time_stamp, bound;
-#ifdef DEBUG_TSC_SYNC
-	static struct syncdebug {
-		long rt;	/* roundtrip time */
-		long master;	/* master's timestamp */
-		long diff;	/* difference between midpoint and master's timestamp */
-		long lat;	/* estimate of tsc adjustment latency */
-	} t[NUM_ROUNDS] __cpuinitdata;
-#endif
-
-	printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n",
-		smp_processor_id(), master);
-
-	go[MASTER] = 1;
-
-	/* It is dangerous to broadcast IPI as cpus are coming up,
-	 * as they may not be ready to accept them.  So since
-	 * we only need to send the ipi to the boot cpu direct
-	 * the message, and avoid the race.
-	 */
-	smp_call_function_single(master, sync_master, NULL, 1, 0);
-
-	while (go[MASTER])	/* wait for master to be ready */
-		no_cpu_relax();
-
-	spin_lock_irqsave(&tsc_sync_lock, flags);
-	{
-		for (i = 0; i < NUM_ROUNDS; ++i) {
-			delta = get_delta(&rt, &master_time_stamp);
-			if (delta == 0) {
-				done = 1;	/* let's lock on to this... */
-				bound = rt;
-			}
-
-			if (!done) {
-				unsigned long t;
-				if (i > 0) {
-					adjust_latency += -delta;
-					adj = -delta + adjust_latency/4;
-				} else
-					adj = -delta;
-
-				rdtscll(t);
-				wrmsrl(MSR_IA32_TSC, t + adj);
-			}
-#ifdef DEBUG_TSC_SYNC
-			t[i].rt = rt;
-			t[i].master = master_time_stamp;
-			t[i].diff = delta;
-			t[i].lat = adjust_latency/4;
-#endif
-		}
-	}
-	spin_unlock_irqrestore(&tsc_sync_lock, flags);
-
-#ifdef DEBUG_TSC_SYNC
-	for (i = 0; i < NUM_ROUNDS; ++i)
-		printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
-		       t[i].rt, t[i].master, t[i].diff, t[i].lat);
-#endif
-
-	printk(KERN_INFO
-	       "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, "
-	       "maxerr %lu cycles)\n",
-	       smp_processor_id(), master, delta, rt);
-}
-
-static void __cpuinit tsc_sync_wait(void)
-{
-	/*
-	 * When the CPU has synchronized TSCs assume the BIOS
-  	 * or the hardware already synced.  Otherwise we could
-	 * mess up a possible perfect synchronization with a
-	 * not-quite-perfect algorithm.
-	 */
-	if (notscsync || !cpu_has_tsc || !unsynchronized_tsc())
-		return;
-	sync_tsc(0);
-}
-
-static __init int notscsync_setup(char *s)
-{
-	notscsync = 1;
-	return 1;
-}
-__setup("notscsync", notscsync_setup);
-
 static atomic_t init_deasserted __cpuinitdata;
 
 /*
@@ -546,6 +335,11 @@
 	/* otherwise gcc will move up the smp_processor_id before the cpu_init */
 	barrier();
 
+	/*
+  	 * Check TSC sync first:
+ 	 */
+	check_tsc_sync_target();
+
 	Dprintk("cpu %d: setting up apic clock\n", smp_processor_id()); 	
 	setup_secondary_APIC_clock();
 
@@ -565,14 +359,6 @@
 	 */
 	set_cpu_sibling_map(smp_processor_id());
 
-	/* 
-  	 * Wait for TSC sync to not schedule things before.
-	 * We still process interrupts, which could see an inconsistent
-	 * time in that window unfortunately. 
-	 * Do this here because TSC sync has global unprotected state.
- 	 */
-	tsc_sync_wait();
-
 	/*
 	 * We need to hold call_lock, so there is no inconsistency
 	 * between the time smp_call_function() determines number of
@@ -592,6 +378,7 @@
 	cpu_set(smp_processor_id(), cpu_online_map);
 	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
 	spin_unlock(&vector_lock);
+
 	unlock_ipi_call_lock();
 
 	cpu_idle();
@@ -1168,6 +955,11 @@
 	/* Unleash the CPU! */
 	Dprintk("waiting for cpu %d\n", cpu);
 
+	/*
+  	 * Make sure and check TSC sync:
+ 	 */
+	check_tsc_sync_source(cpu);
+
 	while (!cpu_isset(cpu, cpu_online_map))
 		cpu_relax();
 
@@ -1190,7 +982,6 @@
 	smp_cleanup_boot();
 	setup_ioapic_dest();
 	check_nmi_watchdog();
-	time_init_gtod();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/x86_64/kernel/stacktrace.c b/arch/x86_64/kernel/stacktrace.c
index 6026b31..65ac2c6 100644
--- a/arch/x86_64/kernel/stacktrace.c
+++ b/arch/x86_64/kernel/stacktrace.c
@@ -32,7 +32,7 @@
 		trace->skip--;
 		return;
 	}
-	if (trace->nr_entries < trace->max_entries - 1)
+	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = addr;
 }
 
@@ -49,7 +49,8 @@
 void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
 {
 	dump_trace(task, NULL, NULL, &save_stack_ops, trace);
-	trace->entries[trace->nr_entries++] = ULONG_MAX;
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 EXPORT_SYMBOL(save_stack_trace);
 
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 335cc91..c9addcf 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -42,10 +42,8 @@
 #include <linux/cpufreq.h>
 #include <linux/hpet.h>
 #include <asm/apic.h>
+#include <asm/hpet.h>
 
-#ifdef CONFIG_CPU_FREQ
-static void cpufreq_delayed_get(void);
-#endif
 extern void i8254_timer_resume(void);
 extern int using_apic_timer;
 
@@ -55,128 +53,7 @@
 EXPORT_SYMBOL(rtc_lock);
 DEFINE_SPINLOCK(i8253_lock);
 
-int nohpet __initdata = 0;
-static int notsc __initdata = 0;
-
-#define USEC_PER_TICK (USEC_PER_SEC / HZ)
-#define NSEC_PER_TICK (NSEC_PER_SEC / HZ)
-#define FSEC_PER_TICK (FSEC_PER_SEC / HZ)
-
-#define NS_SCALE	10 /* 2^10, carefully chosen */
-#define US_SCALE	32 /* 2^32, arbitralrily chosen */
-
-unsigned int cpu_khz;					/* TSC clocks / usec, not used here */
-EXPORT_SYMBOL(cpu_khz);
-static unsigned long hpet_period;			/* fsecs / HPET clock */
-unsigned long hpet_tick;				/* HPET clocks / interrupt */
-int hpet_use_timer;				/* Use counter of hpet for time keeping, otherwise PIT */
-unsigned long vxtime_hz = PIT_TICK_RATE;
-int report_lost_ticks;				/* command line option */
-unsigned long long monotonic_base;
-
-struct vxtime_data __vxtime __section_vxtime;	/* for vsyscalls */
-
 volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
-struct timespec __xtime __section_xtime;
-struct timezone __sys_tz __section_sys_tz;
-
-/*
- * do_gettimeoffset() returns microseconds since last timer interrupt was
- * triggered by hardware. A memory read of HPET is slower than a register read
- * of TSC, but much more reliable. It's also synchronized to the timer
- * interrupt. Note that do_gettimeoffset() may return more than hpet_tick, if a
- * timer interrupt has happened already, but vxtime.trigger wasn't updated yet.
- * This is not a problem, because jiffies hasn't updated either. They are bound
- * together by xtime_lock.
- */
-
-static inline unsigned int do_gettimeoffset_tsc(void)
-{
-	unsigned long t;
-	unsigned long x;
-	t = get_cycles_sync();
-	if (t < vxtime.last_tsc) 
-		t = vxtime.last_tsc; /* hack */
-	x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> US_SCALE;
-	return x;
-}
-
-static inline unsigned int do_gettimeoffset_hpet(void)
-{
-	/* cap counter read to one tick to avoid inconsistencies */
-	unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last;
-	return (min(counter,hpet_tick) * vxtime.quot) >> US_SCALE;
-}
-
-unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
-
-/*
- * This version of gettimeofday() has microsecond resolution and better than
- * microsecond precision, as we're using at least a 10 MHz (usually 14.31818
- * MHz) HPET timer.
- */
-
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long seq;
- 	unsigned int sec, usec;
-
-	do {
-		seq = read_seqbegin(&xtime_lock);
-
-		sec = xtime.tv_sec;
-		usec = xtime.tv_nsec / NSEC_PER_USEC;
-
-		/* i386 does some correction here to keep the clock 
-		   monotonous even when ntpd is fixing drift.
-		   But they didn't work for me, there is a non monotonic
-		   clock anyways with ntp.
-		   I dropped all corrections now until a real solution can
-		   be found. Note when you fix it here you need to do the same
-		   in arch/x86_64/kernel/vsyscall.c and export all needed
-		   variables in vmlinux.lds. -AK */ 
-		usec += do_gettimeoffset();
-
-	} while (read_seqretry(&xtime_lock, seq));
-
-	tv->tv_sec = sec + usec / USEC_PER_SEC;
-	tv->tv_usec = usec % USEC_PER_SEC;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-/*
- * settimeofday() first undoes the correction that gettimeofday would do
- * on the time, and then saves it. This is ugly, but has been like this for
- * ages already.
- */
-
-int do_settimeofday(struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irq(&xtime_lock);
-
-	nsec -= do_gettimeoffset() * NSEC_PER_USEC;
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-	set_normalized_timespec(&xtime, sec, nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	ntp_clear();
-
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
 
 unsigned long profile_pc(struct pt_regs *regs)
 {
@@ -267,84 +144,9 @@
 }
 
 
-/* monotonic_clock(): returns # of nanoseconds passed since time_init()
- *		Note: This function is required to return accurate
- *		time even in the absence of multiple timer ticks.
- */
-static inline unsigned long long cycles_2_ns(unsigned long long cyc);
-unsigned long long monotonic_clock(void)
-{
-	unsigned long seq;
- 	u32 last_offset, this_offset, offset;
-	unsigned long long base;
-
-	if (vxtime.mode == VXTIME_HPET) {
-		do {
-			seq = read_seqbegin(&xtime_lock);
-
-			last_offset = vxtime.last;
-			base = monotonic_base;
-			this_offset = hpet_readl(HPET_COUNTER);
-		} while (read_seqretry(&xtime_lock, seq));
-		offset = (this_offset - last_offset);
-		offset *= NSEC_PER_TICK / hpet_tick;
-	} else {
-		do {
-			seq = read_seqbegin(&xtime_lock);
-
-			last_offset = vxtime.last_tsc;
-			base = monotonic_base;
-		} while (read_seqretry(&xtime_lock, seq));
-		this_offset = get_cycles_sync();
-		offset = cycles_2_ns(this_offset - last_offset);
-	}
-	return base + offset;
-}
-EXPORT_SYMBOL(monotonic_clock);
-
-static noinline void handle_lost_ticks(int lost)
-{
-	static long lost_count;
-	static int warned;
-	if (report_lost_ticks) {
-		printk(KERN_WARNING "time.c: Lost %d timer tick(s)! ", lost);
-		print_symbol("rip %s)\n", get_irq_regs()->rip);
-	}
-
-	if (lost_count == 1000 && !warned) {
-		printk(KERN_WARNING "warning: many lost ticks.\n"
-		       KERN_WARNING "Your time source seems to be instable or "
-		   		"some driver is hogging interupts\n");
-		print_symbol("rip %s\n", get_irq_regs()->rip);
-		if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
-			printk(KERN_WARNING "Falling back to HPET\n");
-			if (hpet_use_timer)
-				vxtime.last = hpet_readl(HPET_T0_CMP) - 
-							hpet_tick;
-			else
-				vxtime.last = hpet_readl(HPET_COUNTER);
-			vxtime.mode = VXTIME_HPET;
-			do_gettimeoffset = do_gettimeoffset_hpet;
-		}
-		/* else should fall back to PIT, but code missing. */
-		warned = 1;
-	} else
-		lost_count++;
-
-#ifdef CONFIG_CPU_FREQ
-	/* In some cases the CPU can change frequency without us noticing
-	   Give cpufreq a change to catch up. */
-	if ((lost_count+1) % 25 == 0)
-		cpufreq_delayed_get();
-#endif
-}
-
 void main_timer_handler(void)
 {
 	static unsigned long rtc_update = 0;
-	unsigned long tsc;
-	int delay = 0, offset = 0, lost = 0;
-
 /*
  * Here we are in the timer irq handler. We have irqs locally disabled (so we
  * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running
@@ -354,72 +156,11 @@
 
 	write_seqlock(&xtime_lock);
 
-	if (vxtime.hpet_address)
-		offset = hpet_readl(HPET_COUNTER);
-
-	if (hpet_use_timer) {
-		/* if we're using the hpet timer functionality,
-		 * we can more accurately know the counter value
-		 * when the timer interrupt occured.
-		 */
-		offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
-		delay = hpet_readl(HPET_COUNTER) - offset;
-	} else if (!pmtmr_ioport) {
-		spin_lock(&i8253_lock);
-		outb_p(0x00, 0x43);
-		delay = inb_p(0x40);
-		delay |= inb(0x40) << 8;
-		spin_unlock(&i8253_lock);
-		delay = LATCH - 1 - delay;
-	}
-
-	tsc = get_cycles_sync();
-
-	if (vxtime.mode == VXTIME_HPET) {
-		if (offset - vxtime.last > hpet_tick) {
-			lost = (offset - vxtime.last) / hpet_tick - 1;
-		}
-
-		monotonic_base += 
-			(offset - vxtime.last) * NSEC_PER_TICK / hpet_tick;
-
-		vxtime.last = offset;
-#ifdef CONFIG_X86_PM_TIMER
-	} else if (vxtime.mode == VXTIME_PMTMR) {
-		lost = pmtimer_mark_offset();
-#endif
-	} else {
-		offset = (((tsc - vxtime.last_tsc) *
-			   vxtime.tsc_quot) >> US_SCALE) - USEC_PER_TICK;
-
-		if (offset < 0)
-			offset = 0;
-
-		if (offset > USEC_PER_TICK) {
-			lost = offset / USEC_PER_TICK;
-			offset %= USEC_PER_TICK;
-		}
-
-		monotonic_base += cycles_2_ns(tsc - vxtime.last_tsc);
-
-		vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot;
-
-		if ((((tsc - vxtime.last_tsc) *
-		      vxtime.tsc_quot) >> US_SCALE) < offset)
-			vxtime.last_tsc = tsc -
-				(((long) offset << US_SCALE) / vxtime.tsc_quot) - 1;
-	}
-
-	if (lost > 0)
-		handle_lost_ticks(lost);
-	else
-		lost = 0;
-
 /*
  * Do the timer stuff.
  */
 
-	do_timer(lost + 1);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
 #endif
@@ -460,40 +201,6 @@
 	return IRQ_HANDLED;
 }
 
-static unsigned int cyc2ns_scale __read_mostly;
-
-static inline void set_cyc2ns_scale(unsigned long cpu_khz)
-{
-	cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / cpu_khz;
-}
-
-static inline unsigned long long cycles_2_ns(unsigned long long cyc)
-{
-	return (cyc * cyc2ns_scale) >> NS_SCALE;
-}
-
-unsigned long long sched_clock(void)
-{
-	unsigned long a = 0;
-
-#if 0
-	/* Don't do a HPET read here. Using TSC always is much faster
-	   and HPET may not be mapped yet when the scheduler first runs.
-           Disadvantage is a small drift between CPUs in some configurations,
-	   but that should be tolerable. */
-	if (__vxtime.mode == VXTIME_HPET)
-		return (hpet_readl(HPET_COUNTER) * vxtime.quot) >> US_SCALE;
-#endif
-
-	/* Could do CPU core sync here. Opteron can execute rdtsc speculatively,
-	   which means it is not completely exact and may not be monotonous between
-	   CPUs. But the errors should be too small to matter for scheduling
-	   purposes. */
-
-	rdtscll(a);
-	return cycles_2_ns(a);
-}
-
 static unsigned long get_cmos_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
@@ -545,159 +252,6 @@
 	return mktime(year, mon, day, hour, min, sec);
 }
 
-#ifdef CONFIG_CPU_FREQ
-
-/* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
-   changes.
-   
-   RED-PEN: On SMP we assume all CPUs run with the same frequency.  It's
-   not that important because current Opteron setups do not support
-   scaling on SMP anyroads.
-
-   Should fix up last_tsc too. Currently gettimeofday in the
-   first tick after the change will be slightly wrong. */
-
-#include <linux/workqueue.h>
-
-static unsigned int cpufreq_delayed_issched = 0;
-static unsigned int cpufreq_init = 0;
-static struct work_struct cpufreq_delayed_get_work;
-
-static void handle_cpufreq_delayed_get(struct work_struct *v)
-{
-	unsigned int cpu;
-	for_each_online_cpu(cpu) {
-		cpufreq_get(cpu);
-	}
-	cpufreq_delayed_issched = 0;
-}
-
-/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries
- * to verify the CPU frequency the timing core thinks the CPU is running
- * at is still correct.
- */
-static void cpufreq_delayed_get(void)
-{
-	static int warned;
-	if (cpufreq_init && !cpufreq_delayed_issched) {
-		cpufreq_delayed_issched = 1;
-		if (!warned) {
-			warned = 1;
-			printk(KERN_DEBUG 
-	"Losing some ticks... checking if CPU frequency changed.\n");
-		}
-		schedule_work(&cpufreq_delayed_get_work);
-	}
-}
-
-static unsigned int  ref_freq = 0;
-static unsigned long loops_per_jiffy_ref = 0;
-
-static unsigned long cpu_khz_ref = 0;
-
-static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-				 void *data)
-{
-        struct cpufreq_freqs *freq = data;
-	unsigned long *lpj, dummy;
-
-	if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
-		return 0;
-
-	lpj = &dummy;
-	if (!(freq->flags & CPUFREQ_CONST_LOOPS))
-#ifdef CONFIG_SMP
-		lpj = &cpu_data[freq->cpu].loops_per_jiffy;
-#else
-		lpj = &boot_cpu_data.loops_per_jiffy;
-#endif
-
-	if (!ref_freq) {
-		ref_freq = freq->old;
-		loops_per_jiffy_ref = *lpj;
-		cpu_khz_ref = cpu_khz;
-	}
-        if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
-            (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
-	    (val == CPUFREQ_RESUMECHANGE)) {
-                *lpj =
-		cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
-
-		cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
-		if (!(freq->flags & CPUFREQ_CONST_LOOPS))
-			vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
-	}
-	
-	set_cyc2ns_scale(cpu_khz_ref);
-
-	return 0;
-}
- 
-static struct notifier_block time_cpufreq_notifier_block = {
-         .notifier_call  = time_cpufreq_notifier
-};
-
-static int __init cpufreq_tsc(void)
-{
-	INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get);
-	if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
-				       CPUFREQ_TRANSITION_NOTIFIER))
-		cpufreq_init = 1;
-	return 0;
-}
-
-core_initcall(cpufreq_tsc);
-
-#endif
-
-/*
- * calibrate_tsc() calibrates the processor TSC in a very simple way, comparing
- * it to the HPET timer of known frequency.
- */
-
-#define TICK_COUNT 100000000
-#define TICK_MIN   5000
-
-/*
- * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none
- * occurs between the reads of the hpet & TSC.
- */
-static void __init read_hpet_tsc(int *hpet, int *tsc)
-{
-	int tsc1, tsc2, hpet1;
-
-	do {
-		tsc1 = get_cycles_sync();
-		hpet1 = hpet_readl(HPET_COUNTER);
-		tsc2 = get_cycles_sync();
-	} while (tsc2 - tsc1 > TICK_MIN);
-	*hpet = hpet1;
-	*tsc = tsc2;
-}
-
-
-static unsigned int __init hpet_calibrate_tsc(void)
-{
-	int tsc_start, hpet_start;
-	int tsc_now, hpet_now;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	local_irq_disable();
-
-	read_hpet_tsc(&hpet_start, &tsc_start);
-
-	do {
-		local_irq_disable();
-		read_hpet_tsc(&hpet_now, &tsc_now);
-		local_irq_restore(flags);
-	} while ((tsc_now - tsc_start) < TICK_COUNT &&
-		 (hpet_now - hpet_start) < TICK_COUNT);
-
-	return (tsc_now - tsc_start) * 1000000000L
-		/ ((hpet_now - hpet_start) * hpet_period / 1000);
-}
-
 
 /*
  * pit_calibrate_tsc() uses the speaker output (channel 2) of
@@ -728,124 +282,6 @@
 	return (end - start) / 50;
 }
 
-#ifdef	CONFIG_HPET
-static __init int late_hpet_init(void)
-{
-	struct hpet_data	hd;
-	unsigned int 		ntimer;
-
-	if (!vxtime.hpet_address)
-        	return 0;
-
-	memset(&hd, 0, sizeof (hd));
-
-	ntimer = hpet_readl(HPET_ID);
-	ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
-	ntimer++;
-
-	/*
-	 * Register with driver.
-	 * Timer0 and Timer1 is used by platform.
-	 */
-	hd.hd_phys_address = vxtime.hpet_address;
-	hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE);
-	hd.hd_nirqs = ntimer;
-	hd.hd_flags = HPET_DATA_PLATFORM;
-	hpet_reserve_timer(&hd, 0);
-#ifdef	CONFIG_HPET_EMULATE_RTC
-	hpet_reserve_timer(&hd, 1);
-#endif
-	hd.hd_irq[0] = HPET_LEGACY_8254;
-	hd.hd_irq[1] = HPET_LEGACY_RTC;
-	if (ntimer > 2) {
-		struct hpet		*hpet;
-		struct hpet_timer	*timer;
-		int			i;
-
-		hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE);
-		timer = &hpet->hpet_timers[2];
-		for (i = 2; i < ntimer; timer++, i++)
-			hd.hd_irq[i] = (timer->hpet_config &
-					Tn_INT_ROUTE_CNF_MASK) >>
-				Tn_INT_ROUTE_CNF_SHIFT;
-
-	}
-
-	hpet_alloc(&hd);
-	return 0;
-}
-fs_initcall(late_hpet_init);
-#endif
-
-static int hpet_timer_stop_set_go(unsigned long tick)
-{
-	unsigned int cfg;
-
-/*
- * Stop the timers and reset the main counter.
- */
-
-	cfg = hpet_readl(HPET_CFG);
-	cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
-	hpet_writel(cfg, HPET_CFG);
-	hpet_writel(0, HPET_COUNTER);
-	hpet_writel(0, HPET_COUNTER + 4);
-
-/*
- * Set up timer 0, as periodic with first interrupt to happen at hpet_tick,
- * and period also hpet_tick.
- */
-	if (hpet_use_timer) {
-		hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
-		    HPET_TN_32BIT, HPET_T0_CFG);
-		hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */
-		hpet_writel(hpet_tick, HPET_T0_CMP); /* period */
-		cfg |= HPET_CFG_LEGACY;
-	}
-/*
- * Go!
- */
-
-	cfg |= HPET_CFG_ENABLE;
-	hpet_writel(cfg, HPET_CFG);
-
-	return 0;
-}
-
-static int hpet_init(void)
-{
-	unsigned int id;
-
-	if (!vxtime.hpet_address)
-		return -1;
-	set_fixmap_nocache(FIX_HPET_BASE, vxtime.hpet_address);
-	__set_fixmap(VSYSCALL_HPET, vxtime.hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
-
-/*
- * Read the period, compute tick and quotient.
- */
-
-	id = hpet_readl(HPET_ID);
-
-	if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER))
-		return -1;
-
-	hpet_period = hpet_readl(HPET_PERIOD);
-	if (hpet_period < 100000 || hpet_period > 100000000)
-		return -1;
-
-	hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period;
-
-	hpet_use_timer = (id & HPET_ID_LEGSUP);
-
-	return hpet_timer_stop_set_go(hpet_tick);
-}
-
-static int hpet_reenable(void)
-{
-	return hpet_timer_stop_set_go(hpet_tick);
-}
-
 #define PIT_MODE 0x43
 #define PIT_CH0  0x40
 
@@ -873,7 +309,7 @@
 void __init stop_timer_interrupt(void)
 {
 	char *name;
-	if (vxtime.hpet_address) {
+	if (hpet_address) {
 		name = "HPET";
 		hpet_timer_stop_set_go(0);
 	} else {
@@ -883,12 +319,6 @@
 	printk(KERN_INFO "timer: %s interrupt stopped.\n", name);
 }
 
-int __init time_setup(char *str)
-{
-	report_lost_ticks = 1;
-	return 1;
-}
-
 static struct irqaction irq0 = {
 	timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL
 };
@@ -896,124 +326,41 @@
 void __init time_init(void)
 {
 	if (nohpet)
-		vxtime.hpet_address = 0;
-
+		hpet_address = 0;
 	xtime.tv_sec = get_cmos_time();
 	xtime.tv_nsec = 0;
 
 	set_normalized_timespec(&wall_to_monotonic,
 	                        -xtime.tv_sec, -xtime.tv_nsec);
 
-	if (!hpet_init())
-                vxtime_hz = (FSEC_PER_SEC + hpet_period / 2) / hpet_period;
-	else
-		vxtime.hpet_address = 0;
+	if (hpet_arch_init())
+		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
-	} else if (pmtmr_ioport && !vxtime.hpet_address) {
-		vxtime_hz = PM_TIMER_FREQUENCY;
-		timename = "PM";
-		pit_init();
-		cpu_khz = pit_calibrate_tsc();
-#endif
 	} else {
 		pit_init();
 		cpu_khz = pit_calibrate_tsc();
 		timename = "PIT";
 	}
 
-	vxtime.mode = VXTIME_TSC;
-	vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz;
-	vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
-	vxtime.last_tsc = get_cycles_sync();
-	set_cyc2ns_scale(cpu_khz);
-	setup_irq(0, &irq0);
-
-#ifndef CONFIG_SMP
-	time_init_gtod();
-#endif
-}
-
-/*
- * Make an educated guess if the TSC is trustworthy and synchronized
- * over all CPUs.
- */
-__cpuinit int unsynchronized_tsc(void)
-{
-#ifdef CONFIG_SMP
-	if (apic_is_clustered_box())
-		return 1;
-#endif
-	/* Most intel systems have synchronized TSCs except for
-	   multi node systems */
- 	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
-#ifdef CONFIG_ACPI
-		/* But TSC doesn't tick in C3 so don't use it there */
-		if (acpi_gbl_FADT.header.length > 0 && acpi_gbl_FADT.C3latency < 1000)
-			return 1;
-#endif
- 		return 0;
-	}
-
- 	/* Assume multi socket systems are not synchronized */
- 	return num_present_cpus() > 1;
-}
-
-/*
- * Decide what mode gettimeofday should use.
- */
-void time_init_gtod(void)
-{
-	char *timetype;
-
 	if (unsynchronized_tsc())
-		notsc = 1;
+		mark_tsc_unstable();
 
- 	if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
+	if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
 		vgetcpu_mode = VGETCPU_RDTSCP;
 	else
 		vgetcpu_mode = VGETCPU_LSL;
 
-	if (vxtime.hpet_address && notsc) {
-		timetype = hpet_use_timer ? "HPET" : "PIT/HPET";
-		if (hpet_use_timer)
-			vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
-		else
-			vxtime.last = hpet_readl(HPET_COUNTER);
-		vxtime.mode = VXTIME_HPET;
-		do_gettimeoffset = do_gettimeoffset_hpet;
-#ifdef CONFIG_X86_PM_TIMER
-	/* Using PM for gettimeofday is quite slow, but we have no other
-	   choice because the TSC is too unreliable on some systems. */
-	} else if (pmtmr_ioport && !vxtime.hpet_address && notsc) {
-		timetype = "PM";
-		do_gettimeoffset = do_gettimeoffset_pm;
-		vxtime.mode = VXTIME_PMTMR;
-		sysctl_vsyscall = 0;
-		printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n");
-#endif
-	} else {
-		timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC";
-		vxtime.mode = VXTIME_TSC;
-	}
-
-	printk(KERN_INFO "time.c: Using %ld.%06ld MHz WALL %s GTOD %s timer.\n",
-	       vxtime_hz / 1000000, vxtime_hz % 1000000, timename, timetype);
+	set_cyc2ns_scale(cpu_khz);
 	printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
 		cpu_khz / 1000, cpu_khz % 1000);
-	vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz;
-	vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
-	vxtime.last_tsc = get_cycles_sync();
-
-	set_cyc2ns_scale(cpu_khz);
+	setup_irq(0, &irq0);
 }
 
-__setup("report_lost_ticks", time_setup);
 
 static long clock_cmos_diff;
 static unsigned long sleep_start;
@@ -1050,7 +397,7 @@
 		sleep_length = 0;
 		ctime = sleep_start;
 	}
-	if (vxtime.hpet_address)
+	if (hpet_address)
 		hpet_reenable();
 	else
 		i8254_timer_resume();
@@ -1059,20 +406,8 @@
 	write_seqlock_irqsave(&xtime_lock,flags);
 	xtime.tv_sec = sec;
 	xtime.tv_nsec = 0;
-	if (vxtime.mode == VXTIME_HPET) {
-		if (hpet_use_timer)
-			vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
-		else
-			vxtime.last = hpet_readl(HPET_COUNTER);
-#ifdef CONFIG_X86_PM_TIMER
-	} else if (vxtime.mode == VXTIME_PMTMR) {
-		pmtimer_resume();
-#endif
-	} else
-		vxtime.last_tsc = get_cycles_sync();
-	write_sequnlock_irqrestore(&xtime_lock,flags);
 	jiffies += sleep_length;
-	monotonic_base += sleep_length * (NSEC_PER_SEC/HZ);
+	write_sequnlock_irqrestore(&xtime_lock,flags);
 	touch_softlockup_watchdog();
 	return 0;
 }
@@ -1083,7 +418,7 @@
 	set_kset_name("timer"),
 };
 
-/* XXX this driverfs stuff should probably go elsewhere later -john */
+/* XXX this sysfs stuff should probably go elsewhere later -john */
 static struct sys_device device_timer = {
 	.id	= 0,
 	.cls	= &timer_sysclass,
@@ -1098,269 +433,3 @@
 }
 
 device_initcall(time_init_device);
-
-#ifdef CONFIG_HPET_EMULATE_RTC
-/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
- * is enabled, we support RTC interrupt functionality in software.
- * RTC has 3 kinds of interrupts:
- * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
- *    is updated
- * 2) Alarm Interrupt - generate an interrupt at a specific time of day
- * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
- *    2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
- * (1) and (2) above are implemented using polling at a frequency of
- * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
- * overhead. (DEFAULT_RTC_INT_FREQ)
- * For (3), we use interrupts at 64Hz or user specified periodic
- * frequency, whichever is higher.
- */
-#include <linux/rtc.h>
-
-#define DEFAULT_RTC_INT_FREQ 	64
-#define RTC_NUM_INTS 		1
-
-static unsigned long UIE_on;
-static unsigned long prev_update_sec;
-
-static unsigned long AIE_on;
-static struct rtc_time alarm_time;
-
-static unsigned long PIE_on;
-static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ;
-static unsigned long PIE_count;
-
-static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
-static unsigned int hpet_t1_cmp; /* cached comparator register */
-
-int is_hpet_enabled(void)
-{
-	return vxtime.hpet_address != 0;
-}
-
-/*
- * Timer 1 for RTC, we do not use periodic interrupt feature,
- * even if HPET supports periodic interrupts on Timer 1.
- * The reason being, to set up a periodic interrupt in HPET, we need to
- * stop the main counter. And if we do that everytime someone diables/enables
- * RTC, we will have adverse effect on main kernel timer running on Timer 0.
- * So, for the time being, simulate the periodic interrupt in software.
- *
- * hpet_rtc_timer_init() is called for the first time and during subsequent
- * interuppts reinit happens through hpet_rtc_timer_reinit().
- */
-int hpet_rtc_timer_init(void)
-{
-	unsigned int cfg, cnt;
-	unsigned long flags;
-
-	if (!is_hpet_enabled())
-		return 0;
-	/*
-	 * Set the counter 1 and enable the interrupts.
-	 */
-	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
-		hpet_rtc_int_freq = PIE_freq;
-	else
-		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
-
-	local_irq_save(flags);
-
-	cnt = hpet_readl(HPET_COUNTER);
-	cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
-	hpet_writel(cnt, HPET_T1_CMP);
-	hpet_t1_cmp = cnt;
-
-	cfg = hpet_readl(HPET_T1_CFG);
-	cfg &= ~HPET_TN_PERIODIC;
-	cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_T1_CFG);
-
-	local_irq_restore(flags);
-
-	return 1;
-}
-
-static void hpet_rtc_timer_reinit(void)
-{
-	unsigned int cfg, cnt, ticks_per_int, lost_ints;
-
-	if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
-		cfg = hpet_readl(HPET_T1_CFG);
-		cfg &= ~HPET_TN_ENABLE;
-		hpet_writel(cfg, HPET_T1_CFG);
-		return;
-	}
-
-	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
-		hpet_rtc_int_freq = PIE_freq;
-	else
-		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
-
-	/* It is more accurate to use the comparator value than current count.*/
-	ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq;
-	hpet_t1_cmp += ticks_per_int;
-	hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
-
-	/*
-	 * If the interrupt handler was delayed too long, the write above tries
-	 * to schedule the next interrupt in the past and the hardware would
-	 * not interrupt until the counter had wrapped around.
-	 * So we have to check that the comparator wasn't set to a past time.
-	 */
-	cnt = hpet_readl(HPET_COUNTER);
-	if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) {
-		lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1;
-		/* Make sure that, even with the time needed to execute
-		 * this code, the next scheduled interrupt has been moved
-		 * back to the future: */
-		lost_ints++;
-
-		hpet_t1_cmp += lost_ints * ticks_per_int;
-		hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
-
-		if (PIE_on)
-			PIE_count += lost_ints;
-
-		printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
-		       hpet_rtc_int_freq);
-	}
-}
-
-/*
- * The functions below are called from rtc driver.
- * Return 0 if HPET is not being used.
- * Otherwise do the necessary changes and return 1.
- */
-int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	if (bit_mask & RTC_UIE)
-		UIE_on = 0;
-	if (bit_mask & RTC_PIE)
-		PIE_on = 0;
-	if (bit_mask & RTC_AIE)
-		AIE_on = 0;
-
-	return 1;
-}
-
-int hpet_set_rtc_irq_bit(unsigned long bit_mask)
-{
-	int timer_init_reqd = 0;
-
-	if (!is_hpet_enabled())
-		return 0;
-
-	if (!(PIE_on | AIE_on | UIE_on))
-		timer_init_reqd = 1;
-
-	if (bit_mask & RTC_UIE) {
-		UIE_on = 1;
-	}
-	if (bit_mask & RTC_PIE) {
-		PIE_on = 1;
-		PIE_count = 0;
-	}
-	if (bit_mask & RTC_AIE) {
-		AIE_on = 1;
-	}
-
-	if (timer_init_reqd)
-		hpet_rtc_timer_init();
-
-	return 1;
-}
-
-int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	alarm_time.tm_hour = hrs;
-	alarm_time.tm_min = min;
-	alarm_time.tm_sec = sec;
-
-	return 1;
-}
-
-int hpet_set_periodic_freq(unsigned long freq)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	PIE_freq = freq;
-	PIE_count = 0;
-
-	return 1;
-}
-
-int hpet_rtc_dropped_irq(void)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	return 1;
-}
-
-irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct rtc_time curr_time;
-	unsigned long rtc_int_flag = 0;
-	int call_rtc_interrupt = 0;
-
-	hpet_rtc_timer_reinit();
-
-	if (UIE_on | AIE_on) {
-		rtc_get_rtc_time(&curr_time);
-	}
-	if (UIE_on) {
-		if (curr_time.tm_sec != prev_update_sec) {
-			/* Set update int info, call real rtc int routine */
-			call_rtc_interrupt = 1;
-			rtc_int_flag = RTC_UF;
-			prev_update_sec = curr_time.tm_sec;
-		}
-	}
-	if (PIE_on) {
-		PIE_count++;
-		if (PIE_count >= hpet_rtc_int_freq/PIE_freq) {
-			/* Set periodic int info, call real rtc int routine */
-			call_rtc_interrupt = 1;
-			rtc_int_flag |= RTC_PF;
-			PIE_count = 0;
-		}
-	}
-	if (AIE_on) {
-		if ((curr_time.tm_sec == alarm_time.tm_sec) &&
-		    (curr_time.tm_min == alarm_time.tm_min) &&
-		    (curr_time.tm_hour == alarm_time.tm_hour)) {
-			/* Set alarm int info, call real rtc int routine */
-			call_rtc_interrupt = 1;
-			rtc_int_flag |= RTC_AF;
-		}
-	}
-	if (call_rtc_interrupt) {
-		rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
-		rtc_interrupt(rtc_int_flag, dev_id);
-	}
-	return IRQ_HANDLED;
-}
-#endif
-
-static int __init nohpet_setup(char *s) 
-{ 
-	nohpet = 1;
-	return 1;
-} 
-
-__setup("nohpet", nohpet_setup);
-
-int __init notsc_setup(char *s)
-{
-	notsc = 1;
-	return 1;
-}
-
-__setup("notsc", notsc_setup);
diff --git a/arch/x86_64/kernel/tsc.c b/arch/x86_64/kernel/tsc.c
new file mode 100644
index 0000000..8958318
--- /dev/null
+++ b/arch/x86_64/kernel/tsc.c
@@ -0,0 +1,226 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/clocksource.h>
+#include <linux/time.h>
+#include <linux/acpi.h>
+#include <linux/cpufreq.h>
+
+#include <asm/timex.h>
+
+static int notsc __initdata = 0;
+
+unsigned int cpu_khz;		/* TSC clocks / usec, not used here */
+EXPORT_SYMBOL(cpu_khz);
+
+static unsigned int cyc2ns_scale __read_mostly;
+
+void set_cyc2ns_scale(unsigned long khz)
+{
+	cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / khz;
+}
+
+static unsigned long long cycles_2_ns(unsigned long long cyc)
+{
+	return (cyc * cyc2ns_scale) >> NS_SCALE;
+}
+
+unsigned long long sched_clock(void)
+{
+	unsigned long a = 0;
+
+	/* Could do CPU core sync here. Opteron can execute rdtsc speculatively,
+	 * which means it is not completely exact and may not be monotonous
+	 * between CPUs. But the errors should be too small to matter for
+	 * scheduling purposes.
+	 */
+
+	rdtscll(a);
+	return cycles_2_ns(a);
+}
+
+static int tsc_unstable;
+
+static inline int check_tsc_unstable(void)
+{
+	return tsc_unstable;
+}
+#ifdef CONFIG_CPU_FREQ
+
+/* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
+ * changes.
+ *
+ * RED-PEN: On SMP we assume all CPUs run with the same frequency.  It's
+ * not that important because current Opteron setups do not support
+ * scaling on SMP anyroads.
+ *
+ * Should fix up last_tsc too. Currently gettimeofday in the
+ * first tick after the change will be slightly wrong.
+ */
+
+#include <linux/workqueue.h>
+
+static unsigned int cpufreq_delayed_issched = 0;
+static unsigned int cpufreq_init = 0;
+static struct work_struct cpufreq_delayed_get_work;
+
+static void handle_cpufreq_delayed_get(struct work_struct *v)
+{
+	unsigned int cpu;
+	for_each_online_cpu(cpu) {
+		cpufreq_get(cpu);
+	}
+	cpufreq_delayed_issched = 0;
+}
+
+static unsigned int  ref_freq = 0;
+static unsigned long loops_per_jiffy_ref = 0;
+
+static unsigned long cpu_khz_ref = 0;
+
+static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+				 void *data)
+{
+	struct cpufreq_freqs *freq = data;
+	unsigned long *lpj, dummy;
+
+	if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
+		return 0;
+
+	lpj = &dummy;
+	if (!(freq->flags & CPUFREQ_CONST_LOOPS))
+#ifdef CONFIG_SMP
+		lpj = &cpu_data[freq->cpu].loops_per_jiffy;
+#else
+		lpj = &boot_cpu_data.loops_per_jiffy;
+#endif
+
+	if (!ref_freq) {
+		ref_freq = freq->old;
+		loops_per_jiffy_ref = *lpj;
+		cpu_khz_ref = cpu_khz;
+	}
+	if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
+		(val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
+		(val == CPUFREQ_RESUMECHANGE)) {
+		*lpj =
+		cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
+
+		cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
+		if (!(freq->flags & CPUFREQ_CONST_LOOPS))
+			mark_tsc_unstable();
+	}
+
+	set_cyc2ns_scale(cpu_khz_ref);
+
+	return 0;
+}
+
+static struct notifier_block time_cpufreq_notifier_block = {
+	.notifier_call  = time_cpufreq_notifier
+};
+
+static int __init cpufreq_tsc(void)
+{
+	INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get);
+	if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
+				       CPUFREQ_TRANSITION_NOTIFIER))
+		cpufreq_init = 1;
+	return 0;
+}
+
+core_initcall(cpufreq_tsc);
+
+#endif
+
+static int tsc_unstable = 0;
+
+/*
+ * Make an educated guess if the TSC is trustworthy and synchronized
+ * over all CPUs.
+ */
+__cpuinit int unsynchronized_tsc(void)
+{
+	if (tsc_unstable)
+		return 1;
+
+#ifdef CONFIG_SMP
+	if (apic_is_clustered_box())
+		return 1;
+#endif
+	/* Most intel systems have synchronized TSCs except for
+	   multi node systems */
+ 	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+#ifdef CONFIG_ACPI
+		/* But TSC doesn't tick in C3 so don't use it there */
+		if (acpi_gbl_FADT.header.length > 0 && acpi_gbl_FADT.C3latency < 1000)
+			return 1;
+#endif
+ 		return 0;
+	}
+
+ 	/* Assume multi socket systems are not synchronized */
+ 	return num_present_cpus() > 1;
+}
+
+int __init notsc_setup(char *s)
+{
+	notsc = 1;
+	return 1;
+}
+
+__setup("notsc", notsc_setup);
+
+
+/* clock source code: */
+static cycle_t read_tsc(void)
+{
+	cycle_t ret = (cycle_t)get_cycles_sync();
+	return ret;
+}
+
+static cycle_t __vsyscall_fn vread_tsc(void)
+{
+	cycle_t ret = (cycle_t)get_cycles_sync();
+	return ret;
+}
+
+static struct clocksource clocksource_tsc = {
+	.name			= "tsc",
+	.rating			= 300,
+	.read			= read_tsc,
+	.mask			= CLOCKSOURCE_MASK(64),
+	.shift			= 22,
+	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
+				  CLOCK_SOURCE_MUST_VERIFY,
+	.vread			= vread_tsc,
+};
+
+void mark_tsc_unstable(void)
+{
+	if (!tsc_unstable) {
+		tsc_unstable = 1;
+		/* Change only the rating, when not registered */
+		if (clocksource_tsc.mult)
+			clocksource_change_rating(&clocksource_tsc, 0);
+		else
+			clocksource_tsc.rating = 0;
+	}
+}
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+
+static int __init init_tsc_clocksource(void)
+{
+	if (!notsc) {
+		clocksource_tsc.mult = clocksource_khz2mult(cpu_khz,
+							clocksource_tsc.shift);
+		if (check_tsc_unstable())
+			clocksource_tsc.rating = 0;
+
+		return clocksource_register(&clocksource_tsc);
+	}
+	return 0;
+}
+
+module_init(init_tsc_clocksource);
diff --git a/arch/x86_64/kernel/tsc_sync.c b/arch/x86_64/kernel/tsc_sync.c
new file mode 100644
index 0000000..014f0db
--- /dev/null
+++ b/arch/x86_64/kernel/tsc_sync.c
@@ -0,0 +1,187 @@
+/*
+ * arch/x86_64/kernel/tsc_sync.c: check TSC synchronization.
+ *
+ * Copyright (C) 2006, Red Hat, Inc., Ingo Molnar
+ *
+ * We check whether all boot CPUs have their TSC's synchronized,
+ * print a warning if not and turn off the TSC clock-source.
+ *
+ * The warp-check is point-to-point between two CPUs, the CPU
+ * initiating the bootup is the 'source CPU', the freshly booting
+ * CPU is the 'target CPU'.
+ *
+ * Only two CPUs may participate - they can enter in any order.
+ * ( The serial nature of the boot logic and the CPU hotplug lock
+ *   protects against more than 2 CPUs entering this code. )
+ */
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/nmi.h>
+#include <asm/tsc.h>
+
+/*
+ * Entry/exit counters that make sure that both CPUs
+ * run the measurement code at once:
+ */
+static __cpuinitdata atomic_t start_count;
+static __cpuinitdata atomic_t stop_count;
+
+/*
+ * We use a raw spinlock in this exceptional case, because
+ * we want to have the fastest, inlined, non-debug version
+ * of a critical section, to be able to prove TSC time-warps:
+ */
+static __cpuinitdata raw_spinlock_t sync_lock = __RAW_SPIN_LOCK_UNLOCKED;
+static __cpuinitdata cycles_t last_tsc;
+static __cpuinitdata cycles_t max_warp;
+static __cpuinitdata int nr_warps;
+
+/*
+ * TSC-warp measurement loop running on both CPUs:
+ */
+static __cpuinit void check_tsc_warp(void)
+{
+	cycles_t start, now, prev, end;
+	int i;
+
+	start = get_cycles_sync();
+	/*
+	 * The measurement runs for 20 msecs:
+	 */
+	end = start + cpu_khz * 20ULL;
+	now = start;
+
+	for (i = 0; ; i++) {
+		/*
+		 * We take the global lock, measure TSC, save the
+		 * previous TSC that was measured (possibly on
+		 * another CPU) and update the previous TSC timestamp.
+		 */
+		__raw_spin_lock(&sync_lock);
+		prev = last_tsc;
+		now = get_cycles_sync();
+		last_tsc = now;
+		__raw_spin_unlock(&sync_lock);
+
+		/*
+		 * Be nice every now and then (and also check whether
+		 * measurement is done [we also insert a 100 million
+		 * loops safety exit, so we dont lock up in case the
+		 * TSC readout is totally broken]):
+		 */
+		if (unlikely(!(i & 7))) {
+			if (now > end || i > 100000000)
+				break;
+			cpu_relax();
+			touch_nmi_watchdog();
+		}
+		/*
+		 * Outside the critical section we can now see whether
+		 * we saw a time-warp of the TSC going backwards:
+		 */
+		if (unlikely(prev > now)) {
+			__raw_spin_lock(&sync_lock);
+			max_warp = max(max_warp, prev - now);
+			nr_warps++;
+			__raw_spin_unlock(&sync_lock);
+		}
+
+	}
+}
+
+/*
+ * Source CPU calls into this - it waits for the freshly booted
+ * target CPU to arrive and then starts the measurement:
+ */
+void __cpuinit check_tsc_sync_source(int cpu)
+{
+	int cpus = 2;
+
+	/*
+	 * No need to check if we already know that the TSC is not
+	 * synchronized:
+	 */
+	if (unsynchronized_tsc())
+		return;
+
+	printk(KERN_INFO "checking TSC synchronization [CPU#%d -> CPU#%d]:",
+			  smp_processor_id(), cpu);
+
+	/*
+	 * Reset it - in case this is a second bootup:
+	 */
+	atomic_set(&stop_count, 0);
+
+	/*
+	 * Wait for the target to arrive:
+	 */
+	while (atomic_read(&start_count) != cpus-1)
+		cpu_relax();
+	/*
+	 * Trigger the target to continue into the measurement too:
+	 */
+	atomic_inc(&start_count);
+
+	check_tsc_warp();
+
+	while (atomic_read(&stop_count) != cpus-1)
+		cpu_relax();
+
+	/*
+	 * Reset it - just in case we boot another CPU later:
+	 */
+	atomic_set(&start_count, 0);
+
+	if (nr_warps) {
+		printk("\n");
+		printk(KERN_WARNING "Measured %Ld cycles TSC warp between CPUs,"
+				    " turning off TSC clock.\n", max_warp);
+		mark_tsc_unstable();
+		nr_warps = 0;
+		max_warp = 0;
+		last_tsc = 0;
+	} else {
+		printk(" passed.\n");
+	}
+
+	/*
+	 * Let the target continue with the bootup:
+	 */
+	atomic_inc(&stop_count);
+}
+
+/*
+ * Freshly booted CPUs call into this:
+ */
+void __cpuinit check_tsc_sync_target(void)
+{
+	int cpus = 2;
+
+	if (unsynchronized_tsc())
+		return;
+
+	/*
+	 * Register this CPU's participation and wait for the
+	 * source CPU to start the measurement:
+	 */
+	atomic_inc(&start_count);
+	while (atomic_read(&start_count) != cpus)
+		cpu_relax();
+
+	check_tsc_warp();
+
+	/*
+	 * Ok, we are done:
+	 */
+	atomic_inc(&stop_count);
+
+	/*
+	 * Wait for the source CPU to print stuff:
+	 */
+	while (atomic_read(&stop_count) != cpus)
+		cpu_relax();
+}
+#undef NR_LOOPS
+
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 1e54ddf..b73212c 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -88,31 +88,25 @@
   __vsyscall_0 = VSYSCALL_VIRT_ADDR;
 
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-  .xtime_lock : AT(VLOAD(.xtime_lock)) { *(.xtime_lock) }
-  xtime_lock = VVIRT(.xtime_lock);
-
-  .vxtime : AT(VLOAD(.vxtime)) { *(.vxtime) }
-  vxtime = VVIRT(.vxtime);
+  .vsyscall_fn : AT(VLOAD(.vsyscall_fn)) { *(.vsyscall_fn) }
+  . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+  .vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data))
+		{ *(.vsyscall_gtod_data) }
+  vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data);
 
   .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
   vgetcpu_mode = VVIRT(.vgetcpu_mode);
 
-  .sys_tz : AT(VLOAD(.sys_tz)) { *(.sys_tz) }
-  sys_tz = VVIRT(.sys_tz);
-
-  .sysctl_vsyscall : AT(VLOAD(.sysctl_vsyscall)) { *(.sysctl_vsyscall) }
-  sysctl_vsyscall = VVIRT(.sysctl_vsyscall);
-
-  .xtime : AT(VLOAD(.xtime)) { *(.xtime) }
-  xtime = VVIRT(.xtime);
-
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   .jiffies : AT(VLOAD(.jiffies)) { *(.jiffies) }
   jiffies = VVIRT(.jiffies);
 
-  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) { *(.vsyscall_1) }
-  .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) { *(.vsyscall_2) }
-  .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) { *(.vsyscall_3) }
+  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1))
+		{ *(.vsyscall_1) }
+  .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2))
+		{ *(.vsyscall_2) }
+  .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3))
+		{ *(.vsyscall_3) }
 
   . = VSYSCALL_VIRT_ADDR + 4096;
 
@@ -192,10 +186,14 @@
      from .altinstructions and .eh_frame */
   .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
   .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
+
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
+
     . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   __per_cpu_start = .;
   .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index 2433d6f..180ff91 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -26,6 +26,7 @@
 #include <linux/seqlock.h>
 #include <linux/jiffies.h>
 #include <linux/sysctl.h>
+#include <linux/clocksource.h>
 #include <linux/getcpu.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
@@ -34,6 +35,7 @@
 #include <asm/vsyscall.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/unistd.h>
 #include <asm/fixmap.h>
 #include <asm/errno.h>
 #include <asm/io.h>
@@ -44,56 +46,41 @@
 #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
 #define __syscall_clobber "r11","rcx","memory"
 
-int __sysctl_vsyscall __section_sysctl_vsyscall = 1;
-seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED;
+struct vsyscall_gtod_data_t {
+	seqlock_t lock;
+	int sysctl_enabled;
+	struct timeval wall_time_tv;
+	struct timezone sys_tz;
+	cycle_t offset_base;
+	struct clocksource clock;
+};
 int __vgetcpu_mode __section_vgetcpu_mode;
 
-#include <asm/unistd.h>
-
-static __always_inline void timeval_normalize(struct timeval * tv)
+struct vsyscall_gtod_data_t __vsyscall_gtod_data __section_vsyscall_gtod_data =
 {
-	time_t __sec;
+	.lock = SEQLOCK_UNLOCKED,
+	.sysctl_enabled = 1,
+};
 
-	__sec = tv->tv_usec / 1000000;
-	if (__sec) {
-		tv->tv_usec %= 1000000;
-		tv->tv_sec += __sec;
-	}
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
+{
+	unsigned long flags;
+
+	write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+	/* copy vsyscall data */
+	vsyscall_gtod_data.clock = *clock;
+	vsyscall_gtod_data.wall_time_tv.tv_sec = wall_time->tv_sec;
+	vsyscall_gtod_data.wall_time_tv.tv_usec = wall_time->tv_nsec/1000;
+	vsyscall_gtod_data.sys_tz = sys_tz;
+	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
 }
 
-static __always_inline void do_vgettimeofday(struct timeval * tv)
-{
-	long sequence, t;
-	unsigned long sec, usec;
-
-	do {
-		sequence = read_seqbegin(&__xtime_lock);
-		
-		sec = __xtime.tv_sec;
-		usec = __xtime.tv_nsec / 1000;
-
-		if (__vxtime.mode != VXTIME_HPET) {
-			t = get_cycles_sync();
-			if (t < __vxtime.last_tsc)
-				t = __vxtime.last_tsc;
-			usec += ((t - __vxtime.last_tsc) *
-				 __vxtime.tsc_quot) >> 32;
-			/* See comment in x86_64 do_gettimeofday. */
-		} else {
-			usec += ((readl((void __iomem *)
-				   fix_to_virt(VSYSCALL_HPET) + 0xf0) -
-				  __vxtime.last) * __vxtime.quot) >> 32;
-		}
-	} while (read_seqretry(&__xtime_lock, sequence));
-
-	tv->tv_sec = sec + usec / 1000000;
-	tv->tv_usec = usec % 1000000;
-}
-
-/* RED-PEN may want to readd seq locking, but then the variable should be write-once. */
+/* RED-PEN may want to readd seq locking, but then the variable should be
+ * write-once.
+ */
 static __always_inline void do_get_tz(struct timezone * tz)
 {
-	*tz = __sys_tz;
+	*tz = __vsyscall_gtod_data.sys_tz;
 }
 
 static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
@@ -101,7 +88,8 @@
 	int ret;
 	asm volatile("vsysc2: syscall"
 		: "=a" (ret)
-		: "0" (__NR_gettimeofday),"D" (tv),"S" (tz) : __syscall_clobber );
+		: "0" (__NR_gettimeofday),"D" (tv),"S" (tz)
+		: __syscall_clobber );
 	return ret;
 }
 
@@ -114,10 +102,44 @@
 	return secs;
 }
 
+static __always_inline void do_vgettimeofday(struct timeval * tv)
+{
+	cycle_t now, base, mask, cycle_delta;
+	unsigned long seq, mult, shift, nsec_delta;
+	cycle_t (*vread)(void);
+	do {
+		seq = read_seqbegin(&__vsyscall_gtod_data.lock);
+
+		vread = __vsyscall_gtod_data.clock.vread;
+		if (unlikely(!__vsyscall_gtod_data.sysctl_enabled || !vread)) {
+			gettimeofday(tv,0);
+			return;
+		}
+		now = vread();
+		base = __vsyscall_gtod_data.clock.cycle_last;
+		mask = __vsyscall_gtod_data.clock.mask;
+		mult = __vsyscall_gtod_data.clock.mult;
+		shift = __vsyscall_gtod_data.clock.shift;
+
+		*tv = __vsyscall_gtod_data.wall_time_tv;
+
+	} while (read_seqretry(&__vsyscall_gtod_data.lock, seq));
+
+	/* calculate interval: */
+	cycle_delta = (now - base) & mask;
+	/* convert to nsecs: */
+	nsec_delta = (cycle_delta * mult) >> shift;
+
+	/* convert to usecs and add to timespec: */
+	tv->tv_usec += nsec_delta / NSEC_PER_USEC;
+	while (tv->tv_usec > USEC_PER_SEC) {
+		tv->tv_sec += 1;
+		tv->tv_usec -= USEC_PER_SEC;
+	}
+}
+
 int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
 {
-	if (!__sysctl_vsyscall)
-		return gettimeofday(tv,tz);
 	if (tv)
 		do_vgettimeofday(tv);
 	if (tz)
@@ -129,11 +151,11 @@
  * unlikely */
 time_t __vsyscall(1) vtime(time_t *t)
 {
-	if (!__sysctl_vsyscall)
+	if (unlikely(!__vsyscall_gtod_data.sysctl_enabled))
 		return time_syscall(t);
 	else if (t)
-		*t = __xtime.tv_sec;		
-	return __xtime.tv_sec;
+		*t = __vsyscall_gtod_data.wall_time_tv.tv_sec;
+	return __vsyscall_gtod_data.wall_time_tv.tv_sec;
 }
 
 /* Fast way to get current CPU and node.
@@ -210,7 +232,7 @@
 		ret = -ENOMEM;
 		goto out;
 	}
-	if (!sysctl_vsyscall) {
+	if (!vsyscall_gtod_data.sysctl_enabled) {
 		writew(SYSCALL, map1);
 		writew(SYSCALL, map2);
 	} else {
@@ -232,16 +254,17 @@
 
 static ctl_table kernel_table2[] = {
 	{ .ctl_name = 99, .procname = "vsyscall64",
-	  .data = &sysctl_vsyscall, .maxlen = sizeof(int), .mode = 0644,
+	  .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
+	  .mode = 0644,
 	  .strategy = vsyscall_sysctl_nostrat,
 	  .proc_handler = vsyscall_sysctl_change },
-	{ 0, }
+	{}
 };
 
 static ctl_table kernel_root_table2[] = {
 	{ .ctl_name = CTL_KERN, .procname = "kernel", .mode = 0555,
 	  .child = kernel_table2 },
-	{ 0 },
+	{}
 };
 
 #endif
@@ -301,7 +324,7 @@
 	BUG_ON((unsigned long) &vgetcpu != VSYSCALL_ADDR(__NR_vgetcpu));
 	map_vsyscall();
 #ifdef CONFIG_SYSCTL
-	register_sysctl_table(kernel_root_table2, 0);
+	register_sysctl_table(kernel_root_table2);
 #endif
 	on_each_cpu(cpu_vsyscall_init, NULL, 0, 1);
 	hotcpu_notifier(cpu_vsyscall_notifier, 0);
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 6d77e47..0dffae6 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -26,6 +26,7 @@
 EXPORT_SYMBOL(__put_user_8);
 
 EXPORT_SYMBOL(copy_user_generic);
+EXPORT_SYMBOL(__copy_user_nocache);
 EXPORT_SYMBOL(copy_from_user);
 EXPORT_SYMBOL(copy_to_user);
 EXPORT_SYMBOL(__copy_from_user_inatomic);
@@ -34,8 +35,8 @@
 EXPORT_SYMBOL(clear_page);
 
 #ifdef CONFIG_SMP
-extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
-extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
+extern void  __write_lock_failed(rwlock_t *rw);
+extern void  __read_lock_failed(rwlock_t *rw);
 EXPORT_SYMBOL(__write_lock_failed);
 EXPORT_SYMBOL(__read_lock_failed);
 #endif
diff --git a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile
index b78d417..8d5f835a 100644
--- a/arch/x86_64/lib/Makefile
+++ b/arch/x86_64/lib/Makefile
@@ -9,4 +9,4 @@
 lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \
 	usercopy.o getuser.o putuser.o  \
 	thunk.o clear_page.o copy_page.o bitstr.o bitops.o
-lib-y += memcpy.o memmove.o memset.o copy_user.o rwlock.o
+lib-y += memcpy.o memmove.o memset.o copy_user.o rwlock.o copy_user_nocache.o
diff --git a/arch/x86_64/lib/copy_user_nocache.S b/arch/x86_64/lib/copy_user_nocache.S
new file mode 100644
index 0000000..4620efb
--- /dev/null
+++ b/arch/x86_64/lib/copy_user_nocache.S
@@ -0,0 +1,217 @@
+/* Copyright 2002 Andi Kleen, SuSE Labs.
+ * Subject to the GNU Public License v2.
+ *
+ * Functions to copy from and to user space.
+ */
+
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
+#define FIX_ALIGNMENT 1
+
+#include <asm/current.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/cpufeature.h>
+
+/*
+ * copy_user_nocache - Uncached memory copy with exception handling
+ * This will force destination/source out of cache for more performance.
+ *
+ * Input:
+ * rdi destination
+ * rsi source
+ * rdx count
+ * rcx zero flag	when 1 zero on exception
+ *
+ * Output:
+ * eax uncopied bytes or 0 if successful.
+ */
+ENTRY(__copy_user_nocache)
+	CFI_STARTPROC
+	pushq %rbx
+	CFI_ADJUST_CFA_OFFSET 8
+	CFI_REL_OFFSET rbx, 0
+	pushq %rcx		/* save zero flag */
+	CFI_ADJUST_CFA_OFFSET 8
+	CFI_REL_OFFSET rcx, 0
+
+	xorl %eax,%eax		/* zero for the exception handler */
+
+#ifdef FIX_ALIGNMENT
+	/* check for bad alignment of destination */
+	movl %edi,%ecx
+	andl $7,%ecx
+	jnz  .Lbad_alignment
+.Lafter_bad_alignment:
+#endif
+
+	movq %rdx,%rcx
+
+	movl $64,%ebx
+	shrq $6,%rdx
+	decq %rdx
+	js   .Lhandle_tail
+
+	.p2align 4
+.Lloop:
+.Ls1:	movq (%rsi),%r11
+.Ls2:	movq 1*8(%rsi),%r8
+.Ls3:	movq 2*8(%rsi),%r9
+.Ls4:	movq 3*8(%rsi),%r10
+.Ld1:	movnti %r11,(%rdi)
+.Ld2:	movnti %r8,1*8(%rdi)
+.Ld3:	movnti %r9,2*8(%rdi)
+.Ld4:	movnti %r10,3*8(%rdi)
+
+.Ls5:	movq 4*8(%rsi),%r11
+.Ls6:	movq 5*8(%rsi),%r8
+.Ls7:	movq 6*8(%rsi),%r9
+.Ls8:	movq 7*8(%rsi),%r10
+.Ld5:	movnti %r11,4*8(%rdi)
+.Ld6:	movnti %r8,5*8(%rdi)
+.Ld7:	movnti %r9,6*8(%rdi)
+.Ld8:	movnti %r10,7*8(%rdi)
+
+	dec  %rdx
+
+	leaq 64(%rsi),%rsi
+	leaq 64(%rdi),%rdi
+
+	jns  .Lloop
+
+	.p2align 4
+.Lhandle_tail:
+	movl %ecx,%edx
+	andl $63,%ecx
+	shrl $3,%ecx
+	jz   .Lhandle_7
+	movl $8,%ebx
+	.p2align 4
+.Lloop_8:
+.Ls9:	movq (%rsi),%r8
+.Ld9:	movnti %r8,(%rdi)
+	decl %ecx
+	leaq 8(%rdi),%rdi
+	leaq 8(%rsi),%rsi
+	jnz .Lloop_8
+
+.Lhandle_7:
+	movl %edx,%ecx
+	andl $7,%ecx
+	jz   .Lende
+	.p2align 4
+.Lloop_1:
+.Ls10:	movb (%rsi),%bl
+.Ld10:	movb %bl,(%rdi)
+	incq %rdi
+	incq %rsi
+	decl %ecx
+	jnz .Lloop_1
+
+	CFI_REMEMBER_STATE
+.Lende:
+	popq %rcx
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_RESTORE %rcx
+	popq %rbx
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_RESTORE rbx
+	ret
+	CFI_RESTORE_STATE
+
+#ifdef FIX_ALIGNMENT
+	/* align destination */
+	.p2align 4
+.Lbad_alignment:
+	movl $8,%r9d
+	subl %ecx,%r9d
+	movl %r9d,%ecx
+	cmpq %r9,%rdx
+	jz   .Lhandle_7
+	js   .Lhandle_7
+.Lalign_1:
+.Ls11:	movb (%rsi),%bl
+.Ld11:	movb %bl,(%rdi)
+	incq %rsi
+	incq %rdi
+	decl %ecx
+	jnz .Lalign_1
+	subq %r9,%rdx
+	jmp .Lafter_bad_alignment
+#endif
+
+	/* table sorted by exception address */
+	.section __ex_table,"a"
+	.align 8
+	.quad .Ls1,.Ls1e
+	.quad .Ls2,.Ls2e
+	.quad .Ls3,.Ls3e
+	.quad .Ls4,.Ls4e
+	.quad .Ld1,.Ls1e
+	.quad .Ld2,.Ls2e
+	.quad .Ld3,.Ls3e
+	.quad .Ld4,.Ls4e
+	.quad .Ls5,.Ls5e
+	.quad .Ls6,.Ls6e
+	.quad .Ls7,.Ls7e
+	.quad .Ls8,.Ls8e
+	.quad .Ld5,.Ls5e
+	.quad .Ld6,.Ls6e
+	.quad .Ld7,.Ls7e
+	.quad .Ld8,.Ls8e
+	.quad .Ls9,.Le_quad
+	.quad .Ld9,.Le_quad
+	.quad .Ls10,.Le_byte
+	.quad .Ld10,.Le_byte
+#ifdef FIX_ALIGNMENT
+	.quad .Ls11,.Lzero_rest
+	.quad .Ld11,.Lzero_rest
+#endif
+	.quad .Le5,.Le_zero
+	.previous
+
+	/* compute 64-offset for main loop. 8 bytes accuracy with error on the
+	   pessimistic side. this is gross. it would be better to fix the
+	   interface. */
+	/* eax: zero, ebx: 64 */
+.Ls1e: 	addl $8,%eax
+.Ls2e: 	addl $8,%eax
+.Ls3e: 	addl $8,%eax
+.Ls4e: 	addl $8,%eax
+.Ls5e: 	addl $8,%eax
+.Ls6e: 	addl $8,%eax
+.Ls7e: 	addl $8,%eax
+.Ls8e: 	addl $8,%eax
+	addq %rbx,%rdi	/* +64 */
+	subq %rax,%rdi  /* correct destination with computed offset */
+
+	shlq $6,%rdx	/* loop counter * 64 (stride length) */
+	addq %rax,%rdx	/* add offset to loopcnt */
+	andl $63,%ecx	/* remaining bytes */
+	addq %rcx,%rdx	/* add them */
+	jmp .Lzero_rest
+
+	/* exception on quad word loop in tail handling */
+	/* ecx:	loopcnt/8, %edx: length, rdi: correct */
+.Le_quad:
+	shll $3,%ecx
+	andl $7,%edx
+	addl %ecx,%edx
+	/* edx: bytes to zero, rdi: dest, eax:zero */
+.Lzero_rest:
+	cmpl $0,(%rsp)	/* zero flag set? */
+	jz   .Le_zero
+	movq %rdx,%rcx
+.Le_byte:
+	xorl %eax,%eax
+.Le5:	rep
+	stosb
+	/* when there is another exception while zeroing the rest just return */
+.Le_zero:
+	movq %rdx,%rax
+	jmp .Lende
+	CFI_ENDPROC
+ENDPROC(__copy_user_nocache)
+
+
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index a65fc6f..6ada723 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -56,38 +56,17 @@
 }
 EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
 
-static inline int notify_page_fault(enum die_val val, const char *str,
-			struct pt_regs *regs, long err, int trap, int sig)
+static inline int notify_page_fault(struct pt_regs *regs, long err)
 {
 	struct die_args args = {
 		.regs = regs,
-		.str = str,
+		.str = "page fault",
 		.err = err,
-		.trapnr = trap,
-		.signr = sig
+		.trapnr = 14,
+		.signr = SIGSEGV
 	};
-	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
-}
-
-void bust_spinlocks(int yes)
-{
-	int loglevel_save = console_loglevel;
-	if (yes) {
-		oops_in_progress = 1;
-	} else {
-#ifdef CONFIG_VT
-		unblank_screen();
-#endif
-		oops_in_progress = 0;
-		/*
-		 * OK, the message is on the console.  Now we call printk()
-		 * without oops_in_progress set so that printk will give klogd
-		 * a poke.  Hold onto your hats...
-		 */
-		console_loglevel = 15;		/* NMI oopser may have shut the console up */
-		printk(" ");
-		console_loglevel = loglevel_save;
-	}
+	return atomic_notifier_call_chain(&notify_page_fault_chain,
+	                                  DIE_PAGE_FAULT, &args);
 }
 
 /* Sometimes the CPU reports invalid exceptions on prefetch.
@@ -376,8 +355,7 @@
 			if (vmalloc_fault(address) >= 0)
 				return;
 		}
-		if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-						SIGSEGV) == NOTIFY_STOP)
+		if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
 			return;
 		/*
 		 * Don't take the mm semaphore here. If we fixup a prefetch
@@ -386,8 +364,7 @@
 		goto bad_area_nosemaphore;
 	}
 
-	if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-					SIGSEGV) == NOTIFY_STOP)
+	if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
 		return;
 
 	if (likely(regs->eflags & X86_EFLAGS_IF))
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 2968b90..ec31534 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -711,20 +711,30 @@
 extern int exception_trace, page_fault_trace;
 
 static ctl_table debug_table2[] = {
-	{ 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL,
-	  proc_dointvec },
-	{ 0, }
+	{
+		.ctl_name	= 99,
+		.procname	= "exception-trace",
+		.data		= &exception_trace,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec
+	},
+	{}
 }; 
 
 static ctl_table debug_root_table2[] = { 
-	{ .ctl_name = CTL_DEBUG, .procname = "debug", .mode = 0555, 
-	   .child = debug_table2 }, 
-	{ 0 }, 
+	{
+		.ctl_name = CTL_DEBUG,
+		.procname = "debug",
+		.mode = 0555,
+		.child = debug_table2
+	},
+	{}
 }; 
 
 static __init int x8664_sysctl_init(void)
 { 
-	register_sysctl_table(debug_root_table2, 1);
+	register_sysctl_table(debug_root_table2);
 	return 0;
 }
 __initcall(x8664_sysctl_init);
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 2ee2e00..41b8fb0 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -36,6 +36,8 @@
 cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly;
 
 int numa_off __initdata;
+unsigned long __initdata nodemap_addr;
+unsigned long __initdata nodemap_size;
 
 
 /*
@@ -52,34 +54,88 @@
 	int res = -1;
 	unsigned long addr, end;
 
-	if (shift >= 64)
-		return -1;
-	memset(memnodemap, 0xff, sizeof(memnodemap));
+	memset(memnodemap, 0xff, memnodemapsize);
 	for (i = 0; i < numnodes; i++) {
 		addr = nodes[i].start;
 		end = nodes[i].end;
 		if (addr >= end)
 			continue;
-		if ((end >> shift) >= NODEMAPSIZE)
+		if ((end >> shift) >= memnodemapsize)
 			return 0;
 		do {
 			if (memnodemap[addr >> shift] != 0xff)
 				return -1;
 			memnodemap[addr >> shift] = i;
-                       addr += (1UL << shift);
+			addr += (1UL << shift);
 		} while (addr < end);
 		res = 1;
 	} 
 	return res;
 }
 
+static int __init allocate_cachealigned_memnodemap(void)
+{
+	unsigned long pad, pad_addr;
+
+	memnodemap = memnode.embedded_map;
+	if (memnodemapsize <= 48)
+		return 0;
+
+	pad = L1_CACHE_BYTES - 1;
+	pad_addr = 0x8000;
+	nodemap_size = pad + memnodemapsize;
+	nodemap_addr = find_e820_area(pad_addr, end_pfn<<PAGE_SHIFT,
+				      nodemap_size);
+	if (nodemap_addr == -1UL) {
+		printk(KERN_ERR
+		       "NUMA: Unable to allocate Memory to Node hash map\n");
+		nodemap_addr = nodemap_size = 0;
+		return -1;
+	}
+	pad_addr = (nodemap_addr + pad) & ~pad;
+	memnodemap = phys_to_virt(pad_addr);
+
+	printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
+	       nodemap_addr, nodemap_addr + nodemap_size);
+	return 0;
+}
+
+/*
+ * The LSB of all start and end addresses in the node map is the value of the
+ * maximum possible shift.
+ */
+static int __init
+extract_lsb_from_nodes (const struct bootnode *nodes, int numnodes)
+{
+	int i, nodes_used = 0;
+	unsigned long start, end;
+	unsigned long bitfield = 0, memtop = 0;
+
+	for (i = 0; i < numnodes; i++) {
+		start = nodes[i].start;
+		end = nodes[i].end;
+		if (start >= end)
+			continue;
+		bitfield |= start;
+		nodes_used++;
+		if (end > memtop)
+			memtop = end;
+	}
+	if (nodes_used <= 1)
+		i = 63;
+	else
+		i = find_first_bit(&bitfield, sizeof(unsigned long)*8);
+	memnodemapsize = (memtop >> i)+1;
+	return i;
+}
+
 int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
 {
-	int shift = 20;
+	int shift;
 
-	while (populate_memnodemap(nodes, numnodes, shift + 1) >= 0)
-		shift++;
-
+	shift = extract_lsb_from_nodes(nodes, numnodes);
+	if (allocate_cachealigned_memnodemap())
+		return -1;
 	printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
 		shift);
 
@@ -216,31 +272,113 @@
 }
 
 #ifdef CONFIG_NUMA_EMU
+/* Numa emulation */
 int numa_fake __initdata = 0;
 
-/* Numa emulation */
+/*
+ * This function is used to find out if the start and end correspond to
+ * different zones.
+ */
+int zone_cross_over(unsigned long start, unsigned long end)
+{
+	if ((start < (MAX_DMA32_PFN << PAGE_SHIFT)) &&
+			(end >= (MAX_DMA32_PFN << PAGE_SHIFT)))
+		return 1;
+	return 0;
+}
+
 static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
 {
- 	int i;
+ 	int i, big;
  	struct bootnode nodes[MAX_NUMNODES];
- 	unsigned long sz = ((end_pfn - start_pfn)<<PAGE_SHIFT) / numa_fake;
+ 	unsigned long sz, old_sz;
+	unsigned long hole_size;
+	unsigned long start, end;
+	unsigned long max_addr = (end_pfn << PAGE_SHIFT);
+
+	start = (start_pfn << PAGE_SHIFT);
+	hole_size = e820_hole_size(start, max_addr);
+	sz = (max_addr - start - hole_size) / numa_fake;
 
  	/* Kludge needed for the hash function */
- 	if (hweight64(sz) > 1) {
- 		unsigned long x = 1;
- 		while ((x << 1) < sz)
- 			x <<= 1;
- 		if (x < sz/2)
- 			printk(KERN_ERR "Numa emulation unbalanced. Complain to maintainer\n");
- 		sz = x;
- 	}
 
+	old_sz = sz;
+	/*
+	 * Round down to the nearest FAKE_NODE_MIN_SIZE.
+	 */
+	sz &= FAKE_NODE_MIN_HASH_MASK;
+
+	/*
+	 * We ensure that each node is at least 64MB big.  Smaller than this
+	 * size can cause VM hiccups.
+	 */
+	if (sz == 0) {
+		printk(KERN_INFO "Not enough memory for %d nodes.  Reducing "
+				"the number of nodes\n", numa_fake);
+		numa_fake = (max_addr - start - hole_size) / FAKE_NODE_MIN_SIZE;
+		printk(KERN_INFO "Number of fake nodes will be = %d\n",
+				numa_fake);
+		sz = FAKE_NODE_MIN_SIZE;
+	}
+	/*
+	 * Find out how many nodes can get an extra NODE_MIN_SIZE granule.
+	 * This logic ensures the extra memory gets distributed among as many
+	 * nodes as possible (as compared to one single node getting all that
+	 * extra memory.
+	 */
+	big = ((old_sz - sz) * numa_fake) / FAKE_NODE_MIN_SIZE;
+	printk(KERN_INFO "Fake node Size: %luMB hole_size: %luMB big nodes: "
+			"%d\n",
+			(sz >> 20), (hole_size >> 20), big);
  	memset(&nodes,0,sizeof(nodes));
+	end = start;
  	for (i = 0; i < numa_fake; i++) {
- 		nodes[i].start = (start_pfn<<PAGE_SHIFT) + i*sz;
+		/*
+		 * In case we are not able to allocate enough memory for all
+		 * the nodes, we reduce the number of fake nodes.
+		 */
+		if (end >= max_addr) {
+			numa_fake = i - 1;
+			break;
+		}
+ 		start = nodes[i].start = end;
+		/*
+		 * Final node can have all the remaining memory.
+		 */
  		if (i == numa_fake-1)
- 			sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start;
- 		nodes[i].end = nodes[i].start + sz;
+ 			sz = max_addr - start;
+ 		end = nodes[i].start + sz;
+		/*
+		 * Fir "big" number of nodes get extra granule.
+		 */
+		if (i < big)
+			end += FAKE_NODE_MIN_SIZE;
+		/*
+		 * Iterate over the range to ensure that this node gets at
+		 * least sz amount of RAM (excluding holes)
+		 */
+		while ((end - start - e820_hole_size(start, end)) < sz) {
+			end += FAKE_NODE_MIN_SIZE;
+			if (end >= max_addr)
+				break;
+		}
+		/*
+		 * Look at the next node to make sure there is some real memory
+		 * to map.  Bad things happen when the only memory present
+		 * in a zone on a fake node is IO hole.
+		 */
+		while (e820_hole_size(end, end + FAKE_NODE_MIN_SIZE) > 0) {
+			if (zone_cross_over(start, end + sz)) {
+				end = (MAX_DMA32_PFN << PAGE_SHIFT);
+				break;
+			}
+			if (end >= max_addr)
+				break;
+			end += FAKE_NODE_MIN_SIZE;
+		}
+		if (end > max_addr)
+			end = max_addr;
+		nodes[i].end = end;
  		printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n",
  		       i,
  		       nodes[i].start, nodes[i].end,
@@ -290,6 +428,7 @@
 	       end_pfn << PAGE_SHIFT); 
 		/* setup dummy node covering all memory */ 
 	memnode_shift = 63; 
+	memnodemap = memnode.embedded_map;
 	memnodemap[0] = 0;
 	nodes_clear(node_online_map);
 	node_set_online(0);
@@ -321,20 +460,6 @@
 	return pages;
 } 
 
-#ifdef CONFIG_SPARSEMEM
-static void __init arch_sparse_init(void)
-{
-	int i;
-
-	for_each_online_node(i)
-		memory_present(i, node_start_pfn(i), node_end_pfn(i));
-
-	sparse_init();
-}
-#else
-#define arch_sparse_init() do {} while (0)
-#endif
-
 void __init paging_init(void)
 { 
 	int i;
@@ -344,7 +469,8 @@
 	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
 	max_zone_pfns[ZONE_NORMAL] = end_pfn;
 
-	arch_sparse_init();
+	sparse_memory_present_with_active_regions(MAX_NUMNODES);
+	sparse_init();
 
 	for_each_online_node(i) {
 		setup_node_zones(i); 
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
index ccb91dd..65c5eaa 100644
--- a/arch/x86_64/mm/pageattr.c
+++ b/arch/x86_64/mm/pageattr.c
@@ -107,6 +107,7 @@
 	pud_t *pud;
 	pmd_t *pmd;
 	pte_t large_pte;
+	unsigned long pfn;
 
 	pgd = pgd_offset_k(address);
 	BUG_ON(pgd_none(*pgd));
@@ -114,7 +115,8 @@
 	BUG_ON(pud_none(*pud));
 	pmd = pmd_offset(pud, address);
 	BUG_ON(pmd_val(*pmd) & _PAGE_PSE);
-	large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, ref_prot);
+	pfn = (__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT;
+	large_pte = pfn_pte(pfn, ref_prot);
 	large_pte = pte_mkhuge(large_pte);
 	set_pte((pte_t *)pmd, large_pte);
 }      
diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile
index 149aba0..c9eddc8 100644
--- a/arch/x86_64/pci/Makefile
+++ b/arch/x86_64/pci/Makefile
@@ -11,7 +11,7 @@
 obj-$(CONFIG_ACPI)	+= acpi.o
 obj-y			+= legacy.o irq.o common.o early.o
 # mmconfig has a 64bit special
-obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o
+obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o mmconfig-shared.o
 
 obj-$(CONFIG_NUMA)	+= k8-bus.o
 
@@ -24,3 +24,4 @@
 i386-y  += ../../i386/pci/i386.o
 init-y += ../../i386/pci/init.o
 early-y += ../../i386/pci/early.o
+mmconfig-shared-y += ../../i386/pci/mmconfig-shared.o
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index faabb6e..65d8273 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -13,16 +13,6 @@
 
 #include "pci.h"
 
-/* aperture is up to 256MB but BIOS may reserve less */
-#define MMCONFIG_APER_MIN	(2 * 1024*1024)
-#define MMCONFIG_APER_MAX	(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*MAX_CHECK_BUS);
-
 /* Static virtual mapping of the MMCONFIG aperture */
 struct mmcfg_virt {
 	struct acpi_mcfg_allocation *cfg;
@@ -32,30 +22,17 @@
 
 static char __iomem *get_virt(unsigned int seg, unsigned bus)
 {
-	int cfg_num = -1;
 	struct acpi_mcfg_allocation *cfg;
+	int cfg_num;
 
-	while (1) {
-		++cfg_num;
-		if (cfg_num >= pci_mmcfg_config_num)
-			break;
+	for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
 		cfg = pci_mmcfg_virt[cfg_num].cfg;
-		if (cfg->pci_segment != seg)
-			continue;
-		if ((cfg->start_bus_number <= bus) &&
+		if (cfg->pci_segment == seg &&
+		    (cfg->start_bus_number <= bus) &&
 		    (cfg->end_bus_number >= bus))
 			return pci_mmcfg_virt[cfg_num].virt;
 	}
 
-	/* Handle more broken MCFG tables on Asus etc.
-	   They only contain a single entry for bus 0-0. Assume
- 	   this applies to all busses. */
-	cfg = &pci_mmcfg_config[0];
-	if (pci_mmcfg_config_num == 1 &&
-		cfg->pci_segment == 0 &&
-		(cfg->start_bus_number | cfg->end_bus_number) == 0)
-		return pci_mmcfg_virt[0].virt;
-
 	/* Fall back to type 0 */
 	return NULL;
 }
@@ -63,8 +40,8 @@
 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
 {
 	char __iomem *addr;
-	if (seg == 0 && bus < MAX_CHECK_BUS &&
-		test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
+	if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
+		test_bit(32*bus + PCI_SLOT(devfn), pci_mmcfg_fallback_slots))
 		return NULL;
 	addr = get_virt(seg, bus);
 	if (!addr)
@@ -135,79 +112,46 @@
 	.write =	pci_mmcfg_write,
 };
 
-/* K8 systems have some devices (typically in the builtin northbridge)
-   that are only accessible using type1
-   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. */
-static __init void unreachable_devices(void)
+static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
 {
-	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;
+	void __iomem *addr;
+	u32 size;
 
-			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 %02x:%02x\n", k, i);
-			}
-		}
+	size = (cfg->end_bus_number + 1) << 20;
+	addr = ioremap_nocache(cfg->address, size);
+	if (addr) {
+		printk(KERN_INFO "PCI: Using MMCONFIG at %Lx - %Lx\n",
+		       cfg->address, cfg->address + size - 1);
 	}
+	return addr;
 }
 
-void __init pci_mmcfg_init(int type)
+int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+				    unsigned int devfn)
+{
+	return pci_dev_base(seg, bus, devfn) != NULL;
+}
+
+int __init pci_mmcfg_arch_init(void)
 {
 	int i;
-
-	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
-		return;
-
-	acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
-	if ((pci_mmcfg_config_num == 0) ||
-	    (pci_mmcfg_config == NULL) ||
-	    (pci_mmcfg_config[0].address == 0))
-		return;
-
-	/* Only do this check when type 1 works. If it doesn't work
-           assume we run on a Mac and always use MCFG */
-	if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address,
-			pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
-			E820_RESERVED)) {
-		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n",
-				(unsigned long)pci_mmcfg_config[0].address);
-		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
-		return;
-	}
-
-	pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
+	pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) *
+				 pci_mmcfg_config_num, GFP_KERNEL);
 	if (pci_mmcfg_virt == NULL) {
 		printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n");
-		return;
+		return 0;
 	}
+
 	for (i = 0; i < pci_mmcfg_config_num; ++i) {
 		pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
-		pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].address,
-							 MMCONFIG_APER_MAX);
+		pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]);
 		if (!pci_mmcfg_virt[i].virt) {
 			printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
 					"segment %d\n",
 				pci_mmcfg_config[i].pci_segment);
-			return;
+			return 0;
 		}
-		printk(KERN_INFO "PCI: Using MMCONFIG at %lx\n",
-			(unsigned long)pci_mmcfg_config[i].address);
 	}
-
-	unreachable_devices();
-
 	raw_pci_ops = &pci_mmcfg;
-	pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+	return 1;
 }
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 2e74cb0..7fbb44b 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -7,6 +7,10 @@
 	bool
 	default n
 
+config ZONE_DMA
+	bool
+	default y
+
 config XTENSA
 	bool
 	default y
@@ -42,6 +46,9 @@
 	bool
 	default n
 
+config NO_IOPORT
+	def_bool y
+
 source "init/Kconfig"
 
 menu "Processor type and features"
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index b6374c0..1ecf671 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -78,7 +78,7 @@
 
 /* Command line specified as configuration option. */
 
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 #ifdef CONFIG_CMDLINE_BOOL
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
@@ -253,8 +253,8 @@
 	extern int mem_reserve(unsigned long, unsigned long, int);
 	extern void bootmem_init(void);
 
-	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 	*cmdline_p = command_line;
 
 	/* Reserve some memory regions */
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index a350431..22949be 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -38,15 +38,6 @@
 unsigned int last_ccount_stamp;
 static long last_rtc_update = 0;
 
-/*
- * Scheduler clock - returns current tim in nanosec units.
- */
-
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies * (1000000000 / HZ);
-}
-
 static irqreturn_t timer_interrupt(int irq, void *dev_id);
 static struct irqaction timer_irqaction = {
 	.handler =	timer_interrupt,
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index a36c104..ab63700 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -203,10 +203,12 @@
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
 
+#ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(4096);
   __initramfs_start =.;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+#endif
 
   /* We need this dummy segment here */
 
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched
index 903f0d3..7e803fc8 100644
--- a/block/Kconfig.iosched
+++ b/block/Kconfig.iosched
@@ -16,10 +16,10 @@
 	tristate "Anticipatory I/O scheduler"
 	default y
 	---help---
-	  The anticipatory I/O scheduler is the default disk scheduler. It is
-	  generally a good choice for most environments, but is quite large and
-	  complex when compared to the deadline I/O scheduler, it can also be
-	  slower in some cases especially some database loads.
+	  The anticipatory I/O scheduler is generally a good choice for most
+	  environments, but is quite large and complex when compared to the
+	  deadline I/O scheduler, it can also be slower in some cases
+	  especially some database loads.
 
 config IOSCHED_DEADLINE
 	tristate "Deadline I/O scheduler"
@@ -38,6 +38,7 @@
 	  The CFQ I/O scheduler tries to distribute bandwidth equally
 	  among all processes in the system. It should provide a fair
 	  working environment, suitable for desktop systems.
+	  This is the default I/O scheduler.
 
 choice
 	prompt "Default I/O scheduler"
diff --git a/block/blktrace.c b/block/blktrace.c
index d3679dd..3f0e7c3 100644
--- a/block/blktrace.c
+++ b/block/blktrace.c
@@ -264,7 +264,7 @@
 	return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
 }
 
-static struct file_operations blk_dropped_fops = {
+static const struct file_operations blk_dropped_fops = {
 	.owner =	THIS_MODULE,
 	.open =		blk_dropped_open,
 	.read =		blk_dropped_read,
@@ -363,10 +363,9 @@
 	if (!bt->dropped_file)
 		goto err;
 
-	bt->rchan = relay_open("trace", dir, buts.buf_size, buts.buf_nr, &blk_relay_callbacks);
+	bt->rchan = relay_open("trace", dir, buts.buf_size, buts.buf_nr, &blk_relay_callbacks, bt);
 	if (!bt->rchan)
 		goto err;
-	bt->rchan->private_data = bt;
 
 	bt->act_mask = buts.act_mask;
 	if (!bt->act_mask)
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 07b7062..b6491c0 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -146,9 +146,9 @@
 	/* fifo list of requests in sort_list */
 	struct list_head fifo;
 
-	unsigned long slice_start;
 	unsigned long slice_end;
-	unsigned long slice_left;
+	unsigned long service_last;
+	long slice_resid;
 
 	/* number of requests that are on the dispatch list */
 	int on_dispatch[2];
@@ -162,15 +162,16 @@
 };
 
 enum cfqq_state_flags {
-	CFQ_CFQQ_FLAG_on_rr = 0,
-	CFQ_CFQQ_FLAG_wait_request,
-	CFQ_CFQQ_FLAG_must_alloc,
-	CFQ_CFQQ_FLAG_must_alloc_slice,
-	CFQ_CFQQ_FLAG_must_dispatch,
-	CFQ_CFQQ_FLAG_fifo_expire,
-	CFQ_CFQQ_FLAG_idle_window,
-	CFQ_CFQQ_FLAG_prio_changed,
-	CFQ_CFQQ_FLAG_queue_new,
+	CFQ_CFQQ_FLAG_on_rr = 0,	/* on round-robin busy list */
+	CFQ_CFQQ_FLAG_wait_request,	/* waiting for a request */
+	CFQ_CFQQ_FLAG_must_alloc,	/* must be allowed rq alloc */
+	CFQ_CFQQ_FLAG_must_alloc_slice,	/* per-slice must_alloc flag */
+	CFQ_CFQQ_FLAG_must_dispatch,	/* must dispatch, even if expired */
+	CFQ_CFQQ_FLAG_fifo_expire,	/* FIFO checked in this slice */
+	CFQ_CFQQ_FLAG_idle_window,	/* slice idling enabled */
+	CFQ_CFQQ_FLAG_prio_changed,	/* task priority has changed */
+	CFQ_CFQQ_FLAG_queue_new,	/* queue never been serviced */
+	CFQ_CFQQ_FLAG_slice_new,	/* no requests dispatched in slice */
 };
 
 #define CFQ_CFQQ_FNS(name)						\
@@ -196,6 +197,7 @@
 CFQ_CFQQ_FNS(idle_window);
 CFQ_CFQQ_FNS(prio_changed);
 CFQ_CFQQ_FNS(queue_new);
+CFQ_CFQQ_FNS(slice_new);
 #undef CFQ_CFQQ_FNS
 
 static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
@@ -231,6 +233,50 @@
 }
 
 /*
+ * Scale schedule slice based on io priority. Use the sync time slice only
+ * if a queue is marked sync and has sync io queued. A sync queue with async
+ * io only, should not get full sync slice length.
+ */
+static inline int
+cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+	const int base_slice = cfqd->cfq_slice[cfq_cfqq_sync(cfqq)];
+
+	WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR);
+
+	return base_slice + (base_slice/CFQ_SLICE_SCALE * (4 - cfqq->ioprio));
+}
+
+static inline void
+cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+	cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies;
+	cfqq->slice_end += cfqq->slice_resid;
+
+	/*
+	 * Don't carry over residual for more than one slice, we only want
+	 * to slightly correct the fairness. Carrying over forever would
+	 * easily introduce oscillations.
+	 */
+	cfqq->slice_resid = 0;
+}
+
+/*
+ * We need to wrap this check in cfq_cfqq_slice_new(), since ->slice_end
+ * isn't valid until the first request from the dispatch is activated
+ * and the slice time set.
+ */
+static inline int cfq_slice_used(struct cfq_queue *cfqq)
+{
+	if (cfq_cfqq_slice_new(cfqq))
+		return 0;
+	if (time_before(jiffies, cfqq->slice_end))
+		return 0;
+
+	return 1;
+}
+
+/*
  * Lifted from AS - choose which of rq1 and rq2 that is best served now.
  * We choose the request that is closest to the head right now. Distance
  * behind the head is penalized and only allowed to a certain extent.
@@ -355,9 +401,14 @@
 static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
 {
 	struct cfq_data *cfqd = cfqq->cfqd;
-	struct list_head *list;
+	struct list_head *list, *n;
+	struct cfq_queue *__cfqq;
 
-	BUG_ON(!cfq_cfqq_on_rr(cfqq));
+	/*
+	 * Resorting requires the cfqq to be on the RR list already.
+	 */
+	if (!cfq_cfqq_on_rr(cfqq))
+		return;
 
 	list_del(&cfqq->cfq_list);
 
@@ -379,15 +430,13 @@
 			list = &cfqd->rr_list[cfqq->ioprio];
 	}
 
-	/*
-	 * If this queue was preempted or is new (never been serviced), let
-	 * it be added first for fairness but beind other new queues.
-	 * Otherwise, just add to the back  of the list.
-	 */
 	if (preempted || cfq_cfqq_queue_new(cfqq)) {
-		struct list_head *n = list;
-		struct cfq_queue *__cfqq;
-
+		/*
+		 * If this queue was preempted or is new (never been serviced),
+		 * let it be added first for fairness but beind other new
+		 * queues.
+		 */
+		n = list;
 		while (n->next != list) {
 			__cfqq = list_entry_cfqq(n->next);
 			if (!cfq_cfqq_queue_new(__cfqq))
@@ -395,11 +444,32 @@
 
 			n = n->next;
 		}
+		list_add_tail(&cfqq->cfq_list, n);
+	} else if (!cfq_cfqq_class_sync(cfqq)) {
+		/*
+		 * async queue always goes to the end. this wont be overly
+		 * unfair to writes, as the sort of the sync queue wont be
+		 * allowed to pass the async queue again.
+		 */
+		list_add_tail(&cfqq->cfq_list, list);
+	} else {
+		/*
+		 * sort by last service, but don't cross a new or async
+		 * queue. we don't cross a new queue because it hasn't been
+		 * service before, and we don't cross an async queue because
+		 * it gets added to the end on expire.
+		 */
+		n = list;
+		while ((n = n->prev) != list) {
+			struct cfq_queue *__cfqq = list_entry_cfqq(n);
 
-		list = n;
+			if (!cfq_cfqq_class_sync(cfqq) || !__cfqq->service_last)
+				break;
+			if (time_before(__cfqq->service_last, cfqq->service_last))
+				break;
+		}
+		list_add(&cfqq->cfq_list, n);
 	}
-
-	list_add_tail(&cfqq->cfq_list, list);
 }
 
 /*
@@ -604,11 +674,10 @@
 		 */
 		del_timer(&cfqd->idle_class_timer);
 
-		cfqq->slice_start = jiffies;
 		cfqq->slice_end = 0;
-		cfqq->slice_left = 0;
 		cfq_clear_cfqq_must_alloc_slice(cfqq);
 		cfq_clear_cfqq_fifo_expire(cfqq);
+		cfq_mark_cfqq_slice_new(cfqq);
 	}
 
 	cfqd->active_queue = cfqq;
@@ -619,16 +688,11 @@
  */
 static void
 __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
-		    int preempted)
+		    int preempted, int timed_out)
 {
-	unsigned long now = jiffies;
-
 	if (cfq_cfqq_wait_request(cfqq))
 		del_timer(&cfqd->idle_slice_timer);
 
-	if (!preempted && !cfq_cfqq_dispatched(cfqq))
-		cfq_schedule_dispatch(cfqd);
-
 	cfq_clear_cfqq_must_dispatch(cfqq);
 	cfq_clear_cfqq_wait_request(cfqq);
 	cfq_clear_cfqq_queue_new(cfqq);
@@ -637,13 +701,10 @@
 	 * store what was left of this slice, if the queue idled out
 	 * or was preempted
 	 */
-	if (time_after(cfqq->slice_end, now))
-		cfqq->slice_left = cfqq->slice_end - now;
-	else
-		cfqq->slice_left = 0;
+	if (timed_out && !cfq_cfqq_slice_new(cfqq))
+		cfqq->slice_resid = cfqq->slice_end - jiffies;
 
-	if (cfq_cfqq_on_rr(cfqq))
-		cfq_resort_rr_list(cfqq, preempted);
+	cfq_resort_rr_list(cfqq, preempted);
 
 	if (cfqq == cfqd->active_queue)
 		cfqd->active_queue = NULL;
@@ -656,12 +717,13 @@
 	cfqd->dispatch_slice = 0;
 }
 
-static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted)
+static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted,
+				     int timed_out)
 {
 	struct cfq_queue *cfqq = cfqd->active_queue;
 
 	if (cfqq)
-		__cfq_slice_expired(cfqd, cfqq, preempted);
+		__cfq_slice_expired(cfqd, cfqq, preempted, timed_out);
 }
 
 /*
@@ -758,14 +820,13 @@
 
 #define CIC_SEEKY(cic) ((cic)->seek_mean > (128 * 1024))
 
-static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
-
+static int cfq_arm_slice_timer(struct cfq_data *cfqd)
 {
+	struct cfq_queue *cfqq = cfqd->active_queue;
 	struct cfq_io_context *cic;
 	unsigned long sl;
 
 	WARN_ON(!RB_EMPTY_ROOT(&cfqq->sort_list));
-	WARN_ON(cfqq != cfqd->active_queue);
 
 	/*
 	 * idle is disabled, either manually or by past process history
@@ -822,41 +883,21 @@
 
 	if (cfq_cfqq_fifo_expire(cfqq))
 		return NULL;
+
+	cfq_mark_cfqq_fifo_expire(cfqq);
+
 	if (list_empty(&cfqq->fifo))
 		return NULL;
 
 	fifo = cfq_cfqq_class_sync(cfqq);
 	rq = rq_entry_fifo(cfqq->fifo.next);
 
-	if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) {
-		cfq_mark_cfqq_fifo_expire(cfqq);
+	if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo]))
 		return rq;
-	}
 
 	return NULL;
 }
 
-/*
- * Scale schedule slice based on io priority. Use the sync time slice only
- * if a queue is marked sync and has sync io queued. A sync queue with async
- * io only, should not get full sync slice length.
- */
-static inline int
-cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
-{
-	const int base_slice = cfqd->cfq_slice[cfq_cfqq_sync(cfqq)];
-
-	WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR);
-
-	return base_slice + (base_slice/CFQ_SLICE_SCALE * (4 - cfqq->ioprio));
-}
-
-static inline void
-cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
-{
-	cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies;
-}
-
 static inline int
 cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
@@ -872,7 +913,6 @@
  */
 static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
 {
-	unsigned long now = jiffies;
 	struct cfq_queue *cfqq;
 
 	cfqq = cfqd->active_queue;
@@ -882,7 +922,7 @@
 	/*
 	 * slice has expired
 	 */
-	if (!cfq_cfqq_must_dispatch(cfqq) && time_after(now, cfqq->slice_end))
+	if (!cfq_cfqq_must_dispatch(cfqq) && cfq_slice_used(cfqq))
 		goto expire;
 
 	/*
@@ -891,16 +931,16 @@
 	 */
 	if (!RB_EMPTY_ROOT(&cfqq->sort_list))
 		goto keep_queue;
-	else if (cfq_cfqq_dispatched(cfqq)) {
+	else if (cfq_cfqq_slice_new(cfqq) || cfq_cfqq_dispatched(cfqq)) {
 		cfqq = NULL;
 		goto keep_queue;
 	} else if (cfq_cfqq_class_sync(cfqq)) {
-		if (cfq_arm_slice_timer(cfqd, cfqq))
+		if (cfq_arm_slice_timer(cfqd))
 			return NULL;
 	}
 
 expire:
-	cfq_slice_expired(cfqd, 0);
+	cfq_slice_expired(cfqd, 0, 0);
 new_queue:
 	cfqq = cfq_set_active_queue(cfqd);
 keep_queue:
@@ -943,20 +983,15 @@
 	} while (dispatched < max_dispatch);
 
 	/*
-	 * if slice end isn't set yet, set it.
-	 */
-	if (!cfqq->slice_end)
-		cfq_set_prio_slice(cfqd, cfqq);
-
-	/*
 	 * expire an async queue immediately if it has used up its slice. idle
 	 * queue always expire after 1 dispatch round.
 	 */
 	if ((!cfq_cfqq_sync(cfqq) &&
 	    cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) ||
-	    cfq_class_idle(cfqq) ||
-	    !cfq_cfqq_idle_window(cfqq))
-		cfq_slice_expired(cfqd, 0);
+	    cfq_class_idle(cfqq)) {
+		cfqq->slice_end = jiffies + 1;
+		cfq_slice_expired(cfqd, 0, 0);
+	}
 
 	return dispatched;
 }
@@ -991,7 +1026,7 @@
 	dispatched += cfq_forced_dispatch_cfqqs(&cfqd->cur_rr);
 	dispatched += cfq_forced_dispatch_cfqqs(&cfqd->idle_rr);
 
-	cfq_slice_expired(cfqd, 0);
+	cfq_slice_expired(cfqd, 0, 0);
 
 	BUG_ON(cfqd->busy_queues);
 
@@ -1022,6 +1057,14 @@
 		if (prev_cfqq == cfqq)
 			break;
 
+		/*
+		 * So we have dispatched before in this round, if the
+		 * next queue has idling enabled (must be sync), don't
+		 * allow it service until the previous have continued.
+		 */
+		if (cfqd->rq_in_driver && cfq_cfqq_idle_window(cfqq))
+			break;
+
 		cfq_clear_cfqq_must_dispatch(cfqq);
 		cfq_clear_cfqq_wait_request(cfqq);
 		del_timer(&cfqd->idle_slice_timer);
@@ -1031,14 +1074,6 @@
 			max_dispatch = 1;
 
 		dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
-
-		/*
-		 * If the dispatch cfqq has idling enabled and is still
-		 * the active queue, break out.
-		 */
-		if (cfq_cfqq_idle_window(cfqq) && cfqd->active_queue)
-			break;
-
 		prev_cfqq = cfqq;
 	}
 
@@ -1064,8 +1099,10 @@
 	BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
 	BUG_ON(cfq_cfqq_on_rr(cfqq));
 
-	if (unlikely(cfqd->active_queue == cfqq))
-		__cfq_slice_expired(cfqd, cfqq, 0);
+	if (unlikely(cfqd->active_queue == cfqq)) {
+		__cfq_slice_expired(cfqd, cfqq, 0, 0);
+		cfq_schedule_dispatch(cfqd);
+	}
 
 	/*
 	 * it's on the empty list and still hashed
@@ -1120,8 +1157,10 @@
 
 static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
-	if (unlikely(cfqq == cfqd->active_queue))
-		__cfq_slice_expired(cfqd, cfqq, 0);
+	if (unlikely(cfqq == cfqd->active_queue)) {
+		__cfq_slice_expired(cfqd, cfqq, 0, 0);
+		cfq_schedule_dispatch(cfqd);
+	}
 
 	cfq_put_queue(cfqq);
 }
@@ -1238,9 +1277,7 @@
 	cfqq->org_ioprio = cfqq->ioprio;
 	cfqq->org_ioprio_class = cfqq->ioprio_class;
 
-	if (cfq_cfqq_on_rr(cfqq))
-		cfq_resort_rr_list(cfqq, 0);
-
+	cfq_resort_rr_list(cfqq, 0);
 	cfq_clear_cfqq_prio_changed(cfqq);
 }
 
@@ -1332,10 +1369,7 @@
 		hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
 		atomic_set(&cfqq->ref, 0);
 		cfqq->cfqd = cfqd;
-		/*
-		 * set ->slice_left to allow preemption for a new process
-		 */
-		cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
+
 		cfq_mark_cfqq_idle_window(cfqq);
 		cfq_mark_cfqq_prio_changed(cfqq);
 		cfq_mark_cfqq_queue_new(cfqq);
@@ -1471,22 +1505,8 @@
 static void
 cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
 {
-	unsigned long elapsed, ttime;
-
-	/*
-	 * if this context already has stuff queued, thinktime is from
-	 * last queue not last end
-	 */
-#if 0
-	if (time_after(cic->last_end_request, cic->last_queue))
-		elapsed = jiffies - cic->last_end_request;
-	else
-		elapsed = jiffies - cic->last_queue;
-#else
-		elapsed = jiffies - cic->last_end_request;
-#endif
-
-	ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle);
+	unsigned long elapsed = jiffies - cic->last_end_request;
+	unsigned long ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle);
 
 	cic->ttime_samples = (7*cic->ttime_samples + 256) / 8;
 	cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8;
@@ -1546,7 +1566,6 @@
 		cfq_clear_cfqq_idle_window(cfqq);
 }
 
-
 /*
  * Check if new_cfqq should preempt the currently active queue. Return 0 for
  * no or if we aren't sure, a 1 will cause a preempt.
@@ -1568,11 +1587,6 @@
 	if (!cfq_cfqq_wait_request(new_cfqq))
 		return 0;
 	/*
-	 * if it doesn't have slice left, forget it
-	 */
-	if (new_cfqq->slice_left < cfqd->cfq_slice_idle)
-		return 0;
-	/*
 	 * if the new request is sync, but the currently running queue is
 	 * not, let the sync request have priority.
 	 */
@@ -1594,10 +1608,7 @@
  */
 static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
-	cfq_slice_expired(cfqd, 1);
-
-	if (!cfqq->slice_left)
-		cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2;
+	cfq_slice_expired(cfqd, 1, 1);
 
 	/*
 	 * Put the new queue at the front of the of the current list,
@@ -1606,7 +1617,8 @@
 	BUG_ON(!cfq_cfqq_on_rr(cfqq));
 	list_move(&cfqq->cfq_list, &cfqd->cur_rr);
 
-	cfqq->slice_end = cfqq->slice_left + jiffies;
+	cfqq->slice_end = 0;
+	cfq_mark_cfqq_slice_new(cfqq);
 }
 
 /*
@@ -1639,7 +1651,7 @@
 		 */
 		if (cic == cfqd->active_cic &&
 		    del_timer(&cfqd->idle_slice_timer)) {
-			cfq_slice_expired(cfqd, 0);
+			cfq_slice_expired(cfqd, 0, 0);
 			blk_start_queueing(cfqd->queue);
 		}
 		return;
@@ -1649,7 +1661,6 @@
 	cfq_update_io_seektime(cic, rq);
 	cfq_update_idle_window(cfqd, cfqq, cic);
 
-	cic->last_queue = jiffies;
 	cic->last_request_pos = rq->sector + rq->nr_sectors;
 
 	if (cfqq == cfqd->active_queue) {
@@ -1702,12 +1713,12 @@
 	WARN_ON(!cfqq->on_dispatch[sync]);
 	cfqd->rq_in_driver--;
 	cfqq->on_dispatch[sync]--;
+	cfqq->service_last = now;
 
 	if (!cfq_class_idle(cfqq))
 		cfqd->last_end_request = now;
 
-	if (!cfq_cfqq_dispatched(cfqq) && cfq_cfqq_on_rr(cfqq))
-		cfq_resort_rr_list(cfqq, 0);
+	cfq_resort_rr_list(cfqq, 0);
 
 	if (sync)
 		RQ_CIC(rq)->last_end_request = now;
@@ -1717,10 +1728,14 @@
 	 * or if we want to idle in case it has no pending requests.
 	 */
 	if (cfqd->active_queue == cfqq) {
-		if (time_after(now, cfqq->slice_end))
-			cfq_slice_expired(cfqd, 0);
+		if (cfq_cfqq_slice_new(cfqq)) {
+			cfq_set_prio_slice(cfqd, cfqq);
+			cfq_clear_cfqq_slice_new(cfqq);
+		}
+		if (cfq_slice_used(cfqq))
+			cfq_slice_expired(cfqd, 0, 1);
 		else if (sync && RB_EMPTY_ROOT(&cfqq->sort_list)) {
-			if (!cfq_arm_slice_timer(cfqd, cfqq))
+			if (!cfq_arm_slice_timer(cfqd))
 				cfq_schedule_dispatch(cfqd);
 		}
 	}
@@ -1757,8 +1772,7 @@
 	/*
 	 * refile between round-robin lists if we moved the priority class
 	 */
-	if ((ioprio_class != cfqq->ioprio_class || ioprio != cfqq->ioprio) &&
-	    cfq_cfqq_on_rr(cfqq))
+	if ((ioprio_class != cfqq->ioprio_class || ioprio != cfqq->ioprio))
 		cfq_resort_rr_list(cfqq, 0);
 }
 
@@ -1893,16 +1907,17 @@
 	struct cfq_data *cfqd = (struct cfq_data *) data;
 	struct cfq_queue *cfqq;
 	unsigned long flags;
+	int timed_out = 1;
 
 	spin_lock_irqsave(cfqd->queue->queue_lock, flags);
 
 	if ((cfqq = cfqd->active_queue) != NULL) {
-		unsigned long now = jiffies;
+		timed_out = 0;
 
 		/*
 		 * expired
 		 */
-		if (time_after(now, cfqq->slice_end))
+		if (cfq_slice_used(cfqq))
 			goto expire;
 
 		/*
@@ -1921,7 +1936,7 @@
 		}
 	}
 expire:
-	cfq_slice_expired(cfqd, 0);
+	cfq_slice_expired(cfqd, 0, timed_out);
 out_kick:
 	cfq_schedule_dispatch(cfqd);
 out_cont:
@@ -1967,7 +1982,7 @@
 	spin_lock_irq(q->queue_lock);
 
 	if (cfqd->active_queue)
-		__cfq_slice_expired(cfqd, cfqd->active_queue, 0);
+		__cfq_slice_expired(cfqd, cfqd->active_queue, 0, 0);
 
 	while (!list_empty(&cfqd->cic_list)) {
 		struct cfq_io_context *cic = list_entry(cfqd->cic_list.next,
diff --git a/block/elevator.c b/block/elevator.c
index f6dafa8..25f6ef2 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -269,6 +269,22 @@
 
 EXPORT_SYMBOL(elevator_exit);
 
+static void elv_activate_rq(request_queue_t *q, struct request *rq)
+{
+	elevator_t *e = q->elevator;
+
+	if (e->ops->elevator_activate_req_fn)
+		e->ops->elevator_activate_req_fn(q, rq);
+}
+
+static void elv_deactivate_rq(request_queue_t *q, struct request *rq)
+{
+	elevator_t *e = q->elevator;
+
+	if (e->ops->elevator_deactivate_req_fn)
+		e->ops->elevator_deactivate_req_fn(q, rq);
+}
+
 static inline void __elv_rqhash_del(struct request *rq)
 {
 	hlist_del_init(&rq->hash);
@@ -397,6 +413,8 @@
 	list_for_each_prev(entry, &q->queue_head) {
 		struct request *pos = list_entry_rq(entry);
 
+		if (rq_data_dir(rq) != rq_data_dir(pos))
+			break;
 		if (pos->cmd_flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED))
 			break;
 		if (rq->sector >= boundary) {
@@ -498,16 +516,14 @@
 
 void elv_requeue_request(request_queue_t *q, struct request *rq)
 {
-	elevator_t *e = q->elevator;
-
 	/*
 	 * it already went through dequeue, we need to decrement the
 	 * in_flight count again
 	 */
 	if (blk_account_rq(rq)) {
 		q->in_flight--;
-		if (blk_sorted_rq(rq) && e->ops->elevator_deactivate_req_fn)
-			e->ops->elevator_deactivate_req_fn(q, rq);
+		if (blk_sorted_rq(rq))
+			elv_deactivate_rq(q, rq);
 	}
 
 	rq->cmd_flags &= ~REQ_STARTED;
@@ -700,16 +716,13 @@
 
 	while ((rq = __elv_next_request(q)) != NULL) {
 		if (!(rq->cmd_flags & REQ_STARTED)) {
-			elevator_t *e = q->elevator;
-
 			/*
 			 * This is the first time the device driver
 			 * sees this request (possibly after
 			 * requeueing).  Notify IO scheduler.
 			 */
-			if (blk_sorted_rq(rq) &&
-			    e->ops->elevator_activate_req_fn)
-				e->ops->elevator_activate_req_fn(q, rq);
+			if (blk_sorted_rq(rq))
+				elv_activate_rq(q, rq);
 
 			/*
 			 * just mark as started even if we don't start
diff --git a/block/genhd.c b/block/genhd.c
index 457fdac..050a1f0 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/genhd.h>
+#include <linux/kdev_t.h>
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
 #include <linux/init.h>
@@ -61,6 +62,8 @@
 	/* temporary */
 	if (major == 0) {
 		for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) {
+			if (is_lanana_major(index))
+				continue;
 			if (major_names[index] == NULL)
 				break;
 		}
diff --git a/block/ioctl.c b/block/ioctl.c
index f6962b6..e06dbe9 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -61,7 +61,7 @@
 				}
 			}
 			/* all seems OK */
-			add_partition(disk, part, start, length);
+			add_partition(disk, part, start, length, ADDPART_FLAG_NONE);
 			mutex_unlock(&bdev->bd_mutex);
 			return 0;
 		case BLKPG_DEL_PARTITION:
@@ -82,7 +82,7 @@
 			fsync_bdev(bdevp);
 			invalidate_bdev(bdevp, 0);
 
-			mutex_lock(&bdev->bd_mutex);
+			mutex_lock_nested(&bdev->bd_mutex, 1);
 			delete_partition(disk, part);
 			mutex_unlock(&bdev->bd_mutex);
 			mutex_unlock(&bdevp->bd_mutex);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index fb67897..38c293b 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1264,7 +1264,7 @@
 	bio->bi_hw_segments = nr_hw_segs;
 	bio->bi_flags |= (1 << BIO_SEG_VALID);
 }
-
+EXPORT_SYMBOL(blk_recount_segments);
 
 static int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
 				   struct bio *nxt)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 918b4d8..086fcec 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -149,6 +149,15 @@
 	  CBC: Cipher Block Chaining mode
 	  This block cipher algorithm is required for IPSec.
 
+config CRYPTO_PCBC
+	tristate "PCBC support"
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_MANAGER
+	default m
+	help
+	  PCBC: Propagating Cipher Block Chaining mode
+	  This block cipher algorithm is required for RxRPC.
+
 config CRYPTO_LRW
 	tristate "LRW support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -168,6 +177,13 @@
 	help
 	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
 
+config CRYPTO_FCRYPT
+	tristate "FCrypt cipher algorithm"
+	select CRYPTO_ALGAPI
+	select CRYPTO_BLKCIPHER
+	help
+	  FCrypt algorithm used by RxRPC.
+
 config CRYPTO_BLOWFISH
 	tristate "Blowfish cipher algorithm"
 	select CRYPTO_ALGAPI
@@ -409,6 +425,21 @@
 	  See Castagnoli93.  This implementation uses lib/libcrc32c.
           Module will be crc32c.
 
+config CRYPTO_CAMELLIA
+	tristate "Camellia cipher algorithms"
+	depends on CRYPTO
+	select CRYPTO_ALGAPI
+	help
+	  Camellia cipher algorithms module.
+
+	  Camellia is a symmetric key block cipher developed jointly
+	  at NTT and Mitsubishi Electric Corporation.
+
+	  The Camellia specifies three key sizes: 128, 192 and 256 bits.
+
+	  See also:
+	  <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
+
 config CRYPTO_TEST
 	tristate "Testing module"
 	depends on m
diff --git a/crypto/Makefile b/crypto/Makefile
index 60e3d24f..12f93f5 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -27,13 +27,16 @@
 obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
 obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
+obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
 obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
 obj-$(CONFIG_CRYPTO_AES) += aes.o
+obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia.o
 obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
 obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
diff --git a/crypto/algapi.c b/crypto/algapi.c
index c915300..f7d2185 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -377,7 +377,8 @@
 }
 EXPORT_SYMBOL_GPL(crypto_drop_spawn);
 
-struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
+struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
+				    u32 mask)
 {
 	struct crypto_alg *alg;
 	struct crypto_alg *alg2;
@@ -396,10 +397,18 @@
 		return ERR_PTR(-EAGAIN);
 	}
 
-	tfm = __crypto_alloc_tfm(alg, 0);
-	if (IS_ERR(tfm))
-		crypto_mod_put(alg);
+	tfm = ERR_PTR(-EINVAL);
+	if (unlikely((alg->cra_flags ^ type) & mask))
+		goto out_put_alg;
 
+	tfm = __crypto_alloc_tfm(alg, type, mask);
+	if (IS_ERR(tfm))
+		goto out_put_alg;
+
+	return tfm;
+
+out_put_alg:
+	crypto_mod_put(alg);
 	return tfm;
 }
 EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
diff --git a/crypto/api.c b/crypto/api.c
index 8c44687..55af8bb 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -212,31 +212,12 @@
 }
 EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
 
-static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
+static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 {
-	tfm->crt_flags = flags & CRYPTO_TFM_REQ_MASK;
-	flags &= ~CRYPTO_TFM_REQ_MASK;
-	
-	switch (crypto_tfm_alg_type(tfm)) {
-	case CRYPTO_ALG_TYPE_CIPHER:
-		return crypto_init_cipher_flags(tfm, flags);
-		
-	case CRYPTO_ALG_TYPE_DIGEST:
-		return crypto_init_digest_flags(tfm, flags);
-		
-	case CRYPTO_ALG_TYPE_COMPRESS:
-		return crypto_init_compress_flags(tfm, flags);
-	}
-	
-	return 0;
-}
+	const struct crypto_type *type_obj = tfm->__crt_alg->cra_type;
 
-static int crypto_init_ops(struct crypto_tfm *tfm)
-{
-	const struct crypto_type *type = tfm->__crt_alg->cra_type;
-
-	if (type)
-		return type->init(tfm);
+	if (type_obj)
+		return type_obj->init(tfm, type, mask);
 
 	switch (crypto_tfm_alg_type(tfm)) {
 	case CRYPTO_ALG_TYPE_CIPHER:
@@ -285,29 +266,29 @@
 	}
 }
 
-static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags)
+static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
 {
-	const struct crypto_type *type = alg->cra_type;
+	const struct crypto_type *type_obj = alg->cra_type;
 	unsigned int len;
 
 	len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1);
-	if (type)
-		return len + type->ctxsize(alg);
+	if (type_obj)
+		return len + type_obj->ctxsize(alg, type, mask);
 
 	switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
 	default:
 		BUG();
 
 	case CRYPTO_ALG_TYPE_CIPHER:
-		len += crypto_cipher_ctxsize(alg, flags);
+		len += crypto_cipher_ctxsize(alg);
 		break;
 		
 	case CRYPTO_ALG_TYPE_DIGEST:
-		len += crypto_digest_ctxsize(alg, flags);
+		len += crypto_digest_ctxsize(alg);
 		break;
 		
 	case CRYPTO_ALG_TYPE_COMPRESS:
-		len += crypto_compress_ctxsize(alg, flags);
+		len += crypto_compress_ctxsize(alg);
 		break;
 	}
 
@@ -322,24 +303,21 @@
 }
 EXPORT_SYMBOL_GPL(crypto_shoot_alg);
 
-struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags)
+struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
+				      u32 mask)
 {
 	struct crypto_tfm *tfm = NULL;
 	unsigned int tfm_size;
 	int err = -ENOMEM;
 
-	tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags);
+	tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask);
 	tfm = kzalloc(tfm_size, GFP_KERNEL);
 	if (tfm == NULL)
 		goto out_err;
 
 	tfm->__crt_alg = alg;
 
-	err = crypto_init_flags(tfm, flags);
-	if (err)
-		goto out_free_tfm;
-		
-	err = crypto_init_ops(tfm);
+	err = crypto_init_ops(tfm, type, mask);
 	if (err)
 		goto out_free_tfm;
 
@@ -362,31 +340,6 @@
 }
 EXPORT_SYMBOL_GPL(__crypto_alloc_tfm);
 
-struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
-{
-	struct crypto_tfm *tfm = NULL;
-	int err;
-
-	do {
-		struct crypto_alg *alg;
-
-		alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC);
-		err = PTR_ERR(alg);
-		if (IS_ERR(alg))
-			continue;
-
-		tfm = __crypto_alloc_tfm(alg, flags);
-		err = 0;
-		if (IS_ERR(tfm)) {
-			crypto_mod_put(alg);
-			err = PTR_ERR(tfm);
-			tfm = NULL;
-		}
-	} while (err == -EAGAIN && !signal_pending(current));
-
-	return tfm;
-}
-
 /*
  *	crypto_alloc_base - Locate algorithm and allocate transform
  *	@alg_name: Name of algorithm
@@ -420,7 +373,7 @@
 			goto err;
 		}
 
-		tfm = __crypto_alloc_tfm(alg, 0);
+		tfm = __crypto_alloc_tfm(alg, type, mask);
 		if (!IS_ERR(tfm))
 			return tfm;
 
@@ -466,7 +419,6 @@
 	kfree(tfm);
 }
 
-EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
 EXPORT_SYMBOL_GPL(crypto_free_tfm);
 
 int crypto_has_alg(const char *name, u32 type, u32 mask)
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 6e93004f..b5befe8 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -16,6 +16,7 @@
 
 #include <linux/crypto.h>
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/scatterlist.h>
@@ -313,6 +314,9 @@
 	struct crypto_blkcipher *tfm = desc->tfm;
 	unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
 
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+
 	walk->nbytes = walk->total;
 	if (unlikely(!walk->total))
 		return 0;
@@ -345,7 +349,8 @@
 	return cipher->setkey(tfm, key, keylen);
 }
 
-static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg)
+static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
+					     u32 mask)
 {
 	struct blkcipher_alg *cipher = &alg->cra_blkcipher;
 	unsigned int len = alg->cra_ctxsize;
@@ -358,7 +363,7 @@
 	return len;
 }
 
-static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm)
+static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 {
 	struct blkcipher_tfm *crt = &tfm->crt_blkcipher;
 	struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
diff --git a/crypto/camellia.c b/crypto/camellia.c
new file mode 100644
index 0000000..6877ecf
--- /dev/null
+++ b/crypto/camellia.c
@@ -0,0 +1,1801 @@
+/*
+ * Copyright (C) 2006
+ * NTT (Nippon Telegraph and Telephone 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.
+ */
+
+/*
+ * Algorithm Specification
+ *  http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
+ */
+
+/*
+ *
+ * NOTE --- NOTE --- NOTE --- NOTE
+ * This implementation assumes that all memory addresses passed
+ * as parameters are four-byte aligned.
+ *
+ */
+
+#include <linux/crypto.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+
+#define CAMELLIA_MIN_KEY_SIZE        16
+#define CAMELLIA_MAX_KEY_SIZE        32
+#define CAMELLIA_BLOCK_SIZE 16
+#define CAMELLIA_TABLE_BYTE_LEN 272
+#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
+
+typedef u32 KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN];
+
+
+/* key constants */
+
+#define CAMELLIA_SIGMA1L (0xA09E667FL)
+#define CAMELLIA_SIGMA1R (0x3BCC908BL)
+#define CAMELLIA_SIGMA2L (0xB67AE858L)
+#define CAMELLIA_SIGMA2R (0x4CAA73B2L)
+#define CAMELLIA_SIGMA3L (0xC6EF372FL)
+#define CAMELLIA_SIGMA3R (0xE94F82BEL)
+#define CAMELLIA_SIGMA4L (0x54FF53A5L)
+#define CAMELLIA_SIGMA4R (0xF1D36F1CL)
+#define CAMELLIA_SIGMA5L (0x10E527FAL)
+#define CAMELLIA_SIGMA5R (0xDE682D1DL)
+#define CAMELLIA_SIGMA6L (0xB05688C2L)
+#define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
+
+struct camellia_ctx {
+	int key_length;
+	KEY_TABLE_TYPE key_table;
+};
+
+
+/*
+ *  macros
+ */
+
+
+# define GETU32(pt) (((u32)(pt)[0] << 24)	\
+		     ^ ((u32)(pt)[1] << 16)	\
+		     ^ ((u32)(pt)[2] <<  8)	\
+		     ^ ((u32)(pt)[3]))
+
+#define COPY4WORD(dst, src)			\
+    do {					\
+	(dst)[0]=(src)[0];			\
+	(dst)[1]=(src)[1];			\
+	(dst)[2]=(src)[2];			\
+	(dst)[3]=(src)[3];			\
+    }while(0)
+
+#define SWAP4WORD(word)				\
+    do {					\
+	CAMELLIA_SWAP4((word)[0]);		\
+	CAMELLIA_SWAP4((word)[1]);		\
+	CAMELLIA_SWAP4((word)[2]);		\
+	CAMELLIA_SWAP4((word)[3]);		\
+    }while(0)
+
+#define XOR4WORD(a, b)/* a = a ^ b */		\
+    do {					\
+	(a)[0]^=(b)[0];				\
+	(a)[1]^=(b)[1];				\
+	(a)[2]^=(b)[2];				\
+	(a)[3]^=(b)[3];				\
+    }while(0)
+
+#define XOR4WORD2(a, b, c)/* a = b ^ c */	\
+    do {					\
+	(a)[0]=(b)[0]^(c)[0];			\
+	(a)[1]=(b)[1]^(c)[1];			\
+	(a)[2]=(b)[2]^(c)[2];			\
+	(a)[3]=(b)[3]^(c)[3];			\
+    }while(0)
+
+#define CAMELLIA_SUBKEY_L(INDEX) (subkey[(INDEX)*2])
+#define CAMELLIA_SUBKEY_R(INDEX) (subkey[(INDEX)*2 + 1])
+
+/* rotation right shift 1byte */
+#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24))
+/* rotation left shift 1bit */
+#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31))
+/* rotation left shift 1byte */
+#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24))
+
+#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits)	\
+    do {						\
+	w0 = ll;					\
+	ll = (ll << bits) + (lr >> (32 - bits));	\
+	lr = (lr << bits) + (rl >> (32 - bits));	\
+	rl = (rl << bits) + (rr >> (32 - bits));	\
+	rr = (rr << bits) + (w0 >> (32 - bits));	\
+    } while(0)
+
+#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits)	\
+    do {						\
+	w0 = ll;					\
+	w1 = lr;					\
+	ll = (lr << (bits - 32)) + (rl >> (64 - bits));	\
+	lr = (rl << (bits - 32)) + (rr >> (64 - bits));	\
+	rl = (rr << (bits - 32)) + (w0 >> (64 - bits));	\
+	rr = (w0 << (bits - 32)) + (w1 >> (64 - bits));	\
+    } while(0)
+
+#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)])
+#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)])
+#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)])
+#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)])
+
+#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
+    do {							\
+	il = xl ^ kl;						\
+	ir = xr ^ kr;						\
+	t0 = il >> 16;						\
+	t1 = ir >> 16;						\
+	yl = CAMELLIA_SP1110(ir & 0xff)				\
+	    ^ CAMELLIA_SP0222((t1 >> 8) & 0xff)			\
+	    ^ CAMELLIA_SP3033(t1 & 0xff)			\
+	    ^ CAMELLIA_SP4404((ir >> 8) & 0xff);		\
+	yr = CAMELLIA_SP1110((t0 >> 8) & 0xff)			\
+	    ^ CAMELLIA_SP0222(t0 & 0xff)			\
+	    ^ CAMELLIA_SP3033((il >> 8) & 0xff)			\
+	    ^ CAMELLIA_SP4404(il & 0xff);			\
+	yl ^= yr;						\
+	yr = CAMELLIA_RR8(yr);					\
+	yr ^= yl;						\
+    } while(0)
+
+
+/*
+ * for speed up
+ *
+ */
+#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
+    do {								\
+	t0 = kll;							\
+	t2 = krr;							\
+	t0 &= ll;							\
+	t2 |= rr;							\
+	rl ^= t2;							\
+	lr ^= CAMELLIA_RL1(t0);						\
+	t3 = krl;							\
+	t1 = klr;							\
+	t3 &= rl;							\
+	t1 |= lr;							\
+	ll ^= t1;							\
+	rr ^= CAMELLIA_RL1(t3);						\
+    } while(0)
+
+#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
+    do {								\
+	ir =  CAMELLIA_SP1110(xr & 0xff);				\
+	il =  CAMELLIA_SP1110((xl>>24) & 0xff);				\
+	ir ^= CAMELLIA_SP0222((xr>>24) & 0xff);				\
+	il ^= CAMELLIA_SP0222((xl>>16) & 0xff);				\
+	ir ^= CAMELLIA_SP3033((xr>>16) & 0xff);				\
+	il ^= CAMELLIA_SP3033((xl>>8) & 0xff);				\
+	ir ^= CAMELLIA_SP4404((xr>>8) & 0xff);				\
+	il ^= CAMELLIA_SP4404(xl & 0xff);				\
+	il ^= kl;							\
+	ir ^= il ^ kr;							\
+	yl ^= ir;							\
+	yr ^= CAMELLIA_RR8(il) ^ ir;					\
+    } while(0)
+
+/**
+ * Stuff related to the Camellia key schedule
+ */
+#define SUBL(x) subL[(x)]
+#define SUBR(x) subR[(x)]
+
+
+static const u32 camellia_sp1110[256] = {
+	0x70707000,0x82828200,0x2c2c2c00,0xececec00,
+	0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500,
+	0xe4e4e400,0x85858500,0x57575700,0x35353500,
+	0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100,
+	0x23232300,0xefefef00,0x6b6b6b00,0x93939300,
+	0x45454500,0x19191900,0xa5a5a500,0x21212100,
+	0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00,
+	0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00,
+	0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00,
+	0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00,
+	0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00,
+	0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00,
+	0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00,
+	0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00,
+	0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600,
+	0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00,
+	0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600,
+	0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00,
+	0x74747400,0x12121200,0x2b2b2b00,0x20202000,
+	0xf0f0f000,0xb1b1b100,0x84848400,0x99999900,
+	0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200,
+	0x34343400,0x7e7e7e00,0x76767600,0x05050500,
+	0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100,
+	0xd1d1d100,0x17171700,0x04040400,0xd7d7d700,
+	0x14141400,0x58585800,0x3a3a3a00,0x61616100,
+	0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00,
+	0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600,
+	0x53535300,0x18181800,0xf2f2f200,0x22222200,
+	0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200,
+	0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100,
+	0x24242400,0x08080800,0xe8e8e800,0xa8a8a800,
+	0x60606000,0xfcfcfc00,0x69696900,0x50505000,
+	0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00,
+	0xa1a1a100,0x89898900,0x62626200,0x97979700,
+	0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500,
+	0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200,
+	0x10101000,0xc4c4c400,0x00000000,0x48484800,
+	0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00,
+	0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00,
+	0x09090900,0x3f3f3f00,0xdddddd00,0x94949400,
+	0x87878700,0x5c5c5c00,0x83838300,0x02020200,
+	0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300,
+	0x73737300,0x67676700,0xf6f6f600,0xf3f3f300,
+	0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200,
+	0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600,
+	0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00,
+	0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00,
+	0x13131300,0xbebebe00,0x63636300,0x2e2e2e00,
+	0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00,
+	0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00,
+	0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600,
+	0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900,
+	0x78787800,0x98989800,0x06060600,0x6a6a6a00,
+	0xe7e7e700,0x46464600,0x71717100,0xbababa00,
+	0xd4d4d400,0x25252500,0xababab00,0x42424200,
+	0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00,
+	0x72727200,0x07070700,0xb9b9b900,0x55555500,
+	0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00,
+	0x36363600,0x49494900,0x2a2a2a00,0x68686800,
+	0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400,
+	0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00,
+	0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100,
+	0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400,
+	0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00,
+};
+
+static const u32 camellia_sp0222[256] = {
+	0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9,
+	0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb,
+	0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a,
+	0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282,
+	0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727,
+	0x008a8a8a,0x00323232,0x004b4b4b,0x00424242,
+	0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c,
+	0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b,
+	0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f,
+	0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d,
+	0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe,
+	0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434,
+	0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595,
+	0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a,
+	0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad,
+	0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a,
+	0x00171717,0x001a1a1a,0x00353535,0x00cccccc,
+	0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a,
+	0x00e8e8e8,0x00242424,0x00565656,0x00404040,
+	0x00e1e1e1,0x00636363,0x00090909,0x00333333,
+	0x00bfbfbf,0x00989898,0x00979797,0x00858585,
+	0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a,
+	0x00dadada,0x006f6f6f,0x00535353,0x00626262,
+	0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf,
+	0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2,
+	0x00bdbdbd,0x00363636,0x00222222,0x00383838,
+	0x00646464,0x001e1e1e,0x00393939,0x002c2c2c,
+	0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444,
+	0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565,
+	0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323,
+	0x00484848,0x00101010,0x00d1d1d1,0x00515151,
+	0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0,
+	0x00555555,0x00a1a1a1,0x00414141,0x00fafafa,
+	0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f,
+	0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b,
+	0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5,
+	0x00202020,0x00898989,0x00000000,0x00909090,
+	0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7,
+	0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5,
+	0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929,
+	0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404,
+	0x009b9b9b,0x00949494,0x00212121,0x00666666,
+	0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7,
+	0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5,
+	0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c,
+	0x00919191,0x006e6e6e,0x008d8d8d,0x00767676,
+	0x00030303,0x002d2d2d,0x00dedede,0x00969696,
+	0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c,
+	0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919,
+	0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d,
+	0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d,
+	0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2,
+	0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4,
+	0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575,
+	0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484,
+	0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5,
+	0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa,
+	0x00f1f1f1,0x00dddddd,0x00595959,0x00141414,
+	0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0,
+	0x00787878,0x00707070,0x00e3e3e3,0x00494949,
+	0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6,
+	0x00777777,0x00939393,0x00868686,0x00838383,
+	0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9,
+	0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d,
+};
+
+static const u32 camellia_sp3033[256] = {
+	0x38003838,0x41004141,0x16001616,0x76007676,
+	0xd900d9d9,0x93009393,0x60006060,0xf200f2f2,
+	0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a,
+	0x75007575,0x06000606,0x57005757,0xa000a0a0,
+	0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9,
+	0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090,
+	0xf600f6f6,0x07000707,0xa700a7a7,0x27002727,
+	0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede,
+	0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7,
+	0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767,
+	0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf,
+	0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d,
+	0x53005353,0xf000f0f0,0x9c009c9c,0x65006565,
+	0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e,
+	0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b,
+	0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6,
+	0xc500c5c5,0x86008686,0x4d004d4d,0x33003333,
+	0xfd00fdfd,0x66006666,0x58005858,0x96009696,
+	0x3a003a3a,0x09000909,0x95009595,0x10001010,
+	0x78007878,0xd800d8d8,0x42004242,0xcc00cccc,
+	0xef00efef,0x26002626,0xe500e5e5,0x61006161,
+	0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282,
+	0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898,
+	0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb,
+	0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0,
+	0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e,
+	0x19001919,0x87008787,0x4e004e4e,0x0b000b0b,
+	0xa900a9a9,0x0c000c0c,0x79007979,0x11001111,
+	0x7f007f7f,0x22002222,0xe700e7e7,0x59005959,
+	0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8,
+	0x12001212,0x04000404,0x74007474,0x54005454,
+	0x30003030,0x7e007e7e,0xb400b4b4,0x28002828,
+	0x55005555,0x68006868,0x50005050,0xbe00bebe,
+	0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb,
+	0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca,
+	0x70007070,0xff00ffff,0x32003232,0x69006969,
+	0x08000808,0x62006262,0x00000000,0x24002424,
+	0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded,
+	0x45004545,0x81008181,0x73007373,0x6d006d6d,
+	0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a,
+	0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101,
+	0xe600e6e6,0x25002525,0x48004848,0x99009999,
+	0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9,
+	0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171,
+	0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313,
+	0x64006464,0x9b009b9b,0x63006363,0x9d009d9d,
+	0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5,
+	0x89008989,0x5f005f5f,0xb100b1b1,0x17001717,
+	0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646,
+	0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747,
+	0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b,
+	0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac,
+	0x3c003c3c,0x4c004c4c,0x03000303,0x35003535,
+	0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d,
+	0x6a006a6a,0x92009292,0xd500d5d5,0x21002121,
+	0x44004444,0x51005151,0xc600c6c6,0x7d007d7d,
+	0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa,
+	0x7c007c7c,0x77007777,0x56005656,0x05000505,
+	0x1b001b1b,0xa400a4a4,0x15001515,0x34003434,
+	0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252,
+	0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd,
+	0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0,
+	0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a,
+	0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f,
+};
+
+static const u32 camellia_sp4404[256] = {
+	0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0,
+	0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae,
+	0x23230023,0x6b6b006b,0x45450045,0xa5a500a5,
+	0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092,
+	0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f,
+	0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b,
+	0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d,
+	0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c,
+	0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0,
+	0x74740074,0x2b2b002b,0xf0f000f0,0x84840084,
+	0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076,
+	0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004,
+	0x14140014,0x3a3a003a,0xdede00de,0x11110011,
+	0x32320032,0x9c9c009c,0x53530053,0xf2f200f2,
+	0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a,
+	0x24240024,0xe8e800e8,0x60600060,0x69690069,
+	0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062,
+	0x54540054,0x1e1e001e,0xe0e000e0,0x64640064,
+	0x10100010,0x00000000,0xa3a300a3,0x75750075,
+	0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd,
+	0x87870087,0x83830083,0xcdcd00cd,0x90900090,
+	0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf,
+	0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6,
+	0x81810081,0x6f6f006f,0x13130013,0x63630063,
+	0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc,
+	0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4,
+	0x78780078,0x06060006,0xe7e700e7,0x71710071,
+	0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d,
+	0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac,
+	0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1,
+	0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043,
+	0x15150015,0xadad00ad,0x77770077,0x80800080,
+	0x82820082,0xecec00ec,0x27270027,0xe5e500e5,
+	0x85850085,0x35350035,0x0c0c000c,0x41410041,
+	0xefef00ef,0x93930093,0x19190019,0x21210021,
+	0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd,
+	0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce,
+	0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a,
+	0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d,
+	0x01010001,0xd6d600d6,0x56560056,0x4d4d004d,
+	0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d,
+	0x12120012,0x20200020,0xb1b100b1,0x99990099,
+	0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005,
+	0xb7b700b7,0x31310031,0x17170017,0xd7d700d7,
+	0x58580058,0x61610061,0x1b1b001b,0x1c1c001c,
+	0x0f0f000f,0x16160016,0x18180018,0x22220022,
+	0x44440044,0xb2b200b2,0xb5b500b5,0x91910091,
+	0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050,
+	0xd0d000d0,0x7d7d007d,0x89890089,0x97970097,
+	0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2,
+	0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db,
+	0x03030003,0xdada00da,0x3f3f003f,0x94940094,
+	0x5c5c005c,0x02020002,0x4a4a004a,0x33330033,
+	0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2,
+	0x9b9b009b,0x26260026,0x37370037,0x3b3b003b,
+	0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e,
+	0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e,
+	0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059,
+	0x98980098,0x6a6a006a,0x46460046,0xbaba00ba,
+	0x25250025,0x42420042,0xa2a200a2,0xfafa00fa,
+	0x07070007,0x55550055,0xeeee00ee,0x0a0a000a,
+	0x49490049,0x68680068,0x38380038,0xa4a400a4,
+	0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1,
+	0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e,
+};
+
+
+
+static void camellia_setup128(const unsigned char *key, u32 *subkey)
+{
+	u32 kll, klr, krl, krr;
+	u32 il, ir, t0, t1, w0, w1;
+	u32 kw4l, kw4r, dw, tl, tr;
+	u32 subL[26];
+	u32 subR[26];
+
+	/**
+	 *  k == kll || klr || krl || krr (|| is concatination)
+	 */
+	kll = GETU32(key     );
+	klr = GETU32(key +  4);
+	krl = GETU32(key +  8);
+	krr = GETU32(key + 12);
+	/**
+	 * generate KL dependent subkeys
+	 */
+	/* kw1 */
+	SUBL(0) = kll; SUBR(0) = klr;
+	/* kw2 */
+	SUBL(1) = krl; SUBR(1) = krr;
+	/* rotation left shift 15bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k3 */
+	SUBL(4) = kll; SUBR(4) = klr;
+	/* k4 */
+	SUBL(5) = krl; SUBR(5) = krr;
+	/* rotation left shift 15+30bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+	/* k7 */
+	SUBL(10) = kll; SUBR(10) = klr;
+	/* k8 */
+	SUBL(11) = krl; SUBR(11) = krr;
+	/* rotation left shift 15+30+15bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k10 */
+	SUBL(13) = krl; SUBR(13) = krr;
+	/* rotation left shift 15+30+15+17 bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+	/* kl3 */
+	SUBL(16) = kll; SUBR(16) = klr;
+	/* kl4 */
+	SUBL(17) = krl; SUBR(17) = krr;
+	/* rotation left shift 15+30+15+17+17 bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+	/* k13 */
+	SUBL(18) = kll; SUBR(18) = klr;
+	/* k14 */
+	SUBL(19) = krl; SUBR(19) = krr;
+	/* rotation left shift 15+30+15+17+17+17 bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+	/* k17 */
+	SUBL(22) = kll; SUBR(22) = klr;
+	/* k18 */
+	SUBL(23) = krl; SUBR(23) = krr;
+
+	/* generate KA */
+	kll = SUBL(0); klr = SUBR(0);
+	krl = SUBL(1); krr = SUBR(1);
+	CAMELLIA_F(kll, klr,
+		   CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
+		   w0, w1, il, ir, t0, t1);
+	krl ^= w0; krr ^= w1;
+	CAMELLIA_F(krl, krr,
+		   CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
+		   kll, klr, il, ir, t0, t1);
+	/* current status == (kll, klr, w0, w1) */
+	CAMELLIA_F(kll, klr,
+		   CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
+		   krl, krr, il, ir, t0, t1);
+	krl ^= w0; krr ^= w1;
+	CAMELLIA_F(krl, krr,
+		   CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
+		   w0, w1, il, ir, t0, t1);
+	kll ^= w0; klr ^= w1;
+
+	/* generate KA dependent subkeys */
+	/* k1, k2 */
+	SUBL(2) = kll; SUBR(2) = klr;
+	SUBL(3) = krl; SUBR(3) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k5,k6 */
+	SUBL(6) = kll; SUBR(6) = klr;
+	SUBL(7) = krl; SUBR(7) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* kl1, kl2 */
+	SUBL(8) = kll; SUBR(8) = klr;
+	SUBL(9) = krl; SUBR(9) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k9 */
+	SUBL(12) = kll; SUBR(12) = klr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k11, k12 */
+	SUBL(14) = kll; SUBR(14) = klr;
+	SUBL(15) = krl; SUBR(15) = krr;
+	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+	/* k15, k16 */
+	SUBL(20) = kll; SUBR(20) = klr;
+	SUBL(21) = krl; SUBR(21) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+	/* kw3, kw4 */
+	SUBL(24) = kll; SUBR(24) = klr;
+	SUBL(25) = krl; SUBR(25) = krr;
+
+
+	/* absorb kw2 to other subkeys */
+	/* round 2 */
+	SUBL(3) ^= SUBL(1); SUBR(3) ^= SUBR(1);
+	/* round 4 */
+	SUBL(5) ^= SUBL(1); SUBR(5) ^= SUBR(1);
+	/* round 6 */
+	SUBL(7) ^= SUBL(1); SUBR(7) ^= SUBR(1);
+	SUBL(1) ^= SUBR(1) & ~SUBR(9);
+	dw = SUBL(1) & SUBL(9),
+		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl2) */
+	/* round 8 */
+	SUBL(11) ^= SUBL(1); SUBR(11) ^= SUBR(1);
+	/* round 10 */
+	SUBL(13) ^= SUBL(1); SUBR(13) ^= SUBR(1);
+	/* round 12 */
+	SUBL(15) ^= SUBL(1); SUBR(15) ^= SUBR(1);
+	SUBL(1) ^= SUBR(1) & ~SUBR(17);
+	dw = SUBL(1) & SUBL(17),
+		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl4) */
+	/* round 14 */
+	SUBL(19) ^= SUBL(1); SUBR(19) ^= SUBR(1);
+	/* round 16 */
+	SUBL(21) ^= SUBL(1); SUBR(21) ^= SUBR(1);
+	/* round 18 */
+	SUBL(23) ^= SUBL(1); SUBR(23) ^= SUBR(1);
+	/* kw3 */
+	SUBL(24) ^= SUBL(1); SUBR(24) ^= SUBR(1);
+
+	/* absorb kw4 to other subkeys */
+	kw4l = SUBL(25); kw4r = SUBR(25);
+	/* round 17 */
+	SUBL(22) ^= kw4l; SUBR(22) ^= kw4r;
+	/* round 15 */
+	SUBL(20) ^= kw4l; SUBR(20) ^= kw4r;
+	/* round 13 */
+	SUBL(18) ^= kw4l; SUBR(18) ^= kw4r;
+	kw4l ^= kw4r & ~SUBR(16);
+	dw = kw4l & SUBL(16),
+		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl3) */
+	/* round 11 */
+	SUBL(14) ^= kw4l; SUBR(14) ^= kw4r;
+	/* round 9 */
+	SUBL(12) ^= kw4l; SUBR(12) ^= kw4r;
+	/* round 7 */
+	SUBL(10) ^= kw4l; SUBR(10) ^= kw4r;
+	kw4l ^= kw4r & ~SUBR(8);
+	dw = kw4l & SUBL(8),
+		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl1) */
+	/* round 5 */
+	SUBL(6) ^= kw4l; SUBR(6) ^= kw4r;
+	/* round 3 */
+	SUBL(4) ^= kw4l; SUBR(4) ^= kw4r;
+	/* round 1 */
+	SUBL(2) ^= kw4l; SUBR(2) ^= kw4r;
+	/* kw1 */
+	SUBL(0) ^= kw4l; SUBR(0) ^= kw4r;
+
+
+	/* key XOR is end of F-function */
+	CAMELLIA_SUBKEY_L(0) = SUBL(0) ^ SUBL(2);/* kw1 */
+	CAMELLIA_SUBKEY_R(0) = SUBR(0) ^ SUBR(2);
+	CAMELLIA_SUBKEY_L(2) = SUBL(3);       /* round 1 */
+	CAMELLIA_SUBKEY_R(2) = SUBR(3);
+	CAMELLIA_SUBKEY_L(3) = SUBL(2) ^ SUBL(4); /* round 2 */
+	CAMELLIA_SUBKEY_R(3) = SUBR(2) ^ SUBR(4);
+	CAMELLIA_SUBKEY_L(4) = SUBL(3) ^ SUBL(5); /* round 3 */
+	CAMELLIA_SUBKEY_R(4) = SUBR(3) ^ SUBR(5);
+	CAMELLIA_SUBKEY_L(5) = SUBL(4) ^ SUBL(6); /* round 4 */
+	CAMELLIA_SUBKEY_R(5) = SUBR(4) ^ SUBR(6);
+	CAMELLIA_SUBKEY_L(6) = SUBL(5) ^ SUBL(7); /* round 5 */
+	CAMELLIA_SUBKEY_R(6) = SUBR(5) ^ SUBR(7);
+	tl = SUBL(10) ^ (SUBR(10) & ~SUBR(8));
+	dw = tl & SUBL(8),  /* FL(kl1) */
+		tr = SUBR(10) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(7) = SUBL(6) ^ tl; /* round 6 */
+	CAMELLIA_SUBKEY_R(7) = SUBR(6) ^ tr;
+	CAMELLIA_SUBKEY_L(8) = SUBL(8);       /* FL(kl1) */
+	CAMELLIA_SUBKEY_R(8) = SUBR(8);
+	CAMELLIA_SUBKEY_L(9) = SUBL(9);       /* FLinv(kl2) */
+	CAMELLIA_SUBKEY_R(9) = SUBR(9);
+	tl = SUBL(7) ^ (SUBR(7) & ~SUBR(9));
+	dw = tl & SUBL(9),  /* FLinv(kl2) */
+		tr = SUBR(7) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(10) = tl ^ SUBL(11); /* round 7 */
+	CAMELLIA_SUBKEY_R(10) = tr ^ SUBR(11);
+	CAMELLIA_SUBKEY_L(11) = SUBL(10) ^ SUBL(12); /* round 8 */
+	CAMELLIA_SUBKEY_R(11) = SUBR(10) ^ SUBR(12);
+	CAMELLIA_SUBKEY_L(12) = SUBL(11) ^ SUBL(13); /* round 9 */
+	CAMELLIA_SUBKEY_R(12) = SUBR(11) ^ SUBR(13);
+	CAMELLIA_SUBKEY_L(13) = SUBL(12) ^ SUBL(14); /* round 10 */
+	CAMELLIA_SUBKEY_R(13) = SUBR(12) ^ SUBR(14);
+	CAMELLIA_SUBKEY_L(14) = SUBL(13) ^ SUBL(15); /* round 11 */
+	CAMELLIA_SUBKEY_R(14) = SUBR(13) ^ SUBR(15);
+	tl = SUBL(18) ^ (SUBR(18) & ~SUBR(16));
+	dw = tl & SUBL(16), /* FL(kl3) */
+		tr = SUBR(18) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(15) = SUBL(14) ^ tl; /* round 12 */
+	CAMELLIA_SUBKEY_R(15) = SUBR(14) ^ tr;
+	CAMELLIA_SUBKEY_L(16) = SUBL(16);     /* FL(kl3) */
+	CAMELLIA_SUBKEY_R(16) = SUBR(16);
+	CAMELLIA_SUBKEY_L(17) = SUBL(17);     /* FLinv(kl4) */
+	CAMELLIA_SUBKEY_R(17) = SUBR(17);
+	tl = SUBL(15) ^ (SUBR(15) & ~SUBR(17));
+	dw = tl & SUBL(17), /* FLinv(kl4) */
+		tr = SUBR(15) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(18) = tl ^ SUBL(19); /* round 13 */
+	CAMELLIA_SUBKEY_R(18) = tr ^ SUBR(19);
+	CAMELLIA_SUBKEY_L(19) = SUBL(18) ^ SUBL(20); /* round 14 */
+	CAMELLIA_SUBKEY_R(19) = SUBR(18) ^ SUBR(20);
+	CAMELLIA_SUBKEY_L(20) = SUBL(19) ^ SUBL(21); /* round 15 */
+	CAMELLIA_SUBKEY_R(20) = SUBR(19) ^ SUBR(21);
+	CAMELLIA_SUBKEY_L(21) = SUBL(20) ^ SUBL(22); /* round 16 */
+	CAMELLIA_SUBKEY_R(21) = SUBR(20) ^ SUBR(22);
+	CAMELLIA_SUBKEY_L(22) = SUBL(21) ^ SUBL(23); /* round 17 */
+	CAMELLIA_SUBKEY_R(22) = SUBR(21) ^ SUBR(23);
+	CAMELLIA_SUBKEY_L(23) = SUBL(22);     /* round 18 */
+	CAMELLIA_SUBKEY_R(23) = SUBR(22);
+	CAMELLIA_SUBKEY_L(24) = SUBL(24) ^ SUBL(23); /* kw3 */
+	CAMELLIA_SUBKEY_R(24) = SUBR(24) ^ SUBR(23);
+
+	/* apply the inverse of the last half of P-function */
+	dw = CAMELLIA_SUBKEY_L(2) ^ CAMELLIA_SUBKEY_R(2),
+		dw = CAMELLIA_RL8(dw);/* round 1 */
+	CAMELLIA_SUBKEY_R(2) = CAMELLIA_SUBKEY_L(2) ^ dw,
+		CAMELLIA_SUBKEY_L(2) = dw;
+	dw = CAMELLIA_SUBKEY_L(3) ^ CAMELLIA_SUBKEY_R(3),
+		dw = CAMELLIA_RL8(dw);/* round 2 */
+	CAMELLIA_SUBKEY_R(3) = CAMELLIA_SUBKEY_L(3) ^ dw,
+		CAMELLIA_SUBKEY_L(3) = dw;
+	dw = CAMELLIA_SUBKEY_L(4) ^ CAMELLIA_SUBKEY_R(4),
+		dw = CAMELLIA_RL8(dw);/* round 3 */
+	CAMELLIA_SUBKEY_R(4) = CAMELLIA_SUBKEY_L(4) ^ dw,
+		CAMELLIA_SUBKEY_L(4) = dw;
+	dw = CAMELLIA_SUBKEY_L(5) ^ CAMELLIA_SUBKEY_R(5),
+		dw = CAMELLIA_RL8(dw);/* round 4 */
+	CAMELLIA_SUBKEY_R(5) = CAMELLIA_SUBKEY_L(5) ^ dw,
+		CAMELLIA_SUBKEY_L(5) = dw;
+	dw = CAMELLIA_SUBKEY_L(6) ^ CAMELLIA_SUBKEY_R(6),
+		dw = CAMELLIA_RL8(dw);/* round 5 */
+	CAMELLIA_SUBKEY_R(6) = CAMELLIA_SUBKEY_L(6) ^ dw,
+		CAMELLIA_SUBKEY_L(6) = dw;
+	dw = CAMELLIA_SUBKEY_L(7) ^ CAMELLIA_SUBKEY_R(7),
+		dw = CAMELLIA_RL8(dw);/* round 6 */
+	CAMELLIA_SUBKEY_R(7) = CAMELLIA_SUBKEY_L(7) ^ dw,
+		CAMELLIA_SUBKEY_L(7) = dw;
+	dw = CAMELLIA_SUBKEY_L(10) ^ CAMELLIA_SUBKEY_R(10),
+		dw = CAMELLIA_RL8(dw);/* round 7 */
+	CAMELLIA_SUBKEY_R(10) = CAMELLIA_SUBKEY_L(10) ^ dw,
+		CAMELLIA_SUBKEY_L(10) = dw;
+	dw = CAMELLIA_SUBKEY_L(11) ^ CAMELLIA_SUBKEY_R(11),
+		dw = CAMELLIA_RL8(dw);/* round 8 */
+	CAMELLIA_SUBKEY_R(11) = CAMELLIA_SUBKEY_L(11) ^ dw,
+		CAMELLIA_SUBKEY_L(11) = dw;
+	dw = CAMELLIA_SUBKEY_L(12) ^ CAMELLIA_SUBKEY_R(12),
+		dw = CAMELLIA_RL8(dw);/* round 9 */
+	CAMELLIA_SUBKEY_R(12) = CAMELLIA_SUBKEY_L(12) ^ dw,
+		CAMELLIA_SUBKEY_L(12) = dw;
+	dw = CAMELLIA_SUBKEY_L(13) ^ CAMELLIA_SUBKEY_R(13),
+		dw = CAMELLIA_RL8(dw);/* round 10 */
+	CAMELLIA_SUBKEY_R(13) = CAMELLIA_SUBKEY_L(13) ^ dw,
+		CAMELLIA_SUBKEY_L(13) = dw;
+	dw = CAMELLIA_SUBKEY_L(14) ^ CAMELLIA_SUBKEY_R(14),
+		dw = CAMELLIA_RL8(dw);/* round 11 */
+	CAMELLIA_SUBKEY_R(14) = CAMELLIA_SUBKEY_L(14) ^ dw,
+		CAMELLIA_SUBKEY_L(14) = dw;
+	dw = CAMELLIA_SUBKEY_L(15) ^ CAMELLIA_SUBKEY_R(15),
+		dw = CAMELLIA_RL8(dw);/* round 12 */
+	CAMELLIA_SUBKEY_R(15) = CAMELLIA_SUBKEY_L(15) ^ dw,
+		CAMELLIA_SUBKEY_L(15) = dw;
+	dw = CAMELLIA_SUBKEY_L(18) ^ CAMELLIA_SUBKEY_R(18),
+		dw = CAMELLIA_RL8(dw);/* round 13 */
+	CAMELLIA_SUBKEY_R(18) = CAMELLIA_SUBKEY_L(18) ^ dw,
+		CAMELLIA_SUBKEY_L(18) = dw;
+	dw = CAMELLIA_SUBKEY_L(19) ^ CAMELLIA_SUBKEY_R(19),
+		dw = CAMELLIA_RL8(dw);/* round 14 */
+	CAMELLIA_SUBKEY_R(19) = CAMELLIA_SUBKEY_L(19) ^ dw,
+		CAMELLIA_SUBKEY_L(19) = dw;
+	dw = CAMELLIA_SUBKEY_L(20) ^ CAMELLIA_SUBKEY_R(20),
+		dw = CAMELLIA_RL8(dw);/* round 15 */
+	CAMELLIA_SUBKEY_R(20) = CAMELLIA_SUBKEY_L(20) ^ dw,
+		CAMELLIA_SUBKEY_L(20) = dw;
+	dw = CAMELLIA_SUBKEY_L(21) ^ CAMELLIA_SUBKEY_R(21),
+		dw = CAMELLIA_RL8(dw);/* round 16 */
+	CAMELLIA_SUBKEY_R(21) = CAMELLIA_SUBKEY_L(21) ^ dw,
+		CAMELLIA_SUBKEY_L(21) = dw;
+	dw = CAMELLIA_SUBKEY_L(22) ^ CAMELLIA_SUBKEY_R(22),
+		dw = CAMELLIA_RL8(dw);/* round 17 */
+	CAMELLIA_SUBKEY_R(22) = CAMELLIA_SUBKEY_L(22) ^ dw,
+		CAMELLIA_SUBKEY_L(22) = dw;
+	dw = CAMELLIA_SUBKEY_L(23) ^ CAMELLIA_SUBKEY_R(23),
+		dw = CAMELLIA_RL8(dw);/* round 18 */
+	CAMELLIA_SUBKEY_R(23) = CAMELLIA_SUBKEY_L(23) ^ dw,
+		CAMELLIA_SUBKEY_L(23) = dw;
+
+	return;
+}
+
+
+static void camellia_setup256(const unsigned char *key, u32 *subkey)
+{
+	u32 kll,klr,krl,krr;           /* left half of key */
+	u32 krll,krlr,krrl,krrr;       /* right half of key */
+	u32 il, ir, t0, t1, w0, w1;    /* temporary variables */
+	u32 kw4l, kw4r, dw, tl, tr;
+	u32 subL[34];
+	u32 subR[34];
+
+	/**
+	 *  key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
+	 *  (|| is concatination)
+	 */
+
+	kll  = GETU32(key     );
+	klr  = GETU32(key +  4);
+	krl  = GETU32(key +  8);
+	krr  = GETU32(key + 12);
+	krll = GETU32(key + 16);
+	krlr = GETU32(key + 20);
+	krrl = GETU32(key + 24);
+	krrr = GETU32(key + 28);
+
+	/* generate KL dependent subkeys */
+	/* kw1 */
+	SUBL(0) = kll; SUBR(0) = klr;
+	/* kw2 */
+	SUBL(1) = krl; SUBR(1) = krr;
+	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
+	/* k9 */
+	SUBL(12) = kll; SUBR(12) = klr;
+	/* k10 */
+	SUBL(13) = krl; SUBR(13) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* kl3 */
+	SUBL(16) = kll; SUBR(16) = klr;
+	/* kl4 */
+	SUBL(17) = krl; SUBR(17) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+	/* k17 */
+	SUBL(22) = kll; SUBR(22) = klr;
+	/* k18 */
+	SUBL(23) = krl; SUBR(23) = krr;
+	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+	/* k23 */
+	SUBL(30) = kll; SUBR(30) = klr;
+	/* k24 */
+	SUBL(31) = krl; SUBR(31) = krr;
+
+	/* generate KR dependent subkeys */
+	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+	/* k3 */
+	SUBL(4) = krll; SUBR(4) = krlr;
+	/* k4 */
+	SUBL(5) = krrl; SUBR(5) = krrr;
+	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+	/* kl1 */
+	SUBL(8) = krll; SUBR(8) = krlr;
+	/* kl2 */
+	SUBL(9) = krrl; SUBR(9) = krrr;
+	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+	/* k13 */
+	SUBL(18) = krll; SUBR(18) = krlr;
+	/* k14 */
+	SUBL(19) = krrl; SUBR(19) = krrr;
+	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+	/* k19 */
+	SUBL(26) = krll; SUBR(26) = krlr;
+	/* k20 */
+	SUBL(27) = krrl; SUBR(27) = krrr;
+	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+
+	/* generate KA */
+	kll = SUBL(0) ^ krll; klr = SUBR(0) ^ krlr;
+	krl = SUBL(1) ^ krrl; krr = SUBR(1) ^ krrr;
+	CAMELLIA_F(kll, klr,
+		   CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
+		   w0, w1, il, ir, t0, t1);
+	krl ^= w0; krr ^= w1;
+	CAMELLIA_F(krl, krr,
+		   CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
+		   kll, klr, il, ir, t0, t1);
+	kll ^= krll; klr ^= krlr;
+	CAMELLIA_F(kll, klr,
+		   CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
+		   krl, krr, il, ir, t0, t1);
+	krl ^= w0 ^ krrl; krr ^= w1 ^ krrr;
+	CAMELLIA_F(krl, krr,
+		   CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
+		   w0, w1, il, ir, t0, t1);
+	kll ^= w0; klr ^= w1;
+
+	/* generate KB */
+	krll ^= kll; krlr ^= klr;
+	krrl ^= krl; krrr ^= krr;
+	CAMELLIA_F(krll, krlr,
+		   CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R,
+		   w0, w1, il, ir, t0, t1);
+	krrl ^= w0; krrr ^= w1;
+	CAMELLIA_F(krrl, krrr,
+		   CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R,
+		   w0, w1, il, ir, t0, t1);
+	krll ^= w0; krlr ^= w1;
+
+	/* generate KA dependent subkeys */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k5 */
+	SUBL(6) = kll; SUBR(6) = klr;
+	/* k6 */
+	SUBL(7) = krl; SUBR(7) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+	/* k11 */
+	SUBL(14) = kll; SUBR(14) = klr;
+	/* k12 */
+	SUBL(15) = krl; SUBR(15) = krr;
+	/* rotation left shift 32bit */
+	/* kl5 */
+	SUBL(24) = klr; SUBR(24) = krl;
+	/* kl6 */
+	SUBL(25) = krr; SUBR(25) = kll;
+	/* rotation left shift 49 from k11,k12 -> k21,k22 */
+	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
+	/* k21 */
+	SUBL(28) = kll; SUBR(28) = klr;
+	/* k22 */
+	SUBL(29) = krl; SUBR(29) = krr;
+
+	/* generate KB dependent subkeys */
+	/* k1 */
+	SUBL(2) = krll; SUBR(2) = krlr;
+	/* k2 */
+	SUBL(3) = krrl; SUBR(3) = krrr;
+	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+	/* k7 */
+	SUBL(10) = krll; SUBR(10) = krlr;
+	/* k8 */
+	SUBL(11) = krrl; SUBR(11) = krrr;
+	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+	/* k15 */
+	SUBL(20) = krll; SUBR(20) = krlr;
+	/* k16 */
+	SUBL(21) = krrl; SUBR(21) = krrr;
+	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
+	/* kw3 */
+	SUBL(32) = krll; SUBR(32) = krlr;
+	/* kw4 */
+	SUBL(33) = krrl; SUBR(33) = krrr;
+
+	/* absorb kw2 to other subkeys */
+	/* round 2 */
+	SUBL(3) ^= SUBL(1); SUBR(3) ^= SUBR(1);
+	/* round 4 */
+	SUBL(5) ^= SUBL(1); SUBR(5) ^= SUBR(1);
+	/* round 6 */
+	SUBL(7) ^= SUBL(1); SUBR(7) ^= SUBR(1);
+	SUBL(1) ^= SUBR(1) & ~SUBR(9);
+	dw = SUBL(1) & SUBL(9),
+		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl2) */
+	/* round 8 */
+	SUBL(11) ^= SUBL(1); SUBR(11) ^= SUBR(1);
+	/* round 10 */
+	SUBL(13) ^= SUBL(1); SUBR(13) ^= SUBR(1);
+	/* round 12 */
+	SUBL(15) ^= SUBL(1); SUBR(15) ^= SUBR(1);
+	SUBL(1) ^= SUBR(1) & ~SUBR(17);
+	dw = SUBL(1) & SUBL(17),
+		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl4) */
+	/* round 14 */
+	SUBL(19) ^= SUBL(1); SUBR(19) ^= SUBR(1);
+	/* round 16 */
+	SUBL(21) ^= SUBL(1); SUBR(21) ^= SUBR(1);
+	/* round 18 */
+	SUBL(23) ^= SUBL(1); SUBR(23) ^= SUBR(1);
+	SUBL(1) ^= SUBR(1) & ~SUBR(25);
+	dw = SUBL(1) & SUBL(25),
+		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl6) */
+	/* round 20 */
+	SUBL(27) ^= SUBL(1); SUBR(27) ^= SUBR(1);
+	/* round 22 */
+	SUBL(29) ^= SUBL(1); SUBR(29) ^= SUBR(1);
+	/* round 24 */
+	SUBL(31) ^= SUBL(1); SUBR(31) ^= SUBR(1);
+	/* kw3 */
+	SUBL(32) ^= SUBL(1); SUBR(32) ^= SUBR(1);
+
+
+	/* absorb kw4 to other subkeys */
+	kw4l = SUBL(33); kw4r = SUBR(33);
+	/* round 23 */
+	SUBL(30) ^= kw4l; SUBR(30) ^= kw4r;
+	/* round 21 */
+	SUBL(28) ^= kw4l; SUBR(28) ^= kw4r;
+	/* round 19 */
+	SUBL(26) ^= kw4l; SUBR(26) ^= kw4r;
+	kw4l ^= kw4r & ~SUBR(24);
+	dw = kw4l & SUBL(24),
+		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl5) */
+	/* round 17 */
+	SUBL(22) ^= kw4l; SUBR(22) ^= kw4r;
+	/* round 15 */
+	SUBL(20) ^= kw4l; SUBR(20) ^= kw4r;
+	/* round 13 */
+	SUBL(18) ^= kw4l; SUBR(18) ^= kw4r;
+	kw4l ^= kw4r & ~SUBR(16);
+	dw = kw4l & SUBL(16),
+		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl3) */
+	/* round 11 */
+	SUBL(14) ^= kw4l; SUBR(14) ^= kw4r;
+	/* round 9 */
+	SUBL(12) ^= kw4l; SUBR(12) ^= kw4r;
+	/* round 7 */
+	SUBL(10) ^= kw4l; SUBR(10) ^= kw4r;
+	kw4l ^= kw4r & ~SUBR(8);
+	dw = kw4l & SUBL(8),
+		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl1) */
+	/* round 5 */
+	SUBL(6) ^= kw4l; SUBR(6) ^= kw4r;
+	/* round 3 */
+	SUBL(4) ^= kw4l; SUBR(4) ^= kw4r;
+	/* round 1 */
+	SUBL(2) ^= kw4l; SUBR(2) ^= kw4r;
+	/* kw1 */
+	SUBL(0) ^= kw4l; SUBR(0) ^= kw4r;
+
+	/* key XOR is end of F-function */
+	CAMELLIA_SUBKEY_L(0) = SUBL(0) ^ SUBL(2);/* kw1 */
+	CAMELLIA_SUBKEY_R(0) = SUBR(0) ^ SUBR(2);
+	CAMELLIA_SUBKEY_L(2) = SUBL(3);       /* round 1 */
+	CAMELLIA_SUBKEY_R(2) = SUBR(3);
+	CAMELLIA_SUBKEY_L(3) = SUBL(2) ^ SUBL(4); /* round 2 */
+	CAMELLIA_SUBKEY_R(3) = SUBR(2) ^ SUBR(4);
+	CAMELLIA_SUBKEY_L(4) = SUBL(3) ^ SUBL(5); /* round 3 */
+	CAMELLIA_SUBKEY_R(4) = SUBR(3) ^ SUBR(5);
+	CAMELLIA_SUBKEY_L(5) = SUBL(4) ^ SUBL(6); /* round 4 */
+	CAMELLIA_SUBKEY_R(5) = SUBR(4) ^ SUBR(6);
+	CAMELLIA_SUBKEY_L(6) = SUBL(5) ^ SUBL(7); /* round 5 */
+	CAMELLIA_SUBKEY_R(6) = SUBR(5) ^ SUBR(7);
+	tl = SUBL(10) ^ (SUBR(10) & ~SUBR(8));
+	dw = tl & SUBL(8),  /* FL(kl1) */
+		tr = SUBR(10) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(7) = SUBL(6) ^ tl; /* round 6 */
+	CAMELLIA_SUBKEY_R(7) = SUBR(6) ^ tr;
+	CAMELLIA_SUBKEY_L(8) = SUBL(8);       /* FL(kl1) */
+	CAMELLIA_SUBKEY_R(8) = SUBR(8);
+	CAMELLIA_SUBKEY_L(9) = SUBL(9);       /* FLinv(kl2) */
+	CAMELLIA_SUBKEY_R(9) = SUBR(9);
+	tl = SUBL(7) ^ (SUBR(7) & ~SUBR(9));
+	dw = tl & SUBL(9),  /* FLinv(kl2) */
+		tr = SUBR(7) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(10) = tl ^ SUBL(11); /* round 7 */
+	CAMELLIA_SUBKEY_R(10) = tr ^ SUBR(11);
+	CAMELLIA_SUBKEY_L(11) = SUBL(10) ^ SUBL(12); /* round 8 */
+	CAMELLIA_SUBKEY_R(11) = SUBR(10) ^ SUBR(12);
+	CAMELLIA_SUBKEY_L(12) = SUBL(11) ^ SUBL(13); /* round 9 */
+	CAMELLIA_SUBKEY_R(12) = SUBR(11) ^ SUBR(13);
+	CAMELLIA_SUBKEY_L(13) = SUBL(12) ^ SUBL(14); /* round 10 */
+	CAMELLIA_SUBKEY_R(13) = SUBR(12) ^ SUBR(14);
+	CAMELLIA_SUBKEY_L(14) = SUBL(13) ^ SUBL(15); /* round 11 */
+	CAMELLIA_SUBKEY_R(14) = SUBR(13) ^ SUBR(15);
+	tl = SUBL(18) ^ (SUBR(18) & ~SUBR(16));
+	dw = tl & SUBL(16), /* FL(kl3) */
+		tr = SUBR(18) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(15) = SUBL(14) ^ tl; /* round 12 */
+	CAMELLIA_SUBKEY_R(15) = SUBR(14) ^ tr;
+	CAMELLIA_SUBKEY_L(16) = SUBL(16);     /* FL(kl3) */
+	CAMELLIA_SUBKEY_R(16) = SUBR(16);
+	CAMELLIA_SUBKEY_L(17) = SUBL(17);     /* FLinv(kl4) */
+	CAMELLIA_SUBKEY_R(17) = SUBR(17);
+	tl = SUBL(15) ^ (SUBR(15) & ~SUBR(17));
+	dw = tl & SUBL(17), /* FLinv(kl4) */
+		tr = SUBR(15) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(18) = tl ^ SUBL(19); /* round 13 */
+	CAMELLIA_SUBKEY_R(18) = tr ^ SUBR(19);
+	CAMELLIA_SUBKEY_L(19) = SUBL(18) ^ SUBL(20); /* round 14 */
+	CAMELLIA_SUBKEY_R(19) = SUBR(18) ^ SUBR(20);
+	CAMELLIA_SUBKEY_L(20) = SUBL(19) ^ SUBL(21); /* round 15 */
+	CAMELLIA_SUBKEY_R(20) = SUBR(19) ^ SUBR(21);
+	CAMELLIA_SUBKEY_L(21) = SUBL(20) ^ SUBL(22); /* round 16 */
+	CAMELLIA_SUBKEY_R(21) = SUBR(20) ^ SUBR(22);
+	CAMELLIA_SUBKEY_L(22) = SUBL(21) ^ SUBL(23); /* round 17 */
+	CAMELLIA_SUBKEY_R(22) = SUBR(21) ^ SUBR(23);
+	tl = SUBL(26) ^ (SUBR(26)
+			 & ~SUBR(24));
+	dw = tl & SUBL(24), /* FL(kl5) */
+		tr = SUBR(26) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(23) = SUBL(22) ^ tl; /* round 18 */
+	CAMELLIA_SUBKEY_R(23) = SUBR(22) ^ tr;
+	CAMELLIA_SUBKEY_L(24) = SUBL(24);     /* FL(kl5) */
+	CAMELLIA_SUBKEY_R(24) = SUBR(24);
+	CAMELLIA_SUBKEY_L(25) = SUBL(25);     /* FLinv(kl6) */
+	CAMELLIA_SUBKEY_R(25) = SUBR(25);
+	tl = SUBL(23) ^ (SUBR(23) &
+			 ~SUBR(25));
+	dw = tl & SUBL(25), /* FLinv(kl6) */
+		tr = SUBR(23) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(26) = tl ^ SUBL(27); /* round 19 */
+	CAMELLIA_SUBKEY_R(26) = tr ^ SUBR(27);
+	CAMELLIA_SUBKEY_L(27) = SUBL(26) ^ SUBL(28); /* round 20 */
+	CAMELLIA_SUBKEY_R(27) = SUBR(26) ^ SUBR(28);
+	CAMELLIA_SUBKEY_L(28) = SUBL(27) ^ SUBL(29); /* round 21 */
+	CAMELLIA_SUBKEY_R(28) = SUBR(27) ^ SUBR(29);
+	CAMELLIA_SUBKEY_L(29) = SUBL(28) ^ SUBL(30); /* round 22 */
+	CAMELLIA_SUBKEY_R(29) = SUBR(28) ^ SUBR(30);
+	CAMELLIA_SUBKEY_L(30) = SUBL(29) ^ SUBL(31); /* round 23 */
+	CAMELLIA_SUBKEY_R(30) = SUBR(29) ^ SUBR(31);
+	CAMELLIA_SUBKEY_L(31) = SUBL(30);     /* round 24 */
+	CAMELLIA_SUBKEY_R(31) = SUBR(30);
+	CAMELLIA_SUBKEY_L(32) = SUBL(32) ^ SUBL(31); /* kw3 */
+	CAMELLIA_SUBKEY_R(32) = SUBR(32) ^ SUBR(31);
+
+	/* apply the inverse of the last half of P-function */
+	dw = CAMELLIA_SUBKEY_L(2) ^ CAMELLIA_SUBKEY_R(2),
+		dw = CAMELLIA_RL8(dw);/* round 1 */
+	CAMELLIA_SUBKEY_R(2) = CAMELLIA_SUBKEY_L(2) ^ dw,
+		CAMELLIA_SUBKEY_L(2) = dw;
+	dw = CAMELLIA_SUBKEY_L(3) ^ CAMELLIA_SUBKEY_R(3),
+		dw = CAMELLIA_RL8(dw);/* round 2 */
+	CAMELLIA_SUBKEY_R(3) = CAMELLIA_SUBKEY_L(3) ^ dw,
+		CAMELLIA_SUBKEY_L(3) = dw;
+	dw = CAMELLIA_SUBKEY_L(4) ^ CAMELLIA_SUBKEY_R(4),
+		dw = CAMELLIA_RL8(dw);/* round 3 */
+	CAMELLIA_SUBKEY_R(4) = CAMELLIA_SUBKEY_L(4) ^ dw,
+		CAMELLIA_SUBKEY_L(4) = dw;
+	dw = CAMELLIA_SUBKEY_L(5) ^ CAMELLIA_SUBKEY_R(5),
+		dw = CAMELLIA_RL8(dw);/* round 4 */
+	CAMELLIA_SUBKEY_R(5) = CAMELLIA_SUBKEY_L(5) ^ dw,
+	CAMELLIA_SUBKEY_L(5) = dw;
+	dw = CAMELLIA_SUBKEY_L(6) ^ CAMELLIA_SUBKEY_R(6),
+		dw = CAMELLIA_RL8(dw);/* round 5 */
+	CAMELLIA_SUBKEY_R(6) = CAMELLIA_SUBKEY_L(6) ^ dw,
+		CAMELLIA_SUBKEY_L(6) = dw;
+	dw = CAMELLIA_SUBKEY_L(7) ^ CAMELLIA_SUBKEY_R(7),
+		dw = CAMELLIA_RL8(dw);/* round 6 */
+	CAMELLIA_SUBKEY_R(7) = CAMELLIA_SUBKEY_L(7) ^ dw,
+		CAMELLIA_SUBKEY_L(7) = dw;
+	dw = CAMELLIA_SUBKEY_L(10) ^ CAMELLIA_SUBKEY_R(10),
+		dw = CAMELLIA_RL8(dw);/* round 7 */
+	CAMELLIA_SUBKEY_R(10) = CAMELLIA_SUBKEY_L(10) ^ dw,
+		CAMELLIA_SUBKEY_L(10) = dw;
+	dw = CAMELLIA_SUBKEY_L(11) ^ CAMELLIA_SUBKEY_R(11),
+	    dw = CAMELLIA_RL8(dw);/* round 8 */
+	CAMELLIA_SUBKEY_R(11) = CAMELLIA_SUBKEY_L(11) ^ dw,
+		CAMELLIA_SUBKEY_L(11) = dw;
+	dw = CAMELLIA_SUBKEY_L(12) ^ CAMELLIA_SUBKEY_R(12),
+		dw = CAMELLIA_RL8(dw);/* round 9 */
+	CAMELLIA_SUBKEY_R(12) = CAMELLIA_SUBKEY_L(12) ^ dw,
+		CAMELLIA_SUBKEY_L(12) = dw;
+	dw = CAMELLIA_SUBKEY_L(13) ^ CAMELLIA_SUBKEY_R(13),
+		dw = CAMELLIA_RL8(dw);/* round 10 */
+	CAMELLIA_SUBKEY_R(13) = CAMELLIA_SUBKEY_L(13) ^ dw,
+		CAMELLIA_SUBKEY_L(13) = dw;
+	dw = CAMELLIA_SUBKEY_L(14) ^ CAMELLIA_SUBKEY_R(14),
+		dw = CAMELLIA_RL8(dw);/* round 11 */
+	CAMELLIA_SUBKEY_R(14) = CAMELLIA_SUBKEY_L(14) ^ dw,
+		CAMELLIA_SUBKEY_L(14) = dw;
+	dw = CAMELLIA_SUBKEY_L(15) ^ CAMELLIA_SUBKEY_R(15),
+		dw = CAMELLIA_RL8(dw);/* round 12 */
+	CAMELLIA_SUBKEY_R(15) = CAMELLIA_SUBKEY_L(15) ^ dw,
+		CAMELLIA_SUBKEY_L(15) = dw;
+	dw = CAMELLIA_SUBKEY_L(18) ^ CAMELLIA_SUBKEY_R(18),
+		dw = CAMELLIA_RL8(dw);/* round 13 */
+	CAMELLIA_SUBKEY_R(18) = CAMELLIA_SUBKEY_L(18) ^ dw,
+		CAMELLIA_SUBKEY_L(18) = dw;
+	dw = CAMELLIA_SUBKEY_L(19) ^ CAMELLIA_SUBKEY_R(19),
+		dw = CAMELLIA_RL8(dw);/* round 14 */
+	CAMELLIA_SUBKEY_R(19) = CAMELLIA_SUBKEY_L(19) ^ dw,
+		CAMELLIA_SUBKEY_L(19) = dw;
+	dw = CAMELLIA_SUBKEY_L(20) ^ CAMELLIA_SUBKEY_R(20),
+		dw = CAMELLIA_RL8(dw);/* round 15 */
+	CAMELLIA_SUBKEY_R(20) = CAMELLIA_SUBKEY_L(20) ^ dw,
+		CAMELLIA_SUBKEY_L(20) = dw;
+	dw = CAMELLIA_SUBKEY_L(21) ^ CAMELLIA_SUBKEY_R(21),
+		dw = CAMELLIA_RL8(dw);/* round 16 */
+	CAMELLIA_SUBKEY_R(21) = CAMELLIA_SUBKEY_L(21) ^ dw,
+		CAMELLIA_SUBKEY_L(21) = dw;
+	dw = CAMELLIA_SUBKEY_L(22) ^ CAMELLIA_SUBKEY_R(22),
+		dw = CAMELLIA_RL8(dw);/* round 17 */
+	CAMELLIA_SUBKEY_R(22) = CAMELLIA_SUBKEY_L(22) ^ dw,
+		CAMELLIA_SUBKEY_L(22) = dw;
+	dw = CAMELLIA_SUBKEY_L(23) ^ CAMELLIA_SUBKEY_R(23),
+		dw = CAMELLIA_RL8(dw);/* round 18 */
+	CAMELLIA_SUBKEY_R(23) = CAMELLIA_SUBKEY_L(23) ^ dw,
+		CAMELLIA_SUBKEY_L(23) = dw;
+	dw = CAMELLIA_SUBKEY_L(26) ^ CAMELLIA_SUBKEY_R(26),
+		dw = CAMELLIA_RL8(dw);/* round 19 */
+	CAMELLIA_SUBKEY_R(26) = CAMELLIA_SUBKEY_L(26) ^ dw,
+		CAMELLIA_SUBKEY_L(26) = dw;
+	dw = CAMELLIA_SUBKEY_L(27) ^ CAMELLIA_SUBKEY_R(27),
+		dw = CAMELLIA_RL8(dw);/* round 20 */
+	CAMELLIA_SUBKEY_R(27) = CAMELLIA_SUBKEY_L(27) ^ dw,
+		CAMELLIA_SUBKEY_L(27) = dw;
+	dw = CAMELLIA_SUBKEY_L(28) ^ CAMELLIA_SUBKEY_R(28),
+		dw = CAMELLIA_RL8(dw);/* round 21 */
+	CAMELLIA_SUBKEY_R(28) = CAMELLIA_SUBKEY_L(28) ^ dw,
+		CAMELLIA_SUBKEY_L(28) = dw;
+	dw = CAMELLIA_SUBKEY_L(29) ^ CAMELLIA_SUBKEY_R(29),
+		dw = CAMELLIA_RL8(dw);/* round 22 */
+	CAMELLIA_SUBKEY_R(29) = CAMELLIA_SUBKEY_L(29) ^ dw,
+		CAMELLIA_SUBKEY_L(29) = dw;
+	dw = CAMELLIA_SUBKEY_L(30) ^ CAMELLIA_SUBKEY_R(30),
+		dw = CAMELLIA_RL8(dw);/* round 23 */
+	CAMELLIA_SUBKEY_R(30) = CAMELLIA_SUBKEY_L(30) ^ dw,
+		CAMELLIA_SUBKEY_L(30) = dw;
+	dw = CAMELLIA_SUBKEY_L(31) ^ CAMELLIA_SUBKEY_R(31),
+		dw = CAMELLIA_RL8(dw);/* round 24 */
+	CAMELLIA_SUBKEY_R(31) = CAMELLIA_SUBKEY_L(31) ^ dw,
+		CAMELLIA_SUBKEY_L(31) = dw;
+
+	return;
+}
+
+static void camellia_setup192(const unsigned char *key, u32 *subkey)
+{
+	unsigned char kk[32];
+	u32 krll, krlr, krrl,krrr;
+
+	memcpy(kk, key, 24);
+	memcpy((unsigned char *)&krll, key+16,4);
+	memcpy((unsigned char *)&krlr, key+20,4);
+	krrl = ~krll;
+	krrr = ~krlr;
+	memcpy(kk+24, (unsigned char *)&krrl, 4);
+	memcpy(kk+28, (unsigned char *)&krrr, 4);
+	camellia_setup256(kk, subkey);
+	return;
+}
+
+
+/**
+ * Stuff related to camellia encryption/decryption
+ */
+static void camellia_encrypt128(const u32 *subkey, __be32 *io_text)
+{
+	u32 il,ir,t0,t1;               /* temporary valiables */
+
+	u32 io[4];
+
+	io[0] = be32_to_cpu(io_text[0]);
+	io[1] = be32_to_cpu(io_text[1]);
+	io[2] = be32_to_cpu(io_text[2]);
+	io[3] = be32_to_cpu(io_text[3]);
+
+	/* pre whitening but absorb kw2*/
+	io[0] ^= CAMELLIA_SUBKEY_L(0);
+	io[1] ^= CAMELLIA_SUBKEY_R(0);
+	/* main iteration */
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+			 io[0],io[1],il,ir,t0,t1);
+
+	/* post whitening but kw4 */
+	io[2] ^= CAMELLIA_SUBKEY_L(24);
+	io[3] ^= CAMELLIA_SUBKEY_R(24);
+
+	t0 = io[0];
+	t1 = io[1];
+	io[0] = io[2];
+	io[1] = io[3];
+	io[2] = t0;
+	io[3] = t1;
+
+	io_text[0] = cpu_to_be32(io[0]);
+	io_text[1] = cpu_to_be32(io[1]);
+	io_text[2] = cpu_to_be32(io[2]);
+	io_text[3] = cpu_to_be32(io[3]);
+
+	return;
+}
+
+static void camellia_decrypt128(const u32 *subkey, __be32 *io_text)
+{
+	u32 il,ir,t0,t1;               /* temporary valiables */
+
+	u32 io[4];
+
+	io[0] = be32_to_cpu(io_text[0]);
+	io[1] = be32_to_cpu(io_text[1]);
+	io[2] = be32_to_cpu(io_text[2]);
+	io[3] = be32_to_cpu(io_text[3]);
+
+	/* pre whitening but absorb kw2*/
+	io[0] ^= CAMELLIA_SUBKEY_L(24);
+	io[1] ^= CAMELLIA_SUBKEY_R(24);
+
+	/* main iteration */
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+			 io[0],io[1],il,ir,t0,t1);
+
+	/* post whitening but kw4 */
+	io[2] ^= CAMELLIA_SUBKEY_L(0);
+	io[3] ^= CAMELLIA_SUBKEY_R(0);
+
+	t0 = io[0];
+	t1 = io[1];
+	io[0] = io[2];
+	io[1] = io[3];
+	io[2] = t0;
+	io[3] = t1;
+
+	io_text[0] = cpu_to_be32(io[0]);
+	io_text[1] = cpu_to_be32(io[1]);
+	io_text[2] = cpu_to_be32(io[2]);
+	io_text[3] = cpu_to_be32(io[3]);
+
+	return;
+}
+
+
+/**
+ * stuff for 192 and 256bit encryption/decryption
+ */
+static void camellia_encrypt256(const u32 *subkey, __be32 *io_text)
+{
+	u32 il,ir,t0,t1;           /* temporary valiables */
+
+	u32 io[4];
+
+	io[0] = be32_to_cpu(io_text[0]);
+	io[1] = be32_to_cpu(io_text[1]);
+	io[2] = be32_to_cpu(io_text[2]);
+	io[3] = be32_to_cpu(io_text[3]);
+
+	/* pre whitening but absorb kw2*/
+	io[0] ^= CAMELLIA_SUBKEY_L(0);
+	io[1] ^= CAMELLIA_SUBKEY_R(0);
+
+	/* main iteration */
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(24),CAMELLIA_SUBKEY_R(24),
+		     CAMELLIA_SUBKEY_L(25),CAMELLIA_SUBKEY_R(25),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(26),CAMELLIA_SUBKEY_R(26),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(27),CAMELLIA_SUBKEY_R(27),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(28),CAMELLIA_SUBKEY_R(28),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(29),CAMELLIA_SUBKEY_R(29),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(30),CAMELLIA_SUBKEY_R(30),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(31),CAMELLIA_SUBKEY_R(31),
+			 io[0],io[1],il,ir,t0,t1);
+
+	/* post whitening but kw4 */
+	io[2] ^= CAMELLIA_SUBKEY_L(32);
+	io[3] ^= CAMELLIA_SUBKEY_R(32);
+
+	t0 = io[0];
+	t1 = io[1];
+	io[0] = io[2];
+	io[1] = io[3];
+	io[2] = t0;
+	io[3] = t1;
+
+	io_text[0] = cpu_to_be32(io[0]);
+	io_text[1] = cpu_to_be32(io[1]);
+	io_text[2] = cpu_to_be32(io[2]);
+	io_text[3] = cpu_to_be32(io[3]);
+
+	return;
+}
+
+
+static void camellia_decrypt256(const u32 *subkey, __be32 *io_text)
+{
+	u32 il,ir,t0,t1;           /* temporary valiables */
+
+	u32 io[4];
+
+	io[0] = be32_to_cpu(io_text[0]);
+	io[1] = be32_to_cpu(io_text[1]);
+	io[2] = be32_to_cpu(io_text[2]);
+	io[3] = be32_to_cpu(io_text[3]);
+
+	/* pre whitening but absorb kw2*/
+	io[0] ^= CAMELLIA_SUBKEY_L(32);
+	io[1] ^= CAMELLIA_SUBKEY_R(32);
+
+	/* main iteration */
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(31),CAMELLIA_SUBKEY_R(31),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(30),CAMELLIA_SUBKEY_R(30),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(29),CAMELLIA_SUBKEY_R(29),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(28),CAMELLIA_SUBKEY_R(28),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(27),CAMELLIA_SUBKEY_R(27),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(26),CAMELLIA_SUBKEY_R(26),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(25),CAMELLIA_SUBKEY_R(25),
+		     CAMELLIA_SUBKEY_L(24),CAMELLIA_SUBKEY_R(24),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+			 io[0],io[1],il,ir,t0,t1);
+
+	/* post whitening but kw4 */
+	io[2] ^= CAMELLIA_SUBKEY_L(0);
+	io[3] ^= CAMELLIA_SUBKEY_R(0);
+
+	t0 = io[0];
+	t1 = io[1];
+	io[0] = io[2];
+	io[1] = io[3];
+	io[2] = t0;
+	io[3] = t1;
+
+	io_text[0] = cpu_to_be32(io[0]);
+	io_text[1] = cpu_to_be32(io[1]);
+	io_text[2] = cpu_to_be32(io[2]);
+	io_text[3] = cpu_to_be32(io[3]);
+
+	return;
+}
+
+
+static int
+camellia_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+		 unsigned int key_len)
+{
+	struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
+	const unsigned char *key = (const unsigned char *)in_key;
+	u32 *flags = &tfm->crt_flags;
+
+	if (key_len != 16 && key_len != 24 && key_len != 32) {
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	cctx->key_length = key_len;
+
+	switch(key_len) {
+	case 16:
+		camellia_setup128(key, cctx->key_table);
+		break;
+	case 24:
+		camellia_setup192(key, cctx->key_table);
+		break;
+	case 32:
+		camellia_setup256(key, cctx->key_table);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+
+static void camellia_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+	const struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
+	const __be32 *src = (const __be32 *)in;
+	__be32 *dst = (__be32 *)out;
+
+	__be32 tmp[4];
+
+	memcpy(tmp, src, CAMELLIA_BLOCK_SIZE);
+
+	switch (cctx->key_length) {
+	case 16:
+		camellia_encrypt128(cctx->key_table, tmp);
+		break;
+	case 24:
+		/* fall through */
+	case 32:
+		camellia_encrypt256(cctx->key_table, tmp);
+		break;
+	default:
+		break;
+	}
+
+	memcpy(dst, tmp, CAMELLIA_BLOCK_SIZE);
+}
+
+
+static void camellia_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+	const struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
+	const __be32 *src = (const __be32 *)in;
+	__be32 *dst = (__be32 *)out;
+
+	__be32 tmp[4];
+
+	memcpy(tmp, src, CAMELLIA_BLOCK_SIZE);
+
+	switch (cctx->key_length) {
+	case 16:
+		camellia_decrypt128(cctx->key_table, tmp);
+		break;
+	case 24:
+		/* fall through */
+	case 32:
+		camellia_decrypt256(cctx->key_table, tmp);
+		break;
+	default:
+		break;
+	}
+
+	memcpy(dst, tmp, CAMELLIA_BLOCK_SIZE);
+}
+
+
+static struct crypto_alg camellia_alg = {
+	.cra_name		=	"camellia",
+	.cra_driver_name	=	"camellia-generic",
+	.cra_priority		=	100,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct camellia_ctx),
+	.cra_alignmask		=	3,
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(camellia_alg.cra_list),
+	.cra_u			=	{
+		.cipher = {
+			.cia_min_keysize	=	CAMELLIA_MIN_KEY_SIZE,
+			.cia_max_keysize	=	CAMELLIA_MAX_KEY_SIZE,
+			.cia_setkey		=	camellia_set_key,
+			.cia_encrypt		=	camellia_encrypt,
+			.cia_decrypt		=	camellia_decrypt
+		}
+	}
+};
+
+static int __init camellia_init(void)
+{
+	return crypto_register_alg(&camellia_alg);
+}
+
+
+static void __exit camellia_fini(void)
+{
+	crypto_unregister_alg(&camellia_alg);
+}
+
+
+module_init(camellia_init);
+module_exit(camellia_fini);
+
+
+MODULE_DESCRIPTION("Camellia Cipher Algorithm");
+MODULE_LICENSE("GPL");
diff --git a/crypto/cbc.c b/crypto/cbc.c
index f5542b4..136fea7 100644
--- a/crypto/cbc.c
+++ b/crypto/cbc.c
@@ -243,6 +243,7 @@
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_cipher *cipher;
 
 	switch (crypto_tfm_alg_blocksize(tfm)) {
 	case 8:
@@ -260,11 +261,11 @@
 			ctx->xor = xor_quad;
 	}
 
-	tfm = crypto_spawn_tfm(spawn);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
 
-	ctx->child = crypto_cipher_cast(tfm);
+	ctx->child = cipher;
 	return 0;
 }
 
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 9e03701..333aab2 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -12,274 +12,13 @@
  * any later version.
  *
  */
-#include <linux/compiler.h>
+
 #include <linux/kernel.h>
 #include <linux/crypto.h>
 #include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
+#include <linux/scatterlist.h>
 #include <linux/string.h>
-#include <asm/scatterlist.h>
 #include "internal.h"
-#include "scatterwalk.h"
-
-struct cipher_alg_compat {
-	unsigned int cia_min_keysize;
-	unsigned int cia_max_keysize;
-	int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key,
-	                  unsigned int keylen);
-	void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-	void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-
-	unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes);
-	unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes);
-	unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes);
-	unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes);
-};
-
-static inline void xor_64(u8 *a, const u8 *b)
-{
-	((u32 *)a)[0] ^= ((u32 *)b)[0];
-	((u32 *)a)[1] ^= ((u32 *)b)[1];
-}
-
-static inline void xor_128(u8 *a, const u8 *b)
-{
-	((u32 *)a)[0] ^= ((u32 *)b)[0];
-	((u32 *)a)[1] ^= ((u32 *)b)[1];
-	((u32 *)a)[2] ^= ((u32 *)b)[2];
-	((u32 *)a)[3] ^= ((u32 *)b)[3];
-}
-
-static unsigned int crypt_slow(const struct cipher_desc *desc,
-			       struct scatter_walk *in,
-			       struct scatter_walk *out, unsigned int bsize)
-{
-	unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm);
-	u8 buffer[bsize * 2 + alignmask];
-	u8 *src = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
-	u8 *dst = src + bsize;
-
-	scatterwalk_copychunks(src, in, bsize, 0);
-	desc->prfn(desc, dst, src, bsize);
-	scatterwalk_copychunks(dst, out, bsize, 1);
-
-	return bsize;
-}
-
-static inline unsigned int crypt_fast(const struct cipher_desc *desc,
-				      struct scatter_walk *in,
-				      struct scatter_walk *out,
-				      unsigned int nbytes, u8 *tmp)
-{
-	u8 *src, *dst;
-	u8 *real_src, *real_dst;
-
-	real_src = scatterwalk_map(in, 0);
-	real_dst = scatterwalk_map(out, 1);
-
-	src = real_src;
-	dst = scatterwalk_samebuf(in, out) ? src : real_dst;
-
-	if (tmp) {
-		memcpy(tmp, src, nbytes);
-		src = tmp;
-		dst = tmp;
-	}
-
-	nbytes = desc->prfn(desc, dst, src, nbytes);
-
-	if (tmp)
-		memcpy(real_dst, tmp, nbytes);
-
-	scatterwalk_unmap(real_src, 0);
-	scatterwalk_unmap(real_dst, 1);
-
-	scatterwalk_advance(in, nbytes);
-	scatterwalk_advance(out, nbytes);
-
-	return nbytes;
-}
-
-/* 
- * Generic encrypt/decrypt wrapper for ciphers, handles operations across
- * multiple page boundaries by using temporary blocks.  In user context,
- * the kernel is given a chance to schedule us once per page.
- */
-static int crypt(const struct cipher_desc *desc,
-		 struct scatterlist *dst,
-		 struct scatterlist *src,
-		 unsigned int nbytes)
-{
-	struct scatter_walk walk_in, walk_out;
-	struct crypto_tfm *tfm = desc->tfm;
-	const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
-	unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
-	unsigned long buffer = 0;
-
-	if (!nbytes)
-		return 0;
-
-	if (nbytes % bsize) {
-		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
-		return -EINVAL;
-	}
-
-	scatterwalk_start(&walk_in, src);
-	scatterwalk_start(&walk_out, dst);
-
-	for(;;) {
-		unsigned int n = nbytes;
-		u8 *tmp = NULL;
-
-		if (!scatterwalk_aligned(&walk_in, alignmask) ||
-		    !scatterwalk_aligned(&walk_out, alignmask)) {
-			if (!buffer) {
-				buffer = __get_free_page(GFP_ATOMIC);
-				if (!buffer)
-					n = 0;
-			}
-			tmp = (u8 *)buffer;
-		}
-
-		n = scatterwalk_clamp(&walk_in, n);
-		n = scatterwalk_clamp(&walk_out, n);
-
-		if (likely(n >= bsize))
-			n = crypt_fast(desc, &walk_in, &walk_out, n, tmp);
-		else
-			n = crypt_slow(desc, &walk_in, &walk_out, bsize);
-
-		nbytes -= n;
-
-		scatterwalk_done(&walk_in, 0, nbytes);
-		scatterwalk_done(&walk_out, 1, nbytes);
-
-		if (!nbytes)
-			break;
-
-		crypto_yield(tfm->crt_flags);
-	}
-
-	if (buffer)
-		free_page(buffer);
-
-	return 0;
-}
-
-static int crypt_iv_unaligned(struct cipher_desc *desc,
-			      struct scatterlist *dst,
-			      struct scatterlist *src,
-			      unsigned int nbytes)
-{
-	struct crypto_tfm *tfm = desc->tfm;
-	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
-	u8 *iv = desc->info;
-
-	if (unlikely(((unsigned long)iv & alignmask))) {
-		unsigned int ivsize = tfm->crt_cipher.cit_ivsize;
-		u8 buffer[ivsize + alignmask];
-		u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
-		int err;
-
-		desc->info = memcpy(tmp, iv, ivsize);
-		err = crypt(desc, dst, src, nbytes);
-		memcpy(iv, tmp, ivsize);
-
-		return err;
-	}
-
-	return crypt(desc, dst, src, nbytes);
-}
-
-static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes)
-{
-	struct crypto_tfm *tfm = desc->tfm;
-	void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
-	int bsize = crypto_tfm_alg_blocksize(tfm);
-
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
-	u8 *iv = desc->info;
-	unsigned int done = 0;
-
-	nbytes -= bsize;
-
-	do {
-		xor(iv, src);
-		fn(tfm, dst, iv);
-		memcpy(iv, dst, bsize);
-
-		src += bsize;
-		dst += bsize;
-	} while ((done += bsize) <= nbytes);
-
-	return done;
-}
-
-static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes)
-{
-	struct crypto_tfm *tfm = desc->tfm;
-	void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
-	int bsize = crypto_tfm_alg_blocksize(tfm);
-	unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm);
-
-	u8 stack[src == dst ? bsize + alignmask : 0];
-	u8 *buf = (u8 *)ALIGN((unsigned long)stack, alignmask + 1);
-	u8 **dst_p = src == dst ? &buf : &dst;
-
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
-	u8 *iv = desc->info;
-	unsigned int done = 0;
-
-	nbytes -= bsize;
-
-	do {
-		u8 *tmp_dst = *dst_p;
-
-		fn(tfm, tmp_dst, src);
-		xor(tmp_dst, iv);
-		memcpy(iv, src, bsize);
-		if (tmp_dst != dst)
-			memcpy(dst, tmp_dst, bsize);
-
-		src += bsize;
-		dst += bsize;
-	} while ((done += bsize) <= nbytes);
-
-	return done;
-}
-
-static unsigned int ecb_process(const struct cipher_desc *desc, u8 *dst,
-				const u8 *src, unsigned int nbytes)
-{
-	struct crypto_tfm *tfm = desc->tfm;
-	int bsize = crypto_tfm_alg_blocksize(tfm);
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
-	unsigned int done = 0;
-
-	nbytes -= bsize;
-
-	do {
-		fn(tfm, dst, src);
-
-		src += bsize;
-		dst += bsize;
-	} while ((done += bsize) <= nbytes);
-
-	return done;
-}
 
 static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
 {
@@ -293,122 +32,6 @@
 		return cia->cia_setkey(tfm, key, keylen);
 }
 
-static int ecb_encrypt(struct crypto_tfm *tfm,
-		       struct scatterlist *dst,
-                       struct scatterlist *src, unsigned int nbytes)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_encrypt;
-	desc.prfn = cipher->cia_encrypt_ecb ?: ecb_process;
-
-	return crypt(&desc, dst, src, nbytes);
-}
-
-static int ecb_decrypt(struct crypto_tfm *tfm,
-                       struct scatterlist *dst,
-                       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_decrypt;
-	desc.prfn = cipher->cia_decrypt_ecb ?: ecb_process;
-
-	return crypt(&desc, dst, src, nbytes);
-}
-
-static int cbc_encrypt(struct crypto_tfm *tfm,
-                       struct scatterlist *dst,
-                       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_encrypt;
-	desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
-	desc.info = tfm->crt_cipher.cit_iv;
-
-	return crypt(&desc, dst, src, nbytes);
-}
-
-static int cbc_encrypt_iv(struct crypto_tfm *tfm,
-                          struct scatterlist *dst,
-                          struct scatterlist *src,
-                          unsigned int nbytes, u8 *iv)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_encrypt;
-	desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
-	desc.info = iv;
-
-	return crypt_iv_unaligned(&desc, dst, src, nbytes);
-}
-
-static int cbc_decrypt(struct crypto_tfm *tfm,
-                       struct scatterlist *dst,
-                       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_decrypt;
-	desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
-	desc.info = tfm->crt_cipher.cit_iv;
-
-	return crypt(&desc, dst, src, nbytes);
-}
-
-static int cbc_decrypt_iv(struct crypto_tfm *tfm,
-                          struct scatterlist *dst,
-                          struct scatterlist *src,
-                          unsigned int nbytes, u8 *iv)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_decrypt;
-	desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
-	desc.info = iv;
-
-	return crypt_iv_unaligned(&desc, dst, src, nbytes);
-}
-
-static int nocrypt(struct crypto_tfm *tfm,
-                   struct scatterlist *dst,
-                   struct scatterlist *src,
-		   unsigned int nbytes)
-{
-	return -ENOSYS;
-}
-
-static int nocrypt_iv(struct crypto_tfm *tfm,
-                      struct scatterlist *dst,
-                      struct scatterlist *src,
-                      unsigned int nbytes, u8 *iv)
-{
-	return -ENOSYS;
-}
-
-int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
-{
-	u32 mode = flags & CRYPTO_TFM_MODE_MASK;
-	tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
-	return 0;
-}
-
 static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,
 					      const u8 *),
 				   struct crypto_tfm *tfm,
@@ -454,7 +77,6 @@
 
 int crypto_init_cipher_ops(struct crypto_tfm *tfm)
 {
-	int ret = 0;
 	struct cipher_tfm *ops = &tfm->crt_cipher;
 	struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
 
@@ -464,70 +86,7 @@
 	ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ?
 		cipher_decrypt_unaligned : cipher->cia_decrypt;
 
-	switch (tfm->crt_cipher.cit_mode) {
-	case CRYPTO_TFM_MODE_ECB:
-		ops->cit_encrypt = ecb_encrypt;
-		ops->cit_decrypt = ecb_decrypt;
-		ops->cit_encrypt_iv = nocrypt_iv;
-		ops->cit_decrypt_iv = nocrypt_iv;
-		break;
-		
-	case CRYPTO_TFM_MODE_CBC:
-		ops->cit_encrypt = cbc_encrypt;
-		ops->cit_decrypt = cbc_decrypt;
-		ops->cit_encrypt_iv = cbc_encrypt_iv;
-		ops->cit_decrypt_iv = cbc_decrypt_iv;
-		break;
-		
-	case CRYPTO_TFM_MODE_CFB:
-		ops->cit_encrypt = nocrypt;
-		ops->cit_decrypt = nocrypt;
-		ops->cit_encrypt_iv = nocrypt_iv;
-		ops->cit_decrypt_iv = nocrypt_iv;
-		break;
-	
-	case CRYPTO_TFM_MODE_CTR:
-		ops->cit_encrypt = nocrypt;
-		ops->cit_decrypt = nocrypt;
-		ops->cit_encrypt_iv = nocrypt_iv;
-		ops->cit_decrypt_iv = nocrypt_iv;
-		break;
-
-	default:
-		BUG();
-	}
-	
-	if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) {
-		unsigned long align;
-		unsigned long addr;
-	    	
-	    	switch (crypto_tfm_alg_blocksize(tfm)) {
-	    	case 8:
-	    		ops->cit_xor_block = xor_64;
-	    		break;
-	    		
-	    	case 16:
-	    		ops->cit_xor_block = xor_128;
-	    		break;
-	    		
-	    	default:
-	    		printk(KERN_WARNING "%s: block size %u not supported\n",
-	    		       crypto_tfm_alg_name(tfm),
-	    		       crypto_tfm_alg_blocksize(tfm));
-	    		ret = -EINVAL;
-	    		goto out;
-	    	}
-	    	
-		ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm);
-		align = crypto_tfm_alg_alignmask(tfm) + 1;
-		addr = (unsigned long)crypto_tfm_ctx(tfm);
-		addr = ALIGN(addr, align);
-		addr += ALIGN(tfm->__crt_alg->cra_ctxsize, align);
-		ops->cit_iv = (void *)addr;
-	}
-
-out:	
-	return ret;
+	return 0;
 }
 
 void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
diff --git a/crypto/compress.c b/crypto/compress.c
index eca182a..0a65700 100644
--- a/crypto/compress.c
+++ b/crypto/compress.c
@@ -34,11 +34,6 @@
 	                                                   dlen);
 }
 
-int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags)
-{
-	return flags ? -EINVAL : 0;
-}
-
 int crypto_init_compress_ops(struct crypto_tfm *tfm)
 {
 	struct compress_tfm *ops = &tfm->crt_compress;
diff --git a/crypto/digest.c b/crypto/digest.c
index 8f45932..1bf7414 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -14,7 +14,9 @@
 
 #include <linux/mm.h>
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/highmem.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/scatterlist.h>
 
@@ -29,8 +31,8 @@
 	return 0;
 }
 
-static int update(struct hash_desc *desc,
-		  struct scatterlist *sg, unsigned int nbytes)
+static int update2(struct hash_desc *desc,
+		   struct scatterlist *sg, unsigned int nbytes)
 {
 	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
 	unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
@@ -81,6 +83,14 @@
 	return 0;
 }
 
+static int update(struct hash_desc *desc,
+		  struct scatterlist *sg, unsigned int nbytes)
+{
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+	return update2(desc, sg, nbytes);
+}
+
 static int final(struct hash_desc *desc, u8 *out)
 {
 	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
@@ -118,14 +128,12 @@
 static int digest(struct hash_desc *desc,
 		  struct scatterlist *sg, unsigned int nbytes, u8 *out)
 {
-	init(desc);
-	update(desc, sg, nbytes);
-	return final(desc, out);
-}
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
 
-int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
-{
-	return flags ? -EINVAL : 0;
+	init(desc);
+	update2(desc, sg, nbytes);
+	return final(desc, out);
 }
 
 int crypto_init_digest_ops(struct crypto_tfm *tfm)
diff --git a/crypto/ecb.c b/crypto/ecb.c
index f239aa9..839a0ae 100644
--- a/crypto/ecb.c
+++ b/crypto/ecb.c
@@ -99,12 +99,13 @@
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_cipher *cipher;
 
-	tfm = crypto_spawn_tfm(spawn);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
 
-	ctx->child = crypto_cipher_cast(tfm);
+	ctx->child = cipher;
 	return 0;
 }
 
diff --git a/crypto/fcrypt.c b/crypto/fcrypt.c
new file mode 100644
index 0000000..9c2bb53
--- /dev/null
+++ b/crypto/fcrypt.c
@@ -0,0 +1,423 @@
+/* FCrypt encryption algorithm
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Based on code:
+ *
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ */
+
+#include <asm/byteorder.h>
+#include <linux/bitops.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+
+#define ROUNDS 16
+
+struct fcrypt_ctx {
+	u32 sched[ROUNDS];
+};
+
+/* Rotate right two 32 bit numbers as a 56 bit number */
+#define ror56(hi, lo, n)					\
+do {								\
+	u32 t = lo & ((1 << n) - 1);				\
+	lo = (lo >> n) | ((hi & ((1 << n) - 1)) << (32 - n));	\
+	hi = (hi >> n) | (t << (24-n));				\
+} while(0)
+
+/* Rotate right one 64 bit number as a 56 bit number */
+#define ror56_64(k, n)						\
+do {								\
+	k = (k >> n) | ((k & ((1 << n) - 1)) << (56 - n));	\
+} while(0)
+
+/*
+ * Sboxes for Feistel network derived from
+ * /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
+ */
+#undef Z
+#define Z(x) __constant_be32_to_cpu(x << 3)
+static const u32 sbox0[256] = {
+	Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11),
+	Z(0xcd), Z(0x86), Z(0x86), Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06),
+	Z(0x0e), Z(0x06), Z(0xd2), Z(0x65), Z(0x73), Z(0xc5), Z(0x28), Z(0x60),
+	Z(0xf2), Z(0x20), Z(0xb5), Z(0x38), Z(0x7e), Z(0xda), Z(0x9f), Z(0xe3),
+	Z(0xd2), Z(0xcf), Z(0xc4), Z(0x3c), Z(0x61), Z(0xff), Z(0x4a), Z(0x4a),
+	Z(0x35), Z(0xac), Z(0xaa), Z(0x5f), Z(0x2b), Z(0xbb), Z(0xbc), Z(0x53),
+	Z(0x4e), Z(0x9d), Z(0x78), Z(0xa3), Z(0xdc), Z(0x09), Z(0x32), Z(0x10),
+	Z(0xc6), Z(0x6f), Z(0x66), Z(0xd6), Z(0xab), Z(0xa9), Z(0xaf), Z(0xfd),
+	Z(0x3b), Z(0x95), Z(0xe8), Z(0x34), Z(0x9a), Z(0x81), Z(0x72), Z(0x80),
+	Z(0x9c), Z(0xf3), Z(0xec), Z(0xda), Z(0x9f), Z(0x26), Z(0x76), Z(0x15),
+	Z(0x3e), Z(0x55), Z(0x4d), Z(0xde), Z(0x84), Z(0xee), Z(0xad), Z(0xc7),
+	Z(0xf1), Z(0x6b), Z(0x3d), Z(0xd3), Z(0x04), Z(0x49), Z(0xaa), Z(0x24),
+	Z(0x0b), Z(0x8a), Z(0x83), Z(0xba), Z(0xfa), Z(0x85), Z(0xa0), Z(0xa8),
+	Z(0xb1), Z(0xd4), Z(0x01), Z(0xd8), Z(0x70), Z(0x64), Z(0xf0), Z(0x51),
+	Z(0xd2), Z(0xc3), Z(0xa7), Z(0x75), Z(0x8c), Z(0xa5), Z(0x64), Z(0xef),
+	Z(0x10), Z(0x4e), Z(0xb7), Z(0xc6), Z(0x61), Z(0x03), Z(0xeb), Z(0x44),
+	Z(0x3d), Z(0xe5), Z(0xb3), Z(0x5b), Z(0xae), Z(0xd5), Z(0xad), Z(0x1d),
+	Z(0xfa), Z(0x5a), Z(0x1e), Z(0x33), Z(0xab), Z(0x93), Z(0xa2), Z(0xb7),
+	Z(0xe7), Z(0xa8), Z(0x45), Z(0xa4), Z(0xcd), Z(0x29), Z(0x63), Z(0x44),
+	Z(0xb6), Z(0x69), Z(0x7e), Z(0x2e), Z(0x62), Z(0x03), Z(0xc8), Z(0xe0),
+	Z(0x17), Z(0xbb), Z(0xc7), Z(0xf3), Z(0x3f), Z(0x36), Z(0xba), Z(0x71),
+	Z(0x8e), Z(0x97), Z(0x65), Z(0x60), Z(0x69), Z(0xb6), Z(0xf6), Z(0xe6),
+	Z(0x6e), Z(0xe0), Z(0x81), Z(0x59), Z(0xe8), Z(0xaf), Z(0xdd), Z(0x95),
+	Z(0x22), Z(0x99), Z(0xfd), Z(0x63), Z(0x19), Z(0x74), Z(0x61), Z(0xb1),
+	Z(0xb6), Z(0x5b), Z(0xae), Z(0x54), Z(0xb3), Z(0x70), Z(0xff), Z(0xc6),
+	Z(0x3b), Z(0x3e), Z(0xc1), Z(0xd7), Z(0xe1), Z(0x0e), Z(0x76), Z(0xe5),
+	Z(0x36), Z(0x4f), Z(0x59), Z(0xc7), Z(0x08), Z(0x6e), Z(0x82), Z(0xa6),
+	Z(0x93), Z(0xc4), Z(0xaa), Z(0x26), Z(0x49), Z(0xe0), Z(0x21), Z(0x64),
+	Z(0x07), Z(0x9f), Z(0x64), Z(0x81), Z(0x9c), Z(0xbf), Z(0xf9), Z(0xd1),
+	Z(0x43), Z(0xf8), Z(0xb6), Z(0xb9), Z(0xf1), Z(0x24), Z(0x75), Z(0x03),
+	Z(0xe4), Z(0xb0), Z(0x99), Z(0x46), Z(0x3d), Z(0xf5), Z(0xd1), Z(0x39),
+	Z(0x72), Z(0x12), Z(0xf6), Z(0xba), Z(0x0c), Z(0x0d), Z(0x42), Z(0x2e)
+};
+
+#undef Z
+#define Z(x) __constant_be32_to_cpu((x << 27) | (x >> 5))
+static const u32 sbox1[256] = {
+	Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e),
+	Z(0x67), Z(0x6c), Z(0xa1), Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85),
+	Z(0x6c), Z(0x7b), Z(0x67), Z(0xc6), Z(0x23), Z(0xe3), Z(0xf2), Z(0x89),
+	Z(0x50), Z(0x9c), Z(0x03), Z(0xb7), Z(0x73), Z(0xe6), Z(0xe1), Z(0x39),
+	Z(0x31), Z(0x2c), Z(0x27), Z(0x9f), Z(0xa5), Z(0x69), Z(0x44), Z(0xd6),
+	Z(0x23), Z(0x83), Z(0x98), Z(0x7d), Z(0x3c), Z(0xb4), Z(0x2d), Z(0x99),
+	Z(0x1c), Z(0x1f), Z(0x8c), Z(0x20), Z(0x03), Z(0x7c), Z(0x5f), Z(0xad),
+	Z(0xf4), Z(0xfa), Z(0x95), Z(0xca), Z(0x76), Z(0x44), Z(0xcd), Z(0xb6),
+	Z(0xb8), Z(0xa1), Z(0xa1), Z(0xbe), Z(0x9e), Z(0x54), Z(0x8f), Z(0x0b),
+	Z(0x16), Z(0x74), Z(0x31), Z(0x8a), Z(0x23), Z(0x17), Z(0x04), Z(0xfa),
+	Z(0x79), Z(0x84), Z(0xb1), Z(0xf5), Z(0x13), Z(0xab), Z(0xb5), Z(0x2e),
+	Z(0xaa), Z(0x0c), Z(0x60), Z(0x6b), Z(0x5b), Z(0xc4), Z(0x4b), Z(0xbc),
+	Z(0xe2), Z(0xaf), Z(0x45), Z(0x73), Z(0xfa), Z(0xc9), Z(0x49), Z(0xcd),
+	Z(0x00), Z(0x92), Z(0x7d), Z(0x97), Z(0x7a), Z(0x18), Z(0x60), Z(0x3d),
+	Z(0xcf), Z(0x5b), Z(0xde), Z(0xc6), Z(0xe2), Z(0xe6), Z(0xbb), Z(0x8b),
+	Z(0x06), Z(0xda), Z(0x08), Z(0x15), Z(0x1b), Z(0x88), Z(0x6a), Z(0x17),
+	Z(0x89), Z(0xd0), Z(0xa9), Z(0xc1), Z(0xc9), Z(0x70), Z(0x6b), Z(0xe5),
+	Z(0x43), Z(0xf4), Z(0x68), Z(0xc8), Z(0xd3), Z(0x84), Z(0x28), Z(0x0a),
+	Z(0x52), Z(0x66), Z(0xa3), Z(0xca), Z(0xf2), Z(0xe3), Z(0x7f), Z(0x7a),
+	Z(0x31), Z(0xf7), Z(0x88), Z(0x94), Z(0x5e), Z(0x9c), Z(0x63), Z(0xd5),
+	Z(0x24), Z(0x66), Z(0xfc), Z(0xb3), Z(0x57), Z(0x25), Z(0xbe), Z(0x89),
+	Z(0x44), Z(0xc4), Z(0xe0), Z(0x8f), Z(0x23), Z(0x3c), Z(0x12), Z(0x52),
+	Z(0xf5), Z(0x1e), Z(0xf4), Z(0xcb), Z(0x18), Z(0x33), Z(0x1f), Z(0xf8),
+	Z(0x69), Z(0x10), Z(0x9d), Z(0xd3), Z(0xf7), Z(0x28), Z(0xf8), Z(0x30),
+	Z(0x05), Z(0x5e), Z(0x32), Z(0xc0), Z(0xd5), Z(0x19), Z(0xbd), Z(0x45),
+	Z(0x8b), Z(0x5b), Z(0xfd), Z(0xbc), Z(0xe2), Z(0x5c), Z(0xa9), Z(0x96),
+	Z(0xef), Z(0x70), Z(0xcf), Z(0xc2), Z(0x2a), Z(0xb3), Z(0x61), Z(0xad),
+	Z(0x80), Z(0x48), Z(0x81), Z(0xb7), Z(0x1d), Z(0x43), Z(0xd9), Z(0xd7),
+	Z(0x45), Z(0xf0), Z(0xd8), Z(0x8a), Z(0x59), Z(0x7c), Z(0x57), Z(0xc1),
+	Z(0x79), Z(0xc7), Z(0x34), Z(0xd6), Z(0x43), Z(0xdf), Z(0xe4), Z(0x78),
+	Z(0x16), Z(0x06), Z(0xda), Z(0x92), Z(0x76), Z(0x51), Z(0xe1), Z(0xd4),
+	Z(0x70), Z(0x03), Z(0xe0), Z(0x2f), Z(0x96), Z(0x91), Z(0x82), Z(0x80)
+};
+
+#undef Z
+#define Z(x) __constant_be32_to_cpu(x << 11)
+static const u32 sbox2[256] = {
+	Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86),
+	Z(0xd1), Z(0xec), Z(0x50), Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d),
+	Z(0xbf), Z(0x80), Z(0x87), Z(0x27), Z(0x95), Z(0xe2), Z(0xc5), Z(0x5d),
+	Z(0xf9), Z(0x6f), Z(0xdb), Z(0xb4), Z(0x65), Z(0x6e), Z(0xe7), Z(0x24),
+	Z(0xc8), Z(0x1a), Z(0xbb), Z(0x49), Z(0xb5), Z(0x0a), Z(0x7d), Z(0xb9),
+	Z(0xe8), Z(0xdc), Z(0xb7), Z(0xd9), Z(0x45), Z(0x20), Z(0x1b), Z(0xce),
+	Z(0x59), Z(0x9d), Z(0x6b), Z(0xbd), Z(0x0e), Z(0x8f), Z(0xa3), Z(0xa9),
+	Z(0xbc), Z(0x74), Z(0xa6), Z(0xf6), Z(0x7f), Z(0x5f), Z(0xb1), Z(0x68),
+	Z(0x84), Z(0xbc), Z(0xa9), Z(0xfd), Z(0x55), Z(0x50), Z(0xe9), Z(0xb6),
+	Z(0x13), Z(0x5e), Z(0x07), Z(0xb8), Z(0x95), Z(0x02), Z(0xc0), Z(0xd0),
+	Z(0x6a), Z(0x1a), Z(0x85), Z(0xbd), Z(0xb6), Z(0xfd), Z(0xfe), Z(0x17),
+	Z(0x3f), Z(0x09), Z(0xa3), Z(0x8d), Z(0xfb), Z(0xed), Z(0xda), Z(0x1d),
+	Z(0x6d), Z(0x1c), Z(0x6c), Z(0x01), Z(0x5a), Z(0xe5), Z(0x71), Z(0x3e),
+	Z(0x8b), Z(0x6b), Z(0xbe), Z(0x29), Z(0xeb), Z(0x12), Z(0x19), Z(0x34),
+	Z(0xcd), Z(0xb3), Z(0xbd), Z(0x35), Z(0xea), Z(0x4b), Z(0xd5), Z(0xae),
+	Z(0x2a), Z(0x79), Z(0x5a), Z(0xa5), Z(0x32), Z(0x12), Z(0x7b), Z(0xdc),
+	Z(0x2c), Z(0xd0), Z(0x22), Z(0x4b), Z(0xb1), Z(0x85), Z(0x59), Z(0x80),
+	Z(0xc0), Z(0x30), Z(0x9f), Z(0x73), Z(0xd3), Z(0x14), Z(0x48), Z(0x40),
+	Z(0x07), Z(0x2d), Z(0x8f), Z(0x80), Z(0x0f), Z(0xce), Z(0x0b), Z(0x5e),
+	Z(0xb7), Z(0x5e), Z(0xac), Z(0x24), Z(0x94), Z(0x4a), Z(0x18), Z(0x15),
+	Z(0x05), Z(0xe8), Z(0x02), Z(0x77), Z(0xa9), Z(0xc7), Z(0x40), Z(0x45),
+	Z(0x89), Z(0xd1), Z(0xea), Z(0xde), Z(0x0c), Z(0x79), Z(0x2a), Z(0x99),
+	Z(0x6c), Z(0x3e), Z(0x95), Z(0xdd), Z(0x8c), Z(0x7d), Z(0xad), Z(0x6f),
+	Z(0xdc), Z(0xff), Z(0xfd), Z(0x62), Z(0x47), Z(0xb3), Z(0x21), Z(0x8a),
+	Z(0xec), Z(0x8e), Z(0x19), Z(0x18), Z(0xb4), Z(0x6e), Z(0x3d), Z(0xfd),
+	Z(0x74), Z(0x54), Z(0x1e), Z(0x04), Z(0x85), Z(0xd8), Z(0xbc), Z(0x1f),
+	Z(0x56), Z(0xe7), Z(0x3a), Z(0x56), Z(0x67), Z(0xd6), Z(0xc8), Z(0xa5),
+	Z(0xf3), Z(0x8e), Z(0xde), Z(0xae), Z(0x37), Z(0x49), Z(0xb7), Z(0xfa),
+	Z(0xc8), Z(0xf4), Z(0x1f), Z(0xe0), Z(0x2a), Z(0x9b), Z(0x15), Z(0xd1),
+	Z(0x34), Z(0x0e), Z(0xb5), Z(0xe0), Z(0x44), Z(0x78), Z(0x84), Z(0x59),
+	Z(0x56), Z(0x68), Z(0x77), Z(0xa5), Z(0x14), Z(0x06), Z(0xf5), Z(0x2f),
+	Z(0x8c), Z(0x8a), Z(0x73), Z(0x80), Z(0x76), Z(0xb4), Z(0x10), Z(0x86)
+};
+
+#undef Z
+#define Z(x) __constant_be32_to_cpu(x << 19)
+static const u32 sbox3[256] = {
+	Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2),
+	Z(0xb5), Z(0xb7), Z(0x42), Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12),
+	Z(0x44), Z(0x48), Z(0x6d), Z(0x28), Z(0xaa), Z(0x20), Z(0x6d), Z(0x57),
+	Z(0xd6), Z(0x6b), Z(0x5d), Z(0x72), Z(0xf0), Z(0x92), Z(0x5a), Z(0x1b),
+	Z(0x53), Z(0x80), Z(0x24), Z(0x70), Z(0x9a), Z(0xcc), Z(0xa7), Z(0x66),
+	Z(0xa1), Z(0x01), Z(0xa5), Z(0x41), Z(0x97), Z(0x41), Z(0x31), Z(0x82),
+	Z(0xf1), Z(0x14), Z(0xcf), Z(0x53), Z(0x0d), Z(0xa0), Z(0x10), Z(0xcc),
+	Z(0x2a), Z(0x7d), Z(0xd2), Z(0xbf), Z(0x4b), Z(0x1a), Z(0xdb), Z(0x16),
+	Z(0x47), Z(0xf6), Z(0x51), Z(0x36), Z(0xed), Z(0xf3), Z(0xb9), Z(0x1a),
+	Z(0xa7), Z(0xdf), Z(0x29), Z(0x43), Z(0x01), Z(0x54), Z(0x70), Z(0xa4),
+	Z(0xbf), Z(0xd4), Z(0x0b), Z(0x53), Z(0x44), Z(0x60), Z(0x9e), Z(0x23),
+	Z(0xa1), Z(0x18), Z(0x68), Z(0x4f), Z(0xf0), Z(0x2f), Z(0x82), Z(0xc2),
+	Z(0x2a), Z(0x41), Z(0xb2), Z(0x42), Z(0x0c), Z(0xed), Z(0x0c), Z(0x1d),
+	Z(0x13), Z(0x3a), Z(0x3c), Z(0x6e), Z(0x35), Z(0xdc), Z(0x60), Z(0x65),
+	Z(0x85), Z(0xe9), Z(0x64), Z(0x02), Z(0x9a), Z(0x3f), Z(0x9f), Z(0x87),
+	Z(0x96), Z(0xdf), Z(0xbe), Z(0xf2), Z(0xcb), Z(0xe5), Z(0x6c), Z(0xd4),
+	Z(0x5a), Z(0x83), Z(0xbf), Z(0x92), Z(0x1b), Z(0x94), Z(0x00), Z(0x42),
+	Z(0xcf), Z(0x4b), Z(0x00), Z(0x75), Z(0xba), Z(0x8f), Z(0x76), Z(0x5f),
+	Z(0x5d), Z(0x3a), Z(0x4d), Z(0x09), Z(0x12), Z(0x08), Z(0x38), Z(0x95),
+	Z(0x17), Z(0xe4), Z(0x01), Z(0x1d), Z(0x4c), Z(0xa9), Z(0xcc), Z(0x85),
+	Z(0x82), Z(0x4c), Z(0x9d), Z(0x2f), Z(0x3b), Z(0x66), Z(0xa1), Z(0x34),
+	Z(0x10), Z(0xcd), Z(0x59), Z(0x89), Z(0xa5), Z(0x31), Z(0xcf), Z(0x05),
+	Z(0xc8), Z(0x84), Z(0xfa), Z(0xc7), Z(0xba), Z(0x4e), Z(0x8b), Z(0x1a),
+	Z(0x19), Z(0xf1), Z(0xa1), Z(0x3b), Z(0x18), Z(0x12), Z(0x17), Z(0xb0),
+	Z(0x98), Z(0x8d), Z(0x0b), Z(0x23), Z(0xc3), Z(0x3a), Z(0x2d), Z(0x20),
+	Z(0xdf), Z(0x13), Z(0xa0), Z(0xa8), Z(0x4c), Z(0x0d), Z(0x6c), Z(0x2f),
+	Z(0x47), Z(0x13), Z(0x13), Z(0x52), Z(0x1f), Z(0x2d), Z(0xf5), Z(0x79),
+	Z(0x3d), Z(0xa2), Z(0x54), Z(0xbd), Z(0x69), Z(0xc8), Z(0x6b), Z(0xf3),
+	Z(0x05), Z(0x28), Z(0xf1), Z(0x16), Z(0x46), Z(0x40), Z(0xb0), Z(0x11),
+	Z(0xd3), Z(0xb7), Z(0x95), Z(0x49), Z(0xcf), Z(0xc3), Z(0x1d), Z(0x8f),
+	Z(0xd8), Z(0xe1), Z(0x73), Z(0xdb), Z(0xad), Z(0xc8), Z(0xc9), Z(0xa9),
+	Z(0xa1), Z(0xc2), Z(0xc5), Z(0xe3), Z(0xba), Z(0xfc), Z(0x0e), Z(0x25)
+};
+
+/*
+ * This is a 16 round Feistel network with permutation F_ENCRYPT
+ */
+#define F_ENCRYPT(R, L, sched)						\
+do {									\
+	union lc4 { u32 l; u8 c[4]; } u;				\
+	u.l = sched ^ R;						\
+	L ^= sbox0[u.c[0]] ^ sbox1[u.c[1]] ^ sbox2[u.c[2]] ^ sbox3[u.c[3]]; \
+} while(0)
+
+/*
+ * encryptor
+ */
+static void fcrypt_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct {
+		u32 l, r;
+	} X;
+
+	memcpy(&X, src, sizeof(X));
+
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
+
+	memcpy(dst, &X, sizeof(X));
+}
+
+/*
+ * decryptor
+ */
+static void fcrypt_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct {
+		u32 l, r;
+	} X;
+
+	memcpy(&X, src, sizeof(X));
+
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
+
+	memcpy(dst, &X, sizeof(X));
+}
+
+/*
+ * Generate a key schedule from key, the least significant bit in each key byte
+ * is parity and shall be ignored. This leaves 56 significant bits in the key
+ * to scatter over the 16 key schedules. For each schedule extract the low
+ * order 32 bits and use as schedule, then rotate right by 11 bits.
+ */
+static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
+
+#if BITS_PER_LONG == 64  /* the 64-bit version can also be used for 32-bit
+			  * kernels - it seems to be faster but the code is
+			  * larger */
+
+	u64 k;	/* k holds all 56 non-parity bits */
+
+	/* discard the parity bits */
+	k = (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key) >> 1;
+
+	/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
+	ctx->sched[0x0] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x1] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x2] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x3] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x4] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x5] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x6] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x7] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x8] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x9] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xa] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xb] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xc] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xd] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xe] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xf] = be32_to_cpu(k);
+
+	return 0;
+#else
+	u32 hi, lo;		/* hi is upper 24 bits and lo lower 32, total 56 */
+
+	/* discard the parity bits */
+	lo = (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	hi = lo >> 4;
+	lo &= 0xf;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key) >> 1;
+
+	/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
+	ctx->sched[0x0] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x1] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x2] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x3] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x4] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x5] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x6] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x7] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x8] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x9] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xa] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xb] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xc] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xd] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xe] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xf] = be32_to_cpu(lo);
+	return 0;
+#endif
+}
+
+static struct crypto_alg fcrypt_alg = {
+	.cra_name		=	"fcrypt",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	8,
+	.cra_ctxsize		=	sizeof(struct fcrypt_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_alignmask		=	3,
+	.cra_list		=	LIST_HEAD_INIT(fcrypt_alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	8,
+	.cia_max_keysize	=	8,
+	.cia_setkey		=	fcrypt_setkey,
+	.cia_encrypt		=	fcrypt_encrypt,
+	.cia_decrypt		=	fcrypt_decrypt } }
+};
+
+static int __init init(void)
+{
+	return crypto_register_alg(&fcrypt_alg);
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&fcrypt_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FCrypt Cipher Algorithm");
+MODULE_AUTHOR("David Howells <dhowells@redhat.com>");
diff --git a/crypto/hash.c b/crypto/hash.c
index cdec23d..12c4514 100644
--- a/crypto/hash.c
+++ b/crypto/hash.c
@@ -16,12 +16,13 @@
 
 #include "internal.h"
 
-static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg)
+static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg, u32 type,
+					u32 mask)
 {
 	return alg->cra_ctxsize;
 }
 
-static int crypto_init_hash_ops(struct crypto_tfm *tfm)
+static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 {
 	struct hash_tfm *crt = &tfm->crt_hash;
 	struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
diff --git a/crypto/hmac.c b/crypto/hmac.c
index b521bcd..44187c5 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -172,15 +172,16 @@
 
 static int hmac_init_tfm(struct crypto_tfm *tfm)
 {
+	struct crypto_hash *hash;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm));
 
-	tfm = crypto_spawn_tfm(spawn);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
+	hash = crypto_spawn_hash(spawn);
+	if (IS_ERR(hash))
+		return PTR_ERR(hash);
 
-	ctx->child = crypto_hash_cast(tfm);
+	ctx->child = hash;
 	return 0;
 }
 
diff --git a/crypto/internal.h b/crypto/internal.h
index 2da6ad4..60acad9 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -83,8 +83,7 @@
 { }
 #endif
 
-static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg,
-						 int flags)
+static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg)
 {
 	unsigned int len = alg->cra_ctxsize;
 
@@ -96,23 +95,12 @@
 	return len;
 }
 
-static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg,
-						 int flags)
+static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg)
 {
-	unsigned int len = alg->cra_ctxsize;
-	
-	switch (flags & CRYPTO_TFM_MODE_MASK) {
-	case CRYPTO_TFM_MODE_CBC:
-		len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
-		len += alg->cra_blocksize;
-		break;
-	}
-
-	return len;
+	return alg->cra_ctxsize;
 }
 
-static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg,
-						   int flags)
+static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg)
 {
 	return alg->cra_ctxsize;
 }
@@ -121,10 +109,6 @@
 struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask);
 struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
 
-int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags);
-int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags);
-int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags);
-
 int crypto_init_digest_ops(struct crypto_tfm *tfm);
 int crypto_init_cipher_ops(struct crypto_tfm *tfm);
 int crypto_init_compress_ops(struct crypto_tfm *tfm);
@@ -136,7 +120,8 @@
 void crypto_larval_error(const char *name, u32 type, u32 mask);
 
 void crypto_shoot_alg(struct crypto_alg *alg);
-struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags);
+struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
+				      u32 mask);
 
 int crypto_register_instance(struct crypto_template *tmpl,
 			     struct crypto_instance *inst);
diff --git a/crypto/lrw.c b/crypto/lrw.c
index 5664258..b410508 100644
--- a/crypto/lrw.c
+++ b/crypto/lrw.c
@@ -201,21 +201,22 @@
 
 static int init_tfm(struct crypto_tfm *tfm)
 {
+	struct crypto_cipher *cipher;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct priv *ctx = crypto_tfm_ctx(tfm);
 	u32 *flags = &tfm->crt_flags;
 
-	tfm = crypto_spawn_tfm(spawn);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
 
-	if (crypto_tfm_alg_blocksize(tfm) != 16) {
+	if (crypto_cipher_blocksize(cipher) != 16) {
 		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
 		return -EINVAL;
 	}
 
-	ctx->child = crypto_cipher_cast(tfm);
+	ctx->child = cipher;
 	return 0;
 }
 
diff --git a/crypto/pcbc.c b/crypto/pcbc.c
new file mode 100644
index 0000000..5174d7f
--- /dev/null
+++ b/crypto/pcbc.c
@@ -0,0 +1,349 @@
+/*
+ * PCBC: Propagating Cipher Block Chaining mode
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * Derived from cbc.c
+ * - Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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 <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+
+struct crypto_pcbc_ctx {
+	struct crypto_cipher *child;
+	void (*xor)(u8 *dst, const u8 *src, unsigned int bs);
+};
+
+static int crypto_pcbc_setkey(struct crypto_tfm *parent, const u8 *key,
+			      unsigned int keylen)
+{
+	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(parent);
+	struct crypto_cipher *child = ctx->child;
+	int err;
+
+	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
+				CRYPTO_TFM_REQ_MASK);
+	err = crypto_cipher_setkey(child, key, keylen);
+	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
+			     CRYPTO_TFM_RES_MASK);
+	return err;
+}
+
+static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
+				       struct blkcipher_walk *walk,
+				       struct crypto_cipher *tfm,
+				       void (*xor)(u8 *, const u8 *,
+						   unsigned int))
+{
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+		crypto_cipher_alg(tfm)->cia_encrypt;
+	int bsize = crypto_cipher_blocksize(tfm);
+	unsigned int nbytes = walk->nbytes;
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	u8 *iv = walk->iv;
+
+	do {
+		xor(iv, src, bsize);
+		fn(crypto_cipher_tfm(tfm), dst, iv);
+		memcpy(iv, dst, bsize);
+		xor(iv, src, bsize);
+
+		src += bsize;
+		dst += bsize;
+	} while ((nbytes -= bsize) >= bsize);
+
+	return nbytes;
+}
+
+static int crypto_pcbc_encrypt_inplace(struct blkcipher_desc *desc,
+				       struct blkcipher_walk *walk,
+				       struct crypto_cipher *tfm,
+				       void (*xor)(u8 *, const u8 *,
+						   unsigned int))
+{
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+		crypto_cipher_alg(tfm)->cia_encrypt;
+	int bsize = crypto_cipher_blocksize(tfm);
+	unsigned int nbytes = walk->nbytes;
+	u8 *src = walk->src.virt.addr;
+	u8 *iv = walk->iv;
+	u8 tmpbuf[bsize];
+
+	do {
+		memcpy(tmpbuf, src, bsize);
+		xor(iv, tmpbuf, bsize);
+		fn(crypto_cipher_tfm(tfm), src, iv);
+		memcpy(iv, src, bsize);
+		xor(iv, tmpbuf, bsize);
+
+		src += bsize;
+	} while ((nbytes -= bsize) >= bsize);
+
+	memcpy(walk->iv, iv, bsize);
+
+	return nbytes;
+}
+
+static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
+			       struct scatterlist *dst, struct scatterlist *src,
+			       unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	struct crypto_blkcipher *tfm = desc->tfm;
+	struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
+	struct crypto_cipher *child = ctx->child;
+	void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		if (walk.src.virt.addr == walk.dst.virt.addr)
+			nbytes = crypto_pcbc_encrypt_inplace(desc, &walk, child,
+							     xor);
+		else
+			nbytes = crypto_pcbc_encrypt_segment(desc, &walk, child,
+							     xor);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
+				       struct blkcipher_walk *walk,
+				       struct crypto_cipher *tfm,
+				       void (*xor)(u8 *, const u8 *,
+						   unsigned int))
+{
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+		crypto_cipher_alg(tfm)->cia_decrypt;
+	int bsize = crypto_cipher_blocksize(tfm);
+	unsigned int nbytes = walk->nbytes;
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	u8 *iv = walk->iv;
+
+	do {
+		fn(crypto_cipher_tfm(tfm), dst, src);
+		xor(dst, iv, bsize);
+		memcpy(iv, src, bsize);
+		xor(iv, dst, bsize);
+
+		src += bsize;
+		dst += bsize;
+	} while ((nbytes -= bsize) >= bsize);
+
+	memcpy(walk->iv, iv, bsize);
+
+	return nbytes;
+}
+
+static int crypto_pcbc_decrypt_inplace(struct blkcipher_desc *desc,
+				       struct blkcipher_walk *walk,
+				       struct crypto_cipher *tfm,
+				       void (*xor)(u8 *, const u8 *,
+						   unsigned int))
+{
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+		crypto_cipher_alg(tfm)->cia_decrypt;
+	int bsize = crypto_cipher_blocksize(tfm);
+	unsigned int nbytes = walk->nbytes;
+	u8 *src = walk->src.virt.addr;
+	u8 *iv = walk->iv;
+	u8 tmpbuf[bsize];
+
+	do {
+		memcpy(tmpbuf, src, bsize);
+		fn(crypto_cipher_tfm(tfm), src, src);
+		xor(src, iv, bsize);
+		memcpy(iv, tmpbuf, bsize);
+		xor(iv, src, bsize);
+
+		src += bsize;
+	} while ((nbytes -= bsize) >= bsize);
+
+	memcpy(walk->iv, iv, bsize);
+
+	return nbytes;
+}
+
+static int crypto_pcbc_decrypt(struct blkcipher_desc *desc,
+			       struct scatterlist *dst, struct scatterlist *src,
+			       unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	struct crypto_blkcipher *tfm = desc->tfm;
+	struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
+	struct crypto_cipher *child = ctx->child;
+	void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		if (walk.src.virt.addr == walk.dst.virt.addr)
+			nbytes = crypto_pcbc_decrypt_inplace(desc, &walk, child,
+							     xor);
+		else
+			nbytes = crypto_pcbc_decrypt_segment(desc, &walk, child,
+							     xor);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static void xor_byte(u8 *a, const u8 *b, unsigned int bs)
+{
+	do {
+		*a++ ^= *b++;
+	} while (--bs);
+}
+
+static void xor_quad(u8 *dst, const u8 *src, unsigned int bs)
+{
+	u32 *a = (u32 *)dst;
+	u32 *b = (u32 *)src;
+
+	do {
+		*a++ ^= *b++;
+	} while ((bs -= 4));
+}
+
+static void xor_64(u8 *a, const u8 *b, unsigned int bs)
+{
+	((u32 *)a)[0] ^= ((u32 *)b)[0];
+	((u32 *)a)[1] ^= ((u32 *)b)[1];
+}
+
+static void xor_128(u8 *a, const u8 *b, unsigned int bs)
+{
+	((u32 *)a)[0] ^= ((u32 *)b)[0];
+	((u32 *)a)[1] ^= ((u32 *)b)[1];
+	((u32 *)a)[2] ^= ((u32 *)b)[2];
+	((u32 *)a)[3] ^= ((u32 *)b)[3];
+}
+
+static int crypto_pcbc_init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
+	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_cipher *cipher;
+
+	switch (crypto_tfm_alg_blocksize(tfm)) {
+	case 8:
+		ctx->xor = xor_64;
+		break;
+
+	case 16:
+		ctx->xor = xor_128;
+		break;
+
+	default:
+		if (crypto_tfm_alg_blocksize(tfm) % 4)
+			ctx->xor = xor_byte;
+		else
+			ctx->xor = xor_quad;
+	}
+
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
+
+	ctx->child = cipher;
+	return 0;
+}
+
+static void crypto_pcbc_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	crypto_free_cipher(ctx->child);
+}
+
+static struct crypto_instance *crypto_pcbc_alloc(void *param, unsigned int len)
+{
+	struct crypto_instance *inst;
+	struct crypto_alg *alg;
+
+	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	if (IS_ERR(alg))
+		return ERR_PTR(PTR_ERR(alg));
+
+	inst = crypto_alloc_instance("pcbc", alg);
+	if (IS_ERR(inst))
+		goto out_put_alg;
+
+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
+	inst->alg.cra_priority = alg->cra_priority;
+	inst->alg.cra_blocksize = alg->cra_blocksize;
+	inst->alg.cra_alignmask = alg->cra_alignmask;
+	inst->alg.cra_type = &crypto_blkcipher_type;
+
+	if (!(alg->cra_blocksize % 4))
+		inst->alg.cra_alignmask |= 3;
+	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
+	inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
+	inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+
+	inst->alg.cra_ctxsize = sizeof(struct crypto_pcbc_ctx);
+
+	inst->alg.cra_init = crypto_pcbc_init_tfm;
+	inst->alg.cra_exit = crypto_pcbc_exit_tfm;
+
+	inst->alg.cra_blkcipher.setkey = crypto_pcbc_setkey;
+	inst->alg.cra_blkcipher.encrypt = crypto_pcbc_encrypt;
+	inst->alg.cra_blkcipher.decrypt = crypto_pcbc_decrypt;
+
+out_put_alg:
+	crypto_mod_put(alg);
+	return inst;
+}
+
+static void crypto_pcbc_free(struct crypto_instance *inst)
+{
+	crypto_drop_spawn(crypto_instance_ctx(inst));
+	kfree(inst);
+}
+
+static struct crypto_template crypto_pcbc_tmpl = {
+	.name = "pcbc",
+	.alloc = crypto_pcbc_alloc,
+	.free = crypto_pcbc_free,
+	.module = THIS_MODULE,
+};
+
+static int __init crypto_pcbc_module_init(void)
+{
+	return crypto_register_template(&crypto_pcbc_tmpl);
+}
+
+static void __exit crypto_pcbc_module_exit(void)
+{
+	crypto_unregister_template(&crypto_pcbc_tmpl);
+}
+
+module_init(crypto_pcbc_module_init);
+module_exit(crypto_pcbc_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PCBC block cipher algorithm");
diff --git a/crypto/proc.c b/crypto/proc.c
index dabce06..102c751 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -101,7 +101,7 @@
 	return seq_open(file, &crypto_seq_ops);
 }
         
-static struct file_operations proc_crypto_ops = {
+static const struct file_operations proc_crypto_ops = {
 	.open		= crypto_info_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index d671e894..f5e9da3 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -12,6 +12,7 @@
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
+ * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
  * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>)
  * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
  *
@@ -71,7 +72,8 @@
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
 	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
-	"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", NULL
+	"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta",  "fcrypt",
+	"camellia", NULL
 };
 
 static void hexdump(unsigned char *buf, unsigned int len)
@@ -765,7 +767,7 @@
 	memcpy(tvmem, deflate_comp_tv_template, tsize);
 	tv = (void *)tvmem;
 
-	tfm = crypto_alloc_tfm("deflate", 0);
+	tfm = crypto_alloc_comp("deflate", 0, CRYPTO_ALG_ASYNC);
 	if (tfm == NULL) {
 		printk("failed to load transform for deflate\n");
 		return;
@@ -964,6 +966,26 @@
 		test_cipher("ecb(xeta)", DECRYPT, xeta_dec_tv_template,
 			    XETA_DEC_TEST_VECTORS);
 
+		//FCrypt
+		test_cipher("pcbc(fcrypt)", ENCRYPT, fcrypt_pcbc_enc_tv_template,
+			    FCRYPT_ENC_TEST_VECTORS);
+		test_cipher("pcbc(fcrypt)", DECRYPT, fcrypt_pcbc_dec_tv_template,
+			    FCRYPT_DEC_TEST_VECTORS);
+
+		//CAMELLIA
+		test_cipher("ecb(camellia)", ENCRYPT,
+			    camellia_enc_tv_template,
+			    CAMELLIA_ENC_TEST_VECTORS);
+		test_cipher("ecb(camellia)", DECRYPT,
+			    camellia_dec_tv_template,
+			    CAMELLIA_DEC_TEST_VECTORS);
+		test_cipher("cbc(camellia)", ENCRYPT,
+			    camellia_cbc_enc_tv_template,
+			    CAMELLIA_CBC_ENC_TEST_VECTORS);
+		test_cipher("cbc(camellia)", DECRYPT,
+			    camellia_cbc_dec_tv_template,
+			    CAMELLIA_CBC_DEC_TEST_VECTORS);
+
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
@@ -980,6 +1002,10 @@
 			  HMAC_SHA1_TEST_VECTORS);
 		test_hash("hmac(sha256)", hmac_sha256_tv_template,
 			  HMAC_SHA256_TEST_VECTORS);
+		test_hash("hmac(sha384)", hmac_sha384_tv_template,
+			  HMAC_SHA384_TEST_VECTORS);
+		test_hash("hmac(sha512)", hmac_sha512_tv_template,
+			  HMAC_SHA512_TEST_VECTORS);
 
 		test_hash("xcbc(aes)", aes_xcbc128_tv_template,
 			  XCBC_AES_TEST_VECTORS);
@@ -1177,6 +1203,28 @@
 			    XETA_DEC_TEST_VECTORS);
 		break;
 
+	case 31:
+		test_cipher("pcbc(fcrypt)", ENCRYPT, fcrypt_pcbc_enc_tv_template,
+			    FCRYPT_ENC_TEST_VECTORS);
+		test_cipher("pcbc(fcrypt)", DECRYPT, fcrypt_pcbc_dec_tv_template,
+			    FCRYPT_DEC_TEST_VECTORS);
+		break;
+
+	case 32:
+		test_cipher("ecb(camellia)", ENCRYPT,
+			    camellia_enc_tv_template,
+			    CAMELLIA_ENC_TEST_VECTORS);
+		test_cipher("ecb(camellia)", DECRYPT,
+			    camellia_dec_tv_template,
+			    CAMELLIA_DEC_TEST_VECTORS);
+		test_cipher("cbc(camellia)", ENCRYPT,
+			    camellia_cbc_enc_tv_template,
+			    CAMELLIA_CBC_ENC_TEST_VECTORS);
+		test_cipher("cbc(camellia)", DECRYPT,
+			    camellia_cbc_dec_tv_template,
+			    CAMELLIA_CBC_DEC_TEST_VECTORS);
+		break;
+
 	case 100:
 		test_hash("hmac(md5)", hmac_md5_tv_template,
 			  HMAC_MD5_TEST_VECTORS);
@@ -1192,6 +1240,16 @@
 			  HMAC_SHA256_TEST_VECTORS);
 		break;
 
+	case 103:
+		test_hash("hmac(sha384)", hmac_sha384_tv_template,
+			  HMAC_SHA384_TEST_VECTORS);
+		break;
+
+	case 104:
+		test_hash("hmac(sha512)", hmac_sha512_tv_template,
+			  HMAC_SHA512_TEST_VECTORS);
+		break;
+
 
 	case 200:
 		test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
@@ -1260,6 +1318,17 @@
 				  des_speed_template);
 		break;
 
+	case 205:
+		test_cipher_speed("ecb(camellia)", ENCRYPT, sec, NULL, 0,
+				camellia_speed_template);
+		test_cipher_speed("ecb(camellia)", DECRYPT, sec, NULL, 0,
+				camellia_speed_template);
+		test_cipher_speed("cbc(camellia)", ENCRYPT, sec, NULL, 0,
+				camellia_speed_template);
+		test_cipher_speed("cbc(camellia)", DECRYPT, sec, NULL, 0,
+				camellia_speed_template);
+		break;
+
 	case 300:
 		/* fall through */
 
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index 48a8136..887527b 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -12,6 +12,7 @@
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
+ * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
  * 2004-08-09 Cipher speed tests by Reyk Floeter <reyk@vantronix.net>
  * 2003-09-14 Changes by Kartikey Mahendra Bhatt
  *
@@ -27,7 +28,7 @@
 
 struct hash_testvec {
 	/* only used with keyed hash algorithms */
-	char key[128] __attribute__ ((__aligned__(4)));
+	char key[132] __attribute__ ((__aligned__(4)));
 	char plaintext[240];
 	char digest[MAX_DIGEST_SIZE];
 	unsigned char tap[MAX_TAP];
@@ -1002,6 +1003,248 @@
 };
 
 /*
+ * SHA384 HMAC test vectors from RFC4231
+ */
+
+#define HMAC_SHA384_TEST_VECTORS	4
+
+static struct hash_testvec hmac_sha384_tv_template[] = {
+	{
+		.key	= { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			    0x0b, 0x0b, 0x0b, 0x0b }, // (20 bytes)
+		.ksize	= 20,
+		.plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 }, // ("Hi There")
+		.psize	= 8,
+		.digest	= { 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62,
+			    0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f,
+			    0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
+			    0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c,
+			    0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f,
+			    0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6 },
+	}, {
+		.key	= { 0x4a, 0x65, 0x66, 0x65 }, // ("Jefe")
+		.ksize	= 4,
+		.plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+			       0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, // ("what do ya want ")
+			       0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+			       0x69, 0x6e, 0x67, 0x3f }, // ("for nothing?")
+		.psize	= 28,
+		.digest	= { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31,
+			    0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b,
+			    0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
+			    0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e,
+			    0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7,
+			    0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49 },
+		.np	= 4,
+		.tap	= { 7, 7, 7, 7 }
+	}, {
+		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa }, // (131 bytes)
+		.ksize	= 131,
+		.plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+			       0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, // ("Test Using Large")
+			       0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+			       0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, // ("r Than Block-Siz")
+			       0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+			       0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, // ("e Key - Hash Key")
+			       0x20, 0x46, 0x69, 0x72, 0x73, 0x74 }, // (" First")
+		.psize	= 54,
+		.digest	= { 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90,
+			    0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4,
+			    0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
+			    0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6,
+			    0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82,
+			    0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52 },
+	}, {
+		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa }, // (131 bytes)
+		.ksize	= 131,
+		.plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+			       0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, // ("This is a test u")
+			       0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+			       0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, // ("sing a larger th")
+			       0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+			       0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65, // ("an block-size ke")
+			       0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+			       0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, // ("y and a larger t")
+			       0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+			       0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, // ("han block-size d")
+			       0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+			       0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65, // ("ata. The key nee")
+			       0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+			       0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, // ("ds to be hashed ")
+			       0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+			       0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, // ("before being use")
+			       0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+			       0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c, // ("d by the HMAC al")
+			       0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e }, // ("gorithm.")
+		.psize	= 152,
+		.digest	= { 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d,
+			    0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c,
+			    0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
+			    0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5,
+			    0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d,
+			    0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e },
+	},
+};
+
+/*
+ * SHA512 HMAC test vectors from RFC4231
+ */
+
+#define HMAC_SHA512_TEST_VECTORS	4
+
+static struct hash_testvec hmac_sha512_tv_template[] = {
+	{
+		.key	= { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			    0x0b, 0x0b, 0x0b, 0x0b }, // (20 bytes)
+		.ksize	= 20,
+		.plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 }, // ("Hi There")
+		.psize	= 8,
+		.digest	= { 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
+			    0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
+			    0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
+			    0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
+			    0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02,
+			    0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
+			    0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70,
+			    0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54 },
+	}, {
+		.key	= { 0x4a, 0x65, 0x66, 0x65 }, // ("Jefe")
+		.ksize	= 4,
+		.plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+			       0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, // ("what do ya want ")
+			       0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+			       0x69, 0x6e, 0x67, 0x3f }, // ("for nothing?")
+		.psize	= 28,
+		.digest	= { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
+			    0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
+			    0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
+			    0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
+			    0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a,
+			    0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
+			    0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b,
+			    0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37 },
+		.np	= 4,
+		.tap	= { 7, 7, 7, 7 }
+	}, {
+		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa }, // (131 bytes)
+		.ksize	= 131,
+		.plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+			       0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, // ("Test Using Large")
+			       0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+			       0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, // ("r Than Block-Siz")
+			       0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+			       0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, // ("e Key - Hash Key")
+			       0x20, 0x46, 0x69, 0x72, 0x73, 0x74 }, // (" First")
+		.psize	= 54,
+		.digest	= { 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb,
+			    0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4,
+			    0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1,
+			    0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52,
+			    0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98,
+			    0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
+			    0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec,
+			    0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98 },
+	}, {
+		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa }, // (131 bytes)
+		.ksize	= 131,
+		.plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+			       0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, // ("This is a test u")
+			       0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+			       0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, // ("sing a larger th")
+			       0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+			       0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65, // ("an block-size ke")
+			       0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+			       0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, // ("y and a larger t")
+			       0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+			       0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, // ("han block-size d")
+			       0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+			       0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65, // ("ata. The key nee")
+			       0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+			       0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, // ("ds to be hashed ")
+			       0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+			       0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, // ("before being use")
+			       0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+			       0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c, // ("d by the HMAC al")
+			       0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e }, // ("gorithm.")
+		.psize	= 152,
+		.digest	= { 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba,
+			    0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd,
+			    0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86,
+			    0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44,
+			    0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1,
+			    0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15,
+			    0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60,
+			    0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58 },
+	},
+};
+
+/*
  * DES test vectors.
  */
 #define DES_ENC_TEST_VECTORS		10
@@ -3316,6 +3559,278 @@
 	}
 };
 
+/* 
+ * FCrypt test vectors 
+ */
+#define FCRYPT_ENC_TEST_VECTORS	ARRAY_SIZE(fcrypt_pcbc_enc_tv_template)
+#define FCRYPT_DEC_TEST_VECTORS	ARRAY_SIZE(fcrypt_pcbc_dec_tv_template)
+
+static struct cipher_testvec fcrypt_pcbc_enc_tv_template[] = {
+	{ /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0x0E, 0x09, 0x00, 0xC7, 0x3E, 0xF7, 0xED, 0x41 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x11, 0x44, 0x77, 0xAA, 0xDD, 0x00, 0x33, 0x66 },
+		.klen	= 8,
+		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 },
+		.ilen	= 8,
+		.result	= { 0xD8, 0xED, 0x78, 0x74, 0x77, 0xEC, 0x06, 0x80 },
+		.rlen	= 8,
+	}, { /* From Arla */
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.klen	= 8,
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.input	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.ilen	= 48,
+		.result	= { 0x00, 0xf0, 0xe,  0x11, 0x75, 0xe6, 0x23, 0x82,
+			    0xee, 0xac, 0x98, 0x62, 0x44, 0x51, 0xe4, 0x84,
+			    0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7,
+			    0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03,
+			    0x23, 0xb5, 0x62, 0xd7, 0x0c, 0xf5, 0x27, 0xd1,
+			    0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef },
+		.rlen	= 48,
+	}, {
+		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 8,
+		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.input	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.ilen	= 48,
+		.result	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
+		.rlen	= 48,
+	}, { /* split-page version */
+		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 8,
+		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.input	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.ilen	= 48,
+		.result	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
+		.rlen	= 48,
+		.np	= 2,
+		.tap	= { 20, 28 },
+	}
+};
+
+static struct cipher_testvec fcrypt_pcbc_dec_tv_template[] = {
+	{ /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input	= { 0x0E, 0x09, 0x00, 0xC7, 0x3E, 0xF7, 0xED, 0x41 },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x11, 0x44, 0x77, 0xAA, 0xDD, 0x00, 0x33, 0x66 },
+		.klen	= 8,
+		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input	= { 0xD8, 0xED, 0x78, 0x74, 0x77, 0xEC, 0x06, 0x80 },
+		.ilen	= 8,
+		.result	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 },
+		.rlen	= 8,
+	}, { /* From Arla */
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.klen	= 8,
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.input	= { 0x00, 0xf0, 0xe,  0x11, 0x75, 0xe6, 0x23, 0x82,
+			    0xee, 0xac, 0x98, 0x62, 0x44, 0x51, 0xe4, 0x84,
+			    0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7,
+			    0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03,
+			    0x23, 0xb5, 0x62, 0xd7, 0x0c, 0xf5, 0x27, 0xd1,
+			    0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef },
+		.ilen	= 48,
+		.result	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.rlen	= 48,
+	}, {
+		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 8,
+		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.input	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
+		.ilen	= 48,
+		.result	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.rlen	= 48,
+	}, { /* split-page version */
+		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 8,
+		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.input	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
+		.ilen	= 48,
+		.result	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.rlen	= 48,
+		.np	= 2,
+		.tap	= { 20, 28 },
+	}
+};
+
+/*
+ * CAMELLIA test vectors.
+ */
+#define CAMELLIA_ENC_TEST_VECTORS 3
+#define CAMELLIA_DEC_TEST_VECTORS 3
+#define CAMELLIA_CBC_ENC_TEST_VECTORS 2
+#define CAMELLIA_CBC_DEC_TEST_VECTORS 2
+
+static struct cipher_testvec camellia_enc_tv_template[] = {
+	{
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 16,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.ilen	= 16,
+		.result	= { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+			    0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+		.klen	= 24,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.ilen	= 16,
+		.result	= { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+			    0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.klen	= 32,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.ilen	= 16,
+		.result	= { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+			    0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
+		.rlen	= 16,
+	},
+};
+
+static struct cipher_testvec camellia_dec_tv_template[] = {
+	{
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 16,
+		.input	= { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+			    0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
+		.ilen	= 16,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+		.klen	= 24,
+		.input	= { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+			    0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
+		.ilen	= 16,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.klen	= 32,
+		.input	= { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+			    0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
+		.ilen	= 16,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.rlen	= 16,
+	},
+};
+
+static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
+	{
+		.key    = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+			    0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
+		.klen   = 16,
+		.iv	= { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+			    0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+		.input	= { "Single block msg" },
+		.ilen   = 16,
+		.result = { 0xea, 0x32, 0x12, 0x76, 0x3b, 0x50, 0x10, 0xe7,
+			    0x18, 0xf6, 0xfd, 0x5d, 0xf6, 0x8f, 0x13, 0x51 },
+		.rlen   = 16,
+	}, {
+		.key    = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+			    0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
+		.klen   = 16,
+		.iv     = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+			    0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+		.input  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+		.ilen   = 32,
+		.result = { 0xa5, 0xdf, 0x6e, 0x50, 0xda, 0x70, 0x6c, 0x01,
+			    0x4a, 0xab, 0xf3, 0xf2, 0xd6, 0xfc, 0x6c, 0xfd,
+			    0x19, 0xb4, 0x3e, 0x57, 0x1c, 0x02, 0x5e, 0xa0,
+			    0x15, 0x78, 0xe0, 0x5e, 0xf2, 0xcb, 0x87, 0x16 },
+		.rlen   = 32,
+	},
+};
+
+static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
+	{
+		.key    = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+			    0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
+		.klen   = 16,
+		.iv	= { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+			    0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+		.input	= { 0xea, 0x32, 0x12, 0x76, 0x3b, 0x50, 0x10, 0xe7,
+			    0x18, 0xf6, 0xfd, 0x5d, 0xf6, 0x8f, 0x13, 0x51 },
+		.ilen   = 16,
+		.result = { "Single block msg" },
+		.rlen   = 16,
+	}, {
+		.key    = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+			    0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
+		.klen   = 16,
+		.iv     = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+			    0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+		.input = { 0xa5, 0xdf, 0x6e, 0x50, 0xda, 0x70, 0x6c, 0x01,
+			    0x4a, 0xab, 0xf3, 0xf2, 0xd6, 0xfc, 0x6c, 0xfd,
+			    0x19, 0xb4, 0x3e, 0x57, 0x1c, 0x02, 0x5e, 0xa0,
+			    0x15, 0x78, 0xe0, 0x5e, 0xf2, 0xcb, 0x87, 0x16 },
+		.ilen   = 32,
+		.result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+		.rlen   = 32,
+	},
+};
+
 /*
  * Compression stuff.
  */
@@ -3769,4 +4284,25 @@
 	{  .blen = 0,	.plen = 0, }
 };
 
+static struct cipher_speed camellia_speed_template[] = {
+      { .klen = 16, .blen = 16, },
+      { .klen = 16, .blen = 64, },
+      { .klen = 16, .blen = 256, },
+      { .klen = 16, .blen = 1024, },
+      { .klen = 16, .blen = 8192, },
+      { .klen = 24, .blen = 16, },
+      { .klen = 24, .blen = 64, },
+      { .klen = 24, .blen = 256, },
+      { .klen = 24, .blen = 1024, },
+      { .klen = 24, .blen = 8192, },
+      { .klen = 32, .blen = 16, },
+      { .klen = 32, .blen = 64, },
+      { .klen = 32, .blen = 256, },
+      { .klen = 32, .blen = 1024, },
+      { .klen = 32, .blen = 8192, },
+
+      /* End marker */
+      {  .klen = 0, .blen = 0, }
+};
+
 #endif	/* _CRYPTO_TCRYPT_H */
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
index 9347eb6..53e8ccb 100644
--- a/crypto/xcbc.c
+++ b/crypto/xcbc.c
@@ -21,6 +21,7 @@
 
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <linux/hardirq.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/rtnetlink.h>
@@ -47,7 +48,7 @@
  * +------------------------
  */
 struct crypto_xcbc_ctx {
-	struct crypto_tfm *child;
+	struct crypto_cipher *child;
 	u8 *odds;
 	u8 *prev;
 	u8 *key;
@@ -75,8 +76,7 @@
 	if ((err = crypto_cipher_setkey(ctx->child, ctx->key, ctx->keylen)))
 	    return err;
 
-	ctx->child->__crt_alg->cra_cipher.cia_encrypt(ctx->child, key1,
-			ctx->consts);
+	crypto_cipher_encrypt_one(ctx->child, key1, ctx->consts);
 
 	return crypto_cipher_setkey(ctx->child, key1, bs);
 }
@@ -86,7 +86,7 @@
 {
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
 
-	if (keylen != crypto_tfm_alg_blocksize(ctx->child))
+	if (keylen != crypto_cipher_blocksize(ctx->child))
 		return -EINVAL;
 
 	ctx->keylen = keylen;
@@ -108,13 +108,13 @@
 	return 0;
 }
 
-static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
-				     struct scatterlist *sg,
-				     unsigned int nbytes)
+static int crypto_xcbc_digest_update2(struct hash_desc *pdesc,
+				      struct scatterlist *sg,
+				      unsigned int nbytes)
 {
 	struct crypto_hash *parent = pdesc->tfm;
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
-	struct crypto_tfm *tfm = ctx->child;
+	struct crypto_cipher *tfm = ctx->child;
 	int bs = crypto_hash_blocksize(parent);
 	unsigned int i = 0;
 
@@ -142,7 +142,7 @@
 					offset += len;
 
 				crypto_kunmap(p, 0);
-				crypto_yield(tfm->crt_flags);
+				crypto_yield(pdesc->flags);
 				continue;
 			}
 
@@ -152,7 +152,7 @@
 			p += bs - ctx->len;
 
 			ctx->xor(ctx->prev, ctx->odds, bs);
-			tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev);
+			crypto_cipher_encrypt_one(tfm, ctx->prev, ctx->prev);
 
 			/* clearing the length */
 			ctx->len = 0;
@@ -160,7 +160,8 @@
 			/* encrypting the rest of data */
 			while (len > bs) {
 				ctx->xor(ctx->prev, p, bs);
-				tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev);
+				crypto_cipher_encrypt_one(tfm, ctx->prev,
+							  ctx->prev);
 				p += bs;
 				len -= bs;
 			}
@@ -171,7 +172,7 @@
 				ctx->len = len;
 			}
 			crypto_kunmap(p, 0);
-			crypto_yield(tfm->crt_flags);
+			crypto_yield(pdesc->flags);
 			slen -= min(slen, ((unsigned int)(PAGE_SIZE)) - offset);
 			offset = 0;
 			pg++;
@@ -183,11 +184,20 @@
 	return 0;
 }
 
+static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
+				     struct scatterlist *sg,
+				     unsigned int nbytes)
+{
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+	return crypto_xcbc_digest_update2(pdesc, sg, nbytes);
+}
+
 static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
 {
 	struct crypto_hash *parent = pdesc->tfm;
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
-	struct crypto_tfm *tfm = ctx->child;
+	struct crypto_cipher *tfm = ctx->child;
 	int bs = crypto_hash_blocksize(parent);
 	int err = 0;
 
@@ -197,13 +207,14 @@
 		if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
 			return err;
 
-		tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key2, (const u8*)(ctx->consts+bs));
+		crypto_cipher_encrypt_one(tfm, key2,
+					  (u8 *)(ctx->consts + bs));
 
 		ctx->xor(ctx->prev, ctx->odds, bs);
 		ctx->xor(ctx->prev, key2, bs);
 		_crypto_xcbc_digest_setkey(parent, ctx);
 
-		tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev);
+		crypto_cipher_encrypt_one(tfm, out, ctx->prev);
 	} else {
 		u8 key3[bs];
 		unsigned int rlen;
@@ -218,14 +229,15 @@
 		if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
 			return err;
 
-		tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key3, (const u8*)(ctx->consts+bs*2));
+		crypto_cipher_encrypt_one(tfm, key3,
+					  (u8 *)(ctx->consts + bs * 2));
 
 		ctx->xor(ctx->prev, ctx->odds, bs);
 		ctx->xor(ctx->prev, key3, bs);
 
 		_crypto_xcbc_digest_setkey(parent, ctx);
 
-		tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev);
+		crypto_cipher_encrypt_one(tfm, out, ctx->prev);
 	}
 
 	return 0;
@@ -234,21 +246,25 @@
 static int crypto_xcbc_digest(struct hash_desc *pdesc,
 		  struct scatterlist *sg, unsigned int nbytes, u8 *out)
 {
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+
 	crypto_xcbc_digest_init(pdesc);
-	crypto_xcbc_digest_update(pdesc, sg, nbytes);
+	crypto_xcbc_digest_update2(pdesc, sg, nbytes);
 	return crypto_xcbc_digest_final(pdesc, out);
 }
 
 static int xcbc_init_tfm(struct crypto_tfm *tfm)
 {
+	struct crypto_cipher *cipher;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm));
 	int bs = crypto_hash_blocksize(__crypto_hash_cast(tfm));
 
-	tfm = crypto_spawn_tfm(spawn);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
 
 	switch(bs) {
 	case 16:
@@ -258,7 +274,7 @@
 		return -EINVAL;
 	}
 
-	ctx->child = crypto_cipher_cast(tfm);
+	ctx->child = cipher;
 	ctx->odds = (u8*)(ctx+1);
 	ctx->prev = ctx->odds + bs;
 	ctx->key = ctx->prev + bs;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index e7da9fa..050323f 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -80,6 +80,8 @@
 
 source "drivers/dma/Kconfig"
 
+source "drivers/auxdisplay/Kconfig"
+
 source "drivers/kvm/Kconfig"
 
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 0dd96d1..3a718f5 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -30,7 +30,7 @@
 obj-y				+= base/ block/ misc/ mfd/ net/ media/
 obj-$(CONFIG_NUBUS)		+= nubus/
 obj-$(CONFIG_ATM)		+= atm/
-obj-$(CONFIG_PPC_PMAC)		+= macintosh/
+obj-y				+= macintosh/
 obj-$(CONFIG_IDE)		+= ide/
 obj-$(CONFIG_FC4)		+= fc4/
 obj-$(CONFIG_SCSI)		+= scsi/
@@ -38,6 +38,7 @@
 obj-$(CONFIG_FUSION)		+= message/
 obj-$(CONFIG_IEEE1394)		+= ieee1394/
 obj-y				+= cdrom/
+obj-y				+= auxdisplay/
 obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_SPI)		+= spi/
 obj-$(CONFIG_PCCARD)		+= pcmcia/
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 7fde8f4..689a4c3 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -99,7 +99,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c
index 9e584a7..d276fd1 100644
--- a/drivers/acorn/char/i2c.c
+++ b/drivers/acorn/char/i2c.c
@@ -14,7 +14,6 @@
  */
 #include <linux/capability.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/miscdevice.h>
 #include <linux/rtc.h>
@@ -238,7 +237,7 @@
 	return -EINVAL;
 }
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.ioctl	= rtc_ioctl,
 };
 
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 20eacc2..e942ffe 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -13,6 +13,7 @@
 	depends on IA64 || X86
 	depends on PCI
 	depends on PM
+	select PNP
 	default y
 	---help---
 	  Advanced Configuration and Power Interface (ACPI) support for 
@@ -132,15 +133,6 @@
 	  Note that this is an ref. implementation only.  It may or may not work
 	  for your integrated video device.
 
-config ACPI_HOTKEY
-	tristate "Generic Hotkey (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	depends on X86
-	default n
-	help
-	  Experimental consolidated hotkey driver.
-	  If you are unsure, say N.
-
 config ACPI_FAN
 	tristate "Fan"
 	default y
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 856c32b..5956e9f 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -46,7 +46,6 @@
 obj-$(CONFIG_ACPI_DOCK)		+= dock.o
 obj-$(CONFIG_ACPI_BAY)		+= bay.o
 obj-$(CONFIG_ACPI_VIDEO)	+= video.o
-obj-$(CONFIG_ACPI_HOTKEY)	+= hotkey.o
 obj-y				+= pci_root.o pci_link.o pci_irq.o pci_bind.o
 obj-$(CONFIG_ACPI_POWER)	+= power.o
 obj-$(CONFIG_ACPI_PROCESSOR)	+= processor.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 6daeace..37c7dc4 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -35,7 +35,6 @@
 #define ACPI_AC_COMPONENT		0x00020000
 #define ACPI_AC_CLASS			"ac_adapter"
 #define ACPI_AC_HID 			"ACPI0003"
-#define ACPI_AC_DRIVER_NAME		"ACPI AC Adapter Driver"
 #define ACPI_AC_DEVICE_NAME		"AC Adapter"
 #define ACPI_AC_FILE_STATE		"state"
 #define ACPI_AC_NOTIFY_STATUS		0x80
@@ -44,10 +43,10 @@
 #define ACPI_AC_STATUS_UNKNOWN		0xFF
 
 #define _COMPONENT		ACPI_AC_COMPONENT
-ACPI_MODULE_NAME("acpi_ac")
+ACPI_MODULE_NAME("ac");
 
-    MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI AC Adapter Driver");
 MODULE_LICENSE("GPL");
 
 extern struct proc_dir_entry *acpi_lock_ac_dir(void);
@@ -58,7 +57,7 @@
 static int acpi_ac_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_ac_driver = {
-	.name = ACPI_AC_DRIVER_NAME,
+	.name = "ac",
 	.class = ACPI_AC_CLASS,
 	.ids = ACPI_AC_HID,
 	.ops = {
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index cd946ed..c261726 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -35,14 +35,13 @@
 #define ACPI_MEMORY_DEVICE_COMPONENT		0x08000000UL
 #define ACPI_MEMORY_DEVICE_CLASS		"memory"
 #define ACPI_MEMORY_DEVICE_HID			"PNP0C80"
-#define ACPI_MEMORY_DEVICE_DRIVER_NAME		"Hotplug Mem Driver"
 #define ACPI_MEMORY_DEVICE_NAME			"Hotplug Mem Device"
 
 #define _COMPONENT		ACPI_MEMORY_DEVICE_COMPONENT
 
-ACPI_MODULE_NAME("acpi_memory")
-    MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
-MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME);
+ACPI_MODULE_NAME("acpi_memhotplug");
+MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
+MODULE_DESCRIPTION("Hotplug Mem Driver");
 MODULE_LICENSE("GPL");
 
 /* ACPI _STA method values */
@@ -60,7 +59,7 @@
 static int acpi_memory_device_start(struct acpi_device *device);
 
 static struct acpi_driver acpi_memory_device_driver = {
-	.name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
+	.name = "acpi_memhotplug",
 	.class = ACPI_MEMORY_DEVICE_CLASS,
 	.ids = ACPI_MEMORY_DEVICE_HID,
 	.ops = {
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index 31ad70a..b770dea 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -141,6 +141,7 @@
 		W5A,		//W5A
 		W3V,            //W3030V
 		xxN,		//M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
+		A4S,            //Z81sp
 		//(Centrino)
 		END_MODEL
 	} model;		//Models currently supported
@@ -397,7 +398,16 @@
 	 .brightness_set = "SPLV",
 	 .brightness_get = "GPLV",
 	 .display_set = "SDSP",
-	 .display_get = "\\ADVG"}
+	.display_get = "\\ADVG"},
+
+	{
+		.name              = "A4S",
+		.brightness_set    = "SPLV",
+		.brightness_get    = "GPLV",
+		.mt_bt_switch      = "BLED",
+		.mt_wled           = "WLED"
+	}
+
 };
 
 /* procdir we use */
@@ -421,7 +431,7 @@
 static int asus_hotk_add(struct acpi_device *device);
 static int asus_hotk_remove(struct acpi_device *device, int type);
 static struct acpi_driver asus_hotk_driver = {
-	.name = ACPI_HOTK_NAME,
+	.name = "asus_acpi",
 	.class = ACPI_HOTK_CLASS,
 	.ids = ACPI_HOTK_HID,
 	.ops = {
@@ -838,7 +848,7 @@
 
 static int set_brightness_status(struct backlight_device *bd)
 {
-	return set_brightness(bd->props->brightness);
+	return set_brightness(bd->props.brightness);
 }
 
 static int
@@ -1117,6 +1127,8 @@
 		return W3V;
 	else if (strncmp(model, "W5A", 3) == 0)
 		return W5A;
+	else if (strncmp(model, "A4S", 3) == 0)
+		return A4S;
 	else
 		return END_MODEL;
 }
@@ -1340,11 +1352,9 @@
 	return 0;
 }
 
-static struct backlight_properties asus_backlight_data = {
-        .owner          = THIS_MODULE,
+static struct backlight_ops asus_backlight_data = {
         .get_brightness = read_brightness,
         .update_status  = set_brightness_status,
-        .max_brightness = 15,
 };
 
 static void __exit asus_acpi_exit(void)
@@ -1365,10 +1375,6 @@
 	if (acpi_disabled)
 		return -ENODEV;
 
-	if (!acpi_specific_hotkey_enabled) {
-		printk(KERN_ERR "Using generic hotkey driver\n");
-		return -ENODEV;
-	}
 	asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
 	if (!asus_proc_dir) {
 		printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
@@ -1402,6 +1408,7 @@
 		asus_backlight_device = NULL;
 		asus_acpi_exit();
 	}
+        asus_backlight_device->props.max_brightness = 15;
 
 	return 0;
 }
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 2f4521a..e64c76c 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -42,7 +42,6 @@
 #define ACPI_BATTERY_COMPONENT		0x00040000
 #define ACPI_BATTERY_CLASS		"battery"
 #define ACPI_BATTERY_HID		"PNP0C0A"
-#define ACPI_BATTERY_DRIVER_NAME	"ACPI Battery Driver"
 #define ACPI_BATTERY_DEVICE_NAME	"Battery"
 #define ACPI_BATTERY_FILE_INFO		"info"
 #define ACPI_BATTERY_FILE_STATUS	"state"
@@ -53,10 +52,10 @@
 #define ACPI_BATTERY_UNITS_AMPS		"mA"
 
 #define _COMPONENT		ACPI_BATTERY_COMPONENT
-ACPI_MODULE_NAME("acpi_battery")
+ACPI_MODULE_NAME("battery");
 
-    MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Battery Driver");
 MODULE_LICENSE("GPL");
 
 extern struct proc_dir_entry *acpi_lock_battery_dir(void);
@@ -67,7 +66,7 @@
 static int acpi_battery_resume(struct acpi_device *device);
 
 static struct acpi_driver acpi_battery_driver = {
-	.name = ACPI_BATTERY_DRIVER_NAME,
+	.name = "battery",
 	.class = ACPI_BATTERY_CLASS,
 	.ids = ACPI_BATTERY_HID,
 	.ops = {
@@ -324,6 +323,13 @@
 	return result;
 }
 
+static void acpi_battery_check_present(struct acpi_battery *battery)
+{
+	if (!battery->flags.present) {
+		acpi_battery_check(battery);
+	}
+}
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -340,6 +346,8 @@
 	if (!battery)
 		goto end;
 
+	acpi_battery_check_present(battery);
+
 	if (battery->flags.present)
 		seq_printf(seq, "present:                 yes\n");
 	else {
@@ -424,6 +432,8 @@
 	if (!battery)
 		goto end;
 
+	acpi_battery_check_present(battery);
+
 	if (battery->flags.present)
 		seq_printf(seq, "present:                 yes\n");
 	else {
@@ -499,6 +509,8 @@
 	if (!battery)
 		goto end;
 
+	acpi_battery_check_present(battery);
+
 	if (!battery->flags.present) {
 		seq_printf(seq, "present:                 no\n");
 		goto end;
@@ -536,6 +548,8 @@
 	if (!battery || (count > sizeof(alarm_string) - 1))
 		return -EINVAL;
 
+	acpi_battery_check_present(battery);
+
 	if (!battery->flags.present)
 		return -ENODEV;
 
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
index 667fa1d..fb3f31b 100644
--- a/drivers/acpi/bay.c
+++ b/drivers/acpi/bay.c
@@ -32,11 +32,9 @@
 #include <asm/uaccess.h>
 #include <linux/platform_device.h>
 
-#define ACPI_BAY_DRIVER_NAME "ACPI Removable Drive Bay Driver"
-
-ACPI_MODULE_NAME("bay")
+ACPI_MODULE_NAME("bay");
 MODULE_AUTHOR("Kristen Carlson Accardi");
-MODULE_DESCRIPTION(ACPI_BAY_DRIVER_NAME);
+MODULE_DESCRIPTION("ACPI Removable Drive Bay Driver");
 MODULE_LICENSE("GPL");
 #define ACPI_BAY_CLASS "bay"
 #define ACPI_BAY_COMPONENT	0x10000000
@@ -47,18 +45,6 @@
 	acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
 	printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
 static void bay_notify(acpi_handle handle, u32 event, void *data);
-static int acpi_bay_add(struct acpi_device *device);
-static int acpi_bay_remove(struct acpi_device *device, int type);
-
-static struct acpi_driver acpi_bay_driver = {
-	.name = ACPI_BAY_DRIVER_NAME,
-	.class = ACPI_BAY_CLASS,
-	.ids = ACPI_BAY_HID,
-	.ops = {
-		.add = acpi_bay_add,
-		.remove = acpi_bay_remove,
-		},
-};
 
 struct bay {
 	acpi_handle handle;
@@ -234,14 +220,6 @@
 }
 EXPORT_SYMBOL_GPL(eject_removable_drive);
 
-static int acpi_bay_add(struct acpi_device *device)
-{
-	bay_dprintk(device->handle, "adding bay device");
-	strcpy(acpi_device_name(device), "Dockable Bay");
-	strcpy(acpi_device_class(device), "bay");
-	return 0;
-}
-
 static int acpi_bay_add_fs(struct bay *bay)
 {
 	int ret;
@@ -296,14 +274,14 @@
 	/*
 	 * Initialize bay device structure
 	 */
-	new_bay = kzalloc(GFP_ATOMIC, sizeof(*new_bay));
+	new_bay = kzalloc(sizeof(*new_bay), GFP_ATOMIC);
 	INIT_LIST_HEAD(&new_bay->list);
 	new_bay->handle = handle;
 	new_bay->name = (char *)nbuffer.pointer;
 
 	/* initialize platform device stuff */
 	pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0);
-	if (pdev == NULL) {
+	if (IS_ERR(pdev)) {
 		printk(KERN_ERR PREFIX "Error registering bay device\n");
 		goto bay_add_err;
 	}
@@ -339,52 +317,6 @@
 	return -ENODEV;
 }
 
-static int acpi_bay_remove(struct acpi_device *device, int type)
-{
-	/*** FIXME: do something here */
-	return 0;
-}
-
-/**
- * bay_create_acpi_device - add new devices to acpi
- * @handle - handle of the device to add
- *
- *  This function will create a new acpi_device for the given
- *  handle if one does not exist already.  This should cause
- *  acpi to scan for drivers for the given devices, and call
- *  matching driver's add routine.
- *
- *  Returns a pointer to the acpi_device corresponding to the handle.
- */
-static struct acpi_device * bay_create_acpi_device(acpi_handle handle)
-{
-	struct acpi_device *device = NULL;
-	struct acpi_device *parent_device;
-	acpi_handle parent;
-	int ret;
-
-	bay_dprintk(handle, "Trying to get device");
-	if (acpi_bus_get_device(handle, &device)) {
-		/*
-		 * no device created for this object,
-		 * so we should create one.
-		 */
-		bay_dprintk(handle, "No device for handle");
-		acpi_get_parent(handle, &parent);
-		if (acpi_bus_get_device(parent, &parent_device))
-			parent_device = NULL;
-
-		ret = acpi_bus_add(&device, parent_device, handle,
-			ACPI_BUS_TYPE_DEVICE);
-		if (ret) {
-			pr_debug("error adding bus, %x\n",
-				-ret);
-			return NULL;
-		}
-	}
-	return device;
-}
-
 /**
  * bay_notify - act upon an acpi bay notification
  * @handle: the bay handle
@@ -394,38 +326,19 @@
  */
 static void bay_notify(acpi_handle handle, u32 event, void *data)
 {
-	struct acpi_device *dev;
+	struct bay *bay_dev = (struct bay *)data;
+	struct device *dev = &bay_dev->pdev->dev;
 
 	bay_dprintk(handle, "Bay event");
 
 	switch(event) {
 	case ACPI_NOTIFY_BUS_CHECK:
-		printk("Bus Check\n");
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		printk("Device Check\n");
-		dev = bay_create_acpi_device(handle);
-		if (dev)
-			acpi_bus_generate_event(dev, event, 0);
-		else
-			printk("No device for generating event\n");
-		/* wouldn't it be a good idea to just rescan SATA
-		 * right here?
-		 */
-		break;
 	case ACPI_NOTIFY_EJECT_REQUEST:
-		printk("Eject request\n");
-		dev = bay_create_acpi_device(handle);
-		if (dev)
-			acpi_bus_generate_event(dev, event, 0);
-		else
-			printk("No device for generating eventn");
-
-		/* wouldn't it be a good idea to just call the
-		 * eject_device here if we were a SATA device?
-		 */
+		kobject_uevent(&dev->kobj, KOBJ_CHANGE);
 		break;
 	default:
-		printk("unknown event %d\n", event);
+		printk(KERN_ERR PREFIX "Bay: unknown event %d\n", event);
 	}
 }
 
@@ -457,10 +370,6 @@
 	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
 		ACPI_UINT32_MAX, find_bay, &bays, NULL);
 
-	if (bays)
-		if ((acpi_bus_register_driver(&acpi_bay_driver) < 0))
-			printk(KERN_ERR "Unable to register bay driver\n");
-
 	if (!bays)
 		return -ENODEV;
 
@@ -481,8 +390,6 @@
 		kfree(bay->name);
 		kfree(bay);
 	}
-
-	acpi_bus_unregister_driver(&acpi_bay_driver);
 }
 
 postcore_initcall(bay_init);
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index c26468d..dd49ea0 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -39,7 +39,7 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT		ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME("acpi_bus")
+ACPI_MODULE_NAME("bus");
 #ifdef	CONFIG_X86
 extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
 #endif
@@ -147,7 +147,7 @@
 			*state = ACPI_STATE_D0;
 	} else {
 		/*
-		 * Get the device's power state either directly (via _PSC) or 
+		 * Get the device's power state either directly (via _PSC) or
 		 * indirectly (via power resources).
 		 */
 		if (device->power.flags.explicit_get) {
@@ -199,15 +199,14 @@
 	 * Get device's current power state if it's unknown
 	 * This means device power state isn't initialized or previous setting failed
 	 */
-	if (!device->flags.force_power_state) {
-		if (device->power.state == ACPI_STATE_UNKNOWN)
-			acpi_bus_get_power(device->handle, &device->power.state);
-		if (state == device->power.state) {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
-					  state));
-			return 0;
-		}
+	if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state)
+		acpi_bus_get_power(device->handle, &device->power.state);
+	if ((state == device->power.state) && !device->flags.force_power_state) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
+				  state));
+		return 0;
 	}
+
 	if (!device->power.states[state].flags.valid) {
 		printk(KERN_WARNING PREFIX "Device does not support D%d\n", state);
 		return -ENODEV;
@@ -462,7 +461,7 @@
 				  "Received BUS CHECK notification for device [%s]\n",
 				  device->pnp.bus_id));
 		result = acpi_bus_check_scope(device);
-		/* 
+		/*
 		 * TBD: We'll need to outsource certain events to non-ACPI
 		 *      drivers via the device manager (device.c).
 		 */
@@ -473,7 +472,7 @@
 				  "Received DEVICE CHECK notification for device [%s]\n",
 				  device->pnp.bus_id));
 		result = acpi_bus_check_device(device, NULL);
-		/* 
+		/*
 		 * TBD: We'll need to outsource certain events to non-ACPI
 		 *      drivers via the device manager (device.c).
 		 */
@@ -543,7 +542,7 @@
 	char *message = NULL;
 
 
-	/* 
+	/*
 	 * Let the system know what interrupt model we are using by
 	 * evaluating the \_PIC object, if exists.
 	 */
@@ -684,7 +683,7 @@
 	 * the EC device is found in the namespace (i.e. before acpi_initialize_objects()
 	 * is called).
 	 *
-	 * This is accomplished by looking for the ECDT table, and getting 
+	 * This is accomplished by looking for the ECDT table, and getting
 	 * the EC parameters out of that.
 	 */
 	status = acpi_ec_ecdt_probe();
@@ -699,6 +698,9 @@
 
 	printk(KERN_INFO PREFIX "Interpreter enabled\n");
 
+	/* Initialize sleep structures */
+	acpi_sleep_init();
+
 	/*
 	 * Get the system interrupt model and evaluate \_PIC.
 	 */
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index c726612..cb4110b 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -34,7 +34,6 @@
 #include <acpi/acpi_drivers.h>
 
 #define ACPI_BUTTON_COMPONENT		0x00080000
-#define ACPI_BUTTON_DRIVER_NAME		"ACPI Button Driver"
 #define ACPI_BUTTON_CLASS		"button"
 #define ACPI_BUTTON_FILE_INFO		"info"
 #define ACPI_BUTTON_FILE_STATE		"state"
@@ -61,10 +60,10 @@
 #define ACPI_BUTTON_TYPE_LID		0x05
 
 #define _COMPONENT		ACPI_BUTTON_COMPONENT
-ACPI_MODULE_NAME("acpi_button")
+ACPI_MODULE_NAME("button");
 
 MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
+MODULE_DESCRIPTION("ACPI Button Driver");
 MODULE_LICENSE("GPL");
 
 static int acpi_button_add(struct acpi_device *device);
@@ -73,7 +72,7 @@
 static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_button_driver = {
-	.name = ACPI_BUTTON_DRIVER_NAME,
+	.name = "button",
 	.class = ACPI_BUTTON_CLASS,
 	.ids = "button_power,button_sleep,PNP0C0D,PNP0C0C,PNP0C0E",
 	.ops = {
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
index 4a9b7bf..f9db4f4 100644
--- a/drivers/acpi/cm_sbs.c
+++ b/drivers/acpi/cm_sbs.c
@@ -31,7 +31,7 @@
 #include <acpi/actypes.h>
 #include <acpi/acutils.h>
 
-ACPI_MODULE_NAME("cm_sbs")
+ACPI_MODULE_NAME("cm_sbs");
 #define ACPI_AC_CLASS		"ac_adapter"
 #define ACPI_BATTERY_CLASS	"battery"
 #define ACPI_SBS_COMPONENT	0x00080000
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 69a68fd..0930d94 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -35,7 +35,6 @@
 #include <acpi/acpi_drivers.h>
 #include <acpi/container.h>
 
-#define ACPI_CONTAINER_DRIVER_NAME	"ACPI container driver"
 #define ACPI_CONTAINER_DEVICE_NAME	"ACPI container device"
 #define ACPI_CONTAINER_CLASS		"container"
 
@@ -44,10 +43,10 @@
 
 #define ACPI_CONTAINER_COMPONENT	0x01000000
 #define _COMPONENT			ACPI_CONTAINER_COMPONENT
-ACPI_MODULE_NAME("acpi_container")
+ACPI_MODULE_NAME("container");
 
-    MODULE_AUTHOR("Anil S Keshavamurthy");
-MODULE_DESCRIPTION(ACPI_CONTAINER_DRIVER_NAME);
+MODULE_AUTHOR("Anil S Keshavamurthy");
+MODULE_DESCRIPTION("ACPI container driver");
 MODULE_LICENSE("GPL");
 
 #define ACPI_STA_PRESENT		(0x00000001)
@@ -56,7 +55,7 @@
 static int acpi_container_remove(struct acpi_device *device, int type);
 
 static struct acpi_driver acpi_container_driver = {
-	.name = ACPI_CONTAINER_DRIVER_NAME,
+	.name = "container",
 	.class = ACPI_CONTAINER_CLASS,
 	.ids = "ACPI0004,PNP0A05,PNP0A06",
 	.ops = {
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index d48f65a..bf513e0 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -12,7 +12,7 @@
 #include <acpi/acglobal.h>
 
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME("debug")
+ACPI_MODULE_NAME("debug");
 
 #ifdef MODULE_PARAM_PREFIX
 #undef MODULE_PARAM_PREFIX
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 1cbe619..1683e5c 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -231,10 +231,8 @@
 		 * Obtain the method mutex if necessary. Do not acquire mutex for a
 		 * recursive call.
 		 */
-		if (!walk_state ||
-		    !obj_desc->method.mutex->mutex.owner_thread ||
-		    (walk_state->thread !=
-		     obj_desc->method.mutex->mutex.owner_thread)) {
+		if (acpi_os_get_thread_id() !=
+		    obj_desc->method.mutex->mutex.owner_thread_id) {
 			/*
 			 * Acquire the method mutex. This releases the interpreter if we
 			 * block (and reacquires it before it returns)
@@ -248,14 +246,14 @@
 			}
 
 			/* Update the mutex and walk info and save the original sync_level */
+			obj_desc->method.mutex->mutex.owner_thread_id =
+				acpi_os_get_thread_id();
 
 			if (walk_state) {
 				obj_desc->method.mutex->mutex.
 				    original_sync_level =
 				    walk_state->thread->current_sync_level;
 
-				obj_desc->method.mutex->mutex.owner_thread =
-				    walk_state->thread;
 				walk_state->thread->current_sync_level =
 				    obj_desc->method.sync_level;
 			} else {
@@ -569,7 +567,7 @@
 
 			acpi_os_release_mutex(method_desc->method.mutex->mutex.
 					      os_mutex);
-			method_desc->method.mutex->mutex.owner_thread = NULL;
+			method_desc->method.mutex->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
 		}
 	}
 
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 688e83a..54a697f 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -32,11 +32,11 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
-#define ACPI_DOCK_DRIVER_NAME "ACPI Dock Station Driver"
+#define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver"
 
-ACPI_MODULE_NAME("dock")
+ACPI_MODULE_NAME("dock");
 MODULE_AUTHOR("Kristen Carlson Accardi");
-MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME);
+MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
 MODULE_LICENSE("GPL");
 
 static struct atomic_notifier_head dock_notifier_list;
@@ -741,7 +741,7 @@
 		goto dock_add_err;
 	}
 
-	printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_NAME);
+	printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION);
 
 	return 0;
 
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 743ce27..ab68883 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -38,11 +38,10 @@
 #include <acpi/actypes.h>
 
 #define _COMPONENT		ACPI_EC_COMPONENT
-ACPI_MODULE_NAME("acpi_ec")
+ACPI_MODULE_NAME("ec");
 #define ACPI_EC_COMPONENT		0x00100000
 #define ACPI_EC_CLASS			"embedded_controller"
 #define ACPI_EC_HID			"PNP0C09"
-#define ACPI_EC_DRIVER_NAME		"ACPI Embedded Controller Driver"
 #define ACPI_EC_DEVICE_NAME		"Embedded Controller"
 #define ACPI_EC_FILE_INFO		"info"
 #undef PREFIX
@@ -80,7 +79,7 @@
 static int acpi_ec_add(struct acpi_device *device);
 
 static struct acpi_driver acpi_ec_driver = {
-	.name = ACPI_EC_DRIVER_NAME,
+	.name = "ec",
 	.class = ACPI_EC_CLASS,
 	.ids = ACPI_EC_HID,
 	.ops = {
@@ -280,8 +279,10 @@
 	mutex_lock(&ec->lock);
 	if (ec->global_lock) {
 		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
-		if (ACPI_FAILURE(status))
+		if (ACPI_FAILURE(status)) {
+			mutex_unlock(&ec->lock);
 			return -ENODEV;
+		}
 	}
 
 	/* Make sure GPE is enabled before doing transaction */
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index 959a893..3b23562 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -13,7 +13,7 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME("event")
+ACPI_MODULE_NAME("event");
 
 /* Global vars for handling event proc entry */
 static DEFINE_SPINLOCK(acpi_system_event_lock);
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index dfac3ec..635ba44 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -636,17 +636,6 @@
 		}
 	}
 
-	if (!acpi_gbl_system_awake_and_running) {
-		/*
-		 * We just woke up because of a wake GPE. Disable any further GPEs
-		 * until we are fully up and running (Only wake GPEs should be enabled
-		 * at this time, but we just brute-force disable them all.)
-		 * 1) We must disable this particular wake GPE so it won't fire again
-		 * 2) We want to disable all wake GPEs, since we are now awake
-		 */
-		(void)acpi_hw_disable_all_gpes();
-	}
-
 	/*
 	 * Dispatch the GPE to either an installed handler, or the control method
 	 * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 1b784ffe..d572700 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -196,12 +196,11 @@
 		notify_info->notify.value = (u16) notify_value;
 		notify_info->notify.handler_obj = handler_obj;
 
-		status =
-		    acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
-				    notify_info);
-		if (ACPI_FAILURE(status)) {
-			acpi_ut_delete_generic_state(notify_info);
-		}
+		acpi_ex_relinquish_interpreter();
+
+		acpi_ev_notify_dispatch(notify_info);
+
+		acpi_ex_reacquire_interpreter();
 	}
 
 	if (!handler_obj) {
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index 68d283f..1a73c14 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -134,7 +134,7 @@
 static struct acpi_exdump_info acpi_ex_dump_mutex[5] = {
 	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL},
 	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"},
-	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread_id), "Owner Thread"},
 	{ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth),
 	 "Acquire Depth"},
 	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"}
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index 5101bad..4eb883b 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -66,10 +66,9 @@
  *
  ******************************************************************************/
 
-void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc,
+			  struct acpi_thread_state *thread)
 {
-	struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
-
 	if (!thread) {
 		return;
 	}
@@ -174,16 +173,13 @@
 
 	/* Support for multiple acquires by the owning thread */
 
-	if (obj_desc->mutex.owner_thread) {
-		if (obj_desc->mutex.owner_thread->thread_id ==
-		    walk_state->thread->thread_id) {
-			/*
-			 * The mutex is already owned by this thread, just increment the
-			 * acquisition depth
-			 */
-			obj_desc->mutex.acquisition_depth++;
-			return_ACPI_STATUS(AE_OK);
-		}
+	if (obj_desc->mutex.owner_thread_id == acpi_os_get_thread_id()) {
+		/*
+		 * The mutex is already owned by this thread, just increment the
+		 * acquisition depth
+		 */
+		obj_desc->mutex.acquisition_depth++;
+		return_ACPI_STATUS(AE_OK);
 	}
 
 	/* Acquire the mutex, wait if necessary. Special case for Global Lock */
@@ -206,7 +202,7 @@
 
 	/* Have the mutex: update mutex and walk info and save the sync_level */
 
-	obj_desc->mutex.owner_thread = walk_state->thread;
+	obj_desc->mutex.owner_thread_id = acpi_os_get_thread_id();
 	obj_desc->mutex.acquisition_depth = 1;
 	obj_desc->mutex.original_sync_level =
 	    walk_state->thread->current_sync_level;
@@ -246,7 +242,7 @@
 
 	/* The mutex must have been previously acquired in order to release it */
 
-	if (!obj_desc->mutex.owner_thread) {
+	if (!obj_desc->mutex.owner_thread_id) {
 		ACPI_ERROR((AE_INFO,
 			    "Cannot release Mutex [%4.4s], not acquired",
 			    acpi_ut_get_node_name(obj_desc->mutex.node)));
@@ -266,14 +262,14 @@
 	 * The Mutex is owned, but this thread must be the owner.
 	 * Special case for Global Lock, any thread can release
 	 */
-	if ((obj_desc->mutex.owner_thread->thread_id !=
+	if ((obj_desc->mutex.owner_thread_id !=
 	     walk_state->thread->thread_id)
 	    && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) {
 		ACPI_ERROR((AE_INFO,
 			    "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
 			    (unsigned long)walk_state->thread->thread_id,
 			    acpi_ut_get_node_name(obj_desc->mutex.node),
-			    (unsigned long)obj_desc->mutex.owner_thread->thread_id));
+			    (unsigned long)obj_desc->mutex.owner_thread_id));
 		return_ACPI_STATUS(AE_AML_NOT_OWNER);
 	}
 
@@ -300,7 +296,7 @@
 
 	/* Unlink the mutex from the owner's list */
 
-	acpi_ex_unlink_mutex(obj_desc);
+	acpi_ex_unlink_mutex(obj_desc, walk_state->thread);
 
 	/* Release the mutex, special case for Global Lock */
 
@@ -312,7 +308,7 @@
 
 	/* Update the mutex and restore sync_level */
 
-	obj_desc->mutex.owner_thread = NULL;
+	obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
 	walk_state->thread->current_sync_level =
 	    obj_desc->mutex.original_sync_level;
 
@@ -367,7 +363,7 @@
 
 		/* Mark mutex unowned */
 
-		obj_desc->mutex.owner_thread = NULL;
+		obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
 
 		/* Update Thread sync_level (Last mutex is the important one) */
 
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index af22fdf..ec655c5 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -36,14 +36,13 @@
 
 #define ACPI_FAN_COMPONENT		0x00200000
 #define ACPI_FAN_CLASS			"fan"
-#define ACPI_FAN_DRIVER_NAME		"ACPI Fan Driver"
 #define ACPI_FAN_FILE_STATE		"state"
 
 #define _COMPONENT		ACPI_FAN_COMPONENT
-ACPI_MODULE_NAME("acpi_fan")
+ACPI_MODULE_NAME("fan");
 
-    MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Fan Driver");
 MODULE_LICENSE("GPL");
 
 static int acpi_fan_add(struct acpi_device *device);
@@ -52,7 +51,7 @@
 static int acpi_fan_resume(struct acpi_device *device);
 
 static struct acpi_driver acpi_fan_driver = {
-	.name = ACPI_FAN_DRIVER_NAME,
+	.name = "fan",
 	.class = ACPI_FAN_CLASS,
 	.ids = "PNP0C0B",
 	.ops = {
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 7b6c9ff..4334c20 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -241,3 +241,65 @@
 }
 
 arch_initcall(init_acpi_device_notify);
+
+
+#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
+
+/* Every ACPI platform has a mc146818 compatible "cmos rtc".  Here we find
+ * its device node and pass extra config data.  This helps its driver use
+ * capabilities that the now-obsolete mc146818 didn't have, and informs it
+ * that this board's RTC is wakeup-capable (per ACPI spec).
+ */
+#include <linux/mc146818rtc.h>
+
+static struct cmos_rtc_board_info rtc_info;
+
+
+/* PNP devices are registered in a subsys_initcall();
+ * ACPI specifies the PNP IDs to use.
+ */
+#include <linux/pnp.h>
+
+static int __init pnp_match(struct device *dev, void *data)
+{
+	static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", };
+	struct pnp_dev *pnp = to_pnp_dev(dev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ids); i++) {
+		if (compare_pnp_id(pnp->id, ids[i]) != 0)
+			return 1;
+	}
+	return 0;
+}
+
+static struct device *__init get_rtc_dev(void)
+{
+	return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match);
+}
+
+static int __init acpi_rtc_init(void)
+{
+	struct device *dev = get_rtc_dev();
+
+	if (dev) {
+		rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm;
+		rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm;
+		rtc_info.rtc_century = acpi_gbl_FADT.century;
+
+		/* NOTE:  acpi_gbl_FADT->rtcs4 is NOT currently useful */
+
+		dev->platform_data = &rtc_info;
+
+		/* RTC always wakes from S1/S2/S3, and often S4/STD */
+		device_init_wakeup(dev, 1);
+
+		put_device(dev);
+	} else
+		pr_debug("ACPI: RTC unavailable?\n");
+	return 0;
+}
+/* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */
+fs_initcall(acpi_rtc_init);
+
+#endif
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 57901ca..8fa9312 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -235,6 +235,14 @@
 				"While executing method _SST"));
 	}
 
+	/*
+	 * 1) Disable/Clear all GPEs
+	 */
+	status = acpi_hw_disable_all_gpes();
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
 	return_ACPI_STATUS(AE_OK);
 }
 
@@ -290,13 +298,8 @@
 	}
 
 	/*
-	 * 1) Disable/Clear all GPEs
 	 * 2) Enable all wakeup GPEs
 	 */
-	status = acpi_hw_disable_all_gpes();
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
 	acpi_gbl_system_awake_and_running = FALSE;
 
 	status = acpi_hw_enable_all_wakeup_gpes();
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
deleted file mode 100644
index 8edfb92..0000000
--- a/drivers/acpi/hotkey.c
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- *  hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $)
- *
- *  Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/sched.h>
-#include <linux/kmod.h>
-#include <linux/seq_file.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
-#include <asm/uaccess.h>
-
-#define HOTKEY_ACPI_VERSION "0.1"
-
-#define HOTKEY_PROC "hotkey"
-#define HOTKEY_EV_CONFIG    "event_config"
-#define HOTKEY_PL_CONFIG    "poll_config"
-#define HOTKEY_ACTION   "action"
-#define HOTKEY_INFO "info"
-
-#define ACPI_HOTK_NAME          "Generic Hotkey Driver"
-#define ACPI_HOTK_CLASS         "Hotkey"
-#define ACPI_HOTK_DEVICE_NAME   "Hotkey"
-#define ACPI_HOTK_HID           "Unknown?"
-#define ACPI_HOTKEY_COMPONENT   0x20000000
-
-#define ACPI_HOTKEY_EVENT   0x1
-#define ACPI_HOTKEY_POLLING 0x2
-#define ACPI_UNDEFINED_EVENT    0xf
-
-#define RESULT_STR_LEN	    80
-
-#define ACTION_METHOD	0
-#define POLL_METHOD	1
-
-#define IS_EVENT(e)       	((e) <= 10000 && (e) >0)
-#define IS_POLL(e)      	((e) > 10000)
-#define IS_OTHERS(e)		((e)<=0 || (e)>=20000)
-#define _COMPONENT              ACPI_HOTKEY_COMPONENT
-ACPI_MODULE_NAME("acpi_hotkey")
-
-    MODULE_AUTHOR("luming.yu@intel.com");
-MODULE_DESCRIPTION(ACPI_HOTK_NAME);
-MODULE_LICENSE("GPL");
-
-/*  standardized internal hotkey number/event  */
-enum {
-	/* Video Extension event */
-	HK_EVENT_CYCLE_OUTPUT_DEVICE = 0x80,
-	HK_EVENT_OUTPUT_DEVICE_STATUS_CHANGE,
-	HK_EVENT_CYCLE_DISPLAY_OUTPUT,
-	HK_EVENT_NEXT_DISPLAY_OUTPUT,
-	HK_EVENT_PREVIOUS_DISPLAY_OUTPUT,
-	HK_EVENT_CYCLE_BRIGHTNESS,
-	HK_EVENT_INCREASE_BRIGHTNESS,
-	HK_EVENT_DECREASE_BRIGHTNESS,
-	HK_EVENT_ZERO_BRIGHTNESS,
-	HK_EVENT_DISPLAY_DEVICE_OFF,
-
-	/* Snd Card event */
-	HK_EVENT_VOLUME_MUTE,
-	HK_EVENT_VOLUME_INCLREASE,
-	HK_EVENT_VOLUME_DECREASE,
-
-	/* running state control */
-	HK_EVENT_ENTERRING_S3,
-	HK_EVENT_ENTERRING_S4,
-	HK_EVENT_ENTERRING_S5,
-};
-
-enum conf_entry_enum {
-	bus_handle = 0,
-	bus_method = 1,
-	action_handle = 2,
-	method = 3,
-	LAST_CONF_ENTRY
-};
-
-/*  procdir we use */
-static struct proc_dir_entry *hotkey_proc_dir;
-static struct proc_dir_entry *hotkey_config;
-static struct proc_dir_entry *hotkey_poll_config;
-static struct proc_dir_entry *hotkey_action;
-static struct proc_dir_entry *hotkey_info;
-
-/* linkage for all type of hotkey */
-struct acpi_hotkey_link {
-	struct list_head entries;
-	int hotkey_type;	/* event or polling based hotkey  */
-	int hotkey_standard_num;	/* standardized hotkey(event) number */
-};
-
-/* event based hotkey */
-struct acpi_event_hotkey {
-	struct acpi_hotkey_link hotkey_link;
-	int flag;
-	acpi_handle bus_handle;	/* bus to install notify handler */
-	int external_hotkey_num;	/* external hotkey/event number */
-	acpi_handle action_handle;	/* acpi handle attached aml action method */
-	char *action_method;	/* action method */
-};
-
-/*
- * There are two ways to poll status
- * 1. directy call read_xxx method, without any arguments passed in
- * 2. call write_xxx method, with arguments passed in, you need
- * the result is saved in acpi_polling_hotkey.poll_result.
- * anthoer read command through polling interface.
- *
- */
-
-/* polling based hotkey */
-struct acpi_polling_hotkey {
-	struct acpi_hotkey_link hotkey_link;
-	int flag;
-	acpi_handle poll_handle;	/* acpi handle attached polling method */
-	char *poll_method;	/* poll method */
-	acpi_handle action_handle;	/* acpi handle attached action method */
-	char *action_method;	/* action method */
-	union acpi_object *poll_result;	/* polling_result */
-	struct proc_dir_entry *proc;
-};
-
-/* hotkey object union */
-union acpi_hotkey {
-	struct list_head entries;
-	struct acpi_hotkey_link link;
-	struct acpi_event_hotkey event_hotkey;
-	struct acpi_polling_hotkey poll_hotkey;
-};
-
-/* hotkey object list */
-struct acpi_hotkey_list {
-	struct list_head *entries;
-	int count;
-};
-
-static int auto_hotkey_add(struct acpi_device *device);
-static int auto_hotkey_remove(struct acpi_device *device, int type);
-
-static struct acpi_driver hotkey_driver = {
-	.name = ACPI_HOTK_NAME,
-	.class = ACPI_HOTK_CLASS,
-	.ids = ACPI_HOTK_HID,
-	.ops = {
-		.add = auto_hotkey_add,
-		.remove = auto_hotkey_remove,
-		},
-};
-
-static void free_hotkey_device(union acpi_hotkey *key);
-static void free_hotkey_buffer(union acpi_hotkey *key);
-static void free_poll_hotkey_buffer(union acpi_hotkey *key);
-static int hotkey_open_config(struct inode *inode, struct file *file);
-static int hotkey_poll_open_config(struct inode *inode, struct file *file);
-static ssize_t hotkey_write_config(struct file *file,
-				   const char __user * buffer,
-				   size_t count, loff_t * data);
-static int hotkey_info_open_fs(struct inode *inode, struct file *file);
-static int hotkey_action_open_fs(struct inode *inode, struct file *file);
-static ssize_t hotkey_execute_aml_method(struct file *file,
-					 const char __user * buffer,
-					 size_t count, loff_t * data);
-static int hotkey_config_seq_show(struct seq_file *seq, void *offset);
-static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset);
-static int hotkey_polling_open_fs(struct inode *inode, struct file *file);
-static union acpi_hotkey *get_hotkey_by_event(struct
-					      acpi_hotkey_list
-					      *hotkey_list, int event);
-
-/* event based config */
-static const struct file_operations hotkey_config_fops = {
-	.open = hotkey_open_config,
-	.read = seq_read,
-	.write = hotkey_write_config,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-/* polling based config */
-static const struct file_operations hotkey_poll_config_fops = {
-	.open = hotkey_poll_open_config,
-	.read = seq_read,
-	.write = hotkey_write_config,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-/* hotkey driver info */
-static const struct file_operations hotkey_info_fops = {
-	.open = hotkey_info_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-/* action */
-static const struct file_operations hotkey_action_fops = {
-	.open = hotkey_action_open_fs,
-	.read = seq_read,
-	.write = hotkey_execute_aml_method,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-/* polling results */
-static const struct file_operations hotkey_polling_fops = {
-	.open = hotkey_polling_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-struct acpi_hotkey_list global_hotkey_list;	/* link all ev or pl hotkey  */
-struct list_head hotkey_entries;	/* head of the list of hotkey_list */
-
-static int hotkey_info_seq_show(struct seq_file *seq, void *offset)
-{
-
-	seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION);
-
-	return 0;
-}
-
-static int hotkey_info_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, hotkey_info_seq_show, PDE(inode)->data);
-}
-
-static char *format_result(union acpi_object *object)
-{
-	char *buf;
-
-	buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL);
-	if (!buf)
-		return NULL;
-	/* Now, just support integer type */
-	if (object->type == ACPI_TYPE_INTEGER)
-		sprintf(buf, "%d\n", (u32) object->integer.value);
-	return buf;
-}
-
-static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_polling_hotkey *poll_hotkey = seq->private;
-	char *buf;
-
-
-	if (poll_hotkey->poll_result) {
-		buf = format_result(poll_hotkey->poll_result);
-		if (buf)
-			seq_printf(seq, "%s", buf);
-		kfree(buf);
-	}
-	return 0;
-}
-
-static int hotkey_polling_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, hotkey_polling_seq_show, PDE(inode)->data);
-}
-
-static int hotkey_action_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, hotkey_info_seq_show, PDE(inode)->data);
-}
-
-/* Mapping external hotkey number to standardized hotkey event num */
-static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list)
-{
-	struct list_head *entries;
-	int val = -1;
-
-
-	list_for_each(entries, list->entries) {
-		union acpi_hotkey *key =
-		    container_of(entries, union acpi_hotkey, entries);
-		if (key->link.hotkey_type == ACPI_HOTKEY_EVENT
-		    && key->event_hotkey.external_hotkey_num == event) {
-			val = key->link.hotkey_standard_num;
-			break;
-		}
-	}
-
-	return val;
-}
-
-static void
-acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data)
-{
-	struct acpi_device *device = NULL;
-	u32 internal_event;
-
-
-	if (acpi_bus_get_device(handle, &device))
-		return;
-
-	internal_event = hotkey_get_internal_event(event, &global_hotkey_list);
-	acpi_bus_generate_event(device, internal_event, 0);
-
-	return;
-}
-
-/* Need to invent automatically hotkey add method */
-static int auto_hotkey_add(struct acpi_device *device)
-{
-	/* Implement me */
-	return 0;
-}
-
-/* Need to invent automatically hotkey remove method */
-static int auto_hotkey_remove(struct acpi_device *device, int type)
-{
-	/* Implement me */
-	return 0;
-}
-
-/* Create a proc file for each polling method */
-static int create_polling_proc(union acpi_hotkey *device)
-{
-	struct proc_dir_entry *proc;
-	char proc_name[80];
-	mode_t mode;
-
-	mode = S_IFREG | S_IRUGO | S_IWUGO;
-
-	sprintf(proc_name, "%d", device->link.hotkey_standard_num);
-	/*
-	   strcat(proc_name, device->poll_hotkey.poll_method);
-	 */
-	proc = create_proc_entry(proc_name, mode, hotkey_proc_dir);
-
-	if (!proc) {
-		return -ENODEV;
-	} else {
-		proc->proc_fops = &hotkey_polling_fops;
-		proc->owner = THIS_MODULE;
-		proc->data = device;
-		proc->uid = 0;
-		proc->gid = 0;
-		device->poll_hotkey.proc = proc;
-	}
-	return 0;
-}
-
-static int hotkey_add(union acpi_hotkey *device)
-{
-	int status = 0;
-	struct acpi_device *dev = NULL;
-
-
-	if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) {
-		acpi_bus_get_device(device->event_hotkey.bus_handle, &dev);
-		status = acpi_install_notify_handler(dev->handle,
-						     ACPI_DEVICE_NOTIFY,
-						     acpi_hotkey_notify_handler,
-						     dev);
-	} else			/* Add polling hotkey */
-		create_polling_proc(device);
-
-	global_hotkey_list.count++;
-
-	list_add_tail(&device->link.entries, global_hotkey_list.entries);
-
-	return status;
-}
-
-static int hotkey_remove(union acpi_hotkey *device)
-{
-	struct list_head *entries, *next;
-
-
-	list_for_each_safe(entries, next, global_hotkey_list.entries) {
-		union acpi_hotkey *key =
-		    container_of(entries, union acpi_hotkey, entries);
-		if (key->link.hotkey_standard_num ==
-		    device->link.hotkey_standard_num) {
-			list_del(&key->link.entries);
-			free_hotkey_device(key);
-			global_hotkey_list.count--;
-			break;
-		}
-	}
-	kfree(device);
-	return 0;
-}
-
-static int hotkey_update(union acpi_hotkey *key)
-{
-	struct list_head *entries;
-
-
-	list_for_each(entries, global_hotkey_list.entries) {
-		union acpi_hotkey *tmp =
-		    container_of(entries, union acpi_hotkey, entries);
-		if (tmp->link.hotkey_standard_num ==
-		    key->link.hotkey_standard_num) {
-			if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
-				free_hotkey_buffer(tmp);
-				tmp->event_hotkey.bus_handle =
-				    key->event_hotkey.bus_handle;
-				tmp->event_hotkey.external_hotkey_num =
-				    key->event_hotkey.external_hotkey_num;
-				tmp->event_hotkey.action_handle =
-				    key->event_hotkey.action_handle;
-				tmp->event_hotkey.action_method =
-				    key->event_hotkey.action_method;
-				kfree(key);
-			} else {
-				/*
-				   char  proc_name[80];
-
-				   sprintf(proc_name, "%d", tmp->link.hotkey_standard_num);
-				   strcat(proc_name, tmp->poll_hotkey.poll_method);
-				   remove_proc_entry(proc_name,hotkey_proc_dir);
-				 */
-				free_poll_hotkey_buffer(tmp);
-				tmp->poll_hotkey.poll_handle =
-				    key->poll_hotkey.poll_handle;
-				tmp->poll_hotkey.poll_method =
-				    key->poll_hotkey.poll_method;
-				tmp->poll_hotkey.action_handle =
-				    key->poll_hotkey.action_handle;
-				tmp->poll_hotkey.action_method =
-				    key->poll_hotkey.action_method;
-				tmp->poll_hotkey.poll_result =
-				    key->poll_hotkey.poll_result;
-				/*
-				   create_polling_proc(tmp);
-				 */
-				kfree(key);
-			}
-			return 0;
-			break;
-		}
-	}
-
-	return -ENODEV;
-}
-
-static void free_hotkey_device(union acpi_hotkey *key)
-{
-	struct acpi_device *dev;
-
-
-	if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
-		acpi_bus_get_device(key->event_hotkey.bus_handle, &dev);
-		if (dev->handle)
-			acpi_remove_notify_handler(dev->handle,
-						   ACPI_DEVICE_NOTIFY,
-						   acpi_hotkey_notify_handler);
-		free_hotkey_buffer(key);
-	} else {
-		char proc_name[80];
-
-		sprintf(proc_name, "%d", key->link.hotkey_standard_num);
-		/*
-		   strcat(proc_name, key->poll_hotkey.poll_method);
-		 */
-		remove_proc_entry(proc_name, hotkey_proc_dir);
-		free_poll_hotkey_buffer(key);
-	}
-	kfree(key);
-	return;
-}
-
-static void free_hotkey_buffer(union acpi_hotkey *key)
-{
-	/* key would never be null, action method could be */
-	kfree(key->event_hotkey.action_method);
-}
-
-static void free_poll_hotkey_buffer(union acpi_hotkey *key)
-{
-	/* key would never be null, others could be*/
-	kfree(key->poll_hotkey.action_method);
-	kfree(key->poll_hotkey.poll_method);
-	kfree(key->poll_hotkey.poll_result);
-}
-static int
-init_hotkey_device(union acpi_hotkey *key, char **config_entry,
-		   int std_num, int external_num)
-{
-	acpi_handle tmp_handle;
-	acpi_status status = AE_OK;
-
-	if (std_num < 0 || IS_POLL(std_num) || !key)
-		goto do_fail;
-
-	if (!config_entry[bus_handle] || !config_entry[action_handle]
-			|| !config_entry[method])
-		goto do_fail;
-
-	key->link.hotkey_type = ACPI_HOTKEY_EVENT;
-	key->link.hotkey_standard_num = std_num;
-	key->event_hotkey.flag = 0;
-	key->event_hotkey.action_method = config_entry[method];
-
-	status = acpi_get_handle(NULL, config_entry[bus_handle],
-			   &(key->event_hotkey.bus_handle));
-	if (ACPI_FAILURE(status))
-		goto do_fail_zero;
-	key->event_hotkey.external_hotkey_num = external_num;
-	status = acpi_get_handle(NULL, config_entry[action_handle],
-			    &(key->event_hotkey.action_handle));
-	if (ACPI_FAILURE(status))
-		goto do_fail_zero;
-	status = acpi_get_handle(key->event_hotkey.action_handle,
-				 config_entry[method], &tmp_handle);
-	if (ACPI_FAILURE(status))
-		goto do_fail_zero;
-	return AE_OK;
-do_fail_zero:
-	key->event_hotkey.action_method = NULL;
-do_fail:
-	return -ENODEV;
-}
-
-static int
-init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry,
-			int std_num)
-{
-	acpi_status status = AE_OK;
-	acpi_handle tmp_handle;
-
-	if (std_num < 0 || IS_EVENT(std_num) || !key)
-		goto do_fail;
-	if (!config_entry[bus_handle] ||!config_entry[bus_method] ||
-		!config_entry[action_handle] || !config_entry[method])
-		goto do_fail;
-
-	key->link.hotkey_type = ACPI_HOTKEY_POLLING;
-	key->link.hotkey_standard_num = std_num;
-	key->poll_hotkey.flag = 0;
-	key->poll_hotkey.poll_method = config_entry[bus_method];
-	key->poll_hotkey.action_method = config_entry[method];
-
-	status = acpi_get_handle(NULL, config_entry[bus_handle],
-		      &(key->poll_hotkey.poll_handle));
-	if (ACPI_FAILURE(status))
-		goto do_fail_zero;
-	status = acpi_get_handle(key->poll_hotkey.poll_handle,
-				 config_entry[bus_method], &tmp_handle);
-	if (ACPI_FAILURE(status))
-		goto do_fail_zero;
-	status =
-	    acpi_get_handle(NULL, config_entry[action_handle],
-			    &(key->poll_hotkey.action_handle));
-	if (ACPI_FAILURE(status))
-		goto do_fail_zero;
-	status = acpi_get_handle(key->poll_hotkey.action_handle,
-				 config_entry[method], &tmp_handle);
-	if (ACPI_FAILURE(status))
-		goto do_fail_zero;
-	key->poll_hotkey.poll_result =
-	    kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-	if (!key->poll_hotkey.poll_result)
-		goto do_fail_zero;
-	return AE_OK;
-
-do_fail_zero:
-	key->poll_hotkey.poll_method = NULL;
-	key->poll_hotkey.action_method = NULL;
-do_fail:
-	return -ENODEV;
-}
-
-static int hotkey_open_config(struct inode *inode, struct file *file)
-{
-	return (single_open
-		     (file, hotkey_config_seq_show, PDE(inode)->data));
-}
-
-static int hotkey_poll_open_config(struct inode *inode, struct file *file)
-{
-	return (single_open
-		     (file, hotkey_poll_config_seq_show, PDE(inode)->data));
-}
-
-static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
-	struct list_head *entries;
-	char bus_name[ACPI_PATHNAME_MAX] = { 0 };
-	char action_name[ACPI_PATHNAME_MAX] = { 0 };
-	struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name };
-	struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name };
-
-
-	list_for_each(entries, hotkey_list->entries) {
-		union acpi_hotkey *key =
-		    container_of(entries, union acpi_hotkey, entries);
-		if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
-			acpi_get_name(key->event_hotkey.bus_handle,
-				      ACPI_NAME_TYPE_MAX, &bus);
-			acpi_get_name(key->event_hotkey.action_handle,
-				      ACPI_NAME_TYPE_MAX, &act);
-			seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name,
-				   action_name,
-				   key->event_hotkey.action_method,
-				   key->link.hotkey_standard_num,
-				   key->event_hotkey.external_hotkey_num);
-		}
-	}
-	seq_puts(seq, "\n");
-	return 0;
-}
-
-static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
-	struct list_head *entries;
-	char bus_name[ACPI_PATHNAME_MAX] = { 0 };
-	char action_name[ACPI_PATHNAME_MAX] = { 0 };
-	struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name };
-	struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name };
-
-
-	list_for_each(entries, hotkey_list->entries) {
-		union acpi_hotkey *key =
-		    container_of(entries, union acpi_hotkey, entries);
-		if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) {
-			acpi_get_name(key->poll_hotkey.poll_handle,
-				      ACPI_NAME_TYPE_MAX, &bus);
-			acpi_get_name(key->poll_hotkey.action_handle,
-				      ACPI_NAME_TYPE_MAX, &act);
-			seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name,
-				   key->poll_hotkey.poll_method,
-				   action_name,
-				   key->poll_hotkey.action_method,
-				   key->link.hotkey_standard_num);
-		}
-	}
-	seq_puts(seq, "\n");
-	return 0;
-}
-
-static int
-get_parms(char *config_record, int *cmd, char **config_entry,
-	       int *internal_event_num, int *external_event_num)
-{
-/* the format of *config_record =
- * "1:\d+:*" : "cmd:internal_event_num"
- * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" :
- * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num"
- */
-	char *tmp, *tmp1, count;
-	int i;
-
-	sscanf(config_record, "%d", cmd);
-	if (*cmd == 1) {
-		if (sscanf(config_record, "%d:%d", cmd, internal_event_num) !=
-		    2)
-			goto do_fail;
-		else
-			return (6);
-	}
-	tmp = strchr(config_record, ':');
-	if (!tmp)
-		goto do_fail;
-	tmp++;
-	for (i = 0; i < LAST_CONF_ENTRY; i++) {
-		tmp1 = strchr(tmp, ':');
-		if (!tmp1) {
-			goto do_fail;
-		}
-		count = tmp1 - tmp;
-		config_entry[i] = kzalloc(count + 1, GFP_KERNEL);
-		if (!config_entry[i])
-			goto handle_failure;
-		strncpy(config_entry[i], tmp, count);
-		tmp = tmp1 + 1;
-	}
-	if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0)
-		goto handle_failure;
-	if (!IS_OTHERS(*internal_event_num)) {
-		return 6;
-	}
-handle_failure:
-	while (i-- > 0)
-		kfree(config_entry[i]);
-do_fail:
-	return -1;
-}
-
-/*  count is length for one input record */
-static ssize_t hotkey_write_config(struct file *file,
-				   const char __user * buffer,
-				   size_t count, loff_t * data)
-{
-	char *config_record = NULL;
-	char *config_entry[LAST_CONF_ENTRY];
-	int cmd, internal_event_num, external_event_num;
-	int ret = 0;
-	union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
-
-	if (!key)
-		return -ENOMEM;
-
-	config_record = kzalloc(count + 1, GFP_KERNEL);
-	if (!config_record) {
-		kfree(key);
-		return -ENOMEM;
-	}
-
-	if (copy_from_user(config_record, buffer, count)) {
-		kfree(config_record);
-		kfree(key);
-		printk(KERN_ERR PREFIX "Invalid data\n");
-		return -EINVAL;
-	}
-	ret = get_parms(config_record, &cmd, config_entry,
-		       &internal_event_num, &external_event_num);
-	kfree(config_record);
-	if (ret != 6) {
-		printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret);
-		return -EINVAL;
-	}
-
-	if (cmd == 1) {
-		union acpi_hotkey *tmp = NULL;
-		tmp = get_hotkey_by_event(&global_hotkey_list,
-					  internal_event_num);
-		if (!tmp)
-			printk(KERN_ERR PREFIX "Invalid key\n");
-		else
-			memcpy(key, tmp, sizeof(union acpi_hotkey));
-		goto cont_cmd;
-	}
-	if (IS_EVENT(internal_event_num)) {
-		if (init_hotkey_device(key, config_entry,
-			internal_event_num, external_event_num))
-			goto init_hotkey_fail;
-	} else {
-		if (init_poll_hotkey_device(key, config_entry,
-			       internal_event_num))
-			goto init_poll_hotkey_fail;
-	}
-cont_cmd:
-	switch (cmd) {
-	case 0:
-		if (get_hotkey_by_event(&global_hotkey_list,
-				key->link.hotkey_standard_num))
-			goto fail_out;
-		else
-			hotkey_add(key);
-		break;
-	case 1:
-		hotkey_remove(key);
-		break;
-	case 2:
-		/* key is kfree()ed if matched*/
-		if (hotkey_update(key))
-			goto fail_out;
-		break;
-	default:
-		goto fail_out;
-		break;
-	}
-	return count;
-
-init_poll_hotkey_fail:		/* failed init_poll_hotkey_device */
-	kfree(config_entry[bus_method]);
-	config_entry[bus_method] = NULL;
-init_hotkey_fail:		/* failed init_hotkey_device */
-	kfree(config_entry[method]);
-fail_out:
-	kfree(config_entry[bus_handle]);
-	kfree(config_entry[action_handle]);
-	/* No double free since elements =NULL for error cases */
-	if (IS_EVENT(internal_event_num)) {
-		if (config_entry[bus_method])
-			kfree(config_entry[bus_method]);
-		free_hotkey_buffer(key);	/* frees [method] */
-	} else
-		free_poll_hotkey_buffer(key);  /* frees [bus_method]+[method] */
-	kfree(key);
-	printk(KERN_ERR PREFIX "invalid key\n");
-	return -EINVAL;
-}
-
-/*
- * This function evaluates an ACPI method, given an int as parameter, the
- * method is searched within the scope of the handle, can be NULL. The output
- * of the method is written is output, which can also be NULL
- *
- * returns 1 if write is successful, 0 else.
- */
-static int write_acpi_int(acpi_handle handle, const char *method, int val,
-			  struct acpi_buffer *output)
-{
-	struct acpi_object_list params;	/* list of input parameters (an int here) */
-	union acpi_object in_obj;	/* the only param we use */
-	acpi_status status;
-
-	params.count = 1;
-	params.pointer = &in_obj;
-	in_obj.type = ACPI_TYPE_INTEGER;
-	in_obj.integer.value = val;
-
-	status = acpi_evaluate_object(handle, (char *)method, &params, output);
-
-	return (status == AE_OK);
-}
-
-static int read_acpi_int(acpi_handle handle, const char *method,
-			 union acpi_object *val)
-{
-	struct acpi_buffer output;
-	union acpi_object out_obj;
-	acpi_status status;
-
-	output.length = sizeof(out_obj);
-	output.pointer = &out_obj;
-
-	status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
-	if (val) {
-		val->integer.value = out_obj.integer.value;
-		val->type = out_obj.type;
-	} else
-		printk(KERN_ERR PREFIX "null val pointer\n");
-	return ((status == AE_OK)
-		     && (out_obj.type == ACPI_TYPE_INTEGER));
-}
-
-static union acpi_hotkey *get_hotkey_by_event(struct
-					      acpi_hotkey_list
-					      *hotkey_list, int event)
-{
-	struct list_head *entries;
-
-	list_for_each(entries, hotkey_list->entries) {
-		union acpi_hotkey *key =
-		    container_of(entries, union acpi_hotkey, entries);
-		if (key->link.hotkey_standard_num == event) {
-			return (key);
-		}
-	}
-	return (NULL);
-}
-
-/*
- * user call AML method interface:
- * Call convention:
- * echo "event_num: arg type : value"
- * example: echo "1:1:30" > /proc/acpi/action
- * Just support 1 integer arg passing to AML method
- */
-
-static ssize_t hotkey_execute_aml_method(struct file *file,
-					 const char __user * buffer,
-					 size_t count, loff_t * data)
-{
-	struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
-	char *arg;
-	int event, method_type, type, value;
-	union acpi_hotkey *key;
-
-
-	arg = kzalloc(count + 1, GFP_KERNEL);
-	if (!arg)
-		return -ENOMEM;
-
-	if (copy_from_user(arg, buffer, count)) {
-		kfree(arg);
-		printk(KERN_ERR PREFIX "Invalid argument 2\n");
-		return -EINVAL;
-	}
-
-	if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) !=
-	    4) {
-		kfree(arg);
-		printk(KERN_ERR PREFIX "Invalid argument 3\n");
-		return -EINVAL;
-	}
-	kfree(arg);
-	if (type == ACPI_TYPE_INTEGER) {
-		key = get_hotkey_by_event(hotkey_list, event);
-		if (!key)
-			goto do_fail;
-		if (IS_EVENT(event))
-			write_acpi_int(key->event_hotkey.action_handle,
-				       key->event_hotkey.action_method, value,
-				       NULL);
-		else if (IS_POLL(event)) {
-			if (method_type == POLL_METHOD)
-				read_acpi_int(key->poll_hotkey.poll_handle,
-					      key->poll_hotkey.poll_method,
-					      key->poll_hotkey.poll_result);
-			else if (method_type == ACTION_METHOD)
-				write_acpi_int(key->poll_hotkey.action_handle,
-					       key->poll_hotkey.action_method,
-					       value, NULL);
-			else
-				goto do_fail;
-
-		}
-	} else {
-		printk(KERN_WARNING "Not supported\n");
-		return -EINVAL;
-	}
-	return count;
-      do_fail:
-	return -EINVAL;
-
-}
-
-static int __init hotkey_init(void)
-{
-	int result;
-	mode_t mode = S_IFREG | S_IRUGO | S_IWUGO;
-
-
-	if (acpi_disabled)
-		return -ENODEV;
-
-	if (acpi_specific_hotkey_enabled) {
-		printk("Using specific hotkey driver\n");
-		return -ENODEV;
-	}
-
-	hotkey_proc_dir = proc_mkdir(HOTKEY_PROC, acpi_root_dir);
-	if (!hotkey_proc_dir) {
-		return (-ENODEV);
-	}
-	hotkey_proc_dir->owner = THIS_MODULE;
-
-	hotkey_config =
-	    create_proc_entry(HOTKEY_EV_CONFIG, mode, hotkey_proc_dir);
-	if (!hotkey_config) {
-		goto do_fail1;
-	} else {
-		hotkey_config->proc_fops = &hotkey_config_fops;
-		hotkey_config->data = &global_hotkey_list;
-		hotkey_config->owner = THIS_MODULE;
-		hotkey_config->uid = 0;
-		hotkey_config->gid = 0;
-	}
-
-	hotkey_poll_config =
-	    create_proc_entry(HOTKEY_PL_CONFIG, mode, hotkey_proc_dir);
-	if (!hotkey_poll_config) {
-		goto do_fail2;
-	} else {
-		hotkey_poll_config->proc_fops = &hotkey_poll_config_fops;
-		hotkey_poll_config->data = &global_hotkey_list;
-		hotkey_poll_config->owner = THIS_MODULE;
-		hotkey_poll_config->uid = 0;
-		hotkey_poll_config->gid = 0;
-	}
-
-	hotkey_action = create_proc_entry(HOTKEY_ACTION, mode, hotkey_proc_dir);
-	if (!hotkey_action) {
-		goto do_fail3;
-	} else {
-		hotkey_action->proc_fops = &hotkey_action_fops;
-		hotkey_action->owner = THIS_MODULE;
-		hotkey_action->uid = 0;
-		hotkey_action->gid = 0;
-	}
-
-	hotkey_info = create_proc_entry(HOTKEY_INFO, mode, hotkey_proc_dir);
-	if (!hotkey_info) {
-		goto do_fail4;
-	} else {
-		hotkey_info->proc_fops = &hotkey_info_fops;
-		hotkey_info->owner = THIS_MODULE;
-		hotkey_info->uid = 0;
-		hotkey_info->gid = 0;
-	}
-
-	result = acpi_bus_register_driver(&hotkey_driver);
-	if (result < 0)
-		goto do_fail5;
-	global_hotkey_list.count = 0;
-	global_hotkey_list.entries = &hotkey_entries;
-
-	INIT_LIST_HEAD(&hotkey_entries);
-
-	return (0);
-
-      do_fail5:
-	remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir);
-      do_fail4:
-	remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir);
-      do_fail3:
-	remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir);
-      do_fail2:
-	remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir);
-      do_fail1:
-	remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
-	return (-ENODEV);
-}
-
-static void __exit hotkey_exit(void)
-{
-	struct list_head *entries, *next;
-
-
-	list_for_each_safe(entries, next, global_hotkey_list.entries) {
-		union acpi_hotkey *key =
-		    container_of(entries, union acpi_hotkey, entries);
-
-		acpi_os_wait_events_complete(NULL);
-		list_del(&key->link.entries);
-		global_hotkey_list.count--;
-		free_hotkey_device(key);
-	}
-	acpi_bus_unregister_driver(&hotkey_driver);
-	remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir);
-	remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir);
-	remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir);
-	remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir);
-	remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
-	return;
-}
-
-module_init(hotkey_init);
-module_exit(hotkey_exit);
diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c
index 8338be0..acab4a4 100644
--- a/drivers/acpi/i2c_ec.c
+++ b/drivers/acpi/i2c_ec.c
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/acpi.h>
@@ -28,18 +27,17 @@
 #define ACPI_EC_HC_COMPONENT	0x00080000
 #define ACPI_EC_HC_CLASS	"ec_hc_smbus"
 #define ACPI_EC_HC_HID		"ACPI0001"
-#define ACPI_EC_HC_DRIVER_NAME	"ACPI EC HC smbus driver"
 #define ACPI_EC_HC_DEVICE_NAME	"EC HC smbus"
 
 #define _COMPONENT		ACPI_EC_HC_COMPONENT
 
-ACPI_MODULE_NAME("acpi_smbus")
+ACPI_MODULE_NAME("i2c_ec");
 
 static int acpi_ec_hc_add(struct acpi_device *device);
 static int acpi_ec_hc_remove(struct acpi_device *device, int type);
 
 static struct acpi_driver acpi_ec_hc_driver = {
-	.name = ACPI_EC_HC_DRIVER_NAME,
+	.name = "i2c_ec",
 	.class = ACPI_EC_HC_CLASS,
 	.ids = ACPI_EC_HC_HID,
 	.ops = {
@@ -340,6 +338,7 @@
 	smbus->adapter.owner = THIS_MODULE;
 	smbus->adapter.algo = &acpi_ec_smbus_algorithm;
 	smbus->adapter.algo_data = smbus;
+	smbus->adapter.dev.parent = &device->dev;
 
 	if (i2c_add_adapter(&smbus->adapter)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index c6144ca..4cc534e 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -496,6 +496,10 @@
 	printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
 	printk(IBM_INFO "%s\n", IBM_URL);
 
+	if (ibm_thinkpad_ec_found)
+		printk(IBM_INFO "ThinkPad EC firmware %s\n",
+		       ibm_thinkpad_ec_found);
+
 	return 0;
 }
 
@@ -1697,14 +1701,12 @@
 
 static int brightness_update_status(struct backlight_device *bd)
 {
-	return brightness_set(bd->props->brightness);
+	return brightness_set(bd->props.brightness);
 }
 
-static struct backlight_properties ibm_backlight_data = {
-        .owner          = THIS_MODULE,
+static struct backlight_ops ibm_backlight_data = {
         .get_brightness = brightness_get,
         .update_status  = brightness_update_status,
-        .max_brightness = 7,
 };
 
 static int brightness_init(void)
@@ -1716,6 +1718,8 @@
 		return PTR_ERR(ibm_backlight_device);
 	}
 
+        ibm_backlight_device->props.max_brightness = 7;
+
 	return 0;
 }
 
@@ -2617,7 +2621,7 @@
 	ibm_handle_init(#object, &object##_handle, *object##_parent,	\
 		object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
 
-static int set_ibm_param(const char *val, struct kernel_param *kp)
+static int __init set_ibm_param(const char *val, struct kernel_param *kp)
 {
 	unsigned int i;
 
@@ -2659,7 +2663,8 @@
 	for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--)
 		ibm_exit(&ibms[i]);
 
-	remove_proc_entry(IBM_DIR, acpi_root_dir);
+	if (proc_dir)
+		remove_proc_entry(IBM_DIR, acpi_root_dir);
 
 	if (ibm_thinkpad_ec_found)
 		kfree(ibm_thinkpad_ec_found);
@@ -2696,11 +2701,6 @@
 	if (acpi_disabled)
 		return -ENODEV;
 
-	if (!acpi_specific_hotkey_enabled) {
-		printk(IBM_ERR "using generic hotkey driver\n");
-		return -ENODEV;
-	}
-
 	/* ec is required because many other handles are relative to it */
 	IBM_HANDLE_INIT(ec);
 	if (!ec_handle) {
@@ -2710,9 +2710,6 @@
 
 	/* Models with newer firmware report the EC in DMI */
 	ibm_thinkpad_ec_found = check_dmi_for_ec();
-	if (ibm_thinkpad_ec_found)
-		printk(IBM_INFO "ThinkPad EC firmware %s\n",
-		       ibm_thinkpad_ec_found);
 
 	/* these handles are not required */
 	IBM_HANDLE_INIT(vid);
@@ -2742,6 +2739,7 @@
 	proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir);
 	if (!proc_dir) {
 		printk(IBM_ERR "unable to create proc dir %s", IBM_DIR);
+		acpi_ibm_exit();
 		return -ENODEV;
 	}
 	proc_dir->owner = THIS_MODULE;
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 326af8f..33db224 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -45,6 +45,7 @@
 #include <acpi/acnamesp.h>
 #include <acpi/acdispat.h>
 #include <acpi/acinterp.h>
+#include <linux/nmi.h>
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsinit")
@@ -534,7 +535,15 @@
 	info->parameter_type = ACPI_PARAM_ARGS;
 	info->flags = ACPI_IGNORE_RETURN_VALUE;
 
+	/*
+	 * Some hardware relies on this being executed as atomically
+	 * as possible (without an NMI being received in the middle of
+	 * this) - so disable NMIs and initialize the device:
+	 */
+	acpi_nmi_disable();
 	status = acpi_ns_evaluate(info);
+	acpi_nmi_enable();
+
 	if (ACPI_SUCCESS(status)) {
 		walk_info->num_INI++;
 
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 4a9faff..8fcd6a1 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -33,7 +33,7 @@
 
 #define ACPI_NUMA	0x80000000
 #define _COMPONENT	ACPI_NUMA
-ACPI_MODULE_NAME("numa")
+ACPI_MODULE_NAME("numa");
 
 static nodemask_t nodes_found_map = NODE_MASK_NONE;
 #define PXM_INVAL	-1
@@ -45,12 +45,6 @@
 int __cpuinitdata node_to_pxm_map[MAX_NUMNODES]
 				= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
 
-extern int __init acpi_table_parse_madt_family(char *id,
-					       unsigned long madt_size,
-					       int entry_id,
-					       acpi_madt_entry_handler handler,
-					       unsigned int max_entries);
-
 int __cpuinit pxm_to_node(int pxm)
 {
 	if (pxm < 0)
@@ -208,9 +202,9 @@
 
 int __init
 acpi_table_parse_srat(enum acpi_srat_type id,
-		      acpi_madt_entry_handler handler, unsigned int max_entries)
+		      acpi_table_entry_handler handler, unsigned int max_entries)
 {
-	return acpi_table_parse_madt_family(ACPI_SIG_SRAT,
+	return acpi_table_parse_entries(ACPI_SIG_SRAT,
 					    sizeof(struct acpi_table_srat), id,
 					    handler, max_entries);
 }
@@ -220,9 +214,7 @@
 	int result;
 
 	/* SRAT: Static Resource Affinity Table */
-	result = acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat);
-
-	if (result > 0) {
+	if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
 		result = acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
 					       acpi_parse_processor_affinity,
 					       NR_CPUS);
@@ -230,7 +222,7 @@
 	}
 
 	/* SLIT: System Locality Information Table */
-	result = acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
+	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
 
 	acpi_numa_arch_fixup();
 	return 0;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 0f6f3bc..971eca4 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -46,7 +46,7 @@
 #include <linux/efi.h>
 
 #define _COMPONENT		ACPI_OS_SERVICES
-ACPI_MODULE_NAME("osl")
+ACPI_MODULE_NAME("osl");
 #define PREFIX		"ACPI: "
 struct acpi_os_dpc {
 	acpi_osd_exec_callback function;
@@ -68,9 +68,6 @@
 extern char line_buf[80];
 #endif				/*ENABLE_DEBUGGER */
 
-int acpi_specific_hotkey_enabled = TRUE;
-EXPORT_SYMBOL(acpi_specific_hotkey_enabled);
-
 static unsigned int acpi_irq_irq;
 static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
@@ -205,7 +202,7 @@
 {
 	if (phys > ULONG_MAX) {
 		printk(KERN_ERR PREFIX "Cannot map memory that high\n");
-		return 0;
+		return NULL;
 	}
 	if (acpi_gbl_permanent_mmap)
 		/*
@@ -890,26 +887,6 @@
 }
 #endif				/*  ACPI_FUTURE_USAGE  */
 
-/* Assumes no unreadable holes inbetween */
-u8 acpi_os_readable(void *ptr, acpi_size len)
-{
-#if defined(__i386__) || defined(__x86_64__)
-	char tmp;
-	return !__get_user(tmp, (char __user *)ptr)
-	    && !__get_user(tmp, (char __user *)ptr + len - 1);
-#endif
-	return 1;
-}
-
-#ifdef ACPI_FUTURE_USAGE
-u8 acpi_os_writable(void *ptr, acpi_size len)
-{
-	/* could do dummy write (racy) or a kernel page table lookup.
-	   The later may be difficult at early boot when kmap doesn't work yet. */
-	return 1;
-}
-#endif
-
 acpi_status acpi_os_signal(u32 function, void *info)
 {
 	switch (function) {
@@ -1012,14 +989,6 @@
 
 __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
 
-static int __init acpi_hotkey_setup(char *str)
-{
-	acpi_specific_hotkey_enabled = FALSE;
-	return 1;
-}
-
-__setup("acpi_generic_hotkey", acpi_hotkey_setup);
-
 /*
  * max_cstate is defined in the base kernel so modules can
  * change it w/o depending on the state of the processor module.
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 55f57a6..0289693 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -36,7 +36,7 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT		ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_bind")
+ACPI_MODULE_NAME("pci_bind");
 
 struct acpi_pci_data {
 	struct acpi_pci_id id;
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index fe7d007..dd3186a 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -38,7 +38,7 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT		ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_irq")
+ACPI_MODULE_NAME("pci_irq");
 
 static struct acpi_prt_list acpi_prt;
 static DEFINE_SPINLOCK(acpi_prt_lock);
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 0f683c8..acc5947 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -44,10 +44,9 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT		ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_link")
+ACPI_MODULE_NAME("pci_link");
 #define ACPI_PCI_LINK_CLASS		"pci_irq_routing"
 #define ACPI_PCI_LINK_HID		"PNP0C0F"
-#define ACPI_PCI_LINK_DRIVER_NAME	"ACPI PCI Interrupt Link Driver"
 #define ACPI_PCI_LINK_DEVICE_NAME	"PCI Interrupt Link"
 #define ACPI_PCI_LINK_FILE_INFO		"info"
 #define ACPI_PCI_LINK_FILE_STATUS	"state"
@@ -56,7 +55,7 @@
 static int acpi_pci_link_remove(struct acpi_device *device, int type);
 
 static struct acpi_driver acpi_pci_link_driver = {
-	.name = ACPI_PCI_LINK_DRIVER_NAME,
+	.name = "pci_link",
 	.class = ACPI_PCI_LINK_CLASS,
 	.ids = ACPI_PCI_LINK_HID,
 	.ops = {
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 4ecf701..ad4145a 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -36,17 +36,16 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT		ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_root")
+ACPI_MODULE_NAME("pci_root");
 #define ACPI_PCI_ROOT_CLASS		"pci_bridge"
 #define ACPI_PCI_ROOT_HID		"PNP0A03"
-#define ACPI_PCI_ROOT_DRIVER_NAME	"ACPI PCI Root Bridge Driver"
 #define ACPI_PCI_ROOT_DEVICE_NAME	"PCI Root Bridge"
 static int acpi_pci_root_add(struct acpi_device *device);
 static int acpi_pci_root_remove(struct acpi_device *device, int type);
 static int acpi_pci_root_start(struct acpi_device *device);
 
 static struct acpi_driver acpi_pci_root_driver = {
-	.name = ACPI_PCI_ROOT_DRIVER_NAME,
+	.name = "pci_root",
 	.class = ACPI_PCI_ROOT_CLASS,
 	.ids = ACPI_PCI_ROOT_HID,
 	.ops = {
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 0ba7dfb..1ef3385 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -45,10 +45,9 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT		ACPI_POWER_COMPONENT
-ACPI_MODULE_NAME("acpi_power")
+ACPI_MODULE_NAME("power");
 #define ACPI_POWER_COMPONENT		0x00800000
 #define ACPI_POWER_CLASS		"power_resource"
-#define ACPI_POWER_DRIVER_NAME		"ACPI Power Resource Driver"
 #define ACPI_POWER_DEVICE_NAME		"Power Resource"
 #define ACPI_POWER_FILE_INFO		"info"
 #define ACPI_POWER_FILE_STATUS		"state"
@@ -57,25 +56,33 @@
 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
 static int acpi_power_add(struct acpi_device *device);
 static int acpi_power_remove(struct acpi_device *device, int type);
+static int acpi_power_resume(struct acpi_device *device);
 static int acpi_power_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_power_driver = {
-	.name = ACPI_POWER_DRIVER_NAME,
+	.name = "power",
 	.class = ACPI_POWER_CLASS,
 	.ids = ACPI_POWER_HID,
 	.ops = {
 		.add = acpi_power_add,
 		.remove = acpi_power_remove,
+		.resume = acpi_power_resume,
 		},
 };
 
+struct acpi_power_reference {
+	struct list_head node;
+	struct acpi_device *device;
+};
+
 struct acpi_power_resource {
 	struct acpi_device * device;
 	acpi_bus_id name;
 	u32 system_level;
 	u32 order;
 	int state;
-	int references;
+	struct mutex resource_lock;
+	struct list_head reference;
 };
 
 static struct list_head acpi_power_resource_list;
@@ -171,22 +178,47 @@
 	return result;
 }
 
-static int acpi_power_on(acpi_handle handle)
+static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
 {
 	int result = 0;
+	int found = 0;
 	acpi_status status = AE_OK;
-	struct acpi_device *device = NULL;
 	struct acpi_power_resource *resource = NULL;
+	struct list_head *node, *next;
+	struct acpi_power_reference *ref;
 
 
 	result = acpi_power_get_context(handle, &resource);
 	if (result)
 		return result;
 
-	resource->references++;
+	mutex_lock(&resource->resource_lock);
+	list_for_each_safe(node, next, &resource->reference) {
+		ref = container_of(node, struct acpi_power_reference, node);
+		if (dev->handle == ref->device->handle) {
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already referenced by resource [%s]\n",
+				  dev->pnp.bus_id, resource->name));
+			found = 1;
+			break;
+		}
+	}
 
-	if ((resource->references > 1)
-	    || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) {
+	if (!found) {
+		ref = kmalloc(sizeof (struct acpi_power_reference),
+		    irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
+		if (!ref) {
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "kmalloc() failed\n"));
+			mutex_unlock(&resource->resource_lock);
+			return -ENOMEM;
+		}
+		list_add_tail(&ref->node, &resource->reference);
+		ref->device = dev;
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] added to resource [%s] references\n",
+			  dev->pnp.bus_id, resource->name));
+	}
+	mutex_unlock(&resource->resource_lock);
+
+	if (resource->state == ACPI_POWER_RESOURCE_STATE_ON) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n",
 				  resource->name));
 		return 0;
@@ -203,38 +235,49 @@
 		return -ENOEXEC;
 
 	/* Update the power resource's _device_ power state */
-	device = resource->device;
 	resource->device->power.state = ACPI_STATE_D0;
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
 			  resource->name));
-
 	return 0;
 }
 
-static int acpi_power_off_device(acpi_handle handle)
+static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
 {
 	int result = 0;
 	acpi_status status = AE_OK;
 	struct acpi_power_resource *resource = NULL;
+	struct list_head *node, *next;
+	struct acpi_power_reference *ref;
+
 
 	result = acpi_power_get_context(handle, &resource);
 	if (result)
 		return result;
 
-	if (resource->references)
-		resource->references--;
+	mutex_lock(&resource->resource_lock);
+	list_for_each_safe(node, next, &resource->reference) {
+		ref = container_of(node, struct acpi_power_reference, node);
+		if (dev->handle == ref->device->handle) {
+			list_del(&ref->node);
+			kfree(ref);
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] removed from resource [%s] references\n",
+			    dev->pnp.bus_id, resource->name));
+			break;
+		}
+	}
 
-	if (resource->references) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Resource [%s] is still in use, dereferencing\n",
-				  resource->device->pnp.bus_id));
+	if (!list_empty(&resource->reference)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cannot turn resource [%s] off - resource is in use\n",
+		    resource->name));
+		mutex_unlock(&resource->resource_lock);
 		return 0;
 	}
+	mutex_unlock(&resource->resource_lock);
 
 	if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
-				  resource->device->pnp.bus_id));
+				  resource->name));
 		return 0;
 	}
 
@@ -276,7 +319,7 @@
 	arg.integer.value = 1;
 	/* Open power resource */
 	for (i = 0; i < dev->wakeup.resources.count; i++) {
-		ret = acpi_power_on(dev->wakeup.resources.handles[i]);
+		ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
 		if (ret) {
 			printk(KERN_ERR PREFIX "Transition power state\n");
 			dev->wakeup.flags.valid = 0;
@@ -323,7 +366,7 @@
 
 	/* Close power resource */
 	for (i = 0; i < dev->wakeup.resources.count; i++) {
-		ret = acpi_power_off_device(dev->wakeup.resources.handles[i]);
+		ret = acpi_power_off_device(dev->wakeup.resources.handles[i], dev);
 		if (ret) {
 			printk(KERN_ERR PREFIX "Transition power state\n");
 			dev->wakeup.flags.valid = 0;
@@ -407,16 +450,20 @@
 	 * (e.g. so the device doesn't lose power while transitioning).
 	 */
 	for (i = 0; i < tl->count; i++) {
-		result = acpi_power_on(tl->handles[i]);
+		result = acpi_power_on(tl->handles[i], device);
 		if (result)
 			goto end;
 	}
 
+	if (device->power.state == state) {
+		goto end;
+	}
+
 	/*
 	 * Then we dereference all power resources used in the current list.
 	 */
 	for (i = 0; i < cl->count; i++) {
-		result = acpi_power_off_device(cl->handles[i]);
+		result = acpi_power_off_device(cl->handles[i], device);
 		if (result)
 			goto end;
 	}
@@ -439,7 +486,11 @@
 
 static int acpi_power_seq_show(struct seq_file *seq, void *offset)
 {
+	int count = 0;
+	int result = 0;
 	struct acpi_power_resource *resource = NULL;
+	struct list_head *node, *next;
+	struct acpi_power_reference *ref;
 
 
 	resource = seq->private;
@@ -447,6 +498,10 @@
 	if (!resource)
 		goto end;
 
+	result = acpi_power_get_state(resource);
+	if (result)
+		goto end;
+
 	seq_puts(seq, "state:                   ");
 	switch (resource->state) {
 	case ACPI_POWER_RESOURCE_STATE_ON:
@@ -460,11 +515,18 @@
 		break;
 	}
 
+	mutex_lock(&resource->resource_lock);
+	list_for_each_safe(node, next, &resource->reference) {
+		ref = container_of(node, struct acpi_power_reference, node);
+		count++;
+	}
+	mutex_unlock(&resource->resource_lock);
+
 	seq_printf(seq, "system level:            S%d\n"
 		   "order:                   %d\n"
 		   "reference count:         %d\n",
 		   resource->system_level,
-		   resource->order, resource->references);
+		   resource->order, count);
 
       end:
 	return 0;
@@ -537,6 +599,8 @@
 		return -ENOMEM;
 
 	resource->device = device;
+	mutex_init(&resource->resource_lock);
+	INIT_LIST_HEAD(&resource->reference);
 	strcpy(resource->name, device->pnp.bus_id);
 	strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
 	strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
@@ -584,6 +648,7 @@
 static int acpi_power_remove(struct acpi_device *device, int type)
 {
 	struct acpi_power_resource *resource = NULL;
+	struct list_head *node, *next;
 
 
 	if (!device || !acpi_driver_data(device))
@@ -593,11 +658,54 @@
 
 	acpi_power_remove_fs(device);
 
+	mutex_lock(&resource->resource_lock);
+	list_for_each_safe(node, next, &resource->reference) {
+		struct acpi_power_reference *ref = container_of(node, struct acpi_power_reference, node);
+		list_del(&ref->node);
+		kfree(ref);
+	}
+	mutex_unlock(&resource->resource_lock);
+
 	kfree(resource);
 
 	return 0;
 }
 
+static int acpi_power_resume(struct acpi_device *device)
+{
+	int result = 0;
+	struct acpi_power_resource *resource = NULL;
+	struct acpi_power_reference *ref;
+
+	if (!device || !acpi_driver_data(device))
+		return -EINVAL;
+
+	resource = (struct acpi_power_resource *)acpi_driver_data(device);
+
+	result = acpi_power_get_state(resource);
+	if (result)
+		return result;
+
+	mutex_lock(&resource->resource_lock);
+	if ((resource->state == ACPI_POWER_RESOURCE_STATE_ON) &&
+	    list_empty(&resource->reference)) {
+		mutex_unlock(&resource->resource_lock);
+		result = acpi_power_off_device(device->handle, NULL);
+		return result;
+	}
+
+	if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) &&
+	    !list_empty(&resource->reference)) {
+		ref = container_of(resource->reference.next, struct acpi_power_reference, node);
+		mutex_unlock(&resource->resource_lock);
+		result = acpi_power_on(device->handle, ref->device);
+		return result;
+	}
+
+	mutex_unlock(&resource->resource_lock);
+	return 0;
+}
+
 static int __init acpi_power_init(void)
 {
 	int result = 0;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 0079bc5..99d1516 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -60,7 +60,6 @@
 
 #define ACPI_PROCESSOR_COMPONENT	0x01000000
 #define ACPI_PROCESSOR_CLASS		"processor"
-#define ACPI_PROCESSOR_DRIVER_NAME	"ACPI Processor Driver"
 #define ACPI_PROCESSOR_DEVICE_NAME	"Processor"
 #define ACPI_PROCESSOR_FILE_INFO	"info"
 #define ACPI_PROCESSOR_FILE_THROTTLING	"throttling"
@@ -74,10 +73,10 @@
 #define ACPI_STA_PRESENT 0x00000001
 
 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_core");
 
-    MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Processor Driver");
 MODULE_LICENSE("GPL");
 
 static int acpi_processor_add(struct acpi_device *device);
@@ -89,7 +88,7 @@
 static int acpi_processor_handle_eject(struct acpi_processor *pr);
 
 static struct acpi_driver acpi_processor_driver = {
-	.name = ACPI_PROCESSOR_DRIVER_NAME,
+	.name = "processor",
 	.class = ACPI_PROCESSOR_CLASS,
 	.ids = ACPI_PROCESSOR_HID,
 	.ops = {
@@ -404,7 +403,7 @@
 	if (lsapic->lapic_flags & ACPI_MADT_ENABLED) {
 		/* First check against id */
 		if (lsapic->processor_id == acpi_id) {
-			*apic_id = lsapic->id;
+			*apic_id = (lsapic->id << 8) | lsapic->eid;
 			return 1;
 		/* Check against optional uid */
 		} else if (entry->length >= 16 &&
@@ -1005,7 +1004,7 @@
 #ifdef CONFIG_SMP
 	if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
 				(struct acpi_table_header **)&madt)))
-		madt = 0;
+		madt = NULL;
 #endif
 
 	acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 6c6751b..6077300 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -39,6 +39,25 @@
 #include <linux/moduleparam.h>
 #include <linux/sched.h>	/* need_resched() */
 #include <linux/latency.h>
+#include <linux/clockchips.h>
+
+/*
+ * Include the apic definitions for x86 to have the APIC timer related defines
+ * available also for UP (on SMP it gets magically included via linux/smp.h).
+ * asm/acpi.h is not an option, as it would require more include magic. Also
+ * creating an empty asm-ia64/apic.h would just trade pest vs. cholera.
+ */
+#ifdef CONFIG_X86
+#include <asm/apic.h>
+#endif
+
+/*
+ * Include the apic definitions for x86 to have the APIC timer related defines
+ * available also for UP (on SMP it gets magically included via linux/smp.h).
+ */
+#ifdef CONFIG_X86
+#include <asm/apic.h>
+#endif
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -48,9 +67,8 @@
 
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_CLASS            "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME      "ACPI Processor Driver"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_idle");
 #define ACPI_PROCESSOR_FILE_POWER	"power"
 #define US_TO_PM_TIMER_TICKS(t)		((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
 #define C2_OVERHEAD			4	/* 1us (3.579 ticks per us) */
@@ -238,6 +256,81 @@
 	}
 }
 
+#ifdef ARCH_APICTIMER_STOPS_ON_C3
+
+/*
+ * Some BIOS implementations switch to C3 in the published C2 state.
+ * This seems to be a common problem on AMD boxen, but other vendors
+ * are affected too. We pick the most conservative approach: we assume
+ * that the local APIC stops in both C2 and C3.
+ */
+static void acpi_timer_check_state(int state, struct acpi_processor *pr,
+				   struct acpi_processor_cx *cx)
+{
+	struct acpi_processor_power *pwr = &pr->power;
+
+	/*
+	 * Check, if one of the previous states already marked the lapic
+	 * unstable
+	 */
+	if (pwr->timer_broadcast_on_state < state)
+		return;
+
+	if (cx->type >= ACPI_STATE_C2)
+		pr->power.timer_broadcast_on_state = state;
+}
+
+static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
+{
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+	unsigned long reason;
+
+	reason = pr->power.timer_broadcast_on_state < INT_MAX ?
+		CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
+
+	clockevents_notify(reason, &pr->id);
+#else
+	cpumask_t mask = cpumask_of_cpu(pr->id);
+
+	if (pr->power.timer_broadcast_on_state < INT_MAX)
+		on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
+	else
+		on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
+#endif
+}
+
+/* Power(C) State timer broadcast control */
+static void acpi_state_timer_broadcast(struct acpi_processor *pr,
+				       struct acpi_processor_cx *cx,
+				       int broadcast)
+{
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+
+	int state = cx - pr->power.states;
+
+	if (state >= pr->power.timer_broadcast_on_state) {
+		unsigned long reason;
+
+		reason = broadcast ?  CLOCK_EVT_NOTIFY_BROADCAST_ENTER :
+			CLOCK_EVT_NOTIFY_BROADCAST_EXIT;
+		clockevents_notify(reason, &pr->id);
+	}
+#endif
+}
+
+#else
+
+static void acpi_timer_check_state(int state, struct acpi_processor *pr,
+				   struct acpi_processor_cx *cstate) { }
+static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { }
+static void acpi_state_timer_broadcast(struct acpi_processor *pr,
+				       struct acpi_processor_cx *cx,
+				       int broadcast)
+{
+}
+
+#endif
+
 static void acpi_processor_idle(void)
 {
 	struct acpi_processor *pr = NULL;
@@ -382,6 +475,7 @@
 		/* Get start time (ticks) */
 		t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
 		/* Invoke C2 */
+		acpi_state_timer_broadcast(pr, cx, 1);
 		acpi_cstate_enter(cx);
 		/* Get end time (ticks) */
 		t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -396,6 +490,7 @@
 		/* Compute time (ticks) that we were actually asleep */
 		sleep_ticks =
 		    ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
+		acpi_state_timer_broadcast(pr, cx, 0);
 		break;
 
 	case ACPI_STATE_C3:
@@ -417,6 +512,7 @@
 		/* Get start time (ticks) */
 		t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
 		/* Invoke C3 */
+		acpi_state_timer_broadcast(pr, cx, 1);
 		acpi_cstate_enter(cx);
 		/* Get end time (ticks) */
 		t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -436,6 +532,7 @@
 		/* Compute time (ticks) that we were actually asleep */
 		sleep_ticks =
 		    ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
+		acpi_state_timer_broadcast(pr, cx, 0);
 		break;
 
 	default:
@@ -904,11 +1001,7 @@
 	unsigned int i;
 	unsigned int working = 0;
 
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
-	int timer_broadcast = 0;
-	cpumask_t mask = cpumask_of_cpu(pr->id);
-	on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
-#endif
+	pr->power.timer_broadcast_on_state = INT_MAX;
 
 	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
 		struct acpi_processor_cx *cx = &pr->power.states[i];
@@ -920,21 +1013,14 @@
 
 		case ACPI_STATE_C2:
 			acpi_processor_power_verify_c2(cx);
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
-			/* Some AMD systems fake C3 as C2, but still
-			   have timer troubles */
-			if (cx->valid && 
-				boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-				timer_broadcast++;
-#endif
+			if (cx->valid)
+				acpi_timer_check_state(i, pr, cx);
 			break;
 
 		case ACPI_STATE_C3:
 			acpi_processor_power_verify_c3(pr, cx);
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
 			if (cx->valid)
-				timer_broadcast++;
-#endif
+				acpi_timer_check_state(i, pr, cx);
 			break;
 		}
 
@@ -942,10 +1028,7 @@
 			working++;
 	}
 
-#ifdef ARCH_APICTIMER_STOPS_ON_C3
-	if (timer_broadcast)
-		on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
-#endif
+	acpi_propagate_timer_broadcast(pr);
 
 	return (working);
 }
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 058f13c..2f2e796 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -44,10 +44,9 @@
 
 #define ACPI_PROCESSOR_COMPONENT	0x01000000
 #define ACPI_PROCESSOR_CLASS		"processor"
-#define ACPI_PROCESSOR_DRIVER_NAME	"ACPI Processor Driver"
 #define ACPI_PROCESSOR_FILE_PERFORMANCE	"performance"
 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_perflib");
 
 static DEFINE_MUTEX(performance_mutex);
 
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 40fecd6..06e6f3f 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -41,9 +41,8 @@
 
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_CLASS            "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME      "ACPI Processor Driver"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_thermal");
 
 /* --------------------------------------------------------------------------
                                  Limit Interface
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 89dff36..b334860 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -41,9 +41,8 @@
 
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_CLASS            "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME      "ACPI Processor Driver"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_throttling");
 
 /* --------------------------------------------------------------------------
                               Throttling Control
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index f58fc74..59640d9 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -59,7 +59,6 @@
 #define ACPI_AC_CLASS			"ac_adapter"
 #define ACPI_BATTERY_CLASS		"battery"
 #define ACPI_SBS_HID			"ACPI0002"
-#define ACPI_SBS_DRIVER_NAME		"ACPI Smart Battery System Driver"
 #define ACPI_SBS_DEVICE_NAME		"Smart Battery System"
 #define ACPI_SBS_FILE_INFO		"info"
 #define ACPI_SBS_FILE_STATE		"state"
@@ -78,7 +77,7 @@
 #define	MAX_SBS_BAT			4
 #define	MAX_SMBUS_ERR			1
 
-ACPI_MODULE_NAME("acpi_sbs");
+ACPI_MODULE_NAME("sbs");
 
 MODULE_AUTHOR("Rich Townsend");
 MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
@@ -110,7 +109,7 @@
 static void acpi_sbs_update_queue(void *data);
 
 static struct acpi_driver acpi_sbs_driver = {
-	.name = ACPI_SBS_DRIVER_NAME,
+	.name = "sbs",
 	.class = ACPI_SBS_CLASS,
 	.ids = ACPI_SBS_HID,
 	.ops = {
@@ -1034,21 +1033,19 @@
 	} else {
 		seq_printf(seq, "capacity state:          ok\n");
 	}
+
+	foo = (s16) battery->state.amperage * battery->info.ipscale;
+	if (battery->info.capacity_mode) {
+		foo = foo * battery->info.design_voltage / 1000;
+	}
 	if (battery->state.amperage < 0) {
 		seq_printf(seq, "charging state:          discharging\n");
-		foo = battery->state.remaining_capacity * cscale * 60 /
-		    (battery->state.average_time_to_empty == 0 ? 1 :
-		     battery->state.average_time_to_empty);
-		seq_printf(seq, "present rate:            %i%s\n",
-			   foo, battery->info.capacity_mode ? "0 mW" : " mA");
+		seq_printf(seq, "present rate:            %d %s\n",
+			   -foo, battery->info.capacity_mode ? "mW" : "mA");
 	} else if (battery->state.amperage > 0) {
 		seq_printf(seq, "charging state:          charging\n");
-		foo = (battery->info.full_charge_capacity -
-		       battery->state.remaining_capacity) * cscale * 60 /
-		    (battery->state.average_time_to_full == 0 ? 1 :
-		     battery->state.average_time_to_full);
-		seq_printf(seq, "present rate:            %i%s\n",
-			   foo, battery->info.capacity_mode ? "0 mW" : " mA");
+		seq_printf(seq, "present rate:            %d %s\n",
+			   foo, battery->info.capacity_mode ? "mW" : "mA");
 	} else {
 		seq_printf(seq, "charging state:          charged\n");
 		seq_printf(seq, "present rate:            0 %s\n",
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 64f26db..bb0e0da 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -11,13 +11,12 @@
 #include <acpi/acinterp.h>	/* for acpi_ex_eisa_id_to_string() */
 
 #define _COMPONENT		ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME("scan")
+ACPI_MODULE_NAME("scan");
 #define STRUCT_TO_INT(s)	(*((int*)&s))
 extern struct acpi_device *acpi_root;
 
 #define ACPI_BUS_CLASS			"system_bus"
 #define ACPI_BUS_HID			"ACPI_BUS"
-#define ACPI_BUS_DRIVER_NAME		"ACPI Bus Driver"
 #define ACPI_BUS_DEVICE_NAME		"System Bus"
 
 static LIST_HEAD(acpi_device_list);
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 62ce87d..37a0930 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -200,7 +200,7 @@
 	{},
 };
 
-static int __init acpi_sleep_init(void)
+int __init acpi_sleep_init(void)
 {
 	int i = 0;
 
@@ -229,4 +229,3 @@
 	return 0;
 }
 
-late_initcall(acpi_sleep_init);
diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c
index 47fb4b3..d9801ef 100644
--- a/drivers/acpi/sleep/poweroff.c
+++ b/drivers/acpi/sleep/poweroff.c
@@ -12,7 +12,6 @@
 #include <linux/pm.h>
 #include <linux/init.h>
 #include <acpi/acpi_bus.h>
-#include <linux/sched.h>
 #include <linux/sysdev.h>
 #include <asm/io.h>
 #include "sleep.h"
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 7147b0b..83a8d30 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -31,14 +31,13 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME("acpi_system")
+ACPI_MODULE_NAME("system");
 #ifdef MODULE_PARAM_PREFIX
 #undef MODULE_PARAM_PREFIX
 #endif
 #define MODULE_PARAM_PREFIX "acpi."
 
 #define ACPI_SYSTEM_CLASS		"system"
-#define ACPI_SYSTEM_DRIVER_NAME		"ACPI System Driver"
 #define ACPI_SYSTEM_DEVICE_NAME		"System"
 #define ACPI_SYSTEM_FILE_INFO		"info"
 #define ACPI_SYSTEM_FILE_EVENT		"event"
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index ba4cb20..849e2c3 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -25,7 +25,6 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/string.h>
 #include <linux/types.h>
@@ -170,40 +169,40 @@
 
 
 int __init
-acpi_table_parse_madt_family(char *id,
-			     unsigned long madt_size,
+acpi_table_parse_entries(char *id,
+			     unsigned long table_size,
 			     int entry_id,
-			     acpi_madt_entry_handler handler,
+			     acpi_table_entry_handler handler,
 			     unsigned int max_entries)
 {
-	struct acpi_table_header *madt = NULL;
+	struct acpi_table_header *table_header = NULL;
 	struct acpi_subtable_header *entry;
 	unsigned int count = 0;
-	unsigned long madt_end;
+	unsigned long table_end;
 
 	if (!handler)
 		return -EINVAL;
 
-	/* Locate the MADT (if exists). There should only be one. */
-	acpi_get_table(id, 0, &madt);
+	/* Locate the table (if exists). There should only be one. */
+	acpi_get_table(id, 0, &table_header);
 
-	if (!madt) {
+	if (!table_header) {
 		printk(KERN_WARNING PREFIX "%4.4s not present\n", id);
 		return -ENODEV;
 	}
 
-	madt_end = (unsigned long)madt + madt->length;
+	table_end = (unsigned long)table_header + table_header->length;
 
 	/* Parse all entries looking for a match. */
 
 	entry = (struct acpi_subtable_header *)
-	    ((unsigned long)madt + madt_size);
+	    ((unsigned long)table_header + table_size);
 
 	while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
-	       madt_end) {
+	       table_end) {
 		if (entry->type == entry_id
 		    && (!max_entries || count++ < max_entries))
-			if (handler(entry, madt_end))
+			if (handler(entry, table_end))
 				return -EINVAL;
 
 		entry = (struct acpi_subtable_header *)
@@ -219,13 +218,22 @@
 
 int __init
 acpi_table_parse_madt(enum acpi_madt_type id,
-		      acpi_madt_entry_handler handler, unsigned int max_entries)
+		      acpi_table_entry_handler handler, unsigned int max_entries)
 {
-	return acpi_table_parse_madt_family(ACPI_SIG_MADT,
+	return acpi_table_parse_entries(ACPI_SIG_MADT,
 					    sizeof(struct acpi_table_madt), id,
 					    handler, max_entries);
 }
 
+/**
+ * acpi_table_parse - find table with @id, run @handler on it
+ *
+ * @id: table id to find
+ * @handler: handler to run
+ *
+ * Scan the ACPI System Descriptor Table (STD) for a table matching @id,
+ * run @handler on it.  Return 0 if table found, return on if not.
+ */
 int __init acpi_table_parse(char *id, acpi_table_handler handler)
 {
 	struct acpi_table_header *table = NULL;
@@ -235,9 +243,9 @@
 	acpi_get_table(id, 0, &table);
 	if (table) {
 		handler(table);
-		return 1;
-	} else
 		return 0;
+	} else
+		return 1;
 }
 
 /*
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 807978d..417ef5f 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -338,9 +338,9 @@
 	int i;
 	acpi_status status = AE_NOT_EXIST;
 
-	ACPI_FUNCTION_TRACE(acpi_unload_table);
+	ACPI_FUNCTION_TRACE(acpi_unload_table_id);
 
-	/* Find table from the requested type list */
+	/* Find table in the global table list */
 	for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
 		if (id != acpi_gbl_root_table_list.tables[i].owner_id) {
 			continue;
@@ -352,8 +352,9 @@
 		* simply a position within the hierarchy
 		*/
 		acpi_tb_delete_namespace_by_owner(i);
-		acpi_tb_release_owner_id(i);
+		status = acpi_tb_release_owner_id(i);
 		acpi_tb_set_table_loaded_flag(i, FALSE);
+		break;
 	}
 	return_ACPI_STATUS(status);
 }
@@ -408,7 +409,7 @@
 		}
 
 		if (!acpi_gbl_permanent_mmap) {
-			acpi_gbl_root_table_list.tables[i].pointer = 0;
+			acpi_gbl_root_table_list.tables[i].pointer = NULL;
 		}
 
 		return (status);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index f76d316..0ae8b93 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -36,7 +36,8 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
-#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
 #include <linux/kmod.h>
 #include <linux/seq_file.h>
 #include <asm/uaccess.h>
@@ -46,7 +47,6 @@
 
 #define ACPI_THERMAL_COMPONENT		0x04000000
 #define ACPI_THERMAL_CLASS		"thermal_zone"
-#define ACPI_THERMAL_DRIVER_NAME	"ACPI Thermal Zone Driver"
 #define ACPI_THERMAL_DEVICE_NAME	"Thermal Zone"
 #define ACPI_THERMAL_FILE_STATE		"state"
 #define ACPI_THERMAL_FILE_TEMPERATURE	"temperature"
@@ -70,10 +70,10 @@
 #define CELSIUS_TO_KELVIN(t)	((t+273)*10)
 
 #define _COMPONENT		ACPI_THERMAL_COMPONENT
-ACPI_MODULE_NAME("acpi_thermal")
+ACPI_MODULE_NAME("thermal");
 
 MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
+MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
 MODULE_LICENSE("GPL");
 
 static int tzp;
@@ -98,7 +98,7 @@
 					  size_t, loff_t *);
 
 static struct acpi_driver acpi_thermal_driver = {
-	.name = ACPI_THERMAL_DRIVER_NAME,
+	.name = "thermal",
 	.class = ACPI_THERMAL_CLASS,
 	.ids = ACPI_THERMAL_HID,
 	.ops = {
@@ -269,7 +269,7 @@
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 			  "Polling frequency set to %lu seconds\n",
-			  tz->polling_frequency));
+			  tz->polling_frequency/10));
 
 	return 0;
 }
@@ -1356,28 +1356,32 @@
 static int acpi_thermal_resume(struct acpi_device *device)
 {
 	struct acpi_thermal *tz = NULL;
-	int i;
+	int i, j, power_state, result;
+
 
 	if (!device || !acpi_driver_data(device))
 		return -EINVAL;
 
 	tz = acpi_driver_data(device);
 
-	acpi_thermal_get_temperature(tz);
-
 	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-		if (tz->trips.active[i].flags.valid) {
- 			tz->temperature = tz->trips.active[i].temperature;
-			tz->trips.active[i].flags.enabled = 0;
-
-			acpi_thermal_active(tz);
-
-			tz->state.active |= tz->trips.active[i].flags.enabled;
-			tz->state.active_index = i;
+		if (!(&tz->trips.active[i]))
+			break;
+		if (!tz->trips.active[i].flags.valid)
+			break;
+		tz->trips.active[i].flags.enabled = 1;
+		for (j = 0; j < tz->trips.active[i].devices.count; j++) {
+			result = acpi_bus_get_power(tz->trips.active[i].devices.
+			    handles[j], &power_state);
+			if (result || (power_state != ACPI_STATE_D0)) {
+				tz->trips.active[i].flags.enabled = 0;
+				break;
+			}
 		}
+		tz->state.active |= tz->trips.active[i].flags.enabled;
 	}
 
- 	acpi_thermal_check(tz);
+	acpi_thermal_check(tz);
 
 	return AE_OK;
 }
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index d9b651f..3906d47 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -125,7 +125,7 @@
 	union acpi_object in_objs[1];
 	acpi_status status;
 
-	params.count = sizeof(in_objs) / sizeof(in_objs[0]);
+	params.count = ARRAY_SIZE(in_objs);
 	params.pointer = in_objs;
 	in_objs[0].type = ACPI_TYPE_INTEGER;
 	in_objs[0].integer.value = val;
@@ -315,7 +315,7 @@
 
 static int set_lcd_status(struct backlight_device *bd)
 {
-	return set_lcd(bd->props->brightness);
+	return set_lcd(bd->props.brightness);
 }
 
 static unsigned long write_lcd(const char *buffer, unsigned long count)
@@ -533,11 +533,9 @@
 	return AE_OK;
 }
 
-static struct backlight_properties toshiba_backlight_data = {
-        .owner          = THIS_MODULE,
+static struct backlight_ops toshiba_backlight_data = {
         .get_brightness = get_lcd,
         .update_status  = set_lcd_status,
-        .max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1,
 };
 
 static void __exit toshiba_acpi_exit(void)
@@ -561,10 +559,6 @@
 	if (acpi_disabled)
 		return -ENODEV;
 
-	if (!acpi_specific_hotkey_enabled) {
-		printk(MY_INFO "Using generic hotkey driver\n");
-		return -ENODEV;
-	}
 	/* simple device detection: look for HCI method */
 	if (is_valid_acpi_path(METHOD_HCI_1))
 		method_hci = METHOD_HCI_1;
@@ -601,6 +595,7 @@
 		toshiba_backlight_device = NULL;
 		toshiba_acpi_exit();
 	}
+        toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
 
 	return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
 }
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index f777ceb..673a0ca 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -170,7 +170,6 @@
 			acpi_os_delete_mutex(object->mutex.os_mutex);
 			acpi_gbl_global_lock_mutex = NULL;
 		} else {
-			acpi_ex_unlink_mutex(object);
 			acpi_os_delete_mutex(object->mutex.os_mutex);
 		}
 		break;
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 68a809f..34f1575 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -31,7 +31,7 @@
 #include <acpi/acpi_drivers.h>
 
 #define _COMPONENT		ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME("acpi_utils")
+ACPI_MODULE_NAME("utils");
 
 /* --------------------------------------------------------------------------
                             Object Evaluation Helpers
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index e0b97ad..0771b43 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -40,7 +40,6 @@
 
 #define ACPI_VIDEO_COMPONENT		0x08000000
 #define ACPI_VIDEO_CLASS		"video"
-#define ACPI_VIDEO_DRIVER_NAME		"ACPI Video Driver"
 #define ACPI_VIDEO_BUS_NAME		"Video Bus"
 #define ACPI_VIDEO_DEVICE_NAME		"Video Device"
 #define ACPI_VIDEO_NOTIFY_SWITCH	0x80
@@ -65,17 +64,17 @@
 #define ACPI_VIDEO_DISPLAY_LCD	4
 
 #define _COMPONENT		ACPI_VIDEO_COMPONENT
-ACPI_MODULE_NAME("acpi_video")
+ACPI_MODULE_NAME("video");
 
-    MODULE_AUTHOR("Bruno Ducrot");
-MODULE_DESCRIPTION(ACPI_VIDEO_DRIVER_NAME);
+MODULE_AUTHOR("Bruno Ducrot");
+MODULE_DESCRIPTION("ACPI Video Driver");
 MODULE_LICENSE("GPL");
 
 static int acpi_video_bus_add(struct acpi_device *device);
 static int acpi_video_bus_remove(struct acpi_device *device, int type);
 
 static struct acpi_driver acpi_video_bus = {
-	.name = ACPI_VIDEO_DRIVER_NAME,
+	.name = "video",
 	.class = ACPI_VIDEO_CLASS,
 	.ids = ACPI_VIDEO_HID,
 	.ops = {
@@ -170,7 +169,6 @@
 	struct acpi_device *dev;
 	struct acpi_video_device_brightness *brightness;
 	struct backlight_device *backlight;
-	struct backlight_properties *data;
 };
 
 /* bus */
@@ -287,13 +285,18 @@
 
 static int acpi_video_set_brightness(struct backlight_device *bd)
 {
-	int request_level = bd->props->brightness;
+	int request_level = bd->props.brightness;
 	struct acpi_video_device *vd =
 		(struct acpi_video_device *)class_get_devdata(&bd->class_dev);
 	acpi_video_device_lcd_set_level(vd, request_level);
 	return 0;
 }
 
+static struct backlight_ops acpi_backlight_ops = {
+	.get_brightness = acpi_video_get_brightness,
+	.update_status  = acpi_video_set_brightness,
+};
+
 /* --------------------------------------------------------------------------
                                Video Management
    -------------------------------------------------------------------------- */
@@ -609,31 +612,18 @@
 		unsigned long tmp;
 		static int count = 0;
 		char *name;
-		struct backlight_properties *acpi_video_data;
-
 		name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
 		if (!name)
 			return;
 
-		acpi_video_data = kzalloc(
-			sizeof(struct backlight_properties),
-			GFP_KERNEL);
-		if (!acpi_video_data){
-			kfree(name);
-			return;
-		}
-		acpi_video_data->owner = THIS_MODULE;
-		acpi_video_data->get_brightness =
-			acpi_video_get_brightness;
-		acpi_video_data->update_status =
-			acpi_video_set_brightness;
 		sprintf(name, "acpi_video%d", count++);
-		device->data = acpi_video_data;
-		acpi_video_data->max_brightness = max_level;
 		acpi_video_device_lcd_get_level_current(device, &tmp);
-		acpi_video_data->brightness = (int)tmp;
 		device->backlight = backlight_device_register(name,
-			NULL, device, acpi_video_data);
+			NULL, device, &acpi_backlight_ops);
+		device->backlight->props.max_brightness = max_level;
+		device->backlight->props.brightness = (int)tmp;
+		backlight_update_status(device->backlight);
+
 		kfree(name);
 	}
 	return;
@@ -1678,10 +1668,7 @@
 	status = acpi_remove_notify_handler(device->dev->handle,
 					    ACPI_DEVICE_NOTIFY,
 					    acpi_video_device_notify);
-	if (device->backlight){
-		backlight_device_unregister(device->backlight);
-		kfree(device->data);
-	}
+	backlight_device_unregister(device->backlight);
 	return 0;
 }
 
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 1c94b43..4af0a4b 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -41,12 +41,12 @@
 	  If unsure, say N.
 
 config ATA_PIIX
-	tristate "Intel PIIX/ICH SATA support"
+	tristate "Intel ESB, ICH, PIIX3, PIIX4 PATA/SATA support"
 	depends on PCI
 	help
 	  This option enables support for ICH5/6/7/8 Serial ATA
-	  and support for PATA on the Intel PIIX3/PIIX4/ICH series
-	  PATA host controllers.
+	  and support for PATA on the Intel ESB/ICH/PIIX3/PIIX4 series
+	  host controllers.
 
 	  If unsure, say N.
 
@@ -116,11 +116,14 @@
 	  If unsure, say N.
 
 config SATA_SIS
-	tristate "SiS 964/180 SATA support"
+	tristate "SiS 964/965/966/180 SATA support"
 	depends on PCI
+	select PATA_SIS
 	help
-	  This option enables support for SiS Serial ATA 964/180.
-
+	  This option enables support for SiS Serial ATA on 
+	  SiS 964/965/966/180 and Parallel ATA on SiS 180.
+	  The PATA support for SiS 180 requires additionally to
+	  enable the PATA_SIS driver in the config.
 	  If unsure, say N.
 
 config SATA_ULI
@@ -147,11 +150,30 @@
 
 	  If unsure, say N.
 
+config SATA_INIC162X
+	tristate "Initio 162x SATA support (HIGHLY EXPERIMENTAL)"
+	depends on PCI && EXPERIMENTAL
+	help
+	  This option enables support for Initio 162x Serial ATA.
+
 config SATA_INTEL_COMBINED
 	bool
 	depends on IDE=y && !BLK_DEV_IDE_SATA && (SATA_AHCI || ATA_PIIX)
 	default y
 
+config SATA_ACPI
+	bool
+	depends on ACPI && PCI
+	default y
+	help
+	  This option adds support for SATA-related ACPI objects.
+	  These ACPI objects add the ability to retrieve taskfiles
+	  from the ACPI BIOS and write them to the disk controller.
+	  These objects may be related to performance, security,
+	  power management, or other areas.
+	  You can disable this at kernel boot time by using the
+	  option libata.noacpi=1
+
 config PATA_ALI
 	tristate "ALi PATA support (Experimental)"
 	depends on PCI && EXPERIMENTAL
@@ -296,7 +318,7 @@
 	  If unsure, say N.
 
 config PATA_IT821X
-	tristate "IT821x PATA support (Experimental)"
+	tristate "IT8211/2 PATA support (Experimental)"
 	depends on PCI && EXPERIMENTAL
 	help
 	  This option enables support for the ITE 8211 and 8212
@@ -305,6 +327,15 @@
 
 	  If unsure, say N.
 
+config PATA_IT8213
+	tristate "IT8213 PATA support (Experimental)"
+	depends on PCI && EXPERIMENTAL
+	help
+	  This option enables support for the ITE 821 PATA
+          controllers via the new ATA layer.
+
+	  If unsure, say N.
+
 config PATA_JMICRON
 	tristate "JMicron PATA support"
 	depends on PCI
@@ -341,6 +372,15 @@
 
 	  If unsure, say N.
 
+config PATA_MPC52xx
+	tristate "Freescale MPC52xx SoC internal IDE"
+	depends on PPC_MPC52xx
+	help
+	  This option enables support for integrated IDE controller
+	  of the Freescale MPC52xx SoC.
+
+	  If unsure, say N.
+
 config PATA_MPIIX
 	tristate "Intel PATA MPIIX support"
 	depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index bc3d81a..74298af 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_SATA_NV)		+= sata_nv.o
 obj-$(CONFIG_SATA_ULI)		+= sata_uli.o
 obj-$(CONFIG_SATA_MV)		+= sata_mv.o
+obj-$(CONFIG_SATA_INIC162X)	+= sata_inic162x.o
 obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
 
 obj-$(CONFIG_PATA_ALI)		+= pata_ali.o
@@ -33,11 +34,13 @@
 obj-$(CONFIG_PATA_HPT3X3)	+= pata_hpt3x3.o
 obj-$(CONFIG_PATA_ISAPNP)	+= pata_isapnp.o
 obj-$(CONFIG_PATA_IT821X)	+= pata_it821x.o
+obj-$(CONFIG_PATA_IT8213)	+= pata_it8213.o
 obj-$(CONFIG_PATA_JMICRON)	+= pata_jmicron.o
 obj-$(CONFIG_PATA_NETCELL)	+= pata_netcell.o
 obj-$(CONFIG_PATA_NS87410)	+= pata_ns87410.o
 obj-$(CONFIG_PATA_OPTI)		+= pata_opti.o
 obj-$(CONFIG_PATA_OPTIDMA)	+= pata_optidma.o
+obj-$(CONFIG_PATA_MPC52xx)	+= pata_mpc52xx.o
 obj-$(CONFIG_PATA_MARVELL)	+= pata_marvell.o
 obj-$(CONFIG_PATA_MPIIX)	+= pata_mpiix.o
 obj-$(CONFIG_PATA_OLDPIIX)	+= pata_oldpiix.o
@@ -63,4 +66,4 @@
 obj-$(CONFIG_PATA_LEGACY)	+= pata_legacy.o
 
 libata-objs	:= libata-core.o libata-scsi.o libata-sff.o libata-eh.o
-
+libata-$(CONFIG_SATA_ACPI) += libata-acpi.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 48616c6..6a3543e 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -39,13 +39,11 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
-#include <asm/io.h>
 
 #define DRV_NAME	"ahci"
 #define DRV_VERSION	"2.0"
@@ -166,9 +164,6 @@
 	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
 	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
 
-	/* hpriv->flags bits */
-	AHCI_FLAG_MSI		= (1 << 0),
-
 	/* ap->flags bits */
 	AHCI_FLAG_NO_NCQ		= (1 << 24),
 	AHCI_FLAG_IGN_IRQ_IF_ERR	= (1 << 25), /* ignore IRQ_IF_ERR */
@@ -191,7 +186,6 @@
 };
 
 struct ahci_host_priv {
-	unsigned long		flags;
 	u32			cap;	/* cache of HOST_CAP register */
 	u32			port_map; /* cache of HOST_PORTS_IMPL reg */
 };
@@ -229,7 +223,6 @@
 static int ahci_port_resume(struct ata_port *ap);
 static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int ahci_pci_device_resume(struct pci_dev *pdev);
-static void ahci_remove_one (struct pci_dev *pdev);
 
 static struct scsi_host_template ahci_sht = {
 	.module			= THIS_MODULE,
@@ -266,6 +259,8 @@
 
 	.irq_handler		= ahci_interrupt,
 	.irq_clear		= ahci_irq_clear,
+	.irq_on			= ata_dummy_irq_on,
+	.irq_ack		= ata_dummy_irq_ack,
 
 	.scr_read		= ahci_scr_read,
 	.scr_write		= ahci_scr_write,
@@ -297,6 +292,8 @@
 
 	.irq_handler		= ahci_interrupt,
 	.irq_clear		= ahci_irq_clear,
+	.irq_on			= ata_dummy_irq_on,
+	.irq_ack		= ata_dummy_irq_ack,
 
 	.scr_read		= ahci_scr_read,
 	.scr_write		= ahci_scr_write,
@@ -431,7 +428,7 @@
 
 	/* Generic, PCI class code for AHCI */
 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-	  0x010601, 0xffffff, board_ahci },
+	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
 
 	{ }	/* terminate list */
 };
@@ -441,9 +438,9 @@
 	.name			= DRV_NAME,
 	.id_table		= ahci_pci_tbl,
 	.probe			= ahci_init_one,
+	.remove			= ata_pci_remove_one,
 	.suspend		= ahci_pci_device_suspend,
 	.resume			= ahci_pci_device_resume,
-	.remove			= ahci_remove_one,
 };
 
 
@@ -452,16 +449,12 @@
 	return (cap & 0x1f) + 1;
 }
 
-static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int port)
+static inline void __iomem *ahci_port_base(void __iomem *base,
+					   unsigned int port)
 {
 	return base + 0x100 + (port * 0x80);
 }
 
-static inline void __iomem *ahci_port_base (void __iomem *base, unsigned int port)
-{
-	return (void __iomem *) ahci_port_base_ul((unsigned long)base, port);
-}
-
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
 {
 	unsigned int sc_reg;
@@ -475,7 +468,7 @@
 		return 0xffffffffU;
 	}
 
-	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -493,7 +486,7 @@
 		return;
 	}
 
-	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 static void ahci_start_engine(void __iomem *port_mmio)
@@ -735,7 +728,7 @@
 
 static unsigned int ahci_dev_classify(struct ata_port *ap)
 {
-	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
 	struct ata_taskfile tf;
 	u32 tmp;
 
@@ -763,7 +756,7 @@
 
 static int ahci_clo(struct ata_port *ap)
 {
-	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
 	struct ahci_host_priv *hpriv = ap->host->private_data;
 	u32 tmp;
 
@@ -785,7 +778,7 @@
 static int ahci_softreset(struct ata_port *ap, unsigned int *class)
 {
 	struct ahci_port_priv *pp = ap->private_data;
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	const u32 cmd_fis_len = 5; /* five dwords */
 	const char *reason = NULL;
@@ -893,7 +886,7 @@
 	struct ahci_port_priv *pp = ap->private_data;
 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
 	struct ata_taskfile tf;
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	int rc;
 
@@ -921,7 +914,7 @@
 
 static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
 {
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	int rc;
 
@@ -946,7 +939,7 @@
 
 static void ahci_postreset(struct ata_port *ap, unsigned int *class)
 {
-	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
 	u32 new_tmp, tmp;
 
 	ata_std_postreset(ap, class);
@@ -965,7 +958,7 @@
 
 static u8 ahci_check_status(struct ata_port *ap)
 {
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+	void __iomem *mmio = ap->ioaddr.cmd_addr;
 
 	return readl(mmio + PORT_TFDATA) & 0xFF;
 }
@@ -1111,7 +1104,7 @@
 
 static void ahci_host_intr(struct ata_port *ap)
 {
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	struct ata_eh_info *ehi = &ap->eh_info;
 	struct ahci_port_priv *pp = ap->private_data;
@@ -1173,7 +1166,7 @@
 		 * dangerous, we need to know more about them.  Print
 		 * more of it.
 		 */
-		const u32 *f = pp->rx_fis + RX_FIS_SDB;
+		const __le32 *f = pp->rx_fis + RX_FIS_SDB;
 
 		ata_port_printk(ap, KERN_INFO, "Spurious SDB FIS during NCQ "
 				"issue=0x%x SAct=0x%x FIS=%08x:%08x%s\n",
@@ -1209,7 +1202,7 @@
 	VPRINTK("ENTER\n");
 
 	hpriv = host->private_data;
-	mmio = host->mmio_base;
+	mmio = host->iomap[AHCI_PCI_BAR];
 
 	/* sigh.  0xffffffff is a valid return from h/w */
 	irq_stat = readl(mmio + HOST_IRQ_STAT);
@@ -1254,7 +1247,7 @@
 static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
 
 	if (qc->tf.protocol == ATA_PROT_NCQ)
 		writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
@@ -1266,7 +1259,7 @@
 
 static void ahci_freeze(struct ata_port *ap)
 {
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 
 	/* turn IRQ off */
@@ -1275,7 +1268,7 @@
 
 static void ahci_thaw(struct ata_port *ap)
 {
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	u32 tmp;
 
@@ -1290,7 +1283,7 @@
 
 static void ahci_error_handler(struct ata_port *ap)
 {
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 
 	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
@@ -1306,7 +1299,7 @@
 
 static void ahci_vt8251_error_handler(struct ata_port *ap)
 {
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 
 	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
@@ -1323,7 +1316,7 @@
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 
 	if (qc->flags & ATA_QCFLAG_FAILED)
@@ -1340,7 +1333,7 @@
 {
 	struct ahci_host_priv *hpriv = ap->host->private_data;
 	struct ahci_port_priv *pp = ap->private_data;
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	const char *emsg = NULL;
 	int rc;
@@ -1361,7 +1354,7 @@
 {
 	struct ahci_port_priv *pp = ap->private_data;
 	struct ahci_host_priv *hpriv = ap->host->private_data;
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 
 	ahci_power_up(port_mmio, hpriv->cap);
@@ -1373,7 +1366,7 @@
 static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	void __iomem *mmio = host->mmio_base;
+	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	u32 ctl;
 
 	if (mesg.event == PM_EVENT_SUSPEND) {
@@ -1394,10 +1387,12 @@
 {
 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
 	struct ahci_host_priv *hpriv = host->private_data;
-	void __iomem *mmio = host->mmio_base;
+	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	int rc;
 
-	ata_pci_device_do_resume(pdev);
+	rc = ata_pci_device_do_resume(pdev);
+	if (rc)
+		return rc;
 
 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
 		rc = ahci_reset_controller(mmio, pdev);
@@ -1418,29 +1413,24 @@
 	struct device *dev = ap->host->dev;
 	struct ahci_host_priv *hpriv = ap->host->private_data;
 	struct ahci_port_priv *pp;
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	void *mem;
 	dma_addr_t mem_dma;
 	int rc;
 
-	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
 	if (!pp)
 		return -ENOMEM;
-	memset(pp, 0, sizeof(*pp));
 
 	rc = ata_pad_alloc(ap, dev);
-	if (rc) {
-		kfree(pp);
+	if (rc)
 		return rc;
-	}
 
-	mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
-	if (!mem) {
-		ata_pad_free(ap, dev);
-		kfree(pp);
+	mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
+				  GFP_KERNEL);
+	if (!mem)
 		return -ENOMEM;
-	}
 	memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
 
 	/*
@@ -1482,10 +1472,8 @@
 
 static void ahci_port_stop(struct ata_port *ap)
 {
-	struct device *dev = ap->host->dev;
 	struct ahci_host_priv *hpriv = ap->host->private_data;
-	struct ahci_port_priv *pp = ap->private_data;
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	const char *emsg = NULL;
 	int rc;
@@ -1494,19 +1482,13 @@
 	rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
 	if (rc)
 		ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
-
-	ap->private_data = NULL;
-	dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
-			  pp->cmd_slot, pp->cmd_slot_dma);
-	ata_pad_free(ap, dev);
-	kfree(pp);
 }
 
-static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
+static void ahci_setup_port(struct ata_ioports *port, void __iomem *base,
 			    unsigned int port_idx)
 {
 	VPRINTK("ENTER, base==0x%lx, port_idx %u\n", base, port_idx);
-	base = ahci_port_base_ul(base, port_idx);
+	base = ahci_port_base(base, port_idx);
 	VPRINTK("base now==0x%lx\n", base);
 
 	port->cmd_addr		= base;
@@ -1519,7 +1501,7 @@
 {
 	struct ahci_host_priv *hpriv = probe_ent->private_data;
 	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
-	void __iomem *mmio = probe_ent->mmio_base;
+	void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
 	unsigned int i, cap_n_ports, using_dac;
 	int rc;
 
@@ -1586,7 +1568,7 @@
 	}
 
 	for (i = 0; i < probe_ent->n_ports; i++)
-		ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
+		ahci_setup_port(&probe_ent->port[i], mmio, i);
 
 	ahci_init_controller(mmio, pdev, probe_ent->n_ports,
 			     probe_ent->port_flags, hpriv);
@@ -1600,7 +1582,7 @@
 {
 	struct ahci_host_priv *hpriv = probe_ent->private_data;
 	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
-	void __iomem *mmio = probe_ent->mmio_base;
+	void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
 	u32 vers, cap, impl, speed;
 	const char *speed_s;
 	u16 cc;
@@ -1619,11 +1601,11 @@
 		speed_s = "?";
 
 	pci_read_config_word(pdev, 0x0a, &cc);
-	if (cc == 0x0101)
+	if (cc == PCI_CLASS_STORAGE_IDE)
 		scc_s = "IDE";
-	else if (cc == 0x0106)
+	else if (cc == PCI_CLASS_STORAGE_SATA)
 		scc_s = "SATA";
-	else if (cc == 0x0104)
+	else if (cc == PCI_CLASS_STORAGE_RAID)
 		scc_s = "RAID";
 	else
 		scc_s = "unknown";
@@ -1667,15 +1649,13 @@
 		);
 }
 
-static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
-	struct ata_probe_ent *probe_ent = NULL;
-	struct ahci_host_priv *hpriv;
-	unsigned long base;
-	void __iomem *mmio_base;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
-	int have_msi, pci_dev_busy = 0;
+	struct device *dev = &pdev->dev;
+	struct ata_probe_ent *probe_ent;
+	struct ahci_host_priv *hpriv;
 	int rc;
 
 	VPRINTK("ENTER\n");
@@ -1685,57 +1665,36 @@
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	/* JMicron-specific fixup: make sure we're in AHCI mode */
-	/* This is protected from races with ata_jmicron by the pci probe
-	   locking */
 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON) {
-		/* AHCI enable, AHCI on function 0 */
-		pci_write_config_byte(pdev, 0x41, 0xa1);
-		/* Function 1 is the PATA controller */
+		/* Function 1 is the PATA controller except on the 368, where
+		   we are not AHCI anyway */
 		if (PCI_FUNC(pdev->devfn))
 			return -ENODEV;
 	}
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
-	rc = pci_request_regions(pdev, DRV_NAME);
-	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out;
-	}
+	rc = pcim_iomap_regions(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
+	if (rc == -EBUSY)
+		pcim_pin_device(pdev);
+	if (rc)
+		return rc;
 
-	if (pci_enable_msi(pdev) == 0)
-		have_msi = 1;
-	else {
+	if (pci_enable_msi(pdev))
 		pci_intx(pdev, 1);
-		have_msi = 0;
-	}
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
-		goto err_out_msi;
-	}
+	probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		return -ENOMEM;
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = pci_iomap(pdev, AHCI_PCI_BAR, 0);
-	if (mmio_base == NULL) {
-		rc = -ENOMEM;
-		goto err_out_free_ent;
-	}
-	base = (unsigned long) mmio_base;
-
-	hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
-	if (!hpriv) {
-		rc = -ENOMEM;
-		goto err_out_iounmap;
-	}
-	memset(hpriv, 0, sizeof(*hpriv));
+	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
+	if (!hpriv)
+		return -ENOMEM;
 
 	probe_ent->sht		= ahci_port_info[board_idx].sht;
 	probe_ent->port_flags	= ahci_port_info[board_idx].flags;
@@ -1745,16 +1704,13 @@
 
        	probe_ent->irq = pdev->irq;
        	probe_ent->irq_flags = IRQF_SHARED;
-	probe_ent->mmio_base = mmio_base;
+	probe_ent->iomap = pcim_iomap_table(pdev);
 	probe_ent->private_data = hpriv;
 
-	if (have_msi)
-		hpriv->flags |= AHCI_FLAG_MSI;
-
 	/* initialize adapter */
 	rc = ahci_host_init(probe_ent);
 	if (rc)
-		goto err_out_hpriv;
+		return rc;
 
 	if (!(probe_ent->port_flags & AHCI_FLAG_NO_NCQ) &&
 	    (hpriv->cap & HOST_CAP_NCQ))
@@ -1762,62 +1718,11 @@
 
 	ahci_print_info(probe_ent);
 
-	/* FIXME: check ata_device_add return value */
-	ata_device_add(probe_ent);
-	kfree(probe_ent);
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
 
+	devm_kfree(dev, probe_ent);
 	return 0;
-
-err_out_hpriv:
-	kfree(hpriv);
-err_out_iounmap:
-	pci_iounmap(pdev, mmio_base);
-err_out_free_ent:
-	kfree(probe_ent);
-err_out_msi:
-	if (have_msi)
-		pci_disable_msi(pdev);
-	else
-		pci_intx(pdev, 0);
-	pci_release_regions(pdev);
-err_out:
-	if (!pci_dev_busy)
-		pci_disable_device(pdev);
-	return rc;
-}
-
-static void ahci_remove_one (struct pci_dev *pdev)
-{
-	struct device *dev = pci_dev_to_dev(pdev);
-	struct ata_host *host = dev_get_drvdata(dev);
-	struct ahci_host_priv *hpriv = host->private_data;
-	unsigned int i;
-	int have_msi;
-
-	for (i = 0; i < host->n_ports; i++)
-		ata_port_detach(host->ports[i]);
-
-	have_msi = hpriv->flags & AHCI_FLAG_MSI;
-	free_irq(host->irq, host);
-
-	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-
-		ata_scsi_release(ap->scsi_host);
-		scsi_host_put(ap->scsi_host);
-	}
-
-	kfree(hpriv);
-	pci_iounmap(pdev, host->mmio_base);
-	kfree(host);
-
-	if (have_msi)
-		pci_disable_msi(pdev);
-	else
-		pci_intx(pdev, 0);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	dev_set_drvdata(dev, NULL);
 }
 
 static int __init ahci_init(void)
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 24af560..be66ea0 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -79,7 +79,7 @@
 
 	/* Bits 5 and 6 indicate if DMA is active on master/slave */
 	if (ap->ioaddr.bmdma_addr)
-		dma_enabled = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+		dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *dev = &ap->device[i];
@@ -138,7 +138,7 @@
 	.bmdma_stop	= ata_bmdma_stop,
 	.bmdma_status 	= ata_bmdma_status,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.freeze		= ata_bmdma_freeze,
 	.thaw		= ata_bmdma_thaw,
@@ -150,10 +150,10 @@
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int all_generic_ide;		/* Set to claim all devices */
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 47701b2..4d716c7 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -118,7 +118,7 @@
 	PIIX_80C_SEC		= (1 << 7) | (1 << 6),
 
 	/* controller IDs */
-	piix_pata_33		= 0,	/* PIIX3 or 4 at 33Mhz */
+	piix_pata_33		= 0,	/* PIIX4 at 33Mhz */
 	ich_pata_33		= 1,	/* ICH up to UDMA 33 only */
 	ich_pata_66		= 2,	/* ICH up to 66 Mhz */
 	ich_pata_100		= 3,	/* ICH up to UDMA 100 */
@@ -128,6 +128,7 @@
 	ich6_sata_ahci		= 7,
 	ich6m_sata_ahci		= 8,
 	ich8_sata_ahci		= 9,
+	piix_pata_mwdma		= 10,	/* PIIX3 MWDMA only */
 
 	/* constants for mapping table */
 	P0			= 0,  /* port 0 */
@@ -153,7 +154,6 @@
 
 static int piix_init_one (struct pci_dev *pdev,
 				    const struct pci_device_id *ent);
-static void piix_host_stop(struct ata_host *host);
 static void piix_pata_error_handler(struct ata_port *ap);
 static void ich_pata_error_handler(struct ata_port *ap);
 static void piix_sata_error_handler(struct ata_port *ap);
@@ -164,7 +164,8 @@
 static unsigned int in_module_init = 1;
 
 static const struct pci_device_id piix_pci_tbl[] = {
-#ifdef ATA_ENABLE_PATA
+	/* Intel PIIX3 for the 430HX etc */
+	{ 0x8086, 0x7010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_mwdma },
 	/* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */
 	/* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */
 	{ 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
@@ -202,7 +203,6 @@
 	/* ICH7/7-R (i945, i975) UDMA 100*/
 	{ 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 },
 	{ 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
-#endif
 
 	/* NOTE: The following PCI ids must be kept in sync with the
 	 * list in drivers/pci/quirks.c.
@@ -297,7 +297,7 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
@@ -306,10 +306,10 @@
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= piix_host_stop,
 };
 
 static const struct ata_port_operations ich_pata_ops = {
@@ -330,7 +330,7 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
@@ -339,10 +339,10 @@
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= piix_host_stop,
 };
 
 static const struct ata_port_operations piix_sata_ops = {
@@ -360,7 +360,7 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
@@ -369,10 +369,10 @@
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= piix_host_stop,
 };
 
 static const struct piix_map_db ich5_map_db = {
@@ -441,7 +441,7 @@
 };
 
 static struct ata_port_info piix_port_info[] = {
-	/* piix_pata_33: 0:  PIIX3 or 4 at 33MHz */
+	/* piix_pata_33: 0:  PIIX4 at 33MHz */
 	{
 		.sht		= &piix_sht,
 		.flags		= PIIX_PATA_FLAGS,
@@ -543,6 +543,14 @@
 		.port_ops	= &piix_sata_ops,
 	},
 
+	/* piix_pata_mwdma: 10:  PIIX3 MWDMA only */
+	{
+		.sht		= &piix_sht,
+		.flags		= PIIX_PATA_FLAGS,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+		.port_ops	= &piix_pata_ops,
+	},
 };
 
 static struct pci_bits piix_enable_bits[] = {
@@ -569,6 +577,7 @@
 static const struct ich_laptop ich_laptop[] = {
 	/* devid, subvendor, subdev */
 	{ 0x27DF, 0x0005, 0x0280 },	/* ICH7 on Acer 5602WLMi */
+	{ 0x27DF, 0x1025, 0x0110 },	/* ICH7 on Acer 3682WLMi */
 	/* end marker */
 	{ 0, }
 };
@@ -632,7 +641,7 @@
 
 	if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
 		return -ENOENT;
-		
+
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
@@ -776,7 +785,7 @@
 	u16 master_data;
 	u8 speed		= adev->dma_mode;
 	int devid		= adev->devno + 2 * ap->port_no;
-	u8 udma_enable;
+	u8 udma_enable		= 0;
 
 	static const	 /* ISP  RTC */
 	u8 timings[][2]	= { { 0, 0 },
@@ -786,7 +795,8 @@
 			    { 2, 3 }, };
 
 	pci_read_config_word(dev, master_port, &master_data);
-	pci_read_config_byte(dev, 0x48, &udma_enable);
+	if (ap->udma_mask)
+		pci_read_config_byte(dev, 0x48, &udma_enable);
 
 	if (speed >= XFER_UDMA_0) {
 		unsigned int udma = adev->dma_mode - XFER_UDMA_0;
@@ -1059,6 +1069,7 @@
 static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
+	struct device *dev = &pdev->dev;
 	struct ata_port_info port_info[2];
 	struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] };
 	struct piix_host_priv *hpriv;
@@ -1072,7 +1083,7 @@
 	if (!in_module_init)
 		return -ENODEV;
 
-	hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
+	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
 	if (!hpriv)
 		return -ENOMEM;
 
@@ -1122,15 +1133,6 @@
 	return ata_pci_init_one(pdev, ppinfo, 2);
 }
 
-static void piix_host_stop(struct ata_host *host)
-{
-	struct piix_host_priv *hpriv = host->private_data;
-
-	ata_host_stop(host);
-
-	kfree(hpriv);
-}
-
 static int __init piix_init(void)
 {
 	int rc;
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
new file mode 100644
index 0000000..b4e8be5
--- /dev/null
+++ b/drivers/ata/libata-acpi.c
@@ -0,0 +1,698 @@
+/*
+ * libata-acpi.c
+ * Provides ACPI support for PATA/SATA.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ * Copyright (C) 2006 Randy Dunlap
+ */
+
+#include <linux/ata.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/acpi.h>
+#include <linux/libata.h>
+#include <linux/pci.h>
+#include "libata.h"
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acnames.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acparser.h>
+#include <acpi/acexcep.h>
+#include <acpi/acmacros.h>
+#include <acpi/actypes.h>
+
+#define SATA_ROOT_PORT(x)	(((x) >> 16) & 0xffff)
+#define SATA_PORT_NUMBER(x)	((x) & 0xffff)	/* or NO_PORT_MULT */
+#define NO_PORT_MULT		0xffff
+#define SATA_ADR_RSVD		0xffffffff
+
+#define REGS_PER_GTF		7
+struct taskfile_array {
+	u8	tfa[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
+};
+
+
+/**
+ * sata_get_dev_handle - finds acpi_handle and PCI device.function
+ * @dev: device to locate
+ * @handle: returned acpi_handle for @dev
+ * @pcidevfn: return PCI device.func for @dev
+ *
+ * This function is somewhat SATA-specific.  Or at least the
+ * PATA & SATA versions of this function are different,
+ * so it's not entirely generic code.
+ *
+ * Returns 0 on success, <0 on error.
+ */
+static int sata_get_dev_handle(struct device *dev, acpi_handle *handle,
+					acpi_integer *pcidevfn)
+{
+	struct pci_dev	*pci_dev;
+	acpi_integer	addr;
+
+	pci_dev = to_pci_dev(dev);	/* NOTE: PCI-specific */
+	/* Please refer to the ACPI spec for the syntax of _ADR. */
+	addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
+	*pcidevfn = addr;
+	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
+	if (!*handle)
+		return -ENODEV;
+	return 0;
+}
+
+/**
+ * pata_get_dev_handle - finds acpi_handle and PCI device.function
+ * @dev: device to locate
+ * @handle: returned acpi_handle for @dev
+ * @pcidevfn: return PCI device.func for @dev
+ *
+ * The PATA and SATA versions of this function are different.
+ *
+ * Returns 0 on success, <0 on error.
+ */
+static int pata_get_dev_handle(struct device *dev, acpi_handle *handle,
+				acpi_integer *pcidevfn)
+{
+	unsigned int bus, devnum, func;
+	acpi_integer addr;
+	acpi_handle dev_handle, parent_handle;
+	struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER,
+					.pointer = NULL};
+	acpi_status status;
+	struct acpi_device_info	*dinfo = NULL;
+	int ret = -ENODEV;
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	bus = pdev->bus->number;
+	devnum = PCI_SLOT(pdev->devfn);
+	func = PCI_FUNC(pdev->devfn);
+
+	dev_handle = DEVICE_ACPI_HANDLE(dev);
+	parent_handle = DEVICE_ACPI_HANDLE(dev->parent);
+
+	status = acpi_get_object_info(parent_handle, &buffer);
+	if (ACPI_FAILURE(status))
+		goto err;
+
+	dinfo = buffer.pointer;
+	if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
+	    dinfo->address == bus) {
+		/* ACPI spec for _ADR for PCI bus: */
+		addr = (acpi_integer)(devnum << 16 | func);
+		*pcidevfn = addr;
+		*handle = dev_handle;
+	} else {
+		goto err;
+	}
+
+	if (!*handle)
+		goto err;
+	ret = 0;
+err:
+	kfree(dinfo);
+	return ret;
+}
+
+struct walk_info {		/* can be trimmed some */
+	struct device	*dev;
+	struct acpi_device *adev;
+	acpi_handle	handle;
+	acpi_integer	pcidevfn;
+	unsigned int	drivenum;
+	acpi_handle	obj_handle;
+	struct ata_port *ataport;
+	struct ata_device *atadev;
+	u32		sata_adr;
+	int		status;
+	char		basepath[ACPI_PATHNAME_MAX];
+	int		basepath_len;
+};
+
+static acpi_status get_devices(acpi_handle handle,
+				u32 level, void *context, void **return_value)
+{
+	acpi_status		status;
+	struct walk_info	*winfo = context;
+	struct acpi_buffer	namebuf = {ACPI_ALLOCATE_BUFFER, NULL};
+	char			*pathname;
+	struct acpi_buffer	buffer;
+	struct acpi_device_info	*dinfo;
+
+	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &namebuf);
+	if (status)
+		goto ret;
+	pathname = namebuf.pointer;
+
+	buffer.length = ACPI_ALLOCATE_BUFFER;
+	buffer.pointer = NULL;
+	status = acpi_get_object_info(handle, &buffer);
+	if (ACPI_FAILURE(status))
+		goto out2;
+
+	dinfo = buffer.pointer;
+
+	/* find full device path name for pcidevfn */
+	if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
+	    dinfo->address == winfo->pcidevfn) {
+		if (ata_msg_probe(winfo->ataport))
+			ata_dev_printk(winfo->atadev, KERN_DEBUG,
+				":%s: matches pcidevfn (0x%llx)\n",
+				pathname, winfo->pcidevfn);
+		strlcpy(winfo->basepath, pathname,
+			sizeof(winfo->basepath));
+		winfo->basepath_len = strlen(pathname);
+		goto out;
+	}
+
+	/* if basepath is not yet known, ignore this object */
+	if (!winfo->basepath_len)
+		goto out;
+
+	/* if this object is in scope of basepath, maybe use it */
+	if (strncmp(pathname, winfo->basepath,
+	    winfo->basepath_len) == 0) {
+		if (!(dinfo->valid & ACPI_VALID_ADR))
+			goto out;
+		if (ata_msg_probe(winfo->ataport))
+			ata_dev_printk(winfo->atadev, KERN_DEBUG,
+				"GOT ONE: (%s) root_port = 0x%llx,"
+				" port_num = 0x%llx\n", pathname,
+				SATA_ROOT_PORT(dinfo->address),
+				SATA_PORT_NUMBER(dinfo->address));
+		/* heuristics: */
+		if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT)
+			if (ata_msg_probe(winfo->ataport))
+				ata_dev_printk(winfo->atadev,
+					KERN_DEBUG, "warning: don't"
+					" know how to handle SATA port"
+					" multiplier\n");
+		if (SATA_ROOT_PORT(dinfo->address) ==
+			winfo->ataport->port_no &&
+		    SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) {
+			if (ata_msg_probe(winfo->ataport))
+				ata_dev_printk(winfo->atadev,
+					KERN_DEBUG,
+					"THIS ^^^^^ is the requested"
+					" SATA drive (handle = 0x%p)\n",
+					handle);
+			winfo->sata_adr = dinfo->address;
+			winfo->obj_handle = handle;
+		}
+	}
+out:
+	kfree(dinfo);
+out2:
+	kfree(pathname);
+
+ret:
+	return status;
+}
+
+/* Get the SATA drive _ADR object. */
+static int get_sata_adr(struct device *dev, acpi_handle handle,
+			acpi_integer pcidevfn, unsigned int drive,
+			struct ata_port *ap,
+			struct ata_device *atadev, u32 *dev_adr)
+{
+	acpi_status	status;
+	struct walk_info *winfo;
+	int		err = -ENOMEM;
+
+	winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL);
+	if (!winfo)
+		goto out;
+
+	winfo->dev = dev;
+	winfo->atadev = atadev;
+	winfo->ataport = ap;
+	if (acpi_bus_get_device(handle, &winfo->adev) < 0)
+		if (ata_msg_probe(ap))
+			ata_dev_printk(winfo->atadev, KERN_DEBUG,
+				"acpi_bus_get_device failed\n");
+	winfo->handle = handle;
+	winfo->pcidevfn = pcidevfn;
+	winfo->drivenum = drive;
+
+	status = acpi_get_devices(NULL, get_devices, winfo, NULL);
+	if (ACPI_FAILURE(status)) {
+		if (ata_msg_probe(ap))
+			ata_dev_printk(winfo->atadev, KERN_DEBUG,
+				"%s: acpi_get_devices failed\n",
+				__FUNCTION__);
+		err = -ENODEV;
+	} else {
+		*dev_adr = winfo->sata_adr;
+		atadev->obj_handle = winfo->obj_handle;
+		err = 0;
+	}
+	kfree(winfo);
+out:
+	return err;
+}
+
+/**
+ * do_drive_get_GTF - get the drive bootup default taskfile settings
+ * @ap: the ata_port for the drive
+ * @ix: target ata_device (drive) index
+ * @gtf_length: number of bytes of _GTF data returned at @gtf_address
+ * @gtf_address: buffer containing _GTF taskfile arrays
+ *
+ * This applies to both PATA and SATA drives.
+ *
+ * The _GTF method has no input parameters.
+ * It returns a variable number of register set values (registers
+ * hex 1F1..1F7, taskfiles).
+ * The <variable number> is not known in advance, so have ACPI-CA
+ * allocate the buffer as needed and return it, then free it later.
+ *
+ * The returned @gtf_length and @gtf_address are only valid if the
+ * function return value is 0.
+ */
+static int do_drive_get_GTF(struct ata_port *ap, int ix,
+			unsigned int *gtf_length, unsigned long *gtf_address,
+			unsigned long *obj_loc)
+{
+	acpi_status			status;
+	acpi_handle			dev_handle = NULL;
+	acpi_handle			chan_handle, drive_handle;
+	acpi_integer			pcidevfn = 0;
+	u32				dev_adr;
+	struct acpi_buffer		output;
+	union acpi_object 		*out_obj;
+	struct device			*dev = ap->host->dev;
+	struct ata_device		*atadev = &ap->device[ix];
+	int				err = -ENODEV;
+
+	*gtf_length = 0;
+	*gtf_address = 0UL;
+	*obj_loc = 0UL;
+
+	if (noacpi)
+		return 0;
+
+	if (ata_msg_probe(ap))
+		ata_dev_printk(atadev, KERN_DEBUG,
+			"%s: ENTER: ap->id: %d, port#: %d\n",
+			__FUNCTION__, ap->id, ap->port_no);
+
+	if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) {
+		if (ata_msg_probe(ap))
+			ata_dev_printk(atadev, KERN_DEBUG, "%s: ERR: "
+				"ata_dev_present: %d, PORT_DISABLED: %lu\n",
+				__FUNCTION__, ata_dev_enabled(atadev),
+				ap->flags & ATA_FLAG_DISABLED);
+		goto out;
+	}
+
+	/* Don't continue if device has no _ADR method.
+	 * _GTF is intended for known motherboard devices. */
+	if (!(ap->cbl == ATA_CBL_SATA)) {
+		err = pata_get_dev_handle(dev, &dev_handle, &pcidevfn);
+		if (err < 0) {
+			if (ata_msg_probe(ap))
+				ata_dev_printk(atadev, KERN_DEBUG,
+					"%s: pata_get_dev_handle failed (%d)\n",
+					__FUNCTION__, err);
+			goto out;
+		}
+	} else {
+		err = sata_get_dev_handle(dev, &dev_handle, &pcidevfn);
+		if (err < 0) {
+			if (ata_msg_probe(ap))
+				ata_dev_printk(atadev, KERN_DEBUG,
+					"%s: sata_get_dev_handle failed (%d\n",
+					__FUNCTION__, err);
+			goto out;
+		}
+	}
+
+	/* Get this drive's _ADR info. if not already known. */
+	if (!atadev->obj_handle) {
+		if (!(ap->cbl == ATA_CBL_SATA)) {
+			/* get child objects of dev_handle == channel objects,
+	 		 * + _their_ children == drive objects */
+			/* channel is ap->port_no */
+			chan_handle = acpi_get_child(dev_handle,
+						ap->port_no);
+			if (ata_msg_probe(ap))
+				ata_dev_printk(atadev, KERN_DEBUG,
+					"%s: chan adr=%d: chan_handle=0x%p\n",
+					__FUNCTION__, ap->port_no,
+					chan_handle);
+			if (!chan_handle) {
+				err = -ENODEV;
+				goto out;
+			}
+			/* TBD: could also check ACPI object VALID bits */
+			drive_handle = acpi_get_child(chan_handle, ix);
+			if (!drive_handle) {
+				err = -ENODEV;
+				goto out;
+			}
+			dev_adr = ix;
+			atadev->obj_handle = drive_handle;
+		} else {	/* for SATA mode */
+			dev_adr = SATA_ADR_RSVD;
+			err = get_sata_adr(dev, dev_handle, pcidevfn, 0,
+					ap, atadev, &dev_adr);
+		}
+		if (err < 0 || dev_adr == SATA_ADR_RSVD ||
+		    !atadev->obj_handle) {
+			if (ata_msg_probe(ap))
+				ata_dev_printk(atadev, KERN_DEBUG,
+					"%s: get_sata/pata_adr failed: "
+					"err=%d, dev_adr=%u, obj_handle=0x%p\n",
+					__FUNCTION__, err, dev_adr,
+					atadev->obj_handle);
+			goto out;
+		}
+	}
+
+	/* Setting up output buffer */
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */
+
+	/* _GTF has no input parameters */
+	err = -EIO;
+	status = acpi_evaluate_object(atadev->obj_handle, "_GTF",
+					NULL, &output);
+	if (ACPI_FAILURE(status)) {
+		if (ata_msg_probe(ap))
+			ata_dev_printk(atadev, KERN_DEBUG,
+				"%s: Run _GTF error: status = 0x%x\n",
+				__FUNCTION__, status);
+		goto out;
+	}
+
+	if (!output.length || !output.pointer) {
+		if (ata_msg_probe(ap))
+			ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: "
+				"length or ptr is NULL (0x%llx, 0x%p)\n",
+				__FUNCTION__,
+				(unsigned long long)output.length,
+				output.pointer);
+		kfree(output.pointer);
+		goto out;
+	}
+
+	out_obj = output.pointer;
+	if (out_obj->type != ACPI_TYPE_BUFFER) {
+		kfree(output.pointer);
+		if (ata_msg_probe(ap))
+			ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: "
+				"error: expected object type of "
+				" ACPI_TYPE_BUFFER, got 0x%x\n",
+				__FUNCTION__, out_obj->type);
+		err = -ENOENT;
+		goto out;
+	}
+
+	if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
+	    out_obj->buffer.length % REGS_PER_GTF) {
+		if (ata_msg_drv(ap))
+			ata_dev_printk(atadev, KERN_ERR,
+				"%s: unexpected GTF length (%d) or addr (0x%p)\n",
+				__FUNCTION__, out_obj->buffer.length,
+				out_obj->buffer.pointer);
+		err = -ENOENT;
+		goto out;
+	}
+
+	*gtf_length = out_obj->buffer.length;
+	*gtf_address = (unsigned long)out_obj->buffer.pointer;
+	*obj_loc = (unsigned long)out_obj;
+	if (ata_msg_probe(ap))
+		ata_dev_printk(atadev, KERN_DEBUG, "%s: returning "
+			"gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n",
+			__FUNCTION__, *gtf_length, *gtf_address, *obj_loc);
+	err = 0;
+out:
+	return err;
+}
+
+/**
+ * taskfile_load_raw - send taskfile registers to host controller
+ * @ap: Port to which output is sent
+ * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
+ *
+ * Outputs ATA taskfile to standard ATA host controller using MMIO
+ * or PIO as indicated by the ATA_FLAG_MMIO flag.
+ * Writes the control, feature, nsect, lbal, lbam, and lbah registers.
+ * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
+ * hob_lbal, hob_lbam, and hob_lbah.
+ *
+ * This function waits for idle (!BUSY and !DRQ) after writing
+ * registers.  If the control register has a new value, this
+ * function also waits for idle after writing control and before
+ * writing the remaining registers.
+ *
+ * LOCKING: TBD:
+ * Inherited from caller.
+ */
+static void taskfile_load_raw(struct ata_port *ap,
+				struct ata_device *atadev,
+				const struct taskfile_array *gtf)
+{
+	if (ata_msg_probe(ap))
+		ata_dev_printk(atadev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: "
+			"%02x %02x %02x %02x %02x %02x %02x\n",
+			__FUNCTION__,
+			gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
+			gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
+
+	if ((gtf->tfa[0] == 0) && (gtf->tfa[1] == 0) && (gtf->tfa[2] == 0)
+	    && (gtf->tfa[3] == 0) && (gtf->tfa[4] == 0) && (gtf->tfa[5] == 0)
+	    && (gtf->tfa[6] == 0))
+		return;
+
+	if (ap->ops->qc_issue) {
+		struct ata_taskfile tf;
+		unsigned int err;
+
+		ata_tf_init(atadev, &tf);
+
+		/* convert gtf to tf */
+		tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
+		tf.protocol = atadev->class == ATA_DEV_ATAPI ?
+			ATA_PROT_ATAPI_NODATA : ATA_PROT_NODATA;
+		tf.feature = gtf->tfa[0];	/* 0x1f1 */
+		tf.nsect   = gtf->tfa[1];	/* 0x1f2 */
+		tf.lbal    = gtf->tfa[2];	/* 0x1f3 */
+		tf.lbam    = gtf->tfa[3];	/* 0x1f4 */
+		tf.lbah    = gtf->tfa[4];	/* 0x1f5 */
+		tf.device  = gtf->tfa[5];	/* 0x1f6 */
+		tf.command = gtf->tfa[6];	/* 0x1f7 */
+
+		err = ata_exec_internal(atadev, &tf, NULL, DMA_NONE, NULL, 0);
+		if (err && ata_msg_probe(ap))
+			ata_dev_printk(atadev, KERN_ERR,
+				"%s: ata_exec_internal failed: %u\n",
+				__FUNCTION__, err);
+	} else
+		if (ata_msg_warn(ap))
+			ata_dev_printk(atadev, KERN_WARNING,
+				"%s: SATA driver is missing qc_issue function"
+				" entry points\n",
+				__FUNCTION__);
+}
+
+/**
+ * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
+ * @ap: the ata_port for the drive
+ * @atadev: target ata_device
+ * @gtf_length: total number of bytes of _GTF taskfiles
+ * @gtf_address: location of _GTF taskfile arrays
+ *
+ * This applies to both PATA and SATA drives.
+ *
+ * Write {gtf_address, length gtf_length} in groups of
+ * REGS_PER_GTF bytes.
+ */
+static int do_drive_set_taskfiles(struct ata_port *ap,
+		struct ata_device *atadev, unsigned int gtf_length,
+		unsigned long gtf_address)
+{
+	int			err = -ENODEV;
+	int			gtf_count = gtf_length / REGS_PER_GTF;
+	int			ix;
+	struct taskfile_array	*gtf;
+
+	if (ata_msg_probe(ap))
+		ata_dev_printk(atadev, KERN_DEBUG,
+			"%s: ENTER: ap->id: %d, port#: %d\n",
+			__FUNCTION__, ap->id, ap->port_no);
+
+	if (noacpi || !(ap->cbl == ATA_CBL_SATA))
+		return 0;
+
+	if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED))
+		goto out;
+	if (!gtf_count)		/* shouldn't be here */
+		goto out;
+
+	if (gtf_length % REGS_PER_GTF) {
+		if (ata_msg_drv(ap))
+			ata_dev_printk(atadev, KERN_ERR,
+				"%s: unexpected GTF length (%d)\n",
+				__FUNCTION__, gtf_length);
+		goto out;
+	}
+
+	for (ix = 0; ix < gtf_count; ix++) {
+		gtf = (struct taskfile_array *)
+			(gtf_address + ix * REGS_PER_GTF);
+
+		/* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
+		taskfile_load_raw(ap, atadev, gtf);
+	}
+
+	err = 0;
+out:
+	return err;
+}
+
+/**
+ * ata_acpi_exec_tfs - get then write drive taskfile settings
+ * @ap: the ata_port for the drive
+ *
+ * This applies to both PATA and SATA drives.
+ */
+int ata_acpi_exec_tfs(struct ata_port *ap)
+{
+	int		ix;
+	int		ret =0;
+	unsigned int	gtf_length;
+	unsigned long	gtf_address;
+	unsigned long	obj_loc;
+
+	if (noacpi)
+		return 0;
+
+	for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
+		if (!ata_dev_enabled(&ap->device[ix]))
+			continue;
+
+		ret = do_drive_get_GTF(ap, ix,
+				&gtf_length, &gtf_address, &obj_loc);
+		if (ret < 0) {
+			if (ata_msg_probe(ap))
+				ata_port_printk(ap, KERN_DEBUG,
+					"%s: get_GTF error (%d)\n",
+					__FUNCTION__, ret);
+			break;
+		}
+
+		ret = do_drive_set_taskfiles(ap, &ap->device[ix],
+				gtf_length, gtf_address);
+		kfree((void *)obj_loc);
+		if (ret < 0) {
+			if (ata_msg_probe(ap))
+				ata_port_printk(ap, KERN_DEBUG,
+					"%s: set_taskfiles error (%d)\n",
+					__FUNCTION__, ret);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * ata_acpi_push_id - send Identify data to drive
+ * @ap: the ata_port for the drive
+ * @ix: drive index
+ *
+ * _SDD ACPI object: for SATA mode only
+ * Must be after Identify (Packet) Device -- uses its data
+ * ATM this function never returns a failure.  It is an optional
+ * method and if it fails for whatever reason, we should still
+ * just keep going.
+ */
+int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
+{
+	acpi_handle                     handle;
+	acpi_integer                    pcidevfn;
+	int                             err;
+	struct device                   *dev = ap->host->dev;
+	struct ata_device               *atadev = &ap->device[ix];
+	u32                             dev_adr;
+	acpi_status                     status;
+	struct acpi_object_list         input;
+	union acpi_object               in_params[1];
+
+	if (noacpi)
+		return 0;
+
+	if (ata_msg_probe(ap))
+		ata_dev_printk(atadev, KERN_DEBUG,
+			"%s: ap->id: %d, ix = %d, port#: %d\n",
+			__FUNCTION__, ap->id, ix, ap->port_no);
+
+	/* Don't continue if not a SATA device. */
+	if (!(ap->cbl == ATA_CBL_SATA)) {
+		if (ata_msg_probe(ap))
+			ata_dev_printk(atadev, KERN_DEBUG,
+				"%s: Not a SATA device\n", __FUNCTION__);
+		goto out;
+	}
+
+	/* Don't continue if device has no _ADR method.
+	 * _SDD is intended for known motherboard devices. */
+	err = sata_get_dev_handle(dev, &handle, &pcidevfn);
+	if (err < 0) {
+		if (ata_msg_probe(ap))
+			ata_dev_printk(atadev, KERN_DEBUG,
+				"%s: sata_get_dev_handle failed (%d\n",
+				__FUNCTION__, err);
+		goto out;
+	}
+
+	/* Get this drive's _ADR info, if not already known */
+	if (!atadev->obj_handle) {
+		dev_adr = SATA_ADR_RSVD;
+		err = get_sata_adr(dev, handle, pcidevfn, ix, ap, atadev,
+					&dev_adr);
+		if (err < 0 || dev_adr == SATA_ADR_RSVD ||
+			!atadev->obj_handle) {
+			if (ata_msg_probe(ap))
+				ata_dev_printk(atadev, KERN_DEBUG,
+					"%s: get_sata_adr failed: "
+					"err=%d, dev_adr=%u, obj_handle=0x%p\n",
+					__FUNCTION__, err, dev_adr,
+					atadev->obj_handle);
+			goto out;
+		}
+	}
+
+	/* Give the drive Identify data to the drive via the _SDD method */
+	/* _SDD: set up input parameters */
+	input.count = 1;
+	input.pointer = in_params;
+	in_params[0].type = ACPI_TYPE_BUFFER;
+	in_params[0].buffer.length = sizeof(atadev->id[0]) * ATA_ID_WORDS;
+	in_params[0].buffer.pointer = (u8 *)atadev->id;
+	/* Output buffer: _SDD has no output */
+
+	/* It's OK for _SDD to be missing too. */
+	swap_buf_le16(atadev->id, ATA_ID_WORDS);
+	status = acpi_evaluate_object(atadev->obj_handle, "_SDD", &input, NULL);
+	swap_buf_le16(atadev->id, ATA_ID_WORDS);
+
+	err = ACPI_FAILURE(status) ? -EIO : 0;
+	if (err < 0) {
+		if (ata_msg_probe(ap))
+			ata_dev_printk(atadev, KERN_DEBUG,
+				"ata%u(%u): %s _SDD error: status = 0x%x\n",
+				ap->id, ap->device->devno,
+				__FUNCTION__, status);
+	}
+
+	/* always return success */
+out:
+	return 0;
+}
+
+
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 667acd2..e900c5e 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -59,6 +59,9 @@
 
 #include "libata.h"
 
+#define DRV_VERSION	"2.10"	/* must be exactly four chars */
+
+
 /* debounce timing parameters in msecs { interval, duration, timeout } */
 const unsigned long sata_deb_timing_normal[]		= {   5,  100, 2000 };
 const unsigned long sata_deb_timing_hotplug[]		= {  25,  500, 2000 };
@@ -90,6 +93,10 @@
 module_param(ata_probe_timeout, int, 0444);
 MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)");
 
+int noacpi;
+module_param(noacpi, int, 0444);
+MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
@@ -598,112 +605,46 @@
 }
 
 /**
- *	ata_pio_devchk - PATA device presence detection
- *	@ap: ATA channel to examine
- *	@device: Device to examine (starting at zero)
- *
- *	This technique was originally described in
- *	Hale Landis's ATADRVR (www.ata-atapi.com), and
- *	later found its way into the ATA/ATAPI spec.
- *
- *	Write a pattern to the ATA shadow registers,
- *	and if a device is present, it will respond by
- *	correctly storing and echoing back the
- *	ATA shadow register contents.
- *
- *	LOCKING:
- *	caller.
- */
-
-static unsigned int ata_pio_devchk(struct ata_port *ap,
-				   unsigned int device)
-{
-	struct ata_ioports *ioaddr = &ap->ioaddr;
-	u8 nsect, lbal;
-
-	ap->ops->dev_select(ap, device);
-
-	outb(0x55, ioaddr->nsect_addr);
-	outb(0xaa, ioaddr->lbal_addr);
-
-	outb(0xaa, ioaddr->nsect_addr);
-	outb(0x55, ioaddr->lbal_addr);
-
-	outb(0x55, ioaddr->nsect_addr);
-	outb(0xaa, ioaddr->lbal_addr);
-
-	nsect = inb(ioaddr->nsect_addr);
-	lbal = inb(ioaddr->lbal_addr);
-
-	if ((nsect == 0x55) && (lbal == 0xaa))
-		return 1;	/* we found a device */
-
-	return 0;		/* nothing found */
-}
-
-/**
- *	ata_mmio_devchk - PATA device presence detection
- *	@ap: ATA channel to examine
- *	@device: Device to examine (starting at zero)
- *
- *	This technique was originally described in
- *	Hale Landis's ATADRVR (www.ata-atapi.com), and
- *	later found its way into the ATA/ATAPI spec.
- *
- *	Write a pattern to the ATA shadow registers,
- *	and if a device is present, it will respond by
- *	correctly storing and echoing back the
- *	ATA shadow register contents.
- *
- *	LOCKING:
- *	caller.
- */
-
-static unsigned int ata_mmio_devchk(struct ata_port *ap,
-				    unsigned int device)
-{
-	struct ata_ioports *ioaddr = &ap->ioaddr;
-	u8 nsect, lbal;
-
-	ap->ops->dev_select(ap, device);
-
-	writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
-	writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
-
-	writeb(0xaa, (void __iomem *) ioaddr->nsect_addr);
-	writeb(0x55, (void __iomem *) ioaddr->lbal_addr);
-
-	writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
-	writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
-
-	nsect = readb((void __iomem *) ioaddr->nsect_addr);
-	lbal = readb((void __iomem *) ioaddr->lbal_addr);
-
-	if ((nsect == 0x55) && (lbal == 0xaa))
-		return 1;	/* we found a device */
-
-	return 0;		/* nothing found */
-}
-
-/**
  *	ata_devchk - PATA device presence detection
  *	@ap: ATA channel to examine
  *	@device: Device to examine (starting at zero)
  *
- *	Dispatch ATA device presence detection, depending
- *	on whether we are using PIO or MMIO to talk to the
- *	ATA shadow registers.
+ *	This technique was originally described in
+ *	Hale Landis's ATADRVR (www.ata-atapi.com), and
+ *	later found its way into the ATA/ATAPI spec.
+ *
+ *	Write a pattern to the ATA shadow registers,
+ *	and if a device is present, it will respond by
+ *	correctly storing and echoing back the
+ *	ATA shadow register contents.
  *
  *	LOCKING:
  *	caller.
  */
 
-static unsigned int ata_devchk(struct ata_port *ap,
-				    unsigned int device)
+static unsigned int ata_devchk(struct ata_port *ap, unsigned int device)
 {
-	if (ap->flags & ATA_FLAG_MMIO)
-		return ata_mmio_devchk(ap, device);
-	return ata_pio_devchk(ap, device);
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u8 nsect, lbal;
+
+	ap->ops->dev_select(ap, device);
+
+	iowrite8(0x55, ioaddr->nsect_addr);
+	iowrite8(0xaa, ioaddr->lbal_addr);
+
+	iowrite8(0xaa, ioaddr->nsect_addr);
+	iowrite8(0x55, ioaddr->lbal_addr);
+
+	iowrite8(0x55, ioaddr->nsect_addr);
+	iowrite8(0xaa, ioaddr->lbal_addr);
+
+	nsect = ioread8(ioaddr->nsect_addr);
+	lbal = ioread8(ioaddr->lbal_addr);
+
+	if ((nsect == 0x55) && (lbal == 0xaa))
+		return 1;	/* we found a device */
+
+	return 0;		/* nothing found */
 }
 
 /**
@@ -923,11 +864,7 @@
 	else
 		tmp = ATA_DEVICE_OBS | ATA_DEV1;
 
-	if (ap->flags & ATA_FLAG_MMIO) {
-		writeb(tmp, (void __iomem *) ap->ioaddr.device_addr);
-	} else {
-		outb(tmp, ap->ioaddr.device_addr);
-	}
+	iowrite8(tmp, ap->ioaddr.device_addr);
 	ata_pause(ap);		/* needed; also flushes, for mmio */
 }
 
@@ -1156,7 +1093,7 @@
 		ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
 }
 
-void ata_qc_complete_internal(struct ata_queued_cmd *qc)
+static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
 {
 	struct completion *waiting = qc->private_data;
 
@@ -1249,7 +1186,6 @@
 			buflen += sg[i].length;
 
 		ata_sg_init(qc, sg, n_elem);
-		qc->nsect = buflen / ATA_SECT_SIZE;
 		qc->nbytes = buflen;
 	}
 
@@ -1292,7 +1228,7 @@
 	if (ap->ops->post_internal_cmd)
 		ap->ops->post_internal_cmd(qc);
 
-	if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) {
+	if ((qc->flags & ATA_QCFLAG_FAILED) && !qc->err_mask) {
 		if (ata_msg_warn(ap))
 			ata_dev_printk(dev, KERN_WARNING,
 				"zero err_mask for failed "
@@ -1478,7 +1414,16 @@
 	}
 
 	tf.protocol = ATA_PROT_PIO;
-	tf.flags |= ATA_TFLAG_POLLING; /* for polling presence detection */
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+
+	/* Device presence detection is unreliable on some
+	 * controllers.  Always poll IDENTIFY if available.
+	 */
+	tf.flags |= ATA_TFLAG_POLLING;
 
 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
 				     id, sizeof(id[0]) * ATA_ID_WORDS);
@@ -1608,6 +1553,8 @@
 	const u16 *id = dev->id;
 	unsigned int xfer_mask;
 	char revbuf[7];		/* XYZ-99\0 */
+	char fwrevbuf[ATA_ID_FW_REV_LEN+1];
+	char modelbuf[ATA_ID_PROD_LEN+1];
 	int rc;
 
 	if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
@@ -1621,6 +1568,16 @@
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
 			       __FUNCTION__, ap->id, dev->devno);
 
+	/* set _SDD */
+	rc = ata_acpi_push_id(ap, dev->devno);
+	if (rc) {
+		ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n",
+			rc);
+	}
+
+	/* retrieve and execute the ATA task file of _GTF */
+	ata_acpi_exec_tfs(ap);
+
 	/* print device capabilities */
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG,
@@ -1662,6 +1619,16 @@
 
 		dev->n_sectors = ata_id_n_sectors(id);
 
+		/* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
+		ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
+				sizeof(fwrevbuf));
+
+		ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
+				sizeof(modelbuf));
+
+		if (dev->id[59] & 0x100)
+			dev->multi_count = dev->id[59] & 0xff;
+
 		if (ata_id_has_lba(id)) {
 			const char *lba_desc;
 			char ncq_desc[20];
@@ -1681,13 +1648,16 @@
 			ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
 
 			/* print device info to dmesg */
-			if (ata_msg_drv(ap) && print_info)
-				ata_dev_printk(dev, KERN_INFO, "%s, "
-					"max %s, %Lu sectors: %s %s\n",
-					revbuf,
-					ata_mode_string(xfer_mask),
+			if (ata_msg_drv(ap) && print_info) {
+				ata_dev_printk(dev, KERN_INFO,
+					"%s: %s, %s, max %s\n",
+					revbuf, modelbuf, fwrevbuf,
+					ata_mode_string(xfer_mask));
+				ata_dev_printk(dev, KERN_INFO,
+					"%Lu sectors, multi %u: %s %s\n",
 					(unsigned long long)dev->n_sectors,
-					lba_desc, ncq_desc);
+					dev->multi_count, lba_desc, ncq_desc);
+			}
 		} else {
 			/* CHS */
 
@@ -1704,22 +1674,17 @@
 			}
 
 			/* print device info to dmesg */
-			if (ata_msg_drv(ap) && print_info)
-				ata_dev_printk(dev, KERN_INFO, "%s, "
-					"max %s, %Lu sectors: CHS %u/%u/%u\n",
-					revbuf,
-					ata_mode_string(xfer_mask),
-					(unsigned long long)dev->n_sectors,
-					dev->cylinders, dev->heads,
-					dev->sectors);
-		}
-
-		if (dev->id[59] & 0x100) {
-			dev->multi_count = dev->id[59] & 0xff;
-			if (ata_msg_drv(ap) && print_info)
+			if (ata_msg_drv(ap) && print_info) {
 				ata_dev_printk(dev, KERN_INFO,
-					"ata%u: dev %u multi count %u\n",
-					ap->id, dev->devno, dev->multi_count);
+					"%s: %s, %s, max %s\n",
+					revbuf,	modelbuf, fwrevbuf,
+					ata_mode_string(xfer_mask));
+				ata_dev_printk(dev, KERN_INFO, 
+					"%Lu sectors, multi %u, CHS %u/%u/%u\n",
+					(unsigned long long)dev->n_sectors,
+					dev->multi_count, dev->cylinders,
+					dev->heads, dev->sectors);
+			}
 		}
 
 		dev->cdb_len = 16;
@@ -2391,6 +2356,10 @@
 		dev->flags |= ATA_DFLAG_PIO;
 
 	err_mask = ata_dev_set_xfermode(dev);
+	/* Old CFA may refuse this command, which is just fine */
+	if (dev->xfer_shift == ATA_SHIFT_PIO && ata_id_is_cfa(dev->id))
+        	err_mask &= ~AC_ERR_DEV;
+
 	if (err_mask) {
 		ata_dev_printk(dev, KERN_ERR, "failed to set xfermode "
 			       "(err_mask=0x%x)\n", err_mask);
@@ -2493,7 +2462,7 @@
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		dev = &ap->device[i];
 
-		/* don't udpate suspended devices' xfer mode */
+		/* don't update suspended devices' xfer mode */
 		if (!ata_dev_ready(dev))
 			continue;
 
@@ -2614,13 +2583,8 @@
 		u8 nsect, lbal;
 
 		ap->ops->dev_select(ap, 1);
-		if (ap->flags & ATA_FLAG_MMIO) {
-			nsect = readb((void __iomem *) ioaddr->nsect_addr);
-			lbal = readb((void __iomem *) ioaddr->lbal_addr);
-		} else {
-			nsect = inb(ioaddr->nsect_addr);
-			lbal = inb(ioaddr->lbal_addr);
-		}
+		nsect = ioread8(ioaddr->nsect_addr);
+		lbal = ioread8(ioaddr->lbal_addr);
 		if ((nsect == 1) && (lbal == 1))
 			break;
 		if (time_after(jiffies, timeout)) {
@@ -2648,19 +2612,11 @@
 	DPRINTK("ata%u: bus reset via SRST\n", ap->id);
 
 	/* software reset.  causes dev0 to be selected */
-	if (ap->flags & ATA_FLAG_MMIO) {
-		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
-		udelay(20);	/* FIXME: flush */
-		writeb(ap->ctl | ATA_SRST, (void __iomem *) ioaddr->ctl_addr);
-		udelay(20);	/* FIXME: flush */
-		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
-	} else {
-		outb(ap->ctl, ioaddr->ctl_addr);
-		udelay(10);
-		outb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
-		udelay(10);
-		outb(ap->ctl, ioaddr->ctl_addr);
-	}
+	iowrite8(ap->ctl, ioaddr->ctl_addr);
+	udelay(20);	/* FIXME: flush */
+	iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+	udelay(20);	/* FIXME: flush */
+	iowrite8(ap->ctl, ioaddr->ctl_addr);
 
 	/* spec mandates ">= 2ms" before checking status.
 	 * We wait 150ms, because that was the magic delay used for
@@ -2745,8 +2701,7 @@
 		ap->device[1].class = ata_dev_try_classify(ap, 1, &err);
 
 	/* re-enable interrupts */
-	if (ap->ioaddr.ctl_addr)	/* FIXME: hack. create a hook instead */
-		ata_irq_on(ap);
+	ap->ops->irq_on(ap);
 
 	/* is double-select really necessary? */
 	if (ap->device[1].class != ATA_DEV_NONE)
@@ -2761,10 +2716,7 @@
 
 	if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
 		/* set up device control for ATA_FLAG_SATA_RESET */
-		if (ap->flags & ATA_FLAG_MMIO)
-			writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
-		else
-			outb(ap->ctl, ioaddr->ctl_addr);
+		iowrite8(ap->ctl, ioaddr->ctl_addr);
 	}
 
 	DPRINTK("EXIT\n");
@@ -3098,6 +3050,9 @@
 		return 0;
 	}
 
+	/* wait a while before checking status, see SRST for more info */
+	msleep(150);
+
 	if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
 		ata_port_printk(ap, KERN_ERR,
 				"COMRESET failed (device not ready)\n");
@@ -3138,11 +3093,8 @@
 		sata_scr_write(ap, SCR_ERROR, serror);
 
 	/* re-enable interrupts */
-	if (!ap->ops->error_handler) {
-		/* FIXME: hack. create a hook instead */
-		if (ap->ioaddr.ctl_addr)
-			ata_irq_on(ap);
-	}
+	if (!ap->ops->error_handler)
+		ap->ops->irq_on(ap);
 
 	/* is double-select really necessary? */
 	if (classes[0] != ATA_DEV_NONE)
@@ -3157,12 +3109,8 @@
 	}
 
 	/* set up device control */
-	if (ap->ioaddr.ctl_addr) {
-		if (ap->flags & ATA_FLAG_MMIO)
-			writeb(ap->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
-		else
-			outb(ap->ctl, ap->ioaddr.ctl_addr);
-	}
+	if (ap->ioaddr.ctl_addr)
+		iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
 
 	DPRINTK("EXIT\n");
 }
@@ -3187,7 +3135,8 @@
 			       const u16 *new_id)
 {
 	const u16 *old_id = dev->id;
-	unsigned char model[2][41], serial[2][21];
+	unsigned char model[2][ATA_ID_PROD_LEN + 1];
+	unsigned char serial[2][ATA_ID_SERNO_LEN + 1];
 	u64 new_n_sectors;
 
 	if (dev->class != new_class) {
@@ -3196,10 +3145,10 @@
 		return 0;
 	}
 
-	ata_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0]));
-	ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1]));
-	ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0]));
-	ata_id_c_string(new_id, serial[1], ATA_ID_SERNO_OFS, sizeof(serial[1]));
+	ata_id_c_string(old_id, model[0], ATA_ID_PROD, sizeof(model[0]));
+	ata_id_c_string(new_id, model[1], ATA_ID_PROD, sizeof(model[1]));
+	ata_id_c_string(old_id, serial[0], ATA_ID_SERNO, sizeof(serial[0]));
+	ata_id_c_string(new_id, serial[1], ATA_ID_SERNO, sizeof(serial[1]));
 	new_n_sectors = ata_id_n_sectors(new_id);
 
 	if (strcmp(model[0], model[1])) {
@@ -3324,37 +3273,20 @@
 	{ }
 };
 
-static int ata_strim(char *s, size_t len)
-{
-	len = strnlen(s, len);
-
-	/* ATAPI specifies that empty space is blank-filled; remove blanks */
-	while ((len > 0) && (s[len - 1] == ' ')) {
-		len--;
-		s[len] = 0;
-	}
-	return len;
-}
-
 unsigned long ata_device_blacklisted(const struct ata_device *dev)
 {
-	unsigned char model_num[40];
-	unsigned char model_rev[16];
-	unsigned int nlen, rlen;
+	unsigned char model_num[ATA_ID_PROD_LEN + 1];
+	unsigned char model_rev[ATA_ID_FW_REV_LEN + 1];
 	const struct ata_blacklist_entry *ad = ata_device_blacklist;
 
-	ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
-			  sizeof(model_num));
-	ata_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS,
-			  sizeof(model_rev));
-	nlen = ata_strim(model_num, sizeof(model_num));
-	rlen = ata_strim(model_rev, sizeof(model_rev));
+	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
+	ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev));
 
 	while (ad->model_num) {
-		if (!strncmp(ad->model_num, model_num, nlen)) {
+		if (!strcmp(ad->model_num, model_num)) {
 			if (ad->model_rev == NULL)
 				return ad->horkage;
-			if (!strncmp(ad->model_rev, model_rev, rlen))
+			if (!strcmp(ad->model_rev, model_rev))
 				return ad->horkage;
 		}
 		ad++;
@@ -3894,53 +3826,7 @@
 }
 
 /**
- *	ata_mmio_data_xfer - Transfer data by MMIO
- *	@adev: device for this I/O
- *	@buf: data buffer
- *	@buflen: buffer length
- *	@write_data: read/write
- *
- *	Transfer data from/to the device data register by MMIO.
- *
- *	LOCKING:
- *	Inherited from caller.
- */
-
-void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
-			unsigned int buflen, int write_data)
-{
-	struct ata_port *ap = adev->ap;
-	unsigned int i;
-	unsigned int words = buflen >> 1;
-	u16 *buf16 = (u16 *) buf;
-	void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
-
-	/* Transfer multiple of 2 bytes */
-	if (write_data) {
-		for (i = 0; i < words; i++)
-			writew(le16_to_cpu(buf16[i]), mmio);
-	} else {
-		for (i = 0; i < words; i++)
-			buf16[i] = cpu_to_le16(readw(mmio));
-	}
-
-	/* Transfer trailing 1 byte, if any. */
-	if (unlikely(buflen & 0x01)) {
-		u16 align_buf[1] = { 0 };
-		unsigned char *trailing_buf = buf + buflen - 1;
-
-		if (write_data) {
-			memcpy(align_buf, trailing_buf, 1);
-			writew(le16_to_cpu(align_buf[0]), mmio);
-		} else {
-			align_buf[0] = cpu_to_le16(readw(mmio));
-			memcpy(trailing_buf, align_buf, 1);
-		}
-	}
-}
-
-/**
- *	ata_pio_data_xfer - Transfer data by PIO
+ *	ata_data_xfer - Transfer data by PIO
  *	@adev: device to target
  *	@buf: data buffer
  *	@buflen: buffer length
@@ -3951,18 +3837,17 @@
  *	LOCKING:
  *	Inherited from caller.
  */
-
-void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf,
-		       unsigned int buflen, int write_data)
+void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
+		   unsigned int buflen, int write_data)
 {
 	struct ata_port *ap = adev->ap;
 	unsigned int words = buflen >> 1;
 
 	/* Transfer multiple of 2 bytes */
 	if (write_data)
-		outsw(ap->ioaddr.data_addr, buf, words);
+		iowrite16_rep(ap->ioaddr.data_addr, buf, words);
 	else
-		insw(ap->ioaddr.data_addr, buf, words);
+		ioread16_rep(ap->ioaddr.data_addr, buf, words);
 
 	/* Transfer trailing 1 byte, if any. */
 	if (unlikely(buflen & 0x01)) {
@@ -3971,16 +3856,16 @@
 
 		if (write_data) {
 			memcpy(align_buf, trailing_buf, 1);
-			outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+			iowrite16(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
 		} else {
-			align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
+			align_buf[0] = cpu_to_le16(ioread16(ap->ioaddr.data_addr));
 			memcpy(trailing_buf, align_buf, 1);
 		}
 	}
 }
 
 /**
- *	ata_pio_data_xfer_noirq - Transfer data by PIO
+ *	ata_data_xfer_noirq - Transfer data by PIO
  *	@adev: device to target
  *	@buf: data buffer
  *	@buflen: buffer length
@@ -3992,13 +3877,12 @@
  *	LOCKING:
  *	Inherited from caller.
  */
-
-void ata_pio_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
-				    unsigned int buflen, int write_data)
+void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
+			 unsigned int buflen, int write_data)
 {
 	unsigned long flags;
 	local_irq_save(flags);
-	ata_pio_data_xfer(adev, buf, buflen, write_data);
+	ata_data_xfer(adev, buf, buflen, write_data);
 	local_irq_restore(flags);
 }
 
@@ -4022,11 +3906,11 @@
 	unsigned int offset;
 	unsigned char *buf;
 
-	if (qc->cursect == (qc->nsect - 1))
+	if (qc->curbytes == qc->nbytes - ATA_SECT_SIZE)
 		ap->hsm_task_state = HSM_ST_LAST;
 
 	page = sg[qc->cursg].page;
-	offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE;
+	offset = sg[qc->cursg].offset + qc->cursg_ofs;
 
 	/* get the current page and offset */
 	page = nth_page(page, (offset >> PAGE_SHIFT));
@@ -4051,10 +3935,10 @@
 		ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write);
 	}
 
-	qc->cursect++;
-	qc->cursg_ofs++;
+	qc->curbytes += ATA_SECT_SIZE;
+	qc->cursg_ofs += ATA_SECT_SIZE;
 
-	if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) {
+	if (qc->cursg_ofs == (&sg[qc->cursg])->length) {
 		qc->cursg++;
 		qc->cursg_ofs = 0;
 	}
@@ -4079,7 +3963,8 @@
 
 		WARN_ON(qc->dev->multi_count == 0);
 
-		nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
+		nsect = min((qc->nbytes - qc->curbytes) / ATA_SECT_SIZE,
+			    qc->dev->multi_count);
 		while (nsect--)
 			ata_pio_sector(qc);
 	} else
@@ -4320,7 +4205,7 @@
 			qc = ata_qc_from_tag(ap, qc->tag);
 			if (qc) {
 				if (likely(!(qc->err_mask & AC_ERR_HSM))) {
-					ata_irq_on(ap);
+					ap->ops->irq_on(ap);
 					ata_qc_complete(qc);
 				} else
 					ata_port_freeze(ap);
@@ -4336,7 +4221,7 @@
 	} else {
 		if (in_wq) {
 			spin_lock_irqsave(ap->lock, flags);
-			ata_irq_on(ap);
+			ap->ops->irq_on(ap);
 			ata_qc_complete(qc);
 			spin_unlock_irqrestore(ap->lock, flags);
 		} else
@@ -5161,7 +5046,7 @@
 
 #ifdef ATA_IRQ_TRAP
 	if ((ap->stats.idle_irq % 1000) == 0) {
-		ata_irq_ack(ap, 0); /* debug trap */
+		ap->ops->irq_ack(ap, 0); /* debug trap */
 		ata_port_printk(ap, KERN_WARNING, "irq trap\n");
 		return 1;
 	}
@@ -5502,54 +5387,25 @@
  *	LOCKING:
  *	Inherited from caller.
  */
-
-int ata_port_start (struct ata_port *ap)
+int ata_port_start(struct ata_port *ap)
 {
 	struct device *dev = ap->dev;
 	int rc;
 
-	ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL);
+	ap->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma,
+				      GFP_KERNEL);
 	if (!ap->prd)
 		return -ENOMEM;
 
 	rc = ata_pad_alloc(ap, dev);
-	if (rc) {
-		dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
+	if (rc)
 		return rc;
-	}
 
-	DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma);
-
+	DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd,
+		(unsigned long long)ap->prd_dma);
 	return 0;
 }
 
-
-/**
- *	ata_port_stop - Undo ata_port_start()
- *	@ap: Port to shut down
- *
- *	Frees the PRD table.
- *
- *	May be used as the port_stop() entry in ata_port_operations.
- *
- *	LOCKING:
- *	Inherited from caller.
- */
-
-void ata_port_stop (struct ata_port *ap)
-{
-	struct device *dev = ap->dev;
-
-	dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
-	ata_pad_free(ap, dev);
-}
-
-void ata_host_stop (struct ata_host *host)
-{
-	if (host->mmio_base)
-		iounmap(host->mmio_base);
-}
-
 /**
  *	ata_dev_init - Initialize an ata_device structure
  *	@dev: Device structure to initialize
@@ -5723,6 +5579,27 @@
 	return ap;
 }
 
+static void ata_host_release(struct device *gendev, void *res)
+{
+	struct ata_host *host = dev_get_drvdata(gendev);
+	int i;
+
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		if (!ap)
+			continue;
+
+		if (ap->ops->port_stop)
+			ap->ops->port_stop(ap);
+
+		scsi_host_put(ap->scsi_host);
+	}
+
+	if (host->ops->host_stop)
+		host->ops->host_stop(host);
+}
+
 /**
  *	ata_sas_host_init - Initialize a host struct
  *	@host:	host to initialize
@@ -5770,22 +5647,28 @@
 	int rc;
 
 	DPRINTK("ENTER\n");
-	
+
 	if (ent->irq == 0) {
 		dev_printk(KERN_ERR, dev, "is not available: No interrupt assigned.\n");
 		return 0;
 	}
-	/* alloc a container for our list of ATA ports (buses) */
-	host = kzalloc(sizeof(struct ata_host) +
-		       (ent->n_ports * sizeof(void *)), GFP_KERNEL);
-	if (!host)
+
+	if (!devres_open_group(dev, ata_device_add, GFP_KERNEL))
 		return 0;
 
+	/* alloc a container for our list of ATA ports (buses) */
+	host = devres_alloc(ata_host_release, sizeof(struct ata_host) +
+			    (ent->n_ports * sizeof(void *)), GFP_KERNEL);
+	if (!host)
+		goto err_out;
+	devres_add(dev, host);
+	dev_set_drvdata(dev, host);
+
 	ata_host_init(host, dev, ent->_host_flags, ent->port_ops);
 	host->n_ports = ent->n_ports;
 	host->irq = ent->irq;
 	host->irq2 = ent->irq2;
-	host->mmio_base = ent->mmio_base;
+	host->iomap = ent->iomap;
 	host->private_data = ent->private_data;
 
 	/* register each port bound to this device */
@@ -5823,8 +5706,8 @@
 				(ap->pio_mask << ATA_SHIFT_PIO);
 
 		/* print per-port info to dmesg */
-		ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX "
-				"ctl 0x%lX bmdma 0x%lX irq %d\n",
+		ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%p "
+				"ctl 0x%p bmdma 0x%p irq %d\n",
 				ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
 				ata_mode_string(xfer_mode_mask),
 				ap->ioaddr.cmd_addr,
@@ -5837,8 +5720,8 @@
 	}
 
 	/* obtain irq, that may be shared between channels */
-	rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
-			 DRV_NAME, host);
+	rc = devm_request_irq(dev, ent->irq, ent->port_ops->irq_handler,
+			      ent->irq_flags, DRV_NAME, host);
 	if (rc) {
 		dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
 			   ent->irq, rc);
@@ -5851,15 +5734,19 @@
 		   so trap it now */
 		BUG_ON(ent->irq == ent->irq2);
 
-		rc = request_irq(ent->irq2, ent->port_ops->irq_handler, ent->irq_flags,
-			 DRV_NAME, host);
+		rc = devm_request_irq(dev, ent->irq2,
+				ent->port_ops->irq_handler, ent->irq_flags,
+				DRV_NAME, host);
 		if (rc) {
 			dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
 				   ent->irq2, rc);
-			goto err_out_free_irq;
+			goto err_out;
 		}
 	}
 
+	/* resource acquisition complete */
+	devres_remove_group(dev, ata_device_add);
+
 	/* perform each probe synchronously */
 	DPRINTK("probe begin\n");
 	for (i = 0; i < host->n_ports; i++) {
@@ -5928,24 +5815,13 @@
 		ata_scsi_scan_host(ap);
 	}
 
-	dev_set_drvdata(dev, host);
-
 	VPRINTK("EXIT, returning %u\n", ent->n_ports);
 	return ent->n_ports; /* success */
 
-err_out_free_irq:
-	free_irq(ent->irq, host);
-err_out:
-	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-		if (ap) {
-			ap->ops->port_stop(ap);
-			scsi_host_put(ap->scsi_host);
-		}
-	}
-
-	kfree(host);
-	VPRINTK("EXIT, returning 0\n");
+ err_out:
+	devres_release_group(dev, ata_device_add);
+	dev_set_drvdata(dev, NULL);
+	VPRINTK("EXIT, returning %d\n", rc);
 	return 0;
 }
 
@@ -6008,76 +5884,20 @@
 }
 
 /**
- *	ata_host_remove - PCI layer callback for device removal
- *	@host: ATA host set that was removed
+ *	ata_host_detach - Detach all ports of an ATA host
+ *	@host: Host to detach
  *
- *	Unregister all objects associated with this host set. Free those
- *	objects.
+ *	Detach all ports of @host.
  *
  *	LOCKING:
- *	Inherited from calling layer (may sleep).
+ *	Kernel thread context (may sleep).
  */
-
-void ata_host_remove(struct ata_host *host)
+void ata_host_detach(struct ata_host *host)
 {
-	unsigned int i;
+	int i;
 
 	for (i = 0; i < host->n_ports; i++)
 		ata_port_detach(host->ports[i]);
-
-	free_irq(host->irq, host);
-	if (host->irq2)
-		free_irq(host->irq2, host);
-
-	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-
-		ata_scsi_release(ap->scsi_host);
-
-		if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
-			struct ata_ioports *ioaddr = &ap->ioaddr;
-
-			/* FIXME: Add -ac IDE pci mods to remove these special cases */
-			if (ioaddr->cmd_addr == ATA_PRIMARY_CMD)
-				release_region(ATA_PRIMARY_CMD, 8);
-			else if (ioaddr->cmd_addr == ATA_SECONDARY_CMD)
-				release_region(ATA_SECONDARY_CMD, 8);
-		}
-
-		scsi_host_put(ap->scsi_host);
-	}
-
-	if (host->ops->host_stop)
-		host->ops->host_stop(host);
-
-	kfree(host);
-}
-
-/**
- *	ata_scsi_release - SCSI layer callback hook for host unload
- *	@shost: libata host to be unloaded
- *
- *	Performs all duties necessary to shut down a libata port...
- *	Kill port kthread, disable port, and release resources.
- *
- *	LOCKING:
- *	Inherited from SCSI layer.
- *
- *	RETURNS:
- *	One.
- */
-
-int ata_scsi_release(struct Scsi_Host *shost)
-{
-	struct ata_port *ap = ata_shost_to_port(shost);
-
-	DPRINTK("ENTER\n");
-
-	ap->ops->port_disable(ap);
-	ap->ops->port_stop(ap);
-
-	DPRINTK("EXIT\n");
-	return 1;
 }
 
 struct ata_probe_ent *
@@ -6085,7 +5905,11 @@
 {
 	struct ata_probe_ent *probe_ent;
 
-	probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
+	/* XXX - the following if can go away once all LLDs are managed */
+	if (!list_empty(&dev->devres_head))
+		probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
+	else
+		probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
 	if (!probe_ent) {
 		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
 		       kobject_name(&(dev->kobj)));
@@ -6135,37 +5959,23 @@
 
 #ifdef CONFIG_PCI
 
-void ata_pci_host_stop (struct ata_host *host)
-{
-	struct pci_dev *pdev = to_pci_dev(host->dev);
-
-	pci_iounmap(pdev, host->mmio_base);
-}
-
 /**
  *	ata_pci_remove_one - PCI layer callback for device removal
  *	@pdev: PCI device that was removed
  *
- *	PCI layer indicates to libata via this hook that
- *	hot-unplug or module unload event has occurred.
- *	Handle this by unregistering all objects associated
- *	with this PCI device.  Free those objects.  Then finally
- *	release PCI resources and disable device.
+ *	PCI layer indicates to libata via this hook that hot-unplug or
+ *	module unload event has occurred.  Detach all ports.  Resource
+ *	release is handled via devres.
  *
  *	LOCKING:
  *	Inherited from PCI layer (may sleep).
  */
-
-void ata_pci_remove_one (struct pci_dev *pdev)
+void ata_pci_remove_one(struct pci_dev *pdev)
 {
 	struct device *dev = pci_dev_to_dev(pdev);
 	struct ata_host *host = dev_get_drvdata(dev);
 
-	ata_host_remove(host);
-
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	dev_set_drvdata(dev, NULL);
+	ata_host_detach(host);
 }
 
 /* move to PCI subsystem */
@@ -6212,12 +6022,22 @@
 	}
 }
 
-void ata_pci_device_do_resume(struct pci_dev *pdev)
+int ata_pci_device_do_resume(struct pci_dev *pdev)
 {
+	int rc;
+
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
-	pci_enable_device(pdev);
+
+	rc = pcim_enable_device(pdev);
+	if (rc) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "failed to enable device after resume (%d)\n", rc);
+		return rc;
+	}
+
 	pci_set_master(pdev);
+	return 0;
 }
 
 int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
@@ -6237,10 +6057,12 @@
 int ata_pci_device_resume(struct pci_dev *pdev)
 {
 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	int rc;
 
-	ata_pci_device_do_resume(pdev);
-	ata_host_resume(host);
-	return 0;
+	rc = ata_pci_device_do_resume(pdev);
+	if (rc == 0)
+		ata_host_resume(host);
+	return rc;
 }
 #endif /* CONFIG_PCI */
 
@@ -6386,8 +6208,7 @@
 EXPORT_SYMBOL_GPL(ata_std_ports);
 EXPORT_SYMBOL_GPL(ata_host_init);
 EXPORT_SYMBOL_GPL(ata_device_add);
-EXPORT_SYMBOL_GPL(ata_port_detach);
-EXPORT_SYMBOL_GPL(ata_host_remove);
+EXPORT_SYMBOL_GPL(ata_host_detach);
 EXPORT_SYMBOL_GPL(ata_sg_init);
 EXPORT_SYMBOL_GPL(ata_sg_init_one);
 EXPORT_SYMBOL_GPL(ata_hsm_move);
@@ -6404,12 +6225,9 @@
 EXPORT_SYMBOL_GPL(ata_altstatus);
 EXPORT_SYMBOL_GPL(ata_exec_command);
 EXPORT_SYMBOL_GPL(ata_port_start);
-EXPORT_SYMBOL_GPL(ata_port_stop);
-EXPORT_SYMBOL_GPL(ata_host_stop);
 EXPORT_SYMBOL_GPL(ata_interrupt);
-EXPORT_SYMBOL_GPL(ata_mmio_data_xfer);
-EXPORT_SYMBOL_GPL(ata_pio_data_xfer);
-EXPORT_SYMBOL_GPL(ata_pio_data_xfer_noirq);
+EXPORT_SYMBOL_GPL(ata_data_xfer);
+EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
 EXPORT_SYMBOL_GPL(ata_qc_prep);
 EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
 EXPORT_SYMBOL_GPL(ata_bmdma_setup);
@@ -6446,7 +6264,6 @@
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
 EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
-EXPORT_SYMBOL_GPL(ata_scsi_release);
 EXPORT_SYMBOL_GPL(ata_host_intr);
 EXPORT_SYMBOL_GPL(sata_scr_valid);
 EXPORT_SYMBOL_GPL(sata_scr_read);
@@ -6467,7 +6284,6 @@
 
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL_GPL(pci_test_config_bits);
-EXPORT_SYMBOL_GPL(ata_pci_host_stop);
 EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
@@ -6491,3 +6307,7 @@
 EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
 EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
 EXPORT_SYMBOL_GPL(ata_do_eh);
+EXPORT_SYMBOL_GPL(ata_irq_on);
+EXPORT_SYMBOL_GPL(ata_dummy_irq_on);
+EXPORT_SYMBOL_GPL(ata_irq_ack);
+EXPORT_SYMBOL_GPL(ata_dummy_irq_ack);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7484358..52c85af 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1443,15 +1443,10 @@
 		};
 		struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
 		struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf;
-		unsigned int nbytes;
 
 		if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask)
 			continue;
 
-		nbytes = qc->nbytes;
-		if (!nbytes)
-			nbytes = qc->nsect << 9;
-
 		ata_dev_printk(qc->dev, KERN_ERR,
 			"cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
 			"tag %d cdb 0x%x data %u %s\n         "
@@ -1461,7 +1456,7 @@
 			cmd->lbal, cmd->lbam, cmd->lbah,
 			cmd->hob_feature, cmd->hob_nsect,
 			cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah,
-			cmd->device, qc->tag, qc->cdb[0], nbytes,
+			cmd->device, qc->tag, qc->cdb[0], qc->nbytes,
 			dma_str[qc->dma_dir],
 			res->command, res->feature, res->nsect,
 			res->lbal, res->lbam, res->lbah,
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 73902d3..0009818 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -149,6 +149,45 @@
 }
 
 /**
+ *	ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
+ *	@sdev: SCSI device to get identify data for
+ *	@arg: User buffer area for identify data
+ *
+ *	LOCKING:
+ *	Defined by the SCSI layer.  We don't really care.
+ *
+ *	RETURNS:
+ *	Zero on success, negative errno on error.
+ */
+static int ata_get_identity(struct scsi_device *sdev, void __user *arg)
+{
+	struct ata_port *ap = ata_shost_to_port(sdev->host);
+	struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
+	u16 __user *dst = arg;
+	char buf[40];
+
+	if (!dev)
+		return -ENOMSG;
+
+	if (copy_to_user(dst, dev->id, ATA_ID_WORDS * sizeof(u16)))
+		return -EFAULT;
+
+	ata_id_string(dev->id, buf, ATA_ID_PROD, ATA_ID_PROD_LEN);
+	if (copy_to_user(dst + ATA_ID_PROD, buf, ATA_ID_PROD_LEN))
+		return -EFAULT;
+
+	ata_id_string(dev->id, buf, ATA_ID_FW_REV, ATA_ID_FW_REV_LEN);
+	if (copy_to_user(dst + ATA_ID_FW_REV, buf, ATA_ID_FW_REV_LEN))
+		return -EFAULT;
+
+	ata_id_string(dev->id, buf, ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+	if (copy_to_user(dst + ATA_ID_SERNO, buf, ATA_ID_SERNO_LEN))
+		return -EFAULT;
+
+	return 0;
+}
+
+/**
  *	ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl
  *	@scsidev: Device to which we are issuing command
  *	@arg: User provided data for issuing command
@@ -159,7 +198,6 @@
  *	RETURNS:
  *	Zero on success, negative errno on error.
  */
-
 int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
 {
 	int rc = 0;
@@ -359,6 +397,9 @@
 			return -EINVAL;
 		return 0;
 
+	case HDIO_GET_IDENTITY:
+		return ata_get_identity(scsidev, arg);
+
 	case HDIO_DRIVE_CMD:
 		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
 			return -EACCES;
@@ -397,9 +438,9 @@
  *	RETURNS:
  *	Command allocated, or %NULL if none available.
  */
-struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
-				       struct scsi_cmnd *cmd,
-				       void (*done)(struct scsi_cmnd *))
+static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
+					      struct scsi_cmnd *cmd,
+					      void (*done)(struct scsi_cmnd *))
 {
 	struct ata_queued_cmd *qc;
 
@@ -435,7 +476,7 @@
  *	LOCKING:
  *	inherited from caller
  */
-void ata_dump_status(unsigned id, struct ata_taskfile *tf)
+static void ata_dump_status(unsigned id, struct ata_taskfile *tf)
 {
 	u8 stat = tf->command, err = tf->feature;
 
@@ -610,8 +651,8 @@
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  */
-void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
-			u8 *ascq, int verbose)
+static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
+			       u8 *asc, u8 *ascq, int verbose)
 {
 	int i;
 
@@ -1359,7 +1400,7 @@
 		goto nothing_to_do;
 
 	qc->flags |= ATA_QCFLAG_IO;
-	qc->nsect = n_block;
+	qc->nbytes = n_block * ATA_SECT_SIZE;
 
 	rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags,
 			     qc->tag);
@@ -1698,8 +1739,8 @@
 
 	if (buflen > 35) {
 		memcpy(&rbuf[8], "ATA     ", 8);
-		ata_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16);
-		ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
+		ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
+		ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
 		if (rbuf[32] == 0 || rbuf[32] == ' ')
 			memcpy(&rbuf[32], "n/a ", 4);
 	}
@@ -1768,13 +1809,13 @@
 		0,
 		0x80,			/* this page code */
 		0,
-		ATA_SERNO_LEN,		/* page len */
+		ATA_ID_SERNO_LEN,	/* page len */
 	};
 	memcpy(rbuf, hdr, sizeof(hdr));
 
-	if (buflen > (ATA_SERNO_LEN + 4 - 1))
+	if (buflen > (ATA_ID_SERNO_LEN + 4 - 1))
 		ata_id_string(args->id, (unsigned char *) &rbuf[4],
-			      ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
+			      ATA_ID_SERNO, ATA_ID_SERNO_LEN);
 
 	return 0;
 }
@@ -1799,19 +1840,18 @@
 {
 	int num;
 	const int sat_model_serial_desc_len = 68;
-	const int ata_model_byte_len = 40;
 
 	rbuf[1] = 0x83;			/* this page code */
 	num = 4;
 
-	if (buflen > (ATA_SERNO_LEN + num + 3)) {
+	if (buflen > (ATA_ID_SERNO_LEN + num + 3)) {
 		/* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
 		rbuf[num + 0] = 2;
-		rbuf[num + 3] = ATA_SERNO_LEN;
+		rbuf[num + 3] = ATA_ID_SERNO_LEN;
 		num += 4;
 		ata_id_string(args->id, (unsigned char *) rbuf + num,
-			      ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
-		num += ATA_SERNO_LEN;
+			      ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+		num += ATA_ID_SERNO_LEN;
 	}
 	if (buflen > (sat_model_serial_desc_len + num + 3)) {
 		/* SAT defined lu model and serial numbers descriptor */
@@ -1823,11 +1863,11 @@
 		memcpy(rbuf + num, "ATA     ", 8);
 		num += 8;
 		ata_id_string(args->id, (unsigned char *) rbuf + num,
-			      ATA_ID_PROD_OFS, ata_model_byte_len);
-		num += ata_model_byte_len;
+			      ATA_ID_PROD, ATA_ID_PROD_LEN);
+		num += ATA_ID_PROD_LEN;
 		ata_id_string(args->id, (unsigned char *) rbuf + num,
-			      ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
-		num += ATA_SERNO_LEN;
+			      ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+		num += ATA_ID_SERNO_LEN;
 	}
 	rbuf[3] = num - 4;    /* page len (assume less than 256 bytes) */
 	return 0;
@@ -1955,15 +1995,15 @@
  */
 static int ata_dev_supports_fua(u16 *id)
 {
-	unsigned char model[41], fw[9];
+	unsigned char model[ATA_ID_PROD_LEN + 1], fw[ATA_ID_FW_REV_LEN + 1];
 
 	if (!libata_fua)
 		return 0;
 	if (!ata_id_has_fua(id))
 		return 0;
 
-	ata_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model));
-	ata_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw));
+	ata_id_c_string(id, model, ATA_ID_PROD, sizeof(model));
+	ata_id_c_string(id, fw, ATA_ID_FW_REV, sizeof(fw));
 
 	if (strcmp(model, "Maxtor"))
 		return 1;
@@ -2661,7 +2701,7 @@
 	 * TODO: find out if we need to do more here to
 	 *       cover scatter/gather case.
 	 */
-	qc->nsect = scmd->request_bufflen / ATA_SECT_SIZE;
+	qc->nbytes = scmd->request_bufflen;
 
 	/* request result TF */
 	qc->flags |= ATA_QCFLAG_RESULT_TF;
@@ -3059,7 +3099,8 @@
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *dev = &ap->device[i];
 		if (ata_dev_enabled(dev) && !dev->sdev) {
-			queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ);
+			queue_delayed_work(ata_aux_wq, &ap->hotplug_task,
+				round_jiffies_relative(HZ));
 			break;
 		}
 	}
@@ -3264,7 +3305,8 @@
 
 void ata_sas_port_destroy(struct ata_port *ap)
 {
-	ap->ops->port_stop(ap);
+	if (ap->ops->port_stop)
+		ap->ops->port_stop(ap);
 	kfree(ap);
 }
 EXPORT_SYMBOL_GPL(ata_sas_port_destroy);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 12c88c5..16bc3e3 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -56,10 +56,7 @@
 	ap->ctl &= ~ATA_NIEN;
 	ap->last_ctl = ap->ctl;
 
-	if (ap->flags & ATA_FLAG_MMIO)
-		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
-	else
-		outb(ap->ctl, ioaddr->ctl_addr);
+	iowrite8(ap->ctl, ioaddr->ctl_addr);
 	tmp = ata_wait_idle(ap);
 
 	ap->ops->irq_clear(ap);
@@ -67,8 +64,48 @@
 	return tmp;
 }
 
+u8 ata_dummy_irq_on (struct ata_port *ap) 	{ return 0; }
+
 /**
- *	ata_tf_load_pio - send taskfile registers to host controller
+ *	ata_irq_ack - Acknowledge a device interrupt.
+ *	@ap: Port on which interrupts are enabled.
+ *
+ *	Wait up to 10 ms for legacy IDE device to become idle (BUSY
+ *	or BUSY+DRQ clear).  Obtain dma status and port status from
+ *	device.  Clear the interrupt.  Return port status.
+ *
+ *	LOCKING:
+ */
+
+u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
+{
+	unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
+	u8 host_stat, post_stat, status;
+
+	status = ata_busy_wait(ap, bits, 1000);
+	if (status & bits)
+		if (ata_msg_err(ap))
+			printk(KERN_ERR "abnormal status 0x%X\n", status);
+
+	/* get controller status; clear intr, err bits */
+	host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
+		 ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+
+	post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+
+	if (ata_msg_intr(ap))
+		printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
+			__FUNCTION__,
+			host_stat, post_stat, status);
+
+	return status;
+}
+
+u8 ata_dummy_irq_ack(struct ata_port *ap, unsigned int chk_drq) { return 0; }
+
+/**
+ *	ata_tf_load - send taskfile registers to host controller
  *	@ap: Port to which output is sent
  *	@tf: ATA taskfile register set
  *
@@ -78,274 +115,73 @@
  *	Inherited from caller.
  */
 
-static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-	struct ata_ioports *ioaddr = &ap->ioaddr;
-	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
-
-	if (tf->ctl != ap->last_ctl) {
-		outb(tf->ctl, ioaddr->ctl_addr);
-		ap->last_ctl = tf->ctl;
-		ata_wait_idle(ap);
-	}
-
-	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
-		outb(tf->hob_feature, ioaddr->feature_addr);
-		outb(tf->hob_nsect, ioaddr->nsect_addr);
-		outb(tf->hob_lbal, ioaddr->lbal_addr);
-		outb(tf->hob_lbam, ioaddr->lbam_addr);
-		outb(tf->hob_lbah, ioaddr->lbah_addr);
-		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
-			tf->hob_feature,
-			tf->hob_nsect,
-			tf->hob_lbal,
-			tf->hob_lbam,
-			tf->hob_lbah);
-	}
-
-	if (is_addr) {
-		outb(tf->feature, ioaddr->feature_addr);
-		outb(tf->nsect, ioaddr->nsect_addr);
-		outb(tf->lbal, ioaddr->lbal_addr);
-		outb(tf->lbam, ioaddr->lbam_addr);
-		outb(tf->lbah, ioaddr->lbah_addr);
-		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
-			tf->feature,
-			tf->nsect,
-			tf->lbal,
-			tf->lbam,
-			tf->lbah);
-	}
-
-	if (tf->flags & ATA_TFLAG_DEVICE) {
-		outb(tf->device, ioaddr->device_addr);
-		VPRINTK("device 0x%X\n", tf->device);
-	}
-
-	ata_wait_idle(ap);
-}
-
-/**
- *	ata_tf_load_mmio - send taskfile registers to host controller
- *	@ap: Port to which output is sent
- *	@tf: ATA taskfile register set
- *
- *	Outputs ATA taskfile to standard ATA host controller using MMIO.
- *
- *	LOCKING:
- *	Inherited from caller.
- */
-
-static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-	struct ata_ioports *ioaddr = &ap->ioaddr;
-	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
-
-	if (tf->ctl != ap->last_ctl) {
-		writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
-		ap->last_ctl = tf->ctl;
-		ata_wait_idle(ap);
-	}
-
-	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
-		writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr);
-		writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr);
-		writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr);
-		writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr);
-		writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr);
-		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
-			tf->hob_feature,
-			tf->hob_nsect,
-			tf->hob_lbal,
-			tf->hob_lbam,
-			tf->hob_lbah);
-	}
-
-	if (is_addr) {
-		writeb(tf->feature, (void __iomem *) ioaddr->feature_addr);
-		writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
-		writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
-		writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
-		writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
-		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
-			tf->feature,
-			tf->nsect,
-			tf->lbal,
-			tf->lbam,
-			tf->lbah);
-	}
-
-	if (tf->flags & ATA_TFLAG_DEVICE) {
-		writeb(tf->device, (void __iomem *) ioaddr->device_addr);
-		VPRINTK("device 0x%X\n", tf->device);
-	}
-
-	ata_wait_idle(ap);
-}
-
-
-/**
- *	ata_tf_load - send taskfile registers to host controller
- *	@ap: Port to which output is sent
- *	@tf: ATA taskfile register set
- *
- *	Outputs ATA taskfile to standard ATA host controller using MMIO
- *	or PIO as indicated by the ATA_FLAG_MMIO flag.
- *	Writes the control, feature, nsect, lbal, lbam, and lbah registers.
- *	Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
- *	hob_lbal, hob_lbam, and hob_lbah.
- *
- *	This function waits for idle (!BUSY and !DRQ) after writing
- *	registers.  If the control register has a new value, this
- *	function also waits for idle after writing control and before
- *	writing the remaining registers.
- *
- *	May be used as the tf_load() entry in ata_port_operations.
- *
- *	LOCKING:
- *	Inherited from caller.
- */
 void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
-	if (ap->flags & ATA_FLAG_MMIO)
-		ata_tf_load_mmio(ap, tf);
-	else
-		ata_tf_load_pio(ap, tf);
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	if (tf->ctl != ap->last_ctl) {
+		iowrite8(tf->ctl, ioaddr->ctl_addr);
+		ap->last_ctl = tf->ctl;
+		ata_wait_idle(ap);
+	}
+
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		iowrite8(tf->hob_feature, ioaddr->feature_addr);
+		iowrite8(tf->hob_nsect, ioaddr->nsect_addr);
+		iowrite8(tf->hob_lbal, ioaddr->lbal_addr);
+		iowrite8(tf->hob_lbam, ioaddr->lbam_addr);
+		iowrite8(tf->hob_lbah, ioaddr->lbah_addr);
+		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+			tf->hob_feature,
+			tf->hob_nsect,
+			tf->hob_lbal,
+			tf->hob_lbam,
+			tf->hob_lbah);
+	}
+
+	if (is_addr) {
+		iowrite8(tf->feature, ioaddr->feature_addr);
+		iowrite8(tf->nsect, ioaddr->nsect_addr);
+		iowrite8(tf->lbal, ioaddr->lbal_addr);
+		iowrite8(tf->lbam, ioaddr->lbam_addr);
+		iowrite8(tf->lbah, ioaddr->lbah_addr);
+		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+			tf->feature,
+			tf->nsect,
+			tf->lbal,
+			tf->lbam,
+			tf->lbah);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE) {
+		iowrite8(tf->device, ioaddr->device_addr);
+		VPRINTK("device 0x%X\n", tf->device);
+	}
+
+	ata_wait_idle(ap);
 }
 
 /**
- *	ata_exec_command_pio - issue ATA command to host controller
- *	@ap: port to which command is being issued
- *	@tf: ATA taskfile register set
- *
- *	Issues PIO write to ATA command register, with proper
- *	synchronization with interrupt handler / other threads.
- *
- *	LOCKING:
- *	spin_lock_irqsave(host lock)
- */
-
-static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
-
-       	outb(tf->command, ap->ioaddr.command_addr);
-	ata_pause(ap);
-}
-
-
-/**
- *	ata_exec_command_mmio - issue ATA command to host controller
- *	@ap: port to which command is being issued
- *	@tf: ATA taskfile register set
- *
- *	Issues MMIO write to ATA command register, with proper
- *	synchronization with interrupt handler / other threads.
- *
- *	FIXME: missing write posting for 400nS delay enforcement
- *
- *	LOCKING:
- *	spin_lock_irqsave(host lock)
- */
-
-static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
-
-       	writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr);
-	ata_pause(ap);
-}
-
-
-/**
  *	ata_exec_command - issue ATA command to host controller
  *	@ap: port to which command is being issued
  *	@tf: ATA taskfile register set
  *
- *	Issues PIO/MMIO write to ATA command register, with proper
- *	synchronization with interrupt handler / other threads.
+ *	Issues ATA command, with proper synchronization with interrupt
+ *	handler / other threads.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  */
 void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
 {
-	if (ap->flags & ATA_FLAG_MMIO)
-		ata_exec_command_mmio(ap, tf);
-	else
-		ata_exec_command_pio(ap, tf);
+	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
+
+	iowrite8(tf->command, ap->ioaddr.command_addr);
+	ata_pause(ap);
 }
 
 /**
- *	ata_tf_read_pio - input device's ATA taskfile shadow registers
- *	@ap: Port from which input is read
- *	@tf: ATA taskfile register set for storing input
- *
- *	Reads ATA taskfile registers for currently-selected device
- *	into @tf.
- *
- *	LOCKING:
- *	Inherited from caller.
- */
-
-static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
-{
-	struct ata_ioports *ioaddr = &ap->ioaddr;
-
-	tf->command = ata_check_status(ap);
-	tf->feature = inb(ioaddr->error_addr);
-	tf->nsect = inb(ioaddr->nsect_addr);
-	tf->lbal = inb(ioaddr->lbal_addr);
-	tf->lbam = inb(ioaddr->lbam_addr);
-	tf->lbah = inb(ioaddr->lbah_addr);
-	tf->device = inb(ioaddr->device_addr);
-
-	if (tf->flags & ATA_TFLAG_LBA48) {
-		outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
-		tf->hob_feature = inb(ioaddr->error_addr);
-		tf->hob_nsect = inb(ioaddr->nsect_addr);
-		tf->hob_lbal = inb(ioaddr->lbal_addr);
-		tf->hob_lbam = inb(ioaddr->lbam_addr);
-		tf->hob_lbah = inb(ioaddr->lbah_addr);
-	}
-}
-
-/**
- *	ata_tf_read_mmio - input device's ATA taskfile shadow registers
- *	@ap: Port from which input is read
- *	@tf: ATA taskfile register set for storing input
- *
- *	Reads ATA taskfile registers for currently-selected device
- *	into @tf via MMIO.
- *
- *	LOCKING:
- *	Inherited from caller.
- */
-
-static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
-{
-	struct ata_ioports *ioaddr = &ap->ioaddr;
-
-	tf->command = ata_check_status(ap);
-	tf->feature = readb((void __iomem *)ioaddr->error_addr);
-	tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
-	tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
-	tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
-	tf->lbah = readb((void __iomem *)ioaddr->lbah_addr);
-	tf->device = readb((void __iomem *)ioaddr->device_addr);
-
-	if (tf->flags & ATA_TFLAG_LBA48) {
-		writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
-		tf->hob_feature = readb((void __iomem *)ioaddr->error_addr);
-		tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr);
-		tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr);
-		tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr);
-		tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr);
-	}
-}
-
-
-/**
  *	ata_tf_read - input device's ATA taskfile shadow registers
  *	@ap: Port from which input is read
  *	@tf: ATA taskfile register set for storing input
@@ -353,55 +189,31 @@
  *	Reads ATA taskfile registers for currently-selected device
  *	into @tf.
  *
- *	Reads nsect, lbal, lbam, lbah, and device.  If ATA_TFLAG_LBA48
- *	is set, also reads the hob registers.
- *
- *	May be used as the tf_read() entry in ata_port_operations.
- *
  *	LOCKING:
  *	Inherited from caller.
  */
 void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if (ap->flags & ATA_FLAG_MMIO)
-		ata_tf_read_mmio(ap, tf);
-	else
-		ata_tf_read_pio(ap, tf);
-}
+	struct ata_ioports *ioaddr = &ap->ioaddr;
 
-/**
- *	ata_check_status_pio - Read device status reg & clear interrupt
- *	@ap: port where the device is
- *
- *	Reads ATA taskfile status register for currently-selected device
- *	and return its value. This also clears pending interrupts
- *      from this device
- *
- *	LOCKING:
- *	Inherited from caller.
- */
-static u8 ata_check_status_pio(struct ata_port *ap)
-{
-	return inb(ap->ioaddr.status_addr);
-}
+	tf->command = ata_check_status(ap);
+	tf->feature = ioread8(ioaddr->error_addr);
+	tf->nsect = ioread8(ioaddr->nsect_addr);
+	tf->lbal = ioread8(ioaddr->lbal_addr);
+	tf->lbam = ioread8(ioaddr->lbam_addr);
+	tf->lbah = ioread8(ioaddr->lbah_addr);
+	tf->device = ioread8(ioaddr->device_addr);
 
-/**
- *	ata_check_status_mmio - Read device status reg & clear interrupt
- *	@ap: port where the device is
- *
- *	Reads ATA taskfile status register for currently-selected device
- *	via MMIO and return its value. This also clears pending interrupts
- *      from this device
- *
- *	LOCKING:
- *	Inherited from caller.
- */
-static u8 ata_check_status_mmio(struct ata_port *ap)
-{
-       	return readb((void __iomem *) ap->ioaddr.status_addr);
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+		tf->hob_feature = ioread8(ioaddr->error_addr);
+		tf->hob_nsect = ioread8(ioaddr->nsect_addr);
+		tf->hob_lbal = ioread8(ioaddr->lbal_addr);
+		tf->hob_lbam = ioread8(ioaddr->lbam_addr);
+		tf->hob_lbah = ioread8(ioaddr->lbah_addr);
+	}
 }
 
-
 /**
  *	ata_check_status - Read device status reg & clear interrupt
  *	@ap: port where the device is
@@ -410,19 +222,14 @@
  *	and return its value. This also clears pending interrupts
  *      from this device
  *
- *	May be used as the check_status() entry in ata_port_operations.
- *
  *	LOCKING:
  *	Inherited from caller.
  */
 u8 ata_check_status(struct ata_port *ap)
 {
-	if (ap->flags & ATA_FLAG_MMIO)
-		return ata_check_status_mmio(ap);
-	return ata_check_status_pio(ap);
+	return ioread8(ap->ioaddr.status_addr);
 }
 
-
 /**
  *	ata_altstatus - Read device alternate status reg
  *	@ap: port where the device is
@@ -441,58 +248,52 @@
 	if (ap->ops->check_altstatus)
 		return ap->ops->check_altstatus(ap);
 
-	if (ap->flags & ATA_FLAG_MMIO)
-		return readb((void __iomem *)ap->ioaddr.altstatus_addr);
-	return inb(ap->ioaddr.altstatus_addr);
+	return ioread8(ap->ioaddr.altstatus_addr);
 }
 
 /**
- *	ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction
+ *	ata_bmdma_setup - Set up PCI IDE BMDMA transaction
  *	@qc: Info associated with this ATA transaction.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  */
-
-static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+void ata_bmdma_setup(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 dmactl;
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 
 	/* load PRD table addr. */
 	mb();	/* make sure PRD table writes are visible to controller */
-	writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
+	iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
 
 	/* specify data direction, triple-check start bit is clear */
-	dmactl = readb(mmio + ATA_DMA_CMD);
+	dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
 	if (!rw)
 		dmactl |= ATA_DMA_WR;
-	writeb(dmactl, mmio + ATA_DMA_CMD);
+	iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 
 	/* issue r/w command */
 	ap->ops->exec_command(ap, &qc->tf);
 }
 
 /**
- *	ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction
+ *	ata_bmdma_start - Start a PCI IDE BMDMA transaction
  *	@qc: Info associated with this ATA transaction.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  */
-
-static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
+void ata_bmdma_start (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 	u8 dmactl;
 
 	/* start host DMA transaction */
-	dmactl = readb(mmio + ATA_DMA_CMD);
-	writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
+	dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+	iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 
 	/* Strictly, one may wish to issue a readb() here, to
 	 * flush the mmio write.  However, control also passes
@@ -508,96 +309,6 @@
 }
 
 /**
- *	ata_bmdma_setup_pio - Set up PCI IDE BMDMA transaction (PIO)
- *	@qc: Info associated with this ATA transaction.
- *
- *	LOCKING:
- *	spin_lock_irqsave(host lock)
- */
-
-static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
-{
-	struct ata_port *ap = qc->ap;
-	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-	u8 dmactl;
-
-	/* load PRD table addr. */
-	outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
-
-	/* specify data direction, triple-check start bit is clear */
-	dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
-	if (!rw)
-		dmactl |= ATA_DMA_WR;
-	outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-
-	/* issue r/w command */
-	ap->ops->exec_command(ap, &qc->tf);
-}
-
-/**
- *	ata_bmdma_start_pio - Start a PCI IDE BMDMA transaction (PIO)
- *	@qc: Info associated with this ATA transaction.
- *
- *	LOCKING:
- *	spin_lock_irqsave(host lock)
- */
-
-static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
-{
-	struct ata_port *ap = qc->ap;
-	u8 dmactl;
-
-	/* start host DMA transaction */
-	dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-	outb(dmactl | ATA_DMA_START,
-	     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-}
-
-
-/**
- *	ata_bmdma_start - Start a PCI IDE BMDMA transaction
- *	@qc: Info associated with this ATA transaction.
- *
- *	Writes the ATA_DMA_START flag to the DMA command register.
- *
- *	May be used as the bmdma_start() entry in ata_port_operations.
- *
- *	LOCKING:
- *	spin_lock_irqsave(host lock)
- */
-void ata_bmdma_start(struct ata_queued_cmd *qc)
-{
-	if (qc->ap->flags & ATA_FLAG_MMIO)
-		ata_bmdma_start_mmio(qc);
-	else
-		ata_bmdma_start_pio(qc);
-}
-
-
-/**
- *	ata_bmdma_setup - Set up PCI IDE BMDMA transaction
- *	@qc: Info associated with this ATA transaction.
- *
- *	Writes address of PRD table to device's PRD Table Address
- *	register, sets the DMA control register, and calls
- *	ops->exec_command() to start the transfer.
- *
- *	May be used as the bmdma_setup() entry in ata_port_operations.
- *
- *	LOCKING:
- *	spin_lock_irqsave(host lock)
- */
-void ata_bmdma_setup(struct ata_queued_cmd *qc)
-{
-	if (qc->ap->flags & ATA_FLAG_MMIO)
-		ata_bmdma_setup_mmio(qc);
-	else
-		ata_bmdma_setup_pio(qc);
-}
-
-
-/**
  *	ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
  *	@ap: Port associated with this ATA transaction.
  *
@@ -608,23 +319,16 @@
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  */
-
 void ata_bmdma_irq_clear(struct ata_port *ap)
 {
-	if (!ap->ioaddr.bmdma_addr)
+	void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+	if (!mmio)
 		return;
 
-	if (ap->flags & ATA_FLAG_MMIO) {
-		void __iomem *mmio =
-		      ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
-		writeb(readb(mmio), mmio);
-	} else {
-		unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
-		outb(inb(addr), addr);
-	}
+	iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
 }
 
-
 /**
  *	ata_bmdma_status - Read PCI IDE BMDMA status
  *	@ap: Port associated with this ATA transaction.
@@ -636,19 +340,11 @@
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  */
-
 u8 ata_bmdma_status(struct ata_port *ap)
 {
-	u8 host_stat;
-	if (ap->flags & ATA_FLAG_MMIO) {
-		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-		host_stat = readb(mmio + ATA_DMA_STATUS);
-	} else
-		host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-	return host_stat;
+	return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
 }
 
-
 /**
  *	ata_bmdma_stop - Stop PCI IDE BMDMA transfer
  *	@qc: Command we are ending DMA for
@@ -660,21 +356,14 @@
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  */
-
 void ata_bmdma_stop(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	if (ap->flags & ATA_FLAG_MMIO) {
-		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = ap->ioaddr.bmdma_addr;
 
-		/* clear start/stop bit */
-		writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
-			mmio + ATA_DMA_CMD);
-	} else {
-		/* clear start/stop bit */
-		outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
-			ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-	}
+	/* clear start/stop bit */
+	iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
+		 mmio + ATA_DMA_CMD);
 
 	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
 	ata_altstatus(ap);        /* dummy read */
@@ -696,10 +385,7 @@
 	ap->ctl |= ATA_NIEN;
 	ap->last_ctl = ap->ctl;
 
-	if (ap->flags & ATA_FLAG_MMIO)
-		writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr);
-	else
-		outb(ap->ctl, ioaddr->ctl_addr);
+	iowrite8(ap->ctl, ioaddr->ctl_addr);
 
 	/* Under certain circumstances, some controllers raise IRQ on
 	 * ATA_NIEN manipulation.  Also, many controllers fail to mask
@@ -724,8 +410,7 @@
 	/* clear & re-enable interrupts */
 	ata_chk_status(ap);
 	ap->ops->irq_clear(ap);
-	if (ap->ioaddr.ctl_addr)	/* FIXME: hack. create a hook instead */
-		ata_irq_on(ap);
+	ap->ops->irq_on(ap);
 }
 
 /**
@@ -775,7 +460,7 @@
 		 * really a timeout event, adjust error mask and
 		 * cancel frozen state.
 		 */
-		if (qc->err_mask == AC_ERR_TIMEOUT && host_stat & ATA_DMA_ERR) {
+		if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) {
 			qc->err_mask = AC_ERR_HOST_BUS;
 			thaw = 1;
 		}
@@ -832,6 +517,21 @@
 }
 
 #ifdef CONFIG_PCI
+
+static int ata_resources_present(struct pci_dev *pdev, int port)
+{
+	int i;
+	
+	/* Check the PCI resources for this channel are enabled */
+	port = port * 2;
+	for (i = 0; i < 2; i ++) {
+		if (pci_resource_start(pdev, port + i) == 0 ||
+			pci_resource_len(pdev, port + i) == 0)
+		return 0;
+	}
+	return 1;
+}
+		
 /**
  *	ata_pci_init_native_mode - Initialize native-mode driver
  *	@pdev:  pci device to be initialized
@@ -853,45 +553,62 @@
 struct ata_probe_ent *
 ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
 {
-	struct ata_probe_ent *probe_ent =
-		ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
-	int p = 0;
-	unsigned long bmdma;
+	struct ata_probe_ent *probe_ent;
+	int i, p = 0;
+	void __iomem * const *iomap;
 
+	/* iomap BARs */
+	for (i = 0; i < 4; i++) {
+		if (pcim_iomap(pdev, i, 0) == NULL) {
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "failed to iomap PCI BAR %d\n", i);
+			return NULL;
+		}
+	}
+
+	pcim_iomap(pdev, 4, 0); /* may fail */
+	iomap = pcim_iomap_table(pdev);
+
+	/* alloc and init probe_ent */
+	probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
 	if (!probe_ent)
 		return NULL;
 
 	probe_ent->irq = pdev->irq;
 	probe_ent->irq_flags = IRQF_SHARED;
+	
+	/* Discard disabled ports. Some controllers show their
+	   unused channels this way */
+	if (ata_resources_present(pdev, 0) == 0)
+		ports &= ~ATA_PORT_PRIMARY;
+	if (ata_resources_present(pdev, 1) == 0)
+		ports &= ~ATA_PORT_SECONDARY;
 
 	if (ports & ATA_PORT_PRIMARY) {
-		probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
+		probe_ent->port[p].cmd_addr = iomap[0];
 		probe_ent->port[p].altstatus_addr =
-		probe_ent->port[p].ctl_addr =
-			pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-		bmdma = pci_resource_start(pdev, 4);
-		if (bmdma) {
+		probe_ent->port[p].ctl_addr = (void __iomem *)
+			((unsigned long)iomap[1] | ATA_PCI_CTL_OFS);
+		if (iomap[4]) {
 			if ((!(port[p]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
-			    (inb(bmdma + 2) & 0x80))
+			    (ioread8(iomap[4] + 2) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
-			probe_ent->port[p].bmdma_addr = bmdma;
+			probe_ent->port[p].bmdma_addr = iomap[4];
 		}
 		ata_std_ports(&probe_ent->port[p]);
 		p++;
 	}
 
 	if (ports & ATA_PORT_SECONDARY) {
-		probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2);
+		probe_ent->port[p].cmd_addr = iomap[2];
 		probe_ent->port[p].altstatus_addr =
-		probe_ent->port[p].ctl_addr =
-			pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-		bmdma = pci_resource_start(pdev, 4);
-		if (bmdma) {
-			bmdma += 8;
+		probe_ent->port[p].ctl_addr = (void __iomem *)
+			((unsigned long)iomap[3] | ATA_PCI_CTL_OFS);
+		if (iomap[4]) {
 			if ((!(port[p]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
-			    (inb(bmdma + 2) & 0x80))
+			    (ioread8(iomap[4] + 10) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
-			probe_ent->port[p].bmdma_addr = bmdma;
+			probe_ent->port[p].bmdma_addr = iomap[4] + 8;
 		}
 		ata_std_ports(&probe_ent->port[p]);
 		probe_ent->pinfo2 = port[1];
@@ -902,13 +619,29 @@
 	return probe_ent;
 }
 
-
 static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
 				struct ata_port_info **port, int port_mask)
 {
 	struct ata_probe_ent *probe_ent;
-	unsigned long bmdma = pci_resource_start(pdev, 4);
+	void __iomem *iomap[5] = { }, *bmdma;
 
+	if (port_mask & ATA_PORT_PRIMARY) {
+		iomap[0] = devm_ioport_map(&pdev->dev, ATA_PRIMARY_CMD, 8);
+		iomap[1] = devm_ioport_map(&pdev->dev, ATA_PRIMARY_CTL, 1);
+		if (!iomap[0] || !iomap[1])
+			return NULL;
+	}
+
+	if (port_mask & ATA_PORT_SECONDARY) {
+		iomap[2] = devm_ioport_map(&pdev->dev, ATA_SECONDARY_CMD, 8);
+		iomap[3] = devm_ioport_map(&pdev->dev, ATA_SECONDARY_CTL, 1);
+		if (!iomap[2] || !iomap[3])
+			return NULL;
+	}
+
+	bmdma = pcim_iomap(pdev, 4, 16); /* may fail */
+
+	/* alloc and init probe_ent */
 	probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
 	if (!probe_ent)
 		return NULL;
@@ -918,13 +651,13 @@
 
 	if (port_mask & ATA_PORT_PRIMARY) {
 		probe_ent->irq = ATA_PRIMARY_IRQ(pdev);
-		probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD;
+		probe_ent->port[0].cmd_addr = iomap[0];
 		probe_ent->port[0].altstatus_addr =
-		probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
+		probe_ent->port[0].ctl_addr = iomap[1];
 		if (bmdma) {
 			probe_ent->port[0].bmdma_addr = bmdma;
 			if ((!(port[0]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
-			    (inb(bmdma + 2) & 0x80))
+			    (ioread8(bmdma + 2) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 		}
 		ata_std_ports(&probe_ent->port[0]);
@@ -936,13 +669,13 @@
 			probe_ent->irq2 = ATA_SECONDARY_IRQ(pdev);
 		else
 			probe_ent->irq = ATA_SECONDARY_IRQ(pdev);
-		probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD;
+		probe_ent->port[1].cmd_addr = iomap[2];
 		probe_ent->port[1].altstatus_addr =
-		probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
+		probe_ent->port[1].ctl_addr = iomap[3];
 		if (bmdma) {
 			probe_ent->port[1].bmdma_addr = bmdma + 8;
 			if ((!(port[1]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
-			    (inb(bmdma + 10) & 0x80))
+			    (ioread8(bmdma + 10) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 		}
 		ata_std_ports(&probe_ent->port[1]);
@@ -984,15 +717,18 @@
 int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
 		      unsigned int n_ports)
 {
+	struct device *dev = &pdev->dev;
 	struct ata_probe_ent *probe_ent = NULL;
 	struct ata_port_info *port[2];
 	u8 mask;
 	unsigned int legacy_mode = 0;
-	int disable_dev_on_err = 1;
 	int rc;
 
 	DPRINTK("ENTER\n");
 
+	if (!devres_open_group(dev, NULL, GFP_KERNEL))
+		return -ENOMEM;
+
 	BUG_ON(n_ports < 1 || n_ports > 2);
 
 	port[0] = port_info[0];
@@ -1009,9 +745,9 @@
 	   boot for the primary video which is BIOS enabled
          */
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
-		return rc;
+		goto err_out;
 
 	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
 		u8 tmp8;
@@ -1027,7 +763,8 @@
 		   left a device in compatibility mode */
 		if (legacy_mode) {
 			printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
-			return -EOPNOTSUPP;
+			rc = -EOPNOTSUPP;
+			goto err_out;
 		}
 #endif
 	}
@@ -1035,13 +772,13 @@
 	if (!legacy_mode) {
 		rc = pci_request_regions(pdev, DRV_NAME);
 		if (rc) {
-			disable_dev_on_err = 0;
+			pcim_pin_device(pdev);
 			goto err_out;
 		}
 	} else {
 		/* Deal with combined mode hack. This side of the logic all
 		   goes away once the combined mode hack is killed in 2.6.21 */
-		if (!request_region(ATA_PRIMARY_CMD, 8, "libata")) {
+		if (!devm_request_region(dev, ATA_PRIMARY_CMD, 8, "libata")) {
 			struct resource *conflict, res;
 			res.start = ATA_PRIMARY_CMD;
 			res.end = ATA_PRIMARY_CMD + 8 - 1;
@@ -1051,7 +788,7 @@
 			if (!strcmp(conflict->name, "libata"))
 				legacy_mode |= ATA_PORT_PRIMARY;
 			else {
-				disable_dev_on_err = 0;
+				pcim_pin_device(pdev);
 				printk(KERN_WARNING "ata: 0x%0X IDE port busy\n" \
 						    "ata: conflict with %s\n",
 						    ATA_PRIMARY_CMD,
@@ -1060,7 +797,7 @@
 		} else
 			legacy_mode |= ATA_PORT_PRIMARY;
 
-		if (!request_region(ATA_SECONDARY_CMD, 8, "libata")) {
+		if (!devm_request_region(dev, ATA_SECONDARY_CMD, 8, "libata")) {
 			struct resource *conflict, res;
 			res.start = ATA_SECONDARY_CMD;
 			res.end = ATA_SECONDARY_CMD + 8 - 1;
@@ -1070,7 +807,7 @@
 			if (!strcmp(conflict->name, "libata"))
 				legacy_mode |= ATA_PORT_SECONDARY;
 			else {
-				disable_dev_on_err = 0;
+				pcim_pin_device(pdev);
 				printk(KERN_WARNING "ata: 0x%X IDE port busy\n" \
 						    "ata: conflict with %s\n",
 						    ATA_SECONDARY_CMD,
@@ -1090,16 +827,16 @@
 	/* we have legacy mode, but all ports are unavailable */
 	if (legacy_mode == (1 << 3)) {
 		rc = -EBUSY;
-		goto err_out_regions;
+		goto err_out;
 	}
 
 	/* TODO: If we get no DMA mask we should fall back to PIO */
 	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		goto err_out;
 	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		goto err_out;
 
 	if (legacy_mode) {
 		probe_ent = ata_pci_init_legacy_port(pdev, port, legacy_mode);
@@ -1111,40 +848,22 @@
 	}
 	if (!probe_ent) {
 		rc = -ENOMEM;
-		goto err_out_regions;
+		goto err_out;
 	}
 
 	pci_set_master(pdev);
 
 	if (!ata_device_add(probe_ent)) {
 		rc = -ENODEV;
-		goto err_out_ent;
+		goto err_out;
 	}
 
-	kfree(probe_ent);
-
+	devm_kfree(dev, probe_ent);
+	devres_remove_group(dev, NULL);
 	return 0;
 
-err_out_ent:
-	kfree(probe_ent);
-err_out_regions:
-	/* All this conditional stuff is needed for the combined mode hack
-	   until 2.6.21 when it can go */
-	if (legacy_mode) {
-		pci_release_region(pdev, 4);
-		if (legacy_mode & ATA_PORT_PRIMARY) {
-			release_region(ATA_PRIMARY_CMD, 8);
-			pci_release_region(pdev, 1);
-		}
-		if (legacy_mode & ATA_PORT_SECONDARY) {
-			release_region(ATA_SECONDARY_CMD, 8);
-			pci_release_region(pdev, 3);
-		}
-	} else
-		pci_release_regions(pdev);
 err_out:
-	if (disable_dev_on_err)
-		pci_disable_device(pdev);
+	devres_release_group(dev, NULL);
 	return rc;
 }
 
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 81ae41d..0ad7781 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -29,7 +29,6 @@
 #define __LIBATA_H__
 
 #define DRV_NAME	"libata"
-#define DRV_VERSION	"2.00"	/* must be exactly four chars */
 
 struct ata_scsi_args {
 	struct ata_device	*dev;
@@ -48,6 +47,7 @@
 extern int atapi_enabled;
 extern int atapi_dmadir;
 extern int libata_fua;
+extern int noacpi;
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
 extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
 			   u64 block, u32 n_block, unsigned int tf_flags,
@@ -88,6 +88,20 @@
 extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev,
 						 const struct ata_port_info *port);
 
+/* libata-acpi.c */
+#ifdef CONFIG_SATA_ACPI
+extern int ata_acpi_exec_tfs(struct ata_port *ap);
+extern int ata_acpi_push_id(struct ata_port *ap, unsigned int ix);
+#else
+static inline int ata_acpi_exec_tfs(struct ata_port *ap)
+{
+	return 0;
+}
+static inline int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
+{
+	return 0;
+}
+#endif
 
 /* libata-scsi.c */
 extern struct scsi_transport_template ata_scsi_transport_template;
@@ -136,4 +150,7 @@
 /* libata-sff.c */
 extern u8 ata_irq_on(struct ata_port *ap);
 
+/* pata_sis.c */
+extern struct ata_port_info sis_info133;
+
 #endif /* __LIBATA_H__ */
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index c5d61d1..ab44d18 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -153,11 +153,11 @@
 
 static unsigned long ali_20_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask)
 {
-	char model_num[40];
+	char model_num[ATA_ID_PROD_LEN + 1];
 	/* No DMA on anything but a disk for now */
 	if (adev->class != ATA_DEV_ATA)
 		mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-	ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
+	ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 	if (strstr(model_num, "WDC"))
 		return mask &= ~ATA_MASK_UDMA;
 	return ata_pci_default_filter(ap, adev, mask);
@@ -370,14 +370,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -411,14 +411,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -449,14 +449,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -486,14 +486,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 
@@ -504,7 +504,7 @@
  *	Perform the setup on the device that must be done both at boot
  *	and at resume time.
  */
- 
+
 static void ali_init_chipset(struct pci_dev *pdev)
 {
 	u8 rev, tmp;
@@ -655,7 +655,7 @@
         	port_info[0] = port_info[1] = &info_c5;
 
 	ali_init_chipset(pdev);
-	
+
 	isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
 	if (isa_bridge && rev >= 0x20 && rev < 0xC2) {
 		/* Are we paired with a UDMA capable chip */
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index a6b33008..619e44b 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -362,14 +362,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations amd66_port_ops = {
@@ -396,14 +396,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations amd100_port_ops = {
@@ -430,14 +430,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations amd133_port_ops = {
@@ -464,14 +464,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations nv100_port_ops = {
@@ -498,14 +498,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations nv133_port_ops = {
@@ -532,14 +532,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 37bc132..21c3028 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -341,14 +341,14 @@
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 static const struct ata_port_operations artop6260_ops = {
@@ -373,14 +373,14 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 504e1db..c3eb40c 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -252,14 +252,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 449162c..da09828 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -313,14 +313,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations cmd646r1_port_ops = {
@@ -347,14 +347,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations cmd648_port_ops = {
@@ -381,14 +381,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 9f165a8..1ce8fcf 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -99,9 +99,9 @@
 static void cs5520_enable_dma(struct ata_port *ap, struct ata_device *adev)
 {
 	/* Set the DMA enable/disable flag */
-	u8 reg = inb(ap->ioaddr.bmdma_addr + 0x02);
+	u8 reg = ioread8(ap->ioaddr.bmdma_addr + 0x02);
 	reg |= 1<<(adev->devno + 5);
-	outb(reg, ap->ioaddr.bmdma_addr + 0x02);
+	iowrite8(reg, ap->ioaddr.bmdma_addr + 0x02);
 }
 
 /**
@@ -193,19 +193,20 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	u8 pcicfg;
+	void *iomap[5];
 	static struct ata_probe_ent probe[2];
 	int ports = 0;
 
@@ -236,6 +237,16 @@
 		return -ENODEV;
 	}
 
+	/* Map IO ports */
+	iomap[0] = devm_ioport_map(&dev->dev, 0x1F0, 8);
+	iomap[1] = devm_ioport_map(&dev->dev, 0x3F6, 1);
+	iomap[2] = devm_ioport_map(&dev->dev, 0x170, 8);
+	iomap[3] = devm_ioport_map(&dev->dev, 0x376, 1);
+	iomap[4] = pcim_iomap(dev, 2, 0);
+
+	if (!iomap[0] || !iomap[1] || !iomap[2] || !iomap[3] || !iomap[4])
+		return -ENOMEM;
+
 	/* We have to do our own plumbing as the PCI setup for this
 	   chipset is non-standard so we can't punt to the libata code */
 
@@ -249,10 +260,10 @@
 	probe[0].irq_flags = 0;
 	probe[0].port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST;
 	probe[0].n_ports = 1;
-	probe[0].port[0].cmd_addr = 0x1F0;
-	probe[0].port[0].ctl_addr = 0x3F6;
-	probe[0].port[0].altstatus_addr = 0x3F6;
-	probe[0].port[0].bmdma_addr = pci_resource_start(dev, 2);
+	probe[0].port[0].cmd_addr = iomap[0];
+	probe[0].port[0].ctl_addr = iomap[1];
+	probe[0].port[0].altstatus_addr = iomap[1];
+	probe[0].port[0].bmdma_addr = iomap[4];
 
 	/* The secondary lurks at different addresses but is otherwise
 	   the same beastie */
@@ -260,10 +271,10 @@
 	probe[1] = probe[0];
 	INIT_LIST_HEAD(&probe[1].node);
 	probe[1].irq = 15;
-	probe[1].port[0].cmd_addr = 0x170;
-	probe[1].port[0].ctl_addr = 0x376;
-	probe[1].port[0].altstatus_addr = 0x376;
-	probe[1].port[0].bmdma_addr = pci_resource_start(dev, 2) + 8;
+	probe[1].port[0].cmd_addr = iomap[2];
+	probe[1].port[0].ctl_addr = iomap[3];
+	probe[1].port[0].altstatus_addr = iomap[3];
+	probe[1].port[0].bmdma_addr = iomap[4] + 8;
 
 	/* Let libata fill in the port details */
 	ata_std_ports(&probe[0].port[0]);
@@ -294,7 +305,7 @@
 	struct device *dev = pci_dev_to_dev(pdev);
 	struct ata_host *host = dev_get_drvdata(dev);
 
-	ata_host_remove(host);
+	ata_host_detach(host);
 	dev_set_drvdata(dev, NULL);
 }
 
@@ -305,7 +316,7 @@
  *	Do any reconfiguration work needed by a resume from RAM. We need
  *	to restore DMA mode support on BIOSen which disabled it
  */
- 
+
 static int cs5520_reinit_one(struct pci_dev *pdev)
 {
 	u8 pcicfg;
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index b1ca207..3d7b7d8 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -37,6 +37,13 @@
 #define DRV_NAME	"pata_cs5530"
 #define DRV_VERSION	"0.7.1"
 
+static void __iomem *cs5530_port_base(struct ata_port *ap)
+{
+	unsigned long bmdma = (unsigned long)ap->ioaddr.bmdma_addr;
+
+	return (void __iomem *)((bmdma & ~0x0F) + 0x20 + 0x10 * ap->port_no);
+}
+
 /**
  *	cs5530_set_piomode		-	PIO setup
  *	@ap: ATA interface
@@ -52,19 +59,19 @@
 		{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},
 		{0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}
 	};
-	unsigned long base = ( ap->ioaddr.bmdma_addr & ~0x0F) + 0x20 + 0x10 * ap->port_no;
+	void __iomem *base = cs5530_port_base(ap);
 	u32 tuning;
 	int format;
 
 	/* Find out which table to use */
-	tuning = inl(base + 0x04);
+	tuning = ioread32(base + 0x04);
 	format = (tuning & 0x80000000UL) ? 1 : 0;
 
 	/* Now load the right timing register */
 	if (adev->devno)
 		base += 0x08;
 
-	outl(cs5530_pio_timings[format][adev->pio_mode - XFER_PIO_0], base);
+	iowrite32(cs5530_pio_timings[format][adev->pio_mode - XFER_PIO_0], base);
 }
 
 /**
@@ -79,12 +86,12 @@
 
 static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
-	unsigned long base = ( ap->ioaddr.bmdma_addr & ~0x0F) + 0x20 + 0x10 * ap->port_no;
+	void __iomem *base = cs5530_port_base(ap);
 	u32 tuning, timing = 0;
 	u8 reg;
 
 	/* Find out which table to use */
-	tuning = inl(base + 0x04);
+	tuning = ioread32(base + 0x04);
 
 	switch(adev->dma_mode) {
 		case XFER_UDMA_0:
@@ -105,20 +112,20 @@
 	/* Merge in the PIO format bit */
 	timing |= (tuning & 0x80000000UL);
 	if (adev->devno == 0) /* Master */
-		outl(timing, base + 0x04);
+		iowrite32(timing, base + 0x04);
 	else {
 		if (timing & 0x00100000)
 			tuning |= 0x00100000;	/* UDMA for both */
 		else
 			tuning &= ~0x00100000;	/* MWDMA for both */
-		outl(tuning, base + 0x04);
-		outl(timing, base + 0x0C);
+		iowrite32(tuning, base + 0x04);
+		iowrite32(timing, base + 0x0C);
 	}
 
 	/* Set the DMA capable bit in the BMDMA area */
-	reg = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	reg = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
 	reg |= (1 << (5 + adev->devno));
-	outb(reg, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	iowrite8(reg, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
 
 	/* Remember the last DMA setup we did */
 
@@ -210,14 +217,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= cs5530_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct dmi_system_id palmax_dmi_table[] = {
@@ -247,7 +254,7 @@
  *	Perform the chip initialisation work that is shared between both
  *	setup and resume paths
  */
- 
+
 static int cs5530_init_chip(void)
 {
 	struct pci_dev *master_0 = NULL, *cs5530_0 = NULL, *dev = NULL;
@@ -357,11 +364,11 @@
 		.port_ops = &cs5530_port_ops
 	};
 	static struct ata_port_info *port_info[2] = { &info, &info };
-	
+
 	/* Chip initialisation */
 	if (cs5530_init_chip())
 		return -ENODEV;
-		
+
 	if (cs5530_is_palmax())
 		port_info[1] = &info_palmax_secondary;
 
@@ -376,7 +383,7 @@
 		BUG();
 	return ata_pci_device_resume(pdev);
 }
-	
+
 static const struct pci_device_id cs5530[] = {
 	{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), },
 
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index e3efec4..17bc693 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -214,14 +214,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index e2a9569..63f48f0 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -165,14 +165,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index edf8a63..c19b6a8 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -261,14 +261,14 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 2663599..27d724b 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -151,23 +151,13 @@
 
 static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[])
 {
-	unsigned char model_num[40];
-	char *s;
-	unsigned int len;
+	unsigned char model_num[ATA_ID_PROD_LEN + 1];
 	int i = 0;
 
-	ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
-	s = &model_num[0];
-	len = strnlen(s, sizeof(model_num));
+	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
-	/* ATAPI specifies that empty space is blank-filled; remove blanks */
-	while ((len > 0) && (s[len - 1] == ' ')) {
-		len--;
-		s[len] = 0;
-	}
-
-	while(list[i] != NULL) {
-		if (!strncmp(list[i], s, len)) {
+	while (list[i] != NULL) {
+		if (!strcmp(list[i], model_num)) {
 			printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
 				modestr, list[i]);
 			return 1;
@@ -232,7 +222,7 @@
 
 	if (!pci_test_config_bits(pdev, &hpt36x_enable_bits[ap->port_no]))
 		return -ENOENT;
-		
+
 	pci_read_config_byte(pdev, 0x5A, &ata66);
 	if (ata66 & (1 << ap->port_no))
 		ap->cbl = ATA_CBL_PATA40;
@@ -371,14 +361,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index dfb3060..4ffc392 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -349,24 +349,13 @@
 
 static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[])
 {
-	unsigned char model_num[40];
-	char *s;
-	unsigned int len;
+	unsigned char model_num[ATA_ID_PROD_LEN + 1];
 	int i = 0;
 
-	ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
-			  sizeof(model_num));
-	s = &model_num[0];
-	len = strnlen(s, sizeof(model_num));
+	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
-	/* ATAPI specifies that empty space is blank-filled; remove blanks */
-	while ((len > 0) && (s[len - 1] == ' ')) {
-		len--;
-		s[len] = 0;
-	}
-
-	while(list[i] != NULL) {
-		if (!strncmp(list[i], s, len)) {
+	while (list[i] != NULL) {
+		if (!strcmp(list[i], model_num)) {
 			printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
 				modestr, list[i]);
 			return 1;
@@ -459,7 +448,7 @@
 	};
 	if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
 		return -ENOENT;
-		
+
 	pci_read_config_byte(pdev, 0x5B, &scr2);
 	pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01);
 	/* Cable register now active */
@@ -504,7 +493,7 @@
 
 	if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
 		return -ENOENT;
-		
+
 	/* Do the extra channel work */
 	pci_read_config_word(pdev, 0x52, &mcr3);
 	pci_read_config_word(pdev, 0x56, &mcr6);
@@ -645,24 +634,24 @@
 {
 	struct ata_port *ap = qc->ap;
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-	u8 dma_stat = inb(ap->ioaddr.bmdma_addr + 2);
+	u8 dma_stat = ioread8(ap->ioaddr.bmdma_addr + 2);
 	u8 dma_cmd;
-	unsigned long bmdma = ap->ioaddr.bmdma_addr;
+	void __iomem *bmdma = ap->ioaddr.bmdma_addr;
 
 	if (dma_stat & 0x01) {
 		udelay(20);
-		dma_stat = inb(bmdma + 2);
+		dma_stat = ioread8(bmdma + 2);
 	}
 	if (dma_stat & 0x01) {
 		/* Clear the engine */
 		pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
 		udelay(10);
 		/* Stop DMA */
-		dma_cmd = inb(bmdma );
-		outb(dma_cmd & 0xFE, bmdma);
+		dma_cmd = ioread8(bmdma );
+		iowrite8(dma_cmd & 0xFE, bmdma);
 		/* Clear Error */
-		dma_stat = inb(bmdma + 2);
-		outb(dma_stat | 0x06 , bmdma + 2);
+		dma_stat = ioread8(bmdma + 2);
+		iowrite8(dma_stat | 0x06 , bmdma + 2);
 		/* Clear the engine */
 		pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
 		udelay(10);
@@ -807,14 +796,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -846,14 +835,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -886,14 +875,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -926,14 +915,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index 886fab9..65f2e18 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -263,26 +263,26 @@
 
 static void hpt3x2n_set_clock(struct ata_port *ap, int source)
 {
-	unsigned long bmdma = ap->ioaddr.bmdma_addr;
+	void __iomem *bmdma = ap->ioaddr.bmdma_addr;
 
 	/* Tristate the bus */
-	outb(0x80, bmdma+0x73);
-	outb(0x80, bmdma+0x77);
+	iowrite8(0x80, bmdma+0x73);
+	iowrite8(0x80, bmdma+0x77);
 
 	/* Switch clock and reset channels */
-	outb(source, bmdma+0x7B);
-	outb(0xC0, bmdma+0x79);
+	iowrite8(source, bmdma+0x7B);
+	iowrite8(0xC0, bmdma+0x79);
 
 	/* Reset state machines */
-	outb(0x37, bmdma+0x70);
-	outb(0x37, bmdma+0x74);
+	iowrite8(0x37, bmdma+0x70);
+	iowrite8(0x37, bmdma+0x74);
 
 	/* Complete reset */
-	outb(0x00, bmdma+0x79);
+	iowrite8(0x00, bmdma+0x79);
 
 	/* Reconnect channels to bus */
-	outb(0x00, bmdma+0x73);
-	outb(0x00, bmdma+0x77);
+	iowrite8(0x00, bmdma+0x73);
+	iowrite8(0x00, bmdma+0x77);
 }
 
 /* Check if our partner interface is busy */
@@ -373,14 +373,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= hpt3x2n_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index 5f1d385..483ce7c 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -148,14 +148,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
@@ -164,7 +164,7 @@
  *
  *	Perform the setup required at boot and on resume.
  */
- 
+
 static void hpt3x3_init_chipset(struct pci_dev *dev)
 {
 	u16 cmd;
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index a97d55a..1bf5ec1 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -53,14 +53,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
@@ -75,6 +75,7 @@
 static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev_id)
 {
 	struct ata_probe_ent ae;
+	void __iomem *cmd_addr, *ctl_addr;
 
 	if (pnp_port_valid(idev, 0) == 0)
 		return -ENODEV;
@@ -83,6 +84,10 @@
 	if (pnp_irq_valid(idev, 0) == 0)
 		return -ENODEV;
 
+	cmd_addr = devm_ioport_map(&idev->dev, pnp_port_start(idev, 0), 8);
+	if (!cmd_addr)
+		return -ENOMEM;
+
 	memset(&ae, 0, sizeof(struct ata_probe_ent));
 	INIT_LIST_HEAD(&ae.node);
 	ae.dev = &idev->dev;
@@ -93,11 +98,13 @@
 	ae.irq = pnp_irq(idev, 0);
 	ae.irq_flags = 0;
 	ae.port_flags = ATA_FLAG_SLAVE_POSS;
-	ae.port[0].cmd_addr = pnp_port_start(idev, 0);
+	ae.port[0].cmd_addr = cmd_addr;
 
 	if (pnp_port_valid(idev, 1) == 0) {
-		ae.port[0].altstatus_addr = pnp_port_start(idev, 1);
-		ae.port[0].ctl_addr = pnp_port_start(idev, 1);
+		ctl_addr = devm_ioport_map(&idev->dev,
+					   pnp_port_start(idev, 1), 1);
+		ae.port[0].altstatus_addr = ctl_addr;
+		ae.port[0].ctl_addr = ctl_addr;
 		ae.port_flags |= ATA_FLAG_SRST;
 	}
 	ata_std_ports(&ae.port[0]);
@@ -120,7 +127,7 @@
 	struct device *dev = &idev->dev;
 	struct ata_host *host = dev_get_drvdata(dev);
 
-	ata_host_remove(host);
+	ata_host_detach(host);
 	dev_set_drvdata(dev, NULL);
 }
 
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
new file mode 100644
index 0000000..7eac869
--- /dev/null
+++ b/drivers/ata/pata_it8213.c
@@ -0,0 +1,354 @@
+/*
+ *    pata_it8213.c - iTE Tech. Inc.  IT8213 PATA driver
+ *
+ *    The IT8213 is a very Intel ICH like device for timing purposes, having
+ *    a similar register layout and the same split clock arrangement. Cable
+ *    detection is different, and it does not have slave channels or all the
+ *    clutter of later ICH/SATA setups.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <linux/ata.h>
+
+#define DRV_NAME	"pata_it8213"
+#define DRV_VERSION	"0.0.2"
+
+/**
+ *	it8213_pre_reset	-	check for 40/80 pin
+ *	@ap: Port
+ *
+ *	Perform cable detection for the 8213 ATA interface. This is
+ *	different to the PIIX arrangement
+ */
+
+static int it8213_pre_reset(struct ata_port *ap)
+{
+	static const struct pci_bits it8213_enable_bits[] = {
+		{ 0x41U, 1U, 0x80UL, 0x80UL },	/* port 0 */
+	};
+
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	u8 tmp;
+
+	if (!pci_test_config_bits(pdev, &it8213_enable_bits[ap->port_no]))
+		return -ENOENT;
+
+	pci_read_config_byte(pdev, 0x42, &tmp);
+	if (tmp & 2)	/* The initial docs are incorrect */
+		ap->cbl = ATA_CBL_PATA40;
+	else
+		ap->cbl = ATA_CBL_PATA80;
+	return ata_std_prereset(ap);
+}
+
+/**
+ *	it8213_probe_reset - Probe specified port on PATA host controller
+ *	@ap: Port to probe
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ */
+
+static void it8213_error_handler(struct ata_port *ap)
+{
+	ata_bmdma_drive_eh(ap, it8213_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ *	it8213_set_piomode - Initialize host controller PATA PIO timings
+ *	@ap: Port whose timings we are configuring
+ *	@adev: um
+ *
+ *	Set PIO mode for device, in host controller PCI config space.
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ */
+
+static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)
+{
+	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
+	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
+	unsigned int idetm_port= ap->port_no ? 0x42 : 0x40;
+	u16 idetm_data;
+	int control = 0;
+
+	/*
+	 *	See Intel Document 298600-004 for the timing programing rules
+	 *	for PIIX/ICH. The 8213 is a clone so very similar
+	 */
+
+	static const	 /* ISP  RTC */
+	u8 timings[][2]	= { { 0, 0 },
+			    { 0, 0 },
+			    { 1, 0 },
+			    { 2, 1 },
+			    { 2, 3 }, };
+
+	if (pio > 2)
+		control |= 1;	/* TIME1 enable */
+	if (ata_pio_need_iordy(adev))	/* PIO 3/4 require IORDY */
+		control |= 2;	/* IORDY enable */
+	/* Bit 2 is set for ATAPI on the IT8213 - reverse of ICH/PIIX */
+	if (adev->class != ATA_DEV_ATA)
+		control |= 4;
+
+	pci_read_config_word(dev, idetm_port, &idetm_data);
+
+	/* Enable PPE, IE and TIME as appropriate */
+
+	if (adev->devno == 0) {
+		idetm_data &= 0xCCF0;
+		idetm_data |= control;
+		idetm_data |= (timings[pio][0] << 12) |
+			(timings[pio][1] << 8);
+	} else {
+		u8 slave_data;
+
+		idetm_data &= 0xCC0F;
+		idetm_data |= (control << 4);
+
+		/* Slave timing in seperate register */
+		pci_read_config_byte(dev, 0x44, &slave_data);
+		slave_data &= 0xF0;
+		slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << 4;
+		pci_write_config_byte(dev, 0x44, slave_data);
+	}
+
+	idetm_data |= 0x4000;	/* Ensure SITRE is enabled */
+	pci_write_config_word(dev, idetm_port, idetm_data);
+}
+
+/**
+ *	it8213_set_dmamode - Initialize host controller PATA DMA timings
+ *	@ap: Port whose timings we are configuring
+ *	@adev: Device to program
+ *
+ *	Set UDMA/MWDMA mode for device, in host controller PCI config space.
+ *	This device is basically an ICH alike.
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ */
+
+static void it8213_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+{
+	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
+	u16 master_data;
+	u8 speed		= adev->dma_mode;
+	int devid		= adev->devno;
+	u8 udma_enable;
+
+	static const	 /* ISP  RTC */
+	u8 timings[][2]	= { { 0, 0 },
+			    { 0, 0 },
+			    { 1, 0 },
+			    { 2, 1 },
+			    { 2, 3 }, };
+
+	pci_read_config_word(dev, 0x40, &master_data);
+	pci_read_config_byte(dev, 0x48, &udma_enable);
+
+	if (speed >= XFER_UDMA_0) {
+		unsigned int udma = adev->dma_mode - XFER_UDMA_0;
+		u16 udma_timing;
+		u16 ideconf;
+		int u_clock, u_speed;
+
+		/* Clocks follow the PIIX style */
+		u_speed = min(2 - (udma & 1), udma);
+		if (udma == 5)
+			u_clock = 0x1000;	/* 100Mhz */
+		else if (udma > 2)
+			u_clock = 1;		/* 66Mhz */
+		else
+			u_clock = 0;		/* 33Mhz */
+
+		udma_enable |= (1 << devid);
+
+		/* Load the UDMA mode number */
+		pci_read_config_word(dev, 0x4A, &udma_timing);
+		udma_timing &= ~(3 << (4 * devid));
+		udma_timing |= (udma & 3) << (4 * devid);
+		pci_write_config_word(dev, 0x4A, udma_timing);
+
+		/* Load the clock selection */
+		pci_read_config_word(dev, 0x54, &ideconf);
+		ideconf &= ~(0x1001 << devid);
+		ideconf |= u_clock << devid;
+		pci_write_config_word(dev, 0x54, ideconf);
+	} else {
+		/*
+		 * MWDMA is driven by the PIO timings. We must also enable
+		 * IORDY unconditionally along with TIME1. PPE has already
+		 * been set when the PIO timing was set.
+		 */
+		unsigned int mwdma	= adev->dma_mode - XFER_MW_DMA_0;
+		unsigned int control;
+		u8 slave_data;
+		static const unsigned int needed_pio[3] = {
+			XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
+		};
+		int pio = needed_pio[mwdma] - XFER_PIO_0;
+
+		control = 3;	/* IORDY|TIME1 */
+
+		/* If the drive MWDMA is faster than it can do PIO then
+		   we must force PIO into PIO0 */
+
+		if (adev->pio_mode < needed_pio[mwdma])
+			/* Enable DMA timing only */
+			control |= 8;	/* PIO cycles in PIO0 */
+
+		if (devid) {	/* Slave */
+			master_data &= 0xFF4F;  /* Mask out IORDY|TIME1|DMAONLY */
+			master_data |= control << 4;
+			pci_read_config_byte(dev, 0x44, &slave_data);
+			slave_data &= (0x0F + 0xE1 * ap->port_no);
+			/* Load the matching timing */
+			slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
+			pci_write_config_byte(dev, 0x44, slave_data);
+		} else { 	/* Master */
+			master_data &= 0xCCF4;	/* Mask out IORDY|TIME1|DMAONLY
+						   and master timing bits */
+			master_data |= control;
+			master_data |=
+				(timings[pio][0] << 12) |
+				(timings[pio][1] << 8);
+		}
+		udma_enable &= ~(1 << devid);
+		pci_write_config_word(dev, 0x40, master_data);
+	}
+	pci_write_config_byte(dev, 0x48, udma_enable);
+}
+
+static struct scsi_host_template it8213_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= ATA_DMA_BOUNDARY,
+	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
+	.resume			= ata_scsi_device_resume,
+	.suspend		= ata_scsi_device_suspend,
+};
+
+static const struct ata_port_operations it8213_ops = {
+	.port_disable		= ata_port_disable,
+	.set_piomode		= it8213_set_piomode,
+	.set_dmamode		= it8213_set_dmamode,
+	.mode_filter		= ata_pci_default_filter,
+
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
+
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= it8213_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
+	.bmdma_stop		= ata_bmdma_stop,
+	.bmdma_status		= ata_bmdma_status,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ata_data_xfer,
+
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
+
+	.port_start		= ata_port_start,
+};
+
+
+/**
+ *	it8213_init_one - Register 8213 ATA PCI device with kernel services
+ *	@pdev: PCI device to register
+ *	@ent: Entry in it8213_pci_tbl matching with @pdev
+ *
+ *	Called from kernel PCI layer.
+ *
+ *	LOCKING:
+ *	Inherited from PCI layer (may sleep).
+ *
+ *	RETURNS:
+ *	Zero on success, or -ERRNO value.
+ */
+
+static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version;
+	static struct ata_port_info info = {
+		.sht		= &it8213_sht,
+		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask 	= 0x1f, /* UDMA 100 */
+		.port_ops	= &it8213_ops,
+	};
+	static struct ata_port_info *port_info[2] = { &info, &info };
+
+	if (!printed_version++)
+		dev_printk(KERN_DEBUG, &pdev->dev,
+			   "version " DRV_VERSION "\n");
+
+	/* Current IT8213 stuff is single port */
+	return ata_pci_init_one(pdev, port_info, 1);
+}
+
+static const struct pci_device_id it8213_pci_tbl[] = {
+	{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8213), },
+
+	{ }	/* terminate list */
+};
+
+static struct pci_driver it8213_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= it8213_pci_tbl,
+	.probe			= it8213_init_one,
+	.remove			= ata_pci_remove_one,
+	.suspend		= ata_pci_device_suspend,
+	.resume			= ata_pci_device_resume,
+};
+
+static int __init it8213_init(void)
+{
+	return pci_register_driver(&it8213_pci_driver);
+}
+
+static void __exit it8213_exit(void)
+{
+	pci_unregister_driver(&it8213_pci_driver);
+}
+
+module_init(it8213_init);
+module_exit(it8213_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("SCSI low-level driver for the ITE 8213");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, it8213_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index e8afd48..73394c7 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -492,7 +492,7 @@
 	/* Bits 5 and 6 indicate if DMA is active on master/slave */
 	/* It is possible that BMDMA isn't allocated */
 	if (ap->ioaddr.bmdma_addr)
-		dma_enabled = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+		dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *dev = &ap->device[i];
@@ -531,23 +531,9 @@
 
 static void it821x_dev_config(struct ata_port *ap, struct ata_device *adev)
 {
-	unsigned char model_num[40];
-	char *s;
-	unsigned int len;
+	unsigned char model_num[ATA_ID_PROD_LEN + 1];
 
-	/* This block ought to be a library routine as it is in several
-	   drivers now */
-
-	ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS,
-			  sizeof(model_num));
-	s = &model_num[0];
-	len = strnlen(s, sizeof(model_num));
-
-	/* ATAPI specifies that empty space is blank-filled; remove blanks */
-	while ((len > 0) && (s[len - 1] == ' ')) {
-		len--;
-		s[len] = 0;
-	}
+	ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
 	if (adev->max_sectors > 255)
 		adev->max_sectors = 255;
@@ -608,14 +594,10 @@
 	if (ret < 0)
 		return ret;
 
-	ap->private_data = kmalloc(sizeof(struct it821x_dev), GFP_KERNEL);
-	if (ap->private_data == NULL) {
-		ata_port_stop(ap);
+	itdev = devm_kzalloc(&pdev->dev, sizeof(struct it821x_dev), GFP_KERNEL);
+	if (itdev == NULL)
 		return -ENOMEM;
-	}
-
-	itdev = ap->private_data;
-	memset(itdev, 0, sizeof(struct it821x_dev));
+	ap->private_data = itdev;
 
 	pci_read_config_byte(pdev, 0x50, &conf);
 
@@ -646,20 +628,6 @@
 	return 0;
 }
 
-/**
- *	it821x_port_stop	-	port shutdown
- *	@ap: ATA port being removed
- *
- *	Release the private objects we added in it821x_port_start
- */
-
-static void it821x_port_stop(struct ata_port *ap) {
-	kfree(ap->private_data);
-	ap->private_data = NULL;	/* We want an OOPS if we reuse this
-					   too late! */
-	ata_port_stop(ap);
-}
-
 static struct scsi_host_template it821x_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
@@ -706,14 +674,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= it821x_smart_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= it821x_port_start,
-	.port_stop	= it821x_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations it821x_passthru_port_ops = {
@@ -742,14 +710,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= it821x_passthru_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_clear	= ata_bmdma_irq_clear,
 	.irq_handler	= ata_interrupt,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= it821x_port_start,
-	.port_stop	= it821x_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static void __devinit it821x_disable_raid(struct pci_dev *pdev)
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index 23b8aab..3222ac7 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -95,14 +95,6 @@
 {
 }
 
-static void ixp4xx_host_stop (struct ata_host *host)
-{
-	struct ixp4xx_pata_data *data = host->dev->platform_data;
-
-	iounmap(data->cs0);
-	iounmap(data->cs1);
-}
-
 static struct scsi_host_template ixp4xx_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
@@ -139,10 +131,10 @@
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ixp4xx_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ixp4xx_host_stop,
 
 	.phy_reset	= ixp4xx_phy_reset,
 };
@@ -150,9 +142,9 @@
 static void ixp4xx_setup_port(struct ata_ioports *ioaddr,
 				struct ixp4xx_pata_data *data)
 {
-	ioaddr->cmd_addr	= (unsigned long) data->cs0;
-	ioaddr->altstatus_addr	= (unsigned long) data->cs1 + 0x06;
-	ioaddr->ctl_addr	= (unsigned long) data->cs1 + 0x06;
+	ioaddr->cmd_addr	= data->cs0;
+	ioaddr->altstatus_addr	= data->cs1 + 0x06;
+	ioaddr->ctl_addr	= data->cs1 + 0x06;
 
 	ata_std_ports(ioaddr);
 
@@ -162,19 +154,19 @@
 	 * ixp4xx in little endian mode.
 	 */
 
-	ioaddr->data_addr	^= 0x02;
-	ioaddr->cmd_addr	^= 0x03;
-	ioaddr->altstatus_addr	^= 0x03;
-	ioaddr->ctl_addr	^= 0x03;
-	ioaddr->error_addr	^= 0x03;
-	ioaddr->feature_addr	^= 0x03;
-	ioaddr->nsect_addr	^= 0x03;
-	ioaddr->lbal_addr 	^= 0x03;
-	ioaddr->lbam_addr	^= 0x03;
-	ioaddr->lbah_addr	^= 0x03;
-	ioaddr->device_addr	^= 0x03;
-	ioaddr->status_addr	^= 0x03;
-	ioaddr->command_addr	^= 0x03;
+	*(unsigned long *)&ioaddr->data_addr		^= 0x02;
+	*(unsigned long *)&ioaddr->cmd_addr		^= 0x03;
+	*(unsigned long *)&ioaddr->altstatus_addr	^= 0x03;
+	*(unsigned long *)&ioaddr->ctl_addr		^= 0x03;
+	*(unsigned long *)&ioaddr->error_addr		^= 0x03;
+	*(unsigned long *)&ioaddr->feature_addr		^= 0x03;
+	*(unsigned long *)&ioaddr->nsect_addr		^= 0x03;
+	*(unsigned long *)&ioaddr->lbal_addr		^= 0x03;
+	*(unsigned long *)&ioaddr->lbam_addr		^= 0x03;
+	*(unsigned long *)&ioaddr->lbah_addr		^= 0x03;
+	*(unsigned long *)&ioaddr->device_addr		^= 0x03;
+	*(unsigned long *)&ioaddr->status_addr		^= 0x03;
+	*(unsigned long *)&ioaddr->command_addr		^= 0x03;
 #endif
 }
 
@@ -195,8 +187,8 @@
 
 	pdev->dev.coherent_dma_mask = DMA_32BIT_MASK;
 
-	data->cs0 = ioremap(cs0->start, 0x1000);
-	data->cs1 = ioremap(cs1->start, 0x1000);
+	data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000);
+	data->cs1 = devm_ioremap(&pdev->dev, cs1->start, 0x1000);
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq)
@@ -238,7 +230,7 @@
 {
 	struct ata_host *host = platform_get_drvdata(dev);
 
-	ata_host_remove(host);
+	ata_host_detach(host);
 	platform_set_drvdata(dev, NULL);
 
 	return 0;
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index d50264a..7a635dd 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -161,16 +161,16 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	/* IRQ-related hooks */
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	/* Generic PATA PCI ATA helpers */
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 
@@ -221,7 +221,7 @@
 static int jmicron_reinit_one(struct pci_dev *pdev)
 {
 	u32 reg;
-	
+
 	switch(pdev->device) {
 		case PCI_DEVICE_ID_JMICRON_JMB368:
 			break;
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 581cb33..98c1fee 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -89,9 +89,10 @@
 static int ht6560a;			/* HT 6560A on primary 1, secondary 2, both 3 */
 static int ht6560b;			/* HT 6560A on primary 1, secondary 2, both 3 */
 static int opti82c611a;			/* Opti82c611A on primary 1, secondary 2, both 3 */
-static int opti82c46x;		/* Opti 82c465MV present (pri/sec autodetect) */
+static int opti82c46x;			/* Opti 82c465MV present (pri/sec autodetect) */
 static int autospeed;			/* Chip present which snoops speed changes */
 static int pio_mask = 0x1F;		/* PIO range for autospeed devices */
+static int iordy_mask = 0xFFFFFFFF;	/* Use iordy if available */
 
 /**
  *	legacy_set_mode		-	mode setting
@@ -113,6 +114,7 @@
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *dev = &ap->device[i];
 		if (ata_dev_enabled(dev)) {
+			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
 			dev->pio_mode = XFER_PIO_0;
 			dev->xfer_mode = XFER_PIO_0;
 			dev->xfer_shift = ATA_SHIFT_PIO;
@@ -164,14 +166,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer_noirq,
+	.data_xfer	= ata_data_xfer_noirq,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations legacy_port_ops = {
@@ -189,14 +191,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer_noirq,
+	.data_xfer	= ata_data_xfer_noirq,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -257,31 +259,33 @@
 		local_irq_save(flags);
 
 		/* Perform the 32bit I/O synchronization sequence */
-		inb(ap->ioaddr.nsect_addr);
-		inb(ap->ioaddr.nsect_addr);
-		inb(ap->ioaddr.nsect_addr);
+		ioread8(ap->ioaddr.nsect_addr);
+		ioread8(ap->ioaddr.nsect_addr);
+		ioread8(ap->ioaddr.nsect_addr);
 
 		/* Now the data */
 
 		if (write_data)
-			outsl(ap->ioaddr.data_addr, buf, buflen >> 2);
+			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 		else
-			insl(ap->ioaddr.data_addr, buf, buflen >> 2);
+			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 
 		if (unlikely(slop)) {
 			u32 pad;
 			if (write_data) {
 				memcpy(&pad, buf + buflen - slop, slop);
-				outl(le32_to_cpu(pad), ap->ioaddr.data_addr);
+				pad = le32_to_cpu(pad);
+				iowrite32(pad, ap->ioaddr.data_addr);
 			} else {
-				pad = cpu_to_le16(inl(ap->ioaddr.data_addr));
+				pad = ioread32(ap->ioaddr.data_addr);
+				pad = cpu_to_le16(pad);
 				memcpy(buf + buflen - slop, &pad, slop);
 			}
 		}
 		local_irq_restore(flags);
 	}
 	else
-		ata_pio_data_xfer_noirq(adev, buf, buflen, write_data);
+		ata_data_xfer_noirq(adev, buf, buflen, write_data);
 }
 
 static struct ata_port_operations pdc20230_port_ops = {
@@ -303,10 +307,10 @@
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -332,8 +336,8 @@
 	inb(0x3E6);
 	inb(0x3E6);
 
-	outb(recover << 4 | active, ap->ioaddr.device_addr);
-	inb(ap->ioaddr.status_addr);
+	iowrite8(recover << 4 | active, ap->ioaddr.device_addr);
+	ioread8(ap->ioaddr.status_addr);
 }
 
 static struct ata_port_operations ht6560a_port_ops = {
@@ -351,14 +355,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,	/* Check vlb/noirq */
+	.data_xfer	= ata_data_xfer,	/* Check vlb/noirq */
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -387,7 +391,7 @@
 	inb(0x3E6);
 	inb(0x3E6);
 
-	outb(recover << 4 | active, ap->ioaddr.device_addr);
+	iowrite8(recover << 4 | active, ap->ioaddr.device_addr);
 
 	if (adev->class != ATA_DEV_ATA) {
 		u8 rconf = inb(0x3E6);
@@ -396,7 +400,7 @@
 			outb(rconf, 0x3E6);
 		}
 	}
-	inb(ap->ioaddr.status_addr);
+	ioread8(ap->ioaddr.status_addr);
 }
 
 static struct ata_port_operations ht6560b_port_ops = {
@@ -414,14 +418,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,	/* FIXME: Check 32bit and noirq */
+	.data_xfer	= ata_data_xfer,	/* FIXME: Check 32bit and noirq */
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -464,12 +468,12 @@
 	u8 rc;
 
 	/* Enter configuration mode */
-	inw(ap->ioaddr.error_addr);
-	inw(ap->ioaddr.error_addr);
-	outb(3, ap->ioaddr.nsect_addr);
+	ioread16(ap->ioaddr.error_addr);
+	ioread16(ap->ioaddr.error_addr);
+	iowrite8(3, ap->ioaddr.nsect_addr);
 
 	/* Read VLB clock strapping */
-	clock = 1000000000 / khz[inb(ap->ioaddr.lbah_addr) & 0x03];
+	clock = 1000000000 / khz[ioread8(ap->ioaddr.lbah_addr) & 0x03];
 
 	/* Get the timing data in cycles */
 	ata_timing_compute(adev, adev->pio_mode, &t, clock, 1000);
@@ -487,33 +491,33 @@
 	setup = FIT(t.setup, 1, 4) - 1;
 
 	/* Select the right timing bank for write timing */
-	rc = inb(ap->ioaddr.lbal_addr);
+	rc = ioread8(ap->ioaddr.lbal_addr);
 	rc &= 0x7F;
 	rc |= (adev->devno << 7);
-	outb(rc, ap->ioaddr.lbal_addr);
+	iowrite8(rc, ap->ioaddr.lbal_addr);
 
 	/* Write the timings */
-	outb(active << 4 | recover, ap->ioaddr.error_addr);
+	iowrite8(active << 4 | recover, ap->ioaddr.error_addr);
 
 	/* Select the right bank for read timings, also
 	   load the shared timings for address */
-	rc = inb(ap->ioaddr.device_addr);
+	rc = ioread8(ap->ioaddr.device_addr);
 	rc &= 0xC0;
 	rc |= adev->devno;	/* Index select */
 	rc |= (setup << 4) | 0x04;
-	outb(rc, ap->ioaddr.device_addr);
+	iowrite8(rc, ap->ioaddr.device_addr);
 
 	/* Load the read timings */
-	outb(active << 4 | recover, ap->ioaddr.data_addr);
+	iowrite8(active << 4 | recover, ap->ioaddr.data_addr);
 
 	/* Ensure the timing register mode is right */
-	rc = inb (ap->ioaddr.lbal_addr);
+	rc = ioread8(ap->ioaddr.lbal_addr);
 	rc &= 0x73;
 	rc |= 0x84;
-	outb(rc, ap->ioaddr.lbal_addr);
+	iowrite8(rc, ap->ioaddr.lbal_addr);
 
 	/* Exit command mode */
-	outb(0x83,  ap->ioaddr.nsect_addr);
+	iowrite8(0x83,  ap->ioaddr.nsect_addr);
 }
 
 
@@ -532,14 +536,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /*
@@ -563,9 +567,9 @@
 	sysclk = opti_syscfg(0xAC) & 0xC0;	/* BIOS set */
 
 	/* Enter configuration mode */
-	inw(ap->ioaddr.error_addr);
-	inw(ap->ioaddr.error_addr);
-	outb(3, ap->ioaddr.nsect_addr);
+	ioread16(ap->ioaddr.error_addr);
+	ioread16(ap->ioaddr.error_addr);
+	iowrite8(3, ap->ioaddr.nsect_addr);
 
 	/* Read VLB clock strapping */
 	clock = 1000000000 / khz[sysclk];
@@ -586,33 +590,33 @@
 	setup = FIT(t.setup, 1, 4) - 1;
 
 	/* Select the right timing bank for write timing */
-	rc = inb(ap->ioaddr.lbal_addr);
+	rc = ioread8(ap->ioaddr.lbal_addr);
 	rc &= 0x7F;
 	rc |= (adev->devno << 7);
-	outb(rc, ap->ioaddr.lbal_addr);
+	iowrite8(rc, ap->ioaddr.lbal_addr);
 
 	/* Write the timings */
-	outb(active << 4 | recover, ap->ioaddr.error_addr);
+	iowrite8(active << 4 | recover, ap->ioaddr.error_addr);
 
 	/* Select the right bank for read timings, also
 	   load the shared timings for address */
-	rc = inb(ap->ioaddr.device_addr);
+	rc = ioread8(ap->ioaddr.device_addr);
 	rc &= 0xC0;
 	rc |= adev->devno;	/* Index select */
 	rc |= (setup << 4) | 0x04;
-	outb(rc, ap->ioaddr.device_addr);
+	iowrite8(rc, ap->ioaddr.device_addr);
 
 	/* Load the read timings */
-	outb(active << 4 | recover, ap->ioaddr.data_addr);
+	iowrite8(active << 4 | recover, ap->ioaddr.data_addr);
 
 	/* Ensure the timing register mode is right */
-	rc = inb (ap->ioaddr.lbal_addr);
+	rc = ioread8(ap->ioaddr.lbal_addr);
 	rc &= 0x73;
 	rc |= 0x84;
-	outb(rc, ap->ioaddr.lbal_addr);
+	iowrite8(rc, ap->ioaddr.lbal_addr);
 
 	/* Exit command mode */
-	outb(0x83,  ap->ioaddr.nsect_addr);
+	iowrite8(0x83,  ap->ioaddr.nsect_addr);
 
 	/* We need to know this for quad device on the MVB */
 	ap->host->private_data = ap;
@@ -662,14 +666,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= opti82c46x_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 
@@ -689,25 +693,32 @@
 	struct legacy_data *ld = &legacy_data[nr_legacy_host];
 	struct ata_probe_ent ae;
 	struct platform_device *pdev;
-	int ret = -EBUSY;
 	struct ata_port_operations *ops = &legacy_port_ops;
+	void __iomem *io_addr, *ctrl_addr;
 	int pio_modes = pio_mask;
 	u32 mask = (1 << port);
-
-	if (request_region(io, 8, "pata_legacy") == NULL)
-		return -EBUSY;
-	if (request_region(ctrl, 1, "pata_legacy") == NULL)
-		goto fail_io;
+	u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
+	int ret;
 
 	pdev = platform_device_register_simple(DRV_NAME, nr_legacy_host, NULL, 0);
-	if (IS_ERR(pdev)) {
-		ret = PTR_ERR(pdev);
-		goto fail_dev;
-	}
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+
+	ret = -EBUSY;
+	if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL ||
+	    devm_request_region(&pdev->dev, ctrl, 1, "pata_legacy") == NULL)
+		goto fail;
+
+	ret = -ENOMEM;
+	io_addr = devm_ioport_map(&pdev->dev, io, 8);
+	ctrl_addr = devm_ioport_map(&pdev->dev, ctrl, 1);
+	if (!io_addr || !ctrl_addr)
+		goto fail;
 
 	if (ht6560a & mask) {
 		ops = &ht6560a_port_ops;
 		pio_modes = 0x07;
+		iordy = ATA_FLAG_NO_IORDY;
 	}
 	if (ht6560b & mask) {
 		ops = &ht6560b_port_ops;
@@ -743,6 +754,7 @@
 			printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller detected.\n");
 				pio_modes = 0x07;
 			ops = &pdc20230_port_ops;
+			iordy = ATA_FLAG_NO_IORDY;
 			udelay(100);
 			inb(0x1F5);
 		} else {
@@ -760,6 +772,7 @@
 	/* Chip does mode setting by command snooping */
 	if (ops == &legacy_port_ops && (autospeed & mask))
 		ops = &simple_port_ops;
+
 	memset(&ae, 0, sizeof(struct ata_probe_ent));
 	INIT_LIST_HEAD(&ae.node);
 	ae.dev = &pdev->dev;
@@ -769,28 +782,23 @@
 	ae.pio_mask = pio_modes;
 	ae.irq = irq;
 	ae.irq_flags = 0;
-	ae.port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST;
-	ae.port[0].cmd_addr = io;
-	ae.port[0].altstatus_addr = ctrl;
-	ae.port[0].ctl_addr =	ctrl;
+	ae.port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST|iordy;
+	ae.port[0].cmd_addr = io_addr;
+	ae.port[0].altstatus_addr = ctrl_addr;
+	ae.port[0].ctl_addr = ctrl_addr;
 	ata_std_ports(&ae.port[0]);
 	ae.private_data = ld;
 
-	ret = ata_device_add(&ae);
-	if (ret == 0) {
-		ret = -ENODEV;
+	ret = -ENODEV;
+	if (!ata_device_add(&ae))
 		goto fail;
-	}
+
 	legacy_host[nr_legacy_host++] = dev_get_drvdata(&pdev->dev);
 	ld->platform_dev = pdev;
 	return 0;
 
 fail:
 	platform_device_unregister(pdev);
-fail_dev:
-	release_region(ctrl, 1);
-fail_io:
-	release_region(io, 8);
 	return ret;
 }
 
@@ -923,15 +931,11 @@
 
 	for (i = 0; i < nr_legacy_host; i++) {
 		struct legacy_data *ld = &legacy_data[i];
-		struct ata_port *ap =legacy_host[i]->ports[0];
-		unsigned long io = ap->ioaddr.cmd_addr;
-		unsigned long ctrl = ap->ioaddr.ctl_addr;
-		ata_host_remove(legacy_host[i]);
+
+		ata_host_detach(legacy_host[i]);
 		platform_device_unregister(ld->platform_dev);
 		if (ld->timing)
 			release_region(ld->timing, 2);
-		release_region(io, 8);
-		release_region(ctrl, 1);
 	}
 }
 
@@ -947,6 +951,7 @@
 module_param(opti82c611a, int, 0);
 module_param(opti82c46x, int, 0);
 module_param(pio_mask, int, 0);
+module_param(iordy_mask, int, 0);
 
 module_init(legacy_init);
 module_exit(legacy_exit);
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index 1c810ea..13a70ac 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -45,10 +45,10 @@
 	for(i = 0; i <= 0x0F; i++)
 		printk("%02X:%02X ", i, readb(barp + i));
 	printk("\n");
-	
+
 	devices = readl(barp + 0x0C);
 	pci_iounmap(pdev, barp);
-	
+
 	if ((pdev->device == 0x6145) && (ap->port_no == 0) &&
 	    (!(devices & 0x10)))	/* PATA enable ? */
 		return -ENOENT;
@@ -57,7 +57,7 @@
 	switch(ap->port_no)
 	{
 	case 0:
-		if (inb(ap->ioaddr.bmdma_addr + 1) & 1)
+		if (ioread8(ap->ioaddr.bmdma_addr + 1) & 1)
 			ap->cbl = ATA_CBL_PATA40;
 		else
 			ap->cbl = ATA_CBL_PATA80;
@@ -129,16 +129,16 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	/* Timeout handling */
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	/* Generic PATA PCI ATA helpers */
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
new file mode 100644
index 0000000..29e1809
--- /dev/null
+++ b/drivers/ata/pata_mpc52xx.c
@@ -0,0 +1,536 @@
+/*
+ * drivers/ata/pata_mpc52xx.c
+ *
+ * libata driver for the Freescale MPC52xx on-chip IDE interface
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/libata.h>
+
+#include <asm/types.h>
+#include <asm/prom.h>
+#include <asm/of_platform.h>
+#include <asm/mpc52xx.h>
+
+
+#define DRV_NAME	"mpc52xx_ata"
+#define DRV_VERSION	"0.1.0"
+
+
+/* Private structures used by the driver */
+struct mpc52xx_ata_timings {
+	u32	pio1;
+	u32	pio2;
+};
+
+struct mpc52xx_ata_priv {
+	unsigned int			ipb_period;
+	struct mpc52xx_ata __iomem *	ata_regs;
+	int				ata_irq;
+	struct mpc52xx_ata_timings	timings[2];
+	int				csel;
+};
+
+
+/* ATAPI-4 PIO specs (in ns) */
+static const int ataspec_t0[5]    = {600, 383, 240, 180, 120};
+static const int ataspec_t1[5]    = { 70,  50,  30,  30,  25};
+static const int ataspec_t2_8[5]  = {290, 290, 290,  80,  70};
+static const int ataspec_t2_16[5] = {165, 125, 100,  80,  70};
+static const int ataspec_t2i[5]   = {  0,   0,   0,  70,  25};
+static const int ataspec_t4[5]    = { 30,  20,  15,  10,  10};
+static const int ataspec_ta[5]    = { 35,  35,  35,  35,  35};
+
+#define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c)))
+
+
+/* Bit definitions inside the registers */
+#define MPC52xx_ATA_HOSTCONF_SMR	0x80000000UL /* State machine reset */
+#define MPC52xx_ATA_HOSTCONF_FR		0x40000000UL /* FIFO Reset */
+#define MPC52xx_ATA_HOSTCONF_IE		0x02000000UL /* Enable interrupt in PIO */
+#define MPC52xx_ATA_HOSTCONF_IORDY	0x01000000UL /* Drive supports IORDY protocol */
+
+#define MPC52xx_ATA_HOSTSTAT_TIP	0x80000000UL /* Transaction in progress */
+#define MPC52xx_ATA_HOSTSTAT_UREP	0x40000000UL /* UDMA Read Extended Pause */
+#define MPC52xx_ATA_HOSTSTAT_RERR	0x02000000UL /* Read Error */
+#define MPC52xx_ATA_HOSTSTAT_WERR	0x01000000UL /* Write Error */
+
+#define MPC52xx_ATA_FIFOSTAT_EMPTY	0x01 /* FIFO Empty */
+
+#define MPC52xx_ATA_DMAMODE_WRITE	0x01 /* Write DMA */
+#define MPC52xx_ATA_DMAMODE_READ	0x02 /* Read DMA */
+#define MPC52xx_ATA_DMAMODE_UDMA	0x04 /* UDMA enabled */
+#define MPC52xx_ATA_DMAMODE_IE		0x08 /* Enable drive interrupt to CPU in DMA mode */
+#define MPC52xx_ATA_DMAMODE_FE		0x10 /* FIFO Flush enable in Rx mode */
+#define MPC52xx_ATA_DMAMODE_FR		0x20 /* FIFO Reset */
+#define MPC52xx_ATA_DMAMODE_HUT		0x40 /* Host UDMA burst terminate */
+
+
+/* Structure of the hardware registers */
+struct mpc52xx_ata {
+
+	/* Host interface registers */
+	u32 config;		/* ATA + 0x00 Host configuration */
+	u32 host_status;	/* ATA + 0x04 Host controller status */
+	u32 pio1;		/* ATA + 0x08 PIO Timing 1 */
+	u32 pio2;		/* ATA + 0x0c PIO Timing 2 */
+	u32 mdma1;		/* ATA + 0x10 MDMA Timing 1 */
+	u32 mdma2;		/* ATA + 0x14 MDMA Timing 2 */
+	u32 udma1;		/* ATA + 0x18 UDMA Timing 1 */
+	u32 udma2;		/* ATA + 0x1c UDMA Timing 2 */
+	u32 udma3;		/* ATA + 0x20 UDMA Timing 3 */
+	u32 udma4;		/* ATA + 0x24 UDMA Timing 4 */
+	u32 udma5;		/* ATA + 0x28 UDMA Timing 5 */
+	u32 share_cnt;		/* ATA + 0x2c ATA share counter */
+	u32 reserved0[3];
+
+	/* FIFO registers */
+	u32 fifo_data;		/* ATA + 0x3c */
+	u8  fifo_status_frame;	/* ATA + 0x40 */
+	u8  fifo_status;	/* ATA + 0x41 */
+	u16 reserved7[1];
+	u8  fifo_control;	/* ATA + 0x44 */
+	u8  reserved8[5];
+	u16 fifo_alarm;		/* ATA + 0x4a */
+	u16 reserved9;
+	u16 fifo_rdp;		/* ATA + 0x4e */
+	u16 reserved10;
+	u16 fifo_wrp;		/* ATA + 0x52 */
+	u16 reserved11;
+	u16 fifo_lfrdp;		/* ATA + 0x56 */
+	u16 reserved12;
+	u16 fifo_lfwrp;		/* ATA + 0x5a */
+
+	/* Drive TaskFile registers */
+	u8  tf_control;		/* ATA + 0x5c TASKFILE Control/Alt Status */
+	u8  reserved13[3];
+	u16 tf_data;		/* ATA + 0x60 TASKFILE Data */
+	u16 reserved14;
+	u8  tf_features;	/* ATA + 0x64 TASKFILE Features/Error */
+	u8  reserved15[3];
+	u8  tf_sec_count;	/* ATA + 0x68 TASKFILE Sector Count */
+	u8  reserved16[3];
+	u8  tf_sec_num;		/* ATA + 0x6c TASKFILE Sector Number */
+	u8  reserved17[3];
+	u8  tf_cyl_low;		/* ATA + 0x70 TASKFILE Cylinder Low */
+	u8  reserved18[3];
+	u8  tf_cyl_high;	/* ATA + 0x74 TASKFILE Cylinder High */
+	u8  reserved19[3];
+	u8  tf_dev_head;	/* ATA + 0x78 TASKFILE Device/Head */
+	u8  reserved20[3];
+	u8  tf_command;		/* ATA + 0x7c TASKFILE Command/Status */
+	u8  dma_mode;		/* ATA + 0x7d ATA Host DMA Mode configuration */
+	u8  reserved21[2];
+};
+
+
+/* ======================================================================== */
+/* Aux fns                                                                  */
+/* ======================================================================== */
+
+
+/* MPC52xx low level hw control */
+
+static int
+mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio)
+{
+	struct mpc52xx_ata_timings *timing = &priv->timings[dev];
+	unsigned int ipb_period = priv->ipb_period;
+	unsigned int t0, t1, t2_8, t2_16, t2i, t4, ta;
+
+	if ((pio<0) || (pio>4))
+		return -EINVAL;
+
+	t0	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t0[pio]);
+	t1	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t1[pio]);
+	t2_8	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t2_8[pio]);
+	t2_16	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t2_16[pio]);
+	t2i	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t2i[pio]);
+	t4	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t4[pio]);
+	ta	= CALC_CLKCYC(ipb_period, 1000 * ataspec_ta[pio]);
+
+	timing->pio1 = (t0 << 24) | (t2_8 << 16) | (t2_16 << 8) | (t2i);
+	timing->pio2 = (t4 << 24) | (t1 << 16) | (ta << 8);
+
+	return 0;
+}
+
+static void
+mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device)
+{
+	struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+	struct mpc52xx_ata_timings *timing = &priv->timings[device];
+
+	out_be32(&regs->pio1,  timing->pio1);
+	out_be32(&regs->pio2,  timing->pio2);
+	out_be32(&regs->mdma1, 0);
+	out_be32(&regs->mdma2, 0);
+	out_be32(&regs->udma1, 0);
+	out_be32(&regs->udma2, 0);
+	out_be32(&regs->udma3, 0);
+	out_be32(&regs->udma4, 0);
+	out_be32(&regs->udma5, 0);
+
+	priv->csel = device;
+}
+
+static int
+mpc52xx_ata_hw_init(struct mpc52xx_ata_priv *priv)
+{
+	struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+	int tslot;
+
+	/* Clear share_cnt (all sample code do this ...) */
+	out_be32(&regs->share_cnt, 0);
+
+	/* Configure and reset host */
+	out_be32(&regs->config,
+			MPC52xx_ATA_HOSTCONF_IE |
+			MPC52xx_ATA_HOSTCONF_IORDY |
+			MPC52xx_ATA_HOSTCONF_SMR |
+			MPC52xx_ATA_HOSTCONF_FR);
+
+	udelay(10);
+
+	out_be32(&regs->config,
+			MPC52xx_ATA_HOSTCONF_IE |
+			MPC52xx_ATA_HOSTCONF_IORDY);
+
+	/* Set the time slot to 1us */
+	tslot = CALC_CLKCYC(priv->ipb_period, 1000000);
+	out_be32(&regs->share_cnt, tslot << 16 );
+
+	/* Init timings to PIO0 */
+	memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings));
+
+	mpc52xx_ata_compute_pio_timings(priv, 0, 0);
+	mpc52xx_ata_compute_pio_timings(priv, 1, 0);
+
+	mpc52xx_ata_apply_timings(priv, 0);
+
+	return 0;
+}
+
+
+/* ======================================================================== */
+/* libata driver                                                            */
+/* ======================================================================== */
+
+static void
+mpc52xx_ata_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+	int pio, rv;
+
+	pio = adev->pio_mode - XFER_PIO_0;
+
+	rv = mpc52xx_ata_compute_pio_timings(priv, adev->devno, pio);
+
+	if (rv) {
+		printk(KERN_ERR DRV_NAME
+			": Trying to select invalid PIO mode %d\n", pio);
+		return;
+	}
+
+	mpc52xx_ata_apply_timings(priv, adev->devno);
+}
+static void
+mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device)
+{
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+
+	if (device != priv->csel)
+		mpc52xx_ata_apply_timings(priv, device);
+
+	ata_std_dev_select(ap,device);
+}
+
+static void
+mpc52xx_ata_error_handler(struct ata_port *ap)
+{
+	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
+			ata_std_postreset);
+}
+
+
+
+static struct scsi_host_template mpc52xx_ata_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= ATA_DMA_BOUNDARY,
+	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations mpc52xx_ata_port_ops = {
+	.port_disable		= ata_port_disable,
+	.set_piomode		= mpc52xx_ata_set_piomode,
+	.dev_select		= mpc52xx_ata_dev_select,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= mpc52xx_ata_error_handler,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ata_data_xfer,
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
+	.port_start		= ata_port_start,
+};
+
+static struct ata_probe_ent mpc52xx_ata_probe_ent = {
+	.port_ops	= &mpc52xx_ata_port_ops,
+	.sht		= &mpc52xx_ata_sht,
+	.n_ports	= 1,
+	.pio_mask	= 0x1f,		/* Up to PIO4 */
+	.mwdma_mask	= 0x00,		/* No MWDMA   */
+	.udma_mask	= 0x00,		/* No UDMA    */
+	.port_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.irq_flags	= 0,
+};
+
+static int __devinit
+mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv)
+{
+	struct ata_probe_ent *ae = &mpc52xx_ata_probe_ent;
+	struct ata_ioports *aio = &ae->port[0];
+	int rv;
+
+	INIT_LIST_HEAD(&ae->node);
+	ae->dev = dev;
+	ae->irq = priv->ata_irq;
+
+	aio->cmd_addr		= 0;	/* Don't have a classic reg block */
+	aio->altstatus_addr	= &priv->ata_regs->tf_control;
+	aio->ctl_addr		= &priv->ata_regs->tf_control;
+	aio->data_addr		= &priv->ata_regs->tf_data;
+	aio->error_addr		= &priv->ata_regs->tf_features;
+	aio->feature_addr	= &priv->ata_regs->tf_features;
+	aio->nsect_addr		= &priv->ata_regs->tf_sec_count;
+	aio->lbal_addr		= &priv->ata_regs->tf_sec_num;
+	aio->lbam_addr		= &priv->ata_regs->tf_cyl_low;
+	aio->lbah_addr		= &priv->ata_regs->tf_cyl_high;
+	aio->device_addr	= &priv->ata_regs->tf_dev_head;
+	aio->status_addr	= &priv->ata_regs->tf_command;
+	aio->command_addr	= &priv->ata_regs->tf_command;
+
+	ae->private_data = priv;
+
+	rv = ata_device_add(ae);
+
+	return rv ? 0 : -EINVAL;
+}
+
+static struct mpc52xx_ata_priv *
+mpc52xx_ata_remove_one(struct device *dev)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct mpc52xx_ata_priv *priv = host->private_data;
+
+	ata_host_detach(host);
+
+	return priv;
+}
+
+
+/* ======================================================================== */
+/* OF Platform driver                                                       */
+/* ======================================================================== */
+
+static int __devinit
+mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
+{
+	unsigned int ipb_freq;
+	struct resource res_mem;
+	int ata_irq = NO_IRQ;
+	struct mpc52xx_ata __iomem *ata_regs;
+	struct mpc52xx_ata_priv *priv;
+	int rv;
+
+	/* Get ipb frequency */
+	ipb_freq = mpc52xx_find_ipb_freq(op->node);
+	if (!ipb_freq) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Unable to find IPB Bus frequency\n" );
+		return -ENODEV;
+	}
+
+	/* Get IRQ and register */
+	rv = of_address_to_resource(op->node, 0, &res_mem);
+	if (rv) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while parsing device node resource\n" );
+		return rv;
+	}
+
+	ata_irq = irq_of_parse_and_map(op->node, 0);
+	if (ata_irq == NO_IRQ) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while mapping the irq\n");
+		return -EINVAL;
+	}
+
+	/* Request mem region */
+	if (!devm_request_mem_region(&op->dev, res_mem.start,
+				     sizeof(struct mpc52xx_ata), DRV_NAME)) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while requesting mem region\n");
+		rv = -EBUSY;
+		goto err;
+	}
+
+	/* Remap registers */
+	ata_regs = devm_ioremap(&op->dev, res_mem.start,
+				sizeof(struct mpc52xx_ata));
+	if (!ata_regs) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while mapping register set\n");
+		rv = -ENOMEM;
+		goto err;
+	}
+
+	/* Prepare our private structure */
+	priv = devm_kzalloc(&op->dev, sizeof(struct mpc52xx_ata_priv),
+			    GFP_ATOMIC);
+	if (!priv) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while allocating private structure\n");
+		rv = -ENOMEM;
+		goto err;
+	}
+
+	priv->ipb_period = 1000000000 / (ipb_freq / 1000);
+	priv->ata_regs = ata_regs;
+	priv->ata_irq = ata_irq;
+	priv->csel = -1;
+
+	/* Init the hw */
+	rv = mpc52xx_ata_hw_init(priv);
+	if (rv) {
+		printk(KERN_ERR DRV_NAME ": Error during HW init\n");
+		goto err;
+	}
+
+	/* Register ourselves to libata */
+	rv = mpc52xx_ata_init_one(&op->dev, priv);
+	if (rv) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while registering to ATA layer\n");
+		return rv;
+	}
+
+	/* Done */
+	return 0;
+
+	/* Error path */
+err:
+	irq_dispose_mapping(ata_irq);
+	return rv;
+}
+
+static int
+mpc52xx_ata_remove(struct of_device *op)
+{
+	struct mpc52xx_ata_priv *priv;
+
+	priv = mpc52xx_ata_remove_one(&op->dev);
+	irq_dispose_mapping(priv->ata_irq);
+
+	return 0;
+}
+
+
+#ifdef CONFIG_PM
+
+static int
+mpc52xx_ata_suspend(struct of_device *op, pm_message_t state)
+{
+	return 0;	/* FIXME : What to do here ? */
+}
+
+static int
+mpc52xx_ata_resume(struct of_device *op)
+{
+	return 0;	/* FIXME : What to do here ? */
+}
+
+#endif
+
+
+static struct of_device_id mpc52xx_ata_of_match[] = {
+	{
+		.type		= "ata",
+		.compatible	= "mpc5200-ata",
+	},
+	{},
+};
+
+
+static struct of_platform_driver mpc52xx_ata_of_platform_driver = {
+	.owner		= THIS_MODULE,
+	.name		= DRV_NAME,
+	.match_table	= mpc52xx_ata_of_match,
+	.probe		= mpc52xx_ata_probe,
+	.remove		= mpc52xx_ata_remove,
+#ifdef CONFIG_PM
+	.suspend	= mpc52xx_ata_suspend,
+	.resume		= mpc52xx_ata_resume,
+#endif
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+
+/* ======================================================================== */
+/* Module                                                                   */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_ata_init(void)
+{
+	printk(KERN_INFO "ata: MPC52xx IDE/ATA libata driver\n");
+	return of_register_platform_driver(&mpc52xx_ata_of_platform_driver);
+}
+
+static void __exit
+mpc52xx_ata_exit(void)
+{
+	of_unregister_platform_driver(&mpc52xx_ata_of_platform_driver);
+}
+
+module_init(mpc52xx_ata_init);
+module_exit(mpc52xx_ata_exit);
+
+MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
+MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, mpc52xx_ata_of_match);
+MODULE_VERSION(DRV_VERSION);
+
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index 4ccca93..f2e7115 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -35,7 +35,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_mpiix"
-#define DRV_VERSION "0.7.3"
+#define DRV_VERSION "0.7.5"
 
 enum {
 	IDETIM = 0x6C,		/* IDE control register */
@@ -49,12 +49,9 @@
 static int mpiix_pre_reset(struct ata_port *ap)
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-	static const struct pci_bits mpiix_enable_bits[] = {
-		{ 0x6D, 1, 0x80, 0x80 },
-		{ 0x6F, 1, 0x80, 0x80 }
-	};
+	static const struct pci_bits mpiix_enable_bits = { 0x6D, 1, 0x80, 0x80 };
 
-	if (!pci_test_config_bits(pdev, &mpiix_enable_bits[ap->port_no]))
+	if (!pci_test_config_bits(pdev, &mpiix_enable_bits))
 		return -ENOENT;
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
@@ -80,8 +77,8 @@
  *	@adev: ATA device
  *
  *	Called to do the PIO mode setup. The MPIIX allows us to program the
- *	IORDY sample point (2-5 clocks), recovery 1-4 clocks and whether
- *	prefetching or iordy are used.
+ *	IORDY sample point (2-5 clocks), recovery (1-4 clocks) and whether
+ *	prefetching or IORDY are used.
  *
  *	This would get very ugly because we can only program timing for one
  *	device at a time, the other gets PIO0. Fortunately libata calls
@@ -103,18 +100,19 @@
 			    { 2, 3 }, };
 
 	pci_read_config_word(pdev, IDETIM, &idetim);
-	/* Mask the IORDY/TIME/PPE0 bank for this device */
+
+	/* Mask the IORDY/TIME/PPE for this device */
 	if (adev->class == ATA_DEV_ATA)
-		control |= PPE;		/* PPE enable for disk */
+		control |= PPE;		/* Enable prefetch/posting for disk */
 	if (ata_pio_need_iordy(adev))
-		control |= IORDY;	/* IORDY */
-	if (pio > 0)
+		control |= IORDY;
+	if (pio > 1)
 		control |= FTIM;	/* This drive is on the fast timing bank */
 
 	/* Mask out timing and clear both TIME bank selects */
 	idetim &= 0xCCEE;
-	idetim &= ~(0x07  << (2 * adev->devno));
-	idetim |= (control << (2 * adev->devno));
+	idetim &= ~(0x07  << (4 * adev->devno));
+	idetim |= control << (4 * adev->devno);
 
 	idetim |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
 	pci_write_config_word(pdev, IDETIM, idetim);
@@ -188,23 +186,24 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= mpiix_qc_issue_prot,
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	/* Single threaded by the PCI probe logic */
-	static struct ata_probe_ent probe[2];
+	static struct ata_probe_ent probe;
 	static int printed_version;
+	void __iomem *cmd_addr, *ctl_addr;
 	u16 idetim;
-	int enabled;
+	int irq;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
@@ -217,65 +216,49 @@
 	if (!(idetim & ENABLED))
 		return -ENODEV;
 
+	/* See if it's primary or secondary channel... */
+	if (!(idetim & SECONDARY)) {
+		irq = 14;
+		cmd_addr = devm_ioport_map(&dev->dev, 0x1F0, 8);
+		ctl_addr = devm_ioport_map(&dev->dev, 0x3F6, 1);
+	} else {
+		irq = 15;
+		cmd_addr = devm_ioport_map(&dev->dev, 0x170, 8);
+		ctl_addr = devm_ioport_map(&dev->dev, 0x376, 1);
+	}
+
+	if (!cmd_addr || !ctl_addr)
+		return -ENOMEM;
+
 	/* We do our own plumbing to avoid leaking special cases for whacko
 	   ancient hardware into the core code. There are two issues to
 	   worry about.  #1 The chip is a bridge so if in legacy mode and
 	   without BARs set fools the setup.  #2 If you pci_disable_device
 	   the MPIIX your box goes castors up */
 
-	INIT_LIST_HEAD(&probe[0].node);
-	probe[0].dev = pci_dev_to_dev(dev);
-	probe[0].port_ops = &mpiix_port_ops;
-	probe[0].sht = &mpiix_sht;
-	probe[0].pio_mask = 0x1F;
-	probe[0].irq = 14;
-	probe[0].irq_flags = SA_SHIRQ;
-	probe[0].port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
-	probe[0].n_ports = 1;
-	probe[0].port[0].cmd_addr = 0x1F0;
-	probe[0].port[0].ctl_addr = 0x3F6;
-	probe[0].port[0].altstatus_addr = 0x3F6;
+	INIT_LIST_HEAD(&probe.node);
+	probe.dev = pci_dev_to_dev(dev);
+	probe.port_ops = &mpiix_port_ops;
+	probe.sht = &mpiix_sht;
+	probe.pio_mask = 0x1F;
+	probe.irq_flags = IRQF_SHARED;
+	probe.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+	probe.n_ports = 1;
 
-	/* The secondary lurks at different addresses but is otherwise
-	   the same beastie */
-
-	INIT_LIST_HEAD(&probe[1].node);
-	probe[1] = probe[0];
-	probe[1].irq = 15;
-	probe[1].port[0].cmd_addr = 0x170;
-	probe[1].port[0].ctl_addr = 0x376;
-	probe[1].port[0].altstatus_addr = 0x376;
+	probe.irq = irq;
+	probe.port[0].cmd_addr = cmd_addr;
+	probe.port[0].ctl_addr = ctl_addr;
+	probe.port[0].altstatus_addr = ctl_addr;
 
 	/* Let libata fill in the port details */
-	ata_std_ports(&probe[0].port[0]);
-	ata_std_ports(&probe[1].port[0]);
+	ata_std_ports(&probe.port[0]);
 
 	/* Now add the port that is active */
-	enabled = (idetim & SECONDARY) ? 1 : 0;
-
-	if (ata_device_add(&probe[enabled]))
+	if (ata_device_add(&probe))
 		return 0;
 	return -ENODEV;
 }
 
-/**
- *	mpiix_remove_one	-	device unload
- *	@pdev: PCI device being removed
- *
- *	Handle an unplug/unload event for a PCI device. Unload the
- *	PCI driver but do not use the default handler as we *MUST NOT*
- *	disable the device as it has other functions.
- */
-
-static void __devexit mpiix_remove_one(struct pci_dev *pdev)
-{
-	struct device *dev = pci_dev_to_dev(pdev);
-	struct ata_host *host = dev_get_drvdata(dev);
-
-	ata_host_remove(host);
-	dev_set_drvdata(dev, NULL);
-}
-
 static const struct pci_device_id mpiix[] = {
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), },
 
@@ -286,7 +269,7 @@
 	.name 		= DRV_NAME,
 	.id_table	= mpiix,
 	.probe 		= mpiix_init_one,
-	.remove		= mpiix_remove_one,
+	.remove		= ata_pci_remove_one,
 	.suspend	= ata_pci_device_suspend,
 	.resume		= ata_pci_device_resume,
 };
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index cf7fe03..e8393e19 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -89,16 +89,16 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	/* IRQ-related hooks */
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	/* Generic PATA PCI ATA helpers */
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index c3032eb..3d1fa48 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -179,14 +179,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ns87410_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index 10ac3cc..45215aa 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -25,7 +25,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_oldpiix"
-#define DRV_VERSION	"0.5.2"
+#define DRV_VERSION	"0.5.3"
 
 /**
  *	oldpiix_pre_reset		-	probe begin
@@ -94,19 +94,21 @@
 			    { 2, 1 },
 			    { 2, 3 }, };
 
-	if (pio > 2)
-		control |= 1;	/* TIME1 enable */
+	if (pio > 1)
+		control |= 1;	/* TIME */
 	if (ata_pio_need_iordy(adev))
-		control |= 2;	/* IE IORDY */
+		control |= 2;	/* IE */
 
-	/* Intel specifies that the PPE functionality is for disk only */
+	/* Intel specifies that the prefetch/posting is for disk only */
 	if (adev->class == ATA_DEV_ATA)
-		control |= 4;	/* PPE enable */
+		control |= 4;	/* PPE */
 
 	pci_read_config_word(dev, idetm_port, &idetm_data);
 
-	/* Enable PPE, IE and TIME as appropriate. Clear the other
-	   drive timing bits */
+	/*
+	 * Set PPE, IE and TIME as appropriate.
+	 * Clear the other drive's timing bits.
+	 */
 	if (adev->devno == 0) {
 		idetm_data &= 0xCCE0;
 		idetm_data |= control;
@@ -259,14 +261,14 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= oldpiix_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index c2988b0..da1aa14 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -95,18 +95,18 @@
 
 static void opti_write_reg(struct ata_port *ap, u8 val, int reg)
 {
-	unsigned long regio = ap->ioaddr.cmd_addr;
+	void __iomem *regio = ap->ioaddr.cmd_addr;
 
 	/* These 3 unlock the control register access */
-	inw(regio + 1);
-	inw(regio + 1);
-	outb(3, regio + 2);
+	ioread16(regio + 1);
+	ioread16(regio + 1);
+	iowrite8(3, regio + 2);
 
 	/* Do the I/O */
-	outb(val, regio + reg);
+	iowrite8(val, regio + reg);
 
 	/* Relock */
-	outb(0x83, regio + 2);
+	iowrite8(0x83, regio + 2);
 }
 
 /**
@@ -124,7 +124,7 @@
 	struct ata_device *pair = ata_dev_pair(adev);
 	int clock;
 	int pio = adev->pio_mode - XFER_PIO_0;
-	unsigned long regio = ap->ioaddr.cmd_addr;
+	void __iomem *regio = ap->ioaddr.cmd_addr;
 	u8 addr;
 
 	/* Address table precomputed with prefetch off and a DCLK of 2 */
@@ -137,8 +137,8 @@
 		{ 0x58, 0x44, 0x32, 0x22, 0x21 }
 	};
 
-	outb(0xff, regio + 5);
-	clock = inw(regio + 5) & 1;
+	iowrite8(0xff, regio + 5);
+	clock = ioread16(regio + 5) & 1;
 
 	/*
  	 *	As with many controllers the address setup time is shared
@@ -205,14 +205,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 80d111c..d80b36e 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -91,12 +91,12 @@
 
 static void optidma_unlock(struct ata_port *ap)
 {
-	unsigned long regio = ap->ioaddr.cmd_addr;
+	void __iomem *regio = ap->ioaddr.cmd_addr;
 
 	/* These 3 unlock the control register access */
-	inw(regio + 1);
-	inw(regio + 1);
-	outb(3, regio + 2);
+	ioread16(regio + 1);
+	ioread16(regio + 1);
+	iowrite8(3, regio + 2);
 }
 
 /**
@@ -108,10 +108,10 @@
 
 static void optidma_lock(struct ata_port *ap)
 {
-	unsigned long regio = ap->ioaddr.cmd_addr;
+	void __iomem *regio = ap->ioaddr.cmd_addr;
 
 	/* Relock */
-	outb(0x83, regio + 2);
+	iowrite8(0x83, regio + 2);
 }
 
 /**
@@ -133,7 +133,7 @@
 	struct ata_device *pair = ata_dev_pair(adev);
 	int pio = adev->pio_mode - XFER_PIO_0;
 	int dma = adev->dma_mode - XFER_MW_DMA_0;
-	unsigned long regio = ap->ioaddr.cmd_addr;
+	void __iomem *regio = ap->ioaddr.cmd_addr;
 	u8 addr;
 
 	/* Address table precomputed with a DCLK of 2 */
@@ -178,20 +178,20 @@
 
 	/* Commence primary programming sequence */
 	/* First we load the device number into the timing select */
-	outb(adev->devno, regio + MISC_REG);
+	iowrite8(adev->devno, regio + MISC_REG);
 	/* Now we load the data timings into read data/write data */
 	if (mode < XFER_MW_DMA_0) {
-		outb(data_rec_timing[pci_clock][pio], regio + READ_REG);
-		outb(data_rec_timing[pci_clock][pio], regio + WRITE_REG);
+		iowrite8(data_rec_timing[pci_clock][pio], regio + READ_REG);
+		iowrite8(data_rec_timing[pci_clock][pio], regio + WRITE_REG);
 	} else if (mode < XFER_UDMA_0) {
-		outb(dma_data_rec_timing[pci_clock][dma], regio + READ_REG);
-		outb(dma_data_rec_timing[pci_clock][dma], regio + WRITE_REG);
+		iowrite8(dma_data_rec_timing[pci_clock][dma], regio + READ_REG);
+		iowrite8(dma_data_rec_timing[pci_clock][dma], regio + WRITE_REG);
 	}
 	/* Finally we load the address setup into the misc register */
-	outb(addr | adev->devno, regio + MISC_REG);
+	iowrite8(addr | adev->devno, regio + MISC_REG);
 
 	/* Programming sequence complete, timing 0 dev 0, timing 1 dev 1 */
-	outb(0x85, regio + CNTRL_REG);
+	iowrite8(0x85, regio + CNTRL_REG);
 
 	/* Switch back to IDE mode */
 	optidma_lock(ap);
@@ -389,14 +389,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations optiplus_port_ops = {
@@ -424,14 +424,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 9ed7f58..36468ec 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -88,14 +88,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer_noirq,
+	.data_xfer	= ata_data_xfer_noirq,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 #define CS_CHECK(fn, ret) \
@@ -123,6 +123,7 @@
 	cistpl_cftable_entry_t *cfg;
 	int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM;
 	unsigned long io_base, ctl_base;
+	void __iomem *io_addr, *ctl_addr;
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (info == NULL)
@@ -233,10 +234,17 @@
 	CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq));
 	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf));
 
+	/* iomap */
+	ret = -ENOMEM;
+	io_addr = devm_ioport_map(&pdev->dev, io_base, 8);
+	ctl_addr = devm_ioport_map(&pdev->dev, ctl_base, 1);
+	if (!io_addr || !ctl_addr)
+		goto failed;
+
 	/* Success. Disable the IRQ nIEN line, do quirks */
-	outb(0x02, ctl_base);
+	iowrite8(0x02, ctl_addr);
 	if (is_kme)
-		outb(0x81, ctl_base + 0x01);
+		iowrite8(0x81, ctl_addr + 0x01);
 
 	/* FIXME: Could be more ports at base + 0x10 but we only deal with
 	   one right now */
@@ -256,13 +264,14 @@
 	ae.n_ports = 1;
 	ae.pio_mask = 1;		/* ISA so PIO 0 cycles */
 	ae.irq = pdev->irq.AssignedIRQ;
-	ae.irq_flags = SA_SHIRQ;
+	ae.irq_flags = IRQF_SHARED;
 	ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
-	ae.port[0].cmd_addr = io_base;
-	ae.port[0].altstatus_addr = ctl_base;
-	ae.port[0].ctl_addr = ctl_base;
+	ae.port[0].cmd_addr = io_addr;
+	ae.port[0].altstatus_addr = ctl_addr;
+	ae.port[0].ctl_addr = ctl_addr;
 	ata_std_ports(&ae.port[0]);
 
+	ret = -ENODEV;
 	if (ata_device_add(&ae) == 0)
 		goto failed;
 
@@ -298,7 +307,7 @@
 		/* If we have attached the device to the ATA layer, detach it */
 		if (info->ndev) {
 			struct ata_host *host = dev_get_drvdata(dev);
-			ata_host_remove(host);
+			ata_host_detach(host);
 			dev_set_drvdata(dev, NULL);
 		}
 		info->ndev = 0;
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 76dd1c9..6153787 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -33,7 +33,6 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
-#include <asm/io.h>
 
 #define DRV_NAME	"pata_pdc2027x"
 #define DRV_VERSION	"0.74-ac5"
@@ -46,6 +45,8 @@
 #endif
 
 enum {
+	PDC_MMIO_BAR		= 5,
+
 	PDC_UDMA_100		= 0,
 	PDC_UDMA_133		= 1,
 
@@ -62,7 +63,6 @@
 };
 
 static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void pdc2027x_remove_one(struct pci_dev *pdev);
 static void pdc2027x_error_handler(struct ata_port *ap);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
@@ -123,7 +123,7 @@
 	.name			= DRV_NAME,
 	.id_table		= pdc2027x_pci_tbl,
 	.probe			= pdc2027x_init_one,
-	.remove			= __devexit_p(pdc2027x_remove_one),
+	.remove			= ata_pci_remove_one,
 };
 
 static struct scsi_host_template pdc2027x_sht = {
@@ -160,7 +160,7 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
@@ -169,10 +169,10 @@
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_pci_host_stop,
 };
 
 static struct ata_port_operations pdc2027x_pata133_ops = {
@@ -194,7 +194,7 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
@@ -203,10 +203,10 @@
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_pci_host_stop,
 };
 
 static struct ata_port_info pdc2027x_port_info[] = {
@@ -245,7 +245,7 @@
  */
 static inline void __iomem *port_mmio(struct ata_port *ap, unsigned int offset)
 {
-	return ap->host->mmio_base + ap->port_no * 0x100 + offset;
+	return ap->host->iomap[PDC_MMIO_BAR] + ap->port_no * 0x100 + offset;
 }
 
 /**
@@ -526,18 +526,19 @@
 
 static long pdc_read_counter(struct ata_probe_ent *probe_ent)
 {
+	void __iomem *mmio_base = probe_ent->iomap[PDC_MMIO_BAR];
 	long counter;
 	int retry = 1;
 	u32 bccrl, bccrh, bccrlv, bccrhv;
 
 retry:
-	bccrl = readl(probe_ent->mmio_base + PDC_BYTE_COUNT) & 0xffff;
-	bccrh = readl(probe_ent->mmio_base + PDC_BYTE_COUNT + 0x100) & 0xffff;
+	bccrl = readl(mmio_base + PDC_BYTE_COUNT) & 0xffff;
+	bccrh = readl(mmio_base + PDC_BYTE_COUNT + 0x100) & 0xffff;
 	rmb();
 
 	/* Read the counter values again for verification */
-	bccrlv = readl(probe_ent->mmio_base + PDC_BYTE_COUNT) & 0xffff;
-	bccrhv = readl(probe_ent->mmio_base + PDC_BYTE_COUNT + 0x100) & 0xffff;
+	bccrlv = readl(mmio_base + PDC_BYTE_COUNT) & 0xffff;
+	bccrhv = readl(mmio_base + PDC_BYTE_COUNT + 0x100) & 0xffff;
 	rmb();
 
 	counter = (bccrh << 15) | bccrl;
@@ -568,7 +569,7 @@
  */
 static void pdc_adjust_pll(struct ata_probe_ent *probe_ent, long pll_clock, unsigned int board_idx)
 {
-
+	void __iomem *mmio_base = probe_ent->iomap[PDC_MMIO_BAR];
 	u16 pll_ctl;
 	long pll_clock_khz = pll_clock / 1000;
 	long pout_required = board_idx? PDC_133_MHZ:PDC_100_MHZ;
@@ -587,7 +588,7 @@
 	/* Show the current clock value of PLL control register
 	 * (maybe already configured by the firmware)
 	 */
-	pll_ctl = readw(probe_ent->mmio_base + PDC_PLL_CTL);
+	pll_ctl = readw(mmio_base + PDC_PLL_CTL);
 
 	PDPRINTK("pll_ctl[%X]\n", pll_ctl);
 #endif
@@ -627,8 +628,8 @@
 
 	PDPRINTK("Writing pll_ctl[%X]\n", pll_ctl);
 
-	writew(pll_ctl, probe_ent->mmio_base + PDC_PLL_CTL);
-	readw(probe_ent->mmio_base + PDC_PLL_CTL); /* flush */
+	writew(pll_ctl, mmio_base + PDC_PLL_CTL);
+	readw(mmio_base + PDC_PLL_CTL); /* flush */
 
 	/* Wait the PLL circuit to be stable */
 	mdelay(30);
@@ -638,7 +639,7 @@
 	 *  Show the current clock value of PLL control register
 	 * (maybe configured by the firmware)
 	 */
-	pll_ctl = readw(probe_ent->mmio_base + PDC_PLL_CTL);
+	pll_ctl = readw(mmio_base + PDC_PLL_CTL);
 
 	PDPRINTK("pll_ctl[%X]\n", pll_ctl);
 #endif
@@ -654,6 +655,7 @@
  */
 static long pdc_detect_pll_input_clock(struct ata_probe_ent *probe_ent)
 {
+	void __iomem *mmio_base = probe_ent->iomap[PDC_MMIO_BAR];
 	u32 scr;
 	long start_count, end_count;
 	long pll_clock;
@@ -662,10 +664,10 @@
 	start_count = pdc_read_counter(probe_ent);
 
 	/* Start the test mode */
-	scr = readl(probe_ent->mmio_base + PDC_SYS_CTL);
+	scr = readl(mmio_base + PDC_SYS_CTL);
 	PDPRINTK("scr[%X]\n", scr);
-	writel(scr | (0x01 << 14), probe_ent->mmio_base + PDC_SYS_CTL);
-	readl(probe_ent->mmio_base + PDC_SYS_CTL); /* flush */
+	writel(scr | (0x01 << 14), mmio_base + PDC_SYS_CTL);
+	readl(mmio_base + PDC_SYS_CTL); /* flush */
 
 	/* Let the counter run for 100 ms. */
 	mdelay(100);
@@ -674,10 +676,10 @@
 	end_count = pdc_read_counter(probe_ent);
 
 	/* Stop the test mode */
-	scr = readl(probe_ent->mmio_base + PDC_SYS_CTL);
+	scr = readl(mmio_base + PDC_SYS_CTL);
 	PDPRINTK("scr[%X]\n", scr);
-	writel(scr & ~(0x01 << 14), probe_ent->mmio_base + PDC_SYS_CTL);
-	readl(probe_ent->mmio_base + PDC_SYS_CTL); /* flush */
+	writel(scr & ~(0x01 << 14), mmio_base + PDC_SYS_CTL);
+	readl(mmio_base + PDC_SYS_CTL); /* flush */
 
 	/* calculate the input clock in Hz */
 	pll_clock = (start_count - end_count) * 10;
@@ -722,7 +724,7 @@
  * @port: ata ioports to setup
  * @base: base address
  */
-static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base)
+static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base)
 {
 	port->cmd_addr		=
 	port->data_addr		= base;
@@ -755,48 +757,37 @@
 	static int printed_version;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 
-	struct ata_probe_ent *probe_ent = NULL;
-	unsigned long base;
+	struct ata_probe_ent *probe_ent;
 	void __iomem *mmio_base;
 	int rc;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
-	rc = pci_request_regions(pdev, DRV_NAME);
+	rc = pcim_iomap_regions(pdev, 1 << PDC_MMIO_BAR, DRV_NAME);
 	if (rc)
-		goto err_out;
+		return rc;
 
 	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 
 	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 
 	/* Prepare the probe entry */
-	probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
+	probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		return -ENOMEM;
 
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = pci_iomap(pdev, 5, 0);
-	if (!mmio_base) {
-		rc = -ENOMEM;
-		goto err_out_free_ent;
-	}
-
-	base = (unsigned long) mmio_base;
-
 	probe_ent->sht		= pdc2027x_port_info[board_idx].sht;
 	probe_ent->port_flags	= pdc2027x_port_info[board_idx].flags;
 	probe_ent->pio_mask	= pdc2027x_port_info[board_idx].pio_mask;
@@ -805,13 +796,15 @@
 	probe_ent->port_ops	= pdc2027x_port_info[board_idx].port_ops;
 
        	probe_ent->irq = pdev->irq;
-       	probe_ent->irq_flags = SA_SHIRQ;
-	probe_ent->mmio_base = mmio_base;
+       	probe_ent->irq_flags = IRQF_SHARED;
+	probe_ent->iomap = pcim_iomap_table(pdev);
 
-	pdc_ata_setup_port(&probe_ent->port[0], base + 0x17c0);
-	probe_ent->port[0].bmdma_addr = base + 0x1000;
-	pdc_ata_setup_port(&probe_ent->port[1], base + 0x15c0);
-	probe_ent->port[1].bmdma_addr = base + 0x1008;
+	mmio_base = probe_ent->iomap[PDC_MMIO_BAR];
+
+	pdc_ata_setup_port(&probe_ent->port[0], mmio_base + 0x17c0);
+	probe_ent->port[0].bmdma_addr = mmio_base + 0x1000;
+	pdc_ata_setup_port(&probe_ent->port[1], mmio_base + 0x15c0);
+	probe_ent->port[1].bmdma_addr = mmio_base + 0x1008;
 
 	probe_ent->n_ports = 2;
 
@@ -820,32 +813,13 @@
 
 	/* initialize adapter */
 	if (pdc_hardware_init(pdev, probe_ent, board_idx) != 0)
-		goto err_out_free_ent;
+		return -EIO;
 
-	ata_device_add(probe_ent);
-	kfree(probe_ent);
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
 
+	devm_kfree(&pdev->dev, probe_ent);
 	return 0;
-
-err_out_free_ent:
-	kfree(probe_ent);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	pci_disable_device(pdev);
-	return rc;
-}
-
-/**
- * pdc2027x_remove_one - Called to remove a single instance of the
- * adapter.
- *
- * @dev: The PCI device to remove.
- * FIXME: module load/unload not working yet
- */
-static void __devexit pdc2027x_remove_one(struct pci_dev *pdev)
-{
-	ata_pci_remove_one(pdev);
 }
 
 /**
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index ad691b9..6dd6341 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -170,17 +170,17 @@
 	struct ata_taskfile *tf = &qc->tf;
 	int sel66 = ap->port_no ? 0x08: 0x02;
 
-	unsigned long master = ap->host->ports[0]->ioaddr.bmdma_addr;
-	unsigned long clock = master + 0x11;
-	unsigned long atapi_reg = master + 0x20 + (4 * ap->port_no);
+	void __iomem *master = ap->host->ports[0]->ioaddr.bmdma_addr;
+	void __iomem *clock = master + 0x11;
+	void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no);
 
 	u32 len;
 
 	/* Check we keep host level locking here */
 	if (adev->dma_mode >= XFER_UDMA_2)
-		outb(inb(clock) | sel66, clock);
+		iowrite8(ioread8(clock) | sel66, clock);
 	else
-		outb(inb(clock) & ~sel66, clock);
+		iowrite8(ioread8(clock) & ~sel66, clock);
 
 	/* The DMA clocks may have been trashed by a reset. FIXME: make conditional
 	   and move to qc_issue ? */
@@ -189,17 +189,14 @@
 	/* Cases the state machine will not complete correctly without help */
 	if ((tf->flags & ATA_TFLAG_LBA48) ||  tf->protocol == ATA_PROT_ATAPI_DMA)
 	{
-		if (tf->flags & ATA_TFLAG_LBA48)
-			len = qc->nsect * 512;
-		else
-			len = qc->nbytes;
+		len = qc->nbytes;
 
 		if (tf->flags & ATA_TFLAG_WRITE)
 			len |= 0x06000000;
 		else
 			len |= 0x05000000;
 
-		outl(len, atapi_reg);
+		iowrite32(len, atapi_reg);
 	}
 
 	/* Activate DMA */
@@ -222,19 +219,19 @@
 
 	int sel66 = ap->port_no ? 0x08: 0x02;
 	/* The clock bits are in the same register for both channels */
-	unsigned long master = ap->host->ports[0]->ioaddr.bmdma_addr;
-	unsigned long clock = master + 0x11;
-	unsigned long atapi_reg = master + 0x20 + (4 * ap->port_no);
+	void __iomem *master = ap->host->ports[0]->ioaddr.bmdma_addr;
+	void __iomem *clock = master + 0x11;
+	void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no);
 
 	/* Cases the state machine will not complete correctly */
 	if (tf->protocol == ATA_PROT_ATAPI_DMA || ( tf->flags & ATA_TFLAG_LBA48)) {
-		outl(0, atapi_reg);
-		outb(inb(clock) & ~sel66, clock);
+		iowrite32(0, atapi_reg);
+		iowrite8(ioread8(clock) & ~sel66, clock);
 	}
 	/* Check we keep host level locking here */
 	/* Flip back to 33Mhz for PIO */
 	if (adev->dma_mode >= XFER_UDMA_2)
-		outb(inb(clock) & ~sel66, clock);
+		iowrite8(ioread8(clock) & ~sel66, clock);
 
 	ata_bmdma_stop(qc);
 }
@@ -297,14 +294,14 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations pdc2026x_port_ops = {
@@ -331,14 +328,14 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 40ae11c..479a326 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -47,23 +47,6 @@
 	return 0;
 }
 
-static void pata_platform_host_stop(struct ata_host *host)
-{
-	int i;
-
-	/*
-	 * Unmap the bases for MMIO
-	 */
-	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-
-		if (ap->flags & ATA_FLAG_MMIO) {
-			iounmap((void __iomem *)ap->ioaddr.ctl_addr);
-			iounmap((void __iomem *)ap->ioaddr.cmd_addr);
-		}
-	}
-}
-
 static struct scsi_host_template pata_platform_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
@@ -100,14 +83,14 @@
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
-	.data_xfer		= ata_pio_data_xfer_noirq,
+	.data_xfer		= ata_data_xfer_noirq,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= pata_platform_host_stop
 };
 
 static void pata_platform_setup_port(struct ata_ioports *ioaddr,
@@ -153,7 +136,6 @@
 	struct resource *io_res, *ctl_res;
 	struct ata_probe_ent ae;
 	unsigned int mmio;
-	int ret;
 
 	/*
 	 * Simple resource validation ..
@@ -207,46 +189,29 @@
 	 * Handle the MMIO case
 	 */
 	if (mmio) {
-		ae.port_flags |= ATA_FLAG_MMIO;
-
-		ae.port[0].cmd_addr = (unsigned long)ioremap(io_res->start,
+		ae.port[0].cmd_addr = devm_ioremap(&pdev->dev, io_res->start,
 				io_res->end - io_res->start + 1);
-		if (unlikely(!ae.port[0].cmd_addr)) {
-			dev_err(&pdev->dev, "failed to remap IO base\n");
-			return -ENXIO;
-		}
-
-		ae.port[0].ctl_addr = (unsigned long)ioremap(ctl_res->start,
+		ae.port[0].ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start,
 				ctl_res->end - ctl_res->start + 1);
-		if (unlikely(!ae.port[0].ctl_addr)) {
-			dev_err(&pdev->dev, "failed to remap CTL base\n");
-			ret = -ENXIO;
-			goto bad_remap;
-		}
 	} else {
-		ae.port[0].cmd_addr = io_res->start;
-		ae.port[0].ctl_addr = ctl_res->start;
+		ae.port[0].cmd_addr = devm_ioport_map(&pdev->dev, io_res->start,
+				io_res->end - io_res->start + 1);
+		ae.port[0].ctl_addr = devm_ioport_map(&pdev->dev, ctl_res->start,
+				ctl_res->end - ctl_res->start + 1);
+	}
+	if (!ae.port[0].cmd_addr || !ae.port[0].ctl_addr) {
+		dev_err(&pdev->dev, "failed to map IO/CTL base\n");
+		return -ENOMEM;
 	}
 
 	ae.port[0].altstatus_addr = ae.port[0].ctl_addr;
 
 	pata_platform_setup_port(&ae.port[0], pdev->dev.platform_data);
 
-	if (unlikely(ata_device_add(&ae) == 0)) {
-		ret = -ENODEV;
-		goto add_failed;
-	}
+	if (unlikely(ata_device_add(&ae) == 0))
+		return -ENODEV;
 
 	return 0;
-
-add_failed:
-	if (ae.port[0].ctl_addr && mmio)
-		iounmap((void __iomem *)ae.port[0].ctl_addr);
-bad_remap:
-	if (ae.port[0].cmd_addr && mmio)
-		iounmap((void __iomem *)ae.port[0].cmd_addr);
-
-	return ret;
 }
 
 /**
@@ -261,7 +226,7 @@
 	struct device *dev = &pdev->dev;
 	struct ata_host *host = dev_get_drvdata(dev);
 
-	ata_host_remove(host);
+	ata_host_detach(host);
 	dev_set_drvdata(dev, NULL);
 
 	return 0;
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index afc0d99..4362141 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -131,22 +131,24 @@
 
 	if (ata_id_has_dword_io(adev->id)) {
 		if (write_data)
-			outsl(ap->ioaddr.data_addr, buf, buflen >> 2);
+			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 		else
-			insl(ap->ioaddr.data_addr, buf, buflen >> 2);
+			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 
 		if (unlikely(slop)) {
 			u32 pad;
 			if (write_data) {
 				memcpy(&pad, buf + buflen - slop, slop);
-				outl(le32_to_cpu(pad), ap->ioaddr.data_addr);
+				pad = le32_to_cpu(pad);
+				iowrite32(pad, ap->ioaddr.data_addr);
 			} else {
-				pad = cpu_to_le32(inl(ap->ioaddr.data_addr));
+				pad = ioread32(ap->ioaddr.data_addr);
+				pad = cpu_to_le32(pad);
 				memcpy(buf + buflen - slop, &pad, slop);
 			}
 		}
 	} else
-		ata_pio_data_xfer(adev, buf, buflen, write_data);
+		ata_data_xfer(adev, buf, buflen, write_data);
 }
 
 static struct scsi_host_template qdi_sht = {
@@ -189,10 +191,10 @@
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations qdi6580_port_ops = {
@@ -217,10 +219,10 @@
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
@@ -238,10 +240,9 @@
 {
 	struct ata_probe_ent ae;
 	struct platform_device *pdev;
+	void __iomem *io_addr, *ctl_addr;
 	int ret;
 
-	unsigned long ctrl = io + 0x206;
-
 	/*
 	 *	Fill in a probe structure first of all
 	 */
@@ -250,6 +251,12 @@
 	if (IS_ERR(pdev))
 		return PTR_ERR(pdev);
 
+	ret = -ENOMEM;
+	io_addr = devm_ioport_map(&pdev->dev, io, 8);
+	ctl_addr = devm_ioport_map(&pdev->dev, io + 0x206, 1);
+	if (!io_addr || !ctl_addr)
+		goto fail;
+
 	memset(&ae, 0, sizeof(struct ata_probe_ent));
 	INIT_LIST_HEAD(&ae.node);
 	ae.dev = &pdev->dev;
@@ -257,19 +264,21 @@
 	if (type == 6580) {
 		ae.port_ops = &qdi6580_port_ops;
 		ae.pio_mask = 0x1F;
+		ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
 	} else {
 		ae.port_ops = &qdi6500_port_ops;
 		ae.pio_mask = 0x07;	/* Actually PIO3 !IORDY is possible */
+		ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
+				ATA_FLAG_NO_IORDY;
 	}
 
 	ae.sht = &qdi_sht;
 	ae.n_ports = 1;
 	ae.irq = irq;
 	ae.irq_flags = 0;
-	ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
-	ae.port[0].cmd_addr = io;
-	ae.port[0].altstatus_addr = ctrl;
-	ae.port[0].ctl_addr =	ctrl;
+	ae.port[0].cmd_addr = io_addr;
+	ae.port[0].altstatus_addr = ctl_addr;
+	ae.port[0].ctl_addr = ctl_addr;
 	ata_std_ports(&ae.port[0]);
 
 	/*
@@ -282,14 +291,17 @@
 	qdi_data[nr_qdi_host].platform_dev = pdev;
 
 	printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io);
-	ret = ata_device_add(&ae);
-	if (ret == 0) {
-		platform_device_unregister(pdev);
-		return -ENODEV;
-	}
+
+	ret = -ENODEV;
+	if (!ata_device_add(&ae))
+		goto fail;
 
 	qdi_host[nr_qdi_host++] = dev_get_drvdata(&pdev->dev);
 	return 0;
+
+ fail:
+	platform_device_unregister(pdev);
+	return ret;
 }
 
 /**
@@ -382,7 +394,7 @@
 	int i;
 
 	for (i = 0; i < nr_qdi_host; i++) {
-		ata_host_remove(qdi_host[i]);
+		ata_host_detach(qdi_host[i]);
 		/* Free the control resource. The 6580 dual channel has the resources
 		 * claimed as a pair of 2 byte resources so we need no special cases...
 		 */
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index 065541d..0d1e571 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -255,14 +255,14 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= radisys_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index cec0729..71a2bac 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -115,7 +115,7 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.freeze		= ata_bmdma_freeze,
 	.thaw		= ata_bmdma_thaw,
@@ -124,10 +124,10 @@
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int rz1000_fifo_disable(struct pci_dev *pdev)
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index a3b35bc..58e42fb 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -220,14 +220,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= sc1200_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index f02b6a3..ad5b43f 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -218,25 +218,18 @@
 static unsigned long serverworks_csb_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask)
 {
 	const char *p;
-	char model_num[40];
-	int len, i;
+	char model_num[ATA_ID_PROD_LEN + 1];
+	int i;
 
 	/* Disk, UDMA */
 	if (adev->class != ATA_DEV_ATA)
 		return ata_pci_default_filter(ap, adev, mask);
 
 	/* Actually do need to check */
-	ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
-	/* Precuationary - why not do this in the libata core ?? */
+	ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
-	len = strlen(model_num);
-	while ((len > 0) && (model_num[len - 1] == ' ')) {
-		len--;
-		model_num[len] = 0;
-	}
-
-	for(i = 0; (p = csb_bad_ata100[i]) != NULL; i++) {
-		if (!strncmp(p, model_num, len))
+	for (i = 0; (p = csb_bad_ata100[i]) != NULL; i++) {
+		if (!strcmp(p, model_num))
 			mask &= ~(0x1F << ATA_SHIFT_UDMA);
 	}
 	return ata_pci_default_filter(ap, adev, mask);
@@ -355,14 +348,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations serverworks_csb_port_ops = {
@@ -390,14 +383,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int serverworks_fixup_osb4(struct pci_dev *pdev)
@@ -559,7 +552,7 @@
 {
 	/* Force master latency timer to 64 PCI clocks */
 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
-	
+
 	switch (pdev->device)
 	{
 		case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index e8dfd8f..ed79fabe 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -252,14 +252,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
@@ -270,7 +270,7 @@
  *	is powered up on boot and when we resume in case we resumed from RAM.
  *	Returns the final clock settings.
  */
- 
+
 static u8 sil680_init_chip(struct pci_dev *pdev)
 {
 	u32 class_rev	= 0;
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 916cedb3..560103d 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -32,7 +32,9 @@
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 #include <linux/ata.h>
+#include "libata.h"
 
+#undef DRV_NAME		/* already defined in libata.h, for libata-core */
 #define DRV_NAME	"pata_sis"
 #define DRV_VERSION	"0.4.5"
 
@@ -43,6 +45,34 @@
 	   up code later */
 };
 
+struct sis_laptop {
+	u16 device;
+	u16 subvendor;
+	u16 subdevice;
+};
+
+static const struct sis_laptop sis_laptop[] = {
+	/* devid, subvendor, subdev */
+	{ 0x5513, 0x1043, 0x1107 },	/* ASUS A6K */
+	/* end marker */
+	{ 0, }
+};
+
+static int sis_short_ata40(struct pci_dev *dev)
+{
+	const struct sis_laptop *lap = &sis_laptop[0];
+
+	while (lap->device) {
+		if (lap->device == dev->device &&
+		    lap->subvendor == dev->subsystem_vendor &&
+		    lap->subdevice == dev->subsystem_device)
+			return 1;
+		lap++;
+	}
+
+	return 0;
+}
+
 /**
  *	sis_port_base		-	return PCI configuration base for dev
  *	@adev: device
@@ -79,7 +109,7 @@
 
 	/* The top bit of this register is the cable detect bit */
 	pci_read_config_word(pdev, 0x50 + 2 * ap->port_no, &tmp);
-	if (tmp & 0x8000)
+	if ((tmp & 0x8000) && !sis_short_ata40(pdev))
 		ap->cbl = ATA_CBL_PATA40;
 	else
 		ap->cbl = ATA_CBL_PATA80;
@@ -127,7 +157,7 @@
 	/* Older chips keep cable detect in bits 4/5 of reg 0x48 */
 	pci_read_config_byte(pdev, 0x48, &tmp);
 	tmp >>= ap->port_no;
-	if (tmp & 0x10)
+	if ((tmp & 0x10) && !sis_short_ata40(pdev))
 		ap->cbl = ATA_CBL_PATA40;
 	else
 		ap->cbl = ATA_CBL_PATA80;
@@ -573,14 +603,14 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 static const struct ata_port_operations sis_133_early_ops = {
@@ -606,14 +636,14 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 static const struct ata_port_operations sis_100_ops = {
@@ -640,14 +670,14 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 static const struct ata_port_operations sis_66_ops = {
@@ -673,14 +703,14 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 static const struct ata_port_operations sis_old_ops = {
@@ -706,14 +736,14 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 static struct ata_port_info sis_info = {
@@ -753,7 +783,7 @@
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.port_ops	= &sis_66_ops,
 };
-static struct ata_port_info sis_info133 = {
+struct ata_port_info sis_info133 = {
 	.sht		= &sis_sht,
 	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
 	.pio_mask	= 0x1f,	/* pio0-4 */
@@ -768,6 +798,8 @@
 	.port_ops	= &sis_133_early_ops,
 };
 
+/* Privately shared with the SiS180 SATA driver, not for use elsewhere */
+EXPORT_SYMBOL_GPL(sis_info133);
 
 static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)
 {
@@ -847,7 +879,7 @@
 	struct sis_chipset *chipset = NULL;
 
 	static struct sis_chipset sis_chipsets[] = {
-	
+
 		{ 0x0968, &sis_info133 },
 		{ 0x0966, &sis_info133 },
 		{ 0x0965, &sis_info133 },
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index e94f515..96e890f 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -139,13 +139,13 @@
 {
 	switch(adev->dma_mode) {
 		case XFER_MW_DMA_0:
-			sl82c105_configure_piomode(ap, adev, 1);
+			sl82c105_configure_piomode(ap, adev, 0);
 			break;
 		case XFER_MW_DMA_1:
 			sl82c105_configure_piomode(ap, adev, 3);
 			break;
 		case XFER_MW_DMA_2:
-			sl82c105_configure_piomode(ap, adev, 3);
+			sl82c105_configure_piomode(ap, adev, 4);
 			break;
 		default:
 			BUG();
@@ -187,7 +187,9 @@
 {
 	struct ata_port *ap = qc->ap;
 
+	udelay(100);
 	sl82c105_reset_engine(ap);
+	udelay(100);
 
 	/* Set the clocks for DMA */
 	sl82c105_configure_dmamode(ap, qc->dev);
@@ -216,6 +218,7 @@
 
 	ata_bmdma_stop(qc);
 	sl82c105_reset_engine(ap);
+	udelay(100);
 
 	/* This will redo the initial setup of the DMA device to matching
 	   PIO timings */
@@ -262,14 +265,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index a142971..453ab90 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -221,14 +221,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index f0b6c3b..220fcd6 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -334,14 +334,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer,
+	.data_xfer	= ata_data_xfer,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 static struct ata_port_operations via_port_ops_noirq = {
@@ -369,14 +369,14 @@
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
-	.data_xfer	= ata_pio_data_xfer_noirq,
+	.data_xfer	= ata_data_xfer_noirq,
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
@@ -391,11 +391,11 @@
 static void via_config_fifo(struct pci_dev *pdev, unsigned int flags)
 {
 	u8 enable;
-	
+
 	/* 0x40 low bits indicate enabled channels */
 	pci_read_config_byte(pdev, 0x40 , &enable);
 	enable &= 3;
-	
+
 	if (flags & VIA_SET_FIFO) {
 		static const u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20};
 		u8 fifo;
@@ -516,7 +516,7 @@
 
 	/* Initialise the FIFO for the enabled channels. */
 	via_config_fifo(pdev, config->flags);
-	
+
 	/* Clock set up */
 	switch(config->flags & VIA_UDMA) {
 		case VIA_UDMA_NONE:
@@ -575,7 +575,7 @@
 	u32 timing;
 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
 	const struct via_isa_bridge *config = host->private_data;
-	
+
 	via_config_fifo(pdev, config->flags);
 
 	if ((config->flags & VIA_UDMA) == VIA_UDMA_66) {
@@ -590,7 +590,7 @@
 		timing &= ~0x80008;
 		pci_write_config_dword(pdev, 0x50, timing);
 	}
-	return ata_pci_device_resume(pdev);	
+	return ata_pci_device_resume(pdev);
 }
 
 static const struct pci_device_id via[] = {
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
index 5d1f518..0888b4f 100644
--- a/drivers/ata/pata_winbond.c
+++ b/drivers/ata/pata_winbond.c
@@ -5,7 +5,7 @@
  *    Support for the Winbond 83759A when operating in advanced mode.
  *    Multichip mode is not currently supported.
  */
- 
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -69,7 +69,7 @@
 	int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2);
 
 	reg = winbond_readcfg(winbond->config, 0x81);
-	
+
 	/* Get the timing data in cycles */
 	if (reg & 0x40)		/* Fast VLB bus, assume 50MHz */
 		ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
@@ -80,9 +80,9 @@
 	recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F;
 	timing = (active << 4) | recovery;
 	winbond_writecfg(winbond->config, timing, reg);
-	
+
 	/* Load the setup timing */
-	
+
 	reg = 0x35;
 	if (adev->class != ATA_DEV_ATA)
 		reg |= 0x08;	/* FIFO off */
@@ -100,22 +100,24 @@
 
 	if (ata_id_has_dword_io(adev->id)) {
 		if (write_data)
-			outsl(ap->ioaddr.data_addr, buf, buflen >> 2);
+			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 		else
-			insl(ap->ioaddr.data_addr, buf, buflen >> 2);
+			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 
 		if (unlikely(slop)) {
 			u32 pad;
 			if (write_data) {
 				memcpy(&pad, buf + buflen - slop, slop);
-				outl(le32_to_cpu(pad), ap->ioaddr.data_addr);
+				pad = le32_to_cpu(pad);
+				iowrite32(pad, ap->ioaddr.data_addr);
 			} else {
-				pad = cpu_to_le16(inl(ap->ioaddr.data_addr));
+				pad = ioread32(ap->ioaddr.data_addr);
+				pad = cpu_to_le16(pad);
 				memcpy(buf + buflen - slop, &pad, slop);
 			}
 		}
 	} else
-		ata_pio_data_xfer(adev, buf, buflen, write_data);
+		ata_data_xfer(adev, buf, buflen, write_data);
 }
 
 static struct scsi_host_template winbond_sht = {
@@ -158,10 +160,10 @@
 
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
+	.irq_on		= ata_irq_on,
+	.irq_ack	= ata_irq_ack,
 
 	.port_start	= ata_port_start,
-	.port_stop	= ata_port_stop,
-	.host_stop	= ata_host_stop
 };
 
 /**
@@ -194,13 +196,15 @@
 	winbond_writecfg(port, 0x85, reg);
 
 	reg = winbond_readcfg(port, 0x81);
-	
+
 	if (!(reg & 0x03))		/* Disabled */
 		return 0;
 
 	for (i = 0; i < 2 ; i ++) {
+		unsigned long cmd_port = 0x1F0 - (0x80 * i);
+		void __iomem *cmd_addr, *ctl_addr;
 
-		if (reg & (1 << i)) {		
+		if (reg & (1 << i)) {
 			/*
 			 *	Fill in a probe structure first of all
 			 */
@@ -209,6 +213,13 @@
 			if (IS_ERR(pdev))
 				return PTR_ERR(pdev);
 
+			cmd_addr = devm_ioport_map(&pdev->dev, cmd_port, 8);
+			ctl_addr = devm_ioport_map(&pdev->dev, cmd_port + 0x0206, 1);
+			if (!cmd_addr || !ctl_addr) {
+				platform_device_unregister(pdev);
+				return -ENOMEM;
+			}
+
 			memset(&ae, 0, sizeof(struct ata_probe_ent));
 			INIT_LIST_HEAD(&ae.node);
 			ae.dev = &pdev->dev;
@@ -217,14 +228,14 @@
 			ae.pio_mask = 0x1F;
 
 			ae.sht = &winbond_sht;
-	
+
 			ae.n_ports = 1;
 			ae.irq = 14 + i;
 			ae.irq_flags = 0;
 			ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
-			ae.port[0].cmd_addr = 0x1F0 - (0x80 * i);
-			ae.port[0].altstatus_addr = ae.port[0].cmd_addr + 0x0206;
-			ae.port[0].ctl_addr = ae.port[0].altstatus_addr;
+			ae.port[0].cmd_addr = cmd_addr;
+			ae.port[0].altstatus_addr = ctl_addr;
+			ae.port[0].ctl_addr = ctl_addr;
 			ata_std_ports(&ae.port[0]);
 			/*
 			 *	Hook in a private data structure per channel
@@ -257,7 +268,7 @@
 
 	int ct = 0;
 	int i;
-	
+
 	if (probe_winbond == 0)
 		return -ENODEV;
 
@@ -288,7 +299,7 @@
 	int i;
 
 	for (i = 0; i < nr_winbond_host; i++) {
-		ata_host_remove(winbond_host[i]);
+		ata_host_detach(winbond_host[i]);
 		release_region(winbond_data[i].config, 2);
 		platform_device_unregister(winbond_data[i].platform_dev);
 	}
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 90786d7..857ac23 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -39,10 +39,8 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
-#include <asm/io.h>
 #include <linux/libata.h>
 
 #define DRV_NAME	"pdc_adma"
@@ -52,9 +50,15 @@
 #define ADMA_ATA_REGS(base,port_no)	((base) + ((port_no) * 0x40))
 
 /* macro to calculate base address for ADMA regs */
-#define ADMA_REGS(base,port_no)	((base) + 0x80 + ((port_no) * 0x20))
+#define ADMA_REGS(base,port_no)		((base) + 0x80 + ((port_no) * 0x20))
+
+/* macro to obtain addresses from ata_host */
+#define ADMA_HOST_REGS(host,port_no) \
+	ADMA_REGS((host)->iomap[ADMA_MMIO_BAR], port_no)
 
 enum {
+	ADMA_MMIO_BAR		= 4,
+
 	ADMA_PORTS		= 2,
 	ADMA_CPB_BYTES		= 40,
 	ADMA_PRD_BYTES		= LIBATA_MAX_PRD * 16,
@@ -167,9 +171,11 @@
 	.qc_prep		= adma_qc_prep,
 	.qc_issue		= adma_qc_issue,
 	.eng_timeout		= adma_eng_timeout,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.irq_handler		= adma_intr,
 	.irq_clear		= adma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.port_start		= adma_port_start,
 	.port_stop		= adma_port_stop,
 	.host_stop		= adma_host_stop,
@@ -235,11 +241,10 @@
 static void adma_reinit_engine(struct ata_port *ap)
 {
 	struct adma_port_priv *pp = ap->private_data;
-	void __iomem *mmio_base = ap->host->mmio_base;
-	void __iomem *chan = ADMA_REGS(mmio_base, ap->port_no);
+	void __iomem *chan = ADMA_HOST_REGS(ap->host, ap->port_no);
 
 	/* mask/clear ATA interrupts */
-	writeb(ATA_NIEN, (void __iomem *)ap->ioaddr.ctl_addr);
+	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
 	ata_check_status(ap);
 
 	/* reset the ADMA engine */
@@ -263,7 +268,7 @@
 
 static inline void adma_enter_reg_mode(struct ata_port *ap)
 {
-	void __iomem *chan = ADMA_REGS(ap->host->mmio_base, ap->port_no);
+	void __iomem *chan = ADMA_HOST_REGS(ap->host, ap->port_no);
 
 	writew(aPIOMD4, chan + ADMA_CONTROL);
 	readb(chan + ADMA_STATUS);	/* flush */
@@ -410,7 +415,7 @@
 static inline void adma_packet_start(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void __iomem *chan = ADMA_REGS(ap->host->mmio_base, ap->port_no);
+	void __iomem *chan = ADMA_HOST_REGS(ap->host, ap->port_no);
 
 	VPRINTK("ENTER, ap %p\n", ap);
 
@@ -443,13 +448,12 @@
 static inline unsigned int adma_intr_pkt(struct ata_host *host)
 {
 	unsigned int handled = 0, port_no;
-	u8 __iomem *mmio_base = host->mmio_base;
 
 	for (port_no = 0; port_no < host->n_ports; ++port_no) {
 		struct ata_port *ap = host->ports[port_no];
 		struct adma_port_priv *pp;
 		struct ata_queued_cmd *qc;
-		void __iomem *chan = ADMA_REGS(mmio_base, port_no);
+		void __iomem *chan = ADMA_HOST_REGS(host, port_no);
 		u8 status = readb(chan + ADMA_STATUS);
 
 		if (status == 0)
@@ -523,7 +527,7 @@
 	return IRQ_RETVAL(handled);
 }
 
-static void adma_ata_setup_port(struct ata_ioports *port, unsigned long base)
+static void adma_ata_setup_port(struct ata_ioports *port, void __iomem *base)
 {
 	port->cmd_addr		=
 	port->data_addr		= base + 0x000;
@@ -550,48 +554,28 @@
 	if (rc)
 		return rc;
 	adma_enter_reg_mode(ap);
-	rc = -ENOMEM;
-	pp = kzalloc(sizeof(*pp), GFP_KERNEL);
+	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
 	if (!pp)
-		goto err_out;
-	pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
-								GFP_KERNEL);
+		return -ENOMEM;
+	pp->pkt = dmam_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
+				      GFP_KERNEL);
 	if (!pp->pkt)
-		goto err_out_kfree;
+		return -ENOMEM;
 	/* paranoia? */
 	if ((pp->pkt_dma & 7) != 0) {
 		printk("bad alignment for pp->pkt_dma: %08x\n",
 						(u32)pp->pkt_dma);
-		dma_free_coherent(dev, ADMA_PKT_BYTES,
-						pp->pkt, pp->pkt_dma);
-		goto err_out_kfree;
+		return -ENOMEM;
 	}
 	memset(pp->pkt, 0, ADMA_PKT_BYTES);
 	ap->private_data = pp;
 	adma_reinit_engine(ap);
 	return 0;
-
-err_out_kfree:
-	kfree(pp);
-err_out:
-	ata_port_stop(ap);
-	return rc;
 }
 
 static void adma_port_stop(struct ata_port *ap)
 {
-	struct device *dev = ap->host->dev;
-	struct adma_port_priv *pp = ap->private_data;
-
-	adma_reset_engine(ADMA_REGS(ap->host->mmio_base, ap->port_no));
-	if (pp != NULL) {
-		ap->private_data = NULL;
-		if (pp->pkt != NULL)
-			dma_free_coherent(dev, ADMA_PKT_BYTES,
-					pp->pkt, pp->pkt_dma);
-		kfree(pp);
-	}
-	ata_port_stop(ap);
+	adma_reset_engine(ADMA_HOST_REGS(ap->host, ap->port_no));
 }
 
 static void adma_host_stop(struct ata_host *host)
@@ -599,16 +583,14 @@
 	unsigned int port_no;
 
 	for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
-		adma_reset_engine(ADMA_REGS(host->mmio_base, port_no));
-
-	ata_pci_host_stop(host);
+		adma_reset_engine(ADMA_HOST_REGS(host, port_no));
 }
 
 static void adma_host_init(unsigned int chip_id,
 				struct ata_probe_ent *probe_ent)
 {
 	unsigned int port_no;
-	void __iomem *mmio_base = probe_ent->mmio_base;
+	void __iomem *mmio_base = probe_ent->iomap[ADMA_MMIO_BAR];
 
 	/* enable/lock aGO operation */
 	writeb(7, mmio_base + ADMA_MODE_LOCK);
@@ -638,7 +620,7 @@
 }
 
 static int adma_ata_init_one(struct pci_dev *pdev,
-				const struct pci_device_id *ent)
+			     const struct pci_device_id *ent)
 {
 	static int printed_version;
 	struct ata_probe_ent *probe_ent = NULL;
@@ -649,34 +631,25 @@
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
-	rc = pci_request_regions(pdev, DRV_NAME);
+	if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0)
+		return -ENODEV;
+
+	rc = pcim_iomap_regions(pdev, 1 << ADMA_MMIO_BAR, DRV_NAME);
 	if (rc)
-		goto err_out;
-
-	if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
-		rc = -ENODEV;
-		goto err_out_regions;
-	}
-
-	mmio_base = pci_iomap(pdev, 4, 0);
-	if (mmio_base == NULL) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
+		return rc;
+	mmio_base = pcim_iomap_table(pdev)[ADMA_MMIO_BAR];
 
 	rc = adma_set_dma_masks(pdev, mmio_base);
 	if (rc)
-		goto err_out_iounmap;
+		return rc;
 
-	probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
-		goto err_out_iounmap;
-	}
+	probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		return -ENOMEM;
 
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
@@ -690,12 +663,12 @@
 
 	probe_ent->irq		= pdev->irq;
 	probe_ent->irq_flags	= IRQF_SHARED;
-	probe_ent->mmio_base	= mmio_base;
 	probe_ent->n_ports	= ADMA_PORTS;
+	probe_ent->iomap	= pcim_iomap_table(pdev);
 
 	for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
 		adma_ata_setup_port(&probe_ent->port[port_no],
-			ADMA_ATA_REGS((unsigned long)mmio_base, port_no));
+				    ADMA_ATA_REGS(mmio_base, port_no));
 	}
 
 	pci_set_master(pdev);
@@ -703,19 +676,11 @@
 	/* initialize adapter */
 	adma_host_init(board_idx, probe_ent);
 
-	rc = ata_device_add(probe_ent);
-	kfree(probe_ent);
-	if (rc != ADMA_PORTS)
-		goto err_out_iounmap;
-	return 0;
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
 
-err_out_iounmap:
-	pci_iounmap(pdev, mmio_base);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	pci_disable_device(pdev);
-	return rc;
+	devm_kfree(&pdev->dev, probe_ent);
+	return 0;
 }
 
 static int __init adma_ata_init(void)
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
new file mode 100644
index 0000000..31b636f
--- /dev/null
+++ b/drivers/ata/sata_inic162x.c
@@ -0,0 +1,781 @@
+/*
+ * sata_inic162x.c - Driver for Initio 162x SATA controllers
+ *
+ * Copyright 2006  SUSE Linux Products GmbH
+ * Copyright 2006  Tejun Heo <teheo@novell.com>
+ *
+ * This file is released under GPL v2.
+ *
+ * This controller is eccentric and easily locks up if something isn't
+ * right.  Documentation is available at initio's website but it only
+ * documents registers (not programming model).
+ *
+ * - ATA disks work.
+ * - Hotplug works.
+ * - ATAPI read works but burning doesn't.  This thing is really
+ *   peculiar about ATAPI and I couldn't figure out how ATAPI PIO and
+ *   ATAPI DMA WRITE should be programmed.  If you've got a clue, be
+ *   my guest.
+ * - Both STR and STD work.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <linux/blkdev.h>
+#include <scsi/scsi_device.h>
+
+#define DRV_NAME	"sata_inic162x"
+#define DRV_VERSION	"0.1"
+
+enum {
+	MMIO_BAR		= 5,
+
+	NR_PORTS		= 2,
+
+	HOST_CTL		= 0x7c,
+	HOST_STAT		= 0x7e,
+	HOST_IRQ_STAT		= 0xbc,
+	HOST_IRQ_MASK		= 0xbe,
+
+	PORT_SIZE		= 0x40,
+
+	/* registers for ATA TF operation */
+	PORT_TF			= 0x00,
+	PORT_ALT_STAT		= 0x08,
+	PORT_IRQ_STAT		= 0x09,
+	PORT_IRQ_MASK		= 0x0a,
+	PORT_PRD_CTL		= 0x0b,
+	PORT_PRD_ADDR		= 0x0c,
+	PORT_PRD_XFERLEN	= 0x10,
+
+	/* IDMA register */
+	PORT_IDMA_CTL		= 0x14,
+
+	PORT_SCR		= 0x20,
+
+	/* HOST_CTL bits */
+	HCTL_IRQOFF		= (1 << 8),  /* global IRQ off */
+	HCTL_PWRDWN		= (1 << 13), /* power down PHYs */
+	HCTL_SOFTRST		= (1 << 13), /* global reset (no phy reset) */
+	HCTL_RPGSEL		= (1 << 15), /* register page select */
+
+	HCTL_KNOWN_BITS		= HCTL_IRQOFF | HCTL_PWRDWN | HCTL_SOFTRST |
+				  HCTL_RPGSEL,
+
+	/* HOST_IRQ_(STAT|MASK) bits */
+	HIRQ_PORT0		= (1 << 0),
+	HIRQ_PORT1		= (1 << 1),
+	HIRQ_SOFT		= (1 << 14),
+	HIRQ_GLOBAL		= (1 << 15), /* STAT only */
+
+	/* PORT_IRQ_(STAT|MASK) bits */
+	PIRQ_OFFLINE		= (1 << 0),  /* device unplugged */
+	PIRQ_ONLINE		= (1 << 1),  /* device plugged */
+	PIRQ_COMPLETE		= (1 << 2),  /* completion interrupt */
+	PIRQ_FATAL		= (1 << 3),  /* fatal error */
+	PIRQ_ATA		= (1 << 4),  /* ATA interrupt */
+	PIRQ_REPLY		= (1 << 5),  /* reply FIFO not empty */
+	PIRQ_PENDING		= (1 << 7),  /* port IRQ pending (STAT only) */
+
+	PIRQ_ERR		= PIRQ_OFFLINE | PIRQ_ONLINE | PIRQ_FATAL,
+
+	PIRQ_MASK_DMA_READ	= PIRQ_REPLY | PIRQ_ATA,
+	PIRQ_MASK_OTHER		= PIRQ_REPLY | PIRQ_COMPLETE,
+	PIRQ_MASK_FREEZE	= 0xff,
+
+	/* PORT_PRD_CTL bits */
+	PRD_CTL_START		= (1 << 0),
+	PRD_CTL_WR		= (1 << 3),
+	PRD_CTL_DMAEN		= (1 << 7),  /* DMA enable */
+
+	/* PORT_IDMA_CTL bits */
+	IDMA_CTL_RST_ATA	= (1 << 2),  /* hardreset ATA bus */
+	IDMA_CTL_RST_IDMA	= (1 << 5),  /* reset IDMA machinary */
+	IDMA_CTL_GO		= (1 << 7),  /* IDMA mode go */
+	IDMA_CTL_ATA_NIEN	= (1 << 8),  /* ATA IRQ disable */
+};
+
+struct inic_host_priv {
+	u16	cached_hctl;
+};
+
+struct inic_port_priv {
+	u8	dfl_prdctl;
+	u8	cached_prdctl;
+	u8	cached_pirq_mask;
+};
+
+static int inic_slave_config(struct scsi_device *sdev)
+{
+	/* This controller is braindamaged.  dma_boundary is 0xffff
+	 * like others but it will lock up the whole machine HARD if
+	 * 65536 byte PRD entry is fed.  Reduce maximum segment size.
+	 */
+	blk_queue_max_segment_size(sdev->request_queue, 65536 - 512);
+
+	return ata_scsi_slave_config(sdev);
+}
+
+static struct scsi_host_template inic_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= ATA_DMA_BOUNDARY,
+	.slave_configure	= inic_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
+	.bios_param		= ata_std_bios_param,
+	.suspend		= ata_scsi_device_suspend,
+	.resume			= ata_scsi_device_resume,
+};
+
+static const int scr_map[] = {
+	[SCR_STATUS]	= 0,
+	[SCR_ERROR]	= 1,
+	[SCR_CONTROL]	= 2,
+};
+
+static void __iomem * inic_port_base(struct ata_port *ap)
+{
+	return ap->host->iomap[MMIO_BAR] + ap->port_no * PORT_SIZE;
+}
+
+static void __inic_set_pirq_mask(struct ata_port *ap, u8 mask)
+{
+	void __iomem *port_base = inic_port_base(ap);
+	struct inic_port_priv *pp = ap->private_data;
+
+	writeb(mask, port_base + PORT_IRQ_MASK);
+	pp->cached_pirq_mask = mask;
+}
+
+static void inic_set_pirq_mask(struct ata_port *ap, u8 mask)
+{
+	struct inic_port_priv *pp = ap->private_data;
+
+	if (pp->cached_pirq_mask != mask)
+		__inic_set_pirq_mask(ap, mask);
+}
+
+static void inic_reset_port(void __iomem *port_base)
+{
+	void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
+	u16 ctl;
+
+	ctl = readw(idma_ctl);
+	ctl &= ~(IDMA_CTL_RST_IDMA | IDMA_CTL_ATA_NIEN | IDMA_CTL_GO);
+
+	/* mask IRQ and assert reset */
+	writew(ctl | IDMA_CTL_RST_IDMA | IDMA_CTL_ATA_NIEN, idma_ctl);
+	readw(idma_ctl); /* flush */
+
+	/* give it some time */
+	msleep(1);
+
+	/* release reset */
+	writew(ctl | IDMA_CTL_ATA_NIEN, idma_ctl);
+
+	/* clear irq */
+	writeb(0xff, port_base + PORT_IRQ_STAT);
+
+	/* reenable ATA IRQ, turn off IDMA mode */
+	writew(ctl, idma_ctl);
+}
+
+static u32 inic_scr_read(struct ata_port *ap, unsigned sc_reg)
+{
+	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+	void __iomem *addr;
+	u32 val;
+
+	if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
+		return 0xffffffffU;
+
+	addr = scr_addr + scr_map[sc_reg] * 4;
+	val = readl(scr_addr + scr_map[sc_reg] * 4);
+
+	/* this controller has stuck DIAG.N, ignore it */
+	if (sc_reg == SCR_ERROR)
+		val &= ~SERR_PHYRDY_CHG;
+	return val;
+}
+
+static void inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+{
+	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+	void __iomem *addr;
+
+	if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
+		return;
+
+	addr = scr_addr + scr_map[sc_reg] * 4;
+	writel(val, scr_addr + scr_map[sc_reg] * 4);
+}
+
+/*
+ * In TF mode, inic162x is very similar to SFF device.  TF registers
+ * function the same.  DMA engine behaves similary using the same PRD
+ * format as BMDMA but different command register, interrupt and event
+ * notification methods are used.  The following inic_bmdma_*()
+ * functions do the impedance matching.
+ */
+static void inic_bmdma_setup(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct inic_port_priv *pp = ap->private_data;
+	void __iomem *port_base = inic_port_base(ap);
+	int rw = qc->tf.flags & ATA_TFLAG_WRITE;
+
+	/* make sure device sees PRD table writes */
+	wmb();
+
+	/* load transfer length */
+	writel(qc->nbytes, port_base + PORT_PRD_XFERLEN);
+
+	/* turn on DMA and specify data direction */
+	pp->cached_prdctl = pp->dfl_prdctl | PRD_CTL_DMAEN;
+	if (!rw)
+		pp->cached_prdctl |= PRD_CTL_WR;
+	writeb(pp->cached_prdctl, port_base + PORT_PRD_CTL);
+
+	/* issue r/w command */
+	ap->ops->exec_command(ap, &qc->tf);
+}
+
+static void inic_bmdma_start(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct inic_port_priv *pp = ap->private_data;
+	void __iomem *port_base = inic_port_base(ap);
+
+	/* start host DMA transaction */
+	pp->cached_prdctl |= PRD_CTL_START;
+	writeb(pp->cached_prdctl, port_base + PORT_PRD_CTL);
+}
+
+static void inic_bmdma_stop(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct inic_port_priv *pp = ap->private_data;
+	void __iomem *port_base = inic_port_base(ap);
+
+	/* stop DMA engine */
+	writeb(pp->dfl_prdctl, port_base + PORT_PRD_CTL);
+}
+
+static u8 inic_bmdma_status(struct ata_port *ap)
+{
+	/* event is already verified by the interrupt handler */
+	return ATA_DMA_INTR;
+}
+
+static void inic_irq_clear(struct ata_port *ap)
+{
+	/* noop */
+}
+
+static void inic_host_intr(struct ata_port *ap)
+{
+	void __iomem *port_base = inic_port_base(ap);
+	struct ata_eh_info *ehi = &ap->eh_info;
+	u8 irq_stat;
+
+	/* fetch and clear irq */
+	irq_stat = readb(port_base + PORT_IRQ_STAT);
+	writeb(irq_stat, port_base + PORT_IRQ_STAT);
+
+	if (likely(!(irq_stat & PIRQ_ERR))) {
+		struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+
+		if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
+			ata_chk_status(ap);	/* clear ATA interrupt */
+			return;
+		}
+
+		if (likely(ata_host_intr(ap, qc)))
+			return;
+
+		ata_chk_status(ap);	/* clear ATA interrupt */
+		ata_port_printk(ap, KERN_WARNING, "unhandled "
+				"interrupt, irq_stat=%x\n", irq_stat);
+		return;
+	}
+
+	/* error */
+	ata_ehi_push_desc(ehi, "irq_stat=0x%x", irq_stat);
+
+	if (irq_stat & (PIRQ_OFFLINE | PIRQ_ONLINE)) {
+		ata_ehi_hotplugged(ehi);
+		ata_port_freeze(ap);
+	} else
+		ata_port_abort(ap);
+}
+
+static irqreturn_t inic_interrupt(int irq, void *dev_instance)
+{
+	struct ata_host *host = dev_instance;
+	void __iomem *mmio_base = host->iomap[MMIO_BAR];
+	u16 host_irq_stat;
+	int i, handled = 0;;
+
+	host_irq_stat = readw(mmio_base + HOST_IRQ_STAT);
+
+	if (unlikely(!(host_irq_stat & HIRQ_GLOBAL)))
+		goto out;
+
+	spin_lock(&host->lock);
+
+	for (i = 0; i < NR_PORTS; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		if (!(host_irq_stat & (HIRQ_PORT0 << i)))
+			continue;
+
+		if (likely(ap && !(ap->flags & ATA_FLAG_DISABLED))) {
+			inic_host_intr(ap);
+			handled++;
+		} else {
+			if (ata_ratelimit())
+				dev_printk(KERN_ERR, host->dev, "interrupt "
+					   "from disabled port %d (0x%x)\n",
+					   i, host_irq_stat);
+		}
+	}
+
+	spin_unlock(&host->lock);
+
+ out:
+	return IRQ_RETVAL(handled);
+}
+
+static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	/* ATA IRQ doesn't wait for DMA transfer completion and vice
+	 * versa.  Mask IRQ selectively to detect command completion.
+	 * Without it, ATA DMA read command can cause data corruption.
+	 *
+	 * Something similar might be needed for ATAPI writes.  I
+	 * tried a lot of combinations but couldn't find the solution.
+	 */
+	if (qc->tf.protocol == ATA_PROT_DMA &&
+	    !(qc->tf.flags & ATA_TFLAG_WRITE))
+		inic_set_pirq_mask(ap, PIRQ_MASK_DMA_READ);
+	else
+		inic_set_pirq_mask(ap, PIRQ_MASK_OTHER);
+
+	/* Issuing a command to yet uninitialized port locks up the
+	 * controller.  Most of the time, this happens for the first
+	 * command after reset which are ATA and ATAPI IDENTIFYs.
+	 * Fast fail if stat is 0x7f or 0xff for those commands.
+	 */
+	if (unlikely(qc->tf.command == ATA_CMD_ID_ATA ||
+		     qc->tf.command == ATA_CMD_ID_ATAPI)) {
+		u8 stat = ata_chk_status(ap);
+		if (stat == 0x7f || stat == 0xff)
+			return AC_ERR_HSM;
+	}
+
+	return ata_qc_issue_prot(qc);
+}
+
+static void inic_freeze(struct ata_port *ap)
+{
+	void __iomem *port_base = inic_port_base(ap);
+
+	__inic_set_pirq_mask(ap, PIRQ_MASK_FREEZE);
+
+	ata_chk_status(ap);
+	writeb(0xff, port_base + PORT_IRQ_STAT);
+
+	readb(port_base + PORT_IRQ_STAT); /* flush */
+}
+
+static void inic_thaw(struct ata_port *ap)
+{
+	void __iomem *port_base = inic_port_base(ap);
+
+	ata_chk_status(ap);
+	writeb(0xff, port_base + PORT_IRQ_STAT);
+
+	__inic_set_pirq_mask(ap, PIRQ_MASK_OTHER);
+
+	readb(port_base + PORT_IRQ_STAT); /* flush */
+}
+
+/*
+ * SRST and SControl hardreset don't give valid signature on this
+ * controller.  Only controller specific hardreset mechanism works.
+ */
+static int inic_hardreset(struct ata_port *ap, unsigned int *class)
+{
+	void __iomem *port_base = inic_port_base(ap);
+	void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
+	const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context);
+	u16 val;
+	int rc;
+
+	/* hammer it into sane state */
+	inic_reset_port(port_base);
+
+	val = readw(idma_ctl);
+	writew(val | IDMA_CTL_RST_ATA, idma_ctl);
+	readw(idma_ctl);	/* flush */
+	msleep(1);
+	writew(val & ~IDMA_CTL_RST_ATA, idma_ctl);
+
+	rc = sata_phy_resume(ap, timing);
+	if (rc) {
+		ata_port_printk(ap, KERN_WARNING, "failed to resume "
+				"link after reset (errno=%d)\n", rc);
+		return rc;
+	}
+
+	*class = ATA_DEV_NONE;
+	if (ata_port_online(ap)) {
+		struct ata_taskfile tf;
+
+		/* wait a while before checking status */
+		msleep(150);
+
+		if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
+			ata_port_printk(ap, KERN_WARNING,
+					"device busy after hardreset\n");
+			return -EIO;
+		}
+
+		ata_tf_read(ap, &tf);
+		*class = ata_dev_classify(&tf);
+		if (*class == ATA_DEV_UNKNOWN)
+			*class = ATA_DEV_NONE;
+	}
+
+	return 0;
+}
+
+static void inic_error_handler(struct ata_port *ap)
+{
+	void __iomem *port_base = inic_port_base(ap);
+	struct inic_port_priv *pp = ap->private_data;
+	unsigned long flags;
+
+	/* reset PIO HSM and stop DMA engine */
+	inic_reset_port(port_base);
+
+	spin_lock_irqsave(ap->lock, flags);
+	ap->hsm_task_state = HSM_ST_IDLE;
+	writeb(pp->dfl_prdctl, port_base + PORT_PRD_CTL);
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	/* PIO and DMA engines have been stopped, perform recovery */
+	ata_do_eh(ap, ata_std_prereset, NULL, inic_hardreset,
+		  ata_std_postreset);
+}
+
+static void inic_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+	/* make DMA engine forget about the failed command */
+	if (qc->err_mask)
+		inic_reset_port(inic_port_base(qc->ap));
+}
+
+static void inic_dev_config(struct ata_port *ap, struct ata_device *dev)
+{
+	/* inic can only handle upto LBA28 max sectors */
+	if (dev->max_sectors > ATA_MAX_SECTORS)
+		dev->max_sectors = ATA_MAX_SECTORS;
+}
+
+static void init_port(struct ata_port *ap)
+{
+	void __iomem *port_base = inic_port_base(ap);
+
+	/* Setup PRD address */
+	writel(ap->prd_dma, port_base + PORT_PRD_ADDR);
+}
+
+static int inic_port_resume(struct ata_port *ap)
+{
+	init_port(ap);
+	return 0;
+}
+
+static int inic_port_start(struct ata_port *ap)
+{
+	void __iomem *port_base = inic_port_base(ap);
+	struct inic_port_priv *pp;
+	u8 tmp;
+	int rc;
+
+	/* alloc and initialize private data */
+	pp = devm_kzalloc(ap->host->dev, sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
+	ap->private_data = pp;
+
+	/* default PRD_CTL value, DMAEN, WR and START off */
+	tmp = readb(port_base + PORT_PRD_CTL);
+	tmp &= ~(PRD_CTL_DMAEN | PRD_CTL_WR | PRD_CTL_START);
+	pp->dfl_prdctl = tmp;
+
+	/* Alloc resources */
+	rc = ata_port_start(ap);
+	if (rc) {
+		kfree(pp);
+		return rc;
+	}
+
+	init_port(ap);
+
+	return 0;
+}
+
+static struct ata_port_operations inic_port_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
+
+	.scr_read		= inic_scr_read,
+	.scr_write		= inic_scr_write,
+
+	.bmdma_setup		= inic_bmdma_setup,
+	.bmdma_start		= inic_bmdma_start,
+	.bmdma_stop		= inic_bmdma_stop,
+	.bmdma_status		= inic_bmdma_status,
+
+	.irq_handler		= inic_interrupt,
+	.irq_clear		= inic_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
+
+	.qc_prep	 	= ata_qc_prep,
+	.qc_issue		= inic_qc_issue,
+	.data_xfer		= ata_data_xfer,
+
+	.freeze			= inic_freeze,
+	.thaw			= inic_thaw,
+	.error_handler		= inic_error_handler,
+	.post_internal_cmd	= inic_post_internal_cmd,
+	.dev_config		= inic_dev_config,
+
+	.port_resume		= inic_port_resume,
+
+	.port_start		= inic_port_start,
+};
+
+static struct ata_port_info inic_port_info = {
+	.sht			= &inic_sht,
+	/* For some reason, ATA_PROT_ATAPI is broken on this
+	 * controller, and no, PIO_POLLING does't fix it.  It somehow
+	 * manages to report the wrong ireason and ignoring ireason
+	 * results in machine lock up.  Tell libata to always prefer
+	 * DMA.
+	 */
+	.flags			= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
+	.pio_mask		= 0x1f,	/* pio0-4 */
+	.mwdma_mask		= 0x07, /* mwdma0-2 */
+	.udma_mask		= 0x7f,	/* udma0-6 */
+	.port_ops		= &inic_port_ops
+};
+
+static int init_controller(void __iomem *mmio_base, u16 hctl)
+{
+	int i;
+	u16 val;
+
+	hctl &= ~HCTL_KNOWN_BITS;
+
+	/* Soft reset whole controller.  Spec says reset duration is 3
+	 * PCI clocks, be generous and give it 10ms.
+	 */
+	writew(hctl | HCTL_SOFTRST, mmio_base + HOST_CTL);
+	readw(mmio_base + HOST_CTL); /* flush */
+
+	for (i = 0; i < 10; i++) {
+		msleep(1);
+		val = readw(mmio_base + HOST_CTL);
+		if (!(val & HCTL_SOFTRST))
+			break;
+	}
+
+	if (val & HCTL_SOFTRST)
+		return -EIO;
+
+	/* mask all interrupts and reset ports */
+	for (i = 0; i < NR_PORTS; i++) {
+		void __iomem *port_base = mmio_base + i * PORT_SIZE;
+
+		writeb(0xff, port_base + PORT_IRQ_MASK);
+		inic_reset_port(port_base);
+	}
+
+	/* port IRQ is masked now, unmask global IRQ */
+	writew(hctl & ~HCTL_IRQOFF, mmio_base + HOST_CTL);
+	val = readw(mmio_base + HOST_IRQ_MASK);
+	val &= ~(HIRQ_PORT0 | HIRQ_PORT1);
+	writew(val, mmio_base + HOST_IRQ_MASK);
+
+	return 0;
+}
+
+static int inic_pci_device_resume(struct pci_dev *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct inic_host_priv *hpriv = host->private_data;
+	void __iomem *mmio_base = host->iomap[MMIO_BAR];
+	int rc;
+
+	ata_pci_device_do_resume(pdev);
+
+	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+		printk("XXX\n");
+		rc = init_controller(mmio_base, hpriv->cached_hctl);
+		if (rc)
+			return rc;
+	}
+
+	ata_host_resume(host);
+
+	return 0;
+}
+
+static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version;
+	struct ata_port_info *pinfo = &inic_port_info;
+	struct ata_probe_ent *probe_ent;
+	struct inic_host_priv *hpriv;
+	void __iomem * const *iomap;
+	int i, rc;
+
+	if (!printed_version++)
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+	rc = pcim_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		return rc;
+
+	rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);
+	if (rc)
+		return rc;
+	iomap = pcim_iomap_table(pdev);
+
+	/* Set dma_mask.  This devices doesn't support 64bit addressing. */
+	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (rc) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "32-bit DMA enable failed\n");
+		return rc;
+	}
+
+	rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+	if (rc) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "32-bit consistent DMA enable failed\n");
+		return rc;
+	}
+
+	probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
+	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
+	if (!probe_ent || !hpriv)
+		return -ENOMEM;
+
+	probe_ent->dev = &pdev->dev;
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	probe_ent->sht			= pinfo->sht;
+	probe_ent->port_flags		= pinfo->flags;
+	probe_ent->pio_mask		= pinfo->pio_mask;
+	probe_ent->mwdma_mask		= pinfo->mwdma_mask;
+	probe_ent->udma_mask		= pinfo->udma_mask;
+	probe_ent->port_ops		= pinfo->port_ops;
+	probe_ent->n_ports		= NR_PORTS;
+
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = IRQF_SHARED;
+
+	probe_ent->iomap = iomap;
+
+	for (i = 0; i < NR_PORTS; i++) {
+		struct ata_ioports *port = &probe_ent->port[i];
+		void __iomem *port_base = iomap[MMIO_BAR] + i * PORT_SIZE;
+
+		port->cmd_addr = iomap[2 * i];
+		port->altstatus_addr =
+		port->ctl_addr = (void __iomem *)
+			((unsigned long)iomap[2 * i + 1] | ATA_PCI_CTL_OFS);
+		port->scr_addr = port_base + PORT_SCR;
+
+		ata_std_ports(port);
+	}
+
+	probe_ent->private_data = hpriv;
+	hpriv->cached_hctl = readw(iomap[MMIO_BAR] + HOST_CTL);
+
+	rc = init_controller(iomap[MMIO_BAR], hpriv->cached_hctl);
+	if (rc) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "failed to initialize controller\n");
+		return rc;
+	}
+
+	pci_set_master(pdev);
+
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
+
+	devm_kfree(&pdev->dev, probe_ent);
+
+	return 0;
+}
+
+static const struct pci_device_id inic_pci_tbl[] = {
+	{ PCI_VDEVICE(INIT, 0x1622), },
+	{ },
+};
+
+static struct pci_driver inic_pci_driver = {
+	.name 		= DRV_NAME,
+	.id_table	= inic_pci_tbl,
+	.suspend	= ata_pci_device_suspend,
+	.resume		= inic_pci_device_resume,
+	.probe 		= inic_init_one,
+	.remove		= ata_pci_remove_one,
+};
+
+static int __init inic_init(void)
+{
+	return pci_register_driver(&inic_pci_driver);
+}
+
+static void __exit inic_exit(void)
+{
+	pci_unregister_driver(&inic_pci_driver);
+}
+
+MODULE_AUTHOR("Tejun Heo");
+MODULE_DESCRIPTION("low-level driver for Initio 162x SATA");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(pci, inic_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(inic_init);
+module_exit(inic_exit);
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index aae0b52..d689df5 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -28,13 +28,11 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
-#include <asm/io.h>
 
 #define DRV_NAME	"sata_mv"
 #define DRV_VERSION	"0.7"
@@ -342,7 +340,6 @@
 static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
 static void mv_phy_reset(struct ata_port *ap);
 static void __mv_phy_reset(struct ata_port *ap, int can_sleep);
-static void mv_host_stop(struct ata_host *host);
 static int mv_port_start(struct ata_port *ap);
 static void mv_port_stop(struct ata_port *ap);
 static void mv_qc_prep(struct ata_queued_cmd *qc);
@@ -406,19 +403,20 @@
 
 	.qc_prep		= mv_qc_prep,
 	.qc_issue		= mv_qc_issue,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.eng_timeout		= mv_eng_timeout,
 
 	.irq_handler		= mv_interrupt,
 	.irq_clear		= mv_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.scr_read		= mv5_scr_read,
 	.scr_write		= mv5_scr_write,
 
 	.port_start		= mv_port_start,
 	.port_stop		= mv_port_stop,
-	.host_stop		= mv_host_stop,
 };
 
 static const struct ata_port_operations mv6_ops = {
@@ -434,19 +432,20 @@
 
 	.qc_prep		= mv_qc_prep,
 	.qc_issue		= mv_qc_issue,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.eng_timeout		= mv_eng_timeout,
 
 	.irq_handler		= mv_interrupt,
 	.irq_clear		= mv_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.scr_read		= mv_scr_read,
 	.scr_write		= mv_scr_write,
 
 	.port_start		= mv_port_start,
 	.port_stop		= mv_port_stop,
-	.host_stop		= mv_host_stop,
 };
 
 static const struct ata_port_operations mv_iie_ops = {
@@ -462,19 +461,20 @@
 
 	.qc_prep		= mv_qc_prep_iie,
 	.qc_issue		= mv_qc_issue,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.eng_timeout		= mv_eng_timeout,
 
 	.irq_handler		= mv_interrupt,
 	.irq_clear		= mv_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.scr_read		= mv_scr_read,
 	.scr_write		= mv_scr_write,
 
 	.port_start		= mv_port_start,
 	.port_stop		= mv_port_stop,
-	.host_stop		= mv_host_stop,
 };
 
 static const struct ata_port_info mv_port_info[] = {
@@ -620,7 +620,7 @@
 
 static inline void __iomem *mv_ap_base(struct ata_port *ap)
 {
-	return mv_port_base(ap->host->mmio_base, ap->port_no);
+	return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no);
 }
 
 static inline int mv_get_hc_count(unsigned long port_flags)
@@ -809,35 +809,6 @@
 	}
 }
 
-/**
- *      mv_host_stop - Host specific cleanup/stop routine.
- *      @host: host data structure
- *
- *      Disable ints, cleanup host memory, call general purpose
- *      host_stop.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static void mv_host_stop(struct ata_host *host)
-{
-	struct mv_host_priv *hpriv = host->private_data;
-	struct pci_dev *pdev = to_pci_dev(host->dev);
-
-	if (hpriv->hp_flags & MV_HP_FLAG_MSI) {
-		pci_disable_msi(pdev);
-	} else {
-		pci_intx(pdev, 0);
-	}
-	kfree(hpriv);
-	ata_host_stop(host);
-}
-
-static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev)
-{
-	dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma);
-}
-
 static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
 {
 	u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
@@ -883,22 +854,21 @@
 	void __iomem *port_mmio = mv_ap_base(ap);
 	void *mem;
 	dma_addr_t mem_dma;
-	int rc = -ENOMEM;
+	int rc;
 
-	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
 	if (!pp)
-		goto err_out;
-	memset(pp, 0, sizeof(*pp));
+		return -ENOMEM;
 
-	mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
-				 GFP_KERNEL);
+	mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
+				  GFP_KERNEL);
 	if (!mem)
-		goto err_out_pp;
+		return -ENOMEM;
 	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
 
 	rc = ata_pad_alloc(ap, dev);
 	if (rc)
-		goto err_out_priv;
+		return rc;
 
 	/* First item in chunk of DMA memory:
 	 * 32-slot command request table (CRQB), 32 bytes each in size
@@ -951,13 +921,6 @@
 	 */
 	ap->private_data = pp;
 	return 0;
-
-err_out_priv:
-	mv_priv_free(pp, dev);
-err_out_pp:
-	kfree(pp);
-err_out:
-	return rc;
 }
 
 /**
@@ -971,18 +934,11 @@
  */
 static void mv_port_stop(struct ata_port *ap)
 {
-	struct device *dev = ap->host->dev;
-	struct mv_port_priv *pp = ap->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&ap->host->lock, flags);
 	mv_stop_dma(ap);
 	spin_unlock_irqrestore(&ap->host->lock, flags);
-
-	ap->private_data = NULL;
-	ata_pad_free(ap, dev);
-	mv_priv_free(pp, dev);
-	kfree(pp);
 }
 
 /**
@@ -1348,7 +1304,7 @@
  */
 static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
 {
-	void __iomem *mmio = host->mmio_base;
+	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
 	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
 	struct ata_queued_cmd *qc;
 	u32 hc_irq_cause;
@@ -1391,8 +1347,7 @@
 		} else {
 			/* PIO: check for device (drive) interrupt */
 			if ((DEV_IRQ << hard_port) & hc_irq_cause) {
-				ata_status = readb((void __iomem *)
-					   ap->ioaddr.status_addr);
+				ata_status = readb(ap->ioaddr.status_addr);
 				handled = 1;
 				/* ignore spurious intr if drive still BUSY */
 				if (ata_status & ATA_BUSY) {
@@ -1452,7 +1407,7 @@
 {
 	struct ata_host *host = dev_instance;
 	unsigned int hc, handled = 0, n_hcs;
-	void __iomem *mmio = host->mmio_base;
+	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
 	struct mv_host_priv *hpriv;
 	u32 irq_stat;
 
@@ -1528,22 +1483,24 @@
 
 static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
 {
-	void __iomem *mmio = mv5_phy_base(ap->host->mmio_base, ap->port_no);
+	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
 	unsigned int ofs = mv5_scr_offset(sc_reg_in);
 
 	if (ofs != 0xffffffffU)
-		return readl(mmio + ofs);
+		return readl(addr + ofs);
 	else
 		return (u32) ofs;
 }
 
 static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
 {
-	void __iomem *mmio = mv5_phy_base(ap->host->mmio_base, ap->port_no);
+	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
 	unsigned int ofs = mv5_scr_offset(sc_reg_in);
 
 	if (ofs != 0xffffffffU)
-		writelfl(val, mmio + ofs);
+		writelfl(val, addr + ofs);
 }
 
 static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
@@ -1905,7 +1862,7 @@
 static void mv_stop_and_reset(struct ata_port *ap)
 {
 	struct mv_host_priv *hpriv = ap->host->private_data;
-	void __iomem *mmio = ap->host->mmio_base;
+	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
 
 	mv_stop_dma(ap);
 
@@ -2003,10 +1960,10 @@
 			break;
 	}
 
-	tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr);
-	tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr);
-	tf.lbal = readb((void __iomem *) ap->ioaddr.lbal_addr);
-	tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
+	tf.lbah = readb(ap->ioaddr.lbah_addr);
+	tf.lbam = readb(ap->ioaddr.lbam_addr);
+	tf.lbal = readb(ap->ioaddr.lbal_addr);
+	tf.nsect = readb(ap->ioaddr.nsect_addr);
 
 	dev->class = ata_dev_classify(&tf);
 	if (!ata_dev_enabled(dev)) {
@@ -2038,17 +1995,17 @@
  */
 static void mv_eng_timeout(struct ata_port *ap)
 {
+	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
 	struct ata_queued_cmd *qc;
 	unsigned long flags;
 
 	ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
 	DPRINTK("All regs @ start of eng_timeout\n");
-	mv_dump_all_regs(ap->host->mmio_base, ap->port_no,
-			 to_pci_dev(ap->host->dev));
+	mv_dump_all_regs(mmio, ap->port_no, to_pci_dev(ap->host->dev));
 
 	qc = ata_qc_from_tag(ap, ap->active_tag);
         printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
-	       ap->host->mmio_base, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd);
+	       mmio, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd);
 
 	spin_lock_irqsave(&ap->host->lock, flags);
 	mv_err_intr(ap, 0);
@@ -2076,7 +2033,7 @@
  */
 static void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
 {
-	unsigned long shd_base = (unsigned long) port_mmio + SHD_BLK_OFS;
+	void __iomem *shd_base = port_mmio + SHD_BLK_OFS;
 	unsigned serr_ofs;
 
 	/* PIO related setup
@@ -2224,7 +2181,7 @@
 			unsigned int board_idx)
 {
 	int rc = 0, n_hc, port, hc;
-	void __iomem *mmio = probe_ent->mmio_base;
+	void __iomem *mmio = probe_ent->iomap[MV_PRIMARY_BAR];
 	struct mv_host_priv *hpriv = probe_ent->private_data;
 
 	/* global interrupt mask */
@@ -2342,49 +2299,36 @@
 static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version = 0;
-	struct ata_probe_ent *probe_ent = NULL;
+	struct device *dev = &pdev->dev;
+	struct ata_probe_ent *probe_ent;
 	struct mv_host_priv *hpriv;
 	unsigned int board_idx = (unsigned int)ent->driver_data;
-	void __iomem *mmio_base;
-	int pci_dev_busy = 0, rc;
+	int rc;
 
 	if (!printed_version++)
 		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
-	if (rc) {
+	rc = pcim_enable_device(pdev);
+	if (rc)
 		return rc;
-	}
 	pci_set_master(pdev);
 
-	rc = pci_request_regions(pdev, DRV_NAME);
-	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out;
-	}
+	rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME);
+	if (rc == -EBUSY)
+		pcim_pin_device(pdev);
+	if (rc)
+		return rc;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
+	probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		return -ENOMEM;
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = pci_iomap(pdev, MV_PRIMARY_BAR, 0);
-	if (mmio_base == NULL) {
-		rc = -ENOMEM;
-		goto err_out_free_ent;
-	}
-
-	hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
-	if (!hpriv) {
-		rc = -ENOMEM;
-		goto err_out_iounmap;
-	}
-	memset(hpriv, 0, sizeof(*hpriv));
+	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
+	if (!hpriv)
+		return -ENOMEM;
 
 	probe_ent->sht = mv_port_info[board_idx].sht;
 	probe_ent->port_flags = mv_port_info[board_idx].flags;
@@ -2394,53 +2338,26 @@
 
 	probe_ent->irq = pdev->irq;
 	probe_ent->irq_flags = IRQF_SHARED;
-	probe_ent->mmio_base = mmio_base;
+	probe_ent->iomap = pcim_iomap_table(pdev);
 	probe_ent->private_data = hpriv;
 
 	/* initialize adapter */
 	rc = mv_init_host(pdev, probe_ent, board_idx);
-	if (rc) {
-		goto err_out_hpriv;
-	}
+	if (rc)
+		return rc;
 
 	/* Enable interrupts */
-	if (msi && pci_enable_msi(pdev) == 0) {
-		hpriv->hp_flags |= MV_HP_FLAG_MSI;
-	} else {
+	if (msi && !pci_enable_msi(pdev))
 		pci_intx(pdev, 1);
-	}
 
 	mv_dump_pci_cfg(pdev, 0x68);
 	mv_print_info(probe_ent);
 
-	if (ata_device_add(probe_ent) == 0) {
-		rc = -ENODEV;		/* No devices discovered */
-		goto err_out_dev_add;
-	}
+	if (ata_device_add(probe_ent) == 0)
+		return -ENODEV;
 
-	kfree(probe_ent);
+	devm_kfree(dev, probe_ent);
 	return 0;
-
-err_out_dev_add:
-	if (MV_HP_FLAG_MSI & hpriv->hp_flags) {
-		pci_disable_msi(pdev);
-	} else {
-		pci_intx(pdev, 0);
-	}
-err_out_hpriv:
-	kfree(hpriv);
-err_out_iounmap:
-	pci_iounmap(pdev, mmio_base);
-err_out_free_ent:
-	kfree(probe_ent);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	if (!pci_dev_busy) {
-		pci_disable_device(pdev);
-	}
-
-	return rc;
 }
 
 static int __init mv_init(void)
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index f7a963e..ab92f20 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -49,11 +49,13 @@
 #include <linux/libata.h>
 
 #define DRV_NAME			"sata_nv"
-#define DRV_VERSION			"3.2"
+#define DRV_VERSION			"3.3"
 
 #define NV_ADMA_DMA_BOUNDARY		0xffffffffUL
 
 enum {
+	NV_MMIO_BAR			= 5,
+
 	NV_PORTS			= 2,
 	NV_PIO_MASK			= 0x1f,
 	NV_MWDMA_MASK			= 0x07,
@@ -213,12 +215,21 @@
 	dma_addr_t		cpb_dma;
 	struct nv_adma_prd	*aprd;
 	dma_addr_t		aprd_dma;
+	void __iomem *		ctl_block;
+	void __iomem *		gen_block;
+	void __iomem *		notifier_clear_block;
 	u8			flags;
 };
 
+struct nv_host_priv {
+	unsigned long		type;
+};
+
 #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT)))))
 
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static void nv_remove_one (struct pci_dev *pdev);
+static int nv_pci_device_resume(struct pci_dev *pdev);
 static void nv_ck804_host_stop(struct ata_host *host);
 static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
 static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
@@ -239,6 +250,8 @@
 static void nv_adma_irq_clear(struct ata_port *ap);
 static int nv_adma_port_start(struct ata_port *ap);
 static void nv_adma_port_stop(struct ata_port *ap);
+static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg);
+static int nv_adma_port_resume(struct ata_port *ap);
 static void nv_adma_error_handler(struct ata_port *ap);
 static void nv_adma_host_stop(struct ata_host *host);
 static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc);
@@ -284,7 +297,9 @@
 	.name			= DRV_NAME,
 	.id_table		= nv_pci_tbl,
 	.probe			= nv_init_one,
-	.remove			= ata_pci_remove_one,
+	.suspend		= ata_pci_device_suspend,
+	.resume			= nv_pci_device_resume,
+	.remove			= nv_remove_one,
 };
 
 static struct scsi_host_template nv_sht = {
@@ -303,6 +318,8 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.suspend		= ata_scsi_device_suspend,
+	.resume			= ata_scsi_device_resume,
 };
 
 static struct scsi_host_template nv_adma_sht = {
@@ -321,6 +338,8 @@
 	.slave_configure	= nv_adma_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.suspend		= ata_scsi_device_suspend,
+	.resume			= ata_scsi_device_resume,
 };
 
 static const struct ata_port_operations nv_generic_ops = {
@@ -340,14 +359,14 @@
 	.thaw			= ata_bmdma_thaw,
 	.error_handler		= nv_error_handler,
 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.irq_handler		= nv_generic_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.scr_read		= nv_scr_read,
 	.scr_write		= nv_scr_write,
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_pci_host_stop,
 };
 
 static const struct ata_port_operations nv_nf2_ops = {
@@ -367,14 +386,14 @@
 	.thaw			= nv_nf2_thaw,
 	.error_handler		= nv_error_handler,
 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.irq_handler		= nv_nf2_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.scr_read		= nv_scr_read,
 	.scr_write		= nv_scr_write,
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_pci_host_stop,
 };
 
 static const struct ata_port_operations nv_ck804_ops = {
@@ -394,13 +413,14 @@
 	.thaw			= nv_ck804_thaw,
 	.error_handler		= nv_error_handler,
 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.irq_handler		= nv_ck804_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.scr_read		= nv_scr_read,
 	.scr_write		= nv_scr_write,
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
 	.host_stop		= nv_ck804_host_stop,
 };
 
@@ -422,13 +442,17 @@
 	.thaw			= nv_ck804_thaw,
 	.error_handler		= nv_adma_error_handler,
 	.post_internal_cmd	= nv_adma_bmdma_stop,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.irq_handler		= nv_adma_interrupt,
 	.irq_clear		= nv_adma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.scr_read		= nv_scr_read,
 	.scr_write		= nv_scr_write,
 	.port_start		= nv_adma_port_start,
 	.port_stop		= nv_adma_port_stop,
+	.port_suspend		= nv_adma_port_suspend,
+	.port_resume		= nv_adma_port_resume,
 	.host_stop		= nv_adma_host_stop,
 };
 
@@ -467,6 +491,7 @@
 	{
 		.sht		= &nv_adma_sht,
 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_HRST_TO_RESUME |
 				  ATA_FLAG_MMIO | ATA_FLAG_NCQ,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
@@ -483,57 +508,72 @@
 
 static int adma_enabled = 1;
 
-static inline void __iomem *__nv_adma_ctl_block(void __iomem *mmio,
-					        unsigned int port_no)
-{
-	mmio += NV_ADMA_PORT + port_no * NV_ADMA_PORT_SIZE;
-	return mmio;
-}
-
-static inline void __iomem *nv_adma_ctl_block(struct ata_port *ap)
-{
-	return __nv_adma_ctl_block(ap->host->mmio_base, ap->port_no);
-}
-
-static inline void __iomem *nv_adma_gen_block(struct ata_port *ap)
-{
-	return (ap->host->mmio_base + NV_ADMA_GEN);
-}
-
-static inline void __iomem *nv_adma_notifier_clear_block(struct ata_port *ap)
-{
-	return (nv_adma_gen_block(ap) + NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no));
-}
-
 static void nv_adma_register_mode(struct ata_port *ap)
 {
-	void __iomem *mmio = nv_adma_ctl_block(ap);
 	struct nv_adma_port_priv *pp = ap->private_data;
-	u16 tmp;
+	void __iomem *mmio = pp->ctl_block;
+	u16 tmp, status;
+	int count = 0;
 
 	if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
 		return;
 
+	status = readw(mmio + NV_ADMA_STAT);
+	while(!(status & NV_ADMA_STAT_IDLE) && count < 20) {
+		ndelay(50);
+		status = readw(mmio + NV_ADMA_STAT);
+		count++;
+	}
+	if(count == 20)
+		ata_port_printk(ap, KERN_WARNING,
+			"timeout waiting for ADMA IDLE, stat=0x%hx\n",
+			status);
+
 	tmp = readw(mmio + NV_ADMA_CTL);
 	writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
 
+	count = 0;
+	status = readw(mmio + NV_ADMA_STAT);
+	while(!(status & NV_ADMA_STAT_LEGACY) && count < 20) {
+		ndelay(50);
+		status = readw(mmio + NV_ADMA_STAT);
+		count++;
+	}
+	if(count == 20)
+		ata_port_printk(ap, KERN_WARNING,
+			 "timeout waiting for ADMA LEGACY, stat=0x%hx\n",
+			 status);
+
 	pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
 }
 
 static void nv_adma_mode(struct ata_port *ap)
 {
-	void __iomem *mmio = nv_adma_ctl_block(ap);
 	struct nv_adma_port_priv *pp = ap->private_data;
-	u16 tmp;
+	void __iomem *mmio = pp->ctl_block;
+	u16 tmp, status;
+	int count = 0;
 
 	if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE))
 		return;
-		
+
 	WARN_ON(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE);
 
 	tmp = readw(mmio + NV_ADMA_CTL);
 	writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
 
+	status = readw(mmio + NV_ADMA_STAT);
+	while(((status & NV_ADMA_STAT_LEGACY) ||
+	      !(status & NV_ADMA_STAT_IDLE)) && count < 20) {
+		ndelay(50);
+		status = readw(mmio + NV_ADMA_STAT);
+		count++;
+	}
+	if(count == 20)
+		ata_port_printk(ap, KERN_WARNING,
+			"timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n",
+			status);
+
 	pp->flags &= ~NV_ADMA_PORT_REGISTER_MODE;
 }
 
@@ -568,7 +608,7 @@
 		/* Subtract 1 since an extra entry may be needed for padding, see
 		   libata-scsi.c */
 		sg_tablesize = LIBATA_MAX_PRD - 1;
-		
+
 		/* Since the legacy DMA engine is in use, we need to disable ADMA
 		   on the port. */
 		adma_enable = 0;
@@ -580,7 +620,7 @@
 		sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN;
 		adma_enable = 1;
 	}
-	
+
 	pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &current_reg);
 
 	if(ap->port_no == 1)
@@ -589,7 +629,7 @@
 	else
 		config_mask = NV_MCP_SATA_CFG_20_PORT0_EN |
 			      NV_MCP_SATA_CFG_20_PORT0_PWB_EN;
-	
+
 	if(adma_enable) {
 		new_reg = current_reg | config_mask;
 		pp->flags &= ~NV_ADMA_ATAPI_SETUP_COMPLETE;
@@ -598,10 +638,10 @@
 		new_reg = current_reg & ~config_mask;
 		pp->flags |= NV_ADMA_ATAPI_SETUP_COMPLETE;
 	}
-	
+
 	if(current_reg != new_reg)
 		pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg);
-	
+
 	blk_queue_bounce_limit(sdev->request_queue, bounce_limit);
 	blk_queue_segment_boundary(sdev->request_queue, segment_boundary);
 	blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize);
@@ -648,53 +688,62 @@
 	return idx;
 }
 
-static void nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
+static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
 {
 	struct nv_adma_port_priv *pp = ap->private_data;
-	int complete = 0, have_err = 0;
 	u8 flags = pp->cpb[cpb_num].resp_flags;
 
 	VPRINTK("CPB %d, flags=0x%x\n", cpb_num, flags);
 
+	if (unlikely((force_err ||
+		     flags & (NV_CPB_RESP_ATA_ERR |
+			      NV_CPB_RESP_CMD_ERR |
+			      NV_CPB_RESP_CPB_ERR)))) {
+		struct ata_eh_info *ehi = &ap->eh_info;
+		int freeze = 0;
+
+		ata_ehi_clear_desc(ehi);
+		ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x", flags );
+		if (flags & NV_CPB_RESP_ATA_ERR) {
+			ata_ehi_push_desc(ehi, ": ATA error");
+			ehi->err_mask |= AC_ERR_DEV;
+		} else if (flags & NV_CPB_RESP_CMD_ERR) {
+			ata_ehi_push_desc(ehi, ": CMD error");
+			ehi->err_mask |= AC_ERR_DEV;
+		} else if (flags & NV_CPB_RESP_CPB_ERR) {
+			ata_ehi_push_desc(ehi, ": CPB error");
+			ehi->err_mask |= AC_ERR_SYSTEM;
+			freeze = 1;
+		} else {
+			/* notifier error, but no error in CPB flags? */
+			ehi->err_mask |= AC_ERR_OTHER;
+			freeze = 1;
+		}
+		/* Kill all commands. EH will determine what actually failed. */
+		if (freeze)
+			ata_port_freeze(ap);
+		else
+			ata_port_abort(ap);
+		return 1;
+	}
+
 	if (flags & NV_CPB_RESP_DONE) {
-		VPRINTK("CPB flags done, flags=0x%x\n", flags);
-		complete = 1;
-	}
-	if (flags & NV_CPB_RESP_ATA_ERR) {
-		ata_port_printk(ap, KERN_ERR, "CPB flags ATA err, flags=0x%x\n", flags);
-		have_err = 1;
-		complete = 1;
-	}
-	if (flags & NV_CPB_RESP_CMD_ERR) {
-		ata_port_printk(ap, KERN_ERR, "CPB flags CMD err, flags=0x%x\n", flags);
-		have_err = 1;
-		complete = 1;
-	}
-	if (flags & NV_CPB_RESP_CPB_ERR) {
-		ata_port_printk(ap, KERN_ERR, "CPB flags CPB err, flags=0x%x\n", flags);
-		have_err = 1;
-		complete = 1;
-	}
-	if(complete || force_err)
-	{
 		struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
-		if(likely(qc)) {
-			u8 ata_status = 0;
-			/* Only use the ATA port status for non-NCQ commands.
+		VPRINTK("CPB flags done, flags=0x%x\n", flags);
+		if (likely(qc)) {
+			/* Grab the ATA port status for non-NCQ commands.
 			   For NCQ commands the current status may have nothing to do with
 			   the command just completed. */
-			if(qc->tf.protocol != ATA_PROT_NCQ)
-				ata_status = readb(nv_adma_ctl_block(ap) + (ATA_REG_STATUS * 4));
-
-			if(have_err || force_err)
-				ata_status |= ATA_ERR;
-
-			qc->err_mask |= ac_err_mask(ata_status);
+			if (qc->tf.protocol != ATA_PROT_NCQ) {
+				u8 ata_status = readb(pp->ctl_block + (ATA_REG_STATUS * 4));
+				qc->err_mask |= ac_err_mask(ata_status);
+			}
 			DPRINTK("Completing qc from tag %d with err_mask %u\n",cpb_num,
 				qc->err_mask);
 			ata_qc_complete(qc);
 		}
 	}
+	return 0;
 }
 
 static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
@@ -735,15 +784,14 @@
 
 		if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
 			struct nv_adma_port_priv *pp = ap->private_data;
-			void __iomem *mmio = nv_adma_ctl_block(ap);
+			void __iomem *mmio = pp->ctl_block;
 			u16 status;
 			u32 gen_ctl;
-			int have_global_err = 0;
 			u32 notifier, notifier_error;
 
 			/* if in ATA register mode, use standard ata interrupt handler */
 			if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
-				u8 irq_stat = readb(host->mmio_base + NV_INT_STATUS_CK804)
+				u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
 					>> (NV_INT_PORT_SHIFT * i);
 				if(ata_tag_valid(ap->active_tag))
 					/** NV_INT_DEV indication seems unreliable at times
@@ -758,7 +806,7 @@
 			notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
 			notifier_clears[i] = notifier | notifier_error;
 
-			gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL);
+			gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
 
 			if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier &&
 			    !notifier_error)
@@ -774,52 +822,64 @@
 			readw(mmio + NV_ADMA_STAT); /* flush posted write */
 			rmb();
 
-			/* freeze if hotplugged */
-			if (unlikely(status & (NV_ADMA_STAT_HOTPLUG | NV_ADMA_STAT_HOTUNPLUG))) {
-				ata_port_printk(ap, KERN_NOTICE, "Hotplug event, freezing\n");
+			handled++; /* irq handled if we got here */
+
+			/* freeze if hotplugged or controller error */
+			if (unlikely(status & (NV_ADMA_STAT_HOTPLUG |
+					       NV_ADMA_STAT_HOTUNPLUG |
+					       NV_ADMA_STAT_TIMEOUT |
+					       NV_ADMA_STAT_SERROR))) {
+				struct ata_eh_info *ehi = &ap->eh_info;
+
+				ata_ehi_clear_desc(ehi);
+				ata_ehi_push_desc(ehi, "ADMA status 0x%08x", status );
+				if (status & NV_ADMA_STAT_TIMEOUT) {
+					ehi->err_mask |= AC_ERR_SYSTEM;
+					ata_ehi_push_desc(ehi, ": timeout");
+				} else if (status & NV_ADMA_STAT_HOTPLUG) {
+					ata_ehi_hotplugged(ehi);
+					ata_ehi_push_desc(ehi, ": hotplug");
+				} else if (status & NV_ADMA_STAT_HOTUNPLUG) {
+					ata_ehi_hotplugged(ehi);
+					ata_ehi_push_desc(ehi, ": hot unplug");
+				} else if (status & NV_ADMA_STAT_SERROR) {
+					/* let libata analyze SError and figure out the cause */
+					ata_ehi_push_desc(ehi, ": SError");
+				}
 				ata_port_freeze(ap);
-				handled++;
 				continue;
 			}
 
-			if (status & NV_ADMA_STAT_TIMEOUT) {
-				ata_port_printk(ap, KERN_ERR, "timeout, stat=0x%x\n", status);
-				have_global_err = 1;
-			}
-			if (status & NV_ADMA_STAT_CPBERR) {
-				ata_port_printk(ap, KERN_ERR, "CPB error, stat=0x%x\n", status);
-				have_global_err = 1;
-			}
-			if ((status & NV_ADMA_STAT_DONE) || have_global_err) {
+			if (status & (NV_ADMA_STAT_DONE |
+				      NV_ADMA_STAT_CPBERR)) {
 				/** Check CPBs for completed commands */
 
-				if(ata_tag_valid(ap->active_tag))
+				if (ata_tag_valid(ap->active_tag)) {
 					/* Non-NCQ command */
-					nv_adma_check_cpb(ap, ap->active_tag, have_global_err ||
-						(notifier_error & (1 << ap->active_tag)));
-				else {
-					int pos;
+					nv_adma_check_cpb(ap, ap->active_tag,
+						notifier_error & (1 << ap->active_tag));
+				} else {
+					int pos, error = 0;
 					u32 active = ap->sactive;
-					while( (pos = ffs(active)) ) {
+
+					while ((pos = ffs(active)) && !error) {
 						pos--;
-						nv_adma_check_cpb(ap, pos, have_global_err ||
-							(notifier_error & (1 << pos)) );
+						error = nv_adma_check_cpb(ap, pos,
+							notifier_error & (1 << pos) );
 						active &= ~(1 << pos );
 					}
 				}
 			}
-
-			handled++; /* irq handled if we got here */
 		}
 	}
-	
+
 	if(notifier_clears[0] || notifier_clears[1]) {
 		/* Note: Both notifier clear registers must be written
 		   if either is set, even if one is zero, according to NVIDIA. */
-		writel(notifier_clears[0], 
-			nv_adma_notifier_clear_block(host->ports[0]));
-		writel(notifier_clears[1], 
-			nv_adma_notifier_clear_block(host->ports[1]));
+		struct nv_adma_port_priv *pp = host->ports[0]->private_data;
+		writel(notifier_clears[0], pp->notifier_clear_block);
+		pp = host->ports[1]->private_data;
+		writel(notifier_clears[1], pp->notifier_clear_block);
 	}
 
 	spin_unlock(&host->lock);
@@ -829,19 +889,20 @@
 
 static void nv_adma_irq_clear(struct ata_port *ap)
 {
-	void __iomem *mmio = nv_adma_ctl_block(ap);
+	struct nv_adma_port_priv *pp = ap->private_data;
+	void __iomem *mmio = pp->ctl_block;
 	u16 status = readw(mmio + NV_ADMA_STAT);
 	u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
 	u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
-	unsigned long dma_stat_addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
+	void __iomem *dma_stat_addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
 
 	/* clear ADMA status */
 	writew(status, mmio + NV_ADMA_STAT);
 	writel(notifier | notifier_error,
-	       nv_adma_notifier_clear_block(ap));
+	       pp->notifier_clear_block);
 
 	/** clear legacy status */
-	outb(inb(dma_stat_addr), dma_stat_addr);
+	iowrite8(ioread8(dma_stat_addr), dma_stat_addr);
 }
 
 static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc)
@@ -857,15 +918,15 @@
 	}
 
 	/* load PRD table addr. */
-	outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
+	iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
 
 	/* specify data direction, triple-check start bit is clear */
-	dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+	dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
 	if (!rw)
 		dmactl |= ATA_DMA_WR;
 
-	outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+	iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 
 	/* issue r/w command */
 	ata_exec_command(ap, &qc->tf);
@@ -883,9 +944,9 @@
 	}
 
 	/* start host DMA transaction */
-	dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-	outb(dmactl | ATA_DMA_START,
-	     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+	dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+	iowrite8(dmactl | ATA_DMA_START,
+		 ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 }
 
 static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc)
@@ -897,8 +958,8 @@
 		return;
 
 	/* clear start/stop bit */
-	outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
-		ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+	iowrite8(ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
+		 ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 
 	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
 	ata_altstatus(ap);        /* dummy read */
@@ -910,7 +971,7 @@
 
 	WARN_ON(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE));
 
-	return inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
 }
 
 static int nv_adma_port_start(struct ata_port *ap)
@@ -920,7 +981,7 @@
 	int rc;
 	void *mem;
 	dma_addr_t mem_dma;
-	void __iomem *mmio = nv_adma_ctl_block(ap);
+	void __iomem *mmio;
 	u16 tmp;
 
 	VPRINTK("ENTER\n");
@@ -929,19 +990,21 @@
 	if (rc)
 		return rc;
 
-	pp = kzalloc(sizeof(*pp), GFP_KERNEL);
-	if (!pp) {
-		rc = -ENOMEM;
-		goto err_out;
-	}
+	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
 
-	mem = dma_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ,
-				 &mem_dma, GFP_KERNEL);
+	mmio = ap->host->iomap[NV_MMIO_BAR] + NV_ADMA_PORT +
+	       ap->port_no * NV_ADMA_PORT_SIZE;
+	pp->ctl_block = mmio;
+	pp->gen_block = ap->host->iomap[NV_MMIO_BAR] + NV_ADMA_GEN;
+	pp->notifier_clear_block = pp->gen_block +
+	       NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no);
 
-	if (!mem) {
-		rc = -ENOMEM;
-		goto err_out_kfree;
-	}
+	mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ,
+				  &mem_dma, GFP_KERNEL);
+	if (!mem)
+		return -ENOMEM;
 	memset(mem, 0, NV_ADMA_PORT_PRIV_DMA_SZ);
 
 	/*
@@ -975,9 +1038,9 @@
 	/* clear CPB fetch count */
 	writew(0, mmio + NV_ADMA_CPB_COUNT);
 
-	/* clear GO for register mode */
+	/* clear GO for register mode, enable interrupt */
 	tmp = readw(mmio + NV_ADMA_CTL);
-	writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
+	writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL);
 
 	tmp = readw(mmio + NV_ADMA_CTL);
 	writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
@@ -987,53 +1050,89 @@
 	readl( mmio + NV_ADMA_CTL );	/* flush posted write */
 
 	return 0;
-
-err_out_kfree:
-	kfree(pp);
-err_out:
-	ata_port_stop(ap);
-	return rc;
 }
 
 static void nv_adma_port_stop(struct ata_port *ap)
 {
-	struct device *dev = ap->host->dev;
 	struct nv_adma_port_priv *pp = ap->private_data;
-	void __iomem *mmio = nv_adma_ctl_block(ap);
+	void __iomem *mmio = pp->ctl_block;
 
 	VPRINTK("ENTER\n");
-
 	writew(0, mmio + NV_ADMA_CTL);
-
-	ap->private_data = NULL;
-	dma_free_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, pp->cpb, pp->cpb_dma);
-	kfree(pp);
-	ata_port_stop(ap);
 }
 
+static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg)
+{
+	struct nv_adma_port_priv *pp = ap->private_data;
+	void __iomem *mmio = pp->ctl_block;
+
+	/* Go to register mode - clears GO */
+	nv_adma_register_mode(ap);
+
+	/* clear CPB fetch count */
+	writew(0, mmio + NV_ADMA_CPB_COUNT);
+
+	/* disable interrupt, shut down port */
+	writew(0, mmio + NV_ADMA_CTL);
+
+	return 0;
+}
+
+static int nv_adma_port_resume(struct ata_port *ap)
+{
+	struct nv_adma_port_priv *pp = ap->private_data;
+	void __iomem *mmio = pp->ctl_block;
+	u16 tmp;
+
+	/* set CPB block location */
+	writel(pp->cpb_dma & 0xFFFFFFFF, 	mmio + NV_ADMA_CPB_BASE_LOW);
+	writel((pp->cpb_dma >> 16 ) >> 16,	mmio + NV_ADMA_CPB_BASE_HIGH);
+
+	/* clear any outstanding interrupt conditions */
+	writew(0xffff, mmio + NV_ADMA_STAT);
+
+	/* initialize port variables */
+	pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
+
+	/* clear CPB fetch count */
+	writew(0, mmio + NV_ADMA_CPB_COUNT);
+
+	/* clear GO for register mode, enable interrupt */
+	tmp = readw(mmio + NV_ADMA_CTL);
+	writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL);
+
+	tmp = readw(mmio + NV_ADMA_CTL);
+	writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
+	readl( mmio + NV_ADMA_CTL );	/* flush posted write */
+	udelay(1);
+	writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
+	readl( mmio + NV_ADMA_CTL );	/* flush posted write */
+
+	return 0;
+}
 
 static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port)
 {
-	void __iomem *mmio = probe_ent->mmio_base;
+	void __iomem *mmio = probe_ent->iomap[NV_MMIO_BAR];
 	struct ata_ioports *ioport = &probe_ent->port[port];
 
 	VPRINTK("ENTER\n");
 
 	mmio += NV_ADMA_PORT + port * NV_ADMA_PORT_SIZE;
 
-	ioport->cmd_addr	= (unsigned long) mmio;
-	ioport->data_addr	= (unsigned long) mmio + (ATA_REG_DATA * 4);
+	ioport->cmd_addr	= mmio;
+	ioport->data_addr	= mmio + (ATA_REG_DATA * 4);
 	ioport->error_addr	=
-	ioport->feature_addr	= (unsigned long) mmio + (ATA_REG_ERR * 4);
-	ioport->nsect_addr	= (unsigned long) mmio + (ATA_REG_NSECT * 4);
-	ioport->lbal_addr	= (unsigned long) mmio + (ATA_REG_LBAL * 4);
-	ioport->lbam_addr	= (unsigned long) mmio + (ATA_REG_LBAM * 4);
-	ioport->lbah_addr	= (unsigned long) mmio + (ATA_REG_LBAH * 4);
-	ioport->device_addr	= (unsigned long) mmio + (ATA_REG_DEVICE * 4);
+	ioport->feature_addr	= mmio + (ATA_REG_ERR * 4);
+	ioport->nsect_addr	= mmio + (ATA_REG_NSECT * 4);
+	ioport->lbal_addr	= mmio + (ATA_REG_LBAL * 4);
+	ioport->lbam_addr	= mmio + (ATA_REG_LBAM * 4);
+	ioport->lbah_addr	= mmio + (ATA_REG_LBAH * 4);
+	ioport->device_addr	= mmio + (ATA_REG_DEVICE * 4);
 	ioport->status_addr	=
-	ioport->command_addr	= (unsigned long) mmio + (ATA_REG_STATUS * 4);
+	ioport->command_addr	= mmio + (ATA_REG_STATUS * 4);
 	ioport->altstatus_addr	=
-	ioport->ctl_addr	= (unsigned long) mmio + 0x20;
+	ioport->ctl_addr	= mmio + 0x20;
 }
 
 static int nv_adma_host_init(struct ata_probe_ent *probe_ent)
@@ -1056,15 +1155,6 @@
 	for (i = 0; i < probe_ent->n_ports; i++)
 		nv_adma_setup_port(probe_ent, i);
 
-	for (i = 0; i < probe_ent->n_ports; i++) {
-		void __iomem *mmio = __nv_adma_ctl_block(probe_ent->mmio_base, i);
-		u16 tmp;
-
-		/* enable interrupt, clear reset if not already clear */
-		tmp = readw(mmio + NV_ADMA_CTL);
-		writew(tmp | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL);
-	}
-
 	return 0;
 }
 
@@ -1110,18 +1200,31 @@
 		cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
 }
 
+static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
+{
+	struct nv_adma_port_priv *pp = qc->ap->private_data;
+
+	/* ADMA engine can only be used for non-ATAPI DMA commands,
+	   or interrupt-driven no-data commands. */
+	if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
+	   (qc->tf.flags & ATA_TFLAG_POLLING))
+		return 1;
+
+	if((qc->flags & ATA_QCFLAG_DMAMAP) ||
+	   (qc->tf.protocol == ATA_PROT_NODATA))
+		return 0;
+
+	return 1;
+}
+
 static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct nv_adma_port_priv *pp = qc->ap->private_data;
 	struct nv_adma_cpb *cpb = &pp->cpb[qc->tag];
 	u8 ctl_flags = NV_CPB_CTL_CPB_VALID |
-		       NV_CPB_CTL_APRD_VALID |
 		       NV_CPB_CTL_IEN;
 
-	VPRINTK("qc->flags = 0x%lx\n", qc->flags);
-
-	if (!(qc->flags & ATA_QCFLAG_DMAMAP) ||
-	     (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
+	if (nv_adma_use_reg_mode(qc)) {
 		nv_adma_register_mode(qc->ap);
 		ata_qc_prep(qc);
 		return;
@@ -1137,9 +1240,15 @@
 	if (qc->tf.protocol == ATA_PROT_NCQ)
 		ctl_flags |= NV_CPB_CTL_QUEUE | NV_CPB_CTL_FPDMA;
 
+	VPRINTK("qc->flags = 0x%lx\n", qc->flags);
+
 	nv_adma_tf_to_cpb(&qc->tf, cpb->tf);
 
-	nv_adma_fill_sg(qc, cpb);
+	if(qc->flags & ATA_QCFLAG_DMAMAP) {
+		nv_adma_fill_sg(qc, cpb);
+		ctl_flags |= NV_CPB_CTL_APRD_VALID;
+	} else
+		memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5);
 
 	/* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are
 	   finished filling in all of the contents */
@@ -1150,14 +1259,13 @@
 static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
 {
 	struct nv_adma_port_priv *pp = qc->ap->private_data;
-	void __iomem *mmio = nv_adma_ctl_block(qc->ap);
+	void __iomem *mmio = pp->ctl_block;
 
 	VPRINTK("ENTER\n");
 
-	if (!(qc->flags & ATA_QCFLAG_DMAMAP) ||
-	     (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
+	if (nv_adma_use_reg_mode(qc)) {
 		/* use ATA register mode */
-		VPRINTK("no dmamap or ATAPI, using ATA register mode: 0x%lx\n", qc->flags);
+		VPRINTK("using ATA register mode: 0x%lx\n", qc->flags);
 		nv_adma_register_mode(qc->ap);
 		return ata_qc_issue_prot(qc);
 	} else
@@ -1229,7 +1337,7 @@
 	irqreturn_t ret;
 
 	spin_lock(&host->lock);
-	irq_stat = inb(host->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
+	irq_stat = ioread8(host->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
 	ret = nv_do_interrupt(host, irq_stat);
 	spin_unlock(&host->lock);
 
@@ -1243,7 +1351,7 @@
 	irqreturn_t ret;
 
 	spin_lock(&host->lock);
-	irq_stat = readb(host->mmio_base + NV_INT_STATUS_CK804);
+	irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
 	ret = nv_do_interrupt(host, irq_stat);
 	spin_unlock(&host->lock);
 
@@ -1255,7 +1363,7 @@
 	if (sc_reg > SCR_CONTROL)
 		return 0xffffffffU;
 
-	return ioread32((void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
+	return ioread32(ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
@@ -1263,36 +1371,36 @@
 	if (sc_reg > SCR_CONTROL)
 		return;
 
-	iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
+	iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 static void nv_nf2_freeze(struct ata_port *ap)
 {
-	unsigned long scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
+	void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
 	int shift = ap->port_no * NV_INT_PORT_SHIFT;
 	u8 mask;
 
-	mask = inb(scr_addr + NV_INT_ENABLE);
+	mask = ioread8(scr_addr + NV_INT_ENABLE);
 	mask &= ~(NV_INT_ALL << shift);
-	outb(mask, scr_addr + NV_INT_ENABLE);
+	iowrite8(mask, scr_addr + NV_INT_ENABLE);
 }
 
 static void nv_nf2_thaw(struct ata_port *ap)
 {
-	unsigned long scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
+	void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
 	int shift = ap->port_no * NV_INT_PORT_SHIFT;
 	u8 mask;
 
-	outb(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS);
+	iowrite8(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS);
 
-	mask = inb(scr_addr + NV_INT_ENABLE);
+	mask = ioread8(scr_addr + NV_INT_ENABLE);
 	mask |= (NV_INT_MASK << shift);
-	outb(mask, scr_addr + NV_INT_ENABLE);
+	iowrite8(mask, scr_addr + NV_INT_ENABLE);
 }
 
 static void nv_ck804_freeze(struct ata_port *ap)
 {
-	void __iomem *mmio_base = ap->host->mmio_base;
+	void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
 	int shift = ap->port_no * NV_INT_PORT_SHIFT;
 	u8 mask;
 
@@ -1303,7 +1411,7 @@
 
 static void nv_ck804_thaw(struct ata_port *ap)
 {
-	void __iomem *mmio_base = ap->host->mmio_base;
+	void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
 	int shift = ap->port_no * NV_INT_PORT_SHIFT;
 	u8 mask;
 
@@ -1335,32 +1443,13 @@
 {
 	struct nv_adma_port_priv *pp = ap->private_data;
 	if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
-		void __iomem *mmio = nv_adma_ctl_block(ap);
+		void __iomem *mmio = pp->ctl_block;
 		int i;
 		u16 tmp;
 
-		u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
-		u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
-		u32 gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL);
-		u32 status = readw(mmio + NV_ADMA_STAT);
-
-		ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X "
-			"notifier_error 0x%X gen_ctl 0x%X status 0x%X\n",
-			notifier, notifier_error, gen_ctl, status);
-
-		for( i=0;i<NV_ADMA_MAX_CPBS;i++) {
-			struct nv_adma_cpb *cpb = &pp->cpb[i];
-			if( cpb->ctl_flags || cpb->resp_flags )
-				ata_port_printk(ap, KERN_ERR,
-					"CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",
-					i, cpb->ctl_flags, cpb->resp_flags);
-		}
-
 		/* Push us back into port register mode for error handling. */
 		nv_adma_register_mode(ap);
 
-		ata_port_printk(ap, KERN_ERR, "Resetting port\n");
-
 		/* Mark all of the CPBs as invalid to prevent them from being executed */
 		for( i=0;i<NV_ADMA_MAX_CPBS;i++)
 			pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID;
@@ -1386,10 +1475,10 @@
 	static int printed_version = 0;
 	struct ata_port_info *ppi[2];
 	struct ata_probe_ent *probe_ent;
-	int pci_dev_busy = 0;
+	struct nv_host_priv *hpriv;
 	int rc;
 	u32 bar;
-	unsigned long base;
+	void __iomem *base;
 	unsigned long type = ent->driver_data;
 	int mask_set = 0;
 
@@ -1400,17 +1489,17 @@
 		if (pci_resource_start(pdev, bar) == 0)
 			return -ENODEV;
 
-	if (	!printed_version++)
+	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
-		goto err_out;
+		return rc;
 
 	rc = pci_request_regions(pdev, DRV_NAME);
 	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out_disable;
+		pcim_pin_device(pdev);
+		return rc;
 	}
 
 	if(type >= CK804 && adma_enabled) {
@@ -1424,27 +1513,31 @@
 	if(!mask_set) {
 		rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
 		if (rc)
-			goto err_out_regions;
+			return rc;
 		rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
 		if (rc)
-			goto err_out_regions;
+			return rc;
 	}
 
 	rc = -ENOMEM;
 
+	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
+	if (!hpriv)
+		return -ENOMEM;
+
 	ppi[0] = ppi[1] = &nv_port_info[type];
 	probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent)
-		goto err_out_regions;
+		return -ENOMEM;
 
-	probe_ent->mmio_base = pci_iomap(pdev, 5, 0);
-	if (!probe_ent->mmio_base) {
-		rc = -EIO;
-		goto err_out_free_ent;
-	}
+	if (!pcim_iomap(pdev, NV_MMIO_BAR, 0))
+		return -EIO;
+	probe_ent->iomap = pcim_iomap_table(pdev);
 
-	base = (unsigned long)probe_ent->mmio_base;
+	probe_ent->private_data = hpriv;
+	hpriv->type = type;
 
+	base = probe_ent->iomap[NV_MMIO_BAR];
 	probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
 	probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
 
@@ -1462,28 +1555,72 @@
 	if (type == ADMA) {
 		rc = nv_adma_host_init(probe_ent);
 		if (rc)
-			goto err_out_iounmap;
+			return rc;
 	}
 
 	rc = ata_device_add(probe_ent);
 	if (rc != NV_PORTS)
-		goto err_out_iounmap;
+		return -ENODEV;
 
-	kfree(probe_ent);
+	devm_kfree(&pdev->dev, probe_ent);
+	return 0;
+}
+
+static void nv_remove_one (struct pci_dev *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct nv_host_priv *hpriv = host->private_data;
+
+	ata_pci_remove_one(pdev);
+	kfree(hpriv);
+}
+
+static int nv_pci_device_resume(struct pci_dev *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct nv_host_priv *hpriv = host->private_data;
+	int rc;
+
+	rc = ata_pci_device_do_resume(pdev);
+	if(rc)
+		return rc;
+
+	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+		if(hpriv->type >= CK804) {
+			u8 regval;
+
+			pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
+			regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
+			pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
+		}
+		if(hpriv->type == ADMA) {
+			u32 tmp32;
+			struct nv_adma_port_priv *pp;
+			/* enable/disable ADMA on the ports appropriately */
+			pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
+
+			pp = host->ports[0]->private_data;
+			if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
+				tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |
+				 	   NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
+			else
+				tmp32 |=  (NV_MCP_SATA_CFG_20_PORT0_EN |
+				 	   NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
+			pp = host->ports[1]->private_data;
+			if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
+				tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN |
+				 	   NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
+			else
+				tmp32 |=  (NV_MCP_SATA_CFG_20_PORT1_EN |
+				 	   NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
+
+			pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
+		}
+	}
+
+	ata_host_resume(host);
 
 	return 0;
-
-err_out_iounmap:
-	pci_iounmap(pdev, probe_ent->mmio_base);
-err_out_free_ent:
-	kfree(probe_ent);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out_disable:
-	if (!pci_dev_busy)
-		pci_disable_device(pdev);
-err_out:
-	return rc;
 }
 
 static void nv_ck804_host_stop(struct ata_host *host)
@@ -1495,25 +1632,13 @@
 	pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
 	regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
 	pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
-
-	ata_pci_host_stop(host);
 }
 
 static void nv_adma_host_stop(struct ata_host *host)
 {
 	struct pci_dev *pdev = to_pci_dev(host->dev);
-	int i;
 	u32 tmp32;
 
-	for (i = 0; i < host->n_ports; i++) {
-		void __iomem *mmio = __nv_adma_ctl_block(host->mmio_base, i);
-		u16 tmp;
-
-		/* disable interrupt */
-		tmp = readw(mmio + NV_ADMA_CTL);
-		writew(tmp & ~NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL);
-	}
-
 	/* disable ADMA on the ports */
 	pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
 	tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index f055874..cf9ed8c 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -37,12 +37,11 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/device.h>
+#include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
-#include <asm/io.h>
 #include "sata_promise.h"
 
 #define DRV_NAME	"sata_promise"
@@ -50,6 +49,17 @@
 
 
 enum {
+	PDC_MMIO_BAR		= 3,
+
+	/* register offsets */
+	PDC_FEATURE		= 0x04, /* Feature/Error reg (per port) */
+	PDC_SECTOR_COUNT	= 0x08, /* Sector count reg (per port) */
+	PDC_SECTOR_NUMBER	= 0x0C, /* Sector number reg (per port) */
+	PDC_CYLINDER_LOW	= 0x10, /* Cylinder low reg (per port) */
+	PDC_CYLINDER_HIGH	= 0x14, /* Cylinder high reg (per port) */
+	PDC_DEVICE		= 0x18, /* Device/Head reg (per port) */
+	PDC_COMMAND		= 0x1C, /* Command/status reg (per port) */
+	PDC_ALTSTATUS		= 0x38, /* Alternate-status/device-control reg (per port) */
 	PDC_PKT_SUBMIT		= 0x40, /* Command packet pointer addr */
 	PDC_INT_SEQMASK		= 0x40,	/* Mask of asserted SEQ INTs */
 	PDC_FLASH_CTL		= 0x44, /* Flash control register */
@@ -71,13 +81,23 @@
 
 	PDC_HAS_PATA		= (1 << 1), /* PDC20375/20575 has PATA */
 
+	/* Sequence counter control registers bit definitions */
+	PDC_SEQCNTRL_INT_MASK	= (1 << 5), /* Sequence Interrupt Mask */
+
+	/* Feature register values */
+	PDC_FEATURE_ATAPI_PIO	= 0x00, /* ATAPI data xfer by PIO */
+	PDC_FEATURE_ATAPI_DMA	= 0x01, /* ATAPI data xfer by DMA */
+
+	/* Device/Head register values */
+	PDC_DEVICE_SATA		= 0xE0, /* Device/Head value for SATA devices */
+
 	/* PDC_CTLSTAT bit definitions */
 	PDC_DMA_ENABLE		= (1 << 7),
 	PDC_IRQ_DISABLE		= (1 << 10),
 	PDC_RESET		= (1 << 11), /* HDMA reset */
 
 	PDC_COMMON_FLAGS	= ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+				  ATA_FLAG_MMIO |
 				  ATA_FLAG_PIO_POLLING,
 
 	/* hp->flags bits */
@@ -92,22 +112,21 @@
 
 struct pdc_host_priv {
 	unsigned long		flags;
+	unsigned long		port_flags[ATA_MAX_PORTS];
 };
 
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static irqreturn_t pdc_interrupt (int irq, void *dev_instance);
-static void pdc_eng_timeout(struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
-static void pdc_port_stop(struct ata_port *ap);
-static void pdc_pata_phy_reset(struct ata_port *ap);
 static void pdc_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
+static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);
+static int pdc_old_check_atapi_dma(struct ata_queued_cmd *qc);
 static void pdc_irq_clear(struct ata_port *ap);
 static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
-static void pdc_host_stop(struct ata_host *host);
 static void pdc_freeze(struct ata_port *ap);
 static void pdc_thaw(struct ata_port *ap);
 static void pdc_error_handler(struct ata_port *ap);
@@ -139,6 +158,7 @@
 	.check_status		= ata_check_status,
 	.exec_command		= pdc_exec_command_mmio,
 	.dev_select		= ata_std_dev_select,
+	.check_atapi_dma	= pdc_check_atapi_dma,
 
 	.qc_prep		= pdc_qc_prep,
 	.qc_issue		= pdc_qc_issue_prot,
@@ -146,15 +166,42 @@
 	.thaw			= pdc_thaw,
 	.error_handler		= pdc_error_handler,
 	.post_internal_cmd	= pdc_post_internal_cmd,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.irq_handler		= pdc_interrupt,
 	.irq_clear		= pdc_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.scr_read		= pdc_sata_scr_read,
 	.scr_write		= pdc_sata_scr_write,
 	.port_start		= pdc_port_start,
-	.port_stop		= pdc_port_stop,
-	.host_stop		= pdc_host_stop,
+};
+
+/* First-generation chips need a more restrictive ->check_atapi_dma op */
+static const struct ata_port_operations pdc_old_sata_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= pdc_tf_load_mmio,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= pdc_exec_command_mmio,
+	.dev_select		= ata_std_dev_select,
+	.check_atapi_dma	= pdc_old_check_atapi_dma,
+
+	.qc_prep		= pdc_qc_prep,
+	.qc_issue		= pdc_qc_issue_prot,
+	.freeze			= pdc_freeze,
+	.thaw			= pdc_thaw,
+	.error_handler		= pdc_error_handler,
+	.post_internal_cmd	= pdc_post_internal_cmd,
+	.data_xfer		= ata_data_xfer,
+	.irq_handler		= pdc_interrupt,
+	.irq_clear		= pdc_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
+
+	.scr_read		= pdc_sata_scr_read,
+	.scr_write		= pdc_sata_scr_write,
+	.port_start		= pdc_port_start,
 };
 
 static const struct ata_port_operations pdc_pata_ops = {
@@ -164,30 +211,31 @@
 	.check_status		= ata_check_status,
 	.exec_command		= pdc_exec_command_mmio,
 	.dev_select		= ata_std_dev_select,
-
-	.phy_reset		= pdc_pata_phy_reset,
+	.check_atapi_dma	= pdc_check_atapi_dma,
 
 	.qc_prep		= pdc_qc_prep,
 	.qc_issue		= pdc_qc_issue_prot,
-	.data_xfer		= ata_mmio_data_xfer,
-	.eng_timeout		= pdc_eng_timeout,
+	.freeze			= pdc_freeze,
+	.thaw			= pdc_thaw,
+	.error_handler		= pdc_error_handler,
+	.data_xfer		= ata_data_xfer,
 	.irq_handler		= pdc_interrupt,
 	.irq_clear		= pdc_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= pdc_port_start,
-	.port_stop		= pdc_port_stop,
-	.host_stop		= pdc_host_stop,
 };
 
 static const struct ata_port_info pdc_port_info[] = {
 	/* board_2037x */
 	{
 		.sht		= &pdc_ata_sht,
-		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+		.flags		= PDC_COMMON_FLAGS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
-		.port_ops	= &pdc_sata_ops,
+		.port_ops	= &pdc_old_sata_ops,
 	},
 
 	/* board_20319 */
@@ -197,13 +245,13 @@
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
-		.port_ops	= &pdc_sata_ops,
+		.port_ops	= &pdc_old_sata_ops,
 	},
 
 	/* board_20619 */
 	{
 		.sht		= &pdc_ata_sht,
-		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
+		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
@@ -213,7 +261,7 @@
 	/* board_2057x */
 	{
 		.sht		= &pdc_ata_sht,
-		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+		.flags		= PDC_COMMON_FLAGS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
@@ -271,21 +319,22 @@
 	struct pdc_port_priv *pp;
 	int rc;
 
+	/* fix up port flags and cable type for SATA+PATA chips */
+	ap->flags |= hp->port_flags[ap->port_no];
+	if (ap->flags & ATA_FLAG_SATA)
+		ap->cbl = ATA_CBL_SATA;
+
 	rc = ata_port_start(ap);
 	if (rc)
 		return rc;
 
-	pp = kzalloc(sizeof(*pp), GFP_KERNEL);
-	if (!pp) {
-		rc = -ENOMEM;
-		goto err_out;
-	}
+	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
 
-	pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);
-	if (!pp->pkt) {
-		rc = -ENOMEM;
-		goto err_out_kfree;
-	}
+	pp->pkt = dmam_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);
+	if (!pp->pkt)
+		return -ENOMEM;
 
 	ap->private_data = pp;
 
@@ -300,40 +349,11 @@
 	}
 
 	return 0;
-
-err_out_kfree:
-	kfree(pp);
-err_out:
-	ata_port_stop(ap);
-	return rc;
 }
 
-
-static void pdc_port_stop(struct ata_port *ap)
-{
-	struct device *dev = ap->host->dev;
-	struct pdc_port_priv *pp = ap->private_data;
-
-	ap->private_data = NULL;
-	dma_free_coherent(dev, 128, pp->pkt, pp->pkt_dma);
-	kfree(pp);
-	ata_port_stop(ap);
-}
-
-
-static void pdc_host_stop(struct ata_host *host)
-{
-	struct pdc_host_priv *hp = host->private_data;
-
-	ata_pci_host_stop(host);
-
-	kfree(hp);
-}
-
-
 static void pdc_reset_port(struct ata_port *ap)
 {
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
+	void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT;
 	unsigned int i;
 	u32 tmp;
 
@@ -367,28 +387,104 @@
 		ap->cbl = ATA_CBL_PATA80;
 }
 
-static void pdc_pata_phy_reset(struct ata_port *ap)
-{
-	pdc_pata_cbl_detect(ap);
-	pdc_reset_port(ap);
-	ata_port_probe(ap);
-	ata_bus_reset(ap);
-}
-
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
-	if (sc_reg > SCR_CONTROL)
+	if (sc_reg > SCR_CONTROL || ap->cbl != ATA_CBL_SATA)
 		return 0xffffffffU;
-	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
 			       u32 val)
 {
-	if (sc_reg > SCR_CONTROL)
+	if (sc_reg > SCR_CONTROL || ap->cbl != ATA_CBL_SATA)
 		return;
-	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	dma_addr_t sg_table = ap->prd_dma;
+	unsigned int cdb_len = qc->dev->cdb_len;
+	u8 *cdb = qc->cdb;
+	struct pdc_port_priv *pp = ap->private_data;
+	u8 *buf = pp->pkt;
+	u32 *buf32 = (u32 *) buf;
+	unsigned int dev_sel, feature, nbytes;
+
+	/* set control bits (byte 0), zero delay seq id (byte 3),
+	 * and seq id (byte 2)
+	 */
+	switch (qc->tf.protocol) {
+	case ATA_PROT_ATAPI_DMA:
+		if (!(qc->tf.flags & ATA_TFLAG_WRITE))
+			buf32[0] = cpu_to_le32(PDC_PKT_READ);
+		else
+			buf32[0] = 0;
+		break;
+	case ATA_PROT_ATAPI_NODATA:
+		buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
+		break;
+	default:
+		BUG();
+		break;
+	}
+	buf32[1] = cpu_to_le32(sg_table);	/* S/G table addr */
+	buf32[2] = 0;				/* no next-packet */
+
+	/* select drive */
+	if (sata_scr_valid(ap)) {
+		dev_sel = PDC_DEVICE_SATA;
+	} else {
+		dev_sel = ATA_DEVICE_OBS;
+		if (qc->dev->devno != 0)
+			dev_sel |= ATA_DEV1;
+	}
+	buf[12] = (1 << 5) | ATA_REG_DEVICE;
+	buf[13] = dev_sel;
+	buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY;
+	buf[15] = dev_sel; /* once more, waiting for BSY to clear */
+
+	buf[16] = (1 << 5) | ATA_REG_NSECT;
+	buf[17] = 0x00;
+	buf[18] = (1 << 5) | ATA_REG_LBAL;
+	buf[19] = 0x00;
+
+	/* set feature and byte counter registers */
+	if (qc->tf.protocol != ATA_PROT_ATAPI_DMA) {
+		feature = PDC_FEATURE_ATAPI_PIO;
+		/* set byte counter register to real transfer byte count */
+		nbytes = qc->nbytes;
+		if (nbytes > 0xffff)
+			nbytes = 0xffff;
+	} else {
+		feature = PDC_FEATURE_ATAPI_DMA;
+		/* set byte counter register to 0 */
+		nbytes = 0;
+	}
+	buf[20] = (1 << 5) | ATA_REG_FEATURE;
+	buf[21] = feature;
+	buf[22] = (1 << 5) | ATA_REG_BYTEL;
+	buf[23] = nbytes & 0xFF;
+	buf[24] = (1 << 5) | ATA_REG_BYTEH;
+	buf[25] = (nbytes >> 8) & 0xFF;
+
+	/* send ATAPI packet command 0xA0 */
+	buf[26] = (1 << 5) | ATA_REG_CMD;
+	buf[27] = ATA_CMD_PACKET;
+
+	/* select drive and check DRQ */
+	buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY;
+	buf[29] = dev_sel;
+
+	/* we can represent cdb lengths 2/4/6/8/10/12/14/16 */
+	BUG_ON(cdb_len & ~0x1E);
+
+	/* append the CDB as the final part */
+	buf[30] = (((cdb_len >> 1) & 7) << 5) | ATA_REG_DATA | PDC_LAST_REG;
+	memcpy(buf+31, cdb, cdb_len);
 }
 
 static void pdc_qc_prep(struct ata_queued_cmd *qc)
@@ -415,6 +511,17 @@
 		pdc_pkt_footer(&qc->tf, pp->pkt, i);
 		break;
 
+	case ATA_PROT_ATAPI:
+		ata_qc_prep(qc);
+		break;
+
+	case ATA_PROT_ATAPI_DMA:
+		ata_qc_prep(qc);
+		/*FALLTHROUGH*/
+	case ATA_PROT_ATAPI_NODATA:
+		pdc_atapi_pkt(qc);
+		break;
+
 	default:
 		break;
 	}
@@ -447,6 +554,13 @@
 	readl(mmio + PDC_CTLSTAT); /* flush */
 }
 
+static int pdc_pre_reset(struct ata_port *ap)
+{
+	if (!sata_scr_valid(ap))
+		pdc_pata_cbl_detect(ap);
+	return ata_std_prereset(ap);
+}
+
 static void pdc_error_handler(struct ata_port *ap)
 {
 	ata_reset_fn_t hardreset;
@@ -459,7 +573,7 @@
 		hardreset = sata_std_hardreset;
 
 	/* perform recovery */
-	ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
+	ata_do_eh(ap, pdc_pre_reset, ata_std_softreset, hardreset,
 		  ata_std_postreset);
 }
 
@@ -475,49 +589,12 @@
 		pdc_reset_port(ap);
 }
 
-static void pdc_eng_timeout(struct ata_port *ap)
-{
-	struct ata_host *host = ap->host;
-	u8 drv_stat;
-	struct ata_queued_cmd *qc;
-	unsigned long flags;
-
-	DPRINTK("ENTER\n");
-
-	spin_lock_irqsave(&host->lock, flags);
-
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-
-	switch (qc->tf.protocol) {
-	case ATA_PROT_DMA:
-	case ATA_PROT_NODATA:
-		ata_port_printk(ap, KERN_ERR, "command timeout\n");
-		drv_stat = ata_wait_idle(ap);
-		qc->err_mask |= __ac_err_mask(drv_stat);
-		break;
-
-	default:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-		ata_port_printk(ap, KERN_ERR,
-				"unknown timeout, cmd 0x%x stat 0x%x\n",
-				qc->tf.command, drv_stat);
-
-		qc->err_mask |= ac_err_mask(drv_stat);
-		break;
-	}
-
-	spin_unlock_irqrestore(&host->lock, flags);
-	ata_eh_qc_complete(qc);
-	DPRINTK("EXIT\n");
-}
-
 static inline unsigned int pdc_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc)
 {
 	unsigned int handled = 0;
 	u32 tmp;
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
+	void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
 
 	tmp = readl(mmio);
 	if (tmp & PDC_ERR_MASK) {
@@ -528,6 +605,8 @@
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
+	case ATA_PROT_ATAPI_DMA:
+	case ATA_PROT_ATAPI_NODATA:
 		qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
 		ata_qc_complete(qc);
 		handled = 1;
@@ -544,7 +623,7 @@
 static void pdc_irq_clear(struct ata_port *ap)
 {
 	struct ata_host *host = ap->host;
-	void __iomem *mmio = host->mmio_base;
+	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
 
 	readl(mmio + PDC_INT_SEQMASK);
 }
@@ -560,12 +639,12 @@
 
 	VPRINTK("ENTER\n");
 
-	if (!host || !host->mmio_base) {
+	if (!host || !host->iomap[PDC_MMIO_BAR]) {
 		VPRINTK("QUICK EXIT\n");
 		return IRQ_NONE;
 	}
 
-	mmio_base = host->mmio_base;
+	mmio_base = host->iomap[PDC_MMIO_BAR];
 
 	/* reading should also clear interrupts */
 	mask = readl(mmio_base + PDC_INT_SEQMASK);
@@ -610,32 +689,34 @@
 {
 	struct ata_port *ap = qc->ap;
 	struct pdc_port_priv *pp = ap->private_data;
+	void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
 	unsigned int port_no = ap->port_no;
 	u8 seq = (u8) (port_no + 1);
 
 	VPRINTK("ENTER, ap %p\n", ap);
 
-	writel(0x00000001, ap->host->mmio_base + (seq * 4));
-	readl(ap->host->mmio_base + (seq * 4));	/* flush */
+	writel(0x00000001, mmio + (seq * 4));
+	readl(mmio + (seq * 4));	/* flush */
 
 	pp->pkt[2] = seq;
 	wmb();			/* flush PRD, pkt writes */
-	writel(pp->pkt_dma, (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-	readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
+	writel(pp->pkt_dma, ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+	readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
 }
 
 static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
 {
 	switch (qc->tf.protocol) {
+	case ATA_PROT_ATAPI_NODATA:
+		if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
+			break;
+		/*FALLTHROUGH*/
+	case ATA_PROT_ATAPI_DMA:
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
 		pdc_packet_start(qc);
 		return 0;
 
-	case ATA_PROT_ATAPI_DMA:
-		BUG();
-		break;
-
 	default:
 		break;
 	}
@@ -658,8 +739,44 @@
 	ata_exec_command(ap, tf);
 }
 
+static int pdc_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+	u8 *scsicmd = qc->scsicmd->cmnd;
+	int pio = 1; /* atapi dma off by default */
 
-static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base)
+	/* Whitelist commands that may use DMA. */
+	switch (scsicmd[0]) {
+	case WRITE_12:
+	case WRITE_10:
+	case WRITE_6:
+	case READ_12:
+	case READ_10:
+	case READ_6:
+	case 0xad: /* READ_DVD_STRUCTURE */
+	case 0xbe: /* READ_CD */
+		pio = 0;
+	}
+	/* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */
+	if (scsicmd[0] == WRITE_10) {
+		unsigned int lba;
+		lba = (scsicmd[2] << 24) | (scsicmd[3] << 16) | (scsicmd[4] << 8) | scsicmd[5];
+		if (lba >= 0xFFFF4FA2)
+			pio = 1;
+	}
+	return pio;
+}
+
+static int pdc_old_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	/* First generation chips cannot use ATAPI DMA on SATA ports */
+	if (sata_scr_valid(ap))
+		return 1;
+	return pdc_check_atapi_dma(qc);
+}
+
+static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base)
 {
 	port->cmd_addr		= base;
 	port->data_addr		= base;
@@ -679,7 +796,7 @@
 
 static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
 {
-	void __iomem *mmio = pe->mmio_base;
+	void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
 	struct pdc_host_priv *hp = pe->private_data;
 	int hotplug_offset;
 	u32 tmp;
@@ -733,55 +850,43 @@
 static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
-	struct ata_probe_ent *probe_ent = NULL;
+	struct ata_probe_ent *probe_ent;
 	struct pdc_host_priv *hp;
-	unsigned long base;
-	void __iomem *mmio_base;
+	void __iomem *base;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
-	int pci_dev_busy = 0;
 	int rc;
+	u8 tmp;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
-	rc = pci_request_regions(pdev, DRV_NAME);
-	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out;
-	}
+	rc = pcim_iomap_regions(pdev, 1 << PDC_MMIO_BAR, DRV_NAME);
+	if (rc == -EBUSY)
+		pcim_pin_device(pdev);
+	if (rc)
+		return rc;
 
 	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 
-	probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
+	probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		return -ENOMEM;
 
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = pci_iomap(pdev, 3, 0);
-	if (mmio_base == NULL) {
-		rc = -ENOMEM;
-		goto err_out_free_ent;
-	}
-	base = (unsigned long) mmio_base;
-
-	hp = kzalloc(sizeof(*hp), GFP_KERNEL);
-	if (hp == NULL) {
-		rc = -ENOMEM;
-		goto err_out_free_ent;
-	}
+	hp = devm_kzalloc(&pdev->dev, sizeof(*hp), GFP_KERNEL);
+	if (hp == NULL)
+		return -ENOMEM;
 
 	probe_ent->private_data = hp;
 
@@ -794,7 +899,9 @@
 
        	probe_ent->irq = pdev->irq;
        	probe_ent->irq_flags = IRQF_SHARED;
-	probe_ent->mmio_base = mmio_base;
+	probe_ent->iomap = pcim_iomap_table(pdev);
+
+	base = probe_ent->iomap[PDC_MMIO_BAR];
 
 	pdc_ata_setup_port(&probe_ent->port[0], base + 0x200);
 	pdc_ata_setup_port(&probe_ent->port[1], base + 0x280);
@@ -820,7 +927,17 @@
 		hp->flags |= PDC_FLAG_GEN_II;
 		/* Fall through */
 	case board_2037x:
-		probe_ent->n_ports = 2;
+		/* TX2plus boards also have a PATA port */
+		tmp = readb(base + PDC_FLASH_CTL+1);
+		if (!(tmp & 0x80)) {
+			probe_ent->n_ports = 3;
+			pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
+			hp->port_flags[2] = ATA_FLAG_SLAVE_POSS;
+			printk(KERN_INFO DRV_NAME " PATA port found\n");
+		} else
+			probe_ent->n_ports = 2;
+		hp->port_flags[0] = ATA_FLAG_SATA;
+		hp->port_flags[1] = ATA_FLAG_SATA;
 		break;
 	case board_20619:
 		probe_ent->n_ports = 4;
@@ -841,22 +958,11 @@
 	/* initialize adapter */
 	pdc_host_init(board_idx, probe_ent);
 
-	/* FIXME: Need any other frees than hp? */
 	if (!ata_device_add(probe_ent))
-		kfree(hp);
+		return -ENODEV;
 
-	kfree(probe_ent);
-
+	devm_kfree(&pdev->dev, probe_ent);
 	return 0;
-
-err_out_free_ent:
-	kfree(probe_ent);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	if (!pci_dev_busy)
-		pci_disable_device(pdev);
-	return rc;
 }
 
 
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 710909d..6097d8f 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -34,16 +34,16 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
-#include <asm/io.h>
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_qstor"
 #define DRV_VERSION	"0.06"
 
 enum {
+	QS_MMIO_BAR		= 4,
+
 	QS_PORTS		= 4,
 	QS_MAX_PRD		= LIBATA_MAX_PRD,
 	QS_CPB_ORDER		= 6,
@@ -117,7 +117,6 @@
 static irqreturn_t qs_intr (int irq, void *dev_instance);
 static int qs_port_start(struct ata_port *ap);
 static void qs_host_stop(struct ata_host *host);
-static void qs_port_stop(struct ata_port *ap);
 static void qs_phy_reset(struct ata_port *ap);
 static void qs_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
@@ -157,14 +156,15 @@
 	.phy_reset		= qs_phy_reset,
 	.qc_prep		= qs_qc_prep,
 	.qc_issue		= qs_qc_issue,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.eng_timeout		= qs_eng_timeout,
 	.irq_handler		= qs_intr,
 	.irq_clear		= qs_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.scr_read		= qs_scr_read,
 	.scr_write		= qs_scr_write,
 	.port_start		= qs_port_start,
-	.port_stop		= qs_port_stop,
 	.host_stop		= qs_host_stop,
 	.bmdma_stop		= qs_bmdma_stop,
 	.bmdma_status		= qs_bmdma_status,
@@ -197,6 +197,11 @@
 	.remove			= ata_pci_remove_one,
 };
 
+static void __iomem *qs_mmio_base(struct ata_host *host)
+{
+	return host->iomap[QS_MMIO_BAR];
+}
+
 static int qs_check_atapi_dma(struct ata_queued_cmd *qc)
 {
 	return 1;	/* ATAPI DMA not supported */
@@ -219,7 +224,7 @@
 
 static inline void qs_enter_reg_mode(struct ata_port *ap)
 {
-	u8 __iomem *chan = ap->host->mmio_base + (ap->port_no * 0x4000);
+	u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000);
 
 	writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
 	readb(chan + QS_CCT_CTR0);        /* flush */
@@ -227,7 +232,7 @@
 
 static inline void qs_reset_channel_logic(struct ata_port *ap)
 {
-	u8 __iomem *chan = ap->host->mmio_base + (ap->port_no * 0x4000);
+	u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000);
 
 	writeb(QS_CTR1_RCHN, chan + QS_CCT_CTR1);
 	readb(chan + QS_CCT_CTR0);        /* flush */
@@ -257,14 +262,14 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return ~0U;
-	return readl((void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8)));
+	return readl(ap->ioaddr.scr_addr + (sc_reg * 8));
 }
 
 static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
 {
 	if (sc_reg > SCR_CONTROL)
 		return;
-	writel(val, (void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8)));
+	writel(val, ap->ioaddr.scr_addr + (sc_reg * 8));
 }
 
 static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
@@ -325,7 +330,7 @@
 	/* host control block (HCB) */
 	buf[ 0] = QS_HCB_HDR;
 	buf[ 1] = hflags;
-	*(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE);
+	*(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nbytes);
 	*(__le32 *)(&buf[ 8]) = cpu_to_le32(nelem);
 	addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES;
 	*(__le64 *)(&buf[16]) = cpu_to_le64(addr);
@@ -341,7 +346,7 @@
 static inline void qs_packet_start(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	u8 __iomem *chan = ap->host->mmio_base + (ap->port_no * 0x4000);
+	u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000);
 
 	VPRINTK("ENTER, ap %p\n", ap);
 
@@ -378,7 +383,7 @@
 {
 	unsigned int handled = 0;
 	u8 sFFE;
-	u8 __iomem *mmio_base = host->mmio_base;
+	u8 __iomem *mmio_base = qs_mmio_base(host);
 
 	do {
 		u32 sff0 = readl(mmio_base + QS_HST_SFF);
@@ -470,7 +475,7 @@
 	return IRQ_RETVAL(handled);
 }
 
-static void qs_ata_setup_port(struct ata_ioports *port, unsigned long base)
+static void qs_ata_setup_port(struct ata_ioports *port, void __iomem *base)
 {
 	port->cmd_addr		=
 	port->data_addr		= base + 0x400;
@@ -492,7 +497,7 @@
 {
 	struct device *dev = ap->host->dev;
 	struct qs_port_priv *pp;
-	void __iomem *mmio_base = ap->host->mmio_base;
+	void __iomem *mmio_base = qs_mmio_base(ap->host);
 	void __iomem *chan = mmio_base + (ap->port_no * 0x4000);
 	u64 addr;
 	int rc;
@@ -501,17 +506,13 @@
 	if (rc)
 		return rc;
 	qs_enter_reg_mode(ap);
-	pp = kzalloc(sizeof(*pp), GFP_KERNEL);
-	if (!pp) {
-		rc = -ENOMEM;
-		goto err_out;
-	}
-	pp->pkt = dma_alloc_coherent(dev, QS_PKT_BYTES, &pp->pkt_dma,
-								GFP_KERNEL);
-	if (!pp->pkt) {
-		rc = -ENOMEM;
-		goto err_out_kfree;
-	}
+	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
+	pp->pkt = dmam_alloc_coherent(dev, QS_PKT_BYTES, &pp->pkt_dma,
+				      GFP_KERNEL);
+	if (!pp->pkt)
+		return -ENOMEM;
 	memset(pp->pkt, 0, QS_PKT_BYTES);
 	ap->private_data = pp;
 
@@ -519,43 +520,19 @@
 	writel((u32) addr,        chan + QS_CCF_CPBA);
 	writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4);
 	return 0;
-
-err_out_kfree:
-	kfree(pp);
-err_out:
-	ata_port_stop(ap);
-	return rc;
-}
-
-static void qs_port_stop(struct ata_port *ap)
-{
-	struct device *dev = ap->host->dev;
-	struct qs_port_priv *pp = ap->private_data;
-
-	if (pp != NULL) {
-		ap->private_data = NULL;
-		if (pp->pkt != NULL)
-			dma_free_coherent(dev, QS_PKT_BYTES, pp->pkt,
-								pp->pkt_dma);
-		kfree(pp);
-	}
-	ata_port_stop(ap);
 }
 
 static void qs_host_stop(struct ata_host *host)
 {
-	void __iomem *mmio_base = host->mmio_base;
-	struct pci_dev *pdev = to_pci_dev(host->dev);
+	void __iomem *mmio_base = qs_mmio_base(host);
 
 	writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
 	writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
-
-	pci_iounmap(pdev, mmio_base);
 }
 
 static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
 {
-	void __iomem *mmio_base = pe->mmio_base;
+	void __iomem *mmio_base = pe->iomap[QS_MMIO_BAR];
 	unsigned int port_no;
 
 	writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
@@ -630,44 +607,34 @@
 				const struct pci_device_id *ent)
 {
 	static int printed_version;
-	struct ata_probe_ent *probe_ent = NULL;
-	void __iomem *mmio_base;
+	struct ata_probe_ent *probe_ent;
+	void __iomem * const *iomap;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	int rc, port_no;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
-	rc = pci_request_regions(pdev, DRV_NAME);
+	if ((pci_resource_flags(pdev, QS_MMIO_BAR) & IORESOURCE_MEM) == 0)
+		return -ENODEV;
+
+	rc = pcim_iomap_regions(pdev, 1 << QS_MMIO_BAR, DRV_NAME);
 	if (rc)
-		goto err_out;
+		return rc;
+	iomap = pcim_iomap_table(pdev);
 
-	if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
-		rc = -ENODEV;
-		goto err_out_regions;
-	}
-
-	mmio_base = pci_iomap(pdev, 4, 0);
-	if (mmio_base == NULL) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
-
-	rc = qs_set_dma_masks(pdev, mmio_base);
+	rc = qs_set_dma_masks(pdev, iomap[QS_MMIO_BAR]);
 	if (rc)
-		goto err_out_iounmap;
+		return rc;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
-		goto err_out_iounmap;
-	}
+	probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		return -ENOMEM;
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
@@ -680,12 +647,12 @@
 
 	probe_ent->irq		= pdev->irq;
 	probe_ent->irq_flags	= IRQF_SHARED;
-	probe_ent->mmio_base	= mmio_base;
+	probe_ent->iomap	= iomap;
 	probe_ent->n_ports	= QS_PORTS;
 
 	for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
-		unsigned long chan = (unsigned long)mmio_base +
-							(port_no * 0x4000);
+		void __iomem *chan =
+			probe_ent->iomap[QS_MMIO_BAR] + (port_no * 0x4000);
 		qs_ata_setup_port(&probe_ent->port[port_no], chan);
 	}
 
@@ -694,19 +661,11 @@
 	/* initialize adapter */
 	qs_host_init(board_idx, probe_ent);
 
-	rc = ata_device_add(probe_ent);
-	kfree(probe_ent);
-	if (rc != QS_PORTS)
-		goto err_out_iounmap;
-	return 0;
+	if (ata_device_add(probe_ent) != QS_PORTS)
+		return -EIO;
 
-err_out_iounmap:
-	pci_iounmap(pdev, mmio_base);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	pci_disable_device(pdev);
-	return rc;
+	devm_kfree(&pdev->dev, probe_ent);
+	return 0;
 }
 
 static int __init qs_ata_init(void)
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 7808d03..dca3d37 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -49,6 +49,8 @@
 #define DRV_VERSION	"2.0"
 
 enum {
+	SIL_MMIO_BAR		= 5,
+
 	/*
 	 * host flags
 	 */
@@ -200,18 +202,18 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.freeze			= sil_freeze,
 	.thaw			= sil_thaw,
 	.error_handler		= ata_bmdma_error_handler,
 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 	.irq_handler		= sil_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.scr_read		= sil_scr_read,
 	.scr_write		= sil_scr_write,
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_pci_host_stop,
 };
 
 static const struct ata_port_info sil_port_info[] = {
@@ -297,7 +299,8 @@
 {
 	struct ata_host *host = ap->host;
 	struct ata_device *dev;
-	void __iomem *addr = host->mmio_base + sil_port[ap->port_no].xfer_mode;
+	void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR];
+	void __iomem *addr = mmio_base + sil_port[ap->port_no].xfer_mode;
 	u32 tmp, dev_mode[2];
 	unsigned int i;
 
@@ -320,9 +323,9 @@
 	readl(addr);	/* flush */
 }
 
-static inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_reg)
+static inline void __iomem *sil_scr_addr(struct ata_port *ap, unsigned int sc_reg)
 {
-	unsigned long offset = ap->ioaddr.scr_addr;
+	void __iomem *offset = ap->ioaddr.scr_addr;
 
 	switch (sc_reg) {
 	case SCR_STATUS:
@@ -341,7 +344,7 @@
 
 static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
-	void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
+	void __iomem *mmio = sil_scr_addr(ap, sc_reg);
 	if (mmio)
 		return readl(mmio);
 	return 0xffffffffU;
@@ -349,7 +352,7 @@
 
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
 {
-	void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
+	void __iomem *mmio = sil_scr_addr(ap, sc_reg);
 	if (mmio)
 		writel(val, mmio);
 }
@@ -444,7 +447,7 @@
 static irqreturn_t sil_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
-	void __iomem *mmio_base = host->mmio_base;
+	void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR];
 	int handled = 0;
 	int i;
 
@@ -476,7 +479,7 @@
 
 static void sil_freeze(struct ata_port *ap)
 {
-	void __iomem *mmio_base = ap->host->mmio_base;
+	void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR];
 	u32 tmp;
 
 	/* global IRQ mask doesn't block SATA IRQ, turn off explicitly */
@@ -491,7 +494,7 @@
 
 static void sil_thaw(struct ata_port *ap)
 {
-	void __iomem *mmio_base = ap->host->mmio_base;
+	void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR];
 	u32 tmp;
 
 	/* clear IRQ */
@@ -541,9 +544,9 @@
 {
 	int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO;
 	unsigned int n, quirks = 0;
-	unsigned char model_num[41];
+	unsigned char model_num[ATA_ID_PROD_LEN + 1];
 
-	ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
+	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
 	for (n = 0; sil_blacklist[n].product; n++)
 		if (!strcmp(sil_blacklist[n].product, model_num)) {
@@ -621,38 +624,35 @@
 static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
-	struct ata_probe_ent *probe_ent = NULL;
-	unsigned long base;
+	struct device *dev = &pdev->dev;
+	struct ata_probe_ent *probe_ent;
 	void __iomem *mmio_base;
 	int rc;
 	unsigned int i;
-	int pci_dev_busy = 0;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
-	rc = pci_request_regions(pdev, DRV_NAME);
-	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out;
-	}
+	rc = pcim_iomap_regions(pdev, 1 << SIL_MMIO_BAR, DRV_NAME);
+	if (rc == -EBUSY)
+		pcim_pin_device(pdev);
+	if (rc)
+		return rc;
 
 	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 
-	probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
+	probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		return -ENOMEM;
 
 	INIT_LIST_HEAD(&probe_ent->node);
 	probe_ent->dev = pci_dev_to_dev(pdev);
@@ -666,22 +666,16 @@
        	probe_ent->irq_flags = IRQF_SHARED;
 	probe_ent->port_flags = sil_port_info[ent->driver_data].flags;
 
-	mmio_base = pci_iomap(pdev, 5, 0);
-	if (mmio_base == NULL) {
-		rc = -ENOMEM;
-		goto err_out_free_ent;
-	}
+	probe_ent->iomap = pcim_iomap_table(pdev);
 
-	probe_ent->mmio_base = mmio_base;
-
-	base = (unsigned long) mmio_base;
+	mmio_base = probe_ent->iomap[SIL_MMIO_BAR];
 
 	for (i = 0; i < probe_ent->n_ports; i++) {
-		probe_ent->port[i].cmd_addr = base + sil_port[i].tf;
+		probe_ent->port[i].cmd_addr = mmio_base + sil_port[i].tf;
 		probe_ent->port[i].altstatus_addr =
-		probe_ent->port[i].ctl_addr = base + sil_port[i].ctl;
-		probe_ent->port[i].bmdma_addr = base + sil_port[i].bmdma;
-		probe_ent->port[i].scr_addr = base + sil_port[i].scr;
+		probe_ent->port[i].ctl_addr = mmio_base + sil_port[i].ctl;
+		probe_ent->port[i].bmdma_addr = mmio_base + sil_port[i].bmdma;
+		probe_ent->port[i].scr_addr = mmio_base + sil_port[i].scr;
 		ata_std_ports(&probe_ent->port[i]);
 	}
 
@@ -690,30 +684,25 @@
 
 	pci_set_master(pdev);
 
-	/* FIXME: check ata_device_add return value */
-	ata_device_add(probe_ent);
-	kfree(probe_ent);
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
 
+	devm_kfree(dev, probe_ent);
 	return 0;
-
-err_out_free_ent:
-	kfree(probe_ent);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	if (!pci_dev_busy)
-		pci_disable_device(pdev);
-	return rc;
 }
 
 #ifdef CONFIG_PM
 static int sil_pci_device_resume(struct pci_dev *pdev)
 {
 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	int rc;
 
-	ata_pci_device_do_resume(pdev);
+	rc = ata_pci_device_do_resume(pdev);
+	if (rc)
+		return rc;
+
 	sil_init_controller(pdev, host->n_ports, host->ports[0]->flags,
-			    host->mmio_base);
+			    host->iomap[SIL_MMIO_BAR]);
 	ata_host_resume(host);
 
 	return 0;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 5aa288d..e65e8d5 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -28,7 +28,6 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
-#include <asm/io.h>
 
 #define DRV_NAME	"sata_sil24"
 #define DRV_VERSION	"0.3"
@@ -61,6 +60,9 @@
 };
 
 enum {
+	SIL24_HOST_BAR		= 0,
+	SIL24_PORT_BAR		= 2,
+
 	/*
 	 * Global controller registers (128 bytes @ BAR0)
 	 */
@@ -321,12 +323,6 @@
 	struct ata_taskfile tf;			/* Cached taskfile registers */
 };
 
-/* ap->host->private_data */
-struct sil24_host_priv {
-	void __iomem *host_base;	/* global controller control (128 bytes @BAR0) */
-	void __iomem *port_base;	/* port registers (4 * 8192 bytes @BAR2) */
-};
-
 static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev);
 static u8 sil24_check_status(struct ata_port *ap);
 static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
@@ -341,8 +337,6 @@
 static void sil24_error_handler(struct ata_port *ap);
 static void sil24_post_internal_cmd(struct ata_queued_cmd *qc);
 static int sil24_port_start(struct ata_port *ap);
-static void sil24_port_stop(struct ata_port *ap);
-static void sil24_host_stop(struct ata_host *host);
 static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 #ifdef CONFIG_PM
 static int sil24_pci_device_resume(struct pci_dev *pdev);
@@ -362,7 +356,7 @@
 	.name			= DRV_NAME,
 	.id_table		= sil24_pci_tbl,
 	.probe			= sil24_init_one,
-	.remove			= ata_pci_remove_one, /* safe? */
+	.remove			= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend		= ata_pci_device_suspend,
 	.resume			= sil24_pci_device_resume,
@@ -406,6 +400,8 @@
 
 	.irq_handler		= sil24_interrupt,
 	.irq_clear		= sil24_irq_clear,
+	.irq_on			= ata_dummy_irq_on,
+	.irq_ack		= ata_dummy_irq_ack,
 
 	.scr_read		= sil24_scr_read,
 	.scr_write		= sil24_scr_write,
@@ -416,8 +412,6 @@
 	.post_internal_cmd	= sil24_post_internal_cmd,
 
 	.port_start		= sil24_port_start,
-	.port_stop		= sil24_port_stop,
-	.host_stop		= sil24_host_stop,
 };
 
 /*
@@ -467,7 +461,7 @@
 
 static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
 {
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	void __iomem *port = ap->ioaddr.cmd_addr;
 
 	if (dev->cdb_len == 16)
 		writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
@@ -478,7 +472,7 @@
 static inline void sil24_update_tf(struct ata_port *ap)
 {
 	struct sil24_port_priv *pp = ap->private_data;
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	void __iomem *port = ap->ioaddr.cmd_addr;
 	struct sil24_prb __iomem *prb = port;
 	u8 fis[6 * 4];
 
@@ -501,7 +495,7 @@
 
 static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
 {
-	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+	void __iomem *scr_addr = ap->ioaddr.scr_addr;
 	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
 		void __iomem *addr;
 		addr = scr_addr + sil24_scr_map[sc_reg] * 4;
@@ -512,7 +506,7 @@
 
 static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
 {
-	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+	void __iomem *scr_addr = ap->ioaddr.scr_addr;
 	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
 		void __iomem *addr;
 		addr = scr_addr + sil24_scr_map[sc_reg] * 4;
@@ -528,7 +522,7 @@
 
 static int sil24_init_port(struct ata_port *ap)
 {
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	void __iomem *port = ap->ioaddr.cmd_addr;
 	u32 tmp;
 
 	writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
@@ -544,7 +538,7 @@
 
 static int sil24_softreset(struct ata_port *ap, unsigned int *class)
 {
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	void __iomem *port = ap->ioaddr.cmd_addr;
 	struct sil24_port_priv *pp = ap->private_data;
 	struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
 	dma_addr_t paddr = pp->cmd_block_dma;
@@ -604,7 +598,7 @@
 
 static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
 {
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	void __iomem *port = ap->ioaddr.cmd_addr;
 	const char *reason;
 	int tout_msec, rc;
 	u32 tmp;
@@ -721,7 +715,7 @@
 {
 	struct ata_port *ap = qc->ap;
 	struct sil24_port_priv *pp = ap->private_data;
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	void __iomem *port = ap->ioaddr.cmd_addr;
 	unsigned int tag = sil24_tag(qc->tag);
 	dma_addr_t paddr;
 	void __iomem *activate;
@@ -742,7 +736,7 @@
 
 static void sil24_freeze(struct ata_port *ap)
 {
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	void __iomem *port = ap->ioaddr.cmd_addr;
 
 	/* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear
 	 * PORT_IRQ_ENABLE instead.
@@ -752,7 +746,7 @@
 
 static void sil24_thaw(struct ata_port *ap)
 {
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	void __iomem *port = ap->ioaddr.cmd_addr;
 	u32 tmp;
 
 	/* clear IRQ */
@@ -765,7 +759,7 @@
 
 static void sil24_error_intr(struct ata_port *ap)
 {
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	void __iomem *port = ap->ioaddr.cmd_addr;
 	struct ata_eh_info *ehi = &ap->eh_info;
 	int freeze = 0;
 	u32 irq_stat;
@@ -843,7 +837,7 @@
 
 static inline void sil24_host_intr(struct ata_port *ap)
 {
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	void __iomem *port = ap->ioaddr.cmd_addr;
 	u32 slot_stat, qc_active;
 	int rc;
 
@@ -878,12 +872,12 @@
 static irqreturn_t sil24_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
-	struct sil24_host_priv *hpriv = host->private_data;
+	void __iomem *host_base = host->iomap[SIL24_HOST_BAR];
 	unsigned handled = 0;
 	u32 status;
 	int i;
 
-	status = readl(hpriv->host_base + HOST_IRQ_STAT);
+	status = readl(host_base + HOST_IRQ_STAT);
 
 	if (status == 0xffffffff) {
 		printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, "
@@ -938,13 +932,6 @@
 		sil24_init_port(ap);
 }
 
-static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev)
-{
-	const size_t cb_size = sizeof(*pp->cmd_block) * SIL24_MAX_CMDS;
-
-	dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
-}
-
 static int sil24_port_start(struct ata_port *ap)
 {
 	struct device *dev = ap->host->dev;
@@ -952,22 +939,22 @@
 	union sil24_cmd_block *cb;
 	size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS;
 	dma_addr_t cb_dma;
-	int rc = -ENOMEM;
+	int rc;
 
-	pp = kzalloc(sizeof(*pp), GFP_KERNEL);
+	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
 	if (!pp)
-		goto err_out;
+		return -ENOMEM;
 
 	pp->tf.command = ATA_DRDY;
 
-	cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
+	cb = dmam_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
 	if (!cb)
-		goto err_out_pp;
+		return -ENOMEM;
 	memset(cb, 0, cb_size);
 
 	rc = ata_pad_alloc(ap, dev);
 	if (rc)
-		goto err_out_pad;
+		return rc;
 
 	pp->cmd_block = cb;
 	pp->cmd_block_dma = cb_dma;
@@ -975,33 +962,6 @@
 	ap->private_data = pp;
 
 	return 0;
-
-err_out_pad:
-	sil24_cblk_free(pp, dev);
-err_out_pp:
-	kfree(pp);
-err_out:
-	return rc;
-}
-
-static void sil24_port_stop(struct ata_port *ap)
-{
-	struct device *dev = ap->host->dev;
-	struct sil24_port_priv *pp = ap->private_data;
-
-	sil24_cblk_free(pp, dev);
-	ata_pad_free(ap, dev);
-	kfree(pp);
-}
-
-static void sil24_host_stop(struct ata_host *host)
-{
-	struct sil24_host_priv *hpriv = host->private_data;
-	struct pci_dev *pdev = to_pci_dev(host->dev);
-
-	pci_iounmap(pdev, hpriv->host_base);
-	pci_iounmap(pdev, hpriv->port_base);
-	kfree(hpriv);
 }
 
 static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
@@ -1066,43 +1026,32 @@
 static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version = 0;
+	struct device *dev = &pdev->dev;
 	unsigned int board_id = (unsigned int)ent->driver_data;
 	struct ata_port_info *pinfo = &sil24_port_info[board_id];
-	struct ata_probe_ent *probe_ent = NULL;
-	struct sil24_host_priv *hpriv = NULL;
-	void __iomem *host_base = NULL;
-	void __iomem *port_base = NULL;
+	struct ata_probe_ent *probe_ent;
+	void __iomem *host_base;
+	void __iomem *port_base;
 	int i, rc;
 	u32 tmp;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
-	rc = pci_request_regions(pdev, DRV_NAME);
+	rc = pcim_iomap_regions(pdev,
+				(1 << SIL24_HOST_BAR) | (1 << SIL24_PORT_BAR),
+				DRV_NAME);
 	if (rc)
-		goto out_disable;
+		return rc;
 
-	rc = -ENOMEM;
-	/* map mmio registers */
-	host_base = pci_iomap(pdev, 0, 0);
-	if (!host_base)
-		goto out_free;
-	port_base = pci_iomap(pdev, 2, 0);
-	if (!port_base)
-		goto out_free;
-
-	/* allocate & init probe_ent and hpriv */
-	probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
+	/* allocate & init probe_ent */
+	probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
 	if (!probe_ent)
-		goto out_free;
-
-	hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
-	if (!hpriv)
-		goto out_free;
+		return -ENOMEM;
 
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
@@ -1117,10 +1066,10 @@
 
 	probe_ent->irq = pdev->irq;
 	probe_ent->irq_flags = IRQF_SHARED;
-	probe_ent->private_data = hpriv;
+	probe_ent->iomap = pcim_iomap_table(pdev);
 
-	hpriv->host_base = host_base;
-	hpriv->port_base = port_base;
+	host_base = probe_ent->iomap[SIL24_HOST_BAR];
+	port_base = probe_ent->iomap[SIL24_PORT_BAR];
 
 	/*
 	 * Configure the device
@@ -1132,7 +1081,7 @@
 			if (rc) {
 				dev_printk(KERN_ERR, &pdev->dev,
 					   "64-bit DMA enable failed\n");
-				goto out_free;
+				return rc;
 			}
 		}
 	} else {
@@ -1140,13 +1089,13 @@
 		if (rc) {
 			dev_printk(KERN_ERR, &pdev->dev,
 				   "32-bit DMA enable failed\n");
-			goto out_free;
+			return rc;
 		}
 		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc) {
 			dev_printk(KERN_ERR, &pdev->dev,
 				   "32-bit consistent DMA enable failed\n");
-			goto out_free;
+			return rc;
 		}
 	}
 
@@ -1162,11 +1111,10 @@
 	}
 
 	for (i = 0; i < probe_ent->n_ports; i++) {
-		unsigned long portu =
-			(unsigned long)port_base + i * PORT_REGS_SIZE;
+		void __iomem *port = port_base + i * PORT_REGS_SIZE;
 
-		probe_ent->port[i].cmd_addr = portu;
-		probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
+		probe_ent->port[i].cmd_addr = port;
+		probe_ent->port[i].scr_addr = port + PORT_SCONTROL;
 
 		ata_std_ports(&probe_ent->port[i]);
 	}
@@ -1176,38 +1124,30 @@
 
 	pci_set_master(pdev);
 
-	/* FIXME: check ata_device_add return value */
-	ata_device_add(probe_ent);
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
 
-	kfree(probe_ent);
+	devm_kfree(dev, probe_ent);
 	return 0;
-
- out_free:
-	if (host_base)
-		pci_iounmap(pdev, host_base);
-	if (port_base)
-		pci_iounmap(pdev, port_base);
-	kfree(probe_ent);
-	kfree(hpriv);
-	pci_release_regions(pdev);
- out_disable:
-	pci_disable_device(pdev);
-	return rc;
 }
 
 #ifdef CONFIG_PM
 static int sil24_pci_device_resume(struct pci_dev *pdev)
 {
 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	struct sil24_host_priv *hpriv = host->private_data;
+	void __iomem *host_base = host->iomap[SIL24_HOST_BAR];
+	void __iomem *port_base = host->iomap[SIL24_PORT_BAR];
+	int rc;
 
-	ata_pci_device_do_resume(pdev);
+	rc = ata_pci_device_do_resume(pdev);
+	if (rc)
+		return rc;
 
 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
-		writel(HOST_CTRL_GLOBAL_RST, hpriv->host_base + HOST_CTRL);
+		writel(HOST_CTRL_GLOBAL_RST, host_base + HOST_CTRL);
 
 	sil24_init_controller(pdev, host->n_ports, host->ports[0]->flags,
-			      hpriv->host_base, hpriv->port_base);
+			      host_base, port_base);
 
 	ata_host_resume(host);
 
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 9c25a1e..49c9e2b 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -40,9 +40,11 @@
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
+#include "libata.h"
 
+#undef DRV_NAME		/* already defined in libata.h, for libata-core */
 #define DRV_NAME	"sata_sis"
-#define DRV_VERSION	"0.6"
+#define DRV_VERSION	"0.7"
 
 enum {
 	sis_180			= 0,
@@ -67,9 +69,12 @@
 static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 
 static const struct pci_device_id sis_pci_tbl[] = {
-	{ PCI_VDEVICE(SI, 0x180), sis_180 },
-	{ PCI_VDEVICE(SI, 0x181), sis_180 },
-	{ PCI_VDEVICE(SI, 0x182), sis_180 },
+	{ PCI_VDEVICE(SI, 0x0180), sis_180 },		/* SiS 964/180 */
+	{ PCI_VDEVICE(SI, 0x0181), sis_180 },		/* SiS 964/180 */
+	{ PCI_VDEVICE(SI, 0x0182), sis_180 },		/* SiS 965/965L */
+	{ PCI_VDEVICE(SI, 0x0183), sis_180 },		/* SiS 965/965L */
+	{ PCI_VDEVICE(SI, 0x1182), sis_180 },		/* SiS 966/966L */
+	{ PCI_VDEVICE(SI, 0x1183), sis_180 },		/* SiS 966/966L */
 
 	{ }	/* terminate list */
 };
@@ -112,18 +117,18 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
 	.error_handler		= ata_bmdma_error_handler,
 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.scr_read		= sis_scr_read,
 	.scr_write		= sis_scr_write,
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 static struct ata_port_info sis_port_info = {
@@ -135,31 +140,42 @@
 	.port_ops	= &sis_ops,
 };
 
-
 MODULE_AUTHOR("Uwe Koziolek");
 MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
-static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg, int device)
+static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg)
 {
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	unsigned int addr = SIS_SCR_BASE + (4 * sc_reg);
+	u8 pmr;
 
-	if (port_no)  {
-		if (device == 0x182)
-			addr += SIS182_SATA1_OFS;
-		else
-			addr += SIS180_SATA1_OFS;
+	if (ap->port_no)  {
+		switch (pdev->device) {
+			case 0x0180:
+			case 0x0181:
+				pci_read_config_byte(pdev, SIS_PMR, &pmr);
+				if ((pmr & SIS_PMR_COMBINED) == 0)
+					addr += SIS180_SATA1_OFS;
+				break;
+
+			case 0x0182:
+			case 0x0183:
+			case 0x1182:
+			case 0x1183:
+				addr += SIS182_SATA1_OFS;
+				break;
+		}
 	}
-
 	return addr;
 }
 
 static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-	unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device);
+	unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
 	u32 val, val2 = 0;
 	u8 pmr;
 
@@ -170,26 +186,28 @@
 
 	pci_read_config_dword(pdev, cfg_addr, &val);
 
-	if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+	if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
+	    (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
 		pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
 
 	return (val|val2) &  0xfffffffb; /* avoid problems with powerdowned ports */
 }
 
-static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
+static void sis_scr_cfg_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-	unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr, pdev->device);
+	unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
 	u8 pmr;
 
-	if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */
+	if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
 		return;
 
 	pci_read_config_byte(pdev, SIS_PMR, &pmr);
 
 	pci_write_config_dword(pdev, cfg_addr, val);
 
-	if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+	if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
+	    (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
 		pci_write_config_dword(pdev, cfg_addr+0x10, val);
 }
 
@@ -207,10 +225,11 @@
 
 	pci_read_config_byte(pdev, SIS_PMR, &pmr);
 
-	val = inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+	val = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4));
 
-	if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
-		val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10);
+	if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
+	    (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
+		val2 = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10);
 
 	return (val | val2) &  0xfffffffb;
 }
@@ -228,9 +247,10 @@
 	if (ap->flags & SIS_FLAG_CFGSCR)
 		sis_scr_cfg_write(ap, sc_reg, val);
 	else {
-		outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
-		if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
-			outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
+		iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+		if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
+		    (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
+			iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
 	}
 }
 
@@ -241,29 +261,28 @@
 	int rc;
 	u32 genctl, val;
 	struct ata_port_info pi = sis_port_info, *ppi[2] = { &pi, &pi };
-	int pci_dev_busy = 0;
 	u8 pmr;
-	u8 port2_start;
+	u8 port2_start = 0x20;
 
 	if (!printed_version++)
 		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
 	rc = pci_request_regions(pdev, DRV_NAME);
 	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out;
+		pcim_pin_device(pdev);
+		return rc;
 	}
 
 	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 
 	/* check and see if the SCRs are in IO space or PCI cfg space */
 	pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
@@ -282,60 +301,79 @@
 	}
 
 	pci_read_config_byte(pdev, SIS_PMR, &pmr);
-	if (ent->device != 0x182) {
+	switch (ent->device) {
+	case 0x0180:
+	case 0x0181:
+
+		/* The PATA-handling is provided by pata_sis */
+		switch (pmr & 0x30) {
+		case 0x10:
+			ppi[1] = &sis_info133;
+			break;
+			
+		case 0x30:
+			ppi[0] = &sis_info133;
+			break;
+		}
 		if ((pmr & SIS_PMR_COMBINED) == 0) {
 			dev_printk(KERN_INFO, &pdev->dev,
 				   "Detected SiS 180/181/964 chipset in SATA mode\n");
 			port2_start = 64;
-		}
-		else {
+		} else {
 			dev_printk(KERN_INFO, &pdev->dev,
 				   "Detected SiS 180/181 chipset in combined mode\n");
 			port2_start=0;
 			pi.flags |= ATA_FLAG_SLAVE_POSS;
 		}
-	}
-	else {
+		break;
+
+	case 0x0182:
+	case 0x0183:
 		pci_read_config_dword ( pdev, 0x6C, &val);
 		if (val & (1L << 31)) {
 			dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965 chipset\n");
 			pi.flags |= ATA_FLAG_SLAVE_POSS;
-		}
-		else
+		} else {
 			dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965L chipset\n");
-		port2_start = 0x20;
+		}
+		break;
+
+	case 0x1182:
+	case 0x1183:
+		pci_read_config_dword(pdev, 0x64, &val);
+		if (val & 0x10000000) {
+			dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/1183/966L SATA controller\n");
+		} else {
+			dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/1183/966 SATA controller\n");
+			pi.flags |= ATA_FLAG_SLAVE_POSS;
+		}
+		break;
 	}
 
 	probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
-	if (!probe_ent) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
+	if (!probe_ent)
+		return -ENOMEM;
 
 	if (!(probe_ent->port_flags & SIS_FLAG_CFGSCR)) {
-		probe_ent->port[0].scr_addr =
-			pci_resource_start(pdev, SIS_SCR_PCI_BAR);
-		probe_ent->port[1].scr_addr =
-			pci_resource_start(pdev, SIS_SCR_PCI_BAR) + port2_start;
+		void *mmio;
+
+		mmio = pcim_iomap(pdev, SIS_SCR_PCI_BAR, 0);
+		if (!mmio)
+			return -ENOMEM;
+
+		probe_ent->port[0].scr_addr = mmio;
+		probe_ent->port[1].scr_addr = mmio + port2_start;
 	}
 
 	pci_set_master(pdev);
 	pci_intx(pdev, 1);
 
-	/* FIXME: check ata_device_add return value */
-	ata_device_add(probe_ent);
-	kfree(probe_ent);
+	if (!ata_device_add(probe_ent))
+		return -EIO;
 
+	devm_kfree(&pdev->dev, probe_ent);
 	return 0;
 
-err_out_regions:
-	pci_release_regions(pdev);
-
-err_out:
-	if (!pci_dev_busy)
-		pci_disable_device(pdev);
-	return rc;
-
 }
 
 static int __init sis_init(void)
@@ -350,4 +388,3 @@
 
 module_init(sis_init);
 module_exit(sis_exit);
-
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 46d8a94..4e42899 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -116,7 +116,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return 0xffffffffU;
-	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -125,7 +125,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return;
-	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -135,31 +135,31 @@
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
 
 	if (tf->ctl != ap->last_ctl) {
-		writeb(tf->ctl, (void __iomem *) ioaddr->ctl_addr);
+		writeb(tf->ctl, ioaddr->ctl_addr);
 		ap->last_ctl = tf->ctl;
 		ata_wait_idle(ap);
 	}
 	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
 		writew(tf->feature | (((u16)tf->hob_feature) << 8),
-		       (void __iomem *) ioaddr->feature_addr);
+		       ioaddr->feature_addr);
 		writew(tf->nsect | (((u16)tf->hob_nsect) << 8),
-		       (void __iomem *) ioaddr->nsect_addr);
+		       ioaddr->nsect_addr);
 		writew(tf->lbal | (((u16)tf->hob_lbal) << 8),
-		       (void __iomem *) ioaddr->lbal_addr);
+		       ioaddr->lbal_addr);
 		writew(tf->lbam | (((u16)tf->hob_lbam) << 8),
-		       (void __iomem *) ioaddr->lbam_addr);
+		       ioaddr->lbam_addr);
 		writew(tf->lbah | (((u16)tf->hob_lbah) << 8),
-		       (void __iomem *) ioaddr->lbah_addr);
+		       ioaddr->lbah_addr);
 	} else if (is_addr) {
-		writew(tf->feature, (void __iomem *) ioaddr->feature_addr);
-		writew(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
-		writew(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
-		writew(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
-		writew(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
+		writew(tf->feature, ioaddr->feature_addr);
+		writew(tf->nsect, ioaddr->nsect_addr);
+		writew(tf->lbal, ioaddr->lbal_addr);
+		writew(tf->lbam, ioaddr->lbam_addr);
+		writew(tf->lbah, ioaddr->lbah_addr);
 	}
 
 	if (tf->flags & ATA_TFLAG_DEVICE)
-		writeb(tf->device, (void __iomem *) ioaddr->device_addr);
+		writeb(tf->device, ioaddr->device_addr);
 
 	ata_wait_idle(ap);
 }
@@ -171,12 +171,12 @@
 	u16 nsect, lbal, lbam, lbah, feature;
 
 	tf->command = k2_stat_check_status(ap);
-	tf->device = readw((void __iomem *)ioaddr->device_addr);
-	feature = readw((void __iomem *)ioaddr->error_addr);
-	nsect = readw((void __iomem *)ioaddr->nsect_addr);
-	lbal = readw((void __iomem *)ioaddr->lbal_addr);
-	lbam = readw((void __iomem *)ioaddr->lbam_addr);
-	lbah = readw((void __iomem *)ioaddr->lbah_addr);
+	tf->device = readw(ioaddr->device_addr);
+	feature = readw(ioaddr->error_addr);
+	nsect = readw(ioaddr->nsect_addr);
+	lbal = readw(ioaddr->lbal_addr);
+	lbam = readw(ioaddr->lbam_addr);
+	lbah = readw(ioaddr->lbah_addr);
 
 	tf->feature = feature;
 	tf->nsect = nsect;
@@ -262,7 +262,7 @@
 
 static u8 k2_stat_check_status(struct ata_port *ap)
 {
-       	return readl((void *) ap->ioaddr.status_addr);
+       	return readl((void __iomem *) ap->ioaddr.status_addr);
 }
 
 #ifdef CONFIG_PPC_OF
@@ -349,21 +349,21 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
 	.error_handler		= ata_bmdma_error_handler,
 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.scr_read		= k2_sata_scr_read,
 	.scr_write		= k2_sata_scr_write,
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_pci_host_stop,
 };
 
-static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base)
+static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base)
 {
 	port->cmd_addr		= base + K2_SATA_TF_CMD_OFFSET;
 	port->data_addr		= base + K2_SATA_TF_DATA_OFFSET;
@@ -386,12 +386,11 @@
 static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
-	struct ata_probe_ent *probe_ent = NULL;
-	unsigned long base;
+	struct device *dev = &pdev->dev;
+	struct ata_probe_ent *probe_ent;
 	void __iomem *mmio_base;
 	const struct k2_board_info *board_info =
 			&k2_board_info[ent->driver_data];
-	int pci_dev_busy = 0;
 	int rc;
 	int i;
 
@@ -402,7 +401,7 @@
 	 * If this driver happens to only be useful on Apple's K2, then
 	 * we should check that here as it has a normal Serverworks ID
 	 */
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 	/*
@@ -412,36 +411,51 @@
 	if (pci_resource_len(pdev, 5) == 0)
 		return -ENODEV;
 
-	/* Request PCI regions */
-	rc = pci_request_regions(pdev, DRV_NAME);
-	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out;
-	}
+	/* Request and iomap PCI regions */
+	rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
+	if (rc == -EBUSY)
+		pcim_pin_device(pdev);
+	if (rc)
+		return rc;
 
 	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
+	probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		return -ENOMEM;
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = pci_iomap(pdev, 5, 0);
-	if (mmio_base == NULL) {
-		rc = -ENOMEM;
-		goto err_out_free_ent;
-	}
-	base = (unsigned long) mmio_base;
+	probe_ent->sht = &k2_sata_sht;
+	probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				ATA_FLAG_MMIO | board_info->port_flags;
+	probe_ent->port_ops = &k2_sata_ops;
+	probe_ent->n_ports = 4;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = IRQF_SHARED;
+	probe_ent->iomap = pcim_iomap_table(pdev);
+
+	/* We don't care much about the PIO/UDMA masks, but the core won't like us
+	 * if we don't fill these
+	 */
+	probe_ent->pio_mask = 0x1f;
+	probe_ent->mwdma_mask = 0x7;
+	probe_ent->udma_mask = 0x7f;
+
+	mmio_base = probe_ent->iomap[5];
+
+	/* different controllers have different number of ports - currently 4 or 8 */
+	/* All ports are on the same function. Multi-function device is no
+	 * longer available. This should not be seen in any system. */
+	for (i = 0; i < board_info->n_ports; i++)
+		k2_sata_setup_port(&probe_ent->port[i],
+				   mmio_base + i * K2_SATA_PORT_OFFSET);
 
 	/* Clear a magic bit in SCR1 according to Darwin, those help
 	 * some funky seagate drives (though so far, those were already
@@ -454,44 +468,13 @@
 	writel(0xffffffff, mmio_base + K2_SATA_SCR_ERROR_OFFSET);
 	writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
 
-	probe_ent->sht = &k2_sata_sht;
-	probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				ATA_FLAG_MMIO | board_info->port_flags;
-	probe_ent->port_ops = &k2_sata_ops;
-	probe_ent->n_ports = 4;
-	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = IRQF_SHARED;
-	probe_ent->mmio_base = mmio_base;
-
-	/* We don't care much about the PIO/UDMA masks, but the core won't like us
-	 * if we don't fill these
-	 */
-	probe_ent->pio_mask = 0x1f;
-	probe_ent->mwdma_mask = 0x7;
-	probe_ent->udma_mask = 0x7f;
-
-	/* different controllers have different number of ports - currently 4 or 8 */
-	/* All ports are on the same function. Multi-function device is no
-	 * longer available. This should not be seen in any system. */
-	for (i = 0; i < board_info->n_ports; i++)
-		k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET);
-
 	pci_set_master(pdev);
 
-	/* FIXME: check ata_device_add return value */
-	ata_device_add(probe_ent);
-	kfree(probe_ent);
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
 
+	devm_kfree(dev, probe_ent);
 	return 0;
-
-err_out_free_ent:
-	kfree(probe_ent);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	if (!pci_dev_busy)
-		pci_disable_device(pdev);
-	return rc;
 }
 
 /* 0x240 is device ID for Apple K2 device
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index ae7992d..0ebd77b 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -37,12 +37,10 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
-#include <asm/io.h>
 #include "sata_promise.h"
 
 #define DRV_NAME	"sata_sx4"
@@ -50,6 +48,9 @@
 
 
 enum {
+	PDC_MMIO_BAR		= 3,
+	PDC_DIMM_BAR		= 4,
+
 	PDC_PRD_TBL		= 0x44,	/* Direct command DMA table addr */
 
 	PDC_PKT_SUBMIT		= 0x40, /* Command packet pointer addr */
@@ -138,8 +139,6 @@
 };
 
 struct pdc_host_priv {
-	void			__iomem *dimm_mmio;
-
 	unsigned int		doing_hdma;
 	unsigned int		hdma_prod;
 	unsigned int		hdma_cons;
@@ -156,11 +155,9 @@
 static void pdc_eng_timeout(struct ata_port *ap);
 static void pdc_20621_phy_reset (struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
-static void pdc_port_stop(struct ata_port *ap);
 static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
-static void pdc20621_host_stop(struct ata_host *host);
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
 static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
@@ -205,13 +202,13 @@
 	.phy_reset		= pdc_20621_phy_reset,
 	.qc_prep		= pdc20621_qc_prep,
 	.qc_issue		= pdc20621_qc_issue_prot,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.eng_timeout		= pdc_eng_timeout,
 	.irq_handler		= pdc20621_interrupt,
 	.irq_clear		= pdc20621_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.port_start		= pdc_port_start,
-	.port_stop		= pdc_port_stop,
-	.host_stop		= pdc20621_host_stop,
 };
 
 static const struct ata_port_info pdc_port_info[] = {
@@ -243,18 +240,6 @@
 };
 
 
-static void pdc20621_host_stop(struct ata_host *host)
-{
-	struct pci_dev *pdev = to_pci_dev(host->dev);
-	struct pdc_host_priv *hpriv = host->private_data;
-	void __iomem *dimm_mmio = hpriv->dimm_mmio;
-
-	pci_iounmap(pdev, dimm_mmio);
-	kfree(hpriv);
-
-	pci_iounmap(pdev, host->mmio_base);
-}
-
 static int pdc_port_start(struct ata_port *ap)
 {
 	struct device *dev = ap->host->dev;
@@ -265,43 +250,19 @@
 	if (rc)
 		return rc;
 
-	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
-	if (!pp) {
-		rc = -ENOMEM;
-		goto err_out;
-	}
-	memset(pp, 0, sizeof(*pp));
+	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
 
-	pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);
-	if (!pp->pkt) {
-		rc = -ENOMEM;
-		goto err_out_kfree;
-	}
+	pp->pkt = dmam_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);
+	if (!pp->pkt)
+		return -ENOMEM;
 
 	ap->private_data = pp;
 
 	return 0;
-
-err_out_kfree:
-	kfree(pp);
-err_out:
-	ata_port_stop(ap);
-	return rc;
 }
 
-
-static void pdc_port_stop(struct ata_port *ap)
-{
-	struct device *dev = ap->host->dev;
-	struct pdc_port_priv *pp = ap->private_data;
-
-	ap->private_data = NULL;
-	dma_free_coherent(dev, 128, pp->pkt, pp->pkt_dma);
-	kfree(pp);
-	ata_port_stop(ap);
-}
-
-
 static void pdc_20621_phy_reset (struct ata_port *ap)
 {
 	VPRINTK("ENTER\n");
@@ -452,9 +413,8 @@
 	struct scatterlist *sg;
 	struct ata_port *ap = qc->ap;
 	struct pdc_port_priv *pp = ap->private_data;
-	void __iomem *mmio = ap->host->mmio_base;
-	struct pdc_host_priv *hpriv = ap->host->private_data;
-	void __iomem *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
+	void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
 	unsigned int portno = ap->port_no;
 	unsigned int i, idx, total_len = 0, sgt_len;
 	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
@@ -513,9 +473,8 @@
 {
 	struct ata_port *ap = qc->ap;
 	struct pdc_port_priv *pp = ap->private_data;
-	void __iomem *mmio = ap->host->mmio_base;
-	struct pdc_host_priv *hpriv = ap->host->private_data;
-	void __iomem *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
+	void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
 	unsigned int portno = ap->port_no;
 	unsigned int i;
 
@@ -565,7 +524,7 @@
 {
 	struct ata_port *ap = qc->ap;
 	struct ata_host *host = ap->host;
-	void __iomem *mmio = host->mmio_base;
+	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
@@ -619,8 +578,7 @@
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int port_no = ap->port_no;
-	struct pdc_host_priv *hpriv = ap->host->private_data;
-	void *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
 
 	dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP);
 	dimm_mmio += PDC_DIMM_HOST_PKT;
@@ -639,7 +597,7 @@
 	struct ata_port *ap = qc->ap;
 	struct ata_host *host = ap->host;
 	unsigned int port_no = ap->port_no;
-	void __iomem *mmio = host->mmio_base;
+	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 seq = (u8) (port_no + 1);
 	unsigned int port_ofs;
@@ -668,8 +626,8 @@
 		readl(mmio + PDC_20621_SEQCTL + (seq * 4));	/* flush */
 
 		writel(port_ofs + PDC_DIMM_ATA_PKT,
-		       (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-		readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+		       ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+		readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
 		VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
 			port_ofs + PDC_DIMM_ATA_PKT,
 			port_ofs + PDC_DIMM_ATA_PKT,
@@ -747,8 +705,8 @@
 			writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
 			readl(mmio + PDC_20621_SEQCTL + (seq * 4));
 			writel(port_ofs + PDC_DIMM_ATA_PKT,
-			       (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-			readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+			       ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+			readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
 		}
 
 		/* step two - execute ATA command */
@@ -781,7 +739,7 @@
 static void pdc20621_irq_clear(struct ata_port *ap)
 {
 	struct ata_host *host = ap->host;
-	void __iomem *mmio = host->mmio_base;
+	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
 
 	mmio += PDC_CHIP0_OFS;
 
@@ -799,12 +757,12 @@
 
 	VPRINTK("ENTER\n");
 
-	if (!host || !host->mmio_base) {
+	if (!host || !host->iomap[PDC_MMIO_BAR]) {
 		VPRINTK("QUICK EXIT\n");
 		return IRQ_NONE;
 	}
 
-	mmio_base = host->mmio_base;
+	mmio_base = host->iomap[PDC_MMIO_BAR];
 
 	/* reading should also clear interrupts */
 	mmio_base += PDC_CHIP0_OFS;
@@ -905,7 +863,7 @@
 }
 
 
-static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
+static void pdc_sata_setup_port(struct ata_ioports *port, void __iomem *base)
 {
 	port->cmd_addr		= base;
 	port->data_addr		= base;
@@ -931,9 +889,8 @@
 	u16 idx;
 	u8 page_mask;
 	long dist;
-	void __iomem *mmio = pe->mmio_base;
-	struct pdc_host_priv *hpriv = pe->private_data;
-	void __iomem *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
+	void __iomem *dimm_mmio = pe->iomap[PDC_DIMM_BAR];
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
@@ -987,9 +944,8 @@
 	u16 idx;
 	u8 page_mask;
 	long dist;
-	void __iomem *mmio = pe->mmio_base;
-	struct pdc_host_priv *hpriv = pe->private_data;
-	void __iomem *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
+	void __iomem *dimm_mmio = pe->iomap[PDC_DIMM_BAR];
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
@@ -1034,7 +990,7 @@
 static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
 				      u32 subaddr, u32 *pdata)
 {
-	void __iomem *mmio = pe->mmio_base;
+	void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
 	u32 i2creg  = 0;
 	u32 status;
 	u32 count =0;
@@ -1093,7 +1049,7 @@
 	u32 data = 0;
    	int size, i;
    	u8 bdimmsize;
-   	void __iomem *mmio = pe->mmio_base;
+	void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
 	static const struct {
 		unsigned int reg;
 		unsigned int ofs;
@@ -1155,8 +1111,8 @@
 static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
 {
 	u32 data, spd0;
-   	int error, i;
-   	void __iomem *mmio = pe->mmio_base;
+	int error, i;
+	void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
 
 	/* hard-code chip #0 */
    	mmio += PDC_CHIP0_OFS;
@@ -1210,7 +1166,7 @@
 	u32 ticks=0;
 	u32 clock=0;
 	u32 fparam=0;
-   	void __iomem *mmio = pe->mmio_base;
+	void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
 
 	/* hard-code chip #0 */
    	mmio += PDC_CHIP0_OFS;
@@ -1334,7 +1290,7 @@
 static void pdc_20621_init(struct ata_probe_ent *pe)
 {
 	u32 tmp;
-	void __iomem *mmio = pe->mmio_base;
+	void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
@@ -1365,67 +1321,43 @@
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
-	struct ata_probe_ent *probe_ent = NULL;
-	unsigned long base;
-	void __iomem *mmio_base;
-	void __iomem *dimm_mmio = NULL;
-	struct pdc_host_priv *hpriv = NULL;
+	struct ata_probe_ent *probe_ent;
+	void __iomem *base;
+	struct pdc_host_priv *hpriv;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
-	int pci_dev_busy = 0;
 	int rc;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
-	rc = pci_request_regions(pdev, DRV_NAME);
-	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out;
-	}
+	rc = pcim_iomap_regions(pdev, (1 << PDC_MMIO_BAR) | (1 << PDC_DIMM_BAR),
+				DRV_NAME);
+	if (rc == -EBUSY)
+		pcim_pin_device(pdev);
+	if (rc)
+		return rc;
 
 	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
+	probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		return -ENOMEM;
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = pci_iomap(pdev, 3, 0);
-	if (mmio_base == NULL) {
-		rc = -ENOMEM;
-		goto err_out_free_ent;
-	}
-	base = (unsigned long) mmio_base;
-
-	hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
-	if (!hpriv) {
-		rc = -ENOMEM;
-		goto err_out_iounmap;
-	}
-	memset(hpriv, 0, sizeof(*hpriv));
-
-	dimm_mmio = pci_iomap(pdev, 4, 0);
-	if (!dimm_mmio) {
-		kfree(hpriv);
-		rc = -ENOMEM;
-		goto err_out_iounmap;
-	}
-
-	hpriv->dimm_mmio = dimm_mmio;
+	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
+	if (!hpriv)
+		return -ENOMEM;
 
 	probe_ent->sht		= pdc_port_info[board_idx].sht;
 	probe_ent->port_flags	= pdc_port_info[board_idx].flags;
@@ -1436,10 +1368,10 @@
 
        	probe_ent->irq = pdev->irq;
        	probe_ent->irq_flags = IRQF_SHARED;
-	probe_ent->mmio_base = mmio_base;
+	probe_ent->iomap = pcim_iomap_table(pdev);
 
 	probe_ent->private_data = hpriv;
-	base += PDC_CHIP0_OFS;
+	base = probe_ent->iomap[PDC_MMIO_BAR] + PDC_CHIP0_OFS;
 
 	probe_ent->n_ports = 4;
 	pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
@@ -1451,31 +1383,15 @@
 
 	/* initialize adapter */
 	/* initialize local dimm */
-	if (pdc20621_dimm_init(probe_ent)) {
-		rc = -ENOMEM;
-		goto err_out_iounmap_dimm;
-	}
+	if (pdc20621_dimm_init(probe_ent))
+		return -ENOMEM;
 	pdc_20621_init(probe_ent);
 
-	/* FIXME: check ata_device_add return value */
-	ata_device_add(probe_ent);
-	kfree(probe_ent);
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
 
+	devm_kfree(&pdev->dev, probe_ent);
 	return 0;
-
-err_out_iounmap_dimm:		/* only get to this label if 20621 */
-	kfree(hpriv);
-	pci_iounmap(pdev, dimm_mmio);
-err_out_iounmap:
-	pci_iounmap(pdev, mmio_base);
-err_out_free_ent:
-	kfree(probe_ent);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	if (!pci_dev_busy)
-		pci_disable_device(pdev);
-	return rc;
 }
 
 
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index a43aec6..80131ee 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -108,7 +108,7 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
@@ -117,13 +117,13 @@
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.scr_read		= uli_scr_read,
 	.scr_write		= uli_scr_write,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
 static struct ata_port_info uli_port_info = {
@@ -189,62 +189,60 @@
 	struct ata_port_info *ppi[2];
 	int rc;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
-	int pci_dev_busy = 0;
 	struct uli_priv *hpriv;
+	void __iomem * const *iomap;
 
 	if (!printed_version++)
 		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
 	rc = pci_request_regions(pdev, DRV_NAME);
 	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out;
+		pcim_pin_device(pdev);
+		return rc;
 	}
 
 	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 
 	ppi[0] = ppi[1] = &uli_port_info;
 	probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
-	if (!probe_ent) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
+	if (!probe_ent)
+		return -ENOMEM;
 
-	hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
-	if (!hpriv) {
-		rc = -ENOMEM;
-		goto err_out_probe_ent;
-	}
+	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
+	if (!hpriv)
+		return -ENOMEM;
 
 	probe_ent->private_data = hpriv;
 
+	iomap = pcim_iomap_table(pdev);
+
 	switch (board_idx) {
 	case uli_5287:
 		hpriv->scr_cfg_addr[0] = ULI5287_BASE;
 		hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS;
        		probe_ent->n_ports = 4;
 
-       		probe_ent->port[2].cmd_addr = pci_resource_start(pdev, 0) + 8;
+		probe_ent->port[2].cmd_addr = iomap[0] + 8;
 		probe_ent->port[2].altstatus_addr =
-		probe_ent->port[2].ctl_addr =
-			(pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS) + 4;
-		probe_ent->port[2].bmdma_addr = pci_resource_start(pdev, 4) + 16;
+		probe_ent->port[2].ctl_addr = (void __iomem *)
+			((unsigned long)iomap[1] | ATA_PCI_CTL_OFS) + 4;
+		probe_ent->port[2].bmdma_addr = iomap[4] + 16;
 		hpriv->scr_cfg_addr[2] = ULI5287_BASE + ULI5287_OFFS*4;
 
-		probe_ent->port[3].cmd_addr = pci_resource_start(pdev, 2) + 8;
+		probe_ent->port[3].cmd_addr = iomap[2] + 8;
 		probe_ent->port[3].altstatus_addr =
-		probe_ent->port[3].ctl_addr =
-			(pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS) + 4;
-		probe_ent->port[3].bmdma_addr = pci_resource_start(pdev, 4) + 24;
+		probe_ent->port[3].ctl_addr = (void __iomem *)
+			((unsigned long)iomap[3] | ATA_PCI_CTL_OFS) + 4;
+		probe_ent->port[3].bmdma_addr = iomap[4] + 24;
 		hpriv->scr_cfg_addr[3] = ULI5287_BASE + ULI5287_OFFS*5;
 
 		ata_std_ports(&probe_ent->port[2]);
@@ -269,21 +267,11 @@
 	pci_set_master(pdev);
 	pci_intx(pdev, 1);
 
-	/* FIXME: check ata_device_add return value */
-	ata_device_add(probe_ent);
-	kfree(probe_ent);
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
 
+	devm_kfree(&pdev->dev, probe_ent);
 	return 0;
-
-err_out_probe_ent:
-	kfree(probe_ent);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	if (!pci_dev_busy)
-		pci_disable_device(pdev);
-	return rc;
-
 }
 
 static int __init uli_init(void)
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index d3d5c0d..baca6d7 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -44,7 +44,6 @@
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
-#include <asm/io.h>
 
 #define DRV_NAME	"sata_via"
 #define DRV_VERSION	"2.0"
@@ -59,11 +58,14 @@
 	SATA_INT_GATE		= 0x41, /* SATA interrupt gating */
 	SATA_NATIVE_MODE	= 0x42, /* Native mode enable */
 	SATA_PATA_SHARING	= 0x49, /* PATA/SATA sharing func ctrl */
-
+	PATA_UDMA_TIMING	= 0xB3, /* PATA timing for DMA/ cable detect */
+	PATA_PIO_TIMING		= 0xAB, /* PATA timing register */
+	
 	PORT0			= (1 << 1),
 	PORT1			= (1 << 0),
 	ALL_PORTS		= PORT0 | PORT1,
-	N_PORTS			= 2,
+	PATA_PORT		= 2,	/* PATA is port 2 */
+	N_PORTS			= 3,
 
 	NATIVE_MODE_ALL		= (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
 
@@ -76,6 +78,11 @@
 static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static void svia_noop_freeze(struct ata_port *ap);
 static void vt6420_error_handler(struct ata_port *ap);
+static void vt6421_sata_error_handler(struct ata_port *ap);
+static void vt6421_pata_error_handler(struct ata_port *ap);
+static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev);
+static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);
+static int vt6421_port_start(struct ata_port *ap);
 
 static const struct pci_device_id svia_pci_tbl[] = {
 	{ PCI_VDEVICE(VIA, 0x5337), vt6420 },
@@ -127,7 +134,7 @@
 
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.freeze			= svia_noop_freeze,
 	.thaw			= ata_bmdma_thaw,
@@ -136,14 +143,17 @@
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
 };
 
-static const struct ata_port_operations vt6421_sata_ops = {
+static const struct ata_port_operations vt6421_pata_ops = {
 	.port_disable		= ata_port_disable,
+	
+	.set_piomode		= vt6421_set_pio_mode,
+	.set_dmamode		= vt6421_set_dma_mode,
 
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
@@ -158,22 +168,53 @@
 
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
-	.error_handler		= ata_bmdma_error_handler,
+	.error_handler		= vt6421_pata_error_handler,
 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
+
+	.port_start		= vt6421_port_start,
+};
+
+static const struct ata_port_operations vt6421_sata_ops = {
+	.port_disable		= ata_port_disable,
+	
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
+
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
+	.bmdma_stop		= ata_bmdma_stop,
+	.bmdma_status		= ata_bmdma_status,
+
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ata_data_xfer,
+
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= vt6421_sata_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 
 	.scr_read		= svia_scr_read,
 	.scr_write		= svia_scr_write,
 
-	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
+	.port_start		= vt6421_port_start,
 };
 
 static struct ata_port_info vt6420_port_info = {
@@ -195,14 +236,14 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return 0xffffffffU;
-	return inl(ap->ioaddr.scr_addr + (4 * sc_reg));
+	return ioread32(ap->ioaddr.scr_addr + (4 * sc_reg));
 }
 
 static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
 {
 	if (sc_reg > SCR_CONTROL)
 		return;
-	outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
+	iowrite32(val, ap->ioaddr.scr_addr + (4 * sc_reg));
 }
 
 static void svia_noop_freeze(struct ata_port *ap)
@@ -289,6 +330,61 @@
 				  NULL, ata_std_postreset);
 }
 
+static int vt6421_pata_prereset(struct ata_port *ap)
+{
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	u8 tmp;
+
+	pci_read_config_byte(pdev, PATA_UDMA_TIMING, &tmp);
+	if (tmp & 0x10)
+		ap->cbl = ATA_CBL_PATA40;
+	else
+		ap->cbl = ATA_CBL_PATA80;
+	return 0;
+}
+
+static void vt6421_pata_error_handler(struct ata_port *ap)
+{
+	return ata_bmdma_drive_eh(ap, vt6421_pata_prereset, ata_std_softreset,
+				  NULL, ata_std_postreset);
+}
+
+static int vt6421_sata_prereset(struct ata_port *ap)
+{
+	ap->cbl = ATA_CBL_SATA;
+	return 0;
+}
+
+static void vt6421_sata_error_handler(struct ata_port *ap)
+{
+	return ata_bmdma_drive_eh(ap, vt6421_sata_prereset, ata_std_softreset,
+				  NULL, ata_std_postreset);
+}
+
+static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev)
+{
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	static const u8 pio_bits[] = { 0xA8, 0x65, 0x65, 0x31, 0x20 };
+	pci_write_config_byte(pdev, PATA_PIO_TIMING, pio_bits[adev->pio_mode - XFER_PIO_0]);
+}
+
+static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev)
+{
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	static const u8 udma_bits[] = { 0xEE, 0xE8, 0xE6, 0xE4, 0xE2, 0xE1, 0xE0, 0xE0 };
+	pci_write_config_byte(pdev, PATA_UDMA_TIMING, udma_bits[adev->pio_mode - XFER_UDMA_0]);
+}
+
+static int vt6421_port_start(struct ata_port *ap)
+{
+	if (ap->port_no == PATA_PORT) {
+		ap->ops = &vt6421_pata_ops;
+		ap->mwdma_mask = 0;
+		ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST;
+	}
+	return ata_port_start(ap);
+}
+
 static const unsigned int svia_bar_sizes[] = {
 	8, 4, 8, 4, 16, 256
 };
@@ -297,31 +393,28 @@
 	16, 16, 16, 16, 32, 128
 };
 
-static unsigned long svia_scr_addr(unsigned long addr, unsigned int port)
+static void __iomem * svia_scr_addr(void __iomem *addr, unsigned int port)
 {
 	return addr + (port * 128);
 }
 
-static unsigned long vt6421_scr_addr(unsigned long addr, unsigned int port)
+static void __iomem * vt6421_scr_addr(void __iomem *addr, unsigned int port)
 {
 	return addr + (port * 64);
 }
 
 static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
-			      struct pci_dev *pdev,
-			      unsigned int port)
+			      void __iomem * const *iomap, unsigned int port)
 {
-	unsigned long reg_addr = pci_resource_start(pdev, port);
-	unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (port * 8);
-	unsigned long scr_addr;
+	void __iomem *reg_addr = iomap[port];
+	void __iomem *bmdma_addr = iomap[4] + (port * 8);
 
 	probe_ent->port[port].cmd_addr = reg_addr;
 	probe_ent->port[port].altstatus_addr =
-	probe_ent->port[port].ctl_addr = (reg_addr + 8) | ATA_PCI_CTL_OFS;
+	probe_ent->port[port].ctl_addr = (void __iomem *)
+		((unsigned long)(reg_addr + 8) | ATA_PCI_CTL_OFS);
 	probe_ent->port[port].bmdma_addr = bmdma_addr;
-
-	scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port);
-	probe_ent->port[port].scr_addr = scr_addr;
+	probe_ent->port[port].scr_addr = vt6421_scr_addr(iomap[5], port);
 
 	ata_std_ports(&probe_ent->port[port]);
 }
@@ -330,16 +423,16 @@
 {
 	struct ata_probe_ent *probe_ent;
 	struct ata_port_info *ppi[2];
-	
+	void __iomem * const *iomap;
+
 	ppi[0] = ppi[1] = &vt6420_port_info;
 	probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent)
 		return NULL;
 
-	probe_ent->port[0].scr_addr =
-		svia_scr_addr(pci_resource_start(pdev, 5), 0);
-	probe_ent->port[1].scr_addr =
-		svia_scr_addr(pci_resource_start(pdev, 5), 1);
+	iomap = pcim_iomap_table(pdev);
+	probe_ent->port[0].scr_addr = svia_scr_addr(iomap[5], 0);
+	probe_ent->port[1].scr_addr = svia_scr_addr(iomap[5], 1);
 
 	return probe_ent;
 }
@@ -349,7 +442,7 @@
 	struct ata_probe_ent *probe_ent;
 	unsigned int i;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
 	if (!probe_ent)
 		return NULL;
 
@@ -368,7 +461,7 @@
 	probe_ent->udma_mask	= 0x7f;
 
 	for (i = 0; i < N_PORTS; i++)
-		vt6421_init_addrs(probe_ent, pdev, i);
+		vt6421_init_addrs(probe_ent, pcim_iomap_table(pdev), i);
 
 	return probe_ent;
 }
@@ -420,20 +513,19 @@
 	struct ata_probe_ent *probe_ent;
 	int board_id = (int) ent->driver_data;
 	const int *bar_sizes;
-	int pci_dev_busy = 0;
 	u8 tmp8;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
-	rc = pci_request_regions(pdev, DRV_NAME);
+	rc = pcim_iomap_regions(pdev, 0x1f, DRV_NAME);
 	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out;
+		pcim_pin_device(pdev);
+		return rc;
 	}
 
 	if (board_id == vt6420) {
@@ -442,8 +534,7 @@
 			dev_printk(KERN_ERR, &pdev->dev,
 				   "SATA master/slave not supported (0x%x)\n",
 		       		   (int) tmp8);
-			rc = -EIO;
-			goto err_out_regions;
+			return -EIO;
 		}
 
 		bar_sizes = &svia_bar_sizes[0];
@@ -459,16 +550,15 @@
 				i,
 			        (unsigned long long)pci_resource_start(pdev, i),
 			        (unsigned long long)pci_resource_len(pdev, i));
-			rc = -ENODEV;
-			goto err_out_regions;
+			return -ENODEV;
 		}
 
 	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 
 	if (board_id == vt6420)
 		probe_ent = vt6420_init_probe_ent(pdev);
@@ -477,26 +567,18 @@
 
 	if (!probe_ent) {
 		dev_printk(KERN_ERR, &pdev->dev, "out of memory\n");
-		rc = -ENOMEM;
-		goto err_out_regions;
+		return -ENOMEM;
 	}
 
 	svia_configure(pdev);
 
 	pci_set_master(pdev);
 
-	/* FIXME: check ata_device_add return value */
-	ata_device_add(probe_ent);
-	kfree(probe_ent);
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
 
+	devm_kfree(&pdev->dev, probe_ent);
 	return 0;
-
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	if (!pci_dev_busy)
-		pci_disable_device(pdev);
-	return rc;
 }
 
 static int __init svia_init(void)
@@ -511,4 +593,3 @@
 
 module_init(svia_init);
 module_exit(svia_exit);
-
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 0fa1b89..2fd037b 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -50,6 +50,8 @@
 #define DRV_VERSION	"2.0"
 
 enum {
+	VSC_MMIO_BAR			= 0,
+
 	/* Interrupt register offsets (from chip base address) */
 	VSC_SATA_INT_STAT_OFFSET	= 0x00,
 	VSC_SATA_INT_MASK_OFFSET	= 0x04,
@@ -96,7 +98,6 @@
 			      VSC_SATA_INT_PHY_CHANGE),
 };
 
-
 #define is_vsc_sata_int_err(port_idx, int_status) \
 	 (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx)))
 
@@ -105,7 +106,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return 0xffffffffU;
-	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -114,7 +115,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return;
-	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -123,7 +124,7 @@
 	void __iomem *mask_addr;
 	u8 mask;
 
-	mask_addr = ap->host->mmio_base +
+	mask_addr = ap->host->iomap[VSC_MMIO_BAR] +
 		VSC_SATA_INT_MASK_OFFSET + ap->port_no;
 	mask = readb(mask_addr);
 	if (ctl & ATA_NIEN)
@@ -150,25 +151,25 @@
 	}
 	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
 		writew(tf->feature | (((u16)tf->hob_feature) << 8),
-		       (void __iomem *) ioaddr->feature_addr);
+		       ioaddr->feature_addr);
 		writew(tf->nsect | (((u16)tf->hob_nsect) << 8),
-		       (void __iomem *) ioaddr->nsect_addr);
+		       ioaddr->nsect_addr);
 		writew(tf->lbal | (((u16)tf->hob_lbal) << 8),
-		       (void __iomem *) ioaddr->lbal_addr);
+		       ioaddr->lbal_addr);
 		writew(tf->lbam | (((u16)tf->hob_lbam) << 8),
-		       (void __iomem *) ioaddr->lbam_addr);
+		       ioaddr->lbam_addr);
 		writew(tf->lbah | (((u16)tf->hob_lbah) << 8),
-		       (void __iomem *) ioaddr->lbah_addr);
+		       ioaddr->lbah_addr);
 	} else if (is_addr) {
-		writew(tf->feature, (void __iomem *) ioaddr->feature_addr);
-		writew(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
-		writew(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
-		writew(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
-		writew(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
+		writew(tf->feature, ioaddr->feature_addr);
+		writew(tf->nsect, ioaddr->nsect_addr);
+		writew(tf->lbal, ioaddr->lbal_addr);
+		writew(tf->lbam, ioaddr->lbam_addr);
+		writew(tf->lbah, ioaddr->lbah_addr);
 	}
 
 	if (tf->flags & ATA_TFLAG_DEVICE)
-		writeb(tf->device, (void __iomem *) ioaddr->device_addr);
+		writeb(tf->device, ioaddr->device_addr);
 
 	ata_wait_idle(ap);
 }
@@ -180,12 +181,12 @@
 	u16 nsect, lbal, lbam, lbah, feature;
 
 	tf->command = ata_check_status(ap);
-	tf->device = readw((void __iomem *) ioaddr->device_addr);
-	feature = readw((void __iomem *) ioaddr->error_addr);
-	nsect = readw((void __iomem *) ioaddr->nsect_addr);
-	lbal = readw((void __iomem *) ioaddr->lbal_addr);
-	lbam = readw((void __iomem *) ioaddr->lbam_addr);
-	lbah = readw((void __iomem *) ioaddr->lbah_addr);
+	tf->device = readw(ioaddr->device_addr);
+	feature = readw(ioaddr->error_addr);
+	nsect = readw(ioaddr->nsect_addr);
+	lbal = readw(ioaddr->lbal_addr);
+	lbam = readw(ioaddr->lbam_addr);
+	lbah = readw(ioaddr->lbah_addr);
 
 	tf->feature = feature;
 	tf->nsect = nsect;
@@ -217,7 +218,8 @@
 
 	spin_lock(&host->lock);
 
-	int_status = readl(host->mmio_base + VSC_SATA_INT_STAT_OFFSET);
+	int_status = readl(host->iomap[VSC_MMIO_BAR] +
+			   VSC_SATA_INT_STAT_OFFSET);
 
 	for (i = 0; i < host->n_ports; i++) {
 		if (int_status & ((u32) 0xFF << (8 * i))) {
@@ -301,21 +303,22 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_mmio_data_xfer,
+	.data_xfer		= ata_data_xfer,
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
 	.error_handler		= ata_bmdma_error_handler,
 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 	.irq_handler		= vsc_sata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_irq_ack,
 	.scr_read		= vsc_sata_scr_read,
 	.scr_write		= vsc_sata_scr_write,
 	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_pci_host_stop,
 };
 
-static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base)
+static void __devinit vsc_sata_setup_port(struct ata_ioports *port,
+					  void __iomem *base)
 {
 	port->cmd_addr		= base + VSC_SATA_TF_CMD_OFFSET;
 	port->data_addr		= base + VSC_SATA_TF_DATA_OFFSET;
@@ -332,71 +335,66 @@
 	port->ctl_addr		= base + VSC_SATA_TF_CTL_OFFSET;
 	port->bmdma_addr	= base + VSC_SATA_DMA_CMD_OFFSET;
 	port->scr_addr		= base + VSC_SATA_SCR_STATUS_OFFSET;
-	writel(0, (void __iomem *) base + VSC_SATA_UP_DESCRIPTOR_OFFSET);
-	writel(0, (void __iomem *) base + VSC_SATA_UP_DATA_BUFFER_OFFSET);
+	writel(0, base + VSC_SATA_UP_DESCRIPTOR_OFFSET);
+	writel(0, base + VSC_SATA_UP_DATA_BUFFER_OFFSET);
 }
 
 
 static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
-	struct ata_probe_ent *probe_ent = NULL;
-	unsigned long base;
-	int pci_dev_busy = 0;
+	struct ata_probe_ent *probe_ent;
 	void __iomem *mmio_base;
 	int rc;
+	u8 cls;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	rc = pci_enable_device(pdev);
+	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
 
 	/*
 	 * Check if we have needed resource mapped.
 	 */
-	if (pci_resource_len(pdev, 0) == 0) {
-		rc = -ENODEV;
-		goto err_out;
-	}
+	if (pci_resource_len(pdev, 0) == 0)
+		return -ENODEV;
 
-	rc = pci_request_regions(pdev, DRV_NAME);
-	if (rc) {
-		pci_dev_busy = 1;
-		goto err_out;
-	}
+	rc = pcim_iomap_regions(pdev, 1 << VSC_MMIO_BAR, DRV_NAME);
+	if (rc == -EBUSY)
+		pcim_pin_device(pdev);
+	if (rc)
+		return rc;
 
 	/*
 	 * Use 32 bit DMA mask, because 64 bit address support is poor.
 	 */
 	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 	rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
 	if (rc)
-		goto err_out_regions;
+		return rc;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
-	memset(probe_ent, 0, sizeof(*probe_ent));
+	probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		return -ENOMEM;
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = pci_iomap(pdev, 0, 0);
-	if (mmio_base == NULL) {
-		rc = -ENOMEM;
-		goto err_out_free_ent;
-	}
-	base = (unsigned long) mmio_base;
-
 	/*
-	 * Due to a bug in the chip, the default cache line size can't be used
+	 * Due to a bug in the chip, the default cache line size can't be
+	 * used (unless the default is non-zero).
 	 */
-	pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80);
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cls);
+	if (cls == 0x00)
+		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80);
+
+	if (pci_enable_msi(pdev) == 0)
+		pci_intx(pdev, 0);
+	else
+		probe_ent->irq_flags = IRQF_SHARED;
 
 	probe_ent->sht = &vsc_sata_sht;
 	probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
@@ -404,8 +402,7 @@
 	probe_ent->port_ops = &vsc_sata_ops;
 	probe_ent->n_ports = 4;
 	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = IRQF_SHARED;
-	probe_ent->mmio_base = mmio_base;
+	probe_ent->iomap = pcim_iomap_table(pdev);
 
 	/* We don't care much about the PIO/UDMA masks, but the core won't like us
 	 * if we don't fill these
@@ -414,11 +411,13 @@
 	probe_ent->mwdma_mask = 0x07;
 	probe_ent->udma_mask = 0x7f;
 
+	mmio_base = probe_ent->iomap[VSC_MMIO_BAR];
+
 	/* We have 4 ports per PCI function */
-	vsc_sata_setup_port(&probe_ent->port[0], base + 1 * VSC_SATA_PORT_OFFSET);
-	vsc_sata_setup_port(&probe_ent->port[1], base + 2 * VSC_SATA_PORT_OFFSET);
-	vsc_sata_setup_port(&probe_ent->port[2], base + 3 * VSC_SATA_PORT_OFFSET);
-	vsc_sata_setup_port(&probe_ent->port[3], base + 4 * VSC_SATA_PORT_OFFSET);
+	vsc_sata_setup_port(&probe_ent->port[0], mmio_base + 1 * VSC_SATA_PORT_OFFSET);
+	vsc_sata_setup_port(&probe_ent->port[1], mmio_base + 2 * VSC_SATA_PORT_OFFSET);
+	vsc_sata_setup_port(&probe_ent->port[2], mmio_base + 3 * VSC_SATA_PORT_OFFSET);
+	vsc_sata_setup_port(&probe_ent->port[3], mmio_base + 4 * VSC_SATA_PORT_OFFSET);
 
 	pci_set_master(pdev);
 
@@ -430,20 +429,11 @@
 	 */
 	pci_write_config_dword(pdev, 0x98, 0);
 
-	/* FIXME: check ata_device_add return value */
-	ata_device_add(probe_ent);
-	kfree(probe_ent);
+	if (!ata_device_add(probe_ent))
+		return -ENODEV;
 
+	devm_kfree(&pdev->dev, probe_ent);
 	return 0;
-
-err_out_free_ent:
-	kfree(probe_ent);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	if (!pci_dev_busy)
-		pci_disable_device(pdev);
-	return rc;
 }
 
 static const struct pci_device_id vsc_sata_pci_tbl[] = {
diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c
index ac2c108..8d60c4eb 100644
--- a/drivers/atm/adummy.c
+++ b/drivers/atm/adummy.c
@@ -13,7 +13,6 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 5aab7bd..8fccf01 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -912,7 +912,6 @@
 		free_page((unsigned long) eni_dev->free_list);
 		return -ENOMEM;
 	}
-	memset(eni_dev->rx_map,0,PAGE_SIZE);
 	eni_dev->rx_mult = DEFAULT_RX_MULT;
 	eni_dev->fast = eni_dev->last_fast = NULL;
 	eni_dev->slow = eni_dev->last_slow = NULL;
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 4aeb3d0..a7c0ed3 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/capability.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/pci.h>
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index db33f6f..8510026 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -3017,7 +3017,7 @@
 	he_writel(he_dev, val, HOST_CNTL);
        
 	/* Send READ instruction */
-	for (i = 0; i < sizeof(readtab)/sizeof(readtab[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(readtab); i++) {
 		he_writel(he_dev, val | readtab[i], HOST_CNTL);
 		udelay(EEPROM_DELAY);
 	}
diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c
index 325325a..0bd657f 100644
--- a/drivers/atm/idt77105.c
+++ b/drivers/atm/idt77105.c
@@ -4,7 +4,6 @@
 
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index f407861..b4b8014 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -388,7 +388,7 @@
 
 	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
 
-	for (i = 0; i < sizeof(rdsrtab)/sizeof(rdsrtab[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
 		idt77252_write_gp(card, gp | rdsrtab[i]);
 		udelay(5);
 	}
@@ -422,7 +422,7 @@
 
 	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
 
-	for (i = 0; i < sizeof(rdtab)/sizeof(rdtab[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(rdtab); i++) {
 		idt77252_write_gp(card, gp | rdtab[i]);
 		udelay(5);
 	}
@@ -469,14 +469,14 @@
 
 	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
 
-	for (i = 0; i < sizeof(wrentab)/sizeof(wrentab[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(wrentab); i++) {
 		idt77252_write_gp(card, gp | wrentab[i]);
 		udelay(5);
 	}
 	idt77252_write_gp(card, gp | SAR_GP_EECS);
 	udelay(5);
 
-	for (i = 0; i < sizeof(wrtab)/sizeof(wrtab[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(wrtab); i++) {
 		idt77252_write_gp(card, gp | wrtab[i]);
 		udelay(5);
 	}
diff --git a/drivers/atm/nicstarmac.c b/drivers/atm/nicstarmac.c
index 2c5e3ae..480947f 100644
--- a/drivers/atm/nicstarmac.c
+++ b/drivers/atm/nicstarmac.c
@@ -7,6 +7,8 @@
  * Read this ForeRunner's MAC address from eprom/eeprom
  */
 
+#include <linux/kernel.h>
+
 typedef void __iomem *virt_addr_t;
 
 #define CYCLE_DELAY 5
@@ -176,7 +178,7 @@
    val = NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) & 0xFFFFFFF0;
 
    /* Send READ instruction */
-   for (i=0; i<sizeof readtab/sizeof readtab[0]; i++)
+   for (i=0; i<ARRAY_SIZE(readtab); i++)
    {
 	NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
 		(val | readtab[i]) );
diff --git a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c
index 9504cce..fc8cb07 100644
--- a/drivers/atm/uPD98402.c
+++ b/drivers/atm/uPD98402.c
@@ -4,7 +4,6 @@
  
 
 #include <linux/module.h>
-#include <linux/sched.h> /* for jiffies */
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/atmdev.h>
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 756d4f7..0d7091e 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -4,7 +4,6 @@
 
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
new file mode 100644
index 0000000..0300e7f5
--- /dev/null
+++ b/drivers/auxdisplay/Kconfig
@@ -0,0 +1,109 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+# Auxiliary display drivers configuration.
+#
+
+menu "Auxiliary Display support"
+
+config KS0108
+	tristate "KS0108 LCD Controller"
+	depends on PARPORT_PC
+	default n
+	---help---
+	  If you have a LCD controlled by one or more KS0108
+	  controllers, say Y. You will need also another more specific
+	  driver for your LCD.
+
+	  Depends on Parallel Port support. If you say Y at
+	  parport, you will be able to compile this as a module (M)
+	  and built-in as well (Y).
+
+	  To compile this as a module, choose M here:
+	  the module will be called ks0108.
+
+	  If unsure, say N.
+
+config KS0108_PORT
+	hex "Parallel port where the LCD is connected"
+	depends on KS0108
+	default 0x378
+	---help---
+	  The address of the parallel port where the LCD is connected.
+
+	  The first  standard parallel port address is 0x378.
+	  The second standard parallel port address is 0x278.
+	  The third  standard parallel port address is 0x3BC.
+
+	  You can specify a different address if you need.
+
+	  If you don't know what I'm talking about, load the parport module,
+	  and execute "dmesg" or "cat /proc/ioports". You can see there how
+	  many parallel ports are present and which address each one has.
+
+	  Usually you only need to use 0x378.
+
+	  If you compile this as a module, you can still override this
+	  using the module parameters.
+
+config KS0108_DELAY
+	int "Delay between each control writing (microseconds)"
+	depends on KS0108
+	default "2"
+	---help---
+	  Amount of time the ks0108 should wait between each control write
+	  to the parallel port.
+
+	  If your driver seems to miss random writings, increment this.
+
+	  If you don't know what I'm talking about, ignore it.
+
+	  If you compile this as a module, you can still override this
+	  value using the module parameters.
+
+config CFAG12864B
+	tristate "CFAG12864B LCD"
+	depends on X86
+	depends on FB
+	depends on KS0108
+	default n
+	---help---
+	  If you have a Crystalfontz 128x64 2-color LCD, cfag12864b Series,
+	  say Y. You also need the ks0108 LCD Controller driver.
+
+	  For help about how to wire your LCD to the parallel port,
+	  check Documentation/auxdisplay/cfag12864b
+
+	  Depends on the x86 arch and the framebuffer support.
+
+	  The LCD framebuffer driver can be attached to a console.
+	  It will work fine. However, you can't attach it to the fbdev driver
+	  of the xorg server.
+
+	  To compile this as a module, choose M here:
+	  the modules will be called cfag12864b and cfag12864bfb.
+
+	  If unsure, say N.
+
+config CFAG12864B_RATE
+       int "Refresh rate (hertz)"
+	depends on CFAG12864B
+	default "20"
+	---help---
+	  Refresh rate of the LCD.
+
+	  As the LCD is not memory mapped, the driver has to make the work by
+	  software. This means you should be careful setting this value higher.
+	  If your CPUs are really slow or you feel the system is slowed down,
+	  decrease the value.
+
+	  Be careful modifying this value to a very high value:
+	  You can freeze the computer, or the LCD maybe can't draw as fast as you
+	  are requesting.
+
+	  If you don't know what I'm talking about, ignore it.
+
+	  If you compile this as a module, you can still override this
+	  value using the module parameters.
+endmenu
diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile
new file mode 100644
index 0000000..8a8936a
--- /dev/null
+++ b/drivers/auxdisplay/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the kernel auxiliary displays device drivers.
+#
+
+obj-$(CONFIG_KS0108)		+= ks0108.o
+obj-$(CONFIG_CFAG12864B)	+= cfag12864b.o cfag12864bfb.o
diff --git a/drivers/auxdisplay/cfag12864b.c b/drivers/auxdisplay/cfag12864b.c
new file mode 100644
index 0000000..cb44cb4
--- /dev/null
+++ b/drivers/auxdisplay/cfag12864b.c
@@ -0,0 +1,402 @@
+/*
+ *    Filename: cfag12864b.c
+ *     Version: 0.1.0
+ * Description: cfag12864b LCD driver
+ *     License: GPLv2
+ *     Depends: ks0108
+ *
+ *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *        Date: 2006-10-31
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+#include <linux/ks0108.h>
+#include <linux/cfag12864b.h>
+
+
+#define CFAG12864B_NAME "cfag12864b"
+
+/*
+ * Module Parameters
+ */
+
+static unsigned int cfag12864b_rate = CONFIG_CFAG12864B_RATE;
+module_param(cfag12864b_rate, uint, S_IRUGO);
+MODULE_PARM_DESC(cfag12864b_rate,
+	"Refresh rate (hertzs)");
+
+unsigned int cfag12864b_getrate(void)
+{
+	return cfag12864b_rate;
+}
+
+/*
+ * cfag12864b Commands
+ *
+ *	E = Enable signal
+ *		Everytime E switch from low to high,
+ *		cfag12864b/ks0108 reads the command/data.
+ *
+ *	CS1 = First ks0108controller.
+ *		If high, the first ks0108 controller receives commands/data.
+ *
+ *	CS2 = Second ks0108 controller
+ *		If high, the second ks0108 controller receives commands/data.
+ *
+ *	DI = Data/Instruction
+ *		If low, cfag12864b will expect commands.
+ *		If high, cfag12864b will expect data.
+ *
+ */
+
+#define bit(n) (((unsigned char)1)<<(n))
+
+#define CFAG12864B_BIT_E	(0)
+#define CFAG12864B_BIT_CS1	(2)
+#define CFAG12864B_BIT_CS2	(1)
+#define CFAG12864B_BIT_DI	(3)
+
+static unsigned char cfag12864b_state;
+
+static void cfag12864b_set(void)
+{
+	ks0108_writecontrol(cfag12864b_state);
+}
+
+static void cfag12864b_setbit(unsigned char state, unsigned char n)
+{
+	if (state)
+		cfag12864b_state |= bit(n);
+	else
+		cfag12864b_state &= ~bit(n);
+}
+
+static void cfag12864b_e(unsigned char state)
+{
+	cfag12864b_setbit(state, CFAG12864B_BIT_E);
+	cfag12864b_set();
+}
+
+static void cfag12864b_cs1(unsigned char state)
+{
+	cfag12864b_setbit(state, CFAG12864B_BIT_CS1);
+}
+
+static void cfag12864b_cs2(unsigned char state)
+{
+	cfag12864b_setbit(state, CFAG12864B_BIT_CS2);
+}
+
+static void cfag12864b_di(unsigned char state)
+{
+	cfag12864b_setbit(state, CFAG12864B_BIT_DI);
+}
+
+static void cfag12864b_setcontrollers(unsigned char first,
+	unsigned char second)
+{
+	if (first)
+		cfag12864b_cs1(0);
+	else
+		cfag12864b_cs1(1);
+
+	if (second)
+		cfag12864b_cs2(0);
+	else
+		cfag12864b_cs2(1);
+}
+
+static void cfag12864b_controller(unsigned char which)
+{
+	if (which == 0)
+		cfag12864b_setcontrollers(1, 0);
+	else if (which == 1)
+		cfag12864b_setcontrollers(0, 1);
+}
+
+static void cfag12864b_displaystate(unsigned char state)
+{
+	cfag12864b_di(0);
+	cfag12864b_e(1);
+	ks0108_displaystate(state);
+	cfag12864b_e(0);
+}
+
+static void cfag12864b_address(unsigned char address)
+{
+	cfag12864b_di(0);
+	cfag12864b_e(1);
+	ks0108_address(address);
+	cfag12864b_e(0);
+}
+
+static void cfag12864b_page(unsigned char page)
+{
+	cfag12864b_di(0);
+	cfag12864b_e(1);
+	ks0108_page(page);
+	cfag12864b_e(0);
+}
+
+static void cfag12864b_startline(unsigned char startline)
+{
+	cfag12864b_di(0);
+	cfag12864b_e(1);
+	ks0108_startline(startline);
+	cfag12864b_e(0);
+}
+
+static void cfag12864b_writebyte(unsigned char byte)
+{
+	cfag12864b_di(1);
+	cfag12864b_e(1);
+	ks0108_writedata(byte);
+	cfag12864b_e(0);
+}
+
+static void cfag12864b_nop(void)
+{
+	cfag12864b_startline(0);
+}
+
+/*
+ * cfag12864b Internal Commands
+ */
+
+static void cfag12864b_on(void)
+{
+	cfag12864b_setcontrollers(1, 1);
+	cfag12864b_displaystate(1);
+}
+
+static void cfag12864b_off(void)
+{
+	cfag12864b_setcontrollers(1, 1);
+	cfag12864b_displaystate(0);
+}
+
+static void cfag12864b_clear(void)
+{
+	unsigned char i, j;
+
+	cfag12864b_setcontrollers(1, 1);
+	for (i = 0; i < CFAG12864B_PAGES; i++) {
+		cfag12864b_page(i);
+		cfag12864b_address(0);
+		for (j = 0; j < CFAG12864B_ADDRESSES; j++)
+			cfag12864b_writebyte(0);
+	}
+}
+
+/*
+ * Update work
+ */
+
+unsigned char *cfag12864b_buffer;
+static unsigned char *cfag12864b_cache;
+static DEFINE_MUTEX(cfag12864b_mutex);
+static unsigned char cfag12864b_updating;
+static void cfag12864b_update(struct work_struct *delayed_work);
+static struct workqueue_struct *cfag12864b_workqueue;
+static DECLARE_DELAYED_WORK(cfag12864b_work, cfag12864b_update);
+
+static void cfag12864b_queue(void)
+{
+	queue_delayed_work(cfag12864b_workqueue, &cfag12864b_work,
+		HZ / cfag12864b_rate);
+}
+
+unsigned char cfag12864b_enable(void)
+{
+	unsigned char ret;
+
+	mutex_lock(&cfag12864b_mutex);
+
+	if (!cfag12864b_updating) {
+		cfag12864b_updating = 1;
+		cfag12864b_queue();
+		ret = 0;
+	} else
+		ret = 1;
+
+	mutex_unlock(&cfag12864b_mutex);
+
+	return ret;
+}
+
+void cfag12864b_disable(void)
+{
+	mutex_lock(&cfag12864b_mutex);
+
+	if (cfag12864b_updating) {
+		cfag12864b_updating = 0;
+		cancel_delayed_work(&cfag12864b_work);
+		flush_workqueue(cfag12864b_workqueue);
+	}
+
+	mutex_unlock(&cfag12864b_mutex);
+}
+
+unsigned char cfag12864b_isenabled(void)
+{
+	return cfag12864b_updating;
+}
+
+static void cfag12864b_update(struct work_struct *work)
+{
+	unsigned char c;
+	unsigned short i, j, k, b;
+
+	if (memcmp(cfag12864b_cache, cfag12864b_buffer, CFAG12864B_SIZE)) {
+		for (i = 0; i < CFAG12864B_CONTROLLERS; i++) {
+			cfag12864b_controller(i);
+			cfag12864b_nop();
+			for (j = 0; j < CFAG12864B_PAGES; j++) {
+				cfag12864b_page(j);
+				cfag12864b_nop();
+				cfag12864b_address(0);
+				cfag12864b_nop();
+				for (k = 0; k < CFAG12864B_ADDRESSES; k++) {
+					for (c = 0, b = 0; b < 8; b++)
+						if (cfag12864b_buffer
+							[i * CFAG12864B_ADDRESSES / 8
+							+ k / 8 + (j * 8 + b) *
+							CFAG12864B_WIDTH / 8]
+							& bit(k % 8))
+							c |= bit(b);
+					cfag12864b_writebyte(c);
+				}
+			}
+		}
+
+		memcpy(cfag12864b_cache, cfag12864b_buffer, CFAG12864B_SIZE);
+	}
+
+	if (cfag12864b_updating)
+		cfag12864b_queue();
+}
+
+/*
+ * cfag12864b Exported Symbols
+ */
+
+EXPORT_SYMBOL_GPL(cfag12864b_buffer);
+EXPORT_SYMBOL_GPL(cfag12864b_getrate);
+EXPORT_SYMBOL_GPL(cfag12864b_enable);
+EXPORT_SYMBOL_GPL(cfag12864b_disable);
+EXPORT_SYMBOL_GPL(cfag12864b_isenabled);
+
+/*
+ * Is the module inited?
+ */
+
+static unsigned char cfag12864b_inited;
+unsigned char cfag12864b_isinited(void)
+{
+	return cfag12864b_inited;
+}
+EXPORT_SYMBOL_GPL(cfag12864b_isinited);
+
+/*
+ * Module Init & Exit
+ */
+
+static int __init cfag12864b_init(void)
+{
+	int ret = -EINVAL;
+
+	/* ks0108_init() must be called first */
+	if (!ks0108_isinited()) {
+		printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
+			"ks0108 is not initialized\n");
+		goto none;
+	}
+
+	if (PAGE_SIZE < CFAG12864B_SIZE) {
+		printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
+			"page size (%i) < cfag12864b size (%i)\n",
+			(unsigned int)PAGE_SIZE, CFAG12864B_SIZE);
+		ret = -ENOMEM;
+		goto none;
+	}
+
+	cfag12864b_buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
+	if (cfag12864b_buffer == NULL) {
+		printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
+			"can't get a free page\n");
+		ret = -ENOMEM;
+		goto none;
+	}
+
+	cfag12864b_cache = kmalloc(sizeof(unsigned char) *
+		CFAG12864B_SIZE, GFP_KERNEL);
+	if (cfag12864b_buffer == NULL) {
+		printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
+			"can't alloc cache buffer (%i bytes)\n",
+			CFAG12864B_SIZE);
+		ret = -ENOMEM;
+		goto bufferalloced;
+	}
+
+	cfag12864b_workqueue = create_singlethread_workqueue(CFAG12864B_NAME);
+	if (cfag12864b_workqueue == NULL)
+		goto cachealloced;
+
+	memset(cfag12864b_buffer, 0, CFAG12864B_SIZE);
+
+	cfag12864b_clear();
+	cfag12864b_on();
+
+	cfag12864b_inited = 1;
+	return 0;
+
+cachealloced:
+	kfree(cfag12864b_cache);
+
+bufferalloced:
+	free_page((unsigned long) cfag12864b_buffer);
+
+none:
+	return ret;
+}
+
+static void __exit cfag12864b_exit(void)
+{
+	cfag12864b_disable();
+	cfag12864b_off();
+	destroy_workqueue(cfag12864b_workqueue);
+	kfree(cfag12864b_cache);
+	free_page((unsigned long) cfag12864b_buffer);
+}
+
+module_init(cfag12864b_init);
+module_exit(cfag12864b_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>");
+MODULE_DESCRIPTION("cfag12864b LCD driver");
diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c
new file mode 100644
index 0000000..66fafbb
--- /dev/null
+++ b/drivers/auxdisplay/cfag12864bfb.c
@@ -0,0 +1,188 @@
+/*
+ *    Filename: cfag12864bfb.c
+ *     Version: 0.1.0
+ * Description: cfag12864b LCD framebuffer driver
+ *     License: GPLv2
+ *     Depends: cfag12864b
+ *
+ *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *        Date: 2006-10-31
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <linux/cfag12864b.h>
+
+#define CFAG12864BFB_NAME "cfag12864bfb"
+
+static struct fb_fix_screeninfo cfag12864bfb_fix __initdata = {
+	.id = "cfag12864b",
+	.type = FB_TYPE_PACKED_PIXELS,
+	.visual = FB_VISUAL_MONO10,
+	.xpanstep = 0,
+	.ypanstep = 0,
+	.ywrapstep = 0,
+	.line_length = CFAG12864B_WIDTH / 8,
+	.accel = FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo cfag12864bfb_var __initdata = {
+	.xres = CFAG12864B_WIDTH,
+	.yres = CFAG12864B_HEIGHT,
+	.xres_virtual = CFAG12864B_WIDTH,
+	.yres_virtual = CFAG12864B_HEIGHT,
+	.bits_per_pixel = 1,
+	.red = { 0, 1, 0 },
+      	.green = { 0, 1, 0 },
+      	.blue = { 0, 1, 0 },
+	.left_margin = 0,
+	.right_margin = 0,
+	.upper_margin = 0,
+	.lower_margin = 0,
+	.vmode = FB_VMODE_NONINTERLACED,
+};
+
+static int cfag12864bfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	return vm_insert_page(vma, vma->vm_start,
+		virt_to_page(cfag12864b_buffer));
+}
+
+static struct fb_ops cfag12864bfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_mmap = cfag12864bfb_mmap,
+};
+
+static int __init cfag12864bfb_probe(struct platform_device *device)
+{
+	int ret = -EINVAL;
+ 	struct fb_info *info = framebuffer_alloc(0, &device->dev);
+
+	if (!info)
+		goto none;
+
+	info->screen_base = (char __iomem *) cfag12864b_buffer;
+	info->screen_size = CFAG12864B_SIZE;
+	info->fbops = &cfag12864bfb_ops;
+	info->fix = cfag12864bfb_fix;
+	info->var = cfag12864bfb_var;
+	info->pseudo_palette = NULL;
+	info->par = NULL;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	if (register_framebuffer(info) < 0)
+		goto fballoced;
+
+	platform_set_drvdata(device, info);
+
+	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+		info->fix.id);
+
+	return 0;
+
+fballoced:
+	framebuffer_release(info);
+
+none:
+	return ret;
+}
+
+static int cfag12864bfb_remove(struct platform_device *device)
+{
+	struct fb_info *info = platform_get_drvdata(device);
+
+	if (info) {
+		unregister_framebuffer(info);
+		framebuffer_release(info);
+	}
+
+	return 0;
+}
+
+static struct platform_driver cfag12864bfb_driver = {
+	.probe	= cfag12864bfb_probe,
+	.remove = cfag12864bfb_remove,
+	.driver = {
+		.name	= CFAG12864BFB_NAME,
+	},
+};
+
+static struct platform_device *cfag12864bfb_device;
+
+static int __init cfag12864bfb_init(void)
+{
+	int ret = -EINVAL;
+
+	/* cfag12864b_init() must be called first */
+	if (!cfag12864b_isinited()) {
+		printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: "
+			"cfag12864b is not initialized\n");
+		goto none;
+	}
+
+	if (cfag12864b_enable()) {
+		printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: "
+			"can't enable cfag12864b refreshing (being used)\n");
+		return -ENODEV;
+	}
+
+	ret = platform_driver_register(&cfag12864bfb_driver);
+
+	if (!ret) {
+		cfag12864bfb_device =
+			platform_device_alloc(CFAG12864BFB_NAME, 0);
+
+		if (cfag12864bfb_device)
+			ret = platform_device_add(cfag12864bfb_device);
+		else
+			ret = -ENOMEM;
+
+		if (ret) {
+			platform_device_put(cfag12864bfb_device);
+			platform_driver_unregister(&cfag12864bfb_driver);
+		}
+	}
+
+none:
+	return ret;
+}
+
+static void __exit cfag12864bfb_exit(void)
+{
+	platform_device_unregister(cfag12864bfb_device);
+	platform_driver_unregister(&cfag12864bfb_driver);
+	cfag12864b_disable();
+}
+
+module_init(cfag12864bfb_init);
+module_exit(cfag12864bfb_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>");
+MODULE_DESCRIPTION("cfag12864b LCD framebuffer driver");
diff --git a/drivers/auxdisplay/ks0108.c b/drivers/auxdisplay/ks0108.c
new file mode 100644
index 0000000..e6c3646
--- /dev/null
+++ b/drivers/auxdisplay/ks0108.c
@@ -0,0 +1,178 @@
+/*
+ *    Filename: ks0108.c
+ *     Version: 0.1.0
+ * Description: ks0108 LCD Controller driver
+ *     License: GPLv2
+ *     Depends: parport
+ *
+ *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *        Date: 2006-10-31
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/parport.h>
+#include <linux/uaccess.h>
+#include <linux/ks0108.h>
+
+#define KS0108_NAME "ks0108"
+
+/*
+ * Module Parameters
+ */
+
+static unsigned int ks0108_port = CONFIG_KS0108_PORT;
+module_param(ks0108_port, uint, S_IRUGO);
+MODULE_PARM_DESC(ks0108_port, "Parallel port where the LCD is connected");
+
+static unsigned int ks0108_delay = CONFIG_KS0108_DELAY;
+module_param(ks0108_delay, uint, S_IRUGO);
+MODULE_PARM_DESC(ks0108_delay, "Delay between each control writing (microseconds)");
+
+/*
+ * Device
+ */
+
+static struct parport *ks0108_parport;
+static struct pardevice *ks0108_pardevice;
+
+/*
+ * ks0108 Exported Commands (don't lock)
+ *
+ *   You _should_ lock in the top driver: This functions _should not_
+ *   get race conditions in any way. Locking for each byte here would be
+ *   so slow and useless.
+ *
+ *   There are not bit definitions because they are not flags,
+ *   just arbitrary combinations defined by the documentation for each
+ *   function in the ks0108 LCD controller. If you want to know what means
+ *   a specific combination, look at the function's name.
+ *
+ *   The ks0108_writecontrol bits need to be reverted ^(0,1,3) because
+ *   the parallel port also revert them using a "not" logic gate.
+ */
+
+#define bit(n) (((unsigned char)1)<<(n))
+
+void ks0108_writedata(unsigned char byte)
+{
+	parport_write_data(ks0108_parport, byte);
+}
+
+void ks0108_writecontrol(unsigned char byte)
+{
+	udelay(ks0108_delay);
+	parport_write_control(ks0108_parport, byte ^ (bit(0) | bit(1) | bit(3)));
+}
+
+void ks0108_displaystate(unsigned char state)
+{
+	ks0108_writedata((state ? bit(0) : 0) | bit(1) | bit(2) | bit(3) | bit(4) | bit(5));
+}
+
+void ks0108_startline(unsigned char startline)
+{
+	ks0108_writedata(min(startline,(unsigned char)63) | bit(6) | bit(7));
+}
+
+void ks0108_address(unsigned char address)
+{
+	ks0108_writedata(min(address,(unsigned char)63) | bit(6));
+}
+
+void ks0108_page(unsigned char page)
+{
+	ks0108_writedata(min(page,(unsigned char)7) | bit(3) | bit(4) | bit(5) | bit(7));
+}
+
+EXPORT_SYMBOL_GPL(ks0108_writedata);
+EXPORT_SYMBOL_GPL(ks0108_writecontrol);
+EXPORT_SYMBOL_GPL(ks0108_displaystate);
+EXPORT_SYMBOL_GPL(ks0108_startline);
+EXPORT_SYMBOL_GPL(ks0108_address);
+EXPORT_SYMBOL_GPL(ks0108_page);
+
+/*
+ * Is the module inited?
+ */
+
+static unsigned char ks0108_inited;
+unsigned char ks0108_isinited(void)
+{
+	return ks0108_inited;
+}
+EXPORT_SYMBOL_GPL(ks0108_isinited);
+
+/*
+ * Module Init & Exit
+ */
+
+static int __init ks0108_init(void)
+{
+	int result;
+	int ret = -EINVAL;
+
+	ks0108_parport = parport_find_base(ks0108_port);
+	if (ks0108_parport == NULL) {
+		printk(KERN_ERR KS0108_NAME ": ERROR: "
+			"parport didn't find %i port\n", ks0108_port);
+		goto none;
+	}
+
+	ks0108_pardevice = parport_register_device(ks0108_parport, KS0108_NAME,
+		NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+	if (ks0108_pardevice == NULL) {
+		printk(KERN_ERR KS0108_NAME ": ERROR: "
+			"parport didn't register new device\n");
+		goto none;
+	}
+
+	result = parport_claim(ks0108_pardevice);
+	if (result != 0) {
+		printk(KERN_ERR KS0108_NAME ": ERROR: "
+			"can't claim %i parport, maybe in use\n", ks0108_port);
+		ret = result;
+		goto registered;
+	}
+
+	ks0108_inited = 1;
+	return 0;
+
+registered:
+	parport_unregister_device(ks0108_pardevice);
+
+none:
+	return ret;
+}
+
+static void __exit ks0108_exit(void)
+{
+	parport_release(ks0108_pardevice);
+	parport_unregister_device(ks0108_pardevice);
+}
+
+module_init(ks0108_init);
+module_exit(ks0108_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>");
+MODULE_DESCRIPTION("ks0108 LCD Controller driver");
+
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 1429f3a2..5d6312e3 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -37,6 +37,18 @@
 
 	  If you are unsure about this, say N here.
 
+config DEBUG_DEVRES
+	bool "Managed device resources verbose debug messages"
+	depends on DEBUG_KERNEL
+	help
+	  This option enables kernel parameter devres.log. If set to
+	  non-zero, devres debug messages are printed. Select this if
+	  you are having a problem with devres or want to debug
+	  resource management for a managed device. devres.log can be
+	  switched on and off from sysfs node.
+
+	  If you are unsure about this, Say N here.
+
 config SYS_HYPERVISOR
 	bool
 	default n
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 7bbb9ee..e9eb738 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -3,6 +3,7 @@
 obj-y			:= core.o sys.o bus.o dd.o \
 			   driver.o class.o platform.o \
 			   cpu.o firmware.o init.o map.o dmapool.o \
+			   dma-mapping.o devres.o \
 			   attribute_container.o transport_class.o
 obj-y			+= power/
 obj-$(CONFIG_ISA)	+= isa.o
diff --git a/drivers/base/base.h b/drivers/base/base.h
index d26644a..de7e144 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -44,3 +44,4 @@
 
 extern char *make_class_name(const char *name, struct kobject *kobj);
 
+extern void devres_release_all(struct device *dev);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 472810f..253868e 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -324,27 +324,25 @@
 	return error;
 }
 
-static int device_add_attrs(struct bus_type * bus, struct device * dev)
+static int device_add_attrs(struct bus_type *bus, struct device *dev)
 {
 	int error = 0;
 	int i;
 
-	if (bus->dev_attrs) {
-		for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
-			error = device_create_file(dev,&bus->dev_attrs[i]);
-			if (error)
-				goto Err;
+	if (!bus->dev_attrs)
+		return 0;
+
+	for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
+		error = device_create_file(dev,&bus->dev_attrs[i]);
+		if (error) {
+			while (--i >= 0)
+				device_remove_file(dev, &bus->dev_attrs[i]);
+			break;
 		}
 	}
- Done:
 	return error;
- Err:
-	while (--i >= 0)
-		device_remove_file(dev,&bus->dev_attrs[i]);
-	goto Done;
 }
 
-
 static void device_remove_attrs(struct bus_type * bus, struct device * dev)
 {
 	int i;
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 96def1d..d596812 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -163,8 +163,7 @@
 void class_unregister(struct class * cls)
 {
 	pr_debug("device class '%s': unregistering\n", cls->name);
-	if (cls->virtual_dir)
-		kobject_unregister(cls->virtual_dir);
+	kobject_unregister(cls->virtual_dir);
 	remove_class_attrs(cls);
 	subsystem_unregister(&cls->subsys);
 }
@@ -841,48 +840,6 @@
 		class_device_unregister(class_dev);
 }
 
-int class_device_rename(struct class_device *class_dev, char *new_name)
-{
-	int error = 0;
-	char *old_class_name = NULL, *new_class_name = NULL;
-
-	class_dev = class_device_get(class_dev);
-	if (!class_dev)
-		return -EINVAL;
-
-	pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
-		 new_name);
-
-#ifdef CONFIG_SYSFS_DEPRECATED
-	if (class_dev->dev)
-		old_class_name = make_class_name(class_dev->class->name,
-						 &class_dev->kobj);
-#endif
-
-	strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
-
-	error = kobject_rename(&class_dev->kobj, new_name);
-
-#ifdef CONFIG_SYSFS_DEPRECATED
-	if (class_dev->dev) {
-		new_class_name = make_class_name(class_dev->class->name,
-						 &class_dev->kobj);
-		if (new_class_name)
-			sysfs_create_link(&class_dev->dev->kobj,
-					  &class_dev->kobj, new_class_name);
-		if (old_class_name)
-			sysfs_remove_link(&class_dev->dev->kobj,
-						old_class_name);
-	}
-#endif
-	class_device_put(class_dev);
-
-	kfree(old_class_name);
-	kfree(new_class_name);
-
-	return error;
-}
-
 struct class_device * class_device_get(struct class_device *class_dev)
 {
 	if (class_dev)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index e136142..cf2a398 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -28,6 +28,20 @@
 int (*platform_notify_remove)(struct device * dev) = NULL;
 
 /*
+ * Detect the LANANA-assigned LOCAL/EXPERIMENTAL majors
+ */
+bool is_lanana_major(unsigned int major)
+{
+	if (major >= 60 && major <= 63)
+		return 1;
+	if (major >= 120 && major <= 127)
+		return 1;
+	if (major >= 240 && major <= 254)
+		return 1;
+	return 0;
+}
+
+/*
  * sysfs bindings for devices.
  */
 
@@ -428,6 +442,8 @@
 	INIT_LIST_HEAD(&dev->dma_pools);
 	INIT_LIST_HEAD(&dev->node);
 	init_MUTEX(&dev->sem);
+	spin_lock_init(&dev->devres_lock);
+	INIT_LIST_HEAD(&dev->devres_head);
 	device_init_wakeup(dev, 0);
 	set_dev_node(dev, -1);
 }
@@ -621,12 +637,41 @@
 					     BUS_NOTIFY_DEL_DEVICE, dev);
 	device_remove_groups(dev);
  GroupError:
- 	device_remove_attrs(dev);
+	device_remove_attrs(dev);
  AttrsError:
 	if (dev->devt_attr) {
 		device_remove_file(dev, dev->devt_attr);
 		kfree(dev->devt_attr);
 	}
+
+	if (dev->class) {
+		sysfs_remove_link(&dev->kobj, "subsystem");
+		/* If this is not a "fake" compatible device, remove the
+		 * symlink from the class to the device. */
+		if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
+			sysfs_remove_link(&dev->class->subsys.kset.kobj,
+					  dev->bus_id);
+#ifdef CONFIG_SYSFS_DEPRECATED
+		if (parent) {
+			char *class_name = make_class_name(dev->class->name,
+							   &dev->kobj);
+			if (class_name)
+				sysfs_remove_link(&dev->parent->kobj,
+						  class_name);
+			kfree(class_name);
+			sysfs_remove_link(&dev->kobj, "device");
+		}
+#endif
+
+		down(&dev->class->sem);
+		/* notify any interfaces that the device is now gone */
+		list_for_each_entry(class_intf, &dev->class->interfaces, node)
+			if (class_intf->remove_dev)
+				class_intf->remove_dev(dev, class_intf);
+		/* remove the device from the class list */
+		list_del_init(&dev->node);
+		up(&dev->class->sem);
+	}
  ueventattrError:
 	device_remove_file(dev, &dev->uevent_attr);
  attrError:
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 7fd095e..fe7ef33 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -103,7 +103,7 @@
 #endif
 
 /*
- * register_cpu - Setup a driverfs device for a CPU.
+ * register_cpu - Setup a sysfs device for a CPU.
  * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
  *	  sysfs for this CPU.
  * @num - CPU number to use when creating the device.
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index b5bf243..6a48824 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -112,6 +112,7 @@
 	atomic_inc(&probe_count);
 	pr_debug("%s: Probing driver %s with device %s\n",
 		 drv->bus->name, drv->name, dev->bus_id);
+	WARN_ON(!list_empty(&dev->devres_head));
 
 	dev->driver = drv;
 	if (driver_sysfs_add(dev)) {
@@ -137,6 +138,7 @@
 	goto done;
 
 probe_failed:
+	devres_release_all(dev);
 	driver_sysfs_remove(dev);
 	dev->driver = NULL;
 
@@ -327,6 +329,7 @@
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+		devres_release_all(dev);
 		dev->driver = NULL;
 		put_driver(drv);
 	}
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
new file mode 100644
index 0000000..e177c95
--- /dev/null
+++ b/drivers/base/devres.c
@@ -0,0 +1,644 @@
+/*
+ * drivers/base/devres.c - device resource management
+ *
+ * Copyright (c) 2006  SUSE Linux Products GmbH
+ * Copyright (c) 2006  Tejun Heo <teheo@suse.de>
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+
+struct devres_node {
+	struct list_head		entry;
+	dr_release_t			release;
+#ifdef CONFIG_DEBUG_DEVRES
+	const char			*name;
+	size_t				size;
+#endif
+};
+
+struct devres {
+	struct devres_node		node;
+	/* -- 3 pointers */
+	unsigned long long		data[];	/* guarantee ull alignment */
+};
+
+struct devres_group {
+	struct devres_node		node[2];
+	void				*id;
+	int				color;
+	/* -- 8 pointers */
+};
+
+#ifdef CONFIG_DEBUG_DEVRES
+static int log_devres = 0;
+module_param_named(log, log_devres, int, S_IRUGO | S_IWUSR);
+
+static void set_node_dbginfo(struct devres_node *node, const char *name,
+			     size_t size)
+{
+	node->name = name;
+	node->size = size;
+}
+
+static void devres_log(struct device *dev, struct devres_node *node,
+		       const char *op)
+{
+	if (unlikely(log_devres))
+		dev_printk(KERN_ERR, dev, "DEVRES %3s %p %s (%lu bytes)\n",
+			   op, node, node->name, (unsigned long)node->size);
+}
+#else /* CONFIG_DEBUG_DEVRES */
+#define set_node_dbginfo(node, n, s)	do {} while (0)
+#define devres_log(dev, node, op)	do {} while (0)
+#endif /* CONFIG_DEBUG_DEVRES */
+
+/*
+ * Release functions for devres group.  These callbacks are used only
+ * for identification.
+ */
+static void group_open_release(struct device *dev, void *res)
+{
+	/* noop */
+}
+
+static void group_close_release(struct device *dev, void *res)
+{
+	/* noop */
+}
+
+static struct devres_group * node_to_group(struct devres_node *node)
+{
+	if (node->release == &group_open_release)
+		return container_of(node, struct devres_group, node[0]);
+	if (node->release == &group_close_release)
+		return container_of(node, struct devres_group, node[1]);
+	return NULL;
+}
+
+static __always_inline struct devres * alloc_dr(dr_release_t release,
+						size_t size, gfp_t gfp)
+{
+	size_t tot_size = sizeof(struct devres) + size;
+	struct devres *dr;
+
+	dr = kmalloc_track_caller(tot_size, gfp);
+	if (unlikely(!dr))
+		return NULL;
+
+	memset(dr, 0, tot_size);
+	INIT_LIST_HEAD(&dr->node.entry);
+	dr->node.release = release;
+	return dr;
+}
+
+static void add_dr(struct device *dev, struct devres_node *node)
+{
+	devres_log(dev, node, "ADD");
+	BUG_ON(!list_empty(&node->entry));
+	list_add_tail(&node->entry, &dev->devres_head);
+}
+
+/**
+ * devres_alloc - Allocate device resource data
+ * @release: Release function devres will be associated with
+ * @size: Allocation size
+ * @gfp: Allocation flags
+ *
+ * allocate devres of @size bytes.  The allocated area is zeroed, then
+ * associated with @release.  The returned pointer can be passed to
+ * other devres_*() functions.
+ *
+ * RETURNS:
+ * Pointer to allocated devres on success, NULL on failure.
+ */
+#ifdef CONFIG_DEBUG_DEVRES
+void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
+		      const char *name)
+{
+	struct devres *dr;
+
+	dr = alloc_dr(release, size, gfp);
+	if (unlikely(!dr))
+		return NULL;
+	set_node_dbginfo(&dr->node, name, size);
+	return dr->data;
+}
+EXPORT_SYMBOL_GPL(__devres_alloc);
+#else
+void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
+{
+	struct devres *dr;
+
+	dr = alloc_dr(release, size, gfp);
+	if (unlikely(!dr))
+		return NULL;
+	return dr->data;
+}
+EXPORT_SYMBOL_GPL(devres_alloc);
+#endif
+
+/**
+ * devres_free - Free device resource data
+ * @res: Pointer to devres data to free
+ *
+ * Free devres created with devres_alloc().
+ */
+void devres_free(void *res)
+{
+	if (res) {
+		struct devres *dr = container_of(res, struct devres, data);
+
+		BUG_ON(!list_empty(&dr->node.entry));
+		kfree(dr);
+	}
+}
+EXPORT_SYMBOL_GPL(devres_free);
+
+/**
+ * devres_add - Register device resource
+ * @dev: Device to add resource to
+ * @res: Resource to register
+ *
+ * Register devres @res to @dev.  @res should have been allocated
+ * using devres_alloc().  On driver detach, the associated release
+ * function will be invoked and devres will be freed automatically.
+ */
+void devres_add(struct device *dev, void *res)
+{
+	struct devres *dr = container_of(res, struct devres, data);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->devres_lock, flags);
+	add_dr(dev, &dr->node);
+	spin_unlock_irqrestore(&dev->devres_lock, flags);
+}
+EXPORT_SYMBOL_GPL(devres_add);
+
+static struct devres *find_dr(struct device *dev, dr_release_t release,
+			      dr_match_t match, void *match_data)
+{
+	struct devres_node *node;
+
+	list_for_each_entry_reverse(node, &dev->devres_head, entry) {
+		struct devres *dr = container_of(node, struct devres, node);
+
+		if (node->release != release)
+			continue;
+		if (match && !match(dev, dr->data, match_data))
+			continue;
+		return dr;
+	}
+
+	return NULL;
+}
+
+/**
+ * devres_find - Find device resource
+ * @dev: Device to lookup resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev which is associated with @release
+ * and for which @match returns 1.  If @match is NULL, it's considered
+ * to match all.
+ *
+ * RETURNS:
+ * Pointer to found devres, NULL if not found.
+ */
+void * devres_find(struct device *dev, dr_release_t release,
+		   dr_match_t match, void *match_data)
+{
+	struct devres *dr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->devres_lock, flags);
+	dr = find_dr(dev, release, match, match_data);
+	spin_unlock_irqrestore(&dev->devres_lock, flags);
+
+	if (dr)
+		return dr->data;
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(devres_find);
+
+/**
+ * devres_get - Find devres, if non-existent, add one atomically
+ * @dev: Device to lookup or add devres for
+ * @new_res: Pointer to new initialized devres to add if not found
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev which has the same release function
+ * as @new_res and for which @match return 1.  If found, @new_res is
+ * freed; otherwise, @new_res is added atomically.
+ *
+ * RETURNS:
+ * Pointer to found or added devres.
+ */
+void * devres_get(struct device *dev, void *new_res,
+		  dr_match_t match, void *match_data)
+{
+	struct devres *new_dr = container_of(new_res, struct devres, data);
+	struct devres *dr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->devres_lock, flags);
+	dr = find_dr(dev, new_dr->node.release, match, match_data);
+	if (!dr) {
+		add_dr(dev, &new_dr->node);
+		dr = new_dr;
+		new_dr = NULL;
+	}
+	spin_unlock_irqrestore(&dev->devres_lock, flags);
+	devres_free(new_dr);
+
+	return dr->data;
+}
+EXPORT_SYMBOL_GPL(devres_get);
+
+/**
+ * devres_remove - Find a device resource and remove it
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1.  If @match is NULL, it's considered to
+ * match all.  If found, the resource is removed atomically and
+ * returned.
+ *
+ * RETURNS:
+ * Pointer to removed devres on success, NULL if not found.
+ */
+void * devres_remove(struct device *dev, dr_release_t release,
+		     dr_match_t match, void *match_data)
+{
+	struct devres *dr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->devres_lock, flags);
+	dr = find_dr(dev, release, match, match_data);
+	if (dr) {
+		list_del_init(&dr->node.entry);
+		devres_log(dev, &dr->node, "REM");
+	}
+	spin_unlock_irqrestore(&dev->devres_lock, flags);
+
+	if (dr)
+		return dr->data;
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(devres_remove);
+
+/**
+ * devres_destroy - Find a device resource and destroy it
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1.  If @match is NULL, it's considered to
+ * match all.  If found, the resource is removed atomically and freed.
+ *
+ * RETURNS:
+ * 0 if devres is found and freed, -ENOENT if not found.
+ */
+int devres_destroy(struct device *dev, dr_release_t release,
+		   dr_match_t match, void *match_data)
+{
+	void *res;
+
+	res = devres_remove(dev, release, match, match_data);
+	if (unlikely(!res))
+		return -ENOENT;
+
+	devres_free(res);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devres_destroy);
+
+static int remove_nodes(struct device *dev,
+			struct list_head *first, struct list_head *end,
+			struct list_head *todo)
+{
+	int cnt = 0, nr_groups = 0;
+	struct list_head *cur;
+
+	/* First pass - move normal devres entries to @todo and clear
+	 * devres_group colors.
+	 */
+	cur = first;
+	while (cur != end) {
+		struct devres_node *node;
+		struct devres_group *grp;
+
+		node = list_entry(cur, struct devres_node, entry);
+		cur = cur->next;
+
+		grp = node_to_group(node);
+		if (grp) {
+			/* clear color of group markers in the first pass */
+			grp->color = 0;
+			nr_groups++;
+		} else {
+			/* regular devres entry */
+			if (&node->entry == first)
+				first = first->next;
+			list_move_tail(&node->entry, todo);
+			cnt++;
+		}
+	}
+
+	if (!nr_groups)
+		return cnt;
+
+	/* Second pass - Scan groups and color them.  A group gets
+	 * color value of two iff the group is wholly contained in
+	 * [cur, end).  That is, for a closed group, both opening and
+	 * closing markers should be in the range, while just the
+	 * opening marker is enough for an open group.
+	 */
+	cur = first;
+	while (cur != end) {
+		struct devres_node *node;
+		struct devres_group *grp;
+
+		node = list_entry(cur, struct devres_node, entry);
+		cur = cur->next;
+
+		grp = node_to_group(node);
+		BUG_ON(!grp || list_empty(&grp->node[0].entry));
+
+		grp->color++;
+		if (list_empty(&grp->node[1].entry))
+			grp->color++;
+
+		BUG_ON(grp->color <= 0 || grp->color > 2);
+		if (grp->color == 2) {
+			/* No need to update cur or end.  The removed
+			 * nodes are always before both.
+			 */
+			list_move_tail(&grp->node[0].entry, todo);
+			list_del_init(&grp->node[1].entry);
+		}
+	}
+
+	return cnt;
+}
+
+static int release_nodes(struct device *dev, struct list_head *first,
+			 struct list_head *end, unsigned long flags)
+{
+	LIST_HEAD(todo);
+	int cnt;
+	struct devres *dr, *tmp;
+
+	cnt = remove_nodes(dev, first, end, &todo);
+
+	spin_unlock_irqrestore(&dev->devres_lock, flags);
+
+	/* Release.  Note that both devres and devres_group are
+	 * handled as devres in the following loop.  This is safe.
+	 */
+	list_for_each_entry_safe_reverse(dr, tmp, &todo, node.entry) {
+		devres_log(dev, &dr->node, "REL");
+		dr->node.release(dev, dr->data);
+		kfree(dr);
+	}
+
+	return cnt;
+}
+
+/**
+ * devres_release_all - Release all resources
+ * @dev: Device to release resources for
+ *
+ * Release all resources associated with @dev.  This function is
+ * called on driver detach.
+ */
+int devres_release_all(struct device *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->devres_lock, flags);
+	return release_nodes(dev, dev->devres_head.next, &dev->devres_head,
+			     flags);
+}
+
+/**
+ * devres_open_group - Open a new devres group
+ * @dev: Device to open devres group for
+ * @id: Separator ID
+ * @gfp: Allocation flags
+ *
+ * Open a new devres group for @dev with @id.  For @id, using a
+ * pointer to an object which won't be used for another group is
+ * recommended.  If @id is NULL, address-wise unique ID is created.
+ *
+ * RETURNS:
+ * ID of the new group, NULL on failure.
+ */
+void * devres_open_group(struct device *dev, void *id, gfp_t gfp)
+{
+	struct devres_group *grp;
+	unsigned long flags;
+
+	grp = kmalloc(sizeof(*grp), gfp);
+	if (unlikely(!grp))
+		return NULL;
+
+	grp->node[0].release = &group_open_release;
+	grp->node[1].release = &group_close_release;
+	INIT_LIST_HEAD(&grp->node[0].entry);
+	INIT_LIST_HEAD(&grp->node[1].entry);
+	set_node_dbginfo(&grp->node[0], "grp<", 0);
+	set_node_dbginfo(&grp->node[1], "grp>", 0);
+	grp->id = grp;
+	if (id)
+		grp->id = id;
+
+	spin_lock_irqsave(&dev->devres_lock, flags);
+	add_dr(dev, &grp->node[0]);
+	spin_unlock_irqrestore(&dev->devres_lock, flags);
+	return grp->id;
+}
+EXPORT_SYMBOL_GPL(devres_open_group);
+
+/* Find devres group with ID @id.  If @id is NULL, look for the latest. */
+static struct devres_group * find_group(struct device *dev, void *id)
+{
+	struct devres_node *node;
+
+	list_for_each_entry_reverse(node, &dev->devres_head, entry) {
+		struct devres_group *grp;
+
+		if (node->release != &group_open_release)
+			continue;
+
+		grp = container_of(node, struct devres_group, node[0]);
+
+		if (id) {
+			if (grp->id == id)
+				return grp;
+		} else if (list_empty(&grp->node[1].entry))
+			return grp;
+	}
+
+	return NULL;
+}
+
+/**
+ * devres_close_group - Close a devres group
+ * @dev: Device to close devres group for
+ * @id: ID of target group, can be NULL
+ *
+ * Close the group identified by @id.  If @id is NULL, the latest open
+ * group is selected.
+ */
+void devres_close_group(struct device *dev, void *id)
+{
+	struct devres_group *grp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->devres_lock, flags);
+
+	grp = find_group(dev, id);
+	if (grp)
+		add_dr(dev, &grp->node[1]);
+	else
+		WARN_ON(1);
+
+	spin_unlock_irqrestore(&dev->devres_lock, flags);
+}
+EXPORT_SYMBOL_GPL(devres_close_group);
+
+/**
+ * devres_remove_group - Remove a devres group
+ * @dev: Device to remove group for
+ * @id: ID of target group, can be NULL
+ *
+ * Remove the group identified by @id.  If @id is NULL, the latest
+ * open group is selected.  Note that removing a group doesn't affect
+ * any other resources.
+ */
+void devres_remove_group(struct device *dev, void *id)
+{
+	struct devres_group *grp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->devres_lock, flags);
+
+	grp = find_group(dev, id);
+	if (grp) {
+		list_del_init(&grp->node[0].entry);
+		list_del_init(&grp->node[1].entry);
+		devres_log(dev, &grp->node[0], "REM");
+	} else
+		WARN_ON(1);
+
+	spin_unlock_irqrestore(&dev->devres_lock, flags);
+
+	kfree(grp);
+}
+EXPORT_SYMBOL_GPL(devres_remove_group);
+
+/**
+ * devres_release_group - Release resources in a devres group
+ * @dev: Device to release group for
+ * @id: ID of target group, can be NULL
+ *
+ * Release all resources in the group identified by @id.  If @id is
+ * NULL, the latest open group is selected.  The selected group and
+ * groups properly nested inside the selected group are removed.
+ *
+ * RETURNS:
+ * The number of released non-group resources.
+ */
+int devres_release_group(struct device *dev, void *id)
+{
+	struct devres_group *grp;
+	unsigned long flags;
+	int cnt = 0;
+
+	spin_lock_irqsave(&dev->devres_lock, flags);
+
+	grp = find_group(dev, id);
+	if (grp) {
+		struct list_head *first = &grp->node[0].entry;
+		struct list_head *end = &dev->devres_head;
+
+		if (!list_empty(&grp->node[1].entry))
+			end = grp->node[1].entry.next;
+
+		cnt = release_nodes(dev, first, end, flags);
+	} else {
+		WARN_ON(1);
+		spin_unlock_irqrestore(&dev->devres_lock, flags);
+	}
+
+	return cnt;
+}
+EXPORT_SYMBOL_GPL(devres_release_group);
+
+/*
+ * Managed kzalloc/kfree
+ */
+static void devm_kzalloc_release(struct device *dev, void *res)
+{
+	/* noop */
+}
+
+static int devm_kzalloc_match(struct device *dev, void *res, void *data)
+{
+	return res == data;
+}
+
+/**
+ * devm_kzalloc - Managed kzalloc
+ * @dev: Device to allocate memory for
+ * @size: Allocation size
+ * @gfp: Allocation gfp flags
+ *
+ * Managed kzalloc.  Memory allocated with this function is
+ * automatically freed on driver detach.  Like all other devres
+ * resources, guaranteed alignment is unsigned long long.
+ *
+ * RETURNS:
+ * Pointer to allocated memory on success, NULL on failure.
+ */
+void * devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
+{
+	struct devres *dr;
+
+	/* use raw alloc_dr for kmalloc caller tracing */
+	dr = alloc_dr(devm_kzalloc_release, size, gfp);
+	if (unlikely(!dr))
+		return NULL;
+
+	set_node_dbginfo(&dr->node, "devm_kzalloc_release", size);
+	devres_add(dev, dr->data);
+	return dr->data;
+}
+EXPORT_SYMBOL_GPL(devm_kzalloc);
+
+/**
+ * devm_kfree - Managed kfree
+ * @dev: Device this memory belongs to
+ * @p: Memory to free
+ *
+ * Free memory allocated with dev_kzalloc().
+ */
+void devm_kfree(struct device *dev, void *p)
+{
+	int rc;
+
+	rc = devres_destroy(dev, devm_kzalloc_release, devm_kzalloc_match, p);
+	WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_kfree);
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
new file mode 100644
index 0000000..ca9186f
--- /dev/null
+++ b/drivers/base/dma-mapping.c
@@ -0,0 +1,218 @@
+/*
+ * drivers/base/dma-mapping.c - arch-independent dma-mapping routines
+ *
+ * Copyright (c) 2006  SUSE Linux Products GmbH
+ * Copyright (c) 2006  Tejun Heo <teheo@suse.de>
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/dma-mapping.h>
+
+/*
+ * Managed DMA API
+ */
+struct dma_devres {
+	size_t		size;
+	void		*vaddr;
+	dma_addr_t	dma_handle;
+};
+
+static void dmam_coherent_release(struct device *dev, void *res)
+{
+	struct dma_devres *this = res;
+
+	dma_free_coherent(dev, this->size, this->vaddr, this->dma_handle);
+}
+
+static void dmam_noncoherent_release(struct device *dev, void *res)
+{
+	struct dma_devres *this = res;
+
+	dma_free_noncoherent(dev, this->size, this->vaddr, this->dma_handle);
+}
+
+static int dmam_match(struct device *dev, void *res, void *match_data)
+{
+	struct dma_devres *this = res, *match = match_data;
+
+	if (this->vaddr == match->vaddr) {
+		WARN_ON(this->size != match->size ||
+			this->dma_handle != match->dma_handle);
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * dmam_alloc_coherent - Managed dma_alloc_coherent()
+ * @dev: Device to allocate coherent memory for
+ * @size: Size of allocation
+ * @dma_handle: Out argument for allocated DMA handle
+ * @gfp: Allocation flags
+ *
+ * Managed dma_alloc_coherent().  Memory allocated using this function
+ * will be automatically released on driver detach.
+ *
+ * RETURNS:
+ * Pointer to allocated memory on success, NULL on failure.
+ */
+void * dmam_alloc_coherent(struct device *dev, size_t size,
+			   dma_addr_t *dma_handle, gfp_t gfp)
+{
+	struct dma_devres *dr;
+	void *vaddr;
+
+	dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp);
+	if (!dr)
+		return NULL;
+
+	vaddr = dma_alloc_coherent(dev, size, dma_handle, gfp);
+	if (!vaddr) {
+		devres_free(dr);
+		return NULL;
+	}
+
+	dr->vaddr = vaddr;
+	dr->dma_handle = *dma_handle;
+	dr->size = size;
+
+	devres_add(dev, dr);
+
+	return vaddr;
+}
+EXPORT_SYMBOL(dmam_alloc_coherent);
+
+/**
+ * dmam_free_coherent - Managed dma_free_coherent()
+ * @dev: Device to free coherent memory for
+ * @size: Size of allocation
+ * @vaddr: Virtual address of the memory to free
+ * @dma_handle: DMA handle of the memory to free
+ *
+ * Managed dma_free_coherent().
+ */
+void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
+			dma_addr_t dma_handle)
+{
+	struct dma_devres match_data = { size, vaddr, dma_handle };
+
+	dma_free_coherent(dev, size, vaddr, dma_handle);
+	WARN_ON(devres_destroy(dev, dmam_coherent_release, dmam_match,
+			       &match_data));
+}
+EXPORT_SYMBOL(dmam_free_coherent);
+
+/**
+ * dmam_alloc_non_coherent - Managed dma_alloc_non_coherent()
+ * @dev: Device to allocate non_coherent memory for
+ * @size: Size of allocation
+ * @dma_handle: Out argument for allocated DMA handle
+ * @gfp: Allocation flags
+ *
+ * Managed dma_alloc_non_coherent().  Memory allocated using this
+ * function will be automatically released on driver detach.
+ *
+ * RETURNS:
+ * Pointer to allocated memory on success, NULL on failure.
+ */
+void *dmam_alloc_noncoherent(struct device *dev, size_t size,
+			     dma_addr_t *dma_handle, gfp_t gfp)
+{
+	struct dma_devres *dr;
+	void *vaddr;
+
+	dr = devres_alloc(dmam_noncoherent_release, sizeof(*dr), gfp);
+	if (!dr)
+		return NULL;
+
+	vaddr = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
+	if (!vaddr) {
+		devres_free(dr);
+		return NULL;
+	}
+
+	dr->vaddr = vaddr;
+	dr->dma_handle = *dma_handle;
+	dr->size = size;
+
+	devres_add(dev, dr);
+
+	return vaddr;
+}
+EXPORT_SYMBOL(dmam_alloc_noncoherent);
+
+/**
+ * dmam_free_coherent - Managed dma_free_noncoherent()
+ * @dev: Device to free noncoherent memory for
+ * @size: Size of allocation
+ * @vaddr: Virtual address of the memory to free
+ * @dma_handle: DMA handle of the memory to free
+ *
+ * Managed dma_free_noncoherent().
+ */
+void dmam_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+			   dma_addr_t dma_handle)
+{
+	struct dma_devres match_data = { size, vaddr, dma_handle };
+
+	dma_free_noncoherent(dev, size, vaddr, dma_handle);
+	WARN_ON(!devres_destroy(dev, dmam_noncoherent_release, dmam_match,
+				&match_data));
+}
+EXPORT_SYMBOL(dmam_free_noncoherent);
+
+#ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
+
+static void dmam_coherent_decl_release(struct device *dev, void *res)
+{
+	dma_release_declared_memory(dev);
+}
+
+/**
+ * dmam_declare_coherent_memory - Managed dma_declare_coherent_memory()
+ * @dev: Device to declare coherent memory for
+ * @bus_addr: Bus address of coherent memory to be declared
+ * @device_addr: Device address of coherent memory to be declared
+ * @size: Size of coherent memory to be declared
+ * @flags: Flags
+ *
+ * Managed dma_declare_coherent_memory().
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+				 dma_addr_t device_addr, size_t size, int flags)
+{
+	void *res;
+	int rc;
+
+	res = devres_alloc(dmam_coherent_decl_release, 0, GFP_KERNEL);
+	if (!res)
+		return -ENOMEM;
+
+	rc = dma_declare_coherent_memory(dev, bus_addr, device_addr, size,
+					 flags);
+	if (rc == 0)
+		devres_add(dev, res);
+	else
+		devres_free(res);
+
+	return rc;
+}
+EXPORT_SYMBOL(dmam_declare_coherent_memory);
+
+/**
+ * dmam_release_declared_memory - Managed dma_release_declared_memory().
+ * @dev: Device to release declared coherent memory for
+ *
+ * Managed dmam_release_declared_memory().
+ */
+void dmam_release_declared_memory(struct device *dev)
+{
+	WARN_ON(devres_destroy(dev, dmam_coherent_decl_release, NULL, NULL));
+}
+EXPORT_SYMBOL(dmam_release_declared_memory);
+
+#endif
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index f95d502..cd467c9 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -415,8 +415,67 @@
 	spin_unlock_irqrestore (&pool->lock, flags);
 }
 
+/*
+ * Managed DMA pool
+ */
+static void dmam_pool_release(struct device *dev, void *res)
+{
+	struct dma_pool *pool = *(struct dma_pool **)res;
+
+	dma_pool_destroy(pool);
+}
+
+static int dmam_pool_match(struct device *dev, void *res, void *match_data)
+{
+	return *(struct dma_pool **)res == match_data;
+}
+
+/**
+ * dmam_pool_create - Managed dma_pool_create()
+ * @name: name of pool, for diagnostics
+ * @dev: device that will be doing the DMA
+ * @size: size of the blocks in this pool.
+ * @align: alignment requirement for blocks; must be a power of two
+ * @allocation: returned blocks won't cross this boundary (or zero)
+ *
+ * Managed dma_pool_create().  DMA pool created with this function is
+ * automatically destroyed on driver detach.
+ */
+struct dma_pool *dmam_pool_create(const char *name, struct device *dev,
+				  size_t size, size_t align, size_t allocation)
+{
+	struct dma_pool **ptr, *pool;
+
+	ptr = devres_alloc(dmam_pool_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	pool = *ptr = dma_pool_create(name, dev, size, align, allocation);
+	if (pool)
+		devres_add(dev, ptr);
+	else
+		devres_free(ptr);
+
+	return pool;
+}
+
+/**
+ * dmam_pool_destroy - Managed dma_pool_destroy()
+ * @pool: dma pool that will be destroyed
+ *
+ * Managed dma_pool_destroy().
+ */
+void dmam_pool_destroy(struct dma_pool *pool)
+{
+	struct device *dev = pool->dev;
+
+	dma_pool_destroy(pool);
+	WARN_ON(devres_destroy(dev, dmam_pool_release, dmam_pool_match, pool));
+}
 
 EXPORT_SYMBOL (dma_pool_create);
 EXPORT_SYMBOL (dma_pool_destroy);
 EXPORT_SYMBOL (dma_pool_alloc);
 EXPORT_SYMBOL (dma_pool_free);
+EXPORT_SYMBOL (dmam_pool_create);
+EXPORT_SYMBOL (dmam_pool_destroy);
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 001e6f6..cae346e 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -40,13 +40,8 @@
 	int n;
 	int nid = dev->id;
 	struct sysinfo i;
-	unsigned long inactive;
-	unsigned long active;
-	unsigned long free;
 
 	si_meminfo_node(&i, nid);
-	__get_zone_counts(&active, &inactive, &free, NODE_DATA(nid));
-
 
 	n = sprintf(buf, "\n"
 		       "Node %d MemTotal:     %8lu kB\n"
@@ -74,8 +69,8 @@
 		       nid, K(i.totalram),
 		       nid, K(i.freeram),
 		       nid, K(i.totalram - i.freeram),
-		       nid, K(active),
-		       nid, K(inactive),
+		       nid, node_page_state(nid, NR_ACTIVE),
+		       nid, node_page_state(nid, NR_INACTIVE),
 #ifdef CONFIG_HIGHMEM
 		       nid, K(i.totalhigh),
 		       nid, K(i.freehigh),
@@ -138,7 +133,7 @@
 
 
 /*
- * register_node - Setup a driverfs device for a node.
+ * register_node - Setup a sysfs device for a node.
  * @num - Node number to use when creating the device.
  *
  * Initialize and register the node device.
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 8d81a3a..92bf868 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -177,7 +177,7 @@
   DAC960_Failure prints a standardized error message, and then returns false.
 */
 
-static boolean DAC960_Failure(DAC960_Controller_T *Controller,
+static bool DAC960_Failure(DAC960_Controller_T *Controller,
 			      unsigned char *ErrorMessage)
 {
   DAC960_Error("While configuring DAC960 PCI RAID Controller at\n",
@@ -206,7 +206,7 @@
   that are passed in.
  */
 
-static boolean init_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf,
+static bool init_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf,
 								 size_t len)
 {
 	void *cpu_addr;
@@ -250,7 +250,7 @@
   failure.
 */
 
-static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
+static bool DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
 {
   int CommandAllocationLength, CommandAllocationGroupSize;
   int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount;
@@ -790,7 +790,7 @@
   on failure.
 */
 
-static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller,
+static bool DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller,
 				      DAC960_V1_CommandOpcode_T CommandOpcode,
 				      dma_addr_t DataDMA)
 {
@@ -814,7 +814,7 @@
   on failure.
 */
 
-static boolean DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller,
+static bool DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller,
 				       DAC960_V1_CommandOpcode_T CommandOpcode,
 				       unsigned char CommandOpcode2,
 				       dma_addr_t DataDMA)
@@ -840,7 +840,7 @@
   on failure.
 */
 
-static boolean DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller,
+static bool DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller,
 				       DAC960_V1_CommandOpcode_T CommandOpcode,
 				       unsigned char Channel,
 				       unsigned char TargetID,
@@ -870,7 +870,7 @@
   Return data in The controller's HealthStatusBuffer, which is dma-able memory
 */
 
-static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller)
+static bool DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
@@ -908,7 +908,7 @@
   memory buffer.
 */
 
-static boolean DAC960_V2_NewControllerInfo(DAC960_Controller_T *Controller)
+static bool DAC960_V2_NewControllerInfo(DAC960_Controller_T *Controller)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
@@ -946,7 +946,7 @@
   Data is returned in the controller's V2.NewLogicalDeviceInformation
 */
 
-static boolean DAC960_V2_NewLogicalDeviceInfo(DAC960_Controller_T *Controller,
+static bool DAC960_V2_NewLogicalDeviceInfo(DAC960_Controller_T *Controller,
 					   unsigned short LogicalDeviceNumber)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
@@ -997,7 +997,7 @@
 
 */
 
-static boolean DAC960_V2_NewPhysicalDeviceInfo(DAC960_Controller_T *Controller,
+static bool DAC960_V2_NewPhysicalDeviceInfo(DAC960_Controller_T *Controller,
 					    unsigned char Channel,
 					    unsigned char TargetID,
 					    unsigned char LogicalUnit)
@@ -1082,7 +1082,7 @@
   memory buffer.
 */
 
-static boolean DAC960_V2_NewInquiryUnitSerialNumber(DAC960_Controller_T *Controller,
+static bool DAC960_V2_NewInquiryUnitSerialNumber(DAC960_Controller_T *Controller,
 			int Channel, int TargetID, int LogicalUnit)
 {
       DAC960_Command_T *Command;
@@ -1110,7 +1110,7 @@
   success and false on failure.
 */
 
-static boolean DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller,
+static bool DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller,
 					 DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode,
 					 DAC960_V2_OperationDevice_T
 					   OperationDevice)
@@ -1142,7 +1142,7 @@
   other dma mapped memory.
 */
 
-static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
+static bool DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
 						      *Controller)
 {
   void __iomem *ControllerBaseAddress = Controller->BaseAddress;
@@ -1348,7 +1348,7 @@
   the structures that are contained in that region.
 */
 
-static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
+static bool DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
 						      *Controller)
 {
   void __iomem *ControllerBaseAddress = Controller->BaseAddress;
@@ -1373,8 +1373,7 @@
   Controller->BounceBufferLimit = DAC690_V2_PciDmaMask;
 
   /* This is a temporary dma mapping, used only in the scope of this function */
-  CommandMailbox =
-	  (DAC960_V2_CommandMailbox_T *)pci_alloc_consistent( PCI_Device,
+  CommandMailbox = pci_alloc_consistent(PCI_Device,
 		sizeof(DAC960_V2_CommandMailbox_T), &CommandMailboxDMA);
   if (CommandMailbox == NULL)
 	  return false;
@@ -1526,7 +1525,7 @@
   from DAC960 V1 Firmware Controllers and initializes the Controller structure.
 */
 
-static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
+static bool DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
 						     *Controller)
 {
   DAC960_V1_Enquiry2_T *Enquiry2;
@@ -1767,7 +1766,7 @@
   from DAC960 V2 Firmware Controllers and initializes the Controller structure.
 */
 
-static boolean DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T
+static bool DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T
 						     *Controller)
 {
   DAC960_V2_ControllerInfo_T *ControllerInfo =
@@ -1879,8 +1878,8 @@
       if (NewLogicalDeviceInfo->LogicalDeviceState !=
 	  DAC960_V2_LogicalDevice_Offline)
 	Controller->LogicalDriveInitiallyAccessible[LogicalDeviceNumber] = true;
-      LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *)
-	kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC);
+      LogicalDeviceInfo = kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T),
+				   GFP_ATOMIC);
       if (LogicalDeviceInfo == NULL)
 	return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION");
       Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] =
@@ -1898,7 +1897,7 @@
   for Controller.
 */
 
-static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T
+static bool DAC960_ReportControllerConfiguration(DAC960_Controller_T
 						    *Controller)
 {
   DAC960_Info("Configuring Mylex %s PCI RAID Controller\n",
@@ -1947,7 +1946,7 @@
   Controller.
 */
 
-static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T
+static bool DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T
 						 *Controller)
 {
   struct dma_loaf local_dma;
@@ -2095,7 +2094,7 @@
   device connected to Controller.
 */
 
-static boolean DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T
+static bool DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T
 						 *Controller)
 {
   unsigned char Channel = 0, TargetID = 0, LogicalUnit = 0;
@@ -2113,8 +2112,8 @@
       if (!DAC960_V2_NewPhysicalDeviceInfo(Controller, Channel, TargetID, LogicalUnit))
 	  break;
 
-      PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *)
-		kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC);
+      PhysicalDeviceInfo = kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T),
+				    GFP_ATOMIC);
       if (PhysicalDeviceInfo == NULL)
 		return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION");
       Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] =
@@ -2122,8 +2121,8 @@
       memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo,
 		sizeof(DAC960_V2_PhysicalDeviceInfo_T));
 
-      InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *)
-	kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC);
+      InquiryUnitSerialNumber = kmalloc(
+	      sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC);
       if (InquiryUnitSerialNumber == NULL) {
 	kfree(PhysicalDeviceInfo);
 	return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION");
@@ -2219,7 +2218,7 @@
   Information for DAC960 V1 Firmware Controllers.
 */
 
-static boolean DAC960_V1_ReportDeviceConfiguration(DAC960_Controller_T
+static bool DAC960_V1_ReportDeviceConfiguration(DAC960_Controller_T
 						   *Controller)
 {
   int LogicalDriveNumber, Channel, TargetID;
@@ -2316,7 +2315,7 @@
   Information for DAC960 V2 Firmware Controllers.
 */
 
-static boolean DAC960_V2_ReportDeviceConfiguration(DAC960_Controller_T
+static bool DAC960_V2_ReportDeviceConfiguration(DAC960_Controller_T
 						   *Controller)
 {
   int PhysicalDeviceIndex, LogicalDriveNumber;
@@ -2501,7 +2500,7 @@
   associated with Controller.
 */
 
-static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
+static bool DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
 {
   int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
   int n;
@@ -2582,7 +2581,7 @@
   It returns true for fatal errors and false otherwise.
 */
 
-static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller,
+static bool DAC960_ReportErrorStatus(DAC960_Controller_T *Controller,
 					unsigned char ErrorStatus,
 					unsigned char Parameter0,
 					unsigned char Parameter1)
@@ -3048,7 +3047,7 @@
   DAC960_InitializeController initializes Controller.
 */
 
-static boolean 
+static bool 
 DAC960_InitializeController(DAC960_Controller_T *Controller)
 {
   if (DAC960_ReadControllerConfiguration(Controller) &&
@@ -3445,8 +3444,8 @@
   individual Buffer.
 */
 
-static inline boolean DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
-						 boolean SuccessfulIO)
+static inline bool DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
+						 bool SuccessfulIO)
 {
 	struct request *Request = Command->Request;
 	int UpToDate;
@@ -3572,7 +3571,7 @@
   else if (CommandType == DAC960_ReadRetryCommand ||
 	   CommandType == DAC960_WriteRetryCommand)
     {
-      boolean normal_completion;
+      bool normal_completion;
 #ifdef FORCE_RETRY_FAILURE_DEBUG
       static int retry_count = 1;
 #endif
@@ -4659,7 +4658,7 @@
   else if (CommandType == DAC960_ReadRetryCommand ||
 	   CommandType == DAC960_WriteRetryCommand)
     {
-      boolean normal_completion;
+      bool normal_completion;
 
 #ifdef FORCE_RETRY_FAILURE_DEBUG
       static int retry_count = 1;
@@ -4949,8 +4948,8 @@
 	      PhysicalDevice.LogicalUnit = NewLogicalDeviceInfo->LogicalUnit;
 	      Controller->V2.LogicalDriveToVirtualDevice[LogicalDeviceNumber] =
 		PhysicalDevice;
-	      LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *)
-		kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC);
+	      LogicalDeviceInfo = kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T),
+					  GFP_ATOMIC);
 	      Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] =
 		LogicalDeviceInfo;
 	      DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
@@ -5632,7 +5631,7 @@
 	&Controller->V2.ControllerInformation;
       unsigned int StatusChangeCounter =
 	Controller->V2.HealthStatusBuffer->StatusChangeCounter;
-      boolean ForceMonitoringCommand = false;
+      bool ForceMonitoringCommand = false;
       if (time_after(jiffies, Controller->SecondaryMonitoringTime
 	  + DAC960_SecondaryMonitoringInterval))
 	{
@@ -5696,7 +5695,7 @@
   necessary.  It returns true if there is enough room and false otherwise.
 */
 
-static boolean DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller,
+static bool DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller,
 					unsigned int ByteCount)
 {
   unsigned char *NewStatusBuffer;
@@ -5709,14 +5708,14 @@
       unsigned int NewStatusBufferLength = DAC960_InitialStatusBufferSize;
       while (NewStatusBufferLength < ByteCount)
 	NewStatusBufferLength *= 2;
-      Controller->CombinedStatusBuffer =
-	(unsigned char *) kmalloc(NewStatusBufferLength, GFP_ATOMIC);
+      Controller->CombinedStatusBuffer = kmalloc(NewStatusBufferLength,
+						  GFP_ATOMIC);
       if (Controller->CombinedStatusBuffer == NULL) return false;
       Controller->CombinedStatusBufferLength = NewStatusBufferLength;
       return true;
     }
-  NewStatusBuffer = (unsigned char *)
-    kmalloc(2 * Controller->CombinedStatusBufferLength, GFP_ATOMIC);
+  NewStatusBuffer = kmalloc(2 * Controller->CombinedStatusBufferLength,
+			     GFP_ATOMIC);
   if (NewStatusBuffer == NULL)
     {
       DAC960_Warning("Unable to expand Combined Status Buffer - Truncating\n",
@@ -5744,7 +5743,7 @@
 			   ...)
 {
   static unsigned char Buffer[DAC960_LineBufferSize];
-  static boolean BeginningOfLine = true;
+  static bool BeginningOfLine = true;
   va_list Arguments;
   int Length = 0;
   va_start(Arguments, Controller);
@@ -5837,7 +5836,7 @@
   Channel and TargetID and returns true on success and false on failure.
 */
 
-static boolean DAC960_ParsePhysicalDevice(DAC960_Controller_T *Controller,
+static bool DAC960_ParsePhysicalDevice(DAC960_Controller_T *Controller,
 					  char *UserCommandString,
 					  unsigned char *Channel,
 					  unsigned char *TargetID)
@@ -5870,7 +5869,7 @@
   returns true on success and false on failure.
 */
 
-static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller,
+static bool DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller,
 					char *UserCommandString,
 					unsigned char *LogicalDriveNumber)
 {
@@ -5951,7 +5950,7 @@
   Controllers.
 */
 
-static boolean DAC960_V1_ExecuteUserCommand(DAC960_Controller_T *Controller,
+static bool DAC960_V1_ExecuteUserCommand(DAC960_Controller_T *Controller,
 					    unsigned char *UserCommand)
 {
   DAC960_Command_T *Command;
@@ -6166,7 +6165,7 @@
   on failure.
 */
 
-static boolean DAC960_V2_TranslatePhysicalDevice(DAC960_Command_T *Command,
+static bool DAC960_V2_TranslatePhysicalDevice(DAC960_Command_T *Command,
 						 unsigned char Channel,
 						 unsigned char TargetID,
 						 unsigned short
@@ -6213,7 +6212,7 @@
   Controllers.
 */
 
-static boolean DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller,
+static bool DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller,
 					    unsigned char *UserCommand)
 {
   DAC960_Command_T *Command;
@@ -7025,7 +7024,7 @@
   return -EINVAL;
 }
 
-static struct file_operations DAC960_gam_fops = {
+static const struct file_operations DAC960_gam_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= DAC960_gam_ioctl
 };
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
index 6148073..f5e2436c 100644
--- a/drivers/block/DAC960.h
+++ b/drivers/block/DAC960.h
@@ -68,13 +68,6 @@
 #define DAC690_V2_PciDmaMask	0xffffffffffffffffULL
 
 /*
-  Define a Boolean data type.
-*/
-
-typedef bool boolean;
-
-
-/*
   Define a 32/64 bit I/O Address data type.
 */
 
@@ -139,25 +132,25 @@
   unsigned char PeripheralDeviceType:5;			/* Byte 0 Bits 0-4 */
   unsigned char PeripheralQualifier:3;			/* Byte 0 Bits 5-7 */
   unsigned char DeviceTypeModifier:7;			/* Byte 1 Bits 0-6 */
-  boolean RMB:1;					/* Byte 1 Bit 7 */
+  bool RMB:1;						/* Byte 1 Bit 7 */
   unsigned char ANSI_ApprovedVersion:3;			/* Byte 2 Bits 0-2 */
   unsigned char ECMA_Version:3;				/* Byte 2 Bits 3-5 */
   unsigned char ISO_Version:2;				/* Byte 2 Bits 6-7 */
   unsigned char ResponseDataFormat:4;			/* Byte 3 Bits 0-3 */
   unsigned char :2;					/* Byte 3 Bits 4-5 */
-  boolean TrmIOP:1;					/* Byte 3 Bit 6 */
-  boolean AENC:1;					/* Byte 3 Bit 7 */
+  bool TrmIOP:1;					/* Byte 3 Bit 6 */
+  bool AENC:1;						/* Byte 3 Bit 7 */
   unsigned char AdditionalLength;			/* Byte 4 */
   unsigned char :8;					/* Byte 5 */
   unsigned char :8;					/* Byte 6 */
-  boolean SftRe:1;					/* Byte 7 Bit 0 */
-  boolean CmdQue:1;					/* Byte 7 Bit 1 */
-  boolean :1;						/* Byte 7 Bit 2 */
-  boolean Linked:1;					/* Byte 7 Bit 3 */
-  boolean Sync:1;					/* Byte 7 Bit 4 */
-  boolean WBus16:1;					/* Byte 7 Bit 5 */
-  boolean WBus32:1;					/* Byte 7 Bit 6 */
-  boolean RelAdr:1;					/* Byte 7 Bit 7 */
+  bool SftRe:1;						/* Byte 7 Bit 0 */
+  bool CmdQue:1;					/* Byte 7 Bit 1 */
+  bool :1;						/* Byte 7 Bit 2 */
+  bool Linked:1;					/* Byte 7 Bit 3 */
+  bool Sync:1;						/* Byte 7 Bit 4 */
+  bool WBus16:1;					/* Byte 7 Bit 5 */
+  bool WBus32:1;					/* Byte 7 Bit 6 */
+  bool RelAdr:1;					/* Byte 7 Bit 7 */
   unsigned char VendorIdentification[8];		/* Bytes 8-15 */
   unsigned char ProductIdentification[16];		/* Bytes 16-31 */
   unsigned char ProductRevisionLevel[4];		/* Bytes 32-35 */
@@ -215,13 +208,13 @@
 typedef struct DAC960_SCSI_RequestSense
 {
   unsigned char ErrorCode:7;				/* Byte 0 Bits 0-6 */
-  boolean Valid:1;					/* Byte 0 Bit 7 */
+  bool Valid:1;						/* Byte 0 Bit 7 */
   unsigned char SegmentNumber;				/* Byte 1 */
   DAC960_SCSI_RequestSenseKey_T SenseKey:4;		/* Byte 2 Bits 0-3 */
   unsigned char :1;					/* Byte 2 Bit 4 */
-  boolean ILI:1;					/* Byte 2 Bit 5 */
-  boolean EOM:1;					/* Byte 2 Bit 6 */
-  boolean Filemark:1;					/* Byte 2 Bit 7 */
+  bool ILI:1;						/* Byte 2 Bit 5 */
+  bool EOM:1;						/* Byte 2 Bit 6 */
+  bool Filemark:1;					/* Byte 2 Bit 7 */
   unsigned char Information[4];				/* Bytes 3-6 */
   unsigned char AdditionalSenseLength;			/* Byte 7 */
   unsigned char CommandSpecificInformation[4];		/* Bytes 8-11 */
@@ -381,8 +374,8 @@
   unsigned int LogicalDriveSizes[32];			/* Bytes 4-131 */
   unsigned short FlashAge;				/* Bytes 132-133 */
   struct {
-    boolean DeferredWriteError:1;			/* Byte 134 Bit 0 */
-    boolean BatteryLow:1;				/* Byte 134 Bit 1 */
+    bool DeferredWriteError:1;				/* Byte 134 Bit 0 */
+    bool BatteryLow:1;					/* Byte 134 Bit 1 */
     unsigned char :6;					/* Byte 134 Bits 2-7 */
   } StatusFlags;
   unsigned char :8;					/* Byte 135 */
@@ -410,7 +403,7 @@
   unsigned char RebuildCount;				/* Byte 150 */
   struct {
     unsigned char :3;					/* Byte 151 Bits 0-2 */
-    boolean BatteryBackupUnitPresent:1;			/* Byte 151 Bit 3 */
+    bool BatteryBackupUnitPresent:1;			/* Byte 151 Bit 3 */
     unsigned char :3;					/* Byte 151 Bits 4-6 */
     unsigned char :1;					/* Byte 151 Bit 7 */
   } MiscFlags;
@@ -492,8 +485,8 @@
       DAC960_V1_ErrorCorrection_ECC =		0x2,
       DAC960_V1_ErrorCorrection_Last =		0x7
     } __attribute__ ((packed)) ErrorCorrection:3;	/* Byte 40 Bits 3-5 */
-    boolean FastPageMode:1;				/* Byte 40 Bit 6 */
-    boolean LowPowerMemory:1;				/* Byte 40 Bit 7 */
+    bool FastPageMode:1;				/* Byte 40 Bit 6 */
+    bool LowPowerMemory:1;				/* Byte 40 Bit 7 */
     unsigned char :8;					/* Bytes 41 */
   } MemoryType;
   unsigned short ClockSpeed;				/* Bytes 42-43 */
@@ -538,7 +531,7 @@
       DAC960_V1_Ultra =				0x1,
       DAC960_V1_Ultra2 =			0x2
     } __attribute__ ((packed)) BusSpeed:2;		/* Byte 106 Bits 2-3 */
-    boolean Differential:1;				/* Byte 106 Bit 4 */
+    bool Differential:1;				/* Byte 106 Bit 4 */
     unsigned char :3;					/* Byte 106 Bits 5-7 */
   } SCSICapability;
   unsigned char :8;					/* Byte 107 */
@@ -554,10 +547,10 @@
   } __attribute__ ((packed)) FaultManagementType;	/* Byte 114 */
   unsigned char :8;					/* Byte 115 */
   struct {
-    boolean Clustering:1;				/* Byte 116 Bit 0 */
-    boolean MylexOnlineRAIDExpansion:1;			/* Byte 116 Bit 1 */
-    boolean ReadAhead:1;				/* Byte 116 Bit 2 */
-    boolean BackgroundInitialization:1;			/* Byte 116 Bit 3 */
+    bool Clustering:1;					/* Byte 116 Bit 0 */
+    bool MylexOnlineRAIDExpansion:1;			/* Byte 116 Bit 1 */
+    bool ReadAhead:1;					/* Byte 116 Bit 2 */
+    bool BackgroundInitialization:1;			/* Byte 116 Bit 3 */
     unsigned int :28;					/* Bytes 116-119 */
   } FirmwareFeatures;
   unsigned int :32;					/* Bytes 120-123 */
@@ -589,7 +582,7 @@
   unsigned int LogicalDriveSize;			/* Bytes 0-3 */
   DAC960_V1_LogicalDriveState_T LogicalDriveState;	/* Byte 4 */
   unsigned char RAIDLevel:7;				/* Byte 5 Bits 0-6 */
-  boolean WriteBack:1;					/* Byte 5 Bit 7 */
+  bool WriteBack:1;					/* Byte 5 Bit 7 */
   unsigned short :16;					/* Bytes 6-7 */
 }
 DAC960_V1_LogicalDriveInformation_T;
@@ -630,13 +623,13 @@
   unsigned char :2;					/* Byte 3 Bits 6-7 */
   unsigned short SequenceNumber;			/* Bytes 4-5 */
   unsigned char ErrorCode:7;				/* Byte 6 Bits 0-6 */
-  boolean Valid:1;					/* Byte 6 Bit 7 */
+  bool Valid:1;						/* Byte 6 Bit 7 */
   unsigned char SegmentNumber;				/* Byte 7 */
   DAC960_SCSI_RequestSenseKey_T SenseKey:4;		/* Byte 8 Bits 0-3 */
   unsigned char :1;					/* Byte 8 Bit 4 */
-  boolean ILI:1;					/* Byte 8 Bit 5 */
-  boolean EOM:1;					/* Byte 8 Bit 6 */
-  boolean Filemark:1;					/* Byte 8 Bit 7 */
+  bool ILI:1;						/* Byte 8 Bit 5 */
+  bool EOM:1;						/* Byte 8 Bit 6 */
+  bool Filemark:1;					/* Byte 8 Bit 7 */
   unsigned char Information[4];				/* Bytes 9-12 */
   unsigned char AdditionalSenseLength;			/* Byte 13 */
   unsigned char CommandSpecificInformation[4];		/* Bytes 14-17 */
@@ -670,7 +663,7 @@
 
 typedef struct DAC960_V1_DeviceState
 {
-  boolean Present:1;					/* Byte 0 Bit 0 */
+  bool Present:1;					/* Byte 0 Bit 0 */
   unsigned char :7;					/* Byte 0 Bits 1-7 */
   enum {
     DAC960_V1_OtherType =			0x0,
@@ -678,12 +671,12 @@
     DAC960_V1_SequentialType =			0x2,
     DAC960_V1_CDROM_or_WORM_Type =		0x3
     } __attribute__ ((packed)) DeviceType:2;		/* Byte 1 Bits 0-1 */
-  boolean :1;						/* Byte 1 Bit 2 */
-  boolean Fast20:1;					/* Byte 1 Bit 3 */
-  boolean Sync:1;					/* Byte 1 Bit 4 */
-  boolean Fast:1;					/* Byte 1 Bit 5 */
-  boolean Wide:1;					/* Byte 1 Bit 6 */
-  boolean TaggedQueuingSupported:1;			/* Byte 1 Bit 7 */
+  bool :1;						/* Byte 1 Bit 2 */
+  bool Fast20:1;					/* Byte 1 Bit 3 */
+  bool Sync:1;						/* Byte 1 Bit 4 */
+  bool Fast:1;						/* Byte 1 Bit 5 */
+  bool Wide:1;						/* Byte 1 Bit 6 */
+  bool TaggedQueuingSupported:1;			/* Byte 1 Bit 7 */
   DAC960_V1_PhysicalDeviceState_T DeviceState;		/* Byte 2 */
   unsigned char :8;					/* Byte 3 */
   unsigned char SynchronousMultiplier;			/* Byte 4 */
@@ -765,15 +758,15 @@
 typedef struct DAC960_V1_Config2
 {
   unsigned char :1;					/* Byte 0 Bit 0 */
-  boolean ActiveNegationEnabled:1;			/* Byte 0 Bit 1 */
+  bool ActiveNegationEnabled:1;				/* Byte 0 Bit 1 */
   unsigned char :5;					/* Byte 0 Bits 2-6 */
-  boolean NoRescanIfResetReceivedDuringScan:1;		/* Byte 0 Bit 7 */
-  boolean StorageWorksSupportEnabled:1;			/* Byte 1 Bit 0 */
-  boolean HewlettPackardSupportEnabled:1;		/* Byte 1 Bit 1 */
-  boolean NoDisconnectOnFirstCommand:1;			/* Byte 1 Bit 2 */
+  bool NoRescanIfResetReceivedDuringScan:1;		/* Byte 0 Bit 7 */
+  bool StorageWorksSupportEnabled:1;			/* Byte 1 Bit 0 */
+  bool HewlettPackardSupportEnabled:1;			/* Byte 1 Bit 1 */
+  bool NoDisconnectOnFirstCommand:1;			/* Byte 1 Bit 2 */
   unsigned char :2;					/* Byte 1 Bits 3-4 */
-  boolean AEMI_ARM:1;					/* Byte 1 Bit 5 */
-  boolean AEMI_OFM:1;					/* Byte 1 Bit 6 */
+  bool AEMI_ARM:1;					/* Byte 1 Bit 5 */
+  bool AEMI_OFM:1;					/* Byte 1 Bit 6 */
   unsigned char :1;					/* Byte 1 Bit 7 */
   enum {
     DAC960_V1_OEMID_Mylex =			0x00,
@@ -787,13 +780,13 @@
   unsigned char PhysicalSector;				/* Byte 4 */
   unsigned char LogicalSector;				/* Byte 5 */
   unsigned char BlockFactor;				/* Byte 6 */
-  boolean ReadAheadEnabled:1;				/* Byte 7 Bit 0 */
-  boolean LowBIOSDelay:1;				/* Byte 7 Bit 1 */
+  bool ReadAheadEnabled:1;				/* Byte 7 Bit 0 */
+  bool LowBIOSDelay:1;					/* Byte 7 Bit 1 */
   unsigned char :2;					/* Byte 7 Bits 2-3 */
-  boolean ReassignRestrictedToOneSector:1;		/* Byte 7 Bit 4 */
+  bool ReassignRestrictedToOneSector:1;			/* Byte 7 Bit 4 */
   unsigned char :1;					/* Byte 7 Bit 5 */
-  boolean ForceUnitAccessDuringWriteRecovery:1;		/* Byte 7 Bit 6 */
-  boolean EnableLeftSymmetricRAID5Algorithm:1;		/* Byte 7 Bit 7 */
+  bool ForceUnitAccessDuringWriteRecovery:1;		/* Byte 7 Bit 6 */
+  bool EnableLeftSymmetricRAID5Algorithm:1;		/* Byte 7 Bit 7 */
   unsigned char DefaultRebuildRate;			/* Byte 8 */
   unsigned char :8;					/* Byte 9 */
   unsigned char BlocksPerCacheLine;			/* Byte 10 */
@@ -805,10 +798,10 @@
       DAC960_V1_Sync_5MHz =			0x2,
       DAC960_V1_Sync_10or20MHz =		0x3	/* Byte 11 Bits 0-1 */
     } __attribute__ ((packed)) Speed:2;
-    boolean Force8Bit:1;				/* Byte 11 Bit 2 */
-    boolean DisableFast20:1;				/* Byte 11 Bit 3 */
+    bool Force8Bit:1;					/* Byte 11 Bit 2 */
+    bool DisableFast20:1;				/* Byte 11 Bit 3 */
     unsigned char :3;					/* Byte 11 Bits 4-6 */
-    boolean EnableTaggedQueuing:1;			/* Byte 11 Bit 7 */
+    bool EnableTaggedQueuing:1;				/* Byte 11 Bit 7 */
   } __attribute__ ((packed)) ChannelParameters[6];	/* Bytes 12-17 */
   unsigned char SCSIInitiatorID;			/* Byte 18 */
   unsigned char :8;					/* Byte 19 */
@@ -819,8 +812,8 @@
   unsigned char SimultaneousDeviceSpinUpCount;		/* Byte 21 */
   unsigned char SecondsDelayBetweenSpinUps;		/* Byte 22 */
   unsigned char Reserved1[29];				/* Bytes 23-51 */
-  boolean BIOSDisabled:1;				/* Byte 52 Bit 0 */
-  boolean CDROMBootEnabled:1;				/* Byte 52 Bit 1 */
+  bool BIOSDisabled:1;					/* Byte 52 Bit 0 */
+  bool CDROMBootEnabled:1;				/* Byte 52 Bit 1 */
   unsigned char :3;					/* Byte 52 Bits 2-4 */
   enum {
     DAC960_V1_Geometry_128_32 =			0x0,
@@ -849,7 +842,7 @@
     DAC960_V1_DCDB_DataTransferSystemToDevice = 2,
     DAC960_V1_DCDB_IllegalDataTransfer =	3
   } __attribute__ ((packed)) Direction:2;		 /* Byte 1 Bits 0-1 */
-  boolean EarlyStatus:1;				 /* Byte 1 Bit 2 */
+  bool EarlyStatus:1;					 /* Byte 1 Bit 2 */
   unsigned char :1;					 /* Byte 1 Bit 3 */
   enum {
     DAC960_V1_DCDB_Timeout_24_hours =		0,
@@ -857,8 +850,8 @@
     DAC960_V1_DCDB_Timeout_60_seconds =		2,
     DAC960_V1_DCDB_Timeout_10_minutes =		3
   } __attribute__ ((packed)) Timeout:2;			 /* Byte 1 Bits 4-5 */
-  boolean NoAutomaticRequestSense:1;			 /* Byte 1 Bit 6 */
-  boolean DisconnectPermitted:1;			 /* Byte 1 Bit 7 */
+  bool NoAutomaticRequestSense:1;			 /* Byte 1 Bit 6 */
+  bool DisconnectPermitted:1;				 /* Byte 1 Bit 7 */
   unsigned short TransferLength;			 /* Bytes 2-3 */
   DAC960_BusAddress32_T BusAddress;			 /* Bytes 4-7 */
   unsigned char CDBLength:4;				 /* Byte 8 Bits 0-3 */
@@ -920,7 +913,7 @@
     DAC960_V1_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
     unsigned char Dummy1[5];				/* Bytes 2-6 */
     unsigned char LogicalDriveNumber:6;			/* Byte 7 Bits 0-6 */
-    boolean AutoRestore:1;				/* Byte 7 Bit 7 */
+    bool AutoRestore:1;					/* Byte 7 Bit 7 */
     unsigned char Dummy2[8];				/* Bytes 8-15 */
   } __attribute__ ((packed)) Type3C;
   struct {
@@ -1070,9 +1063,9 @@
     DAC960_V2_MemoryType_SDRAM =		0x04,
     DAC960_V2_MemoryType_Last =			0x1F
   } __attribute__ ((packed)) MemoryType:5;		/* Byte 0 Bits 0-4 */
-  boolean :1;						/* Byte 0 Bit 5 */
-  boolean MemoryParity:1;				/* Byte 0 Bit 6 */
-  boolean MemoryECC:1;					/* Byte 0 Bit 7 */
+  bool :1;						/* Byte 0 Bit 5 */
+  bool MemoryParity:1;					/* Byte 0 Bit 6 */
+  bool MemoryECC:1;					/* Byte 0 Bit 7 */
 }
 DAC960_V2_MemoryType_T;
 
@@ -1187,13 +1180,13 @@
   unsigned char OEM_Code;				/* Byte 131 */
   unsigned char VendorName[16];				/* Bytes 132-147 */
   /* Other Physical/Controller/Operation Information */
-  boolean BBU_Present:1;				/* Byte 148 Bit 0 */
-  boolean ActiveActiveClusteringMode:1;			/* Byte 148 Bit 1 */
+  bool BBU_Present:1;					/* Byte 148 Bit 0 */
+  bool ActiveActiveClusteringMode:1;			/* Byte 148 Bit 1 */
   unsigned char :6;					/* Byte 148 Bits 2-7 */
   unsigned char :8;					/* Byte 149 */
   unsigned short :16;					/* Bytes 150-151 */
   /* Physical Device Scan Information */
-  boolean PhysicalScanActive:1;				/* Byte 152 Bit 0 */
+  bool PhysicalScanActive:1;				/* Byte 152 Bit 0 */
   unsigned char :7;					/* Byte 152 Bits 1-7 */
   unsigned char PhysicalDeviceChannelNumber;		/* Byte 153 */
   unsigned char PhysicalDeviceTargetID;			/* Byte 154 */
@@ -1305,8 +1298,8 @@
   unsigned int FreeIOP;					/* Bytes 468-471 */
   unsigned short MaximumCombLengthInBlocks;		/* Bytes 472-473 */
   unsigned short NumberOfConfigurationGroups;		/* Bytes 474-475 */
-  boolean InstallationAbortStatus:1;			/* Byte 476 Bit 0 */
-  boolean MaintenanceModeStatus:1;			/* Byte 476 Bit 1 */
+  bool InstallationAbortStatus:1;			/* Byte 476 Bit 0 */
+  bool MaintenanceModeStatus:1;				/* Byte 476 Bit 1 */
   unsigned int :24;					/* Bytes 476-479 */
   unsigned char Reserved10[32];				/* Bytes 480-511 */
   unsigned char Reserved11[512];			/* Bytes 512-1023 */
@@ -1357,33 +1350,33 @@
       DAC960_V2_IntelligentWriteCacheEnabled =	0x3,
       DAC960_V2_WriteCache_Last =		0x7
     } __attribute__ ((packed)) WriteCache:3;		/* Byte 8 Bits 3-5 */
-    boolean :1;						/* Byte 8 Bit 6 */
-    boolean LogicalDeviceInitialized:1;			/* Byte 8 Bit 7 */
+    bool :1;						/* Byte 8 Bit 6 */
+    bool LogicalDeviceInitialized:1;			/* Byte 8 Bit 7 */
   } LogicalDeviceControl;				/* Byte 8 */
   /* Logical Device Operations Status */
-  boolean ConsistencyCheckInProgress:1;			/* Byte 9 Bit 0 */
-  boolean RebuildInProgress:1;				/* Byte 9 Bit 1 */
-  boolean BackgroundInitializationInProgress:1;		/* Byte 9 Bit 2 */
-  boolean ForegroundInitializationInProgress:1;		/* Byte 9 Bit 3 */
-  boolean DataMigrationInProgress:1;			/* Byte 9 Bit 4 */
-  boolean PatrolOperationInProgress:1;			/* Byte 9 Bit 5 */
+  bool ConsistencyCheckInProgress:1;			/* Byte 9 Bit 0 */
+  bool RebuildInProgress:1;				/* Byte 9 Bit 1 */
+  bool BackgroundInitializationInProgress:1;		/* Byte 9 Bit 2 */
+  bool ForegroundInitializationInProgress:1;		/* Byte 9 Bit 3 */
+  bool DataMigrationInProgress:1;			/* Byte 9 Bit 4 */
+  bool PatrolOperationInProgress:1;			/* Byte 9 Bit 5 */
   unsigned char :2;					/* Byte 9 Bits 6-7 */
   unsigned char RAID5WriteUpdate;			/* Byte 10 */
   unsigned char RAID5Algorithm;				/* Byte 11 */
   unsigned short LogicalDeviceNumber;			/* Bytes 12-13 */
   /* BIOS Info */
-  boolean BIOSDisabled:1;				/* Byte 14 Bit 0 */
-  boolean CDROMBootEnabled:1;				/* Byte 14 Bit 1 */
-  boolean DriveCoercionEnabled:1;			/* Byte 14 Bit 2 */
-  boolean WriteSameDisabled:1;				/* Byte 14 Bit 3 */
-  boolean HBA_ModeEnabled:1;				/* Byte 14 Bit 4 */
+  bool BIOSDisabled:1;					/* Byte 14 Bit 0 */
+  bool CDROMBootEnabled:1;				/* Byte 14 Bit 1 */
+  bool DriveCoercionEnabled:1;				/* Byte 14 Bit 2 */
+  bool WriteSameDisabled:1;				/* Byte 14 Bit 3 */
+  bool HBA_ModeEnabled:1;				/* Byte 14 Bit 4 */
   enum {
     DAC960_V2_Geometry_128_32 =			0x0,
     DAC960_V2_Geometry_255_63 =			0x1,
     DAC960_V2_Geometry_Reserved1 =		0x2,
     DAC960_V2_Geometry_Reserved2 =		0x3
   } __attribute__ ((packed)) DriveGeometry:2;		/* Byte 14 Bits 5-6 */
-  boolean SuperReadAheadEnabled:1;			/* Byte 14 Bit 7 */
+  bool SuperReadAheadEnabled:1;				/* Byte 14 Bit 7 */
   unsigned char :8;					/* Byte 15 */
   /* Error Counters */
   unsigned short SoftErrors;				/* Bytes 16-17 */
@@ -1446,13 +1439,13 @@
   unsigned char TargetID;				/* Byte 2 */
   unsigned char LogicalUnit;				/* Byte 3 */
   /* Configuration Status Bits */
-  boolean PhysicalDeviceFaultTolerant:1;		/* Byte 4 Bit 0 */
-  boolean PhysicalDeviceConnected:1;			/* Byte 4 Bit 1 */
-  boolean PhysicalDeviceLocalToController:1;		/* Byte 4 Bit 2 */
+  bool PhysicalDeviceFaultTolerant:1;			/* Byte 4 Bit 0 */
+  bool PhysicalDeviceConnected:1;			/* Byte 4 Bit 1 */
+  bool PhysicalDeviceLocalToController:1;		/* Byte 4 Bit 2 */
   unsigned char :5;					/* Byte 4 Bits 3-7 */
   /* Multiple Host/Controller Status Bits */
-  boolean RemoteHostSystemDead:1;			/* Byte 5 Bit 0 */
-  boolean RemoteControllerDead:1;			/* Byte 5 Bit 1 */
+  bool RemoteHostSystemDead:1;				/* Byte 5 Bit 0 */
+  bool RemoteControllerDead:1;				/* Byte 5 Bit 1 */
   unsigned char :6;					/* Byte 5 Bits 2-7 */
   DAC960_V2_PhysicalDeviceState_T PhysicalDeviceState;	/* Byte 6 */
   unsigned char NegotiatedDataWidthBits;		/* Byte 7 */
@@ -1464,12 +1457,12 @@
   unsigned char NetworkAddress[16];			/* Bytes 16-31 */
   unsigned short MaximumTags;				/* Bytes 32-33 */
   /* Physical Device Operations Status */
-  boolean ConsistencyCheckInProgress:1;			/* Byte 34 Bit 0 */
-  boolean RebuildInProgress:1;				/* Byte 34 Bit 1 */
-  boolean MakingDataConsistentInProgress:1;		/* Byte 34 Bit 2 */
-  boolean PhysicalDeviceInitializationInProgress:1;	/* Byte 34 Bit 3 */
-  boolean DataMigrationInProgress:1;			/* Byte 34 Bit 4 */
-  boolean PatrolOperationInProgress:1;			/* Byte 34 Bit 5 */
+  bool ConsistencyCheckInProgress:1;			/* Byte 34 Bit 0 */
+  bool RebuildInProgress:1;				/* Byte 34 Bit 1 */
+  bool MakingDataConsistentInProgress:1;		/* Byte 34 Bit 2 */
+  bool PhysicalDeviceInitializationInProgress:1;	/* Byte 34 Bit 3 */
+  bool DataMigrationInProgress:1;			/* Byte 34 Bit 4 */
+  bool PatrolOperationInProgress:1;			/* Byte 34 Bit 5 */
   unsigned char :2;					/* Byte 34 Bits 6-7 */
   unsigned char LongOperationStatus;			/* Byte 35 */
   unsigned char ParityErrors;				/* Byte 36 */
@@ -1555,14 +1548,14 @@
 
 typedef struct DAC960_V2_CommandControlBits
 {
-  boolean ForceUnitAccess:1;				/* Byte 0 Bit 0 */
-  boolean DisablePageOut:1;				/* Byte 0 Bit 1 */
-  boolean :1;						/* Byte 0 Bit 2 */
-  boolean AdditionalScatterGatherListMemory:1;		/* Byte 0 Bit 3 */
-  boolean DataTransferControllerToHost:1;		/* Byte 0 Bit 4 */
-  boolean :1;						/* Byte 0 Bit 5 */
-  boolean NoAutoRequestSense:1;				/* Byte 0 Bit 6 */
-  boolean DisconnectProhibited:1;			/* Byte 0 Bit 7 */
+  bool ForceUnitAccess:1;				/* Byte 0 Bit 0 */
+  bool DisablePageOut:1;				/* Byte 0 Bit 1 */
+  bool :1;						/* Byte 0 Bit 2 */
+  bool AdditionalScatterGatherListMemory:1;		/* Byte 0 Bit 3 */
+  bool DataTransferControllerToHost:1;			/* Byte 0 Bit 4 */
+  bool :1;						/* Byte 0 Bit 5 */
+  bool NoAutoRequestSense:1;				/* Byte 0 Bit 6 */
+  bool DisconnectProhibited:1;				/* Byte 0 Bit 7 */
 }
 DAC960_V2_CommandControlBits_T;
 
@@ -1825,8 +1818,8 @@
     DAC960_V2_CommandTimeout_T CommandTimeout;		/* Byte 19 */
     unsigned char RequestSenseSize;			/* Byte 20 */
     unsigned char IOCTL_Opcode;				/* Byte 21 */
-    boolean RestoreConsistency:1;			/* Byte 22 Bit 0 */
-    boolean InitializedAreaOnly:1;			/* Byte 22 Bit 1 */
+    bool RestoreConsistency:1;				/* Byte 22 Bit 0 */
+    bool InitializedAreaOnly:1;				/* Byte 22 Bit 1 */
     unsigned char :6;					/* Byte 22 Bits 2-7 */
     unsigned char Reserved[9];				/* Bytes 23-31 */
     DAC960_V2_DataTransferMemoryAddress_T
@@ -2190,7 +2183,7 @@
   struct {
     DAC960_V1_CommandIdentifier_T CommandIdentifier;	/* Byte 0 */
     unsigned char :7;					/* Byte 1 Bits 0-6 */
-    boolean Valid:1;					/* Byte 1 Bit 7 */
+    bool Valid:1;					/* Byte 1 Bit 7 */
     DAC960_V1_CommandStatus_T CommandStatus;		/* Bytes 2-3 */
   } Fields;
 }
@@ -2322,12 +2315,12 @@
   unsigned long ShutdownMonitoringTimer;
   unsigned long LastProgressReportTime;
   unsigned long LastCurrentStatusTime;
-  boolean ControllerInitialized;
-  boolean MonitoringCommandDeferred;
-  boolean EphemeralProgressMessage;
-  boolean DriveSpinUpMessageDisplayed;
-  boolean MonitoringAlertMode;
-  boolean SuppressEnclosureMessages;
+  bool ControllerInitialized;
+  bool MonitoringCommandDeferred;
+  bool EphemeralProgressMessage;
+  bool DriveSpinUpMessageDisplayed;
+  bool MonitoringAlertMode;
+  bool SuppressEnclosureMessages;
   struct timer_list MonitoringTimer;
   struct gendisk *disks[DAC960_MaxLogicalDrives];
   struct pci_pool *ScatterGatherPool;
@@ -2342,11 +2335,11 @@
   DAC960_Command_T InitialCommand;
   DAC960_Command_T *Commands[DAC960_MaxDriverQueueDepth];
   struct proc_dir_entry *ControllerProcEntry;
-  boolean LogicalDriveInitiallyAccessible[DAC960_MaxLogicalDrives];
+  bool LogicalDriveInitiallyAccessible[DAC960_MaxLogicalDrives];
   void (*QueueCommand)(DAC960_Command_T *Command);
-  boolean (*ReadControllerConfiguration)(struct DAC960_Controller *);
-  boolean (*ReadDeviceConfiguration)(struct DAC960_Controller *);
-  boolean (*ReportDeviceConfiguration)(struct DAC960_Controller *);
+  bool (*ReadControllerConfiguration)(struct DAC960_Controller *);
+  bool (*ReadDeviceConfiguration)(struct DAC960_Controller *);
+  bool (*ReportDeviceConfiguration)(struct DAC960_Controller *);
   void (*QueueReadWriteCommand)(DAC960_Command_T *Command);
   union {
     struct {
@@ -2359,21 +2352,21 @@
       unsigned short OldEventLogSequenceNumber;
       unsigned short DeviceStateChannel;
       unsigned short DeviceStateTargetID;
-      boolean DualModeMemoryMailboxInterface;
-      boolean BackgroundInitializationStatusSupported;
-      boolean SAFTE_EnclosureManagementEnabled;
-      boolean NeedLogicalDriveInformation;
-      boolean NeedErrorTableInformation;
-      boolean NeedDeviceStateInformation;
-      boolean NeedDeviceInquiryInformation;
-      boolean NeedDeviceSerialNumberInformation;
-      boolean NeedRebuildProgress;
-      boolean NeedConsistencyCheckProgress;
-      boolean NeedBackgroundInitializationStatus;
-      boolean StartDeviceStateScan;
-      boolean RebuildProgressFirst;
-      boolean RebuildFlagPending;
-      boolean RebuildStatusPending;
+      bool DualModeMemoryMailboxInterface;
+      bool BackgroundInitializationStatusSupported;
+      bool SAFTE_EnclosureManagementEnabled;
+      bool NeedLogicalDriveInformation;
+      bool NeedErrorTableInformation;
+      bool NeedDeviceStateInformation;
+      bool NeedDeviceInquiryInformation;
+      bool NeedDeviceSerialNumberInformation;
+      bool NeedRebuildProgress;
+      bool NeedConsistencyCheckProgress;
+      bool NeedBackgroundInitializationStatus;
+      bool StartDeviceStateScan;
+      bool RebuildProgressFirst;
+      bool RebuildFlagPending;
+      bool RebuildStatusPending;
 
       dma_addr_t	FirstCommandMailboxDMA;
       DAC960_V1_CommandMailbox_T *FirstCommandMailbox;
@@ -2432,17 +2425,17 @@
       dma_addr_t NewInquiryUnitSerialNumberDMA;
 
       int DeviceResetCount[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
-      boolean DirectCommandActive[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
+      bool DirectCommandActive[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
     } V1;
     struct {
       unsigned int StatusChangeCounter;
       unsigned int NextEventSequenceNumber;
       unsigned int PhysicalDeviceIndex;
-      boolean NeedLogicalDeviceInformation;
-      boolean NeedPhysicalDeviceInformation;
-      boolean NeedDeviceSerialNumberInformation;
-      boolean StartLogicalDeviceInformationScan;
-      boolean StartPhysicalDeviceInformationScan;
+      bool NeedLogicalDeviceInformation;
+      bool NeedPhysicalDeviceInformation;
+      bool NeedDeviceSerialNumberInformation;
+      bool StartLogicalDeviceInformationScan;
+      bool StartPhysicalDeviceInformationScan;
       struct pci_pool *RequestSensePool;
 
       dma_addr_t	FirstCommandMailboxDMA;
@@ -2487,7 +2480,7 @@
 
       DAC960_V2_PhysicalDevice_T
 	LogicalDriveToVirtualDevice[DAC960_MaxLogicalDrives];
-      boolean LogicalDriveFoundDuringScan[DAC960_MaxLogicalDrives];
+      bool LogicalDriveFoundDuringScan[DAC960_MaxLogicalDrives];
     } V2;
   } FW;
   unsigned char ProgressBuffer[DAC960_ProgressBufferSize];
@@ -2572,17 +2565,17 @@
   unsigned int All;
   struct {
     unsigned int :24;
-    boolean HardwareMailboxNewCommand:1;
-    boolean AcknowledgeHardwareMailboxStatus:1;
-    boolean GenerateInterrupt:1;
-    boolean ControllerReset:1;
-    boolean MemoryMailboxNewCommand:1;
+    bool HardwareMailboxNewCommand:1;
+    bool AcknowledgeHardwareMailboxStatus:1;
+    bool GenerateInterrupt:1;
+    bool ControllerReset:1;
+    bool MemoryMailboxNewCommand:1;
     unsigned int :3;
   } Write;
   struct {
     unsigned int :24;
-    boolean HardwareMailboxFull:1;
-    boolean InitializationInProgress:1;
+    bool HardwareMailboxFull:1;
+    bool InitializationInProgress:1;
     unsigned int :6;
   } Read;
 }
@@ -2596,14 +2589,14 @@
   unsigned int All;
   struct {
     unsigned int :24;
-    boolean AcknowledgeHardwareMailboxInterrupt:1;
-    boolean AcknowledgeMemoryMailboxInterrupt:1;
+    bool AcknowledgeHardwareMailboxInterrupt:1;
+    bool AcknowledgeMemoryMailboxInterrupt:1;
     unsigned int :6;
   } Write;
   struct {
     unsigned int :24;
-    boolean HardwareMailboxStatusAvailable:1;
-    boolean MemoryMailboxStatusAvailable:1;
+    bool HardwareMailboxStatusAvailable:1;
+    bool MemoryMailboxStatusAvailable:1;
     unsigned int :6;
   } Read;
 }
@@ -2635,7 +2628,7 @@
   struct {
     unsigned int :24;
     unsigned int :5;
-    boolean ErrorStatusPending:1;
+    bool ErrorStatusPending:1;
     unsigned int :2;
   } Bits;
 }
@@ -2697,7 +2690,7 @@
 }
 
 static inline
-boolean DAC960_GEM_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
+bool DAC960_GEM_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_GEM_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -2707,7 +2700,7 @@
 }
 
 static inline
-boolean DAC960_GEM_InitializationInProgressP(void __iomem *ControllerBaseAddress)
+bool DAC960_GEM_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_GEM_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -2748,7 +2741,7 @@
 }
 
 static inline
-boolean DAC960_GEM_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_GEM_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_GEM_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -2758,7 +2751,7 @@
 }
 
 static inline
-boolean DAC960_GEM_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_GEM_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_GEM_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -2790,7 +2783,7 @@
 }
 
 static inline
-boolean DAC960_GEM_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
+bool DAC960_GEM_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_GEM_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -2834,7 +2827,7 @@
   return readw(ControllerBaseAddress + DAC960_GEM_CommandStatusOffset + 2);
 }
 
-static inline boolean
+static inline bool
 DAC960_GEM_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
@@ -2882,16 +2875,16 @@
 {
   unsigned char All;
   struct {
-    boolean HardwareMailboxNewCommand:1;		/* Bit 0 */
-    boolean AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
-    boolean GenerateInterrupt:1;			/* Bit 2 */
-    boolean ControllerReset:1;				/* Bit 3 */
-    boolean MemoryMailboxNewCommand:1;			/* Bit 4 */
+    bool HardwareMailboxNewCommand:1;			/* Bit 0 */
+    bool AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
+    bool GenerateInterrupt:1;				/* Bit 2 */
+    bool ControllerReset:1;				/* Bit 3 */
+    bool MemoryMailboxNewCommand:1;			/* Bit 4 */
     unsigned char :3;					/* Bits 5-7 */
   } Write;
   struct {
-    boolean HardwareMailboxEmpty:1;			/* Bit 0 */
-    boolean InitializationNotInProgress:1;		/* Bit 1 */
+    bool HardwareMailboxEmpty:1;			/* Bit 0 */
+    bool InitializationNotInProgress:1;			/* Bit 1 */
     unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
@@ -2906,13 +2899,13 @@
 {
   unsigned char All;
   struct {
-    boolean AcknowledgeHardwareMailboxInterrupt:1;	/* Bit 0 */
-    boolean AcknowledgeMemoryMailboxInterrupt:1;	/* Bit 1 */
+    bool AcknowledgeHardwareMailboxInterrupt:1;		/* Bit 0 */
+    bool AcknowledgeMemoryMailboxInterrupt:1;		/* Bit 1 */
     unsigned char :6;					/* Bits 2-7 */
   } Write;
   struct {
-    boolean HardwareMailboxStatusAvailable:1;		/* Bit 0 */
-    boolean MemoryMailboxStatusAvailable:1;		/* Bit 1 */
+    bool HardwareMailboxStatusAvailable:1;		/* Bit 0 */
+    bool MemoryMailboxStatusAvailable:1;		/* Bit 1 */
     unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
@@ -2928,8 +2921,8 @@
   unsigned char All;
   struct {
     unsigned int :2;					/* Bits 0-1 */
-    boolean DisableInterrupts:1;			/* Bit 2 */
-    boolean DisableInterruptsI2O:1;			/* Bit 3 */
+    bool DisableInterrupts:1;				/* Bit 2 */
+    bool DisableInterruptsI2O:1;			/* Bit 3 */
     unsigned int :4;					/* Bits 4-7 */
   } Bits;
 }
@@ -2945,7 +2938,7 @@
   unsigned char All;
   struct {
     unsigned int :2;					/* Bits 0-1 */
-    boolean ErrorStatusPending:1;			/* Bit 2 */
+    bool ErrorStatusPending:1;				/* Bit 2 */
     unsigned int :5;					/* Bits 3-7 */
   } Bits;
 }
@@ -3008,7 +3001,7 @@
 }
 
 static inline
-boolean DAC960_BA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
+bool DAC960_BA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3017,7 +3010,7 @@
 }
 
 static inline
-boolean DAC960_BA_InitializationInProgressP(void __iomem *ControllerBaseAddress)
+bool DAC960_BA_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3057,7 +3050,7 @@
 }
 
 static inline
-boolean DAC960_BA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_BA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3066,7 +3059,7 @@
 }
 
 static inline
-boolean DAC960_BA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_BA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3097,7 +3090,7 @@
 }
 
 static inline
-boolean DAC960_BA_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
+bool DAC960_BA_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3140,7 +3133,7 @@
   return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset + 2);
 }
 
-static inline boolean
+static inline bool
 DAC960_BA_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
@@ -3188,16 +3181,16 @@
 {
   unsigned char All;
   struct {
-    boolean HardwareMailboxNewCommand:1;		/* Bit 0 */
-    boolean AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
-    boolean GenerateInterrupt:1;			/* Bit 2 */
-    boolean ControllerReset:1;				/* Bit 3 */
-    boolean MemoryMailboxNewCommand:1;			/* Bit 4 */
+    bool HardwareMailboxNewCommand:1;			/* Bit 0 */
+    bool AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
+    bool GenerateInterrupt:1;				/* Bit 2 */
+    bool ControllerReset:1;				/* Bit 3 */
+    bool MemoryMailboxNewCommand:1;			/* Bit 4 */
     unsigned char :3;					/* Bits 5-7 */
   } Write;
   struct {
-    boolean HardwareMailboxFull:1;			/* Bit 0 */
-    boolean InitializationInProgress:1;			/* Bit 1 */
+    bool HardwareMailboxFull:1;				/* Bit 0 */
+    bool InitializationInProgress:1;			/* Bit 1 */
     unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
@@ -3212,13 +3205,13 @@
 {
   unsigned char All;
   struct {
-    boolean AcknowledgeHardwareMailboxInterrupt:1;	/* Bit 0 */
-    boolean AcknowledgeMemoryMailboxInterrupt:1;	/* Bit 1 */
+    bool AcknowledgeHardwareMailboxInterrupt:1;		/* Bit 0 */
+    bool AcknowledgeMemoryMailboxInterrupt:1;		/* Bit 1 */
     unsigned char :6;					/* Bits 2-7 */
   } Write;
   struct {
-    boolean HardwareMailboxStatusAvailable:1;		/* Bit 0 */
-    boolean MemoryMailboxStatusAvailable:1;		/* Bit 1 */
+    bool HardwareMailboxStatusAvailable:1;		/* Bit 0 */
+    bool MemoryMailboxStatusAvailable:1;		/* Bit 1 */
     unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
@@ -3234,7 +3227,7 @@
   unsigned char All;
   struct {
     unsigned int :2;					/* Bits 0-1 */
-    boolean DisableInterrupts:1;			/* Bit 2 */
+    bool DisableInterrupts:1;				/* Bit 2 */
     unsigned int :5;					/* Bits 3-7 */
   } Bits;
 }
@@ -3250,7 +3243,7 @@
   unsigned char All;
   struct {
     unsigned int :2;					/* Bits 0-1 */
-    boolean ErrorStatusPending:1;			/* Bit 2 */
+    bool ErrorStatusPending:1;				/* Bit 2 */
     unsigned int :5;					/* Bits 3-7 */
   } Bits;
 }
@@ -3313,7 +3306,7 @@
 }
 
 static inline
-boolean DAC960_LP_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
+bool DAC960_LP_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3322,7 +3315,7 @@
 }
 
 static inline
-boolean DAC960_LP_InitializationInProgressP(void __iomem *ControllerBaseAddress)
+bool DAC960_LP_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3362,7 +3355,7 @@
 }
 
 static inline
-boolean DAC960_LP_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_LP_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3371,7 +3364,7 @@
 }
 
 static inline
-boolean DAC960_LP_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_LP_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3400,7 +3393,7 @@
 }
 
 static inline
-boolean DAC960_LP_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
+bool DAC960_LP_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3442,7 +3435,7 @@
   return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset + 2);
 }
 
-static inline boolean
+static inline bool
 DAC960_LP_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
@@ -3502,16 +3495,16 @@
 {
   unsigned char All;
   struct {
-    boolean HardwareMailboxNewCommand:1;		/* Bit 0 */
-    boolean AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
-    boolean GenerateInterrupt:1;			/* Bit 2 */
-    boolean ControllerReset:1;				/* Bit 3 */
-    boolean MemoryMailboxNewCommand:1;			/* Bit 4 */
+    bool HardwareMailboxNewCommand:1;			/* Bit 0 */
+    bool AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
+    bool GenerateInterrupt:1;				/* Bit 2 */
+    bool ControllerReset:1;				/* Bit 3 */
+    bool MemoryMailboxNewCommand:1;			/* Bit 4 */
     unsigned char :3;					/* Bits 5-7 */
   } Write;
   struct {
-    boolean HardwareMailboxEmpty:1;			/* Bit 0 */
-    boolean InitializationNotInProgress:1;		/* Bit 1 */
+    bool HardwareMailboxEmpty:1;			/* Bit 0 */
+    bool InitializationNotInProgress:1;		/* Bit 1 */
     unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
@@ -3526,13 +3519,13 @@
 {
   unsigned char All;
   struct {
-    boolean AcknowledgeHardwareMailboxInterrupt:1;	/* Bit 0 */
-    boolean AcknowledgeMemoryMailboxInterrupt:1;	/* Bit 1 */
+    bool AcknowledgeHardwareMailboxInterrupt:1;		/* Bit 0 */
+    bool AcknowledgeMemoryMailboxInterrupt:1;		/* Bit 1 */
     unsigned char :6;					/* Bits 2-7 */
   } Write;
   struct {
-    boolean HardwareMailboxStatusAvailable:1;		/* Bit 0 */
-    boolean MemoryMailboxStatusAvailable:1;		/* Bit 1 */
+    bool HardwareMailboxStatusAvailable:1;		/* Bit 0 */
+    bool MemoryMailboxStatusAvailable:1;		/* Bit 1 */
     unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
@@ -3548,7 +3541,7 @@
   unsigned char All;
   struct {
     unsigned char :2;					/* Bits 0-1 */
-    boolean DisableInterrupts:1;			/* Bit 2 */
+    bool DisableInterrupts:1;				/* Bit 2 */
     unsigned char :5;					/* Bits 3-7 */
   } Bits;
 }
@@ -3564,7 +3557,7 @@
   unsigned char All;
   struct {
     unsigned int :2;					/* Bits 0-1 */
-    boolean ErrorStatusPending:1;			/* Bit 2 */
+    bool ErrorStatusPending:1;				/* Bit 2 */
     unsigned int :5;					/* Bits 3-7 */
   } Bits;
 }
@@ -3627,7 +3620,7 @@
 }
 
 static inline
-boolean DAC960_LA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
+bool DAC960_LA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3636,7 +3629,7 @@
 }
 
 static inline
-boolean DAC960_LA_InitializationInProgressP(void __iomem *ControllerBaseAddress)
+bool DAC960_LA_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3676,7 +3669,7 @@
 }
 
 static inline
-boolean DAC960_LA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_LA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3685,7 +3678,7 @@
 }
 
 static inline
-boolean DAC960_LA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_LA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3714,7 +3707,7 @@
 }
 
 static inline
-boolean DAC960_LA_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
+bool DAC960_LA_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3763,7 +3756,7 @@
   return readw(ControllerBaseAddress + DAC960_LA_StatusRegisterOffset);
 }
 
-static inline boolean
+static inline bool
 DAC960_LA_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
@@ -3822,16 +3815,16 @@
 {
   unsigned int All;
   struct {
-    boolean HardwareMailboxNewCommand:1;		/* Bit 0 */
-    boolean AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
-    boolean GenerateInterrupt:1;			/* Bit 2 */
-    boolean ControllerReset:1;				/* Bit 3 */
-    boolean MemoryMailboxNewCommand:1;			/* Bit 4 */
+    bool HardwareMailboxNewCommand:1;			/* Bit 0 */
+    bool AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
+    bool GenerateInterrupt:1;				/* Bit 2 */
+    bool ControllerReset:1;				/* Bit 3 */
+    bool MemoryMailboxNewCommand:1;			/* Bit 4 */
     unsigned int :27;					/* Bits 5-31 */
   } Write;
   struct {
-    boolean HardwareMailboxFull:1;			/* Bit 0 */
-    boolean InitializationInProgress:1;			/* Bit 1 */
+    bool HardwareMailboxFull:1;				/* Bit 0 */
+    bool InitializationInProgress:1;			/* Bit 1 */
     unsigned int :30;					/* Bits 2-31 */
   } Read;
 }
@@ -3846,13 +3839,13 @@
 {
   unsigned int All;
   struct {
-    boolean AcknowledgeHardwareMailboxInterrupt:1;	/* Bit 0 */
-    boolean AcknowledgeMemoryMailboxInterrupt:1;	/* Bit 1 */
+    bool AcknowledgeHardwareMailboxInterrupt:1;		/* Bit 0 */
+    bool AcknowledgeMemoryMailboxInterrupt:1;		/* Bit 1 */
     unsigned int :30;					/* Bits 2-31 */
   } Write;
   struct {
-    boolean HardwareMailboxStatusAvailable:1;		/* Bit 0 */
-    boolean MemoryMailboxStatusAvailable:1;		/* Bit 1 */
+    bool HardwareMailboxStatusAvailable:1;		/* Bit 0 */
+    bool MemoryMailboxStatusAvailable:1;		/* Bit 1 */
     unsigned int :30;					/* Bits 2-31 */
   } Read;
 }
@@ -3868,7 +3861,7 @@
   unsigned int All;
   struct {
     unsigned int MessageUnitInterruptMask1:2;		/* Bits 0-1 */
-    boolean DisableInterrupts:1;			/* Bit 2 */
+    bool DisableInterrupts:1;				/* Bit 2 */
     unsigned int MessageUnitInterruptMask2:5;		/* Bits 3-7 */
     unsigned int Reserved0:24;				/* Bits 8-31 */
   } Bits;
@@ -3885,7 +3878,7 @@
   unsigned char All;
   struct {
     unsigned int :2;					/* Bits 0-1 */
-    boolean ErrorStatusPending:1;			/* Bit 2 */
+    bool ErrorStatusPending:1;				/* Bit 2 */
     unsigned int :5;					/* Bits 3-7 */
   } Bits;
 }
@@ -3948,7 +3941,7 @@
 }
 
 static inline
-boolean DAC960_PG_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
+bool DAC960_PG_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3957,7 +3950,7 @@
 }
 
 static inline
-boolean DAC960_PG_InitializationInProgressP(void __iomem *ControllerBaseAddress)
+bool DAC960_PG_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3997,7 +3990,7 @@
 }
 
 static inline
-boolean DAC960_PG_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_PG_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -4006,7 +3999,7 @@
 }
 
 static inline
-boolean DAC960_PG_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_PG_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -4039,7 +4032,7 @@
 }
 
 static inline
-boolean DAC960_PG_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
+bool DAC960_PG_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -4088,7 +4081,7 @@
   return readw(ControllerBaseAddress + DAC960_PG_StatusRegisterOffset);
 }
 
-static inline boolean
+static inline bool
 DAC960_PG_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
@@ -4147,15 +4140,15 @@
 {
   unsigned char All;
   struct {
-    boolean NewCommand:1;				/* Bit 0 */
-    boolean AcknowledgeStatus:1;			/* Bit 1 */
-    boolean GenerateInterrupt:1;			/* Bit 2 */
-    boolean ControllerReset:1;				/* Bit 3 */
+    bool NewCommand:1;					/* Bit 0 */
+    bool AcknowledgeStatus:1;				/* Bit 1 */
+    bool GenerateInterrupt:1;				/* Bit 2 */
+    bool ControllerReset:1;				/* Bit 3 */
     unsigned char :4;					/* Bits 4-7 */
   } Write;
   struct {
-    boolean MailboxFull:1;				/* Bit 0 */
-    boolean InitializationInProgress:1;			/* Bit 1 */
+    bool MailboxFull:1;					/* Bit 0 */
+    bool InitializationInProgress:1;			/* Bit 1 */
     unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
@@ -4170,11 +4163,11 @@
 {
   unsigned char All;
   struct {
-    boolean AcknowledgeInterrupt:1;			/* Bit 0 */
+    bool AcknowledgeInterrupt:1;			/* Bit 0 */
     unsigned char :7;					/* Bits 1-7 */
   } Write;
   struct {
-    boolean StatusAvailable:1;				/* Bit 0 */
+    bool StatusAvailable:1;				/* Bit 0 */
     unsigned char :7;					/* Bits 1-7 */
   } Read;
 }
@@ -4189,7 +4182,7 @@
 {
   unsigned char All;
   struct {
-    boolean EnableInterrupts:1;				/* Bit 0 */
+    bool EnableInterrupts:1;				/* Bit 0 */
     unsigned char :7;					/* Bits 1-7 */
   } Bits;
 }
@@ -4205,7 +4198,7 @@
   unsigned char All;
   struct {
     unsigned int :2;					/* Bits 0-1 */
-    boolean ErrorStatusPending:1;			/* Bit 2 */
+    bool ErrorStatusPending:1;				/* Bit 2 */
     unsigned int :5;					/* Bits 3-7 */
   } Bits;
 }
@@ -4258,7 +4251,7 @@
 }
 
 static inline
-boolean DAC960_PD_MailboxFullP(void __iomem *ControllerBaseAddress)
+bool DAC960_PD_MailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -4267,7 +4260,7 @@
 }
 
 static inline
-boolean DAC960_PD_InitializationInProgressP(void __iomem *ControllerBaseAddress)
+bool DAC960_PD_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -4286,7 +4279,7 @@
 }
 
 static inline
-boolean DAC960_PD_StatusAvailableP(void __iomem *ControllerBaseAddress)
+bool DAC960_PD_StatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -4315,7 +4308,7 @@
 }
 
 static inline
-boolean DAC960_PD_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
+bool DAC960_PD_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister;
   InterruptEnableRegister.All =
@@ -4350,7 +4343,7 @@
   return readw(ControllerBaseAddress + DAC960_PD_StatusRegisterOffset);
 }
 
-static inline boolean
+static inline bool
 DAC960_PD_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 58c1deb..cacb1c8 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -417,8 +417,10 @@
 	  etc. See <file:Documentation/initrd.txt> for details.
 
 	  If RAM disk support (BLK_DEV_RAM) is also included, this
-	  also enables initial RAM disk (initrd) support.
+	  also enables initial RAM disk (initrd) support and adds
+	  15 Kbytes (more on some other architectures) to the kernel size.
 
+	  If unsure say Y.
 
 config CDROM_PKTCDVD
 	tristate "Packet writing on CD/DVD media"
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 706cdc6..e3d9152 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -46,7 +46,6 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index e04be94..e2e0432 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -269,7 +269,7 @@
 
 static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
 
-static struct file_operations slm_fops = {
+static const struct file_operations slm_fops = {
 	.owner =	THIS_MODULE,
 	.read =		slm_read,
 	.write =	slm_write,
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index e22b4c9..39e563e 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -233,7 +233,7 @@
 	}
 }
 
-static struct file_operations aoe_fops = {
+static const struct file_operations aoe_fops = {
 	.write = aoechr_write,
 	.read = aoechr_read,
 	.open = aoechr_open,
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 3f1b382..5231ed7 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -297,17 +297,17 @@
 #define DRS (&drive_state[current_drive])
 #define DRWE (&write_errors[current_drive])
 #define FDCS (&fdc_state[fdc])
-#define CLEARF(x) (clear_bit(x##_BIT, &DRS->flags))
-#define SETF(x) (set_bit(x##_BIT, &DRS->flags))
-#define TESTF(x) (test_bit(x##_BIT, &DRS->flags))
+#define CLEARF(x) clear_bit(x##_BIT, &DRS->flags)
+#define SETF(x) set_bit(x##_BIT, &DRS->flags)
+#define TESTF(x) test_bit(x##_BIT, &DRS->flags)
 
 #define UDP (&drive_params[drive])
 #define UDRS (&drive_state[drive])
 #define UDRWE (&write_errors[drive])
 #define UFDCS (&fdc_state[FDC(drive)])
-#define UCLEARF(x) (clear_bit(x##_BIT, &UDRS->flags))
-#define USETF(x) (set_bit(x##_BIT, &UDRS->flags))
-#define UTESTF(x) (test_bit(x##_BIT, &UDRS->flags))
+#define UCLEARF(x) clear_bit(x##_BIT, &UDRS->flags)
+#define USETF(x) set_bit(x##_BIT, &UDRS->flags)
+#define UTESTF(x) test_bit(x##_BIT, &UDRS->flags)
 
 #define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args)
 
diff --git a/drivers/block/paride/Kconfig b/drivers/block/paride/Kconfig
index c0d2854..28cf308 100644
--- a/drivers/block/paride/Kconfig
+++ b/drivers/block/paride/Kconfig
@@ -2,14 +2,8 @@
 # PARIDE configuration
 #
 # PARIDE doesn't need PARPORT, but if PARPORT is configured as a module,
-# PARIDE must also be a module.  The bogus CONFIG_PARIDE_PARPORT option
-# controls the choices given to the user ...
+# PARIDE must also be a module.
 # PARIDE only supports PC style parports. Tough for USB or other parports...
-config PARIDE_PARPORT
-	tristate
-	depends on PARIDE!=n
-	default m if PARPORT_PC=m
-	default y if PARPORT_PC!=m
 
 comment "Parallel IDE high-level drivers"
 	depends on PARIDE
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 9d9bff2..99e2c8c 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -153,7 +153,6 @@
 #include <linux/blkpg.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 
 static DEFINE_SPINLOCK(pd_lock);
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 9970aed..d89e7d32 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -227,7 +227,7 @@
 
 /* kernel glue structures */
 
-static struct file_operations pg_fops = {
+static const struct file_operations pg_fops = {
 	.owner = THIS_MODULE,
 	.read = pg_read,
 	.write = pg_write,
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index c902b25..9f4e67e 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -232,7 +232,7 @@
 
 /* kernel glue structures */
 
-static struct file_operations pt_fops = {
+static const struct file_operations pt_fops = {
 	.owner = THIS_MODULE,
 	.read = pt_read,
 	.write = pt_write,
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 6246219..a4fb703 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -190,15 +190,6 @@
 	NULL
 };
 
-/* declares a char buffer[64] _dbuf, copies data from
- * _b with length _l into it and ensures that _dbuf ends
- * with a \0 character.
- */
-#define DECLARE_BUF_AS_STRING(_dbuf, _b, _l) \
-	char _dbuf[64]; int dlen = (_l) < 0 ? 0 : (_l); \
-	if (dlen >= sizeof(_dbuf)) dlen = sizeof(_dbuf)-1; \
-	memcpy(_dbuf, _b, dlen); _dbuf[dlen] = 0
-
 static ssize_t kobj_pkt_show(struct kobject *kobj,
 			struct attribute *attr, char *data)
 {
@@ -264,9 +255,8 @@
 {
 	struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd;
 	int val;
-	DECLARE_BUF_AS_STRING(dbuf, data, len); /* ensure sscanf scans a string */
 
-	if (strcmp(attr->name, "reset") == 0 && dlen > 0) {
+	if (strcmp(attr->name, "reset") == 0 && len > 0) {
 		pd->stats.pkt_started = 0;
 		pd->stats.pkt_ended = 0;
 		pd->stats.secs_w = 0;
@@ -274,7 +264,7 @@
 		pd->stats.secs_r = 0;
 
 	} else if (strcmp(attr->name, "congestion_off") == 0
-		   && sscanf(dbuf, "%d", &val) == 1) {
+		   && sscanf(data, "%d", &val) == 1) {
 		spin_lock(&pd->lock);
 		pd->write_congestion_off = val;
 		init_write_congestion_marks(&pd->write_congestion_off,
@@ -282,7 +272,7 @@
 		spin_unlock(&pd->lock);
 
 	} else if (strcmp(attr->name, "congestion_on") == 0
-		   && sscanf(dbuf, "%d", &val) == 1) {
+		   && sscanf(data, "%d", &val) == 1) {
 		spin_lock(&pd->lock);
 		pd->write_congestion_on = val;
 		init_write_congestion_marks(&pd->write_congestion_off,
@@ -369,8 +359,7 @@
 					size_t count)
 {
 	unsigned int major, minor;
-	DECLARE_BUF_AS_STRING(dbuf, buf, count);
-	if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) {
+	if (sscanf(buf, "%u:%u", &major, &minor) == 2) {
 		pkt_setup_dev(MKDEV(major, minor), NULL);
 		return count;
 	}
@@ -381,8 +370,7 @@
 					size_t count)
 {
 	unsigned int major, minor;
-	DECLARE_BUF_AS_STRING(dbuf, buf, count);
-	if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) {
+	if (sscanf(buf, "%u:%u", &major, &minor) == 2) {
 		pkt_remove_dev(MKDEV(major, minor));
 		return count;
 	}
@@ -447,7 +435,7 @@
 	return single_open(file, pkt_debugfs_seq_show, inode->i_private);
 }
 
-static struct file_operations debug_fops = {
+static const struct file_operations debug_fops = {
 	.open		= pkt_debugfs_fops_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -777,7 +765,7 @@
 			goto out;
 	}
 
-	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+	rq->cmd_len = COMMAND_SIZE(cgc->cmd[0]);
 	memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
 	if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
 		memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
@@ -1377,7 +1365,7 @@
 	 		&& pd->bio_queue_size <= pd->write_congestion_off);
 	spin_unlock(&pd->lock);
 	if (wakeup)
-		blk_clear_queue_congested(pd->disk->queue, WRITE);
+		clear_bdi_congested(&pd->disk->queue->backing_dev_info, WRITE);
 
 	pkt->sleep_time = max(PACKET_WAIT_TIME, 1);
 	pkt_set_state(pkt, PACKET_WAITING_STATE);
@@ -2598,7 +2586,7 @@
 	spin_lock(&pd->lock);
 	if (pd->write_congestion_on > 0
 	    && pd->bio_queue_size >= pd->write_congestion_on) {
-		blk_set_queue_congested(q, WRITE);
+		set_bdi_congested(&q->backing_dev_info, WRITE);
 		do {
 			spin_unlock(&pd->lock);
 			congestion_wait(WRITE, HZ);
@@ -2737,7 +2725,7 @@
 	return single_open(file, pkt_seq_show, PDE(inode)->data);
 }
 
-static struct file_operations pkt_proc_fops = {
+static const struct file_operations pkt_proc_fops = {
 	.open	= pkt_seq_open,
 	.read	= seq_read,
 	.llseek	= seq_lseek,
@@ -3064,7 +3052,7 @@
 }
 
 
-static struct file_operations pkt_ctl_fops = {
+static const struct file_operations pkt_ctl_fops = {
 	.ioctl	 = pkt_ctl_ioctl,
 	.owner	 = THIS_MODULE,
 };
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 30f16bd..dff3766 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -35,7 +35,6 @@
  */
 
 //#define DEBUG /* uncomment if you want debugging info (pr_debug) */
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/bio.h>
 #include <linux/kernel.h>
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 31ade99..27cceb6 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -27,7 +27,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
 
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index aae3aba..34e5555 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -27,7 +27,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 92648ef..c1bce75 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 77b99ee..459aa97 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 5e2c318..d66064c 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -26,7 +26,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index ad62abb..34f0afc 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -27,7 +27,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 420b645..0f4203b 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -27,7 +27,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 6bdf593..406af57 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -35,7 +35,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/unistd.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index a278d98..b71a5cc 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -332,7 +332,7 @@
 	return 0;
 }
 
-static struct file_operations vhci_fops = {
+static const struct file_operations vhci_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= vhci_llseek,
 	.read		= vhci_read,
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index ec46949..1f9fb7a 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -170,7 +170,6 @@
 
 #include <linux/module.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 3105ddd..b36f44d 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -3553,9 +3553,7 @@
 	if (initialized == 1)
 		return;
 
-	cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
-	if (cdrom_root_table->ctl_name && cdrom_root_table->child->de)
-		cdrom_root_table->child->de->owner = THIS_MODULE;
+	cdrom_sysctl_header = register_sysctl_table(cdrom_root_table);
 
 	/* set the defaults */
 	cdrom_sysctl_settings.autoclose = autoclose;
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index b6c61bb..2301311 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -183,7 +183,6 @@
 #include <linux/errno.h>	/* These include what we really need */
 #include <linux/delay.h>
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
 #include <linux/cdrom.h>
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
index fa70824..b3ab6e9 100644
--- a/drivers/cdrom/gscd.c
+++ b/drivers/cdrom/gscd.c
@@ -53,7 +53,6 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
index bf5aef4e5..5409fca 100644
--- a/drivers/cdrom/sjcd.c
+++ b/drivers/cdrom/sjcd.c
@@ -60,7 +60,6 @@
 
 #include <linux/module.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 93fbf84..dc13eba 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -176,7 +176,7 @@
 	return single_open(file, proc_viocd_show, NULL);
 }
 
-static struct file_operations proc_viocd_operations = {
+static const struct file_operations proc_viocd_operations = {
 	.open		= proc_viocd_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index d08bb4e..d0a6dc5 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -191,7 +191,7 @@
 	  module will be called moxa.
 
 config MOXA_SMARTIO
-	tristate "Moxa SmartIO support"
+	tristate "Moxa SmartIO support (OBSOLETE)"
 	depends on SERIAL_NONSTANDARD
 	help
 	  Say Y here if you have a Moxa SmartIO multiport serial card.
@@ -202,7 +202,7 @@
 	  here.
 
 config MOXA_SMARTIO_NEW
-	tristate "Moxa SmartIO support v. 2.0 (EXPERIMENTAL)"
+	tristate "Moxa SmartIO support v. 2.0"
 	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
 	help
 	  Say Y here if you have a Moxa SmartIO multiport serial card and/or
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 0326ca1..ae8567c 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -60,6 +60,8 @@
 obj-$(CONFIG_PRINTER)		+= lp.o
 obj-$(CONFIG_TIPAR)		+= tipar.o
 
+obj-$(CONFIG_APM_EMULATION)	+= apm-emulation.o
+
 obj-$(CONFIG_DTLK)		+= dtlk.o
 obj-$(CONFIG_R3964)		+= n_r3964.o
 obj-$(CONFIG_APPLICOM)		+= applicom.o
diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile
index 3e58160..627f542 100644
--- a/drivers/char/agp/Makefile
+++ b/drivers/char/agp/Makefile
@@ -1,5 +1,7 @@
 agpgart-y := backend.o frontend.o generic.o isoch.o
 
+agpgart-$(CONFIG_COMPAT)	+= compat_ioctl.o
+
 obj-$(CONFIG_AGP)		+= agpgart.o
 obj-$(CONFIG_AGP_ALI)		+= ali-agp.o
 obj-$(CONFIG_AGP_ATI)		+= ati-agp.o
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 1d59e2a..fdbca25 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -93,12 +93,12 @@
 
 struct agp_bridge_driver {
 	struct module *owner;
-	void *aperture_sizes;
+	const void *aperture_sizes;
 	int num_aperture_sizes;
 	enum aper_size_type size_type;
 	int cant_use_aperture;
 	int needs_scratch_page;
-	struct gatt_mask *masks;
+	const struct gatt_mask *masks;
 	int (*fetch_size)(void);
 	int (*configure)(void);
 	void (*agp_enable)(struct agp_bridge_data *, u32);
@@ -114,11 +114,12 @@
 	void (*free_by_type)(struct agp_memory *);
 	void *(*agp_alloc_page)(struct agp_bridge_data *);
 	void (*agp_destroy_page)(void *);
+        int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
 };
 
 struct agp_bridge_data {
 	const struct agp_version *version;
-	struct agp_bridge_driver *driver;
+	const struct agp_bridge_driver *driver;
 	struct vm_operations_struct *vm_ops;
 	void *previous_size;
 	void *current_size;
@@ -218,6 +219,7 @@
 #define I810_PTE_MAIN_UNCACHED	0x00000000
 #define I810_PTE_LOCAL		0x00000002
 #define I810_PTE_VALID		0x00000001
+#define I830_PTE_SYSTEM_CACHED  0x00000006
 #define I810_SMRAM_MISCC	0x70
 #define I810_GFX_MEM_WIN_SIZE	0x00010000
 #define I810_GFX_MEM_WIN_32M	0x00010000
@@ -270,8 +272,16 @@
 void get_agp_version(struct agp_bridge_data *bridge);
 unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
 	unsigned long addr, int type);
+int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge,
+				  int type);
 struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev);
 
+/* generic functions for user-populated AGP memory types */
+struct agp_memory *agp_generic_alloc_user(size_t page_count, int type);
+void agp_alloc_page_array(size_t size, struct agp_memory *mem);
+void agp_free_page_array(struct agp_memory *mem);
+
+
 /* generic routines for agp>=3 */
 int agp3_generic_fetch_size(void);
 void agp3_generic_tlbflush(struct agp_memory *mem);
@@ -280,7 +290,7 @@
 
 /* aperture sizes have been standardised since v3 */
 #define AGP_GENERIC_SIZES_ENTRIES 11
-extern struct aper_size_info_16 agp3_generic_sizes[];
+extern const struct aper_size_info_16 agp3_generic_sizes[];
 
 #define virt_to_gart(x) (phys_to_gart(virt_to_phys(x)))
 #define gart_to_virt(x) (phys_to_virt(gart_to_phys(x)))
@@ -288,6 +298,8 @@
 extern int agp_off;
 extern int agp_try_unsupported_boot;
 
+long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+
 /* Chipset independant registers (from AGP Spec) */
 #define AGP_APBASE	0x10
 
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 5a31ec7..5b684fd 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -182,7 +182,7 @@
 
 /* Setup function */
 
-static struct aper_size_info_32 ali_generic_sizes[7] =
+static const struct aper_size_info_32 ali_generic_sizes[7] =
 {
 	{256, 65536, 6, 10},
 	{128, 32768, 5, 9},
@@ -193,7 +193,7 @@
 	{4, 1024, 0, 3}
 };
 
-static struct agp_bridge_driver ali_generic_bridge = {
+static const struct agp_bridge_driver ali_generic_bridge = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= ali_generic_sizes,
 	.size_type		= U32_APER_SIZE,
@@ -214,9 +214,10 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= ali_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver ali_m1541_bridge = {
+static const struct agp_bridge_driver ali_m1541_bridge = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= ali_generic_sizes,
 	.size_type		= U32_APER_SIZE,
@@ -237,6 +238,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= m1541_alloc_page,
 	.agp_destroy_page	= m1541_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
index b4e00a3..b0acf41 100644
--- a/drivers/char/agp/alpha-agp.c
+++ b/drivers/char/agp/alpha-agp.c
@@ -91,6 +91,9 @@
 	int num_entries, status;
 	void *temp;
 
+	if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
+		return -EINVAL;
+
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_FIX(temp)->num_entries;
 	if ((pg_start + mem->page_count) > num_entries)
@@ -142,6 +145,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 struct agp_bridge_data *alpha_bridge;
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index c85c8ca..e6c534e 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -344,7 +344,7 @@
 	return 0;
 }
 
-static struct aper_size_info_lvl2 amd_irongate_sizes[7] =
+static const struct aper_size_info_lvl2 amd_irongate_sizes[7] =
 {
 	{2048, 524288, 0x0000000c},
 	{1024, 262144, 0x0000000a},
@@ -355,12 +355,12 @@
 	{32, 8192, 0x00000000}
 };
 
-static struct gatt_mask amd_irongate_masks[] =
+static const struct gatt_mask amd_irongate_masks[] =
 {
 	{.mask = 1, .type = 0}
 };
 
-static struct agp_bridge_driver amd_irongate_driver = {
+static const struct agp_bridge_driver amd_irongate_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= amd_irongate_sizes,
 	.size_type		= LVL2_APER_SIZE,
@@ -381,6 +381,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 93d2209..4857204 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -62,12 +62,18 @@
 {
 	int i, j, num_entries;
 	long long tmp;
+	int mask_type;
+	struct agp_bridge_data *bridge = mem->bridge;
 	u32 pte;
 
 	num_entries = agp_num_entries();
 
-	if (type != 0 || mem->type != 0)
+	if (type != mem->type)
 		return -EINVAL;
+	mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
+	if (mask_type != 0)
+		return -EINVAL;
+
 
 	/* Make sure we can fit the range in the gatt table. */
 	/* FIXME: could wrap */
@@ -90,7 +96,7 @@
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		tmp = agp_bridge->driver->mask_memory(agp_bridge,
-			mem->memory[i], mem->type);
+			mem->memory[i], mask_type);
 
 		BUG_ON(tmp & 0xffffff0000000ffcULL);
 		pte = (tmp & 0x000000ff00000000ULL) >> 28;
@@ -186,7 +192,7 @@
 }
 
 
-static struct aper_size_info_32 amd_8151_sizes[7] =
+static const struct aper_size_info_32 amd_8151_sizes[7] =
 {
 	{2048, 524288, 9, 0x00000000 },	/* 0 0 0 0 0 0 */
 	{1024, 262144, 8, 0x00000400 },	/* 1 0 0 0 0 0 */
@@ -226,7 +232,7 @@
 }
 
 
-static struct agp_bridge_driver amd_8151_driver = {
+static const struct agp_bridge_driver amd_8151_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= amd_8151_sizes,
 	.size_type		= U32_APER_SIZE,
@@ -247,6 +253,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 /* Some basic sanity checks for the aperture. */
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 9987dc2..780e59e 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -24,7 +24,7 @@
 #define ATI_GART_CACHE_ENTRY_CNTRL	0x10
 
 
-static struct aper_size_info_lvl2 ati_generic_sizes[7] =
+static const struct aper_size_info_lvl2 ati_generic_sizes[7] =
 {
 	{2048, 524288, 0x0000000c},
 	{1024, 262144, 0x0000000a},
@@ -410,7 +410,7 @@
 	return 0;
 }
 
-static struct agp_bridge_driver ati_generic_bridge = {
+static const struct agp_bridge_driver ati_generic_bridge = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= ati_generic_sizes,
 	.size_type		= LVL2_APER_SIZE,
@@ -431,6 +431,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index d59e037..ebdd6dd 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -43,7 +43,7 @@
  * fix some real stupidity. It's only by chance we can bump
  * past 0.99 at all due to some boolean logic error. */
 #define AGPGART_VERSION_MAJOR 0
-#define AGPGART_VERSION_MINOR 101
+#define AGPGART_VERSION_MINOR 102
 static const struct agp_version agp_current_version =
 {
 	.major = AGPGART_VERSION_MAJOR,
diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c
new file mode 100644
index 0000000..fcb4b1b
--- /dev/null
+++ b/drivers/char/agp/compat_ioctl.c
@@ -0,0 +1,282 @@
+/*
+ * AGPGART driver frontend compatibility ioctls
+ * Copyright (C) 2004 Silicon Graphics, Inc.
+ * Copyright (C) 2002-2003 Dave Jones
+ * Copyright (C) 1999 Jeff Hartmann
+ * Copyright (C) 1999 Precision Insight, Inc.
+ * Copyright (C) 1999 Xi Graphics, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * 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
+ * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/agpgart.h>
+#include <asm/uaccess.h>
+#include "agp.h"
+#include "compat_ioctl.h"
+
+static int compat_agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
+{
+	struct agp_info32 userinfo;
+	struct agp_kern_info kerninfo;
+
+	agp_copy_info(agp_bridge, &kerninfo);
+
+	userinfo.version.major = kerninfo.version.major;
+	userinfo.version.minor = kerninfo.version.minor;
+	userinfo.bridge_id = kerninfo.device->vendor |
+	    (kerninfo.device->device << 16);
+	userinfo.agp_mode = kerninfo.mode;
+	userinfo.aper_base = (compat_long_t)kerninfo.aper_base;
+	userinfo.aper_size = kerninfo.aper_size;
+	userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
+	userinfo.pg_used = kerninfo.current_memory;
+
+	if (copy_to_user(arg, &userinfo, sizeof(userinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
+{
+	struct agp_region32 ureserve;
+	struct agp_region kreserve;
+	struct agp_client *client;
+	struct agp_file_private *client_priv;
+
+	DBG("");
+	if (copy_from_user(&ureserve, arg, sizeof(ureserve)))
+		return -EFAULT;
+
+	if ((unsigned) ureserve.seg_count >= ~0U/sizeof(struct agp_segment32))
+		return -EFAULT;
+
+	kreserve.pid = ureserve.pid;
+	kreserve.seg_count = ureserve.seg_count;
+
+	client = agp_find_client_by_pid(kreserve.pid);
+
+	if (kreserve.seg_count == 0) {
+		/* remove a client */
+		client_priv = agp_find_private(kreserve.pid);
+
+		if (client_priv != NULL) {
+			set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
+			set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
+		}
+		if (client == NULL) {
+			/* client is already removed */
+			return 0;
+		}
+		return agp_remove_client(kreserve.pid);
+	} else {
+		struct agp_segment32 *usegment;
+		struct agp_segment *ksegment;
+		int seg;
+
+		if (ureserve.seg_count >= 16384)
+			return -EINVAL;
+
+		usegment = kmalloc(sizeof(*usegment) * ureserve.seg_count, GFP_KERNEL);
+		if (!usegment)
+			return -ENOMEM;
+
+		ksegment = kmalloc(sizeof(*ksegment) * kreserve.seg_count, GFP_KERNEL);
+		if (!ksegment) {
+			kfree(usegment);
+			return -ENOMEM;
+		}
+
+		if (copy_from_user(usegment, (void __user *) ureserve.seg_list,
+				   sizeof(*usegment) * ureserve.seg_count)) {
+			kfree(usegment);
+			kfree(ksegment);
+			return -EFAULT;
+		}
+
+		for (seg = 0; seg < ureserve.seg_count; seg++) {
+			ksegment[seg].pg_start = usegment[seg].pg_start;
+			ksegment[seg].pg_count = usegment[seg].pg_count;
+			ksegment[seg].prot = usegment[seg].prot;
+		}
+
+		kfree(usegment);
+		kreserve.seg_list = ksegment;
+
+		if (client == NULL) {
+			/* Create the client and add the segment */
+			client = agp_create_client(kreserve.pid);
+
+			if (client == NULL) {
+				kfree(ksegment);
+				return -ENOMEM;
+			}
+			client_priv = agp_find_private(kreserve.pid);
+
+			if (client_priv != NULL) {
+				set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
+				set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
+			}
+		}
+		return agp_create_segment(client, &kreserve);
+	}
+	/* Will never really happen */
+	return -EINVAL;
+}
+
+static int compat_agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
+{
+	struct agp_memory *memory;
+	struct agp_allocate32 alloc;
+
+	DBG("");
+	if (copy_from_user(&alloc, arg, sizeof(alloc)))
+		return -EFAULT;
+
+	memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
+
+	if (memory == NULL)
+		return -ENOMEM;
+
+	alloc.key = memory->key;
+	alloc.physical = memory->physical;
+
+	if (copy_to_user(arg, &alloc, sizeof(alloc))) {
+		agp_free_memory_wrap(memory);
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static int compat_agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
+{
+	struct agp_bind32 bind_info;
+	struct agp_memory *memory;
+
+	DBG("");
+	if (copy_from_user(&bind_info, arg, sizeof(bind_info)))
+		return -EFAULT;
+
+	memory = agp_find_mem_by_key(bind_info.key);
+
+	if (memory == NULL)
+		return -EINVAL;
+
+	return agp_bind_memory(memory, bind_info.pg_start);
+}
+
+static int compat_agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
+{
+	struct agp_memory *memory;
+	struct agp_unbind32 unbind;
+
+	DBG("");
+	if (copy_from_user(&unbind, arg, sizeof(unbind)))
+		return -EFAULT;
+
+	memory = agp_find_mem_by_key(unbind.key);
+
+	if (memory == NULL)
+		return -EINVAL;
+
+	return agp_unbind_memory(memory);
+}
+
+long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct agp_file_private *curr_priv = file->private_data;
+	int ret_val = -ENOTTY;
+
+	mutex_lock(&(agp_fe.agp_mutex));
+
+	if ((agp_fe.current_controller == NULL) &&
+	    (cmd != AGPIOC_ACQUIRE32)) {
+		ret_val = -EINVAL;
+		goto ioctl_out;
+	}
+	if ((agp_fe.backend_acquired != TRUE) &&
+	    (cmd != AGPIOC_ACQUIRE32)) {
+		ret_val = -EBUSY;
+		goto ioctl_out;
+	}
+	if (cmd != AGPIOC_ACQUIRE32) {
+		if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
+			ret_val = -EPERM;
+			goto ioctl_out;
+		}
+		/* Use the original pid of the controller,
+		 * in case it's threaded */
+
+		if (agp_fe.current_controller->pid != curr_priv->my_pid) {
+			ret_val = -EBUSY;
+			goto ioctl_out;
+		}
+	}
+
+	switch (cmd) {
+	case AGPIOC_INFO32:
+		ret_val = compat_agpioc_info_wrap(curr_priv, (void __user *) arg);
+		break;
+
+	case AGPIOC_ACQUIRE32:
+		ret_val = agpioc_acquire_wrap(curr_priv);
+		break;
+
+	case AGPIOC_RELEASE32:
+		ret_val = agpioc_release_wrap(curr_priv);
+		break;
+
+	case AGPIOC_SETUP32:
+		ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
+		break;
+
+	case AGPIOC_RESERVE32:
+		ret_val = compat_agpioc_reserve_wrap(curr_priv, (void __user *) arg);
+		break;
+
+	case AGPIOC_PROTECT32:
+		ret_val = agpioc_protect_wrap(curr_priv);
+		break;
+
+	case AGPIOC_ALLOCATE32:
+		ret_val = compat_agpioc_allocate_wrap(curr_priv, (void __user *) arg);
+		break;
+
+	case AGPIOC_DEALLOCATE32:
+		ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
+		break;
+
+	case AGPIOC_BIND32:
+		ret_val = compat_agpioc_bind_wrap(curr_priv, (void __user *) arg);
+		break;
+
+	case AGPIOC_UNBIND32:
+		ret_val = compat_agpioc_unbind_wrap(curr_priv, (void __user *) arg);
+		break;
+	}
+
+ioctl_out:
+	DBG("ioctl returns %d\n", ret_val);
+	mutex_unlock(&(agp_fe.agp_mutex));
+	return ret_val;
+}
+
diff --git a/drivers/char/agp/compat_ioctl.h b/drivers/char/agp/compat_ioctl.h
new file mode 100644
index 0000000..71939d6
--- /dev/null
+++ b/drivers/char/agp/compat_ioctl.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 1999 Jeff Hartmann
+ * Copyright (C) 1999 Precision Insight, Inc.
+ * Copyright (C) 1999 Xi Graphics, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * 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
+ * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS 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 _AGP_COMPAT_IOCTL_H
+#define _AGP_COMPAT_IOCTL_H
+
+#include <linux/compat.h>
+#include <linux/agpgart.h>
+
+#define AGPIOC_INFO32       _IOR (AGPIOC_BASE, 0, compat_uptr_t)
+#define AGPIOC_ACQUIRE32    _IO  (AGPIOC_BASE, 1)
+#define AGPIOC_RELEASE32    _IO  (AGPIOC_BASE, 2)
+#define AGPIOC_SETUP32      _IOW (AGPIOC_BASE, 3, compat_uptr_t)
+#define AGPIOC_RESERVE32    _IOW (AGPIOC_BASE, 4, compat_uptr_t)
+#define AGPIOC_PROTECT32    _IOW (AGPIOC_BASE, 5, compat_uptr_t)
+#define AGPIOC_ALLOCATE32   _IOWR(AGPIOC_BASE, 6, compat_uptr_t)
+#define AGPIOC_DEALLOCATE32 _IOW (AGPIOC_BASE, 7, compat_int_t)
+#define AGPIOC_BIND32       _IOW (AGPIOC_BASE, 8, compat_uptr_t)
+#define AGPIOC_UNBIND32     _IOW (AGPIOC_BASE, 9, compat_uptr_t)
+
+struct agp_info32 {
+	struct agp_version version;	/* version of the driver        */
+	u32 bridge_id;		/* bridge vendor/device         */
+	u32 agp_mode;		/* mode info of bridge          */
+	compat_long_t aper_base;	/* base of aperture             */
+	compat_size_t aper_size;	/* size of aperture             */
+	compat_size_t pg_total;	/* max pages (swap + system)    */
+	compat_size_t pg_system;	/* max pages (system)           */
+	compat_size_t pg_used;		/* current pages used           */
+};
+
+/*
+ * The "prot" down below needs still a "sleep" flag somehow ...
+ */
+struct agp_segment32 {
+	compat_off_t pg_start;		/* starting page to populate    */
+	compat_size_t pg_count;	/* number of pages              */
+	compat_int_t prot;		/* prot flags for mmap          */
+};
+
+struct agp_region32 {
+	compat_pid_t pid;		/* pid of process               */
+	compat_size_t seg_count;	/* number of segments           */
+	struct agp_segment32 *seg_list;
+};
+
+struct agp_allocate32 {
+	compat_int_t key;		/* tag of allocation            */
+	compat_size_t pg_count;	/* number of pages              */
+	u32 type;		/* 0 == normal, other devspec   */
+	u32 physical;           /* device specific (some devices
+				 * need a phys address of the
+				 * actual page behind the gatt
+				 * table)                        */
+};
+
+struct agp_bind32 {
+	compat_int_t key;		/* tag of allocation            */
+	compat_off_t pg_start;		/* starting page to populate    */
+};
+
+struct agp_unbind32 {
+	compat_int_t key;		/* tag of allocation            */
+	u32 priority;		/* priority for paging out      */
+};
+
+extern struct agp_front_data agp_fe;
+
+int agpioc_acquire_wrap(struct agp_file_private *priv);
+int agpioc_release_wrap(struct agp_file_private *priv);
+int agpioc_protect_wrap(struct agp_file_private *priv);
+int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg);
+int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg);
+struct agp_file_private *agp_find_private(pid_t pid);
+struct agp_client *agp_create_client(pid_t id);
+int agp_remove_client(pid_t id);
+int agp_create_segment(struct agp_client *client, struct agp_region *region);
+void agp_free_memory_wrap(struct agp_memory *memory);
+struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type);
+struct agp_memory *agp_find_mem_by_key(int key);
+struct agp_client *agp_find_client_by_pid(pid_t id);
+
+#endif /* _AGP_COMPAT_H */
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 30f730f..df8da72 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -59,7 +59,7 @@
 	unsigned long l1_table[EFFICEON_L1_SIZE];
 } efficeon_private;
 
-static struct gatt_mask efficeon_generic_masks[] =
+static const struct gatt_mask efficeon_generic_masks[] =
 {
 	{.mask = 0x00000001, .type = 0}
 };
@@ -70,7 +70,7 @@
 	return addr | 0x00000001;
 }
 
-static struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
+static const struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
 {
 	{256, 65536, 0},
 	{128, 32768, 32},
@@ -309,7 +309,7 @@
 }
 
 
-static struct agp_bridge_driver efficeon_driver = {
+static const struct agp_bridge_driver efficeon_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= efficeon_generic_sizes,
 	.size_type		= LVL2_APER_SIZE,
@@ -335,6 +335,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 0f2ed2a..679d7f9 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -41,9 +41,9 @@
 #include <asm/pgtable.h>
 #include "agp.h"
 
-static struct agp_front_data agp_fe;
+struct agp_front_data agp_fe;
 
-static struct agp_memory *agp_find_mem_by_key(int key)
+struct agp_memory *agp_find_mem_by_key(int key)
 {
 	struct agp_memory *curr;
 
@@ -159,7 +159,7 @@
 	return vm_get_page_prot(prot_bits);
 }
 
-static int agp_create_segment(struct agp_client *client, struct agp_region *region)
+int agp_create_segment(struct agp_client *client, struct agp_region *region)
 {
 	struct agp_segment_priv **ret_seg;
 	struct agp_segment_priv *seg;
@@ -211,7 +211,7 @@
 
 /* File private list routines */
 
-static struct agp_file_private *agp_find_private(pid_t pid)
+struct agp_file_private *agp_find_private(pid_t pid)
 {
 	struct agp_file_private *curr;
 
@@ -266,13 +266,13 @@
  * Wrappers for agp_free_memory & agp_allocate_memory
  * These make sure that internal lists are kept updated.
  */
-static void agp_free_memory_wrap(struct agp_memory *memory)
+void agp_free_memory_wrap(struct agp_memory *memory)
 {
 	agp_remove_from_pool(memory);
 	agp_free_memory(memory);
 }
 
-static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
+struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
 {
 	struct agp_memory *memory;
 
@@ -484,7 +484,7 @@
 	return NULL;
 }
 
-static struct agp_client *agp_find_client_by_pid(pid_t id)
+struct agp_client *agp_find_client_by_pid(pid_t id)
 {
 	struct agp_client *temp;
 
@@ -509,7 +509,7 @@
 	agp_fe.current_controller->num_clients++;
 }
 
-static struct agp_client *agp_create_client(pid_t id)
+struct agp_client *agp_create_client(pid_t id)
 {
 	struct agp_client *new_client;
 
@@ -522,7 +522,7 @@
 	return new_client;
 }
 
-static int agp_remove_client(pid_t id)
+int agp_remove_client(pid_t id)
 {
 	struct agp_client *client;
 	struct agp_client *prev_client;
@@ -746,7 +746,7 @@
 	return 0;
 }
 
-static int agpioc_acquire_wrap(struct agp_file_private *priv)
+int agpioc_acquire_wrap(struct agp_file_private *priv)
 {
 	struct agp_controller *controller;
 
@@ -789,14 +789,14 @@
 	return 0;
 }
 
-static int agpioc_release_wrap(struct agp_file_private *priv)
+int agpioc_release_wrap(struct agp_file_private *priv)
 {
 	DBG("");
 	agp_controller_release_current(agp_fe.current_controller, priv);
 	return 0;
 }
 
-static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
+int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
 {
 	struct agp_setup mode;
 
@@ -876,7 +876,7 @@
 	return -EINVAL;
 }
 
-static int agpioc_protect_wrap(struct agp_file_private *priv)
+int agpioc_protect_wrap(struct agp_file_private *priv)
 {
 	DBG("");
 	/* This function is not currently implemented */
@@ -892,6 +892,9 @@
 	if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
 		return -EFAULT;
 
+	if (alloc.type >= AGP_USER_TYPES)
+		return -EINVAL;
+
 	memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
 
 	if (memory == NULL)
@@ -907,7 +910,7 @@
 	return 0;
 }
 
-static int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
+int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
 {
 	struct agp_memory *memory;
 
@@ -1043,6 +1046,9 @@
 	.read		= agp_read,
 	.write		= agp_write,
 	.ioctl		= agp_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= compat_agp_ioctl,
+#endif
 	.mmap		= agp_mmap,
 	.open		= agp_open,
 	.release	= agp_release,
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 3491d6f..f902d71 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -101,6 +101,63 @@
 	return -1;
 }
 
+/*
+ * Use kmalloc if possible for the page list. Otherwise fall back to
+ * vmalloc. This speeds things up and also saves memory for small AGP
+ * regions.
+ */
+
+void agp_alloc_page_array(size_t size, struct agp_memory *mem)
+{
+	mem->memory = NULL;
+	mem->vmalloc_flag = 0;
+
+	if (size <= 2*PAGE_SIZE)
+		mem->memory = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
+	if (mem->memory == NULL) {
+		mem->memory = vmalloc(size);
+		mem->vmalloc_flag = 1;
+	}
+}
+EXPORT_SYMBOL(agp_alloc_page_array);
+
+void agp_free_page_array(struct agp_memory *mem)
+{
+	if (mem->vmalloc_flag) {
+		vfree(mem->memory);
+	} else {
+		kfree(mem->memory);
+	}
+}
+EXPORT_SYMBOL(agp_free_page_array);
+
+
+static struct agp_memory *agp_create_user_memory(unsigned long num_agp_pages)
+{
+	struct agp_memory *new;
+	unsigned long alloc_size = num_agp_pages*sizeof(struct page *);
+
+	new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL);
+	if (new == NULL)
+		return NULL;
+
+	new->key = agp_get_key();
+
+	if (new->key < 0) {
+		kfree(new);
+		return NULL;
+	}
+
+	agp_alloc_page_array(alloc_size, new);
+
+	if (new->memory == NULL) {
+		agp_free_key(new->key);
+		kfree(new);
+		return NULL;
+	}
+	new->num_scratch_pages = 0;
+	return new;
+}
 
 struct agp_memory *agp_create_memory(int scratch_pages)
 {
@@ -116,7 +173,8 @@
 		kfree(new);
 		return NULL;
 	}
-	new->memory = vmalloc(PAGE_SIZE * scratch_pages);
+
+	agp_alloc_page_array(PAGE_SIZE * scratch_pages, new);
 
 	if (new->memory == NULL) {
 		agp_free_key(new->key);
@@ -124,6 +182,7 @@
 		return NULL;
 	}
 	new->num_scratch_pages = scratch_pages;
+	new->type = AGP_NORMAL_MEMORY;
 	return new;
 }
 EXPORT_SYMBOL(agp_create_memory);
@@ -146,6 +205,11 @@
 	if (curr->is_bound == TRUE)
 		agp_unbind_memory(curr);
 
+	if (curr->type >= AGP_USER_TYPES) {
+		agp_generic_free_by_type(curr);
+		return;
+	}
+
 	if (curr->type != 0) {
 		curr->bridge->driver->free_by_type(curr);
 		return;
@@ -157,7 +221,7 @@
 		flush_agp_mappings();
 	}
 	agp_free_key(curr->key);
-	vfree(curr->memory);
+	agp_free_page_array(curr);
 	kfree(curr);
 }
 EXPORT_SYMBOL(agp_free_memory);
@@ -188,6 +252,13 @@
 	if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
 		return NULL;
 
+	if (type >= AGP_USER_TYPES) {
+		new = agp_generic_alloc_user(page_count, type);
+		if (new)
+			new->bridge = bridge;
+		return new;
+	}
+
 	if (type != 0) {
 		new = bridge->driver->alloc_by_type(page_count, type);
 		if (new)
@@ -960,6 +1031,7 @@
 	off_t j;
 	void *temp;
 	struct agp_bridge_data *bridge;
+	int mask_type;
 
 	bridge = mem->bridge;
 	if (!bridge)
@@ -995,7 +1067,11 @@
 	num_entries -= agp_memory_reserved/PAGE_SIZE;
 	if (num_entries < 0) num_entries = 0;
 
-	if (type != 0 || mem->type != 0) {
+	if (type != mem->type)
+		return -EINVAL;
+
+	mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
+	if (mask_type != 0) {
 		/* The generic routines know nothing of memory types */
 		return -EINVAL;
 	}
@@ -1018,7 +1094,8 @@
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j);
+		writel(bridge->driver->mask_memory(bridge, mem->memory[i], mask_type),
+		       bridge->gatt_table+j);
 	}
 	readl(bridge->gatt_table+j-1);	/* PCI Posting. */
 
@@ -1032,6 +1109,7 @@
 {
 	size_t i;
 	struct agp_bridge_data *bridge;
+	int mask_type;
 
 	bridge = mem->bridge;
 	if (!bridge)
@@ -1040,7 +1118,11 @@
 	if (mem->page_count == 0)
 		return 0;
 
-	if (type != 0 || mem->type != 0) {
+	if (type != mem->type)
+		return -EINVAL;
+
+	mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
+	if (mask_type != 0) {
 		/* The generic routines know nothing of memory types */
 		return -EINVAL;
 	}
@@ -1056,22 +1138,40 @@
 }
 EXPORT_SYMBOL(agp_generic_remove_memory);
 
-
 struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type)
 {
 	return NULL;
 }
 EXPORT_SYMBOL(agp_generic_alloc_by_type);
 
-
 void agp_generic_free_by_type(struct agp_memory *curr)
 {
-	vfree(curr->memory);
+	agp_free_page_array(curr);
 	agp_free_key(curr->key);
 	kfree(curr);
 }
 EXPORT_SYMBOL(agp_generic_free_by_type);
 
+struct agp_memory *agp_generic_alloc_user(size_t page_count, int type)
+{
+	struct agp_memory *new;
+	int i;
+	int pages;
+
+	pages = (page_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;
+	new = agp_create_user_memory(page_count);
+	if (new == NULL)
+		return NULL;
+
+	for (i = 0; i < page_count; i++)
+		new->memory[i] = 0;
+	new->page_count = 0;
+	new->type = type;
+	new->num_scratch_pages = pages;
+
+	return new;
+}
+EXPORT_SYMBOL(agp_generic_alloc_user);
 
 /*
  * Basic Page Allocation Routines -
@@ -1165,6 +1265,15 @@
 }
 EXPORT_SYMBOL(agp_generic_mask_memory);
 
+int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge,
+				  int type)
+{
+	if (type >= AGP_USER_TYPES)
+		return 0;
+	return type;
+}
+EXPORT_SYMBOL(agp_generic_type_to_mask_type);
+
 /*
  * These functions are implemented according to the AGPv3 spec,
  * which covers implementation details that had previously been
@@ -1231,7 +1340,7 @@
 }
 EXPORT_SYMBOL(agp3_generic_cleanup);
 
-struct aper_size_info_16 agp3_generic_sizes[AGP_GENERIC_SIZES_ENTRIES] =
+const struct aper_size_info_16 agp3_generic_sizes[AGP_GENERIC_SIZES_ENTRIES] =
 {
 	{4096, 1048576, 10,0x000},
 	{2048,  524288, 9, 0x800},
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 907fb66..79f7c01 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -419,7 +419,7 @@
 	agp_device_command(command, (mode & AGP8X_MODE) != 0);
 }
 
-struct agp_bridge_driver hp_zx1_driver = {
+struct const agp_bridge_driver hp_zx1_driver = {
 	.owner			= THIS_MODULE,
 	.size_type		= FIXED_APER_SIZE,
 	.configure		= hp_zx1_configure,
@@ -438,6 +438,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 	.cant_use_aperture	= 1,
 };
 
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 9176944..1cde376 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -78,7 +78,7 @@
 	} *lp_desc;
 } i460;
 
-static struct aper_size_info_8 i460_sizes[3] =
+static const struct aper_size_info_8 i460_sizes[3] =
 {
 	/*
 	 * The 32GB aperture is only available with a 4M GART page size.  Due to the
@@ -293,6 +293,9 @@
 	pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n",
 		 mem, pg_start, type, mem->memory[0]);
 
+	if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
+		return -EINVAL;
+
 	io_pg_start = I460_IOPAGES_PER_KPAGE * pg_start;
 
 	temp = agp_bridge->current_size;
@@ -396,6 +399,9 @@
 	struct lp_desc *start, *end, *lp;
 	void *temp;
 
+	if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
+		return -EINVAL;
+
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_8(temp)->num_entries;
 
@@ -544,7 +550,7 @@
 		| (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xfffff000) >> 12);
 }
 
-struct agp_bridge_driver intel_i460_driver = {
+struct const agp_bridge_driver intel_i460_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= i460_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -572,6 +578,7 @@
 #endif
 	.alloc_by_type		= agp_generic_alloc_by_type,
 	.free_by_type		= agp_generic_free_by_type,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 	.cant_use_aperture	= 1,
 };
 
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index a3011de..e542a62 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/agp_backend.h>
 #include "agp.h"
@@ -24,6 +25,9 @@
                  agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB)
 
 
+extern int agp_memory_reserved;
+
+
 /* Intel 815 register */
 #define INTEL_815_APCONT	0x51
 #define INTEL_815_ATTBASE_MASK	~0x1FFFFFFF
@@ -59,7 +63,7 @@
 #define INTEL_I7505_AGPCTRL	0x70
 #define INTEL_I7505_MCHCFG	0x50
 
-static struct aper_size_info_fixed intel_i810_sizes[] =
+static const struct aper_size_info_fixed intel_i810_sizes[] =
 {
 	{64, 16384, 4},
 	/* The 32M mode still requires a 64k gatt */
@@ -68,12 +72,15 @@
 
 #define AGP_DCACHE_MEMORY	1
 #define AGP_PHYS_MEMORY		2
+#define INTEL_AGP_CACHED_MEMORY 3
 
 static struct gatt_mask intel_i810_masks[] =
 {
 	{.mask = I810_PTE_VALID, .type = 0},
 	{.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
-	{.mask = I810_PTE_VALID, .type = 0}
+	{.mask = I810_PTE_VALID, .type = 0},
+	{.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED,
+	 .type = INTEL_AGP_CACHED_MEMORY}
 };
 
 static struct _intel_i810_private {
@@ -117,13 +124,15 @@
 
 	current_size = A_SIZE_FIX(agp_bridge->current_size);
 
-	pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
-	temp &= 0xfff80000;
-
-	intel_i810_private.registers = ioremap(temp, 128 * 4096);
 	if (!intel_i810_private.registers) {
-		printk(KERN_ERR PFX "Unable to remap memory.\n");
-		return -ENOMEM;
+		pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
+		temp &= 0xfff80000;
+
+		intel_i810_private.registers = ioremap(temp, 128 * 4096);
+		if (!intel_i810_private.registers) {
+			printk(KERN_ERR PFX "Unable to remap memory.\n");
+			return -ENOMEM;
+		}
 	}
 
 	if ((readl(intel_i810_private.registers+I810_DRAM_CTL)
@@ -201,62 +210,79 @@
 	atomic_dec(&agp_bridge->current_memory_agp);
 }
 
+static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
+					int type)
+{
+	if (type < AGP_USER_TYPES)
+		return type;
+	else if (type == AGP_USER_CACHED_MEMORY)
+		return INTEL_AGP_CACHED_MEMORY;
+	else
+		return 0;
+}
+
 static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
 				int type)
 {
 	int i, j, num_entries;
 	void *temp;
+	int ret = -EINVAL;
+	int mask_type;
 
 	if (mem->page_count == 0)
-		return 0;
+		goto out;
 
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_FIX(temp)->num_entries;
 
 	if ((pg_start + mem->page_count) > num_entries)
-		return -EINVAL;
+		goto out_err;
+
 
 	for (j = pg_start; j < (pg_start + mem->page_count); j++) {
-		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
-			return -EBUSY;
-	}
-
-	if (type != 0 || mem->type != 0) {
-		if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
-			/* special insert */
-			if (!mem->is_flushed) {
-				global_cache_flush();
-				mem->is_flushed = TRUE;
-			}
-
-			for (i = pg_start; i < (pg_start + mem->page_count); i++) {
-				writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));
-			}
-			readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));	/* PCI Posting. */
-
-			agp_bridge->driver->tlb_flush(mem);
-			return 0;
+		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) {
+			ret = -EBUSY;
+			goto out_err;
 		}
-		if ((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
-			goto insert;
-		return -EINVAL;
 	}
 
-insert:
-	if (!mem->is_flushed) {
-		global_cache_flush();
-		mem->is_flushed = TRUE;
-	}
+	if (type != mem->type)
+		goto out_err;
 
-	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(agp_bridge->driver->mask_memory(agp_bridge,
-			mem->memory[i], mem->type),
-			intel_i810_private.registers+I810_PTE_BASE+(j*4));
+	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
+
+	switch (mask_type) {
+	case AGP_DCACHE_MEMORY:
+		if (!mem->is_flushed)
+			global_cache_flush();
+		for (i = pg_start; i < (pg_start + mem->page_count); i++) {
+			writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
+			       intel_i810_private.registers+I810_PTE_BASE+(i*4));
+		}
+		readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
+		break;
+	case AGP_PHYS_MEMORY:
+	case AGP_NORMAL_MEMORY:
+		if (!mem->is_flushed)
+			global_cache_flush();
+		for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
+			writel(agp_bridge->driver->mask_memory(agp_bridge,
+							       mem->memory[i],
+							       mask_type),
+			       intel_i810_private.registers+I810_PTE_BASE+(j*4));
+		}
+		readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));
+		break;
+	default:
+		goto out_err;
 	}
-	readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));	/* PCI Posting. */
 
 	agp_bridge->driver->tlb_flush(mem);
-	return 0;
+out:
+	ret = 0;
+out_err:
+	mem->is_flushed = 1;
+	return ret;
 }
 
 static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
@@ -337,12 +363,11 @@
 		new->type = AGP_DCACHE_MEMORY;
 		new->page_count = pg_count;
 		new->num_scratch_pages = 0;
-		vfree(new->memory);
+		agp_free_page_array(new);
 		return new;
 	}
 	if (type == AGP_PHYS_MEMORY)
 		return alloc_agpphysmem_i8xx(pg_count, type);
-
 	return NULL;
 }
 
@@ -357,7 +382,7 @@
 				 gart_to_virt(curr->memory[0]));
 			global_flush_tlb();
 		}
-		vfree(curr->memory);
+		agp_free_page_array(curr);
 	}
 	kfree(curr);
 }
@@ -619,9 +644,11 @@
 {
 	int i,j,num_entries;
 	void *temp;
+	int ret = -EINVAL;
+	int mask_type;
 
 	if (mem->page_count == 0)
-		return 0;
+		goto out;
 
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -631,34 +658,41 @@
 				pg_start,intel_i830_private.gtt_entries);
 
 		printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
-		return -EINVAL;
+		goto out_err;
 	}
 
 	if ((pg_start + mem->page_count) > num_entries)
-		return -EINVAL;
+		goto out_err;
 
 	/* The i830 can't check the GTT for entries since its read only,
 	 * depend on the caller to make the correct offset decisions.
 	 */
 
-	if ((type != 0 && type != AGP_PHYS_MEMORY) ||
-		(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
-		return -EINVAL;
+	if (type != mem->type)
+		goto out_err;
 
-	if (!mem->is_flushed) {
+	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
+
+	if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
+	    mask_type != INTEL_AGP_CACHED_MEMORY)
+		goto out_err;
+
+	if (!mem->is_flushed)
 		global_cache_flush();
-		mem->is_flushed = TRUE;
-	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
-			mem->memory[i], mem->type),
-			intel_i830_private.registers+I810_PTE_BASE+(j*4));
+						       mem->memory[i], mask_type),
+		       intel_i830_private.registers+I810_PTE_BASE+(j*4));
 	}
 	readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
-
 	agp_bridge->driver->tlb_flush(mem);
-	return 0;
+
+out:
+	ret = 0;
+out_err:
+	mem->is_flushed = 1;
+	return ret;
 }
 
 static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
@@ -687,7 +721,6 @@
 {
 	if (type == AGP_PHYS_MEMORY)
 		return alloc_agpphysmem_i8xx(pg_count, type);
-
 	/* always return NULL for other allocation types for now */
 	return NULL;
 }
@@ -734,9 +767,11 @@
 {
 	int i,j,num_entries;
 	void *temp;
+	int ret = -EINVAL;
+	int mask_type;
 
 	if (mem->page_count == 0)
-		return 0;
+		goto out;
 
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -746,33 +781,41 @@
 				pg_start,intel_i830_private.gtt_entries);
 
 		printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
-		return -EINVAL;
+		goto out_err;
 	}
 
 	if ((pg_start + mem->page_count) > num_entries)
-		return -EINVAL;
+		goto out_err;
 
-	/* The i830 can't check the GTT for entries since its read only,
+	/* The i915 can't check the GTT for entries since its read only,
 	 * depend on the caller to make the correct offset decisions.
 	 */
 
-	if ((type != 0 && type != AGP_PHYS_MEMORY) ||
-		(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
-		return -EINVAL;
+	if (type != mem->type)
+		goto out_err;
 
-	if (!mem->is_flushed) {
+	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
+
+	if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
+	    mask_type != INTEL_AGP_CACHED_MEMORY)
+		goto out_err;
+
+	if (!mem->is_flushed)
 		global_cache_flush();
-		mem->is_flushed = TRUE;
-	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
-			mem->memory[i], mem->type), intel_i830_private.gtt+j);
+			mem->memory[i], mask_type), intel_i830_private.gtt+j);
 	}
-	readl(intel_i830_private.gtt+j-1);
 
+	readl(intel_i830_private.gtt+j-1);
 	agp_bridge->driver->tlb_flush(mem);
-	return 0;
+
+ out:
+	ret = 0;
+ out_err:
+	mem->is_flushed = 1;
+	return ret;
 }
 
 static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
@@ -803,7 +846,7 @@
  */
 static int intel_i9xx_fetch_size(void)
 {
-	int num_sizes = sizeof(intel_i830_sizes) / sizeof(*intel_i830_sizes);
+	int num_sizes = ARRAY_SIZE(intel_i830_sizes);
 	int aper_size; /* size in megabytes */
 	int i;
 
@@ -1322,18 +1365,18 @@
 }
 
 /* Setup function */
-static struct gatt_mask intel_generic_masks[] =
+static const struct gatt_mask intel_generic_masks[] =
 {
 	{.mask = 0x00000017, .type = 0}
 };
 
-static struct aper_size_info_8 intel_815_sizes[2] =
+static const struct aper_size_info_8 intel_815_sizes[2] =
 {
 	{64, 16384, 4, 0},
 	{32, 8192, 3, 8},
 };
 
-static struct aper_size_info_8 intel_8xx_sizes[7] =
+static const struct aper_size_info_8 intel_8xx_sizes[7] =
 {
 	{256, 65536, 6, 0},
 	{128, 32768, 5, 32},
@@ -1344,7 +1387,7 @@
 	{4, 1024, 0, 63}
 };
 
-static struct aper_size_info_16 intel_generic_sizes[7] =
+static const struct aper_size_info_16 intel_generic_sizes[7] =
 {
 	{256, 65536, 6, 0},
 	{128, 32768, 5, 32},
@@ -1355,7 +1398,7 @@
 	{4, 1024, 0, 63}
 };
 
-static struct aper_size_info_8 intel_830mp_sizes[4] =
+static const struct aper_size_info_8 intel_830mp_sizes[4] =
 {
 	{256, 65536, 6, 0},
 	{128, 32768, 5, 32},
@@ -1363,7 +1406,7 @@
 	{32, 8192, 3, 56}
 };
 
-static struct agp_bridge_driver intel_generic_driver = {
+static const struct agp_bridge_driver intel_generic_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_generic_sizes,
 	.size_type		= U16_APER_SIZE,
@@ -1384,9 +1427,10 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_810_driver = {
+static const struct agp_bridge_driver intel_810_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_i810_sizes,
 	.size_type		= FIXED_APER_SIZE,
@@ -1408,9 +1452,10 @@
 	.free_by_type		= intel_i810_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_815_driver = {
+static const struct agp_bridge_driver intel_815_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_815_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -1431,9 +1476,10 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_830_driver = {
+static const struct agp_bridge_driver intel_830_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_i830_sizes,
 	.size_type		= FIXED_APER_SIZE,
@@ -1455,9 +1501,10 @@
 	.free_by_type		= intel_i810_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = intel_i830_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_820_driver = {
+static const struct agp_bridge_driver intel_820_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_8xx_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -1478,9 +1525,10 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_830mp_driver = {
+static const struct agp_bridge_driver intel_830mp_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_830mp_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -1501,9 +1549,10 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_840_driver = {
+static const struct agp_bridge_driver intel_840_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_8xx_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -1524,9 +1573,10 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_845_driver = {
+static const struct agp_bridge_driver intel_845_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_8xx_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -1547,9 +1597,10 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_850_driver = {
+static const struct agp_bridge_driver intel_850_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_8xx_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -1570,9 +1621,10 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_860_driver = {
+static const struct agp_bridge_driver intel_860_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_8xx_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -1593,9 +1645,10 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_915_driver = {
+static const struct agp_bridge_driver intel_915_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_i830_sizes,
 	.size_type		= FIXED_APER_SIZE,
@@ -1617,9 +1670,10 @@
 	.free_by_type		= intel_i810_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = intel_i830_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_i965_driver = {
+static const struct agp_bridge_driver intel_i965_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_i830_sizes,
        .size_type              = FIXED_APER_SIZE,
@@ -1641,9 +1695,10 @@
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_destroy_page       = agp_generic_destroy_page,
+       .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
 };
 
-static struct agp_bridge_driver intel_7505_driver = {
+static const struct agp_bridge_driver intel_7505_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_8xx_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -1664,6 +1719,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static int find_i810(u16 device)
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index df7f37b..0c9dab5 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -272,7 +272,7 @@
 }
 
 
-static struct aper_size_info_8 nvidia_generic_sizes[5] =
+static const struct aper_size_info_8 nvidia_generic_sizes[5] =
 {
 	{512, 131072, 7, 0},
 	{256, 65536, 6, 8},
@@ -283,13 +283,13 @@
 };
 
 
-static struct gatt_mask nvidia_generic_masks[] =
+static const struct gatt_mask nvidia_generic_masks[] =
 {
 	{ .mask = 1, .type = 0}
 };
 
 
-static struct agp_bridge_driver nvidia_driver = {
+static const struct agp_bridge_driver nvidia_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= nvidia_generic_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -310,6 +310,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index 17c50b0..36d07e36 100644
--- a/drivers/char/agp/parisc-agp.c
+++ b/drivers/char/agp/parisc-agp.c
@@ -210,7 +210,7 @@
 	agp_device_command(command, (mode & AGP8X_MODE) != 0);
 }
 
-struct agp_bridge_driver parisc_agp_driver = {
+struct const agp_bridge_driver parisc_agp_driver = {
 	.owner			= THIS_MODULE,
 	.size_type		= FIXED_APER_SIZE,
 	.configure		= parisc_agp_configure,
@@ -228,6 +228,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 	.cant_use_aperture	= 1,
 };
 
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 902648d..e12773a 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -247,7 +247,7 @@
 	return bridge;
 }
 
-struct agp_bridge_driver sgi_tioca_driver = {
+struct const agp_bridge_driver sgi_tioca_driver = {
 	.owner = THIS_MODULE,
 	.size_type = U16_APER_SIZE,
 	.configure = sgi_tioca_configure,
@@ -265,6 +265,7 @@
 	.free_by_type = agp_generic_free_by_type,
 	.agp_alloc_page = sgi_tioca_alloc_page,
 	.agp_destroy_page = agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 	.cant_use_aperture = 1,
 	.needs_scratch_page = 0,
 	.num_aperture_sizes = 1,
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index a00fd48..125f428 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -108,7 +108,7 @@
 	}
 }
 
-static struct aper_size_info_8 sis_generic_sizes[7] =
+static const struct aper_size_info_8 sis_generic_sizes[7] =
 {
 	{256, 65536, 6, 99},
 	{128, 32768, 5, 83},
@@ -140,6 +140,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 4f2d7d9..55212a3 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -385,12 +385,12 @@
 	return 0;
 }
 
-static struct gatt_mask serverworks_masks[] =
+static const struct gatt_mask serverworks_masks[] =
 {
 	{.mask = 1, .type = 0}
 };
 
-static struct aper_size_info_lvl2 serverworks_sizes[7] =
+static const struct aper_size_info_lvl2 serverworks_sizes[7] =
 {
 	{2048, 524288, 0x80000000},
 	{1024, 262144, 0xc0000000},
@@ -423,7 +423,7 @@
 	agp_device_command(command, 0);
 }
 
-static struct agp_bridge_driver sworks_driver = {
+static const struct agp_bridge_driver sworks_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= serverworks_sizes,
 	.size_type		= LVL2_APER_SIZE,
@@ -444,6 +444,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index dffc193..292b4ad 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -460,7 +460,7 @@
 
 /* Setup function */
 
-static struct aper_size_info_32 uninorth_sizes[7] =
+static const struct aper_size_info_32 uninorth_sizes[7] =
 {
 #if 0 /* Not sure uninorth supports that high aperture sizes */
 	{256, 65536, 6, 64},
@@ -477,7 +477,7 @@
  * Not sure that u3 supports that high aperture sizes but it
  * would strange if it did not :)
  */
-static struct aper_size_info_32 u3_sizes[8] =
+static const struct aper_size_info_32 u3_sizes[8] =
 {
 	{512, 131072, 7, 128},
 	{256, 65536, 6, 64},
@@ -489,7 +489,7 @@
 	{4, 1024, 0, 1}
 };
 
-struct agp_bridge_driver uninorth_agp_driver = {
+struct const agp_bridge_driver uninorth_agp_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= (void *)uninorth_sizes,
 	.size_type		= U32_APER_SIZE,
@@ -510,10 +510,11 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 	.cant_use_aperture	= 1,
 };
 
-struct agp_bridge_driver u3_agp_driver = {
+struct const agp_bridge_driver u3_agp_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= (void *)u3_sizes,
 	.size_type		= U32_APER_SIZE,
@@ -534,6 +535,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 	.cant_use_aperture	= 1,
 	.needs_scratch_page	= 1,
 };
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 2ded7a28..a2bb4ec 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -89,7 +89,7 @@
 }
 
 
-static struct aper_size_info_8 via_generic_sizes[9] =
+static const struct aper_size_info_8 via_generic_sizes[9] =
 {
 	{256, 65536, 6, 0},
 	{128, 32768, 5, 128},
@@ -170,7 +170,7 @@
 }
 
 
-static struct agp_bridge_driver via_agp3_driver = {
+static const struct agp_bridge_driver via_agp3_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= agp3_generic_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -191,9 +191,10 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_bridge_driver via_driver = {
+static const struct agp_bridge_driver via_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= via_generic_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -214,6 +215,7 @@
 	.free_by_type		= agp_generic_free_by_type,
 	.agp_alloc_page		= agp_generic_alloc_page,
 	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
 static struct agp_device_ids via_agp_device_ids[] __devinitdata =
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index feb4ac8..0e2b72f 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -527,10 +527,8 @@
 	if (!tty)
 		return;
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
 		tty_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
 }
 
 /*
@@ -904,8 +902,7 @@
 	if (!info->xmit.buf)
 		return 0;
 
-	local_save_flags(flags);
-	local_irq_disable();
+	local_irq_save(flags);
 	while (1) {
 		c = CIRC_SPACE_TO_END(info->xmit.head,
 				      info->xmit.tail,
@@ -968,7 +965,6 @@
 	local_irq_save(flags);
 	info->xmit.head = info->xmit.tail = 0;
 	local_irq_restore(flags);
-	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
 }
 
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
new file mode 100644
index 0000000..179c7a3
--- /dev/null
+++ b/drivers/char/apm-emulation.c
@@ -0,0 +1,672 @@
+/*
+ * bios-less APM driver for ARM Linux
+ *  Jamey Hicks <jamey@crl.dec.com>
+ *  adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * APM 1.2 Reference:
+ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
+ *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Microsoft at:
+ *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ */
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/apm_bios.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/apm-emulation.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+
+/*
+ * The apm_bios device is one of the misc char devices.
+ * This is its minor number.
+ */
+#define APM_MINOR_DEV	134
+
+/*
+ * See Documentation/Config.help for the configuration options.
+ *
+ * Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
+ *	apm=on/off			enable/disable APM
+ */
+
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS		16
+
+struct apm_queue {
+	unsigned int		event_head;
+	unsigned int		event_tail;
+	apm_event_t		events[APM_MAX_EVENTS];
+};
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+	struct list_head	list;
+
+	unsigned int		suser: 1;
+	unsigned int		writer: 1;
+	unsigned int		reader: 1;
+
+	int			suspend_result;
+	unsigned int		suspend_state;
+#define SUSPEND_NONE	0		/* no suspend pending */
+#define SUSPEND_PENDING	1		/* suspend pending read */
+#define SUSPEND_READ	2		/* suspend read, pending ack */
+#define SUSPEND_ACKED	3		/* suspend acked */
+#define SUSPEND_WAIT	4		/* waiting for suspend */
+#define SUSPEND_DONE	5		/* suspend completed */
+
+	struct apm_queue	queue;
+};
+
+/*
+ * Local variables
+ */
+static int suspends_pending;
+static int apm_disabled;
+static struct task_struct *kapmd_tsk;
+
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+
+/*
+ * This is a list of everyone who has opened /dev/apm_bios
+ */
+static DECLARE_RWSEM(user_list_lock);
+static LIST_HEAD(apm_user_list);
+
+/*
+ * kapmd info.  kapmd provides us a process context to handle
+ * "APM" events within - specifically necessary if we're going
+ * to be suspending the system.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
+static DEFINE_SPINLOCK(kapmd_queue_lock);
+static struct apm_queue kapmd_queue;
+
+static DEFINE_MUTEX(state_lock);
+
+static const char driver_version[] = "1.13";	/* no spaces */
+
+
+
+/*
+ * Compatibility cruft until the IPAQ people move over to the new
+ * interface.
+ */
+static void __apm_get_power_status(struct apm_power_info *info)
+{
+}
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
+EXPORT_SYMBOL(apm_get_power_status);
+
+
+/*
+ * APM event queue management.
+ */
+static inline int queue_empty(struct apm_queue *q)
+{
+	return q->event_head == q->event_tail;
+}
+
+static inline apm_event_t queue_get_event(struct apm_queue *q)
+{
+	q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+	return q->events[q->event_tail];
+}
+
+static void queue_add_event(struct apm_queue *q, apm_event_t event)
+{
+	q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
+	if (q->event_head == q->event_tail) {
+		static int notified;
+
+		if (notified++ == 0)
+		    printk(KERN_ERR "apm: an event queue overflowed\n");
+		q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+	}
+	q->events[q->event_head] = event;
+}
+
+static void queue_event(apm_event_t event)
+{
+	struct apm_user *as;
+
+	down_read(&user_list_lock);
+	list_for_each_entry(as, &apm_user_list, list) {
+		if (as->reader)
+			queue_add_event(&as->queue, event);
+	}
+	up_read(&user_list_lock);
+	wake_up_interruptible(&apm_waitqueue);
+}
+
+/*
+ * queue_suspend_event - queue an APM suspend event.
+ *
+ * Check that we're in a state where we can suspend.  If not,
+ * return -EBUSY.  Otherwise, queue an event to all "writer"
+ * users.  If there are no "writer" users, return '1' to
+ * indicate that we can immediately suspend.
+ */
+static int queue_suspend_event(apm_event_t event, struct apm_user *sender)
+{
+	struct apm_user *as;
+	int ret = 1;
+
+	mutex_lock(&state_lock);
+	down_read(&user_list_lock);
+
+	/*
+	 * If a thread is still processing, we can't suspend, so reject
+	 * the request.
+	 */
+	list_for_each_entry(as, &apm_user_list, list) {
+		if (as != sender && as->reader && as->writer && as->suser &&
+		    as->suspend_state != SUSPEND_NONE) {
+			ret = -EBUSY;
+			goto out;
+		}
+	}
+
+	list_for_each_entry(as, &apm_user_list, list) {
+		if (as != sender && as->reader && as->writer && as->suser) {
+			as->suspend_state = SUSPEND_PENDING;
+			suspends_pending++;
+			queue_add_event(&as->queue, event);
+			ret = 0;
+		}
+	}
+ out:
+	up_read(&user_list_lock);
+	mutex_unlock(&state_lock);
+	wake_up_interruptible(&apm_waitqueue);
+	return ret;
+}
+
+static void apm_suspend(void)
+{
+	struct apm_user *as;
+	int err = pm_suspend(PM_SUSPEND_MEM);
+
+	/*
+	 * Anyone on the APM queues will think we're still suspended.
+	 * Send a message so everyone knows we're now awake again.
+	 */
+	queue_event(APM_NORMAL_RESUME);
+
+	/*
+	 * Finally, wake up anyone who is sleeping on the suspend.
+	 */
+	mutex_lock(&state_lock);
+	down_read(&user_list_lock);
+	list_for_each_entry(as, &apm_user_list, list) {
+		if (as->suspend_state == SUSPEND_WAIT ||
+		    as->suspend_state == SUSPEND_ACKED) {
+			as->suspend_result = err;
+			as->suspend_state = SUSPEND_DONE;
+		}
+	}
+	up_read(&user_list_lock);
+	mutex_unlock(&state_lock);
+
+	wake_up(&apm_suspend_waitqueue);
+}
+
+static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
+{
+	struct apm_user *as = fp->private_data;
+	apm_event_t event;
+	int i = count, ret = 0;
+
+	if (count < sizeof(apm_event_t))
+		return -EINVAL;
+
+	if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
+		return -EAGAIN;
+
+	wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
+
+	while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
+		event = queue_get_event(&as->queue);
+
+		ret = -EFAULT;
+		if (copy_to_user(buf, &event, sizeof(event)))
+			break;
+
+		mutex_lock(&state_lock);
+		if (as->suspend_state == SUSPEND_PENDING &&
+		    (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND))
+			as->suspend_state = SUSPEND_READ;
+		mutex_unlock(&state_lock);
+
+		buf += sizeof(event);
+		i -= sizeof(event);
+	}
+
+	if (i < count)
+		ret = count - i;
+
+	return ret;
+}
+
+static unsigned int apm_poll(struct file *fp, poll_table * wait)
+{
+	struct apm_user *as = fp->private_data;
+
+	poll_wait(fp, &apm_waitqueue, wait);
+	return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
+}
+
+/*
+ * apm_ioctl - handle APM ioctl
+ *
+ * APM_IOC_SUSPEND
+ *   This IOCTL is overloaded, and performs two functions.  It is used to:
+ *     - initiate a suspend
+ *     - acknowledge a suspend read from /dev/apm_bios.
+ *   Only when everyone who has opened /dev/apm_bios with write permission
+ *   has acknowledge does the actual suspend happen.
+ */
+static int
+apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
+{
+	struct apm_user *as = filp->private_data;
+	unsigned long flags;
+	int err = -EINVAL;
+
+	if (!as->suser || !as->writer)
+		return -EPERM;
+
+	switch (cmd) {
+	case APM_IOC_SUSPEND:
+		mutex_lock(&state_lock);
+
+		as->suspend_result = -EINTR;
+
+		if (as->suspend_state == SUSPEND_READ) {
+			int pending;
+
+			/*
+			 * If we read a suspend command from /dev/apm_bios,
+			 * then the corresponding APM_IOC_SUSPEND ioctl is
+			 * interpreted as an acknowledge.
+			 */
+			as->suspend_state = SUSPEND_ACKED;
+			suspends_pending--;
+			pending = suspends_pending == 0;
+			mutex_unlock(&state_lock);
+
+			/*
+			 * If there are no further acknowledges required,
+			 * suspend the system.
+			 */
+			if (pending)
+				apm_suspend();
+
+			/*
+			 * Wait for the suspend/resume to complete.  If there
+			 * are pending acknowledges, we wait here for them.
+			 *
+			 * Note: we need to ensure that the PM subsystem does
+			 * not kick us out of the wait when it suspends the
+			 * threads.
+			 */
+			flags = current->flags;
+			current->flags |= PF_NOFREEZE;
+
+			wait_event(apm_suspend_waitqueue,
+				   as->suspend_state == SUSPEND_DONE);
+		} else {
+			as->suspend_state = SUSPEND_WAIT;
+			mutex_unlock(&state_lock);
+
+			/*
+			 * Otherwise it is a request to suspend the system.
+			 * Queue an event for all readers, and expect an
+			 * acknowledge from all writers who haven't already
+			 * acknowledged.
+			 */
+			err = queue_suspend_event(APM_USER_SUSPEND, as);
+			if (err < 0) {
+				/*
+				 * Avoid taking the lock here - this
+				 * should be fine.
+				 */
+				as->suspend_state = SUSPEND_NONE;
+				break;
+			}
+
+			if (err > 0)
+				apm_suspend();
+
+			/*
+			 * Wait for the suspend/resume to complete.  If there
+			 * are pending acknowledges, we wait here for them.
+			 *
+			 * Note: we need to ensure that the PM subsystem does
+			 * not kick us out of the wait when it suspends the
+			 * threads.
+			 */
+			flags = current->flags;
+			current->flags |= PF_NOFREEZE;
+
+			wait_event_interruptible(apm_suspend_waitqueue,
+					 as->suspend_state == SUSPEND_DONE);
+		}
+
+		current->flags = flags;
+
+		mutex_lock(&state_lock);
+		err = as->suspend_result;
+		as->suspend_state = SUSPEND_NONE;
+		mutex_unlock(&state_lock);
+		break;
+	}
+
+	return err;
+}
+
+static int apm_release(struct inode * inode, struct file * filp)
+{
+	struct apm_user *as = filp->private_data;
+	int pending = 0;
+
+	filp->private_data = NULL;
+
+	down_write(&user_list_lock);
+	list_del(&as->list);
+	up_write(&user_list_lock);
+
+	/*
+	 * We are now unhooked from the chain.  As far as new
+	 * events are concerned, we no longer exist.  However, we
+	 * need to balance suspends_pending, which means the
+	 * possibility of sleeping.
+	 */
+	mutex_lock(&state_lock);
+	if (as->suspend_state != SUSPEND_NONE) {
+		suspends_pending -= 1;
+		pending = suspends_pending == 0;
+	}
+	mutex_unlock(&state_lock);
+	if (pending)
+		apm_suspend();
+
+	kfree(as);
+	return 0;
+}
+
+static int apm_open(struct inode * inode, struct file * filp)
+{
+	struct apm_user *as;
+
+	as = kzalloc(sizeof(*as), GFP_KERNEL);
+	if (as) {
+		/*
+		 * XXX - this is a tiny bit broken, when we consider BSD
+		 * process accounting. If the device is opened by root, we
+		 * instantly flag that we used superuser privs. Who knows,
+		 * we might close the device immediately without doing a
+		 * privileged operation -- cevans
+		 */
+		as->suser = capable(CAP_SYS_ADMIN);
+		as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
+		as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+
+		down_write(&user_list_lock);
+		list_add(&as->list, &apm_user_list);
+		up_write(&user_list_lock);
+
+		filp->private_data = as;
+	}
+
+	return as ? 0 : -ENOMEM;
+}
+
+static struct file_operations apm_bios_fops = {
+	.owner		= THIS_MODULE,
+	.read		= apm_read,
+	.poll		= apm_poll,
+	.ioctl		= apm_ioctl,
+	.open		= apm_open,
+	.release	= apm_release,
+};
+
+static struct miscdevice apm_device = {
+	.minor		= APM_MINOR_DEV,
+	.name		= "apm_bios",
+	.fops		= &apm_bios_fops
+};
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Arguments, with symbols from linux/apm_bios.h.
+ *
+ *   0) Linux driver version (this will change if format changes)
+ *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
+ *   2) APM flags from APM Installation Check (0x00):
+ *	bit 0: APM_16_BIT_SUPPORT
+ *	bit 1: APM_32_BIT_SUPPORT
+ *	bit 2: APM_IDLE_SLOWS_CLOCK
+ *	bit 3: APM_BIOS_DISABLED
+ *	bit 4: APM_BIOS_DISENGAGED
+ *   3) AC line status
+ *	0x00: Off-line
+ *	0x01: On-line
+ *	0x02: On backup power (BIOS >= 1.1 only)
+ *	0xff: Unknown
+ *   4) Battery status
+ *	0x00: High
+ *	0x01: Low
+ *	0x02: Critical
+ *	0x03: Charging
+ *	0x04: Selected battery not present (BIOS >= 1.2 only)
+ *	0xff: Unknown
+ *   5) Battery flag
+ *	bit 0: High
+ *	bit 1: Low
+ *	bit 2: Critical
+ *	bit 3: Charging
+ *	bit 7: No system battery
+ *	0xff: Unknown
+ *   6) Remaining battery life (percentage of charge):
+ *	0-100: valid
+ *	-1: Unknown
+ *   7) Remaining battery life (time units):
+ *	Number of remaining minutes or seconds
+ *	-1: Unknown
+ *   8) min = minutes; sec = seconds
+ */
+static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+{
+	struct apm_power_info info;
+	char *units;
+	int ret;
+
+	info.ac_line_status = 0xff;
+	info.battery_status = 0xff;
+	info.battery_flag   = 0xff;
+	info.battery_life   = -1;
+	info.time	    = -1;
+	info.units	    = -1;
+
+	if (apm_get_power_status)
+		apm_get_power_status(&info);
+
+	switch (info.units) {
+	default:	units = "?";	break;
+	case 0: 	units = "min";	break;
+	case 1: 	units = "sec";	break;
+	}
+
+	ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+		     driver_version, APM_32_BIT_SUPPORT,
+		     info.ac_line_status, info.battery_status,
+		     info.battery_flag, info.battery_life,
+		     info.time, units);
+
+	return ret;
+}
+#endif
+
+static int kapmd(void *arg)
+{
+	do {
+		apm_event_t event;
+		int ret;
+
+		wait_event_interruptible(kapmd_wait,
+				!queue_empty(&kapmd_queue) || kthread_should_stop());
+
+		if (kthread_should_stop())
+			break;
+
+		spin_lock_irq(&kapmd_queue_lock);
+		event = 0;
+		if (!queue_empty(&kapmd_queue))
+			event = queue_get_event(&kapmd_queue);
+		spin_unlock_irq(&kapmd_queue_lock);
+
+		switch (event) {
+		case 0:
+			break;
+
+		case APM_LOW_BATTERY:
+		case APM_POWER_STATUS_CHANGE:
+			queue_event(event);
+			break;
+
+		case APM_USER_SUSPEND:
+		case APM_SYS_SUSPEND:
+			ret = queue_suspend_event(event, NULL);
+			if (ret < 0) {
+				/*
+				 * We were busy.  Try again in 50ms.
+				 */
+				queue_add_event(&kapmd_queue, event);
+				msleep(50);
+			}
+			if (ret > 0)
+				apm_suspend();
+			break;
+
+		case APM_CRITICAL_SUSPEND:
+			apm_suspend();
+			break;
+		}
+	} while (1);
+
+	return 0;
+}
+
+static int __init apm_init(void)
+{
+	int ret;
+
+	if (apm_disabled) {
+		printk(KERN_NOTICE "apm: disabled on user request.\n");
+		return -ENODEV;
+	}
+
+	kapmd_tsk = kthread_create(kapmd, NULL, "kapmd");
+	if (IS_ERR(kapmd_tsk)) {
+		ret = PTR_ERR(kapmd_tsk);
+		kapmd_tsk = NULL;
+		return ret;
+	}
+	kapmd_tsk->flags |= PF_NOFREEZE;
+	wake_up_process(kapmd_tsk);
+
+#ifdef CONFIG_PROC_FS
+	create_proc_info_entry("apm", 0, NULL, apm_get_info);
+#endif
+
+	ret = misc_register(&apm_device);
+	if (ret != 0) {
+		remove_proc_entry("apm", NULL);
+		kthread_stop(kapmd_tsk);
+	}
+
+	return ret;
+}
+
+static void __exit apm_exit(void)
+{
+	misc_deregister(&apm_device);
+	remove_proc_entry("apm", NULL);
+
+	kthread_stop(kapmd_tsk);
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_LICENSE("GPL");
+
+#ifndef MODULE
+static int __init apm_setup(char *str)
+{
+	while ((str != NULL) && (*str != '\0')) {
+		if (strncmp(str, "off", 3) == 0)
+			apm_disabled = 1;
+		if (strncmp(str, "on", 2) == 0)
+			apm_disabled = 0;
+		str = strchr(str, ',');
+		if (str != NULL)
+			str += strspn(str, ", \t");
+	}
+	return 1;
+}
+
+__setup("apm=", apm_setup);
+#endif
+
+/**
+ * apm_queue_event - queue an APM event for kapmd
+ * @event: APM event
+ *
+ * Queue an APM event for kapmd to process and ultimately take the
+ * appropriate action.  Only a subset of events are handled:
+ *   %APM_LOW_BATTERY
+ *   %APM_POWER_STATUS_CHANGE
+ *   %APM_USER_SUSPEND
+ *   %APM_SYS_SUSPEND
+ *   %APM_CRITICAL_SUSPEND
+ */
+void apm_queue_event(apm_event_t event)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kapmd_queue_lock, flags);
+	queue_add_event(&kapmd_queue, event);
+	spin_unlock_irqrestore(&kapmd_queue_lock, flags);
+
+	wake_up_interruptible(&kapmd_wait);
+}
+EXPORT_SYMBOL(apm_queue_event);
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index 9f8082f..8dcf9d2 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -8,7 +8,6 @@
 
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/timer.h>
 #include <linux/kernel.h>
@@ -187,7 +186,7 @@
 	return len;
 }
 
-static struct file_operations briq_panel_fops = {
+static const struct file_operations briq_panel_fops = {
 	.owner		= THIS_MODULE,
 	.read		= briq_panel_read,
 	.write		= briq_panel_write,
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 3ffa080..54df355 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -829,17 +829,18 @@
 static unsigned short cy_isa_nboard;
 static unsigned short cy_nboard;
 #ifdef CONFIG_PCI
-static unsigned short cy_pci_dev_id[] = {
-	PCI_DEVICE_ID_CYCLOM_Y_Lo,	/* PCI < 1Mb */
-	PCI_DEVICE_ID_CYCLOM_Y_Hi,	/* PCI > 1Mb */
-	PCI_DEVICE_ID_CYCLOM_4Y_Lo,	/* 4Y PCI < 1Mb */
-	PCI_DEVICE_ID_CYCLOM_4Y_Hi,	/* 4Y PCI > 1Mb */
-	PCI_DEVICE_ID_CYCLOM_8Y_Lo,	/* 8Y PCI < 1Mb */
-	PCI_DEVICE_ID_CYCLOM_8Y_Hi,	/* 8Y PCI > 1Mb */
-	PCI_DEVICE_ID_CYCLOM_Z_Lo,	/* Z PCI < 1Mb */
-	PCI_DEVICE_ID_CYCLOM_Z_Hi,	/* Z PCI > 1Mb */
-	0			/* end of table */
+static struct pci_device_id cy_pci_dev_id[] __devinitdata = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },	/* PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },	/* PCI > 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },	/* 4Y PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },	/* 4Y PCI > 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },	/* 8Y PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },	/* 8Y PCI > 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },	/* Z PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },	/* Z PCI > 1Mb */
+	{ }			/* end of table */
 };
+MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
 #endif
 
 static void cy_start(struct tty_struct *);
@@ -4488,7 +4489,6 @@
 		CY_UNLOCK(info, flags);
 	}
 	tty_wakeup(tty);
-	wake_up_interruptible(&tty->write_wait);
 }				/* cy_flush_buffer */
 
 /*
@@ -4759,7 +4759,7 @@
 
 	for (i = 0; i < NR_CARDS; i++) {
 		/* look for a Cyclades card by vendor and device id */
-		while ((device_id = cy_pci_dev_id[dev_index]) != 0) {
+		while ((device_id = cy_pci_dev_id[dev_index].device) != 0) {
 			if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES,
 						   device_id, pdev)) == NULL) {
 				dev_index++;	/* try next device id */
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index a70af0d..f5b9b24 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -371,7 +371,7 @@
 EXPORT_SYMBOL(drm_exit);
 
 /** File operations structure */
-static struct file_operations drm_stub_fops = {
+static const struct file_operations drm_stub_fops = {
 	.owner = THIS_MODULE,
 	.open = drm_stub_open
 };
diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c
index 1383727..ac9ab40 100644
--- a/drivers/char/drm/ffb_context.c
+++ b/drivers/char/drm/ffb_context.c
@@ -7,7 +7,6 @@
  * for authors.
  */
 
-#include <linux/sched.h>
 #include <asm/upa.h>
 
 #include "ffb.h"
diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
index dd45111..9a19879 100644
--- a/drivers/char/drm/ffb_drv.c
+++ b/drivers/char/drm/ffb_drv.c
@@ -9,7 +9,6 @@
 
 #include "ffb_drv.h"
 
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <asm/shmparam.h>
 #include <asm/oplib.h>
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 60cb4e4..603d17f 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -112,7 +112,7 @@
 	return 0;
 }
 
-static struct file_operations i810_buffer_fops = {
+static const struct file_operations i810_buffer_fops = {
 	.open = drm_open,
 	.release = drm_release,
 	.ioctl = drm_ioctl,
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 9522445..3314a9f 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -114,7 +114,7 @@
 	return 0;
 }
 
-static struct file_operations i830_buffer_fops = {
+static const struct file_operations i830_buffer_fops = {
 	.open = drm_open,
 	.release = drm_release,
 	.ioctl = drm_ioctl,
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
index 2054d57..2881a06 100644
--- a/drivers/char/drm/via_dmablit.c
+++ b/drivers/char/drm/via_dmablit.c
@@ -376,10 +376,8 @@
 			blitq->cur = cur;
 			blitq->num_outstanding--;
 			blitq->end = jiffies + DRM_HZ;
-			if (!timer_pending(&blitq->poll_timer)) {
-				blitq->poll_timer.expires = jiffies+1;
-				add_timer(&blitq->poll_timer);
-			}
+			if (!timer_pending(&blitq->poll_timer))
+				mod_timer(&blitq->poll_timer, jiffies + 1);
 		} else {
 			if (timer_pending(&blitq->poll_timer)) {
 				del_timer(&blitq->poll_timer);
@@ -478,8 +476,7 @@
 	via_dmablit_handler(dev, engine, 0);
 	
 	if (!timer_pending(&blitq->poll_timer)) {
-		blitq->poll_timer.expires = jiffies+1;
-		add_timer(&blitq->poll_timer);
+		mod_timer(&blitq->poll_timer, jiffies + 1);
 
 	       /*
 		* Rerun handler to delete timer if engines are off, and
@@ -574,9 +571,8 @@
 		}
 		DRM_INIT_WAITQUEUE(&blitq->busy_queue);
 		INIT_WORK(&blitq->wq, via_dmablit_workqueue);
-		init_timer(&blitq->poll_timer);
-		blitq->poll_timer.function = &via_dmablit_timer;
-		blitq->poll_timer.data = (unsigned long) blitq;
+		setup_timer(&blitq->poll_timer, via_dmablit_timer,
+				(unsigned long)blitq);
 	}	
 }
 
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c
index bcdb107..fada6dd 100644
--- a/drivers/char/ds1302.c
+++ b/drivers/char/ds1302.c
@@ -120,7 +120,6 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	local_irq_disable();
 
 	rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
 	rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
@@ -219,7 +218,6 @@
 			BIN_TO_BCD(yrs);
 
 			local_irq_save(flags);
-			local_irq_disable();
 			CMOS_WRITE(yrs, RTC_YEAR);
 			CMOS_WRITE(mon, RTC_MONTH);
 			CMOS_WRITE(day, RTC_DAY_OF_MONTH);
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index 48cb8f0..3d7efc2 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -3,7 +3,6 @@
  *   thermometer driver (as used in the Rebel.com NetWinder)
  */
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/miscdevice.h>
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 06f2dbf..db984e4 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -25,7 +25,6 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>	/* for kmalloc() and kfree() */
-#include <linux/sched.h>	/* for struct wait_queue etc */
 #include <linux/major.h>
 #include <linux/types.h>
 #include <linux/errno.h>
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index d4005e9..d8dbdb9 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -72,6 +72,7 @@
 #define TRACE_RET ((void) 0)
 #endif				/* TRACING */
 
+static void dtlk_timer_tick(unsigned long data);
 
 static int dtlk_major;
 static int dtlk_port_lpc;
@@ -81,7 +82,7 @@
 static unsigned int dtlk_portlist[] =
 {0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0};
 static wait_queue_head_t dtlk_process_list;
-static struct timer_list dtlk_timer;
+static DEFINE_TIMER(dtlk_timer, dtlk_timer_tick, 0, 0);
 
 /* prototypes for file_operations struct */
 static ssize_t dtlk_read(struct file *, char __user *,
@@ -117,7 +118,6 @@
 /*
    static void dtlk_handle_error(char, char, unsigned int);
  */
-static void dtlk_timer_tick(unsigned long data);
 
 static ssize_t dtlk_read(struct file *file, char __user *buf,
 			 size_t count, loff_t * ppos)
@@ -318,7 +318,7 @@
 	}
 	TRACE_RET;
 	
-	del_timer(&dtlk_timer);
+	del_timer_sync(&dtlk_timer);
 
 	return 0;
 }
@@ -336,8 +336,6 @@
 	if (dtlk_dev_probe() == 0)
 		printk(", MAJOR %d\n", dtlk_major);
 
-	init_timer(&dtlk_timer);
-	dtlk_timer.function = dtlk_timer_tick;
 	init_waitqueue_head(&dtlk_process_list);
 
 	return 0;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index a0f822c..88fc24f 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -844,7 +844,6 @@
 	fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
 	memoff(ch);
 	spin_unlock_irqrestore(&epca_lock, flags);
-	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
 } /* End pc_flush_buffer */
 
@@ -1795,7 +1794,6 @@
 				{ /* Begin if LOWWAIT */
 					ch->statusflags &= ~LOWWAIT;
 					tty_wakeup(tty);
-					wake_up_interruptible(&tty->write_wait);
 				} /* End if LOWWAIT */
 			} else if (event & EMPTYTX_IND)  { /* Begin EMPTYTX_IND */
 				/* This event is generated by setup_empty_event */
@@ -1803,7 +1801,6 @@
 				if (ch->statusflags & EMPTYWAIT)  { /* Begin if EMPTYWAIT */
 					ch->statusflags &= ~EMPTYWAIT;
 					tty_wakeup(tty);
-					wake_up_interruptible(&tty->write_wait);
 				} /* End if EMPTYWAIT */
 			} /* End EMPTYTX_IND */
 		} /* End if valid tty */
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 43ff598..2398e86 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -117,7 +117,7 @@
 	return 0;
 }
 
-struct file_operations nvram_fops = {
+const struct file_operations nvram_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= nvram_llseek,
 	.read		= read_nvram,
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index e769811..337bbcd 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -382,7 +382,6 @@
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 	spin_unlock_irqrestore (&port->driver_lock, flags);
 
-	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
 	func_exit ();
 }
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index 1aa93a7..ae76a9f 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -117,7 +117,7 @@
 __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
 #endif /* not MODULE */
 
-#if defined(CONFIG_X86_64) || defined(CONFIG_S390)
+#if defined(CONFIG_S390)
 # define HAVE_MONOTONIC
 # define TIMER_FREQ 1000000000ULL
 #elif defined(CONFIG_IA64)
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 20dc3be..0be700f 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -703,7 +703,7 @@
 
 static ctl_table hpet_table[] = {
 	{
-	 .ctl_name = 1,
+	 .ctl_name = CTL_UNNUMBERED,
 	 .procname = "max-user-freq",
 	 .data = &hpet_max_freq,
 	 .maxlen = sizeof(int),
@@ -715,7 +715,7 @@
 
 static ctl_table hpet_root[] = {
 	{
-	 .ctl_name = 1,
+	 .ctl_name = CTL_UNNUMBERED,
 	 .procname = "hpet",
 	 .maxlen = 0,
 	 .mode = 0555,
@@ -1018,7 +1018,7 @@
 	if (result < 0)
 		return -ENODEV;
 
-	sysctl_header = register_sysctl_table(dev_root, 0);
+	sysctl_header = register_sysctl_table(dev_root);
 
 	result = acpi_bus_register_driver(&hpet_acpi_driver);
 	if (result < 0) {
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index d780683..50315d6 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -39,7 +39,6 @@
 #include <linux/module.h>
 #include <linux/major.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/sysrq.h>
 #include <linux/tty.h>
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index f22e78e..cc1046e 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -96,49 +96,49 @@
  */
 static const struct pci_device_id pci_tbl[] = {
 /* AA
-	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
-	{ 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */
+	{ PCI_DEVICE(0x8086, 0x2418) }, */
+	{ PCI_DEVICE(0x8086, 0x2410) }, /* AA */
 /* AB
-	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
-	{ 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */
+	{ PCI_DEVICE(0x8086, 0x2428) }, */
+	{ PCI_DEVICE(0x8086, 0x2420) }, /* AB */
 /* ??
-	{ 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+	{ PCI_DEVICE(0x8086, 0x2430) }, */
 /* BAM, CAM, DBM, FBM, GxM
-	{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
-	{ 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */
-	{ 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */
-	{ 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */
-	{ 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */
-	{ 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */
-	{ 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */
+	{ PCI_DEVICE(0x8086, 0x2448) }, */
+	{ PCI_DEVICE(0x8086, 0x244c) }, /* BAM */
+	{ PCI_DEVICE(0x8086, 0x248c) }, /* CAM */
+	{ PCI_DEVICE(0x8086, 0x24cc) }, /* DBM */
+	{ PCI_DEVICE(0x8086, 0x2641) }, /* FBM */
+	{ PCI_DEVICE(0x8086, 0x27b9) }, /* GxM */
+	{ PCI_DEVICE(0x8086, 0x27bd) }, /* GxM DH */
 /* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx
-	{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
-	{ 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */
-	{ 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */
-	{ 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */
-	{ 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */
-	{ 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */
-	{ 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */
-	{ 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */
+	{ PCI_DEVICE(0x8086, 0x244e) }, */
+	{ PCI_DEVICE(0x8086, 0x2440) }, /* BA */
+	{ PCI_DEVICE(0x8086, 0x2480) }, /* CA */
+	{ PCI_DEVICE(0x8086, 0x24c0) }, /* DB */
+	{ PCI_DEVICE(0x8086, 0x24d0) }, /* Ex */
+	{ PCI_DEVICE(0x8086, 0x25a1) }, /* 6300 */
+	{ PCI_DEVICE(0x8086, 0x2640) }, /* Fx */
+	{ PCI_DEVICE(0x8086, 0x2670) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2671) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2672) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2673) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2674) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2675) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2676) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2677) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2678) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2679) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267a) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267b) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267c) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267d) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267e) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267f) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x27b8) }, /* Gx */
 /* E
-	{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
-	{ 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E  */
+	{ PCI_DEVICE(0x8086, 0x245e) }, */
+	{ PCI_DEVICE(0x8086, 0x2450) }, /* E  */
 	{ 0, },	/* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, pci_tbl);
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index 7804576..e46120d 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -150,6 +150,13 @@
 			  == (CHANNEL_MAGIC | CHANNEL_SUPPORT));
 }
 
+static void iiSendPendingMail_t(unsigned long data)
+{
+	i2eBordStrPtr pB = (i2eBordStrPtr)data;
+
+	iiSendPendingMail(pB);
+}
+
 //******************************************************************************
 // Function:   iiSendPendingMail(pB)
 // Parameters: Pointer to a board structure
@@ -159,7 +166,7 @@
 // If any outgoing mail bits are set and there is outgoing mailbox is empty,
 // send the mail and clear the bits.
 //******************************************************************************
-static inline void
+static void
 iiSendPendingMail(i2eBordStrPtr pB)
 {
 	if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) )
@@ -184,12 +191,9 @@
 			/\/\|=mhw=|\/\/				*/
 
 			if( ++pB->SendPendingRetry < 16 ) {
-
-				init_timer( &(pB->SendPendingTimer) );
-				pB->SendPendingTimer.expires  = jiffies + 1;
-				pB->SendPendingTimer.function = (void*)(unsigned long)iiSendPendingMail;
-				pB->SendPendingTimer.data     = (unsigned long)pB;
-				add_timer( &(pB->SendPendingTimer) );
+				setup_timer(&pB->SendPendingTimer,
+					iiSendPendingMail_t, (unsigned long)pB);
+				mod_timer(&pB->SendPendingTimer, jiffies + 1);
 			} else {
 				printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" );
 			}
@@ -1265,8 +1269,10 @@
 // soon as all the data is completely sent.
 //******************************************************************************
 static void
-i2DrainWakeup(i2ChanStrPtr pCh)
+i2DrainWakeup(unsigned long d)
 {
+	i2ChanStrPtr pCh = (i2ChanStrPtr)d;
+
 	ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires );
 
 	pCh->BookmarkTimer.expires = 0;
@@ -1292,14 +1298,12 @@
 	}
 	if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) {
 		// One per customer (channel)
-		init_timer( &(pCh->BookmarkTimer) );
-		pCh->BookmarkTimer.expires  = jiffies + timeout;
-		pCh->BookmarkTimer.function = (void*)(unsigned long)i2DrainWakeup;
-		pCh->BookmarkTimer.data     = (unsigned long)pCh;
+		setup_timer(&pCh->BookmarkTimer, i2DrainWakeup,
+				(unsigned long)pCh);
 
 		ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires );
 
-		add_timer( &(pCh->BookmarkTimer) );
+		mod_timer(&pCh->BookmarkTimer, jiffies + timeout);
 	}
 	
 	i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ );
@@ -1373,15 +1377,7 @@
 	ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags,
 			(1 << TTY_DO_WRITE_WAKEUP) );
 
-	wake_up_interruptible ( &tp->write_wait );
-	if ( ( tp->flags & (1 << TTY_DO_WRITE_WAKEUP) ) 
-	  && tp->ldisc.write_wakeup )
-	{
-		(tp->ldisc.write_wakeup) ( tp );
-
-		ip2trace (CHANN, ITRC_SICMD, 11, 0 );
-
-	}
+	tty_wakeup(tp);
 }
 
 static inline void
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 7c70310..83c7258 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -1271,8 +1271,8 @@
 // code duplicated from n_tty (ldisc)
 static inline void  isig(int sig, struct tty_struct *tty, int flush)
 {
-	if (tty->pgrp > 0)
-		kill_pg(tty->pgrp, sig, 1);
+	if (tty->pgrp)
+		kill_pgrp(tty->pgrp, sig, 1);
 	if (flush || !L_NOFLSH(tty)) {
 		if ( tty->ldisc.flush_buffer )  
 			tty->ldisc.flush_buffer(tty);
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index ff2d052..c2aa44e 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -35,7 +35,6 @@
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
 #include <asm/system.h>
-#include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 53582b5..8e222f2 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <asm/system.h>
-#include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
@@ -406,13 +405,14 @@
 	free_smi_msg_list(&intf->waiting_msgs);
 	free_recv_msg_list(&intf->waiting_events);
 
-	/* Wholesale remove all the entries from the list in the
-	 * interface and wait for RCU to know that none are in use. */
+	/*
+	 * Wholesale remove all the entries from the list in the
+	 * interface and wait for RCU to know that none are in use.
+	 */
 	mutex_lock(&intf->cmd_rcvrs_mutex);
-	list_add_rcu(&list, &intf->cmd_rcvrs);
-	list_del_rcu(&intf->cmd_rcvrs);
+	INIT_LIST_HEAD(&list);
+	list_splice_init_rcu(&intf->cmd_rcvrs, &list, synchronize_rcu);
 	mutex_unlock(&intf->cmd_rcvrs_mutex);
-	synchronize_rcu();
 
 	list_for_each_entry_safe(rcvr, rcvr2, &list, link)
 		kfree(rcvr);
@@ -451,7 +451,7 @@
 	mutex_lock(&ipmi_interfaces_mutex);
 
 	/* Build a list of things to deliver. */
-	list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+	list_for_each_entry(intf, &ipmi_interfaces, link) {
 		if (intf->intf_num == -1)
 			continue;
 		e = kmalloc(sizeof(*e), GFP_KERNEL);
@@ -1886,7 +1886,6 @@
 		kfree(entry);
 		rv = -ENOMEM;
 	} else {
-		file->nlink = 1;
 		file->data = data;
 		file->read_proc = read_proc;
 		file->write_proc = write_proc;
@@ -2760,9 +2759,15 @@
 		synchronize_rcu();
 		kref_put(&intf->refcount, intf_free);
 	} else {
-		/* After this point the interface is legal to use. */
+		/*
+		 * Keep memory order straight for RCU readers.  Make
+		 * sure everything else is committed to memory before
+		 * setting intf_num to mark the interface valid.
+		 */
+		smp_wmb();
 		intf->intf_num = i;
 		mutex_unlock(&ipmi_interfaces_mutex);
+		/* After this point the interface is legal to use. */
 		call_smi_watchers(i, intf->si_dev);
 		mutex_unlock(&smi_watchers_mutex);
 	}
@@ -3923,6 +3928,14 @@
 			/* Interface was not ready yet. */
 			continue;
 
+		/*
+		 * intf_num is used as an marker to tell if the
+		 * interface is valid.  Thus we need a read barrier to
+		 * make sure data fetched before checking intf_num
+		 * won't be used.
+		 */
+		smp_rmb();
+
 		/* First job here is to figure out where to send the
 		   OEM events.  There's no way in IPMI to send OEM
 		   events using an event send command, so we have to
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index 9d23136..e02893b 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -686,7 +686,7 @@
 		printk(KERN_INFO PFX "Power cycle is enabled.\n");
 
 #ifdef CONFIG_PROC_FS
-	ipmi_table_header = register_sysctl_table(ipmi_root_table, 1);
+	ipmi_table_header = register_sysctl_table(ipmi_root_table);
 	if (!ipmi_table_header) {
 		printk(KERN_ERR PFX "Unable to register powercycle sysctl\n");
 		rv = -ENOMEM;
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 01084ab..43ab9ed 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -183,7 +183,7 @@
 /*   baud index mappings from linux defns to isi */
 
 static signed char linuxb_to_isib[] = {
-	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19
+	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21
 };
 
 struct	isi_board {
@@ -213,8 +213,6 @@
 	struct tty_struct 	* tty;
 	wait_queue_head_t	close_wait;
 	wait_queue_head_t	open_wait;
-	struct work_struct	hangup_tq;
-	struct work_struct	bh_tqueue;
 	unsigned char		* xmit_buf;
 	int			xmit_head;
 	int			xmit_tail;
@@ -510,7 +508,7 @@
 		if (port->xmit_cnt <= 0)
 			port->status &= ~ISI_TXOK;
 		if (port->xmit_cnt <= WAKEUP_CHARS)
-			schedule_work(&port->bh_tqueue);
+			tty_wakeup(tty);
 		unlock_card(&isi_card[card]);
 	}
 
@@ -524,21 +522,6 @@
 	mod_timer(&tx, jiffies + msecs_to_jiffies(10));
 }
 
-/* 	Interrupt handlers 	*/
-
-
-static void isicom_bottomhalf(struct work_struct *work)
-{
-	struct isi_port *port = container_of(work, struct isi_port, bh_tqueue);
-	struct tty_struct *tty = port->tty;
-
-	if (!tty)
-		return;
-
-	tty_wakeup(tty);
-	wake_up_interruptible(&tty->write_wait);
-}
-
 /*
  *	Main interrupt handler routine
  */
@@ -557,6 +540,11 @@
 		return IRQ_NONE;
 
 	base = card->base;
+
+	/* did the card interrupt us? */
+	if (!(inw(base + 0x0e) & 0x02))
+		return IRQ_NONE;
+
 	spin_lock(&card->card_lock);
 
 	/*
@@ -581,6 +569,7 @@
 	port = card->ports + channel;
 	if (!(port->flags & ASYNC_INITIALIZED)) {
 		outw(0x0000, base+0x04); /* enable interrupts */
+		spin_unlock(&card->card_lock);
 		return IRQ_HANDLED;
 	}
 
@@ -609,7 +598,7 @@
 						pr_dbg("interrupt: DCD->low.\n"
 							);
 						port->status &= ~ISI_DCD;
-						schedule_work(&port->hangup_tq);
+						tty_hangup(tty);
 					}
 				} else if (header & ISI_DCD) {
 				/* Carrier has been detected */
@@ -631,7 +620,7 @@
 						/* start tx ing */
 						port->status |= (ISI_TXOK
 							| ISI_CTS);
-						schedule_work(&port->bh_tqueue);
+						tty_wakeup(tty);
 					}
 				} else if (!(header & ISI_CTS)) {
 					port->tty->hw_stopped = 1;
@@ -695,6 +684,7 @@
 		tty_flip_buffer_push(tty);
 	}
 	outw(0x0000, base+0x04); /* enable interrupts */
+	spin_unlock(&card->card_lock);
 
 	return IRQ_HANDLED;
 }
@@ -720,7 +710,8 @@
 		 *  respectively.
 		 */
 
-		if (baud < 1 || baud > 2)
+		/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
+		if (baud < 1 || baud > 4)
 			port->tty->termios->c_cflag &= ~CBAUDEX;
 		else
 			baud += 15;
@@ -736,6 +727,10 @@
 			baud++; /*  57.6 Kbps */
 		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
 			baud +=2; /*  115  Kbps */
+		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			baud += 3; /* 230 kbps*/
+		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			baud += 4; /* 460 kbps*/
 	}
 	if (linuxb_to_isib[baud] == -1) {
 		/* hang up */
@@ -1460,17 +1455,6 @@
 	port->status |= ISI_TXOK;
 }
 
-/* hangup et all */
-static void do_isicom_hangup(struct work_struct *work)
-{
-	struct isi_port *port = container_of(work, struct isi_port, hangup_tq);
-	struct tty_struct *tty;
-
-	tty = port->tty;
-	if (tty)
-		tty_hangup(tty);
-}
-
 static void isicom_hangup(struct tty_struct *tty)
 {
 	struct isi_port *port = tty->driver_data;
@@ -1503,7 +1487,6 @@
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 	spin_unlock_irqrestore(&card->card_lock, flags);
 
-	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
 }
 
@@ -1536,7 +1519,7 @@
 {
 	struct isi_board *board = pci_get_drvdata(pdev);
 	unsigned long base = board->base;
-	unsigned int portcount = 0;
+	unsigned int sig, portcount = 0;
 	int retval = 0;
 
 	dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
@@ -1544,27 +1527,35 @@
 
 	inw(base + 0x8);
 
-	mdelay(10);
+	msleep(10);
 
 	outw(0, base + 0x8); /* Reset */
 
-	msleep(3000);
+	msleep(1000);
 
-	*signature = inw(base + 0x4) & 0xff;
+	sig = inw(base + 0x4) & 0xff;
 
-	portcount = inw(base + 0x2);
-	if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) &&
-			(portcount != 4) && (portcount != 8))) {
-		dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
-			inw(base + 0x2), inw(base + 0xe));
-		dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure "
-			"(Possible bad I/O Port Address 0x%lx).\n",
-			card + 1, base);
+	if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
+			sig != 0xee) {
+		dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
+			"bad I/O Port Address 0x%lx).\n", card + 1, base);
+		dev_dbg(&pdev->dev, "Sig=0x%x\n", sig);
 		retval = -EIO;
 		goto end;
 	}
 
-	switch (*signature) {
+	msleep(10);
+
+	portcount = inw(base + 0x2);
+	if (!inw(base + 0xe) & 0x1 || (portcount != 0 && portcount != 4 &&
+				portcount != 8 && portcount != 16)) {
+		dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.",
+			card + 1);
+		retval = -EIO;
+		goto end;
+	}
+
+	switch (sig) {
 	case 0xa5:
 	case 0xbb:
 	case 0xdd:
@@ -1572,16 +1563,13 @@
 		board->shift_count = 12;
 		break;
 	case 0xcc:
+	case 0xee:
 		board->port_count = 16;
 		board->shift_count = 11;
 		break;
-	default:
-		dev_warn(&pdev->dev, "ISILoad:Card%d reset failure (Possible "
-			"bad I/O Port Address 0x%lx).\n", card + 1, base);
-		dev_dbg(&pdev->dev, "Sig=0x%lx\n", signature);
-		retval = -EIO;
 	}
 	dev_info(&pdev->dev, "-Done\n");
+	*signature = sig;
 
 end:
 	return retval;
@@ -1757,7 +1745,7 @@
 /*
  *	Insmod can set static symbols so keep these static
  */
-static int card;
+static unsigned int card_count;
 
 static int __devinit isicom_probe(struct pci_dev *pdev,
 	const struct pci_device_id *ent)
@@ -1767,7 +1755,7 @@
 	u8 pciirq;
 	struct isi_board *board = NULL;
 
-	if (card >= BOARD_COUNT)
+	if (card_count >= BOARD_COUNT)
 		goto err;
 
 	ioaddr = pci_resource_start(pdev, 3);
@@ -1785,7 +1773,7 @@
 	board->index = index;
 	board->base = ioaddr;
 	board->irq = pciirq;
-	card++;
+	card_count++;
 
 	pci_set_drvdata(pdev, board);
 
@@ -1795,7 +1783,7 @@
 			"will be disabled.\n", board->base, board->base + 15,
 			index + 1);
 		retval = -EBUSY;
-		goto err;
+		goto errdec;
  	}
 
 	retval = request_irq(board->irq, isicom_interrupt,
@@ -1824,8 +1812,10 @@
 	free_irq(board->irq, board);
 errunrr:
 	pci_release_region(pdev, 3);
-err:
+errdec:
 	board->base = 0;
+	card_count--;
+err:
 	return retval;
 }
 
@@ -1839,6 +1829,8 @@
 
 	free_irq(board->irq, board);
 	pci_release_region(pdev, 3);
+	board->base = 0;
+	card_count--;
 }
 
 static int __init isicom_init(void)
@@ -1846,8 +1838,6 @@
 	int retval, idx, channel;
 	struct isi_port *port;
 
-	card = 0;
-
 	for(idx = 0; idx < BOARD_COUNT; idx++) {
 		port = &isi_ports[idx * 16];
 		isi_card[idx].ports = port;
@@ -1858,8 +1848,6 @@
 			port->channel = channel;
 			port->close_delay = 50 * HZ/100;
 			port->closing_wait = 3000 * HZ/100;
-			INIT_WORK(&port->hangup_tq, do_isicom_hangup);
-			INIT_WORK(&port->bh_tqueue, isicom_bottomhalf);
 			port->status = 0;
 			init_waitqueue_head(&port->open_wait);
 			init_waitqueue_head(&port->close_wait);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 68645d3..7b279d1 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -2424,7 +2424,6 @@
 			if (tty != NULL) {
 				tty_wakeup(tty);
 				EBRDENABLE(brdp);
-				wake_up_interruptible(&tty->write_wait);
 			}
 		}
 
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 7a6c1c0..cb8d691 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -595,15 +595,8 @@
 
 static void fn_SAK(struct vc_data *vc)
 {
-	struct tty_struct *tty = vc->vc_tty;
-
-	/*
-	 * SAK should also work in all raw modes and reset
-	 * them properly.
-	 */
-	if (tty)
-		do_SAK(tty);
-	reset_vc(vc);
+	struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
+	schedule_work(SAK_work);
 }
 
 static void fn_null(struct vc_data *vc)
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c
index d649abb..5f4fdcf 100644
--- a/drivers/char/lcd.c
+++ b/drivers/char/lcd.c
@@ -409,138 +409,6 @@
 			break;
 		}
 
-//  Erase the flash
-
-	case FLASH_Erase:{
-
-			int ctr = 0;
-
-			if ( !capable(CAP_SYS_ADMIN) ) return -EPERM;
-
-			pr_info(LCD "Erasing Flash\n");
-
-			// Chip Erase Sequence
-			WRITE_FLASH(kFlash_Addr1, kFlash_Data1);
-			WRITE_FLASH(kFlash_Addr2, kFlash_Data2);
-			WRITE_FLASH(kFlash_Addr1, kFlash_Erase3);
-			WRITE_FLASH(kFlash_Addr1, kFlash_Data1);
-			WRITE_FLASH(kFlash_Addr2, kFlash_Data2);
-			WRITE_FLASH(kFlash_Addr1, kFlash_Erase6);
-
-			while ((!dqpoll(0x00000000, 0xFF))
-			       && (!timeout(0x00000000))) {
-				ctr++;
-			}
-
-			if (READ_FLASH(0x07FFF0) == 0xFF) {
-				pr_info(LCD "Erase Successful\n");
-			} else if (timeout) {
-				pr_info(LCD "Erase Timed Out\n");
-			}
-
-			break;
-		}
-
-// burn the flash
-
-	case FLASH_Burn:{
-
-			volatile unsigned long burn_addr;
-			unsigned long flags;
-			unsigned int i, index;
-			unsigned char *rom;
-
-
-			struct lcd_display display;
-
-			if ( !capable(CAP_SYS_ADMIN) ) return -EPERM;
-
-			if (copy_from_user
-			    (&display, (struct lcd_display *) arg,
-			     sizeof(struct lcd_display)))
-				return -EFAULT;
-			rom = kmalloc((128), GFP_ATOMIC);
-			if (rom == NULL) {
-				printk(KERN_ERR LCD "kmalloc() failed in %s\n",
-						__FUNCTION__);
-				return -ENOMEM;
-			}
-
-			pr_info(LCD "Starting Flash burn\n");
-			for (i = 0; i < FLASH_SIZE; i = i + 128) {
-
-				if (copy_from_user
-				    (rom, display.RomImage + i, 128)) {
-					kfree(rom);
-					return -EFAULT;
-				}
-				burn_addr = kFlashBase + i;
-				spin_lock_irqsave(&lcd_lock, flags);
-				for (index = 0; index < (128); index++) {
-
-					WRITE_FLASH(kFlash_Addr1,
-						    kFlash_Data1);
-					WRITE_FLASH(kFlash_Addr2,
-						    kFlash_Data2);
-					WRITE_FLASH(kFlash_Addr1,
-						    kFlash_Prog);
-					*((volatile unsigned char *)burn_addr) =
-					  (volatile unsigned char) rom[index];
-
-					while ((!dqpoll (burn_addr,
-						(volatile unsigned char)
-						rom[index])) &&
-						(!timeout(burn_addr))) { }
-					burn_addr++;
-				}
-				spin_unlock_irqrestore(&lcd_lock, flags);
-				if (* ((volatile unsigned char *)
-					(burn_addr - 1)) ==
-					(volatile unsigned char)
-					rom[index - 1]) {
-				} else if (timeout) {
-					pr_info(LCD "Flash burn timed out\n");
-				}
-
-
-			}
-			kfree(rom);
-
-			pr_info(LCD "Flash successfully burned\n");
-
-			break;
-		}
-
-//  read the flash all at once
-
-	case FLASH_Read:{
-
-			unsigned char *user_bytes;
-			volatile unsigned long read_addr;
-			unsigned int i;
-
-			user_bytes =
-			    &(((struct lcd_display *) arg)->RomImage[0]);
-
-			if (!access_ok
-			    (VERIFY_WRITE, user_bytes, FLASH_SIZE))
-				return -EFAULT;
-
-			pr_info(LCD "Reading Flash");
-			for (i = 0; i < FLASH_SIZE; i++) {
-				unsigned char tmp_byte;
-				read_addr = kFlashBase + i;
-				tmp_byte =
-				    *((volatile unsigned char *)
-				      read_addr);
-				if (__put_user(tmp_byte, &user_bytes[i]))
-					return -EFAULT;
-			}
-
-
-			break;
-		}
-
 	default:
 		return -EINVAL;
 
@@ -644,42 +512,6 @@
 	misc_deregister(&lcd_dev);
 }
 
-//
-// Function: dqpoll
-//
-// Description:  Polls the data lines to see if the flash is busy
-//
-// In: address, byte data
-//
-// Out: 0 = busy, 1 = write or erase complete
-//
-//
-
-static int dqpoll(volatile unsigned long address, volatile unsigned char data)
-{
-	volatile unsigned char dq7;
-
-	dq7 = data & 0x80;
-
-	return ((READ_FLASH(address) & 0x80) == dq7);
-}
-
-//
-// Function: timeout
-//
-// Description: Checks to see if erase or write has timed out
-//              By polling dq5
-//
-// In: address
-//
-//
-// Out: 0 = not timed out, 1 = timed out
-
-static int timeout(volatile unsigned long address)
-{
-	return (READ_FLASH(address) & 0x20) == 0x20;
-}
-
 module_init(lcd_init);
 module_exit(lcd_exit);
 
diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h
index a8d4ae7..290b3ff 100644
--- a/drivers/char/lcd.h
+++ b/drivers/char/lcd.h
@@ -14,11 +14,7 @@
 
 // function headers
 
-static int dqpoll(volatile unsigned long, volatile unsigned char );
-static int timeout(volatile unsigned long);
-
 #define LCD_CHARS_PER_LINE 40
-#define FLASH_SIZE 524288
 #define MAX_IDLE_TIME 120
 
 struct lcd_display {
@@ -54,26 +50,6 @@
 #define LCDTimeoutValue	0xfff
 
 
-// Flash definitions AMD 29F040
-#define kFlashBase	0x0FC00000
-
-#define kFlash_Addr1    0x5555
-#define kFlash_Addr2    0x2AAA
-#define kFlash_Data1    0xAA
-#define kFlash_Data2    0x55
-#define kFlash_Prog     0xA0
-#define kFlash_Erase3   0x80
-#define kFlash_Erase6   0x10
-#define kFlash_Read     0xF0
-
-#define kFlash_ID       0x90
-#define kFlash_VenAddr  0x00
-#define kFlash_DevAddr  0x01
-#define kFlash_VenID    0x01
-#define kFlash_DevID    0xA4    // 29F040
-//#define kFlash_DevID  0xAD    // 29F016
-
-
 // Macros
 
 #define LCDWriteData(x)	outl((x << 24), kLCD_DR)
@@ -89,9 +65,6 @@
 #define WRITE_GAL(x,y)	outl(y, 0x04000000 | (x))
 #define BusyCheck()	while ((LCDReadInst & 0x80) == 0x80)
 
-#define WRITE_FLASH(x,y) outb((char)y, kFlashBase | (x))
-#define READ_FLASH(x)	(inb(kFlashBase | (x)))
-
 
 
 /*
@@ -124,11 +97,6 @@
 //  Button defs
 #define BUTTON_Read             50
 
-//  Flash command codes
-#define FLASH_Erase		60
-#define FLASH_Burn		61
-#define FLASH_Read		62
-
 
 // Ethernet LINK check hackaroo
 #define LINK_Check              90
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 0afb7ba..57f9115 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -46,7 +46,7 @@
 /*
  * file operations
  */
-struct file_operations mbcs_ops = {
+const struct file_operations mbcs_ops = {
 	.open = mbcs_open,
 	.llseek = mbcs_sram_llseek,
 	.read = mbcs_sram_read,
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index f391a24..7dbaee8d 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -11,15 +11,6 @@
  *      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.
  */
 
 /*
@@ -55,36 +46,20 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#define		MOXA_VERSION		"5.1k"
+#define MOXA_VERSION		"5.1k"
 
-#define MOXAMAJOR       172
-#define MOXACUMAJOR     173
+#define MOXAMAJOR		172
+#define MOXACUMAJOR		173
 
-#define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)
-#define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2)
-
-#define MAX_BOARDS 		4	/* Don't change this value */
+#define MAX_BOARDS		4	/* Don't change this value */
 #define MAX_PORTS_PER_BOARD	32	/* Don't change this value */
-#define MAX_PORTS 		128	/* Don't change this value */
+#define MAX_PORTS		(MAX_BOARDS * MAX_PORTS_PER_BOARD)
 
 /*
  *    Define the Moxa PCI vendor and device IDs.
  */
-#define MOXA_BUS_TYPE_ISA		0
-#define MOXA_BUS_TYPE_PCI		1
-
-#ifndef	PCI_VENDOR_ID_MOXA
-#define	PCI_VENDOR_ID_MOXA	0x1393
-#endif
-#ifndef PCI_DEVICE_ID_CP204J
-#define PCI_DEVICE_ID_CP204J	0x2040
-#endif
-#ifndef PCI_DEVICE_ID_C218
-#define PCI_DEVICE_ID_C218	0x2180
-#endif
-#ifndef PCI_DEVICE_ID_C320
-#define PCI_DEVICE_ID_C320	0x3200
-#endif
+#define MOXA_BUS_TYPE_ISA	0
+#define MOXA_BUS_TYPE_PCI	1
 
 enum {
 	MOXA_BOARD_C218_PCI = 1,
@@ -105,47 +80,56 @@
 
 #ifdef CONFIG_PCI
 static struct pci_device_id moxa_pcibrds[] = {
-	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C218, PCI_ANY_ID, PCI_ANY_ID, 
-	  0, 0, MOXA_BOARD_C218_PCI },
-	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C320, PCI_ANY_ID, PCI_ANY_ID, 
-	  0, 0, MOXA_BOARD_C320_PCI },
-	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP204J, PCI_ANY_ID, PCI_ANY_ID, 
-	  0, 0, MOXA_BOARD_CP204J },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218),
+		.driver_data = MOXA_BOARD_C218_PCI },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320),
+		.driver_data = MOXA_BOARD_C320_PCI },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J),
+		.driver_data = MOXA_BOARD_CP204J },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, moxa_pcibrds);
 #endif /* CONFIG_PCI */
 
-typedef struct _moxa_isa_board_conf {
+struct moxa_isa_board_conf {
 	int boardType;
 	int numPorts;
 	unsigned long baseAddr;
-} moxa_isa_board_conf;
+};
 
-static moxa_isa_board_conf moxa_isa_boards[] =
+static struct moxa_isa_board_conf moxa_isa_boards[] =
 {
 /*       {MOXA_BOARD_C218_ISA,8,0xDC000}, */
 };
 
-typedef struct _moxa_pci_devinfo {
-	ushort busNum;
-	ushort devNum;
-	struct pci_dev *pdev;
-} moxa_pci_devinfo;
-
-typedef struct _moxa_board_conf {
+static struct moxa_board_conf {
 	int boardType;
 	int numPorts;
 	unsigned long baseAddr;
 	int busType;
-	moxa_pci_devinfo pciInfo;
-} moxa_board_conf;
 
-static moxa_board_conf moxa_boards[MAX_BOARDS];
-static void __iomem *moxaBaseAddr[MAX_BOARDS];
-static int loadstat[MAX_BOARDS];
+	int loadstat;
 
-struct moxa_str {
+	void __iomem *basemem;
+	void __iomem *intNdx;
+	void __iomem *intPend;
+	void __iomem *intTable;
+} moxa_boards[MAX_BOARDS];
+
+struct mxser_mstatus {
+	tcflag_t cflag;
+	int cts;
+	int dsr;
+	int ri;
+	int dcd;
+};
+
+struct moxaq_str {
+	int inq;
+	int outq;
+};
+
+struct moxa_port {
 	int type;
 	int port;
 	int close_delay;
@@ -159,18 +143,18 @@
 	int cflag;
 	wait_queue_head_t open_wait;
 	wait_queue_head_t close_wait;
-	struct work_struct tqueue;
-};
 
-struct mxser_mstatus {
-	tcflag_t cflag;
-	int cts;
-	int dsr;
-	int ri;
-	int dcd;
-};
+	struct timer_list emptyTimer;
 
-static struct mxser_mstatus GMStatus[MAX_PORTS];
+	char chkPort;
+	char lineCtrl;
+	void __iomem *tableAddr;
+	long curBaud;
+	char DCDState;
+	char lowChkFlag;
+
+	ushort breakCnt;
+};
 
 /* statusflags */
 #define TXSTOPPED	0x1
@@ -178,25 +162,17 @@
 #define EMPTYWAIT	0x4
 #define THROTTLE	0x8
 
-/* event */
-#define MOXA_EVENT_HANGUP	1
-
 #define SERIAL_DO_RESTART
 
-
-#define SERIAL_TYPE_NORMAL	1
-
 #define WAKEUP_CHARS		256
 
-#define PORTNO(x)		((x)->index)
-
 static int verbose = 0;
 static int ttymajor = MOXAMAJOR;
 /* Variables for insmod */
 #ifdef MODULE
-static int baseaddr[] 	= 	{0, 0, 0, 0};
-static int type[]	=	{0, 0, 0, 0};
-static int numports[] 	=	{0, 0, 0, 0};
+static int baseaddr[4];
+static int type[4];
+static int numports[4];
 #endif
 
 MODULE_AUTHOR("William Chen");
@@ -210,19 +186,9 @@
 module_param(ttymajor, int, 0);
 module_param(verbose, bool, 0644);
 
-static struct tty_driver *moxaDriver;
-static struct moxa_str moxaChannels[MAX_PORTS];
-static unsigned char *moxaXmitBuff;
-static int moxaTimer_on;
-static struct timer_list moxaTimer;
-static int moxaEmptyTimer_on[MAX_PORTS];
-static struct timer_list moxaEmptyTimer[MAX_PORTS];
-static struct semaphore moxaBuffSem;
-
 /*
  * static functions:
  */
-static void do_moxa_softint(struct work_struct *);
 static int moxa_open(struct tty_struct *, struct file *);
 static void moxa_close(struct tty_struct *, struct file *);
 static int moxa_write(struct tty_struct *, const unsigned char *, int);
@@ -244,11 +210,11 @@
 static void moxa_poll(unsigned long);
 static void set_tty_param(struct tty_struct *);
 static int block_till_ready(struct tty_struct *, struct file *,
-			    struct moxa_str *);
+			    struct moxa_port *);
 static void setup_empty_event(struct tty_struct *);
 static void check_xmit_empty(unsigned long);
-static void shut_down(struct moxa_str *);
-static void receive_data(struct moxa_str *);
+static void shut_down(struct moxa_port *);
+static void receive_data(struct moxa_port *);
 /*
  * moxa board interface functions:
  */
@@ -278,8 +244,8 @@
 static void MoxaPortTxEnable(int);
 static int MoxaPortResetBrkCnt(int);
 static void MoxaPortSendBreak(int, int);
-static int moxa_get_serial_info(struct moxa_str *, struct serial_struct __user *);
-static int moxa_set_serial_info(struct moxa_str *, struct serial_struct __user *);
+static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *);
+static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *);
 static void MoxaSetFifo(int port, int enable);
 
 static const struct tty_operations moxa_ops = {
@@ -302,12 +268,41 @@
 	.tiocmset = moxa_tiocmset,
 };
 
+static struct tty_driver *moxaDriver;
+static struct moxa_port moxa_ports[MAX_PORTS];
+static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
 static DEFINE_SPINLOCK(moxa_lock);
 
 #ifdef CONFIG_PCI
-static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board)
+static int __devinit moxa_pci_probe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
 {
-	board->baseAddr = pci_resource_start (p, 2);
+	struct moxa_board_conf *board;
+	unsigned int i;
+	int board_type = ent->driver_data;
+	int retval;
+
+	retval = pci_enable_device(pdev);
+	if (retval)
+		goto err;
+
+	for (i = 0; i < MAX_BOARDS; i++)
+		if (moxa_boards[i].basemem == NULL)
+			break;
+
+	retval = -ENODEV;
+	if (i >= MAX_BOARDS) {
+		if (verbose)
+			printk("More than %d MOXA Intellio family boards "
+				"found. Board is ignored.\n", MAX_BOARDS);
+		goto err;
+	}
+
+	board = &moxa_boards[i];
+	board->basemem = pci_iomap(pdev, 2, 0x4000);
+	if (board->basemem == NULL)
+		goto err;
+
 	board->boardType = board_type;
 	switch (board_type) {
 	case MOXA_BOARD_C218_ISA:
@@ -323,27 +318,40 @@
 		break;
 	}
 	board->busType = MOXA_BUS_TYPE_PCI;
-	board->pciInfo.busNum = p->bus->number;
-	board->pciInfo.devNum = p->devfn >> 3;
-	board->pciInfo.pdev = p;
-	/* don't lose the reference in the next pci_get_device iteration */
-	pci_dev_get(p);
+
+	pci_set_drvdata(pdev, board);
 
 	return (0);
+err:
+	return retval;
 }
+
+static void __devexit moxa_pci_remove(struct pci_dev *pdev)
+{
+	struct moxa_board_conf *brd = pci_get_drvdata(pdev);
+
+	pci_iounmap(pdev, brd->basemem);
+	brd->basemem = NULL;
+}
+
+static struct pci_driver moxa_pci_driver = {
+	.name = "moxa",
+	.id_table = moxa_pcibrds,
+	.probe = moxa_pci_probe,
+	.remove = __devexit_p(moxa_pci_remove)
+};
 #endif /* CONFIG_PCI */
 
 static int __init moxa_init(void)
 {
-	int i, numBoards;
-	struct moxa_str *ch;
+	int i, numBoards, retval = 0;
+	struct moxa_port *ch;
 
 	printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION);
 	moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
 	if (!moxaDriver)
 		return -ENOMEM;
 
-	init_MUTEX(&moxaBuffSem);
 	moxaDriver->owner = THIS_MODULE;
 	moxaDriver->name = "ttyMX";
 	moxaDriver->major = ttymajor;
@@ -351,40 +359,25 @@
 	moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
 	moxaDriver->subtype = SERIAL_TYPE_NORMAL;
 	moxaDriver->init_termios = tty_std_termios;
-	moxaDriver->init_termios.c_iflag = 0;
-	moxaDriver->init_termios.c_oflag = 0;
 	moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-	moxaDriver->init_termios.c_lflag = 0;
 	moxaDriver->init_termios.c_ispeed = 9600;
 	moxaDriver->init_termios.c_ospeed = 9600;
 	moxaDriver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(moxaDriver, &moxa_ops);
 
-	moxaXmitBuff = NULL;
-
-	for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) {
+	for (i = 0, ch = moxa_ports; i < MAX_PORTS; i++, ch++) {
 		ch->type = PORT_16550A;
 		ch->port = i;
-		INIT_WORK(&ch->tqueue, do_moxa_softint);
-		ch->tty = NULL;
 		ch->close_delay = 5 * HZ / 10;
 		ch->closing_wait = 30 * HZ;
-		ch->count = 0;
-		ch->blocked_open = 0;
 		ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
 		init_waitqueue_head(&ch->open_wait);
 		init_waitqueue_head(&ch->close_wait);
+
+		setup_timer(&ch->emptyTimer, check_xmit_empty,
+				(unsigned long)ch);
 	}
 
-	for (i = 0; i < MAX_BOARDS; i++) {
-		moxa_boards[i].boardType = 0;
-		moxa_boards[i].numPorts = 0;
-		moxa_boards[i].baseAddr = 0;
-		moxa_boards[i].busType = 0;
-		moxa_boards[i].pciInfo.busNum = 0;
-		moxa_boards[i].pciInfo.devNum = 0;
-	}
-	MoxaDriverInit();
 	printk("Tty devices major number = %d\n", ttymajor);
 
 	if (tty_register_driver(moxaDriver)) {
@@ -392,18 +385,8 @@
 		put_tty_driver(moxaDriver);
 		return -1;
 	}
-	for (i = 0; i < MAX_PORTS; i++) {
-		init_timer(&moxaEmptyTimer[i]);
-		moxaEmptyTimer[i].function = check_xmit_empty;
-		moxaEmptyTimer[i].data = (unsigned long) & moxaChannels[i];
-		moxaEmptyTimer_on[i] = 0;
-	}
 
-	init_timer(&moxaTimer);
-	moxaTimer.function = moxa_poll;
-	moxaTimer.expires = jiffies + (HZ / 50);
-	moxaTimer_on = 1;
-	add_timer(&moxaTimer);
+	mod_timer(&moxaTimer, jiffies + HZ / 50);
 
 	/* Find the boards defined in source code */
 	numBoards = 0;
@@ -451,35 +434,22 @@
 		}
 	}
 #endif
-	/* Find PCI boards here */
+
 #ifdef CONFIG_PCI
-	{
-		struct pci_dev *p = NULL;
-		int n = ARRAY_SIZE(moxa_pcibrds) - 1;
-		i = 0;
-		while (i < n) {
-			while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
-			{
-				if (pci_enable_device(p))
-					continue;
-				if (numBoards >= MAX_BOARDS) {
-					if (verbose)
-						printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);
-				} else {
-					moxa_get_PCI_conf(p, moxa_pcibrds[i].driver_data,
-						&moxa_boards[numBoards]);
-					numBoards++;
-				}
-			}
-			i++;
-		}
+	retval = pci_register_driver(&moxa_pci_driver);
+	if (retval) {
+		printk(KERN_ERR "Can't register moxa pci driver!\n");
+		if (numBoards)
+			retval = 0;
 	}
 #endif
+
 	for (i = 0; i < numBoards; i++) {
-		moxaBaseAddr[i] = ioremap((unsigned long) moxa_boards[i].baseAddr, 0x4000);
+		moxa_boards[i].basemem = ioremap(moxa_boards[i].baseAddr,
+				0x4000);
 	}
 
-	return (0);
+	return retval;
 }
 
 static void __exit moxa_exit(void)
@@ -489,23 +459,22 @@
 	if (verbose)
 		printk("Unloading module moxa ...\n");
 
-	if (moxaTimer_on)
-		del_timer(&moxaTimer);
+	del_timer_sync(&moxaTimer);
 
 	for (i = 0; i < MAX_PORTS; i++)
-		if (moxaEmptyTimer_on[i])
-			del_timer(&moxaEmptyTimer[i]);
+		del_timer_sync(&moxa_ports[i].emptyTimer);
 
 	if (tty_unregister_driver(moxaDriver))
 		printk("Couldn't unregister MOXA Intellio family serial driver\n");
 	put_tty_driver(moxaDriver);
 
-	for (i = 0; i < MAX_BOARDS; i++) {
-		if (moxaBaseAddr[i])
-			iounmap(moxaBaseAddr[i]);
-		if (moxa_boards[i].busType == MOXA_BUS_TYPE_PCI)
-			pci_dev_put(moxa_boards[i].pciInfo.pdev);
-	}
+#ifdef CONFIG_PCI
+	pci_unregister_driver(&moxa_pci_driver);
+#endif
+
+	for (i = 0; i < MAX_BOARDS; i++)
+		if (moxa_boards[i].basemem)
+			iounmap(moxa_boards[i].basemem);
 
 	if (verbose)
 		printk("Done\n");
@@ -514,28 +483,13 @@
 module_init(moxa_init);
 module_exit(moxa_exit);
 
-static void do_moxa_softint(struct work_struct *work)
-{
-	struct moxa_str *ch = container_of(work, struct moxa_str, tqueue);
-	struct tty_struct *tty;
-
-	if (ch && (tty = ch->tty)) {
-		if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) {
-			tty_hangup(tty);	/* FIXME: module removal race here - AKPM */
-			wake_up_interruptible(&ch->open_wait);
-			ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
-		}
-	}
-}
-
 static int moxa_open(struct tty_struct *tty, struct file *filp)
 {
-	struct moxa_str *ch;
+	struct moxa_port *ch;
 	int port;
 	int retval;
-	unsigned long page;
 
-	port = PORTNO(tty);
+	port = tty->index;
 	if (port == MAX_PORTS) {
 		return (0);
 	}
@@ -543,23 +497,8 @@
 		tty->driver_data = NULL;
 		return (-ENODEV);
 	}
-	down(&moxaBuffSem);
-	if (!moxaXmitBuff) {
-		page = get_zeroed_page(GFP_KERNEL);
-		if (!page) {
-			up(&moxaBuffSem);
-			return (-ENOMEM);
-		}
-		/* This test is guarded by the BuffSem so no longer needed
-		   delete me in 2.5 */
-		if (moxaXmitBuff)
-			free_page(page);
-		else
-			moxaXmitBuff = (unsigned char *) page;
-	}
-	up(&moxaBuffSem);
 
-	ch = &moxaChannels[port];
+	ch = &moxa_ports[port];
 	ch->count++;
 	tty->driver_data = ch;
 	ch->tty = tty;
@@ -585,10 +524,10 @@
 
 static void moxa_close(struct tty_struct *tty, struct file *filp)
 {
-	struct moxa_str *ch;
+	struct moxa_port *ch;
 	int port;
 
-	port = PORTNO(tty);
+	port = tty->index;
 	if (port == MAX_PORTS) {
 		return;
 	}
@@ -605,7 +544,7 @@
 	if (tty_hung_up_p(filp)) {
 		return;
 	}
-	ch = (struct moxa_str *) tty->driver_data;
+	ch = (struct moxa_port *) tty->driver_data;
 
 	if ((tty->count == 1) && (ch->count != 1)) {
 		printk("moxa_close: bad serial port count; tty->count is 1, "
@@ -626,8 +565,7 @@
 	if (ch->asyncflags & ASYNC_INITIALIZED) {
 		setup_empty_event(tty);
 		tty_wait_until_sent(tty, 30 * HZ);	/* 30 seconds timeout */
-		moxaEmptyTimer_on[ch->port] = 0;
-		del_timer(&moxaEmptyTimer[ch->port]);
+		del_timer_sync(&moxa_ports[ch->port].emptyTimer);
 	}
 	shut_down(ch);
 	MoxaPortFlushData(port, 2);
@@ -652,11 +590,11 @@
 static int moxa_write(struct tty_struct *tty,
 		      const unsigned char *buf, int count)
 {
-	struct moxa_str *ch;
+	struct moxa_port *ch;
 	int len, port;
 	unsigned long flags;
 
-	ch = (struct moxa_str *) tty->driver_data;
+	ch = (struct moxa_port *) tty->driver_data;
 	if (ch == NULL)
 		return (0);
 	port = ch->port;
@@ -675,11 +613,11 @@
 
 static int moxa_write_room(struct tty_struct *tty)
 {
-	struct moxa_str *ch;
+	struct moxa_port *ch;
 
 	if (tty->stopped)
 		return (0);
-	ch = (struct moxa_str *) tty->driver_data;
+	ch = (struct moxa_port *) tty->driver_data;
 	if (ch == NULL)
 		return (0);
 	return (MoxaPortTxFree(ch->port));
@@ -687,7 +625,7 @@
 
 static void moxa_flush_buffer(struct tty_struct *tty)
 {
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 
 	if (ch == NULL)
 		return;
@@ -698,7 +636,7 @@
 static int moxa_chars_in_buffer(struct tty_struct *tty)
 {
 	int chars;
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 
 	/*
 	 * Sigh...I have to check if driver_data is NULL here, because
@@ -730,17 +668,16 @@
 
 static void moxa_put_char(struct tty_struct *tty, unsigned char c)
 {
-	struct moxa_str *ch;
+	struct moxa_port *ch;
 	int port;
 	unsigned long flags;
 
-	ch = (struct moxa_str *) tty->driver_data;
+	ch = (struct moxa_port *) tty->driver_data;
 	if (ch == NULL)
 		return;
 	port = ch->port;
 	spin_lock_irqsave(&moxa_lock, flags);
-	moxaXmitBuff[0] = c;
-	MoxaPortWriteData(port, moxaXmitBuff, 1);
+	MoxaPortWriteData(port, &c, 1);
 	spin_unlock_irqrestore(&moxa_lock, flags);
 	/************************************************
 	if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
@@ -750,11 +687,11 @@
 
 static int moxa_tiocmget(struct tty_struct *tty, struct file *file)
 {
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 	int port;
 	int flag = 0, dtr, rts;
 
-	port = PORTNO(tty);
+	port = tty->index;
 	if ((port != MAX_PORTS) && (!ch))
 		return (-EINVAL);
 
@@ -776,11 +713,11 @@
 static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
 			 unsigned int set, unsigned int clear)
 {
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 	int port;
 	int dtr, rts;
 
-	port = PORTNO(tty);
+	port = tty->index;
 	if ((port != MAX_PORTS) && (!ch))
 		return (-EINVAL);
 
@@ -800,12 +737,12 @@
 static int moxa_ioctl(struct tty_struct *tty, struct file *file,
 		      unsigned int cmd, unsigned long arg)
 {
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 	register int port;
 	void __user *argp = (void __user *)arg;
 	int retval;
 
-	port = PORTNO(tty);
+	port = tty->index;
 	if ((port != MAX_PORTS) && (!ch))
 		return (-EINVAL);
 
@@ -853,14 +790,14 @@
 
 static void moxa_throttle(struct tty_struct *tty)
 {
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 
 	ch->statusflags |= THROTTLE;
 }
 
 static void moxa_unthrottle(struct tty_struct *tty)
 {
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 
 	ch->statusflags &= ~THROTTLE;
 }
@@ -868,7 +805,7 @@
 static void moxa_set_termios(struct tty_struct *tty,
 			     struct ktermios *old_termios)
 {
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 
 	if (ch == NULL)
 		return;
@@ -880,7 +817,7 @@
 
 static void moxa_stop(struct tty_struct *tty)
 {
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 
 	if (ch == NULL)
 		return;
@@ -891,7 +828,7 @@
 
 static void moxa_start(struct tty_struct *tty)
 {
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 
 	if (ch == NULL)
 		return;
@@ -905,7 +842,7 @@
 
 static void moxa_hangup(struct tty_struct *tty)
 {
-	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 
 	moxa_flush_buffer(tty);
 	shut_down(ch);
@@ -919,24 +856,20 @@
 static void moxa_poll(unsigned long ignored)
 {
 	register int card;
-	struct moxa_str *ch;
+	struct moxa_port *ch;
 	struct tty_struct *tp;
 	int i, ports;
 
-	moxaTimer_on = 0;
 	del_timer(&moxaTimer);
 
 	if (MoxaDriverPoll() < 0) {
-		moxaTimer.function = moxa_poll;
-		moxaTimer.expires = jiffies + (HZ / 50);
-		moxaTimer_on = 1;
-		add_timer(&moxaTimer);
+		mod_timer(&moxaTimer, jiffies + HZ / 50);
 		return;
 	}
 	for (card = 0; card < MAX_BOARDS; card++) {
 		if ((ports = MoxaPortsOfCard(card)) <= 0)
 			continue;
-		ch = &moxaChannels[card * MAX_PORTS_PER_BOARD];
+		ch = &moxa_ports[card * MAX_PORTS_PER_BOARD];
 		for (i = 0; i < ports; i++, ch++) {
 			if ((ch->asyncflags & ASYNC_INITIALIZED) == 0)
 				continue;
@@ -962,18 +895,16 @@
 					if (MoxaPortDCDON(ch->port))
 						wake_up_interruptible(&ch->open_wait);
 					else {
-						set_bit(MOXA_EVENT_HANGUP, &ch->event);
-						schedule_work(&ch->tqueue);
+						tty_hangup(tp);
+						wake_up_interruptible(&ch->open_wait);
+						ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
 					}
 				}
 			}
 		}
 	}
 
-	moxaTimer.function = moxa_poll;
-	moxaTimer.expires = jiffies + (HZ / 50);
-	moxaTimer_on = 1;
-	add_timer(&moxaTimer);
+	mod_timer(&moxaTimer, jiffies + HZ / 50);
 }
 
 /******************************************************************************/
@@ -981,10 +912,10 @@
 static void set_tty_param(struct tty_struct *tty)
 {
 	register struct ktermios *ts;
-	struct moxa_str *ch;
+	struct moxa_port *ch;
 	int rts, cts, txflow, rxflow, xany;
 
-	ch = (struct moxa_str *) tty->driver_data;
+	ch = (struct moxa_port *) tty->driver_data;
 	ts = tty->termios;
 	if (ts->c_cflag & CLOCAL)
 		ch->asyncflags &= ~ASYNC_CHECK_CD;
@@ -1004,7 +935,7 @@
 }
 
 static int block_till_ready(struct tty_struct *tty, struct file *filp,
-			    struct moxa_str *ch)
+			    struct moxa_port *ch)
 {
 	DECLARE_WAITQUEUE(wait,current);
 	unsigned long flags;
@@ -1095,40 +1026,33 @@
 
 static void setup_empty_event(struct tty_struct *tty)
 {
-	struct moxa_str *ch = tty->driver_data;
+	struct moxa_port *ch = tty->driver_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&moxa_lock, flags);
 	ch->statusflags |= EMPTYWAIT;
-	moxaEmptyTimer_on[ch->port] = 0;
-	del_timer(&moxaEmptyTimer[ch->port]);
-	moxaEmptyTimer[ch->port].expires = jiffies + HZ;
-	moxaEmptyTimer_on[ch->port] = 1;
-	add_timer(&moxaEmptyTimer[ch->port]);
+	mod_timer(&moxa_ports[ch->port].emptyTimer, jiffies + HZ);
 	spin_unlock_irqrestore(&moxa_lock, flags);
 }
 
 static void check_xmit_empty(unsigned long data)
 {
-	struct moxa_str *ch;
+	struct moxa_port *ch;
 
-	ch = (struct moxa_str *) data;
-	moxaEmptyTimer_on[ch->port] = 0;
-	del_timer(&moxaEmptyTimer[ch->port]);
+	ch = (struct moxa_port *) data;
+	del_timer_sync(&moxa_ports[ch->port].emptyTimer);
 	if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
 		if (MoxaPortTxQueue(ch->port) == 0) {
 			ch->statusflags &= ~EMPTYWAIT;
 			tty_wakeup(ch->tty);
 			return;
 		}
-		moxaEmptyTimer[ch->port].expires = jiffies + HZ;
-		moxaEmptyTimer_on[ch->port] = 1;
-		add_timer(&moxaEmptyTimer[ch->port]);
+		mod_timer(&moxa_ports[ch->port].emptyTimer, jiffies + HZ);
 	} else
 		ch->statusflags &= ~EMPTYWAIT;
 }
 
-static void shut_down(struct moxa_str *ch)
+static void shut_down(struct moxa_port *ch)
 {
 	struct tty_struct *tp;
 
@@ -1148,7 +1072,7 @@
 	ch->asyncflags &= ~ASYNC_INITIALIZED;
 }
 
-static void receive_data(struct moxa_str *ch)
+static void receive_data(struct moxa_port *ch)
 {
 	struct tty_struct *tp;
 	struct ktermios *ts;
@@ -1465,35 +1389,21 @@
 /*
  *    Query
  */
-#define QueryPort	MAX_PORTS
-
-
 
 struct mon_str {
 	int tick;
 	int rxcnt[MAX_PORTS];
 	int txcnt[MAX_PORTS];
 };
-typedef struct mon_str mon_st;
 
 #define 	DCD_changed	0x01
 #define 	DCD_oldstate	0x80
 
 static unsigned char moxaBuff[10240];
-static void __iomem *moxaIntNdx[MAX_BOARDS];
-static void __iomem *moxaIntPend[MAX_BOARDS];
-static void __iomem *moxaIntTable[MAX_BOARDS];
-static char moxaChkPort[MAX_PORTS];
-static char moxaLineCtrl[MAX_PORTS];
-static void __iomem *moxaTableAddr[MAX_PORTS];
-static long moxaCurBaud[MAX_PORTS];
-static char moxaDCDState[MAX_PORTS];
-static char moxaLowChkFlag[MAX_PORTS];
 static int moxaLowWaterChk;
 static int moxaCard;
-static mon_st moxaLog;
-static int moxaFuncTout;
-static ushort moxaBreakCnt[MAX_PORTS];
+static struct mon_str moxaLog;
+static int moxaFuncTout = HZ / 2;
 
 static void moxadelay(int);
 static void moxafunc(void __iomem *, int, ushort);
@@ -1514,16 +1424,18 @@
  *****************************************************************************/
 void MoxaDriverInit(void)
 {
-	int i;
+	struct moxa_port *p;
+	unsigned int i;
 
 	moxaFuncTout = HZ / 2;	/* 500 mini-seconds */
 	moxaCard = 0;
 	moxaLog.tick = 0;
 	moxaLowWaterChk = 0;
 	for (i = 0; i < MAX_PORTS; i++) {
-		moxaChkPort[i] = 0;
-		moxaLowChkFlag[i] = 0;
-		moxaLineCtrl[i] = 0;
+		p = &moxa_ports[i];
+		p->chkPort = 0;
+		p->lowChkFlag = 0;
+		p->lineCtrl = 0;
 		moxaLog.rxcnt[i] = 0;
 		moxaLog.txcnt[i] = 0;
 	}
@@ -1545,19 +1457,12 @@
 #define MOXA_GET_CUMAJOR        (MOXA + 64)
 #define MOXA_GETMSTATUS         (MOXA + 65)
 
-
-struct moxaq_str {
-	int inq;
-	int outq;
-};
-
 struct dl_str {
 	char __user *buf;
 	int len;
 	int cardno;
 };
 
-static struct moxaq_str temp_queue[MAX_PORTS];
 static struct dl_str dltmp;
 
 void MoxaPortFlushData(int port, int mode)
@@ -1565,10 +1470,10 @@
 	void __iomem *ofsAddr;
 	if ((mode < 0) || (mode > 2))
 		return;
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	moxafunc(ofsAddr, FC_FlushQueue, mode);
 	if (mode != 1) {
-		moxaLowChkFlag[port] = 0;
+		moxa_ports[port].lowChkFlag = 0;
 		low_water_check(ofsAddr);
 	}
 }
@@ -1580,7 +1485,7 @@
 	int MoxaPortTxQueue(int), MoxaPortRxQueue(int);
 	void __user *argp = (void __user *)arg;
 
-	if (port == QueryPort) {
+	if (port == MAX_PORTS) {
 		if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) &&
 		    (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) &&
 		 (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) &&
@@ -1590,7 +1495,8 @@
 	}
 	switch (cmd) {
 	case MOXA_GET_CONF:
-		if(copy_to_user(argp, &moxa_boards, MAX_BOARDS * sizeof(moxa_board_conf)))
+		if(copy_to_user(argp, &moxa_boards, MAX_BOARDS *
+				sizeof(struct moxa_board_conf)))
 			return -EFAULT;
 		return (0);
 	case MOXA_INIT_DRIVER:
@@ -1599,23 +1505,27 @@
 		return (0);
 	case MOXA_GETDATACOUNT:
 		moxaLog.tick = jiffies;
-		if(copy_to_user(argp, &moxaLog, sizeof(mon_st)))
+		if(copy_to_user(argp, &moxaLog, sizeof(struct mon_str)))
 			return -EFAULT;
 		return (0);
 	case MOXA_FLUSH_QUEUE:
 		MoxaPortFlushData(port, arg);
 		return (0);
-	case MOXA_GET_IOQUEUE:
-		for (i = 0; i < MAX_PORTS; i++) {
-			if (moxaChkPort[i]) {
-				temp_queue[i].inq = MoxaPortRxQueue(i);
-				temp_queue[i].outq = MoxaPortTxQueue(i);
+	case MOXA_GET_IOQUEUE: {
+		struct moxaq_str __user *argm = argp;
+		struct moxaq_str tmp;
+
+		for (i = 0; i < MAX_PORTS; i++, argm++) {
+			memset(&tmp, 0, sizeof(tmp));
+			if (moxa_ports[i].chkPort) {
+				tmp.inq = MoxaPortRxQueue(i);
+				tmp.outq = MoxaPortTxQueue(i);
 			}
+			if (copy_to_user(argm, &tmp, sizeof(tmp)))
+				return -EFAULT;
 		}
-		if(copy_to_user(argp, temp_queue, sizeof(struct moxaq_str) * MAX_PORTS))
-			return -EFAULT;
 		return (0);
-	case MOXA_GET_OQUEUE:
+	} case MOXA_GET_OQUEUE:
 		i = MoxaPortTxQueue(port);
 		return put_user(i, (unsigned long __user *)argp);
 	case MOXA_GET_IQUEUE:
@@ -1630,33 +1540,36 @@
 		if(copy_to_user(argp, &i, sizeof(int)))
 			return -EFAULT;
 		return 0;
-	case MOXA_GETMSTATUS:
-		for (i = 0; i < MAX_PORTS; i++) {
-			GMStatus[i].ri = 0;
-			GMStatus[i].dcd = 0;
-			GMStatus[i].dsr = 0;
-			GMStatus[i].cts = 0;
-			if (!moxaChkPort[i]) {
-				continue;
+	case MOXA_GETMSTATUS: {
+		struct mxser_mstatus __user *argm = argp;
+		struct mxser_mstatus tmp;
+		struct moxa_port *p;
+
+		for (i = 0; i < MAX_PORTS; i++, argm++) {
+			p = &moxa_ports[i];
+			memset(&tmp, 0, sizeof(tmp));
+			if (!p->chkPort) {
+				goto copy;
 			} else {
-				status = MoxaPortLineStatus(moxaChannels[i].port);
+				status = MoxaPortLineStatus(p->port);
 				if (status & 1)
-					GMStatus[i].cts = 1;
+					tmp.cts = 1;
 				if (status & 2)
-					GMStatus[i].dsr = 1;
+					tmp.dsr = 1;
 				if (status & 4)
-					GMStatus[i].dcd = 1;
+					tmp.dcd = 1;
 			}
 
-			if (!moxaChannels[i].tty || !moxaChannels[i].tty->termios)
-				GMStatus[i].cflag = moxaChannels[i].cflag;
+			if (!p->tty || !p->tty->termios)
+				tmp.cflag = p->cflag;
 			else
-				GMStatus[i].cflag = moxaChannels[i].tty->termios->c_cflag;
+				tmp.cflag = p->tty->termios->c_cflag;
+copy:
+			if (copy_to_user(argm, &tmp, sizeof(tmp)))
+				return -EFAULT;
 		}
-		if(copy_to_user(argp, GMStatus, sizeof(struct mxser_mstatus) * MAX_PORTS))
-			return -EFAULT;
 		return 0;
-	default:
+	} default:
 		return (-ENOIOCTLCMD);
 	case MOXA_LOAD_BIOS:
 	case MOXA_FIND_BOARD:
@@ -1694,6 +1607,7 @@
 
 int MoxaDriverPoll(void)
 {
+	struct moxa_board_conf *brd;
 	register ushort temp;
 	register int card;
 	void __iomem *ofsAddr;
@@ -1703,43 +1617,44 @@
 	if (moxaCard == 0)
 		return (-1);
 	for (card = 0; card < MAX_BOARDS; card++) {
-	        if (loadstat[card] == 0)
+		brd = &moxa_boards[card];
+	        if (brd->loadstat == 0)
 			continue;
-		if ((ports = moxa_boards[card].numPorts) == 0)
+		if ((ports = brd->numPorts) == 0)
 			continue;
-		if (readb(moxaIntPend[card]) == 0xff) {
-			ip = moxaIntTable[card] + readb(moxaIntNdx[card]);
+		if (readb(brd->intPend) == 0xff) {
+			ip = brd->intTable + readb(brd->intNdx);
 			p = card * MAX_PORTS_PER_BOARD;
 			ports <<= 1;
 			for (port = 0; port < ports; port += 2, p++) {
 				if ((temp = readw(ip + port)) != 0) {
 					writew(0, ip + port);
-					ofsAddr = moxaTableAddr[p];
+					ofsAddr = moxa_ports[p].tableAddr;
 					if (temp & IntrTx)
 						writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat);
 					if (temp & IntrBreak) {
-						moxaBreakCnt[p]++;
+						moxa_ports[p].breakCnt++;
 					}
 					if (temp & IntrLine) {
 						if (readb(ofsAddr + FlagStat) & DCD_state) {
-							if ((moxaDCDState[p] & DCD_oldstate) == 0)
-								moxaDCDState[p] = (DCD_oldstate |
+							if ((moxa_ports[p].DCDState & DCD_oldstate) == 0)
+								moxa_ports[p].DCDState = (DCD_oldstate |
 										   DCD_changed);
 						} else {
-							if (moxaDCDState[p] & DCD_oldstate)
-								moxaDCDState[p] = DCD_changed;
+							if (moxa_ports[p].DCDState & DCD_oldstate)
+								moxa_ports[p].DCDState = DCD_changed;
 						}
 					}
 				}
 			}
-			writeb(0, moxaIntPend[card]);
+			writeb(0, brd->intPend);
 		}
 		if (moxaLowWaterChk) {
 			p = card * MAX_PORTS_PER_BOARD;
 			for (port = 0; port < ports; port++, p++) {
-				if (moxaLowChkFlag[p]) {
-					moxaLowChkFlag[p] = 0;
-					ofsAddr = moxaTableAddr[p];
+				if (moxa_ports[p].lowChkFlag) {
+					moxa_ports[p].lowChkFlag = 0;
+					ofsAddr = moxa_ports[p].tableAddr;
 					low_water_check(ofsAddr);
 				}
 			}
@@ -1767,9 +1682,7 @@
  *	2.  MoxaPortEnable(int port);					     *
  *	3.  MoxaPortDisable(int port);					     *
  *	4.  MoxaPortGetMaxBaud(int port);				     *
- *	5.  MoxaPortGetCurBaud(int port);				     *
  *	6.  MoxaPortSetBaud(int port, long baud);			     *
- *	7.  MoxaPortSetMode(int port, int databit, int stopbit, int parity); *
  *	8.  MoxaPortSetTermio(int port, unsigned char *termio); 	     *
  *	9.  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);      *
  *	10. MoxaPortLineCtrl(int port, int dtrState, int rtsState);	     *
@@ -1780,18 +1693,12 @@
  *	15. MoxaPortFlushData(int port, int mode);	                     *
  *	16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
  *	17. MoxaPortReadData(int port, struct tty_struct *tty); 	     *
- *	18. MoxaPortTxBufSize(int port);				     *
- *	19. MoxaPortRxBufSize(int port);				     *
  *	20. MoxaPortTxQueue(int port);					     *
  *	21. MoxaPortTxFree(int port);					     *
  *	22. MoxaPortRxQueue(int port);					     *
- *	23. MoxaPortRxFree(int port);					     *
  *	24. MoxaPortTxDisable(int port);				     *
  *	25. MoxaPortTxEnable(int port); 				     *
- *	26. MoxaPortGetBrkCnt(int port);				     *
  *	27. MoxaPortResetBrkCnt(int port);				     *
- *	28. MoxaPortSetXonXoff(int port, int xonValue, int xoffValue);	     *
- *	29. MoxaPortIsTxHold(int port); 				     *
  *	30. MoxaPortSendBreak(int port, int ticks);			     *
  *****************************************************************************/
 /*
@@ -1878,15 +1785,6 @@
  *                      38400/57600/115200 bps
  *
  *
- *      Function 9:     Get the current baud rate of this port.
- *      Syntax:
- *      long MoxaPortGetCurBaud(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    0       : this port is invalid
- *                      50 - 115200 bps
- *
- *
  *      Function 10:    Setting baud rate of this port.
  *      Syntax:
  *      long MoxaPortSetBaud(int port, long baud);
@@ -1900,18 +1798,6 @@
  *                                    baud rate will be the maximun baud rate.
  *
  *
- *      Function 11:    Setting the data-bits/stop-bits/parity of this port
- *      Syntax:
- *      int  MoxaPortSetMode(int port, int databits, int stopbits, int parity);
- *           int port           : port number (0 - 127)
- *           int databits       : data bits (8/7/6/5)
- *           int stopbits       : stop bits (2/1/0, 0 show 1.5 stop bits)
- int parity     : parity (0:None,1:Odd,2:Even,3:Mark,4:Space)
- *
- *           return:    -1      : invalid parameter
- *                      0       : setting O.K.
- *
- *
  *      Function 12:    Configure the port.
  *      Syntax:
  *      int  MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud);
@@ -2016,22 +1902,6 @@
  *           return:    0 - length      : real read data length
  *
  *
- *      Function 22:    Get the Tx buffer size of this port
- *      Syntax:
- *      int  MoxaPortTxBufSize(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    ..      : Tx buffer size
- *
- *
- *      Function 23:    Get the Rx buffer size of this port
- *      Syntax:
- *      int  MoxaPortRxBufSize(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    ..      : Rx buffer size
- *
- *
  *      Function 24:    Get the Tx buffer current queued data bytes
  *      Syntax:
  *      int  MoxaPortTxQueue(int port);
@@ -2056,14 +1926,6 @@
  *           return:    ..      : Rx buffer current queued data bytes
  *
  *
- *      Function 27:    Get the Rx buffer current free space
- *      Syntax:
- *      int  MoxaPortRxFree(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    ..      : Rx buffer current free space
- *
- *
  *      Function 28:    Disable port data transmission.
  *      Syntax:
  *      void MoxaPortTxDisable(int port);
@@ -2076,14 +1938,6 @@
  *           int port           : port number (0 - 127)
  *
  *
- *      Function 30:    Get the received BREAK signal count.
- *      Syntax:
- *      int  MoxaPortGetBrkCnt(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    0 - ..  : BREAK signal count
- *
- *
  *      Function 31:    Get the received BREAK signal count and reset it.
  *      Syntax:
  *      int  MoxaPortResetBrkCnt(int port);
@@ -2092,25 +1946,6 @@
  *           return:    0 - ..  : BREAK signal count
  *
  *
- *      Function 32:    Set the S/W flow control new XON/XOFF value, default
- *                      XON is 0x11 & XOFF is 0x13.
- *      Syntax:
- *      void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue);
- *           int port           : port number (0 - 127)
- *           int xonValue       : new XON value (0 - 255)
- *           int xoffValue      : new XOFF value (0 - 255)
- *
- *
- *      Function 33:    Check this port's transmission is hold by remote site
- *                      because the flow control.
- *      Syntax:
- *      int  MoxaPortIsTxHold(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    0       : normal
- *                      1       : hold by remote site
- *
- *
  *      Function 34:    Send out a BREAK signal.
  *      Syntax:
  *      void MoxaPortSendBreak(int port, int ms100);
@@ -2125,7 +1960,7 @@
 
 	if (moxaCard == 0)
 		return (0);
-	if (moxaChkPort[port] == 0)
+	if (moxa_ports[port].chkPort == 0)
 		return (0);
 	return (1);
 }
@@ -2136,9 +1971,9 @@
 	int MoxaPortLineStatus(int);
 	short lowwater = 512;
 
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	writew(lowwater, ofsAddr + Low_water);
-	moxaBreakCnt[port] = 0;
+	moxa_ports[port].breakCnt = 0;
 	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
 	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
 		moxafunc(ofsAddr, FC_SetBreakIrq, 0);
@@ -2155,7 +1990,7 @@
 
 void MoxaPortDisable(int port)
 {
-	void __iomem *ofsAddr = moxaTableAddr[port];
+	void __iomem *ofsAddr = moxa_ports[port].tableAddr;
 
 	moxafunc(ofsAddr, FC_SetFlowCtl, 0);	/* disable flow control */
 	moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
@@ -2181,7 +2016,7 @@
 
 	if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0))
 		return (0);
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	if (baud > max)
 		baud = max;
 	if (max == 38400L)
@@ -2193,7 +2028,7 @@
 	val = clock / baud;
 	moxafunc(ofsAddr, FC_SetBaud, val);
 	baud = clock / val;
-	moxaCurBaud[port] = baud;
+	moxa_ports[port].curBaud = baud;
 	return (baud);
 }
 
@@ -2203,9 +2038,9 @@
 	tcflag_t cflag;
 	tcflag_t mode = 0;
 
-	if (moxaChkPort[port] == 0 || termio == 0)
+	if (moxa_ports[port].chkPort == 0 || termio == 0)
 		return (-1);
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	cflag = termio->c_cflag;	/* termio->c_cflag */
 
 	mode = termio->c_cflag & CSIZE;
@@ -2259,13 +2094,13 @@
 	if (!MoxaPortIsValid(port))
 		return (-1);
 	if (dtrState) {
-		if (moxaLineCtrl[port] & DTR_ON)
+		if (moxa_ports[port].lineCtrl & DTR_ON)
 			*dtrState = 1;
 		else
 			*dtrState = 0;
 	}
 	if (rtsState) {
-		if (moxaLineCtrl[port] & RTS_ON)
+		if (moxa_ports[port].lineCtrl & RTS_ON)
 			*rtsState = 1;
 		else
 			*rtsState = 0;
@@ -2278,13 +2113,13 @@
 	void __iomem *ofsAddr;
 	int mode;
 
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	mode = 0;
 	if (dtr)
 		mode |= DTR_ON;
 	if (rts)
 		mode |= RTS_ON;
-	moxaLineCtrl[port] = mode;
+	moxa_ports[port].lineCtrl = mode;
 	moxafunc(ofsAddr, FC_LineControl, mode);
 }
 
@@ -2293,7 +2128,7 @@
 	void __iomem *ofsAddr;
 	int mode;
 
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	mode = 0;
 	if (rts)
 		mode |= RTS_FlowCtl;
@@ -2313,7 +2148,7 @@
 	void __iomem *ofsAddr;
 	int val;
 
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
 	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
 		moxafunc(ofsAddr, FC_LineStatus, 0);
@@ -2324,11 +2159,11 @@
 	val &= 0x0B;
 	if (val & 8) {
 		val |= 4;
-		if ((moxaDCDState[port] & DCD_oldstate) == 0)
-			moxaDCDState[port] = (DCD_oldstate | DCD_changed);
+		if ((moxa_ports[port].DCDState & DCD_oldstate) == 0)
+			moxa_ports[port].DCDState = (DCD_oldstate | DCD_changed);
 	} else {
-		if (moxaDCDState[port] & DCD_oldstate)
-			moxaDCDState[port] = DCD_changed;
+		if (moxa_ports[port].DCDState & DCD_oldstate)
+			moxa_ports[port].DCDState = DCD_changed;
 	}
 	val &= 7;
 	return (val);
@@ -2338,10 +2173,10 @@
 {
 	int n;
 
-	if (moxaChkPort[port] == 0)
+	if (moxa_ports[port].chkPort == 0)
 		return (0);
-	n = moxaDCDState[port];
-	moxaDCDState[port] &= ~DCD_changed;
+	n = moxa_ports[port].DCDState;
+	moxa_ports[port].DCDState &= ~DCD_changed;
 	n &= DCD_changed;
 	return (n);
 }
@@ -2350,32 +2185,15 @@
 {
 	int n;
 
-	if (moxaChkPort[port] == 0)
+	if (moxa_ports[port].chkPort == 0)
 		return (0);
-	if (moxaDCDState[port] & DCD_oldstate)
+	if (moxa_ports[port].DCDState & DCD_oldstate)
 		n = 1;
 	else
 		n = 0;
 	return (n);
 }
 
-
-/*
-   int MoxaDumpMem(int port, unsigned char * buffer, int len)
-   {
-   int          i;
-   unsigned long                baseAddr,ofsAddr,ofs;
-
-   baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
-   ofs = baseAddr + DynPage_addr + pageofs;
-   if (len > 0x2000L)
-   len = 0x2000L;
-   for (i = 0; i < len; i++)
-   buffer[i] = readb(ofs+i);
-   }
- */
-
-
 int MoxaPortWriteData(int port, unsigned char * buffer, int len)
 {
 	int c, total, i;
@@ -2385,8 +2203,8 @@
 	ushort pageno, pageofs, bufhead;
 	void __iomem *baseAddr, *ofsAddr, *ofs;
 
-	ofsAddr = moxaTableAddr[port];
-	baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
+	ofsAddr = moxa_ports[port].tableAddr;
+	baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem;
 	tx_mask = readw(ofsAddr + TX_mask);
 	spage = readw(ofsAddr + Page_txb);
 	epage = readw(ofsAddr + EndPage_txb);
@@ -2448,8 +2266,8 @@
 	ushort pageno, bufhead;
 	void __iomem *baseAddr, *ofsAddr, *ofs;
 
-	ofsAddr = moxaTableAddr[port];
-	baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
+	ofsAddr = moxa_ports[port].tableAddr;
+	baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem;
 	head = readw(ofsAddr + RXrptr);
 	tail = readw(ofsAddr + RXwptr);
 	rx_mask = readw(ofsAddr + RX_mask);
@@ -2504,7 +2322,7 @@
 	}
 	if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) {
 		moxaLowWaterChk = 1;
-		moxaLowChkFlag[port] = 1;
+		moxa_ports[port].lowChkFlag = 1;
 	}
 	return (total);
 }
@@ -2516,7 +2334,7 @@
 	ushort rptr, wptr, mask;
 	int len;
 
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	rptr = readw(ofsAddr + TXrptr);
 	wptr = readw(ofsAddr + TXwptr);
 	mask = readw(ofsAddr + TX_mask);
@@ -2530,7 +2348,7 @@
 	ushort rptr, wptr, mask;
 	int len;
 
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	rptr = readw(ofsAddr + TXrptr);
 	wptr = readw(ofsAddr + TXwptr);
 	mask = readw(ofsAddr + TX_mask);
@@ -2544,7 +2362,7 @@
 	ushort rptr, wptr, mask;
 	int len;
 
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	rptr = readw(ofsAddr + RXrptr);
 	wptr = readw(ofsAddr + RXwptr);
 	mask = readw(ofsAddr + RX_mask);
@@ -2557,7 +2375,7 @@
 {
 	void __iomem *ofsAddr;
 
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	moxafunc(ofsAddr, FC_SetXoffState, Magic_code);
 }
 
@@ -2565,7 +2383,7 @@
 {
 	void __iomem *ofsAddr;
 
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	moxafunc(ofsAddr, FC_SetXonState, Magic_code);
 }
 
@@ -2573,8 +2391,8 @@
 int MoxaPortResetBrkCnt(int port)
 {
 	ushort cnt;
-	cnt = moxaBreakCnt[port];
-	moxaBreakCnt[port] = 0;
+	cnt = moxa_ports[port].breakCnt;
+	moxa_ports[port].breakCnt = 0;
 	return (cnt);
 }
 
@@ -2583,7 +2401,7 @@
 {
 	void __iomem *ofsAddr;
 
-	ofsAddr = moxaTableAddr[port];
+	ofsAddr = moxa_ports[port].tableAddr;
 	if (ms100) {
 		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
 		moxadelay(ms100 * (HZ / 10));
@@ -2594,7 +2412,7 @@
 	moxafunc(ofsAddr, FC_StopBreak, Magic_code);
 }
 
-static int moxa_get_serial_info(struct moxa_str *info,
+static int moxa_get_serial_info(struct moxa_port *info,
 				struct serial_struct __user *retinfo)
 {
 	struct serial_struct tmp;
@@ -2616,7 +2434,7 @@
 }
 
 
-static int moxa_set_serial_info(struct moxa_str *info,
+static int moxa_set_serial_info(struct moxa_port *info,
 				struct serial_struct __user *new_info)
 {
 	struct serial_struct new_serial;
@@ -2713,7 +2531,7 @@
 
 	if(copy_from_user(moxaBuff, tmp, len))
 		return -EFAULT;
-	baseAddr = moxaBaseAddr[cardno];
+	baseAddr = moxa_boards[cardno].basemem;
 	writeb(HW_reset, baseAddr + Control_reg);	/* reset */
 	moxadelay(1);		/* delay 10 ms */
 	for (i = 0; i < 4096; i++)
@@ -2729,7 +2547,7 @@
 	void __iomem *baseAddr;
 	ushort tmp;
 
-	baseAddr = moxaBaseAddr[cardno];
+	baseAddr = moxa_boards[cardno].basemem;
 	switch (moxa_boards[cardno].boardType) {
 	case MOXA_BOARD_C218_ISA:
 	case MOXA_BOARD_C218_PCI:
@@ -2762,7 +2580,7 @@
 		return -EINVAL;
 	if(copy_from_user(moxaBuff, tmp, len))
 		return -EFAULT;
-	baseAddr = moxaBaseAddr[cardno];
+	baseAddr = moxa_boards[cardno].basemem;
 	writew(len - 7168 - 2, baseAddr + C320bapi_len);
 	writeb(1, baseAddr + Control_reg);	/* Select Page 1 */
 	for (i = 0; i < 7168; i++)
@@ -2780,7 +2598,7 @@
 
 	if(copy_from_user(moxaBuff, tmp, len))
 		return -EFAULT;
-	baseAddr = moxaBaseAddr[cardno];
+	baseAddr = moxa_boards[cardno].basemem;
 	switch (moxa_boards[cardno].boardType) {
 	case MOXA_BOARD_C218_ISA:
 	case MOXA_BOARD_C218_PCI:
@@ -2790,11 +2608,13 @@
 			return (retval);
 		port = cardno * MAX_PORTS_PER_BOARD;
 		for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
-			moxaChkPort[port] = 1;
-			moxaCurBaud[port] = 9600L;
-			moxaDCDState[port] = 0;
-			moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i;
-			ofsAddr = moxaTableAddr[port];
+			struct moxa_port *p = &moxa_ports[port];
+
+			p->chkPort = 1;
+			p->curBaud = 9600L;
+			p->DCDState = 0;
+			p->tableAddr = baseAddr + Extern_table + Extern_size * i;
+			ofsAddr = p->tableAddr;
 			writew(C218rx_mask, ofsAddr + RX_mask);
 			writew(C218tx_mask, ofsAddr + TX_mask);
 			writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
@@ -2812,11 +2632,13 @@
 			return (retval);
 		port = cardno * MAX_PORTS_PER_BOARD;
 		for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
-			moxaChkPort[port] = 1;
-			moxaCurBaud[port] = 9600L;
-			moxaDCDState[port] = 0;
-			moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i;
-			ofsAddr = moxaTableAddr[port];
+			struct moxa_port *p = &moxa_ports[port];
+
+			p->chkPort = 1;
+			p->curBaud = 9600L;
+			p->DCDState = 0;
+			p->tableAddr = baseAddr + Extern_table + Extern_size * i;
+			ofsAddr = p->tableAddr;
 			if (moxa_boards[cardno].numPorts == 8) {
 				writew(C320p8rx_mask, ofsAddr + RX_mask);
 				writew(C320p8tx_mask, ofsAddr + TX_mask);
@@ -2852,7 +2674,7 @@
 		}
 		break;
 	}
-	loadstat[cardno] = 1;
+	moxa_boards[cardno].loadstat = 1;
 	return (0);
 }
 
@@ -2926,9 +2748,9 @@
 		return (-1);
 	}
 	moxaCard = 1;
-	moxaIntNdx[cardno] = baseAddr + IRQindex;
-	moxaIntPend[cardno] = baseAddr + IRQpending;
-	moxaIntTable[cardno] = baseAddr + IRQtable;
+	moxa_boards[cardno].intNdx = baseAddr + IRQindex;
+	moxa_boards[cardno].intPend = baseAddr + IRQpending;
+	moxa_boards[cardno].intTable = baseAddr + IRQtable;
 	return (0);
 }
 
@@ -3021,25 +2843,15 @@
 	if (readw(baseAddr + Magic_no) != Magic_code)
 		return (-102);
 	moxaCard = 1;
-	moxaIntNdx[cardno] = baseAddr + IRQindex;
-	moxaIntPend[cardno] = baseAddr + IRQpending;
-	moxaIntTable[cardno] = baseAddr + IRQtable;
+	moxa_boards[cardno].intNdx = baseAddr + IRQindex;
+	moxa_boards[cardno].intPend = baseAddr + IRQpending;
+	moxa_boards[cardno].intTable = baseAddr + IRQtable;
 	return (0);
 }
 
-#if 0
-long MoxaPortGetCurBaud(int port)
-{
-
-	if (moxaChkPort[port] == 0)
-		return (0);
-	return (moxaCurBaud[port]);
-}
-#endif  /*  0  */
-
 static void MoxaSetFifo(int port, int enable)
 {
-	void __iomem *ofsAddr = moxaTableAddr[port];
+	void __iomem *ofsAddr = moxa_ports[port].tableAddr;
 
 	if (!enable) {
 		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
@@ -3049,132 +2861,3 @@
 		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16);
 	}
 }
-
-#if 0
-int MoxaPortSetMode(int port, int databits, int stopbits, int parity)
-{
-	void __iomem *ofsAddr;
-	int val;
-
-	val = 0;
-	switch (databits) {
-	case 5:
-		val |= 0;
-		break;
-	case 6:
-		val |= 1;
-		break;
-	case 7:
-		val |= 2;
-		break;
-	case 8:
-		val |= 3;
-		break;
-	default:
-		return (-1);
-	}
-	switch (stopbits) {
-	case 0:
-		val |= 0;
-		break;		/* stop bits 1.5 */
-	case 1:
-		val |= 0;
-		break;
-	case 2:
-		val |= 4;
-		break;
-	default:
-		return (-1);
-	}
-	switch (parity) {
-	case 0:
-		val |= 0x00;
-		break;		/* None  */
-	case 1:
-		val |= 0x08;
-		break;		/* Odd   */
-	case 2:
-		val |= 0x18;
-		break;		/* Even  */
-	case 3:
-		val |= 0x28;
-		break;		/* Mark  */
-	case 4:
-		val |= 0x38;
-		break;		/* Space */
-	default:
-		return (-1);
-	}
-	ofsAddr = moxaTableAddr[port];
-	moxafunc(ofsAddr, FC_SetMode, val);
-	return (0);
-}
-
-int MoxaPortTxBufSize(int port)
-{
-	void __iomem *ofsAddr;
-	int size;
-
-	ofsAddr = moxaTableAddr[port];
-	size = readw(ofsAddr + TX_mask);
-	return (size);
-}
-
-int MoxaPortRxBufSize(int port)
-{
-	void __iomem *ofsAddr;
-	int size;
-
-	ofsAddr = moxaTableAddr[port];
-	size = readw(ofsAddr + RX_mask);
-	return (size);
-}
-
-int MoxaPortRxFree(int port)
-{
-	void __iomem *ofsAddr;
-	ushort rptr, wptr, mask;
-	int len;
-
-	ofsAddr = moxaTableAddr[port];
-	rptr = readw(ofsAddr + RXrptr);
-	wptr = readw(ofsAddr + RXwptr);
-	mask = readw(ofsAddr + RX_mask);
-	len = mask - ((wptr - rptr) & mask);
-	return (len);
-}
-int MoxaPortGetBrkCnt(int port)
-{
-	return (moxaBreakCnt[port]);
-}
-
-void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue)
-{
-	void __iomem *ofsAddr;
-
-	ofsAddr = moxaTableAddr[port];
-	writew(xonValue, ofsAddr + FuncArg);
-	writew(xoffValue, ofsAddr + FuncArg1);
-	writew(FC_SetXonXoff, ofsAddr + FuncCode);
-	wait_finish(ofsAddr);
-}
-
-int MoxaPortIsTxHold(int port)
-{
-	void __iomem *ofsAddr;
-	int val;
-
-	ofsAddr = moxaTableAddr[port];
-	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
-	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
-		moxafunc(ofsAddr, FC_GetCCSR, 0);
-		val = readw(ofsAddr + FuncArg);
-		if (val & 0x04)
-			return (1);
-	} else {
-		if (readw(ofsAddr + FlagStat) & Tx_flowOff)
-			return (1);
-	}
-	return (0);
-}
-#endif
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 235e892..7ac3061 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -291,7 +291,7 @@
 	return mspec_mmap(file, vma, MSPEC_UNCACHED);
 }
 
-static struct file_operations fetchop_fops = {
+static const struct file_operations fetchop_fops = {
 	.owner = THIS_MODULE,
 	.mmap = fetchop_mmap
 };
@@ -302,7 +302,7 @@
 	.fops = &fetchop_fops
 };
 
-static struct file_operations cached_fops = {
+static const struct file_operations cached_fops = {
 	.owner = THIS_MODULE,
 	.mmap = cached_mmap
 };
@@ -313,7 +313,7 @@
 	.fops = &cached_fops
 };
 
-static struct file_operations uncached_fops = {
+static const struct file_operations uncached_fops = {
 	.owner = THIS_MODULE,
 	.mmap = uncached_mmap
 };
diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c
index 4e4865e..492dbfb 100644
--- a/drivers/char/mwave/3780i.c
+++ b/drivers/char/mwave/3780i.c
@@ -63,8 +63,6 @@
 #include "3780i.h"
 
 static DEFINE_SPINLOCK(dsp_lock);
-static unsigned long flags;
-
 
 static void PaceMsaAccess(unsigned short usDspBaseIO)
 {
@@ -76,6 +74,7 @@
 unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
                                    unsigned long ulMsaAddr)
 {
+	unsigned long flags;
 	unsigned short val;
 
 	PRINTK_3(TRACE_3780I,
@@ -96,6 +95,7 @@
 void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
                           unsigned long ulMsaAddr, unsigned short usValue)
 {
+	unsigned long flags;
 
 	PRINTK_4(TRACE_3780I,
 		"3780i::dsp3780i_WriteMsaCfg entry usDspBaseIO %x ulMsaAddr %lx usValue %x\n",
@@ -175,6 +175,7 @@
                        unsigned short *pIrqMap,
                        unsigned short *pDmaMap)
 {
+	unsigned long flags;
 	unsigned short usDspBaseIO = pSettings->usDspBaseIO;
 	int i;
 	DSP_UART_CFG_1 rUartCfg1;
@@ -354,6 +355,7 @@
 
 int dsp3780I_DisableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings)
 {
+	unsigned long flags;
 	unsigned short usDspBaseIO = pSettings->usDspBaseIO;
 	DSP_ISA_SLAVE_CONTROL rSlaveControl;
 
@@ -383,6 +385,7 @@
 
 int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings)
 {
+	unsigned long flags;
 	unsigned short usDspBaseIO = pSettings->usDspBaseIO;
 	DSP_BOOT_DOMAIN rBootDomain;
 	DSP_HBRIDGE_CONTROL rHBridgeControl;
@@ -427,6 +430,7 @@
 
 int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings)
 {
+	unsigned long flags;
 	unsigned short usDspBaseIO = pSettings->usDspBaseIO;
 	DSP_BOOT_DOMAIN rBootDomain;
 	DSP_HBRIDGE_CONTROL rHBridgeControl;
@@ -473,6 +477,7 @@
 int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                         unsigned uCount, unsigned long ulDSPAddr)
 {
+	unsigned long flags;
 	unsigned short __user *pusBuffer = pvBuffer;
 	unsigned short val;
 
@@ -514,6 +519,7 @@
                                 void __user *pvBuffer, unsigned uCount,
                                 unsigned long ulDSPAddr)
 {
+	unsigned long flags;
 	unsigned short __user *pusBuffer = pvBuffer;
 	unsigned short val;
 
@@ -555,6 +561,7 @@
 int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                          unsigned uCount, unsigned long ulDSPAddr)
 {
+	unsigned long flags;
 	unsigned short __user *pusBuffer = pvBuffer;
 
 
@@ -596,6 +603,7 @@
 int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                         unsigned uCount, unsigned long ulDSPAddr)
 {
+	unsigned long flags;
 	unsigned short __user *pusBuffer = pvBuffer;
 
 	PRINTK_5(TRACE_3780I,
@@ -643,6 +651,7 @@
 int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                          unsigned uCount, unsigned long ulDSPAddr)
 {
+	unsigned long flags;
 	unsigned short __user *pusBuffer = pvBuffer;
 
 	PRINTK_5(TRACE_3780I,
@@ -691,6 +700,7 @@
 int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
                           unsigned short *pusIPCSource)
 {
+	unsigned long flags;
 	DSP_HBRIDGE_CONTROL rHBridgeControl;
 	unsigned short temp;
 
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 83f604b..a61fb6d 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -321,8 +321,6 @@
 	unsigned long event;
 	int count;		/* # of fd on device */
 	int blocked_open;	/* # of blocked opens */
-	long session;		/* Session of opening process */
-	long pgrp;		/* pgrp of opening process */
 	unsigned char *xmit_buf;
 	int xmit_head;
 	int xmit_tail;
@@ -1001,15 +999,12 @@
 		mxser_change_speed(info, NULL);
 	}
 
-	info->session = process_session(current);
-	info->pgrp = process_group(current);
-
 	/*
 	status = mxser_get_msr(info->base, 0, info->port);
 	mxser_check_modem_status(info, status);
 	*/
 
-/* unmark here for very high baud rate (ex. 921600 bps) used */
+	/* unmark here for very high baud rate (ex. 921600 bps) used */
 	tty->low_latency = 1;
 	return 0;
 }
@@ -1254,9 +1249,7 @@
 	spin_unlock_irqrestore(&info->slock, flags);
 	/* above added by shinhay */
 
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 }
 
 static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h
index 7e188a4..9fe2849 100644
--- a/drivers/char/mxser.h
+++ b/drivers/char/mxser.h
@@ -439,12 +439,4 @@
 
 #define READ_MOXA_MUST_GDL(baseio)	inb((baseio)+MOXA_MUST_GDL_REGISTER)
 
-
-#ifndef INIT_WORK
-#define INIT_WORK(_work, _func, _data){	\
-	_data->tqueue.routine = _func;\
-	_data->tqueue.data = _data;\
-	}
-#endif
-
 #endif
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index 1bb030b..9af07e4 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -49,22 +49,25 @@
 
 #include "mxser_new.h"
 
-#define	MXSER_VERSION	"2.0"
+#define	MXSER_VERSION	"2.0.1"		/* 1.9.15 */
 #define	MXSERMAJOR	 174
 #define	MXSERCUMAJOR	 175
 
-#define	MXSER_EVENT_TXLOW	1
-
 #define MXSER_BOARDS		4	/* Max. boards */
 #define MXSER_PORTS_PER_BOARD	8	/* Max. ports per board */
 #define MXSER_PORTS		(MXSER_BOARDS * MXSER_PORTS_PER_BOARD)
-#define MXSER_ISR_PASS_LIMIT	99999L
+#define MXSER_ISR_PASS_LIMIT	100
 
 #define	MXSER_ERR_IOADDR	-1
 #define	MXSER_ERR_IRQ		-2
 #define	MXSER_ERR_IRQ_CONFLIT	-3
 #define	MXSER_ERR_VECTOR	-4
 
+/*CheckIsMoxaMust return value*/
+#define MOXA_OTHER_UART		0x00
+#define MOXA_MUST_MU150_HWID	0x01
+#define MOXA_MUST_MU860_HWID	0x02
+
 #define WAKEUP_CHARS		256
 
 #define UART_MCR_AFE		0x20
@@ -176,6 +179,18 @@
 };
 MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
 
+static int mxvar_baud_table[] = {
+	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
+	4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
+};
+static unsigned int mxvar_baud_table1[] = {
+	0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400,
+	B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B921600
+};
+#define BAUD_TABLE_NO ARRAY_SIZE(mxvar_baud_table)
+
+#define B_SPEC	B2000000
+
 static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };
 static int ttymajor = MXSERMAJOR;
 static int calloutmajor = MXSERCUMAJOR;
@@ -237,8 +252,7 @@
 	long realbaud;
 	int type;		/* UART type */
 	int flags;		/* defined in tty.h */
-	long session;		/* Session of opening process */
-	long pgrp;		/* pgrp of opening process */
+	int speed;
 
 	int x_char;		/* xon/xoff character */
 	int IER;		/* Interrupt Enable Register */
@@ -267,14 +281,11 @@
 	int xmit_cnt;
 
 	struct ktermios normal_termios;
-	struct ktermios callout_termios;
 
 	struct mxser_mon mon_data;
 
 	spinlock_t slock;
-	struct work_struct tqueue;
 	wait_queue_head_t open_wait;
-	wait_queue_head_t close_wait;
 	wait_queue_head_t delta_msr_wait;
 };
 
@@ -313,10 +324,9 @@
 static unsigned char mxser_msr[MXSER_PORTS + 1];
 static struct mxser_mon_ext mon_data_ext;
 static int mxser_set_baud_method[MXSER_PORTS + 1];
-static spinlock_t gm_lock;
 
 #ifdef CONFIG_PCI
-static int CheckIsMoxaMust(int io)
+static int __devinit CheckIsMoxaMust(int io)
 {
 	u8 oldmcr, hwid;
 	int i;
@@ -360,15 +370,6 @@
 			}
 }
 
-static void mxser_do_softint(struct work_struct *work)
-{
-	struct mxser_port *info = container_of(work, struct mxser_port, tqueue);
-	struct tty_struct *tty = info->tty;
-
-	if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event))
-		tty_wakeup(tty);
-}
-
 static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
 {
 	unsigned char status = 0;
@@ -456,10 +457,10 @@
 
 static int mxser_set_baud(struct mxser_port *info, long newspd)
 {
+	unsigned int i;
 	int quot = 0;
 	unsigned char cval;
 	int ret = 0;
-	unsigned long flags;
 
 	if (!info->tty || !info->tty->termios)
 		return ret;
@@ -471,29 +472,34 @@
 		return 0;
 
 	info->realbaud = newspd;
-	if (newspd == 134) {
-		quot = (2 * info->baud_base / 269);
-	} else if (newspd) {
-		quot = info->baud_base / newspd;
-		if (quot == 0)
-			quot = 1;
+	for (i = 0; i < BAUD_TABLE_NO; i++)
+	       if (newspd == mxvar_baud_table[i])
+		       break;
+	if (i == BAUD_TABLE_NO) {
+		quot = info->baud_base / info->speed;
+		if (info->speed <= 0 || info->speed > info->max_baud)
+			quot = 0;
 	} else {
-		quot = 0;
+		if (newspd == 134) {
+			quot = (2 * info->baud_base / 269);
+		} else if (newspd) {
+			quot = info->baud_base / newspd;
+			if (quot == 0)
+				quot = 1;
+		} else {
+			quot = 0;
+		}
 	}
 
 	info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base);
 	info->timeout += HZ / 50;	/* Add .02 seconds of slop */
 
 	if (quot) {
-		spin_lock_irqsave(&info->slock, flags);
 		info->MCR |= UART_MCR_DTR;
 		outb(info->MCR, info->ioaddr + UART_MCR);
-		spin_unlock_irqrestore(&info->slock, flags);
 	} else {
-		spin_lock_irqsave(&info->slock, flags);
 		info->MCR &= ~UART_MCR_DTR;
 		outb(info->MCR, info->ioaddr + UART_MCR);
-		spin_unlock_irqrestore(&info->slock, flags);
 		return ret;
 	}
 
@@ -505,6 +511,18 @@
 	outb(quot >> 8, info->ioaddr + UART_DLM);	/* MS of divisor */
 	outb(cval, info->ioaddr + UART_LCR);	/* reset DLAB */
 
+	if (i == BAUD_TABLE_NO) {
+		quot = info->baud_base % info->speed;
+		quot *= 8;
+		if ((quot % info->speed) > (info->speed / 2)) {
+			quot /= info->speed;
+			quot++;
+		} else {
+			quot /= info->speed;
+		}
+		SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, quot);
+	} else
+		SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, 0);
 
 	return ret;
 }
@@ -520,7 +538,6 @@
 	int ret = 0;
 	unsigned char status;
 	long baud;
-	unsigned long flags;
 
 	if (!info->tty || !info->tty->termios)
 		return ret;
@@ -529,7 +546,10 @@
 		return ret;
 
 	if (mxser_set_baud_method[info->tty->index] == 0) {
-		baud = tty_get_baud_rate(info->tty);
+		if ((cflag & CBAUD) == B_SPEC)
+			baud = info->speed;
+		else
+			baud = tty_get_baud_rate(info->tty);
 		mxser_set_baud(info, baud);
 	}
 
@@ -612,8 +632,8 @@
 						outb(info->IER, info->ioaddr +
 								UART_IER);
 					}
-					set_bit(MXSER_EVENT_TXLOW, &info->event);
-					schedule_work(&info->tqueue);				}
+					tty_wakeup(info->tty);
+				}
 			} else {
 				if (!(status & UART_MSR_CTS)) {
 					info->tty->hw_stopped = 1;
@@ -668,7 +688,6 @@
 		}
 	}
 	if (info->board->chip_flag) {
-		spin_lock_irqsave(&info->slock, flags);
 		SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty));
 		SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty));
 		if (I_IXON(info->tty)) {
@@ -681,7 +700,6 @@
 		} else {
 			DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
 		}
-		spin_unlock_irqrestore(&info->slock, flags);
 	}
 
 
@@ -708,7 +726,6 @@
 	if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
 		if (status & UART_MSR_DCD)
 			wake_up_interruptible(&port->open_wait);
-		schedule_work(&port->tqueue);
 	}
 
 	if (port->flags & ASYNC_CTS_FLOW) {
@@ -724,8 +741,7 @@
 					outb(port->IER, port->ioaddr +
 							UART_IER);
 				}
-				set_bit(MXSER_EVENT_TXLOW, &port->event);
-				schedule_work(&port->tqueue);
+				tty_wakeup(port->tty);
 			}
 		} else {
 			if (!(status & UART_MSR_CTS)) {
@@ -836,10 +852,10 @@
 	/*
 	 * and set the speed of the serial port
 	 */
-	spin_unlock_irqrestore(&info->slock, flags);
 	mxser_change_speed(info, NULL);
-
 	info->flags |= ASYNC_INITIALIZED;
+	spin_unlock_irqrestore(&info->slock, flags);
+
 	return 0;
 }
 
@@ -909,11 +925,9 @@
 static int mxser_open(struct tty_struct *tty, struct file *filp)
 {
 	struct mxser_port *info;
+	unsigned long flags;
 	int retval, line;
 
-	/* initialize driver_data in case something fails */
-	tty->driver_data = NULL;
-
 	line = tty->index;
 	if (line == MXSER_PORTS)
 		return 0;
@@ -928,7 +942,9 @@
 	/*
 	 * Start up serial port
 	 */
+	spin_lock_irqsave(&info->slock, flags);
 	info->count++;
+	spin_unlock_irqrestore(&info->slock, flags);
 	retval = mxser_startup(info);
 	if (retval)
 		return retval;
@@ -937,17 +953,6 @@
 	if (retval)
 		return retval;
 
-	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		if (tty->driver->subtype == SERIAL_TYPE_NORMAL)
-			*tty->termios = info->normal_termios;
-		else
-			*tty->termios = info->callout_termios;
-		mxser_change_speed(info, NULL);
-	}
-
-	info->session = process_session(current);
-	info->pgrp = process_group(current);
-
 	/* unmark here for very high baud rate (ex. 921600 bps) used */
 	tty->low_latency = 1;
 	return 0;
@@ -1054,8 +1059,6 @@
 	}
 
 	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
-	wake_up_interruptible(&info->close_wait);
-
 }
 
 static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -1222,6 +1225,7 @@
 		struct serial_struct __user *new_info)
 {
 	struct serial_struct new_serial;
+	unsigned long sl_flags;
 	unsigned int flags;
 	int retval = 0;
 
@@ -1264,8 +1268,11 @@
 	process_txrx_fifo(info);
 
 	if (info->flags & ASYNC_INITIALIZED) {
-		if (flags != (info->flags & ASYNC_SPD_MASK))
+		if (flags != (info->flags & ASYNC_SPD_MASK)) {
+			spin_lock_irqsave(&info->slock, sl_flags);
 			mxser_change_speed(info, NULL);
+			spin_unlock_irqrestore(&info->slock, sl_flags);
+		}
 	} else
 		retval = mxser_startup(info);
 
@@ -1373,11 +1380,10 @@
 	return 0;
 }
 
-static int mxser_program_mode(int port)
+static int __init mxser_program_mode(int port)
 {
 	int id, i, j, n;
 
-	spin_lock(&gm_lock);
 	outb(0, port);
 	outb(0, port);
 	outb(0, port);
@@ -1385,7 +1391,6 @@
 	(void)inb(port);
 	outb(0, port);
 	(void)inb(port);
-	spin_unlock(&gm_lock);
 
 	id = inb(port + 1) & 0x1F;
 	if ((id != C168_ASIC_ID) &&
@@ -1410,7 +1415,7 @@
 	return id;
 }
 
-static void mxser_normal_mode(int port)
+static void __init mxser_normal_mode(int port)
 {
 	int i, n;
 
@@ -1443,7 +1448,7 @@
 #define EN0_PORT	0x010	/* Rcv missed frame error counter RD */
 #define ENC_PAGE0	0x000	/* Select page 0 of chip registers   */
 #define ENC_PAGE3	0x0C0	/* Select page 3 of chip registers   */
-static int mxser_read_register(int port, unsigned short *regs)
+static int __init mxser_read_register(int port, unsigned short *regs)
 {
 	int i, k, value, id;
 	unsigned int j;
@@ -1644,6 +1649,7 @@
 	struct serial_icounter_struct __user *p_cuser;
 	unsigned long templ;
 	unsigned long flags;
+	unsigned int i;
 	void __user *argp = (void __user *)arg;
 	int retval;
 
@@ -1682,6 +1688,36 @@
 		return 0;
 	}
 
+	if (cmd == MOXA_SET_SPECIAL_BAUD_RATE) {
+		int speed;
+
+		if (get_user(speed, (int __user *)argp))
+			return -EFAULT;
+		if (speed <= 0 || speed > info->max_baud)
+			return -EFAULT;
+		if (!info->tty || !info->tty->termios || !info->ioaddr)
+			return 0;
+		info->tty->termios->c_cflag &= ~(CBAUD | CBAUDEX);
+		for (i = 0; i < BAUD_TABLE_NO; i++)
+			if (speed == mxvar_baud_table[i])
+				break;
+		if (i == BAUD_TABLE_NO) {
+			info->tty->termios->c_cflag |= B_SPEC;
+		} else if (speed != 0)
+			info->tty->termios->c_cflag |= mxvar_baud_table1[i];
+
+		info->speed = speed;
+		spin_lock_irqsave(&info->slock, flags);
+		mxser_change_speed(info, NULL);
+		spin_unlock_irqrestore(&info->slock, flags);
+
+		return 0;
+	} else if (cmd == MOXA_GET_SPECIAL_BAUD_RATE) {
+		if (copy_to_user(argp, &info->speed, sizeof(int)))
+		     return -EFAULT;
+		return 0;
+	}
+
 	if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
 			test_bit(TTY_IO_ERROR, &tty->flags))
 		return -EIO;
@@ -1799,7 +1835,9 @@
 		long baud;
 		if (get_user(baud, (long __user *)argp))
 			return -EFAULT;
+		spin_lock_irqsave(&info->slock, flags);
 		mxser_set_baud(info, baud);
+		spin_unlock_irqrestore(&info->slock, flags);
 		return 0;
 	}
 	case MOXA_ASPP_GETBAUD:
@@ -1976,7 +2014,9 @@
 	if ((tty->termios->c_cflag != old_termios->c_cflag) ||
 			(RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
 
+		spin_lock_irqsave(&info->slock, flags);
 		mxser_change_speed(info, old_termios);
+		spin_unlock_irqrestore(&info->slock, flags);
 
 		if ((old_termios->c_cflag & CRTSCTS) &&
 				!(tty->termios->c_cflag & CRTSCTS)) {
@@ -2066,7 +2106,7 @@
 /*
  * This routine is called by tty_hangup() when a hangup is signaled.
  */
-void mxser_hangup(struct tty_struct *tty)
+static void mxser_hangup(struct tty_struct *tty)
 {
 	struct mxser_port *info = tty->driver_data;
 
@@ -2105,9 +2145,6 @@
 	int cnt = 0;
 	int recv_room;
 	int max = 256;
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->slock, flags);
 
 	recv_room = tty->receive_room;
 	if ((recv_room == 0) && (!port->ldisc_stop_rx))
@@ -2169,7 +2206,8 @@
 				} else if (*status & UART_LSR_OE) {
 					flag = TTY_OVERRUN;
 					port->icount.overrun++;
-				}
+				} else
+					flag = TTY_BREAK;
 			}
 			tty_insert_flip_char(tty, ch, flag);
 			cnt++;
@@ -2191,7 +2229,6 @@
 	mxvar_log.rxcnt[port->tty->index] += cnt;
 	port->mon_data.rxcnt += cnt;
 	port->mon_data.up_rxcnt += cnt;
-	spin_unlock_irqrestore(&port->slock, flags);
 
 	tty_flip_buffer_push(tty);
 }
@@ -2199,9 +2236,6 @@
 static void mxser_transmit_chars(struct mxser_port *port)
 {
 	int count, cnt;
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->slock, flags);
 
 	if (port->x_char) {
 		outb(port->x_char, port->ioaddr + UART_TX);
@@ -2210,11 +2244,11 @@
 		port->mon_data.txcnt++;
 		port->mon_data.up_txcnt++;
 		port->icount.tx++;
-		goto unlock;
+		return;
 	}
 
 	if (port->xmit_buf == 0)
-		goto unlock;
+		return;
 
 	if ((port->xmit_cnt <= 0) || port->tty->stopped ||
 			(port->tty->hw_stopped &&
@@ -2222,7 +2256,7 @@
 			(!port->board->chip_flag))) {
 		port->IER &= ~UART_IER_THRI;
 		outb(port->IER, port->ioaddr + UART_IER);
-		goto unlock;
+		return;
 	}
 
 	cnt = port->xmit_cnt;
@@ -2240,16 +2274,13 @@
 	port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
 	port->icount.tx += (cnt - port->xmit_cnt);
 
-	if (port->xmit_cnt < WAKEUP_CHARS) {
-		set_bit(MXSER_EVENT_TXLOW, &port->event);
-		schedule_work(&port->tqueue);
-	}
+	if (port->xmit_cnt < WAKEUP_CHARS)
+		tty_wakeup(port->tty);
+
 	if (port->xmit_cnt <= 0) {
 		port->IER &= ~UART_IER_THRI;
 		outb(port->IER, port->ioaddr + UART_IER);
 	}
-unlock:
-	spin_unlock_irqrestore(&port->slock, flags);
 }
 
 /*
@@ -2261,8 +2292,7 @@
 	struct mxser_board *brd = NULL;
 	struct mxser_port *port;
 	int max, irqbits, bits, msr;
-	int pass_counter = 0;
-	unsigned int int_cnt;
+	unsigned int int_cnt, pass_counter = 0;
 	int handled = IRQ_NONE;
 
 	for (i = 0; i < MXSER_BOARDS; i++)
@@ -2276,7 +2306,7 @@
 	if (brd == NULL)
 		goto irq_stop;
 	max = brd->info->nports;
-	while (1) {
+	while (pass_counter++ < MXSER_ISR_PASS_LIMIT) {
 		irqbits = inb(brd->vector) & brd->vector_mask;
 		if (irqbits == brd->vector_mask)
 			break;
@@ -2290,12 +2320,16 @@
 			port = &brd->ports[i];
 
 			int_cnt = 0;
+			spin_lock(&port->slock);
 			do {
 				iir = inb(port->ioaddr + UART_IIR);
 				if (iir & UART_IIR_NO_INT)
 					break;
 				iir &= MOXA_MUST_IIR_MASK;
-				if (!port->tty) {
+				if (!port->tty ||
+						(port->flags & ASYNC_CLOSING) ||
+						!(port->flags &
+							ASYNC_INITIALIZED)) {
 					status = inb(port->ioaddr + UART_LSR);
 					outb(0x27, port->ioaddr + UART_FCR);
 					inb(port->ioaddr + UART_MSR);
@@ -2341,9 +2375,8 @@
 						mxser_transmit_chars(port);
 				}
 			} while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
+			spin_unlock(&port->slock);
 		}
-		if (pass_counter++ > MXSER_ISR_PASS_LIMIT)
-			break;	/* Prevent infinite loops */
 	}
 
 irq_stop:
@@ -2385,7 +2418,6 @@
 #ifdef CONFIG_PCI
 		pci_release_region(pdev, 2);
 		pci_release_region(pdev, 3);
-		pci_dev_put(pdev);
 #endif
 	} else {
 		release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
@@ -2420,11 +2452,10 @@
 		info->custom_divisor = info->baud_base * 16;
 		info->close_delay = 5 * HZ / 10;
 		info->closing_wait = 30 * HZ;
-		INIT_WORK(&info->tqueue, mxser_do_softint);
 		info->normal_termios = mxvar_sdriver->init_termios;
 		init_waitqueue_head(&info->open_wait);
-		init_waitqueue_head(&info->close_wait);
 		init_waitqueue_head(&info->delta_msr_wait);
+		info->speed = 9600;
 		memset(&info->mon_data, 0, sizeof(struct mxser_mon));
 		info->err_shadow = 0;
 		spin_lock_init(&info->slock);
@@ -2433,22 +2464,17 @@
 		outb(inb(info->ioaddr + UART_IER) & 0xf0,
 			info->ioaddr + UART_IER);
 	}
-	/*
-	 * Allocate the IRQ if necessary
-	 */
 
-	retval = request_irq(brd->irq, mxser_interrupt,
-			(brd->ports[0].flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED :
-			IRQF_DISABLED, "mxser", brd);
+	retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
+			brd);
 	if (retval) {
 		printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
 			"conflict with another device.\n",
 			brd->info->name, brd->irq);
 		/* We hold resources, we need to release them. */
 		mxser_release_res(brd, pdev, 0);
-		return retval;
 	}
-	return 0;
+	return retval;
 }
 
 static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
@@ -2633,8 +2659,9 @@
 	}
 
 	/* mxser_initbrd will hook ISR. */
-	if (mxser_initbrd(brd, pdev) < 0)
-		goto err_relvec;
+	retval = mxser_initbrd(brd, pdev);
+	if (retval)
+		goto err_null;
 
 	for (i = 0; i < brd->info->nports; i++)
 		tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
@@ -2642,10 +2669,9 @@
 	pci_set_drvdata(pdev, brd);
 
 	return 0;
-err_relvec:
-	pci_release_region(pdev, 3);
 err_relio:
 	pci_release_region(pdev, 2);
+err_null:
 	brd->info = NULL;
 err:
 	return retval;
@@ -2663,6 +2689,7 @@
 		tty_unregister_device(mxvar_sdriver, brd->idx + i);
 
 	mxser_release_res(brd, pdev, 1);
+	brd->info = NULL;
 }
 
 static struct pci_driver mxser_driver = {
@@ -2684,7 +2711,6 @@
 	mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);
 	if (!mxvar_sdriver)
 		return -ENOMEM;
-	spin_lock_init(&gm_lock);
 
 	printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n",
 		MXSER_VERSION);
diff --git a/drivers/char/mxser_new.h b/drivers/char/mxser_new.h
index a08f0ec..d42f776 100644
--- a/drivers/char/mxser_new.h
+++ b/drivers/char/mxser_new.h
@@ -26,18 +26,8 @@
 #define RS422_MODE		2
 #define RS485_4WIRE_MODE	3
 #define OP_MODE_MASK		3
-// above add by Victor Yu. 01-05-2004
 
-#define TTY_THRESHOLD_THROTTLE  128
-
-#define LO_WATER	 	(TTY_FLIPBUF_SIZE)
-#define HI_WATER		(TTY_FLIPBUF_SIZE*2*3/4)
-
-// added by James. 03-11-2004.
-#define MOXA_SDS_GETICOUNTER  	(MOXA + 68)
-#define MOXA_SDS_RSTICOUNTER  	(MOXA + 69)
-// (above) added by James.
-
+#define MOXA_SDS_RSTICOUNTER	(MOXA + 69)
 #define MOXA_ASPP_OQUEUE  	(MOXA + 70)
 #define MOXA_ASPP_SETBAUD 	(MOXA + 71)
 #define MOXA_ASPP_GETBAUD 	(MOXA + 72)
@@ -45,7 +35,8 @@
 #define MOXA_ASPP_LSTATUS 	(MOXA + 74)
 #define MOXA_ASPP_MON_EXT 	(MOXA + 75)
 #define MOXA_SET_BAUD_METHOD	(MOXA + 76)
-
+#define MOXA_SET_SPECIAL_BAUD_RATE	(MOXA + 77)
+#define MOXA_GET_SPECIAL_BAUD_RATE	(MOXA + 78)
 
 /* --------------------------------------------------- */
 
@@ -55,51 +46,46 @@
 #define NPPI_NOTIFY_SW_OVERRUN	0x08
 #define NPPI_NOTIFY_BREAK	0x10
 
-#define NPPI_NOTIFY_CTSHOLD         0x01	// Tx hold by CTS low
-#define NPPI_NOTIFY_DSRHOLD         0x02	// Tx hold by DSR low
-#define NPPI_NOTIFY_XOFFHOLD        0x08	// Tx hold by Xoff received
-#define NPPI_NOTIFY_XOFFXENT        0x10	// Xoff Sent
+#define NPPI_NOTIFY_CTSHOLD         0x01	/* Tx hold by CTS low */
+#define NPPI_NOTIFY_DSRHOLD         0x02	/* Tx hold by DSR low */
+#define NPPI_NOTIFY_XOFFHOLD        0x08	/* Tx hold by Xoff received */
+#define NPPI_NOTIFY_XOFFXENT        0x10	/* Xoff Sent */
 
-//CheckIsMoxaMust return value
-#define MOXA_OTHER_UART			0x00
-#define MOXA_MUST_MU150_HWID		0x01
-#define MOXA_MUST_MU860_HWID		0x02
-
-// follow just for Moxa Must chip define.
-//
-// when LCR register (offset 0x03) write following value,
-// the Must chip will enter enchance mode. And write value
-// on EFR (offset 0x02) bit 6,7 to change bank.
+/* follow just for Moxa Must chip define. */
+/* */
+/* when LCR register (offset 0x03) write following value, */
+/* the Must chip will enter enchance mode. And write value */
+/* on EFR (offset 0x02) bit 6,7 to change bank. */
 #define MOXA_MUST_ENTER_ENCHANCE	0xBF
 
-// when enhance mode enable, access on general bank register
+/* when enhance mode enable, access on general bank register */
 #define MOXA_MUST_GDL_REGISTER		0x07
 #define MOXA_MUST_GDL_MASK		0x7F
 #define MOXA_MUST_GDL_HAS_BAD_DATA	0x80
 
-#define MOXA_MUST_LSR_RERR		0x80	// error in receive FIFO
-// enchance register bank select and enchance mode setting register
-// when LCR register equal to 0xBF
+#define MOXA_MUST_LSR_RERR		0x80	/* error in receive FIFO */
+/* enchance register bank select and enchance mode setting register */
+/* when LCR register equal to 0xBF */
 #define MOXA_MUST_EFR_REGISTER		0x02
-// enchance mode enable
+/* enchance mode enable */
 #define MOXA_MUST_EFR_EFRB_ENABLE	0x10
-// enchance reister bank set 0, 1, 2
+/* enchance reister bank set 0, 1, 2 */
 #define MOXA_MUST_EFR_BANK0		0x00
 #define MOXA_MUST_EFR_BANK1		0x40
 #define MOXA_MUST_EFR_BANK2		0x80
 #define MOXA_MUST_EFR_BANK3		0xC0
 #define MOXA_MUST_EFR_BANK_MASK		0xC0
 
-// set XON1 value register, when LCR=0xBF and change to bank0
+/* set XON1 value register, when LCR=0xBF and change to bank0 */
 #define MOXA_MUST_XON1_REGISTER		0x04
 
-// set XON2 value register, when LCR=0xBF and change to bank0
+/* set XON2 value register, when LCR=0xBF and change to bank0 */
 #define MOXA_MUST_XON2_REGISTER		0x05
 
-// set XOFF1 value register, when LCR=0xBF and change to bank0
+/* set XOFF1 value register, when LCR=0xBF and change to bank0 */
 #define MOXA_MUST_XOFF1_REGISTER	0x06
 
-// set XOFF2 value register, when LCR=0xBF and change to bank0
+/* set XOFF2 value register, when LCR=0xBF and change to bank0 */
 #define MOXA_MUST_XOFF2_REGISTER	0x07
 
 #define MOXA_MUST_RBRTL_REGISTER	0x04
@@ -111,32 +97,32 @@
 #define MOXA_MUST_ECR_REGISTER		0x06
 #define MOXA_MUST_CSR_REGISTER		0x07
 
-// good data mode enable
+/* good data mode enable */
 #define MOXA_MUST_FCR_GDA_MODE_ENABLE	0x20
-// only good data put into RxFIFO
+/* only good data put into RxFIFO */
 #define MOXA_MUST_FCR_GDA_ONLY_ENABLE	0x10
 
-// enable CTS interrupt
+/* enable CTS interrupt */
 #define MOXA_MUST_IER_ECTSI		0x80
-// enable RTS interrupt
+/* enable RTS interrupt */
 #define MOXA_MUST_IER_ERTSI		0x40
-// enable Xon/Xoff interrupt
+/* enable Xon/Xoff interrupt */
 #define MOXA_MUST_IER_XINT		0x20
-// enable GDA interrupt
+/* enable GDA interrupt */
 #define MOXA_MUST_IER_EGDAI		0x10
 
 #define MOXA_MUST_RECV_ISR		(UART_IER_RDI | MOXA_MUST_IER_EGDAI)
 
-// GDA interrupt pending
+/* GDA interrupt pending */
 #define MOXA_MUST_IIR_GDA		0x1C
 #define MOXA_MUST_IIR_RDA		0x04
 #define MOXA_MUST_IIR_RTO		0x0C
 #define MOXA_MUST_IIR_LSR		0x06
 
-// recieved Xon/Xoff or specical interrupt pending
+/* recieved Xon/Xoff or specical interrupt pending */
 #define MOXA_MUST_IIR_XSC		0x10
 
-// RTS/CTS change state interrupt pending
+/* RTS/CTS change state interrupt pending */
 #define MOXA_MUST_IIR_RTSCTS		0x20
 #define MOXA_MUST_IIR_MASK		0x3E
 
@@ -144,307 +130,164 @@
 #define MOXA_MUST_MCR_XON_ANY		0x80
 #define MOXA_MUST_MCR_TX_XON		0x08
 
-
-// software flow control on chip mask value
+/* software flow control on chip mask value */
 #define MOXA_MUST_EFR_SF_MASK		0x0F
-// send Xon1/Xoff1
+/* send Xon1/Xoff1 */
 #define MOXA_MUST_EFR_SF_TX1		0x08
-// send Xon2/Xoff2
+/* send Xon2/Xoff2 */
 #define MOXA_MUST_EFR_SF_TX2		0x04
-// send Xon1,Xon2/Xoff1,Xoff2
+/* send Xon1,Xon2/Xoff1,Xoff2 */
 #define MOXA_MUST_EFR_SF_TX12		0x0C
-// don't send Xon/Xoff
+/* don't send Xon/Xoff */
 #define MOXA_MUST_EFR_SF_TX_NO		0x00
-// Tx software flow control mask
+/* Tx software flow control mask */
 #define MOXA_MUST_EFR_SF_TX_MASK	0x0C
-// don't receive Xon/Xoff
+/* don't receive Xon/Xoff */
 #define MOXA_MUST_EFR_SF_RX_NO		0x00
-// receive Xon1/Xoff1
+/* receive Xon1/Xoff1 */
 #define MOXA_MUST_EFR_SF_RX1		0x02
-// receive Xon2/Xoff2
+/* receive Xon2/Xoff2 */
 #define MOXA_MUST_EFR_SF_RX2		0x01
-// receive Xon1,Xon2/Xoff1,Xoff2
+/* receive Xon1,Xon2/Xoff1,Xoff2 */
 #define MOXA_MUST_EFR_SF_RX12		0x03
-// Rx software flow control mask
+/* Rx software flow control mask */
 #define MOXA_MUST_EFR_SF_RX_MASK	0x03
 
-//#define MOXA_MUST_MIN_XOFFLIMIT               66
-//#define MOXA_MUST_MIN_XONLIMIT                20
-//#define ID1_RX_TRIG                   120
-
-
-#define CHECK_MOXA_MUST_XOFFLIMIT(info) { 	\
-	if ( (info)->IsMoxaMustChipFlag && 	\
-	 (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) {	\
-		(info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT;	\
-		(info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT;	\
-	}	\
-}
-
-#define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { 		\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr |= MOXA_MUST_EFR_EFRB_ENABLE;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr |= MOXA_MUST_EFR_EFRB_ENABLE;			\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
-#define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do {		\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_EFRB_ENABLE;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr &= ~MOXA_MUST_EFR_EFRB_ENABLE;			\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
-#define SET_MOXA_MUST_XON1_VALUE(baseio, Value) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define SET_MOXA_MUST_XON1_VALUE(baseio, Value) do {		\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK0;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr &= ~MOXA_MUST_EFR_BANK_MASK;			\
+	__efr |= MOXA_MUST_EFR_BANK0;				\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
 	outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
-#define SET_MOXA_MUST_XON2_VALUE(baseio, Value) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) do {		\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK0;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb((u8)(Value), (baseio)+MOXA_MUST_XON2_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
-
-#define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
-	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK0;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr &= ~MOXA_MUST_EFR_BANK_MASK;			\
+	__efr |= MOXA_MUST_EFR_BANK0;				\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
 	outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
-#define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
-	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK0;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb((u8)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
-
-#define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
-	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK1;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb((u8)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
-
-#define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
-	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK1;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb((u8)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
-
-#define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
-	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK1;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb((u8)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
-
-#define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
-	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK1;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb((u8)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
-
-//#define MOXA_MUST_RBRL_VALUE  4
-#define SET_MOXA_MUST_FIFO_VALUE(info) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((info)->ioaddr+UART_LCR);	\
-	outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR);	\
+#define SET_MOXA_MUST_FIFO_VALUE(info) do {			\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((info)->ioaddr+UART_LCR);		\
+	outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR);\
 	__efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK1;	\
+	__efr &= ~MOXA_MUST_EFR_BANK_MASK;			\
+	__efr |= MOXA_MUST_EFR_BANK1;				\
 	outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER);	\
-	outb((u8)((info)->rx_high_water), (info)->ioaddr+MOXA_MUST_RBRTH_REGISTER);	\
-	outb((u8)((info)->rx_trigger), (info)->ioaddr+MOXA_MUST_RBRTI_REGISTER);	\
-	outb((u8)((info)->rx_low_water), (info)->ioaddr+MOXA_MUST_RBRTL_REGISTER);	\
-	outb(__oldlcr, (info)->ioaddr+UART_LCR);	\
-}
+	outb((u8)((info)->rx_high_water), (info)->ioaddr+	\
+			MOXA_MUST_RBRTH_REGISTER);		\
+	outb((u8)((info)->rx_trigger), (info)->ioaddr+		\
+			MOXA_MUST_RBRTI_REGISTER);		\
+	outb((u8)((info)->rx_low_water), (info)->ioaddr+	\
+			MOXA_MUST_RBRTL_REGISTER);		\
+	outb(__oldlcr, (info)->ioaddr+UART_LCR);		\
+} while (0)
 
-
-
-#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) do {		\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK2;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr &= ~MOXA_MUST_EFR_BANK_MASK;			\
+	__efr |= MOXA_MUST_EFR_BANK2;				\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
 	outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
-#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do {		\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_BANK_MASK;	\
-	__efr |= MOXA_MUST_EFR_BANK2;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	*pId = inb((baseio)+MOXA_MUST_HWID_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr &= ~MOXA_MUST_EFR_BANK_MASK;			\
+	__efr |= MOXA_MUST_EFR_BANK2;				\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
+	*pId = inb((baseio)+MOXA_MUST_HWID_REGISTER);		\
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
-#define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) do {	\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_SF_MASK;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr &= ~MOXA_MUST_EFR_SF_MASK;			\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
-#define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do {	\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_SF_MASK;	\
-	__efr |= MOXA_MUST_EFR_SF_TX1;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr &= ~MOXA_MUST_EFR_SF_TX_MASK;			\
+	__efr |= MOXA_MUST_EFR_SF_TX1;				\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
-#define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do {	\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_SF_TX_MASK;	\
-	__efr |= MOXA_MUST_EFR_SF_TX1;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr &= ~MOXA_MUST_EFR_SF_TX_MASK;			\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
-#define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do {	\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_SF_TX_MASK;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr &= ~MOXA_MUST_EFR_SF_RX_MASK;			\
+	__efr |= MOXA_MUST_EFR_SF_RX1;				\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
-#define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
+#define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do {	\
+	u8	__oldlcr, __efr;				\
+	__oldlcr = inb((baseio)+UART_LCR);			\
 	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_SF_MASK;	\
-	__efr |= MOXA_MUST_EFR_SF_RX1;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
-
-#define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
-	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_SF_RX_MASK;	\
-	__efr |= MOXA_MUST_EFR_SF_RX1;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
-
-#define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
-	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_SF_RX_MASK;	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
-
-#define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) {	\
-	u8	__oldlcr, __efr;	\
-	__oldlcr = inb((baseio)+UART_LCR);	\
-	outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);	\
-	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);	\
-	__efr &= ~MOXA_MUST_EFR_SF_MASK;	\
-	__efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1);	\
-	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);	\
-	outb(__oldlcr, (baseio)+UART_LCR);	\
-}
-
-#define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) {	\
-	u8	__oldmcr;	\
-	__oldmcr = inb((baseio)+UART_MCR);	\
-	__oldmcr |= MOXA_MUST_MCR_XON_ANY;	\
-	outb(__oldmcr, (baseio)+UART_MCR);	\
-}
-
-#define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) {	\
-	u8	__oldmcr;	\
-	__oldmcr = inb((baseio)+UART_MCR);	\
-	__oldmcr &= ~MOXA_MUST_MCR_XON_ANY;	\
-	outb(__oldmcr, (baseio)+UART_MCR);	\
-}
-
-#define READ_MOXA_MUST_GDL(baseio)	inb((baseio)+MOXA_MUST_GDL_REGISTER)
-
-
-#ifndef INIT_WORK
-#define INIT_WORK(_work, _func, _data){	\
-	_data->tqueue.routine = _func;\
-	_data->tqueue.data = _data;\
-	}
-#endif
+	__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);		\
+	__efr &= ~MOXA_MUST_EFR_SF_RX_MASK;			\
+	outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);		\
+	outb(__oldlcr, (baseio)+UART_LCR);			\
+} while (0)
 
 #endif
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index dc6d418..65f2d3a 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -60,62 +60,56 @@
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
-#include <linux/string.h>   /* used in new tty drivers */
-#include <linux/signal.h>   /* used in new tty drivers */
+#include <linux/string.h>	/* used in new tty drivers */
+#include <linux/signal.h>	/* used in new tty drivers */
 #include <linux/ioctl.h>
 #include <linux/n_r3964.h>
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
 
-
-//#define DEBUG_QUEUE
+/*#define DEBUG_QUEUE*/
 
 /* Log successful handshake and protocol operations  */
-//#define DEBUG_PROTO_S
+/*#define DEBUG_PROTO_S*/
 
 /* Log handshake and protocol errors: */
-//#define DEBUG_PROTO_E
+/*#define DEBUG_PROTO_E*/
 
 /* Log Linediscipline operations (open, close, read, write...): */
-//#define DEBUG_LDISC
+/*#define DEBUG_LDISC*/
 
 /* Log module and memory operations (init, cleanup; kmalloc, kfree): */
-//#define DEBUG_MODUL
+/*#define DEBUG_MODUL*/
 
 /* Macro helpers for debug output: */
-#define TRACE(format, args...) printk("r3964: " format "\n" , ## args);
+#define TRACE(format, args...) printk("r3964: " format "\n" , ## args)
 
 #ifdef DEBUG_MODUL
-#define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args);
+#define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args)
 #else
-#define TRACE_M(fmt, arg...) /**/
+#define TRACE_M(fmt, arg...) do {} while (0)
 #endif
-
 #ifdef DEBUG_PROTO_S
-#define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args);
+#define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args)
 #else
-#define TRACE_PS(fmt, arg...) /**/
+#define TRACE_PS(fmt, arg...) do {} while (0)
 #endif
-
 #ifdef DEBUG_PROTO_E
-#define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args);
+#define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args)
 #else
-#define TRACE_PE(fmt, arg...) /**/
+#define TRACE_PE(fmt, arg...) do {} while (0)
 #endif
-
 #ifdef DEBUG_LDISC
-#define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args);
+#define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args)
 #else
-#define TRACE_L(fmt, arg...) /**/
+#define TRACE_L(fmt, arg...) do {} while (0)
 #endif
-
 #ifdef DEBUG_QUEUE
-#define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args);
+#define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args)
 #else
-#define TRACE_Q(fmt, arg...) /**/
+#define TRACE_Q(fmt, arg...) do {} while (0)
 #endif
-
 static void add_tx_queue(struct r3964_info *, struct r3964_block_header *);
 static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code);
 static void put_char(struct r3964_info *pInfo, unsigned char ch);
@@ -126,1280 +120,1149 @@
 static void receive_error(struct r3964_info *pInfo, const char flag);
 static void on_timeout(unsigned long priv);
 static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg);
-static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf);
+static int read_telegram(struct r3964_info *pInfo, struct pid *pid,
+		unsigned char __user * buf);
 static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
-             int error_code, struct r3964_block_header *pBlock);
-static struct r3964_message* remove_msg(struct r3964_info *pInfo, 
-             struct r3964_client_info *pClient);
-static void remove_client_block(struct r3964_info *pInfo, 
-                struct r3964_client_info *pClient);
+		int error_code, struct r3964_block_header *pBlock);
+static struct r3964_message *remove_msg(struct r3964_info *pInfo,
+		struct r3964_client_info *pClient);
+static void remove_client_block(struct r3964_info *pInfo,
+		struct r3964_client_info *pClient);
 
-static int  r3964_open(struct tty_struct *tty);
+static int r3964_open(struct tty_struct *tty);
 static void r3964_close(struct tty_struct *tty);
 static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
-                     unsigned char __user *buf, size_t nr);
-static ssize_t r3964_write(struct tty_struct * tty, struct file * file,
-                      const unsigned char * buf, size_t nr);
-static int r3964_ioctl(struct tty_struct * tty, struct file * file,
-                       unsigned int cmd, unsigned long arg);
-static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old);
-static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,
-		      struct poll_table_struct  *wait);
+		unsigned char __user * buf, size_t nr);
+static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
+		const unsigned char *buf, size_t nr);
+static int r3964_ioctl(struct tty_struct *tty, struct file *file,
+		unsigned int cmd, unsigned long arg);
+static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);
+static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
+		struct poll_table_struct *wait);
 static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-                              char *fp, int count);
+		char *fp, int count);
 
 static struct tty_ldisc tty_ldisc_N_R3964 = {
-	.owner	 = THIS_MODULE,
-	.magic	= TTY_LDISC_MAGIC, 
-	.name	= "R3964",
-	.open	= r3964_open,
-	.close	= r3964_close,
-	.read	= r3964_read,
-	.write	= r3964_write,
-	.ioctl	= r3964_ioctl,
+	.owner = THIS_MODULE,
+	.magic = TTY_LDISC_MAGIC,
+	.name = "R3964",
+	.open = r3964_open,
+	.close = r3964_close,
+	.read = r3964_read,
+	.write = r3964_write,
+	.ioctl = r3964_ioctl,
 	.set_termios = r3964_set_termios,
-	.poll	= r3964_poll,            
+	.poll = r3964_poll,
 	.receive_buf = r3964_receive_buf,
 };
 
-
-
 static void dump_block(const unsigned char *block, unsigned int length)
 {
-   unsigned int i,j;
-   char linebuf[16*3+1];
-   
-   for(i=0;i<length;i+=16)
-   {
-      for(j=0;(j<16) && (j+i<length);j++)
-      {
-         sprintf(linebuf+3*j,"%02x ",block[i+j]);
-      }
-      linebuf[3*j]='\0';
-      TRACE_PS("%s",linebuf);
-   }
+	unsigned int i, j;
+	char linebuf[16 * 3 + 1];
+
+	for (i = 0; i < length; i += 16) {
+		for (j = 0; (j < 16) && (j + i < length); j++) {
+			sprintf(linebuf + 3 * j, "%02x ", block[i + j]);
+		}
+		linebuf[3 * j] = '\0';
+		TRACE_PS("%s", linebuf);
+	}
 }
 
-         
-
-
 /*************************************************************
  * Driver initialisation
  *************************************************************/
 
-
 /*************************************************************
  * Module support routines
  *************************************************************/
 
 static void __exit r3964_exit(void)
 {
-   int status;
-   
-   TRACE_M ("cleanup_module()");
+	int status;
 
-   status=tty_unregister_ldisc(N_R3964);
-   
-   if(status!=0)
-   {
-      printk(KERN_ERR "r3964: error unregistering linediscipline: %d\n", status);
-   }
-   else
-   {
-      TRACE_L("linediscipline successfully unregistered");
-   }
-   
+	TRACE_M("cleanup_module()");
+
+	status = tty_unregister_ldisc(N_R3964);
+
+	if (status != 0) {
+		printk(KERN_ERR "r3964: error unregistering linediscipline: "
+				"%d\n", status);
+	} else {
+		TRACE_L("linediscipline successfully unregistered");
+	}
 }
 
 static int __init r3964_init(void)
 {
-   int status;
-   
-   printk ("r3964: Philips r3964 Driver $Revision: 1.10 $\n");
+	int status;
 
-   /*
-    * Register the tty line discipline
-    */
-   
-   status = tty_register_ldisc (N_R3964, &tty_ldisc_N_R3964);
-   if (status == 0)
-     {
-       TRACE_L("line discipline %d registered", N_R3964);
-       TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, 
-               tty_ldisc_N_R3964.num);
-       TRACE_L("open=%p", tty_ldisc_N_R3964.open);
-       TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964);
-     }
-   else
-     {
-       printk (KERN_ERR "r3964: error registering line discipline: %d\n", status);
-     }
-   return status;
+	printk("r3964: Philips r3964 Driver $Revision: 1.10 $\n");
+
+	/*
+	 * Register the tty line discipline
+	 */
+
+	status = tty_register_ldisc(N_R3964, &tty_ldisc_N_R3964);
+	if (status == 0) {
+		TRACE_L("line discipline %d registered", N_R3964);
+		TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags,
+			tty_ldisc_N_R3964.num);
+		TRACE_L("open=%p", tty_ldisc_N_R3964.open);
+		TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964);
+	} else {
+		printk(KERN_ERR "r3964: error registering line discipline: "
+				"%d\n", status);
+	}
+	return status;
 }
 
 module_init(r3964_init);
 module_exit(r3964_exit);
 
-
 /*************************************************************
  * Protocol implementation routines
  *************************************************************/
 
-static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader)
+static void add_tx_queue(struct r3964_info *pInfo,
+			 struct r3964_block_header *pHeader)
 {
-   unsigned long flags;
-   
-   spin_lock_irqsave(&pInfo->lock, flags);
+	unsigned long flags;
 
-   pHeader->next = NULL;
+	spin_lock_irqsave(&pInfo->lock, flags);
 
-   if(pInfo->tx_last == NULL)
-   {
-      pInfo->tx_first = pInfo->tx_last = pHeader;
-   }
-   else
-   {
-      pInfo->tx_last->next = pHeader;
-      pInfo->tx_last = pHeader;
-   }
-   
-   spin_unlock_irqrestore(&pInfo->lock, flags);
+	pHeader->next = NULL;
 
-   TRACE_Q("add_tx_queue %p, length %d, tx_first = %p", 
-          pHeader, pHeader->length, pInfo->tx_first );
+	if (pInfo->tx_last == NULL) {
+		pInfo->tx_first = pInfo->tx_last = pHeader;
+	} else {
+		pInfo->tx_last->next = pHeader;
+		pInfo->tx_last = pHeader;
+	}
+
+	spin_unlock_irqrestore(&pInfo->lock, flags);
+
+	TRACE_Q("add_tx_queue %p, length %d, tx_first = %p",
+		pHeader, pHeader->length, pInfo->tx_first);
 }
 
 static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
 {
-   struct r3964_block_header *pHeader;
-   unsigned long flags;
+	struct r3964_block_header *pHeader;
+	unsigned long flags;
 #ifdef DEBUG_QUEUE
-   struct r3964_block_header *pDump;
-#endif
-   
-   pHeader = pInfo->tx_first;
-
-   if(pHeader==NULL)
-      return;
-
-#ifdef DEBUG_QUEUE
-   printk("r3964: remove_from_tx_queue: %p, length %u - ",
-          pHeader, pHeader->length );
-   for(pDump=pHeader;pDump;pDump=pDump->next)
-	 printk("%p ", pDump);
-   printk("\n");
+	struct r3964_block_header *pDump;
 #endif
 
+	pHeader = pInfo->tx_first;
 
-   if(pHeader->owner)
-   {
-      if(error_code)
-      {
-          add_msg(pHeader->owner, R3964_MSG_ACK, 0, 
-                  error_code, NULL);
-      }
-      else
-      {
-          add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length, 
-                  error_code, NULL);
-      }
-      wake_up_interruptible (&pInfo->read_wait);
-   }
+	if (pHeader == NULL)
+		return;
 
-   spin_lock_irqsave(&pInfo->lock, flags);
+#ifdef DEBUG_QUEUE
+	printk("r3964: remove_from_tx_queue: %p, length %u - ",
+		pHeader, pHeader->length);
+	for (pDump = pHeader; pDump; pDump = pDump->next)
+		printk("%p ", pDump);
+	printk("\n");
+#endif
 
-   pInfo->tx_first = pHeader->next;
-   if(pInfo->tx_first==NULL)
-   {
-      pInfo->tx_last = NULL;
-   }
+	if (pHeader->owner) {
+		if (error_code) {
+			add_msg(pHeader->owner, R3964_MSG_ACK, 0,
+				error_code, NULL);
+		} else {
+			add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length,
+				error_code, NULL);
+		}
+		wake_up_interruptible(&pInfo->read_wait);
+	}
 
-   spin_unlock_irqrestore(&pInfo->lock, flags);
+	spin_lock_irqsave(&pInfo->lock, flags);
 
-   kfree(pHeader);
-   TRACE_M("remove_from_tx_queue - kfree %p",pHeader);
+	pInfo->tx_first = pHeader->next;
+	if (pInfo->tx_first == NULL) {
+		pInfo->tx_last = NULL;
+	}
 
-   TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p",
-          pInfo->tx_first, pInfo->tx_last );
+	spin_unlock_irqrestore(&pInfo->lock, flags);
+
+	kfree(pHeader);
+	TRACE_M("remove_from_tx_queue - kfree %p", pHeader);
+
+	TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p",
+		pInfo->tx_first, pInfo->tx_last);
 }
 
-static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader)
+static void add_rx_queue(struct r3964_info *pInfo,
+			 struct r3964_block_header *pHeader)
 {
-   unsigned long flags;
-   
-   spin_lock_irqsave(&pInfo->lock, flags);
+	unsigned long flags;
 
-   pHeader->next = NULL;
+	spin_lock_irqsave(&pInfo->lock, flags);
 
-   if(pInfo->rx_last == NULL)
-   {
-      pInfo->rx_first = pInfo->rx_last = pHeader;
-   }
-   else
-   {
-      pInfo->rx_last->next = pHeader;
-      pInfo->rx_last = pHeader;
-   }
-   pInfo->blocks_in_rx_queue++;
-   
-   spin_unlock_irqrestore(&pInfo->lock, flags);
+	pHeader->next = NULL;
 
-   TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d",
-          pHeader, pHeader->length,
-          pInfo->rx_first, pInfo->blocks_in_rx_queue);
+	if (pInfo->rx_last == NULL) {
+		pInfo->rx_first = pInfo->rx_last = pHeader;
+	} else {
+		pInfo->rx_last->next = pHeader;
+		pInfo->rx_last = pHeader;
+	}
+	pInfo->blocks_in_rx_queue++;
+
+	spin_unlock_irqrestore(&pInfo->lock, flags);
+
+	TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d",
+		pHeader, pHeader->length,
+		pInfo->rx_first, pInfo->blocks_in_rx_queue);
 }
 
 static void remove_from_rx_queue(struct r3964_info *pInfo,
-                 struct r3964_block_header *pHeader)
+				 struct r3964_block_header *pHeader)
 {
-   unsigned long flags;
-   struct r3964_block_header *pFind;
-   
-   if(pHeader==NULL)
-      return;
+	unsigned long flags;
+	struct r3964_block_header *pFind;
 
-   TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
-          pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue );
-   TRACE_Q("remove_from_rx_queue: %p, length %u",
-          pHeader, pHeader->length );
+	if (pHeader == NULL)
+		return;
 
-   spin_lock_irqsave(&pInfo->lock, flags);
+	TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
+		pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue);
+	TRACE_Q("remove_from_rx_queue: %p, length %u",
+		pHeader, pHeader->length);
 
-   if(pInfo->rx_first == pHeader)
-   {
-      /* Remove the first block in the linked list: */
-      pInfo->rx_first = pHeader->next;
-      
-      if(pInfo->rx_first==NULL)
-      {
-         pInfo->rx_last = NULL;
-      }
-      pInfo->blocks_in_rx_queue--;
-   }
-   else 
-   {
-      /* Find block to remove: */
-      for(pFind=pInfo->rx_first; pFind; pFind=pFind->next)
-      {
-         if(pFind->next == pHeader) 
-         {
-            /* Got it. */
-            pFind->next = pHeader->next;
-            pInfo->blocks_in_rx_queue--;
-            if(pFind->next==NULL)
-            {
-               /* Oh, removed the last one! */
-               pInfo->rx_last = pFind;
-            }
-            break;
-         }
-      }
-   }
+	spin_lock_irqsave(&pInfo->lock, flags);
 
-   spin_unlock_irqrestore(&pInfo->lock, flags);
+	if (pInfo->rx_first == pHeader) {
+		/* Remove the first block in the linked list: */
+		pInfo->rx_first = pHeader->next;
 
-   kfree(pHeader);
-   TRACE_M("remove_from_rx_queue - kfree %p",pHeader);
+		if (pInfo->rx_first == NULL) {
+			pInfo->rx_last = NULL;
+		}
+		pInfo->blocks_in_rx_queue--;
+	} else {
+		/* Find block to remove: */
+		for (pFind = pInfo->rx_first; pFind; pFind = pFind->next) {
+			if (pFind->next == pHeader) {
+				/* Got it. */
+				pFind->next = pHeader->next;
+				pInfo->blocks_in_rx_queue--;
+				if (pFind->next == NULL) {
+					/* Oh, removed the last one! */
+					pInfo->rx_last = pFind;
+				}
+				break;
+			}
+		}
+	}
 
-   TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
-          pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue );
+	spin_unlock_irqrestore(&pInfo->lock, flags);
+
+	kfree(pHeader);
+	TRACE_M("remove_from_rx_queue - kfree %p", pHeader);
+
+	TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
+		pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue);
 }
 
 static void put_char(struct r3964_info *pInfo, unsigned char ch)
 {
-   struct tty_struct *tty = pInfo->tty;
+	struct tty_struct *tty = pInfo->tty;
 
-   if(tty==NULL)
-      return;
+	if (tty == NULL)
+		return;
 
-   if(tty->driver->put_char)
-   {
-      tty->driver->put_char(tty, ch);
-   }
-   pInfo->bcc ^= ch;
+	if (tty->driver->put_char) {
+		tty->driver->put_char(tty, ch);
+	}
+	pInfo->bcc ^= ch;
 }
 
 static void flush(struct r3964_info *pInfo)
 {
-   struct tty_struct *tty = pInfo->tty;
+	struct tty_struct *tty = pInfo->tty;
 
-   if(tty==NULL)
-      return;
+	if (tty == NULL)
+		return;
 
-   if(tty->driver->flush_chars)
-   {
-      tty->driver->flush_chars(tty);
-   }
+	if (tty->driver->flush_chars) {
+		tty->driver->flush_chars(tty);
+	}
 }
 
 static void trigger_transmit(struct r3964_info *pInfo)
 {
-   unsigned long flags;
-   
+	unsigned long flags;
 
-   spin_lock_irqsave(&pInfo->lock, flags);
+	spin_lock_irqsave(&pInfo->lock, flags);
 
-   if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL))
-   {
-      pInfo->state = R3964_TX_REQUEST;
-      pInfo->nRetry=0;
-      pInfo->flags &= ~R3964_ERROR;
-      mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
+	if ((pInfo->state == R3964_IDLE) && (pInfo->tx_first != NULL)) {
+		pInfo->state = R3964_TX_REQUEST;
+		pInfo->nRetry = 0;
+		pInfo->flags &= ~R3964_ERROR;
+		mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
 
-      spin_unlock_irqrestore(&pInfo->lock, flags);
+		spin_unlock_irqrestore(&pInfo->lock, flags);
 
-      TRACE_PS("trigger_transmit - sent STX");
+		TRACE_PS("trigger_transmit - sent STX");
 
-      put_char(pInfo, STX);
-      flush(pInfo);
+		put_char(pInfo, STX);
+		flush(pInfo);
 
-      pInfo->bcc = 0;
-   }
-   else
-   {
-      spin_unlock_irqrestore(&pInfo->lock, flags);
-   }
+		pInfo->bcc = 0;
+	} else {
+		spin_unlock_irqrestore(&pInfo->lock, flags);
+	}
 }
 
 static void retry_transmit(struct r3964_info *pInfo)
 {
-   if(pInfo->nRetry<R3964_MAX_RETRIES)
-   {
-      TRACE_PE("transmission failed. Retry #%d", 
-             pInfo->nRetry);
-      pInfo->bcc = 0;
-      put_char(pInfo, STX);
-      flush(pInfo);
-      pInfo->state = R3964_TX_REQUEST;
-      pInfo->nRetry++;
-      mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
-   }
-   else
-   {
-      TRACE_PE("transmission failed after %d retries", 
-             R3964_MAX_RETRIES);
+	if (pInfo->nRetry < R3964_MAX_RETRIES) {
+		TRACE_PE("transmission failed. Retry #%d", pInfo->nRetry);
+		pInfo->bcc = 0;
+		put_char(pInfo, STX);
+		flush(pInfo);
+		pInfo->state = R3964_TX_REQUEST;
+		pInfo->nRetry++;
+		mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
+	} else {
+		TRACE_PE("transmission failed after %d retries",
+			 R3964_MAX_RETRIES);
 
-      remove_from_tx_queue(pInfo, R3964_TX_FAIL);
-      
-      put_char(pInfo, NAK);
-      flush(pInfo);
-      pInfo->state = R3964_IDLE;
+		remove_from_tx_queue(pInfo, R3964_TX_FAIL);
 
-      trigger_transmit(pInfo);
-   }
+		put_char(pInfo, NAK);
+		flush(pInfo);
+		pInfo->state = R3964_IDLE;
+
+		trigger_transmit(pInfo);
+	}
 }
 
-
 static void transmit_block(struct r3964_info *pInfo)
 {
-   struct tty_struct *tty = pInfo->tty;
-   struct r3964_block_header *pBlock = pInfo->tx_first;
-   int room=0;
+	struct tty_struct *tty = pInfo->tty;
+	struct r3964_block_header *pBlock = pInfo->tx_first;
+	int room = 0;
 
-   if((tty==NULL) || (pBlock==NULL))
-   {
-      return;
-   }
+	if ((tty == NULL) || (pBlock == NULL)) {
+		return;
+	}
 
-   if(tty->driver->write_room)
-      room=tty->driver->write_room(tty);
+	if (tty->driver->write_room)
+		room = tty->driver->write_room(tty);
 
-   TRACE_PS("transmit_block %p, room %d, length %d", 
-          pBlock, room, pBlock->length);
-   
-   while(pInfo->tx_position < pBlock->length)
-   {
-      if(room<2)
-         break;
- 
-      if(pBlock->data[pInfo->tx_position]==DLE)
-      {
-         /* send additional DLE char: */
-         put_char(pInfo, DLE);
-      }
-      put_char(pInfo, pBlock->data[pInfo->tx_position++]);
-      
-      room--;
-   }
+	TRACE_PS("transmit_block %p, room %d, length %d",
+		 pBlock, room, pBlock->length);
 
-   if((pInfo->tx_position == pBlock->length) && (room>=3))
-   {
-      put_char(pInfo, DLE);
-      put_char(pInfo, ETX);
-      if(pInfo->flags & R3964_BCC)
-      {
-         put_char(pInfo, pInfo->bcc);
-      }
-      pInfo->state = R3964_WAIT_FOR_TX_ACK;
-      mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
-   }
-   flush(pInfo);
+	while (pInfo->tx_position < pBlock->length) {
+		if (room < 2)
+			break;
+
+		if (pBlock->data[pInfo->tx_position] == DLE) {
+			/* send additional DLE char: */
+			put_char(pInfo, DLE);
+		}
+		put_char(pInfo, pBlock->data[pInfo->tx_position++]);
+
+		room--;
+	}
+
+	if ((pInfo->tx_position == pBlock->length) && (room >= 3)) {
+		put_char(pInfo, DLE);
+		put_char(pInfo, ETX);
+		if (pInfo->flags & R3964_BCC) {
+			put_char(pInfo, pInfo->bcc);
+		}
+		pInfo->state = R3964_WAIT_FOR_TX_ACK;
+		mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
+	}
+	flush(pInfo);
 }
 
 static void on_receive_block(struct r3964_info *pInfo)
 {
-   unsigned int length;
-   struct r3964_client_info *pClient;
-   struct r3964_block_header *pBlock;
-   
-   length=pInfo->rx_position;
+	unsigned int length;
+	struct r3964_client_info *pClient;
+	struct r3964_block_header *pBlock;
 
-   /* compare byte checksum characters: */
-   if(pInfo->flags & R3964_BCC)
-   {
-      if(pInfo->bcc!=pInfo->last_rx)
-      {
-         TRACE_PE("checksum error - got %x but expected %x",
-                pInfo->last_rx, pInfo->bcc);
-         pInfo->flags |= R3964_CHECKSUM;
-      }
-   }
+	length = pInfo->rx_position;
 
-   /* check for errors (parity, overrun,...): */
-   if(pInfo->flags & R3964_ERROR)
-   {
-      TRACE_PE("on_receive_block - transmission failed error %x",
-             pInfo->flags & R3964_ERROR);
-      
-      put_char(pInfo, NAK);
-      flush(pInfo);
-      if(pInfo->nRetry<R3964_MAX_RETRIES)
-      {
-         pInfo->state=R3964_WAIT_FOR_RX_REPEAT;
-         pInfo->nRetry++;
-	 mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC);
-      }
-      else
-      {
-         TRACE_PE("on_receive_block - failed after max retries");
-         pInfo->state=R3964_IDLE;
-      }
-      return;
-   }
+	/* compare byte checksum characters: */
+	if (pInfo->flags & R3964_BCC) {
+		if (pInfo->bcc != pInfo->last_rx) {
+			TRACE_PE("checksum error - got %x but expected %x",
+				 pInfo->last_rx, pInfo->bcc);
+			pInfo->flags |= R3964_CHECKSUM;
+		}
+	}
 
-   
-   /* received block; submit DLE: */
-   put_char(pInfo, DLE);
-   flush(pInfo);
-   del_timer_sync(&pInfo->tmr);
-   TRACE_PS(" rx success: got %d chars", length);
+	/* check for errors (parity, overrun,...): */
+	if (pInfo->flags & R3964_ERROR) {
+		TRACE_PE("on_receive_block - transmission failed error %x",
+			 pInfo->flags & R3964_ERROR);
 
-   /* prepare struct r3964_block_header: */
-   pBlock = kmalloc(length+sizeof(struct r3964_block_header), GFP_KERNEL);
-   TRACE_M("on_receive_block - kmalloc %p",pBlock);
+		put_char(pInfo, NAK);
+		flush(pInfo);
+		if (pInfo->nRetry < R3964_MAX_RETRIES) {
+			pInfo->state = R3964_WAIT_FOR_RX_REPEAT;
+			pInfo->nRetry++;
+			mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC);
+		} else {
+			TRACE_PE("on_receive_block - failed after max retries");
+			pInfo->state = R3964_IDLE;
+		}
+		return;
+	}
 
-   if(pBlock==NULL)
-      return;
+	/* received block; submit DLE: */
+	put_char(pInfo, DLE);
+	flush(pInfo);
+	del_timer_sync(&pInfo->tmr);
+	TRACE_PS(" rx success: got %d chars", length);
 
-   pBlock->length = length;
-   pBlock->data   = ((unsigned char*)pBlock)+sizeof(struct r3964_block_header);
-   pBlock->locks  = 0;
-   pBlock->next   = NULL;
-   pBlock->owner  = NULL;
+	/* prepare struct r3964_block_header: */
+	pBlock = kmalloc(length + sizeof(struct r3964_block_header),
+			GFP_KERNEL);
+	TRACE_M("on_receive_block - kmalloc %p", pBlock);
 
-   memcpy(pBlock->data, pInfo->rx_buf, length);
+	if (pBlock == NULL)
+		return;
 
-   /* queue block into rx_queue: */
-   add_rx_queue(pInfo, pBlock);
+	pBlock->length = length;
+	pBlock->data = ((unsigned char *)pBlock) +
+			sizeof(struct r3964_block_header);
+	pBlock->locks = 0;
+	pBlock->next = NULL;
+	pBlock->owner = NULL;
 
-   /* notify attached client processes: */
-   for(pClient=pInfo->firstClient; pClient; pClient=pClient->next)
-   {
-      if(pClient->sig_flags & R3964_SIG_DATA)
-      {
-         add_msg(pClient, R3964_MSG_DATA, length, R3964_OK, pBlock);
-      }
-   }
-   wake_up_interruptible (&pInfo->read_wait);
-   
-   pInfo->state = R3964_IDLE;
+	memcpy(pBlock->data, pInfo->rx_buf, length);
 
-   trigger_transmit(pInfo);
+	/* queue block into rx_queue: */
+	add_rx_queue(pInfo, pBlock);
+
+	/* notify attached client processes: */
+	for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) {
+		if (pClient->sig_flags & R3964_SIG_DATA) {
+			add_msg(pClient, R3964_MSG_DATA, length, R3964_OK,
+				pBlock);
+		}
+	}
+	wake_up_interruptible(&pInfo->read_wait);
+
+	pInfo->state = R3964_IDLE;
+
+	trigger_transmit(pInfo);
 }
 
-
 static void receive_char(struct r3964_info *pInfo, const unsigned char c)
 {
-   switch(pInfo->state)
-   {
-      case R3964_TX_REQUEST:
-         if(c==DLE)
-         {
-            TRACE_PS("TX_REQUEST - got DLE");
+	switch (pInfo->state) {
+	case R3964_TX_REQUEST:
+		if (c == DLE) {
+			TRACE_PS("TX_REQUEST - got DLE");
 
-            pInfo->state = R3964_TRANSMITTING;
-            pInfo->tx_position = 0;
-            
-            transmit_block(pInfo);
-         }
-         else if(c==STX)
-         {
-            if(pInfo->nRetry==0)
-            {
-               TRACE_PE("TX_REQUEST - init conflict");
-               if(pInfo->priority == R3964_SLAVE)
-               {
-                  goto start_receiving;
-               }
-            } 
-            else 
-            {
-               TRACE_PE("TX_REQUEST - secondary init conflict!?"
-                        " Switching to SLAVE mode for next rx.");
-               goto start_receiving;
-            }
-         }
-         else
-         {
-            TRACE_PE("TX_REQUEST - char != DLE: %x", c);
-            retry_transmit(pInfo);
-         }
-         break;
-      case R3964_TRANSMITTING:
-         if(c==NAK)
-         {
-            TRACE_PE("TRANSMITTING - got NAK");
-            retry_transmit(pInfo);
-         }
-         else
-         {
-            TRACE_PE("TRANSMITTING - got invalid char");
- 
-            pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY;
-	    mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
-         }
-         break;
-      case R3964_WAIT_FOR_TX_ACK:
-         if(c==DLE)
-         {
-            TRACE_PS("WAIT_FOR_TX_ACK - got DLE");
-            remove_from_tx_queue(pInfo, R3964_OK);
-            
-            pInfo->state = R3964_IDLE;
-            trigger_transmit(pInfo);
-         }
-         else
-         {
-            retry_transmit(pInfo);
-         }
-         break;
-      case R3964_WAIT_FOR_RX_REPEAT:
-         /* FALLTROUGH */
-      case R3964_IDLE:
-         if(c==STX)
-         {
-            /* Prevent rx_queue from overflow: */
-            if(pInfo->blocks_in_rx_queue >= R3964_MAX_BLOCKS_IN_RX_QUEUE)
-            {
-               TRACE_PE("IDLE - got STX but no space in rx_queue!");
-               pInfo->state=R3964_WAIT_FOR_RX_BUF;
-	       mod_timer(&pInfo->tmr, jiffies + R3964_TO_NO_BUF);
-               break;
-            }
+			pInfo->state = R3964_TRANSMITTING;
+			pInfo->tx_position = 0;
+
+			transmit_block(pInfo);
+		} else if (c == STX) {
+			if (pInfo->nRetry == 0) {
+				TRACE_PE("TX_REQUEST - init conflict");
+				if (pInfo->priority == R3964_SLAVE) {
+					goto start_receiving;
+				}
+			} else {
+				TRACE_PE("TX_REQUEST - secondary init "
+					"conflict!? Switching to SLAVE mode "
+					"for next rx.");
+				goto start_receiving;
+			}
+		} else {
+			TRACE_PE("TX_REQUEST - char != DLE: %x", c);
+			retry_transmit(pInfo);
+		}
+		break;
+	case R3964_TRANSMITTING:
+		if (c == NAK) {
+			TRACE_PE("TRANSMITTING - got NAK");
+			retry_transmit(pInfo);
+		} else {
+			TRACE_PE("TRANSMITTING - got invalid char");
+
+			pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY;
+			mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
+		}
+		break;
+	case R3964_WAIT_FOR_TX_ACK:
+		if (c == DLE) {
+			TRACE_PS("WAIT_FOR_TX_ACK - got DLE");
+			remove_from_tx_queue(pInfo, R3964_OK);
+
+			pInfo->state = R3964_IDLE;
+			trigger_transmit(pInfo);
+		} else {
+			retry_transmit(pInfo);
+		}
+		break;
+	case R3964_WAIT_FOR_RX_REPEAT:
+		/* FALLTROUGH */
+	case R3964_IDLE:
+		if (c == STX) {
+			/* Prevent rx_queue from overflow: */
+			if (pInfo->blocks_in_rx_queue >=
+			    R3964_MAX_BLOCKS_IN_RX_QUEUE) {
+				TRACE_PE("IDLE - got STX but no space in "
+						"rx_queue!");
+				pInfo->state = R3964_WAIT_FOR_RX_BUF;
+				mod_timer(&pInfo->tmr,
+					  jiffies + R3964_TO_NO_BUF);
+				break;
+			}
 start_receiving:
-            /* Ok, start receiving: */
-            TRACE_PS("IDLE - got STX");
-            pInfo->rx_position = 0;
-            pInfo->last_rx = 0;
-            pInfo->flags &= ~R3964_ERROR;
-            pInfo->state=R3964_RECEIVING;
-	    mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
-	    pInfo->nRetry = 0;
-            put_char(pInfo, DLE);
-            flush(pInfo);
-            pInfo->bcc = 0;
-         }
-         break;
-      case R3964_RECEIVING:
-         if(pInfo->rx_position < RX_BUF_SIZE)
-         {
-            pInfo->bcc ^= c;
-            
-            if(c==DLE)
-            {
-               if(pInfo->last_rx==DLE)
-               {
-                  pInfo->last_rx = 0;
-                  goto char_to_buf;
-               }
-               pInfo->last_rx = DLE;
-               break;
-            } 
-            else if((c==ETX) && (pInfo->last_rx==DLE))
-            {
-               if(pInfo->flags & R3964_BCC)
-               {
-                  pInfo->state = R3964_WAIT_FOR_BCC;
-		  mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
-               }
-               else 
-               {
-                  on_receive_block(pInfo);
-               }
-            }
-            else
-            {
-               pInfo->last_rx = c;
+			/* Ok, start receiving: */
+			TRACE_PS("IDLE - got STX");
+			pInfo->rx_position = 0;
+			pInfo->last_rx = 0;
+			pInfo->flags &= ~R3964_ERROR;
+			pInfo->state = R3964_RECEIVING;
+			mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
+			pInfo->nRetry = 0;
+			put_char(pInfo, DLE);
+			flush(pInfo);
+			pInfo->bcc = 0;
+		}
+		break;
+	case R3964_RECEIVING:
+		if (pInfo->rx_position < RX_BUF_SIZE) {
+			pInfo->bcc ^= c;
+
+			if (c == DLE) {
+				if (pInfo->last_rx == DLE) {
+					pInfo->last_rx = 0;
+					goto char_to_buf;
+				}
+				pInfo->last_rx = DLE;
+				break;
+			} else if ((c == ETX) && (pInfo->last_rx == DLE)) {
+				if (pInfo->flags & R3964_BCC) {
+					pInfo->state = R3964_WAIT_FOR_BCC;
+					mod_timer(&pInfo->tmr,
+						  jiffies + R3964_TO_ZVZ);
+				} else {
+					on_receive_block(pInfo);
+				}
+			} else {
+				pInfo->last_rx = c;
 char_to_buf:
-               pInfo->rx_buf[pInfo->rx_position++] = c;
-	       mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
-            }
-         }
-        /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ 
-         break;
-      case R3964_WAIT_FOR_BCC:
-         pInfo->last_rx = c;
-         on_receive_block(pInfo);
-         break;
-   }
+				pInfo->rx_buf[pInfo->rx_position++] = c;
+				mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
+			}
+		}
+		/* else: overflow-msg? BUF_SIZE>MTU; should not happen? */
+		break;
+	case R3964_WAIT_FOR_BCC:
+		pInfo->last_rx = c;
+		on_receive_block(pInfo);
+		break;
+	}
 }
 
 static void receive_error(struct r3964_info *pInfo, const char flag)
 {
-    switch (flag) 
-    {
-    case TTY_NORMAL:
-        break;
-    case TTY_BREAK:
-        TRACE_PE("received break")
-        pInfo->flags |= R3964_BREAK;
-        break;
-    case TTY_PARITY:
-        TRACE_PE("parity error")
-        pInfo->flags |= R3964_PARITY;
-        break;
-    case TTY_FRAME:
-        TRACE_PE("frame error")
-        pInfo->flags |= R3964_FRAME;
-        break;
-    case TTY_OVERRUN:
-        TRACE_PE("frame overrun")
-        pInfo->flags |= R3964_OVERRUN;
-        break;
-    default:
-        TRACE_PE("receive_error - unknown flag %d", flag);
-        pInfo->flags |= R3964_UNKNOWN;
-        break;
-    }
+	switch (flag) {
+	case TTY_NORMAL:
+		break;
+	case TTY_BREAK:
+		TRACE_PE("received break");
+		pInfo->flags |= R3964_BREAK;
+		break;
+	case TTY_PARITY:
+		TRACE_PE("parity error");
+		pInfo->flags |= R3964_PARITY;
+		break;
+	case TTY_FRAME:
+		TRACE_PE("frame error");
+		pInfo->flags |= R3964_FRAME;
+		break;
+	case TTY_OVERRUN:
+		TRACE_PE("frame overrun");
+		pInfo->flags |= R3964_OVERRUN;
+		break;
+	default:
+		TRACE_PE("receive_error - unknown flag %d", flag);
+		pInfo->flags |= R3964_UNKNOWN;
+		break;
+	}
 }
 
 static void on_timeout(unsigned long priv)
 {
-   struct r3964_info *pInfo = (void *)priv;
+	struct r3964_info *pInfo = (void *)priv;
 
-   switch(pInfo->state)
-   {
-      case R3964_TX_REQUEST:
-         TRACE_PE("TX_REQUEST - timeout");
-         retry_transmit(pInfo);
-         break;
-      case R3964_WAIT_ZVZ_BEFORE_TX_RETRY:
-         put_char(pInfo, NAK);
-         flush(pInfo);
-         retry_transmit(pInfo);
-         break;
-      case R3964_WAIT_FOR_TX_ACK:
-         TRACE_PE("WAIT_FOR_TX_ACK - timeout");
-         retry_transmit(pInfo);
-         break;
-      case R3964_WAIT_FOR_RX_BUF:
-         TRACE_PE("WAIT_FOR_RX_BUF - timeout");
-         put_char(pInfo, NAK);
-         flush(pInfo);
-         pInfo->state=R3964_IDLE;
-         break;
-      case R3964_RECEIVING:
-         TRACE_PE("RECEIVING - timeout after %d chars", 
-                  pInfo->rx_position);
-         put_char(pInfo, NAK);
-         flush(pInfo);
-         pInfo->state=R3964_IDLE;
-         break;
-      case R3964_WAIT_FOR_RX_REPEAT:
-         TRACE_PE("WAIT_FOR_RX_REPEAT - timeout");
-         pInfo->state=R3964_IDLE;
-         break;
-      case R3964_WAIT_FOR_BCC:
-         TRACE_PE("WAIT_FOR_BCC - timeout");
-         put_char(pInfo, NAK);
-         flush(pInfo);
-         pInfo->state=R3964_IDLE;
-         break;
-   }
+	switch (pInfo->state) {
+	case R3964_TX_REQUEST:
+		TRACE_PE("TX_REQUEST - timeout");
+		retry_transmit(pInfo);
+		break;
+	case R3964_WAIT_ZVZ_BEFORE_TX_RETRY:
+		put_char(pInfo, NAK);
+		flush(pInfo);
+		retry_transmit(pInfo);
+		break;
+	case R3964_WAIT_FOR_TX_ACK:
+		TRACE_PE("WAIT_FOR_TX_ACK - timeout");
+		retry_transmit(pInfo);
+		break;
+	case R3964_WAIT_FOR_RX_BUF:
+		TRACE_PE("WAIT_FOR_RX_BUF - timeout");
+		put_char(pInfo, NAK);
+		flush(pInfo);
+		pInfo->state = R3964_IDLE;
+		break;
+	case R3964_RECEIVING:
+		TRACE_PE("RECEIVING - timeout after %d chars",
+			 pInfo->rx_position);
+		put_char(pInfo, NAK);
+		flush(pInfo);
+		pInfo->state = R3964_IDLE;
+		break;
+	case R3964_WAIT_FOR_RX_REPEAT:
+		TRACE_PE("WAIT_FOR_RX_REPEAT - timeout");
+		pInfo->state = R3964_IDLE;
+		break;
+	case R3964_WAIT_FOR_BCC:
+		TRACE_PE("WAIT_FOR_BCC - timeout");
+		put_char(pInfo, NAK);
+		flush(pInfo);
+		pInfo->state = R3964_IDLE;
+		break;
+	}
 }
 
-static struct r3964_client_info *findClient(
-  struct r3964_info *pInfo, struct pid *pid)
+static struct r3964_client_info *findClient(struct r3964_info *pInfo,
+		struct pid *pid)
 {
-   struct r3964_client_info *pClient;
-   
-   for(pClient=pInfo->firstClient; pClient; pClient=pClient->next)
-   {
-      if(pClient->pid == pid)
-      {
-         return pClient;
-      }
-   }
-   return NULL;
+	struct r3964_client_info *pClient;
+
+	for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) {
+		if (pClient->pid == pid) {
+			return pClient;
+		}
+	}
+	return NULL;
 }
 
 static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg)
 {
-   struct r3964_client_info *pClient;
-   struct r3964_client_info **ppClient;
-   struct r3964_message *pMsg;
-   
-   if((arg & R3964_SIG_ALL)==0)
-   {
-      /* Remove client from client list */
-      for(ppClient=&pInfo->firstClient; *ppClient; ppClient=&(*ppClient)->next)
-      {
-         pClient = *ppClient;
-         
-         if(pClient->pid == pid)
-         {
-            TRACE_PS("removing client %d from client list", pid_nr(pid));
-            *ppClient = pClient->next;
-            while(pClient->msg_count)
-            {
-               pMsg=remove_msg(pInfo, pClient);
-               if(pMsg)
-               {
-                  kfree(pMsg);
-                  TRACE_M("enable_signals - msg kfree %p",pMsg);
-               }
-            }
-	    put_pid(pClient->pid);
-            kfree(pClient);
-            TRACE_M("enable_signals - kfree %p",pClient);
-            return 0;
-         }
-      }
-      return -EINVAL;
-   }
-   else
-   {
-      pClient=findClient(pInfo, pid);
-      if(pClient)
-      {
-         /* update signal options */
-         pClient->sig_flags=arg;
-      } 
-      else 
-      {
-         /* add client to client list */
-         pClient=kmalloc(sizeof(struct r3964_client_info), GFP_KERNEL);
-         TRACE_M("enable_signals - kmalloc %p",pClient);
-         if(pClient==NULL)
-            return -ENOMEM;
+	struct r3964_client_info *pClient;
+	struct r3964_client_info **ppClient;
+	struct r3964_message *pMsg;
 
-         TRACE_PS("add client %d to client list", pid_nr(pid));
-	 spin_lock_init(&pClient->lock);
-         pClient->sig_flags=arg;
-         pClient->pid = get_pid(pid);
-         pClient->next=pInfo->firstClient;
-         pClient->first_msg = NULL;
-         pClient->last_msg = NULL;
-         pClient->next_block_to_read = NULL;
-         pClient->msg_count = 0;
-         pInfo->firstClient=pClient;
-      }
-   }
+	if ((arg & R3964_SIG_ALL) == 0) {
+		/* Remove client from client list */
+		for (ppClient = &pInfo->firstClient; *ppClient;
+		     ppClient = &(*ppClient)->next) {
+			pClient = *ppClient;
 
-   return 0;
+			if (pClient->pid == pid) {
+				TRACE_PS("removing client %d from client list",
+					 pid_nr(pid));
+				*ppClient = pClient->next;
+				while (pClient->msg_count) {
+					pMsg = remove_msg(pInfo, pClient);
+					if (pMsg) {
+						kfree(pMsg);
+						TRACE_M("enable_signals - msg "
+							"kfree %p", pMsg);
+					}
+				}
+				put_pid(pClient->pid);
+				kfree(pClient);
+				TRACE_M("enable_signals - kfree %p", pClient);
+				return 0;
+			}
+		}
+		return -EINVAL;
+	} else {
+		pClient = findClient(pInfo, pid);
+		if (pClient) {
+			/* update signal options */
+			pClient->sig_flags = arg;
+		} else {
+			/* add client to client list */
+			pClient = kmalloc(sizeof(struct r3964_client_info),
+					GFP_KERNEL);
+			TRACE_M("enable_signals - kmalloc %p", pClient);
+			if (pClient == NULL)
+				return -ENOMEM;
+
+			TRACE_PS("add client %d to client list", pid_nr(pid));
+			spin_lock_init(&pClient->lock);
+			pClient->sig_flags = arg;
+			pClient->pid = get_pid(pid);
+			pClient->next = pInfo->firstClient;
+			pClient->first_msg = NULL;
+			pClient->last_msg = NULL;
+			pClient->next_block_to_read = NULL;
+			pClient->msg_count = 0;
+			pInfo->firstClient = pClient;
+		}
+	}
+
+	return 0;
 }
 
-static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf)
+static int read_telegram(struct r3964_info *pInfo, struct pid *pid,
+			 unsigned char __user * buf)
 {
-    struct r3964_client_info *pClient;
-    struct r3964_block_header *block;
+	struct r3964_client_info *pClient;
+	struct r3964_block_header *block;
 
-    if(!buf)
-    {
-        return -EINVAL;
-    }
+	if (!buf) {
+		return -EINVAL;
+	}
 
-    pClient=findClient(pInfo,pid);
-    if(pClient==NULL)
-    {
-       return -EINVAL;
-    }
-    
-    block=pClient->next_block_to_read;
-    if(!block)
-    {
-       return 0;
-    }
-    else
-    {
-      if (copy_to_user (buf, block->data, block->length))
-	return -EFAULT;
+	pClient = findClient(pInfo, pid);
+	if (pClient == NULL) {
+		return -EINVAL;
+	}
 
-       remove_client_block(pInfo, pClient);
-       return block->length;
-    }
+	block = pClient->next_block_to_read;
+	if (!block) {
+		return 0;
+	} else {
+		if (copy_to_user(buf, block->data, block->length))
+			return -EFAULT;
 
-    return -EINVAL;
+		remove_client_block(pInfo, pClient);
+		return block->length;
+	}
+
+	return -EINVAL;
 }
 
 static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
-             int error_code, struct r3964_block_header *pBlock)
+		int error_code, struct r3964_block_header *pBlock)
 {
-   struct r3964_message *pMsg;
-   unsigned long flags;
-   
-   if(pClient->msg_count<R3964_MAX_MSG_COUNT-1)
-   {
+	struct r3964_message *pMsg;
+	unsigned long flags;
+
+	if (pClient->msg_count < R3964_MAX_MSG_COUNT - 1) {
 queue_the_message:
 
-      pMsg = kmalloc(sizeof(struct r3964_message),
-		     error_code?GFP_ATOMIC:GFP_KERNEL);
-      TRACE_M("add_msg - kmalloc %p",pMsg);
-      if(pMsg==NULL) {
-         return;
-      }
+		pMsg = kmalloc(sizeof(struct r3964_message),
+				error_code ? GFP_ATOMIC : GFP_KERNEL);
+		TRACE_M("add_msg - kmalloc %p", pMsg);
+		if (pMsg == NULL) {
+			return;
+		}
 
-      spin_lock_irqsave(&pClient->lock, flags);
+		spin_lock_irqsave(&pClient->lock, flags);
 
-      pMsg->msg_id = msg_id;
-      pMsg->arg    = arg;
-      pMsg->error_code = error_code;
-      pMsg->block  = pBlock;
-      pMsg->next   = NULL;
-      
-      if(pClient->last_msg==NULL)
-      {
-         pClient->first_msg=pClient->last_msg=pMsg;
-      }
-      else
-      {
-         pClient->last_msg->next = pMsg;
-         pClient->last_msg=pMsg;
-      }
+		pMsg->msg_id = msg_id;
+		pMsg->arg = arg;
+		pMsg->error_code = error_code;
+		pMsg->block = pBlock;
+		pMsg->next = NULL;
 
-      pClient->msg_count++;
+		if (pClient->last_msg == NULL) {
+			pClient->first_msg = pClient->last_msg = pMsg;
+		} else {
+			pClient->last_msg->next = pMsg;
+			pClient->last_msg = pMsg;
+		}
 
-      if(pBlock!=NULL)
-      {
-         pBlock->locks++;
-      }
-      spin_unlock_irqrestore(&pClient->lock, flags);
-   }
-   else
-   {
-      if((pClient->last_msg->msg_id == R3964_MSG_ACK)
-		 && (pClient->last_msg->error_code==R3964_OVERFLOW))
-      {
-         pClient->last_msg->arg++;
-		 TRACE_PE("add_msg - inc prev OVERFLOW-msg");
-      }
-      else
-      {
-         msg_id = R3964_MSG_ACK;
-         arg = 0;
-		 error_code = R3964_OVERFLOW;
-         pBlock = NULL;
-		 TRACE_PE("add_msg - queue OVERFLOW-msg");
-         goto queue_the_message;
-      }
-   }
-   /* Send SIGIO signal to client process: */
-   if(pClient->sig_flags & R3964_USE_SIGIO)
-   {
-      kill_pid(pClient->pid, SIGIO, 1);
-   }
+		pClient->msg_count++;
+
+		if (pBlock != NULL) {
+			pBlock->locks++;
+		}
+		spin_unlock_irqrestore(&pClient->lock, flags);
+	} else {
+		if ((pClient->last_msg->msg_id == R3964_MSG_ACK)
+		    && (pClient->last_msg->error_code == R3964_OVERFLOW)) {
+			pClient->last_msg->arg++;
+			TRACE_PE("add_msg - inc prev OVERFLOW-msg");
+		} else {
+			msg_id = R3964_MSG_ACK;
+			arg = 0;
+			error_code = R3964_OVERFLOW;
+			pBlock = NULL;
+			TRACE_PE("add_msg - queue OVERFLOW-msg");
+			goto queue_the_message;
+		}
+	}
+	/* Send SIGIO signal to client process: */
+	if (pClient->sig_flags & R3964_USE_SIGIO) {
+		kill_pid(pClient->pid, SIGIO, 1);
+	}
 }
 
 static struct r3964_message *remove_msg(struct r3964_info *pInfo,
-                       struct r3964_client_info *pClient)
+					struct r3964_client_info *pClient)
 {
-   struct r3964_message *pMsg=NULL;
-   unsigned long flags;
+	struct r3964_message *pMsg = NULL;
+	unsigned long flags;
 
-   if(pClient->first_msg)
-   {
-      spin_lock_irqsave(&pClient->lock, flags);
+	if (pClient->first_msg) {
+		spin_lock_irqsave(&pClient->lock, flags);
 
-      pMsg = pClient->first_msg;
-      pClient->first_msg = pMsg->next;
-      if(pClient->first_msg==NULL)
-      {
-         pClient->last_msg = NULL;
-      }
-      
-      pClient->msg_count--;
-      if(pMsg->block)
-      {
-        remove_client_block(pInfo, pClient);
-        pClient->next_block_to_read = pMsg->block;
-      }
-      spin_unlock_irqrestore(&pClient->lock, flags);
-   }
-   return pMsg;
+		pMsg = pClient->first_msg;
+		pClient->first_msg = pMsg->next;
+		if (pClient->first_msg == NULL) {
+			pClient->last_msg = NULL;
+		}
+
+		pClient->msg_count--;
+		if (pMsg->block) {
+			remove_client_block(pInfo, pClient);
+			pClient->next_block_to_read = pMsg->block;
+		}
+		spin_unlock_irqrestore(&pClient->lock, flags);
+	}
+	return pMsg;
 }
 
-static void remove_client_block(struct r3964_info *pInfo, 
-                struct r3964_client_info *pClient)
+static void remove_client_block(struct r3964_info *pInfo,
+				struct r3964_client_info *pClient)
 {
-    struct r3964_block_header *block;
+	struct r3964_block_header *block;
 
-    TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid));
+	TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid));
 
-    block=pClient->next_block_to_read;
-    if(block)
-    {
-        block->locks--;
-        if(block->locks==0)
-        {
-            remove_from_rx_queue(pInfo, block);
-        }
-    }
-    pClient->next_block_to_read = NULL;
+	block = pClient->next_block_to_read;
+	if (block) {
+		block->locks--;
+		if (block->locks == 0) {
+			remove_from_rx_queue(pInfo, block);
+		}
+	}
+	pClient->next_block_to_read = NULL;
 }
 
-
 /*************************************************************
  * Line discipline routines
  *************************************************************/
 
 static int r3964_open(struct tty_struct *tty)
 {
-   struct r3964_info *pInfo;
-   
-   TRACE_L("open");
-   TRACE_L("tty=%p, PID=%d, disc_data=%p", 
-          tty, current->pid, tty->disc_data);
-   
-   pInfo=kmalloc(sizeof(struct r3964_info), GFP_KERNEL); 
-   TRACE_M("r3964_open - info kmalloc %p",pInfo);
+	struct r3964_info *pInfo;
 
-   if(!pInfo)
-   {
-      printk(KERN_ERR "r3964: failed to alloc info structure\n");
-      return -ENOMEM;
-   }
+	TRACE_L("open");
+	TRACE_L("tty=%p, PID=%d, disc_data=%p",
+		tty, current->pid, tty->disc_data);
 
-   pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
-   TRACE_M("r3964_open - rx_buf kmalloc %p",pInfo->rx_buf);
+	pInfo = kmalloc(sizeof(struct r3964_info), GFP_KERNEL);
+	TRACE_M("r3964_open - info kmalloc %p", pInfo);
 
-   if(!pInfo->rx_buf)
-   {
-      printk(KERN_ERR "r3964: failed to alloc receive buffer\n");
-      kfree(pInfo);
-      TRACE_M("r3964_open - info kfree %p",pInfo);
-      return -ENOMEM;
-   }
-   
-   pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL);
-   TRACE_M("r3964_open - tx_buf kmalloc %p",pInfo->tx_buf);
+	if (!pInfo) {
+		printk(KERN_ERR "r3964: failed to alloc info structure\n");
+		return -ENOMEM;
+	}
 
-   if(!pInfo->tx_buf)
-   {
-      printk(KERN_ERR "r3964: failed to alloc transmit buffer\n");
-      kfree(pInfo->rx_buf);
-      TRACE_M("r3964_open - rx_buf kfree %p",pInfo->rx_buf);
-      kfree(pInfo);
-      TRACE_M("r3964_open - info kfree %p",pInfo);
-      return -ENOMEM;
-   }
+	pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
+	TRACE_M("r3964_open - rx_buf kmalloc %p", pInfo->rx_buf);
 
-   spin_lock_init(&pInfo->lock);
-   pInfo->tty = tty;
-   init_waitqueue_head (&pInfo->read_wait);
-   pInfo->priority = R3964_MASTER;
-   pInfo->rx_first = pInfo->rx_last = NULL;
-   pInfo->tx_first = pInfo->tx_last = NULL;
-   pInfo->rx_position = 0;
-   pInfo->tx_position = 0;
-   pInfo->last_rx = 0;
-   pInfo->blocks_in_rx_queue = 0;
-   pInfo->firstClient=NULL;
-   pInfo->state=R3964_IDLE;
-   pInfo->flags = R3964_DEBUG;
-   pInfo->nRetry = 0;
-   
-   tty->disc_data = pInfo;
-   tty->receive_room = 65536;
+	if (!pInfo->rx_buf) {
+		printk(KERN_ERR "r3964: failed to alloc receive buffer\n");
+		kfree(pInfo);
+		TRACE_M("r3964_open - info kfree %p", pInfo);
+		return -ENOMEM;
+	}
 
-   init_timer(&pInfo->tmr);
-   pInfo->tmr.data = (unsigned long)pInfo;
-   pInfo->tmr.function = on_timeout;
+	pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL);
+	TRACE_M("r3964_open - tx_buf kmalloc %p", pInfo->tx_buf);
 
-   return 0;
+	if (!pInfo->tx_buf) {
+		printk(KERN_ERR "r3964: failed to alloc transmit buffer\n");
+		kfree(pInfo->rx_buf);
+		TRACE_M("r3964_open - rx_buf kfree %p", pInfo->rx_buf);
+		kfree(pInfo);
+		TRACE_M("r3964_open - info kfree %p", pInfo);
+		return -ENOMEM;
+	}
+
+	spin_lock_init(&pInfo->lock);
+	pInfo->tty = tty;
+	init_waitqueue_head(&pInfo->read_wait);
+	pInfo->priority = R3964_MASTER;
+	pInfo->rx_first = pInfo->rx_last = NULL;
+	pInfo->tx_first = pInfo->tx_last = NULL;
+	pInfo->rx_position = 0;
+	pInfo->tx_position = 0;
+	pInfo->last_rx = 0;
+	pInfo->blocks_in_rx_queue = 0;
+	pInfo->firstClient = NULL;
+	pInfo->state = R3964_IDLE;
+	pInfo->flags = R3964_DEBUG;
+	pInfo->nRetry = 0;
+
+	tty->disc_data = pInfo;
+	tty->receive_room = 65536;
+
+	setup_timer(&pInfo->tmr, on_timeout, (unsigned long)pInfo);
+
+	return 0;
 }
 
 static void r3964_close(struct tty_struct *tty)
 {
-   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
-   struct r3964_client_info *pClient, *pNext;
-   struct r3964_message *pMsg;
-   struct r3964_block_header *pHeader, *pNextHeader;
-   unsigned long flags;
+	struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+	struct r3964_client_info *pClient, *pNext;
+	struct r3964_message *pMsg;
+	struct r3964_block_header *pHeader, *pNextHeader;
+	unsigned long flags;
 
-   TRACE_L("close");
+	TRACE_L("close");
 
-    /*
-     * Make sure that our task queue isn't activated.  If it
-     * is, take it out of the linked list.
-     */
-    del_timer_sync(&pInfo->tmr);
+	/*
+	 * Make sure that our task queue isn't activated.  If it
+	 * is, take it out of the linked list.
+	 */
+	del_timer_sync(&pInfo->tmr);
 
-   /* Remove client-structs and message queues: */
-    pClient=pInfo->firstClient;
-    while(pClient)
-    {
-       pNext=pClient->next;
-       while(pClient->msg_count)
-       {
-          pMsg=remove_msg(pInfo, pClient);
-          if(pMsg)
-          {
-             kfree(pMsg);
-             TRACE_M("r3964_close - msg kfree %p",pMsg);
-          }
-       }
-       put_pid(pClient->pid);
-       kfree(pClient);
-       TRACE_M("r3964_close - client kfree %p",pClient);
-       pClient=pNext;
-    }
-    /* Remove jobs from tx_queue: */
-        spin_lock_irqsave(&pInfo->lock, flags);
-	pHeader=pInfo->tx_first;
-	pInfo->tx_first=pInfo->tx_last=NULL;
+	/* Remove client-structs and message queues: */
+	pClient = pInfo->firstClient;
+	while (pClient) {
+		pNext = pClient->next;
+		while (pClient->msg_count) {
+			pMsg = remove_msg(pInfo, pClient);
+			if (pMsg) {
+				kfree(pMsg);
+				TRACE_M("r3964_close - msg kfree %p", pMsg);
+			}
+		}
+		put_pid(pClient->pid);
+		kfree(pClient);
+		TRACE_M("r3964_close - client kfree %p", pClient);
+		pClient = pNext;
+	}
+	/* Remove jobs from tx_queue: */
+	spin_lock_irqsave(&pInfo->lock, flags);
+	pHeader = pInfo->tx_first;
+	pInfo->tx_first = pInfo->tx_last = NULL;
 	spin_unlock_irqrestore(&pInfo->lock, flags);
-	
-    while(pHeader)
-	{
-	   pNextHeader=pHeader->next;
-	   kfree(pHeader);
-	   pHeader=pNextHeader;
+
+	while (pHeader) {
+		pNextHeader = pHeader->next;
+		kfree(pHeader);
+		pHeader = pNextHeader;
 	}
 
-    /* Free buffers: */
-    wake_up_interruptible(&pInfo->read_wait);
-    kfree(pInfo->rx_buf);
-    TRACE_M("r3964_close - rx_buf kfree %p",pInfo->rx_buf);
-    kfree(pInfo->tx_buf);
-    TRACE_M("r3964_close - tx_buf kfree %p",pInfo->tx_buf);
-    kfree(pInfo);
-    TRACE_M("r3964_close - info kfree %p",pInfo);
+	/* Free buffers: */
+	wake_up_interruptible(&pInfo->read_wait);
+	kfree(pInfo->rx_buf);
+	TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf);
+	kfree(pInfo->tx_buf);
+	TRACE_M("r3964_close - tx_buf kfree %p", pInfo->tx_buf);
+	kfree(pInfo);
+	TRACE_M("r3964_close - info kfree %p", pInfo);
 }
 
 static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
-			  unsigned char __user *buf, size_t nr)
+			  unsigned char __user * buf, size_t nr)
 {
-   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
-   struct r3964_client_info *pClient;
-   struct r3964_message *pMsg;
-   struct r3964_client_message theMsg;
-   DECLARE_WAITQUEUE (wait, current);
-   
-   int count;
-   
-   TRACE_L("read()");
- 
-   pClient=findClient(pInfo, task_pid(current));
-   if(pClient)
-   {
-      pMsg = remove_msg(pInfo, pClient);
-      if(pMsg==NULL)
-      {
-		 /* no messages available. */
-         if (file->f_flags & O_NONBLOCK)
-		 {
-            return -EAGAIN;
-		 }
-         /* block until there is a message: */
-         add_wait_queue(&pInfo->read_wait, &wait);
+	struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+	struct r3964_client_info *pClient;
+	struct r3964_message *pMsg;
+	struct r3964_client_message theMsg;
+	DECLARE_WAITQUEUE(wait, current);
+
+	int count;
+
+	TRACE_L("read()");
+
+	pClient = findClient(pInfo, task_pid(current));
+	if (pClient) {
+		pMsg = remove_msg(pInfo, pClient);
+		if (pMsg == NULL) {
+			/* no messages available. */
+			if (file->f_flags & O_NONBLOCK) {
+				return -EAGAIN;
+			}
+			/* block until there is a message: */
+			add_wait_queue(&pInfo->read_wait, &wait);
 repeat:
-         current->state = TASK_INTERRUPTIBLE;
-         pMsg = remove_msg(pInfo, pClient);
-	 if (!pMsg && !signal_pending(current))
-		 {
-            schedule();
-            goto repeat;
-         }
-         current->state = TASK_RUNNING;
-         remove_wait_queue(&pInfo->read_wait, &wait);
-      }
-      
-      /* If we still haven't got a message, we must have been signalled */
+			current->state = TASK_INTERRUPTIBLE;
+			pMsg = remove_msg(pInfo, pClient);
+			if (!pMsg && !signal_pending(current)) {
+				schedule();
+				goto repeat;
+			}
+			current->state = TASK_RUNNING;
+			remove_wait_queue(&pInfo->read_wait, &wait);
+		}
 
-      if (!pMsg) return -EINTR;
+		/* If we still haven't got a message, we must have been signalled */
 
-      /* deliver msg to client process: */
-      theMsg.msg_id = pMsg->msg_id;
-      theMsg.arg    = pMsg->arg;
-      theMsg.error_code = pMsg->error_code;
-      count = sizeof(struct r3964_client_message);
+		if (!pMsg)
+			return -EINTR;
 
-      kfree(pMsg);
-      TRACE_M("r3964_read - msg kfree %p",pMsg);
+		/* deliver msg to client process: */
+		theMsg.msg_id = pMsg->msg_id;
+		theMsg.arg = pMsg->arg;
+		theMsg.error_code = pMsg->error_code;
+		count = sizeof(struct r3964_client_message);
 
-      if (copy_to_user(buf,&theMsg, count))
-	return -EFAULT;
+		kfree(pMsg);
+		TRACE_M("r3964_read - msg kfree %p", pMsg);
 
-      TRACE_PS("read - return %d", count);
-      return count;
-   }
-   return -EPERM;
+		if (copy_to_user(buf, &theMsg, count))
+			return -EFAULT;
+
+		TRACE_PS("read - return %d", count);
+		return count;
+	}
+	return -EPERM;
 }
 
-static ssize_t r3964_write(struct tty_struct * tty, struct file * file,
+static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
 			   const unsigned char *data, size_t count)
 {
-   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
-   struct r3964_block_header *pHeader;
-   struct r3964_client_info *pClient;
-   unsigned char *new_data;
-   
-   TRACE_L("write request, %d characters", count);
+	struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+	struct r3964_block_header *pHeader;
+	struct r3964_client_info *pClient;
+	unsigned char *new_data;
+
+	TRACE_L("write request, %d characters", count);
 /* 
  * Verify the pointers 
  */
 
-   if(!pInfo)
-      return -EIO;
+	if (!pInfo)
+		return -EIO;
 
 /*
  * Ensure that the caller does not wish to send too much.
  */
-   if (count > R3964_MTU) 
-   {
-      if (pInfo->flags & R3964_DEBUG)
-      {
-         TRACE_L (KERN_WARNING
-                 "r3964_write: truncating user packet "
-                 "from %u to mtu %d", count, R3964_MTU);
-      }
-      count = R3964_MTU;
-   }
+	if (count > R3964_MTU) {
+		if (pInfo->flags & R3964_DEBUG) {
+			TRACE_L(KERN_WARNING "r3964_write: truncating user "
+				"packet from %u to mtu %d", count, R3964_MTU);
+		}
+		count = R3964_MTU;
+	}
 /*
  * Allocate a buffer for the data and copy it from the buffer with header prepended
  */
-   new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL);
-   TRACE_M("r3964_write - kmalloc %p",new_data);
-   if (new_data == NULL) {
-      if (pInfo->flags & R3964_DEBUG)
-      {
-         printk (KERN_ERR
-               "r3964_write: no memory\n");
-      }
-      return -ENOSPC;
-   }
-   
-   pHeader = (struct r3964_block_header *)new_data;
-   pHeader->data = new_data + sizeof(struct r3964_block_header);
-   pHeader->length = count;
-   pHeader->locks = 0;
-   pHeader->owner = NULL;
-   
-   pClient=findClient(pInfo, task_pid(current));
-   if(pClient)
-   {
-      pHeader->owner = pClient;
-   }
+	new_data = kmalloc(count + sizeof(struct r3964_block_header),
+			GFP_KERNEL);
+	TRACE_M("r3964_write - kmalloc %p", new_data);
+	if (new_data == NULL) {
+		if (pInfo->flags & R3964_DEBUG) {
+			printk(KERN_ERR "r3964_write: no memory\n");
+		}
+		return -ENOSPC;
+	}
 
-   memcpy(pHeader->data, data, count); /* We already verified this */
+	pHeader = (struct r3964_block_header *)new_data;
+	pHeader->data = new_data + sizeof(struct r3964_block_header);
+	pHeader->length = count;
+	pHeader->locks = 0;
+	pHeader->owner = NULL;
 
-   if(pInfo->flags & R3964_DEBUG)
-   {
-      dump_block(pHeader->data, count);
-   }
+	pClient = findClient(pInfo, task_pid(current));
+	if (pClient) {
+		pHeader->owner = pClient;
+	}
+
+	memcpy(pHeader->data, data, count);	/* We already verified this */
+
+	if (pInfo->flags & R3964_DEBUG) {
+		dump_block(pHeader->data, count);
+	}
 
 /*
  * Add buffer to transmit-queue:
  */
-   add_tx_queue(pInfo, pHeader);
-   trigger_transmit(pInfo);
-   
-   return 0;
+	add_tx_queue(pInfo, pHeader);
+	trigger_transmit(pInfo);
+
+	return 0;
 }
 
-static int r3964_ioctl(struct tty_struct * tty, struct file * file,
-               unsigned int cmd, unsigned long arg)
+static int r3964_ioctl(struct tty_struct *tty, struct file *file,
+		unsigned int cmd, unsigned long arg)
 {
-   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
-   if(pInfo==NULL)
-      return -EINVAL;
-   switch(cmd)
-   {
-      case R3964_ENABLE_SIGNALS:
-         return enable_signals(pInfo, task_pid(current), arg);
-      case R3964_SETPRIORITY:
-         if(arg<R3964_MASTER || arg>R3964_SLAVE)
-            return -EINVAL;
-         pInfo->priority = arg & 0xff;
-         return 0;
-      case R3964_USE_BCC:
-             if(arg)
-            pInfo->flags |= R3964_BCC;
-         else
-            pInfo->flags &= ~R3964_BCC;
-         return 0;
-      case R3964_READ_TELEGRAM:
-         return read_telegram(pInfo, task_pid(current), (unsigned char __user *)arg);
-      default:
-         return -ENOIOCTLCMD;
-   }
+	struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+	if (pInfo == NULL)
+		return -EINVAL;
+	switch (cmd) {
+	case R3964_ENABLE_SIGNALS:
+		return enable_signals(pInfo, task_pid(current), arg);
+	case R3964_SETPRIORITY:
+		if (arg < R3964_MASTER || arg > R3964_SLAVE)
+			return -EINVAL;
+		pInfo->priority = arg & 0xff;
+		return 0;
+	case R3964_USE_BCC:
+		if (arg)
+			pInfo->flags |= R3964_BCC;
+		else
+			pInfo->flags &= ~R3964_BCC;
+		return 0;
+	case R3964_READ_TELEGRAM:
+		return read_telegram(pInfo, task_pid(current),
+				(unsigned char __user *)arg);
+	default:
+		return -ENOIOCTLCMD;
+	}
 }
 
-static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old)
+static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
-   TRACE_L("set_termios");
+	TRACE_L("set_termios");
 }
 
 /* Called without the kernel lock held - fine */
-static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,
-		      struct poll_table_struct *wait)
+static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
+			struct poll_table_struct *wait)
 {
-   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
-   struct r3964_client_info *pClient;
-   struct r3964_message *pMsg=NULL;
-   unsigned long flags;
-   int result = POLLOUT;
+	struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+	struct r3964_client_info *pClient;
+	struct r3964_message *pMsg = NULL;
+	unsigned long flags;
+	int result = POLLOUT;
 
-   TRACE_L("POLL");
+	TRACE_L("POLL");
 
-   pClient=findClient(pInfo, task_pid(current));
-   if(pClient)
-     {
-       poll_wait(file, &pInfo->read_wait, wait);
-       spin_lock_irqsave(&pInfo->lock, flags);
-       pMsg=pClient->first_msg;
-       spin_unlock_irqrestore(&pInfo->lock, flags);
-       if(pMsg)
-	   result |= POLLIN | POLLRDNORM;
-     }
-   else
-     {
-       result = -EINVAL;
-     }
-   return result;
+	pClient = findClient(pInfo, task_pid(current));
+	if (pClient) {
+		poll_wait(file, &pInfo->read_wait, wait);
+		spin_lock_irqsave(&pInfo->lock, flags);
+		pMsg = pClient->first_msg;
+		spin_unlock_irqrestore(&pInfo->lock, flags);
+		if (pMsg)
+			result |= POLLIN | POLLRDNORM;
+	} else {
+		result = -EINVAL;
+	}
+	return result;
 }
 
 static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-                              char *fp, int count)
+			char *fp, int count)
 {
-   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
-    const unsigned char *p;
-    char *f, flags = 0;
-    int i;
+	struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+	const unsigned char *p;
+	char *f, flags = 0;
+	int i;
 
-    for (i=count, p = cp, f = fp; i; i--, p++) {
-        if (f)
-            flags = *f++;
-        if(flags==TTY_NORMAL)
-        {
-            receive_char(pInfo, *p);
-        }
-        else
-        {
-            receive_error(pInfo, flags);
-        }
-        
-    }
+	for (i = count, p = cp, f = fp; i; i--, p++) {
+		if (f)
+			flags = *f++;
+		if (flags == TTY_NORMAL) {
+			receive_char(pInfo, *p);
+		} else {
+			receive_error(pInfo, flags);
+		}
+
+	}
 }
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 2bdb014..6ac3ca4 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -579,8 +579,8 @@
  
 static inline void isig(int sig, struct tty_struct *tty, int flush)
 {
-	if (tty->pgrp > 0)
-		kill_pg(tty->pgrp, sig, 1);
+	if (tty->pgrp)
+		kill_pgrp(tty->pgrp, sig, 1);
 	if (flush || !L_NOFLSH(tty)) {
 		n_tty_flush_buffer(tty);
 		if (tty->driver->flush_buffer)
@@ -1184,13 +1184,13 @@
 	/* don't stop on /dev/console */
 	if (file->f_op->write != redirected_tty_write &&
 	    current->signal->tty == tty) {
-		if (tty->pgrp <= 0)
-			printk("read_chan: tty->pgrp <= 0!\n");
-		else if (process_group(current) != tty->pgrp) {
+		if (!tty->pgrp)
+			printk("read_chan: no tty->pgrp!\n");
+		else if (task_pgrp(current) != tty->pgrp) {
 			if (is_ignored(SIGTTIN) ||
-			    is_orphaned_pgrp(process_group(current)))
+			    is_current_pgrp_orphaned())
 				return -EIO;
-			kill_pg(process_group(current), SIGTTIN, 1);
+			kill_pgrp(task_pgrp(current), SIGTTIN, 1);
 			return -ERESTARTSYS;
 		}
 	}
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index a39f19c..204deaa 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -37,7 +37,6 @@
 #define NVRAM_VERSION	"1.2"
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/nvram.h>
 
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c
index 2d26497..2604246 100644
--- a/drivers/char/nwbutton.c
+++ b/drivers/char/nwbutton.c
@@ -23,8 +23,11 @@
 #define __NWBUTTON_C		/* Tell the header file who we are */
 #include "nwbutton.h"
 
+static void button_sequence_finished (unsigned long parameters);
+
 static int button_press_count;		/* The count of button presses */
-static struct timer_list button_timer;	/* Times for the end of a sequence */ 
+/* Times for the end of a sequence */
+static DEFINE_TIMER(button_timer, button_sequence_finished, 0, 0);
 static DECLARE_WAIT_QUEUE_HEAD(button_wait_queue); /* Used for blocking read */
 static char button_output_buffer[32];	/* Stores data to write out of device */
 static int bcount;			/* The number of bytes in the buffer */
@@ -146,14 +149,8 @@
 
 static irqreturn_t button_handler (int irq, void *dev_id)
 {
-	if (button_press_count) {
-		del_timer (&button_timer);
-	}
 	button_press_count++;
-	init_timer (&button_timer);
-	button_timer.function = button_sequence_finished;
-	button_timer.expires = (jiffies + bdelay);
-	add_timer (&button_timer);
+	mod_timer(&button_timer, jiffies + bdelay);
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index 206cf6f..ba012c2 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -21,7 +21,6 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
-#include <linux/sched.h>
 #include <linux/miscdevice.h>
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 211c93f..e91b43a 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -946,8 +946,7 @@
 
 return_with_timer:
 	DEBUGP(7, dev, "<- monitor_card (returns with timer)\n");
-	dev->timer.expires = jiffies + dev->mdelay;
-	add_timer(&dev->timer);
+	mod_timer(&dev->timer, jiffies + dev->mdelay);
 	clear_bit(LOCK_MONITOR, &dev->flags);
 }
 
@@ -1406,12 +1405,9 @@
 	DEBUGP(3, dev, "-> start_monitor\n");
 	if (!dev->monitor_running) {
 		DEBUGP(5, dev, "create, init and add timer\n");
-		init_timer(&dev->timer);
+		setup_timer(&dev->timer, monitor_card, (unsigned long)dev);
 		dev->monitor_running = 1;
-		dev->timer.expires = jiffies;
-		dev->timer.data = (unsigned long) dev;
-		dev->timer.function = monitor_card;
-		add_timer(&dev->timer);
+		mod_timer(&dev->timer, jiffies);
 	} else
 		DEBUGP(5, dev, "monitor already running\n");
 	DEBUGP(3, dev, "<- start_monitor\n");
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 9b1ff7e..0e82968 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -632,8 +632,7 @@
 	init_waitqueue_head(&dev->poll_wait);
 	init_waitqueue_head(&dev->read_wait);
 	init_waitqueue_head(&dev->write_wait);
-	init_timer(&dev->poll_timer);
-	dev->poll_timer.function = &cm4040_do_poll;
+	setup_timer(&dev->poll_timer, cm4040_do_poll, 0);
 
 	ret = reader_config(link, i);
 	if (ret)
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index f108c13..8d025e9 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -887,10 +887,8 @@
 	if (debug_level >= DEBUG_LEVEL_BH)
 		printk("bh_transmit() entry on %s\n", info->device_name);
 
-	if (tty) {
+	if (tty)
 		tty_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
 }
 
 static void bh_status(MGSLPC_INFO *info)
@@ -1363,9 +1361,7 @@
 	
 	memset(&info->icount, 0, sizeof(info->icount));
 
-	init_timer(&info->tx_timer);
-	info->tx_timer.data = (unsigned long)info;
-	info->tx_timer.function = tx_timeout;
+	setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
 
 	/* Allocate and claim adapter resources */
 	retval = claim_resources(info);
@@ -1410,7 +1406,7 @@
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 
-	del_timer(&info->tx_timer);	
+	del_timer_sync(&info->tx_timer);
 
 	if (info->tx_buf) {
 		free_page((unsigned long) info->tx_buf);
@@ -3551,8 +3547,8 @@
 		} else {
 			info->tx_active = 1;
 			tx_ready(info);
-			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
-			add_timer(&info->tx_timer);	
+			mod_timer(&info->tx_timer, jiffies +
+					msecs_to_jiffies(5000));
 		}
 	}
 
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index c07a1b5..de14aea 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -14,7 +14,6 @@
 #include <linux/module.h>	/* For EXPORT_SYMBOL */
 
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 13d0b13..b9dc7aa 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1117,14 +1117,14 @@
 	}
 }
 
-struct file_operations random_fops = {
+const struct file_operations random_fops = {
 	.read  = random_read,
 	.write = random_write,
 	.poll  = random_poll,
 	.ioctl = random_ioctl,
 };
 
-struct file_operations urandom_fops = {
+const struct file_operations urandom_fops = {
 	.read  = urandom_read,
 	.write = random_write,
 	.ioctl = random_ioctl,
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 645e20a..1f0d7c6 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -154,7 +154,7 @@
 			goto out;
 		}
 
-		if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS) {
+		if (rq.raw_minor <= 0 || rq.raw_minor >= MAX_RAW_MINORS) {
 			err = -EINVAL;
 			goto out;
 		}
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index e79b2ed..294e9cb 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -418,8 +418,7 @@
 	func_enter();
 
 	rio_interrupt(0, &p->RIOHosts[data]);
-	p->RIOHosts[data].timer.expires = jiffies + rio_poll;
-	add_timer(&p->RIOHosts[data].timer);
+	mod_timer(&p->RIOHosts[data].timer, jiffies + rio_poll);
 
 	func_exit();
 }
@@ -1147,20 +1146,17 @@
 				rio_dprintk(RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
 				hp->Mode |= RIO_PCI_INT_ENABLE;
 			} else
-				hp->Mode &= !RIO_PCI_INT_ENABLE;
+				hp->Mode &= ~RIO_PCI_INT_ENABLE;
 			rio_dprintk(RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
 			rio_start_card_running(hp);
 		}
 		/* Init the timer "always" to make sure that it can safely be
 		   deleted when we unload... */
 
-		init_timer(&hp->timer);
+		setup_timer(&hp->timer, rio_pollfunc, i);
 		if (!hp->Ivec) {
 			rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll);
-			hp->timer.data = i;
-			hp->timer.function = rio_pollfunc;
-			hp->timer.expires = jiffies + rio_poll;
-			add_timer(&hp->timer);
+			mod_timer(&hp->timer, jiffies + rio_poll);
 		}
 	}
 
@@ -1191,7 +1187,7 @@
 			rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
 		}
 		/* It is safe/allowed to del_timer a non-active timer */
-		del_timer(&hp->timer);
+		del_timer_sync(&hp->timer);
 		if (hp->Caddr)
 			iounmap(hp->Caddr);
 		if (hp->Type == RIO_PCI)
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
index eeda40c..ebc7634 100644
--- a/drivers/char/rio/riointr.c
+++ b/drivers/char/rio/riointr.c
@@ -162,13 +162,8 @@
 
 	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
 
-	if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN)) {
-		rio_dprintk(RIO_DEBUG_INTR, "Waking up.... ldisc:%d (%d/%d)....", (int) (PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)), PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
-		if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && PortP->gs.tty->ldisc.write_wakeup)
-			(PortP->gs.tty->ldisc.write_wakeup) (PortP->gs.tty);
-		rio_dprintk(RIO_DEBUG_INTR, "(%d/%d)\n", PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
-		wake_up_interruptible(&PortP->gs.tty->write_wait);
-	}
+	if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN))
+		tty_wakeup(PortP->gs.tty);
 
 }
 
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index e2a94bf..7014525 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1229,7 +1229,6 @@
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 	restore_flags(flags);
 	
-	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
 }
 
@@ -1570,10 +1569,8 @@
 	if(!(tty = port->tty)) 
 		return;
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event))
 		tty_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
 }
 
 static const struct tty_operations riscom_ops = {
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index e94a62e..76357c8 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -106,6 +106,8 @@
 
 /****** RocketPort Local Variables ******/
 
+static void rp_do_poll(unsigned long dummy);
+
 static struct tty_driver *rocket_driver;
 
 static struct rocket_version driver_version = {	
@@ -116,7 +118,7 @@
 static unsigned int xmit_flags[NUM_BOARDS];	       /*  Bit significant, indicates port had data to transmit. */
 						       /*  eg.  Bit 0 indicates port 0 has xmit data, ...        */
 static atomic_t rp_num_ports_open;	               /*  Number of serial ports open                           */
-static struct timer_list rocket_timer;
+static DEFINE_TIMER(rocket_timer, rp_do_poll, 0, 0);
 
 static unsigned long board1;	                       /* ISA addresses, retrieved from rocketport.conf          */
 static unsigned long board2;
@@ -474,7 +476,6 @@
 
 	if (info->xmit_cnt < WAKEUP_CHARS) {
 		tty_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
 #ifdef ROCKETPORT_HAVE_POLL_WAIT
 		wake_up_interruptible(&tty->poll_wait);
 #endif
@@ -1772,7 +1773,6 @@
 end:
  	if (info->xmit_cnt < WAKEUP_CHARS) {
  		tty_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
 #ifdef ROCKETPORT_HAVE_POLL_WAIT
 		wake_up_interruptible(&tty->poll_wait);
 #endif
@@ -1841,7 +1841,6 @@
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	spin_unlock_irqrestore(&info->slock, flags);
 
-	wake_up_interruptible(&tty->write_wait);
 #ifdef ROCKETPORT_HAVE_POLL_WAIT
 	wake_up_interruptible(&tty->poll_wait);
 #endif
@@ -2371,12 +2370,6 @@
 		return -ENOMEM;
 
 	/*
-	 * Set up the timer channel.
-	 */
-	init_timer(&rocket_timer);
-	rocket_timer.function = rp_do_poll;
-
-	/*
 	 * Initialize the array of pointers to our own internal state
 	 * structures.
 	 */
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 664f36c..c7dac9b 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -135,7 +135,9 @@
 static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
 
 #ifdef RTC_IRQ
-static struct timer_list rtc_irq_timer;
+static void rtc_dropped_irq(unsigned long data);
+
+static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0);
 #endif
 
 static ssize_t rtc_read(struct file *file, char __user *buf,
@@ -150,8 +152,6 @@
 
 static void get_rtc_alm_time (struct rtc_time *alm_tm);
 #ifdef RTC_IRQ
-static void rtc_dropped_irq(unsigned long data);
-
 static void set_rtc_irq_bit_locked(unsigned char bit);
 static void mask_rtc_irq_bit_locked(unsigned char bit);
 
@@ -282,7 +282,7 @@
  */
 static ctl_table rtc_table[] = {
 	{
-		.ctl_name	= 1,
+		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "max-user-freq",
 		.data		= &rtc_max_user_freq,
 		.maxlen		= sizeof(int),
@@ -294,9 +294,8 @@
 
 static ctl_table rtc_root[] = {
 	{
-		.ctl_name	= 1,
+		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "rtc",
-		.maxlen		= 0,
 		.mode		= 0555,
 		.child		= rtc_table,
 	},
@@ -307,7 +306,6 @@
 	{
 		.ctl_name	= CTL_DEV,
 		.procname	= "dev",
-		.maxlen		= 0,
 		.mode		= 0555,
 		.child		= rtc_root,
 	},
@@ -318,7 +316,7 @@
 
 static int __init init_sysctl(void)
 {
-    sysctl_header = register_sysctl_table(dev_root, 0);
+    sysctl_header = register_sysctl_table(dev_root);
     return 0;
 }
 
@@ -454,8 +452,8 @@
 
 		spin_lock_irqsave (&rtc_lock, flags);
 		if (!(rtc_status & RTC_TIMER_ON)) {
-			rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
-			add_timer(&rtc_irq_timer);
+			mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq +
+					2*HZ/100);
 			rtc_status |= RTC_TIMER_ON;
 		}
 		set_rtc_irq_bit_locked(RTC_PIE);
@@ -1084,8 +1082,6 @@
 	if (rtc_has_irq == 0)
 		goto no_irq2;
 
-	init_timer(&rtc_irq_timer);
-	rtc_irq_timer.function = rtc_dropped_irq;
 	spin_lock_irq(&rtc_lock);
 	rtc_freq = 1024;
 	if (!hpet_set_periodic_freq(rtc_freq)) {
diff --git a/drivers/char/scan_keyb.c b/drivers/char/scan_keyb.c
deleted file mode 100644
index 2b5bb4f..0000000
--- a/drivers/char/scan_keyb.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *	$Id: scan_keyb.c,v 1.2 2000/07/04 06:24:42 yaegashi Exp $ 
- *	Copyright (C) 2000 YAEGASHI Takeshi
- *	Generic scan keyboard driver
- */
-
-#include <linux/spinlock.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
-#include <linux/init.h>
-#include <linux/kbd_ll.h>
-#include <linux/delay.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/kbd_kern.h>
-#include <linux/timer.h>
-
-#define SCANHZ	(HZ/20)
-
-struct scan_keyboard {
-	struct scan_keyboard *next;
-	int (*scan)(unsigned char *buffer);
-	const unsigned char *table;
-	unsigned char *s0, *s1;
-	int length;
-};
-
-static int scan_jiffies=0;
-static struct scan_keyboard *keyboards=NULL;
-struct timer_list scan_timer;
-
-static void check_kbd(const unsigned char *table,
-		      unsigned char *new, unsigned char *old, int length)
-{
-	int need_tasklet_schedule=0;
-	unsigned int xor, bit;
-	
-	while(length-->0) {
-		if((xor=*new^*old)==0) {
-			table+=8;
-		}
-		else {
-			for(bit=0x01; bit<0x100; bit<<=1) {
-				if(xor&bit) {
-					handle_scancode(*table, !(*new&bit));
-					need_tasklet_schedule=1;
-#if 0
-					printk("0x%x %s\n", *table, (*new&bit)?"released":"pressed");
-#endif
-				}
-				table++;
-			}
-		}
-		new++; old++;
-	}
-
-	if(need_tasklet_schedule)
-		tasklet_schedule(&keyboard_tasklet);
-}
-
-
-static void scan_kbd(unsigned long dummy)
-{
-	struct scan_keyboard *kbd;
-
-	scan_jiffies++;
-
-	for(kbd=keyboards; kbd!=NULL; kbd=kbd->next) {
-		if(scan_jiffies&1) {
-			if(!kbd->scan(kbd->s0))
-				check_kbd(kbd->table,
-					  kbd->s0, kbd->s1, kbd->length);
-			else
-				memcpy(kbd->s0, kbd->s1, kbd->length);
-		}
-		else {
-			if(!kbd->scan(kbd->s1))
-				check_kbd(kbd->table,
-					  kbd->s1, kbd->s0, kbd->length);
-			else
-				memcpy(kbd->s1, kbd->s0, kbd->length);
-		}
-		
-	}
-
-	init_timer(&scan_timer);
-	scan_timer.expires = jiffies + SCANHZ;
-	scan_timer.data = 0;
-	scan_timer.function = scan_kbd;
-	add_timer(&scan_timer);
-}
-
-
-int register_scan_keyboard(int (*scan)(unsigned char *buffer),
-			   const unsigned char *table,
-			   int length)
-{
-	struct scan_keyboard *kbd;
-
-	kbd = kmalloc(sizeof(struct scan_keyboard), GFP_KERNEL);
-	if (kbd == NULL)
-		goto error_out;
-
-	kbd->scan=scan;
-	kbd->table=table;
-	kbd->length=length;
-
-	kbd->s0 = kmalloc(length, GFP_KERNEL);
-	if (kbd->s0 == NULL)
-		goto error_free_kbd;
-
-	kbd->s1 = kmalloc(length, GFP_KERNEL);
-	if (kbd->s1 == NULL)
-		goto error_free_s0;
-
-	memset(kbd->s0, -1, kbd->length);
-	memset(kbd->s1, -1, kbd->length);
-	
-	kbd->next=keyboards;
-	keyboards=kbd;
-
-	return 0;
-
- error_free_s0:
-	kfree(kbd->s0);
-
- error_free_kbd:
-	kfree(kbd);
-
- error_out:
-	return -ENOMEM;
-}
-			      
-			      
-void __init scan_kbd_init(void)
-{
-	init_timer(&scan_timer);
-	scan_timer.expires = jiffies + SCANHZ;
-	scan_timer.data = 0;
-	scan_timer.function = scan_kbd;
-	add_timer(&scan_timer);
-
-	printk(KERN_INFO "Generic scan keyboard driver initialized\n");
-}
diff --git a/drivers/char/scan_keyb.h b/drivers/char/scan_keyb.h
deleted file mode 100644
index b4b6112..0000000
--- a/drivers/char/scan_keyb.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef	__DRIVER_CHAR_SCAN_KEYB_H
-#define	__DRIVER_CHAR_SCAN_KEYB_H
-/*
- *	$Id: scan_keyb.h,v 1.1 2000/06/10 21:45:30 yaegashi Exp $
- *	Copyright (C) 2000 YAEGASHI Takeshi
- *	Generic scan keyboard driver
- */
-
-int register_scan_keyboard(int (*scan)(unsigned char *buffer),
-			   const unsigned char *table,
-			   int length);
-
-void __init scan_kbd_init(void);
-
-#endif
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 75de5f6..3c86914 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -86,7 +86,6 @@
 #include <linux/module.h>
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index af50d32..5fd314a 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -111,12 +111,13 @@
 
 /* This is the per-port data structure */
 struct cyclades_port cy_port[] = {
-      /* CARD#  */
-        {-1 },      /* ttyS0 */
-        {-1 },      /* ttyS1 */
-        {-1 },      /* ttyS2 */
-        {-1 },      /* ttyS3 */
+	/* CARD#  */
+	{-1},			/* ttyS0 */
+	{-1},			/* ttyS1 */
+	{-1},			/* ttyS2 */
+	{-1},			/* ttyS3 */
 };
+
 #define NR_PORTS        ARRAY_SIZE(cy_port)
 
 /*
@@ -128,42 +129,46 @@
  *                                                  HI            VHI
  */
 static int baud_table[] = {
-           0,    50,    75,   110,   134,   150,   200,   300,   600,  1200,
-        1800,  2400,  4800,  9600, 19200, 38400, 57600, 76800,115200,150000,
-        0};
+	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+	1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
+	0
+};
 
 #if 0
-static char baud_co[] = {  /* 25 MHz clock option table */
-        /* value =>    00    01   02    03    04 */
-        /* divide by    8    32   128   512  2048 */
-        0x00,  0x04,  0x04,  0x04,  0x04,  0x04,  0x03,  0x03,  0x03,  0x02,
-        0x02,  0x02,  0x01,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00};
+static char baud_co[] = {	/* 25 MHz clock option table */
+	/* value =>    00    01   02    03    04 */
+	/* divide by    8    32   128   512  2048 */
+	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
+	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
 
-static char baud_bpr[] = {  /* 25 MHz baud rate period table */
-        0x00,  0xf5,  0xa3,  0x6f,  0x5c,  0x51,  0xf5,  0xa3,  0x51,  0xa3,
-        0x6d,  0x51,  0xa3,  0x51,  0xa3,  0x51,  0x36,  0x29,  0x1b,  0x15};
+static char baud_bpr[] = {	/* 25 MHz baud rate period table */
+	0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
+	0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
+};
 #endif
 
 /* I think 166 brd clocks 2401 at 20MHz.... */
 
 /* These values are written directly to tcor, and >> 5 for writing to rcor */
-static u_char baud_co[] = {  /* 20 MHz clock option table */
-        0x00,  0x80,  0x80,  0x80,  0x80,  0x80,  0x80,  0x60,  0x60,  0x40,
-        0x40,  0x40,  0x20,  0x20,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00};
+static u_char baud_co[] = {	/* 20 MHz clock option table */
+	0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40,
+	0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
 
 /* These values written directly to tbpr/rbpr */
-static u_char baud_bpr[] = {  /* 20 MHz baud rate period table */
-        0x00,  0xc0,  0x80,  0x58,  0x6c,  0x40,  0xc0,  0x81,  0x40,  0x81,
-        0x57,  0x40,  0x81,  0x40,  0x81,  0x40,  0x2b,  0x20,  0x15,  0x10};
+static u_char baud_bpr[] = {	/* 20 MHz baud rate period table */
+	0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81,
+	0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10
+};
 
-static u_char baud_cor4[] = {  /* receive threshold */
-        0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,
-        0x0a,  0x0a,  0x0a,  0x09,  0x09,  0x08,  0x08,  0x08,  0x08,  0x07};
-
-
+static u_char baud_cor4[] = {	/* receive threshold */
+	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07
+};
 
 static void shutdown(struct cyclades_port *);
-static int startup (struct cyclades_port *);
+static int startup(struct cyclades_port *);
 static void cy_throttle(struct tty_struct *);
 static void cy_unthrottle(struct tty_struct *);
 static void config_setup(struct cyclades_port *);
@@ -174,16 +179,16 @@
 
 #ifdef CONFIG_REMOTE_DEBUG
 static void debug_setup(void);
-void queueDebugChar (int c);
+void queueDebugChar(int c);
 int getDebugChar(void);
 
 #define DEBUG_PORT	1
 #define DEBUG_LEN	256
 
 typedef struct {
-	int	in;
-	int	out;
-	unsigned char	buf[DEBUG_LEN];
+	int in;
+	int out;
+	unsigned char buf[DEBUG_LEN];
 } debugq;
 
 debugq debugiq;
@@ -196,7 +201,7 @@
  * delay, but this wild guess will do for now.
  */
 
-void my_udelay (long us)
+void my_udelay(long us)
 {
 	u_char x;
 	volatile u_char *p = &x;
@@ -207,62 +212,73 @@
 			x |= *p;
 }
 
-static inline int
-serial_paranoia_check(struct cyclades_port *info, char *name,
-		      const char *routine)
+static inline int serial_paranoia_check(struct cyclades_port *info, char *name,
+		const char *routine)
 {
 #ifdef SERIAL_PARANOIA_CHECK
-    static const char *badmagic =
-	"Warning: bad magic number for serial struct (%s) in %s\n";
-    static const char *badinfo =
-	"Warning: null cyclades_port for (%s) in %s\n";
-    static const char *badrange =
-	"Warning: cyclades_port out of range for (%s) in %s\n";
+	if (!info) {
+		printk("Warning: null cyclades_port for (%s) in %s\n", name,
+				routine);
+		return 1;
+	}
 
-    if (!info) {
-	printk(badinfo, name, routine);
-	return 1;
-    }
+	if ((long)info < (long)(&cy_port[0])
+	    || (long)(&cy_port[NR_PORTS]) < (long)info) {
+		printk("Warning: cyclades_port out of range for (%s) in %s\n",
+				name, routine);
+		return 1;
+	}
 
-    if( (long)info < (long)(&cy_port[0])
-    || (long)(&cy_port[NR_PORTS]) < (long)info ){
-	printk(badrange, name, routine);
-	return 1;
-    }
-
-    if (info->magic != CYCLADES_MAGIC) {
-	printk(badmagic, name, routine);
-	return 1;
-    }
+	if (info->magic != CYCLADES_MAGIC) {
+		printk("Warning: bad magic number for serial struct (%s) in "
+				"%s\n", name, routine);
+		return 1;
+	}
 #endif
 	return 0;
-} /* serial_paranoia_check */
+}				/* serial_paranoia_check */
 
 #if 0
 /* The following diagnostic routines allow the driver to spew
    information on the screen, even (especially!) during interrupts.
  */
-void
-SP(char *data){
-  unsigned long flags;
-    local_irq_save(flags);
-        console_print(data);
-    local_irq_restore(flags);
+void SP(char *data)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	console_print(data);
+	local_irq_restore(flags);
 }
-char scrn[2];
-void
-CP(char data){
-  unsigned long flags;
-    local_irq_save(flags);
-        scrn[0] = data;
-        console_print(scrn);
-    local_irq_restore(flags);
-}/* CP */
 
-void CP1(int data) { (data<10)?  CP(data+'0'): CP(data+'A'-10); }/* CP1 */
-void CP2(int data) { CP1((data>>4) & 0x0f); CP1( data & 0x0f); }/* CP2 */
-void CP4(int data) { CP2((data>>8) & 0xff); CP2(data & 0xff); }/* CP4 */
-void CP8(long data) { CP4((data>>16) & 0xffff); CP4(data & 0xffff); }/* CP8 */
+char scrn[2];
+void CP(char data)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	scrn[0] = data;
+	console_print(scrn);
+	local_irq_restore(flags);
+}				/* CP */
+
+void CP1(int data)
+{
+	(data < 10) ? CP(data + '0') : CP(data + 'A' - 10);
+}				/* CP1 */
+void CP2(int data)
+{
+	CP1((data >> 4) & 0x0f);
+	CP1(data & 0x0f);
+}				/* CP2 */
+void CP4(int data)
+{
+	CP2((data >> 8) & 0xff);
+	CP2(data & 0xff);
+}				/* CP4 */
+void CP8(long data)
+{
+	CP4((data >> 16) & 0xffff);
+	CP4(data & 0xffff);
+}				/* CP8 */
 #endif
 
 /* This routine waits up to 1000 micro-seconds for the previous
@@ -270,87 +286,78 @@
    new command.  An error is returned if the previous command
    didn't finish within the time limit.
  */
-u_short
-write_cy_cmd(volatile u_char *base_addr, u_char cmd)
+u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd)
 {
-  unsigned long flags;
-  volatile int  i;
+	unsigned long flags;
+	volatile int i;
 
-    local_irq_save(flags);
+	local_irq_save(flags);
 	/* Check to see that the previous command has completed */
-	for(i = 0 ; i < 100 ; i++){
-	    if (base_addr[CyCCR] == 0){
-		break;
-	    }
-	    my_udelay(10L);
+	for (i = 0; i < 100; i++) {
+		if (base_addr[CyCCR] == 0) {
+			break;
+		}
+		my_udelay(10L);
 	}
 	/* if the CCR never cleared, the previous command
-	    didn't finish within the "reasonable time" */
-	if ( i == 10 ) {
-	    local_irq_restore(flags);
-	    return (-1);
+	   didn't finish within the "reasonable time" */
+	if (i == 10) {
+		local_irq_restore(flags);
+		return (-1);
 	}
 
 	/* Issue the new command */
 	base_addr[CyCCR] = cmd;
-    local_irq_restore(flags);
-    return(0);
-} /* write_cy_cmd */
-
+	local_irq_restore(flags);
+	return (0);
+}				/* write_cy_cmd */
 
 /* cy_start and cy_stop provide software output flow control as a
    function of XON/XOFF, software CTS, and other such stuff. */
 
-static void
-cy_stop(struct tty_struct *tty)
+static void cy_stop(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-  int channel;
-  unsigned long flags;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+	unsigned long flags;
 
 #ifdef SERIAL_DEBUG_OTHER
-    printk("cy_stop %s\n", tty->name); /* */
+	printk("cy_stop %s\n", tty->name);	/* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_stop"))
-	return;
-	
-    channel = info->line;
+	if (serial_paranoia_check(info, tty->name, "cy_stop"))
+		return;
 
-    local_irq_save(flags);
-        base_addr[CyCAR] = (u_char)(channel); /* index channel */
-        base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
-    local_irq_restore(flags);
+	channel = info->line;
 
-    return;
-} /* cy_stop */
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) (channel);	/* index channel */
+	base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+	local_irq_restore(flags);
+}				/* cy_stop */
 
-static void
-cy_start(struct tty_struct *tty)
+static void cy_start(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-  int channel;
-  unsigned long flags;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+	unsigned long flags;
 
 #ifdef SERIAL_DEBUG_OTHER
-    printk("cy_start %s\n", tty->name); /* */
+	printk("cy_start %s\n", tty->name);	/* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_start"))
-	return;
-	
-    channel = info->line;
+	if (serial_paranoia_check(info, tty->name, "cy_start"))
+		return;
 
-    local_irq_save(flags);
-        base_addr[CyCAR] = (u_char)(channel);
-        base_addr[CyIER] |= CyTxMpty;
-    local_irq_restore(flags);
+	channel = info->line;
 
-    return;
-} /* cy_start */
-
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) (channel);
+	base_addr[CyIER] |= CyTxMpty;
+	local_irq_restore(flags);
+}				/* cy_start */
 
 /*
  * This routine is used by the interrupt handler to schedule
@@ -358,332 +365,332 @@
  * (also known as the "bottom half").  This can be called any
  * number of times for any channel without harm.
  */
-static inline void
-cy_sched_event(struct cyclades_port *info, int event)
+static inline void cy_sched_event(struct cyclades_port *info, int event)
 {
-    info->event |= 1 << event; /* remember what kind of event and who */
-    schedule_work(&info->tqueue);
-} /* cy_sched_event */
-
+	info->event |= 1 << event;	/* remember what kind of event and who */
+	schedule_work(&info->tqueue);
+}				/* cy_sched_event */
 
 /* The real interrupt service routines are called
    whenever the card wants its hand held--chars
    received, out buffer empty, modem change, etc.
  */
-static irqreturn_t
-cd2401_rxerr_interrupt(int irq, void *dev_id)
+static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id)
 {
-    struct tty_struct *tty;
-    struct cyclades_port *info;
-    volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-    unsigned char err, rfoc;
-    int channel;
-    char data;
+	struct tty_struct *tty;
+	struct cyclades_port *info;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	unsigned char err, rfoc;
+	int channel;
+	char data;
 
-    /* determine the channel and change to that context */
-    channel = (u_short ) (base_addr[CyLICR] >> 2);
-    info = &cy_port[channel];
-    info->last_active = jiffies;
+	/* determine the channel and change to that context */
+	channel = (u_short) (base_addr[CyLICR] >> 2);
+	info = &cy_port[channel];
+	info->last_active = jiffies;
 
-    if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
-	/* This is a receive timeout interrupt, ignore it */
-	base_addr[CyREOIR] = CyNOTRANS;
-	return IRQ_HANDLED;
-    }
+	if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
+		/* This is a receive timeout interrupt, ignore it */
+		base_addr[CyREOIR] = CyNOTRANS;
+		return IRQ_HANDLED;
+	}
 
-    /* Read a byte of data if there is any - assume the error
-     * is associated with this character */
+	/* Read a byte of data if there is any - assume the error
+	 * is associated with this character */
 
-    if ((rfoc = base_addr[CyRFOC]) != 0)
-	data = base_addr[CyRDR];
-    else
-	data = 0;
+	if ((rfoc = base_addr[CyRFOC]) != 0)
+		data = base_addr[CyRDR];
+	else
+		data = 0;
 
-    /* if there is nowhere to put the data, discard it */
-    if(info->tty == 0) {
+	/* if there is nowhere to put the data, discard it */
+	if (info->tty == 0) {
+		base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
+		return IRQ_HANDLED;
+	} else {		/* there is an open port for this data */
+		tty = info->tty;
+		if (err & info->ignore_status_mask) {
+			base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
+			return IRQ_HANDLED;
+		}
+		if (tty_buffer_request_room(tty, 1) != 0) {
+			if (err & info->read_status_mask) {
+				if (err & CyBREAK) {
+					tty_insert_flip_char(tty, data,
+							     TTY_BREAK);
+					if (info->flags & ASYNC_SAK) {
+						do_SAK(tty);
+					}
+				} else if (err & CyFRAME) {
+					tty_insert_flip_char(tty, data,
+							     TTY_FRAME);
+				} else if (err & CyPARITY) {
+					tty_insert_flip_char(tty, data,
+							     TTY_PARITY);
+				} else if (err & CyOVERRUN) {
+					tty_insert_flip_char(tty, 0,
+							     TTY_OVERRUN);
+					/*
+					   If the flip buffer itself is
+					   overflowing, we still loose
+					   the next incoming character.
+					 */
+					if (tty_buffer_request_room(tty, 1) !=
+					    0) {
+						tty_insert_flip_char(tty, data,
+								     TTY_FRAME);
+					}
+					/* These two conditions may imply */
+					/* a normal read should be done. */
+					/* else if(data & CyTIMEOUT) */
+					/* else if(data & CySPECHAR) */
+				} else {
+					tty_insert_flip_char(tty, 0,
+							     TTY_NORMAL);
+				}
+			} else {
+				tty_insert_flip_char(tty, data, TTY_NORMAL);
+			}
+		} else {
+			/* there was a software buffer overrun
+			   and nothing could be done about it!!! */
+		}
+	}
+	tty_schedule_flip(tty);
+	/* end of service */
 	base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
 	return IRQ_HANDLED;
-    }
-    else { /* there is an open port for this data */
-	tty = info->tty;
-	if(err & info->ignore_status_mask){
-	    base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-	    return IRQ_HANDLED;
-	}
-	if (tty_buffer_request_room(tty, 1) != 0){
-	    if (err & info->read_status_mask){
-		if(err & CyBREAK){
-		    tty_insert_flip_char(tty, data, TTY_BREAK);
-		    if (info->flags & ASYNC_SAK){
-			do_SAK(tty);
-		    }
-		}else if(err & CyFRAME){
-		    tty_insert_flip_char(tty, data, TTY_FRAME);
-		}else if(err & CyPARITY){
-		    tty_insert_flip_char(tty, data, TTY_PARITY);
-		}else if(err & CyOVERRUN){
-		    tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-		    /*
-		       If the flip buffer itself is
-		       overflowing, we still loose
-		       the next incoming character.
-		     */
-		    if (tty_buffer_request_room(tty, 1) != 0){
-			tty_insert_flip_char(tty, data, TTY_FRAME);
-		    }
-		/* These two conditions may imply */
-		/* a normal read should be done. */
-		/* else if(data & CyTIMEOUT) */
-		/* else if(data & CySPECHAR) */
-		}else{
-		    tty_insert_flip_char(tty, 0, TTY_NORMAL);
-		}
-	    }else{
-		tty_insert_flip_char(tty, data, TTY_NORMAL);
-	    }
-	}else{
-	    /* there was a software buffer overrun
-	       and nothing could be done about it!!! */
-	}
-    }
-    tty_schedule_flip(tty);
-    /* end of service */
-    base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-    return IRQ_HANDLED;
-} /* cy_rxerr_interrupt */
+}				/* cy_rxerr_interrupt */
 
-static irqreturn_t
-cd2401_modem_interrupt(int irq, void *dev_id)
+static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
 {
-    struct cyclades_port *info;
-    volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-    int channel;
-    int mdm_change;
-    int mdm_status;
+	struct cyclades_port *info;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+	int mdm_change;
+	int mdm_status;
 
+	/* determine the channel and change to that context */
+	channel = (u_short) (base_addr[CyLICR] >> 2);
+	info = &cy_port[channel];
+	info->last_active = jiffies;
 
-    /* determine the channel and change to that context */
-    channel = (u_short ) (base_addr[CyLICR] >> 2);
-    info = &cy_port[channel];
-    info->last_active = jiffies;
+	mdm_change = base_addr[CyMISR];
+	mdm_status = base_addr[CyMSVR1];
 
-    mdm_change = base_addr[CyMISR];
-    mdm_status = base_addr[CyMSVR1];
-
-    if(info->tty == 0){ /* nowhere to put the data, ignore it */
-	;
-    }else{
-	if((mdm_change & CyDCD)
-	&& (info->flags & ASYNC_CHECK_CD)){
-	    if(mdm_status & CyDCD){
+	if (info->tty == 0) {	/* nowhere to put the data, ignore it */
+		;
+	} else {
+		if ((mdm_change & CyDCD)
+		    && (info->flags & ASYNC_CHECK_CD)) {
+			if (mdm_status & CyDCD) {
 /* CP('!'); */
-		cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP);
-	    } else {
+				cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP);
+			} else {
 /* CP('@'); */
-		cy_sched_event(info, Cy_EVENT_HANGUP);
-	    }
-	}
-	if((mdm_change & CyCTS)
-	&& (info->flags & ASYNC_CTS_FLOW)){
-	    if(info->tty->stopped){
-		if(mdm_status & CyCTS){
-		    /* !!! cy_start isn't used because... */
-		    info->tty->stopped = 0;
-        	    base_addr[CyIER] |= CyTxMpty;
-		    cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+				cy_sched_event(info, Cy_EVENT_HANGUP);
+			}
 		}
-	    }else{
-		if(!(mdm_status & CyCTS)){
-		    /* !!! cy_stop isn't used because... */
-		    info->tty->stopped = 1;
-        	    base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
+		if ((mdm_change & CyCTS)
+		    && (info->flags & ASYNC_CTS_FLOW)) {
+			if (info->tty->stopped) {
+				if (mdm_status & CyCTS) {
+					/* !!! cy_start isn't used because... */
+					info->tty->stopped = 0;
+					base_addr[CyIER] |= CyTxMpty;
+					cy_sched_event(info,
+						       Cy_EVENT_WRITE_WAKEUP);
+				}
+			} else {
+				if (!(mdm_status & CyCTS)) {
+					/* !!! cy_stop isn't used because... */
+					info->tty->stopped = 1;
+					base_addr[CyIER] &=
+					    ~(CyTxMpty | CyTxRdy);
+				}
+			}
 		}
-	    }
+		if (mdm_status & CyDSR) {
+		}
 	}
-	if(mdm_status & CyDSR){
-	}
-    }
-    base_addr[CyMEOIR] = 0;
-    return IRQ_HANDLED;
-} /* cy_modem_interrupt */
+	base_addr[CyMEOIR] = 0;
+	return IRQ_HANDLED;
+}				/* cy_modem_interrupt */
 
-static irqreturn_t
-cd2401_tx_interrupt(int irq, void *dev_id)
+static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
 {
-    struct cyclades_port *info;
-    volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-    int channel;
-    int char_count, saved_cnt;
-    int outch;
+	struct cyclades_port *info;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+	int char_count, saved_cnt;
+	int outch;
 
-    /* determine the channel and change to that context */
-    channel = (u_short ) (base_addr[CyLICR] >> 2);
+	/* determine the channel and change to that context */
+	channel = (u_short) (base_addr[CyLICR] >> 2);
 
 #ifdef CONFIG_REMOTE_DEBUG
-    if (channel == DEBUG_PORT) {
-	panic ("TxInt on debug port!!!");
-    }
+	if (channel == DEBUG_PORT) {
+		panic("TxInt on debug port!!!");
+	}
 #endif
 
-    info = &cy_port[channel];
+	info = &cy_port[channel];
 
-    /* validate the port number (as configured and open) */
-    if( (channel < 0) || (NR_PORTS <= channel) ){
-	base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
-	base_addr[CyTEOIR] = CyNOTRANS;
-	return IRQ_HANDLED;
-    }
-    info->last_active = jiffies;
-    if(info->tty == 0){
-	base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
-        if (info->xmit_cnt < WAKEUP_CHARS) {
-	    cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
-        }
-	base_addr[CyTEOIR] = CyNOTRANS;
-	return IRQ_HANDLED;
-    }
-
-    /* load the on-chip space available for outbound data */
-    saved_cnt = char_count = base_addr[CyTFTC];
-
-    if(info->x_char) { /* send special char */
-	outch = info->x_char;
-	base_addr[CyTDR] = outch;
-	char_count--;
-	info->x_char = 0;
-    }
-
-    if (info->x_break){
-	/*  The Cirrus chip requires the "Embedded Transmit
-	    Commands" of start break, delay, and end break
-	    sequences to be sent.  The duration of the
-	    break is given in TICs, which runs at HZ
-	    (typically 100) and the PPR runs at 200 Hz,
-	    so the delay is duration * 200/HZ, and thus a
-	    break can run from 1/100 sec to about 5/4 sec.
-	    Need to check these values - RGH 141095.
-	 */
-	base_addr[CyTDR] = 0; /* start break */
-	base_addr[CyTDR] = 0x81;
-	base_addr[CyTDR] = 0; /* delay a bit */
-	base_addr[CyTDR] = 0x82;
-	base_addr[CyTDR] = info->x_break*200/HZ;
-	base_addr[CyTDR] = 0; /* terminate break */
-	base_addr[CyTDR] = 0x83;
-	char_count -= 7;
-	info->x_break = 0;
-    }
-
-    while (char_count > 0){
-	if (!info->xmit_cnt){
-	    base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
-	    break;
+	/* validate the port number (as configured and open) */
+	if ((channel < 0) || (NR_PORTS <= channel)) {
+		base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+		base_addr[CyTEOIR] = CyNOTRANS;
+		return IRQ_HANDLED;
 	}
-	if (info->xmit_buf == 0){
-	    base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
-	    break;
+	info->last_active = jiffies;
+	if (info->tty == 0) {
+		base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+		if (info->xmit_cnt < WAKEUP_CHARS) {
+			cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+		}
+		base_addr[CyTEOIR] = CyNOTRANS;
+		return IRQ_HANDLED;
 	}
-	if (info->tty->stopped || info->tty->hw_stopped){
-	    base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
-	    break;
-	}
-	/* Because the Embedded Transmit Commands have been
-	   enabled, we must check to see if the escape
-	   character, NULL, is being sent.  If it is, we
-	   must ensure that there is room for it to be
-	   doubled in the output stream.  Therefore we
-	   no longer advance the pointer when the character
-	   is fetched, but rather wait until after the check
-	   for a NULL output character. (This is necessary
-	   because there may not be room for the two chars
-	   needed to send a NULL.
-	 */
-	outch = info->xmit_buf[info->xmit_tail];
-	if( outch ){
-	    info->xmit_cnt--;
-	    info->xmit_tail = (info->xmit_tail + 1)
-				      & (PAGE_SIZE - 1);
-	    base_addr[CyTDR] = outch;
-	    char_count--;
-	}else{
-	    if(char_count > 1){
-		info->xmit_cnt--;
-		info->xmit_tail = (info->xmit_tail + 1)
-					  & (PAGE_SIZE - 1);
+
+	/* load the on-chip space available for outbound data */
+	saved_cnt = char_count = base_addr[CyTFTC];
+
+	if (info->x_char) {	/* send special char */
+		outch = info->x_char;
 		base_addr[CyTDR] = outch;
-		base_addr[CyTDR] = 0;
 		char_count--;
-		char_count--;
-	    }else{
-		break;
-	    }
+		info->x_char = 0;
 	}
-    }
 
-    if (info->xmit_cnt < WAKEUP_CHARS) {
-	cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
-    }
-    base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
-    return IRQ_HANDLED;
-} /* cy_tx_interrupt */
+	if (info->x_break) {
+		/*  The Cirrus chip requires the "Embedded Transmit
+		   Commands" of start break, delay, and end break
+		   sequences to be sent.  The duration of the
+		   break is given in TICs, which runs at HZ
+		   (typically 100) and the PPR runs at 200 Hz,
+		   so the delay is duration * 200/HZ, and thus a
+		   break can run from 1/100 sec to about 5/4 sec.
+		   Need to check these values - RGH 141095.
+		 */
+		base_addr[CyTDR] = 0;	/* start break */
+		base_addr[CyTDR] = 0x81;
+		base_addr[CyTDR] = 0;	/* delay a bit */
+		base_addr[CyTDR] = 0x82;
+		base_addr[CyTDR] = info->x_break * 200 / HZ;
+		base_addr[CyTDR] = 0;	/* terminate break */
+		base_addr[CyTDR] = 0x83;
+		char_count -= 7;
+		info->x_break = 0;
+	}
 
-static irqreturn_t
-cd2401_rx_interrupt(int irq, void *dev_id)
+	while (char_count > 0) {
+		if (!info->xmit_cnt) {
+			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+			break;
+		}
+		if (info->xmit_buf == 0) {
+			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+			break;
+		}
+		if (info->tty->stopped || info->tty->hw_stopped) {
+			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+			break;
+		}
+		/* Because the Embedded Transmit Commands have been
+		   enabled, we must check to see if the escape
+		   character, NULL, is being sent.  If it is, we
+		   must ensure that there is room for it to be
+		   doubled in the output stream.  Therefore we
+		   no longer advance the pointer when the character
+		   is fetched, but rather wait until after the check
+		   for a NULL output character. (This is necessary
+		   because there may not be room for the two chars
+		   needed to send a NULL.
+		 */
+		outch = info->xmit_buf[info->xmit_tail];
+		if (outch) {
+			info->xmit_cnt--;
+			info->xmit_tail = (info->xmit_tail + 1)
+			    & (PAGE_SIZE - 1);
+			base_addr[CyTDR] = outch;
+			char_count--;
+		} else {
+			if (char_count > 1) {
+				info->xmit_cnt--;
+				info->xmit_tail = (info->xmit_tail + 1)
+				    & (PAGE_SIZE - 1);
+				base_addr[CyTDR] = outch;
+				base_addr[CyTDR] = 0;
+				char_count--;
+				char_count--;
+			} else {
+				break;
+			}
+		}
+	}
+
+	if (info->xmit_cnt < WAKEUP_CHARS) {
+		cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+	}
+	base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
+	return IRQ_HANDLED;
+}				/* cy_tx_interrupt */
+
+static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
 {
-    struct tty_struct *tty;
-    struct cyclades_port *info;
-    volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-    int channel;
-    char data;
-    int char_count;
-    int save_cnt;
-    int len;
+	struct tty_struct *tty;
+	struct cyclades_port *info;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+	char data;
+	int char_count;
+	int save_cnt;
+	int len;
 
-    /* determine the channel and change to that context */
-    channel = (u_short ) (base_addr[CyLICR] >> 2);
-    info = &cy_port[channel];
-    info->last_active = jiffies;
-    save_cnt = char_count = base_addr[CyRFOC];
+	/* determine the channel and change to that context */
+	channel = (u_short) (base_addr[CyLICR] >> 2);
+	info = &cy_port[channel];
+	info->last_active = jiffies;
+	save_cnt = char_count = base_addr[CyRFOC];
 
 #ifdef CONFIG_REMOTE_DEBUG
-    if (channel == DEBUG_PORT) {
-	while (char_count--) {
-            data = base_addr[CyRDR];
-	    queueDebugChar(data);
-	}
-    }
-    else
+	if (channel == DEBUG_PORT) {
+		while (char_count--) {
+			data = base_addr[CyRDR];
+			queueDebugChar(data);
+		}
+	} else
 #endif
-    /* if there is nowhere to put the data, discard it */
-    if(info->tty == 0){
-	while(char_count--){
-	    data = base_addr[CyRDR];
-	}
-    }else{ /* there is an open port for this data */
-	tty = info->tty;
-	/* load # characters available from the chip */
+		/* if there is nowhere to put the data, discard it */
+	if (info->tty == 0) {
+		while (char_count--) {
+			data = base_addr[CyRDR];
+		}
+	} else {		/* there is an open port for this data */
+		tty = info->tty;
+		/* load # characters available from the chip */
 
 #ifdef CYCLOM_ENABLE_MONITORING
-	++info->mon.int_count;
-	info->mon.char_count += char_count;
-	if (char_count > info->mon.char_max)
-	    info->mon.char_max = char_count;
-	info->mon.char_last = char_count;
+		++info->mon.int_count;
+		info->mon.char_count += char_count;
+		if (char_count > info->mon.char_max)
+			info->mon.char_max = char_count;
+		info->mon.char_last = char_count;
 #endif
-	len = tty_buffer_request_room(tty, char_count);
-	while(len--){
-	    data = base_addr[CyRDR];
-	    tty_insert_flip_char(tty, data, TTY_NORMAL);
+		len = tty_buffer_request_room(tty, char_count);
+		while (len--) {
+			data = base_addr[CyRDR];
+			tty_insert_flip_char(tty, data, TTY_NORMAL);
 #ifdef CYCLOM_16Y_HACK
-	    udelay(10L);
+			udelay(10L);
 #endif
-        }
-	tty_schedule_flip(tty);
-    }
-    /* end of service */
-    base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
-    return IRQ_HANDLED;
-} /* cy_rx_interrupt */
+		}
+		tty_schedule_flip(tty);
+	}
+	/* end of service */
+	base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
+	return IRQ_HANDLED;
+}				/* cy_rx_interrupt */
 
 /*
  * This routine is used to handle the "bottom half" processing for the
@@ -705,192 +712,188 @@
  * structure) to the bottom half of the driver.  Previous kernels
  * had to poll every port to see if that port needed servicing.
  */
-static void
-do_softint(struct work_struct *ugly_api)
+static void do_softint(struct work_struct *ugly_api)
 {
-  struct cyclades_port *info = container_of(ugly_api, struct cyclades_port, tqueue);
-  struct tty_struct    *tty;
+	struct cyclades_port *info =
+	    container_of(ugly_api, struct cyclades_port, tqueue);
+	struct tty_struct *tty;
 
-    tty = info->tty;
-    if (!tty)
-	return;
+	tty = info->tty;
+	if (!tty)
+		return;
 
-    if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
-	tty_hangup(info->tty);
-	wake_up_interruptible(&info->open_wait);
-	info->flags &= ~ASYNC_NORMAL_ACTIVE;
-    }
-    if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
-	wake_up_interruptible(&info->open_wait);
-    }
-    if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
-    	tty_wakeup(tty);
-    }
-} /* do_softint */
-
+	if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
+		tty_hangup(info->tty);
+		wake_up_interruptible(&info->open_wait);
+		info->flags &= ~ASYNC_NORMAL_ACTIVE;
+	}
+	if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
+		wake_up_interruptible(&info->open_wait);
+	}
+	if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
+		tty_wakeup(tty);
+	}
+}				/* do_softint */
 
 /* This is called whenever a port becomes active;
    interrupts are enabled and DTR & RTS are turned on.
  */
-static int
-startup(struct cyclades_port * info)
+static int startup(struct cyclades_port *info)
 {
-  unsigned long flags;
-  volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-  int channel;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
 
-    if (info->flags & ASYNC_INITIALIZED){
-	return 0;
-    }
-
-    if (!info->type){
-	if (info->tty){
-	    set_bit(TTY_IO_ERROR, &info->tty->flags);
+	if (info->flags & ASYNC_INITIALIZED) {
+		return 0;
 	}
-	return 0;
-    }
-    if (!info->xmit_buf){
-	info->xmit_buf = (unsigned char *) get_zeroed_page (GFP_KERNEL);
-	if (!info->xmit_buf){
-	    return -ENOMEM;
+
+	if (!info->type) {
+		if (info->tty) {
+			set_bit(TTY_IO_ERROR, &info->tty->flags);
+		}
+		return 0;
 	}
-    }
+	if (!info->xmit_buf) {
+		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
+		if (!info->xmit_buf) {
+			return -ENOMEM;
+		}
+	}
 
-    config_setup(info);
+	config_setup(info);
 
-    channel = info->line;
+	channel = info->line;
 
 #ifdef SERIAL_DEBUG_OPEN
-    printk("startup channel %d\n", channel);
+	printk("startup channel %d\n", channel);
 #endif
 
-    local_irq_save(flags);
-	base_addr[CyCAR] = (u_char)channel;
-	write_cy_cmd(base_addr,CyENB_RCVR|CyENB_XMTR);
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) channel;
+	write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
 
-	base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */
+	base_addr[CyCAR] = (u_char) channel;	/* !!! Is this needed? */
 	base_addr[CyMSVR1] = CyRTS;
 /* CP('S');CP('1'); */
 	base_addr[CyMSVR2] = CyDTR;
 
 #ifdef SERIAL_DEBUG_DTR
-        printk("cyc: %d: raising DTR\n", __LINE__);
-        printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+	printk("cyc: %d: raising DTR\n", __LINE__);
+	printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+	       base_addr[CyMSVR2]);
 #endif
 
 	base_addr[CyIER] |= CyRxData;
 	info->flags |= ASYNC_INITIALIZED;
 
-	if (info->tty){
-	    clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	if (info->tty) {
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
 	}
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 
-    local_irq_restore(flags);
+	local_irq_restore(flags);
 
 #ifdef SERIAL_DEBUG_OPEN
-    printk(" done\n");
+	printk(" done\n");
 #endif
-    return 0;
-} /* startup */
+	return 0;
+}				/* startup */
 
-void
-start_xmit( struct cyclades_port *info )
+void start_xmit(struct cyclades_port *info)
 {
-  unsigned long flags;
-  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-  int channel;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
 
-    channel = info->line;
-    local_irq_save(flags);
+	channel = info->line;
+	local_irq_save(flags);
 	base_addr[CyCAR] = channel;
 	base_addr[CyIER] |= CyTxMpty;
-    local_irq_restore(flags);
-} /* start_xmit */
+	local_irq_restore(flags);
+}				/* start_xmit */
 
 /*
  * This routine shuts down a serial port; interrupts are disabled,
  * and DTR is dropped if the hangup on close termio flag is on.
  */
-static void
-shutdown(struct cyclades_port * info)
+static void shutdown(struct cyclades_port *info)
 {
-  unsigned long flags;
-  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-  int channel;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
 
-    if (!(info->flags & ASYNC_INITIALIZED)){
+	if (!(info->flags & ASYNC_INITIALIZED)) {
 /* CP('$'); */
-	return;
-    }
-
-    channel = info->line;
-
-#ifdef SERIAL_DEBUG_OPEN
-    printk("shutdown channel %d\n", channel);
-#endif
-
-    /* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE
-       SENT BEFORE DROPPING THE LINE !!!  (Perhaps
-       set some flag that is read when XMTY happens.)
-       Other choices are to delay some fixed interval
-       or schedule some later processing.
-     */
-    local_irq_save(flags);
-	if (info->xmit_buf){
-	    free_page((unsigned long) info->xmit_buf);
-	    info->xmit_buf = NULL;
+		return;
 	}
 
-	base_addr[CyCAR] = (u_char)channel;
-	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-	    base_addr[CyMSVR1] = 0;
-/* CP('C');CP('1'); */
-	    base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-            printk("cyc: %d: dropping DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
-#endif
-        }
-	write_cy_cmd(base_addr,CyDIS_RCVR);
-         /* it may be appropriate to clear _XMIT at
-           some later date (after testing)!!! */
+	channel = info->line;
 
-	if (info->tty){
-	    set_bit(TTY_IO_ERROR, &info->tty->flags);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("shutdown channel %d\n", channel);
+#endif
+
+	/* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE
+	   SENT BEFORE DROPPING THE LINE !!!  (Perhaps
+	   set some flag that is read when XMTY happens.)
+	   Other choices are to delay some fixed interval
+	   or schedule some later processing.
+	 */
+	local_irq_save(flags);
+	if (info->xmit_buf) {
+		free_page((unsigned long)info->xmit_buf);
+		info->xmit_buf = NULL;
+	}
+
+	base_addr[CyCAR] = (u_char) channel;
+	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+		base_addr[CyMSVR1] = 0;
+/* CP('C');CP('1'); */
+		base_addr[CyMSVR2] = 0;
+#ifdef SERIAL_DEBUG_DTR
+		printk("cyc: %d: dropping DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
+#endif
+	}
+	write_cy_cmd(base_addr, CyDIS_RCVR);
+	/* it may be appropriate to clear _XMIT at
+	   some later date (after testing)!!! */
+
+	if (info->tty) {
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
 	}
 	info->flags &= ~ASYNC_INITIALIZED;
-    local_irq_restore(flags);
+	local_irq_restore(flags);
 
 #ifdef SERIAL_DEBUG_OPEN
-    printk(" done\n");
+	printk(" done\n");
 #endif
-    return;
-} /* shutdown */
+}				/* shutdown */
 
 /*
  * This routine finds or computes the various line characteristics.
  */
-static void
-config_setup(struct cyclades_port * info)
+static void config_setup(struct cyclades_port *info)
 {
-  unsigned long flags;
-  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-  int channel;
-  unsigned cflag;
-  int   i;
-  unsigned char ti, need_init_chan = 0;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+	unsigned cflag;
+	int i;
+	unsigned char ti, need_init_chan = 0;
 
-    if (!info->tty || !info->tty->termios){
-        return;
-    }
-    if (info->line == -1){
-        return;
-    }
-    cflag = info->tty->termios->c_cflag;
+	if (!info->tty || !info->tty->termios) {
+		return;
+	}
+	if (info->line == -1) {
+		return;
+	}
+	cflag = info->tty->termios->c_cflag;
 
-    /* baud rate */
-    i = cflag & CBAUD;
+	/* baud rate */
+	i = cflag & CBAUD;
 #ifdef CBAUDEX
 /* Starting with kernel 1.1.65, there is direct support for
    higher baud rates.  The following code supports those
@@ -900,120 +903,123 @@
    is still the possibility of supporting 75 kbit/sec with
    the Cyclades board.)
  */
-    if (i & CBAUDEX) {
-	if (i == B57600)
-	    i = 16;
-	else if(i == B115200) 
-	    i = 18;
+	if (i & CBAUDEX) {
+		if (i == B57600)
+			i = 16;
+		else if (i == B115200)
+			i = 18;
 #ifdef B78600
-	else if(i == B78600) 
-	    i = 17;
+		else if (i == B78600)
+			i = 17;
 #endif
-	else
-	    info->tty->termios->c_cflag &= ~CBAUDEX;
-    }
-#endif
-    if (i == 15) {
-	    if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-		    i += 1;
-	    if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-		    i += 3;
-    }
-    /* Don't ever change the speed of the console port.  It will
-     * run at the speed specified in bootinfo, or at 19.2K */
-    /* Actually, it should run at whatever speed 166Bug was using */
-    /* Note info->timeout isn't used at present */
-    if (info != serial_console_info) {
-	info->tbpr = baud_bpr[i]; /* Tx BPR */
-	info->tco = baud_co[i]; /* Tx CO */
-	info->rbpr = baud_bpr[i]; /* Rx BPR */
-	info->rco = baud_co[i] >> 5; /* Rx CO */
-	if (baud_table[i] == 134) {
-            info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
-            /* get it right for 134.5 baud */
-	} else if (baud_table[i]) {
-            info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2;
-        /* this needs to be propagated into the card info */
-	} else {
-            info->timeout = 0;
+		else
+			info->tty->termios->c_cflag &= ~CBAUDEX;
 	}
-    }
-    /* By tradition (is it a standard?) a baud rate of zero
-       implies the line should be/has been closed.  A bit
-       later in this routine such a test is performed. */
-
-    /* byte size and parity */
-    info->cor7 = 0;
-    info->cor6 = 0;
-    info->cor5 = 0;
-    info->cor4 = (info->default_threshold
-		  ? info->default_threshold
-		  : baud_cor4[i]); /* receive threshold */
-    /* Following two lines added 101295, RGH. */
-    /* It is obviously wrong to access CyCORx, and not info->corx here,
-     * try and remember to fix it later! */
-    channel = info->line;
-    base_addr[CyCAR] = (u_char)channel;
-    if (C_CLOCAL(info->tty)) {
-	if (base_addr[CyIER] & CyMdmCh)
-	    base_addr[CyIER] &= ~CyMdmCh; /* without modem intr */
-			       /* ignore 1->0 modem transitions */
-	if (base_addr[CyCOR4] & (CyDSR|CyCTS|CyDCD))
-	    base_addr[CyCOR4] &= ~(CyDSR|CyCTS|CyDCD);
-			       /* ignore 0->1 modem transitions */
-	if (base_addr[CyCOR5] & (CyDSR|CyCTS|CyDCD))
-	    base_addr[CyCOR5] &= ~(CyDSR|CyCTS|CyDCD);
-    } else {
-	if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh)
-	    base_addr[CyIER] |= CyMdmCh; /* with modem intr */
-			       /* act on 1->0 modem transitions */
-	if ((base_addr[CyCOR4] & (CyDSR|CyCTS|CyDCD)) != (CyDSR|CyCTS|CyDCD))
-	    base_addr[CyCOR4] |= CyDSR|CyCTS|CyDCD;
-			       /* act on 0->1 modem transitions */
-	if ((base_addr[CyCOR5] & (CyDSR|CyCTS|CyDCD)) != (CyDSR|CyCTS|CyDCD))
-	    base_addr[CyCOR5] |= CyDSR|CyCTS|CyDCD;
-    }
-    info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP;
-    info->cor2 = CyETC;
-    switch(cflag & CSIZE){
-    case CS5:
-        info->cor1 = Cy_5_BITS;
-        break;
-    case CS6:
-        info->cor1 = Cy_6_BITS;
-        break;
-    case CS7:
-        info->cor1 = Cy_7_BITS;
-        break;
-    case CS8:
-        info->cor1 = Cy_8_BITS;
-        break;
-    }
-    if (cflag & PARENB){
-        if (cflag & PARODD){
-            info->cor1 |= CyPARITY_O;
-        }else{
-            info->cor1 |= CyPARITY_E;
-        }
-    }else{
-        info->cor1 |= CyPARITY_NONE;
-    }
-	
-    /* CTS flow control flag */
-#if 0
-    /* Don't complcate matters for now! RGH 141095 */
-    if (cflag & CRTSCTS){
-	info->flags |= ASYNC_CTS_FLOW;
-	info->cor2 |= CyCtsAE;
-    }else{
-	info->flags &= ~ASYNC_CTS_FLOW;
-	info->cor2 &= ~CyCtsAE;
-    }
 #endif
-    if (cflag & CLOCAL)
-	info->flags &= ~ASYNC_CHECK_CD;
-    else
-	info->flags |= ASYNC_CHECK_CD;
+	if (i == 15) {
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			i += 1;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			i += 3;
+	}
+	/* Don't ever change the speed of the console port.  It will
+	 * run at the speed specified in bootinfo, or at 19.2K */
+	/* Actually, it should run at whatever speed 166Bug was using */
+	/* Note info->timeout isn't used at present */
+	if (info != serial_console_info) {
+		info->tbpr = baud_bpr[i];	/* Tx BPR */
+		info->tco = baud_co[i];	/* Tx CO */
+		info->rbpr = baud_bpr[i];	/* Rx BPR */
+		info->rco = baud_co[i] >> 5;	/* Rx CO */
+		if (baud_table[i] == 134) {
+			info->timeout =
+			    (info->xmit_fifo_size * HZ * 30 / 269) + 2;
+			/* get it right for 134.5 baud */
+		} else if (baud_table[i]) {
+			info->timeout =
+			    (info->xmit_fifo_size * HZ * 15 / baud_table[i]) +
+			    2;
+			/* this needs to be propagated into the card info */
+		} else {
+			info->timeout = 0;
+		}
+	}
+	/* By tradition (is it a standard?) a baud rate of zero
+	   implies the line should be/has been closed.  A bit
+	   later in this routine such a test is performed. */
+
+	/* byte size and parity */
+	info->cor7 = 0;
+	info->cor6 = 0;
+	info->cor5 = 0;
+	info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]);	/* receive threshold */
+	/* Following two lines added 101295, RGH. */
+	/* It is obviously wrong to access CyCORx, and not info->corx here,
+	 * try and remember to fix it later! */
+	channel = info->line;
+	base_addr[CyCAR] = (u_char) channel;
+	if (C_CLOCAL(info->tty)) {
+		if (base_addr[CyIER] & CyMdmCh)
+			base_addr[CyIER] &= ~CyMdmCh;	/* without modem intr */
+		/* ignore 1->0 modem transitions */
+		if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD))
+			base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD);
+		/* ignore 0->1 modem transitions */
+		if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD))
+			base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD);
+	} else {
+		if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh)
+			base_addr[CyIER] |= CyMdmCh;	/* with modem intr */
+		/* act on 1->0 modem transitions */
+		if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) !=
+		    (CyDSR | CyCTS | CyDCD))
+			base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD;
+		/* act on 0->1 modem transitions */
+		if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) !=
+		    (CyDSR | CyCTS | CyDCD))
+			base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD;
+	}
+	info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP;
+	info->cor2 = CyETC;
+	switch (cflag & CSIZE) {
+	case CS5:
+		info->cor1 = Cy_5_BITS;
+		break;
+	case CS6:
+		info->cor1 = Cy_6_BITS;
+		break;
+	case CS7:
+		info->cor1 = Cy_7_BITS;
+		break;
+	case CS8:
+		info->cor1 = Cy_8_BITS;
+		break;
+	}
+	if (cflag & PARENB) {
+		if (cflag & PARODD) {
+			info->cor1 |= CyPARITY_O;
+		} else {
+			info->cor1 |= CyPARITY_E;
+		}
+	} else {
+		info->cor1 |= CyPARITY_NONE;
+	}
+
+	/* CTS flow control flag */
+#if 0
+	/* Don't complcate matters for now! RGH 141095 */
+	if (cflag & CRTSCTS) {
+		info->flags |= ASYNC_CTS_FLOW;
+		info->cor2 |= CyCtsAE;
+	} else {
+		info->flags &= ~ASYNC_CTS_FLOW;
+		info->cor2 &= ~CyCtsAE;
+	}
+#endif
+	if (cflag & CLOCAL)
+		info->flags &= ~ASYNC_CHECK_CD;
+	else
+		info->flags |= ASYNC_CHECK_CD;
 
      /***********************************************
 	The hardware option, CyRtsAO, presents RTS when
@@ -1025,149 +1031,146 @@
 	cable.  Contact Marcio Saito for details.
      ***********************************************/
 
-    channel = info->line;
+	channel = info->line;
 
-    local_irq_save(flags);
-	base_addr[CyCAR] = (u_char)channel;
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) channel;
 
 	/* CyCMR set once only in mvme167_init_serial() */
 	if (base_addr[CyLICR] != channel << 2)
-	    base_addr[CyLICR] = channel << 2;
+		base_addr[CyLICR] = channel << 2;
 	if (base_addr[CyLIVR] != 0x5c)
-	    base_addr[CyLIVR] = 0x5c;
+		base_addr[CyLIVR] = 0x5c;
 
-       /* tx and rx baud rate */
+	/* tx and rx baud rate */
 
 	if (base_addr[CyCOR1] != info->cor1)
-	    need_init_chan = 1;
+		need_init_chan = 1;
 	if (base_addr[CyTCOR] != info->tco)
-	    base_addr[CyTCOR] = info->tco;
+		base_addr[CyTCOR] = info->tco;
 	if (base_addr[CyTBPR] != info->tbpr)
-	    base_addr[CyTBPR] = info->tbpr;
+		base_addr[CyTBPR] = info->tbpr;
 	if (base_addr[CyRCOR] != info->rco)
-	    base_addr[CyRCOR] = info->rco;
+		base_addr[CyRCOR] = info->rco;
 	if (base_addr[CyRBPR] != info->rbpr)
-	    base_addr[CyRBPR] = info->rbpr;
+		base_addr[CyRBPR] = info->rbpr;
 
 	/* set line characteristics  according configuration */
 
 	if (base_addr[CySCHR1] != START_CHAR(info->tty))
-	    base_addr[CySCHR1] = START_CHAR(info->tty);
+		base_addr[CySCHR1] = START_CHAR(info->tty);
 	if (base_addr[CySCHR2] != STOP_CHAR(info->tty))
-	    base_addr[CySCHR2] = STOP_CHAR(info->tty);
+		base_addr[CySCHR2] = STOP_CHAR(info->tty);
 	if (base_addr[CySCRL] != START_CHAR(info->tty))
-	    base_addr[CySCRL] = START_CHAR(info->tty);
+		base_addr[CySCRL] = START_CHAR(info->tty);
 	if (base_addr[CySCRH] != START_CHAR(info->tty))
-	    base_addr[CySCRH] = START_CHAR(info->tty);
+		base_addr[CySCRH] = START_CHAR(info->tty);
 	if (base_addr[CyCOR1] != info->cor1)
-	    base_addr[CyCOR1] = info->cor1;
+		base_addr[CyCOR1] = info->cor1;
 	if (base_addr[CyCOR2] != info->cor2)
-	    base_addr[CyCOR2] = info->cor2;
+		base_addr[CyCOR2] = info->cor2;
 	if (base_addr[CyCOR3] != info->cor3)
-	    base_addr[CyCOR3] = info->cor3;
+		base_addr[CyCOR3] = info->cor3;
 	if (base_addr[CyCOR4] != info->cor4)
-	    base_addr[CyCOR4] = info->cor4;
+		base_addr[CyCOR4] = info->cor4;
 	if (base_addr[CyCOR5] != info->cor5)
-	    base_addr[CyCOR5] = info->cor5;
+		base_addr[CyCOR5] = info->cor5;
 	if (base_addr[CyCOR6] != info->cor6)
-	    base_addr[CyCOR6] = info->cor6;
+		base_addr[CyCOR6] = info->cor6;
 	if (base_addr[CyCOR7] != info->cor7)
-	    base_addr[CyCOR7] = info->cor7;
+		base_addr[CyCOR7] = info->cor7;
 
 	if (need_init_chan)
-	    write_cy_cmd(base_addr,CyINIT_CHAN);
+		write_cy_cmd(base_addr, CyINIT_CHAN);
 
-	base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */
+	base_addr[CyCAR] = (u_char) channel;	/* !!! Is this needed? */
 
 	/* 2ms default rx timeout */
 	ti = info->default_timeout ? info->default_timeout : 0x02;
 	if (base_addr[CyRTPRL] != ti)
-	    base_addr[CyRTPRL] = ti;
+		base_addr[CyRTPRL] = ti;
 	if (base_addr[CyRTPRH] != 0)
-	    base_addr[CyRTPRH] = 0;
+		base_addr[CyRTPRH] = 0;
 
 	/* Set up RTS here also ????? RGH 141095 */
-	if(i == 0){ /* baud rate is zero, turn off line */
-	    if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
-	        base_addr[CyMSVR2] = 0;
+	if (i == 0) {		/* baud rate is zero, turn off line */
+		if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
+			base_addr[CyMSVR2] = 0;
 #ifdef SERIAL_DEBUG_DTR
-            printk("cyc: %d: dropping DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+		printk("cyc: %d: dropping DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
 #endif
-	}else{
-	    if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
-	        base_addr[CyMSVR2] = CyDTR;
+	} else {
+		if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
+			base_addr[CyMSVR2] = CyDTR;
 #ifdef SERIAL_DEBUG_DTR
-            printk("cyc: %d: raising DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+		printk("cyc: %d: raising DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
 #endif
 	}
 
-	if (info->tty){
-	    clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	if (info->tty) {
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
 	}
 
-    local_irq_restore(flags);
+	local_irq_restore(flags);
 
-} /* config_setup */
+}				/* config_setup */
 
-
-static void
-cy_put_char(struct tty_struct *tty, unsigned char ch)
+static void cy_put_char(struct tty_struct *tty, unsigned char ch)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	unsigned long flags;
 
 #ifdef SERIAL_DEBUG_IO
-    printk("cy_put_char %s(0x%02x)\n", tty->name, ch);
+	printk("cy_put_char %s(0x%02x)\n", tty->name, ch);
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_put_char"))
-	return;
+	if (serial_paranoia_check(info, tty->name, "cy_put_char"))
+		return;
 
-    if (!info->xmit_buf)
-	return;
+	if (!info->xmit_buf)
+		return;
 
-    local_irq_save(flags);
+	local_irq_save(flags);
 	if (info->xmit_cnt >= PAGE_SIZE - 1) {
-	    local_irq_restore(flags);
-	    return;
+		local_irq_restore(flags);
+		return;
 	}
 
 	info->xmit_buf[info->xmit_head++] = ch;
 	info->xmit_head &= PAGE_SIZE - 1;
 	info->xmit_cnt++;
-    local_irq_restore(flags);
-} /* cy_put_char */
+	local_irq_restore(flags);
+}				/* cy_put_char */
 
-
-static void
-cy_flush_chars(struct tty_struct *tty)
+static void cy_flush_chars(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
-  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-  int channel;
-				
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+
 #ifdef SERIAL_DEBUG_IO
-    printk("cy_flush_chars %s\n", tty->name); /* */
+	printk("cy_flush_chars %s\n", tty->name);	/* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
-	return;
+	if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
+		return;
 
-    if (info->xmit_cnt <= 0 || tty->stopped
-    || tty->hw_stopped || !info->xmit_buf)
-	return;
+	if (info->xmit_cnt <= 0 || tty->stopped
+	    || tty->hw_stopped || !info->xmit_buf)
+		return;
 
-    channel = info->line;
+	channel = info->line;
 
-    local_irq_save(flags);
+	local_irq_save(flags);
 	base_addr[CyCAR] = channel;
 	base_addr[CyIER] |= CyTxMpty;
-    local_irq_restore(flags);
-} /* cy_flush_chars */
-
+	local_irq_restore(flags);
+}				/* cy_flush_chars */
 
 /* This routine gets called when tty_write has put something into
     the write_queue.  If the port is not already transmitting stuff,
@@ -1175,650 +1178,616 @@
     routine will then ensure that the characters are sent.  If the
     port is already active, there is no need to kick it.
  */
-static int
-cy_write(struct tty_struct * tty,
-           const unsigned char *buf, int count)
+static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
-  int c, total = 0;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	unsigned long flags;
+	int c, total = 0;
 
 #ifdef SERIAL_DEBUG_IO
-    printk("cy_write %s\n", tty->name); /* */
+	printk("cy_write %s\n", tty->name);	/* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_write")){
-	return 0;
-    }
-	
-    if (!info->xmit_buf){
-        return 0;
-    }
+	if (serial_paranoia_check(info, tty->name, "cy_write")) {
+		return 0;
+	}
 
-    while (1) {
-	    local_irq_save(flags);
-	    c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				      SERIAL_XMIT_SIZE - info->xmit_head));
-	    if (c <= 0) {
-		    local_irq_restore(flags);
-		    break;
-	    }
+	if (!info->xmit_buf) {
+		return 0;
+	}
 
-	    memcpy(info->xmit_buf + info->xmit_head, buf, c);
-	    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-	    info->xmit_cnt += c;
-	    local_irq_restore(flags);
+	while (1) {
+		local_irq_save(flags);
+		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					  SERIAL_XMIT_SIZE - info->xmit_head));
+		if (c <= 0) {
+			local_irq_restore(flags);
+			break;
+		}
 
-	    buf += c;
-	    count -= c;
-	    total += c;
-    }
+		memcpy(info->xmit_buf + info->xmit_head, buf, c);
+		info->xmit_head =
+		    (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
+		info->xmit_cnt += c;
+		local_irq_restore(flags);
 
-    if (info->xmit_cnt
-    && !tty->stopped
-    && !tty->hw_stopped ) {
-        start_xmit(info);
-    }
-    return total;
-} /* cy_write */
+		buf += c;
+		count -= c;
+		total += c;
+	}
 
+	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
+		start_xmit(info);
+	}
+	return total;
+}				/* cy_write */
 
-static int
-cy_write_room(struct tty_struct *tty)
+static int cy_write_room(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  int	ret;
-				
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	int ret;
+
 #ifdef SERIAL_DEBUG_IO
-    printk("cy_write_room %s\n", tty->name); /* */
+	printk("cy_write_room %s\n", tty->name);	/* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_write_room"))
-	return 0;
-    ret = PAGE_SIZE - info->xmit_cnt - 1;
-    if (ret < 0)
-	ret = 0;
-    return ret;
-} /* cy_write_room */
+	if (serial_paranoia_check(info, tty->name, "cy_write_room"))
+		return 0;
+	ret = PAGE_SIZE - info->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+	return ret;
+}				/* cy_write_room */
 
-
-static int
-cy_chars_in_buffer(struct tty_struct *tty)
+static int cy_chars_in_buffer(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-				
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+
 #ifdef SERIAL_DEBUG_IO
-    printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */
+	printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt);	/* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
-	return 0;
+	if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
+		return 0;
 
-    return info->xmit_cnt;
-} /* cy_chars_in_buffer */
+	return info->xmit_cnt;
+}				/* cy_chars_in_buffer */
 
-
-static void
-cy_flush_buffer(struct tty_struct *tty)
+static void cy_flush_buffer(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
-				
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	unsigned long flags;
+
 #ifdef SERIAL_DEBUG_IO
-    printk("cy_flush_buffer %s\n", tty->name); /* */
+	printk("cy_flush_buffer %s\n", tty->name);	/* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
-	return;
-    local_irq_save(flags);
+	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
+		return;
+	local_irq_save(flags);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-    local_irq_restore(flags);
-    tty_wakeup(tty);
-} /* cy_flush_buffer */
-
+	local_irq_restore(flags);
+	tty_wakeup(tty);
+}				/* cy_flush_buffer */
 
 /* This routine is called by the upper-layer tty layer to signal
    that incoming characters should be throttled or that the
    throttle should be released.
  */
-static void
-cy_throttle(struct tty_struct * tty)
+static void cy_throttle(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
-  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-  int channel;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
 
 #ifdef SERIAL_DEBUG_THROTTLE
-  char buf[64];
-	
-    printk("throttle %s: %d....\n", tty_name(tty, buf),
-	   tty->ldisc.chars_in_buffer(tty));
-    printk("cy_throttle %s\n", tty->name);
+	char buf[64];
+
+	printk("throttle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+	printk("cy_throttle %s\n", tty->name);
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_nthrottle")){
-	    return;
-    }
+	if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
+		return;
+	}
 
-    if (I_IXOFF(tty)) {
-	info->x_char = STOP_CHAR(tty);
-	    /* Should use the "Send Special Character" feature!!! */
-    }
+	if (I_IXOFF(tty)) {
+		info->x_char = STOP_CHAR(tty);
+		/* Should use the "Send Special Character" feature!!! */
+	}
 
-    channel = info->line;
+	channel = info->line;
 
-    local_irq_save(flags);
-	base_addr[CyCAR] = (u_char)channel;
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) channel;
 	base_addr[CyMSVR1] = 0;
-    local_irq_restore(flags);
+	local_irq_restore(flags);
+}				/* cy_throttle */
 
-    return;
-} /* cy_throttle */
-
-
-static void
-cy_unthrottle(struct tty_struct * tty)
+static void cy_unthrottle(struct tty_struct *tty)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned long flags;
-  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-  int channel;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
 
 #ifdef SERIAL_DEBUG_THROTTLE
-  char buf[64];
-	
-    printk("throttle %s: %d....\n", tty_name(tty, buf),
-	   tty->ldisc.chars_in_buffer(tty));
-    printk("cy_unthrottle %s\n", tty->name);
+	char buf[64];
+
+	printk("throttle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+	printk("cy_unthrottle %s\n", tty->name);
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_nthrottle")){
-	    return;
-    }
+	if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
+		return;
+	}
 
-    if (I_IXOFF(tty)) {
-	info->x_char = START_CHAR(tty);
-	/* Should use the "Send Special Character" feature!!! */
-    }
+	if (I_IXOFF(tty)) {
+		info->x_char = START_CHAR(tty);
+		/* Should use the "Send Special Character" feature!!! */
+	}
 
-    channel = info->line;
+	channel = info->line;
 
-    local_irq_save(flags);
-	base_addr[CyCAR] = (u_char)channel;
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) channel;
 	base_addr[CyMSVR1] = CyRTS;
-    local_irq_restore(flags);
-
-    return;
-} /* cy_unthrottle */
+	local_irq_restore(flags);
+}				/* cy_unthrottle */
 
 static int
-get_serial_info(struct cyclades_port * info,
-                           struct serial_struct __user * retinfo)
+get_serial_info(struct cyclades_port *info,
+		struct serial_struct __user * retinfo)
 {
-  struct serial_struct tmp;
+	struct serial_struct tmp;
 
 /* CP('g'); */
-    if (!retinfo)
-            return -EFAULT;
-    memset(&tmp, 0, sizeof(tmp));
-    tmp.type = info->type;
-    tmp.line = info->line;
-    tmp.port = info->line;
-    tmp.irq = 0;
-    tmp.flags = info->flags;
-    tmp.baud_base = 0;          /*!!!*/
-    tmp.close_delay = info->close_delay;
-    tmp.custom_divisor = 0;     /*!!!*/
-    tmp.hub6 = 0;               /*!!!*/
-    return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0;
-} /* get_serial_info */
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = info->type;
+	tmp.line = info->line;
+	tmp.port = info->line;
+	tmp.irq = 0;
+	tmp.flags = info->flags;
+	tmp.baud_base = 0;	/*!!! */
+	tmp.close_delay = info->close_delay;
+	tmp.custom_divisor = 0;	/*!!! */
+	tmp.hub6 = 0;		/*!!! */
+	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
+}				/* get_serial_info */
 
 static int
-set_serial_info(struct cyclades_port * info,
-                           struct serial_struct __user * new_info)
+set_serial_info(struct cyclades_port *info,
+		struct serial_struct __user * new_info)
 {
-  struct serial_struct new_serial;
-  struct cyclades_port old_info;
+	struct serial_struct new_serial;
+	struct cyclades_port old_info;
 
 /* CP('s'); */
-    if (!new_info)
-	    return -EFAULT;
-    if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
-	    return -EFAULT;
-    old_info = *info;
+	if (!new_info)
+		return -EFAULT;
+	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+		return -EFAULT;
+	old_info = *info;
 
-    if (!capable(CAP_SYS_ADMIN)) {
-	    if ((new_serial.close_delay != info->close_delay) ||
-		((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
-		 (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
-		    return -EPERM;
-	    info->flags = ((info->flags & ~ASYNC_USR_MASK) |
-			   (new_serial.flags & ASYNC_USR_MASK));
-	    goto check_and_exit;
-    }
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((new_serial.close_delay != info->close_delay) ||
+		    ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
+		     (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		goto check_and_exit;
+	}
 
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
 
-    /*
-     * OK, past this point, all the error checking has been done.
-     * At this point, we start making changes.....
-     */
-
-    info->flags = ((info->flags & ~ASYNC_FLAGS) |
-		    (new_serial.flags & ASYNC_FLAGS));
-    info->close_delay = new_serial.close_delay;
-
+	info->flags = ((info->flags & ~ASYNC_FLAGS) |
+		       (new_serial.flags & ASYNC_FLAGS));
+	info->close_delay = new_serial.close_delay;
 
 check_and_exit:
-    if (info->flags & ASYNC_INITIALIZED){
-	config_setup(info);
-	return 0;
-    }else{
-        return startup(info);
-    }
-} /* set_serial_info */
+	if (info->flags & ASYNC_INITIALIZED) {
+		config_setup(info);
+		return 0;
+	}
+	return startup(info);
+}				/* set_serial_info */
 
-static int
-cy_tiocmget(struct tty_struct *tty, struct file *file)
+static int cy_tiocmget(struct tty_struct *tty, struct file *file)
 {
-  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-  int channel;
-  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-  unsigned long flags;
-  unsigned char status;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	int channel;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	unsigned long flags;
+	unsigned char status;
 
-    channel = info->line;
+	channel = info->line;
 
-    local_irq_save(flags);
-        base_addr[CyCAR] = (u_char)channel;
-        status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
-    local_irq_restore(flags);
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) channel;
+	status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
+	local_irq_restore(flags);
 
-    return    ((status  & CyRTS) ? TIOCM_RTS : 0)
-            | ((status  & CyDTR) ? TIOCM_DTR : 0)
-            | ((status  & CyDCD) ? TIOCM_CAR : 0)
-            | ((status  & CyDSR) ? TIOCM_DSR : 0)
-            | ((status  & CyCTS) ? TIOCM_CTS : 0);
-} /* cy_tiocmget */
+	return ((status & CyRTS) ? TIOCM_RTS : 0)
+	    | ((status & CyDTR) ? TIOCM_DTR : 0)
+	    | ((status & CyDCD) ? TIOCM_CAR : 0)
+	    | ((status & CyDSR) ? TIOCM_DSR : 0)
+	    | ((status & CyCTS) ? TIOCM_CTS : 0);
+}				/* cy_tiocmget */
 
 static int
 cy_tiocmset(struct tty_struct *tty, struct file *file,
 	    unsigned int set, unsigned int clear)
 {
-  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-  int channel;
-  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-  unsigned long flags;
-	  
-    channel = info->line;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	int channel;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	unsigned long flags;
 
-	if (set & TIOCM_RTS){
-	    local_irq_save(flags);
-		base_addr[CyCAR] = (u_char)channel;
+	channel = info->line;
+
+	if (set & TIOCM_RTS) {
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
 		base_addr[CyMSVR1] = CyRTS;
-	    local_irq_restore(flags);
+		local_irq_restore(flags);
 	}
-	if (set & TIOCM_DTR){
-	    local_irq_save(flags);
-	    base_addr[CyCAR] = (u_char)channel;
+	if (set & TIOCM_DTR) {
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
 /* CP('S');CP('2'); */
-	    base_addr[CyMSVR2] = CyDTR;
+		base_addr[CyMSVR2] = CyDTR;
 #ifdef SERIAL_DEBUG_DTR
-            printk("cyc: %d: raising DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+		printk("cyc: %d: raising DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
 #endif
-	    local_irq_restore(flags);
+		local_irq_restore(flags);
 	}
 
-	if (clear & TIOCM_RTS){
-	    local_irq_save(flags);
-		base_addr[CyCAR] = (u_char)channel;
+	if (clear & TIOCM_RTS) {
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
 		base_addr[CyMSVR1] = 0;
-	    local_irq_restore(flags);
+		local_irq_restore(flags);
 	}
-	if (clear & TIOCM_DTR){
-	    local_irq_save(flags);
-	    base_addr[CyCAR] = (u_char)channel;
+	if (clear & TIOCM_DTR) {
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
 /* CP('C');CP('2'); */
-	    base_addr[CyMSVR2] = 0;
+		base_addr[CyMSVR2] = 0;
 #ifdef SERIAL_DEBUG_DTR
-            printk("cyc: %d: dropping DTR\n", __LINE__);
-            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
+		printk("cyc: %d: dropping DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
 #endif
-	    local_irq_restore(flags);
+		local_irq_restore(flags);
 	}
 
-    return 0;
-} /* set_modem_info */
+	return 0;
+}				/* set_modem_info */
 
-static void
-send_break( struct cyclades_port * info, int duration)
-{ /* Let the transmit ISR take care of this (since it
-     requires stuffing characters into the output stream).
-   */
-    info->x_break = duration;
-    if (!info->xmit_cnt ) {
-	start_xmit(info);
-    }
-} /* send_break */
+static void send_break(struct cyclades_port *info, int duration)
+{				/* Let the transmit ISR take care of this (since it
+				   requires stuffing characters into the output stream).
+				 */
+	info->x_break = duration;
+	if (!info->xmit_cnt) {
+		start_xmit(info);
+	}
+}				/* send_break */
 
 static int
-get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon)
+get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
 {
 
-   if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
-	   return -EFAULT;
-   info->mon.int_count  = 0;
-   info->mon.char_count = 0;
-   info->mon.char_max   = 0;
-   info->mon.char_last  = 0;
-   return 0;
+	if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
+		return -EFAULT;
+	info->mon.int_count = 0;
+	info->mon.char_count = 0;
+	info->mon.char_max = 0;
+	info->mon.char_last = 0;
+	return 0;
+}
+
+static int set_threshold(struct cyclades_port *info, unsigned long __user * arg)
+{
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	unsigned long value;
+	int channel;
+
+	if (get_user(value, arg))
+		return -EFAULT;
+
+	channel = info->line;
+	info->cor4 &= ~CyREC_FIFO;
+	info->cor4 |= value & CyREC_FIFO;
+	base_addr[CyCOR4] = info->cor4;
+	return 0;
 }
 
 static int
-set_threshold(struct cyclades_port * info, unsigned long __user *arg)
+get_threshold(struct cyclades_port *info, unsigned long __user * value)
 {
-   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-   unsigned long value;
-   int channel;
-   
-   if (get_user(value, arg))
-	   return -EFAULT;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+	unsigned long tmp;
 
-   channel = info->line;
-   info->cor4 &= ~CyREC_FIFO;
-   info->cor4 |= value & CyREC_FIFO;
-   base_addr[CyCOR4] = info->cor4;
-   return 0;
+	channel = info->line;
+
+	tmp = base_addr[CyCOR4] & CyREC_FIFO;
+	return put_user(tmp, value);
 }
 
 static int
-get_threshold(struct cyclades_port * info, unsigned long __user *value)
+set_default_threshold(struct cyclades_port *info, unsigned long __user * arg)
 {
-   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-   int channel;
-   unsigned long tmp;
-   
-   channel = info->line;
+	unsigned long value;
 
-   tmp = base_addr[CyCOR4] & CyREC_FIFO;
-   return put_user(tmp,value);
+	if (get_user(value, arg))
+		return -EFAULT;
+
+	info->default_threshold = value & 0x0f;
+	return 0;
 }
 
 static int
-set_default_threshold(struct cyclades_port * info, unsigned long __user *arg)
+get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
 {
-   unsigned long value;
+	return put_user(info->default_threshold, value);
+}
 
-   if (get_user(value, arg))
-	return -EFAULT;
+static int set_timeout(struct cyclades_port *info, unsigned long __user * arg)
+{
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+	unsigned long value;
 
-   info->default_threshold = value & 0x0f;
-   return 0;
+	if (get_user(value, arg))
+		return -EFAULT;
+
+	channel = info->line;
+
+	base_addr[CyRTPRL] = value & 0xff;
+	base_addr[CyRTPRH] = (value >> 8) & 0xff;
+	return 0;
+}
+
+static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
+{
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+	unsigned long tmp;
+
+	channel = info->line;
+
+	tmp = base_addr[CyRTPRL];
+	return put_user(tmp, value);
+}
+
+static int set_default_timeout(struct cyclades_port *info, unsigned long value)
+{
+	info->default_timeout = value & 0xff;
+	return 0;
 }
 
 static int
-get_default_threshold(struct cyclades_port * info, unsigned long __user *value)
+get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
 {
-   return put_user(info->default_threshold,value);
+	return put_user(info->default_timeout, value);
 }
 
 static int
-set_timeout(struct cyclades_port * info, unsigned long __user *arg)
+cy_ioctl(struct tty_struct *tty, struct file *file,
+	 unsigned int cmd, unsigned long arg)
 {
-   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-   int channel;
-   unsigned long value;
-
-   if (get_user(value, arg))
-	   return -EFAULT;
-   
-   channel = info->line;
-
-   base_addr[CyRTPRL] = value & 0xff;
-   base_addr[CyRTPRH] = (value >> 8) & 0xff;
-   return 0;
-}
-
-static int
-get_timeout(struct cyclades_port * info, unsigned long __user *value)
-{
-   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-   int channel;
-   unsigned long tmp;
-   
-   channel = info->line;
-
-   tmp = base_addr[CyRTPRL];
-   return put_user(tmp,value);
-}
-
-static int
-set_default_timeout(struct cyclades_port * info, unsigned long value)
-{
-   info->default_timeout = value & 0xff;
-   return 0;
-}
-
-static int
-get_default_timeout(struct cyclades_port * info, unsigned long __user *value)
-{
-   return put_user(info->default_timeout,value);
-}
-
-static int
-cy_ioctl(struct tty_struct *tty, struct file * file,
-            unsigned int cmd, unsigned long arg)
-{
-  unsigned long val;
-  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-  int ret_val = 0;
-  void __user *argp = (void __user *)arg;
+	unsigned long val;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	int ret_val = 0;
+	void __user *argp = (void __user *)arg;
 
 #ifdef SERIAL_DEBUG_OTHER
-    printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */
+	printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg);	/* */
 #endif
 
-    switch (cmd) {
-        case CYGETMON:
-            ret_val = get_mon_info(info, argp);
-	    break;
-        case CYGETTHRESH:
-	    ret_val = get_threshold(info, argp);
- 	    break;
-        case CYSETTHRESH:
-            ret_val = set_threshold(info, argp);
-	    break;
-        case CYGETDEFTHRESH:
-	    ret_val = get_default_threshold(info, argp);
- 	    break;
-        case CYSETDEFTHRESH:
-            ret_val = set_default_threshold(info, argp);
-	    break;
-        case CYGETTIMEOUT:
-	    ret_val = get_timeout(info, argp);
- 	    break;
-        case CYSETTIMEOUT:
-            ret_val = set_timeout(info, argp);
-	    break;
-        case CYGETDEFTIMEOUT:
-	    ret_val = get_default_timeout(info, argp);
- 	    break;
-        case CYSETDEFTIMEOUT:
-            ret_val = set_default_timeout(info, (unsigned long)arg);
-	    break;
-        case TCSBRK:    /* SVID version: non-zero arg --> no break */
-	    ret_val = tty_check_change(tty);
-	    if (ret_val)
-		    break;
-            tty_wait_until_sent(tty,0);
-            if (!arg)
-                send_break(info, HZ/4); /* 1/4 second */
-            break;
-        case TCSBRKP:   /* support for POSIX tcsendbreak() */
-	    ret_val = tty_check_change(tty);
-	    if (ret_val)
+	switch (cmd) {
+	case CYGETMON:
+		ret_val = get_mon_info(info, argp);
 		break;
-            tty_wait_until_sent(tty,0);
-            send_break(info, arg ? arg*(HZ/10) : HZ/4);
-            break;
+	case CYGETTHRESH:
+		ret_val = get_threshold(info, argp);
+		break;
+	case CYSETTHRESH:
+		ret_val = set_threshold(info, argp);
+		break;
+	case CYGETDEFTHRESH:
+		ret_val = get_default_threshold(info, argp);
+		break;
+	case CYSETDEFTHRESH:
+		ret_val = set_default_threshold(info, argp);
+		break;
+	case CYGETTIMEOUT:
+		ret_val = get_timeout(info, argp);
+		break;
+	case CYSETTIMEOUT:
+		ret_val = set_timeout(info, argp);
+		break;
+	case CYGETDEFTIMEOUT:
+		ret_val = get_default_timeout(info, argp);
+		break;
+	case CYSETDEFTIMEOUT:
+		ret_val = set_default_timeout(info, (unsigned long)arg);
+		break;
+	case TCSBRK:		/* SVID version: non-zero arg --> no break */
+		ret_val = tty_check_change(tty);
+		if (ret_val)
+			break;
+		tty_wait_until_sent(tty, 0);
+		if (!arg)
+			send_break(info, HZ / 4);	/* 1/4 second */
+		break;
+	case TCSBRKP:		/* support for POSIX tcsendbreak() */
+		ret_val = tty_check_change(tty);
+		if (ret_val)
+			break;
+		tty_wait_until_sent(tty, 0);
+		send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
+		break;
 
 /* The following commands are incompletely implemented!!! */
-        case TIOCGSOFTCAR:
-            ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);
-            break;
-        case TIOCSSOFTCAR:
-            ret_val = get_user(val, (unsigned long __user *) argp);
-	    if (ret_val)
-		    break;
-            tty->termios->c_cflag =
-                    ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));
-            break;
-        case TIOCGSERIAL:
-            ret_val = get_serial_info(info, argp);
-            break;
-        case TIOCSSERIAL:
-            ret_val = set_serial_info(info, argp);
-            break;
-        default:
-	    ret_val = -ENOIOCTLCMD;
-    }
+	case TIOCGSOFTCAR:
+		ret_val =
+		    put_user(C_CLOCAL(tty) ? 1 : 0,
+			     (unsigned long __user *)argp);
+		break;
+	case TIOCSSOFTCAR:
+		ret_val = get_user(val, (unsigned long __user *)argp);
+		if (ret_val)
+			break;
+		tty->termios->c_cflag =
+		    ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));
+		break;
+	case TIOCGSERIAL:
+		ret_val = get_serial_info(info, argp);
+		break;
+	case TIOCSSERIAL:
+		ret_val = set_serial_info(info, argp);
+		break;
+	default:
+		ret_val = -ENOIOCTLCMD;
+	}
 
 #ifdef SERIAL_DEBUG_OTHER
-    printk("cy_ioctl done\n");
+	printk("cy_ioctl done\n");
 #endif
 
-    return ret_val;
-} /* cy_ioctl */
+	return ret_val;
+}				/* cy_ioctl */
 
-
-
-
-static void
-cy_set_termios(struct tty_struct *tty, struct ktermios * old_termios)
+static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
 
 #ifdef SERIAL_DEBUG_OTHER
-    printk("cy_set_termios %s\n", tty->name);
+	printk("cy_set_termios %s\n", tty->name);
 #endif
 
-    if (tty->termios->c_cflag == old_termios->c_cflag)
-        return;
-    config_setup(info);
+	if (tty->termios->c_cflag == old_termios->c_cflag)
+		return;
+	config_setup(info);
 
-    if ((old_termios->c_cflag & CRTSCTS) &&
-        !(tty->termios->c_cflag & CRTSCTS)) {
-            tty->stopped = 0;
-            cy_start(tty);
-    }
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->stopped = 0;
+		cy_start(tty);
+	}
 #ifdef tytso_patch_94Nov25_1726
-    if (!(old_termios->c_cflag & CLOCAL) &&
-        (tty->termios->c_cflag & CLOCAL))
-            wake_up_interruptible(&info->open_wait);
+	if (!(old_termios->c_cflag & CLOCAL) &&
+	    (tty->termios->c_cflag & CLOCAL))
+		wake_up_interruptible(&info->open_wait);
 #endif
+}				/* cy_set_termios */
 
-    return;
-} /* cy_set_termios */
-
-
-static void
-cy_close(struct tty_struct * tty, struct file * filp)
+static void cy_close(struct tty_struct *tty, struct file *filp)
 {
-  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
 
 /* CP('C'); */
 #ifdef SERIAL_DEBUG_OTHER
-    printk("cy_close %s\n", tty->name);
+	printk("cy_close %s\n", tty->name);
 #endif
 
-    if (!info
-    || serial_paranoia_check(info, tty->name, "cy_close")){
-        return;
-    }
-#ifdef SERIAL_DEBUG_OPEN
-    printk("cy_close %s, count = %d\n", tty->name, info->count);
-#endif
-
-    if ((tty->count == 1) && (info->count != 1)) {
-	/*
-	 * Uh, oh.  tty->count is 1, which means that the tty
-	 * structure will be freed.  Info->count should always
-	 * be one in these conditions.  If it's greater than
-	 * one, we've got real problems, since it means the
-	 * serial port won't be shutdown.
-	 */
-	printk("cy_close: bad serial port count; tty->count is 1, "
-	   "info->count is %d\n", info->count);
-	info->count = 1;
-    }
-#ifdef SERIAL_DEBUG_COUNT
-    printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count - 1);
-#endif
-    if (--info->count < 0) {
-	printk("cy_close: bad serial port count for ttys%d: %d\n",
-	       info->line, info->count);
-#ifdef SERIAL_DEBUG_COUNT
-    printk("cyc: %d: setting count to 0\n", __LINE__);
-#endif
-	info->count = 0;
-    }
-    if (info->count)
-	return;
-    info->flags |= ASYNC_CLOSING;
-    if (info->flags & ASYNC_INITIALIZED)
-	tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
-    shutdown(info);
-    if (tty->driver->flush_buffer)
-	tty->driver->flush_buffer(tty);
-    tty_ldisc_flush(tty);
-    info->event = 0;
-    info->tty = NULL;
-    if (info->blocked_open) {
-	if (info->close_delay) {
-	    msleep_interruptible(jiffies_to_msecs(info->close_delay));
+	if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
+		return;
 	}
-	wake_up_interruptible(&info->open_wait);
-    }
-    info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-    wake_up_interruptible(&info->close_wait);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("cy_close %s, count = %d\n", tty->name, info->count);
+#endif
+
+	if ((tty->count == 1) && (info->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  Info->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		printk("cy_close: bad serial port count; tty->count is 1, "
+		       "info->count is %d\n", info->count);
+		info->count = 1;
+	}
+#ifdef SERIAL_DEBUG_COUNT
+	printk("cyc: %d: decrementing count to %d\n", __LINE__,
+	       info->count - 1);
+#endif
+	if (--info->count < 0) {
+		printk("cy_close: bad serial port count for ttys%d: %d\n",
+		       info->line, info->count);
+#ifdef SERIAL_DEBUG_COUNT
+		printk("cyc: %d: setting count to 0\n", __LINE__);
+#endif
+		info->count = 0;
+	}
+	if (info->count)
+		return;
+	info->flags |= ASYNC_CLOSING;
+	if (info->flags & ASYNC_INITIALIZED)
+		tty_wait_until_sent(tty, 3000);	/* 30 seconds timeout */
+	shutdown(info);
+	if (tty->driver->flush_buffer)
+		tty->driver->flush_buffer(tty);
+	tty_ldisc_flush(tty);
+	info->event = 0;
+	info->tty = NULL;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			msleep_interruptible(jiffies_to_msecs
+					     (info->close_delay));
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+	wake_up_interruptible(&info->close_wait);
 
 #ifdef SERIAL_DEBUG_OTHER
-    printk("cy_close done\n");
+	printk("cy_close done\n");
 #endif
-
-    return;
-} /* cy_close */
+}				/* cy_close */
 
 /*
  * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
  */
-void
-cy_hangup(struct tty_struct *tty)
+void cy_hangup(struct tty_struct *tty)
 {
-  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-	
+	struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+
 #ifdef SERIAL_DEBUG_OTHER
-    printk("cy_hangup %s\n", tty->name); /* */
+	printk("cy_hangup %s\n", tty->name);	/* */
 #endif
 
-    if (serial_paranoia_check(info, tty->name, "cy_hangup"))
-	return;
-    
-    shutdown(info);
+	if (serial_paranoia_check(info, tty->name, "cy_hangup"))
+		return;
+
+	shutdown(info);
 #if 0
-    info->event = 0;
-    info->count = 0;
+	info->event = 0;
+	info->count = 0;
 #ifdef SERIAL_DEBUG_COUNT
-    printk("cyc: %d: setting count to 0\n", __LINE__);
+	printk("cyc: %d: setting count to 0\n", __LINE__);
 #endif
-    info->tty = 0;
+	info->tty = 0;
 #endif
-    info->flags &= ~ASYNC_NORMAL_ACTIVE;
-    wake_up_interruptible(&info->open_wait);
-} /* cy_hangup */
-
-
+	info->flags &= ~ASYNC_NORMAL_ACTIVE;
+	wake_up_interruptible(&info->open_wait);
+}				/* cy_hangup */
 
 /*
  * ------------------------------------------------------------
@@ -1827,177 +1796,180 @@
  */
 
 static int
-block_til_ready(struct tty_struct *tty, struct file * filp,
-                           struct cyclades_port *info)
+block_til_ready(struct tty_struct *tty, struct file *filp,
+		struct cyclades_port *info)
 {
-  DECLARE_WAITQUEUE(wait, current);
-  unsigned long flags;
-  int channel;
-  int retval;
-  volatile u_char *base_addr = (u_char *)BASE_ADDR;
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	int channel;
+	int retval;
+	volatile u_char *base_addr = (u_char *) BASE_ADDR;
 
-    /*
-     * If the device is in the middle of being closed, then block
-     * until it's done, and then try again.
-     */
-    if (info->flags & ASYNC_CLOSING) {
-	interruptible_sleep_on(&info->close_wait);
-	if (info->flags & ASYNC_HUP_NOTIFY){
-	    return -EAGAIN;
-	}else{
-	    return -ERESTARTSYS;
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (info->flags & ASYNC_CLOSING) {
+		interruptible_sleep_on(&info->close_wait);
+		if (info->flags & ASYNC_HUP_NOTIFY) {
+			return -EAGAIN;
+		} else {
+			return -ERESTARTSYS;
+		}
 	}
-    }
 
-    /*
-     * If non-blocking mode is set, then make the check up front
-     * and then exit.
-     */
-    if (filp->f_flags & O_NONBLOCK) {
+	/*
+	 * If non-blocking mode is set, then make the check up front
+	 * and then exit.
+	 */
+	if (filp->f_flags & O_NONBLOCK) {
+		info->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, info->count is dropped by one, so that
+	 * cy_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+	add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready before block: %s, count = %d\n",
+	       tty->name, info->count);
+	/**/
+#endif
+	    info->count--;
+#ifdef SERIAL_DEBUG_COUNT
+	printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
+#endif
+	info->blocked_open++;
+
+	channel = info->line;
+
+	while (1) {
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
+		base_addr[CyMSVR1] = CyRTS;
+/* CP('S');CP('4'); */
+		base_addr[CyMSVR2] = CyDTR;
+#ifdef SERIAL_DEBUG_DTR
+		printk("cyc: %d: raising DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
+#endif
+		local_irq_restore(flags);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (tty_hung_up_p(filp)
+		    || !(info->flags & ASYNC_INITIALIZED)) {
+			if (info->flags & ASYNC_HUP_NOTIFY) {
+				retval = -EAGAIN;
+			} else {
+				retval = -ERESTARTSYS;
+			}
+			break;
+		}
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
+/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
+		if (!(info->flags & ASYNC_CLOSING)
+		    && (C_CLOCAL(tty)
+			|| (base_addr[CyMSVR1] & CyDCD))) {
+			local_irq_restore(flags);
+			break;
+		}
+		local_irq_restore(flags);
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+#ifdef SERIAL_DEBUG_OPEN
+		printk("block_til_ready blocking: %s, count = %d\n",
+		       tty->name, info->count);
+		/**/
+#endif
+		    schedule();
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&info->open_wait, &wait);
+	if (!tty_hung_up_p(filp)) {
+		info->count++;
+#ifdef SERIAL_DEBUG_COUNT
+		printk("cyc: %d: incrementing count to %d\n", __LINE__,
+		       info->count);
+#endif
+	}
+	info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready after blocking: %s, count = %d\n",
+	       tty->name, info->count);
+	/**/
+#endif
+	    if (retval)
+		return retval;
 	info->flags |= ASYNC_NORMAL_ACTIVE;
 	return 0;
-    }
-
-    /*
-     * Block waiting for the carrier detect and the line to become
-     * free (i.e., not in use by the callout).  While we are in
-     * this loop, info->count is dropped by one, so that
-     * cy_close() knows when to free things.  We restore it upon
-     * exit, either normal or abnormal.
-     */
-    retval = 0;
-    add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-    printk("block_til_ready before block: %s, count = %d\n",
-	   tty->name, info->count);/**/
-#endif
-    info->count--;
-#ifdef SERIAL_DEBUG_COUNT
-    printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
-#endif
-    info->blocked_open++;
-
-    channel = info->line;
-
-    while (1) {
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char)channel;
-	base_addr[CyMSVR1] = CyRTS;
-/* CP('S');CP('4'); */
-	base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-	printk("cyc: %d: raising DTR\n", __LINE__);
-	printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
-#endif
-	local_irq_restore(flags);
-	set_current_state(TASK_INTERRUPTIBLE);
-	if (tty_hung_up_p(filp)
-	|| !(info->flags & ASYNC_INITIALIZED) ){
-	    if (info->flags & ASYNC_HUP_NOTIFY) {
-		retval = -EAGAIN;
-	    }else{
-		retval = -ERESTARTSYS;
-	    }
-	    break;
-	}
-	local_irq_save(flags);
-	    base_addr[CyCAR] = (u_char)channel;
-/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
-	    if (!(info->flags & ASYNC_CLOSING)
-	    && (C_CLOCAL(tty)
-	        || (base_addr[CyMSVR1] & CyDCD))) {
-		    local_irq_restore(flags);
-		    break;
-	    }
-	local_irq_restore(flags);
-	if (signal_pending(current)) {
-	    retval = -ERESTARTSYS;
-	    break;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready blocking: %s, count = %d\n",
-	       tty->name, info->count);/**/
-#endif
-	schedule();
-    }
-    current->state = TASK_RUNNING;
-    remove_wait_queue(&info->open_wait, &wait);
-    if (!tty_hung_up_p(filp)){
-	info->count++;
-#ifdef SERIAL_DEBUG_COUNT
-    printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
-#endif
-    }
-    info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-    printk("block_til_ready after blocking: %s, count = %d\n",
-	   tty->name, info->count);/**/
-#endif
-    if (retval)
-	    return retval;
-    info->flags |= ASYNC_NORMAL_ACTIVE;
-    return 0;
-} /* block_til_ready */
+}				/* block_til_ready */
 
 /*
  * This routine is called whenever a serial port is opened.  It
  * performs the serial-specific initialization for the tty structure.
  */
-int
-cy_open(struct tty_struct *tty, struct file * filp)
+int cy_open(struct tty_struct *tty, struct file *filp)
 {
-  struct cyclades_port  *info;
-  int retval, line;
+	struct cyclades_port *info;
+	int retval, line;
 
 /* CP('O'); */
-    line = tty->index;
-    if ((line < 0) || (NR_PORTS <= line)){
-        return -ENODEV;
-    }
-    info = &cy_port[line];
-    if (info->line < 0){
-        return -ENODEV;
-    }
+	line = tty->index;
+	if ((line < 0) || (NR_PORTS <= line)) {
+		return -ENODEV;
+	}
+	info = &cy_port[line];
+	if (info->line < 0) {
+		return -ENODEV;
+	}
 #ifdef SERIAL_DEBUG_OTHER
-    printk("cy_open %s\n", tty->name); /* */
+	printk("cy_open %s\n", tty->name);	/* */
 #endif
-    if (serial_paranoia_check(info, tty->name, "cy_open")){
-        return -ENODEV;
-    }
+	if (serial_paranoia_check(info, tty->name, "cy_open")) {
+		return -ENODEV;
+	}
 #ifdef SERIAL_DEBUG_OPEN
-    printk("cy_open %s, count = %d\n", tty->name, info->count);/**/
+	printk("cy_open %s, count = %d\n", tty->name, info->count);
+	/**/
 #endif
-    info->count++;
+	    info->count++;
 #ifdef SERIAL_DEBUG_COUNT
-    printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
+	printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
 #endif
-    tty->driver_data = info;
-    info->tty = tty;
+	tty->driver_data = info;
+	info->tty = tty;
 
-    /*
-     * Start up serial port
-     */
-    retval = startup(info);
-    if (retval){
-	return retval;
-    }
+	/*
+	 * Start up serial port
+	 */
+	retval = startup(info);
+	if (retval) {
+		return retval;
+	}
 
-    retval = block_til_ready(tty, filp, info);
-    if (retval) {
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
 #ifdef SERIAL_DEBUG_OPEN
-	printk("cy_open returning after block_til_ready with %d\n",
-	       retval);
+		printk("cy_open returning after block_til_ready with %d\n",
+		       retval);
 #endif
-	return retval;
-    }
-
+		return retval;
+	}
 #ifdef SERIAL_DEBUG_OPEN
-    printk("cy_open done\n");/**/
+	printk("cy_open done\n");
+	/**/
 #endif
-    return 0;
-} /* cy_open */
-
-
+	    return 0;
+}				/* cy_open */
 
 /*
  * ---------------------------------------------------------------------
@@ -2012,11 +1984,10 @@
  * number, and identifies which options were configured into this
  * driver.
  */
-static void
-show_version(void)
+static void show_version(void)
 {
-    printk("MVME166/167 cd2401 driver\n");
-} /* show_version */
+	printk("MVME166/167 cd2401 driver\n");
+}				/* show_version */
 
 /* initialize chips on card -- return number of valid
    chips (which is number of ports/4) */
@@ -2030,10 +2001,9 @@
  * ... I wonder what I should do if this fails ...
  */
 
-void
-mvme167_serial_console_setup(int cflag)
+void mvme167_serial_console_setup(int cflag)
 {
-	volatile unsigned char* base_addr = (u_char *)BASE_ADDR;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
 	int ch;
 	u_char spd;
 	u_char rcor, rbpr, badspeed = 0;
@@ -2062,21 +2032,21 @@
 
 	/* OK, we have chosen a speed, now reset and reinitialise */
 
-        my_udelay(20000L);	/* Allow time for any active o/p to complete */
-        if(base_addr[CyCCR] != 0x00){
-            local_irq_restore(flags);
-            /* printk(" chip is never idle (CCR != 0)\n"); */
-            return;
-        }
+	my_udelay(20000L);	/* Allow time for any active o/p to complete */
+	if (base_addr[CyCCR] != 0x00) {
+		local_irq_restore(flags);
+		/* printk(" chip is never idle (CCR != 0)\n"); */
+		return;
+	}
 
-        base_addr[CyCCR] = CyCHIP_RESET;	/* Reset the chip */
-        my_udelay(1000L);
+	base_addr[CyCCR] = CyCHIP_RESET;	/* Reset the chip */
+	my_udelay(1000L);
 
-        if(base_addr[CyGFRCR] == 0x00){
-            local_irq_restore(flags);
-            /* printk(" chip is not responding (GFRCR stayed 0)\n"); */
-            return;
-        }
+	if (base_addr[CyGFRCR] == 0x00) {
+		local_irq_restore(flags);
+		/* printk(" chip is not responding (GFRCR stayed 0)\n"); */
+		return;
+	}
 
 	/*
 	 * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms
@@ -2085,9 +2055,9 @@
 
 	base_addr[CyTPR] = 10;
 
-	base_addr[CyPILR1] = 0x01;    /* Interrupt level for modem change */
-	base_addr[CyPILR2] = 0x02;    /* Interrupt level for tx ints */
-	base_addr[CyPILR3] = 0x03;    /* Interrupt level for rx ints */
+	base_addr[CyPILR1] = 0x01;	/* Interrupt level for modem change */
+	base_addr[CyPILR2] = 0x02;	/* Interrupt level for tx ints */
+	base_addr[CyPILR3] = 0x03;	/* Interrupt level for rx ints */
 
 	/*
 	 * Attempt to set up all channels to something reasonable, and
@@ -2095,11 +2065,11 @@
 	 * the ammount of fiddling we have to do in normal running.
 	 */
 
-	for (ch = 3; ch >= 0 ; ch--) {
-		base_addr[CyCAR] = (u_char)ch;
+	for (ch = 3; ch >= 0; ch--) {
+		base_addr[CyCAR] = (u_char) ch;
 		base_addr[CyIER] = 0;
 		base_addr[CyCMR] = CyASYNC;
-		base_addr[CyLICR] = (u_char)ch << 2;
+		base_addr[CyLICR] = (u_char) ch << 2;
 		base_addr[CyLIVR] = 0x5c;
 		base_addr[CyTCOR] = baud_co[spd];
 		base_addr[CyTBPR] = baud_bpr[spd];
@@ -2118,29 +2088,30 @@
 		base_addr[CyCOR7] = 0;
 		base_addr[CyRTPRL] = 2;
 		base_addr[CyRTPRH] = 0;
-	        base_addr[CyMSVR1] = 0;
-	        base_addr[CyMSVR2] = 0;
-		write_cy_cmd(base_addr,CyINIT_CHAN|CyDIS_RCVR|CyDIS_XMTR);
+		base_addr[CyMSVR1] = 0;
+		base_addr[CyMSVR2] = 0;
+		write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR);
 	}
 
 	/*
 	 * Now do specials for channel zero....
 	 */
 
-        base_addr[CyMSVR1] = CyRTS;
-        base_addr[CyMSVR2] = CyDTR;
+	base_addr[CyMSVR1] = CyRTS;
+	base_addr[CyMSVR2] = CyDTR;
 	base_addr[CyIER] = CyRxData;
-	write_cy_cmd(base_addr,CyENB_RCVR|CyENB_XMTR);
+	write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
 
 	local_irq_restore(flags);
 
 	my_udelay(20000L);	/* Let it all settle down */
 
-        printk("CD2401 initialised,  chip is rev 0x%02x\n", base_addr[CyGFRCR]);
+	printk("CD2401 initialised,  chip is rev 0x%02x\n", base_addr[CyGFRCR]);
 	if (badspeed)
-        	printk("  WARNING:  Failed to identify line speed, rcor=%02x,rbpr=%02x\n",
-					rcor >> 5, rbpr);
-} /* serial_console_init */
+		printk
+		    ("  WARNING:  Failed to identify line speed, rcor=%02x,rbpr=%02x\n",
+		     rcor >> 5, rbpr);
+}				/* serial_console_init */
 
 static const struct tty_operations cy_ops = {
 	.open = cy_open,
@@ -2161,6 +2132,7 @@
 	.tiocmget = cy_tiocmget,
 	.tiocmset = cy_tiocmset,
 };
+
 /* The serial driver boot-time initialization code!
     Hardware I/O ports are mapped to character special devices on a
     first found, first allocated manner.  That is, this code searches
@@ -2177,214 +2149,214 @@
     If there are more cards with more ports than have been statically
     allocated above, a warning is printed and the extra ports are ignored.
  */
-static int __init
-serial167_init(void)
+static int __init serial167_init(void)
 {
-  struct cyclades_port *info;
-  int ret = 0;
-  int good_ports = 0;
-  int port_num = 0;
-  int index;
-  int DefSpeed;
+	struct cyclades_port *info;
+	int ret = 0;
+	int good_ports = 0;
+	int port_num = 0;
+	int index;
+	int DefSpeed;
 #ifdef notyet
-  struct sigaction sa;
+	struct sigaction sa;
 #endif
 
-    if (!(mvme16x_config &MVME16x_CONFIG_GOT_CD2401))
-	return 0;
+	if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401))
+		return 0;
 
-    cy_serial_driver = alloc_tty_driver(NR_PORTS);
-    if (!cy_serial_driver)
-	return -ENOMEM;
+	cy_serial_driver = alloc_tty_driver(NR_PORTS);
+	if (!cy_serial_driver)
+		return -ENOMEM;
 
 #if 0
-scrn[1] = '\0';
+	scrn[1] = '\0';
 #endif
 
-    show_version();
+	show_version();
 
-    /* Has "console=0,9600n8" been used in bootinfo to change speed? */
-    if (serial_console_cflag)
-	DefSpeed = serial_console_cflag & 0017;
-    else {
-	DefSpeed = initial_console_speed;
-	serial_console_info = &cy_port[0];
-	serial_console_cflag = DefSpeed | CS8;
+	/* Has "console=0,9600n8" been used in bootinfo to change speed? */
+	if (serial_console_cflag)
+		DefSpeed = serial_console_cflag & 0017;
+	else {
+		DefSpeed = initial_console_speed;
+		serial_console_info = &cy_port[0];
+		serial_console_cflag = DefSpeed | CS8;
 #if 0
-	serial_console = 64; /*callout_driver.minor_start*/
+		serial_console = 64;	/*callout_driver.minor_start */
 #endif
-    }
-
-    /* Initialize the tty_driver structure */
-    
-    cy_serial_driver->owner = THIS_MODULE;
-    cy_serial_driver->name = "ttyS";
-    cy_serial_driver->major = TTY_MAJOR;
-    cy_serial_driver->minor_start = 64;
-    cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-    cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
-    cy_serial_driver->init_termios = tty_std_termios;
-    cy_serial_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-    cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
-    tty_set_operations(cy_serial_driver, &cy_ops);
-
-    ret = tty_register_driver(cy_serial_driver);
-    if (ret) {
-	    printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
-	    put_tty_driver(cy_serial_driver);
-	    return ret;
-    }
-
-    port_num = 0;
-    info = cy_port;
-    for (index = 0; index < 1; index++) {
-
-	good_ports = 4;
-
-	if(port_num < NR_PORTS){
-	    while( good_ports-- && port_num < NR_PORTS){
-		/*** initialize port ***/
-		info->magic = CYCLADES_MAGIC;
-		info->type = PORT_CIRRUS;
-		info->card = index;
-		info->line = port_num;
-		info->flags = STD_COM_FLAGS;
-		info->tty = NULL;
-		info->xmit_fifo_size = 12;
-		info->cor1 = CyPARITY_NONE|Cy_8_BITS;
-		info->cor2 = CyETC;
-		info->cor3 = Cy_1_STOP;
-		info->cor4 = 0x08; /* _very_ small receive threshold */
-		info->cor5 = 0;
-		info->cor6 = 0;
-		info->cor7 = 0;
-		info->tbpr = baud_bpr[DefSpeed]; /* Tx BPR */
-		info->tco = baud_co[DefSpeed]; /* Tx CO */
-		info->rbpr = baud_bpr[DefSpeed]; /* Rx BPR */
-		info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */
-		info->close_delay = 0;
-		info->x_char = 0;
-		info->event = 0;
-		info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
-    printk("cyc: %d: setting count to 0\n", __LINE__);
-#endif
-		info->blocked_open = 0;
-		info->default_threshold = 0;
-		info->default_timeout = 0;
-		INIT_WORK(&info->tqueue, do_softint);
-		init_waitqueue_head(&info->open_wait);
-		init_waitqueue_head(&info->close_wait);
-		/* info->session */
-		/* info->pgrp */
-/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
-		info->read_status_mask = CyTIMEOUT| CySPECHAR| CyBREAK
-                                       | CyPARITY| CyFRAME| CyOVERRUN;
-		/* info->timeout */
-
-		printk("ttyS%d ", info->line);
-		port_num++;info++;
-		if(!(port_num & 7)){
-		    printk("\n               ");
-		}
-	    }
 	}
-	printk("\n");
-    }
-    while( port_num < NR_PORTS){
-	info->line = -1;
-	port_num++;info++;
-    }
-#ifdef CONFIG_REMOTE_DEBUG
-    debug_setup();
+
+	/* Initialize the tty_driver structure */
+
+	cy_serial_driver->owner = THIS_MODULE;
+	cy_serial_driver->name = "ttyS";
+	cy_serial_driver->major = TTY_MAJOR;
+	cy_serial_driver->minor_start = 64;
+	cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	cy_serial_driver->init_termios = tty_std_termios;
+	cy_serial_driver->init_termios.c_cflag =
+	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(cy_serial_driver, &cy_ops);
+
+	ret = tty_register_driver(cy_serial_driver);
+	if (ret) {
+		printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
+		put_tty_driver(cy_serial_driver);
+		return ret;
+	}
+
+	port_num = 0;
+	info = cy_port;
+	for (index = 0; index < 1; index++) {
+
+		good_ports = 4;
+
+		if (port_num < NR_PORTS) {
+			while (good_ports-- && port_num < NR_PORTS) {
+		/*** initialize port ***/
+				info->magic = CYCLADES_MAGIC;
+				info->type = PORT_CIRRUS;
+				info->card = index;
+				info->line = port_num;
+				info->flags = STD_COM_FLAGS;
+				info->tty = NULL;
+				info->xmit_fifo_size = 12;
+				info->cor1 = CyPARITY_NONE | Cy_8_BITS;
+				info->cor2 = CyETC;
+				info->cor3 = Cy_1_STOP;
+				info->cor4 = 0x08;	/* _very_ small receive threshold */
+				info->cor5 = 0;
+				info->cor6 = 0;
+				info->cor7 = 0;
+				info->tbpr = baud_bpr[DefSpeed];	/* Tx BPR */
+				info->tco = baud_co[DefSpeed];	/* Tx CO */
+				info->rbpr = baud_bpr[DefSpeed];	/* Rx BPR */
+				info->rco = baud_co[DefSpeed] >> 5;	/* Rx CO */
+				info->close_delay = 0;
+				info->x_char = 0;
+				info->event = 0;
+				info->count = 0;
+#ifdef SERIAL_DEBUG_COUNT
+				printk("cyc: %d: setting count to 0\n",
+				       __LINE__);
 #endif
-    ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
-				"cd2401_errors", cd2401_rxerr_interrupt);
-    if (ret) {
-	    printk(KERN_ERR "Could't get cd2401_errors IRQ");
-	    goto cleanup_serial_driver;
-    }
+				info->blocked_open = 0;
+				info->default_threshold = 0;
+				info->default_timeout = 0;
+				INIT_WORK(&info->tqueue, do_softint);
+				init_waitqueue_head(&info->open_wait);
+				init_waitqueue_head(&info->close_wait);
+				/* info->session */
+				/* info->pgrp */
+/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
+				info->read_status_mask =
+				    CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY |
+				    CyFRAME | CyOVERRUN;
+				/* info->timeout */
 
-    ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
-				"cd2401_modem", cd2401_modem_interrupt);
-    if (ret) {
-	    printk(KERN_ERR "Could't get cd2401_modem IRQ");
-	    goto cleanup_irq_cd2401_errors;
-    }
+				printk("ttyS%d ", info->line);
+				port_num++;
+				info++;
+				if (!(port_num & 7)) {
+					printk("\n               ");
+				}
+			}
+		}
+		printk("\n");
+	}
+	while (port_num < NR_PORTS) {
+		info->line = -1;
+		port_num++;
+		info++;
+	}
+#ifdef CONFIG_REMOTE_DEBUG
+	debug_setup();
+#endif
+	ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
+			  "cd2401_errors", cd2401_rxerr_interrupt);
+	if (ret) {
+		printk(KERN_ERR "Could't get cd2401_errors IRQ");
+		goto cleanup_serial_driver;
+	}
 
-    ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
-				"cd2401_txints", cd2401_tx_interrupt);
-    if (ret) {
-	    printk(KERN_ERR "Could't get cd2401_txints IRQ");
-	    goto cleanup_irq_cd2401_modem;
-    }
+	ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
+			  "cd2401_modem", cd2401_modem_interrupt);
+	if (ret) {
+		printk(KERN_ERR "Could't get cd2401_modem IRQ");
+		goto cleanup_irq_cd2401_errors;
+	}
 
-    ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
-				"cd2401_rxints", cd2401_rx_interrupt);
-    if (ret) {
-	    printk(KERN_ERR "Could't get cd2401_rxints IRQ");
-	    goto cleanup_irq_cd2401_txints;
-    }
+	ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
+			  "cd2401_txints", cd2401_tx_interrupt);
+	if (ret) {
+		printk(KERN_ERR "Could't get cd2401_txints IRQ");
+		goto cleanup_irq_cd2401_modem;
+	}
 
-    /* Now we have registered the interrupt handlers, allow the interrupts */
+	ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
+			  "cd2401_rxints", cd2401_rx_interrupt);
+	if (ret) {
+		printk(KERN_ERR "Could't get cd2401_rxints IRQ");
+		goto cleanup_irq_cd2401_txints;
+	}
 
-    pcc2chip[PccSCCMICR] = 0x15;		/* Serial ints are level 5 */
-    pcc2chip[PccSCCTICR] = 0x15;
-    pcc2chip[PccSCCRICR] = 0x15;
+	/* Now we have registered the interrupt handlers, allow the interrupts */
 
-    pcc2chip[PccIMLR] = 3;			/* Allow PCC2 ints above 3!? */
+	pcc2chip[PccSCCMICR] = 0x15;	/* Serial ints are level 5 */
+	pcc2chip[PccSCCTICR] = 0x15;
+	pcc2chip[PccSCCRICR] = 0x15;
 
-    return 0;
+	pcc2chip[PccIMLR] = 3;	/* Allow PCC2 ints above 3!? */
+
+	return 0;
 cleanup_irq_cd2401_txints:
-    free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
+	free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
 cleanup_irq_cd2401_modem:
-    free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
+	free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
 cleanup_irq_cd2401_errors:
-    free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
+	free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
 cleanup_serial_driver:
-    if (tty_unregister_driver(cy_serial_driver))
-	    printk(KERN_ERR "Couldn't unregister MVME166/7 serial driver\n");
-    put_tty_driver(cy_serial_driver);
-    return ret;
-} /* serial167_init */
+	if (tty_unregister_driver(cy_serial_driver))
+		printk(KERN_ERR
+		       "Couldn't unregister MVME166/7 serial driver\n");
+	put_tty_driver(cy_serial_driver);
+	return ret;
+}				/* serial167_init */
 
 module_init(serial167_init);
 
-
 #ifdef CYCLOM_SHOW_STATUS
-static void
-show_status(int line_num)
+static void show_status(int line_num)
 {
-  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-  int channel;
-  struct cyclades_port * info;
-  unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+	struct cyclades_port *info;
+	unsigned long flags;
 
-    info = &cy_port[line_num];
-    channel = info->line;
-    printk("  channel %d\n", channel);/**/
+	info = &cy_port[line_num];
+	channel = info->line;
+	printk("  channel %d\n", channel);
+	/**/ printk(" cy_port\n");
+	printk("  card line flags = %d %d %x\n",
+	       info->card, info->line, info->flags);
+	printk
+	    ("  *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
+	     (long)info->tty, info->read_status_mask, info->timeout,
+	     info->xmit_fifo_size);
+	printk("  cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n",
+	       info->cor1, info->cor2, info->cor3, info->cor4, info->cor5,
+	       info->cor6, info->cor7);
+	printk("  tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco,
+	       info->rbpr, info->rco);
+	printk("  close_delay event count = %d %d %d\n", info->close_delay,
+	       info->event, info->count);
+	printk("  x_char blocked_open = %x %x\n", info->x_char,
+	       info->blocked_open);
+	printk("  open_wait = %lx %lx %lx\n", (long)info->open_wait);
 
-    printk(" cy_port\n");
-    printk("  card line flags = %d %d %x\n",
-                 info->card, info->line, info->flags);
-    printk("  *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
-                 (long)info->tty, info->read_status_mask,
-                 info->timeout, info->xmit_fifo_size);
-    printk("  cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n",
-             info->cor1, info->cor2, info->cor3, info->cor4, info->cor5,
-			info->cor6, info->cor7);
-    printk("  tbpr,tco,rbpr,rco = %d %d %d %d\n",
-             info->tbpr, info->tco, info->rbpr, info->rco);
-    printk("  close_delay event count = %d %d %d\n",
-             info->close_delay, info->event, info->count);
-    printk("  x_char blocked_open = %x %x\n",
-             info->x_char, info->blocked_open);
-    printk("  open_wait = %lx %lx %lx\n",
-             (long)info->open_wait);
-
-
-    local_irq_save(flags);
+	local_irq_save(flags);
 
 /* Global Registers */
 
@@ -2398,7 +2370,7 @@
 	printk(" CyMIR %x\n", base_addr[CyMIR]);
 	printk(" CyTPR %x\n", base_addr[CyTPR]);
 
-	base_addr[CyCAR] = (u_char)channel;
+	base_addr[CyCAR] = (u_char) channel;
 
 /* Virtual Registers */
 
@@ -2442,11 +2414,10 @@
 	printk(" CyTBPR %x\n", base_addr[CyTBPR]);
 	printk(" CyTCOR %x\n", base_addr[CyTCOR]);
 
-    local_irq_restore(flags);
-} /* show_status */
+	local_irq_restore(flags);
+}				/* show_status */
 #endif
 
-
 #if 0
 /* Dummy routine in mvme16x/config.c for now */
 
@@ -2459,61 +2430,67 @@
 	int cflag = 0;
 
 	/* Sanity check. */
-	if (ints[0] > 3 || ints[1] > 3) return;
+	if (ints[0] > 3 || ints[1] > 3)
+		return;
 
 	/* Get baud, bits and parity */
 	baud = 2400;
 	bits = 8;
 	parity = 'n';
-	if (ints[2]) baud = ints[2];
+	if (ints[2])
+		baud = ints[2];
 	if ((s = strchr(str, ','))) {
 		do {
 			s++;
-		} while(*s >= '0' && *s <= '9');
-		if (*s) parity = *s++;
-		if (*s) bits   = *s - '0';
+		} while (*s >= '0' && *s <= '9');
+		if (*s)
+			parity = *s++;
+		if (*s)
+			bits = *s - '0';
 	}
 
 	/* Now construct a cflag setting. */
-	switch(baud) {
-		case 1200:
-			cflag |= B1200;
-			break;
-		case 9600:
-			cflag |= B9600;
-			break;
-		case 19200:
-			cflag |= B19200;
-			break;
-		case 38400:
-			cflag |= B38400;
-			break;
-		case 2400:
-		default:
-			cflag |= B2400;
-			break;
+	switch (baud) {
+	case 1200:
+		cflag |= B1200;
+		break;
+	case 9600:
+		cflag |= B9600;
+		break;
+	case 19200:
+		cflag |= B19200;
+		break;
+	case 38400:
+		cflag |= B38400;
+		break;
+	case 2400:
+	default:
+		cflag |= B2400;
+		break;
 	}
-	switch(bits) {
-		case 7:
-			cflag |= CS7;
-			break;
-		default:
-		case 8:
-			cflag |= CS8;
-			break;
+	switch (bits) {
+	case 7:
+		cflag |= CS7;
+		break;
+	default:
+	case 8:
+		cflag |= CS8;
+		break;
 	}
-	switch(parity) {
-		case 'o': case 'O':
-			cflag |= PARODD;
-			break;
-		case 'e': case 'E':
-			cflag |= PARENB;
-			break;
+	switch (parity) {
+	case 'o':
+	case 'O':
+		cflag |= PARODD;
+		break;
+	case 'e':
+	case 'E':
+		cflag |= PARENB;
+		break;
 	}
 
 	serial_console_info = &cy_port[ints[1]];
 	serial_console_cflag = cflag;
-	serial_console = ints[1] + 64; /*callout_driver.minor_start*/
+	serial_console = ints[1] + 64;	/*callout_driver.minor_start */
 }
 #endif
 
@@ -2532,9 +2509,10 @@
  * The console must be locked when we get here.
  */
 
-void serial167_console_write(struct console *co, const char *str, unsigned count)
+void serial167_console_write(struct console *co, const char *str,
+			     unsigned count)
 {
-	volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
 	unsigned long flags;
 	volatile u_char sink;
 	u_char ier;
@@ -2547,7 +2525,7 @@
 	/* Ensure transmitter is enabled! */
 
 	port = 0;
-	base_addr[CyCAR] = (u_char)port;
+	base_addr[CyCAR] = (u_char) port;
 	while (base_addr[CyCCR])
 		;
 	base_addr[CyCCR] = CyENB_XMTR;
@@ -2556,8 +2534,7 @@
 	base_addr[CyIER] = CyTxMpty;
 
 	while (1) {
-		if (pcc2chip[PccSCCTICR] & 0x20)
-		{
+		if (pcc2chip[PccSCCTICR] & 0x20) {
 			/* We have a Tx int. Acknowledge it */
 			sink = pcc2chip[PccTPIACKR];
 			if ((base_addr[CyLICR] >> 2) == port) {
@@ -2571,18 +2548,15 @@
 					str++;
 					i++;
 					do_lf = 0;
-				}
-				else if (*str == '\n') {
+				} else if (*str == '\n') {
 					base_addr[CyTDR] = '\r';
 					do_lf = 1;
-				}
-				else {
+				} else {
 					base_addr[CyTDR] = *str++;
 					i++;
 				}
 				base_addr[CyTEOIR] = 0;
-			}
-			else
+			} else
 				base_addr[CyTEOIR] = CyNOTRANS;
 		}
 	}
@@ -2592,45 +2566,44 @@
 	local_irq_restore(flags);
 }
 
-static struct tty_driver *serial167_console_device(struct console *c, int *index)
+static struct tty_driver *serial167_console_device(struct console *c,
+						   int *index)
 {
 	*index = c->index;
 	return cy_serial_driver;
 }
 
-
 static int __init serial167_console_setup(struct console *co, char *options)
 {
 	return 0;
 }
 
-
 static struct console sercons = {
-	.name		= "ttyS",
-	.write		= serial167_console_write,
-	.device		= serial167_console_device,
-	.setup		= serial167_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
+	.name = "ttyS",
+	.write = serial167_console_write,
+	.device = serial167_console_device,
+	.setup = serial167_console_setup,
+	.flags = CON_PRINTBUFFER,
+	.index = -1,
 };
 
-
 static int __init serial167_console_init(void)
 {
 	if (vme_brdtype == VME_TYPE_MVME166 ||
-			vme_brdtype == VME_TYPE_MVME167 ||
-			vme_brdtype == VME_TYPE_MVME177) {
+	    vme_brdtype == VME_TYPE_MVME167 ||
+	    vme_brdtype == VME_TYPE_MVME177) {
 		mvme167_serial_console_setup(0);
 		register_console(&sercons);
 	}
 	return 0;
 }
+
 console_initcall(serial167_console_init);
 
 #ifdef CONFIG_REMOTE_DEBUG
-void putDebugChar (int c)
+void putDebugChar(int c)
 {
-	volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
 	unsigned long flags;
 	volatile u_char sink;
 	u_char ier;
@@ -2641,7 +2614,7 @@
 	/* Ensure transmitter is enabled! */
 
 	port = DEBUG_PORT;
-	base_addr[CyCAR] = (u_char)port;
+	base_addr[CyCAR] = (u_char) port;
 	while (base_addr[CyCCR])
 		;
 	base_addr[CyCCR] = CyENB_XMTR;
@@ -2650,16 +2623,14 @@
 	base_addr[CyIER] = CyTxMpty;
 
 	while (1) {
-		if (pcc2chip[PccSCCTICR] & 0x20)
-		{
+		if (pcc2chip[PccSCCTICR] & 0x20) {
 			/* We have a Tx int. Acknowledge it */
 			sink = pcc2chip[PccTPIACKR];
 			if ((base_addr[CyLICR] >> 2) == port) {
 				base_addr[CyTDR] = c;
 				base_addr[CyTEOIR] = 0;
 				break;
-			}
-			else
+			} else
 				base_addr[CyTEOIR] = CyNOTRANS;
 		}
 	}
@@ -2671,7 +2642,7 @@
 
 int getDebugChar()
 {
-	volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
 	unsigned long flags;
 	volatile u_char sink;
 	u_char ier;
@@ -2693,7 +2664,7 @@
 	/* Ensure receiver is enabled! */
 
 	port = DEBUG_PORT;
-	base_addr[CyCAR] = (u_char)port;
+	base_addr[CyCAR] = (u_char) port;
 #if 0
 	while (base_addr[CyCCR])
 		;
@@ -2703,31 +2674,30 @@
 	base_addr[CyIER] = CyRxData;
 
 	while (1) {
-		if (pcc2chip[PccSCCRICR] & 0x20)
-		{
+		if (pcc2chip[PccSCCRICR] & 0x20) {
 			/* We have a Rx int. Acknowledge it */
 			sink = pcc2chip[PccRPIACKR];
 			if ((base_addr[CyLICR] >> 2) == port) {
 				int cnt = base_addr[CyRFOC];
-				while (cnt-- > 0)
-				{
+				while (cnt-- > 0) {
 					c = base_addr[CyRDR];
 					if (c == 0)
-						printk ("!! debug char is null (cnt=%d) !!", cnt);
+						printk
+						    ("!! debug char is null (cnt=%d) !!",
+						     cnt);
 					else
-						queueDebugChar (c);
+						queueDebugChar(c);
 				}
 				base_addr[CyREOIR] = 0;
 				i = debugiq.out;
 				if (i == debugiq.in)
-					panic ("Debug input queue empty!");
+					panic("Debug input queue empty!");
 				c = debugiq.buf[i];
 				if (++i == DEBUG_LEN)
 					i = 0;
 				debugiq.out = i;
 				break;
-			}
-			else
+			} else
 				base_addr[CyREOIR] = CyNOTRANS;
 		}
 	}
@@ -2739,7 +2709,7 @@
 	return (c);
 }
 
-void queueDebugChar (int c)
+void queueDebugChar(int c)
 {
 	int i;
 
@@ -2751,73 +2721,71 @@
 		debugiq.in = i;
 }
 
-static void
-debug_setup()
+static void debug_setup()
 {
-  unsigned long flags;
-  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-  int   i, cflag;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int i, cflag;
 
-    cflag = B19200;
+	cflag = B19200;
 
-    local_irq_save(flags);
+	local_irq_save(flags);
 
-    for (i = 0; i < 4; i++)
-    {
-	base_addr[CyCAR] = i;
-	base_addr[CyLICR] = i << 2;
-    }
+	for (i = 0; i < 4; i++) {
+		base_addr[CyCAR] = i;
+		base_addr[CyLICR] = i << 2;
+	}
 
-    debugiq.in = debugiq.out = 0;
+	debugiq.in = debugiq.out = 0;
 
-    base_addr[CyCAR] = DEBUG_PORT;
+	base_addr[CyCAR] = DEBUG_PORT;
 
-    /* baud rate */
-    i = cflag & CBAUD;
+	/* baud rate */
+	i = cflag & CBAUD;
 
-    base_addr[CyIER] = 0;
+	base_addr[CyIER] = 0;
 
-    base_addr[CyCMR] = CyASYNC;
-    base_addr[CyLICR] = DEBUG_PORT << 2;
-    base_addr[CyLIVR] = 0x5c;
+	base_addr[CyCMR] = CyASYNC;
+	base_addr[CyLICR] = DEBUG_PORT << 2;
+	base_addr[CyLIVR] = 0x5c;
 
-    /* tx and rx baud rate */
+	/* tx and rx baud rate */
 
-    base_addr[CyTCOR] = baud_co[i];
-    base_addr[CyTBPR] = baud_bpr[i];
-    base_addr[CyRCOR] = baud_co[i] >> 5;
-    base_addr[CyRBPR] = baud_bpr[i];
+	base_addr[CyTCOR] = baud_co[i];
+	base_addr[CyTBPR] = baud_bpr[i];
+	base_addr[CyRCOR] = baud_co[i] >> 5;
+	base_addr[CyRBPR] = baud_bpr[i];
 
-    /* set line characteristics  according configuration */
+	/* set line characteristics  according configuration */
 
-    base_addr[CySCHR1] = 0;
-    base_addr[CySCHR2] = 0;
-    base_addr[CySCRL] = 0;
-    base_addr[CySCRH] = 0;
-    base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
-    base_addr[CyCOR2] = 0;
-    base_addr[CyCOR3] = Cy_1_STOP;
-    base_addr[CyCOR4] = baud_cor4[i];
-    base_addr[CyCOR5] = 0;
-    base_addr[CyCOR6] = 0;
-    base_addr[CyCOR7] = 0;
+	base_addr[CySCHR1] = 0;
+	base_addr[CySCHR2] = 0;
+	base_addr[CySCRL] = 0;
+	base_addr[CySCRH] = 0;
+	base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
+	base_addr[CyCOR2] = 0;
+	base_addr[CyCOR3] = Cy_1_STOP;
+	base_addr[CyCOR4] = baud_cor4[i];
+	base_addr[CyCOR5] = 0;
+	base_addr[CyCOR6] = 0;
+	base_addr[CyCOR7] = 0;
 
-    write_cy_cmd(base_addr,CyINIT_CHAN);
-    write_cy_cmd(base_addr,CyENB_RCVR);
+	write_cy_cmd(base_addr, CyINIT_CHAN);
+	write_cy_cmd(base_addr, CyENB_RCVR);
 
-    base_addr[CyCAR] = DEBUG_PORT; /* !!! Is this needed? */
+	base_addr[CyCAR] = DEBUG_PORT;	/* !!! Is this needed? */
 
-    base_addr[CyRTPRL] = 2;
-    base_addr[CyRTPRH] = 0;
+	base_addr[CyRTPRL] = 2;
+	base_addr[CyRTPRH] = 0;
 
-    base_addr[CyMSVR1] = CyRTS;
-    base_addr[CyMSVR2] = CyDTR;
+	base_addr[CyMSVR1] = CyRTS;
+	base_addr[CyMSVR2] = CyDTR;
 
-    base_addr[CyIER] = CyRxData;
+	base_addr[CyIER] = CyRxData;
 
-    local_irq_restore(flags);
+	local_irq_restore(flags);
 
-} /* debug_setup */
+}				/* debug_setup */
 
 #endif
 
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 17d54e1..7823757 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -36,7 +36,6 @@
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 20946f5..baf7234 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -459,10 +459,9 @@
 	if (irq) {
 		printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
 		sx_interrupt (((struct specialix_board *)data)->irq,
-		              (void*)data, NULL);
+				(void*)data);
 	}
-	missed_irq_timer.expires = jiffies + sx_poll;
-	add_timer (&missed_irq_timer);
+	mod_timer(&missed_irq_timer, jiffies + sx_poll);
 }
 #endif
 
@@ -597,11 +596,8 @@
 	dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
 
 #ifdef SPECIALIX_TIMER
-	init_timer (&missed_irq_timer);
-	missed_irq_timer.function = missed_irq;
-	missed_irq_timer.data = (unsigned long) bp;
-	missed_irq_timer.expires = jiffies + sx_poll;
-	add_timer (&missed_irq_timer);
+	setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp);
+	mod_timer(&missed_irq_timer, jiffies + sx_poll);
 #endif
 
 	printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
@@ -2350,10 +2346,8 @@
 		return;
 	}
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event))
  		tty_wakeup(tty);
-		//wake_up_interruptible(&tty->write_wait);
-	}
 
 	func_exit();
 }
@@ -2561,7 +2555,7 @@
 		if (sx_board[i].flags & SX_BOARD_PRESENT)
 			sx_release_io_range(&sx_board[i]);
 #ifdef SPECIALIX_TIMER
-	del_timer (&missed_irq_timer);
+	del_timer_sync(&missed_irq_timer);
 #endif
 
 	func_exit();
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 3fa625d..ce4db6f 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -1148,10 +1148,8 @@
 		printk( "%s(%d):mgsl_bh_transmit() entry on %s\n",
 			__FILE__,__LINE__,info->device_name);
 
-	if (tty) {
+	if (tty)
 		tty_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
 
 	/* if transmitter idle and loopmode_send_done_requested
 	 * then start echoing RxD to TxD
@@ -1800,9 +1798,7 @@
 	
 	memset(&info->icount, 0, sizeof(info->icount));
 
-	init_timer(&info->tx_timer);
-	info->tx_timer.data = (unsigned long)info;
-	info->tx_timer.function = mgsl_tx_timeout;
+	setup_timer(&info->tx_timer, mgsl_tx_timeout, (unsigned long)info);
 	
 	/* Allocate and claim adapter resources */
 	retval = mgsl_claim_resources(info);
@@ -1853,7 +1849,7 @@
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 
-	del_timer(&info->tx_timer);	
+	del_timer_sync(&info->tx_timer);
 
 	if (info->xmit_buf) {
 		free_page((unsigned long) info->xmit_buf);
@@ -2340,7 +2336,6 @@
 	del_timer(&info->tx_timer);	
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 	
-	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
 }
 
@@ -5713,8 +5708,8 @@
 			
 			usc_TCmd( info, TCmd_SendFrame );
 			
-			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
-			add_timer(&info->tx_timer);	
+			mod_timer(&info->tx_timer, jiffies +
+					msecs_to_jiffies(5000));
 		}
 		info->tx_active = 1;
 	}
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 792c79c..0a367cd 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1045,7 +1045,6 @@
 		info->tx_count = 0;
 	spin_unlock_irqrestore(&info->lock,flags);
 
-	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
 }
 
@@ -1826,8 +1825,7 @@
 		if (i < count) {
 			/* receive buffer not completed */
 			info->rbuf_index += i;
-			info->rx_timer.expires = jiffies + 1;
-			add_timer(&info->rx_timer);
+			mod_timer(&info->rx_timer, jiffies + 1);
 			break;
 		}
 
@@ -1933,10 +1931,8 @@
 	struct tty_struct *tty = info->tty;
 
 	DBGBH(("%s bh_transmit\n", info->device_name));
-	if (tty) {
+	if (tty)
 		tty_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
 }
 
 static void dsr_change(struct slgt_info *info)
@@ -3343,13 +3339,8 @@
 		info->adapter_num = adapter_num;
 		info->port_num = port_num;
 
-		init_timer(&info->tx_timer);
-		info->tx_timer.data = (unsigned long)info;
-		info->tx_timer.function = tx_timeout;
-
-		init_timer(&info->rx_timer);
-		info->rx_timer.data = (unsigned long)info;
-		info->rx_timer.function = rx_timeout;
+		setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
+		setup_timer(&info->rx_timer, rx_timeout, (unsigned long)info);
 
 		/* Copy configuration info to device instance data */
 		info->pdev = pdev;
@@ -3797,10 +3788,9 @@
 				}
 			}
 
-			if (info->params.mode == MGSL_MODE_HDLC) {
-				info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
-				add_timer(&info->tx_timer);
-			}
+			if (info->params.mode == MGSL_MODE_HDLC)
+				mod_timer(&info->tx_timer, jiffies +
+						msecs_to_jiffies(5000));
 		} else {
 			tdma_reset(info);
 			/* set 1st descriptor address */
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 8f4d67a..ef93d05 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1258,7 +1258,6 @@
 	del_timer(&info->tx_timer);
 	spin_unlock_irqrestore(&info->lock,flags);
 
-	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
 }
 
@@ -2127,10 +2126,8 @@
 		printk( "%s(%d):%s bh_transmit() entry\n",
 			__FILE__,__LINE__,info->device_name);
 
-	if (tty) {
+	if (tty)
 		tty_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
 }
 
 void bh_status(SLMP_INFO *info)
@@ -2747,8 +2744,7 @@
 
 	change_params(info);
 
-	info->status_timer.expires = jiffies + msecs_to_jiffies(10);
-	add_timer(&info->status_timer);
+	mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10));
 
 	if (info->tty)
 		clear_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -3844,13 +3840,9 @@
 		info->bus_type = MGSL_BUS_TYPE_PCI;
 		info->irq_flags = IRQF_SHARED;
 
-		init_timer(&info->tx_timer);
-		info->tx_timer.data = (unsigned long)info;
-		info->tx_timer.function = tx_timeout;
-
-		init_timer(&info->status_timer);
-		info->status_timer.data = (unsigned long)info;
-		info->status_timer.function = status_timeout;
+		setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
+		setup_timer(&info->status_timer, status_timeout,
+				(unsigned long)info);
 
 		/* Store the PCI9050 misc control register value because a flaw
 		 * in the PCI9050 prevents LCR registers from being read if
@@ -4294,8 +4286,8 @@
 			write_reg(info, TXDMA + DIR, 0x40);		/* enable Tx DMA interrupts (EOM) */
 			write_reg(info, TXDMA + DSR, 0xf2);		/* clear Tx DMA IRQs, enable Tx DMA */
 	
-			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
-			add_timer(&info->tx_timer);
+			mod_timer(&info->tx_timer, jiffies +
+					msecs_to_jiffies(5000));
 		}
 		else {
 			tx_load_fifo(info);
@@ -5577,10 +5569,7 @@
 	if (status)
 		isr_io_pin(info,status);
 
-	info->status_timer.data = (unsigned long)info;
-	info->status_timer.function = status_timeout;
-	info->status_timer.expires = jiffies + msecs_to_jiffies(10);
-	add_timer(&info->status_timer);
+	mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10));
 }
 
 
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 7fd3cd5..1d8c4ae6 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -36,6 +36,7 @@
 #include <linux/workqueue.h>
 #include <linux/kexec.h>
 #include <linux/irq.h>
+#include <linux/hrtimer.h>
 
 #include <asm/ptrace.h>
 #include <asm/irq_regs.h>
@@ -88,9 +89,8 @@
 #ifdef CONFIG_VT
 static void sysrq_handle_SAK(int key, struct tty_struct *tty)
 {
-	if (tty)
-		do_SAK(tty);
-	reset_vc(vc_cons[fg_console].d);
+	struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
+	schedule_work(SAK_work);
 }
 static struct sysrq_key_op sysrq_SAK_op = {
 	.handler	= sysrq_handle_SAK,
@@ -159,6 +159,17 @@
 	.enable_mask	= SYSRQ_ENABLE_SYNC,
 };
 
+static void sysrq_handle_show_timers(int key, struct tty_struct *tty)
+{
+	sysrq_timer_list_show();
+}
+
+static struct sysrq_key_op sysrq_show_timers_op = {
+	.handler	= sysrq_handle_show_timers,
+	.help_msg	= "show-all-timers(Q)",
+	.action_msg	= "Show Pending Timers",
+};
+
 static void sysrq_handle_mountro(int key, struct tty_struct *tty)
 {
 	emergency_remount();
@@ -336,7 +347,7 @@
 	/* o: This will often be registered as 'Off' at init time */
 	NULL,				/* o */
 	&sysrq_showregs_op,		/* p */
-	NULL,				/* q */
+	&sysrq_show_timers_op,		/* q */
 	&sysrq_unraw_op,		/* r */
 	&sysrq_sync_op,			/* s */
 	&sysrq_showstate_op,		/* t */
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 4fac2bd..35e5803 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -29,7 +29,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>	/* printk() */
 #include <linux/fs.h>		/* everything... */
 #include <linux/errno.h>	/* error codes */
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index 07067c3..5422f99 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -58,7 +58,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/miscdevice.h>
@@ -68,6 +67,7 @@
 #include <linux/init.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <linux/toshiba.h>
 
@@ -298,12 +298,10 @@
  * Print the information for /proc/toshiba
  */
 #ifdef CONFIG_PROC_FS
-static int tosh_get_info(char *buffer, char **start, off_t fpos, int length)
+static int proc_toshiba_show(struct seq_file *m, void *v)
 {
-	char *temp;
 	int key;
 
-	temp = buffer;
 	key = tosh_fn_status();
 
 	/* Arguments
@@ -314,8 +312,7 @@
 	     4) BIOS date (in SCI date format)
 	     5) Fn Key status
 	*/
-
-	temp += sprintf(temp, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n",
+	seq_printf(m, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n",
 		tosh_id,
 		(tosh_sci & 0xff00)>>8,
 		tosh_sci & 0xff,
@@ -323,9 +320,21 @@
 		tosh_bios & 0xff,
 		tosh_date,
 		key);
-
-	return temp-buffer;
+	return 0;
 }
+
+static int proc_toshiba_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_toshiba_show, NULL);
+}
+
+static const struct file_operations proc_toshiba_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_toshiba_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 #endif
 
 
@@ -508,10 +517,15 @@
 		return retval;
 
 #ifdef CONFIG_PROC_FS
-	/* register the proc entry */
-	if (create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL) {
-		misc_deregister(&tosh_device);
-		return -ENOMEM;
+	{
+		struct proc_dir_entry *pde;
+
+		pde = create_proc_entry("toshiba", 0, NULL);
+		if (!pde) {
+			misc_deregister(&tosh_device);
+			return -ENOMEM;
+		}
+		pde->proc_fops = &proc_toshiba_fops;
 	}
 #endif
 
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 33e1f66..e5a254a 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -23,7 +23,6 @@
  *
  */
 
-#include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include "tpm.h"
@@ -1107,9 +1106,8 @@
 
 	INIT_WORK(&chip->work, timeout_work);
 
-	init_timer(&chip->user_read_timer);
-	chip->user_read_timer.function = user_reader_timeout;
-	chip->user_read_timer.data = (unsigned long) chip;
+	setup_timer(&chip->user_read_timer, user_reader_timeout,
+			(unsigned long)chip);
 
 	memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
 
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
index 7fca5f4..4eba32b 100644
--- a/drivers/char/tpm/tpm_bios.c
+++ b/drivers/char/tpm/tpm_bios.c
@@ -441,7 +441,7 @@
 	return err;
 }
 
-struct file_operations tpm_ascii_bios_measurements_ops = {
+const struct file_operations tpm_ascii_bios_measurements_ops = {
 	.open = tpm_ascii_bios_measurements_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
@@ -474,7 +474,7 @@
 	return err;
 }
 
-struct file_operations tpm_binary_bios_measurements_ops = {
+const struct file_operations tpm_binary_bios_measurements_ops = {
 	.open = tpm_binary_bios_measurements_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 47a6eac..f24c26d 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -154,7 +154,9 @@
 int tty_ioctl(struct inode * inode, struct file * file,
 	      unsigned int cmd, unsigned long arg);
 static int tty_fasync(int fd, struct file * filp, int on);
-static void release_mem(struct tty_struct *tty, int idx);
+static void release_tty(struct tty_struct *tty, int idx);
+static struct pid *__proc_set_tty(struct task_struct *tsk,
+				struct tty_struct *tty);
 
 /**
  *	alloc_tty_struct	-	allocate a tty object
@@ -1109,17 +1111,17 @@
 {
 	if (current->signal->tty != tty)
 		return 0;
-	if (tty->pgrp <= 0) {
-		printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n");
+	if (!tty->pgrp) {
+		printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
 		return 0;
 	}
-	if (process_group(current) == tty->pgrp)
+	if (task_pgrp(current) == tty->pgrp)
 		return 0;
 	if (is_ignored(SIGTTOU))
 		return 0;
-	if (is_orphaned_pgrp(process_group(current)))
+	if (is_current_pgrp_orphaned())
 		return -EIO;
-	(void) kill_pg(process_group(current), SIGTTOU, 1);
+	(void) kill_pgrp(task_pgrp(current), SIGTTOU, 1);
 	return -ERESTARTSYS;
 }
 
@@ -1354,8 +1356,8 @@
 	  tty_release is called */
 	
 	read_lock(&tasklist_lock);
-	if (tty->session > 0) {
-		do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+	if (tty->session) {
+		do_each_pid_task(tty->session, PIDTYPE_SID, p) {
 			spin_lock_irq(&p->sighand->siglock);
 			if (p->signal->tty == tty)
 				p->signal->tty = NULL;
@@ -1365,16 +1367,17 @@
 			}
 			__group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
 			__group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
-			if (tty->pgrp > 0)
-				p->signal->tty_old_pgrp = tty->pgrp;
+			put_pid(p->signal->tty_old_pgrp);  /* A noop */
+			if (tty->pgrp)
+				p->signal->tty_old_pgrp = get_pid(tty->pgrp);
 			spin_unlock_irq(&p->sighand->siglock);
-		} while_each_task_pid(tty->session, PIDTYPE_SID, p);
+		} while_each_pid_task(tty->session, PIDTYPE_SID, p);
 	}
 	read_unlock(&tasklist_lock);
 
 	tty->flags = 0;
-	tty->session = 0;
-	tty->pgrp = -1;
+	tty->session = NULL;
+	tty->pgrp = NULL;
 	tty->ctrl_status = 0;
 	/*
 	 *	If one of the devices matches a console pointer, we
@@ -1459,12 +1462,12 @@
 
 EXPORT_SYMBOL(tty_hung_up_p);
 
-static void session_clear_tty(pid_t session)
+static void session_clear_tty(struct pid *session)
 {
 	struct task_struct *p;
-	do_each_task_pid(session, PIDTYPE_SID, p) {
+	do_each_pid_task(session, PIDTYPE_SID, p) {
 		proc_clear_tty(p);
-	} while_each_task_pid(session, PIDTYPE_SID, p);
+	} while_each_pid_task(session, PIDTYPE_SID, p);
 }
 
 /**
@@ -1494,46 +1497,54 @@
 void disassociate_ctty(int on_exit)
 {
 	struct tty_struct *tty;
-	int tty_pgrp = -1;
-	int session;
+	struct pid *tty_pgrp = NULL;
 
 	lock_kernel();
 
 	mutex_lock(&tty_mutex);
 	tty = get_current_tty();
 	if (tty) {
-		tty_pgrp = tty->pgrp;
+		tty_pgrp = get_pid(tty->pgrp);
 		mutex_unlock(&tty_mutex);
 		/* XXX: here we race, there is nothing protecting tty */
 		if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
 			tty_vhangup(tty);
-	} else {
-		pid_t old_pgrp = current->signal->tty_old_pgrp;
+	} else if (on_exit) {
+		struct pid *old_pgrp;
+		spin_lock_irq(&current->sighand->siglock);
+		old_pgrp = current->signal->tty_old_pgrp;
+		current->signal->tty_old_pgrp = NULL;
+		spin_unlock_irq(&current->sighand->siglock);
 		if (old_pgrp) {
-			kill_pg(old_pgrp, SIGHUP, on_exit);
-			kill_pg(old_pgrp, SIGCONT, on_exit);
+			kill_pgrp(old_pgrp, SIGHUP, on_exit);
+			kill_pgrp(old_pgrp, SIGCONT, on_exit);
+			put_pid(old_pgrp);
 		}
 		mutex_unlock(&tty_mutex);
 		unlock_kernel();	
 		return;
 	}
-	if (tty_pgrp > 0) {
-		kill_pg(tty_pgrp, SIGHUP, on_exit);
+	if (tty_pgrp) {
+		kill_pgrp(tty_pgrp, SIGHUP, on_exit);
 		if (!on_exit)
-			kill_pg(tty_pgrp, SIGCONT, on_exit);
+			kill_pgrp(tty_pgrp, SIGCONT, on_exit);
+		put_pid(tty_pgrp);
 	}
 
 	spin_lock_irq(&current->sighand->siglock);
-	current->signal->tty_old_pgrp = 0;
-	session = process_session(current);
+	tty_pgrp = current->signal->tty_old_pgrp;
+	current->signal->tty_old_pgrp = NULL;
 	spin_unlock_irq(&current->sighand->siglock);
+	put_pid(tty_pgrp);
 
 	mutex_lock(&tty_mutex);
 	/* It is possible that do_tty_hangup has free'd this tty */
 	tty = get_current_tty();
 	if (tty) {
-		tty->session = 0;
-		tty->pgrp = 0;
+		put_pid(tty->session);
+		put_pid(tty->pgrp);
+		tty->session = NULL;
+		tty->pgrp = NULL;
 	} else {
 #ifdef TTY_DEBUG_HANGUP
 		printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
@@ -1544,7 +1555,7 @@
 
 	/* Now clear signal->tty under the lock */
 	read_lock(&tasklist_lock);
-	session_clear_tty(session);
+	session_clear_tty(task_session(current));
 	read_unlock(&tasklist_lock);
 	unlock_kernel();
 }
@@ -1612,7 +1623,6 @@
 
 	/* If we have a running line discipline it may need kicking */
 	tty_wakeup(tty);
-	wake_up_interruptible(&tty->write_wait);
 }
 
 EXPORT_SYMBOL(start_tty);
@@ -2003,7 +2013,7 @@
 
 	/* 
 	 * All structures have been allocated, so now we install them.
-	 * Failures after this point use release_mem to clean up, so 
+	 * Failures after this point use release_tty to clean up, so
 	 * there's no need to null out the local pointers.
 	 */
 	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
@@ -2024,8 +2034,8 @@
 
 	/* 
 	 * Structures all installed ... call the ldisc open routines.
-	 * If we fail here just call release_mem to clean up.  No need
-	 * to decrement the use counts, as release_mem doesn't care.
+	 * If we fail here just call release_tty to clean up.  No need
+	 * to decrement the use counts, as release_tty doesn't care.
 	 */
 
 	if (tty->ldisc.open) {
@@ -2095,17 +2105,17 @@
 	retval = -ENOMEM;
 	goto end_init;
 
-	/* call the tty release_mem routine to clean out this slot */
+	/* call the tty release_tty routine to clean out this slot */
 release_mem_out:
 	if (printk_ratelimit())
 		printk(KERN_INFO "init_dev: ldisc open failed, "
 				 "clearing slot %d\n", idx);
-	release_mem(tty, idx);
+	release_tty(tty, idx);
 	goto end_init;
 }
 
 /**
- *	release_mem		-	release tty structure memory
+ *	release_one_tty		-	release tty structure memory
  *
  *	Releases memory associated with a tty structure, and clears out the
  *	driver table slots. This function is called when a device is no longer
@@ -2117,37 +2127,14 @@
  *	of ttys that the driver keeps.
  *		FIXME: should we require tty_mutex is held here ??
  */
-
-static void release_mem(struct tty_struct *tty, int idx)
+static void release_one_tty(struct tty_struct *tty, int idx)
 {
-	struct tty_struct *o_tty;
-	struct ktermios *tp;
 	int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
-
-	if ((o_tty = tty->link) != NULL) {
-		if (!devpts)
-			o_tty->driver->ttys[idx] = NULL;
-		if (o_tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-			tp = o_tty->termios;
-			if (!devpts)
-				o_tty->driver->termios[idx] = NULL;
-			kfree(tp);
-
-			tp = o_tty->termios_locked;
-			if (!devpts)
-				o_tty->driver->termios_locked[idx] = NULL;
-			kfree(tp);
-		}
-		o_tty->magic = 0;
-		o_tty->driver->refcount--;
-		file_list_lock();
-		list_del_init(&o_tty->tty_files);
-		file_list_unlock();
-		free_tty_struct(o_tty);
-	}
+	struct ktermios *tp;
 
 	if (!devpts)
 		tty->driver->ttys[idx] = NULL;
+
 	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
 		tp = tty->termios;
 		if (!devpts)
@@ -2160,15 +2147,39 @@
 		kfree(tp);
 	}
 
+
 	tty->magic = 0;
 	tty->driver->refcount--;
+
 	file_list_lock();
 	list_del_init(&tty->tty_files);
 	file_list_unlock();
-	module_put(tty->driver->owner);
+
 	free_tty_struct(tty);
 }
 
+/**
+ *	release_tty		-	release tty structure memory
+ *
+ *	Release both @tty and a possible linked partner (think pty pair),
+ *	and decrement the refcount of the backing module.
+ *
+ *	Locking:
+ *		tty_mutex - sometimes only
+ *		takes the file list lock internally when working on the list
+ *	of ttys that the driver keeps.
+ *		FIXME: should we require tty_mutex is held here ??
+ */
+static void release_tty(struct tty_struct *tty, int idx)
+{
+	struct tty_driver *driver = tty->driver;
+
+	if (tty->link)
+		release_one_tty(tty->link, idx);
+	release_one_tty(tty, idx);
+	module_put(driver->owner);
+}
+
 /*
  * Even releasing the tty structures is a tricky business.. We have
  * to be very careful that the structures are all released at the
@@ -2436,10 +2447,10 @@
 		tty_set_termios_ldisc(o_tty,N_TTY); 
 	}
 	/*
-	 * The release_mem function takes care of the details of clearing
+	 * The release_tty function takes care of the details of clearing
 	 * the slots and preserving the termios structure.
 	 */
-	release_mem(tty, idx);
+	release_tty(tty, idx);
 
 #ifdef CONFIG_UNIX98_PTYS
 	/* Make this pty number available for reallocation */
@@ -2481,6 +2492,7 @@
 	int index;
 	dev_t device = inode->i_rdev;
 	unsigned short saved_flags = filp->f_flags;
+	struct pid *old_pgrp;
 
 	nonseekable_open(inode, filp);
 	
@@ -2574,15 +2586,17 @@
 		goto retry_open;
 	}
 
+	old_pgrp = NULL;
 	mutex_lock(&tty_mutex);
 	spin_lock_irq(&current->sighand->siglock);
 	if (!noctty &&
 	    current->signal->leader &&
 	    !current->signal->tty &&
-	    tty->session == 0)
-		__proc_set_tty(current, tty);
+	    tty->session == NULL)
+		old_pgrp = __proc_set_tty(current, tty);
 	spin_unlock_irq(&current->sighand->siglock);
 	mutex_unlock(&tty_mutex);
+	put_pid(old_pgrp);
 	return 0;
 }
 
@@ -2721,9 +2735,18 @@
 		return retval;
 
 	if (on) {
+		enum pid_type type;
+		struct pid *pid;
 		if (!waitqueue_active(&tty->read_wait))
 			tty->minimum_to_wake = 1;
-		retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0);
+		if (tty->pgrp) {
+			pid = tty->pgrp;
+			type = PIDTYPE_PGID;
+		} else {
+			pid = task_pid(current);
+			type = PIDTYPE_PID;
+		}
+		retval = __f_setown(filp, pid, type, 0);
 		if (retval)
 			return retval;
 	} else {
@@ -2825,10 +2848,10 @@
 		}
 	}
 #endif
-	if (tty->pgrp > 0)
-		kill_pg(tty->pgrp, SIGWINCH, 1);
-	if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0))
-		kill_pg(real_tty->pgrp, SIGWINCH, 1);
+	if (tty->pgrp)
+		kill_pgrp(tty->pgrp, SIGWINCH, 1);
+	if ((real_tty->pgrp != tty->pgrp) && real_tty->pgrp)
+		kill_pgrp(real_tty->pgrp, SIGWINCH, 1);
 	tty->winsize = tmp_ws;
 	real_tty->winsize = tmp_ws;
 done:
@@ -2913,8 +2936,7 @@
 static int tiocsctty(struct tty_struct *tty, int arg)
 {
 	int ret = 0;
-	if (current->signal->leader &&
-			(process_session(current) == tty->session))
+	if (current->signal->leader && (task_session(current) == tty->session))
 		return ret;
 
 	mutex_lock(&tty_mutex);
@@ -2927,7 +2949,7 @@
 		goto unlock;
 	}
 
-	if (tty->session > 0) {
+	if (tty->session) {
 		/*
 		 * This tty is already the controlling
 		 * tty for another session group!
@@ -2970,7 +2992,7 @@
 	 */
 	if (tty == real_tty && current->signal->tty != real_tty)
 		return -ENOTTY;
-	return put_user(real_tty->pgrp, p);
+	return put_user(pid_nr(real_tty->pgrp), p);
 }
 
 /**
@@ -2987,7 +3009,8 @@
 
 static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
 {
-	pid_t pgrp;
+	struct pid *pgrp;
+	pid_t pgrp_nr;
 	int retval = tty_check_change(real_tty);
 
 	if (retval == -EIO)
@@ -2996,16 +3019,26 @@
 		return retval;
 	if (!current->signal->tty ||
 	    (current->signal->tty != real_tty) ||
-	    (real_tty->session != process_session(current)))
+	    (real_tty->session != task_session(current)))
 		return -ENOTTY;
-	if (get_user(pgrp, p))
+	if (get_user(pgrp_nr, p))
 		return -EFAULT;
-	if (pgrp < 0)
+	if (pgrp_nr < 0)
 		return -EINVAL;
-	if (session_of_pgrp(pgrp) != process_session(current))
-		return -EPERM;
-	real_tty->pgrp = pgrp;
-	return 0;
+	rcu_read_lock();
+	pgrp = find_pid(pgrp_nr);
+	retval = -ESRCH;
+	if (!pgrp)
+		goto out_unlock;
+	retval = -EPERM;
+	if (session_of_pgrp(pgrp) != task_session(current))
+		goto out_unlock;
+	retval = 0;
+	put_pid(real_tty->pgrp);
+	real_tty->pgrp = get_pid(pgrp);
+out_unlock:
+	rcu_read_unlock();
+	return retval;
 }
 
 /**
@@ -3028,9 +3061,9 @@
 	*/
 	if (tty == real_tty && current->signal->tty != real_tty)
 		return -ENOTTY;
-	if (real_tty->session <= 0)
+	if (!real_tty->session)
 		return -ENOTTY;
-	return put_user(real_tty->session, p);
+	return put_user(pid_nr(real_tty->session), p);
 }
 
 /**
@@ -3324,15 +3357,13 @@
  * Nasty bug: do_SAK is being called in interrupt context.  This can
  * deadlock.  We punt it up to process context.  AKPM - 16Mar2001
  */
-static void __do_SAK(struct work_struct *work)
+void __do_SAK(struct tty_struct *tty)
 {
-	struct tty_struct *tty =
-		container_of(work, struct tty_struct, SAK_work);
 #ifdef TTY_SOFT_SAK
 	tty_hangup(tty);
 #else
 	struct task_struct *g, *p;
-	int session;
+	struct pid *session;
 	int		i;
 	struct file	*filp;
 	struct fdtable *fdt;
@@ -3348,12 +3379,12 @@
 	
 	read_lock(&tasklist_lock);
 	/* Kill the entire session */
-	do_each_task_pid(session, PIDTYPE_SID, p) {
+	do_each_pid_task(session, PIDTYPE_SID, p) {
 		printk(KERN_NOTICE "SAK: killed process %d"
 			" (%s): process_session(p)==tty->session\n",
 			p->pid, p->comm);
 		send_sig(SIGKILL, p, 1);
-	} while_each_task_pid(session, PIDTYPE_SID, p);
+	} while_each_pid_task(session, PIDTYPE_SID, p);
 	/* Now kill any processes that happen to have the
 	 * tty open.
 	 */
@@ -3394,6 +3425,13 @@
 #endif
 }
 
+static void do_SAK_work(struct work_struct *work)
+{
+	struct tty_struct *tty =
+		container_of(work, struct tty_struct, SAK_work);
+	__do_SAK(tty);
+}
+
 /*
  * The tq handling here is a little racy - tty->SAK_work may already be queued.
  * Fortunately we don't need to worry, because if ->SAK_work is already queued,
@@ -3404,7 +3442,6 @@
 {
 	if (!tty)
 		return;
-	PREPARE_WORK(&tty->SAK_work, __do_SAK);
 	schedule_work(&tty->SAK_work);
 }
 
@@ -3515,7 +3552,8 @@
 	memset(tty, 0, sizeof(struct tty_struct));
 	tty->magic = TTY_MAGIC;
 	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
-	tty->pgrp = -1;
+	tty->session = NULL;
+	tty->pgrp = NULL;
 	tty->overrun_time = jiffies;
 	tty->buf.head = tty->buf.tail = NULL;
 	tty_buffer_init(tty);
@@ -3529,7 +3567,7 @@
 	mutex_init(&tty->atomic_write_lock);
 	spin_lock_init(&tty->read_lock);
 	INIT_LIST_HEAD(&tty->tty_files);
-	INIT_WORK(&tty->SAK_work, NULL);
+	INIT_WORK(&tty->SAK_work, do_SAK_work);
 }
 
 /*
@@ -3675,15 +3713,14 @@
 
 	if (!driver->major) {
 		error = alloc_chrdev_region(&dev, driver->minor_start, driver->num,
-						(char*)driver->name);
+						driver->name);
 		if (!error) {
 			driver->major = MAJOR(dev);
 			driver->minor_start = MINOR(dev);
 		}
 	} else {
 		dev = MKDEV(driver->major, driver->minor_start);
-		error = register_chrdev_region(dev, driver->num,
-						(char*)driver->name);
+		error = register_chrdev_region(dev, driver->num, driver->name);
 	}
 	if (error < 0) {
 		kfree(p);
@@ -3786,21 +3823,28 @@
 }
 EXPORT_SYMBOL(proc_clear_tty);
 
-void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
 {
+	struct pid *old_pgrp;
 	if (tty) {
-		tty->session = process_session(tsk);
-		tty->pgrp = process_group(tsk);
+		tty->session = get_pid(task_session(tsk));
+		tty->pgrp = get_pid(task_pgrp(tsk));
 	}
+	old_pgrp = tsk->signal->tty_old_pgrp;
 	tsk->signal->tty = tty;
-	tsk->signal->tty_old_pgrp = 0;
+	tsk->signal->tty_old_pgrp = NULL;
+	return old_pgrp;
 }
 
 void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
 {
+	struct pid *old_pgrp;
+
 	spin_lock_irq(&tsk->sighand->siglock);
-	__proc_set_tty(tsk, tty);
+	old_pgrp = __proc_set_tty(tsk, tty);
 	spin_unlock_irq(&tsk->sighand->siglock);
+
+	put_pid(old_pgrp);
 }
 
 struct tty_struct *get_current_tty(void)
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index dee47f4..fd471cb 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -225,7 +225,7 @@
 
 /**
  *	tty_termios_encode_baud_rate
- *	@termios: termios structure
+ *	@termios: ktermios structure holding user requested state
  *	@ispeed: input speed
  *	@ospeed: output speed
  *
@@ -233,7 +233,10 @@
  *	used as a library helper for drivers os that they can report back
  *	the actual speed selected when it differs from the speed requested
  *
- *	For now input and output speed must agree.
+ *	For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
+ *	we need to carefully set the bits when the user does not get the
+ *	desired speed. We allow small margins and preserve as much of possible
+ *	of the input intent to keep compatiblity.
  *
  *	Locking: Caller should hold termios lock. This is already held
  *	when calling this function from the driver termios handler.
@@ -242,32 +245,44 @@
 void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
 {
 	int i = 0;
-	int ifound = 0, ofound = 0;
+	int ifound = -1, ofound = -1;
+	int iclose = ibaud/50, oclose = obaud/50;
+	int ibinput = 0;
 
 	termios->c_ispeed = ibaud;
 	termios->c_ospeed = obaud;
 
+	/* If the user asked for a precise weird speed give a precise weird
+	   answer. If they asked for a Bfoo speed they many have problems
+	   digesting non-exact replies so fuzz a bit */
+
+	if ((termios->c_cflag & CBAUD) == BOTHER)
+		oclose = 0;
+	if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
+		iclose = 0;
+	if ((termios->c_cflag >> IBSHIFT) & CBAUD)
+		ibinput = 1;	/* An input speed was specified */
+
 	termios->c_cflag &= ~CBAUD;
-	/* Identical speed means no input encoding (ie B0 << IBSHIFT)*/
-	if (termios->c_ispeed == termios->c_ospeed)
-		ifound = 1;
 
 	do {
-		if (obaud == baud_table[i]) {
+		if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) {
 			termios->c_cflag |= baud_bits[i];
-			ofound = 1;
-			/* So that if ibaud == obaud we don't set it */
-			continue;
+			ofound = i;
 		}
-		if (ibaud == baud_table[i]) {
-			termios->c_cflag |= (baud_bits[i] << IBSHIFT);
-			ifound = 1;
+		if (ibaud - iclose >= baud_table[i] && ibaud + iclose <= baud_table[i]) {
+			/* For the case input == output don't set IBAUD bits if the user didn't do so */
+			if (ofound != i || ibinput)
+				termios->c_cflag |= (baud_bits[i] << IBSHIFT);
+			ifound = i;
 		}
 	}
 	while(++i < n_baud_table);
-	if (!ofound)
+	if (ofound == -1)
 		termios->c_cflag |= BOTHER;
-	if (!ifound)
+	/* Set exact input bits only if the input and output differ or the
+	   user already did */
+	if (ifound == -1 && (ibaud != obaud  || ibinput))
 		termios->c_cflag |= (BOTHER << IBSHIFT);
 }
 
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 2677651..7919303 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -25,7 +25,6 @@
 #include <linux/major.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/init.h>
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 9438512..13faf8d 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -872,7 +872,7 @@
 	return ret;
 }
 
-struct file_operations viotap_fops = {
+const struct file_operations viotap_fops = {
 	owner: THIS_MODULE,
 	read: viotap_read,
 	write: viotap_write,
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index e01317c..bef6d88 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -17,7 +17,6 @@
 #include <linux/kdev_t.h>
 #include <asm/io.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 06c32a3..c3f8e38 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -136,9 +136,6 @@
 #define DEFAULT_BELL_PITCH	750
 #define DEFAULT_BELL_DURATION	(HZ/8)
 
-extern void vcs_make_sysfs(struct tty_struct *tty);
-extern void vcs_remove_sysfs(struct tty_struct *tty);
-
 struct vc vc_cons [MAX_NR_CONSOLES];
 
 #ifndef VT_SINGLE_DRIVER
@@ -213,7 +210,7 @@
  */
 int (*console_blank_hook)(int);
 
-static struct timer_list console_timer;
+static DEFINE_TIMER(console_timer, blank_screen_t, 0, 0);
 static int blank_state;
 static int blank_timer_expired;
 enum {
@@ -869,8 +866,8 @@
 		ws.ws_col = vc->vc_cols;
 		ws.ws_ypixel = vc->vc_scan_lines;
 		if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
-		    vc->vc_tty->pgrp > 0)
-			kill_pg(vc->vc_tty->pgrp, SIGWINCH, 1);
+		    vc->vc_tty->pgrp)
+			kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1);
 		*cws = ws;
 	}
 
@@ -2628,8 +2625,6 @@
 	for (i = 0; i < MAX_NR_CONSOLES; i++)
 		con_driver_map[i] = conswitchp;
 
-	init_timer(&console_timer);
-	console_timer.function = blank_screen_t;
 	if (blankinterval) {
 		blank_state = blank_normal_wait;
 		mod_timer(&console_timer, jiffies + blankinterval);
@@ -2640,6 +2635,7 @@
 	 */
 	for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
 		vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data));
+		INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
 		visual_init(vc, currcons, 1);
 		vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size);
 		vc->vc_kmalloced = 0;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index dc8368e..3a5d301 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -672,7 +672,8 @@
 		vc->vt_mode = tmp;
 		/* the frsig is ignored, so we set it to 0 */
 		vc->vt_mode.frsig = 0;
-		put_pid(xchg(&vc->vt_pid, get_pid(task_pid(current))));
+		put_pid(vc->vt_pid);
+		vc->vt_pid = get_pid(task_pid(current));
 		/* no switch is required -- saw@shade.msu.ru */
 		vc->vt_newvt = -1;
 		release_console_sem();
@@ -1063,12 +1064,35 @@
 	vc->vt_mode.relsig = 0;
 	vc->vt_mode.acqsig = 0;
 	vc->vt_mode.frsig = 0;
-	put_pid(xchg(&vc->vt_pid, NULL));
+	put_pid(vc->vt_pid);
+	vc->vt_pid = NULL;
 	vc->vt_newvt = -1;
 	if (!in_interrupt())    /* Via keyboard.c:SAK() - akpm */
 		reset_palette(vc);
 }
 
+void vc_SAK(struct work_struct *work)
+{
+	struct vc *vc_con =
+		container_of(work, struct vc, SAK_work);
+	struct vc_data *vc;
+	struct tty_struct *tty;
+
+	acquire_console_sem();
+	vc = vc_con->d;
+	if (vc) {
+		tty = vc->vc_tty;
+		/*
+		 * SAK should also work in all raw modes and reset
+		 * them properly.
+		 */
+		if (tty)
+			__do_SAK(tty);
+		reset_vc(vc);
+	}
+	release_console_sem();
+}
+
 /*
  * Performs the back end of a vt switch
  */
diff --git a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c
index 154d67e..85269c3 100644
--- a/drivers/char/watchdog/acquirewdt.c
+++ b/drivers/char/watchdog/acquirewdt.c
@@ -48,46 +48,52 @@
  *		It can be 1, 2, 10, 20, 110 or 220 seconds.
  */
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
+/*
+ *	Includes, defines, variables, module parameters, ...
+ */
 
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
+/* Includes */
+#include <linux/module.h>		/* For module specific items */
+#include <linux/moduleparam.h>		/* For new moduleparam's */
+#include <linux/types.h>		/* For standard types (like size_t) */
+#include <linux/errno.h>		/* For the -ENODEV/... values */
+#include <linux/kernel.h>		/* For printk/panic/... */
+#include <linux/miscdevice.h>		/* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>		/* For the watchdog specific items */
+#include <linux/fs.h>			/* For file operations */
+#include <linux/ioport.h>		/* For io-port access */
+#include <linux/platform_device.h>	/* For platform_driver framework */
+#include <linux/init.h>			/* For __init/__exit/... */
 
+#include <asm/uaccess.h>		/* For copy_to_user/put_user/... */
+#include <asm/io.h>			/* For inb/outb/... */
+
+/* Module information */
+#define DRV_NAME "acquirewdt"
+#define PFX DRV_NAME ": "
 #define WATCHDOG_NAME "Acquire WDT"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_HEARTBEAT 0	/* There is no way to see what the correct time-out period is */
 
+/* internal variables */
+static struct platform_device *acq_platform_device;	/* the watchdog platform device */
 static unsigned long acq_is_open;
 static char expect_close;
 
-/*
- *	You must set these - there is no sane way to probe for this board.
- */
-
-static int wdt_stop = 0x43;
+/* module parameters */
+static int wdt_stop = 0x43;	/* You must set this - there is no sane way to probe for this board. */
 module_param(wdt_stop, int, 0);
 MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)");
 
-static int wdt_start = 0x443;
+static int wdt_start = 0x443;	/* You must set this - there is no sane way to probe for this board. */
 module_param(wdt_start, int, 0);
 MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
- *	Kernel methods.
+ *	Watchdog Operations
  */
 
 static void acq_keepalive(void)
@@ -103,7 +109,7 @@
 }
 
 /*
- *	/dev/watchdog handling.
+ *	/dev/watchdog handling
  */
 
 static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
@@ -143,7 +149,7 @@
 	{
 		.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
-		.identity = "Acquire WDT",
+		.identity = WATCHDOG_NAME,
 	};
 
 	switch(cmd)
@@ -214,20 +220,6 @@
 }
 
 /*
- *	Notifier for system down
- */
-
-static int acq_notify_sys(struct notifier_block *this, unsigned long code,
-	void *unused)
-{
-	if(code==SYS_DOWN || code==SYS_HALT) {
-		/* Turn the WDT off */
-		acq_stop();
-	}
-	return NOTIFY_DONE;
-}
-
-/*
  *	Kernel Interfaces
  */
 
@@ -240,29 +232,20 @@
 	.release	= acq_close,
 };
 
-static struct miscdevice acq_miscdev=
-{
-	.minor = WATCHDOG_MINOR,
-	.name = "watchdog",
-	.fops = &acq_fops,
+static struct miscdevice acq_miscdev = {
+	.minor	= WATCHDOG_MINOR,
+	.name	= "watchdog",
+	.fops	= &acq_fops,
 };
 
 /*
- *	The WDT card needs to learn about soft shutdowns in order to
- *	turn the timebomb registers off.
+ *	Init & exit routines
  */
 
-static struct notifier_block acq_notifier =
-{
-	.notifier_call = acq_notify_sys,
-};
-
-static int __init acq_init(void)
+static int __devinit acq_probe(struct platform_device *dev)
 {
 	int ret;
 
-	printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n");
-
 	if (wdt_stop != wdt_start) {
 		if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
 			printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -279,18 +262,11 @@
 		goto unreg_stop;
 	}
 
-	ret = register_reboot_notifier(&acq_notifier);
-	if (ret != 0) {
-		printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-			ret);
-		goto unreg_regions;
-	}
-
 	ret = misc_register(&acq_miscdev);
 	if (ret != 0) {
 		printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
 			WATCHDOG_MINOR, ret);
-		goto unreg_reboot;
+		goto unreg_regions;
 	}
 
 	printk (KERN_INFO PFX "initialized. (nowayout=%d)\n",
@@ -298,8 +274,6 @@
 
 	return 0;
 
-unreg_reboot:
-	unregister_reboot_notifier(&acq_notifier);
 unreg_regions:
 	release_region(wdt_start, 1);
 unreg_stop:
@@ -309,13 +283,60 @@
 	return ret;
 }
 
-static void __exit acq_exit(void)
+static int __devexit acq_remove(struct platform_device *dev)
 {
 	misc_deregister(&acq_miscdev);
-	unregister_reboot_notifier(&acq_notifier);
+	release_region(wdt_start,1);
 	if(wdt_stop != wdt_start)
 		release_region(wdt_stop,1);
-	release_region(wdt_start,1);
+
+	return 0;
+}
+
+static void acq_shutdown(struct platform_device *dev)
+{
+	/* Turn the WDT off if we have a soft shutdown */
+	acq_stop();
+}
+
+static struct platform_driver acquirewdt_driver = {
+	.probe		= acq_probe,
+	.remove		= __devexit_p(acq_remove),
+	.shutdown	= acq_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= DRV_NAME,
+	},
+};
+
+static int __init acq_init(void)
+{
+	int err;
+
+	printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n");
+
+	err = platform_driver_register(&acquirewdt_driver);
+	if (err)
+		return err;
+
+	acq_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+	if (IS_ERR(acq_platform_device)) {
+		err = PTR_ERR(acq_platform_device);
+		goto unreg_platform_driver;
+	}
+
+	return 0;
+
+unreg_platform_driver:
+	platform_driver_unregister(&acquirewdt_driver);
+	return err;
+}
+
+static void __exit acq_exit(void)
+{
+	platform_device_unregister(acq_platform_device);
+	platform_driver_unregister(&acquirewdt_driver);
+	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(acq_init);
diff --git a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c
index 9d73276..8121cc2 100644
--- a/drivers/char/watchdog/advantechwdt.c
+++ b/drivers/char/watchdog/advantechwdt.c
@@ -35,18 +35,19 @@
 #include <linux/watchdog.h>
 #include <linux/fs.h>
 #include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
+#include <linux/platform_device.h>
 #include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#define DRV_NAME "advantechwdt"
+#define PFX DRV_NAME ": "
 #define WATCHDOG_NAME "Advantech WDT"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60		/* 60 sec default timeout */
 
+static struct platform_device *advwdt_platform_device;	/* the watchdog platform device */
 static unsigned long advwdt_is_open;
 static char adv_expect_close;
 
@@ -75,10 +76,10 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
- *	Kernel methods.
+ *	Watchdog Operations
  */
 
 static void
@@ -94,6 +95,20 @@
 	inb_p(wdt_stop);
 }
 
+static int
+advwdt_set_heartbeat(int t)
+{
+	if ((t < 1) || (t > 63))
+		return -EINVAL;
+
+	timeout = t;
+	return 0;
+}
+
+/*
+ *	/dev/watchdog handling
+ */
+
 static ssize_t
 advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
@@ -126,7 +141,7 @@
 	static struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
-		.identity = "Advantech WDT",
+		.identity = WATCHDOG_NAME,
 	};
 
 	switch (cmd) {
@@ -146,9 +161,8 @@
 	case WDIOC_SETTIMEOUT:
 	  if (get_user(new_timeout, p))
 		  return -EFAULT;
-	  if ((new_timeout < 1) || (new_timeout > 63))
+	  if (advwdt_set_heartbeat(new_timeout))
 		  return -EINVAL;
-	  timeout = new_timeout;
 	  advwdt_ping();
 	  /* Fall */
 
@@ -209,21 +223,6 @@
 }
 
 /*
- *	Notifier for system down
- */
-
-static int
-advwdt_notify_sys(struct notifier_block *this, unsigned long code,
-	void *unused)
-{
-	if (code == SYS_DOWN || code == SYS_HALT) {
-		/* Turn the WDT off */
-		advwdt_disable();
-	}
-	return NOTIFY_DONE;
-}
-
-/*
  *	Kernel Interfaces
  */
 
@@ -237,33 +236,20 @@
 };
 
 static struct miscdevice advwdt_miscdev = {
-	.minor = WATCHDOG_MINOR,
-	.name = "watchdog",
-	.fops = &advwdt_fops,
+	.minor	= WATCHDOG_MINOR,
+	.name	= "watchdog",
+	.fops	= &advwdt_fops,
 };
 
 /*
- *	The WDT needs to learn about soft shutdowns in order to
- *	turn the timebomb registers off.
+ *	Init & exit routines
  */
 
-static struct notifier_block advwdt_notifier = {
-	.notifier_call = advwdt_notify_sys,
-};
-
-static int __init
-advwdt_init(void)
+static int __devinit
+advwdt_probe(struct platform_device *dev)
 {
 	int ret;
 
-	printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");
-
-	if (timeout < 1 || timeout > 63) {
-		timeout = WATCHDOG_TIMEOUT;
-		printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n",
-			timeout);
-	}
-
 	if (wdt_stop != wdt_start) {
 		if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
 			printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -280,18 +266,18 @@
 		goto unreg_stop;
 	}
 
-	ret = register_reboot_notifier(&advwdt_notifier);
-	if (ret != 0) {
-		printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-			ret);
-		goto unreg_regions;
+	/* Check that the heartbeat value is within it's range ; if not reset to the default */
+	if (advwdt_set_heartbeat(timeout)) {
+		advwdt_set_heartbeat(WATCHDOG_TIMEOUT);
+		printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n",
+			timeout);
 	}
 
 	ret = misc_register(&advwdt_miscdev);
 	if (ret != 0) {
 		printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
 			WATCHDOG_MINOR, ret);
-		goto unreg_reboot;
+		goto unreg_regions;
 	}
 
 	printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
@@ -299,8 +285,6 @@
 
 out:
 	return ret;
-unreg_reboot:
-	unregister_reboot_notifier(&advwdt_notifier);
 unreg_regions:
 	release_region(wdt_start, 1);
 unreg_stop:
@@ -309,14 +293,64 @@
 	goto out;
 }
 
+static int __devexit
+advwdt_remove(struct platform_device *dev)
+{
+	misc_deregister(&advwdt_miscdev);
+	release_region(wdt_start,1);
+	if(wdt_stop != wdt_start)
+		release_region(wdt_stop,1);
+
+	return 0;
+}
+
+static void
+advwdt_shutdown(struct platform_device *dev)
+{
+	/* Turn the WDT off if we have a soft shutdown */
+	advwdt_disable();
+}
+
+static struct platform_driver advwdt_driver = {
+	.probe		= advwdt_probe,
+	.remove		= __devexit_p(advwdt_remove),
+	.shutdown	= advwdt_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= DRV_NAME,
+	},
+};
+
+static int __init
+advwdt_init(void)
+{
+	int err;
+
+	printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");
+
+	err = platform_driver_register(&advwdt_driver);
+	if (err)
+		return err;
+
+	advwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+	if (IS_ERR(advwdt_platform_device)) {
+		err = PTR_ERR(advwdt_platform_device);
+		goto unreg_platform_driver;
+	}
+
+	return 0;
+
+unreg_platform_driver:
+	platform_driver_unregister(&advwdt_driver);
+	return err;
+}
+
 static void __exit
 advwdt_exit(void)
 {
-	misc_deregister(&advwdt_miscdev);
-	unregister_reboot_notifier(&advwdt_notifier);
-	if(wdt_stop != wdt_start)
-		release_region(wdt_stop,1);
-	release_region(wdt_start,1);
+	platform_device_unregister(advwdt_platform_device);
+	platform_driver_unregister(&advwdt_driver);
+	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(advwdt_init);
diff --git a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c
index 01b0d13..e3f6a7d 100644
--- a/drivers/char/watchdog/alim1535_wdt.c
+++ b/drivers/char/watchdog/alim1535_wdt.c
@@ -40,7 +40,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *	ali_start	-	start watchdog countdown
diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c
index bf25d0a..67aed9f 100644
--- a/drivers/char/watchdog/alim7101_wdt.c
+++ b/drivers/char/watchdog/alim7101_wdt.c
@@ -69,7 +69,7 @@
 MODULE_PARM_DESC(use_gpio, "Use the gpio watchdog.  (required by old cobalt boards)");
 
 static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 1);
 static unsigned long next_heartbeat;
 static unsigned long wdt_is_open;
 static char wdt_expect_close;
@@ -78,7 +78,7 @@
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
-		 __stringify(CONFIG_WATCHDOG_NOWAYOUT) ")");
+		 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *	Whack the dog
@@ -108,8 +108,7 @@
 		printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
 	}
 	/* Re-set the timer interval */
-	timer.expires = jiffies + WDT_INTERVAL;
-	add_timer(&timer);
+	mod_timer(&timer, jiffies + WDT_INTERVAL);
 }
 
 /*
@@ -147,9 +146,7 @@
 	wdt_change(WDT_ENABLE);
 
 	/* Start the timer */
-	timer.expires = jiffies + WDT_INTERVAL;
-	add_timer(&timer);
-
+	mod_timer(&timer, jiffies + WDT_INTERVAL);
 
 	printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
 }
@@ -380,10 +377,6 @@
 			timeout);
 	}
 
-	init_timer(&timer);
-	timer.function = wdt_timer_ping;
-	timer.data = 1;
-
 	rc = misc_register(&wdt_miscdev);
 	if (rc) {
 		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
@@ -417,10 +410,8 @@
 module_exit(alim7101_wdt_unload);
 
 static struct pci_device_id alim7101_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
 	{ }
 };
 
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
index 00bdabb..bcd7e36 100644
--- a/drivers/char/watchdog/cpu5wdt.c
+++ b/drivers/char/watchdog/cpu5wdt.c
@@ -80,10 +80,8 @@
 	outb(1, port + CPU5WDT_TRIGGER_REG);
 
 	/* requeue?? */
-	if( cpu5wdt_device.queue && ticks ) {
-		cpu5wdt_device.timer.expires = jiffies + CPU5WDT_INTERVAL;
-		add_timer(&cpu5wdt_device.timer);
-	}
+	if (cpu5wdt_device.queue && ticks)
+		mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
 	else {
 		/* ticks doesn't matter anyway */
 		complete(&cpu5wdt_device.stop);
@@ -109,8 +107,7 @@
 		outb(1, port + CPU5WDT_MODE_REG);
 		outb(0, port + CPU5WDT_RESET_REG);
 		outb(0, port + CPU5WDT_ENABLE_REG);
-		cpu5wdt_device.timer.expires = jiffies + CPU5WDT_INTERVAL;
-		add_timer(&cpu5wdt_device.timer);
+		mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
 	}
 	/* if process dies, counter is not decremented */
 	cpu5wdt_device.running++;
@@ -245,9 +242,7 @@
 
 	clear_bit(0, &cpu5wdt_device.inuse);
 
-	init_timer(&cpu5wdt_device.timer);
-	cpu5wdt_device.timer.function = cpu5wdt_trigger;
-	cpu5wdt_device.timer.data = 0;
+	setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
 
 	cpu5wdt_device.default_ticks = ticks;
 
diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c
index e228d6e..f70387f 100644
--- a/drivers/char/watchdog/eurotechwdt.c
+++ b/drivers/char/watchdog/eurotechwdt.c
@@ -73,7 +73,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * Some symbolic names
diff --git a/drivers/char/watchdog/i6300esb.c b/drivers/char/watchdog/i6300esb.c
index fb64df4..c598250 100644
--- a/drivers/char/watchdog/i6300esb.c
+++ b/drivers/char/watchdog/i6300esb.c
@@ -91,7 +91,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * Some i6300ESB specific functions
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
index e0627d7..a62ef48 100644
--- a/drivers/char/watchdog/i8xx_tco.c
+++ b/drivers/char/watchdog/i8xx_tco.c
@@ -109,7 +109,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * Some TCO specific functions
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c
index 7eac922..3c9684c 100644
--- a/drivers/char/watchdog/iTCO_wdt.c
+++ b/drivers/char/watchdog/iTCO_wdt.c
@@ -1,7 +1,7 @@
 /*
  *	intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
  *
- *	(c) Copyright 2006 Wim Van Sebroeck <wim@iguana.be>.
+ *	(c) Copyright 2006-2007 Wim Van Sebroeck <wim@iguana.be>.
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -49,7 +49,7 @@
 /* Module and version information */
 #define DRV_NAME        "iTCO_wdt"
 #define DRV_VERSION     "1.01"
-#define DRV_RELDATE     "11-Nov-2006"
+#define DRV_RELDATE     "21-Jan-2007"
 #define PFX		DRV_NAME ": "
 
 /* Includes */
@@ -187,7 +187,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /* iTCO Vendor Specific Support hooks */
 #ifdef CONFIG_ITCO_VENDOR_SUPPORT
@@ -539,7 +539,7 @@
  *	Kernel Interfaces
  */
 
-static struct file_operations iTCO_wdt_fops = {
+static const struct file_operations iTCO_wdt_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.write =	iTCO_wdt_write,
diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c
index c1ed209..c3a60f5 100644
--- a/drivers/char/watchdog/ib700wdt.c
+++ b/drivers/char/watchdog/ib700wdt.c
@@ -3,8 +3,8 @@
  *
  *	(c) Copyright 2001 Charles Howes <chowes@vsol.net>
  *
- *      Based on advantechwdt.c which is based on acquirewdt.c which
- *       is based on wdt.c.
+ *	Based on advantechwdt.c which is based on acquirewdt.c which
+ *	is based on wdt.c.
  *
  *	(c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
  *
@@ -25,9 +25,9 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
  *
- *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
- *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- *           Added timeout module option to override default
+ *	14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *	     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *	     Added timeout module option to override default
  *
  */
 
@@ -36,22 +36,24 @@
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/ioport.h>
-#include <linux/notifier.h>
 #include <linux/fs.h>
-#include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/moduleparam.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+static struct platform_device *ibwdt_platform_device;
 static unsigned long ibwdt_is_open;
 static spinlock_t ibwdt_lock;
 static char expect_close;
 
-#define PFX "ib700wdt: "
+/* Module information */
+#define DRV_NAME "ib700wdt"
+#define PFX DRV_NAME ": "
 
 /*
  *
@@ -118,20 +120,51 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 
 /*
- *	Kernel methods.
+ *	Watchdog Operations
  */
 
 static void
 ibwdt_ping(void)
 {
+	spin_lock(&ibwdt_lock);
+
 	/* Write a watchdog value */
 	outb_p(wd_margin, WDT_START);
+
+	spin_unlock(&ibwdt_lock);
 }
 
+static void
+ibwdt_disable(void)
+{
+	spin_lock(&ibwdt_lock);
+	outb_p(0, WDT_STOP);
+	spin_unlock(&ibwdt_lock);
+}
+
+static int
+ibwdt_set_heartbeat(int t)
+{
+	int i;
+
+	if ((t < 0) || (t > 30))
+		return -EINVAL;
+
+	for (i = 0x0F; i > -1; i--)
+		if (wd_times[i] > t)
+			break;
+	wd_margin = i;
+	return 0;
+}
+
+/*
+ *	/dev/watchdog handling
+ */
+
 static ssize_t
 ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
@@ -159,7 +192,7 @@
 ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	  unsigned long arg)
 {
-	int i, new_margin;
+	int new_margin;
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
 
@@ -176,6 +209,7 @@
 	  break;
 
 	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
 	  return put_user(0, p);
 
 	case WDIOC_KEEPALIVE:
@@ -185,18 +219,33 @@
 	case WDIOC_SETTIMEOUT:
 	  if (get_user(new_margin, p))
 		  return -EFAULT;
-	  if ((new_margin < 0) || (new_margin > 30))
+	  if (ibwdt_set_heartbeat(new_margin))
 		  return -EINVAL;
-	  for (i = 0x0F; i > -1; i--)
-		  if (wd_times[i] > new_margin)
-			  break;
-	  wd_margin = i;
 	  ibwdt_ping();
 	  /* Fall */
 
 	case WDIOC_GETTIMEOUT:
 	  return put_user(wd_times[wd_margin], p);
-	  break;
+
+	case WDIOC_SETOPTIONS:
+	{
+	  int options, retval = -EINVAL;
+
+	  if (get_user(options, p))
+	    return -EFAULT;
+
+	  if (options & WDIOS_DISABLECARD) {
+	    ibwdt_disable();
+	    retval = 0;
+	  }
+
+	  if (options & WDIOS_ENABLECARD) {
+	    ibwdt_ping();
+	    retval = 0;
+	  }
+
+	  return retval;
+	}
 
 	default:
 	  return -ENOTTY;
@@ -207,9 +256,7 @@
 static int
 ibwdt_open(struct inode *inode, struct file *file)
 {
-	spin_lock(&ibwdt_lock);
 	if (test_and_set_bit(0, &ibwdt_is_open)) {
-		spin_unlock(&ibwdt_lock);
 		return -EBUSY;
 	}
 	if (nowayout)
@@ -217,41 +264,24 @@
 
 	/* Activate */
 	ibwdt_ping();
-	spin_unlock(&ibwdt_lock);
 	return nonseekable_open(inode, file);
 }
 
 static int
 ibwdt_close(struct inode *inode, struct file *file)
 {
-	spin_lock(&ibwdt_lock);
-	if (expect_close == 42)
-		outb_p(0, WDT_STOP);
-	else
+	if (expect_close == 42) {
+		ibwdt_disable();
+	} else {
 		printk(KERN_CRIT PFX "WDT device closed unexpectedly.  WDT will not stop!\n");
-
+		ibwdt_ping();
+	}
 	clear_bit(0, &ibwdt_is_open);
 	expect_close = 0;
-	spin_unlock(&ibwdt_lock);
 	return 0;
 }
 
 /*
- *	Notifier for system down
- */
-
-static int
-ibwdt_notify_sys(struct notifier_block *this, unsigned long code,
-	void *unused)
-{
-	if (code == SYS_DOWN || code == SYS_HALT) {
-		/* Turn the WDT off */
-		outb_p(0, WDT_STOP);
-	}
-	return NOTIFY_DONE;
-}
-
-/*
  *	Kernel Interfaces
  */
 
@@ -271,26 +301,14 @@
 };
 
 /*
- *	The WDT needs to learn about soft shutdowns in order to
- *	turn the timebomb registers off.
+ *	Init & exit routines
  */
 
-static struct notifier_block ibwdt_notifier = {
-	.notifier_call = ibwdt_notify_sys,
-};
-
-static int __init ibwdt_init(void)
+static int __devinit ibwdt_probe(struct platform_device *dev)
 {
 	int res;
 
-	printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n");
-
 	spin_lock_init(&ibwdt_lock);
-	res = misc_register(&ibwdt_miscdev);
-	if (res) {
-		printk (KERN_ERR PFX "failed to register misc device\n");
-		goto out_nomisc;
-	}
 
 #if WDT_START != WDT_STOP
 	if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
@@ -305,34 +323,78 @@
 		res = -EIO;
 		goto out_nostartreg;
 	}
-	res = register_reboot_notifier(&ibwdt_notifier);
+
+	res = misc_register(&ibwdt_miscdev);
 	if (res) {
-		printk (KERN_ERR PFX "Failed to register reboot notifier.\n");
-		goto out_noreboot;
+		printk (KERN_ERR PFX "failed to register misc device\n");
+		goto out_nomisc;
 	}
 	return 0;
 
-out_noreboot:
+out_nomisc:
 	release_region(WDT_START, 1);
 out_nostartreg:
 #if WDT_START != WDT_STOP
 	release_region(WDT_STOP, 1);
 #endif
 out_nostopreg:
-	misc_deregister(&ibwdt_miscdev);
-out_nomisc:
 	return res;
 }
 
-static void __exit
-ibwdt_exit(void)
+static int __devexit ibwdt_remove(struct platform_device *dev)
 {
 	misc_deregister(&ibwdt_miscdev);
-	unregister_reboot_notifier(&ibwdt_notifier);
+	release_region(WDT_START,1);
 #if WDT_START != WDT_STOP
 	release_region(WDT_STOP,1);
 #endif
-	release_region(WDT_START,1);
+	return 0;
+}
+
+static void ibwdt_shutdown(struct platform_device *dev)
+{
+	/* Turn the WDT off if we have a soft shutdown */
+	ibwdt_disable();
+}
+
+static struct platform_driver ibwdt_driver = {
+	.probe		= ibwdt_probe,
+	.remove		= __devexit_p(ibwdt_remove),
+	.shutdown	= ibwdt_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= DRV_NAME,
+	},
+};
+
+static int __init ibwdt_init(void)
+{
+	int err;
+
+	printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n");
+
+	err = platform_driver_register(&ibwdt_driver);
+	if (err)
+		return err;
+
+	ibwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+	if (IS_ERR(ibwdt_platform_device)) {
+		err = PTR_ERR(ibwdt_platform_device);
+		goto unreg_platform_driver;
+	}
+
+	return 0;
+
+unreg_platform_driver:
+	platform_driver_unregister(&ibwdt_driver);
+	return err;
+}
+
+static void __exit ibwdt_exit(void)
+{
+	platform_device_unregister(ibwdt_platform_device);
+	platform_driver_unregister(&ibwdt_driver);
+	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(ibwdt_init);
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/char/watchdog/ibmasr.c
index dd6760f..8195f50 100644
--- a/drivers/char/watchdog/ibmasr.c
+++ b/drivers/char/watchdog/ibmasr.c
@@ -396,7 +396,7 @@
 module_exit(ibmasr_exit);
 
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
 MODULE_AUTHOR("Andrey Panin");
diff --git a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c
index 0bc2393..788245b 100644
--- a/drivers/char/watchdog/indydog.c
+++ b/drivers/char/watchdog/indydog.c
@@ -32,7 +32,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 static void indydog_start(void)
 {
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
index 276577d..4a328ba 100644
--- a/drivers/char/watchdog/machzwd.c
+++ b/drivers/char/watchdog/machzwd.c
@@ -95,7 +95,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 #define PFX "machzwd"
 
@@ -118,12 +118,14 @@
 module_param(action, int, 0);
 MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*)  1 = SMI  2 = NMI  3 = SCI");
 
+static void zf_ping(unsigned long data);
+
 static int zf_action = GEN_RESET;
 static unsigned long zf_is_open;
 static char zf_expect_close;
 static spinlock_t zf_lock;
 static spinlock_t zf_port_lock;
-static struct timer_list zf_timer;
+static DEFINE_TIMER(zf_timer, zf_ping, 0, 0);
 static unsigned long next_heartbeat = 0;
 
 
@@ -220,9 +222,7 @@
 	next_heartbeat = jiffies + ZF_USER_TIMEO;
 
 	/* start the timer for internal ping */
-	zf_timer.expires = jiffies + ZF_HW_TIMEO;
-
-	add_timer(&zf_timer);
+	mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
 
 	/* start watchdog timer */
 	ctrl_reg = zf_get_control();
@@ -260,8 +260,7 @@
 		zf_set_control(ctrl_reg);
 		spin_unlock_irqrestore(&zf_port_lock, flags);
 
-		zf_timer.expires = jiffies + ZF_HW_TIMEO;
-		add_timer(&zf_timer);
+		mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
 	}else{
 		printk(KERN_CRIT PFX ": I will reset your machine\n");
 	}
@@ -465,11 +464,6 @@
 	zf_set_status(0);
 	zf_set_control(0);
 
-	/* this is the timer that will do the hard work */
-	init_timer(&zf_timer);
-	zf_timer.function = zf_ping;
-	zf_timer.data = 0;
-
 	return 0;
 
 no_reboot:
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
index c2dac0a..f35e284 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/char/watchdog/mixcomwd.c
@@ -56,16 +56,18 @@
 #define FLASHCOM_WATCHDOG_OFFSET 0x4
 #define FLASHCOM_ID 0x18
 
+static void mixcomwd_timerfun(unsigned long d);
+
 static unsigned long mixcomwd_opened; /* long req'd for setbit --RR */
 
 static int watchdog_port;
 static int mixcomwd_timer_alive;
-static DEFINE_TIMER(mixcomwd_timer, NULL, 0, 0);
+static DEFINE_TIMER(mixcomwd_timer, mixcomwd_timerfun, 0, 0);
 static char expect_close;
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 static void mixcomwd_ping(void)
 {
@@ -77,7 +79,7 @@
 {
 	mixcomwd_ping();
 
-	mod_timer(&mixcomwd_timer,jiffies+ 5*HZ);
+	mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
 }
 
 /*
@@ -114,12 +116,8 @@
 			printk(KERN_ERR "mixcomwd: release called while internal timer alive");
 			return -EBUSY;
 		}
-		init_timer(&mixcomwd_timer);
-		mixcomwd_timer.expires=jiffies + 5 * HZ;
-		mixcomwd_timer.function=mixcomwd_timerfun;
-		mixcomwd_timer.data=0;
 		mixcomwd_timer_alive=1;
-		add_timer(&mixcomwd_timer);
+		mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
 	} else {
 		printk(KERN_CRIT "mixcomwd: WDT device closed unexpectedly.  WDT will not stop!\n");
 	}
@@ -285,7 +283,7 @@
 		if(mixcomwd_timer_alive) {
 			printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
 			       " probably reboot!\n");
-			del_timer(&mixcomwd_timer);
+			del_timer_sync(&mixcomwd_timer);
 			mixcomwd_timer_alive=0;
 		}
 	}
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c
index 6c6f973..84074a6 100644
--- a/drivers/char/watchdog/omap_wdt.c
+++ b/drivers/char/watchdog/omap_wdt.c
@@ -230,7 +230,7 @@
 	}
 }
 
-static struct file_operations omap_wdt_fops = {
+static const struct file_operations omap_wdt_fops = {
 	.owner = THIS_MODULE,
 	.write = omap_wdt_write,
 	.ioctl = omap_wdt_ioctl,
diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c
index 1d447e32..3d3deae 100644
--- a/drivers/char/watchdog/pc87413_wdt.c
+++ b/drivers/char/watchdog/pc87413_wdt.c
@@ -526,7 +526,7 @@
 
 /* -- Module's structures ---------------------------------------*/
 
-static struct file_operations pc87413_fops = {
+static const struct file_operations pc87413_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.write		= pc87413_write,
@@ -631,5 +631,5 @@
 MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes (default=" __MODULE_STRING(timeout) ").");
 
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 8e1e6e4..6e8b570 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -2,7 +2,7 @@
  * PC Watchdog Driver
  * by Ken Hollis (khollis@bitgate.com)
  *
- * Permission granted from Simon Machell (73244.1270@compuserve.com)
+ * Permission granted from Simon Machell (smachell@berkprod.com)
  * Written for the Linux Kernel, and GPLed by Ken Hollis
  *
  * 960107	Added request_region routines, modulized the whole thing.
@@ -70,8 +70,8 @@
 #include <asm/io.h>		/* For inb/outb/... */
 
 /* Module and version information */
-#define WATCHDOG_VERSION "1.17"
-#define WATCHDOG_DATE "12 Feb 2006"
+#define WATCHDOG_VERSION "1.18"
+#define WATCHDOG_DATE "21 Jan 2007"
 #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
 #define WATCHDOG_NAME "pcwd"
 #define PFX WATCHDOG_NAME ": "
@@ -132,6 +132,18 @@
 #define CMD_ISA_DELAY_TIME_8SECS	0x0C
 #define CMD_ISA_RESET_RELAYS		0x0D
 
+/* Watchdog's Dip Switch heartbeat values */
+static const int heartbeat_tbl [] = {
+	20,	/* OFF-OFF-OFF	= 20 Sec  */
+	40,	/* OFF-OFF-ON	= 40 Sec  */
+	60,	/* OFF-ON-OFF	=  1 Min  */
+	300,	/* OFF-ON-ON	=  5 Min  */
+	600,	/* ON-OFF-OFF	= 10 Min  */
+	1800,	/* ON-OFF-ON	= 30 Min  */
+	3600,	/* ON-ON-OFF	=  1 Hour */
+	7200,	/* ON-ON-ON	=  2 hour */
+};
+
 /*
  * We are using an kernel timer to do the pinging of the watchdog
  * every ~500ms. We try to set the internal heartbeat of the
@@ -167,14 +179,14 @@
 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 */
+#define WATCHDOG_HEARTBEAT 0		/* default heartbeat = delay-time from dip-switches */
 static int heartbeat = WATCHDOG_HEARTBEAT;
 module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *	Internal functions
@@ -831,9 +843,7 @@
 	/* clear the "card caused reboot" flag */
 	pcwd_clear_status();
 
-	init_timer(&pcwd_private.timer);
-	pcwd_private.timer.function = pcwd_timer_ping;
-	pcwd_private.timer.data = 0;
+	setup_timer(&pcwd_private.timer, pcwd_timer_ping, 0);
 
 	/*  Disable the board  */
 	pcwd_stop();
@@ -844,6 +854,10 @@
 	/* Show info about the card itself */
 	pcwd_show_card_info();
 
+	/* If heartbeat = 0 then we use the heartbeat from the dip-switches */
+	if (heartbeat == 0)
+		heartbeat = heartbeat_tbl[(pcwd_get_option_switches() & 0x07)];
+
 	/* Check that the heartbeat value is within it's range ; if not reset to the default */
 	if (pcwd_set_heartbeat(heartbeat)) {
 		pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index f4872c8..61a89e9 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -1,7 +1,7 @@
 /*
  *	Berkshire PCI-PC Watchdog Card Driver
  *
- *	(c) Copyright 2003-2005 Wim Van Sebroeck <wim@iguana.be>.
+ *	(c) Copyright 2003-2007 Wim Van Sebroeck <wim@iguana.be>.
  *
  *	Based on source code of the following authors:
  *	  Ken Hollis <kenji@bitgate.com>,
@@ -51,8 +51,8 @@
 #include <asm/io.h>		/* For inb/outb/... */
 
 /* Module and version information */
-#define WATCHDOG_VERSION "1.02"
-#define WATCHDOG_DATE "03 Sep 2005"
+#define WATCHDOG_VERSION "1.03"
+#define WATCHDOG_DATE "21 Jan 2007"
 #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
 #define WATCHDOG_NAME "pcwd_pci"
 #define PFX WATCHDOG_NAME ": "
@@ -96,6 +96,18 @@
 #define CMD_WRITE_WATCHDOG_TIMEOUT		0x19
 #define CMD_GET_CLEAR_RESET_COUNT		0x84
 
+/* Watchdog's Dip Switch heartbeat values */
+static const int heartbeat_tbl [] = {
+	5,	/* OFF-OFF-OFF	=  5 Sec  */
+	10,	/* OFF-OFF-ON	= 10 Sec  */
+	30,	/* OFF-ON-OFF	= 30 Sec  */
+	60,	/* OFF-ON-ON	=  1 Min  */
+	300,	/* ON-OFF-OFF	=  5 Min  */
+	600,	/* ON-OFF-ON	= 10 Min  */
+	1800,	/* ON-ON-OFF	= 30 Min  */
+	3600,	/* ON-ON-ON	=  1 hour */
+};
+
 /* We can only use 1 card due to the /dev/watchdog restriction */
 static int cards_found;
 
@@ -119,14 +131,14 @@
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
 
-#define WATCHDOG_HEARTBEAT 2	/* 2 sec default heartbeat */
+#define WATCHDOG_HEARTBEAT 0	/* default heartbeat = delay-time from dip-switches */
 static int heartbeat = WATCHDOG_HEARTBEAT;
 module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *	Internal functions
@@ -286,7 +298,9 @@
 static int pcipcwd_keepalive(void)
 {
 	/* Re-trigger watchdog by writing to port 0 */
+	spin_lock(&pcipcwd_private.io_lock);
 	outb_p(0x42, pcipcwd_private.io_addr);	/* send out any data */
+	spin_unlock(&pcipcwd_private.io_lock);
 
 	if (debug >= DEBUG)
 		printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
@@ -373,7 +387,9 @@
 	if (!pcipcwd_private.supports_temp)
 		return -ENODEV;
 
+	spin_lock(&pcipcwd_private.io_lock);
 	*temperature = inb_p(pcipcwd_private.io_addr);
+	spin_unlock(&pcipcwd_private.io_lock);
 
 	/*
 	 * Convert celsius to fahrenheit, since this was
@@ -711,6 +727,10 @@
 	/* Show info about the card itself */
 	pcipcwd_show_card_info();
 
+	/* If heartbeat = 0 then we use the heartbeat from the dip-switches */
+	if (heartbeat == 0)
+		heartbeat = heartbeat_tbl[(pcipcwd_get_option_switches() & 0x07)];
+
 	/* Check that the heartbeat value is within it's range ; if not reset to the default */
 	if (pcipcwd_set_heartbeat(heartbeat)) {
 		pcipcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
@@ -798,6 +818,8 @@
 static void __exit pcipcwd_cleanup_module(void)
 {
 	pci_unregister_driver(&pcipcwd_driver);
+
+	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(pcipcwd_init_module);
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 2da5ac9..31037f9 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -1,7 +1,7 @@
 /*
  *	Berkshire USB-PC Watchdog Card Driver
  *
- *	(c) Copyright 2004 Wim Van Sebroeck <wim@iguana.be>.
+ *	(c) Copyright 2004-2007 Wim Van Sebroeck <wim@iguana.be>.
  *
  *	Based on source code of the following authors:
  *	  Ken Hollis <kenji@bitgate.com>,
@@ -24,26 +24,25 @@
  *	http://www.berkprod.com/ or http://www.pcwatchdog.com/
  */
 
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/fs.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <asm/uaccess.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
+#include <linux/module.h>	/* For module specific items */
+#include <linux/moduleparam.h>	/* For new moduleparam's */
+#include <linux/types.h>	/* For standard types (like size_t) */
+#include <linux/errno.h>	/* For the -ENODEV/... values */
+#include <linux/kernel.h>	/* For printk/panic/... */
+#include <linux/delay.h>	/* For mdelay function */
+#include <linux/miscdevice.h>	/* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>	/* For the watchdog specific items */
+#include <linux/notifier.h>	/* For notifier support */
+#include <linux/reboot.h>	/* For reboot_notifier stuff */
+#include <linux/init.h>		/* For __init/__exit/... */
+#include <linux/fs.h>		/* For file operations */
+#include <linux/usb.h>		/* For USB functions */
+#include <linux/slab.h>		/* For kmalloc, ... */
+#include <linux/mutex.h>	/* For mutex locking */
 #include <linux/hid.h>		/* For HID_REQ_SET_REPORT & HID_DT_REPORT */
 
+#include <asm/uaccess.h>	/* For copy_to_user/put_user/... */
+
 
 #ifdef CONFIG_USB_DEBUG
 	static int debug = 1;
@@ -57,8 +56,8 @@
 
 
 /* Module and Version Information */
-#define DRIVER_VERSION "1.01"
-#define DRIVER_DATE "15 Mar 2005"
+#define DRIVER_VERSION "1.02"
+#define DRIVER_DATE "21 Jan 2007"
 #define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>"
 #define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
 #define DRIVER_LICENSE "GPL"
@@ -75,14 +74,14 @@
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 
-#define WATCHDOG_HEARTBEAT 2	/* 2 sec default heartbeat */
+#define WATCHDOG_HEARTBEAT 0	/* default heartbeat = delay-time from dip-switches */
 static int heartbeat = WATCHDOG_HEARTBEAT;
 module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /* The vendor and product id's for the USB-PC Watchdog card */
 #define USB_PCWD_VENDOR_ID	0x0c98
@@ -110,6 +109,18 @@
 #define CMD_ENABLE_WATCHDOG		0x30	/* Enable / Disable Watchdog */
 #define CMD_DISABLE_WATCHDOG		CMD_ENABLE_WATCHDOG
 
+/* Watchdog's Dip Switch heartbeat values */
+static const int heartbeat_tbl [] = {
+	5,	/* OFF-OFF-OFF	=  5 Sec  */
+	10,	/* OFF-OFF-ON	= 10 Sec  */
+	30,	/* OFF-ON-OFF	= 30 Sec  */
+	60,	/* OFF-ON-ON	=  1 Min  */
+	300,	/* ON-OFF-OFF	=  5 Min  */
+	600,	/* ON-OFF-ON	= 10 Min  */
+	1800,	/* ON-ON-OFF	= 30 Min  */
+	3600,	/* ON-ON-ON	=  1 hour */
+};
+
 /* We can only use 1 card due to the /dev/watchdog restriction */
 static int cards_found;
 
@@ -682,6 +693,10 @@
 		((option_switches & 0x10) ? "ON" : "OFF"),
 		((option_switches & 0x08) ? "ON" : "OFF"));
 
+	/* If heartbeat = 0 then we use the heartbeat from the dip-switches */
+	if (heartbeat == 0)
+		heartbeat = heartbeat_tbl[(option_switches & 0x07)];
+
 	/* Check that the heartbeat value is within it's range ; if not reset to the default */
 	if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {
 		usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);
diff --git a/drivers/char/watchdog/pnx4008_wdt.c b/drivers/char/watchdog/pnx4008_wdt.c
index 3a55fc6..5991add 100644
--- a/drivers/char/watchdog/pnx4008_wdt.c
+++ b/drivers/char/watchdog/pnx4008_wdt.c
@@ -238,7 +238,7 @@
 	return 0;
 }
 
-static struct file_operations pnx4008_wdt_fops = {
+static const struct file_operations pnx4008_wdt_fops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 	.write = pnx4008_wdt_write,
@@ -283,7 +283,8 @@
 	wdt_base = (void __iomem *)IO_ADDRESS(res->start);
 
 	wdt_clk = clk_get(&pdev->dev, "wdt_ck");
-	if (!wdt_clk) {
+	if (IS_ERR(wdt_clk)) {
+		ret = PTR_ERR(wdt_clk);
 		release_resource(wdt_mem);
 		kfree(wdt_mem);
 		goto out;
diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c
index 7576a13..5c921e4 100644
--- a/drivers/char/watchdog/rm9k_wdt.c
+++ b/drivers/char/watchdog/rm9k_wdt.c
@@ -95,7 +95,7 @@
 
 
 /* Kernel interfaces */
-static struct file_operations fops = {
+static const struct file_operations fops = {
 	.owner		= THIS_MODULE,
 	.open		= wdt_gpi_open,
 	.release	= wdt_gpi_release,
@@ -192,7 +192,7 @@
 		locked = 0;
 	}
 
-	res = request_irq(wd_irq, wdt_gpi_irqhdl, SA_SHIRQ | SA_INTERRUPT,
+	res = request_irq(wd_irq, wdt_gpi_irqhdl, IRQF_SHARED | IRQF_DISABLED,
 			  wdt_gpi_name, &miscdev);
 	if (unlikely(res))
 		return res;
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 18cb050..dff6cb5 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -78,7 +78,7 @@
 
 MODULE_PARM_DESC(tmr_atboot, "Watchdog is started at boot time if set to 1, default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT));
 
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)");
 
@@ -366,13 +366,15 @@
 	wdt_mem = request_mem_region(res->start, size, pdev->name);
 	if (wdt_mem == NULL) {
 		printk(KERN_INFO PFX "failed to get memory region\n");
-		return -ENOENT;
+		ret = -ENOENT;
+		goto err_req;
 	}
 
 	wdt_base = ioremap(res->start, size);
 	if (wdt_base == 0) {
 		printk(KERN_INFO PFX "failed to ioremap() region\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_req;
 	}
 
 	DBG("probe: mapped wdt_base=%p\n", wdt_base);
@@ -380,22 +382,21 @@
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (res == NULL) {
 		printk(KERN_INFO PFX "failed to get irq resource\n");
-		iounmap(wdt_base);
-		return -ENOENT;
+		ret = -ENOENT;
+		goto err_map;
 	}
 
 	ret = request_irq(res->start, s3c2410wdt_irq, 0, pdev->name, pdev);
 	if (ret != 0) {
 		printk(KERN_INFO PFX "failed to install irq (%d)\n", ret);
-		iounmap(wdt_base);
-		return ret;
+		goto err_map;
 	}
 
 	wdt_clock = clk_get(&pdev->dev, "watchdog");
-	if (wdt_clock == NULL) {
+	if (IS_ERR(wdt_clock)) {
 		printk(KERN_INFO PFX "failed to find watchdog clock source\n");
-		iounmap(wdt_base);
-		return -ENOENT;
+		ret = PTR_ERR(wdt_clock);
+		goto err_irq;
 	}
 
 	clk_enable(wdt_clock);
@@ -418,8 +419,7 @@
 	if (ret) {
 		printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n",
 			WATCHDOG_MINOR, ret);
-		iounmap(wdt_base);
-		return ret;
+		goto err_clk;
 	}
 
 	if (tmr_atboot && started == 0) {
@@ -434,26 +434,36 @@
 	}
 
 	return 0;
+
+ err_clk:
+	clk_disable(wdt_clock);
+	clk_put(wdt_clock);
+
+ err_irq:
+	free_irq(wdt_irq->start, pdev);
+
+ err_map:
+	iounmap(wdt_base);
+
+ err_req:
+	release_resource(wdt_mem);
+	kfree(wdt_mem);
+
+	return ret;
 }
 
 static int s3c2410wdt_remove(struct platform_device *dev)
 {
-	if (wdt_mem != NULL) {
-		release_resource(wdt_mem);
-		kfree(wdt_mem);
-		wdt_mem = NULL;
-	}
+	release_resource(wdt_mem);
+	kfree(wdt_mem);
+	wdt_mem = NULL;
 
-	if (wdt_irq != NULL) {
-		free_irq(wdt_irq->start, dev);
-		wdt_irq = NULL;
-	}
+	free_irq(wdt_irq->start, dev);
+	wdt_irq = NULL;
 
-	if (wdt_clock != NULL) {
-		clk_disable(wdt_clock);
-		clk_put(wdt_clock);
-		wdt_clock = NULL;
-	}
+	clk_disable(wdt_clock);
+	clk_put(wdt_clock);
+	wdt_clock = NULL;
 
 	iounmap(wdt_base);
 	misc_deregister(&s3c2410wdt_miscdev);
diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c
index c7b2045..b628203 100644
--- a/drivers/char/watchdog/sbc60xxwdt.c
+++ b/drivers/char/watchdog/sbc60xxwdt.c
@@ -100,10 +100,10 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
 static unsigned long next_heartbeat;
 static unsigned long wdt_is_open;
 static char wdt_expect_close;
@@ -122,8 +122,7 @@
 		/* Ping the WDT by reading from wdt_start */
 		inb_p(wdt_start);
 		/* Re-set the timer interval */
-		timer.expires = jiffies + WDT_INTERVAL;
-		add_timer(&timer);
+		mod_timer(&timer, jiffies + WDT_INTERVAL);
 	} else {
 		printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
 	}
@@ -138,8 +137,7 @@
 	next_heartbeat = jiffies + (timeout * HZ);
 
 	/* Start the timer */
-	timer.expires = jiffies + WDT_INTERVAL;
-	add_timer(&timer);
+	mod_timer(&timer, jiffies + WDT_INTERVAL);
 	printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
 }
 
@@ -363,10 +361,6 @@
 		}
 	}
 
-	init_timer(&timer);
-	timer.function = wdt_timer_ping;
-	timer.data = 0;
-
 	rc = misc_register(&wdt_miscdev);
 	if (rc)
 	{
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c
index 41fc6f8..67ae426 100644
--- a/drivers/char/watchdog/sbc8360.c
+++ b/drivers/char/watchdog/sbc8360.c
@@ -204,7 +204,7 @@
 MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout,
-		 "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+		 "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *	Kernel methods.
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c
index 8882b42..82cbd88 100644
--- a/drivers/char/watchdog/sbc_epx_c3.c
+++ b/drivers/char/watchdog/sbc_epx_c3.c
@@ -35,7 +35,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 #define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */
 #define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
index e323983..1e4a8d7 100644
--- a/drivers/char/watchdog/sc1200wdt.c
+++ b/drivers/char/watchdog/sc1200wdt.c
@@ -92,7 +92,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 
 
diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c
index caec37b..2676a43 100644
--- a/drivers/char/watchdog/sc520_wdt.c
+++ b/drivers/char/watchdog/sc520_wdt.c
@@ -97,7 +97,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * AMD Elan SC520 - Watchdog Timer Registers
@@ -121,7 +121,7 @@
 static __u16 __iomem *wdtmrctl;
 
 static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
 static unsigned long next_heartbeat;
 static unsigned long wdt_is_open;
 static char wdt_expect_close;
@@ -145,8 +145,7 @@
 		spin_unlock(&wdt_spinlock);
 
 		/* Re-set the timer interval */
-		timer.expires = jiffies + WDT_INTERVAL;
-		add_timer(&timer);
+		mod_timer(&timer, jiffies + WDT_INTERVAL);
 	} else {
 		printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
 	}
@@ -179,8 +178,7 @@
 	next_heartbeat = jiffies + (timeout * HZ);
 
 	/* Start the timer */
-	timer.expires = jiffies + WDT_INTERVAL;
-	add_timer(&timer);
+	mod_timer(&timer, jiffies + WDT_INTERVAL);
 
 	/* Start the watchdog */
 	wdt_config(WDT_ENB | WDT_WRST_ENB | WDT_EXP_SEL_04);
@@ -389,10 +387,6 @@
 
 	spin_lock_init(&wdt_spinlock);
 
-	init_timer(&timer);
-	timer.function = wdt_timer_ping;
-	timer.data = 0;
-
 	/* Check that the timeout value is within it's range ; if not reset to the default */
 	if (wdt_set_heartbeat(timeout)) {
 		wdt_set_heartbeat(WATCHDOG_TIMEOUT);
diff --git a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c
index dc40362..cecbedd 100644
--- a/drivers/char/watchdog/shwdt.c
+++ b/drivers/char/watchdog/shwdt.c
@@ -65,10 +65,12 @@
 
 #define next_ping_period(cks)	msecs_to_jiffies(cks - 4)
 
+static void sh_wdt_ping(unsigned long data);
+
 static unsigned long shwdt_is_open;
 static struct watchdog_info sh_wdt_info;
 static char shwdt_expect_close;
-static struct timer_list timer;
+static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0);
 static unsigned long next_heartbeat;
 
 #define WATCHDOG_HEARTBEAT 30			/* 30 sec default heartbeat */
@@ -433,10 +435,6 @@
 		       "be 1<=x<=3600, using %d\n", heartbeat);
 	}
 
-	init_timer(&timer);
-	timer.function = sh_wdt_ping;
-	timer.data = 0;
-
 	rc = register_reboot_notifier(&sh_wdt_notifier);
 	if (unlikely(rc)) {
 		printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n",
diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c
index 9f56913..d3cb0a7 100644
--- a/drivers/char/watchdog/smsc37b787_wdt.c
+++ b/drivers/char/watchdog/smsc37b787_wdt.c
@@ -510,7 +510,7 @@
 
 /* -- Module's structures ---------------------------------------*/
 
-static struct file_operations wb_smsc_wdt_fops =
+static const struct file_operations wb_smsc_wdt_fops =
 {
 	.owner          = THIS_MODULE,
 	.llseek		= no_llseek,
@@ -624,4 +624,4 @@
 MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60");
 
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c
index 4067e1f..9c36949 100644
--- a/drivers/char/watchdog/softdog.c
+++ b/drivers/char/watchdog/softdog.c
@@ -59,7 +59,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 #ifdef ONLY_TESTING
 static int soft_noboot = 1;
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c
index 07d4bff..337ee42 100644
--- a/drivers/char/watchdog/w83627hf_wdt.c
+++ b/drivers/char/watchdog/w83627hf_wdt.c
@@ -58,7 +58,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *	Kernel methods.
diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c
index 7768b55..d9e821d 100644
--- a/drivers/char/watchdog/w83697hf_wdt.c
+++ b/drivers/char/watchdog/w83697hf_wdt.c
@@ -60,7 +60,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  *	Kernel methods.
@@ -323,7 +323,7 @@
  *	Kernel Interfaces
  */
 
-static struct file_operations wdt_fops = {
+static const struct file_operations wdt_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.write		= wdt_write,
diff --git a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c
index b0e5f84..3c88fe1 100644
--- a/drivers/char/watchdog/w83877f_wdt.c
+++ b/drivers/char/watchdog/w83877f_wdt.c
@@ -87,10 +87,10 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
 static unsigned long next_heartbeat;
 static unsigned long wdt_is_open;
 static char wdt_expect_close;
@@ -114,8 +114,7 @@
 		inb_p(WDT_PING);
 
 		/* Re-set the timer interval */
-		timer.expires = jiffies + WDT_INTERVAL;
-		add_timer(&timer);
+		mod_timer(&timer, jiffies + WDT_INTERVAL);
 
 		spin_unlock(&wdt_spinlock);
 
@@ -155,8 +154,7 @@
 	next_heartbeat = jiffies + (timeout * HZ);
 
 	/* Start the timer */
-	timer.expires = jiffies + WDT_INTERVAL;
-	add_timer(&timer);
+	mod_timer(&timer, jiffies + WDT_INTERVAL);
 
 	wdt_change(WDT_ENABLE);
 
@@ -377,10 +375,6 @@
 		goto err_out_region1;
 	}
 
-	init_timer(&timer);
-	timer.function = wdt_timer_ping;
-	timer.data = 0;
-
 	rc = misc_register(&wdt_miscdev);
 	if (rc)
 	{
diff --git a/drivers/char/watchdog/w83977f_wdt.c b/drivers/char/watchdog/w83977f_wdt.c
index 2c8d5d8..1579684 100644
--- a/drivers/char/watchdog/w83977f_wdt.c
+++ b/drivers/char/watchdog/w83977f_wdt.c
@@ -59,7 +59,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * Start the watchdog
diff --git a/drivers/char/watchdog/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c
index 163e028..950905d 100644
--- a/drivers/char/watchdog/wafer5823wdt.c
+++ b/drivers/char/watchdog/wafer5823wdt.c
@@ -65,7 +65,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 static void wafwdt_ping(void)
 {
diff --git a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c
index 517fbd8..0a3de6a 100644
--- a/drivers/char/watchdog/wdt.c
+++ b/drivers/char/watchdog/wdt.c
@@ -64,7 +64,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /* You must set these - there is no sane way to probe for this board. */
 static int io=0x240;
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
index 6253041..7d300ff 100644
--- a/drivers/char/watchdog/wdt977.c
+++ b/drivers/char/watchdog/wdt977.c
@@ -68,7 +68,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 /*
  * Start the watchdog
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
index ce1261c..6baf4ae 100644
--- a/drivers/char/watchdog/wdt_pci.c
+++ b/drivers/char/watchdog/wdt_pci.c
@@ -90,7 +90,7 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 #ifdef CONFIG_WDT_501_PCI
 /* Support for the Fan Tachometer on the PCI-WDT501 */
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index b6bcdbb..ccaa6a3 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -16,15 +16,13 @@
  * This file is licensed under the GPL v2.
  */
 
+#include <linux/acpi_pmtmr.h>
 #include <linux/clocksource.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <asm/io.h>
 
-/* Number of PMTMR ticks expected during calibration run */
-#define PMTMR_TICKS_PER_SEC 3579545
-
 /*
  * The I/O port the PMTMR resides at.
  * The location is detected during setup_arch(),
@@ -32,15 +30,13 @@
  */
 u32 pmtmr_ioport __read_mostly;
 
-#define ACPI_PM_MASK CLOCKSOURCE_MASK(24) /* limit it to 24 bits */
-
 static inline u32 read_pmtmr(void)
 {
 	/* mask the output to 24 bits */
 	return inl(pmtmr_ioport) & ACPI_PM_MASK;
 }
 
-static cycle_t acpi_pm_read_verified(void)
+u32 acpi_pm_read_verified(void)
 {
 	u32 v1 = 0, v2 = 0, v3 = 0;
 
@@ -57,7 +53,12 @@
 	} while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
 			  || (v3 > v1 && v3 < v2)));
 
-	return (cycle_t)v2;
+	return v2;
+}
+
+static cycle_t acpi_pm_read_slow(void)
+{
+	return (cycle_t)acpi_pm_read_verified();
 }
 
 static cycle_t acpi_pm_read(void)
@@ -72,7 +73,8 @@
 	.mask		= (cycle_t)ACPI_PM_MASK,
 	.mult		= 0, /*to be caluclated*/
 	.shift		= 22,
-	.is_continuous	= 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+
 };
 
 
@@ -87,7 +89,7 @@
 
 static inline void acpi_pm_need_workaround(void)
 {
-	clocksource_acpi_pm.read = acpi_pm_read_verified;
+	clocksource_acpi_pm.read = acpi_pm_read_slow;
 	clocksource_acpi_pm.rating = 110;
 }
 
diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c
index bf4d3d5..4f3925c 100644
--- a/drivers/clocksource/cyclone.c
+++ b/drivers/clocksource/cyclone.c
@@ -31,7 +31,7 @@
 	.mask		= CYCLONE_TIMER_MASK,
 	.mult		= 10,
 	.shift		= 0,
-	.is_continuous	= 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init init_cyclone_clocksource(void)
diff --git a/drivers/clocksource/scx200_hrt.c b/drivers/clocksource/scx200_hrt.c
index 22915cc..b92da67 100644
--- a/drivers/clocksource/scx200_hrt.c
+++ b/drivers/clocksource/scx200_hrt.c
@@ -57,7 +57,7 @@
 	.rating		= 250,
 	.read		= read_hrt,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.is_continuous	= 1,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 	/* mult, shift are set based on mhz27 flag */
 };
 
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 491779a..d155e81 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -16,7 +16,7 @@
 if CPU_FREQ
 
 config CPU_FREQ_TABLE
-       def_tristate m
+       tristate
 
 config CPU_FREQ_DEBUG
 	bool "Enable CPUfreq debugging"
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a45cc89..f52facc 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -41,8 +41,67 @@
 static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
 static DEFINE_SPINLOCK(cpufreq_driver_lock);
 
+/*
+ * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
+ * all cpufreq/hotplug/workqueue/etc related lock issues.
+ *
+ * The rules for this semaphore:
+ * - Any routine that wants to read from the policy structure will
+ *   do a down_read on this semaphore.
+ * - Any routine that will write to the policy structure and/or may take away
+ *   the policy altogether (eg. CPU hotplug), will hold this lock in write
+ *   mode before doing so.
+ *
+ * Additional rules:
+ * - All holders of the lock should check to make sure that the CPU they
+ *   are concerned with are online after they get the lock.
+ * - Governor routines that can be called in cpufreq hotplug path should not
+ *   take this sem as top level hotplug notifier handler takes this.
+ */
+static DEFINE_PER_CPU(int, policy_cpu);
+static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem);
+
+#define lock_policy_rwsem(mode, cpu)					\
+int lock_policy_rwsem_##mode						\
+(int cpu)								\
+{									\
+	int policy_cpu = per_cpu(policy_cpu, cpu);			\
+	BUG_ON(policy_cpu == -1);					\
+	down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));		\
+	if (unlikely(!cpu_online(cpu))) {				\
+		up_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));	\
+		return -1;						\
+	}								\
+									\
+	return 0;							\
+}
+
+lock_policy_rwsem(read, cpu);
+EXPORT_SYMBOL_GPL(lock_policy_rwsem_read);
+
+lock_policy_rwsem(write, cpu);
+EXPORT_SYMBOL_GPL(lock_policy_rwsem_write);
+
+void unlock_policy_rwsem_read(int cpu)
+{
+	int policy_cpu = per_cpu(policy_cpu, cpu);
+	BUG_ON(policy_cpu == -1);
+	up_read(&per_cpu(cpu_policy_rwsem, policy_cpu));
+}
+EXPORT_SYMBOL_GPL(unlock_policy_rwsem_read);
+
+void unlock_policy_rwsem_write(int cpu)
+{
+	int policy_cpu = per_cpu(policy_cpu, cpu);
+	BUG_ON(policy_cpu == -1);
+	up_write(&per_cpu(cpu_policy_rwsem, policy_cpu));
+}
+EXPORT_SYMBOL_GPL(unlock_policy_rwsem_write);
+
+
 /* internal prototypes */
 static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
+static unsigned int __cpufreq_get(unsigned int cpu);
 static void handle_update(struct work_struct *work);
 
 /**
@@ -415,12 +474,8 @@
 	if (ret != 1)							\
 		return -EINVAL;						\
 									\
-	lock_cpu_hotplug();						\
-	mutex_lock(&policy->lock);					\
 	ret = __cpufreq_set_policy(policy, &new_policy);		\
 	policy->user_policy.object = policy->object;			\
-	mutex_unlock(&policy->lock);					\
-	unlock_cpu_hotplug();						\
 									\
 	return ret ? ret : count;					\
 }
@@ -434,7 +489,7 @@
 static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy,
 							char *buf)
 {
-	unsigned int cur_freq = cpufreq_get(policy->cpu);
+	unsigned int cur_freq = __cpufreq_get(policy->cpu);
 	if (!cur_freq)
 		return sprintf(buf, "<unknown>");
 	return sprintf(buf, "%u\n", cur_freq);
@@ -479,18 +534,12 @@
 						&new_policy.governor))
 		return -EINVAL;
 
-	lock_cpu_hotplug();
-
 	/* 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);
-
-	unlock_cpu_hotplug();
 
 	if (ret)
 		return ret;
@@ -595,11 +644,17 @@
 	policy = cpufreq_cpu_get(policy->cpu);
 	if (!policy)
 		return -EINVAL;
+
+	if (lock_policy_rwsem_read(policy->cpu) < 0)
+		return -EINVAL;
+
 	if (fattr->show)
 		ret = fattr->show(policy, buf);
 	else
 		ret = -EIO;
 
+	unlock_policy_rwsem_read(policy->cpu);
+
 	cpufreq_cpu_put(policy);
 	return ret;
 }
@@ -613,11 +668,17 @@
 	policy = cpufreq_cpu_get(policy->cpu);
 	if (!policy)
 		return -EINVAL;
+
+	if (lock_policy_rwsem_write(policy->cpu) < 0)
+		return -EINVAL;
+
 	if (fattr->store)
 		ret = fattr->store(policy, buf, count);
 	else
 		ret = -EIO;
 
+	unlock_policy_rwsem_write(policy->cpu);
+
 	cpufreq_cpu_put(policy);
 	return ret;
 }
@@ -691,8 +752,10 @@
 	policy->cpu = cpu;
 	policy->cpus = cpumask_of_cpu(cpu);
 
-	mutex_init(&policy->lock);
-	mutex_lock(&policy->lock);
+	/* Initially set CPU itself as the policy_cpu */
+	per_cpu(policy_cpu, cpu) = cpu;
+	lock_policy_rwsem_write(cpu);
+
 	init_completion(&policy->kobj_unregister);
 	INIT_WORK(&policy->update, handle_update);
 
@@ -702,7 +765,7 @@
 	ret = cpufreq_driver->init(policy);
 	if (ret) {
 		dprintk("initialization failed\n");
-		mutex_unlock(&policy->lock);
+		unlock_policy_rwsem_write(cpu);
 		goto err_out;
 	}
 
@@ -716,6 +779,14 @@
 		 */
 		managed_policy = cpufreq_cpu_get(j);
 		if (unlikely(managed_policy)) {
+
+			/* Set proper policy_cpu */
+			unlock_policy_rwsem_write(cpu);
+			per_cpu(policy_cpu, cpu) = managed_policy->cpu;
+
+			if (lock_policy_rwsem_write(cpu) < 0)
+				goto err_out_driver_exit;
+
 			spin_lock_irqsave(&cpufreq_driver_lock, flags);
 			managed_policy->cpus = policy->cpus;
 			cpufreq_cpu_data[cpu] = managed_policy;
@@ -726,13 +797,13 @@
 						&managed_policy->kobj,
 						"cpufreq");
 			if (ret) {
-				mutex_unlock(&policy->lock);
+				unlock_policy_rwsem_write(cpu);
 				goto err_out_driver_exit;
 			}
 
 			cpufreq_debug_enable_ratelimit();
-			mutex_unlock(&policy->lock);
 			ret = 0;
+			unlock_policy_rwsem_write(cpu);
 			goto err_out_driver_exit; /* call driver->exit() */
 		}
 	}
@@ -746,7 +817,7 @@
 
 	ret = kobject_register(&policy->kobj);
 	if (ret) {
-		mutex_unlock(&policy->lock);
+		unlock_policy_rwsem_write(cpu);
 		goto err_out_driver_exit;
 	}
 	/* set up files for this cpu device */
@@ -761,8 +832,10 @@
 		sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
 
 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
-	for_each_cpu_mask(j, policy->cpus)
+	for_each_cpu_mask(j, policy->cpus) {
 		cpufreq_cpu_data[j] = policy;
+		per_cpu(policy_cpu, j) = policy->cpu;
+	}
 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 	/* symlink affected CPUs */
@@ -778,14 +851,14 @@
 		ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
 					"cpufreq");
 		if (ret) {
-			mutex_unlock(&policy->lock);
+			unlock_policy_rwsem_write(cpu);
 			goto err_out_unregister;
 		}
 	}
 
 	policy->governor = NULL; /* to assure that the starting sequence is
 				  * run in cpufreq_set_policy */
-	mutex_unlock(&policy->lock);
+	unlock_policy_rwsem_write(cpu);
 
 	/* set default policy */
 	ret = cpufreq_set_policy(&new_policy);
@@ -826,11 +899,13 @@
 
 
 /**
- * cpufreq_remove_dev - remove a CPU device
+ * __cpufreq_remove_dev - remove a CPU device
  *
  * Removes the cpufreq interface for a CPU device.
+ * Caller should already have policy_rwsem in write mode for this CPU.
+ * This routine frees the rwsem before returning.
  */
-static int cpufreq_remove_dev (struct sys_device * sys_dev)
+static int __cpufreq_remove_dev (struct sys_device * sys_dev)
 {
 	unsigned int cpu = sys_dev->id;
 	unsigned long flags;
@@ -849,6 +924,7 @@
 	if (!data) {
 		spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 		cpufreq_debug_enable_ratelimit();
+		unlock_policy_rwsem_write(cpu);
 		return -EINVAL;
 	}
 	cpufreq_cpu_data[cpu] = NULL;
@@ -865,6 +941,7 @@
 		sysfs_remove_link(&sys_dev->kobj, "cpufreq");
 		cpufreq_cpu_put(data);
 		cpufreq_debug_enable_ratelimit();
+		unlock_policy_rwsem_write(cpu);
 		return 0;
 	}
 #endif
@@ -873,6 +950,7 @@
 	if (!kobject_get(&data->kobj)) {
 		spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 		cpufreq_debug_enable_ratelimit();
+		unlock_policy_rwsem_write(cpu);
 		return -EFAULT;
 	}
 
@@ -906,10 +984,10 @@
 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 #endif
 
-	mutex_lock(&data->lock);
 	if (cpufreq_driver->target)
 		__cpufreq_governor(data, CPUFREQ_GOV_STOP);
-	mutex_unlock(&data->lock);
+
+	unlock_policy_rwsem_write(cpu);
 
 	kobject_unregister(&data->kobj);
 
@@ -933,6 +1011,18 @@
 }
 
 
+static int cpufreq_remove_dev (struct sys_device * sys_dev)
+{
+	unsigned int cpu = sys_dev->id;
+	int retval;
+	if (unlikely(lock_policy_rwsem_write(cpu)))
+		BUG();
+
+	retval = __cpufreq_remove_dev(sys_dev);
+	return retval;
+}
+
+
 static void handle_update(struct work_struct *work)
 {
 	struct cpufreq_policy *policy =
@@ -980,9 +1070,12 @@
 	unsigned int ret_freq = 0;
 
 	if (policy) {
-		mutex_lock(&policy->lock);
+		if (unlikely(lock_policy_rwsem_read(cpu)))
+			return ret_freq;
+
 		ret_freq = policy->cur;
-		mutex_unlock(&policy->lock);
+
+		unlock_policy_rwsem_read(cpu);
 		cpufreq_cpu_put(policy);
 	}
 
@@ -991,24 +1084,13 @@
 EXPORT_SYMBOL(cpufreq_quick_get);
 
 
-/**
- * cpufreq_get - get the current CPU frequency (in kHz)
- * @cpu: CPU number
- *
- * Get the CPU current (static) CPU frequency
- */
-unsigned int cpufreq_get(unsigned int cpu)
+static unsigned int __cpufreq_get(unsigned int cpu)
 {
-	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+	struct cpufreq_policy *policy = cpufreq_cpu_data[cpu];
 	unsigned int ret_freq = 0;
 
-	if (!policy)
-		return 0;
-
 	if (!cpufreq_driver->get)
-		goto out;
-
-	mutex_lock(&policy->lock);
+		return (ret_freq);
 
 	ret_freq = cpufreq_driver->get(cpu);
 
@@ -1022,11 +1104,33 @@
 		}
 	}
 
-	mutex_unlock(&policy->lock);
+	return (ret_freq);
+}
 
-out:
+/**
+ * cpufreq_get - get the current CPU frequency (in kHz)
+ * @cpu: CPU number
+ *
+ * Get the CPU current (static) CPU frequency
+ */
+unsigned int cpufreq_get(unsigned int cpu)
+{
+	unsigned int ret_freq = 0;
+	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+
+	if (!policy)
+		goto out;
+
+	if (unlikely(lock_policy_rwsem_read(cpu)))
+		goto out_policy;
+
+	ret_freq = __cpufreq_get(cpu);
+
+	unlock_policy_rwsem_read(cpu);
+
+out_policy:
 	cpufreq_cpu_put(policy);
-
+out:
 	return (ret_freq);
 }
 EXPORT_SYMBOL(cpufreq_get);
@@ -1278,7 +1382,6 @@
  *********************************************************************/
 
 
-/* Must be called with lock_cpu_hotplug held */
 int __cpufreq_driver_target(struct cpufreq_policy *policy,
 			    unsigned int target_freq,
 			    unsigned int relation)
@@ -1304,20 +1407,19 @@
 	if (!policy)
 		return -EINVAL;
 
-	lock_cpu_hotplug();
-	mutex_lock(&policy->lock);
+	if (unlikely(lock_policy_rwsem_write(policy->cpu)))
+		return -EINVAL;
 
 	ret = __cpufreq_driver_target(policy, target_freq, relation);
 
-	mutex_unlock(&policy->lock);
-	unlock_cpu_hotplug();
+	unlock_policy_rwsem_write(policy->cpu);
 
 	cpufreq_cpu_put(policy);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
 
-int cpufreq_driver_getavg(struct cpufreq_policy *policy)
+int __cpufreq_driver_getavg(struct cpufreq_policy *policy)
 {
 	int ret = 0;
 
@@ -1325,20 +1427,15 @@
 	if (!policy)
 		return -EINVAL;
 
-	mutex_lock(&policy->lock);
-
 	if (cpu_online(policy->cpu) && cpufreq_driver->getavg)
 		ret = cpufreq_driver->getavg(policy->cpu);
 
-	mutex_unlock(&policy->lock);
-
 	cpufreq_cpu_put(policy);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(cpufreq_driver_getavg);
+EXPORT_SYMBOL_GPL(__cpufreq_driver_getavg);
 
 /*
- * Locking: Must be called with the lock_cpu_hotplug() lock held
  * when "event" is CPUFREQ_GOV_LIMITS
  */
 
@@ -1420,9 +1517,7 @@
 	if (!cpu_policy)
 		return -EINVAL;
 
-	mutex_lock(&cpu_policy->lock);
 	memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
-	mutex_unlock(&cpu_policy->lock);
 
 	cpufreq_cpu_put(cpu_policy);
 	return 0;
@@ -1433,7 +1528,6 @@
 /*
  * data   : current policy.
  * policy : policy to be set.
- * Locking: Must be called with the lock_cpu_hotplug() lock held
  */
 static int __cpufreq_set_policy(struct cpufreq_policy *data,
 				struct cpufreq_policy *policy)
@@ -1539,10 +1633,9 @@
 	if (!data)
 		return -EINVAL;
 
-	lock_cpu_hotplug();
+	if (unlikely(lock_policy_rwsem_write(policy->cpu)))
+		return -EINVAL;
 
-	/* lock this CPU */
-	mutex_lock(&data->lock);
 
 	ret = __cpufreq_set_policy(data, policy);
 	data->user_policy.min = data->min;
@@ -1550,9 +1643,8 @@
 	data->user_policy.policy = data->policy;
 	data->user_policy.governor = data->governor;
 
-	mutex_unlock(&data->lock);
+	unlock_policy_rwsem_write(policy->cpu);
 
-	unlock_cpu_hotplug();
 	cpufreq_cpu_put(data);
 
 	return ret;
@@ -1576,8 +1668,8 @@
 	if (!data)
 		return -ENODEV;
 
-	lock_cpu_hotplug();
-	mutex_lock(&data->lock);
+	if (unlikely(lock_policy_rwsem_write(cpu)))
+		return -EINVAL;
 
 	dprintk("updating policy for CPU %u\n", cpu);
 	memcpy(&policy, data, sizeof(struct cpufreq_policy));
@@ -1602,8 +1694,8 @@
 
 	ret = __cpufreq_set_policy(data, &policy);
 
-	mutex_unlock(&data->lock);
-	unlock_cpu_hotplug();
+	unlock_policy_rwsem_write(cpu);
+
 	cpufreq_cpu_put(data);
 	return ret;
 }
@@ -1613,31 +1705,28 @@
 					unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
-	struct cpufreq_policy *policy;
 	struct sys_device *sys_dev;
+	struct cpufreq_policy *policy;
 
 	sys_dev = get_cpu_sysdev(cpu);
-
 	if (sys_dev) {
 		switch (action) {
 		case CPU_ONLINE:
 			cpufreq_add_dev(sys_dev);
 			break;
 		case CPU_DOWN_PREPARE:
-			/*
-			 * We attempt to put this cpu in lowest frequency
-			 * possible before going down. This will permit
-			 * hardware-managed P-State to switch other related
-			 * threads to min or higher speeds if possible.
-			 */
+			if (unlikely(lock_policy_rwsem_write(cpu)))
+				BUG();
+
 			policy = cpufreq_cpu_data[cpu];
 			if (policy) {
-				cpufreq_driver_target(policy, policy->min,
+				__cpufreq_driver_target(policy, policy->min,
 						CPUFREQ_RELATION_H);
 			}
+			__cpufreq_remove_dev(sys_dev);
 			break;
-		case CPU_DEAD:
-			cpufreq_remove_dev(sys_dev);
+		case CPU_DOWN_FAILED:
+			cpufreq_add_dev(sys_dev);
 			break;
 		}
 	}
@@ -1751,3 +1840,16 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
+
+static int __init cpufreq_core_init(void)
+{
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		per_cpu(policy_cpu, cpu) = -1;
+		init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
+	}
+	return 0;
+}
+
+core_initcall(cpufreq_core_init);
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index eef0270..26f440c 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -23,7 +23,6 @@
 #include <linux/fs.h>
 #include <linux/sysfs.h>
 #include <linux/cpu.h>
-#include <linux/sched.h>
 #include <linux/kmod.h>
 #include <linux/workqueue.h>
 #include <linux/jiffies.h>
@@ -430,14 +429,12 @@
 static void do_dbs_timer(struct work_struct *work)
 { 
 	int i;
-	lock_cpu_hotplug();
 	mutex_lock(&dbs_mutex);
 	for_each_online_cpu(i)
 		dbs_check_cpu(i);
 	schedule_delayed_work(&dbs_work, 
 			usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
 	mutex_unlock(&dbs_mutex);
-	unlock_cpu_hotplug();
 } 
 
 static inline void dbs_timer_init(void)
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index f697449..d60bcb9 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -52,19 +52,20 @@
 static void do_dbs_timer(struct work_struct *work);
 
 /* Sampling types */
-enum dbs_sample {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
+enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
 
 struct cpu_dbs_info_s {
 	cputime64_t prev_cpu_idle;
 	cputime64_t prev_cpu_wall;
 	struct cpufreq_policy *cur_policy;
  	struct delayed_work work;
-	enum dbs_sample sample_type;
-	unsigned int enable;
 	struct cpufreq_frequency_table *freq_table;
 	unsigned int freq_lo;
 	unsigned int freq_lo_jiffies;
 	unsigned int freq_hi_jiffies;
+	int cpu;
+	unsigned int enable:1,
+	             sample_type:1;
 };
 static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
 
@@ -402,7 +403,7 @@
 	if (load < (dbs_tuners_ins.up_threshold - 10)) {
 		unsigned int freq_next, freq_cur;
 
-		freq_cur = cpufreq_driver_getavg(policy);
+		freq_cur = __cpufreq_driver_getavg(policy);
 		if (!freq_cur)
 			freq_cur = policy->cur;
 
@@ -423,9 +424,11 @@
 
 static void do_dbs_timer(struct work_struct *work)
 {
-	unsigned int cpu = smp_processor_id();
-	struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
-	enum dbs_sample sample_type = dbs_info->sample_type;
+	struct cpu_dbs_info_s *dbs_info =
+		container_of(work, struct cpu_dbs_info_s, work.work);
+	unsigned int cpu = dbs_info->cpu;
+	int sample_type = dbs_info->sample_type;
+
 	/* We want all CPUs to do sampling nearly on same jiffy */
 	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
 
@@ -434,15 +437,19 @@
 
 	delay -= jiffies % delay;
 
-	if (!dbs_info->enable)
+	if (lock_policy_rwsem_write(cpu) < 0)
 		return;
+
+	if (!dbs_info->enable) {
+		unlock_policy_rwsem_write(cpu);
+		return;
+	}
+
 	/* Common NORMAL_SAMPLE setup */
 	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
 	if (!dbs_tuners_ins.powersave_bias ||
 	    sample_type == DBS_NORMAL_SAMPLE) {
-		lock_cpu_hotplug();
 		dbs_check_cpu(dbs_info);
-		unlock_cpu_hotplug();
 		if (dbs_info->freq_lo) {
 			/* Setup timer for SUB_SAMPLE */
 			dbs_info->sample_type = DBS_SUB_SAMPLE;
@@ -454,26 +461,27 @@
 	                        	CPUFREQ_RELATION_H);
 	}
 	queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
+	unlock_policy_rwsem_write(cpu);
 }
 
-static inline void dbs_timer_init(unsigned int cpu)
+static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
 {
-	struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
 	/* We want all CPUs to do sampling nearly on same jiffy */
 	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
 	delay -= jiffies % delay;
 
+	dbs_info->enable = 1;
 	ondemand_powersave_bias_init();
-	INIT_DELAYED_WORK_NAR(&dbs_info->work, do_dbs_timer);
 	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-	queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
+	INIT_DELAYED_WORK_NAR(&dbs_info->work, do_dbs_timer);
+	queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work,
+	                      delay);
 }
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
 {
 	dbs_info->enable = 0;
 	cancel_delayed_work(&dbs_info->work);
-	flush_workqueue(kondemand_wq);
 }
 
 static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
@@ -502,21 +510,9 @@
 
 		mutex_lock(&dbs_mutex);
 		dbs_enable++;
-		if (dbs_enable == 1) {
-			kondemand_wq = create_workqueue("kondemand");
-			if (!kondemand_wq) {
-				printk(KERN_ERR
-					 "Creation of kondemand failed\n");
-				dbs_enable--;
-				mutex_unlock(&dbs_mutex);
-				return -ENOSPC;
-			}
-		}
 
 		rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
 		if (rc) {
-			if (dbs_enable == 1)
-				destroy_workqueue(kondemand_wq);
 			dbs_enable--;
 			mutex_unlock(&dbs_mutex);
 			return rc;
@@ -530,7 +526,7 @@
 			j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j);
 			j_dbs_info->prev_cpu_wall = get_jiffies_64();
 		}
-		this_dbs_info->enable = 1;
+		this_dbs_info->cpu = cpu;
 		/*
 		 * Start the timerschedule work, when this governor
 		 * is used for first time
@@ -550,7 +546,7 @@
 
 			dbs_tuners_ins.sampling_rate = def_sampling_rate;
 		}
-		dbs_timer_init(policy->cpu);
+		dbs_timer_init(this_dbs_info);
 
 		mutex_unlock(&dbs_mutex);
 		break;
@@ -560,9 +556,6 @@
 		dbs_timer_exit(this_dbs_info);
 		sysfs_remove_group(&policy->kobj, &dbs_attr_group);
 		dbs_enable--;
-		if (dbs_enable == 0)
-			destroy_workqueue(kondemand_wq);
-
 		mutex_unlock(&dbs_mutex);
 
 		break;
@@ -591,12 +584,18 @@
 
 static int __init cpufreq_gov_dbs_init(void)
 {
+	kondemand_wq = create_workqueue("kondemand");
+	if (!kondemand_wq) {
+		printk(KERN_ERR "Creation of kondemand failed\n");
+		return -EFAULT;
+	}
 	return cpufreq_register_governor(&cpufreq_gov_dbs);
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
 	cpufreq_unregister_governor(&cpufreq_gov_dbs);
+	destroy_workqueue(kondemand_wq);
 }
 
 
@@ -608,3 +607,4 @@
 
 module_init(cpufreq_gov_dbs_init);
 module_exit(cpufreq_gov_dbs_exit);
+
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 91ad342..d1c7cac 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -370,12 +370,10 @@
 	cpufreq_unregister_notifier(&notifier_trans_block,
 			CPUFREQ_TRANSITION_NOTIFIER);
 	unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
-	lock_cpu_hotplug();
 	for_each_online_cpu(cpu) {
 		cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier,
 						CPU_DEAD, (void *)(long)cpu);
 	}
-	unlock_cpu_hotplug();
 }
 
 MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>");
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 2a4eb0b..860345c 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -71,7 +71,6 @@
 
 	dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
 
-	lock_cpu_hotplug();
 	mutex_lock(&userspace_mutex);
 	if (!cpu_is_managed[policy->cpu])
 		goto err;
@@ -94,7 +93,6 @@
 
  err:
 	mutex_unlock(&userspace_mutex);
-	unlock_cpu_hotplug();
 	return ret;
 }
 
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
index 43a6839..0eb6284 100644
--- a/drivers/crypto/geode-aes.c
+++ b/drivers/crypto/geode-aes.c
@@ -8,7 +8,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/crypto.h>
@@ -457,7 +456,7 @@
 static int __init
 geode_aes_init(void)
 {
-	return pci_module_init(&geode_aes_driver);
+	return pci_register_driver(&geode_aes_driver);
 }
 
 static void __exit
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index c82bc0e..8bcc887 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -285,8 +285,9 @@
 	if (!pvt->map_type)
 		row = 7 - row;
 
-	edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel,
-		"e752x CE");
+	/* e752x mc reads 34:6 of the DRAM linear address */
+	edac_mc_handle_ce(mci, page, offset_in_page(sec1_add << 4),
+			sec1_syndrome, row, channel, "e752x CE");
 }
 
 static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
@@ -319,8 +320,10 @@
 			((block_page >> 1) & 3) :
 			edac_mc_find_csrow_by_page(mci, block_page);
 
-		edac_mc_handle_ue(mci, block_page, 0, row,
-			"e752x UE from Read");
+		/* e752x mc reads 34:6 of the DRAM linear address */
+		edac_mc_handle_ue(mci, block_page,
+					offset_in_page(error_2b << 4),
+					row, "e752x UE from Read");
 	}
 	if (error_one & 0x0404) {
 		error_2b = scrb_add;
@@ -333,8 +336,10 @@
 			((block_page >> 1) & 3) :
 			edac_mc_find_csrow_by_page(mci, block_page);
 
-		edac_mc_handle_ue(mci, block_page, 0, row,
-				"e752x UE from Scruber");
+		/* e752x mc reads 34:6 of the DRAM linear address */
+		edac_mc_handle_ue(mci, block_page,
+					offset_in_page(error_2b << 4),
+					row, "e752x UE from Scruber");
 	}
 }
 
@@ -556,17 +561,17 @@
 	error32 = (stat32 >> 16) & 0x3ff;
 	stat32 = stat32 & 0x3ff;
 
-	if(stat32 & 0x083)
-		sysbus_error(1, stat32 & 0x083, error_found, handle_error);
+	if(stat32 & 0x087)
+		sysbus_error(1, stat32 & 0x087, error_found, handle_error);
 
-	if(stat32 & 0x37c)
-		sysbus_error(0, stat32 & 0x37c, error_found, handle_error);
+	if(stat32 & 0x378)
+		sysbus_error(0, stat32 & 0x378, error_found, handle_error);
 
-	if(error32 & 0x083)
-		sysbus_error(1, error32 & 0x083, error_found, handle_error);
+	if(error32 & 0x087)
+		sysbus_error(1, error32 & 0x087, error_found, handle_error);
 
-	if(error32 & 0x37c)
-		sysbus_error(0, error32 & 0x37c, error_found, handle_error);
+	if(error32 & 0x378)
+		sysbus_error(0, error32 & 0x378, error_found, handle_error);
 }
 
 static void e752x_check_membuf (struct e752x_error_info *info,
@@ -782,7 +787,12 @@
 	u8 value;
 	u32 dra, drc, cumul_size;
 
-	pci_read_config_dword(pdev, E752X_DRA, &dra);
+	dra = 0;
+	for (index=0; index < 4; index++) {
+		u8 dra_reg;
+		pci_read_config_byte(pdev, E752X_DRA+index, &dra_reg);
+		dra |= dra_reg << (index * 8);
+	}
 	pci_read_config_dword(pdev, E752X_DRC, &drc);
 	drc_chan = dual_channel_active(ddrcsr);
 	drc_drbg = drc_chan + 1;  /* 128 in dual mode, 64 in single */
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 1b4fc92..7b62230 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -927,6 +927,57 @@
 	return count;
 }
 
+/* memory scrubbing */
+static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
+					const char *data, size_t count)
+{
+	u32 bandwidth = -1;
+
+	if (mci->set_sdram_scrub_rate) {
+
+		memctrl_int_store(&bandwidth, data, count);
+
+		if (!(*mci->set_sdram_scrub_rate)(mci, &bandwidth)) {
+			edac_printk(KERN_DEBUG, EDAC_MC,
+				"Scrub rate set successfully, applied: %d\n",
+				bandwidth);
+		} else {
+			/* FIXME: error codes maybe? */
+			edac_printk(KERN_DEBUG, EDAC_MC,
+				"Scrub rate set FAILED, could not apply: %d\n",
+				bandwidth);
+		}
+	} else {
+		/* FIXME: produce "not implemented" ERROR for user-side. */
+		edac_printk(KERN_WARNING, EDAC_MC,
+			"Memory scrubbing 'set'control is not implemented!\n");
+	}
+	return count;
+}
+
+static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
+{
+	u32 bandwidth = -1;
+
+	if (mci->get_sdram_scrub_rate) {
+		if (!(*mci->get_sdram_scrub_rate)(mci, &bandwidth)) {
+			edac_printk(KERN_DEBUG, EDAC_MC,
+				"Scrub rate successfully, fetched: %d\n",
+				bandwidth);
+		} else {
+			/* FIXME: error codes maybe? */
+			edac_printk(KERN_DEBUG, EDAC_MC,
+				"Scrub rate fetch FAILED, got: %d\n",
+				bandwidth);
+		}
+	} else {
+		/* FIXME: produce "not implemented" ERROR for user-side.  */
+		edac_printk(KERN_WARNING, EDAC_MC,
+			"Memory scrubbing 'get' control is not implemented!\n");
+	}
+	return sprintf(data, "%d\n", bandwidth);
+}
+
 /* default attribute files for the MCI object */
 static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
 {
@@ -1033,6 +1084,9 @@
 MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
 MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
 
+/* memory scrubber attribute file */
+MCIDEV_ATTR(sdram_scrub_rate,S_IRUGO|S_IWUSR,mci_sdram_scrub_rate_show,mci_sdram_scrub_rate_store);
+
 static struct mcidev_attribute *mci_attr[] = {
 	&mci_attr_reset_counters,
 	&mci_attr_mc_name,
@@ -1042,6 +1096,7 @@
 	&mci_attr_ce_noinfo_count,
 	&mci_attr_ue_count,
 	&mci_attr_ce_count,
+	&mci_attr_sdram_scrub_rate,
 	NULL
 };
 
@@ -1442,11 +1497,11 @@
 	/* set load time so that error rate can be tracked */
 	mci->start_time = jiffies;
 
-        if (edac_create_sysfs_mci_device(mci)) {
-                edac_mc_printk(mci, KERN_WARNING,
+	if (edac_create_sysfs_mci_device(mci)) {
+		edac_mc_printk(mci, KERN_WARNING,
 			"failed to create sysfs device\n");
-                goto fail1;
-        }
+		goto fail1;
+	}
 
 	/* Report action taken */
 	edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: DEV %s\n",
@@ -1703,6 +1758,116 @@
 EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info);
 
 
+/*************************************************************
+ * On Fully Buffered DIMM modules, this help function is
+ * called to process UE events
+ */
+void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci,
+				unsigned int csrow,
+				unsigned int channela,
+				unsigned int channelb,
+				char *msg)
+{
+	int len = EDAC_MC_LABEL_LEN * 4;
+	char labels[len + 1];
+	char *pos = labels;
+	int chars;
+
+	if (csrow >= mci->nr_csrows) {
+		/* something is wrong */
+		edac_mc_printk(mci, KERN_ERR,
+			"INTERNAL ERROR: row out of range (%d >= %d)\n",
+			csrow, mci->nr_csrows);
+		edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+
+	if (channela >= mci->csrows[csrow].nr_channels) {
+		/* something is wrong */
+		edac_mc_printk(mci, KERN_ERR,
+			"INTERNAL ERROR: channel-a out of range "
+			"(%d >= %d)\n",
+			channela, mci->csrows[csrow].nr_channels);
+		edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+
+	if (channelb >= mci->csrows[csrow].nr_channels) {
+		/* something is wrong */
+		edac_mc_printk(mci, KERN_ERR,
+			"INTERNAL ERROR: channel-b out of range "
+			"(%d >= %d)\n",
+			channelb, mci->csrows[csrow].nr_channels);
+		edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+
+	mci->ue_count++;
+	mci->csrows[csrow].ue_count++;
+
+	/* Generate the DIMM labels from the specified channels */
+	chars = snprintf(pos, len + 1, "%s",
+			 mci->csrows[csrow].channels[channela].label);
+	len -= chars; pos += chars;
+	chars = snprintf(pos, len + 1, "-%s",
+			 mci->csrows[csrow].channels[channelb].label);
+
+	if (log_ue)
+		edac_mc_printk(mci, KERN_EMERG,
+			"UE row %d, channel-a= %d channel-b= %d "
+			"labels \"%s\": %s\n", csrow, channela, channelb,
+			labels, msg);
+
+	if (panic_on_ue)
+		panic("UE row %d, channel-a= %d channel-b= %d "
+				"labels \"%s\": %s\n", csrow, channela,
+				channelb, labels, msg);
+}
+EXPORT_SYMBOL(edac_mc_handle_fbd_ue);
+
+/*************************************************************
+ * On Fully Buffered DIMM modules, this help function is
+ * called to process CE events
+ */
+void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
+			   unsigned int csrow,
+			   unsigned int channel,
+			   char *msg)
+{
+
+	/* Ensure boundary values */
+	if (csrow >= mci->nr_csrows) {
+		/* something is wrong */
+		edac_mc_printk(mci, KERN_ERR,
+			"INTERNAL ERROR: row out of range (%d >= %d)\n",
+			csrow, mci->nr_csrows);
+		edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+	if (channel >= mci->csrows[csrow].nr_channels) {
+		/* something is wrong */
+		edac_mc_printk(mci, KERN_ERR,
+			"INTERNAL ERROR: channel out of range (%d >= %d)\n",
+			channel, mci->csrows[csrow].nr_channels);
+		edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+
+	if (log_ce)
+		/* FIXME - put in DIMM location */
+		edac_mc_printk(mci, KERN_WARNING,
+			"CE row %d, channel %d, label \"%s\": %s\n",
+			csrow, channel,
+			mci->csrows[csrow].channels[channel].label,
+			msg);
+
+	mci->ce_count++;
+	mci->csrows[csrow].ce_count++;
+	mci->csrows[csrow].channels[channel].ce_count++;
+}
+EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
+
+
 /*
  * Iterate over all MC instances and check for ECC, et al, errors
  */
@@ -1806,7 +1971,7 @@
 	debugf0("%s()\n", __func__);
 	kthread_stop(edac_thread);
 
-        /* tear down the sysfs device */
+	/* tear down the sysfs device */
 	edac_sysfs_memctrl_teardown();
 	edac_sysfs_pci_teardown();
 }
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index a1cfd4e..713444c 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -123,7 +123,9 @@
 	MEM_RDR,		/* Registered single data rate SDRAM */
 	MEM_DDR,		/* Double data rate SDRAM */
 	MEM_RDDR,		/* Registered Double data rate SDRAM */
-	MEM_RMBS		/* Rambus DRAM */
+	MEM_RMBS,		/* Rambus DRAM */
+	MEM_DDR2,               /* DDR2 RAM */
+	MEM_FB_DDR2,            /* fully buffered DDR2 */
 };
 
 #define MEM_FLAG_EMPTY		BIT(MEM_EMPTY)
@@ -137,6 +139,8 @@
 #define MEM_FLAG_DDR		BIT(MEM_DDR)
 #define MEM_FLAG_RDDR		BIT(MEM_RDDR)
 #define MEM_FLAG_RMBS		BIT(MEM_RMBS)
+#define MEM_FLAG_DDR2           BIT(MEM_DDR2)
+#define MEM_FLAG_FB_DDR2        BIT(MEM_FB_DDR2)
 
 /* chipset Error Detection and Correction capabilities and mode */
 enum edac_type {
@@ -315,8 +319,21 @@
 	unsigned long scrub_cap;	/* chipset scrub capabilities */
 	enum scrub_type scrub_mode;	/* current scrub mode */
 
+	/* Translates sdram memory scrub rate given in bytes/sec to the
+	   internal representation and configures whatever else needs
+	   to be configured.
+	*/
+	int (*set_sdram_scrub_rate) (struct mem_ctl_info *mci, u32 *bw);
+
+	/* Get the current sdram memory scrub rate from the internal
+	   representation and converts it to the closest matching
+	   bandwith in bytes/sec.
+	*/
+	int (*get_sdram_scrub_rate) (struct mem_ctl_info *mci, u32 *bw);
+
 	/* pointer to edac checking routine */
 	void (*edac_check) (struct mem_ctl_info * mci);
+
 	/*
 	 * Remaps memory pages: controller pages to physical pages.
 	 * For most MC's, this will be NULL.
@@ -441,6 +458,15 @@
 		int row, const char *msg);
 extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
 		const char *msg);
+extern void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci,
+		unsigned int csrow,
+		unsigned int channel0,
+		unsigned int channel1,
+		char *msg);
+extern void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
+		unsigned int csrow,
+		unsigned int channel,
+		char *msg);
 
 /*
  * This kmalloc's and initializes all the structures.
diff --git a/drivers/fc4/fc_syms.c b/drivers/fc4/fc_syms.c
index 8700a80..bd3918d 100644
--- a/drivers/fc4/fc_syms.c
+++ b/drivers/fc4/fc_syms.c
@@ -6,7 +6,6 @@
 
 #ifdef CONFIG_MODULES
 
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c
index b09dfc7..d517734 100644
--- a/drivers/fc4/soc.c
+++ b/drivers/fc4/soc.c
@@ -22,7 +22,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c
index a6b1ae2..c903ebf 100644
--- a/drivers/fc4/socal.c
+++ b/drivers/fc4/socal.c
@@ -17,7 +17,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 5c261e1..d8806e4 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -233,6 +233,8 @@
 
 /**
  * edd_show_raw_data() - copies raw data to buffer for userspace to parse
+ * @edev: target edd_device
+ * @buf: output buffer
  *
  * Returns: number of bytes written, or -EINVAL on failure
  */
@@ -634,8 +636,8 @@
 
 /**
  * edd_dev_is_type() - is this EDD device a 'type' device?
- * @edev
- * @type - a host bus or interface identifier string per the EDD spec
+ * @edev: target edd_device
+ * @type: a host bus or interface identifier string per the EDD spec
  *
  * Returns 1 (TRUE) if it is a 'type' device, 0 otherwise.
  */
@@ -657,7 +659,7 @@
 
 /**
  * edd_get_pci_dev() - finds pci_dev that matches edev
- * @edev - edd_device
+ * @edev: edd_device
  *
  * Returns pci_dev if found, or NULL
  */
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8c7d48e..7452399 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -18,7 +18,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 891ef6d..c3d4856 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -73,6 +73,17 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called adm1026.
 
+config SENSORS_ADM1029
+	tristate "Analog Devices ADM1029"
+	depends on HWMON && I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for Analog Devices ADM1029
+	  sensor chip.
+	  Very rare chip, please let us know you use it.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called adm1029.
+
 config SENSORS_ADM1031
 	tristate "Analog Devices ADM1031 and compatibles"
 	depends on HWMON && I2C && EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 3166112..4165c27 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -17,6 +17,7 @@
 obj-$(CONFIG_SENSORS_ADM1021)	+= adm1021.o
 obj-$(CONFIG_SENSORS_ADM1025)	+= adm1025.o
 obj-$(CONFIG_SENSORS_ADM1026)	+= adm1026.o
+obj-$(CONFIG_SENSORS_ADM1029)	+= adm1029.o
 obj-$(CONFIG_SENSORS_ADM1031)	+= adm1031.o
 obj-$(CONFIG_SENSORS_ADM9240)	+= adm9240.o
 obj-$(CONFIG_SENSORS_AMS)	+= ams/
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index b1dc63e..bede4d9 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -1267,30 +1267,42 @@
 	printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n");
 
 	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(&pdev->dev);
-	if (IS_ERR(data->class_dev)) {
-		res = PTR_ERR(data->class_dev);
-		goto abituguru_probe_error;
-	}
 	for (i = 0; i < sysfs_attr_i; i++)
-		device_create_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
+		if (device_create_file(&pdev->dev,
+				&data->sysfs_attr[i].dev_attr))
+			goto abituguru_probe_error;
 	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
-		device_create_file(&pdev->dev,
-			&abituguru_sysfs_attr[i].dev_attr);
+		if (device_create_file(&pdev->dev,
+				&abituguru_sysfs_attr[i].dev_attr))
+			goto abituguru_probe_error;
 
-	return 0;
+	data->class_dev = hwmon_device_register(&pdev->dev);
+	if (!IS_ERR(data->class_dev))
+		return 0; /* success */
 
+	res = PTR_ERR(data->class_dev);
 abituguru_probe_error:
+	for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
+		device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
+	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
+		device_remove_file(&pdev->dev,
+			&abituguru_sysfs_attr[i].dev_attr);
 	kfree(data);
 	return res;
 }
 
 static int __devexit abituguru_remove(struct platform_device *pdev)
 {
+	int i;
 	struct abituguru_data *data = platform_get_drvdata(pdev);
 
 	platform_set_drvdata(pdev, NULL);
 	hwmon_device_unregister(data->class_dev);
+	for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
+		device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
+	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
+		device_remove_file(&pdev->dev,
+			&abituguru_sysfs_attr[i].dev_attr);
 	kfree(data);
 
 	return 0;
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index b4618b2..ba80cd3 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -261,7 +261,6 @@
 struct adm1026_data {
 	struct i2c_client client;
 	struct class_device *class_dev;
-	struct mutex lock;
 	enum chips type;
 
 	struct mutex update_lock;
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c
new file mode 100644
index 0000000..73ce31b
--- /dev/null
+++ b/drivers/hwmon/adm1029.c
@@ -0,0 +1,508 @@
+/*
+ * adm1029.c - Part of lm_sensors, Linux kernel modules for hardware monitoring
+ *
+ * Copyright (C) 2006 Corentin LABBE <corentin.labbe@geomatys.fr>
+ *
+ * Based on LM83 Driver by Jean Delvare <khali@linux-fr.org>
+ *
+ * Give only processor, motherboard temperatures and fan tachs
+ * Very rare chip please let me know if you use it
+ *
+ * http://www.analog.com/UploadedFiles/Data_Sheets/ADM1029.pdf
+ *
+ *
+ * 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
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+/*
+ * Addresses to scan
+ */
+
+static unsigned short normal_i2c[] = {
+	0x28, 0x29, 0x2a,
+	0x2b, 0x2c, 0x2d,
+	0x2e, 0x2f, I2C_CLIENT_END
+};
+
+/*
+ * Insmod parameters
+ */
+
+I2C_CLIENT_INSMOD_1(adm1029);
+
+/*
+ * The ADM1029 registers
+ * Manufacturer ID is 0x41 for Analog Devices
+ */
+
+#define ADM1029_REG_MAN_ID			0x0D
+#define ADM1029_REG_CHIP_ID			0x0E
+#define ADM1029_REG_CONFIG			0x01
+#define ADM1029_REG_NB_FAN_SUPPORT		0x02
+
+#define ADM1029_REG_TEMP_DEVICES_INSTALLED	0x06
+
+#define ADM1029_REG_LOCAL_TEMP			0xA0
+#define ADM1029_REG_REMOTE1_TEMP		0xA1
+#define ADM1029_REG_REMOTE2_TEMP		0xA2
+
+#define ADM1029_REG_LOCAL_TEMP_HIGH		0x90
+#define ADM1029_REG_REMOTE1_TEMP_HIGH		0x91
+#define ADM1029_REG_REMOTE2_TEMP_HIGH		0x92
+
+#define ADM1029_REG_LOCAL_TEMP_LOW		0x98
+#define ADM1029_REG_REMOTE1_TEMP_LOW		0x99
+#define ADM1029_REG_REMOTE2_TEMP_LOW		0x9A
+
+#define ADM1029_REG_FAN1			0x70
+#define ADM1029_REG_FAN2			0x71
+
+#define ADM1029_REG_FAN1_MIN			0x78
+#define ADM1029_REG_FAN2_MIN			0x79
+
+#define ADM1029_REG_FAN1_CONFIG			0x68
+#define ADM1029_REG_FAN2_CONFIG			0x69
+
+#define TEMP_FROM_REG(val)	((val) * 1000)
+
+#define DIV_FROM_REG(val)	( 1 << (((val) >> 6) - 1))
+
+/* Registers to be checked by adm1029_update_device() */
+static const u8 ADM1029_REG_TEMP[] = {
+	ADM1029_REG_LOCAL_TEMP,
+	ADM1029_REG_REMOTE1_TEMP,
+	ADM1029_REG_REMOTE2_TEMP,
+	ADM1029_REG_LOCAL_TEMP_HIGH,
+	ADM1029_REG_REMOTE1_TEMP_HIGH,
+	ADM1029_REG_REMOTE2_TEMP_HIGH,
+	ADM1029_REG_LOCAL_TEMP_LOW,
+	ADM1029_REG_REMOTE1_TEMP_LOW,
+	ADM1029_REG_REMOTE2_TEMP_LOW,
+};
+
+static const u8 ADM1029_REG_FAN[] = {
+	ADM1029_REG_FAN1,
+	ADM1029_REG_FAN2,
+	ADM1029_REG_FAN1_MIN,
+	ADM1029_REG_FAN2_MIN,
+};
+
+static const u8 ADM1029_REG_FAN_DIV[] = {
+	ADM1029_REG_FAN1_CONFIG,
+	ADM1029_REG_FAN2_CONFIG,
+};
+
+/*
+ * Functions declaration
+ */
+
+static int adm1029_attach_adapter(struct i2c_adapter *adapter);
+static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind);
+static int adm1029_detach_client(struct i2c_client *client);
+static struct adm1029_data *adm1029_update_device(struct device *dev);
+static int adm1029_init_client(struct i2c_client *client);
+
+/*
+ * Driver data (common to all clients)
+ */
+
+static struct i2c_driver adm1029_driver = {
+	.driver = {
+		.name = "adm1029",
+	},
+	.attach_adapter = adm1029_attach_adapter,
+	.detach_client = adm1029_detach_client,
+};
+
+/*
+ * Client data (each client gets its own)
+ */
+
+struct adm1029_data {
+	struct i2c_client client;
+	struct class_device *class_dev;
+	struct mutex update_lock;
+	char valid;		/* zero until following fields are valid */
+	unsigned long last_updated;	/* in jiffies */
+
+	/* registers values, signed for temperature, unsigned for other stuff */
+	s8 temp[ARRAY_SIZE(ADM1029_REG_TEMP)];
+	u8 fan[ARRAY_SIZE(ADM1029_REG_FAN)];
+	u8 fan_div[ARRAY_SIZE(ADM1029_REG_FAN_DIV)];
+};
+
+/*
+ * Sysfs stuff
+ */
+
+static ssize_t
+show_temp(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct adm1029_data *data = adm1029_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
+}
+
+static ssize_t
+show_fan(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct adm1029_data *data = adm1029_update_device(dev);
+	u16 val;
+	if (data->fan[attr->index] == 0 || data->fan_div[attr->index] == 0
+	    || data->fan[attr->index] == 255) {
+		return sprintf(buf, "0\n");
+	}
+
+	val = 1880 * 120 / DIV_FROM_REG(data->fan_div[attr->index])
+	    / data->fan[attr->index];
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct adm1029_data *data = adm1029_update_device(dev);
+	if (data->fan_div[attr->index] == 0)
+		return sprintf(buf, "0\n");
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index]));
+}
+
+static ssize_t set_fan_div(struct device *dev,
+	    struct device_attribute *devattr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm1029_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	long val = simple_strtol(buf, NULL, 10);
+	u8 reg;
+
+	mutex_lock(&data->update_lock);
+
+	/*Read actual config */
+	reg = i2c_smbus_read_byte_data(client,
+				       ADM1029_REG_FAN_DIV[attr->index]);
+
+	switch (val) {
+	case 1:
+		val = 1;
+		break;
+	case 2:
+		val = 2;
+		break;
+	case 4:
+		val = 3;
+		break;
+	default:
+		mutex_unlock(&data->update_lock);
+		dev_err(&client->dev, "fan_div value %ld not "
+			"supported. Choose one of 1, 2 or 4!\n", val);
+		return -EINVAL;
+	}
+	/* Update the value */
+	reg = (reg & 0x3F) | (val << 6);
+
+	/* Write value */
+	i2c_smbus_write_byte_data(client,
+				  ADM1029_REG_FAN_DIV[attr->index], reg);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/*
+Access rights on sysfs, S_IRUGO stand for Is Readable by User, Group and Others
+			S_IWUSR stand for Is Writable by User
+*/
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp, NULL, 8);
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+
+static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan, NULL, 3);
+
+static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
+			  show_fan_div, set_fan_div, 0);
+static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
+			  show_fan_div, set_fan_div, 1);
+
+static struct attribute *adm1029_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group adm1029_group = {
+	.attrs = adm1029_attributes,
+};
+
+/*
+ * Real code
+ */
+
+static int adm1029_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_probe(adapter, &addr_data, adm1029_detect);
+}
+
+/*
+ * The following function does more than just detection. If detection
+ * succeeds, it also registers the new chip.
+ */
+
+static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct adm1029_data *data;
+	int err = 0;
+	const char *name = "";
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		goto exit;
+
+	if (!(data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &adm1029_driver;
+
+	/* Now we do the detection and identification. A negative kind
+	 * means that the driver was loaded with no force parameter
+	 * (default), so we must both detect and identify the chip
+	 * (actually there is only one possible kind of chip for now, adm1029).
+	 * A zero kind means that the driver was loaded with the force
+	 * parameter, the detection step shall be skipped. A positive kind
+	 * means that the driver was loaded with the force parameter and a
+	 * given kind of chip is requested, so both the detection and the
+	 * identification steps are skipped. */
+
+	/* Default to an adm1029 if forced */
+	if (kind == 0)
+		kind = adm1029;
+
+	/* ADM1029 doesn't have CHIP ID, check just MAN ID
+	 * For better detection we check also ADM1029_TEMP_DEVICES_INSTALLED,
+	 * ADM1029_REG_NB_FAN_SUPPORT and compare it with possible values
+	 * documented
+	 */
+
+	if (kind <= 0) {	/* identification */
+		u8 man_id, chip_id, temp_devices_installed, nb_fan_support;
+
+		man_id = i2c_smbus_read_byte_data(client, ADM1029_REG_MAN_ID);
+		chip_id = i2c_smbus_read_byte_data(client, ADM1029_REG_CHIP_ID);
+		temp_devices_installed = i2c_smbus_read_byte_data(client,
+					ADM1029_REG_TEMP_DEVICES_INSTALLED);
+		nb_fan_support = i2c_smbus_read_byte_data(client,
+						ADM1029_REG_NB_FAN_SUPPORT);
+		/* 0x41 is Analog Devices */
+		if (man_id == 0x41 && (temp_devices_installed & 0xf9) == 0x01
+		    && nb_fan_support == 0x03) {
+			if ((chip_id & 0xF0) == 0x00) {
+				kind = adm1029;
+			} else {
+				/* There are no "official" CHIP ID, so actually
+				 * we use Major/Minor revision for that */
+				printk(KERN_INFO
+				       "adm1029: Unknown major revision %x, "
+				       "please let us know\n", chip_id);
+			}
+		}
+
+		if (kind <= 0) {	/* identification failed */
+			pr_debug("adm1029: Unsupported chip (man_id=0x%02X, "
+				 "chip_id=0x%02X)\n", man_id, chip_id);
+			goto exit_free;
+		}
+	}
+
+	if (kind == adm1029) {
+		name = "adm1029";
+	}
+
+	/* We can fill in the remaining client fields */
+	strlcpy(client->name, name, I2C_NAME_SIZE);
+	mutex_init(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(client)))
+		goto exit_free;
+
+	/*
+	 * Initialize the ADM1029 chip
+	 * Check config register
+	 */
+	if (adm1029_init_client(client) == 0)
+		goto exit_detach;
+
+	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group)))
+		goto exit_detach;
+
+	data->class_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove_files;
+	}
+
+	return 0;
+
+ exit_remove_files:
+	sysfs_remove_group(&client->dev.kobj, &adm1029_group);
+ exit_detach:
+	i2c_detach_client(client);
+ exit_free:
+	kfree(data);
+ exit:
+	return err;
+}
+
+static int adm1029_init_client(struct i2c_client *client)
+{
+	u8 config;
+	config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG);
+	if ((config & 0x10) == 0) {
+		i2c_smbus_write_byte_data(client, ADM1029_REG_CONFIG,
+					  config | 0x10);
+	}
+	/* recheck config */
+	config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG);
+	if ((config & 0x10) == 0) {
+		dev_err(&client->dev, "Initialization failed!\n");
+		return 0;
+	}
+	return 1;
+}
+
+static int adm1029_detach_client(struct i2c_client *client)
+{
+	struct adm1029_data *data = i2c_get_clientdata(client);
+	int err;
+
+	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &adm1029_group);
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
+	return 0;
+}
+
+/*
+function that update the status of the chips (temperature for exemple)
+*/
+static struct adm1029_data *adm1029_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm1029_data *data = i2c_get_clientdata(client);
+
+	mutex_lock(&data->update_lock);
+	/*
+	 * Use the "cache" Luke, don't recheck values
+	 * if there are already checked not a long time later
+	 */
+	if (time_after(jiffies, data->last_updated + HZ * 2)
+	 || !data->valid) {
+		int nr;
+
+		dev_dbg(&client->dev, "Updating adm1029 data\n");
+
+		for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) {
+			data->temp[nr] =
+			    i2c_smbus_read_byte_data(client,
+						     ADM1029_REG_TEMP[nr]);
+		}
+		for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) {
+			data->fan[nr] =
+			    i2c_smbus_read_byte_data(client,
+						     ADM1029_REG_FAN[nr]);
+		}
+		for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) {
+			data->fan_div[nr] =
+			    i2c_smbus_read_byte_data(client,
+						     ADM1029_REG_FAN_DIV[nr]);
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+/*
+	Common module stuff
+*/
+static int __init sensors_adm1029_init(void)
+{
+
+	return i2c_add_driver(&adm1029_driver);
+}
+
+static void __exit sensors_adm1029_exit(void)
+{
+
+	i2c_del_driver(&adm1029_driver);
+}
+
+MODULE_AUTHOR("Corentin LABBE <corentin.labbe@geomatys.fr>");
+MODULE_DESCRIPTION("adm1029 driver");
+MODULE_LICENSE("GPL v2");
+
+module_init(sensors_adm1029_init);
+module_exit(sensors_adm1029_exit);
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c
index f126aa4..1821016 100644
--- a/drivers/hwmon/ams/ams-input.c
+++ b/drivers/hwmon/ams/ams-input.c
@@ -153,7 +153,7 @@
 }
 
 /* Call with ams_info.lock held! */
-void ams_input_exit()
+void ams_input_exit(void)
 {
 	ams_input_disable();
 	device_remove_file(&ams_info.of_dev->dev, &dev_attr_joystick);
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index a272cae..7c29734 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -146,7 +146,6 @@
 struct f71805f_data {
 	unsigned short addr;
 	const char *name;
-	struct mutex lock;
 	struct class_device *class_dev;
 
 	struct mutex update_lock;
@@ -271,50 +270,42 @@
  * Device I/O access
  */
 
+/* Must be called with data->update_lock held, except during initialization */
 static u8 f71805f_read8(struct f71805f_data *data, u8 reg)
 {
-	u8 val;
-
-	mutex_lock(&data->lock);
 	outb(reg, data->addr + ADDR_REG_OFFSET);
-	val = inb(data->addr + DATA_REG_OFFSET);
-	mutex_unlock(&data->lock);
-
-	return val;
+	return inb(data->addr + DATA_REG_OFFSET);
 }
 
+/* Must be called with data->update_lock held, except during initialization */
 static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val)
 {
-	mutex_lock(&data->lock);
 	outb(reg, data->addr + ADDR_REG_OFFSET);
 	outb(val, data->addr + DATA_REG_OFFSET);
-	mutex_unlock(&data->lock);
 }
 
 /* It is important to read the MSB first, because doing so latches the
-   value of the LSB, so we are sure both bytes belong to the same value. */
+   value of the LSB, so we are sure both bytes belong to the same value.
+   Must be called with data->update_lock held, except during initialization */
 static u16 f71805f_read16(struct f71805f_data *data, u8 reg)
 {
 	u16 val;
 
-	mutex_lock(&data->lock);
 	outb(reg, data->addr + ADDR_REG_OFFSET);
 	val = inb(data->addr + DATA_REG_OFFSET) << 8;
 	outb(++reg, data->addr + ADDR_REG_OFFSET);
 	val |= inb(data->addr + DATA_REG_OFFSET);
-	mutex_unlock(&data->lock);
 
 	return val;
 }
 
+/* Must be called with data->update_lock held, except during initialization */
 static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
 {
-	mutex_lock(&data->lock);
 	outb(reg, data->addr + ADDR_REG_OFFSET);
 	outb(val >> 8, data->addr + DATA_REG_OFFSET);
 	outb(++reg, data->addr + ADDR_REG_OFFSET);
 	outb(val & 0xff, data->addr + DATA_REG_OFFSET);
-	mutex_unlock(&data->lock);
 }
 
 static struct f71805f_data *f71805f_update_device(struct device *dev)
@@ -1150,7 +1141,6 @@
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	data->addr = res->start;
-	mutex_init(&data->lock);
 	data->name = names[sio_data->kind];
 	mutex_init(&data->update_lock);
 
@@ -1300,14 +1290,11 @@
 	if (err) {
 		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
 		       err);
-		goto exit_kfree_data;
+		goto exit_device_put;
 	}
 
 	return 0;
 
-exit_kfree_data:
-	kfree(pdev->dev.platform_data);
-	pdev->dev.platform_data = NULL;
 exit_device_put:
 	platform_device_put(pdev);
 exit:
@@ -1400,10 +1387,7 @@
 
 static void __exit f71805f_exit(void)
 {
-	kfree(pdev->dev.platform_data);
-	pdev->dev.platform_data = NULL;
 	platform_device_unregister(pdev);
-
 	platform_driver_unregister(&f71805f_driver);
 }
 
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 106fa01..affcc00 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -101,7 +101,7 @@
 	class_destroy(hwmon_class);
 }
 
-module_init(hwmon_init);
+subsys_initcall(hwmon_init);
 module_exit(hwmon_exit);
 
 EXPORT_SYMBOL_GPL(hwmon_device_register);
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 1ed8b7e..62afc63 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -202,15 +202,23 @@
 }
 #define DIV_FROM_REG(val) (1 << (val))
 
+static const unsigned int pwm_freq[8] = {
+	48000000 / 128,
+	24000000 / 128,
+	12000000 / 128,
+	8000000 / 128,
+	6000000 / 128,
+	3000000 / 128,
+	1500000 / 128,
+	750000 / 128,
+};
 
-/* For each registered IT87, we need to keep some data in memory. That
-   data is pointed to by it87_list[NR]->data. The structure itself is
-   dynamically allocated, at the same time when a new it87 client is
-   allocated. */
+
+/* For each registered chip, we need to keep some data in memory.
+   The structure is dynamically allocated. */
 struct it87_data {
 	struct i2c_client client;
 	struct class_device *class_dev;
-	struct mutex lock;
 	enum chips type;
 
 	struct mutex update_lock;
@@ -232,6 +240,7 @@
 	u8 vrm;
 	u32 alarms;		/* Register encoding, combined */
 	u8 fan_main_ctrl;	/* Register value */
+	u8 fan_ctl;		/* Register value */
 	u8 manual_pwm_ctl[3];   /* manual PWM value set by user */
 };
 
@@ -519,6 +528,14 @@
 	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]);
 }
+static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct it87_data *data = it87_update_device(dev);
+	int index = (data->fan_ctl >> 4) & 0x07;
+
+	return sprintf(buf, "%u\n", pwm_freq[index]);
+}
 static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
@@ -528,9 +545,10 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct it87_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
-	u8 reg = it87_read_value(client, IT87_REG_FAN_DIV);
+	u8 reg;
 
 	mutex_lock(&data->update_lock);
+	reg = it87_read_value(client, IT87_REG_FAN_DIV);
 	switch (nr) {
 	case 0: data->fan_div[nr] = reg & 0x07; break;
 	case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break;
@@ -639,6 +657,28 @@
 	mutex_unlock(&data->update_lock);
 	return count;
 }
+static ssize_t set_pwm_freq(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct it87_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int i;
+
+	/* Search for the nearest available frequency */
+	for (i = 0; i < 7; i++) {
+		if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2)
+			break;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL) & 0x8f;
+	data->fan_ctl |= i << 4;
+	it87_write_value(client, IT87_REG_FAN_CTL, data->fan_ctl);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
 
 #define show_fan_offset(offset)					\
 static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,		\
@@ -656,7 +696,10 @@
 static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,	\
 		show_pwm_enable, set_pwm_enable, offset - 1);		\
 static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,		\
-		show_pwm, set_pwm, offset - 1);
+		show_pwm, set_pwm, offset - 1);				\
+static DEVICE_ATTR(pwm##offset##_freq,					\
+		(offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO),		\
+		show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL));
 
 show_pwm_offset(1);
 show_pwm_offset(2);
@@ -904,7 +947,6 @@
 	}
 
 	new_client = &data->client;
-	mutex_init(&data->lock);
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = isa_address;
 	new_client->adapter = adapter;
@@ -1021,7 +1063,13 @@
 		 || (err = device_create_file(&new_client->dev,
 		     &sensor_dev_attr_pwm2.dev_attr))
 		 || (err = device_create_file(&new_client->dev,
-		     &sensor_dev_attr_pwm3.dev_attr)))
+		     &sensor_dev_attr_pwm3.dev_attr))
+		 || (err = device_create_file(&new_client->dev,
+		     &dev_attr_pwm1_freq))
+		 || (err = device_create_file(&new_client->dev,
+		     &dev_attr_pwm2_freq))
+		 || (err = device_create_file(&new_client->dev,
+		     &dev_attr_pwm3_freq)))
 			goto ERROR4;
 	}
 
@@ -1076,33 +1124,22 @@
 	return 0;
 }
 
-/* ISA access must be locked explicitly!
+/* Must be called with data->update_lock held, except during initialization.
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
    would slow down the IT87 access and should not be necessary. */
 static int it87_read_value(struct i2c_client *client, u8 reg)
 {
-	struct it87_data *data = i2c_get_clientdata(client);
-	int res;
-
-	mutex_lock(&data->lock);
 	outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
-	res = inb_p(client->addr + IT87_DATA_REG_OFFSET);
-	mutex_unlock(&data->lock);
-
-	return res;
+	return inb_p(client->addr + IT87_DATA_REG_OFFSET);
 }
 
-/* ISA access must be locked explicitly!
+/* Must be called with data->update_lock held, except during initialization.
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
    would slow down the IT87 access and should not be necessary. */
 static void it87_write_value(struct i2c_client *client, u8 reg, u8 value)
 {
-	struct it87_data *data = i2c_get_clientdata(client);
-
-	mutex_lock(&data->lock);
 	outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
 	outb_p(value, client->addr + IT87_DATA_REG_OFFSET);
-	mutex_unlock(&data->lock);
 }
 
 /* Return 1 if and only if the PWM interface is safe to use */
@@ -1316,6 +1353,7 @@
 			(it87_read_value(client, IT87_REG_ALARM2) << 8) |
 			(it87_read_value(client, IT87_REG_ALARM3) << 16);
 		data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL);
+		data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL);
 
 		data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE);
 		/* The 8705 does not have VID capability */
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 6ba8473..7eaae38 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -126,7 +126,7 @@
 	return status;
 }
 
-static int __exit lm70_remove(struct spi_device *spi)
+static int __devexit lm70_remove(struct spi_device *spi)
 {
 	struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
 
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 73bc2ff..886786c 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -125,10 +125,8 @@
    bad. Quite a lot of bookkeeping is done. A real driver can often cut
    some corners. */
 
-/* For each registered LM78, we need to keep some data in memory. That
-   data is pointed to by lm78_list[NR]->data. The structure itself is
-   dynamically allocated, at the same time when a new lm78 client is
-   allocated. */
+/* For each registered chip, we need to keep some data in memory.
+   The structure is dynamically allocated. */
 struct lm78_data {
 	struct i2c_client client;
 	struct class_device *class_dev;
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 2c3293c..20a8c64 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -298,11 +298,6 @@
 #define LM85_DATA_INTERVAL  (HZ + HZ / 2)
 #define LM85_CONFIG_INTERVAL  (1 * 60 * HZ)
 
-/* For each registered LM85, we need to keep some data in memory. That
-   data is pointed to by lm85_list[NR]->data. The structure itself is
-   dynamically allocated, at the same time when a new lm85 client is
-   allocated. */
-
 /* LM85 can automatically adjust fan speeds based on temperature
  * This structure encapsulates an entire Zone config.  There are
  * three zones (one for each temperature input) on the lm85
@@ -329,10 +324,11 @@
 	u8 min_off;	/* Min PWM or OFF below "limit", flag */
 };
 
+/* For each registered chip, we need to keep some data in memory.
+   The structure is dynamically allocated. */
 struct lm85_data {
 	struct i2c_client client;
 	struct class_device *class_dev;
-	struct mutex lock;
 	enum chips type;
 
 	struct mutex update_lock;
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 95a4b5d..3f40026 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -162,10 +162,8 @@
 }
 #define DIV_FROM_REG(val) (1 << (val))
 
-/* For the SIS5595, we need to keep some data in memory. That
-   data is pointed to by sis5595_list[NR]->data. The structure itself is
-   dynamically allocated, at the time when the new sis5595 client is
-   allocated. */
+/* For each registered chip, we need to keep some data in memory.
+   The structure is dynamically allocated. */
 struct sis5595_data {
 	struct i2c_client client;
 	struct class_device *class_dev;
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index f8acada..9a440c8 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -292,9 +292,8 @@
 #define DIV_FROM_REG(val) (1 << (val))
 #define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
 
-/* For the VIA686A, we need to keep some data in memory.
-   The structure is dynamically allocated, at the same time when a new
-   via686a client is allocated. */
+/* For each registered chip, we need to keep some data in memory.
+   The structure is dynamically allocated. */
 struct via686a_data {
 	struct i2c_client client;
 	struct class_device *class_dev;
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index 25cc560..89c23d6 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -178,9 +178,10 @@
  * Super-I/O constants and functions
  * --------------------------------------------------------------------- */
 
-/* Configuration & data index port registers */
-#define SIO_REG_CIP		0x2e
-#define SIO_REG_DIP		0x2f
+/* Configuration index port registers
+ * The vt1211 can live at 2 different addresses so we need to probe both */
+#define SIO_REG_CIP1		0x2e
+#define SIO_REG_CIP2		0x4e
 
 /* Configuration registers */
 #define SIO_VT1211_LDN		0x07	/* logical device number */
@@ -193,33 +194,33 @@
 /* VT1211 logical device numbers */
 #define SIO_VT1211_LDN_HWMON	0x0b	/* HW monitor */
 
-static inline void superio_outb(int reg, int val)
+static inline void superio_outb(int sio_cip, int reg, int val)
 {
-	outb(reg, SIO_REG_CIP);
-	outb(val, SIO_REG_DIP);
+	outb(reg, sio_cip);
+	outb(val, sio_cip + 1);
 }
 
-static inline int superio_inb(int reg)
+static inline int superio_inb(int sio_cip, int reg)
 {
-	outb(reg, SIO_REG_CIP);
-	return inb(SIO_REG_DIP);
+	outb(reg, sio_cip);
+	return inb(sio_cip + 1);
 }
 
-static inline void superio_select(int ldn)
+static inline void superio_select(int sio_cip, int ldn)
 {
-	outb(SIO_VT1211_LDN, SIO_REG_CIP);
-	outb(ldn, SIO_REG_DIP);
+	outb(SIO_VT1211_LDN, sio_cip);
+	outb(ldn, sio_cip + 1);
 }
 
-static inline void superio_enter(void)
+static inline void superio_enter(int sio_cip)
 {
-	outb(0x87, SIO_REG_CIP);
-	outb(0x87, SIO_REG_CIP);
+	outb(0x87, sio_cip);
+	outb(0x87, sio_cip);
 }
 
-static inline void superio_exit(void)
+static inline void superio_exit(int sio_cip)
 {
-	outb(0xaa, SIO_REG_CIP);
+	outb(0xaa, sio_cip);
 }
 
 /* ---------------------------------------------------------------------
@@ -1263,26 +1264,26 @@
 	return err;
 }
 
-static int __init vt1211_find(unsigned short *address)
+static int __init vt1211_find(int sio_cip, unsigned short *address)
 {
 	int err = -ENODEV;
 
-	superio_enter();
+	superio_enter(sio_cip);
 
-	if (superio_inb(SIO_VT1211_DEVID) != SIO_VT1211_ID) {
+	if (superio_inb(sio_cip, SIO_VT1211_DEVID) != SIO_VT1211_ID) {
 		goto EXIT;
 	}
 
-	superio_select(SIO_VT1211_LDN_HWMON);
+	superio_select(sio_cip, SIO_VT1211_LDN_HWMON);
 
-	if ((superio_inb(SIO_VT1211_ACTIVE) & 1) == 0) {
+	if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) {
 		printk(KERN_WARNING DRVNAME ": HW monitor is disabled, "
 		       "skipping\n");
 		goto EXIT;
 	}
 
-	*address = ((superio_inb(SIO_VT1211_BADDR) << 8) |
-		    (superio_inb(SIO_VT1211_BADDR + 1))) & 0xff00;
+	*address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) |
+		    (superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00;
 	if (*address == 0) {
 		printk(KERN_WARNING DRVNAME ": Base address is not set, "
 		       "skipping\n");
@@ -1291,10 +1292,11 @@
 
 	err = 0;
 	printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, "
-	       "revision %u\n", *address, superio_inb(SIO_VT1211_DEVREV));
+	       "revision %u\n", *address,
+	       superio_inb(sio_cip, SIO_VT1211_DEVREV));
 
 EXIT:
-	superio_exit();
+	superio_exit(sio_cip);
 	return err;
 }
 
@@ -1303,8 +1305,8 @@
 	int err;
 	unsigned short address = 0;
 
-	err = vt1211_find(&address);
-	if (err) {
+	if ((err = vt1211_find(SIO_REG_CIP1, &address)) &&
+	    (err = vt1211_find(SIO_REG_CIP2, &address))) {
 		goto EXIT;
 	}
 
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 93f93d4..a6a4aa0 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -727,7 +727,6 @@
 	client->addr = isa_address;
 	client->adapter = adapter;
 	client->driver = &vt8231_driver;
-	client->dev.parent = &adapter->dev;
 
 	/* Fill in the remaining client fields and put into the global list */
 	strlcpy(client->name, "vt8231", I2C_NAME_SIZE);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 212a155..da5828f 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -32,8 +32,10 @@
 
     Supports the following chips:
 
-    Chip        #vin    #fan    #pwm    #temp   chip_id    man_id
-    w83627ehf   10      5       4       3       0x88,0xa1  0x5ca3
+    Chip        #vin    #fan    #pwm    #temp  chip IDs       man ID
+    w83627ehf   10      5       4       3      0x8850 0x88    0x5ca3
+                                               0x8860 0xa1
+    w83627dhg    9      5       4       3      0xa020 0xc1    0x5ca3
 */
 
 #include <linux/module.h>
@@ -55,8 +57,18 @@
  * Super-I/O constants and functions
  */
 
+/*
+ * The three following globals are initialized in w83627ehf_find(), before
+ * the i2c-isa device is created. Otherwise, they could be stored in
+ * w83627ehf_data. This is ugly, but necessary, and when the driver is next
+ * updated to become a platform driver, the globals will disappear.
+ */
 static int REG;		/* The register to read/write */
 static int VAL;		/* The value to read/write */
+/* The w83627ehf/ehg have 10 voltage inputs, but the w83627dhg has 9. This
+ * value is also used in w83627ehf_detect() to export a device name in sysfs
+ * (e.g. w83627ehf or w83627dhg) */
+static int w83627ehf_num_in;
 
 #define W83627EHF_LD_HWM	0x0b
 
@@ -65,8 +77,10 @@
 #define SIO_REG_ENABLE		0x30	/* Logical device enable */
 #define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
 
-#define SIO_W83627EHF_ID	0x8840
-#define SIO_ID_MASK		0xFFC0
+#define SIO_W83627EHF_ID	0x8850
+#define SIO_W83627EHG_ID	0x8860
+#define SIO_W83627DHG_ID	0xa020
+#define SIO_ID_MASK		0xFFF0
 
 static inline void
 superio_outb(int reg, int val)
@@ -115,8 +129,12 @@
 
 #define W83627EHF_REG_BANK		0x4E
 #define W83627EHF_REG_CONFIG		0x40
-#define W83627EHF_REG_CHIP_ID		0x49
-#define W83627EHF_REG_MAN_ID		0x4F
+
+/* Not currently used:
+ * REG_MAN_ID has the value 0x5ca3 for all supported chips.
+ * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
+ * REG_MAN_ID is at port 0x4f
+ * REG_CHIP_ID is at port 0x58 */
 
 static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
 static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
@@ -429,7 +447,7 @@
 		}
 
 		/* Measured voltages and limits */
-		for (i = 0; i < 10; i++) {
+		for (i = 0; i < w83627ehf_num_in; i++) {
 			data->in[i] = w83627ehf_read_value(client,
 				      W83627EHF_REG_IN(i));
 			data->in_min[i] = w83627ehf_read_value(client,
@@ -1121,7 +1139,7 @@
 		device_remove_file(dev, &sda_sf3_arrays[i].dev_attr);
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
 		device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
-	for (i = 0; i < 10; i++) {
+	for (i = 0; i < w83627ehf_num_in; i++) {
 		device_remove_file(dev, &sda_in_input[i].dev_attr);
 		device_remove_file(dev, &sda_in_alarm[i].dev_attr);
 		device_remove_file(dev, &sda_in_min[i].dev_attr);
@@ -1196,7 +1214,11 @@
 	client->flags = 0;
 	dev = &client->dev;
 
-	strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
+	if (w83627ehf_num_in == 9)
+		strlcpy(client->name, "w83627dhg", I2C_NAME_SIZE);
+	else	/* just say ehf. 627EHG is 627EHF in lead-free packaging. */
+		strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
+
 	data->valid = 0;
 	mutex_init(&data->update_lock);
 
@@ -1246,7 +1268,7 @@
 				goto exit_remove;
 		}
 
-	for (i = 0; i < 10; i++)
+	for (i = 0; i < w83627ehf_num_in; i++)
 		if ((err = device_create_file(dev, &sda_in_input[i].dev_attr))
 			|| (err = device_create_file(dev,
 				&sda_in_alarm[i].dev_attr))
@@ -1340,7 +1362,17 @@
 
 	val = (superio_inb(SIO_REG_DEVID) << 8)
 	    | superio_inb(SIO_REG_DEVID + 1);
-	if ((val & SIO_ID_MASK) != SIO_W83627EHF_ID) {
+	switch (val & SIO_ID_MASK) {
+	case SIO_W83627DHG_ID:
+		w83627ehf_num_in = 9;
+		break;
+	case SIO_W83627EHF_ID:
+	case SIO_W83627EHG_ID:
+		w83627ehf_num_in = 10;
+		break;
+	default:
+		printk(KERN_WARNING "w83627ehf: unsupported chip ID: 0x%04x\n",
+			val);
 		superio_exit();
 		return -ENODEV;
 	}
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index dfdc29c7..d7e2406 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -286,9 +286,8 @@
 	return ((u8) i);
 }
 
-/* For each registered chip, we need to keep some data in memory. That
-   data is pointed to by w83627hf_list[NR]->data. The structure itself is
-   dynamically allocated, at the same time when a new client is allocated. */
+/* For each registered chip, we need to keep some data in memory.
+   The structure is dynamically allocated. */
 struct w83627hf_data {
 	struct i2c_client client;
 	struct class_device *class_dev;
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 1232171..a47da3e 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -221,14 +221,8 @@
    a bit - except if there could be more than one SMBus. Groan. No solution
    for this yet. */
 
-/* This module may seem overly long and complicated. In fact, it is not so
-   bad. Quite a lot of bookkeeping is done. A real driver can often cut
-   some corners. */
-
-/* For each registered W83781D, we need to keep some data in memory. That
-   data is pointed to by w83781d_list[NR]->data. The structure itself is
-   dynamically allocated, at the same time when a new w83781d client is
-   allocated. */
+/* For each registered chip, we need to keep some data in memory.
+   The structure is dynamically allocated. */
 struct w83781d_data {
 	struct i2c_client client;
 	struct class_device *class_dev;
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 9367c4c..4d44a2d 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -183,6 +183,7 @@
 	    ATI IXP200
 	    ATI IXP300
 	    ATI IXP400
+	    ATI SB600
 	    Serverworks OSB4
 	    Serverworks CSB5
 	    Serverworks CSB6
@@ -341,6 +342,13 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-parport-light.
 
+config I2C_PASEMI
+	tristate "PA Semi SMBus interface"
+#	depends on PPC_PASEMI && I2C && PCI
+	depends on I2C && PCI
+	help
+	  Supports the PA Semi PWRficient on-chip SMBus interfaces.
+
 config I2C_PROSAVAGE
 	tristate "S3/VIA (Pro)Savage"
 	depends on I2C && PCI
@@ -499,11 +507,11 @@
 	  will be called i2c-via.
 
 config I2C_VIAPRO
-	tristate "VIA 82C596/82C686/82xx"
+	tristate "VIA VT82C596/82C686/82xx and CX700"
 	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the VIA
-	  82C596/82C686/82xx I2C interfaces.  Specifically, the following
+	  VT82C596 and later SMBus interface.  Specifically, the following
 	  chipsets are supported:
 	    VT82C596A/B
 	    VT82C686A/B
@@ -512,6 +520,7 @@
 	    VT8235
 	    VT8237R/A
 	    VT8251
+	    CX700
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-viapro.
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 37196c1..03505aa 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -27,6 +27,7 @@
 obj-$(CONFIG_I2C_OMAP)		+= i2c-omap.o
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
+obj-$(CONFIG_I2C_PASEMI)	+= i2c-pasemi.o
 obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
 obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o
 obj-$(CONFIG_I2C_PNX)		+= i2c-pnx.o
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index e75d339..1e277ba 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -57,7 +57,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
@@ -475,6 +474,7 @@
 
 static struct i2c_adapter ali1535_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_SMBUS_ALI1535,
 	.class          = I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 };
@@ -494,7 +494,7 @@
 		return -ENODEV;
 	}
 
-	/* set up the driverfs linkage to our parent device */
+	/* set up the sysfs linkage to our parent device */
 	ali1535_adapter.dev.parent = &dev->dev;
 
 	snprintf(ali1535_adapter.name, I2C_NAME_SIZE, 
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index 8e1e3f8..6b68074 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -314,35 +314,11 @@
 }
 
 
-static void ali1563_enable(struct pci_dev * dev)
-{
-	u16 ctrl;
-
-	pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
-	ctrl |= 0x7;
-	pci_write_config_word(dev,ALI1563_SMBBA,ctrl);
-}
-
 static int __devinit ali1563_setup(struct pci_dev * dev)
 {
 	u16 ctrl;
 
 	pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
-	printk("ali1563: SMBus control = %04x\n",ctrl);
-
-	/* Check if device is even enabled first */
-	if (!(ctrl & ALI1563_SMB_IOEN)) {
-		dev_warn(&dev->dev,"I/O space not enabled, trying manually\n");
-		ali1563_enable(dev);
-	}
-	if (!(ctrl & ALI1563_SMB_IOEN)) {
-		dev_warn(&dev->dev,"I/O space still not enabled, giving up\n");
-		goto Err;
-	}
-	if (!(ctrl & ALI1563_SMB_HOSTEN)) {
-		dev_warn(&dev->dev,"Host Controller not enabled\n");
-		goto Err;
-	}
 
 	/* SMB I/O Base in high 12 bits and must be aligned with the
 	 * size of the I/O space. */
@@ -351,11 +327,31 @@
 		dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
 		goto Err;
 	}
-	if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
-			    ali1563_pci_driver.name)) {
-		dev_warn(&dev->dev,"Could not allocate I/O space");
+
+	/* Check if device is enabled */
+	if (!(ctrl & ALI1563_SMB_HOSTEN)) {
+		dev_warn(&dev->dev, "Host Controller not enabled\n");
 		goto Err;
 	}
+	if (!(ctrl & ALI1563_SMB_IOEN)) {
+		dev_warn(&dev->dev, "I/O space not enabled, trying manually\n");
+		pci_write_config_word(dev, ALI1563_SMBBA,
+				      ctrl | ALI1563_SMB_IOEN);
+		pci_read_config_word(dev, ALI1563_SMBBA, &ctrl);
+		if (!(ctrl & ALI1563_SMB_IOEN)) {
+			dev_err(&dev->dev, "I/O space still not enabled, "
+				"giving up\n");
+			goto Err;
+		}
+	}
+
+	if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
+			    ali1563_pci_driver.name)) {
+		dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n",
+			ali1563_smba);
+		goto Err;
+	}
+	dev_info(&dev->dev, "Found ALi1563 SMBus at 0x%04x\n", ali1563_smba);
 
 	return 0;
 Err:
@@ -374,6 +370,7 @@
 
 static struct i2c_adapter ali1563_adapter = {
 	.owner	= THIS_MODULE,
+	.id	= I2C_HW_SMBUS_ALI1563,
 	.class	= I2C_CLASS_HWMON,
 	.algo	= &ali1563_algorithm,
 };
@@ -384,13 +381,18 @@
 	int error;
 
 	if ((error = ali1563_setup(dev)))
-		return error;
+		goto exit;
 	ali1563_adapter.dev.parent = &dev->dev;
 	sprintf(ali1563_adapter.name,"SMBus ALi 1563 Adapter @ %04x",
 		ali1563_smba);
 	if ((error = i2c_add_adapter(&ali1563_adapter)))
-		ali1563_shutdown(dev);
-	printk("%s: Returning %d\n",__FUNCTION__,error);
+		goto exit_shutdown;
+	return 0;
+
+exit_shutdown:
+	ali1563_shutdown(dev);
+exit:
+	dev_warn(&dev->dev, "ALi1563 SMBus probe failed (%d)\n", error);
 	return error;
 }
 
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 3f11b6e..e47fe01 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -64,7 +64,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
@@ -470,6 +469,7 @@
 
 static struct i2c_adapter ali15x3_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_SMBUS_ALI15X3,
 	.class          = I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 };
@@ -489,7 +489,7 @@
 		return -ENODEV;
 	}
 
-	/* set up the driverfs linkage to our parent device */
+	/* set up the sysfs linkage to our parent device */
 	ali15x3_adapter.dev.parent = &dev->dev;
 
 	snprintf(ali15x3_adapter.name, I2C_NAME_SIZE,
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index 08e9157..e5e96c8 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -184,12 +184,14 @@
 	s4882_algo[0].smbus_xfer = amd756_access_virt0;
 	s4882_adapter[0] = amd756_smbus;
 	s4882_adapter[0].algo = s4882_algo;
+	s4882_adapter[0].dev.parent = amd756_smbus.dev.parent;
 	for (i = 1; i < 5; i++) {
 		s4882_algo[i] = *(amd756_smbus.algo);
 		s4882_adapter[i] = amd756_smbus;
 		sprintf(s4882_adapter[i].name,
 			"SMBus 8111 adapter (CPU%d)", i-1);
 		s4882_adapter[i].algo = s4882_algo+i;
+		s4882_adapter[i].dev.parent = amd756_smbus.dev.parent;
 	}
 	s4882_algo[1].smbus_xfer = amd756_access_virt1;
 	s4882_algo[2].smbus_xfer = amd756_access_virt2;
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 2d21afd..7490dc1 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -42,7 +42,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -301,6 +300,7 @@
 
 struct i2c_adapter amd756_smbus = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_SMBUS_AMD756,
 	.class          = I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 };
@@ -374,7 +374,7 @@
 	dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp);
 	dev_dbg(&pdev->dev, "AMD756_smba = 0x%X\n", amd756_ioport);
 
-	/* set up the driverfs linkage to our parent device */
+	/* set up the sysfs linkage to our parent device */
 	amd756_smbus.dev.parent = &pdev->dev;
 
 	sprintf(amd756_smbus.name, "SMBus %s adapter at %04x",
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 0fbc718..e15f9e3 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -12,7 +12,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
@@ -76,7 +75,8 @@
 		udelay(1);
 
 	if (!timeout) {
-		dev_warn(&smbus->dev->dev, "Timeout while waiting for IBF to clear\n");
+		dev_warn(&smbus->dev->dev,
+			 "Timeout while waiting for IBF to clear\n");
 		return -1;
 	}
 
@@ -91,14 +91,16 @@
 		udelay(1);
 
 	if (!timeout) {
-		dev_warn(&smbus->dev->dev, "Timeout while waiting for OBF to set\n");
+		dev_warn(&smbus->dev->dev,
+			 "Timeout while waiting for OBF to set\n");
 		return -1;
 	}
 
 	return 0;
 }
 
-static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data)
+static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
+		unsigned char *data)
 {
 	if (amd_ec_wait_write(smbus))
 		return -1;
@@ -115,7 +117,8 @@
 	return 0;
 }
 
-static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data)
+static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address,
+		unsigned char data)
 {
 	if (amd_ec_wait_write(smbus))
 		return -1;
@@ -175,18 +178,19 @@
 #define AMD_SMB_PRTCL_PEC		0x80
 
 
-static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
-		char read_write, u8 command, int size, union i2c_smbus_data * data)
+static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
+		unsigned short flags, char read_write, u8 command, int size,
+		union i2c_smbus_data * data)
 {
 	struct amd_smbus *smbus = adap->algo_data;
 	unsigned char protocol, len, pec, temp[2];
 	int i;
 
-	protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ : AMD_SMB_PRTCL_WRITE;
+	protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ
+						  : AMD_SMB_PRTCL_WRITE;
 	pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0;
 
 	switch (size) {
-
 		case I2C_SMBUS_QUICK:
 			protocol |= AMD_SMB_PRTCL_QUICK;
 			read_write = I2C_SMBUS_WRITE;
@@ -208,8 +212,10 @@
 		case I2C_SMBUS_WORD_DATA:
 			amd_ec_write(smbus, AMD_SMB_CMD, command);
 			if (read_write == I2C_SMBUS_WRITE) {
-				amd_ec_write(smbus, AMD_SMB_DATA, data->word);
-				amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8);
+				amd_ec_write(smbus, AMD_SMB_DATA,
+					     data->word & 0xff);
+				amd_ec_write(smbus, AMD_SMB_DATA + 1,
+					     data->word >> 8);
 			}
 			protocol |= AMD_SMB_PRTCL_WORD_DATA | pec;
 			break;
@@ -217,27 +223,31 @@
 		case I2C_SMBUS_BLOCK_DATA:
 			amd_ec_write(smbus, AMD_SMB_CMD, command);
 			if (read_write == I2C_SMBUS_WRITE) {
-				len = min_t(u8, data->block[0], 32);
+				len = min_t(u8, data->block[0],
+					    I2C_SMBUS_BLOCK_MAX);
 				amd_ec_write(smbus, AMD_SMB_BCNT, len);
 				for (i = 0; i < len; i++)
-					amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
+					amd_ec_write(smbus, AMD_SMB_DATA + i,
+						     data->block[i + 1]);
 			}
 			protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec;
 			break;
 
 		case I2C_SMBUS_I2C_BLOCK_DATA:
-			len = min_t(u8, data->block[0], 32);
+			len = min_t(u8, data->block[0],
+				    I2C_SMBUS_BLOCK_MAX);
 			amd_ec_write(smbus, AMD_SMB_CMD, command);
 			amd_ec_write(smbus, AMD_SMB_BCNT, len);
 			if (read_write == I2C_SMBUS_WRITE)
 				for (i = 0; i < len; i++)
-					amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
+					amd_ec_write(smbus, AMD_SMB_DATA + i,
+						     data->block[i + 1]);
 			protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA;
 			break;
 
 		case I2C_SMBUS_PROC_CALL:
 			amd_ec_write(smbus, AMD_SMB_CMD, command);
-			amd_ec_write(smbus, AMD_SMB_DATA, data->word);
+			amd_ec_write(smbus, AMD_SMB_DATA, data->word & 0xff);
 			amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8);
 			protocol = AMD_SMB_PRTCL_PROC_CALL | pec;
 			read_write = I2C_SMBUS_READ;
@@ -248,7 +258,8 @@
 			amd_ec_write(smbus, AMD_SMB_CMD, command);
 			amd_ec_write(smbus, AMD_SMB_BCNT, len);
 			for (i = 0; i < len; i++)
-				amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
+				amd_ec_write(smbus, AMD_SMB_DATA + i,
+					     data->block[i + 1]);
 			protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec;
 			read_write = I2C_SMBUS_READ;
 			break;
@@ -280,7 +291,6 @@
 		return 0;
 
 	switch (size) {
-
 		case I2C_SMBUS_BYTE:
 		case I2C_SMBUS_BYTE_DATA:
 			amd_ec_read(smbus, AMD_SMB_DATA, &data->byte);
@@ -296,10 +306,11 @@
 		case I2C_SMBUS_BLOCK_DATA:
 		case I2C_SMBUS_BLOCK_PROC_CALL:
 			amd_ec_read(smbus, AMD_SMB_BCNT, &len);
-			len = min_t(u8, len, 32);
+			len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
 		case I2C_SMBUS_I2C_BLOCK_DATA:
 			for (i = 0; i < len; i++)
-				amd_ec_read(smbus, AMD_SMB_DATA + i, data->block + i + 1);
+				amd_ec_read(smbus, AMD_SMB_DATA + i,
+					    data->block + i + 1);
 			data->block[0] = len;
 			break;
 	}
@@ -310,7 +321,8 @@
 
 static u32 amd8111_func(struct i2c_adapter *adapter)
 {
-	return	I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
+	return	I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
 		I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |
 		I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
 		I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC;
@@ -329,12 +341,13 @@
 
 MODULE_DEVICE_TABLE (pci, amd8111_ids);
 
-static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int __devinit amd8111_probe(struct pci_dev *dev,
+		const struct pci_device_id *id)
 {
 	struct amd_smbus *smbus;
-	int error = -ENODEV;
+	int error;
 
-	if (~pci_resource_flags(dev, 0) & IORESOURCE_IO)
+	if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
 		return -ENODEV;
 
 	smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL);
@@ -345,24 +358,27 @@
 	smbus->base = pci_resource_start(dev, 0);
 	smbus->size = pci_resource_len(dev, 0);
 
-	if (!request_region(smbus->base, smbus->size, amd8111_driver.name))
+	if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) {
+		error = -EBUSY;
 		goto out_kfree;
+	}
 
 	smbus->adapter.owner = THIS_MODULE;
 	snprintf(smbus->adapter.name, I2C_NAME_SIZE,
 		"SMBus2 AMD8111 adapter at %04x", smbus->base);
+	smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
 	smbus->adapter.class = I2C_CLASS_HWMON;
 	smbus->adapter.algo = &smbus_algorithm;
 	smbus->adapter.algo_data = smbus;
 
-	/* set up the driverfs linkage to our parent device */
+	/* set up the sysfs linkage to our parent device */
 	smbus->adapter.dev.parent = &dev->dev;
 
+	pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
 	error = i2c_add_adapter(&smbus->adapter);
 	if (error)
 		goto out_release_region;
 
-	pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
 	pci_set_drvdata(dev, smbus);
 	return 0;
 
@@ -370,10 +386,9 @@
 	release_region(smbus->base, smbus->size);
  out_kfree:
 	kfree(smbus);
-	return -1;
+	return error;
 }
 
-
 static void __devexit amd8111_remove(struct pci_dev *dev)
 {
 	struct amd_smbus *smbus = pci_get_drvdata(dev);
@@ -395,7 +410,6 @@
 	return pci_register_driver(&amd8111_driver);
 }
 
-
 static void __exit i2c_amd8111_exit(void)
 {
 	pci_unregister_driver(&amd8111_driver);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index ae625b8..6569a36 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -48,7 +48,6 @@
 #include <linux/kernel.h>
 #include <linux/stddef.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
@@ -123,7 +122,7 @@
 			dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
 			return -1;
 		} else {
-			dev_dbg(&I801_dev->dev, "Successfull!\n");
+			dev_dbg(&I801_dev->dev, "Successful!\n");
 		}
 	}
 
@@ -442,6 +441,7 @@
 
 static struct i2c_adapter i801_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_SMBUS_I801,
 	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 };
@@ -522,7 +522,7 @@
 	else
 		dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
 
-	/* set up the driverfs linkage to our parent device */
+	/* set up the sysfs linkage to our parent device */
 	i801_adapter.dev.parent = &dev->dev;
 
 	snprintf(i801_adapter.name, I2C_NAME_SIZE,
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
index 10c98bc..42e8d94 100644
--- a/drivers/i2c/busses/i2c-i810.c
+++ b/drivers/i2c/busses/i2c-i810.c
@@ -171,6 +171,7 @@
 
 static struct i2c_adapter i810_i2c_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_B_I810,
 	.name		= "I810/I815 I2C Adapter",
 	.algo_data	= &i810_i2c_bit_data,
 };
@@ -186,6 +187,7 @@
 
 static struct i2c_adapter i810_ddc_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_B_I810,
 	.name		= "I810/I815 DDC Adapter",
 	.algo_data	= &i810_ddc_bit_data,
 };
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 1898e99..8b14d14 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -727,6 +727,7 @@
 	
 	/* Register it with i2c layer */
 	adap = &dev->adap;
+	adap->dev.parent = &ocp->dev;
 	strcpy(adap->name, "IBM IIC");
 	i2c_set_adapdata(adap, dev);
 	adap->id = I2C_HW_OCP;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index d108ab4..90e2d93 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -36,7 +36,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 
@@ -84,7 +83,7 @@
 	 * Every time unit enable is asserted, GPOD needs to be cleared
 	 * on IOP3XX to avoid data corruption on the bus.
 	 */
-#ifdef CONFIG_PLAT_IOP
+#if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X)
 	if (iop3xx_adap->id == 0) {
 		gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW);
 		gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 8ed59a2..5f33bc9 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -39,6 +39,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-isa.h>
 #include <linux/platform_device.h>
+#include <linux/completion.h>
 
 static u32 isa_func(struct i2c_adapter *adapter);
 
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 4901736..a3283b9 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -520,6 +520,7 @@
 		rc = -ENXIO;
 		goto exit_unmap_regs;
 	}
+	drv_data->adapter.dev.parent = &pd->dev;
 	drv_data->adapter.id = I2C_HW_MV64XXX;
 	drv_data->adapter.algo = &mv64xxx_i2c_algo;
 	drv_data->adapter.owner = THIS_MODULE;
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index ad37c10..1514ec5 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -44,7 +44,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
@@ -57,7 +56,6 @@
 
 
 struct nforce2_smbus {
-	struct pci_dev *dev;
 	struct i2c_adapter adapter;
 	int base;
 	int size;
@@ -230,7 +228,6 @@
 		smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
 		smbus->size = 64;
 	}
-	smbus->dev = dev;
 
 	if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
 		dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
@@ -238,6 +235,7 @@
 		return -1;
 	}
 	smbus->adapter.owner = THIS_MODULE;
+	smbus->adapter.id = I2C_HW_SMBUS_NFORCE2;
 	smbus->adapter.class = I2C_CLASS_HWMON;
 	smbus->adapter.algo = &smbus_algorithm;
 	smbus->adapter.algo_data = smbus;
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index f28a76d..e417c2c 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -11,7 +11,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/platform_device.h>
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
index 9ddd816..ed69d84 100644
--- a/drivers/i2c/busses/i2c-parport.h
+++ b/drivers/i2c/busses/i2c-parport.h
@@ -88,6 +88,13 @@
 		.getscl	= { 0x40, STAT, 0 },
 		.init	= { 0xfc, DATA, 0 },
 	},
+	/* type 7: One For All JP1 parallel port adapter */
+	{
+		.setsda	= { 0x01, DATA, 0 },
+		.setscl	= { 0x02, DATA, 0 },
+		.getsda	= { 0x80, STAT, 1 },
+		.init	= { 0x04, DATA, 1 },
+	},
 };
 
 static int type = -1;
@@ -101,4 +108,5 @@
 	" 4 = ADM1032 evaluation board\n"
 	" 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n"
 	" 6 = Barco LPT->DVI (K5800236) adapter\n"
+	" 7 = One For All JP1 parallel port adapter\n"
 );
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
new file mode 100644
index 0000000..f54fb5d
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2006-2007 PA Semi, Inc
+ *
+ * SMBus host driver for PA Semi PWRficient
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+static struct pci_driver pasemi_smb_driver;
+
+struct pasemi_smbus {
+	struct pci_dev		*dev;
+	struct i2c_adapter	 adapter;
+	unsigned long		 base;
+	int			 size;
+};
+
+/* Register offsets */
+#define REG_MTXFIFO	0x00
+#define REG_MRXFIFO	0x04
+#define REG_SMSTA	0x14
+#define REG_CTL		0x1c
+
+/* Register defs */
+#define MTXFIFO_READ	0x00000400
+#define MTXFIFO_STOP	0x00000200
+#define MTXFIFO_START	0x00000100
+#define MTXFIFO_DATA_M	0x000000ff
+
+#define MRXFIFO_EMPTY	0x00000100
+#define MRXFIFO_DATA_M	0x000000ff
+
+#define SMSTA_XEN	0x08000000
+
+#define CTL_MRR		0x00000400
+#define CTL_MTR		0x00000200
+#define CTL_CLK_M	0x000000ff
+
+#define CLK_100K_DIV	84
+#define CLK_400K_DIV	21
+
+static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
+{
+	dev_dbg(&smbus->dev->dev, "smbus write reg %lx val %08x\n",
+		smbus->base + reg, val);
+	outl(val, smbus->base + reg);
+}
+
+static inline int reg_read(struct pasemi_smbus *smbus, int reg)
+{
+	int ret;
+	ret = inl(smbus->base + reg);
+	dev_dbg(&smbus->dev->dev, "smbus read reg %lx val %08x\n",
+		smbus->base + reg, ret);
+	return ret;
+}
+
+#define TXFIFO_WR(smbus, reg)	reg_write((smbus), REG_MTXFIFO, (reg))
+#define RXFIFO_RD(smbus)	reg_read((smbus), REG_MRXFIFO)
+
+static void pasemi_smb_clear(struct pasemi_smbus *smbus)
+{
+	unsigned int status;
+
+	status = reg_read(smbus, REG_SMSTA);
+	reg_write(smbus, REG_SMSTA, status);
+}
+
+static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus)
+{
+	int timeout = 10;
+	unsigned int status;
+
+	status = reg_read(smbus, REG_SMSTA);
+
+	while (!(status & SMSTA_XEN) && timeout--) {
+		msleep(1);
+		status = reg_read(smbus, REG_SMSTA);
+	}
+
+	if (timeout < 0) {
+		dev_warn(&smbus->dev->dev, "Timeout, status 0x%08x\n", status);
+		reg_write(smbus, REG_SMSTA, status);
+		return -ETIME;
+	}
+
+	/* Clear XEN */
+	reg_write(smbus, REG_SMSTA, SMSTA_XEN);
+
+	return 0;
+}
+
+static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter,
+			       struct i2c_msg *msg, int stop)
+{
+	struct pasemi_smbus *smbus = adapter->algo_data;
+	int read, i, err;
+	u32 rd;
+
+	read = msg->flags & I2C_M_RD ? 1 : 0;
+
+	TXFIFO_WR(smbus, MTXFIFO_START | (msg->addr << 1) | read);
+
+	if (read) {
+		TXFIFO_WR(smbus, msg->len | MTXFIFO_READ |
+				 (stop ? MTXFIFO_STOP : 0));
+
+		err = pasemi_smb_waitready(smbus);
+		if (err)
+			goto reset_out;
+
+		for (i = 0; i < msg->len; i++) {
+			rd = RXFIFO_RD(smbus);
+			if (rd & MRXFIFO_EMPTY) {
+				err = -ENODATA;
+				goto reset_out;
+			}
+			msg->buf[i] = rd & MRXFIFO_DATA_M;
+		}
+	} else {
+		for (i = 0; i < msg->len - 1; i++)
+			TXFIFO_WR(smbus, msg->buf[i]);
+
+		TXFIFO_WR(smbus, msg->buf[msg->len] |
+			  (stop ? MTXFIFO_STOP : 0));
+	}
+
+	return 0;
+
+ reset_out:
+	reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
+		  (CLK_100K_DIV & CTL_CLK_M)));
+	return err;
+}
+
+static int pasemi_i2c_xfer(struct i2c_adapter *adapter,
+			   struct i2c_msg *msgs, int num)
+{
+	struct pasemi_smbus *smbus = adapter->algo_data;
+	int ret, i;
+
+	pasemi_smb_clear(smbus);
+
+	ret = 0;
+
+	for (i = 0; i < num && !ret; i++)
+		ret = pasemi_i2c_xfer_msg(adapter, &msgs[i], (i == (num - 1)));
+
+	return ret ? ret : num;
+}
+
+static int pasemi_smb_xfer(struct i2c_adapter *adapter,
+		u16 addr, unsigned short flags, char read_write, u8 command,
+		int size, union i2c_smbus_data *data)
+{
+	struct pasemi_smbus *smbus = adapter->algo_data;
+	unsigned int rd;
+	int read_flag, err;
+	int len = 0, i;
+
+	/* All our ops take 8-bit shifted addresses */
+	addr <<= 1;
+	read_flag = read_write == I2C_SMBUS_READ;
+
+	pasemi_smb_clear(smbus);
+
+	switch (size) {
+	case I2C_SMBUS_QUICK:
+		TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START |
+			  MTXFIFO_STOP);
+		break;
+	case I2C_SMBUS_BYTE:
+		TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START);
+		if (read_write)
+			TXFIFO_WR(smbus, 1 | MTXFIFO_STOP | MTXFIFO_READ);
+		else
+			TXFIFO_WR(smbus, MTXFIFO_STOP | command);
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		TXFIFO_WR(smbus, addr | MTXFIFO_START);
+		TXFIFO_WR(smbus, command);
+		if (read_write) {
+			TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
+			TXFIFO_WR(smbus, 1 | MTXFIFO_READ | MTXFIFO_STOP);
+		} else {
+			TXFIFO_WR(smbus, MTXFIFO_STOP | data->byte);
+		}
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		TXFIFO_WR(smbus, addr | MTXFIFO_START);
+		TXFIFO_WR(smbus, command);
+		if (read_write) {
+			TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
+			TXFIFO_WR(smbus, 2 | MTXFIFO_READ | MTXFIFO_STOP);
+		} else {
+			TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M);
+			TXFIFO_WR(smbus, MTXFIFO_STOP | (data->word >> 8));
+		}
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		TXFIFO_WR(smbus, addr | MTXFIFO_START);
+		TXFIFO_WR(smbus, command);
+		if (read_write) {
+			TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
+			TXFIFO_WR(smbus, 1 | MTXFIFO_READ);
+			rd = RXFIFO_RD(smbus);
+			len = min_t(u8, (rd & MRXFIFO_DATA_M),
+				    I2C_SMBUS_BLOCK_MAX);
+			TXFIFO_WR(smbus, (len + 1) | MTXFIFO_READ |
+					 MTXFIFO_STOP);
+		} else {
+			len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX);
+			TXFIFO_WR(smbus, len);
+			for (i = 1; i < len; i++)
+				TXFIFO_WR(smbus, data->block[i]);
+			TXFIFO_WR(smbus, data->block[len] | MTXFIFO_STOP);
+		}
+		break;
+	case I2C_SMBUS_PROC_CALL:
+		read_write = I2C_SMBUS_READ;
+		TXFIFO_WR(smbus, addr | MTXFIFO_START);
+		TXFIFO_WR(smbus, command);
+		TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M);
+		TXFIFO_WR(smbus, (data->word >> 8) & MTXFIFO_DATA_M);
+		TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
+		TXFIFO_WR(smbus, 2 | MTXFIFO_STOP | MTXFIFO_READ);
+		break;
+	case I2C_SMBUS_BLOCK_PROC_CALL:
+		len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX - 1);
+		read_write = I2C_SMBUS_READ;
+		TXFIFO_WR(smbus, addr | MTXFIFO_START);
+		TXFIFO_WR(smbus, command);
+		TXFIFO_WR(smbus, len);
+		for (i = 1; i <= len; i++)
+			TXFIFO_WR(smbus, data->block[i]);
+		TXFIFO_WR(smbus, addr | I2C_SMBUS_READ);
+		TXFIFO_WR(smbus, MTXFIFO_READ | 1);
+		rd = RXFIFO_RD(smbus);
+		len = min_t(u8, (rd & MRXFIFO_DATA_M),
+			    I2C_SMBUS_BLOCK_MAX - len);
+		TXFIFO_WR(smbus, (len + 1) | MTXFIFO_READ | MTXFIFO_STOP);
+		break;
+
+	default:
+		dev_warn(&adapter->dev, "Unsupported transaction %d\n", size);
+		return -EINVAL;
+	}
+
+	err = pasemi_smb_waitready(smbus);
+	if (err)
+		goto reset_out;
+
+	if (read_write == I2C_SMBUS_WRITE)
+		return 0;
+
+	switch (size) {
+	case I2C_SMBUS_BYTE:
+	case I2C_SMBUS_BYTE_DATA:
+		rd = RXFIFO_RD(smbus);
+		if (rd & MRXFIFO_EMPTY) {
+			err = -ENODATA;
+			goto reset_out;
+		}
+		data->byte = rd & MRXFIFO_DATA_M;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+	case I2C_SMBUS_PROC_CALL:
+		rd = RXFIFO_RD(smbus);
+		if (rd & MRXFIFO_EMPTY) {
+			err = -ENODATA;
+			goto reset_out;
+		}
+		data->word = rd & MRXFIFO_DATA_M;
+		rd = RXFIFO_RD(smbus);
+		if (rd & MRXFIFO_EMPTY) {
+			err = -ENODATA;
+			goto reset_out;
+		}
+		data->word |= (rd & MRXFIFO_DATA_M) << 8;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+	case I2C_SMBUS_BLOCK_PROC_CALL:
+		data->block[0] = len;
+		for (i = 1; i <= len; i ++) {
+			rd = RXFIFO_RD(smbus);
+			if (rd & MRXFIFO_EMPTY) {
+				err = -ENODATA;
+				goto reset_out;
+			}
+			data->block[i] = rd & MRXFIFO_DATA_M;
+		}
+		break;
+	}
+
+	return 0;
+
+ reset_out:
+	reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
+		  (CLK_100K_DIV & CTL_CLK_M)));
+	return err;
+}
+
+static u32 pasemi_smb_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	       I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL |
+	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_I2C;
+}
+
+static const struct i2c_algorithm smbus_algorithm = {
+	.master_xfer	= pasemi_i2c_xfer,
+	.smbus_xfer	= pasemi_smb_xfer,
+	.functionality	= pasemi_smb_func,
+};
+
+static int __devinit pasemi_smb_probe(struct pci_dev *dev,
+				      const struct pci_device_id *id)
+{
+	struct pasemi_smbus *smbus;
+	int error;
+
+	if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
+		return -ENODEV;
+
+	smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL);
+	if (!smbus)
+		return -ENOMEM;
+
+	smbus->dev = dev;
+	smbus->base = pci_resource_start(dev, 0);
+	smbus->size = pci_resource_len(dev, 0);
+
+	if (!request_region(smbus->base, smbus->size,
+			    pasemi_smb_driver.name)) {
+		error = -EBUSY;
+		goto out_kfree;
+	}
+
+	smbus->adapter.owner = THIS_MODULE;
+	snprintf(smbus->adapter.name, I2C_NAME_SIZE,
+		 "PA Semi SMBus adapter at 0x%lx", smbus->base);
+	smbus->adapter.class = I2C_CLASS_HWMON;
+	smbus->adapter.algo = &smbus_algorithm;
+	smbus->adapter.algo_data = smbus;
+
+	/* set up the driverfs linkage to our parent device */
+	smbus->adapter.dev.parent = &dev->dev;
+
+	reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
+		  (CLK_100K_DIV & CTL_CLK_M)));
+
+	error = i2c_add_adapter(&smbus->adapter);
+	if (error)
+		goto out_release_region;
+
+	pci_set_drvdata(dev, smbus);
+
+	return 0;
+
+ out_release_region:
+	release_region(smbus->base, smbus->size);
+ out_kfree:
+	kfree(smbus);
+	return error;
+}
+
+static void __devexit pasemi_smb_remove(struct pci_dev *dev)
+{
+	struct pasemi_smbus *smbus = pci_get_drvdata(dev);
+
+	i2c_del_adapter(&smbus->adapter);
+	release_region(smbus->base, smbus->size);
+	kfree(smbus);
+}
+
+static struct pci_device_id pasemi_smb_ids[] = {
+	{ PCI_DEVICE(0x1959, 0xa003) },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, pasemi_smb_ids);
+
+static struct pci_driver pasemi_smb_driver = {
+	.name		= "i2c-pasemi",
+	.id_table	= pasemi_smb_ids,
+	.probe		= pasemi_smb_probe,
+	.remove		= __devexit_p(pasemi_smb_remove),
+};
+
+static int __init pasemi_smb_init(void)
+{
+	return pci_register_driver(&pasemi_smb_driver);
+}
+
+static void __exit pasemi_smb_exit(void)
+{
+	pci_unregister_driver(&pasemi_smb_driver);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver");
+
+module_init(pasemi_smb_init);
+module_exit(pasemi_smb_exit);
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 30c7a1b..21b1809 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -23,6 +23,7 @@
    Supports:
 	Intel PIIX4, 440MX
 	Serverworks OSB4, CSB5, CSB6, HT-1000
+	ATI IXP200, IXP300, IXP400, SB600
 	SMSC Victory66
 
    Note: we assume there can only be one device, with one SMBus interface.
@@ -34,7 +35,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -383,6 +383,7 @@
 
 static struct i2c_adapter piix4_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_SMBUS_PIIX4,
 	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 };
@@ -396,6 +397,8 @@
 	  .driver_data = 0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS),
 	  .driver_data = 0 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SMBUS),
+	  .driver_data = 0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
 	  .driver_data = 0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
@@ -422,7 +425,7 @@
 	if (retval)
 		return retval;
 
-	/* set up the driverfs linkage to our parent device */
+	/* set up the sysfs linkage to our parent device */
 	piix4_adapter.dev.parent = &dev->dev;
 
 	snprintf(piix4_adapter.name, I2C_NAME_SIZE,
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 648d555..1425d224 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -25,7 +25,6 @@
 #include <linux/types.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
-#include <linux/completion.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <asm/prom.h>
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index c3b1567..14e83d0 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -34,6 +34,7 @@
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/io.h>
 #include <asm/arch/i2c.h>
 #include <asm/arch/pxa-regs.h>
 
@@ -54,8 +55,21 @@
 	unsigned int		irqlogidx;
 	u32			isrlog[32];
 	u32			icrlog[32];
+
+	void __iomem		*reg_base;
+
+	unsigned long		iobase;
+	unsigned long		iosize;
+
+	int			irq;
 };
 
+#define _IBMR(i2c)	((i2c)->reg_base + 0)
+#define _IDBR(i2c)	((i2c)->reg_base + 8)
+#define _ICR(i2c)	((i2c)->reg_base + 0x10)
+#define _ISR(i2c)	((i2c)->reg_base + 0x18)
+#define _ISAR(i2c)	((i2c)->reg_base + 0x20)
+
 /*
  * I2C Slave mode address
  */
@@ -130,7 +144,8 @@
 
 static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
 {
-	dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, ISR, ICR, IBMR);
+	dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno,
+		readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
 }
 
 #define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__)
@@ -153,7 +168,7 @@
 	printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
 		i2c->msg_num, i2c->msg_idx, i2c->msg_ptr);
 	printk("i2c: ICR: %08x ISR: %08x\n"
-	       "i2c: log: ", ICR, ISR);
+	       "i2c: log: ", readl(_ICR(i2c)), readl(_ISR(i2c)));
 	for (i = 0; i < i2c->irqlogidx; i++)
 		printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
 	printk("\n");
@@ -161,7 +176,7 @@
 
 static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
 {
-	return !(ICR & ICR_SCLE);
+	return !(readl(_ICR(i2c)) & ICR_SCLE);
 }
 
 static void i2c_pxa_abort(struct pxa_i2c *i2c)
@@ -173,28 +188,29 @@
 		return;
 	}
 
-	while (time_before(jiffies, timeout) && (IBMR & 0x1) == 0) {
-		unsigned long icr = ICR;
+	while (time_before(jiffies, timeout) && (readl(_IBMR(i2c)) & 0x1) == 0) {
+		unsigned long icr = readl(_ICR(i2c));
 
 		icr &= ~ICR_START;
 		icr |= ICR_ACKNAK | ICR_STOP | ICR_TB;
 
-		ICR = icr;
+		writel(icr, _ICR(i2c));
 
 		show_state(i2c);
 
 		msleep(1);
 	}
 
-	ICR &= ~(ICR_MA | ICR_START | ICR_STOP);
+	writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP),
+	       _ICR(i2c));
 }
 
 static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
 {
 	int timeout = DEF_TIMEOUT;
 
-	while (timeout-- && ISR & (ISR_IBB | ISR_UB)) {
-		if ((ISR & ISR_SAD) != 0)
+	while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
+		if ((readl(_ISR(i2c)) & ISR_SAD) != 0)
 			timeout += 4;
 
 		msleep(2);
@@ -214,9 +230,9 @@
 	while (time_before(jiffies, timeout)) {
 		if (i2c_debug > 1)
 			dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
-				__func__, (long)jiffies, ISR, ICR, IBMR);
+				__func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
 
-		if (ISR & ISR_SAD) {
+		if (readl(_ISR(i2c)) & ISR_SAD) {
 			if (i2c_debug > 0)
 				dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__);
 			goto out;
@@ -226,7 +242,7 @@
 		 * quick check of the i2c lines themselves to ensure they've
 		 * gone high...
 		 */
-		if ((ISR & (ISR_UB | ISR_IBB)) == 0 && IBMR == 3) {
+		if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 && readl(_IBMR(i2c)) == 3) {
 			if (i2c_debug > 0)
 				dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
 			return 1;
@@ -246,7 +262,7 @@
 	if (i2c_debug)
 		dev_dbg(&i2c->adap.dev, "setting to bus master\n");
 
-	if ((ISR & (ISR_UB | ISR_IBB)) != 0) {
+	if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) != 0) {
 		dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__);
 		if (!i2c_pxa_wait_master(i2c)) {
 			dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__);
@@ -254,7 +270,7 @@
 		}
 	}
 
-	ICR |= ICR_SCLE;
+	writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
 	return 0;
 }
 
@@ -270,11 +286,11 @@
 	while (time_before(jiffies, timeout)) {
 		if (i2c_debug > 1)
 			dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
-				__func__, (long)jiffies, ISR, ICR, IBMR);
+				__func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
 
-		if ((ISR & (ISR_UB|ISR_IBB)) == 0 ||
-		    (ISR & ISR_SAD) != 0 ||
-		    (ICR & ICR_SCLE) == 0) {
+		if ((readl(_ISR(i2c)) & (ISR_UB|ISR_IBB)) == 0 ||
+		    (readl(_ISR(i2c)) & ISR_SAD) != 0 ||
+		    (readl(_ICR(i2c)) & ICR_SCLE) == 0) {
 			if (i2c_debug > 1)
 				dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
 			return 1;
@@ -302,9 +318,9 @@
 		/* we need to wait for the stop condition to end */
 
 		/* if we where in stop, then clear... */
-		if (ICR & ICR_STOP) {
+		if (readl(_ICR(i2c)) & ICR_STOP) {
 			udelay(100);
-			ICR &= ~ICR_STOP;
+			writel(readl(_ICR(i2c)) & ~ICR_STOP, _ICR(i2c));
 		}
 
 		if (!i2c_pxa_wait_slave(i2c)) {
@@ -314,12 +330,12 @@
 		}
 	}
 
-	ICR &= ~(ICR_STOP|ICR_ACKNAK|ICR_MA);
-	ICR &= ~ICR_SCLE;
+	writel(readl(_ICR(i2c)) & ~(ICR_STOP|ICR_ACKNAK|ICR_MA), _ICR(i2c));
+	writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
 
 	if (i2c_debug) {
-		dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", ICR, ISR);
-		decode_ICR(ICR);
+		dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", readl(_ICR(i2c)), readl(_ISR(i2c)));
+		decode_ICR(readl(_ICR(i2c)));
 	}
 }
 #else
@@ -334,24 +350,24 @@
 	i2c_pxa_abort(i2c);
 
 	/* reset according to 9.8 */
-	ICR = ICR_UR;
-	ISR = I2C_ISR_INIT;
-	ICR &= ~ICR_UR;
+	writel(ICR_UR, _ICR(i2c));
+	writel(I2C_ISR_INIT, _ISR(i2c));
+	writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
 
-	ISAR = i2c->slave_addr;
+	writel(i2c->slave_addr, _ISAR(i2c));
 
 	/* set control register values */
-	ICR = I2C_ICR_INIT;
+	writel(I2C_ICR_INIT, _ICR(i2c));
 
 #ifdef CONFIG_I2C_PXA_SLAVE
 	dev_info(&i2c->adap.dev, "Enabling slave mode\n");
-	ICR |= ICR_SADIE | ICR_ALDIE | ICR_SSDIE;
+	writel(readl(_ICR(i2c)) | ICR_SADIE | ICR_ALDIE | ICR_SSDIE, _ICR(i2c));
 #endif
 
 	i2c_pxa_set_slave(i2c, 0);
 
 	/* enable unit */
-	ICR |= ICR_IUE;
+	writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
 	udelay(100);
 }
 
@@ -371,19 +387,19 @@
 		if (i2c->slave != NULL)
 			ret = i2c->slave->read(i2c->slave->data);
 
-		IDBR = ret;
-		ICR |= ICR_TB;   /* allow next byte */
+		writel(ret, _IDBR(i2c));
+		writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));   /* allow next byte */
 	}
 }
 
 static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
 {
-	unsigned int byte = IDBR;
+	unsigned int byte = readl(_IDBR(i2c));
 
 	if (i2c->slave != NULL)
 		i2c->slave->write(i2c->slave->data, byte);
 
-	ICR |= ICR_TB;
+	writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
 }
 
 static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
@@ -403,13 +419,13 @@
 	 * start condition... if this happens, we'd better back off
 	 * and stop holding the poor thing up
 	 */
-	ICR &= ~(ICR_START|ICR_STOP);
-	ICR |= ICR_TB;
+	writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c));
+	writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
 
 	timeout = 0x10000;
 
 	while (1) {
-		if ((IBMR & 2) == 2)
+		if ((readl(_IBMR(i2c)) & 2) == 2)
 			break;
 
 		timeout--;
@@ -420,7 +436,7 @@
 		}
 	}
 
-	ICR &= ~ICR_SCLE;
+	writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
 }
 
 static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
@@ -447,14 +463,14 @@
 	if (isr & ISR_BED) {
 		/* what should we do here? */
 	} else {
-		IDBR = 0;
-		ICR |= ICR_TB;
+		writel(0, _IDBR(i2c));
+		writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
 	}
 }
 
 static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
 {
-	ICR |= ICR_TB | ICR_ACKNAK;
+	writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c));
 }
 
 static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
@@ -466,13 +482,13 @@
 	 * start condition... if this happens, we'd better back off
 	 * and stop holding the poor thing up
 	 */
-	ICR &= ~(ICR_START|ICR_STOP);
-	ICR |= ICR_TB | ICR_ACKNAK;
+	writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c));
+	writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c));
 
 	timeout = 0x10000;
 
 	while (1) {
-		if ((IBMR & 2) == 2)
+		if ((readl(_IBMR(i2c)) & 2) == 2)
 			break;
 
 		timeout--;
@@ -483,7 +499,7 @@
 		}
 	}
 
-	ICR &= ~ICR_SCLE;
+	writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
 }
 
 static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
@@ -514,13 +530,13 @@
 	/*
 	 * Step 1: target slave address into IDBR
 	 */
-	IDBR = i2c_pxa_addr_byte(i2c->msg);
+	writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c));
 
 	/*
 	 * Step 2: initiate the write.
 	 */
-	icr = ICR & ~(ICR_STOP | ICR_ALDIE);
-	ICR = icr | ICR_START | ICR_TB;
+	icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE);
+	writel(icr | ICR_START | ICR_TB, _ICR(i2c));
 }
 
 /*
@@ -594,7 +610,7 @@
 
 static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
 {
-	u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
+	u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
 
  again:
 	/*
@@ -645,7 +661,7 @@
 		/*
 		 * Write mode.  Write the next data byte.
 		 */
-		IDBR = i2c->msg->buf[i2c->msg_ptr++];
+		writel(i2c->msg->buf[i2c->msg_ptr++], _IDBR(i2c));
 
 		icr |= ICR_ALDIE | ICR_TB;
 
@@ -675,7 +691,7 @@
 		/*
 		 * Write the next address.
 		 */
-		IDBR = i2c_pxa_addr_byte(i2c->msg);
+		writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c));
 
 		/*
 		 * And trigger a repeated start, and send the byte.
@@ -696,18 +712,18 @@
 
 	i2c->icrlog[i2c->irqlogidx-1] = icr;
 
-	ICR = icr;
+	writel(icr, _ICR(i2c));
 	show_state(i2c);
 }
 
 static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
 {
-	u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
+	u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
 
 	/*
 	 * Read the byte.
 	 */
-	i2c->msg->buf[i2c->msg_ptr++] = IDBR;
+	i2c->msg->buf[i2c->msg_ptr++] = readl(_IDBR(i2c));
 
 	if (i2c->msg_ptr < i2c->msg->len) {
 		/*
@@ -724,17 +740,17 @@
 
 	i2c->icrlog[i2c->irqlogidx-1] = icr;
 
-	ICR = icr;
+	writel(icr, _ICR(i2c));
 }
 
 static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
 {
 	struct pxa_i2c *i2c = dev_id;
-	u32 isr = ISR;
+	u32 isr = readl(_ISR(i2c));
 
 	if (i2c_debug > 2 && 0) {
 		dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n",
-			__func__, isr, ICR, IBMR);
+			__func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c)));
 		decode_ISR(isr);
 	}
 
@@ -746,7 +762,7 @@
 	/*
 	 * Always clear all pending IRQs.
 	 */
-	ISR = isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED);
+	writel(isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED), _ISR(i2c));
 
 	if (isr & ISR_SAD)
 		i2c_pxa_slave_start(i2c, isr);
@@ -779,7 +795,7 @@
 	/* If the I2C controller is disabled we need to reset it (probably due
  	   to a suspend/resume destroying state). We do this here as we can then
  	   avoid worrying about resuming the controller before its users. */
-	if (!(ICR & ICR_IUE))
+	if (!(readl(_ICR(i2c)) & ICR_IUE))
 		i2c_pxa_reset(i2c);
 
 	for (i = adap->retries; i >= 0; i--) {
@@ -810,28 +826,53 @@
 
 static struct pxa_i2c i2c_pxa = {
 	.lock	= SPIN_LOCK_UNLOCKED,
-	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait),
 	.adap	= {
 		.owner		= THIS_MODULE,
 		.algo		= &i2c_pxa_algorithm,
-		.name		= "pxa2xx-i2c",
+		.name		= "pxa2xx-i2c.0",
 		.retries	= 5,
 	},
 };
 
+#define res_len(r)		((r)->end - (r)->start + 1)
 static int i2c_pxa_probe(struct platform_device *dev)
 {
 	struct pxa_i2c *i2c = &i2c_pxa;
+	struct resource *res;
 #ifdef CONFIG_I2C_PXA_SLAVE
 	struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
 #endif
 	int ret;
+	int irq;
 
-#ifdef CONFIG_PXA27x
-	pxa_gpio_mode(GPIO117_I2CSCL_MD);
-	pxa_gpio_mode(GPIO118_I2CSDA_MD);
-	udelay(100);
-#endif
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	irq = platform_get_irq(dev, 0);
+	if (res == NULL || irq < 0)
+		return -ENODEV;
+
+	if (!request_mem_region(res->start, res_len(res), res->name))
+		return -ENOMEM;
+
+	i2c = kmalloc(sizeof(struct pxa_i2c), GFP_KERNEL);
+	if (!i2c) {
+		ret = -ENOMEM;
+		goto emalloc;
+	}
+
+	memcpy(i2c, &i2c_pxa, sizeof(struct pxa_i2c));
+	init_waitqueue_head(&i2c->wait);
+	i2c->adap.name[strlen(i2c->adap.name) - 1] = '0' + dev->id % 10;
+
+	i2c->reg_base = ioremap(res->start, res_len(res));
+	if (!i2c->reg_base) {
+		ret = -EIO;
+		goto eremap;
+	}
+
+	i2c->iobase = res->start;
+	i2c->iosize = res_len(res);
+
+	i2c->irq = irq;
 
 	i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
 
@@ -842,11 +883,28 @@
 	}
 #endif
 
-	pxa_set_cken(CKEN14_I2C, 1);
-	ret = request_irq(IRQ_I2C, i2c_pxa_handler, IRQF_DISABLED,
-			  "pxa2xx-i2c", i2c);
+	switch (dev->id) {
+	case 0:
+#ifdef CONFIG_PXA27x
+		pxa_gpio_mode(GPIO117_I2CSCL_MD);
+		pxa_gpio_mode(GPIO118_I2CSDA_MD);
+#endif
+		pxa_set_cken(CKEN14_I2C, 1);
+		break;
+#ifdef CONFIG_PXA27x
+	case 1:
+		local_irq_disable();
+		PCFR |= PCFR_PI2CEN;
+		local_irq_enable();
+		pxa_set_cken(CKEN15_PWRI2C, 1);
+#endif
+	}
+
+	ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
+			  i2c->adap.name, i2c);
 	if (ret)
-		goto out;
+		goto ereqirq;
+
 
 	i2c_pxa_reset(i2c);
 
@@ -856,7 +914,7 @@
 	ret = i2c_add_adapter(&i2c->adap);
 	if (ret < 0) {
 		printk(KERN_INFO "I2C: Failed to add bus\n");
-		goto err_irq;
+		goto eadapt;
 	}
 
 	platform_set_drvdata(dev, i2c);
@@ -870,9 +928,25 @@
 #endif
 	return 0;
 
- err_irq:
-	free_irq(IRQ_I2C, i2c);
- out:
+eadapt:
+	free_irq(irq, i2c);
+ereqirq:
+	switch (dev->id) {
+	case 0:
+		pxa_set_cken(CKEN14_I2C, 0);
+		break;
+#ifdef CONFIG_PXA27x
+	case 1:
+		pxa_set_cken(CKEN15_PWRI2C, 0);
+		local_irq_disable();
+		PCFR &= ~PCFR_PI2CEN;
+		local_irq_enable();
+#endif
+	}
+eremap:
+	kfree(i2c);
+emalloc:
+	release_mem_region(res->start, res_len(res));
 	return ret;
 }
 
@@ -883,8 +957,21 @@
 	platform_set_drvdata(dev, NULL);
 
 	i2c_del_adapter(&i2c->adap);
-	free_irq(IRQ_I2C, i2c);
-	pxa_set_cken(CKEN14_I2C, 0);
+	free_irq(i2c->irq, i2c);
+	switch (dev->id) {
+	case 0:
+		pxa_set_cken(CKEN14_I2C, 0);
+		break;
+#ifdef CONFIG_PXA27x
+	case 1:
+		pxa_set_cken(CKEN15_PWRI2C, 0);
+		local_irq_disable();
+		PCFR &= ~PCFR_PI2CEN;
+		local_irq_enable();
+#endif
+	}
+	release_mem_region(i2c->iobase, i2c->iosize);
+	kfree(i2c);
 
 	return 0;
 }
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 4ca6de2..556f244 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -28,7 +28,6 @@
 #include <linux/init.h>
 #include <linux/time.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/err.h>
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index 844b4ff..b7fb65c 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -145,6 +145,7 @@
 
 static struct i2c_adapter savage4_i2c_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_B_SAVAGE,
 	.name		= "I2C Savage4 adapter",
 	.algo_data	= &sav_i2c_bit_data,
 };
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 38bbfd8..a6feed4 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -365,6 +365,7 @@
 
 static struct i2c_adapter sis5595_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_SMBUS_SIS5595,
 	.class          = I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 };
@@ -383,7 +384,7 @@
 		return -ENODEV;
 	}
 
-	/* set up the driverfs linkage to our parent device */
+	/* set up the sysfs linkage to our parent device */
 	sis5595_adapter.dev.parent = &dev->dev;
 
 	sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index dec0baf..5fd734f 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -457,6 +457,7 @@
 
 static struct i2c_adapter sis630_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_SMBUS_SIS630,
 	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 };
@@ -476,7 +477,7 @@
 		return -ENODEV;
 	}
 
-	/* set up the driverfs linkage to our parent device */
+	/* set up the sysfs linkage to our parent device */
 	sis630_adapter.dev.parent = &dev->dev;
 
 	sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x",
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 7fd07fb..4157b0c 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -249,6 +248,7 @@
 
 static struct i2c_adapter sis96x_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_SMBUS_SIS96X,
 	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 };
@@ -297,7 +297,7 @@
 		return -EINVAL;
 	}
 
-	/* set up the driverfs linkage to our parent device */
+	/* set up the sysfs linkage to our parent device */
 	sis96x_adapter.dev.parent = &dev->dev;
 
 	snprintf(sis96x_adapter.name, I2C_NAME_SIZE,
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 15d7e00..8152086 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -86,6 +86,7 @@
 
 static struct i2c_adapter vt586b_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_B_VIA,
 	.class          = I2C_CLASS_HWMON,
 	.name		= "VIA i2c",
 	.algo_data	= &bit_data,
@@ -137,7 +138,7 @@
 	outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR);
 	outb(inb(I2C_OUT) & ~(I2C_SDA | I2C_SCL), I2C_OUT);
 
-	/* set up the driverfs linkage to our parent device */
+	/* set up the sysfs linkage to our parent device */
 	vt586b_adapter.dev.parent = &dev->dev;
 
 	res = i2c_bit_add_bus(&vt586b_adapter);
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index efc6bbf..03c5fc8 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -4,7 +4,7 @@
     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
     Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
     Mark D. Studebaker <mdsxyz123@yahoo.com>
-    Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2005 - 2007  Jean Delvare <khali@linux-fr.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
@@ -36,6 +36,7 @@
    VT8237R            0x3227             yes
    VT8237A            0x3337             yes
    VT8251             0x3287             yes
+   CX700              0x8324             yes
 
    Note: we assume there can only be one device, with one SMBus interface.
 */
@@ -306,6 +307,7 @@
 
 static struct i2c_adapter vt596_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_SMBUS_VIA2,
 	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 };
@@ -383,6 +385,7 @@
 	dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
 
 	switch (pdev->device) {
+	case PCI_DEVICE_ID_VIA_CX700:
 	case PCI_DEVICE_ID_VIA_8251:
 	case PCI_DEVICE_ID_VIA_8237:
 	case PCI_DEVICE_ID_VIA_8237A:
@@ -442,6 +445,8 @@
 	  .driver_data = SMBBA1 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
 	  .driver_data = SMBBA3 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700),
+	  .driver_data = SMBBA3 },
 	{ 0, }
 };
 
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index b0377b8..88a3447 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -165,6 +165,7 @@
 
 static struct i2c_adapter voodoo3_i2c_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_B_VOO,
 	.class		= I2C_CLASS_TV_ANALOG, 
 	.name		= "I2C Voodoo3/Banshee adapter",
 	.algo_data	= &voo_i2c_bit_data,
@@ -181,6 +182,7 @@
 
 static struct i2c_adapter voodoo3_ddc_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_B_VOO,
 	.class		= I2C_CLASS_DDC, 
 	.name		= "DDC Voodoo3/Banshee adapter",
 	.algo_data	= &voo_ddc_bit_data,
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 714bae7..0b082c5 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -428,7 +428,7 @@
 }
 
 static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
-		int index)
+		struct device *dev, int index)
 {
 	struct scx200_acb_iface *iface;
 	struct i2c_adapter *adapter;
@@ -446,6 +446,7 @@
 	adapter->id = I2C_HW_SMBUS_SCX200;
 	adapter->algo = &scx200_acb_algorithm;
 	adapter->class = I2C_CLASS_HWMON;
+	adapter->dev.parent = dev;
 
 	mutex_init(&iface->mutex);
 
@@ -486,7 +487,7 @@
 	struct scx200_acb_iface *iface;
 	int rc;
 
-	iface = scx200_create_iface(text, 0);
+	iface = scx200_create_iface(text, &pdev->dev, 0);
 
 	if (iface == NULL)
 		return -ENOMEM;
@@ -524,7 +525,7 @@
 	struct scx200_acb_iface *iface;
 	int rc;
 
-	iface = scx200_create_iface(text, index);
+	iface = scx200_create_iface(text, NULL, index);
 
 	if (iface == NULL)
 		return -ENOMEM;
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
index 6cd96e4..c3022a0 100644
--- a/drivers/i2c/busses/scx200_i2c.c
+++ b/drivers/i2c/busses/scx200_i2c.c
@@ -81,6 +81,7 @@
 
 static struct i2c_adapter scx200_i2c_ops = {
 	.owner		   = THIS_MODULE,
+	.id		   = I2C_HW_B_SCX200,
 	.algo_data	   = &scx200_i2c_data,
 	.name	= "NatSemi SCx200 I2C",
 };
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index cec3a0c..bfce13c 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -30,7 +30,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 4ee56de..214fbb1 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -308,7 +308,7 @@
 	return single_open(file, dbg_show, inode->i_private);
 }
 
-static struct file_operations debug_fops = {
+static const struct file_operations debug_fops = {
 	.open		= dbg_tps_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index b05378a3..21fe140 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -32,6 +32,7 @@
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
+#include <linux/completion.h>
 #include <asm/uaccess.h>
 
 
@@ -40,30 +41,15 @@
 static DEFINE_MUTEX(core_lists);
 static DEFINE_IDR(i2c_adapter_idr);
 
+
+/* ------------------------------------------------------------------------- */
+
 /* match always succeeds, as we want the probe() to tell if we really accept this match */
 static int i2c_device_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
 }
 
-static int i2c_bus_suspend(struct device * dev, pm_message_t state)
-{
-	int rc = 0;
-
-	if (dev->driver && dev->driver->suspend)
-		rc = dev->driver->suspend(dev, state);
-	return rc;
-}
-
-static int i2c_bus_resume(struct device * dev)
-{
-	int rc = 0;
-	
-	if (dev->driver && dev->driver->resume)
-		rc = dev->driver->resume(dev);
-	return rc;
-}
-
 static int i2c_device_probe(struct device *dev)
 {
 	return -ENODEV;
@@ -74,15 +60,53 @@
 	return 0;
 }
 
+static void i2c_device_shutdown(struct device *dev)
+{
+	struct i2c_driver *driver;
+
+	if (!dev->driver)
+		return;
+	driver = to_i2c_driver(dev->driver);
+	if (driver->shutdown)
+		driver->shutdown(to_i2c_client(dev));
+}
+
+static int i2c_device_suspend(struct device * dev, pm_message_t mesg)
+{
+	struct i2c_driver *driver;
+
+	if (!dev->driver)
+		return 0;
+	driver = to_i2c_driver(dev->driver);
+	if (!driver->suspend)
+		return 0;
+	return driver->suspend(to_i2c_client(dev), mesg);
+}
+
+static int i2c_device_resume(struct device * dev)
+{
+	struct i2c_driver *driver;
+
+	if (!dev->driver)
+		return 0;
+	driver = to_i2c_driver(dev->driver);
+	if (!driver->resume)
+		return 0;
+	return driver->resume(to_i2c_client(dev));
+}
+
 struct bus_type i2c_bus_type = {
-	.name =		"i2c",
-	.match =	i2c_device_match,
-	.probe =	i2c_device_probe,
-	.remove =	i2c_device_remove,
-	.suspend =      i2c_bus_suspend,
-	.resume =       i2c_bus_resume,
+	.name		= "i2c",
+	.match		= i2c_device_match,
+	.probe		= i2c_device_probe,
+	.remove		= i2c_device_remove,
+	.shutdown	= i2c_device_shutdown,
+	.suspend	= i2c_device_suspend,
+	.resume		= i2c_device_resume,
 };
 
+/* ------------------------------------------------------------------------- */
+
 void i2c_adapter_dev_release(struct device *dev)
 {
 	struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
@@ -193,9 +217,8 @@
 	 */
 	if (adap->dev.parent == NULL) {
 		adap->dev.parent = &platform_bus;
-		printk(KERN_WARNING "**WARNING** I2C adapter driver [%s] "
-		       "forgot to specify physical device; fix it!\n",
-		       adap->name);
+		pr_debug("I2C adapter driver [%s] forgot to specify "
+			 "physical device\n", adap->name);
 	}
 	sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
 	adap->dev.driver = &i2c_adapter_driver;
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index ac5bd2a..cb4fa9b 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -392,7 +392,7 @@
 	return 0;
 }
 
-static struct file_operations i2cdev_fops = {
+static const struct file_operations i2cdev_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= i2cdev_read,
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index ec03341..49234e3 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -383,6 +383,9 @@
 config BLK_DEV_GENERIC
 	tristate "Generic PCI IDE Chipset Support"
 	depends on BLK_DEV_IDEPCI
+        help
+          This option provides generic support for various PCI IDE Chipsets
+          which otherwise might not be supported.
 
 config BLK_DEV_OPTI621
 	tristate "OPTi 82C621 chipset enhanced support (EXPERIMENTAL)"
@@ -797,6 +800,14 @@
 	  to transfer data to and from memory.  Saying Y is safe and improves
 	  performance.
 
+config BLK_DEV_IDE_CELLEB
+	bool "Toshiba's Cell Reference Set IDE support"
+	depends on PPC_CELLEB
+	help
+	  This driver provides support for the built-in IDE controller on
+	  Toshiba Cell Reference Board.
+	  If unsure, say Y.
+
 config BLK_DEV_IDE_SWARM
 	tristate "IDE for Sibyte evaluation boards"
 	depends on SIBYTE_SB1xxx_SOC
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index d9f029e..28feedf 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -37,6 +37,7 @@
 # built-in only drivers from ppc/
 ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE)	+= ppc/mpc8xx.o
 ide-core-$(CONFIG_BLK_DEV_IDE_PMAC)	+= ppc/pmac.o
+ide-core-$(CONFIG_BLK_DEV_IDE_CELLEB)	+= ppc/scc_pata.o
 
 # built-in only drivers from h8300/
 ide-core-$(CONFIG_H8300)		+= h8300/ide-h8300.o
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 8a1c27f..40e5c66 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -307,26 +307,24 @@
 	return on;
 }
 
-static int icside_dma_host_off(ide_drive_t *drive)
+static void icside_dma_host_off(ide_drive_t *drive)
 {
-	return 0;
 }
 
-static int icside_dma_off_quietly(ide_drive_t *drive)
+static void icside_dma_off_quietly(ide_drive_t *drive)
 {
 	drive->using_dma = 0;
-	return icside_dma_host_off(drive);
 }
 
-static int icside_dma_host_on(ide_drive_t *drive)
+static void icside_dma_host_on(ide_drive_t *drive)
 {
-	return 0;
 }
 
 static int icside_dma_on(ide_drive_t *drive)
 {
 	drive->using_dma = 1;
-	return icside_dma_host_on(drive);
+
+	return 0;
 }
 
 static int icside_dma_check(ide_drive_t *drive)
@@ -365,10 +363,7 @@
 out:
 	on = icside_set_speed(drive, xfer_mode);
 
-	if (on)
-		return icside_dma_on(drive);
-	else
-		return icside_dma_off_quietly(drive);
+	return on ? 0 : -1;
 }
 
 static int icside_dma_end(ide_drive_t *drive)
@@ -497,9 +492,9 @@
 	hwif->autodma		= autodma;
 
 	hwif->ide_dma_check	= icside_dma_check;
-	hwif->ide_dma_host_off	= icside_dma_host_off;
-	hwif->ide_dma_off_quietly = icside_dma_off_quietly;
-	hwif->ide_dma_host_on	= icside_dma_host_on;
+	hwif->dma_host_off	= icside_dma_host_off;
+	hwif->dma_off_quietly	= icside_dma_off_quietly;
+	hwif->dma_host_on	= icside_dma_host_on;
 	hwif->ide_dma_on	= icside_dma_on;
 	hwif->dma_setup		= icside_dma_setup;
 	hwif->dma_exec_cmd	= icside_dma_exec_cmd;
@@ -556,7 +551,7 @@
 		 * Ensure we're using MMIO
 		 */
 		default_hwif_mmiops(hwif);
-		hwif->mmio = 2;
+		hwif->mmio = 1;
 
 		for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
 			hwif->hw.io_ports[i] = port;
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index 3058217..9c6c49f 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -46,7 +46,7 @@
 	hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
 	hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
 	hwif->hw.irq = hwif->irq = irq;
-	hwif->mmio = 2;
+	hwif->mmio = 1;
 	default_hwif_mmiops(hwif);
 
 	return hwif;
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index 5797e0b..6b2d152 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -682,9 +682,12 @@
 static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int);
 static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int);
 static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int);
-static int cris_dma_off (ide_drive_t *drive);
 static int cris_dma_on (ide_drive_t *drive);
 
+static void cris_dma_off(ide_drive_t *drive)
+{
+}
+
 static void tune_cris_ide(ide_drive_t *drive, u8 pio)
 {
 	int setup, strobe, hold;
@@ -795,7 +798,7 @@
 		                0, 0, cris_ide_ack_intr,
 		                ide_default_irq(0));
 		ide_register_hw(&hw, &hwif);
-		hwif->mmio = 2;
+		hwif->mmio = 1;
 		hwif->chipset = ide_etrax100;
 		hwif->tuneproc = &tune_cris_ide;
 		hwif->speedproc = &speed_cris_ide;
@@ -814,13 +817,16 @@
 		hwif->OUTBSYNC = &cris_ide_outbsync;
 		hwif->INB = &cris_ide_inb;
 		hwif->INW = &cris_ide_inw;
-		hwif->ide_dma_host_off = &cris_dma_off;
-		hwif->ide_dma_host_on = &cris_dma_on;
-		hwif->ide_dma_off_quietly = &cris_dma_off;
+		hwif->dma_host_off = &cris_dma_off;
+		hwif->dma_host_on = &cris_dma_on;
+		hwif->dma_off_quietly = &cris_dma_off;
 		hwif->udma_four = 0;
 		hwif->ultra_mask = cris_ultra_mask;
 		hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
 		hwif->swdma_mask = 0x07; /* Singleword DMA 0-2 */
+		hwif->autodma = 1;
+		hwif->drives[0].autodma = 1;
+		hwif->drives[1].autodma = 1;
 	}
 
 	/* Reset pulse */
@@ -835,11 +841,6 @@
 	cris_ide_set_speed(TYPE_UDMA, ATA_UDMA2_CYC, ATA_UDMA2_DVS, 0);
 }
 
-static int cris_dma_off (ide_drive_t *drive)
-{
-	return 0;
-}
-
 static int cris_dma_on (ide_drive_t *drive)
 {
 	return 0;
@@ -1045,17 +1046,10 @@
 
 static int cris_dma_check(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
-	struct hd_driveid* id = drive->id;
+	if (ide_use_dma(drive) && cris_config_drive_for_dma(drive))
+		return 0;
 
-	if (id && (id->capability & 1)) {
-		if (ide_use_dma(drive)) {
-			if (cris_config_drive_for_dma(drive))
-				return hwif->ide_dma_on(drive);
-		}
-	}
-
-	return hwif->ide_dma_off_quietly(drive);
+	return -1;
 }
 
 static int cris_dma_end(ide_drive_t *drive)
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
index 608ca87..88750a3 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/h8300/ide-h8300.c
@@ -76,13 +76,11 @@
 {
 	default_hwif_iops(hwif);
 
-	hwif->mmio  = 2;
+	hwif->mmio  = 1;
 	hwif->OUTW  = mm_outw;
 	hwif->OUTSW = mm_outsw;
 	hwif->INW   = mm_inw;
 	hwif->INSW  = mm_insw;
-	hwif->OUTL  = NULL;
-	hwif->INL   = NULL;
 	hwif->OUTSL = NULL;
 	hwif->INSL  = NULL;
 }
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 5969cec..45a928c 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -687,15 +687,8 @@
 static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
 {
 	struct request *rq = HWGROUP(drive)->rq;
-	ide_hwif_t *hwif = HWIF(drive);
 	int stat, err, sense_key;
 	
-	/* We may have bogus DMA interrupts in PIO state here */
-	if (HWIF(drive)->dma_status && hwif->atapi_irq_bogon) {
-		stat = hwif->INB(hwif->dma_status);
-		/* Should we force the bit as well ? */
-		hwif->OUTB(stat, hwif->dma_status);
-	}
 	/* Check for errors. */
 	stat = HWIF(drive)->INB(IDE_STATUS_REG);
 	if (stat_ret)
@@ -930,6 +923,10 @@
 		HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
  
 	if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
+		/* waiting for CDB interrupt, not DMA yet. */
+		if (info->dma)
+			drive->waiting_for_dma = 0;
+
 		/* packet command */
 		ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
 		return ide_started;
@@ -972,6 +969,10 @@
 		/* Check for errors. */
 		if (cdrom_decode_status(drive, DRQ_STAT, NULL))
 			return ide_stopped;
+
+		/* Ok, next interrupt will be DMA interrupt. */
+		if (info->dma)
+			drive->waiting_for_dma = 1;
 	} else {
 		/* Otherwise, we must wait for DRQ to get set. */
 		if (ide_wait_stat(&startstop, drive, DRQ_STAT,
@@ -1103,7 +1104,7 @@
 	if (dma) {
 		info->dma = 0;
 		if ((dma_error = HWIF(drive)->ide_dma_end(drive)))
-			__ide_dma_off(drive);
+			ide_dma_off(drive);
 	}
 
 	if (cdrom_decode_status(drive, 0, &stat))
@@ -1699,7 +1700,7 @@
 	if (dma) {
 		if (dma_error) {
 			printk(KERN_ERR "ide-cd: dma error\n");
-			__ide_dma_off(drive);
+			ide_dma_off(drive);
 			return ide_error(drive, "dma error", stat);
 		}
 
@@ -1825,7 +1826,7 @@
 		info->dma = 0;
 		if ((dma_error = HWIF(drive)->ide_dma_end(drive))) {
 			printk(KERN_ERR "ide-cd: write dma error\n");
-			__ide_dma_off(drive);
+			ide_dma_off(drive);
 		}
 	}
 
@@ -3254,14 +3255,6 @@
 	if (drive->autotune == IDE_TUNE_DEFAULT ||
 	    drive->autotune == IDE_TUNE_AUTO)
 		drive->dsc_overlap = (drive->next != drive);
-#if 0
-	drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1;
-	if (HWIF(drive)->no_dsc) {
-		printk(KERN_INFO "ide-cd: %s: disabling DSC overlap\n",
-			drive->name);
-		drive->dsc_overlap = 0;
-	}
-#endif
 
 	if (ide_cdrom_register(drive, nslots)) {
 		printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
@@ -3360,21 +3353,16 @@
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct cdrom_info *info;
-	ide_drive_t *drive;
 	int rc = -ENOMEM;
 
 	if (!(info = ide_cd_get(disk)))
 		return -ENXIO;
 
-	drive = info->drive;
-
-	drive->usage++;
-
 	if (!info->buffer)
-		info->buffer = kmalloc(SECTOR_BUFFER_SIZE,
-					GFP_KERNEL|__GFP_REPEAT);
-        if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file)))
-		drive->usage--;
+		info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
+
+	if (info->buffer)
+		rc = cdrom_open(&info->devinfo, inode, file);
 
 	if (rc < 0)
 		ide_cd_put(info);
@@ -3386,10 +3374,8 @@
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct cdrom_info *info = ide_cd_g(disk);
-	ide_drive_t *drive = info->drive;
 
 	cdrom_release (&info->devinfo, file);
-	drive->usage--;
 
 	ide_cd_put(info);
 
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 0a05a37..e2cea18 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -77,6 +77,7 @@
 	ide_driver_t	*driver;
 	struct gendisk	*disk;
 	struct kref	kref;
+	unsigned int	openers;	/* protected by BKL for now */
 };
 
 static DEFINE_MUTEX(idedisk_ref_mutex);
@@ -1081,8 +1082,9 @@
 
 	drive = idkp->drive;
 
-	drive->usage++;
-	if (drive->removable && drive->usage == 1) {
+	idkp->openers++;
+
+	if (drive->removable && idkp->openers == 1) {
 		ide_task_t args;
 		memset(&args, 0, sizeof(ide_task_t));
 		args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
@@ -1106,9 +1108,10 @@
 	struct ide_disk_obj *idkp = ide_disk_g(disk);
 	ide_drive_t *drive = idkp->drive;
 
-	if (drive->usage == 1)
+	if (idkp->openers == 1)
 		ide_cacheflush_p(drive);
-	if (drive->removable && drive->usage == 1) {
+
+	if (drive->removable && idkp->openers == 1) {
 		ide_task_t args;
 		memset(&args, 0, sizeof(ide_task_t));
 		args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK;
@@ -1117,7 +1120,8 @@
 		if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
 			drive->doorlocking = 0;
 	}
-	drive->usage--;
+
+	idkp->openers--;
 
 	ide_disk_put(idkp);
 
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 56efed6..08e7cd0 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -348,15 +348,14 @@
 static int config_drive_for_dma (ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
-	ide_hwif_t *hwif = HWIF(drive);
 
-	if ((id->capability & 1) && hwif->autodma) {
+	if ((id->capability & 1) && drive->hwif->autodma) {
 		/*
 		 * Enable DMA on any drive that has
 		 * UltraDMA (mode 0/1/2/3/4/5/6) enabled
 		 */
 		if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f))
-			return hwif->ide_dma_on(drive);
+			return 0;
 		/*
 		 * Enable DMA on any drive that has mode2 DMA
 		 * (multi or single) enabled
@@ -364,14 +363,14 @@
 		if (id->field_valid & 2)	/* regular DMA */
 			if ((id->dma_mword & 0x404) == 0x404 ||
 			    (id->dma_1word & 0x404) == 0x404)
-				return hwif->ide_dma_on(drive);
+				return 0;
 
 		/* Consult the list of known "good" drives */
 		if (__ide_dma_good_drive(drive))
-			return hwif->ide_dma_on(drive);
+			return 0;
 	}
-//	if (hwif->tuneproc != NULL) hwif->tuneproc(drive, 255);
-	return hwif->ide_dma_off_quietly(drive);
+
+	return -1;
 }
 
 /**
@@ -415,72 +414,68 @@
 }
 
 /**
- *	__ide_dma_host_off	-	Generic DMA kill
+ *	ide_dma_host_off	-	Generic DMA kill
  *	@drive: drive to control
  *
  *	Perform the generic IDE controller DMA off operation. This
  *	works for most IDE bus mastering controllers
  */
 
-int __ide_dma_host_off (ide_drive_t *drive)
+void ide_dma_host_off(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	u8 unit			= (drive->select.b.unit & 0x01);
 	u8 dma_stat		= hwif->INB(hwif->dma_status);
 
 	hwif->OUTB((dma_stat & ~(1<<(5+unit))), hwif->dma_status);
-	return 0;
 }
 
-EXPORT_SYMBOL(__ide_dma_host_off);
+EXPORT_SYMBOL(ide_dma_host_off);
 
 /**
- *	__ide_dma_host_off_quietly	-	Generic DMA kill
+ *	ide_dma_off_quietly	-	Generic DMA kill
  *	@drive: drive to control
  *
  *	Turn off the current DMA on this IDE controller. 
  */
 
-int __ide_dma_off_quietly (ide_drive_t *drive)
+void ide_dma_off_quietly(ide_drive_t *drive)
 {
 	drive->using_dma = 0;
 	ide_toggle_bounce(drive, 0);
 
-	if (HWIF(drive)->ide_dma_host_off(drive))
-		return 1;
-
-	return 0;
+	drive->hwif->dma_host_off(drive);
 }
 
-EXPORT_SYMBOL(__ide_dma_off_quietly);
+EXPORT_SYMBOL(ide_dma_off_quietly);
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
 
 /**
- *	__ide_dma_off	-	disable DMA on a device
+ *	ide_dma_off	-	disable DMA on a device
  *	@drive: drive to disable DMA on
  *
  *	Disable IDE DMA for a device on this IDE controller.
  *	Inform the user that DMA has been disabled.
  */
 
-int __ide_dma_off (ide_drive_t *drive)
+void ide_dma_off(ide_drive_t *drive)
 {
 	printk(KERN_INFO "%s: DMA disabled\n", drive->name);
-	return HWIF(drive)->ide_dma_off_quietly(drive);
+	drive->hwif->dma_off_quietly(drive);
 }
 
-EXPORT_SYMBOL(__ide_dma_off);
+EXPORT_SYMBOL(ide_dma_off);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 /**
- *	__ide_dma_host_on	-	Enable DMA on a host
+ *	ide_dma_host_on	-	Enable DMA on a host
  *	@drive: drive to enable for DMA
  *
  *	Enable DMA on an IDE controller following generic bus mastering
  *	IDE controller behaviour
  */
- 
-int __ide_dma_host_on (ide_drive_t *drive)
+
+void ide_dma_host_on(ide_drive_t *drive)
 {
 	if (drive->using_dma) {
 		ide_hwif_t *hwif	= HWIF(drive);
@@ -488,12 +483,10 @@
 		u8 dma_stat		= hwif->INB(hwif->dma_status);
 
 		hwif->OUTB((dma_stat|(1<<(5+unit))), hwif->dma_status);
-		return 0;
 	}
-	return 1;
 }
 
-EXPORT_SYMBOL(__ide_dma_host_on);
+EXPORT_SYMBOL(ide_dma_host_on);
 
 /**
  *	__ide_dma_on		-	Enable DMA on a device
@@ -511,8 +504,7 @@
 	drive->using_dma = 1;
 	ide_toggle_bounce(drive, 1);
 
-	if (HWIF(drive)->ide_dma_host_on(drive))
-		return 1;
+	drive->hwif->dma_host_on(drive);
 
 	return 0;
 }
@@ -565,7 +557,10 @@
 	}
 
 	/* PRD table */
-	hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable);
+	if (hwif->mmio)
+		writel(hwif->dmatable_dma, (void __iomem *)hwif->dma_prdtable);
+	else
+		outl(hwif->dmatable_dma, hwif->dma_prdtable);
 
 	/* specify r/w */
 	hwif->OUTB(reading, hwif->dma_command);
@@ -680,6 +675,9 @@
 	struct hd_driveid *id = drive->id;
 	ide_hwif_t *hwif = drive->hwif;
 
+	if ((id->capability & 1) == 0 || drive->autodma == 0)
+		return 0;
+
 	/* consult the list of known "bad" drives */
 	if (__ide_dma_bad_drive(drive))
 		return 0;
@@ -753,12 +751,37 @@
 	return;
 bug_dma_off:
 	printk(", BUG DMA OFF");
-	hwif->ide_dma_off_quietly(drive);
+	hwif->dma_off_quietly(drive);
 	return;
 }
 
 EXPORT_SYMBOL(ide_dma_verbose);
 
+int ide_set_dma(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	int rc;
+
+	rc = hwif->ide_dma_check(drive);
+
+	switch(rc) {
+	case -1: /* DMA needs to be disabled */
+		hwif->dma_off_quietly(drive);
+		return 0;
+	case  0: /* DMA needs to be enabled */
+		return hwif->ide_dma_on(drive);
+	case  1: /* DMA setting cannot be changed */
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(ide_set_dma);
+
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 int __ide_dma_lostirq (ide_drive_t *drive)
 {
@@ -809,7 +832,7 @@
 {
 	ide_release_dma_engine(hwif);
 
-	if (hwif->mmio == 2)
+	if (hwif->mmio)
 		return 1;
 	else
 		return ide_release_iomio_dma(hwif);
@@ -878,9 +901,9 @@
 
 static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
 {
-	if (hwif->mmio == 2)
+	if (hwif->mmio)
 		return ide_mapped_mmio_dma(hwif, base,ports);
-	BUG_ON(hwif->mmio == 1);
+
 	return ide_iomio_dma(hwif, base, ports);
 }
 
@@ -908,14 +931,14 @@
 	if (!(hwif->dma_prdtable))
 		hwif->dma_prdtable	= (hwif->dma_base + 4);
 
-	if (!hwif->ide_dma_off_quietly)
-		hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;
-	if (!hwif->ide_dma_host_off)
-		hwif->ide_dma_host_off = &__ide_dma_host_off;
+	if (!hwif->dma_off_quietly)
+		hwif->dma_off_quietly = &ide_dma_off_quietly;
+	if (!hwif->dma_host_off)
+		hwif->dma_host_off = &ide_dma_host_off;
 	if (!hwif->ide_dma_on)
 		hwif->ide_dma_on = &__ide_dma_on;
-	if (!hwif->ide_dma_host_on)
-		hwif->ide_dma_host_on = &__ide_dma_host_on;
+	if (!hwif->dma_host_on)
+		hwif->dma_host_on = &ide_dma_host_on;
 	if (!hwif->ide_dma_check)
 		hwif->ide_dma_check = &__ide_dma_check;
 	if (!hwif->dma_setup)
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index d33717c..57cd21c 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -279,6 +279,7 @@
 	ide_driver_t	*driver;
 	struct gendisk	*disk;
 	struct kref	kref;
+	unsigned int	openers;	/* protected by BKL for now */
 
 	/* Current packet command */
 	idefloppy_pc_t *pc;
@@ -866,7 +867,7 @@
 	if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
 		printk(KERN_ERR "ide-floppy: The floppy wants to issue "
 			"more interrupts in DMA mode\n");
-		(void)__ide_dma_off(drive);
+		ide_dma_off(drive);
 		return ide_do_reset(drive);
 	}
 
@@ -1096,9 +1097,9 @@
 	pc->current_position = pc->buffer;
 	bcount.all = min(pc->request_transfer, 63 * 1024);
 
-	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
-		(void)__ide_dma_off(drive);
-	}
+	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags))
+		ide_dma_off(drive);
+
 	feature.all = 0;
 
 	if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
@@ -1433,7 +1434,8 @@
 	
 	drive->bios_cyl = 0;
 	drive->bios_head = drive->bios_sect = 0;
-	floppy->blocks = floppy->bs_factor = 0;
+	floppy->blocks = 0;
+	floppy->bs_factor = 1;
 	set_capacity(floppy->disk, 0);
 
 	idefloppy_create_read_capacity_cmd(&pc);
@@ -1949,9 +1951,9 @@
 
 	drive = floppy->drive;
 
-	drive->usage++;
+	floppy->openers++;
 
-	if (drive->usage == 1) {
+	if (floppy->openers == 1) {
 		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
 		/* Just in case */
 
@@ -1969,13 +1971,11 @@
 		    ** capacity of the drive or begin the format - Sam
 		    */
 		    ) {
-			drive->usage--;
 			ret = -EIO;
 			goto out_put_floppy;
 		}
 
 		if (floppy->wp && (filp->f_mode & 2)) {
-			drive->usage--;
 			ret = -EROFS;
 			goto out_put_floppy;
 		}
@@ -1987,13 +1987,13 @@
 		}
 		check_disk_change(inode->i_bdev);
 	} else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {
-		drive->usage--;
 		ret = -EBUSY;
 		goto out_put_floppy;
 	}
 	return 0;
 
 out_put_floppy:
+	floppy->openers--;
 	ide_floppy_put(floppy);
 	return ret;
 }
@@ -2007,7 +2007,7 @@
 	
 	debug_log(KERN_INFO "Reached idefloppy_release\n");
 
-	if (drive->usage == 1) {
+	if (floppy->openers == 1) {
 		/* IOMEGA Clik! drives do not support lock/unlock commands */
                 if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
 			idefloppy_create_prevent_cmd(&pc, 0);
@@ -2016,7 +2016,8 @@
 
 		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
 	}
-	drive->usage--;
+
+	floppy->openers--;
 
 	ide_floppy_put(floppy);
 
@@ -2050,7 +2051,7 @@
 		prevent = 0;
 		/* fall through */
 	case CDROM_LOCKDOOR:
-		if (drive->usage > 1)
+		if (floppy->openers > 1)
 			return -EBUSY;
 
 		/* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
@@ -2072,7 +2073,7 @@
 		if (!(file->f_mode & 2))
 			return -EPERM;
 
-		if (drive->usage > 1) {
+		if (floppy->openers > 1) {
 			/* Don't format if someone is using the disk */
 
 			clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 2614f41..c193553 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -226,7 +226,7 @@
 			break;
 		if (drive->hwif->ide_dma_check == NULL)
 			break;
-		drive->hwif->ide_dma_check(drive);
+		ide_set_dma(drive);
 		break;
 	}
 	pm->pm_step = ide_pm_state_completed;
@@ -1351,7 +1351,7 @@
 	 */
 	drive->retry_pio++;
 	drive->state = DMA_PIO_RETRY;
-	(void) hwif->ide_dma_off_quietly(drive);
+	hwif->dma_off_quietly(drive);
 
 	/*
 	 * un-busy drive etc (hwgroup->busy is cleared on return) and
@@ -1646,6 +1646,17 @@
 	del_timer(&hwgroup->timer);
 	spin_unlock(&ide_lock);
 
+	/* Some controllers might set DMA INTR no matter DMA or PIO;
+	 * bmdma status might need to be cleared even for
+	 * PIO interrupts to prevent spurious/lost irq.
+	 */
+	if (hwif->ide_dma_clear_irq && !(drive->waiting_for_dma))
+		/* ide_dma_end() needs bmdma status for error checking.
+		 * So, skip clearing bmdma status here and leave it
+		 * to ide_dma_end() if this is dma interrupt.
+		 */
+		hwif->ide_dma_clear_irq(drive);
+
 	if (drive->unmask)
 		local_irq_enable_in_hardirq();
 	/* service this interrupt, may set handler for next interrupt */
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index badde63..c67b3b1 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -49,11 +49,6 @@
 	insw(port, addr, count);
 }
 
-static u32 ide_inl (unsigned long port)
-{
-	return (u32) inl(port);
-}
-
 static void ide_insl (unsigned long port, void *addr, u32 count)
 {
 	insl(port, addr, count);
@@ -79,11 +74,6 @@
 	outsw(port, addr, count);
 }
 
-static void ide_outl (u32 val, unsigned long port)
-{
-	outl(val, port);
-}
-
 static void ide_outsl (unsigned long port, void *addr, u32 count)
 {
 	outsl(port, addr, count);
@@ -94,12 +84,10 @@
 	hwif->OUTB	= ide_outb;
 	hwif->OUTBSYNC	= ide_outbsync;
 	hwif->OUTW	= ide_outw;
-	hwif->OUTL	= ide_outl;
 	hwif->OUTSW	= ide_outsw;
 	hwif->OUTSL	= ide_outsl;
 	hwif->INB	= ide_inb;
 	hwif->INW	= ide_inw;
-	hwif->INL	= ide_inl;
 	hwif->INSW	= ide_insw;
 	hwif->INSL	= ide_insl;
 }
@@ -123,11 +111,6 @@
 	__ide_mm_insw((void __iomem *) port, addr, count);
 }
 
-static u32 ide_mm_inl (unsigned long port)
-{
-	return (u32) readl((void __iomem *) port);
-}
-
 static void ide_mm_insl (unsigned long port, void *addr, u32 count)
 {
 	__ide_mm_insl((void __iomem *) port, addr, count);
@@ -153,11 +136,6 @@
 	__ide_mm_outsw((void __iomem *) port, addr, count);
 }
 
-static void ide_mm_outl (u32 value, unsigned long port)
-{
-	writel(value, (void __iomem *) port);
-}
-
 static void ide_mm_outsl (unsigned long port, void *addr, u32 count)
 {
 	__ide_mm_outsl((void __iomem *) port, addr, count);
@@ -170,12 +148,10 @@
 	   this one is controller specific! */
 	hwif->OUTBSYNC	= ide_mm_outbsync;
 	hwif->OUTW	= ide_mm_outw;
-	hwif->OUTL	= ide_mm_outl;
 	hwif->OUTSW	= ide_mm_outsw;
 	hwif->OUTSL	= ide_mm_outsl;
 	hwif->INB	= ide_mm_inb;
 	hwif->INW	= ide_mm_inw;
-	hwif->INL	= ide_mm_inl;
 	hwif->INSW	= ide_mm_insw;
 	hwif->INSL	= ide_mm_insl;
 }
@@ -777,7 +753,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->ide_dma_check)	 /* check if host supports DMA */
-		hwif->ide_dma_host_off(drive);
+		hwif->dma_host_off(drive);
 #endif
 
 	/*
@@ -854,9 +830,9 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (speed >= XFER_SW_DMA_0)
-		hwif->ide_dma_host_on(drive);
+		hwif->dma_host_on(drive);
 	else if (hwif->ide_dma_check)	/* check if host supports DMA */
-		hwif->ide_dma_off_quietly(drive);
+		hwif->dma_off_quietly(drive);
 #endif
 
 	switch(speed) {
@@ -1066,12 +1042,12 @@
 {
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (drive->crc_count) {
-		(void) HWIF(drive)->ide_dma_off_quietly(drive);
+		drive->hwif->dma_off_quietly(drive);
 		ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive));
 		if (drive->current_speed >= XFER_SW_DMA_0)
 			(void) HWIF(drive)->ide_dma_on(drive);
 	} else
-		(void)__ide_dma_off(drive);
+		ide_dma_off(drive);
 #endif
 }
 
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 8237d89..8afce4c 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -205,6 +205,21 @@
 
 EXPORT_SYMBOL(ide_dma_enable);
 
+int ide_use_fast_pio(ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+
+	if ((id->capability & 1) && drive->autodma)
+		return 1;
+
+	if ((id->capability & 8) || (id->field_valid & 2))
+		return 1;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ide_use_fast_pio);
+
 /*
  * Standard (generic) timings for PIO modes, from ATA2 specification.
  * These timings are for access to the IDE data port register *only*.
@@ -349,7 +364,6 @@
 	int use_iordy = 0;
 	struct hd_driveid* id = drive->id;
 	int overridden  = 0;
-	int blacklisted = 0;
 
 	if (mode_wanted != 255) {
 		pio_mode = mode_wanted;
@@ -357,7 +371,6 @@
 		pio_mode = 0;
 	} else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) {
 		overridden = 1;
-		blacklisted = 1;
 		use_iordy = (pio_mode > 2);
 	} else {
 		pio_mode = id->tPIO;
@@ -409,7 +422,6 @@
 		d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time;
 		d->use_iordy = use_iordy;
 		d->overridden = overridden;
-		d->blacklisted = blacklisted;
 	}
 	return pio_mode;
 }
@@ -462,8 +474,6 @@
 		return -1;
 }
 
-EXPORT_SYMBOL_GPL(ide_set_xfer_rate);
-
 static void ide_dump_opcode(ide_drive_t *drive)
 {
 	struct request *rq;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 176bbc8..8afbd6c 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -853,11 +853,11 @@
 				 * things, if not checked and cleared.
 				 *   PARANOIA!!!
 				 */
-				hwif->ide_dma_off_quietly(drive);
+				hwif->dma_off_quietly(drive);
 #ifdef CONFIG_IDEDMA_ONLYDISK
 				if (drive->media == ide_disk)
 #endif
-					hwif->ide_dma_check(drive);
+					ide_set_dma(drive);
 			}
 		}
 	}
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index aa049da..afb71c6 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -26,7 +26,6 @@
 
 #include <asm/uaccess.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/mm.h>
@@ -413,7 +412,6 @@
 	while (p->name != NULL) {
 		ent = create_proc_entry(p->name, p->mode, dir);
 		if (!ent) return;
-		ent->nlink = 1;
 		ent->data = data;
 		ent->read_proc = p->read_proc;
 		ent->write_proc = p->write_proc;
@@ -549,7 +547,7 @@
 	return single_open(file, &ide_drivers_show, NULL);
 }
 
-static struct file_operations ide_drivers_operations = {
+static const struct file_operations ide_drivers_operations = {
 	.open		= ide_drivers_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index b3bcd1d..4e59239 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1970,7 +1970,7 @@
 		printk(KERN_ERR "ide-tape: The tape wants to issue more "
 				"interrupts in DMA mode\n");
 		printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
-		(void)__ide_dma_off(drive);
+		ide_dma_off(drive);
 		return ide_do_reset(drive);
 	}
 	/* Get the number of bytes to transfer on this interrupt. */
@@ -2176,7 +2176,7 @@
 	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
 		printk(KERN_WARNING "ide-tape: DMA disabled, "
 				"reverting to PIO\n");
-		(void)__ide_dma_off(drive);
+		ide_dma_off(drive);
 	}
 	if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
 		dma_ok = !hwif->dma_setup(drive);
@@ -4779,7 +4779,7 @@
 /*
  *	Our character device supporting functions, passed to register_chrdev.
  */
-static struct file_operations idetape_fops = {
+static const struct file_operations idetape_fops = {
 	.owner		= THIS_MODULE,
 	.read		= idetape_chrdev_read,
 	.write		= idetape_chrdev_write,
@@ -4792,15 +4792,10 @@
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct ide_tape_obj *tape;
-	ide_drive_t *drive;
 
 	if (!(tape = ide_tape_get(disk)))
 		return -ENXIO;
 
-	drive = tape->drive;
-
-	drive->usage++;
-
 	return 0;
 }
 
@@ -4808,9 +4803,6 @@
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct ide_tape_obj *tape = ide_tape_g(disk);
-	ide_drive_t *drive = tape->drive;
-
-	drive->usage--;
 
 	ide_tape_put(tape);
 
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index c750f6c..b3c0818 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -389,9 +389,8 @@
 	unsigned long addr;
 	unsigned int i;
 
-	if (hwif->mmio == 2)
+	if (hwif->mmio)
 		return 0;
-	BUG_ON(hwif->mmio == 1);
 	addr = hwif->io_ports[IDE_CONTROL_OFFSET];
 	if (addr && !hwif_request_region(hwif, addr, 1))
 		goto control_region_busy;
@@ -438,7 +437,7 @@
 {
 	u32 i = 0;
 
-	if (hwif->mmio == 2)
+	if (hwif->mmio)
 		return;
 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
 		release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
@@ -507,23 +506,22 @@
 	hwif->ide_dma_end		= tmp_hwif->ide_dma_end;
 	hwif->ide_dma_check		= tmp_hwif->ide_dma_check;
 	hwif->ide_dma_on		= tmp_hwif->ide_dma_on;
-	hwif->ide_dma_off_quietly	= tmp_hwif->ide_dma_off_quietly;
+	hwif->dma_off_quietly		= tmp_hwif->dma_off_quietly;
 	hwif->ide_dma_test_irq		= tmp_hwif->ide_dma_test_irq;
-	hwif->ide_dma_host_on		= tmp_hwif->ide_dma_host_on;
-	hwif->ide_dma_host_off		= tmp_hwif->ide_dma_host_off;
+	hwif->ide_dma_clear_irq		= tmp_hwif->ide_dma_clear_irq;
+	hwif->dma_host_on		= tmp_hwif->dma_host_on;
+	hwif->dma_host_off		= tmp_hwif->dma_host_off;
 	hwif->ide_dma_lostirq		= tmp_hwif->ide_dma_lostirq;
 	hwif->ide_dma_timeout		= tmp_hwif->ide_dma_timeout;
 
 	hwif->OUTB			= tmp_hwif->OUTB;
 	hwif->OUTBSYNC			= tmp_hwif->OUTBSYNC;
 	hwif->OUTW			= tmp_hwif->OUTW;
-	hwif->OUTL			= tmp_hwif->OUTL;
 	hwif->OUTSW			= tmp_hwif->OUTSW;
 	hwif->OUTSL			= tmp_hwif->OUTSL;
 
 	hwif->INB			= tmp_hwif->INB;
 	hwif->INW			= tmp_hwif->INW;
-	hwif->INL			= tmp_hwif->INL;
 	hwif->INSW			= tmp_hwif->INSW;
 	hwif->INSL			= tmp_hwif->INSL;
 
@@ -551,7 +549,6 @@
 	hwif->extra_ports		= tmp_hwif->extra_ports;
 	hwif->autodma			= tmp_hwif->autodma;
 	hwif->udma_four			= tmp_hwif->udma_four;
-	hwif->no_dsc			= tmp_hwif->no_dsc;
 
 	hwif->hwif_data			= tmp_hwif->hwif_data;
 }
@@ -1138,12 +1135,11 @@
 	if (HWIF(drive)->ide_dma_check == NULL)
 		return -EPERM;
 	if (arg) {
-		if (HWIF(drive)->ide_dma_check(drive)) return -EIO;
-		if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
-	} else {
-		if (__ide_dma_off(drive))
+		if (ide_set_dma(drive))
 			return -EIO;
-	}
+		if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
+	} else
+		ide_dma_off(drive);
 	return 0;
 #else
 	return -EPERM;
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
index 0391a31..1ed224a 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/legacy/buddha.c
@@ -215,7 +215,7 @@
 			
 			index = ide_register_hw(&hw, &hwif);
 			if (index != -1) {
-				hwif->mmio = 2;
+				hwif->mmio = 1;
 				printk("ide%d: ", index);
 				switch(type) {
 				case BOARD_BUDDHA:
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
index 64d4261..dcfadbb 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/legacy/gayle.c
@@ -167,7 +167,7 @@
 
 	index = ide_register_hw(&hw, &hwif);
 	if (index != -1) {
-	    hwif->mmio = 2;
+	    hwif->mmio = 1;
 	    switch (i) {
 		case 0:
 		    printk("ide%d: Gayle IDE interface (A%d style)\n", index,
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
index c48e87e..19ccd00 100644
--- a/drivers/ide/legacy/ht6560b.c
+++ b/drivers/ide/legacy/ht6560b.c
@@ -143,16 +143,16 @@
 		current_timing = timing;
 		if (drive->media != ide_disk || !drive->present)
 			select |= HT_PREFETCH_MODE;
-		(void) HWIF(drive)->INB(HT_CONFIG_PORT);
-		(void) HWIF(drive)->INB(HT_CONFIG_PORT);
-		(void) HWIF(drive)->INB(HT_CONFIG_PORT);
-		(void) HWIF(drive)->INB(HT_CONFIG_PORT);
-		HWIF(drive)->OUTB(select, HT_CONFIG_PORT);
+		(void)inb(HT_CONFIG_PORT);
+		(void)inb(HT_CONFIG_PORT);
+		(void)inb(HT_CONFIG_PORT);
+		(void)inb(HT_CONFIG_PORT);
+		outb(select, HT_CONFIG_PORT);
 		/*
 		 * Set timing for this drive:
 		 */
-		HWIF(drive)->OUTB(timing, IDE_SELECT_REG);
-		(void) HWIF(drive)->INB(IDE_STATUS_REG);
+		outb(timing, IDE_SELECT_REG);
+		(void)inb(IDE_STATUS_REG);
 #ifdef DEBUG
 		printk("ht6560b: %s: select=%#x timing=%#x\n",
 			drive->name, select, timing);
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 7efd28a..a5023cd 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index b1730d7..4c0079a 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -141,7 +141,7 @@
 	}
 
         if (index != -1) {
-		hwif->mmio = 2;
+		hwif->mmio = 1;
 		if (macintosh_config->ide_type == MAC_IDE_QUADRA)
 			printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index);
 		else if (macintosh_config->ide_type == MAC_IDE_PB)
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index 434a94f..74f0812 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -145,7 +145,7 @@
 	index = ide_register_hw(&hw, &hwif);
 	// **FIXME**
 	if (index != -1)
-		hwif->mmio = 2;
+		hwif->mmio = 1;
     }
 }
 
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index c7854ea..0a59d5e 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -181,12 +181,6 @@
 {
 	int mem_sttime;
 	int mem_stcfg;
-	unsigned long mode;
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-	if (ide_use_dma(drive))
-		mode = ide_dma_speed(drive, 0);
-#endif
 
 	mem_sttime = 0;
 	mem_stcfg  = au_readl(MEM_STCFG2);
@@ -195,7 +189,7 @@
 		auide_tune_drive(drive, speed - XFER_PIO_0);
 		return 0;
 	}
-	      
+
 	switch(speed) {
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 	case XFER_MW_DMA_2:
@@ -207,7 +201,6 @@
 		mem_stcfg &= ~TOECS_MASK;
 		mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS;
 
-		mode = XFER_MW_DMA_2;
 		break;
 	case XFER_MW_DMA_1:
 		mem_sttime = SBC_IDE_TIMING(MDMA1);
@@ -218,7 +211,6 @@
 		mem_stcfg &= ~TOECS_MASK;
 		mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS;
 
-		mode = XFER_MW_DMA_1;
 		break;
 	case XFER_MW_DMA_0:
 		mem_sttime = SBC_IDE_TIMING(MDMA0);
@@ -229,14 +221,13 @@
 		mem_stcfg &= ~TOECS_MASK;
 		mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS;
 
-		mode = XFER_MW_DMA_0;
 		break;
 #endif
 	default:
 		return 1;
 	}
-	
-	if (ide_config_drive_speed(drive, mode))
+
+	if (ide_config_drive_speed(drive, speed))
 		return 1;
 
 	au_writel(mem_sttime,MEM_STTIME2);
@@ -423,9 +414,9 @@
 	speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA);
 	
 	if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
-		return HWIF(drive)->ide_dma_on(drive);
+		return 0;
 
-	return HWIF(drive)->ide_dma_off_quietly(drive);
+	return -1;
 }
 
 static int auide_dma_test_irq(ide_drive_t *drive)
@@ -447,27 +438,24 @@
 	return 0;
 }
 
-static int auide_dma_host_on(ide_drive_t *drive)
+static void auide_dma_host_on(ide_drive_t *drive)
 {
-	return 0;
 }
 
 static int auide_dma_on(ide_drive_t *drive)
 {
 	drive->using_dma = 1;
-	return auide_dma_host_on(drive);
-}
 
-
-static int auide_dma_host_off(ide_drive_t *drive)
-{
 	return 0;
 }
 
-static int auide_dma_off_quietly(ide_drive_t *drive)
+static void auide_dma_host_off(ide_drive_t *drive)
+{
+}
+
+static void auide_dma_off_quietly(ide_drive_t *drive)
 {
 	drive->using_dma = 0;
-	return auide_dma_host_off(drive);
 }
 
 static int auide_dma_lostirq(ide_drive_t *drive)
@@ -717,7 +705,8 @@
 
 	/* hold should be on in all cases */
 	hwif->hold                      = 1;
-	hwif->mmio                      = 2;
+
+	hwif->mmio  = 1;
 
 	/* If the user has selected DDMA assisted copies,
 	   then set up a few local I/O function entry points 
@@ -732,7 +721,7 @@
 	hwif->speedproc                 = &auide_tune_chipset;
 
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-	hwif->ide_dma_off_quietly       = &auide_dma_off_quietly;
+	hwif->dma_off_quietly		= &auide_dma_off_quietly;
 	hwif->ide_dma_timeout           = &auide_dma_timeout;
 
 	hwif->ide_dma_check             = &auide_dma_check;
@@ -741,8 +730,8 @@
 	hwif->ide_dma_end               = &auide_dma_end;
 	hwif->dma_setup                 = &auide_dma_setup;
 	hwif->ide_dma_test_irq          = &auide_dma_test_irq;
-	hwif->ide_dma_host_off          = &auide_dma_host_off;
-	hwif->ide_dma_host_on           = &auide_dma_host_on;
+	hwif->dma_host_off		= &auide_dma_host_off;
+	hwif->dma_host_on		= &auide_dma_host_on;
 	hwif->ide_dma_lostirq           = &auide_dma_lostirq;
 	hwif->ide_dma_on                = &auide_dma_on;
 
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
index 09c9e79..81fa068 100644
--- a/drivers/ide/mips/swarm.c
+++ b/drivers/ide/mips/swarm.c
@@ -115,7 +115,7 @@
 	/* Setup MMIO ops.  */
 	default_hwif_mmiops(hwif);
 	/* Prevent resource map manipulation.  */
-	hwif->mmio = 2;
+	hwif->mmio = 1;
 	hwif->noprobe = 0;
 
 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index d261bfb..990eafe 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -94,9 +94,9 @@
 	switch(hwif->pci_dev->device) {
 		case PCI_DEVICE_ID_ARTOP_ATP865:
 		case PCI_DEVICE_ID_ARTOP_ATP865R:
-			mode = (hwif->INB(((hwif->channel) ?
-					hwif->mate->dma_status :
-					hwif->dma_status)) & 0x10) ? 4 : 3;
+			mode = (inb(hwif->channel ?
+				    hwif->mate->dma_status :
+				    hwif->dma_status) & 0x10) ? 4 : 3;
 			break;
 		case PCI_DEVICE_ID_ARTOP_ATP860:
 		case PCI_DEVICE_ID_ARTOP_ATP860R:
@@ -209,25 +209,13 @@
 
 static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-	if ((id->capability & 1) && drive->autodma) {
-
-		if (ide_use_dma(drive)) {
-			if (config_chipset_for_dma(drive))
-				return hwif->ide_dma_on(drive);
-		}
-
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive))
 		aec62xx_tune_drive(drive, 5);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+
+	return -1;
 }
 
 static int aec62xx_irq_timeout (ide_drive_t *drive)
@@ -286,10 +274,8 @@
 	hwif->tuneproc = &aec62xx_tune_drive;
 	hwif->speedproc = &aec62xx_tune_chipset;
 
-	if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+	if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
 		hwif->serialized = hwif->channel;
-		hwif->no_dsc = 1;
-	}
 
 	if (hwif->mate)
 		hwif->mate->serialized = hwif->serialized;
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 68df77e..4debd18 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -507,17 +507,15 @@
  *
  *	Configure a drive for DMA operation. If DMA is not possible we
  *	drop the drive into PIO mode instead.
- *
- *	FIXME: exactly what are we trying to return here
  */
- 
+
 static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct hd_driveid *id	= drive->id;
 
 	if ((m5229_revision<=0x20) && (drive->media!=ide_disk))
-		return hwif->ide_dma_off_quietly(drive);
+		goto no_dma_set;
 
 	drive->init_speed = 0;
 
@@ -552,9 +550,10 @@
 ata_pio:
 		hwif->tuneproc(drive, 255);
 no_dma_set:
-		return hwif->ide_dma_off_quietly(drive);
+		return -1;
 	}
-	return hwif->ide_dma_on(drive);
+
+	return 0;
 }
 
 /**
@@ -852,8 +851,8 @@
 {
 	if (m5229_revision < 0x20)
 		return;
-	if (!(hwif->channel))
-		hwif->OUTB(hwif->INB(dmabase+2) & 0x60, dmabase+2);
+	if (!hwif->channel)
+		outb(inb(dmabase + 2) & 0x60, dmabase + 2);
 	ide_setup_dma(hwif, dmabase, 8);
 }
 
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index a433699..7989bdd8 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -304,8 +304,9 @@
 	amd_set_drive(drive, speed);
 
 	if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
-		return HWIF(drive)->ide_dma_on(drive);
-	return HWIF(drive)->ide_dma_off_quietly(drive);
+		return 0;
+
+	return -1;
 }
 
 /*
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 982ac31..2d48af3 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -101,7 +101,7 @@
 	}
 }
 
-static int atiixp_ide_dma_host_on(ide_drive_t *drive)
+static void atiixp_dma_host_on(ide_drive_t *drive)
 {
 	struct pci_dev *dev = drive->hwif->pci_dev;
 	unsigned long flags;
@@ -118,10 +118,10 @@
 
 	spin_unlock_irqrestore(&atiixp_lock, flags);
 
-	return __ide_dma_host_on(drive);
+	ide_dma_host_on(drive);
 }
 
-static int atiixp_ide_dma_host_off(ide_drive_t *drive)
+static void atiixp_dma_host_off(ide_drive_t *drive)
 {
 	struct pci_dev *dev = drive->hwif->pci_dev;
 	unsigned long flags;
@@ -135,7 +135,7 @@
 
 	spin_unlock_irqrestore(&atiixp_lock, flags);
 
-	return __ide_dma_host_off(drive);
+	ide_dma_host_off(drive);
 }
 
 /**
@@ -235,11 +235,8 @@
 {
 	u8 speed = ide_dma_speed(drive, atiixp_ratemask(drive));
 
-	/* If no DMA speed was available then disable DMA and use PIO. */
-	if (!speed) {
-		u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
-		speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
-	}
+	if (!speed)
+		return 0;
 
 	(void) atiixp_speedproc(drive, speed);
 	return ide_dma_enable(drive);
@@ -255,30 +252,20 @@
 
 static int atiixp_dma_check(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
 	u8 tspeed, speed;
 
 	drive->init_speed = 0;
 
-	if ((id->capability & 1) && drive->autodma) {
+	if (ide_use_dma(drive) && atiixp_config_drive_for_dma(drive))
+		return 0;
 
-		if (ide_use_dma(drive)) {
-			if (atiixp_config_drive_for_dma(drive))
-				return hwif->ide_dma_on(drive);
-		}
-
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive)) {
 		tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
 		speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
-		hwif->speedproc(drive, speed);
-		return hwif->ide_dma_off_quietly(drive);
+		atiixp_speedproc(drive, speed);
 	}
-	/* IORDY not supported */
-	return 0;
+
+	return -1;
 }
 
 /**
@@ -318,8 +305,8 @@
 	else
 		hwif->udma_four = 0;
 
-	hwif->ide_dma_host_on = &atiixp_ide_dma_host_on;
-	hwif->ide_dma_host_off = &atiixp_ide_dma_host_off;
+	hwif->dma_host_on = &atiixp_dma_host_on;
+	hwif->dma_host_off = &atiixp_dma_host_off;
 	hwif->ide_dma_check = &atiixp_dma_check;
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index aee947e..49df275 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -466,36 +466,21 @@
 	if (!speed)
 		return 0;
 
-	if(ide_set_xfer_rate(drive, speed))
-		return 0; 
-
-	if (!drive->init_speed)
-		drive->init_speed = speed;
+	if (cmd64x_tune_chipset(drive, speed))
+		return 0;
 
 	return ide_dma_enable(drive);
 }
 
 static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-	if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) {
-
-		if (ide_use_dma(drive)) {
-			if (config_chipset_for_dma(drive))
-				return hwif->ide_dma_on(drive);
-		}
-
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive))
 		config_chipset_for_pio(drive, 1);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+
+	return -1;
 }
 
 static int cmd64x_alt_dma_status (struct pci_dev *dev)
@@ -518,13 +503,13 @@
 
 	drive->waiting_for_dma = 0;
 	/* read DMA command state */
-	dma_cmd = hwif->INB(hwif->dma_command);
+	dma_cmd = inb(hwif->dma_command);
 	/* stop DMA */
-	hwif->OUTB((dma_cmd & ~1), hwif->dma_command);
+	outb(dma_cmd & ~1, hwif->dma_command);
 	/* get DMA status */
-	dma_stat = hwif->INB(hwif->dma_status);
+	dma_stat = inb(hwif->dma_status);
 	/* clear the INTR & ERROR bits */
-	hwif->OUTB(dma_stat|6, hwif->dma_status);
+	outb(dma_stat | 6, hwif->dma_status);
 	if (cmd64x_alt_dma_status(dev)) {
 		u8 dma_intr	= 0;
 		u8 dma_mask	= (hwif->channel) ? ARTTIM23_INTR_CH1 :
@@ -546,7 +531,7 @@
 	struct pci_dev *dev		= hwif->pci_dev;
         u8 dma_alt_stat = 0, mask	= (hwif->channel) ? MRDMODE_INTR_CH1 :
 							    MRDMODE_INTR_CH0;
-	u8 dma_stat = hwif->INB(hwif->dma_status);
+	u8 dma_stat = inb(hwif->dma_status);
 
 	(void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat);
 #ifdef DEBUG
@@ -576,13 +561,13 @@
 
 	drive->waiting_for_dma = 0;
 	/* get DMA status */
-	dma_stat = hwif->INB(hwif->dma_status);
+	dma_stat = inb(hwif->dma_status);
 	/* read DMA command state */
-	dma_cmd = hwif->INB(hwif->dma_command);
+	dma_cmd = inb(hwif->dma_command);
 	/* stop DMA */
-	hwif->OUTB((dma_cmd & ~1), hwif->dma_command);
+	outb(dma_cmd & ~1, hwif->dma_command);
 	/* clear the INTR & ERROR bits */
-	hwif->OUTB(dma_stat|6, hwif->dma_status);
+	outb(dma_stat | 6, hwif->dma_status);
 	/* and free any DMA resources */
 	ide_destroy_dmatable(drive);
 	/* verify good DMA status */
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index ba6786a..400859a 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -132,12 +132,11 @@
 
 static int cs5520_config_drive_xfer_rate(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-
 	/* Tune the drive for PIO modes up to PIO 4 */	
 	cs5520_tune_drive(drive, 4);
+
 	/* Then tell the core to use DMA operations */
-	return hwif->ide_dma_on(drive);
+	return 0;
 }
 
 /*
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index 9bf5fdf..b2d7c13 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -81,8 +81,8 @@
 
 	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
 	if (!cs5530_set_xfer_mode(drive, modes[pio])) {
-		format = (hwif->INL(basereg+4) >> 31) & 1;
-		hwif->OUTL(cs5530_pio_timings[format][pio],
+		format = (inl(basereg + 4) >> 31) & 1;
+		outl(cs5530_pio_timings[format][pio],
 			basereg+(drive->select.b.unit<<3));
 	}
 }
@@ -103,16 +103,13 @@
 	int			unit = drive->select.b.unit;
 	ide_drive_t		*mate = &hwif->drives[unit^1];
 	struct hd_driveid	*id = drive->id;
-	unsigned int		reg, timings;
+	unsigned int		reg, timings = 0;
 	unsigned long		basereg;
 
 	/*
 	 * Default to DMA-off in case we run into trouble here.
 	 */
-	hwif->ide_dma_off_quietly(drive);
-	/* turn off DMA while we fiddle */
-	hwif->ide_dma_host_off(drive);
-	/* clear DMA_capable bit */
+	hwif->dma_off_quietly(drive);
 
 	/*
 	 * The CS5530 specifies that two drives sharing a cable cannot
@@ -182,30 +179,24 @@
 		case XFER_MW_DMA_1:	timings = 0x00012121; break;
 		case XFER_MW_DMA_2:	timings = 0x00002020; break;
 		default:
-			printk(KERN_ERR "%s: cs5530_config_dma: huh? mode=%02x\n",
-				drive->name, mode);
-			return 1;	/* failure */
+			BUG();
+			break;
 	}
 	basereg = CS5530_BASEREG(hwif);
-	reg = hwif->INL(basereg+4);		/* get drive0 config register */
+	reg = inl(basereg + 4);			/* get drive0 config register */
 	timings |= reg & 0x80000000;		/* preserve PIO format bit */
 	if (unit == 0) {			/* are we configuring drive0? */
-		hwif->OUTL(timings, basereg+4);	/* write drive0 config register */
+		outl(timings, basereg + 4);	/* write drive0 config register */
 	} else {
 		if (timings & 0x00100000)
 			reg |=  0x00100000;	/* enable UDMA timings for both drives */
 		else
 			reg &= ~0x00100000;	/* disable UDMA timings for both drives */
-		hwif->OUTL(reg,     basereg+4);	/* write drive0 config register */
-		hwif->OUTL(timings, basereg+12);	/* write drive1 config register */
+		outl(reg, basereg + 4);		/* write drive0 config register */
+		outl(timings, basereg + 12);	/* write drive1 config register */
 	}
-	(void) hwif->ide_dma_host_on(drive);
-	/* set DMA_capable bit */
 
-	/*
-	 * Finally, turn DMA on in software, and exit.
-	 */
-	return hwif->ide_dma_on(drive);	/* success */
+	return 0;	/* success */
 }
 
 /**
@@ -321,17 +312,17 @@
 
 	hwif->tuneproc = &cs5530_tuneproc;
 	basereg = CS5530_BASEREG(hwif);
-	d0_timings = hwif->INL(basereg+0);
+	d0_timings = inl(basereg + 0);
 	if (CS5530_BAD_PIO(d0_timings)) {
 		/* PIO timings not initialized? */
-		hwif->OUTL(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0);
+		outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0);
 		if (!hwif->drives[0].autotune)
 			hwif->drives[0].autotune = 1;
 			/* needs autotuning later */
 	}
-	if (CS5530_BAD_PIO(hwif->INL(basereg+8))) {
-	/* PIO timings not initialized? */
-		hwif->OUTL(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8);
+	if (CS5530_BAD_PIO(inl(basereg + 8))) {
+		/* PIO timings not initialized? */
+		outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8);
 		if (!hwif->drives[1].autotune)
 			hwif->drives[1].autotune = 1;
 			/* needs autotuning later */
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 5c5aec2..45f43ef 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -195,28 +195,19 @@
 
 static int cs5535_dma_check(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
-	struct hd_driveid *id	= drive->id;
 	u8 speed;
 
 	drive->init_speed = 0;
 
-	if ((id->capability & 1) && drive->autodma) {
-		if (ide_use_dma(drive)) {
-			if (cs5535_config_drive_for_dma(drive))
-				return hwif->ide_dma_on(drive);
-		}
+	if (ide_use_dma(drive) && cs5535_config_drive_for_dma(drive))
+		return 0;
 
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive)) {
 		speed = ide_get_best_pio_mode(drive, 255, 4, NULL);
 		cs5535_set_drive(drive, speed);
-		return hwif->ide_dma_off_quietly(drive);
 	}
-	/* IORDY not supported */
-	return 0;
+
+	return -1;
 }
 
 static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index 9eafcbf..103b9db 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -197,8 +197,8 @@
 #if CY82C693_DEBUG_LOGS
 	/* for debug let's show the previous values */
 
-	HWIF(drive)->OUTB(index, CY82_INDEX_PORT);
-	data = HWIF(drive)->INB(CY82_DATA_PORT);
+	outb(index, CY82_INDEX_PORT);
+	data = inb(CY82_DATA_PORT);
 
 	printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
 		drive->name, HWIF(drive)->channel, drive->select.b.unit,
@@ -207,8 +207,8 @@
 
 	data = (u8)mode|(u8)(single<<2);
 
-	HWIF(drive)->OUTB(index, CY82_INDEX_PORT);
-	HWIF(drive)->OUTB(data, CY82_DATA_PORT);
+	outb(index, CY82_INDEX_PORT);
+	outb(data, CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO
 	printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
@@ -227,8 +227,8 @@
 	 */
 
 	data = BUSMASTER_TIMEOUT;
-	HWIF(drive)->OUTB(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
-	HWIF(drive)->OUTB(data, CY82_DATA_PORT);
+	outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
+	outb(data, CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO	
 	printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
@@ -478,21 +478,18 @@
 	}
 }
 
-static ide_pci_device_t cy82c693_chipsets[] __devinitdata = {
-	{	/* 0 */
-		.name		= "CY82C693",
-		.init_chipset	= init_chipset_cy82c693,
-		.init_iops	= init_iops_cy82c693,
-		.init_hwif	= init_hwif_cy82c693,
-		.channels	= 1,
-		.autodma	= AUTODMA,
-		.bootable	= ON_BOARD,
-	}
+static ide_pci_device_t cy82c693_chipset __devinitdata = {
+	.name		= "CY82C693",
+	.init_chipset	= init_chipset_cy82c693,
+	.init_iops	= init_iops_cy82c693,
+	.init_hwif	= init_hwif_cy82c693,
+	.channels	= 1,
+	.autodma	= AUTODMA,
+	.bootable	= ON_BOARD,
 };
 
 static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	ide_pci_device_t *d = &cy82c693_chipsets[id->driver_data];
 	struct pci_dev *dev2;
 	int ret = -ENODEV;
 
@@ -501,7 +498,7 @@
         if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
 	    PCI_FUNC(dev->devfn) == 1) {
 		dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
-		ret = ide_setup_pci_devices(dev, dev2, d);
+		ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset);
 		/* We leak pci refs here but thats ok - we can't be unloaded */
 	}
 	return ret;
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index ce7b08f..924eaa3 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -48,19 +48,6 @@
 	return 1;
 }
 
-static void hpt34x_clear_chipset (ide_drive_t *drive)
-{
-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
-	u32 reg1 = 0, tmp1 = 0, reg2 = 0, tmp2 = 0;
-
-	pci_read_config_dword(dev, 0x44, &reg1);
-	pci_read_config_dword(dev, 0x48, &reg2);
-	tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
-	tmp2 = (reg2 & ~(0x11 << drive->dn));
-	pci_write_config_dword(dev, 0x44, tmp1);
-	pci_write_config_dword(dev, 0x48, tmp2);
-}
-
 static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 {
 	struct pci_dev *dev	= HWIF(drive)->pci_dev;
@@ -81,7 +68,7 @@
 	pci_read_config_dword(dev, 0x44, &reg1);
 	pci_read_config_dword(dev, 0x48, &reg2);
 	tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
-	tmp2 = ((hi_speed << drive->dn) | reg2);
+	tmp2 = ((hi_speed << drive->dn) | (reg2 & ~(0x11 << drive->dn)));
 	pci_write_config_dword(dev, 0x44, tmp1);
 	pci_write_config_dword(dev, 0x48, tmp2);
 
@@ -99,7 +86,6 @@
 static void hpt34x_tune_drive (ide_drive_t *drive, u8 pio)
 {
 	pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
-	hpt34x_clear_chipset(drive);
 	(void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio));
 }
 
@@ -117,38 +103,25 @@
 	if (!(speed))
 		return 0;
 
-	hpt34x_clear_chipset(drive);
 	(void) hpt34x_tune_chipset(drive, speed);
 	return ide_dma_enable(drive);
 }
 
 static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
-
 	drive->init_speed = 0;
 
-	if (id && (id->capability & 1) && drive->autodma) {
-
-		if (ide_use_dma(drive)) {
-			if (config_chipset_for_dma(drive))
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
 #ifndef CONFIG_HPT34X_AUTODMA
-				return hwif->ide_dma_off_quietly(drive);
+		return -1;
 #else
-				return hwif->ide_dma_on(drive);
+		return 0;
 #endif
-		}
 
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive))
 		hpt34x_tune_drive(drive, 255);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+
+	return -1;
 }
 
 /*
@@ -209,7 +182,6 @@
 
 	hwif->tuneproc = &hpt34x_tune_drive;
 	hwif->speedproc = &hpt34x_tune_chipset;
-	hwif->no_dsc = 1;
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
 
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 05be8fa..60ecdc2 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -736,24 +736,15 @@
 
 static int hpt366_config_drive_xfer_rate(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
-
 	drive->init_speed = 0;
 
-	if ((id->capability & 1) && drive->autodma) {
-		if (ide_use_dma(drive) && config_chipset_for_dma(drive))
-			return hwif->ide_dma_on(drive);
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive))
 		hpt3xx_tune_drive(drive, 255);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+
+	return -1;
 }
 
 /*
@@ -841,7 +832,7 @@
 		return 0;
 	}
 
-	dma_stat = hwif->INB(hwif->dma_status);
+	dma_stat = inb(hwif->dma_status);
 	/* return 1 if INTR asserted */
 	if (dma_stat & 4)
 		return 1;
@@ -1391,9 +1382,6 @@
 	u8 dma_new	= 0, dma_old	= 0;
 	unsigned long flags;
 
-	if (!dmabase)
-		return;
-		
 	dma_old = hwif->INB(dmabase + 2);
 
 	local_irq_save(flags);
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index 63248b6..424f00b 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -244,17 +244,15 @@
 
 static int it8213_config_drive_for_dma (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
+	u8 pio;
 
-	if (ide_use_dma(drive)) {
-		if (config_chipset_for_dma(drive))
-			return hwif->ide_dma_on(drive);
-	}
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-	hwif->speedproc(drive, XFER_PIO_0
-			+ ide_get_best_pio_mode(drive, 255, 4, NULL));
+	pio = ide_get_best_pio_mode(drive, 255, 4, NULL);
+	it8213_tune_chipset(drive, XFER_PIO_0 + pio);
 
- 	return hwif->ide_dma_off_quietly(drive);
+	return -1;
 }
 
 /**
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index e9bad18..a132767 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -520,14 +520,12 @@
 
 static int it821x_config_drive_for_dma (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-	if (ide_use_dma(drive)) {
-		if (config_chipset_for_dma(drive))
-			return hwif->ide_dma_on(drive);
-	}
 	config_it821x_chipset_for_pio(drive, 1);
-	return hwif->ide_dma_off_quietly(drive);
+
+	return -1;
 }
 
 /**
@@ -608,11 +606,11 @@
 				printk(".\n");
 			/* Now the core code will have wrongly decided no DMA
 			   so we need to fix this */
-			hwif->ide_dma_off_quietly(drive);
+			hwif->dma_off_quietly(drive);
 #ifdef CONFIG_IDEDMA_ONLYDISK
 			if (drive->media == ide_disk)
 #endif
-				hwif->ide_dma_check(drive);
+				ide_set_dma(drive);
 		} else {
 			/* Non RAID volume. Fixups to stop the core code
 			   doing unsupported things */
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index f07bbbe..53f2550 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -147,7 +147,9 @@
 {
 	u8 speed	= ide_dma_speed(drive, jmicron_ratemask(drive));
 
-	config_jmicron_chipset_for_pio(drive, !speed);
+	if (!speed)
+		return 0;
+
 	jmicron_tune_chipset(drive, speed);
 	return ide_dma_enable(drive);
 }
@@ -162,14 +164,12 @@
 
 static int jmicron_config_drive_for_dma (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-	if (ide_use_dma(drive)) {
-		if (config_chipset_for_dma(drive))
-			return hwif->ide_dma_on(drive);
-	}
 	config_jmicron_chipset_for_pio(drive, 1);
-	return hwif->ide_dma_off_quietly(drive);
+
+	return -1;
 }
 
 /**
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index 8aaea4e..b310c4f 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -166,10 +166,10 @@
 	/* get dma command mode */
 	dma_cmd = hwif->INB(hwif->dma_command);
 	/* stop DMA */
-	hwif->OUTB(dma_cmd & ~1, hwif->dma_command);
+	outb(dma_cmd & ~1, hwif->dma_command);
 	/* from ERRATA: clear the INTR & ERROR bits */
 	dma_cmd = hwif->INB(hwif->dma_command);
-	hwif->OUTB(dma_cmd|6, hwif->dma_command);
+	outb(dma_cmd | 6, hwif->dma_command);
 	/* and free any DMA resources */
 	ide_destroy_dmatable(drive);
 	/* verify good DMA status */
@@ -190,7 +190,8 @@
 static int ns87415_ide_dma_check (ide_drive_t *drive)
 {
 	if (drive->media != ide_disk)
-		return HWIF(drive)->ide_dma_off_quietly(drive);
+		return -1;
+
 	return __ide_dma_check(drive);
 }
 
@@ -243,9 +244,9 @@
 		 *      to SELECT_DRIVE() properly during first probe_hwif().
 		 */
 		timeout = 10000;
-		hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+		outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
 		udelay(10);
-		hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+		outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
 		do {
 			udelay(50);
 			stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
@@ -263,7 +264,7 @@
 	if (!hwif->dma_base)
 		return;
 
-	hwif->OUTB(0x60, hwif->dma_status);
+	outb(0x60, hwif->dma_status);
 	hwif->dma_setup = &ns87415_ide_dma_setup;
 	hwif->ide_dma_check = &ns87415_ide_dma_check;
 	hwif->ide_dma_end = &ns87415_ide_dma_end;
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 22bbf61..9ca60dd 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -176,34 +176,35 @@
 	return ((time*bus_speed+999)/1000);
 }
 
-static void write_reg(ide_hwif_t *hwif, u8 value, int reg)
 /* Write value to register reg, base of register
  * is at reg_base (0x1f0 primary, 0x170 secondary,
  * if not changed by PCI configuration).
  * This is from setupvic.exe program.
  */
+static void write_reg(u8 value, int reg)
 {
-	hwif->INW(reg_base+1);
-	hwif->INW(reg_base+1);
-	hwif->OUTB(3, reg_base+2);
-	hwif->OUTB(value, reg_base+reg);
-	hwif->OUTB(0x83, reg_base+2);
+	inw(reg_base + 1);
+	inw(reg_base + 1);
+	outb(3, reg_base + 2);
+	outb(value, reg_base + reg);
+	outb(0x83, reg_base + 2);
 }
 
-static u8 read_reg(ide_hwif_t *hwif, int reg)
 /* Read value from register reg, base of register
  * is at reg_base (0x1f0 primary, 0x170 secondary,
  * if not changed by PCI configuration).
  * This is from setupvic.exe program.
  */
+static u8 read_reg(int reg)
 {
 	u8 ret = 0;
 
-	hwif->INW(reg_base+1);
-	hwif->INW(reg_base+1);
-	hwif->OUTB(3, reg_base+2);
-	ret = hwif->INB(reg_base+reg);
-	hwif->OUTB(0x83, reg_base+2);
+	inw(reg_base + 1);
+	inw(reg_base + 1);
+	outb(3, reg_base + 2);
+	ret = inb(reg_base + reg);
+	outb(0x83, reg_base + 2);
+
 	return ret;
 }
 
@@ -286,39 +287,39 @@
      	reg_base = hwif->io_ports[IDE_DATA_OFFSET];
 
 	/* allow Register-B */
-	hwif->OUTB(0xc0, reg_base+CNTRL_REG);
+	outb(0xc0, reg_base + CNTRL_REG);
 	/* hmm, setupvic.exe does this ;-) */
-	hwif->OUTB(0xff, reg_base+5);
+	outb(0xff, reg_base + 5);
 	/* if reads 0xff, adapter not exist? */
-	(void) hwif->INB(reg_base+CNTRL_REG);
+	(void)inb(reg_base + CNTRL_REG);
 	/* if reads 0xc0, no interface exist? */
-	read_reg(hwif, CNTRL_REG);
+	read_reg(CNTRL_REG);
 	/* read version, probably 0 */
-	read_reg(hwif, STRAP_REG);
+	read_reg(STRAP_REG);
 
 	/* program primary drive */
-		/* select Index-0 for Register-A */
-	write_reg(hwif, 0,      MISC_REG);
-		/* set read cycle timings */
-	write_reg(hwif, cycle1, READ_REG);
-		/* set write cycle timings */
-	write_reg(hwif, cycle1, WRITE_REG);
+	/* select Index-0 for Register-A */
+	write_reg(0, MISC_REG);
+	/* set read cycle timings */
+	write_reg(cycle1, READ_REG);
+	/* set write cycle timings */
+	write_reg(cycle1, WRITE_REG);
 
 	/* program secondary drive */
-		/* select Index-1 for Register-B */
-	write_reg(hwif, 1,      MISC_REG);
-		/* set read cycle timings */
-	write_reg(hwif, cycle2, READ_REG);
-		/* set write cycle timings */
-	write_reg(hwif, cycle2, WRITE_REG);
+	/* select Index-1 for Register-B */
+	write_reg(1, MISC_REG);
+	/* set read cycle timings */
+	write_reg(cycle2, READ_REG);
+	/* set write cycle timings */
+	write_reg(cycle2, WRITE_REG);
 
 	/* use Register-A for drive 0 */
 	/* use Register-B for drive 1 */
-	write_reg(hwif, 0x85, CNTRL_REG);
+	write_reg(0x85, CNTRL_REG);
 
 	/* set address setup, DRDY timings,   */
 	/*  and read prefetch for both drives */
- 	write_reg(hwif, misc, MISC_REG);
+	write_reg(misc, MISC_REG);
 
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 236a031..6ceb25b 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -101,8 +101,8 @@
 {
 	u8 value;
 
-	hwif->OUTB(index, hwif->dma_vendor1);
-	value = hwif->INB(hwif->dma_vendor3);
+	outb(index, hwif->dma_vendor1);
+	value = inb(hwif->dma_vendor3);
 
 	DBG("index[%02X] value[%02X]\n", index, value);
 	return value;
@@ -115,8 +115,8 @@
  */
 static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
 {
-	hwif->OUTB(index, hwif->dma_vendor1);
-	hwif->OUTB(value, hwif->dma_vendor3);
+	outb(index, hwif->dma_vendor1);
+	outb(value, hwif->dma_vendor3);
 	DBG("index[%02X] value[%02X]\n", index, value);
 }
 
@@ -281,25 +281,15 @@
 
 static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
-
 	drive->init_speed = 0;
 
-	if ((id->capability & 1) && drive->autodma) {
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-		if (ide_use_dma(drive) && config_chipset_for_dma(drive))
-			return hwif->ide_dma_on(drive);
+	if (ide_use_fast_pio(drive))
+		pdcnew_tune_drive(drive, 255);
 
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-		hwif->tuneproc(drive, 255);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+	return -1;
 }
 
 static int pdcnew_quirkproc(ide_drive_t *drive)
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 730e8d1..a7a639f 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -2,6 +2,7 @@
  *  linux/drivers/ide/pci/pdc202xx_old.c	Version 0.36	Sept 11, 2002
  *
  *  Copyright (C) 1998-2002		Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2006-2007		MontaVista Software, Inc.
  *
  *  Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this
  *  compiled into the kernel if you have more than one card installed.
@@ -216,21 +217,10 @@
 }
 
 
-/*   0    1    2    3    4    5    6   7   8
- * 960, 480, 390, 300, 240, 180, 120, 90, 60
- *           180, 150, 120,  90,  60
- * DMA_Speed
- * 180, 120,  90,  90,  90,  60,  30
- *  11,   5,   4,   3,   2,   1,   0
- */
-static void config_chipset_for_pio (ide_drive_t *drive, u8 pio)
+static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio)
 {
-	u8 speed = 0;
-
-	if (pio == 5) pio = 4;
-	speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);
-        
-	pdc202xx_tune_chipset(drive, speed);
+	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	pdc202xx_tune_chipset(drive, XFER_PIO_0 + pio);
 }
 
 static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
@@ -250,17 +240,17 @@
 static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
 {
 	unsigned long clock_reg = hwif->dma_master + 0x11;
-	u8 clock = hwif->INB(clock_reg);
+	u8 clock = inb(clock_reg);
 
-	hwif->OUTB(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
+	outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
 }
 
 static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
 {
 	unsigned long clock_reg = hwif->dma_master + 0x11;
-	u8 clock = hwif->INB(clock_reg);
+	u8 clock = inb(clock_reg);
 
-	hwif->OUTB(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
+	outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
 }
 
 static int config_chipset_for_dma (ide_drive_t *drive)
@@ -332,27 +322,15 @@
 
 static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
-
 	drive->init_speed = 0;
 
-	if (id && (id->capability & 1) && drive->autodma) {
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-		if (ide_use_dma(drive)) {
-			if (config_chipset_for_dma(drive))
-				return hwif->ide_dma_on(drive);
-		}
+	if (ide_use_fast_pio(drive))
+		pdc202xx_tune_drive(drive, 255);
 
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-		hwif->tuneproc(drive, 5);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+	return -1;
 }
 
 static int pdc202xx_quirkproc (ide_drive_t *drive)
@@ -375,14 +353,14 @@
 		unsigned long high_16   = hwif->dma_master;
 		unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
 		u32 word_count	= 0;
-		u8 clock = hwif->INB(high_16 + 0x11);
+		u8 clock = inb(high_16 + 0x11);
 
-		hwif->OUTB(clock|(hwif->channel ? 0x08 : 0x02), high_16+0x11);
+		outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11);
 		word_count = (rq->nr_sectors << 8);
 		word_count = (rq_data_dir(rq) == READ) ?
 					word_count | 0x05000000 :
 					word_count | 0x06000000;
-		hwif->OUTL(word_count, atapi_reg);
+		outl(word_count, atapi_reg);
 	}
 	ide_dma_start(drive);
 }
@@ -395,9 +373,9 @@
 		unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
 		u8 clock		= 0;
 
-		hwif->OUTL(0, atapi_reg); /* zero out extra */
-		clock = hwif->INB(high_16 + 0x11);
-		hwif->OUTB(clock & ~(hwif->channel ? 0x08:0x02), high_16+0x11);
+		outl(0, atapi_reg); /* zero out extra */
+		clock = inb(high_16 + 0x11);
+		outb(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11);
 	}
 	if (drive->current_speed > XFER_UDMA_2)
 		pdc_old_disable_66MHz_clock(drive->hwif);
@@ -408,8 +386,8 @@
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	unsigned long high_16	= hwif->dma_master;
-	u8 dma_stat		= hwif->INB(hwif->dma_status);
-	u8 sc1d			= hwif->INB((high_16 + 0x001d));
+	u8 dma_stat		= inb(hwif->dma_status);
+	u8 sc1d			= inb(high_16 + 0x001d);
 
 	if (hwif->channel) {
 		/* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */
@@ -445,11 +423,11 @@
 static void pdc202xx_reset_host (ide_hwif_t *hwif)
 {
 	unsigned long high_16	= hwif->dma_master;
-	u8 udma_speed_flag	= hwif->INB(high_16|0x001f);
+	u8 udma_speed_flag	= inb(high_16 | 0x001f);
 
-	hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f));
+	outb(udma_speed_flag | 0x10, high_16 | 0x001f);
 	mdelay(100);
-	hwif->OUTB((udma_speed_flag & ~0x10), (high_16|0x001f));
+	outb(udma_speed_flag & ~0x10, high_16 | 0x001f);
 	mdelay(2000);	/* 2 seconds ?! */
 
 	printk(KERN_WARNING "PDC202XX: %s channel reset.\n",
@@ -463,7 +441,7 @@
 	
 	pdc202xx_reset_host(hwif);
 	pdc202xx_reset_host(mate);
-	hwif->tuneproc(drive, 5);
+	pdc202xx_tune_drive(drive, 255);
 }
 
 static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
@@ -490,7 +468,7 @@
 		hwif->rqsize = 256;
 
 	hwif->autodma = 0;
-	hwif->tuneproc  = &config_chipset_for_pio;
+	hwif->tuneproc  = &pdc202xx_tune_drive;
 	hwif->quirkproc = &pdc202xx_quirkproc;
 
 	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
@@ -537,9 +515,9 @@
 		return;
 	}
 
-	udma_speed_flag	= hwif->INB((dmabase|0x1f));
-	primary_mode	= hwif->INB((dmabase|0x1a));
-	secondary_mode	= hwif->INB((dmabase|0x1b));
+	udma_speed_flag	= inb(dmabase | 0x1f);
+	primary_mode	= inb(dmabase | 0x1a);
+	secondary_mode	= inb(dmabase | 0x1b);
 	printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \
 		"Primary %s Mode " \
 		"Secondary %s Mode.\n", hwif->cds->name,
@@ -552,30 +530,10 @@
 		printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ",
 			hwif->cds->name, udma_speed_flag,
 			(udma_speed_flag|1));
-		hwif->OUTB(udma_speed_flag|1,(dmabase|0x1f));
-		printk("%sACTIVE\n",
-			(hwif->INB(dmabase|0x1f)&1) ? "":"IN");
+		outb(udma_speed_flag | 1, dmabase | 0x1f);
+		printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN");
 	}
 #endif /* CONFIG_PDC202XX_BURST */
-#ifdef CONFIG_PDC202XX_MASTER
-	if (!(primary_mode & 1)) {
-		printk(KERN_INFO "%s: FORCING PRIMARY MODE BIT "
-			"0x%02x -> 0x%02x ", hwif->cds->name,
-			primary_mode, (primary_mode|1));
-		hwif->OUTB(primary_mode|1, (dmabase|0x1a));
-		printk("%s\n",
-			(hwif->INB((dmabase|0x1a)) & 1) ? "MASTER" : "PCI");
-	}
-
-	if (!(secondary_mode & 1)) {
-		printk(KERN_INFO "%s: FORCING SECONDARY MODE BIT "
-			"0x%02x -> 0x%02x ", hwif->cds->name,
-			secondary_mode, (secondary_mode|1));
-		hwif->OUTB(secondary_mode|1, (dmabase|0x1b));
-		printk("%s\n",
-			(hwif->INB((dmabase|0x1b)) & 1) ? "MASTER" : "PCI");
-	}
-#endif /* CONFIG_PDC202XX_MASTER */
 
 	ide_setup_dma(hwif, dmabase, 8);
 }
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 52cfc2a..569822f 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -369,7 +369,7 @@
 	 * If no DMA speed was available or the chipset has DMA bugs
 	 * then disable DMA and use PIO
 	 */
-	if (!speed || no_piix_dma)
+	if (!speed)
 		return 0;
 
 	(void) piix_tune_chipset(drive, speed);
@@ -386,41 +386,28 @@
  
 static int piix_config_drive_xfer_rate (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
-
 	drive->init_speed = 0;
 
-	if ((id->capability & 1) && drive->autodma) {
+	if (ide_use_dma(drive) && piix_config_drive_for_dma(drive))
+		return 0;
 
-		if (ide_use_dma(drive) && piix_config_drive_for_dma(drive))
-			return hwif->ide_dma_on(drive);
-
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive))
 		/* Find best PIO mode. */
-		(void) hwif->speedproc(drive, XFER_PIO_0 +
-				       ide_get_best_pio_mode(drive, 255, 4, NULL));
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+		piix_tune_chipset(drive, XFER_PIO_0 +
+				  ide_get_best_pio_mode(drive, 255, 4, NULL));
+
+	return -1;
 }
 
 /**
- *	init_chipset_piix	-	set up the PIIX chipset
- *	@dev: PCI device to set up
- *	@name: Name of the device
+ *	piix_is_ichx	-	check if ICHx
+ *	@dev: PCI device to check
  *
- *	Initialize the PCI device as required. For the PIIX this turns
- *	out to be nice and simple
+ *	returns 1 if ICHx, 0 otherwise.
  */
- 
-static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name)
+static int piix_is_ichx(struct pci_dev *dev)
 {
-        switch(dev->device) {
+        switch (dev->device) {
 		case PCI_DEVICE_ID_INTEL_82801EB_1:
 		case PCI_DEVICE_ID_INTEL_82801AA_1:
 		case PCI_DEVICE_ID_INTEL_82801AB_1:
@@ -438,19 +425,61 @@
 		case PCI_DEVICE_ID_INTEL_ICH7_21:
 		case PCI_DEVICE_ID_INTEL_ESB2_18:
 		case PCI_DEVICE_ID_INTEL_ICH8_6:
-		{
-			unsigned int extra = 0;
-			pci_read_config_dword(dev, 0x54, &extra);
-			pci_write_config_dword(dev, 0x54, extra|0x400);
-		}
-		default:
-			break;
+			return 1;
 	}
 
 	return 0;
 }
 
 /**
+ *	init_chipset_piix	-	set up the PIIX chipset
+ *	@dev: PCI device to set up
+ *	@name: Name of the device
+ *
+ *	Initialize the PCI device as required. For the PIIX this turns
+ *	out to be nice and simple
+ */
+
+static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name)
+{
+	if (piix_is_ichx(dev)) {
+		unsigned int extra = 0;
+		pci_read_config_dword(dev, 0x54, &extra);
+		pci_write_config_dword(dev, 0x54, extra|0x400);
+	}
+
+	return 0;
+}
+
+/**
+ *	piix_dma_clear_irq	-	clear BMDMA status
+ *	@drive: IDE drive to clear
+ *
+ *	Called from ide_intr() for PIO interrupts
+ *	to clear BMDMA status as needed by ICHx
+ */
+static void piix_dma_clear_irq(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	u8 dma_stat;
+
+	/* clear the INTR & ERROR bits */
+	dma_stat = hwif->INB(hwif->dma_status);
+	/* Should we force the bit as well ? */
+	hwif->OUTB(dma_stat, hwif->dma_status);
+}
+
+static int __devinit piix_cable_detect(ide_hwif_t *hwif)
+{
+	struct pci_dev *dev = hwif->pci_dev;
+	u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
+
+	pci_read_config_byte(dev, 0x54, &reg54h);
+
+	return (reg54h & mask) ? 1 : 0;
+}
+
+/**
  *	init_hwif_piix		-	fill in the hwif for the PIIX
  *	@hwif: IDE interface
  *
@@ -460,9 +489,6 @@
 
 static void __devinit init_hwif_piix(ide_hwif_t *hwif)
 {
-	u8 reg54h = 0, reg55h = 0, ata66 = 0;
-	u8 mask = hwif->channel ? 0xc0 : 0x30;
-
 #ifndef CONFIG_IA64
 	if (!hwif->irq)
 		hwif->irq = hwif->channel ? 15 : 14;
@@ -472,10 +498,6 @@
 		/* This is a painful system best to let it self tune for now */
 		return;
 	}
-	/* ESB2 appears to generate spurious DMA interrupts in PIO mode
-	   when in native mode */
-	if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18)
-		hwif->atapi_irq_bogon = 1;
 
 	hwif->autodma = 0;
 	hwif->tuneproc = &piix_tune_drive;
@@ -486,15 +508,16 @@
 	if (!hwif->dma_base)
 		return;
 
+	/* ICHx need to clear the bmdma status for all interrupts */
+	if (piix_is_ichx(hwif->pci_dev))
+		hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
+
 	hwif->atapi_dma = 1;
 	hwif->ultra_mask = 0x3f;
 	hwif->mwdma_mask = 0x06;
 	hwif->swdma_mask = 0x04;
 
 	switch(hwif->pci_dev->device) {
-		case PCI_DEVICE_ID_INTEL_82371MX:
-			hwif->mwdma_mask = 0x80;
-			hwif->swdma_mask = 0x80;
 		case PCI_DEVICE_ID_INTEL_82371FB_0:
 		case PCI_DEVICE_ID_INTEL_82371FB_1:
 		case PCI_DEVICE_ID_INTEL_82371SB_1:
@@ -507,14 +530,14 @@
 			hwif->ultra_mask = 0x07;
 			break;
 		default:
-			pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
-			pci_read_config_byte(hwif->pci_dev, 0x55, &reg55h);
-			ata66 = (reg54h & mask) ? 1 : 0;
+			if (!hwif->udma_four)
+				hwif->udma_four = piix_cable_detect(hwif);
 			break;
 	}
 
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66;
+	if (no_piix_dma)
+		hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
+
 	hwif->ide_dma_check = &piix_config_drive_xfer_rate;
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 8d762d3..b5ae0c5 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -161,7 +161,7 @@
 	/*
 	 * Default to DMA-off in case we run into trouble here.
 	 */
-	hwif->ide_dma_off_quietly(drive);			/* turn off DMA while we fiddle */
+	hwif->dma_off_quietly(drive);	/* turn off DMA while we fiddle */
 	outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */
 
 	/*
@@ -241,10 +241,7 @@
 
 	outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2);	/* set DMA_capable bit */
 
-	/*
-	 * Finally, turn DMA on in software, and exit.
-	 */
-	return hwif->ide_dma_on(drive);	/* success */
+	return 0;	/* success */
 }
 
 /*
@@ -442,10 +439,10 @@
 			ide_drive_t *drive = &(hwif->drives[d]);
 			if (drive->present && !__ide_dma_bad_drive(drive)) {
 				int was_using_dma = drive->using_dma;
-				hwif->ide_dma_off_quietly(drive);
+				hwif->dma_off_quietly(drive);
 				sc1200_config_dma(drive);
 				if (!was_using_dma && drive->using_dma) {
-					hwif->ide_dma_off_quietly(drive);
+					hwif->dma_off_quietly(drive);
 				}
 			}
 		}
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index ea9a28a..dbcd37a 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -160,7 +160,7 @@
 	if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
 	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
 		if (!drive->init_speed) {
-			u8 dma_stat = hwif->INB(hwif->dma_status);
+			u8 dma_stat = inb(hwif->dma_status);
 
 dma_pio:
 			if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
@@ -315,35 +315,15 @@
 
 static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
-
 	drive->init_speed = 0;
 
-	if ((id->capability & 1) && drive->autodma) {
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-		if (ide_use_dma(drive)) {
-			if (config_chipset_for_dma(drive))
-				return hwif->ide_dma_on(drive);
-		}
-
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive))
 		config_chipset_for_pio(drive);
-		//	hwif->tuneproc(drive, 5);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
-}
 
-/* This can go soon */
-
-static int svwks_ide_dma_end (ide_drive_t *drive)
-{
-	return __ide_dma_end(drive);
+	return -1;
 }
 
 static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const char *name)
@@ -537,35 +517,20 @@
 	}
 
 	hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
-	if (hwif->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE)
-		hwif->ide_dma_end = &svwks_ide_dma_end;
-	else if (!(hwif->udma_four))
-		hwif->udma_four = ata66_svwks(hwif);
+	if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
+		if (!hwif->udma_four)
+			hwif->udma_four = ata66_svwks(hwif);
+	}
 	if (!noautodma)
 		hwif->autodma = 1;
 
-	dma_stat = hwif->INB(hwif->dma_status);
+	dma_stat = inb(hwif->dma_status);
 	hwif->drives[0].autodma = (dma_stat & 0x20);
 	hwif->drives[1].autodma = (dma_stat & 0x40);
 	hwif->drives[0].autotune = (!(dma_stat & 0x20));
 	hwif->drives[1].autotune = (!(dma_stat & 0x40));
 }
 
-/*
- * We allow the BM-DMA driver to only work on enabled interfaces.
- */
-static void __devinit init_dma_svwks (ide_hwif_t *hwif, unsigned long dmabase)
-{
-	struct pci_dev *dev = hwif->pci_dev;
-
-	if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
-	     (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) &&
-	    (!(PCI_FUNC(dev->devfn) & 1)) && (hwif->channel))
-		return;
-
-	ide_setup_dma(hwif, dmabase, 8);
-}
-
 static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d)
 {
 	return ide_setup_pci_device(dev, d);
@@ -600,7 +565,6 @@
 		.init_setup	= init_setup_svwks,
 		.init_chipset	= init_chipset_svwks,
 		.init_hwif	= init_hwif_svwks,
-		.init_dma	= init_dma_svwks,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.bootable	= ON_BOARD,
@@ -609,7 +573,6 @@
 		.init_setup	= init_setup_csb6,
 		.init_chipset	= init_chipset_svwks,
 		.init_hwif	= init_hwif_svwks,
-		.init_dma	= init_dma_svwks,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.bootable	= ON_BOARD,
@@ -618,7 +581,6 @@
 		.init_setup	= init_setup_csb6,
 		.init_chipset	= init_chipset_svwks,
 		.init_hwif	= init_hwif_svwks,
-		.init_dma	= init_dma_svwks,
 		.channels	= 1,	/* 2 */
 		.autodma	= AUTODMA,
 		.bootable	= ON_BOARD,
@@ -627,7 +589,6 @@
 		.init_setup	= init_setup_svwks,
 		.init_chipset	= init_chipset_svwks,
 		.init_hwif	= init_hwif_svwks,
-		.init_dma	= init_dma_svwks,
 		.channels	= 1,	/* 2 */
 		.autodma	= AUTODMA,
 		.bootable	= ON_BOARD,
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index b0bf018..fd09b29 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -110,24 +110,24 @@
 static void
 sgiioc4_maskproc(ide_drive_t * drive, int mask)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
-		   IDE_CONTROL_REG);
+	writeb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
+	       (void __iomem *)IDE_CONTROL_REG);
 }
 
 
 static int
 sgiioc4_checkirq(ide_hwif_t * hwif)
 {
-	u8 intr_reg =
-	    hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4);
+	unsigned long intr_addr =
+		hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4;
 
-	if (intr_reg & 0x03)
+	if ((u8)readl((void __iomem *)intr_addr) & 0x03)
 		return 1;
 
 	return 0;
 }
 
+static u8 sgiioc4_INB(unsigned long);
 
 static int
 sgiioc4_clearirq(ide_drive_t * drive)
@@ -138,21 +138,21 @@
 	    hwif->io_ports[IDE_IRQ_OFFSET] + (IOC4_INTR_REG << 2);
 
 	/* Code to check for PCI error conditions */
-	intr_reg = hwif->INL(other_ir);
+	intr_reg = readl((void __iomem *)other_ir);
 	if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
 		/*
-		 * Using hwif->INB to read the IDE_STATUS_REG has a side effect
+		 * Using sgiioc4_INB to read the IDE_STATUS_REG has a side effect
 		 * of clearing the interrupt.  The first read should clear it
 		 * if it is set.  The second read should return a "clear" status
 		 * if it got cleared.  If not, then spin for a bit trying to
 		 * clear it.
 		 */
-		u8 stat = hwif->INB(IDE_STATUS_REG);
+		u8 stat = sgiioc4_INB(IDE_STATUS_REG);
 		int count = 0;
-		stat = hwif->INB(IDE_STATUS_REG);
+		stat = sgiioc4_INB(IDE_STATUS_REG);
 		while ((stat & 0x80) && (count++ < 100)) {
 			udelay(1);
-			stat = hwif->INB(IDE_STATUS_REG);
+			stat = sgiioc4_INB(IDE_STATUS_REG);
 		}
 
 		if (intr_reg & 0x02) {
@@ -161,9 +161,9 @@
 			    pci_stat_cmd_reg;
 
 			pci_err_addr_low =
-				hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET]);
+				readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]);
 			pci_err_addr_high =
-				hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + 4);
+				readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4));
 			pci_read_config_dword(hwif->pci_dev, PCI_COMMAND,
 					      &pci_stat_cmd_reg);
 			printk(KERN_ERR
@@ -180,9 +180,9 @@
 		}
 
 		/* Clear the Interrupt, Error bits on the IOC4 */
-		hwif->OUTL(0x03, other_ir);
+		writel(0x03, (void __iomem *)other_ir);
 
-		intr_reg = hwif->INL(other_ir);
+		intr_reg = readl((void __iomem *)other_ir);
 	}
 
 	return intr_reg & 3;
@@ -191,23 +191,25 @@
 static void sgiioc4_ide_dma_start(ide_drive_t * drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	unsigned int reg = hwif->INL(hwif->dma_base + IOC4_DMA_CTRL * 4);
+	unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4;
+	unsigned int reg = readl((void __iomem *)ioc4_dma_addr);
 	unsigned int temp_reg = reg | IOC4_S_DMA_START;
 
-	hwif->OUTL(temp_reg, hwif->dma_base + IOC4_DMA_CTRL * 4);
+	writel(temp_reg, (void __iomem *)ioc4_dma_addr);
 }
 
 static u32
 sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
 {
+	unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
 	u32	ioc4_dma;
 	int	count;
 
 	count = 0;
-	ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+	ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
 	while ((ioc4_dma & IOC4_S_DMA_STOP) && (count++ < 200)) {
 		udelay(1);
-		ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+		ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
 	}
 	return ioc4_dma;
 }
@@ -218,11 +220,11 @@
 {
 	u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
 	ide_hwif_t *hwif = HWIF(drive);
-	u64 dma_base = hwif->dma_base;
+	unsigned long dma_base = hwif->dma_base;
 	int dma_stat = 0;
 	unsigned long *ending_dma = ide_get_hwifdata(hwif);
 
-	hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+	writel(IOC4_S_DMA_STOP, (void __iomem *)(dma_base + IOC4_DMA_CTRL * 4));
 
 	ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
 
@@ -254,8 +256,8 @@
 		dma_stat = 1;
 	}
 
-	bc_dev = hwif->INL(dma_base + IOC4_BC_DEV * 4);
-	bc_mem = hwif->INL(dma_base + IOC4_BC_MEM * 4);
+	bc_dev = readl((void __iomem *)(dma_base + IOC4_BC_DEV * 4));
+	bc_mem = readl((void __iomem *)(dma_base + IOC4_BC_MEM * 4));
 
 	if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) {
 		if (bc_dev > bc_mem + 8) {
@@ -273,34 +275,29 @@
 }
 
 static int
-sgiioc4_ide_dma_check(ide_drive_t * drive)
-{
-	if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) {
-		printk(KERN_INFO
-		       "Couldnot set %s in Multimode-2 DMA mode | "
-			   "Drive %s using PIO instead\n",
-		       drive->name, drive->name);
-		drive->using_dma = 0;
-	} else
-		drive->using_dma = 1;
-
-	return 0;
-}
-
-static int
 sgiioc4_ide_dma_on(ide_drive_t * drive)
 {
 	drive->using_dma = 1;
 
-	return HWIF(drive)->ide_dma_host_on(drive);
+	return 0;
 }
 
-static int
-sgiioc4_ide_dma_off_quietly(ide_drive_t * drive)
+static void sgiioc4_dma_off_quietly(ide_drive_t *drive)
 {
 	drive->using_dma = 0;
 
-	return HWIF(drive)->ide_dma_host_off(drive);
+	drive->hwif->dma_host_off(drive);
+}
+
+static int sgiioc4_ide_dma_check(ide_drive_t *drive)
+{
+	/* FIXME: check for available DMA modes */
+	if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) {
+		printk(KERN_WARNING "%s: couldn't set MWDMA2 mode, "
+				    "using PIO instead\n", drive->name);
+		return -1;
+	} else
+		return 0;
 }
 
 /* returns 1 if dma irq issued, 0 otherwise */
@@ -310,21 +307,13 @@
 	return sgiioc4_checkirq(HWIF(drive));
 }
 
-static int
-sgiioc4_ide_dma_host_on(ide_drive_t * drive)
+static void sgiioc4_dma_host_on(ide_drive_t * drive)
 {
-	if (drive->using_dma)
-		return 0;
-
-	return 1;
 }
 
-static int
-sgiioc4_ide_dma_host_off(ide_drive_t * drive)
+static void sgiioc4_dma_host_off(ide_drive_t * drive)
 {
 	sgiioc4_clearirq(drive);
-
-	return 0;
 }
 
 static int
@@ -436,16 +425,17 @@
 {
 	u32 ioc4_dma;
 	ide_hwif_t *hwif = HWIF(drive);
-	u64 dma_base = hwif->dma_base;
+	unsigned long dma_base = hwif->dma_base;
+	unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
 	u32 dma_addr, ending_dma_addr;
 
-	ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+	ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
 
 	if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
 		printk(KERN_WARNING
 			"%s(%s):Warning!! DMA from previous transfer was still active\n",
 		       __FUNCTION__, drive->name);
-		hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+		writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
 		ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
 
 		if (ioc4_dma & IOC4_S_DMA_STOP)
@@ -454,13 +444,13 @@
 			       __FUNCTION__, drive->name);
 	}
 
-	ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+	ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
 	if (ioc4_dma & IOC4_S_DMA_ERROR) {
 		printk(KERN_WARNING
 		       "%s(%s) : Warning!! - DMA Error during Previous"
 		       " transfer | status 0x%x\n",
 		       __FUNCTION__, drive->name, ioc4_dma);
-		hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+		writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
 		ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
 
 		if (ioc4_dma & IOC4_S_DMA_STOP)
@@ -471,14 +461,14 @@
 
 	/* Address of the Scatter Gather List */
 	dma_addr = cpu_to_le32(hwif->dmatable_dma);
-	hwif->OUTL(dma_addr, dma_base + IOC4_DMA_PTR_L * 4);
+	writel(dma_addr, (void __iomem *)(dma_base + IOC4_DMA_PTR_L * 4));
 
 	/* Address of the Ending DMA */
 	memset(ide_get_hwifdata(hwif), 0, IOC4_IDE_CACHELINE_SIZE);
 	ending_dma_addr = cpu_to_le32(hwif->dma_status);
-	hwif->OUTL(ending_dma_addr, dma_base + IOC4_DMA_END_ADDR * 4);
+	writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4));
 
-	hwif->OUTL(dma_direction, dma_base + IOC4_DMA_CTRL * 4);
+	writel(dma_direction, (void __iomem *)ioc4_dma_addr);
 	drive->waiting_for_dma = 1;
 }
 
@@ -590,7 +580,7 @@
 static void __devinit
 ide_init_sgiioc4(ide_hwif_t * hwif)
 {
-	hwif->mmio = 2;
+	hwif->mmio = 1;
 	hwif->autodma = 1;
 	hwif->atapi_dma = 1;
 	hwif->ultra_mask = 0x0;	/* Disable Ultra DMA */
@@ -613,10 +603,10 @@
 	hwif->ide_dma_end = &sgiioc4_ide_dma_end;
 	hwif->ide_dma_check = &sgiioc4_ide_dma_check;
 	hwif->ide_dma_on = &sgiioc4_ide_dma_on;
-	hwif->ide_dma_off_quietly = &sgiioc4_ide_dma_off_quietly;
+	hwif->dma_off_quietly = &sgiioc4_dma_off_quietly;
 	hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
-	hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on;
-	hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off;
+	hwif->dma_host_on = &sgiioc4_dma_host_on;
+	hwif->dma_host_off = &sgiioc4_dma_host_off;
 	hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
 	hwif->ide_dma_timeout = &__ide_dma_timeout;
 
@@ -688,7 +678,7 @@
 	default_hwif_mmiops(hwif);
 
 	/* Initializing chipset IRQ Registers */
-	hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4);
+	writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
 
 	ide_init_sgiioc4(hwif);
 
@@ -729,8 +719,7 @@
 	return ret;
 }
 
-static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
-	{
+static ide_pci_device_t sgiioc4_chipset __devinitdata = {
 	 /* Channel 0 */
 	 .name = "SGIIOC4",
 	 .init_hwif = ide_init_sgiioc4,
@@ -739,7 +728,6 @@
 	 .autodma = AUTODMA,
 	 /* SGI IOC4 doesn't have enablebits. */
 	 .bootable = ON_BOARD,
-	}
 };
 
 int
@@ -751,8 +739,7 @@
 	if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
 		return 0;
 
-	return pci_init_sgiioc4(idd->idd_pdev,
-				&sgiioc4_chipsets[idd->idd_pci_id->driver_data]);
+	return pci_init_sgiioc4(idd->idd_pdev, &sgiioc4_chipset);
 }
 
 static struct ioc4_submodule ioc4_ide_submodule = {
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 4ff89c7..7b4c189 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1,8 +1,9 @@
 /*
- * linux/drivers/ide/pci/siimage.c		Version 1.07	Nov 30, 2003
+ * linux/drivers/ide/pci/siimage.c		Version 1.11	Jan 27, 2007
  *
  * Copyright (C) 2001-2002	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2003		Red Hat <alan@redhat.com>
+ * Copyright (C) 2007		MontaVista Software, Inc.
  *
  *  May be copied or modified under the terms of the GNU General Public License
  *
@@ -205,41 +206,39 @@
 	unsigned long tfaddr	= siimage_selreg(hwif, 0x02);
 	
 	/* cheat for now and use the docs */
-	switch(mode_wanted) {
-		case 4:	
-			speedp = 0x10c1; 
-			speedt = 0x10c1;
-			break;
-		case 3:	
-			speedp = 0x10C3; 
-			speedt = 0x10C3;
-			break;
-		case 2:	
-			speedp = 0x1104; 
-			speedt = 0x1281;
-			break;
-		case 1:		
-			speedp = 0x2283; 
-			speedt = 0x1281;
-			break;
-		case 0:
-		default:
-			speedp = 0x328A; 
-			speedt = 0x328A;
-			break;
+	switch (mode_wanted) {
+	case 4:
+		speedp = 0x10c1;
+		speedt = 0x10c1;
+		break;
+	case 3:
+		speedp = 0x10c3;
+		speedt = 0x10c3;
+		break;
+	case 2:
+		speedp = 0x1104;
+		speedt = 0x1281;
+		break;
+	case 1:
+		speedp = 0x2283;
+		speedt = 0x2283;
+		break;
+	case 0:
+	default:
+		speedp = 0x328a;
+		speedt = 0x328a;
+		break;
 	}
-	if (hwif->mmio)
-	{
-		hwif->OUTW(speedt, addr);
-		hwif->OUTW(speedp, tfaddr);
+
+	if (hwif->mmio) {
+		hwif->OUTW(speedp, addr);
+		hwif->OUTW(speedt, tfaddr);
 		/* Now set up IORDY */
 		if(mode_wanted == 3 || mode_wanted == 4)
 			hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2);
 		else
 			hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2);
-	}
-	else
-	{
+	} else {
 		pci_write_config_word(hwif->pci_dev, addr, speedp);
 		pci_write_config_word(hwif->pci_dev, tfaddr, speedt);
 		pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp);
@@ -397,12 +396,9 @@
 	if (!speed)
 		return 0;
 
-	if (ide_set_xfer_rate(drive, speed))
+	if (siimage_tune_chipset(drive, speed))
 		return 0;
 
-	if (!drive->init_speed)
-		drive->init_speed = speed;
-
 	return ide_dma_enable(drive);
 }
 
@@ -418,25 +414,13 @@
  
 static int siimage_config_drive_for_dma (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-	if ((id->capability & 1) != 0 && drive->autodma) {
-
-		if (ide_use_dma(drive)) {
-			if (config_chipset_for_dma(drive))
-				return hwif->ide_dma_on(drive);
-		}
-
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive))
 		config_chipset_for_pio(drive, 1);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+
+	return -1;
 }
 
 /* returns 1 if dma irq issued, 0 otherwise */
@@ -472,11 +456,11 @@
 	unsigned long addr	= siimage_selreg(hwif, 0x1);
 
 	if (SATA_ERROR_REG) {
-		u32 ext_stat = hwif->INL(base + 0x10);
+		u32 ext_stat = readl((void __iomem *)(base + 0x10));
 		u8 watchdog = 0;
 		if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
-			u32 sata_error = hwif->INL(SATA_ERROR_REG);
-			hwif->OUTL(sata_error, SATA_ERROR_REG);
+			u32 sata_error = readl((void __iomem *)SATA_ERROR_REG);
+			writel(sata_error, (void __iomem *)SATA_ERROR_REG);
 			watchdog = (sata_error & 0x00680000) ? 1 : 0;
 			printk(KERN_WARNING "%s: sata_error = 0x%08x, "
 				"watchdog = %d, %s\n",
@@ -493,11 +477,11 @@
 	}
 
 	/* return 1 if INTR asserted */
-	if ((hwif->INB(hwif->dma_status) & 0x04) == 0x04)
+	if ((readb((void __iomem *)hwif->dma_status) & 0x04) == 0x04)
 		return 1;
 
 	/* return 1 if Device INTR asserted */
-	if ((hwif->INB(addr) & 8) == 8)
+	if ((readb((void __iomem *)addr) & 8) == 8)
 		return 0;	//return 1;
 
 	return 0;
@@ -519,9 +503,9 @@
 	u32 stat_config		= 0;
 	unsigned long addr	= siimage_selreg(hwif, 0);
 
-	if (hwif->mmio) {
-		stat_config = hwif->INL(addr);
-	} else
+	if (hwif->mmio)
+		stat_config = readl((void __iomem *)addr);
+	else
 		pci_read_config_dword(hwif->pci_dev, addr, &stat_config);
 
 	switch (state) {
@@ -557,9 +541,10 @@
 	if (SATA_STATUS_REG) {
 		ide_hwif_t *hwif	= HWIF(drive);
 
-		if ((hwif->INL(SATA_STATUS_REG) & 0x03) != 0x03) {
+		/* SATA_STATUS_REG is valid only when in MMIO mode */
+		if ((readl((void __iomem *)SATA_STATUS_REG) & 0x03) != 0x03) {
 			printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
-				hwif->name, hwif->INL(SATA_STATUS_REG));
+				hwif->name, readl((void __iomem *)SATA_STATUS_REG));
 			HWGROUP(drive)->polling = 0;
 			return ide_started;
 		}
@@ -619,7 +604,8 @@
 	}
 
 	if (SATA_STATUS_REG) {
-		u32 sata_stat = hwif->INL(SATA_STATUS_REG);
+		/* SATA_STATUS_REG is valid only when in MMIO mode */
+		u32 sata_stat = readl((void __iomem *)SATA_STATUS_REG);
 		printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n",
 			hwif->name, sata_stat, __FUNCTION__);
 		if (!(sata_stat)) {
@@ -898,7 +884,8 @@
        	base = (unsigned long) addr;
 
 	hwif->dma_base			= base + (ch ? 0x08 : 0x00);
-	hwif->mmio			= 2;
+
+	hwif->mmio = 1;
 }
 
 static int is_dev_seagate_sata(ide_drive_t *drive)
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 1afff65..2ba0669 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -667,68 +667,21 @@
 	return ide_dma_enable(drive);
 }
 
-static int sis5513_config_drive_xfer_rate (ide_drive_t *drive)
+static int sis5513_config_xfer_rate(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
+	config_art_rwp_pio(drive, 5);
 
 	drive->init_speed = 0;
 
-	if (id && (id->capability & 1) && drive->autodma) {
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-		if (ide_use_dma(drive)) {
-			if (config_chipset_for_dma(drive))
-				return hwif->ide_dma_on(drive);
-		}
-
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive))
 		sis5513_tune_drive(drive, 5);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+
+	return -1;
 }
 
-/* initiates/aborts (U)DMA read/write operations on a drive. */
-static int sis5513_config_xfer_rate (ide_drive_t *drive)
-{
-	config_drive_art_rwp(drive);
-	config_art_rwp_pio(drive, 5);
-	return sis5513_config_drive_xfer_rate(drive);
-}
-
-/*
-  Future simpler config_xfer_rate :
-   When ide_find_best_mode is made bad-drive aware
-   - remove config_drive_xfer_rate and config_chipset_for_dma,
-   - replace config_xfer_rate with the following
-
-static int sis5513_config_xfer_rate (ide_drive_t *drive)
-{
-	u16 w80 = HWIF(drive)->udma_four;
-	u16 speed;
-
-	config_drive_art_rwp(drive);
-	config_art_rwp_pio(drive, 5);
-
-	speed = ide_find_best_mode(drive,
-		XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
-		(chipset_family >= ATA_33 ? XFER_UDMA : 0) |
-		(w80 && chipset_family >= ATA_66 ? XFER_UDMA_66 : 0) |
-		(w80 && chipset_family >= ATA_100a ? XFER_UDMA_100 : 0) |
-		(w80 && chipset_family >= ATA_133a ? XFER_UDMA_133 : 0));
-
-	sis5513_tune_chipset(drive, speed);
-
-	if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
-		return HWIF(drive)->ide_dma_on(drive);
-	return HWIF(drive)->ide_dma_off_quietly(drive);
-}
-*/
-
 /* Chip detection and general config */
 static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name)
 {
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 170a261..3a8a76f 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -161,14 +161,14 @@
 		if (id->field_valid & 2) {
 			if ((id->dma_mword & hwif->mwdma_mask) ||
 			    (id->dma_1word & hwif->swdma_mask))
-				return hwif->ide_dma_on(drive);
+				return 0;
 		}
 
-		if (__ide_dma_good_drive(drive))
-			return hwif->ide_dma_on(drive);
+		if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)
+			return 0;
 	} while (0);
 
-	return hwif->ide_dma_off_quietly(drive);
+	return -1;
 }
 
 /*
@@ -215,7 +215,7 @@
 	 * Was DMA enabled?  If so, disable it - we're resetting the
 	 * host.  The IDE layer will be handling the drive for us.
 	 */
-	val = hwif->INB(dma_base);
+	val = inb(dma_base);
 	if (val & 1) {
 		outb(val & ~1, dma_base);
 		printk("sl82c105: DMA was enabled\n");
@@ -259,28 +259,22 @@
 {
 	DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name));
 
-	if (config_for_dma(drive)) {
-		config_for_pio(drive, 4, 0, 0);
-		return HWIF(drive)->ide_dma_off_quietly(drive);
-	}
+	if (config_for_dma(drive))
+		return 1;
 	printk(KERN_INFO "%s: DMA enabled\n", drive->name);
 	return __ide_dma_on(drive);
 }
 
-static int sl82c105_ide_dma_off_quietly (ide_drive_t *drive)
+static void sl82c105_dma_off_quietly(ide_drive_t *drive)
 {
 	u8 speed = XFER_PIO_0;
-	int rc;
-	
-	DBG(("sl82c105_ide_dma_off_quietly(drive:%s)\n", drive->name));
 
-	rc = __ide_dma_off_quietly(drive);
+	DBG(("sl82c105_dma_off_quietly(drive:%s)\n", drive->name));
+
+	ide_dma_off_quietly(drive);
 	if (drive->pio_speed)
 		speed = drive->pio_speed - XFER_PIO_0;
 	config_for_pio(drive, speed, 0, 1);
-	drive->current_speed = drive->pio_speed;
-
-	return rc;
 }
 
 /*
@@ -401,11 +395,9 @@
 /*
  * Initialise the chip
  */
-
 static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
 {
 	unsigned int rev;
-	u8 dma_state;
 
 	DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
 
@@ -431,7 +423,6 @@
 	if (!hwif->dma_base)
 		return;
 
-	dma_state = hwif->INB(hwif->dma_base + 2) & ~0x60;
 	rev = sl82c105_bridge_revision(hwif->pci_dev);
 	if (rev <= 5) {
 		/*
@@ -441,15 +432,12 @@
 		printk("    %s: Winbond 553 bridge revision %d, BM-DMA disabled\n",
 		       hwif->name, rev);
 	} else {
-		dma_state |= 0x60;
-
 		hwif->atapi_dma = 1;
-		hwif->mwdma_mask = 0x07;
-		hwif->swdma_mask = 0x07;
+		hwif->mwdma_mask = 0x04;
 
 		hwif->ide_dma_check = &sl82c105_check_drive;
 		hwif->ide_dma_on = &sl82c105_ide_dma_on;
-		hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly;
+		hwif->dma_off_quietly = &sl82c105_dma_off_quietly;
 		hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq;
 		hwif->dma_start = &sl82c105_ide_dma_start;
 		hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout;
@@ -462,7 +450,6 @@
 		if (hwif->mate)
 			hwif->serialized = hwif->mate->serialized = 1;
 	}
-	hwif->OUTB(dma_state, hwif->dma_base + 2);
 }
 
 static ide_pci_device_t sl82c105_chipset __devinitdata = {
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index 2663ddb..ae7eb58 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -179,26 +179,16 @@
 
 static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
-
 	drive->init_speed = 0;
 
-	if ((id->capability & 1) && drive->autodma) {
+	if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive))
+		return 0;
 
-		if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive))
-			return hwif->ide_dma_on(drive);
+	if (ide_use_fast_pio(drive))
+		(void)slc90e66_tune_chipset(drive, XFER_PIO_0 +
+				ide_get_best_pio_mode(drive, 255, 4, NULL));
 
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-		(void) hwif->speedproc(drive, XFER_PIO_0 +
-				       ide_get_best_pio_mode(drive, 255, 4, NULL));
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+	return -1;
 }
 
 static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index 2ad72bb..0b6d81d 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -45,7 +45,7 @@
 
 	scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
 	scr |= mode;
-	hwif->OUTW(scr, scr_port);
+	outw(scr, scr_port);
 
 	return ide_config_drive_speed(drive, speed);
 }
@@ -89,15 +89,15 @@
 		       "attempting recovery...\n", drive->name);
 
 		/* Stop DMA */
-		hwif->OUTB(dma_cmd & ~0x01, hwif->dma_command);
+		outb(dma_cmd & ~0x01, hwif->dma_command);
 
 		/* Setup the dummy DMA transfer */
-		hwif->OUTW(0, sc_base + 0x0a);	/* Sector Count */
-		hwif->OUTW(0, twcr_port);	/* Transfer Word Count 1 or 2 */
+		outw(0, sc_base + 0x0a);	/* Sector Count */
+		outw(0, twcr_port);	/* Transfer Word Count 1 or 2 */
 
 		/* Start the dummy DMA transfer */
-		hwif->OUTB(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
-		hwif->OUTB(0x01, hwif->dma_command); /* set START_STOPBM */
+		outb(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
+		outb(0x01, hwif->dma_command); /* set START_STOPBM */
 
 		/*
 		 * If an interrupt was pending, it should come thru shortly.
@@ -128,8 +128,8 @@
 	 * the appropriate system control registers for DMA to work
 	 * with LBA48 and ATAPI devices...
 	 */
-	hwif->OUTW(nsectors, sc_base + 0x0a);	/* Sector Count */
-	hwif->OUTW(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
+	outw(nsectors, sc_base + 0x0a);	/* Sector Count */
+	outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
 
 	/* Install our timeout expiry hook, saving the current handler... */
 	ide_set_hwifdata(hwif, hwgroup->expiry);
@@ -168,7 +168,7 @@
 	}
 
 	/* System Control 1 Register bit 11 (ATA Hard Reset) write */
-	hwif->OUTW(scr1, sc_base + 0x00);
+	outw(scr1, sc_base + 0x00);
 	return 0;
 }
 
@@ -185,23 +185,13 @@
 
 static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
+	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+		return 0;
 
-	if ((id->capability & 1) && drive->autodma) {
-
-		if (ide_use_dma(drive) && config_chipset_for_dma(drive))
-			return hwif->ide_dma_on(drive);
-
-		goto fast_ata_pio;
-
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+	if (ide_use_fast_pio(drive))
 		tc86c001_tune_drive(drive, 255);
-		return hwif->ide_dma_off_quietly(drive);
-	}
-	/* IORDY not supported */
-	return 0;
+
+	return -1;
 }
 
 static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
@@ -210,13 +200,13 @@
 	u16 scr1		= hwif->INW(sc_base + 0x00);;
 
 	/* System Control 1 Register bit 15 (Soft Reset) set */
-	hwif->OUTW(scr1 |  0x8000, sc_base + 0x00);
+	outw(scr1 |  0x8000, sc_base + 0x00);
 
 	/* System Control 1 Register bit 14 (FIFO Reset) set */
-	hwif->OUTW(scr1 |  0x4000, sc_base + 0x00);
+	outw(scr1 |  0x4000, sc_base + 0x00);
 
 	/* System Control 1 Register: reset clear */
-	hwif->OUTW(scr1 & ~0xc000, sc_base + 0x00);
+	outw(scr1 & ~0xc000, sc_base + 0x00);
 
 	/* Store the system control register base for convenience... */
 	hwif->config_data = sc_base;
@@ -234,7 +224,7 @@
 	 * Sector Count Control Register bits 0 and 1 set:
 	 * software sets Sector Count Register for master and slave device
 	 */
-	hwif->OUTW(0x0003, sc_base + 0x0c);
+	outw(0x0003, sc_base + 0x0c);
 
 	/* Sector Count Register limit */
 	hwif->rqsize	 = 0xffff;
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index b13cce1..5e06179 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -104,29 +104,21 @@
 {
 	int speed = ide_dma_speed(drive, 0); /* No ultra speeds */
 
-	if (!speed) { 
-		u8 pspeed = ide_get_best_pio_mode(drive, 255, 4, NULL);
-		speed = XFER_PIO_0 + pspeed;
-	}
-	
+	if (!speed)
+		return 0;
+
 	(void) triflex_tune_chipset(drive, speed);
 	 return ide_dma_enable(drive);
 }
 
 static int triflex_config_drive_xfer_rate(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct hd_driveid *id	= drive->id;
+	if (ide_use_dma(drive) && triflex_config_drive_for_dma(drive))
+		return 0;
 
-	if ((id->capability & 1) && drive->autodma) {
-		if (ide_use_dma(drive)) {
-			if (triflex_config_drive_for_dma(drive))
-				return hwif->ide_dma_on(drive);
-		}
-	}
+	triflex_tune_drive(drive, 255);
 
-	hwif->tuneproc(drive, 255);
-	return hwif->ide_dma_off_quietly(drive);
+	return -1;
 }
 
 static void __devinit init_hwif_triflex(ide_hwif_t *hwif)
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index 174b88c..cbb1b11 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -157,16 +157,16 @@
 	if (reg != hwif->select_data) {
 		hwif->select_data = reg;
 		/* set PIO/DMA */
-		hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1);
-		hwif->OUTW(reg & 0xff, hwif->config_data);
+		outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
+		outw(reg & 0xff, hwif->config_data);
 	}
 
 	/* enable IRQ if not probing */
 	if (drive->present) {
-		reg = hwif->INW(hwif->config_data + 3);
+		reg = inw(hwif->config_data + 3);
 		reg &= 0x13;
 		reg &= ~(1 << hwif->channel);
-		hwif->OUTW(reg, hwif->config_data+3);
+		outw(reg, hwif->config_data + 3);
 	}
 
 	local_irq_restore(flags);
@@ -177,15 +177,12 @@
 	trm290_prepare_drive(drive, drive->using_dma);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-
 	BUG_ON(HWGROUP(drive)->handler != NULL);	/* paranoia check */
 	ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
 	/* issue cmd to drive */
-	hwif->OUTB(command, IDE_COMMAND_REG);
+	outb(command, IDE_COMMAND_REG);
 }
 
 static int trm290_ide_dma_setup(ide_drive_t *drive)
@@ -211,10 +208,10 @@
 	}
 	/* select DMA xfer */
 	trm290_prepare_drive(drive, 1);
-	hwif->OUTL(hwif->dmatable_dma|rw, hwif->dma_command);
+	outl(hwif->dmatable_dma | rw, hwif->dma_command);
 	drive->waiting_for_dma = 1;
 	/* start DMA */
-	hwif->OUTW((count * 2) - 1, hwif->dma_status);
+	outw((count * 2) - 1, hwif->dma_status);
 	return 0;
 }
 
@@ -230,7 +227,7 @@
 	drive->waiting_for_dma = 0;
 	/* purge DMA mappings */
 	ide_destroy_dmatable(drive);
-	status = hwif->INW(hwif->dma_status);
+	status = inw(hwif->dma_status);
 	return (status != 0x00ff);
 }
 
@@ -239,10 +236,9 @@
 	ide_hwif_t *hwif = HWIF(drive);
 	u16 status = 0;
 
-	status = hwif->INW(hwif->dma_status);
+	status = inw(hwif->dma_status);
 	return (status == 0x00ff);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /*
  * Invoked from ide-dma.c at boot time.
@@ -269,15 +265,15 @@
 
 	local_irq_save(flags);
 	/* put config reg into first byte of hwif->select_data */
-	hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1);
+	outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
 	/* select PIO as default */
 	hwif->select_data = 0x21;
-	hwif->OUTB(hwif->select_data, hwif->config_data);
+	outb(hwif->select_data, hwif->config_data);
 	/* get IRQ info */
-	reg = hwif->INB(hwif->config_data+3);
+	reg = inb(hwif->config_data + 3);
 	/* mask IRQs for both ports */
 	reg = (reg & 0x10) | 0x03;
-	hwif->OUTB(reg, hwif->config_data+3);
+	outb(reg, hwif->config_data + 3);
 	local_irq_restore(flags);
 
 	if ((reg & 0x10))
@@ -289,13 +285,11 @@
 
 	ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->dma_setup = &trm290_ide_dma_setup;
 	hwif->dma_exec_cmd = &trm290_ide_dma_exec_cmd;
 	hwif->dma_start = &trm290_ide_dma_start;
 	hwif->ide_dma_end = &trm290_ide_dma_end;
 	hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	hwif->selectproc = &trm290_selectproc;
 	hwif->autodma = 0;		/* play it safe for now */
@@ -312,16 +306,16 @@
 		static u16 next_offset = 0;
 		u8 old_mask;
 
-		hwif->OUTB(0x54|(hwif->channel<<3), hwif->config_data+1);
-		old = hwif->INW(hwif->config_data);
+		outb(0x54 | (hwif->channel << 3), hwif->config_data + 1);
+		old = inw(hwif->config_data);
 		old &= ~1;
-		old_mask = hwif->INB(old+2);
+		old_mask = inb(old + 2);
 		if (old != compat && old_mask == 0xff) {
 			/* leave lower 10 bits untouched */
 			compat += (next_offset += 0x400);
 			hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2;
-			hwif->OUTW(compat|1, hwif->config_data);
-			new = hwif->INW(hwif->config_data);
+			outw(compat | 1, hwif->config_data);
+			new = inw(hwif->config_data);
 			printk(KERN_INFO "%s: control basereg workaround: "
 				"old=0x%04x, new=0x%04x\n",
 				hwif->name, old, new & ~1);
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 6fb6e50..a508550 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -240,8 +240,9 @@
 	via_set_drive(drive, speed);
 
 	if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
-		return hwif->ide_dma_on(drive);
-	return hwif->ide_dma_off_quietly(drive);
+		return 0;
+
+	return -1;
 }
 
 static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
index 0ac9da3..82de2d7 100644
--- a/drivers/ide/ppc/mpc8xx.c
+++ b/drivers/ide/ppc/mpc8xx.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 91c5344..395d352 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -24,7 +24,6 @@
  */
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
@@ -1238,7 +1237,7 @@
        	hwif->OUTBSYNC = pmac_outbsync;
 
 	/* Tell common code _not_ to mess with resources */
-	hwif->mmio = 2;
+	hwif->mmio = 1;
 	hwif->hwif_data = pmif;
 	pmac_ide_init_hwif_ports(&hwif->hw, pmif->regbase, 0, &hwif->irq);
 	memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
@@ -1980,16 +1979,12 @@
 	return 1;
 }
 
-static int
-pmac_ide_dma_host_off (ide_drive_t *drive)
+static void pmac_ide_dma_host_off(ide_drive_t *drive)
 {
-	return 0;
 }
 
-static int
-pmac_ide_dma_host_on (ide_drive_t *drive)
+static int pmac_ide_dma_host_on(ide_drive_t *drive)
 {
-	return 0;
 }
 
 static int
@@ -2035,7 +2030,7 @@
 		return;
 	}
 
-	hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;
+	hwif->dma_off_quietly = &ide_dma_off_quietly;
 	hwif->ide_dma_on = &__ide_dma_on;
 	hwif->ide_dma_check = &pmac_ide_dma_check;
 	hwif->dma_setup = &pmac_ide_dma_setup;
@@ -2043,8 +2038,8 @@
 	hwif->dma_start = &pmac_ide_dma_start;
 	hwif->ide_dma_end = &pmac_ide_dma_end;
 	hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
-	hwif->ide_dma_host_off = &pmac_ide_dma_host_off;
-	hwif->ide_dma_host_on = &pmac_ide_dma_host_on;
+	hwif->dma_host_off = &pmac_ide_dma_host_off;
+	hwif->dma_host_on = &pmac_ide_dma_host_on;
 	hwif->ide_dma_timeout = &__ide_dma_timeout;
 	hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
 
diff --git a/drivers/ide/ppc/scc_pata.c b/drivers/ide/ppc/scc_pata.c
new file mode 100644
index 0000000..de64b02
--- /dev/null
+++ b/drivers/ide/ppc/scc_pata.c
@@ -0,0 +1,831 @@
+/*
+ * Support for IDE interfaces on Celleb platform
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This code is based on drivers/ide/pci/siimage.c:
+ * Copyright (C) 2001-2002	Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2003		Red Hat <alan@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA            0x01b4
+
+#define SCC_PATA_NAME           "scc IDE"
+
+#define TDVHSEL_MASTER          0x00000001
+#define TDVHSEL_SLAVE           0x00000004
+
+#define MODE_JCUSFEN            0x00000080
+
+#define CCKCTRL_ATARESET        0x00040000
+#define CCKCTRL_BUFCNT          0x00020000
+#define CCKCTRL_CRST            0x00010000
+#define CCKCTRL_OCLKEN          0x00000100
+#define CCKCTRL_ATACLKOEN       0x00000002
+#define CCKCTRL_LCLKEN          0x00000001
+
+#define QCHCD_IOS_SS		0x00000001
+
+#define QCHSD_STPDIAG		0x00020000
+
+#define INTMASK_MSK             0xD1000012
+#define INTSTS_SERROR		0x80000000
+#define INTSTS_PRERR		0x40000000
+#define INTSTS_RERR		0x10000000
+#define INTSTS_ICERR		0x01000000
+#define INTSTS_BMSINT		0x00000010
+#define INTSTS_BMHE		0x00000008
+#define INTSTS_IOIRQS           0x00000004
+#define INTSTS_INTRQ            0x00000002
+#define INTSTS_ACTEINT          0x00000001
+
+#define ECMODE_VALUE 0x01
+
+static struct scc_ports {
+	unsigned long ctl, dma;
+	unsigned char hwif_id;  /* for removing hwif from system */
+} scc_ports[MAX_HWIFS];
+
+/* PIO transfer mode  table */
+/* JCHST */
+static unsigned long JCHSTtbl[2][7] = {
+	{0x0E, 0x05, 0x02, 0x03, 0x02, 0x00, 0x00},   /* 100MHz */
+	{0x13, 0x07, 0x04, 0x04, 0x03, 0x00, 0x00}    /* 133MHz */
+};
+
+/* JCHHT */
+static unsigned long JCHHTtbl[2][7] = {
+	{0x0E, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00},   /* 100MHz */
+	{0x13, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00}    /* 133MHz */
+};
+
+/* JCHCT */
+static unsigned long JCHCTtbl[2][7] = {
+	{0x1D, 0x1D, 0x1C, 0x0B, 0x06, 0x00, 0x00},   /* 100MHz */
+	{0x27, 0x26, 0x26, 0x0E, 0x09, 0x00, 0x00}    /* 133MHz */
+};
+
+
+/* DMA transfer mode  table */
+/* JCHDCTM/JCHDCTS */
+static unsigned long JCHDCTxtbl[2][7] = {
+	{0x0A, 0x06, 0x04, 0x03, 0x01, 0x00, 0x00},   /* 100MHz */
+	{0x0E, 0x09, 0x06, 0x04, 0x02, 0x01, 0x00}    /* 133MHz */
+};
+
+/* JCSTWTM/JCSTWTS  */
+static unsigned long JCSTWTxtbl[2][7] = {
+	{0x06, 0x04, 0x03, 0x02, 0x02, 0x02, 0x00},   /* 100MHz */
+	{0x09, 0x06, 0x04, 0x02, 0x02, 0x02, 0x02}    /* 133MHz */
+};
+
+/* JCTSS */
+static unsigned long JCTSStbl[2][7] = {
+	{0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00},   /* 100MHz */
+	{0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05}    /* 133MHz */
+};
+
+/* JCENVT */
+static unsigned long JCENVTtbl[2][7] = {
+	{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00},   /* 100MHz */
+	{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}    /* 133MHz */
+};
+
+/* JCACTSELS/JCACTSELM */
+static unsigned long JCACTSELtbl[2][7] = {
+	{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00},   /* 100MHz */
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}    /* 133MHz */
+};
+
+
+static u8 scc_ide_inb(unsigned long port)
+{
+	u32 data = in_be32((void*)port);
+	return (u8)data;
+}
+
+static u16 scc_ide_inw(unsigned long port)
+{
+	u32 data = in_be32((void*)port);
+	return (u16)data;
+}
+
+static void scc_ide_insw(unsigned long port, void *addr, u32 count)
+{
+	u16 *ptr = (u16 *)addr;
+	while (count--) {
+		*ptr++ = le16_to_cpu(in_be32((void*)port));
+	}
+}
+
+static void scc_ide_insl(unsigned long port, void *addr, u32 count)
+{
+	u16 *ptr = (u16 *)addr;
+	while (count--) {
+		*ptr++ = le16_to_cpu(in_be32((void*)port));
+		*ptr++ = le16_to_cpu(in_be32((void*)port));
+	}
+}
+
+static void scc_ide_outb(u8 addr, unsigned long port)
+{
+	out_be32((void*)port, addr);
+}
+
+static void scc_ide_outw(u16 addr, unsigned long port)
+{
+	out_be32((void*)port, addr);
+}
+
+static void
+scc_ide_outbsync(ide_drive_t * drive, u8 addr, unsigned long port)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+
+	out_be32((void*)port, addr);
+	__asm__ __volatile__("eieio":::"memory");
+	in_be32((void*)(hwif->dma_base + 0x01c));
+	__asm__ __volatile__("eieio":::"memory");
+}
+
+static void
+scc_ide_outsw(unsigned long port, void *addr, u32 count)
+{
+	u16 *ptr = (u16 *)addr;
+	while (count--) {
+		out_be32((void*)port, cpu_to_le16(*ptr++));
+	}
+}
+
+static void
+scc_ide_outsl(unsigned long port, void *addr, u32 count)
+{
+	u16 *ptr = (u16 *)addr;
+	while (count--) {
+		out_be32((void*)port, cpu_to_le16(*ptr++));
+		out_be32((void*)port, cpu_to_le16(*ptr++));
+	}
+}
+
+/**
+ *	scc_ratemask	-	Compute available modes
+ *	@drive: IDE drive
+ *
+ *	Compute the available speeds for the devices on the interface.
+ *	Enforce UDMA33 as a limit if there is no 80pin cable present.
+ */
+
+static u8 scc_ratemask(ide_drive_t *drive)
+{
+	u8 mode = 4;
+
+	if (!eighty_ninty_three(drive))
+		mode = min(mode, (u8)1);
+	return mode;
+}
+
+/**
+ *	scc_tuneproc	-	tune a drive PIO mode
+ *	@drive: drive to tune
+ *	@mode_wanted: the target operating mode
+ *
+ *	Load the timing settings for this device mode into the
+ *	controller.
+ */
+
+static void scc_tuneproc(ide_drive_t *drive, byte mode_wanted)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct scc_ports *ports = ide_get_hwifdata(hwif);
+	unsigned long ctl_base = ports->ctl;
+	unsigned long cckctrl_port = ctl_base + 0xff0;
+	unsigned long piosht_port = ctl_base + 0x000;
+	unsigned long pioct_port = ctl_base + 0x004;
+	unsigned long reg;
+	unsigned char speed = XFER_PIO_0;
+	int offset;
+
+	mode_wanted = ide_get_best_pio_mode(drive, mode_wanted, 4, NULL);
+	switch (mode_wanted) {
+	case 4:
+		speed = XFER_PIO_4;
+		break;
+	case 3:
+		speed = XFER_PIO_3;
+		break;
+	case 2:
+		speed = XFER_PIO_2;
+		break;
+	case 1:
+		speed = XFER_PIO_1;
+		break;
+	case 0:
+	default:
+		speed = XFER_PIO_0;
+		break;
+	}
+
+	reg = in_be32((void __iomem *)cckctrl_port);
+	if (reg & CCKCTRL_ATACLKOEN) {
+		offset = 1; /* 133MHz */
+	} else {
+		offset = 0; /* 100MHz */
+	}
+	reg = JCHSTtbl[offset][mode_wanted] << 16 | JCHHTtbl[offset][mode_wanted];
+	out_be32((void __iomem *)piosht_port, reg);
+	reg = JCHCTtbl[offset][mode_wanted];
+	out_be32((void __iomem *)pioct_port, reg);
+
+	ide_config_drive_speed(drive, speed);
+}
+
+/**
+ *	scc_tune_chipset	-	tune a drive DMA mode
+ *	@drive: Drive to set up
+ *	@xferspeed: speed we want to achieve
+ *
+ *	Load the timing settings for this device mode into the
+ *	controller.
+ */
+
+static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	u8 speed = ide_rate_filter(scc_ratemask(drive), xferspeed);
+	struct scc_ports *ports = ide_get_hwifdata(hwif);
+	unsigned long ctl_base = ports->ctl;
+	unsigned long cckctrl_port = ctl_base + 0xff0;
+	unsigned long mdmact_port = ctl_base + 0x008;
+	unsigned long mcrcst_port = ctl_base + 0x00c;
+	unsigned long sdmact_port = ctl_base + 0x010;
+	unsigned long scrcst_port = ctl_base + 0x014;
+	unsigned long udenvt_port = ctl_base + 0x018;
+	unsigned long tdvhsel_port   = ctl_base + 0x020;
+	int is_slave = (&hwif->drives[1] == drive);
+	int offset, idx;
+	unsigned long reg;
+	unsigned long jcactsel;
+
+	reg = in_be32((void __iomem *)cckctrl_port);
+	if (reg & CCKCTRL_ATACLKOEN) {
+		offset = 1; /* 133MHz */
+	} else {
+		offset = 0; /* 100MHz */
+	}
+
+	switch (speed) {
+	case XFER_UDMA_6:
+		idx = 6;
+		break;
+	case XFER_UDMA_5:
+		idx = 5;
+		break;
+	case XFER_UDMA_4:
+		idx = 4;
+		break;
+	case XFER_UDMA_3:
+		idx = 3;
+		break;
+	case XFER_UDMA_2:
+		idx = 2;
+		break;
+	case XFER_UDMA_1:
+		idx = 1;
+		break;
+	case XFER_UDMA_0:
+		idx = 0;
+		break;
+	default:
+		return 1;
+	}
+
+	jcactsel = JCACTSELtbl[offset][idx];
+	if (is_slave) {
+		out_be32((void __iomem *)sdmact_port, JCHDCTxtbl[offset][idx]);
+		out_be32((void __iomem *)scrcst_port, JCSTWTxtbl[offset][idx]);
+		jcactsel = jcactsel << 2;
+		out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_SLAVE) | jcactsel);
+	} else {
+		out_be32((void __iomem *)mdmact_port, JCHDCTxtbl[offset][idx]);
+		out_be32((void __iomem *)mcrcst_port, JCSTWTxtbl[offset][idx]);
+		out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_MASTER) | jcactsel);
+	}
+	reg = JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx];
+	out_be32((void __iomem *)udenvt_port, reg);
+
+	return ide_config_drive_speed(drive, speed);
+}
+
+/**
+ *	scc_config_chipset_for_dma	-	configure for DMA
+ *	@drive: drive to configure
+ *
+ *	Called by scc_config_drive_for_dma().
+ */
+
+static int scc_config_chipset_for_dma(ide_drive_t *drive)
+{
+	u8 speed = ide_dma_speed(drive, scc_ratemask(drive));
+
+	if (!speed)
+		return 0;
+
+	if (scc_tune_chipset(drive, speed))
+		return 0;
+
+	return ide_dma_enable(drive);
+}
+
+/**
+ *	scc_configure_drive_for_dma	-	set up for DMA transfers
+ *	@drive: drive we are going to set up
+ *
+ *	Set up the drive for DMA, tune the controller and drive as
+ *	required.
+ *      If the drive isn't suitable for DMA or we hit other problems
+ *      then we will drop down to PIO and set up PIO appropriately.
+ *      (return 1)
+ */
+
+static int scc_config_drive_for_dma(ide_drive_t *drive)
+{
+	if (ide_use_dma(drive) && scc_config_chipset_for_dma(drive))
+		return 0;
+
+	if (ide_use_fast_pio(drive))
+		scc_tuneproc(drive, 4);
+
+	return -1;
+}
+
+/**
+ *	scc_ide_dma_setup	-	begin a DMA phase
+ *	@drive: target device
+ *
+ *	Build an IDE DMA PRD (IDE speak for scatter gather table)
+ *	and then set up the DMA transfer registers.
+ *
+ *	Returns 0 on success. If a PIO fallback is required then 1
+ *	is returned.
+ */
+
+static int scc_dma_setup(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct request *rq = HWGROUP(drive)->rq;
+	unsigned int reading;
+	u8 dma_stat;
+
+	if (rq_data_dir(rq))
+		reading = 0;
+	else
+		reading = 1 << 3;
+
+	/* fall back to pio! */
+	if (!ide_build_dmatable(drive, rq)) {
+		ide_map_sg(drive, rq);
+		return 1;
+	}
+
+	/* PRD table */
+	out_be32((void __iomem *)hwif->dma_prdtable, hwif->dmatable_dma);
+
+	/* specify r/w */
+	out_be32((void __iomem *)hwif->dma_command, reading);
+
+	/* read dma_status for INTR & ERROR flags */
+	dma_stat = in_be32((void __iomem *)hwif->dma_status);
+
+	/* clear INTR & ERROR flags */
+	out_be32((void __iomem *)hwif->dma_status, dma_stat|6);
+	drive->waiting_for_dma = 1;
+	return 0;
+}
+
+
+/**
+ *	scc_ide_dma_end	-	Stop DMA
+ *	@drive: IDE drive
+ *
+ *	Check and clear INT Status register.
+ *      Then call __ide_dma_end().
+ */
+
+static int scc_ide_dma_end(ide_drive_t * drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned long intsts_port = hwif->dma_base + 0x014;
+	u32 reg;
+
+	while (1) {
+		reg = in_be32((void __iomem *)intsts_port);
+
+		if (reg & INTSTS_SERROR) {
+			printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME);
+			out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT);
+
+			out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+			continue;
+		}
+
+		if (reg & INTSTS_PRERR) {
+			u32 maea0, maec0;
+			unsigned long ctl_base = hwif->config_data;
+
+			maea0 = in_be32((void __iomem *)(ctl_base + 0xF50));
+			maec0 = in_be32((void __iomem *)(ctl_base + 0xF54));
+
+			printk(KERN_WARNING "%s: PRERR [addr:%x cmd:%x]\n", SCC_PATA_NAME, maea0, maec0);
+
+			out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT);
+
+			out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+			continue;
+		}
+
+		if (reg & INTSTS_RERR) {
+			printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME);
+			out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT);
+
+			out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+			continue;
+		}
+
+		if (reg & INTSTS_ICERR) {
+			out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+
+			printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME);
+			out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT);
+			continue;
+		}
+
+		if (reg & INTSTS_BMSINT) {
+			printk(KERN_WARNING "%s: Internal Bus Error\n", SCC_PATA_NAME);
+			out_be32((void __iomem *)intsts_port, INTSTS_BMSINT);
+
+			ide_do_reset(drive);
+			continue;
+		}
+
+		if (reg & INTSTS_BMHE) {
+			out_be32((void __iomem *)intsts_port, INTSTS_BMHE);
+			continue;
+		}
+
+		if (reg & INTSTS_ACTEINT) {
+			out_be32((void __iomem *)intsts_port, INTSTS_ACTEINT);
+			continue;
+		}
+
+		if (reg & INTSTS_IOIRQS) {
+			out_be32((void __iomem *)intsts_port, INTSTS_IOIRQS);
+			continue;
+		}
+		break;
+	}
+
+	return __ide_dma_end(drive);
+}
+
+/**
+ *	setup_mmio_scc	-	map CTRL/BMID region
+ *	@dev: PCI device we are configuring
+ *	@name: device name
+ *
+ */
+
+static int setup_mmio_scc (struct pci_dev *dev, const char *name)
+{
+	unsigned long ctl_base = pci_resource_start(dev, 0);
+	unsigned long dma_base = pci_resource_start(dev, 1);
+	unsigned long ctl_size = pci_resource_len(dev, 0);
+	unsigned long dma_size = pci_resource_len(dev, 1);
+	void *ctl_addr;
+	void *dma_addr;
+	int i;
+
+	for (i = 0; i < MAX_HWIFS; i++) {
+		if (scc_ports[i].ctl == 0)
+			break;
+	}
+	if (i >= MAX_HWIFS)
+		return -ENOMEM;
+
+	if (!request_mem_region(ctl_base, ctl_size, name)) {
+		printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
+		goto fail_0;
+	}
+
+	if (!request_mem_region(dma_base, dma_size, name)) {
+		printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
+		goto fail_1;
+	}
+
+	if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL)
+		goto fail_2;
+
+	if ((dma_addr = ioremap(dma_base, dma_size)) == NULL)
+		goto fail_3;
+
+	pci_set_master(dev);
+	scc_ports[i].ctl = (unsigned long)ctl_addr;
+	scc_ports[i].dma = (unsigned long)dma_addr;
+	pci_set_drvdata(dev, (void *) &scc_ports[i]);
+
+	return 1;
+
+ fail_3:
+	iounmap(ctl_addr);
+ fail_2:
+	release_mem_region(dma_base, dma_size);
+ fail_1:
+	release_mem_region(ctl_base, ctl_size);
+ fail_0:
+	return -ENOMEM;
+}
+
+/**
+ *	init_setup_scc	-	set up an SCC PATA Controller
+ *	@dev: PCI device
+ *	@d: IDE PCI device
+ *
+ *	Perform the initial set up for this device.
+ */
+
+static int __devinit init_setup_scc(struct pci_dev *dev, ide_pci_device_t *d)
+{
+	unsigned long ctl_base;
+	unsigned long dma_base;
+	unsigned long cckctrl_port;
+	unsigned long intmask_port;
+	unsigned long mode_port;
+	unsigned long ecmode_port;
+	unsigned long dma_status_port;
+	u32 reg = 0;
+	struct scc_ports *ports;
+	int rc;
+
+	rc = setup_mmio_scc(dev, d->name);
+	if (rc < 0) {
+		return rc;
+	}
+
+	ports = pci_get_drvdata(dev);
+	ctl_base = ports->ctl;
+	dma_base = ports->dma;
+	cckctrl_port = ctl_base + 0xff0;
+	intmask_port = dma_base + 0x010;
+	mode_port = ctl_base + 0x024;
+	ecmode_port = ctl_base + 0xf00;
+	dma_status_port = dma_base + 0x004;
+
+	/* controller initialization */
+	reg = 0;
+	out_be32((void*)cckctrl_port, reg);
+	reg |= CCKCTRL_ATACLKOEN;
+	out_be32((void*)cckctrl_port, reg);
+	reg |= CCKCTRL_LCLKEN | CCKCTRL_OCLKEN;
+	out_be32((void*)cckctrl_port, reg);
+	reg |= CCKCTRL_CRST;
+	out_be32((void*)cckctrl_port, reg);
+
+	for (;;) {
+		reg = in_be32((void*)cckctrl_port);
+		if (reg & CCKCTRL_CRST)
+			break;
+		udelay(5000);
+	}
+
+	reg |= CCKCTRL_ATARESET;
+	out_be32((void*)cckctrl_port, reg);
+
+	out_be32((void*)ecmode_port, ECMODE_VALUE);
+	out_be32((void*)mode_port, MODE_JCUSFEN);
+	out_be32((void*)intmask_port, INTMASK_MSK);
+
+	return ide_setup_pci_device(dev, d);
+}
+
+/**
+ *	init_mmio_iops_scc	-	set up the iops for MMIO
+ *	@hwif: interface to set up
+ *
+ */
+
+static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
+{
+	struct pci_dev *dev = hwif->pci_dev;
+	struct scc_ports *ports = pci_get_drvdata(dev);
+	unsigned long dma_base = ports->dma;
+
+	ide_set_hwifdata(hwif, ports);
+
+	hwif->INB = scc_ide_inb;
+	hwif->INW = scc_ide_inw;
+	hwif->INSW = scc_ide_insw;
+	hwif->INSL = scc_ide_insl;
+	hwif->OUTB = scc_ide_outb;
+	hwif->OUTBSYNC = scc_ide_outbsync;
+	hwif->OUTW = scc_ide_outw;
+	hwif->OUTSW = scc_ide_outsw;
+	hwif->OUTSL = scc_ide_outsl;
+
+	hwif->io_ports[IDE_DATA_OFFSET] = dma_base + 0x20;
+	hwif->io_ports[IDE_ERROR_OFFSET] = dma_base + 0x24;
+	hwif->io_ports[IDE_NSECTOR_OFFSET] = dma_base + 0x28;
+	hwif->io_ports[IDE_SECTOR_OFFSET] = dma_base + 0x2c;
+	hwif->io_ports[IDE_LCYL_OFFSET] = dma_base + 0x30;
+	hwif->io_ports[IDE_HCYL_OFFSET] = dma_base + 0x34;
+	hwif->io_ports[IDE_SELECT_OFFSET] = dma_base + 0x38;
+	hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c;
+	hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40;
+
+	hwif->irq = hwif->pci_dev->irq;
+	hwif->dma_base = dma_base;
+	hwif->config_data = ports->ctl;
+	hwif->mmio = 1;
+}
+
+/**
+ *	init_iops_scc	-	set up iops
+ *	@hwif: interface to set up
+ *
+ *	Do the basic setup for the SCC hardware interface
+ *	and then do the MMIO setup.
+ */
+
+static void __devinit init_iops_scc(ide_hwif_t *hwif)
+{
+	struct pci_dev *dev =  hwif->pci_dev;
+	hwif->hwif_data = NULL;
+	if (pci_get_drvdata(dev) == NULL)
+		return;
+	init_mmio_iops_scc(hwif);
+}
+
+/**
+ *	init_hwif_scc	-	set up hwif
+ *	@hwif: interface to set up
+ *
+ *	We do the basic set up of the interface structure. The SCC
+ *	requires several custom handlers so we override the default
+ *	ide DMA handlers appropriately.
+ */
+
+static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+{
+	struct scc_ports *ports = ide_get_hwifdata(hwif);
+
+	ports->hwif_id = hwif->index;
+
+	hwif->dma_command = hwif->dma_base;
+	hwif->dma_status = hwif->dma_base + 0x04;
+	hwif->dma_prdtable = hwif->dma_base + 0x08;
+
+	/* PTERADD */
+	out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
+
+	hwif->dma_setup = scc_dma_setup;
+	hwif->ide_dma_end = scc_ide_dma_end;
+	hwif->speedproc = scc_tune_chipset;
+	hwif->tuneproc = scc_tuneproc;
+	hwif->ide_dma_check = scc_config_drive_for_dma;
+
+	hwif->drives[0].autotune = IDE_TUNE_AUTO;
+	hwif->drives[1].autotune = IDE_TUNE_AUTO;
+
+	if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN) {
+		hwif->ultra_mask = 0x7f; /* 133MHz */
+	} else {
+		hwif->ultra_mask = 0x3f; /* 100MHz */
+	}
+	hwif->mwdma_mask = 0x00;
+	hwif->swdma_mask = 0x00;
+	hwif->atapi_dma = 1;
+
+	/* we support 80c cable only. */
+	hwif->udma_four = 1;
+
+	hwif->autodma = 0;
+	if (!noautodma)
+		hwif->autodma = 1;
+	hwif->drives[0].autodma = hwif->autodma;
+	hwif->drives[1].autodma = hwif->autodma;
+}
+
+#define DECLARE_SCC_DEV(name_str)			\
+  {							\
+      .name		= name_str,			\
+      .init_setup	= init_setup_scc,		\
+      .init_iops	= init_iops_scc,		\
+      .init_hwif	= init_hwif_scc,		\
+      .channels	= 1,					\
+      .autodma	= AUTODMA,				\
+      .bootable	= ON_BOARD,				\
+  }
+
+static ide_pci_device_t scc_chipsets[] __devinitdata = {
+	/* 0 */ DECLARE_SCC_DEV("sccIDE"),
+};
+
+/**
+ *	scc_init_one	-	pci layer discovery entry
+ *	@dev: PCI device
+ *	@id: ident table entry
+ *
+ *	Called by the PCI code when it finds an SCC PATA controller.
+ *	We then use the IDE PCI generic helper to do most of the work.
+ */
+
+static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	ide_pci_device_t *d = &scc_chipsets[id->driver_data];
+	return d->init_setup(dev, d);
+}
+
+/**
+ *	scc_remove	-	pci layer remove entry
+ *	@dev: PCI device
+ *
+ *	Called by the PCI code when it removes an SCC PATA controller.
+ */
+
+static void __devexit scc_remove(struct pci_dev *dev)
+{
+	struct scc_ports *ports = pci_get_drvdata(dev);
+	ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id];
+	unsigned long ctl_base = pci_resource_start(dev, 0);
+	unsigned long dma_base = pci_resource_start(dev, 1);
+	unsigned long ctl_size = pci_resource_len(dev, 0);
+	unsigned long dma_size = pci_resource_len(dev, 1);
+
+	if (hwif->dmatable_cpu) {
+		pci_free_consistent(hwif->pci_dev,
+				    PRD_ENTRIES * PRD_BYTES,
+				    hwif->dmatable_cpu,
+				    hwif->dmatable_dma);
+		hwif->dmatable_cpu = NULL;
+	}
+
+	ide_unregister(hwif->index);
+
+	hwif->chipset = ide_unknown;
+	iounmap((void*)ports->dma);
+	iounmap((void*)ports->ctl);
+	release_mem_region(dma_base, dma_size);
+	release_mem_region(ctl_base, ctl_size);
+	memset(ports, 0, sizeof(*ports));
+}
+
+static struct pci_device_id scc_pci_tbl[] = {
+	{ PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ 0, },
+};
+MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
+
+static struct pci_driver driver = {
+	.name = "SCC IDE",
+	.id_table = scc_pci_tbl,
+	.probe = scc_init_one,
+	.remove = scc_remove,
+};
+
+static int scc_ide_init(void)
+{
+	return ide_pci_register_driver(&driver);
+}
+
+module_init(scc_ide_init);
+/* -- No exit code?
+static void scc_ide_exit(void)
+{
+	ide_pci_unregister_driver(&driver);
+}
+module_exit(scc_ide_exit);
+ */
+
+
+MODULE_DESCRIPTION("PCI driver module for Toshiba SCC IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ieee1394/.gitignore b/drivers/ieee1394/.gitignore
deleted file mode 100644
index 33da10a..0000000
--- a/drivers/ieee1394/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-oui.c
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index e7d5657..b8a4734 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -35,20 +35,6 @@
 	  Say Y if you really want or need the debugging output, everyone
 	  else says N.
 
-config IEEE1394_OUI_DB
-	bool "OUI Database built-in (deprecated)"
-	depends on IEEE1394
-	help
-	  If you say Y here, then an OUI list (vendor unique ID's) will be
-	  compiled into the ieee1394 module. This doesn't really do much
-	  except being able to display the vendor of a hardware node. The
-	  downside is that it adds about 300k to the size of the module,
-	  or kernel (depending on whether you compile ieee1394 as a
-	  module, or static in the kernel).
-
-	  This option is not needed for userspace programs like gscanbus
-	  to show this information.
-
 config IEEE1394_EXTRA_CONFIG_ROMS
 	bool "Build in extra config rom entries for certain functionality"
 	depends on IEEE1394
@@ -66,13 +52,6 @@
 	  with MacOSX and WinXP IP-over-1394), enable this option and the
 	  eth1394 option below.
 
-config IEEE1394_EXPORT_FULL_API
-	bool "Export all symbols of ieee1394's API (deprecated)"
-	depends on IEEE1394
-	default n
-	help
-	  This option will be removed soon.  Don't worry, say N.
-
 comment "Device Drivers"
 	depends on IEEE1394
 
diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
index d9650d3..489c133 100644
--- a/drivers/ieee1394/Makefile
+++ b/drivers/ieee1394/Makefile
@@ -5,9 +5,6 @@
 ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
 		 highlevel.o csr.o nodemgr.o dma.o iso.o \
 		 csr1212.o config_roms.o
-ifdef CONFIG_IEEE1394_OUI_DB
-ieee1394-objs += oui.o
-endif
 
 obj-$(CONFIG_IEEE1394) += ieee1394.o
 obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
@@ -18,10 +15,3 @@
 obj-$(CONFIG_IEEE1394_DV1394) += dv1394.o
 obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
 
-quiet_cmd_oui2c = OUI2C   $@
-      cmd_oui2c = $(CONFIG_SHELL) $(srctree)/$(src)/oui2c.sh < $< > $@
-
-targets := oui.c
-$(obj)/oui.o: $(obj)/oui.c
-$(obj)/oui.c: $(src)/oui.db $(src)/oui2c.sh FORCE
-	$(call if_changed,oui2c)
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
index 586f71e..c28f639 100644
--- a/drivers/ieee1394/csr1212.c
+++ b/drivers/ieee1394/csr1212.c
@@ -47,14 +47,14 @@
 #define __D (1 << CSR1212_KV_TYPE_DIRECTORY)
 #define __L (1 << CSR1212_KV_TYPE_LEAF)
 static const u_int8_t csr1212_key_id_type_map[0x30] = {
-	0,			/* Reserved */
+	__C,			/* used by Apple iSight */
 	__D | __L,		/* Descriptor */
 	__I | __D | __L,	/* Bus_Dependent_Info */
 	__I | __D | __L,	/* Vendor */
 	__I,			/* Hardware_Version */
 	0, 0,			/* Reserved */
-	__D | __L,		/* Module */
-	0, 0, 0, 0,		/* Reserved */
+	__D | __L | __I,	/* Module */
+	__I, 0, 0, 0,		/* used by Apple iSight, Reserved */
 	__I,			/* Node_Capabilities */
 	__L,			/* EUI_64 */
 	0, 0, 0,		/* Reserved */
@@ -1234,6 +1234,12 @@
 					 csr->private);
 		if (ret != CSR1212_SUCCESS)
 			return ret;
+
+		/* check ROM header's info_length */
+		if (i == 0 &&
+		    CSR1212_BE32_TO_CPU(csr->cache_head->data[0]) >> 24 !=
+		    bytes_to_quads(csr->bus_info_len) - 1)
+			return CSR1212_EINVAL;
 	}
 
 	bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data;
@@ -1250,9 +1256,6 @@
 			return ret;
 	}
 
-	if (bytes_to_quads(csr->bus_info_len - sizeof(csr1212_quad_t)) != bi->length)
-		return CSR1212_EINVAL;
-
 #if 0
 	/* Apparently there are too many differnt wrong implementations of the
 	 * CRC algorithm that verifying them is moot. */
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 1084da4..dee9529 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2147,7 +2147,7 @@
 }
 
 static struct cdev dv1394_cdev;
-static struct file_operations dv1394_fops=
+static const struct file_operations dv1394_fops=
 {
 	.owner =	THIS_MODULE,
 	.poll =         dv1394_poll,
@@ -2255,49 +2255,37 @@
 	return 0;
 }
 
-static void dv1394_un_init(struct video_card *video)
+static void dv1394_remove_host(struct hpsb_host *host)
 {
-	/* obviously nobody has the driver open at this point */
-	do_dv1394_shutdown(video, 1);
-	kfree(video);
-}
-
-
-static void dv1394_remove_host (struct hpsb_host *host)
-{
-	struct video_card *video;
+	struct video_card *video, *tmp_video;
 	unsigned long flags;
-	int id = host->id;
+	int found_ohci_card = 0;
 
-	/* We only work with the OHCI-1394 driver */
-	if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
-		return;
-
-	/* find the corresponding video_cards */
 	do {
-		struct video_card *tmp_vid;
-
 		video = NULL;
-
 		spin_lock_irqsave(&dv1394_cards_lock, flags);
-		list_for_each_entry(tmp_vid, &dv1394_cards, list) {
-			if ((tmp_vid->id >> 2) == id) {
-				list_del(&tmp_vid->list);
-				video = tmp_vid;
+		list_for_each_entry(tmp_video, &dv1394_cards, list) {
+			if ((tmp_video->id >> 2) == host->id) {
+				list_del(&tmp_video->list);
+				video = tmp_video;
+				found_ohci_card = 1;
 				break;
 			}
 		}
 		spin_unlock_irqrestore(&dv1394_cards_lock, flags);
 
-		if (video)
-			dv1394_un_init(video);
-	} while (video != NULL);
+		if (video) {
+			do_dv1394_shutdown(video, 1);
+			kfree(video);
+		}
+	} while (video);
 
-	class_device_destroy(hpsb_protocol_class,
-		MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
+	if (found_ohci_card)
+		class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+			   IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2)));
 }
 
-static void dv1394_add_host (struct hpsb_host *host)
+static void dv1394_add_host(struct hpsb_host *host)
 {
 	struct ti_ohci *ohci;
 	int id = host->id;
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 97e5c3d..a953135 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -43,7 +43,6 @@
 
 #include <linux/module.h>
 
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index ee82a53..32a1309 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -190,14 +190,19 @@
 {
 	if (hpsb_default_host_entry(host))
 		return -ENOMEM;
-
 	hpsb_add_extra_config_roms(host);
-
 	highlevel_add_host(host);
-
 	return 0;
 }
 
+void hpsb_resume_host(struct hpsb_host *host)
+{
+	if (host->driver->set_hw_config_rom)
+		host->driver->set_hw_config_rom(host,
+						host->csr.rom->bus_info_data);
+	host->driver->devctl(host, RESET_BUS, SHORT_RESET);
+}
+
 void hpsb_remove_host(struct hpsb_host *host)
 {
 	host->is_shutdown = 1;
@@ -206,9 +211,7 @@
 	flush_scheduled_work();
 
 	host->driver = &dummy_driver;
-
 	highlevel_remove_host(host);
-
 	hpsb_remove_extra_config_roms(host);
 
 	class_device_unregister(&host->class_dev);
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index d553e38..4bf4fb7 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -61,9 +61,9 @@
 	struct device device;
 	struct class_device class_dev;
 
-	int update_config_rom;
 	struct delayed_work delayed_reset;
-	unsigned int config_roms;
+	unsigned config_roms:31;
+	unsigned update_config_rom:1;
 
 	struct list_head addr_space;
 	u64 low_addr_space;	/* upper bound of physical DMA area */
@@ -200,7 +200,8 @@
 struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
 				  struct device *dev);
 int hpsb_add_host(struct hpsb_host *host);
-void hpsb_remove_host(struct hpsb_host *h);
+void hpsb_resume_host(struct hpsb_host *host);
+void hpsb_remove_host(struct hpsb_host *host);
 
 /* Updates the configuration rom image of a host.  rom_version must be the
  * current version, otherwise it will fail with return value -1. If this
diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h
index 8f20750..46878fe 100644
--- a/drivers/ieee1394/ieee1394-ioctl.h
+++ b/drivers/ieee1394/ieee1394-ioctl.h
@@ -100,5 +100,7 @@
 	_IO  ('#', 0x28)
 #define RAW1394_IOC_ISO_RECV_FLUSH		\
 	_IO  ('#', 0x29)
+#define RAW1394_IOC_GET_CYCLE_TIMER		\
+	_IOR ('#', 0x30, struct raw1394_cycle_timer)
 
 #endif /* __IEEE1394_IOCTL_H */
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 9a48ca2..d791d08 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -33,7 +33,10 @@
 #include <linux/skbuff.h>
 #include <linux/suspend.h>
 #include <linux/kthread.h>
+#include <linux/preempt.h>
+#include <linux/time.h>
 
+#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "ieee1394_types.h"
@@ -186,6 +189,45 @@
 	}
 }
 
+/**
+ * hpsb_read_cycle_timer - read cycle timer register and system time
+ * @host: host whose isochronous cycle timer register is read
+ * @cycle_timer: address of bitfield to return the register contents
+ * @local_time: address to return the system time
+ *
+ * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This
+ * format is also read from non-OHCI controllers. * @local_time contains the
+ * system time in microseconds since the Epoch, read at the moment when the
+ * cycle timer was read.
+ *
+ * Return value: 0 for success or error number otherwise.
+ */
+int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
+			  u64 *local_time)
+{
+	int ctr;
+	struct timeval tv;
+	unsigned long flags;
+
+	if (!host || !cycle_timer || !local_time)
+		return -EINVAL;
+
+	preempt_disable();
+	local_irq_save(flags);
+
+	ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
+	if (ctr)
+		do_gettimeofday(&tv);
+
+	local_irq_restore(flags);
+	preempt_enable();
+
+	if (!ctr)
+		return -EIO;
+	*cycle_timer = ctr;
+	*local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
+	return 0;
+}
 
 int hpsb_bus_reset(struct hpsb_host *host)
 {
@@ -1178,6 +1220,7 @@
 /** hosts.c **/
 EXPORT_SYMBOL(hpsb_alloc_host);
 EXPORT_SYMBOL(hpsb_add_host);
+EXPORT_SYMBOL(hpsb_resume_host);
 EXPORT_SYMBOL(hpsb_remove_host);
 EXPORT_SYMBOL(hpsb_update_config_rom_image);
 
@@ -1189,16 +1232,13 @@
 EXPORT_SYMBOL(hpsb_free_packet);
 EXPORT_SYMBOL(hpsb_send_packet);
 EXPORT_SYMBOL(hpsb_reset_bus);
+EXPORT_SYMBOL(hpsb_read_cycle_timer);
 EXPORT_SYMBOL(hpsb_bus_reset);
 EXPORT_SYMBOL(hpsb_selfid_received);
 EXPORT_SYMBOL(hpsb_selfid_complete);
 EXPORT_SYMBOL(hpsb_packet_sent);
 EXPORT_SYMBOL(hpsb_packet_received);
 EXPORT_SYMBOL_GPL(hpsb_disable_irm);
-#ifdef CONFIG_IEEE1394_EXPORT_FULL_API
-EXPORT_SYMBOL(hpsb_send_phy_config);
-EXPORT_SYMBOL(hpsb_send_packet_and_wait);
-#endif
 
 /** ieee1394_transactions.c **/
 EXPORT_SYMBOL(hpsb_get_tlabel);
@@ -1229,20 +1269,12 @@
 EXPORT_SYMBOL(hpsb_get_hostinfo_bykey);
 EXPORT_SYMBOL(hpsb_set_hostinfo);
 EXPORT_SYMBOL(highlevel_host_reset);
-#ifdef CONFIG_IEEE1394_EXPORT_FULL_API
-EXPORT_SYMBOL(highlevel_add_host);
-EXPORT_SYMBOL(highlevel_remove_host);
-#endif
 
 /** nodemgr.c **/
 EXPORT_SYMBOL(hpsb_node_fill_packet);
 EXPORT_SYMBOL(hpsb_node_write);
 EXPORT_SYMBOL(__hpsb_register_protocol);
 EXPORT_SYMBOL(hpsb_unregister_protocol);
-#ifdef CONFIG_IEEE1394_EXPORT_FULL_API
-EXPORT_SYMBOL(ieee1394_bus_type);
-EXPORT_SYMBOL(nodemgr_for_each_host);
-#endif
 
 /** csr.c **/
 EXPORT_SYMBOL(hpsb_update_config_rom);
@@ -1287,13 +1319,3 @@
 EXPORT_SYMBOL(csr1212_parse_keyval);
 EXPORT_SYMBOL(_csr1212_read_keyval);
 EXPORT_SYMBOL(_csr1212_destroy_keyval);
-#ifdef CONFIG_IEEE1394_EXPORT_FULL_API
-EXPORT_SYMBOL(csr1212_create_csr);
-EXPORT_SYMBOL(csr1212_init_local_csr);
-EXPORT_SYMBOL(csr1212_new_immediate);
-EXPORT_SYMBOL(csr1212_associate_keyval);
-EXPORT_SYMBOL(csr1212_new_string_descriptor_leaf);
-EXPORT_SYMBOL(csr1212_destroy_csr);
-EXPORT_SYMBOL(csr1212_generate_csr_image);
-EXPORT_SYMBOL(csr1212_parse_csr);
-#endif
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index 536ba3f..bd29d8e 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -127,6 +127,9 @@
  * progress, 0 otherwise. */
 int hpsb_reset_bus(struct hpsb_host *host, int type);
 
+int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
+			  u64 *local_time);
+
 /*
  * The following functions are exported for host driver module usage.  All of
  * them are safe to use in interrupt contexts, although some are quite
diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c
index 08bd15d..c6227e5 100644
--- a/drivers/ieee1394/iso.c
+++ b/drivers/ieee1394/iso.c
@@ -10,7 +10,6 @@
  */
 
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 
 #include "hosts.h"
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 61307ca..c5ace19 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -41,22 +41,6 @@
 };
 
 
-static char *nodemgr_find_oui_name(int oui)
-{
-#ifdef CONFIG_IEEE1394_OUI_DB
-	extern struct oui_list_struct {
-		int oui;
-		char *name;
-	} oui_list[];
-	int i;
-
-	for (i = 0; oui_list[i].name; i++)
-		if (oui_list[i].oui == oui)
-			return oui_list[i].name;
-#endif
-	return NULL;
-}
-
 /*
  * Correct the speed map entry.  This is necessary
  *  - for nodes with link speed < phy speed,
@@ -274,7 +258,6 @@
 struct device nodemgr_dev_template_host = {
 	.bus		= &ieee1394_bus_type,
 	.release	= nodemgr_release_host,
-	.driver		= &nodemgr_mid_layer_driver,
 };
 
 
@@ -473,11 +456,9 @@
 
 fw_attr(ne, struct node_entry, vendor_id, unsigned int, "0x%06x\n")
 fw_attr_td(ne, struct node_entry, vendor_name_kv)
-fw_attr(ne, struct node_entry, vendor_oui, const char *, "%s\n")
 
 fw_attr(ne, struct node_entry, guid, unsigned long long, "0x%016Lx\n")
 fw_attr(ne, struct node_entry, guid_vendor_id, unsigned int, "0x%06x\n")
-fw_attr(ne, struct node_entry, guid_vendor_oui, const char *, "%s\n")
 fw_attr(ne, struct node_entry, in_limbo, int, "%d\n");
 
 static struct device_attribute *const fw_ne_attrs[] = {
@@ -503,7 +484,6 @@
 fw_attr(ud, struct unit_directory, specifier_id, unsigned int, "0x%06x\n")
 fw_attr(ud, struct unit_directory, version, unsigned int, "0x%06x\n")
 fw_attr_td(ud, struct unit_directory, vendor_name_kv)
-fw_attr(ud, struct unit_directory, vendor_oui, const char *, "%s\n")
 fw_attr_td(ud, struct unit_directory, model_name_kv)
 
 static struct device_attribute *const fw_ud_attrs[] = {
@@ -865,7 +845,6 @@
 
 	ne->guid = guid;
 	ne->guid_vendor_id = (guid >> 40) & 0xffffff;
-	ne->guid_vendor_oui = nodemgr_find_oui_name(ne->guid_vendor_id);
 	ne->csr = csr;
 
 	memcpy(&ne->device, &nodemgr_dev_template_ne,
@@ -885,9 +864,6 @@
 		goto fail_classdevreg;
 	get_device(&ne->device);
 
-	if (ne->guid_vendor_oui &&
-	    device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui))
-		goto fail_addoiu;
 	nodemgr_create_ne_dev_files(ne);
 
 	nodemgr_update_bus_options(ne);
@@ -898,8 +874,6 @@
 
 	return ne;
 
-fail_addoiu:
-	put_device(&ne->device);
 fail_classdevreg:
 	device_unregister(&ne->device);
 fail_devreg:
@@ -975,15 +949,10 @@
 		goto fail_classdevreg;
 	get_device(&ud->device);
 
-	if (ud->vendor_oui &&
-	    device_create_file(&ud->device, &dev_attr_ud_vendor_oui))
-		goto fail_addoui;
 	nodemgr_create_ud_dev_files(ud);
 
 	return;
 
-fail_addoui:
-	put_device(&ud->device);
 fail_classdevreg:
 	device_unregister(&ud->device);
 fail_devreg:
@@ -1020,9 +989,6 @@
 			if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
 				ud->vendor_id = kv->value.immediate;
 				ud->flags |= UNIT_DIRECTORY_VENDOR_ID;
-
-				if (ud->vendor_id)
-					ud->vendor_oui = nodemgr_find_oui_name(ud->vendor_id);
 			}
 			break;
 
@@ -1153,9 +1119,6 @@
 		switch (kv->key.id) {
 		case CSR1212_KV_ID_VENDOR:
 			ne->vendor_id = kv->value.immediate;
-
-			if (ne->vendor_id)
-				ne->vendor_oui = nodemgr_find_oui_name(ne->vendor_id);
 			break;
 
 		case CSR1212_KV_ID_NODE_CAPABILITIES:
@@ -1183,9 +1146,6 @@
 		last_key_id = kv->key.id;
 	}
 
-	if (ne->vendor_oui &&
-	    device_create_file(&ne->device, &dev_attr_ne_vendor_oui))
-		goto fail;
 	if (ne->vendor_name_kv &&
 	    device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv))
 		goto fail;
@@ -1721,7 +1681,8 @@
 	for (;;) {
 		/* Sleep until next bus reset */
 		set_current_state(TASK_INTERRUPTIBLE);
-		if (get_hpsb_generation(host) == generation)
+		if (get_hpsb_generation(host) == generation &&
+		    !kthread_should_stop())
 			schedule();
 		__set_current_state(TASK_RUNNING);
 
@@ -1889,22 +1850,31 @@
 
 	error = class_register(&nodemgr_ne_class);
 	if (error)
-		return error;
-
+		goto fail_ne;
 	error = class_register(&nodemgr_ud_class);
-	if (error) {
-		class_unregister(&nodemgr_ne_class);
-		return error;
-	}
+	if (error)
+		goto fail_ud;
 	error = driver_register(&nodemgr_mid_layer_driver);
+	if (error)
+		goto fail_ml;
+	/* This driver is not used if nodemgr is off (disable_nodemgr=1). */
+	nodemgr_dev_template_host.driver = &nodemgr_mid_layer_driver;
+
 	hpsb_register_highlevel(&nodemgr_highlevel);
 	return 0;
+
+fail_ml:
+	class_unregister(&nodemgr_ud_class);
+fail_ud:
+	class_unregister(&nodemgr_ne_class);
+fail_ne:
+	return error;
 }
 
 void cleanup_ieee1394_nodemgr(void)
 {
 	hpsb_unregister_highlevel(&nodemgr_highlevel);
-
+	driver_unregister(&nodemgr_mid_layer_driver);
 	class_unregister(&nodemgr_ud_class);
 	class_unregister(&nodemgr_ne_class);
 }
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index e25cbad..4147303 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -70,7 +70,6 @@
 
 	quadlet_t vendor_id;
 	struct csr1212_keyval *vendor_name_kv;
-	const char *vendor_oui;
 
 	quadlet_t model_id;
 	struct csr1212_keyval *model_name_kv;
@@ -93,7 +92,6 @@
 struct node_entry {
 	u64 guid;			/* GUID of this node */
 	u32 guid_vendor_id;		/* Top 24bits of guid */
-	const char *guid_vendor_oui;	/* OUI name of guid vendor id */
 
 	struct hpsb_host *host;		/* Host this node is attached to */
 	nodeid_t nodeid;		/* NodeID */
@@ -104,7 +102,6 @@
 	/* The following is read from the config rom */
 	u32 vendor_id;
 	struct csr1212_keyval *vendor_name_kv;
-	const char *vendor_oui;
 
 	u32 capabilities;
 
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 628130a..06fac0d 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -102,7 +102,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/irq.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
@@ -181,7 +180,7 @@
 static void ohci1394_pci_remove(struct pci_dev *pdev);
 
 #ifndef __LITTLE_ENDIAN
-const static size_t hdr_sizes[] = {
+static const size_t hdr_sizes[] = {
 	3,	/* TCODE_WRITEQ */
 	4,	/* TCODE_WRITEB */
 	3,	/* TCODE_WRITE_RESPONSE */
@@ -3281,14 +3280,11 @@
 		PRINT(KERN_WARNING, "PCI resource length of 0x%llx too small!",
 		      (unsigned long long)pci_resource_len(dev, 0));
 
-	/* Seems PCMCIA handles this internally. Not sure why. Seems
-	 * pretty bogus to force a driver to special case this.  */
-#ifndef PCMCIA
-	if (!request_mem_region (ohci_base, OHCI1394_REGISTER_SIZE, OHCI1394_DRIVER_NAME))
+	if (!request_mem_region(ohci_base, OHCI1394_REGISTER_SIZE,
+				OHCI1394_DRIVER_NAME))
 		FAIL(-ENOMEM, "MMIO resource (0x%llx - 0x%llx) unavailable",
 			(unsigned long long)ohci_base,
 			(unsigned long long)ohci_base + OHCI1394_REGISTER_SIZE);
-#endif
 	ohci->init_state = OHCI_INIT_HAVE_MEM_REGION;
 
 	ohci->registers = ioremap(ohci_base, OHCI1394_REGISTER_SIZE);
@@ -3509,10 +3505,8 @@
 		iounmap(ohci->registers);
 
 	case OHCI_INIT_HAVE_MEM_REGION:
-#ifndef PCMCIA
 		release_mem_region(pci_resource_start(ohci->dev, 0),
 				   OHCI1394_REGISTER_SIZE);
-#endif
 
 #ifdef CONFIG_PPC_PMAC
 	/* On UniNorth, power down the cable and turn off the chip clock
@@ -3541,9 +3535,6 @@
 	int err;
 	struct ti_ohci *ohci = pci_get_drvdata(pdev);
 
-	printk(KERN_INFO "%s does not fully support suspend and resume yet\n",
-	       OHCI1394_DRIVER_NAME);
-
 	if (!ohci) {
 		printk(KERN_ERR "%s: tried to suspend nonexisting host\n",
 		       OHCI1394_DRIVER_NAME);
@@ -3630,15 +3621,14 @@
 	mdelay(50);
 	ohci_initialize(ohci);
 
+	hpsb_resume_host(ohci->host);
 	return 0;
 }
 #endif /* CONFIG_PM */
 
-#define PCI_CLASS_FIREWIRE_OHCI     ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10)
-
 static struct pci_device_id ohci1394_pci_tbl[] = {
 	{
-		.class = 	PCI_CLASS_FIREWIRE_OHCI,
+		.class = 	PCI_CLASS_SERIAL_FIREWIRE_OHCI,
 		.class_mask = 	PCI_ANY_ID,
 		.vendor =	PCI_ANY_ID,
 		.device =	PCI_ANY_ID,
diff --git a/drivers/ieee1394/oui.db b/drivers/ieee1394/oui.db
deleted file mode 100644
index 592c8a6..0000000
--- a/drivers/ieee1394/oui.db
+++ /dev/null
@@ -1,7048 +0,0 @@
-000000 XEROX CORPORATION
-000001 XEROX CORPORATION
-000002 XEROX CORPORATION
-000003 XEROX CORPORATION
-000004 XEROX CORPORATION
-000005 XEROX CORPORATION
-000006 XEROX CORPORATION
-000007 XEROX CORPORATION
-000008 XEROX CORPORATION
-000009 XEROX CORPORATION
-00000A OMRON TATEISI ELECTRONICS CO.
-00000B MATRIX CORPORATION
-00000C CISCO SYSTEMS, INC.
-00000D FIBRONICS LTD.
-00000E FUJITSU LIMITED
-00000F NEXT, INC.
-000010 SYTEK INC.
-000011 NORMEREL SYSTEMES
-000012 INFORMATION TECHNOLOGY LIMITED
-000013 CAMEX
-000014 NETRONIX
-000015 DATAPOINT CORPORATION
-000016 DU PONT PIXEL SYSTEMS     .
-000017 TEKELEC
-000018 WEBSTER COMPUTER CORPORATION
-000019 APPLIED DYNAMICS INTERNATIONAL
-00001A ADVANCED MICRO DEVICES
-00001B NOVELL INC.
-00001C BELL TECHNOLOGIES
-00001D CABLETRON SYSTEMS, INC.
-00001E TELSIST INDUSTRIA ELECTRONICA
-00001F Telco Systems, Inc.
-000020 DATAINDUSTRIER DIAB AB
-000021 SUREMAN COMP. & COMMUN. CORP.
-000022 VISUAL TECHNOLOGY INC.
-000023 ABB INDUSTRIAL SYSTEMS AB
-000024 CONNECT AS
-000025 RAMTEK CORP.
-000026 SHA-KEN CO., LTD.
-000027 JAPAN RADIO COMPANY
-000028 PRODIGY SYSTEMS CORPORATION
-000029 IMC NETWORKS CORP.
-00002A TRW - SEDD/INP
-00002B CRISP AUTOMATION, INC
-00002C AUTOTOTE LIMITED
-00002D CHROMATICS INC
-00002E SOCIETE EVIRA
-00002F TIMEPLEX INC.
-000030 VG LABORATORY SYSTEMS LTD
-000031 QPSX COMMUNICATIONS PTY LTD
-000032 Marconi plc
-000033 EGAN MACHINERY COMPANY
-000034 NETWORK RESOURCES CORPORATION
-000035 SPECTRAGRAPHICS CORPORATION
-000036 ATARI CORPORATION
-000037 OXFORD METRICS LIMITED
-000038 CSS LABS
-000039 TOSHIBA CORPORATION
-00003A CHYRON CORPORATION
-00003B i Controls, Inc.
-00003C AUSPEX SYSTEMS INC.
-00003D UNISYS
-00003E SIMPACT
-00003F SYNTREX, INC.
-000040 APPLICON, INC.
-000041 ICE CORPORATION
-000042 METIER MANAGEMENT SYSTEMS LTD.
-000043 MICRO TECHNOLOGY
-000044 CASTELLE CORPORATION
-000045 FORD AEROSPACE & COMM. CORP.
-000046 OLIVETTI NORTH AMERICA
-000047 NICOLET INSTRUMENTS CORP.
-000048 SEIKO EPSON CORPORATION
-000049 APRICOT COMPUTERS, LTD
-00004A ADC CODENOLL TECHNOLOGY CORP.
-00004B ICL DATA OY
-00004C NEC CORPORATION
-00004D DCI CORPORATION
-00004E AMPEX CORPORATION
-00004F LOGICRAFT, INC.
-000050 RADISYS CORPORATION
-000051 HOB ELECTRONIC GMBH & CO. KG
-000052 Intrusion.com, Inc.
-000053 COMPUCORP
-000054 MODICON, INC.
-000055 COMMISSARIAT A L`ENERGIE ATOM.
-000056 DR. B. STRUCK
-000057 SCITEX CORPORATION LTD.
-000058 RACORE COMPUTER PRODUCTS INC.
-000059 HELLIGE GMBH
-00005A SysKonnect GmbH
-00005B ELTEC ELEKTRONIK AG
-00005C TELEMATICS INTERNATIONAL INC.
-00005D CS TELECOM
-00005E USC INFORMATION SCIENCES INST
-00005F SUMITOMO ELECTRIC IND., LTD.
-000060 KONTRON ELEKTRONIK GMBH
-000061 GATEWAY COMMUNICATIONS
-000062 BULL HN INFORMATION SYSTEMS
-000063 DR.ING.SEUFERT GMBH
-000064 YOKOGAWA DIGITAL COMPUTER CORP
-000065 NETWORK ASSOCIATES, INC.
-000066 TALARIS SYSTEMS, INC.
-000067 SOFT * RITE, INC.
-000068 ROSEMOUNT CONTROLS
-000069 CONCORD COMMUNICATIONS INC
-00006A COMPUTER CONSOLES INC.
-00006B SILICON GRAPHICS INC./MIPS
-00006D CRAY COMMUNICATIONS, LTD.
-00006E ARTISOFT, INC.
-00006F Madge Ltd.
-000070 HCL LIMITED
-000071 ADRA SYSTEMS INC.
-000072 MINIWARE TECHNOLOGY
-000073 SIECOR CORPORATION
-000074 RICOH COMPANY LTD.
-000075 Nortel Networks
-000076 ABEKAS VIDEO SYSTEM
-000077 INTERPHASE CORPORATION
-000078 LABTAM LIMITED
-000079 NETWORTH INCORPORATED
-00007A DANA COMPUTER INC.
-00007B RESEARCH MACHINES
-00007C AMPERE INCORPORATED
-00007D SUN MICROSYSTEMS, INC.
-00007E CLUSTRIX CORPORATION
-00007F LINOTYPE-HELL AG
-000080 CRAY COMMUNICATIONS A/S
-000081 BAY NETWORKS
-000082 LECTRA SYSTEMES SA
-000083 TADPOLE TECHNOLOGY PLC
-000084 SUPERNET
-000085 CANON INC.
-000086 MEGAHERTZ CORPORATION
-000087 HITACHI, LTD.
-000088 COMPUTER NETWORK TECH. CORP.
-000089 CAYMAN SYSTEMS INC.
-00008A DATAHOUSE INFORMATION SYSTEMS
-00008B INFOTRON
-00008C Alloy Computer Products (Australia) Pty Ltd
-00008D VERDIX CORPORATION
-00008E SOLBOURNE COMPUTER, INC.
-00008F RAYTHEON COMPANY
-000090 MICROCOM
-000091 ANRITSU CORPORATION
-000092 COGENT DATA TECHNOLOGIES
-000093 PROTEON INC.
-000094 ASANTE TECHNOLOGIES
-000095 SONY TEKTRONIX CORP.
-000096 MARCONI ELECTRONICS LTD.
-000097 EPOCH SYSTEMS
-000098 CROSSCOMM CORPORATION
-000099 MTX, INC.
-00009A RC COMPUTER A/S
-00009B INFORMATION INTERNATIONAL, INC
-00009C ROLM MIL-SPEC COMPUTERS
-00009D LOCUS COMPUTING CORPORATION
-00009E MARLI S.A.
-00009F AMERISTAR TECHNOLOGIES INC.
-0000A0 TOKYO SANYO ELECTRIC CO. LTD.
-0000A1 MARQUETTE ELECTRIC CO.
-0000A2 BAY NETWORKS
-0000A3 NETWORK APPLICATION TECHNOLOGY
-0000A4 ACORN COMPUTERS LIMITED
-0000A5 COMPATIBLE SYSTEMS CORP.
-0000A6 NETWORK GENERAL CORPORATION
-0000A7 NETWORK COMPUTING DEVICES INC.
-0000A8 STRATUS COMPUTER INC.
-0000A9 NETWORK SYSTEMS CORP.
-0000AA XEROX CORPORATION
-0000AB LOGIC MODELING CORPORATION
-0000AC CONWARE COMPUTER CONSULTING
-0000AD BRUKER INSTRUMENTS INC.
-0000AE DASSAULT ELECTRONIQUE
-0000AF NUCLEAR DATA INSTRUMENTATION
-0000B0 RND-RAD NETWORK DEVICES
-0000B1 ALPHA MICROSYSTEMS INC.
-0000B2 TELEVIDEO SYSTEMS, INC.
-0000B3 CIMLINC INCORPORATED
-0000B4 EDIMAX COMPUTER COMPANY
-0000B5 DATABILITY SOFTWARE SYS. INC.
-0000B6 MICRO-MATIC RESEARCH
-0000B7 DOVE COMPUTER CORPORATION
-0000B8 SEIKOSHA CO., LTD.
-0000B9 MCDONNELL DOUGLAS COMPUTER SYS
-0000BA SIIG, INC.
-0000BB TRI-DATA
-0000BC ALLEN-BRADLEY CO. INC.
-0000BD MITSUBISHI CABLE COMPANY
-0000BE THE NTI GROUP
-0000BF SYMMETRIC COMPUTER SYSTEMS
-0000C0 WESTERN DIGITAL CORPORATION
-0000C1 Madge Ltd.
-0000C2 INFORMATION PRESENTATION TECH.
-0000C3 HARRIS CORP COMPUTER SYS DIV
-0000C4 WATERS DIV. OF MILLIPORE
-0000C5 FARALLON COMPUTING/NETOPIA
-0000C6 EON SYSTEMS
-0000C7 ARIX CORPORATION
-0000C8 ALTOS COMPUTER SYSTEMS
-0000C9 EMULEX CORPORATION
-0000CA APPLITEK
-0000CB COMPU-SHACK ELECTRONIC GMBH
-0000CC DENSAN CO., LTD.
-0000CD Allied Telesyn Research Ltd.
-0000CE MEGADATA CORP.
-0000CF HAYES MICROCOMPUTER PRODUCTS
-0000D0 DEVELCON ELECTRONICS LTD.
-0000D1 ADAPTEC INCORPORATED
-0000D2 SBE, INC.
-0000D3 WANG LABORATORIES INC.
-0000D4 PURE DATA LTD.
-0000D5 MICROGNOSIS INTERNATIONAL
-0000D6 PUNCH LINE HOLDING
-0000D7 DARTMOUTH COLLEGE
-0000D8 NOVELL, INC.
-0000D9 NIPPON TELEGRAPH & TELEPHONE
-0000DA ATEX
-0000DB BRITISH TELECOMMUNICATIONS PLC
-0000DC HAYES MICROCOMPUTER PRODUCTS
-0000DD TCL INCORPORATED
-0000DE CETIA
-0000DF BELL & HOWELL PUB SYS DIV
-0000E0 QUADRAM CORP.
-0000E1 GRID SYSTEMS
-0000E2 ACER TECHNOLOGIES CORP.
-0000E3 INTEGRATED MICRO PRODUCTS LTD
-0000E4 IN2 GROUPE INTERTECHNIQUE
-0000E5 SIGMEX LTD.
-0000E6 APTOR PRODUITS DE COMM INDUST
-0000E7 STAR GATE TECHNOLOGIES
-0000E8 ACCTON TECHNOLOGY CORP.
-0000E9 ISICAD, INC.
-0000EA UPNOD AB
-0000EB MATSUSHITA COMM. IND. CO. LTD.
-0000EC MICROPROCESS
-0000ED APRIL
-0000EE NETWORK DESIGNERS, LTD.
-0000EF KTI
-0000F0 SAMSUNG ELECTRONICS CO., LTD.
-0000F1 MAGNA COMPUTER CORPORATION
-0000F2 SPIDER COMMUNICATIONS
-0000F3 GANDALF DATA LIMITED
-0000F4 ALLIED TELESYN INTERNATIONAL
-0000F5 DIAMOND SALES LIMITED
-0000F6 APPLIED MICROSYSTEMS CORP.
-0000F7 YOUTH KEEP ENTERPRISE CO LTD
-0000F8 DIGITAL EQUIPMENT CORPORATION
-0000F9 QUOTRON SYSTEMS INC.
-0000FA MICROSAGE COMPUTER SYSTEMS INC
-0000FB RECHNER ZUR KOMMUNIKATION
-0000FC MEIKO
-0000FD HIGH LEVEL HARDWARE
-0000FE ANNAPOLIS MICRO SYSTEMS
-0000FF CAMTEC ELECTRONICS LTD.
-000100 EQUIP'TRANS
-000102 3COM CORPORATION
-000103 3COM CORPORATION
-000104 DVICO Co., Ltd.
-000105 BECKHOFF GmbH
-000106 Tews Datentechnik GmbH
-000107 Leiser GmbH
-000108 AVLAB Technology, Inc.
-000109 Nagano Japan Radio Co., Ltd.
-00010A CIS TECHNOLOGY INC.
-00010B Space CyberLink, Inc.
-00010C System Talks Inc.
-00010D CORECO, INC.
-00010E Bri-Link Technologies Co., Ltd
-00010F Nishan Systems, Inc.
-000110 Gotham Networks
-000111 iDigm Inc.
-000112 Shark Multimedia Inc.
-000113 OLYMPUS CORPORATION
-000114 KANDA TSUSHIN KOGYO CO., LTD.
-000115 EXTRATECH CORPORATION
-000116 Netspect Technologies, Inc.
-000117 CANAL +
-000118 EZ Digital Co., Ltd.
-000119 Action Controls Pty. Ltd.
-00011A EEH DataLink GmbH
-00011B Unizone Technologies, Inc.
-00011C Universal Talkware Corporation
-00011D Centillium Communications
-00011E Precidia Technologies, Inc.
-00011F RC Networks, Inc.
-000120 OSCILLOQUARTZ S.A.
-000121 RapidStream Inc.
-000122 Trend Communications, Ltd.
-000123 DIGITAL ELECTRONICS CORP.
-000124 Acer Incorporated
-000125 YAESU MUSEN CO., LTD.
-000126 PAC Labs
-000127 The OPEN Group Limited
-000128 EnjoyWeb, Inc.
-000129 DFI Inc.
-00012A Telematica Sistems Inteligente
-00012B TELENET Co., Ltd.
-00012C Aravox Technologies, Inc.
-00012D Komodo Technology
-00012E PC Partner Ltd.
-00012F Twinhead International Corp
-000130 Extreme Networks
-000131 Detection Systems, Inc.
-000132 Dranetz - BMI
-000133 KYOWA Electronic Instruments C
-000134 SIG Positec Systems AG
-000135 KDC Corp.
-000136 CyberTAN Technology, Inc.
-000137 IT Farm Corporation
-000138 XAVi Technologies Corp.
-000139 Point Multimedia Systems
-00013A SHELCAD COMMUNICATIONS, LTD.
-00013B BNA SYSTEMS
-00013C TIW SYSTEMS
-00013D RiscStation Ltd.
-00013E Ascom Tateco AB
-00013F Neighbor World Co., Ltd.
-000140 Sendtek Corporation
-000141 CABLE PRINT
-000142 Cisco Systems, Inc.
-000143 Cisco Systems, Inc.
-000144 Cereva Networks, Inc.
-000145 WINSYSTEMS, INC.
-000146 Tesco Controls, Inc.
-000147 Zhone Technologies
-000148 X-traWeb Inc.
-000149 T.D.T. Transfer Data Test GmbH
-00014A SONY COMPUTER SCIENCE LABS., I
-00014B Ennovate Networks, Inc.
-00014C Berkeley Process Control
-00014D Shin Kin Enterprises Co., Ltd
-00014E WIN Enterprises, Inc.
-00014F LUMINOUS Networks, Inc.
-000150 GILAT COMMUNICATIONS, LTD.
-000151 Ensemble Communications
-000152 CHROMATEK INC.
-000153 ARCHTEK TELECOM CORPORATION
-000154 G3M Corporation
-000155 Promise Technology, Inc.
-000156 FIREWIREDIRECT.COM, INC.
-000157 SYSWAVE CO., LTD
-000158 Electro Industries/Gauge Tech
-000159 S1 Corporation
-00015A Digital Video Broadcasting
-00015B ITALTEL S.p.A/RF-UP-I
-00015C CADANT INC.
-00015D Sun Microsystems, Inc
-00015E BEST TECHNOLOGY CO., LTD.
-00015F DIGITAL DESIGN GmbH
-000160 ELMEX Co., LTD.
-000161 Meta Machine Technology
-000162 Cygnet Technologies, Inc.
-000163 Cisco Systems, Inc.
-000164 Cisco Systems, Inc.
-000165 AirSwitch Corporation
-000166 TC GROUP A/S
-000167 HIOKI E.E. CORPORATION
-000168 VITANA CORPORATION
-000169 Celestix Networks Pte Ltd.
-00016A ALITEC
-00016B LightChip, Inc.
-00016C FOXCONN
-00016D CarrierComm Inc.
-00016E Conklin Corporation
-00016F HAITAI ELECTRONICS CO., LTD.
-000170 ESE Embedded System Engineer'g
-000171 Allied Data Technologies
-000172 TechnoLand Co., LTD.
-000173 JNI Corporation
-000174 CyberOptics Corporation
-000175 Radiant Communications Corp.
-000176 Orient Silver Enterprises
-000177 EDSL
-000178 MARGI Systems, Inc.
-000179 WIRELESS TECHNOLOGY, INC.
-00017A Chengdu Maipu Electric Industrial Co., Ltd.
-00017B Heidelberger Druckmaschinen AG
-00017C AG-E GmbH
-00017D ThermoQuest
-00017E ADTEK System Science Co., Ltd.
-00017F Experience Music Project
-000180 AOpen, Inc.
-000181 Nortel Networks
-000182 DICA TECHNOLOGIES AG
-000183 ANITE TELECOMS
-000184 SIEB & MEYER AG
-000185 Aloka Co., Ltd.
-000186 DISCH GmbH
-000187 i2SE GmbH
-000188 LXCO Technologies ag
-000189 Refraction Technology, Inc.
-00018A ROI COMPUTER AG
-00018B NetLinks Co., Ltd.
-00018C Mega Vision
-00018D AudeSi Technologies
-00018E Logitec Corporation
-00018F Kenetec, Inc.
-000190 SMK-M
-000191 SYRED Data Systems
-000192 Texas Digital Systems
-000193 Hanbyul Telecom Co., Ltd.
-000194 Capital Equipment Corporation
-000195 Sena Technologies, Inc.
-000196 Cisco Systems, Inc.
-000197 Cisco Systems, Inc.
-000198 Darim Vision
-000199 HeiSei Electronics
-00019A LEUNIG GmbH
-00019B Kyoto Microcomputer Co., Ltd.
-00019C JDS Uniphase Inc.
-00019D E-Control Systems, Inc.
-00019E ESS Technology, Inc.
-00019F Phonex Broadband
-0001A0 Infinilink Corporation
-0001A1 Mag-Tek, Inc.
-0001A2 Logical Co., Ltd.
-0001A3 GENESYS LOGIC, INC.
-0001A4 Microlink Corporation
-0001A5 Nextcomm, Inc.
-0001A6 Scientific-Atlanta Arcodan A/S
-0001A7 UNEX TECHNOLOGY CORPORATION
-0001A8 Welltech Computer Co., Ltd.
-0001A9 BMW AG
-0001AA Airspan Communications, Ltd.
-0001AB Main Street Networks
-0001AC Sitara Networks, Inc.
-0001AD Coach Master International  d.b.a. CMI Worldwide, Inc.
-0001AE Trex Enterprises
-0001AF Motorola Computer Group
-0001B0 Fulltek Technology Co., Ltd.
-0001B1 General Bandwidth
-0001B2 Digital Processing Systems, Inc.
-0001B3 Precision Electronic Manufacturing
-0001B4 Wayport, Inc.
-0001B5 Turin Networks, Inc.
-0001B6 SAEJIN T&M Co., Ltd.
-0001B7 Centos, Inc.
-0001B8 Netsensity, Inc.
-0001B9 SKF Condition Monitoring
-0001BA IC-Net, Inc.
-0001BB Frequentis
-0001BC Brains Corporation
-0001BD Peterson Electro-Musical Products, Inc.
-0001BE Gigalink Co., Ltd.
-0001BF Teleforce Co., Ltd.
-0001C0 CompuLab, Ltd.
-0001C1 Vitesse Semiconductor Corporation
-0001C2 ARK Research Corp.
-0001C3 Acromag, Inc.
-0001C4 NeoWave, Inc.
-0001C5 Simpler Networks
-0001C6 Quarry Technologies
-0001C7 Cisco Systems, Inc.
-0001C8 THOMAS CONRAD CORP.
-0001C8 CONRAD CORP.
-0001C9 Cisco Systems, Inc.
-0001CA Geocast Network Systems, Inc.
-0001CB NetGame, Ltd.
-0001CC Japan Total Design Communication Co., Ltd.
-0001CD ARtem
-0001CE Custom Micro Products, Ltd.
-0001CF Alpha Data Parallel Systems, Ltd.
-0001D0 VitalPoint, Inc.
-0001D1 CoNet Communications, Inc.
-0001D2 MacPower Peripherals, Ltd.
-0001D3 PAXCOMM, Inc.
-0001D4 Leisure Time, Inc.
-0001D5 HAEDONG INFO & COMM CO., LTD
-0001D6 MAN Roland Druckmaschinen AG
-0001D7 F5 Networks, Inc.
-0001D8 Teltronics, Inc.
-0001D9 Sigma, Inc.
-0001DA WINCOMM Corporation
-0001DB Freecom Technologies GmbH
-0001DC Activetelco
-0001DD Avail Networks
-0001DE Trango Systems, Inc.
-0001DF ISDN Communications, Ltd.
-0001E0 Fast Systems, Inc.
-0001E1 Kinpo Electronics, Inc.
-0001E2 Ando Electric Corporation
-0001E3 Siemens AG
-0001E4 Sitera, Inc.
-0001E5 Supernet, Inc.
-0001E6 Hewlett-Packard Company
-0001E7 Hewlett-Packard Company
-0001E8 Force10 Networks, Inc.
-0001E9 Litton Marine Systems B.V.
-0001EA Cirilium Corp.
-0001EB C-COM Corporation
-0001EC Ericsson Group
-0001ED SETA Corp.
-0001EE Comtrol Europe, Ltd.
-0001EF Camtel Technology Corp.
-0001F0 Tridium, Inc.
-0001F1 Innovative Concepts, Inc.
-0001F2 Mark of the Unicorn, Inc.
-0001F3 QPS, Inc.
-0001F4 Enterasys Networks
-0001F5 ERIM S.A.
-0001F6 Association of Musical Electronics Industry
-0001F7 Image Display Systems, Inc.
-0001F8 Adherent Systems, Ltd.
-0001F9 TeraGlobal Communications Corp.
-0001FA HOROSCAS
-0001FB DoTop Technology, Inc.
-0001FC Keyence Corporation
-0001FD Digital Voice Systems, Inc.
-0001FE DIGITAL EQUIPMENT CORPORATION
-0001FF Data Direct Networks, Inc.
-000200 Net & Sys Co., Ltd.
-000201 IFM Electronic gmbh
-000202 Amino Communications, Ltd.
-000203 Woonsang Telecom, Inc.
-000204 Bodmann Industries Elektronik GmbH
-000205 Hitachi Denshi, Ltd.
-000206 Telital R&D Denmark A/S
-000207 VisionGlobal Network Corp.
-000208 Unify Networks, Inc.
-000209 Shenzhen SED Information Technology Co., Ltd.
-00020A Gefran Spa
-00020B Native Networks, Inc.
-00020C Metro-Optix
-00020D Micronpc.com
-00020E Laurel Networks, Inc.
-00020F AATR
-000210 Fenecom
-000211 Nature Worldwide Technology Corp.
-000212 SierraCom
-000213 S.D.E.L.
-000214 DTVRO
-000215 Cotas Computer Technology A/B
-000216 Cisco Systems, Inc.
-000217 Cisco Systems, Inc.
-000218 Advanced Scientific Corp
-000219 Paralon Technologies
-00021A Zuma Networks
-00021B Kollmorgen-Servotronix
-00021C Network Elements, Inc.
-00021D Data General Communication Ltd.
-00021E SIMTEL S.R.L.
-00021F Aculab PLC
-000220 Canon Aptex, Inc.
-000221 DSP Application, Ltd.
-000222 Chromisys, Inc.
-000223 ClickTV
-000224 Lantern Communications, Inc.
-000225 Certus Technology, Inc.
-000226 XESystems, Inc.
-000227 ESD GmbH
-000228 Necsom, Ltd.
-000229 Adtec Corporation
-00022A Asound Electronic
-00022B Tamura Electric Works, Ltd.
-00022C ABB Bomem, Inc.
-00022D Agere Systems
-00022E TEAC Corp. R& D
-00022F P-Cube, Ltd.
-000230 Intersoft Electronics
-000231 Ingersoll-Rand
-000232 Avision, Inc.
-000233 Mantra Communications, Inc.
-000234 Imperial Technology, Inc.
-000235 Paragon Networks International
-000236 INIT GmbH
-000237 Cosmo Research Corp.
-000238 Serome Technology, Inc.
-000239 Visicom
-00023A ZSK Stickmaschinen GmbH
-00023B Redback Networks
-00023C Creative Technology, Ltd.
-00023D NuSpeed, Inc.
-00023E Selta Telematica S.p.a
-00023F Compal Electronics, Inc.
-000240 Seedek Co., Ltd.
-000241 Amer.com
-000242 Videoframe Systems
-000243 Raysis Co., Ltd.
-000244 SURECOM Technology Co.
-000245 Lampus Co, Ltd.
-000246 All-Win Tech Co., Ltd.
-000247 Great Dragon Information Technology (Group) Co., Ltd.
-000248 Pilz GmbH & Co.
-000249 Aviv Infocom Co, Ltd.
-00024A Cisco Systems, Inc.
-00024B Cisco Systems, Inc.
-00024C SiByte, Inc.
-00024D Mannesman Dematic Colby Pty. Ltd.
-00024E Datacard Group
-00024F IPM Datacom S.R.L.
-000250 Geyser Networks, Inc.
-000251 Soma Networks
-000252 Carrier Corporation
-000253 Televideo, Inc.
-000254 WorldGate
-000255 IBM Corporation
-000256 Alpha Processor, Inc.
-000257 Microcom Corp.
-000258 Flying Packets Communications
-000259 Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group
-00025A Catena Networks
-00025B Cambridge Silicon Radio
-00025C SCI Systems (Kunshan) Co., Ltd.
-00025D Calix Networks
-00025E High Technology Ltd
-00025F Nortel Networks
-000260 Accordion Networks, Inc.
-000261 i3 Micro Technology AB
-000262 Soyo Group Soyo Com Tech Co., Ltd
-000263 UPS Manufacturing SRL
-000264 AudioRamp.com
-000265 Virditech Co. Ltd.
-000266 Thermalogic Corporation
-000267 NODE RUNNER, INC.
-000268 Harris Government Communications
-000269 Nadatel Co., Ltd
-00026A Cocess Telecom Co., Ltd.
-00026B BCM Computers Co., Ltd.
-00026C Philips CFT
-00026D Adept Telecom
-00026E NeGeN Access, Inc.
-00026F Senao International Co., Ltd.
-000270 Crewave Co., Ltd.
-000271 Vpacket Communications
-000272 CC&C Technologies, Inc.
-000273 Coriolis Networks
-000274 Tommy Technologies Corp.
-000275 SMART Technologies, Inc.
-000276 Primax Electronics Ltd.
-000277 Cash Systemes Industrie
-000278 Samsung Electro-Mechanics Co., Ltd.
-000279 Control Applications, Ltd.
-00027A IOI Technology Corporation
-00027B Amplify Net, Inc.
-00027C Trilithic, Inc.
-00027D Cisco Systems, Inc.
-00027E Cisco Systems, Inc.
-00027F ask-technologies.com
-000280 Mu Net, Inc.
-000281 Madge Ltd.
-000282 ViaClix, Inc.
-000283 Spectrum Controls, Inc.
-000284 Alstom T&D P&C
-000285 Riverstone Networks
-000286 Occam Networks
-000287 Adapcom
-000288 GLOBAL VILLAGE COMMUNICATION
-000289 DNE Technologies
-00028A Ambit Microsystems Corporation
-00028B VDSL Systems OY
-00028C Micrel-Synergy Semiconductor
-00028D Movita Technologies, Inc.
-00028E Rapid 5 Networks, Inc.
-00028F Globetek, Inc.
-000290 Woorigisool, Inc.
-000291 Open Network Co., Ltd.
-000292 Logic Innovations, Inc.
-000293 Solid Data Systems
-000294 Tokyo Sokushin Co., Ltd.
-000295 IP.Access Limited
-000296 Lectron Co,. Ltd.
-000297 C-COR.net
-000298 Broadframe Corporation
-000299 Apex, Inc.
-00029A Storage Apps
-00029B Kreatel Communications AB
-00029C 3COM
-00029D Merix Corp.
-00029E Information Equipment Co., Ltd.
-00029F L-3 Communication Aviation Recorders
-0002A0 Flatstack Ltd.
-0002A1 World Wide Packets
-0002A2 Hilscher GmbH
-0002A3 ABB Power Automation
-0002A4 AddPac Technology Co., Ltd.
-0002A5 Compaq Computer Corporation
-0002A6 Effinet Systems Co., Ltd.
-0002A7 Vivace Networks
-0002A8 Air Link Technology
-0002A9 RACOM, s.r.o.
-0002AA PLcom Co., Ltd.
-0002AB CTC Union Technologies Co., Ltd.
-0002AC 3PAR data
-0002AD Pentax Corpotation
-0002AE Scannex Electronics Ltd.
-0002AF TeleCruz Technology, Inc.
-0002B0 Hokubu Communication & Industrial Co., Ltd.
-0002B1 Anritsu, Ltd.
-0002B2 Cablevision
-0002B3 Intel Corporation
-0002B4 DAPHNE
-0002B5 Avnet, Inc.
-0002B6 Acrosser Technology Co., Ltd.
-0002B7 Watanabe Electric Industry Co., Ltd.
-0002B8 WHI KONSULT AB
-0002B9 Cisco Systems, Inc.
-0002BA Cisco Systems, Inc.
-0002BB Continuous Computing
-0002BC LVL 7 Systems, Inc.
-0002BD Bionet Co., Ltd.
-0002BE Totsu Engineering, Inc.
-0002BF dotRocket, Inc.
-0002C0 Bencent Tzeng Industry Co., Ltd.
-0002C1 Innovative Electronic Designs, Inc.
-0002C2 Net Vision Telecom
-0002C3 Arelnet Ltd.
-0002C4 Vector International BUBA
-0002C5 Evertz Microsystems Ltd.
-0002C6 Data Track Technology PLC
-0002C7 ALPS ELECTRIC Co., Ltd.
-0002C8 Technocom Communications Technology (pte) Ltd
-0002C9 Mellanox Technologies
-0002CA EndPoints, Inc.
-0002CB TriState Ltd.
-0002CC M.C.C.I
-0002CD TeleDream, Inc.
-0002CE FoxJet, Inc.
-0002CF ZyGate Communications, Inc.
-0002D0 Comdial Corporation
-0002D1 Vivotek, Inc.
-0002D2 Workstation AG
-0002D3 NetBotz, Inc.
-0002D4 PDA Peripherals, Inc.
-0002D5 ACR
-0002D6 NICE Systems
-0002D7 EMPEG Ltd
-0002D8 BRECIS Communications Corporation
-0002D9 Reliable Controls
-0002DA ExiO Communications, Inc.
-0002DB NETSEC
-0002DC Fujitsu General Limited
-0002DD Bromax Communications, Ltd.
-0002DE Astrodesign, Inc.
-0002DF Net Com Systems, Inc.
-0002E0 ETAS GmbH
-0002E1 Integrated Network Corporation
-0002E2 NDC Infared Engineering
-0002E3 LITE-ON Communications, Inc.
-0002E4 JC HYUN Systems, Inc.
-0002E5 Timeware Ltd.
-0002E6 Gould Instrument Systems, Inc.
-0002E7 CAB GmbH & Co KG
-0002E8 E.D.&A.
-0002E9 CS Systemes De Securite - C3S
-0002EA Videonics, Inc.
-0002EB Pico Communications
-0002EC Maschoff Design Engineering
-0002ED DXO Telecom Co., Ltd.
-0002EE Nokia Danmark A/S
-0002EF CCC Network Systems Group Ltd.
-0002F0 AME Optimedia Technology Co., Ltd.
-0002F1 Pinetron Co., Ltd.
-0002F2 eDevice, Inc.
-0002F3 Media Serve Co., Ltd.
-0002F4 PCTEL, Inc.
-0002F5 VIVE Synergies, Inc.
-0002F6 Equipe Communications
-0002F7 ARM
-0002F8 SEAKR Engineering, Inc.
-0002F9 Mimos Semiconductor SDN BHD
-0002FA DX Antenna Co., Ltd.
-0002FB Baumuller Aulugen-Systemtechnik GmbH
-0002FC Cisco Systems, Inc.
-0002FD Cisco Systems, Inc.
-0002FE Viditec, Inc.
-0002FF Handan BroadInfoCom
-000300 NetContinuum, Inc.
-000301 Avantas Networks Corporation
-000302 Oasys Telecom, Inc.
-000303 JAMA Electronics Co., Ltd.
-000304 Pacific Broadband Communications
-000305 Smart Network Devices GmbH
-000306 Fusion In Tech Co., Ltd.
-000307 Secure Works, Inc.
-000308 AM Communications, Inc.
-000309 Texcel Technology PLC
-00030A Argus Technologies
-00030B Hunter Technology, Inc.
-00030C Telesoft Technologies Ltd.
-00030D Uniwill Computer Corp.
-00030E Core Communications Co., Ltd.
-00030F Digital China (Shanghai) Networks Ltd.
-000310 Link Evolution Corp.
-000311 Micro Technology Co., Ltd.
-000312 TR-Systemtechnik GmbH
-000313 Access Media SPA
-000314 Teleware Network Systems
-000315 Cidco Incorporated
-000316 Nobell Communications, Inc.
-000317 Merlin Systems, Inc.
-000318 Cyras Systems, Inc.
-000319 Infineon AG
-00031A Beijing Broad Telecom Ltd., China
-00031B Cellvision Systems, Inc.
-00031C Svenska Hardvarufabriken AB
-00031D Taiwan Commate Computer, Inc.
-00031E Optranet, Inc.
-00031F Condev Ltd.
-000320 Xpeed, Inc.
-000321 Reco Research Co., Ltd.
-000322 IDIS Co., Ltd.
-000323 Cornet Technology, Inc.
-000324 SANYO Multimedia Tottori Co., Ltd.
-000325 Arima Computer Corp.
-000326 Iwasaki Information Systems Co., Ltd.
-000327 ACT'L
-000328 Mace Group, Inc.
-000329 F3, Inc.
-00032A UniData Communication Systems, Inc.
-00032B GAI Datenfunksysteme GmbH
-00032C ABB Industrie AG
-00032D IBASE Technology, Inc.
-00032E Scope Information Management, Ltd.
-00032F Global Sun Technology, Inc.
-000330 Imagenics, Co., Ltd.
-000331 Cisco Systems, Inc.
-000332 Cisco Systems, Inc.
-000333 Digitel Co., Ltd.
-000334 Newport Electronics
-000335 Mirae Technology
-000336 Zetes Technologies
-000337 Vaone, Inc.
-000338 Oak Technology
-000339 Eurologic Systems, Ltd.
-00033A Silicon Wave, Inc.
-00033B TAMI Tech Co., Ltd.
-00033C Daiden Co., Ltd.
-00033D ILSHin Lab
-00033E Tateyama System Laboratory Co., Ltd.
-00033F BigBand Networks, Ltd.
-000340 Floware Wireless Systems, Ltd.
-000341 Axon Digital Design
-000342 Nortel Networks
-000343 Martin Professional A/S
-000344 Tietech.Co., Ltd.
-000345 Routrek Networks Corporation
-000346 Hitachi Kokusai Electric, Inc.
-000347 Intel Corporation
-000348 Norscan Instruments, Ltd.
-000349 Vidicode Datacommunicatie B.V.
-00034A RIAS Corporation
-00034B Nortel Networks
-00034C Shanghai DigiVision Technology Co., Ltd.
-00034D Chiaro Networks, Ltd.
-00034E Pos Data Company, Ltd.
-00034F Sur-Gard Security
-000350 BTICINO SPA
-000351 Diebold, Inc.
-000352 Colubris Networks
-000353 Mitac, Inc.
-000354 Fiber Logic Communications
-000355 TeraBeam Internet Systems
-000356 Wincor Nixdorf GmbH & Co KG
-000357 Intervoice-Brite, Inc.
-000358 iCable System Co., Ltd.
-000359 DigitalSis
-00035A Photron Limited
-00035B BridgeWave Communications
-00035C Saint Song Corp.
-00035D Bosung Hi-Net Co., Ltd.
-00035E Metropolitan Area Networks, Inc.
-00035F Prueftechnik Condition Monitoring GmbH & Co. KG
-000360 PAC Interactive Technology, Inc.
-000361 Widcomm, Inc.
-000362 Vodtel Communications, Inc.
-000363 Miraesys Co., Ltd.
-000364 Scenix Semiconductor, Inc.
-000365 Kira Information & Communications, Ltd.
-000366 ASM Pacific Technology
-000367 Jasmine Networks, Inc.
-000368 Embedone Co., Ltd.
-000369 Nippon Antenna Co., Ltd.
-00036A Mainnet, Ltd.
-00036B Cisco Systems, Inc.
-00036C Cisco Systems, Inc.
-00036D Runtop, Inc.
-00036E Nicon Systems (Pty) Limited
-00036F Telsey SPA
-000370 NXTV, Inc.
-000371 Acomz Networks Corp.
-000372 ULAN
-000373 Aselsan A.S
-000374 Hunter Watertech
-000375 NetMedia, Inc.
-000376 Graphtec Technology, Inc.
-000377 Gigabit Wireless
-000378 HUMAX Co., Ltd.
-000379 Proscend Communications, Inc.
-00037A Taiyo Yuden Co., Ltd.
-00037B IDEC IZUMI Corporation
-00037C Coax Media
-00037D Stellcom
-00037E PORTech Communications, Inc.
-00037F Atheros Communications, Inc.
-000380 SSH Communications Security Corp.
-000381 Ingenico International
-000382 A-One Co., Ltd.
-000383 Metera Networks, Inc.
-000384 AETA
-000385 Actelis Networks, Inc.
-000386 Ho Net, Inc.
-000387 Blaze Network Products
-000388 Fastfame Technology Co., Ltd.
-000389 Plantronics
-00038A America Online, Inc.
-00038B PLUS-ONE I&T, Inc.
-00038C Total Impact
-00038D PCS Revenue Control Systems, Inc.
-00038E Atoga Systems, Inc.
-00038F Weinschel Corporation
-000390 Digital Video Communications, Inc.
-000392 Hyundai Teletek Co., Ltd.
-000393 Apple Computer, Inc.
-000394 Connect One
-000395 California Amplifier
-000396 EZ Cast Co., Ltd.
-000397 Watchfront Electronics
-000398 WISI
-000399 Dongju Informations & Communications Co., Ltd.
-00039A nSine, Ltd.
-00039B NetChip Technology, Inc.
-00039C OptiMight Communications, Inc.
-00039D BENQ CORPORATION
-00039E Tera System Co., Ltd.
-00039F Cisco Systems, Inc.
-0003A0 Cisco Systems, Inc.
-0003A1 HIPER Information & Communication, Inc.
-0003A2 Catapult Communications
-0003A3 MAVIX, Ltd.
-0003A4 Data Storage and Information Management
-0003A5 Medea Corporation
-0003A7 Unixtar Technology, Inc.
-0003A8 IDOT Computers, Inc.
-0003A9 AXCENT Media AG
-0003AA Watlow
-0003AB Bridge Information Systems
-0003AC Fronius Schweissmaschinen
-0003AD Emerson Energy Systems AB
-0003AE Allied Advanced Manufacturing Pte, Ltd.
-0003AF Paragea Communications
-0003B0 Xsense Technology Corp.
-0003B1 Abbott Laboratories HPD
-0003B2 Radware
-0003B3 IA Link Systems Co., Ltd.
-0003B4 Macrotek International Corp.
-0003B5 Entra Technology Co.
-0003B6 QSI Corporation
-0003B7 ZACCESS Systems
-0003B8 NetKit Solutions, LLC
-0003B9 Hualong Telecom Co., Ltd.
-0003BA Sun Microsystems
-0003BB Signal Communications Limited
-0003BC COT GmbH
-0003BD OmniCluster Technologies, Inc.
-0003BE Netility
-0003BF Centerpoint Broadband Technologies, Inc.
-0003C0 RFTNC Co., Ltd.
-0003C1 Packet Dynamics Ltd
-0003C2 Solphone K.K.
-0003C3 Micronik Multimedia
-0003C4 Tomra Systems ASA
-0003C5 Mobotix AG
-0003C6 ICUE Systems, Inc.
-0003C7 hopf Elektronik GmbH
-0003C8 CML Emergency Services
-0003C9 TECOM Co., Ltd.
-0003CA MTS Systems Corp.
-0003CB Nippon Systems Development Co., Ltd.
-0003CC Momentum Computer, Inc.
-0003CD Clovertech, Inc.
-0003CE ETEN Technologies, Inc.
-0003CF Muxcom, Inc.
-0003D0 KOANKEISO Co., Ltd.
-0003D1 Takaya Corporation
-0003D2 Crossbeam Systems, Inc.
-0003D3 Internet Energy Systems, Inc.
-0003D4 Alloptic, Inc.
-0003D5 Advanced Communications Co., Ltd.
-0003D6 RADVision, Ltd.
-0003D7 NextNet Wireless, Inc.
-0003D8 iMPath Networks, Inc.
-0003D9 Secheron SA
-0003DA Takamisawa Cybernetics Co., Ltd.
-0003DB Apogee Electronics Corp.
-0003DC Lexar Media, Inc.
-0003DD Comark Corp.
-0003DE OTC Wireless
-0003DF Desana Systems
-0003E0 RadioFrame Networks, Inc.
-0003E1 Winmate Communication, Inc.
-0003E2 Comspace Corporation
-0003E3 Cisco Systems, Inc.
-0003E4 Cisco Systems, Inc.
-0003E5 Hermstedt SG
-0003E6 Entone Technologies, Inc.
-0003E7 Logostek Co. Ltd.
-0003E8 Wavelength Digital Limited
-0003E9 Akara Canada, Inc.
-0003EA Mega System Technologies, Inc.
-0003EB Atrica
-0003EC ICG Research, Inc.
-0003ED Shinkawa Electric Co., Ltd.
-0003EE MKNet Corporation
-0003EF Oneline AG
-0003F0 Redfern Broadband Networks
-0003F1 Cicada Semiconductor, Inc.
-0003F2 Seneca Networks
-0003F3 Dazzle Multimedia, Inc.
-0003F4 NetBurner
-0003F5 Chip2Chip
-0003F6 Allegro Networks, Inc.
-0003F7 Plast-Control GmbH
-0003F8 SanCastle Technologies, Inc.
-0003F9 Pleiades Communications, Inc.
-0003FA TiMetra Networks
-0003FB Toko Seiki Company, Ltd.
-0003FC Intertex Data AB
-0003FD Cisco Systems, Inc.
-0003FE Cisco Systems, Inc.
-0003FF Connectix
-000400 LEXMARK INTERNATIONAL, INC.
-000401 Osaki Electric Co., Ltd.
-000402 Nexsan Technologies, Ltd.
-000403 Nexsi Corporation
-000404 Makino Milling Machine Co., Ltd.
-000405 ACN Technologies
-000406 Fa. Metabox AG
-000407 Topcon Positioning Systems, Inc.
-000408 Sanko Electronics Co., Ltd.
-000409 Cratos Networks
-00040A Sage Systems
-00040B 3com Europe Ltd.
-00040C KANNO Work's Ltd.
-00040D Avaya, Inc.
-00040E AVM GmbH
-00040F Asus Network Technologies, Inc.
-000410 Spinnaker Networks, Inc.
-000411 Inkra Networks, Inc.
-000412 WaveSmith Networks, Inc.
-000413 SNOM Technology AG
-000414 Umezawa Musen Denki Co., Ltd.
-000415 Rasteme Systems Co., Ltd.
-000416 Parks S/A Comunicacoes Digitais
-000417 ELAU AG
-000418 Teltronic S.A.U.
-000419 Fibercycle Networks, Inc.
-00041A ines GmbH
-00041B Digital Interfaces Ltd.
-00041C ipDialog, Inc.
-00041D Corega of America
-00041E Shikoku Instrumentation Co., Ltd.
-00041F Sony Computer Entertainment, Inc.
-000420 Slim Devices, Inc.
-000421 Ocular Networks
-000422 Gordon Kapes, Inc.
-000423 Intel Corporation
-000424 TMC s.r.l.
-000425 Atmel Corporation
-000426 Autosys
-000427 Cisco Systems, Inc.
-000428 Cisco Systems, Inc.
-000429 Pixord Corporation
-00042A Wireless Networks, Inc.
-00042B IT Access Co., Ltd.
-00042C Minet, Inc.
-00042D Sarian Systems, Ltd.
-00042E Netous Technologies, Ltd.
-00042F International Communications Products, Inc.
-000430 Netgem
-000431 GlobalStreams, Inc.
-000432 Voyetra Turtle Beach, Inc.
-000433 Cyberboard A/S
-000434 Accelent Systems, Inc.
-000435 Comptek International, Inc.
-000436 ELANsat Technologies, Inc.
-000437 Powin Information Technology, Inc.
-000438 Nortel Networks
-000439 Rosco Entertainment Technology, Inc.
-00043A Intelligent Telecommunications, Inc.
-00043B Lava Computer Mfg., Inc.
-00043C SONOS Co., Ltd.
-00043D INDEL AG
-00043E Telencomm
-00043F Electronic Systems Technology, Inc.
-000440 cyberPIXIE, Inc.
-000441 Half Dome Systems, Inc.
-000442 NACT
-000443 Agilent Technologies, Inc.
-000444 Western Multiplex Corporation
-000445 LMS Skalar Instruments GmbH
-000446 CYZENTECH Co., Ltd.
-000447 Acrowave Systems Co., Ltd.
-000448 Polaroid Professional Imaging
-000449 Mapletree Networks
-00044A iPolicy Networks, Inc.
-00044B NVIDIA
-00044C JENOPTIK
-00044D Cisco Systems, Inc.
-00044E Cisco Systems, Inc.
-00044F Leukhardt Systemelektronik GmbH
-000450 DMD Computers SRL
-000451 Medrad, Inc.
-000452 RocketLogix, Inc.
-000453 YottaYotta, Inc.
-000454 Quadriga UK
-000455 ANTARA.net
-000456 PipingHot Networks
-000457 Universal Access Technology, Inc.
-000458 Fusion X Co., Ltd.
-000459 Veristar Corporation
-00045A The Linksys Group, Inc.
-00045B Techsan Electronics Co., Ltd.
-00045C Mobiwave Pte Ltd
-00045D BEKA Elektronik
-00045E PolyTrax Information Technology AG
-00045F Evalue Technology, Inc.
-000460 Knilink Technology, Inc.
-000461 EPOX Computer Co., Ltd.
-000462 DAKOS Data & Communication Co., Ltd.
-000463 Bosch Security Systems
-000464 Fantasma Networks, Inc.
-000465 i.s.t isdn-support technik GmbH
-000466 ARMITEL Co.
-000467 Wuhan Research Institute of MII
-000468 Vivity, Inc.
-000469 Innocom, Inc.
-00046A Navini Networks
-00046B Palm Wireless, Inc.
-00046C Cyber Technology Co., Ltd.
-00046D Cisco Systems, Inc.
-00046E Cisco Systems, Inc.
-00046F Digitel S/A Industria Eletronica
-000470 ipUnplugged AB
-000471 IPrad
-000472 Telelynx, Inc.
-000473 Photonex Corporation
-000474 LEGRAND
-000475 3 Com Corporation
-000476 3 Com Corporation
-000477 Scalant Systems, Inc.
-000478 G. Star Technology Corporation
-000479 Radius Co., Ltd.
-00047A AXXESSIT ASA
-00047B Schlumberger
-00047C Skidata AG
-00047D Pelco
-00047E NKF Electronics
-00047F Chr. Mayr GmbH & Co. KG
-000480 Foundry Networks, Inc.
-000481 Econolite Control Products, Inc.
-000482 Medialogic Corp.
-000483 Deltron Technology, Inc.
-000484 Amann GmbH
-000485 PicoLight
-000486 ITTC, University of Kansas
-000487 Cogency Semiconductor, Inc.
-000488 Eurotherm Action Incorporated.
-000489 YAFO Networks, Inc.
-00048A Temia Vertriebs GmbH
-00048B Poscon Corporation
-00048C Nayna Networks, Inc.
-00048D Tone Commander Systems, Inc.
-00048E Ohm Tech Labs, Inc.
-00048F TD Systems Corp.
-000490 Optical Access
-000491 Technovision, Inc.
-000492 Hive Internet, Ltd.
-000493 Tsinghua Unisplendour Co., Ltd.
-000494 Breezecom, Ltd.
-000495 Tejas Networks
-000496 Extreme Networks
-000497 MacroSystem Digital Video AG
-000499 Chino Corporation
-00049A Cisco Systems, Inc.
-00049B Cisco Systems, Inc.
-00049C Surgient Networks, Inc.
-00049D Ipanema Technologies
-00049E Wirelink Co., Ltd.
-00049F Metrowerks
-0004A0 Verity Instruments, Inc.
-0004A1 Pathway Connectivity
-0004A2 L.S.I. Japan Co., Ltd.
-0004A3 Microchip Technology, Inc.
-0004A4 NetEnabled, Inc.
-0004A5 Barco Projection Systems NV
-0004A6 SAF Tehnika Ltd.
-0004A7 FabiaTech Corporation
-0004A8 Broadmax Technologies, Inc.
-0004A9 SandStream Technologies, Inc.
-0004AA Jetstream Communications
-0004AB Comverse Network Systems, Inc.
-0004AC IBM CORP.
-0004AD Malibu Networks
-0004AE Liquid Metronics
-0004AF Digital Fountain, Inc.
-0004B0 ELESIGN Co., Ltd.
-0004B1 Signal Technology, Inc.
-0004B2 ESSEGI SRL
-0004B3 Videotek, Inc.
-0004B4 CIAC
-0004B5 Equitrac Corporation
-0004B6 Stratex Networks, Inc.
-0004B7 AMB i.t. Holding
-0004B8 Kumahira Co., Ltd.
-0004B9 S.I. Soubou, Inc.
-0004BA KDD Media Will Corporation
-0004BB Bardac Corporation
-0004BC Giantec, Inc.
-0004BD Motorola BCS
-0004BE OptXCon, Inc.
-0004BF VersaLogic Corp.
-0004C0 Cisco Systems, Inc.
-0004C1 Cisco Systems, Inc.
-0004C2 Magnipix, Inc.
-0004C3 CASTOR Informatique
-0004C4 Allen & Heath Limited
-0004C5 ASE Technologies, USA
-0004C6 Yamaha Motor Co., Ltd.
-0004C7 NetMount
-0004C8 LIBA Maschinenfabrik GmbH
-0004C9 Micro Electron Co., Ltd.
-0004CA FreeMs Corp.
-0004CB Tdsoft Communication, Ltd.
-0004CC Peek Traffic B.V.
-0004CD Informedia Research Group
-0004CE Patria Ailon
-0004CF Seagate Technology
-0004D0 Softlink s.r.o.
-0004D1 Drew Technologies, Inc.
-0004D2 Adcon Telemetry AG
-0004D3 Toyokeiki Co., Ltd.
-0004D4 Proview Electronics Co., Ltd.
-0004D5 Hitachi Communication Systems, Inc.
-0004D6 Takagi Industrial Co., Ltd.
-0004D7 Omitec Instrumentation Ltd.
-0004D8 IPWireless, Inc.
-0004D9 Titan Electronics, Inc.
-0004DA Relax Technology, Inc.
-0004DB Tellus Group Corp.
-0004DC Nortel Networks
-0004DD Cisco Systems, Inc.
-0004DE Cisco Systems, Inc.
-0004DF Teracom Telematica Ltda.
-0004E0 Procket Networks
-0004E1 Infinior Microsystems
-0004E2 SMC Networks, Inc.
-0004E3 Accton Technology Corp.
-0004E4 Daeryung Ind., Inc.
-0004E5 Glonet Systems, Inc.
-0004E6 Banyan Network Private Limited
-0004E7 Lightpointe Communications, Inc
-0004E8 IER, Inc.
-0004E9 Infiniswitch Corporation
-0004EA Hewlett-Packard Company
-0004EB Paxonet Communications, Inc.
-0004EC Memobox SA
-0004ED Billion Electric Co., Ltd.
-0004EE Lincoln Electric Company
-0004EF Polestar Corp.
-0004F0 International Computers, Ltd
-0004F1 WhereNet
-0004F2 Circa Communications, Ltd.
-0004F3 FS FORTH-SYSTEME GmbH
-0004F4 Infinite Electronics Inc.
-0004F5 SnowShore Networks, Inc.
-0004F6 Amphus
-0004F7 Omega Band, Inc.
-0004F8 QUALICABLE TV Industria E Com., Ltda
-0004F9 Xtera Communications, Inc.
-0004FA MIST Inc.
-0004FB Commtech, Inc.
-0004FC Stratus Computer (DE), Inc.
-0004FD Japan Control Engineering Co., Ltd.
-0004FE Pelago Networks
-0004FF Acronet Co., Ltd.
-000500 Cisco Systems, Inc.
-000501 Cisco Systems, Inc.
-000502 APPLE COMPUTER
-000503 ICONAG
-000504 Naray Information & Communication Enterprise
-000505 Systems Integration Solutions, Inc.
-000506 Reddo Networks AB
-000507 Fine Appliance Corp.
-000508 Inetcam, Inc.
-000509 AVOC Nishimura Ltd.
-00050A ICS Spa
-00050B SICOM Systems, Inc.
-00050C Network Photonics, Inc.
-00050D Midstream Technologies, Inc.
-00050E 3ware, Inc.
-00050F Tanaka S/S Ltd.
-000510 Infinite Shanghai Communication Terminals Ltd.
-000511 Complementary Technologies Ltd
-000512 MeshNetworks, Inc.
-000513 VTLinx Multimedia Systems, Inc.
-000514 KDT Systems Co., Ltd.
-000515 Nuark Co., Ltd.
-000516 SMART Modular Technologies
-000517 Shellcomm, Inc.
-000518 Jupiters Technology
-000519 Siemens Building Technologies AG,
-00051A 3Com Europe Ltd.
-00051B Magic Control Technology Corporation
-00051C Xnet Technology Corp.
-00051D Airocon, Inc.
-00051E Brocade Communications Systems, Inc.
-00051F Taijin Media Co., Ltd.
-000520 Smartronix, Inc.
-000521 Control Microsystems
-000522 LEA*D Corporation, Inc.
-000523 AVL List GmbH
-000524 BTL System (HK) Limited
-000525 Puretek Industrial Co., Ltd.
-000526 IPAS GmbH
-000527 SJ Tek Co. Ltd
-000528 New Focus, Inc.
-000529 Shanghai Broadan Communication Technology Co., Ltd
-00052A Ikegami Tsushinki Co., Ltd.
-00052B HORIBA, Ltd.
-00052C Supreme Magic Corporation
-00052D Zoltrix International Limited
-00052E Cinta Networks
-00052F Leviton Voice and Data
-000530 Andiamo Systems, Inc.
-000531 Cisco Systems, Inc.
-000532 Cisco Systems, Inc.
-000533 Sanera Systems, Inc.
-000534 Northstar Engineering Ltd.
-000535 Chip PC Ltd.
-000536 Danam Communications, Inc.
-000537 Nets Technology Co., Ltd.
-000538 Merilus, Inc.
-000539 A Brand New World in Sweden AB
-00053A Willowglen Services Pte Ltd
-00053B Harbour Networks Ltd., Co. Beijing
-00053C Xircom
-00053D Agere Systems
-00053E KID Systeme GmbH
-00053F VisionTek, Inc.
-000540 FAST Corporation
-000541 Advanced Systems Co., Ltd.
-000542 Otari, Inc.
-000543 IQ Wireless GmbH
-000544 Valley Technologies, Inc.
-000545 Internet Photonics
-000546 K-Solutions Inc.
-000547 Starent Networks
-000548 Disco Corporation
-000549 Salira Optical Network Systems
-00054A Ario Data Networks, Inc.
-00054B Micro Innovation AG
-00054C RF Innovations Pty Ltd
-00054D Brans Technologies, Inc.
-00054E Philips Components
-000550 Digi-Tech Communications Limited
-000551 F & S Elektronik Systeme GmbH
-000552 Xycotec Computer GmbH
-000553 DVC Company, Inc.
-000554 Rangestar Wireless
-000555 Japan Cash Machine Co., Ltd.
-000556 360 Systems
-000557 Agile TV Corporation
-000558 Synchronous, Inc.
-000559 Intracom S.A.
-00055A Power Dsine Ltd.
-00055B Charles Industries, Ltd.
-00055C Kowa Company, Ltd.
-00055D D-Link Systems, Inc.
-00055E Cisco Systems, Inc.
-00055F Cisco Systems, Inc.
-000560 LEADER COMM.CO., LTD
-000561 nac Image Technology, Inc.
-000562 Digital View Limited
-000563 J-Works, Inc.
-000564 Tsinghua Bitway Co., Ltd.
-000565 Tailyn Communication Company Ltd.
-000566 Secui.com Corporation
-000567 Etymonic Design, Inc.
-000568 Piltofish Networks AB
-000569 VMWARE, Inc.
-00056A Heuft Systemtechnik GmbH
-00056B C.P. Technology Co., Ltd.
-00056C Hung Chang Co., Ltd.
-00056D Pacific Corporation
-00056E National Enhance Technology, Inc.
-00056F Innomedia Technologies Pvt. Ltd.
-000570 Baydel Ltd.
-000571 Seiwa Electronics Co.
-000572 Deonet Co., Ltd.
-000573 Cisco Systems, Inc.
-000574 Cisco Systems, Inc.
-000575 CDS-Electronics BV
-000576 NSM Technology Ltd.
-000577 SM Information & Communication
-000579 Universal Control Solution Corp.
-00057A Hatteras Networks
-00057B Chung Nam Electronic Co., Ltd.
-00057C RCO Security AB
-00057D Sun Communications, Inc.
-00057E Eckelmann Steuerungstechnik GmbH
-00057F Acqis Technology
-000580 Fibrolan Ltd.
-000581 Snell & Wilcox Ltd.
-000582 ClearCube Technology
-000583 ImageCom Limited
-000584 AbsoluteValue Systems, Inc.
-000585 Juniper Networks, Inc.
-000586 Lucent Technologies
-000587 Locus, Incorporated
-000588 Sensoria Corp.
-000589 National Datacomputer
-00058A Netcom Co., Ltd.
-00058B IPmental, Inc.
-00058C Opentech Inc.
-00058D Lynx Photonic Networks, Inc.
-00058E Flextronics International GmbH & Co. Nfg. KG
-00058F CLCsoft co.
-000590 Swissvoice Ltd.
-000591 Active Silicon Ltd.
-000592 Pultek Corp.
-000593 Grammar Engine Inc.
-000594 IXXAT Automation GmbH
-000595 Alesis Corporation
-000596 Genotech Co., Ltd.
-000597 Eagle Traffic Control Systems
-000598 CRONOS S.r.l.
-000599 DRS Test and Energy Management or DRS-TEM
-00059A Cisco Systems, Inc.
-00059B Cisco Systems, Inc.
-00059C Kleinknecht GmbH, Ing. Buero
-00059D Daniel Computing Systems, Inc.
-00059E Zinwell Corporation
-00059F Yotta Networks, Inc.
-0005A0 MOBILINE Kft.
-0005A1 Zenocom
-0005A2 CELOX Networks
-0005A3 QEI, Inc.
-0005A4 Lucid Voice Ltd.
-0005A5 KOTT
-0005A6 Extron Electronics
-0005A7 Hyperchip, Inc.
-0005A8 WYLE ELECTRONICS
-0005A9 Princeton Networks, Inc.
-0005AA Moore Industries International Inc.
-0005AB Cyber Fone, Inc.
-0005AC Northern Digital, Inc.
-0005AD Topspin Communications, Inc.
-0005AE Mediaport USA
-0005AF InnoScan Computing A/S
-0005B0 Korea Computer Technology Co., Ltd.
-0005B1 ASB Technology BV
-0005B2 Medison Co., Ltd.
-0005B3 Asahi-Engineering Co., Ltd.
-0005B4 Aceex Corporation
-0005B5 Broadcom Technologies
-0005B6 INSYS Microelectronics GmbH
-0005B7 Arbor Technology Corp.
-0005B8 Electronic Design Associates, Inc.
-0005B9 Airvana, Inc.
-0005BA Area Netwoeks, Inc.
-0005BB Myspace AB
-0005BC Resorsys Ltd.
-0005BD ROAX BV
-0005BE Kongsberg Seatex AS
-0005BF JustEzy Technology, Inc.
-0005C0 Digital Network Alacarte Co., Ltd.
-0005C1 A-Kyung Motion, Inc.
-0005C2 Soronti, Inc.
-0005C3 Pacific Instruments, Inc.
-0005C4 Telect, Inc.
-0005C5 Flaga HF
-0005C6 Triz Communications
-0005C7 I/F-COM A/S
-0005C8 VERYTECH
-0005C9 LG Innotek
-0005CA Hitron Technology, Inc.
-0005CB ROIS Technologies, Inc.
-0005CC Sumtel Communications, Inc.
-0005CD Denon, Ltd.
-0005CE Prolink Microsystems Corporation
-0005CF Thunder River Technologies, Inc.
-0005D0 Solinet Systems
-0005D1 Metavector Technologies
-0005D2 DAP Technologies
-0005D3 eProduction Solutions, Inc.
-0005D4 FutureSmart Networks, Inc.
-0005D5 Speedcom Wireless
-0005D6 Titan Wireless
-0005D7 Vista Imaging, Inc.
-0005D8 Arescom, Inc.
-0005D9 Techno Valley, Inc.
-0005DA Apex Automationstechnik
-0005DB Nentec GmbH
-0005DC Cisco Systems, Inc.
-0005DD Cisco Systems, Inc.
-0005DE Gi Fone Korea, Inc.
-0005DF Electronic Innovation, Inc.
-0005E0 Empirix Corp.
-0005E1 Trellis Photonics, Ltd.
-0005E2 Creativ Network Technologies
-0005E3 LightSand Communications, Inc.
-0005E4 Red Lion Controls L.P.
-0005E5 Renishaw PLC
-0005E6 Egenera, Inc.
-0005E7 Netrake Corp.
-0005E8 TurboWave, Inc.
-0005E9 Unicess Network, Inc.
-0005EA Rednix
-0005EB Blue Ridge Networks, Inc.
-0005EC Mosaic Systems Inc.
-0005ED Technikum Joanneum GmbH
-0005EE BEWATOR Group
-0005EF ADOIR Digital Technology
-0005F0 SATEC
-0005F1 Vrcom, Inc.
-0005F2 Power R, Inc.
-0005F3 Weboyn
-0005F4 System Base Co., Ltd.
-0005F5 OYO Geospace Corp.
-0005F6 Young Chang Co. Ltd.
-0005F7 Analog Devices, Inc.
-0005F8 Real Time Access, Inc.
-0005F9 TOA Corporation
-0005FA IPOptical, Inc.
-0005FB ShareGate, Inc.
-0005FC Schenck Pegasus Corp.
-0005FD PacketLight Networks Ltd.
-0005FE Traficon N.V.
-0005FF SNS Solutions, Inc.
-000600 Tokyo Electronic Industry Co., Ltd.
-000601 Otanikeiki Co., Ltd.
-000602 Cirkitech Electronics Co.
-000603 Baker Hughes Inc.
-000604 @Track Communications, Inc.
-000605 Inncom International, Inc.
-000606 RapidWAN, Inc.
-000607 Omni Directional Control Technology Inc.
-000608 At-Sky SAS
-000609 Crossport Systems
-00060A Blue2space
-00060B Paceline Systems Corporation
-00060C Melco Industries, Inc.
-00060D Wave7 Optics
-00060E IGYS Systems, Inc.
-00060F Narad Networks Inc
-000610 Abeona Networks Inc
-000611 Zeus Wireless, Inc.
-000612 Accusys, Inc.
-000613 Kawasaki Microelectronics Incorporated
-000614 Prism Holdings
-000615 Kimoto Electric Co., Ltd.
-000616 Tel Net Co., Ltd.
-000617 Redswitch Inc.
-000618 DigiPower Manufacturing Inc.
-000619 Connection Technology Systems
-00061A Zetari Inc.
-00061B Portable Systems, IBM Japan Co, Ltd
-00061C Hoshino Metal Industries, Ltd.
-00061D MIP Telecom, Inc.
-00061E Maxan Systems
-00061F Vision Components GmbH
-000620 Serial System Ltd.
-000621 Hinox, Co., Ltd.
-000622 Chung Fu Chen Yeh Enterprise Corp.
-000623 MGE UPS Systems France
-000624 Gentner Communications Corp.
-000625 The Linksys Group, Inc.
-000626 MWE GmbH
-000627 Uniwide Technologies, Inc.
-000628 Cisco Systems, Inc.
-000629 IBM CORPORATION
-00062A Cisco Systems, Inc.
-00062B INTRASERVER TECHNOLOGY
-00062C Network Robots, Inc.
-00062D TouchStar Technologies, L.L.C.
-00062E Aristos Logic Corp.
-00062F Pivotech Systems Inc.
-000630 Adtranz Sweden
-000631 Optical Solutions, Inc.
-000632 Mesco Engineering GmbH
-000633 Heimann Biometric Systems GmbH
-000634 GTE Airfone Inc.
-000635 PacketAir Networks, Inc.
-000636 Jedai Broadband Networks
-000637 Toptrend-Meta Information (ShenZhen) Inc.
-000638 Sungjin C&C Co., Ltd.
-000639 Newtec
-00063A Dura Micro, Inc.
-00063B Arcturus Networks, Inc.
-00063C NMI Electronics Ltd
-00063D Microwave Data Systems Inc.
-00063E Opthos Inc.
-00063F Everex Communications Inc.
-000640 White Rock Networks
-000641 ITCN
-000642 Genetel Systems Inc.
-000643 SONO Computer Co., Ltd.
-000644 NEIX Inc.
-000645 Meisei Electric Co. Ltd.
-000646 ShenZhen XunBao Network Technology Co Ltd
-000647 Etrali S.A.
-000648 Seedsware, Inc.
-000649 Quante
-00064A Honeywell Co., Ltd. (KOREA)
-00064B Alexon Co., Ltd.
-00064C Invicta Networks, Inc.
-00064D Sencore
-00064E Broad Net Technology Inc.
-00064F PRO-NETS Technology Corporation
-000650 Tiburon Networks, Inc.
-000651 Aspen Networks Inc.
-000652 Cisco Systems, Inc.
-000653 Cisco Systems, Inc.
-000654 Maxxio Technologies
-000655 Yipee, Inc.
-000656 Tactel AB
-000657 Market Central, Inc.
-000658 Helmut Fischer GmbH & Co. KG
-000659 EAL (Apeldoorn) B.V.
-00065A Strix Systems
-00065B Dell Computer Corp.
-00065C Malachite Technologies, Inc.
-00065D Heidelberg Web Systems
-00065E Photuris, Inc.
-00065F ECI Telecom - NGTS Ltd.
-000660 NADEX Co., Ltd.
-000661 NIA Home Technologies Corp.
-000662 MBM Technology Ltd.
-000663 Human Technology Co., Ltd.
-000664 Fostex Corporation
-000665 Sunny Giken, Inc.
-000666 Roving Networks
-000667 Tripp Lite
-000668 Vicon Industries Inc.
-000669 Datasound Laboratories Ltd
-00066A InfiniCon Systems, Inc.
-00066B Sysmex Corporation
-00066C Robinson Corporation
-00066D Compuprint S.P.A.
-00066E Delta Electronics, Inc.
-00066F Korea Data Systems
-000670 Upponetti Oy
-000671 Softing AG
-000672 Netezza
-000673 Optelecom, Inc.
-000674 Spectrum Control, Inc.
-000675 Banderacom, Inc.
-000676 Novra Technologies Inc.
-000677 SICK AG
-000678 Marantz Japan, Inc.
-000679 Konami Corporation
-00067A JMP Systems
-00067B Toplink C&C Corporation
-00067C CISCO SYSTEMS, INC.
-00067D Takasago Ltd.
-00067E WinCom Systems, Inc.
-00067F Rearden Steel Technologies
-000680 Card Access, Inc.
-000681 Goepel Electronic GmbH
-000682 Convedia
-000683 Bravara Communications, Inc.
-000684 Biacore AB
-000685 NetNearU Corporation
-000686 ZARDCOM Co., Ltd.
-000687 Omnitron Systems Technology, Inc.
-000688 Telways Communication Co., Ltd.
-000689 yLez Technologies Pte Ltd
-00068A NeuronNet Co. Ltd. R&D Center
-00068B AirRunner Technologies, Inc.
-00068C 3Com Corporation
-00068D SANgate Systems
-00068E HID Corporation
-00068F Telemonitor, Inc.
-000690 Euracom Communication GmbH
-000691 PT Inovacao
-000692 Intruvert Networks, Inc.
-000693 Flexus Computer Technology, Inc.
-000694 Mobillian Corporation
-000695 Ensure Technologies, Inc.
-000696 Advent Networks
-000697 R & D Center
-000698 egnite Software GmbH
-000699 Vida Design Co.
-00069A e & Tel
-00069B AVT Audio Video Technologies GmbH
-00069C Transmode Systems AB
-00069D Petards Mobile Intelligence
-00069E UNIQA, Inc.
-00069F Kuokoa Networks
-0006A0 Mx Imaging
-0006A1 Celsian Technologies, Inc.
-0006A2 Microtune, Inc.
-0006A3 Bitran Corporation
-0006A4 INNOWELL Corp.
-0006A5 PINON Corp.
-0006A6 Artistic Licence (UK) Ltd
-0006A7 Primarion
-0006A8 KC Technology, Inc.
-0006A9 Universal Instruments Corp.
-0006AA Miltope Corporation
-0006AB W-Link Systems, Inc.
-0006AC Intersoft Co.
-0006AD KB Electronics Ltd.
-0006AE Himachal Futuristic Communications Ltd
-0006B0 Comtech EF Data Corp.
-0006B1 Sonicwall
-0006B2 Linxtek Co.
-0006B3 Diagraph Corporation
-0006B4 Vorne Industries, Inc.
-0006B5 Luminent, Inc.
-0006B6 Nir-Or Israel Ltd.
-0006B7 TELEM GmbH
-0006B8 Bandspeed Pty Ltd
-0006B9 A5TEK Corp.
-0006BA Westwave Communications
-0006BB ATI Technologies Inc.
-0006BC Macrolink, Inc.
-0006BD BNTECHNOLOGY Co., Ltd.
-0006BE Baumer Optronic GmbH
-0006BF Accella Technologies Co., Ltd.
-0006C0 United Internetworks, Inc.
-0006C1 CISCO SYSTEMS, INC.
-0006C2 Smartmatic Corporation
-0006C3 Schindler Elevators Ltd.
-0006C4 Piolink Inc.
-0006C5 INNOVI Technologies Limited
-0006C6 lesswire AG
-0006C7 RFNET Technologies Pte Ltd (S)
-0006C8 Sumitomo Metal Micro Devices, Inc.
-0006C9 Technical Marketing Research, Inc.
-0006CA American Computer & Digital Components, Inc. (ACDC)
-0006CB Jotron Electronics A/S
-0006CC JMI Electronics Co., Ltd.
-0006CD CreoScitex Corporation Ltd.
-0006CE DATENO
-0006CF Thales Avionics In-Flight Systems, LLC
-0006D0 Elgar Electronics Corp.
-0006D1 Tahoe Networks, Inc.
-0006D2 Tundra Semiconductor Corp.
-0006D3 Alpha Telecom, Inc. U.S.A.
-0006D4 Interactive Objects, Inc.
-0006D5 Diamond Systems Corp.
-0006D6 Cisco Systems, Inc.
-0006D7 Cisco Systems, Inc.
-0006D8 Maple Optical Systems
-0006D9 IPM-Net S.p.A.
-0006DA ITRAN Communications Ltd.
-0006DB ICHIPS Co., Ltd.
-0006DC Syabas Technology (Amquest)
-0006DD AT & T Laboratories - Cambridge Ltd
-0006DE Flash Technology
-0006DF AIDONIC Corporation
-0006E0 MAT Co., Ltd.
-0006E1 Techno Trade s.a
-0006E2 Ceemax Technology Co., Ltd.
-0006E3 Quantitative Imaging Corporation
-0006E4 Citel Technologies Ltd.
-0006E5 Fujian Newland Computer Ltd. Co.
-0006E6 DongYang Telecom Co., Ltd.
-0006E7 Bit Blitz Communications Inc.
-0006E8 Optical Network Testing, Inc.
-0006E9 Intime Corp.
-0006EA ELZET80 Mikrocomputer GmbH&Co. KG
-0006EB Global Data
-0006EC M/A COM Private Radio System Inc.
-0006ED Inara Networks
-0006EE Shenyang Neu-era Information & Technology Stock Co., Ltd
-0006EF Maxxan Systems, Inc.
-0006F0 Digeo, Inc.
-0006F1 Optillion
-0006F2 Platys Communications
-0006F3 AcceLight Networks
-0006F4 Prime Electronics & Satellitics Inc.
-0006F9 Mitsui Zosen Systems Research Inc.
-0006FA IP SQUARE Co, Ltd.
-0006FB Hitachi Printing Solutions, Ltd.
-0006FC Fnet Co., Ltd.
-0006FD Comjet Information Systems Corp.
-0006FE Celion Networks, Inc.
-0006FF Sheba Systems Co., Ltd.
-000700 Zettamedia Korea
-000701 RACAL-DATACOM
-000702 Varian Medical Systems
-000703 CSEE Transport
-000705 Endress & Hauser GmbH & Co
-000706 Sanritz Corporation
-000707 Interalia Inc.
-000708 Bitrage Inc.
-000709 Westerstrand Urfabrik AB
-00070A Unicom Automation Co., Ltd.
-00070B Octal, SA
-00070C SVA-Intrusion.com Co. Ltd.
-00070D Cisco Systems Inc.
-00070E Cisco Systems Inc.
-00070F Fujant, Inc.
-000710 Adax, Inc.
-000711 Acterna
-000712 JAL Information Technology
-000713 IP One, Inc.
-000714 Brightcom
-000715 General Research of Electronics, Inc.
-000716 J & S Marine Ltd.
-000717 Wieland Electric GmbH
-000718 iCanTek Co., Ltd.
-000719 Mobiis Co., Ltd.
-00071A Finedigital Inc.
-00071B Position Technology Inc.
-00071C AT&T Fixed Wireless Services
-00071D Satelsa Sistemas Y Aplicaciones De Telecomunicaciones, S.A.
-00071E Tri-M Engineering / Nupak Dev. Corp.
-00071F European Systems Integration
-000720 Trutzschler GmbH & Co. KG
-000721 Formac Elektronik GmbH
-000722 Nielsen Media Research
-000723 ELCON Systemtechnik GmbH
-000724 Telemax Co., Ltd.
-000725 Bematech International Corp.
-000727 Zi Corporation (HK) Ltd.
-000728 Neo Telecom
-000729 Kistler Instrumente AG
-00072A Innovance Networks
-00072B Jung Myung Telecom Co., Ltd.
-00072C Fabricom
-00072D CNSystems
-00072E North Node AB
-00072F Instransa, Inc.
-000730 Hutchison OPTEL Telecom Technology Co., Ltd.
-000731 Spiricon, Inc.
-000732 AAEON Technology Inc.
-000733 DANCONTROL Engineering
-000734 ONStor, Inc.
-000735 Flarion Technologies, Inc.
-000736 Data Video Technologies Co., Ltd.
-000737 Soriya Co. Ltd.
-000738 Young Technology Co., Ltd.
-000739 Motion Media Technology Ltd.
-00073A Inventel Systemes
-00073B Tenovis GmbH & Co KG
-00073C Telecom Design
-00073D Nanjing Postel Telecommunications Co., Ltd.
-00073E China Great-Wall Computer Shenzhen Co., Ltd.
-00073F Woojyun Systec Co., Ltd.
-000740 Melco Inc.
-000741 Sierra Automated Systems
-000742 Current Technologies
-000743 Chelsio Communications
-000744 Unico, Inc.
-000745 Radlan Computer Communications Ltd.
-000746 Interlink BT, LLC
-000747 Mecalc
-000748 The Imaging Source Europe
-000749 CENiX Inc.
-00074A Carl Valentin GmbH
-00074B Daihen Corporation
-00074C Beicom Inc.
-00074D Zebra Technologies Corp.
-00074E Naughty boy co., Ltd.
-00074F Cisco Systems, Inc.
-000750 Cisco Systems, Inc.
-000751 m.u.t. - GmbH
-000752 Rhythm Watch Co., Ltd.
-000753 Beijing Qxcomm Technology Co., Ltd.
-000754 Xyterra Computing, Inc.
-000755 Lafon SA
-000756 Juyoung Telecom
-000757 Topcall International AG
-000758 Dragonwave
-000759 Boris Manufacturing Corp.
-00075A Air Products and Chemicals, Inc.
-00075B Gibson Guitars
-00075C ENCAD, Inc.
-00075D Celleritas Inc.
-00075E Pulsar Technologies, Inc.
-00075F VCS Video Communication Systems AG
-000760 TOMIS Information & Telecom Corp.
-000761 Logitech SA
-000762 Group Sense Limited
-000763 Sunniwell Cyber Tech. Co., Ltd.
-000764 YoungWoo Telecom Co. Ltd.
-000765 Jade Quantum Technologies, Inc.
-000766 Chou Chin Industrial Co., Ltd.
-000767 Yuxing Electronics Company Limited
-000768 Danfoss A/S
-000769 Italiana Macchi SpA
-00076A NEXTEYE Co., Ltd.
-00076B Stralfors AB
-00076C Daehanet, Inc.
-00076D Flexlight Networks
-00076E Sinetica Corporation Ltd.
-00076F Synoptics Limited
-000770 Locusnetworks Corporation
-000771 Embedded System Corporation
-000772 Alcatel Shanghai Bell Co., Ltd.
-000773 Ascom Powerline Communications Ltd.
-000774 GuangZhou Thinker Technology Co. Ltd.
-000775 Valence Semiconductor, Inc.
-000776 Federal APD
-000777 Motah Ltd.
-000778 GERSTEL GmbH & Co. KG
-000779 Sungil Telecom Co., Ltd.
-00077A Infoware System Co., Ltd.
-00077B Millimetrix Broadband Networks
-00077C OnTime Networks
-00077E Elrest GmbH
-00077F J Communications Co., Ltd.
-000780 Bluegiga Technologies OY
-000781 Itron Inc.
-000782 Nauticus Networks, Inc.
-000783 SynCom Network, Inc.
-000784 Cisco Systems Inc.
-000785 Cisco Systems Inc.
-000786 Wireless Networks Inc.
-000787 Idea System Co., Ltd.
-000788 Clipcomm, Inc.
-000789 Eastel Systems Corporation
-00078A Mentor Data System Inc.
-00078B Wegener Communications, Inc.
-00078C Elektronikspecialisten i Borlange AB
-00078D NetEngines Ltd.
-00078E Garz & Friche GmbH
-00078F Emkay Innovative Products
-000790 Tri-M Technologies (s) Limited
-000791 International Data Communications, Inc.
-000792 Suetron Electronic GmbH
-000794 Simple Devices, Inc.
-000795 Elitegroup Computer System Co. (ECS)
-000796 LSI Systems, Inc.
-000797 Netpower Co., Ltd.
-000798 Selea SRL
-000799 Tipping Point Technologies, Inc.
-00079A SmartSight Networks Inc.
-00079B Aurora Networks
-00079C Golden Electronics Technology Co., Ltd.
-00079D Musashi Co., Ltd.
-00079E Ilinx Co., Ltd.
-00079F Action Digital Inc.
-0007A0 e-Watch Inc.
-0007A1 VIASYS Healthcare GmbH
-0007A2 Opteon Corporation
-0007A3 Ositis Software, Inc.
-0007A4 GN Netcom Ltd.
-0007A5 Y.D.K Co. Ltd.
-0007A6 Home Automation, Inc.
-0007A7 A-Z Inc.
-0007A8 Haier Group Technologies Ltd.
-0007A9 Novasonics
-0007AA Quantum Data Inc.
-0007AC Eolring
-0007AD Pentacon GmbH Foto-und Feinwerktechnik
-0007AE Layer N Networks
-0007AF N-Tron Corp.
-0007B0 Office Details, Inc.
-0007B1 Equator Technologies
-0007B2 Transaccess S.A.
-0007B3 Cisco Systems Inc.
-0007B4 Cisco Systems Inc.
-0007B5 Any One Wireless Ltd.
-0007B6 Telecom Technology Ltd.
-0007B7 Samurai Ind. Prods Eletronicos Ltda
-0007B8 American Predator Corp.
-0007B9 Ginganet Corporation
-0007BA Xebeo Communications, Inc.
-0007BB Candera Inc.
-0007BC Identix Inc.
-0007BD Radionet Ltd.
-0007BE DataLogic SpA
-0007BF Armillaire Technologies, Inc.
-0007C0 NetZerver Inc.
-0007C1 Overture Networks, Inc.
-0007C2 Netsys Telecom
-0007C3 Cirpack
-0007C4 JEAN Co. Ltd.
-0007C5 Gcom, Inc.
-0007C6 VDS Vosskuhler GmbH
-0007C7 Synectics Systems Limited
-0007C8 Brain21, Inc.
-0007C9 Technol Seven Co., Ltd.
-0007CA Creatix Polymedia Ges Fur Kommunikaitonssysteme
-0007CB Freebox SA
-0007CC Kaba Benzing GmbH
-0007CD NMTEL Co., Ltd.
-0007CE Cabletime Limited
-0007CF Anoto AB
-0007D0 Automat Engenharia de Automaoa Ltda.
-0007D1 Spectrum Signal Processing Inc.
-0007D2 Logopak Systeme
-0007D3 Stork Digital Imaging B.V.
-0007D4 Zhejiang Yutong Network Communication Co Ltd.
-0007D5 3e Technologies Int;., Inc.
-0007D6 Commil Ltd.
-0007D7 Caporis Networks AG
-0007D8 Hitron Systems Inc.
-0007D9 Splicecom
-0007DA Neuro Telecom Co., Ltd.
-0007DB Kirana Networks, Inc.
-0007DC Atek Co, Ltd.
-0007DD Cradle Technologies
-0007DE eCopilt AB
-0007DF Vbrick Systems Inc.
-0007E0 Palm Inc.
-0007E1 WIS Communications Co. Ltd.
-0007E2 Bitworks, Inc.
-0007E3 Navcom Technology, Inc.
-0007E4 SoftRadio Co., Ltd.
-0007E5 Coup Corporation
-0007E6 edgeflow Canada Inc.
-0007E7 FreeWave Technologies
-0007E8 St. Bernard Software
-0007E9 Intel Corporation
-0007EA Massana, Inc.
-0007EB Cisco Systems Inc.
-0007EC Cisco Systems Inc.
-0007ED Altera Corporation
-0007EE telco Informationssysteme GmbH
-0007EF Lockheed Martin Tactical Systems
-0007F0 LogiSync Corporation
-0007F1 TeraBurst Networks Inc.
-0007F2 IOA Corporation
-0007F3 Think Engine Networks
-0007F4 Eletex Co., Ltd.
-0007F5 Bridgeco Co AG
-0007F6 Qqest Software Systems
-0007F7 Galtronics
-0007F8 ITDevices, Inc.
-0007F9 Phonetics, Inc.
-0007FA ITT Co., Ltd.
-0007FB Giga Stream UMTS Technologies GmbH
-0007FC Adept Systems Inc.
-0007FD LANergy Ltd.
-0007FE Rigaku Corporation
-0007FF Gluon Networks
-000800 MULTITECH SYSTEMS, INC.
-000801 HighSpeed Surfing Inc.
-000802 Compaq Computer Corporation
-000803 Cos Tron
-000804 ICA Inc.
-000805 Techno-Holon Corporation
-000806 Raonet Systems, Inc.
-000807 Access Devices Limited
-000808 PPT Vision, Inc.
-000809 Systemonic AG
-00080A Espera-Werke GmbH
-00080B Birka BPA Informationssystem AB
-00080C VDA elettronica SrL
-00080D Toshiba
-00080E Motorola, BCS
-00080F Proximion Fiber Optics AB
-000810 Key Technology, Inc.
-000811 VOIX Corporation
-000812 GM-2 Corporation
-000813 Diskbank, Inc.
-000814 TIL Technologies
-000815 CATS Co., Ltd.
-000816 Bluetags A/S
-000817 EmergeCore Networks LLC
-000818 Pixelworks, Inc.
-000819 Banksys
-00081A Sanrad Intelligence Storage Communications (2000) Ltd.
-00081B Windigo Systems
-00081C @pos.com
-00081D Ipsil, Incorporated
-00081E Repeatit AB
-00081F Pou Yuen Tech Corp. Ltd.
-000820 Cisco Systems Inc.
-000821 Cisco Systems Inc.
-000822 InPro Comm
-000823 Texa Corp.
-000824 Promatek Industries Ltd.
-000825 Acme Packet
-000826 Colorado Med Tech
-000827 Pirelli Cables & Systems
-000828 Koei Engineering Ltd.
-000829 Aval Nagasaki Corporation
-00082A Powerwallz Network Security
-00082B Wooksung Electronics, Inc.
-00082C Homag AG
-00082D Indus Teqsite Private Limited
-00082E Multitone Electronics PLC
-00084E DivergeNet, Inc.
-00084F Qualstar Corporation
-000850 Arizona Instrument Corp.
-000851 Canadian Bank Note Company, Ltd.
-000852 Davolink Co. Inc.
-000853 Schleicher GmbH & Co. Relaiswerke KG
-000854 Netronix, Inc.
-000855 NASA-Goddard Space Flight Center
-000856 Gamatronic Electronic Industries Ltd.
-000857 Polaris Networks, Inc.
-000858 Novatechnology Inc.
-000859 ShenZhen Unitone Electronics Co., Ltd.
-00085A IntiGate Inc.
-00085B Hanbit Electronics Co., Ltd.
-00085C Shanghai Dare Technologies Co. Ltd.
-00085D Aastra
-00085E PCO AG
-00085F Picanol N.V.
-000860 LodgeNet Entertainment Corp.
-000861 SoftEnergy Co., Ltd.
-000862 NEC Eluminant Technologies, Inc.
-000863 Entrisphere Inc.
-000864 Fasy S.p.A.
-000865 JASCOM CO., LTD
-000866 DSX Access Systems, Inc.
-000867 Uptime Devices
-000868 PurOptix
-000869 Command-e Technology Co.,Ltd.
-00086A Industrie Technik IPS GmbH
-00086B MIPSYS
-00086C Plasmon LMS
-00086D Missouri FreeNet
-00086E Hyglo AB
-00086F Resources Computer Network Ltd.
-000870 Rasvia Systems, Inc.
-000871 NORTHDATA Co., Ltd.
-000872 Sorenson Technologies, Inc.
-000873 DAP Design B.V.
-000874 Dell Computer Corp.
-000875 Acorp Electronics Corp.
-000876 SDSystem
-000877 Liebert HIROSS S.p.A.
-000878 Benchmark Storage Innovations
-000879 CEM Corporation
-00087A Wipotec GmbH
-00087B RTX Telecom A/S
-00087C Cisco Systems, Inc.
-00087D Cisco Systems Inc.
-00087E Bon Electro-Telecom Inc.
-00087F SPAUN electronic GmbH & Co. KG
-000880 BroadTel Canada Communications inc.
-000881 DIGITAL HANDS CO.,LTD.
-000882 SIGMA CORPORATION
-000883 Hewlett-Packard Company
-000884 Index Braille AB
-000885 EMS Dr. Thomas Wuensche
-000886 Hansung Teliann, Inc.
-000887 Maschinenfabrik Reinhausen GmbH
-000888 OULLIM Information Technology Inc,.
-000889 Echostar Technologies Corp
-00088A Minds@Work
-00088B Tropic Networks Inc.
-00088C Quanta Network Systems Inc.
-00088D Sigma-Links Inc.
-00088E Nihon Computer Co., Ltd.
-00088F ADVANCED DIGITAL TECHNOLOGY
-000890 AVILINKS SA
-000891 Lyan Inc.
-000892 EM Solutions
-000894 InnoVISION Multimedia Ltd.
-000895 DIRC Technologie GmbH & Co.KG
-000896 Printronix, Inc.
-000897 Quake Technologies
-000898 Gigabit Optics Corporation
-000899 Netbind, Inc.
-00089A Alcatel Microelectronics
-00089B ICP Electronics Inc.
-00089C Elecs Industry Co., Ltd.
-00089D UHD-Elektronik
-00089E Beijing Enter-Net co.LTD
-00089F EFM Networks
-0008A0 Stotz Feinmesstechnik GmbH
-0008A1 CNet Technology Inc.
-0008A2 ADI Engineering, Inc.
-0008A3 Cisco Systems
-0008A4 Cisco Systems
-0008A5 Peninsula Systems Inc.
-0008A6 Multiware & Image Co., Ltd.
-0008A7 iLogic Inc.
-0008A8 Systec Co., Ltd.
-0008A9 SangSang Technology, Inc.
-0008AA KARAM
-0008AB EnerLinx.com, Inc.
-0008AD Toyo-Linx Co., Ltd.
-0008AE Packetfront
-0008AF Novatec Corporation
-0008B0 BKtel communications GmbH
-0008B1 ProQuent Systems
-0008B2 SHENZHEN COMPASS TECHNOLOGY DEVELOPMENT CO.,LTD
-0008B3 Fastwel
-0008B4 SYSPOL
-0008B5 TAI GUEN ENTERPRISE CO., LTD
-0008B6 RouteFree, Inc.
-0008B7 HIT Incorporated
-0008B8 E.F. Johnson
-0008B9 KAON MEDIA Co., Ltd.
-0008BA Erskine Systems Ltd
-0008BB NetExcell
-0008BC Ilevo AB
-0008BD TEPG-US
-0008BE XENPAK MSA Group
-0008BF Aptus Elektronik AB
-0008C0 ASA SYSTEMS
-0008C1 Avistar Communications Corporation
-0008C2 Cisco Systems
-0008C3 Contex A/S
-0008C4 Hikari Co.,Ltd.
-0008C5 Liontech Co., Ltd.
-0008C6 Philips Consumer Communications
-0008C7 COMPAQ COMPUTER CORPORATION
-0008C8 Soneticom, Inc.
-0008C9 TechniSat Digital GmbH
-0008CA TwinHan Technology Co.,Ltd
-0008CB Zeta Broadband Inc.
-0008CC Remotec, Inc.
-0008CD With-Net Inc
-0008CF Nippon Koei Power Systems Co., Ltd.
-0008D0 Musashi Engineering Co., LTD.
-0008D1 KAREL INC.
-0008D2 ZOOM Networks Inc.
-0008D3 Hercules Technologies S.A.
-0008D4 IneoQuest Technologies, Inc
-0008D5 Vanguard Managed Solutions
-0008D6 HASSNET Inc.
-0008D7 HOW CORPORATION
-0008D8 Dowkey Microwave
-0008D9 Mitadenshi Co.,LTD
-0008DA SofaWare Technologies Ltd.
-0008DB Corrigent Systems
-0008DC Wiznet
-0008DD Telena Communications, Inc.
-0008DE 3UP Systems
-0008DF Alistel Inc.
-0008E0 ATO Technology Ltd.
-0008E1 Barix AG
-0008E2 Cisco Systems
-0008E3 Cisco Systems
-0008E4 Envenergy Inc
-0008E5 IDK Corporation
-0008E6 Littlefeet
-0008E7 SHI ControlSystems,Ltd.
-0008E8 Excel Master Ltd.
-0008E9 NextGig
-0008EA Motion Control Engineering, Inc
-0008EB ROMWin Co.,Ltd.
-0008EC Zonu, Inc.
-0008ED ST&T Instrument Corp.
-0008EE Logic Product Development
-0008EF DIBAL,S.A.
-0008F0 Next Generation Systems, Inc.
-0008F1 Voltaire
-0008F2 C&S Technology
-0008F3 WANY
-0008F4 Bluetake Technology Co., Ltd.
-0008F5 YESTECHNOLOGY Co.,Ltd.
-0008F6 SUMITOMO ELECTRIC HIGHTECHS.co.,ltd.
-0008F7 Hitachi Ltd, Semiconductor &amp; Integrated Circuits Gr
-0008F8 Guardall Ltd
-0008F9 Padcom, Inc.
-0008FA Karl E.Brinkmann GmbH
-0008FB SonoSite, Inc.
-0008FC Gigaphoton Inc.
-0008FD BlueKorea Co., Ltd.
-0008FE UNIK C&C Co.,Ltd.
-0008FF Trilogy Broadcast (Holdings) Ltd
-000900 TMT
-000901 Shenzhen Shixuntong Information & Technoligy Co
-000902 Redline Communications Inc.
-000903 Panasas, Inc
-000904 MONDIAL electronic
-000905 iTEC Technologies Ltd.
-000906 Esteem Networks
-000907 Chrysalis Development
-000908 VTech Technology Corp.
-000909 Telenor Connect A/S
-00090A SnedFar Technology Co., Ltd.
-00090B MTL  Instruments PLC
-00090C Mayekawa Mfg. Co. Ltd.
-00090D LEADER ELECTRONICS CORP.
-00090E Helix Technology Inc.
-00090F Fortinet Inc.
-000910 Simple Access Inc.
-000911 Cisco Systems
-000912 Cisco Systems
-000914 COMPUTROLS INC.
-000915 CAS Corp.
-000916 Listman Home Technologies, Inc.
-000917 WEM Technology Inc
-000918 SAMSUNG TECHWIN CO.,LTD
-000919 MDS Gateways
-00091A Macat Optics & Electronics Co., Ltd.
-00091B Digital Generation Inc.
-00091C CacheVision, Inc
-00091D Proteam Computer Corporation
-00091E Firstech Technology Corp.
-00091F A&amp;D Co., Ltd.
-000920 EpoX COMPUTER CO.,LTD.
-000921 Planmeca Oy
-000922 Touchless Sensor Technology AG
-000923 Heaman System Co., Ltd
-000924 Telebau GmbH
-000925 VSN Systemen BV
-000926 YODA COMMUNICATIONS, INC.
-000927 TOYOKEIKI CO.,LTD.
-000928 Telecore Inc
-000929 Sanyo Industries (UK) Limited
-00092A MYTECS Co.,Ltd.
-00092B iQstor Networks, Inc.
-00092C Hitpoint Inc.
-00092D High Tech Computer, Corp.
-00092E B&Tech System Inc.
-00092F Akom Technology Corporation
-000930 AeroConcierge Inc.
-000931 Future Internet, Inc.
-000932 Omnilux
-000933 OPTOVALLEY Co. Ltd.
-000934 Dream-Multimedia-Tv GmbH
-000935 Sandvine Incorporated
-000936 Ipetronik GmbH & Co.KG
-000937 Inventec Appliance Corp
-000938 Allot Communications
-000939 ShibaSoku Co.,Ltd.
-00093A Molex Fiber Optics
-00093B HYUNDAI NETWORKS INC.
-00093C Jacques Technologies P/L
-00093D Newisys,Inc.
-00093E C&I Technologies
-00093F Double-Win Enterpirse CO., LTD
-000940 AGFEO GmbH & Co. KG
-000941 Allied Telesis K.K.
-000942 CRESCO, LTD.
-000943 Cisco Systems
-000944 Cisco Systems
-000945 Palmmicro Communications Inc
-000946 Cluster Labs GmbH
-000947 Aztek, Inc.
-000948 Vista Control Systems, Corp.
-000949 Glyph Technologies Inc.
-00094A Homenet Communications
-00094B FillFactory NV
-00094C Communication Weaver Co.,Ltd.
-00094D Braintree Communications Pty Ltd
-00094E BARTECH SYSTEMS INTERNATIONAL, INC
-00094F elmegt GmbH & Co. KG
-000950 Independent Storage Corporation
-000951 Apogee Instruments, Inc
-000952 Auerswald GmbH & Co. KG
-000953 Linkage System Integration Co.Ltd.
-000954 AMiT spol. s. r. o.
-000955 Young Generation International Corp.
-000956 Network Systems Group, Ltd. (NSG)
-000957 Supercaller, Inc.
-000958 INTELNET S.A.
-000959 Sitecsoft
-00095A RACEWOOD TECHNOLOGY
-00095B Netgear, Inc.
-00095C Philips Medical Systems - Cardiac and Monitoring Systems (CM
-00095D Dialogue Technology Corp.
-00095E Masstech Group Inc.
-00095F Telebyte, Inc.
-000960 YOZAN Inc.
-000961 Switchgear and Instrumentation Ltd
-000962 Filetrac AS
-000963 Dominion Lasercom Inc.
-000964 Hi-Techniques
-000966 Thales Navigation
-000967 Tachyon, Inc
-000968 TECHNOVENTURE, INC.
-000969 Meret Optical Communications
-00096A Cloverleaf Communications Inc.
-00096B IBM Corporation
-00096C Imedia Semiconductor Corp.
-00096D Powernet Technologies Corp.
-00096E GIANT ELECTRONICS LTD.
-00096F Beijing Zhongqing Elegant Tech. Corp.,Limited
-000970 Vibration Research Corporation
-000971 Time Management, Inc.
-000972 Securebase,Inc
-000973 Lenten Technology Co., Ltd.
-000974 Innopia Technologies, Inc.
-000975 fSONA Communications Corporation
-000976 Datasoft ISDN Systems GmbH
-000977 Brunner Elektronik AG
-000978 AIJI System Co., Ltd.
-000979 Advanced Television Systems Committee, Inc.
-00097A Louis Design Labs.
-00097B Cisco Systems
-00097C Cisco Systems
-00097D SecWell Networks Oy
-00097E IMI TECHNOLOGY CO., LTD
-00097F Vsecure 2000 LTD.
-000980 Power Zenith Inc.
-000981 Newport Networks
-000982 Loewe Opta GmbH
-000983 Gvision Incorporated
-000984 MyCasa Network Inc.
-000985 Auto Telecom Company
-000986 Metalink LTD.
-000987 NISHI NIPPON ELECTRIC WIRE & CABLE CO.,LTD.
-000988 Nudian Electron Co., Ltd.
-000989 VividLogic Inc.
-00098A EqualLogic Inc
-00098B Entropic Communications, Inc.
-00098C Possio AB
-00098D DCT Ltd (Digital Communication Technologies Ltd)
-00098E ipcas GmbH
-00098F Cetacean Networks
-000990 ACKSYS Communications & systems
-000991 GE Fanuc Automation Manufacturing, Inc.
-000992 InterEpoch Technology,INC.
-000993 Visteon Corporation
-000994 Cronyx Engineering
-000995 Castle Technology Ltd
-000996 RDI
-000997 Nortel Networks
-000998 Capinfo Company Limited
-000999 CP GEORGES RENAULT
-00099A ELMO COMPANY, LIMITED
-00099B Western Telematic Inc.
-00099C Naval Research Laboratory
-00099D Haliplex Communications
-00099E Testech, Inc.
-00099F VIDEX INC.
-0009A0 Microtechno Corporation
-0009A1 Telewise Communications, Inc.
-0009A2 Interface Co., Ltd.
-0009A3 Leadfly Techologies Corp. Ltd.
-0009A4 HARTEC Corporation
-0009A5 HANSUNG ELETRONIC INDUSTRIES DEVELOPMENT CO., LTD
-0009A6 Ignis Optics, Inc.
-0009A7 Bang & Olufsen A/S
-0009A8 Eastmode Pte Ltd
-0009A9 Ikanos Communications
-0009AA Data Comm for Business, Inc.
-0009AB Netcontrol Oy
-0009AC LANVOICE
-0009AD HYUNDAI SYSCOMM, INC.
-0009AE OKANO ELECTRIC CO.,LTD
-0009AF e-generis
-0009B0 Onkyo Corporation
-0009B1 Kanematsu Electronics, Ltd.
-0009B2 L&F Inc.
-0009B3 MCM Systems Ltd
-0009B4 KISAN TELECOM CO., LTD.
-0009B5 3J Tech. Co., Ltd.
-0009B6 Cisco Systems
-0009B7 Cisco Systems
-0009B8 Entise Systems
-0009B9 Action Imaging Solutions
-0009BA MAKU Informationstechik GmbH
-0009BB MathStar, Inc.
-0009BC Digital Safety Technologies Inc.
-0009BD Epygi Technologies, Ltd.
-0009BE Mamiya-OP Co.,Ltd.
-0009BF Nintendo Co.,Ltd.
-0009C0 6WIND
-0009C1 PROCES-DATA A/S
-0009C3 NETAS
-0009C4 Medicore Co., Ltd
-0009C5 KINGENE Technology Corporation
-0009C6 Visionics Corporation
-0009C7 Movistec
-0009C8 SINAGAWA TSUSHIN KEISOU SERVICE
-0009C9 BlueWINC Co., Ltd.
-0009CA iMaxNetworks(Shenzhen)Limited.
-0009CB HBrain
-0009CC Moog GmbH
-0009CD HUDSON SOFT CO.,LTD.
-0009CE SpaceBridge Semiconductor Corp.
-0009CF iAd GmbH
-0009D0 Versatel Networks
-0009D1 SERANOA NETWORKS INC
-0009D2 Mai Logic Inc.
-0009D3 Western DataCom Co., Inc.
-0009D4 Transtech Networks
-0009D5 Signal Communication, Inc.
-0009D6 KNC One GmbH
-0009D7 DC Security Products
-0009D9 Neoscale Systems, Inc
-0009DA Control Module Inc.
-0009DB eSpace
-0009DC Galaxis Technology AG
-0009DD Mavin Technology Inc.
-0009DE Samjin Information & Communications Co., Ltd.
-0009DF Vestel Komunikasyon Sanayi ve Ticaret A.S.
-0009E0 XEMICS S.A.
-0009E1 Gemtek Technology Co., Ltd.
-0009E2 Sinbon Electronics Co., Ltd.
-0009E3 Angel Iglesias S.A.
-0009E4 K Tech Infosystem Inc.
-0009E5 Hottinger Baldwin Messtechnik GmbH
-0009E6 Cyber Switching Inc.
-0009E7 ADC Techonology
-0009E8 Cisco Systems
-0009E9 Cisco Systems
-0009EA YEM Inc.
-0009EB HuMANDATA LTD.
-0009EC Daktronics, Inc.
-0009ED CipherOptics
-0009EE MEIKYO ELECTRIC CO.,LTD
-0009EF Vocera Communications
-0009F0 Shimizu Technology Inc.
-0009F1 Yamaki Electric Corporation
-0009F2 Cohu, Inc., Electronics Division
-0009F3 WELL Communication Corp.
-0009F4 Alcon Laboratories, Inc.
-0009F5 Emerson Network Power Co.,Ltd
-0009F6 Shenzhen Eastern Digital Tech Ltd.
-0009F7 SED, a division of Calian
-0009F8 UNIMO TECHNOLOGY CO., LTD.
-0009F9 ART JAPAN CO., LTD.
-0009FB Philips Medizinsysteme Boeblingen GmbH
-0009FC IPFLEX Inc.
-0009FD Ubinetics Limited
-0009FE Daisy Technologies, Inc.
-0009FF X.net 2000 GmbH
-000A00 Mediatek Corp.
-000A01 SOHOware, Inc.
-000A02 ANNSO CO., LTD.
-000A03 ENDESA SERVICIOS, S.L.
-000A04 3Com Europe Ltd
-000A05 Widax Corp.
-000A06 Teledex LLC
-000A07 WebWayOne Ltd
-000A08 ALPINE ELECTRONICS, INC.
-000A09 TaraCom Integrated Products, Inc.
-000A0A SUNIX Co., Ltd.
-000A0B Sealevel Systems, Inc.
-000A0C Scientific Research Corporation
-000A0D MergeOptics GmbH
-000A0E Invivo Research Inc.
-000A0F Ilryung Telesys, Inc
-000A10 FAST media integrations AG
-000A11 ExPet Technologies, Inc
-000A12 Azylex Technology, Inc
-000A13 Silent Witness
-000A14 TECO a.s.
-000A15 Silicon Data, Inc
-000A16 Lassen Research
-000A17 NESTAR COMMUNICATIONS, INC
-000A18 Vichel Inc.
-000A19 Valere Power, Inc.
-000A1A Imerge Ltd
-000A1B Stream Labs
-000A1C Bridge Information Co., Ltd.
-000A1D Optical Communications Products Inc.
-000A1E Red-M (Communications) Limited
-000A1F ART WARE Telecommunication Co., Ltd.
-000A20 SVA Networks, Inc.
-000A21 Integra Telecom Co. Ltd
-000A22 Amperion Inc
-000A23 Parama Networks Inc
-000A24 Octave Communications
-000A25 CERAGON NETWORKS
-000A26 CEIA S.p.A.
-000A27 Apple Computer, Inc.
-000A28 Motorola
-000A29 Pan Dacom Networking AG
-000A2A QSI Systems Inc.
-000A2B Etherstuff
-000A2C Active Tchnology Corporation
-000A2E MAPLE NETWORKS CO., LTD
-000A2F Artnix Inc.
-000A30 Johnson Controls-ASG
-000A31 HCV Wireless
-000A32 Xsido Corporation
-000A33 Sierra Logic, Inc.
-000A34 Identicard Systems Incorporated
-000A35 Xilinx
-000A36 Synelec Telecom Multimedia
-000A37 Procera Networks, Inc.
-000A38 Netlock Technologies, Inc.
-000A39 LoPA Information Technology
-000A3A J-THREE INTERNATIONAL Holding Co., Ltd.
-000A3B GCT Semiconductor, Inc
-000A3C Enerpoint Ltd.
-000A3D Elo Sistemas Eletronicos S.A.
-000A3E EADS Telecom
-000A3F Data East Corporation
-000A40 Crown Audio
-000A41 Cisco Systems
-000A42 Cisco Systems
-000A43 Chunghwa Telecom Co., Ltd.
-000A44 Avery Dennison Deutschland GmbH
-000A45 Audio-Technica Corp.
-000A46 ARO Controls SAS
-000A47 Allied Vision Technologies
-000A48 Albatron Technology
-000A49 Acopia Networks
-000A4A Targa Systems Ltd.
-000A4B DataPower Technology, Inc.
-000A4C Molecular Devices Corporation
-000A4D Noritz Corporation
-000A4E UNITEK Electronics INC.
-000A4F Brain Boxes Limited
-000A50 REMOTEK CORPORATION
-000A51 GyroSignal Technology Co., Ltd.
-000A52 Venitek Co. Ltd.
-000A53 Intronics, Incorporated
-000A54 Laguna Hills, Inc.
-000A55 MARKEM Corporation
-000A56 HITACHI Maxell Ltd.
-000A57 Hewlett-Packard Company - Standards
-000A58 Ingenieur-Buero Freyer & Siegel
-000A59 HW server
-000A5A GreenNET Technologies Co.,Ltd.
-000A5B Power-One as
-000A5C Carel s.p.a.
-000A5D PUC Founder (MSC) Berhad
-000A5E 3COM Corporation
-000A5F almedio inc.
-000A60 Autostar Technology Pte Ltd
-000A61 Cellinx Systems Inc.
-000A62 Crinis Networks, Inc.
-000A63 DHD GmbH
-000A64 Eracom Technologies
-000A65 GentechMedia.co.,ltd.
-000A66 MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD.
-000A67 OngCorp
-000A68 SolarFlare Communications, Inc.
-000A69 SUNNY bell Technology Co., Ltd.
-000A6A SVM Microwaves s.r.o.
-000A6B Tadiran Telecom Business Systems LTD
-000A6C Walchem Corporation
-000A6D EKS Elektronikservice GmbH
-000A6E Broadcast Technology Limited
-000A6F ZyTera Technologies Inc.
-000A70 MPLS Forum
-000A71 Avrio Technologies, Inc
-000A72 SimpleTech, Inc.
-000A73 Scientific Atlanta
-000A74 Manticom Networks Inc.
-000A75 Cat Electronics
-000A76 Beida Jade Bird Huaguang Technology Co.,Ltd
-000A77 Bluewire Technologies LLC
-000A78 OLITEC
-000A79 corega K.K.
-000A7A Kyoritsu Electric Co., Ltd.
-000A7B Cornelius Consult
-000A7C Tecton Ltd
-000A7D Valo, Inc.
-000A7E The Advantage Group
-000A7F Teradon Industries, Inc
-000A80 Telkonet Inc.
-000A81 TEIMA Audiotex S.L.
-000A82 TATSUTA SYSTEM ELECTRONICS CO.,LTD.
-000A83 SALTO SYSTEMS S.L.
-000A84 Rainsun Enterprise Co., Ltd.
-000A85 PLAT'C2,Inc
-000A86 Lenze
-000A87 Integrated Micromachines Inc.
-000A88 InCypher S.A.
-000A89 Creval Systems, Inc.
-000A8A Cisco Systems
-000A8B Cisco Systems
-000A8C Guardware Systems Ltd.
-000A8D EUROTHERM LIMITED
-000A8E Invacom Ltd
-000A8F Aska International Inc.
-000A90 Bayside Interactive, Inc.
-000A91 HemoCue AB
-000A92 Presonus Corporation
-000A93 W2 Networks, Inc.
-000A94 ShangHai cellink CO., LTD
-000A95 Apple Computer, Inc.
-000A96 MEWTEL TECHNOLOGY INC.
-000A97 SONICblue, Inc.
-000A98 M+F Gwinner GmbH & Co
-000A99 Dataradio Inc.
-000A9A Aiptek International Inc
-000A9B Towa Meccs Corporation
-000A9C Server Technology, Inc.
-000A9D King Young Technology Co. Ltd.
-000A9E BroadWeb Corportation
-000A9F Pannaway Technologies, Inc.
-000AA0 Cedar Point Communications
-000AA1 V V S Limited
-000AA2 SYSTEK INC.
-000AA3 SHIMAFUJI ELECTRIC CO.,LTD.
-000AA4 SHANGHAI SURVEILLANCE TECHNOLOGY CO,LTD
-000AA5 MAXLINK INDUSTRIES LIMITED
-000AA6 Hochiki Corporation
-000AA7 FEI Company
-000AA8 ePipe Pty. Ltd.
-000AA9 Brooks Automation GmbH
-000AAA AltiGen Communications Inc.
-000AAB TOYOTA MACS, INC.
-000AAC TerraTec Electronic GmbH
-000AAD Stargames Corporation
-000AAE Rosemount Process Analytical
-000AAF Pipal Systems
-000AB0 LOYTEC electronics GmbH
-000AB1 GENETEC Corporation
-000AB2 Fresnel Wireless Systems
-000AB3 Fa. GIRA
-000AB4 ETIC Telecommunications
-000AB5 Digital Electronic Network
-000AB6 COMPUNETIX, INC
-000AB7 Cisco Systems
-000AB8 Cisco Systems
-000AB9 Astera Technologies Corp.
-000ABA Arcon Technology Limited
-000ABB Taiwan Secom Co,. Ltd
-000ABC Seabridge Ltd.
-000ABD Rupprecht & Patashnick Co.
-000ABE OPNET Technologies CO., LTD.
-000ABF HIROTA SS
-000AC0 Fuyoh Video Industry CO., LTD.
-000AC1 Futuretel
-000AC2 FiberHome Telecommunication Technologies CO.,LTD
-000AC3 eM Technics Co., Ltd.
-000AC4 Daewoo Teletech Co., Ltd
-000AC5 Color Kinetics
-000AC7 Unication Group
-000AC8 ZPSYS CO.,LTD. (Planning&Management)
-000AC9 Zambeel Inc
-000ACA YOKOYAMA SHOKAI CO.,Ltd.
-000ACB XPAK MSA Group
-000ACC Winnow Networks, Inc.
-000ACD Sunrich Technology Limited
-000ACE RADIANTECH, INC.
-000ACF PROVIDEO Multimedia Co. Ltd.
-000AD0 Niigata Develoment Center,  F.I.T. Co., Ltd.
-000AD1 MWS
-000AD2 JEPICO Corporation
-000AD3 INITECH Co., Ltd
-000AD4 CoreBell Systems Inc.
-000AD5 Brainchild Electronic Co., Ltd.
-000AD6 BeamReach Networks
-000AD8 IPCserv Technology Corp.
-000AD9 Sony Ericsson Mobile Communications AB
-000ADB SkyPilot Network, Inc
-000ADC RuggedCom Inc.
-000ADD InSciTek Microsystems, Inc.
-000ADE Happy Communication Co., Ltd.
-000ADF Gennum Corporation
-000AE0 Fujitsu Softek
-000AE1 EG Technology
-000AE2 Binatone Electronics International, Ltd
-000AE3 YANG MEI TECHNOLOGY CO., LTD
-000AE4 Wistron Corp.
-000AE5 ScottCare Corporation
-000AE6 Elitegroup Computer System Co. (ECS)
-000AE7 ELIOP S.A.
-000AE8 Cathay Roxus Information Technology Co. LTD
-000AE9 AirVast Technology Inc.
-000AEA ADAM ELEKTRONIK LTD.STI.
-000AEB Shenzhen Tp-link Technology Co; Ltd.
-000AEC Koatsu Gas Kogyo Co., Ltd.
-000AED HARTING Vending G.m.b.H. & CO KG
-000AEE GCD Hard- & Software GmbH
-000AEF OTRUM ASA
-000AF0 SHIN-OH ELECTRONICS CO., LTD. R&D
-000AF1 Clarity Design, Inc.
-000AF2 NeoAxiom Corp.
-000AF3 Cisco Systems
-000AF4 Cisco Systems
-000AF5 Airgo Networks, Inc.
-000AF6 Computer Process Controls
-000AF7 Broadcom Corp.
-000AF8 American Telecare Inc.
-000AFA Traverse Technologies Australia
-000AFB Ambri Limited
-000AFC Core Tec Communications, LLC
-000AFD Viking Electronic Services
-000AFE NovaPal Ltd
-000AFF Kilchherr Elektronik AG
-000B00 FUJIAN START COMPUTER EQUIPMENT CO.,LTD
-000B01 DAIICHI ELECTRONICS CO., LTD.
-000B02 Dallmeier electronic
-000B03 Taekwang Industrial Co., Ltd
-000B04 Volktek Corporation
-000B05 Pacific Broadband Networks
-000B06 Motorola BCS
-000B07 Voxpath Networks
-000B08 Pillar Data Systems
-000B09 Ifoundry Systems Singapore
-000B0A dBm Optics
-000B0B Corrent Corporation
-000B0C Agile Systems Inc.
-000B0D Air2U, Inc.
-000B0E Trapeze Networks
-000B0F Nyquist Industrial Control BV
-000B10 11wave Technonlogy Co.,Ltd
-000B11 HIMEJI ABC TRADING CO.,LTD.
-000B13 ZETRON INC
-000B14 ViewSonic Corporation
-000B15 Platypus Technology
-000B16 Communication Machinery Corporation
-000B17 MKS Instruments
-000B19 Vernier Networks, Inc.
-000B1A Teltone Corporation
-000B1B Systronix, Inc.
-000B1D LayerZero Power Systems, Inc.
-000B1E KAPPA opto-electronics GmbH
-000B1F I CON Computer Co.
-000B20 Hirata corporation
-000B21 G-Star Communications Inc.
-000B22 Environmental Systems and Services
-000B23 Efficient Networks, Inc.
-000B24 AirLogic
-000B25 Aeluros
-000B26 Wetek Corporation
-000B27 Scion Corporation
-000B28 Quatech Inc.
-000B29 LG Industrial Systems Co.,Ltd.
-000B2A HOWTEL Co., Ltd.
-000B2B HOSTNET CORPORATION
-000B2C Eiki Industrial Co. Ltd.
-000B2D Danfoss Inc.
-000B2E Cal-Comp Electronics (Thailand) Public Company Limited Taipe
-000B2F bplan GmbH
-000B30 Beijing Gongye Science & Technology Co.,Ltd
-000B31 Yantai ZhiYang Scientific and technology industry CO., LTD
-000B32 VORMETRIC, INC.
-000B33 Vivato
-000B34 ShangHai Broadband Technologies CO.LTD
-000B35 Quad Bit System co., Ltd.
-000B36 Productivity Systems, Inc.
-000B37 MANUFACTURE DES MONTRES ROLEX SA
-000B38 Knuerr AG
-000B39 Keisoku Giken Co.,Ltd.
-000B3A Fortel DTV, Inc.
-000B3B devolo AG
-000B3C Cygnal Integrated Products, Inc.
-000B3D CONTAL OK Ltd.
-000B3E BittWare, Inc
-000B3F Anthology Solutions Inc.
-000B40 OpNext Inc.
-000B41 Ing. Buero Dr. Beutlhauser
-000B42 commax Co., Ltd.
-000B43 Microscan Systems, Inc.
-000B44 Concord IDea Corp.
-000B45 Cisco
-000B46 Cisco
-000B47 Advanced Energy
-000B48 sofrel
-000B49 RF-Link System Inc.
-000B4A Visimetrics (UK) Ltd
-000B4B VISIOWAVE SA
-000B4C Clarion (M) Sdn Bhd
-000B4D Emuzed
-000B4E VertexRSI Antenna Products Division
-000B4F Verifone, INC.
-000B50 Oxygnet
-000B51 Micetek International Inc.
-000B52 JOYMAX ELECTRONICS CORP.
-000B53 INITIUM Co., Ltd.
-000B54 BiTMICRO Networks, Inc.
-000B55 ADInstruments
-000B56 Cybernetics
-000B57 Silicon Laboratories
-000B58 Astronautics C.A  LTD
-000B59 ScriptPro, LLC
-000B5A HyperEdge
-000B5B Rincon Research Corporation
-000B5C Newtech Co.,Ltd
-000B5D FUJITSU LIMITED
-000B5E ATMAVA Ltd
-000B5F Cisco Systems
-000B60 Cisco Systems
-000B61 Friedrich Lütze GmbH &Co.
-000B62 Ingenieurbüro Ingo Mohnen
-000B64 Kieback & Peter GmbH & Co KG
-000B65 Sy.A.C. srl
-000B66 Teralink Communications
-000B67 Topview Technology Corporation
-000B68 Addvalue Communications Pte Ltd
-000B69 Franke Finland Oy
-000B6A Asiarock Incorporation
-000B6B Wistron Neweb Corp.
-000B6C Sychip Inc.
-000B6D SOLECTRON JAPAN NAKANIIDA
-000B6E Neff Instrument Corp.
-000B6F Media Streaming Networks Inc
-000B70 Load Technology, Inc.
-000B71 Litchfield Communications Inc.
-000B72 Lawo AG
-000B73 Kodeos Communications
-000B74 Kingwave Technology Co., Ltd.
-000B75 Iosoft Ltd.
-000B76 ET&T Co. Ltd.
-000B77 Cogent Systems, Inc.
-000B78 TAIFATECH INC.
-000B79 X-COM, Inc.
-000B7B Test-Um Inc.
-000B7C Telex Communications
-000B7D SOLOMON EXTREME INTERNATIONAL LTD.
-000B7E SAGINOMIYA Seisakusho Inc.
-000B7F OmniWerks
-000B81 Kaparel Corporation
-000B82 Grandstream Networks, Inc.
-000B83 DATAWATT B.V.
-000B84 BODET
-000B85 Airespace, Inc.
-000B86 Aruba Networks
-000B87 American Reliance Inc.
-000B88 Vidisco ltd.
-000B89 Top Global Technology, Ltd.
-000B8A MITEQ Inc.
-000B8B KERAJET, S.A.
-000B8C flextronics israel
-000B8D Avvio Networks
-000B8E Ascent Corporation
-000B8F AKITA ELECTRONICS SYSTEMS CO.,LTD.
-000B90 Covaro Networks, Inc.
-000B91 Aglaia Gesellschaft für Bildverarbeitung und Kommunikation m
-000B92 Ascom Danmark A/S
-000B93 Barmag Electronic
-000B94 Digital Monitoring Products, Inc.
-000B95 eBet Gaming Systems Pty Ltd
-000B96 Innotrac Diagnostics Oy
-000B97 Matsushita Electric Industrial Co.,Ltd.
-000B98 NiceTechVision
-000B99 SensAble Technologies, Inc.
-000B9A Shanghai Ulink Telecom Equipment Co. Ltd.
-000B9B Sirius System Co, Ltd.
-000B9C TriBeam Technologies, Inc.
-000B9D TwinMOS Technologies Inc.
-000B9E Yasing Technology Corp.
-000B9F Neue ELSA GmbH
-000BA0 T&L Information Inc.
-000BA1 SYSCOM Ltd.
-000BA2 Sumitomo Electric Networks, Inc
-000BA3 Siemens AG, I&S
-000BA4 Shiron Satellite Communications Ltd. (1996)
-000BA5 Quasar Cipta Mandiri, PT
-000BA6 Miyakawa Electric Works Ltd.
-000BA7 Maranti Networks
-000BA8 HANBACK ELECTRONICS CO., LTD.
-000BAA Aiphone co.,Ltd
-000BAB Advantech Technology (CHINA) Co., Ltd.
-000BAC 3Com Europe Ltd.
-000BAD PC-PoS Inc.
-000BAE Vitals System Inc.
-000BB0 Sysnet Telematica srl
-000BB1 Super Star Technology Co., Ltd.
-000BB2 SMALLBIG TECHNOLOGY
-000BB3 RiT technologies Ltd.
-000BB4 RDC Semiconductor Inc.,
-000BB5 nStor Technologies, Inc.
-000BB6 Mototech Inc.
-000BB7 Micro Systems Co.,Ltd.
-000BB8 Kihoku Electronic Co.
-000BB9 Imsys AB
-000BBA Harmonic Broadband Access Networks
-000BBB Etin Systems Co., Ltd
-000BBC En Garde Systems, Inc.
-000BBD Connexionz Limited
-000BBE Cisco Systems
-000BBF Cisco Systems
-000BC0 China IWNComm Co., Ltd.
-000BC1 Bay Microsystems, Inc.
-000BC2 Corinex Communication Corp.
-000BC3 Multiplex, Inc.
-000BC4 BIOTRONIK GmbH & Co
-000BC5 SMC Networks, Inc.
-000BC6 ISAC, Inc.
-000BC7 ICET S.p.A.
-000BC8 AirFlow Networks
-000BC9 Electroline Equipment
-000BCA DATAVAN International Corporation
-000BCB Fagor Automation , S. Coop
-000BCC JUSAN, S.A.
-000BCD Compaq (HP)
-000BCE Free2move AB
-000BCF AGFA NDT INC.
-000BD0 XiMeta Technology Americas Inc.
-000BD1 Aeronix, Inc.
-000BD2 Remopro Technology Inc.
-000BD3 cd3o
-000BD4 Beijing Wise Technology & Science Development Co.Ltd
-000BD5 Nvergence, Inc.
-000BD6 Paxton Access Ltd
-000BD7 MBB Gelma GmbH
-000BD8 Industrial Scientific Corp.
-000BD9 General Hydrogen
-000BDA EyeCross Co.,Inc.
-000BDB Dell ESG PCBA Test
-000BDC AKCP
-000BDD TOHOKU RICOH Co., LTD.
-000BDF Shenzhen RouterD Networks Limited
-000BE0 SercoNet Ltd.
-000BE2 Lumenera Corporation
-000BE3 Key Stream Co., Ltd.
-000BE4 Hosiden Corporation
-000BE5 HIMS Korea Co., Ltd.
-000BE6 Datel Electronics
-000BE7 COMFLUX TECHNOLOGY INC.
-000BE8 AOIP
-000BEA Zultys Technologies
-000BEB Systegra AG
-000BEC NIPPON ELECTRIC INSTRUMENT, INC.
-000BED ELM Inc.
-000BEE inc.jet, Incorporated
-000BEF Code Corporation
-000BF0 MoTEX Products Co., Ltd.
-000BF1 LAP Laser Applikations
-000BF2 Chih-Kan Technology Co., Ltd.
-000BF3 BAE SYSTEMS
-000BF5 Shanghai Sibo Telecom Technology Co.,Ltd
-000BF6 Nitgen Co., Ltd
-000BF7 NIDEK CO.,LTD
-000BF8 Infinera
-000BF9 Gemstone communications, Inc.
-000BFB D-NET International Corporation
-000BFC Cisco Systems
-000BFD Cisco Systems
-000BFE CASTEL Broadband Limited
-000BFF Berkeley Camera Engineering
-000C00 BEB Industrie-Elektronik AG
-000C01 Abatron AG
-000C02 ABB Oy
-000C03 HDMI Licensing, LLC
-000C04 Tecnova
-000C05 RPA Reserch Co., Ltd.
-000C06 Nixvue Systems  Pte Ltd
-000C07 Iftest AG
-000C08 HUMEX Technologies Corp.
-000C09 Hitachi IE Systems Co., Ltd
-000C0A Guangdong Province Electronic Technology Research Institute
-000C0B Broadbus Technologies
-000C0C APPRO TECHNOLOGY INC.
-000C0D Communications & Power Industries / Satcom Division
-000C0E XtremeSpectrum, Inc.
-000C0F Techno-One Co., Ltd
-000C10 PNI Corporation
-000C11 NIPPON DEMPA CO.,LTD.
-000C12 Micro-Optronic-Messtechnik GmbH
-000C13 MediaQ
-000C14 Diagnostic Instruments, Inc.
-000C15 CyberPower Systems, Inc.
-000C16 Concorde Microsystems Inc.
-000C17 AJA Video Systems Inc
-000C18 Zenisu Keisoku Inc.
-000C19 Telio Communications GmbH
-000C1A Quest Technical Solutions Inc.
-000C1B ORACOM Co, Ltd.
-000C1C MicroWeb Co., Ltd.
-000C1D Mettler & Fuchs AG
-000C1E Global Cache
-000C1F Glimmerglass Networks
-000C20 Fi WIn, Inc.
-000C21 Faculty of Science and Technology, Keio University
-000C22 Double D Electronics Ltd
-000C23 Beijing Lanchuan Tech. Co., Ltd.
-000C25 Allied Telesyn Networks
-000C26 Weintek Labs. Inc.
-000C27 Sammy Corporation
-000C28 RIFATRON
-000C29 VMware, Inc.
-000C2A OCTTEL Communication Co., Ltd.
-000C2B ELIAS Technology, Inc.
-000C2C Enwiser Inc.
-000C2D FullWave Technology Co., Ltd.
-000C2E Openet information technology(shenzhen) Co., Ltd.
-000C2F SeorimTechnology Co.,Ltd.
-000C30 Cisco
-000C31 Cisco
-000C32 Avionic Design Development GmbH
-000C33 Compucase Enterprise Co. Ltd.
-000C34 Vixen Co., Ltd.
-000C35 KaVo Dental GmbH & Co. KG
-000C36 SHARP TAKAYA ELECTRONICS INDUSTRY CO.,LTD.
-000C37 Geomation, Inc.
-000C38 TelcoBridges Inc.
-000C39 Sentinel Wireless Inc.
-000C3A Oxance
-000C3B Orion Electric Co., Ltd.
-000C3C MediaChorus, Inc.
-000C3D Glsystech Co., Ltd.
-000C3E Crest Audio
-000C3F Cogent Defence & Security Networks,
-000C40 Altech Controls
-000C41 The Linksys Group, Inc.
-000C42 Routerboard.com
-000C43 Ralink Technology, Corp.
-000C44 Automated Interfaces, Inc.
-000C45 Animation Technologies Inc.
-000C46 Allied Telesyn Inc.
-000C47 SK Teletech(R&D Planning Team)
-000C48 QoStek Corporation
-000C49 Dangaard Telecom RTC Division A/S
-000C4A Cygnus Microsystems Private Limited
-000C4B Cheops Elektronik
-000C4C Arcor AG&Co.
-000C4D ACRA CONTROL
-000C4E Winbest Technology CO,LT
-000C4F UDTech Japan Corporation
-000C50 Seagate Technology
-000C51 Scientific Technologies Inc.
-000C52 Roll Systems Inc.
-000C54 Pedestal Networks, Inc
-000C55 Microlink Communications Inc.
-000C56 Megatel Computer (1986) Corp.
-000C57 MACKIE Engineering Services Belgium BVBA
-000C58 M&S Systems
-000C59 Indyme Electronics, Inc.
-000C5A IBSmm Industrieelektronik Multimedia
-000C5B HANWANG TECHNOLOGY CO.,LTD
-000C5C GTN Systems B.V.
-000C5D CHIC TECHNOLOGY (CHINA) CORP.
-000C5F Avtec, Inc.
-000C60 ACM Systems
-000C61 AC Tech corporation DBA Advanced Digital
-000C62 ABB Automation Technology Products AB, Control
-000C63 Zenith Electronics Corporation
-000C64 X2 MSA Group
-000C65 Sunin Telecom
-000C66 Pronto Networks Inc
-000C67 OYO ELECTRIC CO.,LTD
-000C68 Oasis Semiconductor, Inc.
-000C69 National Radio Astronomy Observatory
-000C6A MBARI
-000C6B Kurz Industrie-Elektronik GmbH
-000C6C Elgato Systems LLC
-000C6D BOC Edwards
-000C6E ASUSTEK COMPUTER INC.
-000C6F Amtek system co.,LTD.
-000C70 ACC GmbH
-000C71 Wybron, Inc
-000C72 Tempearl Industrial Co., Ltd.
-000C73 TELSON ELECTRONICS CO., LTD
-000C74 RIVERTEC CORPORATION
-000C75 Oriental integrated electronics. LTD
-000C76 MICRO-STAR INTERNATIONAL CO., LTD.
-000C77 Life Racing Ltd
-000C78 In-Tech Electronics Limited
-000C79 Extel Communications P/L
-000C7A DaTARIUS Technologies GmbH
-000C7B ALPHA PROJECT Co.,Ltd.
-000C7C Internet Information Image Inc.
-000C7D TEIKOKU ELECTRIC MFG. CO., LTD
-000C7E Tellium Incorporated
-000C7F synertronixx GmbH
-000C80 Opelcomm Inc.
-000C81 Nulec Industries Pty Ltd
-000C82 NETWORK TECHNOLOGIES INC
-000C83 Logical Solutions
-000C84 Eazix, Inc.
-000C85 Cisco Systems
-000C86 Cisco Systems
-000C87 ATI
-000C88 Apache Micro Peripherals, Inc.
-000C89 AC Electric Vehicles, Ltd.
-000C8A Bose Corporation
-000C8B Connect Tech Inc
-000C8C KODICOM CO.,LTD.
-000C8D MATRIX VISION GmbH
-000C8E Mentor Engineering Inc
-000C8F Nergal s.r.l.
-000C90 Octasic Inc.
-000C91 Riverhead Networks Inc.
-000C92 WolfVision Gmbh
-000C93 Xeline Co., Ltd.
-000C94 United Electronic Industries, Inc.
-000C95 PrimeNet
-000C96 OQO, Inc.
-000C97 NV ADB TTV Technologies SA
-000C98 LETEK Communications Inc.
-000C99 HITEL LINK Co.,Ltd
-000C9A Hitech Electronics Corp.
-000C9B EE Solutions, Inc
-000C9C Chongho information & communications
-000C9D AirWalk Communications, Inc.
-000C9E MemoryLink Corp.
-000C9F NKE Corporation
-000CA0 StorCase Technology, Inc.
-000CA1 SIGMACOM Co., LTD.
-000CA2 Scopus Network Technologies Ltd
-000CA3 Rancho Technology, Inc.
-000CA4 Prompttec Product Management GmbH
-000CA6 Mintera Corporation
-000CA7 Metro (Suzhou) Technologies Co., Ltd.
-000CA8 Garuda Networks Corporation
-000CA9 Ebtron Inc.
-000CAA Cubic Transportation Systems Inc
-000CAB COMMEND International
-000CAC Citizen Watch Co., Ltd.
-000CAD BTU International
-000CAE Ailocom Oy
-000CAF TRI TERM CO.,LTD.
-000CB0 Star Semiconductor Corporation
-000CB1 Salland Engineering (Europe) BV
-000CB2 safei Co., Ltd.
-000CB3 ROUND Co.,Ltd.
-000CB4 Propagate Networks, Inc
-000CB5 Premier Technolgies, Inc
-000CB6 NANJING SEU MOBILE & INTERNET TECHNOLOGY CO.,LTD
-000CB7 Nanjing Huazhuo Electronics Co., Ltd.
-000CB8 MEDION AG
-000CB9 LEA
-000CBA Jamex
-000CBB ISKRAEMECO
-000CBC Iscutum
-000CBD Interface Masters, Inc
-000CBF Holy Stone Ent. Co., Ltd.
-000CC0 Genera Oy
-000CC1 Cooper Industries Inc.
-000CC3 BeWAN systems
-000CC4 Tiptel AG
-000CC5 Nextlink Co., Ltd.
-000CC6 Ka-Ro electronics GmbH
-000CC7 Intelligent Computer Solutions Inc.
-000CC8 Integrated Digital Systems, Inc.
-000CC9 ILWOO DATA & TECHNOLOGY CO.,LTD
-000CCA Hitachi Global Storage Technologies
-000CCB Design Combus Ltd
-000CCC Bluesoft Ltd.
-000CCD IEC - TC57
-000CCE Cisco Systems
-000CCF Cisco Systems
-000CD0 Symetrix
-000CD1 SFOM Technology Corp.
-000CD2 Schaffner EMV AG
-000CD3 Prettl Elektronik Radeberg GmbH
-000CD4 Positron Public Safety Systems inc.
-000CD5 Passave Inc.
-000CD6 PARTNER TECH
-000CD7 Nallatech Ltd
-000CD8 M. K. Juchheim GmbH & Co
-000CD9 Itcare Co., Ltd
-000CDA FreeHand Systems, Inc.
-000CDB Foundry Networks
-000CDC BECS Technology, Inc
-000CDD AOS Technologies AG
-000CDE ABB STOTZ-KONTAKT GmbH
-000CDF PULNiX America, Inc
-000CE0 Trek Diagnostics Inc.
-000CE1 The Open Group
-000CE2 Rolls-Royce
-000CE3 Option International N.V.
-000CE4 NeuroCom International, Inc.
-000CE5 Motorola BCS
-000CE6 Meru Networks Inc
-000CE7 MediaTek Inc.
-000CE8 GuangZhou AnJuBao Co., Ltd
-000CE9 BLOOMBERG L.P.
-000CEA aphona Kommunikationssysteme
-000CEB CNMP Networks, Inc.
-000CEC Spectracom Corp.
-000CED Real Digital Media
-000CEE Q-Networks
-000CEF Open Networks Engineering Ltd
-000CF0 M & N GmbH
-000CF1 Intel Corporation
-000CF2 GAMESA EÓLICA
-000CF3 CALL IMAGE SA
-000CF4 AKATSUKI ELECTRIC MFG.CO.,LTD.
-000CF5 InfoExpress
-000CF6 Sitecom Europe BV
-000CF7 Nortel Networks
-000CF8 Nortel Networks
-000CF9 ITT Flygt AB
-000CFA Digital Systems Corp
-000CFB Korea Network Systems
-000CFC S2io Technologies Corp
-000CFE Grand Electronic Co., Ltd
-000CFF MRO-TEK LIMITED
-000D00 Seaway Networks Inc.
-000D01 P&E Microcomputer Systems, Inc.
-000D02 NEC Access Technica,Ltd
-000D03 Matrics, Inc.
-000D04 Foxboro Eckardt Development GmbH
-000D05 cybernet manufacturing inc.
-000D06 Compulogic Limited
-000D07 Calrec Audio Ltd
-000D08 AboveCable, Inc.
-000D09 Yuehua(Zhuhai) Electronic CO. LTD
-000D0A Projectiondesign as
-000D0B Melco Inc.
-000D0C MDI Security Systems
-000D0D ITSupported, LLC
-000D0E Inqnet Systems, Inc.
-000D0F Finlux Ltd
-000D10 Embedtronics Oy
-000D11 DENTSPLY - Gendex
-000D12 AXELL Corporation
-000D13 Wilhelm Rutenbeck GmbH&Co.
-000D14 Vtech Innovation LP dba Advanced American Telephones
-000D15 Voipac s.r.o.
-000D16 UHS Systems Pty Ltd
-000D17 Turbo Networks Co.Ltd
-000D18 Sunitec Enterprise Co., Ltd.
-000D19 ROBE Show lighting
-000D1A Mustek System Inc.
-000D1B Kyoto Electronics Manufacturing Co., Ltd.
-000D1C I2E TELECOM
-000D1D HIGH-TEK HARNESS ENT. CO., LTD.
-000D1E Control Techniques
-000D1F AV Digital
-000D20 ASAHIKASEI TECHNOSYSTEM CO.,LTD.
-000D21 WISCORE Inc.
-000D22 Unitronics
-000D23 Smart Solution, Inc
-000D24 SENTEC E&E CO., LTD.
-000D25 SANDEN CORPORATION
-000D26 Primagraphics Limited
-000D27 MICROPLEX Printware AG
-000D28 Cisco
-000D29 Cisco
-000D2A Scanmatic AS
-000D2B Racal Instruments
-000D2C Patapsco Designs Ltd
-000D2D NCT Deutschland GmbH
-000D2E Matsushita Avionics Systems Corporation
-000D2F AIN Comm.Tech.Co., LTD
-000D30 IceFyre Semiconductor
-000D31 Compellent Technologies, Inc.
-000D32 DispenseSource, Inc.
-000D33 Prediwave Corp.
-000D34 Shell International Exploration and Production, Inc.
-000D35 PAC International Ltd
-000D36 Wu Han Routon Electronic Co., Ltd
-000D37 WIPLUG
-000D38 NISSIN INC.
-000D39 Network Electronics
-000D3A Microsoft Corp.
-000D3B Microelectronics Technology Inc.
-000D3C i.Tech Dynamic Ltd
-000D3E APLUX Communications Ltd.
-000D3F VXI Technology
-000D40 Verint Loronix Video Solutions
-000D41 Siemens AG ICM MP UC RD IT KLF1
-000D42 Newbest Development Limited
-000D43 DRS Tactical Systems Inc.
-000D45 Tottori SANYO Electric Co., Ltd.
-000D46 Eurotherm Drives, Ltd.
-000D47 Collex
-000D48 AEWIN Technologies Co., Ltd.
-000D49 Triton Systems of Delaware, Inc.
-000D4A Steag ETA-Optik
-000D4B Roku, LLC
-000D4C Outline Electronics Ltd.
-000D4D Ninelanes
-000D4E NDR Co.,LTD.
-000D4F Kenwood Corporation
-000D50 Galazar Networks
-000D51 DIVR Systems, Inc.
-000D52 Comart system
-000D53 Beijing 5w Communication Corp.
-000D54 3Com Europe Ltd
-000D55 SANYCOM Technology Co.,Ltd
-000D56 Dell PCBA Test
-000D57 Fujitsu I-Network Systems Limited.
-000D59 Amity Systems, Inc.
-000D5A Tiesse SpA
-000D5B Smart Empire Investments Limited
-000D5C Robert Bosch GmbH, VT-ATMO
-000D5D Raritan Computer, Inc
-000D5E NEC CustomTechnica, Ltd.
-000D5F Minds Inc
-000D60 IBM Corporation
-000D61 Giga-Byte Technology Co., Ltd.
-000D62 Funkwerk Dabendorf GmbH
-000D63 DENT Instruments, Inc.
-000D64 COMAG Handels AG
-000D65 Cisco Systems
-000D66 Cisco Systems
-000D67 BelAir Networks Inc.
-000D68 Vinci Systems, Inc.
-000D69 TMT&D Corporation
-000D6A Redwood Technologies LTD
-000D6B Mita-Teknik A/S
-000D6C M-Audio
-000D6D K-Tech Devices Corp.
-000D6E K-Patents Oy
-000D6F Ember Corporation
-000D70 Datamax Corporation
-000D71 boca systems
-000D72 2Wire, Inc
-000D73 Technical Support, Inc.
-000D74 Sand Network Systems, Inc.
-000D75 Kobian Pte Ltd - Taiwan Branch
-000D76 Hokuto Denshi Co,. Ltd.
-000D77 FalconStor Software
-000D78 Engineering & Security
-000D79 Dynamic Solutions Co,.Ltd.
-000D7A DiGATTO Asia Pacific Pte Ltd
-000D7B Consensys Computers Inc.
-000D7C Codian Ltd
-000D7D Afco Systems
-000D7E Axiowave Networks, Inc.
-000D7F MIDAS  COMMUNICATION TECHNOLOGIES PTE LTD ( Foreign Branch)
-000D80 Online Development Inc
-000D81 Pepperl+Fuchs GmbH
-000D82 PHS srl
-000D83 Sanmina-SCI Hungary  Ltd.
-000D84 Seodu Inchip, Inc.
-000D85 Tapwave, Inc.
-000D86 Huber + Suhner AG
-000D87 Elitegroup Computer System Co. (ECS)
-000D88 D-Link Corporation
-000D89 Bils Technology Inc
-000D8A Winners Electronics Co., Ltd.
-000D8B T&D Corporation
-000D8C Shanghai Wedone Digital Ltd. CO.
-000D8D ProLinx Communication Gateways, Inc.
-000D8E Koden Electronics Co., Ltd.
-000D8F King Tsushin Kogyo Co., LTD.
-000D90 Factum Electronics AB
-000D91 Eclipse (HQ Espana) S.L.
-000D92 Arima Communication Corporation
-000D93 Apple Computer
-000D94 AFAR Communications,Inc
-000D96 Vtera Technology Inc.
-000D97 Tropos Networks, Inc.
-000D98 S.W.A.C. Schmitt-Walter Automation Consult GmbH
-000D99 Orbital Sciences Corp.; Launch Systems Group
-000D9A INFOTEC LTD
-000D9C Elan GmbH & Co KG
-000D9D Hewlett Packard
-000D9E TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd.
-000D9F RF Micro Devices
-000DA0 NEDAP N.V.
-000DA1 MIRAE ITS Co.,LTD.
-000DA2 Infrant Technologies, Inc.
-000DA3 Emerging Technologies Limited
-000DA4 DOSCH & AMAND SYSTEMS AG
-000DA5 Fabric7 Systems, Inc
-000DA6 Universal Switching Corporation
-000DA8 Teletronics Technology Corporation
-000DA9 T.E.A.M. S.L.
-000DAA S.A.Tehnology co.,Ltd.
-000DAB Parker Hannifin GmbH Electromechanical Division Europe
-000DAC Japan CBM Corporation
-000DAD Dataprobe Inc
-000DAE SAMSUNG HEAVY INDUSTRIES CO., LTD.
-000DAF Plexus Corp (UK) Ltd
-000DB0 Olym-tech Co.,Ltd.
-000DB1 Japan Network Service Co., Ltd.
-000DB2 Ammasso, Inc.
-000DB3 SDO Communication Corperation
-000DB4 NETASQ
-000DB5 GLOBALSAT TECHNOLOGY CORPORATION
-000DB6 Teknovus, Inc.
-000DB7 SANKO ELECTRIC CO,.LTD
-000DB8 SCHILLER AG
-000DB9 PC Engines GmbH
-000DBA Océ Document Technologies GmbH
-000DBB Nippon Dentsu Co.,Ltd.
-000DBC Cisco Systems
-000DBD Cisco Systems
-000DBE Bel Fuse Europe Ltd.,UK
-000DBF TekTone Sound & Signal Mfg., Inc.
-000DC0 Spagat AS
-000DC1 SafeWeb Inc
-000DC3 First Communication, Inc.
-000DC4 Emcore Corporation
-000DC5 EchoStar International Corporation
-000DC6 DigiRose Technology Co., Ltd.
-000DC7 COSMIC ENGINEERING INC.
-000DC8 AirMagnet, Inc
-000DC9 THALES Elektronik Systeme GmbH
-000DCA Tait Electronics
-000DCB Petcomkorea Co., Ltd.
-000DCC NEOSMART Corp.
-000DCD GROUPE TXCOM
-000DCE Dynavac Technology Pte Ltd
-000DCF Cidra Corp.
-000DD0 TetraTec Instruments GmbH
-000DD1 Stryker Corporation
-000DD2 Simrad Optronics ASA
-000DD3 SAMWOO Telecommunication Co.,Ltd.
-000DD4 Revivio Inc.
-000DD5 O'RITE TECHNOLOGY CO.,LTD
-000DD7 Bright
-000DD8 BBN
-000DD9 Anton Paar GmbH
-000DDA ALLIED TELESIS K.K.
-000DDB AIRWAVE TECHNOLOGIES INC.
-000DDC VAC
-000DDD PROFÝLO TELRA ELEKTRONÝK SANAYÝ VE TÝCARET A.Þ.
-000DDE Joyteck Co., Ltd.
-000DDF Japan Image & Network Inc.
-000DE0 ICPDAS Co.,LTD
-000DE1 Control Products, Inc.
-000DE2 CMZ Sistemi Elettronici
-000DE3 AT Sweden AB
-000DE4 DIGINICS, Inc.
-000DE5 Samsung Thales
-000DE6 YOUNGBO ENGINEERING CO.,LTD
-000DE7 Snap-on OEM Group
-000DE8 Nasaco Electronics Pte. Ltd
-000DE9 Napatech Aps
-000DEA Kingtel Telecommunication Corp.
-000DEB CompXs Limited
-000DEC Cisco Systems
-000DED Cisco Systems
-000DEF Soc. Coop. Bilanciai
-000DF0 QCOM TECHNOLOGY INC.
-000DF1 IONIX INC.
-000DF3 Asmax Solutions
-000DF4 Watertek Co.
-000DF5 Teletronics International Inc.
-000DF6 Technology Thesaurus Corp.
-000DF7 Space Dynamics Lab
-000DF8 ORGA Kartensysteme GmbH
-000DF9 NDS Limited
-000DFA Micro Control Systems Ltd.
-000DFB Komax AG
-000DFC ITFOR Inc. resarch and development
-000DFD Huges Hi-Tech Inc.,
-000DFE Hauppauge Computer Works, Inc.
-000DFF CHENMING MOLD INDUSTRY CORP.
-000E01 ASIP Technologies Inc.
-000E02 Advantech AMT Inc.
-000E03 Aarohi Communications, Inc.
-000E05 WIRELESS MATRIX CORP.
-000E06 Team Simoco Ltd
-000E07 Sony Ericsson Mobile Communications AB
-000E08 Sipura Technology, Inc.
-000E09 Shenzhen Coship Software Co.,LTD.
-000E0B Netac Technology Co., Ltd.
-000E0C Intel Corporation
-000E0D HESCH Schröder GmbH
-000E0E ESA elettronica S.P.A.
-000E0F ERMME
-000E11 BDT Büro- und Datentechnik GmbH & Co. KG
-000E12 Adaptive Micro Systems Inc.
-000E13 Accu-Sort Systems inc.
-000E14 Visionary Solutions, Inc.
-000E15 Tadlys LTD
-000E16 SouthWing
-000E18 MyA Technology
-000E19 LogicaCMG Pty Ltd
-000E1B IAV GmbH
-000E1C Hach Company
-000E1F TCL Networks Equipment Co., Ltd.
-000E20 PalmSource, Inc.
-000E21 MTU Friedrichshafen GmbH
-000E23 Incipient, Inc.
-000E25 Hannae Technology Co., Ltd
-000E26 Gincom Technology Corp.
-000E27 Crere Networks, Inc.
-000E28 Dynamic Ratings P/L
-000E29 Shester Communications Inc
-000E2B Safari Technologies
-000E2C Netcodec co.
-000E2D Hyundai Digital Technology Co.,Ltd.
-000E2E Edimax Technology Co., Ltd.
-000E2F Disetronic Medical Systems AG
-000E30 AERAS Networks, Inc.
-000E31 Olympus BioSystems GmbH
-000E32 Kontron Medical
-000E33 Shuko Electronics Co.,Ltd
-000E34 NexxGenCity
-000E35 Intel Corp
-000E36 HEINESYS, Inc.
-000E37 Harms & Wende GmbH & Co.KG
-000E38 Cisco Systems
-000E39 Cisco Systems
-000E3A Cirrus Logic
-000E3B Hawking Technologies, Inc.
-000E3C TransAct Technoloiges Inc.
-000E3D Televic N.V.
-000E3E Sun Optronics Inc
-000E3F Soronti, Inc.
-000E40 Nortel Networks
-000E41 NIHON MECHATRONICS CO.,LTD.
-000E42 Motic Incoporation Ltd.
-000E43 G-Tek Electronics Sdn. Bhd.
-000E44 Digital 5, Inc.
-000E45 Beijing Newtry Electronic Technology Ltd
-000E46 Niigata Seimitsu Co.,Ltd.
-000E47 NCI System Co.,Ltd.
-000E48 Lipman TransAction Solutions
-000E49 Forsway Scandinavia AB
-000E4A Changchun Huayu WEBPAD Co.,LTD
-000E4B atrium c and i
-000E4C Bermai Inc.
-000E4D Numesa Inc.
-000E4E Waveplus Technology Co., Ltd.
-000E4F Trajet GmbH
-000E50 Thomson Multi Media
-000E51 tecna elettronica srl
-000E52 Optium Corporation
-000E53 AV TECH CORPORATION
-000E54 AlphaCell Wireless Ltd.
-000E55 AUVITRAN
-000E56 4G Systems GmbH
-000E57 Iworld Networking, Inc.
-000E58 Rincon Networks
-000E5A TELEFIELD inc.
-000E5B ParkerVision - Direct2Data
-000E5C Motorola BCS
-000E5D Com-X Networks
-000E5E Beijing Raisecom Science & Technology Development Co.,Ltd
-000E5F activ-net GmbH & Co. KG
-000E60 360SUN Digital Broadband Corporation
-000E61 MICROTROL LIMITED
-000E62 Nortel Networks
-000E63 Lemke Diagnostics GmbH
-000E64 Elphel, Inc
-000E65 TransCore
-000E66 Hitachi Advanced Digital, Inc.
-000E67 Eltis Microelectronics Ltd.
-000E68 E-TOP Network Technology Inc.
-000E69 China Electric Power Research Institute
-000E6A 3COM EUROPE LTD
-000E6B Janitza electronics GmbH
-000E6C Device Drivers Limited
-000E6D Murata Manufacturing Co., Ltd.
-000E6E MICRELEC  ELECTRONICS S.A
-000E6F IRIS Corporation Berhad
-000E70 in2 Networks
-000E71 Gemstar Technology Development Ltd.
-000E72 CTS electronics
-000E73 Tpack A/S
-000E74 Solar Telecom. Tech
-000E75 New York Air Brake Corp.
-000E76 GEMSOC INNOVISION INC.
-000E77 Decru, Inc.
-000E78 Amtelco
-000E79 Ample Communications Inc.
-000E7B Toshiba
-000E7D Electronics Line 3000 Ltd.
-000E7E Comprog Oy
-000E7F Hewlett Packard
-000E81 Instant802 Networks Inc.
-000E82 Commtech Wireless
-000E83 Cisco Systems
-000E84 Cisco Systems
-000E85 Catalyst Enterprises, Inc.
-000E86 Alcatel North America
-000E87 adp Gauselmann GmbH
-000E88 VIDEOTRON CORP.
-000E89 CLEMATIC
-000E8A Avara Technologies Pty. Ltd.
-000E8B Astarte Technology Co, Ltd.
-000E8C Siemens AG A&D ET
-000E8D Systems in Progress Holding GmbH
-000E8E SparkLAN Communications, Inc.
-000E8F Sercomm Corp.
-000E90 PONICO CORP.
-000E92 Millinet Co., Ltd.
-000E93 Milénio 3 Sistemas Electrónicos, Lda.
-000E94 Maas International BV
-000E95 Fujiya Denki Seisakusho Co.,Ltd.
-000E96 Cubic Defense Applications, Inc.
-000E97 Ultracker Technology CO., Inc
-000E98 Vitec CC, INC.
-000E99 Spectrum Digital, Inc
-000E9A BOE TECHNOLOGY GROUP CO.,LTD
-000E9C Pemstar
-000E9D Video Networks Ltd
-000E9E Topfield Co., Ltd
-000E9F TEMIC SDS GmbH
-000EA0 NetKlass Technology Inc.
-000EA1 Formosa Teletek Corporation
-000EA2 CyberGuard Corporation
-000EA3 CNCR-IT CO.,LTD,HangZhou P.R.CHINA
-000EA4 Certance Inc.
-000EA5 BLIP Systems
-000EA6 ASUSTEK COMPUTER INC.
-000EA7 Endace Inc Ltd.
-000EA8 United Technologists Europe Limited
-000EA9 Shanghai Xun Shi Communications Equipment Ltd. Co.
-000EAC MINTRON ENTERPRISE CO., LTD.
-000EAD Metanoia Technologies, Inc.
-000EAE GAWELL TECHNOLOGIES CORP.
-000EAF CASTEL
-000EB0 Solutions Radio BV
-000EB1 Newcotech,Ltd
-000EB2 Micro-Research Finland Oy
-000EB3 LeftHand Networks
-000EB4 GUANGZHOU GAOKE COMMUNICATIONS TECHNOLOGY CO.LTD.
-000EB5 Ecastle Electronics Co., Ltd.
-000EB6 Riverbed Technology, Inc.
-000EB7 Knovative, Inc.
-000EB8 Iiga co.,Ltd
-000EB9 HASHIMOTO Electronics Industry Co.,Ltd.
-000EBA HANMI SEMICONDUCTOR CO., LTD.
-000EBB Everbee Networks
-000EBC Cullmann GmbH
-000EBD Burdick, a Quinton Compny
-000EBE B&B Electronics Manufacturing Co.
-000EC0 Nortel Networks
-000EC1 MYNAH Technologies
-000EC2 Lowrance Electronics, Inc.
-000EC3 Logic Controls, Inc.
-000EC4 Iskra Transmission d.d.
-000EC6 ASIX ELECTRONICS CORP.
-000EC7 Appeal Telecom Co.,Ltd.
-000EC8 Zoran Corporation
-000EC9 YOKO Technology Corp.
-000ECB VineSys Technology
-000ECC Tableau
-000ECD SKOV A/S
-000ECE S.I.T.T.I. S.p.A.
-000ECF PROFIBUS Nutzerorganisation e.V.
-000ED0 Privaris, Inc.
-000ED1 Osaka Micro Computer.
-000ED2 Filtronic plc
-000ED3 Epicenter, Inc.
-000ED4 CRESITT INDUSTRIE
-000ED5 COPAN Systems Inc.
-000ED6 Cisco Systems
-000ED7 Cisco Systems
-000ED8 Aktino, Inc.
-000ED9 Aksys, Ltd.
-000EDA C-TECH UNITED CORP.
-000EDB XiNCOM Corp.
-000EDC Tellion INC.
-000EDD SHURE INCORPORATED
-000EDE REMEC, Inc.
-000EDF PLX Technology
-000EE0 Mcharge
-000EE1 ExtremeSpeed Inc.
-000EE2 Custom Engineering S.p.A.
-000EE3 Chiyu Technology Co.,Ltd
-000EE5 bitWallet, Inc.
-000EE6 Adimos Systems LTD
-000EE7 AAC ELECTRONICS CORP.
-000EE8 zioncom
-000EE9 WayTech Development, Inc.
-000EEA Shadong Luneng Jicheng Electronics,Co.,Ltd
-000EEB Sandmartin(zhong shan)Electronics Co.,Ltd
-000EEC Orban
-000EED Nokia Danmark A/S
-000EEE Muco Industrie BV
-000EF0 Festo AG & Co. KG
-000EF1 EZQUEST INC.
-000EF3 Smarthome
-000EF4 Shenzhen Kasda Digital Technology Co.,Ltd
-000EF5 iPAC Technology Co., Ltd.
-000EF6 E-TEN Information Systems Co., Ltd.
-000EF7 Vulcan Portals Inc
-000EF8 SBC ASI
-000EF9 REA Elektronik GmbH
-000EFA Optoway Technology Incorporation
-000EFB Macey Enterprises
-000EFC JTAG Technologies B.V.
-000EFD FUJI PHOTO OPTICAL CO., LTD.
-000EFE EndRun Technologies LLC
-000EFF Megasolution,Inc.
-000F00 Legra Systems, Inc.
-000F01 DIGITALKS INC
-000F02 Digicube Technology Co., Ltd
-000F03 COM&C CO., LTD
-000F04 cim-usa inc
-000F05 3B SYSTEM INC.
-000F06 Nortel Networks
-000F07 Mangrove Systems, Inc.
-000F08 Indagon Oy
-000F0B Kentima Technologies AB
-000F0C SYNCHRONIC ENGINEERING
-000F0D Hunt Electronic Co., Ltd.
-000F0E WaveSplitter Technologies, Inc.
-000F0F Real ID Technology Co., Ltd.
-000F10 RDM Corporation
-000F11 Prodrive B.V.
-000F12 Panasonic AVC Networks Germany GmbH
-000F13 Nisca corporation
-000F14 Mindray Co., Ltd.
-000F15 Kjaerulff1 A/S
-000F16 JAY HOW TECHNOLOGY CO.,
-000F17 Insta Elektro GmbH
-000F18 Industrial Control Systems
-000F19 Guidant Corporation
-000F1A Gaming Support B.V.
-000F1B Ego Systems Inc.
-000F1C DigitAll World Co., Ltd
-000F1D Cosmo Techs Co., Ltd.
-000F1E Chengdu KT Electric Co.of High & New Technology
-000F1F WW PCBA Test
-000F20 WW Ops
-000F21 Scientific Atlanta, Inc
-000F22 Helius, Inc.
-000F23 Cisco Systems
-000F24 Cisco Systems
-000F25 AimValley B.V.
-000F26 WorldAccxx  LLC
-000F27 TEAL Electronics, Inc.
-000F28 Itronix Corporation
-000F29 Augmentix Corporation
-000F2A Cableware Electronics
-000F2B GREENBELL SYSTEMS
-000F2C Uplogix, Inc.
-001000 CABLE TELEVISION LABORATORIES, INC.
-001001 MCK COMMUNICATIONS
-001002 ACTIA
-001003 IMATRON, INC.
-001004 THE BRANTLEY COILE COMPANY,INC
-001005 UEC COMMERCIAL
-001006 Thales Contact Solutions Ltd.
-001007 CISCO SYSTEMS, INC.
-001008 VIENNA SYSTEMS CORPORATION
-001009 HORO QUARTZ
-00100A WILLIAMS COMMUNICATIONS GROUP
-00100B CISCO SYSTEMS, INC.
-00100C ITO CO., LTD.
-00100D CISCO SYSTEMS, INC.
-00100E MICRO LINEAR COPORATION
-00100F INDUSTRIAL CPU SYSTEMS
-001010 INITIO CORPORATION
-001011 CISCO SYSTEMS, INC.
-001012 PROCESSOR SYSTEMS (I) PVT LTD
-001013 INDUSTRIAL COMPUTER SOURCE
-001014 CISCO SYSTEMS, INC.
-001015 OOmon Inc.
-001016 T.SQWARE
-001017 MICOS GmbH
-001018 BROADCOM CORPORATION
-001019 SIRONA DENTAL SYSTEMS GmbH & Co. KG
-00101A PictureTel Corp.
-00101B CORNET TECHNOLOGY, INC.
-00101C OHM TECHNOLOGIES INTL, LLC
-00101D WINBOND ELECTRONICS CORP.
-00101E MATSUSHITA ELECTRONIC INSTRUMENTS CORP.
-00101F CISCO SYSTEMS, INC.
-001020 WELCH ALLYN, DATA COLLECTION
-001021 ENCANTO NETWORKS, INC.
-001022 SatCom Media Corporation
-001023 FLOWWISE NETWORKS, INC.
-001024 NAGOYA ELECTRIC WORKS CO., LTD
-001025 GRAYHILL INC.
-001026 ACCELERATED NETWORKS, INC.
-001027 L-3 COMMUNICATIONS EAST
-001028 COMPUTER TECHNICA, INC.
-001029 CISCO SYSTEMS, INC.
-00102A ZF MICROSYSTEMS, INC.
-00102B UMAX DATA SYSTEMS, INC.
-00102C Lasat Networks A/S
-00102D HITACHI SOFTWARE ENGINEERING
-00102E NETWORK SYSTEMS & TECHNOLOGIES PVT. LTD.
-00102F CISCO SYSTEMS, INC.
-001030 Wi-LAN, Inc.
-001031 OBJECTIVE COMMUNICATIONS, INC.
-001032 ALTA TECHNOLOGY
-001033 ACCESSLAN COMMUNICATIONS, INC.
-001034 GNP Computers
-001035 ELITEGROUP COMPUTER SYSTEMS CO., LTD
-001036 INTER-TEL INTEGRATED SYSTEMS
-001037 CYQ've Technology Co., Ltd.
-001038 MICRO RESEARCH INSTITUTE, INC.
-001039 Vectron Systems AG
-00103A DIAMOND NETWORK TECH
-00103B HIPPI NETWORKING FORUM
-00103C IC ENSEMBLE, INC.
-00103D PHASECOM, LTD.
-00103E NETSCHOOLS CORPORATION
-00103F TOLLGRADE COMMUNICATIONS, INC.
-001040 INTERMEC CORPORATION
-001041 BRISTOL BABCOCK, INC.
-001042 AlacriTech
-001043 A2 CORPORATION
-001044 InnoLabs Corporation
-001045 Nortel Networks
-001046 ALCORN MCBRIDE INC.
-001047 ECHO ELETRIC CO. LTD.
-001048 HTRC AUTOMATION, INC.
-001049 SHORELINE TELEWORKS, INC.
-00104A THE PARVUC CORPORATION
-00104B 3COM CORPORATION
-00104C COMPUTER ACCESS TECHNOLOGY
-00104D SURTEC INDUSTRIES, INC.
-00104E CEOLOGIC
-00104F STORAGE TECHNOLOGY CORPORATION
-001050 RION CO., LTD.
-001051 CMICRO CORPORATION
-001052 METTLER-TOLEDO (ALBSTADT) GMBH
-001053 COMPUTER TECHNOLOGY CORP.
-001054 CISCO SYSTEMS, INC.
-001055 FUJITSU MICROELECTRONICS, INC.
-001056 SODICK CO., LTD.
-001057 Rebel.com, Inc.
-001058 ArrowPoint Communications
-001059 DIABLO RESEARCH CO. LLC
-00105A 3COM CORPORATION
-00105B NET INSIGHT AB
-00105C QUANTUM DESIGNS (H.K.) LTD.
-00105D Draeger Medical
-00105E HEKIMIAN LABORATORIES, INC.
-00105F IN-SNEC
-001060 BILLIONTON SYSTEMS, INC.
-001061 HOSTLINK CORP.
-001062 NX SERVER, ILNC.
-001063 STARGUIDE DIGITAL NETWORKS
-001064 DIGITAL EQUIPMENT CORP.
-001065 RADYNE CORPORATION
-001066 ADVANCED CONTROL SYSTEMS, INC.
-001067 REDBACK NETWORKS, INC.
-001068 COMOS TELECOM
-001069 HELIOSS COMMUNICATIONS, INC.
-00106A DIGITAL MICROWAVE CORPORATION
-00106B SONUS NETWORKS, INC.
-00106C INFRATEC PLUS GmbH
-00106D INTEGRITY COMMUNICATIONS, INC.
-00106E TADIRAN COM. LTD.
-00106F TRENTON TECHNOLOGY INC.
-001070 CARADON TREND LTD.
-001071 ADVANET INC.
-001072 GVN TECHNOLOGIES, INC.
-001073 TECHNOBOX, INC.
-001074 ATEN INTERNATIONAL CO., LTD.
-001075 Maxtor Corporation
-001076 EUREM GmbH
-001077 SAF DRIVE SYSTEMS, LTD.
-001078 NUERA COMMUNICATIONS, INC.
-001079 CISCO SYSTEMS, INC.
-00107A AmbiCom, Inc.
-00107B CISCO SYSTEMS, INC.
-00107C P-COM, INC.
-00107D AURORA COMMUNICATIONS, LTD.
-00107E BACHMANN ELECTRONIC GmbH
-00107F CRESTRON ELECTRONICS, INC.
-001080 METAWAVE COMMUNICATIONS
-001081 DPS, INC.
-001082 JNA TELECOMMUNICATIONS LIMITED
-001083 HEWLETT-PACKARD COMPANY
-001084 K-BOT COMMUNICATIONS
-001085 POLARIS COMMUNICATIONS, INC.
-001086 ATTO TECHNOLOGY, INC.
-001087 Xstreamis PLC
-001088 AMERICAN NETWORKS INC.
-001089 WebSonic
-00108A TeraLogic, Inc.
-00108B LASERANIMATION SOLLINGER GmbH
-00108C FUJITSU TELECOMMUNICATIONS EUROPE, LTD.
-00108D JOHNSON CONTROLS, INC.
-00108E HUGH SYMONS CONCEPT Technologies Ltd.
-00108F RAPTOR SYSTEMS
-001090 CIMETRICS, INC.
-001091 NO WIRES NEEDED BV
-001092 NETCORE INC.
-001093 CMS COMPUTERS, LTD.
-001094 Performance Analysis Broadband, Spirent plc
-001095 Thomson Multimedia, Inc.
-001096 TRACEWELL SYSTEMS, INC.
-001097 WinNet Metropolitan Communications Systems, Inc.
-001098 STARNET TECHNOLOGIES, INC.
-001099 InnoMedia, Inc.
-00109A NETLINE
-00109B VIXEL CORPORATION
-00109C M-SYSTEM CO., LTD.
-00109D CLARINET SYSTEMS, INC.
-00109E AWARE, INC.
-00109F PAVO, INC.
-0010A0 INNOVEX TECHNOLOGIES, INC.
-0010A1 KENDIN SEMICONDUCTOR, INC.
-0010A2 TNS
-0010A3 OMNITRONIX, INC.
-0010A4 XIRCOM
-0010A5 OXFORD INSTRUMENTS
-0010A6 CISCO SYSTEMS, INC.
-0010A7 UNEX TECHNOLOGY CORPORATION
-0010A8 RELIANCE COMPUTER CORP.
-0010A9 ADHOC TECHNOLOGIES
-0010AA MEDIA4, INC.
-0010AB KOITO INDUSTRIES, LTD.
-0010AC IMCI TECHNOLOGIES
-0010AD SOFTRONICS USB, INC.
-0010AE SHINKO ELECTRIC INDUSTRIES CO.
-0010AF TAC SYSTEMS, INC.
-0010B0 MERIDIAN TECHNOLOGY CORP.
-0010B1 FOR-A CO., LTD.
-0010B2 COACTIVE AESTHETICS
-0010B3 NOKIA MULTIMEDIA TERMINALS
-0010B4 ATMOSPHERE NETWORKS
-0010B5 ACCTON TECHNOLOGY CORPORATION
-0010B6 ENTRATA COMMUNICATIONS CORP.
-0010B7 COYOTE TECHNOLOGIES, LLC
-0010B8 ISHIGAKI COMPUTER SYSTEM CO.
-0010B9 MAXTOR CORP.
-0010BA MARTINHO-DAVIS SYSTEMS, INC.
-0010BB DATA & INFORMATION TECHNOLOGY
-0010BC Aastra Telecom
-0010BD THE TELECOMMUNICATION TECHNOLOGY COMMITTEE
-0010BE TELEXIS CORP.
-0010BF InterAir Wireless
-0010C0 ARMA, INC.
-0010C1 OI ELECTRIC CO., LTD.
-0010C2 WILLNET, INC.
-0010C3 CSI-CONTROL SYSTEMS
-0010C4 MEDIA LINKS CO., LTD.
-0010C5 PROTOCOL TECHNOLOGIES, INC.
-0010C6 USI
-0010C7 DATA TRANSMISSION NETWORK
-0010C8 COMMUNICATIONS ELECTRONICS SECURITY GROUP
-0010C9 MITSUBISHI ELECTRONICS LOGISTIC SUPPORT CO.
-0010CA INTEGRAL ACCESS
-0010CB FACIT K.K.
-0010CC CLP COMPUTER LOGISTIK PLANUNG GmbH
-0010CD INTERFACE CONCEPT
-0010CE VOLAMP, LTD.
-0010CF FIBERLANE COMMUNICATIONS
-0010D0 WITCOM, LTD.
-0010D1 Top Layer Networks, Inc.
-0010D2 NITTO TSUSHINKI CO., LTD
-0010D3 GRIPS ELECTRONIC GMBH
-0010D4 STORAGE COMPUTER CORPORATION
-0010D5 IMASDE CANARIAS, S.A.
-0010D6 ITT - A/CD
-0010D7 ARGOSY RESEARCH INC.
-0010D8 CALISTA
-0010D9 IBM JAPAN, FUJISAWA MT+D
-0010DA MOTION ENGINEERING, INC.
-0010DB NetScreen Technologies, Inc.
-0010DC MICRO-STAR INTERNATIONAL CO., LTD.
-0010DD ENABLE SEMICONDUCTOR, INC.
-0010DE INTERNATIONAL DATACASTING CORPORATION
-0010DF RISE COMPUTER INC.
-0010E0 COBALT MICROSERVER, INC.
-0010E1 S.I. TECH, INC.
-0010E2 ArrayComm, Inc.
-0010E3 COMPAQ COMPUTER CORPORATION
-0010E4 NSI CORPORATION
-0010E5 SOLECTRON TEXAS
-0010E6 APPLIED INTELLIGENT SYSTEMS, INC.
-0010E7 BreezeCom
-0010E8 TELOCITY, INCORPORATED
-0010E9 RAIDTEC LTD.
-0010EA ADEPT TECHNOLOGY
-0010EB SELSIUS SYSTEMS, INC.
-0010EC RPCG, LLC
-0010ED SUNDANCE TECHNOLOGY, INC.
-0010EE CTI PRODUCTS, INC.
-0010EF DBTEL INCORPORATED
-0010F1 I-O CORPORATION
-0010F2 ANTEC
-0010F3 Nexcom International Co., Ltd.
-0010F4 VERTICAL NETWORKS, INC.
-0010F5 AMHERST SYSTEMS, INC.
-0010F6 CISCO SYSTEMS, INC.
-0010F7 IRIICHI TECHNOLOGIES Inc.
-0010F8 KENWOOD TMI CORPORATION
-0010F9 UNIQUE SYSTEMS, INC.
-0010FA ZAYANTE, INC.
-0010FB ZIDA TECHNOLOGIES LIMITED
-0010FC BROADBAND NETWORKS, INC.
-0010FD COCOM A/S
-0010FE DIGITAL EQUIPMENT CORPORATION
-0010FF CISCO SYSTEMS, INC.
-001C7C PERQ SYSTEMS CORPORATION
-002000 LEXMARK INTERNATIONAL, INC.
-002001 DSP SOLUTIONS, INC.
-002002 SERITECH ENTERPRISE CO., LTD.
-002003 PIXEL POWER LTD.
-002004 YAMATAKE-HONEYWELL CO., LTD.
-002005 SIMPLE TECHNOLOGY
-002006 GARRETT COMMUNICATIONS, INC.
-002007 SFA, INC.
-002008 CABLE & COMPUTER TECHNOLOGY
-002009 PACKARD BELL ELEC., INC.
-00200A SOURCE-COMM CORP.
-00200B OCTAGON SYSTEMS CORP.
-00200C ADASTRA SYSTEMS CORP.
-00200D CARL ZEISS
-00200E SATELLITE TECHNOLOGY MGMT, INC
-00200F TANBAC CO., LTD.
-002010 JEOL SYSTEM TECHNOLOGY CO. LTD
-002011 CANOPUS CO., LTD.
-002012 CAMTRONICS MEDICAL SYSTEMS
-002013 DIVERSIFIED TECHNOLOGY, INC.
-002014 GLOBAL VIEW CO., LTD.
-002015 ACTIS COMPUTER SA
-002016 SHOWA ELECTRIC WIRE & CABLE CO
-002017 ORBOTECH
-002018 CIS TECHNOLOGY INC.
-002019 OHLER GmbH
-00201A N-BASE SWITCH COMMUNICATIONS
-00201B NORTHERN TELECOM/NETWORK
-00201C EXCEL, INC.
-00201D KATANA PRODUCTS
-00201E NETQUEST CORPORATION
-00201F BEST POWER TECHNOLOGY, INC.
-002020 MEGATRON COMPUTER INDUSTRIES PTY, LTD.
-002021 ALGORITHMS SOFTWARE PVT. LTD.
-002022 TEKNIQUE, INC.
-002023 T.C. TECHNOLOGIES PTY. LTD
-002024 PACIFIC COMMUNICATION SCIENCES
-002025 CONTROL TECHNOLOGY, INC.
-002026 AMKLY SYSTEMS, INC.
-002027 MING FORTUNE INDUSTRY CO., LTD
-002028 WEST EGG SYSTEMS, INC.
-002029 TELEPROCESSING PRODUCTS, INC.
-00202A N.V. DZINE
-00202B ADVANCED TELECOMMUNICATIONS MODULES, LTD.
-00202C WELLTRONIX CO., LTD.
-00202D TAIYO CORPORATION
-00202E DAYSTAR DIGITAL
-00202F ZETA COMMUNICATIONS, LTD.
-002030 ANALOG & DIGITAL SYSTEMS
-002031 ERTEC GmbH
-002032 ALCATEL TAISEL
-002033 SYNAPSE TECHNOLOGIES, INC.
-002034 ROTEC INDUSTRIEAUTOMATION GMBH
-002035 IBM CORPORATION
-002036 BMC SOFTWARE
-002037 SEAGATE TECHNOLOGY
-002038 VME MICROSYSTEMS INTERNATIONAL CORPORATION
-002039 SCINETS
-00203A DIGITAL BI0METRICS INC.
-00203B WISDM LTD.
-00203C EUROTIME AB
-00203D NOVAR ELECTRONICS CORPORATION
-00203E LogiCan Technologies, Inc.
-00203F JUKI CORPORATION
-002040 Motorola Broadband Communications Sector
-002041 DATA NET
-002042 DATAMETRICS CORP.
-002043 NEURON COMPANY LIMITED
-002044 GENITECH PTY LTD
-002045 ION Networks, Inc.
-002046 CIPRICO, INC.
-002047 STEINBRECHER CORP.
-002048 Marconi Communications
-002049 COMTRON, INC.
-00204A PRONET GMBH
-00204B AUTOCOMPUTER CO., LTD.
-00204C MITRON COMPUTER PTE LTD.
-00204D INOVIS GMBH
-00204E NETWORK SECURITY SYSTEMS, INC.
-00204F DEUTSCHE AEROSPACE AG
-002050 KOREA COMPUTER INC.
-002051 Verilink Corporation
-002052 RAGULA SYSTEMS
-002053 HUNTSVILLE MICROSYSTEMS, INC.
-002054 EASTERN RESEARCH, INC.
-002055 ALTECH CO., LTD.
-002056 NEOPRODUCTS
-002057 TITZE DATENTECHNIK GmbH
-002058 ALLIED SIGNAL INC.
-002059 MIRO COMPUTER PRODUCTS AG
-00205A COMPUTER IDENTICS
-00205B SKYLINE TECHNOLOGY
-00205C InterNet Systems of Florida, Inc.
-00205D NANOMATIC OY
-00205E CASTLE ROCK, INC.
-00205F GAMMADATA COMPUTER GMBH
-002060 ALCATEL ITALIA S.p.A.
-002061 DYNATECH COMMUNICATIONS, INC.
-002062 SCORPION LOGIC, LTD.
-002063 WIPRO INFOTECH LTD.
-002064 PROTEC MICROSYSTEMS, INC.
-002065 SUPERNET NETWORKING INC.
-002066 GENERAL MAGIC, INC.
-002068 ISDYNE
-002069 ISDN SYSTEMS CORPORATION
-00206A OSAKA COMPUTER CORP.
-00206B KONICA MINOLTA HOLDINGS, INC.
-00206C EVERGREEN TECHNOLOGY CORP.
-00206D DATA RACE, INC.
-00206E XACT, INC.
-00206F FLOWPOINT CORPORATION
-002070 HYNET, LTD.
-002071 IBR GMBH
-002072 WORKLINK INNOVATIONS
-002073 FUSION SYSTEMS CORPORATION
-002074 SUNGWOON SYSTEMS
-002075 MOTOROLA COMMUNICATION ISRAEL
-002076 REUDO CORPORATION
-002077 KARDIOS SYSTEMS CORP.
-002078 RUNTOP, INC.
-002079 MIKRON GMBH
-00207A WiSE Communications, Inc.
-00207B Intel Corporation
-00207C AUTEC GmbH
-00207D ADVANCED COMPUTER APPLICATIONS
-00207E FINECOM Co., Ltd.
-00207F KYOEI SANGYO CO., LTD.
-002080 SYNERGY (UK) LTD.
-002081 TITAN ELECTRONICS
-002082 ONEAC CORPORATION
-002083 PRESTICOM INCORPORATED
-002084 OCE PRINTING SYSTEMS, GMBH
-002085 EXIDE ELECTRONICS
-002086 MICROTECH ELECTRONICS LIMITED
-002087 MEMOTEC COMMUNICATIONS CORP.
-002088 GLOBAL VILLAGE COMMUNICATION
-002089 T3PLUS NETWORKING, INC.
-00208A SONIX COMMUNICATIONS, LTD.
-00208B LAPIS TECHNOLOGIES, INC.
-00208C GALAXY NETWORKS, INC.
-00208D CMD TECHNOLOGY
-00208E CHEVIN SOFTWARE ENG. LTD.
-00208F ECI TELECOM LTD.
-002090 ADVANCED COMPRESSION TECHNOLOGY, INC.
-002091 J125, NATIONAL SECURITY AGENCY
-002092 CHESS ENGINEERING B.V.
-002093 LANDINGS TECHNOLOGY CORP.
-002094 CUBIX CORPORATION
-002095 RIVA ELECTRONICS
-002096 Invensys
-002097 APPLIED SIGNAL TECHNOLOGY
-002098 HECTRONIC AB
-002099 BON ELECTRIC CO., LTD.
-00209A THE 3DO COMPANY
-00209B ERSAT ELECTRONIC GMBH
-00209C PRIMARY ACCESS CORP.
-00209D LIPPERT AUTOMATIONSTECHNIK
-00209E BROWN'S OPERATING SYSTEM SERVICES, LTD.
-00209F MERCURY COMPUTER SYSTEMS, INC.
-0020A0 OA LABORATORY CO., LTD.
-0020A1 DOVATRON
-0020A2 GALCOM NETWORKING LTD.
-0020A3 DIVICOM INC.
-0020A4 MULTIPOINT NETWORKS
-0020A5 API ENGINEERING
-0020A6 PROXIM, INC.
-0020A7 PAIRGAIN TECHNOLOGIES, INC.
-0020A8 SAST TECHNOLOGY CORP.
-0020A9 WHITE HORSE INDUSTRIAL
-0020AA DIGIMEDIA VISION LTD.
-0020AB MICRO INDUSTRIES CORP.
-0020AC INTERFLEX DATENSYSTEME GMBH
-0020AD LINQ SYSTEMS
-0020AE ORNET DATA COMMUNICATION TECH.
-0020AF 3COM CORPORATION
-0020B0 GATEWAY DEVICES, INC.
-0020B1 COMTECH RESEARCH INC.
-0020B2 GKD Gesellschaft Fur Kommunikation Und Datentechnik
-0020B3 SCLTEC COMMUNICATIONS SYSTEMS
-0020B4 TERMA ELEKTRONIK AS
-0020B5 YASKAWA ELECTRIC CORPORATION
-0020B6 AGILE NETWORKS, INC.
-0020B7 NAMAQUA COMPUTERWARE
-0020B8 PRIME OPTION, INC.
-0020B9 METRICOM, INC.
-0020BA CENTER FOR HIGH PERFORMANCE
-0020BB ZAX CORPORATION
-0020BC JTEC PTY LTD.
-0020BD NIOBRARA R & D CORPORATION
-0020BE LAN ACCESS CORP.
-0020BF AEHR TEST SYSTEMS
-0020C0 PULSE ELECTRONICS, INC.
-0020C1 TAIKO ELECTRIC WORKS, LTD.
-0020C2 TEXAS MEMORY SYSTEMS, INC.
-0020C3 COUNTER SOLUTIONS LTD.
-0020C4 INET,INC.
-0020C5 EAGLE TECHNOLOGY
-0020C6 NECTEC
-0020C7 AKAI Professional M.I. Corp.
-0020C8 LARSCOM INCORPORATED
-0020C9 VICTRON BV
-0020CA DIGITAL OCEAN
-0020CB PRETEC ELECTRONICS CORP.
-0020CC DIGITAL SERVICES, LTD.
-0020CD HYBRID NETWORKS, INC.
-0020CE LOGICAL DESIGN GROUP, INC.
-0020CF TEST & MEASUREMENT SYSTEMS INC
-0020D0 VERSALYNX CORPORATION
-0020D1 MICROCOMPUTER SYSTEMS (M) SDN.
-0020D2 RAD DATA COMMUNICATIONS, LTD.
-0020D3 OST (OUEST STANDARD TELEMATIQU
-0020D4 CABLETRON - ZEITTNET INC.
-0020D5 VIPA GMBH
-0020D6 BREEZECOM
-0020D7 JAPAN MINICOMPUTER SYSTEMS CO., Ltd.
-0020D8 Nortel Networks
-0020D9 PANASONIC TECHNOLOGIES, INC./MIECO-US
-0020DA XYLAN CORPORATION
-0020DB XNET TECHNOLOGY, INC.
-0020DC DENSITRON TAIWAN LTD.
-0020DD Cybertec Pty Ltd
-0020DE JAPAN DIGITAL LABORAT'Y CO.LTD
-0020DF KYOSAN ELECTRIC MFG. CO., LTD.
-0020E0 PREMAX ELECTRONICS, INC.
-0020E1 ALAMAR ELECTRONICS
-0020E2 INFORMATION RESOURCE ENGINEERING
-0020E3 MCD KENCOM CORPORATION
-0020E4 HSING TECH ENTERPRISE CO., LTD
-0020E5 APEX DATA, INC.
-0020E6 LIDKOPING MACHINE TOOLS AB
-0020E7 B&W NUCLEAR SERVICE COMPANY
-0020E8 DATATREK CORPORATION
-0020E9 DANTEL
-0020EA EFFICIENT NETWORKS, INC.
-0020EB CINCINNATI MICROWAVE, INC.
-0020EC TECHWARE SYSTEMS CORP.
-0020ED GIGA-BYTE TECHNOLOGY CO., LTD.
-0020EE GTECH CORPORATION
-0020EF USC CORPORATION
-0020F0 UNIVERSAL MICROELECTRONICS CO.
-0020F1 ALTOS INDIA LIMITED
-0020F2 SUN MICROSYSTEMS, INC.
-0020F3 RAYNET CORPORATION
-0020F4 SPECTRIX CORPORATION
-0020F5 PANDATEL AG
-0020F6 NET TEK  AND KARLNET, INC.
-0020F7 CYBERDATA
-0020F8 CARRERA COMPUTERS, INC.
-0020F9 PARALINK NETWORKS, INC.
-0020FA GDE SYSTEMS, INC.
-0020FB OCTEL COMMUNICATIONS CORP.
-0020FC MATROX
-0020FD ITV TECHNOLOGIES, INC.
-0020FE TOPWARE INC. / GRAND COMPUTER
-0020FF SYMMETRICAL TECHNOLOGIES
-003000 ALLWELL TECHNOLOGY CORP.
-003001 SMP
-003002 Expand Networks
-003003 Phasys Ltd.
-003004 LEADTEK RESEARCH INC.
-003005 Fujitsu Siemens Computers
-003006 SUPERPOWER COMPUTER
-003007 OPTI, INC.
-003008 AVIO DIGITAL, INC.
-003009 Tachion Networks, Inc.
-00300A AZTECH SYSTEMS LTD.
-00300B mPHASE Technologies, Inc.
-00300C CONGRUENCY, LTD.
-00300D MMC Technology, Inc.
-00300E Klotz Digital AG
-00300F IMT - Information Management T
-003010 VISIONETICS INTERNATIONAL
-003011 HMS FIELDBUS SYSTEMS AB
-003012 DIGITAL ENGINEERING LTD.
-003013 NEC Corporation
-003014 DIVIO, INC.
-003015 CP CLARE CORP.
-003016 ISHIDA CO., LTD.
-003017 TERASTACK LTD.
-003018 Jetway Information Co., Ltd.
-003019 CISCO SYSTEMS, INC.
-00301A SMARTBRIDGES PTE. LTD.
-00301B SHUTTLE, INC.
-00301C ALTVATER AIRDATA SYSTEMS
-00301D SKYSTREAM, INC.
-00301E 3COM Europe Ltd.
-00301F OPTICAL NETWORKS, INC.
-003020 TSI, Inc..
-003021 HSING TECH. ENTERPRISE CO.,LTD
-003022 Fong Kai Industrial Co., Ltd.
-003023 COGENT COMPUTER SYSTEMS, INC.
-003024 CISCO SYSTEMS, INC.
-003025 CHECKOUT COMPUTER SYSTEMS, LTD
-003026 HEITEL
-003027 KERBANGO, INC.
-003028 FASE Saldatura srl
-003029 OPICOM
-00302A SOUTHERN INFORMATION
-00302B INALP NETWORKS, INC.
-00302C SYLANTRO SYSTEMS CORPORATION
-00302D QUANTUM BRIDGE COMMUNICATIONS
-00302E Hoft & Wessel AG
-00302F Smiths Industries
-003030 HARMONIX CORPORATION
-003031 LIGHTWAVE COMMUNICATIONS, INC.
-003032 MagicRam, Inc.
-003033 ORIENT TELECOM CO., LTD.
-003036 RMP ELEKTRONIKSYSTEME GMBH
-003037 Packard Bell Nec Services
-003038 XCP, INC.
-003039 SOFTBOOK PRESS
-00303A MAATEL
-00303B PowerCom Technology
-00303C ONNTO CORP.
-00303D IVA CORPORATION
-00303E Radcom Ltd.
-00303F TurboComm Tech Inc.
-003040 CISCO SYSTEMS, INC.
-003041 SAEJIN T & M CO., LTD.
-003042 DeTeWe-Deutsche Telephonwerke
-003043 IDREAM TECHNOLOGIES, PTE. LTD.
-003044 Portsmith LLC
-003045 Village Networks, Inc. (VNI)
-003046 Controlled Electronic Manageme
-003047 NISSEI ELECTRIC CO., LTD.
-003048 Supermicro Computer, Inc.
-003049 BRYANT TECHNOLOGY, LTD.
-00304A FRAUNHOFER INSTITUTE IMS
-00304B ORBACOM SYSTEMS, INC.
-00304C APPIAN COMMUNICATIONS, INC.
-00304D ESI
-00304E BUSTEC PRODUCTION LTD.
-00304F PLANET Technology Corporation
-003050 Versa Technology
-003051 ORBIT AVIONIC & COMMUNICATION
-003052 ELASTIC NETWORKS
-003053 Basler AG
-003054 CASTLENET TECHNOLOGY, INC.
-003055 Hitachi Semiconductor America,
-003056 Beck IPC GmbH
-003057 E-Tel Corporation
-003058 API MOTION
-003059 DIGITAL-LOGIC AG
-00305A TELGEN CORPORATION
-00305B MODULE DEPARTMENT
-00305C SMAR Laboratories Corp.
-00305D DIGITRA SYSTEMS, INC.
-00305E Abelko Innovation
-00305F IMACON APS
-003060 STARMATIX, INC.
-003061 MobyTEL
-003062 PATH 1 NETWORK TECHNOL'S INC.
-003063 SANTERA SYSTEMS, INC.
-003064 ADLINK TECHNOLOGY, INC.
-003065 APPLE COMPUTER, INC.
-003066 DIGITAL WIRELESS CORPORATION
-003067 BIOSTAR MICROTECH INT'L CORP.
-003068 CYBERNETICS TECH. CO., LTD.
-003069 IMPACCT TECHNOLOGY CORP.
-00306A PENTA MEDIA CO., LTD.
-00306B CMOS SYSTEMS, INC.
-00306C Hitex Holding GmbH
-00306D LUCENT TECHNOLOGIES
-00306E HEWLETT PACKARD
-00306F SEYEON TECH. CO., LTD.
-003070 1Net Corporation
-003071 Cisco Systems, Inc.
-003072 INTELLIBYTE INC.
-003073 International Microsystems, In
-003074 EQUIINET LTD.
-003075 ADTECH
-003076 Akamba Corporation
-003077 ONPREM NETWORKS
-003078 Cisco Systems, Inc.
-003079 CQOS, INC.
-00307A Advanced Technology & Systems
-00307B Cisco Systems, Inc.
-00307C ADID SA
-00307D GRE AMERICA, INC.
-00307E Redflex Communication Systems
-00307F IRLAN LTD.
-003080 CISCO SYSTEMS, INC.
-003081 ALTOS C&C
-003082 TAIHAN ELECTRIC WIRE CO., LTD.
-003083 Ivron Systems
-003084 ALLIED TELESYN INTERNAIONAL
-003085 CISCO SYSTEMS, INC.
-003086 Transistor Devices, Inc.
-003087 VEGA GRIESHABER KG
-003088 Siara Systems, Inc.
-003089 Spectrapoint Wireless, LLC
-00308A NICOTRA SISTEMI S.P.A
-00308B Brix Networks
-00308C ADVANCED DIGITAL INFORMATION
-00308D PINNACLE SYSTEMS, INC.
-00308E CROSS MATCH TECHNOLOGIES, INC.
-00308F MICRILOR, Inc.
-003090 CYRA TECHNOLOGIES, INC.
-003091 TAIWAN FIRST LINE ELEC. CORP.
-003092 ModuNORM GmbH
-003093 SONNET TECHNOLOGIES, INC.
-003094 Cisco Systems, Inc.
-003095 Procomp Informatics, Ltd.
-003096 CISCO SYSTEMS, INC.
-003097 EXOMATIC AB
-003098 Global Converging Technologies
-003099 BOENIG UND KALLENBACH OHG
-00309A ASTRO TERRA CORP.
-00309B Smartware
-00309C Timing Applications, Inc.
-00309D Nimble Microsystems, Inc.
-00309E WORKBIT CORPORATION.
-00309F AMBER NETWORKS
-0030A0 TYCO SUBMARINE SYSTEMS, LTD.
-0030A1 WEBGATE Inc.
-0030A2 Lightner Engineering
-0030A3 CISCO SYSTEMS, INC.
-0030A4 Woodwind Communications System
-0030A5 ACTIVE POWER
-0030A6 VIANET TECHNOLOGIES, LTD.
-0030A7 SCHWEITZER ENGINEERING
-0030A8 OL'E COMMUNICATIONS, INC.
-0030A9 Netiverse, Inc.
-0030AA AXUS MICROSYSTEMS, INC.
-0030AB DELTA NETWORKS, INC.
-0030AC Systeme Lauer GmbH & Co., Ltd.
-0030AD SHANGHAI COMMUNICATION
-0030AE Times N System, Inc.
-0030AF Honeywell GmbH
-0030B0 Convergenet Technologies
-0030B1 GOC GESELLSCHAFT FUR OPTISCHE
-0030B2 WESCAM - HEALDSBURG
-0030B3 San Valley Systems, Inc.
-0030B4 INTERSIL CORP.
-0030B5 Tadiran Microwave Networks
-0030B6 CISCO SYSTEMS, INC.
-0030B7 Teletrol Systems, Inc.
-0030B8 RiverDelta Networks
-0030B9 ECTEL
-0030BA AC&T SYSTEM CO., LTD.
-0030BB CacheFlow, Inc.
-0030BC Optronic AG
-0030BD BELKIN COMPONENTS
-0030BE City-Net Technology, Inc.
-0030BF MULTIDATA GMBH
-0030C0 Lara Technology, Inc.
-0030C1 HEWLETT-PACKARD
-0030C2 COMONE
-0030C3 FLUECKIGER ELEKTRONIK AG
-0030C4 Niigata Canotec Co., Inc.
-0030C5 CADENCE DESIGN SYSTEMS
-0030C6 CONTROL SOLUTIONS, INC.
-0030C7 MACROMATE CORP.
-0030C8 GAD LINE, LTD.
-0030C9 LuxN, N
-0030CA Discovery Com
-0030CB OMNI FLOW COMPUTERS, INC.
-0030CC Tenor Networks, Inc.
-0030CD CONEXANT SYSTEMS, INC.
-0030CE Zaffire
-0030CF TWO TECHNOLOGIES, INC.
-0030D1 INOVA CORPORATION
-0030D2 WIN TECHNOLOGIES, CO., LTD.
-0030D3 Agilent Technologies
-0030D4 COMTIER
-0030D5 DResearch GmbH
-0030D6 MSC VERTRIEBS GMBH
-0030D7 Innovative Systems, L.L.C.
-0030D8 SITEK
-0030D9 DATACORE SOFTWARE CORP.
-0030DA COMTREND CO.
-0030DB Mindready Solutions, Inc.
-0030DC RIGHTECH CORPORATION
-0030DD INDIGITA CORPORATION
-0030DE WAGO Kontakttechnik GmbH
-0030DF KB/TEL TELECOMUNICACIONES
-0030E0 OXFORD SEMICONDUCTOR LTD.
-0030E1 ACROTRON SYSTEMS, INC.
-0030E2 GARNET SYSTEMS CO., LTD.
-0030E3 SEDONA NETWORKS CORP.
-0030E4 CHIYODA SYSTEM RIKEN
-0030E5 Amper Datos S.A.
-0030E6 SIEMENS MEDICAL SYSTEMS
-0030E7 CNF MOBILE SOLUTIONS, INC.
-0030E8 ENSIM CORP.
-0030E9 GMA COMMUNICATION MANUFACT'G
-0030EA TeraForce Technology Corporation
-0030EB TURBONET COMMUNICATIONS, INC.
-0030EC BORGARDT
-0030ED Expert Magnetics Corp.
-0030EE DSG Technology, Inc.
-0030EF NEON TECHNOLOGY, INC.
-0030F0 Uniform Industrial Corp.
-0030F1 Accton Technology Corp.
-0030F2 CISCO SYSTEMS, INC.
-0030F3 At Work Computers
-0030F4 STARDOT TECHNOLOGIES
-0030F5 Wild Lab. Ltd.
-0030F6 SECURELOGIX CORPORATION
-0030F7 RAMIX INC.
-0030F8 Dynapro Systems, Inc.
-0030F9 Sollae Systems Co., Ltd.
-0030FA TELICA, INC.
-0030FB AZS Technology AG
-0030FC Terawave Communications, Inc.
-0030FD INTEGRATED SYSTEMS DESIGN
-0030FE DSA GmbH
-0030FF DATAFAB SYSTEMS, INC.
-004000 PCI COMPONENTES DA AMZONIA LTD
-004001 ZYXEL COMMUNICATIONS, INC.
-004002 PERLE SYSTEMS LIMITED
-004003 WESTINGHOUSE PROCESS CONTROL
-004004 ICM CO. LTD.
-004005 ANI COMMUNICATIONS INC.
-004006 SAMPO TECHNOLOGY CORPORATION
-004007 TELMAT INFORMATIQUE
-004008 A PLUS INFO CORPORATION
-004009 TACHIBANA TECTRON CO., LTD.
-00400A PIVOTAL TECHNOLOGIES, INC.
-00400B CISCO SYSTEMS, INC.
-00400C GENERAL MICRO SYSTEMS, INC.
-00400D LANNET DATA COMMUNICATIONS,LTD
-00400E MEMOTEC COMMUNICATIONS, INC.
-00400F DATACOM TECHNOLOGIES
-004010 SONIC SYSTEMS, INC.
-004011 ANDOVER CONTROLS CORPORATION
-004012 WINDATA, INC.
-004013 NTT DATA COMM. SYSTEMS CORP.
-004014 COMSOFT GMBH
-004015 ASCOM INFRASYS AG
-004016 HADAX ELECTRONICS, INC.
-004017 XCD INC.
-004018 ADOBE SYSTEMS, INC.
-004019 AEON SYSTEMS, INC.
-00401A FUJI ELECTRIC CO., LTD.
-00401B PRINTER SYSTEMS CORP.
-00401C AST RESEARCH, INC.
-00401D INVISIBLE SOFTWARE, INC.
-00401E ICC
-00401F COLORGRAPH LTD
-004020 PINACL COMMUNICATION
-004021 RASTER GRAPHICS
-004022 KLEVER COMPUTERS, INC.
-004023 LOGIC CORPORATION
-004024 COMPAC INC.
-004025 MOLECULAR DYNAMICS
-004026 MELCO, INC.
-004027 SMC MASSACHUSETTS, INC.
-004028 NETCOMM LIMITED
-004029 COMPEX
-00402A CANOGA-PERKINS
-00402B TRIGEM COMPUTER, INC.
-00402C ISIS DISTRIBUTED SYSTEMS, INC.
-00402D HARRIS ADACOM CORPORATION
-00402E PRECISION SOFTWARE, INC.
-00402F XLNT DESIGNS INC.
-004030 GK COMPUTER
-004031 KOKUSAI ELECTRIC CO., LTD
-004032 DIGITAL COMMUNICATIONS
-004033 ADDTRON TECHNOLOGY CO., LTD.
-004034 BUSTEK CORPORATION
-004035 OPCOM
-004036 TRIBE COMPUTER WORKS, INC.
-004037 SEA-ILAN, INC.
-004038 TALENT ELECTRIC INCORPORATED
-004039 OPTEC DAIICHI DENKO CO., LTD.
-00403A IMPACT TECHNOLOGIES
-00403B SYNERJET INTERNATIONAL CORP.
-00403C FORKS, INC.
-00403D TERADATA
-00403E RASTER OPS CORPORATION
-00403F SSANGYONG COMPUTER SYSTEMS
-004040 RING ACCESS, INC.
-004041 FUJIKURA LTD.
-004042 N.A.T. GMBH
-004043 NOKIA TELECOMMUNICATIONS
-004044 QNIX COMPUTER CO., LTD.
-004045 TWINHEAD CORPORATION
-004046 UDC RESEARCH LIMITED
-004047 WIND RIVER SYSTEMS
-004048 SMD INFORMATICA S.A.
-004049 TEGIMENTA AG
-00404A WEST AUSTRALIAN DEPARTMENT
-00404B MAPLE COMPUTER SYSTEMS
-00404C HYPERTEC PTY LTD.
-00404D TELECOMMUNICATIONS TECHNIQUES
-00404E FLUENT, INC.
-00404F SPACE & NAVAL WARFARE SYSTEMS
-004050 IRONICS, INCORPORATED
-004051 GRACILIS, INC.
-004052 STAR TECHNOLOGIES, INC.
-004053 AMPRO COMPUTERS
-004054 CONNECTION MACHINES SERVICES
-004055 METRONIX GMBH
-004056 MCM JAPAN LTD.
-004057 LOCKHEED - SANDERS
-004058 KRONOS, INC.
-004059 YOSHIDA KOGYO K. K.
-00405A GOLDSTAR INFORMATION & COMM.
-00405B FUNASSET LIMITED
-00405C FUTURE SYSTEMS, INC.
-00405D STAR-TEK, INC.
-00405E NORTH HILLS ISRAEL
-00405F AFE COMPUTERS LTD.
-004060 COMENDEC LTD
-004061 DATATECH ENTERPRISES CO., LTD.
-004062 E-SYSTEMS, INC./GARLAND DIV.
-004063 VIA TECHNOLOGIES, INC.
-004064 KLA INSTRUMENTS CORPORATION
-004065 GTE SPACENET
-004066 HITACHI CABLE, LTD.
-004067 OMNIBYTE CORPORATION
-004068 EXTENDED SYSTEMS
-004069 LEMCOM SYSTEMS, INC.
-00406A KENTEK INFORMATION SYSTEMS,INC
-00406B SYSGEN
-00406C COPERNIQUE
-00406D LANCO, INC.
-00406E COROLLARY, INC.
-00406F SYNC RESEARCH INC.
-004070 INTERWARE CO., LTD.
-004071 ATM COMPUTER GMBH
-004072 Applied Innovation Inc.
-004073 BASS ASSOCIATES
-004074 CABLE AND WIRELESS
-004075 M-TRADE (UK) LTD
-004076 Sun Conversion Technologies
-004077 MAXTON TECHNOLOGY CORPORATION
-004078 WEARNES AUTOMATION PTE LTD
-004079 JUKO MANUFACTURE COMPANY, LTD.
-00407A SOCIETE D'EXPLOITATION DU CNIT
-00407B SCIENTIFIC ATLANTA
-00407C QUME CORPORATION
-00407D EXTENSION TECHNOLOGY CORP.
-00407E EVERGREEN SYSTEMS, INC.
-00407F FLIR Systems
-004080 ATHENIX CORPORATION
-004081 MANNESMANN SCANGRAPHIC GMBH
-004082 LABORATORY EQUIPMENT CORP.
-004083 TDA INDUSTRIA DE PRODUTOS
-004084 HONEYWELL INC.
-004085 SAAB INSTRUMENTS AB
-004086 MICHELS & KLEBERHOFF COMPUTER
-004087 UBITREX CORPORATION
-004088 MOBIUS TECHNOLOGIES, INC.
-004089 MEIDENSHA CORPORATION
-00408A TPS TELEPROCESSING SYS. GMBH
-00408B RAYLAN CORPORATION
-00408C AXIS COMMUNICATIONS AB
-00408D THE GOODYEAR TIRE & RUBBER CO.
-00408E DIGILOG, INC.
-00408F WM-DATA MINFO AB
-004090 ANSEL COMMUNICATIONS
-004091 PROCOMP INDUSTRIA ELETRONICA
-004092 ASP COMPUTER PRODUCTS, INC.
-004093 PAXDATA NETWORKS LTD.
-004094 SHOGRAPHICS, INC.
-004095 R.P.T. INTERGROUPS INT'L LTD.
-004096 Aironet Wireless Communication
-004097 DATEX DIVISION OF
-004098 DRESSLER GMBH & CO.
-004099 NEWGEN SYSTEMS CORP.
-00409A NETWORK EXPRESS, INC.
-00409B HAL COMPUTER SYSTEMS INC.
-00409C TRANSWARE
-00409D DIGIBOARD, INC.
-00409E CONCURRENT TECHNOLOGIES  LTD.
-00409F LANCAST/CASAT TECHNOLOGY, INC.
-0040A0 GOLDSTAR CO., LTD.
-0040A1 ERGO COMPUTING
-0040A2 KINGSTAR TECHNOLOGY INC.
-0040A3 MICROUNITY SYSTEMS ENGINEERING
-0040A4 ROSE ELECTRONICS
-0040A5 CLINICOMP INTL.
-0040A6 Cray, Inc.
-0040A7 ITAUTEC PHILCO S.A.
-0040A8 IMF INTERNATIONAL LTD.
-0040A9 DATACOM INC.
-0040AA VALMET AUTOMATION INC.
-0040AB ROLAND DG CORPORATION
-0040AC SUPER WORKSTATION, INC.
-0040AD SMA REGELSYSTEME GMBH
-0040AE DELTA CONTROLS, INC.
-0040AF DIGITAL PRODUCTS, INC.
-0040B0 BYTEX CORPORATION, ENGINEERING
-0040B1 CODONICS INC.
-0040B2 SYSTEMFORSCHUNG
-0040B3 PAR MICROSYSTEMS CORPORATION
-0040B4 NEXTCOM K.K.
-0040B5 VIDEO TECHNOLOGY COMPUTERS LTD
-0040B6 COMPUTERM  CORPORATION
-0040B7 STEALTH COMPUTER SYSTEMS
-0040B8 IDEA ASSOCIATES
-0040B9 MACQ ELECTRONIQUE SA
-0040BA ALLIANT COMPUTER SYSTEMS CORP.
-0040BB GOLDSTAR CABLE CO., LTD.
-0040BC ALGORITHMICS LTD.
-0040BD STARLIGHT NETWORKS, INC.
-0040BE BOEING DEFENSE & SPACE
-0040BF CHANNEL SYSTEMS INTERN'L INC.
-0040C0 VISTA CONTROLS CORPORATION
-0040C1 BIZERBA-WERKE WILHEIM KRAUT
-0040C2 APPLIED COMPUTING DEVICES
-0040C3 FISCHER AND PORTER CO.
-0040C4 KINKEI SYSTEM CORPORATION
-0040C5 MICOM COMMUNICATIONS INC.
-0040C6 FIBERNET RESEARCH, INC.
-0040C7 RUBY TECH CORPORATION
-0040C8 MILAN TECHNOLOGY CORPORATION
-0040C9 NCUBE
-0040CA FIRST INTERNAT'L COMPUTER, INC
-0040CB LANWAN TECHNOLOGIES
-0040CC SILCOM MANUF'G TECHNOLOGY INC.
-0040CD TERA MICROSYSTEMS, INC.
-0040CE NET-SOURCE, INC.
-0040CF STRAWBERRY TREE, INC.
-0040D0 MITAC INTERNATIONAL CORP.
-0040D1 FUKUDA DENSHI CO., LTD.
-0040D2 PAGINE CORPORATION
-0040D3 KIMPSION INTERNATIONAL CORP.
-0040D4 GAGE TALKER CORP.
-0040D5 SARTORIUS AG
-0040D6 LOCAMATION B.V.
-0040D7 STUDIO GEN INC.
-0040D8 OCEAN OFFICE AUTOMATION LTD.
-0040D9 AMERICAN MEGATRENDS INC.
-0040DA TELSPEC LTD
-0040DB ADVANCED TECHNICAL SOLUTIONS
-0040DC TRITEC ELECTRONIC GMBH
-0040DD HONG TECHNOLOGIES
-0040DE ELETTRONICA SAN GIORGIO
-0040DF DIGALOG SYSTEMS, INC.
-0040E0 ATOMWIDE LTD.
-0040E1 MARNER INTERNATIONAL, INC.
-0040E2 MESA RIDGE TECHNOLOGIES, INC.
-0040E3 QUIN SYSTEMS LTD
-0040E4 E-M TECHNOLOGY, INC.
-0040E5 SYBUS CORPORATION
-0040E6 C.A.E.N.
-0040E7 ARNOS INSTRUMENTS & COMPUTER
-0040E8 CHARLES RIVER DATA SYSTEMS,INC
-0040E9 ACCORD SYSTEMS, INC.
-0040EA PLAIN TREE SYSTEMS INC
-0040EB MARTIN MARIETTA CORPORATION
-0040EC MIKASA SYSTEM ENGINEERING
-0040ED NETWORK CONTROLS INT'NATL INC.
-0040EE OPTIMEM
-0040EF HYPERCOM, INC.
-0040F0 MICRO SYSTEMS, INC.
-0040F1 CHUO ELECTRONICS CO., LTD.
-0040F2 JANICH & KLASS COMPUTERTECHNIK
-0040F3 NETCOR
-0040F4 CAMEO COMMUNICATIONS, INC.
-0040F5 OEM ENGINES
-0040F6 KATRON COMPUTERS INC.
-0040F7 POLAROID MEDICAL IMAGING SYS.
-0040F8 SYSTEMHAUS DISCOM
-0040F9 COMBINET
-0040FA MICROBOARDS, INC.
-0040FB CASCADE COMMUNICATIONS CORP.
-0040FC IBR COMPUTER TECHNIK GMBH
-0040FD LXE
-0040FE SYMPLEX COMMUNICATIONS
-0040FF TELEBIT CORPORATION
-004252 RLX Technologies
-005000 NEXO COMMUNICATIONS, INC.
-005001 YAMASHITA SYSTEMS CORP.
-005002 OMNISEC AG
-005003 GRETAG MACBETH AG
-005004 3COM CORPORATION
-005006 TAC AB
-005007 SIEMENS TELECOMMUNICATION SYSTEMS LIMITED
-005008 TIVA MICROCOMPUTER CORP. (TMC)
-005009 PHILIPS BROADBAND NETWORKS
-00500A IRIS TECHNOLOGIES, INC.
-00500B CISCO SYSTEMS, INC.
-00500C e-Tek Labs, Inc.
-00500D SATORI ELECTORIC CO., LTD.
-00500E CHROMATIS NETWORKS, INC.
-00500F CISCO SYSTEMS, INC.
-005010 NovaNET Learning, Inc.
-005012 CBL - GMBH
-005013 Chaparral Network Storage
-005014 CISCO SYSTEMS, INC.
-005015 BRIGHT STAR ENGINEERING
-005016 SST/WOODHEAD INDUSTRIES
-005017 RSR S.R.L.
-005018 ADVANCED MULTIMEDIA INTERNET TECHNOLOGY INC.
-005019 SPRING TIDE NETWORKS, INC.
-00501A UISIQN
-00501B ABL CANADA, INC.
-00501C JATOM SYSTEMS, INC.
-00501E Miranda Technologies, Inc.
-00501F MRG SYSTEMS, LTD.
-005020 MEDIASTAR CO., LTD.
-005021 EIS INTERNATIONAL, INC.
-005022 ZONET TECHNOLOGY, INC.
-005023 PG DESIGN ELECTRONICS, INC.
-005024 NAVIC SYSTEMS, INC.
-005026 COSYSTEMS, INC.
-005027 GENICOM CORPORATION
-005028 AVAL COMMUNICATIONS
-005029 1394 PRINTER WORKING GROUP
-00502A CISCO SYSTEMS, INC.
-00502B GENRAD LTD.
-00502C SOYO COMPUTER, INC.
-00502D ACCEL, INC.
-00502E CAMBEX CORPORATION
-00502F TollBridge Technologies, Inc.
-005030 FUTURE PLUS SYSTEMS
-005031 AEROFLEX LABORATORIES, INC.
-005032 PICAZO COMMUNICATIONS, INC.
-005033 MAYAN NETWORKS
-005036 NETCAM, LTD.
-005037 KOGA ELECTRONICS CO.
-005038 DAIN TELECOM CO., LTD.
-005039 MARINER NETWORKS
-00503A DATONG ELECTRONICS LTD.
-00503B MEDIAFIRE CORPORATION
-00503C TSINGHUA NOVEL ELECTRONICS
-00503E CISCO SYSTEMS, INC.
-00503F ANCHOR GAMES
-005040 EMWARE, INC.
-005041 CTX OPTO ELECTRONIC CORP.
-005042 SCI MANUFACTURING SINGAPORE PTE, LTD.
-005043 MARVELL SEMICONDUCTOR, INC.
-005044 ASACA CORPORATION
-005045 RIOWORKS SOLUTIONS, INC.
-005046 MENICX INTERNATIONAL CO., LTD.
-005048 INFOLIBRIA
-005049 ELLACOYA NETWORKS, INC.
-00504A ELTECO A.S.
-00504B BARCONET N.V.
-00504C GALIL MOTION CONTROL, INC.
-00504D TOKYO ELECTRON DEVICE LTD.
-00504E SIERRA MONITOR CORP.
-00504F OLENCOM ELECTRONICS
-005050 CISCO SYSTEMS, INC.
-005051 IWATSU ELECTRIC CO., LTD.
-005052 TIARA NETWORKS, INC.
-005053 CISCO SYSTEMS, INC.
-005054 CISCO SYSTEMS, INC.
-005055 DOMS A/S
-005056 VMWare, Inc.
-005057 BROADBAND ACCESS SYSTEMS
-005058 VEGASTREAM LIMITED
-005059 SUITE TECHNOLOGY SYSTEMS NETWORK
-00505A NETWORK ALCHEMY, INC.
-00505B KAWASAKI LSI U.S.A., INC.
-00505C TUNDO CORPORATION
-00505E DIGITEK MICROLOGIC S.A.
-00505F BRAND INNOVATORS
-005060 TANDBERG TELECOM AS
-005062 KOUWELL ELECTRONICS CORP.  **
-005063 OY COMSEL SYSTEM AB
-005064 CAE ELECTRONICS
-005065 DENSEI-LAMBAD Co., Ltd.
-005066 AtecoM GmbH advanced telecomunication modules
-005067 AEROCOMM, INC.
-005068 ELECTRONIC INDUSTRIES ASSOCIATION
-005069 PixStream Incorporated
-00506A EDEVA, INC.
-00506B SPX-ATEG
-00506C G & L BEIJER ELECTRONICS AB
-00506D VIDEOJET SYSTEMS
-00506E CORDER ENGINEERING CORPORATION
-00506F G-CONNECT
-005070 CHAINTECH COMPUTER CO., LTD.
-005071 AIWA CO., LTD.
-005072 CORVIS CORPORATION
-005073 CISCO SYSTEMS, INC.
-005074 ADVANCED HI-TECH CORP.
-005075 KESTREL SOLUTIONS
-005076 IBM
-005077 PROLIFIC TECHNOLOGY, INC.
-005078 MEGATON HOUSE, LTD.
-00507A XPEED, INC.
-00507B MERLOT COMMUNICATIONS
-00507C VIDEOCON AG
-00507D IFP
-00507E NEWER TECHNOLOGY
-00507F DrayTek Corp.
-005080 CISCO SYSTEMS, INC.
-005081 MURATA MACHINERY, LTD.
-005082 FORESSON CORPORATION
-005083 GILBARCO, INC.
-005084 ATL PRODUCTS
-005086 TELKOM SA, LTD.
-005087 TERASAKI ELECTRIC CO., LTD.
-005088 AMANO CORPORATION
-005089 SAFETY MANAGEMENT SYSTEMS
-00508B COMPAQ COMPUTER CORPORATION
-00508C RSI SYSTEMS
-00508D ABIT COMPUTER CORPORATION
-00508E OPTIMATION, INC.
-00508F ASITA TECHNOLOGIES INT'L LTD.
-005090 DCTRI
-005091 NETACCESS, INC.
-005092 RIGAKU INDUSTRIAL CORPORATION
-005093 BOEING
-005094 PACE MICRO TECHNOLOGY PLC
-005095 PERACOM NETWORKS
-005096 SALIX TECHNOLOGIES, INC.
-005097 MMC-EMBEDDED COMPUTERTECHNIK GmbH
-005098 GLOBALOOP, LTD.
-005099 3COM EUROPE, LTD.
-00509A TAG ELECTRONIC SYSTEMS
-00509B SWITCHCORE AB
-00509C BETA RESEARCH
-00509D THE INDUSTREE B.V.
-00509E Les Technologies SoftAcoustik Inc.
-00509F HORIZON COMPUTER
-0050A0 DELTA COMPUTER SYSTEMS, INC.
-0050A1 CARLO GAVAZZI, INC.
-0050A2 CISCO SYSTEMS, INC.
-0050A3 TransMedia Communications, Inc.
-0050A4 IO TECH, INC.
-0050A5 CAPITOL BUSINESS SYSTEMS, LTD.
-0050A6 OPTRONICS
-0050A7 CISCO SYSTEMS, INC.
-0050A8 OpenCon Systems, Inc.
-0050A9 MOLDAT WIRELESS TECHNOLGIES
-0050AA KONICA MINOLTA HOLDINGS, INC.
-0050AB NALTEC, INC.
-0050AC MAPLE COMPUTER CORPORATION
-0050AD CommUnique Wireless Corp.
-0050AE IWAKI ELECTRONICS CO., LTD.
-0050AF INTERGON, INC.
-0050B0 TECHNOLOGY ATLANTA CORPORATION
-0050B1 GIDDINGS & LEWIS
-0050B2 BRODEL AUTOMATION
-0050B3 VOICEBOARD CORPORATION
-0050B4 SATCHWELL CONTROL SYSTEMS, LTD
-0050B5 FICHET-BAUCHE
-0050B6 GOOD WAY IND. CO., LTD.
-0050B7 BOSER TECHNOLOGY CO., LTD.
-0050B8 INOVA COMPUTERS GMBH & CO. KG
-0050B9 XITRON TECHNOLOGIES, INC.
-0050BA D-LINK
-0050BB CMS TECHNOLOGIES
-0050BC HAMMER STORAGE SOLUTIONS
-0050BD CISCO SYSTEMS, INC.
-0050BE FAST MULTIMEDIA AG
-0050BF MOTOTECH INC.
-0050C0 GATAN, INC.
-0050C1 GEMFLEX NETWORKS, LTD.
-0050C2 IEEE REGISTRATION AUTHORITY
-0050C4 IMD
-0050C5 ADS TECHNOLOGIES, INC.
-0050C6 LOOP TELECOMMUNICATION INTERNATIONAL, INC.
-0050C8 ADDONICS COMMUNICATIONS, INC.
-0050C9 MASPRO DENKOH CORP.
-0050CA NET TO NET TECHNOLOGIES
-0050CB JETTER
-0050CC XYRATEX
-0050CD DIGIANSWER A/S
-0050CE LG INTERNATIONAL CORP.
-0050CF VANLINK COMMUNICATION TECHNOLOGY RESEARCH INSTITUTE
-0050D0 MINERVA SYSTEMS
-0050D1 CISCO SYSTEMS, INC.
-0050D2 BAE Systems Canada, Inc.
-0050D3 DIGITAL AUDIO PROCESSING PTY. LTD.
-0050D4 JOOHONG INFORMATION &
-0050D5 AD SYSTEMS CORP.
-0050D6 ATLAS COPCO TOOLS AB
-0050D7 TELSTRAT
-0050D8 UNICORN COMPUTER CORP.
-0050D9 ENGETRON-ENGENHARIA ELETRONICA IND. e COM. LTDA
-0050DA 3COM CORPORATION
-0050DB CONTEMPORARY CONTROL
-0050DC TAS TELEFONBAU A. SCHWABE GMBH & CO. KG
-0050DD SERRA SOLDADURA, S.A.
-0050DE SIGNUM SYSTEMS CORP.
-0050DF AirFiber, Inc.
-0050E1 NS TECH ELECTRONICS SDN BHD
-0050E2 CISCO SYSTEMS, INC.
-0050E3 Terayon Communications Systems
-0050E4 APPLE COMPUTER, INC.
-0050E6 HAKUSAN CORPORATION
-0050E7 PARADISE INNOVATIONS (ASIA)
-0050E8 NOMADIX INC.
-0050EA XEL COMMUNICATIONS, INC.
-0050EB ALPHA-TOP CORPORATION
-0050EC OLICOM A/S
-0050ED ANDA NETWORKS
-0050EE TEK DIGITEL CORPORATION
-0050EF SPE Systemhaus GmbH
-0050F0 CISCO SYSTEMS, INC.
-0050F1 LIBIT SIGNAL PROCESSING, LTD.
-0050F2 MICROSOFT CORP.
-0050F3 GLOBAL NET INFORMATION CO., Ltd.
-0050F4 SIGMATEK GMBH & CO. KG
-0050F6 PAN-INTERNATIONAL INDUSTRIAL CORP.
-0050F7 VENTURE MANUFACTURING (SINGAPORE) LTD.
-0050F8 ENTREGA TECHNOLOGIES, INC.
-0050FA OXTEL, LTD.
-0050FB VSK ELECTRONICS
-0050FC EDIMAX TECHNOLOGY CO., LTD.
-0050FD VISIONCOMM CO., LTD.
-0050FE PCTVnet ASA
-0050FF HAKKO ELECTRONICS CO., LTD.
-006000 XYCOM INC.
-006001 InnoSys, Inc.
-006002 SCREEN SUBTITLING SYSTEMS, LTD
-006003 TERAOKA WEIGH SYSTEM PTE, LTD.
-006004 COMPUTADORES MODULARES SA
-006005 FEEDBACK DATA LTD.
-006006 SOTEC CO., LTD
-006007 ACRES GAMING, INC.
-006008 3COM CORPORATION
-006009 CISCO SYSTEMS, INC.
-00600A SORD COMPUTER CORPORATION
-00600B LOGWARE GmbH
-00600C APPLIED DATA SYSTEMS, INC.
-00600D Digital Logic GmbH
-00600E WAVENET INTERNATIONAL, INC.
-00600F WESTELL, INC.
-006010 NETWORK MACHINES, INC.
-006011 CRYSTAL SEMICONDUCTOR CORP.
-006012 POWER COMPUTING CORPORATION
-006013 NETSTAL MASCHINEN AG
-006014 EDEC CO., LTD.
-006015 NET2NET CORPORATION
-006016 CLARIION
-006017 TOKIMEC INC.
-006018 STELLAR ONE CORPORATION
-006019 Roche Diagnostics
-00601A KEITHLEY INSTRUMENTS
-00601B MESA ELECTRONICS
-00601C TELXON CORPORATION
-00601D LUCENT TECHNOLOGIES
-00601E SOFTLAB, INC.
-00601F STALLION TECHNOLOGIES
-006020 PIVOTAL NETWORKING, INC.
-006021 DSC CORPORATION
-006022 VICOM SYSTEMS, INC.
-006023 PERICOM SEMICONDUCTOR CORP.
-006024 GRADIENT TECHNOLOGIES, INC.
-006025 ACTIVE IMAGING PLC
-006026 VIKING COMPONENTS, INC.
-006027 Superior Modular Products
-006028 MACROVISION CORPORATION
-006029 CARY PERIPHERALS INC.
-00602A SYMICRON COMPUTER COMMUNICATIONS, LTD.
-00602B PEAK AUDIO
-00602C LINX Data Terminals, Inc.
-00602D ALERTON TECHNOLOGIES, INC.
-00602E CYCLADES CORPORATION
-00602F CISCO SYSTEMS, INC.
-006030 VILLAGE TRONIC ENTWICKLUNG
-006031 HRK SYSTEMS
-006032 I-CUBE, INC.
-006033 ACUITY IMAGING, INC.
-006034 ROBERT BOSCH GmbH
-006035 DALLAS SEMICONDUCTOR, INC.
-006036 AUSTRIAN RESEARCH CENTER SEIBERSDORF
-006037 PHILIPS SEMICONDUCTORS
-006038 Nortel Networks
-006039 SanCom Technology, Inc.
-00603A QUICK CONTROLS LTD.
-00603B AMTEC spa
-00603C HAGIWARA SYS-COM CO., LTD.
-00603D 3CX
-00603E CISCO SYSTEMS, INC.
-00603F PATAPSCO DESIGNS
-006040 NETRO CORP.
-006041 Yokogawa Electric Corporation
-006042 TKS (USA), INC.
-006043 ComSoft Systems, Inc.
-006044 LITTON/POLY-SCIENTIFIC
-006045 PATHLIGHT TECHNOLOGIES
-006046 VMETRO, INC.
-006047 CISCO SYSTEMS, INC.
-006048 EMC CORPORATION
-006049 VINA TECHNOLOGIES
-00604A SAIC IDEAS GROUP
-00604B BIODATA GmbH
-00604C SAT
-00604D MMC NETWORKS, INC.
-00604E CYCLE COMPUTER CORPORATION, INC.
-00604F SUZUKI MFG. CO., LTD.
-006050 INTERNIX INC.
-006051 QUALITY SEMICONDUCTOR
-006052 PERIPHERALS ENTERPRISE CO., Ltd.
-006053 TOYODA MACHINE WORKS, LTD.
-006054 CONTROLWARE GMBH
-006055 CORNELL UNIVERSITY
-006056 NETWORK TOOLS, INC.
-006057 MURATA MANUFACTURING CO., LTD.
-006058 COPPER MOUNTAIN COMMUNICATIONS, INC.
-006059 TECHNICAL COMMUNICATIONS CORP.
-00605A CELCORE, INC.
-00605B IntraServer Technology, Inc.
-00605C CISCO SYSTEMS, INC.
-00605D SCANIVALVE CORP.
-00605E LIBERTY TECHNOLOGY NETWORKING
-00605F NIPPON UNISOFT CORPORATION
-006060 DAWNING TECHNOLOGIES, INC.
-006061 WHISTLE COMMUNICATIONS CORP.
-006062 TELESYNC, INC.
-006063 PSION DACOM PLC.
-006064 NETCOMM LIMITED
-006065 BERNECKER & RAINER INDUSTRIE-ELEKTRONIC GmbH
-006066 LACROIX TECHNOLGIE
-006067 ACER NETXUS INC.
-006068 EICON TECHNOLOGY CORPORATION
-006069 BROCADE COMMUNICATIONS SYSTEMS, Inc.
-00606A MITSUBISHI WIRELESS COMMUNICATIONS. INC.
-00606B Synclayer Inc.
-00606C ARESCOM
-00606D DIGITAL EQUIPMENT CORP.
-00606E DAVICOM SEMICONDUCTOR, INC.
-00606F CLARION CORPORATION OF AMERICA
-006070 CISCO SYSTEMS, INC.
-006071 MIDAS LAB, INC.
-006072 VXL INSTRUMENTS, LIMITED
-006073 REDCREEK COMMUNICATIONS, INC.
-006074 QSC AUDIO PRODUCTS
-006075 PENTEK, INC.
-006076 SCHLUMBERGER TECHNOLOGIES RETAIL PETROLEUM SYSTEMS
-006077 PRISA NETWORKS
-006078 POWER MEASUREMENT LTD.
-006079 Mainstream Data, Inc.
-00607A DVS GmbH
-00607B FORE SYSTEMS, INC.
-00607C WaveAccess, Ltd.
-00607D SENTIENT NETWORKS INC.
-00607E GIGALABS, INC.
-00607F AURORA TECHNOLOGIES, INC.
-006080 MICROTRONIX DATACOM LTD.
-006081 TV/COM INTERNATIONAL
-006082 NOVALINK TECHNOLOGIES, INC.
-006083 CISCO SYSTEMS, INC.
-006084 DIGITAL VIDEO
-006085 Storage Concepts
-006086 LOGIC REPLACEMENT TECH. LTD.
-006087 KANSAI ELECTRIC CO., LTD.
-006088 WHITE MOUNTAIN DSP, INC.
-006089 XATA
-00608A CITADEL COMPUTER
-00608B ConferTech International
-00608C 3COM CORPORATION
-00608D UNIPULSE CORP.
-00608E HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH
-00608F TEKRAM TECHNOLOGY CO., LTD.
-006090 ABLE COMMUNICATIONS, INC.
-006091 FIRST PACIFIC NETWORKS, INC.
-006092 MICRO/SYS, INC.
-006093 VARIAN
-006094 IBM CORP.
-006095 ACCU-TIME SYSTEMS, INC.
-006096 T.S. MICROTECH INC.
-006097 3COM CORPORATION
-006098 HT COMMUNICATIONS
-006099 LAN MEDIA CORPORATION
-00609A NJK TECHNO CO.
-00609B ASTRO-MED, INC.
-00609C Perkin-Elmer Incorporated
-00609D PMI FOOD EQUIPMENT GROUP
-00609E ASC X3 - INFORMATION TECHNOLOGY STANDARDS SECRETARIATS
-00609F PHAST CORPORATION
-0060A0 SWITCHED NETWORK TECHNOLOGIES, INC.
-0060A1 VPNet, Inc.
-0060A2 NIHON UNISYS LIMITED CO.
-0060A3 CONTINUUM TECHNOLOGY CORP.
-0060A4 GRINAKER SYSTEM TECHNOLOGIES
-0060A5 PERFORMANCE TELECOM CORP.
-0060A6 PARTICLE MEASURING SYSTEMS
-0060A7 MICROSENS GmbH & CO. KG
-0060A8 TIDOMAT AB
-0060A9 GESYTEC MbH
-0060AA INTELLIGENT DEVICES INC. (IDI)
-0060AB LARSCOM INCORPORATED
-0060AC RESILIENCE CORPORATION
-0060AD MegaChips Corporation
-0060AE TRIO INFORMATION SYSTEMS AB
-0060AF PACIFIC MICRO DATA, INC.
-0060B0 HEWLETT-PACKARD CO.
-0060B1 INPUT/OUTPUT, INC.
-0060B2 PROCESS CONTROL CORP.
-0060B3 Z-COM, INC.
-0060B4 GLENAYRE R&D INC.
-0060B5 KEBA GmbH
-0060B6 LAND COMPUTER CO., LTD.
-0060B7 CHANNELMATIC, INC.
-0060B8 CORELIS INC.
-0060B9 NITSUKO CORPORATION
-0060BA SAHARA NETWORKS, INC.
-0060BB CABLETRON - NETLINK, INC.
-0060BC KeunYoung Electronics & Communication Co., Ltd.
-0060BD HUBBELL-PULSECOM
-0060BE WEBTRONICS
-0060BF MACRAIGOR SYSTEMS, INC.
-0060C0 NERA AS
-0060C1 WaveSpan Corporation
-0060C2 MPL AG
-0060C3 NETVISION CORPORATION
-0060C4 SOLITON SYSTEMS K.K.
-0060C5 ANCOT CORP.
-0060C6 DCS AG
-0060C7 AMATI COMMUNICATIONS CORP.
-0060C8 KUKA WELDING SYSTEMS & ROBOTS
-0060C9 ControlNet, Inc.
-0060CA HARMONIC SYSTEMS INCORPORATED
-0060CB HITACHI ZOSEN CORPORATION
-0060CC EMTRAK, INCORPORATED
-0060CD VideoServer, Inc.
-0060CE ACCLAIM COMMUNICATIONS
-0060CF ALTEON NETWORKS, INC.
-0060D0 SNMP RESEARCH INCORPORATED
-0060D1 CASCADE COMMUNICATIONS
-0060D2 LUCENT TECHNOLOGIES TAIWAN TELECOMMUNICATIONS CO., LTD.
-0060D3 AT&T
-0060D4 ELDAT COMMUNICATION LTD.
-0060D5 MIYACHI TECHNOS CORP.
-0060D6 NovAtel Wireless Technologies Ltd.
-0060D7 ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE (EPFL)
-0060D8 ELMIC SYSTEMS, INC.
-0060D9 TRANSYS NETWORKS INC.
-0060DA JBM ELECTRONICS CO.
-0060DB NTP ELEKTRONIK A/S
-0060DC TOYO COMMUNICATION EQUIPMENT Co., Ltd.
-0060DD MYRICOM, INC.
-0060DE KAYSER-THREDE GmbH
-0060DF CNT Corporation
-0060E0 AXIOM TECHNOLOGY CO., LTD.
-0060E1 ORCKIT COMMUNICATIONS LTD.
-0060E2 QUEST ENGINEERING & DEVELOPMENT
-0060E3 ARBIN INSTRUMENTS
-0060E4 COMPUSERVE, INC.
-0060E5 FUJI AUTOMATION CO., LTD.
-0060E6 SHOMITI SYSTEMS INCORPORATED
-0060E7 RANDATA
-0060E8 HITACHI COMPUTER PRODUCTS (AMERICA), INC.
-0060E9 ATOP TECHNOLOGIES, INC.
-0060EA StreamLogic
-0060EB FOURTHTRACK SYSTEMS
-0060EC HERMARY OPTO ELECTRONICS INC.
-0060ED RICARDO TEST AUTOMATION LTD.
-0060EE APOLLO
-0060EF FLYTECH TECHNOLOGY CO., LTD.
-0060F0 JOHNSON & JOHNSON MEDICAL, INC
-0060F1 EXP COMPUTER, INC.
-0060F2 LASERGRAPHICS, INC.
-0060F3 Performance Analysis Broadband, Spirent plc
-0060F4 ADVANCED COMPUTER SOLUTIONS, Inc.
-0060F5 ICON WEST, INC.
-0060F6 NEXTEST COMMUNICATIONS PRODUCTS, INC.
-0060F7 DATAFUSION SYSTEMS
-0060F8 Loran International Technologies Inc.
-0060F9 DIAMOND LANE COMMUNICATIONS
-0060FA EDUCATIONAL TECHNOLOGY RESOURCES, INC.
-0060FB PACKETEER, INC.
-0060FC CONSERVATION THROUGH INNOVATION LTD.
-0060FD NetICs, Inc.
-0060FE LYNX SYSTEM DEVELOPERS, INC.
-0060FF QuVis, Inc.
-0070B0 M/A-COM INC. COMPANIES
-0070B3 DATA RECALL LTD.
-008000 MULTITECH SYSTEMS, INC.
-008001 PERIPHONICS CORPORATION
-008002 SATELCOM (UK) LTD
-008003 HYTEC ELECTRONICS LTD.
-008004 ANTLOW COMMUNICATIONS, LTD.
-008005 CACTUS COMPUTER INC.
-008006 COMPUADD CORPORATION
-008007 DLOG NC-SYSTEME
-008008 DYNATECH COMPUTER SYSTEMS
-008009 JUPITER SYSTEMS, INC.
-00800A JAPAN COMPUTER CORP.
-00800B CSK CORPORATION
-00800C VIDECOM LIMITED
-00800D VOSSWINKEL F.U.
-00800E ATLANTIX CORPORATION
-00800F STANDARD MICROSYSTEMS
-008010 COMMODORE INTERNATIONAL
-008011 DIGITAL SYSTEMS INT'L. INC.
-008012 INTEGRATED MEASUREMENT SYSTEMS
-008013 THOMAS-CONRAD CORPORATION
-008014 ESPRIT SYSTEMS
-008015 SEIKO SYSTEMS, INC.
-008016 WANDEL AND GOLTERMANN
-008017 PFU LIMITED
-008018 KOBE STEEL, LTD.
-008019 DAYNA COMMUNICATIONS, INC.
-00801A BELL ATLANTIC
-00801B KODIAK TECHNOLOGY
-00801C NEWPORT SYSTEMS SOLUTIONS
-00801D INTEGRATED INFERENCE MACHINES
-00801E XINETRON, INC.
-00801F KRUPP ATLAS ELECTRONIK GMBH
-008020 NETWORK PRODUCTS
-008021 Alcatel Canada Inc.
-008022 SCAN-OPTICS
-008023 INTEGRATED BUSINESS NETWORKS
-008024 KALPANA, INC.
-008025 STOLLMANN GMBH
-008026 NETWORK PRODUCTS CORPORATION
-008027 ADAPTIVE SYSTEMS, INC.
-008028 TRADPOST (HK) LTD
-008029 EAGLE TECHNOLOGY, INC.
-00802A TEST SYSTEMS & SIMULATIONS INC
-00802B INTEGRATED MARKETING CO
-00802C THE SAGE GROUP PLC
-00802D XYLOGICS INC
-00802E CASTLE ROCK COMPUTING
-00802F NATIONAL INSTRUMENTS CORP.
-008030 NEXUS ELECTRONICS
-008031 BASYS, CORP.
-008032 ACCESS CO., LTD.
-008033 FORMATION, INC.
-008034 SMT GOUPIL
-008035 TECHNOLOGY WORKS, INC.
-008036 REFLEX MANUFACTURING SYSTEMS
-008037 Ericsson Group
-008038 DATA RESEARCH & APPLICATIONS
-008039 ALCATEL STC AUSTRALIA
-00803A VARITYPER, INC.
-00803B APT COMMUNICATIONS, INC.
-00803C TVS ELECTRONICS LTD
-00803D SURIGIKEN CO.,  LTD.
-00803E SYNERNETICS
-00803F TATUNG COMPANY
-008040 JOHN FLUKE MANUFACTURING CO.
-008041 VEB KOMBINAT ROBOTRON
-008042 FORCE COMPUTERS
-008043 NETWORLD, INC.
-008044 SYSTECH COMPUTER CORP.
-008045 MATSUSHITA ELECTRIC IND. CO
-008046 UNIVERSITY OF TORONTO
-008047 IN-NET CORP.
-008048 COMPEX INCORPORATED
-008049 NISSIN ELECTRIC CO., LTD.
-00804A PRO-LOG
-00804B EAGLE TECHNOLOGIES PTY.LTD.
-00804C CONTEC CO., LTD.
-00804D CYCLONE MICROSYSTEMS, INC.
-00804E APEX COMPUTER COMPANY
-00804F DAIKIN INDUSTRIES, LTD.
-008050 ZIATECH CORPORATION
-008051 FIBERMUX
-008052 TECHNICALLY ELITE CONCEPTS
-008053 INTELLICOM, INC.
-008054 FRONTIER TECHNOLOGIES CORP.
-008055 FERMILAB
-008056 SPHINX ELEKTRONIK GMBH
-008057 ADSOFT, LTD.
-008058 PRINTER SYSTEMS CORPORATION
-008059 STANLEY ELECTRIC CO., LTD
-00805A TULIP COMPUTERS INTERNAT'L B.V
-00805B CONDOR SYSTEMS, INC.
-00805C AGILIS CORPORATION
-00805D CANSTAR
-00805E LSI LOGIC CORPORATION
-00805F COMPAQ COMPUTER CORPORATION
-008060 NETWORK INTERFACE CORPORATION
-008061 LITTON SYSTEMS, INC.
-008062 INTERFACE  CO.
-008063 RICHARD HIRSCHMANN GMBH & CO.
-008064 WYSE TECHNOLOGY
-008065 CYBERGRAPHIC SYSTEMS PTY LTD.
-008066 ARCOM CONTROL SYSTEMS, LTD.
-008067 SQUARE D COMPANY
-008068 YAMATECH SCIENTIFIC LTD.
-008069 COMPUTONE SYSTEMS
-00806A ERI (EMPAC RESEARCH INC.)
-00806B SCHMID TELECOMMUNICATION
-00806C CEGELEC PROJECTS LTD
-00806D CENTURY SYSTEMS CORP.
-00806E NIPPON STEEL CORPORATION
-00806F ONELAN LTD.
-008070 COMPUTADORAS MICRON
-008071 SAI TECHNOLOGY
-008072 MICROPLEX SYSTEMS LTD.
-008073 DWB ASSOCIATES
-008074 FISHER CONTROLS
-008075 PARSYTEC GMBH
-008076 MCNC
-008077 BROTHER INDUSTRIES, LTD.
-008078 PRACTICAL PERIPHERALS, INC.
-008079 MICROBUS DESIGNS LTD.
-00807A AITECH SYSTEMS LTD.
-00807B ARTEL COMMUNICATIONS CORP.
-00807C FIBERCOM, INC.
-00807D EQUINOX SYSTEMS INC.
-00807E SOUTHERN PACIFIC LTD.
-00807F DY-4 INCORPORATED
-008080 DATAMEDIA CORPORATION
-008081 KENDALL SQUARE RESEARCH CORP.
-008082 PEP MODULAR COMPUTERS GMBH
-008083 AMDAHL
-008084 THE CLOUD INC.
-008085 H-THREE SYSTEMS CORPORATION
-008086 COMPUTER GENERATION INC.
-008087 OKI ELECTRIC INDUSTRY CO., LTD
-008088 VICTOR COMPANY OF JAPAN, LTD.
-008089 TECNETICS (PTY) LTD.
-00808A SUMMIT MICROSYSTEMS CORP.
-00808B DACOLL LIMITED
-00808C NetScout Systems, Inc.
-00808D WESTCOAST TECHNOLOGY B.V.
-00808E RADSTONE TECHNOLOGY
-00808F C. ITOH ELECTRONICS, INC.
-008090 MICROTEK INTERNATIONAL, INC.
-008091 TOKYO ELECTRIC CO.,LTD
-008092 JAPAN COMPUTER INDUSTRY, INC.
-008093 XYRON CORPORATION
-008094 ALFA LAVAL AUTOMATION AB
-008095 BASIC MERTON HANDELSGES.M.B.H.
-008096 HUMAN DESIGNED SYSTEMS, INC.
-008097 CENTRALP AUTOMATISMES
-008098 TDK CORPORATION
-008099 KLOCKNER MOELLER IPC
-00809A NOVUS NETWORKS LTD
-00809B JUSTSYSTEM CORPORATION
-00809C LUXCOM, INC.
-00809D Commscraft Ltd.
-00809E DATUS GMBH
-00809F ALCATEL BUSINESS SYSTEMS
-0080A0 EDISA HEWLETT PACKARD S/A
-0080A1 MICROTEST, INC.
-0080A2 CREATIVE ELECTRONIC SYSTEMS
-0080A3 LANTRONIX
-0080A4 LIBERTY ELECTRONICS
-0080A5 SPEED INTERNATIONAL
-0080A6 REPUBLIC TECHNOLOGY, INC.
-0080A7 MEASUREX CORP.
-0080A8 VITACOM CORPORATION
-0080A9 CLEARPOINT RESEARCH
-0080AA MAXPEED
-0080AB DUKANE NETWORK INTEGRATION
-0080AC IMLOGIX, DIVISION OF GENESYS
-0080AD CNET TECHNOLOGY, INC.
-0080AE HUGHES NETWORK SYSTEMS
-0080AF ALLUMER CO., LTD.
-0080B0 ADVANCED INFORMATION
-0080B1 SOFTCOM A/S
-0080B2 NETWORK EQUIPMENT TECHNOLOGIES
-0080B3 AVAL DATA CORPORATION
-0080B4 SOPHIA SYSTEMS
-0080B5 UNITED NETWORKS INC.
-0080B6 THEMIS COMPUTER
-0080B7 STELLAR COMPUTER
-0080B8 BUG, INCORPORATED
-0080B9 ARCHE TECHNOLIGIES INC.
-0080BA SPECIALIX (ASIA) PTE, LTD
-0080BB HUGHES LAN SYSTEMS
-0080BC HITACHI ENGINEERING CO., LTD
-0080BD THE FURUKAWA ELECTRIC CO., LTD
-0080BE ARIES RESEARCH
-0080BF TAKAOKA ELECTRIC MFG. CO. LTD.
-0080C0 PENRIL DATACOMM
-0080C1 LANEX CORPORATION
-0080C2 IEEE 802.1 COMMITTEE
-0080C3 BICC INFORMATION SYSTEMS & SVC
-0080C4 DOCUMENT TECHNOLOGIES, INC.
-0080C5 NOVELLCO DE MEXICO
-0080C6 NATIONAL DATACOMM CORPORATION
-0080C7 XIRCOM
-0080C8 D-LINK SYSTEMS, INC.
-0080C9 ALBERTA MICROELECTRONIC CENTRE
-0080CA NETCOM RESEARCH INCORPORATED
-0080CB FALCO DATA PRODUCTS
-0080CC MICROWAVE BYPASS SYSTEMS
-0080CD MICRONICS COMPUTER, INC.
-0080CE BROADCAST TELEVISION SYSTEMS
-0080CF EMBEDDED PERFORMANCE INC.
-0080D0 COMPUTER PERIPHERALS, INC.
-0080D1 KIMTRON CORPORATION
-0080D2 SHINNIHONDENKO CO., LTD.
-0080D3 SHIVA CORP.
-0080D4 CHASE RESEARCH LTD.
-0080D5 CADRE TECHNOLOGIES
-0080D6 NUVOTECH, INC.
-0080D7 Fantum Engineering
-0080D8 NETWORK PERIPHERALS INC.
-0080D9 EMK ELEKTRONIK
-0080DA BRUEL & KJAER
-0080DB GRAPHON CORPORATION
-0080DC PICKER INTERNATIONAL
-0080DD GMX INC/GIMIX
-0080DE GIPSI S.A.
-0080DF ADC CODENOLL TECHNOLOGY CORP.
-0080E0 XTP SYSTEMS, INC.
-0080E1 STMICROELECTRONICS
-0080E2 T.D.I. CO., LTD.
-0080E3 CORAL NETWORK CORPORATION
-0080E4 NORTHWEST DIGITAL SYSTEMS, INC
-0080E5 MYLEX CORPORATION
-0080E6 PEER NETWORKS, INC.
-0080E7 LYNWOOD SCIENTIFIC DEV. LTD.
-0080E8 CUMULUS CORPORATIION
-0080E9 Madge Ltd.
-0080EA ADVA Optical Networking Ltd.
-0080EB COMPCONTROL B.V.
-0080EC SUPERCOMPUTING SOLUTIONS, INC.
-0080ED IQ TECHNOLOGIES, INC.
-0080EE THOMSON CSF
-0080EF RATIONAL
-0080F0 Panasonic Communications Co., Ltd.
-0080F1 OPUS SYSTEMS
-0080F2 RAYCOM SYSTEMS INC
-0080F3 SUN ELECTRONICS CORP.
-0080F4 TELEMECANIQUE ELECTRIQUE
-0080F5 QUANTEL LTD
-0080F6 SYNERGY MICROSYSTEMS
-0080F7 ZENITH ELECTRONICS
-0080F8 MIZAR, INC.
-0080F9 HEURIKON CORPORATION
-0080FA RWT GMBH
-0080FB BVM LIMITED
-0080FC AVATAR CORPORATION
-0080FD EXSCEED CORPRATION
-0080FE AZURE TECHNOLOGIES, INC.
-0080FF SOC. DE TELEINFORMATIQUE RTC
-009000 DIAMOND MULTIMEDIA
-009001 NISHIMU ELECTRONICS INDUSTRIES CO., LTD.
-009002 ALLGON AB
-009003 APLIO
-009004 3COM EUROPE LTD.
-009005 PROTECH SYSTEMS CO., LTD.
-009006 HAMAMATSU PHOTONICS K.K.
-009007 DOMEX TECHNOLOGY CORP.
-009008 HanA Systems Inc.
-009009 i Controls, Inc.
-00900A PROTON ELECTRONIC INDUSTRIAL CO., LTD.
-00900B LANNER ELECTRONICS, INC.
-00900C CISCO SYSTEMS, INC.
-00900D OVERLAND DATA INC.
-00900E HANDLINK TECHNOLOGIES, INC.
-00900F KAWASAKI HEAVY INDUSTRIES, LTD
-009010 SIMULATION LABORATORIES, INC.
-009011 WAVTrace, Inc.
-009012 GLOBESPAN SEMICONDUCTOR, INC.
-009013 SAMSAN CORP.
-009014 ROTORK INSTRUMENTS, LTD.
-009015 CENTIGRAM COMMUNICATIONS CORP.
-009016 ZAC
-009017 ZYPCOM, INC.
-009018 ITO ELECTRIC INDUSTRY CO, LTD.
-009019 HERMES ELECTRONICS CO., LTD.
-00901A UNISPHERE SOLUTIONS
-00901B DIGITAL CONTROLS
-00901C mps Software Gmbh
-00901D PEC (NZ) LTD.
-00901E SELESTA INGEGNE RIA S.P.A.
-00901F ADTEC PRODUCTIONS, INC.
-009020 PHILIPS ANALYTICAL X-RAY B.V.
-009021 CISCO SYSTEMS, INC.
-009022 IVEX
-009023 ZILOG INC.
-009024 PIPELINKS, INC.
-009025 VISION SYSTEMS LTD. PTY
-009026 ADVANCED SWITCHING COMMUNICATIONS, INC.
-009027 INTEL CORPORATION
-009028 NIPPON SIGNAL CO., LTD.
-009029 CRYPTO AG
-00902A COMMUNICATION DEVICES, INC.
-00902B CISCO SYSTEMS, INC.
-00902C DATA & CONTROL EQUIPMENT LTD.
-00902D DATA ELECTRONICS (AUST.) PTY, LTD.
-00902E NAMCO LIMITED
-00902F NETCORE SYSTEMS, INC.
-009030 HONEYWELL-DATING
-009031 MYSTICOM, LTD.
-009032 PELCOMBE GROUP LTD.
-009033 INNOVAPHONE GmbH
-009034 IMAGIC, INC.
-009035 ALPHA TELECOM, INC.
-009036 ens, inc.
-009037 ACUCOMM, INC.
-009038 FOUNTAIN TECHNOLOGIES, INC.
-009039 SHASTA NETWORKS
-00903A NIHON MEDIA TOOL INC.
-00903B TriEMS Research Lab, Inc.
-00903C ATLANTIC NETWORK SYSTEMS
-00903D BIOPAC SYSTEMS, INC.
-00903E N.V. PHILIPS INDUSTRIAL ACTIVITIES
-00903F AZTEC RADIOMEDIA
-009040 Siemens Network Convergence LLC
-009041 APPLIED DIGITAL ACCESS
-009042 ECCS, Inc.
-009043 NICHIBEI DENSHI CO., LTD.
-009044 ASSURED DIGITAL, INC.
-009045 Marconi Communications
-009046 DEXDYNE, LTD.
-009047 GIGA FAST E. LTD.
-009048 ZEAL CORPORATION
-009049 ENTRIDIA CORPORATION
-00904A CONCUR SYSTEM TECHNOLOGIES
-00904B GemTek Technology Co., Ltd.
-00904C EPIGRAM, INC.
-00904D SPEC S.A.
-00904E DELEM BV
-00904F ABB POWER T&D COMPANY, INC.
-009050 TELESTE OY
-009051 ULTIMATE TECHNOLOGY CORP.
-009052 SELCOM ELETTRONICA S.R.L.
-009053 DAEWOO ELECTRONICS CO., LTD.
-009054 INNOVATIVE SEMICONDUCTORS, INC
-009055 PARKER HANNIFIN CORPORATION COMPUMOTOR DIVISION
-009056 TELESTREAM, INC.
-009057 AANetcom, Inc.
-009058 Ultra Electronics Ltd., Command and Control Systems
-009059 TELECOM DEVICE K.K.
-00905A DEARBORN GROUP, INC.
-00905B RAYMOND AND LAE ENGINEERING
-00905C EDMI
-00905D NETCOM SICHERHEITSTECHNIK GmbH
-00905E RAULAND-BORG CORPORATION
-00905F CISCO SYSTEMS, INC.
-009060 SYSTEM CREATE CORP.
-009061 PACIFIC RESEARCH & ENGINEERING CORPORATION
-009062 ICP VORTEX COMPUTERSYSTEME GmbH
-009063 COHERENT COMMUNICATIONS SYSTEMS CORPORATION
-009064 THOMSON BROADCAST SYSTEMS
-009065 FINISAR CORPORATION
-009066 Troika Networks, Inc.
-009067 WalkAbout Computers, Inc.
-009068 DVT CORP.
-009069 JUNIPER NETWORKS, INC.
-00906A TURNSTONE SYSTEMS, INC.
-00906B APPLIED RESOURCES, INC.
-00906C GWT GLOBAL WEIGHING TECHNOLOGIES GmbH
-00906D CISCO SYSTEMS, INC.
-00906E PRAXON, INC.
-00906F CISCO SYSTEMS, INC.
-009070 NEO NETWORKS, INC.
-009071 Applied Innovation Inc.
-009072 SIMRAD AS
-009073 GAIO TECHNOLOGY
-009074 ARGON NETWORKS, INC.
-009075 NEC DO BRASIL S.A.
-009076 FMT AIRCRAFT GATE SUPPORT SYSTEMS AB
-009077 ADVANCED FIBRE COMMUNICATIONS
-009078 MER TELEMANAGEMENT SOLUTIONS, LTD.
-009079 ClearOne, Inc.
-00907A SPECTRALINK CORP.
-00907B E-TECH, INC.
-00907C DIGITALCAST, INC.
-00907D Lake Communications
-00907E VETRONIX CORP.
-00907F WatchGuard Technologies, Inc.
-009080 NOT LIMITED, INC.
-009081 ALOHA NETWORKS, INC.
-009082 FORCE INSTITUTE
-009083 TURBO COMMUNICATION, INC.
-009084 ATECH SYSTEM
-009085 GOLDEN ENTERPRISES, INC.
-009086 CISCO SYSTEMS, INC.
-009087 ITIS
-009088 BAXALL SECURITY LTD.
-009089 SOFTCOM MICROSYSTEMS, INC.
-00908A BAYLY COMMUNICATIONS, INC.
-00908B CELL COMPUTING, INC.
-00908C ETREND ELECTRONICS, INC.
-00908D VICKERS ELECTRONICS SYSTEMS
-00908E Nortel Networks Broadband Access
-00908F AUDIO CODES LTD.
-009090 I-BUS
-009091 DigitalScape, Inc.
-009092 CISCO SYSTEMS, INC.
-009093 NANAO CORPORATION
-009094 OSPREY TECHNOLOGIES, INC.
-009095 UNIVERSAL AVIONICS
-009096 ASKEY COMPUTER CORP.
-009097 SYCAMORE NETWORKS
-009098 SBC DESIGNS, INC.
-009099 ALLIED TELESIS, K.K.
-00909A ONE WORLD SYSTEMS, INC.
-00909B MARKPOINT AB
-00909C Terayon Communications Systems
-00909D GSE SYSTEMS, INC.
-00909E Critical IO, LLC
-00909F DIGI-DATA CORPORATION
-0090A0 8X8 INC.
-0090A1 FLYING PIG SYSTEMS, LTD.
-0090A2 CYBERTAN TECHNOLOGY, INC.
-0090A3 Corecess Inc.
-0090A4 ALTIGA NETWORKS
-0090A5 SPECTRA LOGIC
-0090A6 CISCO SYSTEMS, INC.
-0090A7 CLIENTEC CORPORATION
-0090A8 NineTiles Networks, Ltd.
-0090A9 WESTERN DIGITAL
-0090AA INDIGO ACTIVE VISION SYSTEMS LIMITED
-0090AB CISCO SYSTEMS, INC.
-0090AC OPTIVISION, INC.
-0090AD ASPECT ELECTRONICS, INC.
-0090AE ITALTEL S.p.A.
-0090AF J. MORITA MFG. CORP.
-0090B0 VADEM
-0090B1 CISCO SYSTEMS, INC.
-0090B2 AVICI SYSTEMS INC.
-0090B3 AGRANAT SYSTEMS
-0090B4 WILLOWBROOK TECHNOLOGIES
-0090B5 NIKON CORPORATION
-0090B6 FIBEX SYSTEMS
-0090B7 DIGITAL LIGHTWAVE, INC.
-0090B8 ROHDE & SCHWARZ GMBH & CO. KG
-0090B9 BERAN INSTRUMENTS LTD.
-0090BA VALID NETWORKS, INC.
-0090BB TAINET COMMUNICATION SYSTEM Corp.
-0090BC TELEMANN CO., LTD.
-0090BD OMNIA COMMUNICATIONS, INC.
-0090BE IBC/INTEGRATED BUSINESS COMPUTERS
-0090BF CISCO SYSTEMS, INC.
-0090C0 K.J. LAW ENGINEERS, INC.
-0090C1 Peco II, Inc.
-0090C2 JK microsystems, Inc.
-0090C3 TOPIC SEMICONDUCTOR CORP.
-0090C4 JAVELIN SYSTEMS, INC.
-0090C5 INTERNET MAGIC, INC.
-0090C6 OPTIM SYSTEMS, INC.
-0090C7 ICOM INC.
-0090C8 WAVERIDER COMMUNICATIONS (CANADA) INC.
-0090C9 DPAC Technologies
-0090CA ACCORD VIDEO TELECOMMUNICATIONS, LTD.
-0090CB Wireless OnLine, Inc.
-0090CC PLANET COMMUNICATIONS, INC.
-0090CD ENT-EMPRESA NACIONAL DE TELECOMMUNICACOES, S.A.
-0090CE TETRA GmbH
-0090CF NORTEL
-0090D0 Thomson Belgium
-0090D1 LEICHU ENTERPRISE CO., LTD.
-0090D2 ARTEL VIDEO SYSTEMS
-0090D3 GIESECKE & DEVRIENT GmbH
-0090D4 BindView Development Corp.
-0090D5 EUPHONIX, INC.
-0090D6 CRYSTAL GROUP
-0090D7 NetBoost Corp.
-0090D8 WHITECROSS SYSTEMS
-0090D9 CISCO SYSTEMS, INC.
-0090DA DYNARC, INC.
-0090DB NEXT LEVEL COMMUNICATIONS
-0090DC TECO INFORMATION SYSTEMS
-0090DD THE MIHARU COMMUNICATIONS CO., LTD.
-0090DE CARDKEY SYSTEMS, INC.
-0090DF MITSUBISHI CHEMICAL AMERICA, INC.
-0090E0 SYSTRAN CORP.
-0090E1 TELENA S.P.A.
-0090E2 DISTRIBUTED PROCESSING TECHNOLOGY
-0090E3 AVEX ELECTRONICS INC.
-0090E4 NEC AMERICA, INC.
-0090E5 TEKNEMA, INC.
-0090E6 ACER LABORATORIES, INC.
-0090E7 HORSCH ELEKTRONIK AG
-0090E8 MOXA TECHNOLOGIES CORP., LTD.
-0090E9 JANZ COMPUTER AG
-0090EA ALPHA TECHNOLOGIES, INC.
-0090EB SENTRY TELECOM SYSTEMS
-0090EC PYRESCOM
-0090ED CENTRAL SYSTEM RESEARCH CO., LTD.
-0090EE PERSONAL COMMUNICATIONS TECHNOLOGIES
-0090EF INTEGRIX, INC.
-0090F0 HARMONIC LIGHTWAVES, LTD.
-0090F1 DOT HILL SYSTEMS CORPORATION
-0090F2 CISCO SYSTEMS, INC.
-0090F3 ASPECT COMMUNICATIONS
-0090F4 LIGHTNING INSTRUMENTATION
-0090F5 CLEVO CO.
-0090F6 ESCALATE NETWORKS, INC.
-0090F7 NBASE COMMUNICATIONS LTD.
-0090F8 MEDIATRIX TELECOM
-0090F9 LEITCH
-0090FA GigaNet, Inc.
-0090FB PORTWELL, INC.
-0090FC NETWORK COMPUTING DEVICES
-0090FD CopperCom, Inc.
-0090FE ELECOM CO., LTD.  (LANEED DIV.)
-0090FF TELLUS TECHNOLOGY INC.
-0091D6 Crystal Group, Inc.
-009D8E CARDIAC RECORDERS, INC.
-00A000 CENTILLION NETWORKS, INC.
-00A001 WATKINS-JOHNSON COMPANY
-00A002 LEEDS & NORTHRUP AUSTRALIA PTY LTD
-00A003 STAEFA CONTROL SYSTEM
-00A004 NETPOWER, INC.
-00A005 DANIEL INSTRUMENTS, LTD.
-00A006 IMAGE DATA PROCESSING SYSTEM GROUP
-00A007 APEXX TECHNOLOGY, INC.
-00A008 NETCORP
-00A009 WHITETREE NETWORK
-00A00A R.D.C. COMMUNICATION
-00A00B COMPUTEX CO., LTD.
-00A00C KINGMAX TECHNOLOGY, INC.
-00A00D THE PANDA PROJECT
-00A00E VISUAL NETWORKS, INC.
-00A00F Broadband Technologies
-00A010 SYSLOGIC DATENTECHNIK AG
-00A011 MUTOH INDUSTRIES LTD.
-00A012 B.A.T.M. ADVANCED TECHNOLOGIES
-00A013 TELTREND LTD.
-00A014 CSIR
-00A015 WYLE
-00A016 MICROPOLIS CORP.
-00A017 J B M CORPORATION
-00A018 CREATIVE CONTROLLERS, INC.
-00A019 NEBULA CONSULTANTS, INC.
-00A01A BINAR ELEKTRONIK AB
-00A01B PREMISYS COMMUNICATIONS, INC.
-00A01C NASCENT NETWORKS CORPORATION
-00A01D SIXNET
-00A01E EST CORPORATION
-00A01F TRICORD SYSTEMS, INC.
-00A020 CITICORP/TTI
-00A021 GENERAL DYNAMICS-
-00A022 CENTRE FOR DEVELOPMENT OF ADVANCED COMPUTING
-00A023 APPLIED CREATIVE TECHNOLOGY, INC.
-00A024 3COM CORPORATION
-00A025 REDCOM LABS INC.
-00A026 TELDAT, S.A.
-00A027 FIREPOWER SYSTEMS, INC.
-00A028 CONNER PERIPHERALS
-00A029 COULTER CORPORATION
-00A02A TRANCELL SYSTEMS
-00A02B TRANSITIONS RESEARCH CORP.
-00A02C interWAVE Communications
-00A02D 1394 Trade Association
-00A02E BRAND COMMUNICATIONS, LTD.
-00A02F PIRELLI CAVI
-00A030 CAPTOR NV/SA
-00A031 HAZELTINE CORPORATION, MS 1-17
-00A032 GES SINGAPORE PTE. LTD.
-00A033 imc MeBsysteme GmbH
-00A034 AXEL
-00A035 CYLINK CORPORATION
-00A036 APPLIED NETWORK TECHNOLOGY
-00A037 DATASCOPE CORPORATION
-00A038 EMAIL ELECTRONICS
-00A039 ROSS TECHNOLOGY, INC.
-00A03A KUBOTEK CORPORATION
-00A03B TOSHIN ELECTRIC CO., LTD.
-00A03C EG&G NUCLEAR INSTRUMENTS
-00A03D OPTO-22
-00A03E ATM FORUM
-00A03F COMPUTER SOCIETY MICROPROCESSOR & MICROPROCESSOR STANDARDS C
-00A040 APPLE COMPUTER
-00A041 LEYBOLD-INFICON
-00A042 SPUR PRODUCTS CORP.
-00A043 AMERICAN TECHNOLOGY LABS, INC.
-00A044 NTT IT CO., LTD.
-00A045 PHOENIX CONTACT GMBH & CO.
-00A046 SCITEX CORP. LTD.
-00A047 INTEGRATED FITNESS CORP.
-00A048 QUESTECH, LTD.
-00A049 DIGITECH INDUSTRIES, INC.
-00A04A NISSHIN ELECTRIC CO., LTD.
-00A04B TFL LAN INC.
-00A04C INNOVATIVE SYSTEMS & TECHNOLOGIES, INC.
-00A04D EDA INSTRUMENTS, INC.
-00A04E VOELKER TECHNOLOGIES, INC.
-00A04F AMERITEC CORP.
-00A050 CYPRESS SEMICONDUCTOR
-00A051 ANGIA COMMUNICATIONS. INC.
-00A052 STANILITE ELECTRONICS PTY. LTD
-00A053 COMPACT DEVICES, INC.
-00A055 Data Device Corporation
-00A056 MICROPROSS
-00A057 LANCOM Systems GmbH
-00A058 GLORY, LTD.
-00A059 HAMILTON HALLMARK
-00A05A KOFAX IMAGE PRODUCTS
-00A05B MARQUIP, INC.
-00A05C INVENTORY CONVERSION, INC./
-00A05D CS COMPUTER SYSTEME GmbH
-00A05E MYRIAD LOGIC INC.
-00A05F BTG ENGINEERING BV
-00A060 ACER PERIPHERALS, INC.
-00A061 PURITAN BENNETT
-00A062 AES PRODATA
-00A063 JRL SYSTEMS, INC.
-00A064 KVB/ANALECT
-00A065 NEXLAND, INC.
-00A066 ISA CO., LTD.
-00A067 NETWORK SERVICES GROUP
-00A068 BHP LIMITED
-00A069 Symmetricom, Inc.
-00A06A Verilink Corporation
-00A06B DMS DORSCH MIKROSYSTEM GMBH
-00A06C SHINDENGEN ELECTRIC MFG. CO., LTD.
-00A06D MANNESMANN TALLY CORPORATION
-00A06E AUSTRON, INC.
-00A06F THE APPCON GROUP, INC.
-00A070 COASTCOM
-00A071 VIDEO LOTTERY TECHNOLOGIES,INC
-00A072 OVATION SYSTEMS LTD.
-00A073 COM21, INC.
-00A074 PERCEPTION TECHNOLOGY
-00A075 MICRON TECHNOLOGY, INC.
-00A076 CARDWARE LAB, INC.
-00A077 FUJITSU NEXION, INC.
-00A078 Marconi Communications
-00A079 ALPS ELECTRIC (USA), INC.
-00A07A ADVANCED PERIPHERALS TECHNOLOGIES, INC.
-00A07B DAWN COMPUTER INCORPORATION
-00A07C TONYANG NYLON CO., LTD.
-00A07D SEEQ TECHNOLOGY, INC.
-00A07E AVID TECHNOLOGY, INC.
-00A07F GSM-SYNTEL, LTD.
-00A080 ANTARES MICROSYSTEMS
-00A081 ALCATEL DATA NETWORKS
-00A082 NKT ELEKTRONIK A/S
-00A083 ASIMMPHONY TURKEY
-00A084 DATAPLEX PTY. LTD.
-00A086 AMBER WAVE SYSTEMS, INC.
-00A087 Zarlink Semiconductor Ltd.
-00A088 ESSENTIAL COMMUNICATIONS
-00A089 XPOINT TECHNOLOGIES, INC.
-00A08A BROOKTROUT TECHNOLOGY, INC.
-00A08B ASTON ELECTRONIC DESIGNS LTD.
-00A08C MultiMedia LANs, Inc.
-00A08D JACOMO CORPORATION
-00A08E Nokia Internet Communications
-00A08F DESKNET SYSTEMS, INC.
-00A090 TimeStep Corporation
-00A091 APPLICOM INTERNATIONAL
-00A092 H. BOLLMANN MANUFACTURERS, LTD
-00A093 B/E AEROSPACE, Inc.
-00A094 COMSAT CORPORATION
-00A095 ACACIA NETWORKS, INC.
-00A096 MITUMI ELECTRIC CO., LTD.
-00A097 JC INFORMATION SYSTEMS
-00A098 NETWORK APPLIANCE CORP.
-00A099 K-NET LTD.
-00A09A NIHON KOHDEN AMERICA
-00A09B QPSX COMMUNICATIONS, LTD.
-00A09C Xyplex, Inc.
-00A09D JOHNATHON FREEMAN TECHNOLOGIES
-00A09E ICTV
-00A09F COMMVISION CORP.
-00A0A0 COMPACT DATA, LTD.
-00A0A1 EPIC DATA INC.
-00A0A2 DIGICOM S.P.A.
-00A0A3 RELIABLE POWER METERS
-00A0A4 MICROS SYSTEMS, INC.
-00A0A5 TEKNOR MICROSYSTEME, INC.
-00A0A6 M.I. SYSTEMS, K.K.
-00A0A7 VORAX CORPORATION
-00A0A8 RENEX CORPORATION
-00A0A9 GN NETTEST (CANADA) NAVTEL DIVISION
-00A0AA SPACELABS MEDICAL
-00A0AB NETCS INFORMATIONSTECHNIK GMBH
-00A0AC GILAT SATELLITE NETWORKS, LTD.
-00A0AD MARCONI SPA
-00A0AE NUCOM SYSTEMS, INC.
-00A0AF WMS INDUSTRIES
-00A0B0 I-O DATA DEVICE, INC.
-00A0B1 FIRST VIRTUAL CORPORATION
-00A0B2 SHIMA SEIKI
-00A0B3 ZYKRONIX
-00A0B4 TEXAS MICROSYSTEMS, INC.
-00A0B5 3H TECHNOLOGY
-00A0B6 SANRITZ AUTOMATION CO., LTD.
-00A0B7 CORDANT, INC.
-00A0B8 SYMBIOS LOGIC INC.
-00A0B9 EAGLE TECHNOLOGY, INC.
-00A0BA PATTON ELECTRONICS CO.
-00A0BB HILAN GMBH
-00A0BC VIASAT, INCORPORATED
-00A0BD I-TECH CORP.
-00A0BE INTEGRATED CIRCUIT SYSTEMS, INC. COMMUNICATIONS GROUP
-00A0BF WIRELESS DATA GROUP MOTOROLA
-00A0C0 DIGITAL LINK CORP.
-00A0C1 ORTIVUS MEDICAL AB
-00A0C2 R.A. SYSTEMS CO., LTD.
-00A0C3 UNICOMPUTER GMBH
-00A0C4 CRISTIE ELECTRONICS LTD.
-00A0C5 ZYXEL COMMUNICATION
-00A0C6 QUALCOMM INCORPORATED
-00A0C7 TADIRAN TELECOMMUNICATIONS
-00A0C8 ADTRAN INC.
-00A0C9 INTEL CORPORATION - HF1-06
-00A0CA FUJITSU DENSO LTD.
-00A0CB ARK TELECOMMUNICATIONS, INC.
-00A0CC LITE-ON COMMUNICATIONS, INC.
-00A0CD DR. JOHANNES HEIDENHAIN GmbH
-00A0CE ASTROCOM CORPORATION
-00A0CF SOTAS, INC.
-00A0D0 TEN X TECHNOLOGY, INC.
-00A0D1 INVENTEC CORPORATION
-00A0D2 ALLIED TELESIS INTERNATIONAL CORPORATION
-00A0D3 INSTEM COMPUTER SYSTEMS, LTD.
-00A0D4 RADIOLAN,  INC.
-00A0D5 SIERRA WIRELESS INC.
-00A0D6 SBE, INC.
-00A0D7 KASTEN CHASE APPLIED RESEARCH
-00A0D8 SPECTRA - TEK
-00A0D9 CONVEX COMPUTER CORPORATION
-00A0DA INTEGRATED SYSTEMS Technology, Inc.
-00A0DB FISHER & PAYKEL PRODUCTION
-00A0DC O.N. ELECTRONIC CO., LTD.
-00A0DD AZONIX CORPORATION
-00A0DE YAMAHA CORPORATION
-00A0DF STS TECHNOLOGIES, INC.
-00A0E0 TENNYSON TECHNOLOGIES PTY LTD
-00A0E1 WESTPORT RESEARCH ASSOCIATES, INC.
-00A0E2 KEISOKU GIKEN CORP.
-00A0E3 XKL SYSTEMS CORP.
-00A0E4 OPTIQUEST
-00A0E5 NHC COMMUNICATIONS
-00A0E6 DIALOGIC CORPORATION
-00A0E7 CENTRAL DATA CORPORATION
-00A0E8 REUTERS HOLDINGS PLC
-00A0E9 ELECTRONIC RETAILING SYSTEMS INTERNATIONAL
-00A0EA ETHERCOM CORP.
-00A0EB Encore Networks
-00A0EC TRANSMITTON LTD.
-00A0ED PRI AUTOMATION
-00A0EE NASHOBA NETWORKS
-00A0EF LUCIDATA LTD.
-00A0F0 TORONTO MICROELECTRONICS INC.
-00A0F1 MTI
-00A0F2 INFOTEK COMMUNICATIONS, INC.
-00A0F3 STAUBLI
-00A0F4 GE
-00A0F5 RADGUARD LTD.
-00A0F6 AutoGas Systems Inc.
-00A0F7 V.I COMPUTER CORP.
-00A0F8 SYMBOL TECHNOLOGIES, INC.
-00A0F9 BINTEC COMMUNICATIONS GMBH
-00A0FA Marconi Communication GmbH
-00A0FB TORAY ENGINEERING CO., LTD.
-00A0FC IMAGE SCIENCES, INC.
-00A0FD SCITEX DIGITAL PRINTING, INC.
-00A0FE BOSTON TECHNOLOGY, INC.
-00A0FF TELLABS OPERATIONS, INC.
-00AA00 INTEL CORPORATION
-00AA01 INTEL CORPORATION
-00AA02 INTEL CORPORATION
-00AA3C OLIVETTI TELECOM SPA (OLTECO)
-00B009 Grass Valley Group
-00B017 InfoGear Technology Corp.
-00B019 Casi-Rusco
-00B01C Westport Technologies
-00B01E Rantic Labs, Inc.
-00B02A ORSYS GmbH
-00B02D ViaGate Technologies, Inc.
-00B03B HiQ Networks
-00B048 Marconi Communications Inc.
-00B04A Cisco Systems, Inc.
-00B052 Intellon Corporation
-00B064 Cisco Systems, Inc.
-00B069 Honewell Oy
-00B06D Jones Futurex Inc.
-00B080 Mannesmann Ipulsys B.V.
-00B086 LocSoft Limited
-00B08E Cisco Systems, Inc.
-00B091 Transmeta Corp.
-00B094 Alaris, Inc.
-00B09A Morrow Technologies Corp.
-00B09D Point Grey Research Inc.
-00B0AC SIAE-Microelettronica S.p.A.
-00B0AE Symmetricom
-00B0B3 Xstreamis PLC
-00B0C2 Cisco Systems, Inc.
-00B0C7 Tellabs Operations, Inc.
-00B0CE TECHNOLOGY RESCUE
-00B0D0 Dell Computer Corp.
-00B0DB Nextcell, Inc.
-00B0DF Reliable Data Technology, Inc.
-00B0E7 British Federal Ltd.
-00B0EC EACEM
-00B0EE Ajile Systems, Inc.
-00B0F0 CALY NETWORKS
-00B0F5 NetWorth Technologies, Inc.
-00BB01 OCTOTHORPE CORP.
-00BBF0 UNGERMANN-BASS INC.
-00C000 LANOPTICS, LTD.
-00C001 DIATEK PATIENT MANAGMENT
-00C002 SERCOMM CORPORATION
-00C003 GLOBALNET COMMUNICATIONS
-00C004 JAPAN BUSINESS COMPUTER CO.LTD
-00C005 LIVINGSTON ENTERPRISES, INC.
-00C006 NIPPON AVIONICS CO., LTD.
-00C007 PINNACLE DATA SYSTEMS, INC.
-00C008 SECO SRL
-00C009 KT TECHNOLOGY (S) PTE LTD
-00C00A MICRO CRAFT
-00C00B NORCONTROL A.S.
-00C00C RELIA TECHNOLGIES
-00C00D ADVANCED LOGIC RESEARCH, INC.
-00C00E PSITECH, INC.
-00C00F QUANTUM SOFTWARE SYSTEMS LTD.
-00C010 HIRAKAWA HEWTECH CORP.
-00C011 INTERACTIVE COMPUTING DEVICES
-00C012 NETSPAN CORPORATION
-00C013 NETRIX
-00C014 TELEMATICS CALABASAS INT'L,INC
-00C015 NEW MEDIA CORPORATION
-00C016 ELECTRONIC THEATRE CONTROLS
-00C017 FORTE NETWORKS
-00C018 LANART CORPORATION
-00C019 LEAP TECHNOLOGY, INC.
-00C01A COROMETRICS MEDICAL SYSTEMS
-00C01B SOCKET COMMUNICATIONS, INC.
-00C01C INTERLINK COMMUNICATIONS LTD.
-00C01D GRAND JUNCTION NETWORKS, INC.
-00C01E LA FRANCAISE DES JEUX
-00C01F S.E.R.C.E.L.
-00C020 ARCO ELECTRONIC, CONTROL LTD.
-00C021 NETEXPRESS
-00C022 LASERMASTER TECHNOLOGIES, INC.
-00C023 TUTANKHAMON ELECTRONICS
-00C024 EDEN SISTEMAS DE COMPUTACAO SA
-00C025 DATAPRODUCTS CORPORATION
-00C026 LANS TECHNOLOGY CO., LTD.
-00C027 CIPHER SYSTEMS, INC.
-00C028 JASCO CORPORATION
-00C029 Nexans Deutschland AG - ANS
-00C02A OHKURA ELECTRIC CO., LTD.
-00C02B GERLOFF GESELLSCHAFT FUR
-00C02C CENTRUM COMMUNICATIONS, INC.
-00C02D FUJI PHOTO FILM CO., LTD.
-00C02E NETWIZ
-00C02F OKUMA CORPORATION
-00C030 INTEGRATED ENGINEERING B. V.
-00C031 DESIGN RESEARCH SYSTEMS, INC.
-00C032 I-CUBED LIMITED
-00C033 TELEBIT COMMUNICATIONS APS
-00C034 TRANSACTION NETWORK
-00C035 QUINTAR COMPANY
-00C036 RAYTECH ELECTRONIC CORP.
-00C037 DYNATEM
-00C038 RASTER IMAGE PROCESSING SYSTEM
-00C039 TDK SEMICONDUCTOR CORPORATION
-00C03A MEN-MIKRO ELEKTRONIK GMBH
-00C03B MULTIACCESS COMPUTING CORP.
-00C03C TOWER TECH S.R.L.
-00C03D WIESEMANN & THEIS GMBH
-00C03E FA. GEBR. HELLER GMBH
-00C03F STORES AUTOMATED SYSTEMS, INC.
-00C040 ECCI
-00C041 DIGITAL TRANSMISSION SYSTEMS
-00C042 DATALUX CORP.
-00C043 STRATACOM
-00C044 EMCOM CORPORATION
-00C045 ISOLATION SYSTEMS, LTD.
-00C046 KEMITRON LTD.
-00C047 UNIMICRO SYSTEMS, INC.
-00C048 BAY TECHNICAL ASSOCIATES
-00C049 U.S. ROBOTICS, INC.
-00C04A GROUP 2000 AG
-00C04B CREATIVE MICROSYSTEMS
-00C04C DEPARTMENT OF FOREIGN AFFAIRS
-00C04D MITEC, INC.
-00C04E COMTROL CORPORATION
-00C04F DELL COMPUTER CORPORATION
-00C050 TOYO DENKI SEIZO K.K.
-00C051 ADVANCED INTEGRATION RESEARCH
-00C052 BURR-BROWN
-00C053 DAVOX CORPORATION
-00C054 NETWORK PERIPHERALS, LTD.
-00C055 MODULAR COMPUTING TECHNOLOGIES
-00C056 SOMELEC
-00C057 MYCO ELECTRONICS
-00C058 DATAEXPERT CORP.
-00C059 NIPPON DENSO CO., LTD.
-00C05A SEMAPHORE COMMUNICATIONS CORP.
-00C05B NETWORKS NORTHWEST, INC.
-00C05C ELONEX PLC
-00C05D L&N TECHNOLOGIES
-00C05E VARI-LITE, INC.
-00C05F FINE-PAL COMPANY LIMITED
-00C060 ID SCANDINAVIA AS
-00C061 SOLECTEK CORPORATION
-00C062 IMPULSE TECHNOLOGY
-00C063 MORNING STAR TECHNOLOGIES, INC
-00C064 GENERAL DATACOMM IND. INC.
-00C065 SCOPE COMMUNICATIONS, INC.
-00C066 DOCUPOINT, INC.
-00C067 UNITED BARCODE INDUSTRIES
-00C068 PHILIP DRAKE ELECTRONICS LTD.
-00C069 Axxcelera Broadband Wireless
-00C06A ZAHNER-ELEKTRIK GMBH & CO. KG
-00C06B OSI PLUS CORPORATION
-00C06C SVEC COMPUTER CORP.
-00C06D BOCA RESEARCH, INC.
-00C06E HAFT TECHNOLOGY, INC.
-00C06F KOMATSU LTD.
-00C070 SECTRA SECURE-TRANSMISSION AB
-00C071 AREANEX COMMUNICATIONS, INC.
-00C072 KNX LTD.
-00C073 XEDIA CORPORATION
-00C074 TOYODA AUTOMATIC LOOM
-00C075 XANTE CORPORATION
-00C076 I-DATA INTERNATIONAL A-S
-00C077 DAEWOO TELECOM LTD.
-00C078 COMPUTER SYSTEMS ENGINEERING
-00C079 FONSYS CO.,LTD.
-00C07A PRIVA B.V.
-00C07B ASCEND COMMUNICATIONS, INC.
-00C07C HIGHTECH INFORMATION
-00C07D RISC DEVELOPMENTS LTD.
-00C07E KUBOTA CORPORATION ELECTRONIC
-00C07F NUPON COMPUTING CORP.
-00C080 NETSTAR, INC.
-00C081 METRODATA LTD.
-00C082 MOORE PRODUCTS CO.
-00C083 TRACE MOUNTAIN PRODUCTS, INC.
-00C084 DATA LINK CORP. LTD.
-00C085 ELECTRONICS FOR IMAGING, INC.
-00C086 THE LYNK CORPORATION
-00C087 UUNET TECHNOLOGIES, INC.
-00C088 EKF ELEKTRONIK GMBH
-00C089 TELINDUS DISTRIBUTION
-00C08A LAUTERBACH DATENTECHNIK GMBH
-00C08B RISQ MODULAR SYSTEMS, INC.
-00C08C PERFORMANCE TECHNOLOGIES, INC.
-00C08D TRONIX PRODUCT DEVELOPMENT
-00C08E NETWORK INFORMATION TECHNOLOGY
-00C08F MATSUSHITA ELECTRIC WORKS, LTD
-00C090 PRAIM S.R.L.
-00C091 JABIL CIRCUIT, INC.
-00C092 MENNEN MEDICAL INC.
-00C093 ALTA RESEARCH CORP.
-00C094 VMX INC.
-00C095 ZNYX
-00C096 TAMURA CORPORATION
-00C097 ARCHIPEL SA
-00C098 CHUNTEX ELECTRONIC CO., LTD.
-00C099 YOSHIKI INDUSTRIAL CO.,LTD.
-00C09A PHOTONICS CORPORATION
-00C09B RELIANCE COMM/TEC, R-TEC
-00C09C TOA ELECTRONIC LTD.
-00C09D DISTRIBUTED SYSTEMS INT'L, INC
-00C09E CACHE COMPUTERS, INC.
-00C09F QUANTA COMPUTER, INC.
-00C0A0 ADVANCE MICRO RESEARCH, INC.
-00C0A1 TOKYO DENSHI SEKEI CO.
-00C0A2 INTERMEDIUM A/S
-00C0A3 DUAL ENTERPRISES CORPORATION
-00C0A4 UNIGRAF OY
-00C0A5 DICKENS DATA SYSTEMS
-00C0A6 EXICOM AUSTRALIA PTY. LTD
-00C0A7 SEEL LTD.
-00C0A8 GVC CORPORATION
-00C0A9 BARRON MCCANN LTD.
-00C0AA SILICON VALLEY COMPUTER
-00C0AB Telco Systems, Inc.
-00C0AC GAMBIT COMPUTER COMMUNICATIONS
-00C0AD MARBEN COMMUNICATION SYSTEMS
-00C0AE TOWERCOM CO. INC. DBA PC HOUSE
-00C0AF TEKLOGIX INC.
-00C0B0 GCC TECHNOLOGIES,INC.
-00C0B1 GENIUS NET CO.
-00C0B2 NORAND CORPORATION
-00C0B3 COMSTAT DATACOMM CORPORATION
-00C0B4 MYSON TECHNOLOGY, INC.
-00C0B5 CORPORATE NETWORK SYSTEMS,INC.
-00C0B6 Snap Appliance, Inc.
-00C0B7 AMERICAN POWER CONVERSION CORP
-00C0B8 FRASER'S HILL LTD.
-00C0B9 FUNK SOFTWARE, INC.
-00C0BA NETVANTAGE
-00C0BB FORVAL CREATIVE, INC.
-00C0BC TELECOM AUSTRALIA/CSSC
-00C0BD INEX TECHNOLOGIES, INC.
-00C0BE ALCATEL - SEL
-00C0BF TECHNOLOGY CONCEPTS, LTD.
-00C0C0 SHORE MICROSYSTEMS, INC.
-00C0C1 QUAD/GRAPHICS, INC.
-00C0C2 INFINITE NETWORKS LTD.
-00C0C3 ACUSON COMPUTED SONOGRAPHY
-00C0C4 COMPUTER OPERATIONAL
-00C0C5 SID INFORMATICA
-00C0C6 PERSONAL MEDIA CORP.
-00C0C7 SPARKTRUM MICROSYSTEMS, INC.
-00C0C8 MICRO BYTE PTY. LTD.
-00C0C9 ELSAG BAILEY PROCESS
-00C0CA ALFA, INC.
-00C0CB CONTROL TECHNOLOGY CORPORATION
-00C0CC TELESCIENCES CO SYSTEMS, INC.
-00C0CD COMELTA, S.A.
-00C0CE CEI SYSTEMS & ENGINEERING PTE
-00C0CF IMATRAN VOIMA OY
-00C0D0 RATOC SYSTEM INC.
-00C0D1 COMTREE TECHNOLOGY CORPORATION
-00C0D2 SYNTELLECT, INC.
-00C0D3 OLYMPUS IMAGE SYSTEMS, INC.
-00C0D4 AXON NETWORKS, INC.
-00C0D5 QUANCOM ELECTRONIC GMBH
-00C0D6 J1 SYSTEMS, INC.
-00C0D7 TAIWAN TRADING CENTER DBA
-00C0D8 UNIVERSAL DATA SYSTEMS
-00C0D9 QUINTE NETWORK CONFIDENTIALITY
-00C0DA NICE SYSTEMS LTD.
-00C0DB IPC CORPORATION (PTE) LTD.
-00C0DC EOS TECHNOLOGIES, INC.
-00C0DD QLogic Corporation
-00C0DE ZCOMM, INC.
-00C0DF KYE Systems Corp.
-00C0E0 DSC COMMUNICATION CORP.
-00C0E1 SONIC SOLUTIONS
-00C0E2 CALCOMP, INC.
-00C0E3 OSITECH COMMUNICATIONS, INC.
-00C0E4 SIEMENS BUILDING
-00C0E5 GESPAC, S.A.
-00C0E6 Verilink Corporation
-00C0E7 FIBERDATA AB
-00C0E8 PLEXCOM, INC.
-00C0E9 OAK SOLUTIONS, LTD.
-00C0EA ARRAY TECHNOLOGY LTD.
-00C0EB SEH COMPUTERTECHNIK GMBH
-00C0EC DAUPHIN TECHNOLOGY
-00C0ED US ARMY ELECTRONIC
-00C0EE KYOCERA CORPORATION
-00C0EF ABIT CORPORATION
-00C0F0 KINGSTON TECHNOLOGY CORP.
-00C0F1 SHINKO ELECTRIC CO., LTD.
-00C0F2 TRANSITION NETWORKS
-00C0F3 NETWORK COMMUNICATIONS CORP.
-00C0F4 INTERLINK SYSTEM CO., LTD.
-00C0F5 METACOMP, INC.
-00C0F6 CELAN TECHNOLOGY INC.
-00C0F7 ENGAGE COMMUNICATION, INC.
-00C0F8 ABOUT COMPUTING INC.
-00C0F9 HARRIS AND JEFFRIES, INC.
-00C0FA CANARY COMMUNICATIONS, INC.
-00C0FB ADVANCED TECHNOLOGY LABS
-00C0FC ELASTIC REALITY, INC.
-00C0FD PROSUM
-00C0FE APTEC COMPUTER SYSTEMS, INC.
-00C0FF DOT HILL SYSTEMS CORPORATION
-00CBBD Cambridge Broadband Ltd.
-00CF1C COMMUNICATION MACHINERY CORP.
-00D000 FERRAN SCIENTIFIC, INC.
-00D001 VST TECHNOLOGIES, INC.
-00D002 DITECH CORPORATION
-00D003 COMDA ENTERPRISES CORP.
-00D004 PENTACOM LTD.
-00D005 ZHS ZEITMANAGEMENTSYSTEME
-00D006 CISCO SYSTEMS, INC.
-00D007 MIC ASSOCIATES, INC.
-00D008 MACTELL CORPORATION
-00D009 HSING TECH. ENTERPRISE CO. LTD
-00D00A LANACCESS TELECOM S.A.
-00D00B RHK TECHNOLOGY, INC.
-00D00C SNIJDER MICRO SYSTEMS
-00D00D MICROMERITICS INSTRUMENT
-00D00E PLURIS, INC.
-00D00F SPEECH DESIGN GMBH
-00D010 CONVERGENT NETWORKS, INC.
-00D011 PRISM VIDEO, INC.
-00D012 GATEWORKS CORP.
-00D013 PRIMEX AEROSPACE COMPANY
-00D014 ROOT, INC.
-00D015 UNIVEX MICROTECHNOLOGY CORP.
-00D016 SCM MICROSYSTEMS, INC.
-00D017 SYNTECH INFORMATION CO., LTD.
-00D018 QWES. COM, INC.
-00D019 DAINIPPON SCREEN CORPORATE
-00D01A URMET SUD S.P.A.
-00D01B MIMAKI ENGINEERING CO., LTD.
-00D01C SBS TECHNOLOGIES,
-00D01D FURUNO ELECTRIC CO., LTD.
-00D01E PINGTEL CORP.
-00D01F CTAM PTY. LTD.
-00D020 AIM SYSTEM, INC.
-00D021 REGENT ELECTRONICS CORP.
-00D022 INCREDIBLE TECHNOLOGIES, INC.
-00D023 INFORTREND TECHNOLOGY, INC.
-00D024 Cognex Corporation
-00D025 XROSSTECH, INC.
-00D026 HIRSCHMANN AUSTRIA GMBH
-00D027 APPLIED AUTOMATION, INC.
-00D028 OMNEON VIDEO NETWORKS
-00D029 WAKEFERN FOOD CORPORATION
-00D02A Voxent Systems Ltd.
-00D02B JETCELL, INC.
-00D02C CAMPBELL SCIENTIFIC, INC.
-00D02D ADEMCO
-00D02E COMMUNICATION AUTOMATION CORP.
-00D02F VLSI TECHNOLOGY INC.
-00D030 SAFETRAN SYSTEMS CORP.
-00D031 INDUSTRIAL LOGIC CORPORATION
-00D032 YANO ELECTRIC CO., LTD.
-00D033 DALIAN DAXIAN NETWORK
-00D034 ORMEC SYSTEMS CORP.
-00D035 BEHAVIOR TECH. COMPUTER CORP.
-00D036 TECHNOLOGY ATLANTA CORP.
-00D037 PHILIPS-DVS-LO BDR
-00D038 FIVEMERE, LTD.
-00D039 UTILICOM, INC.
-00D03A ZONEWORX, INC.
-00D03B VISION PRODUCTS PTY. LTD.
-00D03C Vieo, Inc.
-00D03D GALILEO TECHNOLOGY, LTD.
-00D03E ROCKETCHIPS, INC.
-00D03F AMERICAN COMMUNICATION
-00D040 SYSMATE CO., LTD.
-00D041 AMIGO TECHNOLOGY CO., LTD.
-00D042 MAHLO GMBH & CO. UG
-00D043 ZONAL RETAIL DATA SYSTEMS
-00D044 ALIDIAN NETWORKS, INC.
-00D045 KVASER AB
-00D046 DOLBY LABORATORIES, INC.
-00D047 XN TECHNOLOGIES
-00D048 ECTON, INC.
-00D049 IMPRESSTEK CO., LTD.
-00D04A PRESENCE TECHNOLOGY GMBH
-00D04B LA CIE GROUP S.A.
-00D04C EUROTEL TELECOM LTD.
-00D04D DIV OF RESEARCH & STATISTICS
-00D04E LOGIBAG
-00D04F BITRONICS, INC.
-00D050 ISKRATEL
-00D051 O2 MICRO, INC.
-00D052 ASCEND COMMUNICATIONS, INC.
-00D053 CONNECTED SYSTEMS
-00D054 SAS INSTITUTE INC.
-00D055 KATHREIN-WERKE KG
-00D056 SOMAT CORPORATION
-00D057 ULTRAK, INC.
-00D058 CISCO SYSTEMS, INC.
-00D059 AMBIT MICROSYSTEMS CORP.
-00D05A SYMBIONICS, LTD.
-00D05B ACROLOOP MOTION CONTROL
-00D05C TECHNOTREND SYSTEMTECHNIK GMBH
-00D05D INTELLIWORXX, INC.
-00D05E STRATABEAM TECHNOLOGY, INC.
-00D05F VALCOM, INC.
-00D060 PANASONIC EUROPEAN
-00D061 TREMON ENTERPRISES CO., LTD.
-00D062 DIGIGRAM
-00D063 CISCO SYSTEMS, INC.
-00D064 MULTITEL
-00D065 TOKO ELECTRIC
-00D066 WINTRISS ENGINEERING CORP.
-00D067 CAMPIO COMMUNICATIONS
-00D068 IWILL CORPORATION
-00D069 TECHNOLOGIC SYSTEMS
-00D06A LINKUP SYSTEMS CORPORATION
-00D06B SR TELECOM INC.
-00D06C SHAREWAVE, INC.
-00D06D ACRISON, INC.
-00D06E TRENDVIEW RECORDERS LTD.
-00D06F KMC CONTROLS
-00D070 LONG WELL ELECTRONICS CORP.
-00D071 ECHELON CORP.
-00D072 BROADLOGIC
-00D073 ACN ADVANCED COMMUNICATIONS
-00D074 TAQUA SYSTEMS, INC.
-00D075 ALARIS MEDICAL SYSTEMS, INC.
-00D076 MERRILL LYNCH & CO., INC.
-00D077 LUCENT TECHNOLOGIES
-00D078 ELTEX OF SWEDEN AB
-00D079 CISCO SYSTEMS, INC.
-00D07A AMAQUEST COMPUTER CORP.
-00D07B COMCAM INTERNATIONAL LTD.
-00D07C KOYO ELECTRONICS INC. CO.,LTD.
-00D07D COSINE COMMUNICATIONS
-00D07E KEYCORP LTD.
-00D07F STRATEGY & TECHNOLOGY, LIMITED
-00D080 EXABYTE CORPORATION
-00D081 REAL TIME DEVICES USA, INC.
-00D082 IOWAVE INC.
-00D083 INVERTEX, INC.
-00D084 NEXCOMM SYSTEMS, INC.
-00D085 OTIS ELEVATOR COMPANY
-00D086 FOVEON, INC.
-00D087 MICROFIRST INC.
-00D088 Terayon Communications Systems
-00D089 DYNACOLOR, INC.
-00D08A PHOTRON USA
-00D08B ADVA Limited
-00D08C GENOA TECHNOLOGY, INC.
-00D08D PHOENIX GROUP, INC.
-00D08E NVISION INC.
-00D08F ARDENT TECHNOLOGIES, INC.
-00D090 CISCO SYSTEMS, INC.
-00D091 SMARTSAN SYSTEMS, INC.
-00D092 GLENAYRE WESTERN MULTIPLEX
-00D093 TQ - COMPONENTS GMBH
-00D094 TIMELINE VISTA, INC.
-00D095 XYLAN CORPORATION
-00D096 3COM EUROPE LTD.
-00D097 CISCO SYSTEMS, INC.
-00D098 Photon Dynamics Canada Inc.
-00D099 ELCARD OY
-00D09A FILANET CORPORATION
-00D09B SPECTEL LTD.
-00D09C KAPADIA COMMUNICATIONS
-00D09D VERIS INDUSTRIES
-00D09E 2WIRE, INC.
-00D09F NOVTEK TEST SYSTEMS
-00D0A0 MIPS DENMARK
-00D0A1 OSKAR VIERLING GMBH + CO. KG
-00D0A2 INTEGRATED DEVICE
-00D0A3 VOCAL DATA, INC.
-00D0A4 ALANTRO COMMUNICATIONS
-00D0A5 AMERICAN ARIUM
-00D0A6 LANBIRD TECHNOLOGY CO., LTD.
-00D0A7 TOKYO SOKKI KENKYUJO CO., LTD.
-00D0A8 NETWORK ENGINES, INC.
-00D0A9 SHINANO KENSHI CO., LTD.
-00D0AA CHASE COMMUNICATIONS
-00D0AB DELTAKABEL TELECOM CV
-00D0AC GRAYSON WIRELESS
-00D0AD TL INDUSTRIES
-00D0AE ORESIS COMMUNICATIONS, INC.
-00D0AF CUTLER-HAMMER, INC.
-00D0B0 BITSWITCH LTD.
-00D0B1 OMEGA ELECTRONICS SA
-00D0B2 XIOTECH CORPORATION
-00D0B3 DRS FLIGHT SAFETY AND
-00D0B4 KATSUJIMA CO., LTD.
-00D0B5 IPricot formerly DotCom
-00D0B6 CRESCENT NETWORKS, INC.
-00D0B7 INTEL CORPORATION
-00D0B8 IOMEGA CORP.
-00D0B9 MICROTEK INTERNATIONAL, INC.
-00D0BA CISCO SYSTEMS, INC.
-00D0BB CISCO SYSTEMS, INC.
-00D0BC CISCO SYSTEMS, INC.
-00D0BD SICAN GMBH
-00D0BE EMUTEC INC.
-00D0BF PIVOTAL TECHNOLOGIES
-00D0C0 CISCO SYSTEMS, INC.
-00D0C1 HARMONIC DATA SYSTEMS, LTD.
-00D0C2 BALTHAZAR TECHNOLOGY AB
-00D0C3 VIVID TECHNOLOGY PTE, LTD.
-00D0C4 TERATECH CORPORATION
-00D0C5 COMPUTATIONAL SYSTEMS, INC.
-00D0C6 THOMAS & BETTS CORP.
-00D0C7 PATHWAY, INC.
-00D0C8 I/O CONSULTING A/S
-00D0C9 ADVANTECH CO., LTD.
-00D0CA INTRINSYC SOFTWARE INC.
-00D0CB DASAN CO., LTD.
-00D0CC TECHNOLOGIES LYRE INC.
-00D0CD ATAN TECHNOLOGY INC.
-00D0CE ASYST ELECTRONIC
-00D0CF MORETON BAY
-00D0D0 ZHONGXING TELECOM LTD.
-00D0D1 SIROCCO SYSTEMS, INC.
-00D0D2 EPILOG CORPORATION
-00D0D3 CISCO SYSTEMS, INC.
-00D0D4 V-BITS, INC.
-00D0D5 GRUNDIG AG
-00D0D6 AETHRA TELECOMUNICAZIONI
-00D0D7 B2C2, INC.
-00D0D8 3Com Corporation
-00D0D9 DEDICATED MICROCOMPUTERS
-00D0DA TAICOM DATA SYSTEMS CO., LTD.
-00D0DB MCQUAY INTERNATIONAL
-00D0DC MODULAR MINING SYSTEMS, INC.
-00D0DD SUNRISE TELECOM, INC.
-00D0DE PHILIPS MULTIMEDIA NETWORK
-00D0DF KUZUMI ELECTRONICS, INC.
-00D0E0 DOOIN ELECTRONICS CO.
-00D0E1 AVIONITEK ISRAEL INC.
-00D0E2 MRT MICRO, INC.
-00D0E3 ELE-CHEM ENGINEERING CO., LTD.
-00D0E4 CISCO SYSTEMS, INC.
-00D0E5 SOLIDUM SYSTEMS CORP.
-00D0E6 IBOND INC.
-00D0E7 VCON TELECOMMUNICATION LTD.
-00D0E8 MAC SYSTEM CO., LTD.
-00D0E9 ADVANTAGE CENTURY
-00D0EA NEXTONE COMMUNICATIONS, INC.
-00D0EB LIGHTERA NETWORKS, INC.
-00D0EC NAKAYO TELECOMMUNICATIONS, INC
-00D0ED XIOX
-00D0EE DICTAPHONE CORPORATION
-00D0EF IGT
-00D0F0 CONVISION TECHNOLOGY GMBH
-00D0F1 SEGA ENTERPRISES, LTD.
-00D0F2 MONTEREY NETWORKS
-00D0F3 SOLARI DI UDINE SPA
-00D0F4 CARINTHIAN TECH INSTITUTE
-00D0F5 ORANGE MICRO, INC.
-00D0F6 Alcatel Canada
-00D0F7 NEXT NETS CORPORATION
-00D0F8 FUJIAN STAR TERMINAL
-00D0F9 ACUTE COMMUNICATIONS CORP.
-00D0FA RACAL GUARDATA
-00D0FB TEK MICROSYSTEMS, INCORPORATED
-00D0FC GRANITE MICROSYSTEMS
-00D0FD OPTIMA TELE.COM, INC.
-00D0FE ASTRAL POINT
-00D0FF CISCO SYSTEMS, INC.
-00DD00 UNGERMANN-BASS INC.
-00DD01 UNGERMANN-BASS INC.
-00DD02 UNGERMANN-BASS INC.
-00DD03 UNGERMANN-BASS INC.
-00DD04 UNGERMANN-BASS INC.
-00DD05 UNGERMANN-BASS INC.
-00DD06 UNGERMANN-BASS INC.
-00DD07 UNGERMANN-BASS INC.
-00DD08 UNGERMANN-BASS INC.
-00DD09 UNGERMANN-BASS INC.
-00DD0A UNGERMANN-BASS INC.
-00DD0B UNGERMANN-BASS INC.
-00DD0C UNGERMANN-BASS INC.
-00DD0D UNGERMANN-BASS INC.
-00DD0E UNGERMANN-BASS INC.
-00DD0F UNGERMANN-BASS INC.
-00E000 FUJITSU, LTD
-00E001 STRAND LIGHTING LIMITED
-00E002 CROSSROADS SYSTEMS, INC.
-00E003 NOKIA WIRELESS BUSINESS COMMUN
-00E004 PMC-SIERRA, INC.
-00E005 TECHNICAL CORP.
-00E006 SILICON INTEGRATED SYS. CORP.
-00E007 NETWORK ALCHEMY LTD.
-00E008 AMAZING CONTROLS! INC.
-00E009 MARATHON TECHNOLOGIES CORP.
-00E00A DIBA, INC.
-00E00B ROOFTOP COMMUNICATIONS CORP.
-00E00C MOTOROLA
-00E00D RADIANT SYSTEMS
-00E00E AVALON IMAGING SYSTEMS, INC.
-00E00F SHANGHAI BAUD DATA
-00E010 HESS SB-AUTOMATENBAU GmbH
-00E011 UNIDEN SAN DIEGO R&D CENTER, INC.
-00E012 PLUTO TECHNOLOGIES INTERNATIONAL INC.
-00E013 EASTERN ELECTRONIC CO., LTD.
-00E014 CISCO SYSTEMS, INC.
-00E015 HEIWA CORPORATION
-00E016 RAPID CITY COMMUNICATIONS
-00E017 EXXACT GmbH
-00E018 ASUSTEK COMPUTER INC.
-00E019 ING. GIORDANO ELETTRONICA
-00E01A COMTEC SYSTEMS. CO., LTD.
-00E01B SPHERE COMMUNICATIONS, INC.
-00E01C MOBILITY ELECTRONICSY
-00E01D WebTV NETWORKS, INC.
-00E01E CISCO SYSTEMS, INC.
-00E01F AVIDIA Systems, Inc.
-00E020 TECNOMEN OY
-00E021 FREEGATE CORP.
-00E022 MediaLight, Inc.
-00E023 TELRAD
-00E024 GADZOOX NETWORKS
-00E025 dit CO., LTD.
-00E026 EASTMAN KODAK CO.
-00E027 DUX, INC.
-00E028 APTIX CORPORATION
-00E029 STANDARD MICROSYSTEMS CORP.
-00E02A TANDBERG TELEVISION AS
-00E02B EXTREME NETWORKS
-00E02C AST COMPUTER
-00E02D InnoMediaLogic, Inc.
-00E02E SPC ELECTRONICS CORPORATION
-00E02F MCNS HOLDINGS, L.P.
-00E030 MELITA INTERNATIONAL CORP.
-00E031 HAGIWARA ELECTRIC CO., LTD.
-00E032 MISYS FINANCIAL SYSTEMS, LTD.
-00E033 E.E.P.D. GmbH
-00E034 CISCO SYSTEMS, INC.
-00E035 LOUGHBOROUGH SOUND IMAGES, PLC
-00E036 PIONEER CORPORATION
-00E037 CENTURY CORPORATION
-00E038 PROXIMA CORPORATION
-00E039 PARADYNE CORP.
-00E03A CABLETRON SYSTEMS, INC.
-00E03B PROMINET CORPORATION
-00E03C AdvanSys
-00E03D FOCON ELECTRONIC SYSTEMS A/S
-00E03E ALFATECH, INC.
-00E03F JATON CORPORATION
-00E040 DeskStation Technology, Inc.
-00E041 CSPI
-00E042 Pacom Systems Ltd.
-00E043 VitalCom
-00E044 LSICS CORPORATION
-00E045 TOUCHWAVE, INC.
-00E046 BENTLY NEVADA CORP.
-00E047 INFOCUS SYSTEMS
-00E048 SDL COMMUNICATIONS, INC.
-00E049 MICROWI ELECTRONIC GmbH
-00E04A ENHANCED MESSAGING SYSTEMS, INC
-00E04B JUMP INDUSTRIELLE COMPUTERTECHNIK GmbH
-00E04C REALTEK SEMICONDUCTOR CORP.
-00E04D INTERNET INITIATIVE JAPAN, INC
-00E04E SANYO DENKI CO., LTD.
-00E04F CISCO SYSTEMS, INC.
-00E050 EXECUTONE INFORMATION SYSTEMS, INC.
-00E051 TALX CORPORATION
-00E052 FOUNDRY NETWORKS, INC.
-00E053 CELLPORT LABS, INC.
-00E054 KODAI HITEC CO., LTD.
-00E055 INGENIERIA ELECTRONICA COMERCIAL INELCOM S.A.
-00E056 HOLONTECH CORPORATION
-00E057 HAN MICROTELECOM. CO., LTD.
-00E058 PHASE ONE DENMARK A/S
-00E059 CONTROLLED ENVIRONMENTS, LTD.
-00E05A GALEA NETWORK SECURITY
-00E05B WEST END SYSTEMS CORP.
-00E05C MATSUSHITA KOTOBUKI ELECTRONICS INDUSTRIES, LTD.
-00E05D UNITEC CO., LTD.
-00E05E JAPAN AVIATION ELECTRONICS INDUSTRY, LTD.
-00E05F e-Net, Inc.
-00E060 SHERWOOD
-00E061 EdgePoint Networks, Inc.
-00E062 HOST ENGINEERING
-00E063 CABLETRON - YAGO SYSTEMS, INC.
-00E064 SAMSUNG ELECTRONICS
-00E065 OPTICAL ACCESS INTERNATIONAL
-00E066 ProMax Systems, Inc.
-00E067 eac AUTOMATION-CONSULTING GmbH
-00E068 MERRIMAC SYSTEMS INC.
-00E069 JAYCOR
-00E06A KAPSCH AG
-00E06B W&G SPECIAL PRODUCTS
-00E06C AEP Systems International Ltd
-00E06D COMPUWARE CORPORATION
-00E06E FAR SYSTEMS S.p.A.
-00E06F Terayon Communications Systems
-00E070 DH TECHNOLOGY
-00E071 EPIS MICROCOMPUTER
-00E072 LYNK
-00E073 NATIONAL AMUSEMENT NETWORK, INC.
-00E074 TIERNAN COMMUNICATIONS, INC.
-00E075 Verilink Corporation
-00E076 DEVELOPMENT CONCEPTS, INC.
-00E077 WEBGEAR, INC.
-00E078 BERKELEY NETWORKS
-00E079 A.T.N.R.
-00E07A MIKRODIDAKT AB
-00E07B BAY NETWORKS
-00E07C METTLER-TOLEDO, INC.
-00E07D NETRONIX, INC.
-00E07E WALT DISNEY IMAGINEERING
-00E07F LOGISTISTEM s.r.l.
-00E080 CONTROL RESOURCES CORPORATION
-00E081 TYAN COMPUTER CORP.
-00E082 ANERMA
-00E083 JATO TECHNOLOGIES, INC.
-00E084 COMPULITE R&D
-00E085 GLOBAL MAINTECH, INC.
-00E086 CYBEX COMPUTER PRODUCTS
-00E087 LeCroy - Networking Productions Division
-00E088 LTX CORPORATION
-00E089 ION Networks, Inc.
-00E08A GEC AVERY, LTD.
-00E08B QLogic Corp.
-00E08C NEOPARADIGM LABS, INC.
-00E08D PRESSURE SYSTEMS, INC.
-00E08E UTSTARCOM
-00E08F CISCO SYSTEMS, INC.
-00E090 BECKMAN LAB. AUTOMATION DIV.
-00E091 LG ELECTRONICS, INC.
-00E092 ADMTEK INCORPORATED
-00E093 ACKFIN NETWORKS
-00E094 OSAI SRL
-00E095 ADVANCED-VISION TECHNOLGIES CORP.
-00E096 SHIMADZU CORPORATION
-00E097 CARRIER ACCESS CORPORATION
-00E098 AboCom Systems, Inc.
-00E099 SAMSON AG
-00E09A POSITRON INDUSTRIES, INC.
-00E09B ENGAGE NETWORKS, INC.
-00E09C MII
-00E09D SARNOFF CORPORATION
-00E09E QUANTUM CORPORATION
-00E09F PIXEL VISION
-00E0A0 WILTRON CO.
-00E0A1 HIMA PAUL HILDEBRANDT GmbH Co. KG
-00E0A2 MICROSLATE INC.
-00E0A3 CISCO SYSTEMS, INC.
-00E0A4 ESAOTE S.p.A.
-00E0A5 ComCore Semiconductor, Inc.
-00E0A6 TELOGY NETWORKS, INC.
-00E0A7 IPC INFORMATION SYSTEMS, INC.
-00E0A8 SAT GmbH & Co.
-00E0A9 FUNAI ELECTRIC CO., LTD.
-00E0AA ELECTROSONIC LTD.
-00E0AB DIMAT S.A.
-00E0AC MIDSCO, INC.
-00E0AD EES TECHNOLOGY, LTD.
-00E0AE XAQTI CORPORATION
-00E0AF GENERAL DYNAMICS INFORMATION SYSTEMS
-00E0B0 CISCO SYSTEMS, INC.
-00E0B1 PACKET ENGINES, INC.
-00E0B2 TELMAX COMMUNICATIONS CORP.
-00E0B3 EtherWAN Systems, Inc.
-00E0B4 TECHNO SCOPE CO., LTD.
-00E0B5 ARDENT COMMUNICATIONS CORP.
-00E0B6 Entrada Networks
-00E0B7 PI GROUP, LTD.
-00E0B8 GATEWAY 2000
-00E0B9 BYAS SYSTEMS
-00E0BA BERGHOF AUTOMATIONSTECHNIK GmbH
-00E0BB NBX CORPORATION
-00E0BC SYMON COMMUNICATIONS, INC.
-00E0BD INTERFACE SYSTEMS, INC.
-00E0BE GENROCO INTERNATIONAL, INC.
-00E0BF TORRENT NETWORKING TECHNOLOGIES CORP.
-00E0C0 SEIWA ELECTRIC MFG. CO., LTD.
-00E0C1 MEMOREX TELEX JAPAN, LTD.
-00E0C2 NECSY S.p.A.
-00E0C3 SAKAI SYSTEM DEVELOPMENT CORP.
-00E0C4 HORNER ELECTRIC, INC.
-00E0C5 BCOM ELECTRONICS INC.
-00E0C6 LINK2IT, L.L.C.
-00E0C7 EUROTECH SRL
-00E0C8 VIRTUAL ACCESS, LTD.
-00E0C9 AutomatedLogic Corporation
-00E0CA BEST DATA PRODUCTS
-00E0CB RESON, INC.
-00E0CC HERO SYSTEMS, LTD.
-00E0CD SENSIS CORPORATION
-00E0CE ARN
-00E0CF INTEGRATED DEVICE TECHNOLOGY, INC.
-00E0D0 NETSPEED, INC.
-00E0D1 TELSIS LIMITED
-00E0D2 VERSANET COMMUNICATIONS, INC.
-00E0D3 DATENTECHNIK GmbH
-00E0D4 EXCELLENT COMPUTER
-00E0D5 ARCXEL TECHNOLOGIES, INC.
-00E0D6 COMPUTER & COMMUNICATION RESEARCH LAB.
-00E0D7 SUNSHINE ELECTRONICS, INC.
-00E0D8 LANBit Computer, Inc.
-00E0D9 TAZMO CO., LTD.
-00E0DA ASSURED ACCESS TECHNOLOGY, INC.
-00E0DB ViaVideo Communications, Inc.
-00E0DC NEXWARE CORP.
-00E0DD ZENITH ELECTRONICS CORPORATION
-00E0DE DATAX NV
-00E0DF KE KOMMUNIKATIONS-ELECTRONIK
-00E0E0 SI ELECTRONICS, LTD.
-00E0E1 G2 NETWORKS, INC.
-00E0E2 INNOVA CORP.
-00E0E3 SK-ELEKTRONIK GmbH
-00E0E4 FANUC ROBOTICS NORTH AMERICA, Inc.
-00E0E5 CINCO NETWORKS, INC.
-00E0E6 INCAA DATACOM B.V.
-00E0E7 RAYTHEON E-SYSTEMS, INC.
-00E0E8 GRETACODER Data Systems AG
-00E0E9 DATA LABS, INC.
-00E0EA INNOVAT COMMUNICATIONS, INC.
-00E0EB DIGICOM SYSTEMS, INCORPORATED
-00E0EC CELESTICA INC.
-00E0ED SILICOM, LTD.
-00E0EE MAREL HF
-00E0EF DIONEX
-00E0F0 ABLER TECHNOLOGY, INC.
-00E0F1 THAT CORPORATION
-00E0F2 ARLOTTO COMNET, INC.
-00E0F3 WebSprint Communications, Inc.
-00E0F4 INSIDE Technology A/S
-00E0F5 TELES AG
-00E0F6 DECISION EUROPE
-00E0F7 CISCO SYSTEMS, INC.
-00E0F8 DICNA CONTROL AB
-00E0F9 CISCO SYSTEMS, INC.
-00E0FA TRL TECHNOLOGY, LTD.
-00E0FB LEIGHTRONIX, INC.
-00E0FC HUAWEI TECHNOLOGIES CO., LTD.
-00E0FD A-TREND TECHNOLOGY CO., LTD.
-00E0FE CISCO SYSTEMS, INC.
-00E0FF SECURITY DYNAMICS TECHNOLOGIES, Inc.
-00E6D3 NIXDORF COMPUTER CORP.
-020701 RACAL-DATACOM
-021C7C PERQ SYSTEMS CORPORATION
-026086 LOGIC REPLACEMENT TECH. LTD.
-02608C 3COM CORPORATION
-027001 RACAL-DATACOM
-0270B0 M/A-COM INC. COMPANIES
-0270B3 DATA RECALL LTD
-029D8E CARDIAC RECORDERS INC.
-02AA3C OLIVETTI TELECOMM SPA (OLTECO)
-02BB01 OCTOTHORPE CORP.
-02C08C 3COM CORPORATION
-02CF1C COMMUNICATION MACHINERY CORP.
-02E6D3 NIXDORF COMPUTER CORPORATION
-040AE0 XMIT AG COMPUTER NETWORKS
-04E0C4 TRIUMPH-ADLER AG
-080001 COMPUTERVISION CORPORATION
-080002 BRIDGE COMMUNICATIONS INC.
-080003 ADVANCED COMPUTER COMM.
-080004 CROMEMCO INCORPORATED
-080005 SYMBOLICS INC.
-080006 SIEMENS AG
-080007 APPLE COMPUTER INC.
-080008 BOLT BERANEK AND NEWMAN INC.
-080009 HEWLETT PACKARD
-08000A NESTAR SYSTEMS INCORPORATED
-08000B UNISYS CORPORATION
-08000C MIKLYN DEVELOPMENT CO.
-08000D INTERNATIONAL COMPUTERS LTD.
-08000E NCR CORPORATION
-08000F MITEL CORPORATION
-080011 TEKTRONIX INC.
-080012 BELL ATLANTIC INTEGRATED SYST.
-080013 EXXON
-080014 EXCELAN
-080015 STC BUSINESS SYSTEMS
-080016 BARRISTER INFO SYS CORP
-080017 NATIONAL SEMICONDUCTOR
-080018 PIRELLI FOCOM NETWORKS
-080019 GENERAL ELECTRIC CORPORATION
-08001A TIARA/ 10NET
-08001B DATA GENERAL
-08001C KDD-KOKUSAI DEBNSIN DENWA CO.
-08001D ABLE COMMUNICATIONS INC.
-08001E APOLLO COMPUTER INC.
-08001F SHARP CORPORATION
-080020 SUN MICROSYSTEMS INC.
-080021 3M COMPANY
-080022 NBI INC.
-080023 Panasonic Communications Co., Ltd.
-080024 10NET COMMUNICATIONS/DCA
-080025 CONTROL DATA
-080026 NORSK DATA A.S.
-080027 CADMUS COMPUTER SYSTEMS
-080028 Texas Instruments
-080029 MEGATEK CORPORATION
-08002A MOSAIC TECHNOLOGIES INC.
-08002B DIGITAL EQUIPMENT CORPORATION
-08002C BRITTON LEE INC.
-08002D LAN-TEC INC.
-08002E METAPHOR COMPUTER SYSTEMS
-08002F PRIME COMPUTER INC.
-080030 NETWORK RESEARCH CORPORATION
-080030 CERN
-080030 ROYAL MELBOURNE INST OF TECH
-080031 LITTLE MACHINES INC.
-080032 TIGAN INCORPORATED
-080033 BAUSCH & LOMB
-080034 FILENET CORPORATION
-080035 MICROFIVE CORPORATION
-080036 INTERGRAPH CORPORATION
-080037 FUJI-XEROX CO. LTD.
-080038 CII HONEYWELL BULL
-080039 SPIDER SYSTEMS LIMITED
-08003A ORCATECH INC.
-08003B TORUS SYSTEMS LIMITED
-08003C SCHLUMBERGER WELL SERVICES
-08003D CADNETIX CORPORATIONS
-08003E CODEX CORPORATION
-08003F FRED KOSCHARA ENTERPRISES
-080040 FERRANTI COMPUTER SYS. LIMITED
-080041 RACAL-MILGO INFORMATION SYS..
-080042 JAPAN MACNICS CORP.
-080043 PIXEL COMPUTER INC.
-080044 DAVID SYSTEMS INC.
-080045 CONCURRENT COMPUTER CORP.
-080046 SONY CORPORATION LTD.
-080047 SEQUENT COMPUTER SYSTEMS INC.
-080048 EUROTHERM GAUGING SYSTEMS
-080049 UNIVATION
-08004A BANYAN SYSTEMS INC.
-08004B PLANNING RESEARCH CORP.
-08004C HYDRA COMPUTER SYSTEMS INC.
-08004D CORVUS SYSTEMS INC.
-08004E 3COM EUROPE LTD.
-08004F CYGNET SYSTEMS
-080050 DAISY SYSTEMS CORP.
-080051 EXPERDATA
-080052 INSYSTEC
-080053 MIDDLE EAST TECH. UNIVERSITY
-080055 STANFORD TELECOMM. INC.
-080056 STANFORD LINEAR ACCEL. CENTER
-080057 EVANS & SUTHERLAND
-080058 SYSTEMS CONCEPTS
-080059 A/S MYCRON
-08005A IBM CORPORATION
-08005B VTA TECHNOLOGIES INC.
-08005C FOUR PHASE SYSTEMS
-08005D GOULD INC.
-08005E COUNTERPOINT COMPUTER INC.
-08005F SABER TECHNOLOGY CORP.
-080060 INDUSTRIAL NETWORKING INC.
-080061 JAROGATE LTD.
-080062 GENERAL DYNAMICS
-080063 PLESSEY
-080064 AUTOPHON AG
-080065 GENRAD INC.
-080066 AGFA CORPORATION
-080067 COMDESIGN
-080068 RIDGE COMPUTERS
-080069 SILICON GRAPHICS INC.
-08006A ATT BELL LABORATORIES
-08006B ACCEL TECHNOLOGIES INC.
-08006C SUNTEK TECHNOLOGY INT'L
-08006D WHITECHAPEL COMPUTER WORKS
-08006E MASSCOMP
-08006F PHILIPS APELDOORN B.V.
-080070 MITSUBISHI ELECTRIC CORP.
-080071 MATRA (DSIE)
-080072 XEROX CORP UNIV GRANT PROGRAM
-080073 TECMAR INC.
-080074 CASIO COMPUTER CO. LTD.
-080075 DANSK DATA ELECTRONIK
-080076 PC LAN TECHNOLOGIES
-080077 TSL COMMUNICATIONS LTD.
-080078 ACCELL CORPORATION
-080079 THE DROID WORKS
-08007A INDATA
-08007B SANYO ELECTRIC CO. LTD.
-08007C VITALINK COMMUNICATIONS CORP.
-08007E AMALGAMATED WIRELESS(AUS) LTD
-08007F CARNEGIE-MELLON UNIVERSITY
-080080 AES DATA INC.
-080081 ,ASTECH INC.
-080082 VERITAS SOFTWARE
-080083 Seiko Instruments Inc.
-080084 TOMEN ELECTRONICS CORP.
-080085 ELXSI
-080086 KONICA MINOLTA HOLDINGS, INC.
-080087 XYPLEX
-080088 MCDATA CORPORATION
-080089 KINETICS
-08008A PERFORMANCE TECHNOLOGY
-08008B PYRAMID TECHNOLOGY CORP.
-08008C NETWORK RESEARCH CORPORATION
-08008D XYVISION INC.
-08008E TANDEM COMPUTERS
-08008F CHIPCOM CORPORATION
-080090 SONOMA SYSTEMS
-081443 UNIBRAIN S.A.
-08BBCC AK-NORD EDV VERTRIEBSGES. mbH
-10005A IBM CORPORATION
-1000E8 NATIONAL SEMICONDUCTOR
-800010 ATT BELL LABORATORIES
-A06A00 Verilink Corporation
-AA0000 DIGITAL EQUIPMENT CORPORATION
-AA0001 DIGITAL EQUIPMENT CORPORATION
-AA0002 DIGITAL EQUIPMENT CORPORATION
-AA0003 DIGITAL EQUIPMENT CORPORATION
-AA0004 DIGITAL EQUIPMENT CORPORATION
diff --git a/drivers/ieee1394/oui2c.sh b/drivers/ieee1394/oui2c.sh
deleted file mode 100644
index b9d0e8f..0000000
--- a/drivers/ieee1394/oui2c.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-
-cat <<EOF
-/* Generated file for OUI database */
-
-
-#ifdef CONFIG_IEEE1394_OUI_DB
-struct oui_list_struct {
-	int oui;
-	char *name;
-} oui_list[] = {
-EOF
-
-while read oui name; do
-	echo "	{ 0x$oui, \"$name\" },"
-done
-
-cat <<EOF
-};
-
-#endif /* CONFIG_IEEE1394_OUI_DB */
-EOF
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index fbb7f14..0742bef 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1434,6 +1434,7 @@
                 i2c_adapter_data = bit_data;
                 i2c_ad->algo_data = &i2c_adapter_data;
                 i2c_adapter_data.data = lynx;
+		i2c_ad->dev.parent = &dev->dev;
 
 		PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d",
 		       reg_read(lynx, SERIAL_EEPROM_CONTROL));
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index ad2108f..bb897a3 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -636,27 +636,32 @@
 
 	case RAW1394_REQ_SET_CARD:
 		spin_lock_irqsave(&host_info_lock, flags);
-		if (req->req.misc < host_count) {
-			list_for_each_entry(hi, &host_info_list, list) {
-				if (!req->req.misc--)
-					break;
-			}
-			get_device(&hi->host->device);	// XXX Need to handle failure case
-			list_add_tail(&fi->list, &hi->file_info_list);
-			fi->host = hi->host;
-			fi->state = connected;
-
-			req->req.error = RAW1394_ERROR_NONE;
-			req->req.generation = get_hpsb_generation(fi->host);
-			req->req.misc = (fi->host->node_id << 16)
-			    | fi->host->node_count;
-			if (fi->protocol_version > 3) {
-				req->req.misc |=
-				    NODEID_TO_NODE(fi->host->irm_id) << 8;
-			}
-		} else {
+		if (req->req.misc >= host_count) {
 			req->req.error = RAW1394_ERROR_INVALID_ARG;
+			goto out_set_card;
 		}
+		list_for_each_entry(hi, &host_info_list, list)
+			if (!req->req.misc--)
+				break;
+		get_device(&hi->host->device); /* FIXME handle failure case */
+		list_add_tail(&fi->list, &hi->file_info_list);
+
+		/* prevent unloading of the host's low-level driver */
+		if (!try_module_get(hi->host->driver->owner)) {
+			req->req.error = RAW1394_ERROR_ABORTED;
+			goto out_set_card;
+		}
+		WARN_ON(fi->host);
+		fi->host = hi->host;
+		fi->state = connected;
+
+		req->req.error = RAW1394_ERROR_NONE;
+		req->req.generation = get_hpsb_generation(fi->host);
+		req->req.misc = (fi->host->node_id << 16)
+				| fi->host->node_count;
+		if (fi->protocol_version > 3)
+			req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
+out_set_card:
 		spin_unlock_irqrestore(&host_info_lock, flags);
 
 		req->req.length = 0;
@@ -2664,6 +2669,18 @@
 	fi->iso_state = RAW1394_ISO_INACTIVE;
 }
 
+static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr)
+{
+	struct raw1394_cycle_timer ct;
+	int err;
+
+	err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
+	if (!err)
+		if (copy_to_user(uaddr, &ct, sizeof(ct)))
+			err = -EFAULT;
+	return err;
+}
+
 /* mmap the rawiso xmit/recv buffer */
 static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
 {
@@ -2772,6 +2789,14 @@
 		break;
 	}
 
+	/* state-independent commands */
+	switch(cmd) {
+	case RAW1394_IOC_GET_CYCLE_TIMER:
+		return raw1394_read_cycle_timer(fi, argp);
+	default:
+		break;
+	}
+
 	return -EINVAL;
 }
 
@@ -2955,6 +2980,11 @@
 		put_device(&fi->host->device);
 	}
 
+	spin_lock_irqsave(&host_info_lock, flags);
+	if (fi->host)
+		module_put(fi->host->driver->owner);
+	spin_unlock_irqrestore(&host_info_lock, flags);
+
 	kfree(fi);
 
 	return 0;
@@ -3003,7 +3033,7 @@
 };
 
 static struct cdev raw1394_cdev;
-static struct file_operations raw1394_fops = {
+static const struct file_operations raw1394_fops = {
 	.owner = THIS_MODULE,
 	.read = raw1394_read,
 	.write = raw1394_write,
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
index 35bfc38..7bd22ee 100644
--- a/drivers/ieee1394/raw1394.h
+++ b/drivers/ieee1394/raw1394.h
@@ -178,4 +178,14 @@
 	__s16 xmit_cycle;
 };
 
+/* argument to RAW1394_IOC_GET_CYCLE_TIMER ioctl */
+struct raw1394_cycle_timer {
+	/* contents of Isochronous Cycle Timer register,
+	   as in OHCI 1.1 clause 5.13 (also with non-OHCI hosts) */
+	__u32 cycle_timer;
+
+	/* local time in microseconds since Epoch,
+	   simultaneously read with cycle timer */
+	__u64 local_time;
+};
 #endif /* IEEE1394_RAW1394_H */
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 4325aac..4edfff4 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -51,7 +51,6 @@
  * Grep for inline FIXME comments below.
  */
 
-#include <linux/blkdev.h>
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -304,10 +303,11 @@
 	.use_clustering		 = ENABLE_CLUSTERING,
 	.cmd_per_lun		 = SBP2_MAX_CMDS,
 	.can_queue		 = SBP2_MAX_CMDS,
-	.emulated		 = 1,
 	.sdev_attrs		 = sbp2_sysfs_sdev_attrs,
 };
 
+/* for match-all entries in sbp2_workarounds_table */
+#define SBP2_ROM_VALUE_WILDCARD 0x1000000
 
 /*
  * List of devices with known bugs.
@@ -329,22 +329,14 @@
 	},
 	/* Initio bridges, actually only needed for some older ones */ {
 		.firmware_revision	= 0x000200,
+		.model_id		= SBP2_ROM_VALUE_WILDCARD,
 		.workarounds		= SBP2_WORKAROUND_INQUIRY_36,
 	},
 	/* Symbios bridge */ {
 		.firmware_revision	= 0xa0b800,
+		.model_id		= SBP2_ROM_VALUE_WILDCARD,
 		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS,
 	},
-	/*
-	 * Note about the following Apple iPod blacklist entries:
-	 *
-	 * There are iPods (2nd gen, 3rd gen) with model_id==0.  Since our
-	 * matching logic treats 0 as a wildcard, we cannot match this ID
-	 * without rewriting the matching routine.  Fortunately these iPods
-	 * do not feature the read_capacity bug according to one report.
-	 * Read_capacity behaviour as well as model_id could change due to
-	 * Apple-supplied firmware updates though.
-	 */
 	/* iPod 4th generation */ {
 		.firmware_revision	= 0x0a2700,
 		.model_id		= 0x000021,
@@ -1307,11 +1299,13 @@
 
 	if (!(workarounds & SBP2_WORKAROUND_OVERRIDE))
 		for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
-			if (sbp2_workarounds_table[i].firmware_revision &&
+			if (sbp2_workarounds_table[i].firmware_revision !=
+			    SBP2_ROM_VALUE_WILDCARD &&
 			    sbp2_workarounds_table[i].firmware_revision !=
 			    (firmware_revision & 0xffff00))
 				continue;
-			if (sbp2_workarounds_table[i].model_id &&
+			if (sbp2_workarounds_table[i].model_id !=
+			    SBP2_ROM_VALUE_WILDCARD &&
 			    sbp2_workarounds_table[i].model_id != ud->model_id)
 				continue;
 			workarounds |= sbp2_workarounds_table[i].workarounds;
@@ -2017,7 +2011,6 @@
 {
 	struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];
 
-	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
 	sdev->use_10_for_rw = 1;
 
 	if (sdev->type == TYPE_ROM)
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 598b19f..95ca26d 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -489,6 +489,9 @@
 			reset_ir_status(d, i);
 			d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
 			do_gettimeofday(&d->buffer_time[d->buffer_prg_assignment[i]]);
+			dma_region_sync_for_cpu(&d->dma,
+				d->buffer_prg_assignment[i] * d->buf_size,
+				d->buf_size);
 		}
 	}
 
@@ -1096,6 +1099,8 @@
 			DBGMSG(ohci->host->id, "Starting iso transmit DMA ctx=%d",
 			       d->ctx);
 			put_timestamp(ohci, d, d->last_buffer);
+			dma_region_sync_for_device(&d->dma,
+				v.buffer * d->buf_size, d->buf_size);
 
 			/* Tell the controller where the first program is */
 			reg_write(ohci, d->cmdPtr,
@@ -1111,6 +1116,9 @@
 				      "Waking up iso transmit dma ctx=%d",
 				      d->ctx);
 				put_timestamp(ohci, d, d->last_buffer);
+				dma_region_sync_for_device(&d->dma,
+					v.buffer * d->buf_size, d->buf_size);
+
 				reg_write(ohci, d->ctrlSet, 0x1000);
 			}
 		}
@@ -1269,7 +1277,7 @@
 #endif
 
 static struct cdev video1394_cdev;
-static struct file_operations video1394_fops=
+static const struct file_operations video1394_fops=
 {
 	.owner =	THIS_MODULE,
 	.unlocked_ioctl = video1394_ioctl,
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 9edface..66b36de 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -38,6 +38,7 @@
 source "drivers/infiniband/hw/ipath/Kconfig"
 source "drivers/infiniband/hw/ehca/Kconfig"
 source "drivers/infiniband/hw/amso1100/Kconfig"
+source "drivers/infiniband/hw/cxgb3/Kconfig"
 
 source "drivers/infiniband/ulp/ipoib/Kconfig"
 
diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile
index 2b5d109..da2066c 100644
--- a/drivers/infiniband/Makefile
+++ b/drivers/infiniband/Makefile
@@ -3,6 +3,7 @@
 obj-$(CONFIG_INFINIBAND_IPATH)		+= hw/ipath/
 obj-$(CONFIG_INFINIBAND_EHCA)		+= hw/ehca/
 obj-$(CONFIG_INFINIBAND_AMSO1100)	+= hw/amso1100/
+obj-$(CONFIG_INFINIBAND_CXGB3)		+= hw/cxgb3/
 obj-$(CONFIG_INFINIBAND_IPOIB)		+= ulp/ipoib/
 obj-$(CONFIG_INFINIBAND_SRP)		+= ulp/srp/
 obj-$(CONFIG_INFINIBAND_ISER)		+= ulp/iser/
diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index 50fb1cd..189e5d4 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -12,7 +12,7 @@
 
 ib_mad-y :=			mad.o smi.o agent.o mad_rmpp.o
 
-ib_sa-y :=			sa_query.o
+ib_sa-y :=			sa_query.o multicast.o
 
 ib_cm-y :=			cm.o
 
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index d2bb5a9..a91001c 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -373,7 +373,7 @@
 
 static int addr_init(void)
 {
-	addr_wq = create_singlethread_workqueue("ib_addr_wq");
+	addr_wq = create_singlethread_workqueue("ib_addr");
 	if (!addr_wq)
 		return -ENOMEM;
 
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 98272fb..558c9a0 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -38,7 +38,6 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/sched.h>	/* INIT_WORK, schedule_work(), flush_scheduled_work() */
 
 #include <rdma/ib_cache.h>
 
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 9e0ab04..f8d69b3 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -71,6 +71,8 @@
 static DEFINE_IDR(sdp_ps);
 static DEFINE_IDR(tcp_ps);
 static DEFINE_IDR(udp_ps);
+static DEFINE_IDR(ipoib_ps);
+static int next_port;
 
 struct cma_device {
 	struct list_head	list;
@@ -115,6 +117,7 @@
 	struct list_head	list;
 	struct list_head	listen_list;
 	struct cma_device	*cma_dev;
+	struct list_head	mc_list;
 
 	enum cma_state		state;
 	spinlock_t		lock;
@@ -133,10 +136,23 @@
 	} cm_id;
 
 	u32			seq_num;
+	u32			qkey;
 	u32			qp_num;
 	u8			srq;
 };
 
+struct cma_multicast {
+	struct rdma_id_private *id_priv;
+	union {
+		struct ib_sa_multicast *ib;
+	} multicast;
+	struct list_head	list;
+	void			*context;
+	struct sockaddr		addr;
+	u8			pad[sizeof(struct sockaddr_in6) -
+				    sizeof(struct sockaddr)];
+};
+
 struct cma_work {
 	struct work_struct	work;
 	struct rdma_id_private	*id;
@@ -242,6 +258,11 @@
 	hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF);
 }
 
+static inline int cma_is_ud_ps(enum rdma_port_space ps)
+{
+	return (ps == RDMA_PS_UDP || ps == RDMA_PS_IPOIB);
+}
+
 static void cma_attach_to_dev(struct rdma_id_private *id_priv,
 			      struct cma_device *cma_dev)
 {
@@ -264,19 +285,41 @@
 	id_priv->cma_dev = NULL;
 }
 
+static int cma_set_qkey(struct ib_device *device, u8 port_num,
+			enum rdma_port_space ps,
+			struct rdma_dev_addr *dev_addr, u32 *qkey)
+{
+	struct ib_sa_mcmember_rec rec;
+	int ret = 0;
+
+	switch (ps) {
+	case RDMA_PS_UDP:
+		*qkey = RDMA_UDP_QKEY;
+		break;
+	case RDMA_PS_IPOIB:
+		ib_addr_get_mgid(dev_addr, &rec.mgid);
+		ret = ib_sa_get_mcmember_rec(device, port_num, &rec.mgid, &rec);
+		*qkey = be32_to_cpu(rec.qkey);
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
 static int cma_acquire_dev(struct rdma_id_private *id_priv)
 {
-	enum rdma_node_type dev_type = id_priv->id.route.addr.dev_addr.dev_type;
+	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
 	struct cma_device *cma_dev;
 	union ib_gid gid;
 	int ret = -ENODEV;
 
-	switch (rdma_node_get_transport(dev_type)) {
+	switch (rdma_node_get_transport(dev_addr->dev_type)) {
 	case RDMA_TRANSPORT_IB:
-		ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+		ib_addr_get_sgid(dev_addr, &gid);
 		break;
 	case RDMA_TRANSPORT_IWARP:
-		iw_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+		iw_addr_get_sgid(dev_addr, &gid);
 		break;
 	default:
 		return -ENODEV;
@@ -286,7 +329,12 @@
 		ret = ib_find_cached_gid(cma_dev->device, &gid,
 					 &id_priv->id.port_num, NULL);
 		if (!ret) {
-			cma_attach_to_dev(id_priv, cma_dev);
+			ret = cma_set_qkey(cma_dev->device,
+					   id_priv->id.port_num,
+					   id_priv->id.ps, dev_addr,
+					   &id_priv->qkey);
+			if (!ret)
+				cma_attach_to_dev(id_priv, cma_dev);
 			break;
 		}
 	}
@@ -324,40 +372,50 @@
 	init_waitqueue_head(&id_priv->wait_remove);
 	atomic_set(&id_priv->dev_remove, 0);
 	INIT_LIST_HEAD(&id_priv->listen_list);
+	INIT_LIST_HEAD(&id_priv->mc_list);
 	get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
 
 	return &id_priv->id;
 }
 EXPORT_SYMBOL(rdma_create_id);
 
-static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
+static int cma_init_ud_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
 {
 	struct ib_qp_attr qp_attr;
-	struct rdma_dev_addr *dev_addr;
-	int ret;
+	int qp_attr_mask, ret;
 
-	dev_addr = &id_priv->id.route.addr.dev_addr;
-	ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
-				  ib_addr_get_pkey(dev_addr),
-				  &qp_attr.pkey_index);
+	qp_attr.qp_state = IB_QPS_INIT;
+	ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
 	if (ret)
 		return ret;
 
-	qp_attr.qp_state = IB_QPS_INIT;
-	qp_attr.qp_access_flags = 0;
-	qp_attr.port_num = id_priv->id.port_num;
-	return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS |
-					  IB_QP_PKEY_INDEX | IB_QP_PORT);
+	ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
+	if (ret)
+		return ret;
+
+	qp_attr.qp_state = IB_QPS_RTR;
+	ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE);
+	if (ret)
+		return ret;
+
+	qp_attr.qp_state = IB_QPS_RTS;
+	qp_attr.sq_psn = 0;
+	ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_SQ_PSN);
+
+	return ret;
 }
 
-static int cma_init_iw_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
+static int cma_init_conn_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
 {
 	struct ib_qp_attr qp_attr;
+	int qp_attr_mask, ret;
 
 	qp_attr.qp_state = IB_QPS_INIT;
-	qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+	ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
+	if (ret)
+		return ret;
 
-	return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS);
+	return ib_modify_qp(qp, &qp_attr, qp_attr_mask);
 }
 
 int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
@@ -375,18 +433,10 @@
 	if (IS_ERR(qp))
 		return PTR_ERR(qp);
 
-	switch (rdma_node_get_transport(id->device->node_type)) {
-	case RDMA_TRANSPORT_IB:
-		ret = cma_init_ib_qp(id_priv, qp);
-		break;
-	case RDMA_TRANSPORT_IWARP:
-		ret = cma_init_iw_qp(id_priv, qp);
-		break;
-	default:
-		ret = -ENOSYS;
-		break;
-	}
-
+	if (cma_is_ud_ps(id_priv->id.ps))
+		ret = cma_init_ud_qp(id_priv, qp);
+	else
+		ret = cma_init_conn_qp(id_priv, qp);
 	if (ret)
 		goto err;
 
@@ -459,23 +509,55 @@
 	return ib_modify_qp(id->qp, &qp_attr, IB_QP_STATE);
 }
 
+static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
+			       struct ib_qp_attr *qp_attr, int *qp_attr_mask)
+{
+	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+	int ret;
+
+	ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
+				  ib_addr_get_pkey(dev_addr),
+				  &qp_attr->pkey_index);
+	if (ret)
+		return ret;
+
+	qp_attr->port_num = id_priv->id.port_num;
+	*qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT;
+
+	if (cma_is_ud_ps(id_priv->id.ps)) {
+		qp_attr->qkey = id_priv->qkey;
+		*qp_attr_mask |= IB_QP_QKEY;
+	} else {
+		qp_attr->qp_access_flags = 0;
+		*qp_attr_mask |= IB_QP_ACCESS_FLAGS;
+	}
+	return 0;
+}
+
 int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
 		       int *qp_attr_mask)
 {
 	struct rdma_id_private *id_priv;
-	int ret;
+	int ret = 0;
 
 	id_priv = container_of(id, struct rdma_id_private, id);
 	switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
 	case RDMA_TRANSPORT_IB:
-		ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
-					 qp_attr_mask);
+		if (!id_priv->cm_id.ib || cma_is_ud_ps(id_priv->id.ps))
+			ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask);
+		else
+			ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
+						 qp_attr_mask);
 		if (qp_attr->qp_state == IB_QPS_RTR)
 			qp_attr->rq_psn = id_priv->seq_num;
 		break;
 	case RDMA_TRANSPORT_IWARP:
-		ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
-					qp_attr_mask);
+		if (!id_priv->cm_id.iw) {
+			qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+			*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
+		} else
+			ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
+						 qp_attr_mask);
 		break;
 	default:
 		ret = -ENOSYS;
@@ -697,6 +779,19 @@
 	mutex_unlock(&lock);
 }
 
+static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
+{
+	struct cma_multicast *mc;
+
+	while (!list_empty(&id_priv->mc_list)) {
+		mc = container_of(id_priv->mc_list.next,
+				  struct cma_multicast, list);
+		list_del(&mc->list);
+		ib_sa_free_multicast(mc->multicast.ib);
+		kfree(mc);
+	}
+}
+
 void rdma_destroy_id(struct rdma_cm_id *id)
 {
 	struct rdma_id_private *id_priv;
@@ -721,6 +816,7 @@
 		default:
 			break;
 		}
+		cma_leave_mc_groups(id_priv);
 		mutex_lock(&lock);
 		cma_detach_from_dev(id_priv);
 	}
@@ -971,7 +1067,7 @@
 	memset(&event, 0, sizeof event);
 	offset = cma_user_data_offset(listen_id->id.ps);
 	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
-	if (listen_id->id.ps == RDMA_PS_UDP) {
+	if (cma_is_ud_ps(listen_id->id.ps)) {
 		conn_id = cma_new_udp_id(&listen_id->id, ib_event);
 		event.param.ud.private_data = ib_event->private_data + offset;
 		event.param.ud.private_data_len =
@@ -1722,33 +1818,74 @@
 			  unsigned short snum)
 {
 	struct rdma_bind_list *bind_list;
-	int port, start, ret;
+	int port, ret;
 
-	bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
+	bind_list = kmalloc(sizeof *bind_list, GFP_KERNEL);
 	if (!bind_list)
 		return -ENOMEM;
 
-	start = snum ? snum : sysctl_local_port_range[0];
-
 	do {
-		ret = idr_get_new_above(ps, bind_list, start, &port);
+		ret = idr_get_new_above(ps, bind_list, snum, &port);
 	} while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
 
 	if (ret)
-		goto err;
+		goto err1;
 
-	if ((snum && port != snum) ||
-	    (!snum && port > sysctl_local_port_range[1])) {
-		idr_remove(ps, port);
+	if (port != snum) {
 		ret = -EADDRNOTAVAIL;
-		goto err;
+		goto err2;
 	}
 
 	bind_list->ps = ps;
 	bind_list->port = (unsigned short) port;
 	cma_bind_port(bind_list, id_priv);
 	return 0;
-err:
+err2:
+	idr_remove(ps, port);
+err1:
+	kfree(bind_list);
+	return ret;
+}
+
+static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv)
+{
+	struct rdma_bind_list *bind_list;
+	int port, ret;
+
+	bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
+	if (!bind_list)
+		return -ENOMEM;
+
+retry:
+	do {
+		ret = idr_get_new_above(ps, bind_list, next_port, &port);
+	} while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
+
+	if (ret)
+		goto err1;
+
+	if (port > sysctl_local_port_range[1]) {
+		if (next_port != sysctl_local_port_range[0]) {
+			idr_remove(ps, port);
+			next_port = sysctl_local_port_range[0];
+			goto retry;
+		}
+		ret = -EADDRNOTAVAIL;
+		goto err2;
+	}
+
+	if (port == sysctl_local_port_range[1])
+		next_port = sysctl_local_port_range[0];
+	else
+		next_port = port + 1;
+
+	bind_list->ps = ps;
+	bind_list->port = (unsigned short) port;
+	cma_bind_port(bind_list, id_priv);
+	return 0;
+err2:
+	idr_remove(ps, port);
+err1:
 	kfree(bind_list);
 	return ret;
 }
@@ -1805,13 +1942,16 @@
 	case RDMA_PS_UDP:
 		ps = &udp_ps;
 		break;
+	case RDMA_PS_IPOIB:
+		ps = &ipoib_ps;
+		break;
 	default:
 		return -EPROTONOSUPPORT;
 	}
 
 	mutex_lock(&lock);
 	if (cma_any_port(&id_priv->id.route.addr.src_addr))
-		ret = cma_alloc_port(ps, id_priv, 0);
+		ret = cma_alloc_any_port(ps, id_priv);
 	else
 		ret = cma_use_port(ps, id_priv);
 	mutex_unlock(&lock);
@@ -1919,7 +2059,7 @@
 			event.status = ib_event->param.sidr_rep_rcvd.status;
 			break;
 		}
-		if (rep->qkey != RDMA_UD_QKEY) {
+		if (id_priv->qkey != rep->qkey) {
 			event.event = RDMA_CM_EVENT_UNREACHABLE;
 			event.status = -EINVAL;
 			break;
@@ -2118,7 +2258,7 @@
 
 	switch (rdma_node_get_transport(id->device->node_type)) {
 	case RDMA_TRANSPORT_IB:
-		if (id->ps == RDMA_PS_UDP)
+		if (cma_is_ud_ps(id->ps))
 			ret = cma_resolve_ib_udp(id_priv, conn_param);
 		else
 			ret = cma_connect_ib(id_priv, conn_param);
@@ -2214,7 +2354,7 @@
 	rep.status = status;
 	if (status == IB_SIDR_SUCCESS) {
 		rep.qp_num = id_priv->qp_num;
-		rep.qkey = RDMA_UD_QKEY;
+		rep.qkey = id_priv->qkey;
 	}
 	rep.private_data = private_data;
 	rep.private_data_len = private_data_len;
@@ -2238,7 +2378,7 @@
 
 	switch (rdma_node_get_transport(id->device->node_type)) {
 	case RDMA_TRANSPORT_IB:
-		if (id->ps == RDMA_PS_UDP)
+		if (cma_is_ud_ps(id->ps))
 			ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
 						conn_param->private_data,
 						conn_param->private_data_len);
@@ -2299,7 +2439,7 @@
 
 	switch (rdma_node_get_transport(id->device->node_type)) {
 	case RDMA_TRANSPORT_IB:
-		if (id->ps == RDMA_PS_UDP)
+		if (cma_is_ud_ps(id->ps))
 			ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT,
 						private_data, private_data_len);
 		else
@@ -2350,6 +2490,178 @@
 }
 EXPORT_SYMBOL(rdma_disconnect);
 
+static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
+{
+	struct rdma_id_private *id_priv;
+	struct cma_multicast *mc = multicast->context;
+	struct rdma_cm_event event;
+	int ret;
+
+	id_priv = mc->id_priv;
+	atomic_inc(&id_priv->dev_remove);
+	if (!cma_comp(id_priv, CMA_ADDR_BOUND) &&
+	    !cma_comp(id_priv, CMA_ADDR_RESOLVED))
+		goto out;
+
+	if (!status && id_priv->id.qp)
+		status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid,
+					 multicast->rec.mlid);
+
+	memset(&event, 0, sizeof event);
+	event.status = status;
+	event.param.ud.private_data = mc->context;
+	if (!status) {
+		event.event = RDMA_CM_EVENT_MULTICAST_JOIN;
+		ib_init_ah_from_mcmember(id_priv->id.device,
+					 id_priv->id.port_num, &multicast->rec,
+					 &event.param.ud.ah_attr);
+		event.param.ud.qp_num = 0xFFFFFF;
+		event.param.ud.qkey = be32_to_cpu(multicast->rec.qkey);
+	} else
+		event.event = RDMA_CM_EVENT_MULTICAST_ERROR;
+
+	ret = id_priv->id.event_handler(&id_priv->id, &event);
+	if (ret) {
+		cma_exch(id_priv, CMA_DESTROYING);
+		cma_release_remove(id_priv);
+		rdma_destroy_id(&id_priv->id);
+		return 0;
+	}
+out:
+	cma_release_remove(id_priv);
+	return 0;
+}
+
+static void cma_set_mgid(struct rdma_id_private *id_priv,
+			 struct sockaddr *addr, union ib_gid *mgid)
+{
+	unsigned char mc_map[MAX_ADDR_LEN];
+	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+	struct sockaddr_in *sin = (struct sockaddr_in *) addr;
+	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
+
+	if (cma_any_addr(addr)) {
+		memset(mgid, 0, sizeof *mgid);
+	} else if ((addr->sa_family == AF_INET6) &&
+		   ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFF10A01B) ==
+								 0xFF10A01B)) {
+		/* IPv6 address is an SA assigned MGID. */
+		memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
+	} else {
+		ip_ib_mc_map(sin->sin_addr.s_addr, mc_map);
+		if (id_priv->id.ps == RDMA_PS_UDP)
+			mc_map[7] = 0x01;	/* Use RDMA CM signature */
+		mc_map[8] = ib_addr_get_pkey(dev_addr) >> 8;
+		mc_map[9] = (unsigned char) ib_addr_get_pkey(dev_addr);
+		*mgid = *(union ib_gid *) (mc_map + 4);
+	}
+}
+
+static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
+				 struct cma_multicast *mc)
+{
+	struct ib_sa_mcmember_rec rec;
+	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+	ib_sa_comp_mask comp_mask;
+	int ret;
+
+	ib_addr_get_mgid(dev_addr, &rec.mgid);
+	ret = ib_sa_get_mcmember_rec(id_priv->id.device, id_priv->id.port_num,
+				     &rec.mgid, &rec);
+	if (ret)
+		return ret;
+
+	cma_set_mgid(id_priv, &mc->addr, &rec.mgid);
+	if (id_priv->id.ps == RDMA_PS_UDP)
+		rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
+	ib_addr_get_sgid(dev_addr, &rec.port_gid);
+	rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
+	rec.join_state = 1;
+
+	comp_mask = IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
+		    IB_SA_MCMEMBER_REC_PKEY | IB_SA_MCMEMBER_REC_JOIN_STATE |
+		    IB_SA_MCMEMBER_REC_QKEY | IB_SA_MCMEMBER_REC_SL |
+		    IB_SA_MCMEMBER_REC_FLOW_LABEL |
+		    IB_SA_MCMEMBER_REC_TRAFFIC_CLASS;
+
+	mc->multicast.ib = ib_sa_join_multicast(&sa_client, id_priv->id.device,
+						id_priv->id.port_num, &rec,
+						comp_mask, GFP_KERNEL,
+						cma_ib_mc_handler, mc);
+	if (IS_ERR(mc->multicast.ib))
+		return PTR_ERR(mc->multicast.ib);
+
+	return 0;
+}
+
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
+			void *context)
+{
+	struct rdma_id_private *id_priv;
+	struct cma_multicast *mc;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (!cma_comp(id_priv, CMA_ADDR_BOUND) &&
+	    !cma_comp(id_priv, CMA_ADDR_RESOLVED))
+		return -EINVAL;
+
+	mc = kmalloc(sizeof *mc, GFP_KERNEL);
+	if (!mc)
+		return -ENOMEM;
+
+	memcpy(&mc->addr, addr, ip_addr_size(addr));
+	mc->context = context;
+	mc->id_priv = id_priv;
+
+	spin_lock(&id_priv->lock);
+	list_add(&mc->list, &id_priv->mc_list);
+	spin_unlock(&id_priv->lock);
+
+	switch (rdma_node_get_transport(id->device->node_type)) {
+	case RDMA_TRANSPORT_IB:
+		ret = cma_join_ib_multicast(id_priv, mc);
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+
+	if (ret) {
+		spin_lock_irq(&id_priv->lock);
+		list_del(&mc->list);
+		spin_unlock_irq(&id_priv->lock);
+		kfree(mc);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(rdma_join_multicast);
+
+void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
+{
+	struct rdma_id_private *id_priv;
+	struct cma_multicast *mc;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	spin_lock_irq(&id_priv->lock);
+	list_for_each_entry(mc, &id_priv->mc_list, list) {
+		if (!memcmp(&mc->addr, addr, ip_addr_size(addr))) {
+			list_del(&mc->list);
+			spin_unlock_irq(&id_priv->lock);
+
+			if (id->qp)
+				ib_detach_mcast(id->qp,
+						&mc->multicast.ib->rec.mgid,
+						mc->multicast.ib->rec.mlid);
+			ib_sa_free_multicast(mc->multicast.ib);
+			kfree(mc);
+			return;
+		}
+	}
+	spin_unlock_irq(&id_priv->lock);
+}
+EXPORT_SYMBOL(rdma_leave_multicast);
+
 static void cma_add_one(struct ib_device *device)
 {
 	struct cma_device *cma_dev;
@@ -2448,7 +2760,11 @@
 {
 	int ret;
 
-	cma_wq = create_singlethread_workqueue("rdma_cm_wq");
+	get_random_bytes(&next_port, sizeof next_port);
+	next_port = (next_port % (sysctl_local_port_range[1] -
+				  sysctl_local_port_range[0])) +
+		    sysctl_local_port_range[0];
+	cma_wq = create_singlethread_workqueue("rdma_cm");
 	if (!cma_wq)
 		return -ENOMEM;
 
@@ -2476,6 +2792,7 @@
 	idr_destroy(&sdp_ps);
 	idr_destroy(&tcp_ps);
 	idr_destroy(&udp_ps);
+	idr_destroy(&ipoib_ps);
 }
 
 module_init(cma_init);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 63d2a39..7fabb42 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -36,6 +36,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -93,7 +94,7 @@
 	};
 	int i;
 
-	for (i = 0; i < sizeof mandatory_table / sizeof mandatory_table[0]; ++i) {
+	for (i = 0; i < ARRAY_SIZE(mandatory_table); ++i) {
 		if (!*(void **) ((void *) device + mandatory_table[i].offset)) {
 			printk(KERN_WARNING "Device %s is missing mandatory function %s\n",
 			       device->name, mandatory_table[i].name);
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index 8926a2b..1d796e7 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -301,7 +301,7 @@
 
 	{
 		struct ib_pool_fmr *fmr;
-		struct ib_fmr_attr attr = {
+		struct ib_fmr_attr fmr_attr = {
 			.max_pages  = params->max_pages_per_fmr,
 			.max_maps   = pool->max_remaps,
 			.page_shift = params->page_shift
@@ -321,7 +321,7 @@
 			fmr->ref_count        = 0;
 			INIT_HLIST_NODE(&fmr->cache_node);
 
-			fmr->fmr = ib_alloc_fmr(pd, params->access, &attr);
+			fmr->fmr = ib_alloc_fmr(pd, params->access, &fmr_attr);
 			if (IS_ERR(fmr->fmr)) {
 				printk(KERN_WARNING "fmr_create failed for FMR %d", i);
 				kfree(fmr);
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 1039ad5..891d1fa 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -146,6 +146,12 @@
 	return 0;
 }
 
+static void free_cm_id(struct iwcm_id_private *cm_id_priv)
+{
+	dealloc_work_entries(cm_id_priv);
+	kfree(cm_id_priv);
+}
+
 /*
  * Release a reference on cm_id. If the last reference is being
  * released, enable the waiting thread (in iw_destroy_cm_id) to
@@ -153,21 +159,14 @@
  */
 static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
 {
-	int ret = 0;
-
 	BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
 	if (atomic_dec_and_test(&cm_id_priv->refcount)) {
 		BUG_ON(!list_empty(&cm_id_priv->work_list));
-		if (waitqueue_active(&cm_id_priv->destroy_comp.wait)) {
-			BUG_ON(cm_id_priv->state != IW_CM_STATE_DESTROYING);
-			BUG_ON(test_bit(IWCM_F_CALLBACK_DESTROY,
-					&cm_id_priv->flags));
-			ret = 1;
-		}
 		complete(&cm_id_priv->destroy_comp);
+		return 1;
 	}
 
-	return ret;
+	return 0;
 }
 
 static void add_ref(struct iw_cm_id *cm_id)
@@ -181,7 +180,11 @@
 {
 	struct iwcm_id_private *cm_id_priv;
 	cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
-	iwcm_deref_id(cm_id_priv);
+	if (iwcm_deref_id(cm_id_priv) &&
+	    test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
+		BUG_ON(!list_empty(&cm_id_priv->work_list));
+		free_cm_id(cm_id_priv);
+	}
 }
 
 static int cm_event_handler(struct iw_cm_id *cm_id, struct iw_cm_event *event);
@@ -355,7 +358,9 @@
 	case IW_CM_STATE_CONN_RECV:
 		/*
 		 * App called destroy before/without calling accept after
-		 * receiving connection request event notification.
+		 * receiving connection request event notification or
+		 * returned non zero from the event callback function.
+		 * In either case, must tell the provider to reject.
 		 */
 		cm_id_priv->state = IW_CM_STATE_DESTROYING;
 		break;
@@ -391,9 +396,7 @@
 
 	wait_for_completion(&cm_id_priv->destroy_comp);
 
-	dealloc_work_entries(cm_id_priv);
-
-	kfree(cm_id_priv);
+	free_cm_id(cm_id_priv);
 }
 EXPORT_SYMBOL(iw_destroy_cm_id);
 
@@ -647,10 +650,11 @@
 	/* Call the client CM handler */
 	ret = cm_id->cm_handler(cm_id, iw_event);
 	if (ret) {
+		iw_cm_reject(cm_id, NULL, 0);
 		set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
 		destroy_cm_id(cm_id);
 		if (atomic_read(&cm_id_priv->refcount)==0)
-			kfree(cm_id);
+			free_cm_id(cm_id_priv);
 	}
 
 out:
@@ -854,13 +858,12 @@
 			destroy_cm_id(&cm_id_priv->id);
 		}
 		BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
-		if (iwcm_deref_id(cm_id_priv))
-			return;
-
-		if (atomic_read(&cm_id_priv->refcount)==0 &&
-		    test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
-			dealloc_work_entries(cm_id_priv);
-			kfree(cm_id_priv);
+		if (iwcm_deref_id(cm_id_priv)) {
+			if (test_bit(IWCM_F_CALLBACK_DESTROY,
+				     &cm_id_priv->flags)) {
+				BUG_ON(!list_empty(&cm_id_priv->work_list));
+				free_cm_id(cm_id_priv);
+			}
 			return;
 		}
 		spin_lock_irqsave(&cm_id_priv->lock, flags);
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
new file mode 100644
index 0000000..4a579b3
--- /dev/null
+++ b/drivers/infiniband/core/multicast.c
@@ -0,0 +1,837 @@
+/*
+ * Copyright (c) 2006 Intel Corporation.  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/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <linux/random.h>
+
+#include <rdma/ib_cache.h>
+#include "sa.h"
+
+static void mcast_add_one(struct ib_device *device);
+static void mcast_remove_one(struct ib_device *device);
+
+static struct ib_client mcast_client = {
+	.name   = "ib_multicast",
+	.add    = mcast_add_one,
+	.remove = mcast_remove_one
+};
+
+static struct ib_sa_client	sa_client;
+static struct workqueue_struct	*mcast_wq;
+static union ib_gid mgid0;
+
+struct mcast_device;
+
+struct mcast_port {
+	struct mcast_device	*dev;
+	spinlock_t		lock;
+	struct rb_root		table;
+	atomic_t		refcount;
+	struct completion	comp;
+	u8			port_num;
+};
+
+struct mcast_device {
+	struct ib_device	*device;
+	struct ib_event_handler	event_handler;
+	int			start_port;
+	int			end_port;
+	struct mcast_port	port[0];
+};
+
+enum mcast_state {
+	MCAST_IDLE,
+	MCAST_JOINING,
+	MCAST_MEMBER,
+	MCAST_BUSY,
+	MCAST_ERROR
+};
+
+struct mcast_member;
+
+struct mcast_group {
+	struct ib_sa_mcmember_rec rec;
+	struct rb_node		node;
+	struct mcast_port	*port;
+	spinlock_t		lock;
+	struct work_struct	work;
+	struct list_head	pending_list;
+	struct list_head	active_list;
+	struct mcast_member	*last_join;
+	int			members[3];
+	atomic_t		refcount;
+	enum mcast_state	state;
+	struct ib_sa_query	*query;
+	int			query_id;
+};
+
+struct mcast_member {
+	struct ib_sa_multicast	multicast;
+	struct ib_sa_client	*client;
+	struct mcast_group	*group;
+	struct list_head	list;
+	enum mcast_state	state;
+	atomic_t		refcount;
+	struct completion	comp;
+};
+
+static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
+			 void *context);
+static void leave_handler(int status, struct ib_sa_mcmember_rec *rec,
+			  void *context);
+
+static struct mcast_group *mcast_find(struct mcast_port *port,
+				      union ib_gid *mgid)
+{
+	struct rb_node *node = port->table.rb_node;
+	struct mcast_group *group;
+	int ret;
+
+	while (node) {
+		group = rb_entry(node, struct mcast_group, node);
+		ret = memcmp(mgid->raw, group->rec.mgid.raw, sizeof *mgid);
+		if (!ret)
+			return group;
+
+		if (ret < 0)
+			node = node->rb_left;
+		else
+			node = node->rb_right;
+	}
+	return NULL;
+}
+
+static struct mcast_group *mcast_insert(struct mcast_port *port,
+					struct mcast_group *group,
+					int allow_duplicates)
+{
+	struct rb_node **link = &port->table.rb_node;
+	struct rb_node *parent = NULL;
+	struct mcast_group *cur_group;
+	int ret;
+
+	while (*link) {
+		parent = *link;
+		cur_group = rb_entry(parent, struct mcast_group, node);
+
+		ret = memcmp(group->rec.mgid.raw, cur_group->rec.mgid.raw,
+			     sizeof group->rec.mgid);
+		if (ret < 0)
+			link = &(*link)->rb_left;
+		else if (ret > 0)
+			link = &(*link)->rb_right;
+		else if (allow_duplicates)
+			link = &(*link)->rb_left;
+		else
+			return cur_group;
+	}
+	rb_link_node(&group->node, parent, link);
+	rb_insert_color(&group->node, &port->table);
+	return NULL;
+}
+
+static void deref_port(struct mcast_port *port)
+{
+	if (atomic_dec_and_test(&port->refcount))
+		complete(&port->comp);
+}
+
+static void release_group(struct mcast_group *group)
+{
+	struct mcast_port *port = group->port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (atomic_dec_and_test(&group->refcount)) {
+		rb_erase(&group->node, &port->table);
+		spin_unlock_irqrestore(&port->lock, flags);
+		kfree(group);
+		deref_port(port);
+	} else
+		spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void deref_member(struct mcast_member *member)
+{
+	if (atomic_dec_and_test(&member->refcount))
+		complete(&member->comp);
+}
+
+static void queue_join(struct mcast_member *member)
+{
+	struct mcast_group *group = member->group;
+	unsigned long flags;
+
+	spin_lock_irqsave(&group->lock, flags);
+	list_add(&member->list, &group->pending_list);
+	if (group->state == MCAST_IDLE) {
+		group->state = MCAST_BUSY;
+		atomic_inc(&group->refcount);
+		queue_work(mcast_wq, &group->work);
+	}
+	spin_unlock_irqrestore(&group->lock, flags);
+}
+
+/*
+ * A multicast group has three types of members: full member, non member, and
+ * send only member.  We need to keep track of the number of members of each
+ * type based on their join state.  Adjust the number of members the belong to
+ * the specified join states.
+ */
+static void adjust_membership(struct mcast_group *group, u8 join_state, int inc)
+{
+	int i;
+
+	for (i = 0; i < 3; i++, join_state >>= 1)
+		if (join_state & 0x1)
+			group->members[i] += inc;
+}
+
+/*
+ * If a multicast group has zero members left for a particular join state, but
+ * the group is still a member with the SA, we need to leave that join state.
+ * Determine which join states we still belong to, but that do not have any
+ * active members.
+ */
+static u8 get_leave_state(struct mcast_group *group)
+{
+	u8 leave_state = 0;
+	int i;
+
+	for (i = 0; i < 3; i++)
+		if (!group->members[i])
+			leave_state |= (0x1 << i);
+
+	return leave_state & group->rec.join_state;
+}
+
+static int check_selector(ib_sa_comp_mask comp_mask,
+			  ib_sa_comp_mask selector_mask,
+			  ib_sa_comp_mask value_mask,
+			  u8 selector, u8 src_value, u8 dst_value)
+{
+	int err;
+
+	if (!(comp_mask & selector_mask) || !(comp_mask & value_mask))
+		return 0;
+
+	switch (selector) {
+	case IB_SA_GT:
+		err = (src_value <= dst_value);
+		break;
+	case IB_SA_LT:
+		err = (src_value >= dst_value);
+		break;
+	case IB_SA_EQ:
+		err = (src_value != dst_value);
+		break;
+	default:
+		err = 0;
+		break;
+	}
+
+	return err;
+}
+
+static int cmp_rec(struct ib_sa_mcmember_rec *src,
+		   struct ib_sa_mcmember_rec *dst, ib_sa_comp_mask comp_mask)
+{
+	/* MGID must already match */
+
+	if (comp_mask & IB_SA_MCMEMBER_REC_PORT_GID &&
+	    memcmp(&src->port_gid, &dst->port_gid, sizeof src->port_gid))
+		return -EINVAL;
+	if (comp_mask & IB_SA_MCMEMBER_REC_QKEY && src->qkey != dst->qkey)
+		return -EINVAL;
+	if (comp_mask & IB_SA_MCMEMBER_REC_MLID && src->mlid != dst->mlid)
+		return -EINVAL;
+	if (check_selector(comp_mask, IB_SA_MCMEMBER_REC_MTU_SELECTOR,
+			   IB_SA_MCMEMBER_REC_MTU, dst->mtu_selector,
+			   src->mtu, dst->mtu))
+		return -EINVAL;
+	if (comp_mask & IB_SA_MCMEMBER_REC_TRAFFIC_CLASS &&
+	    src->traffic_class != dst->traffic_class)
+		return -EINVAL;
+	if (comp_mask & IB_SA_MCMEMBER_REC_PKEY && src->pkey != dst->pkey)
+		return -EINVAL;
+	if (check_selector(comp_mask, IB_SA_MCMEMBER_REC_RATE_SELECTOR,
+			   IB_SA_MCMEMBER_REC_RATE, dst->rate_selector,
+			   src->rate, dst->rate))
+		return -EINVAL;
+	if (check_selector(comp_mask,
+			   IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME_SELECTOR,
+			   IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME,
+			   dst->packet_life_time_selector,
+			   src->packet_life_time, dst->packet_life_time))
+		return -EINVAL;
+	if (comp_mask & IB_SA_MCMEMBER_REC_SL && src->sl != dst->sl)
+		return -EINVAL;
+	if (comp_mask & IB_SA_MCMEMBER_REC_FLOW_LABEL &&
+	    src->flow_label != dst->flow_label)
+		return -EINVAL;
+	if (comp_mask & IB_SA_MCMEMBER_REC_HOP_LIMIT &&
+	    src->hop_limit != dst->hop_limit)
+		return -EINVAL;
+	if (comp_mask & IB_SA_MCMEMBER_REC_SCOPE && src->scope != dst->scope)
+		return -EINVAL;
+
+	/* join_state checked separately, proxy_join ignored */
+
+	return 0;
+}
+
+static int send_join(struct mcast_group *group, struct mcast_member *member)
+{
+	struct mcast_port *port = group->port;
+	int ret;
+
+	group->last_join = member;
+	ret = ib_sa_mcmember_rec_query(&sa_client, port->dev->device,
+				       port->port_num, IB_MGMT_METHOD_SET,
+				       &member->multicast.rec,
+				       member->multicast.comp_mask,
+				       3000, GFP_KERNEL, join_handler, group,
+				       &group->query);
+	if (ret >= 0) {
+		group->query_id = ret;
+		ret = 0;
+	}
+	return ret;
+}
+
+static int send_leave(struct mcast_group *group, u8 leave_state)
+{
+	struct mcast_port *port = group->port;
+	struct ib_sa_mcmember_rec rec;
+	int ret;
+
+	rec = group->rec;
+	rec.join_state = leave_state;
+
+	ret = ib_sa_mcmember_rec_query(&sa_client, port->dev->device,
+				       port->port_num, IB_SA_METHOD_DELETE, &rec,
+				       IB_SA_MCMEMBER_REC_MGID     |
+				       IB_SA_MCMEMBER_REC_PORT_GID |
+				       IB_SA_MCMEMBER_REC_JOIN_STATE,
+				       3000, GFP_KERNEL, leave_handler,
+				       group, &group->query);
+	if (ret >= 0) {
+		group->query_id = ret;
+		ret = 0;
+	}
+	return ret;
+}
+
+static void join_group(struct mcast_group *group, struct mcast_member *member,
+		       u8 join_state)
+{
+	member->state = MCAST_MEMBER;
+	adjust_membership(group, join_state, 1);
+	group->rec.join_state |= join_state;
+	member->multicast.rec = group->rec;
+	member->multicast.rec.join_state = join_state;
+	list_move(&member->list, &group->active_list);
+}
+
+static int fail_join(struct mcast_group *group, struct mcast_member *member,
+		     int status)
+{
+	spin_lock_irq(&group->lock);
+	list_del_init(&member->list);
+	spin_unlock_irq(&group->lock);
+	return member->multicast.callback(status, &member->multicast);
+}
+
+static void process_group_error(struct mcast_group *group)
+{
+	struct mcast_member *member;
+	int ret;
+
+	spin_lock_irq(&group->lock);
+	while (!list_empty(&group->active_list)) {
+		member = list_entry(group->active_list.next,
+				    struct mcast_member, list);
+		atomic_inc(&member->refcount);
+		list_del_init(&member->list);
+		adjust_membership(group, member->multicast.rec.join_state, -1);
+		member->state = MCAST_ERROR;
+		spin_unlock_irq(&group->lock);
+
+		ret = member->multicast.callback(-ENETRESET,
+						 &member->multicast);
+		deref_member(member);
+		if (ret)
+			ib_sa_free_multicast(&member->multicast);
+		spin_lock_irq(&group->lock);
+	}
+
+	group->rec.join_state = 0;
+	group->state = MCAST_BUSY;
+	spin_unlock_irq(&group->lock);
+}
+
+static void mcast_work_handler(struct work_struct *work)
+{
+	struct mcast_group *group;
+	struct mcast_member *member;
+	struct ib_sa_multicast *multicast;
+	int status, ret;
+	u8 join_state;
+
+	group = container_of(work, typeof(*group), work);
+retest:
+	spin_lock_irq(&group->lock);
+	while (!list_empty(&group->pending_list) ||
+	       (group->state == MCAST_ERROR)) {
+
+		if (group->state == MCAST_ERROR) {
+			spin_unlock_irq(&group->lock);
+			process_group_error(group);
+			goto retest;
+		}
+
+		member = list_entry(group->pending_list.next,
+				    struct mcast_member, list);
+		multicast = &member->multicast;
+		join_state = multicast->rec.join_state;
+		atomic_inc(&member->refcount);
+
+		if (join_state == (group->rec.join_state & join_state)) {
+			status = cmp_rec(&group->rec, &multicast->rec,
+					 multicast->comp_mask);
+			if (!status)
+				join_group(group, member, join_state);
+			else
+				list_del_init(&member->list);
+			spin_unlock_irq(&group->lock);
+			ret = multicast->callback(status, multicast);
+		} else {
+			spin_unlock_irq(&group->lock);
+			status = send_join(group, member);
+			if (!status) {
+				deref_member(member);
+				return;
+			}
+			ret = fail_join(group, member, status);
+		}
+
+		deref_member(member);
+		if (ret)
+			ib_sa_free_multicast(&member->multicast);
+		spin_lock_irq(&group->lock);
+	}
+
+	join_state = get_leave_state(group);
+	if (join_state) {
+		group->rec.join_state &= ~join_state;
+		spin_unlock_irq(&group->lock);
+		if (send_leave(group, join_state))
+			goto retest;
+	} else {
+		group->state = MCAST_IDLE;
+		spin_unlock_irq(&group->lock);
+		release_group(group);
+	}
+}
+
+/*
+ * Fail a join request if it is still active - at the head of the pending queue.
+ */
+static void process_join_error(struct mcast_group *group, int status)
+{
+	struct mcast_member *member;
+	int ret;
+
+	spin_lock_irq(&group->lock);
+	member = list_entry(group->pending_list.next,
+			    struct mcast_member, list);
+	if (group->last_join == member) {
+		atomic_inc(&member->refcount);
+		list_del_init(&member->list);
+		spin_unlock_irq(&group->lock);
+		ret = member->multicast.callback(status, &member->multicast);
+		deref_member(member);
+		if (ret)
+			ib_sa_free_multicast(&member->multicast);
+	} else
+		spin_unlock_irq(&group->lock);
+}
+
+static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
+			 void *context)
+{
+	struct mcast_group *group = context;
+
+	if (status)
+		process_join_error(group, status);
+	else {
+		spin_lock_irq(&group->port->lock);
+		group->rec = *rec;
+		if (!memcmp(&mgid0, &group->rec.mgid, sizeof mgid0)) {
+			rb_erase(&group->node, &group->port->table);
+			mcast_insert(group->port, group, 1);
+		}
+		spin_unlock_irq(&group->port->lock);
+	}
+	mcast_work_handler(&group->work);
+}
+
+static void leave_handler(int status, struct ib_sa_mcmember_rec *rec,
+			  void *context)
+{
+	struct mcast_group *group = context;
+
+	mcast_work_handler(&group->work);
+}
+
+static struct mcast_group *acquire_group(struct mcast_port *port,
+					 union ib_gid *mgid, gfp_t gfp_mask)
+{
+	struct mcast_group *group, *cur_group;
+	unsigned long flags;
+	int is_mgid0;
+
+	is_mgid0 = !memcmp(&mgid0, mgid, sizeof mgid0);
+	if (!is_mgid0) {
+		spin_lock_irqsave(&port->lock, flags);
+		group = mcast_find(port, mgid);
+		if (group)
+			goto found;
+		spin_unlock_irqrestore(&port->lock, flags);
+	}
+
+	group = kzalloc(sizeof *group, gfp_mask);
+	if (!group)
+		return NULL;
+
+	group->port = port;
+	group->rec.mgid = *mgid;
+	INIT_LIST_HEAD(&group->pending_list);
+	INIT_LIST_HEAD(&group->active_list);
+	INIT_WORK(&group->work, mcast_work_handler);
+	spin_lock_init(&group->lock);
+
+	spin_lock_irqsave(&port->lock, flags);
+	cur_group = mcast_insert(port, group, is_mgid0);
+	if (cur_group) {
+		kfree(group);
+		group = cur_group;
+	} else
+		atomic_inc(&port->refcount);
+found:
+	atomic_inc(&group->refcount);
+	spin_unlock_irqrestore(&port->lock, flags);
+	return group;
+}
+
+/*
+ * We serialize all join requests to a single group to make our lives much
+ * easier.  Otherwise, two users could try to join the same group
+ * simultaneously, with different configurations, one could leave while the
+ * join is in progress, etc., which makes locking around error recovery
+ * difficult.
+ */
+struct ib_sa_multicast *
+ib_sa_join_multicast(struct ib_sa_client *client,
+		     struct ib_device *device, u8 port_num,
+		     struct ib_sa_mcmember_rec *rec,
+		     ib_sa_comp_mask comp_mask, gfp_t gfp_mask,
+		     int (*callback)(int status,
+				     struct ib_sa_multicast *multicast),
+		     void *context)
+{
+	struct mcast_device *dev;
+	struct mcast_member *member;
+	struct ib_sa_multicast *multicast;
+	int ret;
+
+	dev = ib_get_client_data(device, &mcast_client);
+	if (!dev)
+		return ERR_PTR(-ENODEV);
+
+	member = kmalloc(sizeof *member, gfp_mask);
+	if (!member)
+		return ERR_PTR(-ENOMEM);
+
+	ib_sa_client_get(client);
+	member->client = client;
+	member->multicast.rec = *rec;
+	member->multicast.comp_mask = comp_mask;
+	member->multicast.callback = callback;
+	member->multicast.context = context;
+	init_completion(&member->comp);
+	atomic_set(&member->refcount, 1);
+	member->state = MCAST_JOINING;
+
+	member->group = acquire_group(&dev->port[port_num - dev->start_port],
+				      &rec->mgid, gfp_mask);
+	if (!member->group) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/*
+	 * The user will get the multicast structure in their callback.  They
+	 * could then free the multicast structure before we can return from
+	 * this routine.  So we save the pointer to return before queuing
+	 * any callback.
+	 */
+	multicast = &member->multicast;
+	queue_join(member);
+	return multicast;
+
+err:
+	ib_sa_client_put(client);
+	kfree(member);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(ib_sa_join_multicast);
+
+void ib_sa_free_multicast(struct ib_sa_multicast *multicast)
+{
+	struct mcast_member *member;
+	struct mcast_group *group;
+
+	member = container_of(multicast, struct mcast_member, multicast);
+	group = member->group;
+
+	spin_lock_irq(&group->lock);
+	if (member->state == MCAST_MEMBER)
+		adjust_membership(group, multicast->rec.join_state, -1);
+
+	list_del_init(&member->list);
+
+	if (group->state == MCAST_IDLE) {
+		group->state = MCAST_BUSY;
+		spin_unlock_irq(&group->lock);
+		/* Continue to hold reference on group until callback */
+		queue_work(mcast_wq, &group->work);
+	} else {
+		spin_unlock_irq(&group->lock);
+		release_group(group);
+	}
+
+	deref_member(member);
+	wait_for_completion(&member->comp);
+	ib_sa_client_put(member->client);
+	kfree(member);
+}
+EXPORT_SYMBOL(ib_sa_free_multicast);
+
+int ib_sa_get_mcmember_rec(struct ib_device *device, u8 port_num,
+			   union ib_gid *mgid, struct ib_sa_mcmember_rec *rec)
+{
+	struct mcast_device *dev;
+	struct mcast_port *port;
+	struct mcast_group *group;
+	unsigned long flags;
+	int ret = 0;
+
+	dev = ib_get_client_data(device, &mcast_client);
+	if (!dev)
+		return -ENODEV;
+
+	port = &dev->port[port_num - dev->start_port];
+	spin_lock_irqsave(&port->lock, flags);
+	group = mcast_find(port, mgid);
+	if (group)
+		*rec = group->rec;
+	else
+		ret = -EADDRNOTAVAIL;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(ib_sa_get_mcmember_rec);
+
+int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
+			     struct ib_sa_mcmember_rec *rec,
+			     struct ib_ah_attr *ah_attr)
+{
+	int ret;
+	u16 gid_index;
+	u8 p;
+
+	ret = ib_find_cached_gid(device, &rec->port_gid, &p, &gid_index);
+	if (ret)
+		return ret;
+
+	memset(ah_attr, 0, sizeof *ah_attr);
+	ah_attr->dlid = be16_to_cpu(rec->mlid);
+	ah_attr->sl = rec->sl;
+	ah_attr->port_num = port_num;
+	ah_attr->static_rate = rec->rate;
+
+	ah_attr->ah_flags = IB_AH_GRH;
+	ah_attr->grh.dgid = rec->mgid;
+
+	ah_attr->grh.sgid_index = (u8) gid_index;
+	ah_attr->grh.flow_label = be32_to_cpu(rec->flow_label);
+	ah_attr->grh.hop_limit = rec->hop_limit;
+	ah_attr->grh.traffic_class = rec->traffic_class;
+
+	return 0;
+}
+EXPORT_SYMBOL(ib_init_ah_from_mcmember);
+
+static void mcast_groups_lost(struct mcast_port *port)
+{
+	struct mcast_group *group;
+	struct rb_node *node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	for (node = rb_first(&port->table); node; node = rb_next(node)) {
+		group = rb_entry(node, struct mcast_group, node);
+		spin_lock(&group->lock);
+		if (group->state == MCAST_IDLE) {
+			atomic_inc(&group->refcount);
+			queue_work(mcast_wq, &group->work);
+		}
+		group->state = MCAST_ERROR;
+		spin_unlock(&group->lock);
+	}
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void mcast_event_handler(struct ib_event_handler *handler,
+				struct ib_event *event)
+{
+	struct mcast_device *dev;
+
+	dev = container_of(handler, struct mcast_device, event_handler);
+
+	switch (event->event) {
+	case IB_EVENT_PORT_ERR:
+	case IB_EVENT_LID_CHANGE:
+	case IB_EVENT_SM_CHANGE:
+	case IB_EVENT_CLIENT_REREGISTER:
+		mcast_groups_lost(&dev->port[event->element.port_num -
+					     dev->start_port]);
+		break;
+	default:
+		break;
+	}
+}
+
+static void mcast_add_one(struct ib_device *device)
+{
+	struct mcast_device *dev;
+	struct mcast_port *port;
+	int i;
+
+	if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+		return;
+
+	dev = kmalloc(sizeof *dev + device->phys_port_cnt * sizeof *port,
+		      GFP_KERNEL);
+	if (!dev)
+		return;
+
+	if (device->node_type == RDMA_NODE_IB_SWITCH)
+		dev->start_port = dev->end_port = 0;
+	else {
+		dev->start_port = 1;
+		dev->end_port = device->phys_port_cnt;
+	}
+
+	for (i = 0; i <= dev->end_port - dev->start_port; i++) {
+		port = &dev->port[i];
+		port->dev = dev;
+		port->port_num = dev->start_port + i;
+		spin_lock_init(&port->lock);
+		port->table = RB_ROOT;
+		init_completion(&port->comp);
+		atomic_set(&port->refcount, 1);
+	}
+
+	dev->device = device;
+	ib_set_client_data(device, &mcast_client, dev);
+
+	INIT_IB_EVENT_HANDLER(&dev->event_handler, device, mcast_event_handler);
+	ib_register_event_handler(&dev->event_handler);
+}
+
+static void mcast_remove_one(struct ib_device *device)
+{
+	struct mcast_device *dev;
+	struct mcast_port *port;
+	int i;
+
+	dev = ib_get_client_data(device, &mcast_client);
+	if (!dev)
+		return;
+
+	ib_unregister_event_handler(&dev->event_handler);
+	flush_workqueue(mcast_wq);
+
+	for (i = 0; i <= dev->end_port - dev->start_port; i++) {
+		port = &dev->port[i];
+		deref_port(port);
+		wait_for_completion(&port->comp);
+	}
+
+	kfree(dev);
+}
+
+int mcast_init(void)
+{
+	int ret;
+
+	mcast_wq = create_singlethread_workqueue("ib_mcast");
+	if (!mcast_wq)
+		return -ENOMEM;
+
+	ib_sa_register_client(&sa_client);
+
+	ret = ib_register_client(&mcast_client);
+	if (ret)
+		goto err;
+	return 0;
+
+err:
+	ib_sa_unregister_client(&sa_client);
+	destroy_workqueue(mcast_wq);
+	return ret;
+}
+
+void mcast_cleanup(void)
+{
+	ib_unregister_client(&mcast_client);
+	ib_sa_unregister_client(&sa_client);
+	destroy_workqueue(mcast_wq);
+}
diff --git a/drivers/infiniband/core/sa.h b/drivers/infiniband/core/sa.h
new file mode 100644
index 0000000..24c93fd
--- /dev/null
+++ b/drivers/infiniband/core/sa.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
+ * Copyright (c) 2006 Intel Corporation.  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 SA_H
+#define SA_H
+
+#include <rdma/ib_sa.h>
+
+static inline void ib_sa_client_get(struct ib_sa_client *client)
+{
+	atomic_inc(&client->users);
+}
+
+static inline void ib_sa_client_put(struct ib_sa_client *client)
+{
+	if (atomic_dec_and_test(&client->users))
+		complete(&client->comp);
+}
+
+int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
+			     struct ib_device *device, u8 port_num,
+			     u8 method,
+			     struct ib_sa_mcmember_rec *rec,
+			     ib_sa_comp_mask comp_mask,
+			     int timeout_ms, gfp_t gfp_mask,
+			     void (*callback)(int status,
+					      struct ib_sa_mcmember_rec *resp,
+					      void *context),
+			     void *context,
+			     struct ib_sa_query **sa_query);
+
+int mcast_init(void);
+void mcast_cleanup(void);
+
+#endif /* SA_H */
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index e45afba..68db633 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -47,8 +47,8 @@
 #include <linux/workqueue.h>
 
 #include <rdma/ib_pack.h>
-#include <rdma/ib_sa.h>
 #include <rdma/ib_cache.h>
+#include "sa.h"
 
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("InfiniBand subnet administration query support");
@@ -425,17 +425,6 @@
 }
 EXPORT_SYMBOL(ib_sa_register_client);
 
-static inline void ib_sa_client_get(struct ib_sa_client *client)
-{
-	atomic_inc(&client->users);
-}
-
-static inline void ib_sa_client_put(struct ib_sa_client *client)
-{
-	if (atomic_dec_and_test(&client->users))
-		complete(&client->comp);
-}
-
 void ib_sa_unregister_client(struct ib_sa_client *client)
 {
 	ib_sa_client_put(client);
@@ -482,6 +471,7 @@
 	ah_attr->sl = rec->sl;
 	ah_attr->src_path_bits = be16_to_cpu(rec->slid) & 0x7f;
 	ah_attr->port_num = port_num;
+	ah_attr->static_rate = rec->rate;
 
 	if (rec->hop_limit > 1) {
 		ah_attr->ah_flags = IB_AH_GRH;
@@ -901,7 +891,6 @@
 	kfree(query);
 	return ret;
 }
-EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
 
 static void send_handler(struct ib_mad_agent *agent,
 			 struct ib_mad_send_wc *mad_send_wc)
@@ -1053,14 +1042,27 @@
 	get_random_bytes(&tid, sizeof tid);
 
 	ret = ib_register_client(&sa_client);
-	if (ret)
+	if (ret) {
 		printk(KERN_ERR "Couldn't register ib_sa client\n");
+		goto err1;
+	}
 
+	ret = mcast_init();
+	if (ret) {
+		printk(KERN_ERR "Couldn't initialize multicast handling\n");
+		goto err2;
+	}
+
+	return 0;
+err2:
+	ib_unregister_client(&sa_client);
+err1:
 	return ret;
 }
 
 static void __exit ib_sa_cleanup(void)
 {
+	mcast_cleanup();
 	ib_unregister_client(&sa_client);
 	idr_destroy(&query_idr);
 }
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 709323c..000c086 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -714,8 +714,6 @@
 		if (ret)
 			goto err_put;
 	} else {
-		int i;
-
 		for (i = 1; i <= device->phys_port_cnt; ++i) {
 			ret = add_port(device, i);
 			if (ret)
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index f15220a..ee51d79 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1221,7 +1221,7 @@
 	kfree(dev);
 }
 
-static struct file_operations ucm_fops = {
+static const struct file_operations ucm_fops = {
 	.owner 	 = THIS_MODULE,
 	.open 	 = ib_ucm_open,
 	.release = ib_ucm_close,
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index e2e8d32..b516b93 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -70,10 +70,24 @@
 	u64			uid;
 
 	struct list_head	list;
+	struct list_head	mc_list;
+};
+
+struct ucma_multicast {
+	struct ucma_context	*ctx;
+	int			id;
+	int			events_reported;
+
+	u64			uid;
+	struct list_head	list;
+	struct sockaddr		addr;
+	u8			pad[sizeof(struct sockaddr_in6) -
+				    sizeof(struct sockaddr)];
 };
 
 struct ucma_event {
 	struct ucma_context	*ctx;
+	struct ucma_multicast	*mc;
 	struct list_head	list;
 	struct rdma_cm_id	*cm_id;
 	struct rdma_ucm_event_resp resp;
@@ -81,6 +95,7 @@
 
 static DEFINE_MUTEX(mut);
 static DEFINE_IDR(ctx_idr);
+static DEFINE_IDR(multicast_idr);
 
 static inline struct ucma_context *_ucma_find_context(int id,
 						      struct ucma_file *file)
@@ -124,6 +139,7 @@
 
 	atomic_set(&ctx->ref, 1);
 	init_completion(&ctx->comp);
+	INIT_LIST_HEAD(&ctx->mc_list);
 	ctx->file = file;
 
 	do {
@@ -147,6 +163,37 @@
 	return NULL;
 }
 
+static struct ucma_multicast* ucma_alloc_multicast(struct ucma_context *ctx)
+{
+	struct ucma_multicast *mc;
+	int ret;
+
+	mc = kzalloc(sizeof(*mc), GFP_KERNEL);
+	if (!mc)
+		return NULL;
+
+	do {
+		ret = idr_pre_get(&multicast_idr, GFP_KERNEL);
+		if (!ret)
+			goto error;
+
+		mutex_lock(&mut);
+		ret = idr_get_new(&multicast_idr, mc, &mc->id);
+		mutex_unlock(&mut);
+	} while (ret == -EAGAIN);
+
+	if (ret)
+		goto error;
+
+	mc->ctx = ctx;
+	list_add_tail(&mc->list, &ctx->mc_list);
+	return mc;
+
+error:
+	kfree(mc);
+	return NULL;
+}
+
 static void ucma_copy_conn_event(struct rdma_ucm_conn_param *dst,
 				 struct rdma_conn_param *src)
 {
@@ -180,8 +227,19 @@
 				   struct ucma_event *uevent)
 {
 	uevent->ctx = ctx;
-	uevent->resp.uid = ctx->uid;
-	uevent->resp.id = ctx->id;
+	switch (event->event) {
+	case RDMA_CM_EVENT_MULTICAST_JOIN:
+	case RDMA_CM_EVENT_MULTICAST_ERROR:
+		uevent->mc = (struct ucma_multicast *)
+			     event->param.ud.private_data;
+		uevent->resp.uid = uevent->mc->uid;
+		uevent->resp.id = uevent->mc->id;
+		break;
+	default:
+		uevent->resp.uid = ctx->uid;
+		uevent->resp.id = ctx->id;
+		break;
+	}
 }
 
 static int ucma_event_handler(struct rdma_cm_id *cm_id,
@@ -199,7 +257,7 @@
 	ucma_set_event_context(ctx, event, uevent);
 	uevent->resp.event = event->event;
 	uevent->resp.status = event->status;
-	if (cm_id->ps == RDMA_PS_UDP)
+	if (cm_id->ps == RDMA_PS_UDP || cm_id->ps == RDMA_PS_IPOIB)
 		ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
 	else
 		ucma_copy_conn_event(&uevent->resp.param.conn,
@@ -290,6 +348,8 @@
 
 	list_del(&uevent->list);
 	uevent->ctx->events_reported++;
+	if (uevent->mc)
+		uevent->mc->events_reported++;
 	kfree(uevent);
 done:
 	mutex_unlock(&file->mut);
@@ -342,6 +402,19 @@
 	return ret;
 }
 
+static void ucma_cleanup_multicast(struct ucma_context *ctx)
+{
+	struct ucma_multicast *mc, *tmp;
+
+	mutex_lock(&mut);
+	list_for_each_entry_safe(mc, tmp, &ctx->mc_list, list) {
+		list_del(&mc->list);
+		idr_remove(&multicast_idr, mc->id);
+		kfree(mc);
+	}
+	mutex_unlock(&mut);
+}
+
 static void ucma_cleanup_events(struct ucma_context *ctx)
 {
 	struct ucma_event *uevent, *tmp;
@@ -360,6 +433,19 @@
 	}
 }
 
+static void ucma_cleanup_mc_events(struct ucma_multicast *mc)
+{
+	struct ucma_event *uevent, *tmp;
+
+	list_for_each_entry_safe(uevent, tmp, &mc->ctx->file->event_list, list) {
+		if (uevent->mc != mc)
+			continue;
+
+		list_del(&uevent->list);
+		kfree(uevent);
+	}
+}
+
 static int ucma_free_ctx(struct ucma_context *ctx)
 {
 	int events_reported;
@@ -367,6 +453,8 @@
 	/* No new events will be generated after destroying the id. */
 	rdma_destroy_id(ctx->cm_id);
 
+	ucma_cleanup_multicast(ctx);
+
 	/* Cleanup events not yet reported to the user. */
 	mutex_lock(&ctx->file->mut);
 	ucma_cleanup_events(ctx);
@@ -731,6 +819,114 @@
 	return ret;
 }
 
+static ssize_t ucma_join_multicast(struct ucma_file *file,
+				   const char __user *inbuf,
+				   int in_len, int out_len)
+{
+	struct rdma_ucm_join_mcast cmd;
+	struct rdma_ucm_create_id_resp resp;
+	struct ucma_context *ctx;
+	struct ucma_multicast *mc;
+	int ret;
+
+	if (out_len < sizeof(resp))
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+		return -EFAULT;
+
+	ctx = ucma_get_ctx(file, cmd.id);
+	if (IS_ERR(ctx))
+		return PTR_ERR(ctx);
+
+	mutex_lock(&file->mut);
+	mc = ucma_alloc_multicast(ctx);
+	if (IS_ERR(mc)) {
+		ret = PTR_ERR(mc);
+		goto err1;
+	}
+
+	mc->uid = cmd.uid;
+	memcpy(&mc->addr, &cmd.addr, sizeof cmd.addr);
+	ret = rdma_join_multicast(ctx->cm_id, &mc->addr, mc);
+	if (ret)
+		goto err2;
+
+	resp.id = mc->id;
+	if (copy_to_user((void __user *)(unsigned long)cmd.response,
+			 &resp, sizeof(resp))) {
+		ret = -EFAULT;
+		goto err3;
+	}
+
+	mutex_unlock(&file->mut);
+	ucma_put_ctx(ctx);
+	return 0;
+
+err3:
+	rdma_leave_multicast(ctx->cm_id, &mc->addr);
+	ucma_cleanup_mc_events(mc);
+err2:
+	mutex_lock(&mut);
+	idr_remove(&multicast_idr, mc->id);
+	mutex_unlock(&mut);
+	list_del(&mc->list);
+	kfree(mc);
+err1:
+	mutex_unlock(&file->mut);
+	ucma_put_ctx(ctx);
+	return ret;
+}
+
+static ssize_t ucma_leave_multicast(struct ucma_file *file,
+				    const char __user *inbuf,
+				    int in_len, int out_len)
+{
+	struct rdma_ucm_destroy_id cmd;
+	struct rdma_ucm_destroy_id_resp resp;
+	struct ucma_multicast *mc;
+	int ret = 0;
+
+	if (out_len < sizeof(resp))
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+		return -EFAULT;
+
+	mutex_lock(&mut);
+	mc = idr_find(&multicast_idr, cmd.id);
+	if (!mc)
+		mc = ERR_PTR(-ENOENT);
+	else if (mc->ctx->file != file)
+		mc = ERR_PTR(-EINVAL);
+	else {
+		idr_remove(&multicast_idr, mc->id);
+		atomic_inc(&mc->ctx->ref);
+	}
+	mutex_unlock(&mut);
+
+	if (IS_ERR(mc)) {
+		ret = PTR_ERR(mc);
+		goto out;
+	}
+
+	rdma_leave_multicast(mc->ctx->cm_id, &mc->addr);
+	mutex_lock(&mc->ctx->file->mut);
+	ucma_cleanup_mc_events(mc);
+	list_del(&mc->list);
+	mutex_unlock(&mc->ctx->file->mut);
+
+	ucma_put_ctx(mc->ctx);
+	resp.events_reported = mc->events_reported;
+	kfree(mc);
+
+	if (copy_to_user((void __user *)(unsigned long)cmd.response,
+			 &resp, sizeof(resp)))
+		ret = -EFAULT;
+out:
+	return ret;
+}
+
 static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
 				   const char __user *inbuf,
 				   int in_len, int out_len) = {
@@ -750,6 +946,8 @@
 	[RDMA_USER_CM_CMD_GET_OPTION]	= NULL,
 	[RDMA_USER_CM_CMD_SET_OPTION]	= NULL,
 	[RDMA_USER_CM_CMD_NOTIFY]	= ucma_notify,
+	[RDMA_USER_CM_CMD_JOIN_MCAST]	= ucma_join_multicast,
+	[RDMA_USER_CM_CMD_LEAVE_MCAST]	= ucma_leave_multicast,
 };
 
 static ssize_t ucma_write(struct file *filp, const char __user *buf,
@@ -833,7 +1031,7 @@
 	return 0;
 }
 
-static struct file_operations ucma_fops = {
+static const struct file_operations ucma_fops = {
 	.owner 	 = THIS_MODULE,
 	.open 	 = ucma_open,
 	.release = ucma_close,
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 807fbd6..c069ebeb 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -771,7 +771,7 @@
 	return 0;
 }
 
-static struct file_operations umad_fops = {
+static const struct file_operations umad_fops = {
 	.owner 	 	= THIS_MODULE,
 	.read 	 	= ib_umad_read,
 	.write 	 	= ib_umad_write,
@@ -846,7 +846,7 @@
 	return ret;
 }
 
-static struct file_operations umad_sm_fops = {
+static const struct file_operations umad_sm_fops = {
 	.owner 	 = THIS_MODULE,
 	.open 	 = ib_umad_sm_open,
 	.release = ib_umad_sm_close
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index a617ca7..f8bc822 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -375,7 +375,7 @@
 	return 0;
 }
 
-static struct file_operations uverbs_event_fops = {
+static const struct file_operations uverbs_event_fops = {
 	.owner	 = THIS_MODULE,
 	.read 	 = ib_uverbs_event_read,
 	.poll    = ib_uverbs_event_poll,
@@ -679,14 +679,14 @@
 	return 0;
 }
 
-static struct file_operations uverbs_fops = {
+static const struct file_operations uverbs_fops = {
 	.owner 	 = THIS_MODULE,
 	.write 	 = ib_uverbs_write,
 	.open 	 = ib_uverbs_open,
 	.release = ib_uverbs_close
 };
 
-static struct file_operations uverbs_mmap_fops = {
+static const struct file_operations uverbs_mmap_fops = {
 	.owner 	 = THIS_MODULE,
 	.write 	 = ib_uverbs_write,
 	.mmap    = ib_uverbs_mmap,
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 27fe242..59243d9 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -1073,7 +1073,7 @@
 	     0xffffc000) / sizeof(struct c2_rxp_desc);
 
 	/* Request an interrupt line for the driver */
-	ret = request_irq(pcidev->irq, c2_interrupt, SA_SHIRQ, DRV_NAME, c2dev);
+	ret = request_irq(pcidev->irq, c2_interrupt, IRQF_SHARED, DRV_NAME, c2dev);
 	if (ret) {
 		printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n",
 			pci_name(pcidev), pcidev->irq);
diff --git a/drivers/infiniband/hw/cxgb3/Kconfig b/drivers/infiniband/hw/cxgb3/Kconfig
new file mode 100644
index 0000000..77977f5
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/Kconfig
@@ -0,0 +1,27 @@
+config INFINIBAND_CXGB3
+	tristate "Chelsio RDMA Driver"
+	depends on CHELSIO_T3 && INFINIBAND && INET
+	select GENERIC_ALLOCATOR
+	---help---
+	  This is an iWARP/RDMA driver for the Chelsio T3 1GbE and
+	  10GbE adapters.
+
+	  For general information about Chelsio and our products, visit
+	  our website at <http://www.chelsio.com>.
+
+	  For customer support, please visit our customer support page at
+	  <http://www.chelsio.com/support.htm>.
+
+	  Please send feedback to <linux-bugs@chelsio.com>.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called iw_cxgb3.
+
+config INFINIBAND_CXGB3_DEBUG
+	bool "Verbose debugging output"
+	depends on INFINIBAND_CXGB3
+	default n
+	---help---
+	  This option causes the Chelsio RDMA driver to produce copious
+	  amounts of debug messages.  Select this if you are developing
+	  the driver or trying to diagnose a problem.
diff --git a/drivers/infiniband/hw/cxgb3/Makefile b/drivers/infiniband/hw/cxgb3/Makefile
new file mode 100644
index 0000000..0e110f3
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/Makefile
@@ -0,0 +1,12 @@
+EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3 \
+		-I$(TOPDIR)/drivers/infiniband/hw/cxgb3/core
+
+obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o
+
+iw_cxgb3-y :=  iwch_cm.o iwch_ev.o iwch_cq.o iwch_qp.o iwch_mem.o \
+	       iwch_provider.o iwch.o cxio_hal.o cxio_resource.o
+
+ifdef CONFIG_INFINIBAND_CXGB3_DEBUG
+EXTRA_CFLAGS += -DDEBUG
+iw_cxgb3-y += cxio_dbg.o
+endif
diff --git a/drivers/infiniband/hw/cxgb3/cxio_dbg.c b/drivers/infiniband/hw/cxgb3/cxio_dbg.c
new file mode 100644
index 0000000..75f7b16
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/cxio_dbg.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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.
+ */
+#ifdef DEBUG
+#include <linux/types.h>
+#include "common.h"
+#include "cxgb3_ioctl.h"
+#include "cxio_hal.h"
+#include "cxio_wr.h"
+
+void cxio_dump_tpt(struct cxio_rdev *rdev, u32 stag)
+{
+	struct ch_mem_range *m;
+	u64 *data;
+	int rc;
+	int size = 32;
+
+	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+	if (!m) {
+		PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
+		return;
+	}
+	m->mem_id = MEM_PMRX;
+	m->addr = (stag>>8) * 32 + rdev->rnic_info.tpt_base;
+	m->len = size;
+	PDBG("%s TPT addr 0x%x len %d\n", __FUNCTION__, m->addr, m->len);
+	rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+	if (rc) {
+		PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
+		kfree(m);
+		return;
+	}
+
+	data = (u64 *)m->buf;
+	while (size > 0) {
+		PDBG("TPT %08x: %016llx\n", m->addr, (unsigned long long) *data);
+		size -= 8;
+		data++;
+		m->addr += 8;
+	}
+	kfree(m);
+}
+
+void cxio_dump_pbl(struct cxio_rdev *rdev, u32 pbl_addr, uint len, u8 shift)
+{
+	struct ch_mem_range *m;
+	u64 *data;
+	int rc;
+	int size, npages;
+
+	shift += 12;
+	npages = (len + (1ULL << shift) - 1) >> shift;
+	size = npages * sizeof(u64);
+
+	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+	if (!m) {
+		PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
+		return;
+	}
+	m->mem_id = MEM_PMRX;
+	m->addr = pbl_addr;
+	m->len = size;
+	PDBG("%s PBL addr 0x%x len %d depth %d\n",
+		__FUNCTION__, m->addr, m->len, npages);
+	rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+	if (rc) {
+		PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
+		kfree(m);
+		return;
+	}
+
+	data = (u64 *)m->buf;
+	while (size > 0) {
+		PDBG("PBL %08x: %016llx\n", m->addr, (unsigned long long) *data);
+		size -= 8;
+		data++;
+		m->addr += 8;
+	}
+	kfree(m);
+}
+
+void cxio_dump_wqe(union t3_wr *wqe)
+{
+	__be64 *data = (__be64 *)wqe;
+	uint size = (uint)(be64_to_cpu(*data) & 0xff);
+
+	if (size == 0)
+		size = 8;
+	while (size > 0) {
+		PDBG("WQE %p: %016llx\n", data,
+		     (unsigned long long) be64_to_cpu(*data));
+		size--;
+		data++;
+	}
+}
+
+void cxio_dump_wce(struct t3_cqe *wce)
+{
+	__be64 *data = (__be64 *)wce;
+	int size = sizeof(*wce);
+
+	while (size > 0) {
+		PDBG("WCE %p: %016llx\n", data,
+		     (unsigned long long) be64_to_cpu(*data));
+		size -= 8;
+		data++;
+	}
+}
+
+void cxio_dump_rqt(struct cxio_rdev *rdev, u32 hwtid, int nents)
+{
+	struct ch_mem_range *m;
+	int size = nents * 64;
+	u64 *data;
+	int rc;
+
+	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+	if (!m) {
+		PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
+		return;
+	}
+	m->mem_id = MEM_PMRX;
+	m->addr = ((hwtid)<<10) + rdev->rnic_info.rqt_base;
+	m->len = size;
+	PDBG("%s RQT addr 0x%x len %d\n", __FUNCTION__, m->addr, m->len);
+	rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+	if (rc) {
+		PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
+		kfree(m);
+		return;
+	}
+
+	data = (u64 *)m->buf;
+	while (size > 0) {
+		PDBG("RQT %08x: %016llx\n", m->addr, (unsigned long long) *data);
+		size -= 8;
+		data++;
+		m->addr += 8;
+	}
+	kfree(m);
+}
+
+void cxio_dump_tcb(struct cxio_rdev *rdev, u32 hwtid)
+{
+	struct ch_mem_range *m;
+	int size = TCB_SIZE;
+	u32 *data;
+	int rc;
+
+	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+	if (!m) {
+		PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
+		return;
+	}
+	m->mem_id = MEM_CM;
+	m->addr = hwtid * size;
+	m->len = size;
+	PDBG("%s TCB %d len %d\n", __FUNCTION__, m->addr, m->len);
+	rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+	if (rc) {
+		PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
+		kfree(m);
+		return;
+	}
+
+	data = (u32 *)m->buf;
+	while (size > 0) {
+		printk("%2u: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+			m->addr,
+			*(data+2), *(data+3), *(data),*(data+1),
+			*(data+6), *(data+7), *(data+4), *(data+5));
+		size -= 32;
+		data += 8;
+		m->addr += 32;
+	}
+	kfree(m);
+}
+#endif
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
new file mode 100644
index 0000000..114ac3b
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -0,0 +1,1279 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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/delay.h>
+
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+
+#include "cxio_resource.h"
+#include "cxio_hal.h"
+#include "cxgb3_offload.h"
+#include "sge_defs.h"
+
+static LIST_HEAD(rdev_list);
+static cxio_hal_ev_callback_func_t cxio_ev_cb = NULL;
+
+static inline struct cxio_rdev *cxio_hal_find_rdev_by_name(char *dev_name)
+{
+	struct cxio_rdev *rdev;
+
+	list_for_each_entry(rdev, &rdev_list, entry)
+		if (!strcmp(rdev->dev_name, dev_name))
+			return rdev;
+	return NULL;
+}
+
+static inline struct cxio_rdev *cxio_hal_find_rdev_by_t3cdev(struct t3cdev
+							     *tdev)
+{
+	struct cxio_rdev *rdev;
+
+	list_for_each_entry(rdev, &rdev_list, entry)
+		if (rdev->t3cdev_p == tdev)
+			return rdev;
+	return NULL;
+}
+
+int cxio_hal_cq_op(struct cxio_rdev *rdev_p, struct t3_cq *cq,
+		   enum t3_cq_opcode op, u32 credit)
+{
+	int ret;
+	struct t3_cqe *cqe;
+	u32 rptr;
+
+	struct rdma_cq_op setup;
+	setup.id = cq->cqid;
+	setup.credits = (op == CQ_CREDIT_UPDATE) ? credit : 0;
+	setup.op = op;
+	ret = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_OP, &setup);
+
+	if ((ret < 0) || (op == CQ_CREDIT_UPDATE))
+		return ret;
+
+	/*
+	 * If the rearm returned an index other than our current index,
+	 * then there might be CQE's in flight (being DMA'd).  We must wait
+	 * here for them to complete or the consumer can miss a notification.
+	 */
+	if (Q_PTR2IDX((cq->rptr), cq->size_log2) != ret) {
+		int i=0;
+
+		rptr = cq->rptr;
+
+		/*
+		 * Keep the generation correct by bumping rptr until it
+		 * matches the index returned by the rearm - 1.
+		 */
+		while (Q_PTR2IDX((rptr+1), cq->size_log2) != ret)
+			rptr++;
+
+		/*
+		 * Now rptr is the index for the (last) cqe that was
+		 * in-flight at the time the HW rearmed the CQ.  We
+		 * spin until that CQE is valid.
+		 */
+		cqe = cq->queue + Q_PTR2IDX(rptr, cq->size_log2);
+		while (!CQ_VLD_ENTRY(rptr, cq->size_log2, cqe)) {
+			udelay(1);
+			if (i++ > 1000000) {
+				BUG_ON(1);
+				printk(KERN_ERR "%s: stalled rnic\n",
+				       rdev_p->dev_name);
+				return -EIO;
+			}
+		}
+	}
+	return 0;
+}
+
+static inline int cxio_hal_clear_cq_ctx(struct cxio_rdev *rdev_p, u32 cqid)
+{
+	struct rdma_cq_setup setup;
+	setup.id = cqid;
+	setup.base_addr = 0;	/* NULL address */
+	setup.size = 0;		/* disaable the CQ */
+	setup.credits = 0;
+	setup.credit_thres = 0;
+	setup.ovfl_mode = 0;
+	return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));
+}
+
+int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid)
+{
+	u64 sge_cmd;
+	struct t3_modify_qp_wr *wqe;
+	struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_KERNEL);
+	if (!skb) {
+		PDBG("%s alloc_skb failed\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));
+	memset(wqe, 0, sizeof(*wqe));
+	build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 3, 1, qpid, 7);
+	wqe->flags = cpu_to_be32(MODQP_WRITE_EC);
+	sge_cmd = qpid << 8 | 3;
+	wqe->sge_cmd = cpu_to_be64(sge_cmd);
+	skb->priority = CPL_PRIORITY_CONTROL;
+	return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
+}
+
+int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
+{
+	struct rdma_cq_setup setup;
+	int size = (1UL << (cq->size_log2)) * sizeof(struct t3_cqe);
+
+	cq->cqid = cxio_hal_get_cqid(rdev_p->rscp);
+	if (!cq->cqid)
+		return -ENOMEM;
+	cq->sw_queue = kzalloc(size, GFP_KERNEL);
+	if (!cq->sw_queue)
+		return -ENOMEM;
+	cq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev),
+					     (1UL << (cq->size_log2)) *
+					     sizeof(struct t3_cqe),
+					     &(cq->dma_addr), GFP_KERNEL);
+	if (!cq->queue) {
+		kfree(cq->sw_queue);
+		return -ENOMEM;
+	}
+	pci_unmap_addr_set(cq, mapping, cq->dma_addr);
+	memset(cq->queue, 0, size);
+	setup.id = cq->cqid;
+	setup.base_addr = (u64) (cq->dma_addr);
+	setup.size = 1UL << cq->size_log2;
+	setup.credits = 65535;
+	setup.credit_thres = 1;
+	if (rdev_p->t3cdev_p->type == T3B)
+		setup.ovfl_mode = 0;
+	else
+		setup.ovfl_mode = 1;
+	return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));
+}
+
+int cxio_resize_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
+{
+	struct rdma_cq_setup setup;
+	setup.id = cq->cqid;
+	setup.base_addr = (u64) (cq->dma_addr);
+	setup.size = 1UL << cq->size_log2;
+	setup.credits = setup.size;
+	setup.credit_thres = setup.size;	/* TBD: overflow recovery */
+	setup.ovfl_mode = 1;
+	return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));
+}
+
+static u32 get_qpid(struct cxio_rdev *rdev_p, struct cxio_ucontext *uctx)
+{
+	struct cxio_qpid_list *entry;
+	u32 qpid;
+	int i;
+
+	mutex_lock(&uctx->lock);
+	if (!list_empty(&uctx->qpids)) {
+		entry = list_entry(uctx->qpids.next, struct cxio_qpid_list,
+				   entry);
+		list_del(&entry->entry);
+		qpid = entry->qpid;
+		kfree(entry);
+	} else {
+		qpid = cxio_hal_get_qpid(rdev_p->rscp);
+		if (!qpid)
+			goto out;
+		for (i = qpid+1; i & rdev_p->qpmask; i++) {
+			entry = kmalloc(sizeof *entry, GFP_KERNEL);
+			if (!entry)
+				break;
+			entry->qpid = i;
+			list_add_tail(&entry->entry, &uctx->qpids);
+		}
+	}
+out:
+	mutex_unlock(&uctx->lock);
+	PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
+	return qpid;
+}
+
+static void put_qpid(struct cxio_rdev *rdev_p, u32 qpid,
+		     struct cxio_ucontext *uctx)
+{
+	struct cxio_qpid_list *entry;
+
+	entry = kmalloc(sizeof *entry, GFP_KERNEL);
+	if (!entry)
+		return;
+	PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
+	entry->qpid = qpid;
+	mutex_lock(&uctx->lock);
+	list_add_tail(&entry->entry, &uctx->qpids);
+	mutex_unlock(&uctx->lock);
+}
+
+void cxio_release_ucontext(struct cxio_rdev *rdev_p, struct cxio_ucontext *uctx)
+{
+	struct list_head *pos, *nxt;
+	struct cxio_qpid_list *entry;
+
+	mutex_lock(&uctx->lock);
+	list_for_each_safe(pos, nxt, &uctx->qpids) {
+		entry = list_entry(pos, struct cxio_qpid_list, entry);
+		list_del_init(&entry->entry);
+		if (!(entry->qpid & rdev_p->qpmask))
+			cxio_hal_put_qpid(rdev_p->rscp, entry->qpid);
+		kfree(entry);
+	}
+	mutex_unlock(&uctx->lock);
+}
+
+void cxio_init_ucontext(struct cxio_rdev *rdev_p, struct cxio_ucontext *uctx)
+{
+	INIT_LIST_HEAD(&uctx->qpids);
+	mutex_init(&uctx->lock);
+}
+
+int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain,
+		   struct t3_wq *wq, struct cxio_ucontext *uctx)
+{
+	int depth = 1UL << wq->size_log2;
+	int rqsize = 1UL << wq->rq_size_log2;
+
+	wq->qpid = get_qpid(rdev_p, uctx);
+	if (!wq->qpid)
+		return -ENOMEM;
+
+	wq->rq = kzalloc(depth * sizeof(u64), GFP_KERNEL);
+	if (!wq->rq)
+		goto err1;
+
+	wq->rq_addr = cxio_hal_rqtpool_alloc(rdev_p, rqsize);
+	if (!wq->rq_addr)
+		goto err2;
+
+	wq->sq = kzalloc(depth * sizeof(struct t3_swsq), GFP_KERNEL);
+	if (!wq->sq)
+		goto err3;
+
+	wq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev),
+					     depth * sizeof(union t3_wr),
+					     &(wq->dma_addr), GFP_KERNEL);
+	if (!wq->queue)
+		goto err4;
+
+	memset(wq->queue, 0, depth * sizeof(union t3_wr));
+	pci_unmap_addr_set(wq, mapping, wq->dma_addr);
+	wq->doorbell = (void __iomem *)rdev_p->rnic_info.kdb_addr;
+	if (!kernel_domain)
+		wq->udb = (u64)rdev_p->rnic_info.udbell_physbase +
+					(wq->qpid << rdev_p->qpshift);
+	PDBG("%s qpid 0x%x doorbell 0x%p udb 0x%llx\n", __FUNCTION__,
+	     wq->qpid, wq->doorbell, (unsigned long long) wq->udb);
+	return 0;
+err4:
+	kfree(wq->sq);
+err3:
+	cxio_hal_rqtpool_free(rdev_p, wq->rq_addr, rqsize);
+err2:
+	kfree(wq->rq);
+err1:
+	put_qpid(rdev_p, wq->qpid, uctx);
+	return -ENOMEM;
+}
+
+int cxio_destroy_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
+{
+	int err;
+	err = cxio_hal_clear_cq_ctx(rdev_p, cq->cqid);
+	kfree(cq->sw_queue);
+	dma_free_coherent(&(rdev_p->rnic_info.pdev->dev),
+			  (1UL << (cq->size_log2))
+			  * sizeof(struct t3_cqe), cq->queue,
+			  pci_unmap_addr(cq, mapping));
+	cxio_hal_put_cqid(rdev_p->rscp, cq->cqid);
+	return err;
+}
+
+int cxio_destroy_qp(struct cxio_rdev *rdev_p, struct t3_wq *wq,
+		    struct cxio_ucontext *uctx)
+{
+	dma_free_coherent(&(rdev_p->rnic_info.pdev->dev),
+			  (1UL << (wq->size_log2))
+			  * sizeof(union t3_wr), wq->queue,
+			  pci_unmap_addr(wq, mapping));
+	kfree(wq->sq);
+	cxio_hal_rqtpool_free(rdev_p, wq->rq_addr, (1UL << wq->rq_size_log2));
+	kfree(wq->rq);
+	put_qpid(rdev_p, wq->qpid, uctx);
+	return 0;
+}
+
+static void insert_recv_cqe(struct t3_wq *wq, struct t3_cq *cq)
+{
+	struct t3_cqe cqe;
+
+	PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __FUNCTION__,
+	     wq, cq, cq->sw_rptr, cq->sw_wptr);
+	memset(&cqe, 0, sizeof(cqe));
+	cqe.header = cpu_to_be32(V_CQE_STATUS(TPT_ERR_SWFLUSH) |
+			         V_CQE_OPCODE(T3_SEND) |
+				 V_CQE_TYPE(0) |
+				 V_CQE_SWCQE(1) |
+				 V_CQE_QPID(wq->qpid) |
+				 V_CQE_GENBIT(Q_GENBIT(cq->sw_wptr,
+						       cq->size_log2)));
+	*(cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2)) = cqe;
+	cq->sw_wptr++;
+}
+
+void cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count)
+{
+	u32 ptr;
+
+	PDBG("%s wq %p cq %p\n", __FUNCTION__, wq, cq);
+
+	/* flush RQ */
+	PDBG("%s rq_rptr %u rq_wptr %u skip count %u\n", __FUNCTION__,
+	    wq->rq_rptr, wq->rq_wptr, count);
+	ptr = wq->rq_rptr + count;
+	while (ptr++ != wq->rq_wptr)
+		insert_recv_cqe(wq, cq);
+}
+
+static void insert_sq_cqe(struct t3_wq *wq, struct t3_cq *cq,
+		          struct t3_swsq *sqp)
+{
+	struct t3_cqe cqe;
+
+	PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __FUNCTION__,
+	     wq, cq, cq->sw_rptr, cq->sw_wptr);
+	memset(&cqe, 0, sizeof(cqe));
+	cqe.header = cpu_to_be32(V_CQE_STATUS(TPT_ERR_SWFLUSH) |
+			         V_CQE_OPCODE(sqp->opcode) |
+			         V_CQE_TYPE(1) |
+			         V_CQE_SWCQE(1) |
+			         V_CQE_QPID(wq->qpid) |
+			         V_CQE_GENBIT(Q_GENBIT(cq->sw_wptr,
+						       cq->size_log2)));
+	cqe.u.scqe.wrid_hi = sqp->sq_wptr;
+
+	*(cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2)) = cqe;
+	cq->sw_wptr++;
+}
+
+void cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count)
+{
+	__u32 ptr;
+	struct t3_swsq *sqp = wq->sq + Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2);
+
+	ptr = wq->sq_rptr + count;
+	sqp += count;
+	while (ptr != wq->sq_wptr) {
+		insert_sq_cqe(wq, cq, sqp);
+		sqp++;
+		ptr++;
+	}
+}
+
+/*
+ * Move all CQEs from the HWCQ into the SWCQ.
+ */
+void cxio_flush_hw_cq(struct t3_cq *cq)
+{
+	struct t3_cqe *cqe, *swcqe;
+
+	PDBG("%s cq %p cqid 0x%x\n", __FUNCTION__, cq, cq->cqid);
+	cqe = cxio_next_hw_cqe(cq);
+	while (cqe) {
+		PDBG("%s flushing hwcq rptr 0x%x to swcq wptr 0x%x\n",
+		     __FUNCTION__, cq->rptr, cq->sw_wptr);
+		swcqe = cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2);
+		*swcqe = *cqe;
+		swcqe->header |= cpu_to_be32(V_CQE_SWCQE(1));
+		cq->sw_wptr++;
+		cq->rptr++;
+		cqe = cxio_next_hw_cqe(cq);
+	}
+}
+
+static inline int cqe_completes_wr(struct t3_cqe *cqe, struct t3_wq *wq)
+{
+	if (CQE_OPCODE(*cqe) == T3_TERMINATE)
+		return 0;
+
+	if ((CQE_OPCODE(*cqe) == T3_RDMA_WRITE) && RQ_TYPE(*cqe))
+		return 0;
+
+	if ((CQE_OPCODE(*cqe) == T3_READ_RESP) && SQ_TYPE(*cqe))
+		return 0;
+
+	if ((CQE_OPCODE(*cqe) == T3_SEND) && RQ_TYPE(*cqe) &&
+	    Q_EMPTY(wq->rq_rptr, wq->rq_wptr))
+		return 0;
+
+	return 1;
+}
+
+void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+{
+	struct t3_cqe *cqe;
+	u32 ptr;
+
+	*count = 0;
+	ptr = cq->sw_rptr;
+	while (!Q_EMPTY(ptr, cq->sw_wptr)) {
+		cqe = cq->sw_queue + (Q_PTR2IDX(ptr, cq->size_log2));
+		if ((SQ_TYPE(*cqe) || (CQE_OPCODE(*cqe) == T3_READ_RESP)) &&
+		    (CQE_QPID(*cqe) == wq->qpid))
+			(*count)++;
+		ptr++;
+	}
+	PDBG("%s cq %p count %d\n", __FUNCTION__, cq, *count);
+}
+
+void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+{
+	struct t3_cqe *cqe;
+	u32 ptr;
+
+	*count = 0;
+	PDBG("%s count zero %d\n", __FUNCTION__, *count);
+	ptr = cq->sw_rptr;
+	while (!Q_EMPTY(ptr, cq->sw_wptr)) {
+		cqe = cq->sw_queue + (Q_PTR2IDX(ptr, cq->size_log2));
+		if (RQ_TYPE(*cqe) && (CQE_OPCODE(*cqe) != T3_READ_RESP) &&
+		    (CQE_QPID(*cqe) == wq->qpid) && cqe_completes_wr(cqe, wq))
+			(*count)++;
+		ptr++;
+	}
+	PDBG("%s cq %p count %d\n", __FUNCTION__, cq, *count);
+}
+
+static int cxio_hal_init_ctrl_cq(struct cxio_rdev *rdev_p)
+{
+	struct rdma_cq_setup setup;
+	setup.id = 0;
+	setup.base_addr = 0;	/* NULL address */
+	setup.size = 1;		/* enable the CQ */
+	setup.credits = 0;
+
+	/* force SGE to redirect to RspQ and interrupt */
+	setup.credit_thres = 0;
+	setup.ovfl_mode = 1;
+	return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));
+}
+
+static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
+{
+	int err;
+	u64 sge_cmd, ctx0, ctx1;
+	u64 base_addr;
+	struct t3_modify_qp_wr *wqe;
+	struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_KERNEL);
+
+
+	if (!skb) {
+		PDBG("%s alloc_skb failed\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	err = cxio_hal_init_ctrl_cq(rdev_p);
+	if (err) {
+		PDBG("%s err %d initializing ctrl_cq\n", __FUNCTION__, err);
+		return err;
+	}
+	rdev_p->ctrl_qp.workq = dma_alloc_coherent(
+					&(rdev_p->rnic_info.pdev->dev),
+					(1 << T3_CTRL_QP_SIZE_LOG2) *
+					sizeof(union t3_wr),
+					&(rdev_p->ctrl_qp.dma_addr),
+					GFP_KERNEL);
+	if (!rdev_p->ctrl_qp.workq) {
+		PDBG("%s dma_alloc_coherent failed\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	pci_unmap_addr_set(&rdev_p->ctrl_qp, mapping,
+			   rdev_p->ctrl_qp.dma_addr);
+	rdev_p->ctrl_qp.doorbell = (void __iomem *)rdev_p->rnic_info.kdb_addr;
+	memset(rdev_p->ctrl_qp.workq, 0,
+	       (1 << T3_CTRL_QP_SIZE_LOG2) * sizeof(union t3_wr));
+
+	mutex_init(&rdev_p->ctrl_qp.lock);
+	init_waitqueue_head(&rdev_p->ctrl_qp.waitq);
+
+	/* update HW Ctrl QP context */
+	base_addr = rdev_p->ctrl_qp.dma_addr;
+	base_addr >>= 12;
+	ctx0 = (V_EC_SIZE((1 << T3_CTRL_QP_SIZE_LOG2)) |
+		V_EC_BASE_LO((u32) base_addr & 0xffff));
+	ctx0 <<= 32;
+	ctx0 |= V_EC_CREDITS(FW_WR_NUM);
+	base_addr >>= 16;
+	ctx1 = (u32) base_addr;
+	base_addr >>= 32;
+	ctx1 |= ((u64) (V_EC_BASE_HI((u32) base_addr & 0xf) | V_EC_RESPQ(0) |
+			V_EC_TYPE(0) | V_EC_GEN(1) |
+			V_EC_UP_TOKEN(T3_CTL_QP_TID) | F_EC_VALID)) << 32;
+	wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));
+	memset(wqe, 0, sizeof(*wqe));
+	build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 0, 1,
+		       T3_CTL_QP_TID, 7);
+	wqe->flags = cpu_to_be32(MODQP_WRITE_EC);
+	sge_cmd = (3ULL << 56) | FW_RI_SGEEC_START << 8 | 3;
+	wqe->sge_cmd = cpu_to_be64(sge_cmd);
+	wqe->ctx1 = cpu_to_be64(ctx1);
+	wqe->ctx0 = cpu_to_be64(ctx0);
+	PDBG("CtrlQP dma_addr 0x%llx workq %p size %d\n",
+	     (unsigned long long) rdev_p->ctrl_qp.dma_addr,
+	     rdev_p->ctrl_qp.workq, 1 << T3_CTRL_QP_SIZE_LOG2);
+	skb->priority = CPL_PRIORITY_CONTROL;
+	return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
+}
+
+static int cxio_hal_destroy_ctrl_qp(struct cxio_rdev *rdev_p)
+{
+	dma_free_coherent(&(rdev_p->rnic_info.pdev->dev),
+			  (1UL << T3_CTRL_QP_SIZE_LOG2)
+			  * sizeof(union t3_wr), rdev_p->ctrl_qp.workq,
+			  pci_unmap_addr(&rdev_p->ctrl_qp, mapping));
+	return cxio_hal_clear_qp_ctx(rdev_p, T3_CTRL_QP_ID);
+}
+
+/* write len bytes of data into addr (32B aligned address)
+ * If data is NULL, clear len byte of memory to zero.
+ * caller aquires the ctrl_qp lock before the call
+ */
+static int cxio_hal_ctrl_qp_write_mem(struct cxio_rdev *rdev_p, u32 addr,
+				      u32 len, void *data, int completion)
+{
+	u32 i, nr_wqe, copy_len;
+	u8 *copy_data;
+	u8 wr_len, utx_len;	/* lenght in 8 byte flit */
+	enum t3_wr_flags flag;
+	__be64 *wqe;
+	u64 utx_cmd;
+	addr &= 0x7FFFFFF;
+	nr_wqe = len % 96 ? len / 96 + 1 : len / 96;	/* 96B max per WQE */
+	PDBG("%s wptr 0x%x rptr 0x%x len %d, nr_wqe %d data %p addr 0x%0x\n",
+	     __FUNCTION__, rdev_p->ctrl_qp.wptr, rdev_p->ctrl_qp.rptr, len,
+	     nr_wqe, data, addr);
+	utx_len = 3;		/* in 32B unit */
+	for (i = 0; i < nr_wqe; i++) {
+		if (Q_FULL(rdev_p->ctrl_qp.rptr, rdev_p->ctrl_qp.wptr,
+		           T3_CTRL_QP_SIZE_LOG2)) {
+			PDBG("%s ctrl_qp full wtpr 0x%0x rptr 0x%0x, "
+			     "wait for more space i %d\n", __FUNCTION__,
+			     rdev_p->ctrl_qp.wptr, rdev_p->ctrl_qp.rptr, i);
+			if (wait_event_interruptible(rdev_p->ctrl_qp.waitq,
+					     !Q_FULL(rdev_p->ctrl_qp.rptr,
+						     rdev_p->ctrl_qp.wptr,
+						     T3_CTRL_QP_SIZE_LOG2))) {
+				PDBG("%s ctrl_qp workq interrupted\n",
+				     __FUNCTION__);
+				return -ERESTARTSYS;
+			}
+			PDBG("%s ctrl_qp wakeup, continue posting work request "
+			     "i %d\n", __FUNCTION__, i);
+		}
+		wqe = (__be64 *)(rdev_p->ctrl_qp.workq + (rdev_p->ctrl_qp.wptr %
+						(1 << T3_CTRL_QP_SIZE_LOG2)));
+		flag = 0;
+		if (i == (nr_wqe - 1)) {
+			/* last WQE */
+			flag = completion ? T3_COMPLETION_FLAG : 0;
+			if (len % 32)
+				utx_len = len / 32 + 1;
+			else
+				utx_len = len / 32;
+		}
+
+		/*
+		 * Force a CQE to return the credit to the workq in case
+		 * we posted more than half the max QP size of WRs
+		 */
+		if ((i != 0) &&
+		    (i % (((1 << T3_CTRL_QP_SIZE_LOG2)) >> 1) == 0)) {
+			flag = T3_COMPLETION_FLAG;
+			PDBG("%s force completion at i %d\n", __FUNCTION__, i);
+		}
+
+		/* build the utx mem command */
+		wqe += (sizeof(struct t3_bypass_wr) >> 3);
+		utx_cmd = (T3_UTX_MEM_WRITE << 28) | (addr + i * 3);
+		utx_cmd <<= 32;
+		utx_cmd |= (utx_len << 28) | ((utx_len << 2) + 1);
+		*wqe = cpu_to_be64(utx_cmd);
+		wqe++;
+		copy_data = (u8 *) data + i * 96;
+		copy_len = len > 96 ? 96 : len;
+
+		/* clear memory content if data is NULL */
+		if (data)
+			memcpy(wqe, copy_data, copy_len);
+		else
+			memset(wqe, 0, copy_len);
+		if (copy_len % 32)
+			memset(((u8 *) wqe) + copy_len, 0,
+			       32 - (copy_len % 32));
+		wr_len = ((sizeof(struct t3_bypass_wr)) >> 3) + 1 +
+			 (utx_len << 2);
+		wqe = (__be64 *)(rdev_p->ctrl_qp.workq + (rdev_p->ctrl_qp.wptr %
+			      (1 << T3_CTRL_QP_SIZE_LOG2)));
+
+		/* wptr in the WRID[31:0] */
+		((union t3_wrid *)(wqe+1))->id0.low = rdev_p->ctrl_qp.wptr;
+
+		/*
+		 * This must be the last write with a memory barrier
+		 * for the genbit
+		 */
+		build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_BP, flag,
+			       Q_GENBIT(rdev_p->ctrl_qp.wptr,
+					T3_CTRL_QP_SIZE_LOG2), T3_CTRL_QP_ID,
+			       wr_len);
+		if (flag == T3_COMPLETION_FLAG)
+			ring_doorbell(rdev_p->ctrl_qp.doorbell, T3_CTRL_QP_ID);
+		len -= 96;
+		rdev_p->ctrl_qp.wptr++;
+	}
+	return 0;
+}
+
+/* IN: stag key, pdid, perm, zbva, to, len, page_size, pbl, and pbl_size
+ * OUT: stag index, actual pbl_size, pbl_addr allocated.
+ * TBD: shared memory region support
+ */
+static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry,
+			 u32 *stag, u8 stag_state, u32 pdid,
+			 enum tpt_mem_type type, enum tpt_mem_perm perm,
+			 u32 zbva, u64 to, u32 len, u8 page_size, __be64 *pbl,
+			 u32 *pbl_size, u32 *pbl_addr)
+{
+	int err;
+	struct tpt_entry tpt;
+	u32 stag_idx;
+	u32 wptr;
+	int rereg = (*stag != T3_STAG_UNSET);
+
+	stag_state = stag_state > 0;
+	stag_idx = (*stag) >> 8;
+
+	if ((!reset_tpt_entry) && !(*stag != T3_STAG_UNSET)) {
+		stag_idx = cxio_hal_get_stag(rdev_p->rscp);
+		if (!stag_idx)
+			return -ENOMEM;
+		*stag = (stag_idx << 8) | ((*stag) & 0xFF);
+	}
+	PDBG("%s stag_state 0x%0x type 0x%0x pdid 0x%0x, stag_idx 0x%x\n",
+	     __FUNCTION__, stag_state, type, pdid, stag_idx);
+
+	if (reset_tpt_entry)
+		cxio_hal_pblpool_free(rdev_p, *pbl_addr, *pbl_size << 3);
+	else if (!rereg) {
+		*pbl_addr = cxio_hal_pblpool_alloc(rdev_p, *pbl_size << 3);
+		if (!*pbl_addr) {
+			return -ENOMEM;
+		}
+	}
+
+	mutex_lock(&rdev_p->ctrl_qp.lock);
+
+	/* write PBL first if any - update pbl only if pbl list exist */
+	if (pbl) {
+
+		PDBG("%s *pdb_addr 0x%x, pbl_base 0x%x, pbl_size %d\n",
+		     __FUNCTION__, *pbl_addr, rdev_p->rnic_info.pbl_base,
+		     *pbl_size);
+		err = cxio_hal_ctrl_qp_write_mem(rdev_p,
+				(*pbl_addr >> 5),
+				(*pbl_size << 3), pbl, 0);
+		if (err)
+			goto ret;
+	}
+
+	/* write TPT entry */
+	if (reset_tpt_entry)
+		memset(&tpt, 0, sizeof(tpt));
+	else {
+		tpt.valid_stag_pdid = cpu_to_be32(F_TPT_VALID |
+				V_TPT_STAG_KEY((*stag) & M_TPT_STAG_KEY) |
+				V_TPT_STAG_STATE(stag_state) |
+				V_TPT_STAG_TYPE(type) | V_TPT_PDID(pdid));
+		BUG_ON(page_size >= 28);
+		tpt.flags_pagesize_qpid = cpu_to_be32(V_TPT_PERM(perm) |
+				F_TPT_MW_BIND_ENABLE |
+				V_TPT_ADDR_TYPE((zbva ? TPT_ZBTO : TPT_VATO)) |
+				V_TPT_PAGE_SIZE(page_size));
+		tpt.rsvd_pbl_addr = reset_tpt_entry ? 0 :
+				    cpu_to_be32(V_TPT_PBL_ADDR(PBL_OFF(rdev_p, *pbl_addr)>>3));
+		tpt.len = cpu_to_be32(len);
+		tpt.va_hi = cpu_to_be32((u32) (to >> 32));
+		tpt.va_low_or_fbo = cpu_to_be32((u32) (to & 0xFFFFFFFFULL));
+		tpt.rsvd_bind_cnt_or_pstag = 0;
+		tpt.rsvd_pbl_size = reset_tpt_entry ? 0 :
+				  cpu_to_be32(V_TPT_PBL_SIZE((*pbl_size) >> 2));
+	}
+	err = cxio_hal_ctrl_qp_write_mem(rdev_p,
+				       stag_idx +
+				       (rdev_p->rnic_info.tpt_base >> 5),
+				       sizeof(tpt), &tpt, 1);
+
+	/* release the stag index to free pool */
+	if (reset_tpt_entry)
+		cxio_hal_put_stag(rdev_p->rscp, stag_idx);
+ret:
+	wptr = rdev_p->ctrl_qp.wptr;
+	mutex_unlock(&rdev_p->ctrl_qp.lock);
+	if (!err)
+		if (wait_event_interruptible(rdev_p->ctrl_qp.waitq,
+					     SEQ32_GE(rdev_p->ctrl_qp.rptr,
+						      wptr)))
+			return -ERESTARTSYS;
+	return err;
+}
+
+/* IN : stag key, pdid, pbl_size
+ * Out: stag index, actaul pbl_size, and pbl_addr allocated.
+ */
+int cxio_allocate_stag(struct cxio_rdev *rdev_p, u32 * stag, u32 pdid,
+		       enum tpt_mem_perm perm, u32 * pbl_size, u32 * pbl_addr)
+{
+	*stag = T3_STAG_UNSET;
+	return (__cxio_tpt_op(rdev_p, 0, stag, 0, pdid, TPT_NON_SHARED_MR,
+			      perm, 0, 0ULL, 0, 0, NULL, pbl_size, pbl_addr));
+}
+
+int cxio_register_phys_mem(struct cxio_rdev *rdev_p, u32 *stag, u32 pdid,
+			   enum tpt_mem_perm perm, u32 zbva, u64 to, u32 len,
+			   u8 page_size, __be64 *pbl, u32 *pbl_size,
+			   u32 *pbl_addr)
+{
+	*stag = T3_STAG_UNSET;
+	return __cxio_tpt_op(rdev_p, 0, stag, 1, pdid, TPT_NON_SHARED_MR, perm,
+			     zbva, to, len, page_size, pbl, pbl_size, pbl_addr);
+}
+
+int cxio_reregister_phys_mem(struct cxio_rdev *rdev_p, u32 *stag, u32 pdid,
+			   enum tpt_mem_perm perm, u32 zbva, u64 to, u32 len,
+			   u8 page_size, __be64 *pbl, u32 *pbl_size,
+			   u32 *pbl_addr)
+{
+	return __cxio_tpt_op(rdev_p, 0, stag, 1, pdid, TPT_NON_SHARED_MR, perm,
+			     zbva, to, len, page_size, pbl, pbl_size, pbl_addr);
+}
+
+int cxio_dereg_mem(struct cxio_rdev *rdev_p, u32 stag, u32 pbl_size,
+		   u32 pbl_addr)
+{
+	return __cxio_tpt_op(rdev_p, 1, &stag, 0, 0, 0, 0, 0, 0ULL, 0, 0, NULL,
+			     &pbl_size, &pbl_addr);
+}
+
+int cxio_allocate_window(struct cxio_rdev *rdev_p, u32 * stag, u32 pdid)
+{
+	u32 pbl_size = 0;
+	*stag = T3_STAG_UNSET;
+	return __cxio_tpt_op(rdev_p, 0, stag, 0, pdid, TPT_MW, 0, 0, 0ULL, 0, 0,
+			     NULL, &pbl_size, NULL);
+}
+
+int cxio_deallocate_window(struct cxio_rdev *rdev_p, u32 stag)
+{
+	return __cxio_tpt_op(rdev_p, 1, &stag, 0, 0, 0, 0, 0, 0ULL, 0, 0, NULL,
+			     NULL, NULL);
+}
+
+int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)
+{
+	struct t3_rdma_init_wr *wqe;
+	struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+	PDBG("%s rdev_p %p\n", __FUNCTION__, rdev_p);
+	wqe = (struct t3_rdma_init_wr *) __skb_put(skb, sizeof(*wqe));
+	wqe->wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_INIT));
+	wqe->wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(attr->tid) |
+					   V_FW_RIWR_LEN(sizeof(*wqe) >> 3));
+	wqe->wrid.id1 = 0;
+	wqe->qpid = cpu_to_be32(attr->qpid);
+	wqe->pdid = cpu_to_be32(attr->pdid);
+	wqe->scqid = cpu_to_be32(attr->scqid);
+	wqe->rcqid = cpu_to_be32(attr->rcqid);
+	wqe->rq_addr = cpu_to_be32(attr->rq_addr - rdev_p->rnic_info.rqt_base);
+	wqe->rq_size = cpu_to_be32(attr->rq_size);
+	wqe->mpaattrs = attr->mpaattrs;
+	wqe->qpcaps = attr->qpcaps;
+	wqe->ulpdu_size = cpu_to_be16(attr->tcp_emss);
+	wqe->flags = cpu_to_be32(attr->flags);
+	wqe->ord = cpu_to_be32(attr->ord);
+	wqe->ird = cpu_to_be32(attr->ird);
+	wqe->qp_dma_addr = cpu_to_be64(attr->qp_dma_addr);
+	wqe->qp_dma_size = cpu_to_be32(attr->qp_dma_size);
+	wqe->rsvd = 0;
+	skb->priority = 0;	/* 0=>ToeQ; 1=>CtrlQ */
+	return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
+}
+
+void cxio_register_ev_cb(cxio_hal_ev_callback_func_t ev_cb)
+{
+	cxio_ev_cb = ev_cb;
+}
+
+void cxio_unregister_ev_cb(cxio_hal_ev_callback_func_t ev_cb)
+{
+	cxio_ev_cb = NULL;
+}
+
+static int cxio_hal_ev_handler(struct t3cdev *t3cdev_p, struct sk_buff *skb)
+{
+	static int cnt;
+	struct cxio_rdev *rdev_p = NULL;
+	struct respQ_msg_t *rsp_msg = (struct respQ_msg_t *) skb->data;
+	PDBG("%d: %s cq_id 0x%x cq_ptr 0x%x genbit %0x overflow %0x an %0x"
+	     " se %0x notify %0x cqbranch %0x creditth %0x\n",
+	     cnt, __FUNCTION__, RSPQ_CQID(rsp_msg), RSPQ_CQPTR(rsp_msg),
+	     RSPQ_GENBIT(rsp_msg), RSPQ_OVERFLOW(rsp_msg), RSPQ_AN(rsp_msg),
+	     RSPQ_SE(rsp_msg), RSPQ_NOTIFY(rsp_msg), RSPQ_CQBRANCH(rsp_msg),
+	     RSPQ_CREDIT_THRESH(rsp_msg));
+	PDBG("CQE: QPID 0x%0x genbit %0x type 0x%0x status 0x%0x opcode %d "
+	     "len 0x%0x wrid_hi_stag 0x%x wrid_low_msn 0x%x\n",
+	     CQE_QPID(rsp_msg->cqe), CQE_GENBIT(rsp_msg->cqe),
+	     CQE_TYPE(rsp_msg->cqe), CQE_STATUS(rsp_msg->cqe),
+	     CQE_OPCODE(rsp_msg->cqe), CQE_LEN(rsp_msg->cqe),
+	     CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+	rdev_p = (struct cxio_rdev *)t3cdev_p->ulp;
+	if (!rdev_p) {
+		PDBG("%s called by t3cdev %p with null ulp\n", __FUNCTION__,
+		     t3cdev_p);
+		return 0;
+	}
+	if (CQE_QPID(rsp_msg->cqe) == T3_CTRL_QP_ID) {
+		rdev_p->ctrl_qp.rptr = CQE_WRID_LOW(rsp_msg->cqe) + 1;
+		wake_up_interruptible(&rdev_p->ctrl_qp.waitq);
+		dev_kfree_skb_irq(skb);
+	} else if (CQE_QPID(rsp_msg->cqe) == 0xfff8)
+		dev_kfree_skb_irq(skb);
+	else if (cxio_ev_cb)
+		(*cxio_ev_cb) (rdev_p, skb);
+	else
+		dev_kfree_skb_irq(skb);
+	cnt++;
+	return 0;
+}
+
+/* Caller takes care of locking if needed */
+int cxio_rdev_open(struct cxio_rdev *rdev_p)
+{
+	struct net_device *netdev_p = NULL;
+	int err = 0;
+	if (strlen(rdev_p->dev_name)) {
+		if (cxio_hal_find_rdev_by_name(rdev_p->dev_name)) {
+			return -EBUSY;
+		}
+		netdev_p = dev_get_by_name(rdev_p->dev_name);
+		if (!netdev_p) {
+			return -EINVAL;
+		}
+		dev_put(netdev_p);
+	} else if (rdev_p->t3cdev_p) {
+		if (cxio_hal_find_rdev_by_t3cdev(rdev_p->t3cdev_p)) {
+			return -EBUSY;
+		}
+		netdev_p = rdev_p->t3cdev_p->lldev;
+		strncpy(rdev_p->dev_name, rdev_p->t3cdev_p->name,
+			T3_MAX_DEV_NAME_LEN);
+	} else {
+		PDBG("%s t3cdev_p or dev_name must be set\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	list_add_tail(&rdev_p->entry, &rdev_list);
+
+	PDBG("%s opening rnic dev %s\n", __FUNCTION__, rdev_p->dev_name);
+	memset(&rdev_p->ctrl_qp, 0, sizeof(rdev_p->ctrl_qp));
+	if (!rdev_p->t3cdev_p)
+		rdev_p->t3cdev_p = T3CDEV(netdev_p);
+	rdev_p->t3cdev_p->ulp = (void *) rdev_p;
+	err = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_GET_PARAMS,
+					 &(rdev_p->rnic_info));
+	if (err) {
+		printk(KERN_ERR "%s t3cdev_p(%p)->ctl returned error %d.\n",
+		     __FUNCTION__, rdev_p->t3cdev_p, err);
+		goto err1;
+	}
+	err = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, GET_PORTS,
+				    &(rdev_p->port_info));
+	if (err) {
+		printk(KERN_ERR "%s t3cdev_p(%p)->ctl returned error %d.\n",
+		     __FUNCTION__, rdev_p->t3cdev_p, err);
+		goto err1;
+	}
+
+	/*
+	 * qpshift is the number of bits to shift the qpid left in order
+	 * to get the correct address of the doorbell for that qp.
+	 */
+	cxio_init_ucontext(rdev_p, &rdev_p->uctx);
+	rdev_p->qpshift = PAGE_SHIFT -
+			  ilog2(65536 >>
+			            ilog2(rdev_p->rnic_info.udbell_len >>
+					      PAGE_SHIFT));
+	rdev_p->qpnr = rdev_p->rnic_info.udbell_len >> PAGE_SHIFT;
+	rdev_p->qpmask = (65536 >> ilog2(rdev_p->qpnr)) - 1;
+	PDBG("%s rnic %s info: tpt_base 0x%0x tpt_top 0x%0x num stags %d "
+	     "pbl_base 0x%0x pbl_top 0x%0x rqt_base 0x%0x, rqt_top 0x%0x\n",
+	     __FUNCTION__, rdev_p->dev_name, rdev_p->rnic_info.tpt_base,
+	     rdev_p->rnic_info.tpt_top, cxio_num_stags(rdev_p),
+	     rdev_p->rnic_info.pbl_base,
+	     rdev_p->rnic_info.pbl_top, rdev_p->rnic_info.rqt_base,
+	     rdev_p->rnic_info.rqt_top);
+	PDBG("udbell_len 0x%0x udbell_physbase 0x%lx kdb_addr %p qpshift %lu "
+	     "qpnr %d qpmask 0x%x\n",
+	     rdev_p->rnic_info.udbell_len,
+	     rdev_p->rnic_info.udbell_physbase, rdev_p->rnic_info.kdb_addr,
+	     rdev_p->qpshift, rdev_p->qpnr, rdev_p->qpmask);
+
+	err = cxio_hal_init_ctrl_qp(rdev_p);
+	if (err) {
+		printk(KERN_ERR "%s error %d initializing ctrl_qp.\n",
+		       __FUNCTION__, err);
+		goto err1;
+	}
+	err = cxio_hal_init_resource(rdev_p, cxio_num_stags(rdev_p), 0,
+				     0, T3_MAX_NUM_QP, T3_MAX_NUM_CQ,
+				     T3_MAX_NUM_PD);
+	if (err) {
+		printk(KERN_ERR "%s error %d initializing hal resources.\n",
+		       __FUNCTION__, err);
+		goto err2;
+	}
+	err = cxio_hal_pblpool_create(rdev_p);
+	if (err) {
+		printk(KERN_ERR "%s error %d initializing pbl mem pool.\n",
+		       __FUNCTION__, err);
+		goto err3;
+	}
+	err = cxio_hal_rqtpool_create(rdev_p);
+	if (err) {
+		printk(KERN_ERR "%s error %d initializing rqt mem pool.\n",
+		       __FUNCTION__, err);
+		goto err4;
+	}
+	return 0;
+err4:
+	cxio_hal_pblpool_destroy(rdev_p);
+err3:
+	cxio_hal_destroy_resource(rdev_p->rscp);
+err2:
+	cxio_hal_destroy_ctrl_qp(rdev_p);
+err1:
+	list_del(&rdev_p->entry);
+	return err;
+}
+
+void cxio_rdev_close(struct cxio_rdev *rdev_p)
+{
+	if (rdev_p) {
+		cxio_hal_pblpool_destroy(rdev_p);
+		cxio_hal_rqtpool_destroy(rdev_p);
+		list_del(&rdev_p->entry);
+		rdev_p->t3cdev_p->ulp = NULL;
+		cxio_hal_destroy_ctrl_qp(rdev_p);
+		cxio_hal_destroy_resource(rdev_p->rscp);
+	}
+}
+
+int __init cxio_hal_init(void)
+{
+	if (cxio_hal_init_rhdl_resource(T3_MAX_NUM_RI))
+		return -ENOMEM;
+	t3_register_cpl_handler(CPL_ASYNC_NOTIF, cxio_hal_ev_handler);
+	return 0;
+}
+
+void __exit cxio_hal_exit(void)
+{
+	struct cxio_rdev *rdev, *tmp;
+
+	t3_register_cpl_handler(CPL_ASYNC_NOTIF, NULL);
+	list_for_each_entry_safe(rdev, tmp, &rdev_list, entry)
+		cxio_rdev_close(rdev);
+	cxio_hal_destroy_rhdl_resource();
+}
+
+static inline void flush_completed_wrs(struct t3_wq *wq, struct t3_cq *cq)
+{
+	struct t3_swsq *sqp;
+	__u32 ptr = wq->sq_rptr;
+	int count = Q_COUNT(wq->sq_rptr, wq->sq_wptr);
+
+	sqp = wq->sq + Q_PTR2IDX(ptr, wq->sq_size_log2);
+	while (count--)
+		if (!sqp->signaled) {
+			ptr++;
+			sqp = wq->sq + Q_PTR2IDX(ptr,  wq->sq_size_log2);
+		} else if (sqp->complete) {
+
+			/*
+			 * Insert this completed cqe into the swcq.
+			 */
+			PDBG("%s moving cqe into swcq sq idx %ld cq idx %ld\n",
+			     __FUNCTION__, Q_PTR2IDX(ptr,  wq->sq_size_log2),
+			     Q_PTR2IDX(cq->sw_wptr, cq->size_log2));
+			sqp->cqe.header |= htonl(V_CQE_SWCQE(1));
+			*(cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2))
+				= sqp->cqe;
+			cq->sw_wptr++;
+			sqp->signaled = 0;
+			break;
+		} else
+			break;
+}
+
+static inline void create_read_req_cqe(struct t3_wq *wq,
+				       struct t3_cqe *hw_cqe,
+				       struct t3_cqe *read_cqe)
+{
+	read_cqe->u.scqe.wrid_hi = wq->oldest_read->sq_wptr;
+	read_cqe->len = wq->oldest_read->read_len;
+	read_cqe->header = htonl(V_CQE_QPID(CQE_QPID(*hw_cqe)) |
+				 V_CQE_SWCQE(SW_CQE(*hw_cqe)) |
+				 V_CQE_OPCODE(T3_READ_REQ) |
+				 V_CQE_TYPE(1));
+}
+
+/*
+ * Return a ptr to the next read wr in the SWSQ or NULL.
+ */
+static inline void advance_oldest_read(struct t3_wq *wq)
+{
+
+	u32 rptr = wq->oldest_read - wq->sq + 1;
+	u32 wptr = Q_PTR2IDX(wq->sq_wptr, wq->sq_size_log2);
+
+	while (Q_PTR2IDX(rptr, wq->sq_size_log2) != wptr) {
+		wq->oldest_read = wq->sq + Q_PTR2IDX(rptr, wq->sq_size_log2);
+
+		if (wq->oldest_read->opcode == T3_READ_REQ)
+			return;
+		rptr++;
+	}
+	wq->oldest_read = NULL;
+}
+
+/*
+ * cxio_poll_cq
+ *
+ * Caller must:
+ *     check the validity of the first CQE,
+ *     supply the wq assicated with the qpid.
+ *
+ * credit: cq credit to return to sge.
+ * cqe_flushed: 1 iff the CQE is flushed.
+ * cqe: copy of the polled CQE.
+ *
+ * return value:
+ *     0       CQE returned,
+ *    -1       CQE skipped, try again.
+ */
+int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
+		     u8 *cqe_flushed, u64 *cookie, u32 *credit)
+{
+	int ret = 0;
+	struct t3_cqe *hw_cqe, read_cqe;
+
+	*cqe_flushed = 0;
+	*credit = 0;
+	hw_cqe = cxio_next_cqe(cq);
+
+	PDBG("%s CQE OOO %d qpid 0x%0x genbit %d type %d status 0x%0x"
+	     " opcode 0x%0x len 0x%0x wrid_hi_stag 0x%x wrid_low_msn 0x%x\n",
+	     __FUNCTION__, CQE_OOO(*hw_cqe), CQE_QPID(*hw_cqe),
+	     CQE_GENBIT(*hw_cqe), CQE_TYPE(*hw_cqe), CQE_STATUS(*hw_cqe),
+	     CQE_OPCODE(*hw_cqe), CQE_LEN(*hw_cqe), CQE_WRID_HI(*hw_cqe),
+	     CQE_WRID_LOW(*hw_cqe));
+
+	/*
+	 * skip cqe's not affiliated with a QP.
+	 */
+	if (wq == NULL) {
+		ret = -1;
+		goto skip_cqe;
+	}
+
+	/*
+	 * Gotta tweak READ completions:
+	 *	1) the cqe doesn't contain the sq_wptr from the wr.
+	 *	2) opcode not reflected from the wr.
+	 *	3) read_len not reflected from the wr.
+	 *	4) cq_type is RQ_TYPE not SQ_TYPE.
+	 */
+	if (RQ_TYPE(*hw_cqe) && (CQE_OPCODE(*hw_cqe) == T3_READ_RESP)) {
+
+		/*
+		 * Don't write to the HWCQ, so create a new read req CQE
+		 * in local memory.
+		 */
+		create_read_req_cqe(wq, hw_cqe, &read_cqe);
+		hw_cqe = &read_cqe;
+		advance_oldest_read(wq);
+	}
+
+	/*
+	 * T3A: Discard TERMINATE CQEs.
+	 */
+	if (CQE_OPCODE(*hw_cqe) == T3_TERMINATE) {
+		ret = -1;
+		wq->error = 1;
+		goto skip_cqe;
+	}
+
+	if (CQE_STATUS(*hw_cqe) || wq->error) {
+		*cqe_flushed = wq->error;
+		wq->error = 1;
+
+		/*
+		 * T3A inserts errors into the CQE.  We cannot return
+		 * these as work completions.
+		 */
+		/* incoming write failures */
+		if ((CQE_OPCODE(*hw_cqe) == T3_RDMA_WRITE)
+		     && RQ_TYPE(*hw_cqe)) {
+			ret = -1;
+			goto skip_cqe;
+		}
+		/* incoming read request failures */
+		if ((CQE_OPCODE(*hw_cqe) == T3_READ_RESP) && SQ_TYPE(*hw_cqe)) {
+			ret = -1;
+			goto skip_cqe;
+		}
+
+		/* incoming SEND with no receive posted failures */
+		if ((CQE_OPCODE(*hw_cqe) == T3_SEND) && RQ_TYPE(*hw_cqe) &&
+		    Q_EMPTY(wq->rq_rptr, wq->rq_wptr)) {
+			ret = -1;
+			goto skip_cqe;
+		}
+		goto proc_cqe;
+	}
+
+	/*
+	 * RECV completion.
+	 */
+	if (RQ_TYPE(*hw_cqe)) {
+
+		/*
+		 * HW only validates 4 bits of MSN.  So we must validate that
+		 * the MSN in the SEND is the next expected MSN.  If its not,
+		 * then we complete this with TPT_ERR_MSN and mark the wq in
+		 * error.
+		 */
+		if (unlikely((CQE_WRID_MSN(*hw_cqe) != (wq->rq_rptr + 1)))) {
+			wq->error = 1;
+			hw_cqe->header |= htonl(V_CQE_STATUS(TPT_ERR_MSN));
+			goto proc_cqe;
+		}
+		goto proc_cqe;
+	}
+
+	/*
+	 * If we get here its a send completion.
+	 *
+	 * Handle out of order completion. These get stuffed
+	 * in the SW SQ. Then the SW SQ is walked to move any
+	 * now in-order completions into the SW CQ.  This handles
+	 * 2 cases:
+	 *	1) reaping unsignaled WRs when the first subsequent
+	 *	   signaled WR is completed.
+	 *	2) out of order read completions.
+	 */
+	if (!SW_CQE(*hw_cqe) && (CQE_WRID_SQ_WPTR(*hw_cqe) != wq->sq_rptr)) {
+		struct t3_swsq *sqp;
+
+		PDBG("%s out of order completion going in swsq at idx %ld\n",
+		     __FUNCTION__,
+		     Q_PTR2IDX(CQE_WRID_SQ_WPTR(*hw_cqe), wq->sq_size_log2));
+		sqp = wq->sq +
+		      Q_PTR2IDX(CQE_WRID_SQ_WPTR(*hw_cqe), wq->sq_size_log2);
+		sqp->cqe = *hw_cqe;
+		sqp->complete = 1;
+		ret = -1;
+		goto flush_wq;
+	}
+
+proc_cqe:
+	*cqe = *hw_cqe;
+
+	/*
+	 * Reap the associated WR(s) that are freed up with this
+	 * completion.
+	 */
+	if (SQ_TYPE(*hw_cqe)) {
+		wq->sq_rptr = CQE_WRID_SQ_WPTR(*hw_cqe);
+		PDBG("%s completing sq idx %ld\n", __FUNCTION__,
+		     Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2));
+		*cookie = (wq->sq +
+			   Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2))->wr_id;
+		wq->sq_rptr++;
+	} else {
+		PDBG("%s completing rq idx %ld\n", __FUNCTION__,
+		     Q_PTR2IDX(wq->rq_rptr, wq->rq_size_log2));
+		*cookie = *(wq->rq + Q_PTR2IDX(wq->rq_rptr, wq->rq_size_log2));
+		wq->rq_rptr++;
+	}
+
+flush_wq:
+	/*
+	 * Flush any completed cqes that are now in-order.
+	 */
+	flush_completed_wrs(wq, cq);
+
+skip_cqe:
+	if (SW_CQE(*hw_cqe)) {
+		PDBG("%s cq %p cqid 0x%x skip sw cqe sw_rptr 0x%x\n",
+		     __FUNCTION__, cq, cq->cqid, cq->sw_rptr);
+		++cq->sw_rptr;
+	} else {
+		PDBG("%s cq %p cqid 0x%x skip hw cqe rptr 0x%x\n",
+		     __FUNCTION__, cq, cq->cqid, cq->rptr);
+		++cq->rptr;
+
+		/*
+		 * T3A: compute credits.
+		 */
+		if (((cq->rptr - cq->wptr) > (1 << (cq->size_log2 - 1)))
+		    || ((cq->rptr - cq->wptr) >= 128)) {
+			*credit = cq->rptr - cq->wptr;
+			cq->wptr = cq->rptr;
+		}
+	}
+	return ret;
+}
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h
new file mode 100644
index 0000000..8ab04a7
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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  __CXIO_HAL_H__
+#define  __CXIO_HAL_H__
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+
+#include "t3_cpl.h"
+#include "t3cdev.h"
+#include "cxgb3_ctl_defs.h"
+#include "cxio_wr.h"
+
+#define T3_CTRL_QP_ID    FW_RI_SGEEC_START
+#define T3_CTL_QP_TID	 FW_RI_TID_START
+#define T3_CTRL_QP_SIZE_LOG2  8
+#define T3_CTRL_CQ_ID    0
+
+/* TBD */
+#define T3_MAX_NUM_RI (1<<15)
+#define T3_MAX_NUM_QP (1<<15)
+#define T3_MAX_NUM_CQ (1<<15)
+#define T3_MAX_NUM_PD (1<<15)
+#define T3_MAX_PBL_SIZE 256
+#define T3_MAX_RQ_SIZE 1024
+#define T3_MAX_NUM_STAG (1<<15)
+
+#define T3_STAG_UNSET 0xffffffff
+
+#define T3_MAX_DEV_NAME_LEN 32
+
+struct cxio_hal_ctrl_qp {
+	u32 wptr;
+	u32 rptr;
+	struct mutex lock;	/* for the wtpr, can sleep */
+	wait_queue_head_t waitq;/* wait for RspQ/CQE msg */
+	union t3_wr *workq;	/* the work request queue */
+	dma_addr_t dma_addr;	/* pci bus address of the workq */
+	DECLARE_PCI_UNMAP_ADDR(mapping)
+	void __iomem *doorbell;
+};
+
+struct cxio_hal_resource {
+	struct kfifo *tpt_fifo;
+	spinlock_t tpt_fifo_lock;
+	struct kfifo *qpid_fifo;
+	spinlock_t qpid_fifo_lock;
+	struct kfifo *cqid_fifo;
+	spinlock_t cqid_fifo_lock;
+	struct kfifo *pdid_fifo;
+	spinlock_t pdid_fifo_lock;
+};
+
+struct cxio_qpid_list {
+	struct list_head entry;
+	u32 qpid;
+};
+
+struct cxio_ucontext {
+	struct list_head qpids;
+	struct mutex lock;
+};
+
+struct cxio_rdev {
+	char dev_name[T3_MAX_DEV_NAME_LEN];
+	struct t3cdev *t3cdev_p;
+	struct rdma_info rnic_info;
+	struct adap_ports port_info;
+	struct cxio_hal_resource *rscp;
+	struct cxio_hal_ctrl_qp ctrl_qp;
+	void *ulp;
+	unsigned long qpshift;
+	u32 qpnr;
+	u32 qpmask;
+	struct cxio_ucontext uctx;
+	struct gen_pool *pbl_pool;
+	struct gen_pool *rqt_pool;
+	struct list_head entry;
+};
+
+static inline int cxio_num_stags(struct cxio_rdev *rdev_p)
+{
+	return min((int)T3_MAX_NUM_STAG, (int)((rdev_p->rnic_info.tpt_top - rdev_p->rnic_info.tpt_base) >> 5));
+}
+
+typedef void (*cxio_hal_ev_callback_func_t) (struct cxio_rdev * rdev_p,
+					     struct sk_buff * skb);
+
+#define RSPQ_CQID(rsp) (be32_to_cpu(rsp->cq_ptrid) & 0xffff)
+#define RSPQ_CQPTR(rsp) ((be32_to_cpu(rsp->cq_ptrid) >> 16) & 0xffff)
+#define RSPQ_GENBIT(rsp) ((be32_to_cpu(rsp->flags) >> 16) & 1)
+#define RSPQ_OVERFLOW(rsp) ((be32_to_cpu(rsp->flags) >> 17) & 1)
+#define RSPQ_AN(rsp) ((be32_to_cpu(rsp->flags) >> 18) & 1)
+#define RSPQ_SE(rsp) ((be32_to_cpu(rsp->flags) >> 19) & 1)
+#define RSPQ_NOTIFY(rsp) ((be32_to_cpu(rsp->flags) >> 20) & 1)
+#define RSPQ_CQBRANCH(rsp) ((be32_to_cpu(rsp->flags) >> 21) & 1)
+#define RSPQ_CREDIT_THRESH(rsp) ((be32_to_cpu(rsp->flags) >> 22) & 1)
+
+struct respQ_msg_t {
+	__be32 flags;		/* flit 0 */
+	__be32 cq_ptrid;
+	__be64 rsvd;		/* flit 1 */
+	struct t3_cqe cqe;	/* flits 2-3 */
+};
+
+enum t3_cq_opcode {
+	CQ_ARM_AN = 0x2,
+	CQ_ARM_SE = 0x6,
+	CQ_FORCE_AN = 0x3,
+	CQ_CREDIT_UPDATE = 0x7
+};
+
+int cxio_rdev_open(struct cxio_rdev *rdev);
+void cxio_rdev_close(struct cxio_rdev *rdev);
+int cxio_hal_cq_op(struct cxio_rdev *rdev, struct t3_cq *cq,
+		   enum t3_cq_opcode op, u32 credit);
+int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev, u32 qpid);
+int cxio_create_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
+int cxio_destroy_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
+int cxio_resize_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
+void cxio_release_ucontext(struct cxio_rdev *rdev, struct cxio_ucontext *uctx);
+void cxio_init_ucontext(struct cxio_rdev *rdev, struct cxio_ucontext *uctx);
+int cxio_create_qp(struct cxio_rdev *rdev, u32 kernel_domain, struct t3_wq *wq,
+		   struct cxio_ucontext *uctx);
+int cxio_destroy_qp(struct cxio_rdev *rdev, struct t3_wq *wq,
+		    struct cxio_ucontext *uctx);
+int cxio_peek_cq(struct t3_wq *wr, struct t3_cq *cq, int opcode);
+int cxio_allocate_stag(struct cxio_rdev *rdev, u32 * stag, u32 pdid,
+		       enum tpt_mem_perm perm, u32 * pbl_size, u32 * pbl_addr);
+int cxio_register_phys_mem(struct cxio_rdev *rdev, u32 * stag, u32 pdid,
+			   enum tpt_mem_perm perm, u32 zbva, u64 to, u32 len,
+			   u8 page_size, __be64 *pbl, u32 *pbl_size,
+			   u32 *pbl_addr);
+int cxio_reregister_phys_mem(struct cxio_rdev *rdev, u32 * stag, u32 pdid,
+			   enum tpt_mem_perm perm, u32 zbva, u64 to, u32 len,
+			   u8 page_size, __be64 *pbl, u32 *pbl_size,
+			   u32 *pbl_addr);
+int cxio_dereg_mem(struct cxio_rdev *rdev, u32 stag, u32 pbl_size,
+		   u32 pbl_addr);
+int cxio_allocate_window(struct cxio_rdev *rdev, u32 * stag, u32 pdid);
+int cxio_deallocate_window(struct cxio_rdev *rdev, u32 stag);
+int cxio_rdma_init(struct cxio_rdev *rdev, struct t3_rdma_init_attr *attr);
+void cxio_register_ev_cb(cxio_hal_ev_callback_func_t ev_cb);
+void cxio_unregister_ev_cb(cxio_hal_ev_callback_func_t ev_cb);
+u32 cxio_hal_get_rhdl(void);
+void cxio_hal_put_rhdl(u32 rhdl);
+u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp);
+void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid);
+int __init cxio_hal_init(void);
+void __exit cxio_hal_exit(void);
+void cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count);
+void cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count);
+void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count);
+void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count);
+void cxio_flush_hw_cq(struct t3_cq *cq);
+int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
+		     u8 *cqe_flushed, u64 *cookie, u32 *credit);
+
+#define MOD "iw_cxgb3: "
+#define PDBG(fmt, args...) pr_debug(MOD fmt, ## args)
+
+#ifdef DEBUG
+void cxio_dump_tpt(struct cxio_rdev *rev, u32 stag);
+void cxio_dump_pbl(struct cxio_rdev *rev, u32 pbl_addr, uint len, u8 shift);
+void cxio_dump_wqe(union t3_wr *wqe);
+void cxio_dump_wce(struct t3_cqe *wce);
+void cxio_dump_rqt(struct cxio_rdev *rdev, u32 hwtid, int nents);
+void cxio_dump_tcb(struct cxio_rdev *rdev, u32 hwtid);
+#endif
+
+#endif
diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c
new file mode 100644
index 0000000..65bf577
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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.
+ */
+/* Crude resource management */
+#include <linux/kernel.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/kfifo.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include "cxio_resource.h"
+#include "cxio_hal.h"
+
+static struct kfifo *rhdl_fifo;
+static spinlock_t rhdl_fifo_lock;
+
+#define RANDOM_SIZE 16
+
+static int __cxio_init_resource_fifo(struct kfifo **fifo,
+				   spinlock_t *fifo_lock,
+				   u32 nr, u32 skip_low,
+				   u32 skip_high,
+				   int random)
+{
+	u32 i, j, entry = 0, idx;
+	u32 random_bytes;
+	u32 rarray[16];
+	spin_lock_init(fifo_lock);
+
+	*fifo = kfifo_alloc(nr * sizeof(u32), GFP_KERNEL, fifo_lock);
+	if (IS_ERR(*fifo))
+		return -ENOMEM;
+
+	for (i = 0; i < skip_low + skip_high; i++)
+		__kfifo_put(*fifo, (unsigned char *) &entry, sizeof(u32));
+	if (random) {
+		j = 0;
+		random_bytes = random32();
+		for (i = 0; i < RANDOM_SIZE; i++)
+			rarray[i] = i + skip_low;
+		for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {
+			if (j >= RANDOM_SIZE) {
+				j = 0;
+				random_bytes = random32();
+			}
+			idx = (random_bytes >> (j * 2)) & 0xF;
+			__kfifo_put(*fifo,
+				(unsigned char *) &rarray[idx],
+				sizeof(u32));
+			rarray[idx] = i;
+			j++;
+		}
+		for (i = 0; i < RANDOM_SIZE; i++)
+			__kfifo_put(*fifo,
+				(unsigned char *) &rarray[i],
+				sizeof(u32));
+	} else
+		for (i = skip_low; i < nr - skip_high; i++)
+			__kfifo_put(*fifo, (unsigned char *) &i, sizeof(u32));
+
+	for (i = 0; i < skip_low + skip_high; i++)
+		kfifo_get(*fifo, (unsigned char *) &entry, sizeof(u32));
+	return 0;
+}
+
+static int cxio_init_resource_fifo(struct kfifo **fifo, spinlock_t * fifo_lock,
+				   u32 nr, u32 skip_low, u32 skip_high)
+{
+	return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
+					  skip_high, 0));
+}
+
+static int cxio_init_resource_fifo_random(struct kfifo **fifo,
+				   spinlock_t * fifo_lock,
+				   u32 nr, u32 skip_low, u32 skip_high)
+{
+
+	return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
+					  skip_high, 1));
+}
+
+static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p)
+{
+	u32 i;
+
+	spin_lock_init(&rdev_p->rscp->qpid_fifo_lock);
+
+	rdev_p->rscp->qpid_fifo = kfifo_alloc(T3_MAX_NUM_QP * sizeof(u32),
+					      GFP_KERNEL,
+					      &rdev_p->rscp->qpid_fifo_lock);
+	if (IS_ERR(rdev_p->rscp->qpid_fifo))
+		return -ENOMEM;
+
+	for (i = 16; i < T3_MAX_NUM_QP; i++)
+		if (!(i & rdev_p->qpmask))
+			__kfifo_put(rdev_p->rscp->qpid_fifo,
+				    (unsigned char *) &i, sizeof(u32));
+	return 0;
+}
+
+int cxio_hal_init_rhdl_resource(u32 nr_rhdl)
+{
+	return cxio_init_resource_fifo(&rhdl_fifo, &rhdl_fifo_lock, nr_rhdl, 1,
+				       0);
+}
+
+void cxio_hal_destroy_rhdl_resource(void)
+{
+	kfifo_free(rhdl_fifo);
+}
+
+/* nr_* must be power of 2 */
+int cxio_hal_init_resource(struct cxio_rdev *rdev_p,
+			   u32 nr_tpt, u32 nr_pbl,
+			   u32 nr_rqt, u32 nr_qpid, u32 nr_cqid, u32 nr_pdid)
+{
+	int err = 0;
+	struct cxio_hal_resource *rscp;
+
+	rscp = kmalloc(sizeof(*rscp), GFP_KERNEL);
+	if (!rscp)
+		return -ENOMEM;
+	rdev_p->rscp = rscp;
+	err = cxio_init_resource_fifo_random(&rscp->tpt_fifo,
+				      &rscp->tpt_fifo_lock,
+				      nr_tpt, 1, 0);
+	if (err)
+		goto tpt_err;
+	err = cxio_init_qpid_fifo(rdev_p);
+	if (err)
+		goto qpid_err;
+	err = cxio_init_resource_fifo(&rscp->cqid_fifo, &rscp->cqid_fifo_lock,
+				      nr_cqid, 1, 0);
+	if (err)
+		goto cqid_err;
+	err = cxio_init_resource_fifo(&rscp->pdid_fifo, &rscp->pdid_fifo_lock,
+				      nr_pdid, 1, 0);
+	if (err)
+		goto pdid_err;
+	return 0;
+pdid_err:
+	kfifo_free(rscp->cqid_fifo);
+cqid_err:
+	kfifo_free(rscp->qpid_fifo);
+qpid_err:
+	kfifo_free(rscp->tpt_fifo);
+tpt_err:
+	return -ENOMEM;
+}
+
+/*
+ * returns 0 if no resource available
+ */
+static inline u32 cxio_hal_get_resource(struct kfifo *fifo)
+{
+	u32 entry;
+	if (kfifo_get(fifo, (unsigned char *) &entry, sizeof(u32)))
+		return entry;
+	else
+		return 0;	/* fifo emptry */
+}
+
+static inline void cxio_hal_put_resource(struct kfifo *fifo, u32 entry)
+{
+	BUG_ON(kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)) == 0);
+}
+
+u32 cxio_hal_get_rhdl(void)
+{
+	return cxio_hal_get_resource(rhdl_fifo);
+}
+
+void cxio_hal_put_rhdl(u32 rhdl)
+{
+	cxio_hal_put_resource(rhdl_fifo, rhdl);
+}
+
+u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp)
+{
+	return cxio_hal_get_resource(rscp->tpt_fifo);
+}
+
+void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag)
+{
+	cxio_hal_put_resource(rscp->tpt_fifo, stag);
+}
+
+u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp)
+{
+	u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo);
+	PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
+	return qpid;
+}
+
+void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid)
+{
+	PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
+	cxio_hal_put_resource(rscp->qpid_fifo, qpid);
+}
+
+u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp)
+{
+	return cxio_hal_get_resource(rscp->cqid_fifo);
+}
+
+void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid)
+{
+	cxio_hal_put_resource(rscp->cqid_fifo, cqid);
+}
+
+u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp)
+{
+	return cxio_hal_get_resource(rscp->pdid_fifo);
+}
+
+void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid)
+{
+	cxio_hal_put_resource(rscp->pdid_fifo, pdid);
+}
+
+void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp)
+{
+	kfifo_free(rscp->tpt_fifo);
+	kfifo_free(rscp->cqid_fifo);
+	kfifo_free(rscp->qpid_fifo);
+	kfifo_free(rscp->pdid_fifo);
+	kfree(rscp);
+}
+
+/*
+ * PBL Memory Manager.  Uses Linux generic allocator.
+ */
+
+#define MIN_PBL_SHIFT 8			/* 256B == min PBL size (32 entries) */
+#define PBL_CHUNK 2*1024*1024
+
+u32 cxio_hal_pblpool_alloc(struct cxio_rdev *rdev_p, int size)
+{
+	unsigned long addr = gen_pool_alloc(rdev_p->pbl_pool, size);
+	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, (u32)addr, size);
+	return (u32)addr;
+}
+
+void cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
+{
+	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, addr, size);
+	gen_pool_free(rdev_p->pbl_pool, (unsigned long)addr, size);
+}
+
+int cxio_hal_pblpool_create(struct cxio_rdev *rdev_p)
+{
+	unsigned long i;
+	rdev_p->pbl_pool = gen_pool_create(MIN_PBL_SHIFT, -1);
+	if (rdev_p->pbl_pool)
+		for (i = rdev_p->rnic_info.pbl_base;
+		     i <= rdev_p->rnic_info.pbl_top - PBL_CHUNK + 1;
+		     i += PBL_CHUNK)
+			gen_pool_add(rdev_p->pbl_pool, i, PBL_CHUNK, -1);
+	return rdev_p->pbl_pool ? 0 : -ENOMEM;
+}
+
+void cxio_hal_pblpool_destroy(struct cxio_rdev *rdev_p)
+{
+	gen_pool_destroy(rdev_p->pbl_pool);
+}
+
+/*
+ * RQT Memory Manager.  Uses Linux generic allocator.
+ */
+
+#define MIN_RQT_SHIFT 10	/* 1KB == mini RQT size (16 entries) */
+#define RQT_CHUNK 2*1024*1024
+
+u32 cxio_hal_rqtpool_alloc(struct cxio_rdev *rdev_p, int size)
+{
+	unsigned long addr = gen_pool_alloc(rdev_p->rqt_pool, size << 6);
+	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, (u32)addr, size << 6);
+	return (u32)addr;
+}
+
+void cxio_hal_rqtpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
+{
+	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, addr, size << 6);
+	gen_pool_free(rdev_p->rqt_pool, (unsigned long)addr, size << 6);
+}
+
+int cxio_hal_rqtpool_create(struct cxio_rdev *rdev_p)
+{
+	unsigned long i;
+	rdev_p->rqt_pool = gen_pool_create(MIN_RQT_SHIFT, -1);
+	if (rdev_p->rqt_pool)
+		for (i = rdev_p->rnic_info.rqt_base;
+		     i <= rdev_p->rnic_info.rqt_top - RQT_CHUNK + 1;
+		     i += RQT_CHUNK)
+			gen_pool_add(rdev_p->rqt_pool, i, RQT_CHUNK, -1);
+	return rdev_p->rqt_pool ? 0 : -ENOMEM;
+}
+
+void cxio_hal_rqtpool_destroy(struct cxio_rdev *rdev_p)
+{
+	gen_pool_destroy(rdev_p->rqt_pool);
+}
diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.h b/drivers/infiniband/hw/cxgb3/cxio_resource.h
new file mode 100644
index 0000000..a2703a3
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/cxio_resource.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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 __CXIO_RESOURCE_H__
+#define __CXIO_RESOURCE_H__
+
+#include <linux/kernel.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/kfifo.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/genalloc.h>
+#include "cxio_hal.h"
+
+extern int cxio_hal_init_rhdl_resource(u32 nr_rhdl);
+extern void cxio_hal_destroy_rhdl_resource(void);
+extern int cxio_hal_init_resource(struct cxio_rdev *rdev_p,
+				  u32 nr_tpt, u32 nr_pbl,
+				  u32 nr_rqt, u32 nr_qpid, u32 nr_cqid,
+				  u32 nr_pdid);
+extern u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp);
+extern void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag);
+extern u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp);
+extern void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid);
+extern u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp);
+extern void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid);
+extern void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp);
+
+#define PBL_OFF(rdev_p, a) ( (a) - (rdev_p)->rnic_info.pbl_base )
+extern int cxio_hal_pblpool_create(struct cxio_rdev *rdev_p);
+extern void cxio_hal_pblpool_destroy(struct cxio_rdev *rdev_p);
+extern u32 cxio_hal_pblpool_alloc(struct cxio_rdev *rdev_p, int size);
+extern void cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size);
+
+#define RQT_OFF(rdev_p, a) ( (a) - (rdev_p)->rnic_info.rqt_base )
+extern int cxio_hal_rqtpool_create(struct cxio_rdev *rdev_p);
+extern void cxio_hal_rqtpool_destroy(struct cxio_rdev *rdev_p);
+extern u32 cxio_hal_rqtpool_alloc(struct cxio_rdev *rdev_p, int size);
+extern void cxio_hal_rqtpool_free(struct cxio_rdev *rdev_p, u32 addr, int size);
+#endif
diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h
new file mode 100644
index 0000000..90d7b89
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h
@@ -0,0 +1,684 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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 __CXIO_WR_H__
+#define __CXIO_WR_H__
+
+#include <asm/io.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include "firmware_exports.h"
+
+#define T3_MAX_SGE      4
+
+#define Q_EMPTY(rptr,wptr) ((rptr)==(wptr))
+#define Q_FULL(rptr,wptr,size_log2)  ( (((wptr)-(rptr))>>(size_log2)) && \
+				       ((rptr)!=(wptr)) )
+#define Q_GENBIT(ptr,size_log2) (!(((ptr)>>size_log2)&0x1))
+#define Q_FREECNT(rptr,wptr,size_log2) ((1UL<<size_log2)-((wptr)-(rptr)))
+#define Q_COUNT(rptr,wptr) ((wptr)-(rptr))
+#define Q_PTR2IDX(ptr,size_log2) (ptr & ((1UL<<size_log2)-1))
+
+static inline void ring_doorbell(void __iomem *doorbell, u32 qpid)
+{
+	writel(((1<<31) | qpid), doorbell);
+}
+
+#define SEQ32_GE(x,y) (!( (((u32) (x)) - ((u32) (y))) & 0x80000000 ))
+
+enum t3_wr_flags {
+	T3_COMPLETION_FLAG = 0x01,
+	T3_NOTIFY_FLAG = 0x02,
+	T3_SOLICITED_EVENT_FLAG = 0x04,
+	T3_READ_FENCE_FLAG = 0x08,
+	T3_LOCAL_FENCE_FLAG = 0x10
+} __attribute__ ((packed));
+
+enum t3_wr_opcode {
+	T3_WR_BP = FW_WROPCODE_RI_BYPASS,
+	T3_WR_SEND = FW_WROPCODE_RI_SEND,
+	T3_WR_WRITE = FW_WROPCODE_RI_RDMA_WRITE,
+	T3_WR_READ = FW_WROPCODE_RI_RDMA_READ,
+	T3_WR_INV_STAG = FW_WROPCODE_RI_LOCAL_INV,
+	T3_WR_BIND = FW_WROPCODE_RI_BIND_MW,
+	T3_WR_RCV = FW_WROPCODE_RI_RECEIVE,
+	T3_WR_INIT = FW_WROPCODE_RI_RDMA_INIT,
+	T3_WR_QP_MOD = FW_WROPCODE_RI_MODIFY_QP
+} __attribute__ ((packed));
+
+enum t3_rdma_opcode {
+	T3_RDMA_WRITE,		/* IETF RDMAP v1.0 ... */
+	T3_READ_REQ,
+	T3_READ_RESP,
+	T3_SEND,
+	T3_SEND_WITH_INV,
+	T3_SEND_WITH_SE,
+	T3_SEND_WITH_SE_INV,
+	T3_TERMINATE,
+	T3_RDMA_INIT,		/* CHELSIO RI specific ... */
+	T3_BIND_MW,
+	T3_FAST_REGISTER,
+	T3_LOCAL_INV,
+	T3_QP_MOD,
+	T3_BYPASS
+} __attribute__ ((packed));
+
+static inline enum t3_rdma_opcode wr2opcode(enum t3_wr_opcode wrop)
+{
+	switch (wrop) {
+		case T3_WR_BP: return T3_BYPASS;
+		case T3_WR_SEND: return T3_SEND;
+		case T3_WR_WRITE: return T3_RDMA_WRITE;
+		case T3_WR_READ: return T3_READ_REQ;
+		case T3_WR_INV_STAG: return T3_LOCAL_INV;
+		case T3_WR_BIND: return T3_BIND_MW;
+		case T3_WR_INIT: return T3_RDMA_INIT;
+		case T3_WR_QP_MOD: return T3_QP_MOD;
+		default: break;
+	}
+	return -1;
+}
+
+
+/* Work request id */
+union t3_wrid {
+	struct {
+		u32 hi;
+		u32 low;
+	} id0;
+	u64 id1;
+};
+
+#define WRID(wrid)		(wrid.id1)
+#define WRID_GEN(wrid)		(wrid.id0.wr_gen)
+#define WRID_IDX(wrid)		(wrid.id0.wr_idx)
+#define WRID_LO(wrid)		(wrid.id0.wr_lo)
+
+struct fw_riwrh {
+	__be32 op_seop_flags;
+	__be32 gen_tid_len;
+};
+
+#define S_FW_RIWR_OP		24
+#define M_FW_RIWR_OP		0xff
+#define V_FW_RIWR_OP(x)		((x) << S_FW_RIWR_OP)
+#define G_FW_RIWR_OP(x)	((((x) >> S_FW_RIWR_OP)) & M_FW_RIWR_OP)
+
+#define S_FW_RIWR_SOPEOP	22
+#define M_FW_RIWR_SOPEOP	0x3
+#define V_FW_RIWR_SOPEOP(x)	((x) << S_FW_RIWR_SOPEOP)
+
+#define S_FW_RIWR_FLAGS		8
+#define M_FW_RIWR_FLAGS		0x3fffff
+#define V_FW_RIWR_FLAGS(x)	((x) << S_FW_RIWR_FLAGS)
+#define G_FW_RIWR_FLAGS(x)	((((x) >> S_FW_RIWR_FLAGS)) & M_FW_RIWR_FLAGS)
+
+#define S_FW_RIWR_TID		8
+#define V_FW_RIWR_TID(x)	((x) << S_FW_RIWR_TID)
+
+#define S_FW_RIWR_LEN		0
+#define V_FW_RIWR_LEN(x)	((x) << S_FW_RIWR_LEN)
+
+#define S_FW_RIWR_GEN           31
+#define V_FW_RIWR_GEN(x)        ((x)  << S_FW_RIWR_GEN)
+
+struct t3_sge {
+	__be32 stag;
+	__be32 len;
+	__be64 to;
+};
+
+/* If num_sgle is zero, flit 5+ contains immediate data.*/
+struct t3_send_wr {
+	struct fw_riwrh wrh;	/* 0 */
+	union t3_wrid wrid;	/* 1 */
+
+	u8 rdmaop;		/* 2 */
+	u8 reserved[3];
+	__be32 rem_stag;
+	__be32 plen;		/* 3 */
+	__be32 num_sgle;
+	struct t3_sge sgl[T3_MAX_SGE];	/* 4+ */
+};
+
+struct t3_local_inv_wr {
+	struct fw_riwrh wrh;	/* 0 */
+	union t3_wrid wrid;	/* 1 */
+	__be32 stag;		/* 2 */
+	__be32 reserved3;
+};
+
+struct t3_rdma_write_wr {
+	struct fw_riwrh wrh;	/* 0 */
+	union t3_wrid wrid;	/* 1 */
+	u8 rdmaop;		/* 2 */
+	u8 reserved[3];
+	__be32 stag_sink;
+	__be64 to_sink;		/* 3 */
+	__be32 plen;		/* 4 */
+	__be32 num_sgle;
+	struct t3_sge sgl[T3_MAX_SGE];	/* 5+ */
+};
+
+struct t3_rdma_read_wr {
+	struct fw_riwrh wrh;	/* 0 */
+	union t3_wrid wrid;	/* 1 */
+	u8 rdmaop;		/* 2 */
+	u8 reserved[3];
+	__be32 rem_stag;
+	__be64 rem_to;		/* 3 */
+	__be32 local_stag;	/* 4 */
+	__be32 local_len;
+	__be64 local_to;	/* 5 */
+};
+
+enum t3_addr_type {
+	T3_VA_BASED_TO = 0x0,
+	T3_ZERO_BASED_TO = 0x1
+} __attribute__ ((packed));
+
+enum t3_mem_perms {
+	T3_MEM_ACCESS_LOCAL_READ = 0x1,
+	T3_MEM_ACCESS_LOCAL_WRITE = 0x2,
+	T3_MEM_ACCESS_REM_READ = 0x4,
+	T3_MEM_ACCESS_REM_WRITE = 0x8
+} __attribute__ ((packed));
+
+struct t3_bind_mw_wr {
+	struct fw_riwrh wrh;	/* 0 */
+	union t3_wrid wrid;	/* 1 */
+	u16 reserved;		/* 2 */
+	u8 type;
+	u8 perms;
+	__be32 mr_stag;
+	__be32 mw_stag;		/* 3 */
+	__be32 mw_len;
+	__be64 mw_va;		/* 4 */
+	__be32 mr_pbl_addr;	/* 5 */
+	u8 reserved2[3];
+	u8 mr_pagesz;
+};
+
+struct t3_receive_wr {
+	struct fw_riwrh wrh;	/* 0 */
+	union t3_wrid wrid;	/* 1 */
+	u8 pagesz[T3_MAX_SGE];
+	__be32 num_sgle;		/* 2 */
+	struct t3_sge sgl[T3_MAX_SGE];	/* 3+ */
+	__be32 pbl_addr[T3_MAX_SGE];
+};
+
+struct t3_bypass_wr {
+	struct fw_riwrh wrh;
+	union t3_wrid wrid;	/* 1 */
+};
+
+struct t3_modify_qp_wr {
+	struct fw_riwrh wrh;	/* 0 */
+	union t3_wrid wrid;	/* 1 */
+	__be32 flags;		/* 2 */
+	__be32 quiesce;		/* 2 */
+	__be32 max_ird;		/* 3 */
+	__be32 max_ord;		/* 3 */
+	__be64 sge_cmd;		/* 4 */
+	__be64 ctx1;		/* 5 */
+	__be64 ctx0;		/* 6 */
+};
+
+enum t3_modify_qp_flags {
+	MODQP_QUIESCE  = 0x01,
+	MODQP_MAX_IRD  = 0x02,
+	MODQP_MAX_ORD  = 0x04,
+	MODQP_WRITE_EC = 0x08,
+	MODQP_READ_EC  = 0x10,
+};
+
+
+enum t3_mpa_attrs {
+	uP_RI_MPA_RX_MARKER_ENABLE = 0x1,
+	uP_RI_MPA_TX_MARKER_ENABLE = 0x2,
+	uP_RI_MPA_CRC_ENABLE = 0x4,
+	uP_RI_MPA_IETF_ENABLE = 0x8
+} __attribute__ ((packed));
+
+enum t3_qp_caps {
+	uP_RI_QP_RDMA_READ_ENABLE = 0x01,
+	uP_RI_QP_RDMA_WRITE_ENABLE = 0x02,
+	uP_RI_QP_BIND_ENABLE = 0x04,
+	uP_RI_QP_FAST_REGISTER_ENABLE = 0x08,
+	uP_RI_QP_STAG0_ENABLE = 0x10
+} __attribute__ ((packed));
+
+struct t3_rdma_init_attr {
+	u32 tid;
+	u32 qpid;
+	u32 pdid;
+	u32 scqid;
+	u32 rcqid;
+	u32 rq_addr;
+	u32 rq_size;
+	enum t3_mpa_attrs mpaattrs;
+	enum t3_qp_caps qpcaps;
+	u16 tcp_emss;
+	u32 ord;
+	u32 ird;
+	u64 qp_dma_addr;
+	u32 qp_dma_size;
+	u32 flags;
+};
+
+struct t3_rdma_init_wr {
+	struct fw_riwrh wrh;	/* 0 */
+	union t3_wrid wrid;	/* 1 */
+	__be32 qpid;		/* 2 */
+	__be32 pdid;
+	__be32 scqid;		/* 3 */
+	__be32 rcqid;
+	__be32 rq_addr;		/* 4 */
+	__be32 rq_size;
+	u8 mpaattrs;		/* 5 */
+	u8 qpcaps;
+	__be16 ulpdu_size;
+	__be32 flags;		/* bits 31-1 - reservered */
+				/* bit     0 - set if RECV posted */
+	__be32 ord;		/* 6 */
+	__be32 ird;
+	__be64 qp_dma_addr;	/* 7 */
+	__be32 qp_dma_size;	/* 8 */
+	u32 rsvd;
+};
+
+struct t3_genbit {
+	u64 flit[15];
+	__be64 genbit;
+};
+
+enum rdma_init_wr_flags {
+	RECVS_POSTED = 1,
+};
+
+union t3_wr {
+	struct t3_send_wr send;
+	struct t3_rdma_write_wr write;
+	struct t3_rdma_read_wr read;
+	struct t3_receive_wr recv;
+	struct t3_local_inv_wr local_inv;
+	struct t3_bind_mw_wr bind;
+	struct t3_bypass_wr bypass;
+	struct t3_rdma_init_wr init;
+	struct t3_modify_qp_wr qp_mod;
+	struct t3_genbit genbit;
+	u64 flit[16];
+};
+
+#define T3_SQ_CQE_FLIT	  13
+#define T3_SQ_COOKIE_FLIT 14
+
+#define T3_RQ_COOKIE_FLIT 13
+#define T3_RQ_CQE_FLIT	  14
+
+static inline enum t3_wr_opcode fw_riwrh_opcode(struct fw_riwrh *wqe)
+{
+	return G_FW_RIWR_OP(be32_to_cpu(wqe->op_seop_flags));
+}
+
+static inline void build_fw_riwrh(struct fw_riwrh *wqe, enum t3_wr_opcode op,
+				  enum t3_wr_flags flags, u8 genbit, u32 tid,
+				  u8 len)
+{
+	wqe->op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(op) |
+					 V_FW_RIWR_SOPEOP(M_FW_RIWR_SOPEOP) |
+					 V_FW_RIWR_FLAGS(flags));
+	wmb();
+	wqe->gen_tid_len = cpu_to_be32(V_FW_RIWR_GEN(genbit) |
+				       V_FW_RIWR_TID(tid) |
+				       V_FW_RIWR_LEN(len));
+	/* 2nd gen bit... */
+	((union t3_wr *)wqe)->genbit.genbit = cpu_to_be64(genbit);
+}
+
+/*
+ * T3 ULP2_TX commands
+ */
+enum t3_utx_mem_op {
+	T3_UTX_MEM_READ = 2,
+	T3_UTX_MEM_WRITE = 3
+};
+
+/* T3 MC7 RDMA TPT entry format */
+
+enum tpt_mem_type {
+	TPT_NON_SHARED_MR = 0x0,
+	TPT_SHARED_MR = 0x1,
+	TPT_MW = 0x2,
+	TPT_MW_RELAXED_PROTECTION = 0x3
+};
+
+enum tpt_addr_type {
+	TPT_ZBTO = 0,
+	TPT_VATO = 1
+};
+
+enum tpt_mem_perm {
+	TPT_LOCAL_READ = 0x8,
+	TPT_LOCAL_WRITE = 0x4,
+	TPT_REMOTE_READ = 0x2,
+	TPT_REMOTE_WRITE = 0x1
+};
+
+struct tpt_entry {
+	__be32 valid_stag_pdid;
+	__be32 flags_pagesize_qpid;
+
+	__be32 rsvd_pbl_addr;
+	__be32 len;
+	__be32 va_hi;
+	__be32 va_low_or_fbo;
+
+	__be32 rsvd_bind_cnt_or_pstag;
+	__be32 rsvd_pbl_size;
+};
+
+#define S_TPT_VALID		31
+#define V_TPT_VALID(x)		((x) << S_TPT_VALID)
+#define F_TPT_VALID		V_TPT_VALID(1U)
+
+#define S_TPT_STAG_KEY		23
+#define M_TPT_STAG_KEY		0xFF
+#define V_TPT_STAG_KEY(x)	((x) << S_TPT_STAG_KEY)
+#define G_TPT_STAG_KEY(x)	(((x) >> S_TPT_STAG_KEY) & M_TPT_STAG_KEY)
+
+#define S_TPT_STAG_STATE	22
+#define V_TPT_STAG_STATE(x)	((x) << S_TPT_STAG_STATE)
+#define F_TPT_STAG_STATE	V_TPT_STAG_STATE(1U)
+
+#define S_TPT_STAG_TYPE		20
+#define M_TPT_STAG_TYPE		0x3
+#define V_TPT_STAG_TYPE(x)	((x) << S_TPT_STAG_TYPE)
+#define G_TPT_STAG_TYPE(x)	(((x) >> S_TPT_STAG_TYPE) & M_TPT_STAG_TYPE)
+
+#define S_TPT_PDID		0
+#define M_TPT_PDID		0xFFFFF
+#define V_TPT_PDID(x)		((x) << S_TPT_PDID)
+#define G_TPT_PDID(x)		(((x) >> S_TPT_PDID) & M_TPT_PDID)
+
+#define S_TPT_PERM		28
+#define M_TPT_PERM		0xF
+#define V_TPT_PERM(x)		((x) << S_TPT_PERM)
+#define G_TPT_PERM(x)		(((x) >> S_TPT_PERM) & M_TPT_PERM)
+
+#define S_TPT_REM_INV_DIS	27
+#define V_TPT_REM_INV_DIS(x)	((x) << S_TPT_REM_INV_DIS)
+#define F_TPT_REM_INV_DIS	V_TPT_REM_INV_DIS(1U)
+
+#define S_TPT_ADDR_TYPE		26
+#define V_TPT_ADDR_TYPE(x)	((x) << S_TPT_ADDR_TYPE)
+#define F_TPT_ADDR_TYPE		V_TPT_ADDR_TYPE(1U)
+
+#define S_TPT_MW_BIND_ENABLE	25
+#define V_TPT_MW_BIND_ENABLE(x)	((x) << S_TPT_MW_BIND_ENABLE)
+#define F_TPT_MW_BIND_ENABLE    V_TPT_MW_BIND_ENABLE(1U)
+
+#define S_TPT_PAGE_SIZE		20
+#define M_TPT_PAGE_SIZE		0x1F
+#define V_TPT_PAGE_SIZE(x)	((x) << S_TPT_PAGE_SIZE)
+#define G_TPT_PAGE_SIZE(x)	(((x) >> S_TPT_PAGE_SIZE) & M_TPT_PAGE_SIZE)
+
+#define S_TPT_PBL_ADDR		0
+#define M_TPT_PBL_ADDR		0x1FFFFFFF
+#define V_TPT_PBL_ADDR(x)	((x) << S_TPT_PBL_ADDR)
+#define G_TPT_PBL_ADDR(x)       (((x) >> S_TPT_PBL_ADDR) & M_TPT_PBL_ADDR)
+
+#define S_TPT_QPID		0
+#define M_TPT_QPID		0xFFFFF
+#define V_TPT_QPID(x)		((x) << S_TPT_QPID)
+#define G_TPT_QPID(x)		(((x) >> S_TPT_QPID) & M_TPT_QPID)
+
+#define S_TPT_PSTAG		0
+#define M_TPT_PSTAG		0xFFFFFF
+#define V_TPT_PSTAG(x)		((x) << S_TPT_PSTAG)
+#define G_TPT_PSTAG(x)		(((x) >> S_TPT_PSTAG) & M_TPT_PSTAG)
+
+#define S_TPT_PBL_SIZE		0
+#define M_TPT_PBL_SIZE		0xFFFFF
+#define V_TPT_PBL_SIZE(x)	((x) << S_TPT_PBL_SIZE)
+#define G_TPT_PBL_SIZE(x)	(((x) >> S_TPT_PBL_SIZE) & M_TPT_PBL_SIZE)
+
+/*
+ * CQE defs
+ */
+struct t3_cqe {
+	__be32 header;
+	__be32 len;
+	union {
+		struct {
+			__be32 stag;
+			__be32 msn;
+		} rcqe;
+		struct {
+			u32 wrid_hi;
+			u32 wrid_low;
+		} scqe;
+	} u;
+};
+
+#define S_CQE_OOO	  31
+#define M_CQE_OOO	  0x1
+#define G_CQE_OOO(x)	  ((((x) >> S_CQE_OOO)) & M_CQE_OOO)
+#define V_CEQ_OOO(x)	  ((x)<<S_CQE_OOO)
+
+#define S_CQE_QPID        12
+#define M_CQE_QPID        0x7FFFF
+#define G_CQE_QPID(x)     ((((x) >> S_CQE_QPID)) & M_CQE_QPID)
+#define V_CQE_QPID(x)	  ((x)<<S_CQE_QPID)
+
+#define S_CQE_SWCQE       11
+#define M_CQE_SWCQE       0x1
+#define G_CQE_SWCQE(x)    ((((x) >> S_CQE_SWCQE)) & M_CQE_SWCQE)
+#define V_CQE_SWCQE(x)	  ((x)<<S_CQE_SWCQE)
+
+#define S_CQE_GENBIT      10
+#define M_CQE_GENBIT      0x1
+#define G_CQE_GENBIT(x)   (((x) >> S_CQE_GENBIT) & M_CQE_GENBIT)
+#define V_CQE_GENBIT(x)	  ((x)<<S_CQE_GENBIT)
+
+#define S_CQE_STATUS      5
+#define M_CQE_STATUS      0x1F
+#define G_CQE_STATUS(x)   ((((x) >> S_CQE_STATUS)) & M_CQE_STATUS)
+#define V_CQE_STATUS(x)   ((x)<<S_CQE_STATUS)
+
+#define S_CQE_TYPE        4
+#define M_CQE_TYPE        0x1
+#define G_CQE_TYPE(x)     ((((x) >> S_CQE_TYPE)) & M_CQE_TYPE)
+#define V_CQE_TYPE(x)     ((x)<<S_CQE_TYPE)
+
+#define S_CQE_OPCODE      0
+#define M_CQE_OPCODE      0xF
+#define G_CQE_OPCODE(x)   ((((x) >> S_CQE_OPCODE)) & M_CQE_OPCODE)
+#define V_CQE_OPCODE(x)   ((x)<<S_CQE_OPCODE)
+
+#define SW_CQE(x)         (G_CQE_SWCQE(be32_to_cpu((x).header)))
+#define CQE_OOO(x)        (G_CQE_OOO(be32_to_cpu((x).header)))
+#define CQE_QPID(x)       (G_CQE_QPID(be32_to_cpu((x).header)))
+#define CQE_GENBIT(x)     (G_CQE_GENBIT(be32_to_cpu((x).header)))
+#define CQE_TYPE(x)       (G_CQE_TYPE(be32_to_cpu((x).header)))
+#define SQ_TYPE(x)	  (CQE_TYPE((x)))
+#define RQ_TYPE(x)	  (!CQE_TYPE((x)))
+#define CQE_STATUS(x)     (G_CQE_STATUS(be32_to_cpu((x).header)))
+#define CQE_OPCODE(x)     (G_CQE_OPCODE(be32_to_cpu((x).header)))
+
+#define CQE_LEN(x)        (be32_to_cpu((x).len))
+
+/* used for RQ completion processing */
+#define CQE_WRID_STAG(x)  (be32_to_cpu((x).u.rcqe.stag))
+#define CQE_WRID_MSN(x)   (be32_to_cpu((x).u.rcqe.msn))
+
+/* used for SQ completion processing */
+#define CQE_WRID_SQ_WPTR(x)	((x).u.scqe.wrid_hi)
+#define CQE_WRID_WPTR(x)	((x).u.scqe.wrid_low)
+
+/* generic accessor macros */
+#define CQE_WRID_HI(x)		((x).u.scqe.wrid_hi)
+#define CQE_WRID_LOW(x)		((x).u.scqe.wrid_low)
+
+#define TPT_ERR_SUCCESS                     0x0
+#define TPT_ERR_STAG                        0x1	 /* STAG invalid: either the */
+						 /* STAG is offlimt, being 0, */
+						 /* or STAG_key mismatch */
+#define TPT_ERR_PDID                        0x2	 /* PDID mismatch */
+#define TPT_ERR_QPID                        0x3	 /* QPID mismatch */
+#define TPT_ERR_ACCESS                      0x4	 /* Invalid access right */
+#define TPT_ERR_WRAP                        0x5	 /* Wrap error */
+#define TPT_ERR_BOUND                       0x6	 /* base and bounds voilation */
+#define TPT_ERR_INVALIDATE_SHARED_MR        0x7	 /* attempt to invalidate a  */
+						 /* shared memory region */
+#define TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND 0x8	 /* attempt to invalidate a  */
+						 /* shared memory region */
+#define TPT_ERR_ECC                         0x9	 /* ECC error detected */
+#define TPT_ERR_ECC_PSTAG                   0xA	 /* ECC error detected when  */
+						 /* reading PSTAG for a MW  */
+						 /* Invalidate */
+#define TPT_ERR_PBL_ADDR_BOUND              0xB	 /* pbl addr out of bounds:  */
+						 /* software error */
+#define TPT_ERR_SWFLUSH			    0xC	 /* SW FLUSHED */
+#define TPT_ERR_CRC                         0x10 /* CRC error */
+#define TPT_ERR_MARKER                      0x11 /* Marker error */
+#define TPT_ERR_PDU_LEN_ERR                 0x12 /* invalid PDU length */
+#define TPT_ERR_OUT_OF_RQE                  0x13 /* out of RQE */
+#define TPT_ERR_DDP_VERSION                 0x14 /* wrong DDP version */
+#define TPT_ERR_RDMA_VERSION                0x15 /* wrong RDMA version */
+#define TPT_ERR_OPCODE                      0x16 /* invalid rdma opcode */
+#define TPT_ERR_DDP_QUEUE_NUM               0x17 /* invalid ddp queue number */
+#define TPT_ERR_MSN                         0x18 /* MSN error */
+#define TPT_ERR_TBIT                        0x19 /* tag bit not set correctly */
+#define TPT_ERR_MO                          0x1A /* MO not 0 for TERMINATE  */
+						 /* or READ_REQ */
+#define TPT_ERR_MSN_GAP                     0x1B
+#define TPT_ERR_MSN_RANGE                   0x1C
+#define TPT_ERR_IRD_OVERFLOW                0x1D
+#define TPT_ERR_RQE_ADDR_BOUND              0x1E /* RQE addr out of bounds:  */
+						 /* software error */
+#define TPT_ERR_INTERNAL_ERR                0x1F /* internal error (opcode  */
+						 /* mismatch) */
+
+struct t3_swsq {
+	__u64			wr_id;
+	struct t3_cqe		cqe;
+	__u32			sq_wptr;
+	__be32			read_len;
+	int			opcode;
+	int			complete;
+	int			signaled;
+};
+
+/*
+ * A T3 WQ implements both the SQ and RQ.
+ */
+struct t3_wq {
+	union t3_wr *queue;		/* DMA accessable memory */
+	dma_addr_t dma_addr;		/* DMA address for HW */
+	DECLARE_PCI_UNMAP_ADDR(mapping)	/* unmap kruft */
+	u32 error;			/* 1 once we go to ERROR */
+	u32 qpid;
+	u32 wptr;			/* idx to next available WR slot */
+	u32 size_log2;			/* total wq size */
+	struct t3_swsq *sq;		/* SW SQ */
+	struct t3_swsq *oldest_read;	/* tracks oldest pending read */
+	u32 sq_wptr;			/* sq_wptr - sq_rptr == count of */
+	u32 sq_rptr;			/* pending wrs */
+	u32 sq_size_log2;		/* sq size */
+	u64 *rq;			/* SW RQ (holds consumer wr_ids */
+	u32 rq_wptr;			/* rq_wptr - rq_rptr == count of */
+	u32 rq_rptr;			/* pending wrs */
+	u64 *rq_oldest_wr;		/* oldest wr on the SW RQ */
+	u32 rq_size_log2;		/* rq size */
+	u32 rq_addr;			/* rq adapter address */
+	void __iomem *doorbell;		/* kernel db */
+	u64 udb;			/* user db if any */
+};
+
+struct t3_cq {
+	u32 cqid;
+	u32 rptr;
+	u32 wptr;
+	u32 size_log2;
+	dma_addr_t dma_addr;
+	DECLARE_PCI_UNMAP_ADDR(mapping)
+	struct t3_cqe *queue;
+	struct t3_cqe *sw_queue;
+	u32 sw_rptr;
+	u32 sw_wptr;
+};
+
+#define CQ_VLD_ENTRY(ptr,size_log2,cqe) (Q_GENBIT(ptr,size_log2) == \
+					 CQE_GENBIT(*cqe))
+
+static inline void cxio_set_wq_in_error(struct t3_wq *wq)
+{
+	wq->queue->flit[13] = 1;
+}
+
+static inline struct t3_cqe *cxio_next_hw_cqe(struct t3_cq *cq)
+{
+	struct t3_cqe *cqe;
+
+	cqe = cq->queue + (Q_PTR2IDX(cq->rptr, cq->size_log2));
+	if (CQ_VLD_ENTRY(cq->rptr, cq->size_log2, cqe))
+		return cqe;
+	return NULL;
+}
+
+static inline struct t3_cqe *cxio_next_sw_cqe(struct t3_cq *cq)
+{
+	struct t3_cqe *cqe;
+
+	if (!Q_EMPTY(cq->sw_rptr, cq->sw_wptr)) {
+		cqe = cq->sw_queue + (Q_PTR2IDX(cq->sw_rptr, cq->size_log2));
+		return cqe;
+	}
+	return NULL;
+}
+
+static inline struct t3_cqe *cxio_next_cqe(struct t3_cq *cq)
+{
+	struct t3_cqe *cqe;
+
+	if (!Q_EMPTY(cq->sw_rptr, cq->sw_wptr)) {
+		cqe = cq->sw_queue + (Q_PTR2IDX(cq->sw_rptr, cq->size_log2));
+		return cqe;
+	}
+	cqe = cq->queue + (Q_PTR2IDX(cq->rptr, cq->size_log2));
+	if (CQ_VLD_ENTRY(cq->rptr, cq->size_log2, cqe))
+		return cqe;
+	return NULL;
+}
+
+#endif
diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c
new file mode 100644
index 0000000..0315c9d
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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/module.h>
+#include <linux/moduleparam.h>
+
+#include <rdma/ib_verbs.h>
+
+#include "cxgb3_offload.h"
+#include "iwch_provider.h"
+#include "iwch_user.h"
+#include "iwch.h"
+#include "iwch_cm.h"
+
+#define DRV_VERSION "1.1"
+
+MODULE_AUTHOR("Boyd Faulkner, Steve Wise");
+MODULE_DESCRIPTION("Chelsio T3 RDMA Driver");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRV_VERSION);
+
+cxgb3_cpl_handler_func t3c_handlers[NUM_CPL_CMDS];
+
+static void open_rnic_dev(struct t3cdev *);
+static void close_rnic_dev(struct t3cdev *);
+
+struct cxgb3_client t3c_client = {
+	.name = "iw_cxgb3",
+	.add = open_rnic_dev,
+	.remove = close_rnic_dev,
+	.handlers = t3c_handlers,
+	.redirect = iwch_ep_redirect
+};
+
+static LIST_HEAD(dev_list);
+static DEFINE_MUTEX(dev_mutex);
+
+static void rnic_init(struct iwch_dev *rnicp)
+{
+	PDBG("%s iwch_dev %p\n", __FUNCTION__,  rnicp);
+	idr_init(&rnicp->cqidr);
+	idr_init(&rnicp->qpidr);
+	idr_init(&rnicp->mmidr);
+	spin_lock_init(&rnicp->lock);
+
+	rnicp->attr.vendor_id = 0x168;
+	rnicp->attr.vendor_part_id = 7;
+	rnicp->attr.max_qps = T3_MAX_NUM_QP - 32;
+	rnicp->attr.max_wrs = (1UL << 24) - 1;
+	rnicp->attr.max_sge_per_wr = T3_MAX_SGE;
+	rnicp->attr.max_sge_per_rdma_write_wr = T3_MAX_SGE;
+	rnicp->attr.max_cqs = T3_MAX_NUM_CQ - 1;
+	rnicp->attr.max_cqes_per_cq = (1UL << 24) - 1;
+	rnicp->attr.max_mem_regs = cxio_num_stags(&rnicp->rdev);
+	rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE;
+	rnicp->attr.max_pds = T3_MAX_NUM_PD - 1;
+	rnicp->attr.mem_pgsizes_bitmask = 0x7FFF;	/* 4KB-128MB */
+	rnicp->attr.can_resize_wq = 0;
+	rnicp->attr.max_rdma_reads_per_qp = 8;
+	rnicp->attr.max_rdma_read_resources =
+	    rnicp->attr.max_rdma_reads_per_qp * rnicp->attr.max_qps;
+	rnicp->attr.max_rdma_read_qp_depth = 8;	/* IRD */
+	rnicp->attr.max_rdma_read_depth =
+	    rnicp->attr.max_rdma_read_qp_depth * rnicp->attr.max_qps;
+	rnicp->attr.rq_overflow_handled = 0;
+	rnicp->attr.can_modify_ird = 0;
+	rnicp->attr.can_modify_ord = 0;
+	rnicp->attr.max_mem_windows = rnicp->attr.max_mem_regs - 1;
+	rnicp->attr.stag0_value = 1;
+	rnicp->attr.zbva_support = 1;
+	rnicp->attr.local_invalidate_fence = 1;
+	rnicp->attr.cq_overflow_detection = 1;
+	return;
+}
+
+static void open_rnic_dev(struct t3cdev *tdev)
+{
+	struct iwch_dev *rnicp;
+	static int vers_printed;
+
+	PDBG("%s t3cdev %p\n", __FUNCTION__,  tdev);
+	if (!vers_printed++)
+		printk(KERN_INFO MOD "Chelsio T3 RDMA Driver - version %s\n",
+		       DRV_VERSION);
+	rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp));
+	if (!rnicp) {
+		printk(KERN_ERR MOD "Cannot allocate ib device\n");
+		return;
+	}
+	rnicp->rdev.ulp = rnicp;
+	rnicp->rdev.t3cdev_p = tdev;
+
+	mutex_lock(&dev_mutex);
+
+	if (cxio_rdev_open(&rnicp->rdev)) {
+		mutex_unlock(&dev_mutex);
+		printk(KERN_ERR MOD "Unable to open CXIO rdev\n");
+		ib_dealloc_device(&rnicp->ibdev);
+		return;
+	}
+
+	rnic_init(rnicp);
+
+	list_add_tail(&rnicp->entry, &dev_list);
+	mutex_unlock(&dev_mutex);
+
+	if (iwch_register_device(rnicp)) {
+		printk(KERN_ERR MOD "Unable to register device\n");
+		close_rnic_dev(tdev);
+	}
+	printk(KERN_INFO MOD "Initialized device %s\n",
+	       pci_name(rnicp->rdev.rnic_info.pdev));
+	return;
+}
+
+static void close_rnic_dev(struct t3cdev *tdev)
+{
+	struct iwch_dev *dev, *tmp;
+	PDBG("%s t3cdev %p\n", __FUNCTION__,  tdev);
+	mutex_lock(&dev_mutex);
+	list_for_each_entry_safe(dev, tmp, &dev_list, entry) {
+		if (dev->rdev.t3cdev_p == tdev) {
+			list_del(&dev->entry);
+			iwch_unregister_device(dev);
+			cxio_rdev_close(&dev->rdev);
+			idr_destroy(&dev->cqidr);
+			idr_destroy(&dev->qpidr);
+			idr_destroy(&dev->mmidr);
+			ib_dealloc_device(&dev->ibdev);
+			break;
+		}
+	}
+	mutex_unlock(&dev_mutex);
+}
+
+static int __init iwch_init_module(void)
+{
+	int err;
+
+	err = cxio_hal_init();
+	if (err)
+		return err;
+	err = iwch_cm_init();
+	if (err)
+		return err;
+	cxio_register_ev_cb(iwch_ev_dispatch);
+	cxgb3_register_client(&t3c_client);
+	return 0;
+}
+
+static void __exit iwch_exit_module(void)
+{
+	cxgb3_unregister_client(&t3c_client);
+	cxio_unregister_ev_cb(iwch_ev_dispatch);
+	iwch_cm_term();
+	cxio_hal_exit();
+}
+
+module_init(iwch_init_module);
+module_exit(iwch_exit_module);
diff --git a/drivers/infiniband/hw/cxgb3/iwch.h b/drivers/infiniband/hw/cxgb3/iwch.h
new file mode 100644
index 0000000..caf4e60
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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 __IWCH_H__
+#define __IWCH_H__
+
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/idr.h>
+
+#include <rdma/ib_verbs.h>
+
+#include "cxio_hal.h"
+#include "cxgb3_offload.h"
+
+struct iwch_pd;
+struct iwch_cq;
+struct iwch_qp;
+struct iwch_mr;
+
+struct iwch_rnic_attributes {
+	u32 vendor_id;
+	u32 vendor_part_id;
+	u32 max_qps;
+	u32 max_wrs;				/* Max for any SQ/RQ */
+	u32 max_sge_per_wr;
+	u32 max_sge_per_rdma_write_wr;	/* for RDMA Write WR */
+	u32 max_cqs;
+	u32 max_cqes_per_cq;
+	u32 max_mem_regs;
+	u32 max_phys_buf_entries;		/* for phys buf list */
+	u32 max_pds;
+
+	/*
+	 * The memory page sizes supported by this RNIC.
+	 * Bit position i in bitmap indicates page of
+	 * size (4k)^i.  Phys block list mode unsupported.
+	 */
+	u32 mem_pgsizes_bitmask;
+	u8 can_resize_wq;
+
+	/*
+	 * The maximum number of RDMA Reads that can be outstanding
+	 * per QP with this RNIC as the target.
+	 */
+	u32 max_rdma_reads_per_qp;
+
+	/*
+	 * The maximum number of resources used for RDMA Reads
+	 * by this RNIC with this RNIC as the target.
+	 */
+	u32 max_rdma_read_resources;
+
+	/*
+	 * The max depth per QP for initiation of RDMA Read
+	 * by this RNIC.
+	 */
+	u32 max_rdma_read_qp_depth;
+
+	/*
+	 * The maximum depth for initiation of RDMA Read
+	 * operations by this RNIC on all QPs
+	 */
+	u32 max_rdma_read_depth;
+	u8 rq_overflow_handled;
+	u32 can_modify_ird;
+	u32 can_modify_ord;
+	u32 max_mem_windows;
+	u32 stag0_value;
+	u8 zbva_support;
+	u8 local_invalidate_fence;
+	u32 cq_overflow_detection;
+};
+
+struct iwch_dev {
+	struct ib_device ibdev;
+	struct cxio_rdev rdev;
+	u32 device_cap_flags;
+	struct iwch_rnic_attributes attr;
+	struct idr cqidr;
+	struct idr qpidr;
+	struct idr mmidr;
+	spinlock_t lock;
+	struct list_head entry;
+};
+
+static inline struct iwch_dev *to_iwch_dev(struct ib_device *ibdev)
+{
+	return container_of(ibdev, struct iwch_dev, ibdev);
+}
+
+static inline int t3b_device(const struct iwch_dev *rhp)
+{
+	return rhp->rdev.t3cdev_p->type == T3B;
+}
+
+static inline int t3a_device(const struct iwch_dev *rhp)
+{
+	return rhp->rdev.t3cdev_p->type == T3A;
+}
+
+static inline struct iwch_cq *get_chp(struct iwch_dev *rhp, u32 cqid)
+{
+	return idr_find(&rhp->cqidr, cqid);
+}
+
+static inline struct iwch_qp *get_qhp(struct iwch_dev *rhp, u32 qpid)
+{
+	return idr_find(&rhp->qpidr, qpid);
+}
+
+static inline struct iwch_mr *get_mhp(struct iwch_dev *rhp, u32 mmid)
+{
+	return idr_find(&rhp->mmidr, mmid);
+}
+
+static inline int insert_handle(struct iwch_dev *rhp, struct idr *idr,
+				void *handle, u32 id)
+{
+	int ret;
+	u32 newid;
+
+	do {
+		if (!idr_pre_get(idr, GFP_KERNEL)) {
+			return -ENOMEM;
+		}
+		spin_lock_irq(&rhp->lock);
+		ret = idr_get_new_above(idr, handle, id, &newid);
+		BUG_ON(newid != id);
+		spin_unlock_irq(&rhp->lock);
+	} while (ret == -EAGAIN);
+
+	return ret;
+}
+
+static inline void remove_handle(struct iwch_dev *rhp, struct idr *idr, u32 id)
+{
+	spin_lock_irq(&rhp->lock);
+	idr_remove(idr, id);
+	spin_unlock_irq(&rhp->lock);
+}
+
+extern struct cxgb3_client t3c_client;
+extern cxgb3_cpl_handler_func t3c_handlers[NUM_CPL_CMDS];
+extern void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb);
+
+#endif
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
new file mode 100644
index 0000000..e5442e3
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -0,0 +1,2080 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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/module.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/timer.h>
+#include <linux/notifier.h>
+
+#include <net/neighbour.h>
+#include <net/netevent.h>
+#include <net/route.h>
+
+#include "tcb.h"
+#include "cxgb3_offload.h"
+#include "iwch.h"
+#include "iwch_provider.h"
+#include "iwch_cm.h"
+
+static char *states[] = {
+	"idle",
+	"listen",
+	"connecting",
+	"mpa_wait_req",
+	"mpa_req_sent",
+	"mpa_req_rcvd",
+	"mpa_rep_sent",
+	"fpdu_mode",
+	"aborting",
+	"closing",
+	"moribund",
+	"dead",
+	NULL,
+};
+
+static int ep_timeout_secs = 10;
+module_param(ep_timeout_secs, int, 0444);
+MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout "
+				   "in seconds (default=10)");
+
+static int mpa_rev = 1;
+module_param(mpa_rev, int, 0444);
+MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, "
+		 "1 is spec compliant. (default=1)");
+
+static int markers_enabled = 0;
+module_param(markers_enabled, int, 0444);
+MODULE_PARM_DESC(markers_enabled, "Enable MPA MARKERS (default(0)=disabled)");
+
+static int crc_enabled = 1;
+module_param(crc_enabled, int, 0444);
+MODULE_PARM_DESC(crc_enabled, "Enable MPA CRC (default(1)=enabled)");
+
+static int rcv_win = 256 * 1024;
+module_param(rcv_win, int, 0444);
+MODULE_PARM_DESC(rcv_win, "TCP receive window in bytes (default=256)");
+
+static int snd_win = 32 * 1024;
+module_param(snd_win, int, 0444);
+MODULE_PARM_DESC(snd_win, "TCP send window in bytes (default=32KB)");
+
+static unsigned int nocong = 0;
+module_param(nocong, uint, 0444);
+MODULE_PARM_DESC(nocong, "Turn off congestion control (default=0)");
+
+static unsigned int cong_flavor = 1;
+module_param(cong_flavor, uint, 0444);
+MODULE_PARM_DESC(cong_flavor, "TCP Congestion control flavor (default=1)");
+
+static void process_work(struct work_struct *work);
+static struct workqueue_struct *workq;
+static DECLARE_WORK(skb_work, process_work);
+
+static struct sk_buff_head rxq;
+static cxgb3_cpl_handler_func work_handlers[NUM_CPL_CMDS];
+
+static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp);
+static void ep_timeout(unsigned long arg);
+static void connect_reply_upcall(struct iwch_ep *ep, int status);
+
+static void start_ep_timer(struct iwch_ep *ep)
+{
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	if (timer_pending(&ep->timer)) {
+		PDBG("%s stopped / restarted timer ep %p\n", __FUNCTION__, ep);
+		del_timer_sync(&ep->timer);
+	} else
+		get_ep(&ep->com);
+	ep->timer.expires = jiffies + ep_timeout_secs * HZ;
+	ep->timer.data = (unsigned long)ep;
+	ep->timer.function = ep_timeout;
+	add_timer(&ep->timer);
+}
+
+static void stop_ep_timer(struct iwch_ep *ep)
+{
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	del_timer_sync(&ep->timer);
+	put_ep(&ep->com);
+}
+
+static void release_tid(struct t3cdev *tdev, u32 hwtid, struct sk_buff *skb)
+{
+	struct cpl_tid_release *req;
+
+	skb = get_skb(skb, sizeof *req, GFP_KERNEL);
+	if (!skb)
+		return;
+	req = (struct cpl_tid_release *) skb_put(skb, sizeof(*req));
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_TID_RELEASE, hwtid));
+	skb->priority = CPL_PRIORITY_SETUP;
+	tdev->send(tdev, skb);
+	return;
+}
+
+int iwch_quiesce_tid(struct iwch_ep *ep)
+{
+	struct cpl_set_tcb_field *req;
+	struct sk_buff *skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+
+	if (!skb)
+		return -ENOMEM;
+	req = (struct cpl_set_tcb_field *) skb_put(skb, sizeof(*req));
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	req->wr.wr_lo = htonl(V_WR_TID(ep->hwtid));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, ep->hwtid));
+	req->reply = 0;
+	req->cpu_idx = 0;
+	req->word = htons(W_TCB_RX_QUIESCE);
+	req->mask = cpu_to_be64(1ULL << S_TCB_RX_QUIESCE);
+	req->val = cpu_to_be64(1 << S_TCB_RX_QUIESCE);
+
+	skb->priority = CPL_PRIORITY_DATA;
+	ep->com.tdev->send(ep->com.tdev, skb);
+	return 0;
+}
+
+int iwch_resume_tid(struct iwch_ep *ep)
+{
+	struct cpl_set_tcb_field *req;
+	struct sk_buff *skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+
+	if (!skb)
+		return -ENOMEM;
+	req = (struct cpl_set_tcb_field *) skb_put(skb, sizeof(*req));
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	req->wr.wr_lo = htonl(V_WR_TID(ep->hwtid));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, ep->hwtid));
+	req->reply = 0;
+	req->cpu_idx = 0;
+	req->word = htons(W_TCB_RX_QUIESCE);
+	req->mask = cpu_to_be64(1ULL << S_TCB_RX_QUIESCE);
+	req->val = 0;
+
+	skb->priority = CPL_PRIORITY_DATA;
+	ep->com.tdev->send(ep->com.tdev, skb);
+	return 0;
+}
+
+static void set_emss(struct iwch_ep *ep, u16 opt)
+{
+	PDBG("%s ep %p opt %u\n", __FUNCTION__, ep, opt);
+	ep->emss = T3C_DATA(ep->com.tdev)->mtus[G_TCPOPT_MSS(opt)] - 40;
+	if (G_TCPOPT_TSTAMP(opt))
+		ep->emss -= 12;
+	if (ep->emss < 128)
+		ep->emss = 128;
+	PDBG("emss=%d\n", ep->emss);
+}
+
+static enum iwch_ep_state state_read(struct iwch_ep_common *epc)
+{
+	unsigned long flags;
+	enum iwch_ep_state state;
+
+	spin_lock_irqsave(&epc->lock, flags);
+	state = epc->state;
+	spin_unlock_irqrestore(&epc->lock, flags);
+	return state;
+}
+
+static inline void __state_set(struct iwch_ep_common *epc,
+			       enum iwch_ep_state new)
+{
+	epc->state = new;
+}
+
+static void state_set(struct iwch_ep_common *epc, enum iwch_ep_state new)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&epc->lock, flags);
+	PDBG("%s - %s -> %s\n", __FUNCTION__, states[epc->state], states[new]);
+	__state_set(epc, new);
+	spin_unlock_irqrestore(&epc->lock, flags);
+	return;
+}
+
+static void *alloc_ep(int size, gfp_t gfp)
+{
+	struct iwch_ep_common *epc;
+
+	epc = kmalloc(size, gfp);
+	if (epc) {
+		memset(epc, 0, size);
+		kref_init(&epc->kref);
+		spin_lock_init(&epc->lock);
+		init_waitqueue_head(&epc->waitq);
+	}
+	PDBG("%s alloc ep %p\n", __FUNCTION__, epc);
+	return epc;
+}
+
+void __free_ep(struct kref *kref)
+{
+	struct iwch_ep_common *epc;
+	epc = container_of(kref, struct iwch_ep_common, kref);
+	PDBG("%s ep %p state %s\n", __FUNCTION__, epc, states[state_read(epc)]);
+	kfree(epc);
+}
+
+static void release_ep_resources(struct iwch_ep *ep)
+{
+	PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, ep->hwtid);
+	cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid);
+	dst_release(ep->dst);
+	l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+	if (ep->com.tdev->type == T3B)
+		release_tid(ep->com.tdev, ep->hwtid, NULL);
+	put_ep(&ep->com);
+}
+
+static void process_work(struct work_struct *work)
+{
+	struct sk_buff *skb = NULL;
+	void *ep;
+	struct t3cdev *tdev;
+	int ret;
+
+	while ((skb = skb_dequeue(&rxq))) {
+		ep = *((void **) (skb->cb));
+		tdev = *((struct t3cdev **) (skb->cb + sizeof(void *)));
+		ret = work_handlers[G_OPCODE(ntohl((__force __be32)skb->csum))](tdev, skb, ep);
+		if (ret & CPL_RET_BUF_DONE)
+			kfree_skb(skb);
+
+		/*
+		 * ep was referenced in sched(), and is freed here.
+		 */
+		put_ep((struct iwch_ep_common *)ep);
+	}
+}
+
+static int status2errno(int status)
+{
+	switch (status) {
+	case CPL_ERR_NONE:
+		return 0;
+	case CPL_ERR_CONN_RESET:
+		return -ECONNRESET;
+	case CPL_ERR_ARP_MISS:
+		return -EHOSTUNREACH;
+	case CPL_ERR_CONN_TIMEDOUT:
+		return -ETIMEDOUT;
+	case CPL_ERR_TCAM_FULL:
+		return -ENOMEM;
+	case CPL_ERR_CONN_EXIST:
+		return -EADDRINUSE;
+	default:
+		return -EIO;
+	}
+}
+
+/*
+ * Try and reuse skbs already allocated...
+ */
+static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp)
+{
+	if (skb) {
+		BUG_ON(skb_cloned(skb));
+		skb_trim(skb, 0);
+		skb_get(skb);
+	} else {
+		skb = alloc_skb(len, gfp);
+	}
+	return skb;
+}
+
+static struct rtable *find_route(struct t3cdev *dev, __be32 local_ip,
+				 __be32 peer_ip, __be16 local_port,
+				 __be16 peer_port, u8 tos)
+{
+	struct rtable *rt;
+	struct flowi fl = {
+		.oif = 0,
+		.nl_u = {
+			 .ip4_u = {
+				   .daddr = peer_ip,
+				   .saddr = local_ip,
+				   .tos = tos}
+			 },
+		.proto = IPPROTO_TCP,
+		.uli_u = {
+			  .ports = {
+				    .sport = local_port,
+				    .dport = peer_port}
+			  }
+	};
+
+	if (ip_route_output_flow(&rt, &fl, NULL, 0))
+		return NULL;
+	return rt;
+}
+
+static unsigned int find_best_mtu(const struct t3c_data *d, unsigned short mtu)
+{
+	int i = 0;
+
+	while (i < d->nmtus - 1 && d->mtus[i + 1] <= mtu)
+		++i;
+	return i;
+}
+
+static void arp_failure_discard(struct t3cdev *dev, struct sk_buff *skb)
+{
+	PDBG("%s t3cdev %p\n", __FUNCTION__, dev);
+	kfree_skb(skb);
+}
+
+/*
+ * Handle an ARP failure for an active open.
+ */
+static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
+{
+	printk(KERN_ERR MOD "ARP failure duing connect\n");
+	kfree_skb(skb);
+}
+
+/*
+ * Handle an ARP failure for a CPL_ABORT_REQ.  Change it into a no RST variant
+ * and send it along.
+ */
+static void abort_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
+{
+	struct cpl_abort_req *req = cplhdr(skb);
+
+	PDBG("%s t3cdev %p\n", __FUNCTION__, dev);
+	req->cmd = CPL_ABORT_NO_RST;
+	cxgb3_ofld_send(dev, skb);
+}
+
+static int send_halfclose(struct iwch_ep *ep, gfp_t gfp)
+{
+	struct cpl_close_con_req *req;
+	struct sk_buff *skb;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	skb = get_skb(NULL, sizeof(*req), gfp);
+	if (!skb) {
+		printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	skb->priority = CPL_PRIORITY_DATA;
+	set_arp_failure_handler(skb, arp_failure_discard);
+	req = (struct cpl_close_con_req *) skb_put(skb, sizeof(*req));
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_CLOSE_CON));
+	req->wr.wr_lo = htonl(V_WR_TID(ep->hwtid));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, ep->hwtid));
+	l2t_send(ep->com.tdev, skb, ep->l2t);
+	return 0;
+}
+
+static int send_abort(struct iwch_ep *ep, struct sk_buff *skb, gfp_t gfp)
+{
+	struct cpl_abort_req *req;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	skb = get_skb(skb, sizeof(*req), gfp);
+	if (!skb) {
+		printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
+		       __FUNCTION__);
+		return -ENOMEM;
+	}
+	skb->priority = CPL_PRIORITY_DATA;
+	set_arp_failure_handler(skb, abort_arp_failure);
+	req = (struct cpl_abort_req *) skb_put(skb, sizeof(*req));
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ));
+	req->wr.wr_lo = htonl(V_WR_TID(ep->hwtid));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, ep->hwtid));
+	req->cmd = CPL_ABORT_SEND_RST;
+	l2t_send(ep->com.tdev, skb, ep->l2t);
+	return 0;
+}
+
+static int send_connect(struct iwch_ep *ep)
+{
+	struct cpl_act_open_req *req;
+	struct sk_buff *skb;
+	u32 opt0h, opt0l, opt2;
+	unsigned int mtu_idx;
+	int wscale;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+
+	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+	if (!skb) {
+		printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
+		       __FUNCTION__);
+		return -ENOMEM;
+	}
+	mtu_idx = find_best_mtu(T3C_DATA(ep->com.tdev), dst_mtu(ep->dst));
+	wscale = compute_wscale(rcv_win);
+	opt0h = V_NAGLE(0) |
+	    V_NO_CONG(nocong) |
+	    V_KEEP_ALIVE(1) |
+	    F_TCAM_BYPASS |
+	    V_WND_SCALE(wscale) |
+	    V_MSS_IDX(mtu_idx) |
+	    V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx);
+	opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10);
+	opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor);
+	skb->priority = CPL_PRIORITY_SETUP;
+	set_arp_failure_handler(skb, act_open_req_arp_failure);
+
+	req = (struct cpl_act_open_req *) skb_put(skb, sizeof(*req));
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, ep->atid));
+	req->local_port = ep->com.local_addr.sin_port;
+	req->peer_port = ep->com.remote_addr.sin_port;
+	req->local_ip = ep->com.local_addr.sin_addr.s_addr;
+	req->peer_ip = ep->com.remote_addr.sin_addr.s_addr;
+	req->opt0h = htonl(opt0h);
+	req->opt0l = htonl(opt0l);
+	req->params = 0;
+	req->opt2 = htonl(opt2);
+	l2t_send(ep->com.tdev, skb, ep->l2t);
+	return 0;
+}
+
+static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb)
+{
+	int mpalen;
+	struct tx_data_wr *req;
+	struct mpa_message *mpa;
+	int len;
+
+	PDBG("%s ep %p pd_len %d\n", __FUNCTION__, ep, ep->plen);
+
+	BUG_ON(skb_cloned(skb));
+
+	mpalen = sizeof(*mpa) + ep->plen;
+	if (skb->data + mpalen + sizeof(*req) > skb->end) {
+		kfree_skb(skb);
+		skb=alloc_skb(mpalen + sizeof(*req), GFP_KERNEL);
+		if (!skb) {
+			connect_reply_upcall(ep, -ENOMEM);
+			return;
+		}
+	}
+	skb_trim(skb, 0);
+	skb_reserve(skb, sizeof(*req));
+	skb_put(skb, mpalen);
+	skb->priority = CPL_PRIORITY_DATA;
+	mpa = (struct mpa_message *) skb->data;
+	memset(mpa, 0, sizeof(*mpa));
+	memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key));
+	mpa->flags = (crc_enabled ? MPA_CRC : 0) |
+		     (markers_enabled ? MPA_MARKERS : 0);
+	mpa->private_data_size = htons(ep->plen);
+	mpa->revision = mpa_rev;
+
+	if (ep->plen)
+		memcpy(mpa->private_data, ep->mpa_pkt + sizeof(*mpa), ep->plen);
+
+	/*
+	 * Reference the mpa skb.  This ensures the data area
+	 * will remain in memory until the hw acks the tx.
+	 * Function tx_ack() will deref it.
+	 */
+	skb_get(skb);
+	set_arp_failure_handler(skb, arp_failure_discard);
+	skb->h.raw = skb->data;
+	len = skb->len;
+	req = (struct tx_data_wr *) skb_push(skb, sizeof(*req));
+	req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
+	req->wr_lo = htonl(V_WR_TID(ep->hwtid));
+	req->len = htonl(len);
+	req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
+			   V_TX_SNDBUF(snd_win>>15));
+	req->flags = htonl(F_TX_IMM_ACK|F_TX_INIT);
+	req->sndseq = htonl(ep->snd_seq);
+	BUG_ON(ep->mpa_skb);
+	ep->mpa_skb = skb;
+	l2t_send(ep->com.tdev, skb, ep->l2t);
+	start_ep_timer(ep);
+	state_set(&ep->com, MPA_REQ_SENT);
+	return;
+}
+
+static int send_mpa_reject(struct iwch_ep *ep, const void *pdata, u8 plen)
+{
+	int mpalen;
+	struct tx_data_wr *req;
+	struct mpa_message *mpa;
+	struct sk_buff *skb;
+
+	PDBG("%s ep %p plen %d\n", __FUNCTION__, ep, plen);
+
+	mpalen = sizeof(*mpa) + plen;
+
+	skb = get_skb(NULL, mpalen + sizeof(*req), GFP_KERNEL);
+	if (!skb) {
+		printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	skb_reserve(skb, sizeof(*req));
+	mpa = (struct mpa_message *) skb_put(skb, mpalen);
+	memset(mpa, 0, sizeof(*mpa));
+	memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
+	mpa->flags = MPA_REJECT;
+	mpa->revision = mpa_rev;
+	mpa->private_data_size = htons(plen);
+	if (plen)
+		memcpy(mpa->private_data, pdata, plen);
+
+	/*
+	 * Reference the mpa skb again.  This ensures the data area
+	 * will remain in memory until the hw acks the tx.
+	 * Function tx_ack() will deref it.
+	 */
+	skb_get(skb);
+	skb->priority = CPL_PRIORITY_DATA;
+	set_arp_failure_handler(skb, arp_failure_discard);
+	skb->h.raw = skb->data;
+	req = (struct tx_data_wr *) skb_push(skb, sizeof(*req));
+	req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
+	req->wr_lo = htonl(V_WR_TID(ep->hwtid));
+	req->len = htonl(mpalen);
+	req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
+			   V_TX_SNDBUF(snd_win>>15));
+	req->flags = htonl(F_TX_IMM_ACK|F_TX_INIT);
+	req->sndseq = htonl(ep->snd_seq);
+	BUG_ON(ep->mpa_skb);
+	ep->mpa_skb = skb;
+	l2t_send(ep->com.tdev, skb, ep->l2t);
+	return 0;
+}
+
+static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen)
+{
+	int mpalen;
+	struct tx_data_wr *req;
+	struct mpa_message *mpa;
+	int len;
+	struct sk_buff *skb;
+
+	PDBG("%s ep %p plen %d\n", __FUNCTION__, ep, plen);
+
+	mpalen = sizeof(*mpa) + plen;
+
+	skb = get_skb(NULL, mpalen + sizeof(*req), GFP_KERNEL);
+	if (!skb) {
+		printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	skb->priority = CPL_PRIORITY_DATA;
+	skb_reserve(skb, sizeof(*req));
+	mpa = (struct mpa_message *) skb_put(skb, mpalen);
+	memset(mpa, 0, sizeof(*mpa));
+	memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
+	mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) |
+		     (markers_enabled ? MPA_MARKERS : 0);
+	mpa->revision = mpa_rev;
+	mpa->private_data_size = htons(plen);
+	if (plen)
+		memcpy(mpa->private_data, pdata, plen);
+
+	/*
+	 * Reference the mpa skb.  This ensures the data area
+	 * will remain in memory until the hw acks the tx.
+	 * Function tx_ack() will deref it.
+	 */
+	skb_get(skb);
+	set_arp_failure_handler(skb, arp_failure_discard);
+	skb->h.raw = skb->data;
+	len = skb->len;
+	req = (struct tx_data_wr *) skb_push(skb, sizeof(*req));
+	req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
+	req->wr_lo = htonl(V_WR_TID(ep->hwtid));
+	req->len = htonl(len);
+	req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
+			   V_TX_SNDBUF(snd_win>>15));
+	req->flags = htonl(F_TX_MORE | F_TX_IMM_ACK | F_TX_INIT);
+	req->sndseq = htonl(ep->snd_seq);
+	ep->mpa_skb = skb;
+	state_set(&ep->com, MPA_REP_SENT);
+	l2t_send(ep->com.tdev, skb, ep->l2t);
+	return 0;
+}
+
+static int act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep *ep = ctx;
+	struct cpl_act_establish *req = cplhdr(skb);
+	unsigned int tid = GET_TID(req);
+
+	PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, tid);
+
+	dst_confirm(ep->dst);
+
+	/* setup the hwtid for this connection */
+	ep->hwtid = tid;
+	cxgb3_insert_tid(ep->com.tdev, &t3c_client, ep, tid);
+
+	ep->snd_seq = ntohl(req->snd_isn);
+
+	set_emss(ep, ntohs(req->tcp_opt));
+
+	/* dealloc the atid */
+	cxgb3_free_atid(ep->com.tdev, ep->atid);
+
+	/* start MPA negotiation */
+	send_mpa_req(ep, skb);
+
+	return 0;
+}
+
+static void abort_connection(struct iwch_ep *ep, struct sk_buff *skb, gfp_t gfp)
+{
+	PDBG("%s ep %p\n", __FILE__, ep);
+	state_set(&ep->com, ABORTING);
+	send_abort(ep, skb, gfp);
+}
+
+static void close_complete_upcall(struct iwch_ep *ep)
+{
+	struct iw_cm_event event;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	memset(&event, 0, sizeof(event));
+	event.event = IW_CM_EVENT_CLOSE;
+	if (ep->com.cm_id) {
+		PDBG("close complete delivered ep %p cm_id %p tid %d\n",
+		     ep, ep->com.cm_id, ep->hwtid);
+		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+		ep->com.cm_id->rem_ref(ep->com.cm_id);
+		ep->com.cm_id = NULL;
+		ep->com.qp = NULL;
+	}
+}
+
+static void peer_close_upcall(struct iwch_ep *ep)
+{
+	struct iw_cm_event event;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	memset(&event, 0, sizeof(event));
+	event.event = IW_CM_EVENT_DISCONNECT;
+	if (ep->com.cm_id) {
+		PDBG("peer close delivered ep %p cm_id %p tid %d\n",
+		     ep, ep->com.cm_id, ep->hwtid);
+		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+	}
+}
+
+static void peer_abort_upcall(struct iwch_ep *ep)
+{
+	struct iw_cm_event event;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	memset(&event, 0, sizeof(event));
+	event.event = IW_CM_EVENT_CLOSE;
+	event.status = -ECONNRESET;
+	if (ep->com.cm_id) {
+		PDBG("abort delivered ep %p cm_id %p tid %d\n", ep,
+		     ep->com.cm_id, ep->hwtid);
+		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+		ep->com.cm_id->rem_ref(ep->com.cm_id);
+		ep->com.cm_id = NULL;
+		ep->com.qp = NULL;
+	}
+}
+
+static void connect_reply_upcall(struct iwch_ep *ep, int status)
+{
+	struct iw_cm_event event;
+
+	PDBG("%s ep %p status %d\n", __FUNCTION__, ep, status);
+	memset(&event, 0, sizeof(event));
+	event.event = IW_CM_EVENT_CONNECT_REPLY;
+	event.status = status;
+	event.local_addr = ep->com.local_addr;
+	event.remote_addr = ep->com.remote_addr;
+
+	if ((status == 0) || (status == -ECONNREFUSED)) {
+		event.private_data_len = ep->plen;
+		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+	}
+	if (ep->com.cm_id) {
+		PDBG("%s ep %p tid %d status %d\n", __FUNCTION__, ep,
+		     ep->hwtid, status);
+		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+	}
+	if (status < 0) {
+		ep->com.cm_id->rem_ref(ep->com.cm_id);
+		ep->com.cm_id = NULL;
+		ep->com.qp = NULL;
+	}
+}
+
+static void connect_request_upcall(struct iwch_ep *ep)
+{
+	struct iw_cm_event event;
+
+	PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, ep->hwtid);
+	memset(&event, 0, sizeof(event));
+	event.event = IW_CM_EVENT_CONNECT_REQUEST;
+	event.local_addr = ep->com.local_addr;
+	event.remote_addr = ep->com.remote_addr;
+	event.private_data_len = ep->plen;
+	event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+	event.provider_data = ep;
+	if (state_read(&ep->parent_ep->com) != DEAD)
+		ep->parent_ep->com.cm_id->event_handler(
+						ep->parent_ep->com.cm_id,
+						&event);
+	put_ep(&ep->parent_ep->com);
+	ep->parent_ep = NULL;
+}
+
+static void established_upcall(struct iwch_ep *ep)
+{
+	struct iw_cm_event event;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	memset(&event, 0, sizeof(event));
+	event.event = IW_CM_EVENT_ESTABLISHED;
+	if (ep->com.cm_id) {
+		PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, ep->hwtid);
+		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+	}
+}
+
+static int update_rx_credits(struct iwch_ep *ep, u32 credits)
+{
+	struct cpl_rx_data_ack *req;
+	struct sk_buff *skb;
+
+	PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
+	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+	if (!skb) {
+		printk(KERN_ERR MOD "update_rx_credits - cannot alloc skb!\n");
+		return 0;
+	}
+
+	req = (struct cpl_rx_data_ack *) skb_put(skb, sizeof(*req));
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, ep->hwtid));
+	req->credit_dack = htonl(V_RX_CREDITS(credits) | V_RX_FORCE_ACK(1));
+	skb->priority = CPL_PRIORITY_ACK;
+	ep->com.tdev->send(ep->com.tdev, skb);
+	return credits;
+}
+
+static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
+{
+	struct mpa_message *mpa;
+	u16 plen;
+	struct iwch_qp_attributes attrs;
+	enum iwch_qp_attr_mask mask;
+	int err;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+
+	/*
+	 * Stop mpa timer.  If it expired, then the state has
+	 * changed and we bail since ep_timeout already aborted
+	 * the connection.
+	 */
+	stop_ep_timer(ep);
+	if (state_read(&ep->com) != MPA_REQ_SENT)
+		return;
+
+	/*
+	 * If we get more than the supported amount of private data
+	 * then we must fail this connection.
+	 */
+	if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) {
+		err = -EINVAL;
+		goto err;
+	}
+
+	/*
+	 * copy the new data into our accumulation buffer.
+	 */
+	memcpy(&(ep->mpa_pkt[ep->mpa_pkt_len]), skb->data, skb->len);
+	ep->mpa_pkt_len += skb->len;
+
+	/*
+	 * if we don't even have the mpa message, then bail.
+	 */
+	if (ep->mpa_pkt_len < sizeof(*mpa))
+		return;
+	mpa = (struct mpa_message *) ep->mpa_pkt;
+
+	/* Validate MPA header. */
+	if (mpa->revision != mpa_rev) {
+		err = -EPROTO;
+		goto err;
+	}
+	if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) {
+		err = -EPROTO;
+		goto err;
+	}
+
+	plen = ntohs(mpa->private_data_size);
+
+	/*
+	 * Fail if there's too much private data.
+	 */
+	if (plen > MPA_MAX_PRIVATE_DATA) {
+		err = -EPROTO;
+		goto err;
+	}
+
+	/*
+	 * If plen does not account for pkt size
+	 */
+	if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) {
+		err = -EPROTO;
+		goto err;
+	}
+
+	ep->plen = (u8) plen;
+
+	/*
+	 * If we don't have all the pdata yet, then bail.
+	 * We'll continue process when more data arrives.
+	 */
+	if (ep->mpa_pkt_len < (sizeof(*mpa) + plen))
+		return;
+
+	if (mpa->flags & MPA_REJECT) {
+		err = -ECONNREFUSED;
+		goto err;
+	}
+
+	/*
+	 * If we get here we have accumulated the entire mpa
+	 * start reply message including private data. And
+	 * the MPA header is valid.
+	 */
+	state_set(&ep->com, FPDU_MODE);
+	ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
+	ep->mpa_attr.recv_marker_enabled = markers_enabled;
+	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
+	ep->mpa_attr.version = mpa_rev;
+	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
+	     "xmit_marker_enabled=%d, version=%d\n", __FUNCTION__,
+	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
+	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+
+	attrs.mpa_attr = ep->mpa_attr;
+	attrs.max_ird = ep->ird;
+	attrs.max_ord = ep->ord;
+	attrs.llp_stream_handle = ep;
+	attrs.next_state = IWCH_QP_STATE_RTS;
+
+	mask = IWCH_QP_ATTR_NEXT_STATE |
+	    IWCH_QP_ATTR_LLP_STREAM_HANDLE | IWCH_QP_ATTR_MPA_ATTR |
+	    IWCH_QP_ATTR_MAX_IRD | IWCH_QP_ATTR_MAX_ORD;
+
+	/* bind QP and TID with INIT_WR */
+	err = iwch_modify_qp(ep->com.qp->rhp,
+			     ep->com.qp, mask, &attrs, 1);
+	if (!err)
+		goto out;
+err:
+	abort_connection(ep, skb, GFP_KERNEL);
+out:
+	connect_reply_upcall(ep, err);
+	return;
+}
+
+static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+{
+	struct mpa_message *mpa;
+	u16 plen;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+
+	/*
+	 * Stop mpa timer.  If it expired, then the state has
+	 * changed and we bail since ep_timeout already aborted
+	 * the connection.
+	 */
+	stop_ep_timer(ep);
+	if (state_read(&ep->com) != MPA_REQ_WAIT)
+		return;
+
+	/*
+	 * If we get more than the supported amount of private data
+	 * then we must fail this connection.
+	 */
+	if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) {
+		abort_connection(ep, skb, GFP_KERNEL);
+		return;
+	}
+
+	PDBG("%s enter (%s line %u)\n", __FUNCTION__, __FILE__, __LINE__);
+
+	/*
+	 * Copy the new data into our accumulation buffer.
+	 */
+	memcpy(&(ep->mpa_pkt[ep->mpa_pkt_len]), skb->data, skb->len);
+	ep->mpa_pkt_len += skb->len;
+
+	/*
+	 * If we don't even have the mpa message, then bail.
+	 * We'll continue process when more data arrives.
+	 */
+	if (ep->mpa_pkt_len < sizeof(*mpa))
+		return;
+	PDBG("%s enter (%s line %u)\n", __FUNCTION__, __FILE__, __LINE__);
+	mpa = (struct mpa_message *) ep->mpa_pkt;
+
+	/*
+	 * Validate MPA Header.
+	 */
+	if (mpa->revision != mpa_rev) {
+		abort_connection(ep, skb, GFP_KERNEL);
+		return;
+	}
+
+	if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) {
+		abort_connection(ep, skb, GFP_KERNEL);
+		return;
+	}
+
+	plen = ntohs(mpa->private_data_size);
+
+	/*
+	 * Fail if there's too much private data.
+	 */
+	if (plen > MPA_MAX_PRIVATE_DATA) {
+		abort_connection(ep, skb, GFP_KERNEL);
+		return;
+	}
+
+	/*
+	 * If plen does not account for pkt size
+	 */
+	if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) {
+		abort_connection(ep, skb, GFP_KERNEL);
+		return;
+	}
+	ep->plen = (u8) plen;
+
+	/*
+	 * If we don't have all the pdata yet, then bail.
+	 */
+	if (ep->mpa_pkt_len < (sizeof(*mpa) + plen))
+		return;
+
+	/*
+	 * If we get here we have accumulated the entire mpa
+	 * start reply message including private data.
+	 */
+	ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
+	ep->mpa_attr.recv_marker_enabled = markers_enabled;
+	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
+	ep->mpa_attr.version = mpa_rev;
+	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
+	     "xmit_marker_enabled=%d, version=%d\n", __FUNCTION__,
+	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
+	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+
+	state_set(&ep->com, MPA_REQ_RCVD);
+
+	/* drive upcall */
+	connect_request_upcall(ep);
+	return;
+}
+
+static int rx_data(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep *ep = ctx;
+	struct cpl_rx_data *hdr = cplhdr(skb);
+	unsigned int dlen = ntohs(hdr->len);
+
+	PDBG("%s ep %p dlen %u\n", __FUNCTION__, ep, dlen);
+
+	skb_pull(skb, sizeof(*hdr));
+	skb_trim(skb, dlen);
+
+	switch (state_read(&ep->com)) {
+	case MPA_REQ_SENT:
+		process_mpa_reply(ep, skb);
+		break;
+	case MPA_REQ_WAIT:
+		process_mpa_request(ep, skb);
+		break;
+	case MPA_REP_SENT:
+		break;
+	default:
+		printk(KERN_ERR MOD "%s Unexpected streaming data."
+		       " ep %p state %d tid %d\n",
+		       __FUNCTION__, ep, state_read(&ep->com), ep->hwtid);
+
+		/*
+		 * The ep will timeout and inform the ULP of the failure.
+		 * See ep_timeout().
+		 */
+		break;
+	}
+
+	/* update RX credits */
+	update_rx_credits(ep, dlen);
+
+	return CPL_RET_BUF_DONE;
+}
+
+/*
+ * Upcall from the adapter indicating data has been transmitted.
+ * For us its just the single MPA request or reply.  We can now free
+ * the skb holding the mpa message.
+ */
+static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep *ep = ctx;
+	struct cpl_wr_ack *hdr = cplhdr(skb);
+	unsigned int credits = ntohs(hdr->credits);
+	enum iwch_qp_attr_mask  mask;
+
+	PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
+
+	if (credits == 0)
+		return CPL_RET_BUF_DONE;
+	BUG_ON(credits != 1);
+	BUG_ON(ep->mpa_skb == NULL);
+	kfree_skb(ep->mpa_skb);
+	ep->mpa_skb = NULL;
+	dst_confirm(ep->dst);
+	if (state_read(&ep->com) == MPA_REP_SENT) {
+		struct iwch_qp_attributes attrs;
+
+		/* bind QP to EP and move to RTS */
+		attrs.mpa_attr = ep->mpa_attr;
+		attrs.max_ird = ep->ord;
+		attrs.max_ord = ep->ord;
+		attrs.llp_stream_handle = ep;
+		attrs.next_state = IWCH_QP_STATE_RTS;
+
+		/* bind QP and TID with INIT_WR */
+		mask = IWCH_QP_ATTR_NEXT_STATE |
+				     IWCH_QP_ATTR_LLP_STREAM_HANDLE |
+				     IWCH_QP_ATTR_MPA_ATTR |
+				     IWCH_QP_ATTR_MAX_IRD |
+				     IWCH_QP_ATTR_MAX_ORD;
+
+		ep->com.rpl_err = iwch_modify_qp(ep->com.qp->rhp,
+				     ep->com.qp, mask, &attrs, 1);
+
+		if (!ep->com.rpl_err) {
+			state_set(&ep->com, FPDU_MODE);
+			established_upcall(ep);
+		}
+
+		ep->com.rpl_done = 1;
+		PDBG("waking up ep %p\n", ep);
+		wake_up(&ep->com.waitq);
+	}
+	return CPL_RET_BUF_DONE;
+}
+
+static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep *ep = ctx;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+
+	close_complete_upcall(ep);
+	state_set(&ep->com, DEAD);
+	release_ep_resources(ep);
+	return CPL_RET_BUF_DONE;
+}
+
+static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep *ep = ctx;
+	struct cpl_act_open_rpl *rpl = cplhdr(skb);
+
+	PDBG("%s ep %p status %u errno %d\n", __FUNCTION__, ep, rpl->status,
+	     status2errno(rpl->status));
+	connect_reply_upcall(ep, status2errno(rpl->status));
+	state_set(&ep->com, DEAD);
+	if (ep->com.tdev->type == T3B)
+		release_tid(ep->com.tdev, GET_TID(rpl), NULL);
+	cxgb3_free_atid(ep->com.tdev, ep->atid);
+	dst_release(ep->dst);
+	l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+	put_ep(&ep->com);
+	return CPL_RET_BUF_DONE;
+}
+
+static int listen_start(struct iwch_listen_ep *ep)
+{
+	struct sk_buff *skb;
+	struct cpl_pass_open_req *req;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+	if (!skb) {
+		printk(KERN_ERR MOD "t3c_listen_start failed to alloc skb!\n");
+		return -ENOMEM;
+	}
+
+	req = (struct cpl_pass_open_req *) skb_put(skb, sizeof(*req));
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, ep->stid));
+	req->local_port = ep->com.local_addr.sin_port;
+	req->local_ip = ep->com.local_addr.sin_addr.s_addr;
+	req->peer_port = 0;
+	req->peer_ip = 0;
+	req->peer_netmask = 0;
+	req->opt0h = htonl(F_DELACK | F_TCAM_BYPASS);
+	req->opt0l = htonl(V_RCV_BUFSIZ(rcv_win>>10));
+	req->opt1 = htonl(V_CONN_POLICY(CPL_CONN_POLICY_ASK));
+
+	skb->priority = 1;
+	ep->com.tdev->send(ep->com.tdev, skb);
+	return 0;
+}
+
+static int pass_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_listen_ep *ep = ctx;
+	struct cpl_pass_open_rpl *rpl = cplhdr(skb);
+
+	PDBG("%s ep %p status %d error %d\n", __FUNCTION__, ep,
+	     rpl->status, status2errno(rpl->status));
+	ep->com.rpl_err = status2errno(rpl->status);
+	ep->com.rpl_done = 1;
+	wake_up(&ep->com.waitq);
+
+	return CPL_RET_BUF_DONE;
+}
+
+static int listen_stop(struct iwch_listen_ep *ep)
+{
+	struct sk_buff *skb;
+	struct cpl_close_listserv_req *req;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+	if (!skb) {
+		printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	req = (struct cpl_close_listserv_req *) skb_put(skb, sizeof(*req));
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_LISTSRV_REQ, ep->stid));
+	skb->priority = 1;
+	ep->com.tdev->send(ep->com.tdev, skb);
+	return 0;
+}
+
+static int close_listsrv_rpl(struct t3cdev *tdev, struct sk_buff *skb,
+			     void *ctx)
+{
+	struct iwch_listen_ep *ep = ctx;
+	struct cpl_close_listserv_rpl *rpl = cplhdr(skb);
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	ep->com.rpl_err = status2errno(rpl->status);
+	ep->com.rpl_done = 1;
+	wake_up(&ep->com.waitq);
+	return CPL_RET_BUF_DONE;
+}
+
+static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb)
+{
+	struct cpl_pass_accept_rpl *rpl;
+	unsigned int mtu_idx;
+	u32 opt0h, opt0l, opt2;
+	int wscale;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	BUG_ON(skb_cloned(skb));
+	skb_trim(skb, sizeof(*rpl));
+	skb_get(skb);
+	mtu_idx = find_best_mtu(T3C_DATA(ep->com.tdev), dst_mtu(ep->dst));
+	wscale = compute_wscale(rcv_win);
+	opt0h = V_NAGLE(0) |
+	    V_NO_CONG(nocong) |
+	    V_KEEP_ALIVE(1) |
+	    F_TCAM_BYPASS |
+	    V_WND_SCALE(wscale) |
+	    V_MSS_IDX(mtu_idx) |
+	    V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx);
+	opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10);
+	opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor);
+
+	rpl = cplhdr(skb);
+	rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, ep->hwtid));
+	rpl->peer_ip = peer_ip;
+	rpl->opt0h = htonl(opt0h);
+	rpl->opt0l_status = htonl(opt0l | CPL_PASS_OPEN_ACCEPT);
+	rpl->opt2 = htonl(opt2);
+	rpl->rsvd = rpl->opt2;	/* workaround for HW bug */
+	skb->priority = CPL_PRIORITY_SETUP;
+	l2t_send(ep->com.tdev, skb, ep->l2t);
+
+	return;
+}
+
+static void reject_cr(struct t3cdev *tdev, u32 hwtid, __be32 peer_ip,
+		      struct sk_buff *skb)
+{
+	PDBG("%s t3cdev %p tid %u peer_ip %x\n", __FUNCTION__, tdev, hwtid,
+	     peer_ip);
+	BUG_ON(skb_cloned(skb));
+	skb_trim(skb, sizeof(struct cpl_tid_release));
+	skb_get(skb);
+
+	if (tdev->type == T3B)
+		release_tid(tdev, hwtid, skb);
+	else {
+		struct cpl_pass_accept_rpl *rpl;
+
+		rpl = cplhdr(skb);
+		skb->priority = CPL_PRIORITY_SETUP;
+		rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+		OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL,
+						      hwtid));
+		rpl->peer_ip = peer_ip;
+		rpl->opt0h = htonl(F_TCAM_BYPASS);
+		rpl->opt0l_status = htonl(CPL_PASS_OPEN_REJECT);
+		rpl->opt2 = 0;
+		rpl->rsvd = rpl->opt2;
+		tdev->send(tdev, skb);
+	}
+}
+
+static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep *child_ep, *parent_ep = ctx;
+	struct cpl_pass_accept_req *req = cplhdr(skb);
+	unsigned int hwtid = GET_TID(req);
+	struct dst_entry *dst;
+	struct l2t_entry *l2t;
+	struct rtable *rt;
+	struct iff_mac tim;
+
+	PDBG("%s parent ep %p tid %u\n", __FUNCTION__, parent_ep, hwtid);
+
+	if (state_read(&parent_ep->com) != LISTEN) {
+		printk(KERN_ERR "%s - listening ep not in LISTEN\n",
+		       __FUNCTION__);
+		goto reject;
+	}
+
+	/*
+	 * Find the netdev for this connection request.
+	 */
+	tim.mac_addr = req->dst_mac;
+	tim.vlan_tag = ntohs(req->vlan_tag);
+	if (tdev->ctl(tdev, GET_IFF_FROM_MAC, &tim) < 0 || !tim.dev) {
+		printk(KERN_ERR
+			"%s bad dst mac %02x %02x %02x %02x %02x %02x\n",
+			__FUNCTION__,
+			req->dst_mac[0],
+			req->dst_mac[1],
+			req->dst_mac[2],
+			req->dst_mac[3],
+			req->dst_mac[4],
+			req->dst_mac[5]);
+		goto reject;
+	}
+
+	/* Find output route */
+	rt = find_route(tdev,
+			req->local_ip,
+			req->peer_ip,
+			req->local_port,
+			req->peer_port, G_PASS_OPEN_TOS(ntohl(req->tos_tid)));
+	if (!rt) {
+		printk(KERN_ERR MOD "%s - failed to find dst entry!\n",
+		       __FUNCTION__);
+		goto reject;
+	}
+	dst = &rt->u.dst;
+	l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
+	if (!l2t) {
+		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
+		       __FUNCTION__);
+		dst_release(dst);
+		goto reject;
+	}
+	child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL);
+	if (!child_ep) {
+		printk(KERN_ERR MOD "%s - failed to allocate ep entry!\n",
+		       __FUNCTION__);
+		l2t_release(L2DATA(tdev), l2t);
+		dst_release(dst);
+		goto reject;
+	}
+	state_set(&child_ep->com, CONNECTING);
+	child_ep->com.tdev = tdev;
+	child_ep->com.cm_id = NULL;
+	child_ep->com.local_addr.sin_family = PF_INET;
+	child_ep->com.local_addr.sin_port = req->local_port;
+	child_ep->com.local_addr.sin_addr.s_addr = req->local_ip;
+	child_ep->com.remote_addr.sin_family = PF_INET;
+	child_ep->com.remote_addr.sin_port = req->peer_port;
+	child_ep->com.remote_addr.sin_addr.s_addr = req->peer_ip;
+	get_ep(&parent_ep->com);
+	child_ep->parent_ep = parent_ep;
+	child_ep->tos = G_PASS_OPEN_TOS(ntohl(req->tos_tid));
+	child_ep->l2t = l2t;
+	child_ep->dst = dst;
+	child_ep->hwtid = hwtid;
+	init_timer(&child_ep->timer);
+	cxgb3_insert_tid(tdev, &t3c_client, child_ep, hwtid);
+	accept_cr(child_ep, req->peer_ip, skb);
+	goto out;
+reject:
+	reject_cr(tdev, hwtid, req->peer_ip, skb);
+out:
+	return CPL_RET_BUF_DONE;
+}
+
+static int pass_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep *ep = ctx;
+	struct cpl_pass_establish *req = cplhdr(skb);
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	ep->snd_seq = ntohl(req->snd_isn);
+
+	set_emss(ep, ntohs(req->tcp_opt));
+
+	dst_confirm(ep->dst);
+	state_set(&ep->com, MPA_REQ_WAIT);
+	start_ep_timer(ep);
+
+	return CPL_RET_BUF_DONE;
+}
+
+static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep *ep = ctx;
+	struct iwch_qp_attributes attrs;
+	unsigned long flags;
+	int disconnect = 1;
+	int release = 0;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	dst_confirm(ep->dst);
+
+	spin_lock_irqsave(&ep->com.lock, flags);
+	switch (ep->com.state) {
+	case MPA_REQ_WAIT:
+		__state_set(&ep->com, CLOSING);
+		break;
+	case MPA_REQ_SENT:
+		__state_set(&ep->com, CLOSING);
+		connect_reply_upcall(ep, -ECONNRESET);
+		break;
+	case MPA_REQ_RCVD:
+
+		/*
+		 * We're gonna mark this puppy DEAD, but keep
+		 * the reference on it until the ULP accepts or
+		 * rejects the CR.
+		 */
+		__state_set(&ep->com, CLOSING);
+		get_ep(&ep->com);
+		break;
+	case MPA_REP_SENT:
+		__state_set(&ep->com, CLOSING);
+		ep->com.rpl_done = 1;
+		ep->com.rpl_err = -ECONNRESET;
+		PDBG("waking up ep %p\n", ep);
+		wake_up(&ep->com.waitq);
+		break;
+	case FPDU_MODE:
+		__state_set(&ep->com, CLOSING);
+		attrs.next_state = IWCH_QP_STATE_CLOSING;
+		iwch_modify_qp(ep->com.qp->rhp, ep->com.qp,
+			       IWCH_QP_ATTR_NEXT_STATE, &attrs, 1);
+		peer_close_upcall(ep);
+		break;
+	case ABORTING:
+		disconnect = 0;
+		break;
+	case CLOSING:
+		start_ep_timer(ep);
+		__state_set(&ep->com, MORIBUND);
+		disconnect = 0;
+		break;
+	case MORIBUND:
+		stop_ep_timer(ep);
+		if (ep->com.cm_id && ep->com.qp) {
+			attrs.next_state = IWCH_QP_STATE_IDLE;
+			iwch_modify_qp(ep->com.qp->rhp, ep->com.qp,
+				       IWCH_QP_ATTR_NEXT_STATE, &attrs, 1);
+		}
+		close_complete_upcall(ep);
+		__state_set(&ep->com, DEAD);
+		release = 1;
+		disconnect = 0;
+		break;
+	case DEAD:
+		disconnect = 0;
+		break;
+	default:
+		BUG_ON(1);
+	}
+	spin_unlock_irqrestore(&ep->com.lock, flags);
+	if (disconnect)
+		iwch_ep_disconnect(ep, 0, GFP_KERNEL);
+	if (release)
+		release_ep_resources(ep);
+	return CPL_RET_BUF_DONE;
+}
+
+/*
+ * Returns whether an ABORT_REQ_RSS message is a negative advice.
+ */
+static inline int is_neg_adv_abort(unsigned int status)
+{
+	return status == CPL_ERR_RTX_NEG_ADVICE ||
+	       status == CPL_ERR_PERSIST_NEG_ADVICE;
+}
+
+static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct cpl_abort_req_rss *req = cplhdr(skb);
+	struct iwch_ep *ep = ctx;
+	struct cpl_abort_rpl *rpl;
+	struct sk_buff *rpl_skb;
+	struct iwch_qp_attributes attrs;
+	int ret;
+	int state;
+
+	if (is_neg_adv_abort(req->status)) {
+		PDBG("%s neg_adv_abort ep %p tid %d\n", __FUNCTION__, ep,
+		     ep->hwtid);
+		t3_l2t_send_event(ep->com.tdev, ep->l2t);
+		return CPL_RET_BUF_DONE;
+	}
+
+	state = state_read(&ep->com);
+	PDBG("%s ep %p state %u\n", __FUNCTION__, ep, state);
+	switch (state) {
+	case CONNECTING:
+		break;
+	case MPA_REQ_WAIT:
+		break;
+	case MPA_REQ_SENT:
+		connect_reply_upcall(ep, -ECONNRESET);
+		break;
+	case MPA_REP_SENT:
+		ep->com.rpl_done = 1;
+		ep->com.rpl_err = -ECONNRESET;
+		PDBG("waking up ep %p\n", ep);
+		wake_up(&ep->com.waitq);
+		break;
+	case MPA_REQ_RCVD:
+
+		/*
+		 * We're gonna mark this puppy DEAD, but keep
+		 * the reference on it until the ULP accepts or
+		 * rejects the CR.
+		 */
+		get_ep(&ep->com);
+		break;
+	case MORIBUND:
+		stop_ep_timer(ep);
+	case FPDU_MODE:
+	case CLOSING:
+		if (ep->com.cm_id && ep->com.qp) {
+			attrs.next_state = IWCH_QP_STATE_ERROR;
+			ret = iwch_modify_qp(ep->com.qp->rhp,
+				     ep->com.qp, IWCH_QP_ATTR_NEXT_STATE,
+				     &attrs, 1);
+			if (ret)
+				printk(KERN_ERR MOD
+				       "%s - qp <- error failed!\n",
+				       __FUNCTION__);
+		}
+		peer_abort_upcall(ep);
+		break;
+	case ABORTING:
+		break;
+	case DEAD:
+		PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __FUNCTION__);
+		return CPL_RET_BUF_DONE;
+	default:
+		BUG_ON(1);
+		break;
+	}
+	dst_confirm(ep->dst);
+
+	rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
+	if (!rpl_skb) {
+		printk(KERN_ERR MOD "%s - cannot allocate skb!\n",
+		       __FUNCTION__);
+		dst_release(ep->dst);
+		l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+		put_ep(&ep->com);
+		return CPL_RET_BUF_DONE;
+	}
+	rpl_skb->priority = CPL_PRIORITY_DATA;
+	rpl = (struct cpl_abort_rpl *) skb_put(rpl_skb, sizeof(*rpl));
+	rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL));
+	rpl->wr.wr_lo = htonl(V_WR_TID(ep->hwtid));
+	OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid));
+	rpl->cmd = CPL_ABORT_NO_RST;
+	ep->com.tdev->send(ep->com.tdev, rpl_skb);
+	if (state != ABORTING) {
+		state_set(&ep->com, DEAD);
+		release_ep_resources(ep);
+	}
+	return CPL_RET_BUF_DONE;
+}
+
+static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep *ep = ctx;
+	struct iwch_qp_attributes attrs;
+	unsigned long flags;
+	int release = 0;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	BUG_ON(!ep);
+
+	/* The cm_id may be null if we failed to connect */
+	spin_lock_irqsave(&ep->com.lock, flags);
+	switch (ep->com.state) {
+	case CLOSING:
+		start_ep_timer(ep);
+		__state_set(&ep->com, MORIBUND);
+		break;
+	case MORIBUND:
+		stop_ep_timer(ep);
+		if ((ep->com.cm_id) && (ep->com.qp)) {
+			attrs.next_state = IWCH_QP_STATE_IDLE;
+			iwch_modify_qp(ep->com.qp->rhp,
+					     ep->com.qp,
+					     IWCH_QP_ATTR_NEXT_STATE,
+					     &attrs, 1);
+		}
+		close_complete_upcall(ep);
+		__state_set(&ep->com, DEAD);
+		release = 1;
+		break;
+	case DEAD:
+	default:
+		BUG_ON(1);
+		break;
+	}
+	spin_unlock_irqrestore(&ep->com.lock, flags);
+	if (release)
+		release_ep_resources(ep);
+	return CPL_RET_BUF_DONE;
+}
+
+/*
+ * T3A does 3 things when a TERM is received:
+ * 1) send up a CPL_RDMA_TERMINATE message with the TERM packet
+ * 2) generate an async event on the QP with the TERMINATE opcode
+ * 3) post a TERMINATE opcde cqe into the associated CQ.
+ *
+ * For (1), we save the message in the qp for later consumer consumption.
+ * For (2), we move the QP into TERMINATE, post a QP event and disconnect.
+ * For (3), we toss the CQE in cxio_poll_cq().
+ *
+ * terminate() handles case (1)...
+ */
+static int terminate(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep *ep = ctx;
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	skb_pull(skb, sizeof(struct cpl_rdma_terminate));
+	PDBG("%s saving %d bytes of term msg\n", __FUNCTION__, skb->len);
+	memcpy(ep->com.qp->attr.terminate_buffer, skb->data, skb->len);
+	ep->com.qp->attr.terminate_msg_len = skb->len;
+	ep->com.qp->attr.is_terminate_local = 0;
+	return CPL_RET_BUF_DONE;
+}
+
+static int ec_status(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct cpl_rdma_ec_status *rep = cplhdr(skb);
+	struct iwch_ep *ep = ctx;
+
+	PDBG("%s ep %p tid %u status %d\n", __FUNCTION__, ep, ep->hwtid,
+	     rep->status);
+	if (rep->status) {
+		struct iwch_qp_attributes attrs;
+
+		printk(KERN_ERR MOD "%s BAD CLOSE - Aborting tid %u\n",
+		       __FUNCTION__, ep->hwtid);
+		attrs.next_state = IWCH_QP_STATE_ERROR;
+		iwch_modify_qp(ep->com.qp->rhp,
+			       ep->com.qp, IWCH_QP_ATTR_NEXT_STATE,
+			       &attrs, 1);
+		abort_connection(ep, NULL, GFP_KERNEL);
+	}
+	return CPL_RET_BUF_DONE;
+}
+
+static void ep_timeout(unsigned long arg)
+{
+	struct iwch_ep *ep = (struct iwch_ep *)arg;
+	struct iwch_qp_attributes attrs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ep->com.lock, flags);
+	PDBG("%s ep %p tid %u state %d\n", __FUNCTION__, ep, ep->hwtid,
+	     ep->com.state);
+	switch (ep->com.state) {
+	case MPA_REQ_SENT:
+		connect_reply_upcall(ep, -ETIMEDOUT);
+		break;
+	case MPA_REQ_WAIT:
+		break;
+	case MORIBUND:
+		if (ep->com.cm_id && ep->com.qp) {
+			attrs.next_state = IWCH_QP_STATE_ERROR;
+			iwch_modify_qp(ep->com.qp->rhp,
+				     ep->com.qp, IWCH_QP_ATTR_NEXT_STATE,
+				     &attrs, 1);
+		}
+		break;
+	default:
+		BUG();
+	}
+	__state_set(&ep->com, CLOSING);
+	spin_unlock_irqrestore(&ep->com.lock, flags);
+	abort_connection(ep, NULL, GFP_ATOMIC);
+	put_ep(&ep->com);
+}
+
+int iwch_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
+{
+	int err;
+	struct iwch_ep *ep = to_ep(cm_id);
+	PDBG("%s ep %p tid %u\n", __FUNCTION__, ep, ep->hwtid);
+
+	if (state_read(&ep->com) == DEAD) {
+		put_ep(&ep->com);
+		return -ECONNRESET;
+	}
+	BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
+	state_set(&ep->com, CLOSING);
+	if (mpa_rev == 0)
+		abort_connection(ep, NULL, GFP_KERNEL);
+	else {
+		err = send_mpa_reject(ep, pdata, pdata_len);
+		err = send_halfclose(ep, GFP_KERNEL);
+	}
+	return 0;
+}
+
+int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+{
+	int err;
+	struct iwch_qp_attributes attrs;
+	enum iwch_qp_attr_mask mask;
+	struct iwch_ep *ep = to_ep(cm_id);
+	struct iwch_dev *h = to_iwch_dev(cm_id->device);
+	struct iwch_qp *qp = get_qhp(h, conn_param->qpn);
+
+	PDBG("%s ep %p tid %u\n", __FUNCTION__, ep, ep->hwtid);
+	if (state_read(&ep->com) == DEAD) {
+		put_ep(&ep->com);
+		return -ECONNRESET;
+	}
+
+	BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
+	BUG_ON(!qp);
+
+	if ((conn_param->ord > qp->rhp->attr.max_rdma_read_qp_depth) ||
+	    (conn_param->ird > qp->rhp->attr.max_rdma_reads_per_qp)) {
+		abort_connection(ep, NULL, GFP_KERNEL);
+		return -EINVAL;
+	}
+
+	cm_id->add_ref(cm_id);
+	ep->com.cm_id = cm_id;
+	ep->com.qp = qp;
+
+	ep->com.rpl_done = 0;
+	ep->com.rpl_err = 0;
+	ep->ird = conn_param->ird;
+	ep->ord = conn_param->ord;
+	PDBG("%s %d ird %d ord %d\n", __FUNCTION__, __LINE__, ep->ird, ep->ord);
+	get_ep(&ep->com);
+	err = send_mpa_reply(ep, conn_param->private_data,
+			     conn_param->private_data_len);
+	if (err) {
+		ep->com.cm_id = NULL;
+		ep->com.qp = NULL;
+		cm_id->rem_ref(cm_id);
+		abort_connection(ep, NULL, GFP_KERNEL);
+		put_ep(&ep->com);
+		return err;
+	}
+
+	/* bind QP to EP and move to RTS */
+	attrs.mpa_attr = ep->mpa_attr;
+	attrs.max_ird = ep->ord;
+	attrs.max_ord = ep->ord;
+	attrs.llp_stream_handle = ep;
+	attrs.next_state = IWCH_QP_STATE_RTS;
+
+	/* bind QP and TID with INIT_WR */
+	mask = IWCH_QP_ATTR_NEXT_STATE |
+			     IWCH_QP_ATTR_LLP_STREAM_HANDLE |
+			     IWCH_QP_ATTR_MPA_ATTR |
+			     IWCH_QP_ATTR_MAX_IRD |
+			     IWCH_QP_ATTR_MAX_ORD;
+
+	err = iwch_modify_qp(ep->com.qp->rhp,
+			     ep->com.qp, mask, &attrs, 1);
+
+	if (err) {
+		ep->com.cm_id = NULL;
+		ep->com.qp = NULL;
+		cm_id->rem_ref(cm_id);
+		abort_connection(ep, NULL, GFP_KERNEL);
+	} else {
+		state_set(&ep->com, FPDU_MODE);
+		established_upcall(ep);
+	}
+	put_ep(&ep->com);
+	return err;
+}
+
+int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+{
+	int err = 0;
+	struct iwch_dev *h = to_iwch_dev(cm_id->device);
+	struct iwch_ep *ep;
+	struct rtable *rt;
+
+	ep = alloc_ep(sizeof(*ep), GFP_KERNEL);
+	if (!ep) {
+		printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __FUNCTION__);
+		err = -ENOMEM;
+		goto out;
+	}
+	init_timer(&ep->timer);
+	ep->plen = conn_param->private_data_len;
+	if (ep->plen)
+		memcpy(ep->mpa_pkt + sizeof(struct mpa_message),
+		       conn_param->private_data, ep->plen);
+	ep->ird = conn_param->ird;
+	ep->ord = conn_param->ord;
+	ep->com.tdev = h->rdev.t3cdev_p;
+
+	cm_id->add_ref(cm_id);
+	ep->com.cm_id = cm_id;
+	ep->com.qp = get_qhp(h, conn_param->qpn);
+	BUG_ON(!ep->com.qp);
+	PDBG("%s qpn 0x%x qp %p cm_id %p\n", __FUNCTION__, conn_param->qpn,
+	     ep->com.qp, cm_id);
+
+	/*
+	 * Allocate an active TID to initiate a TCP connection.
+	 */
+	ep->atid = cxgb3_alloc_atid(h->rdev.t3cdev_p, &t3c_client, ep);
+	if (ep->atid == -1) {
+		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __FUNCTION__);
+		err = -ENOMEM;
+		goto fail2;
+	}
+
+	/* find a route */
+	rt = find_route(h->rdev.t3cdev_p,
+			cm_id->local_addr.sin_addr.s_addr,
+			cm_id->remote_addr.sin_addr.s_addr,
+			cm_id->local_addr.sin_port,
+			cm_id->remote_addr.sin_port, IPTOS_LOWDELAY);
+	if (!rt) {
+		printk(KERN_ERR MOD "%s - cannot find route.\n", __FUNCTION__);
+		err = -EHOSTUNREACH;
+		goto fail3;
+	}
+	ep->dst = &rt->u.dst;
+
+	/* get a l2t entry */
+	ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
+			     ep->dst->neighbour->dev);
+	if (!ep->l2t) {
+		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __FUNCTION__);
+		err = -ENOMEM;
+		goto fail4;
+	}
+
+	state_set(&ep->com, CONNECTING);
+	ep->tos = IPTOS_LOWDELAY;
+	ep->com.local_addr = cm_id->local_addr;
+	ep->com.remote_addr = cm_id->remote_addr;
+
+	/* send connect request to rnic */
+	err = send_connect(ep);
+	if (!err)
+		goto out;
+
+	l2t_release(L2DATA(h->rdev.t3cdev_p), ep->l2t);
+fail4:
+	dst_release(ep->dst);
+fail3:
+	cxgb3_free_atid(ep->com.tdev, ep->atid);
+fail2:
+	put_ep(&ep->com);
+out:
+	return err;
+}
+
+int iwch_create_listen(struct iw_cm_id *cm_id, int backlog)
+{
+	int err = 0;
+	struct iwch_dev *h = to_iwch_dev(cm_id->device);
+	struct iwch_listen_ep *ep;
+
+
+	might_sleep();
+
+	ep = alloc_ep(sizeof(*ep), GFP_KERNEL);
+	if (!ep) {
+		printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __FUNCTION__);
+		err = -ENOMEM;
+		goto fail1;
+	}
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+	ep->com.tdev = h->rdev.t3cdev_p;
+	cm_id->add_ref(cm_id);
+	ep->com.cm_id = cm_id;
+	ep->backlog = backlog;
+	ep->com.local_addr = cm_id->local_addr;
+
+	/*
+	 * Allocate a server TID.
+	 */
+	ep->stid = cxgb3_alloc_stid(h->rdev.t3cdev_p, &t3c_client, ep);
+	if (ep->stid == -1) {
+		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __FUNCTION__);
+		err = -ENOMEM;
+		goto fail2;
+	}
+
+	state_set(&ep->com, LISTEN);
+	err = listen_start(ep);
+	if (err)
+		goto fail3;
+
+	/* wait for pass_open_rpl */
+	wait_event(ep->com.waitq, ep->com.rpl_done);
+	err = ep->com.rpl_err;
+	if (!err) {
+		cm_id->provider_data = ep;
+		goto out;
+	}
+fail3:
+	cxgb3_free_stid(ep->com.tdev, ep->stid);
+fail2:
+	put_ep(&ep->com);
+fail1:
+out:
+	return err;
+}
+
+int iwch_destroy_listen(struct iw_cm_id *cm_id)
+{
+	int err;
+	struct iwch_listen_ep *ep = to_listen_ep(cm_id);
+
+	PDBG("%s ep %p\n", __FUNCTION__, ep);
+
+	might_sleep();
+	state_set(&ep->com, DEAD);
+	ep->com.rpl_done = 0;
+	ep->com.rpl_err = 0;
+	err = listen_stop(ep);
+	wait_event(ep->com.waitq, ep->com.rpl_done);
+	cxgb3_free_stid(ep->com.tdev, ep->stid);
+	err = ep->com.rpl_err;
+	cm_id->rem_ref(cm_id);
+	put_ep(&ep->com);
+	return err;
+}
+
+int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp)
+{
+	int ret=0;
+	unsigned long flags;
+	int close = 0;
+
+	spin_lock_irqsave(&ep->com.lock, flags);
+
+	PDBG("%s ep %p state %s, abrupt %d\n", __FUNCTION__, ep,
+	     states[ep->com.state], abrupt);
+
+	if (ep->com.state == DEAD) {
+		PDBG("%s already dead ep %p\n", __FUNCTION__, ep);
+		goto out;
+	}
+
+	if (abrupt) {
+		if (ep->com.state != ABORTING) {
+			ep->com.state = ABORTING;
+			close = 1;
+		}
+		goto out;
+	}
+
+	switch (ep->com.state) {
+	case MPA_REQ_WAIT:
+	case MPA_REQ_SENT:
+	case MPA_REQ_RCVD:
+	case MPA_REP_SENT:
+	case FPDU_MODE:
+		ep->com.state = CLOSING;
+		close = 1;
+		break;
+	case CLOSING:
+		start_ep_timer(ep);
+		ep->com.state = MORIBUND;
+		close = 1;
+		break;
+	case MORIBUND:
+		break;
+	default:
+		BUG();
+		break;
+	}
+out:
+	spin_unlock_irqrestore(&ep->com.lock, flags);
+	if (close) {
+		if (abrupt)
+			ret = send_abort(ep, NULL, gfp);
+		else
+			ret = send_halfclose(ep, gfp);
+	}
+	return ret;
+}
+
+int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
+		     struct l2t_entry *l2t)
+{
+	struct iwch_ep *ep = ctx;
+
+	if (ep->dst != old)
+		return 0;
+
+	PDBG("%s ep %p redirect to dst %p l2t %p\n", __FUNCTION__, ep, new,
+	     l2t);
+	dst_hold(new);
+	l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+	ep->l2t = l2t;
+	dst_release(old);
+	ep->dst = new;
+	return 1;
+}
+
+/*
+ * All the CM events are handled on a work queue to have a safe context.
+ */
+static int sched(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct iwch_ep_common *epc = ctx;
+
+	get_ep(epc);
+
+	/*
+	 * Save ctx and tdev in the skb->cb area.
+	 */
+	*((void **) skb->cb) = ctx;
+	*((struct t3cdev **) (skb->cb + sizeof(void *))) = tdev;
+
+	/*
+	 * Queue the skb and schedule the worker thread.
+	 */
+	skb_queue_tail(&rxq, skb);
+	queue_work(workq, &skb_work);
+	return 0;
+}
+
+int __init iwch_cm_init(void)
+{
+	skb_queue_head_init(&rxq);
+
+	workq = create_singlethread_workqueue("iw_cxgb3");
+	if (!workq)
+		return -ENOMEM;
+
+	/*
+	 * All upcalls from the T3 Core go to sched() to
+	 * schedule the processing on a work queue.
+	 */
+	t3c_handlers[CPL_ACT_ESTABLISH] = sched;
+	t3c_handlers[CPL_ACT_OPEN_RPL] = sched;
+	t3c_handlers[CPL_RX_DATA] = sched;
+	t3c_handlers[CPL_TX_DMA_ACK] = sched;
+	t3c_handlers[CPL_ABORT_RPL_RSS] = sched;
+	t3c_handlers[CPL_ABORT_RPL] = sched;
+	t3c_handlers[CPL_PASS_OPEN_RPL] = sched;
+	t3c_handlers[CPL_CLOSE_LISTSRV_RPL] = sched;
+	t3c_handlers[CPL_PASS_ACCEPT_REQ] = sched;
+	t3c_handlers[CPL_PASS_ESTABLISH] = sched;
+	t3c_handlers[CPL_PEER_CLOSE] = sched;
+	t3c_handlers[CPL_CLOSE_CON_RPL] = sched;
+	t3c_handlers[CPL_ABORT_REQ_RSS] = sched;
+	t3c_handlers[CPL_RDMA_TERMINATE] = sched;
+	t3c_handlers[CPL_RDMA_EC_STATUS] = sched;
+
+	/*
+	 * These are the real handlers that are called from a
+	 * work queue.
+	 */
+	work_handlers[CPL_ACT_ESTABLISH] = act_establish;
+	work_handlers[CPL_ACT_OPEN_RPL] = act_open_rpl;
+	work_handlers[CPL_RX_DATA] = rx_data;
+	work_handlers[CPL_TX_DMA_ACK] = tx_ack;
+	work_handlers[CPL_ABORT_RPL_RSS] = abort_rpl;
+	work_handlers[CPL_ABORT_RPL] = abort_rpl;
+	work_handlers[CPL_PASS_OPEN_RPL] = pass_open_rpl;
+	work_handlers[CPL_CLOSE_LISTSRV_RPL] = close_listsrv_rpl;
+	work_handlers[CPL_PASS_ACCEPT_REQ] = pass_accept_req;
+	work_handlers[CPL_PASS_ESTABLISH] = pass_establish;
+	work_handlers[CPL_PEER_CLOSE] = peer_close;
+	work_handlers[CPL_ABORT_REQ_RSS] = peer_abort;
+	work_handlers[CPL_CLOSE_CON_RPL] = close_con_rpl;
+	work_handlers[CPL_RDMA_TERMINATE] = terminate;
+	work_handlers[CPL_RDMA_EC_STATUS] = ec_status;
+	return 0;
+}
+
+void __exit iwch_cm_term(void)
+{
+	flush_workqueue(workq);
+	destroy_workqueue(workq);
+}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
new file mode 100644
index 0000000..0c6f281
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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 _IWCH_CM_H_
+#define _IWCH_CM_H_
+
+#include <linux/inet.h>
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/iw_cm.h>
+
+#include "cxgb3_offload.h"
+#include "iwch_provider.h"
+
+#define MPA_KEY_REQ "MPA ID Req Frame"
+#define MPA_KEY_REP "MPA ID Rep Frame"
+
+#define MPA_MAX_PRIVATE_DATA	256
+#define MPA_REV		0	/* XXX - amso1100 uses rev 0 ! */
+#define MPA_REJECT		0x20
+#define MPA_CRC			0x40
+#define MPA_MARKERS		0x80
+#define MPA_FLAGS_MASK		0xE0
+
+#define put_ep(ep) { \
+	PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __FUNCTION__, __LINE__,  \
+	     ep, atomic_read(&((ep)->kref.refcount))); \
+	kref_put(&((ep)->kref), __free_ep); \
+}
+
+#define get_ep(ep) { \
+	PDBG("get_ep (via %s:%u) ep %p, refcnt %d\n", __FUNCTION__, __LINE__, \
+	     ep, atomic_read(&((ep)->kref.refcount))); \
+	kref_get(&((ep)->kref));  \
+}
+
+struct mpa_message {
+	u8 key[16];
+	u8 flags;
+	u8 revision;
+	__be16 private_data_size;
+	u8 private_data[0];
+};
+
+struct terminate_message {
+	u8 layer_etype;
+	u8 ecode;
+	__be16 hdrct_rsvd;
+	u8 len_hdrs[0];
+};
+
+#define TERM_MAX_LENGTH (sizeof(struct terminate_message) + 2 + 18 + 28)
+
+enum iwch_layers_types {
+	LAYER_RDMAP		= 0x00,
+	LAYER_DDP		= 0x10,
+	LAYER_MPA		= 0x20,
+	RDMAP_LOCAL_CATA	= 0x00,
+	RDMAP_REMOTE_PROT	= 0x01,
+	RDMAP_REMOTE_OP		= 0x02,
+	DDP_LOCAL_CATA		= 0x00,
+	DDP_TAGGED_ERR		= 0x01,
+	DDP_UNTAGGED_ERR	= 0x02,
+	DDP_LLP			= 0x03
+};
+
+enum iwch_rdma_ecodes {
+	RDMAP_INV_STAG		= 0x00,
+	RDMAP_BASE_BOUNDS	= 0x01,
+	RDMAP_ACC_VIOL		= 0x02,
+	RDMAP_STAG_NOT_ASSOC	= 0x03,
+	RDMAP_TO_WRAP		= 0x04,
+	RDMAP_INV_VERS		= 0x05,
+	RDMAP_INV_OPCODE	= 0x06,
+	RDMAP_STREAM_CATA	= 0x07,
+	RDMAP_GLOBAL_CATA	= 0x08,
+	RDMAP_CANT_INV_STAG	= 0x09,
+	RDMAP_UNSPECIFIED	= 0xff
+};
+
+enum iwch_ddp_ecodes {
+	DDPT_INV_STAG		= 0x00,
+	DDPT_BASE_BOUNDS	= 0x01,
+	DDPT_STAG_NOT_ASSOC	= 0x02,
+	DDPT_TO_WRAP		= 0x03,
+	DDPT_INV_VERS		= 0x04,
+	DDPU_INV_QN		= 0x01,
+	DDPU_INV_MSN_NOBUF	= 0x02,
+	DDPU_INV_MSN_RANGE	= 0x03,
+	DDPU_INV_MO		= 0x04,
+	DDPU_MSG_TOOBIG		= 0x05,
+	DDPU_INV_VERS		= 0x06
+};
+
+enum iwch_mpa_ecodes {
+	MPA_CRC_ERR		= 0x02,
+	MPA_MARKER_ERR		= 0x03
+};
+
+enum iwch_ep_state {
+	IDLE = 0,
+	LISTEN,
+	CONNECTING,
+	MPA_REQ_WAIT,
+	MPA_REQ_SENT,
+	MPA_REQ_RCVD,
+	MPA_REP_SENT,
+	FPDU_MODE,
+	ABORTING,
+	CLOSING,
+	MORIBUND,
+	DEAD,
+};
+
+struct iwch_ep_common {
+	struct iw_cm_id *cm_id;
+	struct iwch_qp *qp;
+	struct t3cdev *tdev;
+	enum iwch_ep_state state;
+	struct kref kref;
+	spinlock_t lock;
+	struct sockaddr_in local_addr;
+	struct sockaddr_in remote_addr;
+	wait_queue_head_t waitq;
+	int rpl_done;
+	int rpl_err;
+};
+
+struct iwch_listen_ep {
+	struct iwch_ep_common com;
+	unsigned int stid;
+	int backlog;
+};
+
+struct iwch_ep {
+	struct iwch_ep_common com;
+	struct iwch_ep *parent_ep;
+	struct timer_list timer;
+	unsigned int atid;
+	u32 hwtid;
+	u32 snd_seq;
+	struct l2t_entry *l2t;
+	struct dst_entry *dst;
+	struct sk_buff *mpa_skb;
+	struct iwch_mpa_attributes mpa_attr;
+	unsigned int mpa_pkt_len;
+	u8 mpa_pkt[sizeof(struct mpa_message) + MPA_MAX_PRIVATE_DATA];
+	u8 tos;
+	u16 emss;
+	u16 plen;
+	u32 ird;
+	u32 ord;
+};
+
+static inline struct iwch_ep *to_ep(struct iw_cm_id *cm_id)
+{
+	return cm_id->provider_data;
+}
+
+static inline struct iwch_listen_ep *to_listen_ep(struct iw_cm_id *cm_id)
+{
+	return cm_id->provider_data;
+}
+
+static inline int compute_wscale(int win)
+{
+	int wscale = 0;
+
+	while (wscale < 14 && (65535<<wscale) < win)
+		wscale++;
+	return wscale;
+}
+
+/* CM prototypes */
+
+int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param);
+int iwch_create_listen(struct iw_cm_id *cm_id, int backlog);
+int iwch_destroy_listen(struct iw_cm_id *cm_id);
+int iwch_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len);
+int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param);
+int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp);
+int iwch_quiesce_tid(struct iwch_ep *ep);
+int iwch_resume_tid(struct iwch_ep *ep);
+void __free_ep(struct kref *kref);
+void iwch_rearp(struct iwch_ep *ep);
+int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, struct l2t_entry *l2t);
+
+int __init iwch_cm_init(void);
+void __exit iwch_cm_term(void);
+
+#endif				/* _IWCH_CM_H_ */
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cq.c b/drivers/infiniband/hw/cxgb3/iwch_cq.c
new file mode 100644
index 0000000..d7624c1
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch_cq.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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 "iwch_provider.h"
+#include "iwch.h"
+
+/*
+ * Get one cq entry from cxio and map it to openib.
+ *
+ * Returns:
+ *	0			EMPTY;
+ *	1			cqe returned
+ *	-EAGAIN		caller must try again
+ *	any other -errno	fatal error
+ */
+static int iwch_poll_cq_one(struct iwch_dev *rhp, struct iwch_cq *chp,
+			    struct ib_wc *wc)
+{
+	struct iwch_qp *qhp = NULL;
+	struct t3_cqe cqe, *rd_cqe;
+	struct t3_wq *wq;
+	u32 credit = 0;
+	u8 cqe_flushed;
+	u64 cookie;
+	int ret = 1;
+
+	rd_cqe = cxio_next_cqe(&chp->cq);
+
+	if (!rd_cqe)
+		return 0;
+
+	qhp = get_qhp(rhp, CQE_QPID(*rd_cqe));
+	if (!qhp)
+		wq = NULL;
+	else {
+		spin_lock(&qhp->lock);
+		wq = &(qhp->wq);
+	}
+	ret = cxio_poll_cq(wq, &(chp->cq), &cqe, &cqe_flushed, &cookie,
+				   &credit);
+	if (t3a_device(chp->rhp) && credit) {
+		PDBG("%s updating %d cq credits on id %d\n", __FUNCTION__,
+		     credit, chp->cq.cqid);
+		cxio_hal_cq_op(&rhp->rdev, &chp->cq, CQ_CREDIT_UPDATE, credit);
+	}
+
+	if (ret) {
+		ret = -EAGAIN;
+		goto out;
+	}
+	ret = 1;
+
+	wc->wr_id = cookie;
+	wc->qp = &qhp->ibqp;
+	wc->vendor_err = CQE_STATUS(cqe);
+
+	PDBG("%s qpid 0x%x type %d opcode %d status 0x%x wrid hi 0x%x "
+	     "lo 0x%x cookie 0x%llx\n", __FUNCTION__,
+	     CQE_QPID(cqe), CQE_TYPE(cqe),
+	     CQE_OPCODE(cqe), CQE_STATUS(cqe), CQE_WRID_HI(cqe),
+	     CQE_WRID_LOW(cqe), (unsigned long long) cookie);
+
+	if (CQE_TYPE(cqe) == 0) {
+		if (!CQE_STATUS(cqe))
+			wc->byte_len = CQE_LEN(cqe);
+		else
+			wc->byte_len = 0;
+		wc->opcode = IB_WC_RECV;
+	} else {
+		switch (CQE_OPCODE(cqe)) {
+		case T3_RDMA_WRITE:
+			wc->opcode = IB_WC_RDMA_WRITE;
+			break;
+		case T3_READ_REQ:
+			wc->opcode = IB_WC_RDMA_READ;
+			wc->byte_len = CQE_LEN(cqe);
+			break;
+		case T3_SEND:
+		case T3_SEND_WITH_SE:
+			wc->opcode = IB_WC_SEND;
+			break;
+		case T3_BIND_MW:
+			wc->opcode = IB_WC_BIND_MW;
+			break;
+
+		/* these aren't supported yet */
+		case T3_SEND_WITH_INV:
+		case T3_SEND_WITH_SE_INV:
+		case T3_LOCAL_INV:
+		case T3_FAST_REGISTER:
+		default:
+			printk(KERN_ERR MOD "Unexpected opcode %d "
+			       "in the CQE received for QPID=0x%0x\n",
+			       CQE_OPCODE(cqe), CQE_QPID(cqe));
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	if (cqe_flushed)
+		wc->status = IB_WC_WR_FLUSH_ERR;
+	else {
+
+		switch (CQE_STATUS(cqe)) {
+		case TPT_ERR_SUCCESS:
+			wc->status = IB_WC_SUCCESS;
+			break;
+		case TPT_ERR_STAG:
+			wc->status = IB_WC_LOC_ACCESS_ERR;
+			break;
+		case TPT_ERR_PDID:
+			wc->status = IB_WC_LOC_PROT_ERR;
+			break;
+		case TPT_ERR_QPID:
+		case TPT_ERR_ACCESS:
+			wc->status = IB_WC_LOC_ACCESS_ERR;
+			break;
+		case TPT_ERR_WRAP:
+			wc->status = IB_WC_GENERAL_ERR;
+			break;
+		case TPT_ERR_BOUND:
+			wc->status = IB_WC_LOC_LEN_ERR;
+			break;
+		case TPT_ERR_INVALIDATE_SHARED_MR:
+		case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND:
+			wc->status = IB_WC_MW_BIND_ERR;
+			break;
+		case TPT_ERR_CRC:
+		case TPT_ERR_MARKER:
+		case TPT_ERR_PDU_LEN_ERR:
+		case TPT_ERR_OUT_OF_RQE:
+		case TPT_ERR_DDP_VERSION:
+		case TPT_ERR_RDMA_VERSION:
+		case TPT_ERR_DDP_QUEUE_NUM:
+		case TPT_ERR_MSN:
+		case TPT_ERR_TBIT:
+		case TPT_ERR_MO:
+		case TPT_ERR_MSN_RANGE:
+		case TPT_ERR_IRD_OVERFLOW:
+		case TPT_ERR_OPCODE:
+			wc->status = IB_WC_FATAL_ERR;
+			break;
+		case TPT_ERR_SWFLUSH:
+			wc->status = IB_WC_WR_FLUSH_ERR;
+			break;
+		default:
+			printk(KERN_ERR MOD "Unexpected cqe_status 0x%x for "
+			       "QPID=0x%0x\n", CQE_STATUS(cqe), CQE_QPID(cqe));
+			ret = -EINVAL;
+		}
+	}
+out:
+	if (wq)
+		spin_unlock(&qhp->lock);
+	return ret;
+}
+
+int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
+{
+	struct iwch_dev *rhp;
+	struct iwch_cq *chp;
+	unsigned long flags;
+	int npolled;
+	int err = 0;
+
+	chp = to_iwch_cq(ibcq);
+	rhp = chp->rhp;
+
+	spin_lock_irqsave(&chp->lock, flags);
+	for (npolled = 0; npolled < num_entries; ++npolled) {
+#ifdef DEBUG
+		int i=0;
+#endif
+
+		/*
+		 * Because T3 can post CQEs that are _not_ associated
+		 * with a WR, we might have to poll again after removing
+		 * one of these.
+		 */
+		do {
+			err = iwch_poll_cq_one(rhp, chp, wc + npolled);
+#ifdef DEBUG
+			BUG_ON(++i > 1000);
+#endif
+		} while (err == -EAGAIN);
+		if (err <= 0)
+			break;
+	}
+	spin_unlock_irqrestore(&chp->lock, flags);
+
+	if (err < 0)
+		return err;
+	else {
+		return npolled;
+	}
+}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c
new file mode 100644
index 0000000..54362af
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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/slab.h>
+#include <linux/mman.h>
+#include <net/sock.h>
+#include "iwch_provider.h"
+#include "iwch.h"
+#include "iwch_cm.h"
+#include "cxio_hal.h"
+#include "cxio_wr.h"
+
+static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
+			  struct respQ_msg_t *rsp_msg,
+			  enum ib_event_type ib_event,
+			  int send_term)
+{
+	struct ib_event event;
+	struct iwch_qp_attributes attrs;
+	struct iwch_qp *qhp;
+
+	printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x "
+	       "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
+	       CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
+	       CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
+	       CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+
+	spin_lock(&rnicp->lock);
+	qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
+
+	if (!qhp) {
+		printk(KERN_ERR "%s unaffiliated error 0x%x qpid 0x%x\n",
+		       __FUNCTION__, CQE_STATUS(rsp_msg->cqe),
+		       CQE_QPID(rsp_msg->cqe));
+		spin_unlock(&rnicp->lock);
+		return;
+	}
+
+	if ((qhp->attr.state == IWCH_QP_STATE_ERROR) ||
+	    (qhp->attr.state == IWCH_QP_STATE_TERMINATE)) {
+		PDBG("%s AE received after RTS - "
+		     "qp state %d qpid 0x%x status 0x%x\n", __FUNCTION__,
+		     qhp->attr.state, qhp->wq.qpid, CQE_STATUS(rsp_msg->cqe));
+		spin_unlock(&rnicp->lock);
+		return;
+	}
+
+	atomic_inc(&qhp->refcnt);
+	spin_unlock(&rnicp->lock);
+
+	event.event = ib_event;
+	event.device = chp->ibcq.device;
+	if (ib_event == IB_EVENT_CQ_ERR)
+		event.element.cq = &chp->ibcq;
+	else
+		event.element.qp = &qhp->ibqp;
+
+	if (qhp->ibqp.event_handler)
+		(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
+
+	if (qhp->attr.state == IWCH_QP_STATE_RTS) {
+		attrs.next_state = IWCH_QP_STATE_TERMINATE;
+		iwch_modify_qp(qhp->rhp, qhp, IWCH_QP_ATTR_NEXT_STATE,
+			       &attrs, 1);
+		if (send_term)
+			iwch_post_terminate(qhp, rsp_msg);
+	}
+
+	if (atomic_dec_and_test(&qhp->refcnt))
+		wake_up(&qhp->wait);
+}
+
+void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
+{
+	struct iwch_dev *rnicp;
+	struct respQ_msg_t *rsp_msg = (struct respQ_msg_t *) skb->data;
+	struct iwch_cq *chp;
+	struct iwch_qp *qhp;
+	u32 cqid = RSPQ_CQID(rsp_msg);
+
+	rnicp = (struct iwch_dev *) rdev_p->ulp;
+	spin_lock(&rnicp->lock);
+	chp = get_chp(rnicp, cqid);
+	qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
+	if (!chp || !qhp) {
+		printk(KERN_ERR MOD "BAD AE cqid 0x%x qpid 0x%x opcode %d "
+		       "status 0x%x type %d wrid.hi 0x%x wrid.lo 0x%x \n",
+		       cqid, CQE_QPID(rsp_msg->cqe),
+		       CQE_OPCODE(rsp_msg->cqe), CQE_STATUS(rsp_msg->cqe),
+		       CQE_TYPE(rsp_msg->cqe), CQE_WRID_HI(rsp_msg->cqe),
+		       CQE_WRID_LOW(rsp_msg->cqe));
+		spin_unlock(&rnicp->lock);
+		goto out;
+	}
+	iwch_qp_add_ref(&qhp->ibqp);
+	atomic_inc(&chp->refcnt);
+	spin_unlock(&rnicp->lock);
+
+	/*
+	 * 1) completion of our sending a TERMINATE.
+	 * 2) incoming TERMINATE message.
+	 */
+	if ((CQE_OPCODE(rsp_msg->cqe) == T3_TERMINATE) &&
+	    (CQE_STATUS(rsp_msg->cqe) == 0)) {
+		if (SQ_TYPE(rsp_msg->cqe)) {
+			PDBG("%s QPID 0x%x ep %p disconnecting\n",
+			     __FUNCTION__, qhp->wq.qpid, qhp->ep);
+			iwch_ep_disconnect(qhp->ep, 0, GFP_ATOMIC);
+		} else {
+			PDBG("%s post REQ_ERR AE QPID 0x%x\n", __FUNCTION__,
+			     qhp->wq.qpid);
+			post_qp_event(rnicp, chp, rsp_msg,
+				      IB_EVENT_QP_REQ_ERR, 0);
+			iwch_ep_disconnect(qhp->ep, 0, GFP_ATOMIC);
+		}
+		goto done;
+	}
+
+	/* Bad incoming Read request */
+	if (SQ_TYPE(rsp_msg->cqe) &&
+	    (CQE_OPCODE(rsp_msg->cqe) == T3_READ_RESP)) {
+		post_qp_event(rnicp, chp, rsp_msg, IB_EVENT_QP_REQ_ERR, 1);
+		goto done;
+	}
+
+	/* Bad incoming write */
+	if (RQ_TYPE(rsp_msg->cqe) &&
+	    (CQE_OPCODE(rsp_msg->cqe) == T3_RDMA_WRITE)) {
+		post_qp_event(rnicp, chp, rsp_msg, IB_EVENT_QP_REQ_ERR, 1);
+		goto done;
+	}
+
+	switch (CQE_STATUS(rsp_msg->cqe)) {
+
+	/* Completion Events */
+	case TPT_ERR_SUCCESS:
+
+		/*
+		 * Confirm the destination entry if this is a RECV completion.
+		 */
+		if (qhp->ep && SQ_TYPE(rsp_msg->cqe))
+			dst_confirm(qhp->ep->dst);
+		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+		break;
+
+	case TPT_ERR_STAG:
+	case TPT_ERR_PDID:
+	case TPT_ERR_QPID:
+	case TPT_ERR_ACCESS:
+	case TPT_ERR_WRAP:
+	case TPT_ERR_BOUND:
+	case TPT_ERR_INVALIDATE_SHARED_MR:
+	case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND:
+		printk(KERN_ERR "%s - CQE Err qpid 0x%x opcode %d status 0x%x "
+		       "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
+		       CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
+		       CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
+		       CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+		post_qp_event(rnicp, chp, rsp_msg, IB_EVENT_QP_ACCESS_ERR, 1);
+		break;
+
+	/* Device Fatal Errors */
+	case TPT_ERR_ECC:
+	case TPT_ERR_ECC_PSTAG:
+	case TPT_ERR_INTERNAL_ERR:
+		post_qp_event(rnicp, chp, rsp_msg, IB_EVENT_DEVICE_FATAL, 1);
+		break;
+
+	/* QP Fatal Errors */
+	case TPT_ERR_OUT_OF_RQE:
+	case TPT_ERR_PBL_ADDR_BOUND:
+	case TPT_ERR_CRC:
+	case TPT_ERR_MARKER:
+	case TPT_ERR_PDU_LEN_ERR:
+	case TPT_ERR_DDP_VERSION:
+	case TPT_ERR_RDMA_VERSION:
+	case TPT_ERR_OPCODE:
+	case TPT_ERR_DDP_QUEUE_NUM:
+	case TPT_ERR_MSN:
+	case TPT_ERR_TBIT:
+	case TPT_ERR_MO:
+	case TPT_ERR_MSN_GAP:
+	case TPT_ERR_MSN_RANGE:
+	case TPT_ERR_RQE_ADDR_BOUND:
+	case TPT_ERR_IRD_OVERFLOW:
+		post_qp_event(rnicp, chp, rsp_msg, IB_EVENT_QP_FATAL, 1);
+		break;
+
+	default:
+		printk(KERN_ERR MOD "Unknown T3 status 0x%x QPID 0x%x\n",
+		       CQE_STATUS(rsp_msg->cqe), qhp->wq.qpid);
+		post_qp_event(rnicp, chp, rsp_msg, IB_EVENT_QP_FATAL, 1);
+		break;
+	}
+done:
+	if (atomic_dec_and_test(&chp->refcnt))
+	        wake_up(&chp->wait);
+	iwch_qp_rem_ref(&qhp->ibqp);
+out:
+	dev_kfree_skb_irq(skb);
+}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_mem.c b/drivers/infiniband/hw/cxgb3/iwch_mem.c
new file mode 100644
index 0000000..a6c2c4b
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch_mem.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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/byteorder.h>
+
+#include <rdma/iw_cm.h>
+#include <rdma/ib_verbs.h>
+
+#include "cxio_hal.h"
+#include "iwch.h"
+#include "iwch_provider.h"
+
+int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php,
+					struct iwch_mr *mhp,
+					int shift,
+					__be64 *page_list)
+{
+	u32 stag;
+	u32 mmid;
+
+
+	if (cxio_register_phys_mem(&rhp->rdev,
+				   &stag, mhp->attr.pdid,
+				   mhp->attr.perms,
+				   mhp->attr.zbva,
+				   mhp->attr.va_fbo,
+				   mhp->attr.len,
+				   shift-12,
+				   page_list,
+				   &mhp->attr.pbl_size, &mhp->attr.pbl_addr))
+		return -ENOMEM;
+	mhp->attr.state = 1;
+	mhp->attr.stag = stag;
+	mmid = stag >> 8;
+	mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
+	insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+	PDBG("%s mmid 0x%x mhp %p\n", __FUNCTION__, mmid, mhp);
+	return 0;
+}
+
+int iwch_reregister_mem(struct iwch_dev *rhp, struct iwch_pd *php,
+					struct iwch_mr *mhp,
+					int shift,
+					__be64 *page_list,
+					int npages)
+{
+	u32 stag;
+	u32 mmid;
+
+
+	/* We could support this... */
+	if (npages > mhp->attr.pbl_size)
+		return -ENOMEM;
+
+	stag = mhp->attr.stag;
+	if (cxio_reregister_phys_mem(&rhp->rdev,
+				   &stag, mhp->attr.pdid,
+				   mhp->attr.perms,
+				   mhp->attr.zbva,
+				   mhp->attr.va_fbo,
+				   mhp->attr.len,
+				   shift-12,
+				   page_list,
+				   &mhp->attr.pbl_size, &mhp->attr.pbl_addr))
+		return -ENOMEM;
+	mhp->attr.state = 1;
+	mhp->attr.stag = stag;
+	mmid = stag >> 8;
+	mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
+	insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+	PDBG("%s mmid 0x%x mhp %p\n", __FUNCTION__, mmid, mhp);
+	return 0;
+}
+
+int build_phys_page_list(struct ib_phys_buf *buffer_list,
+					int num_phys_buf,
+					u64 *iova_start,
+					u64 *total_size,
+					int *npages,
+					int *shift,
+					__be64 **page_list)
+{
+	u64 mask;
+	int i, j, n;
+
+	mask = 0;
+	*total_size = 0;
+	for (i = 0; i < num_phys_buf; ++i) {
+		if (i != 0 && buffer_list[i].addr & ~PAGE_MASK)
+			return -EINVAL;
+		if (i != 0 && i != num_phys_buf - 1 &&
+		    (buffer_list[i].size & ~PAGE_MASK))
+			return -EINVAL;
+		*total_size += buffer_list[i].size;
+		if (i > 0)
+			mask |= buffer_list[i].addr;
+	}
+
+	if (*total_size > 0xFFFFFFFFULL)
+		return -ENOMEM;
+
+	/* Find largest page shift we can use to cover buffers */
+	for (*shift = PAGE_SHIFT; *shift < 27; ++(*shift))
+		if (num_phys_buf > 1) {
+			if ((1ULL << *shift) & mask)
+				break;
+		} else
+			if (1ULL << *shift >=
+			    buffer_list[0].size +
+			    (buffer_list[0].addr & ((1ULL << *shift) - 1)))
+				break;
+
+	buffer_list[0].size += buffer_list[0].addr & ((1ULL << *shift) - 1);
+	buffer_list[0].addr &= ~0ull << *shift;
+
+	*npages = 0;
+	for (i = 0; i < num_phys_buf; ++i)
+		*npages += (buffer_list[i].size +
+			(1ULL << *shift) - 1) >> *shift;
+
+	if (!*npages)
+		return -EINVAL;
+
+	*page_list = kmalloc(sizeof(u64) * *npages, GFP_KERNEL);
+	if (!*page_list)
+		return -ENOMEM;
+
+	n = 0;
+	for (i = 0; i < num_phys_buf; ++i)
+		for (j = 0;
+		     j < (buffer_list[i].size + (1ULL << *shift) - 1) >> *shift;
+		     ++j)
+			(*page_list)[n++] = cpu_to_be64(buffer_list[i].addr +
+			    ((u64) j << *shift));
+
+	PDBG("%s va 0x%llx mask 0x%llx shift %d len %lld pbl_size %d\n",
+	     __FUNCTION__, (unsigned long long) *iova_start,
+	     (unsigned long long) mask, *shift, (unsigned long long) *total_size,
+	     *npages);
+
+	return 0;
+
+}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
new file mode 100644
index 0000000..2aef122
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -0,0 +1,1202 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/byteorder.h>
+
+#include <rdma/iw_cm.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_smi.h>
+#include <rdma/ib_user_verbs.h>
+
+#include "cxio_hal.h"
+#include "iwch.h"
+#include "iwch_provider.h"
+#include "iwch_cm.h"
+#include "iwch_user.h"
+
+static int iwch_modify_port(struct ib_device *ibdev,
+			    u8 port, int port_modify_mask,
+			    struct ib_port_modify *props)
+{
+	return -ENOSYS;
+}
+
+static struct ib_ah *iwch_ah_create(struct ib_pd *pd,
+				    struct ib_ah_attr *ah_attr)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static int iwch_ah_destroy(struct ib_ah *ah)
+{
+	return -ENOSYS;
+}
+
+static int iwch_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+{
+	return -ENOSYS;
+}
+
+static int iwch_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+{
+	return -ENOSYS;
+}
+
+static int iwch_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)
+{
+	return -ENOSYS;
+}
+
+static int iwch_dealloc_ucontext(struct ib_ucontext *context)
+{
+	struct iwch_dev *rhp = to_iwch_dev(context->device);
+	struct iwch_ucontext *ucontext = to_iwch_ucontext(context);
+	struct iwch_mm_entry *mm, *tmp;
+
+	PDBG("%s context %p\n", __FUNCTION__, context);
+	list_for_each_entry_safe(mm, tmp, &ucontext->mmaps, entry)
+		kfree(mm);
+	cxio_release_ucontext(&rhp->rdev, &ucontext->uctx);
+	kfree(ucontext);
+	return 0;
+}
+
+static struct ib_ucontext *iwch_alloc_ucontext(struct ib_device *ibdev,
+					struct ib_udata *udata)
+{
+	struct iwch_ucontext *context;
+	struct iwch_dev *rhp = to_iwch_dev(ibdev);
+
+	PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
+	context = kzalloc(sizeof(*context), GFP_KERNEL);
+	if (!context)
+		return ERR_PTR(-ENOMEM);
+	cxio_init_ucontext(&rhp->rdev, &context->uctx);
+	INIT_LIST_HEAD(&context->mmaps);
+	spin_lock_init(&context->mmap_lock);
+	return &context->ibucontext;
+}
+
+static int iwch_destroy_cq(struct ib_cq *ib_cq)
+{
+	struct iwch_cq *chp;
+
+	PDBG("%s ib_cq %p\n", __FUNCTION__, ib_cq);
+	chp = to_iwch_cq(ib_cq);
+
+	remove_handle(chp->rhp, &chp->rhp->cqidr, chp->cq.cqid);
+	atomic_dec(&chp->refcnt);
+	wait_event(chp->wait, !atomic_read(&chp->refcnt));
+
+	cxio_destroy_cq(&chp->rhp->rdev, &chp->cq);
+	kfree(chp);
+	return 0;
+}
+
+static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries,
+			     struct ib_ucontext *ib_context,
+			     struct ib_udata *udata)
+{
+	struct iwch_dev *rhp;
+	struct iwch_cq *chp;
+	struct iwch_create_cq_resp uresp;
+	struct iwch_create_cq_req ureq;
+	struct iwch_ucontext *ucontext = NULL;
+
+	PDBG("%s ib_dev %p entries %d\n", __FUNCTION__, ibdev, entries);
+	rhp = to_iwch_dev(ibdev);
+	chp = kzalloc(sizeof(*chp), GFP_KERNEL);
+	if (!chp)
+		return ERR_PTR(-ENOMEM);
+
+	if (ib_context) {
+		ucontext = to_iwch_ucontext(ib_context);
+		if (!t3a_device(rhp)) {
+			if (ib_copy_from_udata(&ureq, udata, sizeof (ureq))) {
+				kfree(chp);
+				return ERR_PTR(-EFAULT);
+			}
+			chp->user_rptr_addr = (u32 __user *)(unsigned long)ureq.user_rptr_addr;
+		}
+	}
+
+	if (t3a_device(rhp)) {
+
+		/*
+		 * T3A: Add some fluff to handle extra CQEs inserted
+		 * for various errors.
+		 * Additional CQE possibilities:
+		 *      TERMINATE,
+		 *      incoming RDMA WRITE Failures
+		 *      incoming RDMA READ REQUEST FAILUREs
+		 * NOTE: We cannot ensure the CQ won't overflow.
+		 */
+		entries += 16;
+	}
+	entries = roundup_pow_of_two(entries);
+	chp->cq.size_log2 = ilog2(entries);
+
+	if (cxio_create_cq(&rhp->rdev, &chp->cq)) {
+		kfree(chp);
+		return ERR_PTR(-ENOMEM);
+	}
+	chp->rhp = rhp;
+	chp->ibcq.cqe = (1 << chp->cq.size_log2) - 1;
+	spin_lock_init(&chp->lock);
+	atomic_set(&chp->refcnt, 1);
+	init_waitqueue_head(&chp->wait);
+	insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid);
+
+	if (ucontext) {
+		struct iwch_mm_entry *mm;
+
+		mm = kmalloc(sizeof *mm, GFP_KERNEL);
+		if (!mm) {
+			iwch_destroy_cq(&chp->ibcq);
+			return ERR_PTR(-ENOMEM);
+		}
+		uresp.cqid = chp->cq.cqid;
+		uresp.size_log2 = chp->cq.size_log2;
+		spin_lock(&ucontext->mmap_lock);
+		uresp.key = ucontext->key;
+		ucontext->key += PAGE_SIZE;
+		spin_unlock(&ucontext->mmap_lock);
+		if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) {
+			kfree(mm);
+			iwch_destroy_cq(&chp->ibcq);
+			return ERR_PTR(-EFAULT);
+		}
+		mm->key = uresp.key;
+		mm->addr = virt_to_phys(chp->cq.queue);
+		mm->len = PAGE_ALIGN((1UL << uresp.size_log2) *
+					     sizeof (struct t3_cqe));
+		insert_mmap(ucontext, mm);
+	}
+	PDBG("created cqid 0x%0x chp %p size 0x%0x, dma_addr 0x%0llx\n",
+	     chp->cq.cqid, chp, (1 << chp->cq.size_log2),
+	     (unsigned long long) chp->cq.dma_addr);
+	return &chp->ibcq;
+}
+
+static int iwch_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
+{
+#ifdef notyet
+	struct iwch_cq *chp = to_iwch_cq(cq);
+	struct t3_cq oldcq, newcq;
+	int ret;
+
+	PDBG("%s ib_cq %p cqe %d\n", __FUNCTION__, cq, cqe);
+
+	/* We don't downsize... */
+	if (cqe <= cq->cqe)
+		return 0;
+
+	/* create new t3_cq with new size */
+	cqe = roundup_pow_of_two(cqe+1);
+	newcq.size_log2 = ilog2(cqe);
+
+	/* Dont allow resize to less than the current wce count */
+	if (cqe < Q_COUNT(chp->cq.rptr, chp->cq.wptr)) {
+		return -ENOMEM;
+	}
+
+	/* Quiesce all QPs using this CQ */
+	ret = iwch_quiesce_qps(chp);
+	if (ret) {
+		return ret;
+	}
+
+	ret = cxio_create_cq(&chp->rhp->rdev, &newcq);
+	if (ret) {
+		return ret;
+	}
+
+	/* copy CQEs */
+	memcpy(newcq.queue, chp->cq.queue, (1 << chp->cq.size_log2) *
+				        sizeof(struct t3_cqe));
+
+	/* old iwch_qp gets new t3_cq but keeps old cqid */
+	oldcq = chp->cq;
+	chp->cq = newcq;
+	chp->cq.cqid = oldcq.cqid;
+
+	/* resize new t3_cq to update the HW context */
+	ret = cxio_resize_cq(&chp->rhp->rdev, &chp->cq);
+	if (ret) {
+		chp->cq = oldcq;
+		return ret;
+	}
+	chp->ibcq.cqe = (1<<chp->cq.size_log2) - 1;
+
+	/* destroy old t3_cq */
+	oldcq.cqid = newcq.cqid;
+	ret = cxio_destroy_cq(&chp->rhp->rdev, &oldcq);
+	if (ret) {
+		printk(KERN_ERR MOD "%s - cxio_destroy_cq failed %d\n",
+			__FUNCTION__, ret);
+	}
+
+	/* add user hooks here */
+
+	/* resume qps */
+	ret = iwch_resume_qps(chp);
+	return ret;
+#else
+	return -ENOSYS;
+#endif
+}
+
+static int iwch_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
+{
+	struct iwch_dev *rhp;
+	struct iwch_cq *chp;
+	enum t3_cq_opcode cq_op;
+	int err;
+	unsigned long flag;
+	u32 rptr;
+
+	chp = to_iwch_cq(ibcq);
+	rhp = chp->rhp;
+	if (notify == IB_CQ_SOLICITED)
+		cq_op = CQ_ARM_SE;
+	else
+		cq_op = CQ_ARM_AN;
+	if (chp->user_rptr_addr) {
+		if (get_user(rptr, chp->user_rptr_addr))
+			return -EFAULT;
+		spin_lock_irqsave(&chp->lock, flag);
+		chp->cq.rptr = rptr;
+	} else
+		spin_lock_irqsave(&chp->lock, flag);
+	PDBG("%s rptr 0x%x\n", __FUNCTION__, chp->cq.rptr);
+	err = cxio_hal_cq_op(&rhp->rdev, &chp->cq, cq_op, 0);
+	spin_unlock_irqrestore(&chp->lock, flag);
+	if (err)
+		printk(KERN_ERR MOD "Error %d rearming CQID 0x%x\n", err,
+		       chp->cq.cqid);
+	return err;
+}
+
+static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+{
+	int len = vma->vm_end - vma->vm_start;
+	u32 key = vma->vm_pgoff << PAGE_SHIFT;
+	struct cxio_rdev *rdev_p;
+	int ret = 0;
+	struct iwch_mm_entry *mm;
+	struct iwch_ucontext *ucontext;
+
+	PDBG("%s pgoff 0x%lx key 0x%x len %d\n", __FUNCTION__, vma->vm_pgoff,
+	     key, len);
+
+	if (vma->vm_start & (PAGE_SIZE-1)) {
+	        return -EINVAL;
+	}
+
+	rdev_p = &(to_iwch_dev(context->device)->rdev);
+	ucontext = to_iwch_ucontext(context);
+
+	mm = remove_mmap(ucontext, key, len);
+	if (!mm)
+		return -EINVAL;
+	kfree(mm);
+
+	if ((mm->addr >= rdev_p->rnic_info.udbell_physbase) &&
+	    (mm->addr < (rdev_p->rnic_info.udbell_physbase +
+		       rdev_p->rnic_info.udbell_len))) {
+
+		/*
+		 * Map T3 DB register.
+		 */
+		if (vma->vm_flags & VM_READ) {
+			return -EPERM;
+		}
+
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+		vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
+		vma->vm_flags &= ~VM_MAYREAD;
+		ret = io_remap_pfn_range(vma, vma->vm_start,
+					 mm->addr >> PAGE_SHIFT,
+				         len, vma->vm_page_prot);
+	} else {
+
+		/*
+		 * Map WQ or CQ contig dma memory...
+		 */
+		ret = remap_pfn_range(vma, vma->vm_start,
+				      mm->addr >> PAGE_SHIFT,
+				      len, vma->vm_page_prot);
+	}
+
+	return ret;
+}
+
+static int iwch_deallocate_pd(struct ib_pd *pd)
+{
+	struct iwch_dev *rhp;
+	struct iwch_pd *php;
+
+	php = to_iwch_pd(pd);
+	rhp = php->rhp;
+	PDBG("%s ibpd %p pdid 0x%x\n", __FUNCTION__, pd, php->pdid);
+	cxio_hal_put_pdid(rhp->rdev.rscp, php->pdid);
+	kfree(php);
+	return 0;
+}
+
+static struct ib_pd *iwch_allocate_pd(struct ib_device *ibdev,
+			       struct ib_ucontext *context,
+			       struct ib_udata *udata)
+{
+	struct iwch_pd *php;
+	u32 pdid;
+	struct iwch_dev *rhp;
+
+	PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
+	rhp = (struct iwch_dev *) ibdev;
+	pdid = cxio_hal_get_pdid(rhp->rdev.rscp);
+	if (!pdid)
+		return ERR_PTR(-EINVAL);
+	php = kzalloc(sizeof(*php), GFP_KERNEL);
+	if (!php) {
+		cxio_hal_put_pdid(rhp->rdev.rscp, pdid);
+		return ERR_PTR(-ENOMEM);
+	}
+	php->pdid = pdid;
+	php->rhp = rhp;
+	if (context) {
+		if (ib_copy_to_udata(udata, &php->pdid, sizeof (__u32))) {
+			iwch_deallocate_pd(&php->ibpd);
+			return ERR_PTR(-EFAULT);
+		}
+	}
+	PDBG("%s pdid 0x%0x ptr 0x%p\n", __FUNCTION__, pdid, php);
+	return &php->ibpd;
+}
+
+static int iwch_dereg_mr(struct ib_mr *ib_mr)
+{
+	struct iwch_dev *rhp;
+	struct iwch_mr *mhp;
+	u32 mmid;
+
+	PDBG("%s ib_mr %p\n", __FUNCTION__, ib_mr);
+	/* There can be no memory windows */
+	if (atomic_read(&ib_mr->usecnt))
+		return -EINVAL;
+
+	mhp = to_iwch_mr(ib_mr);
+	rhp = mhp->rhp;
+	mmid = mhp->attr.stag >> 8;
+	cxio_dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
+		       mhp->attr.pbl_addr);
+	remove_handle(rhp, &rhp->mmidr, mmid);
+	if (mhp->kva)
+		kfree((void *) (unsigned long) mhp->kva);
+	PDBG("%s mmid 0x%x ptr %p\n", __FUNCTION__, mmid, mhp);
+	kfree(mhp);
+	return 0;
+}
+
+static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd,
+					struct ib_phys_buf *buffer_list,
+					int num_phys_buf,
+					int acc,
+					u64 *iova_start)
+{
+	__be64 *page_list;
+	int shift;
+	u64 total_size;
+	int npages;
+	struct iwch_dev *rhp;
+	struct iwch_pd *php;
+	struct iwch_mr *mhp;
+	int ret;
+
+	PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
+	php = to_iwch_pd(pd);
+	rhp = php->rhp;
+
+	acc = iwch_convert_access(acc);
+
+
+	mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
+	if (!mhp)
+		return ERR_PTR(-ENOMEM);
+
+	/* First check that we have enough alignment */
+	if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (num_phys_buf > 1 &&
+	    ((buffer_list[0].addr + buffer_list[0].size) & ~PAGE_MASK)) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	ret = build_phys_page_list(buffer_list, num_phys_buf, iova_start,
+				   &total_size, &npages, &shift, &page_list);
+	if (ret)
+		goto err;
+
+	mhp->rhp = rhp;
+	mhp->attr.pdid = php->pdid;
+	mhp->attr.zbva = 0;
+
+	/* NOTE: TPT perms are backwards from BIND WR perms! */
+	mhp->attr.perms = (acc & 0x1) << 3;
+	mhp->attr.perms |= (acc & 0x2) << 1;
+	mhp->attr.perms |= (acc & 0x4) >> 1;
+	mhp->attr.perms |= (acc & 0x8) >> 3;
+
+	mhp->attr.va_fbo = *iova_start;
+	mhp->attr.page_size = shift - 12;
+
+	mhp->attr.len = (u32) total_size;
+	mhp->attr.pbl_size = npages;
+	ret = iwch_register_mem(rhp, php, mhp, shift, page_list);
+	kfree(page_list);
+	if (ret) {
+		goto err;
+	}
+	return &mhp->ibmr;
+err:
+	kfree(mhp);
+	return ERR_PTR(ret);
+
+}
+
+static int iwch_reregister_phys_mem(struct ib_mr *mr,
+				     int mr_rereg_mask,
+				     struct ib_pd *pd,
+	                             struct ib_phys_buf *buffer_list,
+	                             int num_phys_buf,
+	                             int acc, u64 * iova_start)
+{
+
+	struct iwch_mr mh, *mhp;
+	struct iwch_pd *php;
+	struct iwch_dev *rhp;
+	int new_acc;
+	__be64 *page_list = NULL;
+	int shift = 0;
+	u64 total_size;
+	int npages;
+	int ret;
+
+	PDBG("%s ib_mr %p ib_pd %p\n", __FUNCTION__, mr, pd);
+
+	/* There can be no memory windows */
+	if (atomic_read(&mr->usecnt))
+		return -EINVAL;
+
+	mhp = to_iwch_mr(mr);
+	rhp = mhp->rhp;
+	php = to_iwch_pd(mr->pd);
+
+	/* make sure we are on the same adapter */
+	if (rhp != php->rhp)
+		return -EINVAL;
+
+	new_acc = mhp->attr.perms;
+
+	memcpy(&mh, mhp, sizeof *mhp);
+
+	if (mr_rereg_mask & IB_MR_REREG_PD)
+		php = to_iwch_pd(pd);
+	if (mr_rereg_mask & IB_MR_REREG_ACCESS)
+		mh.attr.perms = iwch_convert_access(acc);
+	if (mr_rereg_mask & IB_MR_REREG_TRANS)
+		ret = build_phys_page_list(buffer_list, num_phys_buf,
+					   iova_start,
+					   &total_size, &npages,
+					   &shift, &page_list);
+
+	ret = iwch_reregister_mem(rhp, php, &mh, shift, page_list, npages);
+	kfree(page_list);
+	if (ret) {
+		return ret;
+	}
+	if (mr_rereg_mask & IB_MR_REREG_PD)
+		mhp->attr.pdid = php->pdid;
+	if (mr_rereg_mask & IB_MR_REREG_ACCESS)
+		mhp->attr.perms = acc;
+	if (mr_rereg_mask & IB_MR_REREG_TRANS) {
+		mhp->attr.zbva = 0;
+		mhp->attr.va_fbo = *iova_start;
+		mhp->attr.page_size = shift - 12;
+		mhp->attr.len = (u32) total_size;
+		mhp->attr.pbl_size = npages;
+	}
+
+	return 0;
+}
+
+
+static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
+				      int acc, struct ib_udata *udata)
+{
+	__be64 *pages;
+	int shift, n, len;
+	int i, j, k;
+	int err = 0;
+	struct ib_umem_chunk *chunk;
+	struct iwch_dev *rhp;
+	struct iwch_pd *php;
+	struct iwch_mr *mhp;
+	struct iwch_reg_user_mr_resp uresp;
+
+	PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
+	shift = ffs(region->page_size) - 1;
+
+	php = to_iwch_pd(pd);
+	rhp = php->rhp;
+	mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
+	if (!mhp)
+		return ERR_PTR(-ENOMEM);
+
+	n = 0;
+	list_for_each_entry(chunk, &region->chunk_list, list)
+		n += chunk->nents;
+
+	pages = kmalloc(n * sizeof(u64), GFP_KERNEL);
+	if (!pages) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	acc = iwch_convert_access(acc);
+
+	i = n = 0;
+
+	list_for_each_entry(chunk, &region->chunk_list, list)
+		for (j = 0; j < chunk->nmap; ++j) {
+			len = sg_dma_len(&chunk->page_list[j]) >> shift;
+			for (k = 0; k < len; ++k) {
+				pages[i++] = cpu_to_be64(sg_dma_address(
+					&chunk->page_list[j]) +
+					region->page_size * k);
+			}
+		}
+
+	mhp->rhp = rhp;
+	mhp->attr.pdid = php->pdid;
+	mhp->attr.zbva = 0;
+	mhp->attr.perms = (acc & 0x1) << 3;
+	mhp->attr.perms |= (acc & 0x2) << 1;
+	mhp->attr.perms |= (acc & 0x4) >> 1;
+	mhp->attr.perms |= (acc & 0x8) >> 3;
+	mhp->attr.va_fbo = region->virt_base;
+	mhp->attr.page_size = shift - 12;
+	mhp->attr.len = (u32) region->length;
+	mhp->attr.pbl_size = i;
+	err = iwch_register_mem(rhp, php, mhp, shift, pages);
+	kfree(pages);
+	if (err)
+		goto err;
+
+	if (udata && t3b_device(rhp)) {
+		uresp.pbl_addr = (mhp->attr.pbl_addr -
+	                         rhp->rdev.rnic_info.pbl_base) >> 3;
+		PDBG("%s user resp pbl_addr 0x%x\n", __FUNCTION__,
+		     uresp.pbl_addr);
+
+		if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) {
+			iwch_dereg_mr(&mhp->ibmr);
+			err = -EFAULT;
+			goto err;
+		}
+	}
+
+	return &mhp->ibmr;
+
+err:
+	kfree(mhp);
+	return ERR_PTR(err);
+}
+
+static struct ib_mr *iwch_get_dma_mr(struct ib_pd *pd, int acc)
+{
+	struct ib_phys_buf bl;
+	u64 kva;
+	struct ib_mr *ibmr;
+
+	PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
+
+	/*
+	 * T3 only supports 32 bits of size.
+	 */
+	bl.size = 0xffffffff;
+	bl.addr = 0;
+	kva = 0;
+	ibmr = iwch_register_phys_mem(pd, &bl, 1, acc, &kva);
+	return ibmr;
+}
+
+static struct ib_mw *iwch_alloc_mw(struct ib_pd *pd)
+{
+	struct iwch_dev *rhp;
+	struct iwch_pd *php;
+	struct iwch_mw *mhp;
+	u32 mmid;
+	u32 stag = 0;
+	int ret;
+
+	php = to_iwch_pd(pd);
+	rhp = php->rhp;
+	mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
+	if (!mhp)
+		return ERR_PTR(-ENOMEM);
+	ret = cxio_allocate_window(&rhp->rdev, &stag, php->pdid);
+	if (ret) {
+		kfree(mhp);
+		return ERR_PTR(ret);
+	}
+	mhp->rhp = rhp;
+	mhp->attr.pdid = php->pdid;
+	mhp->attr.type = TPT_MW;
+	mhp->attr.stag = stag;
+	mmid = (stag) >> 8;
+	insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+	PDBG("%s mmid 0x%x mhp %p stag 0x%x\n", __FUNCTION__, mmid, mhp, stag);
+	return &(mhp->ibmw);
+}
+
+static int iwch_dealloc_mw(struct ib_mw *mw)
+{
+	struct iwch_dev *rhp;
+	struct iwch_mw *mhp;
+	u32 mmid;
+
+	mhp = to_iwch_mw(mw);
+	rhp = mhp->rhp;
+	mmid = (mw->rkey) >> 8;
+	cxio_deallocate_window(&rhp->rdev, mhp->attr.stag);
+	remove_handle(rhp, &rhp->mmidr, mmid);
+	kfree(mhp);
+	PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __FUNCTION__, mw, mmid, mhp);
+	return 0;
+}
+
+static int iwch_destroy_qp(struct ib_qp *ib_qp)
+{
+	struct iwch_dev *rhp;
+	struct iwch_qp *qhp;
+	struct iwch_qp_attributes attrs;
+	struct iwch_ucontext *ucontext;
+
+	qhp = to_iwch_qp(ib_qp);
+	rhp = qhp->rhp;
+
+	if (qhp->attr.state == IWCH_QP_STATE_RTS) {
+		attrs.next_state = IWCH_QP_STATE_ERROR;
+		iwch_modify_qp(rhp, qhp, IWCH_QP_ATTR_NEXT_STATE, &attrs, 0);
+	}
+	wait_event(qhp->wait, !qhp->ep);
+
+	remove_handle(rhp, &rhp->qpidr, qhp->wq.qpid);
+
+	atomic_dec(&qhp->refcnt);
+	wait_event(qhp->wait, !atomic_read(&qhp->refcnt));
+
+	ucontext = ib_qp->uobject ? to_iwch_ucontext(ib_qp->uobject->context)
+				  : NULL;
+	cxio_destroy_qp(&rhp->rdev, &qhp->wq,
+			ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
+
+	PDBG("%s ib_qp %p qpid 0x%0x qhp %p\n", __FUNCTION__,
+	     ib_qp, qhp->wq.qpid, qhp);
+	kfree(qhp);
+	return 0;
+}
+
+static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
+			     struct ib_qp_init_attr *attrs,
+			     struct ib_udata *udata)
+{
+	struct iwch_dev *rhp;
+	struct iwch_qp *qhp;
+	struct iwch_pd *php;
+	struct iwch_cq *schp;
+	struct iwch_cq *rchp;
+	struct iwch_create_qp_resp uresp;
+	int wqsize, sqsize, rqsize;
+	struct iwch_ucontext *ucontext;
+
+	PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
+	if (attrs->qp_type != IB_QPT_RC)
+		return ERR_PTR(-EINVAL);
+	php = to_iwch_pd(pd);
+	rhp = php->rhp;
+	schp = get_chp(rhp, ((struct iwch_cq *) attrs->send_cq)->cq.cqid);
+	rchp = get_chp(rhp, ((struct iwch_cq *) attrs->recv_cq)->cq.cqid);
+	if (!schp || !rchp)
+		return ERR_PTR(-EINVAL);
+
+	/* The RQT size must be # of entries + 1 rounded up to a power of two */
+	rqsize = roundup_pow_of_two(attrs->cap.max_recv_wr);
+	if (rqsize == attrs->cap.max_recv_wr)
+		rqsize = roundup_pow_of_two(attrs->cap.max_recv_wr+1);
+
+	/* T3 doesn't support RQT depth < 16 */
+	if (rqsize < 16)
+		rqsize = 16;
+
+	if (rqsize > T3_MAX_RQ_SIZE)
+		return ERR_PTR(-EINVAL);
+
+	/*
+	 * NOTE: The SQ and total WQ sizes don't need to be
+	 * a power of two.  However, all the code assumes
+	 * they are. EG: Q_FREECNT() and friends.
+	 */
+	sqsize = roundup_pow_of_two(attrs->cap.max_send_wr);
+	wqsize = roundup_pow_of_two(rqsize + sqsize);
+	PDBG("%s wqsize %d sqsize %d rqsize %d\n", __FUNCTION__,
+	     wqsize, sqsize, rqsize);
+	qhp = kzalloc(sizeof(*qhp), GFP_KERNEL);
+	if (!qhp)
+		return ERR_PTR(-ENOMEM);
+	qhp->wq.size_log2 = ilog2(wqsize);
+	qhp->wq.rq_size_log2 = ilog2(rqsize);
+	qhp->wq.sq_size_log2 = ilog2(sqsize);
+	ucontext = pd->uobject ? to_iwch_ucontext(pd->uobject->context) : NULL;
+	if (cxio_create_qp(&rhp->rdev, !udata, &qhp->wq,
+			   ucontext ? &ucontext->uctx : &rhp->rdev.uctx)) {
+		kfree(qhp);
+		return ERR_PTR(-ENOMEM);
+	}
+	attrs->cap.max_recv_wr = rqsize - 1;
+	attrs->cap.max_send_wr = sqsize;
+	qhp->rhp = rhp;
+	qhp->attr.pd = php->pdid;
+	qhp->attr.scq = ((struct iwch_cq *) attrs->send_cq)->cq.cqid;
+	qhp->attr.rcq = ((struct iwch_cq *) attrs->recv_cq)->cq.cqid;
+	qhp->attr.sq_num_entries = attrs->cap.max_send_wr;
+	qhp->attr.rq_num_entries = attrs->cap.max_recv_wr;
+	qhp->attr.sq_max_sges = attrs->cap.max_send_sge;
+	qhp->attr.sq_max_sges_rdma_write = attrs->cap.max_send_sge;
+	qhp->attr.rq_max_sges = attrs->cap.max_recv_sge;
+	qhp->attr.state = IWCH_QP_STATE_IDLE;
+	qhp->attr.next_state = IWCH_QP_STATE_IDLE;
+
+	/*
+	 * XXX - These don't get passed in from the openib user
+	 * at create time.  The CM sets them via a QP modify.
+	 * Need to fix...  I think the CM should
+	 */
+	qhp->attr.enable_rdma_read = 1;
+	qhp->attr.enable_rdma_write = 1;
+	qhp->attr.enable_bind = 1;
+	qhp->attr.max_ord = 1;
+	qhp->attr.max_ird = 1;
+
+	spin_lock_init(&qhp->lock);
+	init_waitqueue_head(&qhp->wait);
+	atomic_set(&qhp->refcnt, 1);
+	insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.qpid);
+
+	if (udata) {
+
+		struct iwch_mm_entry *mm1, *mm2;
+
+		mm1 = kmalloc(sizeof *mm1, GFP_KERNEL);
+		if (!mm1) {
+			iwch_destroy_qp(&qhp->ibqp);
+			return ERR_PTR(-ENOMEM);
+		}
+
+		mm2 = kmalloc(sizeof *mm2, GFP_KERNEL);
+		if (!mm2) {
+			kfree(mm1);
+			iwch_destroy_qp(&qhp->ibqp);
+			return ERR_PTR(-ENOMEM);
+		}
+
+		uresp.qpid = qhp->wq.qpid;
+		uresp.size_log2 = qhp->wq.size_log2;
+		uresp.sq_size_log2 = qhp->wq.sq_size_log2;
+		uresp.rq_size_log2 = qhp->wq.rq_size_log2;
+		spin_lock(&ucontext->mmap_lock);
+		uresp.key = ucontext->key;
+		ucontext->key += PAGE_SIZE;
+		uresp.db_key = ucontext->key;
+		ucontext->key += PAGE_SIZE;
+		spin_unlock(&ucontext->mmap_lock);
+		if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) {
+			kfree(mm1);
+			kfree(mm2);
+			iwch_destroy_qp(&qhp->ibqp);
+			return ERR_PTR(-EFAULT);
+		}
+		mm1->key = uresp.key;
+		mm1->addr = virt_to_phys(qhp->wq.queue);
+		mm1->len = PAGE_ALIGN(wqsize * sizeof (union t3_wr));
+		insert_mmap(ucontext, mm1);
+		mm2->key = uresp.db_key;
+		mm2->addr = qhp->wq.udb & PAGE_MASK;
+		mm2->len = PAGE_SIZE;
+		insert_mmap(ucontext, mm2);
+	}
+	qhp->ibqp.qp_num = qhp->wq.qpid;
+	init_timer(&(qhp->timer));
+	PDBG("%s sq_num_entries %d, rq_num_entries %d "
+	     "qpid 0x%0x qhp %p dma_addr 0x%llx size %d\n",
+	     __FUNCTION__, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
+	     qhp->wq.qpid, qhp, (unsigned long long) qhp->wq.dma_addr,
+	     1 << qhp->wq.size_log2);
+	return &qhp->ibqp;
+}
+
+static int iwch_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		      int attr_mask, struct ib_udata *udata)
+{
+	struct iwch_dev *rhp;
+	struct iwch_qp *qhp;
+	enum iwch_qp_attr_mask mask = 0;
+	struct iwch_qp_attributes attrs;
+
+	PDBG("%s ib_qp %p\n", __FUNCTION__, ibqp);
+
+	/* iwarp does not support the RTR state */
+	if ((attr_mask & IB_QP_STATE) && (attr->qp_state == IB_QPS_RTR))
+		attr_mask &= ~IB_QP_STATE;
+
+	/* Make sure we still have something left to do */
+	if (!attr_mask)
+		return 0;
+
+	memset(&attrs, 0, sizeof attrs);
+	qhp = to_iwch_qp(ibqp);
+	rhp = qhp->rhp;
+
+	attrs.next_state = iwch_convert_state(attr->qp_state);
+	attrs.enable_rdma_read = (attr->qp_access_flags &
+			       IB_ACCESS_REMOTE_READ) ?  1 : 0;
+	attrs.enable_rdma_write = (attr->qp_access_flags &
+				IB_ACCESS_REMOTE_WRITE) ? 1 : 0;
+	attrs.enable_bind = (attr->qp_access_flags & IB_ACCESS_MW_BIND) ? 1 : 0;
+
+
+	mask |= (attr_mask & IB_QP_STATE) ? IWCH_QP_ATTR_NEXT_STATE : 0;
+	mask |= (attr_mask & IB_QP_ACCESS_FLAGS) ?
+			(IWCH_QP_ATTR_ENABLE_RDMA_READ |
+			 IWCH_QP_ATTR_ENABLE_RDMA_WRITE |
+			 IWCH_QP_ATTR_ENABLE_RDMA_BIND) : 0;
+
+	return iwch_modify_qp(rhp, qhp, mask, &attrs, 0);
+}
+
+void iwch_qp_add_ref(struct ib_qp *qp)
+{
+	PDBG("%s ib_qp %p\n", __FUNCTION__, qp);
+	atomic_inc(&(to_iwch_qp(qp)->refcnt));
+}
+
+void iwch_qp_rem_ref(struct ib_qp *qp)
+{
+	PDBG("%s ib_qp %p\n", __FUNCTION__, qp);
+	if (atomic_dec_and_test(&(to_iwch_qp(qp)->refcnt)))
+	        wake_up(&(to_iwch_qp(qp)->wait));
+}
+
+struct ib_qp *iwch_get_qp(struct ib_device *dev, int qpn)
+{
+	PDBG("%s ib_dev %p qpn 0x%x\n", __FUNCTION__, dev, qpn);
+	return (struct ib_qp *)get_qhp(to_iwch_dev(dev), qpn);
+}
+
+
+static int iwch_query_pkey(struct ib_device *ibdev,
+			   u8 port, u16 index, u16 * pkey)
+{
+	PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
+	*pkey = 0;
+	return 0;
+}
+
+static int iwch_query_gid(struct ib_device *ibdev, u8 port,
+			  int index, union ib_gid *gid)
+{
+	struct iwch_dev *dev;
+
+	PDBG("%s ibdev %p, port %d, index %d, gid %p\n",
+	       __FUNCTION__, ibdev, port, index, gid);
+	dev = to_iwch_dev(ibdev);
+	BUG_ON(port == 0 || port > 2);
+	memset(&(gid->raw[0]), 0, sizeof(gid->raw));
+	memcpy(&(gid->raw[0]), dev->rdev.port_info.lldevs[port-1]->dev_addr, 6);
+	return 0;
+}
+
+static int iwch_query_device(struct ib_device *ibdev,
+			     struct ib_device_attr *props)
+{
+
+	struct iwch_dev *dev;
+	PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
+
+	dev = to_iwch_dev(ibdev);
+	memset(props, 0, sizeof *props);
+	memcpy(&props->sys_image_guid, dev->rdev.t3cdev_p->lldev->dev_addr, 6);
+	props->device_cap_flags = dev->device_cap_flags;
+	props->vendor_id = (u32)dev->rdev.rnic_info.pdev->vendor;
+	props->vendor_part_id = (u32)dev->rdev.rnic_info.pdev->device;
+	props->max_mr_size = ~0ull;
+	props->max_qp = dev->attr.max_qps;
+	props->max_qp_wr = dev->attr.max_wrs;
+	props->max_sge = dev->attr.max_sge_per_wr;
+	props->max_sge_rd = 1;
+	props->max_qp_rd_atom = dev->attr.max_rdma_reads_per_qp;
+	props->max_cq = dev->attr.max_cqs;
+	props->max_cqe = dev->attr.max_cqes_per_cq;
+	props->max_mr = dev->attr.max_mem_regs;
+	props->max_pd = dev->attr.max_pds;
+	props->local_ca_ack_delay = 0;
+
+	return 0;
+}
+
+static int iwch_query_port(struct ib_device *ibdev,
+			   u8 port, struct ib_port_attr *props)
+{
+	PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
+	props->max_mtu = IB_MTU_4096;
+	props->lid = 0;
+	props->lmc = 0;
+	props->sm_lid = 0;
+	props->sm_sl = 0;
+	props->state = IB_PORT_ACTIVE;
+	props->phys_state = 0;
+	props->port_cap_flags =
+	    IB_PORT_CM_SUP |
+	    IB_PORT_SNMP_TUNNEL_SUP |
+	    IB_PORT_REINIT_SUP |
+	    IB_PORT_DEVICE_MGMT_SUP |
+	    IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP;
+	props->gid_tbl_len = 1;
+	props->pkey_tbl_len = 1;
+	props->qkey_viol_cntr = 0;
+	props->active_width = 2;
+	props->active_speed = 2;
+	props->max_msg_sz = -1;
+
+	return 0;
+}
+
+static ssize_t show_rev(struct class_device *cdev, char *buf)
+{
+	struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+					    ibdev.class_dev);
+	PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
+	return sprintf(buf, "%d\n", dev->rdev.t3cdev_p->type);
+}
+
+static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
+{
+	struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+					    ibdev.class_dev);
+	struct ethtool_drvinfo info;
+	struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
+
+	PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
+	lldev->ethtool_ops->get_drvinfo(lldev, &info);
+	return sprintf(buf, "%s\n", info.fw_version);
+}
+
+static ssize_t show_hca(struct class_device *cdev, char *buf)
+{
+	struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+					    ibdev.class_dev);
+	struct ethtool_drvinfo info;
+	struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
+
+	PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
+	lldev->ethtool_ops->get_drvinfo(lldev, &info);
+	return sprintf(buf, "%s\n", info.driver);
+}
+
+static ssize_t show_board(struct class_device *cdev, char *buf)
+{
+	struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+					    ibdev.class_dev);
+	PDBG("%s class dev 0x%p\n", __FUNCTION__, dev);
+	return sprintf(buf, "%x.%x\n", dev->rdev.rnic_info.pdev->vendor,
+		                       dev->rdev.rnic_info.pdev->device);
+}
+
+static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
+
+static struct class_device_attribute *iwch_class_attributes[] = {
+	&class_device_attr_hw_rev,
+	&class_device_attr_fw_ver,
+	&class_device_attr_hca_type,
+	&class_device_attr_board_id
+};
+
+int iwch_register_device(struct iwch_dev *dev)
+{
+	int ret;
+	int i;
+
+	PDBG("%s iwch_dev %p\n", __FUNCTION__, dev);
+	strlcpy(dev->ibdev.name, "cxgb3_%d", IB_DEVICE_NAME_MAX);
+	memset(&dev->ibdev.node_guid, 0, sizeof(dev->ibdev.node_guid));
+	memcpy(&dev->ibdev.node_guid, dev->rdev.t3cdev_p->lldev->dev_addr, 6);
+	dev->ibdev.owner = THIS_MODULE;
+	dev->device_cap_flags =
+	    (IB_DEVICE_ZERO_STAG |
+	     IB_DEVICE_SEND_W_INV | IB_DEVICE_MEM_WINDOW);
+
+	dev->ibdev.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_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_DESTROY_CQ) |
+	    (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |
+	    (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
+	    (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
+	    (1ull << IB_USER_VERBS_CMD_POLL_CQ) |
+	    (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
+	    (1ull << IB_USER_VERBS_CMD_POST_SEND) |
+	    (1ull << IB_USER_VERBS_CMD_POST_RECV);
+	dev->ibdev.node_type = RDMA_NODE_RNIC;
+	memcpy(dev->ibdev.node_desc, IWCH_NODE_DESC, sizeof(IWCH_NODE_DESC));
+	dev->ibdev.phys_port_cnt = dev->rdev.port_info.nports;
+	dev->ibdev.dma_device = &(dev->rdev.rnic_info.pdev->dev);
+	dev->ibdev.class_dev.dev = &(dev->rdev.rnic_info.pdev->dev);
+	dev->ibdev.query_device = iwch_query_device;
+	dev->ibdev.query_port = iwch_query_port;
+	dev->ibdev.modify_port = iwch_modify_port;
+	dev->ibdev.query_pkey = iwch_query_pkey;
+	dev->ibdev.query_gid = iwch_query_gid;
+	dev->ibdev.alloc_ucontext = iwch_alloc_ucontext;
+	dev->ibdev.dealloc_ucontext = iwch_dealloc_ucontext;
+	dev->ibdev.mmap = iwch_mmap;
+	dev->ibdev.alloc_pd = iwch_allocate_pd;
+	dev->ibdev.dealloc_pd = iwch_deallocate_pd;
+	dev->ibdev.create_ah = iwch_ah_create;
+	dev->ibdev.destroy_ah = iwch_ah_destroy;
+	dev->ibdev.create_qp = iwch_create_qp;
+	dev->ibdev.modify_qp = iwch_ib_modify_qp;
+	dev->ibdev.destroy_qp = iwch_destroy_qp;
+	dev->ibdev.create_cq = iwch_create_cq;
+	dev->ibdev.destroy_cq = iwch_destroy_cq;
+	dev->ibdev.resize_cq = iwch_resize_cq;
+	dev->ibdev.poll_cq = iwch_poll_cq;
+	dev->ibdev.get_dma_mr = iwch_get_dma_mr;
+	dev->ibdev.reg_phys_mr = iwch_register_phys_mem;
+	dev->ibdev.rereg_phys_mr = iwch_reregister_phys_mem;
+	dev->ibdev.reg_user_mr = iwch_reg_user_mr;
+	dev->ibdev.dereg_mr = iwch_dereg_mr;
+	dev->ibdev.alloc_mw = iwch_alloc_mw;
+	dev->ibdev.bind_mw = iwch_bind_mw;
+	dev->ibdev.dealloc_mw = iwch_dealloc_mw;
+
+	dev->ibdev.attach_mcast = iwch_multicast_attach;
+	dev->ibdev.detach_mcast = iwch_multicast_detach;
+	dev->ibdev.process_mad = iwch_process_mad;
+
+	dev->ibdev.req_notify_cq = iwch_arm_cq;
+	dev->ibdev.post_send = iwch_post_send;
+	dev->ibdev.post_recv = iwch_post_receive;
+
+
+	dev->ibdev.iwcm =
+	    (struct iw_cm_verbs *) kmalloc(sizeof(struct iw_cm_verbs),
+					   GFP_KERNEL);
+	dev->ibdev.iwcm->connect = iwch_connect;
+	dev->ibdev.iwcm->accept = iwch_accept_cr;
+	dev->ibdev.iwcm->reject = iwch_reject_cr;
+	dev->ibdev.iwcm->create_listen = iwch_create_listen;
+	dev->ibdev.iwcm->destroy_listen = iwch_destroy_listen;
+	dev->ibdev.iwcm->add_ref = iwch_qp_add_ref;
+	dev->ibdev.iwcm->rem_ref = iwch_qp_rem_ref;
+	dev->ibdev.iwcm->get_qp = iwch_get_qp;
+
+	ret = ib_register_device(&dev->ibdev);
+	if (ret)
+		goto bail1;
+
+	for (i = 0; i < ARRAY_SIZE(iwch_class_attributes); ++i) {
+		ret = class_device_create_file(&dev->ibdev.class_dev,
+					       iwch_class_attributes[i]);
+		if (ret) {
+			goto bail2;
+		}
+	}
+	return 0;
+bail2:
+	ib_unregister_device(&dev->ibdev);
+bail1:
+	return ret;
+}
+
+void iwch_unregister_device(struct iwch_dev *dev)
+{
+	int i;
+
+	PDBG("%s iwch_dev %p\n", __FUNCTION__, dev);
+	for (i = 0; i < ARRAY_SIZE(iwch_class_attributes); ++i)
+		class_device_remove_file(&dev->ibdev.class_dev,
+					 iwch_class_attributes[i]);
+	ib_unregister_device(&dev->ibdev);
+	return;
+}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
new file mode 100644
index 0000000..2af3e93
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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 __IWCH_PROVIDER_H__
+#define __IWCH_PROVIDER_H__
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <rdma/ib_verbs.h>
+#include <asm/types.h>
+#include "t3cdev.h"
+#include "iwch.h"
+#include "cxio_wr.h"
+#include "cxio_hal.h"
+
+struct iwch_pd {
+	struct ib_pd ibpd;
+	u32 pdid;
+	struct iwch_dev *rhp;
+};
+
+static inline struct iwch_pd *to_iwch_pd(struct ib_pd *ibpd)
+{
+	return container_of(ibpd, struct iwch_pd, ibpd);
+}
+
+struct tpt_attributes {
+	u32 stag;
+	u32 state:1;
+	u32 type:2;
+	u32 rsvd:1;
+	enum tpt_mem_perm perms;
+	u32 remote_invaliate_disable:1;
+	u32 zbva:1;
+	u32 mw_bind_enable:1;
+	u32 page_size:5;
+
+	u32 pdid;
+	u32 qpid;
+	u32 pbl_addr;
+	u32 len;
+	u64 va_fbo;
+	u32 pbl_size;
+};
+
+struct iwch_mr {
+	struct ib_mr ibmr;
+	struct iwch_dev *rhp;
+	u64 kva;
+	struct tpt_attributes attr;
+};
+
+typedef struct iwch_mw iwch_mw_handle;
+
+static inline struct iwch_mr *to_iwch_mr(struct ib_mr *ibmr)
+{
+	return container_of(ibmr, struct iwch_mr, ibmr);
+}
+
+struct iwch_mw {
+	struct ib_mw ibmw;
+	struct iwch_dev *rhp;
+	u64 kva;
+	struct tpt_attributes attr;
+};
+
+static inline struct iwch_mw *to_iwch_mw(struct ib_mw *ibmw)
+{
+	return container_of(ibmw, struct iwch_mw, ibmw);
+}
+
+struct iwch_cq {
+	struct ib_cq ibcq;
+	struct iwch_dev *rhp;
+	struct t3_cq cq;
+	spinlock_t lock;
+	atomic_t refcnt;
+	wait_queue_head_t wait;
+	u32 __user *user_rptr_addr;
+};
+
+static inline struct iwch_cq *to_iwch_cq(struct ib_cq *ibcq)
+{
+	return container_of(ibcq, struct iwch_cq, ibcq);
+}
+
+enum IWCH_QP_FLAGS {
+	QP_QUIESCED = 0x01
+};
+
+struct iwch_mpa_attributes {
+	u8 recv_marker_enabled;
+	u8 xmit_marker_enabled;	/* iWARP: enable inbound Read Resp. */
+	u8 crc_enabled;
+	u8 version;	/* 0 or 1 */
+};
+
+struct iwch_qp_attributes {
+	u32 scq;
+	u32 rcq;
+	u32 sq_num_entries;
+	u32 rq_num_entries;
+	u32 sq_max_sges;
+	u32 sq_max_sges_rdma_write;
+	u32 rq_max_sges;
+	u32 state;
+	u8 enable_rdma_read;
+	u8 enable_rdma_write;	/* enable inbound Read Resp. */
+	u8 enable_bind;
+	u8 enable_mmid0_fastreg;	/* Enable STAG0 + Fast-register */
+	/*
+	 * Next QP state. If specify the current state, only the
+	 * QP attributes will be modified.
+	 */
+	u32 max_ord;
+	u32 max_ird;
+	u32 pd;	/* IN */
+	u32 next_state;
+	char terminate_buffer[52];
+	u32 terminate_msg_len;
+	u8 is_terminate_local;
+	struct iwch_mpa_attributes mpa_attr;	/* IN-OUT */
+	struct iwch_ep *llp_stream_handle;
+	char *stream_msg_buf;	/* Last stream msg. before Idle -> RTS */
+	u32 stream_msg_buf_len;	/* Only on Idle -> RTS */
+};
+
+struct iwch_qp {
+	struct ib_qp ibqp;
+	struct iwch_dev *rhp;
+	struct iwch_ep *ep;
+	struct iwch_qp_attributes attr;
+	struct t3_wq wq;
+	spinlock_t lock;
+	atomic_t refcnt;
+	wait_queue_head_t wait;
+	enum IWCH_QP_FLAGS flags;
+	struct timer_list timer;
+};
+
+static inline int qp_quiesced(struct iwch_qp *qhp)
+{
+	return qhp->flags & QP_QUIESCED;
+}
+
+static inline struct iwch_qp *to_iwch_qp(struct ib_qp *ibqp)
+{
+	return container_of(ibqp, struct iwch_qp, ibqp);
+}
+
+void iwch_qp_add_ref(struct ib_qp *qp);
+void iwch_qp_rem_ref(struct ib_qp *qp);
+struct ib_qp *iwch_get_qp(struct ib_device *dev, int qpn);
+
+struct iwch_ucontext {
+	struct ib_ucontext ibucontext;
+	struct cxio_ucontext uctx;
+	u32 key;
+	spinlock_t mmap_lock;
+	struct list_head mmaps;
+};
+
+static inline struct iwch_ucontext *to_iwch_ucontext(struct ib_ucontext *c)
+{
+	return container_of(c, struct iwch_ucontext, ibucontext);
+}
+
+struct iwch_mm_entry {
+	struct list_head entry;
+	u64 addr;
+	u32 key;
+	unsigned len;
+};
+
+static inline struct iwch_mm_entry *remove_mmap(struct iwch_ucontext *ucontext,
+						u32 key, unsigned len)
+{
+	struct list_head *pos, *nxt;
+	struct iwch_mm_entry *mm;
+
+	spin_lock(&ucontext->mmap_lock);
+	list_for_each_safe(pos, nxt, &ucontext->mmaps) {
+
+		mm = list_entry(pos, struct iwch_mm_entry, entry);
+		if (mm->key == key && mm->len == len) {
+			list_del_init(&mm->entry);
+			spin_unlock(&ucontext->mmap_lock);
+			PDBG("%s key 0x%x addr 0x%llx len %d\n", __FUNCTION__,
+			     key, (unsigned long long) mm->addr, mm->len);
+			return mm;
+		}
+	}
+	spin_unlock(&ucontext->mmap_lock);
+	return NULL;
+}
+
+static inline void insert_mmap(struct iwch_ucontext *ucontext,
+			       struct iwch_mm_entry *mm)
+{
+	spin_lock(&ucontext->mmap_lock);
+	PDBG("%s key 0x%x addr 0x%llx len %d\n", __FUNCTION__,
+	     mm->key, (unsigned long long) mm->addr, mm->len);
+	list_add_tail(&mm->entry, &ucontext->mmaps);
+	spin_unlock(&ucontext->mmap_lock);
+}
+
+enum iwch_qp_attr_mask {
+	IWCH_QP_ATTR_NEXT_STATE = 1 << 0,
+	IWCH_QP_ATTR_ENABLE_RDMA_READ = 1 << 7,
+	IWCH_QP_ATTR_ENABLE_RDMA_WRITE = 1 << 8,
+	IWCH_QP_ATTR_ENABLE_RDMA_BIND = 1 << 9,
+	IWCH_QP_ATTR_MAX_ORD = 1 << 11,
+	IWCH_QP_ATTR_MAX_IRD = 1 << 12,
+	IWCH_QP_ATTR_LLP_STREAM_HANDLE = 1 << 22,
+	IWCH_QP_ATTR_STREAM_MSG_BUFFER = 1 << 23,
+	IWCH_QP_ATTR_MPA_ATTR = 1 << 24,
+	IWCH_QP_ATTR_QP_CONTEXT_ACTIVATE = 1 << 25,
+	IWCH_QP_ATTR_VALID_MODIFY = (IWCH_QP_ATTR_ENABLE_RDMA_READ |
+				     IWCH_QP_ATTR_ENABLE_RDMA_WRITE |
+				     IWCH_QP_ATTR_MAX_ORD |
+				     IWCH_QP_ATTR_MAX_IRD |
+				     IWCH_QP_ATTR_LLP_STREAM_HANDLE |
+				     IWCH_QP_ATTR_STREAM_MSG_BUFFER |
+				     IWCH_QP_ATTR_MPA_ATTR |
+				     IWCH_QP_ATTR_QP_CONTEXT_ACTIVATE)
+};
+
+int iwch_modify_qp(struct iwch_dev *rhp,
+				struct iwch_qp *qhp,
+				enum iwch_qp_attr_mask mask,
+				struct iwch_qp_attributes *attrs,
+				int internal);
+
+enum iwch_qp_state {
+	IWCH_QP_STATE_IDLE,
+	IWCH_QP_STATE_RTS,
+	IWCH_QP_STATE_ERROR,
+	IWCH_QP_STATE_TERMINATE,
+	IWCH_QP_STATE_CLOSING,
+	IWCH_QP_STATE_TOT
+};
+
+static inline int iwch_convert_state(enum ib_qp_state ib_state)
+{
+	switch (ib_state) {
+	case IB_QPS_RESET:
+	case IB_QPS_INIT:
+		return IWCH_QP_STATE_IDLE;
+	case IB_QPS_RTS:
+		return IWCH_QP_STATE_RTS;
+	case IB_QPS_SQD:
+		return IWCH_QP_STATE_CLOSING;
+	case IB_QPS_SQE:
+		return IWCH_QP_STATE_TERMINATE;
+	case IB_QPS_ERR:
+		return IWCH_QP_STATE_ERROR;
+	default:
+		return -1;
+	}
+}
+
+enum iwch_mem_perms {
+	IWCH_MEM_ACCESS_LOCAL_READ = 1 << 0,
+	IWCH_MEM_ACCESS_LOCAL_WRITE = 1 << 1,
+	IWCH_MEM_ACCESS_REMOTE_READ = 1 << 2,
+	IWCH_MEM_ACCESS_REMOTE_WRITE = 1 << 3,
+	IWCH_MEM_ACCESS_ATOMICS = 1 << 4,
+	IWCH_MEM_ACCESS_BINDING = 1 << 5,
+	IWCH_MEM_ACCESS_LOCAL =
+	    (IWCH_MEM_ACCESS_LOCAL_READ | IWCH_MEM_ACCESS_LOCAL_WRITE),
+	IWCH_MEM_ACCESS_REMOTE =
+	    (IWCH_MEM_ACCESS_REMOTE_WRITE | IWCH_MEM_ACCESS_REMOTE_READ)
+	    /* cannot go beyond 1 << 31 */
+} __attribute__ ((packed));
+
+static inline u32 iwch_convert_access(int acc)
+{
+	return (acc & IB_ACCESS_REMOTE_WRITE ? IWCH_MEM_ACCESS_REMOTE_WRITE : 0)
+	    | (acc & IB_ACCESS_REMOTE_READ ? IWCH_MEM_ACCESS_REMOTE_READ : 0) |
+	    (acc & IB_ACCESS_LOCAL_WRITE ? IWCH_MEM_ACCESS_LOCAL_WRITE : 0) |
+	    (acc & IB_ACCESS_MW_BIND ? IWCH_MEM_ACCESS_BINDING : 0) |
+	    IWCH_MEM_ACCESS_LOCAL_READ;
+}
+
+enum iwch_mmid_state {
+	IWCH_STAG_STATE_VALID,
+	IWCH_STAG_STATE_INVALID
+};
+
+enum iwch_qp_query_flags {
+	IWCH_QP_QUERY_CONTEXT_NONE = 0x0,	/* No ctx; Only attrs */
+	IWCH_QP_QUERY_CONTEXT_GET = 0x1,	/* Get ctx + attrs */
+	IWCH_QP_QUERY_CONTEXT_SUSPEND = 0x2,	/* Not Supported */
+
+	/*
+	 * Quiesce QP context; Consumer
+	 * will NOT replay outstanding WR
+	 */
+	IWCH_QP_QUERY_CONTEXT_QUIESCE = 0x4,
+	IWCH_QP_QUERY_CONTEXT_REMOVE = 0x8,
+	IWCH_QP_QUERY_TEST_USERWRITE = 0x32	/* Test special */
+};
+
+int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+		      struct ib_send_wr **bad_wr);
+int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+		      struct ib_recv_wr **bad_wr);
+int iwch_bind_mw(struct ib_qp *qp,
+			     struct ib_mw *mw,
+			     struct ib_mw_bind *mw_bind);
+int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
+int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg);
+int iwch_register_device(struct iwch_dev *dev);
+void iwch_unregister_device(struct iwch_dev *dev);
+int iwch_quiesce_qps(struct iwch_cq *chp);
+int iwch_resume_qps(struct iwch_cq *chp);
+void stop_read_rep_timer(struct iwch_qp *qhp);
+int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php,
+					struct iwch_mr *mhp,
+					int shift,
+					__be64 *page_list);
+int iwch_reregister_mem(struct iwch_dev *rhp, struct iwch_pd *php,
+					struct iwch_mr *mhp,
+					int shift,
+					__be64 *page_list,
+					int npages);
+int build_phys_page_list(struct ib_phys_buf *buffer_list,
+					int num_phys_buf,
+					u64 *iova_start,
+					u64 *total_size,
+					int *npages,
+					int *shift,
+					__be64 **page_list);
+
+
+#define IWCH_NODE_DESC "cxgb3 Chelsio Communications"
+
+#endif
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
new file mode 100644
index 0000000..4dda2f6
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -0,0 +1,1008 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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 "iwch_provider.h"
+#include "iwch.h"
+#include "iwch_cm.h"
+#include "cxio_hal.h"
+
+#define NO_SUPPORT -1
+
+static inline int iwch_build_rdma_send(union t3_wr *wqe, struct ib_send_wr *wr,
+				       u8 * flit_cnt)
+{
+	int i;
+	u32 plen;
+
+	switch (wr->opcode) {
+	case IB_WR_SEND:
+	case IB_WR_SEND_WITH_IMM:
+		if (wr->send_flags & IB_SEND_SOLICITED)
+			wqe->send.rdmaop = T3_SEND_WITH_SE;
+		else
+			wqe->send.rdmaop = T3_SEND;
+		wqe->send.rem_stag = 0;
+		break;
+#if 0				/* Not currently supported */
+	case TYPE_SEND_INVALIDATE:
+	case TYPE_SEND_INVALIDATE_IMMEDIATE:
+		wqe->send.rdmaop = T3_SEND_WITH_INV;
+		wqe->send.rem_stag = cpu_to_be32(wr->wr.rdma.rkey);
+		break;
+	case TYPE_SEND_SE_INVALIDATE:
+		wqe->send.rdmaop = T3_SEND_WITH_SE_INV;
+		wqe->send.rem_stag = cpu_to_be32(wr->wr.rdma.rkey);
+		break;
+#endif
+	default:
+		break;
+	}
+	if (wr->num_sge > T3_MAX_SGE)
+		return -EINVAL;
+	wqe->send.reserved[0] = 0;
+	wqe->send.reserved[1] = 0;
+	wqe->send.reserved[2] = 0;
+	if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+		plen = 4;
+		wqe->send.sgl[0].stag = wr->imm_data;
+		wqe->send.sgl[0].len = __constant_cpu_to_be32(0);
+		wqe->send.num_sgle = __constant_cpu_to_be32(0);
+		*flit_cnt = 5;
+	} else {
+		plen = 0;
+		for (i = 0; i < wr->num_sge; i++) {
+			if ((plen + wr->sg_list[i].length) < plen) {
+				return -EMSGSIZE;
+			}
+			plen += wr->sg_list[i].length;
+			wqe->send.sgl[i].stag =
+			    cpu_to_be32(wr->sg_list[i].lkey);
+			wqe->send.sgl[i].len =
+			    cpu_to_be32(wr->sg_list[i].length);
+			wqe->send.sgl[i].to = cpu_to_be64(wr->sg_list[i].addr);
+		}
+		wqe->send.num_sgle = cpu_to_be32(wr->num_sge);
+		*flit_cnt = 4 + ((wr->num_sge) << 1);
+	}
+	wqe->send.plen = cpu_to_be32(plen);
+	return 0;
+}
+
+static inline int iwch_build_rdma_write(union t3_wr *wqe, struct ib_send_wr *wr,
+					u8 *flit_cnt)
+{
+	int i;
+	u32 plen;
+	if (wr->num_sge > T3_MAX_SGE)
+		return -EINVAL;
+	wqe->write.rdmaop = T3_RDMA_WRITE;
+	wqe->write.reserved[0] = 0;
+	wqe->write.reserved[1] = 0;
+	wqe->write.reserved[2] = 0;
+	wqe->write.stag_sink = cpu_to_be32(wr->wr.rdma.rkey);
+	wqe->write.to_sink = cpu_to_be64(wr->wr.rdma.remote_addr);
+
+	if (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
+		plen = 4;
+		wqe->write.sgl[0].stag = wr->imm_data;
+		wqe->write.sgl[0].len = __constant_cpu_to_be32(0);
+		wqe->write.num_sgle = __constant_cpu_to_be32(0);
+		*flit_cnt = 6;
+	} else {
+		plen = 0;
+		for (i = 0; i < wr->num_sge; i++) {
+			if ((plen + wr->sg_list[i].length) < plen) {
+				return -EMSGSIZE;
+			}
+			plen += wr->sg_list[i].length;
+			wqe->write.sgl[i].stag =
+			    cpu_to_be32(wr->sg_list[i].lkey);
+			wqe->write.sgl[i].len =
+			    cpu_to_be32(wr->sg_list[i].length);
+			wqe->write.sgl[i].to =
+			    cpu_to_be64(wr->sg_list[i].addr);
+		}
+		wqe->write.num_sgle = cpu_to_be32(wr->num_sge);
+		*flit_cnt = 5 + ((wr->num_sge) << 1);
+	}
+	wqe->write.plen = cpu_to_be32(plen);
+	return 0;
+}
+
+static inline int iwch_build_rdma_read(union t3_wr *wqe, struct ib_send_wr *wr,
+				       u8 *flit_cnt)
+{
+	if (wr->num_sge > 1)
+		return -EINVAL;
+	wqe->read.rdmaop = T3_READ_REQ;
+	wqe->read.reserved[0] = 0;
+	wqe->read.reserved[1] = 0;
+	wqe->read.reserved[2] = 0;
+	wqe->read.rem_stag = cpu_to_be32(wr->wr.rdma.rkey);
+	wqe->read.rem_to = cpu_to_be64(wr->wr.rdma.remote_addr);
+	wqe->read.local_stag = cpu_to_be32(wr->sg_list[0].lkey);
+	wqe->read.local_len = cpu_to_be32(wr->sg_list[0].length);
+	wqe->read.local_to = cpu_to_be64(wr->sg_list[0].addr);
+	*flit_cnt = sizeof(struct t3_rdma_read_wr) >> 3;
+	return 0;
+}
+
+/*
+ * TBD: this is going to be moved to firmware. Missing pdid/qpid check for now.
+ */
+static inline int iwch_sgl2pbl_map(struct iwch_dev *rhp,
+				   struct ib_sge *sg_list, u32 num_sgle,
+				   u32 * pbl_addr, u8 * page_size)
+{
+	int i;
+	struct iwch_mr *mhp;
+	u32 offset;
+	for (i = 0; i < num_sgle; i++) {
+
+		mhp = get_mhp(rhp, (sg_list[i].lkey) >> 8);
+		if (!mhp) {
+			PDBG("%s %d\n", __FUNCTION__, __LINE__);
+			return -EIO;
+		}
+		if (!mhp->attr.state) {
+			PDBG("%s %d\n", __FUNCTION__, __LINE__);
+			return -EIO;
+		}
+		if (mhp->attr.zbva) {
+			PDBG("%s %d\n", __FUNCTION__, __LINE__);
+			return -EIO;
+		}
+
+		if (sg_list[i].addr < mhp->attr.va_fbo) {
+			PDBG("%s %d\n", __FUNCTION__, __LINE__);
+			return -EINVAL;
+		}
+		if (sg_list[i].addr + ((u64) sg_list[i].length) <
+		    sg_list[i].addr) {
+			PDBG("%s %d\n", __FUNCTION__, __LINE__);
+			return -EINVAL;
+		}
+		if (sg_list[i].addr + ((u64) sg_list[i].length) >
+		    mhp->attr.va_fbo + ((u64) mhp->attr.len)) {
+			PDBG("%s %d\n", __FUNCTION__, __LINE__);
+			return -EINVAL;
+		}
+		offset = sg_list[i].addr - mhp->attr.va_fbo;
+		offset += ((u32) mhp->attr.va_fbo) %
+		          (1UL << (12 + mhp->attr.page_size));
+		pbl_addr[i] = ((mhp->attr.pbl_addr -
+			        rhp->rdev.rnic_info.pbl_base) >> 3) +
+			      (offset >> (12 + mhp->attr.page_size));
+		page_size[i] = mhp->attr.page_size;
+	}
+	return 0;
+}
+
+static inline int iwch_build_rdma_recv(struct iwch_dev *rhp,
+						    union t3_wr *wqe,
+						    struct ib_recv_wr *wr)
+{
+	int i, err = 0;
+	u32 pbl_addr[4];
+	u8 page_size[4];
+	if (wr->num_sge > T3_MAX_SGE)
+		return -EINVAL;
+	err = iwch_sgl2pbl_map(rhp, wr->sg_list, wr->num_sge, pbl_addr,
+			       page_size);
+	if (err)
+		return err;
+	wqe->recv.pagesz[0] = page_size[0];
+	wqe->recv.pagesz[1] = page_size[1];
+	wqe->recv.pagesz[2] = page_size[2];
+	wqe->recv.pagesz[3] = page_size[3];
+	wqe->recv.num_sgle = cpu_to_be32(wr->num_sge);
+	for (i = 0; i < wr->num_sge; i++) {
+		wqe->recv.sgl[i].stag = cpu_to_be32(wr->sg_list[i].lkey);
+		wqe->recv.sgl[i].len = cpu_to_be32(wr->sg_list[i].length);
+
+		/* to in the WQE == the offset into the page */
+		wqe->recv.sgl[i].to = cpu_to_be64(((u32) wr->sg_list[i].addr) %
+				(1UL << (12 + page_size[i])));
+
+		/* pbl_addr is the adapters address in the PBL */
+		wqe->recv.pbl_addr[i] = cpu_to_be32(pbl_addr[i]);
+	}
+	for (; i < T3_MAX_SGE; i++) {
+		wqe->recv.sgl[i].stag = 0;
+		wqe->recv.sgl[i].len = 0;
+		wqe->recv.sgl[i].to = 0;
+		wqe->recv.pbl_addr[i] = 0;
+	}
+	return 0;
+}
+
+int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+		      struct ib_send_wr **bad_wr)
+{
+	int err = 0;
+	u8 t3_wr_flit_cnt;
+	enum t3_wr_opcode t3_wr_opcode = 0;
+	enum t3_wr_flags t3_wr_flags;
+	struct iwch_qp *qhp;
+	u32 idx;
+	union t3_wr *wqe;
+	u32 num_wrs;
+	unsigned long flag;
+	struct t3_swsq *sqp;
+
+	qhp = to_iwch_qp(ibqp);
+	spin_lock_irqsave(&qhp->lock, flag);
+	if (qhp->attr.state > IWCH_QP_STATE_RTS) {
+		spin_unlock_irqrestore(&qhp->lock, flag);
+		return -EINVAL;
+	}
+	num_wrs = Q_FREECNT(qhp->wq.sq_rptr, qhp->wq.sq_wptr,
+		  qhp->wq.sq_size_log2);
+	if (num_wrs <= 0) {
+		spin_unlock_irqrestore(&qhp->lock, flag);
+		return -ENOMEM;
+	}
+	while (wr) {
+		if (num_wrs == 0) {
+			err = -ENOMEM;
+			*bad_wr = wr;
+			break;
+		}
+		idx = Q_PTR2IDX(qhp->wq.wptr, qhp->wq.size_log2);
+		wqe = (union t3_wr *) (qhp->wq.queue + idx);
+		t3_wr_flags = 0;
+		if (wr->send_flags & IB_SEND_SOLICITED)
+			t3_wr_flags |= T3_SOLICITED_EVENT_FLAG;
+		if (wr->send_flags & IB_SEND_FENCE)
+			t3_wr_flags |= T3_READ_FENCE_FLAG;
+		if (wr->send_flags & IB_SEND_SIGNALED)
+			t3_wr_flags |= T3_COMPLETION_FLAG;
+		sqp = qhp->wq.sq +
+		      Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2);
+		switch (wr->opcode) {
+		case IB_WR_SEND:
+		case IB_WR_SEND_WITH_IMM:
+			t3_wr_opcode = T3_WR_SEND;
+			err = iwch_build_rdma_send(wqe, wr, &t3_wr_flit_cnt);
+			break;
+		case IB_WR_RDMA_WRITE:
+		case IB_WR_RDMA_WRITE_WITH_IMM:
+			t3_wr_opcode = T3_WR_WRITE;
+			err = iwch_build_rdma_write(wqe, wr, &t3_wr_flit_cnt);
+			break;
+		case IB_WR_RDMA_READ:
+			t3_wr_opcode = T3_WR_READ;
+			t3_wr_flags = 0; /* T3 reads are always signaled */
+			err = iwch_build_rdma_read(wqe, wr, &t3_wr_flit_cnt);
+			if (err)
+				break;
+			sqp->read_len = wqe->read.local_len;
+			if (!qhp->wq.oldest_read)
+				qhp->wq.oldest_read = sqp;
+			break;
+		default:
+			PDBG("%s post of type=%d TBD!\n", __FUNCTION__,
+			     wr->opcode);
+			err = -EINVAL;
+		}
+		if (err) {
+			*bad_wr = wr;
+			break;
+		}
+		wqe->send.wrid.id0.hi = qhp->wq.sq_wptr;
+		sqp->wr_id = wr->wr_id;
+		sqp->opcode = wr2opcode(t3_wr_opcode);
+		sqp->sq_wptr = qhp->wq.sq_wptr;
+		sqp->complete = 0;
+		sqp->signaled = (wr->send_flags & IB_SEND_SIGNALED);
+
+		build_fw_riwrh((void *) wqe, t3_wr_opcode, t3_wr_flags,
+			       Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2),
+			       0, t3_wr_flit_cnt);
+		PDBG("%s cookie 0x%llx wq idx 0x%x swsq idx %ld opcode %d\n",
+		     __FUNCTION__, (unsigned long long) wr->wr_id, idx,
+		     Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2),
+		     sqp->opcode);
+		wr = wr->next;
+		num_wrs--;
+		++(qhp->wq.wptr);
+		++(qhp->wq.sq_wptr);
+	}
+	spin_unlock_irqrestore(&qhp->lock, flag);
+	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+	return err;
+}
+
+int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+		      struct ib_recv_wr **bad_wr)
+{
+	int err = 0;
+	struct iwch_qp *qhp;
+	u32 idx;
+	union t3_wr *wqe;
+	u32 num_wrs;
+	unsigned long flag;
+
+	qhp = to_iwch_qp(ibqp);
+	spin_lock_irqsave(&qhp->lock, flag);
+	if (qhp->attr.state > IWCH_QP_STATE_RTS) {
+		spin_unlock_irqrestore(&qhp->lock, flag);
+		return -EINVAL;
+	}
+	num_wrs = Q_FREECNT(qhp->wq.rq_rptr, qhp->wq.rq_wptr,
+			    qhp->wq.rq_size_log2) - 1;
+	if (!wr) {
+		spin_unlock_irqrestore(&qhp->lock, flag);
+		return -EINVAL;
+	}
+	while (wr) {
+		idx = Q_PTR2IDX(qhp->wq.wptr, qhp->wq.size_log2);
+		wqe = (union t3_wr *) (qhp->wq.queue + idx);
+		if (num_wrs)
+			err = iwch_build_rdma_recv(qhp->rhp, wqe, wr);
+		else
+			err = -ENOMEM;
+		if (err) {
+			*bad_wr = wr;
+			break;
+		}
+		qhp->wq.rq[Q_PTR2IDX(qhp->wq.rq_wptr, qhp->wq.rq_size_log2)] =
+			wr->wr_id;
+		build_fw_riwrh((void *) wqe, T3_WR_RCV, T3_COMPLETION_FLAG,
+			       Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2),
+			       0, sizeof(struct t3_receive_wr) >> 3);
+		PDBG("%s cookie 0x%llx idx 0x%x rq_wptr 0x%x rw_rptr 0x%x "
+		     "wqe %p \n", __FUNCTION__, (unsigned long long) wr->wr_id,
+		     idx, qhp->wq.rq_wptr, qhp->wq.rq_rptr, wqe);
+		++(qhp->wq.rq_wptr);
+		++(qhp->wq.wptr);
+		wr = wr->next;
+		num_wrs--;
+	}
+	spin_unlock_irqrestore(&qhp->lock, flag);
+	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+	return err;
+}
+
+int iwch_bind_mw(struct ib_qp *qp,
+			     struct ib_mw *mw,
+			     struct ib_mw_bind *mw_bind)
+{
+	struct iwch_dev *rhp;
+	struct iwch_mw *mhp;
+	struct iwch_qp *qhp;
+	union t3_wr *wqe;
+	u32 pbl_addr;
+	u8 page_size;
+	u32 num_wrs;
+	unsigned long flag;
+	struct ib_sge sgl;
+	int err=0;
+	enum t3_wr_flags t3_wr_flags;
+	u32 idx;
+	struct t3_swsq *sqp;
+
+	qhp = to_iwch_qp(qp);
+	mhp = to_iwch_mw(mw);
+	rhp = qhp->rhp;
+
+	spin_lock_irqsave(&qhp->lock, flag);
+	if (qhp->attr.state > IWCH_QP_STATE_RTS) {
+		spin_unlock_irqrestore(&qhp->lock, flag);
+		return -EINVAL;
+	}
+	num_wrs = Q_FREECNT(qhp->wq.sq_rptr, qhp->wq.sq_wptr,
+			    qhp->wq.sq_size_log2);
+	if ((num_wrs) <= 0) {
+		spin_unlock_irqrestore(&qhp->lock, flag);
+		return -ENOMEM;
+	}
+	idx = Q_PTR2IDX(qhp->wq.wptr, qhp->wq.size_log2);
+	PDBG("%s: idx 0x%0x, mw 0x%p, mw_bind 0x%p\n", __FUNCTION__, idx,
+	     mw, mw_bind);
+	wqe = (union t3_wr *) (qhp->wq.queue + idx);
+
+	t3_wr_flags = 0;
+	if (mw_bind->send_flags & IB_SEND_SIGNALED)
+		t3_wr_flags = T3_COMPLETION_FLAG;
+
+	sgl.addr = mw_bind->addr;
+	sgl.lkey = mw_bind->mr->lkey;
+	sgl.length = mw_bind->length;
+	wqe->bind.reserved = 0;
+	wqe->bind.type = T3_VA_BASED_TO;
+
+	/* TBD: check perms */
+	wqe->bind.perms = iwch_convert_access(mw_bind->mw_access_flags);
+	wqe->bind.mr_stag = cpu_to_be32(mw_bind->mr->lkey);
+	wqe->bind.mw_stag = cpu_to_be32(mw->rkey);
+	wqe->bind.mw_len = cpu_to_be32(mw_bind->length);
+	wqe->bind.mw_va = cpu_to_be64(mw_bind->addr);
+	err = iwch_sgl2pbl_map(rhp, &sgl, 1, &pbl_addr, &page_size);
+	if (err) {
+		spin_unlock_irqrestore(&qhp->lock, flag);
+	        return err;
+	}
+	wqe->send.wrid.id0.hi = qhp->wq.sq_wptr;
+	sqp = qhp->wq.sq + Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2);
+	sqp->wr_id = mw_bind->wr_id;
+	sqp->opcode = T3_BIND_MW;
+	sqp->sq_wptr = qhp->wq.sq_wptr;
+	sqp->complete = 0;
+	sqp->signaled = (mw_bind->send_flags & IB_SEND_SIGNALED);
+	wqe->bind.mr_pbl_addr = cpu_to_be32(pbl_addr);
+	wqe->bind.mr_pagesz = page_size;
+	wqe->flit[T3_SQ_COOKIE_FLIT] = mw_bind->wr_id;
+	build_fw_riwrh((void *)wqe, T3_WR_BIND, t3_wr_flags,
+		       Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2), 0,
+			        sizeof(struct t3_bind_mw_wr) >> 3);
+	++(qhp->wq.wptr);
+	++(qhp->wq.sq_wptr);
+	spin_unlock_irqrestore(&qhp->lock, flag);
+
+	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+
+	return err;
+}
+
+static inline void build_term_codes(int t3err, u8 *layer_type, u8 *ecode,
+				    int tagged)
+{
+	switch (t3err) {
+	case TPT_ERR_STAG:
+		if (tagged == 1) {
+			*layer_type = LAYER_DDP|DDP_TAGGED_ERR;
+			*ecode = DDPT_INV_STAG;
+		} else if (tagged == 2) {
+			*layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
+			*ecode = RDMAP_INV_STAG;
+		}
+		break;
+	case TPT_ERR_PDID:
+	case TPT_ERR_QPID:
+	case TPT_ERR_ACCESS:
+		if (tagged == 1) {
+			*layer_type = LAYER_DDP|DDP_TAGGED_ERR;
+			*ecode = DDPT_STAG_NOT_ASSOC;
+		} else if (tagged == 2) {
+			*layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
+			*ecode = RDMAP_STAG_NOT_ASSOC;
+		}
+		break;
+	case TPT_ERR_WRAP:
+		*layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
+		*ecode = RDMAP_TO_WRAP;
+		break;
+	case TPT_ERR_BOUND:
+		if (tagged == 1) {
+			*layer_type = LAYER_DDP|DDP_TAGGED_ERR;
+			*ecode = DDPT_BASE_BOUNDS;
+		} else if (tagged == 2) {
+			*layer_type = LAYER_RDMAP|RDMAP_REMOTE_PROT;
+			*ecode = RDMAP_BASE_BOUNDS;
+		} else {
+			*layer_type = LAYER_DDP|DDP_UNTAGGED_ERR;
+			*ecode = DDPU_MSG_TOOBIG;
+		}
+		break;
+	case TPT_ERR_INVALIDATE_SHARED_MR:
+	case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND:
+		*layer_type = LAYER_RDMAP|RDMAP_REMOTE_OP;
+		*ecode = RDMAP_CANT_INV_STAG;
+		break;
+	case TPT_ERR_ECC:
+	case TPT_ERR_ECC_PSTAG:
+	case TPT_ERR_INTERNAL_ERR:
+		*layer_type = LAYER_RDMAP|RDMAP_LOCAL_CATA;
+		*ecode = 0;
+		break;
+	case TPT_ERR_OUT_OF_RQE:
+		*layer_type = LAYER_DDP|DDP_UNTAGGED_ERR;
+		*ecode = DDPU_INV_MSN_NOBUF;
+		break;
+	case TPT_ERR_PBL_ADDR_BOUND:
+		*layer_type = LAYER_DDP|DDP_TAGGED_ERR;
+		*ecode = DDPT_BASE_BOUNDS;
+		break;
+	case TPT_ERR_CRC:
+		*layer_type = LAYER_MPA|DDP_LLP;
+		*ecode = MPA_CRC_ERR;
+		break;
+	case TPT_ERR_MARKER:
+		*layer_type = LAYER_MPA|DDP_LLP;
+		*ecode = MPA_MARKER_ERR;
+		break;
+	case TPT_ERR_PDU_LEN_ERR:
+		*layer_type = LAYER_DDP|DDP_UNTAGGED_ERR;
+		*ecode = DDPU_MSG_TOOBIG;
+		break;
+	case TPT_ERR_DDP_VERSION:
+		if (tagged) {
+			*layer_type = LAYER_DDP|DDP_TAGGED_ERR;
+			*ecode = DDPT_INV_VERS;
+		} else {
+			*layer_type = LAYER_DDP|DDP_UNTAGGED_ERR;
+			*ecode = DDPU_INV_VERS;
+		}
+		break;
+	case TPT_ERR_RDMA_VERSION:
+		*layer_type = LAYER_RDMAP|RDMAP_REMOTE_OP;
+		*ecode = RDMAP_INV_VERS;
+		break;
+	case TPT_ERR_OPCODE:
+		*layer_type = LAYER_RDMAP|RDMAP_REMOTE_OP;
+		*ecode = RDMAP_INV_OPCODE;
+		break;
+	case TPT_ERR_DDP_QUEUE_NUM:
+		*layer_type = LAYER_DDP|DDP_UNTAGGED_ERR;
+		*ecode = DDPU_INV_QN;
+		break;
+	case TPT_ERR_MSN:
+	case TPT_ERR_MSN_GAP:
+	case TPT_ERR_MSN_RANGE:
+	case TPT_ERR_IRD_OVERFLOW:
+		*layer_type = LAYER_DDP|DDP_UNTAGGED_ERR;
+		*ecode = DDPU_INV_MSN_RANGE;
+		break;
+	case TPT_ERR_TBIT:
+		*layer_type = LAYER_DDP|DDP_LOCAL_CATA;
+		*ecode = 0;
+		break;
+	case TPT_ERR_MO:
+		*layer_type = LAYER_DDP|DDP_UNTAGGED_ERR;
+		*ecode = DDPU_INV_MO;
+		break;
+	default:
+		*layer_type = LAYER_RDMAP|DDP_LOCAL_CATA;
+		*ecode = 0;
+		break;
+	}
+}
+
+/*
+ * This posts a TERMINATE with layer=RDMA, type=catastrophic.
+ */
+int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg)
+{
+	union t3_wr *wqe;
+	struct terminate_message *term;
+	int status;
+	int tagged = 0;
+	struct sk_buff *skb;
+
+	PDBG("%s %d\n", __FUNCTION__, __LINE__);
+	skb = alloc_skb(40, GFP_ATOMIC);
+	if (!skb) {
+		printk(KERN_ERR "%s cannot send TERMINATE!\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	wqe = (union t3_wr *)skb_put(skb, 40);
+	memset(wqe, 0, 40);
+	wqe->send.rdmaop = T3_TERMINATE;
+
+	/* immediate data length */
+	wqe->send.plen = htonl(4);
+
+	/* immediate data starts here. */
+	term = (struct terminate_message *)wqe->send.sgl;
+	if (rsp_msg) {
+		status = CQE_STATUS(rsp_msg->cqe);
+		if (CQE_OPCODE(rsp_msg->cqe) == T3_RDMA_WRITE)
+			tagged = 1;
+		if ((CQE_OPCODE(rsp_msg->cqe) == T3_READ_REQ) ||
+		    (CQE_OPCODE(rsp_msg->cqe) == T3_READ_RESP))
+			tagged = 2;
+	} else {
+		status = TPT_ERR_INTERNAL_ERR;
+	}
+	build_term_codes(status, &term->layer_etype, &term->ecode, tagged);
+	build_fw_riwrh((void *)wqe, T3_WR_SEND,
+		       T3_COMPLETION_FLAG | T3_NOTIFY_FLAG, 1,
+		       qhp->ep->hwtid, 5);
+	skb->priority = CPL_PRIORITY_DATA;
+	return cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb);
+}
+
+/*
+ * Assumes qhp lock is held.
+ */
+static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+{
+	struct iwch_cq *rchp, *schp;
+	int count;
+
+	rchp = get_chp(qhp->rhp, qhp->attr.rcq);
+	schp = get_chp(qhp->rhp, qhp->attr.scq);
+
+	PDBG("%s qhp %p rchp %p schp %p\n", __FUNCTION__, qhp, rchp, schp);
+	/* take a ref on the qhp since we must release the lock */
+	atomic_inc(&qhp->refcnt);
+	spin_unlock_irqrestore(&qhp->lock, *flag);
+
+	/* locking heirarchy: cq lock first, then qp lock. */
+	spin_lock_irqsave(&rchp->lock, *flag);
+	spin_lock(&qhp->lock);
+	cxio_flush_hw_cq(&rchp->cq);
+	cxio_count_rcqes(&rchp->cq, &qhp->wq, &count);
+	cxio_flush_rq(&qhp->wq, &rchp->cq, count);
+	spin_unlock(&qhp->lock);
+	spin_unlock_irqrestore(&rchp->lock, *flag);
+
+	/* locking heirarchy: cq lock first, then qp lock. */
+	spin_lock_irqsave(&schp->lock, *flag);
+	spin_lock(&qhp->lock);
+	cxio_flush_hw_cq(&schp->cq);
+	cxio_count_scqes(&schp->cq, &qhp->wq, &count);
+	cxio_flush_sq(&qhp->wq, &schp->cq, count);
+	spin_unlock(&qhp->lock);
+	spin_unlock_irqrestore(&schp->lock, *flag);
+
+	/* deref */
+	if (atomic_dec_and_test(&qhp->refcnt))
+	        wake_up(&qhp->wait);
+
+	spin_lock_irqsave(&qhp->lock, *flag);
+}
+
+static inline void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+{
+	if (t3b_device(qhp->rhp))
+		cxio_set_wq_in_error(&qhp->wq);
+	else
+		__flush_qp(qhp, flag);
+}
+
+
+/*
+ * Return non zero if at least one RECV was pre-posted.
+ */
+static inline int rqes_posted(struct iwch_qp *qhp)
+{
+	return fw_riwrh_opcode((struct fw_riwrh *)qhp->wq.queue) == T3_WR_RCV;
+}
+
+static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
+				enum iwch_qp_attr_mask mask,
+				struct iwch_qp_attributes *attrs)
+{
+	struct t3_rdma_init_attr init_attr;
+	int ret;
+
+	init_attr.tid = qhp->ep->hwtid;
+	init_attr.qpid = qhp->wq.qpid;
+	init_attr.pdid = qhp->attr.pd;
+	init_attr.scqid = qhp->attr.scq;
+	init_attr.rcqid = qhp->attr.rcq;
+	init_attr.rq_addr = qhp->wq.rq_addr;
+	init_attr.rq_size = 1 << qhp->wq.rq_size_log2;
+	init_attr.mpaattrs = uP_RI_MPA_IETF_ENABLE |
+		qhp->attr.mpa_attr.recv_marker_enabled |
+		(qhp->attr.mpa_attr.xmit_marker_enabled << 1) |
+		(qhp->attr.mpa_attr.crc_enabled << 2);
+
+	/*
+	 * XXX - The IWCM doesn't quite handle getting these
+	 * attrs set before going into RTS.  For now, just turn
+	 * them on always...
+	 */
+#if 0
+	init_attr.qpcaps = qhp->attr.enableRdmaRead |
+		(qhp->attr.enableRdmaWrite << 1) |
+		(qhp->attr.enableBind << 2) |
+		(qhp->attr.enable_stag0_fastreg << 3) |
+		(qhp->attr.enable_stag0_fastreg << 4);
+#else
+	init_attr.qpcaps = 0x1f;
+#endif
+	init_attr.tcp_emss = qhp->ep->emss;
+	init_attr.ord = qhp->attr.max_ord;
+	init_attr.ird = qhp->attr.max_ird;
+	init_attr.qp_dma_addr = qhp->wq.dma_addr;
+	init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
+	init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0;
+	PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
+	     "flags 0x%x qpcaps 0x%x\n", __FUNCTION__,
+	     init_attr.rq_addr, init_attr.rq_size,
+	     init_attr.flags, init_attr.qpcaps);
+	ret = cxio_rdma_init(&rhp->rdev, &init_attr);
+	PDBG("%s ret %d\n", __FUNCTION__, ret);
+	return ret;
+}
+
+int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
+				enum iwch_qp_attr_mask mask,
+				struct iwch_qp_attributes *attrs,
+				int internal)
+{
+	int ret = 0;
+	struct iwch_qp_attributes newattr = qhp->attr;
+	unsigned long flag;
+	int disconnect = 0;
+	int terminate = 0;
+	int abort = 0;
+	int free = 0;
+	struct iwch_ep *ep = NULL;
+
+	PDBG("%s qhp %p qpid 0x%x ep %p state %d -> %d\n", __FUNCTION__,
+	     qhp, qhp->wq.qpid, qhp->ep, qhp->attr.state,
+	     (mask & IWCH_QP_ATTR_NEXT_STATE) ? attrs->next_state : -1);
+
+	spin_lock_irqsave(&qhp->lock, flag);
+
+	/* Process attr changes if in IDLE */
+	if (mask & IWCH_QP_ATTR_VALID_MODIFY) {
+		if (qhp->attr.state != IWCH_QP_STATE_IDLE) {
+			ret = -EIO;
+			goto out;
+		}
+		if (mask & IWCH_QP_ATTR_ENABLE_RDMA_READ)
+			newattr.enable_rdma_read = attrs->enable_rdma_read;
+		if (mask & IWCH_QP_ATTR_ENABLE_RDMA_WRITE)
+			newattr.enable_rdma_write = attrs->enable_rdma_write;
+		if (mask & IWCH_QP_ATTR_ENABLE_RDMA_BIND)
+			newattr.enable_bind = attrs->enable_bind;
+		if (mask & IWCH_QP_ATTR_MAX_ORD) {
+			if (attrs->max_ord >
+			    rhp->attr.max_rdma_read_qp_depth) {
+				ret = -EINVAL;
+				goto out;
+			}
+			newattr.max_ord = attrs->max_ord;
+		}
+		if (mask & IWCH_QP_ATTR_MAX_IRD) {
+			if (attrs->max_ird >
+			    rhp->attr.max_rdma_reads_per_qp) {
+				ret = -EINVAL;
+				goto out;
+			}
+			newattr.max_ird = attrs->max_ird;
+		}
+		qhp->attr = newattr;
+	}
+
+	if (!(mask & IWCH_QP_ATTR_NEXT_STATE))
+		goto out;
+	if (qhp->attr.state == attrs->next_state)
+		goto out;
+
+	switch (qhp->attr.state) {
+	case IWCH_QP_STATE_IDLE:
+		switch (attrs->next_state) {
+		case IWCH_QP_STATE_RTS:
+			if (!(mask & IWCH_QP_ATTR_LLP_STREAM_HANDLE)) {
+				ret = -EINVAL;
+				goto out;
+			}
+			if (!(mask & IWCH_QP_ATTR_MPA_ATTR)) {
+				ret = -EINVAL;
+				goto out;
+			}
+			qhp->attr.mpa_attr = attrs->mpa_attr;
+			qhp->attr.llp_stream_handle = attrs->llp_stream_handle;
+			qhp->ep = qhp->attr.llp_stream_handle;
+			qhp->attr.state = IWCH_QP_STATE_RTS;
+
+			/*
+			 * Ref the endpoint here and deref when we
+			 * disassociate the endpoint from the QP.  This
+			 * happens in CLOSING->IDLE transition or *->ERROR
+			 * transition.
+			 */
+			get_ep(&qhp->ep->com);
+			spin_unlock_irqrestore(&qhp->lock, flag);
+			ret = rdma_init(rhp, qhp, mask, attrs);
+			spin_lock_irqsave(&qhp->lock, flag);
+			if (ret)
+				goto err;
+			break;
+		case IWCH_QP_STATE_ERROR:
+			qhp->attr.state = IWCH_QP_STATE_ERROR;
+			flush_qp(qhp, &flag);
+			break;
+		default:
+			ret = -EINVAL;
+			goto out;
+		}
+		break;
+	case IWCH_QP_STATE_RTS:
+		switch (attrs->next_state) {
+		case IWCH_QP_STATE_CLOSING:
+			BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2);
+			qhp->attr.state = IWCH_QP_STATE_CLOSING;
+			if (!internal) {
+				abort=0;
+				disconnect = 1;
+				ep = qhp->ep;
+			}
+			break;
+		case IWCH_QP_STATE_TERMINATE:
+			qhp->attr.state = IWCH_QP_STATE_TERMINATE;
+			if (t3b_device(qhp->rhp))
+				cxio_set_wq_in_error(&qhp->wq);
+			if (!internal)
+				terminate = 1;
+			break;
+		case IWCH_QP_STATE_ERROR:
+			qhp->attr.state = IWCH_QP_STATE_ERROR;
+			if (!internal) {
+				abort=1;
+				disconnect = 1;
+				ep = qhp->ep;
+			}
+			goto err;
+			break;
+		default:
+			ret = -EINVAL;
+			goto out;
+		}
+		break;
+	case IWCH_QP_STATE_CLOSING:
+		if (!internal) {
+			ret = -EINVAL;
+			goto out;
+		}
+		switch (attrs->next_state) {
+			case IWCH_QP_STATE_IDLE:
+				qhp->attr.state = IWCH_QP_STATE_IDLE;
+				qhp->attr.llp_stream_handle = NULL;
+				put_ep(&qhp->ep->com);
+				qhp->ep = NULL;
+				wake_up(&qhp->wait);
+				break;
+			case IWCH_QP_STATE_ERROR:
+				goto err;
+			default:
+				ret = -EINVAL;
+				goto err;
+		}
+		break;
+	case IWCH_QP_STATE_ERROR:
+		if (attrs->next_state != IWCH_QP_STATE_IDLE) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		if (!Q_EMPTY(qhp->wq.sq_rptr, qhp->wq.sq_wptr) ||
+		    !Q_EMPTY(qhp->wq.rq_rptr, qhp->wq.rq_wptr)) {
+			ret = -EINVAL;
+			goto out;
+		}
+		qhp->attr.state = IWCH_QP_STATE_IDLE;
+		memset(&qhp->attr, 0, sizeof(qhp->attr));
+		break;
+	case IWCH_QP_STATE_TERMINATE:
+		if (!internal) {
+			ret = -EINVAL;
+			goto out;
+		}
+		goto err;
+		break;
+	default:
+		printk(KERN_ERR "%s in a bad state %d\n",
+		       __FUNCTION__, qhp->attr.state);
+		ret = -EINVAL;
+		goto err;
+		break;
+	}
+	goto out;
+err:
+	PDBG("%s disassociating ep %p qpid 0x%x\n", __FUNCTION__, qhp->ep,
+	     qhp->wq.qpid);
+
+	/* disassociate the LLP connection */
+	qhp->attr.llp_stream_handle = NULL;
+	ep = qhp->ep;
+	qhp->ep = NULL;
+	qhp->attr.state = IWCH_QP_STATE_ERROR;
+	free=1;
+	wake_up(&qhp->wait);
+	BUG_ON(!ep);
+	flush_qp(qhp, &flag);
+out:
+	spin_unlock_irqrestore(&qhp->lock, flag);
+
+	if (terminate)
+		iwch_post_terminate(qhp, NULL);
+
+	/*
+	 * If disconnect is 1, then we need to initiate a disconnect
+	 * on the EP.  This can be a normal close (RTS->CLOSING) or
+	 * an abnormal close (RTS/CLOSING->ERROR).
+	 */
+	if (disconnect)
+		iwch_ep_disconnect(ep, abort, GFP_KERNEL);
+
+	/*
+	 * If free is 1, then we've disassociated the EP from the QP
+	 * and we need to dereference the EP.
+	 */
+	if (free)
+		put_ep(&ep->com);
+
+	PDBG("%s exit state %d\n", __FUNCTION__, qhp->attr.state);
+	return ret;
+}
+
+static int quiesce_qp(struct iwch_qp *qhp)
+{
+	spin_lock_irq(&qhp->lock);
+	iwch_quiesce_tid(qhp->ep);
+	qhp->flags |= QP_QUIESCED;
+	spin_unlock_irq(&qhp->lock);
+	return 0;
+}
+
+static int resume_qp(struct iwch_qp *qhp)
+{
+	spin_lock_irq(&qhp->lock);
+	iwch_resume_tid(qhp->ep);
+	qhp->flags &= ~QP_QUIESCED;
+	spin_unlock_irq(&qhp->lock);
+	return 0;
+}
+
+int iwch_quiesce_qps(struct iwch_cq *chp)
+{
+	int i;
+	struct iwch_qp *qhp;
+
+	for (i=0; i < T3_MAX_NUM_QP; i++) {
+		qhp = get_qhp(chp->rhp, i);
+		if (!qhp)
+			continue;
+		if ((qhp->attr.rcq == chp->cq.cqid) && !qp_quiesced(qhp)) {
+			quiesce_qp(qhp);
+			continue;
+		}
+		if ((qhp->attr.scq == chp->cq.cqid) && !qp_quiesced(qhp))
+			quiesce_qp(qhp);
+	}
+	return 0;
+}
+
+int iwch_resume_qps(struct iwch_cq *chp)
+{
+	int i;
+	struct iwch_qp *qhp;
+
+	for (i=0; i < T3_MAX_NUM_QP; i++) {
+		qhp = get_qhp(chp->rhp, i);
+		if (!qhp)
+			continue;
+		if ((qhp->attr.rcq == chp->cq.cqid) && qp_quiesced(qhp)) {
+			resume_qp(qhp);
+			continue;
+		}
+		if ((qhp->attr.scq == chp->cq.cqid) && qp_quiesced(qhp))
+			resume_qp(qhp);
+	}
+	return 0;
+}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_user.h b/drivers/infiniband/hw/cxgb3/iwch_user.h
new file mode 100644
index 0000000..cb7086f
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/iwch_user.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2006 Chelsio, 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 __IWCH_USER_H__
+#define __IWCH_USER_H__
+
+#define IWCH_UVERBS_ABI_VERSION	1
+
+/*
+ * Make sure that all structs defined in this file remain laid out so
+ * that they pack the same way on 32-bit and 64-bit architectures (to
+ * avoid incompatibility between 32-bit userspace and 64-bit kernels).
+ * In particular do not use pointer types -- pass pointers in __u64
+ * instead.
+ */
+struct iwch_create_cq_req {
+	__u64 user_rptr_addr;
+};
+
+struct iwch_create_cq_resp {
+	__u64 key;
+	__u32 cqid;
+	__u32 size_log2;
+};
+
+struct iwch_create_qp_resp {
+	__u64 key;
+	__u64 db_key;
+	__u32 qpid;
+	__u32 size_log2;
+	__u32 sq_size_log2;
+	__u32 rq_size_log2;
+};
+
+struct iwch_reg_user_mr_resp {
+	__u32 pbl_addr;
+};
+#endif
diff --git a/drivers/infiniband/hw/cxgb3/tcb.h b/drivers/infiniband/hw/cxgb3/tcb.h
new file mode 100644
index 0000000..c702dc1
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb3/tcb.h
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2007 Chelsio, 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 _TCB_DEFS_H
+#define _TCB_DEFS_H
+
+#define W_TCB_T_STATE    0
+#define S_TCB_T_STATE    0
+#define M_TCB_T_STATE    0xfULL
+#define V_TCB_T_STATE(x) ((x) << S_TCB_T_STATE)
+
+#define W_TCB_TIMER    0
+#define S_TCB_TIMER    4
+#define M_TCB_TIMER    0x1ULL
+#define V_TCB_TIMER(x) ((x) << S_TCB_TIMER)
+
+#define W_TCB_DACK_TIMER    0
+#define S_TCB_DACK_TIMER    5
+#define M_TCB_DACK_TIMER    0x1ULL
+#define V_TCB_DACK_TIMER(x) ((x) << S_TCB_DACK_TIMER)
+
+#define W_TCB_DEL_FLAG    0
+#define S_TCB_DEL_FLAG    6
+#define M_TCB_DEL_FLAG    0x1ULL
+#define V_TCB_DEL_FLAG(x) ((x) << S_TCB_DEL_FLAG)
+
+#define W_TCB_L2T_IX    0
+#define S_TCB_L2T_IX    7
+#define M_TCB_L2T_IX    0x7ffULL
+#define V_TCB_L2T_IX(x) ((x) << S_TCB_L2T_IX)
+
+#define W_TCB_SMAC_SEL    0
+#define S_TCB_SMAC_SEL    18
+#define M_TCB_SMAC_SEL    0x3ULL
+#define V_TCB_SMAC_SEL(x) ((x) << S_TCB_SMAC_SEL)
+
+#define W_TCB_TOS    0
+#define S_TCB_TOS    20
+#define M_TCB_TOS    0x3fULL
+#define V_TCB_TOS(x) ((x) << S_TCB_TOS)
+
+#define W_TCB_MAX_RT    0
+#define S_TCB_MAX_RT    26
+#define M_TCB_MAX_RT    0xfULL
+#define V_TCB_MAX_RT(x) ((x) << S_TCB_MAX_RT)
+
+#define W_TCB_T_RXTSHIFT    0
+#define S_TCB_T_RXTSHIFT    30
+#define M_TCB_T_RXTSHIFT    0xfULL
+#define V_TCB_T_RXTSHIFT(x) ((x) << S_TCB_T_RXTSHIFT)
+
+#define W_TCB_T_DUPACKS    1
+#define S_TCB_T_DUPACKS    2
+#define M_TCB_T_DUPACKS    0xfULL
+#define V_TCB_T_DUPACKS(x) ((x) << S_TCB_T_DUPACKS)
+
+#define W_TCB_T_MAXSEG    1
+#define S_TCB_T_MAXSEG    6
+#define M_TCB_T_MAXSEG    0xfULL
+#define V_TCB_T_MAXSEG(x) ((x) << S_TCB_T_MAXSEG)
+
+#define W_TCB_T_FLAGS1    1
+#define S_TCB_T_FLAGS1    10
+#define M_TCB_T_FLAGS1    0xffffffffULL
+#define V_TCB_T_FLAGS1(x) ((x) << S_TCB_T_FLAGS1)
+
+#define W_TCB_T_MIGRATION    1
+#define S_TCB_T_MIGRATION    20
+#define M_TCB_T_MIGRATION    0x1ULL
+#define V_TCB_T_MIGRATION(x) ((x) << S_TCB_T_MIGRATION)
+
+#define W_TCB_T_FLAGS2    2
+#define S_TCB_T_FLAGS2    10
+#define M_TCB_T_FLAGS2    0x7fULL
+#define V_TCB_T_FLAGS2(x) ((x) << S_TCB_T_FLAGS2)
+
+#define W_TCB_SND_SCALE    2
+#define S_TCB_SND_SCALE    17
+#define M_TCB_SND_SCALE    0xfULL
+#define V_TCB_SND_SCALE(x) ((x) << S_TCB_SND_SCALE)
+
+#define W_TCB_RCV_SCALE    2
+#define S_TCB_RCV_SCALE    21
+#define M_TCB_RCV_SCALE    0xfULL
+#define V_TCB_RCV_SCALE(x) ((x) << S_TCB_RCV_SCALE)
+
+#define W_TCB_SND_UNA_RAW    2
+#define S_TCB_SND_UNA_RAW    25
+#define M_TCB_SND_UNA_RAW    0x7ffffffULL
+#define V_TCB_SND_UNA_RAW(x) ((x) << S_TCB_SND_UNA_RAW)
+
+#define W_TCB_SND_NXT_RAW    3
+#define S_TCB_SND_NXT_RAW    20
+#define M_TCB_SND_NXT_RAW    0x7ffffffULL
+#define V_TCB_SND_NXT_RAW(x) ((x) << S_TCB_SND_NXT_RAW)
+
+#define W_TCB_RCV_NXT    4
+#define S_TCB_RCV_NXT    15
+#define M_TCB_RCV_NXT    0xffffffffULL
+#define V_TCB_RCV_NXT(x) ((x) << S_TCB_RCV_NXT)
+
+#define W_TCB_RCV_ADV    5
+#define S_TCB_RCV_ADV    15
+#define M_TCB_RCV_ADV    0xffffULL
+#define V_TCB_RCV_ADV(x) ((x) << S_TCB_RCV_ADV)
+
+#define W_TCB_SND_MAX_RAW    5
+#define S_TCB_SND_MAX_RAW    31
+#define M_TCB_SND_MAX_RAW    0x7ffffffULL
+#define V_TCB_SND_MAX_RAW(x) ((x) << S_TCB_SND_MAX_RAW)
+
+#define W_TCB_SND_CWND    6
+#define S_TCB_SND_CWND    26
+#define M_TCB_SND_CWND    0x7ffffffULL
+#define V_TCB_SND_CWND(x) ((x) << S_TCB_SND_CWND)
+
+#define W_TCB_SND_SSTHRESH    7
+#define S_TCB_SND_SSTHRESH    21
+#define M_TCB_SND_SSTHRESH    0x7ffffffULL
+#define V_TCB_SND_SSTHRESH(x) ((x) << S_TCB_SND_SSTHRESH)
+
+#define W_TCB_T_RTT_TS_RECENT_AGE    8
+#define S_TCB_T_RTT_TS_RECENT_AGE    16
+#define M_TCB_T_RTT_TS_RECENT_AGE    0xffffffffULL
+#define V_TCB_T_RTT_TS_RECENT_AGE(x) ((x) << S_TCB_T_RTT_TS_RECENT_AGE)
+
+#define W_TCB_T_RTSEQ_RECENT    9
+#define S_TCB_T_RTSEQ_RECENT    16
+#define M_TCB_T_RTSEQ_RECENT    0xffffffffULL
+#define V_TCB_T_RTSEQ_RECENT(x) ((x) << S_TCB_T_RTSEQ_RECENT)
+
+#define W_TCB_T_SRTT    10
+#define S_TCB_T_SRTT    16
+#define M_TCB_T_SRTT    0xffffULL
+#define V_TCB_T_SRTT(x) ((x) << S_TCB_T_SRTT)
+
+#define W_TCB_T_RTTVAR    11
+#define S_TCB_T_RTTVAR    0
+#define M_TCB_T_RTTVAR    0xffffULL
+#define V_TCB_T_RTTVAR(x) ((x) << S_TCB_T_RTTVAR)
+
+#define W_TCB_TS_LAST_ACK_SENT_RAW    11
+#define S_TCB_TS_LAST_ACK_SENT_RAW    16
+#define M_TCB_TS_LAST_ACK_SENT_RAW    0x7ffffffULL
+#define V_TCB_TS_LAST_ACK_SENT_RAW(x) ((x) << S_TCB_TS_LAST_ACK_SENT_RAW)
+
+#define W_TCB_DIP    12
+#define S_TCB_DIP    11
+#define M_TCB_DIP    0xffffffffULL
+#define V_TCB_DIP(x) ((x) << S_TCB_DIP)
+
+#define W_TCB_SIP    13
+#define S_TCB_SIP    11
+#define M_TCB_SIP    0xffffffffULL
+#define V_TCB_SIP(x) ((x) << S_TCB_SIP)
+
+#define W_TCB_DP    14
+#define S_TCB_DP    11
+#define M_TCB_DP    0xffffULL
+#define V_TCB_DP(x) ((x) << S_TCB_DP)
+
+#define W_TCB_SP    14
+#define S_TCB_SP    27
+#define M_TCB_SP    0xffffULL
+#define V_TCB_SP(x) ((x) << S_TCB_SP)
+
+#define W_TCB_TIMESTAMP    15
+#define S_TCB_TIMESTAMP    11
+#define M_TCB_TIMESTAMP    0xffffffffULL
+#define V_TCB_TIMESTAMP(x) ((x) << S_TCB_TIMESTAMP)
+
+#define W_TCB_TIMESTAMP_OFFSET    16
+#define S_TCB_TIMESTAMP_OFFSET    11
+#define M_TCB_TIMESTAMP_OFFSET    0xfULL
+#define V_TCB_TIMESTAMP_OFFSET(x) ((x) << S_TCB_TIMESTAMP_OFFSET)
+
+#define W_TCB_TX_MAX    16
+#define S_TCB_TX_MAX    15
+#define M_TCB_TX_MAX    0xffffffffULL
+#define V_TCB_TX_MAX(x) ((x) << S_TCB_TX_MAX)
+
+#define W_TCB_TX_HDR_PTR_RAW    17
+#define S_TCB_TX_HDR_PTR_RAW    15
+#define M_TCB_TX_HDR_PTR_RAW    0x1ffffULL
+#define V_TCB_TX_HDR_PTR_RAW(x) ((x) << S_TCB_TX_HDR_PTR_RAW)
+
+#define W_TCB_TX_LAST_PTR_RAW    18
+#define S_TCB_TX_LAST_PTR_RAW    0
+#define M_TCB_TX_LAST_PTR_RAW    0x1ffffULL
+#define V_TCB_TX_LAST_PTR_RAW(x) ((x) << S_TCB_TX_LAST_PTR_RAW)
+
+#define W_TCB_TX_COMPACT    18
+#define S_TCB_TX_COMPACT    17
+#define M_TCB_TX_COMPACT    0x1ULL
+#define V_TCB_TX_COMPACT(x) ((x) << S_TCB_TX_COMPACT)
+
+#define W_TCB_RX_COMPACT    18
+#define S_TCB_RX_COMPACT    18
+#define M_TCB_RX_COMPACT    0x1ULL
+#define V_TCB_RX_COMPACT(x) ((x) << S_TCB_RX_COMPACT)
+
+#define W_TCB_RCV_WND    18
+#define S_TCB_RCV_WND    19
+#define M_TCB_RCV_WND    0x7ffffffULL
+#define V_TCB_RCV_WND(x) ((x) << S_TCB_RCV_WND)
+
+#define W_TCB_RX_HDR_OFFSET    19
+#define S_TCB_RX_HDR_OFFSET    14
+#define M_TCB_RX_HDR_OFFSET    0x7ffffffULL
+#define V_TCB_RX_HDR_OFFSET(x) ((x) << S_TCB_RX_HDR_OFFSET)
+
+#define W_TCB_RX_FRAG0_START_IDX_RAW    20
+#define S_TCB_RX_FRAG0_START_IDX_RAW    9
+#define M_TCB_RX_FRAG0_START_IDX_RAW    0x7ffffffULL
+#define V_TCB_RX_FRAG0_START_IDX_RAW(x) ((x) << S_TCB_RX_FRAG0_START_IDX_RAW)
+
+#define W_TCB_RX_FRAG1_START_IDX_OFFSET    21
+#define S_TCB_RX_FRAG1_START_IDX_OFFSET    4
+#define M_TCB_RX_FRAG1_START_IDX_OFFSET    0x7ffffffULL
+#define V_TCB_RX_FRAG1_START_IDX_OFFSET(x) ((x) << S_TCB_RX_FRAG1_START_IDX_OFFSET)
+
+#define W_TCB_RX_FRAG0_LEN    21
+#define S_TCB_RX_FRAG0_LEN    31
+#define M_TCB_RX_FRAG0_LEN    0x7ffffffULL
+#define V_TCB_RX_FRAG0_LEN(x) ((x) << S_TCB_RX_FRAG0_LEN)
+
+#define W_TCB_RX_FRAG1_LEN    22
+#define S_TCB_RX_FRAG1_LEN    26
+#define M_TCB_RX_FRAG1_LEN    0x7ffffffULL
+#define V_TCB_RX_FRAG1_LEN(x) ((x) << S_TCB_RX_FRAG1_LEN)
+
+#define W_TCB_NEWRENO_RECOVER    23
+#define S_TCB_NEWRENO_RECOVER    21
+#define M_TCB_NEWRENO_RECOVER    0x7ffffffULL
+#define V_TCB_NEWRENO_RECOVER(x) ((x) << S_TCB_NEWRENO_RECOVER)
+
+#define W_TCB_PDU_HAVE_LEN    24
+#define S_TCB_PDU_HAVE_LEN    16
+#define M_TCB_PDU_HAVE_LEN    0x1ULL
+#define V_TCB_PDU_HAVE_LEN(x) ((x) << S_TCB_PDU_HAVE_LEN)
+
+#define W_TCB_PDU_LEN    24
+#define S_TCB_PDU_LEN    17
+#define M_TCB_PDU_LEN    0xffffULL
+#define V_TCB_PDU_LEN(x) ((x) << S_TCB_PDU_LEN)
+
+#define W_TCB_RX_QUIESCE    25
+#define S_TCB_RX_QUIESCE    1
+#define M_TCB_RX_QUIESCE    0x1ULL
+#define V_TCB_RX_QUIESCE(x) ((x) << S_TCB_RX_QUIESCE)
+
+#define W_TCB_RX_PTR_RAW    25
+#define S_TCB_RX_PTR_RAW    2
+#define M_TCB_RX_PTR_RAW    0x1ffffULL
+#define V_TCB_RX_PTR_RAW(x) ((x) << S_TCB_RX_PTR_RAW)
+
+#define W_TCB_CPU_NO    25
+#define S_TCB_CPU_NO    19
+#define M_TCB_CPU_NO    0x7fULL
+#define V_TCB_CPU_NO(x) ((x) << S_TCB_CPU_NO)
+
+#define W_TCB_ULP_TYPE    25
+#define S_TCB_ULP_TYPE    26
+#define M_TCB_ULP_TYPE    0xfULL
+#define V_TCB_ULP_TYPE(x) ((x) << S_TCB_ULP_TYPE)
+
+#define W_TCB_RX_FRAG1_PTR_RAW    25
+#define S_TCB_RX_FRAG1_PTR_RAW    30
+#define M_TCB_RX_FRAG1_PTR_RAW    0x1ffffULL
+#define V_TCB_RX_FRAG1_PTR_RAW(x) ((x) << S_TCB_RX_FRAG1_PTR_RAW)
+
+#define W_TCB_RX_FRAG2_START_IDX_OFFSET_RAW    26
+#define S_TCB_RX_FRAG2_START_IDX_OFFSET_RAW    15
+#define M_TCB_RX_FRAG2_START_IDX_OFFSET_RAW    0x7ffffffULL
+#define V_TCB_RX_FRAG2_START_IDX_OFFSET_RAW(x) ((x) << S_TCB_RX_FRAG2_START_IDX_OFFSET_RAW)
+
+#define W_TCB_RX_FRAG2_PTR_RAW    27
+#define S_TCB_RX_FRAG2_PTR_RAW    10
+#define M_TCB_RX_FRAG2_PTR_RAW    0x1ffffULL
+#define V_TCB_RX_FRAG2_PTR_RAW(x) ((x) << S_TCB_RX_FRAG2_PTR_RAW)
+
+#define W_TCB_RX_FRAG2_LEN_RAW    27
+#define S_TCB_RX_FRAG2_LEN_RAW    27
+#define M_TCB_RX_FRAG2_LEN_RAW    0x7ffffffULL
+#define V_TCB_RX_FRAG2_LEN_RAW(x) ((x) << S_TCB_RX_FRAG2_LEN_RAW)
+
+#define W_TCB_RX_FRAG3_PTR_RAW    28
+#define S_TCB_RX_FRAG3_PTR_RAW    22
+#define M_TCB_RX_FRAG3_PTR_RAW    0x1ffffULL
+#define V_TCB_RX_FRAG3_PTR_RAW(x) ((x) << S_TCB_RX_FRAG3_PTR_RAW)
+
+#define W_TCB_RX_FRAG3_LEN_RAW    29
+#define S_TCB_RX_FRAG3_LEN_RAW    7
+#define M_TCB_RX_FRAG3_LEN_RAW    0x7ffffffULL
+#define V_TCB_RX_FRAG3_LEN_RAW(x) ((x) << S_TCB_RX_FRAG3_LEN_RAW)
+
+#define W_TCB_RX_FRAG3_START_IDX_OFFSET_RAW    30
+#define S_TCB_RX_FRAG3_START_IDX_OFFSET_RAW    2
+#define M_TCB_RX_FRAG3_START_IDX_OFFSET_RAW    0x7ffffffULL
+#define V_TCB_RX_FRAG3_START_IDX_OFFSET_RAW(x) ((x) << S_TCB_RX_FRAG3_START_IDX_OFFSET_RAW)
+
+#define W_TCB_PDU_HDR_LEN    30
+#define S_TCB_PDU_HDR_LEN    29
+#define M_TCB_PDU_HDR_LEN    0xffULL
+#define V_TCB_PDU_HDR_LEN(x) ((x) << S_TCB_PDU_HDR_LEN)
+
+#define W_TCB_SLUSH1    31
+#define S_TCB_SLUSH1    5
+#define M_TCB_SLUSH1    0x7ffffULL
+#define V_TCB_SLUSH1(x) ((x) << S_TCB_SLUSH1)
+
+#define W_TCB_ULP_RAW    31
+#define S_TCB_ULP_RAW    24
+#define M_TCB_ULP_RAW    0xffULL
+#define V_TCB_ULP_RAW(x) ((x) << S_TCB_ULP_RAW)
+
+#define W_TCB_DDP_RDMAP_VERSION    25
+#define S_TCB_DDP_RDMAP_VERSION    30
+#define M_TCB_DDP_RDMAP_VERSION    0x1ULL
+#define V_TCB_DDP_RDMAP_VERSION(x) ((x) << S_TCB_DDP_RDMAP_VERSION)
+
+#define W_TCB_MARKER_ENABLE_RX    25
+#define S_TCB_MARKER_ENABLE_RX    31
+#define M_TCB_MARKER_ENABLE_RX    0x1ULL
+#define V_TCB_MARKER_ENABLE_RX(x) ((x) << S_TCB_MARKER_ENABLE_RX)
+
+#define W_TCB_MARKER_ENABLE_TX    26
+#define S_TCB_MARKER_ENABLE_TX    0
+#define M_TCB_MARKER_ENABLE_TX    0x1ULL
+#define V_TCB_MARKER_ENABLE_TX(x) ((x) << S_TCB_MARKER_ENABLE_TX)
+
+#define W_TCB_CRC_ENABLE    26
+#define S_TCB_CRC_ENABLE    1
+#define M_TCB_CRC_ENABLE    0x1ULL
+#define V_TCB_CRC_ENABLE(x) ((x) << S_TCB_CRC_ENABLE)
+
+#define W_TCB_IRS_ULP    26
+#define S_TCB_IRS_ULP    2
+#define M_TCB_IRS_ULP    0x1ffULL
+#define V_TCB_IRS_ULP(x) ((x) << S_TCB_IRS_ULP)
+
+#define W_TCB_ISS_ULP    26
+#define S_TCB_ISS_ULP    11
+#define M_TCB_ISS_ULP    0x1ffULL
+#define V_TCB_ISS_ULP(x) ((x) << S_TCB_ISS_ULP)
+
+#define W_TCB_TX_PDU_LEN    26
+#define S_TCB_TX_PDU_LEN    20
+#define M_TCB_TX_PDU_LEN    0x3fffULL
+#define V_TCB_TX_PDU_LEN(x) ((x) << S_TCB_TX_PDU_LEN)
+
+#define W_TCB_TX_PDU_OUT    27
+#define S_TCB_TX_PDU_OUT    2
+#define M_TCB_TX_PDU_OUT    0x1ULL
+#define V_TCB_TX_PDU_OUT(x) ((x) << S_TCB_TX_PDU_OUT)
+
+#define W_TCB_CQ_IDX_SQ    27
+#define S_TCB_CQ_IDX_SQ    3
+#define M_TCB_CQ_IDX_SQ    0xffffULL
+#define V_TCB_CQ_IDX_SQ(x) ((x) << S_TCB_CQ_IDX_SQ)
+
+#define W_TCB_CQ_IDX_RQ    27
+#define S_TCB_CQ_IDX_RQ    19
+#define M_TCB_CQ_IDX_RQ    0xffffULL
+#define V_TCB_CQ_IDX_RQ(x) ((x) << S_TCB_CQ_IDX_RQ)
+
+#define W_TCB_QP_ID    28
+#define S_TCB_QP_ID    3
+#define M_TCB_QP_ID    0xffffULL
+#define V_TCB_QP_ID(x) ((x) << S_TCB_QP_ID)
+
+#define W_TCB_PD_ID    28
+#define S_TCB_PD_ID    19
+#define M_TCB_PD_ID    0xffffULL
+#define V_TCB_PD_ID(x) ((x) << S_TCB_PD_ID)
+
+#define W_TCB_STAG    29
+#define S_TCB_STAG    3
+#define M_TCB_STAG    0xffffffffULL
+#define V_TCB_STAG(x) ((x) << S_TCB_STAG)
+
+#define W_TCB_RQ_START    30
+#define S_TCB_RQ_START    3
+#define M_TCB_RQ_START    0x3ffffffULL
+#define V_TCB_RQ_START(x) ((x) << S_TCB_RQ_START)
+
+#define W_TCB_RQ_MSN    30
+#define S_TCB_RQ_MSN    29
+#define M_TCB_RQ_MSN    0x3ffULL
+#define V_TCB_RQ_MSN(x) ((x) << S_TCB_RQ_MSN)
+
+#define W_TCB_RQ_MAX_OFFSET    31
+#define S_TCB_RQ_MAX_OFFSET    7
+#define M_TCB_RQ_MAX_OFFSET    0xfULL
+#define V_TCB_RQ_MAX_OFFSET(x) ((x) << S_TCB_RQ_MAX_OFFSET)
+
+#define W_TCB_RQ_WRITE_PTR    31
+#define S_TCB_RQ_WRITE_PTR    11
+#define M_TCB_RQ_WRITE_PTR    0x3ffULL
+#define V_TCB_RQ_WRITE_PTR(x) ((x) << S_TCB_RQ_WRITE_PTR)
+
+#define W_TCB_INB_WRITE_PERM    31
+#define S_TCB_INB_WRITE_PERM    21
+#define M_TCB_INB_WRITE_PERM    0x1ULL
+#define V_TCB_INB_WRITE_PERM(x) ((x) << S_TCB_INB_WRITE_PERM)
+
+#define W_TCB_INB_READ_PERM    31
+#define S_TCB_INB_READ_PERM    22
+#define M_TCB_INB_READ_PERM    0x1ULL
+#define V_TCB_INB_READ_PERM(x) ((x) << S_TCB_INB_READ_PERM)
+
+#define W_TCB_ORD_L_BIT_VLD    31
+#define S_TCB_ORD_L_BIT_VLD    23
+#define M_TCB_ORD_L_BIT_VLD    0x1ULL
+#define V_TCB_ORD_L_BIT_VLD(x) ((x) << S_TCB_ORD_L_BIT_VLD)
+
+#define W_TCB_RDMAP_OPCODE    31
+#define S_TCB_RDMAP_OPCODE    24
+#define M_TCB_RDMAP_OPCODE    0xfULL
+#define V_TCB_RDMAP_OPCODE(x) ((x) << S_TCB_RDMAP_OPCODE)
+
+#define W_TCB_TX_FLUSH    31
+#define S_TCB_TX_FLUSH    28
+#define M_TCB_TX_FLUSH    0x1ULL
+#define V_TCB_TX_FLUSH(x) ((x) << S_TCB_TX_FLUSH)
+
+#define W_TCB_TX_OOS_RXMT    31
+#define S_TCB_TX_OOS_RXMT    29
+#define M_TCB_TX_OOS_RXMT    0x1ULL
+#define V_TCB_TX_OOS_RXMT(x) ((x) << S_TCB_TX_OOS_RXMT)
+
+#define W_TCB_TX_OOS_TXMT    31
+#define S_TCB_TX_OOS_TXMT    30
+#define M_TCB_TX_OOS_TXMT    0x1ULL
+#define V_TCB_TX_OOS_TXMT(x) ((x) << S_TCB_TX_OOS_TXMT)
+
+#define W_TCB_SLUSH_AUX2    31
+#define S_TCB_SLUSH_AUX2    31
+#define M_TCB_SLUSH_AUX2    0x1ULL
+#define V_TCB_SLUSH_AUX2(x) ((x) << S_TCB_SLUSH_AUX2)
+
+#define W_TCB_RX_FRAG1_PTR_RAW2    25
+#define S_TCB_RX_FRAG1_PTR_RAW2    30
+#define M_TCB_RX_FRAG1_PTR_RAW2    0x1ffffULL
+#define V_TCB_RX_FRAG1_PTR_RAW2(x) ((x) << S_TCB_RX_FRAG1_PTR_RAW2)
+
+#define W_TCB_RX_DDP_FLAGS    26
+#define S_TCB_RX_DDP_FLAGS    15
+#define M_TCB_RX_DDP_FLAGS    0x3ffULL
+#define V_TCB_RX_DDP_FLAGS(x) ((x) << S_TCB_RX_DDP_FLAGS)
+
+#define W_TCB_SLUSH_AUX3    26
+#define S_TCB_SLUSH_AUX3    31
+#define M_TCB_SLUSH_AUX3    0x1ffULL
+#define V_TCB_SLUSH_AUX3(x) ((x) << S_TCB_SLUSH_AUX3)
+
+#define W_TCB_RX_DDP_BUF0_OFFSET    27
+#define S_TCB_RX_DDP_BUF0_OFFSET    8
+#define M_TCB_RX_DDP_BUF0_OFFSET    0x3fffffULL
+#define V_TCB_RX_DDP_BUF0_OFFSET(x) ((x) << S_TCB_RX_DDP_BUF0_OFFSET)
+
+#define W_TCB_RX_DDP_BUF0_LEN    27
+#define S_TCB_RX_DDP_BUF0_LEN    30
+#define M_TCB_RX_DDP_BUF0_LEN    0x3fffffULL
+#define V_TCB_RX_DDP_BUF0_LEN(x) ((x) << S_TCB_RX_DDP_BUF0_LEN)
+
+#define W_TCB_RX_DDP_BUF1_OFFSET    28
+#define S_TCB_RX_DDP_BUF1_OFFSET    20
+#define M_TCB_RX_DDP_BUF1_OFFSET    0x3fffffULL
+#define V_TCB_RX_DDP_BUF1_OFFSET(x) ((x) << S_TCB_RX_DDP_BUF1_OFFSET)
+
+#define W_TCB_RX_DDP_BUF1_LEN    29
+#define S_TCB_RX_DDP_BUF1_LEN    10
+#define M_TCB_RX_DDP_BUF1_LEN    0x3fffffULL
+#define V_TCB_RX_DDP_BUF1_LEN(x) ((x) << S_TCB_RX_DDP_BUF1_LEN)
+
+#define W_TCB_RX_DDP_BUF0_TAG    30
+#define S_TCB_RX_DDP_BUF0_TAG    0
+#define M_TCB_RX_DDP_BUF0_TAG    0xffffffffULL
+#define V_TCB_RX_DDP_BUF0_TAG(x) ((x) << S_TCB_RX_DDP_BUF0_TAG)
+
+#define W_TCB_RX_DDP_BUF1_TAG    31
+#define S_TCB_RX_DDP_BUF1_TAG    0
+#define M_TCB_RX_DDP_BUF1_TAG    0xffffffffULL
+#define V_TCB_RX_DDP_BUF1_TAG(x) ((x) << S_TCB_RX_DDP_BUF1_TAG)
+
+#define S_TF_DACK    10
+#define V_TF_DACK(x) ((x) << S_TF_DACK)
+
+#define S_TF_NAGLE    11
+#define V_TF_NAGLE(x) ((x) << S_TF_NAGLE)
+
+#define S_TF_RECV_SCALE    12
+#define V_TF_RECV_SCALE(x) ((x) << S_TF_RECV_SCALE)
+
+#define S_TF_RECV_TSTMP    13
+#define V_TF_RECV_TSTMP(x) ((x) << S_TF_RECV_TSTMP)
+
+#define S_TF_RECV_SACK    14
+#define V_TF_RECV_SACK(x) ((x) << S_TF_RECV_SACK)
+
+#define S_TF_TURBO    15
+#define V_TF_TURBO(x) ((x) << S_TF_TURBO)
+
+#define S_TF_KEEPALIVE    16
+#define V_TF_KEEPALIVE(x) ((x) << S_TF_KEEPALIVE)
+
+#define S_TF_TCAM_BYPASS    17
+#define V_TF_TCAM_BYPASS(x) ((x) << S_TF_TCAM_BYPASS)
+
+#define S_TF_CORE_FIN    18
+#define V_TF_CORE_FIN(x) ((x) << S_TF_CORE_FIN)
+
+#define S_TF_CORE_MORE    19
+#define V_TF_CORE_MORE(x) ((x) << S_TF_CORE_MORE)
+
+#define S_TF_MIGRATING    20
+#define V_TF_MIGRATING(x) ((x) << S_TF_MIGRATING)
+
+#define S_TF_ACTIVE_OPEN    21
+#define V_TF_ACTIVE_OPEN(x) ((x) << S_TF_ACTIVE_OPEN)
+
+#define S_TF_ASK_MODE    22
+#define V_TF_ASK_MODE(x) ((x) << S_TF_ASK_MODE)
+
+#define S_TF_NON_OFFLOAD    23
+#define V_TF_NON_OFFLOAD(x) ((x) << S_TF_NON_OFFLOAD)
+
+#define S_TF_MOD_SCHD    24
+#define V_TF_MOD_SCHD(x) ((x) << S_TF_MOD_SCHD)
+
+#define S_TF_MOD_SCHD_REASON0    25
+#define V_TF_MOD_SCHD_REASON0(x) ((x) << S_TF_MOD_SCHD_REASON0)
+
+#define S_TF_MOD_SCHD_REASON1    26
+#define V_TF_MOD_SCHD_REASON1(x) ((x) << S_TF_MOD_SCHD_REASON1)
+
+#define S_TF_MOD_SCHD_RX    27
+#define V_TF_MOD_SCHD_RX(x) ((x) << S_TF_MOD_SCHD_RX)
+
+#define S_TF_CORE_PUSH    28
+#define V_TF_CORE_PUSH(x) ((x) << S_TF_CORE_PUSH)
+
+#define S_TF_RCV_COALESCE_ENABLE    29
+#define V_TF_RCV_COALESCE_ENABLE(x) ((x) << S_TF_RCV_COALESCE_ENABLE)
+
+#define S_TF_RCV_COALESCE_PUSH    30
+#define V_TF_RCV_COALESCE_PUSH(x) ((x) << S_TF_RCV_COALESCE_PUSH)
+
+#define S_TF_RCV_COALESCE_LAST_PSH    31
+#define V_TF_RCV_COALESCE_LAST_PSH(x) ((x) << S_TF_RCV_COALESCE_LAST_PSH)
+
+#define S_TF_RCV_COALESCE_HEARTBEAT    32
+#define V_TF_RCV_COALESCE_HEARTBEAT(x) ((x) << S_TF_RCV_COALESCE_HEARTBEAT)
+
+#define S_TF_HALF_CLOSE    33
+#define V_TF_HALF_CLOSE(x) ((x) << S_TF_HALF_CLOSE)
+
+#define S_TF_DACK_MSS    34
+#define V_TF_DACK_MSS(x) ((x) << S_TF_DACK_MSS)
+
+#define S_TF_CCTRL_SEL0    35
+#define V_TF_CCTRL_SEL0(x) ((x) << S_TF_CCTRL_SEL0)
+
+#define S_TF_CCTRL_SEL1    36
+#define V_TF_CCTRL_SEL1(x) ((x) << S_TF_CCTRL_SEL1)
+
+#define S_TF_TCP_NEWRENO_FAST_RECOVERY    37
+#define V_TF_TCP_NEWRENO_FAST_RECOVERY(x) ((x) << S_TF_TCP_NEWRENO_FAST_RECOVERY)
+
+#define S_TF_TX_PACE_AUTO    38
+#define V_TF_TX_PACE_AUTO(x) ((x) << S_TF_TX_PACE_AUTO)
+
+#define S_TF_PEER_FIN_HELD    39
+#define V_TF_PEER_FIN_HELD(x) ((x) << S_TF_PEER_FIN_HELD)
+
+#define S_TF_CORE_URG    40
+#define V_TF_CORE_URG(x) ((x) << S_TF_CORE_URG)
+
+#define S_TF_RDMA_ERROR    41
+#define V_TF_RDMA_ERROR(x) ((x) << S_TF_RDMA_ERROR)
+
+#define S_TF_SSWS_DISABLED    42
+#define V_TF_SSWS_DISABLED(x) ((x) << S_TF_SSWS_DISABLED)
+
+#define S_TF_DUPACK_COUNT_ODD    43
+#define V_TF_DUPACK_COUNT_ODD(x) ((x) << S_TF_DUPACK_COUNT_ODD)
+
+#define S_TF_TX_CHANNEL    44
+#define V_TF_TX_CHANNEL(x) ((x) << S_TF_TX_CHANNEL)
+
+#define S_TF_RX_CHANNEL    45
+#define V_TF_RX_CHANNEL(x) ((x) << S_TF_RX_CHANNEL)
+
+#define S_TF_TX_PACE_FIXED    46
+#define V_TF_TX_PACE_FIXED(x) ((x) << S_TF_TX_PACE_FIXED)
+
+#define S_TF_RDMA_FLM_ERROR    47
+#define V_TF_RDMA_FLM_ERROR(x) ((x) << S_TF_RDMA_FLM_ERROR)
+
+#define S_TF_RX_FLOW_CONTROL_DISABLE    48
+#define V_TF_RX_FLOW_CONTROL_DISABLE(x) ((x) << S_TF_RX_FLOW_CONTROL_DISABLE)
+
+#endif /* _TCB_DEFS_H */
diff --git a/drivers/infiniband/hw/ehca/Kconfig b/drivers/infiniband/hw/ehca/Kconfig
index 727b10d..1a85459 100644
--- a/drivers/infiniband/hw/ehca/Kconfig
+++ b/drivers/infiniband/hw/ehca/Kconfig
@@ -7,11 +7,3 @@
 	To compile the driver as a module, choose M here. The module
 	will be called ib_ehca.
 
-config INFINIBAND_EHCA_SCALING
-	bool "Scaling support (EXPERIMENTAL)"
-	depends on IBMEBUS && INFINIBAND_EHCA && HOTPLUG_CPU && EXPERIMENTAL
-	default y
-	---help---
-	eHCA scaling support schedules the CQ callbacks to different CPUs.
-
-	To enable this feature choose Y here.
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index cf95ee4..40404c9 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -42,8 +42,6 @@
 #ifndef __EHCA_CLASSES_H__
 #define __EHCA_CLASSES_H__
 
-#include "ehca_classes.h"
-#include "ipz_pt_fn.h"
 
 struct ehca_module;
 struct ehca_qp;
@@ -54,15 +52,23 @@
 struct ehca_pd;
 struct ehca_av;
 
-#ifdef CONFIG_PPC64
-#include "ehca_classes_pSeries.h"
-#endif
-
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_user_verbs.h>
 
+#ifdef CONFIG_PPC64
+#include "ehca_classes_pSeries.h"
+#endif
+#include "ipz_pt_fn.h"
+#include "ehca_qes.h"
 #include "ehca_irq.h"
 
+#define EHCA_EQE_CACHE_SIZE 20
+
+struct ehca_eqe_cache_entry {
+	struct ehca_eqe *eqe;
+	struct ehca_cq *cq;
+};
+
 struct ehca_eq {
 	u32 length;
 	struct ipz_queue ipz_queue;
@@ -74,6 +80,8 @@
 	spinlock_t spinlock;
 	struct tasklet_struct interrupt_task;
 	u32 ist;
+	spinlock_t irq_spinlock;
+	struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE];
 };
 
 struct ehca_sport {
@@ -269,6 +277,7 @@
 extern int ehca_static_rate;
 extern int ehca_port_act_time;
 extern int ehca_use_hp_mr;
+extern int ehca_scaling_code;
 
 struct ipzu_queue_resp {
 	u32 qe_size;      /* queue entry size */
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 9291a86..6ebfa27 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -134,14 +134,13 @@
 	if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
 		return ERR_PTR(-EINVAL);
 
-	my_cq = kmem_cache_alloc(cq_cache, GFP_KERNEL);
+	my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL);
 	if (!my_cq) {
 		ehca_err(device, "Out of memory for ehca_cq struct device=%p",
 			 device);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	memset(my_cq, 0, sizeof(struct ehca_cq));
 	memset(&param, 0, sizeof(struct ehca_alloc_cq_parms));
 
 	spin_lock_init(&my_cq->spinlock);
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index 5281dec..4961eb8 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -61,6 +61,7 @@
 	struct ib_device *ib_dev = &shca->ib_device;
 
 	spin_lock_init(&eq->spinlock);
+	spin_lock_init(&eq->irq_spinlock);
 	eq->is_initialized = 0;
 
 	if (type != EHCA_EQ && type != EHCA_NEQ) {
@@ -122,7 +123,7 @@
 	/* register interrupt handlers and initialize work queues */
 	if (type == EHCA_EQ) {
 		ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq,
-					  SA_INTERRUPT, "ehca_eq",
+					  IRQF_DISABLED, "ehca_eq",
 					  (void *)shca);
 		if (ret < 0)
 			ehca_err(ib_dev, "Can't map interrupt handler.");
@@ -130,7 +131,7 @@
 		tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
 	} else if (type == EHCA_NEQ) {
 		ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq,
-					  SA_INTERRUPT, "ehca_neq",
+					  IRQF_DISABLED, "ehca_neq",
 					  (void *)shca);
 		if (ret < 0)
 			ehca_err(ib_dev, "Can't map interrupt handler.");
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index b7be950..30eb45d 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -162,6 +162,9 @@
 	props->active_width    = IB_WIDTH_12X;
 	props->active_speed    = 0x1;
 
+	/* at the moment (logical) link state is always LINK_UP */
+	props->phys_state      = 0x5;
+
 query_port1:
 	ehca_free_fw_ctrlblock(rblock);
 
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index c069be8..3ec53c6 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -63,15 +63,11 @@
 #define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52,63)
 #define ERROR_DATA_TYPE        EHCA_BMASK_IBM(0,7)
 
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
-
 static void queue_comp_task(struct ehca_cq *__cq);
 
 static struct ehca_comp_pool* pool;
 static struct notifier_block comp_pool_callback_nb;
 
-#endif
-
 static inline void comp_event_callback(struct ehca_cq *cq)
 {
 	if (!cq->ib_cq.comp_handler)
@@ -206,7 +202,7 @@
 }
 
 static void cq_event_callback(struct ehca_shca *shca,
-					  u64 eqe)
+			      u64 eqe)
 {
 	struct ehca_cq *cq;
 	unsigned long flags;
@@ -318,7 +314,7 @@
 			  "disruptive port %x configuration change", port);
 
 		ehca_info(&shca->ib_device,
-			 "port %x is inactive.", port);
+			  "port %x is inactive.", port);
 		event.device = &shca->ib_device;
 		event.event = IB_EVENT_PORT_ERR;
 		event.element.port_num = port;
@@ -326,7 +322,7 @@
 		ib_dispatch_event(&event);
 
 		ehca_info(&shca->ib_device,
-			 "port %x is active.", port);
+			  "port %x is active.", port);
 		event.device = &shca->ib_device;
 		event.event = IB_EVENT_PORT_ACTIVE;
 		event.element.port_num = port;
@@ -401,115 +397,170 @@
 	return IRQ_HANDLED;
 }
 
-void ehca_tasklet_eq(unsigned long data)
+
+static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
 {
-	struct ehca_shca *shca = (struct ehca_shca*)data;
-	struct ehca_eqe *eqe;
-	int int_state;
-	int query_cnt = 0;
-
-	do {
-		eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
-
-		if ((shca->hw_level >= 2) && eqe)
-			int_state = 1;
-		else
-			int_state = 0;
-
-		while ((int_state == 1) || eqe) {
-			while (eqe) {
-				u64 eqe_value = eqe->entry;
-
-				ehca_dbg(&shca->ib_device,
-					 "eqe_value=%lx", eqe_value);
-
-				/* TODO: better structure */
-				if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT,
-						   eqe_value)) {
-					unsigned long flags;
-					u32 token;
-					struct ehca_cq *cq;
-
-					ehca_dbg(&shca->ib_device,
-						 "... completion event");
-					token =
-						EHCA_BMASK_GET(EQE_CQ_TOKEN,
-							       eqe_value);
-					spin_lock_irqsave(&ehca_cq_idr_lock,
-							  flags);
-					cq = idr_find(&ehca_cq_idr, token);
-
-					if (cq == NULL) {
-						spin_unlock_irqrestore(&ehca_cq_idr_lock,
-								       flags);
-						break;
-					}
-
-					reset_eq_pending(cq);
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
-					queue_comp_task(cq);
-					spin_unlock_irqrestore(&ehca_cq_idr_lock,
-							       flags);
-#else
-					spin_unlock_irqrestore(&ehca_cq_idr_lock,
-							       flags);
-					comp_event_callback(cq);
-#endif
-				} else {
-					ehca_dbg(&shca->ib_device,
-						 "... non completion event");
-					parse_identifier(shca, eqe_value);
-				}
-				eqe =
-					(struct ehca_eqe *)ehca_poll_eq(shca,
-								    &shca->eq);
-			}
-
-			if (shca->hw_level >= 2) {
-				int_state =
-				    hipz_h_query_int_state(shca->ipz_hca_handle,
-							   shca->eq.ist);
-				query_cnt++;
-				iosync();
-				if (query_cnt >= 100) {
-					query_cnt = 0;
-					int_state = 0;
-				}
-			}
-			eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
-
+	u64 eqe_value;
+	u32 token;
+	unsigned long flags;
+	struct ehca_cq *cq;
+	eqe_value = eqe->entry;
+	ehca_dbg(&shca->ib_device, "eqe_value=%lx", eqe_value);
+	if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
+		ehca_dbg(&shca->ib_device, "... completion event");
+		token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
+		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+		cq = idr_find(&ehca_cq_idr, token);
+		if (cq == NULL) {
+			spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+			ehca_err(&shca->ib_device,
+				 "Invalid eqe for non-existing cq token=%x",
+				 token);
+			return;
 		}
-	} while (int_state != 0);
-
-	return;
+		reset_eq_pending(cq);
+		if (ehca_scaling_code) {
+			queue_comp_task(cq);
+			spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+		} else {
+			spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+			comp_event_callback(cq);
+		}
+	} else {
+		ehca_dbg(&shca->ib_device,
+			 "Got non completion event");
+		parse_identifier(shca, eqe_value);
+	}
 }
 
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
+void ehca_process_eq(struct ehca_shca *shca, int is_irq)
+{
+	struct ehca_eq *eq = &shca->eq;
+	struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache;
+	u64 eqe_value;
+	unsigned long flags;
+	int eqe_cnt, i;
+	int eq_empty = 0;
+
+	spin_lock_irqsave(&eq->irq_spinlock, flags);
+	if (is_irq) {
+		const int max_query_cnt = 100;
+		int query_cnt = 0;
+		int int_state = 1;
+		do {
+			int_state = hipz_h_query_int_state(
+				shca->ipz_hca_handle, eq->ist);
+			query_cnt++;
+			iosync();
+		} while (int_state && query_cnt < max_query_cnt);
+		if (unlikely((query_cnt == max_query_cnt)))
+			ehca_dbg(&shca->ib_device, "int_state=%x query_cnt=%x",
+				 int_state, query_cnt);
+	}
+
+	/* read out all eqes */
+	eqe_cnt = 0;
+	do {
+		u32 token;
+		eqe_cache[eqe_cnt].eqe =
+			(struct ehca_eqe *)ehca_poll_eq(shca, eq);
+		if (!eqe_cache[eqe_cnt].eqe)
+			break;
+		eqe_value = eqe_cache[eqe_cnt].eqe->entry;
+		if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
+			token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
+			spin_lock(&ehca_cq_idr_lock);
+			eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
+			if (!eqe_cache[eqe_cnt].cq) {
+				spin_unlock(&ehca_cq_idr_lock);
+				ehca_err(&shca->ib_device,
+					 "Invalid eqe for non-existing cq "
+					 "token=%x", token);
+				continue;
+			}
+			spin_unlock(&ehca_cq_idr_lock);
+		} else
+			eqe_cache[eqe_cnt].cq = NULL;
+		eqe_cnt++;
+	} while (eqe_cnt < EHCA_EQE_CACHE_SIZE);
+	if (!eqe_cnt) {
+		if (is_irq)
+			ehca_dbg(&shca->ib_device,
+				 "No eqe found for irq event");
+		goto unlock_irq_spinlock;
+	} else if (!is_irq)
+		ehca_dbg(&shca->ib_device, "deadman found %x eqe", eqe_cnt);
+	if (unlikely(eqe_cnt == EHCA_EQE_CACHE_SIZE))
+		ehca_dbg(&shca->ib_device, "too many eqes for one irq event");
+	/* enable irq for new packets */
+	for (i = 0; i < eqe_cnt; i++) {
+		if (eq->eqe_cache[i].cq)
+			reset_eq_pending(eq->eqe_cache[i].cq);
+	}
+	/* check eq */
+	spin_lock(&eq->spinlock);
+	eq_empty = (!ipz_eqit_eq_peek_valid(&shca->eq.ipz_queue));
+	spin_unlock(&eq->spinlock);
+	/* call completion handler for cached eqes */
+	for (i = 0; i < eqe_cnt; i++)
+		if (eq->eqe_cache[i].cq) {
+			if (ehca_scaling_code) {
+				spin_lock(&ehca_cq_idr_lock);
+				queue_comp_task(eq->eqe_cache[i].cq);
+				spin_unlock(&ehca_cq_idr_lock);
+			} else
+				comp_event_callback(eq->eqe_cache[i].cq);
+		} else {
+			ehca_dbg(&shca->ib_device, "Got non completion event");
+			parse_identifier(shca, eq->eqe_cache[i].eqe->entry);
+		}
+	/* poll eq if not empty */
+	if (eq_empty)
+		goto unlock_irq_spinlock;
+	do {
+		struct ehca_eqe *eqe;
+		eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
+		if (!eqe)
+			break;
+		process_eqe(shca, eqe);
+		eqe_cnt++;
+	} while (1);
+
+unlock_irq_spinlock:
+	spin_unlock_irqrestore(&eq->irq_spinlock, flags);
+}
+
+void ehca_tasklet_eq(unsigned long data)
+{
+	ehca_process_eq((struct ehca_shca*)data, 1);
+}
 
 static inline int find_next_online_cpu(struct ehca_comp_pool* pool)
 {
-	unsigned long flags_last_cpu;
+	int cpu;
+	unsigned long flags;
 
+	WARN_ON_ONCE(!in_interrupt());
 	if (ehca_debug_level)
 		ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
 
-	spin_lock_irqsave(&pool->last_cpu_lock, flags_last_cpu);
-	pool->last_cpu = next_cpu(pool->last_cpu, cpu_online_map);
-	if (pool->last_cpu == NR_CPUS)
-		pool->last_cpu = first_cpu(cpu_online_map);
-	spin_unlock_irqrestore(&pool->last_cpu_lock, flags_last_cpu);
+	spin_lock_irqsave(&pool->last_cpu_lock, flags);
+	cpu = next_cpu(pool->last_cpu, cpu_online_map);
+	if (cpu == NR_CPUS)
+		cpu = first_cpu(cpu_online_map);
+	pool->last_cpu = cpu;
+	spin_unlock_irqrestore(&pool->last_cpu_lock, flags);
 
-	return pool->last_cpu;
+	return cpu;
 }
 
 static void __queue_comp_task(struct ehca_cq *__cq,
 			      struct ehca_cpu_comp_task *cct)
 {
-	unsigned long flags_cct;
-	unsigned long flags_cq;
+	unsigned long flags;
 
-	spin_lock_irqsave(&cct->task_lock, flags_cct);
-	spin_lock_irqsave(&__cq->task_lock, flags_cq);
+	spin_lock_irqsave(&cct->task_lock, flags);
+	spin_lock(&__cq->task_lock);
 
 	if (__cq->nr_callbacks == 0) {
 		__cq->nr_callbacks++;
@@ -520,8 +571,8 @@
 	else
 		__cq->nr_callbacks++;
 
-	spin_unlock_irqrestore(&__cq->task_lock, flags_cq);
-	spin_unlock_irqrestore(&cct->task_lock, flags_cct);
+	spin_unlock(&__cq->task_lock);
+	spin_unlock_irqrestore(&cct->task_lock, flags);
 }
 
 static void queue_comp_task(struct ehca_cq *__cq)
@@ -532,69 +583,69 @@
 
 	cpu = get_cpu();
 	cpu_id = find_next_online_cpu(pool);
-
 	BUG_ON(!cpu_online(cpu_id));
 
 	cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
+	BUG_ON(!cct);
 
 	if (cct->cq_jobs > 0) {
 		cpu_id = find_next_online_cpu(pool);
 		cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
+		BUG_ON(!cct);
 	}
 
 	__queue_comp_task(__cq, cct);
-
-	put_cpu();
-
-	return;
 }
 
 static void run_comp_task(struct ehca_cpu_comp_task* cct)
 {
 	struct ehca_cq *cq;
-	unsigned long flags_cct;
-	unsigned long flags_cq;
+	unsigned long flags;
 
-	spin_lock_irqsave(&cct->task_lock, flags_cct);
+	spin_lock_irqsave(&cct->task_lock, flags);
 
 	while (!list_empty(&cct->cq_list)) {
 		cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
-		spin_unlock_irqrestore(&cct->task_lock, flags_cct);
+		spin_unlock_irqrestore(&cct->task_lock, flags);
 		comp_event_callback(cq);
-		spin_lock_irqsave(&cct->task_lock, flags_cct);
+		spin_lock_irqsave(&cct->task_lock, flags);
 
-		spin_lock_irqsave(&cq->task_lock, flags_cq);
+		spin_lock(&cq->task_lock);
 		cq->nr_callbacks--;
 		if (cq->nr_callbacks == 0) {
 			list_del_init(cct->cq_list.next);
 			cct->cq_jobs--;
 		}
-		spin_unlock_irqrestore(&cq->task_lock, flags_cq);
-
+		spin_unlock(&cq->task_lock);
 	}
 
-	spin_unlock_irqrestore(&cct->task_lock, flags_cct);
-
-	return;
+	spin_unlock_irqrestore(&cct->task_lock, flags);
 }
 
 static int comp_task(void *__cct)
 {
 	struct ehca_cpu_comp_task* cct = __cct;
+	int cql_empty;
 	DECLARE_WAITQUEUE(wait, current);
 
 	set_current_state(TASK_INTERRUPTIBLE);
 	while(!kthread_should_stop()) {
 		add_wait_queue(&cct->wait_queue, &wait);
 
-		if (list_empty(&cct->cq_list))
+		spin_lock_irq(&cct->task_lock);
+		cql_empty = list_empty(&cct->cq_list);
+		spin_unlock_irq(&cct->task_lock);
+		if (cql_empty)
 			schedule();
 		else
 			__set_current_state(TASK_RUNNING);
 
 		remove_wait_queue(&cct->wait_queue, &wait);
 
-		if (!list_empty(&cct->cq_list))
+		spin_lock_irq(&cct->task_lock);
+		cql_empty = list_empty(&cct->cq_list);
+		spin_unlock_irq(&cct->task_lock);
+		if (!cql_empty)
 			run_comp_task(__cct);
 
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -637,8 +688,6 @@
 
 	if (task)
 		kthread_stop(task);
-
-	return;
 }
 
 static void take_over_work(struct ehca_comp_pool *pool,
@@ -654,11 +703,11 @@
 	list_splice_init(&cct->cq_list, &list);
 
 	while(!list_empty(&list)) {
-	       cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
+		cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
 
-	       list_del(&cq->entry);
-	       __queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks,
-						 smp_processor_id()));
+		list_del(&cq->entry);
+		__queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks,
+						  smp_processor_id()));
 	}
 
 	spin_unlock_irqrestore(&cct->task_lock, flags_cct);
@@ -708,14 +757,14 @@
 	return NOTIFY_OK;
 }
 
-#endif
-
 int ehca_create_comp_pool(void)
 {
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
 	int cpu;
 	struct task_struct *task;
 
+	if (!ehca_scaling_code)
+		return 0;
+
 	pool = kzalloc(sizeof(struct ehca_comp_pool), GFP_KERNEL);
 	if (pool == NULL)
 		return -ENOMEM;
@@ -740,23 +789,25 @@
 	comp_pool_callback_nb.notifier_call = comp_pool_callback;
 	comp_pool_callback_nb.priority =0;
 	register_cpu_notifier(&comp_pool_callback_nb);
-#endif
+
+	printk(KERN_INFO "eHCA scaling code enabled\n");
 
 	return 0;
 }
 
 void ehca_destroy_comp_pool(void)
 {
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
 	int i;
 
+	if (!ehca_scaling_code)
+		return;
+
 	unregister_cpu_notifier(&comp_pool_callback_nb);
 
 	for (i = 0; i < NR_CPUS; i++) {
 		if (cpu_online(i))
 			destroy_comp_task(pool, i);
 	}
-#endif
-
-	return;
+	free_percpu(pool->cpu_comp_tasks);
+	kfree(pool);
 }
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h
index be579cc..6ed06ee 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.h
+++ b/drivers/infiniband/hw/ehca/ehca_irq.h
@@ -56,6 +56,7 @@
 
 irqreturn_t ehca_interrupt_eq(int irq, void *dev_id);
 void ehca_tasklet_eq(unsigned long data);
+void ehca_process_eq(struct ehca_shca *shca, int is_irq);
 
 struct ehca_cpu_comp_task {
 	wait_queue_head_t wait_queue;
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 1155bcf..c183512 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -52,7 +52,7 @@
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
 MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0020");
+MODULE_VERSION("SVNEHCA_0021");
 
 int ehca_open_aqp1     = 0;
 int ehca_debug_level   = 0;
@@ -62,6 +62,7 @@
 int ehca_port_act_time = 30;
 int ehca_poll_all_eqs  = 1;
 int ehca_static_rate   = -1;
+int ehca_scaling_code  = 1;
 
 module_param_named(open_aqp1,     ehca_open_aqp1,     int, 0);
 module_param_named(debug_level,   ehca_debug_level,   int, 0);
@@ -71,6 +72,7 @@
 module_param_named(port_act_time, ehca_port_act_time, int, 0);
 module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  int, 0);
 module_param_named(static_rate,   ehca_static_rate,   int, 0);
+module_param_named(scaling_code,   ehca_scaling_code,   int, 0);
 
 MODULE_PARM_DESC(open_aqp1,
 		 "AQP1 on startup (0: no (default), 1: yes)");
@@ -91,6 +93,8 @@
 		 " (0: no, 1: yes (default))");
 MODULE_PARM_DESC(static_rate,
 		 "set permanent static rate (default: disabled)");
+MODULE_PARM_DESC(scaling_code,
+		 "set scaling code (0: disabled, 1: enabled/default)");
 
 spinlock_t ehca_qp_idr_lock;
 spinlock_t ehca_cq_idr_lock;
@@ -432,8 +436,8 @@
 
 static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf)
 {
-	return  snprintf(buf, PAGE_SIZE, "%d\n",
-			 ehca_debug_level);
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			ehca_debug_level);
 }
 
 static ssize_t ehca_store_debug_level(struct device_driver *ddp,
@@ -778,8 +782,24 @@
 
 	spin_lock(&shca_list_lock);
 	list_for_each_entry(shca, &shca_list, shca_list) {
-		if (shca->eq.is_initialized)
-			ehca_tasklet_eq((unsigned long)(void*)shca);
+		if (shca->eq.is_initialized) {
+			/* call deadman proc only if eq ptr does not change */
+			struct ehca_eq *eq = &shca->eq;
+			int max = 3;
+			volatile u64 q_ofs, q_ofs2;
+			u64 flags;
+			spin_lock_irqsave(&eq->spinlock, flags);
+			q_ofs = eq->ipz_queue.current_q_offset;
+			spin_unlock_irqrestore(&eq->spinlock, flags);
+			do {
+				spin_lock_irqsave(&eq->spinlock, flags);
+				q_ofs2 = eq->ipz_queue.current_q_offset;
+				spin_unlock_irqrestore(&eq->spinlock, flags);
+				max--;
+			} while (q_ofs == q_ofs2 && max > 0);
+			if (q_ofs == q_ofs2)
+				ehca_process_eq(shca, 0);
+		}
 	}
 	mod_timer(&poll_eqs_timer, jiffies + HZ);
 	spin_unlock(&shca_list_lock);
@@ -790,7 +810,7 @@
 	int ret;
 
 	printk(KERN_INFO "eHCA Infiniband Device Driver "
-	                 "(Rel.: SVNEHCA_0020)\n");
+	       "(Rel.: SVNEHCA_0021)\n");
 	idr_init(&ehca_qp_idr);
 	idr_init(&ehca_cq_idr);
 	spin_lock_init(&ehca_qp_idr_lock);
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index cfb362a..d22ab56 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -53,9 +53,8 @@
 {
 	struct ehca_mr *me;
 
-	me = kmem_cache_alloc(mr_cache, GFP_KERNEL);
+	me = kmem_cache_zalloc(mr_cache, GFP_KERNEL);
 	if (me) {
-		memset(me, 0, sizeof(struct ehca_mr));
 		spin_lock_init(&me->mrlock);
 	} else
 		ehca_gen_err("alloc failed");
@@ -72,9 +71,8 @@
 {
 	struct ehca_mw *me;
 
-	me = kmem_cache_alloc(mw_cache, GFP_KERNEL);
+	me = kmem_cache_zalloc(mw_cache, GFP_KERNEL);
 	if (me) {
-		memset(me, 0, sizeof(struct ehca_mw));
 		spin_lock_init(&me->mwlock);
 	} else
 		ehca_gen_err("alloc failed");
diff --git a/drivers/infiniband/hw/ehca/ehca_pd.c b/drivers/infiniband/hw/ehca/ehca_pd.c
index d5345e5..79d0591 100644
--- a/drivers/infiniband/hw/ehca/ehca_pd.c
+++ b/drivers/infiniband/hw/ehca/ehca_pd.c
@@ -50,14 +50,13 @@
 {
 	struct ehca_pd *pd;
 
-	pd = kmem_cache_alloc(pd_cache, GFP_KERNEL);
+	pd = kmem_cache_zalloc(pd_cache, GFP_KERNEL);
 	if (!pd) {
 		ehca_err(device, "device=%p context=%p out of memory",
 			 device, context);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	memset(pd, 0, sizeof(struct ehca_pd));
 	pd->ownpid = current->tgid;
 
 	/*
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 95efef9..df0516f 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -450,13 +450,12 @@
 	if (pd->uobject && udata)
 		context = pd->uobject->context;
 
-	my_qp = kmem_cache_alloc(qp_cache, GFP_KERNEL);
+	my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);
 	if (!my_qp) {
 		ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	memset(my_qp, 0, sizeof(struct ehca_qp));
 	memset (&parms, 0, sizeof(struct ehca_alloc_qp_parms));
 	spin_lock_init(&my_qp->spinlock_s);
 	spin_lock_init(&my_qp->spinlock_r);
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.h b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
index dc3bda2..8199c45 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.h
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
@@ -79,7 +79,7 @@
 	if (q_offset >= queue->queue_length)
 		return NULL;
 	current_page = (queue->queue_pages)[q_offset >> EHCA_PAGESHIFT];
-	return  &current_page->entries[q_offset & (EHCA_PAGESIZE - 1)];
+	return &current_page->entries[q_offset & (EHCA_PAGESIZE - 1)];
 }
 
 /*
@@ -247,6 +247,15 @@
 	return ret;
 }
 
+static inline void *ipz_eqit_eq_peek_valid(struct ipz_queue *queue)
+{
+	void *ret = ipz_qeit_get(queue);
+	u32 qe = *(u8 *) ret;
+	if ((qe >> 7) != (queue->toggle_state & 1))
+		return NULL;
+	return ret;
+}
+
 /* returns address (GX) of first queue entry */
 static inline u64 ipz_qpt_get_firstpage(struct ipz_qpt *qpt)
 {
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index 28c087b..0f13a21 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -59,7 +59,7 @@
 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 = {
+static const struct file_operations diag_file_ops = {
 	.owner = THIS_MODULE,
 	.write = ipath_diag_write,
 	.read = ipath_diag_read,
@@ -71,7 +71,7 @@
 				   const char __user *data,
 				   size_t count, loff_t *off);
 
-static struct file_operations diagpkt_file_ops = {
+static const struct file_operations diagpkt_file_ops = {
 	.owner = THIS_MODULE,
 	.write = ipath_diagpkt_write,
 };
diff --git a/drivers/infiniband/hw/ipath/ipath_dma.c b/drivers/infiniband/hw/ipath/ipath_dma.c
index 6e0f2b8..f6f9490 100644
--- a/drivers/infiniband/hw/ipath/ipath_dma.c
+++ b/drivers/infiniband/hw/ipath/ipath_dma.c
@@ -96,8 +96,8 @@
 	BUG_ON(!valid_dma_direction(direction));
 }
 
-int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents,
-		 enum dma_data_direction direction)
+static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents,
+			enum dma_data_direction direction)
 {
 	u64 addr;
 	int i;
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index b932bcb..5d64ff8 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -54,7 +54,7 @@
 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 = {
+static const struct file_operations ipath_file_ops = {
 	.owner = THIS_MODULE,
 	.write = ipath_write,
 	.open = ipath_open,
@@ -2153,7 +2153,7 @@
 
 static struct class *ipath_class;
 
-static int init_cdev(int minor, char *name, struct file_operations *fops,
+static int init_cdev(int minor, char *name, const struct file_operations *fops,
 		     struct cdev **cdevp, struct class_device **class_devp)
 {
 	const dev_t dev = MKDEV(IPATH_MAJOR, minor);
@@ -2210,7 +2210,7 @@
 	return ret;
 }
 
-int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
+int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
 		    struct cdev **cdevp, struct class_device **class_devp)
 {
 	return init_cdev(minor, name, fops, cdevp, class_devp);
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 79a60f0..5b40a84 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -47,7 +47,7 @@
 static struct super_block *ipath_super;
 
 static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
-			 int mode, struct file_operations *fops,
+			 int mode, const struct file_operations *fops,
 			 void *data)
 {
 	int error;
@@ -81,7 +81,7 @@
 
 static int create_file(const char *name, mode_t mode,
 		       struct dentry *parent, struct dentry **dentry,
-		       struct file_operations *fops, void *data)
+		       const struct file_operations *fops, void *data)
 {
 	int error;
 
@@ -105,7 +105,7 @@
 				       sizeof ipath_stats);
 }
 
-static struct file_operations atomic_stats_ops = {
+static const struct file_operations atomic_stats_ops = {
 	.read = atomic_stats_read,
 };
 
@@ -127,7 +127,7 @@
 				       sizeof counters);
 }
 
-static struct file_operations atomic_counters_ops = {
+static const struct file_operations atomic_counters_ops = {
 	.read = atomic_counters_read,
 };
 
@@ -166,7 +166,7 @@
 				       sizeof nodeinfo);
 }
 
-static struct file_operations atomic_node_info_ops = {
+static const struct file_operations atomic_node_info_ops = {
 	.read = atomic_node_info_read,
 };
 
@@ -291,7 +291,7 @@
 				       sizeof portinfo);
 }
 
-static struct file_operations atomic_port_info_ops = {
+static const struct file_operations atomic_port_info_ops = {
 	.read = atomic_port_info_read,
 };
 
@@ -394,7 +394,7 @@
 	return ret;
 }
 
-static struct file_operations flash_ops = {
+static const struct file_operations flash_ops = {
 	.read = flash_read,
 	.write = flash_write,
 };
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
index 7468477..9934825 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
@@ -1534,7 +1534,7 @@
  * @kbase: ipath_base_info pointer
  *
  * We set the PCIE flag because the lower bandwidth on PCIe vs
- * HyperTransport can affect some user packet algorithims.
+ * HyperTransport can affect some user packet algorithms.
  */
 static int ipath_ht_get_base_info(struct ipath_portdata *pd, void *kbase)
 {
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
index ae8bf99..05918e1 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
@@ -1293,7 +1293,7 @@
  * @kbase: ipath_base_info pointer
  *
  * We set the PCIE flag because the lower bandwidth on PCIe vs
- * HyperTransport can affect some user packet algorithims.
+ * HyperTransport can affect some user packet algorithms.
  */
 static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase)
 {
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 986b212..6d8d05f 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -593,7 +593,7 @@
 void ipath_disarm_senderrbufs(struct ipath_devdata *);
 
 struct file_operations;
-int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
+int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
 		    struct cdev **cdevp, struct class_device **class_devp);
 void ipath_cdev_cleanup(struct cdev **cdevp,
 			struct class_device **class_devp);
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 968d151..7131446 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1051,7 +1051,11 @@
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_EQ_OFFSET);
 	dev_lim->max_eqs = 1 << (field & 0x7);
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_MTT_OFFSET);
-	dev_lim->reserved_mtts = 1 << (field >> 4);
+	if (mthca_is_memfree(dev))
+		dev_lim->reserved_mtts = ALIGN((1 << (field >> 4)) * sizeof(u64),
+					       MTHCA_MTT_SEG_SIZE) / MTHCA_MTT_SEG_SIZE;
+	else
+		dev_lim->reserved_mtts = 1 << (field >> 4);
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_MRW_SZ_OFFSET);
 	dev_lim->max_mrw_sz = 1 << field;
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_MRW_OFFSET);
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index fe5cecf..b7e42ef 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -464,6 +464,8 @@
 int mthca_pd_alloc(struct mthca_dev *dev, int privileged, struct mthca_pd *pd);
 void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd);
 
+int mthca_write_mtt_size(struct mthca_dev *dev);
+
 struct mthca_mtt *mthca_alloc_mtt(struct mthca_dev *dev, int size);
 void mthca_free_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt);
 int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 44bc6cc..0d9b7d0 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -379,7 +379,7 @@
 
 	mdev->fw.arbel.fw_icm =
 		mthca_alloc_icm(mdev, mdev->fw.arbel.fw_pages,
-				GFP_HIGHUSER | __GFP_NOWARN);
+				GFP_HIGHUSER | __GFP_NOWARN, 0);
 	if (!mdev->fw.arbel.fw_icm) {
 		mthca_err(mdev, "Couldn't allocate FW area, aborting.\n");
 		return -ENOMEM;
@@ -412,7 +412,7 @@
 	mthca_UNMAP_FA(mdev, &status);
 
 err_free:
-	mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
+	mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
 	return err;
 }
 
@@ -441,7 +441,7 @@
 		  (unsigned long long) aux_pages << 2);
 
 	mdev->fw.arbel.aux_icm = mthca_alloc_icm(mdev, aux_pages,
-						 GFP_HIGHUSER | __GFP_NOWARN);
+						 GFP_HIGHUSER | __GFP_NOWARN, 0);
 	if (!mdev->fw.arbel.aux_icm) {
 		mthca_err(mdev, "Couldn't allocate aux memory, aborting.\n");
 		return -ENOMEM;
@@ -464,10 +464,15 @@
 		goto err_unmap_aux;
 	}
 
+	/* CPU writes to non-reserved MTTs, while HCA might DMA to reserved mtts */
+	mdev->limits.reserved_mtts = ALIGN(mdev->limits.reserved_mtts * MTHCA_MTT_SEG_SIZE,
+					   dma_get_cache_alignment()) / MTHCA_MTT_SEG_SIZE;
+
 	mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base,
 							 MTHCA_MTT_SEG_SIZE,
 							 mdev->limits.num_mtt_segs,
-							 mdev->limits.reserved_mtts, 1);
+							 mdev->limits.reserved_mtts,
+							 1, 0);
 	if (!mdev->mr_table.mtt_table) {
 		mthca_err(mdev, "Failed to map MTT context memory, aborting.\n");
 		err = -ENOMEM;
@@ -477,7 +482,8 @@
 	mdev->mr_table.mpt_table = mthca_alloc_icm_table(mdev, init_hca->mpt_base,
 							 dev_lim->mpt_entry_sz,
 							 mdev->limits.num_mpts,
-							 mdev->limits.reserved_mrws, 1);
+							 mdev->limits.reserved_mrws,
+							 1, 1);
 	if (!mdev->mr_table.mpt_table) {
 		mthca_err(mdev, "Failed to map MPT context memory, aborting.\n");
 		err = -ENOMEM;
@@ -487,7 +493,8 @@
 	mdev->qp_table.qp_table = mthca_alloc_icm_table(mdev, init_hca->qpc_base,
 							dev_lim->qpc_entry_sz,
 							mdev->limits.num_qps,
-							mdev->limits.reserved_qps, 0);
+							mdev->limits.reserved_qps,
+							0, 0);
 	if (!mdev->qp_table.qp_table) {
 		mthca_err(mdev, "Failed to map QP context memory, aborting.\n");
 		err = -ENOMEM;
@@ -497,7 +504,8 @@
 	mdev->qp_table.eqp_table = mthca_alloc_icm_table(mdev, init_hca->eqpc_base,
 							 dev_lim->eqpc_entry_sz,
 							 mdev->limits.num_qps,
-							 mdev->limits.reserved_qps, 0);
+							 mdev->limits.reserved_qps,
+							 0, 0);
 	if (!mdev->qp_table.eqp_table) {
 		mthca_err(mdev, "Failed to map EQP context memory, aborting.\n");
 		err = -ENOMEM;
@@ -507,7 +515,7 @@
 	mdev->qp_table.rdb_table = mthca_alloc_icm_table(mdev, init_hca->rdb_base,
 							 MTHCA_RDB_ENTRY_SIZE,
 							 mdev->limits.num_qps <<
-							 mdev->qp_table.rdb_shift,
+							 mdev->qp_table.rdb_shift, 0,
 							 0, 0);
 	if (!mdev->qp_table.rdb_table) {
 		mthca_err(mdev, "Failed to map RDB context memory, aborting\n");
@@ -518,7 +526,8 @@
        mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base,
 						    dev_lim->cqc_entry_sz,
 						    mdev->limits.num_cqs,
-						    mdev->limits.reserved_cqs, 0);
+						    mdev->limits.reserved_cqs,
+						    0, 0);
 	if (!mdev->cq_table.table) {
 		mthca_err(mdev, "Failed to map CQ context memory, aborting.\n");
 		err = -ENOMEM;
@@ -530,7 +539,8 @@
 			mthca_alloc_icm_table(mdev, init_hca->srqc_base,
 					      dev_lim->srq_entry_sz,
 					      mdev->limits.num_srqs,
-					      mdev->limits.reserved_srqs, 0);
+					      mdev->limits.reserved_srqs,
+					      0, 0);
 		if (!mdev->srq_table.table) {
 			mthca_err(mdev, "Failed to map SRQ context memory, "
 				  "aborting.\n");
@@ -550,7 +560,7 @@
 						      mdev->limits.num_amgms,
 						      mdev->limits.num_mgms +
 						      mdev->limits.num_amgms,
-						      0);
+						      0, 0);
 	if (!mdev->mcg_table.table) {
 		mthca_err(mdev, "Failed to map MCG context memory, aborting.\n");
 		err = -ENOMEM;
@@ -588,7 +598,7 @@
 	mthca_UNMAP_ICM_AUX(mdev, &status);
 
 err_free_aux:
-	mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
+	mthca_free_icm(mdev, mdev->fw.arbel.aux_icm, 0);
 
 	return err;
 }
@@ -609,7 +619,7 @@
 	mthca_unmap_eq_icm(mdev);
 
 	mthca_UNMAP_ICM_AUX(mdev, &status);
-	mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
+	mthca_free_icm(mdev, mdev->fw.arbel.aux_icm, 0);
 }
 
 static int mthca_init_arbel(struct mthca_dev *mdev)
@@ -693,7 +703,7 @@
 
 err_stop_fw:
 	mthca_UNMAP_FA(mdev, &status);
-	mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
+	mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
 
 err_disable:
 	if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
@@ -712,7 +722,7 @@
 		mthca_free_icms(mdev);
 
 		mthca_UNMAP_FA(mdev, &status);
-		mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
+		mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
 
 		if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
 			mthca_DISABLE_LAM(mdev, &status);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 6b19645..48f7c65 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -35,6 +35,9 @@
  */
 
 #include <linux/mm.h>
+#include <linux/scatterlist.h>
+
+#include <asm/page.h>
 
 #include "mthca_memfree.h"
 #include "mthca_dev.h"
@@ -58,22 +61,42 @@
 	}                page[0];
 };
 
-void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm)
+static void mthca_free_icm_pages(struct mthca_dev *dev, struct mthca_icm_chunk *chunk)
+{
+	int i;
+
+	if (chunk->nsg > 0)
+		pci_unmap_sg(dev->pdev, chunk->mem, chunk->npages,
+			     PCI_DMA_BIDIRECTIONAL);
+
+	for (i = 0; i < chunk->npages; ++i)
+		__free_pages(chunk->mem[i].page,
+			     get_order(chunk->mem[i].length));
+}
+
+static void mthca_free_icm_coherent(struct mthca_dev *dev, struct mthca_icm_chunk *chunk)
+{
+	int i;
+
+	for (i = 0; i < chunk->npages; ++i) {
+		dma_free_coherent(&dev->pdev->dev, chunk->mem[i].length,
+				  lowmem_page_address(chunk->mem[i].page),
+				  sg_dma_address(&chunk->mem[i]));
+	}
+}
+
+void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm, int coherent)
 {
 	struct mthca_icm_chunk *chunk, *tmp;
-	int i;
 
 	if (!icm)
 		return;
 
 	list_for_each_entry_safe(chunk, tmp, &icm->chunk_list, list) {
-		if (chunk->nsg > 0)
-			pci_unmap_sg(dev->pdev, chunk->mem, chunk->npages,
-				     PCI_DMA_BIDIRECTIONAL);
-
-		for (i = 0; i < chunk->npages; ++i)
-			__free_pages(chunk->mem[i].page,
-				     get_order(chunk->mem[i].length));
+		if (coherent)
+			mthca_free_icm_coherent(dev, chunk);
+		else
+			mthca_free_icm_pages(dev, chunk);
 
 		kfree(chunk);
 	}
@@ -81,12 +104,41 @@
 	kfree(icm);
 }
 
+static int mthca_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_mask)
+{
+	mem->page = alloc_pages(gfp_mask, order);
+	if (!mem->page)
+		return -ENOMEM;
+
+	mem->length = PAGE_SIZE << order;
+	mem->offset = 0;
+	return 0;
+}
+
+static int mthca_alloc_icm_coherent(struct device *dev, struct scatterlist *mem,
+				    int order, gfp_t gfp_mask)
+{
+	void *buf = dma_alloc_coherent(dev, PAGE_SIZE << order, &sg_dma_address(mem),
+				       gfp_mask);
+	if (!buf)
+		return -ENOMEM;
+
+	sg_set_buf(mem, buf, PAGE_SIZE << order);
+	BUG_ON(mem->offset);
+	sg_dma_len(mem) = PAGE_SIZE << order;
+	return 0;
+}
+
 struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
-				  gfp_t gfp_mask)
+				  gfp_t gfp_mask, int coherent)
 {
 	struct mthca_icm *icm;
 	struct mthca_icm_chunk *chunk = NULL;
 	int cur_order;
+	int ret;
+
+	/* We use sg_set_buf for coherent allocs, which assumes low memory */
+	BUG_ON(coherent && (gfp_mask & __GFP_HIGHMEM));
 
 	icm = kmalloc(sizeof *icm, gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
 	if (!icm)
@@ -112,22 +164,31 @@
 		while (1 << cur_order > npages)
 			--cur_order;
 
-		chunk->mem[chunk->npages].page = alloc_pages(gfp_mask, cur_order);
-		if (chunk->mem[chunk->npages].page) {
-			chunk->mem[chunk->npages].length = PAGE_SIZE << cur_order;
-			chunk->mem[chunk->npages].offset = 0;
+		if (coherent)
+			ret = mthca_alloc_icm_coherent(&dev->pdev->dev,
+						       &chunk->mem[chunk->npages],
+						       cur_order, gfp_mask);
+		else
+			ret = mthca_alloc_icm_pages(&chunk->mem[chunk->npages],
+						    cur_order, gfp_mask);
 
-			if (++chunk->npages == MTHCA_ICM_CHUNK_LEN) {
+		if (!ret) {
+			++chunk->npages;
+
+			if (coherent)
+				++chunk->nsg;
+			else if (chunk->npages == MTHCA_ICM_CHUNK_LEN) {
 				chunk->nsg = pci_map_sg(dev->pdev, chunk->mem,
 							chunk->npages,
 							PCI_DMA_BIDIRECTIONAL);
 
 				if (chunk->nsg <= 0)
 					goto fail;
-
-				chunk = NULL;
 			}
 
+			if (chunk->npages == MTHCA_ICM_CHUNK_LEN)
+				chunk = NULL;
+
 			npages -= 1 << cur_order;
 		} else {
 			--cur_order;
@@ -136,7 +197,7 @@
 		}
 	}
 
-	if (chunk) {
+	if (!coherent && chunk) {
 		chunk->nsg = pci_map_sg(dev->pdev, chunk->mem,
 					chunk->npages,
 					PCI_DMA_BIDIRECTIONAL);
@@ -148,7 +209,7 @@
 	return icm;
 
 fail:
-	mthca_free_icm(dev, icm);
+	mthca_free_icm(dev, icm, coherent);
 	return NULL;
 }
 
@@ -167,7 +228,7 @@
 
 	table->icm[i] = mthca_alloc_icm(dev, MTHCA_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
 					(table->lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
-					__GFP_NOWARN);
+					__GFP_NOWARN, table->coherent);
 	if (!table->icm[i]) {
 		ret = -ENOMEM;
 		goto out;
@@ -175,7 +236,7 @@
 
 	if (mthca_MAP_ICM(dev, table->icm[i], table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
 			  &status) || status) {
-		mthca_free_icm(dev, table->icm[i]);
+		mthca_free_icm(dev, table->icm[i], table->coherent);
 		table->icm[i] = NULL;
 		ret = -ENOMEM;
 		goto out;
@@ -204,16 +265,16 @@
 		mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
 				MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
 				&status);
-		mthca_free_icm(dev, table->icm[i]);
+		mthca_free_icm(dev, table->icm[i], table->coherent);
 		table->icm[i] = NULL;
 	}
 
 	mutex_unlock(&table->mutex);
 }
 
-void *mthca_table_find(struct mthca_icm_table *table, int obj)
+void *mthca_table_find(struct mthca_icm_table *table, int obj, dma_addr_t *dma_handle)
 {
-	int idx, offset, i;
+	int idx, offset, dma_offset, i;
 	struct mthca_icm_chunk *chunk;
 	struct mthca_icm *icm;
 	struct page *page = NULL;
@@ -225,13 +286,22 @@
 
 	idx = (obj & (table->num_obj - 1)) * table->obj_size;
 	icm = table->icm[idx / MTHCA_TABLE_CHUNK_SIZE];
-	offset = idx % MTHCA_TABLE_CHUNK_SIZE;
+	dma_offset = offset = idx % MTHCA_TABLE_CHUNK_SIZE;
 
 	if (!icm)
 		goto out;
 
 	list_for_each_entry(chunk, &icm->chunk_list, list) {
 		for (i = 0; i < chunk->npages; ++i) {
+			if (dma_handle && dma_offset >= 0) {
+				if (sg_dma_len(&chunk->mem[i]) > dma_offset)
+					*dma_handle = sg_dma_address(&chunk->mem[i]) +
+						dma_offset;
+				dma_offset -= sg_dma_len(&chunk->mem[i]);
+			}
+			/* DMA mapping can merge pages but not split them,
+			 * so if we found the page, dma_handle has already
+			 * been assigned to. */
 			if (chunk->mem[i].length > offset) {
 				page = chunk->mem[i].page;
 				goto out;
@@ -283,7 +353,7 @@
 struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
 					      u64 virt, int obj_size,
 					      int nobj, int reserved,
-					      int use_lowmem)
+					      int use_lowmem, int use_coherent)
 {
 	struct mthca_icm_table *table;
 	int num_icm;
@@ -302,6 +372,7 @@
 	table->num_obj  = nobj;
 	table->obj_size = obj_size;
 	table->lowmem   = use_lowmem;
+	table->coherent = use_coherent;
 	mutex_init(&table->mutex);
 
 	for (i = 0; i < num_icm; ++i)
@@ -314,12 +385,12 @@
 
 		table->icm[i] = mthca_alloc_icm(dev, chunk_size >> PAGE_SHIFT,
 						(use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
-						__GFP_NOWARN);
+						__GFP_NOWARN, use_coherent);
 		if (!table->icm[i])
 			goto err;
 		if (mthca_MAP_ICM(dev, table->icm[i], virt + i * MTHCA_TABLE_CHUNK_SIZE,
 				  &status) || status) {
-			mthca_free_icm(dev, table->icm[i]);
+			mthca_free_icm(dev, table->icm[i], table->coherent);
 			table->icm[i] = NULL;
 			goto err;
 		}
@@ -339,7 +410,7 @@
 			mthca_UNMAP_ICM(dev, virt + i * MTHCA_TABLE_CHUNK_SIZE,
 					MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
 				        &status);
-			mthca_free_icm(dev, table->icm[i]);
+			mthca_free_icm(dev, table->icm[i], table->coherent);
 		}
 
 	kfree(table);
@@ -357,7 +428,7 @@
 			mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
 					MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
 					&status);
-			mthca_free_icm(dev, table->icm[i]);
+			mthca_free_icm(dev, table->icm[i], table->coherent);
 		}
 
 	kfree(table);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
index 6d42947..5941441 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -69,6 +69,7 @@
 	int               num_obj;
 	int               obj_size;
 	int               lowmem;
+	int               coherent;
 	struct mutex      mutex;
 	struct mthca_icm *icm[0];
 };
@@ -82,17 +83,17 @@
 struct mthca_dev;
 
 struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
-				  gfp_t gfp_mask);
-void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm);
+				  gfp_t gfp_mask, int coherent);
+void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm, int coherent);
 
 struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
 					      u64 virt, int obj_size,
 					      int nobj, int reserved,
-					      int use_lowmem);
+					      int use_lowmem, int use_coherent);
 void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table);
 int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj);
 void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj);
-void *mthca_table_find(struct mthca_icm_table *table, int obj);
+void *mthca_table_find(struct mthca_icm_table *table, int obj, dma_addr_t *dma_handle);
 int mthca_table_get_range(struct mthca_dev *dev, struct mthca_icm_table *table,
 			  int start, int end);
 void mthca_table_put_range(struct mthca_dev *dev, struct mthca_icm_table *table,
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index f71ffa8..6037dd3 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -243,8 +243,8 @@
 	kfree(mtt);
 }
 
-int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
-		    int start_index, u64 *buffer_list, int list_len)
+static int __mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
+			     int start_index, u64 *buffer_list, int list_len)
 {
 	struct mthca_mailbox *mailbox;
 	__be64 *mtt_entry;
@@ -295,6 +295,84 @@
 	return err;
 }
 
+int mthca_write_mtt_size(struct mthca_dev *dev)
+{
+	if (dev->mr_table.fmr_mtt_buddy != &dev->mr_table.mtt_buddy)
+		/*
+		 * Be friendly to WRITE_MTT command
+		 * and leave two empty slots for the
+		 * index and reserved fields of the
+		 * mailbox.
+		 */
+		return PAGE_SIZE / sizeof (u64) - 2;
+
+	/* For Arbel, all MTTs must fit in the same page. */
+	return mthca_is_memfree(dev) ? (PAGE_SIZE / sizeof (u64)) : 0x7ffffff;
+}
+
+void mthca_tavor_write_mtt_seg(struct mthca_dev *dev, struct mthca_mtt *mtt,
+			      int start_index, u64 *buffer_list, int list_len)
+{
+	u64 __iomem *mtts;
+	int i;
+
+	mtts = dev->mr_table.tavor_fmr.mtt_base + mtt->first_seg * MTHCA_MTT_SEG_SIZE +
+		start_index * sizeof (u64);
+	for (i = 0; i < list_len; ++i)
+		mthca_write64_raw(cpu_to_be64(buffer_list[i] | MTHCA_MTT_FLAG_PRESENT),
+				  mtts + i);
+}
+
+void mthca_arbel_write_mtt_seg(struct mthca_dev *dev, struct mthca_mtt *mtt,
+			      int start_index, u64 *buffer_list, int list_len)
+{
+	__be64 *mtts;
+	dma_addr_t dma_handle;
+	int i;
+	int s = start_index * sizeof (u64);
+
+	/* For Arbel, all MTTs must fit in the same page. */
+	BUG_ON(s / PAGE_SIZE != (s + list_len * sizeof(u64) - 1) / PAGE_SIZE);
+	/* Require full segments */
+	BUG_ON(s % MTHCA_MTT_SEG_SIZE);
+
+	mtts = mthca_table_find(dev->mr_table.mtt_table, mtt->first_seg +
+				s / MTHCA_MTT_SEG_SIZE, &dma_handle);
+
+	BUG_ON(!mtts);
+
+	for (i = 0; i < list_len; ++i)
+		mtts[i] = cpu_to_be64(buffer_list[i] | MTHCA_MTT_FLAG_PRESENT);
+
+	dma_sync_single(&dev->pdev->dev, dma_handle, list_len * sizeof (u64), DMA_TO_DEVICE);
+}
+
+int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
+		    int start_index, u64 *buffer_list, int list_len)
+{
+	int size = mthca_write_mtt_size(dev);
+	int chunk;
+
+	if (dev->mr_table.fmr_mtt_buddy != &dev->mr_table.mtt_buddy)
+		return __mthca_write_mtt(dev, mtt, start_index, buffer_list, list_len);
+
+	while (list_len > 0) {
+		chunk = min(size, list_len);
+		if (mthca_is_memfree(dev))
+			mthca_arbel_write_mtt_seg(dev, mtt, start_index,
+						  buffer_list, chunk);
+		else
+			mthca_tavor_write_mtt_seg(dev, mtt, start_index,
+						  buffer_list, chunk);
+
+		list_len    -= chunk;
+		start_index += chunk;
+		buffer_list += chunk;
+	}
+
+	return 0;
+}
+
 static inline u32 tavor_hw_index_to_key(u32 ind)
 {
 	return ind;
@@ -524,7 +602,7 @@
 		if (err)
 			goto err_out_mpt_free;
 
-		mr->mem.arbel.mpt = mthca_table_find(dev->mr_table.mpt_table, key);
+		mr->mem.arbel.mpt = mthca_table_find(dev->mr_table.mpt_table, key, NULL);
 		BUG_ON(!mr->mem.arbel.mpt);
 	} else
 		mr->mem.tavor.mpt = dev->mr_table.tavor_fmr.mpt_base +
@@ -538,7 +616,8 @@
 
 	if (mthca_is_memfree(dev)) {
 		mr->mem.arbel.mtts = mthca_table_find(dev->mr_table.mtt_table,
-						      mr->mtt->first_seg);
+						      mr->mtt->first_seg,
+						      &mr->mem.arbel.dma_handle);
 		BUG_ON(!mr->mem.arbel.mtts);
 	} else
 		mr->mem.tavor.mtts = dev->mr_table.tavor_fmr.mtt_base + mtt_seg;
@@ -712,6 +791,9 @@
 		fmr->mem.arbel.mtts[i] = cpu_to_be64(page_list[i] |
 						     MTHCA_MTT_FLAG_PRESENT);
 
+	dma_sync_single(&dev->pdev->dev, fmr->mem.arbel.dma_handle,
+			list_len * sizeof(u64), DMA_TO_DEVICE);
+
 	fmr->mem.arbel.mpt->key    = cpu_to_be32(key);
 	fmr->mem.arbel.mpt->lkey   = cpu_to_be32(key);
 	fmr->mem.arbel.mpt->length = cpu_to_be64(list_len * (1ull << fmr->attr.page_shift));
@@ -761,7 +843,7 @@
 int mthca_init_mr_table(struct mthca_dev *dev)
 {
 	unsigned long addr;
-	int err, i;
+	int mpts, mtts, err, i;
 
 	err = mthca_alloc_init(&dev->mr_table.mpt_alloc,
 			       dev->limits.num_mpts,
@@ -795,13 +877,21 @@
 			err = -EINVAL;
 			goto err_fmr_mpt;
 		}
+		mpts = mtts = 1 << i;
+	} else {
+		mpts = dev->limits.num_mtt_segs;
+		mtts = dev->limits.num_mpts;
+	}
+
+	if (!mthca_is_memfree(dev) &&
+	    (dev->mthca_flags & MTHCA_FLAG_FMR)) {
 
 		addr = pci_resource_start(dev->pdev, 4) +
 			((pci_resource_len(dev->pdev, 4) - 1) &
 			 dev->mr_table.mpt_base);
 
 		dev->mr_table.tavor_fmr.mpt_base =
-			ioremap(addr, (1 << i) * sizeof(struct mthca_mpt_entry));
+			ioremap(addr, mpts * sizeof(struct mthca_mpt_entry));
 
 		if (!dev->mr_table.tavor_fmr.mpt_base) {
 			mthca_warn(dev, "MPT ioremap for FMR failed.\n");
@@ -814,19 +904,21 @@
 			 dev->mr_table.mtt_base);
 
 		dev->mr_table.tavor_fmr.mtt_base =
-			ioremap(addr, (1 << i) * MTHCA_MTT_SEG_SIZE);
+			ioremap(addr, mtts * MTHCA_MTT_SEG_SIZE);
 		if (!dev->mr_table.tavor_fmr.mtt_base) {
 			mthca_warn(dev, "MTT ioremap for FMR failed.\n");
 			err = -ENOMEM;
 			goto err_fmr_mtt;
 		}
+	}
 
-		err = mthca_buddy_init(&dev->mr_table.tavor_fmr.mtt_buddy, i);
+	if (dev->limits.fmr_reserved_mtts) {
+		err = mthca_buddy_init(&dev->mr_table.tavor_fmr.mtt_buddy, fls(mtts - 1));
 		if (err)
 			goto err_fmr_mtt_buddy;
 
 		/* Prevent regular MRs from using FMR keys */
-		err = mthca_buddy_alloc(&dev->mr_table.mtt_buddy, i);
+		err = mthca_buddy_alloc(&dev->mr_table.mtt_buddy, fls(mtts - 1));
 		if (err)
 			goto err_reserve_fmr;
 
diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c
index 58d44aa..26bf86d 100644
--- a/drivers/infiniband/hw/mthca/mthca_profile.c
+++ b/drivers/infiniband/hw/mthca/mthca_profile.c
@@ -277,7 +277,7 @@
 	 * out of the MR pool. They don't use additional memory, but
 	 * we assign them as part of the HCA profile anyway.
 	 */
-	if (mthca_is_memfree(dev))
+	if (mthca_is_memfree(dev) || BITS_PER_LONG == 64)
 		dev->limits.fmr_reserved_mtts = 0;
 	else
 		dev->limits.fmr_reserved_mtts = request->fmr_reserved_mtts;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 7b96751..0725ad7 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1015,6 +1015,7 @@
 	int shift, n, len;
 	int i, j, k;
 	int err = 0;
+	int write_mtt_size;
 
 	shift = ffs(region->page_size) - 1;
 
@@ -1040,6 +1041,8 @@
 
 	i = n = 0;
 
+	write_mtt_size = min(mthca_write_mtt_size(dev), (int) (PAGE_SIZE / sizeof *pages));
+
 	list_for_each_entry(chunk, &region->chunk_list, list)
 		for (j = 0; j < chunk->nmap; ++j) {
 			len = sg_dma_len(&chunk->page_list[j]) >> shift;
@@ -1047,14 +1050,11 @@
 				pages[i++] = sg_dma_address(&chunk->page_list[j]) +
 					region->page_size * k;
 				/*
-				 * Be friendly to WRITE_MTT command
-				 * and leave two empty slots for the
-				 * index and reserved fields of the
-				 * mailbox.
+				 * Be friendly to write_mtt and pass it chunks
+				 * of appropriate size.
 				 */
-				if (i == PAGE_SIZE / sizeof (u64) - 2) {
-					err = mthca_write_mtt(dev, mr->mtt,
-							      n, pages, i);
+				if (i == write_mtt_size) {
+					err = mthca_write_mtt(dev, mr->mtt, n, pages, i);
 					if (err)
 						goto mtt_done;
 					n += i;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 9a5bece..1d266ac 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -89,6 +89,7 @@
 		struct {
 			struct mthca_mpt_entry *mpt;
 			__be64 *mtts;
+			dma_addr_t dma_handle;
 		} arbel;
 	} mem;
 };
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 5f5214c..71dc84b 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -399,7 +399,7 @@
 static void to_ib_ah_attr(struct mthca_dev *dev, struct ib_ah_attr *ib_ah_attr,
 				struct mthca_qp_path *path)
 {
-	memset(ib_ah_attr, 0, sizeof *path);
+	memset(ib_ah_attr, 0, sizeof *ib_ah_attr);
 	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)
@@ -573,6 +573,11 @@
 		goto out;
 	}
 
+	if (cur_state == new_state && cur_state == IB_QPS_RESET) {
+		err = 0;
+		goto out;
+	}
+
 	if ((attr_mask & IB_QP_PKEY_INDEX) &&
 	     attr->pkey_index >= dev->limits.pkey_table_len) {
 		mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 10684da..61974b0 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -116,11 +116,16 @@
 					 struct mthca_srq *srq,
 					 struct mthca_arbel_srq_context *context)
 {
-	int logsize;
+	int logsize, max;
 
 	memset(context, 0, sizeof *context);
 
-	logsize = ilog2(srq->max);
+	/*
+	 * Put max in a temporary variable to work around gcc bug
+	 * triggered by ilog2() on sparc64.
+	 */
+	max = srq->max;
+	logsize = ilog2(max);
 	context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn);
 	context->lkey = cpu_to_be32(srq->mr.ibmr.lkey);
 	context->db_index = cpu_to_be32(srq->db_index);
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig
index c75322d..af78ccc 100644
--- a/drivers/infiniband/ulp/ipoib/Kconfig
+++ b/drivers/infiniband/ulp/ipoib/Kconfig
@@ -1,6 +1,6 @@
 config INFINIBAND_IPOIB
 	tristate "IP-over-InfiniBand"
-	depends on INFINIBAND && NETDEVICES && INET
+	depends on INFINIBAND && NETDEVICES && INET && (IPV6 || IPV6=n)
 	---help---
 	  Support for the IP-over-InfiniBand protocol (IPoIB). This
 	  transports IP packets over InfiniBand so you can use your IB
@@ -8,6 +8,20 @@
 
 	  See Documentation/infiniband/ipoib.txt for more information
 
+config INFINIBAND_IPOIB_CM
+	bool "IP-over-InfiniBand Connected Mode support"
+	depends on INFINIBAND_IPOIB && EXPERIMENTAL
+	default n
+	---help---
+	  This option enables experimental support for IPoIB connected mode.
+	  After enabling this option, you need to switch to connected mode through
+	  /sys/class/net/ibXXX/mode to actually create connections, and then increase
+	  the interface MTU with e.g. ifconfig ib0 mtu 65520.
+
+	  WARNING: Enabling connected mode will trigger some
+	  packet drops for multicast and UD mode traffic from this interface,
+	  unless you limit mtu for these destinations to 2044.
+
 config INFINIBAND_IPOIB_DEBUG
 	bool "IP-over-InfiniBand debugging" if EMBEDDED
 	depends on INFINIBAND_IPOIB
diff --git a/drivers/infiniband/ulp/ipoib/Makefile b/drivers/infiniband/ulp/ipoib/Makefile
index 8935e74..98ee38e 100644
--- a/drivers/infiniband/ulp/ipoib/Makefile
+++ b/drivers/infiniband/ulp/ipoib/Makefile
@@ -5,5 +5,6 @@
 						   ipoib_multicast.o \
 						   ipoib_verbs.o \
 						   ipoib_vlan.o
+ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM)		+= ipoib_cm.o
 ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG)	+= ipoib_fs.o
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 07deee8..2594db2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -62,6 +62,10 @@
 
 	IPOIB_ENCAP_LEN 	  = 4,
 
+	IPOIB_CM_MTU              = 0x10000 - 0x10, /* padding to align header to 16 */
+	IPOIB_CM_BUF_SIZE         = IPOIB_CM_MTU  + IPOIB_ENCAP_LEN,
+	IPOIB_CM_HEAD_SIZE 	  = IPOIB_CM_BUF_SIZE % PAGE_SIZE,
+	IPOIB_CM_RX_SG            = ALIGN(IPOIB_CM_BUF_SIZE, PAGE_SIZE) / PAGE_SIZE,
 	IPOIB_RX_RING_SIZE 	  = 128,
 	IPOIB_TX_RING_SIZE 	  = 64,
 	IPOIB_MAX_QUEUE_SIZE	  = 8192,
@@ -81,6 +85,8 @@
 	IPOIB_MCAST_RUN 	  = 6,
 	IPOIB_STOP_REAPER         = 7,
 	IPOIB_MCAST_STARTED       = 8,
+	IPOIB_FLAG_NETIF_STOPPED  = 9,
+	IPOIB_FLAG_ADMIN_CM 	  = 10,
 
 	IPOIB_MAX_BACKOFF_SECONDS = 16,
 
@@ -90,6 +96,13 @@
 	IPOIB_MCAST_FLAG_ATTACHED = 3,
 };
 
+#define	IPOIB_OP_RECV   (1ul << 31)
+#ifdef CONFIG_INFINIBAND_IPOIB_CM
+#define	IPOIB_CM_OP_SRQ (1ul << 30)
+#else
+#define	IPOIB_CM_OP_SRQ (0)
+#endif
+
 /* structs */
 
 struct ipoib_header {
@@ -113,6 +126,59 @@
 	u64		mapping;
 };
 
+struct ib_cm_id;
+
+struct ipoib_cm_data {
+	__be32 qpn; /* High byte MUST be ignored on receive */
+	__be32 mtu;
+};
+
+struct ipoib_cm_rx {
+	struct ib_cm_id     *id;
+	struct ib_qp        *qp;
+	struct list_head     list;
+	struct net_device   *dev;
+	unsigned long        jiffies;
+};
+
+struct ipoib_cm_tx {
+	struct ib_cm_id     *id;
+	struct ib_cq        *cq;
+	struct ib_qp        *qp;
+	struct list_head     list;
+	struct net_device   *dev;
+	struct ipoib_neigh  *neigh;
+	struct ipoib_path   *path;
+	struct ipoib_tx_buf *tx_ring;
+	unsigned             tx_head;
+	unsigned             tx_tail;
+	unsigned long        flags;
+	u32                  mtu;
+	struct ib_wc         ibwc[IPOIB_NUM_WC];
+};
+
+struct ipoib_cm_rx_buf {
+	struct sk_buff *skb;
+	u64 mapping[IPOIB_CM_RX_SG];
+};
+
+struct ipoib_cm_dev_priv {
+	struct ib_srq  	       *srq;
+	struct ipoib_cm_rx_buf *srq_ring;
+	struct ib_cm_id        *id;
+	struct list_head        passive_ids;
+	struct work_struct      start_task;
+	struct work_struct      reap_task;
+	struct work_struct      skb_task;
+	struct delayed_work     stale_task;
+	struct sk_buff_head     skb_queue;
+	struct list_head        start_list;
+	struct list_head        reap_list;
+	struct ib_wc            ibwc[IPOIB_NUM_WC];
+	struct ib_sge           rx_sge[IPOIB_CM_RX_SG];
+	struct ib_recv_wr       rx_wr;
+};
+
 /*
  * Device private locking: tx_lock protects members used in TX fast
  * path (and we use LLTX so upper layers don't do extra locking).
@@ -179,6 +245,10 @@
 	struct list_head child_intfs;
 	struct list_head list;
 
+#ifdef CONFIG_INFINIBAND_IPOIB_CM
+	struct ipoib_cm_dev_priv cm;
+#endif
+
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
 	struct list_head fs_list;
 	struct dentry *mcg_dentry;
@@ -212,6 +282,9 @@
 
 struct ipoib_neigh {
 	struct ipoib_ah    *ah;
+#ifdef CONFIG_INFINIBAND_IPOIB_CM
+	struct ipoib_cm_tx *cm;
+#endif
 	union ib_gid        dgid;
 	struct sk_buff_head queue;
 
@@ -315,6 +388,146 @@
 void ipoib_pkey_poll(struct work_struct *work);
 int ipoib_pkey_dev_delay_open(struct net_device *dev);
 
+#ifdef CONFIG_INFINIBAND_IPOIB_CM
+
+#define IPOIB_FLAGS_RC          0x80
+#define IPOIB_FLAGS_UC          0x40
+
+/* We don't support UC connections at the moment */
+#define IPOIB_CM_SUPPORTED(ha)   (ha[0] & (IPOIB_FLAGS_RC))
+
+static inline int ipoib_cm_admin_enabled(struct net_device *dev)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	return IPOIB_CM_SUPPORTED(dev->dev_addr) &&
+		test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+}
+
+static inline int ipoib_cm_enabled(struct net_device *dev, struct neighbour *n)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	return IPOIB_CM_SUPPORTED(n->ha) &&
+		test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+}
+
+static inline int ipoib_cm_up(struct ipoib_neigh *neigh)
+
+{
+	return test_bit(IPOIB_FLAG_OPER_UP, &neigh->cm->flags);
+}
+
+static inline struct ipoib_cm_tx *ipoib_cm_get(struct ipoib_neigh *neigh)
+{
+	return neigh->cm;
+}
+
+static inline void ipoib_cm_set(struct ipoib_neigh *neigh, struct ipoib_cm_tx *tx)
+{
+	neigh->cm = tx;
+}
+
+void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx);
+int ipoib_cm_dev_open(struct net_device *dev);
+void ipoib_cm_dev_stop(struct net_device *dev);
+int ipoib_cm_dev_init(struct net_device *dev);
+int ipoib_cm_add_mode_attr(struct net_device *dev);
+void ipoib_cm_dev_cleanup(struct net_device *dev);
+struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path *path,
+				    struct ipoib_neigh *neigh);
+void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx);
+void ipoib_cm_skb_too_long(struct net_device* dev, struct sk_buff *skb,
+			   unsigned int mtu);
+void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc);
+#else
+
+struct ipoib_cm_tx;
+
+static inline int ipoib_cm_admin_enabled(struct net_device *dev)
+{
+	return 0;
+}
+static inline int ipoib_cm_enabled(struct net_device *dev, struct neighbour *n)
+
+{
+	return 0;
+}
+
+static inline int ipoib_cm_up(struct ipoib_neigh *neigh)
+
+{
+	return 0;
+}
+
+static inline struct ipoib_cm_tx *ipoib_cm_get(struct ipoib_neigh *neigh)
+{
+	return NULL;
+}
+
+static inline void ipoib_cm_set(struct ipoib_neigh *neigh, struct ipoib_cm_tx *tx)
+{
+}
+
+static inline
+void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx)
+{
+	return;
+}
+
+static inline
+int ipoib_cm_dev_open(struct net_device *dev)
+{
+	return 0;
+}
+
+static inline
+void ipoib_cm_dev_stop(struct net_device *dev)
+{
+	return;
+}
+
+static inline
+int ipoib_cm_dev_init(struct net_device *dev)
+{
+	return -ENOSYS;
+}
+
+static inline
+void ipoib_cm_dev_cleanup(struct net_device *dev)
+{
+	return;
+}
+
+static inline
+struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path *path,
+				    struct ipoib_neigh *neigh)
+{
+	return NULL;
+}
+
+static inline
+void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx)
+{
+	return;
+}
+
+static inline
+int ipoib_cm_add_mode_attr(struct net_device *dev)
+{
+	return 0;
+}
+
+static inline void ipoib_cm_skb_too_long(struct net_device* dev, struct sk_buff *skb,
+					 unsigned int mtu)
+{
+	dev_kfree_skb_any(skb);
+}
+
+static inline void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
+{
+}
+
+#endif
+
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
 void ipoib_create_debug_files(struct net_device *dev);
 void ipoib_delete_debug_files(struct net_device *dev);
@@ -392,4 +605,6 @@
 
 #define IPOIB_GID_ARG(gid)	IPOIB_GID_RAW_ARG((gid).raw)
 
+#define IPOIB_QPN(ha) (be32_to_cpup((__be32 *) ha) & 0xffffff)
+
 #endif /* _IPOIB_H */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
new file mode 100644
index 0000000..4d59682
--- /dev/null
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -0,0 +1,1237 @@
+/*
+ * Copyright (c) 2006 Mellanox Technologies. 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.
+ *
+ * $Id$
+ */
+
+#include <rdma/ib_cm.h>
+#include <rdma/ib_cache.h>
+#include <net/dst.h>
+#include <net/icmp.h>
+#include <linux/icmpv6.h>
+
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG_DATA
+static int data_debug_level;
+
+module_param_named(cm_data_debug_level, data_debug_level, int, 0644);
+MODULE_PARM_DESC(cm_data_debug_level,
+		 "Enable data path debug tracing for connected mode if > 0");
+#endif
+
+#include "ipoib.h"
+
+#define IPOIB_CM_IETF_ID 0x1000000000000000ULL
+
+#define IPOIB_CM_RX_UPDATE_TIME (256 * HZ)
+#define IPOIB_CM_RX_TIMEOUT     (2 * 256 * HZ)
+#define IPOIB_CM_RX_DELAY       (3 * 256 * HZ)
+#define IPOIB_CM_RX_UPDATE_MASK (0x3)
+
+struct ipoib_cm_id {
+	struct ib_cm_id *id;
+	int flags;
+	u32 remote_qpn;
+	u32 remote_mtu;
+};
+
+static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
+			       struct ib_cm_event *event);
+
+static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv,
+				  u64 mapping[IPOIB_CM_RX_SG])
+{
+	int i;
+
+	ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
+
+	for (i = 0; i < IPOIB_CM_RX_SG - 1; ++i)
+		ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
+}
+
+static int ipoib_cm_post_receive(struct net_device *dev, int id)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ib_recv_wr *bad_wr;
+	int i, ret;
+
+	priv->cm.rx_wr.wr_id = id | IPOIB_CM_OP_SRQ;
+
+	for (i = 0; i < IPOIB_CM_RX_SG; ++i)
+		priv->cm.rx_sge[i].addr = priv->cm.srq_ring[id].mapping[i];
+
+	ret = ib_post_srq_recv(priv->cm.srq, &priv->cm.rx_wr, &bad_wr);
+	if (unlikely(ret)) {
+		ipoib_warn(priv, "post srq failed for buf %d (%d)\n", id, ret);
+		ipoib_cm_dma_unmap_rx(priv, priv->cm.srq_ring[id].mapping);
+		dev_kfree_skb_any(priv->cm.srq_ring[id].skb);
+		priv->cm.srq_ring[id].skb = NULL;
+	}
+
+	return ret;
+}
+
+static int ipoib_cm_alloc_rx_skb(struct net_device *dev, int id,
+				 u64 mapping[IPOIB_CM_RX_SG])
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct sk_buff *skb;
+	int i;
+
+	skb = dev_alloc_skb(IPOIB_CM_HEAD_SIZE + 12);
+	if (unlikely(!skb))
+		return -ENOMEM;
+
+	/*
+	 * IPoIB adds a 4 byte header. So we need 12 more bytes to align the
+	 * IP header to a multiple of 16.
+	 */
+	skb_reserve(skb, 12);
+
+	mapping[0] = ib_dma_map_single(priv->ca, skb->data, IPOIB_CM_HEAD_SIZE,
+				       DMA_FROM_DEVICE);
+	if (unlikely(ib_dma_mapping_error(priv->ca, mapping[0]))) {
+		dev_kfree_skb_any(skb);
+		return -EIO;
+	}
+
+	for (i = 0; i < IPOIB_CM_RX_SG - 1; i++) {
+		struct page *page = alloc_page(GFP_ATOMIC);
+
+		if (!page)
+			goto partial_error;
+		skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE);
+
+		mapping[i + 1] = ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[i].page,
+						 0, PAGE_SIZE, DMA_TO_DEVICE);
+		if (unlikely(ib_dma_mapping_error(priv->ca, mapping[i + 1])))
+			goto partial_error;
+	}
+
+	priv->cm.srq_ring[id].skb = skb;
+	return 0;
+
+partial_error:
+
+	ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
+
+	for (; i >= 0; --i)
+		ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
+
+	dev_kfree_skb_any(skb);
+	return -ENOMEM;
+}
+
+static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev,
+					   struct ipoib_cm_rx *p)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ib_qp_init_attr attr = {
+		.send_cq = priv->cq, /* does not matter, we never send anything */
+		.recv_cq = priv->cq,
+		.srq = priv->cm.srq,
+		.cap.max_send_wr = 1, /* FIXME: 0 Seems not to work */
+		.cap.max_send_sge = 1, /* FIXME: 0 Seems not to work */
+		.sq_sig_type = IB_SIGNAL_ALL_WR,
+		.qp_type = IB_QPT_RC,
+		.qp_context = p,
+	};
+	return ib_create_qp(priv->pd, &attr);
+}
+
+static int ipoib_cm_modify_rx_qp(struct net_device *dev,
+				  struct ib_cm_id *cm_id, struct ib_qp *qp,
+				  unsigned psn)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ib_qp_attr qp_attr;
+	int qp_attr_mask, ret;
+
+	qp_attr.qp_state = IB_QPS_INIT;
+	ret = ib_cm_init_qp_attr(cm_id, &qp_attr, &qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to init QP attr for INIT: %d\n", ret);
+		return ret;
+	}
+	ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to modify QP to INIT: %d\n", ret);
+		return ret;
+	}
+	qp_attr.qp_state = IB_QPS_RTR;
+	ret = ib_cm_init_qp_attr(cm_id, &qp_attr, &qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to init QP attr for RTR: %d\n", ret);
+		return ret;
+	}
+	qp_attr.rq_psn = psn;
+	ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to modify QP to RTR: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static int ipoib_cm_send_rep(struct net_device *dev, struct ib_cm_id *cm_id,
+			     struct ib_qp *qp, struct ib_cm_req_event_param *req,
+			     unsigned psn)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ipoib_cm_data data = {};
+	struct ib_cm_rep_param rep = {};
+
+	data.qpn = cpu_to_be32(priv->qp->qp_num);
+	data.mtu = cpu_to_be32(IPOIB_CM_BUF_SIZE);
+
+	rep.private_data = &data;
+	rep.private_data_len = sizeof data;
+	rep.flow_control = 0;
+	rep.rnr_retry_count = req->rnr_retry_count;
+	rep.target_ack_delay = 20; /* FIXME */
+	rep.srq = 1;
+	rep.qp_num = qp->qp_num;
+	rep.starting_psn = psn;
+	return ib_send_cm_rep(cm_id, &rep);
+}
+
+static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
+{
+	struct net_device *dev = cm_id->context;
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ipoib_cm_rx *p;
+	unsigned long flags;
+	unsigned psn;
+	int ret;
+
+	ipoib_dbg(priv, "REQ arrived\n");
+	p = kzalloc(sizeof *p, GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+	p->dev = dev;
+	p->id = cm_id;
+	p->qp = ipoib_cm_create_rx_qp(dev, p);
+	if (IS_ERR(p->qp)) {
+		ret = PTR_ERR(p->qp);
+		goto err_qp;
+	}
+
+	psn = random32() & 0xffffff;
+	ret = ipoib_cm_modify_rx_qp(dev, cm_id, p->qp, psn);
+	if (ret)
+		goto err_modify;
+
+	ret = ipoib_cm_send_rep(dev, cm_id, p->qp, &event->param.req_rcvd, psn);
+	if (ret) {
+		ipoib_warn(priv, "failed to send REP: %d\n", ret);
+		goto err_rep;
+	}
+
+	cm_id->context = p;
+	p->jiffies = jiffies;
+	spin_lock_irqsave(&priv->lock, flags);
+	list_add(&p->list, &priv->cm.passive_ids);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	queue_delayed_work(ipoib_workqueue,
+			   &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
+	return 0;
+
+err_rep:
+err_modify:
+	ib_destroy_qp(p->qp);
+err_qp:
+	kfree(p);
+	return ret;
+}
+
+static int ipoib_cm_rx_handler(struct ib_cm_id *cm_id,
+			       struct ib_cm_event *event)
+{
+	struct ipoib_cm_rx *p;
+	struct ipoib_dev_priv *priv;
+	unsigned long flags;
+	int ret;
+
+	switch (event->event) {
+	case IB_CM_REQ_RECEIVED:
+		return ipoib_cm_req_handler(cm_id, event);
+	case IB_CM_DREQ_RECEIVED:
+		p = cm_id->context;
+		ib_send_cm_drep(cm_id, NULL, 0);
+		/* Fall through */
+	case IB_CM_REJ_RECEIVED:
+		p = cm_id->context;
+		priv = netdev_priv(p->dev);
+		spin_lock_irqsave(&priv->lock, flags);
+		if (list_empty(&p->list))
+			ret = 0; /* Connection is going away already. */
+		else {
+			list_del_init(&p->list);
+			ret = -ECONNRESET;
+		}
+		spin_unlock_irqrestore(&priv->lock, flags);
+		if (ret) {
+			ib_destroy_qp(p->qp);
+			kfree(p);
+			return ret;
+		}
+		return 0;
+	default:
+		return 0;
+	}
+}
+/* Adjust length of skb with fragments to match received data */
+static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
+			  unsigned int length)
+{
+	int i, num_frags;
+	unsigned int size;
+
+	/* put header into skb */
+	size = min(length, hdr_space);
+	skb->tail += size;
+	skb->len += size;
+	length -= size;
+
+	num_frags = skb_shinfo(skb)->nr_frags;
+	for (i = 0; i < num_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+		if (length == 0) {
+			/* don't need this page */
+			__free_page(frag->page);
+			--skb_shinfo(skb)->nr_frags;
+		} else {
+			size = min(length, (unsigned) PAGE_SIZE);
+
+			frag->size = size;
+			skb->data_len += size;
+			skb->truesize += size;
+			skb->len += size;
+			length -= size;
+		}
+	}
+}
+
+void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	unsigned int wr_id = wc->wr_id & ~IPOIB_CM_OP_SRQ;
+	struct sk_buff *skb;
+	struct ipoib_cm_rx *p;
+	unsigned long flags;
+	u64 mapping[IPOIB_CM_RX_SG];
+
+	ipoib_dbg_data(priv, "cm recv completion: id %d, op %d, status: %d\n",
+		       wr_id, wc->opcode, wc->status);
+
+	if (unlikely(wr_id >= ipoib_recvq_size)) {
+		ipoib_warn(priv, "cm recv completion event with wrid %d (> %d)\n",
+			   wr_id, ipoib_recvq_size);
+		return;
+	}
+
+	skb  = priv->cm.srq_ring[wr_id].skb;
+
+	if (unlikely(wc->status != IB_WC_SUCCESS)) {
+		ipoib_dbg(priv, "cm recv error "
+			   "(status=%d, wrid=%d vend_err %x)\n",
+			   wc->status, wr_id, wc->vendor_err);
+		++priv->stats.rx_dropped;
+		goto repost;
+	}
+
+	if (!likely(wr_id & IPOIB_CM_RX_UPDATE_MASK)) {
+		p = wc->qp->qp_context;
+		if (time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) {
+			spin_lock_irqsave(&priv->lock, flags);
+			p->jiffies = jiffies;
+			/* Move this entry to list head, but do
+			 * not re-add it if it has been removed. */
+			if (!list_empty(&p->list))
+				list_move(&p->list, &priv->cm.passive_ids);
+			spin_unlock_irqrestore(&priv->lock, flags);
+			queue_delayed_work(ipoib_workqueue,
+					   &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
+		}
+	}
+
+	if (unlikely(ipoib_cm_alloc_rx_skb(dev, wr_id, mapping))) {
+		/*
+		 * If we can't allocate a new RX buffer, dump
+		 * this packet and reuse the old buffer.
+		 */
+		ipoib_dbg(priv, "failed to allocate receive buffer %d\n", wr_id);
+		++priv->stats.rx_dropped;
+		goto repost;
+	}
+
+	ipoib_cm_dma_unmap_rx(priv, priv->cm.srq_ring[wr_id].mapping);
+	memcpy(priv->cm.srq_ring[wr_id].mapping, mapping, sizeof mapping);
+
+	ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n",
+		       wc->byte_len, wc->slid);
+
+	skb_put_frags(skb, IPOIB_CM_HEAD_SIZE, wc->byte_len);
+
+	skb->protocol = ((struct ipoib_header *) skb->data)->proto;
+	skb->mac.raw = skb->data;
+	skb_pull(skb, IPOIB_ENCAP_LEN);
+
+	dev->last_rx = jiffies;
+	++priv->stats.rx_packets;
+	priv->stats.rx_bytes += skb->len;
+
+	skb->dev = dev;
+	/* XXX get correct PACKET_ type here */
+	skb->pkt_type = PACKET_HOST;
+	netif_rx_ni(skb);
+
+repost:
+	if (unlikely(ipoib_cm_post_receive(dev, wr_id)))
+		ipoib_warn(priv, "ipoib_cm_post_receive failed "
+			   "for buf %d\n", wr_id);
+}
+
+static inline int post_send(struct ipoib_dev_priv *priv,
+			    struct ipoib_cm_tx *tx,
+			    unsigned int wr_id,
+			    u64 addr, int len)
+{
+	struct ib_send_wr *bad_wr;
+
+	priv->tx_sge.addr             = addr;
+	priv->tx_sge.length           = len;
+
+	priv->tx_wr.wr_id 	      = wr_id;
+
+	return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr);
+}
+
+void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ipoib_tx_buf *tx_req;
+	u64 addr;
+
+	if (unlikely(skb->len > tx->mtu)) {
+		ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n",
+			   skb->len, tx->mtu);
+		++priv->stats.tx_dropped;
+		++priv->stats.tx_errors;
+		ipoib_cm_skb_too_long(dev, skb, tx->mtu - INFINIBAND_ALEN);
+		return;
+	}
+
+	ipoib_dbg_data(priv, "sending packet: head 0x%x length %d connection 0x%x\n",
+		       tx->tx_head, skb->len, tx->qp->qp_num);
+
+	/*
+	 * We put the skb into the tx_ring _before_ we call post_send()
+	 * because it's entirely possible that the completion handler will
+	 * run before we execute anything after the post_send().  That
+	 * means we have to make sure everything is properly recorded and
+	 * our state is consistent before we call post_send().
+	 */
+	tx_req = &tx->tx_ring[tx->tx_head & (ipoib_sendq_size - 1)];
+	tx_req->skb = skb;
+	addr = ib_dma_map_single(priv->ca, skb->data, skb->len, DMA_TO_DEVICE);
+	if (unlikely(ib_dma_mapping_error(priv->ca, addr))) {
+		++priv->stats.tx_errors;
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
+	tx_req->mapping = addr;
+
+	if (unlikely(post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1),
+			        addr, skb->len))) {
+		ipoib_warn(priv, "post_send failed\n");
+		++priv->stats.tx_errors;
+		ib_dma_unmap_single(priv->ca, addr, skb->len, DMA_TO_DEVICE);
+		dev_kfree_skb_any(skb);
+	} else {
+		dev->trans_start = jiffies;
+		++tx->tx_head;
+
+		if (tx->tx_head - tx->tx_tail == ipoib_sendq_size) {
+			ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
+				  tx->qp->qp_num);
+			netif_stop_queue(dev);
+			set_bit(IPOIB_FLAG_NETIF_STOPPED, &tx->flags);
+		}
+	}
+}
+
+static void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ipoib_cm_tx *tx,
+				  struct ib_wc *wc)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	unsigned int wr_id = wc->wr_id;
+	struct ipoib_tx_buf *tx_req;
+	unsigned long flags;
+
+	ipoib_dbg_data(priv, "cm send completion: id %d, op %d, status: %d\n",
+		       wr_id, wc->opcode, wc->status);
+
+	if (unlikely(wr_id >= ipoib_sendq_size)) {
+		ipoib_warn(priv, "cm send completion event with wrid %d (> %d)\n",
+			   wr_id, ipoib_sendq_size);
+		return;
+	}
+
+	tx_req = &tx->tx_ring[wr_id];
+
+	ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len, DMA_TO_DEVICE);
+
+	/* FIXME: is this right? Shouldn't we only increment on success? */
+	++priv->stats.tx_packets;
+	priv->stats.tx_bytes += tx_req->skb->len;
+
+	dev_kfree_skb_any(tx_req->skb);
+
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	++tx->tx_tail;
+	if (unlikely(test_bit(IPOIB_FLAG_NETIF_STOPPED, &tx->flags)) &&
+	    tx->tx_head - tx->tx_tail <= ipoib_sendq_size >> 1) {
+		clear_bit(IPOIB_FLAG_NETIF_STOPPED, &tx->flags);
+		netif_wake_queue(dev);
+	}
+
+	if (wc->status != IB_WC_SUCCESS &&
+	    wc->status != IB_WC_WR_FLUSH_ERR) {
+		struct ipoib_neigh *neigh;
+
+		ipoib_dbg(priv, "failed cm send event "
+			   "(status=%d, wrid=%d vend_err %x)\n",
+			   wc->status, wr_id, wc->vendor_err);
+
+		spin_lock(&priv->lock);
+		neigh = tx->neigh;
+
+		if (neigh) {
+			neigh->cm = NULL;
+			list_del(&neigh->list);
+			if (neigh->ah)
+				ipoib_put_ah(neigh->ah);
+			ipoib_neigh_free(dev, neigh);
+
+			tx->neigh = NULL;
+		}
+
+		/* queue would be re-started anyway when TX is destroyed,
+		 * but it makes sense to do it ASAP here. */
+		if (test_and_clear_bit(IPOIB_FLAG_NETIF_STOPPED, &tx->flags))
+			netif_wake_queue(dev);
+
+		if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) {
+			list_move(&tx->list, &priv->cm.reap_list);
+			queue_work(ipoib_workqueue, &priv->cm.reap_task);
+		}
+
+		clear_bit(IPOIB_FLAG_OPER_UP, &tx->flags);
+
+		spin_unlock(&priv->lock);
+	}
+
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
+}
+
+static void ipoib_cm_tx_completion(struct ib_cq *cq, void *tx_ptr)
+{
+	struct ipoib_cm_tx *tx = tx_ptr;
+	int n, i;
+
+	ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
+	do {
+		n = ib_poll_cq(cq, IPOIB_NUM_WC, tx->ibwc);
+		for (i = 0; i < n; ++i)
+			ipoib_cm_handle_tx_wc(tx->dev, tx, tx->ibwc + i);
+	} while (n == IPOIB_NUM_WC);
+}
+
+int ipoib_cm_dev_open(struct net_device *dev)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	int ret;
+
+	if (!IPOIB_CM_SUPPORTED(dev->dev_addr))
+		return 0;
+
+	priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev);
+	if (IS_ERR(priv->cm.id)) {
+		printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name);
+		return IS_ERR(priv->cm.id);
+	}
+
+	ret = ib_cm_listen(priv->cm.id, cpu_to_be64(IPOIB_CM_IETF_ID | priv->qp->qp_num),
+			   0, NULL);
+	if (ret) {
+		printk(KERN_WARNING "%s: failed to listen on ID 0x%llx\n", priv->ca->name,
+		       IPOIB_CM_IETF_ID | priv->qp->qp_num);
+		ib_destroy_cm_id(priv->cm.id);
+		return ret;
+	}
+	return 0;
+}
+
+void ipoib_cm_dev_stop(struct net_device *dev)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ipoib_cm_rx *p;
+	unsigned long flags;
+
+	if (!IPOIB_CM_SUPPORTED(dev->dev_addr))
+		return;
+
+	ib_destroy_cm_id(priv->cm.id);
+	spin_lock_irqsave(&priv->lock, flags);
+	while (!list_empty(&priv->cm.passive_ids)) {
+		p = list_entry(priv->cm.passive_ids.next, typeof(*p), list);
+		list_del_init(&p->list);
+		spin_unlock_irqrestore(&priv->lock, flags);
+		ib_destroy_cm_id(p->id);
+		ib_destroy_qp(p->qp);
+		kfree(p);
+		spin_lock_irqsave(&priv->lock, flags);
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	cancel_delayed_work(&priv->cm.stale_task);
+}
+
+static int ipoib_cm_rep_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
+{
+	struct ipoib_cm_tx *p = cm_id->context;
+	struct ipoib_dev_priv *priv = netdev_priv(p->dev);
+	struct ipoib_cm_data *data = event->private_data;
+	struct sk_buff_head skqueue;
+	struct ib_qp_attr qp_attr;
+	int qp_attr_mask, ret;
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	p->mtu = be32_to_cpu(data->mtu);
+
+	if (p->mtu < priv->dev->mtu + IPOIB_ENCAP_LEN) {
+		ipoib_warn(priv, "Rejecting connection: mtu %d < device mtu %d + 4\n",
+			   p->mtu, priv->dev->mtu);
+		return -EINVAL;
+	}
+
+	qp_attr.qp_state = IB_QPS_RTR;
+	ret = ib_cm_init_qp_attr(cm_id, &qp_attr, &qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to init QP attr for RTR: %d\n", ret);
+		return ret;
+	}
+
+	qp_attr.rq_psn = 0 /* FIXME */;
+	ret = ib_modify_qp(p->qp, &qp_attr, qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to modify QP to RTR: %d\n", ret);
+		return ret;
+	}
+
+	qp_attr.qp_state = IB_QPS_RTS;
+	ret = ib_cm_init_qp_attr(cm_id, &qp_attr, &qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to init QP attr for RTS: %d\n", ret);
+		return ret;
+	}
+	ret = ib_modify_qp(p->qp, &qp_attr, qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to modify QP to RTS: %d\n", ret);
+		return ret;
+	}
+
+	skb_queue_head_init(&skqueue);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	set_bit(IPOIB_FLAG_OPER_UP, &p->flags);
+	if (p->neigh)
+		while ((skb = __skb_dequeue(&p->neigh->queue)))
+			__skb_queue_tail(&skqueue, skb);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	while ((skb = __skb_dequeue(&skqueue))) {
+		skb->dev = p->dev;
+		if (dev_queue_xmit(skb))
+			ipoib_warn(priv, "dev_queue_xmit failed "
+				   "to requeue packet\n");
+	}
+
+	ret = ib_send_cm_rtu(cm_id, NULL, 0);
+	if (ret) {
+		ipoib_warn(priv, "failed to send RTU: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ib_cq *cq)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ib_qp_init_attr attr = {};
+	attr.recv_cq = priv->cq;
+	attr.srq = priv->cm.srq;
+	attr.cap.max_send_wr = ipoib_sendq_size;
+	attr.cap.max_send_sge = 1;
+	attr.sq_sig_type = IB_SIGNAL_ALL_WR;
+	attr.qp_type = IB_QPT_RC;
+	attr.send_cq = cq;
+	return ib_create_qp(priv->pd, &attr);
+}
+
+static int ipoib_cm_send_req(struct net_device *dev,
+			     struct ib_cm_id *id, struct ib_qp *qp,
+			     u32 qpn,
+			     struct ib_sa_path_rec *pathrec)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ipoib_cm_data data = {};
+	struct ib_cm_req_param req = {};
+
+	data.qpn = cpu_to_be32(priv->qp->qp_num);
+	data.mtu = cpu_to_be32(IPOIB_CM_BUF_SIZE);
+
+	req.primary_path 	      = pathrec;
+	req.alternate_path 	      = NULL;
+	req.service_id                = cpu_to_be64(IPOIB_CM_IETF_ID | qpn);
+	req.qp_num 		      = qp->qp_num;
+	req.qp_type 		      = qp->qp_type;
+	req.private_data 	      = &data;
+	req.private_data_len 	      = sizeof data;
+	req.flow_control 	      = 0;
+
+	req.starting_psn              = 0; /* FIXME */
+
+	/*
+	 * Pick some arbitrary defaults here; we could make these
+	 * module parameters if anyone cared about setting them.
+	 */
+	req.responder_resources	      = 4;
+	req.remote_cm_response_timeout = 20;
+	req.local_cm_response_timeout  = 20;
+	req.retry_count 	      = 0; /* RFC draft warns against retries */
+	req.rnr_retry_count 	      = 0; /* RFC draft warns against retries */
+	req.max_cm_retries 	      = 15;
+	req.srq 	              = 1;
+	return ib_send_cm_req(id, &req);
+}
+
+static int ipoib_cm_modify_tx_init(struct net_device *dev,
+				  struct ib_cm_id *cm_id, struct ib_qp *qp)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ib_qp_attr qp_attr;
+	int qp_attr_mask, ret;
+	ret = ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &qp_attr.pkey_index);
+	if (ret) {
+		ipoib_warn(priv, "pkey 0x%x not in cache: %d\n", priv->pkey, ret);
+		return ret;
+	}
+
+	qp_attr.qp_state = IB_QPS_INIT;
+	qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+	qp_attr.port_num = priv->port;
+	qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS | IB_QP_PKEY_INDEX | IB_QP_PORT;
+
+	ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
+	if (ret) {
+		ipoib_warn(priv, "failed to modify tx QP to INIT: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
+			    struct ib_sa_path_rec *pathrec)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(p->dev);
+	int ret;
+
+	p->tx_ring = kzalloc(ipoib_sendq_size * sizeof *p->tx_ring,
+				GFP_KERNEL);
+	if (!p->tx_ring) {
+		ipoib_warn(priv, "failed to allocate tx ring\n");
+		ret = -ENOMEM;
+		goto err_tx;
+	}
+
+	p->cq = ib_create_cq(priv->ca, ipoib_cm_tx_completion, NULL, p,
+			     ipoib_sendq_size + 1);
+	if (IS_ERR(p->cq)) {
+		ret = PTR_ERR(p->cq);
+		ipoib_warn(priv, "failed to allocate tx cq: %d\n", ret);
+		goto err_cq;
+	}
+
+	ret = ib_req_notify_cq(p->cq, IB_CQ_NEXT_COMP);
+	if (ret) {
+		ipoib_warn(priv, "failed to request completion notification: %d\n", ret);
+		goto err_req_notify;
+	}
+
+	p->qp = ipoib_cm_create_tx_qp(p->dev, p->cq);
+	if (IS_ERR(p->qp)) {
+		ret = PTR_ERR(p->qp);
+		ipoib_warn(priv, "failed to allocate tx qp: %d\n", ret);
+		goto err_qp;
+	}
+
+	p->id = ib_create_cm_id(priv->ca, ipoib_cm_tx_handler, p);
+	if (IS_ERR(p->id)) {
+		ret = PTR_ERR(p->id);
+		ipoib_warn(priv, "failed to create tx cm id: %d\n", ret);
+		goto err_id;
+	}
+
+	ret = ipoib_cm_modify_tx_init(p->dev, p->id,  p->qp);
+	if (ret) {
+		ipoib_warn(priv, "failed to modify tx qp to rtr: %d\n", ret);
+		goto err_modify;
+	}
+
+	ret = ipoib_cm_send_req(p->dev, p->id, p->qp, qpn, pathrec);
+	if (ret) {
+		ipoib_warn(priv, "failed to send cm req: %d\n", ret);
+		goto err_send_cm;
+	}
+
+	ipoib_dbg(priv, "Request connection 0x%x for gid " IPOIB_GID_FMT " qpn 0x%x\n",
+		  p->qp->qp_num, IPOIB_GID_ARG(pathrec->dgid), qpn);
+
+	return 0;
+
+err_send_cm:
+err_modify:
+	ib_destroy_cm_id(p->id);
+err_id:
+	p->id = NULL;
+	ib_destroy_qp(p->qp);
+err_req_notify:
+err_qp:
+	p->qp = NULL;
+	ib_destroy_cq(p->cq);
+err_cq:
+	p->cq = NULL;
+err_tx:
+	return ret;
+}
+
+static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(p->dev);
+	struct ipoib_tx_buf *tx_req;
+
+	ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n",
+		  p->qp ? p->qp->qp_num : 0, p->tx_head, p->tx_tail);
+
+	if (p->id)
+		ib_destroy_cm_id(p->id);
+
+	if (p->qp)
+		ib_destroy_qp(p->qp);
+
+	if (p->cq)
+		ib_destroy_cq(p->cq);
+
+	if (test_bit(IPOIB_FLAG_NETIF_STOPPED, &p->flags))
+		netif_wake_queue(p->dev);
+
+	if (p->tx_ring) {
+		while ((int) p->tx_tail - (int) p->tx_head < 0) {
+			tx_req = &p->tx_ring[p->tx_tail & (ipoib_sendq_size - 1)];
+			ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len,
+					 DMA_TO_DEVICE);
+			dev_kfree_skb_any(tx_req->skb);
+			++p->tx_tail;
+		}
+
+		kfree(p->tx_ring);
+	}
+
+	kfree(p);
+}
+
+static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
+			       struct ib_cm_event *event)
+{
+	struct ipoib_cm_tx *tx = cm_id->context;
+	struct ipoib_dev_priv *priv = netdev_priv(tx->dev);
+	struct net_device *dev = priv->dev;
+	struct ipoib_neigh *neigh;
+	unsigned long flags;
+	int ret;
+
+	switch (event->event) {
+	case IB_CM_DREQ_RECEIVED:
+		ipoib_dbg(priv, "DREQ received.\n");
+		ib_send_cm_drep(cm_id, NULL, 0);
+		break;
+	case IB_CM_REP_RECEIVED:
+		ipoib_dbg(priv, "REP received.\n");
+		ret = ipoib_cm_rep_handler(cm_id, event);
+		if (ret)
+			ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
+				       NULL, 0, NULL, 0);
+		break;
+	case IB_CM_REQ_ERROR:
+	case IB_CM_REJ_RECEIVED:
+	case IB_CM_TIMEWAIT_EXIT:
+		ipoib_dbg(priv, "CM error %d.\n", event->event);
+		spin_lock_irqsave(&priv->tx_lock, flags);
+		spin_lock(&priv->lock);
+		neigh = tx->neigh;
+
+		if (neigh) {
+			neigh->cm = NULL;
+			list_del(&neigh->list);
+			if (neigh->ah)
+				ipoib_put_ah(neigh->ah);
+			ipoib_neigh_free(dev, neigh);
+
+			tx->neigh = NULL;
+		}
+
+		if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) {
+			list_move(&tx->list, &priv->cm.reap_list);
+			queue_work(ipoib_workqueue, &priv->cm.reap_task);
+		}
+
+		spin_unlock(&priv->lock);
+		spin_unlock_irqrestore(&priv->tx_lock, flags);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path *path,
+				       struct ipoib_neigh *neigh)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ipoib_cm_tx *tx;
+
+	tx = kzalloc(sizeof *tx, GFP_ATOMIC);
+	if (!tx)
+		return NULL;
+
+	neigh->cm = tx;
+	tx->neigh = neigh;
+	tx->path = path;
+	tx->dev = dev;
+	list_add(&tx->list, &priv->cm.start_list);
+	set_bit(IPOIB_FLAG_INITIALIZED, &tx->flags);
+	queue_work(ipoib_workqueue, &priv->cm.start_task);
+	return tx;
+}
+
+void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(tx->dev);
+	if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) {
+		list_move(&tx->list, &priv->cm.reap_list);
+		queue_work(ipoib_workqueue, &priv->cm.reap_task);
+		ipoib_dbg(priv, "Reap connection for gid " IPOIB_GID_FMT "\n",
+			  IPOIB_GID_ARG(tx->neigh->dgid));
+		tx->neigh = NULL;
+	}
+}
+
+static void ipoib_cm_tx_start(struct work_struct *work)
+{
+	struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
+						   cm.start_task);
+	struct net_device *dev = priv->dev;
+	struct ipoib_neigh *neigh;
+	struct ipoib_cm_tx *p;
+	unsigned long flags;
+	int ret;
+
+	struct ib_sa_path_rec pathrec;
+	u32 qpn;
+
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	spin_lock(&priv->lock);
+	while (!list_empty(&priv->cm.start_list)) {
+		p = list_entry(priv->cm.start_list.next, typeof(*p), list);
+		list_del_init(&p->list);
+		neigh = p->neigh;
+		qpn = IPOIB_QPN(neigh->neighbour->ha);
+		memcpy(&pathrec, &p->path->pathrec, sizeof pathrec);
+		spin_unlock(&priv->lock);
+		spin_unlock_irqrestore(&priv->tx_lock, flags);
+		ret = ipoib_cm_tx_init(p, qpn, &pathrec);
+		spin_lock_irqsave(&priv->tx_lock, flags);
+		spin_lock(&priv->lock);
+		if (ret) {
+			neigh = p->neigh;
+			if (neigh) {
+				neigh->cm = NULL;
+				list_del(&neigh->list);
+				if (neigh->ah)
+					ipoib_put_ah(neigh->ah);
+				ipoib_neigh_free(dev, neigh);
+			}
+			list_del(&p->list);
+			kfree(p);
+		}
+	}
+	spin_unlock(&priv->lock);
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
+}
+
+static void ipoib_cm_tx_reap(struct work_struct *work)
+{
+	struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
+						   cm.reap_task);
+	struct ipoib_cm_tx *p;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	spin_lock(&priv->lock);
+	while (!list_empty(&priv->cm.reap_list)) {
+		p = list_entry(priv->cm.reap_list.next, typeof(*p), list);
+		list_del(&p->list);
+		spin_unlock(&priv->lock);
+		spin_unlock_irqrestore(&priv->tx_lock, flags);
+		ipoib_cm_tx_destroy(p);
+		spin_lock_irqsave(&priv->tx_lock, flags);
+		spin_lock(&priv->lock);
+	}
+	spin_unlock(&priv->lock);
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
+}
+
+static void ipoib_cm_skb_reap(struct work_struct *work)
+{
+	struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
+						   cm.skb_task);
+	struct net_device *dev = priv->dev;
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	unsigned mtu = priv->mcast_mtu;
+
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	spin_lock(&priv->lock);
+	while ((skb = skb_dequeue(&priv->cm.skb_queue))) {
+		spin_unlock(&priv->lock);
+		spin_unlock_irqrestore(&priv->tx_lock, flags);
+		if (skb->protocol == htons(ETH_P_IP))
+			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		else if (skb->protocol == htons(ETH_P_IPV6))
+			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
+#endif
+		dev_kfree_skb_any(skb);
+		spin_lock_irqsave(&priv->tx_lock, flags);
+		spin_lock(&priv->lock);
+	}
+	spin_unlock(&priv->lock);
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
+}
+
+void ipoib_cm_skb_too_long(struct net_device* dev, struct sk_buff *skb,
+			   unsigned int mtu)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	int e = skb_queue_empty(&priv->cm.skb_queue);
+
+	if (skb->dst)
+		skb->dst->ops->update_pmtu(skb->dst, mtu);
+
+	skb_queue_tail(&priv->cm.skb_queue, skb);
+	if (e)
+		queue_work(ipoib_workqueue, &priv->cm.skb_task);
+}
+
+static void ipoib_cm_stale_task(struct work_struct *work)
+{
+	struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
+						   cm.stale_task.work);
+	struct ipoib_cm_rx *p;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	while (!list_empty(&priv->cm.passive_ids)) {
+		/* List if sorted by LRU, start from tail,
+		 * stop when we see a recently used entry */
+		p = list_entry(priv->cm.passive_ids.prev, typeof(*p), list);
+		if (time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_TIMEOUT))
+			break;
+		list_del_init(&p->list);
+		spin_unlock_irqrestore(&priv->lock, flags);
+		ib_destroy_cm_id(p->id);
+		ib_destroy_qp(p->qp);
+		kfree(p);
+		spin_lock_irqsave(&priv->lock, flags);
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+
+static ssize_t show_mode(struct device *d, struct device_attribute *attr, 
+			 char *buf)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(d));
+
+	if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags))
+		return sprintf(buf, "connected\n");
+	else
+		return sprintf(buf, "datagram\n");
+}
+
+static ssize_t set_mode(struct device *d, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct net_device *dev = to_net_dev(d);
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+	/* flush paths if we switch modes so that connections are restarted */
+	if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) {
+		set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+		ipoib_warn(priv, "enabling connected mode "
+			   "will cause multicast packet drops\n");
+		ipoib_flush_paths(dev);
+		return count;
+	}
+
+	if (!strcmp(buf, "datagram\n")) {
+		clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+		dev->mtu = min(priv->mcast_mtu, dev->mtu);
+		ipoib_flush_paths(dev);
+		return count;
+	}
+
+	return -EINVAL;
+}
+
+static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode);
+
+int ipoib_cm_add_mode_attr(struct net_device *dev)
+{
+	return device_create_file(&dev->dev, &dev_attr_mode);
+}
+
+int ipoib_cm_dev_init(struct net_device *dev)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct ib_srq_init_attr srq_init_attr = {
+		.attr = {
+			.max_wr  = ipoib_recvq_size,
+			.max_sge = IPOIB_CM_RX_SG
+		}
+	};
+	int ret, i;
+
+	INIT_LIST_HEAD(&priv->cm.passive_ids);
+	INIT_LIST_HEAD(&priv->cm.reap_list);
+	INIT_LIST_HEAD(&priv->cm.start_list);
+	INIT_WORK(&priv->cm.start_task, ipoib_cm_tx_start);
+	INIT_WORK(&priv->cm.reap_task, ipoib_cm_tx_reap);
+	INIT_WORK(&priv->cm.skb_task, ipoib_cm_skb_reap);
+	INIT_DELAYED_WORK(&priv->cm.stale_task, ipoib_cm_stale_task);
+
+	skb_queue_head_init(&priv->cm.skb_queue);
+
+	priv->cm.srq = ib_create_srq(priv->pd, &srq_init_attr);
+	if (IS_ERR(priv->cm.srq)) {
+		ret = PTR_ERR(priv->cm.srq);
+		priv->cm.srq = NULL;
+		return ret;
+	}
+
+	priv->cm.srq_ring = kzalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring,
+				    GFP_KERNEL);
+	if (!priv->cm.srq_ring) {
+		printk(KERN_WARNING "%s: failed to allocate CM ring (%d entries)\n",
+		       priv->ca->name, ipoib_recvq_size);
+		ipoib_cm_dev_cleanup(dev);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < IPOIB_CM_RX_SG; ++i)
+		priv->cm.rx_sge[i].lkey	= priv->mr->lkey;
+
+	priv->cm.rx_sge[0].length = IPOIB_CM_HEAD_SIZE;
+	for (i = 1; i < IPOIB_CM_RX_SG; ++i)
+		priv->cm.rx_sge[i].length = PAGE_SIZE;
+	priv->cm.rx_wr.next = NULL;
+	priv->cm.rx_wr.sg_list = priv->cm.rx_sge;
+	priv->cm.rx_wr.num_sge = IPOIB_CM_RX_SG;
+
+	for (i = 0; i < ipoib_recvq_size; ++i) {
+		if (ipoib_cm_alloc_rx_skb(dev, i, priv->cm.srq_ring[i].mapping)) {
+			ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
+			ipoib_cm_dev_cleanup(dev);
+			return -ENOMEM;
+		}
+		if (ipoib_cm_post_receive(dev, i)) {
+			ipoib_warn(priv, "ipoib_ib_post_receive failed for buf %d\n", i);
+			ipoib_cm_dev_cleanup(dev);
+			return -EIO;
+		}
+	}
+
+	priv->dev->dev_addr[0] = IPOIB_FLAGS_RC;
+	return 0;
+}
+
+void ipoib_cm_dev_cleanup(struct net_device *dev)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	int i, ret;
+
+	if (!priv->cm.srq)
+		return;
+
+	ipoib_dbg(priv, "Cleanup ipoib connected mode.\n");
+
+	ret = ib_destroy_srq(priv->cm.srq);
+	if (ret)
+		ipoib_warn(priv, "ib_destroy_srq failed: %d\n", ret);
+
+	priv->cm.srq = NULL;
+	if (!priv->cm.srq_ring)
+		return;
+	for (i = 0; i < ipoib_recvq_size; ++i)
+		if (priv->cm.srq_ring[i].skb) {
+			ipoib_cm_dma_unmap_rx(priv, priv->cm.srq_ring[i].mapping);
+			dev_kfree_skb_any(priv->cm.srq_ring[i].skb);
+			priv->cm.srq_ring[i].skb = NULL;
+		}
+	kfree(priv->cm.srq_ring);
+	priv->cm.srq_ring = NULL;
+}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index f1cb836..44c1741 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -146,7 +146,7 @@
 	return 0;
 }
 
-static struct file_operations ipoib_mcg_fops = {
+static const struct file_operations ipoib_mcg_fops = {
 	.owner   = THIS_MODULE,
 	.open    = ipoib_mcg_open,
 	.read    = seq_read,
@@ -252,7 +252,7 @@
 	return 0;
 }
 
-static struct file_operations ipoib_path_fops = {
+static const struct file_operations ipoib_path_fops = {
 	.owner   = THIS_MODULE,
 	.open    = ipoib_path_open,
 	.read    = seq_read,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 59d9594..f2aa923 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -50,8 +50,6 @@
 		 "Enable data path debug tracing if > 0");
 #endif
 
-#define	IPOIB_OP_RECV	(1ul << 31)
-
 static DEFINE_MUTEX(pkey_mutex);
 
 struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
@@ -268,10 +266,11 @@
 
 	spin_lock_irqsave(&priv->tx_lock, flags);
 	++priv->tx_tail;
-	if (netif_queue_stopped(dev) &&
-	    test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags) &&
-	    priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1)
+	if (unlikely(test_bit(IPOIB_FLAG_NETIF_STOPPED, &priv->flags)) &&
+	    priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1) {
+		clear_bit(IPOIB_FLAG_NETIF_STOPPED, &priv->flags);
 		netif_wake_queue(dev);
+	}
 	spin_unlock_irqrestore(&priv->tx_lock, flags);
 
 	if (wc->status != IB_WC_SUCCESS &&
@@ -283,7 +282,9 @@
 
 static void ipoib_ib_handle_wc(struct net_device *dev, struct ib_wc *wc)
 {
-	if (wc->wr_id & IPOIB_OP_RECV)
+	if (wc->wr_id & IPOIB_CM_OP_SRQ)
+		ipoib_cm_handle_rx_wc(dev, wc);
+	else if (wc->wr_id & IPOIB_OP_RECV)
 		ipoib_ib_handle_rx_wc(dev, wc);
 	else
 		ipoib_ib_handle_tx_wc(dev, wc);
@@ -327,12 +328,12 @@
 	struct ipoib_tx_buf *tx_req;
 	u64 addr;
 
-	if (unlikely(skb->len > dev->mtu + INFINIBAND_ALEN)) {
+	if (unlikely(skb->len > priv->mcast_mtu + INFINIBAND_ALEN)) {
 		ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n",
-			   skb->len, dev->mtu + INFINIBAND_ALEN);
+			   skb->len, priv->mcast_mtu + INFINIBAND_ALEN);
 		++priv->stats.tx_dropped;
 		++priv->stats.tx_errors;
-		dev_kfree_skb_any(skb);
+		ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu);
 		return;
 	}
 
@@ -372,6 +373,7 @@
 		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);
+			set_bit(IPOIB_FLAG_NETIF_STOPPED, &priv->flags);
 		}
 	}
 }
@@ -424,6 +426,13 @@
 		return -1;
 	}
 
+	ret = ipoib_cm_dev_open(dev);
+	if (ret) {
+		ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret);
+		ipoib_ib_dev_stop(dev);
+		return -1;
+	}
+
 	clear_bit(IPOIB_STOP_REAPER, &priv->flags);
 	queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, HZ);
 
@@ -509,6 +518,8 @@
 
 	clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
 
+	ipoib_cm_dev_stop(dev);
+
 	/*
 	 * Move our QP to the error state and then reinitialize in
 	 * when all work requests have completed or have been flushed.
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index af5ee2e..18d27fd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -49,8 +49,6 @@
 
 #include <net/dst.h>
 
-#define IPOIB_QPN(ha) (be32_to_cpup((__be32 *) ha) & 0xffffff)
-
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
 MODULE_LICENSE("Dual BSD/GPL");
@@ -145,6 +143,8 @@
 
 	netif_stop_queue(dev);
 
+	clear_bit(IPOIB_FLAG_NETIF_STOPPED, &priv->flags);
+
 	/*
 	 * Now flush workqueue to make sure a scheduled task doesn't
 	 * bring our internal state back up.
@@ -178,8 +178,18 @@
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-	if (new_mtu > IPOIB_PACKET_SIZE - IPOIB_ENCAP_LEN)
+	/* dev->mtu > 2K ==> connected mode */
+	if (ipoib_cm_admin_enabled(dev) && new_mtu <= IPOIB_CM_MTU) {
+		if (new_mtu > priv->mcast_mtu)
+			ipoib_warn(priv, "mtu > %d will cause multicast packet drops.\n",
+				   priv->mcast_mtu);
+		dev->mtu = new_mtu;
+		return 0;
+	}
+
+	if (new_mtu > IPOIB_PACKET_SIZE - IPOIB_ENCAP_LEN) {
 		return -EINVAL;
+	}
 
 	priv->admin_mtu = new_mtu;
 
@@ -414,6 +424,20 @@
 			memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw,
 			       sizeof(union ib_gid));
 
+			if (ipoib_cm_enabled(dev, neigh->neighbour)) {
+				if (!ipoib_cm_get(neigh))
+					ipoib_cm_set(neigh, ipoib_cm_create_tx(dev,
+									       path,
+									       neigh));
+				if (!ipoib_cm_get(neigh)) {
+					list_del(&neigh->list);
+					if (neigh->ah)
+						ipoib_put_ah(neigh->ah);
+					ipoib_neigh_free(dev, neigh);
+					continue;
+				}
+			}
+
 			while ((skb = __skb_dequeue(&neigh->queue)))
 				__skb_queue_tail(&skqueue, skb);
 		}
@@ -520,7 +544,25 @@
 		memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw,
 		       sizeof(union ib_gid));
 
-		ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha));
+		if (ipoib_cm_enabled(dev, neigh->neighbour)) {
+			if (!ipoib_cm_get(neigh))
+				ipoib_cm_set(neigh, ipoib_cm_create_tx(dev, path, neigh));
+			if (!ipoib_cm_get(neigh)) {
+				list_del(&neigh->list);
+				if (neigh->ah)
+					ipoib_put_ah(neigh->ah);
+				ipoib_neigh_free(dev, neigh);
+				goto err_drop;
+			}
+			if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE)
+				__skb_queue_tail(&neigh->queue, skb);
+			else {
+				ipoib_warn(priv, "queue length limit %d. Packet drop.\n",
+					   skb_queue_len(&neigh->queue));
+				goto err_drop;
+			}
+		} else
+			ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha));
 	} else {
 		neigh->ah  = NULL;
 
@@ -538,6 +580,7 @@
 
 err_path:
 	ipoib_neigh_free(dev, neigh);
+err_drop:
 	++priv->stats.tx_dropped;
 	dev_kfree_skb_any(skb);
 
@@ -640,7 +683,12 @@
 
 		neigh = *to_ipoib_neigh(skb->dst->neighbour);
 
-		if (likely(neigh->ah)) {
+		if (ipoib_cm_get(neigh)) {
+			if (ipoib_cm_up(neigh)) {
+				ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
+				goto out;
+			}
+		} else if (neigh->ah) {
 			if (unlikely(memcmp(&neigh->dgid.raw,
 					    skb->dst->neighbour->ha + 4,
 					    sizeof(union ib_gid)))) {
@@ -805,6 +853,7 @@
 	neigh->neighbour = neighbour;
 	*to_ipoib_neigh(neighbour) = neigh;
 	skb_queue_head_init(&neigh->queue);
+	ipoib_cm_set(neigh, NULL);
 
 	return neigh;
 }
@@ -818,6 +867,8 @@
 		++priv->stats.tx_dropped;
 		dev_kfree_skb_any(skb);
 	}
+	if (ipoib_cm_get(neigh))
+		ipoib_cm_destroy_tx(ipoib_cm_get(neigh));
 	kfree(neigh);
 }
 
@@ -1080,6 +1131,8 @@
 
 	ipoib_create_debug_files(priv->dev);
 
+	if (ipoib_cm_add_mode_attr(priv->dev))
+		goto sysfs_failed;
 	if (ipoib_add_pkey_attr(priv->dev))
 		goto sysfs_failed;
 	if (device_create_file(&priv->dev->dev, &dev_attr_create_child))
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index b04b72c..b303ce6 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -60,14 +60,11 @@
 /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
 struct ipoib_mcast {
 	struct ib_sa_mcmember_rec mcmember;
+	struct ib_sa_multicast	 *mc;
 	struct ipoib_ah          *ah;
 
 	struct rb_node    rb_node;
 	struct list_head  list;
-	struct completion done;
-
-	int                 query_id;
-	struct ib_sa_query *query;
 
 	unsigned long created;
 	unsigned long backoff;
@@ -299,18 +296,22 @@
 	return 0;
 }
 
-static void
+static int
 ipoib_mcast_sendonly_join_complete(int status,
-				   struct ib_sa_mcmember_rec *mcmember,
-				   void *mcast_ptr)
+				   struct ib_sa_multicast *multicast)
 {
-	struct ipoib_mcast *mcast = mcast_ptr;
+	struct ipoib_mcast *mcast = multicast->context;
 	struct net_device *dev = mcast->dev;
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
+	/* We trap for port events ourselves. */
+	if (status == -ENETRESET)
+		return 0;
+
 	if (!status)
-		ipoib_mcast_join_finish(mcast, mcmember);
-	else {
+		status = ipoib_mcast_join_finish(mcast, &multicast->rec);
+
+	if (status) {
 		if (mcast->logcount++ < 20)
 			ipoib_dbg_mcast(netdev_priv(dev), "multicast join failed for "
 					IPOIB_GID_FMT ", status %d\n",
@@ -325,11 +326,10 @@
 		spin_unlock_irq(&priv->tx_lock);
 
 		/* Clear the busy flag so we try again */
-		clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
-		mcast->query = NULL;
+		status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY,
+					    &mcast->flags);
 	}
-
-	complete(&mcast->done);
+	return status;
 }
 
 static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
@@ -359,35 +359,33 @@
 	rec.port_gid = priv->local_gid;
 	rec.pkey     = cpu_to_be16(priv->pkey);
 
-	init_completion(&mcast->done);
-
-	ret = ib_sa_mcmember_rec_set(&ipoib_sa_client, priv->ca, priv->port, &rec,
-				     IB_SA_MCMEMBER_REC_MGID		|
-				     IB_SA_MCMEMBER_REC_PORT_GID	|
-				     IB_SA_MCMEMBER_REC_PKEY		|
-				     IB_SA_MCMEMBER_REC_JOIN_STATE,
-				     1000, GFP_ATOMIC,
-				     ipoib_mcast_sendonly_join_complete,
-				     mcast, &mcast->query);
-	if (ret < 0) {
-		ipoib_warn(priv, "ib_sa_mcmember_rec_set failed (ret = %d)\n",
+	mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca,
+					 priv->port, &rec,
+					 IB_SA_MCMEMBER_REC_MGID	|
+					 IB_SA_MCMEMBER_REC_PORT_GID	|
+					 IB_SA_MCMEMBER_REC_PKEY	|
+					 IB_SA_MCMEMBER_REC_JOIN_STATE,
+					 GFP_ATOMIC,
+					 ipoib_mcast_sendonly_join_complete,
+					 mcast);
+	if (IS_ERR(mcast->mc)) {
+		ret = PTR_ERR(mcast->mc);
+		clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+		ipoib_warn(priv, "ib_sa_join_multicast failed (ret = %d)\n",
 			   ret);
 	} else {
 		ipoib_dbg_mcast(priv, "no multicast record for " IPOIB_GID_FMT
 				", starting join\n",
 				IPOIB_GID_ARG(mcast->mcmember.mgid));
-
-		mcast->query_id = ret;
 	}
 
 	return ret;
 }
 
-static void ipoib_mcast_join_complete(int status,
-				      struct ib_sa_mcmember_rec *mcmember,
-				      void *mcast_ptr)
+static int ipoib_mcast_join_complete(int status,
+				     struct ib_sa_multicast *multicast)
 {
-	struct ipoib_mcast *mcast = mcast_ptr;
+	struct ipoib_mcast *mcast = multicast->context;
 	struct net_device *dev = mcast->dev;
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
@@ -395,24 +393,25 @@
 			" (status %d)\n",
 			IPOIB_GID_ARG(mcast->mcmember.mgid), status);
 
-	if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) {
+	/* We trap for port events ourselves. */
+	if (status == -ENETRESET)
+		return 0;
+
+	if (!status)
+		status = ipoib_mcast_join_finish(mcast, &multicast->rec);
+
+	if (!status) {
 		mcast->backoff = 1;
 		mutex_lock(&mcast_mutex);
 		if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
 			queue_delayed_work(ipoib_workqueue,
 					   &priv->mcast_task, 0);
 		mutex_unlock(&mcast_mutex);
-		complete(&mcast->done);
-		return;
+		return 0;
 	}
 
-	if (status == -EINTR) {
-		complete(&mcast->done);
-		return;
-	}
-
-	if (status && mcast->logcount++ < 20) {
-		if (status == -ETIMEDOUT || status == -EINTR) {
+	if (mcast->logcount++ < 20) {
+		if (status == -ETIMEDOUT) {
 			ipoib_dbg_mcast(priv, "multicast join failed for " IPOIB_GID_FMT
 					", status %d\n",
 					IPOIB_GID_ARG(mcast->mcmember.mgid),
@@ -429,24 +428,18 @@
 	if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
 		mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
 
+	/* Clear the busy flag so we try again */
+	status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+
 	mutex_lock(&mcast_mutex);
-
 	spin_lock_irq(&priv->lock);
-	mcast->query = NULL;
-
-	if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) {
-		if (status == -ETIMEDOUT)
-			queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
-					   0);
-		else
-			queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
-					   mcast->backoff * HZ);
-	} else
-		complete(&mcast->done);
+	if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
+		queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
+				   mcast->backoff * HZ);
 	spin_unlock_irq(&priv->lock);
 	mutex_unlock(&mcast_mutex);
 
-	return;
+	return status;
 }
 
 static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
@@ -495,15 +488,14 @@
 		rec.hop_limit	  = priv->broadcast->mcmember.hop_limit;
 	}
 
-	init_completion(&mcast->done);
-
-	ret = ib_sa_mcmember_rec_set(&ipoib_sa_client, priv->ca, priv->port,
-				     &rec, comp_mask, mcast->backoff * 1000,
-				     GFP_ATOMIC, ipoib_mcast_join_complete,
-				     mcast, &mcast->query);
-
-	if (ret < 0) {
-		ipoib_warn(priv, "ib_sa_mcmember_rec_set failed, status %d\n", ret);
+	set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+	mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
+					 &rec, comp_mask, GFP_KERNEL,
+					 ipoib_mcast_join_complete, mcast);
+	if (IS_ERR(mcast->mc)) {
+		clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+		ret = PTR_ERR(mcast->mc);
+		ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
 
 		mcast->backoff *= 2;
 		if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
@@ -515,8 +507,7 @@
 					   &priv->mcast_task,
 					   mcast->backoff * HZ);
 		mutex_unlock(&mcast_mutex);
-	} else
-		mcast->query_id = ret;
+	}
 }
 
 void ipoib_mcast_join_task(struct work_struct *work)
@@ -541,7 +532,7 @@
 			priv->local_rate = attr.active_speed *
 				ib_width_enum_to_int(attr.active_width);
 		} else
-		ipoib_warn(priv, "ib_query_port failed\n");
+			ipoib_warn(priv, "ib_query_port failed\n");
 	}
 
 	if (!priv->broadcast) {
@@ -568,7 +559,8 @@
 	}
 
 	if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
-		ipoib_mcast_join(dev, priv->broadcast, 0);
+		if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags))
+			ipoib_mcast_join(dev, priv->broadcast, 0);
 		return;
 	}
 
@@ -597,7 +589,9 @@
 
 	priv->mcast_mtu = ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu) -
 		IPOIB_ENCAP_LEN;
-	dev->mtu = min(priv->mcast_mtu, priv->admin_mtu);
+
+	if (!ipoib_cm_admin_enabled(dev))
+		dev->mtu = min(priv->mcast_mtu, priv->admin_mtu);
 
 	ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");
 
@@ -623,26 +617,9 @@
 	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);
-	struct ipoib_mcast *mcast;
 
 	ipoib_dbg_mcast(priv, "stopping multicast thread\n");
 
@@ -658,52 +635,27 @@
 	if (flush)
 		flush_workqueue(ipoib_workqueue);
 
-	wait_for_mcast_join(priv, priv->broadcast);
-
-	list_for_each_entry(mcast, &priv->multicast_list, list)
-		wait_for_mcast_join(priv, mcast);
-
 	return 0;
 }
 
 static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
-	struct ib_sa_mcmember_rec rec = {
-		.join_state = 1
-	};
 	int ret = 0;
 
-	if (!test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags))
-		return 0;
+	if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
+		ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n",
+				IPOIB_GID_ARG(mcast->mcmember.mgid));
 
-	ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n",
-			IPOIB_GID_ARG(mcast->mcmember.mgid));
+		/* Remove ourselves from the multicast group */
+		ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
+					 &mcast->mcmember.mgid);
+		if (ret)
+			ipoib_warn(priv, "ipoib_mcast_detach failed (result = %d)\n", ret);
+	}
 
-	rec.mgid     = mcast->mcmember.mgid;
-	rec.port_gid = priv->local_gid;
-	rec.pkey     = cpu_to_be16(priv->pkey);
-
-	/* Remove ourselves from the multicast group */
-	ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
-				 &mcast->mcmember.mgid);
-	if (ret)
-		ipoib_warn(priv, "ipoib_mcast_detach failed (result = %d)\n", ret);
-
-	/*
-	 * Just make one shot at leaving and don't wait for a reply;
-	 * if we fail, too bad.
-	 */
-	ret = ib_sa_mcmember_rec_delete(&ipoib_sa_client, priv->ca, priv->port, &rec,
-					IB_SA_MCMEMBER_REC_MGID		|
-					IB_SA_MCMEMBER_REC_PORT_GID	|
-					IB_SA_MCMEMBER_REC_PKEY		|
-					IB_SA_MCMEMBER_REC_JOIN_STATE,
-					0, GFP_ATOMIC, NULL,
-					mcast, &mcast->query);
-	if (ret < 0)
-		ipoib_warn(priv, "ib_sa_mcmember_rec_delete failed "
-			   "for leave (result = %d)\n", ret);
+	if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
+		ib_sa_free_multicast(mcast->mc);
 
 	return 0;
 }
@@ -756,7 +708,7 @@
 			dev_kfree_skb_any(skb);
 		}
 
-		if (mcast->query)
+		if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
 			ipoib_dbg_mcast(priv, "no address vector, "
 					"but multicast join already started\n");
 		else if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
@@ -914,7 +866,6 @@
 
 	/* 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 7b717c64..3cb551b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -168,35 +168,41 @@
 		.qp_type     = IB_QPT_UD
 	};
 
+	int ret, size;
+
 	priv->pd = ib_alloc_pd(priv->ca);
 	if (IS_ERR(priv->pd)) {
 		printk(KERN_WARNING "%s: failed to allocate PD\n", ca->name);
 		return -ENODEV;
 	}
 
-	priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev,
-				ipoib_sendq_size + ipoib_recvq_size + 1);
+	priv->mr = ib_get_dma_mr(priv->pd, IB_ACCESS_LOCAL_WRITE);
+	if (IS_ERR(priv->mr)) {
+		printk(KERN_WARNING "%s: ib_get_dma_mr failed\n", ca->name);
+		goto out_free_pd;
+	}
+
+	size = ipoib_sendq_size + ipoib_recvq_size + 1;
+	ret = ipoib_cm_dev_init(dev);
+	if (!ret)
+		size += ipoib_recvq_size;
+
+	priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size);
 	if (IS_ERR(priv->cq)) {
 		printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
-		goto out_free_pd;
+		goto out_free_mr;
 	}
 
 	if (ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP))
 		goto out_free_cq;
 
-	priv->mr = ib_get_dma_mr(priv->pd, IB_ACCESS_LOCAL_WRITE);
-	if (IS_ERR(priv->mr)) {
-		printk(KERN_WARNING "%s: ib_get_dma_mr failed\n", ca->name);
-		goto out_free_cq;
-	}
-
 	init_attr.send_cq = priv->cq;
 	init_attr.recv_cq = priv->cq,
 
 	priv->qp = ib_create_qp(priv->pd, &init_attr);
 	if (IS_ERR(priv->qp)) {
 		printk(KERN_WARNING "%s: failed to create QP\n", ca->name);
-		goto out_free_mr;
+		goto out_free_cq;
 	}
 
 	priv->dev->dev_addr[1] = (priv->qp->qp_num >> 16) & 0xff;
@@ -212,12 +218,12 @@
 
 	return 0;
 
-out_free_mr:
-	ib_dereg_mr(priv->mr);
-
 out_free_cq:
 	ib_destroy_cq(priv->cq);
 
+out_free_mr:
+	ib_dereg_mr(priv->mr);
+
 out_free_pd:
 	ib_dealloc_pd(priv->pd);
 	return -ENODEV;
@@ -235,12 +241,14 @@
 		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
 	}
 
-	if (ib_dereg_mr(priv->mr))
-		ipoib_warn(priv, "ib_dereg_mr failed\n");
-
 	if (ib_destroy_cq(priv->cq))
 		ipoib_warn(priv, "ib_cq_destroy failed\n");
 
+	ipoib_cm_dev_cleanup(dev);
+
+	if (ib_dereg_mr(priv->mr))
+		ipoib_warn(priv, "ib_dereg_mr failed\n");
+
 	if (ib_dealloc_pd(priv->pd))
 		ipoib_warn(priv, "ib_dealloc_pd failed\n");
 }
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index 085eafe..6762988 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -115,6 +115,8 @@
 
 	ipoib_create_debug_files(priv->dev);
 
+	if (ipoib_cm_add_mode_attr(priv->dev))
+		goto sysfs_failed;
 	if (ipoib_add_pkey_attr(priv->dev))
 		goto sysfs_failed;
 
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 0a7d1ab..89e3728 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -567,7 +567,7 @@
 	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
 
 	if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
-	        itt = hdr->itt & ISCSI_ITT_MASK; /* mask out cid and age bits */
+	        itt = get_itt(hdr->itt); /* mask out cid and age bits */
 		if (!(itt < session->cmds_max))
 			iser_err("itt can't be matched to task!!!"
 				 "conn %p opcode %d cmds_max %d itt %d\n",
@@ -625,7 +625,7 @@
 		/* this arithmetic is legal by libiscsi dd_data allocation */
 		mtask = (void *) ((long)(void *)tx_desc -
 				  sizeof(struct iscsi_mgmt_task));
-		if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
+		if (mtask->hdr->itt == RESERVED_ITT) {
 			struct iscsi_session *session = conn->session;
 
 			spin_lock(&conn->session->lock);
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index eba18b6..d226d93 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -29,7 +29,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
-#include <linux/sched.h>
+#include <linux/jiffies.h>
 
 #include "fixp-arith.h"
 
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index f68dbe6..7b7a546 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -151,7 +151,6 @@
 		return -ENOMEM;
 	}
 
-	memset(ns558, 0, sizeof(struct ns558));
 	ns558->io = io;
 	ns558->size = 1 << i;
 	ns558->gameport = port;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 7cf2b4f..a9a706f 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -11,7 +11,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/input.h>
 #include <linux/module.h>
@@ -482,7 +481,7 @@
 	return seq_open(file, &input_devices_seq_ops);
 }
 
-static struct file_operations input_devices_fileops = {
+static const struct file_operations input_devices_fileops = {
 	.owner		= THIS_MODULE,
 	.open		= input_proc_devices_open,
 	.poll		= input_proc_devices_poll,
@@ -533,7 +532,7 @@
 	return seq_open(file, &input_handlers_seq_ops);
 }
 
-static struct file_operations input_handlers_fileops = {
+static const struct file_operations input_handlers_fileops = {
 	.owner		= THIS_MODULE,
 	.open		= input_proc_handlers_open,
 	.read		= seq_read,
@@ -589,18 +588,9 @@
 static ssize_t input_dev_show_##name(struct class_device *dev, char *buf)	\
 {										\
 	struct input_dev *input_dev = to_input_dev(dev);			\
-	int retval;								\
 										\
-	retval = mutex_lock_interruptible(&input_dev->mutex);			\
-	if (retval)								\
-		return retval;							\
-										\
-	retval = scnprintf(buf, PAGE_SIZE,					\
-			   "%s\n", input_dev->name ? input_dev->name : "");	\
-										\
-	mutex_unlock(&input_dev->mutex);					\
-										\
-	return retval;								\
+	return scnprintf(buf, PAGE_SIZE, "%s\n",				\
+			 input_dev->name ? input_dev->name : "");		\
 }										\
 static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
 
@@ -1050,10 +1040,6 @@
 	sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
 	sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
 
-	mutex_lock(&dev->mutex);
-	dev->name = dev->phys = dev->uniq = NULL;
-	mutex_unlock(&dev->mutex);
-
 	class_device_unregister(&dev->cdev);
 
 	input_wakeup_procfs_readers();
@@ -1142,7 +1128,7 @@
 	return err;
 }
 
-static struct file_operations input_fops = {
+static const struct file_operations input_fops = {
 	.owner = THIS_MODULE,
 	.open = input_open_file,
 };
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index e608691..b0f5541 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -50,8 +50,6 @@
 module_param_array_named(map, amijoy, uint, NULL, 0);
 MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is 0,1)");
 
-__obsolete_setup("amijoy=");
-
 static int amijoy_used;
 static DEFINE_MUTEX(amijoy_mutex);
 static struct input_dev *amijoy_dev[2];
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 7ef6845..51f1e4b 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -58,8 +58,6 @@
 module_param_array_named(map, js, charp, &js_nargs, 0);
 MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities");
 
-__obsolete_setup("js=");
-
 /*
  * Times, feature definitions.
  */
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 5080e15..b41bd2e 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -59,10 +59,6 @@
 module_param_array_named(dev3, db9[2].args, int, &db9[2].nargs, 0);
 MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
 
-__obsolete_setup("db9=");
-__obsolete_setup("db9_2=");
-__obsolete_setup("db9_3=");
-
 #define DB9_ARG_PARPORT		0
 #define DB9_ARG_MODE		1
 
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index fe12aa3..711e4b3 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -60,10 +60,6 @@
 module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0);
 MODULE_PARM_DESC(map3, "Describes third set of devices");
 
-__obsolete_setup("gc=");
-__obsolete_setup("gc_2=");
-__obsolete_setup("gc_3=");
-
 /* see also gs_psx_delay parameter in PSX support section */
 
 #define GC_SNES		1
@@ -403,8 +399,6 @@
 module_param_named(psx_delay, gc_psx_delay, uint, 0);
 MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)");
 
-__obsolete_setup("gc_psx_delay=");
-
 static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
 static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
 				BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 5570fd5..037d348 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -60,10 +60,6 @@
 module_param_array_named(map3, tgfx[2].args, int, &tgfx[2].nargs, 0);
 MODULE_PARM_DESC(map3, "Describes third set of devices");
 
-__obsolete_setup("tgfx=");
-__obsolete_setup("tgfx_2=");
-__obsolete_setup("tgfx_3=");
-
 #define TGFX_REFRESH_TIME	HZ/100	/* 10 ms */
 
 #define TGFX_TRIGGER		0x08
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 049f2f5..6450968 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -135,12 +135,12 @@
 config KEYBOARD_CORGI
 	tristate "Corgi keyboard"
 	depends on PXA_SHARPSL
-	default y	
+	default y
 	help
-	  Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx 
+	  Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx
 	  series of PDAs.
 
-	  To compile this driver as a module, choose M here: the 
+	  To compile this driver as a module, choose M here: the
 	  module will be called corgikbd.
 
 config KEYBOARD_SPITZ
@@ -214,4 +214,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called aaed2000_kbd.
 
+config KEYBOARD_GPIO
+	tristate "Buttons on CPU GPIOs (PXA)"
+	depends on (ARCH_SA1100 || ARCH_PXA || ARCH_S3C2410)
+	help
+	  This driver implements support for buttons connected
+	  directly to GPIO pins of SA1100, PXA or S3C24xx CPUs.
+
+	  Say Y here if your device has buttons connected
+	  directly to GPIO pins of the CPU.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gpio-keys.
+
 endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 5687979..586a0fe 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -16,6 +16,7 @@
 obj-$(CONFIG_KEYBOARD_SPITZ)		+= spitzkbd.o
 obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
-obj-$(CONFIG_KEYBOARD_OMAP)             += omap-keypad.o
-obj-$(CONFIG_KEYBOARD_AAED2000)         += aaed2000_kbd.o
+obj-$(CONFIG_KEYBOARD_OMAP)		+= omap-keypad.o
+obj-$(CONFIG_KEYBOARD_AAED2000)		+= aaed2000_kbd.o
+obj-$(CONFIG_KEYBOARD_GPIO)		+= gpio_keys.o
 
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index c621a91..6638770 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -63,10 +63,6 @@
 module_param_named(extra, atkbd_extra, bool, 0);
 MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
 
-__obsolete_setup("atkbd_set=");
-__obsolete_setup("atkbd_reset");
-__obsolete_setup("atkbd_softrepeat=");
-
 /*
  * Scancode to keycode tables. These are just the default setting, and
  * are loadable via an userland utility.
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
new file mode 100644
index 0000000..fa03a00
--- /dev/null
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -0,0 +1,148 @@
+/*
+ * Driver for keys on GPIO lines capable of generating interrupts.
+ *
+ * Copyright 2005 Phil Blundell
+ *
+ * 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/version.h>
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+
+#include <asm/gpio.h>
+#include <asm/arch/hardware.h>
+
+#include <asm/hardware/gpio_keys.h>
+
+static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
+{
+	int i;
+	struct platform_device *pdev = dev_id;
+	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+	struct input_dev *input = platform_get_drvdata(pdev);
+
+	for (i = 0; i < pdata->nbuttons; i++) {
+		int gpio = pdata->buttons[i].gpio;
+		if (irq == gpio_to_irq(gpio)) {
+			int state = (gpio_get_value(gpio) ? 1 : 0) ^ (pdata->buttons[i].active_low);
+
+			input_report_key(input, pdata->buttons[i].keycode, state);
+			input_sync(input);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit gpio_keys_probe(struct platform_device *pdev)
+{
+	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+	struct input_dev *input;
+	int i, error;
+
+	input = input_allocate_device();
+	if (!input)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, input);
+
+	input->evbit[0] = BIT(EV_KEY);
+
+	input->name = pdev->name;
+	input->phys = "gpio-keys/input0";
+	input->cdev.dev = &pdev->dev;
+	input->private = pdata;
+
+	input->id.bustype = BUS_HOST;
+	input->id.vendor = 0x0001;
+	input->id.product = 0x0001;
+	input->id.version = 0x0100;
+
+	for (i = 0; i < pdata->nbuttons; i++) {
+		int code = pdata->buttons[i].keycode;
+		int irq = gpio_to_irq(pdata->buttons[i].gpio);
+
+		set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
+		error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM,
+				     pdata->buttons[i].desc ? pdata->buttons[i].desc : "gpio_keys",
+				     pdev);
+		if (error) {
+			printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n",
+				irq, error);
+			goto fail;
+		}
+		set_bit(code, input->keybit);
+	}
+
+	error = input_register_device(input);
+	if (error) {
+		printk(KERN_ERR "Unable to register gpio-keys input device\n");
+		goto fail;
+	}
+
+	return 0;
+
+ fail:
+	for (i = i - 1; i >= 0; i--)
+		free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
+
+	input_free_device(input);
+
+	return error;
+}
+
+static int __devexit gpio_keys_remove(struct platform_device *pdev)
+{
+	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+	struct input_dev *input = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < pdata->nbuttons; i++) {
+		int irq = gpio_to_irq(pdata->buttons[i].gpio);
+		free_irq(irq, pdev);
+	}
+
+	input_unregister_device(input);
+
+	return 0;
+}
+
+struct platform_driver gpio_keys_device_driver = {
+	.probe		= gpio_keys_probe,
+	.remove		= __devexit_p(gpio_keys_remove),
+	.driver		= {
+		.name	= "gpio-keys",
+	}
+};
+
+static int __init gpio_keys_init(void)
+{
+	return platform_driver_register(&gpio_keys_device_driver);
+}
+
+static void __exit gpio_keys_exit(void)
+{
+	platform_driver_unregister(&gpio_keys_device_driver);
+}
+
+module_init(gpio_keys_init);
+module_exit(gpio_keys_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
+MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index 35461ea..4de4dc2 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -6,10 +6,10 @@
  *  Copyright (C) 1999-2006 Helge Deller <deller@gmx.de>
  *
  *  Very basic HP Human Interface Loop (HIL) driver.
- *  This driver handles the keyboard on HP300 (m68k) and on some 
+ *  This driver handles the keyboard on HP300 (m68k) and on some
  *  HP700 (parisc) series machines.
  *
- * 
+ *
  * This file is subject to the terms and conditions of the GNU General Public
  * License version 2.  See the file COPYING in the main directory of this
  * archive for more details.
@@ -64,9 +64,9 @@
 #endif
 
 
- 
+
 /* HIL helper functions */
- 
+
 #define hil_busy()              (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY)
 #define hil_data_available()    (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
 #define hil_status()            (hil_readb(HILBASE + HIL_CMD))
@@ -75,7 +75,7 @@
 #define hil_write_data(x)       do { hil_writeb((x), HILBASE + HIL_DATA); } while (0)
 
 /* HIL constants */
- 
+
 #define	HIL_BUSY		0x02
 #define	HIL_DATA_RDY		0x01
 
@@ -86,10 +86,10 @@
 #define	HIL_INTON		0x5C		/* Turn on interrupts. */
 #define	HIL_INTOFF		0x5D		/* Turn off interrupts. */
 
-#define	HIL_READKBDSADR	 	0xF9
-#define	HIL_WRITEKBDSADR 	0xE9
+#define	HIL_READKBDSADR		0xF9
+#define	HIL_WRITEKBDSADR	0xE9
 
-static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = 
+static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
 	{ HIL_KEYCODES_SET1 };
 
 /* HIL structure */
@@ -97,11 +97,11 @@
 	struct input_dev *dev;
 
 	unsigned int curdev;
-	
+
 	unsigned char s;
 	unsigned char c;
 	int valid;
-	
+
 	unsigned char data[16];
 	unsigned int ptr;
 	spinlock_t lock;
@@ -115,7 +115,7 @@
 	int down;
 	int key;
 	unsigned char scode;
-	
+
 	switch (hil_dev.data[0]) {
 	case 0x40:
 		down = (hil_dev.data[1] & 1) == 0;
@@ -127,6 +127,7 @@
 	hil_dev.curdev = 0;
 }
 
+
 static inline void handle_status(unsigned char s, unsigned char c)
 {
 	if (c & 0x8) {
@@ -143,6 +144,7 @@
 	}
 }
 
+
 static inline void handle_data(unsigned char s, unsigned char c)
 {
 	if (hil_dev.curdev) {
@@ -152,13 +154,11 @@
 }
 
 
-/* 
- * Handle HIL interrupts.
- */
+/* handle HIL interrupts */
 static irqreturn_t hil_interrupt(int irq, void *handle)
 {
 	unsigned char s, c;
-	
+
 	s = hil_status();
 	c = hil_read_data();
 
@@ -179,10 +179,8 @@
 	return IRQ_HANDLED;
 }
 
-/*
- * Send a command to the HIL
- */
 
+/* send a command to the HIL */
 static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
 {
 	unsigned long flags;
@@ -200,16 +198,14 @@
 }
 
 
-/*
- * Initialise HIL. 
- */
-
+/* initialise HIL */
 static int __init
 hil_keyb_init(void)
 {
 	unsigned char c;
 	unsigned int i, kbid;
 	wait_queue_head_t hil_wait;
+	int err;
 
 	if (hil_dev.dev) {
 		return -ENODEV; /* already initialized */
@@ -219,15 +215,25 @@
 	if (!hil_dev.dev)
 		return -ENOMEM;
 	hil_dev.dev->private = &hil_dev;
-	
+
 #if defined(CONFIG_HP300)
-	if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
-		return -ENODEV;
-	
-	request_region(HILBASE+HIL_DATA, 2, "hil");
+	if (!hwreg_present((void *)(HILBASE + HIL_DATA))) {
+		printk(KERN_ERR "HIL: hardware register was not found\n");
+		err = -ENODEV;
+		goto err1;
+	}
+	if (!request_region(HILBASE + HIL_DATA, 2, "hil")) {
+		printk(KERN_ERR "HIL: IOPORT region already used\n");
+		err = -EIO;
+		goto err1;
+	}
 #endif
-	
-	request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
+
+	err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
+	if (err) {
+		printk(KERN_ERR "HIL: Can't get IRQ\n");
+		goto err2;
+	}
 
 	/* Turn on interrupts */
 	hil_do(HIL_INTON, NULL, 0);
@@ -239,47 +245,65 @@
 	init_waitqueue_head(&hil_wait);
 	wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ);
 	if (!hil_dev.valid) {
-		printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n");
+		printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n");
 	}
 
-	c = hil_dev.c; 
+	c = hil_dev.c;
 	hil_dev.valid = 0;
 	if (c == 0) {
 		kbid = -1;
-		printk(KERN_WARNING "HIL: no keyboard present.\n");
+		printk(KERN_WARNING "HIL: no keyboard present\n");
 	} else {
 		kbid = ffz(~c);
-		/* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */
+		printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid);
 	}
 
 	/* set it to raw mode */
 	c = 0;
 	hil_do(HIL_WRITEKBDSADR, &c, 1);
-	
+
 	for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
 		if (hphilkeyb_keycode[i] != KEY_RESERVED)
 			set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit);
 
-	hil_dev.dev->evbit[0]    = BIT(EV_KEY) | BIT(EV_REP);
-	hil_dev.dev->ledbit[0]   = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
-	hil_dev.dev->keycodemax  = HIL_KEYCODES_SET1_TBLSIZE;
-	hil_dev.dev->keycodesize = sizeof(hphilkeyb_keycode[0]);
-	hil_dev.dev->keycode     = hphilkeyb_keycode;
-	hil_dev.dev->name 	= "HIL keyboard";
-	hil_dev.dev->phys 	= "hpkbd/input0";
+	hil_dev.dev->evbit[0]	= BIT(EV_KEY) | BIT(EV_REP);
+	hil_dev.dev->ledbit[0]	= BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+	hil_dev.dev->keycodemax	= HIL_KEYCODES_SET1_TBLSIZE;
+	hil_dev.dev->keycodesize= sizeof(hphilkeyb_keycode[0]);
+	hil_dev.dev->keycode	= hphilkeyb_keycode;
+	hil_dev.dev->name	= "HIL keyboard";
+	hil_dev.dev->phys	= "hpkbd/input0";
 
 	hil_dev.dev->id.bustype	= BUS_HIL;
 	hil_dev.dev->id.vendor	= PCI_VENDOR_ID_HP;
 	hil_dev.dev->id.product	= 0x0001;
 	hil_dev.dev->id.version	= 0x0010;
 
-	input_register_device(hil_dev.dev);
+	err = input_register_device(hil_dev.dev);
+	if (err) {
+		printk(KERN_ERR "HIL: Can't register device\n");
+		goto err3;
+	}
 	printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
-		hil_dev.dev->name, kbid, HILBASE, HIL_IRQ);
+	       hil_dev.dev->name, kbid, HILBASE, HIL_IRQ);
 
 	return 0;
+
+err3:
+	hil_do(HIL_INTOFF, NULL, 0);
+	disable_irq(HIL_IRQ);
+	free_irq(HIL_IRQ, hil_dev.dev_id);
+err2:
+#if defined(CONFIG_HP300)
+	release_region(HILBASE + HIL_DATA, 2);
+err1:
+#endif
+	input_free_device(hil_dev.dev);
+	hil_dev.dev = NULL;
+	return err;
 }
 
+
 #if defined(CONFIG_PARISC)
 static int __init
 hil_init_chip(struct parisc_device *dev)
@@ -292,7 +316,7 @@
 	hil_base = dev->hpa.start;
 	hil_irq  = dev->irq;
 	hil_dev.dev_id = dev;
-	
+
 	printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq);
 
 	return hil_keyb_init();
@@ -313,9 +337,6 @@
 #endif /* CONFIG_PARISC */
 
 
-
-
-
 static int __init hil_init(void)
 {
 #if defined(CONFIG_PARISC)
@@ -349,4 +370,3 @@
 
 module_init(hil_init);
 module_exit(hil_exit);
-
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index ba0e88c..41b4258 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -50,6 +50,16 @@
 	  To compile this driver as a module, choose M here: the module will
 	  be called wistron_btns.
 
+config INPUT_ATLAS_BTNS
+	tristate "x86 Atlas button interface"
+	depends on X86 && ACPI
+	help
+	  Say Y here for support of Atlas wallmount touchscreen buttons.
+	  The events will show up as scancodes F1 through F9 via evdev.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called atlas_btns.
+
 config INPUT_IXP4XX_BEEPER
 	tristate "IXP4XX Beeper support"
 	depends on ARCH_IXP4XX
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 415c491..e0a8d58 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -9,5 +9,6 @@
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
+obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c
new file mode 100644
index 0000000..0acc3a1
--- /dev/null
+++ b/drivers/input/misc/atlas_btns.c
@@ -0,0 +1,170 @@
+/*
+ *  atlas_btns.c - Atlas Wallmount Touchscreen ACPI Extras
+ *
+ *  Copyright (C) 2006 Jaya Kumar
+ *  Based on Toshiba ACPI by John Belmonte and ASUS ACPI
+ *  This work was sponsored by CIS(M) Sdn Bhd.
+ *
+ *  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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <acpi/acpi_drivers.h>
+
+#define ACPI_ATLAS_NAME			"Atlas ACPI"
+#define ACPI_ATLAS_CLASS		"Atlas"
+#define ACPI_ATLAS_BUTTON_HID		"ASIM0000"
+
+static struct input_dev *input_dev;
+
+/* button handling code */
+static acpi_status acpi_atlas_button_setup(acpi_handle region_handle,
+		    u32 function, void *handler_context, void **return_context)
+{
+	*return_context =
+		(function != ACPI_REGION_DEACTIVATE) ? handler_context : NULL;
+
+	return AE_OK;
+}
+
+static acpi_status acpi_atlas_button_handler(u32 function,
+		      acpi_physical_address address,
+		      u32 bit_width, acpi_integer *value,
+		      void *handler_context, void *region_context)
+{
+	acpi_status status;
+	int keycode;
+
+	if (function == ACPI_WRITE) {
+		keycode = KEY_F1 + (address & 0x0F);
+		input_report_key(input_dev, keycode, !(address & 0x10));
+		input_sync(input_dev);
+		status = 0;
+	} else {
+		printk(KERN_WARNING "atlas: shrugged on unexpected function"
+			":function=%x,address=%lx,value=%x\n",
+			function, (unsigned long)address, (u32)*value);
+		status = -EINVAL;
+	}
+
+	return status;
+}
+
+static int atlas_acpi_button_add(struct acpi_device *device)
+{
+	acpi_status status;
+	int err;
+
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		printk(KERN_ERR "atlas: unable to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	input_dev->name = "Atlas ACPI button driver";
+	input_dev->phys = "ASIM0000/atlas/input0";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->evbit[LONG(EV_KEY)] = BIT(EV_KEY);
+
+	set_bit(KEY_F1, input_dev->keybit);
+	set_bit(KEY_F2, input_dev->keybit);
+	set_bit(KEY_F3, input_dev->keybit);
+	set_bit(KEY_F4, input_dev->keybit);
+	set_bit(KEY_F5, input_dev->keybit);
+	set_bit(KEY_F6, input_dev->keybit);
+	set_bit(KEY_F7, input_dev->keybit);
+	set_bit(KEY_F8, input_dev->keybit);
+	set_bit(KEY_F9, input_dev->keybit);
+
+	err = input_register_device(input_dev);
+	if (err) {
+		printk(KERN_ERR "atlas: couldn't register input device\n");
+		input_free_device(input_dev);
+		return err;
+	}
+
+	/* hookup button handler */
+	status = acpi_install_address_space_handler(device->handle,
+				0x81, &acpi_atlas_button_handler,
+				&acpi_atlas_button_setup, device);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "Atlas: Error installing addr spc handler\n");
+		input_unregister_device(input_dev);
+		status = -EINVAL;
+	}
+
+	return status;
+}
+
+static int atlas_acpi_button_remove(struct acpi_device *device, int type)
+{
+	acpi_status status;
+
+	status = acpi_remove_address_space_handler(device->handle,
+				0x81, &acpi_atlas_button_handler);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "Atlas: Error removing addr spc handler\n");
+		status = -EINVAL;
+	}
+
+	input_unregister_device(input_dev);
+
+	return status;
+}
+
+static struct acpi_driver atlas_acpi_driver = {
+	.name	= ACPI_ATLAS_NAME,
+	.class	= ACPI_ATLAS_CLASS,
+	.ids	= ACPI_ATLAS_BUTTON_HID,
+	.ops	= {
+		.add	= atlas_acpi_button_add,
+		.remove	= atlas_acpi_button_remove,
+	},
+};
+
+static int __init atlas_acpi_init(void)
+{
+	int result;
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	result = acpi_bus_register_driver(&atlas_acpi_driver);
+	if (result < 0) {
+		printk(KERN_ERR "Atlas ACPI: Unable to register driver\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit atlas_acpi_exit(void)
+{
+	acpi_bus_unregister_driver(&atlas_acpi_driver);
+}
+
+module_init(atlas_acpi_init);
+module_exit(atlas_acpi_exit);
+
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Atlas button driver");
+
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 31d5a13..ab76ea4 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -670,7 +670,7 @@
 #endif
 }
 
-static struct file_operations hp_sdc_rtc_fops = {
+static const struct file_operations hp_sdc_rtc_fops = {
         .owner =	THIS_MODULE,
         .llseek =	no_llseek,
         .read =		hp_sdc_rtc_read,
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 9516439..4255623 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -627,7 +627,7 @@
 	return retval;
 }
 
-static struct file_operations uinput_fops = {
+static const struct file_operations uinput_fops = {
 	.owner		= THIS_MODULE,
 	.open		= uinput_open,
 	.release	= uinput_release,
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 7b9d1c1..e1183ae 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -335,6 +335,17 @@
 	{ KE_END,  0 },
 };
 
+static struct key_entry keymap_fs_amilo_d88x0[] = {
+	{ KE_KEY, 0x01, KEY_HELP },
+	{ KE_KEY, 0x08, KEY_MUTE },
+	{ KE_KEY, 0x31, KEY_MAIL },
+	{ KE_KEY, 0x36, KEY_WWW },
+	{ KE_KEY, 0x11, KEY_PROG1 },
+	{ KE_KEY, 0x12, KEY_PROG2 },
+	{ KE_KEY, 0x13, KEY_PROG3 },
+	{ KE_END, 0 }
+};
+
 /*
  * If your machine is not here (which is currently rather likely), please send
  * a list of buttons and their key codes (reported when loading this module
@@ -413,6 +424,15 @@
 		},
 		.driver_data = keymap_wistron_ms2111
 	},
+	{
+		.callback = dmi_matched,
+		.ident = "Fujitsu Siemens Amilo D88x0",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"),
+		},
+		.driver_data = keymap_fs_amilo_d88x0
+	},
 	{ NULL, }
 };
 
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
index 13dd967..79b624f 100644
--- a/drivers/input/mouse/inport.c
+++ b/drivers/input/mouse/inport.c
@@ -61,7 +61,7 @@
 #define INPORT_REG_MODE		0x07
 #define INPORT_RESET		0x80
 
-#ifdef CONFIG_INPUT_ATIXL
+#ifdef CONFIG_MOUSE_ATIXL
 #define INPORT_NAME		"ATI XL Mouse"
 #define INPORT_VENDOR		0x0002
 #define INPORT_SPEED_30HZ	0x01
@@ -84,8 +84,6 @@
 module_param_named(irq, inport_irq, uint, 0);
 MODULE_PARM_DESC(irq, "IRQ number (5=default)");
 
-__obsolete_setup("inport_irq=");
-
 static struct input_dev *inport_dev;
 
 static irqreturn_t inport_interrupt(int irq, void *dev_id)
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
index db20599..26c3b2e 100644
--- a/drivers/input/mouse/logibm.c
+++ b/drivers/input/mouse/logibm.c
@@ -75,8 +75,6 @@
 module_param_named(irq, logibm_irq, uint, 0);
 MODULE_PARM_DESC(irq, "IRQ number (5=default)");
 
-__obsolete_setup("logibm_irq=");
-
 static struct input_dev *logibm_dev;
 
 static irqreturn_t logibm_interrupt(int irq, void *dev_id)
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index f155c1f..05d992e 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -113,7 +113,7 @@
 	dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
 	if (dev) {
 		pci_dev_put(dev);
-		return -ENOENT;
+		return -ENODEV;
 	}
 
 	if (!request_region(pc110pad_io, 4, "pc110pad")) {
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index a0e4a03..0fe5869 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -93,12 +93,6 @@
 	.attrs	= psmouse_attributes,
 };
 
-__obsolete_setup("psmouse_noext");
-__obsolete_setup("psmouse_resolution=");
-__obsolete_setup("psmouse_smartscroll=");
-__obsolete_setup("psmouse_resetafter=");
-__obsolete_setup("psmouse_rate=");
-
 /*
  * psmouse_mutex protects all operations changing state of mouse
  * (connecting, disconnecting, changing rate or resolution via
@@ -987,8 +981,36 @@
 static void psmouse_cleanup(struct serio *serio)
 {
 	struct psmouse *psmouse = serio_get_drvdata(serio);
+	struct psmouse *parent = NULL;
+
+	mutex_lock(&psmouse_mutex);
+
+	if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+		parent = serio_get_drvdata(serio->parent);
+		psmouse_deactivate(parent);
+	}
+
+	psmouse_deactivate(psmouse);
+
+	if (psmouse->cleanup)
+		psmouse->cleanup(psmouse);
 
 	psmouse_reset(psmouse);
+
+/*
+ * Some boxes, such as HP nx7400, get terribly confused if mouse
+ * is not fully enabled before suspending/shutting down.
+ */
+	ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+
+	if (parent) {
+		if (parent->pt_deactivate)
+			parent->pt_deactivate(parent);
+
+		psmouse_activate(parent);
+	}
+
+	mutex_unlock(&psmouse_mutex);
 }
 
 /*
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 1b74cae..cf1de95 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -68,6 +68,7 @@
 
 	int (*reconnect)(struct psmouse *psmouse);
 	void (*disconnect)(struct psmouse *psmouse);
+	void (*cleanup)(struct psmouse *psmouse);
 	int (*poll)(struct psmouse *psmouse);
 
 	void (*pt_activate)(struct psmouse *psmouse);
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index fbdcfd8..355efd0 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -18,7 +18,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 49ac696..f0f9413 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -652,6 +652,7 @@
 	psmouse->set_rate = synaptics_set_rate;
 	psmouse->disconnect = synaptics_disconnect;
 	psmouse->reconnect = synaptics_reconnect;
+	psmouse->cleanup = synaptics_reset;
 	psmouse->pktsize = 6;
 	/* Synaptics can usually stay in sync without extra help */
 	psmouse->resync_time = 0;
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 49e11e2..4fa93ff 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -59,7 +59,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 
 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 9907ad3..b57370d 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -62,7 +62,6 @@
  */
 
 #include <linux/hp_sdc.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/module.h>
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index debe944..ec195a3 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -76,13 +76,6 @@
 MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off");
 #endif
 
-__obsolete_setup("i8042_noaux");
-__obsolete_setup("i8042_nomux");
-__obsolete_setup("i8042_unlock");
-__obsolete_setup("i8042_reset");
-__obsolete_setup("i8042_direct");
-__obsolete_setup("i8042_dumbkbd");
-
 #include "i8042.h"
 
 static DEFINE_SPINLOCK(i8042_lock);
@@ -371,7 +364,7 @@
 	if (unlikely(i8042_suppress_kbd_ack))
 		if (port_no == I8042_KBD_PORT_NO &&
 		    (data == 0xfa || data == 0xfe)) {
-			i8042_suppress_kbd_ack = 0;
+			i8042_suppress_kbd_ack--;
 			goto out;
 		}
 
@@ -543,6 +536,7 @@
 {
 	int retval = -1;
 	int irq_registered = 0;
+	int aux_loop_broken = 0;
 	unsigned long flags;
 	unsigned char param;
 
@@ -572,6 +566,8 @@
 		if (i8042_command(&param, I8042_CMD_AUX_TEST) ||
 		    (param && param != 0xfa && param != 0xff))
 			return -1;
+
+		aux_loop_broken = 1;
 	}
 
 /*
@@ -595,7 +591,7 @@
  * used it for a PCI card or somethig else.
  */
 
-	if (i8042_noloop) {
+	if (i8042_noloop || aux_loop_broken) {
 /*
  * Without LOOP command we can't test AUX IRQ delivery. Assume the port
  * is working and hope we are right.
@@ -721,7 +717,7 @@
 	if (~i8042_read_status() & I8042_STR_KEYLOCK) {
 		if (i8042_unlock)
 			i8042_ctr |= I8042_CTR_IGNKEYLOCK;
-		 else
+		else
 			printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
 	}
 	spin_unlock_irqrestore(&i8042_lock, flags);
@@ -788,27 +784,6 @@
 
 
 /*
- * Here we try to reset everything back to a state in which the BIOS will be
- * able to talk to the hardware when rebooting.
- */
-
-static void i8042_controller_cleanup(void)
-{
-	int i;
-
-/*
- * Reset anything that is connected to the ports.
- */
-
-	for (i = 0; i < I8042_NUM_PORTS; i++)
-		if (i8042_ports[i].serio)
-			serio_cleanup(i8042_ports[i].serio);
-
-	i8042_controller_reset();
-}
-
-
-/*
  * i8042_panic_blink() will flash the keyboard LEDs and is called when
  * kernel panics. Flashing LEDs is useful for users running X who may
  * not see the console and will help distingushing panics from "real"
@@ -838,13 +813,14 @@
 	led ^= 0x01 | 0x04;
 	while (i8042_read_status() & I8042_STR_IBF)
 		DELAY;
-	i8042_suppress_kbd_ack = 1;
+	dbg("%02x -> i8042 (panic blink)", 0xed);
+	i8042_suppress_kbd_ack = 2;
 	i8042_write_data(0xed); /* set leds */
 	DELAY;
 	while (i8042_read_status() & I8042_STR_IBF)
 		DELAY;
 	DELAY;
-	i8042_suppress_kbd_ack = 1;
+	dbg("%02x -> i8042 (panic blink)", led);
 	i8042_write_data(led);
 	DELAY;
 	last_blink = count;
@@ -853,13 +829,22 @@
 
 #undef DELAY
 
+#ifdef CONFIG_PM
 /*
- * Here we try to restore the original BIOS settings
+ * Here we try to restore the original BIOS settings. We only want to
+ * do that once, when we really suspend, not when we taking memory
+ * snapshot for swsusp (in this case we'll perform required cleanup
+ * as part of shutdown process).
  */
 
 static int i8042_suspend(struct platform_device *dev, pm_message_t state)
 {
-	i8042_controller_cleanup();
+	if (dev->dev.power.power_state.event != state.event) {
+		if (state.event == PM_EVENT_SUSPEND)
+			i8042_controller_reset();
+
+		dev->dev.power.power_state = state;
+	}
 
 	return 0;
 }
@@ -873,6 +858,12 @@
 {
 	int error;
 
+/*
+ * Do not bother with restoring state if we haven't suspened yet
+ */
+	if (dev->dev.power.power_state.event == PM_EVENT_ON)
+		return 0;
+
 	error = i8042_controller_check();
 	if (error)
 		return error;
@@ -882,9 +873,12 @@
 		return error;
 
 /*
- * Restore pre-resume CTR value and disable all ports
+ * Restore original CTR value and disable all ports
  */
 
+	i8042_ctr = i8042_initial_ctr;
+	if (i8042_direct)
+		i8042_ctr &= ~I8042_CTR_XLATE;
 	i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS;
 	i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT);
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
@@ -905,8 +899,11 @@
 
 	i8042_interrupt(0, NULL);
 
+	dev->dev.power.power_state = PMSG_ON;
+
 	return 0;
 }
+#endif /* CONFIG_PM */
 
 /*
  * We need to reset the 8042 back to original mode on system shutdown,
@@ -915,7 +912,7 @@
 
 static void i8042_shutdown(struct platform_device *dev)
 {
-	i8042_controller_cleanup();
+	i8042_controller_reset();
 }
 
 static int __devinit i8042_create_kbd_port(void)
@@ -1150,9 +1147,11 @@
 	},
 	.probe		= i8042_probe,
 	.remove		= __devexit_p(i8042_remove),
+	.shutdown	= i8042_shutdown,
+#ifdef CONFIG_PM
 	.suspend	= i8042_suspend,
 	.resume		= i8042_resume,
-	.shutdown	= i8042_shutdown,
+#endif
 };
 
 static int __init i8042_init(void)
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index b3e84d3..10d9d74 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -97,7 +97,7 @@
 
 int ps2_is_keyboard_id(char id_byte)
 {
-	const static char keyboard_ids[] = {
+	static const char keyboard_ids[] = {
 		0xab,	/* Regular keyboards		*/
 		0xac,	/* NCD Sun keyboard		*/
 		0x2b,	/* Trust keyboard, translated	*/
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 17c8c63c..a15e531 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -778,6 +778,19 @@
 	return 0;
 }
 
+static void serio_cleanup(struct serio *serio)
+{
+	if (serio->drv && serio->drv->cleanup)
+		serio->drv->cleanup(serio);
+}
+
+static void serio_shutdown(struct device *dev)
+{
+	struct serio *serio = to_serio_port(dev);
+
+	serio_cleanup(serio);
+}
+
 static void serio_attach_driver(struct serio_driver *drv)
 {
 	int error;
@@ -910,11 +923,25 @@
 
 #endif /* CONFIG_HOTPLUG */
 
+#ifdef CONFIG_PM
+static int serio_suspend(struct device *dev, pm_message_t state)
+{
+	if (dev->power.power_state.event != state.event) {
+		if (state.event == PM_EVENT_SUSPEND)
+			serio_cleanup(to_serio_port(dev));
+
+		dev->power.power_state = state;
+	}
+
+	return 0;
+}
+
 static int serio_resume(struct device *dev)
 {
 	struct serio *serio = to_serio_port(dev);
 
-	if (serio_reconnect_driver(serio)) {
+	if (dev->power.power_state.event != PM_EVENT_ON &&
+	    serio_reconnect_driver(serio)) {
 		/*
 		 * Driver re-probing can take a while, so better let kseriod
 		 * deal with it.
@@ -922,8 +949,11 @@
 		serio_rescan(serio);
 	}
 
+	dev->power.power_state = PMSG_ON;
+
 	return 0;
 }
+#endif /* CONFIG_PM */
 
 /* called from serio_driver->connect/disconnect methods under serio_mutex */
 int serio_open(struct serio *serio, struct serio_driver *drv)
@@ -974,7 +1004,11 @@
 	.uevent		= serio_uevent,
 	.probe		= serio_driver_probe,
 	.remove		= serio_driver_remove,
+	.shutdown	= serio_shutdown,
+#ifdef CONFIG_PM
+	.suspend	= serio_suspend,
 	.resume		= serio_resume,
+#endif
 };
 
 static int __init serio_init(void)
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 088ebc3..8873576 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -234,7 +234,7 @@
 	return 0;
 }
 
-static struct file_operations serio_raw_fops = {
+static const struct file_operations serio_raw_fops = {
 	.owner =	THIS_MODULE,
 	.open =		serio_raw_open,
 	.release =	serio_raw_release,
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6b46c9b..9716180 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -12,13 +12,18 @@
 if INPUT_TOUCHSCREEN
 
 config TOUCHSCREEN_ADS7846
-	tristate "ADS 7846 based touchscreens"
+	tristate "ADS 7846/7843 based touchscreens"
 	depends on SPI_MASTER
+	depends on HWMON = n || HWMON
 	help
 	  Say Y here if you have a touchscreen interface using the
-	  ADS7846 controller, and your board-specific initialization
+	  ADS7846 or ADS7843 controller, and your board-specific setup
 	  code includes that in its table of SPI devices.
 
+	  If HWMON is selected, and the driver is told the reference voltage
+	  on your board, you will also get hwmon interfaces for the voltage
+	  (and on ads7846, temperature) sensors of this chip.
+
 	  If unsure, say N (but it's safe to say "Y").
 
 	  To compile this driver as a module, choose M here: the
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index c6164b6..0a26e06 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -17,8 +17,9 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
-#include <linux/device.h>
+#include <linux/hwmon.h>
 #include <linux/init.h>
+#include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
@@ -54,7 +55,8 @@
  * files.
  */
 
-#define	TS_POLL_PERIOD	msecs_to_jiffies(10)
+#define TS_POLL_DELAY	(1 * 1000000)	/* ns delay before the first sample */
+#define TS_POLL_PERIOD	(5 * 1000000)	/* ns delay between samples */
 
 /* this driver doesn't aim at the peak continuous sample rate */
 #define	SAMPLE_BITS	(8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
@@ -63,12 +65,12 @@
 	/* For portability, we can't read 12 bit values using SPI (which
 	 * would make the controller deliver them as native byteorder u16
 	 * with msbs zeroed).  Instead, we read them as two 8-bit values,
-	 * which need byteswapping then range adjustment.
+	 * *** WHICH NEED BYTESWAPPING *** and range adjustment.
 	 */
-	__be16 x;
-	__be16 y;
-	__be16 z1, z2;
-	int    ignore;
+	u16	x;
+	u16	y;
+	u16	z1, z2;
+	int	ignore;
 };
 
 struct ads7846 {
@@ -76,7 +78,12 @@
 	char			phys[32];
 
 	struct spi_device	*spi;
+
+#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE)
 	struct attribute_group	*attr_group;
+	struct class_device	*hwmon;
+#endif
+
 	u16			model;
 	u16			vref_delay_usecs;
 	u16			x_plate_ohms;
@@ -99,13 +106,16 @@
 	u16			debounce_rep;
 
 	spinlock_t		lock;
-	struct timer_list	timer;		/* P: lock */
+	struct hrtimer		timer;
 	unsigned		pendown:1;	/* P: lock */
 	unsigned		pending:1;	/* P: lock */
 // FIXME remove "irq_disabled"
 	unsigned		irq_disabled:1;	/* P: lock */
 	unsigned		disabled:1;
 
+	int			(*filter)(void *data, int data_idx, int *val);
+	void			*filter_data;
+	void			(*filter_cleanup)(void *data);
 	int			(*get_pendown_state)(void);
 };
 
@@ -142,15 +152,16 @@
 #define	MAX_12BIT	((1<<12)-1)
 
 /* leave ADC powered up (disables penirq) between differential samples */
-#define	READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \
-	| ADS_12_BIT | ADS_DFR)
+#define	READ_12BIT_DFR(x, adc, vref) (ADS_START | ADS_A2A1A0_d_ ## x \
+	| ADS_12_BIT | ADS_DFR | \
+	(adc ? ADS_PD10_ADC_ON : 0) | (vref ? ADS_PD10_REF_ON : 0))
 
-#define	READ_Y	(READ_12BIT_DFR(y)  | ADS_PD10_ADC_ON)
-#define	READ_Z1	(READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON)
-#define	READ_Z2	(READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON)
+#define	READ_Y(vref)	(READ_12BIT_DFR(y,  1, vref))
+#define	READ_Z1(vref)	(READ_12BIT_DFR(z1, 1, vref))
+#define	READ_Z2(vref)	(READ_12BIT_DFR(z2, 1, vref))
 
-#define	READ_X	(READ_12BIT_DFR(x)  | ADS_PD10_ADC_ON)
-#define	PWRDOWN	(READ_12BIT_DFR(y)  | ADS_PD10_PDOWN)	/* LAST */
+#define	READ_X(vref)	(READ_12BIT_DFR(x,  1, vref))
+#define	PWRDOWN		(READ_12BIT_DFR(y,  0, 0))	/* LAST */
 
 /* single-ended samples need to first power up reference voltage;
  * we leave both ADC and VREF powered
@@ -158,14 +169,19 @@
 #define	READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \
 	| ADS_12_BIT | ADS_SER)
 
-#define	REF_ON	(READ_12BIT_DFR(x) | ADS_PD10_ALL_ON)
-#define	REF_OFF	(READ_12BIT_DFR(y) | ADS_PD10_PDOWN)
+#define	REF_ON	(READ_12BIT_DFR(x, 1, 1))
+#define	REF_OFF	(READ_12BIT_DFR(y, 0, 0))
 
 /*--------------------------------------------------------------------------*/
 
 /*
  * Non-touchscreen sensors only use single-ended conversions.
+ * The range is GND..vREF. The ads7843 and ads7835 must use external vREF;
+ * ads7846 lets that pin be unconnected, to use internal vREF.
  */
+static unsigned vREF_mV;
+module_param(vREF_mV, uint, 0);
+MODULE_PARM_DESC(vREF_mV, "external vREF voltage, in milliVolts");
 
 struct ser_req {
 	u8			ref_on;
@@ -193,50 +209,55 @@
 	struct ser_req		*req = kzalloc(sizeof *req, GFP_KERNEL);
 	int			status;
 	int			sample;
-	int			i;
+	int			use_internal;
 
 	if (!req)
 		return -ENOMEM;
 
 	spi_message_init(&req->msg);
 
-	/* activate reference, so it has time to settle; */
-	req->ref_on = REF_ON;
-	req->xfer[0].tx_buf = &req->ref_on;
-	req->xfer[0].len = 1;
-	req->xfer[1].rx_buf = &req->scratch;
-	req->xfer[1].len = 2;
+	/* FIXME boards with ads7846 might use external vref instead ... */
+	use_internal = (ts->model == 7846);
 
-	/*
-	 * for external VREF, 0 usec (and assume it's always on);
-	 * for 1uF, use 800 usec;
-	 * no cap, 100 usec.
-	 */
-	req->xfer[1].delay_usecs = ts->vref_delay_usecs;
+	/* maybe turn on internal vREF, and let it settle */
+	if (use_internal) {
+		req->ref_on = REF_ON;
+		req->xfer[0].tx_buf = &req->ref_on;
+		req->xfer[0].len = 1;
+		spi_message_add_tail(&req->xfer[0], &req->msg);
+
+		req->xfer[1].rx_buf = &req->scratch;
+		req->xfer[1].len = 2;
+
+		/* for 1uF, settle for 800 usec; no cap, 100 usec.  */
+		req->xfer[1].delay_usecs = ts->vref_delay_usecs;
+		spi_message_add_tail(&req->xfer[1], &req->msg);
+	}
 
 	/* take sample */
 	req->command = (u8) command;
 	req->xfer[2].tx_buf = &req->command;
 	req->xfer[2].len = 1;
+	spi_message_add_tail(&req->xfer[2], &req->msg);
+
 	req->xfer[3].rx_buf = &req->sample;
 	req->xfer[3].len = 2;
+	spi_message_add_tail(&req->xfer[3], &req->msg);
 
 	/* REVISIT:  take a few more samples, and compare ... */
 
-	/* turn off reference */
-	req->ref_off = REF_OFF;
-	req->xfer[4].tx_buf = &req->ref_off;
-	req->xfer[4].len = 1;
-	req->xfer[5].rx_buf = &req->scratch;
-	req->xfer[5].len = 2;
+	/* maybe off internal vREF */
+	if (use_internal) {
+		req->ref_off = REF_OFF;
+		req->xfer[4].tx_buf = &req->ref_off;
+		req->xfer[4].len = 1;
+		spi_message_add_tail(&req->xfer[4], &req->msg);
 
-	CS_CHANGE(req->xfer[5]);
-
-	/* group all the transfers together, so we can't interfere with
-	 * reading touchscreen state; disable penirq while sampling
-	 */
-	for (i = 0; i < 6; i++)
-		spi_message_add_tail(&req->xfer[i], &req->msg);
+		req->xfer[5].rx_buf = &req->scratch;
+		req->xfer[5].len = 2;
+		CS_CHANGE(req->xfer[5]);
+		spi_message_add_tail(&req->xfer[5], &req->msg);
+	}
 
 	ts->irq_disabled = 1;
 	disable_irq(spi->irq);
@@ -256,25 +277,173 @@
 	return status ? status : sample;
 }
 
-#define SHOW(name) static ssize_t \
+#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE)
+
+#define SHOW(name, var, adjust) static ssize_t \
 name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
+	struct ads7846 *ts = dev_get_drvdata(dev); \
 	ssize_t v = ads7846_read12_ser(dev, \
-			READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \
+			READ_12BIT_SER(var) | ADS_PD10_ALL_ON); \
 	if (v < 0) \
 		return v; \
-	return sprintf(buf, "%u\n", (unsigned) v); \
+	return sprintf(buf, "%u\n", adjust(ts, v)); \
 } \
 static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL);
 
-SHOW(temp0)
-SHOW(temp1)
-SHOW(vaux)
-SHOW(vbatt)
+
+/* Sysfs conventions report temperatures in millidegrees Celcius.
+ * ADS7846 could use the low-accuracy two-sample scheme, but can't do the high
+ * accuracy scheme without calibration data.  For now we won't try either;
+ * userspace sees raw sensor values, and must scale/calibrate appropriately.
+ */
+static inline unsigned null_adjust(struct ads7846 *ts, ssize_t v)
+{
+	return v;
+}
+
+SHOW(temp0, temp0, null_adjust)		/* temp1_input */
+SHOW(temp1, temp1, null_adjust)		/* temp2_input */
+
+
+/* sysfs conventions report voltages in millivolts.  We can convert voltages
+ * if we know vREF.  userspace may need to scale vAUX to match the board's
+ * external resistors; we assume that vBATT only uses the internal ones.
+ */
+static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v)
+{
+	unsigned retval = v;
+
+	/* external resistors may scale vAUX into 0..vREF */
+	retval *= vREF_mV;
+	retval = retval >> 12;
+	return retval;
+}
+
+static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v)
+{
+	unsigned retval = vaux_adjust(ts, v);
+
+	/* ads7846 has a resistor ladder to scale this signal down */
+	if (ts->model == 7846)
+		retval *= 4;
+	return retval;
+}
+
+SHOW(in0_input, vaux, vaux_adjust)
+SHOW(in1_input, vbatt, vbatt_adjust)
+
+
+static struct attribute *ads7846_attributes[] = {
+	&dev_attr_temp0.attr,
+	&dev_attr_temp1.attr,
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	NULL,
+};
+
+static struct attribute_group ads7846_attr_group = {
+	.attrs = ads7846_attributes,
+};
+
+static struct attribute *ads7843_attributes[] = {
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	NULL,
+};
+
+static struct attribute_group ads7843_attr_group = {
+	.attrs = ads7843_attributes,
+};
+
+static struct attribute *ads7845_attributes[] = {
+	&dev_attr_in0_input.attr,
+	NULL,
+};
+
+static struct attribute_group ads7845_attr_group = {
+	.attrs = ads7845_attributes,
+};
+
+static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
+{
+	struct class_device *hwmon;
+	int err;
+
+	/* hwmon sensors need a reference voltage */
+	switch (ts->model) {
+	case 7846:
+		if (!vREF_mV) {
+			dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n");
+			vREF_mV = 2500;
+		}
+		break;
+	case 7845:
+	case 7843:
+		if (!vREF_mV) {
+			dev_warn(&spi->dev,
+				"external vREF for ADS%d not specified\n",
+				ts->model);
+			return 0;
+		}
+		break;
+	}
+
+	/* different chips have different sensor groups */
+	switch (ts->model) {
+	case 7846:
+		ts->attr_group = &ads7846_attr_group;
+		break;
+	case 7845:
+		ts->attr_group = &ads7845_attr_group;
+		break;
+	case 7843:
+		ts->attr_group = &ads7843_attr_group;
+		break;
+	default:
+		dev_dbg(&spi->dev, "ADS%d not recognized\n", ts->model);
+		return 0;
+	}
+
+	err = sysfs_create_group(&spi->dev.kobj, ts->attr_group);
+	if (err)
+		return err;
+
+	hwmon = hwmon_device_register(&spi->dev);
+	if (IS_ERR(hwmon)) {
+		sysfs_remove_group(&spi->dev.kobj, ts->attr_group);
+		return PTR_ERR(hwmon);
+	}
+
+	ts->hwmon = hwmon;
+	return 0;
+}
+
+static void ads784x_hwmon_unregister(struct spi_device *spi,
+				     struct ads7846 *ts)
+{
+	if (ts->hwmon) {
+		sysfs_remove_group(&spi->dev.kobj, ts->attr_group);
+		hwmon_device_unregister(ts->hwmon);
+	}
+}
+
+#else
+static inline int ads784x_hwmon_register(struct spi_device *spi,
+					 struct ads7846 *ts)
+{
+	return 0;
+}
+
+static inline void ads784x_hwmon_unregister(struct spi_device *spi,
+					    struct ads7846 *ts)
+{
+}
+#endif
 
 static int is_pen_down(struct device *dev)
 {
-	struct ads7846		*ts = dev_get_drvdata(dev);
+	struct ads7846	*ts = dev_get_drvdata(dev);
 
 	return ts->pendown;
 }
@@ -318,46 +487,14 @@
 
 static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
 
-static struct attribute *ads7846_attributes[] = {
-	&dev_attr_temp0.attr,
-	&dev_attr_temp1.attr,
-	&dev_attr_vbatt.attr,
-	&dev_attr_vaux.attr,
+static struct attribute *ads784x_attributes[] = {
 	&dev_attr_pen_down.attr,
 	&dev_attr_disable.attr,
 	NULL,
 };
 
-static struct attribute_group ads7846_attr_group = {
-	.attrs = ads7846_attributes,
-};
-
-/*
- * ads7843/7845 don't have temperature sensors, and
- * use the other sensors a bit differently too
- */
-
-static struct attribute *ads7843_attributes[] = {
-	&dev_attr_vbatt.attr,
-	&dev_attr_vaux.attr,
-	&dev_attr_pen_down.attr,
-	&dev_attr_disable.attr,
-	NULL,
-};
-
-static struct attribute_group ads7843_attr_group = {
-	.attrs = ads7843_attributes,
-};
-
-static struct attribute *ads7845_attributes[] = {
-	&dev_attr_vaux.attr,
-	&dev_attr_pen_down.attr,
-	&dev_attr_disable.attr,
-	NULL,
-};
-
-static struct attribute_group ads7845_attr_group = {
-	.attrs = ads7845_attributes,
+static struct attribute_group ads784x_attr_group = {
+	.attrs = ads784x_attributes,
 };
 
 /*--------------------------------------------------------------------------*/
@@ -373,25 +510,22 @@
 static void ads7846_rx(void *ads)
 {
 	struct ads7846		*ts = ads;
-	struct input_dev	*input_dev = ts->input;
 	unsigned		Rt;
-	unsigned		sync = 0;
 	u16			x, y, z1, z2;
-	unsigned long		flags;
 
-	/* adjust:  on-wire is a must-ignore bit, a BE12 value, then padding;
-	 * built from two 8 bit values written msb-first.
+	/* ads7846_rx_val() did in-place conversion (including byteswap) from
+	 * on-the-wire format as part of debouncing to get stable readings.
 	 */
-	x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff;
-	y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff;
-	z1 = (be16_to_cpu(ts->tc.z1) >> 3) & 0x0fff;
-	z2 = (be16_to_cpu(ts->tc.z2) >> 3) & 0x0fff;
+	x = ts->tc.x;
+	y = ts->tc.y;
+	z1 = ts->tc.z1;
+	z2 = ts->tc.z2;
 
 	/* range filtering */
 	if (x == MAX_12BIT)
 		x = 0;
 
-	if (likely(x && z1 && !device_suspended(&ts->spi->dev))) {
+	if (likely(x && z1)) {
 		/* compute touch pressure resistance using equation #2 */
 		Rt = z2;
 		Rt -= z1;
@@ -403,100 +537,130 @@
 		Rt = 0;
 
 	/* Sample found inconsistent by debouncing or pressure is beyond
-	* the maximum. Don't report it to user space, repeat at least
-	* once more the measurement */
+	 * the maximum. Don't report it to user space, repeat at least
+	 * once more the measurement
+	 */
 	if (ts->tc.ignore || Rt > ts->pressure_max) {
-		mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
+#ifdef VERBOSE
+		pr_debug("%s: ignored %d pressure %d\n",
+			ts->spi->dev.bus_id, ts->tc.ignore, Rt);
+#endif
+		hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
+			      HRTIMER_MODE_REL);
 		return;
 	}
 
-	/* NOTE:  "pendown" is inferred from pressure; we don't rely on
-	 * being able to check nPENIRQ status, or "friendly" trigger modes
-	 * (both-edges is much better than just-falling or low-level).
+	/* NOTE: We can't rely on the pressure to determine the pen down
+	 * state, even this controller has a pressure sensor.  The pressure
+	 * value can fluctuate for quite a while after lifting the pen and
+	 * in some cases may not even settle at the expected value.
 	 *
-	 * REVISIT:  some boards may require reading nPENIRQ; it's
-	 * needed on 7843.  and 7845 reads pressure differently...
-	 *
-	 * REVISIT:  the touchscreen might not be connected; this code
-	 * won't notice that, even if nPENIRQ never fires ...
+	 * The only safe way to check for the pen up condition is in the
+	 * timer by reading the pen signal state (it's a GPIO _and_ IRQ).
 	 */
-	if (!ts->pendown && Rt != 0) {
-		input_report_key(input_dev, BTN_TOUCH, 1);
-		sync = 1;
-	} else if (ts->pendown && Rt == 0) {
-		input_report_key(input_dev, BTN_TOUCH, 0);
-		sync = 1;
-	}
-
 	if (Rt) {
-		input_report_abs(input_dev, ABS_X, x);
-		input_report_abs(input_dev, ABS_Y, y);
-		sync = 1;
-	}
+		struct input_dev *input = ts->input;
 
-	if (sync) {
-		input_report_abs(input_dev, ABS_PRESSURE, Rt);
-		input_sync(input_dev);
-	}
-
-#ifdef	VERBOSE
-	if (Rt || ts->pendown)
-		pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id,
-			x, y, Rt, Rt ? "" : " UP");
+		if (!ts->pendown) {
+			input_report_key(input, BTN_TOUCH, 1);
+			ts->pendown = 1;
+#ifdef VERBOSE
+			dev_dbg(&ts->spi->dev, "DOWN\n");
 #endif
+		}
+		input_report_abs(input, ABS_X, x);
+		input_report_abs(input, ABS_Y, y);
+		input_report_abs(input, ABS_PRESSURE, Rt);
 
-	spin_lock_irqsave(&ts->lock, flags);
+		input_sync(input);
+#ifdef VERBOSE
+		dev_dbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt);
+#endif
+	}
 
-	ts->pendown = (Rt != 0);
-	mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
-
-	spin_unlock_irqrestore(&ts->lock, flags);
+	hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
+			HRTIMER_MODE_REL);
 }
 
-static void ads7846_debounce(void *ads)
+static int ads7846_debounce(void *ads, int data_idx, int *val)
 {
 	struct ads7846		*ts = ads;
-	struct spi_message	*m;
-	struct spi_transfer	*t;
-	int			val;
-	int			status;
 
-	m = &ts->msg[ts->msg_idx];
-	t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
-	val = (be16_to_cpu(*(__be16 *)t->rx_buf) >> 3) & 0x0fff;
-	if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) {
+	if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) {
+		/* Start over collecting consistent readings. */
+		ts->read_rep = 0;
 		/* Repeat it, if this was the first read or the read
 		 * wasn't consistent enough. */
 		if (ts->read_cnt < ts->debounce_max) {
-			ts->last_read = val;
+			ts->last_read = *val;
 			ts->read_cnt++;
+			return ADS7846_FILTER_REPEAT;
 		} else {
 			/* Maximum number of debouncing reached and still
 			 * not enough number of consistent readings. Abort
 			 * the whole sample, repeat it in the next sampling
 			 * period.
 			 */
-			ts->tc.ignore = 1;
 			ts->read_cnt = 0;
-			/* Last message will contain ads7846_rx() as the
-			 * completion function.
-			 */
-			m = ts->last_msg;
+			return ADS7846_FILTER_IGNORE;
 		}
-		/* Start over collecting consistent readings. */
-		ts->read_rep = 0;
 	} else {
 		if (++ts->read_rep > ts->debounce_rep) {
 			/* Got a good reading for this coordinate,
 			 * go for the next one. */
-			ts->tc.ignore = 0;
-			ts->msg_idx++;
 			ts->read_cnt = 0;
 			ts->read_rep = 0;
-			m++;
-		} else
+			return ADS7846_FILTER_OK;
+		} else {
 			/* Read more values that are consistent. */
 			ts->read_cnt++;
+			return ADS7846_FILTER_REPEAT;
+		}
+	}
+}
+
+static int ads7846_no_filter(void *ads, int data_idx, int *val)
+{
+	return ADS7846_FILTER_OK;
+}
+
+static void ads7846_rx_val(void *ads)
+{
+	struct ads7846 *ts = ads;
+	struct spi_message *m;
+	struct spi_transfer *t;
+	u16 *rx_val;
+	int val;
+	int action;
+	int status;
+
+	m = &ts->msg[ts->msg_idx];
+	t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+	rx_val = t->rx_buf;
+
+	/* adjust:  on-wire is a must-ignore bit, a BE12 value, then padding;
+	 * built from two 8 bit values written msb-first.
+	 */
+	val = be16_to_cpu(*rx_val) >> 3;
+
+	action = ts->filter(ts->filter_data, ts->msg_idx, &val);
+	switch (action) {
+	case ADS7846_FILTER_REPEAT:
+		break;
+	case ADS7846_FILTER_IGNORE:
+		ts->tc.ignore = 1;
+		/* Last message will contain ads7846_rx() as the
+		 * completion function.
+		 */
+		m = ts->last_msg;
+		break;
+	case ADS7846_FILTER_OK:
+		*rx_val = val;
+		ts->tc.ignore = 0;
+		m = &ts->msg[++ts->msg_idx];
+		break;
+	default:
+		BUG();
 	}
 	status = spi_async(ts->spi, m);
 	if (status)
@@ -504,21 +668,34 @@
 				status);
 }
 
-static void ads7846_timer(unsigned long handle)
+static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
 {
-	struct ads7846	*ts = (void *)handle;
+	struct ads7846	*ts = container_of(handle, struct ads7846, timer);
 	int		status = 0;
 
 	spin_lock_irq(&ts->lock);
 
-	if (unlikely(ts->msg_idx && !ts->pendown)) {
+	if (unlikely(!ts->get_pendown_state() ||
+		     device_suspended(&ts->spi->dev))) {
+		if (ts->pendown) {
+			struct input_dev *input = ts->input;
+
+			input_report_key(input, BTN_TOUCH, 0);
+			input_report_abs(input, ABS_PRESSURE, 0);
+			input_sync(input);
+
+			ts->pendown = 0;
+#ifdef VERBOSE
+			dev_dbg(&ts->spi->dev, "UP\n");
+#endif
+		}
+
 		/* measurement cycle ended */
 		if (!device_suspended(&ts->spi->dev)) {
 			ts->irq_disabled = 0;
 			enable_irq(ts->spi->irq);
 		}
 		ts->pending = 0;
-		ts->msg_idx = 0;
 	} else {
 		/* pen is still down, continue with the measurement */
 		ts->msg_idx = 0;
@@ -528,6 +705,7 @@
 	}
 
 	spin_unlock_irq(&ts->lock);
+	return HRTIMER_NORESTART;
 }
 
 static irqreturn_t ads7846_irq(int irq, void *handle)
@@ -546,7 +724,8 @@
 			ts->irq_disabled = 1;
 			disable_irq(ts->spi->irq);
 			ts->pending = 1;
-			mod_timer(&ts->timer, jiffies);
+			hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
+					HRTIMER_MODE_REL);
 		}
 	}
 	spin_unlock_irqrestore(&ts->lock, flags);
@@ -632,6 +811,7 @@
 	struct ads7846_platform_data	*pdata = spi->dev.platform_data;
 	struct spi_message		*m;
 	struct spi_transfer		*x;
+	int				vref;
 	int				err;
 
 	if (!spi->irq) {
@@ -665,6 +845,10 @@
 	 * may not.  So we stick to very-portable 8 bit words, both RX and TX.
 	 */
 	spi->bits_per_word = 8;
+	spi->mode = SPI_MODE_1;
+	err = spi_setup(spi);
+	if (err < 0)
+		return err;
 
 	ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
 	input_dev = input_allocate_device();
@@ -679,8 +863,7 @@
 	ts->spi = spi;
 	ts->input = input_dev;
 
-	init_timer(&ts->timer);
-	ts->timer.data = (unsigned long) ts;
+	hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	ts->timer.function = ads7846_timer;
 
 	spin_lock_init(&ts->lock);
@@ -689,14 +872,25 @@
 	ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
 	ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
 	ts->pressure_max = pdata->pressure_max ? : ~0;
-	if (pdata->debounce_max) {
+
+	if (pdata->filter != NULL) {
+		if (pdata->filter_init != NULL) {
+			err = pdata->filter_init(pdata, &ts->filter_data);
+			if (err < 0)
+				goto err_free_mem;
+		}
+		ts->filter = pdata->filter;
+		ts->filter_cleanup = pdata->filter_cleanup;
+	} else if (pdata->debounce_max) {
 		ts->debounce_max = pdata->debounce_max;
+		if (ts->debounce_max < 2)
+			ts->debounce_max = 2;
 		ts->debounce_tol = pdata->debounce_tol;
 		ts->debounce_rep = pdata->debounce_rep;
-		if (ts->debounce_rep > ts->debounce_max + 1)
-			ts->debounce_rep = ts->debounce_max - 1;
+		ts->filter = ads7846_debounce;
+		ts->filter_data = ts;
 	} else
-		ts->debounce_tol = ~0;
+		ts->filter = ads7846_no_filter;
 	ts->get_pendown_state = pdata->get_pendown_state;
 
 	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);
@@ -718,6 +912,8 @@
 	input_set_abs_params(input_dev, ABS_PRESSURE,
 			pdata->pressure_min, pdata->pressure_max, 0, 0);
 
+	vref = pdata->keep_vref_on;
+
 	/* set up the transfers to read touchscreen state; this assumes we
 	 * use formula #2 for pressure, not #3.
 	 */
@@ -727,7 +923,7 @@
 	spi_message_init(m);
 
 	/* y- still on; turn on only y+ (and ADC) */
-	ts->read_y = READ_Y;
+	ts->read_y = READ_Y(vref);
 	x->tx_buf = &ts->read_y;
 	x->len = 1;
 	spi_message_add_tail(x, m);
@@ -737,7 +933,7 @@
 	x->len = 2;
 	spi_message_add_tail(x, m);
 
-	m->complete = ads7846_debounce;
+	m->complete = ads7846_rx_val;
 	m->context = ts;
 
 	m++;
@@ -745,7 +941,7 @@
 
 	/* turn y- off, x+ on, then leave in lowpower */
 	x++;
-	ts->read_x = READ_X;
+	ts->read_x = READ_X(vref);
 	x->tx_buf = &ts->read_x;
 	x->len = 1;
 	spi_message_add_tail(x, m);
@@ -755,7 +951,7 @@
 	x->len = 2;
 	spi_message_add_tail(x, m);
 
-	m->complete = ads7846_debounce;
+	m->complete = ads7846_rx_val;
 	m->context = ts;
 
 	/* turn y+ off, x- on; we'll use formula #2 */
@@ -764,7 +960,7 @@
 		spi_message_init(m);
 
 		x++;
-		ts->read_z1 = READ_Z1;
+		ts->read_z1 = READ_Z1(vref);
 		x->tx_buf = &ts->read_z1;
 		x->len = 1;
 		spi_message_add_tail(x, m);
@@ -774,14 +970,14 @@
 		x->len = 2;
 		spi_message_add_tail(x, m);
 
-		m->complete = ads7846_debounce;
+		m->complete = ads7846_rx_val;
 		m->context = ts;
 
 		m++;
 		spi_message_init(m);
 
 		x++;
-		ts->read_z2 = READ_Z2;
+		ts->read_z2 = READ_Z2(vref);
 		x->tx_buf = &ts->read_z2;
 		x->len = 1;
 		spi_message_add_tail(x, m);
@@ -791,7 +987,7 @@
 		x->len = 2;
 		spi_message_add_tail(x, m);
 
-		m->complete = ads7846_debounce;
+		m->complete = ads7846_rx_val;
 		m->context = ts;
 	}
 
@@ -820,31 +1016,24 @@
 			spi->dev.driver->name, ts)) {
 		dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
 		err = -EBUSY;
-		goto err_free_mem;
+		goto err_cleanup_filter;
 	}
 
+	err = ads784x_hwmon_register(spi, ts);
+	if (err)
+		goto err_free_irq;
+
 	dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
 
-	/* take a first sample, leaving nPENIRQ active; avoid
+	/* take a first sample, leaving nPENIRQ active and vREF off; avoid
 	 * the touchscreen, in case it's not connected.
 	 */
 	(void) ads7846_read12_ser(&spi->dev,
 			  READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
 
-	switch (ts->model) {
-	case 7846:
-		ts->attr_group = &ads7846_attr_group;
-		break;
-	case 7845:
-		ts->attr_group = &ads7845_attr_group;
-		break;
-	default:
-		ts->attr_group = &ads7843_attr_group;
-		break;
-	}
-	err = sysfs_create_group(&spi->dev.kobj, ts->attr_group);
+	err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group);
 	if (err)
-		goto err_free_irq;
+		goto err_remove_hwmon;
 
 	err = input_register_device(input_dev);
 	if (err)
@@ -853,9 +1042,14 @@
 	return 0;
 
  err_remove_attr_group:
-	sysfs_remove_group(&spi->dev.kobj, ts->attr_group);
+	sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group);
+ err_remove_hwmon:
+	ads784x_hwmon_unregister(spi, ts);
  err_free_irq:
 	free_irq(spi->irq, ts);
+ err_cleanup_filter:
+	if (ts->filter_cleanup)
+		ts->filter_cleanup(ts->filter_data);
  err_free_mem:
 	input_free_device(input_dev);
 	kfree(ts);
@@ -866,16 +1060,20 @@
 {
 	struct ads7846		*ts = dev_get_drvdata(&spi->dev);
 
+	ads784x_hwmon_unregister(spi, ts);
 	input_unregister_device(ts->input);
 
 	ads7846_suspend(spi, PMSG_SUSPEND);
 
-	sysfs_remove_group(&spi->dev.kobj, ts->attr_group);
+	sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group);
 
 	free_irq(ts->spi->irq, ts);
 	/* suspend left the IRQ disabled */
 	enable_irq(ts->spi->irq);
 
+	if (ts->filter_cleanup)
+		ts->filter_cleanup(ts->filter_data);
+
 	kfree(ts);
 
 	dev_dbg(&spi->dev, "unregistered touchscreen\n");
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index 4358a0a..c7db4032 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -83,7 +83,7 @@
 
 
 struct ucb1400 {
-	ac97_t			*ac97;
+	struct snd_ac97		*ac97;
 	struct input_dev	*ts_idev;
 
 	int			irq;
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index a730c46..0300dca 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -151,6 +151,10 @@
 	int i = iminor(inode) - TSDEV_MINOR_BASE;
 	struct tsdev_list *list;
 
+	printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled "
+		"for removal.\nSee Documentation/feature-removal-schedule.txt "
+		"for details.\n");
+
 	if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
 		return -ENODEV;
 
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index d22c022..db1260f 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -118,6 +118,15 @@
 };
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 
+/* FIXME: The following lock is a sledgehammer-workaround to a
+ * locking issue with the capiminor (and maybe other) data structure(s).
+ * Access to this data is done in a racy way and crashes the machine with
+ * a FritzCard DSL driver; sooner or later. This is a workaround
+ * which trades scalability vs stability, so it doesn't crash the kernel anymore.
+ * The correct (and scalable) fix for the issue seems to require
+ * an API change to the drivers... . */
+static DEFINE_SPINLOCK(workaround_lock);
+
 struct capincci {
 	struct capincci *next;
 	u32		 ncci;
@@ -589,6 +598,7 @@
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 	struct capincci *np;
 	u32 ncci;
+	unsigned long flags;
 
 	if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {
 		u16 info = CAPIMSG_U16(skb->data, 12); // Info field
@@ -603,9 +613,11 @@
 		capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
 		up(&cdev->ncci_list_sem);
 	}
+	spin_lock_irqsave(&workaround_lock, flags);
 	if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) {
 		skb_queue_tail(&cdev->recvqueue, skb);
 		wake_up_interruptible(&cdev->recvwait);
+		spin_unlock_irqrestore(&workaround_lock, flags);
 		return;
 	}
 	ncci = CAPIMSG_CONTROL(skb->data);
@@ -615,6 +627,7 @@
 		printk(KERN_ERR "BUG: capi_signal: ncci not found\n");
 		skb_queue_tail(&cdev->recvqueue, skb);
 		wake_up_interruptible(&cdev->recvwait);
+		spin_unlock_irqrestore(&workaround_lock, flags);
 		return;
 	}
 #ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -625,6 +638,7 @@
 	if (!mp) {
 		skb_queue_tail(&cdev->recvqueue, skb);
 		wake_up_interruptible(&cdev->recvwait);
+		spin_unlock_irqrestore(&workaround_lock, flags);
 		return;
 	}
 
@@ -660,6 +674,7 @@
 		wake_up_interruptible(&cdev->recvwait);
 	}
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+	spin_unlock_irqrestore(&workaround_lock, flags);
 }
 
 /* -------- file_operations for capidev ----------------------------- */
@@ -988,7 +1003,7 @@
 	return 0;
 }
 
-static struct file_operations capi_fops =
+static const struct file_operations capi_fops =
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
@@ -1006,6 +1021,7 @@
 static int capinc_tty_open(struct tty_struct * tty, struct file * file)
 {
 	struct capiminor *mp;
+	unsigned long flags;
 
 	if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == 0)
 		return -ENXIO;
@@ -1014,6 +1030,7 @@
 
 	tty->driver_data = (void *)mp;
 
+	spin_lock_irqsave(&workaround_lock, flags);
 	if (atomic_read(&mp->ttyopencount) == 0)
 		mp->tty = tty;
 	atomic_inc(&mp->ttyopencount);
@@ -1021,6 +1038,7 @@
 	printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount));
 #endif
 	handle_minor_recv(mp);
+	spin_unlock_irqrestore(&workaround_lock, flags);
 	return 0;
 }
 
@@ -1054,6 +1072,7 @@
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
+	unsigned long flags;
 
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count);
@@ -1066,6 +1085,7 @@
 		return 0;
 	}
 
+	spin_lock_irqsave(&workaround_lock, flags);
 	skb = mp->ttyskb;
 	if (skb) {
 		mp->ttyskb = NULL;
@@ -1076,6 +1096,7 @@
 	skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC);
 	if (!skb) {
 		printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n");
+		spin_unlock_irqrestore(&workaround_lock, flags);
 		return -ENOMEM;
 	}
 
@@ -1086,6 +1107,7 @@
 	mp->outbytes += skb->len;
 	(void)handle_minor_send(mp);
 	(void)handle_minor_recv(mp);
+	spin_unlock_irqrestore(&workaround_lock, flags);
 	return count;
 }
 
@@ -1093,6 +1115,7 @@
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
+	unsigned long flags;
 
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_put_char(%u)\n", ch);
@@ -1105,10 +1128,12 @@
 		return;
 	}
 
+	spin_lock_irqsave(&workaround_lock, flags);
 	skb = mp->ttyskb;
 	if (skb) {
 		if (skb_tailroom(skb) > 0) {
 			*(skb_put(skb, 1)) = ch;
+			spin_unlock_irqrestore(&workaround_lock, flags);
 			return;
 		}
 		mp->ttyskb = NULL;
@@ -1124,12 +1149,14 @@
 	} else {
 		printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);
 	}
+	spin_unlock_irqrestore(&workaround_lock, flags);
 }
 
 static void capinc_tty_flush_chars(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
+	unsigned long flags;
 
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_flush_chars\n");
@@ -1142,6 +1169,7 @@
 		return;
 	}
 
+	spin_lock_irqsave(&workaround_lock, flags);
 	skb = mp->ttyskb;
 	if (skb) {
 		mp->ttyskb = NULL;
@@ -1150,6 +1178,7 @@
 		(void)handle_minor_send(mp);
 	}
 	(void)handle_minor_recv(mp);
+	spin_unlock_irqrestore(&workaround_lock, flags);
 }
 
 static int capinc_tty_write_room(struct tty_struct *tty)
@@ -1220,12 +1249,15 @@
 static void capinc_tty_unthrottle(struct tty_struct * tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
+	unsigned long flags;
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_unthrottle\n");
 #endif
 	if (mp) {
+		spin_lock_irqsave(&workaround_lock, flags);
 		mp->ttyinstop = 0;
 		handle_minor_recv(mp);
+		spin_unlock_irqrestore(&workaround_lock, flags);
 	}
 }
 
@@ -1243,12 +1275,15 @@
 static void capinc_tty_start(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
+	unsigned long flags;
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_start\n");
 #endif
 	if (mp) {
+		spin_lock_irqsave(&workaround_lock, flags);
 		mp->ttyoutstop = 0;
 		(void)handle_minor_send(mp);
+		spin_unlock_irqrestore(&workaround_lock, flags);
 	}
 }
 
@@ -1456,7 +1491,7 @@
 
 static void __init proc_init(void)
 {
-    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int nelem = ARRAY_SIZE(procfsentries);
     int i;
 
     for (i=0; i < nelem; i++) {
@@ -1468,7 +1503,7 @@
 
 static void __exit proc_exit(void)
 {
-    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int nelem = ARRAY_SIZE(procfsentries);
     int i;
 
     for (i=nelem-1; i >= 0; i--) {
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index c4d438c..2a49cea 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -13,7 +13,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/fs.h>
@@ -2218,7 +2217,7 @@
 
 static void __init proc_init(void)
 {
-    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int nelem = ARRAY_SIZE(procfsentries);
     int i;
 
     for (i=0; i < nelem; i++) {
@@ -2230,7 +2229,7 @@
 
 static void __exit proc_exit(void)
 {
-    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int nelem = ARRAY_SIZE(procfsentries);
     int i;
 
     for (i=nelem-1; i >= 0; i--) {
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index ca9dc00..31f4fd8 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -113,14 +113,14 @@
 	return seq_open(file, &seq_contrstats_ops);
 }
 
-static struct file_operations proc_controller_ops = {
+static const struct file_operations proc_controller_ops = {
 	.open		= seq_controller_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
 	.release	= seq_release,
 };
 
-static struct file_operations proc_contrstats_ops = {
+static const struct file_operations proc_contrstats_ops = {
 	.open		= seq_contrstats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -218,14 +218,14 @@
 	return seq_open(file, &seq_applstats_ops);
 }
 
-static struct file_operations proc_applications_ops = {
+static const struct file_operations proc_applications_ops = {
 	.open		= seq_applications_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
 	.release	= seq_release,
 };
 
-static struct file_operations proc_applstats_ops = {
+static const struct file_operations proc_applstats_ops = {
 	.open		= seq_applstats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -302,7 +302,7 @@
 	return err;
 }
 
-static struct file_operations proc_driver_ops = {
+static const struct file_operations proc_driver_ops = {
 	.open		= seq_capi_driver_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 06967da..53a1890 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -256,7 +256,7 @@
 
 
 #ifdef CONFIG_PROC_FS
-static struct file_operations isdn_fops =
+static const struct file_operations isdn_fops =
 {
 	.owner          = THIS_MODULE,
 	.llseek         = no_llseek,
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig
index 708d47a..bcbb650 100644
--- a/drivers/isdn/gigaset/Kconfig
+++ b/drivers/isdn/gigaset/Kconfig
@@ -7,7 +7,13 @@
 	select CRC_CCITT
 	select BITREVERSE
 	help
-	  Say m here if you have a Gigaset or Sinus isdn device.
+	  This driver supports the Siemens Gigaset SX205/255 family of
+	  ISDN DECT bases, including the predecessors Gigaset 3070/3075
+	  and 4170/4175 and their T-Com versions Sinus 45isdn and Sinus
+	  721X.
+	  If you have one of these devices, say M here and for at least
+	  one of the connection specific parts that follow.
+	  This will build a module called "gigaset".
 
 if ISDN_DRV_GIGASET!=n
 
@@ -15,14 +21,25 @@
 	tristate "Gigaset base station support"
 	depends on ISDN_DRV_GIGASET && USB
 	help
-	  Say m here if you need to communicate with the base
-	  directly via USB.
+	  Say M here if you want to use the USB interface of the Gigaset
+	  base for connection to your system.
+	  This will build a module called "bas_gigaset".
 
 config GIGASET_M105
 	tristate "Gigaset M105 support"
 	depends on ISDN_DRV_GIGASET && USB
 	help
-	  Say m here if you need the driver for the Gigaset M105 device.
+	  Say M here if you want to connect to the Gigaset base via DECT
+	  using a Gigaset M105 (Sinus 45 Data 2) USB DECT device.
+	  This will build a module called "usb_gigaset".
+
+config GIGASET_M101
+	tristate "Gigaset M101 support"
+	depends on ISDN_DRV_GIGASET
+	help
+	  Say M here if you want to connect to the Gigaset base via DECT
+	  using a Gigaset M101 (Sinus 45 Data 1) RS232 DECT device.
+	  This will build a module called "ser_gigaset".
 
 config GIGASET_DEBUG
 	bool "Gigaset debugging"
diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile
index 9b9acf1..5158be0 100644
--- a/drivers/isdn/gigaset/Makefile
+++ b/drivers/isdn/gigaset/Makefile
@@ -1,6 +1,8 @@
-gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o
-usb_gigaset-y := usb-gigaset.o asyncdata.o
+gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o asyncdata.o
+usb_gigaset-y := usb-gigaset.o
 bas_gigaset-y := bas-gigaset.o isocdata.o
+ser_gigaset-y := ser-gigaset.o
 
 obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o gigaset.o
 obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o gigaset.o
+obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o gigaset.o
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 88e958f..f2f108f 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -13,6 +13,11 @@
  * =====================================================================
  */
 
+/* not set by Kbuild when building both ser_gigaset and usb_gigaset */
+#ifndef KBUILD_MODNAME
+#define KBUILD_MODNAME "asy_gigaset"
+#endif
+
 #include "gigaset.h"
 #include <linux/crc-ccitt.h>
 #include <linux/bitrev.h>
@@ -439,6 +444,7 @@
 		atomic_set(&inbuf->head, head);
 	}
 }
+EXPORT_SYMBOL_GPL(gigaset_m10x_input);
 
 
 /* == data output ========================================================== */
@@ -586,3 +592,4 @@
 
 	return len;	/* ok so far */
 }
+EXPORT_SYMBOL_GPL(gigaset_m10x_send_skb);
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index b5e7f9c..63e51dd 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -257,10 +257,10 @@
 			urb->transfer_flags);
 		gig_dbg(level,
 			"  transfer_buffer=0x%08lx[%d], actual_length=%d, "
-			"bandwidth=%d, setup_packet=0x%08lx,",
+			"setup_packet=0x%08lx,",
 			(unsigned long) urb->transfer_buffer,
 			urb->transfer_buffer_length, urb->actual_length,
-			urb->bandwidth, (unsigned long) urb->setup_packet);
+			(unsigned long) urb->setup_packet);
 		gig_dbg(level,
 			"  start_frame=%d, number_of_packets=%d, interval=%d, "
 			"error_count=%d,",
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 4f75cce..b460a73 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -640,7 +640,6 @@
 		return NULL;
 	}
 	mutex_init(&cs->mutex);
-	mutex_lock(&cs->mutex);
 
 	gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
 	cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
@@ -738,6 +737,7 @@
 
 	++cs->cs_init;
 
+	/* set up character device */
 	gigaset_if_init(cs);
 
 	/* set up device sysfs */
@@ -753,11 +753,9 @@
 	add_timer(&cs->timer);
 
 	gig_dbg(DEBUG_INIT, "cs initialized");
-	mutex_unlock(&cs->mutex);
 	return cs;
 
 error:
-	mutex_unlock(&cs->mutex);
 	gig_dbg(DEBUG_INIT, "failed");
 	gigaset_freecs(cs);
 	return NULL;
@@ -908,20 +906,7 @@
 	gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN");
 	gigaset_schedule_event(cs);
 
-	if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
-		warn("%s: aborted", __func__);
-		//FIXME
-	}
-
-	if (atomic_read(&cs->mstate) != MS_LOCKED) {
-		//FIXME?
-		//gigaset_baud_rate(cs, B115200);
-		//gigaset_set_line_ctrl(cs, CS8);
-		//gigaset_set_modem_ctrl(cs, TIOCM_DTR|TIOCM_RTS, 0);
-		//cs->control_state = 0;
-	} else {
-		//FIXME use some saved values?
-	}
+	wait_event(cs->waitqueue, !cs->waiting);
 
 	cleanup_cs(cs);
 
@@ -944,10 +929,7 @@
 	gig_dbg(DEBUG_CMD, "scheduling STOP");
 	gigaset_schedule_event(cs);
 
-	if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
-		warn("%s: aborted", __func__);
-		//FIXME
-	}
+	wait_event(cs->waitqueue, !cs->waiting);
 
 	cleanup_cs(cs);
 
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 44f02db..4661e2c 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -1015,7 +1015,7 @@
 
 	cs->cmd_result = -ENODEV;
 	cs->waiting = 0;
-	wake_up_interruptible(&cs->waitqueue);
+	wake_up(&cs->waitqueue);
 }
 
 static void do_shutdown(struct cardstate *cs)
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index 458b646..eb50f3d 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -599,19 +599,9 @@
 static void if_wake(unsigned long data)
 {
 	struct cardstate *cs = (struct cardstate *) data;
-	struct tty_struct *tty;
 
-	tty = cs->tty;
-	if (!tty)
-		return;
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup) {
-		gig_dbg(DEBUG_IF, "write wakeup call");
-		tty->ldisc.write_wakeup(tty);
-	}
-
-	wake_up_interruptible(&tty->write_wait);
+	if (cs->tty)
+		tty_wakeup(cs->tty);
 }
 
 /*** interface to common ***/
@@ -625,6 +615,8 @@
 		return;
 
 	tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs);
+
+	mutex_lock(&cs->mutex);
 	cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
 
 	if (!IS_ERR(cs->tty_dev))
@@ -633,6 +625,7 @@
 		warn("could not register device to the tty subsystem");
 		cs->tty_dev = NULL;
 	}
+	mutex_unlock(&cs->mutex);
 }
 
 void gigaset_if_free(struct cardstate *cs)
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index df988eb..8c0eb52 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -921,6 +921,8 @@
 			/* end of line */
 			gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
 				__func__, cbytes);
+			if (cbytes >= MAX_RESP_SIZE - 1)
+				dev_warn(cs->dev, "response too large\n");
 			cs->cbytes = cbytes;
 			gigaset_handle_modem_response(cs);
 			cbytes = 0;
@@ -929,8 +931,6 @@
 			/* advance in line buffer, checking for overflow */
 			if (cbytes < MAX_RESP_SIZE - 1)
 				cbytes++;
-			else
-				dev_warn(cs->dev, "response too large\n");
 		}
 	}
 
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
new file mode 100644
index 0000000..c8b7db6
--- /dev/null
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -0,0 +1,837 @@
+/* This is the serial hardware link layer (HLL) for the Gigaset 307x isdn
+ * DECT base (aka Sinus 45 isdn) using the RS232 DECT data module M101,
+ * written as a line discipline.
+ *
+ * =====================================================================
+ * 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 "gigaset.h"
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/poll.h>
+
+/* Version Information */
+#define DRIVER_AUTHOR "Tilman Schmidt"
+#define DRIVER_DESC "Serial Driver for Gigaset 307x using Siemens M101"
+
+#define GIGASET_MINORS     1
+#define GIGASET_MINOR      0
+#define GIGASET_MODULENAME "ser_gigaset"
+#define GIGASET_DEVNAME    "ttyGS"
+
+/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
+#define IF_WRITEBUF 264
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_LDISC(N_GIGASET_M101);
+
+static int startmode = SM_ISDN;
+module_param(startmode, int, S_IRUGO);
+MODULE_PARM_DESC(startmode, "initial operation mode");
+static int cidmode = 1;
+module_param(cidmode, int, S_IRUGO);
+MODULE_PARM_DESC(cidmode, "stay in CID mode when idle");
+
+static struct gigaset_driver *driver;
+
+struct ser_cardstate {
+	struct platform_device	dev;
+	struct tty_struct	*tty;
+	atomic_t		refcnt;
+	struct mutex		dead_mutex;
+};
+
+static struct platform_driver device_driver = {
+	.driver = {
+		.name = GIGASET_MODULENAME,
+	},
+};
+
+static void flush_send_queue(struct cardstate *);
+
+/* transmit data from current open skb
+ * result: number of bytes sent or error code < 0
+ */
+static int write_modem(struct cardstate *cs)
+{
+	struct tty_struct *tty = cs->hw.ser->tty;
+	struct bc_state *bcs = &cs->bcs[0];	/* only one channel */
+	struct sk_buff *skb = bcs->tx_skb;
+	int sent;
+
+	if (!tty || !tty->driver || !skb)
+		return -EFAULT;
+
+	if (!skb->len) {
+		dev_kfree_skb_any(skb);
+		bcs->tx_skb = NULL;
+		return -EINVAL;
+	}
+
+	set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+	sent = tty->driver->write(tty, skb->data, skb->len);
+	gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent);
+	if (sent < 0) {
+		/* error */
+		flush_send_queue(cs);
+		return sent;
+	}
+	skb_pull(skb, sent);
+	if (!skb->len) {
+		/* skb sent completely */
+		gigaset_skb_sent(bcs, skb);
+
+		gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
+			(unsigned long) skb);
+		dev_kfree_skb_any(skb);
+		bcs->tx_skb = NULL;
+	}
+	return sent;
+}
+
+/*
+ * transmit first queued command buffer
+ * result: number of bytes sent or error code < 0
+ */
+static int send_cb(struct cardstate *cs)
+{
+	struct tty_struct *tty = cs->hw.ser->tty;
+	struct cmdbuf_t *cb, *tcb;
+	unsigned long flags;
+	int sent = 0;
+
+	if (!tty || !tty->driver)
+		return -EFAULT;
+
+	cb = cs->cmdbuf;
+	if (!cb)
+		return 0;	/* nothing to do */
+
+	if (cb->len) {
+		set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+		sent = tty->driver->write(tty, cb->buf + cb->offset, cb->len);
+		if (sent < 0) {
+			/* error */
+			gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent);
+			flush_send_queue(cs);
+			return sent;
+		}
+		cb->offset += sent;
+		cb->len -= sent;
+		gig_dbg(DEBUG_OUTPUT, "send_cb: sent %d, left %u, queued %u",
+			sent, cb->len, cs->cmdbytes);
+	}
+
+	while (cb && !cb->len) {
+		spin_lock_irqsave(&cs->cmdlock, flags);
+		cs->cmdbytes -= cs->curlen;
+		tcb = cb;
+		cs->cmdbuf = cb = cb->next;
+		if (cb) {
+			cb->prev = NULL;
+			cs->curlen = cb->len;
+		} else {
+			cs->lastcmdbuf = NULL;
+			cs->curlen = 0;
+		}
+		spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+		if (tcb->wake_tasklet)
+			tasklet_schedule(tcb->wake_tasklet);
+		kfree(tcb);
+	}
+	return sent;
+}
+
+/*
+ * send queue tasklet
+ * 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.
+ */
+static void gigaset_modem_fill(unsigned long data)
+{
+	struct cardstate *cs = (struct cardstate *) data;
+	struct bc_state *bcs;
+	int sent = 0;
+
+	if (!cs || !(bcs = cs->bcs)) {
+		gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__);
+		return;
+	}
+	if (!bcs->tx_skb) {
+		/* no skb is being sent; send command if any */
+		sent = send_cb(cs);
+		gig_dbg(DEBUG_OUTPUT, "%s: send_cb -> %d", __func__, sent);
+		if (sent)
+			/* something sent or error */
+			return;
+
+		/* no command to send; get skb */
+		if (!(bcs->tx_skb = skb_dequeue(&bcs->squeue)))
+			/* no skb either, nothing to do */
+			return;
+
+		gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)",
+			(unsigned long) bcs->tx_skb);
+	}
+
+	/* send skb */
+	gig_dbg(DEBUG_OUTPUT, "%s: tx_skb", __func__);
+	if (write_modem(cs) < 0)
+		gig_dbg(DEBUG_OUTPUT, "%s: write_modem failed", __func__);
+}
+
+/*
+ * throw away all data queued for sending
+ */
+static void flush_send_queue(struct cardstate *cs)
+{
+	struct sk_buff *skb;
+	struct cmdbuf_t *cb;
+	unsigned long flags;
+
+	/* command queue */
+	spin_lock_irqsave(&cs->cmdlock, flags);
+	while ((cb = cs->cmdbuf) != NULL) {
+		cs->cmdbuf = cb->next;
+		if (cb->wake_tasklet)
+			tasklet_schedule(cb->wake_tasklet);
+		kfree(cb);
+	}
+	cs->cmdbuf = cs->lastcmdbuf = NULL;
+	cs->cmdbytes = cs->curlen = 0;
+	spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+	/* data queue */
+	if (cs->bcs->tx_skb)
+		dev_kfree_skb_any(cs->bcs->tx_skb);
+	while ((skb = skb_dequeue(&cs->bcs->squeue)) != NULL)
+		dev_kfree_skb_any(skb);
+}
+
+
+/* Gigaset Driver Interface */
+/* ======================== */
+
+/*
+ * queue an AT command string for transmission to the Gigaset device
+ * parameters:
+ *	cs		controller state structure
+ *	buf		buffer containing the string to send
+ *	len		number of characters to send
+ *	wake_tasklet	tasklet to run when transmission is complete, or NULL
+ * return value:
+ *	number of bytes queued, or error code < 0
+ */
+static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
+                             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);
+
+	if (len <= 0)
+		return 0;
+
+	if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
+		dev_err(cs->dev, "%s: out of memory!\n", __func__);
+		return -ENOMEM;
+	}
+
+	memcpy(cb->buf, buf, len);
+	cb->len = len;
+	cb->offset = 0;
+	cb->next = NULL;
+	cb->wake_tasklet = wake_tasklet;
+
+	spin_lock_irqsave(&cs->cmdlock, flags);
+	cb->prev = cs->lastcmdbuf;
+	if (cs->lastcmdbuf)
+		cs->lastcmdbuf->next = cb;
+	else {
+		cs->cmdbuf = cb;
+		cs->curlen = len;
+	}
+	cs->cmdbytes += len;
+	cs->lastcmdbuf = cb;
+	spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+	spin_lock_irqsave(&cs->lock, flags);
+	if (cs->connected)
+		tasklet_schedule(&cs->write_tasklet);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return len;
+}
+
+/*
+ * tty_driver.write_room interface routine
+ * return number of characters the driver will accept to be written
+ * parameter:
+ *	controller state structure
+ * return value:
+ *	number of characters
+ */
+static int gigaset_write_room(struct cardstate *cs)
+{
+	unsigned bytes;
+
+	bytes = cs->cmdbytes;
+	return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0;
+}
+
+/*
+ * tty_driver.chars_in_buffer interface routine
+ * return number of characters waiting to be sent
+ * parameter:
+ *	controller state structure
+ * return value:
+ *	number of characters
+ */
+static int gigaset_chars_in_buffer(struct cardstate *cs)
+{
+	return cs->cmdbytes;
+}
+
+/*
+ * implementation of ioctl(GIGASET_BRKCHARS)
+ * parameter:
+ *	controller state structure
+ * return value:
+ *	-EINVAL (unimplemented function)
+ */
+static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
+{
+	/* not implemented */
+	return -EINVAL;
+}
+
+/*
+ * Open B channel
+ * Called by "do_action" in ev-layer.c
+ */
+static int gigaset_init_bchannel(struct bc_state *bcs)
+{
+	/* nothing to do for M10x */
+	gigaset_bchannel_up(bcs);
+	return 0;
+}
+
+/*
+ * Close B channel
+ * Called by "do_action" in ev-layer.c
+ */
+static int gigaset_close_bchannel(struct bc_state *bcs)
+{
+	/* nothing to do for M10x */
+	gigaset_bchannel_down(bcs);
+	return 0;
+}
+
+/*
+ * Set up B channel structure
+ * This is called by "gigaset_initcs" in common.c
+ */
+static int gigaset_initbcshw(struct bc_state *bcs)
+{
+	/* unused */
+	bcs->hw.ser = NULL;
+	return 1;
+}
+
+/*
+ * Free B channel structure
+ * Called by "gigaset_freebcs" in common.c
+ */
+static int gigaset_freebcshw(struct bc_state *bcs)
+{
+	/* unused */
+	return 1;
+}
+
+/*
+ * Reinitialize B channel structure
+ * This is called by "bcs_reinit" in common.c
+ */
+static void gigaset_reinitbcshw(struct bc_state *bcs)
+{
+	/* nothing to do for M10x */
+}
+
+/*
+ * Free hardware specific device data
+ * This will be called by "gigaset_freecs" in common.c
+ */
+static void gigaset_freecshw(struct cardstate *cs)
+{
+	tasklet_kill(&cs->write_tasklet);
+	if (!cs->hw.ser)
+		return;
+	dev_set_drvdata(&cs->hw.ser->dev.dev, NULL);
+	platform_device_unregister(&cs->hw.ser->dev);
+	kfree(cs->hw.ser);
+	cs->hw.ser = NULL;
+}
+
+static void gigaset_device_release(struct device *dev)
+{
+	struct platform_device *pdev =
+		container_of(dev, struct platform_device, dev);
+
+	/* adapted from platform_device_release() in drivers/base/platform.c */
+	//FIXME is this actually necessary?
+	kfree(dev->platform_data);
+	kfree(pdev->resource);
+}
+
+/*
+ * Set up hardware specific device data
+ * This is called by "gigaset_initcs" in common.c
+ */
+static int gigaset_initcshw(struct cardstate *cs)
+{
+	int rc;
+
+	if (!(cs->hw.ser = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL))) {
+		err("%s: out of memory!", __func__);
+		return 0;
+	}
+
+	cs->hw.ser->dev.name = GIGASET_MODULENAME;
+	cs->hw.ser->dev.id = cs->minor_index;
+	cs->hw.ser->dev.dev.release = gigaset_device_release;
+	if ((rc = platform_device_register(&cs->hw.ser->dev)) != 0) {
+		err("error %d registering platform device", rc);
+		kfree(cs->hw.ser);
+		cs->hw.ser = NULL;
+		return 0;
+	}
+	dev_set_drvdata(&cs->hw.ser->dev.dev, cs);
+
+	tasklet_init(&cs->write_tasklet,
+	             &gigaset_modem_fill, (unsigned long) cs);
+	return 1;
+}
+
+/*
+ * set modem control lines
+ * Parameters:
+ *	card state structure
+ *	modem control line state ([TIOCM_DTR]|[TIOCM_RTS])
+ * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c
+ * and by "if_lock" and "if_termios" in interface.c
+ */
+static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsigned new_state)
+{
+	struct tty_struct *tty = cs->hw.ser->tty;
+	unsigned int set, clear;
+
+	if (!tty || !tty->driver || !tty->driver->tiocmset)
+		return -EFAULT;
+	set = new_state & ~old_state;
+	clear = old_state & ~new_state;
+	if (!set && !clear)
+		return 0;
+	gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
+	return tty->driver->tiocmset(tty, NULL, set, clear);
+}
+
+static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
+{
+	return -EINVAL;
+}
+
+static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
+{
+	return -EINVAL;
+}
+
+static struct gigaset_ops ops = {
+	gigaset_write_cmd,
+	gigaset_write_room,
+	gigaset_chars_in_buffer,
+	gigaset_brkchars,
+	gigaset_init_bchannel,
+	gigaset_close_bchannel,
+	gigaset_initbcshw,
+	gigaset_freebcshw,
+	gigaset_reinitbcshw,
+	gigaset_initcshw,
+	gigaset_freecshw,
+	gigaset_set_modem_ctrl,
+	gigaset_baud_rate,
+	gigaset_set_line_ctrl,
+	gigaset_m10x_send_skb,	/* asyncdata.c */
+	gigaset_m10x_input,	/* asyncdata.c */
+};
+
+
+/* Line Discipline Interface */
+/* ========================= */
+
+/* helper functions for cardstate refcounting */
+static struct cardstate *cs_get(struct tty_struct *tty)
+{
+	struct cardstate *cs = tty->disc_data;
+
+	if (!cs || !cs->hw.ser) {
+		gig_dbg(DEBUG_ANY, "%s: no cardstate", __func__);
+		return NULL;
+	}
+	atomic_inc(&cs->hw.ser->refcnt);
+	return cs;
+}
+
+static void cs_put(struct cardstate *cs)
+{
+	if (atomic_dec_and_test(&cs->hw.ser->refcnt))
+		mutex_unlock(&cs->hw.ser->dead_mutex);
+}
+
+/*
+ * Called by the tty driver when the line discipline is pushed onto the tty.
+ * Called in process context.
+ */
+static int
+gigaset_tty_open(struct tty_struct *tty)
+{
+	struct cardstate *cs;
+
+	gig_dbg(DEBUG_INIT, "Starting HLL for Gigaset M101");
+
+	info(DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
+	if (!driver) {
+		err("%s: no driver structure", __func__);
+		return -ENODEV;
+	}
+
+	/* allocate memory for our device state and intialize it */
+	if (!(cs = gigaset_initcs(driver, 1, 1, 0, cidmode,
+				  GIGASET_MODULENAME)))
+		goto error;
+
+	cs->dev = &cs->hw.ser->dev.dev;
+	cs->hw.ser->tty = tty;
+	mutex_init(&cs->hw.ser->dead_mutex);
+	atomic_set(&cs->hw.ser->refcnt, 1);
+
+	tty->disc_data = cs;
+
+	/* OK.. Initialization of the datastructures and the HW is done.. Now
+	 * startup system and notify the LL that we are ready to run
+	 */
+	if (startmode == SM_LOCKED)
+		atomic_set(&cs->mstate, MS_LOCKED);
+	if (!gigaset_start(cs)) {
+		tasklet_kill(&cs->write_tasklet);
+		goto error;
+	}
+
+	gig_dbg(DEBUG_INIT, "Startup of HLL done");
+	mutex_lock(&cs->hw.ser->dead_mutex);
+	return 0;
+
+error:
+	gig_dbg(DEBUG_INIT, "Startup of HLL failed");
+	tty->disc_data = NULL;
+	gigaset_freecs(cs);
+	return -ENODEV;
+}
+
+/*
+ * Called by the tty driver when the line discipline is removed.
+ * Called from process context.
+ */
+static void
+gigaset_tty_close(struct tty_struct *tty)
+{
+	struct cardstate *cs = tty->disc_data;
+
+	gig_dbg(DEBUG_INIT, "Stopping HLL for Gigaset M101");
+
+	if (!cs) {
+		gig_dbg(DEBUG_INIT, "%s: no cardstate", __func__);
+		return;
+	}
+
+	/* prevent other callers from entering ldisc methods */
+	tty->disc_data = NULL;
+
+	if (!cs->hw.ser)
+		err("%s: no hw cardstate", __func__);
+	else {
+		/* wait for running methods to finish */
+		if (!atomic_dec_and_test(&cs->hw.ser->refcnt))
+			mutex_lock(&cs->hw.ser->dead_mutex);
+	}
+
+	/* stop operations */
+	gigaset_stop(cs);
+	tasklet_kill(&cs->write_tasklet);
+	flush_send_queue(cs);
+	cs->dev = NULL;
+	gigaset_freecs(cs);
+
+	gig_dbg(DEBUG_INIT, "Shutdown of HLL done");
+}
+
+/*
+ * Called by the tty driver when the tty line is hung up.
+ * Wait for I/O to driver to complete and unregister ISDN device.
+ * This is already done by the close routine, so just call that.
+ * Called from process context.
+ */
+static int gigaset_tty_hangup(struct tty_struct *tty)
+{
+	gigaset_tty_close(tty);
+	return 0;
+}
+
+/*
+ * Read on the tty.
+ * Unused, received data goes only to the Gigaset driver.
+ */
+static ssize_t
+gigaset_tty_read(struct tty_struct *tty, struct file *file,
+		 unsigned char __user *buf, size_t count)
+{
+	return -EAGAIN;
+}
+
+/*
+ * Write on the tty.
+ * Unused, transmit data comes only from the Gigaset driver.
+ */
+static ssize_t
+gigaset_tty_write(struct tty_struct *tty, struct file *file,
+		  const unsigned char *buf, size_t count)
+{
+	return -EAGAIN;
+}
+
+/*
+ * Ioctl on the tty.
+ * Called in process context only.
+ * May be re-entered by multiple ioctl calling threads.
+ */
+static int
+gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
+		  unsigned int cmd, unsigned long arg)
+{
+	struct cardstate *cs = cs_get(tty);
+	int rc, val;
+	int __user *p = (int __user *)arg;
+
+	if (!cs)
+		return -ENXIO;
+
+	switch (cmd) {
+	case TCGETS:
+	case TCGETA:
+		/* pass through to underlying serial device */
+		rc = n_tty_ioctl(tty, file, cmd, arg);
+		break;
+
+	case TCFLSH:
+		/* flush our buffers and the serial port's buffer */
+		switch (arg) {
+		case TCIFLUSH:
+			/* no own input buffer to flush */
+			break;
+		case TCIOFLUSH:
+		case TCOFLUSH:
+			flush_send_queue(cs);
+			break;
+		}
+		/* flush the serial port's buffer */
+		rc = n_tty_ioctl(tty, file, cmd, arg);
+		break;
+
+	case FIONREAD:
+		/* unused, always return zero */
+		val = 0;
+		rc = put_user(val, p);
+		break;
+
+	default:
+		rc = -ENOIOCTLCMD;
+	}
+
+	cs_put(cs);
+	return rc;
+}
+
+/*
+ * Poll on the tty.
+ * Unused, always return zero.
+ */
+static unsigned int
+gigaset_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
+{
+	return 0;
+}
+
+/*
+ * Called by the tty driver when a block of data has been received.
+ * Will not be re-entered while running but other ldisc functions
+ * may be called in parallel.
+ * Can be called from hard interrupt level as well as soft interrupt
+ * level or mainline.
+ * Parameters:
+ *	tty	tty structure
+ *	buf	buffer containing received characters
+ *	cflags	buffer containing error flags for received characters (ignored)
+ *	count	number of received characters
+ */
+static void
+gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
+		    char *cflags, int count)
+{
+	struct cardstate *cs = cs_get(tty);
+	unsigned tail, head, n;
+	struct inbuf_t *inbuf;
+
+	if (!cs)
+		return;
+	if (!(inbuf = cs->inbuf)) {
+		dev_err(cs->dev, "%s: no inbuf\n", __func__);
+		cs_put(cs);
+		return;
+	}
+
+	tail = atomic_read(&inbuf->tail);
+	head = atomic_read(&inbuf->head);
+	gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes",
+		head, tail, count);
+
+	if (head <= tail) {
+		/* possible buffer wraparound */
+		n = min_t(unsigned, count, RBUFSIZE - tail);
+		memcpy(inbuf->data + tail, buf, n);
+		tail = (tail + n) % RBUFSIZE;
+		buf += n;
+		count -= n;
+	}
+
+	if (count > 0) {
+		/* tail < head and some data left */
+		n = head - tail - 1;
+		if (count > n) {
+			dev_err(cs->dev,
+				"inbuf overflow, discarding %d bytes\n",
+				count - n);
+			count = n;
+		}
+		memcpy(inbuf->data + tail, buf, count);
+		tail += count;
+	}
+
+	gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
+	atomic_set(&inbuf->tail, tail);
+
+	/* Everything was received .. Push data into handler */
+	gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
+	gigaset_schedule_event(cs);
+	cs_put(cs);
+}
+
+/*
+ * Called by the tty driver when there's room for more data to send.
+ */
+static void
+gigaset_tty_wakeup(struct tty_struct *tty)
+{
+	struct cardstate *cs = cs_get(tty);
+
+	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+	if (!cs)
+		return;
+	tasklet_schedule(&cs->write_tasklet);
+	cs_put(cs);
+}
+
+static struct tty_ldisc gigaset_ldisc = {
+	.owner		= THIS_MODULE,
+	.magic		= TTY_LDISC_MAGIC,
+	.name		= "ser_gigaset",
+	.open		= gigaset_tty_open,
+	.close		= gigaset_tty_close,
+	.hangup		= gigaset_tty_hangup,
+	.read		= gigaset_tty_read,
+	.write		= gigaset_tty_write,
+	.ioctl		= gigaset_tty_ioctl,
+	.poll		= gigaset_tty_poll,
+	.receive_buf	= gigaset_tty_receive,
+	.write_wakeup	= gigaset_tty_wakeup,
+};
+
+
+/* Initialization / Shutdown */
+/* ========================= */
+
+static int __init ser_gigaset_init(void)
+{
+	int rc;
+
+	gig_dbg(DEBUG_INIT, "%s", __func__);
+	if ((rc = platform_driver_register(&device_driver)) != 0) {
+		err("error %d registering platform driver", rc);
+		return rc;
+	}
+
+	/* allocate memory for our driver state and intialize it */
+	if (!(driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
+					  GIGASET_MODULENAME, GIGASET_DEVNAME,
+					  &ops, THIS_MODULE)))
+		goto error;
+
+	if ((rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc)) != 0) {
+		err("error %d registering line discipline", rc);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	if (driver) {
+		gigaset_freedriver(driver);
+		driver = NULL;
+	}
+	platform_driver_unregister(&device_driver);
+	return rc;
+}
+
+static void __exit ser_gigaset_exit(void)
+{
+	int rc;
+
+	gig_dbg(DEBUG_INIT, "%s", __func__);
+
+	if (driver) {
+		gigaset_freedriver(driver);
+		driver = NULL;
+	}
+
+	if ((rc = tty_unregister_ldisc(N_GIGASET_M101)) != 0)
+		err("error %d unregistering line discipline", rc);
+
+	platform_driver_unregister(&device_driver);
+}
+
+module_init(ser_gigaset_init);
+module_exit(ser_gigaset_exit);
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index eba1046..a5b941c 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index ddd47cdf..1e2d38e 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -29,7 +29,7 @@
 
 static char *revision = "$Revision: 1.1.2.3 $";
 
-#undef CONFIG_B1DMA_DEBUG
+#undef AVM_B1DMA_DEBUG
 
 /* ------------------------------------------------------------- */
 
@@ -391,16 +391,16 @@
 			_put_slice(&p, skb->data, len);
 		}
 		txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;
-#ifdef CONFIG_B1DMA_DEBUG
+#ifdef AVM_B1DMA_DEBUG
 		printk(KERN_DEBUG "tx: put msg len=%d\n", txlen);
 #endif
 	} else {
 		txlen = skb->len-2;
-#ifdef CONFIG_B1DMA_POLLDEBUG
+#ifdef AVM_B1DMA_POLLDEBUG
 		if (skb->data[2] == SEND_POLLACK)
 			printk(KERN_INFO "%s: send ack\n", card->name);
 #endif
-#ifdef CONFIG_B1DMA_DEBUG
+#ifdef AVM_B1DMA_DEBUG
 		printk(KERN_DEBUG "tx: put 0x%x len=%d\n", 
 		       skb->data[2], txlen);
 #endif
@@ -450,7 +450,7 @@
 	u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
 	u8 b1cmd =  _get_byte(&p);
 
-#ifdef CONFIG_B1DMA_DEBUG
+#ifdef AVM_B1DMA_DEBUG
 	printk(KERN_DEBUG "rx: 0x%x %lu\n", b1cmd, (unsigned long)dma->recvlen);
 #endif
 	
@@ -515,7 +515,7 @@
 		break;
 
 	case RECEIVE_START:
-#ifdef CONFIG_B1DMA_POLLDEBUG
+#ifdef AVM_B1DMA_POLLDEBUG
 		printk(KERN_INFO "%s: receive poll\n", card->name);
 #endif
 		if (!suppress_pollack)
@@ -601,7 +601,7 @@
 				rxlen = (dma->recvlen + 3) & ~3;
 				b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR);
 				b1dma_writel(card, rxlen, AMCC_RXLEN);
-#ifdef CONFIG_B1DMA_DEBUG
+#ifdef AVM_B1DMA_DEBUG
 			} else {
 				printk(KERN_ERR "%s: rx not complete (%d).\n",
 					card->name, rxlen);
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index 2a3eb38..6f5efa8d 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -28,8 +28,8 @@
 #include <linux/isdn/capilli.h>
 #include "avmcard.h"
 
-#undef CONFIG_C4_DEBUG
-#undef CONFIG_C4_POLLDEBUG
+#undef AVM_C4_DEBUG
+#undef AVM_C4_POLLDEBUG
 
 /* ------------------------------------------------------------- */
 
@@ -420,7 +420,7 @@
 
 	skb = skb_dequeue(&dma->send_queue);
 	if (!skb) {
-#ifdef CONFIG_C4_DEBUG
+#ifdef AVM_C4_DEBUG
 		printk(KERN_DEBUG "%s: tx underrun\n", card->name);
 #endif
 		return;
@@ -444,16 +444,16 @@
 			_put_slice(&p, skb->data, len);
 		}
 		txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;
-#ifdef CONFIG_C4_DEBUG
+#ifdef AVM_C4_DEBUG
 		printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
 #endif
 	} else {
 		txlen = skb->len-2;
-#ifdef CONFIG_C4_POLLDEBUG
+#ifdef AVM_C4_POLLDEBUG
 		if (skb->data[2] == SEND_POLLACK)
 			printk(KERN_INFO "%s: ack to c4\n", card->name);
 #endif
-#ifdef CONFIG_C4_DEBUG
+#ifdef AVM_C4_DEBUG
 		printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
 				card->name, skb->data[2], txlen);
 #endif
@@ -508,7 +508,7 @@
 	u32 cidx;
 
 
-#ifdef CONFIG_C4_DEBUG
+#ifdef AVM_C4_DEBUG
 	printk(KERN_DEBUG "%s: rx 0x%x len=%lu\n", card->name,
 				b1cmd, (unsigned long)dma->recvlen);
 #endif
@@ -586,7 +586,7 @@
 		break;
 
 	case RECEIVE_START:
-#ifdef CONFIG_C4_POLLDEBUG
+#ifdef AVM_C4_POLLDEBUG
 		printk(KERN_INFO "%s: poll from c4\n", card->name);
 #endif
 		if (!suppress_pollack)
diff --git a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c
index 0afd763..ff284ae 100644
--- a/drivers/isdn/hardware/eicon/capifunc.c
+++ b/drivers/isdn/hardware/eicon/capifunc.c
@@ -187,7 +187,7 @@
  */
 void *TransmitBufferSet(APPL * appl, dword ref)
 {
-	appl->xbuffer_used[ref] = TRUE;
+	appl->xbuffer_used[ref] = true;
 	DBG_PRV1(("%d:xbuf_used(%d)", appl->Id, ref + 1))
 	    return (void *) ref;
 }
@@ -202,7 +202,7 @@
 
 void TransmitBufferFree(APPL * appl, void *p)
 {
-	appl->xbuffer_used[(dword) p] = FALSE;
+	appl->xbuffer_used[(dword) p] = false;
 	DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword) p) + 1))
 }
 
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c
index d835e74..0db9cc6 100644
--- a/drivers/isdn/hardware/eicon/debug.c
+++ b/drivers/isdn/hardware/eicon/debug.c
@@ -287,7 +287,7 @@
   }
   external_dbg_queue = 0;
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].pmem) {
       diva_os_free (0, clients[i].pmem);
     }
@@ -391,7 +391,7 @@
 
   diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
 
-  for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) {
+  for (id = 1; id < ARRAY_SIZE(clients); id++) {
     if (clients[id].hDbg == hDbg) {
       /*
         driver already registered
@@ -494,7 +494,7 @@
   diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
   diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].hDbg == hDbg) {
       diva_dbg_entry_head_t* pmsg;
       char tmp[256];
@@ -736,7 +736,7 @@
   int to_copy;
 
   if (!data || !id || (data_length < 17) ||
-      (id >= (sizeof(clients)/sizeof(clients[0])))) {
+      (id >= ARRAY_SIZE(clients))) {
     return (-1);
   }
 
@@ -786,7 +786,7 @@
   diva_os_spin_lock_magic_t old_irql;
   int ret = -1;
 
-  if (!data || !id || (id >= (sizeof(clients)/sizeof(clients[0])))) {
+  if (!data || !id || (id >= ARRAY_SIZE(clients))) {
     return (-1);
   }
   diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info");
@@ -809,7 +809,7 @@
   int ret = -1;
   
 
-  if (!id || (id >= (sizeof(clients)/sizeof(clients[0])))) {
+  if (!id || (id >= ARRAY_SIZE(clients))) {
     return (-1);
   }
 
@@ -887,7 +887,7 @@
   diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
   diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
 
-  for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) {
+  for (id = 1; id < ARRAY_SIZE(clients); id++) {
     if (clients[id].hDbg && (clients[id].request == d->request)) {
       diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
       diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
@@ -1037,7 +1037,7 @@
   diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
   diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].hDbg && (clients[i].request == d->request)) {
       diva_dbg_entry_head_t* pmsg;
       char tmp[256];
@@ -1115,7 +1115,7 @@
 void* SuperTraceOpenAdapter   (int AdapterNumber) {
   int i;
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].hDbg && clients[i].request && (clients[i].logical == AdapterNumber)) {
       return (&clients[i]);
     }
@@ -1508,7 +1508,7 @@
 					int ch = TraceFilterChannel;
 					int id = TraceFilterIdent;
 
-					if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+					if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
 						(clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
 						if (ch != (int)modem->ChannelNumber) {
 							break;
@@ -1555,7 +1555,7 @@
 					int ch = TraceFilterChannel;
 					int id = TraceFilterIdent;
 
-					if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+					if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
 						(clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
 						if (ch != (int)fax->ChannelNumber) {
 							break;
@@ -1803,7 +1803,7 @@
   /*
     Selective trace
     */
-  if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+  if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
       (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
     const char* p = NULL;
     int ch_value = -1;
@@ -1925,7 +1925,7 @@
   byte * pmem;
 
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     pmem = NULL;
 
     diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
@@ -2006,7 +2006,7 @@
 
   on = (TraceFilter[0] == 0);
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
       client_b_on    = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
       client_atap_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO)    != 0);
@@ -2017,7 +2017,7 @@
     }
   }
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
       diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
       clients[i].request_pending = 0;
diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c
index e1df8d9..ce8df38 100644
--- a/drivers/isdn/hardware/eicon/di.c
+++ b/drivers/isdn/hardware/eicon/di.c
@@ -173,16 +173,16 @@
         xdi_xlog_request (XDI_A_NR(a), this->Id, this->ReqCh, this->MInd,
                           a->IdTypeTable[this->No]);
         a->ram_out(a, &ReqOut->Req, this->MInd);
-        more = TRUE;
+        more = true;
       }
       else {
         xdi_xlog_request (XDI_A_NR(a), this->Id, this->ReqCh, this->Req,
                           a->IdTypeTable[this->No]);
         this->More |=XMOREF;
         a->ram_out(a, &ReqOut->Req, this->Req);
-        more = FALSE;
+        more = false;
         if (a->FlowControlIdTable[this->ReqCh] == this->Id)
-          a->FlowControlSkipTable[this->ReqCh] = TRUE;
+          a->FlowControlSkipTable[this->ReqCh] = true;
         /*
            Note that remove request was sent to the card
            */
@@ -311,7 +311,7 @@
         /* are marked RNR                                           */
       if(RNRId && RNRId==a->ram_in(a, &IndIn->IndId)) {
         a->ram_out(a, &IndIn->Ind, 0);
-        a->ram_out(a, &IndIn->RNR, TRUE);
+        a->ram_out(a, &IndIn->RNR, true);
       }
       else {
         Ind = a->ram_in(a, &IndIn->Ind);
@@ -331,7 +331,7 @@
             dtrc(dprintf("RNR"));
             a->ram_out(a, &IndIn->Ind, 0);
             RNRId = a->ram_in(a, &IndIn->IndId);
-            a->ram_out(a, &IndIn->RNR, TRUE);
+            a->ram_out(a, &IndIn->RNR, true);
           }
         }
       }
@@ -340,7 +340,7 @@
     }
     a->ram_out(a, &PR_RAM->IndOutput, 0);
   }
-  return FALSE;
+  return false;
 }
 byte scom_test_int(ADAPTER * a)
 {
@@ -399,7 +399,7 @@
           return (0);
         }
         if (extended_info_type == DIVA_RC_TYPE_REMOVE_COMPLETE)
-          a->RcExtensionSupported = TRUE;
+          a->RcExtensionSupported = true;
       }
       a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_REMOVE_PENDING;
       a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_NO_RC_CANCELLING;
@@ -428,7 +428,7 @@
     }
     if (Rc==OK_FC) {
       a->FlowControlIdTable[Ch] = Id;
-      a->FlowControlSkipTable[Ch] = FALSE;
+      a->FlowControlSkipTable[Ch] = false;
       this->Rc = Rc;
       this->More &= ~(XBUSY | XMOREC);
       this->complete=0xff;
diff --git a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c
index 77155d9..4aba5c5 100644
--- a/drivers/isdn/hardware/eicon/divamnt.c
+++ b/drivers/isdn/hardware/eicon/divamnt.c
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <asm/uaccess.h>
@@ -164,7 +163,7 @@
 	return (maint_read_write(buf, (int) count));
 }
 
-static struct file_operations divas_maint_fops = {
+static const struct file_operations divas_maint_fops = {
 	.owner   = THIS_MODULE,
 	.llseek  = no_llseek,
 	.read    = divas_maint_read,
diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c
index fff0d89..556b196 100644
--- a/drivers/isdn/hardware/eicon/divasi.c
+++ b/drivers/isdn/hardware/eicon/divasi.c
@@ -131,7 +131,7 @@
 	}
 }
 
-static struct file_operations divas_idi_fops = {
+static const struct file_operations divas_idi_fops = {
 	.owner   = THIS_MODULE,
 	.llseek  = no_llseek,
 	.read    = um_idi_read,
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index 91fc92c..5e862e2 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/ioport.h>
@@ -663,7 +662,7 @@
 	return (POLLIN | POLLRDNORM);
 }
 
-static struct file_operations divas_fops = {
+static const struct file_operations divas_fops = {
 	.owner   = THIS_MODULE,
 	.llseek  = no_llseek,
 	.read    = divas_read,
diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c
index 6a4373a..0632a26 100644
--- a/drivers/isdn/hardware/eicon/divasproc.c
+++ b/drivers/isdn/hardware/eicon/divasproc.c
@@ -113,7 +113,7 @@
 	return (0);
 }
 
-static struct file_operations divas_fops = {
+static const struct file_operations divas_fops = {
 	.owner   = THIS_MODULE,
 	.llseek  = no_llseek,
 	.read    = divas_read,
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
index f9b00f1..784232a 100644
--- a/drivers/isdn/hardware/eicon/message.c
+++ b/drivers/isdn/hardware/eicon/message.c
@@ -253,7 +253,7 @@
 
 
 
-static byte remove_started = FALSE;
+static byte remove_started = false;
 static PLCI dummy_plci;
 
 
@@ -456,12 +456,12 @@
 
         return _QUEUE_FULL;
       }
-      c = FALSE;
+      c = false;
       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
       {
         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
-          c = TRUE;
+          c = true;
       }
       if (msg->header.command == _DATA_B3_R)
       {
@@ -506,13 +506,13 @@
 
             return _QUEUE_FULL;
           }
-          c = TRUE;
+          c = true;
         }
       }
       else
       {
         if (plci->req_in || plci->internal_command)
-          c = TRUE;
+          c = true;
         else
         {
           plci->command = msg->header.command;
@@ -626,10 +626,10 @@
       break;
     }
 
-    if(p>length) return TRUE;
+    if(p>length) return true;
   }
   if(parms) parms[i].info = NULL;
-  return FALSE;
+  return false;
 }
 
 void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out)
@@ -687,7 +687,7 @@
   word j;
 
   if(!remove_started) {
-    remove_started = TRUE;
+    remove_started = true;
     for(i=0;i<max_adapter;i++) {
       if(adapter[i].request) {
         for(j=0;j<adapter[i].max_plci;j++) {
@@ -1080,7 +1080,7 @@
       send_req(plci);
     }
   }
-  ncci_remove (plci, 0, FALSE);
+  ncci_remove (plci, 0, false);
   plci_free_msg_in_queue (plci);
 
   plci->channels = 0;
@@ -1226,7 +1226,7 @@
       Id = ((word)1<<8)|a->Id;
       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
-      return FALSE;
+      return false;
     }
     Info = _OUT_OF_PLCI;
     if((i=get_plci(a)))
@@ -1330,7 +1330,7 @@
       plci->command = _CONNECT_R;
       plci->number = Number;
       /* x.31 or D-ch free SAPI in LinkLayer? */
-      if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = TRUE;
+      if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
       {
         /* B-channel used for B3 connections (ch==0), or no B channel    */
@@ -1381,7 +1381,7 @@
             plci->command = 0;
             dbug(1,dprintf("Spoof"));
             send_req(plci);
-            return FALSE;
+            return false;
           }
           if(ch==4)add_p(plci,CHI,p_chi);
           add_s(plci,CPN,&parms[1]);
@@ -1395,11 +1395,11 @@
             plci->appl = appl;
             sig_req(plci,LISTEN_REQ,0);
             send_req(plci);
-            return FALSE;
+            return false;
           }
         }
         send_req(plci);
-        return FALSE;
+        return false;
       }
       plci->Id = 0;
     }
@@ -1571,7 +1571,7 @@
 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 {
   dbug(1,dprintf("connect_a_res"));
-  return FALSE;
+  return false;
 }
 
 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
@@ -1624,9 +1624,9 @@
       }
     }
 
-  if(!appl)  return FALSE;
+  if(!appl)  return false;
   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
-  return FALSE;
+  return false;
 }
 
 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
@@ -1702,7 +1702,7 @@
         "w",Info);
 
   if (a) listen_check(a);
-  return FALSE;
+  return false;
 }
 
 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
@@ -1739,7 +1739,7 @@
       add_s(plci,KEY,&ai_parms[1]);
       sig_req(plci,INFO_REQ,0);
       send_req(plci);
-      return FALSE;
+      return false;
     }
 
     if(plci->State && ai_parms[2].length)
@@ -1769,7 +1769,7 @@
     if((i=get_plci(a)))
     {
       rc_plci = &a->plci[i-1];
-      appl->NullCREnable  = TRUE;
+      appl->NullCREnable  = true;
       rc_plci->internal_command = C_NCR_FAC_REQ;
       rc_plci->appl = appl;
       add_p(rc_plci,CAI,"\x01\x80");
@@ -1788,7 +1788,7 @@
       add_ai(rc_plci, &msg[1]);
       sig_req(rc_plci,NCR_FACILITY,0);
       send_req(rc_plci);
-      return FALSE;
+      return false;
      /* for application controlled supplementary services    */
     }
   }
@@ -1811,13 +1811,13 @@
           Number,
           "w",Info);
   }
-  return FALSE;
+  return false;
 }
 
 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 {
   dbug(1,dprintf("info_res"));
-  return FALSE;
+  return false;
 }
 
 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
@@ -1828,7 +1828,7 @@
   dbug(1,dprintf("alert_req"));
 
   Info = _WRONG_IDENTIFIER;
-  ret = FALSE;
+  ret = false;
   if(plci) {
     Info = _ALERT_IGNORED;
     if(plci->State!=INC_CON_ALERT) {
@@ -1922,7 +1922,7 @@
             rplci->appl = appl;
             sig_req(rplci,S_SUPPORTED,0);
             send_req(rplci);
-            return FALSE;
+            return false;
             break;
 
           case S_LISTEN:
@@ -1972,7 +1972,7 @@
               add_s(plci,CAI,&ss_parms[1]);
               sig_req(plci,CALL_HOLD,0);
               send_req(plci);
-              return FALSE;
+              return false;
             }
             else Info = 0x3010;                    /* wrong state           */
             break;
@@ -1997,13 +1997,13 @@
                 plci->internal_command = BLOCK_PLCI;
                 plci->command = 0;
                 dbug(1,dprintf("Spoof"));
-                return FALSE;
+                return false;
               }
               else
               {
                 sig_req(plci,CALL_RETRIEVE,0);
                 send_req(plci);
-                return FALSE;
+                return false;
               }
             }
             else Info = 0x3010;                    /* wrong state           */
@@ -2123,7 +2123,7 @@
               add_p(plci,CAI,cai);
               sig_req(plci,S_SERVICE,0);
               send_req(plci);
-              return FALSE;
+              return false;
             }
             else Info = 0x3010;                    /* wrong state           */
             break;
@@ -2265,7 +2265,7 @@
               add_p(rplci,CAI,cai);
               sig_req(rplci,S_SERVICE,0);
               send_req(rplci);
-              return FALSE;
+              return false;
             }
             else
             {
@@ -2291,14 +2291,14 @@
             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
             plci->command = 0;
             plci->internal_command = CD_REQ_PEND;
-            appl->CDEnable = TRUE;
+            appl->CDEnable = true;
             cai[0] = 1;
             cai[1] = CALL_DEFLECTION;
             add_p(plci,CAI,cai);
             add_p(plci,CPN,ss_parms[3].info);
             sig_req(plci,S_SERVICE,0);
             send_req(plci);
-            return FALSE;
+            return false;
             break;
 
           case S_CALL_FORWARDING_START:
@@ -2337,7 +2337,7 @@
             add_p(rplci,CPN,ss_parms[6].info);
             sig_req(rplci,S_SERVICE,0);
             send_req(rplci);
-            return FALSE;
+            return false;
             break;
 
           case S_INTERROGATE_DIVERSION:
@@ -2456,7 +2456,7 @@
                         
             sig_req(rplci,S_SERVICE,0);
             send_req(rplci);
-            return FALSE;
+            return false;
             break;
 
           case S_MWI_ACTIVATE:
@@ -2472,7 +2472,7 @@
               {
                 rplci = &a->plci[i-1];
                 rplci->appl = appl;
-                rplci->cr_enquiry=TRUE;
+                rplci->cr_enquiry=true;
                 add_p(rplci,CAI,"\x01\x80");
                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
                 sig_req(rplci,ASSIGN,DSIG_ID);
@@ -2487,7 +2487,7 @@
             else
             {
               rplci = plci;
-              rplci->cr_enquiry=FALSE;
+              rplci->cr_enquiry=false;
             }
 
             rplci->command = 0;
@@ -2509,7 +2509,7 @@
             add_p(rplci,UID,ss_parms[10].info); /* Time */
             sig_req(rplci,S_SERVICE,0);
             send_req(rplci);
-            return FALSE;
+            return false;
 
           case S_MWI_DEACTIVATE:
             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
@@ -2524,7 +2524,7 @@
               {
                 rplci = &a->plci[i-1];
                 rplci->appl = appl;
-                rplci->cr_enquiry=TRUE;
+                rplci->cr_enquiry=true;
                 add_p(rplci,CAI,"\x01\x80");
                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
                 sig_req(rplci,ASSIGN,DSIG_ID);
@@ -2539,7 +2539,7 @@
             else
             {
               rplci = plci;
-              rplci->cr_enquiry=FALSE;
+              rplci->cr_enquiry=false;
             }
 
             rplci->command = 0;
@@ -2556,7 +2556,7 @@
             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
             sig_req(rplci,S_SERVICE,0);
             send_req(rplci);
-            return FALSE;
+            return false;
 
           default:
             Info = 0x300E;  /* not supported */
@@ -2597,13 +2597,13 @@
         Id,
         Number,
         "wws",Info,selector,SSparms);
-  return FALSE;
+  return false;
 }
 
 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 {
   dbug(1,dprintf("facility_res"));
-  return FALSE;
+  return false;
 }
 
 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -2649,7 +2649,7 @@
               Id,
               Number,
               "w",Info);
-        return FALSE;
+        return false;
       }
       plci->requested_options_conn = 0;
 
@@ -2684,7 +2684,7 @@
            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
           {
             len = (byte)(&(((T30_INFO *) 0)->universal_6));
-            fax_info_change = FALSE;
+            fax_info_change = false;
             if (ncpi->length >= 4)
             {
               w = GET_WORD(&ncpi->info[3]);
@@ -2693,7 +2693,7 @@
                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
-                fax_info_change = TRUE;
+                fax_info_change = true;
               }
               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
               if (w & 0x0002)  /* Fax-polling request */
@@ -2709,7 +2709,7 @@
                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
                 {
                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
-                  fax_info_change = TRUE;
+                  fax_info_change = true;
                 }
 
                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
@@ -2781,13 +2781,13 @@
                 {
                   len = (byte)(&(((T30_INFO *) 0)->universal_6));
                 }
-                fax_info_change = TRUE;
+                fax_info_change = true;
 
               }
               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
               {
                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
-                fax_info_change = TRUE;
+                fax_info_change = true;
               }
             }
             if (Info == GOOD)
@@ -2798,12 +2798,12 @@
                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
                 {
                   start_internal_command (Id, plci, fax_connect_info_command);
-                  return FALSE;
+                  return false;
                 }
                 else
                 {
                   start_internal_command (Id, plci, fax_adjust_b23_command);
-                  return FALSE;
+                  return false;
                 }
               }
             }
@@ -2820,7 +2820,7 @@
         for (w = 0; w < ncpi->length; w++)
           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
         start_internal_command (Id, plci, rtp_connect_b3_req_command);
-        return FALSE;
+        return false;
       }
 
       if(!Info)
@@ -2837,7 +2837,7 @@
         Id,
         Number,
         "w",Info);
-  return FALSE;
+  return false;
 }
 
 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -2909,7 +2909,7 @@
             plci->fax_connect_info_length = len;
             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
             start_internal_command (Id, plci, fax_connect_ack_command);
-     return FALSE;
+     return false;
           }
         }
 
@@ -2932,7 +2932,7 @@
         for (w = 0; w < ncpi->length; w++)
           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
         start_internal_command (Id, plci, rtp_connect_b3_res_command);
-        return FALSE;
+        return false;
       }
 
       else
@@ -2945,14 +2945,14 @@
         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
         if (plci->adjust_b_restore)
         {
-          plci->adjust_b_restore = FALSE;
+          plci->adjust_b_restore = false;
           start_internal_command (Id, plci, adjust_b_restore);
         }
       }
       return 1;
     }
   }
-  return FALSE;
+  return false;
 }
 
 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -2972,7 +2972,7 @@
       channel_xmit_xon (plci);
     }
   }
-  return FALSE;
+  return false;
 }
 
 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3004,7 +3004,7 @@
       {
         plci->send_disc = (byte)ncci;
         plci->command = 0;
-        return FALSE;
+        return false;
       }
       else
       {
@@ -3028,7 +3028,7 @@
         Id,
         Number,
         "w",Info);
-  return FALSE;
+  return false;
 }
 
 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3084,7 +3084,7 @@
       }
     }
   }
-  return FALSE;
+  return false;
 }
 
 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3140,7 +3140,7 @@
       }
 
       send_data(plci);
-      return FALSE;
+      return false;
     }
   }
   if (appl)
@@ -3161,7 +3161,7 @@
           Number,
           "ww",GET_WORD(parms[2].info),Info);
   }
-  return FALSE;
+  return false;
 }
 
 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3194,7 +3194,7 @@
       }
     }
   }
-  return FALSE;
+  return false;
 }
 
 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3235,7 +3235,7 @@
         Id,
         Number,
         "w",Info);
-  return FALSE;
+  return false;
 }
 
 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3254,12 +3254,12 @@
       {
         a->ncci_state[ncci] = CONNECTED;
         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
-        return TRUE;
+        return true;
       }
     break;
     }
   }
-  return FALSE;
+  return false;
 }
 
 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3292,7 +3292,7 @@
       return 1;
     }
   }
-  return FALSE;
+  return false;
 }
 
 
@@ -3378,7 +3378,7 @@
               plci->internal_command = BLOCK_PLCI; /* lock other commands */
               plci->command = 0;
               dbug(1,dprintf("continue if codec loaded"));
-              return FALSE;
+              return false;
             }
           }
         }
@@ -3407,12 +3407,12 @@
         else if (plci->call_dir & CALL_DIR_IN)
           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
         start_internal_command (Id, plci, select_b_command);
-        return FALSE;
+        return false;
       }
     }
   }
   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
-  return FALSE;
+  return false;
 }
 
 byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3489,7 +3489,7 @@
           }
 
           plci->State = LOCAL_CONNECT;
-          plci->manufacturer = TRUE;
+          plci->manufacturer = true;
           plci->command = _MANUFACTURER_R;
           plci->m_command = command;
           plci->number = Number;
@@ -3520,7 +3520,7 @@
                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
                 plci->command = 0;
                 send_req(plci);
-                return FALSE;
+                return false;
               }
               if(dir==1) {
                 sig_req(plci,CALL_REQ,0);
@@ -3573,7 +3573,7 @@
       }
       else if(req==LAW_REQ)
       {
-        plci->cr_enquiry = TRUE;
+        plci->cr_enquiry = true;
       }
       add_ss(plci,FTY,&m_parms[1]);
       sig_req(plci,req,0);
@@ -3739,7 +3739,7 @@
         Id,
         Number,
         "dww",_DI_MANU_ID,command,Info);
-  return FALSE;
+  return false;
 }
 
 
@@ -3760,7 +3760,7 @@
    || (msg[1].length == 0)
    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
   {
-    return FALSE;
+    return false;
   }
   indication = GET_WORD(msg[1].info);
   switch (indication)
@@ -3811,7 +3811,7 @@
     break;
 
   }
-  return FALSE;
+  return false;
 }
 
 /*------------------------------------------------------------------*/
@@ -3908,14 +3908,14 @@
           plci->nl_req = 0;
       }
       if (plci->nl_req)
-        control_rc (plci, 0, rc, ch, 0, TRUE);
+        control_rc (plci, 0, rc, ch, 0, true);
       else
       {
         if (req == N_XON)
         {
           channel_x_on (plci, ch);
           if (plci->internal_command)
-            control_rc (plci, req, rc, ch, 0, TRUE);
+            control_rc (plci, req, rc, ch, 0, true);
         }
         else
         {
@@ -3931,21 +3931,21 @@
               }
             }
             channel_xmit_xon (plci);
-            control_rc (plci, 0, rc, ch, global_req, TRUE);
+            control_rc (plci, 0, rc, ch, global_req, true);
           }
           else if (plci->data_sent)
           {
             channel_xmit_xon (plci);
-            plci->data_sent = FALSE;
+            plci->data_sent = false;
             plci->NL.XNum = 1;
             data_rc (plci, ch);
             if (plci->internal_command)
-              control_rc (plci, req, rc, ch, 0, TRUE);
+              control_rc (plci, req, rc, ch, 0, true);
           }
           else
           {
             channel_xmit_xon (plci);
-            control_rc (plci, req, rc, ch, 0, TRUE);
+            control_rc (plci, req, rc, ch, 0, true);
           }
         }
       }
@@ -3974,12 +3974,12 @@
         if (rc != ASSIGN_OK)
           e->Id = 0;
         channel_xmit_xon (plci);
-        control_rc (plci, 0, rc, ch, global_req, FALSE);
+        control_rc (plci, 0, rc, ch, global_req, false);
       }
       else
       {
         channel_xmit_xon (plci);
-        control_rc (plci, req, rc, ch, 0, FALSE);
+        control_rc (plci, req, rc, ch, 0, false);
       }
     }
     /*
@@ -4065,8 +4065,8 @@
 
     if (plci->li_notify_update)
     {
-      plci->li_notify_update = FALSE;
-      mixer_notify_update (plci, FALSE);
+      plci->li_notify_update = false;
+      mixer_notify_update (plci, false);
     }
 
   }
@@ -4428,7 +4428,7 @@
           else
           {
             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
-            appl->NullCREnable = FALSE;
+            appl->NullCREnable = false;
             plci_remove(plci);
           }
         }
@@ -4441,7 +4441,7 @@
           else
           {
             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
-            appl->NullCREnable = FALSE;
+            appl->NullCREnable = false;
           }
           plci_remove(plci);
         }
@@ -4862,7 +4862,7 @@
     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
-  byte force_mt_info = FALSE;
+  byte force_mt_info = false;
   byte dir;
   dword d;
   word w;
@@ -4933,7 +4933,7 @@
   {
     if(plci->cr_enquiry && plci->appl)
     {
-      plci->cr_enquiry = FALSE;
+      plci->cr_enquiry = false;
       /* d = MANU_ID            */
       /* w = m_command          */
       /* b = total length       */
@@ -5158,7 +5158,7 @@
         if(application[i].CDEnable)
         {
           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
-          application[i].CDEnable = FALSE;
+          application[i].CDEnable = false;
         }
       }
       break;
@@ -5375,7 +5375,7 @@
         if(application[i].CDEnable)
         {
           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
-          application[i].CDEnable = FALSE;
+          application[i].CDEnable = false;
         }
       }
       break;
@@ -5730,7 +5730,7 @@
                         plci,
                         Id,
                         parms,
-                        SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, TRUE));
+                        SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
         }
       }
       clear_c_ind_mask_bit (plci, MAX_APPL);
@@ -6117,38 +6117,38 @@
         dbug(1,dprintf("CPN "));
         Info_Number = 0x0070;
         Info_Mask   = 0x80;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         break;
       case 8:  /* display      */
         dbug(1,dprintf("display(%d)",i));
         Info_Number = 0x0028;
         Info_Mask = 0x04;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         break;
       case 16: /* Channel Id */
         dbug(1,dprintf("CHI"));
         Info_Number = 0x0018;
         Info_Mask = 0x100;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         mixer_set_bchannel_id (plci, Info_Element);
         break;
       case 19: /* Redirected Number */
         dbug(1,dprintf("RDN"));
         Info_Number = 0x0074;
         Info_Mask = 0x400;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         break;
       case 20: /* Redirected Number extended */
         dbug(1,dprintf("RDX"));
         Info_Number = 0x0073;
         Info_Mask = 0x400;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         break;
       case 22: /* Redirecing Number  */
         dbug(1,dprintf("RIN"));
         Info_Number = 0x0076;
         Info_Mask = 0x400;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         break;
       default:
         Info_Number = 0;
@@ -6312,7 +6312,7 @@
         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
         {
           dbug(1,dprintf("NCR_Ind"));
-          iesent=TRUE;
+          iesent=true;
           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
         }
       }
@@ -6330,7 +6330,7 @@
           if(test_c_ind_mask_bit (plci, j))
           {
             dbug(1,dprintf("Ovl_Ind"));
-            iesent=TRUE;
+            iesent=true;
             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
           }
         }
@@ -6340,7 +6340,7 @@
     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
     {
       dbug(1,dprintf("Std_Ind"));
-      iesent=TRUE;
+      iesent=true;
       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
     }
   }
@@ -6391,7 +6391,7 @@
         && appl->Id
         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
         {
-          iesent = TRUE;
+          iesent = true;
           dbug(1,dprintf("Mlt_NCR_Ind"));
           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
         }
@@ -6403,7 +6403,7 @@
       {
         if(test_c_ind_mask_bit (plci, j))
         {
-          iesent = TRUE;
+          iesent = true;
           dbug(1,dprintf("Mlt_Ovl_Ind"));
           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
         }
@@ -6412,7 +6412,7 @@
     else if(Info_Number
     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
     {
-      iesent = TRUE;
+      iesent = true;
       dbug(1,dprintf("Mlt_Std_Ind"));
       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
     }
@@ -6812,7 +6812,7 @@
         }
         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
         {
-          if (((T30_INFO   *)plci->NL.RBuffer->P)->code < sizeof(fax_info) / sizeof(fax_info[0]))
+	  if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
           else
             info = _FAX_PROTOCOL_ERROR;
@@ -6887,7 +6887,7 @@
           (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
         plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
  if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
-   fax_send_edata_ack = FALSE;
+   fax_send_edata_ack = false;
       }
 
       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
@@ -6928,7 +6928,7 @@
             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
             a->ncci_state[ncci] = INC_DIS_PENDING;
             plci->ncpi_state = 0;
-     fax_send_edata_ack = FALSE;
+     fax_send_edata_ack = false;
           }
           break;
         }
@@ -7025,7 +7025,7 @@
     }
     if (plci->adjust_b_restore)
     {
-      plci->adjust_b_restore = FALSE;
+      plci->adjust_b_restore = false;
       start_internal_command (Id, plci, adjust_b_restore);
     }
     break;
@@ -7041,7 +7041,7 @@
         next_internal_command (Id, plci);
     }
     ncci_state = a->ncci_state[ncci];
-    ncci_remove (plci, ncci, FALSE);
+    ncci_remove (plci, ncci, false);
 
         /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
         /* channel, so we cannot store the state in ncci_state! The */
@@ -7288,18 +7288,18 @@
   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
 
-  plci->data_sent = FALSE;
+  plci->data_sent = false;
   plci->send_disc = 0;
   plci->sig_global_req = 0;
   plci->sig_remove_id = 0;
   plci->nl_global_req = 0;
   plci->nl_remove_id = 0;
   plci->adv_nl = 0;
-  plci->manufacturer = FALSE;
+  plci->manufacturer = false;
   plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
   plci->spoofed_msg = 0;
   plci->ptyState = 0;
-  plci->cr_enquiry = FALSE;
+  plci->cr_enquiry = false;
   plci->hangup_flow_ctrl_timer = 0;
 
   plci->ncci_ring_list = 0;
@@ -7972,7 +7972,7 @@
 
   if(!bp->length && plci->tel)
   {
-    plci->adv_nl = TRUE;
+    plci->adv_nl = true;
     dbug(1,dprintf("Default adv.Nl"));
     add_p(plci,LLI,lli);
     plci->B2_prot = 1 /*XPARENT*/;
@@ -8022,7 +8022,7 @@
   {  
     if(GET_WORD(bp_parms[1].info)!=1
     || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
-    plci->adv_nl = TRUE;
+    plci->adv_nl = true;
   }
   else if(plci->tel) return _B2_NOT_SUPPORTED;
 
@@ -8840,7 +8840,7 @@
             plci->NL.X = plci->NData;
             plci->NL.ReqCh = a->ncci_ch[ncci];
             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
-            plci->data_sent = TRUE;
+            plci->data_sent = true;
             plci->data_sent_ptr = data->P;
             a->request(&plci->NL);
           }
@@ -8995,10 +8995,10 @@
 byte ie_compare(byte   * ie1, byte * ie2)
 {
   word i;
-  if(!ie1 || ! ie2) return FALSE;
-  if(!ie1[0]) return FALSE;
-  for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return FALSE;
-  return TRUE;
+  if(!ie1 || ! ie2) return false;
+  if(!ie1[0]) return false;
+  for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
+  return true;
 }
 
 word find_cip(DIVA_CAPI_ADAPTER   * a, byte   * bc, byte   * hlc)
@@ -9151,7 +9151,7 @@
         plci->tel=ADV_VOICE;
       }
       a->AdvSignalAppl = appl;
-      a->AdvCodecFLAG = TRUE;
+      a->AdvCodecFLAG = true;
       a->AdvCodecPLCI = splci;
       add_p(splci,CAI,"\x01\x15");
       add_p(splci,LLI,"\x01\x00");
@@ -9183,7 +9183,7 @@
         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
         send_req(splci);
-        a->scom_appl_disable = TRUE;
+        a->scom_appl_disable = true;
       }
       else{
         return 0x2001; /* wrong state, no more plcis */
@@ -9411,7 +9411,7 @@
       }
       if(a->AdvSignalAppl==this)
       {
-        this->NullCREnable = FALSE;
+        this->NullCREnable = false;
         if (a->AdvCodecPLCI)
         {
           plci_remove(a->AdvCodecPLCI);
@@ -9433,7 +9433,7 @@
 
 static word plci_remove_check(PLCI   *plci)
 {
-  if(!plci) return TRUE;
+  if(!plci) return true;
   if(!plci->NL.Id && c_ind_mask_empty (plci))
   {
     if(plci->Sig.Id == 0xff)
@@ -9446,7 +9446,7 @@
       {
         CodecIdCheck(plci->adapter, plci);
         clear_b1_config (plci);
-        ncci_remove (plci, 0, FALSE);
+        ncci_remove (plci, 0, false);
         plci_free_msg_in_queue (plci);
         channel_flow_control_remove (plci);
         plci->Id = 0;
@@ -9456,10 +9456,10 @@
         plci->notifiedcall = 0;
       }
       listen_check(plci->adapter);
-      return TRUE;
+      return true;
     }
   }
-  return FALSE;
+  return false;
 }
 
 
@@ -9564,7 +9564,7 @@
 
 };
 
-#define DTMF_DIGIT_MAP_ENTRIES (sizeof(dtmf_digit_map) / sizeof(dtmf_digit_map[0]))
+#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
 
 
 static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
@@ -9815,7 +9815,7 @@
         }
         plci->dtmf_rec_active &= ~mask;
         plci->internal_command = DTMF_COMMAND_2;
-        dtmf_enable_receiver (plci, FALSE);
+        dtmf_enable_receiver (plci, false);
         return;
       }
       Rc = OK;
@@ -10020,7 +10020,7 @@
           }
         }
         start_internal_command (Id, plci, dtmf_command);
-        return (FALSE);
+        return (false);
 
 
       case DTMF_SEND_TONE:
@@ -10069,8 +10069,7 @@
           PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
           break;
         }
-        if (plci->dtmf_send_requests >=
-          sizeof(plci->dtmf_msg_number_queue) / sizeof(plci->dtmf_msg_number_queue[0]))
+        if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
         {
           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
             UnMapId (Id), (char   *)(FILE_), __LINE__));
@@ -10079,7 +10078,7 @@
         }
         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
         start_internal_command (Id, plci, dtmf_command);
-        return (FALSE);
+        return (false);
 
       default:
         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
@@ -10090,7 +10089,7 @@
   }
   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
     "wws", Info, SELECTOR_DTMF, result);
-  return (FALSE);
+  return (false);
 }
 
 
@@ -10842,10 +10841,10 @@
   byte to_pc;
 } xconnect_write_prog[] =
 {
-  { LI_COEF_CH_CH, FALSE, FALSE },
-  { LI_COEF_CH_PC, FALSE, TRUE },
-  { LI_COEF_PC_CH, TRUE, FALSE },
-  { LI_COEF_PC_PC, TRUE, TRUE }
+  { LI_COEF_CH_CH, false, false },
+  { LI_COEF_CH_PC, false, true },
+  { LI_COEF_PC_CH, true, false },
+  { LI_COEF_PC_PC, true, true }
 };
 
 
@@ -10916,7 +10915,7 @@
   {
     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
       UnMapId (Id), (char   *)(FILE_), __LINE__));
-    return (TRUE);
+    return (true);
   }
   i = a->li_base + (plci->li_bchannel_id - 1);
   j = plci->li_write_channel;
@@ -10927,7 +10926,7 @@
     {
       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
-      return (FALSE);
+      return (false);
     }
   }
   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
@@ -10969,7 +10968,7 @@
     {
       plci->internal_command = plci->li_write_command;
       if (plci_nl_busy (plci))
-        return (TRUE);
+        return (true);
       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
       *(p++) = UDATA_REQUEST_XCONNECT_TO;
       do
@@ -11018,9 +11017,9 @@
             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
           }
           n++;
-        } while ((n < sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
+        } while ((n < ARRAY_SIZE(xconnect_write_prog))
           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
-        if (n == sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
+        if (n == ARRAY_SIZE(xconnect_write_prog))
         {
           do
           {
@@ -11050,7 +11049,7 @@
     {
       plci->internal_command = plci->li_write_command;
       if (plci_nl_busy (plci))
-        return (TRUE);
+        return (true);
       if (a->li_pri)
       {
         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
@@ -11090,7 +11089,7 @@
             ch_map[j+1] = (byte)(j+1);
           }
         }
-        for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
+        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
         {
           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
@@ -11127,7 +11126,7 @@
     {
       plci->internal_command = plci->li_write_command;
       if (plci_nl_busy (plci))
-        return (TRUE);
+        return (true);
       if (j < a->li_base)
         j = a->li_base;
       if (a->li_pri)
@@ -11140,7 +11139,7 @@
           w |= MIXER_FEATURE_ENABLE_RX_DATA;
         *(p++) = (byte) w;
         *(p++) = (byte)(w >> 8);
-        for (n = 0; n < sizeof(mixer_write_prog_pri) / sizeof(mixer_write_prog_pri[0]); n++)
+        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
         {
           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
@@ -11196,7 +11195,7 @@
             ch_map[j+1] = (byte)(j+1);
           }
         }
-        for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
+        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
         {
           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
@@ -11232,7 +11231,7 @@
     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
     plci->adapter->request (&plci->NL);
   }
-  return (TRUE);
+  return (true);
 }
 
 
@@ -11251,7 +11250,7 @@
   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
   {
     if (others)
-      plci->li_notify_update = TRUE;
+      plci->li_notify_update = true;
     i = 0;
     do
     {
@@ -11277,7 +11276,7 @@
        && (notify_plci->State)
        && notify_plci->NL.Id && !notify_plci->nl_remove_id)
       {
-        notify_plci->li_notify_update = TRUE;
+        notify_plci->li_notify_update = true;
         ((CAPI_MSG *) msg)->header.length = 18;
         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
         ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
@@ -11299,12 +11298,12 @@
               (char   *)(FILE_), __LINE__,
               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
           }
-          notify_plci->li_notify_update = FALSE;
+          notify_plci->li_notify_update = false;
         }
       }
     } while (others && (notify_plci != NULL));
     if (others)
-      plci->li_notify_update = FALSE;
+      plci->li_notify_update = false;
   }
 }
 
@@ -11318,7 +11317,7 @@
     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
     (char   *)(FILE_), __LINE__));
 
-  plci->li_notify_update = FALSE;
+  plci->li_notify_update = false;
   plci->li_plci_b_write_pos = 0;
   plci->li_plci_b_read_pos = 0;
   plci->li_plci_b_req_pos = 0;
@@ -12159,7 +12158,7 @@
         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
         if (plci_b == NULL)
           break;
-        li_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
+        li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
         plci->li_plci_b_write_pos = plci_b_write_pos;
@@ -12188,7 +12187,7 @@
         plci_b_write_pos = plci->li_plci_b_write_pos;
         participant_parms_pos = 0;
         result_pos = 7;
-        li2_update_connect (Id, a, plci, UnMapId (Id), TRUE, li_flags);
+        li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
         while (participant_parms_pos < li_req_parms[1].length)
         {
           result[result_pos] = 6;
@@ -12224,7 +12223,7 @@
           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
           if (plci_b != NULL)
           {
-            li2_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
+            li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
@@ -12249,13 +12248,13 @@
       }
       mixer_calculate_coefs (a);
       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
-      mixer_notify_update (plci, TRUE);
+      mixer_notify_update (plci, true);
       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
       plci->command = 0;
       plci->li_cmd = GET_WORD (li_parms[0].info);
       start_internal_command (Id, plci, mixer_command);
-      return (FALSE);
+      return (false);
 
     case LI_REQ_DISCONNECT:
       if (li_parms[1].length == 4)
@@ -12283,7 +12282,7 @@
         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
         if (plci_b == NULL)
           break;
-        li_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
+        li_update_connect (Id, a, plci, plci_b_id, false, 0);
         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
         plci->li_plci_b_write_pos = plci_b_write_pos;
@@ -12345,7 +12344,7 @@
           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
           if (plci_b != NULL)
           {
-            li2_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
+            li2_update_connect (Id, a, plci, plci_b_id, false, 0);
             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
           }
@@ -12368,13 +12367,13 @@
       }
       mixer_calculate_coefs (a);
       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
-      mixer_notify_update (plci, TRUE);
+      mixer_notify_update (plci, true);
       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
       plci->command = 0;
       plci->li_cmd = GET_WORD (li_parms[0].info);
       start_internal_command (Id, plci, mixer_command);
-      return (FALSE);
+      return (false);
 
     case LI_REQ_SILENT_UPDATE:
       if (!plci || !plci->State
@@ -12384,7 +12383,7 @@
       {
         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
           UnMapId (Id), (char   *)(FILE_), __LINE__));
-        return (FALSE);
+        return (false);
       }
       plci_b_write_pos = plci->li_plci_b_write_pos;
       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
@@ -12392,7 +12391,7 @@
       {
         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
           UnMapId (Id), (char   *)(FILE_), __LINE__));
-        return (FALSE);
+        return (false);
       }
       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
       if ((plci_b_write_pos == plci->li_plci_b_read_pos)
@@ -12408,7 +12407,7 @@
       plci->command = 0;
       plci->li_cmd = GET_WORD (li_parms[0].info);
       start_internal_command (Id, plci, mixer_command);
-      return (FALSE);
+      return (false);
 
     default:
       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
@@ -12418,7 +12417,7 @@
   }
   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
-  return (FALSE);
+  return (false);
 }
 
 
@@ -12523,7 +12522,7 @@
     if (!plci->internal_command)
       next_internal_command (Id, plci);
   }
-  mixer_notify_update (plci, TRUE);
+  mixer_notify_update (plci, true);
 }
 
 
@@ -12547,12 +12546,12 @@
     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
       (char   *)(FILE_), __LINE__));
-    return (FALSE);
+    return (false);
   }
   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
   plci->li_plci_b_write_pos = plci_b_write_pos;
-  return (TRUE);
+  return (true);
 }
 
 
@@ -12596,7 +12595,7 @@
         }
         mixer_clear_config (plci);
         mixer_calculate_coefs (a);
-        mixer_notify_update (plci, TRUE);
+        mixer_notify_update (plci, true);
       }
       li_config_table[i].plci = NULL;
       plci->li_bchannel_id = 0;
@@ -12883,29 +12882,29 @@
           case EC_ENABLE_OPERATION:
             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           case EC_DISABLE_OPERATION:
             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
               LEC_RESET_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           case EC_FREEZE_COEFFICIENTS:
             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           case EC_RESUME_COEFFICIENT_UPDATE:
             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           case EC_RESET_COEFFICIENTS:
             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           default:
             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
@@ -12978,14 +12977,14 @@
           case EC_ENABLE_OPERATION:
             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           case EC_DISABLE_OPERATION:
             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
               LEC_RESET_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           default:
             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
@@ -12999,7 +12998,7 @@
   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
-  return (FALSE);
+  return (false);
 }
 
 
@@ -13178,7 +13177,7 @@
         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
       }
-      for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
+      for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
       {
         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
@@ -13563,7 +13562,7 @@
     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
     (char   *)(FILE_), __LINE__));
 
-  plci->adjust_b_restore = FALSE;
+  plci->adjust_b_restore = false;
 }
 
 
@@ -13832,7 +13831,7 @@
     }
     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
     {
-      plci->adjust_b_restore = TRUE;
+      plci->adjust_b_restore = true;
       break;
     }
     plci->adjust_b_state = ADJUST_B_CONNECT_1;
@@ -14603,7 +14602,7 @@
 
 static void channel_xmit_extended_xon (PLCI   * plci) {
   DIVA_CAPI_ADAPTER   * a;
-  int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
+  int max_ch = ARRAY_SIZE(a->ch_flow_control);
   int i, one_requested = 0;
 
   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
@@ -14628,7 +14627,7 @@
   Try to xmit next X_ON
   */
 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
-  int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
+  int max_ch = ARRAY_SIZE(a->ch_flow_control);
   int i;
 
   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
@@ -14768,19 +14767,19 @@
   {
     if(application[i].Id && a->CIP_Mask[i] )
     {
-      for(k=0,busy=FALSE; k<a->max_plci; k++)
+      for(k=0,busy=false; k<a->max_plci; k++)
       {
         if(a->plci[k].Id) 
         {
           auxplci = &a->plci[k];
           if(auxplci->appl == &application[i]) /* application has a busy PLCI */
           {
-            busy = TRUE;
+            busy = true;
             dbug(1,dprintf("Appl 0x%x is busy",i+1));
           }
           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
           {
-            busy = TRUE;
+            busy = true;
             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
           }
         }
@@ -14791,13 +14790,13 @@
         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
           appl_number_group_type[i] = MAX_CIP_TYPES;
-          group_found=TRUE;
+          group_found=true;
           dbug(1,dprintf("Field overflow appl 0x%x",i+1));
         }
         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
         {                                      /* is group already present ?                  */
           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
-          group_found=TRUE;
+          group_found=true;
           dbug(1,dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
         }
         else if(!info_mask_group[j])
@@ -14805,7 +14804,7 @@
           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
-          group_found=TRUE;
+          group_found=true;
           dbug(1,dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
         }
       }
@@ -14860,7 +14859,7 @@
     }
   }
 
-  if(appls_found) return TRUE;
+  if(appls_found) return true;
   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
   {
     a = &adapter[i];
@@ -14889,7 +14888,7 @@
       }
     }
   }
-  return FALSE;
+  return false;
 }
 
 /*------------------------------------------------------------------*/
diff --git a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c
index a296a84..9033565 100644
--- a/drivers/isdn/hardware/eicon/os_pri.c
+++ b/drivers/isdn/hardware/eicon/os_pri.c
@@ -487,7 +487,7 @@
 	}
 	DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
 
-	IoAdapter->Initialized = TRUE;
+	IoAdapter->Initialized = true;
 
 	/*
 	   Check Interrupt
@@ -504,7 +504,7 @@
 	if (!IoAdapter->IrqCount) {
 		DBG_ERR(("A: A(%d) interrupt test failed",
 			 IoAdapter->ANum))
-		IoAdapter->Initialized = FALSE;
+		IoAdapter->Initialized = false;
 		IoAdapter->stop(IoAdapter);
 		return (-1);
 	}
diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h
index 2444811..ff09f07 100644
--- a/drivers/isdn/hardware/eicon/platform.h
+++ b/drivers/isdn/hardware/eicon/platform.h
@@ -71,14 +71,6 @@
 #define	qword  u64
 #endif
 
-#ifndef	TRUE
-#define	TRUE	1
-#endif
-
-#ifndef	FALSE
-#define	FALSE	0
-#endif
-
 #ifndef	NULL
 #define	NULL	((void *) 0)
 #endif
@@ -131,10 +123,6 @@
 #define DIVA_OS_MEM_DETACH_CONFIG(a, x)	do { } while(0)
 #define DIVA_OS_MEM_DETACH_CONTROL(a, x)	do { } while(0)
 
-#if !defined(DIM)
-#define DIM(array)  (sizeof (array)/sizeof ((array)[0]))
-#endif
-
 #define DIVA_INVALID_FILE_HANDLE  ((dword)(-1))
 
 #define DIVAS_CONTAINING_RECORD(address, type, field) \
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index 34ab5f7..12d91fb 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -340,8 +340,6 @@
 	  This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA
 	  cards. This code is not finished yet.
 
-#      bool '  TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
-
 config HISAX_ENTERNOW_PCI
 	bool "Formula-n enter:now PCI card"
 	depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index 293e277..c7a3794 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -60,5 +60,4 @@
 hisax-$(CONFIG_HISAX_GAZEL)		+= gazel.o isac.o arcofi.o hscx.o
 hisax-$(CONFIG_HISAX_W6692)		+= w6692.o
 hisax-$(CONFIG_HISAX_ENTERNOW_PCI)	+= enternow_pci.o amd7930_fn.o
-#hisax-$(CONFIG_HISAX_TESTEMU)		+= testemu.o
 
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 9e70c20..fc6cc2c 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -14,7 +14,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 17ec0b7..da4196f2 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -549,10 +549,6 @@
 extern int setup_saphir(struct IsdnCard *card);
 #endif
 
-#if CARD_TESTEMU
-extern int setup_testemu(struct IsdnCard *card);
-#endif
-
 #if CARD_BKM_A4T
 extern int setup_bkm_a4t(struct IsdnCard *card);
 #endif
@@ -1061,11 +1057,6 @@
 		ret = setup_saphir(card);
 		break;
 #endif
-#if CARD_TESTEMU
-	case ISDN_CTYPE_TESTEMU:
-		ret = setup_testemu(card);
-		break;
-#endif
 #if	CARD_BKM_A4T
 	case ISDN_CTYPE_BKM_A4T:
 		ret = setup_bkm_a4t(card);
@@ -1881,7 +1872,7 @@
 	{PCI_VENDOR_ID_PLX,      PCI_DEVICE_ID_PLX_DJINN_ITOO,   PCI_ANY_ID, PCI_ANY_ID},
 	{PCI_VENDOR_ID_PLX,      PCI_DEVICE_ID_PLX_OLITEC,       PCI_ANY_ID, PCI_ANY_ID},
 #endif
-#ifdef CONFIG_HISAX_QUADRO
+#ifdef CONFIG_HISAX_SCT_QUADRO
 	{PCI_VENDOR_ID_PLX,      PCI_DEVICE_ID_PLX_9050,         PCI_ANY_ID, PCI_ANY_ID},
 #endif
 #ifdef CONFIG_HISAX_NICCY
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 79ab9dd..db7e644 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -38,7 +38,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
index 0279fb3..ae377e8 100644
--- a/drivers/isdn/hisax/elsa_ser.c
+++ b/drivers/isdn/hisax/elsa_ser.c
@@ -58,7 +58,7 @@
 static inline unsigned int serial_inp(struct IsdnCardState *cs, int offset)
 {
 #ifdef SERIAL_DEBUG_REG
-#ifdef CONFIG_SERIAL_NOPAUSE_IO
+#ifdef ELSA_SERIAL_NOPAUSE_IO
 	u_int val = inb(cs->hw.elsa.base + 8 + offset);
 	debugl1(cs,"inp  %s %02x",ModemIn[offset], val);
 #else
@@ -67,7 +67,7 @@
 #endif
 	return(val);
 #else
-#ifdef CONFIG_SERIAL_NOPAUSE_IO
+#ifdef ELSA_SERIAL_NOPAUSE_IO
 	return inb(cs->hw.elsa.base + 8 + offset);
 #else
 	return inb_p(cs->hw.elsa.base + 8 + offset);
@@ -87,13 +87,13 @@
 			       int value)
 {
 #ifdef SERIAL_DEBUG_REG
-#ifdef CONFIG_SERIAL_NOPAUSE_IO
+#ifdef ELSA_SERIAL_NOPAUSE_IO
 	debugl1(cs,"outp %s %02x",ModemOut[offset], value);
 #else
 	debugl1(cs,"outP %s %02x",ModemOut[offset], value);
 #endif
 #endif
-#ifdef CONFIG_SERIAL_NOPAUSE_IO
+#ifdef ELSA_SERIAL_NOPAUSE_IO
 	outb(value, cs->hw.elsa.base + 8 + offset);
 #else
     	outb_p(value, cs->hw.elsa.base + 8 + offset);
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index a2fa4ec..ab98e13 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -199,7 +199,7 @@
 /***************************/
 /* inline function defines */
 /***************************/
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM	/* inline functions mempry mapped */
+#ifdef HISAX_HFC4S8S_PCIMEM	/* inline functions memory mapped */
 
 /* memory write and dummy IO read to avoid PCI byte merge problems */
 #define Write_hfc8(a,b,c) {(*((volatile u_char *)(a->membase+b)) = c); inb(a->iobase+4);}
@@ -305,7 +305,7 @@
 
 #define PCI_ENA_REGIO	0x01
 
-#endif				/* CONFIG_HISAX_HFC4S8S_PCIMEM */
+#endif				/* HISAX_HFC4S8S_PCIMEM */
 
 /******************************************************/
 /* function to read critical counter registers that   */
@@ -724,12 +724,12 @@
 			} else {
 				/* read errornous D frame */
 
-#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef HISAX_HFC4S8S_PCIMEM
 				SetRegAddr(l1p->hw, A_FIFO_DATA0);
 #endif
 
 				while (z1 >= 4) {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 					Read_hfc32(l1p->hw, A_FIFO_DATA0);
 #else
 					fRead_hfc32(l1p->hw);
@@ -738,7 +738,7 @@
 				}
 
 				while (z1--)
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 					Read_hfc8(l1p->hw, A_FIFO_DATA0);
 #else
 					fRead_hfc8(l1p->hw);
@@ -752,12 +752,12 @@
 
 		cp = skb->data;
 
-#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef HISAX_HFC4S8S_PCIMEM
 		SetRegAddr(l1p->hw, A_FIFO_DATA0);
 #endif
 
 		while (z1 >= 4) {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			*((unsigned long *) cp) =
 			    Read_hfc32(l1p->hw, A_FIFO_DATA0);
 #else
@@ -768,7 +768,7 @@
 		}
 
 		while (z1--)
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			*cp++ = Read_hfc8(l1p->hw, A_FIFO_DATA0);
 #else
 			*cp++ = fRead_hfc8(l1p->hw);
@@ -858,12 +858,12 @@
 			wait_busy(l1->hw);
 			return;
 		}
-#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef HISAX_HFC4S8S_PCIMEM
 		SetRegAddr(l1->hw, A_FIFO_DATA0);
 #endif
 
 		while (z1 >= 4) {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			*((unsigned long *) bch->rx_ptr) =
 			    Read_hfc32(l1->hw, A_FIFO_DATA0);
 #else
@@ -875,7 +875,7 @@
 		}
 
 		while (z1--)
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			*(bch->rx_ptr++) = Read_hfc8(l1->hw, A_FIFO_DATA0);
 #else
 			*(bch->rx_ptr++) = fRead_hfc8(l1->hw);
@@ -939,12 +939,12 @@
 	if ((skb = skb_dequeue(&l1p->d_tx_queue))) {
 		cp = skb->data;
 		cnt = skb->len;
-#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef HISAX_HFC4S8S_PCIMEM
 		SetRegAddr(l1p->hw, A_FIFO_DATA0);
 #endif
 
 		while (cnt >= 4) {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			fWrite_hfc32(l1p->hw, A_FIFO_DATA0,
 				     *(unsigned long *) cp);
 #else
@@ -955,7 +955,7 @@
 			cnt -= 4;
 		}
 
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 		while (cnt--)
 			fWrite_hfc8(l1p->hw, A_FIFO_DATA0, *cp++);
 #else
@@ -1036,11 +1036,11 @@
 		cp = skb->data + bch->tx_cnt;
 		bch->tx_cnt += cnt;
 
-#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef HISAX_HFC4S8S_PCIMEM
 		SetRegAddr(l1->hw, A_FIFO_DATA0);
 #endif
 		while (cnt >= 4) {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			fWrite_hfc32(l1->hw, A_FIFO_DATA0,
 				     *(unsigned long *) cp);
 #else
@@ -1051,7 +1051,7 @@
 		}
 
 		while (cnt--)
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			fWrite_hfc8(l1->hw, A_FIFO_DATA0, *cp++);
 #else
 			fWrite_hfc8(l1->hw, *cp++);
@@ -1280,7 +1280,7 @@
 	if (!hw || !(hw->mr.r_irq_ctrl & M_GLOB_IRQ_EN))
 		return IRQ_NONE;
 
-#ifndef	CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef	HISAX_HFC4S8S_PCIMEM
 	/* read current selected regsister */
 	old_ioreg = GetRegAddr(hw);
 #endif
@@ -1291,7 +1291,7 @@
 	if (!
 	    (b = (Read_hfc8(hw, R_STATUS) & (M_MISC_IRQSTA | M_FR_IRQSTA)))
 && !hw->mr.r_irq_statech) {
-#ifndef	CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef	HISAX_HFC4S8S_PCIMEM
 		SetRegAddr(hw, old_ioreg);
 #endif
 		return IRQ_NONE;
@@ -1321,7 +1321,7 @@
 	/* queue the request to allow other cards to interrupt */
 	schedule_work(&hw->tqueue);
 
-#ifndef	CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef	HISAX_HFC4S8S_PCIMEM
 	SetRegAddr(hw, old_ioreg);
 #endif
 	return IRQ_HANDLED;
@@ -1470,7 +1470,7 @@
 release_pci_ports(hfc4s8s_hw * hw)
 {
 	pci_write_config_word(hw->pdev, PCI_COMMAND, 0);
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 	if (hw->membase)
 		iounmap((void *) hw->membase);
 #else
@@ -1485,7 +1485,7 @@
 static void
 enable_pci_ports(hfc4s8s_hw * hw)
 {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 	pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_MEMIO);
 #else
 	pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_REGIO);
@@ -1560,7 +1560,7 @@
 		       hw->irq);
 		goto out;
 	}
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 	printk(KERN_INFO
 	       "HFC-4S/8S: found PCI card at membase 0x%p, irq %d\n",
 	       hw->hw_membase, hw->irq);
@@ -1613,7 +1613,7 @@
 	hw->irq = pdev->irq;
 	hw->iobase = pci_resource_start(pdev, 0);
 
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 	hw->hw_membase = (u_char *) pci_resource_start(pdev, 1);
 	hw->membase = ioremap((ulong) hw->hw_membase, 256);
 #else
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index 5a6989f..9f44d3e 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -38,7 +38,6 @@
 #include <linux/usb.h>
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
-#include <linux/sched.h>
 #include "hisax.h"
 #include "hisax_if.h"
 #include "hfc_usb.h"
@@ -183,7 +182,7 @@
 	int vend_idx;		/* vendor found */
 	int b_mode[2];		/* B-channel mode */
 	int l1_activated;	/* layer 1 activated */
-	int disc_flag;		/* TRUE if device was disonnected to avoid some USB actions */
+	int disc_flag;		/* 'true' if device was disonnected to avoid some USB actions */
 	int packet_size, iso_packet_size;
 
 	/* control pipe background handling */
@@ -392,7 +391,7 @@
 	DBG(ISDN_DBG,
 	    "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T3 expire)");
 #endif
-	hfc->l1_activated = FALSE;
+	hfc->l1_activated = false;
 	handle_led(hfc, LED_S0_OFF);
 	/* deactivate : */
 	queue_control_request(hfc, HFCUSB_STATES, 0x10, 1);
@@ -411,7 +410,7 @@
 	DBG(ISDN_DBG,
 	    "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T4 expire)");
 #endif
-	hfc->l1_activated = FALSE;
+	hfc->l1_activated = false;
 	handle_led(hfc, LED_S0_OFF);
 }
 
@@ -452,7 +451,7 @@
 #ifdef CONFIG_HISAX_DEBUG
 		DBG(ISDN_DBG, "HFC-S USB: PH_ACTIVATE | INDICATION sent");
 #endif
-		hfc->l1_activated = TRUE;
+		hfc->l1_activated = true;
 		handle_led(hfc, LED_S0_ON);
 	} else if (state <= 3 /* && activated */ ) {
 		if (old_state == 7 || old_state == 8) {
@@ -472,7 +471,7 @@
 			DBG(ISDN_DBG,
 			    "HFC-S USB: PH_DEACTIVATE | INDICATION sent");
 #endif
-			hfc->l1_activated = FALSE;
+			hfc->l1_activated = false;
 			handle_led(hfc, LED_S0_OFF);
 		}
 	}
@@ -622,7 +621,7 @@
 	if (fifo->active && !status) {
 		transp_mode = 0;
 		if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
-			transp_mode = TRUE;
+			transp_mode = true;
 
 		/* is FifoFull-threshold set for our channel? */
 		threshbit = threshtable[fifon] & hfc->threshold_mask;
@@ -640,7 +639,7 @@
 			      tx_iso_complete, urb->context);
 		memset(context_iso_urb->buffer, 0,
 		       sizeof(context_iso_urb->buffer));
-		frame_complete = FALSE;
+		frame_complete = false;
 		/* Generate next Iso Packets */
 		for (k = 0; k < num_isoc_packets; ++k) {
 			if (fifo->skbuff) {
@@ -666,7 +665,7 @@
 						/* add 2 byte flags and 16bit CRC at end of ISDN frame */
 						fifo->bit_line += 32;
 					}
-					frame_complete = TRUE;
+					frame_complete = true;
 				}
 
 				memcpy(context_iso_urb->buffer +
@@ -693,7 +692,7 @@
 			}
 
 			if (frame_complete) {
-				fifo->delete_flg = TRUE;
+				fifo->delete_flg = true;
 				fifo->hif->l1l2(fifo->hif,
 						PH_DATA | CONFIRM,
 						(void *) (unsigned long) fifo->skbuff->
@@ -701,9 +700,9 @@
 				if (fifo->skbuff && fifo->delete_flg) {
 					dev_kfree_skb_any(fifo->skbuff);
 					fifo->skbuff = NULL;
-					fifo->delete_flg = FALSE;
+					fifo->delete_flg = false;
 				}
-				frame_complete = FALSE;
+				frame_complete = false;
 			}
 		}
 		errcode = usb_submit_urb(urb, GFP_ATOMIC);
@@ -837,7 +836,7 @@
 	fifon = fifo->fifonum;
 	transp_mode = 0;
 	if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
-		transp_mode = TRUE;
+		transp_mode = true;
 
 	if (!fifo->skbuff) {
 		fifo->skbuff = dev_alloc_skb(fifo->max_size + 3);
@@ -1176,7 +1175,7 @@
 			if (fifo->skbuff && fifo->delete_flg) {
 				dev_kfree_skb_any(fifo->skbuff);
 				fifo->skbuff = NULL;
-				fifo->delete_flg = FALSE;
+				fifo->delete_flg = false;
 			}
 			fifo->skbuff = arg;	/* we have a new buffer */
 			break;
@@ -1262,8 +1261,8 @@
 	hfc->b_mode[0] = L1_MODE_NULL;
 	hfc->b_mode[1] = L1_MODE_NULL;
 
-	hfc->l1_activated = FALSE;
-	hfc->disc_flag = FALSE;
+	hfc->l1_activated = false;
+	hfc->disc_flag = false;
 	hfc->led_state = 0;
 	hfc->led_new_data = 0;
 	hfc->old_led_state = 0;
@@ -1404,7 +1403,7 @@
 
 			/* check for config EOL element */
 			while (validconf[cfg_used][0]) {
-				cfg_found = TRUE;
+				cfg_found = true;
 				vcf = validconf[cfg_used];
 				/* first endpoint descriptor */
 				ep = iface->endpoint;
@@ -1426,7 +1425,7 @@
 						idx++;
 					attr = ep->desc.bmAttributes;
 					if (cmptbl[idx] == EP_NUL) {
-						cfg_found = FALSE;
+						cfg_found = false;
 					}
 					if (attr == USB_ENDPOINT_XFER_INT
 					    && cmptbl[idx] == EP_INT)
@@ -1448,7 +1447,7 @@
 							    "HFC-S USB: Interrupt Endpoint interval < %d found - skipping config",
 							    vcf[17]);
 #endif
-						cfg_found = FALSE;
+						cfg_found = false;
 					}
 					ep++;
 				}
@@ -1456,7 +1455,7 @@
 					/* all entries must be EP_NOP or EP_NUL for a valid config */
 					if (cmptbl[i] != EP_NOP
 					    && cmptbl[i] != EP_NUL)
-						cfg_found = FALSE;
+						cfg_found = false;
 				}
 				if (cfg_found) {
 					if (cfg_used < small_match) {
@@ -1656,7 +1655,7 @@
 	hfcusb_data *context = usb_get_intfdata(intf);
 	int i;
 	printk(KERN_INFO "HFC-S USB: device disconnect\n");
-	context->disc_flag = TRUE;
+	context->disc_flag = true;
 	usb_set_intfdata(intf, NULL);
 	if (!context)
 		return;
diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h
index 6349367..471f235 100644
--- a/drivers/isdn/hisax/hfc_usb.h
+++ b/drivers/isdn/hisax/hfc_usb.h
@@ -12,9 +12,6 @@
 
 #define VERBOSE_USB_DEBUG
 
-#define TRUE  1
-#define FALSE 0
-
 
 /***********/
 /* defines */
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 3f1137e..3cd8d5b 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -795,19 +795,6 @@
 	struct timer_list timer;
 };
 
-#ifdef  CONFIG_HISAX_TESTEMU
-struct te_hw {
-	unsigned char *sfifo;
-	unsigned char *sfifo_w;
-	unsigned char *sfifo_r;
-	unsigned char *sfifo_e;
-	int sfifo_cnt;
-	unsigned int stat;
-	wait_queue_head_t rwaitq;
-	wait_queue_head_t swaitq;
-};
-#endif
-
 struct arcofi_msg {
 	struct arcofi_msg *next;
 	u_char receive;
@@ -916,9 +903,6 @@
 		struct ix1_hw niccy;
 		struct isurf_hw isurf;
 		struct saphir_hw saphir;
-#ifdef CONFIG_HISAX_TESTEMU
-		struct te_hw te;
-#endif
 		struct bkm_hw ax;
 		struct gazel_hw gazel;
 		struct w6692_hw w6692;
@@ -1175,15 +1159,6 @@
 #define CARD_HSTSAPHIR 0
 #endif
 
-#ifdef	CONFIG_HISAX_TESTEMU
-#define	CARD_TESTEMU 1
-#define ISDN_CTYPE_TESTEMU 99
-#undef ISDN_CTYPE_COUNT
-#define  ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU
-#else
-#define CARD_TESTEMU 0
-#endif
-
 #ifdef	CONFIG_HISAX_BKM_A4T
 #define	CARD_BKM_A4T 1
 #ifndef ISDN_CHIP_ISAC
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index 6f1a658..9df9e35 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -431,7 +431,6 @@
 	return(ret);
 }
 
-extern void BChannel_bh(struct BCState *);
 #define B_LL_NOCARRIER	8
 #define B_LL_CONNECT	9
 #define B_LL_OK		10
diff --git a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h
index 0e88cfa..172ad4c 100644
--- a/drivers/isdn/hisax/isdnl1.h
+++ b/drivers/isdn/hisax/isdnl1.h
@@ -21,12 +21,11 @@
 #define B_XMTBUFREADY	1
 #define B_ACKPENDING	2
 
-extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
-extern void DChannel_proc_xmt(struct IsdnCardState *cs);
-extern void DChannel_proc_rcv(struct IsdnCardState *cs);
-extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
-extern void l1_msg_b(struct PStack *st, int pr, void *arg);
-
-#ifdef L2FRAME_DEBUG
-extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
-#endif
+void debugl1(struct IsdnCardState *cs, char *fmt, ...);
+void DChannel_proc_xmt(struct IsdnCardState *cs);
+void DChannel_proc_rcv(struct IsdnCardState *cs);
+void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
+void l1_msg_b(struct PStack *st, int pr, void *arg);
+void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf,
+		int dir);
+void BChannel_bh(struct work_struct *work);
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index 281fa27..935f233 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -231,18 +231,6 @@
 	return(-1);
 }
 
-#ifdef	CONFIG_HISAX_EURO
-extern void setstack_dss1(struct PStack *st);
-#endif
-
-#ifdef  CONFIG_HISAX_NI1
-extern void setstack_ni1(struct PStack *st);
-#endif
-
-#ifdef	CONFIG_HISAX_1TR6
-extern void setstack_1tr6(struct PStack *st);
-#endif
-
 struct l3_process
 *getl3proc(struct PStack *st, int cr)
 {
diff --git a/drivers/isdn/hisax/isdnl3.h b/drivers/isdn/hisax/isdnl3.h
index 1dbe029..749498f 100644
--- a/drivers/isdn/hisax/isdnl3.h
+++ b/drivers/isdn/hisax/isdnl3.h
@@ -25,13 +25,19 @@
 
 #define l3_debug(st, fmt, args...) HiSax_putstatus(st->l1.hardware, "l3 ", fmt, ## args)
 
-extern void newl3state(struct l3_process *pc, int state);
-extern void L3InitTimer(struct l3_process *pc, struct L3Timer *t);
-extern void L3DelTimer(struct L3Timer *t);
-extern int L3AddTimer(struct L3Timer *t, int millisec, int event);
-extern void StopAllL3Timer(struct l3_process *pc);
-extern struct sk_buff *l3_alloc_skb(int len);
-extern struct l3_process *new_l3_process(struct PStack *st, int cr);
-extern void release_l3_process(struct l3_process *p);
-extern struct l3_process *getl3proc(struct PStack *st, int cr);
-extern void l3_msg(struct PStack *st, int pr, void *arg);
+struct PStack;
+
+void newl3state(struct l3_process *pc, int state);
+void L3InitTimer(struct l3_process *pc, struct L3Timer *t);
+void L3DelTimer(struct L3Timer *t);
+int L3AddTimer(struct L3Timer *t, int millisec, int event);
+void StopAllL3Timer(struct l3_process *pc);
+struct sk_buff *l3_alloc_skb(int len);
+struct l3_process *new_l3_process(struct PStack *st, int cr);
+void release_l3_process(struct l3_process *p);
+struct l3_process *getl3proc(struct PStack *st, int cr);
+void l3_msg(struct PStack *st, int pr, void *arg);
+void setstack_dss1(struct PStack *st);
+void setstack_ni1(struct PStack *st);
+void setstack_1tr6(struct PStack *st);
+
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 45debde..439cb53 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -38,7 +38,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 3e3e182..ab4bd45 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c
index a1206498..84dccd5 100644
--- a/drivers/isdn/hysdn/boardergo.c
+++ b/drivers/isdn/hysdn/boardergo.c
@@ -14,7 +14,6 @@
  *
  */
 
-#include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 94a93508..dc477e0 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -367,7 +367,7 @@
 /******************************************************/
 /* table for conf filesystem functions defined above. */
 /******************************************************/
-static struct file_operations conf_fops =
+static const struct file_operations conf_fops =
 {
 	.llseek         = no_llseek,
 	.read           = hysdn_conf_read,
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index 375d956..f7e83a8 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -383,7 +383,7 @@
 /**************************************************/
 /* table for log filesystem functions defined above. */
 /**************************************************/
-static struct file_operations log_fops =
+static const struct file_operations log_fops =
 {
 	.llseek         = no_llseek,
 	.read           = hysdn_log_read,
diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c
index 1875877..b7b5aa4 100644
--- a/drivers/isdn/hysdn/hysdn_sched.c
+++ b/drivers/isdn/hysdn/hysdn_sched.c
@@ -11,7 +11,6 @@
  *
  */
 
-#include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
index a20f33b..90a2379 100644
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -56,7 +56,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 6a2ef0a..9c926e4 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1822,7 +1822,7 @@
 	return 0;
 }
 
-static struct file_operations isdn_fops =
+static const struct file_operations isdn_fops =
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 4e3f127..1b2df80 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -1680,7 +1680,7 @@
 	 * - we hit a gap in the sequence, so no reassembly/processing is 
 	 *   possible ('start' would be set to NULL)
 	 *
-	 * algorightm for this code is derived from code in the book
+	 * algorithm for this code is derived from code in the book
 	 * 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
 	 */
   	while (start != NULL || newfrag != NULL) {
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index fc80afe..ea5f30d 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1261,7 +1261,6 @@
 	}
 	isdn_tty_cleanup_xmit(info);
 	info->xmit_count = 0;
-	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
 }
 
diff --git a/drivers/isdn/pcbit/callbacks.c b/drivers/isdn/pcbit/callbacks.c
index f151f36..43ecd0f 100644
--- a/drivers/isdn/pcbit/callbacks.c
+++ b/drivers/isdn/pcbit/callbacks.c
@@ -15,7 +15,6 @@
  * NULL pointer dereference in cb_in_1 (originally fixed in 2.0)
  */
 
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 
diff --git a/drivers/isdn/pcbit/capi.c b/drivers/isdn/pcbit/capi.c
index bef321d0..47c59e9 100644
--- a/drivers/isdn/pcbit/capi.c
+++ b/drivers/isdn/pcbit/capi.c
@@ -27,7 +27,6 @@
  *              encode our number in CallerPN and ConnectedPN
  */
 
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index 11c1b0b..8c66bcb 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -19,7 +19,6 @@
 
 #include <linux/module.h>
 
-#include <linux/sched.h>
 
 #include <linux/kernel.h>
 
@@ -774,10 +773,6 @@
 	dev->dev_if->statcallb(&ictl);
 }
 	
-extern char * isdn_state_table[];
-extern char * strisdnevent(unsigned short);
-
-
 void pcbit_state_change(struct pcbit_dev * dev, struct pcbit_chan * chan, 
 			unsigned short i, unsigned short ev, unsigned short f)
 {
diff --git a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c
index 93ca7de..37e9626 100644
--- a/drivers/isdn/pcbit/edss1.c
+++ b/drivers/isdn/pcbit/edss1.c
@@ -15,7 +15,6 @@
  *              move state/event descriptions to a user space logger
  */
 
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 
@@ -35,12 +34,6 @@
 #include "callbacks.h"
 
 
-extern void pcbit_state_change(struct pcbit_dev *, struct pcbit_chan *, 
-                               unsigned short i, unsigned short ev, 
-                               unsigned short f);
-
-extern struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS];
-
 char * isdn_state_table[] = {
   "Closed",
   "Call initiated",
diff --git a/drivers/isdn/pcbit/edss1.h b/drivers/isdn/pcbit/edss1.h
index 6bb5870..0b64f97 100644
--- a/drivers/isdn/pcbit/edss1.h
+++ b/drivers/isdn/pcbit/edss1.h
@@ -90,9 +90,12 @@
 	unsigned long timeout;          /* in seconds */
 };
 
+extern char * isdn_state_table[];
 
-extern void pcbit_fsm_event(struct pcbit_dev *, struct pcbit_chan *,
-			    unsigned short event, struct callb_data *);
+void pcbit_fsm_event(struct pcbit_dev *, struct pcbit_chan *,
+		     unsigned short event, struct callb_data *);
+char * strisdnevent(ushort ev);
+
 #endif
 
 
diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c
index eafcce5..5ba2a87 100644
--- a/drivers/isdn/pcbit/layer2.c
+++ b/drivers/isdn/pcbit/layer2.c
@@ -24,7 +24,6 @@
  *              re-write/remove debug printks
  */
 
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -47,22 +46,6 @@
 #undef DEBUG_FRAG
 
 
-
-/*
- *  task queue struct
- */
-
-
-
-/*
- *  Layer 3 packet demultiplexer
- *  drv.c
- */
-
-extern void pcbit_l3_receive(struct pcbit_dev *dev, ulong msg,
-			     struct sk_buff *skb,
-			     ushort hdr_len, ushort refnum);
-
 /*
  *  Prototypes
  */
diff --git a/drivers/isdn/pcbit/module.c b/drivers/isdn/pcbit/module.c
index 282073a..04ea241 100644
--- a/drivers/isdn/pcbit/module.c
+++ b/drivers/isdn/pcbit/module.c
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
@@ -32,9 +31,6 @@
 static int num_boards;
 struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS];
 
-extern void pcbit_terminate(int board);
-extern int pcbit_init_dev(int board, int mem_base, int irq);
-
 static int __init pcbit_init(void)
 {
 	int board;
diff --git a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h
index 19c18e8..d76fffc 100644
--- a/drivers/isdn/pcbit/pcbit.h
+++ b/drivers/isdn/pcbit/pcbit.h
@@ -166,6 +166,12 @@
 #define L2_RUNNING  5
 #define L2_ERROR    6
 
-extern void pcbit_deliver(struct work_struct *work);
+void pcbit_deliver(struct work_struct *work);
+int pcbit_init_dev(int board, int mem_base, int irq);
+void pcbit_terminate(int board);
+void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg, struct sk_buff * skb,
+		      ushort hdr_len, ushort refnum);
+void pcbit_state_change(struct pcbit_dev * dev, struct pcbit_chan * chan,
+			unsigned short i, unsigned short ev, unsigned short f);
 
 #endif
diff --git a/drivers/isdn/sc/card.h b/drivers/isdn/sc/card.h
index 8e44928..4fbfa82 100644
--- a/drivers/isdn/sc/card.h
+++ b/drivers/isdn/sc/card.h
@@ -26,7 +26,9 @@
 #include <linux/timer.h>
 #include <linux/time.h>
 #include <linux/isdnif.h>
+#include <linux/irqreturn.h>
 #include "message.h"
+#include "scioc.h"
 
 /*
  * Amount of time to wait for a reset to complete
@@ -98,4 +100,32 @@
 	spinlock_t lock;		/* local lock */
 } board;
 
+
+extern board *sc_adapter[];
+extern int cinst;
+
+void memcpy_toshmem(int card, void *dest, const void *src, size_t n);
+void memcpy_fromshmem(int card, void *dest, const void *src, size_t n);
+int get_card_from_id(int driver);
+int indicate_status(int card, int event, ulong Channel, char *Data);
+irqreturn_t interrupt_handler(int interrupt, void *cardptr);
+int sndpkt(int devId, int channel, struct sk_buff *data);
+void rcvpkt(int card, RspMessage *rcvmsg);
+int command(isdn_ctrl *cmd);
+int reset(int card);
+int startproc(int card);
+int send_and_receive(int card, unsigned int procid, unsigned char type,
+		     unsigned char class, unsigned char code,
+		     unsigned char link, unsigned char data_len,
+		     unsigned char *data,  RspMessage *mesgdata, int timeout);
+void flushreadfifo (int card);
+int sendmessage(int card, unsigned int procid, unsigned int type,
+		unsigned int class, unsigned int code, unsigned int link,
+		unsigned int data_len, unsigned int *data);
+int receivemessage(int card, RspMessage *rspmsg);
+int sc_ioctl(int card, scs_ioctl *data);
+int setup_buffers(int card, int c);
+void check_reset(unsigned long data);
+void check_phystat(unsigned long data);
+
 #endif /* CARD_H */
diff --git a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c
index 04b8a58..b7bb7cb 100644
--- a/drivers/isdn/sc/command.c
+++ b/drivers/isdn/sc/command.c
@@ -31,19 +31,6 @@
 static int setl3(int card, unsigned long arg);
 static int acceptb(int card, unsigned long channel);
 
-extern int cinst;
-extern board *sc_adapter[];
-
-extern int sc_ioctl(int, scs_ioctl *);
-extern int setup_buffers(int, int, unsigned int);
-extern int indicate_status(int, int,ulong,char*);
-extern void check_reset(unsigned long);
-extern int send_and_receive(int, unsigned int, unsigned char, unsigned char,
-                unsigned char, unsigned char, unsigned char, unsigned char *,
-                RspMessage *, int);
-extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
-                unsigned int, unsigned int, unsigned int, unsigned int *);
-
 #ifdef DEBUG
 /*
  * Translate command codes to strings
@@ -208,7 +195,7 @@
 		return -ENODEV;
 	}
 
-	if(setup_buffers(card, channel+1, BUFFER_SIZE)) {
+	if(setup_buffers(card, channel+1)) {
 		hangup(card, channel+1);
 		return -ENOBUFS;
 	}
@@ -297,7 +284,7 @@
 		return -ENODEV;
 	}
 
-	if(setup_buffers(card, channel+1, BUFFER_SIZE))
+	if(setup_buffers(card, channel+1))
 	{
 		hangup(card, channel+1);
 		return -ENOBUFS;
diff --git a/drivers/isdn/sc/event.c b/drivers/isdn/sc/event.c
index 5736732..498f403 100644
--- a/drivers/isdn/sc/event.c
+++ b/drivers/isdn/sc/event.c
@@ -20,9 +20,6 @@
 #include "message.h"
 #include "card.h"
 
-extern int cinst;
-extern board *sc_adapter[];
-
 #ifdef DEBUG
 static char *events[] = { "ISDN_STAT_STAVAIL",
 			  "ISDN_STAT_ICALL",
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 150759a..0bf7634 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -35,12 +35,6 @@
 module_param_array(ram, int, NULL, 0);
 module_param(do_reset, bool, 0);
 
-extern irqreturn_t interrupt_handler(int, void *);
-extern int sndpkt(int, int, int, struct sk_buff *);
-extern int command(isdn_ctrl *);
-extern int indicate_status(int, int, ulong, char*);
-extern int reset(int);
-
 static int identify_board(unsigned long, unsigned int);
 
 static int __init sc_init(void)
diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c
index cd17de1..bef7963 100644
--- a/drivers/isdn/sc/interrupt.c
+++ b/drivers/isdn/sc/interrupt.c
@@ -21,16 +21,6 @@
 #include "card.h"
 #include <linux/interrupt.h>
 
-extern int indicate_status(int, int, ulong, char *);
-extern void check_phystat(unsigned long);
-extern int receivemessage(int, RspMessage *);
-extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
-        unsigned int, unsigned int, unsigned int, unsigned int *);
-extern void rcvpkt(int, RspMessage *);
-
-extern int cinst;
-extern board *sc_adapter[];
-
 static int get_card_from_irq(int irq)
 {
 	int i;
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
index 57c4ab9..7817d22 100644
--- a/drivers/isdn/sc/ioctl.c
+++ b/drivers/isdn/sc/ioctl.c
@@ -12,16 +12,6 @@
 #include "card.h"
 #include "scioc.h"
 
-extern int indicate_status(int, int, unsigned long, char *);
-extern int startproc(int);
-extern int reset(int);
-extern int send_and_receive(int, unsigned int, unsigned char,unsigned char,
-		unsigned char,unsigned char, 
-		unsigned char, unsigned char *, RspMessage *, int);
-
-extern board *sc_adapter[];
-
-
 static int GetStatus(int card, boardInfo *);
 
 /*
diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c
index 0a0fe6b..c5a307e 100644
--- a/drivers/isdn/sc/message.c
+++ b/drivers/isdn/sc/message.c
@@ -22,16 +22,6 @@
 #include "message.h"
 #include "card.h"
 
-extern board *sc_adapter[];
-extern unsigned int cinst;
-
-/*
- * Obligatory function prototypes
- */
-extern int indicate_status(int,ulong,char*);
-extern int scm_command(isdn_ctrl *);
-
-
 /*
  * receive a message from the board
  */
diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
index 1e04676..92016a2 100644
--- a/drivers/isdn/sc/packet.c
+++ b/drivers/isdn/sc/packet.c
@@ -20,16 +20,6 @@
 #include "message.h"
 #include "card.h"
 
-extern board *sc_adapter[];
-extern unsigned int cinst;
-
-extern int get_card_from_id(int);
-extern int indicate_status(int, int,ulong, char*);
-extern void memcpy_toshmem(int, void *, const void *, size_t);
-extern void memcpy_fromshmem(int, void *, const void *, size_t);
-extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
-                unsigned int, unsigned int, unsigned int, unsigned int *);
-
 int sndpkt(int devId, int channel, struct sk_buff *data)
 {
 	LLData	ReqLnkWrite;
diff --git a/drivers/isdn/sc/scioc.h b/drivers/isdn/sc/scioc.h
index d08e650..dfb107a 100644
--- a/drivers/isdn/sc/scioc.h
+++ b/drivers/isdn/sc/scioc.h
@@ -1,3 +1,6 @@
+#ifndef __ISDN_SC_SCIOC_H__
+#define __ISDN_SC_SCIOC_H__
+
 /*
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
@@ -103,3 +106,6 @@
 		POTInfo potsinfo;
 	} info;
 } boardInfo;
+
+#endif  /*  __ISDN_SC_SCIOC_H__  */
+
diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
index 6f58862..034d41a 100644
--- a/drivers/isdn/sc/shmem.c
+++ b/drivers/isdn/sc/shmem.c
@@ -22,12 +22,6 @@
 #include "card.h"
 
 /*
- * Main adapter array
- */
-extern board *sc_adapter[];
-extern int cinst;
-
-/*
  *
  */
 void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
diff --git a/drivers/isdn/sc/timer.c b/drivers/isdn/sc/timer.c
index f43282b..cc1b886 100644
--- a/drivers/isdn/sc/timer.c
+++ b/drivers/isdn/sc/timer.c
@@ -20,14 +20,6 @@
 #include "message.h"
 #include "card.h"
 
-extern board *sc_adapter[];
-
-extern void flushreadfifo(int);
-extern int  startproc(int);
-extern int  indicate_status(int, int, unsigned long, char *);
-extern int  sendmessage(int, unsigned int, unsigned int, unsigned int,
-        unsigned int, unsigned int, unsigned int, unsigned int *);
-
 
 /*
  * Write the proper values into the I/O ports following a reset
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 2db1ca4..04574a9 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -304,6 +304,7 @@
 	int memory_config_version;
 	int busy;
 	unsigned long rmap_overflow;
+	struct list_head vm_list;
 };
 
 struct kvm_stat {
@@ -340,6 +341,7 @@
 
 	struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu);
 	void (*vcpu_put)(struct kvm_vcpu *vcpu);
+	void (*vcpu_decache)(struct kvm_vcpu *vcpu);
 
 	int (*set_guest_debug)(struct kvm_vcpu *vcpu,
 			       struct kvm_debug_guest *dbg);
@@ -558,7 +560,7 @@
 #ifndef load_ldt
 static inline void load_ldt(u16 sel)
 {
-	asm ("lldt %0" : : "g"(sel));
+	asm ("lldt %0" : : "rm"(sel));
 }
 #endif
 
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index b10972e..af86614 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -34,6 +34,8 @@
 #include <linux/highmem.h>
 #include <linux/file.h>
 #include <asm/desc.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
 
 #include "x86_emulate.h"
 #include "segment_descriptor.h"
@@ -41,6 +43,9 @@
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+static DEFINE_SPINLOCK(kvm_lock);
+static LIST_HEAD(vm_list);
+
 struct kvm_arch_ops *kvm_arch_ops;
 struct kvm_stat kvm_stat;
 EXPORT_SYMBOL_GPL(kvm_stat);
@@ -62,7 +67,7 @@
 	{ "halt_exits", &kvm_stat.halt_exits },
 	{ "request_irq", &kvm_stat.request_irq_exits },
 	{ "irq_exits", &kvm_stat.irq_exits },
-	{ 0, 0 }
+	{ NULL, NULL }
 };
 
 static struct dentry *debugfs_dir;
@@ -205,7 +210,7 @@
 	mutex_lock(&vcpu->mutex);
 	if (unlikely(!vcpu->vmcs)) {
 		mutex_unlock(&vcpu->mutex);
-		return 0;
+		return NULL;
 	}
 	return kvm_arch_ops->vcpu_load(vcpu);
 }
@@ -230,9 +235,13 @@
 		struct kvm_vcpu *vcpu = &kvm->vcpus[i];
 
 		mutex_init(&vcpu->mutex);
+		vcpu->cpu = -1;
 		vcpu->kvm = kvm;
 		vcpu->mmu.root_hpa = INVALID_PAGE;
 		INIT_LIST_HEAD(&vcpu->free_pages);
+		spin_lock(&kvm_lock);
+		list_add(&kvm->vm_list, &vm_list);
+		spin_unlock(&kvm_lock);
 	}
 	filp->private_data = kvm;
 	return 0;
@@ -257,9 +266,9 @@
 	if (!dont || free->dirty_bitmap != dont->dirty_bitmap)
 		vfree(free->dirty_bitmap);
 
-	free->phys_mem = 0;
+	free->phys_mem = NULL;
 	free->npages = 0;
-	free->dirty_bitmap = 0;
+	free->dirty_bitmap = NULL;
 }
 
 static void kvm_free_physmem(struct kvm *kvm)
@@ -267,12 +276,14 @@
 	int i;
 
 	for (i = 0; i < kvm->nmemslots; ++i)
-		kvm_free_physmem_slot(&kvm->memslots[i], 0);
+		kvm_free_physmem_slot(&kvm->memslots[i], NULL);
 }
 
 static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
 {
-	vcpu_load(vcpu->kvm, vcpu_slot(vcpu));
+	if (!vcpu_load(vcpu->kvm, vcpu_slot(vcpu)))
+		return;
+
 	kvm_mmu_destroy(vcpu);
 	vcpu_put(vcpu);
 	kvm_arch_ops->vcpu_free(vcpu);
@@ -290,6 +301,9 @@
 {
 	struct kvm *kvm = filp->private_data;
 
+	spin_lock(&kvm_lock);
+	list_del(&kvm->vm_list);
+	spin_unlock(&kvm_lock);
 	kvm_free_vcpus(kvm);
 	kvm_free_physmem(kvm);
 	kfree(kvm);
@@ -544,7 +558,6 @@
 					   FX_IMAGE_ALIGN);
 	vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE;
 
-	vcpu->cpu = -1;  /* First load will set up TR */
 	r = kvm_arch_ops->vcpu_create(vcpu);
 	if (r < 0)
 		goto out_free_vcpus;
@@ -640,11 +653,11 @@
 
 	/* Deallocate if slot is being removed */
 	if (!npages)
-		new.phys_mem = 0;
+		new.phys_mem = NULL;
 
 	/* Free page dirty bitmap if unneeded */
 	if (!(new.flags & KVM_MEM_LOG_DIRTY_PAGES))
-		new.dirty_bitmap = 0;
+		new.dirty_bitmap = NULL;
 
 	r = -ENOMEM;
 
@@ -799,14 +812,14 @@
 		    && gfn < memslot->base_gfn + memslot->npages)
 			return memslot;
 	}
-	return 0;
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(gfn_to_memslot);
 
 void mark_page_dirty(struct kvm *kvm, gfn_t gfn)
 {
 	int i;
-	struct kvm_memory_slot *memslot = 0;
+	struct kvm_memory_slot *memslot = NULL;
 	unsigned long rel_gfn;
 
 	for (i = 0; i < kvm->nmemslots; ++i) {
@@ -1360,6 +1373,9 @@
 	if (!vcpu)
 		return -ENOENT;
 
+	/* re-sync apic's tpr */
+	vcpu->cr8 = kvm_run->cr8;
+
 	if (kvm_run->emulated) {
 		kvm_arch_ops->skip_emulated_instruction(vcpu);
 		kvm_run->emulated = 0;
@@ -1778,6 +1794,7 @@
 			  unsigned int ioctl, unsigned long arg)
 {
 	struct kvm *kvm = filp->private_data;
+	void __user *argp = (void __user *)arg;
 	int r = -EINVAL;
 
 	switch (ioctl) {
@@ -1794,12 +1811,12 @@
 		struct kvm_run kvm_run;
 
 		r = -EFAULT;
-		if (copy_from_user(&kvm_run, (void *)arg, sizeof kvm_run))
+		if (copy_from_user(&kvm_run, argp, sizeof kvm_run))
 			goto out;
 		r = kvm_dev_ioctl_run(kvm, &kvm_run);
 		if (r < 0 &&  r != -EINTR)
 			goto out;
-		if (copy_to_user((void *)arg, &kvm_run, sizeof kvm_run)) {
+		if (copy_to_user(argp, &kvm_run, sizeof kvm_run)) {
 			r = -EFAULT;
 			goto out;
 		}
@@ -1809,13 +1826,13 @@
 		struct kvm_regs kvm_regs;
 
 		r = -EFAULT;
-		if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
+		if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs))
 			goto out;
 		r = kvm_dev_ioctl_get_regs(kvm, &kvm_regs);
 		if (r)
 			goto out;
 		r = -EFAULT;
-		if (copy_to_user((void *)arg, &kvm_regs, sizeof kvm_regs))
+		if (copy_to_user(argp, &kvm_regs, sizeof kvm_regs))
 			goto out;
 		r = 0;
 		break;
@@ -1824,7 +1841,7 @@
 		struct kvm_regs kvm_regs;
 
 		r = -EFAULT;
-		if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
+		if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs))
 			goto out;
 		r = kvm_dev_ioctl_set_regs(kvm, &kvm_regs);
 		if (r)
@@ -1836,13 +1853,13 @@
 		struct kvm_sregs kvm_sregs;
 
 		r = -EFAULT;
-		if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs))
+		if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs))
 			goto out;
 		r = kvm_dev_ioctl_get_sregs(kvm, &kvm_sregs);
 		if (r)
 			goto out;
 		r = -EFAULT;
-		if (copy_to_user((void *)arg, &kvm_sregs, sizeof kvm_sregs))
+		if (copy_to_user(argp, &kvm_sregs, sizeof kvm_sregs))
 			goto out;
 		r = 0;
 		break;
@@ -1851,7 +1868,7 @@
 		struct kvm_sregs kvm_sregs;
 
 		r = -EFAULT;
-		if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs))
+		if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs))
 			goto out;
 		r = kvm_dev_ioctl_set_sregs(kvm, &kvm_sregs);
 		if (r)
@@ -1863,13 +1880,13 @@
 		struct kvm_translation tr;
 
 		r = -EFAULT;
-		if (copy_from_user(&tr, (void *)arg, sizeof tr))
+		if (copy_from_user(&tr, argp, sizeof tr))
 			goto out;
 		r = kvm_dev_ioctl_translate(kvm, &tr);
 		if (r)
 			goto out;
 		r = -EFAULT;
-		if (copy_to_user((void *)arg, &tr, sizeof tr))
+		if (copy_to_user(argp, &tr, sizeof tr))
 			goto out;
 		r = 0;
 		break;
@@ -1878,7 +1895,7 @@
 		struct kvm_interrupt irq;
 
 		r = -EFAULT;
-		if (copy_from_user(&irq, (void *)arg, sizeof irq))
+		if (copy_from_user(&irq, argp, sizeof irq))
 			goto out;
 		r = kvm_dev_ioctl_interrupt(kvm, &irq);
 		if (r)
@@ -1890,7 +1907,7 @@
 		struct kvm_debug_guest dbg;
 
 		r = -EFAULT;
-		if (copy_from_user(&dbg, (void *)arg, sizeof dbg))
+		if (copy_from_user(&dbg, argp, sizeof dbg))
 			goto out;
 		r = kvm_dev_ioctl_debug_guest(kvm, &dbg);
 		if (r)
@@ -1902,7 +1919,7 @@
 		struct kvm_memory_region kvm_mem;
 
 		r = -EFAULT;
-		if (copy_from_user(&kvm_mem, (void *)arg, sizeof kvm_mem))
+		if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
 			goto out;
 		r = kvm_dev_ioctl_set_memory_region(kvm, &kvm_mem);
 		if (r)
@@ -1913,7 +1930,7 @@
 		struct kvm_dirty_log log;
 
 		r = -EFAULT;
-		if (copy_from_user(&log, (void *)arg, sizeof log))
+		if (copy_from_user(&log, argp, sizeof log))
 			goto out;
 		r = kvm_dev_ioctl_get_dirty_log(kvm, &log);
 		if (r)
@@ -1921,13 +1938,13 @@
 		break;
 	}
 	case KVM_GET_MSRS:
-		r = msr_io(kvm, (void __user *)arg, get_msr, 1);
+		r = msr_io(kvm, argp, get_msr, 1);
 		break;
 	case KVM_SET_MSRS:
-		r = msr_io(kvm, (void __user *)arg, do_set_msr, 0);
+		r = msr_io(kvm, argp, do_set_msr, 0);
 		break;
 	case KVM_GET_MSR_INDEX_LIST: {
-		struct kvm_msr_list __user *user_msr_list = (void __user *)arg;
+		struct kvm_msr_list __user *user_msr_list = argp;
 		struct kvm_msr_list msr_list;
 		unsigned n;
 
@@ -2014,7 +2031,7 @@
 		 * in vmx root mode.
 		 */
 		printk(KERN_INFO "kvm: exiting hardware virtualization\n");
-		on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+		on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
 	}
 	return NOTIFY_OK;
 }
@@ -2024,11 +2041,69 @@
 	.priority = 0,
 };
 
+/*
+ * Make sure that a cpu that is being hot-unplugged does not have any vcpus
+ * cached on it.
+ */
+static void decache_vcpus_on_cpu(int cpu)
+{
+	struct kvm *vm;
+	struct kvm_vcpu *vcpu;
+	int i;
+
+	spin_lock(&kvm_lock);
+	list_for_each_entry(vm, &vm_list, vm_list)
+		for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+			vcpu = &vm->vcpus[i];
+			/*
+			 * If the vcpu is locked, then it is running on some
+			 * other cpu and therefore it is not cached on the
+			 * cpu in question.
+			 *
+			 * If it's not locked, check the last cpu it executed
+			 * on.
+			 */
+			if (mutex_trylock(&vcpu->mutex)) {
+				if (vcpu->cpu == cpu) {
+					kvm_arch_ops->vcpu_decache(vcpu);
+					vcpu->cpu = -1;
+				}
+				mutex_unlock(&vcpu->mutex);
+			}
+		}
+	spin_unlock(&kvm_lock);
+}
+
+static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
+			   void *v)
+{
+	int cpu = (long)v;
+
+	switch (val) {
+	case CPU_DEAD:
+	case CPU_UP_CANCELED:
+		decache_vcpus_on_cpu(cpu);
+		smp_call_function_single(cpu, kvm_arch_ops->hardware_disable,
+					 NULL, 0, 1);
+		break;
+	case CPU_UP_PREPARE:
+		smp_call_function_single(cpu, kvm_arch_ops->hardware_enable,
+					 NULL, 0, 1);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block kvm_cpu_notifier = {
+	.notifier_call = kvm_cpu_hotplug,
+	.priority = 20, /* must be > scheduler priority */
+};
+
 static __init void kvm_init_debug(void)
 {
 	struct kvm_stats_debugfs_item *p;
 
-	debugfs_dir = debugfs_create_dir("kvm", 0);
+	debugfs_dir = debugfs_create_dir("kvm", NULL);
 	for (p = debugfs_entries; p->name; ++p)
 		p->dentry = debugfs_create_u32(p->name, 0444, debugfs_dir,
 					       p->data);
@@ -2043,6 +2118,30 @@
 	debugfs_remove(debugfs_dir);
 }
 
+static int kvm_suspend(struct sys_device *dev, pm_message_t state)
+{
+	decache_vcpus_on_cpu(raw_smp_processor_id());
+	on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+	return 0;
+}
+
+static int kvm_resume(struct sys_device *dev)
+{
+	on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1);
+	return 0;
+}
+
+static struct sysdev_class kvm_sysdev_class = {
+	set_kset_name("kvm"),
+	.suspend = kvm_suspend,
+	.resume = kvm_resume,
+};
+
+static struct sys_device kvm_sysdev = {
+	.id = 0,
+	.cls = &kvm_sysdev_class,
+};
+
 hpa_t bad_page_address;
 
 int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
@@ -2069,9 +2168,20 @@
 	if (r < 0)
 	    return r;
 
-	on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1);
+	on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1);
+	r = register_cpu_notifier(&kvm_cpu_notifier);
+	if (r)
+		goto out_free_1;
 	register_reboot_notifier(&kvm_reboot_notifier);
 
+	r = sysdev_class_register(&kvm_sysdev_class);
+	if (r)
+		goto out_free_2;
+
+	r = sysdev_register(&kvm_sysdev);
+	if (r)
+		goto out_free_3;
+
 	kvm_chardev_ops.owner = module;
 
 	r = misc_register(&kvm_dev);
@@ -2083,8 +2193,14 @@
 	return r;
 
 out_free:
+	sysdev_unregister(&kvm_sysdev);
+out_free_3:
+	sysdev_class_unregister(&kvm_sysdev_class);
+out_free_2:
 	unregister_reboot_notifier(&kvm_reboot_notifier);
-	on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+	unregister_cpu_notifier(&kvm_cpu_notifier);
+out_free_1:
+	on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
 	kvm_arch_ops->hardware_unsetup();
 	return r;
 }
@@ -2092,9 +2208,11 @@
 void kvm_exit_arch(void)
 {
 	misc_deregister(&kvm_dev);
-
+	sysdev_unregister(&kvm_sysdev);
+	sysdev_class_unregister(&kvm_sysdev_class);
 	unregister_reboot_notifier(&kvm_reboot_notifier);
-	on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+	unregister_cpu_notifier(&kvm_cpu_notifier);
+	on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
 	kvm_arch_ops->hardware_unsetup();
 	kvm_arch_ops = NULL;
 }
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 22c426c..be79377 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -333,7 +333,7 @@
 	for (j = RMAP_EXT - 1; !desc->shadow_ptes[j] && j > i; --j)
 		;
 	desc->shadow_ptes[i] = desc->shadow_ptes[j];
-	desc->shadow_ptes[j] = 0;
+	desc->shadow_ptes[j] = NULL;
 	if (j != 0)
 		return;
 	if (!prev_desc && !desc->more)
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 149fa45..b6b90e9 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -443,31 +443,17 @@
 static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
 {
 	struct guest_walker walker;
-	pt_element_t guest_pte;
-	gpa_t gpa;
+	gpa_t gpa = UNMAPPED_GVA;
+	int r;
 
-	FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
-	guest_pte = *walker.ptep;
-	FNAME(release_walker)(&walker);
+	r = FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
 
-	if (!is_present_pte(guest_pte))
-		return UNMAPPED_GVA;
-
-	if (walker.level == PT_DIRECTORY_LEVEL) {
-		ASSERT((guest_pte & PT_PAGE_SIZE_MASK));
-		ASSERT(PTTYPE == 64 || is_pse(vcpu));
-
-		gpa = (guest_pte & PT_DIR_BASE_ADDR_MASK) | (vaddr &
-			(PT_LEVEL_MASK(PT_PAGE_TABLE_LEVEL) | ~PAGE_MASK));
-
-		if (PTTYPE == 32 && is_cpuid_PSE36())
-			gpa |= (guest_pte & PT32_DIR_PSE36_MASK) <<
-					(32 - PT32_DIR_PSE36_SHIFT);
-	} else {
-		gpa = (guest_pte & PT_BASE_ADDR_MASK);
-		gpa |= (vaddr & ~PAGE_MASK);
+	if (r) {
+		gpa = (gpa_t)walker.gfn << PAGE_SHIFT;
+		gpa |= vaddr & ~PAGE_MASK;
 	}
 
+	FNAME(release_walker)(&walker);
 	return gpa;
 }
 
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index c79df79..83da4ea 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -274,7 +274,7 @@
 		wrmsrl(MSR_VM_HSAVE_PA, 0);
 		rdmsrl(MSR_EFER, efer);
 		wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK);
-		per_cpu(svm_data, raw_smp_processor_id()) = 0;
+		per_cpu(svm_data, raw_smp_processor_id()) = NULL;
 		__free_page(svm_data->save_area);
 		kfree(svm_data);
 	}
@@ -528,7 +528,13 @@
 	save->cs.attrib = SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK |
 		SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK;
 	save->cs.limit = 0xffff;
-	save->cs.base = 0xffff0000;
+	/*
+	 * cs.base should really be 0xffff0000, but vmx can't handle that, so
+	 * be consistent with it.
+	 *
+	 * Replace when we have real mode working for vmx.
+	 */
+	save->cs.base = 0xf0000;
 
 	save->gdtr.limit = 0xffff;
 	save->idtr.limit = 0xffff;
@@ -603,6 +609,10 @@
 	put_cpu();
 }
 
+static void svm_vcpu_decache(struct kvm_vcpu *vcpu)
+{
+}
+
 static void svm_cache_regs(struct kvm_vcpu *vcpu)
 {
 	vcpu->regs[VCPU_REGS_RAX] = vcpu->svm->vmcb->save.rax;
@@ -642,7 +652,7 @@
 	case VCPU_SREG_LDTR: return &save->ldtr;
 	}
 	BUG();
-	return 0;
+	return NULL;
 }
 
 static u64 svm_get_segment_base(struct kvm_vcpu *vcpu, int seg)
@@ -723,7 +733,7 @@
 	}
 #endif
 	vcpu->svm->cr0 = cr0;
-	vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK;
+	vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK | CR0_WP_MASK;
 	vcpu->cr0 = cr0;
 }
 
@@ -934,7 +944,7 @@
 		return 0;
 
 	*addr_override = 0;
-	*seg = 0;
+	*seg = NULL;
 	for (i = 0; i < ins_length; i++)
 		switch (inst[i]) {
 		case 0xf0:
@@ -1087,7 +1097,7 @@
 
 static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-	if (emulate_instruction(vcpu, 0, 0, 0) != EMULATE_DONE)
+	if (emulate_instruction(vcpu, NULL, 0, 0) != EMULATE_DONE)
 		printk(KERN_ERR "%s: failed\n", __FUNCTION__);
 	return 1;
 }
@@ -1671,6 +1681,7 @@
 
 	.vcpu_load = svm_vcpu_load,
 	.vcpu_put = svm_vcpu_put,
+	.vcpu_decache = svm_vcpu_decache,
 
 	.set_guest_debug = svm_guest_debug,
 	.get_msr = svm_get_msr,
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 54c35c0..fd4e9173 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -98,7 +98,7 @@
 	for (i = 0; i < vcpu->nmsrs; ++i)
 		if (vcpu->guest_msrs[i].index == msr)
 			return &vcpu->guest_msrs[i];
-	return 0;
+	return NULL;
 }
 
 static void vmcs_clear(struct vmcs *vmcs)
@@ -125,6 +125,15 @@
 		per_cpu(current_vmcs, cpu) = NULL;
 }
 
+static void vcpu_clear(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->cpu != raw_smp_processor_id() && vcpu->cpu != -1)
+		smp_call_function_single(vcpu->cpu, __vcpu_clear, vcpu, 0, 1);
+	else
+		__vcpu_clear(vcpu);
+	vcpu->launched = 0;
+}
+
 static unsigned long vmcs_readl(unsigned long field)
 {
 	unsigned long value;
@@ -202,10 +211,8 @@
 
 	cpu = get_cpu();
 
-	if (vcpu->cpu != cpu) {
-		smp_call_function(__vcpu_clear, vcpu, 0, 1);
-		vcpu->launched = 0;
-	}
+	if (vcpu->cpu != cpu)
+		vcpu_clear(vcpu);
 
 	if (per_cpu(current_vmcs, cpu) != vcpu->vmcs) {
 		u8 error;
@@ -243,6 +250,11 @@
 	put_cpu();
 }
 
+static void vmx_vcpu_decache(struct kvm_vcpu *vcpu)
+{
+	vcpu_clear(vcpu);
+}
+
 static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
 {
 	return vmcs_readl(GUEST_RFLAGS);
@@ -502,7 +514,7 @@
 	return (msr & 5) == 1; /* locked but not enabled */
 }
 
-static __init void hardware_enable(void *garbage)
+static void hardware_enable(void *garbage)
 {
 	int cpu = raw_smp_processor_id();
 	u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
@@ -1375,6 +1387,11 @@
 	return 1;
 }
 
+static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
+	return 0;
+}
 
 static int get_io_count(struct kvm_vcpu *vcpu, u64 *count)
 {
@@ -1635,6 +1652,7 @@
 				      struct kvm_run *kvm_run) = {
 	[EXIT_REASON_EXCEPTION_NMI]           = handle_exception,
 	[EXIT_REASON_EXTERNAL_INTERRUPT]      = handle_external_interrupt,
+	[EXIT_REASON_TRIPLE_FAULT]            = handle_triple_fault,
 	[EXIT_REASON_IO_INSTRUCTION]          = handle_io,
 	[EXIT_REASON_CR_ACCESS]               = handle_cr,
 	[EXIT_REASON_DR_ACCESS]               = handle_dr,
@@ -1786,10 +1804,10 @@
 		"kvm_vmx_return: "
 		/* Save guest registers, load host registers, keep flags */
 #ifdef CONFIG_X86_64
-		"xchg %3,     0(%%rsp) \n\t"
+		"xchg %3,     (%%rsp) \n\t"
 		"mov %%rax, %c[rax](%3) \n\t"
 		"mov %%rbx, %c[rbx](%3) \n\t"
-		"pushq 0(%%rsp); popq %c[rcx](%3) \n\t"
+		"pushq (%%rsp); popq %c[rcx](%3) \n\t"
 		"mov %%rdx, %c[rdx](%3) \n\t"
 		"mov %%rsi, %c[rsi](%3) \n\t"
 		"mov %%rdi, %c[rdi](%3) \n\t"
@@ -1804,24 +1822,24 @@
 		"mov %%r15, %c[r15](%3) \n\t"
 		"mov %%cr2, %%rax   \n\t"
 		"mov %%rax, %c[cr2](%3) \n\t"
-		"mov 0(%%rsp), %3 \n\t"
+		"mov (%%rsp), %3 \n\t"
 
 		"pop  %%rcx; pop  %%r15; pop  %%r14; pop  %%r13; pop  %%r12;"
 		"pop  %%r11; pop  %%r10; pop  %%r9;  pop  %%r8;"
 		"pop  %%rbp; pop  %%rdi; pop  %%rsi;"
 		"pop  %%rdx; pop  %%rbx; pop  %%rax \n\t"
 #else
-		"xchg %3, 0(%%esp) \n\t"
+		"xchg %3, (%%esp) \n\t"
 		"mov %%eax, %c[rax](%3) \n\t"
 		"mov %%ebx, %c[rbx](%3) \n\t"
-		"pushl 0(%%esp); popl %c[rcx](%3) \n\t"
+		"pushl (%%esp); popl %c[rcx](%3) \n\t"
 		"mov %%edx, %c[rdx](%3) \n\t"
 		"mov %%esi, %c[rsi](%3) \n\t"
 		"mov %%edi, %c[rdi](%3) \n\t"
 		"mov %%ebp, %c[rbp](%3) \n\t"
 		"mov %%cr2, %%eax  \n\t"
 		"mov %%eax, %c[cr2](%3) \n\t"
-		"mov 0(%%esp), %3 \n\t"
+		"mov (%%esp), %3 \n\t"
 
 		"pop %%ecx; popa \n\t"
 #endif
@@ -1859,15 +1877,7 @@
 	fx_restore(vcpu->host_fx_image);
 	vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0;
 
-#ifndef CONFIG_X86_64
 	asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
-#endif
-
-	/*
-	 * Profile KVM exit RIPs:
-	 */
-	if (unlikely(prof_on == KVM_PROFILING))
-		profile_hit(KVM_PROFILING, (void *)vmcs_readl(GUEST_RIP));
 
 	kvm_run->exit_type = 0;
 	if (fail) {
@@ -1891,6 +1901,12 @@
 
 			reload_tss();
 		}
+		/*
+		 * Profile KVM exit RIPs:
+		 */
+		if (unlikely(prof_on == KVM_PROFILING))
+			profile_hit(KVM_PROFILING, (void *)vmcs_readl(GUEST_RIP));
+
 		vcpu->launched = 1;
 		kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT;
 		r = kvm_handle_exit(kvm_run, vcpu);
@@ -2012,6 +2028,7 @@
 
 	.vcpu_load = vmx_vcpu_load,
 	.vcpu_put = vmx_vcpu_put,
+	.vcpu_decache = vmx_vcpu_decache,
 
 	.set_guest_debug = set_guest_debug,
 	.get_msr = vmx_get_msr,
diff --git a/drivers/kvm/vmx.h b/drivers/kvm/vmx.h
index 4c0ab15..d0dc93d 100644
--- a/drivers/kvm/vmx.h
+++ b/drivers/kvm/vmx.h
@@ -180,6 +180,7 @@
 
 #define EXIT_REASON_EXCEPTION_NMI       0
 #define EXIT_REASON_EXTERNAL_INTERRUPT  1
+#define EXIT_REASON_TRIPLE_FAULT        2
 
 #define EXIT_REASON_PENDING_INTERRUPT   7
 
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index a9e747c..1a86387 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -1,6 +1,6 @@
 
 menu "Macintosh device drivers"
-	depends on PPC || MAC
+	depends on PPC || MAC || X86
 
 config ADB
 	bool "Apple Desktop Bus (ADB) support"
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 7cec6de..f729eeb 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -885,7 +885,7 @@
 	return ret;
 }
 
-static struct file_operations adb_fops = {
+static const struct file_operations adb_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= adb_read,
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 1c7d6f2..b77ef51 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -574,8 +574,8 @@
 static int leds_pending[16];
 static int leds_req_pending;
 static int pending_devs[16];
-static int pending_led_start=0;
-static int pending_led_end=0;
+static int pending_led_start;
+static int pending_led_end;
 static DEFINE_SPINLOCK(leds_lock);
 
 static void leds_done(struct adb_request *req)
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index 2b8a6e8..cdd5a0f 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -121,7 +121,7 @@
 	return 0;
 }
 
-struct file_operations anslcd_fops = {
+const struct file_operations anslcd_fops = {
 	.write	= anslcd_write,
 	.ioctl	= anslcd_ioctl,
 	.open	= anslcd_open,
diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c
index 4300c62..c5e4d43 100644
--- a/drivers/macintosh/apm_emu.c
+++ b/drivers/macintosh/apm_emu.c
@@ -102,7 +102,7 @@
 	SLEEP_LEVEL_USERLAND,
 };
 
-static char			driver_version[] = "0.5";	/* no spaces */
+static const char driver_version[] = "0.5";	/* no spaces */
 
 #ifdef DEBUG
 static char *	apm_event_name[] = {
@@ -501,7 +501,7 @@
 	return p - buf;
 }
 
-static struct file_operations apm_bios_fops = {
+static const struct file_operations apm_bios_fops = {
 	.owner		= THIS_MODULE,
 	.read		= do_read,
 	.poll		= do_poll,
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index ee6b4ca..c1fd816 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -17,10 +17,10 @@
 
 static struct input_dev *emumousebtn;
 static int emumousebtn_input_register(void);
-static int mouse_emulate_buttons = 0;
+static int mouse_emulate_buttons;
 static int mouse_button2_keycode = KEY_RIGHTCTRL;	/* right control key */
 static int mouse_button3_keycode = KEY_RIGHTALT;	/* right option key */
-static int mouse_last_keycode = 0;
+static int mouse_last_keycode;
 
 #if defined(CONFIG_SYSCTL)
 /* file(s) in /proc/sys/dev/mac_hid */
@@ -138,7 +138,7 @@
 		return err;
 
 #if defined(CONFIG_SYSCTL)
-	mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir, 1);
+	mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir);
 #endif /* CONFIG_SYSCTL */
 
 	return 0;
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c
index 797cef7..026b67f 100644
--- a/drivers/macintosh/macio-adb.c
+++ b/drivers/macintosh/macio-adb.c
@@ -6,7 +6,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <asm/prom.h>
diff --git a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c
index 3079187..b195d75 100644
--- a/drivers/macintosh/nvram.c
+++ b/drivers/macintosh/nvram.c
@@ -100,7 +100,7 @@
 	return 0;
 }
 
-struct file_operations nvram_fops = {
+const struct file_operations nvram_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= nvram_llseek,
 	.read		= read_nvram,
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c
index 5ed41fe..f83fad2 100644
--- a/drivers/macintosh/rack-meter.c
+++ b/drivers/macintosh/rack-meter.c
@@ -171,11 +171,11 @@
 	/* Make sure dbdma is reset */
 	DBDMA_DO_RESET(rm->dma_regs);
 
-	pr_debug("rackmeter: mark offset=0x%lx\n",
+	pr_debug("rackmeter: mark offset=0x%zx\n",
 		 offsetof(struct rackmeter_dma, mark));
-	pr_debug("rackmeter: buf1 offset=0x%lx\n",
+	pr_debug("rackmeter: buf1 offset=0x%zx\n",
 		 offsetof(struct rackmeter_dma, buf1));
-	pr_debug("rackmeter: buf2 offset=0x%lx\n",
+	pr_debug("rackmeter: buf2 offset=0x%zx\n",
 		 offsetof(struct rackmeter_dma, buf2));
 
 	/* Prepare 4 dbdma commands for the 2 buffers */
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 6f30459..3096836 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -1277,7 +1277,7 @@
 }
 
 
-static struct file_operations smu_device_fops = {
+static const struct file_operations smu_device_fops = {
 	.llseek		= no_llseek,
 	.read		= smu_read,
 	.write		= smu_write,
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 3d3bf16..a7ce5592 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -48,11 +48,11 @@
 
 static u8 default_limits_local[3] = {70, 50, 70};    /* local, sensor1, sensor2 */
 static u8 default_limits_chip[3] = {80, 65, 80};    /* local, sensor1, sensor2 */
-static const char *sensor_location[3] = {NULL, NULL, NULL};
+static const char *sensor_location[3];
 
-static int limit_adjust = 0;
+static int limit_adjust;
 static int fan_speed = -1;
-static int verbose = 0;
+static int verbose;
 
 MODULE_AUTHOR("Colin Leroy <colin@colino.net>");
 MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and "
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index df66291..d58fcf6 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -13,7 +13,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/spinlock.h>
@@ -86,7 +85,7 @@
 #ifdef CONFIG_PPC
 static struct device_node *vias;
 #endif
-static int cuda_fully_inited = 0;
+static int cuda_fully_inited;
 
 #ifdef CONFIG_ADB
 static int cuda_probe(void);
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index 5d88d5b..1b3bad6 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -19,7 +19,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/adb.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -107,10 +106,10 @@
 	awaiting_reply
 } macii_state;
 
-static int need_poll    = 0;
-static int command_byte = 0;
-static int last_reply   = 0;
-static int last_active  = 0;
+static int need_poll;
+static int command_byte;
+static int last_reply;
+static int last_active;
 
 static struct adb_request *current_req;
 static struct adb_request *last_req;
@@ -124,7 +123,7 @@
 static int prefix_len;
 static int status = ST_IDLE|TREQ;
 static int last_status;
-static int driver_running = 0;
+static int driver_running;
 
 /* debug level 10 required for ADB logging (should be && debug_adb, ideally) */
 
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c
index 1f0aa5d..2dc7880 100644
--- a/drivers/macintosh/via-maciisi.c
+++ b/drivers/macintosh/via-maciisi.c
@@ -18,7 +18,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/delay.h>
@@ -63,10 +62,10 @@
 
 #undef DEBUG_MACIISI_ADB
 
-static struct adb_request* current_req = NULL;
-static struct adb_request* last_req = NULL;
+static struct adb_request* current_req;
+static struct adb_request* last_req;
 static unsigned char maciisi_rbuf[16];
-static unsigned char *reply_ptr = NULL;
+static unsigned char *reply_ptr;
 static int data_index;
 static int reading_reply;
 static int reply_len;
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index 801a974..7e27071 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -15,7 +15,7 @@
 
 #define MAX_PMU_LEVEL 0xFF
 
-static struct backlight_properties pmu_backlight_data;
+static struct backlight_ops pmu_backlight_data;
 static DEFINE_SPINLOCK(pmu_backlight_lock);
 static int sleeping;
 static u8 bl_curve[FB_BACKLIGHT_LEVELS];
@@ -72,7 +72,7 @@
 {
 	struct adb_request req;
 	unsigned long flags;
-	int level = bd->props->brightness;
+	int level = bd->props.brightness;
 
 	spin_lock_irqsave(&pmu_backlight_lock, flags);
 
@@ -80,8 +80,8 @@
 	if (sleeping)
 		goto out;
 
-	if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 
 	if (level > 0) {
@@ -107,14 +107,13 @@
 
 static int pmu_backlight_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties pmu_backlight_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops pmu_backlight_data = {
 	.get_brightness	= pmu_backlight_get_brightness,
 	.update_status	= pmu_backlight_update_status,
-	.max_brightness	= (FB_BACKLIGHT_LEVELS - 1),
+
 };
 
 #ifdef CONFIG_PM
@@ -152,9 +151,10 @@
 		printk("pmubl: Backlight registration failed\n");
 		goto error;
 	}
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
 
-	level = pmu_backlight_data.max_brightness;
+	level = bd->props.max_brightness;
 
 	if (autosave) {
 		/* read autosaved value if available */
@@ -164,19 +164,12 @@
 
 		level = pmu_backlight_curve_lookup(
 				(req.reply[0] >> 4) *
-				pmu_backlight_data.max_brightness / 15);
+				bd->props.max_brightness / 15);
 	}
 
-	down(&bd->sem);
-	bd->props->brightness = level;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
+	bd->props.brightness = level;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("pmubl: Backlight initialized (%s)\n", name);
 
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 8ca75e5..b6073bd 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -141,13 +141,13 @@
 static volatile int disable_poll;
 static struct device_node *vias;
 static int pmu_kind = PMU_UNKNOWN;
-static int pmu_fully_inited = 0;
+static int pmu_fully_inited;
 static int pmu_has_adb;
 static struct device_node *gpio_node;
-static unsigned char __iomem *gpio_reg = NULL;
+static unsigned char __iomem *gpio_reg;
 static int gpio_irq = NO_IRQ;
 static int gpio_irq_enabled = -1;
-static volatile int pmu_suspended = 0;
+static volatile int pmu_suspended;
 static spinlock_t pmu_lock;
 static u8 pmu_intr_mask;
 static int pmu_version;
@@ -169,7 +169,7 @@
 
 int pmu_battery_count;
 int pmu_cur_battery;
-unsigned int pmu_power_flags;
+unsigned int pmu_power_flags = PMU_PWR_AC_PRESENT;
 struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES];
 static int query_batt_timer = BATTERY_POLLING_COUNT;
 static struct adb_request batt_req;
@@ -180,7 +180,7 @@
 BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
 
 #ifdef CONFIG_ADB
-static int adb_dev_map = 0;
+static int adb_dev_map;
 static int pmu_adb_flags;
 
 static int pmu_probe(void);
@@ -516,7 +516,6 @@
 					proc_get_irqstats, NULL);
 		proc_pmu_options = create_proc_entry("options", 0600, proc_pmu_root);
 		if (proc_pmu_options) {
-			proc_pmu_options->nlink = 1;
 			proc_pmu_options->read_proc = proc_read_options;
 			proc_pmu_options->write_proc = proc_write_options;
 		}
@@ -2673,7 +2672,7 @@
 	return error;
 }
 
-static struct file_operations pmu_device_fops = {
+static const struct file_operations pmu_device_fops = {
 	.read		= pmu_read,
 	.write		= pmu_write,
 	.poll		= pmu_fpoll,
@@ -2777,7 +2776,7 @@
 
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
 
-static int pmu_sys_suspended = 0;
+static int pmu_sys_suspended;
 
 static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
 {
@@ -2817,7 +2816,6 @@
 };
 
 static struct sys_device device_pmu = {
-	.id		= 0,
 	.cls		= &pmu_sysclass,
 };
 
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 93e6ef92..356c721 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -22,7 +22,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/miscdevice.h>
 #include <linux/blkdev.h>
 #include <linux/pci.h>
@@ -96,10 +95,10 @@
 static int data_len;
 static int adb_int_pending;
 static int pmu_adb_flags;
-static int adb_dev_map = 0;
+static int adb_dev_map;
 static struct adb_request bright_req_1, bright_req_2, bright_req_3;
 static int pmu_kind = PMU_UNKNOWN;
-static int pmu_fully_inited = 0;
+static int pmu_fully_inited;
 
 int asleep;
 BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
@@ -1040,7 +1039,7 @@
 	return -EINVAL;
 }
 
-static struct file_operations pmu_device_fops = {
+static const struct file_operations pmu_device_fops = {
 	.read		= pmu_read,
 	.write		= pmu_write,
 	.ioctl		= pmu_ioctl,
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 1110816..5554ada 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -666,7 +666,7 @@
 
 	if (file) {
 		struct inode *inode = file->f_path.dentry->d_inode;
-		invalidate_inode_pages(inode->i_mapping);
+		invalidate_mapping_pages(inode->i_mapping, 0, -1);
 		fput(file);
 	}
 }
@@ -1160,6 +1160,22 @@
 			return 0;
 		}
 
+		if (unlikely((*bmc & COUNTER_MAX) == COUNTER_MAX)) {
+			DEFINE_WAIT(__wait);
+			/* note that it is safe to do the prepare_to_wait
+			 * after the test as long as we do it before dropping
+			 * the spinlock.
+			 */
+			prepare_to_wait(&bitmap->overflow_wait, &__wait,
+					TASK_UNINTERRUPTIBLE);
+			spin_unlock_irq(&bitmap->lock);
+			bitmap->mddev->queue
+				->unplug_fn(bitmap->mddev->queue);
+			schedule();
+			finish_wait(&bitmap->overflow_wait, &__wait);
+			continue;
+		}
+
 		switch(*bmc) {
 		case 0:
 			bitmap_file_set_bit(bitmap, offset);
@@ -1169,7 +1185,7 @@
 		case 1:
 			*bmc = 2;
 		}
-		BUG_ON((*bmc & COUNTER_MAX) == COUNTER_MAX);
+
 		(*bmc)++;
 
 		spin_unlock_irq(&bitmap->lock);
@@ -1207,6 +1223,9 @@
 		if (!success && ! (*bmc & NEEDED_MASK))
 			*bmc |= NEEDED_MASK;
 
+		if ((*bmc & COUNTER_MAX) == COUNTER_MAX)
+			wake_up(&bitmap->overflow_wait);
+
 		(*bmc)--;
 		if (*bmc <= 2) {
 			set_page_attr(bitmap,
@@ -1431,6 +1450,7 @@
 	spin_lock_init(&bitmap->lock);
 	atomic_set(&bitmap->pending_writes, 0);
 	init_waitqueue_head(&bitmap->write_wait);
+	init_waitqueue_head(&bitmap->overflow_wait);
 
 	bitmap->mddev = mddev;
 
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index cd6a184..b441d82 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1473,7 +1473,7 @@
 	return r;
 }
 
-static struct file_operations _ctl_fops = {
+static const struct file_operations _ctl_fops = {
 	.ioctl	 = ctl_ioctl,
 	.owner	 = THIS_MODULE,
 };
diff --git a/drivers/md/md.c b/drivers/md/md.c
index e8807ea..05febfd 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4920,7 +4920,7 @@
 	return mask;
 }
 
-static struct file_operations md_seq_fops = {
+static const struct file_operations md_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = md_seq_open,
 	.read           = seq_read,
@@ -5581,7 +5581,7 @@
 			    md_probe, NULL, NULL);
 
 	register_reboot_notifier(&md_notifier);
-	raid_table_header = register_sysctl_table(raid_root_table, 1);
+	raid_table_header = register_sysctl_table(raid_root_table);
 
 	md_geninit();
 	return (0);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 467c169..11c3d7b 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2620,7 +2620,7 @@
 	}
 	bi = conf->retry_read_aligned_list;
 	if(bi) {
-		conf->retry_read_aligned = bi->bi_next;
+		conf->retry_read_aligned_list = bi->bi_next;
 		bi->bi_next = NULL;
 		bi->bi_phys_segments = 1; /* biased count of active stripes */
 		bi->bi_hw_segments = 0; /* count of processed stripes */
@@ -2669,6 +2669,27 @@
 	return 0;
 }
 
+static int bio_fits_rdev(struct bio *bi)
+{
+	request_queue_t *q = bdev_get_queue(bi->bi_bdev);
+
+	if ((bi->bi_size>>9) > q->max_sectors)
+		return 0;
+	blk_recount_segments(q, bi);
+	if (bi->bi_phys_segments > q->max_phys_segments ||
+	    bi->bi_hw_segments > q->max_hw_segments)
+		return 0;
+
+	if (q->merge_bvec_fn)
+		/* it's too hard to apply the merge_bvec_fn at this stage,
+		 * just just give up
+		 */
+		return 0;
+
+	return 1;
+}
+
+
 static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio)
 {
 	mddev_t *mddev = q->queuedata;
@@ -2715,6 +2736,13 @@
 		align_bi->bi_flags &= ~(1 << BIO_SEG_VALID);
 		align_bi->bi_sector += rdev->data_offset;
 
+		if (!bio_fits_rdev(align_bi)) {
+			/* too big in some way */
+			bio_put(align_bi);
+			rdev_dec_pending(rdev, mddev);
+			return 0;
+		}
+
 		spin_lock_irq(&conf->device_lock);
 		wait_event_lock_irq(conf->wait_for_stripe,
 				    conf->quiesce == 0,
@@ -3107,7 +3135,9 @@
 	last_sector = raid_bio->bi_sector + (raid_bio->bi_size>>9);
 
 	for (; logical_sector < last_sector;
-	     logical_sector += STRIPE_SECTORS, scnt++) {
+	     logical_sector += STRIPE_SECTORS,
+		     sector += STRIPE_SECTORS,
+		     scnt++) {
 
 		if (scnt < raid_bio->bi_hw_segments)
 			/* already done this stripe */
@@ -3123,7 +3153,13 @@
 		}
 
 		set_bit(R5_ReadError, &sh->dev[dd_idx].flags);
-		add_stripe_bio(sh, raid_bio, dd_idx, 0);
+		if (!add_stripe_bio(sh, raid_bio, dd_idx, 0)) {
+			release_stripe(sh);
+			raid_bio->bi_hw_segments = scnt;
+			conf->retry_read_aligned = raid_bio;
+			return handled;
+		}
+
 		handle_stripe(sh, NULL);
 		release_stripe(sh);
 		handled++;
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 87410db..91d25798 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -70,6 +70,7 @@
 	depends on I2C
 
 config VIDEO_BUF
+	depends on PCI
 	tristate
 
 config VIDEO_BUF_DVB
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index f33e5d9..c120114 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -5,8 +5,4 @@
 config VIDEO_SAA7146_VV
 	tristate
 	select VIDEO_BUF
-	select VIDEO_VIDEOBUF
 	select VIDEO_SAA7146
-
-config VIDEO_VIDEOBUF
-	tristate
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
index 9a8dd87..cbf7c05 100644
--- a/drivers/media/common/ir-functions.c
+++ b/drivers/media/common/ir-functions.c
@@ -256,6 +256,112 @@
 	return value;
 }
 
+/* RC5 decoding stuff, moved from bttv-input.c to share it with
+ * saa7134 */
+
+/* decode raw bit pattern to RC5 code */
+u32 ir_rc5_decode(unsigned int code)
+{
+	unsigned int org_code = code;
+	unsigned int pair;
+	unsigned int rc5 = 0;
+	int i;
+
+	for (i = 0; i < 14; ++i) {
+		pair = code & 0x3;
+		code >>= 2;
+
+		rc5 <<= 1;
+		switch (pair) {
+		case 0:
+		case 2:
+			break;
+		case 1:
+			rc5 |= 1;
+			break;
+		case 3:
+			dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);
+			return 0;
+		}
+	}
+	dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+		"instr=%x\n", rc5, org_code, RC5_START(rc5),
+		RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
+	return rc5;
+}
+
+void ir_rc5_timer_end(unsigned long data)
+{
+	struct card_ir *ir = (struct card_ir *)data;
+	struct timeval tv;
+	unsigned long current_jiffies, timeout;
+	u32 gap;
+	u32 rc5 = 0;
+
+	/* get time */
+	current_jiffies = jiffies;
+	do_gettimeofday(&tv);
+
+	/* avoid overflow with gap >1s */
+	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+		gap = 200000;
+	} else {
+		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+		    tv.tv_usec - ir->base_time.tv_usec;
+	}
+
+	/* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
+	if (gap < 28000) {
+		dprintk(1, "ir-common: spurious timer_end\n");
+		return;
+	}
+
+	ir->active = 0;
+	if (ir->last_bit < 20) {
+		/* ignore spurious codes (caused by light/other remotes) */
+		dprintk(1, "ir-common: short code: %x\n", ir->code);
+	} else {
+		ir->code = (ir->code << ir->shift_by) | 1;
+		rc5 = ir_rc5_decode(ir->code);
+
+		/* two start bits? */
+		if (RC5_START(rc5) != ir->start) {
+			dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5));
+
+			/* right address? */
+		} else if (RC5_ADDR(rc5) == ir->addr) {
+			u32 toggle = RC5_TOGGLE(rc5);
+			u32 instr = RC5_INSTR(rc5);
+
+			/* Good code, decide if repeat/repress */
+			if (toggle != RC5_TOGGLE(ir->last_rc5) ||
+			    instr != RC5_INSTR(ir->last_rc5)) {
+				dprintk(1, "ir-common: instruction %x, toggle %x\n", instr,
+					toggle);
+				ir_input_nokey(ir->dev, &ir->ir);
+				ir_input_keydown(ir->dev, &ir->ir, instr,
+						 instr);
+			}
+
+			/* Set/reset key-up timer */
+			timeout = current_jiffies + (500 + ir->rc5_key_timeout
+						     * HZ) / 1000;
+			mod_timer(&ir->timer_keyup, timeout);
+
+			/* Save code for repeat test */
+			ir->last_rc5 = rc5;
+		}
+	}
+}
+
+void ir_rc5_timer_keyup(unsigned long data)
+{
+	struct card_ir *ir = (struct card_ir *)data;
+
+	dprintk(1, "ir-common: key released\n");
+	ir_input_nokey(ir->dev, &ir->ir);
+}
+
 EXPORT_SYMBOL_GPL(ir_input_init);
 EXPORT_SYMBOL_GPL(ir_input_nokey);
 EXPORT_SYMBOL_GPL(ir_input_keydown);
@@ -265,6 +371,10 @@
 EXPORT_SYMBOL_GPL(ir_decode_biphase);
 EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
 
+EXPORT_SYMBOL_GPL(ir_rc5_decode);
+EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
+EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
+
 /*
  * Local variables:
  * c-basic-offset: 8
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
index f51e02fe..03b47a2 100644
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/common/ir-keymaps.c
@@ -698,7 +698,6 @@
 	[ 0x29 ] = KEY_TEXT,
 	[ 0x2a ] = KEY_MEDIA,
 	[ 0x18 ] = KEY_EPG,
-	[ 0x27 ] = KEY_RECORD,
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey);
@@ -1607,3 +1606,174 @@
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old);
+
+/*
+ * Marc Fargas <telenieko@telenieko.com>
+ * this is the remote control that comes with the asus p7131
+ * which has a label saying is "Model PC-39"
+ */
+IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = {
+	/* Keys 0 to 9 */
+	[ 0x15 ] = KEY_0,
+	[ 0x29 ] = KEY_1,
+	[ 0x2d ] = KEY_2,
+	[ 0x2b ] = KEY_3,
+	[ 0x09 ] = KEY_4,
+	[ 0x0d ] = KEY_5,
+	[ 0x0b ] = KEY_6,
+	[ 0x31 ] = KEY_7,
+	[ 0x35 ] = KEY_8,
+	[ 0x33 ] = KEY_9,
+
+	[ 0x3e ] = KEY_RADIO,		/* radio */
+	[ 0x03 ] = KEY_MENU,		/* dvd/menu */
+	[ 0x2a ] = KEY_VOLUMEUP,
+	[ 0x19 ] = KEY_VOLUMEDOWN,
+	[ 0x37 ] = KEY_UP,
+	[ 0x3b ] = KEY_DOWN,
+	[ 0x27 ] = KEY_LEFT,
+	[ 0x2f ] = KEY_RIGHT,
+	[ 0x25 ] = KEY_VIDEO,		/* video */
+	[ 0x39 ] = KEY_AUDIO,		/* music */
+
+	[ 0x21 ] = KEY_TV,		/* tv */
+	[ 0x1d ] = KEY_EXIT,		/* back */
+	[ 0x0a ] = KEY_CHANNELUP,	/* channel / program + */
+	[ 0x1b ] = KEY_CHANNELDOWN,	/* channel / program - */
+	[ 0x1a ] = KEY_ENTER,		/* enter */
+
+	[ 0x06 ] = KEY_PAUSE,		/* play/pause */
+	[ 0x1e ] = KEY_PREVIOUS,	/* rew */
+	[ 0x26 ] = KEY_NEXT,		/* forward */
+	[ 0x0e ] = KEY_REWIND,		/* backward << */
+	[ 0x3a ] = KEY_FASTFORWARD,	/* forward >> */
+	[ 0x36 ] = KEY_STOP,
+	[ 0x2e ] = KEY_RECORD,		/* recording */
+	[ 0x16 ] = KEY_POWER,		/* the button that reads "close" */
+
+	[ 0x11 ] = KEY_ZOOM,		/* full screen */
+	[ 0x13 ] = KEY_MACRO,		/* recall */
+	[ 0x23 ] = KEY_HOME,		/* home */
+	[ 0x05 ] = KEY_PVR,		/* picture */
+	[ 0x3d ] = KEY_MUTE,		/* mute */
+	[ 0x01 ] = KEY_DVD,		/* dvd */
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_asus_pc39);
+
+
+/* Encore ENLTV-FM  - black plastic, white front cover with white glowing buttons
+    Juan Pablo Sormani <sorman@gmail.com> */
+IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = {
+
+	/* Power button does nothing, neither in Windows app,
+	 although it sends data (used for BIOS wakeup?) */
+	[ 0x0d ] = KEY_MUTE,
+
+	[ 0x1e ] = KEY_TV,
+	[ 0x00 ] = KEY_VIDEO,
+	[ 0x01 ] = KEY_AUDIO,		/* music */
+	[ 0x02 ] = KEY_MHP,		/* picture */
+
+	[ 0x1f ] = KEY_1,
+	[ 0x03 ] = KEY_2,
+	[ 0x04 ] = KEY_3,
+	[ 0x05 ] = KEY_4,
+	[ 0x1c ] = KEY_5,
+	[ 0x06 ] = KEY_6,
+	[ 0x07 ] = KEY_7,
+	[ 0x08 ] = KEY_8,
+	[ 0x1d ] = KEY_9,
+	[ 0x0a ] = KEY_0,
+
+	[ 0x09 ] = KEY_LIST,        /* -/-- */
+	[ 0x0b ] = KEY_LAST,        /* recall */
+
+	[ 0x14 ] = KEY_HOME,		/* win start menu */
+	[ 0x15 ] = KEY_EXIT,		/* exit */
+	[ 0x16 ] = KEY_UP,
+	[ 0x12 ] = KEY_DOWN,
+	[ 0x0c ] = KEY_RIGHT,
+	[ 0x17 ] = KEY_LEFT,
+
+	[ 0x18 ] = KEY_ENTER,		/* OK */
+
+	[ 0x0e ] = KEY_ESC,
+	[ 0x13 ] = KEY_D,		/* desktop */
+	[ 0x11 ] = KEY_TAB,
+	[ 0x19 ] = KEY_SWITCHVIDEOMODE,	/* switch */
+
+	[ 0x1a ] = KEY_MENU,
+	[ 0x1b ] = KEY_ZOOM,		/* fullscreen */
+	[ 0x44 ] = KEY_TIME,		/* time shift */
+	[ 0x40 ] = KEY_MODE,		/* source */
+
+	[ 0x5a ] = KEY_RECORD,
+	[ 0x42 ] = KEY_PLAY,		/* play/pause */
+	[ 0x45 ] = KEY_STOP,
+	[ 0x43 ] = KEY_CAMERA,		/* camera icon */
+
+	[ 0x48 ] = KEY_REWIND,
+	[ 0x4a ] = KEY_FASTFORWARD,
+	[ 0x49 ] = KEY_PREVIOUS,
+	[ 0x4b ] = KEY_NEXT,
+
+	[ 0x4c ] = KEY_FAVORITES,	/* tv wall */
+	[ 0x4d ] = KEY_SOUND,		/* DVD sound */
+	[ 0x4e ] = KEY_LANGUAGE,	/* DVD lang */
+	[ 0x4f ] = KEY_TEXT,		/* DVD text */
+
+	[ 0x50 ] = KEY_SLEEP,		/* shutdown */
+	[ 0x51 ] = KEY_MODE,		/* stereo > main */
+	[ 0x52 ] = KEY_SELECT,		/* stereo > sap */
+	[ 0x53 ] = KEY_PROG1,		/* teletext */
+
+
+	[ 0x59 ] = KEY_RED,		/* AP1 */
+	[ 0x41 ] = KEY_GREEN,		/* AP2 */
+	[ 0x47 ] = KEY_YELLOW,		/* AP3 */
+	[ 0x57 ] = KEY_BLUE,		/* AP4 */
+
+
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_encore_enltv);
+
+/* for the Technotrend 1500 bundled remote: */
+IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = {
+	[ 0x01 ] = KEY_POWER,
+	[ 0x02 ] = KEY_SHUFFLE,	/* ? double-arrow key */
+	[ 0x03 ] = KEY_1,
+	[ 0x04 ] = KEY_2,
+	[ 0x05 ] = KEY_3,
+	[ 0x06 ] = KEY_4,
+	[ 0x07 ] = KEY_5,
+	[ 0x08 ] = KEY_6,
+	[ 0x09 ] = KEY_7,
+	[ 0x0a ] = KEY_8,
+	[ 0x0b ] = KEY_9,
+	[ 0x0c ] = KEY_0,
+	[ 0x0d ] = KEY_UP,
+	[ 0x0e ] = KEY_LEFT,
+	[ 0x0f ] = KEY_OK,
+	[ 0x10 ] = KEY_RIGHT,
+	[ 0x11 ] = KEY_DOWN,
+	[ 0x12 ] = KEY_INFO,
+	[ 0x13 ] = KEY_EXIT,
+	[ 0x14 ] = KEY_RED,
+	[ 0x15 ] = KEY_GREEN,
+	[ 0x16 ] = KEY_YELLOW,
+	[ 0x17 ] = KEY_BLUE,
+	[ 0x18 ] = KEY_MUTE,
+	[ 0x19 ] = KEY_TEXT,
+	[ 0x1a ] = KEY_MODE,	/* ? TV/Radio */
+	[ 0x21 ] = KEY_OPTION,
+	[ 0x22 ] = KEY_EPG,
+	[ 0x23 ] = KEY_CHANNELUP,
+	[ 0x24 ] = KEY_CHANNELDOWN,
+	[ 0x25 ] = KEY_VOLUMEUP,
+	[ 0x26 ] = KEY_VOLUMEDOWN,
+	[ 0x27 ] = KEY_SETUP,
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_tt_1500);
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index d867a6a..c18a5da 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -416,7 +416,7 @@
 	}
 }
 
-static struct file_operations video_fops =
+static const struct file_operations video_fops =
 {
 	.owner		= THIS_MODULE,
 	.open		= fops_open,
@@ -508,7 +508,7 @@
 
 	DEB_EE(("dev:%p\n",dev));
 
-	pci_free_consistent(dev->pci, SAA7146_RPS_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
+	pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
 	kfree(vv);
 	dev->vv_data = NULL;
 	dev->vv_callback = NULL;
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index c2b35e3..752cf79 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -385,9 +385,9 @@
 	else buf[3] = 0x88;
 
 	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
+		fe->ops.i2c_gate_ctrl(fe, 0);
 	deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
-	ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3);
+	ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3);
 	deb_tuner("tuner write returned: %d\n",ret);
 
 	return 0;
@@ -398,91 +398,71 @@
 	0x80, 0x00,
 	0x81, 0x01,
 	0x81, 0x00,
-	0x00, 0x09,
-	0x01, 0x69,
+	0x00, 0x48,
+	0x01, 0x58,
 	0x03, 0x00,
 	0x04, 0x00,
 	0x07, 0x00,
 	0x08, 0x00,
-	0x20, 0x00,
-	0x21, 0x40,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x24, 0x40,
-	0x25, 0x88,
 	0x30, 0xff,
-	0x31, 0x00,
+	0x31, 0x9d,
 	0x32, 0xff,
 	0x33, 0x00,
-	0x34, 0x50,
-	0x35, 0x7f,
-	0x36, 0x00,
-	0x37, 0x20,
-	0x38, 0x00,
-	0x40, 0x1c,
-	0x41, 0xff,
-	0x42, 0x29,
+	0x34, 0x29,
+	0x35, 0x55,
+	0x36, 0x80,
+	0x37, 0x6e,
+	0x38, 0x9c,
+	0x40, 0x1a,
+	0x41, 0xfe,
+	0x42, 0x33,
 	0x43, 0x00,
 	0x44, 0xff,
 	0x45, 0x00,
 	0x46, 0x00,
 	0x49, 0x04,
-	0x4a, 0x00,
+	0x4a, 0x51,
 	0x4b, 0xf8,
 	0x52, 0x30,
-	0x55, 0xae,
-	0x56, 0x47,
-	0x57, 0xe1,
-	0x58, 0x3a,
-	0x5a, 0x1e,
-	0x5b, 0x34,
-	0x60, 0x00,
-	0x63, 0x00,
-	0x64, 0x00,
-	0x65, 0x00,
-	0x66, 0x00,
-	0x67, 0x00,
-	0x68, 0x00,
-	0x69, 0x00,
-	0x6a, 0x02,
-	0x6b, 0x00,
+	0x53, 0x06,
+	0x59, 0x06,
+	0x5a, 0x5e,
+	0x5b, 0x04,
+	0x61, 0x49,
+	0x62, 0x0a,
 	0x70, 0xff,
-	0x71, 0x00,
+	0x71, 0x04,
 	0x72, 0x00,
 	0x73, 0x00,
 	0x74, 0x0c,
-	0x80, 0x00,
+	0x80, 0x20,
 	0x81, 0x00,
-	0x82, 0x00,
+	0x82, 0x30,
 	0x83, 0x00,
 	0x84, 0x04,
-	0x85, 0x80,
-	0x86, 0x24,
-	0x87, 0x78,
-	0x88, 0x10,
+	0x85, 0x22,
+	0x86, 0x08,
+	0x87, 0x1b,
+	0x88, 0x00,
 	0x89, 0x00,
-	0x90, 0x01,
-	0x91, 0x01,
-	0xa0, 0x04,
+	0x90, 0x00,
+	0x91, 0x04,
+	0xa0, 0x86,
 	0xa1, 0x00,
 	0xa2, 0x00,
 	0xb0, 0x91,
 	0xb1, 0x0b,
-	0xc0, 0x53,
-	0xc1, 0x70,
+	0xc0, 0x5b,
+	0xc1, 0x10,
 	0xc2, 0x12,
-	0xd0, 0x00,
+	0xd0, 0x02,
 	0xd1, 0x00,
 	0xd2, 0x00,
 	0xd3, 0x00,
-	0xd4, 0x00,
+	0xd4, 0x02,
 	0xd5, 0x00,
 	0xde, 0x00,
-	0xdf, 0x00,
-	0x61, 0x49,
-	0x62, 0x0b,
-	0x53, 0x08,
-	0x59, 0x08,
+	0xdf, 0x01,
 	0xff, 0xff,
 };
 
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index e0bd2d8..5347a40 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -190,6 +190,7 @@
 	fc->i2c_adap.class	    = I2C_CLASS_TV_DIGITAL;
 	fc->i2c_adap.algo       = &flexcop_algo;
 	fc->i2c_adap.algo_data  = NULL;
+	fc->i2c_adap.dev.parent	= fc->dev;
 
 	if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
 		return ret;
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index 329a51c..83b090e 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -390,6 +390,7 @@
 	{ 0xfc00270f, BTTV_BOARD_TWINHAN_DST,			"ChainTech digitop DST-1000 DVB-S" },
 	{ 0x07711461, BTTV_BOARD_AVDVBT_771,			"AVermedia AverTV DVB-T 771" },
 	{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,		"DViCO FusionHDTV DVB-T Lite" },
+	{ 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE,		"Ultraview DVB-T Lite" },
 	{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,	"DViCO FusionHDTV 5 Lite" },
 	{ 0x20007063, BTTV_BOARD_PC_HDTV,			"pcHDTV HD-2000 TV" },
 	{ 0x00261822, BTTV_BOARD_TWINHAN_DST,			"DNTV Live! Mini" },
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 9f72b70..0393a3d 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1161,7 +1161,7 @@
 		}
 	}
 
-	if (i >= sizeof (dst_tlist) / sizeof (dst_tlist [0])) {
+	if (i >= ARRAY_SIZE(dst_tlist)) {
 		dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]);
 		dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in");
 		use_dst_type = DST_TYPE_IS_SAT;
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 3e35931..58f69f6 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -213,7 +214,7 @@
 		freq = 2150000; /* satellite IF is 950..2150MHz */
 
 	/* decide which VCO to use for the input frequency */
-	for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
+	for(i = 1; (i < ARRAY_SIZE(osci)) && (osci[i] < freq); i++);
 	printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);
 	band=bandsel[i];
 	/* the gain values must be set by SetSymbolrate */
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index d64b96c..a6cbbdd 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -819,6 +819,11 @@
 		set_bit(rc_keys[i + 2], input_dev->keybit);
 	input_dev->keycodesize = 0;
 	input_dev->keycodemax = 0;
+	input_dev->id.bustype = BUS_USB;
+	input_dev->id.vendor = cinergyt2->udev->descriptor.idVendor;
+	input_dev->id.product = cinergyt2->udev->descriptor.idProduct;
+	input_dev->id.version = 1;
+	input_dev->cdev.dev = &cinergyt2->udev->dev;
 
 	err = input_register_device(input_dev);
 	if (err) {
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 988499d..fc77de4 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -25,7 +25,6 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/ioctl.h>
 #include <linux/wait.h>
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index e859722..a21a894 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -36,6 +36,7 @@
 #include <linux/list.h>
 #include <linux/freezer.h>
 #include <linux/jiffies.h>
+#include <linux/kthread.h>
 #include <asm/processor.h>
 
 #include "dvb_frontend.h"
@@ -100,7 +101,7 @@
 	struct semaphore sem;
 	struct list_head list_head;
 	wait_queue_head_t wait_queue;
-	pid_t thread_pid;
+	struct task_struct *thread;
 	unsigned long release_jiffies;
 	unsigned int exit;
 	unsigned int wakeup;
@@ -508,19 +509,11 @@
 	struct dvb_frontend *fe = data;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	unsigned long timeout;
-	char name [15];
 	fe_status_t s;
 	struct dvb_frontend_parameters *params;
 
 	dprintk("%s\n", __FUNCTION__);
 
-	snprintf (name, sizeof(name), "kdvb-fe-%i", fe->dvb->num);
-
-	lock_kernel();
-	daemonize(name);
-	sigfillset(&current->blocked);
-	unlock_kernel();
-
 	fepriv->check_wrapped = 0;
 	fepriv->quality = 0;
 	fepriv->delay = 3*HZ;
@@ -532,16 +525,18 @@
 
 	while (1) {
 		up(&fepriv->sem);	    /* is locked when we enter the thread... */
-
+restart:
 		timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
-							   dvb_frontend_should_wakeup(fe),
-							   fepriv->delay);
-		if (0 != dvb_frontend_is_exiting(fe)) {
+			dvb_frontend_should_wakeup(fe) || kthread_should_stop(),
+			fepriv->delay);
+
+		if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
 			/* got signal or quitting */
 			break;
 		}
 
-		try_to_freeze();
+		if (try_to_freeze())
+			goto restart;
 
 		if (down_interruptible(&fepriv->sem))
 			break;
@@ -591,7 +586,7 @@
 			fe->ops.sleep(fe);
 	}
 
-	fepriv->thread_pid = 0;
+	fepriv->thread = NULL;
 	mb();
 
 	dvb_frontend_wakeup(fe);
@@ -600,7 +595,6 @@
 
 static void dvb_frontend_stop(struct dvb_frontend *fe)
 {
-	unsigned long ret;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
 	dprintk ("%s\n", __FUNCTION__);
@@ -608,33 +602,17 @@
 	fepriv->exit = 1;
 	mb();
 
-	if (!fepriv->thread_pid)
+	if (!fepriv->thread)
 		return;
 
-	/* check if the thread is really alive */
-	if (kill_proc(fepriv->thread_pid, 0, 1) == -ESRCH) {
-		printk("dvb_frontend_stop: thread PID %d already died\n",
-				fepriv->thread_pid);
-		/* make sure the mutex was not held by the thread */
-		init_MUTEX (&fepriv->sem);
-		return;
-	}
-
-	/* wake up the frontend thread, so it notices that fe->exit == 1 */
-	dvb_frontend_wakeup(fe);
-
-	/* wait until the frontend thread has exited */
-	ret = wait_event_interruptible(fepriv->wait_queue,0 == fepriv->thread_pid);
-	if (-ERESTARTSYS != ret) {
-		fepriv->state = FESTATE_IDLE;
-		return;
-	}
+	kthread_stop(fepriv->thread);
+	init_MUTEX (&fepriv->sem);
 	fepriv->state = FESTATE_IDLE;
 
 	/* paranoia check in case a signal arrived */
-	if (fepriv->thread_pid)
-		printk("dvb_frontend_stop: warning: thread PID %d won't exit\n",
-				fepriv->thread_pid);
+	if (fepriv->thread)
+		printk("dvb_frontend_stop: warning: thread %p won't exit\n",
+				fepriv->thread);
 }
 
 s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime)
@@ -684,10 +662,11 @@
 {
 	int ret;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct task_struct *fe_thread;
 
 	dprintk ("%s\n", __FUNCTION__);
 
-	if (fepriv->thread_pid) {
+	if (fepriv->thread) {
 		if (!fepriv->exit)
 			return 0;
 		else
@@ -701,18 +680,18 @@
 
 	fepriv->state = FESTATE_IDLE;
 	fepriv->exit = 0;
-	fepriv->thread_pid = 0;
+	fepriv->thread = NULL;
 	mb();
 
-	ret = kernel_thread (dvb_frontend_thread, fe, 0);
-
-	if (ret < 0) {
-		printk("dvb_frontend_start: failed to start kernel_thread (%d)\n", ret);
+	fe_thread = kthread_run(dvb_frontend_thread, fe,
+		"kdvb-fe-%i", fe->dvb->num);
+	if (IS_ERR(fe_thread)) {
+		ret = PTR_ERR(fe_thread);
+		printk("dvb_frontend_start: failed to start kthread (%d)\n", ret);
 		up(&fepriv->sem);
 		return ret;
 	}
-	fepriv->thread_pid = ret;
-
+	fepriv->thread = fe_thread;
 	return 0;
 }
 
@@ -915,7 +894,7 @@
 			fetunesettings.parameters.inversion = INVERSION_AUTO;
 		}
 		if (fe->ops.info.type == FE_OFDM) {
-			/* without hierachical coding code_rate_LP is irrelevant,
+			/* without hierarchical coding code_rate_LP is irrelevant,
 			 * so we tolerate the otherwise invalid FEC_NONE setting */
 			if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
 			    fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE)
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 40774fe..490337b 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/device.h>
@@ -200,12 +199,14 @@
 			const struct dvb_device *template, void *priv, int type)
 {
 	struct dvb_device *dvbdev;
+	struct file_operations *dvbdevfops;
+
 	int id;
 
 	if (mutex_lock_interruptible(&dvbdev_register_lock))
 		return -ERESTARTSYS;
 
-	if ((id = dvbdev_get_free_id (adap, type)) < 0) {
+	if ((id = dvbdev_get_free_id (adap, type)) < 0){
 		mutex_unlock(&dvbdev_register_lock);
 		*pdvbdev = NULL;
 		printk ("%s: could get find free device id...\n", __FUNCTION__);
@@ -214,7 +215,15 @@
 
 	*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
 
-	if (!dvbdev) {
+	if (!dvbdev){
+		mutex_unlock(&dvbdev_register_lock);
+		return -ENOMEM;
+	}
+
+	dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
+
+	if (!dvbdevfops){
+		kfree (dvbdev);
 		mutex_unlock(&dvbdev_register_lock);
 		return -ENOMEM;
 	}
@@ -224,7 +233,9 @@
 	dvbdev->id = id;
 	dvbdev->adapter = adap;
 	dvbdev->priv = priv;
+	dvbdev->fops = dvbdevfops;
 
+	memcpy(dvbdev->fops, template->fops, sizeof(struct file_operations));
 	dvbdev->fops->owner = adap->module;
 
 	list_add_tail (&dvbdev->list_head, &adap->device_list);
@@ -252,6 +263,7 @@
 					dvbdev->type, dvbdev->id)));
 
 	list_del (&dvbdev->list_head);
+	kfree (dvbdev->fops);
 	kfree (dvbdev);
 }
 EXPORT_SYMBOL(dvb_unregister_device);
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index ad52143..80f67a5 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -109,6 +109,34 @@
 	  Medion MD95700 hybrid USB2.0 device.
 	  DViCO FusionHDTV (Bluebird) USB2.0 devices
 
+config DVB_USB_M920X
+	tristate "Uli m920x DVB-T USB2.0 support"
+	depends on DVB_USB
+	select DVB_MT352 if !DVB_FE_CUSTOMISE
+	select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+	help
+	  Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
+	  Currently, only devices with a product id of
+	  "DTV USB MINI" (in cold state) are supported.
+	  Firmware required.
+
+config DVB_USB_GL861
+	tristate "Genesys Logic GL861 USB2.0 support"
+	depends on DVB_USB
+	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+	select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+	help
+	  Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
+	  receiver with USB ID 0db0:5581.
+
+config DVB_USB_AU6610
+	tristate "Alcor Micro AU6610 USB2.0 support"
+	depends on DVB_USB
+	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+	select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+	help
+	  Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
+
 config DVB_USB_DIGITV
 	tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
 	depends on DVB_USB
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 154d593..40f28f5 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -30,6 +30,15 @@
 dvb-usb-umt-010-objs = umt-010.o
 obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
 
+dvb-usb-m920x-objs = m920x.o
+obj-$(CONFIG_DVB_USB_M920X) += dvb-usb-m920x.o
+
+dvb-usb-gl861-objs = gl861.o
+obj-$(CONFIG_DVB_USB_GL861) += dvb-usb-gl861.o
+
+dvb-usb-au6610-objs = au6610.o
+obj-$(CONFIG_DVB_USB_AU6610) += dvb-usb-au6610.o
+
 dvb-usb-digitv-objs = digitv.o
 obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
 
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c
new file mode 100644
index 0000000..0dc66a8
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/au6610.c
@@ -0,0 +1,255 @@
+/* DVB USB compliant linux driver for Sigmatek DVB-110 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *
+ *	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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+#include "au6610.h"
+
+#include "zl10353.h"
+#include "qt1010.h"
+
+/* debug */
+static int dvb_usb_au6610_debug;
+module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
+			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+	int ret;
+	u16 index;
+	u8 usb_buf[6]; /* enough for all known requests,
+			  read returns 5 and write 6 bytes */
+	switch (wlen) {
+	case 1:
+		index = wbuf[0] << 8;
+		break;
+	case 2:
+		index = wbuf[0] << 8;
+		index += wbuf[1];
+		break;
+	default:
+		warn("wlen = %x, aborting.", wlen);
+		return -EINVAL;
+	}
+
+	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
+			      USB_TYPE_VENDOR|USB_DIR_IN, addr, index, usb_buf,
+			      sizeof(usb_buf), AU6610_USB_TIMEOUT);
+
+	if (ret < 0)
+		return ret;
+
+	switch (operation) {
+	case AU6610_REQ_I2C_READ:
+	case AU6610_REQ_USB_READ:
+		/* requested value is always 5th byte in buffer */
+		rbuf[0] = usb_buf[4];
+	}
+
+	return ret;
+}
+
+static int au6610_i2c_msg(struct dvb_usb_device *d, u8 addr,
+			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+	u8 request;
+	u8 wo = (rbuf == NULL || rlen == 0); /* write-only */
+
+	if (wo) {
+		request = AU6610_REQ_I2C_WRITE;
+	} else { /* rw */
+		request = AU6610_REQ_I2C_READ;
+	}
+
+	return au6610_usb_msg(d, request, addr, wbuf, wlen, rbuf, rlen);
+}
+
+
+/* I2C */
+static int au6610_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+			   int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int i;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	if (num > 2)
+		return -EINVAL;
+
+	for (i = 0; i < num; i++) {
+		/* write/read request */
+		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+			if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf,
+					   msg[i].len, msg[i+1].buf,
+					   msg[i+1].len) < 0)
+				break;
+			i++;
+		} else if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf,
+					       msg[i].len, NULL, 0) < 0)
+				break;
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+	return i;
+}
+
+
+static u32 au6610_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm au6610_i2c_algo = {
+	.master_xfer   = au6610_i2c_xfer,
+	.functionality = au6610_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int au6610_identify_state(struct usb_device *udev,
+				 struct dvb_usb_device_properties *props,
+				 struct dvb_usb_device_description **desc,
+				 int *cold)
+{
+	*cold = 0;
+	return 0;
+}
+
+static struct zl10353_config au6610_zl10353_config = {
+	.demod_address = 0x1e,
+	.no_tuner = 1,
+	.parallel_ts = 1,
+};
+
+static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	if ((adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
+				   &adap->dev->i2c_adap)) != NULL) {
+		return 0;
+	}
+
+	return -EIO;
+}
+
+static struct qt1010_config au6610_qt1010_config = {
+	.i2c_address = 0xc4
+};
+
+static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	return dvb_attach(qt1010_attach,
+			  adap->fe, &adap->dev->i2c_adap,
+			  &au6610_qt1010_config) == NULL ? -ENODEV : 0;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties au6610_properties;
+
+static int au6610_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
+{
+	struct dvb_usb_device *d;
+	struct usb_host_interface *alt;
+	int ret;
+
+	if (intf->num_altsetting < AU6610_ALTSETTING_COUNT)
+		return -ENODEV;
+
+	if ((ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d)) == 0) {
+		alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
+
+		if (alt == NULL) {
+			deb_rc("no alt found!\n");
+			return -ENODEV;
+		}
+		ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
+					alt->desc.bAlternateSetting);
+	}
+
+	return ret;
+}
+
+
+static struct usb_device_id au6610_table [] = {
+	{ USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) },
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, au6610_table);
+
+static struct dvb_usb_device_properties au6610_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.size_of_priv     = 0,
+	.identify_state   = au6610_identify_state,
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.frontend_attach  = au6610_zl10353_frontend_attach,
+			.tuner_attach     = au6610_qt1010_tuner_attach,
+
+			.stream = {
+				.type = USB_ISOC,
+				.count = 5,
+				.endpoint = 0x82,
+				.u = {
+					.isoc = {
+						.framesperurb = 40,
+						.framesize = 942,   /* maximum packet size */
+						.interval = 1.25,   /* 125 us */
+					}
+				}
+			},
+		}
+	},
+	.i2c_algo = &au6610_i2c_algo,
+	.num_device_descs = 1,
+	.devices = {
+		{
+			"Sigmatek DVB-110 DVB-T USB2.0",
+			{ &au6610_table[0], NULL },
+			{ NULL },
+		},
+	}
+};
+
+static struct usb_driver au6610_driver = {
+	.name       = "dvb_usb_au6610",
+	.probe      = au6610_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table   = au6610_table,
+};
+
+/* module stuff */
+static int __init au6610_module_init(void)
+{
+	int ret;
+
+	if ((ret = usb_register(&au6610_driver))) {
+		err("usb_register failed. Error number %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit au6610_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&au6610_driver);
+}
+
+module_init (au6610_module_init);
+module_exit (au6610_module_exit);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Driver Sigmatek DVB-110 DVB-T USB2.0 / AU6610");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/au6610.h b/drivers/media/dvb/dvb-usb/au6610.h
new file mode 100644
index 0000000..4161b05
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/au6610.h
@@ -0,0 +1,19 @@
+#ifndef _DVB_USB_AU6610_H_
+#define _DVB_USB_AU6610_H_
+
+#define DVB_USB_LOG_PREFIX "au6610"
+#include "dvb-usb.h"
+
+#define deb_rc(args...)   dprintk(dvb_usb_au6610_debug,0x01,args)
+
+#define AU6610_REQ_I2C_WRITE	0x14
+#define AU6610_REQ_I2C_READ	0x13
+#define AU6610_REQ_USB_WRITE	0x16
+#define AU6610_REQ_USB_READ	0x15
+
+#define AU6610_USB_TIMEOUT 1000
+
+#define AU6610_ALTSETTING_COUNT 6
+#define AU6610_ALTSETTING       5
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 55ba020..70df31b 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -27,6 +27,7 @@
 #endif
 	d->i2c_adap.algo      = d->props.i2c_algo;
 	d->i2c_adap.algo_data = NULL;
+	d->i2c_adap.dev.parent = &d->udev->dev;
 
 	i2c_set_adapdata(&d->i2c_adap, d);
 
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 299382d..148386a 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -11,6 +11,7 @@
 
 /* Vendor IDs */
 #define USB_VID_ADSTECH				0x06e1
+#define USB_VID_ALCOR_MICRO		0x058f
 #define USB_VID_ANCHOR				0x0547
 #define USB_VID_AVERMEDIA			0x07ca
 #define USB_VID_COMPRO				0x185b
@@ -29,6 +30,7 @@
 #define USB_VID_LEADTEK				0x0413
 #define USB_VID_LITEON				0x04ca
 #define USB_VID_MEDION				0x1660
+#define USB_VID_MSI				0x0db0
 #define USB_VID_PINNACLE			0x2304
 #define USB_VID_VISIONPLUS			0x13d3
 #define USB_VID_TWINHAN				0x1822
@@ -119,6 +121,8 @@
 #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD		0xdb54
 #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM		0xdb55
 #define USB_PID_MEDION_MD95700				0x0932
+#define USB_PID_MSI_MEGASKY580				0x5580
+#define USB_PID_MSI_MEGASKY580_55801			0x5581
 #define USB_PID_KYE_DVB_T_COLD				0x701e
 #define USB_PID_KYE_DVB_T_WARM				0x701f
 #define USB_PID_PCTV_200E				0x020e
@@ -134,6 +138,7 @@
 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P		0x6f00
 #define USB_PID_GENPIX_8PSK_COLD			0x0200
 #define USB_PID_GENPIX_8PSK_WARM			0x0201
+#define USB_PID_SIGMATEK_DVB_110			0x6610
 
 
 #endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index 19ff597..9511a31 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -151,7 +151,7 @@
 int dvb_usb_remote_exit(struct dvb_usb_device *d)
 {
 	if (d->state & DVB_USB_STATE_REMOTE) {
-		cancel_delayed_work(&d->rc_query_work);
+		cancel_rearming_delayed_work(&d->rc_query_work);
 		flush_scheduled_work();
 		input_unregister_device(d->rc_input_dev);
 	}
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c
new file mode 100644
index 0000000..c9f38a5
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/gl861.c
@@ -0,0 +1,231 @@
+/* DVB USB compliant linux driver for GL861 USB2.0 devices.
+ *
+ *	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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "gl861.h"
+
+#include "zl10353.h"
+#include "qt1010.h"
+
+/* debug */
+int dvb_usb_gl861_debug;
+module_param_named(debug,dvb_usb_gl861_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
+			 u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+	u16 index;
+	u16 value = addr << 8;
+	int wo = (rbuf == NULL || rlen == 0); /* write-only */
+	u8 req, type;
+
+	if (wo) {
+		req = GL861_REQ_I2C_WRITE;
+		type = GL861_WRITE;
+	} else { /* rw */
+		req = GL861_REQ_I2C_READ;
+		type = GL861_READ;
+	}
+
+	switch (wlen) {
+	case 1:
+		index = wbuf[0];
+		break;
+	case 2:
+		index = wbuf[0];
+		value = value + wbuf[1];
+		break;
+	default:
+		warn("wlen = %x, aborting.", wlen);
+		return -EINVAL;
+	}
+
+	return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
+			       value, index, rbuf, rlen, 2000);
+}
+
+/* I2C */
+static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+			  int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int i;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	if (num > 2)
+		return -EINVAL;
+
+	for (i = 0; i < num; i++) {
+		/* write/read request */
+		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
+					  msg[i].len, msg[i+1].buf, msg[i+1].len) < 0)
+				break;
+			i++;
+		} else
+			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
+					  msg[i].len, NULL, 0) < 0)
+				break;
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+	return i;
+}
+
+static u32 gl861_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm gl861_i2c_algo = {
+	.master_xfer   = gl861_i2c_xfer,
+	.functionality = gl861_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int gl861_identify_state(struct usb_device *udev,
+				struct dvb_usb_device_properties *props,
+				struct dvb_usb_device_description **desc,
+				int *cold)
+{
+	*cold = 0;
+
+	return 0;
+}
+
+static struct zl10353_config gl861_zl10353_config = {
+	.demod_address = 0x1e,
+	.no_tuner = 1,
+	.parallel_ts = 1,
+};
+
+static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	if ((adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
+				   &adap->dev->i2c_adap)) != NULL) {
+		return 0;
+	}
+
+	return -EIO;
+}
+
+static struct qt1010_config gl861_qt1010_config = {
+	.i2c_address = 0xc4
+};
+
+static int gl861_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	return dvb_attach(qt1010_attach,
+			  adap->fe, &adap->dev->i2c_adap,
+			  &gl861_qt1010_config) == NULL ? -ENODEV : 0;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties gl861_properties;
+
+static int gl861_probe(struct usb_interface *intf,
+		       const struct usb_device_id *id)
+{
+	struct dvb_usb_device *d;
+	struct usb_host_interface *alt;
+	int ret;
+
+	if (intf->num_altsetting < 2)
+		return -ENODEV;
+
+	if ((ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d)) == 0) {
+		alt = usb_altnum_to_altsetting(intf, 0);
+
+		if (alt == NULL) {
+			deb_rc("not alt found!\n");
+			return -ENODEV;
+		}
+
+		ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
+					alt->desc.bAlternateSetting);
+	}
+
+	return ret;
+}
+
+static struct usb_device_id gl861_table [] = {
+		{ USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801) },
+		{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, gl861_table);
+
+static struct dvb_usb_device_properties gl861_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+
+	.size_of_priv     = 0,
+
+	.identify_state   = gl861_identify_state,
+	.num_adapters = 1,
+	.adapter = {{
+
+		.frontend_attach  = gl861_frontend_attach,
+		.tuner_attach     = gl861_tuner_attach,
+
+		.stream = {
+			.type = USB_BULK,
+			.count = 7,
+			.endpoint = 0x81,
+			.u = {
+				.bulk = {
+					.buffersize = 512,
+				}
+			}
+		},
+	}},
+	.i2c_algo         = &gl861_i2c_algo,
+
+	.num_device_descs = 1,
+	.devices = {
+		{   "MSI Mega Sky 55801 DVB-T USB2.0",
+			{ &gl861_table[0], NULL },
+			{ NULL },
+		},
+	}
+};
+
+static struct usb_driver gl861_driver = {
+	.name		= "dvb_usb_gl861",
+	.probe		= gl861_probe,
+	.disconnect	= dvb_usb_device_exit,
+	.id_table	= gl861_table,
+};
+
+/* module stuff */
+static int __init gl861_module_init(void)
+{
+	int ret;
+
+	if ((ret = usb_register(&gl861_driver))) {
+		err("usb_register failed. Error number %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit gl861_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&gl861_driver);
+}
+
+module_init (gl861_module_init);
+module_exit (gl861_module_exit);
+
+MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>");
+MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/gl861.h b/drivers/media/dvb/dvb-usb/gl861.h
new file mode 100644
index 0000000..72a51af
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/gl861.h
@@ -0,0 +1,15 @@
+#ifndef _DVB_USB_GL861_H_
+#define _DVB_USB_GL861_H_
+
+#define DVB_USB_LOG_PREFIX "gl861"
+#include "dvb-usb.h"
+
+#define deb_rc(args...)   dprintk(dvb_usb_gl861_debug,0x01,args)
+
+#define GL861_WRITE		0x40
+#define GL861_READ		0xc0
+
+#define GL861_REQ_I2C_WRITE	0x01
+#define GL861_REQ_I2C_READ	0x02
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
new file mode 100644
index 0000000..d48b24d
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/m920x.c
@@ -0,0 +1,541 @@
+/* DVB USB compliant linux driver for MSI Mega Sky 580 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+#include "m920x.h"
+
+#include "mt352.h"
+#include "mt352_priv.h"
+#include "qt1010.h"
+
+/* debug */
+static int dvb_usb_m920x_debug;
+module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+static struct dvb_usb_rc_key megasky_rc_keys [] = {
+	{ 0x0, 0x12, KEY_POWER },
+	{ 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */
+	{ 0x0, 0x02, KEY_CHANNELUP },
+	{ 0x0, 0x05, KEY_CHANNELDOWN },
+	{ 0x0, 0x03, KEY_VOLUMEUP },
+	{ 0x0, 0x06, KEY_VOLUMEDOWN },
+	{ 0x0, 0x04, KEY_MUTE },
+	{ 0x0, 0x07, KEY_OK }, /* TS */
+	{ 0x0, 0x08, KEY_STOP },
+	{ 0x0, 0x09, KEY_MENU }, /* swap */
+	{ 0x0, 0x0a, KEY_REWIND },
+	{ 0x0, 0x1b, KEY_PAUSE },
+	{ 0x0, 0x1f, KEY_FASTFORWARD },
+	{ 0x0, 0x0c, KEY_RECORD },
+	{ 0x0, 0x0d, KEY_CAMERA }, /* screenshot */
+	{ 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */
+};
+
+static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\
+			     u16 index, void *data, int size)
+{
+	int ret;
+
+	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+			      request, USB_TYPE_VENDOR | USB_DIR_IN,
+			      value, index, data, size, 2000);
+	if (ret < 0)
+		return ret;
+
+	if (ret != size)
+		return -EIO;
+
+	return 0;
+}
+
+static inline int m9206_write(struct usb_device *udev, u8 request,
+			      u16 value, u16 index)
+{
+	int ret;
+
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			      request, USB_TYPE_VENDOR | USB_DIR_OUT,
+			      value, index, NULL, 0, 2000);
+	return ret;
+}
+
+static int m9206_rc_init(struct usb_device *udev)
+{
+	int ret = 0;
+
+	/* Remote controller init. */
+	if ((ret = m9206_write(udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0)
+		return ret;
+
+	if ((ret = m9206_write(udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0)
+		return ret;
+
+	return ret;
+}
+
+static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+	struct m9206_state *m = d->priv;
+	int i, ret = 0;
+	u8 rc_state[2];
+
+
+	if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
+		goto unlock;
+
+	if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
+		goto unlock;
+
+	for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++)
+		if (megasky_rc_keys[i].data == rc_state[1]) {
+			*event = megasky_rc_keys[i].event;
+
+			switch(rc_state[0]) {
+			case 0x80:
+				*state = REMOTE_NO_KEY_PRESSED;
+				goto unlock;
+
+			case 0x93:
+			case 0x92:
+				m->rep_count = 0;
+				*state = REMOTE_KEY_PRESSED;
+				goto unlock;
+
+			case 0x91:
+				/* For comfort. */
+				if (++m->rep_count > 2)
+					*state = REMOTE_KEY_REPEAT;
+				goto unlock;
+
+			default:
+				deb_rc("Unexpected rc response %x\n", rc_state[0]);
+				*state = REMOTE_NO_KEY_PRESSED;
+				goto unlock;
+			}
+		}
+
+	if (rc_state[1] != 0)
+		deb_rc("Unknown rc key %x\n", rc_state[1]);
+
+	*state = REMOTE_NO_KEY_PRESSED;
+
+	unlock:
+
+	return ret;
+}
+
+/* I2C */
+static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+			  int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	struct m9206_state *m = d->priv;
+	int i;
+	int ret = 0;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	if (num > 2)
+		return -EINVAL;
+
+	for (i = 0; i < num; i++) {
+		if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].addr, 0x80)) != 0)
+			goto unlock;
+
+		if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[0], 0x0)) != 0)
+			goto unlock;
+
+		if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) {
+			int i2c_i;
+
+			for (i2c_i = 0; i2c_i < M9206_I2C_MAX; i2c_i++)
+				if (msg[i].addr == m->i2c_r[i2c_i].addr)
+					break;
+
+			if (i2c_i >= M9206_I2C_MAX) {
+				deb_rc("No magic for i2c addr!\n");
+				ret = -EINVAL;
+				goto unlock;
+			}
+
+			if ((ret = m9206_write(d->udev, M9206_I2C, m->i2c_r[i2c_i].magic, 0x80)) != 0)
+				goto unlock;
+
+			if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0)
+				goto unlock;
+
+			i++;
+		} else {
+			if (msg[i].len != 2)
+				return -EINVAL;
+
+			if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[1], 0x40)) != 0)
+				goto unlock;
+		}
+	}
+	ret = i;
+	unlock:
+	mutex_unlock(&d->i2c_mutex);
+
+	return ret;
+}
+
+static u32 m9206_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm m9206_i2c_algo = {
+	.master_xfer   = m9206_i2c_xfer,
+	.functionality = m9206_i2c_func,
+};
+
+
+static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx,
+			    int pid)
+{
+	int ret = 0;
+
+	if (pid >= 0x8000)
+		return -EINVAL;
+
+	pid |= 0x8000;
+
+	if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
+		return ret;
+
+	if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
+		return ret;
+
+	return ret;
+}
+
+static int m9206_update_filters(struct dvb_usb_adapter *adap)
+{
+	struct m9206_state *m = adap->dev->priv;
+	int enabled = m->filtering_enabled;
+	int i, ret = 0, filter = 0;
+
+	for (i = 0; i < M9206_MAX_FILTERS; i++)
+		if (m->filters[i] == 8192)
+			enabled = 0;
+
+	/* Disable all filters */
+	if ((ret = m9206_set_filter(adap, 0x81, 1, enabled)) != 0)
+		return ret;
+
+	for (i = 0; i < M9206_MAX_FILTERS; i++)
+		if ((ret = m9206_set_filter(adap, 0x81, i + 2, 0)) != 0)
+			return ret;
+
+	if ((ret = m9206_set_filter(adap, 0x82, 0, 0x0)) != 0)
+		return ret;
+
+	/* Set */
+	if (enabled) {
+		for (i = 0; i < M9206_MAX_FILTERS; i++) {
+			if (m->filters[i] == 0)
+				continue;
+
+			if ((ret = m9206_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0)
+				return ret;
+
+			filter++;
+		}
+	}
+
+	if ((ret = m9206_set_filter(adap, 0x82, 0, 0x02f5)) != 0)
+		return ret;
+
+	return ret;
+}
+
+static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	struct m9206_state *m = adap->dev->priv;
+
+	m->filtering_enabled = onoff ? 1 : 0;
+
+	return m9206_update_filters(adap);
+}
+
+static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
+			    int onoff)
+{
+	struct m9206_state *m = adap->dev->priv;
+
+	m->filters[index] = onoff ? pid : 0;
+
+	return m9206_update_filters(adap);
+}
+
+static int m9206_firmware_download(struct usb_device *udev,
+				   const struct firmware *fw)
+{
+	u16 value, index, size;
+	u8 read[4], *buff;
+	int i, pass, ret = 0;
+
+	buff = kmalloc(65536, GFP_KERNEL);
+
+	if ((ret = m9206_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
+		goto done;
+	deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
+
+	if ((ret = m9206_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
+		goto done;
+	deb_rc("%x\n", read[0]);
+
+	for (pass = 0; pass < 2; pass++) {
+		for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
+			value = le16_to_cpu(*(u16 *)(fw->data + i));
+			i += sizeof(u16);
+
+			index = le16_to_cpu(*(u16 *)(fw->data + i));
+			i += sizeof(u16);
+
+			size = le16_to_cpu(*(u16 *)(fw->data + i));
+			i += sizeof(u16);
+
+			if (pass == 1) {
+				/* Will stall if using fw->data ... */
+				memcpy(buff, fw->data + i, size);
+
+				ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
+					    M9206_FW,
+					    USB_TYPE_VENDOR | USB_DIR_OUT,
+					    value, index, buff, size, 20);
+				if (ret != size) {
+					deb_rc("error while uploading fw!\n");
+					ret = -EIO;
+					goto done;
+				}
+				msleep(3);
+			}
+			i += size;
+		}
+		if (i != fw->size) {
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	msleep(36);
+
+	/* m9206 will disconnect itself from the bus after this. */
+	(void) m9206_write(udev, M9206_CORE, 0x01, M9206_FW_GO);
+	deb_rc("firmware uploaded!\n");
+
+	done:
+	kfree(buff);
+
+	return ret;
+}
+
+/* Callbacks for DVB USB */
+static int megasky_identify_state(struct usb_device *udev,
+				  struct dvb_usb_device_properties *props,
+				  struct dvb_usb_device_description **desc,
+				  int *cold)
+{
+	struct usb_host_interface *alt;
+
+	alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1);
+	*cold = (alt == NULL) ? 1 : 0;
+
+	return 0;
+}
+
+static int megasky_mt352_demod_init(struct dvb_frontend *fe)
+{
+	u8 config[] = { CONFIG, 0x3d };
+	u8 clock[] = { CLOCK_CTL, 0x30 };
+	u8 reset[] = { RESET, 0x80 };
+	u8 adc_ctl[] = { ADC_CTL_1, 0x40 };
+	u8 agc[] = { AGC_TARGET, 0x1c, 0x20 };
+	u8 sec_agc[] = { 0x69, 0x00, 0xff, 0xff, 0x40, 0xff, 0x00, 0x40, 0x40 };
+	u8 unk1[] = { 0x93, 0x1a };
+	u8 unk2[] = { 0xb5, 0x7a };
+
+	mt352_write(fe, config, ARRAY_SIZE(config));
+	mt352_write(fe, clock, ARRAY_SIZE(clock));
+	mt352_write(fe, reset, ARRAY_SIZE(reset));
+	mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl));
+	mt352_write(fe, agc, ARRAY_SIZE(agc));
+	mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc));
+	mt352_write(fe, unk1, ARRAY_SIZE(unk1));
+	mt352_write(fe, unk2, ARRAY_SIZE(unk2));
+
+	deb_rc("Demod init!\n");
+
+	return 0;
+}
+
+static struct mt352_config megasky_mt352_config = {
+	.demod_address = 0x1e,
+	.no_tuner = 1,
+	.demod_init = megasky_mt352_demod_init,
+};
+
+static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct m9206_state *m = adap->dev->priv;
+
+	deb_rc("megasky_frontend_attach!\n");
+
+	m->i2c_r[M9206_I2C_DEMOD].addr = megasky_mt352_config.demod_address;
+	m->i2c_r[M9206_I2C_DEMOD].magic = 0x1f;
+
+	if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL)
+		return -EIO;
+
+	return 0;
+}
+
+static struct qt1010_config megasky_qt1010_config = {
+	.i2c_address = 0xc4
+};
+
+static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	struct m9206_state *m = adap->dev->priv;
+
+	m->i2c_r[M9206_I2C_TUNER].addr = megasky_qt1010_config.i2c_address;
+	m->i2c_r[M9206_I2C_TUNER].magic = 0xc5;
+
+	if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
+		       &megasky_qt1010_config) == NULL)
+		return -ENODEV;
+
+	return 0;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties megasky_properties;
+
+static int m920x_probe(struct usb_interface *intf,
+		       const struct usb_device_id *id)
+{
+	struct dvb_usb_device *d;
+	struct usb_host_interface *alt;
+	int ret;
+
+	if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) {
+		deb_rc("probed!\n");
+
+		alt = usb_altnum_to_altsetting(intf, 1);
+		if (alt == NULL) {
+			deb_rc("not alt found!\n");
+			return -ENODEV;
+		}
+
+		ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
+					alt->desc.bAlternateSetting);
+		if (ret < 0)
+			return ret;
+
+		deb_rc("Changed to alternate setting!\n");
+
+		if ((ret = m9206_rc_init(d->udev)) != 0)
+			return ret;
+	}
+	return ret;
+}
+
+static struct usb_device_id m920x_table [] = {
+		{ USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) },
+		{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, m920x_table);
+
+static struct dvb_usb_device_properties megasky_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.firmware = "dvb-usb-megasky-02.fw",
+	.download_firmware = m9206_firmware_download,
+
+	.rc_interval      = 100,
+	.rc_key_map       = megasky_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(megasky_rc_keys),
+	.rc_query         = m9206_rc_query,
+
+	.size_of_priv     = sizeof(struct m9206_state),
+
+	.identify_state   = megasky_identify_state,
+	.num_adapters = 1,
+	.adapter = {{
+		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
+			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+		.pid_filter_count = 8,
+		.pid_filter       = m9206_pid_filter,
+		.pid_filter_ctrl  = m9206_pid_filter_ctrl,
+
+		.frontend_attach  = megasky_mt352_frontend_attach,
+		.tuner_attach     = megasky_qt1010_tuner_attach,
+
+		.stream = {
+			.type = USB_BULK,
+			.count = 8,
+			.endpoint = 0x81,
+			.u = {
+				.bulk = {
+					.buffersize = 512,
+				}
+			}
+		},
+	}},
+	.i2c_algo         = &m9206_i2c_algo,
+
+	.num_device_descs = 1,
+	.devices = {
+		{   "MSI Mega Sky 580 DVB-T USB2.0",
+			{ &m920x_table[0], NULL },
+			{ NULL },
+		},
+	}
+};
+
+static struct usb_driver m920x_driver = {
+	.name		= "dvb_usb_m920x",
+	.probe		= m920x_probe,
+	.disconnect	= dvb_usb_device_exit,
+	.id_table	= m920x_table,
+};
+
+/* module stuff */
+static int __init m920x_module_init(void)
+{
+	int ret;
+
+	if ((ret = usb_register(&m920x_driver))) {
+		err("usb_register failed. Error number %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit m920x_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&m920x_driver);
+}
+
+module_init (m920x_module_init);
+module_exit (m920x_module_exit);
+
+MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
+MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h
new file mode 100644
index 0000000..c354196
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/m920x.h
@@ -0,0 +1,35 @@
+#ifndef _DVB_USB_M920X_H_
+#define _DVB_USB_M920X_H_
+
+#define DVB_USB_LOG_PREFIX "m920x"
+#include "dvb-usb.h"
+
+#define deb_rc(args...)   dprintk(dvb_usb_m920x_debug,0x01,args)
+
+#define M9206_CORE	0x22
+#define M9206_RC_STATE	0xff51
+#define M9206_RC_KEY	0xff52
+#define M9206_RC_INIT1	0xff54
+#define M9206_RC_INIT2	0xff55
+#define M9206_FW_GO	0xff69
+
+#define M9206_I2C	0x23
+#define M9206_FILTER	0x25
+#define M9206_FW	0x30
+
+#define M9206_MAX_FILTERS 8
+
+#define M9206_I2C_TUNER	0
+#define M9206_I2C_DEMOD	1
+#define M9206_I2C_MAX	2
+
+struct m9206_state {
+	u16 filters[M9206_MAX_FILTERS];
+	int filtering_enabled;
+	int rep_count;
+	struct {
+		unsigned char addr;
+		unsigned char magic;
+	}i2c_r[M9206_I2C_MAX];
+};
+#endif
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index af314bb..22c2cf2 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -290,6 +290,13 @@
 	help
 	  A DVB-S silicon tuner module. Say Y when you want to support this tuner.
 
+config DVB_TUNER_QT1010
+	tristate "Quantek QT1010 silicon tuner"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A driver for the silicon tuner QT1010 from Quantek.
+
 config DVB_TUNER_MT2060
 	tristate "Microtune MT2060 silicon IF tuner"
 	depends on I2C
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 3fa6e5d..a646d99 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -38,5 +38,6 @@
 obj-$(CONFIG_DVB_TDA10086) += tda10086.o
 obj-$(CONFIG_DVB_TDA826X) += tda826x.o
 obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
+obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o
 obj-$(CONFIG_DVB_TUA6100) += tua6100.o
 obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index ae96395..10fc0c8 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -254,7 +254,7 @@
 	if (srate<500000)
 		srate=500000;
 
-	for(i=0;(i<sizeof(bands)/sizeof(bands[0]))&&(srate>bands[i]);i++)
+	for(i = 0; (i < ARRAY_SIZE(bands)) && (srate>bands[i]); i++)
 		;
 	/* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz,
 	   and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult,
@@ -361,7 +361,7 @@
 
 	dprintk("%s: init chip\n", __FUNCTION__);
 
-	for(i=0;i<sizeof(cx24110_regdata)/sizeof(cx24110_regdata[0]);i++) {
+	for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
 		cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
 	};
 
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
index a356d28..732e94a 100644
--- a/drivers/media/dvb/frontends/cx24123.c
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -507,7 +507,7 @@
 	int i = 0;
 	int pump = 2;
 	int band = 0;
-	int num_bands = sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]);
+	int num_bands = ARRAY_SIZE(cx24123_bandselect_vals);
 
 	/* Defaults for low freq, low rate */
 	state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
@@ -516,7 +516,7 @@
 	vco_div = cx24123_bandselect_vals[0].VCOdivider;
 
 	/* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */
-	for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++)
 	{
 		if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
 		    (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
@@ -658,7 +658,7 @@
 	dprintk("%s:  init frontend\n",__FUNCTION__);
 
 	/* Configure the demod to a good set of defaults */
-	for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
 		cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
 
 	/* Set the LNB polarity */
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index adbabfd..b6adea5 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -239,7 +239,7 @@
 		default:
 			return -EINVAL;
 	}
-	deb_setf("hierachy: ");
+	deb_setf("hierarchy: ");
 	switch (ofdm->hierarchy_information) {
 		case HIERARCHY_NONE:
 			deb_setf("none ");
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 23aa75a..054d7e6 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -475,7 +475,7 @@
 	tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha;
 	dib3000mc_write_word(state, 0, tmp);
 
-	dib3000mc_write_word(state, 5, seq);
+	dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
 
 	tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp);
 	if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp))
diff --git a/drivers/media/dvb/frontends/qt1010.c b/drivers/media/dvb/frontends/qt1010.c
new file mode 100644
index 0000000..825aa14
--- /dev/null
+++ b/drivers/media/dvb/frontends/qt1010.c
@@ -0,0 +1,485 @@
+/*
+ *  Driver for Quantek QT1010 silicon tuner
+ *
+ *  Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *                     Aapo Tahkola <aet@rasterburn.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "qt1010.h"
+#include "qt1010_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "QT1010: " args); \
+	} while (0)
+
+/* read single register */
+static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val)
+{
+	struct i2c_msg msg[2] = {
+		{ .addr = priv->cfg->i2c_address,
+		  .flags = 0, .buf = &reg, .len = 1 },
+		{ .addr = priv->cfg->i2c_address,
+		  .flags = I2C_M_RD, .buf = val, .len = 1 },
+	};
+
+	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+		printk(KERN_WARNING "qt1010 I2C read failed\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+/* write single register */
+static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val)
+{
+	u8 buf[2] = { reg, val };
+	struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+			       .flags = 0, .buf = buf, .len = 2 };
+
+	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+		printk(KERN_WARNING "qt1010 I2C write failed\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+/* dump all registers */
+static void qt1010_dump_regs(struct qt1010_priv *priv)
+{
+	char buf[52], buf2[4];
+	u8 reg, val;
+
+	for (reg = 0; ; reg++) {
+		if (reg % 16 == 0) {
+			if (reg)
+				printk("%s\n", buf);
+			sprintf(buf, "%02x: ", reg);
+		}
+		if (qt1010_readreg(priv, reg, &val) == 0)
+			sprintf(buf2, "%02x ", val);
+		else
+			strcpy(buf2, "-- ");
+		strcat(buf, buf2);
+		if (reg == 0x2f)
+			break;
+	}
+	printk("%s\n", buf);
+}
+
+static int qt1010_set_params(struct dvb_frontend *fe,
+			     struct dvb_frontend_parameters *params)
+{
+	struct qt1010_priv *priv;
+	int err;
+	u32 freq, div, mod1, mod2;
+	u8 i, tmpval, reg05;
+	qt1010_i2c_oper_t rd[48] = {
+		{ QT1010_WR, 0x01, 0x80 },
+		{ QT1010_WR, 0x02, 0x3f },
+		{ QT1010_WR, 0x05, 0xff }, /* 02 c write */
+		{ QT1010_WR, 0x06, 0x44 },
+		{ QT1010_WR, 0x07, 0xff }, /* 04 c write */
+		{ QT1010_WR, 0x08, 0x08 },
+		{ QT1010_WR, 0x09, 0xff }, /* 06 c write */
+		{ QT1010_WR, 0x0a, 0xff }, /* 07 c write */
+		{ QT1010_WR, 0x0b, 0xff }, /* 08 c write */
+		{ QT1010_WR, 0x0c, 0xe1 },
+		{ QT1010_WR, 0x1a, 0xff }, /* 10 c write */
+		{ QT1010_WR, 0x1b, 0x00 },
+		{ QT1010_WR, 0x1c, 0x89 },
+		{ QT1010_WR, 0x11, 0xff }, /* 13 c write */
+		{ QT1010_WR, 0x12, 0xff }, /* 14 c write */
+		{ QT1010_WR, 0x22, 0xff }, /* 15 c write */
+		{ QT1010_WR, 0x1e, 0x00 },
+		{ QT1010_WR, 0x1e, 0xd0 },
+		{ QT1010_RD, 0x22, 0xff }, /* 16 c read */
+		{ QT1010_WR, 0x1e, 0x00 },
+		{ QT1010_RD, 0x05, 0xff }, /* 20 c read */
+		{ QT1010_RD, 0x22, 0xff }, /* 21 c read */
+		{ QT1010_WR, 0x23, 0xd0 },
+		{ QT1010_WR, 0x1e, 0x00 },
+		{ QT1010_WR, 0x1e, 0xe0 },
+		{ QT1010_RD, 0x23, 0xff }, /* 25 c read */
+		{ QT1010_RD, 0x23, 0xff }, /* 26 c read */
+		{ QT1010_WR, 0x1e, 0x00 },
+		{ QT1010_WR, 0x24, 0xd0 },
+		{ QT1010_WR, 0x1e, 0x00 },
+		{ QT1010_WR, 0x1e, 0xf0 },
+		{ QT1010_RD, 0x24, 0xff }, /* 31 c read */
+		{ QT1010_WR, 0x1e, 0x00 },
+		{ QT1010_WR, 0x14, 0x7f },
+		{ QT1010_WR, 0x15, 0x7f },
+		{ QT1010_WR, 0x05, 0xff }, /* 35 c write */
+		{ QT1010_WR, 0x06, 0x00 },
+		{ QT1010_WR, 0x15, 0x1f },
+		{ QT1010_WR, 0x16, 0xff },
+		{ QT1010_WR, 0x18, 0xff },
+		{ QT1010_WR, 0x1f, 0xff }, /* 40 c write */
+		{ QT1010_WR, 0x20, 0xff }, /* 41 c write */
+		{ QT1010_WR, 0x21, 0x53 },
+		{ QT1010_WR, 0x25, 0xff }, /* 43 c write */
+		{ QT1010_WR, 0x26, 0x15 },
+		{ QT1010_WR, 0x00, 0xff }, /* 45 c write */
+		{ QT1010_WR, 0x02, 0x00 },
+		{ QT1010_WR, 0x01, 0x00 }
+	};
+
+#define FREQ1 32000000 /* 32 MHz */
+#define FREQ2  4000000 /* 4 MHz Quartz oscillator in the stick? */
+
+	priv = fe->tuner_priv;
+	freq = params->frequency;
+	div = (freq + QT1010_OFFSET) / QT1010_STEP;
+	freq = (div * QT1010_STEP) - QT1010_OFFSET;
+	mod1 = (freq + QT1010_OFFSET) % FREQ1;
+	mod2 = (freq + QT1010_OFFSET) % FREQ2;
+	priv->bandwidth =
+		(fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+	priv->frequency = freq;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+	/* reg 05 base value */
+	if      (freq < 290000000) reg05 = 0x14; /* 290 MHz */
+	else if (freq < 610000000) reg05 = 0x34; /* 610 MHz */
+	else if (freq < 802000000) reg05 = 0x54; /* 802 MHz */
+	else                       reg05 = 0x74;
+
+	/* 0x5 */
+	rd[2].val = reg05;
+
+	/* 07 - set frequency: 32 MHz scale */
+	rd[4].val = (freq + QT1010_OFFSET) / FREQ1;
+
+	/* 09 - changes every 8/24 MHz */
+	if (mod1 < 8000000) rd[6].val = 0x1d;
+	else                rd[6].val = 0x1c;
+
+	/* 0a - set frequency: 4 MHz scale (max 28 MHz) */
+	if      (mod1 < 1*FREQ2) rd[7].val = 0x09; /*  +0 MHz */
+	else if (mod1 < 2*FREQ2) rd[7].val = 0x08; /*  +4 MHz */
+	else if (mod1 < 3*FREQ2) rd[7].val = 0x0f; /*  +8 MHz */
+	else if (mod1 < 4*FREQ2) rd[7].val = 0x0e; /* +12 MHz */
+	else if (mod1 < 5*FREQ2) rd[7].val = 0x0d; /* +16 MHz */
+	else if (mod1 < 6*FREQ2) rd[7].val = 0x0c; /* +20 MHz */
+	else if (mod1 < 7*FREQ2) rd[7].val = 0x0b; /* +24 MHz */
+	else                     rd[7].val = 0x0a; /* +28 MHz */
+
+	/* 0b - changes every 2/2 MHz */
+	if (mod2 < 2000000) rd[8].val = 0x45;
+	else                rd[8].val = 0x44;
+
+	/* 1a - set frequency: 125 kHz scale (max 3875 kHz)*/
+	tmpval = 0x78; /* byte, overflows intentionally */
+	rd[10].val = tmpval-((mod2/QT1010_STEP)*0x08);
+
+	/* 11 */
+	rd[13].val = 0xfd; /* TODO: correct value calculation */
+
+	/* 12 */
+	rd[14].val = 0x91; /* TODO: correct value calculation */
+
+	/* 22 */
+	if      (freq < 450000000) rd[15].val = 0xd0; /* 450 MHz */
+	else if (freq < 482000000) rd[15].val = 0xd1; /* 482 MHz */
+	else if (freq < 514000000) rd[15].val = 0xd4; /* 514 MHz */
+	else if (freq < 546000000) rd[15].val = 0xd7; /* 546 MHz */
+	else if (freq < 610000000) rd[15].val = 0xda; /* 610 MHz */
+	else                       rd[15].val = 0xd0;
+
+	/* 05 */
+	rd[35].val = (reg05 & 0xf0);
+
+	/* 1f */
+	if      (mod1 <  8000000) tmpval = 0x00;
+	else if (mod1 < 12000000) tmpval = 0x01;
+	else if (mod1 < 16000000) tmpval = 0x02;
+	else if (mod1 < 24000000) tmpval = 0x03;
+	else if (mod1 < 28000000) tmpval = 0x04;
+	else                      tmpval = 0x05;
+	rd[40].val = (priv->reg1f_init_val + 0x0e + tmpval);
+
+	/* 20 */
+	if      (mod1 <  8000000) tmpval = 0x00;
+	else if (mod1 < 12000000) tmpval = 0x01;
+	else if (mod1 < 20000000) tmpval = 0x02;
+	else if (mod1 < 24000000) tmpval = 0x03;
+	else if (mod1 < 28000000) tmpval = 0x04;
+	else                      tmpval = 0x05;
+	rd[41].val = (priv->reg20_init_val + 0x0d + tmpval);
+
+	/* 25 */
+	rd[43].val = priv->reg25_init_val;
+
+	/* 00 */
+	rd[45].val = 0x92; /* TODO: correct value calculation */
+
+	dprintk("freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \
+		"1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \
+		"20:%02x 25:%02x 00:%02x", \
+		freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, rd[8].val, \
+		rd[10].val, rd[13].val, rd[14].val, rd[15].val, rd[35].val, \
+		rd[40].val, rd[41].val, rd[43].val, rd[45].val);
+
+	for (i = 0; i < ARRAY_SIZE(rd); i++) {
+		if (rd[i].oper == QT1010_WR) {
+			err = qt1010_writereg(priv, rd[i].reg, rd[i].val);
+		} else { /* read is required to proper locking */
+			err = qt1010_readreg(priv, rd[i].reg, &tmpval);
+		}
+		if (err) return err;
+	}
+
+	if (debug)
+		qt1010_dump_regs(priv);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+	return 0;
+}
+
+static int qt1010_init_meas1(struct qt1010_priv *priv,
+			     u8 oper, u8 reg, u8 reg_init_val, u8 *retval)
+{
+	u8 i, val1, val2;
+	int err;
+
+	qt1010_i2c_oper_t i2c_data[] = {
+		{ QT1010_WR, reg, reg_init_val },
+		{ QT1010_WR, 0x1e, 0x00 },
+		{ QT1010_WR, 0x1e, oper },
+		{ QT1010_RD, reg, 0xff }
+	};
+
+	for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
+		if (i2c_data[i].oper == QT1010_WR) {
+			err = qt1010_writereg(priv, i2c_data[i].reg,
+					      i2c_data[i].val);
+		} else {
+			err = qt1010_readreg(priv, i2c_data[i].reg, &val2);
+		}
+		if (err) return err;
+	}
+
+	do {
+		val1 = val2;
+		err = qt1010_readreg(priv, reg, &val2);
+		if (err) return err;
+		dprintk("compare reg:%02x %02x %02x", reg, val1, val2);
+	} while (val1 != val2);
+	*retval = val1;
+
+	return qt1010_writereg(priv, 0x1e, 0x00);
+}
+
+static u8 qt1010_init_meas2(struct qt1010_priv *priv,
+			    u8 reg_init_val, u8 *retval)
+{
+	u8 i, val;
+	int err;
+	qt1010_i2c_oper_t i2c_data[] = {
+		{ QT1010_WR, 0x07, reg_init_val },
+		{ QT1010_WR, 0x22, 0xd0 },
+		{ QT1010_WR, 0x1e, 0x00 },
+		{ QT1010_WR, 0x1e, 0xd0 },
+		{ QT1010_RD, 0x22, 0xff },
+		{ QT1010_WR, 0x1e, 0x00 },
+		{ QT1010_WR, 0x22, 0xff }
+	};
+	for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
+		if (i2c_data[i].oper == QT1010_WR) {
+			err = qt1010_writereg(priv, i2c_data[i].reg,
+					      i2c_data[i].val);
+		} else {
+			err = qt1010_readreg(priv, i2c_data[i].reg, &val);
+		}
+		if (err) return err;
+	}
+	*retval = val;
+	return 0;
+}
+
+static int qt1010_init(struct dvb_frontend *fe)
+{
+	struct qt1010_priv *priv = fe->tuner_priv;
+	struct dvb_frontend_parameters params;
+	int err = 0;
+	u8 i, tmpval, *valptr = NULL;
+
+	qt1010_i2c_oper_t i2c_data[] = {
+		{ QT1010_WR, 0x01, 0x80 },
+		{ QT1010_WR, 0x0d, 0x84 },
+		{ QT1010_WR, 0x0e, 0xb7 },
+		{ QT1010_WR, 0x2a, 0x23 },
+		{ QT1010_WR, 0x2c, 0xdc },
+		{ QT1010_M1, 0x25, 0x40 }, /* get reg 25 init value */
+		{ QT1010_M1, 0x81, 0xff }, /* get reg 25 init value */
+		{ QT1010_WR, 0x2b, 0x70 },
+		{ QT1010_WR, 0x2a, 0x23 },
+		{ QT1010_M1, 0x26, 0x08 },
+		{ QT1010_M1, 0x82, 0xff },
+		{ QT1010_WR, 0x05, 0x14 },
+		{ QT1010_WR, 0x06, 0x44 },
+		{ QT1010_WR, 0x07, 0x28 },
+		{ QT1010_WR, 0x08, 0x0b },
+		{ QT1010_WR, 0x11, 0xfd },
+		{ QT1010_M1, 0x22, 0x0d },
+		{ QT1010_M1, 0xd0, 0xff },
+		{ QT1010_WR, 0x06, 0x40 },
+		{ QT1010_WR, 0x16, 0xf0 },
+		{ QT1010_WR, 0x02, 0x38 },
+		{ QT1010_WR, 0x03, 0x18 },
+		{ QT1010_WR, 0x20, 0xe0 },
+		{ QT1010_M1, 0x1f, 0x20 }, /* get reg 1f init value */
+		{ QT1010_M1, 0x84, 0xff }, /* get reg 1f init value */
+		{ QT1010_RD, 0x20, 0x20 }, /* get reg 20 init value */
+		{ QT1010_WR, 0x03, 0x19 },
+		{ QT1010_WR, 0x02, 0x3f },
+		{ QT1010_WR, 0x21, 0x53 },
+		{ QT1010_RD, 0x21, 0xff },
+		{ QT1010_WR, 0x11, 0xfd },
+		{ QT1010_WR, 0x05, 0x34 },
+		{ QT1010_WR, 0x06, 0x44 },
+		{ QT1010_WR, 0x08, 0x08 }
+	};
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+	for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
+		switch (i2c_data[i].oper) {
+		case QT1010_WR:
+			err = qt1010_writereg(priv, i2c_data[i].reg,
+					      i2c_data[i].val);
+			break;
+		case QT1010_RD:
+			if (i2c_data[i].val == 0x20)
+				valptr = &priv->reg20_init_val;
+			else
+				valptr = &tmpval;
+			err = qt1010_readreg(priv, i2c_data[i].reg, valptr);
+			break;
+		case QT1010_M1:
+			if (i2c_data[i].val == 0x25)
+				valptr = &priv->reg25_init_val;
+			else if (i2c_data[i].val == 0x1f)
+				valptr = &priv->reg1f_init_val;
+			else
+				valptr = &tmpval;
+			err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
+						i2c_data[i].reg,
+						i2c_data[i].val, valptr);
+			i++;
+			break;
+		}
+		if (err) return err;
+	}
+
+	for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */
+		if ((err = qt1010_init_meas2(priv, i, &tmpval)))
+			return err;
+
+	params.frequency = 545000000; /* Sigmatek DVB-110 545000000 */
+				      /* MSI Megasky 580 GL861 533000000 */
+	return qt1010_set_params(fe, &params);
+}
+
+static int qt1010_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct qt1010_priv *priv = fe->tuner_priv;
+	*frequency = priv->frequency;
+	return 0;
+}
+
+static int qt1010_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct qt1010_priv *priv = fe->tuner_priv;
+	*bandwidth = priv->bandwidth;
+	return 0;
+}
+
+static const struct dvb_tuner_ops qt1010_tuner_ops = {
+	.info = {
+		.name           = "Quantek QT1010",
+		.frequency_min  = QT1010_MIN_FREQ,
+		.frequency_max  = QT1010_MAX_FREQ,
+		.frequency_step = QT1010_STEP,
+	},
+
+	.release       = qt1010_release,
+	.init          = qt1010_init,
+	/* TODO: implement sleep */
+
+	.set_params    = qt1010_set_params,
+	.get_frequency = qt1010_get_frequency,
+	.get_bandwidth = qt1010_get_bandwidth
+};
+
+struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe,
+				    struct i2c_adapter *i2c,
+				    struct qt1010_config *cfg)
+{
+	struct qt1010_priv *priv = NULL;
+	u8 id;
+
+	priv = kzalloc(sizeof(struct qt1010_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return NULL;
+
+	priv->cfg = cfg;
+	priv->i2c = i2c;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+
+	/* Try to detect tuner chip. Probably this is not correct register. */
+	if (qt1010_readreg(priv, 0x29, &id) != 0 || (id != 0x39)) {
+		kfree(priv);
+		return NULL;
+	}
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+	printk(KERN_INFO "Quantek QT1010 successfully identified.\n");
+	memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops,
+	       sizeof(struct dvb_tuner_ops));
+
+	fe->tuner_priv = priv;
+	return fe;
+}
+EXPORT_SYMBOL(qt1010_attach);
+
+MODULE_DESCRIPTION("Quantek QT1010 silicon tuner driver");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/qt1010.h b/drivers/media/dvb/frontends/qt1010.h
new file mode 100644
index 0000000..3ab4aa0
--- /dev/null
+++ b/drivers/media/dvb/frontends/qt1010.h
@@ -0,0 +1,53 @@
+/*
+ *  Driver for Quantek QT1010 silicon tuner
+ *
+ *  Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *                     Aapo Tahkola <aet@rasterburn.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef QT1010_H
+#define QT1010_H
+
+#include "dvb_frontend.h"
+
+struct qt1010_config {
+	u8 i2c_address;
+};
+
+/**
+ * Attach a qt1010 tuner to the supplied frontend structure.
+ *
+ * @param fe   frontend to attach to
+ * @param i2c  i2c adapter to use
+ * @param cfg  tuner hw based configuration
+ * @return fe  pointer on success, NULL on failure
+ */
+#if defined(CONFIG_DVB_TUNER_QT1010) || (defined(CONFIG_DVB_TUNER_QT1010_MODULE) && defined(MODULE))
+extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
+					  struct i2c_adapter *i2c,
+					  struct qt1010_config *cfg);
+#else
+static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
+						 struct i2c_adapter *i2c,
+						 struct qt1010_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+	return NULL;
+}
+#endif // CONFIG_DVB_TUNER_QT1010
+
+#endif
diff --git a/drivers/media/dvb/frontends/qt1010_priv.h b/drivers/media/dvb/frontends/qt1010_priv.h
new file mode 100644
index 0000000..090cf47
--- /dev/null
+++ b/drivers/media/dvb/frontends/qt1010_priv.h
@@ -0,0 +1,105 @@
+/*
+ *  Driver for Quantek QT1010 silicon tuner
+ *
+ *  Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *                     Aapo Tahkola <aet@rasterburn.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef QT1010_PRIV_H
+#define QT1010_PRIV_H
+
+/*
+reg def meaning
+=== === =======
+00  00  ?
+01  a0  ? operation start/stop; start=80, stop=00
+02  00  ?
+03  19  ?
+04  00  ?
+05  00  ? maybe band selection
+06  00  ?
+07  2b  set frequency: 32 MHz scale, n*32 MHz
+08  0b  ?
+09  10  ? changes every 8/24 MHz; values 1d/1c
+0a  08  set frequency: 4 MHz scale, n*4 MHz
+0b  41  ? changes every 2/2 MHz; values 45/45
+0c  e1  ?
+0d  94  ?
+0e  b6  ?
+0f  2c  ?
+10  10  ?
+11  f1  ? maybe device specified adjustment
+12  11  ? maybe device specified adjustment
+13  3f  ?
+14  1f  ?
+15  3f  ?
+16  ff  ?
+17  ff  ?
+18  f7  ?
+19  80  ?
+1a  d0  set frequency: 125 kHz scale, n*125 kHz
+1b  00  ?
+1c  89  ?
+1d  00  ?
+1e  00  ? looks like operation register; write cmd here, read result from 1f-26
+1f  20  ? chip initialization
+20  e0  ? chip initialization
+21  20  ?
+22  d0  ?
+23  d0  ?
+24  d0  ?
+25  40  ? chip initialization
+26  08  ?
+27  29  ?
+28  55  ?
+29  39  ?
+2a  13  ?
+2b  01  ?
+2c  ea  ?
+2d  00  ?
+2e  00  ? not used?
+2f  00  ? not used?
+*/
+
+#define QT1010_STEP         125000 /*  125 kHz used by Windows drivers,
+				      hw could be more precise but we don't
+				      know how to use */
+#define QT1010_MIN_FREQ   48000000 /*   48 MHz */
+#define QT1010_MAX_FREQ  860000000 /*  860 MHz */
+#define QT1010_OFFSET   1246000000 /* 1246 MHz */
+
+#define QT1010_WR 0
+#define QT1010_RD 1
+#define QT1010_M1 3
+
+typedef struct {
+	u8 oper, reg, val;
+} qt1010_i2c_oper_t;
+
+struct qt1010_priv {
+	struct qt1010_config *cfg;
+	struct i2c_adapter   *i2c;
+
+	u8 reg1f_init_val;
+	u8 reg20_init_val;
+	u8 reg25_init_val;
+
+	u32 frequency;
+	u32 bandwidth;
+};
+
+#endif
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index 1ca6424..9a34397 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -35,6 +35,7 @@
 	const struct stv0297_config *config;
 	struct dvb_frontend frontend;
 
+	unsigned long last_ber;
 	unsigned long base_freq;
 };
 
@@ -310,6 +311,8 @@
 		stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);
 	msleep(200);
 
+	state->last_ber = 0;
+
 	return 0;
 }
 
@@ -340,11 +343,13 @@
 	struct stv0297_state *state = fe->demodulator_priv;
 	u8 BER[3];
 
-	stv0297_writereg(state, 0xA0, 0x80);	// Start Counting bit errors for 4096 Bytes
-	mdelay(25);		// Hopefully got 4096 Bytes
 	stv0297_readregs(state, 0xA0, BER, 3);
-	mdelay(25);
-	*ber = (BER[2] << 8 | BER[1]) / (8 * 4096);
+	if (!(BER[0] & 0x80)) {
+		state->last_ber = BER[2] << 8 | BER[1];
+		stv0297_writereg_mask(state, 0xA0, 0x80, 0x80);
+	}
+
+	*ber = state->last_ber;
 
 	return 0;
 }
@@ -376,9 +381,14 @@
 {
 	struct stv0297_state *state = fe->demodulator_priv;
 
+	stv0297_writereg_mask(state, 0xDF, 0x03, 0x03); /* freeze the counters */
+
 	*ucblocks = (stv0297_readreg(state, 0xD5) << 8)
 		| stv0297_readreg(state, 0xD4);
 
+	stv0297_writereg_mask(state, 0xDF, 0x03, 0x02); /* clear the counters */
+	stv0297_writereg_mask(state, 0xDF, 0x03, 0x01); /* re-enable the counters */
+
 	return 0;
 }
 
@@ -648,6 +658,7 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
+	state->last_ber = 0;
 	state->base_freq = 0;
 
 	/* check if the demod is there */
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 9348376..18768d2 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -92,7 +92,7 @@
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
 
-int stv0299_write(struct dvb_frontend* fe, u8 *buf, int len)
+static int stv0299_write(struct dvb_frontend* fe, u8 *buf, int len)
 {
 	struct stv0299_state* state = fe->demodulator_priv;
 
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index dca8917..5b9c5bb 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -201,7 +201,7 @@
 	return 0;
 }
 
-int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len)
+static int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len)
 {
 	struct tda10021_state* state = fe->demodulator_priv;
 
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 00e4bcd..f4a9cf9 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -579,7 +579,7 @@
 	return -1;
 }
 
-int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len)
+static int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len)
 {
 	struct tda1004x_state* state = fe->demodulator_priv;
 
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
index 0e9b59a..245f9b7 100644
--- a/drivers/media/dvb/frontends/zl10353.c
+++ b/drivers/media/dvb/frontends/zl10353.c
@@ -38,6 +38,12 @@
 	struct zl10353_config config;
 };
 
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "zl10353: " args); \
+	} while (0)
+
 static int debug_regs = 0;
 
 static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
@@ -54,7 +60,7 @@
 	return 0;
 }
 
-int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen)
+static int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen)
 {
 	int err, i;
 	for (i = 0; i < ilen - 1; i++)
@@ -113,6 +119,36 @@
 	printk(KERN_DEBUG "%s\n", buf);
 }
 
+static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+				      enum fe_bandwidth bandwidth,
+				      u16 *nominal_rate)
+{
+	u32 adc_clock = 22528; /* 20.480 MHz on the board(!?) */
+	u8 bw;
+	struct zl10353_state *state = fe->demodulator_priv;
+
+	if (state->config.adc_clock)
+		adc_clock = state->config.adc_clock;
+
+	switch (bandwidth) {
+	case BANDWIDTH_6_MHZ:
+		bw = 6;
+		break;
+	case BANDWIDTH_7_MHZ:
+		bw = 7;
+		break;
+	case BANDWIDTH_8_MHZ:
+	default:
+		bw = 8;
+		break;
+	}
+
+	*nominal_rate = (64 * bw * (1<<16) / (7 * 8) * 4000 / adc_clock + 2) / 4;
+
+	dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+		__FUNCTION__, bw, adc_clock, *nominal_rate);
+}
+
 static int zl10353_sleep(struct dvb_frontend *fe)
 {
 	static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 };
@@ -125,7 +161,7 @@
 				  struct dvb_frontend_parameters *param)
 {
 	struct zl10353_state *state = fe->demodulator_priv;
-
+	u16 nominal_rate;
 	u8 pllbuf[6] = { 0x67 };
 
 	/* These settings set "auto-everything" and start the FSM. */
@@ -138,18 +174,23 @@
 	zl10353_single_write(fe, 0x56, 0x28);
 	zl10353_single_write(fe, 0x89, 0x20);
 	zl10353_single_write(fe, 0x5E, 0x00);
-	zl10353_single_write(fe, 0x65, 0x5A);
-	zl10353_single_write(fe, 0x66, 0xE9);
+
+	zl10353_calc_nominal_rate(fe, param->u.ofdm.bandwidth, &nominal_rate);
+	zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
+	zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
+
 	zl10353_single_write(fe, 0x6C, 0xCD);
 	zl10353_single_write(fe, 0x6D, 0x7E);
-	zl10353_single_write(fe, 0x62, 0x0A);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
 
 	// if there is no attached secondary tuner, we call set_params to program
 	// a potential tuner attached somewhere else
 	if (state->config.no_tuner) {
 		if (fe->ops.tuner_ops.set_params) {
 			fe->ops.tuner_ops.set_params(fe, param);
-			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
 		}
 	}
 
@@ -213,6 +254,29 @@
 	return 0;
 }
 
+static int zl10353_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+
+	*ber = zl10353_read_register(state, RS_ERR_CNT_2) << 16 |
+	       zl10353_read_register(state, RS_ERR_CNT_1) << 8 |
+	       zl10353_read_register(state, RS_ERR_CNT_0);
+
+	return 0;
+}
+
+static int zl10353_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+
+	u16 signal = zl10353_read_register(state, AGC_GAIN_1) << 10 |
+		     zl10353_read_register(state, AGC_GAIN_0) << 2 | 3;
+
+	*strength = ~signal;
+
+	return 0;
+}
+
 static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
 	struct zl10353_state *state = fe->demodulator_priv;
@@ -227,6 +291,16 @@
 	return 0;
 }
 
+static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+
+	*ucblocks = zl10353_read_register(state, RS_UBC_1) << 8 |
+		    zl10353_read_register(state, RS_UBC_0);
+
+	return 0;
+}
+
 static int zl10353_get_tune_settings(struct dvb_frontend *fe,
 				     struct dvb_frontend_tune_settings
 					 *fe_tune_settings)
@@ -261,6 +335,16 @@
 	return 0;
 }
 
+static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	u8 val = 0x0a;
+
+	if (enable)
+		val |= 0x10;
+
+	return zl10353_single_write(fe, 0x62, val);
+}
+
 static void zl10353_release(struct dvb_frontend *fe)
 {
 	struct zl10353_state *state = fe->demodulator_priv;
@@ -319,15 +403,22 @@
 
 	.init = zl10353_init,
 	.sleep = zl10353_sleep,
+	.i2c_gate_ctrl = zl10353_i2c_gate_ctrl,
 	.write = zl10353_write,
 
 	.set_frontend = zl10353_set_parameters,
 	.get_tune_settings = zl10353_get_tune_settings,
 
 	.read_status = zl10353_read_status,
+	.read_ber = zl10353_read_ber,
+	.read_signal_strength = zl10353_read_signal_strength,
 	.read_snr = zl10353_read_snr,
+	.read_ucblocks = zl10353_read_ucblocks,
 };
 
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
 module_param(debug_regs, int, 0644);
 MODULE_PARM_DESC(debug_regs, "Turn on/off frontend register dumps (default:off).");
 
diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
index 0bc0109..cb274dc 100644
--- a/drivers/media/dvb/frontends/zl10353.h
+++ b/drivers/media/dvb/frontends/zl10353.h
@@ -29,6 +29,9 @@
 	/* demodulator's I2C address */
 	u8 demod_address;
 
+	/* frequencies in kHz */
+	int adc_clock;  // default: 22528
+
 	/* set if no pll is connected to the secondary i2c bus */
 	int no_tuner;
 
diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h
index b72224b..4962434 100644
--- a/drivers/media/dvb/frontends/zl10353_priv.h
+++ b/drivers/media/dvb/frontends/zl10353_priv.h
@@ -24,19 +24,31 @@
 
 #define ID_ZL10353	0x14
 
+#define msb(x) (((x) >> 8) & 0xff)
+#define lsb(x) ((x) & 0xff)
+
 enum zl10353_reg_addr {
-	INTERRUPT_0	= 0x00,
-	INTERRUPT_1	= 0x01,
-	INTERRUPT_2	= 0x02,
-	INTERRUPT_3	= 0x03,
-	INTERRUPT_4	= 0x04,
-	INTERRUPT_5	= 0x05,
-	STATUS_6	= 0x06,
-	STATUS_7	= 0x07,
-	STATUS_8	= 0x08,
-	STATUS_9	= 0x09,
-	SNR		= 0x10,
-	CHIP_ID		= 0x7F,
+	INTERRUPT_0        = 0x00,
+	INTERRUPT_1        = 0x01,
+	INTERRUPT_2        = 0x02,
+	INTERRUPT_3        = 0x03,
+	INTERRUPT_4        = 0x04,
+	INTERRUPT_5        = 0x05,
+	STATUS_6           = 0x06,
+	STATUS_7           = 0x07,
+	STATUS_8           = 0x08,
+	STATUS_9           = 0x09,
+	AGC_GAIN_1         = 0x0A,
+	AGC_GAIN_0         = 0x0B,
+	SNR                = 0x10,
+	RS_ERR_CNT_2       = 0x11,
+	RS_ERR_CNT_1       = 0x12,
+	RS_ERR_CNT_0       = 0x13,
+	RS_UBC_1           = 0x14,
+	RS_UBC_0           = 0x15,
+	TRL_NOMINAL_RATE_1 = 0x65,
+	TRL_NOMINAL_RATE_0 = 0x66,
+	CHIP_ID            = 0x7F,
 };
 
 #endif                          /* _ZL10353_PRIV_ */
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 366c137..29ed532 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -51,6 +51,7 @@
 #include <linux/firmware.h>
 #include <linux/crc32.h>
 #include <linux/i2c.h>
+#include <linux/kthread.h>
 
 #include <asm/system.h>
 
@@ -223,11 +224,10 @@
 
 static void av7110_arm_sync(struct av7110 *av7110)
 {
-	av7110->arm_rmmod = 1;
-	wake_up_interruptible(&av7110->arm_wait);
+	if (av7110->arm_thread)
+		kthread_stop(av7110->arm_thread);
 
-	while (av7110->arm_thread)
-		msleep(1);
+	av7110->arm_thread = NULL;
 }
 
 static int arm_thread(void *data)
@@ -238,17 +238,11 @@
 
 	dprintk(4, "%p\n",av7110);
 
-	lock_kernel();
-	daemonize("arm_mon");
-	sigfillset(&current->blocked);
-	unlock_kernel();
-
-	av7110->arm_thread = current;
-
 	for (;;) {
 		timeout = wait_event_interruptible_timeout(av7110->arm_wait,
-							   av7110->arm_rmmod, 5 * HZ);
-		if (-ERESTARTSYS == timeout || av7110->arm_rmmod) {
+			kthread_should_stop(), 5 * HZ);
+
+		if (-ERESTARTSYS == timeout || kthread_should_stop()) {
 			/* got signal or told to quit*/
 			break;
 		}
@@ -276,7 +270,6 @@
 		av7110->arm_errors = 0;
 	}
 
-	av7110->arm_thread = NULL;
 	return 0;
 }
 
@@ -695,8 +688,8 @@
 static int dvb_osd_ioctl(struct inode *inode, struct file *file,
 			 unsigned int cmd, void *parg)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 
 	dprintk(4, "%p\n", av7110);
 
@@ -786,7 +779,7 @@
 static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
 {
 	struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
-	struct av7110 *av7110 = (struct av7110 *) dvbdmxfeed->demux->priv;
+	struct av7110 *av7110 = dvbdmxfeed->demux->priv;
 	u16 buf[20];
 	int ret, i;
 	u16 handle;
@@ -835,7 +828,7 @@
 
 static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
 {
-	struct av7110 *av7110 = (struct av7110 *) dvbdmxfilter->feed->demux->priv;
+	struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
 	u16 buf[3];
 	u16 answ[2];
 	int ret;
@@ -871,7 +864,7 @@
 static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
 {
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
+	struct av7110 *av7110 = dvbdmx->priv;
 	u16 *pid = dvbdmx->pids, npids[5];
 	int i;
 	int ret = 0;
@@ -914,7 +907,7 @@
 static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
 {
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
+	struct av7110 *av7110 = dvbdmx->priv;
 	u16 *pid = dvbdmx->pids, npids[5];
 	int i;
 
@@ -1103,9 +1096,9 @@
 
 	/* pointer casting paranoia... */
 	BUG_ON(!demux);
-	dvbdemux = (struct dvb_demux *) demux->priv;
+	dvbdemux = demux->priv;
 	BUG_ON(!dvbdemux);
-	av7110 = (struct av7110 *) dvbdemux->priv;
+	av7110 = dvbdemux->priv;
 
 	dprintk(4, "%p\n", av7110);
 
@@ -1137,7 +1130,7 @@
 
 static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
-	struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+	struct av7110* av7110 = fe->dvb->priv;
 
 	switch (tone) {
 	case SEC_TONE_ON:
@@ -1197,7 +1190,7 @@
 static int budget_start_feed(struct dvb_demux_feed *feed)
 {
 	struct dvb_demux *demux = feed->demux;
-	struct av7110 *budget = (struct av7110 *) demux->priv;
+	struct av7110 *budget = demux->priv;
 	int status;
 
 	dprintk(2, "av7110: %p\n", budget);
@@ -1212,7 +1205,7 @@
 static int budget_stop_feed(struct dvb_demux_feed *feed)
 {
 	struct dvb_demux *demux = feed->demux;
-	struct av7110 *budget = (struct av7110 *) demux->priv;
+	struct av7110 *budget = demux->priv;
 	int status;
 
 	dprintk(2, "budget: %p\n", budget);
@@ -1551,7 +1544,7 @@
 
 static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
-	struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+	struct av7110* av7110 = fe->dvb->priv;
 	u8 pwr = 0;
 	u8 buf[4];
 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
@@ -1702,7 +1695,7 @@
 static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
 {
 #if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
-	struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+	struct av7110* av7110 = fe->dvb->priv;
 
 	return request_firmware(fw, name, &av7110->dev->pci->dev);
 #else
@@ -1867,7 +1860,7 @@
 
 static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
-	struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+	struct av7110* av7110 = fe->dvb->priv;
 	u32 div;
 	u8 cfg, cpump, band_select;
 	u8 data[4];
@@ -2338,6 +2331,7 @@
 	const int length = TS_WIDTH * TS_HEIGHT;
 	struct pci_dev *pdev = dev->pci;
 	struct av7110 *av7110;
+	struct task_struct *thread;
 	int ret, count = 0;
 
 	dprintk(4, "dev: %p\n", dev);
@@ -2622,9 +2616,12 @@
 		printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
 			"System might be unstable!\n", FW_VERSION(av7110->arm_app));
 
-	ret = kernel_thread(arm_thread, (void *) av7110, 0);
-	if (ret < 0)
+	thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
+	if (IS_ERR(thread)) {
+		ret = PTR_ERR(thread);
 		goto err_stop_arm_9;
+	}
+	av7110->arm_thread = thread;
 
 	/* set initial volume in mixer struct */
 	av7110->mixer.volume_left  = volume;
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index 9c79696..b98bd45 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -35,7 +35,6 @@
 
 #define ANALOG_TUNER_VES1820 1
 #define ANALOG_TUNER_STV0297 2
-#define ANALOG_TUNER_VBI     0x100
 
 extern int av7110_debug;
 
@@ -205,7 +204,6 @@
 	struct task_struct *arm_thread;
 	wait_queue_head_t   arm_wait;
 	u16		    arm_loops;
-	int		    arm_rmmod;
 
 	void		   *debi_virt;
 	dma_addr_t	    debi_bus;
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 8c577cf..e719af8 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -31,7 +31,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
@@ -881,8 +880,8 @@
 
 static unsigned int dvb_video_poll(struct file *file, poll_table *wait)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 	unsigned int mask = 0;
 
 	dprintk(2, "av7110:%p, \n", av7110);
@@ -909,8 +908,8 @@
 static ssize_t dvb_video_write(struct file *file, const char __user *buf,
 			       size_t count, loff_t *ppos)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 
 	dprintk(2, "av7110:%p, \n", av7110);
 
@@ -925,8 +924,8 @@
 
 static unsigned int dvb_audio_poll(struct file *file, poll_table *wait)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 	unsigned int mask = 0;
 
 	dprintk(2, "av7110:%p, \n", av7110);
@@ -945,8 +944,8 @@
 static ssize_t dvb_audio_write(struct file *file, const char __user *buf,
 			       size_t count, loff_t *ppos)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 
 	dprintk(2, "av7110:%p, \n", av7110);
 
@@ -990,8 +989,8 @@
 static int dvb_video_ioctl(struct inode *inode, struct file *file,
 			   unsigned int cmd, void *parg)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 	unsigned long arg = (unsigned long) parg;
 	int ret = 0;
 
@@ -1204,8 +1203,8 @@
 static int dvb_audio_ioctl(struct inode *inode, struct file *file,
 			   unsigned int cmd, void *parg)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 	unsigned long arg = (unsigned long) parg;
 	int ret = 0;
 
@@ -1350,8 +1349,8 @@
 
 static int dvb_video_open(struct inode *inode, struct file *file)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 	int err;
 
 	dprintk(2, "av7110:%p, \n", av7110);
@@ -1375,8 +1374,8 @@
 
 static int dvb_video_release(struct inode *inode, struct file *file)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 
 	dprintk(2, "av7110:%p, \n", av7110);
 
@@ -1389,9 +1388,9 @@
 
 static int dvb_audio_open(struct inode *inode, struct file *file)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
-	int err=dvb_generic_open(inode, file);
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
+	int err = dvb_generic_open(inode, file);
 
 	dprintk(2, "av7110:%p, \n", av7110);
 
@@ -1404,8 +1403,8 @@
 
 static int dvb_audio_release(struct inode *inode, struct file *file)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 
 	dprintk(2, "av7110:%p, \n", av7110);
 
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index dd9aee3..e9b4e88 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -29,7 +29,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
@@ -215,8 +214,8 @@
 
 static int dvb_ca_open(struct inode *inode, struct file *file)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 	int err = dvb_generic_open(inode, file);
 
 	dprintk(8, "av7110:%p\n",av7110);
@@ -229,8 +228,8 @@
 
 static unsigned int dvb_ca_poll (struct file *file, poll_table *wait)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 	struct dvb_ringbuffer *rbuf = &av7110->ci_rbuffer;
 	struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer;
 	unsigned int mask = 0;
@@ -252,8 +251,8 @@
 static int dvb_ca_ioctl(struct inode *inode, struct file *file,
 		 unsigned int cmd, void *parg)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 	unsigned long arg = (unsigned long) parg;
 
 	dprintk(8, "av7110:%p\n",av7110);
@@ -330,8 +329,8 @@
 static ssize_t dvb_ca_write(struct file *file, const char __user *buf,
 			    size_t count, loff_t *ppos)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 
 	dprintk(8, "av7110:%p\n",av7110);
 	return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos);
@@ -340,15 +339,13 @@
 static ssize_t dvb_ca_read(struct file *file, char __user *buf,
 			   size_t count, loff_t *ppos)
 {
-	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
+	struct dvb_device *dvbdev = file->private_data;
+	struct av7110 *av7110 = dvbdev->priv;
 
 	dprintk(8, "av7110:%p\n",av7110);
 	return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos);
 }
 
-
-
 static struct file_operations dvb_ca_fops = {
 	.owner		= THIS_MODULE,
 	.read		= dvb_ca_read,
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index 37de2e8..4d7150e 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -32,7 +32,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index e4544ea..f59465b 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -4,6 +4,7 @@
 #include <linux/moduleparam.h>
 #include <linux/input.h>
 #include <linux/proc_fs.h>
+#include <linux/kernel.h>
 #include <asm/bitops.h>
 
 #include "av7110.h"
@@ -16,6 +17,7 @@
 static int av_cnt;
 static struct av7110 *av_list[4];
 static struct input_dev *input_dev;
+static char input_phys[32];
 
 static u8 delay_timer_finished;
 
@@ -217,7 +219,7 @@
 	static struct proc_dir_entry *e;
 	int err;
 
-	if (av_cnt >= sizeof av_list/sizeof av_list[0])
+	if (av_cnt >= ARRAY_SIZE(av_list))
 		return -ENOSPC;
 
 	av7110_setup_irc_config(av7110, 0x0001);
@@ -231,8 +233,22 @@
 		if (!input_dev)
 			return -ENOMEM;
 
+		snprintf(input_phys, sizeof(input_phys),
+			"pci-%s/ir0", pci_name(av7110->dev->pci));
+
 		input_dev->name = "DVB on-card IR receiver";
 
+		input_dev->phys = input_phys;
+		input_dev->id.bustype = BUS_PCI;
+		input_dev->id.version = 1;
+		if (av7110->dev->pci->subsystem_vendor) {
+			input_dev->id.vendor = av7110->dev->pci->subsystem_vendor;
+			input_dev->id.product = av7110->dev->pci->subsystem_device;
+		} else {
+			input_dev->id.vendor = av7110->dev->pci->vendor;
+			input_dev->id.product = av7110->dev->pci->device;
+		}
+		input_dev->cdev.dev = &av7110->dev->pci->dev;
 		set_bit(EV_KEY, input_dev->evbit);
 		set_bit(EV_REP, input_dev->evbit);
 		input_register_keys();
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index 10cfe31..cde5d3a 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -26,7 +26,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
@@ -141,17 +140,6 @@
 	return 0;
 }
 
-static int stv0297_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
-{
-	u8 buf [] = { reg, data };
-	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 2 };
-
-	if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
-		return -1;
-	return 0;
-}
-
-
 static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
 {
 	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
@@ -194,6 +182,7 @@
 
 static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq)
 {
+	struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
 	u32 div;
 	u8 data[4];
 
@@ -214,8 +203,8 @@
 	else
 		return -EINVAL;
 
-	stv0297_writereg(dev, 0x1C, 0x87, 0x78);
-	stv0297_writereg(dev, 0x1C, 0x86, 0xc8);
+	if (av7110->fe->ops.i2c_gate_ctrl)
+		av7110->fe->ops.i2c_gate_ctrl(av7110->fe, 1);
 	return tuner_write(dev, 0x63, data);
 }
 
@@ -818,20 +807,20 @@
 		saa7146_vv_release(dev);
 		return -ENODEV;
 	}
-	if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
+	if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
 		ERR(("cannot register vbi v4l2 device. skipping.\n"));
-	} else {
-		if (av7110->analog_tuner_flags)
-			av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
-	}
 	return 0;
 }
 
 int av7110_exit_v4l(struct av7110 *av7110)
 {
+	struct saa7146_dev* dev = av7110->dev;
+
 	saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);
-	if (av7110->analog_tuner_flags & ANALOG_TUNER_VBI)
-		saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
+	saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
+
+	saa7146_vv_release(dev);
+
 	return 0;
 }
 
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 89ab4b5..3035b22 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -1089,6 +1089,8 @@
 		msleep(200);
 
 		saa7146_unregister_device(&budget_av->vd, dev);
+
+		saa7146_vv_release(dev);
 	}
 
 	if (budget_av->budget.ci_present)
@@ -1145,6 +1147,7 @@
 		if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
 			/* fixme: proper cleanup here */
 			ERR(("cannot register capture v4l2 device.\n"));
+			saa7146_vv_release(dev);
 			return err;
 		}
 
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index f2066b4..464feaf 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -29,8 +29,6 @@
  * the project's page is at http://www.linuxtv.org/dvb/
  */
 
-#include "budget.h"
-
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
@@ -39,6 +37,8 @@
 #include <linux/spinlock.h>
 #include <media/ir-common.h>
 
+#include "budget.h"
+
 #include "dvb_ca_en50221.h"
 #include "stv0299.h"
 #include "stv0297.h"
@@ -130,6 +130,7 @@
 	int toggle;
 	static int prev_toggle = -1;
 	static u32 ir_key;
+	static int state = 0;
 	u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
 
 	/*
@@ -138,21 +139,34 @@
 	 * type1: X1CCCCCC, C = command bits (0 - 63)
 	 * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
 	 *
-	 * More than one command byte may be generated before the device byte
-	 * Only when we have both, a correct keypress is generated
+	 * Each signal from the remote control can generate one or more command
+	 * bytes and one or more device bytes. For the repeated bytes, the
+	 * highest bit (X) is set. The first command byte is always generated
+	 * before the first device byte. Other than that, no specific order
+	 * seems to apply.
+	 *
+	 * Only when we have a command and device byte, a keypress is
+	 * generated.
 	 */
 
+	if (ir_debug)
+		printk("budget_ci: received byte 0x%02x\n", command);
+
+	/* Is this a repeated byte? */
+	if (command & 0x80)
+		return;
+
 	/* Is this a RC5 command byte? */
 	if (command & 0x40) {
-		if (ir_debug)
-			printk("budget_ci: received command byte 0x%02x\n", command);
+		state = 1;
 		ir_key = command & 0x3f;
 		return;
 	}
 
 	/* It's a RC5 device byte */
-	if (ir_debug)
-		printk("budget_ci: received device byte 0x%02x\n", command);
+	if (!state)
+		return;
+	state = 0;
 	device = command & 0x1f;
 	toggle = command & 0x20;
 
@@ -223,7 +237,6 @@
 	switch (budget_ci->budget.dev->pci->subsystem_device) {
 	case 0x100c:
 	case 0x100f:
-	case 0x1010:
 	case 0x1011:
 	case 0x1012:
 	case 0x1017:
@@ -236,6 +249,16 @@
 		else
 			budget_ci->ir.rc5_device = rc5_device;
 		break;
+	case 0x1010:
+		/* for the Technotrend 1500 bundled remote */
+		ir_input_init(input_dev, &budget_ci->ir.state,
+			      IR_TYPE_RC5, ir_codes_tt_1500);
+
+		if (rc5_device < 0)
+			budget_ci->ir.rc5_device = IR_DEVICE_ANY;
+		else
+			budget_ci->ir.rc5_device = rc5_device;
+		break;
 	default:
 		/* unknown remote */
 		ir_input_init(input_dev, &budget_ci->ir.state,
@@ -869,6 +892,17 @@
 	.request_firmware = philips_tdm1316l_request_firmware,
 };
 
+static struct tda1004x_config philips_tdm1316l_config_invert = {
+
+	.demod_address = 0x8,
+	.invert = 1,
+	.invert_oclk = 0,
+	.xtal_freq = TDA10046_XTAL_4M,
+	.agc_config = TDA10046_AGC_DEFAULT,
+	.if_freq = TDA10046_FREQ_3617,
+	.request_firmware = philips_tdm1316l_request_firmware,
+};
+
 static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
@@ -1092,9 +1126,8 @@
 
 	case 0x1012:		// TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
 		budget_ci->tuner_pll_address = 0x60;
-		philips_tdm1316l_config.invert = 1;
 		budget_ci->budget.dvb_frontend =
-			dvb_attach(tda10046_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+			dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
 		if (budget_ci->budget.dvb_frontend) {
 			budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
 			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 60820de..b60cdc9 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -1690,6 +1690,7 @@
 #endif
 	ttusb->i2c_adap.algo              = &ttusb_dec_algo;
 	ttusb->i2c_adap.algo_data         = NULL;
+	ttusb->i2c_adap.dev.parent	  = &udev->dev;
 
 	result = i2c_add_adapter(&ttusb->i2c_adap);
 	if (result) {
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index bd6e7ba..78c98b0 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -20,8 +20,6 @@
  *
  */
 
-#include <linux/mutex.h>
-
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -35,6 +33,8 @@
 #include <linux/init.h>
 #include <linux/input.h>
 
+#include <linux/mutex.h>
+
 #include "dmxdev.h"
 #include "dvb_demux.h"
 #include "dvb_filter.h"
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index db865a0..df8d052 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -144,7 +144,7 @@
 
 
 /* File system interface */
-static struct file_operations usb_dsbr100_fops = {
+static const struct file_operations usb_dsbr100_fops = {
 	.owner =	THIS_MODULE,
 	.open =		usb_dsbr100_open,
 	.release =     	usb_dsbr100_close,
diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
index c4312fa..c7c9d1d 100644
--- a/drivers/media/radio/miropcm20-radio.c
+++ b/drivers/media/radio/miropcm20-radio.c
@@ -216,7 +216,7 @@
 	.muted  = 1,
 };
 
-static struct file_operations pcm20_fops = {
+static const struct file_operations pcm20_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
index c1b1db6..aed1147 100644
--- a/drivers/media/radio/miropcm20-rds.c
+++ b/drivers/media/radio/miropcm20-rds.c
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
-#include <linux/sched.h>	/* current, TASK_*, schedule_timeout() */
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 #include "miropcm20-rds-core.h"
@@ -105,7 +104,7 @@
 	}
 }
 
-static struct file_operations rds_fops = {
+static const struct file_operations rds_fops = {
 	.owner		= THIS_MODULE,
 	.read		= rds_f_read,
 	.open		= rds_f_open,
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 3368a89..b2e88ad 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -358,7 +358,7 @@
 
 static struct rt_device rtrack_unit;
 
-static struct file_operations rtrack_fops = {
+static const struct file_operations rtrack_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 3ba5fa8..9f1adda 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -180,158 +180,200 @@
 	return 0;
 }
 
-static int az_do_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg)
+static int vidioc_querycap (struct file *file, void  *priv,
+					struct v4l2_capability *v)
+{
+	strlcpy(v->driver, "radio-aztech", sizeof (v->driver));
+	strlcpy(v->card, "Aztech Radio", sizeof (v->card));
+	sprintf(v->bus_info,"ISA");
+	v->version = RADIO_VERSION;
+	v->capabilities = V4L2_CAP_TUNER;
+	return 0;
+}
+
+static int vidioc_g_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *v)
 {
 	struct video_device *dev = video_devdata(file);
 	struct az_device *az = dev->priv;
 
-	switch(cmd)
-	{
-		case VIDIOC_QUERYCAP:
-		{
-			struct v4l2_capability *v = arg;
-			memset(v,0,sizeof(*v));
-			strlcpy(v->driver, "radio-aztech", sizeof (v->driver));
-			strlcpy(v->card, "Aztech Radio", sizeof (v->card));
-			sprintf(v->bus_info,"ISA");
-			v->version = RADIO_VERSION;
-			v->capabilities = V4L2_CAP_TUNER;
+	if (v->index > 0)
+		return -EINVAL;
 
-			return 0;
-		}
-		case VIDIOC_G_TUNER:
-		{
-			struct v4l2_tuner *v = arg;
+	strcpy(v->name, "FM");
+	v->type = V4L2_TUNER_RADIO;
 
-			if (v->index > 0)
-				return -EINVAL;
+	v->rangelow=(87*16000);
+	v->rangehigh=(108*16000);
+	v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+	v->capability=V4L2_TUNER_CAP_LOW;
+	if(az_getstereo(az))
+		v->audmode = V4L2_TUNER_MODE_STEREO;
+	else
+		v->audmode = V4L2_TUNER_MODE_MONO;
+	v->signal=0xFFFF*az_getsigstr(az);
 
-			memset(v,0,sizeof(*v));
-			strcpy(v->name, "FM");
-			v->type = V4L2_TUNER_RADIO;
-
-			v->rangelow=(87*16000);
-			v->rangehigh=(108*16000);
-			v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
-			v->capability=V4L2_TUNER_CAP_LOW;
-			if(az_getstereo(az))
-				v->audmode = V4L2_TUNER_MODE_STEREO;
-			else
-				v->audmode = V4L2_TUNER_MODE_MONO;
-			v->signal=0xFFFF*az_getsigstr(az);
-
-			return 0;
-		}
-		case VIDIOC_S_TUNER:
-		{
-			struct v4l2_tuner *v = arg;
-
-			if (v->index > 0)
-				return -EINVAL;
-
-			return 0;
-		}
-		case VIDIOC_S_FREQUENCY:
-		{
-			struct v4l2_frequency *f = arg;
-
-			az->curfreq = f->frequency;
-			az_setfreq(az, az->curfreq);
-			return 0;
-		}
-		case VIDIOC_G_FREQUENCY:
-		{
-			struct v4l2_frequency *f = arg;
-
-			f->type = V4L2_TUNER_RADIO;
-			f->frequency = az->curfreq;
-
-			return 0;
-		}
-
-		case VIDIOC_QUERYCTRL:
-		{
-			struct v4l2_queryctrl *qc = arg;
-			int i;
-
-			for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-				if (qc->id && qc->id == radio_qctrl[i].id) {
-					memcpy(qc, &(radio_qctrl[i]),
-								sizeof(*qc));
-					return (0);
-				}
-			}
-			return -EINVAL;
-		}
-		case VIDIOC_G_CTRL:
-		{
-			struct v4l2_control *ctrl= arg;
-
-			switch (ctrl->id) {
-				case V4L2_CID_AUDIO_MUTE:
-					if (az->curvol==0)
-						ctrl->value=1;
-					else
-						ctrl->value=0;
-					return (0);
-				case V4L2_CID_AUDIO_VOLUME:
-					ctrl->value=az->curvol * 6554;
-					return (0);
-			}
-			return -EINVAL;
-		}
-		case VIDIOC_S_CTRL:
-		{
-			struct v4l2_control *ctrl= arg;
-
-			switch (ctrl->id) {
-				case V4L2_CID_AUDIO_MUTE:
-					if (ctrl->value) {
-						az_setvol(az,0);
-					} else {
-						az_setvol(az,az->curvol);
-					}
-					return (0);
-				case V4L2_CID_AUDIO_VOLUME:
-					az_setvol(az,ctrl->value);
-					return (0);
-			}
-			return -EINVAL;
-		}
-
-		default:
-			return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-							  az_do_ioctl);
-	}
+	return 0;
 }
 
-static int az_ioctl(struct inode *inode, struct file *file,
-		    unsigned int cmd, unsigned long arg)
+
+static int vidioc_s_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *v)
 {
-	return video_usercopy(inode, file, cmd, arg, az_do_ioctl);
+	if (v->index > 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int vidioc_g_audio (struct file *file, void *priv,
+			   struct v4l2_audio *a)
+{
+	if (a->index > 1)
+		return -EINVAL;
+
+	strcpy(a->name, "Radio");
+	a->capability = V4L2_AUDCAP_STEREO;
+	return 0;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+	if (i != 0)
+		return -EINVAL;
+	return 0;
+}
+
+
+static int vidioc_s_audio (struct file *file, void *priv,
+			   struct v4l2_audio *a)
+{
+	if (a->index != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct video_device *dev = video_devdata(file);
+	struct az_device *az = dev->priv;
+
+	az->curfreq = f->frequency;
+	az_setfreq(az, az->curfreq);
+	return 0;
+}
+
+static int vidioc_g_frequency (struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct video_device *dev = video_devdata(file);
+	struct az_device *az = dev->priv;
+
+	f->type = V4L2_TUNER_RADIO;
+	f->frequency = az->curfreq;
+
+	return 0;
+}
+
+static int vidioc_queryctrl (struct file *file, void *priv,
+			    struct v4l2_queryctrl *qc)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+		if (qc->id && qc->id == radio_qctrl[i].id) {
+			memcpy(qc, &(radio_qctrl[i]),
+						sizeof(*qc));
+			return (0);
+		}
+	}
+	return -EINVAL;
+}
+
+static int vidioc_g_ctrl (struct file *file, void *priv,
+			    struct v4l2_control *ctrl)
+{
+	struct video_device *dev = video_devdata(file);
+	struct az_device *az = dev->priv;
+
+	switch (ctrl->id) {
+		case V4L2_CID_AUDIO_MUTE:
+			if (az->curvol==0)
+				ctrl->value=1;
+			else
+				ctrl->value=0;
+			return (0);
+		case V4L2_CID_AUDIO_VOLUME:
+			ctrl->value=az->curvol * 6554;
+			return (0);
+	}
+	return -EINVAL;
+}
+
+static int vidioc_s_ctrl (struct file *file, void *priv,
+			    struct v4l2_control *ctrl)
+{
+	struct video_device *dev = video_devdata(file);
+	struct az_device *az = dev->priv;
+
+	switch (ctrl->id) {
+		case V4L2_CID_AUDIO_MUTE:
+			if (ctrl->value) {
+				az_setvol(az,0);
+			} else {
+				az_setvol(az,az->curvol);
+			}
+			return (0);
+		case V4L2_CID_AUDIO_VOLUME:
+			az_setvol(az,ctrl->value);
+			return (0);
+	}
+	return -EINVAL;
 }
 
 static struct az_device aztech_unit;
 
-static struct file_operations aztech_fops = {
+static const struct file_operations aztech_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
-	.ioctl		= az_ioctl,
+	.ioctl		= video_ioctl2,
 	.compat_ioctl	= v4l_compat_ioctl32,
 	.llseek         = no_llseek,
 };
 
 static struct video_device aztech_radio=
 {
-	.owner		= THIS_MODULE,
-	.name		= "Aztech radio",
-	.type		= VID_TYPE_TUNER,
-	.hardware	= 0,
-	.fops           = &aztech_fops,
+	.owner		    = THIS_MODULE,
+	.name		    = "Aztech radio",
+	.type		    = VID_TYPE_TUNER,
+	.hardware	    = 0,
+	.fops               = &aztech_fops,
+	.vidioc_querycap    = vidioc_querycap,
+	.vidioc_g_tuner     = vidioc_g_tuner,
+	.vidioc_s_tuner     = vidioc_s_tuner,
+	.vidioc_g_audio     = vidioc_g_audio,
+	.vidioc_s_audio     = vidioc_s_audio,
+	.vidioc_g_input     = vidioc_g_input,
+	.vidioc_s_input     = vidioc_s_input,
+	.vidioc_g_frequency = vidioc_g_frequency,
+	.vidioc_s_frequency = vidioc_s_frequency,
+	.vidioc_queryctrl   = vidioc_queryctrl,
+	.vidioc_g_ctrl      = vidioc_g_ctrl,
+	.vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+module_param_named(debug,aztech_radio.debug, int, 0644);
+MODULE_PARM_DESC(debug,"activates debug info");
+
 static int __init aztech_init(void)
 {
 	if(io==-1)
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 69d4b79..8fbf0d8 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -507,7 +507,7 @@
 }
 
 
-static struct file_operations cadet_fops = {
+static const struct file_operations cadet_fops = {
 	.owner		= THIS_MODULE,
 	.open		= cadet_open,
 	.release       	= cadet_release,
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index eb14106..74976cba 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -89,14 +89,6 @@
 #define GEMTEK_PCI_RANGE_HIGH (108*16000)
 #endif
 
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
 struct gemtek_pci_card {
 	struct video_device *videodev;
 
@@ -146,12 +138,12 @@
 
 static inline void gemtek_pci_nil( u32 port, u8 *last_byte )
 {
-	__gemtek_pci_cmd( 0x00, port, last_byte, FALSE );
+	__gemtek_pci_cmd( 0x00, port, last_byte, false );
 }
 
 static inline void gemtek_pci_cmd( u16 cmd, u32 port, u8 *last_byte )
 {
-	__gemtek_pci_cmd( cmd, port, last_byte, TRUE );
+	__gemtek_pci_cmd( cmd, port, last_byte, true );
 }
 
 static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long frequency )
@@ -184,14 +176,14 @@
 static inline void gemtek_pci_mute( struct gemtek_pci_card *card )
 {
 	outb( 0x1f, card->iobase );
-	card->mute = TRUE;
+	card->mute = true;
 }
 
 static inline void gemtek_pci_unmute( struct gemtek_pci_card *card )
 {
 	if ( card->mute ) {
 		gemtek_pci_setfrequency( card, card->current_frequency );
-		card->mute = FALSE;
+		card->mute = false;
 	}
 }
 
@@ -259,7 +251,7 @@
 
 			gemtek_pci_setfrequency( card, f->frequency );
 			card->current_frequency = f->frequency;
-			card->mute = FALSE;
+			card->mute = false;
 			return 0;
 		}
 		case VIDIOC_QUERYCTRL:
@@ -346,7 +338,7 @@
 
 static int mx = 1;
 
-static struct file_operations gemtek_pci_fops = {
+static const struct file_operations gemtek_pci_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 730fe16..36c4be6 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -296,7 +296,7 @@
 
 static struct gemtek_device gemtek_unit;
 
-static struct file_operations gemtek_fops = {
+static const struct file_operations gemtek_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index e8ce5f7..e67b7f2 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -22,7 +22,6 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/mutex.h>
@@ -99,7 +98,7 @@
 	.remove		= __devexit_p(maestro_remove),
 };
 
-static struct file_operations maestro_fops = {
+static const struct file_operations maestro_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index c2eeae7..8e184cf 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -27,7 +27,9 @@
  * BUGS:
  *   - card unmutes if you change frequency
  *
- * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
+ * (c) 2006, 2007 by Mauro Carvalho Chehab <mchehab@infradead.org>:
+ *	- Conversion to V4L2 API
+ *      - Uses video_ioctl2 for parsing and to add debug support
  */
 
 
@@ -35,7 +37,6 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/mutex.h>
@@ -44,10 +45,18 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 
-#define DRIVER_VERSION	"0.76"
+#define DRIVER_VERSION	"0.77"
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,7,6)
+#define RADIO_VERSION KERNEL_VERSION(0,7,7)
+
+static struct video_device maxiradio_radio;
+
+#define dprintk(num, fmt, arg...)                                          \
+	do {                                                               \
+		if (maxiradio_radio.debug >= num)                          \
+			printk(KERN_DEBUG "%s: " fmt,                      \
+				maxiradio_radio.name, ## arg); } while (0)
 
 static struct v4l2_queryctrl radio_qctrl[] = {
 	{
@@ -82,30 +91,21 @@
 #define FREQ_IF         171200 /* 10.7*16000   */
 #define FREQ_STEP       200    /* 12.5*16      */
 
-#define FREQ2BITS(x)	((( (unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))\
-			/(FREQ_STEP<<2))<<2) /* (x==fmhz*16*1000) -> bits */
+/* (x==fmhz*16*1000) -> bits */
+#define FREQ2BITS(x)	((( (unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1)) \
+			/(FREQ_STEP<<2))<<2)
 
 #define BITS2FREQ(x)	((x) * FREQ_STEP - FREQ_IF)
 
 
-static int radio_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg);
-
-static struct file_operations maxiradio_fops = {
+static const struct file_operations maxiradio_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
-	.ioctl		= radio_ioctl,
+	.ioctl          = video_ioctl2,
 	.compat_ioctl	= v4l_compat_ioctl32,
 	.llseek         = no_llseek,
 };
-static struct video_device maxiradio_radio =
-{
-	.owner		= THIS_MODULE,
-	.name		= "Maxi Radio FM2000 radio",
-	.type		= VID_TYPE_TUNER,
-	.fops           = &maxiradio_fops,
-};
 
 static struct radio_device
 {
@@ -117,12 +117,14 @@
 	unsigned long freq;
 
 	struct mutex lock;
-} radio_unit = {0, 0, 0, 0, };
-
+} radio_unit = {
+	.muted =1,
+	.freq = FREQ_LO,
+};
 
 static void outbit(unsigned long bit, __u16 io)
 {
-	if(bit != 0)
+	if (bit != 0)
 		{
 			outb(  power|wren|data     ,io); udelay(4);
 			outb(  power|wren|data|clk ,io); udelay(4);
@@ -138,14 +140,20 @@
 
 static void turn_power(__u16 io, int p)
 {
-	if(p != 0) outb(power, io); else outb(0,io);
+	if (p != 0) {
+		dprintk(1, "Radio powered on\n");
+		outb(power, io);
+	} else {
+		dprintk(1, "Radio powered off\n");
+		outb(0,io);
+	}
 }
 
-
-static void set_freq(__u16 io, __u32 data)
+static void set_freq(__u16 io, __u32 freq)
 {
 	unsigned long int si;
 	int bl;
+	int data = FREQ2BITS(freq);
 
 	/* TEA5757 shift register bits (see pdf) */
 
@@ -164,161 +172,225 @@
 	outbit(0,io); // 16  search level
 
 	si = 0x8000;
-	for(bl = 1; bl <= 16 ; bl++) { outbit(data & si,io); si >>=1; }
+	for (bl = 1; bl <= 16 ; bl++) {
+		outbit(data & si,io);
+		si >>=1;
+	}
 
-	outb(power,io);
+	dprintk(1, "Radio freq set to %d.%02d MHz\n",
+				freq / 16000,
+				freq % 16000 * 100 / 16000);
+
+	turn_power(io, 1);
 }
 
 static int get_stereo(__u16 io)
 {
-	outb(power,io); udelay(4);
+	outb(power,io);
+	udelay(4);
+
 	return !(inb(io) & mo_st);
 }
 
 static int get_tune(__u16 io)
 {
-	outb(power+clk,io); udelay(4);
+	outb(power+clk,io);
+	udelay(4);
+
 	return !(inb(io) & mo_st);
 }
 
 
-static inline int radio_function(struct inode *inode, struct file *file,
-				 unsigned int cmd, void *arg)
+static int vidioc_querycap (struct file *file, void  *priv,
+			    struct v4l2_capability *v)
+{
+	strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver));
+	strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card));
+	sprintf(v->bus_info,"ISA");
+	v->version = RADIO_VERSION;
+	v->capabilities = V4L2_CAP_TUNER;
+
+	return 0;
+}
+
+static int vidioc_g_tuner (struct file *file, void *priv,
+			   struct v4l2_tuner *v)
 {
 	struct video_device *dev = video_devdata(file);
 	struct radio_device *card=dev->priv;
 
-	switch(cmd) {
-		case VIDIOC_QUERYCAP:
-		{
-			struct v4l2_capability *v = arg;
-			memset(v,0,sizeof(*v));
-			strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver));
-			strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card));
-			sprintf(v->bus_info,"ISA");
-			v->version = RADIO_VERSION;
-			v->capabilities = V4L2_CAP_TUNER;
+	if (v->index > 0)
+		return -EINVAL;
 
-			return 0;
-		}
-		case VIDIOC_G_TUNER:
-		{
-			struct v4l2_tuner *v = arg;
+	memset(v,0,sizeof(*v));
+	strcpy(v->name, "FM");
+	v->type = V4L2_TUNER_RADIO;
 
-			if (v->index > 0)
-				return -EINVAL;
+	v->rangelow=FREQ_LO;
+	v->rangehigh=FREQ_HI;
+	v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+	v->capability=V4L2_TUNER_CAP_LOW;
+	if(get_stereo(card->io))
+		v->audmode = V4L2_TUNER_MODE_STEREO;
+	else
+		v->audmode = V4L2_TUNER_MODE_MONO;
+	v->signal=0xffff*get_tune(card->io);
 
-			memset(v,0,sizeof(*v));
-			strcpy(v->name, "FM");
-			v->type = V4L2_TUNER_RADIO;
+	return 0;
+}
 
-			v->rangelow=FREQ_LO;
-			v->rangehigh=FREQ_HI;
-			v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
-			v->capability=V4L2_TUNER_CAP_LOW;
-			if(get_stereo(card->io))
-				v->audmode = V4L2_TUNER_MODE_STEREO;
-			else
-				v->audmode = V4L2_TUNER_MODE_MONO;
-			v->signal=0xffff*get_tune(card->io);
+static int vidioc_s_tuner (struct file *file, void *priv,
+			   struct v4l2_tuner *v)
+{
+	if (v->index > 0)
+		return -EINVAL;
 
-			return 0;
-		}
-		case VIDIOC_S_TUNER:
-		{
-			struct v4l2_tuner *v = arg;
+	return 0;
+}
 
-			if (v->index > 0)
-				return -EINVAL;
+static int vidioc_g_audio (struct file *file, void *priv,
+			   struct v4l2_audio *a)
+{
+	if (a->index > 1)
+		return -EINVAL;
 
-			return 0;
-		}
-		case VIDIOC_S_FREQUENCY:
-		{
-			struct v4l2_frequency *f = arg;
+	strcpy(a->name, "FM");
+	a->capability = V4L2_AUDCAP_STEREO;
+	return 0;
+}
 
-			if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
-				return -EINVAL;
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+	*i = 0;
 
-			card->freq = f->frequency;
-			set_freq(card->io, FREQ2BITS(card->freq));
-			msleep(125);
-			return 0;
-		}
-		case VIDIOC_G_FREQUENCY:
-		{
-			struct v4l2_frequency *f = arg;
+	return 0;
+}
 
-			f->type = V4L2_TUNER_RADIO;
-			f->frequency = card->freq;
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+	if (i != 0)
+		return -EINVAL;
 
-			return 0;
-		}
-		case VIDIOC_QUERYCTRL:
-		{
-			struct v4l2_queryctrl *qc = arg;
-			int i;
+	return 0;
+}
 
-			for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-				if (qc->id && qc->id == radio_qctrl[i].id) {
-					memcpy(qc, &(radio_qctrl[i]),
-								sizeof(*qc));
-					return (0);
-				}
-			}
-			return -EINVAL;
-		}
-		case VIDIOC_G_CTRL:
-		{
-			struct v4l2_control *ctrl= arg;
 
-			switch (ctrl->id) {
-				case V4L2_CID_AUDIO_MUTE:
-					ctrl->value=card->muted;
-					return (0);
-			}
-			return -EINVAL;
-		}
-		case VIDIOC_S_CTRL:
-		{
-			struct v4l2_control *ctrl= arg;
+static int vidioc_s_audio (struct file *file, void *priv,
+			   struct v4l2_audio *a)
+{
+	if (a->index != 0)
+		return -EINVAL;
 
-			switch (ctrl->id) {
-				case V4L2_CID_AUDIO_MUTE:
-					card->muted = ctrl->value;
-					if(card->muted)
-						turn_power(card->io, 0);
-					else
-						set_freq(card->io, FREQ2BITS(card->freq));
-					return 0;
-			}
-			return -EINVAL;
-		}
+	return 0;
+}
 
-		default:
-			return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-							  radio_function);
+static int vidioc_s_frequency (struct file *file, void *priv,
+			       struct v4l2_frequency *f)
+{
+	struct video_device *dev = video_devdata(file);
+	struct radio_device *card=dev->priv;
 
+	if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) {
+		dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n",
+					f->frequency / 16000,
+					f->frequency % 16000 * 100 / 16000,
+					FREQ_LO / 16000, FREQ_HI / 16000);
+
+		return -EINVAL;
 	}
+
+	card->freq = f->frequency;
+	set_freq(card->io, card->freq);
+	msleep(125);
+
+	return 0;
 }
 
-static int radio_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg)
+static int vidioc_g_frequency (struct file *file, void *priv,
+			       struct v4l2_frequency *f)
 {
 	struct video_device *dev = video_devdata(file);
 	struct radio_device *card=dev->priv;
-	int ret;
 
-	mutex_lock(&card->lock);
-	ret = video_usercopy(inode, file, cmd, arg, radio_function);
-	mutex_unlock(&card->lock);
-	return ret;
+	f->type = V4L2_TUNER_RADIO;
+	f->frequency = card->freq;
+
+	dprintk(4, "radio freq is %d.%02d MHz",
+				f->frequency / 16000,
+				f->frequency % 16000 * 100 / 16000);
+
+	return 0;
 }
 
-MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net");
-MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio.");
-MODULE_LICENSE("GPL");
+static int vidioc_queryctrl (struct file *file, void *priv,
+			     struct v4l2_queryctrl *qc)
+{
+	int i;
 
+	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+		if (qc->id && qc->id == radio_qctrl[i].id) {
+			memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
+			return (0);
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_g_ctrl (struct file *file, void *priv,
+			    struct v4l2_control *ctrl)
+{
+	struct video_device *dev = video_devdata(file);
+	struct radio_device *card=dev->priv;
+
+	switch (ctrl->id) {
+		case V4L2_CID_AUDIO_MUTE:
+			ctrl->value=card->muted;
+			return (0);
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_s_ctrl (struct file *file, void *priv,
+			  struct v4l2_control *ctrl)
+{
+	struct video_device *dev = video_devdata(file);
+	struct radio_device *card=dev->priv;
+
+	switch (ctrl->id) {
+		case V4L2_CID_AUDIO_MUTE:
+			card->muted = ctrl->value;
+			if(card->muted)
+				turn_power(card->io, 0);
+			else
+				set_freq(card->io, card->freq);
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
+static struct video_device maxiradio_radio =
+{
+	.owner		    = THIS_MODULE,
+	.name		    = "Maxi Radio FM2000 radio",
+	.type		    = VID_TYPE_TUNER,
+	.fops               = &maxiradio_fops,
+
+	.vidioc_querycap    = vidioc_querycap,
+	.vidioc_g_tuner     = vidioc_g_tuner,
+	.vidioc_s_tuner     = vidioc_s_tuner,
+	.vidioc_g_audio     = vidioc_g_audio,
+	.vidioc_s_audio     = vidioc_s_audio,
+	.vidioc_g_input     = vidioc_g_input,
+	.vidioc_s_input     = vidioc_s_input,
+	.vidioc_g_frequency = vidioc_g_frequency,
+	.vidioc_s_frequency = vidioc_s_frequency,
+	.vidioc_queryctrl   = vidioc_queryctrl,
+	.vidioc_g_ctrl      = vidioc_g_ctrl,
+	.vidioc_s_ctrl      = vidioc_s_ctrl,
+};
 
 static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -335,7 +407,7 @@
 	mutex_init(&radio_unit.lock);
 	maxiradio_radio.priv = &radio_unit;
 
-	if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
+	if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
 		printk("radio-maxiradio: can't register device!");
 		goto err_out_free_region;
 	}
@@ -390,3 +462,10 @@
 
 module_init(maxiradio_radio_init);
 module_exit(maxiradio_radio_exit);
+
+MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net");
+MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio.");
+MODULE_LICENSE("GPL");
+
+module_param_named(debug,maxiradio_radio.debug, int, 0644);
+MODULE_PARM_DESC(debug,"activates debug info");
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index b9e9848..f668387 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -262,7 +262,7 @@
 
 static struct rt_device rtrack2_unit;
 
-static struct file_operations rtrack2_fops = {
+static const struct file_operations rtrack2_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index ecc854b..f4619e4 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -265,7 +265,7 @@
 
 static struct fmi_device fmi_unit;
 
-static struct file_operations fmi_fops = {
+static const struct file_operations fmi_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 4444dce..b96fafe 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -410,7 +410,7 @@
 
 static struct fmr2_device fmr2_unit;
 
-static struct file_operations fmr2_fops = {
+static const struct file_operations fmr2_fops = {
 	.owner          = THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index f539491..d59a27a 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -338,7 +338,7 @@
 
 static struct tt_device terratec_unit;
 
-static struct file_operations terratec_fops = {
+static const struct file_operations terratec_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index bb03ad5..6d7f1e7 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -325,7 +325,7 @@
 	return video_usercopy(inode, file, cmd, arg, tr_do_ioctl);
 }
 
-static struct file_operations trust_fops = {
+static const struct file_operations trust_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index 4a72b4d..3031fef 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -318,7 +318,7 @@
 	.mutefreq	= CONFIG_RADIO_TYPHOON_MUTEFREQ,
 };
 
-static struct file_operations typhoon_fops = {
+static const struct file_operations typhoon_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 671fe1b..ec08491 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -373,7 +373,7 @@
 
 static struct zol_device zoltrix_unit;
 
-static struct file_operations zoltrix_fops =
+static const struct file_operations zoltrix_fops =
 {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 57357db..7a61051 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -342,7 +342,7 @@
 
 config VIDEO_VIVI
 	tristate "Virtual Video Driver"
-	depends on VIDEO_V4L2 && !SPARC32 && !SPARC64
+	depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI
 	select VIDEO_BUF
 	default n
 	---help---
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 9b1f3f0..44ccaed 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -113,4 +113,3 @@
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-extra-cflags-$(CONFIG_VIDEO_V4L1_COMPAT) += -DCONFIG_VIDEO_V4L1_COMPAT
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 4870958..2aa9ce9 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -42,7 +42,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 68e7d7a..a3246a2 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -38,7 +38,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 4861799..649f52f 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -742,7 +742,7 @@
  * Video4Linux Module functions
  *
  ****************************************************************************/
-static struct file_operations ar_fops = {
+static const struct file_operations ar_fops = {
 	.owner		= THIS_MODULE,
 	.open		= video_exclusive_open,
 	.release	= video_exclusive_release,
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index e7b38fd..6867386 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -42,7 +42,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index af3b61d..42e2299 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -42,7 +42,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index 21ebe8f..6addc42 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -307,6 +307,7 @@
 	{ 0x07711461, BTTV_BOARD_AVDVBT_771,    "AVermedia AverTV DVB-T 771" },
 	{ 0x07611461, BTTV_BOARD_AVDVBT_761,    "AverMedia AverTV DVB-T 761" },
 	{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,    "DViCO FusionHDTV DVB-T Lite" },
+	{ 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE,    "Ultraview DVB-T Lite" },
 	{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
 	{ 0x00261822, BTTV_BOARD_TWINHAN_DST,	"DNTV Live! Mini "},
 
@@ -578,14 +579,9 @@
 		.svhs		= 2,
 		.gpiomask	= 0x01fe00,
 		.muxsel		= { 2, 3, 1, 1 },
-	#if 0
-		/* old */
-		.gpiomux 	= { 0x01c000, 0, 0x018000, 0x014000, 0x002000 },
-	#else
 		/* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */
 		.gpiomux        = { 0x001e00, 0, 0x018000, 0x014000 },
 		.gpiomute 	= 0x002000,
-	#endif
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= -1,
@@ -894,15 +890,10 @@
 		.tuner		= 0,
 		.svhs		= 2,
 		.muxsel		= { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */
-	#if 0
-		.gpiomask	= 0xc33000,
-		.gpiomux 	= { 0x422000,0x1000,0x0000,0x620000,0x800000 },
-	#else
 		/* Alexander Varakin <avarakin@hotmail.com> [stereo version] */
 		.gpiomask	= 0xb33000,
 		.gpiomux 	= { 0x122000,0x1000,0x0000,0x620000 },
 		.gpiomute 	= 0x800000,
-	#endif
 		/* Audio Routing for "WinFast 2000 XP" (no tv stereo !)
 			gpio23 -- hef4052:nEnable (0x800000)
 			gpio12 -- hef4052:A1
@@ -1937,11 +1928,6 @@
 		.video_inputs   = 4,
 		.audio_inputs   = 1,
 		.tuner          = -1,
-	#if 0 /* TODO ... */
-		.svhs           = OSPREY540_SVID_ANALOG,
-		.muxsel         = {       [OSPREY540_COMP_ANALOG] = 2,
-					[OSPREY540_SVID_ANALOG] = 3, },
-	#endif
 		.pll            = PLL_28,
 		.tuner_type     = -1,
 		.tuner_addr	= ADDR_UNSET,
@@ -1949,10 +1935,6 @@
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
-	#if 0 /* TODO ... */
-		.muxsel_hook    = osprey_540_muxsel,
-		.picture_hook   = osprey_540_set_picture,
-	#endif
 	},
 
 		/* ---- card 0x5C ---------------------------------- */
@@ -2627,9 +2609,6 @@
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 		.has_radio      = 0,
-	#if 0
-		.has_remote     = 1,
-	#endif
 	},
 	[BTTV_BOARD_SUPER_TV] = {
 		/* Rick C <cryptdragoon@gmail.com> */
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index ab8f970..5720b77 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -9,6 +9,10 @@
     some v4l2 code lines are taken from Justin's bttv2 driver which is
     (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
 
+    Cropping and overscan support
+    Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
+    Sponsored by OPQ Systems AB
+
     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
@@ -64,6 +68,7 @@
 static unsigned int irq_debug;
 static unsigned int gbuffers = 8;
 static unsigned int gbufsize = 0x208000;
+static unsigned int reset_crop = 1;
 
 static int video_nr = -1;
 static int radio_nr = -1;
@@ -103,6 +108,7 @@
 module_param(vbi_nr,            int, 0444);
 module_param(gbuffers,          int, 0444);
 module_param(gbufsize,          int, 0444);
+module_param(reset_crop,        int, 0444);
 
 module_param(v4l2,              int, 0644);
 module_param(bigendian,         int, 0644);
@@ -129,6 +135,8 @@
 MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
 MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
 MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
+MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
+		 "is 1 (yes) for compatibility with older applications");
 MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
 MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
 MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
@@ -192,6 +200,33 @@
 	}
 };
 
+/* minhdelayx1	first video pixel we can capture on a line and
+   hdelayx1	start of active video, both relative to rising edge of
+		/HRESET pulse (0H) in 1 / fCLKx1.
+   swidth	width of active video and
+   totalwidth	total line width, both in 1 / fCLKx1.
+   sqwidth	total line width in square pixels.
+   vdelay	start of active video in 2 * field lines relative to
+		trailing edge of /VRESET pulse (VDELAY register).
+   sheight	height of active video in 2 * field lines.
+   videostart0	ITU-R frame line number of the line corresponding
+		to vdelay in the first field. */
+#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth,	 \
+		vdelay, sheight, videostart0)				 \
+	.cropcap.bounds.left = minhdelayx1,				 \
+	/* * 2 because vertically we count field lines times two, */	 \
+	/* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */		 \
+	.cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
+	/* 4 is a safety margin at the end of the line. */		 \
+	.cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4,	 \
+	.cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY,	 \
+	.cropcap.defrect.left = hdelayx1,				 \
+	.cropcap.defrect.top = (videostart0) * 2,			 \
+	.cropcap.defrect.width = swidth,				 \
+	.cropcap.defrect.height = sheight,				 \
+	.cropcap.pixelaspect.numerator = totalwidth,			 \
+	.cropcap.pixelaspect.denominator = sqwidth,
+
 const struct bttv_tvnorm bttv_tvnorms[] = {
 	/* PAL-BDGHI */
 	/* max. active video is actually 922, but 924 is divisible by 4 and 3! */
@@ -210,11 +245,26 @@
 		.hdelayx1       = 186,
 		.hactivex1      = 924,
 		.vdelay         = 0x20,
-		.vbipack        = 255,
+		.vbipack        = 255, /* min (2048 / 4, 0x1ff) & 0xff */
 		.sram           = 0,
 		/* ITU-R frame line number of the first VBI line
-		   we can capture, of the first and second field. */
-		.vbistart	= { 7,320 },
+		   we can capture, of the first and second field.
+		   The last line is determined by cropcap.bounds. */
+		.vbistart       = { 7, 320 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 186,
+			/* Should be (768 * 1135 + 944 / 2) / 944.
+			   cropcap.defrect is used for image width
+			   checks, so we keep the old value 924. */
+			/* swidth */ 924,
+			/* totalwidth */ 1135,
+			/* sqwidth */ 944,
+			/* vdelay */ 0x20,
+			/* sheight */ 576,
+			/* videostart0 */ 23)
+		/* bt878 (and bt848?) can capture another
+		   line below active video. */
+		.cropcap.bounds.height = (576 + 2) + 0x20 - 2,
 	},{
 		.v4l2_id        = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
 		.name           = "NTSC",
@@ -229,9 +279,18 @@
 		.hdelayx1       = 128,
 		.hactivex1      = 910,
 		.vdelay         = 0x1a,
-		.vbipack        = 144,
+		.vbipack        = 144, /* min (1600 / 4, 0x1ff) & 0xff */
 		.sram           = 1,
 		.vbistart	= { 10, 273 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 128,
+			/* Should be (640 * 910 + 780 / 2) / 780? */
+			/* swidth */ 768,
+			/* totalwidth */ 910,
+			/* sqwidth */ 780,
+			/* vdelay */ 0x1a,
+			/* sheight */ 480,
+			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_SECAM,
 		.name           = "SECAM",
@@ -249,6 +308,14 @@
 		.vbipack        = 255,
 		.sram           = 0, /* like PAL, correct? */
 		.vbistart	= { 7, 320 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 186,
+			/* swidth */ 924,
+			/* totalwidth */ 1135,
+			/* sqwidth */ 944,
+			/* vdelay */ 0x20,
+			/* sheight */ 576,
+			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_PAL_Nc,
 		.name           = "PAL-Nc",
@@ -266,6 +333,14 @@
 		.vbipack        = 144,
 		.sram           = -1,
 		.vbistart	= { 7, 320 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 130,
+			/* swidth */ (640 * 910 + 780 / 2) / 780,
+			/* totalwidth */ 910,
+			/* sqwidth */ 780,
+			/* vdelay */ 0x1a,
+			/* sheight */ 576,
+			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_PAL_M,
 		.name           = "PAL-M",
@@ -283,6 +358,14 @@
 		.vbipack        = 144,
 		.sram           = -1,
 		.vbistart	= { 10, 273 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 135,
+			/* swidth */ (640 * 910 + 780 / 2) / 780,
+			/* totalwidth */ 910,
+			/* sqwidth */ 780,
+			/* vdelay */ 0x1a,
+			/* sheight */ 480,
+			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_PAL_N,
 		.name           = "PAL-N",
@@ -299,7 +382,15 @@
 		.vdelay         = 0x20,
 		.vbipack        = 144,
 		.sram           = -1,
-		.vbistart	= { 7, 320},
+		.vbistart       = { 7, 320 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 186,
+			/* swidth */ (768 * 1135 + 944 / 2) / 944,
+			/* totalwidth */ 1135,
+			/* sqwidth */ 944,
+			/* vdelay */ 0x20,
+			/* sheight */ 576,
+			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_NTSC_M_JP,
 		.name           = "NTSC-JP",
@@ -316,7 +407,15 @@
 		.vdelay         = 0x16,
 		.vbipack        = 144,
 		.sram           = -1,
-		.vbistart	= {10, 273},
+		.vbistart       = { 10, 273 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 135,
+			/* swidth */ (640 * 910 + 780 / 2) / 780,
+			/* totalwidth */ 910,
+			/* sqwidth */ 780,
+			/* vdelay */ 0x16,
+			/* sheight */ 480,
+			/* videostart0 */ 23)
 	},{
 		/* that one hopefully works with the strange timing
 		 * which video recorders produce when playing a NTSC
@@ -338,6 +437,14 @@
 		.vtotal         = 524,
 		.sram           = -1,
 		.vbistart	= { 10, 273 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 186,
+			/* swidth */ 924,
+			/* totalwidth */ 1135,
+			/* sqwidth */ 944,
+			/* vdelay */ 0x1a,
+			/* sheight */ 480,
+			/* videostart0 */ 23)
 	}
 };
 static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
@@ -678,25 +785,89 @@
 /* ----------------------------------------------------------------------- */
 /* resource management                                                     */
 
+/*
+   RESOURCE_    allocated by                freed by
+
+   VIDEO_READ   bttv_read 1)                bttv_read 2)
+
+   VIDEO_STREAM VIDIOC_STREAMON             VIDIOC_STREAMOFF
+		 VIDIOC_QBUF 1)              bttv_release
+		 VIDIOCMCAPTURE 1)
+
+   OVERLAY	 VIDIOCCAPTURE on            VIDIOCCAPTURE off
+		 VIDIOC_OVERLAY on           VIDIOC_OVERLAY off
+		 3)                          bttv_release
+
+   VBI		 VIDIOC_STREAMON             VIDIOC_STREAMOFF
+		 VIDIOC_QBUF 1)              bttv_release
+		 bttv_read, bttv_poll 1) 4)
+
+   1) The resource must be allocated when we enter buffer prepare functions
+      and remain allocated while buffers are in the DMA queue.
+   2) This is a single frame read.
+   3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
+      RESOURCE_OVERLAY is allocated.
+   4) This is a continuous read, implies VIDIOC_STREAMON.
+
+   Note this driver permits video input and standard changes regardless if
+   resources are allocated.
+*/
+
+#define VBI_RESOURCES (RESOURCE_VBI)
+#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
+			 RESOURCE_VIDEO_STREAM | \
+			 RESOURCE_OVERLAY)
+
 static
 int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit)
 {
+	int xbits; /* mutual exclusive resources */
+
 	if (fh->resources & bit)
 		/* have it already allocated */
 		return 1;
 
+	xbits = bit;
+	if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
+		xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
+
 	/* is it free? */
-	mutex_lock(&btv->reslock);
-	if (btv->resources & bit) {
+	mutex_lock(&btv->lock);
+	if (btv->resources & xbits) {
 		/* no, someone else uses it */
-		mutex_unlock(&btv->reslock);
-		return 0;
+		goto fail;
 	}
+
+	if ((bit & VIDEO_RESOURCES)
+	    && 0 == (btv->resources & VIDEO_RESOURCES)) {
+		/* Do crop - use current, don't - use default parameters. */
+		__s32 top = btv->crop[!!fh->do_crop].rect.top;
+
+		if (btv->vbi_end > top)
+			goto fail;
+
+		/* We cannot capture the same line as video and VBI data.
+		   Claim scan lines crop[].rect.top to bottom. */
+		btv->crop_start = top;
+	} else if (bit & VBI_RESOURCES) {
+		__s32 end = fh->vbi_fmt.end;
+
+		if (end > btv->crop_start)
+			goto fail;
+
+		/* Claim scan lines above fh->vbi_fmt.end. */
+		btv->vbi_end = end;
+	}
+
 	/* it's free, grab it */
 	fh->resources  |= bit;
 	btv->resources |= bit;
-	mutex_unlock(&btv->reslock);
+	mutex_unlock(&btv->lock);
 	return 1;
+
+ fail:
+	mutex_unlock(&btv->lock);
+	return 0;
 }
 
 static
@@ -711,6 +882,35 @@
 	return (btv->resources & bit);
 }
 
+/* Call with btv->lock down. */
+static void
+disclaim_vbi_lines(struct bttv *btv)
+{
+	btv->vbi_end = 0;
+}
+
+/* Call with btv->lock down. */
+static void
+disclaim_video_lines(struct bttv *btv)
+{
+	const struct bttv_tvnorm *tvnorm;
+	u8 crop;
+
+	tvnorm = &bttv_tvnorms[btv->tvnorm];
+	btv->crop_start = tvnorm->cropcap.bounds.top
+		+ tvnorm->cropcap.bounds.height;
+
+	/* VBI capturing ends at VDELAY, start of video capturing, no
+	   matter how many lines the VBI RISC program expects. When video
+	   capturing is off, it shall no longer "preempt" VBI capturing,
+	   so we set VDELAY to maximum. */
+	crop = btread(BT848_E_CROP) | 0xc0;
+	btwrite(crop, BT848_E_CROP);
+	btwrite(0xfe, BT848_E_VDELAY_LO);
+	btwrite(crop, BT848_O_CROP);
+	btwrite(0xfe, BT848_O_VDELAY_LO);
+}
+
 static
 void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits)
 {
@@ -718,10 +918,19 @@
 		/* trying to free ressources not allocated by us ... */
 		printk("bttv: BUG! (btres)\n");
 	}
-	mutex_lock(&btv->reslock);
+	mutex_lock(&btv->lock);
 	fh->resources  &= ~bits;
 	btv->resources &= ~bits;
-	mutex_unlock(&btv->reslock);
+
+	bits = btv->resources;
+
+	if (0 == (bits & VIDEO_RESOURCES))
+		disclaim_video_lines(btv);
+
+	if (0 == (bits & VBI_RESOURCES))
+		disclaim_vbi_lines(btv);
+
+	mutex_unlock(&btv->lock);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1030,6 +1239,36 @@
 		bttv_tda9880_setnorm(btv,btv->tvnorm);
 }
 
+static void
+bttv_crop_calc_limits(struct bttv_crop *c)
+{
+	/* Scale factor min. 1:1, max. 16:1. Min. image size
+	   48 x 32. Scaled width must be a multiple of 4. */
+
+	if (1) {
+		/* For bug compatibility with VIDIOCGCAP and image
+		   size checks in earlier driver versions. */
+		c->min_scaled_width = 48;
+		c->min_scaled_height = 32;
+	} else {
+		c->min_scaled_width =
+			(max(48, c->rect.width >> 4) + 3) & ~3;
+		c->min_scaled_height =
+			max(32, c->rect.height >> 4);
+	}
+
+	c->max_scaled_width  = c->rect.width & ~3;
+	c->max_scaled_height = c->rect.height;
+}
+
+static void
+bttv_crop_reset(struct bttv_crop *c, int norm)
+{
+	c->rect = bttv_tvnorms[norm].cropcap.defrect;
+	bttv_crop_calc_limits(c);
+}
+
+/* Call with btv->lock down. */
 static int
 set_tvnorm(struct bttv *btv, unsigned int norm)
 {
@@ -1038,9 +1277,24 @@
 	if (norm < 0 || norm >= BTTV_TVNORMS)
 		return -EINVAL;
 
-	btv->tvnorm = norm;
 	tvnorm = &bttv_tvnorms[norm];
 
+	if (btv->tvnorm < 0 ||
+	    btv->tvnorm >= BTTV_TVNORMS ||
+	    0 != memcmp(&bttv_tvnorms[btv->tvnorm].cropcap,
+			&tvnorm->cropcap,
+			sizeof (tvnorm->cropcap))) {
+		bttv_crop_reset(&btv->crop[0], norm);
+		btv->crop[1] = btv->crop[0]; /* current = default */
+
+		if (0 == (btv->resources & VIDEO_RESOURCES)) {
+			btv->crop_start = tvnorm->cropcap.bounds.top
+				+ tvnorm->cropcap.bounds.height;
+		}
+	}
+
+	btv->tvnorm = norm;
+
 	btwrite(tvnorm->adelay, BT848_ADELAY);
 	btwrite(tvnorm->bdelay, BT848_BDELAY);
 	btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
@@ -1057,6 +1311,7 @@
 	return 0;
 }
 
+/* Call with btv->lock down. */
 static void
 set_input(struct bttv *btv, unsigned int input)
 {
@@ -1459,13 +1714,13 @@
 	btv->loop_irq |= 1;
 	bttv_set_dma(btv, 0x03);
 	spin_unlock_irqrestore(&btv->s_lock,flags);
-	if (NULL == new)
-		free_btres(btv,fh,RESOURCE_OVERLAY);
 	if (NULL != old) {
 		dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
 		bttv_dma_free(&fh->cap,btv, old);
 		kfree(old);
 	}
+	if (NULL == new)
+		free_btres(btv,fh,RESOURCE_OVERLAY);
 	dprintk("switch_overlay: done\n");
 	return retval;
 }
@@ -1479,7 +1734,10 @@
 			       unsigned int width, unsigned int height,
 			       enum v4l2_field field)
 {
+	struct bttv_fh *fh = q->priv_data;
 	int redo_dma_risc = 0;
+	struct bttv_crop c;
+	int norm;
 	int rc;
 
 	/* check settings */
@@ -1491,12 +1749,52 @@
 		if (width*height > buf->vb.bsize)
 			return -EINVAL;
 		buf->vb.size = buf->vb.bsize;
-	} else {
-		if (width  < 48 ||
-		    height < 32 ||
-		    width  > bttv_tvnorms[btv->tvnorm].swidth ||
-		    height > bttv_tvnorms[btv->tvnorm].sheight)
+
+		/* Make sure tvnorm and vbi_end remain consistent
+		   until we're done. */
+		mutex_lock(&btv->lock);
+
+		norm = btv->tvnorm;
+
+		/* In this mode capturing always starts at defrect.top
+		   (default VDELAY), ignoring cropping parameters. */
+		if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
+			mutex_unlock(&btv->lock);
 			return -EINVAL;
+		}
+
+		mutex_unlock(&btv->lock);
+
+		c.rect = bttv_tvnorms[norm].cropcap.defrect;
+	} else {
+		mutex_lock(&btv->lock);
+
+		norm = btv->tvnorm;
+		c = btv->crop[!!fh->do_crop];
+
+		mutex_unlock(&btv->lock);
+
+		if (width < c.min_scaled_width ||
+		    width > c.max_scaled_width ||
+		    height < c.min_scaled_height)
+			return -EINVAL;
+
+		switch (field) {
+		case V4L2_FIELD_TOP:
+		case V4L2_FIELD_BOTTOM:
+		case V4L2_FIELD_ALTERNATE:
+			/* btv->crop counts frame lines. Max. scale
+			   factor is 16:1 for frames, 8:1 for fields. */
+			if (height * 2 > c.max_scaled_height)
+				return -EINVAL;
+			break;
+
+		default:
+			if (height > c.max_scaled_height)
+				return -EINVAL;
+			break;
+		}
+
 		buf->vb.size = (width * height * fmt->depth) >> 3;
 		if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
 			return -EINVAL;
@@ -1505,12 +1803,17 @@
 	/* alloc + fill struct bttv_buffer (if changed) */
 	if (buf->vb.width != width || buf->vb.height != height ||
 	    buf->vb.field != field ||
-	    buf->tvnorm != btv->tvnorm || buf->fmt != fmt) {
+	    buf->tvnorm != norm || buf->fmt != fmt ||
+	    buf->crop.top != c.rect.top ||
+	    buf->crop.left != c.rect.left ||
+	    buf->crop.width != c.rect.width ||
+	    buf->crop.height != c.rect.height) {
 		buf->vb.width  = width;
 		buf->vb.height = height;
 		buf->vb.field  = field;
-		buf->tvnorm    = btv->tvnorm;
+		buf->tvnorm    = norm;
 		buf->fmt       = fmt;
+		buf->crop      = c.rect;
 		redo_dma_risc = 1;
 	}
 
@@ -1577,7 +1880,7 @@
 	struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
 	struct bttv_fh *fh = q->priv_data;
 
-	bttv_dma_free(&fh->cap,fh->btv,buf);
+	bttv_dma_free(q,fh->btv,buf);
 }
 
 static struct videobuf_queue_ops bttv_video_qops = {
@@ -1939,11 +2242,179 @@
 	return 0;
 }
 
-static int verify_window(const struct bttv_tvnorm *tvn,
-			 struct v4l2_window *win, int fixup)
+/* Given cropping boundaries b and the scaled width and height of a
+   single field or frame, which must not exceed hardware limits, this
+   function adjusts the cropping parameters c. */
+static void
+bttv_crop_adjust	(struct bttv_crop *             c,
+			 const struct v4l2_rect *	b,
+			 __s32                          width,
+			 __s32                          height,
+			 enum v4l2_field                field)
+{
+	__s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
+	__s32 max_left;
+	__s32 max_top;
+
+	if (width < c->min_scaled_width) {
+		/* Max. hor. scale factor 16:1. */
+		c->rect.width = width * 16;
+	} else if (width > c->max_scaled_width) {
+		/* Min. hor. scale factor 1:1. */
+		c->rect.width = width;
+
+		max_left = b->left + b->width - width;
+		max_left = min(max_left, (__s32) MAX_HDELAY);
+		if (c->rect.left > max_left)
+			c->rect.left = max_left;
+	}
+
+	if (height < c->min_scaled_height) {
+		/* Max. vert. scale factor 16:1, single fields 8:1. */
+		c->rect.height = height * 16;
+	} else if (frame_height > c->max_scaled_height) {
+		/* Min. vert. scale factor 1:1.
+		   Top and height count field lines times two. */
+		c->rect.height = (frame_height + 1) & ~1;
+
+		max_top = b->top + b->height - c->rect.height;
+		if (c->rect.top > max_top)
+			c->rect.top = max_top;
+	}
+
+	bttv_crop_calc_limits(c);
+}
+
+/* Returns an error if scaling to a frame or single field with the given
+   width and height is not possible with the current cropping parameters
+   and width aligned according to width_mask. If adjust_size is TRUE the
+   function may adjust the width and/or height instead, rounding width
+   to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
+   also adjust the current cropping parameters to get closer to the
+   desired image size. */
+static int
+limit_scaled_size       (struct bttv_fh *               fh,
+			 __s32 *                        width,
+			 __s32 *                        height,
+			 enum v4l2_field                field,
+			 unsigned int			width_mask,
+			 unsigned int			width_bias,
+			 int                            adjust_size,
+			 int                            adjust_crop)
+{
+	struct bttv *btv = fh->btv;
+	const struct v4l2_rect *b;
+	struct bttv_crop *c;
+	__s32 min_width;
+	__s32 min_height;
+	__s32 max_width;
+	__s32 max_height;
+	int rc;
+
+	BUG_ON((int) width_mask >= 0 ||
+	       width_bias >= (unsigned int) -width_mask);
+
+	/* Make sure tvnorm, vbi_end and the current cropping parameters
+	   remain consistent until we're done. */
+	mutex_lock(&btv->lock);
+
+	b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
+
+	/* Do crop - use current, don't - use default parameters. */
+	c = &btv->crop[!!fh->do_crop];
+
+	if (fh->do_crop
+	    && adjust_size
+	    && adjust_crop
+	    && !locked_btres(btv, VIDEO_RESOURCES)) {
+		min_width = 48;
+		min_height = 32;
+
+		/* We cannot scale up. When the scaled image is larger
+		   than crop.rect we adjust the crop.rect as required
+		   by the V4L2 spec, hence cropcap.bounds are our limit. */
+		max_width = min(b->width, (__s32) MAX_HACTIVE);
+		max_height = b->height;
+
+		/* We cannot capture the same line as video and VBI data.
+		   Note btv->vbi_end is really a minimum, see
+		   bttv_vbi_try_fmt(). */
+		if (btv->vbi_end > b->top) {
+			max_height -= btv->vbi_end - b->top;
+			rc = -EBUSY;
+			if (min_height > max_height)
+				goto fail;
+		}
+	} else {
+		rc = -EBUSY;
+		if (btv->vbi_end > c->rect.top)
+			goto fail;
+
+		min_width  = c->min_scaled_width;
+		min_height = c->min_scaled_height;
+		max_width  = c->max_scaled_width;
+		max_height = c->max_scaled_height;
+
+		adjust_crop = 0;
+	}
+
+	min_width = (min_width - width_mask - 1) & width_mask;
+	max_width = max_width & width_mask;
+
+	/* Max. scale factor is 16:1 for frames, 8:1 for fields. */
+	min_height = min_height;
+	/* Min. scale factor is 1:1. */
+	max_height >>= !V4L2_FIELD_HAS_BOTH(field);
+
+	if (adjust_size) {
+		*width = clamp(*width, min_width, max_width);
+		*height = clamp(*height, min_height, max_height);
+
+		/* Round after clamping to avoid overflow. */
+		*width = (*width + width_bias) & width_mask;
+
+		if (adjust_crop) {
+			bttv_crop_adjust(c, b, *width, *height, field);
+
+			if (btv->vbi_end > c->rect.top) {
+				/* Move the crop window out of the way. */
+				c->rect.top = btv->vbi_end;
+			}
+		}
+	} else {
+		rc = -EINVAL;
+		if (*width  < min_width ||
+		    *height < min_height ||
+		    *width  > max_width ||
+		    *height > max_height ||
+		    0 != (*width & ~width_mask))
+			goto fail;
+	}
+
+	rc = 0; /* success */
+
+ fail:
+	mutex_unlock(&btv->lock);
+
+	return rc;
+}
+
+/* Returns an error if the given overlay window dimensions are not
+   possible with the current cropping parameters. If adjust_size is
+   TRUE the function may adjust the window width and/or height
+   instead, however it always rounds the horizontal position and
+   width as btcx_align() does. If adjust_crop is TRUE the function
+   may also adjust the current cropping parameters to get closer
+   to the desired window size. */
+static int
+verify_window		(struct bttv_fh *               fh,
+			 struct v4l2_window *           win,
+			 int                            adjust_size,
+			 int                            adjust_crop)
 {
 	enum v4l2_field field;
-	int maxw, maxh;
+	unsigned int width_mask;
+	int rc;
 
 	if (win->w.width  < 48 || win->w.height < 32)
 		return -EINVAL;
@@ -1951,32 +2422,52 @@
 		return -EINVAL;
 
 	field = win->field;
-	maxw  = tvn->swidth;
-	maxh  = tvn->sheight;
 
 	if (V4L2_FIELD_ANY == field) {
-		field = (win->w.height > maxh/2)
+		__s32 height2;
+
+		height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
+		field = (win->w.height > height2)
 			? V4L2_FIELD_INTERLACED
 			: V4L2_FIELD_TOP;
 	}
 	switch (field) {
 	case V4L2_FIELD_TOP:
 	case V4L2_FIELD_BOTTOM:
-		maxh = maxh / 2;
-		break;
 	case V4L2_FIELD_INTERLACED:
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	if (!fixup && (win->w.width > maxw || win->w.height > maxh))
+	/* 4-byte alignment. */
+	if (NULL == fh->ovfmt)
 		return -EINVAL;
+	width_mask = ~0;
+	switch (fh->ovfmt->depth) {
+	case 8:
+	case 24:
+		width_mask = ~3;
+		break;
+	case 16:
+		width_mask = ~1;
+		break;
+	case 32:
+		break;
+	default:
+		BUG();
+	}
 
-	if (win->w.width > maxw)
-		win->w.width = maxw;
-	if (win->w.height > maxh)
-		win->w.height = maxh;
+	win->w.width -= win->w.left & ~width_mask;
+	win->w.left = (win->w.left - width_mask - 1) & width_mask;
+
+	rc = limit_scaled_size(fh, &win->w.width, &win->w.height,
+			       field, width_mask,
+			       /* width_bias: round down */ 0,
+			       adjust_size, adjust_crop);
+	if (0 != rc)
+		return rc;
+
 	win->field = field;
 	return 0;
 }
@@ -1991,7 +2482,9 @@
 		return -EINVAL;
 	if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
 		return -EINVAL;
-	retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup);
+	retval = verify_window(fh, win,
+			       /* adjust_size */ fixup,
+			       /* adjust_crop */ fixup);
 	if (0 != retval)
 		return retval;
 
@@ -2048,6 +2541,7 @@
 		struct bttv_buffer *new;
 
 		new = videobuf_alloc(sizeof(*new));
+		new->crop = btv->crop[!!fh->do_crop].rect;
 		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
 		retval = bttv_switch_overlay(btv,fh,new);
 	}
@@ -2080,7 +2574,7 @@
 
 	switch (fh->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		res = RESOURCE_VIDEO;
+		res = RESOURCE_VIDEO_STREAM;
 		break;
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
 		res = RESOURCE_VBI;
@@ -2138,7 +2632,7 @@
 		f->fmt.win.field = fh->ov.field;
 		return 0;
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		bttv_vbi_get_fmt(fh,f);
+		bttv_vbi_get_fmt(fh, &f->fmt.vbi);
 		return 0;
 	default:
 		return -EINVAL;
@@ -2146,35 +2640,35 @@
 }
 
 static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
-			struct v4l2_format *f)
+			struct v4l2_format *f, int adjust_crop)
 {
 	switch (f->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	{
 		const struct bttv_format *fmt;
 		enum v4l2_field field;
-		unsigned int maxw,maxh;
+		__s32 width, height;
+		int rc;
 
 		fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 		if (NULL == fmt)
 			return -EINVAL;
 
-		/* fixup format */
-		maxw  = bttv_tvnorms[btv->tvnorm].swidth;
-		maxh  = bttv_tvnorms[btv->tvnorm].sheight;
 		field = f->fmt.pix.field;
-		if (V4L2_FIELD_ANY == field)
-			field = (f->fmt.pix.height > maxh/2)
+		if (V4L2_FIELD_ANY == field) {
+			__s32 height2;
+
+			height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+			field = (f->fmt.pix.height > height2)
 				? V4L2_FIELD_INTERLACED
 				: V4L2_FIELD_BOTTOM;
+		}
 		if (V4L2_FIELD_SEQ_BT == field)
 			field = V4L2_FIELD_SEQ_TB;
 		switch (field) {
 		case V4L2_FIELD_TOP:
 		case V4L2_FIELD_BOTTOM:
 		case V4L2_FIELD_ALTERNATE:
-			maxh = maxh/2;
-			break;
 		case V4L2_FIELD_INTERLACED:
 			break;
 		case V4L2_FIELD_SEQ_TB:
@@ -2185,28 +2679,29 @@
 			return -EINVAL;
 		}
 
+		width = f->fmt.pix.width;
+		height = f->fmt.pix.height;
+
+		rc = limit_scaled_size(fh, &width, &height, field,
+				       /* width_mask: 4 pixels */ ~3,
+				       /* width_bias: nearest */ 2,
+				       /* adjust_size */ 1,
+				       adjust_crop);
+		if (0 != rc)
+			return rc;
+
 		/* update data for the application */
 		f->fmt.pix.field = field;
-		if (f->fmt.pix.width  < 48)
-			f->fmt.pix.width  = 48;
-		if (f->fmt.pix.height < 32)
-			f->fmt.pix.height = 32;
-		if (f->fmt.pix.width  > maxw)
-			f->fmt.pix.width = maxw;
-		if (f->fmt.pix.height > maxh)
-			f->fmt.pix.height = maxh;
-		pix_format_set_size (&f->fmt.pix, fmt,
-				     f->fmt.pix.width & ~3,
-				     f->fmt.pix.height);
+		pix_format_set_size(&f->fmt.pix, fmt, width, height);
 
 		return 0;
 	}
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-		return verify_window(&bttv_tvnorms[btv->tvnorm],
-				     &f->fmt.win, 1);
+		return verify_window(fh, &f->fmt.win,
+				     /* adjust_size */ 1,
+				     /* adjust_crop */ 0);
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		bttv_vbi_try_fmt(fh,f);
-		return 0;
+		return bttv_vbi_try_fmt(fh, &f->fmt.vbi);
 	default:
 		return -EINVAL;
 	}
@@ -2225,7 +2720,7 @@
 		retval = bttv_switch_type(fh,f->type);
 		if (0 != retval)
 			return retval;
-		retval = bttv_try_fmt(fh,btv,f);
+		retval = bttv_try_fmt(fh,btv,f, /* adjust_crop */ 1);
 		if (0 != retval)
 			return retval;
 		fmt = format_by_fourcc(f->fmt.pix.pixelformat);
@@ -2254,12 +2749,7 @@
 		retval = bttv_switch_type(fh,f->type);
 		if (0 != retval)
 			return retval;
-		if (locked_btres(fh->btv, RESOURCE_VBI))
-			return -EBUSY;
-		bttv_vbi_try_fmt(fh,f);
-		bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]);
-		bttv_vbi_get_fmt(fh,f);
-		return 0;
+		return bttv_vbi_set_fmt(fh, &f->fmt.vbi);
 	default:
 		return -EINVAL;
 	}
@@ -2517,6 +3007,7 @@
 		if (*on) {
 			fh->ov.tvnorm = btv->tvnorm;
 			new = videobuf_alloc(sizeof(*new));
+			new->crop = btv->crop[!!fh->do_crop].rect;
 			bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
 		} else {
 			new = NULL;
@@ -2551,10 +3042,16 @@
 		struct video_mmap *vm = arg;
 		struct bttv_buffer *buf;
 		enum v4l2_field field;
+		__s32 height2;
+		int res;
 
 		if (vm->frame >= VIDEO_MAX_FRAME)
 			return -EINVAL;
 
+		res = bttv_resource(fh);
+		if (!check_alloc_btres(btv, fh, res))
+			return -EBUSY;
+
 		mutex_lock(&fh->cap.lock);
 		retval = -EINVAL;
 		buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame];
@@ -2566,7 +3063,8 @@
 		    buf->vb.state == STATE_ACTIVE)
 			goto fh_unlock_and_return;
 
-		field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2)
+		height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+		field = (vm->height > height2)
 			? V4L2_FIELD_INTERLACED
 			: V4L2_FIELD_BOTTOM;
 		retval = bttv_prepare_buffer(&fh->cap,btv,buf,
@@ -2613,54 +3111,17 @@
 	}
 
 	case VIDIOCGVBIFMT:
-	{
-		struct vbi_format *fmt = (void *) arg;
-		struct v4l2_format fmt2;
-
 		if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) {
 			retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
 			if (0 != retval)
 				return retval;
 		}
-		bttv_vbi_get_fmt(fh, &fmt2);
 
-		memset(fmt,0,sizeof(*fmt));
-		fmt->sampling_rate    = fmt2.fmt.vbi.sampling_rate;
-		fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line;
-		fmt->sample_format    = VIDEO_PALETTE_RAW;
-		fmt->start[0]         = fmt2.fmt.vbi.start[0];
-		fmt->count[0]         = fmt2.fmt.vbi.count[0];
-		fmt->start[1]         = fmt2.fmt.vbi.start[1];
-		fmt->count[1]         = fmt2.fmt.vbi.count[1];
-		if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC)
-			fmt->flags   |= VBI_UNSYNC;
-		if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED)
-			fmt->flags   |= VBI_INTERLACED;
-		return 0;
-	}
+		/* fall through */
+
 	case VIDIOCSVBIFMT:
-	{
-		struct vbi_format *fmt = (void *) arg;
-		struct v4l2_format fmt2;
-
-		retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
-		if (0 != retval)
-			return retval;
-		bttv_vbi_get_fmt(fh, &fmt2);
-
-		if (fmt->sampling_rate    != fmt2.fmt.vbi.sampling_rate     ||
-		    fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line  ||
-		    fmt->sample_format    != VIDEO_PALETTE_RAW              ||
-		    fmt->start[0]         != fmt2.fmt.vbi.start[0]          ||
-		    fmt->start[1]         != fmt2.fmt.vbi.start[1]          ||
-		    fmt->count[0]         != fmt->count[1]                  ||
-		    fmt->count[0]         <  1                              ||
-		    fmt->count[0]         >  32 /* VBI_MAXLINES */)
-			return -EINVAL;
-
-		bttv_vbi_setlines(fh,btv,fmt->count[0]);
-		return 0;
-	}
+		return v4l_compat_translate_ioctl(inode, file, cmd,
+						  arg, bttv_do_ioctl);
 
 	case BTTV_VERSION:
 	case VIDIOCGFREQ:
@@ -2753,7 +3214,7 @@
 	case VIDIOC_TRY_FMT:
 	{
 		struct v4l2_format *f = arg;
-		return bttv_try_fmt(fh,btv,f);
+		return bttv_try_fmt(fh,btv,f, /* adjust_crop */ 0);
 	}
 	case VIDIOC_G_FMT:
 	{
@@ -2792,16 +3253,23 @@
 		if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
 			return -EINVAL;
 
-		mutex_lock(&fh->cap.lock);
 		retval = -EINVAL;
 		if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
-			if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth)
-				goto fh_unlock_and_return;
-			if (fb->fmt.height > bttv_tvnorms[btv->tvnorm].sheight)
-				goto fh_unlock_and_return;
+			__s32 width = fb->fmt.width;
+			__s32 height = fb->fmt.height;
+
+			retval = limit_scaled_size(fh, &width, &height,
+						   V4L2_FIELD_INTERLACED,
+						   /* width_mask */ ~3,
+						   /* width_bias */ 2,
+						   /* adjust_size */ 0,
+						   /* adjust_crop */ 0);
+			if (0 != retval)
+				return retval;
 		}
 
 		/* ok, accept it */
+		mutex_lock(&fh->cap.lock);
 		btv->fbuf.base       = fb->base;
 		btv->fbuf.fmt.width  = fb->fmt.width;
 		btv->fbuf.fmt.height = fb->fmt.height;
@@ -2828,6 +3296,7 @@
 				struct bttv_buffer *new;
 
 				new = videobuf_alloc(sizeof(*new));
+				new->crop = btv->crop[!!fh->do_crop].rect;
 				bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
 				retval = bttv_switch_overlay(btv,fh,new);
 			}
@@ -2843,7 +3312,13 @@
 		return videobuf_querybuf(bttv_queue(fh),arg);
 
 	case VIDIOC_QBUF:
+	{
+		int res = bttv_resource(fh);
+
+		if (!check_alloc_btres(btv, fh, res))
+			return -EBUSY;
 		return videobuf_qbuf(bttv_queue(fh),arg);
+	}
 
 	case VIDIOC_DQBUF:
 		return videobuf_dqbuf(bttv_queue(fh),arg,
@@ -2942,6 +3417,122 @@
 		return v4l2_prio_change(&btv->prio, &fh->prio, *prio);
 	}
 
+	case VIDIOC_CROPCAP:
+	{
+		struct v4l2_cropcap *cap = arg;
+		enum v4l2_buf_type type;
+
+		type = cap->type;
+
+		if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+		    type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+			return -EINVAL;
+
+		*cap = bttv_tvnorms[btv->tvnorm].cropcap;
+		cap->type = type;
+
+		return 0;
+	}
+	case VIDIOC_G_CROP:
+	{
+		struct v4l2_crop * crop = arg;
+
+		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+		    crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+			return -EINVAL;
+
+		/* No fh->do_crop = 1; because btv->crop[1] may be
+		   inconsistent with fh->width or fh->height and apps
+		   do not expect a change here. */
+
+		crop->c = btv->crop[!!fh->do_crop].rect;
+
+		return 0;
+	}
+	case VIDIOC_S_CROP:
+	{
+		struct v4l2_crop *crop = arg;
+		const struct v4l2_rect *b;
+		struct bttv_crop c;
+		__s32 b_left;
+		__s32 b_top;
+		__s32 b_right;
+		__s32 b_bottom;
+
+		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+		    crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+			return -EINVAL;
+
+		retval = v4l2_prio_check(&btv->prio,&fh->prio);
+		if (0 != retval)
+			return retval;
+
+		/* Make sure tvnorm, vbi_end and the current cropping
+		   parameters remain consistent until we're done. Note
+		   read() may change vbi_end in check_alloc_btres(). */
+		mutex_lock(&btv->lock);
+
+		retval = -EBUSY;
+
+		if (locked_btres(fh->btv, VIDEO_RESOURCES))
+			goto btv_unlock_and_return;
+
+		b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
+
+		b_left = b->left;
+		b_right = b_left + b->width;
+		b_bottom = b->top + b->height;
+
+		b_top = max(b->top, btv->vbi_end);
+		if (b_top + 32 >= b_bottom)
+			goto btv_unlock_and_return;
+
+		/* Min. scaled size 48 x 32. */
+		c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
+		c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
+
+		c.rect.width = clamp(crop->c.width,
+				     48, b_right - c.rect.left);
+
+		c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
+		/* Top and height must be a multiple of two. */
+		c.rect.top = (c.rect.top + 1) & ~1;
+
+		c.rect.height = clamp(crop->c.height,
+				      32, b_bottom - c.rect.top);
+		c.rect.height = (c.rect.height + 1) & ~1;
+
+		bttv_crop_calc_limits(&c);
+
+		btv->crop[1] = c;
+
+		mutex_unlock(&btv->lock);
+
+		fh->do_crop = 1;
+
+		mutex_lock(&fh->cap.lock);
+
+		if (fh->width < c.min_scaled_width) {
+			fh->width = c.min_scaled_width;
+			btv->init.width = c.min_scaled_width;
+		} else if (fh->width > c.max_scaled_width) {
+			fh->width = c.max_scaled_width;
+			btv->init.width = c.max_scaled_width;
+		}
+
+		if (fh->height < c.min_scaled_height) {
+			fh->height = c.min_scaled_height;
+			btv->init.height = c.min_scaled_height;
+		} else if (fh->height > c.max_scaled_height) {
+			fh->height = c.max_scaled_height;
+			btv->init.height = c.max_scaled_height;
+		}
+
+		mutex_unlock(&fh->cap.lock);
+
+		return 0;
+	}
+
 	case VIDIOC_ENUMSTD:
 	case VIDIOC_G_STD:
 	case VIDIOC_S_STD:
@@ -2963,6 +3554,10 @@
  fh_unlock_and_return:
 	mutex_unlock(&fh->cap.lock);
 	return retval;
+
+ btv_unlock_and_return:
+	mutex_unlock(&btv->lock);
+	return retval;
 }
 
 static int bttv_ioctl(struct inode *inode, struct file *file,
@@ -2972,8 +3567,26 @@
 
 	switch (cmd) {
 	case BTTV_VBISIZE:
+	{
+		const struct bttv_tvnorm *tvnorm;
+
+		tvnorm = fh->vbi_fmt.tvnorm;
+
+		if (fh->vbi_fmt.fmt.start[0] != tvnorm->vbistart[0] ||
+		    fh->vbi_fmt.fmt.start[1] != tvnorm->vbistart[1] ||
+		    fh->vbi_fmt.fmt.count[0] != fh->vbi_fmt.fmt.count[1]) {
+			/* BTTV_VBISIZE cannot express these parameters,
+			   however open() resets the paramters to defaults
+			   and apps shouldn't call BTTV_VBISIZE after
+			   VIDIOC_S_FMT. */
+			return -EINVAL;
+		}
+
 		bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
-		return fh->lines * 2 * 2048;
+		return (fh->vbi_fmt.fmt.count[0] * 2
+			* fh->vbi_fmt.fmt.samples_per_line);
+	}
+
 	default:
 		return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl);
 	}
@@ -2992,10 +3605,14 @@
 
 	switch (fh->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		if (locked_btres(fh->btv,RESOURCE_VIDEO))
+		if (!check_alloc_btres(fh->btv, fh, RESOURCE_VIDEO_READ)) {
+			/* VIDEO_READ in use by another fh,
+			   or VIDEO_STREAM by any fh. */
 			return -EBUSY;
+		}
 		retval = videobuf_read_one(&fh->cap, data, count, ppos,
 					   file->f_flags & O_NONBLOCK);
+		free_btres(fh->btv, fh, RESOURCE_VIDEO_READ);
 		break;
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
 		if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
@@ -3021,7 +3638,7 @@
 		return videobuf_poll_stream(file, &fh->vbi, wait);
 	}
 
-	if (check_btres(fh,RESOURCE_VIDEO)) {
+	if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
 		/* streaming capture */
 		if (list_empty(&fh->cap.stream))
 			return POLLERR;
@@ -3031,7 +3648,7 @@
 		mutex_lock(&fh->cap.lock);
 		if (NULL == fh->cap.read_buf) {
 			/* need to capture a new frame */
-			if (locked_btres(fh->btv,RESOURCE_VIDEO)) {
+			if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM)) {
 				mutex_unlock(&fh->cap.lock);
 				return POLLERR;
 			}
@@ -3117,8 +3734,23 @@
 	i2c_vidiocschan(btv);
 
 	btv->users++;
-	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
-		bttv_vbi_setlines(fh,btv,16);
+
+	/* The V4L2 spec requires one global set of cropping parameters
+	   which only change on request. These are stored in btv->crop[1].
+	   However for compatibility with V4L apps and cropping unaware
+	   V4L2 apps we now reset the cropping parameters as seen through
+	   this fh, which is to say VIDIOC_G_CROP and scaling limit checks
+	   will use btv->crop[0], the default cropping parameters for the
+	   current video standard, and VIDIOC_S_FMT will not implicitely
+	   change the cropping parameters until VIDIOC_S_CROP has been
+	   called. */
+	fh->do_crop = !reset_crop; /* module parameter */
+
+	/* Likewise there should be one global set of VBI capture
+	   parameters, but for compatibility with V4L apps and earlier
+	   driver versions each fh has its own parameters. */
+	bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
+
 	bttv_field_count(btv);
 	return 0;
 }
@@ -3133,14 +3765,17 @@
 		bttv_switch_overlay(btv,fh,NULL);
 
 	/* stop video capture */
-	if (check_btres(fh, RESOURCE_VIDEO)) {
+	if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
 		videobuf_streamoff(&fh->cap);
-		free_btres(btv,fh,RESOURCE_VIDEO);
+		free_btres(btv,fh,RESOURCE_VIDEO_STREAM);
 	}
 	if (fh->cap.read_buf) {
 		buffer_release(&fh->cap,fh->cap.read_buf);
 		kfree(fh->cap.read_buf);
 	}
+	if (check_btres(fh, RESOURCE_VIDEO_READ)) {
+		free_btres(btv, fh, RESOURCE_VIDEO_READ);
+	}
 
 	/* stop vbi capture */
 	if (check_btres(fh, RESOURCE_VBI)) {
@@ -3174,7 +3809,7 @@
 	return videobuf_mmap_mapper(bttv_queue(fh),vma);
 }
 
-static struct file_operations bttv_fops =
+static const struct file_operations bttv_fops =
 {
 	.owner	  = THIS_MODULE,
 	.open	  = bttv_open,
@@ -3332,7 +3967,7 @@
 	return cmd.result;
 }
 
-static struct file_operations radio_fops =
+static const struct file_operations radio_fops =
 {
 	.owner	  = THIS_MODULE,
 	.open	  = radio_open,
@@ -3997,7 +4632,6 @@
 
 	/* initialize structs / fill in defaults */
 	mutex_init(&btv->lock);
-	mutex_init(&btv->reslock);
 	spin_lock_init(&btv->s_lock);
 	spin_lock_init(&btv->gpio_lock);
 	init_waitqueue_head(&btv->gpioq);
@@ -4095,7 +4729,6 @@
 	btv->init.fmt         = format_by_palette(VIDEO_PALETTE_RGB24);
 	btv->init.width       = 320;
 	btv->init.height      = 240;
-	btv->init.lines       = 16;
 	btv->input = 0;
 
 	/* initialize hardware */
@@ -4130,6 +4763,10 @@
 		bt848_sat(btv,32768);
 		audio_mute(btv, 1);
 		set_input(btv,0);
+		bttv_crop_reset(&btv->crop[0], btv->tvnorm);
+		btv->crop[1] = btv->crop[0]; /* current = default */
+		disclaim_vbi_lines(btv);
+		disclaim_video_lines(btv);
 	}
 
 	/* add subdevices */
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index cbc012f..6f74c80 100644
--- a/drivers/media/video/bt8xx/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
@@ -36,13 +36,18 @@
 static int repeat_period = 33;
 module_param(repeat_period, int, 0644);
 
+static int ir_rc5_remote_gap = 885;
+module_param(ir_rc5_remote_gap, int, 0644);
+static int ir_rc5_key_timeout = 200;
+module_param(ir_rc5_key_timeout, int, 0644);
+
 #define DEVNAME "bttv-input"
 
 /* ---------------------------------------------------------------------- */
 
 static void ir_handle_key(struct bttv *btv)
 {
-	struct bttv_ir *ir = btv->remote;
+	struct card_ir *ir = btv->remote;
 	u32 gpio,data;
 
 	/* read gpio value */
@@ -72,7 +77,7 @@
 
 void bttv_input_irq(struct bttv *btv)
 {
-	struct bttv_ir *ir = btv->remote;
+	struct card_ir *ir = btv->remote;
 
 	if (!ir->polling)
 		ir_handle_key(btv);
@@ -81,65 +86,21 @@
 static void bttv_input_timer(unsigned long data)
 {
 	struct bttv *btv = (struct bttv*)data;
-	struct bttv_ir *ir = btv->remote;
-	unsigned long timeout;
+	struct card_ir *ir = btv->remote;
 
 	ir_handle_key(btv);
-	timeout = jiffies + (ir->polling * HZ / 1000);
-	mod_timer(&ir->timer, timeout);
+	mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
 }
 
 /* ---------------------------------------------------------------*/
 
-static int rc5_remote_gap = 885;
-module_param(rc5_remote_gap, int, 0644);
-static int rc5_key_timeout = 200;
-module_param(rc5_key_timeout, int, 0644);
-
-#define RC5_START(x)	(((x)>>12)&3)
-#define RC5_TOGGLE(x)	(((x)>>11)&1)
-#define RC5_ADDR(x)	(((x)>>6)&31)
-#define RC5_INSTR(x)	((x)&63)
-
-/* decode raw bit pattern to RC5 code */
-static u32 rc5_decode(unsigned int code)
-{
-	unsigned int org_code = code;
-	unsigned int pair;
-	unsigned int rc5 = 0;
-	int i;
-
-	code = (code << 1) | 1;
-	for (i = 0; i < 14; ++i) {
-		pair = code & 0x3;
-		code >>= 2;
-
-		rc5 <<= 1;
-		switch (pair) {
-		case 0:
-		case 2:
-			break;
-		case 1:
-			rc5 |= 1;
-			break;
-		case 3:
-			dprintk(KERN_WARNING "bad code: %x\n", org_code);
-			return 0;
-		}
-	}
-	dprintk(KERN_WARNING "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
-		"instr=%x\n", rc5, org_code, RC5_START(rc5),
-		RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
-	return rc5;
-}
-
 static int bttv_rc5_irq(struct bttv *btv)
 {
-	struct bttv_ir *ir = btv->remote;
+	struct card_ir *ir = btv->remote;
 	struct timeval tv;
 	u32 gpio;
 	u32 gap;
-	unsigned long current_jiffies, timeout;
+	unsigned long current_jiffies;
 
 	/* read gpio port */
 	gpio = bttv_gpio_read(&btv->c);
@@ -165,8 +126,8 @@
 		/* only if in the code (otherwise spurious IRQ or timer
 		   late) */
 		if (ir->last_bit < 28) {
-			ir->last_bit = (gap - rc5_remote_gap / 2) /
-			    rc5_remote_gap;
+			ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
+			    ir_rc5_remote_gap;
 			ir->code |= 1 << ir->last_bit;
 		}
 		/* starting new code */
@@ -176,8 +137,8 @@
 		ir->base_time = tv;
 		ir->last_bit = 0;
 
-		timeout = current_jiffies + (500 + 30 * HZ) / 1000;
-		mod_timer(&ir->timer_end, timeout);
+		mod_timer(&ir->timer_end,
+			  current_jiffies + msecs_to_jiffies(30));
 	}
 
 	/* toggle GPIO pin 4 to reset the irq */
@@ -186,96 +147,28 @@
 	return 1;
 }
 
-
-static void bttv_rc5_timer_end(unsigned long data)
-{
-	struct bttv_ir *ir = (struct bttv_ir *)data;
-	struct timeval tv;
-	unsigned long current_jiffies, timeout;
-	u32 gap;
-
-	/* get time */
-	current_jiffies = jiffies;
-	do_gettimeofday(&tv);
-
-	/* avoid overflow with gap >1s */
-	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
-		gap = 200000;
-	} else {
-		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
-		    tv.tv_usec - ir->base_time.tv_usec;
-	}
-
-	/* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
-	if (gap < 28000) {
-		dprintk(KERN_WARNING "spurious timer_end\n");
-		return;
-	}
-
-	ir->active = 0;
-	if (ir->last_bit < 20) {
-		/* ignore spurious codes (caused by light/other remotes) */
-		dprintk(KERN_WARNING "short code: %x\n", ir->code);
-	} else {
-		u32 rc5 = rc5_decode(ir->code);
-
-		/* two start bits? */
-		if (RC5_START(rc5) != 3) {
-			dprintk(KERN_WARNING "rc5 start bits invalid: %u\n", RC5_START(rc5));
-
-			/* right address? */
-		} else if (RC5_ADDR(rc5) == 0x0) {
-			u32 toggle = RC5_TOGGLE(rc5);
-			u32 instr = RC5_INSTR(rc5);
-
-			/* Good code, decide if repeat/repress */
-			if (toggle != RC5_TOGGLE(ir->last_rc5) ||
-			    instr != RC5_INSTR(ir->last_rc5)) {
-				dprintk(KERN_WARNING "instruction %x, toggle %x\n", instr,
-					toggle);
-				ir_input_nokey(ir->dev, &ir->ir);
-				ir_input_keydown(ir->dev, &ir->ir, instr,
-						 instr);
-			}
-
-			/* Set/reset key-up timer */
-			timeout = current_jiffies + (500 + rc5_key_timeout
-						     * HZ) / 1000;
-			mod_timer(&ir->timer_keyup, timeout);
-
-			/* Save code for repeat test */
-			ir->last_rc5 = rc5;
-		}
-	}
-}
-
-static void bttv_rc5_timer_keyup(unsigned long data)
-{
-	struct bttv_ir *ir = (struct bttv_ir *)data;
-
-	dprintk(KERN_DEBUG "key released\n");
-	ir_input_nokey(ir->dev, &ir->ir);
-}
-
 /* ---------------------------------------------------------------------- */
 
-static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
+static void bttv_ir_start(struct bttv *btv, struct card_ir *ir)
 {
 	if (ir->polling) {
-		init_timer(&ir->timer);
-		ir->timer.function = bttv_input_timer;
-		ir->timer.data     = (unsigned long)btv;
+		setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv);
 		ir->timer.expires  = jiffies + HZ;
 		add_timer(&ir->timer);
 	} else if (ir->rc5_gpio) {
 		/* set timer_end for code completion */
 		init_timer(&ir->timer_end);
-		ir->timer_end.function = bttv_rc5_timer_end;
+		ir->timer_end.function = ir_rc5_timer_end;
 		ir->timer_end.data = (unsigned long)ir;
 
 		init_timer(&ir->timer_keyup);
-		ir->timer_keyup.function = bttv_rc5_timer_keyup;
+		ir->timer_keyup.function = ir_rc5_timer_keyup;
 		ir->timer_keyup.data = (unsigned long)ir;
+		ir->shift_by = 1;
+		ir->start = 3;
+		ir->addr = 0x0;
+		ir->rc5_key_timeout = ir_rc5_key_timeout;
+		ir->rc5_remote_gap = ir_rc5_remote_gap;
 	}
 }
 
@@ -299,7 +192,7 @@
 
 int bttv_input_init(struct bttv *btv)
 {
-	struct bttv_ir *ir;
+	struct card_ir *ir;
 	IR_KEYTAB_TYPE *ir_codes = NULL;
 	struct input_dev *input_dev;
 	int ir_type = IR_TYPE_OTHER;
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c
index afcfe71..e7104d9 100644
--- a/drivers/media/video/bt8xx/bttv-risc.c
+++ b/drivers/media/video/bt8xx/bttv-risc.c
@@ -43,7 +43,8 @@
 bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
 		 struct scatterlist *sglist,
 		 unsigned int offset, unsigned int bpl,
-		 unsigned int padding, unsigned int lines)
+		 unsigned int padding, unsigned int skip_lines,
+		 unsigned int store_lines)
 {
 	u32 instructions,line,todo;
 	struct scatterlist *sg;
@@ -54,9 +55,11 @@
 	   one write per scan line + sync + jump (all 2 dwords).  padding
 	   can cause next bpl to start close to a page border.  First DMA
 	   region may be smaller than PAGE_SIZE */
-	instructions  = 1 + ((bpl + padding) * lines) / PAGE_SIZE + lines;
-	instructions += 2;
-	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0)
+	instructions  = skip_lines * 4;
+	instructions += (1 + ((bpl + padding) * store_lines)
+			 / PAGE_SIZE + store_lines) * 8;
+	instructions += 2 * 8;
+	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
 		return rc;
 
 	/* sync instruction */
@@ -64,11 +67,16 @@
 	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
 	*(rp++) = cpu_to_le32(0);
 
+	while (skip_lines-- > 0) {
+		*(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
+				      BT848_RISC_EOL | bpl);
+	}
+
 	/* scan lines */
 	sg = sglist;
-	for (line = 0; line < lines; line++) {
+	for (line = 0; line < store_lines; line++) {
 		if ((btv->opt_vcr_hack) &&
-		    (line >= (lines - VCR_HACK_LINES)))
+		    (line >= (store_lines - VCR_HACK_LINES)))
 			continue;
 		while (offset && offset >= sg_dma_len(sg)) {
 			offset -= sg_dma_len(sg);
@@ -130,7 +138,8 @@
 	/* estimate risc mem: worst case is one write per page border +
 	   one write per scan line (5 dwords)
 	   plus sync + jump (2 dwords) */
-	instructions  = (ybpl * ylines * 2) / PAGE_SIZE + ylines;
+	instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
+			 / PAGE_SIZE) + ylines;
 	instructions += 2;
 	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
 		return rc;
@@ -317,10 +326,10 @@
 /* ---------------------------------------------------------- */
 
 static void
-bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo,
-	      int width, int height, int interleaved, int norm)
+bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
+		  int width, int height, int interleaved,
+		  const struct bttv_tvnorm *tvnorm)
 {
-	const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm];
 	u32 xsf, sr;
 	int vdelay;
 
@@ -361,6 +370,62 @@
 }
 
 static void
+bttv_calc_geo		(struct bttv *                  btv,
+			 struct bttv_geometry *         geo,
+			 unsigned int                   width,
+			 unsigned int                   height,
+			 int                            both_fields,
+			 const struct bttv_tvnorm *     tvnorm,
+			 const struct v4l2_rect *       crop)
+{
+	unsigned int c_width;
+	unsigned int c_height;
+	u32 sr;
+
+	if ((crop->left == tvnorm->cropcap.defrect.left
+	     && crop->top == tvnorm->cropcap.defrect.top
+	     && crop->width == tvnorm->cropcap.defrect.width
+	     && crop->height == tvnorm->cropcap.defrect.height
+	     && width <= tvnorm->swidth /* see PAL-Nc et al */)
+	    || bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) {
+		bttv_calc_geo_old(btv, geo, width, height,
+				  both_fields, tvnorm);
+		return;
+	}
+
+	/* For bug compatibility the image size checks permit scale
+	   factors > 16. See bttv_crop_calc_limits(). */
+	c_width = min((unsigned int) crop->width, width * 16);
+	c_height = min((unsigned int) crop->height, height * 16);
+
+	geo->width = width;
+	geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
+	/* Even to store Cb first, odd for Cr. */
+	geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
+
+	geo->sheight = c_height;
+	geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
+	sr = c_height >> !both_fields;
+	sr = (sr * 512U + (height >> 1)) / height - 512;
+	geo->vscale = (0x10000UL - sr) & 0x1fff;
+	geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
+	geo->vtotal = tvnorm->vtotal;
+
+	geo->crop = (((geo->width   >> 8) & 0x03) |
+		     ((geo->hdelay  >> 6) & 0x0c) |
+		     ((geo->sheight >> 4) & 0x30) |
+		     ((geo->vdelay  >> 2) & 0xc0));
+
+	if (btv->opt_combfilter) {
+		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
+		geo->comb = (width < 769) ? 1 : 0;
+	} else {
+		geo->vtc  = 0;
+		geo->comb = 0;
+	}
+}
+
+static void
 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
 {
 	int off = odd ? 0x80 : 0x00;
@@ -522,16 +587,51 @@
 bttv_buffer_activate_vbi(struct bttv *btv,
 			 struct bttv_buffer *vbi)
 {
-	/* vbi capture */
+	struct btcx_riscmem *top;
+	struct btcx_riscmem *bottom;
+	int top_irq_flags;
+	int bottom_irq_flags;
+
+	top = NULL;
+	bottom = NULL;
+	top_irq_flags = 0;
+	bottom_irq_flags = 0;
+
 	if (vbi) {
+		unsigned int crop, vdelay;
+
 		vbi->vb.state = STATE_ACTIVE;
 		list_del(&vbi->vb.queue);
-		bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top,    0);
-		bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4);
-	} else {
-		bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
-		bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
+
+		/* VDELAY is start of video, end of VBI capturing. */
+		crop = btread(BT848_E_CROP);
+		vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
+
+		if (vbi->geo.vdelay > vdelay) {
+			vdelay = vbi->geo.vdelay & 0xfe;
+			crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
+
+			btwrite(vdelay, BT848_E_VDELAY_LO);
+			btwrite(crop,	BT848_E_CROP);
+			btwrite(vdelay, BT848_O_VDELAY_LO);
+			btwrite(crop,	BT848_O_CROP);
+		}
+
+		if (vbi->vbi_count[0] > 0) {
+			top = &vbi->top;
+			top_irq_flags = 4;
+		}
+
+		if (vbi->vbi_count[1] > 0) {
+			top_irq_flags = 0;
+			bottom = &vbi->bottom;
+			bottom_irq_flags = 4;
+		}
 	}
+
+	bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
+	bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
+
 	return 0;
 }
 
@@ -611,28 +711,31 @@
 		int bpf = bpl * (buf->vb.height >> 1);
 
 		bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
-			      V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm);
+			      V4L2_FIELD_HAS_BOTH(buf->vb.field),
+			      tvnorm,&buf->crop);
 
 		switch (buf->vb.field) {
 		case V4L2_FIELD_TOP:
 			bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
-					 0,bpl,0,buf->vb.height);
+					 /* offset */ 0,bpl,
+					 /* padding */ 0,/* skip_lines */ 0,
+					 buf->vb.height);
 			break;
 		case V4L2_FIELD_BOTTOM:
 			bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
-					 0,bpl,0,buf->vb.height);
+					 0,bpl,0,0,buf->vb.height);
 			break;
 		case V4L2_FIELD_INTERLACED:
 			bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
-					 0,bpl,bpl,buf->vb.height >> 1);
+					 0,bpl,bpl,0,buf->vb.height >> 1);
 			bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
-					 bpl,bpl,bpl,buf->vb.height >> 1);
+					 bpl,bpl,bpl,0,buf->vb.height >> 1);
 			break;
 		case V4L2_FIELD_SEQ_TB:
 			bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
-					 0,bpl,0,buf->vb.height >> 1);
+					 0,bpl,0,0,buf->vb.height >> 1);
 			bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
-					 bpf,bpl,0,buf->vb.height >> 1);
+					 bpf,bpl,0,0,buf->vb.height >> 1);
 			break;
 		default:
 			BUG();
@@ -662,7 +765,8 @@
 		switch (buf->vb.field) {
 		case V4L2_FIELD_TOP:
 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-				      buf->vb.height,0,buf->tvnorm);
+				      buf->vb.height,/* both_fields */ 0,
+				      tvnorm,&buf->crop);
 			bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist,
 					 0,buf->vb.width,0,buf->vb.height,
 					 uoffset,voffset,buf->fmt->hshift,
@@ -670,7 +774,8 @@
 			break;
 		case V4L2_FIELD_BOTTOM:
 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-				      buf->vb.height,0,buf->tvnorm);
+				      buf->vb.height,0,
+				      tvnorm,&buf->crop);
 			bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist,
 					 0,buf->vb.width,0,buf->vb.height,
 					 uoffset,voffset,buf->fmt->hshift,
@@ -678,7 +783,8 @@
 			break;
 		case V4L2_FIELD_INTERLACED:
 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-				      buf->vb.height,1,buf->tvnorm);
+				      buf->vb.height,1,
+				      tvnorm,&buf->crop);
 			lines    = buf->vb.height >> 1;
 			ypadding = buf->vb.width;
 			cpadding = buf->vb.width >> buf->fmt->hshift;
@@ -700,7 +806,8 @@
 			break;
 		case V4L2_FIELD_SEQ_TB:
 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-				      buf->vb.height,1,buf->tvnorm);
+				      buf->vb.height,1,
+				      tvnorm,&buf->crop);
 			lines    = buf->vb.height >> 1;
 			ypadding = buf->vb.width;
 			cpadding = buf->vb.width >> buf->fmt->hshift;
@@ -731,11 +838,12 @@
 		/* build risc code */
 		buf->vb.field = V4L2_FIELD_SEQ_TB;
 		bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
-			      1,buf->tvnorm);
+			      1,tvnorm,&buf->crop);
 		bttv_risc_packed(btv, &buf->top,  buf->vb.dma.sglist,
-				 0, RAW_BPL, 0, RAW_LINES);
+				 /* offset */ 0, RAW_BPL, /* padding */ 0,
+				 /* skip_lines */ 0, RAW_LINES);
 		bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist,
-				 buf->vb.size/2 , RAW_BPL, 0, RAW_LINES);
+				 buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
 	}
 
 	/* copy format info */
@@ -761,7 +869,8 @@
 
 	/* calculate geometry */
 	bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
-		      V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm);
+		      V4L2_FIELD_HAS_BOTH(ov->field),
+		      &bttv_tvnorms[ov->tvnorm],&buf->crop);
 
 	/* build risc code */
 	switch (ov->field) {
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index 63676e7..93e35de 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -5,6 +5,9 @@
 
     (c) 2002 Gerd Knorr <kraxel@bytesex.org>
 
+    Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
+    Sponsored by OPQ Systems AB
+
     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
@@ -25,7 +28,6 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/kdev_t.h>
 #include <asm/io.h>
@@ -42,8 +44,15 @@
    to be about 244.  */
 #define VBI_OFFSET 244
 
+/* 2048 for compatibility with earlier driver versions. The driver
+   really stores 1024 + tvnorm->vbipack * 4 samples per line in the
+   buffer. Note tvnorm->vbipack is <= 0xFF (limit of VBIPACK_LO + HI
+   is 0x1FF DWORDs) and VBI read()s store a frame counter in the last
+   four bytes of the VBI image. */
+#define VBI_BPL 2048
+
+/* Compatibility. */
 #define VBI_DEFLINES 16
-#define VBI_MAXLINES 32
 
 static unsigned int vbibufs = 4;
 static unsigned int vbi_debug = 0;
@@ -59,21 +68,12 @@
 #define dprintk(fmt, arg...)	if (vbi_debug) \
 	printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg)
 
+#define IMAGE_SIZE(fmt) \
+	(((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
+
 /* ----------------------------------------------------------------------- */
 /* vbi risc code + mm                                                      */
 
-static int
-vbi_buffer_risc(struct bttv *btv, struct bttv_buffer *buf, int lines)
-{
-	int bpl = 2048;
-
-	bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist,
-			 0, bpl-4, 4, lines);
-	bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist,
-			 lines * bpl, bpl-4, 4, lines);
-	return 0;
-}
-
 static int vbi_buffer_setup(struct videobuf_queue *q,
 			    unsigned int *count, unsigned int *size)
 {
@@ -82,8 +82,16 @@
 
 	if (0 == *count)
 		*count = vbibufs;
-	*size = fh->lines * 2 * 2048;
-	dprintk("setup: lines=%d\n",fh->lines);
+
+	*size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
+
+	dprintk("setup: samples=%u start=%d,%d count=%u,%u\n",
+		fh->vbi_fmt.fmt.samples_per_line,
+		fh->vbi_fmt.fmt.start[0],
+		fh->vbi_fmt.fmt.start[1],
+		fh->vbi_fmt.fmt.count[0],
+		fh->vbi_fmt.fmt.count[1]);
+
 	return 0;
 }
 
@@ -94,18 +102,93 @@
 	struct bttv_fh *fh = q->priv_data;
 	struct bttv *btv = fh->btv;
 	struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+	const struct bttv_tvnorm *tvnorm;
+	unsigned int skip_lines0, skip_lines1, min_vdelay;
+	int redo_dma_risc;
 	int rc;
 
-	buf->vb.size = fh->lines * 2 * 2048;
+	buf->vb.size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
 		return -EINVAL;
 
+	tvnorm = fh->vbi_fmt.tvnorm;
+
+	/* There's no VBI_VDELAY register, RISC must skip the lines
+	   we don't want. With default parameters we skip zero lines
+	   as earlier driver versions did. The driver permits video
+	   standard changes while capturing, so we use vbi_fmt.tvnorm
+	   instead of btv->tvnorm to skip zero lines after video
+	   standard changes as well. */
+
+	skip_lines0 = 0;
+	skip_lines1 = 0;
+
+	if (fh->vbi_fmt.fmt.count[0] > 0)
+		skip_lines0 = max(0, (fh->vbi_fmt.fmt.start[0]
+				      - tvnorm->vbistart[0]));
+	if (fh->vbi_fmt.fmt.count[1] > 0)
+		skip_lines1 = max(0, (fh->vbi_fmt.fmt.start[1]
+				      - tvnorm->vbistart[1]));
+
+	redo_dma_risc = 0;
+
+	if (buf->vbi_skip[0] != skip_lines0 ||
+	    buf->vbi_skip[1] != skip_lines1 ||
+	    buf->vbi_count[0] != fh->vbi_fmt.fmt.count[0] ||
+	    buf->vbi_count[1] != fh->vbi_fmt.fmt.count[1]) {
+		buf->vbi_skip[0] = skip_lines0;
+		buf->vbi_skip[1] = skip_lines1;
+		buf->vbi_count[0] = fh->vbi_fmt.fmt.count[0];
+		buf->vbi_count[1] = fh->vbi_fmt.fmt.count[1];
+		redo_dma_risc = 1;
+	}
+
 	if (STATE_NEEDS_INIT == buf->vb.state) {
+		redo_dma_risc = 1;
 		if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
 			goto fail;
-		if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines)))
-			goto fail;
 	}
+
+	if (redo_dma_risc) {
+		unsigned int bpl, padding, offset;
+
+		bpl = 2044; /* max. vbipack */
+		padding = VBI_BPL - bpl;
+
+		if (fh->vbi_fmt.fmt.count[0] > 0) {
+			rc = bttv_risc_packed(btv, &buf->top,
+					      buf->vb.dma.sglist,
+					      /* offset */ 0, bpl,
+					      padding, skip_lines0,
+					      fh->vbi_fmt.fmt.count[0]);
+			if (0 != rc)
+				goto fail;
+		}
+
+		if (fh->vbi_fmt.fmt.count[1] > 0) {
+			offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL;
+
+			rc = bttv_risc_packed(btv, &buf->bottom,
+					      buf->vb.dma.sglist,
+					      offset, bpl,
+					      padding, skip_lines1,
+					      fh->vbi_fmt.fmt.count[1]);
+			if (0 != rc)
+				goto fail;
+		}
+	}
+
+	/* VBI capturing ends at VDELAY, start of video capturing,
+	   no matter where the RISC program ends. VDELAY minimum is 2,
+	   bounds.top is the corresponding first field line number
+	   times two. VDELAY counts half field lines. */
+	min_vdelay = MIN_VDELAY;
+	if (fh->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
+		min_vdelay += fh->vbi_fmt.end - tvnorm->cropcap.bounds.top;
+
+	/* For bttv_buffer_activate_vbi(). */
+	buf->geo.vdelay = min_vdelay;
+
 	buf->vb.state = STATE_PREPARED;
 	buf->vb.field = field;
 	dprintk("buf prepare %p: top=%p bottom=%p field=%s\n",
@@ -141,7 +224,7 @@
 	struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
 
 	dprintk("free %p\n",vb);
-	bttv_dma_free(&fh->cap,fh->btv,buf);
+	bttv_dma_free(q,fh->btv,buf);
 }
 
 struct videobuf_queue_ops bttv_vbi_qops = {
@@ -153,69 +236,215 @@
 
 /* ----------------------------------------------------------------------- */
 
-void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines)
+static int
+try_fmt			(struct v4l2_vbi_format *	f,
+			 const struct bttv_tvnorm *	tvnorm,
+			 __s32				crop_start)
 {
-	int vdelay;
+	__s32 min_start, max_start, max_end, f2_offset;
+	unsigned int i;
 
-	if (lines < 1)
-		lines = 1;
-	if (lines > VBI_MAXLINES)
-		lines = VBI_MAXLINES;
-	fh->lines = lines;
+	/* For compatibility with earlier driver versions we must pretend
+	   the VBI and video capture window may overlap. In reality RISC
+	   magic aborts VBI capturing at the first line of video capturing,
+	   leaving the rest of the buffer unchanged, usually all zero.
+	   VBI capturing must always start before video capturing. >> 1
+	   because cropping counts field lines times two. */
+	min_start = tvnorm->vbistart[0];
+	max_start = (crop_start >> 1) - 1;
+	max_end = (tvnorm->cropcap.bounds.top
+		   + tvnorm->cropcap.bounds.height) >> 1;
 
-	vdelay = btread(BT848_E_VDELAY_LO);
-	if (vdelay < lines*2) {
-		vdelay = lines*2;
-		btwrite(vdelay,BT848_E_VDELAY_LO);
-		btwrite(vdelay,BT848_O_VDELAY_LO);
+	if (min_start > max_start)
+		return -EBUSY;
+
+	BUG_ON(max_start >= max_end);
+
+	f->sampling_rate    = tvnorm->Fsc;
+	f->samples_per_line = VBI_BPL;
+	f->sample_format    = V4L2_PIX_FMT_GREY;
+	f->offset           = VBI_OFFSET;
+
+	f2_offset = tvnorm->vbistart[1] - tvnorm->vbistart[0];
+
+	for (i = 0; i < 2; ++i) {
+		if (0 == f->count[i]) {
+			/* No data from this field. We leave f->start[i]
+			   alone because VIDIOCSVBIFMT is w/o and EINVALs
+			   when a driver does not support exactly the
+			   requested parameters. */
+		} else {
+			s64 start, count;
+
+			start = clamp(f->start[i], min_start, max_start);
+			/* s64 to prevent overflow. */
+			count = (s64) f->start[i] + f->count[i] - start;
+			f->start[i] = start;
+			f->count[i] = clamp(count, (s64) 1,
+					    max_end - start);
+		}
+
+		min_start += f2_offset;
+		max_start += f2_offset;
+		max_end += f2_offset;
+	}
+
+	if (0 == (f->count[0] | f->count[1])) {
+		/* As in earlier driver versions. */
+		f->start[0] = tvnorm->vbistart[0];
+		f->start[1] = tvnorm->vbistart[1];
+		f->count[0] = 1;
+		f->count[1] = 1;
+	}
+
+	f->flags = 0;
+
+	f->reserved[0] = 0;
+	f->reserved[1] = 0;
+
+	return 0;
+}
+
+int
+bttv_vbi_try_fmt	(struct bttv_fh *		fh,
+			 struct v4l2_vbi_format *	f)
+{
+	struct bttv *btv = fh->btv;
+	const struct bttv_tvnorm *tvnorm;
+	__s32 crop_start;
+
+	mutex_lock(&btv->lock);
+
+	tvnorm = &bttv_tvnorms[btv->tvnorm];
+	crop_start = btv->crop_start;
+
+	mutex_unlock(&btv->lock);
+
+	return try_fmt(f, tvnorm, crop_start);
+}
+
+int
+bttv_vbi_set_fmt	(struct bttv_fh *		fh,
+			 struct v4l2_vbi_format *	f)
+{
+	struct bttv *btv = fh->btv;
+	const struct bttv_tvnorm *tvnorm;
+	__s32 start1, end;
+	int rc;
+
+	mutex_lock(&btv->lock);
+
+	rc = -EBUSY;
+	if (fh->resources & RESOURCE_VBI)
+		goto fail;
+
+	tvnorm = &bttv_tvnorms[btv->tvnorm];
+
+	rc = try_fmt(f, tvnorm, btv->crop_start);
+	if (0 != rc)
+		goto fail;
+
+	start1 = f->start[1] - tvnorm->vbistart[1] + tvnorm->vbistart[0];
+
+	/* First possible line of video capturing. Should be
+	   max(f->start[0] + f->count[0], start1 + f->count[1]) * 2
+	   when capturing both fields. But for compatibility we must
+	   pretend the VBI and video capture window may overlap,
+	   so end = start + 1, the lowest possible value, times two
+	   because vbi_fmt.end counts field lines times two. */
+	end = max(f->start[0], start1) * 2 + 2;
+
+	mutex_lock(&fh->vbi.lock);
+
+	fh->vbi_fmt.fmt    = *f;
+	fh->vbi_fmt.tvnorm = tvnorm;
+	fh->vbi_fmt.end    = end;
+
+	mutex_unlock(&fh->vbi.lock);
+
+	rc = 0;
+
+ fail:
+	mutex_unlock(&btv->lock);
+
+	return rc;
+}
+
+void
+bttv_vbi_get_fmt	(struct bttv_fh *		fh,
+			 struct v4l2_vbi_format *	f)
+{
+	const struct bttv_tvnorm *tvnorm;
+
+	*f = fh->vbi_fmt.fmt;
+
+	tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
+
+	if (tvnorm != fh->vbi_fmt.tvnorm) {
+		__s32 max_end;
+		unsigned int i;
+
+		/* As in vbi_buffer_prepare() this imitates the
+		   behaviour of earlier driver versions after video
+		   standard changes, with default parameters anyway. */
+
+		max_end = (tvnorm->cropcap.bounds.top
+			   + tvnorm->cropcap.bounds.height) >> 1;
+
+		f->sampling_rate = tvnorm->Fsc;
+
+		for (i = 0; i < 2; ++i) {
+			__s32 new_start;
+
+			new_start = f->start[i]
+				+ tvnorm->vbistart[i]
+				- fh->vbi_fmt.tvnorm->vbistart[i];
+
+			f->start[i] = min(new_start, max_end - 1);
+			f->count[i] = min((__s32) f->count[i],
+					  max_end - f->start[i]);
+
+			max_end += tvnorm->vbistart[1]
+				- tvnorm->vbistart[0];
+		}
 	}
 }
 
-void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
+void
+bttv_vbi_fmt_reset	(struct bttv_vbi_fmt *		f,
+			 int				norm)
 {
 	const struct bttv_tvnorm *tvnorm;
-	s64 count0,count1,count;
+	unsigned int real_samples_per_line;
+	unsigned int real_count;
 
-	tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
-	f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-	f->fmt.vbi.sampling_rate    = tvnorm->Fsc;
-	f->fmt.vbi.samples_per_line = 2048;
-	f->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
-	f->fmt.vbi.offset           = VBI_OFFSET;
-	f->fmt.vbi.flags            = 0;
+	tvnorm = &bttv_tvnorms[norm];
 
-	/* s64 to prevent overflow. */
-	count0 = (s64) f->fmt.vbi.start[0] + f->fmt.vbi.count[0]
-		- tvnorm->vbistart[0];
-	count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1]
-		- tvnorm->vbistart[1];
-	count  = clamp (max (count0, count1), (s64) 1, (s64) VBI_MAXLINES);
+	f->fmt.sampling_rate    = tvnorm->Fsc;
+	f->fmt.samples_per_line = VBI_BPL;
+	f->fmt.sample_format    = V4L2_PIX_FMT_GREY;
+	f->fmt.offset           = VBI_OFFSET;
+	f->fmt.start[0]		= tvnorm->vbistart[0];
+	f->fmt.start[1]		= tvnorm->vbistart[1];
+	f->fmt.count[0]		= VBI_DEFLINES;
+	f->fmt.count[1]		= VBI_DEFLINES;
+	f->fmt.flags            = 0;
+	f->fmt.reserved[0]      = 0;
+	f->fmt.reserved[1]      = 0;
 
-	f->fmt.vbi.start[0] = tvnorm->vbistart[0];
-	f->fmt.vbi.start[1] = tvnorm->vbistart[1];
-	f->fmt.vbi.count[0] = count;
-	f->fmt.vbi.count[1] = count;
+	/* For compatibility the buffer size must be 2 * VBI_DEFLINES *
+	   VBI_BPL regardless of the current video standard. */
+	real_samples_per_line   = 1024 + tvnorm->vbipack * 4;
+	real_count              = ((tvnorm->cropcap.defrect.top >> 1)
+				   - tvnorm->vbistart[0]);
 
-	f->fmt.vbi.reserved[0] = 0;
-	f->fmt.vbi.reserved[1] = 0;
-}
+	BUG_ON(real_samples_per_line > VBI_BPL);
+	BUG_ON(real_count > VBI_DEFLINES);
 
-void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
-{
-	const struct bttv_tvnorm *tvnorm;
+	f->tvnorm               = tvnorm;
 
-	tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
-	memset(f,0,sizeof(*f));
-	f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-	f->fmt.vbi.sampling_rate    = tvnorm->Fsc;
-	f->fmt.vbi.samples_per_line = 2048;
-	f->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
-	f->fmt.vbi.offset           = VBI_OFFSET;
-	f->fmt.vbi.start[0]         = tvnorm->vbistart[0];
-	f->fmt.vbi.start[1]         = tvnorm->vbistart[1];
-	f->fmt.vbi.count[0]         = fh->lines;
-	f->fmt.vbi.count[1]         = fh->lines;
-	f->fmt.vbi.flags            = 0;
+	/* See bttv_vbi_fmt_set(). */
+	f->end                  = tvnorm->vbistart[0] * 2 + 2;
 }
 
 /* ----------------------------------------------------------------------- */
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
index f9c9e3c..5491acb 100644
--- a/drivers/media/video/bt8xx/bttv.h
+++ b/drivers/media/video/bt8xx/bttv.h
@@ -197,33 +197,6 @@
 struct bttv;
 
 
-struct bttv_ir {
-	struct input_dev        *dev;
-	struct ir_input_state   ir;
-	char                    name[32];
-	char                    phys[32];
-
-	/* Usual gpio signalling */
-
-	u32                     mask_keycode;
-	u32                     mask_keydown;
-	u32                     mask_keyup;
-	u32                     polling;
-	u32                     last_gpio;
-	struct work_struct      work;
-	struct timer_list       timer;
-
-	/* RC5 gpio */
-	u32 rc5_gpio;
-	struct timer_list timer_end;	/* timer_end for code completion */
-	struct timer_list timer_keyup;	/* timer_end for key release */
-	u32 last_rc5;			/* last good rc5 code */
-	u32 last_bit;			/* last raw bit seen */
-	u32 code;			/* raw code under construction */
-	struct timeval base_time;	/* time of last seen code */
-	int active;			/* building raw code */
-};
-
 struct tvcard
 {
 	char *name;
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index 311c4c5..ad79b8d 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -26,7 +26,7 @@
 #define _BTTVP_H_
 
 #include <linux/version.h>
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16)
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,17)
 
 #include <linux/types.h>
 #include <linux/wait.h>
@@ -66,14 +66,22 @@
 #define RISC_SLOT_LOOP        14
 
 #define RESOURCE_OVERLAY       1
-#define RESOURCE_VIDEO         2
+#define RESOURCE_VIDEO_STREAM  2
 #define RESOURCE_VBI           4
+#define RESOURCE_VIDEO_READ    8
 
 #define RAW_LINES            640
 #define RAW_BPL             1024
 
 #define UNSET (-1U)
 
+/* Min. value in VDELAY register. */
+#define MIN_VDELAY 2
+/* Even to get Cb first, odd for Cr. */
+#define MAX_HDELAY (0x3FF & -2)
+/* Limits scaled width, which must be a multiple of 4. */
+#define MAX_HACTIVE (0x3FF & -4)
+
 #define clamp(x, low, high) min (max (low, x), high)
 
 /* ---------------------------------------------------------- */
@@ -92,8 +100,13 @@
 	u16   vtotal;
 	int   sram;
 	/* ITU-R frame line number of the first VBI line we can
-	   capture, of the first and second field. */
+	   capture, of the first and second field. The last possible line
+	   is determined by cropcap.bounds. */
 	u16   vbistart[2];
+	/* Horizontally this counts fCLKx1 samples following the leading
+	   edge of the horizontal sync pulse, vertically ITU-R frame line
+	   numbers of the first field times two (2, 4, 6, ... 524 or 624). */
+	struct v4l2_cropcap cropcap;
 };
 extern const struct bttv_tvnorm bttv_tvnorms[];
 
@@ -128,6 +141,9 @@
 	struct bttv_geometry       geo;
 	struct btcx_riscmem        top;
 	struct btcx_riscmem        bottom;
+	struct v4l2_rect           crop;
+	unsigned int               vbi_skip[2];
+	unsigned int               vbi_count[2];
 };
 
 struct bttv_buffer_set {
@@ -146,6 +162,34 @@
 	int                    setup_ok;
 };
 
+struct bttv_vbi_fmt {
+	struct v4l2_vbi_format fmt;
+
+	/* fmt.start[] and count[] refer to this video standard. */
+	const struct bttv_tvnorm *tvnorm;
+
+	/* Earliest possible start of video capturing with this
+	   v4l2_vbi_format, in struct bttv_crop.rect units. */
+	__s32                  end;
+};
+
+/* bttv-vbi.c */
+void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm);
+
+struct bttv_crop {
+	/* A cropping rectangle in struct bttv_tvnorm.cropcap units. */
+	struct v4l2_rect       rect;
+
+	/* Scaled image size limits with this crop rect. Divide
+	   max_height, but not min_height, by two when capturing
+	   single fields. See also bttv_crop_reset() and
+	   bttv_crop_adjust() in bttv-driver.c. */
+	__s32                  min_scaled_width;
+	__s32                  min_scaled_height;
+	__s32                  max_scaled_width;
+	__s32                  max_scaled_height;
+};
+
 struct bttv_fh {
 	struct bttv              *btv;
 	int resources;
@@ -160,13 +204,19 @@
 	int                      width;
 	int                      height;
 
-	/* current settings */
+	/* video overlay */
 	const struct bttv_format *ovfmt;
 	struct bttv_overlay      ov;
 
-	/* video overlay */
+	/* Application called VIDIOC_S_CROP. */
+	int                      do_crop;
+
+	/* vbi capture */
 	struct videobuf_queue    vbi;
-	int                      lines;
+	/* Current VBI capture window as seen through this fh (cannot
+	   be global for compatibility with earlier drivers). Protected
+	   by struct bttv.lock and struct bttv_fh.vbi.lock. */
+	struct bttv_vbi_fmt      vbi_fmt;
 };
 
 /* ---------------------------------------------------------- */
@@ -176,7 +226,8 @@
 int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
 		     struct scatterlist *sglist,
 		     unsigned int offset, unsigned int bpl,
-		     unsigned int pitch, unsigned int lines);
+		     unsigned int pitch, unsigned int skip_lines,
+		     unsigned int store_lines);
 
 /* control dma register + risc main loop */
 void bttv_set_dma(struct bttv *btv, int override);
@@ -202,9 +253,9 @@
 /* ---------------------------------------------------------- */
 /* bttv-vbi.c                                                 */
 
-void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f);
-void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f);
-void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines);
+int bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
+void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
+int bttv_vbi_set_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
 
 extern struct videobuf_queue_ops bttv_vbi_qops;
 
@@ -233,7 +284,6 @@
 #define d2printk if (bttv_debug >= 2) printk
 
 #define BTTV_MAX_FBUF   0x208000
-#define VBIBUF_SIZE     (2048*VBI_MAXLINES*2)
 #define BTTV_TIMEOUT    (HZ/2) /* 0.5 seconds */
 #define BTTV_FREE_IDLE  (HZ)   /* one second */
 
@@ -308,13 +358,12 @@
 
 	/* infrared remote */
 	int has_remote;
-	struct bttv_ir *remote;
+	struct card_ir *remote;
 
 	/* locking */
 	spinlock_t s_lock;
 	struct mutex lock;
 	int resources;
-	struct mutex reslock;
 #ifdef VIDIOC_G_PRIORITY
 	struct v4l2_prio_state prio;
 #endif
@@ -384,6 +433,21 @@
 
 	unsigned int users;
 	struct bttv_fh init;
+
+	/* Default (0) and current (1) video capturing and overlay
+	   cropping parameters in bttv_tvnorm.cropcap units. Protected
+	   by bttv.lock. */
+	struct bttv_crop crop[2];
+
+	/* Earliest possible start of video capturing in
+	   bttv_tvnorm.cropcap line units. Set by check_alloc_btres()
+	   and free_btres(). Protected by bttv.lock. */
+	__s32			vbi_end;
+
+	/* Latest possible end of VBI capturing (= crop[x].rect.top when
+	   VIDEO_RESOURCES are locked). Set by check_alloc_btres()
+	   and free_btres(). Protected by bttv.lock. */
+	__s32			crop_start;
 };
 
 /* our devices */
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 7d0b6e5..7d47cbe 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -871,7 +871,7 @@
 	return len;
 }
 
-static struct file_operations qcam_fops = {
+static const struct file_operations qcam_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index a3989bd..925ff17 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -684,7 +684,7 @@
 }
 
 /* video device template */
-static struct file_operations qcam_fops = {
+static const struct file_operations qcam_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 3083c80..682dc7c 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -549,6 +549,7 @@
 	adap->client_unregister = cafe_smbus_detach;
 	adap->algo = &cafe_smbus_algo;
 	strcpy(adap->name, "cafe_ccic");
+	adap->dev.parent = &cam->pdev->dev;
 	i2c_set_adapdata(adap, cam);
 	ret = i2c_add_adapter(adap);
 	if (ret)
@@ -1194,7 +1195,7 @@
 		struct v4l2_requestbuffers *req)
 {
 	struct cafe_camera *cam = filp->private_data;
-	int ret;
+	int ret = 0;  /* Silence warning */
 
 	/*
 	 * Make sure it's something we can do.  User pointers could be
@@ -1715,7 +1716,7 @@
  * clone it for specific real devices.
  */
 
-static struct file_operations cafe_v4l_fops = {
+static const struct file_operations cafe_v4l_fops = {
 	.owner = THIS_MODULE,
 	.open = cafe_v4l_open,
 	.release = cafe_v4l_release,
@@ -1969,7 +1970,7 @@
 			s - cafe_debug_buf);
 }
 
-static struct file_operations cafe_dfs_reg_ops = {
+static const struct file_operations cafe_dfs_reg_ops = {
 	.owner = THIS_MODULE,
 	.read = cafe_dfs_read_regs,
 	.open = cafe_dfs_open
@@ -1995,7 +1996,7 @@
 			s - cafe_debug_buf);
 }
 
-static struct file_operations cafe_dfs_cam_ops = {
+static const struct file_operations cafe_dfs_cam_ops = {
 	.owner = THIS_MODULE,
 	.read = cafe_dfs_read_cam,
 	.open = cafe_dfs_open
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 3b31a0d..78c9699 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -1350,13 +1350,13 @@
 
 static void create_proc_cpia_cam(struct cam_data *cam)
 {
-	char name[7];
+	char name[5 + 1 + 10 + 1];
 	struct proc_dir_entry *ent;
 
 	if (!cpia_proc_root || !cam)
 		return;
 
-	sprintf(name, "video%d", cam->vdev.minor);
+	snprintf(name, sizeof(name), "video%d", cam->vdev.minor);
 
 	ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root);
 	if (!ent)
@@ -1376,12 +1376,12 @@
 
 static void destroy_proc_cpia_cam(struct cam_data *cam)
 {
-	char name[7];
+	char name[5 + 1 + 10 + 1];
 
 	if (!cam || !cam->proc_entry)
 		return;
 
-	sprintf(name, "video%d", cam->vdev.minor);
+	snprintf(name, sizeof(name), "video%d", cam->vdev.minor);
 	remove_proc_entry(name, cpia_proc_root);
 	cam->proc_entry = NULL;
 }
@@ -3153,8 +3153,7 @@
 
 static void put_cam(struct cpia_camera_ops* ops)
 {
-	if (ops->owner)
-		module_put(ops->owner);
+	module_put(ops->owner);
 }
 
 /* ------------------------- V4L interface --------------------- */
@@ -3791,7 +3790,7 @@
 	return 0;
 }
 
-static struct file_operations cpia_fops = {
+static const struct file_operations cpia_fops = {
 	.owner		= THIS_MODULE,
 	.open		= cpia_open,
 	.release       	= cpia_close,
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index d09f499..1bda7ad 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -1924,7 +1924,7 @@
 /***
  * The v4l video device structure initialized for this device
  ***/
-static struct file_operations fops_template = {
+static const struct file_operations fops_template = {
 	.owner		= THIS_MODULE,
 	.open		= cpia2_open,
 	.release	= cpia2_close,
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index 2f5ca71..d60cd5e 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -56,7 +56,6 @@
 	V4L2_CID_MPEG_VIDEO_B_FRAMES,
 	V4L2_CID_MPEG_VIDEO_GOP_SIZE,
 	V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
-	V4L2_CID_MPEG_VIDEO_PULLDOWN,
 	V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
 	V4L2_CID_MPEG_VIDEO_BITRATE,
 	V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
@@ -118,9 +117,6 @@
 	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
 		ctrl->value = params->video_gop_closure;
 		break;
-	case V4L2_CID_MPEG_VIDEO_PULLDOWN:
-		ctrl->value = params->video_pulldown;
-		break;
 	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
 		ctrl->value = params->video_bitrate_mode;
 		break;
@@ -231,9 +227,6 @@
 	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
 		params->video_gop_closure = ctrl->value;
 		break;
-	case V4L2_CID_MPEG_VIDEO_PULLDOWN:
-		params->video_pulldown = ctrl->value;
-		break;
 	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
 		/* MPEG-1 only allows CBR */
 		if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
@@ -679,7 +672,6 @@
 	.video_b_frames = 2,
 	.video_gop_size = 12,
 	.video_gop_closure = 1,
-	.video_pulldown = 0,
 	.video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
 	.video_bitrate = 6000000,
 	.video_bitrate_peak = 8000000,
@@ -783,10 +775,6 @@
 		err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
 		if (err) return err;
 	}
-	if (old == NULL || old->video_pulldown != new->video_pulldown) {
-		err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown);
-		if (err) return err;
-	}
 	if (old == NULL || old->audio_properties != new->audio_properties) {
 		err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
 		if (err) return err;
@@ -888,11 +876,10 @@
 		printk(", Peak %d", p->video_bitrate_peak);
 	}
 	printk("\n");
-	printk(KERN_INFO "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n",
+	printk(KERN_INFO "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
 		prefix,
 		p->video_gop_size, p->video_b_frames,
-		p->video_gop_closure ? "" : "No ",
-		p->video_pulldown ? "" : "No ");
+		p->video_gop_closure ? "" : "No ");
 	if (p->video_temporal_decimation) {
 		printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
 			prefix, p->video_temporal_decimation);
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 7bb7589..cc535ca 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -628,17 +628,8 @@
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	/* ioctls to allow direct access to the
 	 * cx25840 registers for testing */
-	case VIDIOC_INT_G_REGISTER:
-	{
-		struct v4l2_register *reg = arg;
-
-		if (reg->i2c_id != I2C_DRIVERID_CX25840)
-			return -EINVAL;
-		reg->val = cx25840_read(client, reg->reg & 0x0fff);
-		break;
-	}
-
-	case VIDIOC_INT_S_REGISTER:
+	case VIDIOC_DBG_G_REGISTER:
+	case VIDIOC_DBG_S_REGISTER:
 	{
 		struct v4l2_register *reg = arg;
 
@@ -646,7 +637,10 @@
 			return -EINVAL;
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);
+		if (cmd == VIDIOC_DBG_G_REGISTER)
+			reg->val = cx25840_read(client, reg->reg & 0x0fff);
+		else
+			cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);
 		break;
 	}
 #endif
@@ -893,9 +887,11 @@
 		return 0;
 	}
 
+	/* Note: revision '(device_id & 0x0f) == 2' was never built. The
+	   marking skips from 0x1 == 22 to 0x3 == 23. */
 	v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n",
 		    (device_id & 0xfff0) >> 4,
-		    (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3,
+		    (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f),
 		    address << 1, adapter->name);
 
 	i2c_set_clientdata(client, state);
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 639c3b6..532cee3 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -12,8 +12,3 @@
 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_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1
-
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 0cf0360..a1be1e2 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -6,6 +6,9 @@
  *    (c) 2004 Jelle Foks <jelle@foks.8m.com>
  *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
  *
+ *    (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *        - video_ioctl2 conversion
+ *
  *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -520,7 +523,7 @@
 
 	dev->params.width = dev->width;
 	dev->params.height = dev->height;
-	dev->params.is_50hz = (dev->core->tvnorm->id & V4L2_STD_625_50) != 0;
+	dev->params.is_50hz = (dev->core->tvnorm & V4L2_STD_625_50) != 0;
 
 	cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);
 }
@@ -710,8 +713,13 @@
 	return 0;
 }
 
-static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qmenu)
+/* ------------------------------------------------------------------ */
+/* IOCTL Handlers                                                     */
+
+static int vidioc_querymenu (struct file *file, void *priv,
+				struct v4l2_querymenu *qmenu)
 {
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
 	struct v4l2_queryctrl qctrl;
 
 	qctrl.id = qmenu->id;
@@ -719,221 +727,347 @@
 	return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id));
 }
 
-/* ------------------------------------------------------------------ */
-
-static int mpeg_do_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, void *arg)
+static int vidioc_querycap (struct file *file, void  *priv,
+					struct v4l2_capability *cap)
 {
-	struct cx8802_fh  *fh  = file->private_data;
-	struct cx8802_dev *dev = fh->dev;
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
 	struct cx88_core  *core = dev->core;
 
-	if (debug > 1)
-		v4l_print_ioctl(core->name,cmd);
-
-	switch (cmd) {
-
-	/* --- capabilities ------------------------------------------ */
-	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability *cap = arg;
-
-		memset(cap,0,sizeof(*cap));
-		strcpy(cap->driver, "cx88_blackbird");
-		strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
-		sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
-		cap->version = CX88_VERSION_CODE;
-		cap->capabilities =
-			V4L2_CAP_VIDEO_CAPTURE |
-			V4L2_CAP_READWRITE     |
-			V4L2_CAP_STREAMING     |
-			0;
-		if (UNSET != core->tuner_type)
-			cap->capabilities |= V4L2_CAP_TUNER;
-
-		return 0;
-	}
-
-	/* --- capture ioctls ---------------------------------------- */
-	case VIDIOC_ENUM_FMT:
-	{
-		struct v4l2_fmtdesc *f = arg;
-		int index;
-
-		index = f->index;
-		if (index != 0)
-			return -EINVAL;
-
-		memset(f,0,sizeof(*f));
-		f->index = index;
-		strlcpy(f->description, "MPEG", sizeof(f->description));
-		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		f->pixelformat = V4L2_PIX_FMT_MPEG;
-		return 0;
-	}
-	case VIDIOC_G_FMT:
-	{
-		struct v4l2_format *f = arg;
-
-		memset(f,0,sizeof(*f));
-		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-		f->fmt.pix.bytesperline = 0;
-		f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
-		f->fmt.pix.colorspace   = 0;
-		f->fmt.pix.width        = dev->width;
-		f->fmt.pix.height       = dev->height;
-		f->fmt.pix.field        = fh->mpegq.field;
-		dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
-			dev->width, dev->height, fh->mpegq.field );
-		return 0;
-	}
-	case VIDIOC_TRY_FMT:
-	{
-		struct v4l2_format *f = arg;
-
-		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-		f->fmt.pix.bytesperline = 0;
-		f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
-		f->fmt.pix.colorspace   = 0;
-		dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
-			dev->width, dev->height, fh->mpegq.field );
-		return 0;
-	}
-	case VIDIOC_S_FMT:
-	{
-		struct v4l2_format *f = arg;
-
-		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-		f->fmt.pix.bytesperline = 0;
-		f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
-		f->fmt.pix.colorspace   = 0;
-		dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
-			f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
-		return 0;
-	}
-
-	/* --- streaming capture ------------------------------------- */
-	case VIDIOC_REQBUFS:
-		return videobuf_reqbufs(&fh->mpegq, arg);
-
-	case VIDIOC_QUERYBUF:
-		return videobuf_querybuf(&fh->mpegq, arg);
-
-	case VIDIOC_QBUF:
-		return videobuf_qbuf(&fh->mpegq, arg);
-
-	case VIDIOC_DQBUF:
-		return videobuf_dqbuf(&fh->mpegq, arg,
-				      file->f_flags & O_NONBLOCK);
-
-	case VIDIOC_STREAMON:
-		return videobuf_streamon(&fh->mpegq);
-
-	case VIDIOC_STREAMOFF:
-		return videobuf_streamoff(&fh->mpegq);
-
-	/* --- mpeg compression -------------------------------------- */
-	case VIDIOC_G_MPEGCOMP:
-	{
-		struct v4l2_mpeg_compression *f = arg;
-
-		printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
-				    "Replace with VIDIOC_G_EXT_CTRLS!");
-		memcpy(f,&default_mpeg_params,sizeof(*f));
-		return 0;
-	}
-	case VIDIOC_S_MPEGCOMP:
-		printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
-				    "Replace with VIDIOC_S_EXT_CTRLS!");
-		return 0;
-	case VIDIOC_G_EXT_CTRLS:
-	{
-		struct v4l2_ext_controls *f = arg;
-
-		if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-			return -EINVAL;
-		return cx2341x_ext_ctrls(&dev->params, f, cmd);
-	}
-	case VIDIOC_S_EXT_CTRLS:
-	case VIDIOC_TRY_EXT_CTRLS:
-	{
-		struct v4l2_ext_controls *f = arg;
-		struct cx2341x_mpeg_params p;
-		int err;
-
-		if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-			return -EINVAL;
-		p = dev->params;
-		err = cx2341x_ext_ctrls(&p, f, cmd);
-		if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
-			err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
-			dev->params = p;
-		}
-		return err;
-	}
-	case VIDIOC_S_FREQUENCY:
-	{
-		blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
-				  BLACKBIRD_END_NOW,
-				  BLACKBIRD_MPEG_CAPTURE,
-				  BLACKBIRD_RAW_BITS_NONE);
-
-		cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
-
-		blackbird_initialize_codec(dev);
-		cx88_set_scale(dev->core, dev->width, dev->height,
-			       fh->mpegq.field);
-		return 0;
-	}
-	case VIDIOC_LOG_STATUS:
-	{
-		char name[32 + 2];
-
-		snprintf(name, sizeof(name), "%s/2", core->name);
-		printk("%s/2: ============  START LOG STATUS  ============\n",
-		       core->name);
-		cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
-		cx2341x_log_status(&dev->params, name);
-		printk("%s/2: =============  END LOG STATUS  =============\n",
-		       core->name);
-		return 0;
-	}
-	case VIDIOC_QUERYMENU:
-		return blackbird_querymenu(dev, arg);
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *c = arg;
-
-		if (blackbird_queryctrl(dev, c) == 0)
-			return 0;
-		return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
-	}
-
-	default:
-		return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
-	}
+	strcpy(cap->driver, "cx88_blackbird");
+	strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
+	sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
+	cap->version = CX88_VERSION_CODE;
+	cap->capabilities =
+		V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_READWRITE     |
+		V4L2_CAP_STREAMING;
+	if (UNSET != core->tuner_type)
+		cap->capabilities |= V4L2_CAP_TUNER;
 	return 0;
 }
 
-int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
-			unsigned int cmd, void *arg);
-unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
-
-static unsigned int mpeg_translate_ioctl(unsigned int cmd)
+static int vidioc_enum_fmt_cap (struct file *file, void  *priv,
+					struct v4l2_fmtdesc *f)
 {
-	return cmd;
+	if (f->index != 0)
+		return -EINVAL;
+
+	strlcpy(f->description, "MPEG", sizeof(f->description));
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	f->pixelformat = V4L2_PIX_FMT_MPEG;
+	return 0;
 }
 
-static int mpeg_ioctl(struct inode *inode, struct file *file,
-			unsigned int cmd, unsigned long arg)
+static int vidioc_g_fmt_cap (struct file *file, void *priv,
+					struct v4l2_format *f)
 {
-	cmd = cx88_ioctl_translator( cmd );
-	return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
+	f->fmt.pix.colorspace   = 0;
+	f->fmt.pix.width        = dev->width;
+	f->fmt.pix.height       = dev->height;
+	f->fmt.pix.field        = fh->mpegq.field;
+	dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+		dev->width, dev->height, fh->mpegq.field );
+	return 0;
 }
 
+static int vidioc_try_fmt_cap (struct file *file, void *priv,
+			struct v4l2_format *f)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
+	f->fmt.pix.colorspace   = 0;
+	dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+		dev->width, dev->height, fh->mpegq.field );
+	return 0;
+}
+
+static int vidioc_s_fmt_cap (struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+	struct cx88_core  *core = dev->core;
+
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
+	f->fmt.pix.colorspace   = 0;
+	dev->width              = f->fmt.pix.width;
+	dev->height             = f->fmt.pix.height;
+	fh->mpegq.field         = f->fmt.pix.field;
+	cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+	blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+				f->fmt.pix.height, f->fmt.pix.width);
+	dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+		f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
+	return 0;
+}
+
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_reqbufs(&fh->mpegq, p));
+}
+
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_querybuf(&fh->mpegq, p));
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_qbuf(&fh->mpegq, p));
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_dqbuf(&fh->mpegq, p,
+				file->f_flags & O_NONBLOCK));
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx8802_fh  *fh   = priv;
+	return videobuf_streamon(&fh->mpegq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx8802_fh  *fh   = priv;
+	return videobuf_streamoff(&fh->mpegq);
+}
+
+static int vidioc_g_mpegcomp (struct file *file, void *fh,
+			      struct v4l2_mpeg_compression *f)
+{
+	printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
+				"Replace with VIDIOC_G_EXT_CTRLS!");
+	memcpy(f,&default_mpeg_params,sizeof(*f));
+	return 0;
+}
+
+static int vidioc_s_mpegcomp (struct file *file, void *fh,
+			      struct v4l2_mpeg_compression *f)
+{
+	printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
+				"Replace with VIDIOC_S_EXT_CTRLS!");
+	return 0;
+}
+
+static int vidioc_g_ext_ctrls (struct file *file, void *priv,
+			       struct v4l2_ext_controls *f)
+{
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+
+	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+		return -EINVAL;
+	return cx2341x_ext_ctrls(&dev->params, f, VIDIOC_G_EXT_CTRLS);
+}
+
+static int vidioc_s_ext_ctrls (struct file *file, void *priv,
+			       struct v4l2_ext_controls *f)
+{
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+	struct cx2341x_mpeg_params p;
+	int err;
+
+	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+		return -EINVAL;
+	p = dev->params;
+	err = cx2341x_ext_ctrls(&p, f, VIDIOC_S_EXT_CTRLS);
+	if (!err) {
+		err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
+		dev->params = p;
+	}
+	return err;
+}
+
+static int vidioc_try_ext_ctrls (struct file *file, void *priv,
+			       struct v4l2_ext_controls *f)
+{
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+	struct cx2341x_mpeg_params p;
+	int err;
+
+	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+		return -EINVAL;
+	p = dev->params;
+	err = cx2341x_ext_ctrls(&p, f, VIDIOC_TRY_EXT_CTRLS);
+
+	return err;
+}
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+	struct cx88_core  *core = dev->core;
+
+	blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+				BLACKBIRD_END_NOW,
+				BLACKBIRD_MPEG_CAPTURE,
+				BLACKBIRD_RAW_BITS_NONE);
+	cx88_set_freq (core,f);
+	blackbird_initialize_codec(dev);
+	cx88_set_scale(dev->core, dev->width, dev->height,
+			fh->mpegq.field);
+	return 0;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+	struct cx88_core  *core = dev->core;
+	char name[32 + 2];
+
+	snprintf(name, sizeof(name), "%s/2", core->name);
+	printk("%s/2: ============  START LOG STATUS  ============\n",
+		core->name);
+	cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
+	cx2341x_log_status(&dev->params, name);
+	printk("%s/2: =============  END LOG STATUS  =============\n",
+		core->name);
+	return 0;
+}
+
+static int vidioc_queryctrl (struct file *file, void *priv,
+				struct v4l2_queryctrl *qctrl)
+{
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+
+	if (blackbird_queryctrl(dev, qctrl) == 0)
+		return 0;
+
+	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+	if (unlikely(qctrl->id == 0))
+		return -EINVAL;
+	return cx8800_ctrl_query(qctrl);
+}
+
+static int vidioc_enum_input (struct file *file, void *priv,
+				struct v4l2_input *i)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+	return cx88_enum_input (core,i);
+}
+
+static int vidioc_g_ctrl (struct file *file, void *priv,
+				struct v4l2_control *ctl)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+	return
+		cx88_get_control(core,ctl);
+}
+
+static int vidioc_s_ctrl (struct file *file, void *priv,
+				struct v4l2_control *ctl)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+	return
+		cx88_set_control(core,ctl);
+}
+
+static int vidioc_g_frequency (struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx88_core  *core = fh->dev->core;
+
+	if (unlikely(UNSET == core->tuner_type))
+		return -EINVAL;
+
+	f->type = V4L2_TUNER_ANALOG_TV;
+	f->frequency = core->freq;
+	cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
+
+	return 0;
+}
+
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+	*i = core->input;
+	return 0;
+}
+
+static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+	if (i >= 4)
+		return -EINVAL;
+
+	mutex_lock(&core->lock);
+	cx88_newstation(core);
+	cx88_video_mux(core,i);
+	mutex_unlock(&core->lock);
+	return 0;
+}
+
+static int vidioc_g_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+	u32 reg;
+
+	if (unlikely(UNSET == core->tuner_type))
+		return -EINVAL;
+
+	strcpy(t->name, "Television");
+	t->type       = V4L2_TUNER_ANALOG_TV;
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->rangehigh  = 0xffffffffUL;
+
+	cx88_get_stereo(core ,t);
+	reg = cx_read(MO_DEVICE_STATUS);
+	t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
+	return 0;
+}
+
+static int vidioc_s_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+	if (UNSET == core->tuner_type)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	cx88_set_stereo(core, t->audmode, 1);
+	return 0;
+}
+
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+	mutex_lock(&core->lock);
+	cx88_set_tvnorm(core,*id);
+	mutex_unlock(&core->lock);
+	return 0;
+}
+
+/* FIXME: cx88_ioctl_hook not implemented */
+
 static int mpeg_open(struct inode *inode, struct file *file)
 {
 	int minor = iminor(inode);
@@ -1051,7 +1185,7 @@
 	return videobuf_mmap_mapper(&fh->mpegq, vma);
 }
 
-static struct file_operations mpeg_fops =
+static const struct file_operations mpeg_fops =
 {
 	.owner	       = THIS_MODULE,
 	.open	       = mpeg_open,
@@ -1059,17 +1193,47 @@
 	.read	       = mpeg_read,
 	.poll          = mpeg_poll,
 	.mmap	       = mpeg_mmap,
-	.ioctl	       = mpeg_ioctl,
+	.ioctl	       = video_ioctl2,
 	.llseek        = no_llseek,
 };
 
 static struct video_device cx8802_mpeg_template =
 {
-	.name          = "cx8802",
-	.type          = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,
-	.hardware      = 0,
-	.fops          = &mpeg_fops,
-	.minor         = -1,
+	.name                 = "cx8802",
+	.type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,
+	.fops                 = &mpeg_fops,
+	.minor                = -1,
+	.vidioc_querymenu     = vidioc_querymenu,
+	.vidioc_querycap      = vidioc_querycap,
+	.vidioc_enum_fmt_cap  = vidioc_enum_fmt_cap,
+	.vidioc_g_fmt_cap     = vidioc_g_fmt_cap,
+	.vidioc_try_fmt_cap   = vidioc_try_fmt_cap,
+	.vidioc_s_fmt_cap     = vidioc_s_fmt_cap,
+	.vidioc_reqbufs       = vidioc_reqbufs,
+	.vidioc_querybuf      = vidioc_querybuf,
+	.vidioc_qbuf          = vidioc_qbuf,
+	.vidioc_dqbuf         = vidioc_dqbuf,
+	.vidioc_streamon      = vidioc_streamon,
+	.vidioc_streamoff     = vidioc_streamoff,
+	.vidioc_g_mpegcomp    = vidioc_g_mpegcomp,
+	.vidioc_s_mpegcomp    = vidioc_s_mpegcomp,
+	.vidioc_g_ext_ctrls   = vidioc_g_ext_ctrls,
+	.vidioc_s_ext_ctrls   = vidioc_s_ext_ctrls,
+	.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
+	.vidioc_s_frequency   = vidioc_s_frequency,
+	.vidioc_log_status    = vidioc_log_status,
+	.vidioc_queryctrl     = vidioc_queryctrl,
+	.vidioc_enum_input    = vidioc_enum_input,
+	.vidioc_g_ctrl        = vidioc_g_ctrl,
+	.vidioc_s_ctrl        = vidioc_s_ctrl,
+	.vidioc_g_frequency   = vidioc_g_frequency,
+	.vidioc_g_input       = vidioc_g_input,
+	.vidioc_s_input       = vidioc_s_input,
+	.vidioc_g_tuner       = vidioc_g_tuner,
+	.vidioc_s_tuner       = vidioc_s_tuner,
+	.vidioc_s_std         = vidioc_s_std,
+	.tvnorms              = CX88_NORMS,
+       .current_norm         = V4L2_STD_NTSC_M,
 };
 
 /* ------------------------------------------------------------------ */
@@ -1164,7 +1328,9 @@
 	cx2341x_fill_defaults(&dev->params);
 	dev->params.port = CX2341X_PORT_STREAMING;
 
-	if (core->tvnorm->id & V4L2_STD_525_60) {
+	cx8802_mpeg_template.current_norm = core->tvnorm;
+
+	if (core->tvnorm & V4L2_STD_525_60) {
 		dev->height = 480;
 	} else {
 		dev->height = 576;
@@ -1178,6 +1344,11 @@
 	blackbird_register_video(dev);
 
 	/* initial device configuration: needed ? */
+	mutex_lock(&dev->core->lock);
+//	init_controls(core);
+	cx88_set_tvnorm(core,core->tvnorm);
+	cx88_video_mux(core,0);
+	mutex_unlock(&dev->core->lock);
 
 	return 0;
 
@@ -1212,8 +1383,6 @@
 	printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
 	       SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
 #endif
-	cx88_ioctl_hook = mpeg_do_ioctl;
-	cx88_ioctl_translator = mpeg_translate_ioctl;
 	return cx8802_register_driver(&cx8802_blackbird_driver);
 }
 
@@ -1225,8 +1394,8 @@
 module_init(blackbird_init);
 module_exit(blackbird_fini);
 
-EXPORT_SYMBOL(cx88_ioctl_hook);
-EXPORT_SYMBOL(cx88_ioctl_translator);
+module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [video]");
 
 /* ----------------------------------------------------------- */
 /*
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 434b78a..65e9d809 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -764,6 +764,12 @@
 		.input          = {{
 			.type   = CX88_VMUX_DVB,
 			.vmux   = 0,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 2,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
 		}},
 		.mpeg           = CX88_MPEG_DVB,
 	},
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 1899736..d86813b 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -5,6 +5,11 @@
  *
  * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
+ * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *     - Multituner support
+ *     - video_ioctl2 conversion
+ *     - PAL/M fixes
+ *
  *  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
@@ -631,30 +636,30 @@
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int inline norm_swidth(struct cx88_tvnorm *norm)
+static unsigned int inline norm_swidth(v4l2_std_id norm)
 {
-	return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
+	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
 }
 
-static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm)
+static unsigned int inline norm_hdelay(v4l2_std_id norm)
 {
-	return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
+	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
 }
 
-static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
+static unsigned int inline norm_vdelay(v4l2_std_id norm)
 {
-	return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18;
+	return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
 }
 
-static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
+static unsigned int inline norm_fsc8(v4l2_std_id norm)
 {
-	if (norm->id & V4L2_STD_PAL_M)
+	if (norm & V4L2_STD_PAL_M)
 		return 28604892;      // 3.575611 MHz
 
-	if (norm->id & (V4L2_STD_PAL_Nc))
+	if (norm & (V4L2_STD_PAL_Nc))
 		return 28656448;      // 3.582056 MHz
 
-	if (norm->id & V4L2_STD_NTSC) // All NTSC/M and variants
+	if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
 		return 28636360;      // 3.57954545 MHz +/- 10 Hz
 
 	/* SECAM have also different sub carrier for chroma,
@@ -666,20 +671,20 @@
 	return 35468950;      // 4.43361875 MHz +/- 5 Hz
 }
 
-static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
+static unsigned int inline norm_htotal(v4l2_std_id norm)
 {
 
 	unsigned int fsc4=norm_fsc8(norm)/2;
 
 	/* returns 4*FSC / vtotal / frames per seconds */
-	return (norm->id & V4L2_STD_625_50) ?
+	return (norm & V4L2_STD_625_50) ?
 				((fsc4+312)/625+12)/25 :
 				((fsc4+262)/525*1001+15000)/30000;
 }
 
-static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
+static unsigned int inline norm_vbipack(v4l2_std_id norm)
 {
-	return (norm->id & V4L2_STD_625_50) ? 511 : 400;
+	return (norm & V4L2_STD_625_50) ? 511 : 400;
 }
 
 int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
@@ -692,7 +697,7 @@
 	dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
 		V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
 		V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
-		core->tvnorm->name);
+		v4l2_norm_to_name(core->tvnorm));
 	if (!V4L2_FIELD_HAS_BOTH(field))
 		height *= 2;
 
@@ -729,7 +734,7 @@
 	// setup filters
 	value = 0;
 	value |= (1 << 19);        // CFILT (default)
-	if (core->tvnorm->id & V4L2_STD_SECAM) {
+	if (core->tvnorm & V4L2_STD_SECAM) {
 		value |= (1 << 15);
 		value |= (1 << 16);
 	}
@@ -826,36 +831,36 @@
 
 static int set_tvaudio(struct cx88_core *core)
 {
-	struct cx88_tvnorm *norm = core->tvnorm;
+	v4l2_std_id norm = core->tvnorm;
 
 	if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
 		return 0;
 
-	if (V4L2_STD_PAL_BG & norm->id) {
+	if (V4L2_STD_PAL_BG & norm) {
 		core->tvaudio = WW_BG;
 
-	} else if (V4L2_STD_PAL_DK & norm->id) {
+	} else if (V4L2_STD_PAL_DK & norm) {
 		core->tvaudio = WW_DK;
 
-	} else if (V4L2_STD_PAL_I & norm->id) {
+	} else if (V4L2_STD_PAL_I & norm) {
 		core->tvaudio = WW_I;
 
-	} else if (V4L2_STD_SECAM_L & norm->id) {
+	} else if (V4L2_STD_SECAM_L & norm) {
 		core->tvaudio = WW_L;
 
-	} else if (V4L2_STD_SECAM_DK & norm->id) {
+	} else if (V4L2_STD_SECAM_DK & norm) {
 		core->tvaudio = WW_DK;
 
-	} else if ((V4L2_STD_NTSC_M & norm->id) ||
-		   (V4L2_STD_PAL_M  & norm->id)) {
+	} else if ((V4L2_STD_NTSC_M & norm) ||
+		   (V4L2_STD_PAL_M  & norm)) {
 		core->tvaudio = WW_BTSC;
 
-	} else if (V4L2_STD_NTSC_M_JP & norm->id) {
+	} else if (V4L2_STD_NTSC_M_JP & norm) {
 		core->tvaudio = WW_EIAJ;
 
 	} else {
 		printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
-		       core->name, norm->name);
+		       core->name, v4l2_norm_to_name(core->tvnorm));
 		core->tvaudio = 0;
 		return 0;
 	}
@@ -874,7 +879,7 @@
 
 
 
-int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
+int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
 {
 	u32 fsc8;
 	u32 adc_clock;
@@ -882,6 +887,7 @@
 	u32 step_db,step_dr;
 	u64 tmp64;
 	u32 bdelay,agcdelay,htotal;
+	u32 cxiformat, cxoformat;
 
 	core->tvnorm = norm;
 	fsc8       = norm_fsc8(norm);
@@ -890,23 +896,51 @@
 	step_db    = fsc8;
 	step_dr    = fsc8;
 
-	if (norm->id & V4L2_STD_SECAM) {
+	if (norm & V4L2_STD_NTSC_M_JP) {
+		cxiformat = VideoFormatNTSCJapan;
+		cxoformat = 0x181f0008;
+	} else if (norm & V4L2_STD_NTSC_443) {
+		cxiformat = VideoFormatNTSC443;
+		cxoformat = 0x181f0008;
+	} else if (norm & V4L2_STD_PAL_M) {
+		cxiformat = VideoFormatPALM;
+		cxoformat = 0x1c1f0008;
+	} else if (norm & V4L2_STD_PAL_N) {
+		cxiformat = VideoFormatPALN;
+		cxoformat = 0x1c1f0008;
+	} else if (norm & V4L2_STD_PAL_Nc) {
+		cxiformat = VideoFormatPALNC;
+		cxoformat = 0x1c1f0008;
+	} else if (norm & V4L2_STD_PAL_60) {
+		cxiformat = VideoFormatPAL60;
+		cxoformat = 0x181f0008;
+	} else if (norm & V4L2_STD_NTSC) {
+		cxiformat = VideoFormatNTSC;
+		cxoformat = 0x181f0008;
+	} else if (norm & V4L2_STD_SECAM) {
 		step_db = 4250000 * 8;
 		step_dr = 4406250 * 8;
+
+		cxiformat = VideoFormatSECAM;
+		cxoformat = 0x181f0008;
+	} else { /* PAL */
+		cxiformat = VideoFormatPAL;
+		cxoformat = 0x181f0008;
 	}
 
 	dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
-		norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr);
+		v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
+		step_db, step_dr);
 	set_pll(core,2,vdec_clock);
 
 	dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
-		norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
-	cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat);
+		cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
+	cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat);
 
 	// FIXME: as-is from DScaler
 	dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
-		norm->cxoformat, cx_read(MO_OUTPUT_FORMAT));
-	cx_write(MO_OUTPUT_FORMAT, norm->cxoformat);
+		cxoformat, cx_read(MO_OUTPUT_FORMAT));
+	cx_write(MO_OUTPUT_FORMAT, cxoformat);
 
 	// MO_SCONV_REG = adc clock / video dec clock * 2^17
 	tmp64  = adc_clock * (u64)(1 << 17);
@@ -955,7 +989,7 @@
 	set_tvaudio(core);
 
 	// tell i2c chips
-	cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id);
+	cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm);
 
 	// done
 	return 0;
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 8b20335..4f55602 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -35,7 +35,7 @@
 
 #include "mt352.h"
 #include "mt352_priv.h"
-#ifdef HAVE_VP3054_I2C
+#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
 # include "cx88-vp3054-i2c.h"
 #endif
 #include "zl10353.h"
@@ -200,7 +200,7 @@
 	.demod_init    = dvico_dual_demod_init,
 };
 
-#ifdef HAVE_VP3054_I2C
+#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
 static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
 {
 	static u8 clock_config []  = { 0x89, 0x38, 0x38 };
@@ -543,7 +543,7 @@
 		}
 		break;
 	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
-#ifdef HAVE_VP3054_I2C
+#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
 		dev->core->pll_addr = 0x61;
 		dev->core->pll_desc = &dvb_pll_fmd1216me;
 		dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
@@ -793,7 +793,7 @@
 	if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB))
 		goto fail_core;
 
-#ifdef HAVE_VP3054_I2C
+#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
 	err = vp3054_i2c_probe(dev);
 	if (0 != err)
 		goto fail_core;
@@ -822,7 +822,7 @@
 	/* dvb */
 	videobuf_dvb_unregister(&dev->dvb);
 
-#ifdef HAVE_VP3054_I2C
+#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
 	vp3054_i2c_remove(dev);
 #endif
 
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 88af23a..9830d5c 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -145,6 +145,7 @@
 	if (0 != core->i2c_rc)
 		return;
 
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
 	if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) {
 		if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
 			core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
@@ -154,6 +155,7 @@
 		if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
 			core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0);
 	} else
+#endif
 		i2c_clients_command(&core->i2c_adap, cmd, arg);
 }
 
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 2bd84d3..97ef421 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -46,7 +46,6 @@
 #include <linux/pci.h>
 #include <linux/signal.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/vmalloc.h>
@@ -798,55 +797,6 @@
        Add some code here later.
 */
 
-# if 0
-	t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
-	    V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
-	t->rxsubchans = V4L2_TUNER_SUB_MONO;
-	t->audmode = V4L2_TUNER_MODE_MONO;
-
-	switch (core->tvaudio) {
-	case WW_BTSC:
-		t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP;
-		t->rxsubchans = V4L2_TUNER_SUB_STEREO;
-		if (1 == pilot) {
-			/* SAP */
-			t->rxsubchans |= V4L2_TUNER_SUB_SAP;
-		}
-		break;
-	case WW_A2_BG:
-	case WW_A2_DK:
-	case WW_A2_M:
-		if (1 == pilot) {
-			/* stereo */
-			t->rxsubchans =
-			    V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-			if (0 == mode)
-				t->audmode = V4L2_TUNER_MODE_STEREO;
-		}
-		if (2 == pilot) {
-			/* dual language -- FIXME */
-			t->rxsubchans =
-			    V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-			t->audmode = V4L2_TUNER_MODE_LANG1;
-		}
-		break;
-	case WW_NICAM_BGDKL:
-		if (0 == mode) {
-			t->audmode = V4L2_TUNER_MODE_STEREO;
-			t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
-		}
-		break;
-	case WW_SYSTEM_L_AM:
-		if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
-			t->audmode = V4L2_TUNER_MODE_STEREO;
-			t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
-		}
-		break;
-	default:
-		/* nothing */
-		break;
-	}
-# endif
 	return;
 }
 
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index aa2a697..86c1cf8 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -21,9 +21,11 @@
 
 /* ------------------------------------------------------------------ */
 
-void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f)
+int cx8800_vbi_fmt (struct file *file, void *priv,
+					struct v4l2_format *f)
 {
-	memset(&f->fmt.vbi,0,sizeof(f->fmt.vbi));
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev  = fh->dev;
 
 	f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
 	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
@@ -31,18 +33,19 @@
 	f->fmt.vbi.count[0] = VBI_LINE_COUNT;
 	f->fmt.vbi.count[1] = VBI_LINE_COUNT;
 
-	if (dev->core->tvnorm->id & V4L2_STD_525_60) {
+	if (dev->core->tvnorm & V4L2_STD_525_60) {
 		/* ntsc */
 		f->fmt.vbi.sampling_rate = 28636363;
 		f->fmt.vbi.start[0] = 10;
 		f->fmt.vbi.start[1] = 273;
 
-	} else if (dev->core->tvnorm->id & V4L2_STD_625_50) {
+	} else if (dev->core->tvnorm & V4L2_STD_625_50) {
 		/* pal */
 		f->fmt.vbi.sampling_rate = 35468950;
 		f->fmt.vbi.start[0] = 7 -1;
 		f->fmt.vbi.start[1] = 319 -1;
 	}
+	return 0;
 }
 
 static int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 8613378..a97be1b 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1,3 +1,4 @@
+
 /*
  *
  * device driver for Conexant 2388x based TV cards
@@ -5,6 +6,11 @@
  *
  * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
+ * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *	- Multituner support
+ *	- video_ioctl2 conversion
+ *	- PAL/M fixes
+ *
  *  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
@@ -80,65 +86,6 @@
 /* ------------------------------------------------------------------- */
 /* static data                                                         */
 
-static struct cx88_tvnorm tvnorms[] = {
-	{
-		.name      = "NTSC-M",
-		.id        = V4L2_STD_NTSC_M,
-		.cxiformat = VideoFormatNTSC,
-		.cxoformat = 0x181f0008,
-	},{
-		.name      = "NTSC-JP",
-		.id        = V4L2_STD_NTSC_M_JP,
-		.cxiformat = VideoFormatNTSCJapan,
-		.cxoformat = 0x181f0008,
-	},{
-		.name      = "PAL-BG",
-		.id        = V4L2_STD_PAL_BG,
-		.cxiformat = VideoFormatPAL,
-		.cxoformat = 0x181f0008,
-	},{
-		.name      = "PAL-DK",
-		.id        = V4L2_STD_PAL_DK,
-		.cxiformat = VideoFormatPAL,
-		.cxoformat = 0x181f0008,
-	},{
-		.name      = "PAL-I",
-		.id        = V4L2_STD_PAL_I,
-		.cxiformat = VideoFormatPAL,
-		.cxoformat = 0x181f0008,
-	},{
-		.name      = "PAL-M",
-		.id        = V4L2_STD_PAL_M,
-		.cxiformat = VideoFormatPALM,
-		.cxoformat = 0x1c1f0008,
-	},{
-		.name      = "PAL-N",
-		.id        = V4L2_STD_PAL_N,
-		.cxiformat = VideoFormatPALN,
-		.cxoformat = 0x1c1f0008,
-	},{
-		.name      = "PAL-Nc",
-		.id        = V4L2_STD_PAL_Nc,
-		.cxiformat = VideoFormatPALNC,
-		.cxoformat = 0x1c1f0008,
-	},{
-		.name      = "PAL-60",
-		.id        = V4L2_STD_PAL_60,
-		.cxiformat = VideoFormatPAL60,
-		.cxoformat = 0x181f0008,
-	},{
-		.name      = "SECAM-L",
-		.id        = V4L2_STD_SECAM_L,
-		.cxiformat = VideoFormatSECAM,
-		.cxoformat = 0x181f0008,
-	},{
-		.name      = "SECAM-DK",
-		.id        = V4L2_STD_SECAM_DK,
-		.cxiformat = VideoFormatSECAM,
-		.cxoformat = 0x181f0008,
-	}
-};
-
 static struct cx8800_fmt formats[] = {
 	{
 		.name     = "8 bpp, gray",
@@ -364,14 +311,6 @@
 }
 EXPORT_SYMBOL(cx8800_ctrl_query);
 
-static int cx88_queryctrl(struct v4l2_queryctrl *qctrl)
-{
-	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
-	if (qctrl->id == 0)
-		return -EINVAL;
-	return cx8800_ctrl_query(qctrl);
-}
-
 /* ------------------------------------------------------------------- */
 /* resource management                                                 */
 
@@ -424,8 +363,7 @@
 
 /* ------------------------------------------------------------------ */
 
-/* static int video_mux(struct cx8800_dev *dev, unsigned int input) */
-static int video_mux(struct cx88_core *core, unsigned int input)
+int cx88_video_mux(struct cx88_core *core, unsigned int input)
 {
 	/* struct cx88_core *core = dev->core; */
 
@@ -464,6 +402,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL(cx88_video_mux);
 
 /* ------------------------------------------------------------------ */
 
@@ -944,19 +883,18 @@
 }
 
 /* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
 
-/* static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
-static int get_control(struct cx88_core *core, struct v4l2_control *ctl)
+int cx88_get_control (struct cx88_core  *core, struct v4l2_control *ctl)
 {
-	/* struct cx88_core *core = dev->core; */
-	struct cx88_ctrl *c = NULL;
+	struct cx88_ctrl  *c    = NULL;
 	u32 value;
 	int i;
 
 	for (i = 0; i < CX8800_CTLS; i++)
 		if (cx8800_ctls[i].v.id == ctl->id)
 			c = &cx8800_ctls[i];
-	if (NULL == c)
+	if (unlikely(NULL == c))
 		return -EINVAL;
 
 	value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg);
@@ -977,20 +915,20 @@
 				value,c->mask, c->sreg ? " [shadowed]" : "");
 	return 0;
 }
+EXPORT_SYMBOL(cx88_get_control);
 
-/* static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
-static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
+int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
 {
-	/* struct cx88_core *core = dev->core; */
 	struct cx88_ctrl *c = NULL;
 	u32 value,mask;
 	int i;
+
 	for (i = 0; i < CX8800_CTLS; i++) {
 		if (cx8800_ctls[i].v.id == ctl->id) {
 			c = &cx8800_ctls[i];
 		}
 	}
-	if (NULL == c)
+	if (unlikely(NULL == c))
 		return -EINVAL;
 
 	if (ctl->value < c->v.minimum)
@@ -1010,7 +948,7 @@
 
 		value = ((ctl->value - c->off) << c->shift) & c->mask;
 
-		if (core->tvnorm->id & V4L2_STD_SECAM) {
+		if (core->tvnorm & V4L2_STD_SECAM) {
 			/* For SECAM, both U and V sat should be equal */
 			value=value<<8|value;
 		} else {
@@ -1033,6 +971,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL(cx88_set_control);
 
 static void init_controls(struct cx88_core *core)
 {
@@ -1042,648 +981,531 @@
 	for (i = 0; i < CX8800_CTLS; i++) {
 		ctrl.id=cx8800_ctls[i].v.id;
 		ctrl.value=cx8800_ctls[i].v.default_value;
-		set_control(core, &ctrl);
+
+		cx88_set_control(core, &ctrl);
 	}
 }
 
 /* ------------------------------------------------------------------ */
+/* VIDEO IOCTLS                                                       */
 
-static int cx8800_g_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
+static int vidioc_g_fmt_cap (struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct cx8800_fh  *fh   = priv;
+
+	f->fmt.pix.width        = fh->width;
+	f->fmt.pix.height       = fh->height;
+	f->fmt.pix.field        = fh->vidq.field;
+	f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+	f->fmt.pix.bytesperline =
+		(f->fmt.pix.width * fh->fmt->depth) >> 3;
+	f->fmt.pix.sizeimage =
+		f->fmt.pix.height * f->fmt.pix.bytesperline;
+	return 0;
+}
+
+static int vidioc_try_fmt_cap (struct file *file, void *priv,
 			struct v4l2_format *f)
 {
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
-		f->fmt.pix.width        = fh->width;
-		f->fmt.pix.height       = fh->height;
-		f->fmt.pix.field        = fh->vidq.field;
-		f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-		f->fmt.pix.bytesperline =
-			(f->fmt.pix.width * fh->fmt->depth) >> 3;
-		f->fmt.pix.sizeimage =
-			f->fmt.pix.height * f->fmt.pix.bytesperline;
-		return 0;
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		cx8800_vbi_fmt(dev, f);
-		return 0;
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+	struct cx8800_fmt *fmt;
+	enum v4l2_field   field;
+	unsigned int      maxw, maxh;
+
+	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+
+	field = f->fmt.pix.field;
+	maxw  = norm_maxw(core->tvnorm);
+	maxh  = norm_maxh(core->tvnorm);
+
+	if (V4L2_FIELD_ANY == field) {
+		field = (f->fmt.pix.height > maxh/2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_BOTTOM;
+	}
+
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+		maxh = maxh / 2;
+		break;
+	case V4L2_FIELD_INTERLACED:
+		break;
 	default:
 		return -EINVAL;
 	}
+
+	f->fmt.pix.field = field;
+	if (f->fmt.pix.height < 32)
+		f->fmt.pix.height = 32;
+	if (f->fmt.pix.height > maxh)
+		f->fmt.pix.height = maxh;
+	if (f->fmt.pix.width < 48)
+		f->fmt.pix.width = 48;
+	if (f->fmt.pix.width > maxw)
+		f->fmt.pix.width = maxw;
+	f->fmt.pix.width &= ~0x03;
+	f->fmt.pix.bytesperline =
+		(f->fmt.pix.width * fmt->depth) >> 3;
+	f->fmt.pix.sizeimage =
+		f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
 }
 
-static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
-			  struct v4l2_format *f)
+static int vidioc_s_fmt_cap (struct file *file, void *priv,
+					struct v4l2_format *f)
 {
-	struct cx88_core *core = dev->core;
+	struct cx8800_fh  *fh   = priv;
+	int err = vidioc_try_fmt_cap (file,priv,f);
 
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-	{
-		struct cx8800_fmt *fmt;
-		enum v4l2_field field;
-		unsigned int maxw, maxh;
-
-		fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-		if (NULL == fmt)
-			return -EINVAL;
-
-		field = f->fmt.pix.field;
-		maxw  = norm_maxw(core->tvnorm);
-		maxh  = norm_maxh(core->tvnorm);
-
-		if (V4L2_FIELD_ANY == field) {
-			field = (f->fmt.pix.height > maxh/2)
-				? V4L2_FIELD_INTERLACED
-				: V4L2_FIELD_BOTTOM;
-		}
-
-		switch (field) {
-		case V4L2_FIELD_TOP:
-		case V4L2_FIELD_BOTTOM:
-			maxh = maxh / 2;
-			break;
-		case V4L2_FIELD_INTERLACED:
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		f->fmt.pix.field = field;
-		if (f->fmt.pix.height < 32)
-			f->fmt.pix.height = 32;
-		if (f->fmt.pix.height > maxh)
-			f->fmt.pix.height = maxh;
-		if (f->fmt.pix.width < 48)
-			f->fmt.pix.width = 48;
-		if (f->fmt.pix.width > maxw)
-			f->fmt.pix.width = maxw;
-		f->fmt.pix.width &= ~0x03;
-		f->fmt.pix.bytesperline =
-			(f->fmt.pix.width * fmt->depth) >> 3;
-		f->fmt.pix.sizeimage =
-			f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-		return 0;
-	}
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		cx8800_vbi_fmt(dev, f);
-		return 0;
-	default:
-		return -EINVAL;
-	}
+	if (0 != err)
+		return err;
+	fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+	fh->width      = f->fmt.pix.width;
+	fh->height     = f->fmt.pix.height;
+	fh->vidq.field = f->fmt.pix.field;
+	return 0;
 }
 
-static int cx8800_s_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
-			struct v4l2_format *f)
+static int vidioc_querycap (struct file *file, void  *priv,
+					struct v4l2_capability *cap)
 {
-	int err;
-
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		err = cx8800_try_fmt(dev,fh,f);
-		if (0 != err)
-			return err;
-
-		fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
-		fh->width      = f->fmt.pix.width;
-		fh->height     = f->fmt.pix.height;
-		fh->vidq.field = f->fmt.pix.field;
-		return 0;
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		cx8800_vbi_fmt(dev, f);
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-/*
- * This function is _not_ called directly, but from
- * video_generic_ioctl (and maybe others).  userspace
- * copying is done already, arg is a kernel pointer.
- */
-static int video_do_ioctl(struct inode *inode, struct file *file,
-			  unsigned int cmd, void *arg)
-{
-	struct cx8800_fh  *fh   = file->private_data;
-	struct cx8800_dev *dev  = fh->dev;
+	struct cx8800_dev *dev  = ((struct cx8800_fh *)priv)->dev;
 	struct cx88_core  *core = dev->core;
-	int err;
 
-	if (video_debug > 1)
-		v4l_print_ioctl(core->name,cmd);
-	switch (cmd) {
+	strcpy(cap->driver, "cx8800");
+	strlcpy(cap->card, cx88_boards[core->board].name,
+		sizeof(cap->card));
+	sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
+	cap->version = CX88_VERSION_CODE;
+	cap->capabilities =
+		V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_READWRITE     |
+		V4L2_CAP_STREAMING     |
+		V4L2_CAP_VBI_CAPTURE;
+	if (UNSET != core->tuner_type)
+		cap->capabilities |= V4L2_CAP_TUNER;
+	return 0;
+}
 
-	/* --- capabilities ------------------------------------------ */
-	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability *cap = arg;
+static int vidioc_enum_fmt_cap (struct file *file, void  *priv,
+					struct v4l2_fmtdesc *f)
+{
+	if (unlikely(f->index >= ARRAY_SIZE(formats)))
+		return -EINVAL;
 
-		memset(cap,0,sizeof(*cap));
-		strcpy(cap->driver, "cx8800");
-		strlcpy(cap->card, cx88_boards[core->board].name,
-			sizeof(cap->card));
-		sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
-		cap->version = CX88_VERSION_CODE;
-		cap->capabilities =
-			V4L2_CAP_VIDEO_CAPTURE |
-			V4L2_CAP_READWRITE     |
-			V4L2_CAP_STREAMING     |
-			V4L2_CAP_VBI_CAPTURE   |
-			0;
-		if (UNSET != core->tuner_type)
-			cap->capabilities |= V4L2_CAP_TUNER;
-		return 0;
-	}
+	strlcpy(f->description,formats[f->index].name,sizeof(f->description));
+	f->pixelformat = formats[f->index].fourcc;
 
-	/* --- capture ioctls ---------------------------------------- */
-	case VIDIOC_ENUM_FMT:
-	{
-		struct v4l2_fmtdesc *f = arg;
-		enum v4l2_buf_type type;
-		unsigned int index;
+	return 0;
+}
 
-		index = f->index;
-		type  = f->type;
-		switch (type) {
-		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-			if (index >= ARRAY_SIZE(formats))
-				return -EINVAL;
-			memset(f,0,sizeof(*f));
-			f->index = index;
-			f->type  = type;
-			strlcpy(f->description,formats[index].name,sizeof(f->description));
-			f->pixelformat = formats[index].fourcc;
-			break;
-		default:
-			return -EINVAL;
-		}
-		return 0;
-	}
-	case VIDIOC_G_FMT:
-	{
-		struct v4l2_format *f = arg;
-		return cx8800_g_fmt(dev,fh,f);
-	}
-	case VIDIOC_S_FMT:
-	{
-		struct v4l2_format *f = arg;
-		return cx8800_s_fmt(dev,fh,f);
-	}
-	case VIDIOC_TRY_FMT:
-	{
-		struct v4l2_format *f = arg;
-		return cx8800_try_fmt(dev,fh,f);
-	}
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
-	/* --- streaming capture ------------------------------------- */
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *mbuf = arg;
-		struct videobuf_queue *q;
-		struct v4l2_requestbuffers req;
-		unsigned int i;
-
-		q = get_queue(fh);
-		memset(&req,0,sizeof(req));
-		req.type   = q->type;
-		req.count  = 8;
-		req.memory = V4L2_MEMORY_MMAP;
-		err = videobuf_reqbufs(q,&req);
-		if (err < 0)
-			return err;
-		memset(mbuf,0,sizeof(*mbuf));
-		mbuf->frames = req.count;
-		mbuf->size   = 0;
-		for (i = 0; i < mbuf->frames; i++) {
-			mbuf->offsets[i]  = q->bufs[i]->boff;
-			mbuf->size       += q->bufs[i]->bsize;
-		}
-		return 0;
-	}
-#endif
-	case VIDIOC_REQBUFS:
-		return videobuf_reqbufs(get_queue(fh), arg);
-
-	case VIDIOC_QUERYBUF:
-		return videobuf_querybuf(get_queue(fh), arg);
-
-	case VIDIOC_QBUF:
-		return videobuf_qbuf(get_queue(fh), arg);
-
-	case VIDIOC_DQBUF:
-		return videobuf_dqbuf(get_queue(fh), arg,
-					file->f_flags & O_NONBLOCK);
-
-	case VIDIOC_STREAMON:
-	{
-		int res = get_ressource(fh);
-
-		if (!res_get(dev,fh,res))
-			return -EBUSY;
-		return videobuf_streamon(get_queue(fh));
-	}
-	case VIDIOC_STREAMOFF:
-	{
-		int res = get_ressource(fh);
-
-		err = videobuf_streamoff(get_queue(fh));
-		if (err < 0)
-			return err;
-		res_free(dev,fh,res);
-		return 0;
-	}
-	default:
-		return cx88_do_ioctl( inode, file, fh->radio, core, cmd, arg, video_do_ioctl );
-	}
-	return 0;
-}
-
-int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
-		  struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl)
+static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
 {
+	struct cx8800_fh           *fh   = priv;
+	struct videobuf_queue      *q;
+	struct v4l2_requestbuffers req;
+	unsigned int i;
 	int err;
 
-       if (video_debug) {
-	       if (video_debug > 1) {
-		       if (_IOC_DIR(cmd) & _IOC_WRITE)
-			       v4l_printk_ioctl_arg("cx88(w)",cmd, arg);
-		       else if (!_IOC_DIR(cmd) & _IOC_READ) {
-			       v4l_print_ioctl("cx88", cmd);
-		       }
-	       } else
-		       v4l_print_ioctl(core->name,cmd);
+	q = get_queue(fh);
+	memset(&req,0,sizeof(req));
+	req.type   = q->type;
+	req.count  = 8;
+	req.memory = V4L2_MEMORY_MMAP;
+	err = videobuf_reqbufs(q,&req);
+	if (err < 0)
+		return err;
 
-       }
-
-	switch (cmd) {
-	/* ---------- tv norms ---------- */
-	case VIDIOC_ENUMSTD:
-	{
-		struct v4l2_standard *e = arg;
-		unsigned int i;
-
-		i = e->index;
-		if (i >= ARRAY_SIZE(tvnorms))
-			return -EINVAL;
-		err = v4l2_video_std_construct(e, tvnorms[e->index].id,
-					       tvnorms[e->index].name);
-		e->index = i;
-		if (err < 0)
-			return err;
-		return 0;
-	}
-	case VIDIOC_G_STD:
-	{
-		v4l2_std_id *id = arg;
-
-		*id = core->tvnorm->id;
-		return 0;
-	}
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *id = arg;
-		unsigned int i;
-
-		for(i = 0; i < ARRAY_SIZE(tvnorms); i++)
-			if (*id & tvnorms[i].id)
-				break;
-		if (i == ARRAY_SIZE(tvnorms))
-			return -EINVAL;
-
-		mutex_lock(&core->lock);
-		cx88_set_tvnorm(core,&tvnorms[i]);
-		mutex_unlock(&core->lock);
-		return 0;
-	}
-
-	/* ------ input switching ---------- */
-	case VIDIOC_ENUMINPUT:
-	{
-		static const char *iname[] = {
-			[ CX88_VMUX_COMPOSITE1 ] = "Composite1",
-			[ CX88_VMUX_COMPOSITE2 ] = "Composite2",
-			[ CX88_VMUX_COMPOSITE3 ] = "Composite3",
-			[ CX88_VMUX_COMPOSITE4 ] = "Composite4",
-			[ CX88_VMUX_SVIDEO     ] = "S-Video",
-			[ CX88_VMUX_TELEVISION ] = "Television",
-			[ CX88_VMUX_CABLE      ] = "Cable TV",
-			[ CX88_VMUX_DVB        ] = "DVB",
-			[ CX88_VMUX_DEBUG      ] = "for debug only",
-		};
-		struct v4l2_input *i = arg;
-		unsigned int n;
-
-		n = i->index;
-		if (n >= 4)
-			return -EINVAL;
-		if (0 == INPUT(n)->type)
-			return -EINVAL;
-		memset(i,0,sizeof(*i));
-		i->index = n;
-		i->type  = V4L2_INPUT_TYPE_CAMERA;
-		strcpy(i->name,iname[INPUT(n)->type]);
-		if ((CX88_VMUX_TELEVISION == INPUT(n)->type) ||
-		    (CX88_VMUX_CABLE      == INPUT(n)->type))
-			i->type = V4L2_INPUT_TYPE_TUNER;
-		for (n = 0; n < ARRAY_SIZE(tvnorms); n++)
-			i->std |= tvnorms[n].id;
-		return 0;
-	}
-	case VIDIOC_G_INPUT:
-	{
-		unsigned int *i = arg;
-
-		*i = core->input;
-		return 0;
-	}
-	case VIDIOC_S_INPUT:
-	{
-		unsigned int *i = arg;
-
-		if (*i >= 4)
-			return -EINVAL;
-		mutex_lock(&core->lock);
-		cx88_newstation(core);
-		video_mux(core,*i);
-		mutex_unlock(&core->lock);
-		return 0;
-	}
-
-
-
-	/* --- controls ---------------------------------------------- */
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *c = arg;
-
-		return cx88_queryctrl(c);
-	}
-	case VIDIOC_G_CTRL:
-		return get_control(core,arg);
-	case VIDIOC_S_CTRL:
-		return set_control(core,arg);
-
-	/* --- tuner ioctls ------------------------------------------ */
-	case VIDIOC_G_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
-		u32 reg;
-
-		if (UNSET == core->tuner_type)
-			return -EINVAL;
-		if (0 != t->index)
-			return -EINVAL;
-
-		memset(t,0,sizeof(*t));
-		strcpy(t->name, "Television");
-		t->type       = V4L2_TUNER_ANALOG_TV;
-		t->capability = V4L2_TUNER_CAP_NORM;
-		t->rangehigh  = 0xffffffffUL;
-
-		cx88_get_stereo(core ,t);
-		reg = cx_read(MO_DEVICE_STATUS);
-		t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
-		return 0;
-	}
-	case VIDIOC_S_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
-
-		if (UNSET == core->tuner_type)
-			return -EINVAL;
-		if (0 != t->index)
-			return -EINVAL;
-		cx88_set_stereo(core, t->audmode, 1);
-		return 0;
-	}
-	case VIDIOC_G_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
-
-		memset(f,0,sizeof(*f));
-
-		if (UNSET == core->tuner_type)
-			return -EINVAL;
-
-		/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
-		f->type = radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-		f->frequency = core->freq;
-
-		cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
-
-		return 0;
-	}
-	case VIDIOC_S_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
-
-		if (UNSET == core->tuner_type)
-			return -EINVAL;
-		if (f->tuner != 0)
-			return -EINVAL;
-		if (0 == radio && f->type != V4L2_TUNER_ANALOG_TV)
-			return -EINVAL;
-		if (1 == radio && f->type != V4L2_TUNER_RADIO)
-			return -EINVAL;
-		mutex_lock(&core->lock);
-		core->freq = f->frequency;
-		cx88_newstation(core);
-		cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
-
-		/* When changing channels it is required to reset TVAUDIO */
-		msleep (10);
-		cx88_set_tvaudio(core);
-
-		mutex_unlock(&core->lock);
-		return 0;
-	}
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-	/* ioctls to allow direct acces to the cx2388x registers */
-	case VIDIOC_INT_G_REGISTER:
-	{
-		struct v4l2_register *reg = arg;
-
-		if (reg->i2c_id != 0)
-			return -EINVAL;
-		/* cx2388x has a 24-bit register space */
-		reg->val = cx_read(reg->reg&0xffffff);
-		return 0;
-	}
-	case VIDIOC_INT_S_REGISTER:
-	{
-		struct v4l2_register *reg = arg;
-
-		if (reg->i2c_id != 0)
-			return -EINVAL;
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		cx_write(reg->reg&0xffffff, reg->val);
-		return 0;
-	}
-#endif
-
-	default:
-		return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-						  driver_ioctl);
+	mbuf->frames = req.count;
+	mbuf->size   = 0;
+	for (i = 0; i < mbuf->frames; i++) {
+		mbuf->offsets[i]  = q->bufs[i]->boff;
+		mbuf->size       += q->bufs[i]->bsize;
 	}
 	return 0;
 }
+#endif
 
-static int video_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg)
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
 {
-       int retval;
-
-       retval=video_usercopy(inode, file, cmd, arg, video_do_ioctl);
-
-       if (video_debug > 1) {
-	       if (retval < 0) {
-		       v4l_print_ioctl("cx88(err)", cmd);
-		       printk(KERN_DEBUG "cx88(err): errcode=%d\n",retval);
-	       } else if (_IOC_DIR(cmd) & _IOC_READ)
-		       v4l_printk_ioctl_arg("cx88(r)",cmd, (void *)arg);
-       }
-
-       return retval;
+	struct cx8800_fh  *fh   = priv;
+	return (videobuf_reqbufs(get_queue(fh), p));
 }
 
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8800_fh  *fh   = priv;
+	return (videobuf_querybuf(get_queue(fh), p));
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8800_fh  *fh   = priv;
+	return (videobuf_qbuf(get_queue(fh), p));
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8800_fh  *fh   = priv;
+	return (videobuf_dqbuf(get_queue(fh), p,
+				file->f_flags & O_NONBLOCK));
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev  = fh->dev;
+
+	if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+		return -EINVAL;
+	if (unlikely(i != fh->type))
+		return -EINVAL;
+
+	if (unlikely(!res_get(dev,fh,get_ressource(fh))))
+		return -EBUSY;
+	return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev  = fh->dev;
+	int               err, res;
+
+	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (i != fh->type)
+		return -EINVAL;
+
+	res = get_ressource(fh);
+	err = videobuf_streamoff(get_queue(fh));
+	if (err < 0)
+		return err;
+	res_free(dev,fh,res);
+	return 0;
+}
+
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	mutex_lock(&core->lock);
+	cx88_set_tvnorm(core,*tvnorms);
+	mutex_unlock(&core->lock);
+
+	return 0;
+}
+
+/* only one input in this sample driver */
+int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i)
+{
+	static const char *iname[] = {
+		[ CX88_VMUX_COMPOSITE1 ] = "Composite1",
+		[ CX88_VMUX_COMPOSITE2 ] = "Composite2",
+		[ CX88_VMUX_COMPOSITE3 ] = "Composite3",
+		[ CX88_VMUX_COMPOSITE4 ] = "Composite4",
+		[ CX88_VMUX_SVIDEO     ] = "S-Video",
+		[ CX88_VMUX_TELEVISION ] = "Television",
+		[ CX88_VMUX_CABLE      ] = "Cable TV",
+		[ CX88_VMUX_DVB        ] = "DVB",
+		[ CX88_VMUX_DEBUG      ] = "for debug only",
+	};
+	unsigned int n;
+
+	n = i->index;
+	if (n >= 4)
+		return -EINVAL;
+	if (0 == INPUT(n)->type)
+		return -EINVAL;
+	memset(i,0,sizeof(*i));
+	i->index = n;
+	i->type  = V4L2_INPUT_TYPE_CAMERA;
+	strcpy(i->name,iname[INPUT(n)->type]);
+	if ((CX88_VMUX_TELEVISION == INPUT(n)->type) ||
+		(CX88_VMUX_CABLE      == INPUT(n)->type))
+		i->type = V4L2_INPUT_TYPE_TUNER;
+		i->std = CX88_NORMS;
+	return 0;
+}
+EXPORT_SYMBOL(cx88_enum_input);
+
+static int vidioc_enum_input (struct file *file, void *priv,
+				struct v4l2_input *i)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+	return cx88_enum_input (core,i);
+}
+
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	*i = core->input;
+	return 0;
+}
+
+static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	if (i >= 4)
+		return -EINVAL;
+
+	mutex_lock(&core->lock);
+	cx88_newstation(core);
+	cx88_video_mux(core,i);
+	mutex_unlock(&core->lock);
+	return 0;
+}
+
+
+
+static int vidioc_queryctrl (struct file *file, void *priv,
+				struct v4l2_queryctrl *qctrl)
+{
+	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+	if (unlikely(qctrl->id == 0))
+		return -EINVAL;
+	return cx8800_ctrl_query(qctrl);
+}
+
+static int vidioc_g_ctrl (struct file *file, void *priv,
+				struct v4l2_control *ctl)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+	return
+		cx88_get_control(core,ctl);
+}
+
+static int vidioc_s_ctrl (struct file *file, void *priv,
+				struct v4l2_control *ctl)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+	return
+		cx88_set_control(core,ctl);
+}
+
+static int vidioc_g_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+	u32 reg;
+
+	if (unlikely(UNSET == core->tuner_type))
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	strcpy(t->name, "Television");
+	t->type       = V4L2_TUNER_ANALOG_TV;
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->rangehigh  = 0xffffffffUL;
+
+	cx88_get_stereo(core ,t);
+	reg = cx_read(MO_DEVICE_STATUS);
+	t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
+	return 0;
+}
+
+static int vidioc_s_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	if (UNSET == core->tuner_type)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	cx88_set_stereo(core, t->audmode, 1);
+	return 0;
+}
+
+static int vidioc_g_frequency (struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct cx8800_fh  *fh   = priv;
+	struct cx88_core  *core = fh->dev->core;
+
+	if (unlikely(UNSET == core->tuner_type))
+		return -EINVAL;
+
+	/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
+	f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+	f->frequency = core->freq;
+
+	cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
+
+	return 0;
+}
+
+int cx88_set_freq (struct cx88_core  *core,
+				struct v4l2_frequency *f)
+{
+	if (unlikely(UNSET == core->tuner_type))
+		return -EINVAL;
+	if (unlikely(f->tuner != 0))
+		return -EINVAL;
+
+	mutex_lock(&core->lock);
+	core->freq = f->frequency;
+	cx88_newstation(core);
+	cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
+
+	/* When changing channels it is required to reset TVAUDIO */
+	msleep (10);
+	cx88_set_tvaudio(core);
+
+	mutex_unlock(&core->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(cx88_set_freq);
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct cx8800_fh  *fh   = priv;
+	struct cx88_core  *core = fh->dev->core;
+
+	if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
+		return -EINVAL;
+	if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
+		return -EINVAL;
+
+	return
+		cx88_set_freq (core,f);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register (struct file *file, void *fh,
+				struct v4l2_register *reg)
+{
+	struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
+
+	if (reg->i2c_id != 0)
+		return -EINVAL;
+	/* cx2388x has a 24-bit register space */
+	reg->val = cx_read(reg->reg&0xffffff);
+	return 0;
+}
+
+static int vidioc_s_register (struct file *file, void *fh,
+				struct v4l2_register *reg)
+{
+	struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
+
+	if (reg->i2c_id != 0)
+		return -EINVAL;
+	cx_write(reg->reg&0xffffff, reg->val);
+	return 0;
+}
+#endif
+
 /* ----------------------------------------------------------- */
+/* RADIO ESPECIFIC IOCTLS                                      */
+/* ----------------------------------------------------------- */
 
-static int radio_do_ioctl(struct inode *inode, struct file *file,
-			unsigned int cmd, void *arg)
+static int radio_querycap (struct file *file, void  *priv,
+					struct v4l2_capability *cap)
 {
-	struct cx8800_fh *fh    = file->private_data;
-	struct cx8800_dev *dev  = fh->dev;
+	struct cx8800_dev *dev  = ((struct cx8800_fh *)priv)->dev;
 	struct cx88_core  *core = dev->core;
 
-	if (video_debug > 1)
-		v4l_print_ioctl(core->name,cmd);
-
-	switch (cmd) {
-	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability *cap = arg;
-
-		memset(cap,0,sizeof(*cap));
-		strcpy(cap->driver, "cx8800");
-		strlcpy(cap->card, cx88_boards[core->board].name,
-			sizeof(cap->card));
-		sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
-		cap->version = CX88_VERSION_CODE;
-		cap->capabilities = V4L2_CAP_TUNER;
-		return 0;
-	}
-	case VIDIOC_G_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
-
-		if (t->index > 0)
-			return -EINVAL;
-
-		memset(t,0,sizeof(*t));
-		strcpy(t->name, "Radio");
-		t->type = V4L2_TUNER_RADIO;
-
-		cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);
-		return 0;
-	}
-	case VIDIOC_ENUMINPUT:
-	{
-		struct v4l2_input *i = arg;
-
-		if (i->index != 0)
-			return -EINVAL;
-		strcpy(i->name,"Radio");
-		i->type = V4L2_INPUT_TYPE_TUNER;
-		return 0;
-	}
-	case VIDIOC_G_INPUT:
-	{
-		int *i = arg;
-		*i = 0;
-		return 0;
-	}
-	case VIDIOC_G_AUDIO:
-	{
-		struct v4l2_audio *a = arg;
-
-		memset(a,0,sizeof(*a));
-		strcpy(a->name,"Radio");
-		return 0;
-	}
-	case VIDIOC_G_STD:
-	{
-		v4l2_std_id *id = arg;
-		*id = 0;
-		return 0;
-	}
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case VIDIOCSTUNER:
-	{
-		struct video_tuner *v = arg;
-
-		if (v->tuner) /* Only tuner 0 */
-			return -EINVAL;
-
-		cx88_call_i2c_clients(core,VIDIOCSTUNER,v);
-		return 0;
-	}
-#endif
-	case VIDIOC_S_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
-
-		if (0 != t->index)
-			return -EINVAL;
-
-		cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);
-
-		return 0;
-	}
-
-	case VIDIOC_S_AUDIO:
-	case VIDIOC_S_INPUT:
-	case VIDIOC_S_STD:
-		return 0;
-
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *c = arg;
-		int i;
-
-		if (c->id <  V4L2_CID_BASE ||
-		    c->id >= V4L2_CID_LASTP1)
-			return -EINVAL;
-		if (c->id == V4L2_CID_AUDIO_MUTE) {
-			for (i = 0; i < CX8800_CTLS; i++)
-				if (cx8800_ctls[i].v.id == c->id)
-					break;
-			*c = cx8800_ctls[i].v;
-		} else
-			*c = no_ctl;
-		return 0;
-	}
-
-
-	case VIDIOC_G_CTRL:
-	case VIDIOC_S_CTRL:
-	case VIDIOC_G_FREQUENCY:
-	case VIDIOC_S_FREQUENCY:
-		return video_do_ioctl(inode,file,cmd,arg);
-
-	default:
-		return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-						  radio_do_ioctl);
-	}
+	strcpy(cap->driver, "cx8800");
+	strlcpy(cap->card, cx88_boards[core->board].name,
+		sizeof(cap->card));
+	sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
+	cap->version = CX88_VERSION_CODE;
+	cap->capabilities = V4L2_CAP_TUNER;
 	return 0;
-};
+}
 
-static int radio_ioctl(struct inode *inode, struct file *file,
-			unsigned int cmd, unsigned long arg)
+static int radio_g_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
 {
-	return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
-};
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	if (unlikely(t->index > 0))
+		return -EINVAL;
+
+	strcpy(t->name, "Radio");
+	t->type = V4L2_TUNER_RADIO;
+
+	cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);
+	return 0;
+}
+
+static int radio_enum_input (struct file *file, void *priv,
+				struct v4l2_input *i)
+{
+	if (i->index != 0)
+		return -EINVAL;
+	strcpy(i->name,"Radio");
+	i->type = V4L2_INPUT_TYPE_TUNER;
+
+	return 0;
+}
+
+static int radio_g_audio (struct file *file, void *priv, struct v4l2_audio *a)
+{
+	if (unlikely(a->index))
+		return -EINVAL;
+
+	memset(a,0,sizeof(*a));
+	strcpy(a->name,"Radio");
+	return 0;
+}
+
+/* FIXME: Should add a standard for radio */
+
+static int radio_s_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	if (0 != t->index)
+		return -EINVAL;
+
+	cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);
+
+	return 0;
+}
+
+static int radio_s_audio (struct file *file, void *fh,
+			  struct v4l2_audio *a)
+{
+	return 0;
+}
+
+static int radio_s_input (struct file *file, void *fh, unsigned int i)
+{
+	return 0;
+}
+
+static int radio_queryctrl (struct file *file, void *priv,
+			    struct v4l2_queryctrl *c)
+{
+	int i;
+
+	if (c->id <  V4L2_CID_BASE ||
+		c->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+	if (c->id == V4L2_CID_AUDIO_MUTE) {
+		for (i = 0; i < CX8800_CTLS; i++)
+			if (cx8800_ctls[i].v.id == c->id)
+				break;
+		*c = cx8800_ctls[i].v;
+	} else
+		*c = no_ctl;
+	return 0;
+}
 
 /* ----------------------------------------------------------- */
 
@@ -1808,7 +1630,7 @@
 /* ----------------------------------------------------------- */
 /* exported stuff                                              */
 
-static struct file_operations video_fops =
+static const struct file_operations video_fops =
 {
 	.owner	       = THIS_MODULE,
 	.open	       = video_open,
@@ -1816,46 +1638,83 @@
 	.read	       = video_read,
 	.poll          = video_poll,
 	.mmap	       = video_mmap,
-	.ioctl	       = video_ioctl,
+	.ioctl	       = video_ioctl2,
 	.compat_ioctl  = v4l_compat_ioctl32,
 	.llseek        = no_llseek,
 };
 
+static struct video_device cx8800_vbi_template;
 static struct video_device cx8800_video_template =
 {
-	.name          = "cx8800-video",
-	.type          = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
-	.hardware      = 0,
-	.fops          = &video_fops,
-	.minor         = -1,
+	.name                 = "cx8800-video",
+	.type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
+	.fops                 = &video_fops,
+	.minor                = -1,
+	.vidioc_querycap      = vidioc_querycap,
+	.vidioc_enum_fmt_cap  = vidioc_enum_fmt_cap,
+	.vidioc_g_fmt_cap     = vidioc_g_fmt_cap,
+	.vidioc_try_fmt_cap   = vidioc_try_fmt_cap,
+	.vidioc_s_fmt_cap     = vidioc_s_fmt_cap,
+	.vidioc_g_fmt_vbi     = cx8800_vbi_fmt,
+	.vidioc_try_fmt_vbi   = cx8800_vbi_fmt,
+	.vidioc_s_fmt_vbi     = cx8800_vbi_fmt,
+	.vidioc_reqbufs       = vidioc_reqbufs,
+	.vidioc_querybuf      = vidioc_querybuf,
+	.vidioc_qbuf          = vidioc_qbuf,
+	.vidioc_dqbuf         = vidioc_dqbuf,
+	.vidioc_s_std         = vidioc_s_std,
+	.vidioc_enum_input    = vidioc_enum_input,
+	.vidioc_g_input       = vidioc_g_input,
+	.vidioc_s_input       = vidioc_s_input,
+	.vidioc_queryctrl     = vidioc_queryctrl,
+	.vidioc_g_ctrl        = vidioc_g_ctrl,
+	.vidioc_s_ctrl        = vidioc_s_ctrl,
+	.vidioc_streamon      = vidioc_streamon,
+	.vidioc_streamoff     = vidioc_streamoff,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+	.vidiocgmbuf          = vidiocgmbuf,
+#endif
+	.vidioc_g_tuner       = vidioc_g_tuner,
+	.vidioc_s_tuner       = vidioc_s_tuner,
+	.vidioc_g_frequency   = vidioc_g_frequency,
+	.vidioc_s_frequency   = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register    = vidioc_g_register,
+	.vidioc_s_register    = vidioc_s_register,
+#endif
+	.tvnorms              = CX88_NORMS,
+	.current_norm         = V4L2_STD_NTSC_M,
 };
 
-static struct video_device cx8800_vbi_template =
-{
-	.name          = "cx8800-vbi",
-	.type          = VID_TYPE_TELETEXT|VID_TYPE_TUNER,
-	.hardware      = 0,
-	.fops          = &video_fops,
-	.minor         = -1,
-};
-
-static struct file_operations radio_fops =
+static const struct file_operations radio_fops =
 {
 	.owner         = THIS_MODULE,
 	.open          = video_open,
 	.release       = video_release,
-	.ioctl         = radio_ioctl,
+	.ioctl         = video_ioctl2,
 	.compat_ioctl  = v4l_compat_ioctl32,
 	.llseek        = no_llseek,
 };
 
 static struct video_device cx8800_radio_template =
 {
-	.name          = "cx8800-radio",
-	.type          = VID_TYPE_TUNER,
-	.hardware      = 0,
-	.fops          = &radio_fops,
-	.minor         = -1,
+	.name                 = "cx8800-radio",
+	.type                 = VID_TYPE_TUNER,
+	.hardware             = 0,
+	.fops                 = &radio_fops,
+	.minor                = -1,
+	.vidioc_querycap      = radio_querycap,
+	.vidioc_g_tuner       = radio_g_tuner,
+	.vidioc_enum_input    = radio_enum_input,
+	.vidioc_g_audio       = radio_g_audio,
+	.vidioc_s_tuner       = radio_s_tuner,
+	.vidioc_s_audio       = radio_s_audio,
+	.vidioc_s_input       = radio_s_input,
+	.vidioc_queryctrl     = radio_queryctrl,
+	.vidioc_g_ctrl        = vidioc_g_ctrl,
+	.vidioc_s_ctrl        = vidioc_s_ctrl,
+	.vidioc_g_frequency   = vidioc_g_frequency,
+	.vidioc_s_frequency   = vidioc_s_frequency,
 };
 
 /* ----------------------------------------------------------- */
@@ -1890,6 +1749,7 @@
 {
 	struct cx8800_dev *dev;
 	struct cx88_core *core;
+
 	int err;
 
 	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
@@ -1924,9 +1784,15 @@
 		goto fail_core;
 	}
 
+	/* Initialize VBI template */
+	memcpy( &cx8800_vbi_template, &cx8800_video_template,
+		sizeof(cx8800_vbi_template) );
+	strcpy(cx8800_vbi_template.name,"cx8800-vbi");
+	cx8800_vbi_template.type = VID_TYPE_TELETEXT|VID_TYPE_TUNER;
+
 	/* initialize driver struct */
 	spin_lock_init(&dev->slock);
-	core->tvnorm = tvnorms;
+	core->tvnorm = cx8800_video_template.current_norm;
 
 	/* init video dma queues */
 	INIT_LIST_HEAD(&dev->vidq.active);
@@ -2007,9 +1873,9 @@
 
 	/* initial device configuration */
 	mutex_lock(&core->lock);
-	cx88_set_tvnorm(core,tvnorms);
+	cx88_set_tvnorm(core,core->tvnorm);
 	init_controls(core);
-	video_mux(core,0);
+	cx88_video_mux(core,0);
 	mutex_unlock(&core->lock);
 
 	/* start tvaudio thread */
@@ -2178,8 +2044,6 @@
 module_init(cx8800_init);
 module_exit(cx8800_fini);
 
-EXPORT_SYMBOL(cx88_do_ioctl);
-
 /* ----------------------------------------------------------- */
 /*
  * Local variables:
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index a9575ad..d2ecfba 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -31,7 +31,9 @@
 #include <media/video-buf.h>
 #include <media/cx2341x.h>
 #include <media/audiochip.h>
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
 #include <media/video-buf-dvb.h>
+#endif
 
 #include "btcx-risc.h"
 #include "cx88-reg.h"
@@ -50,6 +52,13 @@
 /* ----------------------------------------------------------- */
 /* defines and enums                                           */
 
+/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
+#define CX88_NORMS (\
+	V4L2_STD_NTSC_M|  V4L2_STD_NTSC_M_JP|  V4L2_STD_NTSC_443 | \
+	V4L2_STD_PAL_BG|  V4L2_STD_PAL_DK   |  V4L2_STD_PAL_I    | \
+	V4L2_STD_PAL_M |  V4L2_STD_PAL_N    |  V4L2_STD_PAL_Nc   | \
+	V4L2_STD_PAL_60|  V4L2_STD_SECAM_L  |  V4L2_STD_SECAM_DK )
+
 #define FORMAT_FLAGS_PACKED       0x01
 #define FORMAT_FLAGS_PLANAR       0x02
 
@@ -82,22 +91,15 @@
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
 
-struct cx88_tvnorm {
-	char                   *name;
-	v4l2_std_id            id;
-	u32                    cxiformat;
-	u32                    cxoformat;
-};
-
-static unsigned int inline norm_maxw(struct cx88_tvnorm *norm)
+static unsigned int inline norm_maxw(v4l2_std_id norm)
 {
-	return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
+	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
 }
 
 
-static unsigned int inline norm_maxh(struct cx88_tvnorm *norm)
+static unsigned int inline norm_maxh(v4l2_std_id norm)
 {
-	return (norm->id & V4L2_STD_625_50) ? 576 : 480;
+	return (norm & V4L2_STD_625_50) ? 576 : 480;
 }
 
 /* ----------------------------------------------------------- */
@@ -313,13 +315,15 @@
 	unsigned int               tuner_formats;
 
 	/* config info -- dvb */
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
 	struct dvb_pll_desc        *pll_desc;
 	unsigned int               pll_addr;
 	int 			   (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
+#endif
 
 	/* state info */
 	struct task_struct         *kthread;
-	struct cx88_tvnorm         *tvnorm;
+	v4l2_std_id                tvnorm;
 	u32                        tvaudio;
 	u32                        audiomode_manual;
 	u32                        audiomode_current;
@@ -460,12 +464,14 @@
 	int                        width;
 	int                        height;
 
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
 	/* for dvb only */
 	struct videobuf_dvb        dvb;
 	void*                      fe_handle;
 	int                        (*fe_release)(void *handle);
 
 	void			   *card_priv;
+#endif
 	/* for switching modulation types */
 	unsigned char              ts_gen_cntrl;
 
@@ -536,7 +542,7 @@
 
 extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
 			  unsigned int height, enum v4l2_field field);
-extern int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm);
+extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm);
 
 extern struct video_device *cx88_vdev_init(struct cx88_core *core,
 					   struct pci_dev *pci,
@@ -553,7 +559,10 @@
 /* ----------------------------------------------------------- */
 /* cx88-vbi.c                                                  */
 
-void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f);
+/* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */
+int cx8800_vbi_fmt (struct file *file, void *priv,
+					struct v4l2_format *f);
+
 /*
 int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
 			 struct cx88_dmaqueue *q,
@@ -633,19 +642,14 @@
 int cx8802_resume_common(struct pci_dev *pci_dev);
 
 /* ----------------------------------------------------------- */
-/* cx88-video.c                                                */
-extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
-				struct cx88_core *core, unsigned int cmd,
-				void *arg, v4l2_kioctl driver_ioctl);
+/* cx88-video.c*/
 extern const u32 cx88_user_ctrls[];
 extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);
-
-/* ----------------------------------------------------------- */
-/* cx88-blackbird.c                                            */
-/* used by cx88-ivtv ioctl emulation layer                     */
-extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
-			      unsigned int cmd, void *arg);
-extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i);
+int cx88_set_freq (struct cx88_core  *core,struct v4l2_frequency *f);
+int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
+int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl);
+int cx88_video_mux(struct cx88_core *core, unsigned int input);
 
 /*
  * Local variables:
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index 917021f..ff4b238 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -696,7 +696,7 @@
 	return ret;
 }
 
-static struct file_operations dabusb_fops =
+static const struct file_operations dabusb_fops =
 {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 3ffb568..55d45b0 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -25,7 +25,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/usb.h>
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 36e72c2..bec6760 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1480,7 +1480,7 @@
 	return ret;
 }
 
-static struct file_operations em28xx_v4l_fops = {
+static const struct file_operations em28xx_v4l_fops = {
 	.owner = THIS_MODULE,
 	.open = em28xx_v4l2_open,
 	.release = em28xx_v4l2_close,
diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h
index 2e5ca40..262f98e 100644
--- a/drivers/media/video/et61x251/et61x251.h
+++ b/drivers/media/video/et61x251/et61x251.h
@@ -171,10 +171,7 @@
 struct et61x251_device*
 et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id)
 {
-	if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
-		return cam;
-
-	return NULL;
+	return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
 }
 
 
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 86e353b..a652551 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -1,7 +1,7 @@
 /***************************************************************************
  * V4L2 driver for ET61X[12]51 PC Camera Controllers                       *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -48,8 +48,8 @@
 #define ET61X251_MODULE_AUTHOR  "(C) 2006 Luca Risolia"
 #define ET61X251_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
 #define ET61X251_MODULE_LICENSE "GPL"
-#define ET61X251_MODULE_VERSION "1:1.02"
-#define ET61X251_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 2)
+#define ET61X251_MODULE_VERSION "1:1.04"
+#define ET61X251_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 4)
 
 /*****************************************************************************/
 
@@ -85,7 +85,7 @@
 		 "\ndetected camera."
 		 "\n 0 = do not force memory unmapping"
 		 "\n 1 = force memory unmapping (save memory)"
-		 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+		 "\nDefault value is "__MODULE_STRING(ET61X251_FORCE_MUNMAP)"."
 		 "\n");
 
 static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] =
@@ -133,7 +133,8 @@
 
 	cam->nbuffers = count;
 	while (cam->nbuffers > 0) {
-		if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+		if ((buff = vmalloc_32_user(cam->nbuffers *
+					    PAGE_ALIGN(imagesize))))
 			break;
 		cam->nbuffers--;
 	}
@@ -543,10 +544,11 @@
 {
 	struct usb_device *udev = cam->usbdev;
 	struct urb* urb;
-	const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832,
-					       864, 896, 920, 956, 980, 1000,
-					       1022};
-	const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING];
+	struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
+						   usb_ifnum_to_if(udev, 0),
+						   ET61X251_ALTERNATE_SETTING);
+	const unsigned int psz = le16_to_cpu(altsetting->
+					     endpoint[0].desc.wMaxPacketSize);
 	s8 i, j;
 	int err = 0;
 
@@ -976,29 +978,31 @@
 static int et61x251_create_sysfs(struct et61x251_device* cam)
 {
 	struct video_device *v4ldev = cam->v4ldev;
-	int rc;
+	int err = 0;
 
-	rc = video_device_create_file(v4ldev, &class_device_attr_reg);
-	if (rc) goto err;
-	rc = video_device_create_file(v4ldev, &class_device_attr_val);
-	if (rc) goto err_reg;
+	if ((err = video_device_create_file(v4ldev, &class_device_attr_reg)))
+		goto err_out;
+	if ((err = video_device_create_file(v4ldev, &class_device_attr_val)))
+		goto err_reg;
+
 	if (cam->sensor.sysfs_ops) {
-		rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
-		if (rc) goto err_val;
-		rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val);
-		if (rc) goto err_i2c_reg;
+		if ((err = video_device_create_file(v4ldev,
+						  &class_device_attr_i2c_reg)))
+			goto err_val;
+		if ((err = video_device_create_file(v4ldev,
+						  &class_device_attr_i2c_val)))
+			goto err_i2c_reg;
 	}
 
-	return 0;
-
 err_i2c_reg:
+	if (cam->sensor.sysfs_ops)
 	video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
 err_val:
 	video_device_remove_file(v4ldev, &class_device_attr_val);
 err_reg:
 	video_device_remove_file(v4ldev, &class_device_attr_reg);
-err:
-	return rc;
+err_out:
+	return err;
 }
 #endif /* CONFIG_VIDEO_ADV_DEBUG */
 
@@ -1767,10 +1771,10 @@
 	rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
 	rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
 
-	if (rect->width < 4)
-		rect->width = 4;
-	if (rect->height < 4)
-		rect->height = 4;
+	if (rect->width < 16)
+		rect->width = 16;
+	if (rect->height < 16)
+		rect->height = 16;
 	if (rect->width > bounds->width)
 		rect->width = bounds->width;
 	if (rect->height > bounds->height)
@@ -1784,8 +1788,8 @@
 	if (rect->top + rect->height > bounds->top + bounds->height)
 		rect->top = bounds->top+bounds->height - rect->height;
 
-	rect->width &= ~3L;
-	rect->height &= ~3L;
+	rect->width &= ~15L;
+	rect->height &= ~15L;
 
 	if (ET61X251_PRESERVE_IMGSCALE) {
 		/* Calculate the actual scaling factor */
@@ -1846,6 +1850,35 @@
 
 
 static int
+et61x251_vidioc_enum_framesizes(struct et61x251_device* cam, void __user * arg)
+{
+	struct v4l2_frmsizeenum frmsize;
+
+	if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
+		return -EFAULT;
+
+	if (frmsize.index != 0)
+		return -EINVAL;
+
+	if (frmsize.pixel_format != V4L2_PIX_FMT_ET61X251 &&
+	    frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
+		return -EINVAL;
+
+	frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
+	frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
+	frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
+	frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
+	memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
+
+	if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
 et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg)
 {
 	struct v4l2_fmtdesc fmtd;
@@ -1853,6 +1886,9 @@
 	if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
 		return -EFAULT;
 
+	if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
 	if (fmtd.index == 0) {
 		strcpy(fmtd.description, "bayer rgb");
 		fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
@@ -1934,17 +1970,17 @@
 	rect.width = scale * pix->width;
 	rect.height = scale * pix->height;
 
-	if (rect.width < 4)
-		rect.width = 4;
-	if (rect.height < 4)
-		rect.height = 4;
+	if (rect.width < 16)
+		rect.width = 16;
+	if (rect.height < 16)
+		rect.height = 16;
 	if (rect.width > bounds->left + bounds->width - rect.left)
 		rect.width = bounds->left + bounds->width - rect.left;
 	if (rect.height > bounds->top + bounds->height - rect.top)
 		rect.height = bounds->top + bounds->height - rect.top;
 
-	rect.width &= ~3L;
-	rect.height &= ~3L;
+	rect.width &= ~15L;
+	rect.height &= ~15L;
 
 	{ /* adjust the scaling factor */
 		u32 a, b;
@@ -2378,6 +2414,9 @@
 	case VIDIOC_S_FMT:
 		return et61x251_vidioc_try_s_fmt(cam, cmd, arg);
 
+	case VIDIOC_ENUM_FRAMESIZES:
+		return et61x251_vidioc_enum_framesizes(cam, arg);
+
 	case VIDIOC_G_JPEGCOMP:
 		return et61x251_vidioc_g_jpegcomp(cam, arg);
 
@@ -2413,6 +2452,7 @@
 	case VIDIOC_QUERYSTD:
 	case VIDIOC_ENUMSTD:
 	case VIDIOC_QUERYMENU:
+	case VIDIOC_ENUM_FRAMEINTERVALS:
 		return -EINVAL;
 
 	default:
@@ -2454,11 +2494,12 @@
 }
 
 
-static struct file_operations et61x251_fops = {
+static const struct file_operations et61x251_fops = {
 	.owner = THIS_MODULE,
 	.open =    et61x251_open,
 	.release = et61x251_release,
 	.ioctl =   et61x251_ioctl,
+	.compat_ioctl = v4l_compat_ioctl32,
 	.read =    et61x251_read,
 	.poll =    et61x251_poll,
 	.mmap =    et61x251_mmap,
@@ -2497,7 +2538,7 @@
 	mutex_init(&cam->dev_mutex);
 
 	DBG(2, "ET61X[12]51 PC Camera Controller detected "
-	       "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct);
+	       "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct);
 
 	for  (i = 0; et61x251_sensor_table[i]; i++) {
 		err = et61x251_sensor_table[i](cam);
@@ -2550,9 +2591,14 @@
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	err = et61x251_create_sysfs(cam);
-	if (err)
-		goto fail2;
-	DBG(2, "Optional device control through 'sysfs' interface ready");
+	if (!err)
+		DBG(2, "Optional device control through 'sysfs' "
+		       "interface ready");
+	else
+		DBG(2, "Failed to create 'sysfs' interface for optional "
+		       "device controlling. Error #%d", err);
+#else
+	DBG(2, "Optional device control through 'sysfs' interface disabled");
 #endif
 
 	usb_set_intfdata(intf, cam);
@@ -2561,13 +2607,6 @@
 
 	return 0;
 
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-fail2:
-	video_nr[dev_nr] = -1;
-	dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
-	mutex_unlock(&cam->dev_mutex);
-	video_unregister_device(cam->v4ldev);
-#endif
 fail:
 	if (cam) {
 		kfree(cam->control_buffer);
diff --git a/drivers/media/video/et61x251/et61x251_sensor.h b/drivers/media/video/et61x251/et61x251_sensor.h
index 65edd08..5fadb5d 100644
--- a/drivers/media/video/et61x251/et61x251_sensor.h
+++ b/drivers/media/video/et61x251/et61x251_sensor.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  * API for image sensors connected to ET61X[12]51 PC Camera Controllers    *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -82,7 +82,7 @@
 	ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */
 };
 
-#define ET61X251_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
+#define ET61X251_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
 
 struct et61x251_sensor {
 	char name[32];
diff --git a/drivers/media/video/et61x251/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c
index a7d65b8..b066434 100644
--- a/drivers/media/video/et61x251/et61x251_tas5130d1b.c
+++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c
@@ -2,7 +2,7 @@
  * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51        *
  * PC Camera Controllers                                                   *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
index 7420b79..5c2c402 100644
--- a/drivers/media/video/indycam.c
+++ b/drivers/media/video/indycam.c
@@ -17,7 +17,6 @@
 #include <linux/major.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 59edf58..210582d 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -31,7 +31,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 616a35d..98681da 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -28,7 +28,6 @@
  */
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
@@ -1748,7 +1747,7 @@
 	return 0;
 }
 
-static struct file_operations meye_fops = {
+static const struct file_operations meye_fops = {
 	.owner		= THIS_MODULE,
 	.open		= meye_open,
 	.release	= meye_release,
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index b4db2cb..e5edff1 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -4653,7 +4653,7 @@
 	return 0;
 }
 
-static struct file_operations ov511_fops = {
+static const struct file_operations ov511_fops = {
 	.owner =	THIS_MODULE,
 	.open =		ov51x_v4l1_open,
 	.release =	ov51x_v4l1_close,
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 5d681fa..b5a67f0 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -28,7 +28,6 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <asm/io.h>
-#include <linux/sched.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
 #include <linux/mutex.h>
@@ -881,7 +880,7 @@
 	return len;
 }
 
-static struct file_operations pms_fops = {
+static const struct file_operations pms_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c
index 9846c46..379645e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-audio.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c
@@ -31,7 +31,6 @@
 	struct pvr2_hdw *hdw;
 	struct pvr2_i2c_client *client;
 	struct pvr2_i2c_handler i2c_handler;
-	struct pvr2_audio_stat astat;
 	unsigned long stale_mask;
 };
 
@@ -44,13 +43,6 @@
 
 	pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
 
-	if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
-		struct v4l2_tuner vt;
-		memset(&vt,0,sizeof(vt));
-		vt.audmode = hdw->audiomode_val;
-		pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt);
-	}
-
 	route.input = MSP_INPUT_DEFAULT;
 	route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
 	switch (hdw->input_val) {
@@ -78,8 +70,7 @@
 static int check_stereo(struct pvr2_msp3400_handler *ctxt)
 {
 	struct pvr2_hdw *hdw = ctxt->hdw;
-	return (hdw->input_dirty ||
-		hdw->audiomode_dirty);
+	return hdw->input_dirty;
 }
 
 
@@ -99,8 +90,7 @@
 	unsigned long msk;
 	unsigned int idx;
 
-	for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
-	     idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) {
 		msk = 1 << idx;
 		if (ctxt->stale_mask & msk) continue;
 		if (msp3400_ops[idx].check(ctxt)) {
@@ -116,8 +106,7 @@
 	unsigned long msk;
 	unsigned int idx;
 
-	for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
-	     idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) {
 		msk = 1 << idx;
 		if (!(ctxt->stale_mask & msk)) continue;
 		ctxt->stale_mask &= ~msk;
@@ -126,27 +115,9 @@
 }
 
 
-/* This reads back the current signal type */
-static int get_audio_status(struct pvr2_msp3400_handler *ctxt)
-{
-	struct v4l2_tuner vt;
-	int stat;
-
-	memset(&vt,0,sizeof(vt));
-	stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
-	if (stat < 0) return stat;
-
-	ctxt->hdw->flag_stereo = (vt.audmode & V4L2_TUNER_MODE_STEREO) != 0;
-	ctxt->hdw->flag_bilingual =
-		(vt.audmode & V4L2_TUNER_MODE_LANG2) != 0;
-	return 0;
-}
-
-
 static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt)
 {
 	ctxt->client->handler = NULL;
-	ctxt->hdw->audio_stat = NULL;
 	kfree(ctxt);
 }
 
@@ -158,7 +129,7 @@
 }
 
 
-const static struct pvr2_i2c_handler_functions msp3400_funcs = {
+static const struct pvr2_i2c_handler_functions msp3400_funcs = {
 	.detach = (void (*)(void *))pvr2_msp3400_detach,
 	.check = (int (*)(void *))msp3400_check,
 	.update = (void (*)(void *))msp3400_update,
@@ -169,24 +140,17 @@
 int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
 {
 	struct pvr2_msp3400_handler *ctxt;
-	if (hdw->audio_stat) return 0;
 	if (cp->handler) return 0;
 
-	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
 	if (!ctxt) return 0;
-	memset(ctxt,0,sizeof(*ctxt));
 
 	ctxt->i2c_handler.func_data = ctxt;
 	ctxt->i2c_handler.func_table = &msp3400_funcs;
 	ctxt->client = cp;
 	ctxt->hdw = hdw;
-	ctxt->astat.ctxt = ctxt;
-	ctxt->astat.status = (int (*)(void *))get_audio_status;
-	ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach;
-	ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/
-				  sizeof(msp3400_ops[0]))) - 1;
+	ctxt->stale_mask = (1 << ARRAY_SIZE(msp3400_ops)) - 1;
 	cp->handler = &ctxt->i2c_handler;
-	hdw->audio_stat = &ctxt->astat;
 	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up",
 		   cp->client->addr);
 	return !0;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
index cf12974..6bbed88 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-context.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-context.c
@@ -83,9 +83,8 @@
 	void (*setup_func)(struct pvr2_context *))
 {
 	struct pvr2_context *mp = NULL;
-	mp = kmalloc(sizeof(*mp),GFP_KERNEL);
+	mp = kzalloc(sizeof(*mp),GFP_KERNEL);
 	if (!mp) goto done;
-	memset(mp,0,sizeof(*mp));
 	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
 	mp->setup_func = setup_func;
 	mutex_init(&mp->mutex);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
index c77de85..f569b00 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -26,6 +26,27 @@
 #include <linux/mutex.h>
 
 
+static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
+{
+	if (cptr->info->check_value) {
+		if (!cptr->info->check_value(cptr,val)) return -ERANGE;
+	} else {
+		int lim;
+		lim = cptr->info->def.type_int.min_value;
+		if (cptr->info->get_min_value) {
+			cptr->info->get_min_value(cptr,&lim);
+		}
+		if (val < lim) return -ERANGE;
+		lim = cptr->info->def.type_int.max_value;
+		if (cptr->info->get_max_value) {
+			cptr->info->get_max_value(cptr,&lim);
+		}
+		if (val > lim) return -ERANGE;
+	}
+	return 0;
+}
+
+
 /* Set the given control. */
 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
 {
@@ -43,17 +64,8 @@
 			if (cptr->info->type == pvr2_ctl_bitmask) {
 				mask &= cptr->info->def.type_bitmask.valid_bits;
 			} else if (cptr->info->type == pvr2_ctl_int) {
-				int lim;
-				lim = cptr->info->def.type_int.min_value;
-				if (cptr->info->get_min_value) {
-					cptr->info->get_min_value(cptr,&lim);
-				}
-				if (val < lim) break;
-				lim = cptr->info->def.type_int.max_value;
-				if (cptr->info->get_max_value) {
-					cptr->info->get_max_value(cptr,&lim);
-				}
-				if (val > lim) break;
+				ret = pvr2_ctrl_range_check(cptr,val);
+				if (ret < 0) break;
 			} else if (cptr->info->type == pvr2_ctl_enum) {
 				if (val >= cptr->info->def.type_enum.count) {
 					break;
@@ -498,16 +510,13 @@
 	LOCK_TAKE(cptr->hdw->big_lock); do {
 		if (cptr->info->type == pvr2_ctl_int) {
 			ret = parse_token(ptr,len,valptr,NULL,0);
-			if ((ret >= 0) &&
-			    ((*valptr < cptr->info->def.type_int.min_value) ||
-			     (*valptr > cptr->info->def.type_int.max_value))) {
-				ret = -ERANGE;
+			if (ret >= 0) {
+				ret = pvr2_ctrl_range_check(cptr,*valptr);
 			}
 			if (maskptr) *maskptr = ~0;
 		} else if (cptr->info->type == pvr2_ctl_bool) {
-			ret = parse_token(
-				ptr,len,valptr,boolNames,
-				sizeof(boolNames)/sizeof(boolNames[0]));
+			ret = parse_token(ptr,len,valptr,boolNames,
+					  ARRAY_SIZE(boolNames));
 			if (ret == 1) {
 				*valptr = *valptr ? !0 : 0;
 			} else if (ret == 0) {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
index 848fb233..e8a9252 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -63,6 +63,7 @@
 		vid_input = CX25840_COMPOSITE7;
 		aud_input = CX25840_AUDIO8;
 		break;
+	case PVR2_CVAL_INPUT_RADIO: // Treat same as composite
 	case PVR2_CVAL_INPUT_COMPOSITE:
 		vid_input = CX25840_COMPOSITE3;
 		aud_input = CX25840_AUDIO_SERIAL;
@@ -71,7 +72,6 @@
 		vid_input = CX25840_SVIDEO1;
 		aud_input = CX25840_AUDIO_SERIAL;
 		break;
-	case PVR2_CVAL_INPUT_RADIO:
 	default:
 		// Just set it to be composite input for now...
 		vid_input = CX25840_COMPOSITE3;
@@ -150,8 +150,7 @@
 	unsigned long msk;
 	unsigned int idx;
 
-	for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
-	     idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
 		msk = 1 << idx;
 		if (ctxt->stale_mask & msk) continue;
 		if (decoder_ops[idx].check(ctxt)) {
@@ -167,8 +166,7 @@
 	unsigned long msk;
 	unsigned int idx;
 
-	for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
-	     idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
 		msk = 1 << idx;
 		if (!(ctxt->stale_mask & msk)) continue;
 		ctxt->stale_mask &= ~msk;
@@ -199,18 +197,6 @@
 }
 
 
-static int decoder_is_tuned(struct pvr2_v4l_cx2584x *ctxt)
-{
-	struct v4l2_tuner vt;
-	int ret;
-
-	memset(&vt,0,sizeof(vt));
-	ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
-	if (ret < 0) return -EINVAL;
-	return vt.signal ? 1 : 0;
-}
-
-
 static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
 				     char *buf,unsigned int cnt)
 {
@@ -226,7 +212,7 @@
 }
 
 
-const static struct pvr2_i2c_handler_functions hfuncs = {
+static const struct pvr2_i2c_handler_functions hfuncs = {
 	.detach = (void (*)(void *))decoder_detach,
 	.check = (int (*)(void *))decoder_check,
 	.update = (void (*)(void *))decoder_update,
@@ -243,21 +229,18 @@
 	if (cp->handler) return 0;
 	if (!decoder_detect(cp)) return 0;
 
-	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
 	if (!ctxt) return 0;
-	memset(ctxt,0,sizeof(*ctxt));
 
 	ctxt->handler.func_data = ctxt;
 	ctxt->handler.func_table = &hfuncs;
 	ctxt->ctrl.ctxt = ctxt;
 	ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
 	ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
-	ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned;
 	ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset;
 	ctxt->client = cp;
 	ctxt->hdw = hdw;
-	ctxt->stale_mask = (1 << (sizeof(decoder_ops)/
-				  sizeof(decoder_ops[0]))) - 1;
+	ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1;
 	hdw->decoder_ctrl = &ctxt->ctrl;
 	cp->handler = &ctxt->handler;
 	{
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
index f985f00..e9da9bb 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
@@ -152,7 +152,7 @@
 {
 	struct debugifc_mask_item *mip;
 	unsigned int idx;
-	for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(mask_items); idx++) {
 		mip = mask_items + idx;
 		if (debugifc_match_keyword(buf,count,mip->name)) {
 			return mip->msk;
@@ -169,7 +169,7 @@
 	unsigned int idx;
 	int bcnt = 0;
 	int ccnt;
-	for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(mask_items); idx++) {
 		mip = mask_items + idx;
 		if (!(mip->msk & msk)) continue;
 		ccnt = scnprintf(buf,sz,"%s%c%s",
diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
index 6cff8e7..45cbca0 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
@@ -102,9 +102,8 @@
 		}
 		msg[1].len = pcnt;
 		msg[1].buf = eeprom+tcnt;
-		if ((ret = i2c_transfer(
-			     &hdw->i2c_adap,
-			     msg,sizeof(msg)/sizeof(msg[0]))) != 2) {
+		if ((ret = i2c_transfer(&hdw->i2c_adap,
+					msg,ARRAY_SIZE(msg))) != 2) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 				   "eeprom fetch set offs err=%d",ret);
 			kfree(eeprom);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
index c94f97b..5786faf 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -26,6 +26,7 @@
 #include "pvrusb2-encoder.h"
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-debug.h"
+#include "pvrusb2-fx2-cmd.h"
 
 
 
@@ -34,34 +35,41 @@
 #define IVTV_MBOX_DRIVER_DONE 0x00000002
 #define IVTV_MBOX_DRIVER_BUSY 0x00000001
 
+#define MBOX_BASE 0x44
+
 
 static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
+				    unsigned int offs,
 				    const u32 *data, unsigned int dlen)
 {
-	unsigned int idx;
+	unsigned int idx,addr;
+	unsigned int bAddr;
 	int ret;
-	unsigned int offs = 0;
 	unsigned int chunkCnt;
 
 	/*
 
 	Format: First byte must be 0x01.  Remaining 32 bit words are
-	spread out into chunks of 7 bytes each, little-endian ordered,
-	offset at zero within each 2 blank bytes following and a
-	single byte that is 0x44 plus the offset of the word.  Repeat
-	request for additional words, with offset adjusted
-	accordingly.
+	spread out into chunks of 7 bytes each, with the first 4 bytes
+	being the data word (little endian), and the next 3 bytes
+	being the address where that data word is to be written (big
+	endian).  Repeat request for additional words, with offset
+	adjusted accordingly.
 
 	*/
 	while (dlen) {
 		chunkCnt = 8;
 		if (chunkCnt > dlen) chunkCnt = dlen;
 		memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
-		hdw->cmd_buffer[0] = 0x01;
+		bAddr = 0;
+		hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD;
 		for (idx = 0; idx < chunkCnt; idx++) {
-			hdw->cmd_buffer[1+(idx*7)+6] = 0x44 + idx + offs;
-			PVR2_DECOMPOSE_LE(hdw->cmd_buffer, 1+(idx*7),
-					  data[idx]);
+			addr = idx + offs;
+			hdw->cmd_buffer[bAddr+6] = (addr & 0xffu);
+			hdw->cmd_buffer[bAddr+5] = ((addr>>8) & 0xffu);
+			hdw->cmd_buffer[bAddr+4] = ((addr>>16) & 0xffu);
+			PVR2_DECOMPOSE_LE(hdw->cmd_buffer, bAddr,data[idx]);
+			bAddr += 7;
 		}
 		ret = pvr2_send_request(hdw,
 					hdw->cmd_buffer,1+(chunkCnt*7),
@@ -76,33 +84,42 @@
 }
 
 
-static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl,
+static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,
+				   unsigned int offs,
 				   u32 *data, unsigned int dlen)
 {
 	unsigned int idx;
 	int ret;
-	unsigned int offs = 0;
 	unsigned int chunkCnt;
 
 	/*
 
 	Format: First byte must be 0x02 (status check) or 0x28 (read
 	back block of 32 bit words).  Next 6 bytes must be zero,
-	followed by a single byte of 0x44+offset for portion to be
-	read.  Returned data is packed set of 32 bits words that were
-	read.
+	followed by a single byte of MBOX_BASE+offset for portion to
+	be read.  Returned data is packed set of 32 bits words that
+	were read.
 
 	*/
 
 	while (dlen) {
 		chunkCnt = 16;
 		if (chunkCnt > dlen) chunkCnt = dlen;
-		memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
-		hdw->cmd_buffer[0] = statusFl ? 0x02 : 0x28;
-		hdw->cmd_buffer[7] = 0x44 + offs;
+		if (chunkCnt < 16) chunkCnt = 1;
+		hdw->cmd_buffer[0] =
+			((chunkCnt == 1) ?
+			 FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES);
+		hdw->cmd_buffer[1] = 0;
+		hdw->cmd_buffer[2] = 0;
+		hdw->cmd_buffer[3] = 0;
+		hdw->cmd_buffer[4] = 0;
+		hdw->cmd_buffer[5] = ((offs>>16) & 0xffu);
+		hdw->cmd_buffer[6] = ((offs>>8) & 0xffu);
+		hdw->cmd_buffer[7] = (offs & 0xffu);
 		ret = pvr2_send_request(hdw,
 					hdw->cmd_buffer,8,
-					hdw->cmd_buffer,chunkCnt * 4);
+					hdw->cmd_buffer,
+					(chunkCnt == 1 ? 4 : 16 * 4));
 		if (ret) return ret;
 
 		for (idx = 0; idx < chunkCnt; idx++) {
@@ -129,6 +146,8 @@
 			    u32 *argp)
 {
 	unsigned int poll_count;
+	unsigned int try_count = 0;
+	int retry_flag;
 	int ret = 0;
 	unsigned int idx;
 	/* These sizes look to be limited by the FX2 firmware implementation */
@@ -140,14 +159,15 @@
 	/*
 
 	The encoder seems to speak entirely using blocks 32 bit words.
-	In ivtv driver terms, this is a mailbox which we populate with
-	data and watch what the hardware does with it.  The first word
-	is a set of flags used to control the transaction, the second
-	word is the command to execute, the third byte is zero (ivtv
-	driver suggests that this is some kind of return value), and
-	the fourth byte is a specified timeout (windows driver always
-	uses 0x00060000 except for one case when it is zero).  All
-	successive words are the argument words for the command.
+	In ivtv driver terms, this is a mailbox at MBOX_BASE which we
+	populate with data and watch what the hardware does with it.
+	The first word is a set of flags used to control the
+	transaction, the second word is the command to execute, the
+	third byte is zero (ivtv driver suggests that this is some
+	kind of return value), and the fourth byte is a specified
+	timeout (windows driver always uses 0x00060000 except for one
+	case when it is zero).  All successive words are the argument
+	words for the command.
 
 	First, write out the entire set of words, with the first word
 	being zero.
@@ -156,44 +176,42 @@
 	IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
 	probably means "go").
 
-	Next, read back 16 words as status.  Check the first word,
+	Next, read back the return count words.  Check the first word,
 	which should have IVTV_MBOX_FIRMWARE_DONE set.  If however
 	that bit is not set, then the command isn't done so repeat the
-	read.
-
-	Next, read back 32 words and compare with the original
-	arugments.  Hopefully they will match.
+	read until it is set.
 
 	Finally, write out just the first word again, but set it to
 	0x0 this time (which probably means "idle").
 
 	*/
 
-	if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) {
+	if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) {
 		pvr2_trace(
 			PVR2_TRACE_ERROR_LEGS,
 			"Failed to write cx23416 command"
 			" - too many input arguments"
-			" (was given %u limit %u)",
-			arg_cnt_send,
-			(unsigned int)(sizeof(wrData)/sizeof(wrData[0])) - 4);
+			" (was given %u limit %lu)",
+			arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4);
 		return -EINVAL;
 	}
 
-	if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) {
+	if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) {
 		pvr2_trace(
 			PVR2_TRACE_ERROR_LEGS,
 			"Failed to write cx23416 command"
 			" - too many return arguments"
-			" (was given %u limit %u)",
-			arg_cnt_recv,
-			(unsigned int)(sizeof(rdData)/sizeof(rdData[0])) - 4);
+			" (was given %u limit %lu)",
+			arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4);
 		return -EINVAL;
 	}
 
 
 	LOCK_TAKE(hdw->ctl_lock); do {
 
+		retry_flag = 0;
+		try_count++;
+		ret = 0;
 		wrData[0] = 0;
 		wrData[1] = cmd;
 		wrData[2] = 0;
@@ -201,59 +219,74 @@
 		for (idx = 0; idx < arg_cnt_send; idx++) {
 			wrData[idx+4] = argp[idx];
 		}
-		for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) {
+		for (; idx < ARRAY_SIZE(wrData) - 4; idx++) {
 			wrData[idx+4] = 0;
 		}
 
-		ret = pvr2_encoder_write_words(hdw,wrData,idx);
+		ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,idx);
 		if (ret) break;
 		wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
-		ret = pvr2_encoder_write_words(hdw,wrData,1);
+		ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
 		if (ret) break;
 		poll_count = 0;
 		while (1) {
-			if (poll_count < 10000000) poll_count++;
-			ret = pvr2_encoder_read_words(hdw,!0,rdData,1);
-			if (ret) break;
+			poll_count++;
+			ret = pvr2_encoder_read_words(hdw,MBOX_BASE,rdData,
+						      arg_cnt_recv+4);
+			if (ret) {
+				break;
+			}
 			if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
 				break;
 			}
-			if (poll_count == 100) {
+			if (rdData[0] && (poll_count < 1000)) continue;
+			if (!rdData[0]) {
+				retry_flag = !0;
+				pvr2_trace(
+					PVR2_TRACE_ERROR_LEGS,
+					"Encoder timed out waiting for us"
+					"; arranging to retry");
+			} else {
 				pvr2_trace(
 					PVR2_TRACE_ERROR_LEGS,
 					"***WARNING*** device's encoder"
 					" appears to be stuck"
-					" (status=0%08x)",rdData[0]);
-				pvr2_trace(
-					PVR2_TRACE_ERROR_LEGS,
-					"Encoder command: 0x%02x",cmd);
-				for (idx = 4; idx < arg_cnt_send; idx++) {
-					pvr2_trace(
-						PVR2_TRACE_ERROR_LEGS,
-						"Encoder arg%d: 0x%08x",
-						idx-3,wrData[idx]);
-				}
-				pvr2_trace(
-					PVR2_TRACE_ERROR_LEGS,
-					"Giving up waiting."
-					"  It is likely that"
-					" this is a bad idea...");
-				ret = -EBUSY;
-				break;
+					" (status=0x%08x)",rdData[0]);
 			}
+			pvr2_trace(
+				PVR2_TRACE_ERROR_LEGS,
+				"Encoder command: 0x%02x",cmd);
+			for (idx = 4; idx < arg_cnt_send; idx++) {
+				pvr2_trace(
+					PVR2_TRACE_ERROR_LEGS,
+					"Encoder arg%d: 0x%08x",
+					idx-3,wrData[idx]);
+			}
+			ret = -EBUSY;
+			break;
 		}
-		if (ret) break;
+		if (retry_flag) {
+			if (try_count < 20) continue;
+			pvr2_trace(
+				PVR2_TRACE_ERROR_LEGS,
+				"Too many retries...");
+			ret = -EBUSY;
+		}
+		if (ret) {
+			pvr2_trace(
+				PVR2_TRACE_ERROR_LEGS,
+				"Giving up on command."
+				"  It is likely that"
+				" this is a bad idea...");
+			break;
+		}
 		wrData[0] = 0x7;
-		ret = pvr2_encoder_read_words(
-			hdw,0,rdData,
-			sizeof(rdData)/sizeof(rdData[0]));
-		if (ret) break;
 		for (idx = 0; idx < arg_cnt_recv; idx++) {
 			argp[idx] = rdData[idx+4];
 		}
 
 		wrData[0] = 0x0;
-		ret = pvr2_encoder_write_words(hdw,wrData,1);
+		ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
 		if (ret) break;
 
 	} while(0); LOCK_GIVE(hdw->ctl_lock);
@@ -269,13 +302,13 @@
 	unsigned int idx;
 	u32 data[12];
 
-	if (args > sizeof(data)/sizeof(data[0])) {
+	if (args > ARRAY_SIZE(data)) {
 		pvr2_trace(
 			PVR2_TRACE_ERROR_LEGS,
 			"Failed to write cx23416 command"
 			" - too many arguments"
-			" (was given %u limit %u)",
-			args,(unsigned int)(sizeof(data)/sizeof(data[0])));
+			" (was given %u limit %lu)",
+			args, (long unsigned) ARRAY_SIZE(data));
 		return -EINVAL;
 	}
 
@@ -288,6 +321,73 @@
 	return pvr2_encoder_cmd(hdw,cmd,args,0,data);
 }
 
+
+/* This implements some extra setup for the encoder that seems to be
+   specific to the PVR USB2 hardware. */
+int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
+{
+	int ret = 0;
+	int encMisc3Arg = 0;
+
+#if 0
+	/* This inexplicable bit happens in the Hauppage windows
+	   driver (for both 24xxx and 29xxx devices).  However I
+	   currently see no difference in behavior with or without
+	   this stuff.  Leave this here as a note of its existence,
+	   but don't use it. */
+	LOCK_TAKE(hdw->ctl_lock); do {
+		u32 dat[1];
+		dat[0] = 0x80000640;
+		pvr2_encoder_write_words(hdw,0x01fe,dat,1);
+		pvr2_encoder_write_words(hdw,0x023e,dat,1);
+	} while(0); LOCK_GIVE(hdw->ctl_lock);
+#endif
+
+	/* Mike Isely <isely@pobox.com> 26-Jan-2006 The windows driver
+	   sends the following list of ENC_MISC commands (for both
+	   24xxx and 29xxx devices).  Meanings are not entirely clear,
+	   however without the ENC_MISC(3,1) command then we risk
+	   random perpetual video corruption whenever the video input
+	   breaks up for a moment (like when switching channels). */
+
+
+#if 0
+	/* This ENC_MISC(5,0) command seems to hurt 29xxx sync
+	   performance on channel changes, but is not a problem on
+	   24xxx devices. */
+	ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
+#endif
+
+	/* This ENC_MISC(3,encMisc3Arg) command is critical - without
+	   it there will eventually be video corruption.  Also, the
+	   29xxx case is strange - the Windows driver is passing 1
+	   regardless of device type but if we have 1 for 29xxx device
+	   the video turns sluggish.  */
+	switch (hdw->hdw_type) {
+	case PVR2_HDW_TYPE_24XXX: encMisc3Arg = 1; break;
+	case PVR2_HDW_TYPE_29XXX: encMisc3Arg = 0; break;
+	default: break;
+	}
+	ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
+				 encMisc3Arg,0,0);
+
+	ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
+
+#if 0
+	/* This ENC_MISC(4,1) command is poisonous, so it is commented
+	   out.  But I'm leaving it here anyway to document its
+	   existence in the Windows driver.  The effect of this
+	   command is that apps displaying the stream become sluggish
+	   with stuttering video. */
+	ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
+#endif
+
+	ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
+	ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
+
+	return ret;
+}
+
 int pvr2_encoder_configure(struct pvr2_hdw *hdw)
 {
 	int ret;
@@ -302,6 +402,8 @@
 
 	ret = 0;
 
+	ret |= pvr2_encoder_prep_config(hdw);
+
 	if (!ret) ret = pvr2_encoder_vcmd(
 		hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
 		0xf0, 0xf0);
@@ -360,15 +462,22 @@
 	pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
 	pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
 
-	if (hdw->config == pvr2_config_vbi) {
+	pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
+			  hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
+
+	switch (hdw->config) {
+	case pvr2_config_vbi:
 		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 					   0x01,0x14);
-	} else if (hdw->config == pvr2_config_mpeg) {
+		break;
+	case pvr2_config_mpeg:
 		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 					   0,0x13);
-	} else {
+		break;
+	default: /* Unhandled cases for now */
 		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 					   0,0x13);
+		break;
 	}
 	if (!status) {
 		hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
@@ -383,15 +492,19 @@
 	/* mask all interrupts */
 	pvr2_write_register(hdw, 0x0048, 0xffffffff);
 
-	if (hdw->config == pvr2_config_vbi) {
+	switch (hdw->config) {
+	case pvr2_config_vbi:
 		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 					   0x01,0x01,0x14);
-	} else if (hdw->config == pvr2_config_mpeg) {
+		break;
+	case pvr2_config_mpeg:
 		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 					   0x01,0,0x13);
-	} else {
+		break;
+	default: /* Unhandled cases for now */
 		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 					   0x01,0,0x13);
+		break;
 	}
 
 	/* change some GPIO data */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
new file mode 100644
index 0000000..ffbc6d0
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
@@ -0,0 +1,62 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2007 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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
+ *
+ */
+
+#ifndef _PVRUSB2_FX2_CMD_H_
+#define _PVRUSB2_FX2_CMD_H_
+
+#define FX2CMD_MEM_WRITE_DWORD  0x01
+#define FX2CMD_MEM_READ_DWORD   0x02
+
+#define FX2CMD_MEM_READ_64BYTES 0x28
+
+#define FX2CMD_REG_WRITE        0x04
+#define FX2CMD_REG_READ         0x05
+#define FX2CMD_MEMSEL           0x06
+
+#define FX2CMD_I2C_WRITE        0x08
+#define FX2CMD_I2C_READ         0x09
+
+#define FX2CMD_GET_USB_SPEED    0x0b
+
+#define FX2CMD_STREAMING_ON     0x36
+#define FX2CMD_STREAMING_OFF    0x37
+
+#define FX2CMD_FWPOST1          0x52
+
+#define FX2CMD_POWER_OFF        0xdc
+#define FX2CMD_POWER_ON         0xde
+
+#define FX2CMD_DEEP_RESET       0xdd
+
+#define FX2CMD_GET_EEPROM_ADDR  0xeb
+#define FX2CMD_GET_IR_CODE      0xec
+
+#endif /* _PVRUSB2_FX2_CMD_H_ */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index 34b08fb..16bd741 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -60,6 +60,7 @@
 
 typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *);
 typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *);
+typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int);
 typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *);
 typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val);
 typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val,
@@ -83,6 +84,7 @@
 	pvr2_ctlf_get_value get_min_value;  /* Get minimum allowed value */
 	pvr2_ctlf_get_value get_max_value;  /* Get maximum allowed value */
 	pvr2_ctlf_set_value set_value;      /* Set its value */
+	pvr2_ctlf_check_value check_value;  /* Check that value is valid */
 	pvr2_ctlf_val_to_sym val_to_sym;    /* Custom convert value->symbol */
 	pvr2_ctlf_sym_to_val sym_to_val;    /* Custom convert symbol->value */
 	pvr2_ctlf_is_dirty is_dirty;        /* Return true if dirty */
@@ -135,17 +137,10 @@
 };
 
 
-struct pvr2_audio_stat {
-	void *ctxt;
-	void (*detach)(void *);
-	int (*status)(void *);
-};
-
 struct pvr2_decoder_ctrl {
 	void *ctxt;
 	void (*detach)(void *);
 	void (*enable)(void *,int);
-	int (*tuned)(void *);
 	void (*force_reset)(void *);
 };
 
@@ -212,7 +207,6 @@
 	/* Frequency table */
 	unsigned int freqTable[FREQTABLE_SIZE];
 	unsigned int freqProgSlot;
-	unsigned int freqSlot;
 
 	/* Stuff for handling low level control interaction with device */
 	struct mutex ctl_lock_mutex;
@@ -258,9 +252,17 @@
 	/* Tuner / frequency control stuff */
 	unsigned int tuner_type;
 	int tuner_updated;
-	unsigned int freqVal;
+	unsigned int freqValTelevision;  /* Current freq for tv mode */
+	unsigned int freqValRadio;       /* Current freq for radio mode */
+	unsigned int freqSlotTelevision; /* Current slot for tv mode */
+	unsigned int freqSlotRadio;      /* Current slot for radio mode */
+	unsigned int freqSelector;       /* 0=radio 1=television */
 	int freqDirty;
 
+	/* Current tuner info - this information is polled from the I2C bus */
+	struct v4l2_tuner tuner_signal_info;
+	int tuner_signal_stale;
+
 	/* Video standard handling */
 	v4l2_std_id std_mask_eeprom; // Hardware supported selections
 	v4l2_std_id std_mask_avail;  // Which standards we may select from
@@ -281,20 +283,17 @@
 	int unit_number;             /* ID for driver instance */
 	unsigned long serial_number; /* ID for hardware itself */
 
-	/* Minor number used by v4l logic (yes, this is a hack, as there should
-	   be no v4l junk here).  Probably a better way to do this. */
-	int v4l_minor_number;
+	/* Minor numbers used by v4l logic (yes, this is a hack, as there
+	   should be no v4l junk here).  Probably a better way to do this. */
+	int v4l_minor_number_video;
+	int v4l_minor_number_vbi;
+	int v4l_minor_number_radio;
 
 	/* Location of eeprom or a negative number if none */
 	int eeprom_addr;
 
 	enum pvr2_config config;
 
-	/* Information about what audio signal we're hearing */
-	int flag_stereo;
-	int flag_bilingual;
-	struct pvr2_audio_stat *audio_stat;
-
 	/* Control state needed for cx2341x module */
 	struct cx2341x_mpeg_params enc_cur_state;
 	struct cx2341x_mpeg_params enc_ctl_state;
@@ -327,6 +326,9 @@
 	unsigned int control_cnt;
 };
 
+/* This function gets the current frequency */
+unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *);
+
 #endif /* __PVRUSB2_HDW_INTERNAL_H */
 
 /*
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index d200496..a1ca0f5 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -36,6 +36,10 @@
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-encoder.h"
 #include "pvrusb2-debug.h"
+#include "pvrusb2-fx2-cmd.h"
+
+#define TV_MIN_FREQ     55250000L
+#define TV_MAX_FREQ    850000000L
 
 struct usb_device_id pvr2_device_table[] = {
 	[PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },
@@ -71,12 +75,10 @@
 
 static struct pvr2_string_table pvr2_client_lists[] = {
 	[PVR2_HDW_TYPE_29XXX] = {
-		pvr2_client_29xxx,
-		sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]),
+		pvr2_client_29xxx, ARRAY_SIZE(pvr2_client_29xxx)
 	},
 	[PVR2_HDW_TYPE_24XXX] = {
-		pvr2_client_24xxx,
-		sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]),
+		pvr2_client_24xxx, ARRAY_SIZE(pvr2_client_24xxx)
 	},
 };
 
@@ -160,9 +162,6 @@
 		.strid = "video_gop_closure",
 		.id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
 	},{
-		.strid = "video_pulldown",
-		.id = V4L2_CID_MPEG_VIDEO_PULLDOWN,
-	},{
 		.strid = "video_bitrate_mode",
 		.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
 	},{
@@ -212,7 +211,7 @@
 		.id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
 	}
 };
-#define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0]))
+#define MPEGDEF_COUNT ARRAY_SIZE(mpeg_ids)
 
 
 static const char *control_values_srate[] = {
@@ -255,10 +254,10 @@
 	[PVR2_SUBSYS_B_ENC_RUN] = "enc_run",
 };
 
+static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
 static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
 static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw);
 static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw);
-static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw);
 static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
 static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
 static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw);
@@ -272,8 +271,6 @@
 				unsigned int timeout,int probe_fl,
 				void *write_data,unsigned int write_len,
 				void *read_data,unsigned int read_len);
-static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res);
-static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res);
 
 static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp)
 {
@@ -289,8 +286,21 @@
 static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v)
 {
 	struct pvr2_hdw *hdw = cptr->hdw;
-	if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
-		hdw->freqTable[hdw->freqProgSlot-1] = v;
+	unsigned int slotId = hdw->freqProgSlot;
+	if ((slotId > 0) && (slotId <= FREQTABLE_SIZE)) {
+		hdw->freqTable[slotId-1] = v;
+		/* Handle side effects correctly - if we're tuned to this
+		   slot, then forgot the slot id relation since the stored
+		   frequency has been changed. */
+		if (hdw->freqSelector) {
+			if (hdw->freqSlotRadio == slotId) {
+				hdw->freqSlotRadio = 0;
+			}
+		} else {
+			if (hdw->freqSlotTelevision == slotId) {
+				hdw->freqSlotTelevision = 0;
+			}
+		}
 	}
 	return 0;
 }
@@ -312,28 +322,32 @@
 
 static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp)
 {
-	*vp = cptr->hdw->freqSlot;
+	struct pvr2_hdw *hdw = cptr->hdw;
+	*vp = hdw->freqSelector ? hdw->freqSlotRadio : hdw->freqSlotTelevision;
 	return 0;
 }
 
-static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int v)
+static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int slotId)
 {
 	unsigned freq = 0;
 	struct pvr2_hdw *hdw = cptr->hdw;
-	hdw->freqSlot = v;
-	if ((hdw->freqSlot > 0) && (hdw->freqSlot <= FREQTABLE_SIZE)) {
-		freq = hdw->freqTable[hdw->freqSlot-1];
+	if ((slotId < 0) || (slotId > FREQTABLE_SIZE)) return 0;
+	if (slotId > 0) {
+		freq = hdw->freqTable[slotId-1];
+		if (!freq) return 0;
+		pvr2_hdw_set_cur_freq(hdw,freq);
 	}
-	if (freq && (freq != hdw->freqVal)) {
-		hdw->freqVal = freq;
-		hdw->freqDirty = !0;
+	if (hdw->freqSelector) {
+		hdw->freqSlotRadio = slotId;
+	} else {
+		hdw->freqSlotTelevision = slotId;
 	}
 	return 0;
 }
 
 static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp)
 {
-	*vp = cptr->hdw->freqVal;
+	*vp = pvr2_hdw_get_cur_freq(cptr->hdw);
 	return 0;
 }
 
@@ -349,10 +363,7 @@
 
 static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
 {
-	struct pvr2_hdw *hdw = cptr->hdw;
-	hdw->freqVal = v;
-	hdw->freqDirty = !0;
-	hdw->freqSlot = 0;
+	pvr2_hdw_set_cur_freq(cptr->hdw,v);
 	return 0;
 }
 
@@ -378,6 +389,89 @@
 	return 0;
 }
 
+static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = cptr->hdw->input_val;
+	return 0;
+}
+
+static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
+{
+	struct pvr2_hdw *hdw = cptr->hdw;
+
+	if (hdw->input_val != v) {
+		hdw->input_val = v;
+		hdw->input_dirty = !0;
+	}
+
+	/* Handle side effects - if we switch to a mode that needs the RF
+	   tuner, then select the right frequency choice as well and mark
+	   it dirty. */
+	if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+		hdw->freqSelector = 0;
+		hdw->freqDirty = !0;
+	} else if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
+		hdw->freqSelector = 1;
+		hdw->freqDirty = !0;
+	}
+	return 0;
+}
+
+static int ctrl_isdirty_input(struct pvr2_ctrl *cptr)
+{
+	return cptr->hdw->input_dirty != 0;
+}
+
+static void ctrl_cleardirty_input(struct pvr2_ctrl *cptr)
+{
+	cptr->hdw->input_dirty = 0;
+}
+
+
+static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp)
+{
+	unsigned long fv;
+	struct pvr2_hdw *hdw = cptr->hdw;
+	if (hdw->tuner_signal_stale) {
+		pvr2_i2c_core_status_poll(hdw);
+	}
+	fv = hdw->tuner_signal_info.rangehigh;
+	if (!fv) {
+		/* Safety fallback */
+		*vp = TV_MAX_FREQ;
+		return 0;
+	}
+	if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+		fv = (fv * 125) / 2;
+	} else {
+		fv = fv * 62500;
+	}
+	*vp = fv;
+	return 0;
+}
+
+static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp)
+{
+	unsigned long fv;
+	struct pvr2_hdw *hdw = cptr->hdw;
+	if (hdw->tuner_signal_stale) {
+		pvr2_i2c_core_status_poll(hdw);
+	}
+	fv = hdw->tuner_signal_info.rangelow;
+	if (!fv) {
+		/* Safety fallback */
+		*vp = TV_MIN_FREQ;
+		return 0;
+	}
+	if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+		fv = (fv * 125) / 2;
+	} else {
+		fv = fv * 62500;
+	}
+	*vp = fv;
+	return 0;
+}
+
 static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
 {
 	return cptr->hdw->enc_stale != 0;
@@ -534,8 +628,32 @@
 
 static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
 {
-	*vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) &
-		PVR2_SIGNAL_OK) ? 1 : 0);
+	struct pvr2_hdw *hdw = cptr->hdw;
+	pvr2_i2c_core_status_poll(hdw);
+	*vp = hdw->tuner_signal_info.signal;
+	return 0;
+}
+
+static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	int val = 0;
+	unsigned int subchan;
+	struct pvr2_hdw *hdw = cptr->hdw;
+	pvr2_i2c_core_status_poll(hdw);
+	subchan = hdw->tuner_signal_info.rxsubchans;
+	if (subchan & V4L2_TUNER_SUB_MONO) {
+		val |= (1 << V4L2_TUNER_MODE_MONO);
+	}
+	if (subchan & V4L2_TUNER_SUB_STEREO) {
+		val |= (1 << V4L2_TUNER_MODE_STEREO);
+	}
+	if (subchan & V4L2_TUNER_SUB_LANG1) {
+		val |= (1 << V4L2_TUNER_MODE_LANG1);
+	}
+	if (subchan & V4L2_TUNER_SUB_LANG2) {
+		val |= (1 << V4L2_TUNER_MODE_LANG2);
+	}
+	*vp = val;
 	return 0;
 }
 
@@ -604,7 +722,7 @@
 
 #define DEFENUM(tab) \
 	.type = pvr2_ctl_enum, \
-	.def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \
+	.def.type_enum.count = ARRAY_SIZE(tab), \
 	.def.type_enum.value_names = tab
 
 #define DEFBOOL \
@@ -641,15 +759,11 @@
 VCREATE_FUNCS(bass)
 VCREATE_FUNCS(treble)
 VCREATE_FUNCS(mute)
-VCREATE_FUNCS(input)
 VCREATE_FUNCS(audiomode)
 VCREATE_FUNCS(res_hor)
 VCREATE_FUNCS(res_ver)
 VCREATE_FUNCS(srate)
 
-#define MIN_FREQ 55250000L
-#define MAX_FREQ 850000000L
-
 /* Table definition of all controls which can be manipulated */
 static const struct pvr2_ctl_info control_defs[] = {
 	{
@@ -684,7 +798,7 @@
 		.v4l_id = V4L2_CID_AUDIO_VOLUME,
 		.desc = "Volume",
 		.name = "volume",
-		.default_value = 65535,
+		.default_value = 62000,
 		DEFREF(volume),
 		DEFINT(0,65535),
 	},{
@@ -758,12 +872,16 @@
 		.desc = "Tuner Frequency (Hz)",
 		.name = "frequency",
 		.internal_id = PVR2_CID_FREQUENCY,
-		.default_value = 175250000L,
+		.default_value = 0,
 		.set_value = ctrl_freq_set,
 		.get_value = ctrl_freq_get,
 		.is_dirty = ctrl_freq_is_dirty,
 		.clear_dirty = ctrl_freq_clear_dirty,
-		DEFINT(MIN_FREQ,MAX_FREQ),
+		DEFINT(0,0),
+		/* Hook in check for input value (tv/radio) and adjust
+		   max/min values accordingly */
+		.get_max_value = ctrl_freq_max_get,
+		.get_min_value = ctrl_freq_min_get,
 	},{
 		.desc = "Channel",
 		.name = "channel",
@@ -775,7 +893,11 @@
 		.name = "freq_table_value",
 		.set_value = ctrl_channelfreq_set,
 		.get_value = ctrl_channelfreq_get,
-		DEFINT(MIN_FREQ,MAX_FREQ),
+		DEFINT(0,0),
+		/* Hook in check for input value (tv/radio) and adjust
+		   max/min values accordingly */
+		.get_max_value = ctrl_freq_max_get,
+		.get_min_value = ctrl_freq_min_get,
 	},{
 		.desc = "Channel Program ID",
 		.name = "freq_table_channel",
@@ -796,7 +918,20 @@
 		.desc = "Signal Present",
 		.name = "signal_present",
 		.get_value = ctrl_signal_get,
-		DEFBOOL,
+		DEFINT(0,65535),
+	},{
+		.desc = "Audio Modes Present",
+		.name = "audio_modes_present",
+		.get_value = ctrl_audio_modes_present_get,
+		/* For this type we "borrow" the V4L2_TUNER_MODE enum from
+		   v4l.  Nothing outside of this module cares about this,
+		   but I reuse it in order to also reuse the
+		   control_values_audiomode string table. */
+		DEFMASK(((1 << V4L2_TUNER_MODE_MONO)|
+			 (1 << V4L2_TUNER_MODE_STEREO)|
+			 (1 << V4L2_TUNER_MODE_LANG1)|
+			 (1 << V4L2_TUNER_MODE_LANG2)),
+			control_values_audiomode),
 	},{
 		.desc = "Video Standards Available Mask",
 		.name = "video_standard_mask_available",
@@ -846,7 +981,7 @@
 	}
 };
 
-#define CTRLDEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0]))
+#define CTRLDEF_COUNT ARRAY_SIZE(control_defs)
 
 
 const char *pvr2_config_get_name(enum pvr2_config cfg)
@@ -855,7 +990,8 @@
 	case pvr2_config_empty: return "empty";
 	case pvr2_config_mpeg: return "mpeg";
 	case pvr2_config_vbi: return "vbi";
-	case pvr2_config_radio: return "radio";
+	case pvr2_config_pcm: return "pcm";
+	case pvr2_config_rawvideo: return "raw video";
 	}
 	return "<unknown>";
 }
@@ -872,6 +1008,40 @@
 	return hdw->serial_number;
 }
 
+unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
+{
+	return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio;
+}
+
+/* Set the currently tuned frequency and account for all possible
+   driver-core side effects of this action. */
+void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
+{
+	if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+		if (hdw->freqSelector) {
+			/* Swing over to radio frequency selection */
+			hdw->freqSelector = 0;
+			hdw->freqDirty = !0;
+		}
+		if (hdw->freqValRadio != val) {
+			hdw->freqValRadio = val;
+			hdw->freqSlotRadio = 0;
+			hdw->freqDirty = !0;
+		}
+	} else {
+		if (!(hdw->freqSelector)) {
+			/* Swing over to television frequency selection */
+			hdw->freqSelector = 1;
+			hdw->freqDirty = !0;
+		}
+		if (hdw->freqValTelevision != val) {
+			hdw->freqValTelevision = val;
+			hdw->freqSlotTelevision = 0;
+			hdw->freqDirty = !0;
+		}
+	}
+}
+
 int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
 {
 	return hdw->unit_number;
@@ -960,12 +1130,10 @@
 	};
 	static const struct pvr2_string_table fw_file_defs[] = {
 		[PVR2_HDW_TYPE_29XXX] = {
-			fw_files_29xxx,
-			sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]),
+			fw_files_29xxx, ARRAY_SIZE(fw_files_29xxx)
 		},
 		[PVR2_HDW_TYPE_24XXX] = {
-			fw_files_24xxx,
-			sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]),
+			fw_files_24xxx, ARRAY_SIZE(fw_files_24xxx)
 		},
 	};
 	hdw->fw1_state = FW1_STATE_FAILED; // default result
@@ -1041,7 +1209,7 @@
 {
 	const struct firmware *fw_entry = NULL;
 	void  *fw_ptr;
-	unsigned int pipe, fw_len, fw_done;
+	unsigned int pipe, fw_len, fw_done, bcnt, icnt;
 	int actual_length;
 	int ret = 0;
 	int fwidx;
@@ -1052,8 +1220,7 @@
 	trace_firmware("pvr2_upload_firmware2");
 
 	ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder",
-				   sizeof(fw_files)/sizeof(fw_files[0]),
-				   fw_files);
+				   ARRAY_SIZE(fw_files), fw_files);
 	if (ret < 0) return ret;
 	fwidx = ret;
 	ret = 0;
@@ -1079,8 +1246,13 @@
 	ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
 	ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
 	ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
-	ret |= pvr2_write_u8(hdw, 0x52, 0);
-	ret |= pvr2_write_u16(hdw, 0x0600, 0);
+	LOCK_TAKE(hdw->ctl_lock); do {
+		hdw->cmd_buffer[0] = FX2CMD_FWPOST1;
+		ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0);
+		hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
+		hdw->cmd_buffer[1] = 0;
+		ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0);
+	} while (0); LOCK_GIVE(hdw->ctl_lock);
 
 	if (ret) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
@@ -1093,11 +1265,11 @@
 
 	fw_len = fw_entry->size;
 
-	if (fw_len % FIRMWARE_CHUNK_SIZE) {
+	if (fw_len % sizeof(u32)) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 			   "size of %s firmware"
-			   " must be a multiple of 8192B",
-			   fw_files[fwidx]);
+			   " must be a multiple of %u bytes",
+			   fw_files[fwidx],sizeof(u32));
 		release_firmware(fw_entry);
 		return -1;
 	}
@@ -1112,18 +1284,21 @@
 
 	pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
 
-	for (fw_done = 0 ; (fw_done < fw_len) && !ret ;
-	     fw_done += FIRMWARE_CHUNK_SIZE ) {
-		int i;
-		memcpy(fw_ptr, fw_entry->data + fw_done, FIRMWARE_CHUNK_SIZE);
-		/* Usbsnoop log  shows that we must swap bytes... */
-		for (i = 0; i < FIRMWARE_CHUNK_SIZE/4 ; i++)
-			((u32 *)fw_ptr)[i] = ___swab32(((u32 *)fw_ptr)[i]);
+	fw_done = 0;
+	for (fw_done = 0; fw_done < fw_len;) {
+		bcnt = fw_len - fw_done;
+		if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE;
+		memcpy(fw_ptr, fw_entry->data + fw_done, bcnt);
+		/* Usbsnoop log shows that we must swap bytes... */
+		for (icnt = 0; icnt < bcnt/4 ; icnt++)
+			((u32 *)fw_ptr)[icnt] =
+				___swab32(((u32 *)fw_ptr)[icnt]);
 
-		ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,
-				    FIRMWARE_CHUNK_SIZE,
+		ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt,
 				    &actual_length, HZ);
-		ret |= (actual_length != FIRMWARE_CHUNK_SIZE);
+		ret |= (actual_length != bcnt);
+		if (ret) break;
+		fw_done += bcnt;
 	}
 
 	trace_firmware("upload of %s : %i / %i ",
@@ -1142,7 +1317,11 @@
 
 	ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
 	ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
-	ret |= pvr2_write_u16(hdw, 0x0600, 0);
+	LOCK_TAKE(hdw->ctl_lock); do {
+		hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
+		hdw->cmd_buffer[1] = 0;
+		ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,0,0);
+	} while (0); LOCK_GIVE(hdw->ctl_lock);
 
 	if (ret) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
@@ -1479,7 +1658,7 @@
 	   firmware needs be loaded. */
 	int result;
 	LOCK_TAKE(hdw->ctl_lock); do {
-		hdw->cmd_buffer[0] = 0xeb;
+		hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR;
 		result = pvr2_send_request_ex(hdw,HZ*1,!0,
 					   hdw->cmd_buffer,1,
 					   hdw->cmd_buffer,1);
@@ -1611,6 +1790,16 @@
 		cptr->info->set_value(cptr,~0,cptr->info->default_value);
 	}
 
+	/* Set up special default values for the television and radio
+	   frequencies here.  It's not really important what these defaults
+	   are, but I set them to something usable in the Chicago area just
+	   to make driver testing a little easier. */
+
+	/* US Broadcast channel 7 (175.25 MHz) */
+	hdw->freqValTelevision = 175250000L;
+	/* 104.3 MHz, a usable FM station for my area */
+	hdw->freqValRadio = 104300000L;
+
 	// Do not use pvr2_reset_ctl_endpoints() here.  It is not
 	// thread-safe against the normal pvr2_send_request() mechanism.
 	// (We should make it thread safe).
@@ -1750,26 +1939,24 @@
 	struct pvr2_ctl_info *ciptr;
 
 	hdw_type = devid - pvr2_device_table;
-	if (hdw_type >=
-	    sizeof(pvr2_device_names)/sizeof(pvr2_device_names[0])) {
+	if (hdw_type >= ARRAY_SIZE(pvr2_device_names)) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 			   "Bogus device type of %u reported",hdw_type);
 		return NULL;
 	}
 
-	hdw = kmalloc(sizeof(*hdw),GFP_KERNEL);
+	hdw = kzalloc(sizeof(*hdw),GFP_KERNEL);
 	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
 		   hdw,pvr2_device_names[hdw_type]);
 	if (!hdw) goto fail;
-	memset(hdw,0,sizeof(*hdw));
+	hdw->tuner_signal_stale = !0;
 	cx2341x_fill_defaults(&hdw->enc_ctl_state);
 
 	hdw->control_cnt = CTRLDEF_COUNT;
 	hdw->control_cnt += MPEGDEF_COUNT;
-	hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
+	hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
 				GFP_KERNEL);
 	if (!hdw->controls) goto fail;
-	memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * hdw->control_cnt);
 	hdw->hdw_type = hdw_type;
 	for (idx = 0; idx < hdw->control_cnt; idx++) {
 		cptr = hdw->controls + idx;
@@ -1783,11 +1970,9 @@
 		cptr->info = control_defs+idx;
 	}
 	/* Define and configure additional controls from cx2341x module. */
-	hdw->mpeg_ctrl_info = kmalloc(
+	hdw->mpeg_ctrl_info = kzalloc(
 		sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
 	if (!hdw->mpeg_ctrl_info) goto fail;
-	memset(hdw->mpeg_ctrl_info,0,
-	       sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT);
 	for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
 		cptr = hdw->controls + idx + CTRLDEF_COUNT;
 		ciptr = &(hdw->mpeg_ctrl_info[idx].info);
@@ -1872,7 +2057,9 @@
 
 	hdw->eeprom_addr = -1;
 	hdw->unit_number = -1;
-	hdw->v4l_minor_number = -1;
+	hdw->v4l_minor_number_video = -1;
+	hdw->v4l_minor_number_vbi = -1;
+	hdw->v4l_minor_number_radio = -1;
 	hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
 	if (!hdw->ctl_write_buffer) goto fail;
 	hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
@@ -1929,10 +2116,10 @@
 	if (hdw) {
 		usb_free_urb(hdw->ctl_read_urb);
 		usb_free_urb(hdw->ctl_write_urb);
-		if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);
-		if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);
-		if (hdw->controls) kfree(hdw->controls);
-		if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
+		kfree(hdw->ctl_read_buffer);
+		kfree(hdw->ctl_write_buffer);
+		kfree(hdw->controls);
+		kfree(hdw->mpeg_ctrl_info);
 		kfree(hdw);
 	}
 	return NULL;
@@ -1982,9 +2169,6 @@
 		pvr2_stream_destroy(hdw->vid_stream);
 		hdw->vid_stream = NULL;
 	}
-	if (hdw->audio_stat) {
-		hdw->audio_stat->detach(hdw->audio_stat->ctxt);
-	}
 	if (hdw->decoder_ctrl) {
 		hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);
 	}
@@ -1997,10 +2181,10 @@
 			unit_pointers[hdw->unit_number] = NULL;
 		}
 	} while (0); up(&pvr2_unit_sem);
-	if (hdw->controls) kfree(hdw->controls);
-	if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
-	if (hdw->std_defs) kfree(hdw->std_defs);
-	if (hdw->std_enum_names) kfree(hdw->std_enum_names);
+	kfree(hdw->controls);
+	kfree(hdw->mpeg_ctrl_info);
+	kfree(hdw->std_defs);
+	kfree(hdw->std_enum_names);
 	kfree(hdw);
 }
 
@@ -2210,10 +2394,9 @@
 		cptr = hdw->controls + idx;
 		if (cptr->info->is_dirty == 0) continue;
 		if (!cptr->info->is_dirty(cptr)) continue;
-		if (!commit_flag) {
-			commit_flag = !0;
-		}
+		commit_flag = !0;
 
+		if (!(pvrusb2_debug & PVR2_TRACE_CTL)) continue;
 		bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ",
 				 cptr->info->name);
 		value = 0;
@@ -2263,6 +2446,13 @@
 		stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
 	}
 
+	if (hdw->input_dirty) {
+		/* pk: If input changes to or from radio, then the encoder
+		   needs to be restarted (for ENC_MUTE_VIDEO to work) */
+		stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
+	}
+
+
 	if (hdw->srate_dirty) {
 		/* Write new sample rate into control structure since
 		 * the master copy is stale.  We must track srate
@@ -2343,39 +2533,11 @@
 }
 
 
-/* Return bit mask indicating signal status */
-static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw)
-{
-	unsigned int msk = 0;
-	switch (hdw->input_val) {
-	case PVR2_CVAL_INPUT_TV:
-	case PVR2_CVAL_INPUT_RADIO:
-		if (hdw->decoder_ctrl &&
-		    hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) {
-			msk |= PVR2_SIGNAL_OK;
-			if (hdw->audio_stat &&
-			    hdw->audio_stat->status(hdw->audio_stat->ctxt)) {
-				if (hdw->flag_stereo) {
-					msk |= PVR2_SIGNAL_STEREO;
-				}
-				if (hdw->flag_bilingual) {
-					msk |= PVR2_SIGNAL_SAP;
-				}
-			}
-		}
-		break;
-	default:
-		msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO;
-	}
-	return msk;
-}
-
-
 int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
 {
 	int result;
 	LOCK_TAKE(hdw->ctl_lock); do {
-		hdw->cmd_buffer[0] = 0x0b;
+		hdw->cmd_buffer[0] = FX2CMD_GET_USB_SPEED;
 		result = pvr2_send_request(hdw,
 					   hdw->cmd_buffer,1,
 					   hdw->cmd_buffer,1);
@@ -2386,14 +2548,25 @@
 }
 
 
-/* Return bit mask indicating signal status */
-unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw)
+/* Execute poll of tuner status */
+void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
 {
-	unsigned int msk = 0;
 	LOCK_TAKE(hdw->big_lock); do {
-		msk = pvr2_hdw_get_signal_status_internal(hdw);
+		pvr2_i2c_core_status_poll(hdw);
 	} while (0); LOCK_GIVE(hdw->big_lock);
-	return msk;
+}
+
+
+/* Return information about the tuner */
+int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp)
+{
+	LOCK_TAKE(hdw->big_lock); do {
+		if (hdw->tuner_signal_stale) {
+			pvr2_i2c_core_status_poll(hdw);
+		}
+		memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner));
+	} while (0); LOCK_GIVE(hdw->big_lock);
+	return 0;
 }
 
 
@@ -2442,14 +2615,12 @@
 		pvr2_trace(PVR2_TRACE_FIRMWARE,
 			   "Preparing to suck out CPU firmware");
 		hdw->fw_size = 0x2000;
-		hdw->fw_buffer = kmalloc(hdw->fw_size,GFP_KERNEL);
+		hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL);
 		if (!hdw->fw_buffer) {
 			hdw->fw_size = 0;
 			break;
 		}
 
-		memset(hdw->fw_buffer,0,hdw->fw_size);
-
 		/* We have to hold the CPU during firmware upload. */
 		pvr2_hdw_cpureset_assert(hdw,1);
 
@@ -2513,16 +2684,28 @@
 }
 
 
-int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw)
+int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw,
+				  enum pvr2_v4l_type index)
 {
-	return hdw->v4l_minor_number;
+	switch (index) {
+	case pvr2_v4l_type_video: return hdw->v4l_minor_number_video;
+	case pvr2_v4l_type_vbi: return hdw->v4l_minor_number_vbi;
+	case pvr2_v4l_type_radio: return hdw->v4l_minor_number_radio;
+	default: return -1;
+	}
 }
 
 
-/* Store the v4l minor device number */
-void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,int v)
+/* Store a v4l minor device number */
+void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,
+				     enum pvr2_v4l_type index,int v)
 {
-	hdw->v4l_minor_number = v;
+	switch (index) {
+	case pvr2_v4l_type_video: hdw->v4l_minor_number_video = v;
+	case pvr2_v4l_type_vbi: hdw->v4l_minor_number_vbi = v;
+	case pvr2_v4l_type_radio: hdw->v4l_minor_number_radio = v;
+	default: break;
+	}
 }
 
 
@@ -2804,7 +2987,7 @@
 
 	LOCK_TAKE(hdw->ctl_lock);
 
-	hdw->cmd_buffer[0] = 0x04;  /* write register prefix */
+	hdw->cmd_buffer[0] = FX2CMD_REG_WRITE;  /* write register prefix */
 	PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data);
 	hdw->cmd_buffer[5] = 0;
 	hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
@@ -2825,7 +3008,7 @@
 
 	LOCK_TAKE(hdw->ctl_lock);
 
-	hdw->cmd_buffer[0] = 0x05;  /* read register prefix */
+	hdw->cmd_buffer[0] = FX2CMD_REG_READ;  /* read register prefix */
 	hdw->cmd_buffer[1] = 0;
 	hdw->cmd_buffer[2] = 0;
 	hdw->cmd_buffer[3] = 0;
@@ -2843,39 +3026,6 @@
 }
 
 
-static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res)
-{
-	int ret;
-
-	LOCK_TAKE(hdw->ctl_lock);
-
-	hdw->cmd_buffer[0] = (data >> 8) & 0xff;
-	hdw->cmd_buffer[1] = data & 0xff;
-
-	ret = pvr2_send_request(hdw, hdw->cmd_buffer, 2, hdw->cmd_buffer, res);
-
-	LOCK_GIVE(hdw->ctl_lock);
-
-	return ret;
-}
-
-
-static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res)
-{
-	int ret;
-
-	LOCK_TAKE(hdw->ctl_lock);
-
-	hdw->cmd_buffer[0] = data;
-
-	ret = pvr2_send_request(hdw, hdw->cmd_buffer, 1, hdw->cmd_buffer, res);
-
-	LOCK_GIVE(hdw->ctl_lock);
-
-	return ret;
-}
-
-
 static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw)
 {
 	if (!hdw->flag_ok) return;
@@ -2949,7 +3099,7 @@
 	LOCK_TAKE(hdw->ctl_lock); do {
 		pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
 		hdw->flag_ok = !0;
-		hdw->cmd_buffer[0] = 0xdd;
+		hdw->cmd_buffer[0] = FX2CMD_DEEP_RESET;
 		status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
 	} while (0); LOCK_GIVE(hdw->ctl_lock);
 	return status;
@@ -2961,7 +3111,7 @@
 	int status;
 	LOCK_TAKE(hdw->ctl_lock); do {
 		pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup");
-		hdw->cmd_buffer[0] = 0xde;
+		hdw->cmd_buffer[0] = FX2CMD_POWER_ON;
 		status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
 	} while (0); LOCK_GIVE(hdw->ctl_lock);
 	return status;
@@ -2994,7 +3144,8 @@
 {
 	int status;
 	LOCK_TAKE(hdw->ctl_lock); do {
-		hdw->cmd_buffer[0] = (runFl ? 0x36 : 0x37);
+		hdw->cmd_buffer[0] =
+			(runFl ? FX2CMD_STREAMING_ON : FX2CMD_STREAMING_OFF);
 		status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
 	} while (0); LOCK_GIVE(hdw->ctl_lock);
 	if (!status) {
@@ -3093,7 +3244,7 @@
 {
 	int result;
 	LOCK_TAKE(hdw->ctl_lock); do {
-		hdw->cmd_buffer[0] = 0xeb;
+		hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR;
 		result = pvr2_send_request(hdw,
 					   hdw->cmd_buffer,1,
 					   hdw->cmd_buffer,1);
@@ -3105,7 +3256,7 @@
 
 
 int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
-			     u32 chip_id,unsigned long reg_id,
+			     u32 chip_id, u64 reg_id,
 			     int setFl,u32 *val_ptr)
 {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -3115,6 +3266,8 @@
 	int stat = 0;
 	int okFl = 0;
 
+	if (!capable(CAP_SYS_ADMIN)) return -EPERM;
+
 	req.i2c_id = chip_id;
 	req.reg = reg_id;
 	if (setFl) req.val = *val_ptr;
@@ -3123,8 +3276,8 @@
 			cp = list_entry(item,struct pvr2_i2c_client,list);
 			if (cp->client->driver->id != chip_id) continue;
 			stat = pvr2_i2c_client_cmd(
-				cp,(setFl ? VIDIOC_INT_S_REGISTER :
-				    VIDIOC_INT_G_REGISTER),&req);
+				cp,(setFl ? VIDIOC_DBG_S_REGISTER :
+				    VIDIOC_DBG_G_REGISTER),&req);
 			if (!setFl) *val_ptr = req.val;
 			okFl = !0;
 			break;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index 29979bb..566a8ef 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -44,12 +44,6 @@
 #define PVR2_CVAL_INPUT_COMPOSITE 2
 #define PVR2_CVAL_INPUT_RADIO 3
 
-/* Values that pvr2_hdw_get_signal_status() returns */
-#define PVR2_SIGNAL_OK     0x0001
-#define PVR2_SIGNAL_STEREO 0x0002
-#define PVR2_SIGNAL_SAP    0x0004
-
-
 /* Subsystem definitions - these are various pieces that can be
    independently stopped / started.  Usually you don't want to mess with
    this directly (let the driver handle things itself), but it is useful
@@ -72,10 +66,17 @@
 	PVR2_SUBSYS_RUN_ALL )
 
 enum pvr2_config {
-	pvr2_config_empty,
-	pvr2_config_mpeg,
-	pvr2_config_vbi,
-	pvr2_config_radio,
+	pvr2_config_empty,    /* No configuration */
+	pvr2_config_mpeg,     /* Encoded / compressed video */
+	pvr2_config_vbi,      /* Standard vbi info */
+	pvr2_config_pcm,      /* Audio raw pcm stream */
+	pvr2_config_rawvideo, /* Video raw frames */
+};
+
+enum pvr2_v4l_type {
+	pvr2_v4l_type_video,
+	pvr2_v4l_type_vbi,
+	pvr2_v4l_type_radio,
 };
 
 const char *pvr2_config_get_name(enum pvr2_config);
@@ -148,8 +149,11 @@
 /* Return name for this driver instance */
 const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
 
-/* Return PVR2_SIGNAL_XXXX bit mask indicating signal status */
-unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *);
+/* Mark tuner status stale so that it will be re-fetched */
+void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *);
+
+/* Return information about the tuner */
+int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *);
 
 /* Query device and see if it thinks it is on a high-speed USB link */
 int pvr2_hdw_is_hsm(struct pvr2_hdw *);
@@ -205,11 +209,12 @@
 int pvr2_hdw_cpufw_get(struct pvr2_hdw *,unsigned int offs,
 		       char *buf,unsigned int cnt);
 
-/* Retrieve previously stored v4l minor device number */
-int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *);
+/* Retrieve a previously stored v4l minor device number */
+int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *,enum pvr2_v4l_type index);
 
-/* Store the v4l minor device number */
-void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,int);
+/* Store a v4l minor device number */
+void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,
+				     enum pvr2_v4l_type index,int);
 
 /* Direct read/write access to chip's registers:
    chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx)
@@ -217,7 +222,7 @@
    setFl   - true to set the register, false to read it
    val_ptr - storage location for source / result. */
 int pvr2_hdw_register_access(struct pvr2_hdw *,
-			     u32 chip_id,unsigned long reg_id,
+			     u32 chip_id,u64 reg_id,
 			     int setFl,u32 *val_ptr);
 
 /* The following entry points are all lower level things you normally don't
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
index 0512166..4977376 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
@@ -33,15 +33,17 @@
 #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
 
 #define OP_STANDARD 0
-#define OP_BCSH 1
-#define OP_VOLUME 2
-#define OP_FREQ 3
-#define OP_AUDIORATE 4
-#define OP_SIZE 5
-#define OP_LOG 6
+#define OP_AUDIOMODE 1
+#define OP_BCSH 2
+#define OP_VOLUME 3
+#define OP_FREQ 4
+#define OP_AUDIORATE 5
+#define OP_SIZE 6
+#define OP_LOG 7
 
 static const struct pvr2_i2c_op * const ops[] = {
 	[OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
+	[OP_AUDIOMODE] = &pvr2_i2c_op_v4l2_audiomode,
 	[OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
 	[OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
 	[OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
@@ -54,11 +56,13 @@
 	int id;
 	id = cp->client->driver->id;
 	cp->ctl_mask = ((1 << OP_STANDARD) |
+			(1 << OP_AUDIOMODE) |
 			(1 << OP_BCSH) |
 			(1 << OP_VOLUME) |
 			(1 << OP_FREQ) |
 			(1 << OP_SIZE) |
 			(1 << OP_LOG));
+	cp->status_poll = pvr2_v4l2_cmd_status_poll;
 
 	if (id == I2C_DRIVERID_MSP3400) {
 		if (pvr2_i2c_msp3400_setup(hdw,cp)) {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
index 05ea17a..c650e02 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
@@ -24,22 +24,26 @@
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-debug.h"
 #include <linux/videodev2.h>
-
+#include <media/v4l2-common.h>
 
 static void set_standard(struct pvr2_hdw *hdw)
 {
-	v4l2_std_id vs;
-	vs = hdw->std_mask_cur;
-	pvr2_trace(PVR2_TRACE_CHIPS,
-		   "i2c v4l2 set_standard(0x%llx)",(long long unsigned)vs);
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_standard");
 
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
+	if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+		pvr2_i2c_core_cmd(hdw,AUDC_SET_RADIO,NULL);
+	} else {
+		v4l2_std_id vs;
+		vs = hdw->std_mask_cur;
+		pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
+	}
+	hdw->tuner_signal_stale = !0;
 }
 
 
 static int check_standard(struct pvr2_hdw *hdw)
 {
-	return hdw->std_dirty != 0;
+	return (hdw->input_dirty != 0) || (hdw->std_dirty != 0);
 }
 
 
@@ -136,16 +140,53 @@
 };
 
 
+static void set_audiomode(struct pvr2_hdw *hdw)
+{
+	struct v4l2_tuner vt;
+	memset(&vt,0,sizeof(vt));
+	vt.audmode = hdw->audiomode_val;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_TUNER,&vt);
+}
+
+
+static int check_audiomode(struct pvr2_hdw *hdw)
+{
+	return (hdw->input_dirty ||
+		hdw->audiomode_dirty);
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode = {
+	.check = check_audiomode,
+	.update = set_audiomode,
+	.name = "v4l2_audiomode",
+};
+
+
 static void set_frequency(struct pvr2_hdw *hdw)
 {
 	unsigned long fv;
 	struct v4l2_frequency freq;
-	fv = hdw->freqVal;
+	fv = pvr2_hdw_get_cur_freq(hdw);
 	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv);
+	if (hdw->tuner_signal_stale) {
+		pvr2_i2c_core_status_poll(hdw);
+	}
 	memset(&freq,0,sizeof(freq));
-	freq.frequency = fv / 62500;
+	if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+		// ((fv * 1000) / 62500)
+		freq.frequency = (fv * 2) / 125;
+	} else {
+		freq.frequency = fv / 62500;
+	}
+	/* tuner-core currently doesn't seem to care about this, but
+	   let's set it anyway for completeness. */
+	if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+		freq.type = V4L2_TUNER_RADIO;
+	} else {
+		freq.type = V4L2_TUNER_ANALOG_TV;
+	}
 	freq.tuner = 0;
-	freq.type = V4L2_TUNER_ANALOG_TV;
 	pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq);
 }
 
@@ -221,6 +262,12 @@
 }
 
 
+void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp)
+{
+	pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info);
+}
+
+
 /*
   Stuff for Emacs to see, in order to encourage consistent editing style:
   *** Local Variables: ***
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
index ecabddb..c838df6 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
@@ -26,13 +26,16 @@
 #include "pvrusb2-i2c-core.h"
 
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;
 
 void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int);
+void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *);
 
 #endif /* __PVRUSB2_CMD_V4L2_H */
 
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index f9bb41d..58fc3c7 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -22,6 +22,7 @@
 #include "pvrusb2-i2c-core.h"
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-debug.h"
+#include "pvrusb2-fx2-cmd.h"
 
 #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
 
@@ -66,7 +67,7 @@
 	memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
 
 	/* Set up command buffer for an I2C write */
-	hdw->cmd_buffer[0] = 0x08;      /* write prefix */
+	hdw->cmd_buffer[0] = FX2CMD_I2C_WRITE;      /* write prefix */
 	hdw->cmd_buffer[1] = i2c_addr;  /* i2c addr of chip */
 	hdw->cmd_buffer[2] = length;    /* length of what follows */
 	if (length) memcpy(hdw->cmd_buffer + 3, data, length);
@@ -128,7 +129,7 @@
 	memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
 
 	/* Set up command buffer for an I2C write followed by a read */
-	hdw->cmd_buffer[0] = 0x09;  /* read prefix */
+	hdw->cmd_buffer[0] = FX2CMD_I2C_READ;  /* read prefix */
 	hdw->cmd_buffer[1] = dlen;  /* arg length */
 	hdw->cmd_buffer[2] = rlen;  /* answer length. Device will send one
 				       more byte (status). */
@@ -221,7 +222,7 @@
 
 	/* Issue a command to the FX2 to read the IR receiver. */
 	LOCK_TAKE(hdw->ctl_lock); do {
-		hdw->cmd_buffer[0] = 0xec;
+		hdw->cmd_buffer[0] = FX2CMD_GET_IR_CODE;
 		stat = pvr2_send_request(hdw,
 					 hdw->cmd_buffer,1,
 					 hdw->cmd_buffer,4);
@@ -590,6 +591,33 @@
 
 #define BUFSIZE 500
 
+
+void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw)
+{
+	struct list_head *item;
+	struct pvr2_i2c_client *cp;
+	mutex_lock(&hdw->i2c_list_lock); do {
+		struct v4l2_tuner *vtp = &hdw->tuner_signal_info;
+		memset(vtp,0,sizeof(*vtp));
+		list_for_each(item,&hdw->i2c_clients) {
+			cp = list_entry(item,struct pvr2_i2c_client,list);
+			if (!cp->detected_flag) continue;
+			if (!cp->status_poll) continue;
+			cp->status_poll(cp);
+		}
+		hdw->tuner_signal_stale = 0;
+		pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll"
+			   " type=%u strength=%u audio=0x%x cap=0x%x"
+			   " low=%u hi=%u",
+			   vtp->type,
+			   vtp->signal,vtp->rxsubchans,vtp->capability,
+			   vtp->rangelow,vtp->rangehigh);
+	} while (0); mutex_unlock(&hdw->i2c_list_lock);
+}
+
+
+/* Issue various I2C operations to bring chip-level drivers into sync with
+   state stored in this driver. */
 void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
 {
 	unsigned long msk;
@@ -870,12 +898,12 @@
 	struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
 	struct pvr2_i2c_client *cp;
 	int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL);
-	cp = kmalloc(sizeof(*cp),GFP_KERNEL);
+	cp = kzalloc(sizeof(*cp),GFP_KERNEL);
 	trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]",
 		  client->name,
 		  client->addr,cp);
 	if (!cp) return -ENOMEM;
-	memset(cp,0,sizeof(*cp));
+	cp->hdw = hdw;
 	INIT_LIST_HEAD(&cp->list);
 	cp->client = client;
 	mutex_lock(&hdw->i2c_list_lock); do {
@@ -948,8 +976,7 @@
 	printk("%s: i2c scan beginning\n",hdw->name);
 	for (i = 0; i < 128; i++) {
 		msg[0].addr = i;
-		rc = i2c_transfer(&hdw->i2c_adap,msg,
-				  sizeof(msg)/sizeof(msg[0]));
+		rc = i2c_transfer(&hdw->i2c_adap,msg, ARRAY_SIZE(msg));
 		if (rc != 1) continue;
 		printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i);
 	}
@@ -977,6 +1004,7 @@
 	memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
 	memcpy(&hdw->i2c_algo,&pvr2_i2c_algo_template,sizeof(hdw->i2c_algo));
 	strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name));
+	hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;
 	hdw->i2c_adap.algo = &hdw->i2c_algo;
 	hdw->i2c_adap.algo_data = hdw;
 	hdw->i2c_pend_mask = 0;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
index 6d7e252..bd0807b 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
@@ -35,10 +35,12 @@
 	struct i2c_client *client;
 	struct pvr2_i2c_handler *handler;
 	struct list_head list;
+	struct pvr2_hdw *hdw;
 	int detected_flag;
 	int recv_enable;
 	unsigned long pend_mask;
 	unsigned long ctl_mask;
+	void (*status_poll)(struct pvr2_i2c_client *);
 };
 
 struct pvr2_i2c_handler {
@@ -67,6 +69,7 @@
 
 int pvr2_i2c_core_check_stale(struct pvr2_hdw *);
 void pvr2_i2c_core_sync(struct pvr2_hdw *);
+void pvr2_i2c_core_status_poll(struct pvr2_hdw *);
 unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen);
 #define PVR2_I2C_DETAIL_DEBUG   0x0001
 #define PVR2_I2C_DETAIL_HANDLER 0x0002
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
index 57fb320..ce3c898 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -474,9 +474,8 @@
 struct pvr2_stream *pvr2_stream_create(void)
 {
 	struct pvr2_stream *sp;
-	sp = kmalloc(sizeof(*sp),GFP_KERNEL);
+	sp = kzalloc(sizeof(*sp),GFP_KERNEL);
 	if (!sp) return sp;
-	memset(sp,0,sizeof(*sp));
 	pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp);
 	pvr2_stream_init(sp);
 	return sp;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
index b71f9a9..f782418 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
@@ -87,10 +87,9 @@
 struct pvr2_ioread *pvr2_ioread_create(void)
 {
 	struct pvr2_ioread *cp;
-	cp = kmalloc(sizeof(*cp),GFP_KERNEL);
+	cp = kzalloc(sizeof(*cp),GFP_KERNEL);
 	if (!cp) return NULL;
 	pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp);
-	memset(cp,0,sizeof(*cp));
 	if (pvr2_ioread_init(cp) < 0) {
 		kfree(cp);
 		return NULL;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c
index f95c598..81de26b 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-std.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-std.c
@@ -78,14 +78,14 @@
 #define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM)
 
 /* Mapping of standard bits to color system */
-const static struct std_name std_groups[] = {
+static const struct std_name std_groups[] = {
 	{"PAL",CSTD_PAL},
 	{"NTSC",CSTD_NTSC},
 	{"SECAM",CSTD_SECAM},
 };
 
 /* Mapping of standard bits to modulation system */
-const static struct std_name std_items[] = {
+static const struct std_name std_items[] = {
 	{"B",TSTD_B},
 	{"B1",TSTD_B1},
 	{"D",TSTD_D},
@@ -141,10 +141,8 @@
 			cnt = 0;
 			while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++;
 			if (cnt >= bufSize) return 0; // No more characters
-			sp = find_std_name(
-				std_groups,
-				sizeof(std_groups)/sizeof(std_groups[0]),
-				bufPtr,cnt);
+			sp = find_std_name(std_groups, ARRAY_SIZE(std_groups),
+					   bufPtr,cnt);
 			if (!sp) return 0; // Illegal color system name
 			cnt++;
 			bufPtr += cnt;
@@ -163,8 +161,7 @@
 			if (ch == '/') break;
 			cnt++;
 		}
-		sp = find_std_name(std_items,
-				   sizeof(std_items)/sizeof(std_items[0]),
+		sp = find_std_name(std_items, ARRAY_SIZE(std_items),
 				   bufPtr,cnt);
 		if (!sp) return 0; // Illegal modulation system ID
 		t = sp->id & cmsk;
@@ -189,14 +186,10 @@
 	unsigned int c1,c2;
 	cfl = 0;
 	c1 = 0;
-	for (idx1 = 0;
-	     idx1 < sizeof(std_groups)/sizeof(std_groups[0]);
-	     idx1++) {
+	for (idx1 = 0; idx1 < ARRAY_SIZE(std_groups); idx1++) {
 		gp = std_groups + idx1;
 		gfl = 0;
-		for (idx2 = 0;
-		     idx2 < sizeof(std_items)/sizeof(std_items[0]);
-		     idx2++) {
+		for (idx2 = 0; idx2 < ARRAY_SIZE(std_items); idx2++) {
 			ip = std_items + idx2;
 			if (!(gp->id & ip->id & id)) continue;
 			if (!gfl) {
@@ -279,7 +272,7 @@
 	}
 };
 
-#define generic_standards_cnt (sizeof(generic_standards)/sizeof(generic_standards[0]))
+#define generic_standards_cnt ARRAY_SIZE(generic_standards)
 
 static struct v4l2_standard *match_std(v4l2_std_id id)
 {
@@ -348,7 +341,7 @@
 		fmsk |= idmsk;
 	}
 
-	for (idx2 = 0; idx2 < sizeof(std_mixes)/sizeof(std_mixes[0]); idx2++) {
+	for (idx2 = 0; idx2 < ARRAY_SIZE(std_mixes); idx2++) {
 		if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
 	}
 
@@ -366,16 +359,15 @@
 		   std_cnt);
 	if (!std_cnt) return NULL; // paranoia
 
-	stddefs = kmalloc(sizeof(struct v4l2_standard) * std_cnt,
+	stddefs = kzalloc(sizeof(struct v4l2_standard) * std_cnt,
 			  GFP_KERNEL);
-	memset(stddefs,0,sizeof(struct v4l2_standard) * std_cnt);
 	for (idx = 0; idx < std_cnt; idx++) stddefs[idx].index = idx;
 
 	idx = 0;
 
 	/* Enumerate potential special cases */
-	for (idx2 = 0; ((idx2 < sizeof(std_mixes)/sizeof(std_mixes[0])) &&
-			(idx < std_cnt)); idx2++) {
+	for (idx2 = 0; (idx2 < ARRAY_SIZE(std_mixes)) && (idx < std_cnt);
+	     idx2++) {
 		if (!(id & std_mixes[idx2])) continue;
 		if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++;
 	}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index c294f46..91396fd 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -40,8 +40,10 @@
 	struct pvr2_sysfs_ctl_item *item_first;
 	struct pvr2_sysfs_ctl_item *item_last;
 	struct class_device_attribute attr_v4l_minor_number;
+	struct class_device_attribute attr_v4l_radio_minor_number;
 	struct class_device_attribute attr_unit_number;
 	int v4l_minor_number_created_ok;
+	int v4l_radio_minor_number_created_ok;
 	int unit_number_created_ok;
 };
 
@@ -491,7 +493,7 @@
 	unsigned int cnt,acnt;
 	int ret;
 
-	if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
+	if ((ctl_id < 0) || (ctl_id >= ARRAY_SIZE(funcs))) {
 		return;
 	}
 
@@ -499,9 +501,8 @@
 	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
 	if (!cptr) return;
 
-	cip = kmalloc(sizeof(*cip),GFP_KERNEL);
+	cip = kzalloc(sizeof(*cip),GFP_KERNEL);
 	if (!cip) return;
-	memset(cip,0,sizeof(*cip));
 	pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
 
 	cip->cptr = cptr;
@@ -611,9 +612,8 @@
 	struct pvr2_sysfs_debugifc *dip;
 	int ret;
 
-	dip = kmalloc(sizeof(*dip),GFP_KERNEL);
+	dip = kzalloc(sizeof(*dip),GFP_KERNEL);
 	if (!dip) return;
-	memset(dip,0,sizeof(*dip));
 	dip->attr_debugcmd.attr.owner = THIS_MODULE;
 	dip->attr_debugcmd.attr.name = "debugcmd";
 	dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
@@ -709,6 +709,10 @@
 		class_device_remove_file(sfp->class_dev,
 					 &sfp->attr_v4l_minor_number);
 	}
+	if (sfp->v4l_radio_minor_number_created_ok) {
+		class_device_remove_file(sfp->class_dev,
+					 &sfp->attr_v4l_radio_minor_number);
+	}
 	if (sfp->unit_number_created_ok) {
 		class_device_remove_file(sfp->class_dev,
 					 &sfp->attr_unit_number);
@@ -726,7 +730,20 @@
 	sfp = (struct pvr2_sysfs *)class_dev->class_data;
 	if (!sfp) return -EINVAL;
 	return scnprintf(buf,PAGE_SIZE,"%d\n",
-			 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw));
+			 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
+						       pvr2_v4l_type_video));
+}
+
+
+static ssize_t v4l_radio_minor_number_show(struct class_device *class_dev,
+					   char *buf)
+{
+	struct pvr2_sysfs *sfp;
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	return scnprintf(buf,PAGE_SIZE,"%d\n",
+			 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
+						       pvr2_v4l_type_radio));
 }
 
 
@@ -749,9 +766,8 @@
 
 	usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
 	if (!usb_dev) return;
-	class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL);
+	class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL);
 	if (!class_dev) return;
-	memset(class_dev,0,sizeof(*class_dev));
 
 	pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
 
@@ -793,6 +809,20 @@
 		sfp->v4l_minor_number_created_ok = !0;
 	}
 
+	sfp->attr_v4l_radio_minor_number.attr.owner = THIS_MODULE;
+	sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
+	sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
+	sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
+	sfp->attr_v4l_radio_minor_number.store = NULL;
+	ret = class_device_create_file(sfp->class_dev,
+				       &sfp->attr_v4l_radio_minor_number);
+	if (ret < 0) {
+		printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+		       __FUNCTION__, ret);
+	} else {
+		sfp->v4l_radio_minor_number_created_ok = !0;
+	}
+
 	sfp->attr_unit_number.attr.owner = THIS_MODULE;
 	sfp->attr_unit_number.attr.name = "unit_number";
 	sfp->attr_unit_number.attr.mode = S_IRUGO;
@@ -829,9 +859,8 @@
 				     struct pvr2_sysfs_class *class_ptr)
 {
 	struct pvr2_sysfs *sfp;
-	sfp = kmalloc(sizeof(*sfp),GFP_KERNEL);
+	sfp = kzalloc(sizeof(*sfp),GFP_KERNEL);
 	if (!sfp) return sfp;
-	memset(sfp,0,sizeof(*sfp));
 	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
 	pvr2_channel_init(&sfp->channel,mp);
 	sfp->channel.check_func = pvr2_sysfs_internal_check;
@@ -852,9 +881,8 @@
 struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
 {
 	struct pvr2_sysfs_class *clp;
-	clp = kmalloc(sizeof(*clp),GFP_KERNEL);
+	clp = kzalloc(sizeof(*clp),GFP_KERNEL);
 	if (!clp) return clp;
-	memset(clp,0,sizeof(*clp));
 	pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp);
 	clp->class.name = "pvrusb2";
 	clp->class.class_release = pvr2_sysfs_class_release;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/drivers/media/video/pvrusb2/pvrusb2-tuner.c
index af9f246..05e65ce 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-tuner.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-tuner.c
@@ -80,7 +80,7 @@
 }
 
 
-const static struct pvr2_i2c_handler_functions tuner_funcs = {
+static const struct pvr2_i2c_handler_functions tuner_funcs = {
 	.detach = (void (*)(void *))pvr2_tuner_detach,
 	.check = (int (*)(void *))tuner_check,
 	.update = (void (*)(void *))tuner_update,
@@ -93,9 +93,8 @@
 	struct pvr2_tuner_handler *ctxt;
 	if (cp->handler) return 0;
 
-	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
 	if (!ctxt) return 0;
-	memset(ctxt,0,sizeof(*ctxt));
 
 	ctxt->i2c_handler.func_data = ctxt;
 	ctxt->i2c_handler.func_table = &tuner_funcs;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index bb40e90..4fe4136 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -40,7 +40,10 @@
 	struct video_device devbase; /* MUST be first! */
 	struct pvr2_v4l2 *v4lp;
 	struct pvr2_context_stream *stream;
-	enum pvr2_config config;
+	/* Information about this device: */
+	enum pvr2_config config; /* Expected stream format */
+	int v4l_type; /* V4L defined type for this device node */
+	enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
 };
 
 struct pvr2_v4l2_fh {
@@ -54,6 +57,7 @@
 	struct pvr2_v4l2_fh *vprev;
 	wait_queue_head_t wait_data;
 	int fw_mode_flag;
+	int prev_input_val;
 };
 
 struct pvr2_v4l2 {
@@ -63,13 +67,22 @@
 
 	struct v4l2_prio_state prio;
 
-	/* streams */
-	struct pvr2_v4l2_dev *vdev;
+	/* streams - Note that these must be separately, individually,
+	 * allocated pointers.  This is because the v4l core is going to
+	 * manage their deletion - separately, individually...  */
+	struct pvr2_v4l2_dev *dev_video;
+	struct pvr2_v4l2_dev *dev_radio;
 };
 
 static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
 module_param_array(video_nr, int, NULL, 0444);
-MODULE_PARM_DESC(video_nr, "Offset for device's minor");
+MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
+static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
+module_param_array(radio_nr, int, NULL, 0444);
+MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
+static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
+module_param_array(vbi_nr, int, NULL, 0444);
+MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
 
 static struct v4l2_capability pvr_capability ={
 	.driver         = "pvrusb2",
@@ -77,30 +90,11 @@
 	.bus_info       = "usb",
 	.version        = KERNEL_VERSION(0,8,0),
 	.capabilities   = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
-			   V4L2_CAP_TUNER | V4L2_CAP_AUDIO |
+			   V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
 			   V4L2_CAP_READWRITE),
 	.reserved       = {0,0,0,0}
 };
 
-static struct v4l2_tuner pvr_v4l2_tuners[]= {
-	{
-		.index      = 0,
-		.name       = "TV Tuner",
-		.type           = V4L2_TUNER_ANALOG_TV,
-		.capability     = (V4L2_TUNER_CAP_NORM |
-				   V4L2_TUNER_CAP_STEREO |
-				   V4L2_TUNER_CAP_LANG1 |
-				   V4L2_TUNER_CAP_LANG2),
-		.rangelow   = 0,
-		.rangehigh  = 0,
-		.rxsubchans     = V4L2_TUNER_SUB_STEREO,
-		.audmode        = V4L2_TUNER_MODE_STEREO,
-		.signal         = 0,
-		.afc            = 0,
-		.reserved       = {0,0,0,0}
-	}
-};
-
 static struct v4l2_fmtdesc pvr_fmtdesc [] = {
 	{
 		.index          = 0,
@@ -154,6 +148,18 @@
 	}
 };
 
+
+static const char *get_v4l_name(int v4l_type)
+{
+	switch (v4l_type) {
+	case VFL_TYPE_GRABBER: return "video";
+	case VFL_TYPE_RADIO: return "radio";
+	case VFL_TYPE_VBI: return "vbi";
+	default: return "?";
+	}
+}
+
+
 /*
  * pvr_ioctl()
  *
@@ -315,13 +321,39 @@
 
 	case VIDIOC_ENUMAUDIO:
 	{
+		/* pkt: FIXME: We are returning one "fake" input here
+		   which could very well be called "whatever_we_like".
+		   This is for apps that want to see an audio input
+		   just to feel comfortable, as well as to test if
+		   it can do stereo or sth. There is actually no guarantee
+		   that the actual audio input cannot change behind the app's
+		   back, but most applications should not mind that either.
+
+		   Hopefully, mplayer people will work with us on this (this
+		   whole mess is to support mplayer pvr://), or Hans will come
+		   up with a more standard way to say "we have inputs but we
+		   don 't want you to change them independent of video" which
+		   will sort this mess.
+		 */
+		struct v4l2_audio *vin = arg;
 		ret = -EINVAL;
+		if (vin->index > 0) break;
+		strncpy(vin->name, "PVRUSB2 Audio",14);
+		vin->capability = V4L2_AUDCAP_STEREO;
+		ret = 0;
+		break;
 		break;
 	}
 
 	case VIDIOC_G_AUDIO:
 	{
-		ret = -EINVAL;
+		/* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
+		struct v4l2_audio *vin = arg;
+		memset(vin,0,sizeof(*vin));
+		vin->index = 0;
+		strncpy(vin->name, "PVRUSB2 Audio",14);
+		vin->capability = V4L2_AUDCAP_STEREO;
+		ret = 0;
 		break;
 	}
 
@@ -333,34 +365,11 @@
 	case VIDIOC_G_TUNER:
 	{
 		struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
-		unsigned int status_mask;
-		int val;
-		if (vt->index !=0) break;
 
-		status_mask = pvr2_hdw_get_signal_status(hdw);
+		if (vt->index != 0) break; /* Only answer for the 1st tuner */
 
-		memcpy(vt, &pvr_v4l2_tuners[vt->index],
-		       sizeof(struct v4l2_tuner));
-
-		vt->signal = 0;
-		if (status_mask & PVR2_SIGNAL_OK) {
-			if (status_mask & PVR2_SIGNAL_STEREO) {
-				vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
-			} else {
-				vt->rxsubchans = V4L2_TUNER_SUB_MONO;
-			}
-			if (status_mask & PVR2_SIGNAL_SAP) {
-				vt->rxsubchans |= (V4L2_TUNER_SUB_LANG1 |
-						   V4L2_TUNER_SUB_LANG2);
-			}
-			vt->signal = 65535;
-		}
-
-		val = 0;
-		ret = pvr2_ctrl_get_value(
-			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
-			&val);
-		vt->audmode = val;
+		pvr2_hdw_execute_tuner_poll(hdw);
+		ret = pvr2_hdw_get_tuner_status(hdw,vt);
 		break;
 	}
 
@@ -374,14 +383,40 @@
 		ret = pvr2_ctrl_set_value(
 			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
 			vt->audmode);
+		break;
 	}
 
 	case VIDIOC_S_FREQUENCY:
 	{
 		const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
+		unsigned long fv;
+		struct v4l2_tuner vt;
+		int cur_input;
+		struct pvr2_ctrl *ctrlp;
+		ret = pvr2_hdw_get_tuner_status(hdw,&vt);
+		if (ret != 0) break;
+		ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+		ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
+		if (ret != 0) break;
+		if (vf->type == V4L2_TUNER_RADIO) {
+			if (cur_input != PVR2_CVAL_INPUT_RADIO) {
+				pvr2_ctrl_set_value(ctrlp,
+						    PVR2_CVAL_INPUT_RADIO);
+			}
+		} else {
+			if (cur_input == PVR2_CVAL_INPUT_RADIO) {
+				pvr2_ctrl_set_value(ctrlp,
+						    PVR2_CVAL_INPUT_TV);
+			}
+		}
+		fv = vf->frequency;
+		if (vt.capability & V4L2_TUNER_CAP_LOW) {
+			fv = (fv * 125) / 2;
+		} else {
+			fv = fv * 62500;
+		}
 		ret = pvr2_ctrl_set_value(
-			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
-			vf->frequency * 62500);
+			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
 		break;
 	}
 
@@ -389,10 +424,27 @@
 	{
 		struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
 		int val = 0;
+		int cur_input;
+		struct v4l2_tuner vt;
+		ret = pvr2_hdw_get_tuner_status(hdw,&vt);
+		if (ret != 0) break;
 		ret = pvr2_ctrl_get_value(
 			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
 			&val);
-		val /= 62500;
+		if (ret != 0) break;
+		pvr2_ctrl_get_value(
+			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
+			&cur_input);
+		if (cur_input == PVR2_CVAL_INPUT_RADIO) {
+			vf->type = V4L2_TUNER_RADIO;
+		} else {
+			vf->type = V4L2_TUNER_ANALOG_TV;
+		}
+		if (vt.capability & V4L2_TUNER_CAP_LOW) {
+			val = (val * 2) / 125;
+		} else {
+			val /= 62500;
+		}
 		vf->frequency = val;
 		break;
 	}
@@ -449,7 +501,7 @@
 		ret = 0;
 		switch(vf->type) {
 		case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-			int lmin,lmax;
+			int lmin,lmax,ldef;
 			struct pvr2_ctrl *hcp,*vcp;
 			int h = vf->fmt.pix.height;
 			int w = vf->fmt.pix.width;
@@ -458,14 +510,20 @@
 
 			lmin = pvr2_ctrl_get_min(hcp);
 			lmax = pvr2_ctrl_get_max(hcp);
-			if (w < lmin) {
+			ldef = pvr2_ctrl_get_def(hcp);
+			if (w == -1) {
+				w = ldef;
+			} else if (w < lmin) {
 				w = lmin;
 			} else if (w > lmax) {
 				w = lmax;
 			}
 			lmin = pvr2_ctrl_get_min(vcp);
 			lmax = pvr2_ctrl_get_max(vcp);
-			if (h < lmin) {
+			ldef = pvr2_ctrl_get_def(vcp);
+			if (h == -1) {
+				h = ldef;
+			} else if (h < lmin) {
 				h = lmin;
 			} else if (h > lmax) {
 				h = lmax;
@@ -494,6 +552,13 @@
 
 	case VIDIOC_STREAMON:
 	{
+		if (!fh->dev_info->stream) {
+			/* No stream defined for this node.  This means
+			   that we're not currently allowed to stream from
+			   this node. */
+			ret = -EPERM;
+			break;
+		}
 		ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
 		if (ret < 0) return ret;
 		ret = pvr2_hdw_set_streaming(hdw,!0);
@@ -502,6 +567,13 @@
 
 	case VIDIOC_STREAMOFF:
 	{
+		if (!fh->dev_info->stream) {
+			/* No stream defined for this node.  This means
+			   that we're not currently allowed to stream from
+			   this node. */
+			ret = -EPERM;
+			break;
+		}
 		ret = pvr2_hdw_set_streaming(hdw,0);
 		break;
 	}
@@ -599,6 +671,7 @@
 		struct v4l2_ext_control *ctrl;
 		unsigned int idx;
 		int val;
+		ret = 0;
 		for (idx = 0; idx < ctls->count; idx++) {
 			ctrl = ctls->controls + idx;
 			ret = pvr2_ctrl_get_value(
@@ -621,6 +694,7 @@
 			(struct v4l2_ext_controls *)arg;
 		struct v4l2_ext_control *ctrl;
 		unsigned int idx;
+		ret = 0;
 		for (idx = 0; idx < ctls->count; idx++) {
 			ctrl = ctls->controls + idx;
 			ret = pvr2_ctrl_set_value(
@@ -643,6 +717,7 @@
 		unsigned int idx;
 		/* For the moment just validate that the requested control
 		   actually exists. */
+		ret = 0;
 		for (idx = 0; idx < ctls->count; idx++) {
 			ctrl = ctls->controls + idx;
 			pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
@@ -662,16 +737,16 @@
 		break;
 	}
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	case VIDIOC_INT_G_REGISTER:
-	case VIDIOC_INT_S_REGISTER:
+	case VIDIOC_DBG_S_REGISTER:
+	case VIDIOC_DBG_G_REGISTER:
 	{
 		u32 val;
 		struct v4l2_register *req = (struct v4l2_register *)arg;
-		if (cmd == VIDIOC_INT_S_REGISTER) val = req->val;
+		if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
 		ret = pvr2_hdw_register_access(
 			hdw,req->i2c_id,req->reg,
-			cmd == VIDIOC_INT_S_REGISTER,&val);
-		if (cmd == VIDIOC_INT_G_REGISTER) req->val = val;
+			cmd == VIDIOC_DBG_S_REGISTER,&val);
+		if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
 		break;
 	}
 #endif
@@ -707,8 +782,12 @@
 
 static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
 {
-	printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n",
-	       dip->devbase.minor,pvr2_config_get_name(dip->config));
+	int minor_id = dip->devbase.minor;
+	struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
+	enum pvr2_config cfg = dip->config;
+	int v4l_type = dip->v4l_type;
+
+	pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
 
 	/* Paranoia */
 	dip->v4lp = NULL;
@@ -717,13 +796,24 @@
 	/* Actual deallocation happens later when all internal references
 	   are gone. */
 	video_unregister_device(&dip->devbase);
+
+	printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
+	       get_v4l_name(v4l_type),minor_id & 0x1f,
+	       pvr2_config_get_name(cfg));
+
 }
 
 
 static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
 {
-	pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,-1);
-	pvr2_v4l2_dev_destroy(vp->vdev);
+	if (vp->dev_video) {
+		pvr2_v4l2_dev_destroy(vp->dev_video);
+		vp->dev_video = 0;
+	}
+	if (vp->dev_radio) {
+		pvr2_v4l2_dev_destroy(vp->dev_radio);
+		vp->dev_radio = 0;
+	}
 
 	pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
 	pvr2_channel_done(&vp->channel);
@@ -766,23 +856,37 @@
 	struct pvr2_v4l2_fh *fhp = file->private_data;
 	struct pvr2_v4l2 *vp = fhp->vhead;
 	struct pvr2_context *mp = fhp->vhead->channel.mc_head;
+	struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
 
 	pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
 
 	if (fhp->rhp) {
 		struct pvr2_stream *sp;
-		struct pvr2_hdw *hdw;
-		hdw = fhp->channel.mc_head->hdw;
 		pvr2_hdw_set_streaming(hdw,0);
 		sp = pvr2_ioread_get_stream(fhp->rhp);
 		if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
 		pvr2_ioread_destroy(fhp->rhp);
 		fhp->rhp = NULL;
 	}
+
 	v4l2_prio_close(&vp->prio, &fhp->prio);
 	file->private_data = NULL;
 
 	pvr2_context_enter(mp); do {
+		/* Restore the previous input selection, if it makes sense
+		   to do so. */
+		if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
+			struct pvr2_ctrl *cp;
+			int pval;
+			cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+			pvr2_ctrl_get_value(cp,&pval);
+			/* Only restore if we're still selecting the radio */
+			if (pval == PVR2_CVAL_INPUT_RADIO) {
+				pvr2_ctrl_set_value(cp,fhp->prev_input_val);
+				pvr2_hdw_commit_ctl(hdw);
+			}
+		}
+
 		if (fhp->vnext) {
 			fhp->vnext->vprev = fhp->vprev;
 		} else {
@@ -828,11 +932,10 @@
 		return -EIO;
 	}
 
-	fhp = kmalloc(sizeof(*fhp),GFP_KERNEL);
+	fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
 	if (!fhp) {
 		return -ENOMEM;
 	}
-	memset(fhp,0,sizeof(*fhp));
 
 	init_waitqueue_head(&fhp->wait_data);
 	fhp->dev_info = dip;
@@ -840,6 +943,7 @@
 	pvr2_context_enter(vp->channel.mc_head); do {
 		pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
 		pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
+
 		fhp->vnext = NULL;
 		fhp->vprev = vp->vlast;
 		if (vp->vlast) {
@@ -849,6 +953,18 @@
 		}
 		vp->vlast = fhp;
 		fhp->vhead = vp;
+
+		/* Opening the /dev/radioX device implies a mode switch.
+		   So execute that here.  Note that you can get the
+		   IDENTICAL effect merely by opening the normal video
+		   device and setting the input appropriately. */
+		if (dip->v4l_type == VFL_TYPE_RADIO) {
+			struct pvr2_ctrl *cp;
+			cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+			pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
+			pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
+			pvr2_hdw_commit_ctl(hdw);
+		}
 	} while (0); pvr2_context_exit(vp->channel.mc_head);
 
 	fhp->file = file;
@@ -873,6 +989,12 @@
 	struct pvr2_hdw *hdw;
 	if (fh->rhp) return 0;
 
+	if (!fh->dev_info->stream) {
+		/* No stream defined for this node.  This means that we're
+		   not currently allowed to stream from this node. */
+		return -EPERM;
+	}
+
 	/* First read() attempt.  Try to claim the stream and start
 	   it... */
 	if ((ret = pvr2_channel_claim_stream(&fh->channel,
@@ -986,7 +1108,7 @@
 }
 
 
-static struct file_operations vdev_fops = {
+static const struct file_operations vdev_fops = {
 	.owner      = THIS_MODULE,
 	.open       = pvr2_v4l2_open,
 	.release    = pvr2_v4l2_release,
@@ -1012,25 +1134,37 @@
 
 static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
 			       struct pvr2_v4l2 *vp,
-			       enum pvr2_config cfg)
+			       int v4l_type)
 {
 	int mindevnum;
 	int unit_number;
-	int v4l_type;
+	int *nr_ptr = 0;
 	dip->v4lp = vp;
-	dip->config = cfg;
 
 
-	switch (cfg) {
-	case pvr2_config_mpeg:
-		v4l_type = VFL_TYPE_GRABBER;
+	dip->v4l_type = v4l_type;
+	switch (v4l_type) {
+	case VFL_TYPE_GRABBER:
 		dip->stream = &vp->channel.mc_head->video_stream;
+		dip->config = pvr2_config_mpeg;
+		dip->minor_type = pvr2_v4l_type_video;
+		nr_ptr = video_nr;
+		if (!dip->stream) {
+			err("Failed to set up pvrusb2 v4l video dev"
+			    " due to missing stream instance");
+			return;
+		}
 		break;
-	case pvr2_config_vbi:
-		v4l_type = VFL_TYPE_VBI;
+	case VFL_TYPE_VBI:
+		dip->config = pvr2_config_vbi;
+		dip->minor_type = pvr2_v4l_type_vbi;
+		nr_ptr = vbi_nr;
 		break;
-	case pvr2_config_radio:
-		v4l_type = VFL_TYPE_RADIO;
+	case VFL_TYPE_RADIO:
+		dip->stream = &vp->channel.mc_head->video_stream;
+		dip->config = pvr2_config_mpeg;
+		dip->minor_type = pvr2_v4l_type_radio;
+		nr_ptr = radio_nr;
 		break;
 	default:
 		/* Bail out (this should be impossible) */
@@ -1039,30 +1173,27 @@
 		return;
 	}
 
-	if (!dip->stream) {
-		err("Failed to set up pvrusb2 v4l dev"
-		    " due to missing stream instance");
-		return;
-	}
-
 	memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
 	dip->devbase.release = pvr2_video_device_release;
 
 	mindevnum = -1;
 	unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
-	if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
-		mindevnum = video_nr[unit_number];
+	if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
+		mindevnum = nr_ptr[unit_number];
 	}
-	if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) &&
-	    (video_register_device(&dip->devbase, v4l_type, -1) < 0)) {
-		err("Failed to register pvrusb2 v4l video device");
-	} else {
-		printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n",
-		       dip->devbase.minor,pvr2_config_get_name(dip->config));
+	if ((video_register_device(&dip->devbase,
+				   dip->v4l_type, mindevnum) < 0) &&
+	    (video_register_device(&dip->devbase,
+				   dip->v4l_type, -1) < 0)) {
+		err("Failed to register pvrusb2 v4l device");
 	}
 
+	printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
+	       get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
+	       pvr2_config_get_name(dip->config));
+
 	pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
-					dip->devbase.minor);
+					dip->minor_type,dip->devbase.minor);
 }
 
 
@@ -1070,22 +1201,24 @@
 {
 	struct pvr2_v4l2 *vp;
 
-	vp = kmalloc(sizeof(*vp),GFP_KERNEL);
+	vp = kzalloc(sizeof(*vp),GFP_KERNEL);
 	if (!vp) return vp;
-	memset(vp,0,sizeof(*vp));
-	vp->vdev = kmalloc(sizeof(*vp->vdev),GFP_KERNEL);
-	if (!vp->vdev) {
+	vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
+	vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
+	if (!(vp->dev_video && vp->dev_radio)) {
+		kfree(vp->dev_video);
+		kfree(vp->dev_radio);
 		kfree(vp);
 		return NULL;
 	}
-	memset(vp->vdev,0,sizeof(*vp->vdev));
 	pvr2_channel_init(&vp->channel,mnp);
 	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
 
 	vp->channel.check_func = pvr2_v4l2_internal_check;
 
 	/* register streams */
-	pvr2_v4l2_dev_init(vp->vdev,vp,pvr2_config_mpeg);
+	pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
+	pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
 
 	return vp;
 }
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
index 05f2cdd..61efa6f 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
@@ -66,7 +66,9 @@
 		route.input = SAA7115_SVIDEO2;
 		break;
 	case PVR2_CVAL_INPUT_RADIO:
-		// ????? No idea yet what to do here
+		// In radio mode, we mute the video, but point at one
+		// spot just to stay consistent
+		route.input = SAA7115_COMPOSITE5;
 	default:
 		return;
 	}
@@ -137,8 +139,7 @@
 	unsigned long msk;
 	unsigned int idx;
 
-	for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
-	     idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
 		msk = 1 << idx;
 		if (ctxt->stale_mask & msk) continue;
 		if (decoder_ops[idx].check(ctxt)) {
@@ -154,8 +155,7 @@
 	unsigned long msk;
 	unsigned int idx;
 
-	for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
-	     idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
 		msk = 1 << idx;
 		if (!(ctxt->stale_mask & msk)) continue;
 		ctxt->stale_mask &= ~msk;
@@ -183,25 +183,13 @@
 }
 
 
-static int decoder_is_tuned(struct pvr2_v4l_decoder *ctxt)
-{
-	struct v4l2_tuner vt;
-	int ret;
-
-	memset(&vt,0,sizeof(vt));
-	ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
-	if (ret < 0) return -EINVAL;
-	return vt.signal ? 1 : 0;
-}
-
-
 static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt)
 {
 	return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l");
 }
 
 
-const static struct pvr2_i2c_handler_functions hfuncs = {
+static const struct pvr2_i2c_handler_functions hfuncs = {
 	.detach = (void (*)(void *))decoder_detach,
 	.check = (int (*)(void *))decoder_check,
 	.update = (void (*)(void *))decoder_update,
@@ -218,20 +206,17 @@
 	if (cp->handler) return 0;
 	if (!decoder_detect(cp)) return 0;
 
-	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
 	if (!ctxt) return 0;
-	memset(ctxt,0,sizeof(*ctxt));
 
 	ctxt->handler.func_data = ctxt;
 	ctxt->handler.func_table = &hfuncs;
 	ctxt->ctrl.ctxt = ctxt;
 	ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
 	ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
-	ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned;
 	ctxt->client = cp;
 	ctxt->hdw = hdw;
-	ctxt->stale_mask = (1 << (sizeof(decoder_ops)/
-				  sizeof(decoder_ops[0]))) - 1;
+	ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1;
 	hdw->decoder_ctrl = &ctxt->ctrl;
 	cp->handler = &ctxt->handler;
 	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up",
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
index 2413e51..66b4d36 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
@@ -50,15 +50,21 @@
 {
 	struct v4l2_routing route;
 	struct pvr2_hdw *hdw = ctxt->hdw;
-	int msk = 0;
 
 	memset(&route,0,sizeof(route));
 
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d msk=0x%x)",
-		   hdw->input_val,msk);
+	switch(hdw->input_val) {
+	case PVR2_CVAL_INPUT_RADIO:
+		route.input = 1;
+		break;
+	default:
+		/* All other cases just use the second input */
+		route.input = 2;
+		break;
+	}
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d route=0x%x)",
+		   hdw->input_val,route.input);
 
-	// Always point to input #1 no matter what
-	route.input = 2;
 	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
 }
 
@@ -99,8 +105,7 @@
 	unsigned long msk;
 	unsigned int idx;
 
-	for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]);
-	     idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) {
 		msk = 1 << idx;
 		if (ctxt->stale_mask & msk) continue;
 		if (wm8775_ops[idx].check(ctxt)) {
@@ -116,8 +121,7 @@
 	unsigned long msk;
 	unsigned int idx;
 
-	for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]);
-	     idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) {
 		msk = 1 << idx;
 		if (!(ctxt->stale_mask & msk)) continue;
 		ctxt->stale_mask &= ~msk;
@@ -126,7 +130,7 @@
 }
 
 
-const static struct pvr2_i2c_handler_functions hfuncs = {
+static const struct pvr2_i2c_handler_functions hfuncs = {
 	.detach = (void (*)(void *))wm8775_detach,
 	.check = (int (*)(void *))wm8775_check,
 	.update = (void (*)(void *))wm8775_update,
@@ -140,16 +144,14 @@
 
 	if (cp->handler) return 0;
 
-	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
 	if (!ctxt) return 0;
-	memset(ctxt,0,sizeof(*ctxt));
 
 	ctxt->handler.func_data = ctxt;
 	ctxt->handler.func_table = &hfuncs;
 	ctxt->client = cp;
 	ctxt->hdw = hdw;
-	ctxt->stale_mask = (1 << (sizeof(wm8775_ops)/
-				  sizeof(wm8775_ops[0]))) - 1;
+	ctxt->stale_mask = (1 << ARRAY_SIZE(wm8775_ops)) - 1;
 	cp->handler = &ctxt->handler;
 	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up",
 		   cp->client->addr);
diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile
index 9db2260..f5c8ec2 100644
--- a/drivers/media/video/pwc/Makefile
+++ b/drivers/media/video/pwc/Makefile
@@ -2,11 +2,3 @@
 pwc-objs	+= pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
 
 obj-$(CONFIG_USB_PWC) += pwc.o
-
-ifeq ($(CONFIG_USB_PWC_DEBUG),y)
-EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=1
-else
-EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=0
-endif
-
-
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index a996aad..27ed769 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -128,7 +128,7 @@
 static int default_fps = 10;
 static int default_fbufs = 3;   /* Default number of frame buffers */
        int pwc_mbufs = 2;	/* Default number of mmap() buffers */
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
        int pwc_trace = PWC_DEBUG_LEVEL;
 #endif
 static int power_save = 0;
@@ -152,7 +152,7 @@
 			    unsigned int ioctlnr, unsigned long arg);
 static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
 
-static struct file_operations pwc_fops = {
+static const struct file_operations pwc_fops = {
 	.owner =	THIS_MODULE,
 	.open =		pwc_video_open,
 	.release =     	pwc_video_close,
@@ -1051,7 +1051,7 @@
 	video_device_remove_file(vdev, &class_device_attr_button);
 }
 
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
 static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
 {
 	switch(sensor_type) {
@@ -1835,7 +1835,7 @@
 module_param(fps, int, 0444);
 module_param(fbufs, int, 0444);
 module_param(mbufs, int, 0444);
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
 module_param_named(trace, pwc_trace, int, 0644);
 #endif
 module_param(power_save, int, 0444);
@@ -1908,7 +1908,7 @@
 		default_fbufs = fbufs;
 		PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs);
 	}
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
 	if (pwc_trace >= 0) {
 		PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
 	}
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index b7eb3ce..d5e6bc8 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -350,7 +350,7 @@
 	if (pdev == NULL)
 		return -EFAULT;
 
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
 	if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
 		v4l_printk_ioctl(cmd);
 #endif
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 7e9c423..e778a2b 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -39,11 +39,6 @@
 #include "pwc-uncompress.h"
 #include <media/pwc-ioctl.h>
 
-/* Turn some debugging options on/off */
-#ifndef CONFIG_PWC_DEBUG
-#define CONFIG_PWC_DEBUG 1
-#endif
-
 /* Version block */
 #define PWC_MAJOR	10
 #define PWC_MINOR	0
@@ -76,7 +71,7 @@
 #define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
 
 
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
 
 #define PWC_DEBUG_LEVEL	(PWC_DEBUG_LEVEL_MODULE)
 
@@ -270,7 +265,7 @@
 #endif
 
 /* Global variables */
-#if CONFIG_PWC_DEBUG
+#ifdef CONFIG_USB_PWC_DEBUG
 extern int pwc_trace;
 #endif
 extern int pwc_mbufs;
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index 77bb940..e20aa36 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -40,7 +40,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
@@ -112,7 +111,7 @@
 	for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
 	{
 		memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0]));
-		t->is_searching[pgbuf] = FALSE;
+		t->is_searching[pgbuf] = false;
 	}
 	vd->priv=t;
 
@@ -199,7 +198,7 @@
 
 /* Get count number of bytes from I²C-device at address adr, store them in buf.
  * Start & stop handshaking is done by this routine, ack will be sent after the
- * last byte to inhibit further sending of data. If uaccess is TRUE, data is
+ * last byte to inhibit further sending of data. If uaccess is 'true', data is
  * written to user-space with put_user. Returns -1 if I²C-device didn't send
  * acknowledge, 0 otherwise
  */
@@ -339,7 +338,7 @@
 		return -EIO;
 	}
 
-	t->is_searching[req->pgbuf] = TRUE;
+	t->is_searching[req->pgbuf] = true;
 	return 0;
 }
 
@@ -453,7 +452,7 @@
 		}
 	}
 	if (!info->hamming && !info->notfound)
-		t->is_searching[dau_no] = FALSE;
+		t->is_searching[dau_no] = false;
 	return 0;
 }
 
@@ -565,7 +564,7 @@
 	{
 		return -EIO;
 	}
-	t->is_searching[dau_no] = FALSE;
+	t->is_searching[dau_no] = false;
 	return 0;
 }
 
@@ -817,7 +816,7 @@
 module_init(init_saa_5246a);
 module_exit(cleanup_saa_5246a);
 
-static struct file_operations saa_fops = {
+static const struct file_operations saa_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = saa5246a_open,
 	.release = saa5246a_release,
diff --git a/drivers/media/video/saa5246a.h b/drivers/media/video/saa5246a.h
index 7b91112..64394c0 100644
--- a/drivers/media/video/saa5246a.h
+++ b/drivers/media/video/saa5246a.h
@@ -41,23 +41,18 @@
 #define POS_HEADER_START 7
 #define POS_HEADER_END 31
 
-/* Returns TRUE if the part of the videotext page described with req contains
+/* Returns 'true' if the part of the videotext page described with req contains
    (at least parts of) the time field */
 #define REQ_CONTAINS_TIME(p_req) \
 	((p_req)->start <= POS_TIME_END && \
 	 (p_req)->end   >= POS_TIME_START)
 
-/* Returns TRUE if the part of the videotext page described with req contains
+/* Returns 'true' if the part of the videotext page described with req contains
    (at least parts of) the page header */
 #define REQ_CONTAINS_HEADER(p_req) \
 	((p_req)->start <= POS_HEADER_END && \
 	 (p_req)->end   >= POS_HEADER_START)
 
-#ifndef FALSE
-#define FALSE 0
-#define TRUE 1
-#endif
-
 /*****************************************************************************/
 /* Mode register numbers of the SAA5246A				     */
 /*****************************************************************************/
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index bb3fb43..f2a2f34 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -124,11 +124,6 @@
 
 /* General defines and debugging support */
 
-#ifndef FALSE
-#define FALSE 0
-#define TRUE 1
-#endif
-
 #define RESCHED do { cond_resched(); } while(0)
 
 static struct video_device saa_template;	/* Declared near bottom */
@@ -183,9 +178,9 @@
 		memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
 		memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
 		t->vdau[pgbuf].expire = 0;
-		t->vdau[pgbuf].clrfound = TRUE;
-		t->vdau[pgbuf].stopped = TRUE;
-		t->is_searching[pgbuf] = FALSE;
+		t->vdau[pgbuf].clrfound = true;
+		t->vdau[pgbuf].stopped = true;
+		t->is_searching[pgbuf] = false;
 	}
 	vd->priv=t;
 
@@ -298,7 +293,7 @@
 
 /* Get count number of bytes from I²C-device at address adr, store them in buf. Start & stop
  * handshaking is done by this routine, ack will be sent after the last byte to inhibit further
- * sending of data. If uaccess is TRUE, data is written to user-space with put_user.
+ * sending of data. If uaccess is 'true', data is written to user-space with put_user.
  * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise
  */
 
@@ -317,7 +312,7 @@
 static int do_saa5249_ioctl(struct inode *inode, struct file *file,
 			    unsigned int cmd, void *arg)
 {
-	static int virtual_mode = FALSE;
+	static int virtual_mode = false;
 	struct video_device *vd = video_devdata(file);
 	struct saa5249_device *t=vd->priv;
 
@@ -340,7 +335,7 @@
 			if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
 				return -EINVAL;
 			memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
-			t->vdau[req->pgbuf].clrfound = TRUE;
+			t->vdau[req->pgbuf].clrfound = true;
 			return 0;
 		}
 
@@ -350,7 +345,7 @@
 
 			if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
 				return -EINVAL;
-			t->vdau[req->pgbuf].clrfound = TRUE;
+			t->vdau[req->pgbuf].clrfound = true;
 			return 0;
 		}
 
@@ -376,9 +371,9 @@
 			t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf);
 			t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10);
 			t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf);
-			t->vdau[req->pgbuf].stopped = FALSE;
-			t->vdau[req->pgbuf].clrfound = TRUE;
-			t->is_searching[req->pgbuf] = TRUE;
+			t->vdau[req->pgbuf].stopped = false;
+			t->vdau[req->pgbuf].clrfound = true;
+			t->is_searching[req->pgbuf] = true;
 			return 0;
 		}
 
@@ -430,7 +425,7 @@
 							i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40))
 							return -EIO;
 					}
-					t->vdau[req->pgbuf].clrfound = FALSE;
+					t->vdau[req->pgbuf].clrfound = false;
 					memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits));
 				}
 				else
@@ -474,7 +469,7 @@
 				return -EFAULT;
 			if (!info.hamming && !info.notfound)
 			{
-				t->is_searching[req->pgbuf] = FALSE;
+				t->is_searching[req->pgbuf] = false;
 			}
 			return 0;
 		}
@@ -530,8 +525,8 @@
 
 			if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
 				return -EINVAL;
-			t->vdau[req->pgbuf].stopped = TRUE;
-			t->is_searching[req->pgbuf] = FALSE;
+			t->vdau[req->pgbuf].stopped = true;
+			t->is_searching[req->pgbuf] = false;
 			return 0;
 		}
 
@@ -660,11 +655,11 @@
 		memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
 		memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
 		t->vdau[pgbuf].expire = 0;
-		t->vdau[pgbuf].clrfound = TRUE;
-		t->vdau[pgbuf].stopped = TRUE;
-		t->is_searching[pgbuf] = FALSE;
+		t->vdau[pgbuf].clrfound = true;
+		t->vdau[pgbuf].stopped = true;
+		t->is_searching[pgbuf] = false;
 	}
-	t->virtual_mode=FALSE;
+	t->virtual_mode = false;
 	return 0;
 
  fail:
@@ -699,7 +694,7 @@
 module_init(init_saa_5249);
 module_exit(cleanup_saa_5249);
 
-static struct file_operations saa_fops = {
+static const struct file_operations saa_fops = {
 	.owner		= THIS_MODULE,
 	.open		= saa5249_open,
 	.release       	= saa5249_release,
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index 686fd47..44dc747 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -41,7 +41,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index 90398ab..2ce3321 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -44,7 +44,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index c2374ed..c4f066d 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -71,6 +71,7 @@
 struct saa711x_state {
 	v4l2_std_id std;
 	int input;
+	int output;
 	int enable;
 	int radio;
 	int bright;
@@ -1301,7 +1302,7 @@
 		struct v4l2_routing *route = arg;
 
 		route->input = state->input;
-		route->output = 0;
+		route->output = state->output;
 		break;
 	}
 
@@ -1309,7 +1310,7 @@
 	{
 		struct v4l2_routing *route = arg;
 
-		v4l_dbg(1, debug, client, "decoder set input %d\n", route->input);
+		v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output);
 		/* saa7113 does not have these inputs */
 		if (state->ident == V4L2_IDENT_SAA7113 &&
 		    (route->input == SAA7115_COMPOSITE4 ||
@@ -1318,10 +1319,12 @@
 		}
 		if (route->input > SAA7115_SVIDEO3)
 			return -EINVAL;
-		if (state->input == route->input)
+		if (route->output > SAA7115_IPORT_ON)
+			return -EINVAL;
+		if (state->input == route->input && state->output == route->output)
 			break;
-		v4l_dbg(1, debug, client, "now setting %s input\n",
-			(route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite");
+		v4l_dbg(1, debug, client, "now setting %s input %s output\n",
+			(route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
 		state->input = route->input;
 
 		/* select mode */
@@ -1333,6 +1336,14 @@
 		saa711x_write(client, R_09_LUMA_CNTL,
 			      (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) |
 			       (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
+
+		state->output = route->output;
+		if (state->ident == V4L2_IDENT_SAA7114 ||
+			state->ident == V4L2_IDENT_SAA7115) {
+			saa711x_write(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
+			      (saa711x_read(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
+			       (state->output & 0x01));
+		}
 		break;
 	}
 
@@ -1377,6 +1388,9 @@
 	{
 		struct v4l2_sliced_vbi_data *data = arg;
 
+		/* Note: the internal field ID is inverted for NTSC,
+		   so data->field 0 maps to the saa7115 even field,
+		   whereas for PAL it maps to the saa7115 odd field. */
 		switch (data->id) {
 		case V4L2_SLICED_WSS_625:
 			if (saa711x_read(client, 0x6b) & 0xc0)
@@ -1387,17 +1401,17 @@
 		case V4L2_SLICED_CAPTION_525:
 			if (data->field == 0) {
 				/* CC */
-				if (saa711x_read(client, 0x66) & 0xc0)
+				if (saa711x_read(client, 0x66) & 0x30)
 					return -EIO;
-				data->data[0] = saa711x_read(client, 0x67);
-				data->data[1] = saa711x_read(client, 0x68);
+				data->data[0] = saa711x_read(client, 0x69);
+				data->data[1] = saa711x_read(client, 0x6a);
 				return 0;
 			}
 			/* XDS */
-			if (saa711x_read(client, 0x66) & 0x30)
+			if (saa711x_read(client, 0x66) & 0xc0)
 				return -EIO;
-			data->data[0] = saa711x_read(client, 0x69);
-			data->data[1] = saa711x_read(client, 0x6a);
+			data->data[0] = saa711x_read(client, 0x67);
+			data->data[1] = saa711x_read(client, 0x68);
 			return 0;
 		default:
 			return -EINVAL;
@@ -1406,17 +1420,8 @@
 	}
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	case VIDIOC_INT_G_REGISTER:
-	{
-		struct v4l2_register *reg = arg;
-
-		if (reg->i2c_id != I2C_DRIVERID_SAA711X)
-			return -EINVAL;
-		reg->val = saa711x_read(client, reg->reg & 0xff);
-		break;
-	}
-
-	case VIDIOC_INT_S_REGISTER:
+	case VIDIOC_DBG_G_REGISTER:
+	case VIDIOC_DBG_S_REGISTER:
 	{
 		struct v4l2_register *reg = arg;
 
@@ -1424,7 +1429,10 @@
 			return -EINVAL;
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		saa711x_write(client, reg->reg & 0xff, reg->val & 0xff);
+		if (cmd == VIDIOC_DBG_G_REGISTER)
+			reg->val = saa711x_read(client, reg->reg & 0xff);
+		else
+			saa711x_write(client, reg->reg & 0xff, reg->val & 0xff);
 		break;
 	}
 #endif
@@ -1492,6 +1500,7 @@
 		return -ENOMEM;
 	}
 	state->input = -1;
+	state->output = SAA7115_IPORT_ON;
 	state->enable = 1;
 	state->radio = 0;
 	state->bright = 128;
@@ -1550,7 +1559,7 @@
 
 static int saa711x_probe(struct i2c_adapter *adapter)
 {
-	if (adapter->class & I2C_CLASS_TV_ANALOG)
+	if (adapter->class & I2C_CLASS_TV_ANALOG || adapter->class & I2C_CLASS_TV_DIGITAL)
 		return i2c_probe(adapter, &addr_data, &saa711x_attach);
 	return 0;
 }
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
index 708fae5..269d711 100644
--- a/drivers/media/video/saa711x.c
+++ b/drivers/media/video/saa711x.c
@@ -35,7 +35,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index ad401bd..bd9c4f3 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -614,17 +614,8 @@
 		break;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	case VIDIOC_INT_G_REGISTER:
-	{
-		struct v4l2_register *reg = arg;
-
-		if (reg->i2c_id != I2C_DRIVERID_SAA7127)
-			return -EINVAL;
-		reg->val = saa7127_read(client, reg->reg & 0xff);
-		break;
-	}
-
-	case VIDIOC_INT_S_REGISTER:
+	case VIDIOC_DBG_G_REGISTER:
+	case VIDIOC_DBG_S_REGISTER:
 	{
 		struct v4l2_register *reg = arg;
 
@@ -632,7 +623,10 @@
 			return -EINVAL;
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		saa7127_write(client, reg->reg & 0xff, reg->val & 0xff);
+		if (cmd == VIDIOC_DBG_G_REGISTER)
+			reg->val = saa7127_read(client, reg->reg & 0xff);
+		else
+			saa7127_write(client, reg->reg & 0xff, reg->val & 0xff);
 		break;
 	}
 #endif
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index 89a1565..c85c8a8 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -14,7 +14,3 @@
 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 += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index afc8f35..57f1f5d 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -1,6 +1,5 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index ae984bb..89f3210 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -2469,6 +2469,11 @@
 			.amux = LINE2,
 			.gpio = 0x0200000,
 		},{
+			.name = name_comp2,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x0200000,
+		},{
 			.name = name_svideo,
 			.vmux = 8,
 			.amux = LINE2,
@@ -3183,6 +3188,107 @@
 			.amux   = LINE1,
 		}},
 	},
+	[SAA7134_BOARD_ENCORE_ENLTV] = {
+	/* Steven Walter <stevenrwalter@gmail.com>
+	   Juan Pablo Sormani <sorman@gmail.com> */
+		.name           = "Encore ENLTV",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_TNF_5335MF,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = 3,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 7,
+			.amux = 4,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = 2,
+		},{
+			.name = name_svideo,
+			.vmux = 0,
+			.amux = 2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+/*			.gpio = 0x00300001,*/
+			.gpio = 0x20000,
+
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = 0,
+		},
+	},
+	[SAA7134_BOARD_ENCORE_ENLTV_FM] = {
+  /*	Juan Pablo Sormani <sorman@gmail.com> */
+		.name           = "Encore ENLTV-FM",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_ATSC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = 3,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 7,
+			.amux = 4,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = 2,
+		},{
+			.name = name_svideo,
+			.vmux = 0,
+			.amux = 2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x20000,
+
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = 0,
+		},
+	},
+	[SAA7134_BOARD_CINERGY_HT_PCI] = {
+		.name           = "Terratec Cinergy HT PCI",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 6,
+			.amux   = LINE1,
+		}},
+	},
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -3822,6 +3928,36 @@
 		.subdevice    = 0x1172,
 		.driver_data  = SAA7134_BOARD_CINERGY_HT_PCMCIA,
 	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2342,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1131,
+		.subdevice    = 0x2341,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x3016,
+		.subdevice    = 0x2344,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1131,
+		.subdevice    = 0x230f,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x153b,
+		.subdevice    = 0x1175,
+		.driver_data  = SAA7134_BOARD_CINERGY_HT_PCI,
+	},{
 		/* --- boards without eeprom + subsystem ID --- */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3926,9 +4062,12 @@
 	case SAA7134_BOARD_KWORLD_TERMINATOR:
 	case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
 	case SAA7134_BOARD_FLYDVBT_LR301:
+	case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
 	case SAA7134_BOARD_FLYDVBTDUO:
 	case SAA7134_BOARD_PROTEUS_2309:
 	case SAA7134_BOARD_AVERMEDIA_A16AR:
+	case SAA7134_BOARD_ENCORE_ENLTV:
+	case SAA7134_BOARD_ENCORE_ENLTV_FM:
 		dev->has_remote = SAA7134_REMOTE_GPIO;
 		break;
 	case SAA7134_BOARD_FLYDVBS_LR300:
@@ -4150,6 +4289,7 @@
 		}
 		break;
 	case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+	case SAA7134_BOARD_CINERGY_HT_PCI:
 		/* make the tda10046 find its eeprom */
 		{
 		u8 data[] = { 0x3c, 0x33, 0x60};
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index c33f6a6..e3059fd 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1426,6 +1426,18 @@
 
 		}
 		break;
+	case SAA7134_BOARD_CINERGY_HT_PCI:
+		dev->dvb.frontend = dvb_attach(tda10046_attach,
+					       &cinergy_ht_config,
+					       &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+			dev->dvb.frontend->ops.tuner_ops.init = cinergy_ht_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = cinergy_ht_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = md8800_dvbt_pll_set;
+
+		}
+		break;
 	default:
 		printk("%s: Huh? unknown DVB card?\n",dev->name);
 		break;
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index daaae87..f521603 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -319,7 +319,7 @@
 	return video_usercopy(inode, file, cmd, arg, ts_do_ioctl);
 }
 
-static struct file_operations ts_fops =
+static const struct file_operations ts_fops =
 {
 	.owner	  = THIS_MODULE,
 	.open	  = ts_open,
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 6f9fe86..cce8da6 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -120,9 +120,9 @@
 	case ARB_LOST:
 	case SEQ_ERR:
 	case ST_ERR:
-		return TRUE;
+		return true;
 	default:
-		return FALSE;
+		return false;
 	}
 }
 
@@ -131,9 +131,9 @@
 	switch (status) {
 	case IDLE:
 	case DONE_STOP:
-		return TRUE;
+		return true;
 	default:
-		return FALSE;
+		return false;
 	}
 }
 
@@ -141,9 +141,9 @@
 {
 	switch (status) {
 	case BUSY:
-		return TRUE;
+		return true;
 	default:
-		return FALSE;
+		return false;
 	}
 }
 
@@ -159,8 +159,8 @@
 		saa_wait(I2C_WAIT_DELAY);
 	}
 	if (I2C_WAIT_RETRY == count)
-		return FALSE;
-	return TRUE;
+		return false;
+	return true;
 }
 
 static int i2c_reset(struct saa7134_dev *dev)
@@ -171,7 +171,7 @@
 	d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name);
 	status = i2c_get_status(dev);
 	if (!i2c_is_error(status))
-		return TRUE;
+		return true;
 	i2c_set_status(dev,status);
 
 	for (count = 0; count < I2C_WAIT_RETRY; count++) {
@@ -181,13 +181,13 @@
 		udelay(I2C_WAIT_DELAY);
 	}
 	if (I2C_WAIT_RETRY == count)
-		return FALSE;
+		return false;
 
 	if (!i2c_is_idle(status))
-		return FALSE;
+		return false;
 
 	i2c_set_attr(dev,NOP);
-	return TRUE;
+	return true;
 }
 
 static inline int i2c_send_byte(struct saa7134_dev *dev,
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 60b38de..46c583f 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -22,7 +22,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
 
@@ -41,16 +40,24 @@
 module_param(pinnacle_remote, int, 0644);    /* Choose Pinnacle PCTV remote */
 MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
 
+static int ir_rc5_remote_gap = 885;
+module_param(ir_rc5_remote_gap, int, 0644);
+static int ir_rc5_key_timeout = 115;
+module_param(ir_rc5_key_timeout, int, 0644);
+
 #define dprintk(fmt, arg...)	if (ir_debug) \
 	printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
 #define i2cdprintk(fmt, arg...)    if (ir_debug) \
 	printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
 
+/** rc5 functions */
+static int saa7134_rc5_irq(struct saa7134_dev *dev);
+
 /* -------------------- GPIO generic keycode builder -------------------- */
 
 static int build_key(struct saa7134_dev *dev)
 {
-	struct saa7134_ir *ir = dev->remote;
+	struct card_ir *ir = dev->remote;
 	u32 gpio, data;
 
 	/* rising SAA7134_GPIO_GPRESCAN reads the status */
@@ -135,16 +142,19 @@
 
 void saa7134_input_irq(struct saa7134_dev *dev)
 {
-	struct saa7134_ir *ir = dev->remote;
+	struct card_ir *ir = dev->remote;
 
-	if (!ir->polling)
+	if (!ir->polling && !ir->rc5_gpio) {
 		build_key(dev);
+	} else if (ir->rc5_gpio) {
+		saa7134_rc5_irq(dev);
+	}
 }
 
 static void saa7134_input_timer(unsigned long data)
 {
 	struct saa7134_dev *dev = (struct saa7134_dev*)data;
-	struct saa7134_ir *ir = dev->remote;
+	struct card_ir *ir = dev->remote;
 	unsigned long timeout;
 
 	build_key(dev);
@@ -152,7 +162,7 @@
 	mod_timer(&ir->timer, timeout);
 }
 
-static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir)
+static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
 {
 	if (ir->polling) {
 		init_timer(&ir->timer);
@@ -160,6 +170,19 @@
 		ir->timer.data     = (unsigned long)dev;
 		ir->timer.expires  = jiffies + HZ;
 		add_timer(&ir->timer);
+	} else if (ir->rc5_gpio) {
+		/* set timer_end for code completion */
+		init_timer(&ir->timer_end);
+		ir->timer_end.function = ir_rc5_timer_end;
+		ir->timer_end.data = (unsigned long)ir;
+		init_timer(&ir->timer_keyup);
+		ir->timer_keyup.function = ir_rc5_timer_keyup;
+		ir->timer_keyup.data = (unsigned long)ir;
+		ir->shift_by = 2;
+		ir->start = 0x2;
+		ir->addr = 0x17;
+		ir->rc5_key_timeout = ir_rc5_key_timeout;
+		ir->rc5_remote_gap = ir_rc5_remote_gap;
 	}
 }
 
@@ -171,13 +194,14 @@
 
 int saa7134_input_init1(struct saa7134_dev *dev)
 {
-	struct saa7134_ir *ir;
+	struct card_ir *ir;
 	struct input_dev *input_dev;
 	IR_KEYTAB_TYPE *ir_codes = NULL;
 	u32 mask_keycode = 0;
 	u32 mask_keydown = 0;
 	u32 mask_keyup   = 0;
 	int polling      = 0;
+	int rc5_gpio	 = 0;
 	int ir_type      = IR_TYPE_OTHER;
 	int err;
 
@@ -296,6 +320,18 @@
 		mask_keycode = 0x0001F00;
 		mask_keydown = 0x0040000;
 		break;
+	case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+		ir_codes     = ir_codes_asus_pc39;
+		mask_keydown = 0x0040000;
+		rc5_gpio = 1;
+		break;
+	case SAA7134_BOARD_ENCORE_ENLTV:
+	case SAA7134_BOARD_ENCORE_ENLTV_FM:
+		ir_codes     = ir_codes_encore_enltv;
+		mask_keycode = 0x00007f;
+		mask_keyup   = 0x040000;
+		polling      = 50; // ms
+		break;
 	}
 	if (NULL == ir_codes) {
 		printk("%s: Oops: IR config error [card=%d]\n",
@@ -317,6 +353,7 @@
 	ir->mask_keydown = mask_keydown;
 	ir->mask_keyup   = mask_keyup;
 	ir->polling      = polling;
+	ir->rc5_gpio	 = rc5_gpio;
 
 	/* init input device */
 	snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
@@ -403,6 +440,49 @@
 	}
 
 }
+
+static int saa7134_rc5_irq(struct saa7134_dev *dev)
+{
+	struct card_ir *ir = dev->remote;
+	struct timeval tv;
+	u32 gap;
+	unsigned long current_jiffies, timeout;
+
+	/* get time of bit */
+	current_jiffies = jiffies;
+	do_gettimeofday(&tv);
+
+	/* avoid overflow with gap >1s */
+	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+		gap = 200000;
+	} else {
+		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+		    tv.tv_usec - ir->base_time.tv_usec;
+	}
+
+	/* active code => add bit */
+	if (ir->active) {
+		/* only if in the code (otherwise spurious IRQ or timer
+		   late) */
+		if (ir->last_bit < 28) {
+			ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
+			    ir_rc5_remote_gap;
+			ir->code |= 1 << ir->last_bit;
+		}
+		/* starting new code */
+	} else {
+		ir->active = 1;
+		ir->code = 0;
+		ir->base_time = tv;
+		ir->last_bit = 0;
+
+		timeout = current_jiffies + (500 + 30 * HZ) / 1000;
+		mod_timer(&ir->timer_end, timeout);
+	}
+
+	return 1;
+}
+
 /* ----------------------------------------------------------------------
  * Local variables:
  * c-basic-offset: 8
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index bfcb860..72444f0 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -563,7 +563,7 @@
 	return mask;
 }
 
-struct file_operations saa7134_dsp_fops = {
+const struct file_operations saa7134_dsp_fops = {
 	.owner   = THIS_MODULE,
 	.open    = dsp_open,
 	.release = dsp_release,
@@ -804,7 +804,7 @@
 	}
 }
 
-struct file_operations saa7134_mixer_fops = {
+const struct file_operations saa7134_mixer_fops = {
 	.owner   = THIS_MODULE,
 	.open    = mixer_open,
 	.release = mixer_release,
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 830617e..f2cb630 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -2336,7 +2336,7 @@
 	return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
 }
 
-static struct file_operations video_fops =
+static const struct file_operations video_fops =
 {
 	.owner	  = THIS_MODULE,
 	.open	  = video_open,
@@ -2349,7 +2349,7 @@
 	.llseek   = no_llseek,
 };
 
-static struct file_operations radio_fops =
+static const struct file_operations radio_fops =
 {
 	.owner	  = THIS_MODULE,
 	.open	  = video_open,
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index e88ad7b..b3e3957 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -41,14 +41,10 @@
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
 #include <media/video-buf-dvb.h>
+#endif
 
-#ifndef TRUE
-# define TRUE (1==1)
-#endif
-#ifndef FALSE
-# define FALSE (1==0)
-#endif
 #define UNSET (-1U)
 
 /* ----------------------------------------------------------- */
@@ -232,6 +228,9 @@
 #define SAA7134_BOARD_VIDEOMATE_DVBT_200A  103
 #define SAA7134_BOARD_HAUPPAUGE_HVR1110    104
 #define SAA7134_BOARD_CINERGY_HT_PCMCIA    105
+#define SAA7134_BOARD_ENCORE_ENLTV         106
+#define SAA7134_BOARD_ENCORE_ENLTV_FM      107
+#define SAA7134_BOARD_CINERGY_HT_PCI       108
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
@@ -411,20 +410,6 @@
 	struct snd_pcm_substream   *substream;
 };
 
-/* IR input */
-struct saa7134_ir {
-	struct input_dev           *dev;
-	struct ir_input_state      ir;
-	char                       name[32];
-	char                       phys[32];
-	u32                        mask_keycode;
-	u32                        mask_keydown;
-	u32                        mask_keyup;
-	int                        polling;
-	u32                        last_gpio;
-	struct timer_list          timer;
-};
-
 /* ts/mpeg status */
 struct saa7134_ts {
 	/* TS capture */
@@ -463,7 +448,7 @@
 
 	/* infrared remote */
 	int                        has_remote;
-	struct saa7134_ir          *remote;
+	struct card_ir		   *remote;
 
 	/* pci i/o */
 	char                       name[32];
@@ -543,9 +528,11 @@
 	struct work_struct         empress_workqueue;
 	int                        empress_started;
 
+#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
 	/* SAA7134_MPEG_DVB only */
 	struct videobuf_dvb        dvb;
 	int (*original_demod_sleep)(struct dvb_frontend* fe);
+#endif
 };
 
 /* ----------------------------------------------------------- */
@@ -683,8 +670,8 @@
 /* ----------------------------------------------------------- */
 /* saa7134-oss.c                                               */
 
-extern struct file_operations saa7134_dsp_fops;
-extern struct file_operations saa7134_mixer_fops;
+extern const struct file_operations saa7134_dsp_fops;
+extern const struct file_operations saa7134_mixer_fops;
 
 int saa7134_oss_init1(struct saa7134_dev *dev);
 int saa7134_oss_fini(struct saa7134_dev *dev);
@@ -698,6 +685,7 @@
 void saa7134_input_irq(struct saa7134_dev *dev);
 void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir);
 
+
 /*
  * Local variables:
  * c-basic-offset: 8
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 9c30841..e0fdb1a 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -38,7 +38,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
index 746cadb..8615a60 100644
--- a/drivers/media/video/saa7191.c
+++ b/drivers/media/video/saa7191.c
@@ -17,7 +17,6 @@
 #include <linux/major.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 
 #include <linux/videodev.h>
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
index 7aeec57..038448f 100644
--- a/drivers/media/video/se401.c
+++ b/drivers/media/video/se401.c
@@ -1185,7 +1185,7 @@
 	return 0;
 }
 
-static struct file_operations se401_fops = {
+static const struct file_operations se401_fops = {
 	.owner =	THIS_MODULE,
 	.open =         se401_open,
 	.release =      se401_close,
diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig
index cf552e6..1a7ccb66 100644
--- a/drivers/media/video/sn9c102/Kconfig
+++ b/drivers/media/video/sn9c102/Kconfig
@@ -1,9 +1,9 @@
 config USB_SN9C102
-	tristate "USB SN9C10x PC Camera Controller support"
+	tristate "USB SN9C1xx PC Camera Controller support"
 	depends on USB && VIDEO_V4L1
 	---help---
 	  Say Y here if you want support for cameras based on SONiX SN9C101,
-	  SN9C102 or SN9C103 PC Camera Controllers.
+	  SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
 
 	  See <file:Documentation/video4linux/sn9c102.txt> for more info.
 
diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile
index 536ad30..30e3dfe 100644
--- a/drivers/media/video/sn9c102/Makefile
+++ b/drivers/media/video/sn9c102/Makefile
@@ -1,5 +1,5 @@
 sn9c102-objs    := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
-		   sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \
+		   sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \
 		   sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
 		   sn9c102_tas5130d1b.o
 
diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
index 2c6ff39..5428f34 100644
--- a/drivers/media/video/sn9c102/sn9c102.h
+++ b/drivers/media/video/sn9c102/sn9c102.h
@@ -1,5 +1,5 @@
 /***************************************************************************
- * V4L2 driver for SN9C10x PC Camera Controllers                           *
+ * V4L2 driver for SN9C1xx PC Camera Controllers                           *
  *                                                                         *
  * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
@@ -37,33 +37,10 @@
 #include <linux/string.h>
 #include <linux/stddef.h>
 
+#include "sn9c102_config.h"
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
-/*****************************************************************************/
-
-#define SN9C102_DEBUG
-#define SN9C102_DEBUG_LEVEL       2
-#define SN9C102_MAX_DEVICES       64
-#define SN9C102_PRESERVE_IMGSCALE 0
-#define SN9C102_FORCE_MUNMAP      0
-#define SN9C102_MAX_FRAMES        32
-#define SN9C102_URBS              2
-#define SN9C102_ISO_PACKETS       7
-#define SN9C102_ALTERNATE_SETTING 8
-#define SN9C102_URB_TIMEOUT       msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
-#define SN9C102_CTRL_TIMEOUT      300
-#define SN9C102_FRAME_TIMEOUT     2
-
-/*****************************************************************************/
-
-enum sn9c102_bridge {
-	BRIDGE_SN9C101 = 0x01,
-	BRIDGE_SN9C102 = 0x02,
-	BRIDGE_SN9C103 = 0x04,
-};
-
-SN9C102_ID_TABLE
-SN9C102_SENSOR_TABLE
 
 enum sn9c102_frame_state {
 	F_UNUSED,
@@ -99,13 +76,11 @@
 	STREAM_ON,
 };
 
-typedef char sn9c103_sof_header_t[18];
-typedef char sn9c102_sof_header_t[12];
-typedef char sn9c102_eof_header_t[4];
+typedef char sn9c102_sof_header_t[62];
 
 struct sn9c102_sysfs_attr {
 	u8 reg, i2c_reg;
-	sn9c103_sof_header_t frame_header;
+	sn9c102_sof_header_t frame_header;
 };
 
 struct sn9c102_module_param {
@@ -137,8 +112,8 @@
 	struct v4l2_jpegcompression compression;
 
 	struct sn9c102_sysfs_attr sysfs;
-	sn9c103_sof_header_t sof_header;
-	u16 reg[63];
+	sn9c102_sof_header_t sof_header;
+	u16 reg[384];
 
 	struct sn9c102_module_param module_param;
 
@@ -155,10 +130,7 @@
 struct sn9c102_device*
 sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
 {
-	if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
-		return cam;
-
-	return NULL;
+	return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
 }
 
 
@@ -169,6 +141,19 @@
 	memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
 }
 
+
+enum sn9c102_bridge
+sn9c102_get_bridge(struct sn9c102_device* cam)
+{
+	return cam->bridge;
+}
+
+
+struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam)
+{
+	return &cam->sensor;
+}
+
 /*****************************************************************************/
 
 #undef DBG
diff --git a/drivers/media/video/sn9c102/sn9c102_config.h b/drivers/media/video/sn9c102/sn9c102_config.h
new file mode 100644
index 0000000..0f4e037
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_config.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * Global parameters for the V4L2 driver for SN9C1xx PC Camera Controllers *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#ifndef _SN9C102_CONFIG_H_
+#define _SN9C102_CONFIG_H_
+
+#include <linux/types.h>
+#include <linux/jiffies.h>
+
+#define SN9C102_DEBUG
+#define SN9C102_DEBUG_LEVEL       2
+#define SN9C102_MAX_DEVICES       64
+#define SN9C102_PRESERVE_IMGSCALE 0
+#define SN9C102_FORCE_MUNMAP      0
+#define SN9C102_MAX_FRAMES        32
+#define SN9C102_URBS              2
+#define SN9C102_ISO_PACKETS       7
+#define SN9C102_ALTERNATE_SETTING 8
+#define SN9C102_URB_TIMEOUT       msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
+#define SN9C102_CTRL_TIMEOUT      300
+#define SN9C102_FRAME_TIMEOUT     0
+
+/*****************************************************************************/
+
+static const u8 SN9C102_Y_QTABLE0[64] = {
+	 8,   5,   5,   8,  12,  20,  25,  30,
+	 6,   6,   7,   9,  13,  29,  30,  27,
+	 7,   6,   8,  12,  20,  28,  34,  28,
+	 7,   8,  11,  14,  25,  43,  40,  31,
+	 9,  11,  18,  28,  34,  54,  51,  38,
+	12,  17,  27,  32,  40,  52,  56,  46,
+	24,  32,  39,  43,  51,  60,  60,  50,
+	36,  46,  47,  49,  56,  50,  51,  49
+};
+
+static const u8 SN9C102_UV_QTABLE0[64] = {
+	 8,   9,  12,  23,  49,  49,  49,  49,
+	 9,  10,  13,  33,  49,  49,  49,  49,
+	12,  13,  28,  49,  49,  49,  49,  49,
+	23,  33,  49,  49,  49,  49,  49,  49,
+	49,  49,  49,  49,  49,  49,  49,  49,
+	49,  49,  49,  49,  49,  49,  49,  49,
+	49,  49,  49,  49,  49,  49,  49,  49,
+	49,  49,  49,  49,  49,  49,  49,  49
+};
+
+static const u8 SN9C102_Y_QTABLE1[64] = {
+	16,  11,  10,  16,  24,  40,  51,  61,
+	12,  12,  14,  19,  26,  58,  60,  55,
+	14,  13,  16,  24,  40,  57,  69,  56,
+	14,  17,  22,  29,  51,  87,  80,  62,
+	18,  22,  37,  56,  68, 109, 103,  77,
+	24,  35,  55,  64,  81, 104, 113,  92,
+	49,  64,  78,  87, 103, 121, 120, 101,
+	72,  92,  95,  98, 112, 100, 103,  99
+};
+
+static const u8 SN9C102_UV_QTABLE1[64] = {
+	17,  18,  24,  47,  99,  99,  99,  99,
+	18,  21,  26,  66,  99,  99,  99,  99,
+	24,  26,  56,  99,  99,  99,  99,  99,
+	47,  66,  99,  99,  99,  99,  99,  99,
+	99,  99,  99,  99,  99,  99,  99,  99,
+	99,  99,  99,  99,  99,  99,  99,  99,
+	99,  99,  99,  99,  99,  99,  99,  99,
+	99,  99,  99,  99,  99,  99,  99,  99
+};
+
+#endif /* _SN9C102_CONFIG_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 18458d4..d0e2b40 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -1,7 +1,7 @@
 /***************************************************************************
- * V4L2 driver for SN9C10x PC Camera Controllers                           *
+ * V4L2 driver for SN9C1xx PC Camera Controllers                           *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -43,12 +43,12 @@
 
 /*****************************************************************************/
 
-#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C10x PC Camera Controllers"
+#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C1xx PC Camera Controllers"
 #define SN9C102_MODULE_AUTHOR   "(C) 2004-2006 Luca Risolia"
 #define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
 #define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.27"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 27)
+#define SN9C102_MODULE_VERSION  "1:1.34"
+#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 34)
 
 /*****************************************************************************/
 
@@ -91,7 +91,8 @@
 				       SN9C102_FRAME_TIMEOUT};
 module_param_array(frame_timeout, uint, NULL, 0644);
 MODULE_PARM_DESC(frame_timeout,
-		 "\n<n[,...]> Timeout for a video frame in seconds."
+		 "\n<0|n[,...]> Timeout for a video frame in seconds before"
+		 "\nreturning an I/O error; 0 for infinity."
 		 "\nThis parameter is specific for each detected camera."
 		 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
 		 "\n");
@@ -113,32 +114,13 @@
 
 /*****************************************************************************/
 
-static sn9c102_sof_header_t sn9c102_sof_header[] = {
-	{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00},
-	{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
-};
-
-static sn9c103_sof_header_t sn9c103_sof_header[] = {
-	{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20},
-};
-
-static sn9c102_eof_header_t sn9c102_eof_header[] = {
-	{0x00, 0x00, 0x00, 0x00},
-	{0x40, 0x00, 0x00, 0x00},
-	{0x80, 0x00, 0x00, 0x00},
-	{0xc0, 0x00, 0x00, 0x00},
-};
-
-/*****************************************************************************/
-
 static u32
 sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
 			enum sn9c102_io_method io)
 {
 	struct v4l2_pix_format* p = &(cam->sensor.pix_format);
 	struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
-	const size_t imagesize = cam->module_param.force_munmap ||
-				 io == IO_READ ?
+	size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
 				 (p->width * p->height * p->priv) / 8 :
 				 (r->width * r->height * p->priv) / 8;
 	void* buff = NULL;
@@ -147,9 +129,13 @@
 	if (count > SN9C102_MAX_FRAMES)
 		count = SN9C102_MAX_FRAMES;
 
+	if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120)
+		imagesize += 589 + 2; /* length of JPEG header + EOI marker */
+
 	cam->nbuffers = count;
 	while (cam->nbuffers > 0) {
-		if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+		if ((buff = vmalloc_32_user(cam->nbuffers *
+					    PAGE_ALIGN(imagesize))))
 			break;
 		cam->nbuffers--;
 	}
@@ -322,9 +308,21 @@
 sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
 			      struct sn9c102_sensor* sensor)
 {
-	int r;
+	int r , err = 0;
+
 	r = sn9c102_read_reg(cam, 0x08);
-	return (r < 0 || (r >= 0 && !(r & 0x08))) ? -EIO : 0;
+	if (r < 0)
+		err += r;
+
+	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
+		if (!(r & 0x08))
+			err += -1;
+	} else {
+		if (r & 0x08)
+			err += -1;
+	}
+
+	return err ? -EIO : 0;
 }
 
 
@@ -415,7 +413,7 @@
 	data[4] = data3;
 	data[5] = data4;
 	data[6] = data5;
-	data[7] = 0x14;
+	data[7] = 0x17;
 	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
 			      0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
 	if (res < 0)
@@ -467,31 +465,35 @@
 
 /*****************************************************************************/
 
-static void*
-sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
+static size_t sn9c102_sof_length(struct sn9c102_device* cam)
 {
-	size_t soflen = 0, i;
-	u8 j, n = 0;
-
 	switch (cam->bridge) {
 	case BRIDGE_SN9C101:
 	case BRIDGE_SN9C102:
-		soflen = sizeof(sn9c102_sof_header_t);
-		n = sizeof(sn9c102_sof_header) / soflen;
-		break;
+		return 12;
 	case BRIDGE_SN9C103:
-		soflen = sizeof(sn9c103_sof_header_t);
-		n = sizeof(sn9c103_sof_header) / soflen;
+		return 18;
+	case BRIDGE_SN9C105:
+	case BRIDGE_SN9C120:
+		return 62;
 	}
 
+	return 0;
+}
+
+
+static void*
+sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
+{
+	char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
+	size_t soflen = 0, i;
+
+	soflen = sn9c102_sof_length(cam);
+
 	for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
-		for (j = 0; j < n; j++)
-			/* The invariable part of the header is 6 bytes long */
-			if ((cam->bridge != BRIDGE_SN9C103 &&
-			    !memcmp(mem + i, sn9c102_sof_header[j], 6)) ||
-			    (cam->bridge == BRIDGE_SN9C103 &&
-			    !memcmp(mem + i, sn9c103_sof_header[j], 6))) {
-				memcpy(cam->sof_header, mem + i, soflen);
+		if (!memcmp(mem + i, sof_header, sizeof(sof_header))) {
+			memcpy(cam->sof_header, mem + i,
+			       sizeof(sn9c102_sof_header_t));
 				/* Skip the header */
 				return mem + i + soflen;
 			}
@@ -503,21 +505,123 @@
 static void*
 sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
 {
-	size_t eoflen = sizeof(sn9c102_eof_header_t), i;
-	unsigned j, n = sizeof(sn9c102_eof_header) / eoflen;
+	char eof_header[4][4] = {
+		{0x00, 0x00, 0x00, 0x00},
+		{0x40, 0x00, 0x00, 0x00},
+		{0x80, 0x00, 0x00, 0x00},
+		{0xc0, 0x00, 0x00, 0x00},
+	};
+	size_t i, j;
 
-	if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
+	if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
+	    cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
 		return NULL; /* EOF header does not exist in compressed data */
 
-	for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++)
-		for (j = 0; j < n; j++)
-			if (!memcmp(mem + i, sn9c102_eof_header[j], eoflen))
+	for (i = 0; (len >= 4) && (i <= len - 4); i++)
+		for (j = 0; j < ARRAY_SIZE(eof_header); j++)
+			if (!memcmp(mem + i, eof_header[j], 4))
 				return mem + i;
 
 	return NULL;
 }
 
 
+static void
+sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
+{
+	static u8 jpeg_header[589] = {
+		0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
+		0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
+		0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
+		0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16,
+		0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16,
+		0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29,
+		0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29,
+		0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
+		0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28,
+		0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+		0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+		0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+		0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+		0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2,
+		0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+		0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01,
+		0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
+		0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00,
+		0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
+		0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
+		0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+		0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
+		0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
+		0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
+		0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
+		0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
+		0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
+		0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
+		0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+		0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+		0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
+		0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
+		0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
+		0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
+		0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
+		0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
+		0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
+		0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
+		0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+		0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
+		0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
+		0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19,
+		0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+		0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
+		0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
+		0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
+		0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+		0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+		0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
+		0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
+		0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+		0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
+		0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
+		0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11,
+		0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02,
+		0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03,
+		0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+	};
+	u8 *pos = f->bufmem;
+
+	memcpy(pos, jpeg_header, sizeof(jpeg_header));
+	*(pos + 6) = 0x00;
+	*(pos + 7 + 64) = 0x01;
+	if (cam->compression.quality == 0) {
+		memcpy(pos + 7, SN9C102_Y_QTABLE0, 64);
+		memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64);
+	} else if (cam->compression.quality == 1) {
+		memcpy(pos + 7, SN9C102_Y_QTABLE1, 64);
+		memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64);
+	}
+	*(pos + 564) = cam->sensor.pix_format.width & 0xFF;
+	*(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF;
+	*(pos + 562) = cam->sensor.pix_format.height & 0xFF;
+	*(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF;
+	*(pos + 567) = 0x21;
+
+	f->buf.bytesused += sizeof(jpeg_header);
+}
+
+
+static void
+sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
+{
+	static const u8 eoi_marker[2] = {0xff, 0xd9};
+
+	memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker));
+	f->buf.bytesused += sizeof(eoi_marker);
+}
+
+
 static void sn9c102_urb_complete(struct urb *urb)
 {
 	struct sn9c102_device* cam = urb->context;
@@ -535,7 +639,7 @@
 		cam->stream = STREAM_OFF;
 		if ((*f))
 			(*f)->state = F_QUEUED;
-		DBG(3, "Stream interrupted");
+		DBG(3, "Stream interrupted by application");
 		wake_up(&cam->wait_stream);
 	}
 
@@ -557,10 +661,9 @@
 	imagesize = (cam->sensor.pix_format.width *
 		     cam->sensor.pix_format.height *
 		     cam->sensor.pix_format.priv) / 8;
-
-	soflen = (cam->bridge) == BRIDGE_SN9C103 ?
-				  sizeof(sn9c103_sof_header_t) :
-				  sizeof(sn9c102_sof_header_t);
+	if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
+		imagesize += 589; /* length of jpeg header */
+	soflen = sn9c102_sof_length(cam);
 
 	for (i = 0; i < urb->number_of_packets; i++) {
 		unsigned int img, len, status;
@@ -610,12 +713,21 @@
 				(*f)->buf.bytesused += img;
 
 				if ((*f)->buf.bytesused == imagesize ||
-				    (cam->sensor.pix_format.pixelformat ==
-						V4L2_PIX_FMT_SN9C10X && eof)) {
+				    ((cam->sensor.pix_format.pixelformat ==
+				      V4L2_PIX_FMT_SN9C10X ||
+				      cam->sensor.pix_format.pixelformat ==
+				      V4L2_PIX_FMT_JPEG) && eof)) {
 					u32 b;
+
+					if (cam->sensor.pix_format.pixelformat
+					    == V4L2_PIX_FMT_JPEG)
+						sn9c102_write_eoimarker(cam,
+									(*f));
+
 					b = (*f)->buf.bytesused;
 					(*f)->state = F_DONE;
 					(*f)->buf.sequence= ++cam->frame_count;
+
 					spin_lock(&cam->queue_lock);
 					list_move_tail(&(*f)->frame,
 						       &cam->outqueue);
@@ -627,8 +739,10 @@
 					else
 						(*f) = NULL;
 					spin_unlock(&cam->queue_lock);
+
 					memcpy(cam->sysfs.frame_header,
 					       cam->sof_header, soflen);
+
 					DBG(3, "Video frame captured: %lu "
 					       "bytes", (unsigned long)(b));
 
@@ -661,6 +775,9 @@
 			(*f)->buf.bytesused = 0;
 			len -= (sof - pos);
 			pos = sof;
+			if (cam->sensor.pix_format.pixelformat ==
+			    V4L2_PIX_FMT_JPEG)
+				sn9c102_write_jpegheader(cam, (*f));
 			DBG(3, "SOF detected: new video frame");
 			if (len)
 				goto redo;
@@ -671,7 +788,9 @@
 				goto end_of_frame; /* (1) */
 			else {
 				if (cam->sensor.pix_format.pixelformat ==
-				    V4L2_PIX_FMT_SN9C10X) {
+				    V4L2_PIX_FMT_SN9C10X ||
+				    cam->sensor.pix_format.pixelformat ==
+				    V4L2_PIX_FMT_JPEG) {
 					eof = sof - soflen;
 					goto end_of_frame;
 				} else {
@@ -701,13 +820,11 @@
 {
 	struct usb_device *udev = cam->usbdev;
 	struct urb* urb;
-	const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512,
-						       680, 800, 900, 1023};
-	const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512,
-						       680, 800, 900, 1003};
-	const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ?
-			    sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] :
-			    sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
+	struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
+						    usb_ifnum_to_if(udev, 0),
+						    SN9C102_ALTERNATE_SETTING);
+	const unsigned int psz = le16_to_cpu(altsetting->
+					     endpoint[0].desc.wMaxPacketSize);
 	s8 i, j;
 	int err = 0;
 
@@ -775,7 +892,7 @@
 	return 0;
 
 free_urbs:
-	for (i = 0; i < SN9C102_URBS; i++)
+	for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
 		usb_free_urb(cam->urb[i]);
 
 free_buffers:
@@ -834,29 +951,29 @@
 /*****************************************************************************/
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count)
+static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)
 {
-	char str[5];
+	char str[7];
 	char* endp;
 	unsigned long val;
 
-	if (len < 4) {
+	if (len < 6) {
 		strncpy(str, buff, len);
 		str[len+1] = '\0';
 	} else {
 		strncpy(str, buff, 4);
-		str[4] = '\0';
+		str[6] = '\0';
 	}
 
 	val = simple_strtoul(str, &endp, 0);
 
 	*count = 0;
-	if (val <= 0xff)
+	if (val <= 0xffff)
 		*count = (ssize_t)(endp - str);
 	if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
 		*count += 1;
 
-	return (u8)val;
+	return (u16)val;
 }
 
 /*
@@ -873,7 +990,8 @@
 	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
 		return -ERESTARTSYS;
 
-	cam = video_get_drvdata(to_video_device(cd));
+	cam = video_get_drvdata(container_of(cd, struct video_device,
+					     class_dev));
 	if (!cam) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -ENODEV;
@@ -891,27 +1009,28 @@
 sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len)
 {
 	struct sn9c102_device* cam;
-	u8 index;
+	u16 index;
 	ssize_t count;
 
 	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
 		return -ERESTARTSYS;
 
-	cam = video_get_drvdata(to_video_device(cd));
+	cam = video_get_drvdata(container_of(cd, struct video_device,
+					     class_dev));
 	if (!cam) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -ENODEV;
 	}
 
-	index = sn9c102_strtou8(buf, len, &count);
-	if (index > 0x1f || !count) {
+	index = sn9c102_strtou16(buf, len, &count);
+	if (index >= ARRAY_SIZE(cam->reg) || !count) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -EINVAL;
 	}
 
 	cam->sysfs.reg = index;
 
-	DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg);
+	DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg);
 	DBG(3, "Written bytes: %zd", count);
 
 	mutex_unlock(&sn9c102_sysfs_lock);
@@ -929,7 +1048,8 @@
 	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
 		return -ERESTARTSYS;
 
-	cam = video_get_drvdata(to_video_device(cd));
+	cam = video_get_drvdata(container_of(cd, struct video_device,
+					     class_dev));
 	if (!cam) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -ENODEV;
@@ -954,20 +1074,21 @@
 sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
 {
 	struct sn9c102_device* cam;
-	u8 value;
+	u16 value;
 	ssize_t count;
 	int err;
 
 	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
 		return -ERESTARTSYS;
 
-	cam = video_get_drvdata(to_video_device(cd));
+	cam = video_get_drvdata(container_of(cd, struct video_device,
+					     class_dev));
 	if (!cam) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -ENODEV;
 	}
 
-	value = sn9c102_strtou8(buf, len, &count);
+	value = sn9c102_strtou16(buf, len, &count);
 	if (!count) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -EINVAL;
@@ -979,7 +1100,7 @@
 		return -EIO;
 	}
 
-	DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X",
+	DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X",
 	    cam->sysfs.reg, value);
 	DBG(3, "Written bytes: %zd", count);
 
@@ -997,7 +1118,8 @@
 	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
 		return -ERESTARTSYS;
 
-	cam = video_get_drvdata(to_video_device(cd));
+	cam = video_get_drvdata(container_of(cd, struct video_device,
+					     class_dev));
 	if (!cam) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -ENODEV;
@@ -1017,19 +1139,20 @@
 sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
 {
 	struct sn9c102_device* cam;
-	u8 index;
+	u16 index;
 	ssize_t count;
 
 	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
 		return -ERESTARTSYS;
 
-	cam = video_get_drvdata(to_video_device(cd));
+	cam = video_get_drvdata(container_of(cd, struct video_device,
+					     class_dev));
 	if (!cam) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -ENODEV;
 	}
 
-	index = sn9c102_strtou8(buf, len, &count);
+	index = sn9c102_strtou16(buf, len, &count);
 	if (!count) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -EINVAL;
@@ -1055,7 +1178,8 @@
 	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
 		return -ERESTARTSYS;
 
-	cam = video_get_drvdata(to_video_device(cd));
+	cam = video_get_drvdata(container_of(cd, struct video_device,
+					     class_dev));
 	if (!cam) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -ENODEV;
@@ -1085,14 +1209,15 @@
 sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
 {
 	struct sn9c102_device* cam;
-	u8 value;
+	u16 value;
 	ssize_t count;
 	int err;
 
 	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
 		return -ERESTARTSYS;
 
-	cam = video_get_drvdata(to_video_device(cd));
+	cam = video_get_drvdata(container_of(cd, struct video_device,
+					     class_dev));
 	if (!cam) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -ENODEV;
@@ -1103,7 +1228,7 @@
 		return -ENOSYS;
 	}
 
-	value = sn9c102_strtou8(buf, len, &count);
+	value = sn9c102_strtou16(buf, len, &count);
 	if (!count) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -EINVAL;
@@ -1131,13 +1256,14 @@
 	struct sn9c102_device* cam;
 	enum sn9c102_bridge bridge;
 	ssize_t res = 0;
-	u8 value;
+	u16 value;
 	ssize_t count;
 
 	if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
 		return -ERESTARTSYS;
 
-	cam = video_get_drvdata(to_video_device(cd));
+	cam = video_get_drvdata(container_of(cd, struct video_device,
+					     class_dev));
 	if (!cam) {
 		mutex_unlock(&sn9c102_sysfs_lock);
 		return -ENODEV;
@@ -1147,7 +1273,7 @@
 
 	mutex_unlock(&sn9c102_sysfs_lock);
 
-	value = sn9c102_strtou8(buf, len, &count);
+	value = sn9c102_strtou16(buf, len, &count);
 	if (!count)
 		return -EINVAL;
 
@@ -1160,9 +1286,11 @@
 			res = sn9c102_store_val(cd, buf, len);
 		break;
 	case BRIDGE_SN9C103:
+	case BRIDGE_SN9C105:
+	case BRIDGE_SN9C120:
 		if (value > 0x7f)
 			return -EINVAL;
-		if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0)
+		if ((res = sn9c102_store_reg(cd, "0x07", 4)) >= 0)
 			res = sn9c102_store_val(cd, buf, len);
 		break;
 	}
@@ -1175,10 +1303,10 @@
 sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len)
 {
 	ssize_t res = 0;
-	u8 value;
+	u16 value;
 	ssize_t count;
 
-	value = sn9c102_strtou8(buf, len, &count);
+	value = sn9c102_strtou16(buf, len, &count);
 	if (!count || value > 0x7f)
 		return -EINVAL;
 
@@ -1193,10 +1321,10 @@
 sn9c102_store_red(struct class_device* cd, const char* buf, size_t len)
 {
 	ssize_t res = 0;
-	u8 value;
+	u16 value;
 	ssize_t count;
 
-	value = sn9c102_strtou8(buf, len, &count);
+	value = sn9c102_strtou16(buf, len, &count);
 	if (!count || value > 0x7f)
 		return -EINVAL;
 
@@ -1212,7 +1340,8 @@
 	struct sn9c102_device* cam;
 	ssize_t count;
 
-	cam = video_get_drvdata(to_video_device(cd));
+	cam = video_get_drvdata(container_of(cd, struct video_device,
+					     class_dev));
 	if (!cam)
 		return -ENODEV;
 
@@ -1243,30 +1372,36 @@
 static int sn9c102_create_sysfs(struct sn9c102_device* cam)
 {
 	struct video_device *v4ldev = cam->v4ldev;
-	int rc;
+	int err = 0;
 
-	rc = video_device_create_file(v4ldev, &class_device_attr_reg);
-	if (rc) goto err;
-	rc = video_device_create_file(v4ldev, &class_device_attr_val);
-	if (rc) goto err_reg;
-	rc = video_device_create_file(v4ldev, &class_device_attr_frame_header);
-	if (rc) goto err_val;
+	if ((err = video_device_create_file(v4ldev, &class_device_attr_reg)))
+		goto err_out;
+	if ((err = video_device_create_file(v4ldev, &class_device_attr_val)))
+		goto err_reg;
+	if ((err = video_device_create_file(v4ldev,
+					    &class_device_attr_frame_header)))
+		goto err_val;
 
 	if (cam->sensor.sysfs_ops) {
-		rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
-		if (rc) goto err_frhead;
-		rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val);
-		if (rc) goto err_i2c_reg;
+		if ((err = video_device_create_file(v4ldev,
+						  &class_device_attr_i2c_reg)))
+			goto err_frame_header;
+		if ((err = video_device_create_file(v4ldev,
+						  &class_device_attr_i2c_val)))
+			goto err_i2c_reg;
 	}
 
 	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
-		rc = video_device_create_file(v4ldev, &class_device_attr_green);
-		if (rc) goto err_i2c_val;
-	} else if (cam->bridge == BRIDGE_SN9C103) {
-		rc = video_device_create_file(v4ldev, &class_device_attr_blue);
-		if (rc) goto err_i2c_val;
-		rc = video_device_create_file(v4ldev, &class_device_attr_red);
-		if (rc) goto err_blue;
+		if ((err = video_device_create_file(v4ldev,
+						    &class_device_attr_green)))
+			goto err_i2c_val;
+	} else {
+		if ((err = video_device_create_file(v4ldev,
+						    &class_device_attr_blue)))
+			goto err_i2c_val;
+		if ((err = video_device_create_file(v4ldev,
+						    &class_device_attr_red)))
+			goto err_blue;
 	}
 
 	return 0;
@@ -1279,14 +1414,14 @@
 err_i2c_reg:
 	if (cam->sensor.sysfs_ops)
 		video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
-err_frhead:
+err_frame_header:
 	video_device_remove_file(v4ldev, &class_device_attr_frame_header);
 err_val:
 	video_device_remove_file(v4ldev, &class_device_attr_val);
 err_reg:
 	video_device_remove_file(v4ldev, &class_device_attr_reg);
-err:
-	return rc;
+err_out:
+	return err;
 }
 #endif /* CONFIG_VIDEO_ADV_DEBUG */
 
@@ -1297,10 +1432,36 @@
 {
 	int err = 0;
 
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-		err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18);
-	else
-		err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18);
+	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
+	    pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+		switch (cam->bridge) {
+		case BRIDGE_SN9C101:
+		case BRIDGE_SN9C102:
+		case BRIDGE_SN9C103:
+			err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
+						 0x18);
+			break;
+		case BRIDGE_SN9C105:
+		case BRIDGE_SN9C120:
+			err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
+						 0x18);
+			break;
+		}
+	} else {
+		switch (cam->bridge) {
+		case BRIDGE_SN9C101:
+		case BRIDGE_SN9C102:
+		case BRIDGE_SN9C103:
+			err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
+						 0x18);
+			break;
+		case BRIDGE_SN9C105:
+		case BRIDGE_SN9C120:
+			err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
+						 0x18);
+			break;
+		}
+	}
 
 	return err ? -EIO : 0;
 }
@@ -1310,12 +1471,46 @@
 sn9c102_set_compression(struct sn9c102_device* cam,
 			struct v4l2_jpegcompression* compression)
 {
-	int err = 0;
+	int i, err = 0;
 
+	switch (cam->bridge) {
+	case BRIDGE_SN9C101:
+	case BRIDGE_SN9C102:
+	case BRIDGE_SN9C103:
 	if (compression->quality == 0)
-		err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17);
+			err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
+						 0x17);
 	else if (compression->quality == 1)
-		err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17);
+			err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
+						 0x17);
+		break;
+	case BRIDGE_SN9C105:
+	case BRIDGE_SN9C120:
+		if (compression->quality == 0) {
+			for (i = 0; i <= 63; i++) {
+				err += sn9c102_write_reg(cam,
+							 SN9C102_Y_QTABLE0[i],
+							 0x100 + i);
+				err += sn9c102_write_reg(cam,
+							 SN9C102_UV_QTABLE0[i],
+							 0x140 + i);
+			}
+			err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
+						 0x18);
+		} else if (compression->quality == 1) {
+			for (i = 0; i <= 63; i++) {
+				err += sn9c102_write_reg(cam,
+							 SN9C102_Y_QTABLE1[i],
+							 0x100 + i);
+				err += sn9c102_write_reg(cam,
+							 SN9C102_UV_QTABLE1[i],
+							 0x140 + i);
+			}
+			err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40,
+						 0x18);
+		}
+		break;
+	}
 
 	return err ? -EIO : 0;
 }
@@ -1399,7 +1594,16 @@
 	}
 
 	if (!(cam->state & DEV_INITIALIZED))
-		cam->compression.quality =  cam->reg[0x17] & 0x01 ? 0 : 1;
+		if (cam->bridge == BRIDGE_SN9C101 ||
+		    cam->bridge == BRIDGE_SN9C102 ||
+		    cam->bridge == BRIDGE_SN9C103) {
+			cam->compression.quality =  cam->reg[0x17] & 0x01 ?
+						    0 : 1;
+		} else {
+			cam->compression.quality =  cam->reg[0x18] & 0x40 ?
+						    0 : 1;
+			err += sn9c102_set_compression(cam, &cam->compression);
+		}
 	else
 		err += sn9c102_set_compression(cam, &cam->compression);
 	err += sn9c102_set_pix_format(cam, &s->pix_format);
@@ -1408,7 +1612,8 @@
 	if (err)
 		return err;
 
-	if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
+	if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
+	    s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
 		DBG(3, "Compressed video format is active, quality %d",
 		    cam->compression.quality);
 	else
@@ -1490,6 +1695,7 @@
 
 	if (cam->users) {
 		DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
+		DBG(3, "Simultaneous opens are not supported");
 		if ((filp->f_flags & O_NONBLOCK) ||
 		    (filp->f_flags & O_NDELAY)) {
 			err = -EWOULDBLOCK;
@@ -1628,6 +1834,17 @@
 			mutex_unlock(&cam->fileop_mutex);
 			return -EAGAIN;
 		}
+		if (!cam->module_param.frame_timeout) {
+			err = wait_event_interruptible
+			      ( cam->wait_frame,
+				(!list_empty(&cam->outqueue)) ||
+				(cam->state & DEV_DISCONNECTED) ||
+				(cam->state & DEV_MISCONFIGURED) );
+			if (err) {
+				mutex_unlock(&cam->fileop_mutex);
+				return err;
+			}
+		} else {
 		timeout = wait_event_interruptible_timeout
 			  ( cam->wait_frame,
 			    (!list_empty(&cam->outqueue)) ||
@@ -1638,12 +1855,18 @@
 		if (timeout < 0) {
 			mutex_unlock(&cam->fileop_mutex);
 			return timeout;
+			} else if (timeout == 0 &&
+				   !(cam->state & DEV_DISCONNECTED)) {
+				DBG(1, "Video frame timeout elapsed");
+				mutex_unlock(&cam->fileop_mutex);
+				return -EIO;
+			}
 		}
 		if (cam->state & DEV_DISCONNECTED) {
 			mutex_unlock(&cam->fileop_mutex);
 			return -ENODEV;
 		}
-		if (!timeout || (cam->state & DEV_MISCONFIGURED)) {
+		if (cam->state & DEV_MISCONFIGURED) {
 			mutex_unlock(&cam->fileop_mutex);
 			return -EIO;
 		}
@@ -1940,6 +2163,9 @@
 	if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
 		return -EFAULT;
 
+	PDBGG("VIDIOC_G_CTRL: id %lu, value %lu",
+	      (unsigned long)ctrl.id, (unsigned long)ctrl.value);
+
 	return err;
 }
 
@@ -2127,6 +2353,45 @@
 
 
 static int
+sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_frmsizeenum frmsize;
+
+	if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
+		return -EFAULT;
+
+	if (frmsize.index != 0)
+		return -EINVAL;
+
+	switch (cam->bridge) {
+	case BRIDGE_SN9C101:
+	case BRIDGE_SN9C102:
+	case BRIDGE_SN9C103:
+		if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
+		    frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
+			return -EINVAL;
+	case BRIDGE_SN9C105:
+	case BRIDGE_SN9C120:
+		if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
+		    frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
+			return -EINVAL;
+	}
+
+	frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
+	frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
+	frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
+	frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
+	memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
+
+	if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
 sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
 {
 	struct v4l2_fmtdesc fmtd;
@@ -2134,12 +2399,26 @@
 	if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
 		return -EFAULT;
 
+	if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
 	if (fmtd.index == 0) {
 		strcpy(fmtd.description, "bayer rgb");
 		fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
 	} else if (fmtd.index == 1) {
+		switch (cam->bridge) {
+		case BRIDGE_SN9C101:
+		case BRIDGE_SN9C102:
+		case BRIDGE_SN9C103:
 		strcpy(fmtd.description, "compressed");
 		fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
+			break;
+		case BRIDGE_SN9C105:
+		case BRIDGE_SN9C120:
+			strcpy(fmtd.description, "JPEG");
+			fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
+			break;
+		}
 		fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
 	} else
 		return -EINVAL;
@@ -2166,7 +2445,8 @@
 	if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
 
-	pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X)
+	pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X ||
+			      pfmt->pixelformat==V4L2_PIX_FMT_JPEG)
 			     ? 0 : (pfmt->width * pfmt->priv) / 8;
 	pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
 	pfmt->field = V4L2_FIELD_NONE;
@@ -2237,12 +2517,25 @@
 	pix->width = rect.width / scale;
 	pix->height = rect.height / scale;
 
+	switch (cam->bridge) {
+	case BRIDGE_SN9C101:
+	case BRIDGE_SN9C102:
+	case BRIDGE_SN9C103:
 	if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
 	    pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
 		pix->pixelformat = pfmt->pixelformat;
+		break;
+	case BRIDGE_SN9C105:
+	case BRIDGE_SN9C120:
+		if (pix->pixelformat != V4L2_PIX_FMT_JPEG &&
+		    pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
+			pix->pixelformat = pfmt->pixelformat;
+		break;
+	}
 	pix->priv = pfmt->priv; /* bpp */
 	pix->colorspace = pfmt->colorspace;
-	pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+	pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
+			     pix->pixelformat == V4L2_PIX_FMT_JPEG)
 			    ? 0 : (pix->width * pix->priv) / 8;
 	pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
 	pix->field = V4L2_FIELD_NONE;
@@ -2315,8 +2608,7 @@
 static int
 sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
 {
-	if (copy_to_user(arg, &cam->compression,
-			 sizeof(cam->compression)))
+	if (copy_to_user(arg, &cam->compression, sizeof(cam->compression)))
 		return -EFAULT;
 
 	return 0;
@@ -2471,6 +2763,7 @@
 	struct sn9c102_frame_t *f;
 	unsigned long lock_flags;
 	long timeout;
+	int err = 0;
 
 	if (copy_from_user(&b, arg, sizeof(b)))
 		return -EFAULT;
@@ -2483,6 +2776,15 @@
 			return -EINVAL;
 		if (filp->f_flags & O_NONBLOCK)
 			return -EAGAIN;
+		if (!cam->module_param.frame_timeout) {
+			err = wait_event_interruptible
+			      ( cam->wait_frame,
+				(!list_empty(&cam->outqueue)) ||
+				(cam->state & DEV_DISCONNECTED) ||
+				(cam->state & DEV_MISCONFIGURED) );
+			if (err)
+				return err;
+		} else {
 		timeout = wait_event_interruptible_timeout
 			  ( cam->wait_frame,
 			    (!list_empty(&cam->outqueue)) ||
@@ -2492,9 +2794,15 @@
 			    1000 * msecs_to_jiffies(1) );
 		if (timeout < 0)
 			return timeout;
+			else if (timeout == 0 &&
+				 !(cam->state & DEV_DISCONNECTED)) {
+				DBG(1, "Video frame timeout elapsed");
+				return -EIO;
+			}
+		}
 		if (cam->state & DEV_DISCONNECTED)
 			return -ENODEV;
-		if (!timeout || (cam->state & DEV_MISCONFIGURED))
+		if (cam->state & DEV_MISCONFIGURED)
 			return -EIO;
 	}
 
@@ -2612,6 +2920,70 @@
 }
 
 
+static int
+sn9c102_vidioc_enumaudio(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_audio audio;
+
+	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
+		return -EINVAL;
+
+	if (copy_from_user(&audio, arg, sizeof(audio)))
+		return -EFAULT;
+
+	if (audio.index != 0)
+		return -EINVAL;
+
+	strcpy(audio.name, "Microphone");
+	audio.capability = 0;
+	audio.mode = 0;
+
+	if (copy_to_user(arg, &audio, sizeof(audio)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_audio(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_audio audio;
+
+	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
+		return -EINVAL;
+
+	if (copy_from_user(&audio, arg, sizeof(audio)))
+		return -EFAULT;
+
+	memset(&audio, 0, sizeof(audio));
+	strcpy(audio.name, "Microphone");
+
+	if (copy_to_user(arg, &audio, sizeof(audio)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg)
+{
+	struct v4l2_audio audio;
+
+	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
+		return -EINVAL;
+
+	if (copy_from_user(&audio, arg, sizeof(audio)))
+		return -EFAULT;
+
+	if (audio.index != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+
 static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
 			      unsigned int cmd, void __user * arg)
 {
@@ -2649,6 +3021,9 @@
 	case VIDIOC_S_CROP:
 		return sn9c102_vidioc_s_crop(cam, arg);
 
+	case VIDIOC_ENUM_FRAMESIZES:
+		return sn9c102_vidioc_enum_framesizes(cam, arg);
+
 	case VIDIOC_ENUM_FMT:
 		return sn9c102_vidioc_enum_fmt(cam, arg);
 
@@ -2689,11 +3064,21 @@
 	case VIDIOC_S_PARM:
 		return sn9c102_vidioc_s_parm(cam, arg);
 
+	case VIDIOC_ENUMAUDIO:
+		return sn9c102_vidioc_enumaudio(cam, arg);
+
+	case VIDIOC_G_AUDIO:
+		return sn9c102_vidioc_g_audio(cam, arg);
+
+	case VIDIOC_S_AUDIO:
+		return sn9c102_vidioc_s_audio(cam, arg);
+
 	case VIDIOC_G_STD:
 	case VIDIOC_S_STD:
 	case VIDIOC_QUERYSTD:
 	case VIDIOC_ENUMSTD:
 	case VIDIOC_QUERYMENU:
+	case VIDIOC_ENUM_FRAMEINTERVALS:
 		return -EINVAL;
 
 	default:
@@ -2736,11 +3121,12 @@
 
 /*****************************************************************************/
 
-static struct file_operations sn9c102_fops = {
+static const struct file_operations sn9c102_fops = {
 	.owner = THIS_MODULE,
 	.open =    sn9c102_open,
 	.release = sn9c102_release,
 	.ioctl =   sn9c102_ioctl,
+	.compat_ioctl = v4l_compat_ioctl32,
 	.read =    sn9c102_read,
 	.poll =    sn9c102_poll,
 	.mmap =    sn9c102_mmap,
@@ -2765,7 +3151,7 @@
 	cam->usbdev = udev;
 
 	if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
-		DBG(1, "kmalloc() failed");
+		DBG(1, "kzalloc() failed");
 		err = -ENOMEM;
 		goto fail;
 	}
@@ -2779,24 +3165,31 @@
 	mutex_init(&cam->dev_mutex);
 
 	r = sn9c102_read_reg(cam, 0x00);
-	if (r < 0 || r != 0x10) {
-		DBG(1, "Sorry, this is not a SN9C10x based camera "
-		       "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
+	if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
+		DBG(1, "Sorry, this is not a SN9C1xx based camera "
+		       "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
 		err = -ENODEV;
 		goto fail;
 	}
 
-	cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ?
-		      BRIDGE_SN9C103 : BRIDGE_SN9C102;
+	cam->bridge = id->driver_info;
 	switch (cam->bridge) {
 	case BRIDGE_SN9C101:
 	case BRIDGE_SN9C102:
 		DBG(2, "SN9C10[12] PC Camera Controller detected "
-		       "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
+		       "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
 		break;
 	case BRIDGE_SN9C103:
 		DBG(2, "SN9C103 PC Camera Controller detected "
-		       "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
+		       "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+		break;
+	case BRIDGE_SN9C105:
+		DBG(2, "SN9C105 PC Camera Controller detected "
+		       "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+		break;
+	case BRIDGE_SN9C120:
+		DBG(2, "SN9C120 PC Camera Controller detected "
+		       "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
 		break;
 	}
 
@@ -2816,12 +3209,18 @@
 		goto fail;
 	}
 
+	if (!(cam->bridge & cam->sensor.supported_bridge)) {
+		DBG(1, "Bridge not supported");
+		err = -ENODEV;
+		goto fail;
+	}
+
 	if (sn9c102_init(cam)) {
 		DBG(1, "Initialization failed. I will retry on open().");
 		cam->state |= DEV_MISCONFIGURED;
 	}
 
-	strcpy(cam->v4ldev->name, "SN9C10x PC Camera");
+	strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
 	cam->v4ldev->owner = THIS_MODULE;
 	cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
 	cam->v4ldev->hardware = 0;
@@ -2838,7 +3237,10 @@
 		DBG(1, "V4L2 device registration failed");
 		if (err == -ENFILE && video_nr[dev_nr] == -1)
 			DBG(1, "Free /dev/videoX node not found");
-		goto fail2;
+		video_nr[dev_nr] = -1;
+		dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
+		mutex_unlock(&cam->dev_mutex);
+		goto fail;
 	}
 
 	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
@@ -2850,9 +3252,14 @@
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	err = sn9c102_create_sysfs(cam);
-	if (err)
-		goto fail3;
-	DBG(2, "Optional device control through 'sysfs' interface ready");
+	if (!err)
+		DBG(2, "Optional device control through 'sysfs' "
+		       "interface ready");
+	else
+		DBG(2, "Failed to create optional 'sysfs' interface for "
+		       "device controlling. Error #%d", err);
+#else
+	DBG(2, "Optional device control through 'sysfs' interface disabled");
 #endif
 
 	usb_set_intfdata(intf, cam);
@@ -2861,14 +3268,6 @@
 
 	return 0;
 
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-fail3:
-	video_unregister_device(cam->v4ldev);
-#endif
-fail2:
-	video_nr[dev_nr] = -1;
-	dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
-	mutex_unlock(&cam->dev_mutex);
 fail:
 	if (cam) {
 		kfree(cam->control_buffer);
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
new file mode 100644
index 0000000..3a682ec
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -0,0 +1,142 @@
+/***************************************************************************
+ * Table of device identifiers of the SN9C1xx PC Camera Controllers        *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#ifndef _SN9C102_DEVTABLE_H_
+#define _SN9C102_DEVTABLE_H_
+
+#include <linux/usb.h>
+
+struct sn9c102_device;
+
+/*
+   Each SN9C1xx camera has proper PID/VID identifiers.
+   SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to
+   handle the video class interface.
+*/
+#define SN9C102_USB_DEVICE(vend, prod, bridge)                                \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |                           \
+		       USB_DEVICE_ID_MATCH_INT_CLASS,                         \
+	.idVendor = (vend),                                                   \
+	.idProduct = (prod),                                                  \
+	.bInterfaceClass = 0xff,                                              \
+	.driver_info = (bridge)
+
+static const struct usb_device_id sn9c102_id_table[] = {
+	/* SN9C101 and SN9C102 */
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x603f, BRIDGE_SN9C102), },
+	/* SN9C103 */
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), },
+	/* SN9C105 */
+	{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
+	/* SN9C120 */
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
+	{ }
+};
+
+/*
+   Probing functions: on success, you must attach the sensor to the camera
+   by calling sn9c102_attach_sensor().
+   To enable the I2C communication, you might need to perform a really basic
+   initialization of the SN9C1XX chip.
+   Functions must return 0 on success, the appropriate error otherwise.
+*/
+extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
+extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
+extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
+extern int sn9c102_probe_ov7660(struct sn9c102_device* cam);
+extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
+extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
+extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
+extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
+
+/*
+   Add the above entries to this table. Be sure to add the entry in the right
+   place, since, on failure, the next probing routine is called according to
+   the order of the list below, from top to bottom.
+*/
+static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
+	&sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
+	&sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
+	&sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
+	&sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
+	&sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
+	&sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
+	&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
+	&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
+	NULL,
+};
+
+#endif /* _SN9C102_DEVTABLE_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
index c4117bf..7ae368f 100644
--- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera     *
+ * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera     *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -124,7 +124,7 @@
 static int hv7131d_set_crop(struct sn9c102_device* cam,
 			    const struct v4l2_rect* rect)
 {
-	struct sn9c102_sensor* s = &hv7131d;
+	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 	int err = 0;
 	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
 	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
@@ -153,6 +153,7 @@
 static struct sn9c102_sensor hv7131d = {
 	.name = "HV7131D",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
 	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
 	.frequency = SN9C102_I2C_100KHZ,
 	.interface = SN9C102_I2C_2WIRES,
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c
index 4169ea4..a33d1bc 100644
--- a/drivers/media/video/sn9c102/sn9c102_mi0343.c
+++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera     *
+ * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera     *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -201,7 +201,7 @@
 static int mi0343_set_crop(struct sn9c102_device* cam,
 			    const struct v4l2_rect* rect)
 {
-	struct sn9c102_sensor* s = &mi0343;
+	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 	int err = 0;
 	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
 	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
@@ -237,6 +237,7 @@
 static struct sn9c102_sensor mi0343 = {
 	.name = "MI-0343",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
 	.frequency = SN9C102_I2C_100KHZ,
 	.interface = SN9C102_I2C_2WIRES,
 	.i2c_slave_id = 0x5d,
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
index 3da0420..7df09ff 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7630.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera      *
+ * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera      *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2005-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -29,13 +29,17 @@
 {
 	int err = 0;
 
+	switch (sn9c102_get_bridge(cam)) {
+	case BRIDGE_SN9C101:
+	case BRIDGE_SN9C102:
 	err += sn9c102_write_reg(cam, 0x00, 0x14);
 	err += sn9c102_write_reg(cam, 0x60, 0x17);
 	err += sn9c102_write_reg(cam, 0x0f, 0x18);
 	err += sn9c102_write_reg(cam, 0x50, 0x19);
 
-	err += sn9c102_i2c_write(cam, 0x12, 0x80);
-	err += sn9c102_i2c_write(cam, 0x11, 0x01);
+		err += sn9c102_i2c_write(cam, 0x12, 0x8d);
+		err += sn9c102_i2c_write(cam, 0x12, 0x0d);
+		err += sn9c102_i2c_write(cam, 0x11, 0x00);
 	err += sn9c102_i2c_write(cam, 0x15, 0x34);
 	err += sn9c102_i2c_write(cam, 0x16, 0x03);
 	err += sn9c102_i2c_write(cam, 0x17, 0x1c);
@@ -43,14 +47,72 @@
 	err += sn9c102_i2c_write(cam, 0x19, 0x06);
 	err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
 	err += sn9c102_i2c_write(cam, 0x1b, 0x04);
-	err += sn9c102_i2c_write(cam, 0x20, 0xf6);
+		err += sn9c102_i2c_write(cam, 0x20, 0x44);
+		err += sn9c102_i2c_write(cam, 0x23, 0xee);
+		err += sn9c102_i2c_write(cam, 0x26, 0xa0);
+		err += sn9c102_i2c_write(cam, 0x27, 0x9a);
+		err += sn9c102_i2c_write(cam, 0x28, 0x20);
+		err += sn9c102_i2c_write(cam, 0x29, 0x30);
+		err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
+		err += sn9c102_i2c_write(cam, 0x30, 0x24);
+		err += sn9c102_i2c_write(cam, 0x32, 0x86);
+		err += sn9c102_i2c_write(cam, 0x60, 0xa9);
+		err += sn9c102_i2c_write(cam, 0x61, 0x42);
+		err += sn9c102_i2c_write(cam, 0x65, 0x00);
+		err += sn9c102_i2c_write(cam, 0x69, 0x38);
+		err += sn9c102_i2c_write(cam, 0x6f, 0x88);
+		err += sn9c102_i2c_write(cam, 0x70, 0x0b);
+		err += sn9c102_i2c_write(cam, 0x71, 0x00);
+		err += sn9c102_i2c_write(cam, 0x74, 0x21);
+		err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
+		break;
+	case BRIDGE_SN9C103:
+		err += sn9c102_write_reg(cam, 0x00, 0x02);
+		err += sn9c102_write_reg(cam, 0x00, 0x03);
+		err += sn9c102_write_reg(cam, 0x1a, 0x04);
+		err += sn9c102_write_reg(cam, 0x20, 0x05);
+		err += sn9c102_write_reg(cam, 0x20, 0x06);
+		err += sn9c102_write_reg(cam, 0x20, 0x07);
+		err += sn9c102_write_reg(cam, 0x03, 0x10);
+		err += sn9c102_write_reg(cam, 0x0a, 0x14);
+		err += sn9c102_write_reg(cam, 0x60, 0x17);
+		err += sn9c102_write_reg(cam, 0x0f, 0x18);
+		err += sn9c102_write_reg(cam, 0x50, 0x19);
+		err += sn9c102_write_reg(cam, 0x1d, 0x1a);
+		err += sn9c102_write_reg(cam, 0x10, 0x1b);
+		err += sn9c102_write_reg(cam, 0x02, 0x1c);
+		err += sn9c102_write_reg(cam, 0x03, 0x1d);
+		err += sn9c102_write_reg(cam, 0x0f, 0x1e);
+		err += sn9c102_write_reg(cam, 0x0c, 0x1f);
+		err += sn9c102_write_reg(cam, 0x00, 0x20);
+		err += sn9c102_write_reg(cam, 0x10, 0x21);
+		err += sn9c102_write_reg(cam, 0x20, 0x22);
+		err += sn9c102_write_reg(cam, 0x30, 0x23);
+		err += sn9c102_write_reg(cam, 0x40, 0x24);
+		err += sn9c102_write_reg(cam, 0x50, 0x25);
+		err += sn9c102_write_reg(cam, 0x60, 0x26);
+		err += sn9c102_write_reg(cam, 0x70, 0x27);
+		err += sn9c102_write_reg(cam, 0x80, 0x28);
+		err += sn9c102_write_reg(cam, 0x90, 0x29);
+		err += sn9c102_write_reg(cam, 0xa0, 0x2a);
+		err += sn9c102_write_reg(cam, 0xb0, 0x2b);
+		err += sn9c102_write_reg(cam, 0xc0, 0x2c);
+		err += sn9c102_write_reg(cam, 0xd0, 0x2d);
+		err += sn9c102_write_reg(cam, 0xe0, 0x2e);
+		err += sn9c102_write_reg(cam, 0xf0, 0x2f);
+		err += sn9c102_write_reg(cam, 0xff, 0x30);
+
+		err += sn9c102_i2c_write(cam, 0x12, 0x8d);
+		err += sn9c102_i2c_write(cam, 0x12, 0x0d);
+		err += sn9c102_i2c_write(cam, 0x15, 0x34);
+		err += sn9c102_i2c_write(cam, 0x11, 0x01);
+		err += sn9c102_i2c_write(cam, 0x1b, 0x04);
+		err += sn9c102_i2c_write(cam, 0x20, 0x44);
 	err += sn9c102_i2c_write(cam, 0x23, 0xee);
 	err += sn9c102_i2c_write(cam, 0x26, 0xa0);
 	err += sn9c102_i2c_write(cam, 0x27, 0x9a);
-	err += sn9c102_i2c_write(cam, 0x28, 0xa0);
+		err += sn9c102_i2c_write(cam, 0x28, 0x20);
 	err += sn9c102_i2c_write(cam, 0x29, 0x30);
-	err += sn9c102_i2c_write(cam, 0x2a, 0xa0);
-	err += sn9c102_i2c_write(cam, 0x2b, 0x1f);
 	err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
 	err += sn9c102_i2c_write(cam, 0x30, 0x24);
 	err += sn9c102_i2c_write(cam, 0x32, 0x86);
@@ -63,11 +125,77 @@
 	err += sn9c102_i2c_write(cam, 0x71, 0x00);
 	err += sn9c102_i2c_write(cam, 0x74, 0x21);
 	err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
+		break;
+	default:
+		break;
+	}
 
 	return err;
 }
 
 
+static int ov7630_get_ctrl(struct sn9c102_device* cam,
+			   struct v4l2_control* ctrl)
+{
+	int err = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
+			return -EIO;
+		break;
+	case V4L2_CID_RED_BALANCE:
+		ctrl->value = sn9c102_pread_reg(cam, 0x07);
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		ctrl->value = sn9c102_pread_reg(cam, 0x06);
+		break;
+	case SN9C102_V4L2_CID_GREEN_BALANCE:
+		ctrl->value = sn9c102_pread_reg(cam, 0x05);
+		break;
+	case V4L2_CID_GAIN:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
+			return -EIO;
+		ctrl->value &= 0x3f;
+		break;
+	case V4L2_CID_DO_WHITE_BALANCE:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
+			return -EIO;
+		ctrl->value &= 0x3f;
+		break;
+	case V4L2_CID_WHITENESS:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0)
+			return -EIO;
+		ctrl->value &= 0x3f;
+		break;
+	case V4L2_CID_AUTOGAIN:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
+			return -EIO;
+		ctrl->value &= 0x01;
+		break;
+	case V4L2_CID_VFLIP:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x75)) < 0)
+			return -EIO;
+		ctrl->value = (ctrl->value & 0x80) ? 1 : 0;
+		break;
+	case SN9C102_V4L2_CID_GAMMA:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x14)) < 0)
+			return -EIO;
+		ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
+		break;
+	case SN9C102_V4L2_CID_BAND_FILTER:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x2d)) < 0)
+			return -EIO;
+		ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err ? -EIO : 0;
+}
+
+
 static int ov7630_set_ctrl(struct sn9c102_device* cam,
 			   const struct v4l2_control* ctrl)
 {
@@ -75,57 +203,35 @@
 
 	switch (ctrl->id) {
 	case V4L2_CID_EXPOSURE:
-		err += sn9c102_i2c_write(cam, 0x10, ctrl->value >> 2);
-		err += sn9c102_i2c_write(cam, 0x76, ctrl->value & 0x03);
+		err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
 		break;
 	case V4L2_CID_RED_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x02, ctrl->value);
+		err += sn9c102_write_reg(cam, ctrl->value, 0x07);
 		break;
 	case V4L2_CID_BLUE_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x01, ctrl->value);
+		err += sn9c102_write_reg(cam, ctrl->value, 0x06);
+		break;
+	case SN9C102_V4L2_CID_GREEN_BALANCE:
+		err += sn9c102_write_reg(cam, ctrl->value, 0x05);
 		break;
 	case V4L2_CID_GAIN:
 		err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
 		break;
-	case V4L2_CID_CONTRAST:
-		err += ctrl->value ? sn9c102_i2c_write(cam, 0x05,
-						       (ctrl->value-1) | 0x20)
-				   : sn9c102_i2c_write(cam, 0x05, 0x00);
-		break;
-	case V4L2_CID_BRIGHTNESS:
-		err += sn9c102_i2c_write(cam, 0x06, ctrl->value);
-		break;
-	case V4L2_CID_SATURATION:
-		err += sn9c102_i2c_write(cam, 0x03, ctrl->value << 4);
-		break;
-	case V4L2_CID_HUE:
-		err += ctrl->value ? sn9c102_i2c_write(cam, 0x04,
-						       (ctrl->value-1) | 0x20)
-				   : sn9c102_i2c_write(cam, 0x04, 0x00);
-		break;
 	case V4L2_CID_DO_WHITE_BALANCE:
 		err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
 		break;
 	case V4L2_CID_WHITENESS:
 		err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
 		break;
-	case V4L2_CID_AUTO_WHITE_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78);
-		break;
 	case V4L2_CID_AUTOGAIN:
-		err += sn9c102_i2c_write(cam, 0x13, ctrl->value);
+		err += sn9c102_i2c_write(cam, 0x13, ctrl->value |
+						    (ctrl->value << 1));
 		break;
 	case V4L2_CID_VFLIP:
 		err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
 		break;
-	case V4L2_CID_BLACK_LEVEL:
-		err += sn9c102_i2c_write(cam, 0x25, ctrl->value);
-		break;
-	case SN9C102_V4L2_CID_BRIGHT_LEVEL:
-		err += sn9c102_i2c_write(cam, 0x24, ctrl->value);
-		break;
 	case SN9C102_V4L2_CID_GAMMA:
-		err += sn9c102_i2c_write(cam, 0x14, (ctrl->value << 2) | 0x80);
+		err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2);
 		break;
 	case SN9C102_V4L2_CID_BAND_FILTER:
 		err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
@@ -141,10 +247,12 @@
 static int ov7630_set_crop(struct sn9c102_device* cam,
 			   const struct v4l2_rect* rect)
 {
-	struct sn9c102_sensor* s = &ov7630;
+	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 	int err = 0;
-	u8 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
+	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
 
+	err += sn9c102_write_reg(cam, h_start, 0x12);
 	err += sn9c102_write_reg(cam, v_start, 0x13);
 
 	return err;
@@ -168,7 +276,8 @@
 static struct sn9c102_sensor ov7630 = {
 	.name = "OV7630",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.sysfs_ops = SN9C102_I2C_WRITE,
+	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
+	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
 	.frequency = SN9C102_I2C_100KHZ,
 	.interface = SN9C102_I2C_2WIRES,
 	.i2c_slave_id = 0x21,
@@ -185,83 +294,13 @@
 			.flags = 0,
 		},
 		{
-			.id = V4L2_CID_HUE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "hue",
-			.minimum = 0x00,
-			.maximum = 0x1f+1,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_SATURATION,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "saturation",
-			.minimum = 0x00,
-			.maximum = 0x0f,
-			.step = 0x01,
-			.default_value = 0x08,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_CONTRAST,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "contrast",
-			.minimum = 0x00,
-			.maximum = 0x1f+1,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
 			.id = V4L2_CID_EXPOSURE,
 			.type = V4L2_CTRL_TYPE_INTEGER,
 			.name = "exposure",
-			.minimum = 0x000,
-			.maximum = 0x3ff,
-			.step = 0x001,
-			.default_value = 0x83<<2,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_RED_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "red balance",
 			.minimum = 0x00,
 			.maximum = 0xff,
 			.step = 0x01,
-			.default_value = 0x3a,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLUE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "blue balance",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 0x01,
-			.default_value = 0x77,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BRIGHTNESS,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "brightness",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 0x01,
-			.default_value = 0xa0,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_DO_WHITE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "white balance background: blue",
-			.minimum = 0x00,
-			.maximum = 0x3f,
-			.step = 0x01,
-			.default_value = 0x20,
+			.default_value = 0x60,
 			.flags = 0,
 		},
 		{
@@ -275,21 +314,41 @@
 			.flags = 0,
 		},
 		{
-			.id = V4L2_CID_AUTO_WHITE_BALANCE,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "auto white balance",
+			.id = V4L2_CID_DO_WHITE_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "white balance background: blue",
 			.minimum = 0x00,
-			.maximum = 0x01,
+			.maximum = 0x3f,
 			.step = 0x01,
-			.default_value = 0x01,
+			.default_value = 0x20,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_RED_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "red balance",
+			.minimum = 0x00,
+			.maximum = 0x7f,
+			.step = 0x01,
+			.default_value = 0x20,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_BLUE_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "blue balance",
+			.minimum = 0x00,
+			.maximum = 0x7f,
+			.step = 0x01,
+			.default_value = 0x20,
 			.flags = 0,
 		},
 		{
 			.id = V4L2_CID_AUTOGAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "gain & exposure mode",
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "auto adjust",
 			.minimum = 0x00,
-			.maximum = 0x03,
+			.maximum = 0x01,
 			.step = 0x01,
 			.default_value = 0x00,
 			.flags = 0,
@@ -305,23 +364,13 @@
 			.flags = 0,
 		},
 		{
-			.id = V4L2_CID_BLACK_LEVEL,
+			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
 			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "black pixel ratio",
-			.minimum = 0x01,
-			.maximum = 0x9a,
+			.name = "green balance",
+			.minimum = 0x00,
+			.maximum = 0x7f,
 			.step = 0x01,
-			.default_value = 0x8a,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_BRIGHT_LEVEL,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "bright pixel ratio",
-			.minimum = 0x01,
-			.maximum = 0x9a,
-			.step = 0x01,
-			.default_value = 0x10,
+			.default_value = 0x20,
 			.flags = 0,
 		},
 		{
@@ -345,6 +394,7 @@
 			.flags = 0,
 		},
 	},
+	.get_ctrl = &ov7630_get_ctrl,
 	.set_ctrl = &ov7630_set_ctrl,
 	.cropcap = {
 		.bounds = {
@@ -364,7 +414,7 @@
 	.pix_format = {
 		.width = 640,
 		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
+		.pixelformat = V4L2_PIX_FMT_SN9C10X,
 		.priv = 8,
 	},
 	.set_pix_format = &ov7630_set_pix_format
@@ -373,28 +423,36 @@
 
 int sn9c102_probe_ov7630(struct sn9c102_device* cam)
 {
-	const struct usb_device_id ov7630_id_table[] = {
-		{ USB_DEVICE(0x0c45, 0x602c), },
-		{ USB_DEVICE(0x0c45, 0x602d), },
-		{ USB_DEVICE(0x0c45, 0x608f), },
-		{ USB_DEVICE(0x0c45, 0x60b0), },
-		{ }
-	};
-	int err = 0;
+	int pid, ver, err = 0;
 
-	if (!sn9c102_match_id(cam, ov7630_id_table))
-		return -ENODEV;
-
+	switch (sn9c102_get_bridge(cam)) {
+	case BRIDGE_SN9C101:
+	case BRIDGE_SN9C102:
 	err += sn9c102_write_reg(cam, 0x01, 0x01);
 	err += sn9c102_write_reg(cam, 0x00, 0x01);
 	err += sn9c102_write_reg(cam, 0x28, 0x17);
-	if (err)
+		break;
+	case BRIDGE_SN9C103: /* do _not_ change anything! */
+		err += sn9c102_write_reg(cam, 0x09, 0x01);
+		err += sn9c102_write_reg(cam, 0x42, 0x01);
+		err += sn9c102_write_reg(cam, 0x28, 0x17);
+		err += sn9c102_write_reg(cam, 0x44, 0x02);
+		pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
+		if (err || pid < 0) { /* try a different initialization */
+			err = sn9c102_write_reg(cam, 0x01, 0x01);
+			err += sn9c102_write_reg(cam, 0x00, 0x01);
+		}
+		break;
+	default:
+		break;
+	}
+
+	pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
+	ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b);
+	if (err || pid < 0 || ver < 0)
 		return -EIO;
-
-	err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0);
-	if (err)
+	if (pid != 0x76 || ver != 0x31)
 		return -ENODEV;
-
 	sn9c102_attach_sensor(cam, &ov7630);
 
 	return 0;
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c
new file mode 100644
index 0000000..d670c24
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c
@@ -0,0 +1,592 @@
+/***************************************************************************
+ * Plug-in for OV7660 image sensor connected to the SN9C1xx PC Camera      *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#include "sn9c102_sensor.h"
+
+
+static struct sn9c102_sensor ov7660;
+
+
+static int ov7660_init(struct sn9c102_device* cam)
+{
+	int err = 0;
+
+	err += sn9c102_write_reg(cam, 0x40, 0x02);
+	err += sn9c102_write_reg(cam, 0x00, 0x03);
+	err += sn9c102_write_reg(cam, 0x1a, 0x04);
+	err += sn9c102_write_reg(cam, 0x03, 0x10);
+	err += sn9c102_write_reg(cam, 0x08, 0x14);
+	err += sn9c102_write_reg(cam, 0x20, 0x17);
+	err += sn9c102_write_reg(cam, 0x8b, 0x18);
+	err += sn9c102_write_reg(cam, 0x00, 0x19);
+	err += sn9c102_write_reg(cam, 0x1d, 0x1a);
+	err += sn9c102_write_reg(cam, 0x10, 0x1b);
+	err += sn9c102_write_reg(cam, 0x02, 0x1c);
+	err += sn9c102_write_reg(cam, 0x03, 0x1d);
+	err += sn9c102_write_reg(cam, 0x0f, 0x1e);
+	err += sn9c102_write_reg(cam, 0x0c, 0x1f);
+	err += sn9c102_write_reg(cam, 0x00, 0x20);
+	err += sn9c102_write_reg(cam, 0x29, 0x21);
+	err += sn9c102_write_reg(cam, 0x40, 0x22);
+	err += sn9c102_write_reg(cam, 0x54, 0x23);
+	err += sn9c102_write_reg(cam, 0x66, 0x24);
+	err += sn9c102_write_reg(cam, 0x76, 0x25);
+	err += sn9c102_write_reg(cam, 0x85, 0x26);
+	err += sn9c102_write_reg(cam, 0x94, 0x27);
+	err += sn9c102_write_reg(cam, 0xa1, 0x28);
+	err += sn9c102_write_reg(cam, 0xae, 0x29);
+	err += sn9c102_write_reg(cam, 0xbb, 0x2a);
+	err += sn9c102_write_reg(cam, 0xc7, 0x2b);
+	err += sn9c102_write_reg(cam, 0xd3, 0x2c);
+	err += sn9c102_write_reg(cam, 0xde, 0x2d);
+	err += sn9c102_write_reg(cam, 0xea, 0x2e);
+	err += sn9c102_write_reg(cam, 0xf4, 0x2f);
+	err += sn9c102_write_reg(cam, 0xff, 0x30);
+	err += sn9c102_write_reg(cam, 0x00, 0x3F);
+	err += sn9c102_write_reg(cam, 0xC7, 0x40);
+	err += sn9c102_write_reg(cam, 0x01, 0x41);
+	err += sn9c102_write_reg(cam, 0x44, 0x42);
+	err += sn9c102_write_reg(cam, 0x00, 0x43);
+	err += sn9c102_write_reg(cam, 0x44, 0x44);
+	err += sn9c102_write_reg(cam, 0x00, 0x45);
+	err += sn9c102_write_reg(cam, 0x44, 0x46);
+	err += sn9c102_write_reg(cam, 0x00, 0x47);
+	err += sn9c102_write_reg(cam, 0xC7, 0x48);
+	err += sn9c102_write_reg(cam, 0x01, 0x49);
+	err += sn9c102_write_reg(cam, 0xC7, 0x4A);
+	err += sn9c102_write_reg(cam, 0x01, 0x4B);
+	err += sn9c102_write_reg(cam, 0xC7, 0x4C);
+	err += sn9c102_write_reg(cam, 0x01, 0x4D);
+	err += sn9c102_write_reg(cam, 0x44, 0x4E);
+	err += sn9c102_write_reg(cam, 0x00, 0x4F);
+	err += sn9c102_write_reg(cam, 0x44, 0x50);
+	err += sn9c102_write_reg(cam, 0x00, 0x51);
+	err += sn9c102_write_reg(cam, 0x44, 0x52);
+	err += sn9c102_write_reg(cam, 0x00, 0x53);
+	err += sn9c102_write_reg(cam, 0xC7, 0x54);
+	err += sn9c102_write_reg(cam, 0x01, 0x55);
+	err += sn9c102_write_reg(cam, 0xC7, 0x56);
+	err += sn9c102_write_reg(cam, 0x01, 0x57);
+	err += sn9c102_write_reg(cam, 0xC7, 0x58);
+	err += sn9c102_write_reg(cam, 0x01, 0x59);
+	err += sn9c102_write_reg(cam, 0x44, 0x5A);
+	err += sn9c102_write_reg(cam, 0x00, 0x5B);
+	err += sn9c102_write_reg(cam, 0x44, 0x5C);
+	err += sn9c102_write_reg(cam, 0x00, 0x5D);
+	err += sn9c102_write_reg(cam, 0x44, 0x5E);
+	err += sn9c102_write_reg(cam, 0x00, 0x5F);
+	err += sn9c102_write_reg(cam, 0xC7, 0x60);
+	err += sn9c102_write_reg(cam, 0x01, 0x61);
+	err += sn9c102_write_reg(cam, 0xC7, 0x62);
+	err += sn9c102_write_reg(cam, 0x01, 0x63);
+	err += sn9c102_write_reg(cam, 0xC7, 0x64);
+	err += sn9c102_write_reg(cam, 0x01, 0x65);
+	err += sn9c102_write_reg(cam, 0x44, 0x66);
+	err += sn9c102_write_reg(cam, 0x00, 0x67);
+	err += sn9c102_write_reg(cam, 0x44, 0x68);
+	err += sn9c102_write_reg(cam, 0x00, 0x69);
+	err += sn9c102_write_reg(cam, 0x44, 0x6A);
+	err += sn9c102_write_reg(cam, 0x00, 0x6B);
+	err += sn9c102_write_reg(cam, 0xC7, 0x6C);
+	err += sn9c102_write_reg(cam, 0x01, 0x6D);
+	err += sn9c102_write_reg(cam, 0xC7, 0x6E);
+	err += sn9c102_write_reg(cam, 0x01, 0x6F);
+	err += sn9c102_write_reg(cam, 0xC7, 0x70);
+	err += sn9c102_write_reg(cam, 0x01, 0x71);
+	err += sn9c102_write_reg(cam, 0x44, 0x72);
+	err += sn9c102_write_reg(cam, 0x00, 0x73);
+	err += sn9c102_write_reg(cam, 0x44, 0x74);
+	err += sn9c102_write_reg(cam, 0x00, 0x75);
+	err += sn9c102_write_reg(cam, 0x44, 0x76);
+	err += sn9c102_write_reg(cam, 0x00, 0x77);
+	err += sn9c102_write_reg(cam, 0xC7, 0x78);
+	err += sn9c102_write_reg(cam, 0x01, 0x79);
+	err += sn9c102_write_reg(cam, 0xC7, 0x7A);
+	err += sn9c102_write_reg(cam, 0x01, 0x7B);
+	err += sn9c102_write_reg(cam, 0xC7, 0x7C);
+	err += sn9c102_write_reg(cam, 0x01, 0x7D);
+	err += sn9c102_write_reg(cam, 0x44, 0x7E);
+	err += sn9c102_write_reg(cam, 0x00, 0x7F);
+	err += sn9c102_write_reg(cam, 0x14, 0x84);
+	err += sn9c102_write_reg(cam, 0x00, 0x85);
+	err += sn9c102_write_reg(cam, 0x27, 0x86);
+	err += sn9c102_write_reg(cam, 0x00, 0x87);
+	err += sn9c102_write_reg(cam, 0x07, 0x88);
+	err += sn9c102_write_reg(cam, 0x00, 0x89);
+	err += sn9c102_write_reg(cam, 0xEC, 0x8A);
+	err += sn9c102_write_reg(cam, 0x0f, 0x8B);
+	err += sn9c102_write_reg(cam, 0xD8, 0x8C);
+	err += sn9c102_write_reg(cam, 0x0f, 0x8D);
+	err += sn9c102_write_reg(cam, 0x3D, 0x8E);
+	err += sn9c102_write_reg(cam, 0x00, 0x8F);
+	err += sn9c102_write_reg(cam, 0x3D, 0x90);
+	err += sn9c102_write_reg(cam, 0x00, 0x91);
+	err += sn9c102_write_reg(cam, 0xCD, 0x92);
+	err += sn9c102_write_reg(cam, 0x0f, 0x93);
+	err += sn9c102_write_reg(cam, 0xf7, 0x94);
+	err += sn9c102_write_reg(cam, 0x0f, 0x95);
+	err += sn9c102_write_reg(cam, 0x0C, 0x96);
+	err += sn9c102_write_reg(cam, 0x00, 0x97);
+	err += sn9c102_write_reg(cam, 0x00, 0x98);
+	err += sn9c102_write_reg(cam, 0x66, 0x99);
+	err += sn9c102_write_reg(cam, 0x05, 0x9A);
+	err += sn9c102_write_reg(cam, 0x00, 0x9B);
+	err += sn9c102_write_reg(cam, 0x04, 0x9C);
+	err += sn9c102_write_reg(cam, 0x00, 0x9D);
+	err += sn9c102_write_reg(cam, 0x08, 0x9E);
+	err += sn9c102_write_reg(cam, 0x00, 0x9F);
+	err += sn9c102_write_reg(cam, 0x2D, 0xC0);
+	err += sn9c102_write_reg(cam, 0x2D, 0xC1);
+	err += sn9c102_write_reg(cam, 0x3A, 0xC2);
+	err += sn9c102_write_reg(cam, 0x05, 0xC3);
+	err += sn9c102_write_reg(cam, 0x04, 0xC4);
+	err += sn9c102_write_reg(cam, 0x3F, 0xC5);
+	err += sn9c102_write_reg(cam, 0x00, 0xC6);
+	err += sn9c102_write_reg(cam, 0x00, 0xC7);
+	err += sn9c102_write_reg(cam, 0x50, 0xC8);
+	err += sn9c102_write_reg(cam, 0x3C, 0xC9);
+	err += sn9c102_write_reg(cam, 0x28, 0xCA);
+	err += sn9c102_write_reg(cam, 0xD8, 0xCB);
+	err += sn9c102_write_reg(cam, 0x14, 0xCC);
+	err += sn9c102_write_reg(cam, 0xEC, 0xCD);
+	err += sn9c102_write_reg(cam, 0x32, 0xCE);
+	err += sn9c102_write_reg(cam, 0xDD, 0xCF);
+	err += sn9c102_write_reg(cam, 0x32, 0xD0);
+	err += sn9c102_write_reg(cam, 0xDD, 0xD1);
+	err += sn9c102_write_reg(cam, 0x6A, 0xD2);
+	err += sn9c102_write_reg(cam, 0x50, 0xD3);
+	err += sn9c102_write_reg(cam, 0x00, 0xD4);
+	err += sn9c102_write_reg(cam, 0x00, 0xD5);
+	err += sn9c102_write_reg(cam, 0x00, 0xD6);
+
+	err += sn9c102_i2c_write(cam, 0x12, 0x80);
+	err += sn9c102_i2c_write(cam, 0x11, 0x09);
+	err += sn9c102_i2c_write(cam, 0x00, 0x0A);
+	err += sn9c102_i2c_write(cam, 0x01, 0x78);
+	err += sn9c102_i2c_write(cam, 0x02, 0x90);
+	err += sn9c102_i2c_write(cam, 0x03, 0x00);
+	err += sn9c102_i2c_write(cam, 0x04, 0x00);
+	err += sn9c102_i2c_write(cam, 0x05, 0x08);
+	err += sn9c102_i2c_write(cam, 0x06, 0x0B);
+	err += sn9c102_i2c_write(cam, 0x07, 0x00);
+	err += sn9c102_i2c_write(cam, 0x08, 0x1C);
+	err += sn9c102_i2c_write(cam, 0x09, 0x01);
+	err += sn9c102_i2c_write(cam, 0x0A, 0x76);
+	err += sn9c102_i2c_write(cam, 0x0B, 0x60);
+	err += sn9c102_i2c_write(cam, 0x0C, 0x00);
+	err += sn9c102_i2c_write(cam, 0x0D, 0x08);
+	err += sn9c102_i2c_write(cam, 0x0E, 0x04);
+	err += sn9c102_i2c_write(cam, 0x0F, 0x6F);
+	err += sn9c102_i2c_write(cam, 0x10, 0x20);
+	err += sn9c102_i2c_write(cam, 0x11, 0x03);
+	err += sn9c102_i2c_write(cam, 0x12, 0x05);
+	err += sn9c102_i2c_write(cam, 0x13, 0xF8);
+	err += sn9c102_i2c_write(cam, 0x14, 0x2C);
+	err += sn9c102_i2c_write(cam, 0x15, 0x00);
+	err += sn9c102_i2c_write(cam, 0x16, 0x02);
+	err += sn9c102_i2c_write(cam, 0x17, 0x10);
+	err += sn9c102_i2c_write(cam, 0x18, 0x60);
+	err += sn9c102_i2c_write(cam, 0x19, 0x02);
+	err += sn9c102_i2c_write(cam, 0x1A, 0x7B);
+	err += sn9c102_i2c_write(cam, 0x1B, 0x02);
+	err += sn9c102_i2c_write(cam, 0x1C, 0x7F);
+	err += sn9c102_i2c_write(cam, 0x1D, 0xA2);
+	err += sn9c102_i2c_write(cam, 0x1E, 0x01);
+	err += sn9c102_i2c_write(cam, 0x1F, 0x0E);
+	err += sn9c102_i2c_write(cam, 0x20, 0x05);
+	err += sn9c102_i2c_write(cam, 0x21, 0x05);
+	err += sn9c102_i2c_write(cam, 0x22, 0x05);
+	err += sn9c102_i2c_write(cam, 0x23, 0x05);
+	err += sn9c102_i2c_write(cam, 0x24, 0x68);
+	err += sn9c102_i2c_write(cam, 0x25, 0x58);
+	err += sn9c102_i2c_write(cam, 0x26, 0xD4);
+	err += sn9c102_i2c_write(cam, 0x27, 0x80);
+	err += sn9c102_i2c_write(cam, 0x28, 0x80);
+	err += sn9c102_i2c_write(cam, 0x29, 0x30);
+	err += sn9c102_i2c_write(cam, 0x2A, 0x00);
+	err += sn9c102_i2c_write(cam, 0x2B, 0x00);
+	err += sn9c102_i2c_write(cam, 0x2C, 0x80);
+	err += sn9c102_i2c_write(cam, 0x2D, 0x00);
+	err += sn9c102_i2c_write(cam, 0x2E, 0x00);
+	err += sn9c102_i2c_write(cam, 0x2F, 0x0E);
+	err += sn9c102_i2c_write(cam, 0x30, 0x08);
+	err += sn9c102_i2c_write(cam, 0x31, 0x30);
+	err += sn9c102_i2c_write(cam, 0x32, 0xB4);
+	err += sn9c102_i2c_write(cam, 0x33, 0x00);
+	err += sn9c102_i2c_write(cam, 0x34, 0x07);
+	err += sn9c102_i2c_write(cam, 0x35, 0x84);
+	err += sn9c102_i2c_write(cam, 0x36, 0x00);
+	err += sn9c102_i2c_write(cam, 0x37, 0x0C);
+	err += sn9c102_i2c_write(cam, 0x38, 0x02);
+	err += sn9c102_i2c_write(cam, 0x39, 0x43);
+	err += sn9c102_i2c_write(cam, 0x3A, 0x00);
+	err += sn9c102_i2c_write(cam, 0x3B, 0x02);
+	err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
+	err += sn9c102_i2c_write(cam, 0x3D, 0x99);
+	err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
+	err += sn9c102_i2c_write(cam, 0x3F, 0x41);
+	err += sn9c102_i2c_write(cam, 0x40, 0xC1);
+	err += sn9c102_i2c_write(cam, 0x41, 0x22);
+	err += sn9c102_i2c_write(cam, 0x42, 0x08);
+	err += sn9c102_i2c_write(cam, 0x43, 0xF0);
+	err += sn9c102_i2c_write(cam, 0x44, 0x10);
+	err += sn9c102_i2c_write(cam, 0x45, 0x78);
+	err += sn9c102_i2c_write(cam, 0x46, 0xA8);
+	err += sn9c102_i2c_write(cam, 0x47, 0x60);
+	err += sn9c102_i2c_write(cam, 0x48, 0x80);
+	err += sn9c102_i2c_write(cam, 0x49, 0x00);
+	err += sn9c102_i2c_write(cam, 0x4A, 0x00);
+	err += sn9c102_i2c_write(cam, 0x4B, 0x00);
+	err += sn9c102_i2c_write(cam, 0x4C, 0x00);
+	err += sn9c102_i2c_write(cam, 0x4D, 0x00);
+	err += sn9c102_i2c_write(cam, 0x4E, 0x00);
+	err += sn9c102_i2c_write(cam, 0x4F, 0x46);
+	err += sn9c102_i2c_write(cam, 0x50, 0x36);
+	err += sn9c102_i2c_write(cam, 0x51, 0x0F);
+	err += sn9c102_i2c_write(cam, 0x52, 0x17);
+	err += sn9c102_i2c_write(cam, 0x53, 0x7F);
+	err += sn9c102_i2c_write(cam, 0x54, 0x96);
+	err += sn9c102_i2c_write(cam, 0x55, 0x40);
+	err += sn9c102_i2c_write(cam, 0x56, 0x40);
+	err += sn9c102_i2c_write(cam, 0x57, 0x40);
+	err += sn9c102_i2c_write(cam, 0x58, 0x0F);
+	err += sn9c102_i2c_write(cam, 0x59, 0xBA);
+	err += sn9c102_i2c_write(cam, 0x5A, 0x9A);
+	err += sn9c102_i2c_write(cam, 0x5B, 0x22);
+	err += sn9c102_i2c_write(cam, 0x5C, 0xB9);
+	err += sn9c102_i2c_write(cam, 0x5D, 0x9B);
+	err += sn9c102_i2c_write(cam, 0x5E, 0x10);
+	err += sn9c102_i2c_write(cam, 0x5F, 0xF0);
+	err += sn9c102_i2c_write(cam, 0x60, 0x05);
+	err += sn9c102_i2c_write(cam, 0x61, 0x60);
+	err += sn9c102_i2c_write(cam, 0x62, 0x00);
+	err += sn9c102_i2c_write(cam, 0x63, 0x00);
+	err += sn9c102_i2c_write(cam, 0x64, 0x50);
+	err += sn9c102_i2c_write(cam, 0x65, 0x30);
+	err += sn9c102_i2c_write(cam, 0x66, 0x00);
+	err += sn9c102_i2c_write(cam, 0x67, 0x80);
+	err += sn9c102_i2c_write(cam, 0x68, 0x7A);
+	err += sn9c102_i2c_write(cam, 0x69, 0x90);
+	err += sn9c102_i2c_write(cam, 0x6A, 0x80);
+	err += sn9c102_i2c_write(cam, 0x6B, 0x0A);
+	err += sn9c102_i2c_write(cam, 0x6C, 0x30);
+	err += sn9c102_i2c_write(cam, 0x6D, 0x48);
+	err += sn9c102_i2c_write(cam, 0x6E, 0x80);
+	err += sn9c102_i2c_write(cam, 0x6F, 0x74);
+	err += sn9c102_i2c_write(cam, 0x70, 0x64);
+	err += sn9c102_i2c_write(cam, 0x71, 0x60);
+	err += sn9c102_i2c_write(cam, 0x72, 0x5C);
+	err += sn9c102_i2c_write(cam, 0x73, 0x58);
+	err += sn9c102_i2c_write(cam, 0x74, 0x54);
+	err += sn9c102_i2c_write(cam, 0x75, 0x4C);
+	err += sn9c102_i2c_write(cam, 0x76, 0x40);
+	err += sn9c102_i2c_write(cam, 0x77, 0x38);
+	err += sn9c102_i2c_write(cam, 0x78, 0x34);
+	err += sn9c102_i2c_write(cam, 0x79, 0x30);
+	err += sn9c102_i2c_write(cam, 0x7A, 0x2F);
+	err += sn9c102_i2c_write(cam, 0x7B, 0x2B);
+	err += sn9c102_i2c_write(cam, 0x7C, 0x03);
+	err += sn9c102_i2c_write(cam, 0x7D, 0x07);
+	err += sn9c102_i2c_write(cam, 0x7E, 0x17);
+	err += sn9c102_i2c_write(cam, 0x7F, 0x34);
+	err += sn9c102_i2c_write(cam, 0x80, 0x41);
+	err += sn9c102_i2c_write(cam, 0x81, 0x4D);
+	err += sn9c102_i2c_write(cam, 0x82, 0x58);
+	err += sn9c102_i2c_write(cam, 0x83, 0x63);
+	err += sn9c102_i2c_write(cam, 0x84, 0x6E);
+	err += sn9c102_i2c_write(cam, 0x85, 0x77);
+	err += sn9c102_i2c_write(cam, 0x86, 0x87);
+	err += sn9c102_i2c_write(cam, 0x87, 0x95);
+	err += sn9c102_i2c_write(cam, 0x88, 0xAF);
+	err += sn9c102_i2c_write(cam, 0x89, 0xC7);
+	err += sn9c102_i2c_write(cam, 0x8A, 0xDF);
+	err += sn9c102_i2c_write(cam, 0x8B, 0x99);
+	err += sn9c102_i2c_write(cam, 0x8C, 0x99);
+	err += sn9c102_i2c_write(cam, 0x8D, 0xCF);
+	err += sn9c102_i2c_write(cam, 0x8E, 0x20);
+	err += sn9c102_i2c_write(cam, 0x8F, 0x26);
+	err += sn9c102_i2c_write(cam, 0x90, 0x10);
+	err += sn9c102_i2c_write(cam, 0x91, 0x0C);
+	err += sn9c102_i2c_write(cam, 0x92, 0x25);
+	err += sn9c102_i2c_write(cam, 0x93, 0x00);
+	err += sn9c102_i2c_write(cam, 0x94, 0x50);
+	err += sn9c102_i2c_write(cam, 0x95, 0x50);
+	err += sn9c102_i2c_write(cam, 0x96, 0x00);
+	err += sn9c102_i2c_write(cam, 0x97, 0x01);
+	err += sn9c102_i2c_write(cam, 0x98, 0x10);
+	err += sn9c102_i2c_write(cam, 0x99, 0x40);
+	err += sn9c102_i2c_write(cam, 0x9A, 0x40);
+	err += sn9c102_i2c_write(cam, 0x9B, 0x20);
+	err += sn9c102_i2c_write(cam, 0x9C, 0x00);
+	err += sn9c102_i2c_write(cam, 0x9D, 0x99);
+	err += sn9c102_i2c_write(cam, 0x9E, 0x7F);
+	err += sn9c102_i2c_write(cam, 0x9F, 0x00);
+	err += sn9c102_i2c_write(cam, 0xA0, 0x00);
+	err += sn9c102_i2c_write(cam, 0xA1, 0x00);
+
+	return err;
+}
+
+
+static int ov7660_get_ctrl(struct sn9c102_device* cam,
+			   struct v4l2_control* ctrl)
+{
+	int err = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
+			return -EIO;
+		break;
+	case V4L2_CID_DO_WHITE_BALANCE:
+		ctrl->value = sn9c102_pread_reg(cam, 0x02);
+		ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
+		break;
+	case V4L2_CID_RED_BALANCE:
+		ctrl->value = sn9c102_pread_reg(cam, 0x05);
+		ctrl->value &= 0x7f;
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		ctrl->value = sn9c102_pread_reg(cam, 0x06);
+		ctrl->value &= 0x7f;
+		break;
+	case SN9C102_V4L2_CID_GREEN_BALANCE:
+		ctrl->value = sn9c102_pread_reg(cam, 0x07);
+		ctrl->value &= 0x7f;
+		break;
+	case V4L2_CID_GAIN:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
+			return -EIO;
+		ctrl->value &= 0x7f;
+		break;
+	case V4L2_CID_AUTOGAIN:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
+			return -EIO;
+		ctrl->value &= 0x01;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err ? -EIO : 0;
+}
+
+
+static int ov7660_set_ctrl(struct sn9c102_device* cam,
+			   const struct v4l2_control* ctrl)
+{
+	int err = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE:
+		err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
+		break;
+	case V4L2_CID_DO_WHITE_BALANCE:
+		err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02);
+		break;
+	case V4L2_CID_RED_BALANCE:
+		err += sn9c102_write_reg(cam, ctrl->value, 0x05);
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		err += sn9c102_write_reg(cam, ctrl->value, 0x06);
+		break;
+	case SN9C102_V4L2_CID_GREEN_BALANCE:
+		err += sn9c102_write_reg(cam, ctrl->value, 0x07);
+		break;
+	case V4L2_CID_GAIN:
+		err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
+		break;
+	case V4L2_CID_AUTOGAIN:
+		err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value |
+						    (ctrl->value << 1));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err ? -EIO : 0;
+}
+
+
+static int ov7660_set_crop(struct sn9c102_device* cam,
+			   const struct v4l2_rect* rect)
+{
+	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+	int err = 0;
+	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
+	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+	err += sn9c102_write_reg(cam, h_start, 0x12);
+	err += sn9c102_write_reg(cam, v_start, 0x13);
+
+	return err;
+}
+
+
+static int ov7660_set_pix_format(struct sn9c102_device* cam,
+				 const struct v4l2_pix_format* pix)
+{
+	int r0, err = 0;
+
+	r0 = sn9c102_pread_reg(cam, 0x01);
+
+	if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+		err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
+		err += sn9c102_write_reg(cam, 0xa2, 0x17);
+		err += sn9c102_i2c_write(cam, 0x11, 0x00);
+	} else {
+		err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
+		err += sn9c102_write_reg(cam, 0xa2, 0x17);
+		err += sn9c102_i2c_write(cam, 0x11, 0x0d);
+	}
+
+	return err;
+}
+
+
+static struct sn9c102_sensor ov7660 = {
+	.name = "OV7660",
+	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+	.supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
+	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+	.frequency = SN9C102_I2C_100KHZ,
+	.interface = SN9C102_I2C_2WIRES,
+	.i2c_slave_id = 0x21,
+	.init = &ov7660_init,
+	.qctrl = {
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "global gain",
+			.minimum = 0x00,
+			.maximum = 0x7f,
+			.step = 0x01,
+			.default_value = 0x0a,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_EXPOSURE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "exposure",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = 0x50,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_DO_WHITE_BALANCE,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "night mode",
+			.minimum = 0x00,
+			.maximum = 0x01,
+			.step = 0x01,
+			.default_value = 0x00,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_RED_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "red balance",
+			.minimum = 0x00,
+			.maximum = 0x7f,
+			.step = 0x01,
+			.default_value = 0x1f,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_BLUE_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "blue balance",
+			.minimum = 0x00,
+			.maximum = 0x7f,
+			.step = 0x01,
+			.default_value = 0x1e,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_AUTOGAIN,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "auto adjust",
+			.minimum = 0x00,
+			.maximum = 0x01,
+			.step = 0x01,
+			.default_value = 0x00,
+			.flags = 0,
+		},
+		{
+			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "green balance",
+			.minimum = 0x00,
+			.maximum = 0x7f,
+			.step = 0x01,
+			.default_value = 0x20,
+			.flags = 0,
+		},
+	},
+	.get_ctrl = &ov7660_get_ctrl,
+	.set_ctrl = &ov7660_set_ctrl,
+	.cropcap = {
+		.bounds = {
+			.left = 0,
+			.top = 0,
+			.width = 640,
+			.height = 480,
+		},
+		.defrect = {
+			.left = 0,
+			.top = 0,
+			.width = 640,
+			.height = 480,
+		},
+	},
+	.set_crop = &ov7660_set_crop,
+	.pix_format = {
+		.width = 640,
+		.height = 480,
+		.pixelformat = V4L2_PIX_FMT_JPEG,
+		.priv = 8,
+	},
+	.set_pix_format = &ov7660_set_pix_format
+};
+
+
+int sn9c102_probe_ov7660(struct sn9c102_device* cam)
+{
+	int pid, ver, err = 0;
+
+	err += sn9c102_write_reg(cam, 0x01, 0xf1);
+	err += sn9c102_write_reg(cam, 0x00, 0xf1);
+	err += sn9c102_write_reg(cam, 0x01, 0x01);
+	err += sn9c102_write_reg(cam, 0x00, 0x01);
+	err += sn9c102_write_reg(cam, 0x28, 0x17);
+
+	pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
+	ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b);
+	if (err || pid < 0 || ver < 0)
+		return -EIO;
+	if (pid != 0x76 || ver != 0x60)
+		return -ENODEV;
+	sn9c102_attach_sensor(cam, &ov7660);
+
+	return 0;
+}
diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c
index 9915944..8d79a5f 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas106b.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera     *
+ * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera     *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -143,7 +143,7 @@
 static int pas106b_set_crop(struct sn9c102_device* cam,
 			    const struct v4l2_rect* rect)
 {
-	struct sn9c102_sensor* s = &pas106b;
+	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 	int err = 0;
 	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
 	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
@@ -172,6 +172,7 @@
 static struct sn9c102_sensor pas106b = {
 	.name = "PAS106B",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
 	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
 	.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
 	.interface = SN9C102_I2C_2WIRES,
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bca.c b/drivers/media/video/sn9c102/sn9c102_pas202bca.c
deleted file mode 100644
index c8f1ae2..0000000
--- a/drivers/media/video/sn9c102/sn9c102_pas202bca.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/***************************************************************************
- * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera   *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * This program is free software; you can redistribute it and/or modify    *
- * it under the terms of the GNU General Public License as published by    *
- * the Free Software Foundation; either version 2 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * This program is distributed in the hope that it will be useful,         *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
- * GNU General Public License for more details.                            *
- *                                                                         *
- * You should have received a copy of the GNU General Public License       *
- * along with this program; if not, write to the Free Software             *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
- ***************************************************************************/
-
-#include <linux/delay.h>
-#include "sn9c102_sensor.h"
-
-
-static struct sn9c102_sensor pas202bca;
-
-
-static int pas202bca_init(struct sn9c102_device* cam)
-{
-	int err = 0;
-
-	err += sn9c102_write_reg(cam, 0x00, 0x10);
-	err += sn9c102_write_reg(cam, 0x00, 0x11);
-	err += sn9c102_write_reg(cam, 0x00, 0x14);
-	err += sn9c102_write_reg(cam, 0x20, 0x17);
-	err += sn9c102_write_reg(cam, 0x30, 0x19);
-	err += sn9c102_write_reg(cam, 0x09, 0x18);
-
-	err += sn9c102_i2c_write(cam, 0x02, 0x14);
-	err += sn9c102_i2c_write(cam, 0x03, 0x40);
-	err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
-	err += sn9c102_i2c_write(cam, 0x0e, 0x01);
-	err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
-	err += sn9c102_i2c_write(cam, 0x10, 0x08);
-	err += sn9c102_i2c_write(cam, 0x13, 0x63);
-	err += sn9c102_i2c_write(cam, 0x15, 0x70);
-	err += sn9c102_i2c_write(cam, 0x11, 0x01);
-
-	msleep(400);
-
-	return err;
-}
-
-
-static int pas202bca_set_pix_format(struct sn9c102_device* cam,
-				    const struct v4l2_pix_format* pix)
-{
-	int err = 0;
-
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-		err += sn9c102_write_reg(cam, 0x24, 0x17);
-	else
-		err += sn9c102_write_reg(cam, 0x20, 0x17);
-
-	return err;
-}
-
-
-static int pas202bca_set_ctrl(struct sn9c102_device* cam,
-			      const struct v4l2_control* ctrl)
-{
-	int err = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_EXPOSURE:
-		err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
-		err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
-		break;
-	case V4L2_CID_RED_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
-		break;
-	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
-		break;
-	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
-		break;
-	case SN9C102_V4L2_CID_DAC_MAGNITUDE:
-		err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
-		break;
-	default:
-		return -EINVAL;
-	}
-	err += sn9c102_i2c_write(cam, 0x11, 0x01);
-
-	return err ? -EIO : 0;
-}
-
-
-static int pas202bca_set_crop(struct sn9c102_device* cam,
-			      const struct v4l2_rect* rect)
-{
-	struct sn9c102_sensor* s = &pas202bca;
-	int err = 0;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
-
-	err += sn9c102_write_reg(cam, h_start, 0x12);
-	err += sn9c102_write_reg(cam, v_start, 0x13);
-
-	return err;
-}
-
-
-static struct sn9c102_sensor pas202bca = {
-	.name = "PAS202BCA",
-	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-	.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
-	.interface = SN9C102_I2C_2WIRES,
-	.i2c_slave_id = 0x40,
-	.init = &pas202bca_init,
-	.qctrl = {
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "exposure",
-			.minimum = 0x01e5,
-			.maximum = 0x3fff,
-			.step = 0x0001,
-			.default_value = 0x01e5,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "global gain",
-			.minimum = 0x00,
-			.maximum = 0x1f,
-			.step = 0x01,
-			.default_value = 0x0c,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_RED_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "red balance",
-			.minimum = 0x00,
-			.maximum = 0x0f,
-			.step = 0x01,
-			.default_value = 0x01,
-			.flags = 0,
-		},
-		{
-			.id = V4L2_CID_BLUE_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "blue balance",
-			.minimum = 0x00,
-			.maximum = 0x0f,
-			.step = 0x01,
-			.default_value = 0x05,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "green balance",
-			.minimum = 0x00,
-			.maximum = 0x0f,
-			.step = 0x01,
-			.default_value = 0x00,
-			.flags = 0,
-		},
-		{
-			.id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "DAC magnitude",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 0x01,
-			.default_value = 0x04,
-			.flags = 0,
-		},
-	},
-	.set_ctrl = &pas202bca_set_ctrl,
-	.cropcap = {
-		.bounds = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-		.defrect = {
-			.left = 0,
-			.top = 0,
-			.width = 640,
-			.height = 480,
-		},
-	},
-	.set_crop = &pas202bca_set_crop,
-	.pix_format = {
-		.width = 640,
-		.height = 480,
-		.pixelformat = V4L2_PIX_FMT_SBGGR8,
-		.priv = 8,
-	},
-	.set_pix_format = &pas202bca_set_pix_format
-};
-
-
-int sn9c102_probe_pas202bca(struct sn9c102_device* cam)
-{
-	const struct usb_device_id pas202bca_id_table[] = {
-		{ USB_DEVICE(0x0c45, 0x60af), },
-		{ }
-	};
-	int err = 0;
-
-	if (!sn9c102_match_id(cam,pas202bca_id_table))
-		return -ENODEV;
-
-	err += sn9c102_write_reg(cam, 0x01, 0x01);
-	err += sn9c102_write_reg(cam, 0x40, 0x01);
-	err += sn9c102_write_reg(cam, 0x28, 0x17);
-	if (err)
-		return -EIO;
-
-	if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */
-		return -ENODEV;
-
-	sn9c102_attach_sensor(cam, &pas202bca);
-
-	return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
index e3c1178..7894f01 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
@@ -1,13 +1,13 @@
 /***************************************************************************
- * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera   *
+ * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera   *
  * Controllers                                                             *
  *                                                                         *
  * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio                  *
  *                       <medaglia@undl.org.br>                            *
  *                       http://cadu.homelinux.com:8080/                   *
  *                                                                         *
- * DAC Magnitude, exposure and green gain controls added by                *
- * Luca Risolia <luca.risolia@studio.unibo.it>                             *
+ * Support for SN9C103, DAC Magnitude, exposure and green gain controls    *
+ * added by Luca Risolia <luca.risolia@studio.unibo.it>                    *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -35,12 +35,54 @@
 {
 	int err = 0;
 
+	switch (sn9c102_get_bridge(cam)) {
+	case BRIDGE_SN9C101:
+	case BRIDGE_SN9C102:
 	err += sn9c102_write_reg(cam, 0x00, 0x10);
 	err += sn9c102_write_reg(cam, 0x00, 0x11);
 	err += sn9c102_write_reg(cam, 0x00, 0x14);
 	err += sn9c102_write_reg(cam, 0x20, 0x17);
 	err += sn9c102_write_reg(cam, 0x30, 0x19);
 	err += sn9c102_write_reg(cam, 0x09, 0x18);
+		break;
+	case BRIDGE_SN9C103:
+		err += sn9c102_write_reg(cam, 0x00, 0x02);
+		err += sn9c102_write_reg(cam, 0x00, 0x03);
+		err += sn9c102_write_reg(cam, 0x1a, 0x04);
+		err += sn9c102_write_reg(cam, 0x20, 0x05);
+		err += sn9c102_write_reg(cam, 0x20, 0x06);
+		err += sn9c102_write_reg(cam, 0x20, 0x07);
+		err += sn9c102_write_reg(cam, 0x00, 0x10);
+		err += sn9c102_write_reg(cam, 0x00, 0x11);
+		err += sn9c102_write_reg(cam, 0x00, 0x14);
+		err += sn9c102_write_reg(cam, 0x20, 0x17);
+		err += sn9c102_write_reg(cam, 0x30, 0x19);
+		err += sn9c102_write_reg(cam, 0x09, 0x18);
+		err += sn9c102_write_reg(cam, 0x02, 0x1c);
+		err += sn9c102_write_reg(cam, 0x03, 0x1d);
+		err += sn9c102_write_reg(cam, 0x0f, 0x1e);
+		err += sn9c102_write_reg(cam, 0x0c, 0x1f);
+		err += sn9c102_write_reg(cam, 0x00, 0x20);
+		err += sn9c102_write_reg(cam, 0x10, 0x21);
+		err += sn9c102_write_reg(cam, 0x20, 0x22);
+		err += sn9c102_write_reg(cam, 0x30, 0x23);
+		err += sn9c102_write_reg(cam, 0x40, 0x24);
+		err += sn9c102_write_reg(cam, 0x50, 0x25);
+		err += sn9c102_write_reg(cam, 0x60, 0x26);
+		err += sn9c102_write_reg(cam, 0x70, 0x27);
+		err += sn9c102_write_reg(cam, 0x80, 0x28);
+		err += sn9c102_write_reg(cam, 0x90, 0x29);
+		err += sn9c102_write_reg(cam, 0xa0, 0x2a);
+		err += sn9c102_write_reg(cam, 0xb0, 0x2b);
+		err += sn9c102_write_reg(cam, 0xc0, 0x2c);
+		err += sn9c102_write_reg(cam, 0xd0, 0x2d);
+		err += sn9c102_write_reg(cam, 0xe0, 0x2e);
+		err += sn9c102_write_reg(cam, 0xf0, 0x2f);
+		err += sn9c102_write_reg(cam, 0xff, 0x30);
+		break;
+	default:
+		break;
+	}
 
 	err += sn9c102_i2c_write(cam, 0x02, 0x14);
 	err += sn9c102_i2c_write(cam, 0x03, 0x40);
@@ -107,7 +149,7 @@
 	int err = 0;
 
 	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-		err += sn9c102_write_reg(cam, 0x24, 0x17);
+		err += sn9c102_write_reg(cam, 0x28, 0x17);
 	else
 		err += sn9c102_write_reg(cam, 0x20, 0x17);
 
@@ -152,11 +194,23 @@
 static int pas202bcb_set_crop(struct sn9c102_device* cam,
 			      const struct v4l2_rect* rect)
 {
-	struct sn9c102_sensor* s = &pas202bcb;
+	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 	int err = 0;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
+	u8 h_start = 0,
 	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
 
+	switch (sn9c102_get_bridge(cam)) {
+	case BRIDGE_SN9C101:
+	case BRIDGE_SN9C102:
+		h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
+		break;
+	case BRIDGE_SN9C103:
+		h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3;
+		break;
+	default:
+		break;
+	}
+
 	err += sn9c102_write_reg(cam, h_start, 0x12);
 	err += sn9c102_write_reg(cam, v_start, 0x13);
 
@@ -166,8 +220,8 @@
 
 static struct sn9c102_sensor pas202bcb = {
 	.name = "PAS202BCB",
-	.maintainer = "Carlos Eduardo Medaglia Dyonisio "
-		      "<medaglia@undl.org.br>",
+	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
 	.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
 	.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
 	.interface = SN9C102_I2C_2WIRES,
@@ -191,7 +245,7 @@
 			.minimum = 0x00,
 			.maximum = 0x1f,
 			.step = 0x01,
-			.default_value = 0x0c,
+			.default_value = 0x0b,
 			.flags = 0,
 		},
 		{
@@ -201,7 +255,7 @@
 			.minimum = 0x00,
 			.maximum = 0x0f,
 			.step = 0x01,
-			.default_value = 0x01,
+			.default_value = 0x00,
 			.flags = 0,
 		},
 		{
@@ -271,16 +325,27 @@
 	 *  Minimal initialization to enable the I2C communication
 	 *  NOTE: do NOT change the values!
 	 */
-	err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
-	err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */
-	err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
-	if (err)
-		return -EIO;
+	switch (sn9c102_get_bridge(cam)) {
+	case BRIDGE_SN9C101:
+	case BRIDGE_SN9C102:
+		err += sn9c102_write_reg(cam, 0x01, 0x01); /* power down */
+		err += sn9c102_write_reg(cam, 0x40, 0x01); /* power on */
+		err += sn9c102_write_reg(cam, 0x28, 0x17); /* clock 24 MHz */
+		break;
+	case BRIDGE_SN9C103: /* do _not_ change anything! */
+		err += sn9c102_write_reg(cam, 0x09, 0x01);
+		err += sn9c102_write_reg(cam, 0x44, 0x01);
+		err += sn9c102_write_reg(cam, 0x44, 0x02);
+		err += sn9c102_write_reg(cam, 0x29, 0x17);
+		break;
+	default:
+		break;
+	}
 
 	r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
 	r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
 
-	if (r0 < 0 || r1 < 0)
+	if (err || r0 < 0 || r1 < 0)
 		return -EIO;
 
 	pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h
index 2a874ee..05f2942 100644
--- a/drivers/media/video/sn9c102/sn9c102_sensor.h
+++ b/drivers/media/video/sn9c102/sn9c102_sensor.h
@@ -1,7 +1,7 @@
 /***************************************************************************
- * API for image sensors connected to the SN9C10x PC Camera Controllers    *
+ * API for image sensors connected to the SN9C1xx PC Camera Controllers    *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -36,14 +36,13 @@
 /*
    OVERVIEW.
    This is a small interface that allows you to add support for any CCD/CMOS
-   image sensors connected to the SN9C10X bridges. The entire API is documented
+   image sensors connected to the SN9C1XX bridges. The entire API is documented
    below. In the most general case, to support a sensor there are three steps
    you have to follow:
    1) define the main "sn9c102_sensor" structure by setting the basic fields;
    2) write a probing function to be called by the core module when the USB
       camera is recognized, then add both the USB ids and the name of that
-      function to the two corresponding tables SENSOR_TABLE and ID_TABLE (see
-      below);
+      function to the two corresponding tables in sn9c102_devtable.h;
    3) implement the methods that you want/need (and fill the rest of the main
       structure accordingly).
    "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
@@ -54,42 +53,21 @@
 
 /*****************************************************************************/
 
-/*
-   Probing functions: on success, you must attach the sensor to the camera
-   by calling sn9c102_attach_sensor() provided below.
-   To enable the I2C communication, you might need to perform a really basic
-   initialization of the SN9C10X chip by using the write function declared
-   ahead.
-   Functions must return 0 on success, the appropriate error otherwise.
-*/
-extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
-extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
-extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
-extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
-extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam);
-extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
-extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
-extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
-
-/*
-   Add the above entries to this table. Be sure to add the entry in the right
-   place, since, on failure, the next probing routine is called according to
-   the order of the list below, from top to bottom.
-*/
-#define SN9C102_SENSOR_TABLE                                                  \
-static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {              \
-	&sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */     \
-	&sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */    \
-	&sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */  \
-	&sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */    \
-	&sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \
-	&sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */    \
-	&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */       \
-	&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */       \
-	NULL,                                                                 \
+enum sn9c102_bridge {
+	BRIDGE_SN9C101 = 0x01,
+	BRIDGE_SN9C102 = 0x02,
+	BRIDGE_SN9C103 = 0x04,
+	BRIDGE_SN9C105 = 0x08,
+	BRIDGE_SN9C120 = 0x10,
 };
 
-/* Device identification */
+/* Return the bridge name */
+enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device* cam);
+
+/* Return a pointer the sensor struct attached to the camera */
+struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam);
+
+/* Identify a device */
 extern struct sn9c102_device*
 sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
 
@@ -99,68 +77,8 @@
 		      struct sn9c102_sensor* sensor);
 
 /*
-   Each SN9C10x camera has proper PID/VID identifiers.
-   SN9C103 supports multiple interfaces, but we only handle the video class
-   interface.
-*/
-#define SN9C102_USB_DEVICE(vend, prod, intclass)                              \
-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |                           \
-		       USB_DEVICE_ID_MATCH_INT_CLASS,                         \
-	.idVendor = (vend),                                                   \
-	.idProduct = (prod),                                                  \
-	.bInterfaceClass = (intclass)
-
-#define SN9C102_ID_TABLE                                                      \
-static const struct usb_device_id sn9c102_id_table[] = {                      \
-	{ USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */                     \
-	{ USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */                     \
-	{ USB_DEVICE(0x0c45, 0x6007), },                                      \
-	{ USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */                        \
-	{ USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */                        \
-	{ USB_DEVICE(0x0c45, 0x6024), },                                      \
-	{ USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */      \
-	{ USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */                      \
-	{ USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */                        \
-	{ USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */                        \
-	{ USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */                        \
-	{ USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */                         \
-	{ USB_DEVICE(0x0c45, 0x602d), },                                      \
-	{ USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */                         \
-	{ USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */                          \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */  \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */     \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */         \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */         \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */           \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */          \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */       \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */       \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */       \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), },                        \
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), },                        \
-	{ }                                                                   \
-};
-
-/*****************************************************************************/
-
-/*
    Read/write routines: they always return -1 on error, 0 or the read value
-   otherwise. NOTE that a real read operation is not supported by the SN9C10X
+   otherwise. NOTE that a real read operation is not supported by the SN9C1XX
    chip for some of its registers. To work around this problem, a pseudo-read
    call is provided instead: it returns the last successfully written value
    on the register (0 if it has never been written), the usual -1 on error.
@@ -176,7 +94,7 @@
    These must be used if and only if the sensor doesn't implement the standard
    I2C protocol. There are a number of good reasons why you must use the
    single-byte versions of these functions: do not abuse. The first function
-   writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X
+   writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX
    chip. The second one programs the registers 0x09 and 0x10 with data0 and
    data1, and places the n bytes read from the sensor register table in the
    buffer pointed by 'buffer'. Both the functions return -1 on error; the write
@@ -200,16 +118,6 @@
 extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
 extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
 
-/*
-   NOTE: there are no exported debugging functions. To uniform the output you
-   must use the dev_info()/dev_warn()/dev_err() macros defined in device.h,
-   already included here, the argument being the struct device '&usbdev->dev'
-   of the sensor structure. Do NOT use these macros before the sensor is
-   attached or the kernel will crash! However, you should not need to notify
-   the user about common errors or other messages, since this is done by the
-   master module.
-*/
-
 /*****************************************************************************/
 
 enum sn9c102_i2c_sysfs_ops {
@@ -227,17 +135,19 @@
 	SN9C102_I2C_3WIRES,
 };
 
-#define SN9C102_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
+#define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
 
 struct sn9c102_sensor {
 	char name[32], /* sensor name */
 	     maintainer[64]; /* name of the mantainer <email> */
 
+	enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */
+
 	/* Supported operations through the 'sysfs' interface */
 	enum sn9c102_i2c_sysfs_ops sysfs_ops;
 
 	/*
-	   These sensor capabilities must be provided if the SN9C10X controller
+	   These sensor capabilities must be provided if the SN9C1XX controller
 	   needs to communicate through the sensor serial interface by using
 	   at least one of the i2c functions available.
 	*/
@@ -260,7 +170,7 @@
 	/*
 	   This function will be called after the sensor has been attached.
 	   It should be used to initialize the sensor only, but may also
-	   configure part of the SN9C10X chip if necessary. You don't need to
+	   configure part of the SN9C1XX chip if necessary. You don't need to
 	   setup picture settings like brightness, contrast, etc.. here, if
 	   the corrisponding controls are implemented (see below), since
 	   they are adjusted in the core driver by calling the set_ctrl()
@@ -300,7 +210,7 @@
 	   It is not always true that the largest achievable active window can
 	   cover the whole array of pixels. The V4L2 API defines another
 	   area called "source rectangle", which, in turn, is a subrectangle of
-	   the active window. The SN9C10X chip is always programmed to read the
+	   the active window. The SN9C1XX chip is always programmed to read the
 	   source rectangle.
 	   The bounds of both the active window and the source rectangle are
 	   specified in the cropcap substructures 'bounds' and 'defrect'.
@@ -326,13 +236,13 @@
 			const struct v4l2_rect* rect);
 	/*
 	   To be called on VIDIOC_C_SETCROP. The core module always calls a
-	   default routine which configures the appropriate SN9C10X regs (also
+	   default routine which configures the appropriate SN9C1XX regs (also
 	   scaling), but you may need to override/adjust specific stuff.
 	   'rect' contains width and height values that are multiple of 16: in
 	   case you override the default function, you always have to program
 	   the chip to match those values; on error return the corresponding
 	   error code without rolling back.
-	   NOTE: in case, you must program the SN9C10X chip to get rid of
+	   NOTE: in case, you must program the SN9C1XX chip to get rid of
 		 blank pixels or blank lines at the _start_ of each line or
 		 frame after each HSYNC or VSYNC, so that the image starts with
 		 real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
@@ -344,16 +254,16 @@
 	/*
 	   What you have to define here are: 1) initial 'width' and 'height' of
 	   the target rectangle 2) the initial 'pixelformat', which can be
-	   either V4L2_PIX_FMT_SN9C10X (for compressed video) or
-	   V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the
-	   number of bits per pixel for uncompressed video, 8 or 9 (despite the
-	   current value of 'pixelformat').
+	   either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video)
+	   or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate
+	   the number of bits per pixel for uncompressed video, 8 or 9 (despite
+	   the current value of 'pixelformat').
 	   NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
 		   of cropcap.defrect.width and cropcap.defrect.height. I
 		   suggest 1/1.
 	   NOTE 2: The initial compression quality is defined by the first bit
 		   of reg 0x17 during the initialization of the image sensor.
-	   NOTE 3: as said above, you have to program the SN9C10X chip to get
+	   NOTE 3: as said above, you have to program the SN9C1XX chip to get
 		   rid of any blank pixels, so that the output of the sensor
 		   matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
 	*/
@@ -378,12 +288,12 @@
 /*****************************************************************************/
 
 /* Private ioctl's for control settings supported by some image sensors */
-#define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE
-#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1
-#define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2
-#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3
-#define SN9C102_V4L2_CID_GAMMA V4L2_CID_PRIVATE_BASE + 4
-#define SN9C102_V4L2_CID_BAND_FILTER V4L2_CID_PRIVATE_BASE + 5
-#define SN9C102_V4L2_CID_BRIGHT_LEVEL V4L2_CID_PRIVATE_BASE + 6
+#define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0)
+#define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1)
+#define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2)
+#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3)
+#define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4)
+#define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5)
+#define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6)
 
 #endif /* _SN9C102_SENSOR_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
index 294eb02..90023ad 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera  *
+ * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera  *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -64,7 +64,7 @@
 static int tas5110c1b_set_crop(struct sn9c102_device* cam,
 			       const struct v4l2_rect* rect)
 {
-	struct sn9c102_sensor* s = &tas5110c1b;
+	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 	int err = 0;
 	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
 	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
@@ -98,6 +98,7 @@
 static struct sn9c102_sensor tas5110c1b = {
 	.name = "TAS5110C1B",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
 	.sysfs_ops = SN9C102_I2C_WRITE,
 	.frequency = SN9C102_I2C_100KHZ,
 	.interface = SN9C102_I2C_3WIRES,
@@ -145,6 +146,7 @@
 	const struct usb_device_id tas5110c1b_id_table[] = {
 		{ USB_DEVICE(0x0c45, 0x6001), },
 		{ USB_DEVICE(0x0c45, 0x6005), },
+		{ USB_DEVICE(0x0c45, 0x6007), },
 		{ USB_DEVICE(0x0c45, 0x60ab), },
 		{ }
 	};
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
index 9ecb090..cb1b318 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera  *
+ * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera  *
  * Controllers                                                             *
  *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -65,7 +65,7 @@
 static int tas5130d1b_set_crop(struct sn9c102_device* cam,
 			       const struct v4l2_rect* rect)
 {
-	struct sn9c102_sensor* s = &tas5130d1b;
+	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
 	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
 	int err = 0;
@@ -99,6 +99,7 @@
 static struct sn9c102_sensor tas5130d1b = {
 	.name = "TAS5130D1B",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
 	.sysfs_ops = SN9C102_I2C_WRITE,
 	.frequency = SN9C102_I2C_100KHZ,
 	.interface = SN9C102_I2C_3WIRES,
@@ -154,6 +155,7 @@
 int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
 {
 	const struct usb_device_id tas5130d1b_id_table[] = {
+		{ USB_DEVICE(0x0c45, 0x6024), },
 		{ USB_DEVICE(0x0c45, 0x6025), },
 		{ USB_DEVICE(0x0c45, 0x60aa), },
 		{ }
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 525d812..3e736be 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -1901,7 +1901,7 @@
 	return 0;
 }
 
-static struct file_operations saa_fops = {
+static const struct file_operations saa_fops = {
 	.owner = THIS_MODULE,
 	.open = saa_open,
 	.release = saa_release,
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index a1ec3ac..bf3aa8d 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -1380,7 +1380,7 @@
 	return realcount;
 }				/* stv680_read */
 
-static struct file_operations stv680_fops = {
+static const struct file_operations stv680_fops = {
 	.owner =	THIS_MODULE,
 	.open =		stv_open,
 	.release =     	stv_close,
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 78e043a..d1ccc06 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -38,7 +38,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 827633b..00f0e8b 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -19,7 +19,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index ee4a493..7be73e3 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -7,7 +7,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 1654576..3ae5a9c 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -4,7 +4,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
@@ -213,8 +212,7 @@
 		return -ENODEV;
 	}
 
-	if (client->adapter->owner)
-		module_put(client->adapter->owner);
+	module_put(client->adapter->owner);
 	return 0;
 }
 
@@ -228,7 +226,7 @@
 	.detach_client   = tvmixer_clients,
 };
 
-static struct file_operations tvmixer_fops = {
+static const struct file_operations tvmixer_fops = {
 	.owner		= THIS_MODULE,
 	.llseek         = no_llseek,
 	.ioctl          = tvmixer_ioctl,
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index bc0a4fc..886b5df 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -950,17 +950,8 @@
 	}
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	case VIDIOC_INT_G_REGISTER:
-	{
-		struct v4l2_register *reg = arg;
-
-		if (reg->i2c_id != I2C_DRIVERID_TVP5150)
-			return -EINVAL;
-		reg->val = tvp5150_read(c, reg->reg & 0xff);
-		break;
-	}
-
-	case VIDIOC_INT_S_REGISTER:
+	case VIDIOC_DBG_G_REGISTER:
+	case VIDIOC_DBG_S_REGISTER:
 	{
 		struct v4l2_register *reg = arg;
 
@@ -968,7 +959,10 @@
 			return -EINVAL;
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff);
+		if (cmd == VIDIOC_DBG_G_REGISTER)
+			reg->val = tvp5150_read(c, reg->reg & 0xff);
+		else
+			tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff);
 		break;
 	}
 #endif
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c
index fc52201..b3b5fd5 100644
--- a/drivers/media/video/upd64031a.c
+++ b/drivers/media/video/upd64031a.c
@@ -162,27 +162,19 @@
 		break;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	case VIDIOC_INT_G_REGISTER:
+	case VIDIOC_DBG_G_REGISTER:
+	case VIDIOC_DBG_S_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);
+		if (cmd == VIDIOC_DBG_G_REGISTER)
+			reg->val = upd64031a_read(client, reg->reg & 0xff);
+		else
+			upd64031a_write(client, reg->reg & 0xff, reg->val & 0xff);
 		break;
 	}
 #endif
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c
index c3a7ffe..8852903 100644
--- a/drivers/media/video/upd64083.c
+++ b/drivers/media/video/upd64083.c
@@ -139,27 +139,19 @@
 		break;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	case VIDIOC_INT_G_REGISTER:
+	case VIDIOC_DBG_G_REGISTER:
+	case VIDIOC_DBG_S_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);
+		if (cmd == VIDIOC_DBG_G_REGISTER)
+			reg->val = upd64083_read(client, reg->reg & 0xff);
+		else
+			upd64083_write(client, reg->reg & 0xff, reg->val & 0xff);
 		break;
 	}
 #endif
diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c
index 76f771b..14db95e 100644
--- a/drivers/media/video/usbvideo/ibmcam.c
+++ b/drivers/media/video/usbvideo/ibmcam.c
@@ -15,7 +15,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c
index 10c58b4..95453c1 100644
--- a/drivers/media/video/usbvideo/ultracam.c
+++ b/drivers/media/video/usbvideo/ultracam.c
@@ -6,7 +6,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index b560c9d..d34d8c8 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -945,7 +945,7 @@
 	return rv;
 }
 
-static struct file_operations usbvideo_fops = {
+static const struct file_operations usbvideo_fops = {
 	.owner =  THIS_MODULE,
 	.open =   usbvideo_v4l_open,
 	.release =usbvideo_v4l_close,
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
index 08f9559..876fd27 100644
--- a/drivers/media/video/usbvideo/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -1234,7 +1234,7 @@
 static inline void vicam_destroy_proc_entry(void *ptr) { }
 #endif
 
-static struct file_operations vicam_fops = {
+static const struct file_operations vicam_fops = {
 	.owner		= THIS_MODULE,
 	.open		= vicam_open,
 	.release	= vicam_close,
diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig
index fc24ef0..c43a5d8 100644
--- a/drivers/media/video/usbvision/Kconfig
+++ b/drivers/media/video/usbvision/Kconfig
@@ -1,6 +1,6 @@
 config VIDEO_USBVISION
 	tristate "USB video devices based on Nogatech NT1003/1004/1005"
-	depends on I2C && VIDEO_V4L2
+	depends on I2C && VIDEO_V4L2 && USB
 	select VIDEO_TUNER
 	select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
 	---help---
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index a807d97..f2154dc 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -24,7 +24,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
@@ -139,7 +138,7 @@
 	return mem;
 }
 
-void usbvision_rvfree(void *mem, unsigned long size)
+static void usbvision_rvfree(void *mem, unsigned long size)
 {
 	unsigned long adr;
 
@@ -1853,28 +1852,33 @@
 
 /*
  * usbvision_frames_alloc
- * allocate the maximum frames this driver can manage
+ * allocate the required frames
  */
-int usbvision_frames_alloc(struct usb_usbvision *usbvision)
+int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames)
 {
 	int i;
 
-	/* Allocate memory for the frame buffers */
-	usbvision->max_frame_size = MAX_FRAME_SIZE;
-	usbvision->fbuf_size = USBVISION_NUMFRAMES * usbvision->max_frame_size;
-	usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size);
+	/*needs to be page aligned cause the buffers can be mapped individually! */
+	usbvision->max_frame_size =  PAGE_ALIGN(usbvision->curwidth *
+						usbvision->curheight *
+						usbvision->palette.bytes_per_pixel);
 
-	if(usbvision->fbuf == NULL) {
-		err("%s: unable to allocate %d bytes for fbuf ",
-		    __FUNCTION__, usbvision->fbuf_size);
-		return -ENOMEM;
+	/* Try to do my best to allocate the frames the user want in the remaining memory */
+	usbvision->num_frames = number_of_frames;
+	while (usbvision->num_frames > 0) {
+		usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size;
+		if((usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size))) {
+			break;
+		}
+		usbvision->num_frames--;
 	}
+
 	spin_lock_init(&usbvision->queue_lock);
 	init_waitqueue_head(&usbvision->wait_frame);
 	init_waitqueue_head(&usbvision->wait_stream);
 
 	/* Allocate all buffers */
-	for (i = 0; i < USBVISION_NUMFRAMES; i++) {
+	for (i = 0; i < usbvision->num_frames; i++) {
 		usbvision->frame[i].index = i;
 		usbvision->frame[i].grabstate = FrameState_Unused;
 		usbvision->frame[i].data = usbvision->fbuf +
@@ -1888,7 +1892,8 @@
 		usbvision->frame[i].height = usbvision->curheight;
 		usbvision->frame[i].bytes_read = 0;
 	}
-	return 0;
+	PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",usbvision->num_frames,usbvision->max_frame_size);
+	return usbvision->num_frames;
 }
 
 /*
@@ -1898,9 +1903,13 @@
 void usbvision_frames_free(struct usb_usbvision *usbvision)
 {
 	/* Have to free all that memory */
+	PDEBUG(DBG_FUNC, "free %d frames",usbvision->num_frames);
+
 	if (usbvision->fbuf != NULL) {
 		usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size);
 		usbvision->fbuf = NULL;
+
+		usbvision->num_frames = 0;
 	}
 }
 /*
@@ -2352,6 +2361,32 @@
 	return USBVISION_IS_OPERATIONAL(usbvision);
 }
 
+int usbvision_set_alternate(struct usb_usbvision *dev)
+{
+	int errCode, prev_alt = dev->ifaceAlt;
+	int i;
+
+	dev->ifaceAlt=0;
+	for(i=0;i< dev->num_alt; i++)
+		if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->ifaceAlt])
+			dev->ifaceAlt=i;
+
+	if (dev->ifaceAlt != prev_alt) {
+		dev->isocPacketSize = dev->alt_max_pkt_size[dev->ifaceAlt];
+		PDEBUG(DBG_FUNC,"setting alternate %d with wMaxPacketSize=%u", dev->ifaceAlt,dev->isocPacketSize);
+		errCode = usb_set_interface(dev->dev, dev->iface, dev->ifaceAlt);
+		if (errCode < 0) {
+			err ("cannot change alternate number to %d (error=%i)",
+							dev->ifaceAlt, errCode);
+			return errCode;
+		}
+	}
+
+	PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isocPacketSize);
+
+	return 0;
+}
+
 /*
  * usbvision_init_isoc()
  *
@@ -2369,15 +2404,13 @@
 	scratch_reset(usbvision);
 
 	/* Alternate interface 1 is is the biggest frame size */
-	errCode = usb_set_interface(dev, usbvision->iface, usbvision->ifaceAltActive);
+	errCode = usbvision_set_alternate(usbvision);
 	if (errCode < 0) {
 		usbvision->last_error = errCode;
 		return -EBUSY;
 	}
 
 	regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
-	usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1;
-	PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize);
 
 	usbvision->usb_bandwidth = regValue >> 1;
 	PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
@@ -2463,8 +2496,9 @@
 	if (!usbvision->remove_pending) {
 
 		/* Set packet size to 0 */
+		usbvision->ifaceAlt=0;
 		errCode = usb_set_interface(usbvision->dev, usbvision->iface,
-				      usbvision->ifaceAltInactive);
+					    usbvision->ifaceAlt);
 		if (errCode < 0) {
 			err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode);
 			usbvision->last_error = errCode;
@@ -2491,6 +2525,7 @@
 	RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs);
 	usbvision->ctl_input = channel;
 	  route.input = SAA7115_COMPOSITE1;
+	  route.output = 0;
 	  call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route);
 	  call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input);
 
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index 858252c..609e1fd 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -34,7 +34,6 @@
 #include <asm/uaccess.h>
 #include <linux/ioport.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
 #include "usbvision.h"
@@ -258,6 +257,7 @@
 	sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name),
 		" #%d", usbvision->vdev->minor & 0x1f);
 	PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name);
+	usbvision->i2c_adap.dev.parent = &usbvision->dev->dev;
 
 	i2c_set_adapdata(&usbvision->i2c_adap, usbvision);
 	i2c_set_clientdata(&usbvision->i2c_client, usbvision);
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 7243337..ae5f425 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -46,7 +46,6 @@
 
 #include <linux/version.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
@@ -231,7 +230,7 @@
 	ctrl.value = 0;
 	if(usbvision->user)
 		call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-	return sprintf(buf, "%d\n", ctrl.value >> 8);
+	return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
 
@@ -244,7 +243,7 @@
 	ctrl.value = 0;
 	if(usbvision->user)
 		call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-	return sprintf(buf, "%d\n", ctrl.value >> 8);
+	return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
 
@@ -257,7 +256,7 @@
 	ctrl.value = 0;
 	if(usbvision->user)
 		call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-	return sprintf(buf, "%d\n", ctrl.value >> 8);
+	return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
 
@@ -270,7 +269,7 @@
 	ctrl.value = 0;
 	if(usbvision->user)
 		call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-	return sprintf(buf, "%d\n", ctrl.value >> 8);
+	return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
 
@@ -392,19 +391,14 @@
 	if (usbvision->user)
 		errCode = -EBUSY;
 	else {
-		/* Allocate memory for the frame buffers */
-		errCode = usbvision_frames_alloc(usbvision);
-		if(!errCode) {
-			/* Allocate memory for the scratch ring buffer */
-			errCode = usbvision_scratch_alloc(usbvision);
-			if ((!errCode) && (isocMode==ISOC_MODE_COMPRESS)) {
-				/* Allocate intermediate decompression buffers only if needed */
-				errCode = usbvision_decompress_alloc(usbvision);
-			}
+		/* Allocate memory for the scratch ring buffer */
+		errCode = usbvision_scratch_alloc(usbvision);
+		if (isocMode==ISOC_MODE_COMPRESS) {
+			/* Allocate intermediate decompression buffers only if needed */
+			errCode = usbvision_decompress_alloc(usbvision);
 		}
 		if (errCode) {
 			/* Deallocate all buffers if trouble */
-			usbvision_frames_free(usbvision);
 			usbvision_scratch_free(usbvision);
 			usbvision_decompress_free(usbvision);
 		}
@@ -477,6 +471,7 @@
 
 	usbvision_decompress_free(usbvision);
 	usbvision_frames_free(usbvision);
+	usbvision_empty_framequeues(usbvision);
 	usbvision_scratch_free(usbvision);
 
 	usbvision->user--;
@@ -490,7 +485,7 @@
 	up(&usbvision->lock);
 
 	if (usbvision->remove_pending) {
-		info("%s: Final disconnect", __FUNCTION__);
+		printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
 		usbvision_release(usbvision);
 	}
 
@@ -520,27 +515,8 @@
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 		/* ioctls to allow direct acces to the NT100x registers */
-		case VIDIOC_INT_G_REGISTER:
-		{
-			struct v4l2_register *reg = arg;
-			int errCode;
-
-			if (reg->i2c_id != 0)
-				return -EINVAL;
-			/* NT100x has a 8-bit register space */
-			errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
-			if (errCode < 0) {
-				err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode);
-			}
-			else {
-				reg->val=(unsigned char)errCode;
-				PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X",
-							(unsigned int)reg->reg, reg->val);
-				errCode = 0; // No error
-			}
-			return errCode;
-		}
-		case VIDIOC_INT_S_REGISTER:
+		case VIDIOC_DBG_G_REGISTER:
+		case VIDIOC_DBG_S_REGISTER:
 		{
 			struct v4l2_register *reg = arg;
 			int errCode;
@@ -549,15 +525,22 @@
 				return -EINVAL;
 			if (!capable(CAP_SYS_ADMIN))
 				return -EPERM;
-			errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
+			/* NT100x has a 8-bit register space */
+			if (cmd == VIDIOC_DBG_G_REGISTER)
+				errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
+			else
+				errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
 			if (errCode < 0) {
-				err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode);
+				err("%s: VIDIOC_DBG_%c_REGISTER failed: error %d", __FUNCTION__,
+				    cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', errCode);
+				return errCode;
 			}
-			else {
-				PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X",
-							(unsigned int)reg->reg, reg->val);
-				errCode = 0;
-			}
+			if (cmd == VIDIOC_DBG_S_REGISTER)
+				reg->val = (u8)errCode;
+
+			PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X",
+			       cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S',
+			       (unsigned int)reg->reg, reg->val);
 			return 0;
 		}
 #endif
@@ -793,8 +776,8 @@
 		case VIDIOC_G_CTRL:
 		{
 			struct v4l2_control *ctrl = arg;
-			PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
 			call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
+			PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
 			return 0;
 		}
 		case VIDIOC_S_CTRL:
@@ -822,7 +805,9 @@
 				    return ret;
 			}
 
+			usbvision_frames_free(usbvision);
 			usbvision_empty_framequeues(usbvision);
+			vr->count = usbvision_frames_alloc(usbvision,vr->count);
 
 			usbvision->curFrame = NULL;
 
@@ -839,7 +824,7 @@
 			if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
 				return -EINVAL;
 			}
-			if(vb->index>=USBVISION_NUMFRAMES)  {
+			if(vb->index>=usbvision->num_frames)  {
 				return -EINVAL;
 			}
 			// Updating the corresponding frame state
@@ -853,7 +838,7 @@
 				vb->flags |= V4L2_BUF_FLAG_MAPPED;
 			vb->memory = V4L2_MEMORY_MMAP;
 
-			vb->m.offset = vb->index*usbvision->max_frame_size;
+			vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size);
 
 			vb->memory = V4L2_MEMORY_MMAP;
 			vb->field = V4L2_FIELD_NONE;
@@ -872,7 +857,7 @@
 			if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
 				return -EINVAL;
 			}
-			if(vb->index>=USBVISION_NUMFRAMES)  {
+			if(vb->index>=usbvision->num_frames)  {
 				return -EINVAL;
 			}
 
@@ -1042,6 +1027,7 @@
 						if ((ret = usbvision_stream_interrupt(usbvision)))
 							return ret;
 					}
+					usbvision_frames_free(usbvision);
 					usbvision_empty_framequeues(usbvision);
 
 					usbvision->curFrame = NULL;
@@ -1072,7 +1058,7 @@
 }
 
 
-static ssize_t usbvision_v4l2_read(struct file *file, char *buf,
+static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
 		      size_t count, loff_t *ppos)
 {
 	struct video_device *dev = video_devdata(file);
@@ -1088,12 +1074,24 @@
 	if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
 		return -EFAULT;
 
-	/* no stream is running, make it running ! */
-	usbvision->streaming = Stream_On;
-	call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL);
+	/* This entry point is compatible with the mmap routines so that a user can do either
+	   VIDIOC_QBUF/VIDIOC_DQBUF to get frames or call read on the device. */
+	if(!usbvision->num_frames) {
+		/* First, allocate some frames to work with if this has not been done with
+		 VIDIOC_REQBUF */
+		usbvision_frames_free(usbvision);
+		usbvision_empty_framequeues(usbvision);
+		usbvision_frames_alloc(usbvision,USBVISION_NUMFRAMES);
+	}
 
-	/* First, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */
-	for(i=0;i<USBVISION_NUMFRAMES;i++) {
+	if(usbvision->streaming != Stream_On) {
+		/* no stream is running, make it running ! */
+		usbvision->streaming = Stream_On;
+		call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL);
+	}
+
+	/* Then, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */
+	for(i=0;i<usbvision->num_frames;i++) {
 		frame = &usbvision->frame[i];
 		if(frame->grabstate == FrameState_Unused) {
 			/* Mark it as ready and enqueue frame */
@@ -1170,6 +1168,8 @@
 	struct video_device *dev = video_devdata(file);
 	struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
 
+	PDEBUG(DBG_MMAP, "mmap");
+
 	down(&usbvision->lock);
 
 	if (!USBVISION_IS_OPERATIONAL(usbvision)) {
@@ -1178,16 +1178,16 @@
 	}
 
 	if (!(vma->vm_flags & VM_WRITE) ||
-	    size != PAGE_ALIGN(usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel)) {
+	    size != PAGE_ALIGN(usbvision->max_frame_size)) {
 		up(&usbvision->lock);
 		return -EINVAL;
 	}
 
-	for (i = 0; i < USBVISION_NUMFRAMES; i++) {
-		if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff)
+	for (i = 0; i < usbvision->num_frames; i++) {
+		if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) == vma->vm_pgoff)
 			break;
 	}
-	if (i == USBVISION_NUMFRAMES) {
+	if (i == usbvision->num_frames) {
 		PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range");
 		up(&usbvision->lock);
 		return -EINVAL;
@@ -1243,6 +1243,13 @@
 			}
 		}
 
+		/* Alternate interface 1 is is the biggest frame size */
+		errCode = usbvision_set_alternate(usbvision);
+		if (errCode < 0) {
+			usbvision->last_error = errCode;
+			return -EBUSY;
+		}
+
 		// If so far no errors then we shall start the radio
 		usbvision->radio = 1;
 		call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type);
@@ -1274,6 +1281,11 @@
 
 	down(&usbvision->lock);
 
+	/* Set packet size to 0 */
+	usbvision->ifaceAlt=0;
+	errCode = usb_set_interface(usbvision->dev, usbvision->iface,
+				    usbvision->ifaceAlt);
+
 	usbvision_audio_off(usbvision);
 	usbvision->radio=0;
 	usbvision->user--;
@@ -1286,7 +1298,7 @@
 	up(&usbvision->lock);
 
 	if (usbvision->remove_pending) {
-		info("%s: Final disconnect", __FUNCTION__);
+		printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
 		usbvision_release(usbvision);
 	}
 
@@ -1475,7 +1487,7 @@
 //
 
 // Video template
-static struct file_operations usbvision_fops = {
+static const struct file_operations usbvision_fops = {
 	.owner             = THIS_MODULE,
 	.open		= usbvision_v4l2_open,
 	.release	= usbvision_v4l2_close,
@@ -1496,7 +1508,7 @@
 
 
 // Radio template
-static struct file_operations usbvision_radio_fops = {
+static const struct file_operations usbvision_radio_fops = {
 	.owner             = THIS_MODULE,
 	.open		= usbvision_radio_open,
 	.release	= usbvision_radio_close,
@@ -1517,7 +1529,7 @@
 
 
 // vbi template
-static struct file_operations usbvision_vbi_fops = {
+static const struct file_operations usbvision_vbi_fops = {
 	.owner             = THIS_MODULE,
 	.open		= usbvision_vbi_open,
 	.release	= usbvision_vbi_close,
@@ -1612,7 +1624,7 @@
 	if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) {
 		goto err_exit;
 	}
-	info("USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]", usbvision->nr,usbvision->vdev->minor & 0x1f);
+	printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", usbvision->nr,usbvision->vdev->minor & 0x1f);
 
 	// Radio Device:
 	if (usbvision_device_data[usbvision->DevModel].Radio) {
@@ -1624,7 +1636,7 @@
 		if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) {
 			goto err_exit;
 		}
-		info("USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]", usbvision->nr, usbvision->rdev->minor & 0x1f);
+		printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", usbvision->nr, usbvision->rdev->minor & 0x1f);
 	}
 	// vbi Device:
 	if (usbvision_device_data[usbvision->DevModel].vbi) {
@@ -1635,7 +1647,7 @@
 		if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) {
 			goto err_exit;
 		}
-		info("USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)", usbvision->nr,usbvision->vbi->minor & 0x1f);
+		printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", usbvision->nr,usbvision->vbi->minor & 0x1f);
 	}
 	// all done
 	return 0;
@@ -1765,15 +1777,17 @@
  */
 static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid)
 {
-	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_device *dev = usb_get_dev(interface_to_usbdev(intf));
+	struct usb_interface *uif;
 	__u8 ifnum = intf->altsetting->desc.bInterfaceNumber;
 	const struct usb_host_interface *interface;
 	struct usb_usbvision *usbvision = NULL;
 	const struct usb_endpoint_descriptor *endpoint;
-	int model;
+	int model,i;
 
 	PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u",
 					dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
+
 	/* Is it an USBVISION video dev? */
 	model = 0;
 	for(model = 0; usbvision_device_data[model].idVendor; model++) {
@@ -1784,7 +1798,7 @@
 			continue;
 		}
 
-		info("%s: %s found", __FUNCTION__, usbvision_device_data[model].ModelString);
+		printk(KERN_INFO "%s: %s found\n", __FUNCTION__, usbvision_device_data[model].ModelString);
 		break;
 	}
 
@@ -1800,7 +1814,7 @@
 	endpoint = &interface->endpoint[1].desc;
 	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) {
 		err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum);
-		err("%s: Endpoint attribures %d", __FUNCTION__, endpoint->bmAttributes);
+		err("%s: Endpoint attributes %d", __FUNCTION__, endpoint->bmAttributes);
 		return -ENODEV;
 	}
 	if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
@@ -1827,6 +1841,28 @@
 
 	down(&usbvision->lock);
 
+	/* compute alternate max packet sizes */
+	uif = dev->actconfig->interface[0];
+
+	usbvision->num_alt=uif->num_altsetting;
+	PDEBUG(DBG_PROBE, "Alternate settings: %i",usbvision->num_alt);
+	usbvision->alt_max_pkt_size = kmalloc(32*
+					      usbvision->num_alt,GFP_KERNEL);
+	if (usbvision->alt_max_pkt_size == NULL) {
+		err("usbvision: out of memory!\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < usbvision->num_alt ; i++) {
+		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
+				      wMaxPacketSize);
+		usbvision->alt_max_pkt_size[i] =
+			(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+		PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i",i,
+		       usbvision->alt_max_pkt_size[i]);
+	}
+
+
 	usbvision->nr = usbvision_nr++;
 
 	usbvision->have_tuner = usbvision_device_data[model].Tuner;
@@ -1839,8 +1875,7 @@
 	usbvision->DevModel = model;
 	usbvision->remove_pending = 0;
 	usbvision->iface = ifnum;
-	usbvision->ifaceAltInactive = 0;
-	usbvision->ifaceAltActive = 1;
+	usbvision->ifaceAlt = 0;
 	usbvision->video_endp = endpoint->bEndpointAddress;
 	usbvision->isocPacketSize = 0;
 	usbvision->usb_bandwidth = 0;
@@ -1896,7 +1931,7 @@
 	up(&usbvision->lock);
 
 	if (usbvision->user) {
-		info("%s: In use, disconnect pending", __FUNCTION__);
+		printk(KERN_INFO "%s: In use, disconnect pending\n", __FUNCTION__);
 		wake_up_interruptible(&usbvision->wait_frame);
 		wake_up_interruptible(&usbvision->wait_stream);
 	}
@@ -2062,7 +2097,7 @@
 	errCode = usb_register(&usbvision_driver);
 
 	if (errCode == 0) {
-		info(DRIVER_DESC " : " USBVISION_VERSION_STRING);
+		printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n");
 		PDEBUG(DBG_PROBE, "success");
 	}
 	return errCode;
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
index e2bcaba..ad6afd3 100644
--- a/drivers/media/video/usbvision/usbvision.h
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -33,6 +33,7 @@
 
 #include <linux/list.h>
 #include <linux/usb.h>
+#include <linux/i2c.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include <linux/videodev2.h>
@@ -396,8 +397,11 @@
 
 	/* Device structure */
 	struct usb_device *dev;
+	/* usb transfer */
+	int num_alt;		/* Number of alternative settings */
+	unsigned int *alt_max_pkt_size;	/* array of wMaxPacketSize */
 	unsigned char iface;						/* Video interface number */
-	unsigned char ifaceAltActive, ifaceAltInactive;			/* Alt settings */
+	unsigned char ifaceAlt;			/* Alt settings */
 	unsigned char Vin_Reg2_Preset;
 	struct semaphore lock;
 	struct timer_list powerOffTimer;
@@ -421,6 +425,7 @@
 	wait_queue_head_t wait_stream;					/* Processes waiting */
 	struct usbvision_frame *curFrame;				// pointer to current frame, set by usbvision_find_header
 	struct usbvision_frame frame[USBVISION_NUMFRAMES];		// frame buffer
+	int num_frames;							// number of frames allocated
 	struct usbvision_sbuf sbuf[USBVISION_NUMSBUF];			// S buffering
 	volatile int remove_pending;					/* If set then about to exit */
 
@@ -486,12 +491,11 @@
 void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg);
 
 /* defined in usbvision-core.c                                      */
-void usbvision_rvfree(void *mem, unsigned long size);
 int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg);
 int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
 			unsigned char value);
 
-int usbvision_frames_alloc(struct usb_usbvision *usbvision);
+int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames);
 void usbvision_frames_free(struct usb_usbvision *usbvision);
 int usbvision_scratch_alloc(struct usb_usbvision *usbvision);
 void usbvision_scratch_free(struct usb_usbvision *usbvision);
@@ -502,6 +506,7 @@
 int usbvision_init_isoc(struct usb_usbvision *usbvision);
 int usbvision_restart_isoc(struct usb_usbvision *usbvision);
 void usbvision_stop_isoc(struct usb_usbvision *usbvision);
+int usbvision_set_alternate(struct usb_usbvision *dev);
 
 int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel);
 int usbvision_audio_off(struct usb_usbvision *usbvision);
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 8a13e59..d2c1ae0 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -11,7 +11,7 @@
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
  *
- * Author:	Bill Dirks <bdirks@pacbell.net>
+ * Author:	Bill Dirks <bill@thedirks.org>
  *		et al.
  *
  */
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index b87d571..ddfd80c 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -12,7 +12,7 @@
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
  *
- * Author:	Bill Dirks <bdirks@pacbell.net>
+ * Author:	Bill Dirks <bill@thedirks.org>
  *		based on code by Alan Cox, <alan@cymru.net>
  *
  */
@@ -47,7 +47,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/string.h>
@@ -272,11 +271,6 @@
 	[V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "slicec-vbi-out",
 };
 
-static char *v4l2_memory_names[] = {
-	[V4L2_MEMORY_MMAP]    = "mmap",
-	[V4L2_MEMORY_USERPTR] = "userptr",
-	[V4L2_MEMORY_OVERLAY] = "overlay",
-};
 
 #define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown"
 
@@ -401,9 +395,10 @@
 	[_IOC_NR(TUNER_SET_STANDBY)]           = "TUNER_SET_STANDBY",
 	[_IOC_NR(TDA9887_SET_CONFIG)]          = "TDA9887_SET_CONFIG",
 
+	[_IOC_NR(VIDIOC_DBG_S_REGISTER)]       = "VIDIOC_DBG_S_REGISTER",
+	[_IOC_NR(VIDIOC_DBG_G_REGISTER)]       = "VIDIOC_DBG_G_REGISTER",
+
 	[_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",
 	[_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
 	[_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)]  = "VIDIOC_INT_DECODE_VBI_LINE",
@@ -420,14 +415,6 @@
 };
 #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
 
-static void v4l_print_pix_fmt (char *s, struct v4l2_pix_format *fmt)
-{
-	printk ("%s: width=%d, height=%d, format=%d, field=%s, "
-		"bytesperline=%d sizeimage=%d, colorspace=%d\n", s,
-		fmt->width,fmt->height,fmt->pixelformat,
-		prt_names(fmt->field,v4l2_field_names),
-		fmt->bytesperline,fmt->sizeimage,fmt->colorspace);
-};
 
 /* Common ioctl debug function. This function can be used by
    external ioctl messages as well as internal V4L ioctl */
@@ -467,576 +454,6 @@
 	}
 }
 
-/* Common ioctl debug function. This function can be used by
-   external ioctl messages as well as internal V4L ioctl and its
-   arguments */
-void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
-{
-	printk(s);
-	printk(": ");
-	v4l_printk_ioctl(cmd);
-	switch (cmd) {
-	case VIDIOC_INT_G_CHIP_IDENT:
-	{
-		enum v4l2_chip_ident  *p=arg;
-		printk ("%s: chip ident=%d\n", s, *p);
-		break;
-	}
-	case VIDIOC_G_PRIORITY:
-	case VIDIOC_S_PRIORITY:
-	{
-		enum v4l2_priority *p=arg;
-		printk ("%s: priority=%d\n", s, *p);
-		break;
-	}
-	case VIDIOC_INT_S_TUNER_MODE:
-	{
-		enum v4l2_tuner_type *p=arg;
-		printk ("%s: tuner type=%d\n", s, *p);
-		break;
-	}
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case DECODER_SET_VBI_BYPASS:
-	case DECODER_ENABLE_OUTPUT:
-	case DECODER_GET_STATUS:
-	case DECODER_SET_OUTPUT:
-	case DECODER_SET_INPUT:
-	case DECODER_SET_GPIO:
-	case DECODER_SET_NORM:
-	case VIDIOCCAPTURE:
-	case VIDIOCSYNC:
-	case VIDIOCSWRITEMODE:
-#endif
-	case TUNER_SET_TYPE_ADDR:
-	case TUNER_SET_STANDBY:
-	case TDA9887_SET_CONFIG:
-#ifdef __OLD_VIDIOC_
-	case VIDIOC_OVERLAY_OLD:
-#endif
-	case VIDIOC_STREAMOFF:
-	case VIDIOC_G_OUTPUT:
-	case VIDIOC_S_OUTPUT:
-	case VIDIOC_STREAMON:
-	case VIDIOC_G_INPUT:
-	case VIDIOC_OVERLAY:
-	case VIDIOC_S_INPUT:
-	{
-		int *p=arg;
-		printk ("%s: value=%d\n", s, *p);
-		break;
-	}
-	case VIDIOC_G_AUDIO:
-	case VIDIOC_S_AUDIO:
-	case VIDIOC_ENUMAUDIO:
-#ifdef __OLD_VIDIOC_
-	case VIDIOC_G_AUDIO_OLD:
-#endif
-	{
-		struct v4l2_audio *p=arg;
-
-		printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n",
-			s,p->index, p->name,p->capability, p->mode);
-		break;
-	}
-	case VIDIOC_G_AUDOUT:
-	case VIDIOC_S_AUDOUT:
-	case VIDIOC_ENUMAUDOUT:
-#ifdef __OLD_VIDIOC_
-	case VIDIOC_G_AUDOUT_OLD:
-#endif
-	{
-		struct v4l2_audioout *p=arg;
-		printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", s,
-				p->index, p->name, p->capability,p->mode);
-		break;
-	}
-	case VIDIOC_QBUF:
-	case VIDIOC_DQBUF:
-	case VIDIOC_QUERYBUF:
-	{
-		struct v4l2_buffer *p=arg;
-		struct v4l2_timecode *tc=&p->timecode;
-		printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, "
-			"bytesused=%d, flags=0x%08x, "
-			"field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n",
-				s,
-				(p->timestamp.tv_sec/3600),
-				(int)(p->timestamp.tv_sec/60)%60,
-				(int)(p->timestamp.tv_sec%60),
-				p->timestamp.tv_usec,
-				p->index,
-				prt_names(p->type,v4l2_type_names),
-				p->bytesused,p->flags,
-				p->field,p->sequence,
-				prt_names(p->memory,v4l2_memory_names),
-				p->m.userptr);
-		printk ("%s: timecode= %02d:%02d:%02d type=%d, "
-			"flags=0x%08x, frames=%d, userbits=0x%08x\n",
-				s,tc->hours,tc->minutes,tc->seconds,
-				tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits);
-		break;
-	}
-	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability *p=arg;
-		printk ("%s: driver=%s, card=%s, bus=%s, version=0x%08x, "
-			"capabilities=0x%08x\n", s,
-				p->driver,p->card,p->bus_info,
-				p->version,
-				p->capabilities);
-		break;
-	}
-	case VIDIOC_G_CTRL:
-	case VIDIOC_S_CTRL:
-#ifdef __OLD_VIDIOC_
-	case VIDIOC_S_CTRL_OLD:
-#endif
-	{
-		struct v4l2_control *p=arg;
-		printk ("%s: id=%d, value=%d\n", s, p->id, p->value);
-		break;
-	}
-	case VIDIOC_G_EXT_CTRLS:
-	case VIDIOC_S_EXT_CTRLS:
-	case VIDIOC_TRY_EXT_CTRLS:
-	{
-		struct v4l2_ext_controls *p = arg;
-		int i;
-
-		printk("%s: ctrl_class=%d, count=%d\n", s, p->ctrl_class, p->count);
-		for (i = 0; i < p->count; i++) {
-			struct v4l2_ext_control *c = &p->controls[i];
-			if (cmd == VIDIOC_G_EXT_CTRLS)
-				printk("%s: id=%d\n", s, c->id);
-			else
-				printk("%s: id=%d, value=%d\n", s, c->id, c->value);
-		}
-		break;
-	}
-	case VIDIOC_G_CROP:
-	case VIDIOC_S_CROP:
-	{
-		struct v4l2_crop *p=arg;
-		/*FIXME: Should also show rect structs */
-		printk ("%s: type=%d\n", s, p->type);
-		break;
-	}
-	case VIDIOC_CROPCAP:
-#ifdef __OLD_VIDIOC_
-	case VIDIOC_CROPCAP_OLD:
-#endif
-	{
-		struct v4l2_cropcap *p=arg;
-		/*FIXME: Should also show rect structs */
-		printk ("%s: type=%d\n", s, p->type);
-		break;
-	}
-	case VIDIOC_INT_DECODE_VBI_LINE:
-	{
-		struct v4l2_decode_vbi_line *p=arg;
-		printk ("%s: is_second_field=%d, ptr=0x%08lx, line=%d, "
-			"type=%d\n", s,
-				p->is_second_field,(unsigned long)p->p,p->line,p->type);
-		break;
-	}
-	case VIDIOC_ENUM_FMT:
-	{
-		struct v4l2_fmtdesc *p=arg;
-		printk ("%s: index=%d, type=%d, flags=%d, description=%s,"
-			" pixelformat=%d\n", s,
-				p->index, p->type, p->flags,p->description,
-				p->pixelformat);
-
-		break;
-	}
-	case VIDIOC_G_FMT:
-	case VIDIOC_S_FMT:
-	case VIDIOC_TRY_FMT:
-	{
-		struct v4l2_format *p=arg;
-		printk ("%s: type=%s\n", s,
-				prt_names(p->type,v4l2_type_names));
-		switch (p->type) {
-		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-			v4l_print_pix_fmt (s, &p->fmt.pix);
-			break;
-		default:
-			break;
-		}
-	}
-	case VIDIOC_G_FBUF:
-	case VIDIOC_S_FBUF:
-	{
-		struct v4l2_framebuffer *p=arg;
-		printk ("%s: capability=%d, flags=%d, base=0x%08lx\n", s,
-				p->capability,p->flags, (unsigned long)p->base);
-		v4l_print_pix_fmt (s, &p->fmt);
-		break;
-	}
-	case VIDIOC_G_FREQUENCY:
-	case VIDIOC_S_FREQUENCY:
-	{
-		struct v4l2_frequency *p=arg;
-		printk ("%s: tuner=%d, type=%d, frequency=%d\n", s,
-				p->tuner,p->type,p->frequency);
-		break;
-	}
-	case VIDIOC_ENUMINPUT:
-	{
-		struct v4l2_input *p=arg;
-		printk ("%s: index=%d, name=%s, type=%d, audioset=%d, "
-			"tuner=%d, std=%Ld, status=%d\n", s,
-				p->index,p->name,p->type,p->audioset,
-				p->tuner,
-				(unsigned long long)p->std,
-				p->status);
-		break;
-	}
-	case VIDIOC_G_JPEGCOMP:
-	case VIDIOC_S_JPEGCOMP:
-	{
-		struct v4l2_jpegcompression *p=arg;
-		printk ("%s: quality=%d, APPn=%d, APP_len=%d, COM_len=%d,"
-			" jpeg_markers=%d\n", s,
-				p->quality,p->APPn,p->APP_len,
-				p->COM_len,p->jpeg_markers);
-		break;
-	}
-	case VIDIOC_G_MODULATOR:
-	case VIDIOC_S_MODULATOR:
-	{
-		struct v4l2_modulator *p=arg;
-		printk ("%s: index=%d, name=%s, capability=%d, rangelow=%d,"
-			" rangehigh=%d, txsubchans=%d\n", s,
-				p->index, p->name,p->capability,p->rangelow,
-				p->rangehigh,p->txsubchans);
-		break;
-	}
-	case VIDIOC_G_MPEGCOMP:
-	case VIDIOC_S_MPEGCOMP:
-	{
-		struct v4l2_mpeg_compression *p=arg;
-		/*FIXME: Several fields not shown */
-		printk ("%s: ts_pid_pmt=%d, ts_pid_audio=%d, ts_pid_video=%d, "
-			"ts_pid_pcr=%d, ps_size=%d, au_sample_rate=%d, "
-			"au_pesid=%c, vi_frame_rate=%d, vi_frames_per_gop=%d, "
-			"vi_bframes_count=%d, vi_pesid=%c\n", s,
-				p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video,
-				p->ts_pid_pcr, p->ps_size, p->au_sample_rate,
-				p->au_pesid, p->vi_frame_rate,
-				p->vi_frames_per_gop, p->vi_bframes_count,
-				p->vi_pesid);
-		break;
-	}
-	case VIDIOC_ENUMOUTPUT:
-	{
-		struct v4l2_output *p=arg;
-		printk ("%s: index=%d, name=%s,type=%d, audioset=%d, "
-			"modulator=%d, std=%Ld\n",
-				s,p->index,p->name,p->type,p->audioset,
-				p->modulator,
-				(unsigned long long)p->std);
-		break;
-	}
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *p=arg;
-		printk ("%s: id=%d, type=%d, name=%s, min/max=%d/%d,"
-			" step=%d, default=%d, flags=0x%08x\n", s,
-				p->id,p->type,p->name,p->minimum,p->maximum,
-				p->step,p->default_value,p->flags);
-		break;
-	}
-	case VIDIOC_QUERYMENU:
-	{
-		struct v4l2_querymenu *p=arg;
-		printk ("%s: id=%d, index=%d, name=%s\n", s,
-				p->id,p->index,p->name);
-		break;
-	}
-	case VIDIOC_INT_G_REGISTER:
-	case VIDIOC_INT_S_REGISTER:
-	{
-		struct v4l2_register *p=arg;
-		printk ("%s: i2c_id=%d, reg=%lu, val=%d\n", s,
-				p->i2c_id,p->reg,p->val);
-
-		break;
-	}
-	case VIDIOC_REQBUFS:
-	{
-		struct v4l2_requestbuffers *p=arg;
-		printk ("%s: count=%d, type=%s, memory=%s\n", s,
-				p->count,
-				prt_names(p->type,v4l2_type_names),
-				prt_names(p->memory,v4l2_memory_names));
-		break;
-	}
-	case VIDIOC_INT_S_AUDIO_ROUTING:
-	case VIDIOC_INT_S_VIDEO_ROUTING:
-	case VIDIOC_INT_G_AUDIO_ROUTING:
-	case VIDIOC_INT_G_VIDEO_ROUTING:
-	{
-		struct v4l2_routing  *p=arg;
-		printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output);
-		break;
-	}
-	case VIDIOC_INT_S_CRYSTAL_FREQ:
-	{
-		struct v4l2_crystal_freq *p=arg;
-		printk ("%s: freq=%u, flags=0x%x\n", s, p->freq, p->flags);
-		break;
-	}
-	case VIDIOC_G_SLICED_VBI_CAP:
-	{
-		struct v4l2_sliced_vbi_cap *p=arg;
-		printk ("%s: service_set=%d\n", s,
-				p->service_set);
-		break;
-	}
-	case VIDIOC_INT_S_VBI_DATA:
-	case VIDIOC_INT_G_VBI_DATA:
-	{
-		struct v4l2_sliced_vbi_data  *p=arg;
-		printk ("%s: id=%d, field=%d, line=%d\n", s,
-				p->id, p->field, p->line);
-		break;
-	}
-	case VIDIOC_ENUMSTD:
-	{
-		struct v4l2_standard *p=arg;
-		printk ("%s: index=%d, id=%Ld, name=%s, fps=%d/%d, "
-			"framelines=%d\n", s, p->index,
-				(unsigned long long)p->id, p->name,
-				p->frameperiod.numerator,
-				p->frameperiod.denominator,
-				p->framelines);
-
-		break;
-	}
-	case VIDIOC_G_PARM:
-	case VIDIOC_S_PARM:
-#ifdef __OLD_VIDIOC_
-	case VIDIOC_S_PARM_OLD:
-#endif
-	{
-		struct v4l2_streamparm *p=arg;
-		printk ("%s: type=%d\n", s, p->type);
-
-		break;
-	}
-	case VIDIOC_G_TUNER:
-	case VIDIOC_S_TUNER:
-	{
-		struct v4l2_tuner *p=arg;
-		printk ("%s: index=%d, name=%s, type=%d, capability=%d, "
-			"rangelow=%d, rangehigh=%d, signal=%d, afc=%d, "
-			"rxsubchans=%d, audmode=%d\n", s,
-				p->index, p->name, p->type,
-				p->capability, p->rangelow,p->rangehigh,
-				p->rxsubchans, p->audmode, p->signal,
-				p->afc);
-		break;
-	}
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case VIDIOCGVBIFMT:
-	case VIDIOCSVBIFMT:
-	{
-		struct vbi_format *p=arg;
-		printk ("%s: sampling_rate=%d, samples_per_line=%d, "
-			"sample_format=%d, start=%d/%d, count=%d/%d, flags=%d\n", s,
-				p->sampling_rate,p->samples_per_line,
-				p->sample_format,p->start[0],p->start[1],
-				p->count[0],p->count[1],p->flags);
-		break;
-	}
-	case VIDIOCGAUDIO:
-	case VIDIOCSAUDIO:
-	{
-		struct video_audio *p=arg;
-		printk ("%s: audio=%d, volume=%d, bass=%d, treble=%d, "
-			"flags=%d, name=%s, mode=%d, balance=%d, step=%d\n",
-				s,p->audio,p->volume,p->bass, p->treble,
-				p->flags,p->name,p->mode,p->balance,p->step);
-		break;
-	}
-	case VIDIOCGFBUF:
-	case VIDIOCSFBUF:
-	{
-		struct video_buffer *p=arg;
-		printk ("%s: base=%08lx, height=%d, width=%d, depth=%d, "
-			"bytesperline=%d\n", s,
-				(unsigned long) p->base, p->height, p->width,
-				p->depth,p->bytesperline);
-		break;
-	}
-	case VIDIOCGCAP:
-	{
-		struct video_capability *p=arg;
-		printk ("%s: name=%s, type=%d, channels=%d, audios=%d, "
-			"maxwidth=%d, maxheight=%d, minwidth=%d, minheight=%d\n",
-				s,p->name,p->type,p->channels,p->audios,
-				p->maxwidth,p->maxheight,p->minwidth,
-				p->minheight);
-
-		break;
-	}
-	case VIDIOCGCAPTURE:
-	case VIDIOCSCAPTURE:
-	{
-		struct video_capture *p=arg;
-		printk ("%s: x=%d, y=%d, width=%d, height=%d, decimation=%d,"
-			" flags=%d\n", s,
-				p->x, p->y,p->width, p->height,
-				p->decimation,p->flags);
-		break;
-	}
-	case VIDIOCGCHAN:
-	case VIDIOCSCHAN:
-	{
-		struct video_channel *p=arg;
-		printk ("%s: channel=%d, name=%s, tuners=%d, flags=%d, "
-			"type=%d, norm=%d\n", s,
-				p->channel,p->name,p->tuners,
-				p->flags,p->type,p->norm);
-
-		break;
-	}
-	case VIDIOCSMICROCODE:
-	{
-		struct video_code *p=arg;
-		printk ("%s: loadwhat=%s, datasize=%d\n", s,
-				p->loadwhat,p->datasize);
-		break;
-	}
-	case DECODER_GET_CAPABILITIES:
-	{
-		struct video_decoder_capability *p=arg;
-		printk ("%s: flags=%d, inputs=%d, outputs=%d\n", s,
-				p->flags,p->inputs,p->outputs);
-		break;
-	}
-	case DECODER_INIT:
-	{
-		struct video_decoder_init *p=arg;
-		printk ("%s: len=%c\n", s, p->len);
-		break;
-	}
-	case VIDIOCGPLAYINFO:
-	{
-		struct video_info *p=arg;
-		printk ("%s: frame_count=%d, h_size=%d, v_size=%d, "
-			"smpte_timecode=%d, picture_type=%d, "
-			"temporal_reference=%d, user_data=%s\n", s,
-				p->frame_count, p->h_size,
-				p->v_size, p->smpte_timecode,
-				p->picture_type, p->temporal_reference,
-				p->user_data);
-		break;
-	}
-	case VIDIOCKEY:
-	{
-		struct video_key *p=arg;
-		printk ("%s: key=%s, flags=%d\n", s,
-				p->key, p->flags);
-		break;
-	}
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *p=arg;
-		printk ("%s: size=%d, frames=%d, offsets=0x%08lx\n", s,
-				p->size,
-				p->frames,
-				(unsigned long)p->offsets);
-		break;
-	}
-	case VIDIOCMCAPTURE:
-	{
-		struct video_mmap *p=arg;
-		printk ("%s: frame=%d, height=%d, width=%d, format=%d\n", s,
-				p->frame,
-				p->height, p->width,
-				p->format);
-		break;
-	}
-	case VIDIOCGPICT:
-	case VIDIOCSPICT:
-	case DECODER_SET_PICTURE:
-	{
-		struct video_picture *p=arg;
-
-		printk ("%s: brightness=%d, hue=%d, colour=%d, contrast=%d,"
-			" whiteness=%d, depth=%d, palette=%d\n", s,
-				p->brightness, p->hue, p->colour,
-				p->contrast, p->whiteness, p->depth,
-				p->palette);
-		break;
-	}
-	case VIDIOCSPLAYMODE:
-	{
-		struct video_play_mode *p=arg;
-		printk ("%s: mode=%d, p1=%d, p2=%d\n", s,
-				p->mode,p->p1,p->p2);
-		break;
-	}
-	case VIDIOCGTUNER:
-	case VIDIOCSTUNER:
-	{
-		struct video_tuner *p=arg;
-		printk ("%s: tuner=%d, name=%s, rangelow=%ld, rangehigh=%ld, "
-			"flags=%d, mode=%d, signal=%d\n", s,
-				p->tuner, p->name,p->rangelow, p->rangehigh,
-				p->flags,p->mode, p->signal);
-		break;
-	}
-	case VIDIOCGUNIT:
-	{
-		struct video_unit *p=arg;
-		printk ("%s: video=%d, vbi=%d, radio=%d, audio=%d, "
-			"teletext=%d\n", s,
-				p->video,p->vbi,p->radio,p->audio,p->teletext);
-		break;
-	}
-	case VIDIOCGWIN:
-	case VIDIOCSWIN:
-	{
-		struct video_window *p=arg;
-		printk ("%s: x=%d, y=%d, width=%d, height=%d, chromakey=%d,"
-			" flags=%d, clipcount=%d\n", s,
-				p->x, p->y,p->width, p->height,
-				p->chromakey,p->flags,
-				p->clipcount);
-		break;
-	}
-	case VIDIOCGFREQ:
-	case VIDIOCSFREQ:
-	{
-		unsigned long *p=arg;
-		printk ("%s: value=%lu\n", s, *p);
-		break;
-	}
-#endif
-	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
-	case VIDIOC_INT_I2S_CLOCK_FREQ:
-	case VIDIOC_INT_S_STANDBY:
-	case VIDIOC_INT_RESET:
-	{
-		u32 *p=arg;
-
-		printk ("%s: value=%d\n", s, *p);
-		break;
-	}
-	case VIDIOC_G_STD:
-	case VIDIOC_S_STD:
-	case VIDIOC_QUERYSTD:
-	{
-		v4l2_std_id *p=arg;
-
-		printk ("%s: value=%Lu\n", s, (unsigned long long)*p);
-		break;
-	}
-	}
-}
 
 /* ----------------------------------------------------------------- */
 
@@ -1545,7 +962,6 @@
 EXPORT_SYMBOL(v4l2_field_names);
 EXPORT_SYMBOL(v4l2_type_names);
 EXPORT_SYMBOL(v4l_printk_ioctl);
-EXPORT_SYMBOL(v4l_printk_ioctl_arg);
 
 EXPORT_SYMBOL(v4l2_ctrl_next);
 EXPORT_SYMBOL(v4l2_ctrl_check);
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index 6504a58..459786f 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -148,6 +148,8 @@
 	dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n",
 		data,size,dma->nr_pages);
 
+	dma->varea = (void *) data;
+
 	down_read(&current->mm->mmap_sem);
 	err = get_user_pages(current,current->mm,
 			     data & PAGE_MASK, dma->nr_pages,
@@ -285,6 +287,7 @@
 
 	vfree(dma->vmalloc);
 	dma->vmalloc = NULL;
+	dma->varea = NULL;
 
 	if (dma->bus_addr) {
 		dma->bus_addr = 0;
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 6a0e8ca..dc9b1ef 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/string.h>
@@ -1454,6 +1453,26 @@
 		ret=vfd->vidioc_log_status(file, fh);
 		break;
 	}
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	case VIDIOC_DBG_G_REGISTER:
+	{
+		struct v4l2_register *p=arg;
+		if (!capable(CAP_SYS_ADMIN))
+			ret=-EPERM;
+		else if (vfd->vidioc_g_register)
+			ret=vfd->vidioc_g_register(file, fh, p);
+		break;
+	}
+	case VIDIOC_DBG_S_REGISTER:
+	{
+		struct v4l2_register *p=arg;
+		if (!capable(CAP_SYS_ADMIN))
+			ret=-EPERM;
+		else if (vfd->vidioc_s_register)
+			ret=vfd->vidioc_s_register(file, fh, p);
+		break;
+	}
+#endif
 	} /* switch */
 
 	if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
@@ -1561,7 +1580,7 @@
 }
 
 
-static struct file_operations video_fops;
+static const struct file_operations video_fops;
 
 /**
  *	video_register_device - register video4linux devices
@@ -1709,7 +1728,7 @@
 /*
  * Video fs operations
  */
-static struct file_operations video_fops=
+static const struct file_operations video_fops=
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index a373c14..0c658b7 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -4390,7 +4390,7 @@
 // __initdata
 static int vino_init_stage = 0;
 
-static struct file_operations vino_fops = {
+static const struct file_operations vino_fops = {
 	.owner		= THIS_MODULE,
 	.open		= vino_open,
 	.release	= vino_close,
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index d4cf556..f7e1d19 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -145,7 +145,9 @@
 
 	struct vivi_fmt        *fmt;
 
+#ifdef CONFIG_VIVI_SCATTER
 	struct sg_to_addr      *to_addr;
+#endif
 };
 
 struct vivi_dmaqueue {
@@ -230,6 +232,7 @@
 #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
 #define TSTAMP_MIN_X 64
 
+#ifdef CONFIG_VIVI_SCATTER
 static void prep_to_addr(struct sg_to_addr to_addr[],
 			 struct videobuf_buffer *vb)
 {
@@ -262,14 +265,24 @@
 
 	return (p1);
 }
+#endif
 
+#ifdef CONFIG_VIVI_SCATTER
 static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
 		     int hmax, int line, char *timestr)
+#else
+static void gen_line(char *basep,int inipos,int wmax,
+		     int hmax, int line, char *timestr)
+#endif
 {
-	int  w,i,j,pos=inipos,pgpos,oldpg,y;
-	char *p,*s,*basep;
-	struct page *pg;
+	int  w,i,j,pos=inipos,y;
+	char *p,*s;
 	u8   chr,r,g,b,color;
+#ifdef CONFIG_VIVI_SCATTER
+	int pgpos,oldpg;
+	char *basep;
+	struct page *pg;
+
 	unsigned long flags;
 	spinlock_t spinlock;
 
@@ -280,6 +293,7 @@
 	pg=pfn_to_page(sg_dma_address(to_addr[oldpg].sg) >> PAGE_SHIFT);
 	spin_lock_irqsave(&spinlock,flags);
 	basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset;
+#endif
 
 	/* We will just duplicate the second pixel at the packet */
 	wmax/=2;
@@ -291,6 +305,7 @@
 		b=bars[w*7/wmax][2];
 
 		for (color=0;color<4;color++) {
+#ifdef CONFIG_VIVI_SCATTER
 			pgpos=get_addr_pos(pos,pages,to_addr);
 			if (pgpos!=oldpg) {
 				pg=pfn_to_page(sg_dma_address(to_addr[pgpos].sg) >> PAGE_SHIFT);
@@ -299,6 +314,9 @@
 				oldpg=pgpos;
 			}
 			p=basep+pos-to_addr[pgpos].pos;
+#else
+			p=basep+pos;
+#endif
 
 			switch (color) {
 				case 0:
@@ -343,6 +361,7 @@
 
 				pos=inipos+j*2;
 				for (color=0;color<4;color++) {
+#ifdef CONFIG_VIVI_SCATTER
 					pgpos=get_addr_pos(pos,pages,to_addr);
 					if (pgpos!=oldpg) {
 						pg=pfn_to_page(sg_dma_address(
@@ -356,6 +375,9 @@
 						oldpg=pgpos;
 					}
 					p=basep+pos-to_addr[pgpos].pos;
+#else
+					p=basep+pos;
+#endif
 
 					y=TO_Y(r,g,b);
 
@@ -380,19 +402,27 @@
 
 
 end:
+#ifdef CONFIG_VIVI_SCATTER
 	kunmap_atomic(basep, KM_BOUNCE_READ);
 	spin_unlock_irqrestore(&spinlock,flags);
-
+#else
+	return;
+#endif
 }
 static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
 {
 	int h,pos=0;
 	int hmax  = buf->vb.height;
 	int wmax  = buf->vb.width;
-	struct videobuf_buffer *vb=&buf->vb;
-	struct sg_to_addr *to_addr=buf->to_addr;
 	struct timeval ts;
+#ifdef CONFIG_VIVI_SCATTER
+	struct sg_to_addr *to_addr=buf->to_addr;
+	struct videobuf_buffer *vb=&buf->vb;
+#else
+	char *tmpbuf;
+#endif
 
+#ifdef CONFIG_VIVI_SCATTER
 	/* Test if DMA mapping is ready */
 	if (!sg_dma_address(&vb->dma.sglist[0]))
 		return;
@@ -401,9 +431,28 @@
 
 	/* Check if there is enough memory */
 	BUG_ON(buf->vb.dma.nr_pages << PAGE_SHIFT < (buf->vb.width*buf->vb.height)*2);
+#else
+	if (buf->vb.dma.varea) {
+		tmpbuf=kmalloc (wmax*2, GFP_KERNEL);
+	} else {
+		tmpbuf=buf->vb.dma.vmalloc;
+	}
+
+#endif
 
 	for (h=0;h<hmax;h++) {
+#ifdef CONFIG_VIVI_SCATTER
 		gen_line(to_addr,pos,vb->dma.nr_pages,wmax,hmax,h,dev->timestr);
+#else
+		if (buf->vb.dma.varea) {
+			gen_line(tmpbuf,0,wmax,hmax,h,dev->timestr);
+			/* FIXME: replacing to __copy_to_user */
+			if (copy_to_user(buf->vb.dma.varea+pos,tmpbuf,wmax*2)!=0)
+				dprintk(2,"vivifill copy_to_user failed.\n");
+		} else {
+			gen_line(tmpbuf,pos,wmax,hmax,h,dev->timestr);
+		}
+#endif
 		pos += wmax*2;
 	}
 
@@ -429,7 +478,7 @@
 			dev->h,dev->m,dev->s,(dev->us+500)/1000);
 
 	dprintk(2,"vivifill at %s: Buffer 0x%08lx size= %d\n",dev->timestr,
-			(unsigned long)buf->vb.dma.vmalloc,pos);
+			(unsigned long)buf->vb.dma.varea,pos);
 
 	/* Advice that buffer was filled */
 	buf->vb.state = STATE_DONE;
@@ -471,11 +520,12 @@
 
 		/* Fill buffer */
 		vivi_fillbuff(dev,buf);
-	}
-	if (list_empty(&dma_q->active)) {
-		del_timer(&dma_q->timeout);
-	} else {
-		mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+
+		if (list_empty(&dma_q->active)) {
+			del_timer(&dma_q->timeout);
+		} else {
+			mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+		}
 	}
 	if (bc != 1)
 		dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
@@ -522,6 +572,8 @@
 
 	dprintk(1,"thread started\n");
 
+	mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+
 	for (;;) {
 		vivi_sleep(dma_q);
 
@@ -538,7 +590,6 @@
 	dma_q->ini_jiffies=jiffies;
 
 	dprintk(1,"%s\n",__FUNCTION__);
-	init_waitqueue_head(&dma_q->wq);
 
 	dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi");
 
@@ -546,6 +597,9 @@
 		printk(KERN_ERR "vivi: kernel_thread() failed\n");
 		return PTR_ERR(dma_q->kthread);
 	}
+	/* Wakes thread */
+	wake_up_interruptible(&dma_q->wq);
+
 	dprintk(1,"returning from %s\n",__FUNCTION__);
 	return 0;
 }
@@ -663,9 +717,11 @@
 	if (in_interrupt())
 		BUG();
 
+#ifdef CONFIG_VIVI_SCATTER
 	/*FIXME: Maybe a spinlock is required here */
 	kfree(buf->to_addr);
 	buf->to_addr=NULL;
+#endif
 
 	videobuf_waiton(&buf->vb,0,0);
 	videobuf_dma_unmap(vq, &buf->vb.dma);
@@ -711,11 +767,12 @@
 
 	buf->vb.state = STATE_PREPARED;
 
+#ifdef CONFIG_VIVI_SCATTER
 	if (NULL == (buf->to_addr = kmalloc(sizeof(*buf->to_addr) * vb->dma.nr_pages,GFP_KERNEL))) {
 		rc=-ENOMEM;
 		goto fail;
 	}
-
+#endif
 	return 0;
 
 fail:
@@ -780,6 +837,7 @@
 	free_buffer(vq,buf);
 }
 
+#ifdef CONFIG_VIVI_SCATTER
 static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents,
 		       int direction)
 {
@@ -812,6 +870,7 @@
 //	flush_write_buffers();
 	return 0;
 }
+#endif
 
 static struct videobuf_queue_ops vivi_video_qops = {
 	.buf_setup      = buffer_setup,
@@ -820,9 +879,9 @@
 	.buf_release    = buffer_release,
 
 	/* Non-pci handling routines */
-	.vb_map_sg      = vivi_map_sg,
-	.vb_dma_sync_sg = vivi_dma_sync_sg,
-	.vb_unmap_sg    = vivi_unmap_sg,
+//	.vb_map_sg      = vivi_map_sg,
+//	.vb_dma_sync_sg = vivi_dma_sync_sg,
+//	.vb_unmap_sg    = vivi_unmap_sg,
 };
 
 /* ------------------------------------------------------------------
@@ -1200,11 +1259,19 @@
 	sprintf(dev->timestr,"%02d:%02d:%02d:%03d",
 			dev->h,dev->m,dev->s,(dev->us+500)/1000);
 
+#ifdef CONFIG_VIVI_SCATTER
+	videobuf_queue_init(&fh->vb_vidq,VIDEOBUF_DMA_SCATTER, &vivi_video_qops,
+			NULL, NULL,
+			fh->type,
+			V4L2_FIELD_INTERLACED,
+			sizeof(struct vivi_buffer),fh);
+#else
 	videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops,
 			NULL, NULL,
 			fh->type,
 			V4L2_FIELD_INTERLACED,
 			sizeof(struct vivi_buffer),fh);
+#endif
 
 	return 0;
 }
@@ -1292,7 +1359,7 @@
 	return ret;
 }
 
-static struct file_operations vivi_fops = {
+static const struct file_operations vivi_fops = {
 	.owner		= THIS_MODULE,
 	.open           = vivi_open,
 	.release        = vivi_release,
@@ -1352,6 +1419,7 @@
 	/* init video dma queues */
 	INIT_LIST_HEAD(&dev->vidq.active);
 	INIT_LIST_HEAD(&dev->vidq.queued);
+	init_waitqueue_head(&dev->vidq.wq);
 
 	/* initialize locks */
 	init_MUTEX(&dev->lock);
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index 8d14f30..4736640 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -183,7 +183,7 @@
 static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
 			      size_t count, loff_t *ppos);
 
-static struct file_operations w9966_fops = {
+static const struct file_operations w9966_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 9f403af..8f31613 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -399,7 +399,7 @@
  ****************************************************************************/
 
 /* Video4linux interface */
-static struct file_operations w9968cf_fops;
+static const struct file_operations w9968cf_fops;
 static int w9968cf_open(struct inode*, struct file*);
 static int w9968cf_release(struct inode*, struct file*);
 static int w9968cf_mmap(struct file*, struct vm_area_struct*);
@@ -1573,6 +1573,7 @@
 
 	memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter));
 	strcpy(cam->i2c_adapter.name, "w9968cf");
+	cam->i2c_adapter.dev.parent = &cam->usbdev->dev;
 	i2c_set_adapdata(&cam->i2c_adapter, cam);
 
 	DBG(6, "Registering I2C adapter with kernel...")
@@ -3466,7 +3467,7 @@
 }
 
 
-static struct file_operations w9968cf_fops = {
+static const struct file_operations w9968cf_fops = {
 	.owner =   THIS_MODULE,
 	.open =    w9968cf_open,
 	.release = w9968cf_release,
diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h
index b9c93b8..710f12e 100644
--- a/drivers/media/video/zc0301/zc0301.h
+++ b/drivers/media/video/zc0301/zc0301.h
@@ -1,7 +1,7 @@
 /***************************************************************************
- * V4L2 driver for ZC0301 Image Processor and Control Chip                 *
+ * V4L2 driver for ZC0301[P] Image Processor and Control Chip              *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 52d0f75..f112055 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -1,7 +1,7 @@
 /***************************************************************************
  * Video4Linux2 driver for ZC0301[P] Image Processor and Control Chip      *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * Informations about the chip internals needed to enable the I2C protocol *
  * have been taken from the documentation of the ZC030x Video4Linux1       *
@@ -52,8 +52,8 @@
 #define ZC0301_MODULE_AUTHOR  "(C) 2006 Luca Risolia"
 #define ZC0301_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
 #define ZC0301_MODULE_LICENSE "GPL"
-#define ZC0301_MODULE_VERSION "1:1.05"
-#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 5)
+#define ZC0301_MODULE_VERSION "1:1.07"
+#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 7)
 
 /*****************************************************************************/
 
@@ -89,7 +89,7 @@
 		 "\ndetected camera."
 		 "\n 0 = do not force memory unmapping"
 		 "\n 1 = force memory unmapping (save memory)"
-		 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+		 "\nDefault value is "__MODULE_STRING(ZC0301_FORCE_MUNMAP)"."
 		 "\n");
 
 static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] =
@@ -136,7 +136,8 @@
 
 	cam->nbuffers = count;
 	while (cam->nbuffers > 0) {
-		if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+		if ((buff = vmalloc_32_user(cam->nbuffers *
+					    PAGE_ALIGN(imagesize))))
 			break;
 		cam->nbuffers--;
 	}
@@ -430,7 +431,8 @@
 	struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
 						     usb_ifnum_to_if(udev, 0),
 						     ZC0301_ALTERNATE_SETTING);
-	const unsigned int psz = altsetting->endpoint[0].desc.wMaxPacketSize;
+	const unsigned int psz = le16_to_cpu(altsetting->
+					     endpoint[0].desc.wMaxPacketSize);
 	struct urb* urb;
 	s8 i, j;
 	int err = 0;
@@ -489,7 +491,7 @@
 	return 0;
 
 free_urbs:
-	for (i = 0; i < ZC0301_URBS; i++)
+	for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++)
 		usb_free_urb(cam->urb[i]);
 
 free_buffers:
@@ -1288,6 +1290,35 @@
 
 
 static int
+zc0301_vidioc_enum_framesizes(struct zc0301_device* cam, void __user * arg)
+{
+	struct v4l2_frmsizeenum frmsize;
+
+	if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
+		return -EFAULT;
+
+	if (frmsize.index != 0 && frmsize.index != 1)
+		return -EINVAL;
+
+	if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG)
+		return -EINVAL;
+
+	frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE;
+
+	if (frmsize.index == 1) {
+		frmsize.discrete.width = cam->sensor.cropcap.defrect.width;
+		frmsize.discrete.height = cam->sensor.cropcap.defrect.height;
+	}
+	memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
+
+	if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int
 zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg)
 {
 	struct v4l2_fmtdesc fmtd;
@@ -1295,6 +1326,9 @@
 	if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
 		return -EFAULT;
 
+	if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
 	if (fmtd.index == 0) {
 		strcpy(fmtd.description, "JPEG");
 		fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
@@ -1795,6 +1829,9 @@
 	case VIDIOC_S_FMT:
 		return zc0301_vidioc_try_s_fmt(cam, cmd, arg);
 
+	case VIDIOC_ENUM_FRAMESIZES:
+		return zc0301_vidioc_enum_framesizes(cam, arg);
+
 	case VIDIOC_G_JPEGCOMP:
 		return zc0301_vidioc_g_jpegcomp(cam, arg);
 
@@ -1830,6 +1867,7 @@
 	case VIDIOC_QUERYSTD:
 	case VIDIOC_ENUMSTD:
 	case VIDIOC_QUERYMENU:
+	case VIDIOC_ENUM_FRAMEINTERVALS:
 		return -EINVAL;
 
 	default:
@@ -1871,11 +1909,12 @@
 }
 
 
-static struct file_operations zc0301_fops = {
+static const struct file_operations zc0301_fops = {
 	.owner =   THIS_MODULE,
 	.open =    zc0301_open,
 	.release = zc0301_release,
 	.ioctl =   zc0301_ioctl,
+	.compat_ioctl = v4l_compat_ioctl32,
 	.read =    zc0301_read,
 	.poll =    zc0301_poll,
 	.mmap =    zc0301_mmap,
@@ -1913,7 +1952,7 @@
 	mutex_init(&cam->dev_mutex);
 
 	DBG(2, "ZC0301[P] Image Processor and Control Chip detected "
-	       "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct);
+	       "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct);
 
 	for  (i = 0; zc0301_sensor_table[i]; i++) {
 		err = zc0301_sensor_table[i](cam);
diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c
index ecfd39a..3efb92a 100644
--- a/drivers/media/video/zc0301/zc0301_pas202bcb.c
+++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for PAS202BCB image sensor connected to the ZC0301[P] Image     *
+ * Plug-in for PAS202BCB image sensor connected to the ZC0301 Image        *
  * Processor and Control Chip                                              *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
  * driver maintained by Michel Xhaard <mxhaard@magic.fr>                   *
diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c
index ed8542e..5784b1d 100644
--- a/drivers/media/video/zc0301/zc0301_pb0330.c
+++ b/drivers/media/video/zc0301/zc0301_pb0330.c
@@ -1,8 +1,8 @@
 /***************************************************************************
- * Plug-in for PB-0330 image sensor connected to the ZC0301[P] Image       *
+ * Plug-in for PB-0330 image sensor connected to the ZC0301P Image         *
  * Processor and Control Chip                                              *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
  * driver maintained by Michel Xhaard <mxhaard@magic.fr>                   *
diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h
index 3daf049..44e82cf 100644
--- a/drivers/media/video/zc0301/zc0301_sensor.h
+++ b/drivers/media/video/zc0301/zc0301_sensor.h
@@ -1,8 +1,8 @@
 /***************************************************************************
- * API for image sensors connected to the ZC0301 Image Processor and       *
+ * API for image sensors connected to the ZC0301[P] Image Processor and    *
  * Control Chip                                                            *
  *                                                                         *
- * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
@@ -70,7 +70,7 @@
 	{ ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */            \
 	{ ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */            \
 	{ ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */           \
-	{ ZC0301_USB_DEVICE(0x0458, 0x700C, 0xff), }, /* TAS5130 */           \
+	{ ZC0301_USB_DEVICE(0x0458, 0x700c, 0xff), }, /* TAS5130 */           \
 	{ ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */           \
 	{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */            \
 	{ ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */           \
@@ -93,9 +93,9 @@
 
 /*****************************************************************************/
 
-#define ZC0301_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
-#define ZC0301_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE
-#define ZC0301_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1
+#define ZC0301_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10)
+#define ZC0301_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0)
+#define ZC0301_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1)
 
 struct zc0301_sensor {
 	char name[32];
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 4d1eb2f..73162a3 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -843,6 +843,7 @@
 		sizeof(I2C_NAME(&zr->i2c_adapter)) - 1);
 	i2c_set_adapdata(&zr->i2c_adapter, zr);
 	zr->i2c_adapter.algo_data = &zr->i2c_algo;
+	zr->i2c_adapter.dev.parent = &zr->pci_dev->dev;
 	return i2c_bit_add_bus(&zr->i2c_adapter);
 }
 
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index 862a984..0743237 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -562,7 +562,6 @@
 			jpg_fbuffer_free(file);
 			return -ENOBUFS;
 		}
-		memset((void *) mem, 0, PAGE_SIZE);
 		fh->jpg_buffers.buffer[i].frag_tab = (u32 *) mem;
 		fh->jpg_buffers.buffer[i].frag_tab_bus =
 		    virt_to_bus((void *) mem);
@@ -4680,7 +4679,7 @@
 	return 0;
 }
 
-static struct file_operations zoran_fops = {
+static const struct file_operations zoran_fops = {
 	.owner = THIS_MODULE,
 	.open = zoran_open,
 	.release = zoran_close,
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c
index c374c76..446ae8d 100644
--- a/drivers/media/video/zoran_procfs.c
+++ b/drivers/media/video/zoran_procfs.c
@@ -186,7 +186,7 @@
 	return count;
 }
 
-static struct file_operations zoran_operations = {
+static const struct file_operations zoran_operations = {
 	.open		= zoran_open,
 	.read		= seq_read,
 	.write		= zoran_write,
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index ea31d84..71037f9 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -66,7 +66,7 @@
 
 config FUSION_CTL
 	tristate "Fusion MPT misc device (ioctl) driver"
-	depends on FUSION_SPI || FUSION_FC
+	depends on FUSION_SPI || FUSION_FC || FUSION_SAS
 	---help---
 	  The Fusion MPT misc device driver provides specialized control
 	  of MPT adapters via system ioctl calls.  Use of ioctl calls to
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index 3416913..6003b46 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -8,6 +8,9 @@
 #EXTRA_CFLAGS += -DMPT_DEBUG_INIT
 #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
 #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
+#EXTRA_CFLAGS += -DMPT_DEBUG_DV
+#EXTRA_CFLAGS += -DMPT_DEBUG_TM
+#EXTRA_CFLAGS += -DMPT_DEBUG_REPLY
 
 #
 # driver/module specifics...
@@ -20,11 +23,7 @@
 #CFLAGS_mptbase.o += -DMPT_DEBUG_RESET
 #
 #  For mptscsih:
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM
 #CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY
 #
 #  For mptctl:
 #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index 81ad776..75223bf 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2005 LSI Logic Corporation.
+ *  Copyright (c) 2000-2006 LSI Logic Corporation.
  *
  *
  *           Name:  mpi.h
  *          Title:  MPI Message independent structures and definitions
  *  Creation Date:  July 27, 2000
  *
- *    mpi.h Version:  01.05.11
+ *    mpi.h Version:  01.05.12
  *
  *  Version History
  *  ---------------
@@ -77,6 +77,7 @@
  *  08-03-05  01.05.09  Bumped MPI_HEADER_VERSION_UNIT.
  *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
  *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
+ *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
  *  --------------------------------------------------------------------------
  */
 
@@ -107,7 +108,7 @@
 /* Note: The major versions of 0xe0 through 0xff are reserved */
 
 /* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT             (0x0D)
+#define MPI_HEADER_VERSION_UNIT             (0x0E)
 #define MPI_HEADER_VERSION_DEV              (0x00)
 #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
 #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index 47e13e3..0e4c8e7 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2005 LSI Logic Corporation.
+ *  Copyright (c) 2000-2006 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_cnfg.h
  *          Title:  MPI Config message, structures, and Pages
  *  Creation Date:  July 27, 2000
  *
- *    mpi_cnfg.h Version:  01.05.12
+ *    mpi_cnfg.h Version:  01.05.13
  *
  *  Version History
  *  ---------------
@@ -276,6 +276,23 @@
  *                      Added AdditionalControlFlags, MaxTargetPortConnectTime,
  *                      ReportDeviceMissingDelay, and IODeviceMissingDelay
  *                      fields to SAS IO Unit Page 1.
+ *  10-11-06  01.05.13  Added NumForceWWID field and ForceWWID array to
+ *                      Manufacturing Page 5.
+ *                      Added Manufacturing pages 8 through 10.
+ *                      Added defines for supported metadata size bits in
+ *                      CapabilitiesFlags field of IOC Page 6.
+ *                      Added defines for metadata size bits in VolumeSettings
+ *                      field of RAID Volume Page 0.
+ *                      Added SATA Link Reset settings, Enable SATA Asynchronous
+ *                      Notification bit, and HideNonZeroAttachedPhyIdentifiers
+ *                      bit to AdditionalControlFlags field of SAS IO Unit
+ *                      Page 1.
+ *                      Added defines for Enclosure Devices Unmapped and
+ *                      Device Limit Exceeded bits in Status field of SAS IO
+ *                      Unit Page 2.
+ *                      Added more AccessStatus values for SAS Device Page 0.
+ *                      Added bit for SATA Asynchronous Notification Support in
+ *                      Flags field of SAS Device Page 0.
  *  --------------------------------------------------------------------------
  */
 
@@ -654,17 +671,24 @@
 #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA                 (0x01)
 
 
+#ifndef MPI_MANPAGE5_NUM_FORCEWWID
+#define MPI_MANPAGE5_NUM_FORCEWWID      (1)
+#endif
+
 typedef struct _CONFIG_PAGE_MANUFACTURING_5
 {
     CONFIG_PAGE_HEADER              Header;             /* 00h */
     U64                             BaseWWID;           /* 04h */
     U8                              Flags;              /* 0Ch */
-    U8                              Reserved1;          /* 0Dh */
+    U8                              NumForceWWID;       /* 0Dh */
     U16                             Reserved2;          /* 0Eh */
+    U32                             Reserved3;          /* 10h */
+    U32                             Reserved4;          /* 14h */
+    U64                             ForceWWID[MPI_MANPAGE5_NUM_FORCEWWID]; /* 18h */
 } CONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5,
   ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t;
 
-#define MPI_MANUFACTURING5_PAGEVERSION                  (0x01)
+#define MPI_MANUFACTURING5_PAGEVERSION                  (0x02)
 
 /* defines for the Flags field */
 #define MPI_MANPAGE5_TWO_WWID_PER_PHY                   (0x01)
@@ -740,6 +764,36 @@
 #define MPI_MANPAGE7_FLAG_USE_SLOT_INFO                 (0x00000001)
 
 
+typedef struct _CONFIG_PAGE_MANUFACTURING_8
+{
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
+    U32                             ProductSpecificInfo;/* 04h */
+} CONFIG_PAGE_MANUFACTURING_8, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_8,
+  ManufacturingPage8_t, MPI_POINTER pManufacturingPage8_t;
+
+#define MPI_MANUFACTURING8_PAGEVERSION                  (0x00)
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_9
+{
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
+    U32                             ProductSpecificInfo;/* 04h */
+} CONFIG_PAGE_MANUFACTURING_9, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_9,
+  ManufacturingPage9_t, MPI_POINTER pManufacturingPage9_t;
+
+#define MPI_MANUFACTURING6_PAGEVERSION                  (0x00)
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_10
+{
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
+    U32                             ProductSpecificInfo;/* 04h */
+} CONFIG_PAGE_MANUFACTURING_10, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_10,
+  ManufacturingPage10_t, MPI_POINTER pManufacturingPage10_t;
+
+#define MPI_MANUFACTURING10_PAGEVERSION                 (0x00)
+
+
 /****************************************************************************
 *   IO Unit Config Pages
 ****************************************************************************/
@@ -1080,10 +1134,14 @@
 } CONFIG_PAGE_IOC_6, MPI_POINTER PTR_CONFIG_PAGE_IOC_6,
   IOCPage6_t, MPI_POINTER pIOCPage6_t;
 
-#define MPI_IOCPAGE6_PAGEVERSION                        (0x00)
+#define MPI_IOCPAGE6_PAGEVERSION                        (0x01)
 
 /* IOC Page 6 Capabilities Flags */
 
+#define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE       (0x00000006)
+#define MPI_IOCPAGE6_CAP_FLAGS_64MB_METADATA_SIZE       (0x00000000)
+#define MPI_IOCPAGE6_CAP_FLAGS_512MB_METADATA_SIZE      (0x00000002)
+
 #define MPI_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE         (0x00000001)
 
 
@@ -2160,6 +2218,11 @@
 #define MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE             (0x0004)
 #define MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC            (0x0008)
 #define MPI_RAIDVOL0_SETTING_FAST_DATA_SCRUBBING_0102   (0x0020) /* obsolete */
+
+#define MPI_RAIDVOL0_SETTING_MASK_METADATA_SIZE         (0x00C0)
+#define MPI_RAIDVOL0_SETTING_64MB_METADATA_SIZE         (0x0000)
+#define MPI_RAIDVOL0_SETTING_512MB_METADATA_SIZE        (0x0040)
+
 #define MPI_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX      (0x0010)
 #define MPI_RAIDVOL0_SETTING_USE_DEFAULTS               (0x8000)
 
@@ -2203,7 +2266,7 @@
 } CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
   RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t;
 
-#define MPI_RAIDVOLPAGE0_PAGEVERSION                    (0x06)
+#define MPI_RAIDVOLPAGE0_PAGEVERSION                    (0x07)
 
 /* values for RAID Volume Page 0 InactiveStatus field */
 #define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE               (0x00)
@@ -2518,7 +2581,7 @@
 } CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
   SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
 
-#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x06)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x07)
 
 /* values for SAS IO Unit Page 1 ControlFlags */
 #define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST            (0x8000)
@@ -2544,7 +2607,13 @@
 #define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION           (0x0001)
 
 /* values for SAS IO Unit Page 1 AdditionalControlFlags */
-#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE       (0x0001)
+#define MPI_SAS_IOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION    (0x0040)
+#define MPI_SAS_IOUNIT1_ACONTROL_HIDE_NONZERO_ATTACHED_PHY_IDENT    (0x0020)
+#define MPI_SAS_IOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET   (0x0010)
+#define MPI_SAS_IOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET  (0x0008)
+#define MPI_SAS_IOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET   (0x0004)
+#define MPI_SAS_IOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET     (0x0002)
+#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE               (0x0001)
 
 /* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
 #define MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK         (0x7F)
@@ -2585,9 +2654,11 @@
 } CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
   SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
 
-#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x05)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x06)
 
 /* values for SAS IO Unit Page 2 Status field */
+#define MPI_SAS_IOUNIT2_STATUS_DEVICE_LIMIT_EXCEEDED        (0x08)
+#define MPI_SAS_IOUNIT2_STATUS_ENCLOSURE_DEVICES_UNMAPPED   (0x04)
 #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
 #define MPI_SAS_IOUNIT2_STATUS_FULL_PERSISTENT_MAPPINGS     (0x01)
 
@@ -2739,24 +2810,38 @@
 } CONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0,
   SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t;
 
-#define MPI_SASDEVICE0_PAGEVERSION          (0x04)
+#define MPI_SASDEVICE0_PAGEVERSION          (0x05)
 
 /* values for SAS Device Page 0 AccessStatus field */
-#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS               (0x00)
-#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED        (0x01)
-#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED  (0x02)
+#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS                   (0x00)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED            (0x01)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED      (0x02)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT   (0x03)
+/* specific values for SATA Init failures */
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN                 (0x10)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT    (0x11)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_DIAG                    (0x12)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION          (0x13)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER             (0x14)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_PIO_SN                  (0x15)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN                 (0x16)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN                 (0x17)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION        (0x18)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE         (0x19)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_MAX                     (0x1F)
 
 /* values for SAS Device Page 0 Flags field */
-#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE          (0x0200)
-#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE        (0x0100)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED  (0x0080)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED      (0x0040)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED        (0x0020)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED        (0x0010)
-#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH      (0x0008)
-#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT        (0x0004)
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED             (0x0002)
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT            (0x0001)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY      (0x0400)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE              (0x0200)
+#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE            (0x0100)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED      (0x0080)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED          (0x0040)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED            (0x0020)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED            (0x0010)
+#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH          (0x0008)
+#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT            (0x0004)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED                 (0x0002)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT                (0x0001)
 
 /* see mpi_sas.h for values for SAS Device Page 0 DeviceInfo values */
 
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 582cfe7..d6b4c60 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -3,28 +3,28 @@
  MPI Header File Change History
  ==============================
 
- Copyright (c) 2000-2005 LSI Logic Corporation.
+ Copyright (c) 2000-2006 LSI Logic Corporation.
 
  ---------------------------------------
- Header Set Release Version:    01.05.13
- Header Set Release Date:       03-27-06
+ Header Set Release Version:    01.05.14
+ Header Set Release Date:       10-11-06
  ---------------------------------------
 
  Filename               Current version     Prior version
  ----------             ---------------     -------------
- mpi.h                  01.05.11            01.05.10
- mpi_ioc.h              01.05.11            01.05.10
- mpi_cnfg.h             01.05.12            01.05.11
- mpi_init.h             01.05.07            01.05.06
- mpi_targ.h             01.05.06            01.05.05
+ mpi.h                  01.05.12            01.05.11
+ mpi_ioc.h              01.05.12            01.05.11
+ mpi_cnfg.h             01.05.13            01.05.12
+ mpi_init.h             01.05.08            01.05.07
+ mpi_targ.h             01.05.06            01.05.06
  mpi_fc.h               01.05.01            01.05.01
  mpi_lan.h              01.05.01            01.05.01
  mpi_raid.h             01.05.02            01.05.02
  mpi_tool.h             01.05.03            01.05.03
  mpi_inb.h              01.05.01            01.05.01
- mpi_sas.h              01.05.03            01.05.02
+ mpi_sas.h              01.05.04            01.05.03
  mpi_type.h             01.05.02            01.05.02
- mpi_history.txt        01.05.13            01.05.12
+ mpi_history.txt        01.05.14            01.05.13
 
 
  *  Date      Version   Description
@@ -94,6 +94,7 @@
  *  08-03-05  01.05.09  Bumped MPI_HEADER_VERSION_UNIT.
  *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
  *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
+ *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
  *  --------------------------------------------------------------------------
 
 mpi_ioc.h
@@ -182,6 +183,14 @@
  *                      Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event
  *                      data structure.
  *                      Added MPI_EXT_IMAGE_TYPE_INITIALIZATION.
+ *  10-11-06  01.05.12  Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
+ *                      Added MaxInitiators field to PortFacts reply.
+ *                      Added SAS Device Status Change ReasonCode for
+ *                      asynchronous notificaiton.
+ *                      Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
+ *                      data structure.
+ *                      Added new ImageType values for FWDownload and FWUpload
+ *                      requests.
  *  --------------------------------------------------------------------------
 
 mpi_cnfg.h
@@ -447,6 +456,23 @@
  *                      Added AdditionalControlFlags, MaxTargetPortConnectTime,
  *                      ReportDeviceMissingDelay, and IODeviceMissingDelay
  *                      fields to SAS IO Unit Page 1.
+ *  10-11-06  01.05.13  Added NumForceWWID field and ForceWWID array to
+ *                      Manufacturing Page 5.
+ *                      Added Manufacturing pages 8 through 10.
+ *                      Added defines for supported metadata size bits in
+ *                      CapabilitiesFlags field of IOC Page 6.
+ *                      Added defines for metadata size bits in VolumeSettings
+ *                      field of RAID Volume Page 0.
+ *                      Added SATA Link Reset settings, Enable SATA Asynchronous
+ *                      Notification bit, and HideNonZeroAttachedPhyIdentifiers
+ *                      bit to AdditionalControlFlags field of SAS IO Unit
+ *                      Page 1.
+ *                      Added defines for Enclosure Devices Unmapped and
+ *                      Device Limit Exceeded bits in Status field of SAS IO
+ *                      Unit Page 2.
+ *                      Added more AccessStatus values for SAS Device Page 0.
+ *                      Added bit for SATA Asynchronous Notification Support in
+ *                      Flags field of SAS Device Page 0.
  *  --------------------------------------------------------------------------
 
 mpi_init.h
@@ -490,6 +516,7 @@
  *  08-03-05  01.05.06  Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
  *                      unique in the first 32 characters.
  *  03-27-06  01.05.07  Added Task Management type of Clear ACA.
+ *  10-11-06  01.05.08  Shortened define for Task Management type of Clear ACA.
  *  --------------------------------------------------------------------------
 
 mpi_targ.h
@@ -638,6 +665,8 @@
  *                      and Remove Device operations to SAS IO Unit Control.
  *                      Added DevHandle field to SAS IO Unit Control request and
  *                      reply.
+ *  10-11-06  01.05.04  Fixed the name of a define for Operation field of SAS IO
+ *                      Unit Control request.
  *  --------------------------------------------------------------------------
 
 mpi_type.h
@@ -653,20 +682,20 @@
 
 mpi_history.txt         Parts list history
 
-Filename    01.05.13  01.05.12  01.05.11  01.05.10  01.05.09
-----------  --------  --------  --------  --------  --------
-mpi.h       01.05.11  01.05.10  01.05.09  01.05.08  01.05.07
-mpi_ioc.h   01.05.11  01.05.10  01.05.09  01.05.09  01.05.08
-mpi_cnfg.h  01.05.12  01.05.11  01.05.10  01.05.09  01.05.08
-mpi_init.h  01.05.07  01.05.06  01.05.06  01.05.05  01.05.04
-mpi_targ.h  01.05.06  01.05.05  01.05.05  01.05.05  01.05.04
-mpi_fc.h    01.05.01  01.05.01  01.05.01  01.05.01  01.05.01
-mpi_lan.h   01.05.01  01.05.01  01.05.01  01.05.01  01.05.01
-mpi_raid.h  01.05.02  01.05.02  01.05.02  01.05.02  01.05.02
-mpi_tool.h  01.05.03  01.05.03  01.05.03  01.05.03  01.05.03
-mpi_inb.h   01.05.01  01.05.01  01.05.01  01.05.01  01.05.01
-mpi_sas.h   01.05.03  01.05.02  01.05.01  01.05.01  01.05.01
-mpi_type.h  01.05.02  01.05.02  01.05.01  01.05.01  01.05.01
+Filename    01.05.13   01.05.13   01.05.12   01.05.11   01.05.10   01.05.09
+----------  --------   --------   --------   --------   --------   --------
+mpi.h       01.05.12   01.05.11   01.05.10   01.05.09   01.05.08   01.05.07
+mpi_ioc.h   01.05.12   01.05.11   01.05.10   01.05.09   01.05.09   01.05.08
+mpi_cnfg.h  01.05.13   01.05.12   01.05.11   01.05.10   01.05.09   01.05.08
+mpi_init.h  01.05.08   01.05.07   01.05.06   01.05.06   01.05.05   01.05.04
+mpi_targ.h  01.05.06   01.05.06   01.05.05   01.05.05   01.05.05   01.05.04
+mpi_fc.h    01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+mpi_lan.h   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+mpi_raid.h  01.05.02   01.05.02   01.05.02   01.05.02   01.05.02   01.05.02
+mpi_tool.h  01.05.03   01.05.03   01.05.03   01.05.03   01.05.03   01.05.03
+mpi_inb.h   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+mpi_sas.h   01.05.04   01.05.03   01.05.02   01.05.01   01.05.01   01.05.01
+mpi_type.h  01.05.02   01.05.02   01.05.02   01.05.01   01.05.01   01.05.01
 
 Filename    01.05.08   01.05.07   01.05.06   01.05.05   01.05.04   01.05.03
 ----------  --------   --------   --------   --------   --------   --------
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index c1c6789..ec9dff2 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2005 LSI Logic Corporation.
+ *  Copyright (c) 2000-2006 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_init.h
  *          Title:  MPI initiator mode messages and structures
  *  Creation Date:  June 8, 2000
  *
- *    mpi_init.h Version:  01.05.07
+ *    mpi_init.h Version:  01.05.08
  *
  *  Version History
  *  ---------------
@@ -53,6 +53,7 @@
  *  08-03-05  01.05.06  Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
  *                      unique in the first 32 characters.
  *  03-27-06  01.05.07  Added Task Management type of Clear ACA.
+ *  10-11-06  01.05.08  Shortened define for Task Management type of Clear ACA.
  *  --------------------------------------------------------------------------
  */
 
@@ -428,7 +429,7 @@
 #define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET    (0x05)
 #define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET        (0x06)
 #define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK            (0x07)
-#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_ACA             (0x08)
+#define MPI_SCSITASKMGMT_TASKTYPE_CLR_ACA               (0x08)
 
 /* MsgFlags bits */
 #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION   (0x00)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 18ba407..6c33e33 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2005 LSI Logic Corporation.
+ *  Copyright (c) 2000-2006 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_ioc.h
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  August 11, 2000
  *
- *    mpi_ioc.h Version:  01.05.11
+ *    mpi_ioc.h Version:  01.05.12
  *
  *  Version History
  *  ---------------
@@ -98,6 +98,14 @@
  *                      Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event
  *                      data structure.
  *                      Added MPI_EXT_IMAGE_TYPE_INITIALIZATION.
+ *  10-11-06  01.05.12  Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
+ *                      Added MaxInitiators field to PortFacts reply.
+ *                      Added SAS Device Status Change ReasonCode for
+ *                      asynchronous notificaiton.
+ *                      Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
+ *                      data structure.
+ *                      Added new ImageType values for FWDownload and FWUpload
+ *                      requests.
  *  --------------------------------------------------------------------------
  */
 
@@ -264,6 +272,7 @@
 #define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID         (0x0002)
 #define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL            (0x0004)
 #define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL       (0x0008)
+#define MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED        (0x0010)
 
 #define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT             (0x01)
 #define MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL       (0x02)
@@ -328,7 +337,8 @@
      U16                    MaxPostedCmdBuffers;        /* 1Ch */
      U16                    MaxPersistentIDs;           /* 1Eh */
      U16                    MaxLanBuckets;              /* 20h */
-     U16                    Reserved4;                  /* 22h */
+     U8                     MaxInitiators;              /* 22h */
+     U8                     Reserved4;                  /* 23h */
      U32                    Reserved5;                  /* 24h */
 } MSG_PORT_FACTS_REPLY, MPI_POINTER PTR_MSG_PORT_FACTS_REPLY,
   PortFactsReply_t, MPI_POINTER pPortFactsReply_t;
@@ -487,6 +497,7 @@
 #define MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x00000018)
 #define MPI_EVENT_SAS_INIT_TABLE_OVERFLOW       (0x00000019)
 #define MPI_EVENT_SAS_SMP_ERROR                 (0x0000001A)
+#define MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE    (0x0000001B)
 #define MPI_EVENT_LOG_ENTRY_ADDED               (0x00000021)
 
 /* AckRequired field values */
@@ -593,6 +604,7 @@
 #define MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL   (0x0A)
 #define MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL   (0x0B)
 #define MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL       (0x0C)
+#define MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION        (0x0D)
 
 
 /* SCSI Event data for Queue Full event */
@@ -895,6 +907,54 @@
   MpiEventDataSasInitTableOverflow_t,
   MPI_POINTER pMpiEventDataSasInitTableOverflow_t;
 
+/* SAS Expander Status Change Event data */
+
+typedef struct _EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE
+{
+    U8                      ReasonCode;             /* 00h */
+    U8                      Reserved1;              /* 01h */
+    U16                     Reserved2;              /* 02h */
+    U8                      PhysicalPort;           /* 04h */
+    U8                      Reserved3;              /* 05h */
+    U16                     EnclosureHandle;        /* 06h */
+    U64                     SASAddress;             /* 08h */
+    U32                     DiscoveryStatus;        /* 10h */
+    U16                     DevHandle;              /* 14h */
+    U16                     ParentDevHandle;        /* 16h */
+    U16                     ExpanderChangeCount;    /* 18h */
+    U16                     ExpanderRouteIndexes;   /* 1Ah */
+    U8                      NumPhys;                /* 1Ch */
+    U8                      SASLevel;               /* 1Dh */
+    U8                      Flags;                  /* 1Eh */
+    U8                      Reserved4;              /* 1Fh */
+} EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE,
+  MPI_POINTER PTR_EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE,
+  MpiEventDataSasExpanderStatusChange_t,
+  MPI_POINTER pMpiEventDataSasExpanderStatusChange_t;
+
+/* values for ReasonCode field of SAS Expander Status Change Event data */
+#define MPI_EVENT_SAS_EXP_RC_ADDED                      (0x00)
+#define MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING             (0x01)
+
+/* values for DiscoveryStatus field of SAS Expander Status Change Event data */
+#define MPI_EVENT_SAS_EXP_DS_LOOP_DETECTED              (0x00000001)
+#define MPI_EVENT_SAS_EXP_DS_UNADDRESSABLE_DEVICE       (0x00000002)
+#define MPI_EVENT_SAS_EXP_DS_MULTIPLE_PORTS             (0x00000004)
+#define MPI_EVENT_SAS_EXP_DS_EXPANDER_ERR               (0x00000008)
+#define MPI_EVENT_SAS_EXP_DS_SMP_TIMEOUT                (0x00000010)
+#define MPI_EVENT_SAS_EXP_DS_OUT_ROUTE_ENTRIES          (0x00000020)
+#define MPI_EVENT_SAS_EXP_DS_INDEX_NOT_EXIST            (0x00000040)
+#define MPI_EVENT_SAS_EXP_DS_SMP_FUNCTION_FAILED        (0x00000080)
+#define MPI_EVENT_SAS_EXP_DS_SMP_CRC_ERROR              (0x00000100)
+#define MPI_EVENT_SAS_EXP_DS_SUBTRACTIVE_LINK           (0x00000200)
+#define MPI_EVENT_SAS_EXP_DS_TABLE_LINK                 (0x00000400)
+#define MPI_EVENT_SAS_EXP_DS_UNSUPPORTED_DEVICE         (0x00000800)
+
+/* values for Flags field of SAS Expander Status Change Event data */
+#define MPI_EVENT_SAS_EXP_FLAGS_ROUTE_TABLE_CONFIG      (0x02)
+#define MPI_EVENT_SAS_EXP_FLAGS_CONFIG_IN_PROGRESS      (0x01)
+
+
 
 /*****************************************************************************
 *
@@ -926,6 +986,10 @@
 #define MPI_FW_DOWNLOAD_ITYPE_BIOS              (0x02)
 #define MPI_FW_DOWNLOAD_ITYPE_NVDATA            (0x03)
 #define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER        (0x04)
+#define MPI_FW_DOWNLOAD_ITYPE_MANUFACTURING     (0x06)
+#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_1          (0x07)
+#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_2          (0x08)
+#define MPI_FW_DOWNLOAD_ITYPE_MEGARAID          (0x09)
 
 
 typedef struct _FWDownloadTCSGE
@@ -980,6 +1044,11 @@
 #define MPI_FW_UPLOAD_ITYPE_NVDATA          (0x03)
 #define MPI_FW_UPLOAD_ITYPE_BOOTLOADER      (0x04)
 #define MPI_FW_UPLOAD_ITYPE_FW_BACKUP       (0x05)
+#define MPI_FW_UPLOAD_ITYPE_MANUFACTURING   (0x06)
+#define MPI_FW_UPLOAD_ITYPE_CONFIG_1        (0x07)
+#define MPI_FW_UPLOAD_ITYPE_CONFIG_2        (0x08)
+#define MPI_FW_UPLOAD_ITYPE_MEGARAID        (0x09)
+#define MPI_FW_UPLOAD_ITYPE_COMPLETE        (0x0A)
 
 typedef struct _FWUploadTCSGE
 {
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
index 871ebc0..635bbe0 100644
--- a/drivers/message/fusion/lsi/mpi_log_sas.h
+++ b/drivers/message/fusion/lsi/mpi_log_sas.h
@@ -1,4 +1,3 @@
-
 /***************************************************************************
  *                                                                         *
  *  Copyright 2003 LSI Logic Corporation.  All rights reserved.            *
@@ -14,7 +13,7 @@
 #define IOPI_IOCLOGINFO_H_INCLUDED
 
 #define SAS_LOGINFO_NEXUS_LOSS		0x31170000
-#define SAS_LOGINFO_MASK			0xFFFF0000
+#define SAS_LOGINFO_MASK		0xFFFF0000
 
 /****************************************************************************/
 /*  IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF                            */
@@ -43,129 +42,172 @@
 /****************************************************************************/
 /* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP          */
 /****************************************************************************/
-#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS            (0x00010000)
-#define IOP_LOGINFO_CODE_UNUSED2                        (0x00020000)
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE            (0x00030000)
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT         (0x00030100) /* Route Table Entry not found */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN         (0x00030200) /* Invalid Page Number */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM       (0x00030300) /* Invalid FORM */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT         (0x00030400) /* Invalid Page Type */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM        (0x00030500) /* Device Not Mapped */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST    (0x00030600) /* Persistent Page not found */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT    (0x00030700) /* Default Page not found */
+#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS                 (0x00010000)
+#define IOP_LOGINFO_CODE_UNUSED2                             (0x00020000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE                 (0x00030000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT              (0x00030100) /* Route Table Entry not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN              (0x00030200) /* Invalid Page Number */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM            (0x00030300) /* Invalid FORM */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT              (0x00030400) /* Invalid Page Type */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM             (0x00030500) /* Device Not Mapped */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST         (0x00030600) /* Persistent Page not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT         (0x00030700) /* Default Page not found */
 
-#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR                 (0x00040000) /* Error handling diag msg - or'd with diag status */
+#define IOP_LOGINFO_CODE_FWUPLOAD_NO_FLASH_AVAILABLE         (0x0003E000) /* Tried to upload from flash, but there is none */
+#define IOP_LOGINFO_CODE_FWUPLOAD_UNKNOWN_IMAGE_TYPE         (0x0003E001) /* ImageType field contents were invalid */
+#define IOP_LOGINFO_CODE_FWUPLOAD_WRONG_IMAGE_SIZE           (0x0003E002) /* ImageSize field in TCSGE was bad/offset in MfgPg 4 was wrong */
+#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occured while attempting to upload the entire flash */
+#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED       (0x0003E004) /* Error occured while attempting to upload single flash region */
+#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE                (0x0003E005) /* Problem occured while DMAing FW to host memory */
 
-#define IOP_LOGINFO_CODE_TASK_TERMINATED                (0x00050000)
+#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR                      (0x00040000) /* Error handling diag msg - or'd with diag status */
 
-#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R    (0x00060001) /* Read Action not supported for SEP msg */
-#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */
+#define IOP_LOGINFO_CODE_TASK_TERMINATED                     (0x00050000)
 
-#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED       (0x00070001)
-#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED  (0x00070002)
-#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO       (0x00070003)
-#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO     (0x00070004)
-#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005)
+#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R         (0x00060001) /* Read Action not supported for SEP msg */
+#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R      (0x00060002) /* Invalid Bus/ID in SEP msg */
+
+#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED            (0x00070001)
+#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED       (0x00070002)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO            (0x00070003)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO          (0x00070004)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ      (0x00070005)
 
 /****************************************************************************/
 /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL            */
 /****************************************************************************/
-#define PL_LOGINFO_CODE_OPEN_FAILURE                        (0x00010000)
-#define PL_LOG_INFO_CODE_OPEN_FAILURE_NO_DEST_TIME_OUT      (0x00010001)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_BAD_DESTINATION        (0x00010011)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_PROTOCOL_NOT_SUPPORTED (0x00010013)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_STP_RESOURCES_BSY      (0x00010018)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_WRONG_DESTINATION      (0x00010019)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_ORR_TIMEOUT            (0X0001001A)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_PATHWAY_BLOCKED        (0x0001001B)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_AWT_MAXED              (0x0001001C)
-#define PL_LOGINFO_CODE_INVALID_SGL                         (0x00020000)
-#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH       (0x00030000)
-#define PL_LOGINFO_CODE_FRAME_XFER_ERROR                    (0x00040000)
-#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW                 (0x00050000)
-#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET         (0x00060000)
-#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR      (0x00070000)
-#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR     (0x00080000)
-#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS     (0x00090000)
-#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE               (0x000A0000)
-#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR          (0x000B0000)
-#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR           (0x000C0000)
-#define PL_LOGINFO_CODE_SATA_LINK_DOWN                      (0x000D0000)
-#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS           (0x000E0000)
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE                 (0x000F0000)
-#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED           (0x000F0001) /* PL not yet initialized, can't do config page req. */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT              (0x000F0100) /* Invalid Page Type */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS        (0x000F0200) /* Invalid Number of Phys */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP         (0x000F0300) /* Case Not Handled */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV          (0x000F0400) /* No Device Found */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM            (0x000F0500) /* Invalid FORM */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY             (0x000F0600) /* Invalid Phy */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER        (0x000F0700) /* No Owner Found */
-#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT            (0x00100000)
-#define PL_LOGINFO_CODE_RESET                               (0x00110000) /* See Sub-Codes below */
-#define PL_LOGINFO_CODE_ABORT                               (0x00120000) /* See Sub-Codes below */
-#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED                 (0x00130000)
-#define PL_LOGINFO_CODE_IO_EXECUTED                         (0x00140000)
-#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER       (0x00150000)
-#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT                    (0x00160000)
-#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY       (0x00170000)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE                    (0x00000100)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT    (0x00000101)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT        (0x0000011A) /* Open Reject (Retry) Timeout */
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATHWAY_BLOCKED    (0x0000011B)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED          (0x0000011C) /* Arbitration Wait Timer Maxed */
+#define PL_LOGINFO_CODE_OPEN_FAILURE                         (0x00010000) /* see SUB_CODE_OPEN_FAIL_ below */
 
-#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET                (0x00000120)
-#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER                 (0x00000130)  /* Leave lower nibble (1-f) reserved. */
-#define PL_LOGINFO_SUB_CODE_PORT_LAYER                      (0x00000140)  /* Leave lower nibble (1-f) reserved. */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_NO_DEST_TIME_OUT       (0x00000001)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PATHWAY_BLOCKED        (0x00000002)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_CONTINUE0          (0x00000003)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_CONTINUE1          (0x00000004)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_INITIALIZE0        (0x00000005)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_INITIALIZE1        (0x00000006)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_STOP0              (0x00000007)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_STOP1              (0x00000008)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RETRY                  (0x00000009)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_BREAK                  (0x0000000A)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0B              (0x0000000B)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_OPEN_TIMEOUT_EXP       (0x0000000C)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0D              (0x0000000D)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_DVTBLE_ACCSS_FAIL      (0x0000000E)
+#define PL_LOGINFO_SUB CODE_OPEN_FAIL_BAD_DEST               (0x00000011)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RATE_NOT_SUPP          (0x00000012)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PROT_NOT_SUPP          (0x00000013)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON0      (0x00000014)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON1      (0x00000015)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON2      (0x00000016)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON3      (0x00000017)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_STP_RESOURCES_BSY      (0x00000018)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_WRONG_DESTINATION      (0x00000019)
+
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PATH_BLOCKED           (0x0000001B) /* Retry Timeout */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_AWT_MAXED              (0x0000001C) /* Retry Timeout */
 
 
-#define PL_LOGINFO_SUB_CODE_INVALID_SGL                     (0x00000200)
-#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH   (0x00000300)
-#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR                (0x00000400)
-#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW             (0x00000500)
-#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET     (0x00000600)
-#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR  (0x00000700)
-#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800)
-#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900)
-#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE           (0x00000A00)
-#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR      (0x00000B00)
-#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR       (0x00000C00)
-#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN                  (0x00000D00)
-#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS       (0x00000E00)
-#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET      (0x00000E01)
-#define PL_LOGINFO_SUB_CODE_SECOND_OPEN                     (0x00000F00)
-#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT        (0x00001000)
+
+#define PL_LOGINFO_CODE_INVALID_SGL                          (0x00020000)
+#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH        (0x00030000)
+#define PL_LOGINFO_CODE_FRAME_XFER_ERROR                     (0x00040000)
+#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW                  (0x00050000)
+#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET          (0x00060000)
+#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR       (0x00070000)
+#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR      (0x00080000)
+#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS      (0x00090000)
+#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE                (0x000A0000)
+#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR           (0x000B0000)
+#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR            (0x000C0000)
+#define PL_LOGINFO_CODE_SATA_LINK_DOWN                       (0x000D0000)
+#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS            (0x000E0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE                  (0x000F0000)
+#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED            (0x000F0001) /* PL not yet initialized, can't do config page req. */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT               (0x000F0100) /* Invalid Page Type */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS         (0x000F0200) /* Invalid Number of Phys */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP          (0x000F0300) /* Case Not Handled */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV           (0x000F0400) /* No Device Found */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM             (0x000F0500) /* Invalid FORM */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY              (0x000F0600) /* Invalid Phy */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER         (0x000F0700) /* No Owner Found */
+#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT             (0x00100000)
+#define PL_LOGINFO_CODE_RESET                                (0x00110000) /* See Sub-Codes below (PL_LOGINFO_SUB_CODE) */
+#define PL_LOGINFO_CODE_ABORT                                (0x00120000) /* See Sub-Codes below  (PL_LOGINFO_SUB_CODE)*/
+#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED                  (0x00130000)
+#define PL_LOGINFO_CODE_IO_EXECUTED                          (0x00140000)
+#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER        (0x00150000)
+#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT                     (0x00160000)
+#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY        (0x00170000)
+#define PL_LOGINFO_CODE_IO_CANCELLED_DUE_TO_R_ERR            (0x00180000)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE                     (0x00000100)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT     (0x00000101)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_SATA_NEG_RATE_2HI   (0x00000102)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_RATE_NOT_SUPPORTED  (0x00000103)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_BREAK               (0x00000104)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ZONE_VIOLATION      (0x00000114)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON0            (0x00000114) /* Open Reject (Zone Violation) - available on SAS-2 devices */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON1            (0x00000115)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON2            (0x00000116)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON3            (0x00000117)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT         (0x0000011A) /* Open Reject (Retry) Timeout */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATH_BLOCKED        (0x0000011B)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED           (0x0000011C) /* Arbitration Wait Timer Maxed */
+
+#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET                 (0x00000120)
+#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER                  (0x00000130)  /* Leave lower nibble (1-f) reserved. */
+#define PL_LOGINFO_SUB_CODE_PORT_LAYER                       (0x00000140)  /* Leave lower nibble (1-f) reserved. */
 
 
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE         (0x00200000) /* Can't get SMP Frame */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR            (0x00200010) /* Error occured on SMP Read */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR           (0x00200020) /* Error occured on SMP Write */
-#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL     (0x00200040) /* Encl Mgmt services not available for this WWID */
-#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED   (0x00200050) /* Address Mode not suppored */
-#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM              (0x00200060) /* Invalid Slot Number in SEP Msg */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT         (0x00200070) /* SGPIO not present/enabled */
-#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED       (0x00200080) /* GPIO not configured */
-#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR          (0x00200090) /* GPIO can't allocate a frame */
-#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR    (0x002000A0) /* GPIO failed config page request */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR     (0x002000B0) /* Can't get frame for SES command */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR              (0x002000C0) /* I/O execution error */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED     (0x002000D0) /* SEP I/O retries exhausted */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR     (0x002000E0) /* Can't get frame for SMP command */
+#define PL_LOGINFO_SUB_CODE_INVALID_SGL                      (0x00000200)
+#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH    (0x00000300)
+#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR                 (0x00000400) /* Bits 0-3 encode Transport Status Register (offset 0x08) */
+                                                                          /* Bit 0 is Status Bit 0: FrameXferErr */
+                                                                          /* Bit 1 & 2 are Status Bits 16 and 17: FrameXmitErrStatus */
+                                                                          /* Bit 3 is Status Bit 18 WriteDataLenghtGTDataLengthErr */
 
-#define PL_LOGINFO_DA_SEP_NOT_PRESENT                       (0x00200100) /* SEP not present when msg received */
-#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR               (0x00200101) /* Can only accept 1 msg at a time */
-#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE          (0x00200102) /* ISTWI interrupt recvd. while IDLE */
-#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE          (0x00200103) /* SEP NACK'd, it is busy */
-#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK               (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */
-#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM             (0x00200105) /* SEP stopped or sent bad chksum in Hdr */
-#define PL_LOGINFO_DA_SEP_STOP_ON_DATA                      (0x00200106) /* SEP stopped while transfering data */
-#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA                (0x00200107) /* SEP stopped while transfering sense data */
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1         (0x00200108) /* SEP returned unknown scsi status */
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2         (0x00200109) /* SEP returned unknown scsi status */
-#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP           (0x0020010A) /* SEP returned bad chksum after STOP */
-#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA   (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND               (0x0020010C) /* SEP doesn't support CDB opcode */
+#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW              (0x00000500)
+#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET      (0x00000600)
+#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR   (0x00000700)
+#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR  (0x00000800)
+#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS  (0x00000900)
+#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE            (0x00000A00)
+#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR       (0x00000B00)
+#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR        (0x00000C00)
+#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN                   (0x00000D00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS        (0x00000E00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET       (0x00000E01)
+#define PL_LOGINFO_SUB_CODE_SECOND_OPEN                      (0x00000F00)
+#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT         (0x00001000)
+
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE          (0x00200000) /* Can't get SMP Frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR             (0x00200010) /* Error occured on SMP Read */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR            (0x00200020) /* Error occured on SMP Write */
+#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL      (0x00200040) /* Encl Mgmt services not available for this WWID */
+#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED    (0x00200050) /* Address Mode not suppored */
+#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM               (0x00200060) /* Invalid Slot Number in SEP Msg */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT          (0x00200070) /* SGPIO not present/enabled */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED        (0x00200080) /* GPIO not configured */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR           (0x00200090) /* GPIO can't allocate a frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR     (0x002000A0) /* GPIO failed config page request */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR      (0x002000B0) /* Can't get frame for SES command */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR               (0x002000C0) /* I/O execution error */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED      (0x002000D0) /* SEP I/O retries exhausted */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR      (0x002000E0) /* Can't get frame for SMP command */
+
+#define PL_LOGINFO_DA_SEP_NOT_PRESENT                        (0x00200100) /* SEP not present when msg received */
+#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR                (0x00200101) /* Can only accept 1 msg at a time */
+#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE           (0x00200102) /* ISTWI interrupt recvd. while IDLE */
+#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE           (0x00200103) /* SEP NACK'd, it is busy */
+#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK                (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */
+#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM              (0x00200105) /* SEP stopped or sent bad chksum in Hdr */
+#define PL_LOGINFO_DA_SEP_STOP_ON_DATA                       (0x00200106) /* SEP stopped while transfering data */
+#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA                 (0x00200107) /* SEP stopped while transfering sense data */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1          (0x00200108) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2          (0x00200109) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP            (0x0020010A) /* SEP returned bad chksum after STOP */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA    (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND                (0x0020010C) /* SEP doesn't support CDB opcode f/w location 1 */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND_2              (0x0020010D) /* SEP doesn't support CDB opcode f/w location 2 */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND_3              (0x0020010E) /* SEP doesn't support CDB opcode f/w location 3 */
 
 
 /****************************************************************************/
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index 50b8f0a..8e990a0 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2004 LSI Logic Corporation.
+ *  Copyright (c) 2004-2006 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_sas.h
  *          Title:  MPI Serial Attached SCSI structures and definitions
  *  Creation Date:  August 19, 2004
  *
- *    mpi_sas.h Version:  01.05.03
+ *    mpi_sas.h Version:  01.05.04
  *
  *  Version History
  *  ---------------
@@ -21,6 +21,8 @@
  *                      and Remove Device operations to SAS IO Unit Control.
  *                      Added DevHandle field to SAS IO Unit Control request and
  *                      reply.
+ *  10-11-06  01.05.04  Fixed the name of a define for Operation field of SAS IO
+ *                      Unit Control request.
  *  --------------------------------------------------------------------------
  */
 
@@ -237,7 +239,8 @@
 #define MPI_SAS_OP_SEND_PRIMITIVE               (0x0A)
 #define MPI_SAS_OP_FORCE_FULL_DISCOVERY         (0x0B)
 #define MPI_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL  (0x0C)
-#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE       (0x0D)
+#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE       (0x0D)  /* obsolete name */
+#define MPI_SAS_OP_REMOVE_DEVICE                (0x0D)
 
 /* values for the PrimFlags field */
 #define MPI_SAS_PRIMFLAGS_SINGLE                (0x08)
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index b3f28a0..083acfd 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -82,6 +82,10 @@
 module_param(mpt_msi_enable, int, 0);
 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
 
+static int mpt_channel_mapping;
+module_param(mpt_channel_mapping, int, 0);
+MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
+
 #ifdef MFCNT
 static int mfcounter = 0;
 #define PRINT_MF_COUNT 20000
@@ -173,11 +177,14 @@
 
 //int		mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
 static int	ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
-static void	mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
+#ifdef MPT_DEBUG_REPLY
+static void	mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
+#endif
 static void	mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void	mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void	mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static int	mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
+static void	mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
 
 /* module entry point */
 static int  __init    fusion_init  (void);
@@ -319,13 +326,11 @@
 		else if (ioc->bus_type == SAS)
 			mpt_sas_log_info(ioc, log_info);
 	}
-	if (ioc_stat & MPI_IOCSTATUS_MASK) {
-		if (ioc->bus_type == SPI &&
-		    cb_idx != mpt_stm_index &&
-		    cb_idx != mpt_lan_index)
-			mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
-	}
 
+#ifdef MPT_DEBUG_REPLY
+	if (ioc_stat & MPI_IOCSTATUS_MASK)
+		mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
+#endif
 
 	/*  Check for (valid) IO callback!  */
 	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
@@ -911,7 +916,7 @@
 int
 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
 {
-	int		 r = 0;
+	int	r = 0;
 	u8	*req_as_bytes;
 	int	 ii;
 
@@ -1811,6 +1816,13 @@
 	 *	and we try GetLanConfigPages again...
 	 */
 	if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
+
+		/*
+		 * Initalize link list for inactive raid volumes.
+		 */
+		init_MUTEX(&ioc->raid_data.inactive_list_mutex);
+		INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
+
 		if (ioc->bus_type == SAS) {
 
 			/* clear persistency table */
@@ -2017,6 +2029,8 @@
 	}
 
 	kfree(ioc->spi_data.nvram);
+	mpt_inactive_raid_list_free(ioc);
+	kfree(ioc->raid_data.pIocPg2);
 	kfree(ioc->raid_data.pIocPg3);
 	ioc->spi_data.nvram = NULL;
 	ioc->raid_data.pIocPg3 = NULL;
@@ -2413,6 +2427,9 @@
 			facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
 
 		facts->ProductID = le16_to_cpu(facts->ProductID);
+		if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+		    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
+			ioc->ir_firmware = 1;
 		facts->CurrentHostMfaHighAddr =
 				le32_to_cpu(facts->CurrentHostMfaHighAddr);
 		facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
@@ -2505,6 +2522,7 @@
 	int			 ii;
 	int			 req_sz;
 	int			 reply_sz;
+	int			 max_id;
 
 	/* IOC *must* NOT be in RESET state! */
 	if (ioc->last_state == MPI_IOC_STATE_RESET) {
@@ -2552,6 +2570,21 @@
 	pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
 	pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
 
+	max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
+	    pfacts->MaxDevices;
+	ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
+	ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
+
+	/*
+	 * Place all the devices on channels
+	 *
+	 * (for debuging)
+	 */
+	if (mpt_channel_mapping) {
+		ioc->devices_per_bus = 1;
+		ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
+	}
+
 	return 0;
 }
 
@@ -2592,13 +2625,8 @@
 	ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
 		   ioc->name, ioc->upload_fw, ioc->facts.Flags));
 
-	if(ioc->bus_type == SAS)
-		ioc_init.MaxDevices = ioc->facts.MaxDevices;
-	else if(ioc->bus_type == FC)
-		ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
-	else
-		ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
-	ioc_init.MaxBuses = MPT_MAX_BUS;
+	ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
+	ioc_init.MaxBuses = (U8)ioc->number_of_buses;
 	dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
 		   ioc->name, ioc->facts.MsgVersion));
 	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
@@ -2720,9 +2748,7 @@
 
 	/* RAID FW may take a long time to enable
 	 */
-	if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
-	    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
-	    (ioc->bus_type == SAS)) {
+	if (ioc->ir_firmware || ioc->bus_type == SAS) {
 		rc = mpt_handshake_req_reply_wait(ioc, req_sz,
 		(u32*)&port_enable, reply_sz, (u16*)&reply_buf,
 		300 /*seconds*/, sleepFlag);
@@ -3193,6 +3219,9 @@
 	u32 diag1val = 0;
 #endif
 
+	/* Clear any existing interrupts */
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
 	if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
 		drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
 			"address=%p\n",  ioc->name, __FUNCTION__,
@@ -3212,7 +3241,7 @@
 			        " count=%d\n",
 				ioc->name, doorbell, count));
 			if (doorbell == MPI_IOC_STATE_READY) {
-				return 0;
+				return 1;
 			}
 
 			/* wait 1 sec */
@@ -3224,9 +3253,6 @@
 		return -1;
 	}
 
-	/* Clear any existing interrupts */
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-
 	/* Use "Diagnostic reset" method! (only thing available!) */
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
 
@@ -3942,7 +3968,7 @@
 		}
 	} else {
 		while (--cntdn) {
-			mdelay (1);
+			udelay (1000);
 			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
 			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
 				break;
@@ -3994,7 +4020,7 @@
 			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
 			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
 				break;
-			mdelay(1);
+			udelay (1000);
 			count++;
 		}
 	}
@@ -4310,8 +4336,8 @@
 	if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
 	     reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
 	    (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
-		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
-			ioc->name, disk);
+		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
+			ioc->name, disk, volume);
 	} else {
 		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
 			ioc->name, volume);
@@ -4712,7 +4738,187 @@
 	return 0;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mpt_inactive_raid_list_free
+ *
+ * This clears this link list.
+ *
+ * @ioc - pointer to per adapter structure
+ *
+ **/
+static void
+mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
+{
+	struct inactive_raid_component_info *component_info, *pNext;
+
+	if (list_empty(&ioc->raid_data.inactive_list))
+		return;
+
+	down(&ioc->raid_data.inactive_list_mutex);
+	list_for_each_entry_safe(component_info, pNext,
+	    &ioc->raid_data.inactive_list, list) {
+		list_del(&component_info->list);
+		kfree(component_info);
+	}
+	up(&ioc->raid_data.inactive_list_mutex);
+}
+
+/**
+ * mpt_inactive_raid_volumes
+ *
+ * This sets up link list of phy_disk_nums for devices belonging in an inactive volume
+ *
+ * @ioc - pointer to per adapter structure
+ * @channel - volume channel
+ * @id - volume target id
+ *
+ *
+ **/
+static void
+mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	CONFIGPARMS			cfg;
+	ConfigPageHeader_t		hdr;
+	dma_addr_t			dma_handle;
+	pRaidVolumePage0_t		buffer = NULL;
+	int				i;
+	RaidPhysDiskPage0_t 		phys_disk;
+	struct inactive_raid_component_info *component_info;
+	int				handle_inactive_volumes;
+
+	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+	cfg.pageAddr = (channel << 8) + id;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+	if (mpt_config(ioc, &cfg) != 0)
+		goto out;
+
+	if (!hdr.PageLength)
+		goto out;
+
+	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+	    &dma_handle);
+
+	if (!buffer)
+		goto out;
+
+	cfg.physAddr = dma_handle;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+	if (mpt_config(ioc, &cfg) != 0)
+		goto out;
+
+	if (!buffer->NumPhysDisks)
+		goto out;
+
+	handle_inactive_volumes =
+	   (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
+	   (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
+	    buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
+	    buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
+
+	if (!handle_inactive_volumes)
+		goto out;
+
+	down(&ioc->raid_data.inactive_list_mutex);
+	for (i = 0; i < buffer->NumPhysDisks; i++) {
+		if(mpt_raid_phys_disk_pg0(ioc,
+		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+			continue;
+
+		if ((component_info = kmalloc(sizeof (*component_info),
+		 GFP_KERNEL)) == NULL)
+			continue;
+
+		component_info->volumeID = id;
+		component_info->volumeBus = channel;
+		component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
+		component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
+		component_info->d.PhysDiskID = phys_disk.PhysDiskID;
+		component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
+
+		list_add_tail(&component_info->list,
+		    &ioc->raid_data.inactive_list);
+	}
+	up(&ioc->raid_data.inactive_list_mutex);
+
+ out:
+	if (buffer)
+		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+		    dma_handle);
+}
+
+/**
+ *	mpt_raid_phys_disk_pg0 - returns phys disk page zero
+ *	@ioc: Pointer to a Adapter Structure
+ *	@phys_disk_num: io unit unique phys disk num generated by the ioc
+ *	@phys_disk: requested payload data returned
+ *
+ *	Return:
+ *	0 on success
+ *	-EFAULT if read of config page header fails or data pointer not NULL
+ *	-ENOMEM if pci_alloc failed
+ **/
+int
+mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
+{
+	CONFIGPARMS		 	cfg;
+	ConfigPageHeader_t	 	hdr;
+	dma_addr_t			dma_handle;
+	pRaidPhysDiskPage0_t		buffer = NULL;
+	int				rc;
+
+	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+
+	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+	if (mpt_config(ioc, &cfg) != 0) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	if (!hdr.PageLength) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+	    &dma_handle);
+
+	if (!buffer) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	cfg.physAddr = dma_handle;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+	cfg.pageAddr = phys_disk_num;
+
+	if (mpt_config(ioc, &cfg) != 0) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	rc = 0;
+	memcpy(phys_disk, buffer, sizeof(*buffer));
+	phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
+
+ out:
+
+	if (buffer)
+		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+		    dma_handle);
+
+	return rc;
+}
+
 /**
  *	mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
  *	@ioc: Pointer to a Adapter Strucutre
@@ -4722,21 +4928,27 @@
  *	0 on success
  *	-EFAULT if read of config page header fails or data pointer not NULL
  *	-ENOMEM if pci_alloc failed
- */
+ **/
 int
 mpt_findImVolumes(MPT_ADAPTER *ioc)
 {
 	IOCPage2_t		*pIoc2;
 	u8			*mem;
-	ConfigPageIoc2RaidVol_t	*pIocRv;
 	dma_addr_t		 ioc2_dma;
 	CONFIGPARMS		 cfg;
 	ConfigPageHeader_t	 header;
-	int			 jj;
 	int			 rc = 0;
 	int			 iocpage2sz;
-	u8			 nVols, nPhys;
-	u8			 vid, vbus, vioc;
+	int			 i;
+
+	if (!ioc->ir_firmware)
+		return 0;
+
+	/* Free the old page
+	 */
+	kfree(ioc->raid_data.pIocPg2);
+	ioc->raid_data.pIocPg2 = NULL;
+	mpt_inactive_raid_list_free(ioc);
 
 	/* Read IOCP2 header then the page.
 	 */
@@ -4764,55 +4976,23 @@
 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 	cfg.physAddr = ioc2_dma;
 	if (mpt_config(ioc, &cfg) != 0)
-		goto done_and_free;
+		goto out;
 
-	if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
-		mem = kmalloc(iocpage2sz, GFP_ATOMIC);
-		if (mem) {
-			ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
-		} else {
-			goto done_and_free;
-		}
-	}
+	mem = kmalloc(iocpage2sz, GFP_KERNEL);
+	if (!mem)
+		goto out;
+
 	memcpy(mem, (u8 *)pIoc2, iocpage2sz);
+	ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
 
-	/* Identify RAID Volume Id's */
-	nVols = pIoc2->NumActiveVolumes;
-	if ( nVols == 0) {
-		/* No RAID Volume.
-		 */
-		goto done_and_free;
-	} else {
-		/* At least 1 RAID Volume
-		 */
-		pIocRv = pIoc2->RaidVolume;
-		ioc->raid_data.isRaid = 0;
-		for (jj = 0; jj < nVols; jj++, pIocRv++) {
-			vid = pIocRv->VolumeID;
-			vbus = pIocRv->VolumeBus;
-			vioc = pIocRv->VolumeIOC;
+	mpt_read_ioc_pg_3(ioc);
 
-			/* find the match
-			 */
-			if (vbus == 0) {
-				ioc->raid_data.isRaid |= (1 << vid);
-			} else {
-				/* Error! Always bus 0
-				 */
-			}
-		}
-	}
+	for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
+		mpt_inactive_raid_volumes(ioc,
+		    pIoc2->RaidVolume[i].VolumeBus,
+		    pIoc2->RaidVolume[i].VolumeID);
 
-	/* Identify Hidden Physical Disk Id's */
-	nPhys = pIoc2->NumActivePhysDisks;
-	if (nPhys == 0) {
-		/* No physical disks.
-		 */
-	} else {
-		mpt_read_ioc_pg_3(ioc);
-	}
-
-done_and_free:
+ out:
 	pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
 
 	return rc;
@@ -4865,7 +5045,7 @@
 	cfg.physAddr = ioc3_dma;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 	if (mpt_config(ioc, &cfg) == 0) {
-		mem = kmalloc(iocpage3sz, GFP_ATOMIC);
+		mem = kmalloc(iocpage3sz, GFP_KERNEL);
 		if (mem) {
 			memcpy(mem, (u8 *)pIoc3, iocpage3sz);
 			ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
@@ -5679,8 +5859,6 @@
 	return rc;
 }
 
-# define EVENT_DESCR_STR_SZ		100
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static void
 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
@@ -5708,9 +5886,6 @@
 		break;
 	case MPI_EVENT_RESCAN:
 		ds = "Bus Rescan Event";
-		/* Ok, do we need to do anything here? As far as
-		   I can tell, this is when a new device gets added
-		   to the loop. */
 		break;
 	case MPI_EVENT_LINK_STATUS_CHANGE:
 		if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
@@ -5787,48 +5962,63 @@
 	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
 	{
 		u8 id = (u8)(evData0);
+		u8 channel = (u8)(evData0 >> 8);
 		u8 ReasonCode = (u8)(evData0 >> 16);
 		switch (ReasonCode) {
 		case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Added: id=%d", id);
+			    "SAS Device Status Change: Added: "
+			    "id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Deleted: id=%d", id);
+			    "SAS Device Status Change: Deleted: "
+			    "id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: SMART Data: id=%d",
-			    id);
+			    "SAS Device Status Change: SMART Data: "
+			    "id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: No Persistancy: id=%d", id);
+			    "SAS Device Status Change: No Persistancy: "
+			    "id=%d channel=%d", id, channel);
+			break;
+		case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS Device Status Change: Unsupported Device "
+			    "Discovered : id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Internal Device Reset : id=%d", id);
+			    "SAS Device Status Change: Internal Device "
+			    "Reset : id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Internal Task Abort : id=%d", id);
+			    "SAS Device Status Change: Internal Task "
+			    "Abort : id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Internal Abort Task Set : id=%d", id);
+			    "SAS Device Status Change: Internal Abort "
+			    "Task Set : id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Internal Clear Task Set : id=%d", id);
+			    "SAS Device Status Change: Internal Clear "
+			    "Task Set : id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Internal Query Task : id=%d", id);
+			    "SAS Device Status Change: Internal Query "
+			    "Task : id=%d channel=%d", id, channel);
 			break;
 		default:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Unknown: id=%d", id);
+			    "SAS Device Status Change: Unknown: "
+			    "id=%d channel=%d", id, channel);
 			break;
 		}
 		break;
@@ -5837,8 +6027,16 @@
 		ds = "Bus Timer Expired";
 		break;
 	case MPI_EVENT_QUEUE_FULL:
-		ds = "Queue Full";
+	{
+		u16 curr_depth = (u16)(evData0 >> 16);
+		u8 channel = (u8)(evData0 >> 8);
+		u8 id = (u8)(evData0);
+
+		snprintf(evStr, EVENT_DESCR_STR_SZ,
+		   "Queue Full: channel=%d id=%d depth=%d",
+		   channel, id, curr_depth);
 		break;
+	}
 	case MPI_EVENT_SAS_SES:
 		ds = "SAS SES Event";
 		break;
@@ -5942,6 +6140,76 @@
 		ds = "SAS Log Entry Added";
 		break;
 
+	case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
+	{
+		u8 phy_num = (u8)(evData0);
+		u8 port_num = (u8)(evData0 >> 8);
+		u8 port_width = (u8)(evData0 >> 16);
+		u8 primative = (u8)(evData0 >> 24);
+		snprintf(evStr, EVENT_DESCR_STR_SZ,
+		    "SAS Broadcase Primative: phy=%d port=%d "
+		    "width=%d primative=0x%02x",
+		    phy_num, port_num, port_width, primative);
+		break;
+	}
+
+	case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
+	{
+		u8 reason = (u8)(evData0);
+		u8 port_num = (u8)(evData0 >> 8);
+		u16 handle = le16_to_cpu(evData0 >> 16);
+
+		snprintf(evStr, EVENT_DESCR_STR_SZ,
+		    "SAS Initiator Device Status Change: reason=0x%02x "
+		    "port=%d handle=0x%04x",
+		    reason, port_num, handle);
+		break;
+	}
+
+	case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
+	{
+		u8 max_init = (u8)(evData0);
+		u8 current_init = (u8)(evData0 >> 8);
+
+		snprintf(evStr, EVENT_DESCR_STR_SZ,
+		    "SAS Initiator Device Table Overflow: max initiators=%02d "
+		    "current initators=%02d",
+		    max_init, current_init);
+		break;
+	}
+	case MPI_EVENT_SAS_SMP_ERROR:
+	{
+		u8 status = (u8)(evData0);
+		u8 port_num = (u8)(evData0 >> 8);
+		u8 result = (u8)(evData0 >> 16);
+
+		if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d result=0x%02x",
+			    port_num, result);
+		else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d : CRC Error",
+			    port_num);
+		else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d : Timeout",
+			    port_num);
+		else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d : No Destination",
+			    port_num);
+		else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d : Bad Destination",
+			    port_num);
+		else
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d : status=0x%02x",
+			    port_num, status);
+		break;
+	}
+
 	/*
 	 *  MPT base "custom" events may be added here...
 	 */
@@ -6205,10 +6473,11 @@
 		"Abort",					/* 12h */
 		"IO Not Yet Executed",				/* 13h */
 		"IO Executed",					/* 14h */
-		"Persistent Reservation Out Not Affiliation Owner", /* 15h */
+		"Persistent Reservation Out Not Affiliation "
+		    "Owner", 					/* 15h */
 		"Open Transmit DMA Abort",			/* 16h */
 		"IO Device Missing Delay Retry",		/* 17h */
-		NULL,						/* 18h */
+		"IO Cancelled Due to Recieve Error",		/* 18h */
 		NULL,						/* 19h */
 		NULL,						/* 1Ah */
 		NULL,						/* 1Bh */
@@ -6218,6 +6487,96 @@
 		NULL,						/* 1Fh */
 		"Enclosure Management"				/* 20h */
 	};
+	static char *ir_code_str[] = {
+		"Raid Action Error",				/* 00h */
+		NULL,						/* 00h */
+		NULL,						/* 01h */
+		NULL,						/* 02h */
+		NULL,						/* 03h */
+		NULL,						/* 04h */
+		NULL,						/* 05h */
+		NULL,						/* 06h */
+		NULL						/* 07h */
+	};
+	static char *raid_sub_code_str[] = {
+		NULL, 						/* 00h */
+		"Volume Creation Failed: Data Passed too "
+		    "Large", 					/* 01h */
+		"Volume Creation Failed: Duplicate Volumes "
+		    "Attempted", 				/* 02h */
+		"Volume Creation Failed: Max Number "
+		    "Supported Volumes Exceeded",		/* 03h */
+		"Volume Creation Failed: DMA Error",		/* 04h */
+		"Volume Creation Failed: Invalid Volume Type",	/* 05h */
+		"Volume Creation Failed: Error Reading "
+		    "MFG Page 4", 				/* 06h */
+		"Volume Creation Failed: Creating Internal "
+		    "Structures", 				/* 07h */
+		NULL,						/* 08h */
+		NULL,						/* 09h */
+		NULL,						/* 0Ah */
+		NULL,						/* 0Bh */
+		NULL,						/* 0Ch */
+		NULL,						/* 0Dh */
+		NULL,						/* 0Eh */
+		NULL,						/* 0Fh */
+		"Activation failed: Already Active Volume", 	/* 10h */
+		"Activation failed: Unsupported Volume Type", 	/* 11h */
+		"Activation failed: Too Many Active Volumes", 	/* 12h */
+		"Activation failed: Volume ID in Use", 		/* 13h */
+		"Activation failed: Reported Failure", 		/* 14h */
+		"Activation failed: Importing a Volume", 	/* 15h */
+		NULL,						/* 16h */
+		NULL,						/* 17h */
+		NULL,						/* 18h */
+		NULL,						/* 19h */
+		NULL,						/* 1Ah */
+		NULL,						/* 1Bh */
+		NULL,						/* 1Ch */
+		NULL,						/* 1Dh */
+		NULL,						/* 1Eh */
+		NULL,						/* 1Fh */
+		"Phys Disk failed: Too Many Phys Disks", 	/* 20h */
+		"Phys Disk failed: Data Passed too Large",	/* 21h */
+		"Phys Disk failed: DMA Error", 			/* 22h */
+		"Phys Disk failed: Invalid <channel:id>", 	/* 23h */
+		"Phys Disk failed: Creating Phys Disk Config "
+		    "Page", 					/* 24h */
+		NULL,						/* 25h */
+		NULL,						/* 26h */
+		NULL,						/* 27h */
+		NULL,						/* 28h */
+		NULL,						/* 29h */
+		NULL,						/* 2Ah */
+		NULL,						/* 2Bh */
+		NULL,						/* 2Ch */
+		NULL,						/* 2Dh */
+		NULL,						/* 2Eh */
+		NULL,						/* 2Fh */
+		"Compatibility Error: IR Disabled",		/* 30h */
+		"Compatibility Error: Inquiry Comand Failed",	/* 31h */
+		"Compatibility Error: Device not Direct Access "
+		    "Device ",					/* 32h */
+		"Compatibility Error: Removable Device Found",	/* 33h */
+		"Compatibility Error: Device SCSI Version not "
+		    "2 or Higher", 				/* 34h */
+		"Compatibility Error: SATA Device, 48 BIT LBA "
+		    "not Supported", 				/* 35h */
+		"Compatibility Error: Device doesn't have "
+		    "512 Byte Block Sizes", 			/* 36h */
+		"Compatibility Error: Volume Type Check Failed", /* 37h */
+		"Compatibility Error: Volume Type is "
+		    "Unsupported by FW", 			/* 38h */
+		"Compatibility Error: Disk Drive too Small for "
+		    "use in Volume", 				/* 39h */
+		"Compatibility Error: Phys Disk for Create "
+		    "Volume not Found", 			/* 3Ah */
+		"Compatibility Error: Too Many or too Few "
+		    "Disks for Volume Type", 			/* 3Bh */
+		"Compatibility Error: Disk stripe Sizes "
+		    "Must be 64KB", 				/* 3Ch */
+		"Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
+	};
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
@@ -6226,7 +6585,7 @@
  *	@log_info: U32 LogInfo reply word from the IOC
  *
  *	Refer to lsi/mpi_log_sas.h.
- */
+ **/
 static void
 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
 {
@@ -6240,56 +6599,165 @@
 	}dw;
 };
 	union loginfo_type sas_loginfo;
+	char *originator_desc = NULL;
 	char *code_desc = NULL;
+	char *sub_code_desc = NULL;
 
 	sas_loginfo.loginfo = log_info;
 	if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
 	    (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
 		return;
-	if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
-	    (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
-		code_desc = iop_code_str[sas_loginfo.dw.code];
-	}else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
-	    (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
-		code_desc = pl_code_str[sas_loginfo.dw.code];
+
+	originator_desc = originator_str[sas_loginfo.dw.originator];
+
+	switch (sas_loginfo.dw.originator) {
+
+		case 0:  /* IOP */
+			if (sas_loginfo.dw.code <
+			    sizeof(iop_code_str)/sizeof(char*))
+				code_desc = iop_code_str[sas_loginfo.dw.code];
+			break;
+		case 1:  /* PL */
+			if (sas_loginfo.dw.code <
+			    sizeof(pl_code_str)/sizeof(char*))
+				code_desc = pl_code_str[sas_loginfo.dw.code];
+			break;
+		case 2:  /* IR */
+			if (sas_loginfo.dw.code >=
+			    sizeof(ir_code_str)/sizeof(char*))
+				break;
+			code_desc = ir_code_str[sas_loginfo.dw.code];
+			if (sas_loginfo.dw.subcode >=
+			    sizeof(raid_sub_code_str)/sizeof(char*))
+			break;
+			if (sas_loginfo.dw.code == 0)
+				sub_code_desc =
+				    raid_sub_code_str[sas_loginfo.dw.subcode];
+			break;
+		default:
+			return;
 	}
 
-	if (code_desc != NULL)
+	if (sub_code_desc != NULL)
+		printk(MYIOC_s_INFO_FMT
+			"LogInfo(0x%08x): Originator={%s}, Code={%s},"
+			" SubCode={%s}\n",
+			ioc->name, log_info, originator_desc, code_desc,
+			sub_code_desc);
+	else if (code_desc != NULL)
 		printk(MYIOC_s_INFO_FMT
 			"LogInfo(0x%08x): Originator={%s}, Code={%s},"
 			" SubCode(0x%04x)\n",
-			ioc->name,
-			log_info,
-			originator_str[sas_loginfo.dw.originator],
-			code_desc,
+			ioc->name, log_info, originator_desc, code_desc,
 			sas_loginfo.dw.subcode);
 	else
 		printk(MYIOC_s_INFO_FMT
 			"LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
 			" SubCode(0x%04x)\n",
-			ioc->name,
-			log_info,
-			originator_str[sas_loginfo.dw.originator],
-			sas_loginfo.dw.code,
-			sas_loginfo.dw.subcode);
+			ioc->name, log_info, originator_desc,
+			sas_loginfo.dw.code, sas_loginfo.dw.subcode);
 }
 
+#ifdef MPT_DEBUG_REPLY
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *	mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
+ *	mpt_iocstatus_info_config - IOCSTATUS information for config pages
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	ioc_status: U32 IOCStatus word from IOC
+ *	@mf: Pointer to MPT request frame
+ *
+ *	Refer to lsi/mpi.h.
+ **/
+static void
+mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
+{
+	Config_t *pReq = (Config_t *)mf;
+	char extend_desc[EVENT_DESCR_STR_SZ];
+	char *desc = NULL;
+	u32 form;
+	u8 page_type;
+
+	if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
+		page_type = pReq->ExtPageType;
+	else
+		page_type = pReq->Header.PageType;
+
+	/*
+	 * ignore invalid page messages for GET_NEXT_HANDLE
+	 */
+	form = le32_to_cpu(pReq->PageAddress);
+	if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
+		if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
+		    page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
+		    page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
+			if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
+				MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
+				return;
+		}
+		if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
+			if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
+				MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
+				return;
+	}
+
+	snprintf(extend_desc, EVENT_DESCR_STR_SZ,
+	    "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
+	    page_type, pReq->Header.PageNumber, pReq->Action, form);
+
+	switch (ioc_status) {
+
+	case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
+		desc = "Config Page Invalid Action";
+		break;
+
+	case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
+		desc = "Config Page Invalid Type";
+		break;
+
+	case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
+		desc = "Config Page Invalid Page";
+		break;
+
+	case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
+		desc = "Config Page Invalid Data";
+		break;
+
+	case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
+		desc = "Config Page No Defaults";
+		break;
+
+	case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
+		desc = "Config Page Can't Commit";
+		break;
+	}
+
+	if (!desc)
+		return;
+
+	printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
+	    ioc->name, ioc_status, desc, extend_desc);
+}
+
+/**
+ *	mpt_iocstatus_info - IOCSTATUS information returned from IOC.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@ioc_status: U32 IOCStatus word from IOC
  *	@mf: Pointer to MPT request frame
  *
  *	Refer to lsi/mpi.h.
- */
+ **/
 static void
-mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
+mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
 {
 	u32 status = ioc_status & MPI_IOCSTATUS_MASK;
 	char *desc = NULL;
 
 	switch (status) {
+
+/****************************************************************************/
+/*  Common IOCStatus values for all replies                                 */
+/****************************************************************************/
+
 	case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
 		desc = "Invalid Function";
 		break;
@@ -6322,84 +6790,180 @@
 		desc = "Invalid State";
 		break;
 
+/****************************************************************************/
+/*  Config IOCStatus values                                                 */
+/****************************************************************************/
+
 	case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
 	case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
 	case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
 	case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
 	case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
 	case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
-		/* No message for Config IOCStatus values */
+		mpt_iocstatus_info_config(ioc, status, mf);
 		break;
 
+/****************************************************************************/
+/*  SCSIIO Reply (SPI, FCP, SAS) initiator values                           */
+/*                                                                          */
+/*  Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
+/*                                                                          */
+/****************************************************************************/
+
 	case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
-		/* No message for recovered error
-		desc = "SCSI Recovered Error";
-		*/
-		break;
-
-	case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
-		desc = "SCSI Invalid Bus";
-		break;
-
-	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
-		desc = "SCSI Invalid TargetID";
-		break;
-
-	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
-	  {
-		SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
-		U8 cdb = pScsiReq->CDB[0];
-		if (cdb != 0x12) { /* Inquiry is issued for device scanning */
-			desc = "SCSI Device Not There";
-		}
-		break;
-	  }
-
-	case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
-		desc = "SCSI Data Overrun";
-		break;
-
 	case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
-		/* This error is checked in scsi_io_done(). Skip.
-		desc = "SCSI Data Underrun";
-		*/
-		break;
-
+	case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
+	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
+	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
+	case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
 	case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
-		desc = "SCSI I/O Data Error";
-		break;
-
 	case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
-		desc = "SCSI Protocol Error";
-		break;
-
 	case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
-		desc = "SCSI Task Terminated";
-		break;
-
 	case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
-		desc = "SCSI Residual Mismatch";
-		break;
-
 	case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
-		desc = "SCSI Task Management Failed";
-		break;
-
 	case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
-		desc = "SCSI IOC Terminated";
+	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
 		break;
 
-	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
-		desc = "SCSI Ext Terminated";
+/****************************************************************************/
+/*  SCSI Target values                                                      */
+/****************************************************************************/
+
+	case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
+		desc = "Target: Priority IO";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
+		desc = "Target: Invalid Port";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
+		desc = "Target Invalid IO Index:";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
+		desc = "Target: Aborted";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
+		desc = "Target: No Conn Retryable";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
+		desc = "Target: No Connection";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
+		desc = "Target: Transfer Count Mismatch";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
+		desc = "Target: STS Data not Sent";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
+		desc = "Target: Data Offset Error";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
+		desc = "Target: Too Much Write Data";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
+		desc = "Target: IU Too Short";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
+		desc = "Target: ACK NAK Timeout";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
+		desc = "Target: Nak Received";
+		break;
+
+/****************************************************************************/
+/*  Fibre Channel Direct Access values                                      */
+/****************************************************************************/
+
+	case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
+		desc = "FC: Aborted";
+		break;
+
+	case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
+		desc = "FC: RX ID Invalid";
+		break;
+
+	case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
+		desc = "FC: DID Invalid";
+		break;
+
+	case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
+		desc = "FC: Node Logged Out";
+		break;
+
+	case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
+		desc = "FC: Exchange Canceled";
+		break;
+
+/****************************************************************************/
+/*  LAN values                                                              */
+/****************************************************************************/
+
+	case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
+		desc = "LAN: Device not Found";
+		break;
+
+	case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
+		desc = "LAN: Device Failure";
+		break;
+
+	case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
+		desc = "LAN: Transmit Error";
+		break;
+
+	case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
+		desc = "LAN: Transmit Aborted";
+		break;
+
+	case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
+		desc = "LAN: Receive Error";
+		break;
+
+	case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
+		desc = "LAN: Receive Aborted";
+		break;
+
+	case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
+		desc = "LAN: Partial Packet";
+		break;
+
+	case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
+		desc = "LAN: Canceled";
+		break;
+
+/****************************************************************************/
+/*  Serial Attached SCSI values                                             */
+/****************************************************************************/
+
+	case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
+		desc = "SAS: SMP Request Failed";
+		break;
+
+	case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
+		desc = "SAS: SMP Data Overrun";
 		break;
 
 	default:
 		desc = "Others";
 		break;
 	}
-	if (desc != NULL)
-		printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
+
+	if (!desc)
+		return;
+
+	printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc);
 }
+#endif
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 EXPORT_SYMBOL(mpt_attach);
@@ -6434,6 +6998,7 @@
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
 EXPORT_SYMBOL(mptbase_sas_persist_operation);
+EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index e316708..e3a3927 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -75,8 +75,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2007 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.04.03"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.03"
+#define MPT_LINUX_VERSION_COMMON	"3.04.04"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.04"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -172,6 +172,9 @@
 #define MPT_SCSI_SG_DEPTH	40
 #endif
 
+/* debug print string length used for events and iocstatus */
+# define EVENT_DESCR_STR_SZ             100
+
 #ifdef __KERNEL__	/* { */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
@@ -334,8 +337,8 @@
 	struct scsi_target	*starget;
 	u8			 tflags;
 	u8			 ioc_id;
-	u8			 target_id;
-	u8			 bus_id;
+	u8			 id;
+	u8			 channel;
 	u8			 minSyncFactor;	/* 0xFF is async */
 	u8			 maxOffset;	/* 0 if async */
 	u8			 maxWidth;	/* 0 if narrow, 1 if wide */
@@ -344,13 +347,12 @@
 	u8			 type;		/* byte 0 of Inquiry data */
 	u8			 deleted;	/* target in process of being removed */
 	u32			 num_luns;
-	u32			 luns[8];		/* Max LUNs is 256 */
 } VirtTarget;
 
 typedef struct _VirtDevice {
 	VirtTarget		*vtarget;
 	u8			 configured_lun;
-	u32			 lun;
+	int			 lun;
 } VirtDevice;
 
 /*
@@ -412,7 +414,7 @@
 	u8			 rsvd;
 	u8			 status;	/* current command status */
 	u8			 reset;		/* 1 if bus reset allowed */
-	u8			 target;	/* target for reset */
+	u8			 id;		/* target for reset */
 	struct mutex		 ioctl_mutex;
 } MPT_IOCTL;
 
@@ -483,10 +485,24 @@
 						 */
 }SasCfgData;
 
+/*
+ * Inactive volume link list of raid component data
+ * @inactive_list
+ */
+struct inactive_raid_component_info {
+	struct 	 list_head list;
+	u8		 volumeID;		/* volume target id */
+	u8		 volumeBus;		/* volume channel */
+	IOC_3_PHYS_DISK	 d;			/* phys disk info */
+};
+
 typedef	struct _RaidCfgData {
 	IOCPage2_t	*pIocPg2;		/* table of Raid Volumes */
 	IOCPage3_t	*pIocPg3;		/* table of physical disks */
-	int		 isRaid;		/* bit field, 1 if RAID */
+	struct semaphore	inactive_list_mutex;
+	struct list_head	inactive_list; /* link list for physical
+						disk that belong in
+						inactive volumes */
 }RaidCfgData;
 
 typedef struct _FcCfgData {
@@ -528,6 +544,8 @@
 	u32			 mem_phys;	/* == f4020000 (mmap) */
 	u32			 pio_mem_phys;	/* Programmed IO (downloadboot) */
 	int			 mem_size;	/* mmap memory size */
+	int			 number_of_buses;
+	int			 devices_per_bus;
 	int			 alloc_total;
 	u32			 last_state;
 	int			 active;
@@ -607,6 +625,8 @@
 	u8			 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */
 	LANPage0_t		 lan_cnfg_page0;
 	LANPage1_t		 lan_cnfg_page1;
+
+	u8			 ir_firmware; /* =1 if IR firmware detected */
 	/*
 	 * Description: errata_flag_1064
 	 * If a PCIX read occurs within 1 or 2 cycles after the chip receives
@@ -790,12 +810,6 @@
 #define ddvprintk(x)
 #endif
 
-#ifdef MPT_DEBUG_NEGO
-#define dnegoprintk(x)  printk x
-#else
-#define dnegoprintk(x)
-#endif
-
 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
 #define ddvtprintk(x)  printk x
 #else
@@ -957,7 +971,6 @@
 	int			  port;
 	u32			  pad0;
 	struct scsi_cmnd	**ScsiLookup;
-	VirtTarget		**Targets;
 	MPT_LOCAL_REPLY		 *pLocal;		/* used for internal commands */
 	struct timer_list	  timer;
 		/* Pool of memory for holding SCpnts before doing
@@ -981,6 +994,7 @@
 	int			  scandv_wait_done;
 	long			  last_queue_full;
 	u16			  tm_iocstatus;
+	struct list_head	  target_reset_list;
 } MPT_SCSI_HOST;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1046,6 +1060,7 @@
 extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc);
 extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
 extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+extern int	 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk);
 
 /*
  *  Public data decl's...
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 504632d..9d0f304 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -5,7 +5,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -313,7 +313,7 @@
 		 */
 		dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
 			 ioctl->ioc->name));
-		mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
+		mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP);
 	}
 	return;
 
@@ -361,7 +361,7 @@
 			ioctl->ioc->name, mf));
 
 	pScsiTm = (SCSITaskMgmt_t *) mf;
-	pScsiTm->TargetID = ioctl->target;
+	pScsiTm->TargetID = ioctl->id;
 	pScsiTm->Bus = hd->port;	/* 0 */
 	pScsiTm->ChainOffset = 0;
 	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
@@ -1159,15 +1159,12 @@
 	struct mpt_ioctl_iocinfo *karg;
 	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
-	struct Scsi_Host	*sh;
-	MPT_SCSI_HOST		*hd;
 	int			iocnum;
-	int			numDevices = 0;
-	unsigned int		max_id;
-	int			ii;
 	unsigned int		port;
 	int			cim_rev;
 	u8			revision;
+	struct scsi_device 	*sdev;
+	VirtDevice		*vdev;
 
 	dctlprintk((": mptctl_getiocinfo called.\n"));
 	/* Add of PCI INFO results in unaligned access for
@@ -1257,23 +1254,16 @@
 
 	/* Get number of devices
          */
-	if ((sh = ioc->sh) != NULL) {
-		 /* sh->max_id = maximum target ID + 1
-		 */
-		max_id = sh->max_id - 1;
-		hd = (MPT_SCSI_HOST *) sh->hostdata;
-
-		/* Check all of the target structures and
-		 * keep a counter.
-		 */
-		if (hd && hd->Targets) {
-			for (ii = 0; ii <= max_id; ii++) {
-				if (hd->Targets[ii])
-					numDevices++;
-			}
+	karg->numDevices = 0;
+	if (ioc->sh) {
+		shost_for_each_device(sdev, ioc->sh) {
+			vdev = sdev->hostdata;
+			if (vdev->vtarget->tflags &
+			    MPT_TARGET_FLAGS_RAID_COMPONENT)
+				continue;
+			karg->numDevices++;
 		}
 	}
-	karg->numDevices = numDevices;
 
 	/* Set the BIOS and FW Version
 	 */
@@ -1319,21 +1309,16 @@
 	struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_targetinfo karg;
 	MPT_ADAPTER		*ioc;
-	struct Scsi_Host	*sh;
-	MPT_SCSI_HOST		*hd;
-	VirtTarget		*vdev;
+	VirtDevice		*vdev;
 	char			*pmem;
 	int			*pdata;
-	IOCPage2_t		*pIoc2;
-	IOCPage3_t		*pIoc3;
 	int			iocnum;
 	int			numDevices = 0;
-	unsigned int		max_id;
-	int			id, jj, indexed_lun, lun_index;
-	u32			lun;
+	int			lun;
 	int			maxWordsLeft;
 	int			numBytes;
-	u8			port, devType, bus_id;
+	u8			port;
+	struct scsi_device 	*sdev;
 
 	dctlprintk(("mptctl_gettargetinfo called.\n"));
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
@@ -1389,74 +1374,22 @@
 
 	/* Get number of devices
          */
-	if ((sh = ioc->sh) != NULL) {
-
-		max_id = sh->max_id - 1;
-		hd = (MPT_SCSI_HOST *) sh->hostdata;
-
-		/* Check all of the target structures.
-		 * Save the Id and increment the counter,
-		 * if ptr non-null.
-		 * sh->max_id = maximum target ID + 1
-		 */
-		if (hd && hd->Targets) {
-			mpt_findImVolumes(ioc);
-			pIoc2 = ioc->raid_data.pIocPg2;
-			for ( id = 0; id <= max_id; ) {
-				if ( pIoc2 && pIoc2->NumActiveVolumes ) {
-					if ( id == pIoc2->RaidVolume[0].VolumeID ) {
-						if (maxWordsLeft <= 0) {
-							printk(KERN_ERR "mptctl_gettargetinfo - "
-			"buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);
-							goto data_space_full;
-						}
-						if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
-                        				devType = 0x80;
-                    				else
-                        				devType = 0xC0;
-						bus_id = pIoc2->RaidVolume[0].VolumeBus;
-	            				numDevices++;
-                    				*pdata = ( (devType << 24) | (bus_id << 8) | id );
-						dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
-		"volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
-                    				pdata++;
-						--maxWordsLeft;
-						goto next_id;
-					} else {
-						pIoc3 = ioc->raid_data.pIocPg3;
-            					for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
-                    					if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
-								goto next_id;
-						}
-					}
-				}
-				if ( (vdev = hd->Targets[id]) ) {
-					for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
-						lun_index = (jj >> 5);
-						indexed_lun = (jj % 32);
-						lun = (1 << indexed_lun);
-						if (vdev->luns[lun_index] & lun) {
-							if (maxWordsLeft <= 0) {
-								printk(KERN_ERR "mptctl_gettargetinfo - "
-			"buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
-								goto data_space_full;
-							}
-							bus_id = vdev->bus_id;
-							numDevices++;
-                            				*pdata = ( (jj << 16) | (bus_id << 8) | id );
-							dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
-		"target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
-							pdata++;
-							--maxWordsLeft;
-						}
-					}
-				}
-next_id:
-				id++;
-			}
+	if (ioc->sh){
+		shost_for_each_device(sdev, ioc->sh) {
+			if (!maxWordsLeft)
+				continue;
+			vdev = sdev->hostdata;
+			if (vdev->vtarget->tflags &
+			    MPT_TARGET_FLAGS_RAID_COMPONENT)
+				continue;
+			lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun;
+			*pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) +
+			    (vdev->vtarget->id ));
+			pdata++;
+			numDevices++;
+			--maxWordsLeft;
 		}
 	}
-data_space_full:
 	karg.numDevices = numDevices;
 
 	/* Copy part of the data from kernel memory to user memory
@@ -1821,6 +1754,7 @@
 	int		msgContext;
 	u16		req_idx;
 	ulong 		timeout;
+	struct scsi_device *sdev;
 
 	dctlprintk(("mptctl_do_mpt_command called.\n"));
 	bufIn.kptr = bufOut.kptr = NULL;
@@ -1902,14 +1836,13 @@
 	case MPI_FUNCTION_SCSI_IO_REQUEST:
 		if (ioc->sh) {
 			SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
-			VirtTarget	*pTarget = NULL;
-			MPT_SCSI_HOST	*hd = NULL;
 			int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
 			int scsidir = 0;
-			int target = (int) pScsiReq->TargetID;
 			int dataSize;
+			u32 id;
 
-			if ((target < 0) || (target >= ioc->sh->max_id)) {
+			id = (ioc->devices_per_bus == 0) ? 256 : ioc->devices_per_bus;
+			if (pScsiReq->TargetID > id) {
 				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
 					"Target ID out of bounds. \n",
 					__FILE__, __LINE__);
@@ -1917,6 +1850,14 @@
 				goto done_free_mem;
 			}
 
+			if (pScsiReq->Bus >= ioc->number_of_buses) {
+				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+					"Target Bus out of bounds. \n",
+					__FILE__, __LINE__);
+				rc = -ENODEV;
+				goto done_free_mem;
+			}
+
 			pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
 			pScsiReq->MsgFlags |= mpt_msg_flags();
 
@@ -1936,13 +1877,15 @@
 				cpu_to_le32(ioc->sense_buf_low_dma
 				   + (req_idx * MPT_SENSE_BUFFER_ALLOC));
 
-			if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) {
-				if (hd->Targets)
-					pTarget = hd->Targets[target];
-			}
+			shost_for_each_device(sdev, ioc->sh) {
+				struct scsi_target *starget = scsi_target(sdev);
+				VirtTarget *vtarget = starget->hostdata;
 
-			if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
-				qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+				if ((pScsiReq->TargetID == vtarget->id) &&
+				    (pScsiReq->Bus == vtarget->channel) &&
+				    (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+					qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+			}
 
 			/* Have the IOCTL driver set the direction based
 			 * on the dataOutSize (ordering issue with Sparc).
@@ -1959,7 +1902,7 @@
 			pScsiReq->DataLength = cpu_to_le32(dataSize);
 
 			ioc->ioctl->reset = MPTCTL_RESET_OK;
-			ioc->ioctl->target = target;
+			ioc->ioctl->id = pScsiReq->TargetID;
 
 		} else {
 			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
@@ -2038,7 +1981,7 @@
 			pScsiReq->DataLength = cpu_to_le32(dataSize);
 
 			ioc->ioctl->reset = MPTCTL_RESET_OK;
-			ioc->ioctl->target = pScsiReq->TargetID;
+			ioc->ioctl->id = pScsiReq->TargetID;
 		} else {
 			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
 				"SCSI driver is not loaded. \n",
@@ -2719,7 +2662,7 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-static struct file_operations mptctl_fops = {
+static const struct file_operations mptctl_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.release =	mptctl_release,
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index e65a1cf..f7e72c5 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index c819c23..0caaf64 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -53,7 +53,6 @@
 #include <linux/delay.h>	/* for mdelay */
 #include <linux/interrupt.h>	/* needed for in_interrupt() proto */
 #include <linux/reboot.h>	/* notifier code */
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/sort.h>
 
@@ -86,6 +85,12 @@
 				     " return following a device loss event."
 				     "  Default=60.");
 
+/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
+#define MPTFC_MAX_LUN (16895)
+static int max_lun = MPTFC_MAX_LUN;
+module_param(max_lun, int, 0);
+MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+
 static int	mptfcDoneCtx = -1;
 static int	mptfcTaskCtx = -1;
 static int	mptfcInternalCtx = -1; /* Used only for internal commands */
@@ -292,10 +297,9 @@
 	U32			 port_id = 0xffffff;
 	int			 num_targ = 0;
 	int			 max_bus = ioc->facts.MaxBuses;
-	int			 max_targ = ioc->facts.MaxDevices;
+	int			 max_targ;
 
-	if (max_bus == 0 || max_targ == 0)
-		goto out;
+	max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
 
 	data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
 	p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
@@ -467,8 +471,8 @@
 			if (ri->starget) {
 				vtarget = ri->starget->hostdata;
 				if (vtarget) {
-					vtarget->target_id = pg0->CurrentTargetID;
-					vtarget->bus_id = pg0->CurrentBus;
+					vtarget->id = pg0->CurrentTargetID;
+					vtarget->channel = pg0->CurrentBus;
 				}
 			}
 			*((struct mptfc_rport_info **)rport->dd_data) = ri;
@@ -540,8 +544,8 @@
 	if (rport) {
 		ri = *((struct mptfc_rport_info **)rport->dd_data);
 		if (ri) {	/* better be! */
-			vtarget->target_id = ri->pg0.CurrentTargetID;
-			vtarget->bus_id = ri->pg0.CurrentBus;
+			vtarget->id = ri->pg0.CurrentTargetID;
+			vtarget->channel = ri->pg0.CurrentBus;
 			ri->starget = starget;
 			rc = 0;
 		}
@@ -592,7 +596,6 @@
 	if (vtarget->num_luns == 0) {
 		vtarget->ioc_id = hd->ioc->id;
 		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
-		hd->Targets[sdev->id] = vtarget;
 	}
 
 	vdev->vtarget = vtarget;
@@ -630,16 +633,17 @@
 	struct mptfc_rport_info	*ri;
 	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
 	int		err;
+	VirtDevice	*vdev = SCpnt->device->hostdata;
 
-	err = fc_remote_port_chkready(rport);
-	if (unlikely(err)) {
-		SCpnt->result = err;
+	if (!vdev || !vdev->vtarget) {
+		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
 		return 0;
 	}
 
-	if (!SCpnt->device->hostdata) {	/* vdev */
-		SCpnt->result = DID_NO_CONNECT << 16;
+	err = fc_remote_port_chkready(rport);
+	if (unlikely(err)) {
+		SCpnt->result = err;
 		done(SCpnt);
 		return 0;
 	}
@@ -1143,7 +1147,7 @@
 		printk(MYIOC_s_WARN_FMT
 			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
 			ioc->name, ioc);
-		return -ENODEV;
+		return 0;
 	}
 
 	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
@@ -1173,10 +1177,9 @@
 	/* set 16 byte cdb's */
 	sh->max_cmd_len = 16;
 
-	sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
+	sh->max_id = ioc->pfacts->MaxDevices;
+	sh->max_lun = max_lun;
 
-	sh->max_lun = MPT_LAST_LUN + 1;
-	sh->max_channel = 0;
 	sh->this_id = ioc->pfacts[0].PortSCSIID;
 
 	/* Required entry.
@@ -1230,19 +1233,6 @@
 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
 		 ioc->name, hd->ScsiLookup));
 
-	/* Allocate memory for the device structures.
-	 * A non-Null pointer at an offset
-	 * indicates a device exists.
-	 * max_id = 1 + maximum id (hosts.h)
-	 */
-	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
-	if (!hd->Targets) {
-		error = -ENOMEM;
-		goto out_mptfc_probe;
-	}
-
-	dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
-
 	/* Clear the TM flags
 	 */
 	hd->tmPending = 0;
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 2936204..b691292 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -5,6 +5,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 2000-2007 LSI Logic Corporation
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h
index 70ab75e..fe438bf 100644
--- a/drivers/message/fusion/mptlan.h
+++ b/drivers/message/fusion/mptlan.h
@@ -5,6 +5,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 2000-2007 LSI Logic Corporation
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 09e9a9d..404c014 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *  Copyright (c) 2005-2007 Dell
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -48,7 +48,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/jiffies.h>
 #include <linux/workqueue.h>
 #include <linux/delay.h>	/* for mdelay */
 
@@ -83,17 +83,31 @@
 		" Clear persistency table: enable=1  "
 		"(default=MPTSCSIH_PT_CLEAR=0)");
 
+/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
+#define MPTSAS_MAX_LUN (16895)
+static int max_lun = MPTSAS_MAX_LUN;
+module_param(max_lun, int, 0);
+MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+
 static int	mptsasDoneCtx = -1;
 static int	mptsasTaskCtx = -1;
 static int	mptsasInternalCtx = -1; /* Used only for internal commands */
 static int	mptsasMgmtCtx = -1;
 
+static void mptsas_hotplug_work(struct work_struct *work);
+
+struct mptsas_target_reset_event {
+	struct list_head 	list;
+	EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
+	u8	target_reset_issued;
+};
 
 enum mptsas_hotplug_action {
 	MPTSAS_ADD_DEVICE,
 	MPTSAS_DEL_DEVICE,
 	MPTSAS_ADD_RAID,
 	MPTSAS_DEL_RAID,
+	MPTSAS_ADD_INACTIVE_VOLUME,
 	MPTSAS_IGNORE_EVENT,
 };
 
@@ -102,14 +116,15 @@
 	MPT_ADAPTER		*ioc;
 	enum mptsas_hotplug_action event_type;
 	u64			sas_address;
-	u32			channel;
-	u32			id;
+	u8			channel;
+	u8			id;
 	u32			device_info;
 	u16			handle;
 	u16			parent_handle;
 	u8			phy_id;
-	u8			phys_disk_num;
-	u8			phys_disk_num_valid;
+	u8			phys_disk_num_valid;	/* hrc (hidden raid component) */
+	u8			phys_disk_num;		/* hrc - unique index*/
+	u8			hidden_raid_component;	/* hrc - don't expose*/
 };
 
 struct mptsas_discovery_event {
@@ -134,6 +149,7 @@
 	u8	port_id;	/* sas physical port this device
 				   is assoc'd with */
 	u8	id;		/* logical target id of this device */
+	u32	phys_disk_num;	/* phys disk id, for csmi-ioctls */
 	u8	channel;	/* logical bus number of this device */
 	u64	sas_address;    /* WWN of this device,
 				   SATA is assigned by HBA,expander */
@@ -153,6 +169,7 @@
 };
 
 struct mptsas_phyinfo {
+	u16	handle;			/* unique id to address this */
 	u8	phy_id; 		/* phy index */
 	u8	port_id; 		/* firmware port identifier */
 	u8	negotiated_link_rate;	/* nego'd link rate for this phy */
@@ -168,7 +185,6 @@
 
 struct mptsas_portinfo {
 	struct list_head list;
-	u16		handle;		/* unique id to address this */
 	u16		num_phys;	/* number of phys */
 	struct mptsas_phyinfo *phy_info;
 };
@@ -561,20 +577,271 @@
 	mutex_unlock(&ioc->sas_topology_mutex);
 }
 
-static void
-mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
+/**
+ * csmisas_find_vtarget
+ *
+ * @ioc
+ * @volume_id
+ * @volume_bus
+ *
+ **/
+static VirtTarget *
+mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
-	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+	struct scsi_device 		*sdev;
+	VirtDevice			*vdev;
+	VirtTarget 			*vtarget = NULL;
 
-	if (mptscsih_TMHandler(hd,
-	     MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-	     vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) {
-		hd->tmPending = 0;
-		hd->tmState = TM_STATE_NONE;
-		printk(MYIOC_s_WARN_FMT
-	       "Error processing TaskMgmt id=%d TARGET_RESET\n",
-			ioc->name, vtarget->target_id);
+	shost_for_each_device(sdev, ioc->sh) {
+		if ((vdev = sdev->hostdata) == NULL)
+			continue;
+		if (vdev->vtarget->id == id &&
+		    vdev->vtarget->channel == channel)
+			vtarget = vdev->vtarget;
 	}
+	return vtarget;
+}
+
+/**
+ * mptsas_target_reset
+ *
+ * Issues TARGET_RESET to end device using handshaking method
+ *
+ * @ioc
+ * @channel
+ * @id
+ *
+ * Returns (1) success
+ *         (0) failure
+ *
+ **/
+static int
+mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	MPT_FRAME_HDR	*mf;
+	SCSITaskMgmt_t	*pScsiTm;
+
+	if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
+		dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
+		    ioc->name,__FUNCTION__, __LINE__));
+		return 0;
+	}
+
+	/* Format the Request
+	 */
+	pScsiTm = (SCSITaskMgmt_t *) mf;
+	memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
+	pScsiTm->TargetID = id;
+	pScsiTm->Bus = channel;
+	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+	pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
+
+	DBG_DUMP_TM_REQUEST_FRAME(mf);
+
+	if (mpt_send_handshake_request(ioc->TaskCtx, ioc,
+	    sizeof(SCSITaskMgmt_t), (u32 *)mf, NO_SLEEP)) {
+		mpt_free_msg_frame(ioc, mf);
+		dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n",
+		    ioc->name,__FUNCTION__, __LINE__));
+		return 0;
+	}
+
+	return 1;
+}
+
+/**
+ * mptsas_target_reset_queue
+ *
+ * Receive request for TARGET_RESET after recieving an firmware
+ * event NOT_RESPONDING_EVENT, then put command in link list
+ * and queue if task_queue already in use.
+ *
+ * @ioc
+ * @sas_event_data
+ *
+ **/
+static void
+mptsas_target_reset_queue(MPT_ADAPTER *ioc,
+    EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+{
+	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+	VirtTarget *vtarget = NULL;
+	struct mptsas_target_reset_event *target_reset_list;
+	u8		id, channel;
+
+	id = sas_event_data->TargetID;
+	channel = sas_event_data->Bus;
+
+	if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
+		return;
+
+	vtarget->deleted = 1; /* block IO */
+
+	target_reset_list = kzalloc(sizeof(*target_reset_list),
+	    GFP_ATOMIC);
+	if (!target_reset_list) {
+		dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
+		    ioc->name,__FUNCTION__, __LINE__));
+		return;
+	}
+
+	memcpy(&target_reset_list->sas_event_data, sas_event_data,
+		sizeof(*sas_event_data));
+	list_add_tail(&target_reset_list->list, &hd->target_reset_list);
+
+	if (hd->resetPending)
+		return;
+
+	if (mptsas_target_reset(ioc, channel, id)) {
+		target_reset_list->target_reset_issued = 1;
+		hd->resetPending = 1;
+	}
+}
+
+/**
+ * mptsas_dev_reset_complete
+ *
+ * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
+ * enable work queue to finish off removing device from upper layers.
+ * then send next TARGET_RESET in the queue.
+ *
+ * @ioc
+ *
+ **/
+static void
+mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
+{
+	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+        struct list_head *head = &hd->target_reset_list;
+	struct mptsas_target_reset_event *target_reset_list;
+	struct mptsas_hotplug_event *ev;
+	EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
+	u8		id, channel;
+	__le64		sas_address;
+
+	if (list_empty(head))
+		return;
+
+	target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
+
+	sas_event_data = &target_reset_list->sas_event_data;
+	id = sas_event_data->TargetID;
+	channel = sas_event_data->Bus;
+	hd->resetPending = 0;
+
+	/*
+	 * retry target reset
+	 */
+	if (!target_reset_list->target_reset_issued) {
+		if (mptsas_target_reset(ioc, channel, id)) {
+			target_reset_list->target_reset_issued = 1;
+			hd->resetPending = 1;
+		}
+		return;
+	}
+
+	/*
+	 * enable work queue to remove device from upper layers
+	 */
+	list_del(&target_reset_list->list);
+
+	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev) {
+		dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
+		    ioc->name,__FUNCTION__, __LINE__));
+		return;
+	}
+
+	INIT_WORK(&ev->work, mptsas_hotplug_work);
+	ev->ioc = ioc;
+	ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+	ev->parent_handle =
+	    le16_to_cpu(sas_event_data->ParentDevHandle);
+	ev->channel = channel;
+	ev->id =id;
+	ev->phy_id = sas_event_data->PhyNum;
+	memcpy(&sas_address, &sas_event_data->SASAddress,
+	    sizeof(__le64));
+	ev->sas_address = le64_to_cpu(sas_address);
+	ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
+	ev->event_type = MPTSAS_DEL_DEVICE;
+	schedule_work(&ev->work);
+	kfree(target_reset_list);
+
+	/*
+	 * issue target reset to next device in the queue
+	 */
+
+	head = &hd->target_reset_list;
+	if (list_empty(head))
+		return;
+
+	target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
+	    list);
+
+	sas_event_data = &target_reset_list->sas_event_data;
+	id = sas_event_data->TargetID;
+	channel = sas_event_data->Bus;
+
+	if (mptsas_target_reset(ioc, channel, id)) {
+		target_reset_list->target_reset_issued = 1;
+		hd->resetPending = 1;
+	}
+}
+
+/**
+ * mptsas_taskmgmt_complete
+ *
+ * @ioc
+ * @mf
+ * @mr
+ *
+ **/
+static int
+mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
+{
+	mptsas_dev_reset_complete(ioc);
+	return mptscsih_taskmgmt_complete(ioc, mf, mr);
+}
+
+/**
+ * mptscsih_ioc_reset
+ *
+ * @ioc
+ * @reset_phase
+ *
+ **/
+static int
+mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+{
+	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+	struct mptsas_target_reset_event *target_reset_list, *n;
+	int rc;
+
+	rc = mptscsih_ioc_reset(ioc, reset_phase);
+
+	if (ioc->bus_type != SAS)
+		goto out;
+
+	if (reset_phase != MPT_IOC_POST_RESET)
+		goto out;
+
+	if (!hd || !hd->ioc)
+		goto out;
+
+	if (list_empty(&hd->target_reset_list))
+		goto out;
+
+	/* flush the target_reset_list */
+	list_for_each_entry_safe(target_reset_list, n,
+	    &hd->target_reset_list, list) {
+		list_del(&target_reset_list->list);
+		kfree(target_reset_list);
+	}
+
+ out:
+	return rc;
 }
 
 static int
@@ -661,8 +928,7 @@
 	struct Scsi_Host *host = dev_to_shost(&starget->dev);
 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
 	VirtTarget		*vtarget;
-	u32			target_id;
-	u32			channel;
+	u8			id, channel;
 	struct sas_rphy		*rphy;
 	struct mptsas_portinfo	*p;
 	int 			 i;
@@ -673,15 +939,19 @@
 
 	vtarget->starget = starget;
 	vtarget->ioc_id = hd->ioc->id;
-	vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
-
-	target_id = starget->id;
+	vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+	id = starget->id;
 	channel = 0;
 
-	hd->Targets[target_id] = vtarget;
-
-	if (starget->channel == MPTSAS_RAID_CHANNEL)
+	/*
+	 * RAID volumes placed beyond the last expected port.
+	 */
+	if (starget->channel == MPTSAS_RAID_CHANNEL) {
+		for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
+			if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
+				channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
 		goto out;
+	}
 
 	rphy = dev_to_rphy(starget->dev.parent);
 	mutex_lock(&hd->ioc->sas_topology_mutex);
@@ -690,18 +960,19 @@
 			if (p->phy_info[i].attached.sas_address !=
 					rphy->identify.sas_address)
 				continue;
-			target_id = p->phy_info[i].attached.id;
+			id = p->phy_info[i].attached.id;
 			channel = p->phy_info[i].attached.channel;
 			mptsas_set_starget(&p->phy_info[i], starget);
 
 			/*
 			 * Exposing hidden raid components
 			 */
-			if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
-				target_id = mptscsih_raid_id_to_num(hd,
-						target_id);
+			if (mptscsih_is_phys_disk(hd->ioc, channel, id)) {
+				id = mptscsih_raid_id_to_num(hd->ioc,
+						channel, id);
 				vtarget->tflags |=
 				    MPT_TARGET_FLAGS_RAID_COMPONENT;
+				p->phy_info[i].attached.phys_disk_num = id;
 			}
 			mutex_unlock(&hd->ioc->sas_topology_mutex);
 			goto out;
@@ -713,8 +984,8 @@
 	return -ENXIO;
 
  out:
-	vtarget->target_id = target_id;
-	vtarget->bus_id = channel;
+	vtarget->id = id;
+	vtarget->channel = channel;
 	starget->hostdata = vtarget;
 	return 0;
 }
@@ -786,7 +1057,8 @@
 			 * Exposing hidden raid components
 			 */
 			if (mptscsih_is_phys_disk(hd->ioc,
-					p->phy_info[i].attached.id))
+			    p->phy_info[i].attached.channel,
+			    p->phy_info[i].attached.id))
 				sdev->no_uld_attach = 1;
 			mutex_unlock(&hd->ioc->sas_topology_mutex);
 			goto out;
@@ -808,13 +1080,14 @@
 {
 	VirtDevice	*vdev = SCpnt->device->hostdata;
 
-//	scsi_print_command(SCpnt);
-	if (vdev->vtarget->deleted) {
+	if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
 		return 0;
 	}
 
+//	scsi_print_command(SCpnt);
+
 	return mptscsih_qcmd(SCpnt,done);
 }
 
@@ -1114,9 +1387,6 @@
 		goto out_free_consistent;
 	}
 
-	if (port_info->num_phys)
-		port_info->handle =
-		    le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
 	for (i = 0; i < port_info->num_phys; i++) {
 		mptsas_print_phy_data(&buffer->PhyData[i]);
 		port_info->phy_info[i].phy_id = i;
@@ -1125,6 +1395,8 @@
 		port_info->phy_info[i].negotiated_link_rate =
 		    buffer->PhyData[i].NegotiatedLinkRate;
 		port_info->phy_info[i].portinfo = port_info;
+		port_info->phy_info[i].handle =
+		    le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
 	}
 
  out_free_consistent:
@@ -1261,6 +1533,7 @@
 	device_info->phy_id = buffer->PhyNum;
 	device_info->port_id = buffer->PhysicalPort;
 	device_info->id = buffer->TargetID;
+	device_info->phys_disk_num = ~0;
 	device_info->channel = buffer->Bus;
 	memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
 	device_info->sas_address = le64_to_cpu(sas_address);
@@ -1325,7 +1598,6 @@
 
 	/* save config data */
 	port_info->num_phys = buffer->NumPhys;
-	port_info->handle = le16_to_cpu(buffer->DevHandle);
 	port_info->phy_info = kcalloc(port_info->num_phys,
 		sizeof(*port_info->phy_info),GFP_KERNEL);
 	if (!port_info->phy_info) {
@@ -1333,8 +1605,11 @@
 		goto out_free_consistent;
 	}
 
-	for (i = 0; i < port_info->num_phys; i++)
+	for (i = 0; i < port_info->num_phys; i++) {
 		port_info->phy_info[i].portinfo = port_info;
+		port_info->phy_info[i].handle =
+		    le16_to_cpu(buffer->DevHandle);
+	}
 
  out_free_consistent:
 	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
@@ -1702,7 +1977,6 @@
 mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
 {
 	struct mptsas_portinfo *port_info, *hba;
-	u32 handle = 0xFFFF;
 	int error = -ENOMEM, i;
 
 	hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
@@ -1714,34 +1988,36 @@
 		goto out_free_port_info;
 
 	mutex_lock(&ioc->sas_topology_mutex);
-	ioc->handle = hba->handle;
-	port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
+	ioc->handle = hba->phy_info[0].handle;
+	port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
 	if (!port_info) {
 		port_info = hba;
 		list_add_tail(&port_info->list, &ioc->sas_topology);
 	} else {
-		port_info->handle = hba->handle;
-		for (i = 0; i < hba->num_phys; i++)
+		for (i = 0; i < hba->num_phys; i++) {
 			port_info->phy_info[i].negotiated_link_rate =
 				hba->phy_info[i].negotiated_link_rate;
+			port_info->phy_info[i].handle =
+				hba->phy_info[i].handle;
+			port_info->phy_info[i].port_id =
+				hba->phy_info[i].port_id;
+		}
 		kfree(hba->phy_info);
 		kfree(hba);
 		hba = NULL;
 	}
 	mutex_unlock(&ioc->sas_topology_mutex);
-
 	for (i = 0; i < port_info->num_phys; i++) {
 		mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
 			(MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
 			 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
 
 		mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
-			(MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
-			 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
+			(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+			 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+			 port_info->phy_info[i].handle);
 		port_info->phy_info[i].identify.phy_id =
-		    port_info->phy_info[i].phy_id;
-		handle = port_info->phy_info[i].identify.handle;
-
+		    port_info->phy_info[i].phy_id = i;
 		if (port_info->phy_info[i].attached.handle)
 			mptsas_sas_device_pg0(ioc,
 				&port_info->phy_info[i].attached,
@@ -1777,12 +2053,12 @@
 		goto out;
 
 	error = mptsas_sas_expander_pg0(ioc, ex,
-		(MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
-		 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
+	    (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
+	     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
 	if (error)
 		goto out_free_port_info;
 
-	*handle = ex->handle;
+	*handle = ex->phy_info[0].handle;
 
 	mutex_lock(&ioc->sas_topology_mutex);
 	port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
@@ -1790,7 +2066,12 @@
 		port_info = ex;
 		list_add_tail(&port_info->list, &ioc->sas_topology);
 	} else {
-		port_info->handle = ex->handle;
+		for (i = 0; i < ex->num_phys; i++) {
+			port_info->phy_info[i].handle =
+				ex->phy_info[i].handle;
+			port_info->phy_info[i].port_id =
+				ex->phy_info[i].port_id;
+		}
 		kfree(ex->phy_info);
 		kfree(ex);
 		ex = NULL;
@@ -1868,8 +2149,6 @@
 	struct mptsas_portinfo buffer;
 	struct mptsas_portinfo *port_info, *n, *parent;
 	struct mptsas_phyinfo *phy_info;
-	struct scsi_target * starget;
-	VirtTarget * vtarget;
 	struct sas_port * port;
 	int i;
 	u64	expander_sas_address;
@@ -1884,26 +2163,8 @@
 
 		if (mptsas_sas_expander_pg0(ioc, &buffer,
 		     (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
-		     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
-
-			/*
-			 * Issue target reset to all child end devices
-			 * then mark them deleted to prevent further
-			 * IO going to them.
-			 */
-			phy_info = port_info->phy_info;
-			for (i = 0; i < port_info->num_phys; i++, phy_info++) {
-				starget = mptsas_get_starget(phy_info);
-				if (!starget)
-					continue;
-				vtarget = starget->hostdata;
-				if(vtarget->deleted)
-					continue;
-				vtarget->deleted = 1;
-				mptsas_target_reset(ioc, vtarget);
-				sas_port_delete(mptsas_get_port(phy_info));
-				mptsas_port_delete(phy_info->port_details);
-			}
+		     MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
+		     port_info->phy_info[0].handle)) {
 
 			/*
 			 * Obtain the port_info instance to the parent port
@@ -1972,11 +2233,13 @@
 	/*
 	  Reporting RAID volumes.
 	*/
+	if (!ioc->ir_firmware)
+		goto out;
 	if (!ioc->raid_data.pIocPg2)
 		goto out;
 	if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
 		goto out;
-	for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+	for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
 		scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
 		    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
 	}
@@ -2030,12 +2293,12 @@
 	mutex_lock(&ioc->sas_topology_mutex);
 	list_for_each_entry(port_info, &ioc->sas_topology, list) {
 		for (i = 0; i < port_info->num_phys; i++) {
-			if (port_info->phy_info[i].attached.sas_address
-			    != sas_address)
-				continue;
 			if (!mptsas_is_end_device(
 				&port_info->phy_info[i].attached))
 				continue;
+			if (port_info->phy_info[i].attached.sas_address
+			    != sas_address)
+				continue;
 			phy_info = &port_info->phy_info[i];
 			break;
 		}
@@ -2045,7 +2308,7 @@
 }
 
 static struct mptsas_phyinfo *
-mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
+mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
 	struct mptsas_portinfo *port_info;
 	struct mptsas_phyinfo *phy_info = NULL;
@@ -2054,11 +2317,40 @@
 	mutex_lock(&ioc->sas_topology_mutex);
 	list_for_each_entry(port_info, &ioc->sas_topology, list) {
 		for (i = 0; i < port_info->num_phys; i++) {
-			if (port_info->phy_info[i].attached.id != id)
-				continue;
 			if (!mptsas_is_end_device(
 				&port_info->phy_info[i].attached))
 				continue;
+			if (port_info->phy_info[i].attached.id != id)
+				continue;
+			if (port_info->phy_info[i].attached.channel != channel)
+				continue;
+			phy_info = &port_info->phy_info[i];
+			break;
+		}
+	}
+	mutex_unlock(&ioc->sas_topology_mutex);
+	return phy_info;
+}
+
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	struct mptsas_portinfo *port_info;
+	struct mptsas_phyinfo *phy_info = NULL;
+	int i;
+
+	mutex_lock(&ioc->sas_topology_mutex);
+	list_for_each_entry(port_info, &ioc->sas_topology, list) {
+		for (i = 0; i < port_info->num_phys; i++) {
+			if (!mptsas_is_end_device(
+				&port_info->phy_info[i].attached))
+				continue;
+			if (port_info->phy_info[i].attached.phys_disk_num == ~0)
+				continue;
+			if (port_info->phy_info[i].attached.phys_disk_num != id)
+				continue;
+			if (port_info->phy_info[i].attached.channel != channel)
+				continue;
 			phy_info = &port_info->phy_info[i];
 			break;
 		}
@@ -2094,6 +2386,76 @@
 			mptsas_reprobe_lun);
 }
 
+static void
+mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	CONFIGPARMS			cfg;
+	ConfigPageHeader_t		hdr;
+	dma_addr_t			dma_handle;
+	pRaidVolumePage0_t		buffer = NULL;
+	RaidPhysDiskPage0_t 		phys_disk;
+	int				i;
+	struct mptsas_hotplug_event 	*ev;
+
+	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+	cfg.pageAddr = (channel << 8) + id;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+	if (mpt_config(ioc, &cfg) != 0)
+		goto out;
+
+	if (!hdr.PageLength)
+		goto out;
+
+	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+	    &dma_handle);
+
+	if (!buffer)
+		goto out;
+
+	cfg.physAddr = dma_handle;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+	if (mpt_config(ioc, &cfg) != 0)
+		goto out;
+
+	if (!(buffer->VolumeStatus.Flags &
+	    MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
+		goto out;
+
+	if (!buffer->NumPhysDisks)
+		goto out;
+
+	for (i = 0; i < buffer->NumPhysDisks; i++) {
+
+		if (mpt_raid_phys_disk_pg0(ioc,
+		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+			continue;
+
+		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+		if (!ev) {
+			printk(KERN_WARNING "mptsas: lost hotplug event\n");
+			goto out;
+		}
+
+		INIT_WORK(&ev->work, mptsas_hotplug_work);
+		ev->ioc = ioc;
+		ev->id = phys_disk.PhysDiskID;
+		ev->channel = phys_disk.PhysDiskBus;
+		ev->phys_disk_num_valid = 1;
+		ev->phys_disk_num = phys_disk.PhysDiskNum;
+		ev->event_type = MPTSAS_ADD_DEVICE;
+		schedule_work(&ev->work);
+	}
+
+ out:
+	if (buffer)
+		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+		    dma_handle);
+}
 /*
  * Work queue thread to handle SAS hotplug events
  */
@@ -2102,6 +2464,7 @@
 {
 	struct mptsas_hotplug_event *ev =
 		container_of(work, struct mptsas_hotplug_event, work);
+
 	MPT_ADAPTER *ioc = ev->ioc;
 	struct mptsas_phyinfo *phy_info;
 	struct sas_rphy *rphy;
@@ -2114,17 +2477,43 @@
 	VirtTarget *vtarget;
 	VirtDevice *vdevice;
 
-
 	mutex_lock(&ioc->sas_discovery_mutex);
 	switch (ev->event_type) {
 	case MPTSAS_DEL_DEVICE:
 
-		phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
+		phy_info = NULL;
+		if (ev->phys_disk_num_valid) {
+			if (ev->hidden_raid_component){
+				if (mptsas_sas_device_pg0(ioc, &sas_device,
+				    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+				     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+				    (ev->channel << 8) + ev->id)) {
+					dfailprintk((MYIOC_s_ERR_FMT
+					"%s: exit at line=%d\n", ioc->name,
+						__FUNCTION__, __LINE__));
+					break;
+				}
+				phy_info = mptsas_find_phyinfo_by_sas_address(
+				    ioc, sas_device.sas_address);
+			}else
+				phy_info = mptsas_find_phyinfo_by_phys_disk_num(
+				    ioc, ev->channel, ev->phys_disk_num);
+		}
+
+		if (!phy_info)
+			phy_info = mptsas_find_phyinfo_by_target(ioc,
+			    ev->channel, ev->id);
 
 		/*
 		 * Sanity checks, for non-existing phys and remote rphys.
 		 */
-		if (!phy_info || !phy_info->port_details) {
+		if (!phy_info){
+			dfailprintk((MYIOC_s_ERR_FMT
+				"%s: exit at line=%d\n", ioc->name,
+				__FUNCTION__, __LINE__));
+			break;
+		}
+		if (!phy_info->port_details) {
 			dfailprintk((MYIOC_s_ERR_FMT
 				"%s: exit at line=%d\n", ioc->name,
 			       	__FUNCTION__, __LINE__));
@@ -2137,6 +2526,7 @@
 			       	__FUNCTION__, __LINE__));
 			break;
 		}
+
 		port = mptsas_get_port(phy_info);
 		if (!port) {
 			dfailprintk((MYIOC_s_ERR_FMT
@@ -2159,28 +2549,35 @@
 			/*
 			 * Handling  RAID components
 			 */
-			if (ev->phys_disk_num_valid) {
-				vtarget->target_id = ev->phys_disk_num;
-				vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+			if (ev->phys_disk_num_valid &&
+			    ev->hidden_raid_component) {
+				printk(MYIOC_s_INFO_FMT
+				    "RAID Hidding: channel=%d, id=%d, "
+				    "physdsk %d \n", ioc->name, ev->channel,
+				    ev->id, ev->phys_disk_num);
+				vtarget->id = ev->phys_disk_num;
+				vtarget->tflags |=
+				    MPT_TARGET_FLAGS_RAID_COMPONENT;
 				mptsas_reprobe_target(starget, 1);
-				break;
+				phy_info->attached.phys_disk_num =
+				    ev->phys_disk_num;
+			break;
 			}
-
-			vtarget->deleted = 1;
-			mptsas_target_reset(ioc, vtarget);
 		}
 
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_SSP_TARGET)
 			ds = "ssp";
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_STP_TARGET)
 			ds = "stp";
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
 			ds = "sata";
 
 		printk(MYIOC_s_INFO_FMT
 		       "removing %s device, channel %d, id %d, phy %d\n",
 		       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
-
 #ifdef MPT_DEBUG_SAS_WIDE
 		dev_printk(KERN_DEBUG, &port->dev,
 		    "delete port (%d)\n", port->port_identifier);
@@ -2198,14 +2595,14 @@
 		 */
 		if (mptsas_sas_device_pg0(ioc, &sas_device,
 		    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
-		     MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
+		     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+			(ev->channel << 8) + ev->id)) {
 				dfailprintk((MYIOC_s_ERR_FMT
 					"%s: exit at line=%d\n", ioc->name,
 					__FUNCTION__, __LINE__));
 			break;
 		}
 
-		ssleep(2);
 		__mptsas_discovery_work(ioc);
 
 		phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
@@ -2219,7 +2616,8 @@
 		}
 
 		starget = mptsas_get_starget(phy_info);
-		if (starget) {
+		if (starget && (!ev->hidden_raid_component)){
+
 			vtarget = starget->hostdata;
 
 			if (!vtarget) {
@@ -2232,9 +2630,15 @@
 			 * Handling  RAID components
 			 */
 			if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
-				vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
-				vtarget->target_id = ev->id;
+				printk(MYIOC_s_INFO_FMT
+				    "RAID Exposing: channel=%d, id=%d, "
+				    "physdsk %d \n", ioc->name, ev->channel,
+				    ev->id, ev->phys_disk_num);
+				vtarget->tflags &=
+				    ~MPT_TARGET_FLAGS_RAID_COMPONENT;
+				vtarget->id = ev->id;
 				mptsas_reprobe_target(starget, 0);
+				phy_info->attached.phys_disk_num = ~0;
 			}
 			break;
 		}
@@ -2243,8 +2647,10 @@
 			dfailprintk((MYIOC_s_ERR_FMT
 				"%s: exit at line=%d\n", ioc->name,
 			       	__FUNCTION__, __LINE__));
+			if (ev->channel) printk("%d\n", __LINE__);
 			break;
 		}
+
 		port = mptsas_get_port(phy_info);
 		if (!port) {
 			dfailprintk((MYIOC_s_ERR_FMT
@@ -2252,15 +2658,17 @@
 			       	__FUNCTION__, __LINE__));
 			break;
 		}
-
 		memcpy(&phy_info->attached, &sas_device,
 		    sizeof(struct mptsas_devinfo));
 
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_SSP_TARGET)
 			ds = "ssp";
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_STP_TARGET)
 			ds = "stp";
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
 			ds = "sata";
 
 		printk(MYIOC_s_INFO_FMT
@@ -2301,19 +2709,21 @@
 		break;
 	case MPTSAS_DEL_RAID:
 		sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
-	    	    ev->id, 0);
+		    ev->id, 0);
 		if (!sdev)
 			break;
 		printk(MYIOC_s_INFO_FMT
 		       "removing raid volume, channel %d, id %d\n",
 		       ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
 		vdevice = sdev->hostdata;
-		vdevice->vtarget->deleted = 1;
-		mptsas_target_reset(ioc, vdevice->vtarget);
 		scsi_remove_device(sdev);
 		scsi_device_put(sdev);
 		mpt_findImVolumes(ioc);
 		break;
+	case MPTSAS_ADD_INACTIVE_VOLUME:
+		mptsas_adding_inactive_raid_components(ioc,
+		    ev->channel, ev->id);
+		break;
 	case MPTSAS_IGNORE_EVENT:
 	default:
 		break;
@@ -2321,7 +2731,6 @@
 
 	mutex_unlock(&ioc->sas_discovery_mutex);
 	kfree(ev);
-
 }
 
 static void
@@ -2339,8 +2748,12 @@
 		return;
 
 	switch (sas_event_data->ReasonCode) {
-	case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
 	case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+
+		mptsas_target_reset_queue(ioc, sas_event_data);
+		break;
+
+	case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
 		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 		if (!ev) {
 			printk(KERN_WARNING "mptsas: lost hotplug event\n");
@@ -2375,15 +2788,20 @@
 		    mptsas_persist_clear_table);
 		schedule_work(&ioc->sas_persist_task);
 		break;
+	/*
+	 * TODO, handle other events
+	 */
 	case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
-	/* TODO */
+	case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
 	case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
-	/* TODO */
+	case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
+	case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
+	case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
+	case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
 	default:
 		break;
 	}
 }
-
 static void
 mptsas_send_raid_event(MPT_ADAPTER *ioc,
 		EVENT_DATA_RAID *raid_event_data)
@@ -2404,31 +2822,36 @@
 	INIT_WORK(&ev->work, mptsas_hotplug_work);
 	ev->ioc = ioc;
 	ev->id = raid_event_data->VolumeID;
+	ev->channel = raid_event_data->VolumeBus;
 	ev->event_type = MPTSAS_IGNORE_EVENT;
 
 	switch (raid_event_data->ReasonCode) {
 	case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+		ev->phys_disk_num_valid = 1;
+		ev->phys_disk_num = raid_event_data->PhysDiskNum;
 		ev->event_type = MPTSAS_ADD_DEVICE;
 		break;
 	case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
-		ioc->raid_data.isRaid = 1;
 		ev->phys_disk_num_valid = 1;
 		ev->phys_disk_num = raid_event_data->PhysDiskNum;
+		ev->hidden_raid_component = 1;
 		ev->event_type = MPTSAS_DEL_DEVICE;
 		break;
 	case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
 		switch (state) {
 		case MPI_PD_STATE_ONLINE:
-			ioc->raid_data.isRaid = 1;
+		case MPI_PD_STATE_NOT_COMPATIBLE:
 			ev->phys_disk_num_valid = 1;
 			ev->phys_disk_num = raid_event_data->PhysDiskNum;
+			ev->hidden_raid_component = 1;
 			ev->event_type = MPTSAS_ADD_DEVICE;
 			break;
 		case MPI_PD_STATE_MISSING:
-		case MPI_PD_STATE_NOT_COMPATIBLE:
 		case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
 		case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
 		case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
+			ev->phys_disk_num_valid = 1;
+			ev->phys_disk_num = raid_event_data->PhysDiskNum;
 			ev->event_type = MPTSAS_DEL_DEVICE;
 			break;
 		default:
@@ -2485,6 +2908,35 @@
 	schedule_work(&ev->work);
 };
 
+/*
+ * mptsas_send_ir2_event - handle exposing hidden disk when
+ * an inactive raid volume is added
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @ir2_data
+ *
+ */
+static void
+mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
+{
+	struct mptsas_hotplug_event *ev;
+
+	if (ir2_data->ReasonCode !=
+	    MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
+		return;
+
+	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev)
+		return;
+
+	INIT_WORK(&ev->work, mptsas_hotplug_work);
+	ev->ioc = ioc;
+	ev->id = ir2_data->TargetID;
+	ev->channel = ir2_data->Bus;
+	ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
+
+	schedule_work(&ev->work);
+};
 
 static int
 mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
@@ -2524,6 +2976,10 @@
 		mptsas_send_discovery_event(ioc,
 			(EVENT_DATA_SAS_DISCOVERY *)reply->Data);
 		break;
+	case MPI_EVENT_IR2:
+		mptsas_send_ir2_event(ioc,
+		    (PTR_MPI_EVENT_DATA_IR2)reply->Data);
+		break;
 	default:
 		rc = mptscsih_event_process(ioc, reply);
 		break;
@@ -2611,12 +3067,11 @@
 	/* set 16 byte cdb's */
 	sh->max_cmd_len = 16;
 
-	sh->max_id = ioc->pfacts->MaxDevices + 1;
+	sh->max_id = ioc->pfacts[0].PortSCSIID;
+	sh->max_lun = max_lun;
 
 	sh->transportt = mptsas_transport_template;
 
-	sh->max_lun = MPT_LAST_LUN + 1;
-	sh->max_channel = 0;
 	sh->this_id = ioc->pfacts[0].PortSCSIID;
 
 	/* Required entry.
@@ -2659,8 +3114,6 @@
 		sh->sg_tablesize = numSGE;
 	}
 
-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
 	hd = (MPT_SCSI_HOST *) sh->hostdata;
 	hd->ioc = ioc;
 
@@ -2676,19 +3129,6 @@
 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
 		 ioc->name, hd->ScsiLookup));
 
-	/* Allocate memory for the device structures.
-	 * A non-Null pointer at an offset
-	 * indicates a device exists.
-	 * max_id = 1 + maximum id (hosts.h)
-	 */
-	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
-	if (!hd->Targets) {
-		error = -ENOMEM;
-		goto out_mptsas_probe;
-	}
-
-	dprintk((KERN_INFO "  vtarget @ %p\n", hd->Targets));
-
 	/* Clear the TM flags
 	 */
 	hd->tmPending = 0;
@@ -2713,15 +3153,17 @@
 
 	ioc->sas_data.ptClear = mpt_pt_clear;
 
+	init_waitqueue_head(&hd->scandv_waitq);
+	hd->scandv_wait_done = 0;
+	hd->last_queue_full = 0;
+	INIT_LIST_HEAD(&hd->target_reset_list);
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
 	if (ioc->sas_data.ptClear==1) {
 		mptbase_sas_persist_operation(
 		    ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
 	}
 
-	init_waitqueue_head(&hd->scandv_waitq);
-	hd->scandv_wait_done = 0;
-	hd->last_queue_full = 0;
-
 	error = scsi_add_host(sh, &ioc->pcidev->dev);
 	if (error) {
 		dprintk((KERN_ERR MYNAM
@@ -2745,7 +3187,7 @@
 	struct mptsas_portinfo *p, *n;
 	int i;
 
-	ioc->sas_discovery_ignore_events=1;
+	ioc->sas_discovery_ignore_events = 1;
 	sas_remove_host(ioc->sh);
 
 	mutex_lock(&ioc->sas_topology_mutex);
@@ -2800,7 +3242,7 @@
 		return -ENODEV;
 
 	mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
-	mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
+	mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
 	mptsasInternalCtx =
 		mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
 	mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
@@ -2810,7 +3252,7 @@
 		  ": Registered for IOC event notifications\n"));
 	}
 
-	if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
+	if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) {
 		dprintk((KERN_INFO MYNAM
 		  ": Registered for IOC reset notifications\n"));
 	}
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index f0cca3e..2a3e9e66 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -54,7 +54,6 @@
 #include <linux/delay.h>	/* for mdelay */
 #include <linux/interrupt.h>	/* needed for in_interrupt() proto */
 #include <linux/reboot.h>	/* notifier code */
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 
 #include <scsi/scsi.h>
@@ -79,43 +78,6 @@
 MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-typedef struct _BIG_SENSE_BUF {
-	u8		data[MPT_SENSE_BUFFER_ALLOC];
-} BIG_SENSE_BUF;
-
-#define MPT_SCANDV_GOOD			(0x00000000) /* must be 0 */
-#define MPT_SCANDV_DID_RESET		(0x00000001)
-#define MPT_SCANDV_SENSE		(0x00000002)
-#define MPT_SCANDV_SOME_ERROR		(0x00000004)
-#define MPT_SCANDV_SELECTION_TIMEOUT	(0x00000008)
-#define MPT_SCANDV_ISSUE_SENSE		(0x00000010)
-#define MPT_SCANDV_FALLBACK		(0x00000020)
-
-#define MPT_SCANDV_MAX_RETRIES		(10)
-
-#define MPT_ICFLAG_BUF_CAP	0x01	/* ReadBuffer Read Capacity format */
-#define MPT_ICFLAG_ECHO		0x02	/* ReadBuffer Echo buffer format */
-#define MPT_ICFLAG_EBOS		0x04	/* ReadBuffer Echo buffer has EBOS */
-#define MPT_ICFLAG_PHYS_DISK	0x08	/* Any SCSI IO but do Phys Disk Format */
-#define MPT_ICFLAG_TAGGED_CMD	0x10	/* Do tagged IO */
-#define MPT_ICFLAG_DID_RESET	0x20	/* Bus Reset occurred with this command */
-#define MPT_ICFLAG_RESERVED	0x40	/* Reserved has been issued */
-
-typedef struct _internal_cmd {
-	char		*data;		/* data pointer */
-	dma_addr_t	data_dma;	/* data dma address */
-	int		size;		/* transfer size */
-	u8		cmd;		/* SCSI Op Code */
-	u8		bus;		/* bus number */
-	u8		id;		/* SCSI ID (virtual) */
-	u8		lun;
-	u8		flags;		/* Bit Field - See above */
-	u8		physDiskNum;	/* Phys disk number, -1 else */
-	u8		rsvd2;
-	u8		rsvd;
-} INTERNAL_CMD;
-
 /*
  *  Other private/forward protos...
  */
@@ -131,14 +93,11 @@
 static int	mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
 static int	SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
 
-static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
 
 int		mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 int		mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
-static void	mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
-static void	mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
-static int	mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
 int		mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static int	mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
 static void	mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
@@ -517,16 +476,100 @@
 
 	SEPMsg = (SEPRequest_t *)mf;
 	SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
-	SEPMsg->Bus = vtarget->bus_id;
-	SEPMsg->TargetID = vtarget->target_id;
+	SEPMsg->Bus = vtarget->channel;
+	SEPMsg->TargetID = vtarget->id;
 	SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
 	SEPMsg->SlotStatus = SlotStatus;
 	devtverboseprintk((MYIOC_s_WARN_FMT
-	    "Sending SEP cmd=%x id=%d bus=%d\n",
-	    ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
+	    "Sending SEP cmd=%x channel=%d id=%d\n",
+	    ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
 	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
 }
 
+#ifdef MPT_DEBUG_REPLY
+/**
+ *	mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@ioc_status: U32 IOCStatus word from IOC
+ *	@scsi_status: U8 sam status from target
+ *	@scsi_state: U8 scsi state
+ *	@sc: original scsi cmnd pointer
+ *	@mf: Pointer to MPT request frame
+ *
+ *	Refer to lsi/mpi.h.
+ **/
+static void
+mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status,
+    u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc)
+{
+	char extend_desc[EVENT_DESCR_STR_SZ];
+	char *desc = NULL;
+
+	switch (ioc_status) {
+
+	case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
+		desc = "SCSI Invalid Bus";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
+		desc = "SCSI Invalid TargetID";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
+		/*
+		 * Inquiry is issued for device scanning
+		 */
+		if (sc->cmnd[0] != 0x12)
+			desc = "SCSI Device Not There";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
+		desc = "SCSI Data Overrun";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
+		desc = "SCSI I/O Data Error";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
+		desc = "SCSI Protocol Error";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
+		desc = "SCSI Task Terminated";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
+		desc = "SCSI Residual Mismatch";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
+		desc = "SCSI Task Management Failed";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
+		desc = "SCSI IOC Terminated";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
+		desc = "SCSI Ext Terminated";
+		break;
+	}
+
+	if (!desc)
+		return;
+
+	snprintf(extend_desc, EVENT_DESCR_STR_SZ,
+	    "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh",
+		sc->device->host->host_no,
+		sc->device->channel, sc->device->id, sc->device->lun,
+		sc->cmnd[0], scsi_status, scsi_state);
+
+	printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
+	    ioc->name, ioc_status, desc, extend_desc);
+}
+#endif
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	mptscsih_io_done - Main SCSI IO callback routine registered to
@@ -613,12 +656,14 @@
 		u32	 xfer_cnt;
 		u16	 status;
 		u8	 scsi_state, scsi_status;
+		u32	 log_info;
 
 		status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
 		scsi_state = pScsiReply->SCSIState;
 		scsi_status = pScsiReply->SCSIStatus;
 		xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
 		sc->resid = sc->request_bufflen - xfer_cnt;
+		log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
 
 		/*
 		 *  if we get a data underrun indication, yet no data was
@@ -633,13 +678,6 @@
 			status = MPI_IOCSTATUS_SUCCESS;
 		}
 
-		dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
-			"IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
-			"resid=%d bufflen=%d xfer_cnt=%d\n",
-			ioc->id, sc->device->id, sc->device->lun,
-			status, scsi_state, scsi_status, sc->resid,
-			sc->request_bufflen, xfer_cnt));
-
 		if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
 			mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
 
@@ -648,9 +686,10 @@
 		 */
 		if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
 		    pScsiReply->ResponseInfo) {
-			printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
+			printk(KERN_NOTICE "[%d:%d:%d:%d] "
 			"FCP_ResponseInfo=%08xh\n",
-			ioc->id, sc->device->id, sc->device->lun,
+			sc->device->host->host_no, sc->device->channel,
+			sc->device->id, sc->device->lun,
 			le32_to_cpu(pScsiReply->ResponseInfo));
 		}
 
@@ -695,9 +734,8 @@
 			if ( ioc->bus_type == SAS ) {
 				u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
 				if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
-					u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
-					log_info &=SAS_LOGINFO_MASK;
-					if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
+					if ((log_info & SAS_LOGINFO_MASK)
+					    == SAS_LOGINFO_NEXUS_LOSS) {
 						sc->result = (DID_BUS_BUSY << 16);
 						break;
 					}
@@ -735,7 +773,8 @@
 			else /* Sufficient data transfer occurred */
 				sc->result = (DID_OK << 16) | scsi_status;
 			dreplyprintk((KERN_NOTICE
-			    "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
+			    "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
+			    sc->result, sc->device->channel, sc->device->id));
 			break;
 
 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
@@ -848,7 +887,28 @@
 
 		}	/* switch(status) */
 
-		dreplyprintk((KERN_NOTICE "  sc->result is %08xh\n", sc->result));
+#ifdef MPT_DEBUG_REPLY
+		if (sc->result) {
+
+			mptscsih_iocstatus_info_scsiio(ioc, status,
+			    scsi_status, scsi_state, sc);
+
+			dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x "
+			    "result=0x%08x\n\tiocstatus=0x%04X "
+			    "scsi_state=0x%02X scsi_status=0x%02X "
+			    "loginfo=0x%08X\n", __FUNCTION__,
+			    sc->device->host->host_no, sc->device->channel, sc->device->id,
+			    sc->device->lun, sc->cmnd[0], sc->result, status,
+			    scsi_state, scsi_status, log_info));
+
+			dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
+			    "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
+			    sc->device->host->host_no, sc->device->channel, sc->device->id,
+			    sc->device->lun, sc->resid, sc->request_bufflen,
+			    xfer_cnt));
+		}
+#endif
+
 	} /* end of address reply case */
 
 	/* Unmap the DMA buffers, if any. */
@@ -955,9 +1015,10 @@
 	int		 ii;
 	int		 max = hd->ioc->req_depth;
 	struct scsi_cmnd *sc;
+	struct scsi_lun  lun;
 
-	dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
-			vdevice->vtarget->target_id, vdevice->lun, max));
+	dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n",
+	    vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
 
 	for (ii=0; ii < max; ii++) {
 		if ((sc = hd->ScsiLookup[ii]) != NULL) {
@@ -965,10 +1026,14 @@
 			mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
 			if (mf == NULL)
 				continue;
-			dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
-					hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
-			if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
+			int_to_scsilun(vdevice->lun, &lun);
+			if ((mf->Bus != vdevice->vtarget->channel) ||
+			    (mf->TargetID != vdevice->vtarget->id) ||
+			    memcmp(lun.scsi_lun, mf->LUN, 8))
 				continue;
+			dsprintk(( "search_running: found (sc=%p, mf = %p) "
+			    "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
+			    mf, mf->Bus, mf->TargetID, vdevice->lun));
 
 			/* Cleanup
 			 */
@@ -1065,12 +1130,6 @@
 		hd->ScsiLookup = NULL;
 	}
 
-	/*
-	 * Free pointer array.
-	 */
-	kfree(hd->Targets);
-	hd->Targets = NULL;
-
 	dprintk((MYIOC_s_INFO_FMT
 	    "Free'd ScsiLookup (%d) memory\n",
 	    hd->ioc->name, sz1));
@@ -1317,14 +1376,6 @@
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
-	if ((hd->ioc->bus_type == SPI) &&
-	    vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT &&
-	    mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) {
-		SCpnt->result = DID_NO_CONNECT << 16;
-		done(SCpnt);
-		return 0;
-	}
-
 	/*
 	 *  Put together a MPT SCSI request...
 	 */
@@ -1368,8 +1419,8 @@
 
 	/* Use the above information to set up the message frame
 	 */
-	pScsiReq->TargetID = (u8) vdev->vtarget->target_id;
-	pScsiReq->Bus = vdev->vtarget->bus_id;
+	pScsiReq->TargetID = (u8) vdev->vtarget->id;
+	pScsiReq->Bus = vdev->vtarget->channel;
 	pScsiReq->ChainOffset = 0;
 	if (vdev->vtarget->tflags &  MPT_TARGET_FLAGS_RAID_COMPONENT)
 		pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
@@ -1379,14 +1430,7 @@
 	pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
 	pScsiReq->Reserved = 0;
 	pScsiReq->MsgFlags = mpt_msg_flags();
-	pScsiReq->LUN[0] = 0;
-	pScsiReq->LUN[1] = lun;
-	pScsiReq->LUN[2] = 0;
-	pScsiReq->LUN[3] = 0;
-	pScsiReq->LUN[4] = 0;
-	pScsiReq->LUN[5] = 0;
-	pScsiReq->LUN[6] = 0;
-	pScsiReq->LUN[7] = 0;
+	int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
 	pScsiReq->Control = cpu_to_le32(scsictl);
 
 	/*
@@ -1491,14 +1535,14 @@
  */
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *	mptscsih_TMHandler - Generic handler for SCSI Task Management.
  *	Fall through to mpt_HardResetHandler if: not operational, too many
  *	failed TM requests or handshake failure.
  *
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@type: Task Management type
- *	@target: Logical Target ID for reset (if appropriate)
+ *	@id: Logical Target ID for reset (if appropriate)
  *	@lun: Logical Unit for reset (if appropriate)
  *	@ctx2abort: Context for the task to be aborted (if appropriate)
  *
@@ -1507,28 +1551,17 @@
  *	Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
  *	will be active.
  *
- *	Returns 0 for SUCCESS or -1 if FAILED.
- */
+ *	Returns 0 for SUCCESS, or FAILED.
+ **/
 int
-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
+mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
 {
 	MPT_ADAPTER	*ioc;
 	int		 rc = -1;
-	int		 doTask = 1;
 	u32		 ioc_raw_state;
 	unsigned long	 flags;
 
-	/* If FW is being reloaded currently, return success to
-	 * the calling function.
-	 */
-	if (hd == NULL)
-		return 0;
-
 	ioc = hd->ioc;
-	if (ioc == NULL) {
-		printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
-		return FAILED;
-	}
 	dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
 
 	// SJR - CHECKME - Can we avoid this here?
@@ -1541,8 +1574,10 @@
 	spin_unlock_irqrestore(&ioc->diagLock, flags);
 
 	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
-	 *  If we time out and not bus reset, then we return a FAILED status to the caller.
-	 *  The call to mptscsih_tm_pending_wait() will set the pending flag if we are
+	 *  If we time out and not bus reset, then we return a FAILED status
+	 *  to the caller.
+	 *  The call to mptscsih_tm_pending_wait() will set the pending flag
+	 *  if we are
 	 *  successful. Otherwise, reload the FW.
 	 */
 	if (mptscsih_tm_pending_wait(hd) == FAILED) {
@@ -1552,18 +1587,16 @@
 			   hd->ioc->name, hd->tmPending));
 			return FAILED;
 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
-			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
-			   "Timed out waiting for last TM (%d) to complete! \n",
-			   hd->ioc->name, hd->tmPending));
+			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target "
+				"reset: Timed out waiting for last TM (%d) "
+				"to complete! \n", hd->ioc->name,
+				hd->tmPending));
 			return FAILED;
 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
 			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
 			   "Timed out waiting for last TM (%d) to complete! \n",
 			   hd->ioc->name, hd->tmPending));
-			if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
-				return FAILED;
-
-			doTask = 0;
+			return FAILED;
 		}
 	} else {
 		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
@@ -1571,47 +1604,40 @@
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
 	}
 
-	/* Is operational?
-	 */
 	ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
 
-#ifdef MPT_DEBUG_RESET
 	if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
 		printk(MYIOC_s_WARN_FMT
-			"TM Handler: IOC Not operational(0x%x)!\n",
-			hd->ioc->name, ioc_raw_state);
-	}
-#endif
-
-	if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
-				&& !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
-
-		/* Isse the Task Mgmt request.
-		 */
-		if (hd->hard_resets < -1)
-			hd->hard_resets++;
-		rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
-		if (rc) {
-			printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
-		} else {
-			dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
-		}
+			"TM Handler for type=%x: IOC Not operational (0x%x)!\n",
+			ioc->name, type, ioc_raw_state);
+		printk(KERN_WARNING " Issuing HardReset!!\n");
+		if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
+			printk((KERN_WARNING "TMHandler: HardReset "
+				"FAILED!!\n"));
+		return FAILED;
 	}
 
-	/* Only fall through to the HRH if this is a bus reset
+	if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
+		printk(MYIOC_s_WARN_FMT
+			"TM Handler for type=%x: ioc_state: "
+			"DOORBELL_ACTIVE (0x%x)!\n",
+			ioc->name, type, ioc_raw_state);
+		return FAILED;
+	}
+
+	/* Isse the Task Mgmt request.
 	 */
-	if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
-		ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
-		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
-			 hd->ioc->name));
-		rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
-	}
+	if (hd->hard_resets < -1)
+		hd->hard_resets++;
 
-	/*
-	 * Check IOCStatus from TM reply message
-	 */
-	 if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
-		rc = FAILED;
+	rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
+	    ctx2abort, timeout);
+	if (rc)
+		printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
+		       hd->ioc->name);
+	else
+		dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n",
+			   hd->ioc->name));
 
 	dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
 
@@ -1620,11 +1646,11 @@
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *	mptscsih_IssueTaskMgmt - Generic send Task Management function.
  *	@hd: Pointer to MPT_SCSI_HOST structure
  *	@type: Task Management type
- *	@target: Logical Target ID for reset (if appropriate)
+ *	@id: Logical Target ID for reset (if appropriate)
  *	@lun: Logical Unit for reset (if appropriate)
  *	@ctx2abort: Context for the task to be aborted (if appropriate)
  *
@@ -1633,11 +1659,11 @@
  *
  *	Not all fields are meaningfull for all task types.
  *
- *	Returns 0 for SUCCESS, -999 for "no msg frames",
- *	else other non-zero value returned.
- */
+ *	Returns 0 for SUCCESS, or FAILED.
+ *
+ **/
 static int
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
+mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
 {
 	MPT_FRAME_HDR	*mf;
 	SCSITaskMgmt_t	*pScsiTm;
@@ -1657,7 +1683,7 @@
 	/* Format the Request
 	 */
 	pScsiTm = (SCSITaskMgmt_t *) mf;
-	pScsiTm->TargetID = target;
+	pScsiTm->TargetID = id;
 	pScsiTm->Bus = channel;
 	pScsiTm->ChainOffset = 0;
 	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
@@ -1668,42 +1694,59 @@
 	pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
                     ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
 
-	for (ii= 0; ii < 8; ii++) {
-		pScsiTm->LUN[ii] = 0;
-	}
-	pScsiTm->LUN[1] = lun;
+	int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
 
 	for (ii=0; ii < 7; ii++)
 		pScsiTm->Reserved2[ii] = 0;
 
 	pScsiTm->TaskMsgContext = ctx2abort;
 
-	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
-			hd->ioc->name, ctx2abort, type));
+	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
+		"type=%d\n", hd->ioc->name, ctx2abort, type));
 
 	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
 
 	if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
-		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
-		CAN_SLEEP)) != 0) {
-		dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
-			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
-			hd->ioc, mf));
-		mpt_free_msg_frame(hd->ioc, mf);
-		return retval;
+		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
+		dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!"
+			" (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
+			hd->ioc, mf, retval));
+		goto fail_out;
 	}
 
 	if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
-		dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
+		dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!"
 			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
 			hd->ioc, mf));
-		mpt_free_msg_frame(hd->ioc, mf);
 		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
 			 hd->ioc->name));
 		retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
+		dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n",
+			 hd->ioc->name, retval));
+		goto fail_out;
 	}
 
+	/*
+	 * Handle success case, see if theres a non-zero ioc_status.
+	 */
+	if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
+	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
+	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
+		retval = 0;
+	else
+		retval = FAILED;
+
 	return retval;
+
+ fail_out:
+
+	/*
+	 * Free task managment mf, and corresponding tm flags
+	 */
+	mpt_free_msg_frame(hd->ioc, mf);
+	hd->tmPending = 0;
+	hd->tmState = TM_STATE_NONE;
+	return FAILED;
 }
 
 static int
@@ -1728,7 +1771,7 @@
  *	(linux scsi_host_template.eh_abort_handler routine)
  *
  *	Returns SUCCESS or FAILED.
- */
+ **/
 int
 mptscsih_abort(struct scsi_cmnd * SCpnt)
 {
@@ -1764,9 +1807,8 @@
 		return SUCCESS;
 	}
 
-	if (hd->resetPending) {
+	if (hd->resetPending)
 		return FAILED;
-	}
 
 	if (hd->timeouts < -1)
 		hd->timeouts++;
@@ -1789,13 +1831,12 @@
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
-		vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
+		vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
 		ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
 
 	if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
-	    SCpnt->serial_number == sn) {
+	    SCpnt->serial_number == sn)
 		retval = FAILED;
-	}
 
 	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
 		hd->ioc->name,
@@ -1803,12 +1844,8 @@
 
 	if (retval == 0)
 		return SUCCESS;
-
-	if(retval != FAILED ) {
-		hd->tmPending = 0;
-		hd->tmState = TM_STATE_NONE;
-	}
-	return FAILED;
+	else
+		return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1819,7 +1856,7 @@
  *	(linux scsi_host_template.eh_dev_reset_handler routine)
  *
  *	Returns SUCCESS or FAILED.
- */
+ **/
 int
 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 {
@@ -1845,7 +1882,7 @@
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-		vdev->vtarget->bus_id, vdev->vtarget->target_id,
+		vdev->vtarget->channel, vdev->vtarget->id,
 		0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
@@ -1854,14 +1891,11 @@
 
 	if (retval == 0)
 		return SUCCESS;
-
-	if(retval != FAILED ) {
-		hd->tmPending = 0;
-		hd->tmState = TM_STATE_NONE;
-	}
-	return FAILED;
+	else
+		return FAILED;
 }
 
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptscsih_bus_reset - Perform a SCSI BUS_RESET!	new_eh variant
@@ -1870,7 +1904,7 @@
  *	(linux scsi_host_template.eh_bus_reset_handler routine)
  *
  *	Returns SUCCESS or FAILED.
- */
+ **/
 int
 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
@@ -1896,7 +1930,7 @@
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-		vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
+		vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
 		hd->ioc->name,
@@ -1904,12 +1938,8 @@
 
 	if (retval == 0)
 		return SUCCESS;
-
-	if(retval != FAILED ) {
-		hd->tmPending = 0;
-		hd->tmState = TM_STATE_NONE;
-	}
-	return FAILED;
+	else
+		return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1992,7 +2022,6 @@
 /**
  *	mptscsih_tm_wait_for_completion - wait for completion of TM task
  *	@hd: Pointer to MPT host structure.
- *	@timeout: timeout in seconds
  *
  *	Returns {SUCCESS,FAILED}.
  */
@@ -2066,7 +2095,7 @@
  *	load/init time via the mpt_register() API call.
  *
  *	Returns 1 indicating alloc'd request frame ptr should be freed.
- */
+ **/
 int
 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 {
@@ -2076,78 +2105,85 @@
 	unsigned long		 flags;
 	u16			 iocstatus;
 	u8			 tmType;
+	u32			 termination_count;
 
 	dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
-			ioc->name, mf, mr));
-	if (ioc->sh) {
-		/* Depending on the thread, a timer is activated for
-		 * the TM request.  Delete this timer on completion of TM.
-		 * Decrement count of outstanding TM requests.
-		 */
-		hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
-	} else {
-		dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
-			ioc->name));
+	    ioc->name, mf, mr));
+	if (!ioc->sh) {
+		dtmprintk((MYIOC_s_WARN_FMT
+		    "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
 		return 1;
 	}
 
 	if (mr == NULL) {
-		dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
-			ioc->name, mf));
+		dtmprintk((MYIOC_s_WARN_FMT
+		    "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
 		return 1;
-	} else {
-		pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
-		pScsiTmReq = (SCSITaskMgmt_t*)mf;
-
-		/* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
-		tmType = pScsiTmReq->TaskType;
-
-		if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
-		    pScsiTmReply->ResponseCode)
-			mptscsih_taskmgmt_response_code(ioc,
-			    pScsiTmReply->ResponseCode);
-
-		dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",
-				ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
-		DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
-
-		iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
-		hd->tm_iocstatus = iocstatus;
-		dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
-			ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
-		/* Error?  (anything non-zero?) */
-		if (iocstatus) {
-
-			/* clear flags and continue.
-			 */
-			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
-				hd->abortSCpnt = NULL;
-
-			/* If an internal command is present
-			 * or the TM failed - reload the FW.
-			 * FC FW may respond FAILED to an ABORT
-			 */
-			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
-				if ((hd->cmdPtr) ||
-				    (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
-					if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
-						printk((KERN_WARNING
-							" Firmware Reload FAILED!!\n"));
-					}
-				}
-			}
-		} else {
-			dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
-
-			hd->abortSCpnt = NULL;
-
-		}
 	}
 
+	hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+	pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
+	pScsiTmReq = (SCSITaskMgmt_t*)mf;
+	tmType = pScsiTmReq->TaskType;
+	iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+	termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
+
+	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
+	    pScsiTmReply->ResponseCode)
+		mptscsih_taskmgmt_response_code(ioc,
+		    pScsiTmReply->ResponseCode);
+	DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
+
+#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM)
+	printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
+	    "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
+	    "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
+	    pScsiTmReply->TargetID, pScsiTmReq->TaskType,
+	    le16_to_cpu(pScsiTmReply->IOCStatus),
+	    le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
+	    le32_to_cpu(pScsiTmReply->TerminationCount));
+#endif
+	if (!iocstatus) {
+		dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
+			hd->abortSCpnt = NULL;
+		goto out;
+	}
+
+	/* Error?  (anything non-zero?) */
+
+	/* clear flags and continue.
+	 */
+	switch (tmType) {
+
+	case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
+		if (termination_count == 1)
+			iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
+		hd->abortSCpnt = NULL;
+		break;
+
+	case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
+
+		/* If an internal command is present
+		 * or the TM failed - reload the FW.
+		 * FC FW may respond FAILED to an ABORT
+		 */
+		if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
+		    hd->cmdPtr)
+			if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
+				printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
+		break;
+
+	case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
+	default:
+		break;
+	}
+
+ out:
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 	hd->tmPending = 0;
-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 	hd->tmState = TM_STATE_NONE;
+	hd->tm_iocstatus = iocstatus;
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 	return 1;
 }
@@ -2191,7 +2227,7 @@
 
 	dprintk((KERN_NOTICE
 		": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
-		sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
+		sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors));
 
 	return 0;
 }
@@ -2200,115 +2236,78 @@
  *
  */
 int
-mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
+	struct inactive_raid_component_info *component_info;
 	int i;
+	int rc = 0;
 
-	if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
-		return 0;
+	if (!ioc->raid_data.pIocPg3)
+		goto out;
 	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
-                if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
-                        return 1;
-        }
-        return 0;
+		if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+		    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+			rc = 1;
+			goto out;
+		}
+	}
+
+	/*
+	 * Check inactive list for matching phys disks
+	 */
+	if (list_empty(&ioc->raid_data.inactive_list))
+		goto out;
+
+	down(&ioc->raid_data.inactive_list_mutex);
+	list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+	    list) {
+		if ((component_info->d.PhysDiskID == id) &&
+		    (component_info->d.PhysDiskBus == channel))
+			rc = 1;
+	}
+	up(&ioc->raid_data.inactive_list_mutex);
+
+ out:
+	return rc;
 }
 EXPORT_SYMBOL(mptscsih_is_phys_disk);
 
-int
-mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid)
+u8
+mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
+	struct inactive_raid_component_info *component_info;
 	int i;
+	int rc = -ENXIO;
 
-	if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3)
-		return -ENXIO;
-
-	for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
-		if (physdiskid ==
-		    hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
-			return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
-	}
-
-	return -ENXIO;
-}
-EXPORT_SYMBOL(mptscsih_raid_id_to_num);
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	OS entry point to allow host driver to alloc memory
- *	for each scsi target. Called once per device the bus scan.
- *	Return non-zero if allocation fails.
- */
-int
-mptscsih_target_alloc(struct scsi_target *starget)
-{
-	VirtTarget		*vtarget;
-
-	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
-	if (!vtarget)
-		return -ENOMEM;
-	starget->hostdata = vtarget;
-	vtarget->starget = starget;
-	return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	OS entry point to allow host driver to alloc memory
- *	for each scsi device. Called once per device the bus scan.
- *	Return non-zero if allocation fails.
- */
-int
-mptscsih_slave_alloc(struct scsi_device *sdev)
-{
-	struct Scsi_Host	*host = sdev->host;
-	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
-	VirtTarget		*vtarget;
-	VirtDevice		*vdev;
-	struct scsi_target 	*starget;
-
-	vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
-	if (!vdev) {
-		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
-				hd->ioc->name, sizeof(VirtDevice));
-		return -ENOMEM;
-	}
-
-	vdev->lun = sdev->lun;
-	sdev->hostdata = vdev;
-
-	starget = scsi_target(sdev);
-	vtarget = starget->hostdata;
-
-	vdev->vtarget = vtarget;
-
-	if (vtarget->num_luns == 0) {
-		hd->Targets[sdev->id] = vtarget;
-		vtarget->ioc_id = hd->ioc->id;
-		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
-		vtarget->target_id = sdev->id;
-		vtarget->bus_id = sdev->channel;
-		if (hd->ioc->bus_type == SPI && sdev->channel == 0 &&
-		    hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
-			vtarget->raidVolume = 1;
-			ddvtprintk((KERN_INFO
-				    "RAID Volume @ id %d\n", sdev->id));
+	if (!ioc->raid_data.pIocPg3)
+		goto out;
+	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+		if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+		    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+			rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
+			goto out;
 		}
 	}
-	vtarget->num_luns++;
-	return 0;
-}
 
-/*
- *	OS entry point to allow for host driver to free allocated memory
- *	Called if no device present or device being unloaded
- */
-void
-mptscsih_target_destroy(struct scsi_target *starget)
-{
-	if (starget->hostdata)
-		kfree(starget->hostdata);
-	starget->hostdata = NULL;
+	/*
+	 * Check inactive list for matching phys disks
+	 */
+	if (list_empty(&ioc->raid_data.inactive_list))
+		goto out;
+
+	down(&ioc->raid_data.inactive_list_mutex);
+	list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+	    list) {
+		if ((component_info->d.PhysDiskID == id) &&
+		    (component_info->d.PhysDiskBus == channel))
+			rc = component_info->d.PhysDiskNum;
+	}
+	up(&ioc->raid_data.inactive_list_mutex);
+
+ out:
+	return rc;
 }
+EXPORT_SYMBOL(mptscsih_raid_id_to_num);
 
 /*
  *	OS entry point to allow for host driver to free allocated memory
@@ -2328,11 +2327,7 @@
 	vdevice = sdev->hostdata;
 
 	mptscsih_search_running_cmds(hd, vdevice);
-	vtarget->luns[0] &= ~(1 << vdevice->lun);
 	vtarget->num_luns--;
-	if (vtarget->num_luns == 0) {
-		hd->Targets[sdev->id] = NULL;
-	}
 	mptscsih_synchronize_cache(hd, vdevice);
 	kfree(vdevice);
 	sdev->hostdata = NULL;
@@ -2394,15 +2389,14 @@
 	VirtDevice		*vdevice;
 	struct scsi_target 	*starget;
 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)sh->hostdata;
-	int			indexed_lun, lun_index;
 
 	starget = scsi_target(sdev);
 	vtarget = starget->hostdata;
 	vdevice = sdev->hostdata;
 
 	dsprintk((MYIOC_s_INFO_FMT
-		"device @ %p, id=%d, LUN=%d, channel=%d\n",
-		hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
+		"device @ %p, channel=%d, id=%d, lun=%d\n",
+		hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
 	if (hd->ioc->bus_type == SPI)
 		dsprintk((MYIOC_s_INFO_FMT
 		    "sdtr %d wdtr %d ppr %d inq length=%d\n",
@@ -2415,11 +2409,7 @@
 		goto slave_configure_exit;
 	}
 
-	vdevice->configured_lun=1;
-	lun_index = (vdevice->lun >> 5);  /* 32 luns per lun_index */
-	indexed_lun = (vdevice->lun % 32);
-	vtarget->luns[lun_index] |= (1 << indexed_lun);
-	mptscsih_initTarget(hd, vtarget, sdev);
+	vdevice->configured_lun = 1;
 	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
 
 	dsprintk((MYIOC_s_INFO_FMT
@@ -2683,285 +2673,6 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptscsih_initTarget - Target, LUN alloc/free functionality.
- *	@hd: Pointer to MPT_SCSI_HOST structure
- *	@vtarget: per target private data
- *	@sdev: SCSI device
- *
- *	NOTE: It's only SAFE to call this routine if data points to
- *	sane & valid STANDARD INQUIRY data!
- *
- *	Allocate and initialize memory for this target.
- *	Save inquiry data.
- *
- */
-static void
-mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
-		    struct scsi_device *sdev)
-{
-	dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
-		hd->ioc->name, vtarget->bus_id, vtarget->target_id,
-		sdev->lun, hd));
-
-	/* Is LUN supported? If so, upper 2 bits will be 0
-	* in first byte of inquiry data.
-	*/
-	if (sdev->inq_periph_qual != 0)
-		return;
-
-	if (vtarget == NULL)
-		return;
-
-	vtarget->type = sdev->type;
-
-	if (hd->ioc->bus_type != SPI)
-		return;
-
-	if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
-		/* Treat all Processors as SAF-TE if
-		 * command line option is set */
-		vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-		mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
-	}else if ((sdev->type == TYPE_PROCESSOR) &&
-		!(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
-		if (sdev->inquiry_len > 49 ) {
-			if (sdev->inquiry[44] == 'S' &&
-			    sdev->inquiry[45] == 'A' &&
-			    sdev->inquiry[46] == 'F' &&
-			    sdev->inquiry[47] == '-' &&
-			    sdev->inquiry[48] == 'T' &&
-			    sdev->inquiry[49] == 'E' ) {
-				vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-				mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
-			}
-		}
-	}
-	mptscsih_setTargetNegoParms(hd, vtarget, sdev);
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Update the target negotiation parameters based on the
- *  the Inquiry data, adapter capabilities, and NVRAM settings.
- *
- */
-static void
-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
-			    struct scsi_device *sdev)
-{
-	SpiCfgData *pspi_data = &hd->ioc->spi_data;
-	int  id = (int) target->target_id;
-	int  nvram;
-	u8 width = MPT_NARROW;
-	u8 factor = MPT_ASYNC;
-	u8 offset = 0;
-	u8 nfactor;
-	u8 noQas = 1;
-
-	target->negoFlags = pspi_data->noQas;
-
-	/* noQas == 0 => device supports QAS. */
-
-	if (sdev->scsi_level < SCSI_2) {
-		width = 0;
-		factor = MPT_ULTRA2;
-		offset = pspi_data->maxSyncOffset;
-		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
-	} else {
-		if (scsi_device_wide(sdev)) {
-			width = 1;
-		}
-
-		if (scsi_device_sync(sdev)) {
-			factor = pspi_data->minSyncFactor;
-			if (!scsi_device_dt(sdev))
-					factor = MPT_ULTRA2;
-			else {
-				if (!scsi_device_ius(sdev) &&
-				    !scsi_device_qas(sdev))
-					factor = MPT_ULTRA160;
-				else {
-					factor = MPT_ULTRA320;
-					if (scsi_device_qas(sdev)) {
-						ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
-						noQas = 0;
-					}
-					if (sdev->type == TYPE_TAPE &&
-					    scsi_device_ius(sdev))
-						target->negoFlags |= MPT_TAPE_NEGO_IDP;
-				}
-			}
-			offset = pspi_data->maxSyncOffset;
-
-			/* If RAID, never disable QAS
-			 * else if non RAID, do not disable
-			 *   QAS if bit 1 is set
-			 * bit 1 QAS support, non-raid only
-			 * bit 0 IU support
-			 */
-			if (target->raidVolume == 1) {
-				noQas = 0;
-			}
-		} else {
-			factor = MPT_ASYNC;
-			offset = 0;
-		}
-	}
-
-	if (!sdev->tagged_supported) {
-		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
-	}
-
-	/* Update tflags based on NVRAM settings. (SCSI only)
-	 */
-	if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-		nvram = pspi_data->nvram[id];
-		nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
-
-		if (width)
-			width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
-
-		if (offset > 0) {
-			/* Ensure factor is set to the
-			 * maximum of: adapter, nvram, inquiry
-			 */
-			if (nfactor) {
-				if (nfactor < pspi_data->minSyncFactor )
-					nfactor = pspi_data->minSyncFactor;
-
-				factor = max(factor, nfactor);
-				if (factor == MPT_ASYNC)
-					offset = 0;
-			} else {
-				offset = 0;
-				factor = MPT_ASYNC;
-		}
-		} else {
-			factor = MPT_ASYNC;
-		}
-	}
-
-	/* Make sure data is consistent
-	 */
-	if ((!width) && (factor < MPT_ULTRA2)) {
-		factor = MPT_ULTRA2;
-	}
-
-	/* Save the data to the target structure.
-	 */
-	target->minSyncFactor = factor;
-	target->maxOffset = offset;
-	target->maxWidth = width;
-
-	target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
-
-	/* Disable unused features.
-	 */
-	if (!width)
-		target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
-	if (!offset)
-		target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
-
-	if ( factor > MPT_ULTRA320 )
-		noQas = 0;
-
-	if (noQas && (pspi_data->noQas == 0)) {
-		pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
-		target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-
-		/* Disable QAS in a mixed configuration case
-		 */
-
-		ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
-	}
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  SCSI Config Page functionality ...
- */
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*	mptscsih_writeIOCPage4  - write IOC Page 4
- *	@hd: Pointer to a SCSI Host Structure
- *	@target_id: write IOC Page4 for this ID & Bus
- *
- *	Return: -EAGAIN if unable to obtain a Message Frame
- *		or 0 if success.
- *
- *	Remark: We do not wait for a return, write pages sequentially.
- */
-static int
-mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
-{
-	MPT_ADAPTER		*ioc = hd->ioc;
-	Config_t		*pReq;
-	IOCPage4_t		*IOCPage4Ptr;
-	MPT_FRAME_HDR		*mf;
-	dma_addr_t		 dataDma;
-	u16			 req_idx;
-	u32			 frameOffset;
-	u32			 flagsLength;
-	int			 ii;
-
-	/* Get a MF for this command.
-	 */
-	if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
-		dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
-					ioc->name));
-		return -EAGAIN;
-	}
-
-	/* Set the request and the data pointers.
-	 * Place data at end of MF.
-	 */
-	pReq = (Config_t *)mf;
-
-	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
-	frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
-
-	/* Complete the request frame (same for all requests).
-	 */
-	pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-	pReq->Reserved = 0;
-	pReq->ChainOffset = 0;
-	pReq->Function = MPI_FUNCTION_CONFIG;
-	pReq->ExtPageLength = 0;
-	pReq->ExtPageType = 0;
-	pReq->MsgFlags = 0;
-	for (ii=0; ii < 8; ii++) {
-		pReq->Reserved2[ii] = 0;
-	}
-
-       	IOCPage4Ptr = ioc->spi_data.pIocPg4;
-       	dataDma = ioc->spi_data.IocPg4_dma;
-       	ii = IOCPage4Ptr->ActiveSEP++;
-       	IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
-       	IOCPage4Ptr->SEP[ii].SEPBus = bus;
-       	pReq->Header = IOCPage4Ptr->Header;
-	pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
-
-	/* Add a SGE to the config request.
-	 */
-	flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
-		(IOCPage4Ptr->Header.PageLength + ii) * 4;
-
-	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
-
-	dinitprintk((MYIOC_s_INFO_FMT
-		"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
-			ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
-
-	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
-
-	return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
  *  Bus Scan and Domain Validation functionality ...
  */
 
@@ -3343,7 +3054,7 @@
 		pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
 	} else {
 		pScsiReq->TargetID = io->id;
-		pScsiReq->Bus = io->bus;
+		pScsiReq->Bus = io->channel;
 		pScsiReq->ChainOffset = 0;
 		pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
 	}
@@ -3356,9 +3067,7 @@
 	pScsiReq->MsgFlags = mpt_msg_flags();
 	/* MsgContext set in mpt_get_msg_fram call  */
 
-	for (ii=0; ii < 8; ii++)
-		pScsiReq->LUN[ii] = 0;
-	pScsiReq->LUN[1] = io->lun;
+	int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
 
 	if (io->flags & MPT_ICFLAG_TAGGED_CMD)
 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
@@ -3379,7 +3088,7 @@
 					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));
 
 	ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
-			hd->ioc->name, cmd, io->bus, io->id, io->lun));
+			hd->ioc->name, cmd, io->channel, io->id, io->lun));
 
 	if (dir == MPI_SCSIIO_CONTROL_READ) {
 		mpt_add_sge((char *) &pScsiReq->SGL,
@@ -3462,9 +3171,9 @@
 	iocmd.data_dma = -1;
 	iocmd.size = 0;
 	iocmd.rsvd = iocmd.rsvd2 = 0;
-	iocmd.bus = vdevice->vtarget->bus_id;
-	iocmd.id = vdevice->vtarget->target_id;
-	iocmd.lun = (u8)vdevice->lun;
+	iocmd.channel = vdevice->vtarget->channel;
+	iocmd.id = vdevice->vtarget->id;
+	iocmd.lun = vdevice->lun;
 
 	if ((vdevice->vtarget->type == TYPE_DISK) &&
 	    (vdevice->configured_lun))
@@ -3480,9 +3189,6 @@
 EXPORT_SYMBOL(mptscsih_proc_info);
 EXPORT_SYMBOL(mptscsih_info);
 EXPORT_SYMBOL(mptscsih_qcmd);
-EXPORT_SYMBOL(mptscsih_target_alloc);
-EXPORT_SYMBOL(mptscsih_slave_alloc);
-EXPORT_SYMBOL(mptscsih_target_destroy);
 EXPORT_SYMBOL(mptscsih_slave_destroy);
 EXPORT_SYMBOL(mptscsih_slave_configure);
 EXPORT_SYMBOL(mptscsih_abort);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 187c8af..843c01a 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -53,6 +53,24 @@
  *	SCSI Public stuff...
  */
 
+#define MPT_SCANDV_GOOD			(0x00000000) /* must be 0 */
+#define MPT_SCANDV_DID_RESET		(0x00000001)
+#define MPT_SCANDV_SENSE		(0x00000002)
+#define MPT_SCANDV_SOME_ERROR		(0x00000004)
+#define MPT_SCANDV_SELECTION_TIMEOUT	(0x00000008)
+#define MPT_SCANDV_ISSUE_SENSE		(0x00000010)
+#define MPT_SCANDV_FALLBACK		(0x00000020)
+
+#define MPT_SCANDV_MAX_RETRIES		(10)
+
+#define MPT_ICFLAG_BUF_CAP	0x01	/* ReadBuffer Read Capacity format */
+#define MPT_ICFLAG_ECHO		0x02	/* ReadBuffer Echo buffer format */
+#define MPT_ICFLAG_EBOS		0x04	/* ReadBuffer Echo buffer has EBOS */
+#define MPT_ICFLAG_PHYS_DISK	0x08	/* Any SCSI IO but do Phys Disk Format */
+#define MPT_ICFLAG_TAGGED_CMD	0x10	/* Do tagged IO */
+#define MPT_ICFLAG_DID_RESET	0x20	/* Bus Reset occurred with this command */
+#define MPT_ICFLAG_RESERVED	0x40	/* Reserved has been issued */
+
 #define MPT_SCSI_CMD_PER_DEV_HIGH	64
 #define MPT_SCSI_CMD_PER_DEV_LOW	32
 
@@ -69,9 +87,22 @@
 #define MPTSCSIH_SAF_TE                 0
 #define MPTSCSIH_PT_CLEAR               0
 
-
 #endif
 
+typedef struct _internal_cmd {
+	char		*data;		/* data pointer */
+	dma_addr_t	data_dma;	/* data dma address */
+	int		size;		/* transfer size */
+	u8		cmd;		/* SCSI Op Code */
+	u8		channel;	/* bus number */
+	u8		id;		/* SCSI ID (virtual) */
+	int		lun;
+	u8		flags;		/* Bit Field - See above */
+	u8		physDiskNum;	/* Phys disk number, -1 else */
+	u8		rsvd2;
+	u8		rsvd;
+} INTERNAL_CMD;
+
 extern void mptscsih_remove(struct pci_dev *);
 extern void mptscsih_shutdown(struct pci_dev *);
 #ifdef CONFIG_PM
@@ -81,9 +112,6 @@
 extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
 extern const char * mptscsih_info(struct Scsi_Host *SChost);
 extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
-extern int mptscsih_target_alloc(struct scsi_target *starget);
-extern int mptscsih_slave_alloc(struct scsi_device *device);
-extern void mptscsih_target_destroy(struct scsi_target *starget);
 extern void mptscsih_slave_destroy(struct scsi_device *device);
 extern int mptscsih_slave_configure(struct scsi_device *device);
 extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
@@ -98,6 +126,6 @@
 extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
 extern void mptscsih_timer_expired(unsigned long data);
-extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
-extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid);
-extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
+extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
+extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
+extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 203c661..85f21b5 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -54,7 +54,6 @@
 #include <linux/delay.h>	/* for mdelay */
 #include <linux/interrupt.h>	/* needed for in_interrupt() proto */
 #include <linux/reboot.h>	/* notifier code */
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/raid_class.h>
 
@@ -65,6 +64,7 @@
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_spi.h>
+#include <scsi/scsi_dbg.h>
 
 #include "mptbase.h"
 #include "mptscsih.h"
@@ -95,25 +95,339 @@
 static int	mptspiTaskCtx = -1;
 static int	mptspiInternalCtx = -1; /* Used only for internal commands */
 
+/**
+ * 	mptspi_setTargetNegoParms  - Update the target negotiation
+ *	parameters based on the the Inquiry data, adapter capabilities,
+ *	and NVRAM settings
+ *
+ *	@hd: Pointer to a SCSI Host Structure
+ *	@vtarget: per target private data
+ *	@sdev: SCSI device
+ *
+ **/
+static void
+mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
+			    struct scsi_device *sdev)
+{
+	SpiCfgData *pspi_data = &hd->ioc->spi_data;
+	int  id = (int) target->id;
+	int  nvram;
+	u8 width = MPT_NARROW;
+	u8 factor = MPT_ASYNC;
+	u8 offset = 0;
+	u8 nfactor;
+	u8 noQas = 1;
+
+	target->negoFlags = pspi_data->noQas;
+
+	if (sdev->scsi_level < SCSI_2) {
+		width = 0;
+		factor = MPT_ULTRA2;
+		offset = pspi_data->maxSyncOffset;
+		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+	} else {
+		if (scsi_device_wide(sdev))
+			width = 1;
+
+		if (scsi_device_sync(sdev)) {
+			factor = pspi_data->minSyncFactor;
+			if (!scsi_device_dt(sdev))
+					factor = MPT_ULTRA2;
+			else {
+				if (!scsi_device_ius(sdev) &&
+				    !scsi_device_qas(sdev))
+					factor = MPT_ULTRA160;
+				else {
+					factor = MPT_ULTRA320;
+					if (scsi_device_qas(sdev)) {
+						ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
+						noQas = 0;
+					}
+					if (sdev->type == TYPE_TAPE &&
+					    scsi_device_ius(sdev))
+						target->negoFlags |= MPT_TAPE_NEGO_IDP;
+				}
+			}
+			offset = pspi_data->maxSyncOffset;
+
+			/* If RAID, never disable QAS
+			 * else if non RAID, do not disable
+			 *   QAS if bit 1 is set
+			 * bit 1 QAS support, non-raid only
+			 * bit 0 IU support
+			 */
+			if (target->raidVolume == 1)
+				noQas = 0;
+		} else {
+			factor = MPT_ASYNC;
+			offset = 0;
+		}
+	}
+
+	if (!sdev->tagged_supported)
+		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+
+	/* Update tflags based on NVRAM settings. (SCSI only)
+	 */
+	if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+		nvram = pspi_data->nvram[id];
+		nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
+
+		if (width)
+			width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+
+		if (offset > 0) {
+			/* Ensure factor is set to the
+			 * maximum of: adapter, nvram, inquiry
+			 */
+			if (nfactor) {
+				if (nfactor < pspi_data->minSyncFactor )
+					nfactor = pspi_data->minSyncFactor;
+
+				factor = max(factor, nfactor);
+				if (factor == MPT_ASYNC)
+					offset = 0;
+			} else {
+				offset = 0;
+				factor = MPT_ASYNC;
+		}
+		} else {
+			factor = MPT_ASYNC;
+		}
+	}
+
+	/* Make sure data is consistent
+	 */
+	if ((!width) && (factor < MPT_ULTRA2))
+		factor = MPT_ULTRA2;
+
+	/* Save the data to the target structure.
+	 */
+	target->minSyncFactor = factor;
+	target->maxOffset = offset;
+	target->maxWidth = width;
+
+	target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
+
+	/* Disable unused features.
+	 */
+	if (!width)
+		target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+
+	if (!offset)
+		target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+
+	if ( factor > MPT_ULTRA320 )
+		noQas = 0;
+
+	if (noQas && (pspi_data->noQas == 0)) {
+		pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
+		target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+
+		/* Disable QAS in a mixed configuration case
+		 */
+
+		ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
+	}
+}
+
+/**
+ * 	mptspi_writeIOCPage4  - write IOC Page 4
+ *	@hd: Pointer to a SCSI Host Structure
+ *	@channel:
+ *	@id: write IOC Page4 for this ID & Bus
+ *
+ *	Return: -EAGAIN if unable to obtain a Message Frame
+ *		or 0 if success.
+ *
+ *	Remark: We do not wait for a return, write pages sequentially.
+ **/
+static int
+mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id)
+{
+	MPT_ADAPTER		*ioc = hd->ioc;
+	Config_t		*pReq;
+	IOCPage4_t		*IOCPage4Ptr;
+	MPT_FRAME_HDR		*mf;
+	dma_addr_t		 dataDma;
+	u16			 req_idx;
+	u32			 frameOffset;
+	u32			 flagsLength;
+	int			 ii;
+
+	/* Get a MF for this command.
+	 */
+	if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
+		dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
+					ioc->name));
+		return -EAGAIN;
+	}
+
+	/* Set the request and the data pointers.
+	 * Place data at end of MF.
+	 */
+	pReq = (Config_t *)mf;
+
+	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+	frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
+
+	/* Complete the request frame (same for all requests).
+	 */
+	pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+	pReq->Reserved = 0;
+	pReq->ChainOffset = 0;
+	pReq->Function = MPI_FUNCTION_CONFIG;
+	pReq->ExtPageLength = 0;
+	pReq->ExtPageType = 0;
+	pReq->MsgFlags = 0;
+	for (ii=0; ii < 8; ii++) {
+		pReq->Reserved2[ii] = 0;
+	}
+
+	IOCPage4Ptr = ioc->spi_data.pIocPg4;
+	dataDma = ioc->spi_data.IocPg4_dma;
+	ii = IOCPage4Ptr->ActiveSEP++;
+	IOCPage4Ptr->SEP[ii].SEPTargetID = id;
+	IOCPage4Ptr->SEP[ii].SEPBus = channel;
+	pReq->Header = IOCPage4Ptr->Header;
+	pReq->PageAddress = cpu_to_le32(id | (channel << 8 ));
+
+	/* Add a SGE to the config request.
+	 */
+	flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
+		(IOCPage4Ptr->Header.PageLength + ii) * 4;
+
+	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
+
+	ddvprintk((MYIOC_s_INFO_FMT
+		"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
+			ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
+
+	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+
+	return 0;
+}
+
+/**
+ *	mptspi_initTarget - Target, LUN alloc/free functionality.
+ *	@hd: Pointer to MPT_SCSI_HOST structure
+ *	@vtarget: per target private data
+ *	@sdev: SCSI device
+ *
+ *	NOTE: It's only SAFE to call this routine if data points to
+ *	sane & valid STANDARD INQUIRY data!
+ *
+ *	Allocate and initialize memory for this target.
+ *	Save inquiry data.
+ *
+ **/
+static void
+mptspi_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
+		    struct scsi_device *sdev)
+{
+
+	/* Is LUN supported? If so, upper 2 bits will be 0
+	* in first byte of inquiry data.
+	*/
+	if (sdev->inq_periph_qual != 0)
+		return;
+
+	if (vtarget == NULL)
+		return;
+
+	vtarget->type = sdev->type;
+
+	if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
+		/* Treat all Processors as SAF-TE if
+		 * command line option is set */
+		vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+		mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
+	}else if ((sdev->type == TYPE_PROCESSOR) &&
+		!(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
+		if (sdev->inquiry_len > 49 ) {
+			if (sdev->inquiry[44] == 'S' &&
+			    sdev->inquiry[45] == 'A' &&
+			    sdev->inquiry[46] == 'F' &&
+			    sdev->inquiry[47] == '-' &&
+			    sdev->inquiry[48] == 'T' &&
+			    sdev->inquiry[49] == 'E' ) {
+				vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+				mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
+			}
+		}
+	}
+	mptspi_setTargetNegoParms(hd, vtarget, sdev);
+}
+
+/**
+ *	mptspi_is_raid - Determines whether target is belonging to volume
+ *	@hd: Pointer to a SCSI HOST structure
+ *	@id: target device id
+ *
+ *	Return:
+ *		non-zero = true
+ *		zero = false
+ *
+ */
+static int
+mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
+{
+	int i, rc = 0;
+
+	if (!hd->ioc->raid_data.pIocPg2)
+		goto out;
+
+	if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes)
+		goto out;
+	for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+		if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) {
+			rc = 1;
+			goto out;
+		}
+	}
+
+ out:
+	return rc;
+}
+
 static int mptspi_target_alloc(struct scsi_target *starget)
 {
 	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
 	struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
-	int ret;
+	VirtTarget		*vtarget;
 
 	if (hd == NULL)
 		return -ENODEV;
 
-	ret = mptscsih_target_alloc(starget);
-	if (ret)
-		return ret;
+	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
+	if (!vtarget)
+		return -ENOMEM;
 
-	/* if we're a device on virtual channel 1 and we're not part
-	 * of an array, just return here (otherwise the setup below
-	 * may actually affect a real physical device on channel 0 */
-	if (starget->channel == 1 &&
-	    mptscsih_raid_id_to_num(hd, starget->id) < 0)
-		return 0;
+	vtarget->ioc_id = hd->ioc->id;
+	vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+	vtarget->id = (u8)starget->id;
+	vtarget->channel = (u8)starget->channel;
+	vtarget->starget = starget;
+	starget->hostdata = vtarget;
+
+	if (starget->channel == 1) {
+		if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0)
+			return 0;
+		vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+		/* The real channel for this device is zero */
+		vtarget->channel = 0;
+		/* The actual physdisknum (for RAID passthrough) */
+		vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0,
+		    starget->id);
+	}
+
+	if (starget->channel == 0 &&
+	    mptspi_is_raid(hd, starget->id)) {
+		vtarget->raidVolume = 1;
+		ddvprintk((KERN_INFO
+		    "RAID Volume @ channel=%d id=%d\n", starget->channel,
+		    starget->id));
+	}
 
 	if (hd->ioc->spi_data.nvram &&
 	    hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
@@ -132,6 +446,64 @@
 	return 0;
 }
 
+void
+mptspi_target_destroy(struct scsi_target *starget)
+{
+	if (starget->hostdata)
+		kfree(starget->hostdata);
+	starget->hostdata = NULL;
+}
+
+/**
+ *	mptspi_print_write_nego - negotiation parameters debug info that is being sent
+ *	@hd: Pointer to a SCSI HOST structure
+ *	@starget: SCSI target
+ *	@ii: negotiation parameters
+ *
+ */
+static void
+mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
+{
+	ddvprintk((MYIOC_s_INFO_FMT "id=%d Requested = 0x%08x"
+	    " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
+	    hd->ioc->name, starget->id, ii,
+	    ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
+	    ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
+	    ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
+}
+
+/**
+ *	mptspi_print_read_nego - negotiation parameters debug info that is being read
+ *	@hd: Pointer to a SCSI HOST structure
+ *	@starget: SCSI target
+ *	@ii: negotiation parameters
+ *
+ */
+static void
+mptspi_print_read_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
+{
+	ddvprintk((MYIOC_s_INFO_FMT "id=%d Read = 0x%08x"
+	    " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
+	    hd->ioc->name, starget->id, ii,
+	    ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
+	    ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
+	    ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
+}
+
 static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
 			     struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
 {
@@ -147,7 +519,7 @@
 
 	/* No SPI parameters for RAID devices */
 	if (starget->channel == 0 &&
-	    (hd->ioc->raid_data.isRaid & (1 << starget->id)))
+	    mptspi_is_raid(hd, starget->id))
 		return -1;
 
 	size = ioc->spi_data.sdp0length * 4;
@@ -185,6 +557,8 @@
 	err = 0;
 	memcpy(pass_pg0, pg0, size);
 
+	mptspi_print_read_nego(hd, starget, le32_to_cpu(pg0->NegotiatedParameters));
+
  out_free:
 	dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
 	return err;
@@ -233,7 +607,7 @@
 }
 
 static int
-mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
+mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
 {
 	MpiRaidActionRequest_t	*pReq;
 	MPT_FRAME_HDR		*mf;
@@ -253,8 +627,8 @@
 	pReq->Reserved1 = 0;
 	pReq->ChainOffset = 0;
 	pReq->Function = MPI_FUNCTION_RAID_ACTION;
-	pReq->VolumeID = disk;
-	pReq->VolumeBus = 0;
+	pReq->VolumeID = id;
+	pReq->VolumeBus = channel;
 	pReq->PhysDiskNum = 0;
 	pReq->MsgFlags = 0;
 	pReq->Reserved2 = 0;
@@ -263,8 +637,8 @@
 	mpt_add_sge((char *)&pReq->ActionDataSGE,
 		MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
 
-	ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
-			hd->ioc->name, action, io->id));
+	ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n",
+			hd->ioc->name, pReq->Action, channel, id));
 
 	hd->pLocal = NULL;
 	hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
@@ -292,12 +666,12 @@
 
 	/* no DV on RAID devices */
 	if (sdev->channel == 0 &&
-	    (hd->ioc->raid_data.isRaid & (1 << sdev->id)))
+	    mptspi_is_raid(hd, sdev->id))
 		return;
 
 	/* If this is a piece of a RAID, then quiesce first */
 	if (sdev->channel == 1 &&
-	    mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) {
+	    mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
 		starget_printk(KERN_ERR, scsi_target(sdev),
 			       "Integrated RAID quiesce failed\n");
 		return;
@@ -306,7 +680,7 @@
 	spi_dv_device(sdev);
 
 	if (sdev->channel == 1 &&
-	    mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0)
+	    mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
 		starget_printk(KERN_ERR, scsi_target(sdev),
 			       "Integrated RAID resume failed\n");
 
@@ -317,54 +691,89 @@
 
 static int mptspi_slave_alloc(struct scsi_device *sdev)
 {
-	int ret;
 	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
-	/* gcc doesn't see that all uses of this variable occur within
-	 * the if() statements, so stop it from whining */
-	int physdisknum = 0;
+	VirtTarget		*vtarget;
+	VirtDevice		*vdev;
+	struct scsi_target 	*starget;
 
-	if (sdev->channel == 1) {
-		physdisknum = mptscsih_raid_id_to_num(hd, sdev->id);
+	if (sdev->channel == 1 &&
+		mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0)
+			return -ENXIO;
 
-		if (physdisknum < 0)
-			return physdisknum;
+	vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
+	if (!vdev) {
+		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+				hd->ioc->name, sizeof(VirtDevice));
+		return -ENOMEM;
 	}
 
-	ret = mptscsih_slave_alloc(sdev);
+	vdev->lun = sdev->lun;
+	sdev->hostdata = vdev;
 
-	if (ret)
-		return ret;
+	starget = scsi_target(sdev);
+	vtarget = starget->hostdata;
+	vdev->vtarget = vtarget;
+	vtarget->num_luns++;
 
-	if (sdev->channel == 1) {
-		VirtDevice *vdev = sdev->hostdata;
+	if (sdev->channel == 1)
 		sdev->no_uld_attach = 1;
-		vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
-		/* The real channel for this device is zero */
-		vdev->vtarget->bus_id = 0;
-		/* The actual physdisknum (for RAID passthrough) */
-		vdev->vtarget->target_id = physdisknum;
-	}
 
 	return 0;
 }
 
 static int mptspi_slave_configure(struct scsi_device *sdev)
 {
-	int ret = mptscsih_slave_configure(sdev);
 	struct _MPT_SCSI_HOST *hd =
 		(struct _MPT_SCSI_HOST *)sdev->host->hostdata;
+	VirtTarget *vtarget = scsi_target(sdev)->hostdata;
+	int ret = mptscsih_slave_configure(sdev);
 
 	if (ret)
 		return ret;
 
+	mptspi_initTarget(hd, vtarget, sdev);
+
+	ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x"
+		" max_offset=0x%02x max_width=%d\n", hd->ioc->name,
+		sdev->id, spi_min_period(scsi_target(sdev)),
+		spi_max_offset(scsi_target(sdev)),
+		spi_max_width(scsi_target(sdev))));
+
 	if ((sdev->channel == 1 ||
-	     !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) &&
+	     !(mptspi_is_raid(hd, sdev->id))) &&
 	    !spi_initial_dv(sdev->sdev_target))
 		mptspi_dv_device(hd, sdev);
 
 	return 0;
 }
 
+static int
+mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+{
+	struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+	VirtDevice	*vdev = SCpnt->device->hostdata;
+
+	if (!vdev || !vdev->vtarget) {
+		SCpnt->result = DID_NO_CONNECT << 16;
+		done(SCpnt);
+		return 0;
+	}
+
+	if (SCpnt->device->channel == 1 &&
+		mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) {
+		SCpnt->result = DID_NO_CONNECT << 16;
+		done(SCpnt);
+		return 0;
+	}
+
+#ifdef MPT_DEBUG_DV
+	if (spi_dv_pending(scsi_target(SCpnt->device)))
+		scsi_print_command(SCpnt);
+#endif
+
+	return mptscsih_qcmd(SCpnt,done);
+}
+
 static void mptspi_slave_destroy(struct scsi_device *sdev)
 {
 	struct scsi_target *starget = scsi_target(sdev);
@@ -392,11 +801,11 @@
 	.proc_info			= mptscsih_proc_info,
 	.name				= "MPT SPI Host",
 	.info				= mptscsih_info,
-	.queuecommand			= mptscsih_qcmd,
+	.queuecommand			= mptspi_qcmd,
 	.target_alloc			= mptspi_target_alloc,
 	.slave_alloc			= mptspi_slave_alloc,
 	.slave_configure		= mptspi_slave_configure,
-	.target_destroy			= mptscsih_target_destroy,
+	.target_destroy			= mptspi_target_destroy,
 	.slave_destroy			= mptspi_slave_destroy,
 	.change_queue_depth 		= mptscsih_change_queue_depth,
 	.eh_abort_handler		= mptscsih_abort,
@@ -427,7 +836,7 @@
 
 	/* don't allow updating nego parameters on RAID devices */
 	if (starget->channel == 0 &&
-	    (hd->ioc->raid_data.isRaid & (1 << starget->id)))
+	    mptspi_is_raid(hd, starget->id))
 		return -1;
 
 	size = ioc->spi_data.sdp1length * 4;
@@ -460,6 +869,8 @@
 	pg1->Header.PageNumber = hdr.PageNumber;
 	pg1->Header.PageType = hdr.PageType;
 
+	mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));
+
 	if (mpt_config(ioc, &cfg)) {
 		starget_printk(KERN_ERR, starget, "mpt_config failed\n");
 		goto out_free;
@@ -672,9 +1083,9 @@
 		if (sdev->channel != 1)
 			continue;
 
-		/* The target_id is the raid PhysDiskNum, even if
+		/* The id is the raid PhysDiskNum, even if
 		 * starget->id is the actual target address */
-		if(vtarget->target_id != disk)
+		if(vtarget->id != disk)
 			continue;
 
 		starget_printk(KERN_INFO, vtarget->starget,
@@ -727,7 +1138,7 @@
 {
 	struct _MPT_SCSI_HOST *hd =
 		(struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
-	return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) &&
+	return ((mptspi_is_raid(hd, starget->id)) &&
 		starget->channel == 0) ? 1 : 0;
 }
 
@@ -945,14 +1356,13 @@
 	 * max_lun = 1 + actual last lun,
 	 *	see hosts.h :o(
 	 */
-	sh->max_id = MPT_MAX_SCSI_DEVICES;
+	sh->max_id = ioc->devices_per_bus;
 
 	sh->max_lun = MPT_LAST_LUN + 1;
 	/*
 	 * If RAID Firmware Detected, setup virtual channel
 	 */
-	if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
-	    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
+	if (ioc->ir_firmware)
 		sh->max_channel = 1;
 	else
 		sh->max_channel = 0;
@@ -1009,20 +1419,6 @@
 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
 		 ioc->name, hd->ScsiLookup));
 
-	/* Allocate memory for the device structures.
-	 * A non-Null pointer at an offset
-	 * indicates a device exists.
-	 * max_id = 1 + maximum id (hosts.h)
-	 */
-	hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1),
-			      sizeof(void *), GFP_ATOMIC);
-	if (!hd->Targets) {
-		error = -ENOMEM;
-		goto out_mptspi_probe;
-	}
-
-	dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
-
 	/* Clear the TM flags
 	 */
 	hd->tmPending = 0;
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index e33d446..8ba275a 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -1111,7 +1111,7 @@
 	return 0;
 }
 
-static struct file_operations config_fops = {
+static const struct file_operations config_fops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 	.ioctl = i2o_cfg_ioctl,
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index a61cb17..06892ac 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -1703,133 +1703,133 @@
 	return single_open(file, i2o_seq_show_dev_name, PDE(inode)->data);
 };
 
-static struct file_operations i2o_seq_fops_lct = {
+static const struct file_operations i2o_seq_fops_lct = {
 	.open = i2o_seq_open_lct,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_hrt = {
+static const struct file_operations i2o_seq_fops_hrt = {
 	.open = i2o_seq_open_hrt,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_status = {
+static const struct file_operations i2o_seq_fops_status = {
 	.open = i2o_seq_open_status,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_hw = {
+static const struct file_operations i2o_seq_fops_hw = {
 	.open = i2o_seq_open_hw,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_ddm_table = {
+static const struct file_operations i2o_seq_fops_ddm_table = {
 	.open = i2o_seq_open_ddm_table,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_driver_store = {
+static const struct file_operations i2o_seq_fops_driver_store = {
 	.open = i2o_seq_open_driver_store,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_drivers_stored = {
+static const struct file_operations i2o_seq_fops_drivers_stored = {
 	.open = i2o_seq_open_drivers_stored,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_groups = {
+static const struct file_operations i2o_seq_fops_groups = {
 	.open = i2o_seq_open_groups,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_phys_device = {
+static const struct file_operations i2o_seq_fops_phys_device = {
 	.open = i2o_seq_open_phys_device,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_claimed = {
+static const struct file_operations i2o_seq_fops_claimed = {
 	.open = i2o_seq_open_claimed,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_users = {
+static const struct file_operations i2o_seq_fops_users = {
 	.open = i2o_seq_open_users,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_priv_msgs = {
+static const struct file_operations i2o_seq_fops_priv_msgs = {
 	.open = i2o_seq_open_priv_msgs,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_authorized_users = {
+static const struct file_operations i2o_seq_fops_authorized_users = {
 	.open = i2o_seq_open_authorized_users,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_dev_name = {
+static const struct file_operations i2o_seq_fops_dev_name = {
 	.open = i2o_seq_open_dev_name,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_dev_identity = {
+static const struct file_operations i2o_seq_fops_dev_identity = {
 	.open = i2o_seq_open_dev_identity,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_ddm_identity = {
+static const struct file_operations i2o_seq_fops_ddm_identity = {
 	.open = i2o_seq_open_ddm_identity,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_uinfo = {
+static const struct file_operations i2o_seq_fops_uinfo = {
 	.open = i2o_seq_open_uinfo,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_sgl_limits = {
+static const struct file_operations i2o_seq_fops_sgl_limits = {
 	.open = i2o_seq_open_sgl_limits,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_sensors = {
+static const struct file_operations i2o_seq_fops_sensors = {
 	.open = i2o_seq_open_sensors,
 	.read = seq_read,
 	.llseek = seq_lseek,
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fc3c885..ab6e985 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2,6 +2,20 @@
 # Multifunction miscellaneous devices
 #
 
+menu "Multifunction device drivers"
+
+config MFD_SM501
+	tristate "Support for Silicon Motion SM501"
+	 ---help---
+	  This is the core driver for the Silicon Motion SM501 multimedia
+	  companion chip. This device is a multifunction device which may
+	  provide numerous interfaces including USB host controller USB gadget,
+	  Asyncronous Serial ports, Audio functions and a dual display video
+	  interface. The device may be connected by PCI or local bus with
+	  varying functions enabled.
+
+endmenu
+
 menu "Multimedia Capabilities Port drivers"
 	depends on ARCH_SA1100
 
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index adb29b5..5143209 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -2,6 +2,8 @@
 # Makefile for multifunction miscellaneous devices
 #
 
+obj-$(CONFIG_MFD_SM501)		+= sm501.o
+
 obj-$(CONFIG_MCP)		+= mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)	+= mcp-sa11x0.o
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
new file mode 100644
index 0000000..5c5a1e2
--- /dev/null
+++ b/drivers/mfd/sm501.c
@@ -0,0 +1,1148 @@
+/* linux/drivers/mfd/sm501.c
+ *
+ * Copyright (C) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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.
+ *
+ * SM501 MFD driver
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
+#include <asm/io.h>
+
+struct sm501_device {
+	struct list_head		list;
+	struct platform_device		pdev;
+};
+
+struct sm501_devdata {
+	spinlock_t			 reg_lock;
+	struct mutex			 clock_lock;
+	struct list_head		 devices;
+
+	struct device			*dev;
+	struct resource			*io_res;
+	struct resource			*mem_res;
+	struct resource			*regs_claim;
+	struct sm501_platdata		*platdata;
+
+	int				 unit_power[20];
+	unsigned int			 pdev_id;
+	unsigned int			 irq;
+	void __iomem			*regs;
+};
+
+#define MHZ (1000 * 1000)
+
+#ifdef DEBUG
+static const unsigned int misc_div[] = {
+	[0]		= 1,
+	[1]		= 2,
+	[2]		= 4,
+	[3]		= 8,
+	[4]		= 16,
+	[5]		= 32,
+	[6]		= 64,
+	[7]		= 128,
+	[8]		= 3,
+	[9]		= 6,
+	[10]		= 12,
+	[11]		= 24,
+	[12]		= 48,
+	[13]		= 96,
+	[14]		= 192,
+	[15]		= 384,
+};
+
+static const unsigned int px_div[] = {
+	[0]		= 1,
+	[1]		= 2,
+	[2]		= 4,
+	[3]		= 8,
+	[4]		= 16,
+	[5]		= 32,
+	[6]		= 64,
+	[7]		= 128,
+	[8]		= 3,
+	[9]		= 6,
+	[10]	        = 12,
+	[11]		= 24,
+	[12]		= 48,
+	[13]		= 96,
+	[14]		= 192,
+	[15]		= 384,
+	[16]		= 5,
+	[17]		= 10,
+	[18]		= 20,
+	[19]		= 40,
+	[20]		= 80,
+	[21]		= 160,
+	[22]		= 320,
+	[23]		= 604,
+};
+
+static unsigned long decode_div(unsigned long pll2, unsigned long val,
+				unsigned int lshft, unsigned int selbit,
+				unsigned long mask, const unsigned int *dtab)
+{
+	if (val & selbit)
+		pll2 = 288 * MHZ;
+
+	return pll2 / dtab[(val >> lshft) & mask];
+}
+
+#define fmt_freq(x) ((x) / MHZ), ((x) % MHZ), (x)
+
+/* sm501_dump_clk
+ *
+ * Print out the current clock configuration for the device
+*/
+
+static void sm501_dump_clk(struct sm501_devdata *sm)
+{
+	unsigned long misct = readl(sm->regs + SM501_MISC_TIMING);
+	unsigned long pm0 = readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
+	unsigned long pm1 = readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
+	unsigned long pmc = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	unsigned long sdclk0, sdclk1;
+	unsigned long pll2 = 0;
+
+	switch (misct & 0x30) {
+	case 0x00:
+		pll2 = 336 * MHZ;
+		break;
+	case 0x10:
+		pll2 = 288 * MHZ;
+		break;
+	case 0x20:
+		pll2 = 240 * MHZ;
+		break;
+	case 0x30:
+		pll2 = 192 * MHZ;
+		break;
+	}
+
+	sdclk0 = (misct & (1<<12)) ? pll2 : 288 * MHZ;
+	sdclk0 /= misc_div[((misct >> 8) & 0xf)];
+
+	sdclk1 = (misct & (1<<20)) ? pll2 : 288 * MHZ;
+	sdclk1 /= misc_div[((misct >> 16) & 0xf)];
+
+	dev_dbg(sm->dev, "MISCT=%08lx, PM0=%08lx, PM1=%08lx\n",
+		misct, pm0, pm1);
+
+	dev_dbg(sm->dev, "PLL2 = %ld.%ld MHz (%ld), SDCLK0=%08lx, SDCLK1=%08lx\n",
+		fmt_freq(pll2), sdclk0, sdclk1);
+
+	dev_dbg(sm->dev, "SDRAM: PM0=%ld, PM1=%ld\n", sdclk0, sdclk1);
+
+	dev_dbg(sm->dev, "PM0[%c]: "
+		 "P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), "
+x		 "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
+		 (pmc & 3 ) == 0 ? '*' : '-',
+		 fmt_freq(decode_div(pll2, pm0, 24, 1<<29, 31, px_div)),
+		 fmt_freq(decode_div(pll2, pm0, 16, 1<<20, 15, misc_div)),
+		 fmt_freq(decode_div(pll2, pm0, 8,  1<<12, 15, misc_div)),
+		 fmt_freq(decode_div(pll2, pm0, 0,  1<<4,  15, misc_div)));
+
+	dev_dbg(sm->dev, "PM1[%c]: "
+		"P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), "
+		"M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
+		(pmc & 3 ) == 1 ? '*' : '-',
+		fmt_freq(decode_div(pll2, pm1, 24, 1<<29, 31, px_div)),
+		fmt_freq(decode_div(pll2, pm1, 16, 1<<20, 15, misc_div)),
+		fmt_freq(decode_div(pll2, pm1, 8,  1<<12, 15, misc_div)),
+		fmt_freq(decode_div(pll2, pm1, 0,  1<<4,  15, misc_div)));
+}
+#else
+static void sm501_dump_clk(struct sm501_devdata *sm)
+{
+}
+#endif
+
+/* sm501_sync_regs
+ *
+ * ensure the
+*/
+
+static void sm501_sync_regs(struct sm501_devdata *sm)
+{
+	readl(sm->regs);
+}
+
+/* sm501_misc_control
+ *
+ * alters the misceleneous control parameters
+*/
+
+int sm501_misc_control(struct device *dev,
+		       unsigned long set, unsigned long clear)
+{
+	struct sm501_devdata *sm = dev_get_drvdata(dev);
+	unsigned long misc;
+	unsigned long save;
+	unsigned long to;
+
+	spin_lock_irqsave(&sm->reg_lock, save);
+
+	misc = readl(sm->regs + SM501_MISC_CONTROL);
+	to = (misc & ~clear) | set;
+
+	if (to != misc) {
+		writel(to, sm->regs + SM501_MISC_CONTROL);
+		sm501_sync_regs(sm);
+
+		dev_dbg(sm->dev, "MISC_CONTROL %08lx\n", misc);
+	}
+
+	spin_unlock_irqrestore(&sm->reg_lock, save);
+	return to;
+}
+
+EXPORT_SYMBOL_GPL(sm501_misc_control);
+
+/* sm501_modify_reg
+ *
+ * Modify a register in the SM501 which may be shared with other
+ * drivers.
+*/
+
+unsigned long sm501_modify_reg(struct device *dev,
+			       unsigned long reg,
+			       unsigned long set,
+			       unsigned long clear)
+{
+	struct sm501_devdata *sm = dev_get_drvdata(dev);
+	unsigned long data;
+	unsigned long save;
+
+	spin_lock_irqsave(&sm->reg_lock, save);
+
+	data = readl(sm->regs + reg);
+	data |= set;
+	data &= ~clear;
+
+	writel(data, sm->regs + reg);
+	sm501_sync_regs(sm);
+
+	spin_unlock_irqrestore(&sm->reg_lock, save);
+
+	return data;
+}
+
+EXPORT_SYMBOL_GPL(sm501_modify_reg);
+
+unsigned long sm501_gpio_get(struct device *dev,
+			     unsigned long gpio)
+{
+	struct sm501_devdata *sm = dev_get_drvdata(dev);
+	unsigned long result;
+	unsigned long reg;
+
+	reg = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW;
+	result = readl(sm->regs + reg);
+
+	result >>= (gpio & 31);
+	return result & 1UL;
+}
+
+EXPORT_SYMBOL_GPL(sm501_gpio_get);
+
+void sm501_gpio_set(struct device *dev,
+		    unsigned long gpio,
+		    unsigned int to,
+		    unsigned int dir)
+{
+	struct sm501_devdata *sm = dev_get_drvdata(dev);
+
+	unsigned long bit = 1 << (gpio & 31);
+	unsigned long base;
+	unsigned long save;
+	unsigned long val;
+
+	base = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW;
+	base += SM501_GPIO;
+
+	spin_lock_irqsave(&sm->reg_lock, save);
+
+	val = readl(sm->regs + base) & ~bit;
+	if (to)
+		val |= bit;
+	writel(val, sm->regs + base);
+
+	val = readl(sm->regs + SM501_GPIO_DDR_LOW) & ~bit;
+	if (dir)
+		val |= bit;
+
+	writel(val, sm->regs + SM501_GPIO_DDR_LOW);
+	sm501_sync_regs(sm);
+
+	spin_unlock_irqrestore(&sm->reg_lock, save);
+
+}
+
+EXPORT_SYMBOL_GPL(sm501_gpio_set);
+
+
+/* sm501_unit_power
+ *
+ * alters the power active gate to set specific units on or off
+ */
+
+int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
+{
+	struct sm501_devdata *sm = dev_get_drvdata(dev);
+	unsigned long mode;
+	unsigned long gate;
+	unsigned long clock;
+
+	mutex_lock(&sm->clock_lock);
+
+	mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	gate = readl(sm->regs + SM501_CURRENT_GATE);
+	clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+
+	mode &= 3;		/* get current power mode */
+
+	if (unit > ARRAY_SIZE(sm->unit_power)) {
+		dev_err(dev, "%s: bad unit %d\n", __FUNCTION__, unit);
+		goto already;
+	}
+
+	dev_dbg(sm->dev, "%s: unit %d, cur %d, to %d\n", __FUNCTION__, unit,
+		sm->unit_power[unit], to);
+
+	if (to == 0 && sm->unit_power[unit] == 0) {
+		dev_err(sm->dev, "unit %d is already shutdown\n", unit);
+		goto already;
+	}
+
+	sm->unit_power[unit] += to ? 1 : -1;
+	to = sm->unit_power[unit] ? 1 : 0;
+
+	if (to) {
+		if (gate & (1 << unit))
+			goto already;
+		gate |= (1 << unit);
+	} else {
+		if (!(gate & (1 << unit)))
+			goto already;
+		gate &= ~(1 << unit);
+	}
+
+	switch (mode) {
+	case 1:
+		writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+		writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+		mode = 0;
+		break;
+	case 2:
+	case 0:
+		writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+		writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+		mode = 1;
+		break;
+
+	default:
+		return -1;
+	}
+
+	writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+	sm501_sync_regs(sm);
+
+	dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
+		gate, clock, mode);
+
+	msleep(16);
+
+ already:
+	mutex_unlock(&sm->clock_lock);
+	return gate;
+}
+
+EXPORT_SYMBOL_GPL(sm501_unit_power);
+
+
+/* Perform a rounded division. */
+static long sm501fb_round_div(long num, long denom)
+{
+        /* n / d + 1 / 2 = (2n + d) / 2d */
+        return (2 * num + denom) / (2 * denom);
+}
+
+/* clock value structure. */
+struct sm501_clock {
+	unsigned long mclk;
+	int divider;
+	int shift;
+};
+
+/* sm501_select_clock
+ *
+ * selects nearest discrete clock frequency the SM501 can achive
+ *   the maximum divisor is 3 or 5
+ */
+static unsigned long sm501_select_clock(unsigned long freq,
+					struct sm501_clock *clock,
+					int max_div)
+{
+	unsigned long mclk;
+	int divider;
+	int shift;
+	long diff;
+	long best_diff = 999999999;
+
+	/* Try 288MHz and 336MHz clocks. */
+	for (mclk = 288000000; mclk <= 336000000; mclk += 48000000) {
+		/* try dividers 1 and 3 for CRT and for panel,
+		   try divider 5 for panel only.*/
+
+		for (divider = 1; divider <= max_div; divider += 2) {
+			/* try all 8 shift values.*/
+			for (shift = 0; shift < 8; shift++) {
+				/* Calculate difference to requested clock */
+				diff = sm501fb_round_div(mclk, divider << shift) - freq;
+				if (diff < 0)
+					diff = -diff;
+
+				/* If it is less than the current, use it */
+				if (diff < best_diff) {
+					best_diff = diff;
+
+					clock->mclk = mclk;
+					clock->divider = divider;
+					clock->shift = shift;
+				}
+			}
+		}
+	}
+
+	/* Return best clock. */
+	return clock->mclk / (clock->divider << clock->shift);
+}
+
+/* sm501_set_clock
+ *
+ * set one of the four clock sources to the closest available frequency to
+ *  the one specified
+*/
+
+unsigned long sm501_set_clock(struct device *dev,
+			      int clksrc,
+			      unsigned long req_freq)
+{
+	struct sm501_devdata *sm = dev_get_drvdata(dev);
+	unsigned long mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	unsigned long gate = readl(sm->regs + SM501_CURRENT_GATE);
+	unsigned long clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+	unsigned char reg;
+	unsigned long sm501_freq; /* the actual frequency acheived */
+
+	struct sm501_clock to;
+
+	/* find achivable discrete frequency and setup register value
+	 * accordingly, V2XCLK, MCLK and M1XCLK are the same P2XCLK
+	 * has an extra bit for the divider */
+
+	switch (clksrc) {
+	case SM501_CLOCK_P2XCLK:
+		/* This clock is divided in half so to achive the
+		 * requested frequency the value must be multiplied by
+		 * 2. This clock also has an additional pre divisor */
+
+		sm501_freq = (sm501_select_clock(2 * req_freq, &to, 5) / 2);
+		reg=to.shift & 0x07;/* bottom 3 bits are shift */
+		if (to.divider == 3)
+			reg |= 0x08; /* /3 divider required */
+		else if (to.divider == 5)
+			reg |= 0x10; /* /5 divider required */
+		if (to.mclk != 288000000)
+			reg |= 0x20; /* which mclk pll is source */
+		break;
+
+	case SM501_CLOCK_V2XCLK:
+		/* This clock is divided in half so to achive the
+		 * requested frequency the value must be multiplied by 2. */
+
+		sm501_freq = (sm501_select_clock(2 * req_freq, &to, 3) / 2);
+		reg=to.shift & 0x07;	/* bottom 3 bits are shift */
+		if (to.divider == 3)
+			reg |= 0x08;	/* /3 divider required */
+		if (to.mclk != 288000000)
+			reg |= 0x10;	/* which mclk pll is source */
+		break;
+
+	case SM501_CLOCK_MCLK:
+	case SM501_CLOCK_M1XCLK:
+		/* These clocks are the same and not further divided */
+
+		sm501_freq = sm501_select_clock( req_freq, &to, 3);
+		reg=to.shift & 0x07;	/* bottom 3 bits are shift */
+		if (to.divider == 3)
+			reg |= 0x08;	/* /3 divider required */
+		if (to.mclk != 288000000)
+			reg |= 0x10;	/* which mclk pll is source */
+		break;
+
+	default:
+		return 0; /* this is bad */
+	}
+
+	mutex_lock(&sm->clock_lock);
+
+	mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	gate = readl(sm->regs + SM501_CURRENT_GATE);
+	clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+
+	clock = clock & ~(0xFF << clksrc);
+	clock |= reg<<clksrc;
+
+	mode &= 3;	/* find current mode */
+
+	switch (mode) {
+	case 1:
+		writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+		writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+		mode = 0;
+		break;
+	case 2:
+	case 0:
+		writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+		writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+		mode = 1;
+		break;
+
+	default:
+		mutex_unlock(&sm->clock_lock);
+		return -1;
+	}
+
+	writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+	sm501_sync_regs(sm);
+
+	dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
+		 gate, clock, mode);
+
+	msleep(16);
+	mutex_unlock(&sm->clock_lock);
+
+	sm501_dump_clk(sm);
+
+	return sm501_freq;
+}
+
+EXPORT_SYMBOL_GPL(sm501_set_clock);
+
+/* sm501_find_clock
+ *
+ * finds the closest available frequency for a given clock
+*/
+
+unsigned long sm501_find_clock(int clksrc,
+			       unsigned long req_freq)
+{
+	unsigned long sm501_freq; /* the frequency achiveable by the 501 */
+	struct sm501_clock to;
+
+	switch (clksrc) {
+	case SM501_CLOCK_P2XCLK:
+		sm501_freq = (sm501_select_clock(2 * req_freq, &to, 5) / 2);
+		break;
+
+	case SM501_CLOCK_V2XCLK:
+		sm501_freq = (sm501_select_clock(2 * req_freq, &to, 3) / 2);
+		break;
+
+	case SM501_CLOCK_MCLK:
+	case SM501_CLOCK_M1XCLK:
+		sm501_freq = sm501_select_clock(req_freq, &to, 3);
+		break;
+
+	default:
+		sm501_freq = 0;		/* error */
+	}
+
+	return sm501_freq;
+}
+
+EXPORT_SYMBOL_GPL(sm501_find_clock);
+
+static struct sm501_device *to_sm_device(struct platform_device *pdev)
+{
+	return container_of(pdev, struct sm501_device, pdev);
+}
+
+/* sm501_device_release
+ *
+ * A release function for the platform devices we create to allow us to
+ * free any items we allocated
+*/
+
+static void sm501_device_release(struct device *dev)
+{
+	kfree(to_sm_device(to_platform_device(dev)));
+}
+
+/* sm501_create_subdev
+ *
+ * Create a skeleton platform device with resources for passing to a
+ * sub-driver
+*/
+
+static struct platform_device *
+sm501_create_subdev(struct sm501_devdata *sm,
+		    char *name, unsigned int res_count)
+{
+	struct sm501_device *smdev;
+
+	smdev = kzalloc(sizeof(struct sm501_device) +
+			sizeof(struct resource) * res_count, GFP_KERNEL);
+	if (!smdev)
+		return NULL;
+
+	smdev->pdev.dev.release = sm501_device_release;
+
+	smdev->pdev.name = name;
+	smdev->pdev.id = sm->pdev_id;
+	smdev->pdev.resource = (struct resource *)(smdev+1);
+	smdev->pdev.num_resources = res_count;
+
+	smdev->pdev.dev.parent = sm->dev;
+
+	return &smdev->pdev;
+}
+
+/* sm501_register_device
+ *
+ * Register a platform device created with sm501_create_subdev()
+*/
+
+static int sm501_register_device(struct sm501_devdata *sm,
+				 struct platform_device *pdev)
+{
+	struct sm501_device *smdev = to_sm_device(pdev);
+	int ptr;
+	int ret;
+
+	for (ptr = 0; ptr < pdev->num_resources; ptr++) {
+		printk("%s[%d] flags %08lx: %08llx..%08llx\n",
+		       pdev->name, ptr,
+		       pdev->resource[ptr].flags,
+		       (unsigned long long)pdev->resource[ptr].start,
+		       (unsigned long long)pdev->resource[ptr].end);
+	}
+
+	ret = platform_device_register(pdev);
+
+	if (ret >= 0) {
+		dev_dbg(sm->dev, "registered %s\n", pdev->name);
+		list_add_tail(&smdev->list, &sm->devices);
+	} else
+		dev_err(sm->dev, "error registering %s (%d)\n",
+			pdev->name, ret);
+
+	return ret;
+}
+
+/* sm501_create_subio
+ *
+ * Fill in an IO resource for a sub device
+*/
+
+static void sm501_create_subio(struct sm501_devdata *sm,
+			       struct resource *res,
+			       resource_size_t offs,
+			       resource_size_t size)
+{
+	res->flags = IORESOURCE_MEM;
+	res->parent = sm->io_res;
+	res->start = sm->io_res->start + offs;
+	res->end = res->start + size - 1;
+}
+
+/* sm501_create_mem
+ *
+ * Fill in an MEM resource for a sub device
+*/
+
+static void sm501_create_mem(struct sm501_devdata *sm,
+			     struct resource *res,
+			     resource_size_t *offs,
+			     resource_size_t size)
+{
+	*offs -= size;		/* adjust memory size */
+
+	res->flags = IORESOURCE_MEM;
+	res->parent = sm->mem_res;
+	res->start = sm->mem_res->start + *offs;
+	res->end = res->start + size - 1;
+}
+
+/* sm501_create_irq
+ *
+ * Fill in an IRQ resource for a sub device
+*/
+
+static void sm501_create_irq(struct sm501_devdata *sm,
+			     struct resource *res)
+{
+	res->flags = IORESOURCE_IRQ;
+	res->parent = NULL;
+	res->start = res->end = sm->irq;
+}
+
+static int sm501_register_usbhost(struct sm501_devdata *sm,
+				  resource_size_t *mem_avail)
+{
+	struct platform_device *pdev;
+
+	pdev = sm501_create_subdev(sm, "sm501-usb", 3);
+	if (!pdev)
+		return -ENOMEM;
+
+	sm501_create_subio(sm, &pdev->resource[0], 0x40000, 0x20000);
+	sm501_create_mem(sm, &pdev->resource[1], mem_avail, 256*1024);
+	sm501_create_irq(sm, &pdev->resource[2]);
+
+	return sm501_register_device(sm, pdev);
+}
+
+static int sm501_register_display(struct sm501_devdata *sm,
+				  resource_size_t *mem_avail)
+{
+	struct platform_device *pdev;
+
+	pdev = sm501_create_subdev(sm, "sm501-fb", 4);
+	if (!pdev)
+		return -ENOMEM;
+
+	sm501_create_subio(sm, &pdev->resource[0], 0x80000, 0x10000);
+	sm501_create_subio(sm, &pdev->resource[1], 0x100000, 0x50000);
+	sm501_create_mem(sm, &pdev->resource[2], mem_avail, *mem_avail);
+	sm501_create_irq(sm, &pdev->resource[3]);
+
+	return sm501_register_device(sm, pdev);
+}
+
+/* sm501_dbg_regs
+ *
+ * Debug attribute to attach to parent device to show core registers
+*/
+
+static ssize_t sm501_dbg_regs(struct device *dev,
+			      struct device_attribute *attr, char *buff)
+{
+	struct sm501_devdata *sm = dev_get_drvdata(dev)	;
+	unsigned int reg;
+	char *ptr = buff;
+	int ret;
+
+	for (reg = 0x00; reg < 0x70; reg += 4) {
+		ret = sprintf(ptr, "%08x = %08x\n",
+			      reg, readl(sm->regs + reg));
+		ptr += ret;
+	}
+
+	return ptr - buff;
+}
+
+
+static DEVICE_ATTR(dbg_regs, 0666, sm501_dbg_regs, NULL);
+
+/* sm501_init_reg
+ *
+ * Helper function for the init code to setup a register
+*/
+
+static inline void sm501_init_reg(struct sm501_devdata *sm,
+				  unsigned long reg,
+				  struct sm501_reg_init *r)
+{
+	unsigned long tmp;
+
+	tmp = readl(sm->regs + reg);
+	tmp |= r->set;
+	tmp &= ~r->mask;
+	writel(tmp, sm->regs + reg);
+}
+
+/* sm501_init_regs
+ *
+ * Setup core register values
+*/
+
+static void sm501_init_regs(struct sm501_devdata *sm,
+			    struct sm501_initdata *init)
+{
+	sm501_misc_control(sm->dev,
+			   init->misc_control.set,
+			   init->misc_control.mask);
+
+	sm501_init_reg(sm, SM501_MISC_TIMING, &init->misc_timing);
+	sm501_init_reg(sm, SM501_GPIO31_0_CONTROL, &init->gpio_low);
+	sm501_init_reg(sm, SM501_GPIO63_32_CONTROL, &init->gpio_high);
+
+	if (init->mclk) {
+		dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk);
+		sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk);
+	}
+
+	if (init->m1xclk) {
+		dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk);
+		sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk);
+	}
+}
+
+static unsigned int sm501_mem_local[] = {
+	[0]	= 4*1024*1024,
+	[1]	= 8*1024*1024,
+	[2]	= 16*1024*1024,
+	[3]	= 32*1024*1024,
+	[4]	= 64*1024*1024,
+	[5]	= 2*1024*1024,
+};
+
+/* sm501_init_dev
+ *
+ * Common init code for an SM501
+*/
+
+static int sm501_init_dev(struct sm501_devdata *sm)
+{
+	resource_size_t mem_avail;
+	unsigned long dramctrl;
+	int ret;
+
+	mutex_init(&sm->clock_lock);
+	spin_lock_init(&sm->reg_lock);
+
+	INIT_LIST_HEAD(&sm->devices);
+
+	dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
+
+	mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
+
+	dev_info(sm->dev, "SM501 At %p: Version %08x, %ld Mb, IRQ %d\n",
+		 sm->regs, readl(sm->regs + SM501_DEVICEID),
+		 (unsigned long)mem_avail >> 20, sm->irq);
+
+	dev_info(sm->dev, "CurrentGate      %08x\n", readl(sm->regs+0x38));
+	dev_info(sm->dev, "CurrentClock     %08x\n", readl(sm->regs+0x3c));
+	dev_info(sm->dev, "PowerModeControl %08x\n", readl(sm->regs+0x54));
+
+	ret = device_create_file(sm->dev, &dev_attr_dbg_regs);
+	if (ret)
+		dev_err(sm->dev, "failed to create debug regs file\n");
+
+	sm501_dump_clk(sm);
+
+	/* check to see if we have some device initialisation */
+
+	if (sm->platdata) {
+		struct sm501_platdata *pdata = sm->platdata;
+
+		if (pdata->init) {
+			sm501_init_regs(sm, sm->platdata->init);
+
+			if (pdata->init->devices & SM501_USE_USB_HOST)
+				sm501_register_usbhost(sm, &mem_avail);
+		}
+	}
+
+	/* always create a framebuffer */
+	sm501_register_display(sm, &mem_avail);
+
+	return 0;
+}
+
+static int sm501_plat_probe(struct platform_device *dev)
+{
+	struct sm501_devdata *sm;
+	int err;
+
+	sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
+	if (sm == NULL) {
+		dev_err(&dev->dev, "no memory for device data\n");
+		err = -ENOMEM;
+		goto err1;
+	}
+
+	sm->dev = &dev->dev;
+	sm->pdev_id = dev->id;
+	sm->irq = platform_get_irq(dev, 0);
+	sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+	sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	sm->platdata = dev->dev.platform_data;
+
+	if (sm->irq < 0) {
+		dev_err(&dev->dev, "failed to get irq resource\n");
+		err = sm->irq;
+		goto err_res;
+	}
+
+	if (sm->io_res == NULL || sm->mem_res == NULL) {
+		dev_err(&dev->dev, "failed to get IO resource\n");
+		err = -ENOENT;
+		goto err_res;
+	}
+
+	sm->regs_claim = request_mem_region(sm->io_res->start,
+					    0x100, "sm501");
+
+	if (sm->regs_claim == NULL) {
+		dev_err(&dev->dev, "cannot claim registers\n");
+		err= -EBUSY;
+		goto err_res;
+	}
+
+	platform_set_drvdata(dev, sm);
+
+	sm->regs = ioremap(sm->io_res->start,
+			   (sm->io_res->end - sm->io_res->start) - 1);
+
+	if (sm->regs == NULL) {
+		dev_err(&dev->dev, "cannot remap registers\n");
+		err = -EIO;
+		goto err_claim;
+	}
+
+	return sm501_init_dev(sm);
+
+ err_claim:
+	release_resource(sm->regs_claim);
+	kfree(sm->regs_claim);
+ err_res:
+	kfree(sm);
+ err1:
+	return err;
+
+}
+
+/* Initialisation data for PCI devices */
+
+static struct sm501_initdata sm501_pci_initdata = {
+	.gpio_high	= {
+		.set	= 0x3F000000,		/* 24bit panel */
+		.mask	= 0x0,
+	},
+	.misc_timing	= {
+		.set	= 0x010100,		/* SDRAM timing */
+		.mask	= 0x1F1F00,
+	},
+	.misc_control	= {
+		.set	= SM501_MISC_PNL_24BIT,
+		.mask	= 0,
+	},
+
+	.devices	= SM501_USE_ALL,
+	.mclk		= 100 * MHZ,
+	.m1xclk		= 160 * MHZ,
+};
+
+static struct sm501_platdata_fbsub sm501_pdata_fbsub = {
+	.flags		= (SM501FB_FLAG_USE_INIT_MODE |
+			   SM501FB_FLAG_USE_HWCURSOR |
+			   SM501FB_FLAG_USE_HWACCEL |
+			   SM501FB_FLAG_DISABLE_AT_EXIT),
+};
+
+static struct sm501_platdata_fb sm501_fb_pdata = {
+	.fb_route	= SM501_FB_OWN,
+	.fb_crt		= &sm501_pdata_fbsub,
+	.fb_pnl		= &sm501_pdata_fbsub,
+};
+
+static struct sm501_platdata sm501_pci_platdata = {
+	.init		= &sm501_pci_initdata,
+	.fb		= &sm501_fb_pdata,
+};
+
+static int sm501_pci_probe(struct pci_dev *dev,
+			   const struct pci_device_id *id)
+{
+	struct sm501_devdata *sm;
+	int err;
+
+	sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
+	if (sm == NULL) {
+		dev_err(&dev->dev, "no memory for device data\n");
+		err = -ENOMEM;
+		goto err1;
+	}
+
+	/* set a default set of platform data */
+	dev->dev.platform_data = sm->platdata = &sm501_pci_platdata;
+
+	/* set a hopefully unique id for our child platform devices */
+	sm->pdev_id = 32 + dev->devfn;
+
+	pci_set_drvdata(dev, sm);
+
+	err = pci_enable_device(dev);
+	if (err) {
+		dev_err(&dev->dev, "cannot enable device\n");
+		goto err2;
+	}
+
+	sm->dev = &dev->dev;
+	sm->irq = dev->irq;
+
+#ifdef __BIG_ENDIAN
+	/* if the system is big-endian, we most probably have a
+	 * translation in the IO layer making the PCI bus little endian
+	 * so make the framebuffer swapped pixels */
+
+	sm501_fb_pdata.flags |= SM501_FBPD_SWAP_FB_ENDIAN;
+#endif
+
+	/* check our resources */
+
+	if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM)) {
+		dev_err(&dev->dev, "region #0 is not memory?\n");
+		err = -EINVAL;
+		goto err3;
+	}
+
+	if (!(pci_resource_flags(dev, 1) & IORESOURCE_MEM)) {
+		dev_err(&dev->dev, "region #1 is not memory?\n");
+		err = -EINVAL;
+		goto err3;
+	}
+
+	/* make our resources ready for sharing */
+
+	sm->io_res = &dev->resource[1];
+	sm->mem_res = &dev->resource[0];
+
+	sm->regs_claim = request_mem_region(sm->io_res->start,
+					    0x100, "sm501");
+	if (sm->regs_claim == NULL) {
+		dev_err(&dev->dev, "cannot claim registers\n");
+		err= -EBUSY;
+		goto err3;
+	}
+
+	sm->regs = ioremap(pci_resource_start(dev, 1),
+			   pci_resource_len(dev, 1));
+
+	if (sm->regs == NULL) {
+		dev_err(&dev->dev, "cannot remap registers\n");
+		err = -EIO;
+		goto err4;
+	}
+
+	sm501_init_dev(sm);
+	return 0;
+
+ err4:
+	release_resource(sm->regs_claim);
+	kfree(sm->regs_claim);
+ err3:
+	pci_disable_device(dev);
+ err2:
+	pci_set_drvdata(dev, NULL);
+	kfree(sm);
+ err1:
+	return err;
+}
+
+static void sm501_remove_sub(struct sm501_devdata *sm,
+			     struct sm501_device *smdev)
+{
+	list_del(&smdev->list);
+	platform_device_unregister(&smdev->pdev);
+}
+
+static void sm501_dev_remove(struct sm501_devdata *sm)
+{
+	struct sm501_device *smdev, *tmp;
+
+	list_for_each_entry_safe(smdev, tmp, &sm->devices, list)
+		sm501_remove_sub(sm, smdev);
+
+	device_remove_file(sm->dev, &dev_attr_dbg_regs);
+}
+
+static void sm501_pci_remove(struct pci_dev *dev)
+{
+	struct sm501_devdata *sm = pci_get_drvdata(dev);
+
+	sm501_dev_remove(sm);
+	iounmap(sm->regs);
+
+	release_resource(sm->regs_claim);
+	kfree(sm->regs_claim);
+
+	pci_set_drvdata(dev, NULL);
+	pci_disable_device(dev);
+}
+
+static int sm501_plat_remove(struct platform_device *dev)
+{
+	struct sm501_devdata *sm = platform_get_drvdata(dev);
+
+	sm501_dev_remove(sm);
+	iounmap(sm->regs);
+
+	release_resource(sm->regs_claim);
+	kfree(sm->regs_claim);
+
+	return 0;
+}
+
+static struct pci_device_id sm501_pci_tbl[] = {
+	{ 0x126f, 0x0501, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, sm501_pci_tbl);
+
+static struct pci_driver sm501_pci_drv = {
+	.name		= "sm501",
+	.id_table	= sm501_pci_tbl,
+	.probe		= sm501_pci_probe,
+	.remove		= sm501_pci_remove,
+};
+
+static struct platform_driver sm501_plat_drv = {
+	.driver		= {
+		.name	= "sm501",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sm501_plat_probe,
+	.remove		= sm501_plat_remove,
+};
+
+static int __init sm501_base_init(void)
+{
+	platform_driver_register(&sm501_plat_drv);
+	return pci_module_init(&sm501_pci_drv);
+}
+
+static void __exit sm501_base_exit(void)
+{
+	platform_driver_unregister(&sm501_plat_drv);
+	pci_unregister_driver(&sm501_pci_drv);
+}
+
+module_init(sm501_base_init);
+module_exit(sm501_base_exit);
+
+MODULE_DESCRIPTION("SM501 Core Driver");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, Vincent Sanders");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 89bba27..80b199f 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -42,7 +42,7 @@
 
 config TIFM_CORE
 	tristate "TI Flash Media interface support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	depends on EXPERIMENTAL && PCI
 	help
 	  If you want support for Texas Instruments(R) Flash Media adapters
 	  you should select this option and then also choose an appropriate
@@ -107,4 +107,19 @@
 
 	  If you have an MSI S270 laptop, say Y or M here.
 
+config SONY_LAPTOP
+	tristate "Sony Laptop Extras"
+	depends on X86 && ACPI
+	select BACKLIGHT_CLASS_DEVICE
+	  ---help---
+	  This mini-driver drives the SNC device present in the ACPI BIOS of
+	  the Sony Vaio laptops.
+
+	  It gives access to some extra laptop functionalities. In its current
+	  form, this driver let the user set or query the screen brightness
+	  through the backlight subsystem and remove/apply power to some
+	  devices.
+
+	  Read <file:Documentation/sony-laptop.txt> for more information.
+
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 35da53c..7793ccd 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -11,3 +11,4 @@
 obj-$(CONFIG_TIFM_CORE)       	+= tifm_core.o
 obj-$(CONFIG_TIFM_7XX1)       	+= tifm_7xx1.o
 obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
+obj-$(CONFIG_SONY_LAPTOP)	+= sony-laptop.o
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 861c399..295e931 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -195,11 +195,9 @@
  */
 static int read_brightness(struct backlight_device *bd);
 static int update_bl_status(struct backlight_device *bd);
-static struct backlight_properties asusbl_data = {
-	.owner = THIS_MODULE,
+static struct backlight_ops asusbl_ops = {
 	.get_brightness = read_brightness,
 	.update_status = update_bl_status,
-	.max_brightness = 15,
 };
 
 /* These functions actually update the LED's, and are called from a
@@ -349,13 +347,8 @@
 	struct backlight_device *bd = asus_backlight_device;
 
 	if (bd) {
-		down(&bd->sem);
-		if (likely(bd->props)) {
-			bd->props->power = blank;
-			if (likely(bd->props->update_status))
-				bd->props->update_status(bd);
-		}
-		up(&bd->sem);
+		bd->props.power = blank;
+		backlight_update_status(bd);
 	}
 }
 
@@ -387,13 +380,13 @@
 static int update_bl_status(struct backlight_device *bd)
 {
 	int rv;
-	int value = bd->props->brightness;
+	int value = bd->props.brightness;
 
 	rv = set_brightness(bd, value);
 	if (rv)
 		return rv;
 
-	value = (bd->props->power == FB_BLANK_UNBLANK) ? 1 : 0;
+	value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
 	return set_lcd_state(value);
 }
 
@@ -1019,7 +1012,7 @@
 
 	if (brightness_set_handle && lcd_switch_handle) {
 		bd = backlight_device_register(ASUS_HOTK_FILE, dev,
-					       NULL, &asusbl_data);
+					       NULL, &asusbl_ops);
 		if (IS_ERR(bd)) {
 			printk(ASUS_ERR
 			       "Could not register asus backlight device\n");
@@ -1029,14 +1022,10 @@
 
 		asus_backlight_device = bd;
 
-		down(&bd->sem);
-		if (likely(bd->props)) {
-			bd->props->brightness = read_brightness(NULL);
-			bd->props->power = FB_BLANK_UNBLANK;
-			if (likely(bd->props->update_status))
-				bd->props->update_status(bd);
-		}
-		up(&bd->sem);
+		bd->props.max_brightness = 15;
+		bd->props.brightness = read_brightness(NULL);
+		bd->props.power = FB_BLANK_UNBLANK;
+		backlight_update_status(bd);
 	}
 	return 0;
 }
@@ -1088,11 +1077,6 @@
 	if (acpi_disabled)
 		return -ENODEV;
 
-	if (!acpi_specific_hotkey_enabled) {
-		printk(ASUS_ERR "Using generic hotkey driver\n");
-		return -ENODEV;
-	}
-
 	result = acpi_bus_register_driver(&asus_hotk_driver);
 	if (result < 0)
 		return result;
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
index 11a801b..ca86f11 100644
--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
+++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
@@ -169,7 +169,7 @@
 /*
  *	The various file operations we support.
  */
-static struct file_operations cpustate_fops = {
+static const struct file_operations cpustate_fops = {
       owner:THIS_MODULE,
       open:cpustate_open,
       release:cpustate_release,
diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
index ea9d5f23..6a51e99 100644
--- a/drivers/misc/hdpuftrs/hdpu_nexus.c
+++ b/drivers/misc/hdpuftrs/hdpu_nexus.c
@@ -72,11 +72,9 @@
 		printk("Could not map slot id\n");
 	hdpu_slot_id = create_proc_entry("sky_slot_id", 0666, &proc_root);
 	hdpu_slot_id->read_proc = hdpu_slot_id_read;
-	hdpu_slot_id->nlink = 1;
 
 	hdpu_chassis_id = create_proc_entry("sky_chassis_id", 0666, &proc_root);
 	hdpu_chassis_id->read_proc = hdpu_chassis_id_read;
-	hdpu_chassis_id->nlink = 1;
 	return 0;
 }
 
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index b99dc50..c436d3d 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -156,7 +156,7 @@
 static struct dentry *ibmasmfs_create_file (struct super_block *sb,
 			struct dentry *parent,
 		       	const char *name,
-			struct file_operations *fops,
+			const struct file_operations *fops,
 			void *data,
 			int mode)
 {
@@ -581,28 +581,28 @@
 	return count;
 }
 
-static struct file_operations command_fops = {
+static const struct file_operations command_fops = {
 	.open =		command_file_open,
 	.release =	command_file_close,
 	.read =		command_file_read,
 	.write =	command_file_write,
 };
 
-static struct file_operations event_fops = {
+static const struct file_operations event_fops = {
 	.open =		event_file_open,
 	.release =	event_file_close,
 	.read =		event_file_read,
 	.write =	event_file_write,
 };
 
-static struct file_operations r_heartbeat_fops = {
+static const struct file_operations r_heartbeat_fops = {
 	.open =		r_heartbeat_file_open,
 	.release =	r_heartbeat_file_close,
 	.read =		r_heartbeat_file_read,
 	.write =	r_heartbeat_file_write,
 };
 
-static struct file_operations remote_settings_fops = {
+static const struct file_operations remote_settings_fops = {
 	.open =		remote_settings_file_open,
 	.release =	remote_settings_file_close,
 	.read =		remote_settings_file_read,
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
index b995a15..6a5a05d 100644
--- a/drivers/misc/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -309,7 +309,7 @@
 		ret = -ENODEV;
 		goto out_pci;
 	}
-	if (!request_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
+	if (!request_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
 			    "ioc4_misc")) {
 		printk(KERN_WARNING
 		       "%s: Unable to request IOC4 misc region "
@@ -379,7 +379,7 @@
 	return 0;
 
 out_misc_region:
-	release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
+	release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
 out_pci:
 	kfree(idd);
 out_idd:
@@ -418,7 +418,7 @@
 		       "Device removal may be incomplete.\n",
 		       __FUNCTION__, pci_name(idd->idd_pdev));
 	}
-	release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
+	release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
 
 	/* Disable IOC4 and relinquish */
 	pci_disable_device(pdev);
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index db9d7df..552b795 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -108,8 +108,8 @@
 static int lkdtm_parse_commandline(void);
 static void lkdtm_handler(void);
 
-static char* cpoint_name = INVALID;
-static char* cpoint_type = NONE;
+static char* cpoint_name;
+static char* cpoint_type;
 static int cpoint_count = DEFAULT_COUNT;
 static int recur_count = REC_NUM_DEFAULT;
 
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index 8e5e07e..68c4b58 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -157,14 +157,12 @@
 
 static int bl_update_status(struct backlight_device *b)
 {
-	return set_lcd_level(b->props->brightness);
+	return set_lcd_level(b->props.brightness);
 }
 
-static struct backlight_properties msibl_props = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops msibl_ops = {
 	.get_brightness = bl_get_brightness,
 	.update_status  = bl_update_status,
-	.max_brightness = MSI_LCD_LEVEL_MAX-1,
 };
 
 static struct backlight_device *msibl_device;
@@ -318,10 +316,12 @@
 	/* Register backlight stuff */
 
 	msibl_device = backlight_device_register("msi-laptop-bl", NULL, NULL,
-						&msibl_props);
+						&msibl_ops);
 	if (IS_ERR(msibl_device))
 		return PTR_ERR(msibl_device);
 
+	msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1,
+
 	ret = platform_driver_register(&msipf_driver);
 	if (ret)
 		goto fail_backlight;
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
new file mode 100644
index 0000000..2ebe240
--- /dev/null
+++ b/drivers/misc/sony-laptop.c
@@ -0,0 +1,564 @@
+/*
+ * ACPI Sony Notebook Control Driver (SNC)
+ *
+ * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
+ * Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
+ *
+ * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
+ * which are copyrighted by their respective authors.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/backlight.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/acpi_bus.h>
+#include <asm/uaccess.h>
+
+#define ACPI_SNC_CLASS		"sony"
+#define ACPI_SNC_HID		"SNY5001"
+#define ACPI_SNC_DRIVER_NAME	"ACPI Sony Notebook Control Driver v0.4"
+
+/* the device uses 1-based values, while the backlight subsystem uses
+   0-based values */
+#define SONY_MAX_BRIGHTNESS	8
+
+#define LOG_PFX			KERN_WARNING "sony-laptop: "
+
+MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
+MODULE_DESCRIPTION(ACPI_SNC_DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
+		 "the development of this driver");
+
+static ssize_t sony_acpi_show(struct device *, struct device_attribute *,
+			      char *);
+static ssize_t sony_acpi_store(struct device *, struct device_attribute *,
+			       const char *, size_t);
+static int boolean_validate(const int, const int);
+static int brightness_default_validate(const int, const int);
+
+#define SNC_VALIDATE_IN		0
+#define SNC_VALIDATE_OUT	1
+
+struct sony_acpi_value {
+	char *name;		/* name of the entry */
+	char **acpiget;		/* names of the ACPI get function */
+	char **acpiset;		/* names of the ACPI set function */
+	int (*validate)(const int, const int);	/* input/output validation */
+	int value;		/* current setting */
+	int valid;		/* Has ever been set */
+	int debug;		/* active only in debug mode ? */
+	struct device_attribute devattr;	/* sysfs atribute */
+};
+
+#define HANDLE_NAMES(_name, _values...) \
+	static char *snc_##_name[] = { _values, NULL }
+
+#define SONY_ACPI_VALUE(_name, _getters, _setters, _validate, _debug) \
+	{ \
+		.name		= __stringify(_name), \
+		.acpiget	= _getters, \
+		.acpiset	= _setters, \
+		.validate	= _validate, \
+		.debug		= _debug, \
+		.devattr	= __ATTR(_name, 0, sony_acpi_show, sony_acpi_store), \
+	}
+
+#define SONY_ACPI_VALUE_NULL	{ .name = NULL }
+
+HANDLE_NAMES(fnkey_get, "GHKE");
+
+HANDLE_NAMES(brightness_def_get, "GPBR");
+HANDLE_NAMES(brightness_def_set, "SPBR");
+
+HANDLE_NAMES(cdpower_get, "GCDP");
+HANDLE_NAMES(cdpower_set, "SCDP", "CDPW");
+
+HANDLE_NAMES(audiopower_get, "GAZP");
+HANDLE_NAMES(audiopower_set, "AZPW");
+
+HANDLE_NAMES(lanpower_get, "GLNP");
+HANDLE_NAMES(lanpower_set, "LNPW");
+
+HANDLE_NAMES(PID_get, "GPID");
+
+HANDLE_NAMES(CTR_get, "GCTR");
+HANDLE_NAMES(CTR_set, "SCTR");
+
+HANDLE_NAMES(PCR_get, "GPCR");
+HANDLE_NAMES(PCR_set, "SPCR");
+
+HANDLE_NAMES(CMI_get, "GCMI");
+HANDLE_NAMES(CMI_set, "SCMI");
+
+static struct sony_acpi_value sony_acpi_values[] = {
+	SONY_ACPI_VALUE(brightness_default, snc_brightness_def_get,
+			snc_brightness_def_set, brightness_default_validate, 0),
+	SONY_ACPI_VALUE(fnkey, snc_fnkey_get, NULL, NULL, 0),
+	SONY_ACPI_VALUE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
+	SONY_ACPI_VALUE(audiopower, snc_audiopower_get, snc_audiopower_set,
+			boolean_validate, 0),
+	SONY_ACPI_VALUE(lanpower, snc_lanpower_get, snc_lanpower_set,
+			boolean_validate, 1),
+	/* unknown methods */
+	SONY_ACPI_VALUE(PID, snc_PID_get, NULL, NULL, 1),
+	SONY_ACPI_VALUE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
+	SONY_ACPI_VALUE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
+	SONY_ACPI_VALUE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
+	SONY_ACPI_VALUE_NULL
+};
+
+static acpi_handle sony_acpi_handle;
+static struct acpi_device *sony_acpi_acpi_device = NULL;
+
+/*
+ * acpi_evaluate_object wrappers
+ */
+static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)
+{
+	struct acpi_buffer output;
+	union acpi_object out_obj;
+	acpi_status status;
+
+	output.length = sizeof(out_obj);
+	output.pointer = &out_obj;
+
+	status = acpi_evaluate_object(handle, name, NULL, &output);
+	if ((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)) {
+		*result = out_obj.integer.value;
+		return 0;
+	}
+
+	printk(LOG_PFX "acpi_callreadfunc failed\n");
+
+	return -1;
+}
+
+static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
+			    int *result)
+{
+	struct acpi_object_list params;
+	union acpi_object in_obj;
+	struct acpi_buffer output;
+	union acpi_object out_obj;
+	acpi_status status;
+
+	params.count = 1;
+	params.pointer = &in_obj;
+	in_obj.type = ACPI_TYPE_INTEGER;
+	in_obj.integer.value = value;
+
+	output.length = sizeof(out_obj);
+	output.pointer = &out_obj;
+
+	status = acpi_evaluate_object(handle, name, &params, &output);
+	if (status == AE_OK) {
+		if (result != NULL) {
+			if (out_obj.type != ACPI_TYPE_INTEGER) {
+				printk(LOG_PFX "acpi_evaluate_object bad "
+				       "return type\n");
+				return -1;
+			}
+			*result = out_obj.integer.value;
+		}
+		return 0;
+	}
+
+	printk(LOG_PFX "acpi_evaluate_object failed\n");
+
+	return -1;
+}
+
+/*
+ * sony_acpi_values input/output validate functions
+ */
+
+/* brightness_default_validate:
+ *
+ * manipulate input output values to keep consistency with the
+ * backlight framework for which brightness values are 0-based.
+ */
+static int brightness_default_validate(const int direction, const int value)
+{
+	switch (direction) {
+		case SNC_VALIDATE_OUT:
+			return value - 1;
+		case SNC_VALIDATE_IN:
+			if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
+				return value + 1;
+	}
+	return -EINVAL;
+}
+
+/* boolean_validate:
+ *
+ * on input validate boolean values 0/1, on output just pass the
+ * received value.
+ */
+static int boolean_validate(const int direction, const int value)
+{
+	if (direction == SNC_VALIDATE_IN) {
+		if (value != 0 && value != 1)
+			return -EINVAL;
+	}
+	return value;
+}
+
+/*
+ * Sysfs show/store common to all sony_acpi_values
+ */
+static ssize_t sony_acpi_show(struct device *dev, struct device_attribute *attr,
+			      char *buffer)
+{
+	int value;
+	struct sony_acpi_value *item =
+	    container_of(attr, struct sony_acpi_value, devattr);
+
+	if (!*item->acpiget)
+		return -EIO;
+
+	if (acpi_callgetfunc(sony_acpi_handle, *item->acpiget, &value) < 0)
+		return -EIO;
+
+	if (item->validate)
+		value = item->validate(SNC_VALIDATE_OUT, value);
+
+	return snprintf(buffer, PAGE_SIZE, "%d\n", value);
+}
+
+static ssize_t sony_acpi_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buffer, size_t count)
+{
+	int value;
+	struct sony_acpi_value *item =
+	    container_of(attr, struct sony_acpi_value, devattr);
+
+	if (!item->acpiset)
+		return -EIO;
+
+	if (count > 31)
+		return -EINVAL;
+
+	value = simple_strtoul(buffer, NULL, 10);
+
+	if (item->validate)
+		value = item->validate(SNC_VALIDATE_IN, value);
+
+	if (value < 0)
+		return value;
+
+	if (acpi_callsetfunc(sony_acpi_handle, *item->acpiset, value, NULL) < 0)
+		return -EIO;
+	item->value = value;
+	item->valid = 1;
+	return count;
+}
+
+/*
+ * Platform device
+ */
+static struct platform_driver sncpf_driver = {
+	.driver = {
+		   .name = "sony-laptop",
+		   .owner = THIS_MODULE,
+		   }
+};
+static struct platform_device *sncpf_device;
+
+static int sony_snc_pf_add(void)
+{
+	acpi_handle handle;
+	struct sony_acpi_value *item;
+	int ret = 0;
+
+	ret = platform_driver_register(&sncpf_driver);
+	if (ret)
+		goto out;
+
+	sncpf_device = platform_device_alloc("sony-laptop", -1);
+	if (!sncpf_device) {
+		ret = -ENOMEM;
+		goto out_platform_registered;
+	}
+
+	ret = platform_device_add(sncpf_device);
+	if (ret)
+		goto out_platform_alloced;
+
+	for (item = sony_acpi_values; item->name; ++item) {
+
+		if (!debug && item->debug)
+			continue;
+
+		/* find the available acpiget as described in the DSDT */
+		for (; item->acpiget && *item->acpiget; ++item->acpiget) {
+			if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle,
+							 *item->acpiget,
+							 &handle))) {
+				if (debug)
+					printk(LOG_PFX "Found %s getter: %s\n",
+					       item->name, *item->acpiget);
+				item->devattr.attr.mode |= S_IRUGO;
+				break;
+			}
+		}
+
+		/* find the available acpiset as described in the DSDT */
+		for (; item->acpiset && *item->acpiset; ++item->acpiset) {
+			if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle,
+							 *item->acpiset,
+							 &handle))) {
+				if (debug)
+					printk(LOG_PFX "Found %s setter: %s\n",
+					       item->name, *item->acpiset);
+				item->devattr.attr.mode |= S_IWUSR;
+				break;
+			}
+		}
+
+		if (item->devattr.attr.mode != 0) {
+			ret =
+			    device_create_file(&sncpf_device->dev,
+					       &item->devattr);
+			if (ret)
+				goto out_sysfs;
+		}
+	}
+
+	return 0;
+
+      out_sysfs:
+	for (item = sony_acpi_values; item->name; ++item) {
+		device_remove_file(&sncpf_device->dev, &item->devattr);
+	}
+	platform_device_del(sncpf_device);
+      out_platform_alloced:
+	platform_device_put(sncpf_device);
+      out_platform_registered:
+	platform_driver_unregister(&sncpf_driver);
+      out:
+	return ret;
+}
+
+static void sony_snc_pf_remove(void)
+{
+	struct sony_acpi_value *item;
+
+	for (item = sony_acpi_values; item->name; ++item) {
+		device_remove_file(&sncpf_device->dev, &item->devattr);
+	}
+
+	platform_device_del(sncpf_device);
+	platform_device_put(sncpf_device);
+	platform_driver_unregister(&sncpf_driver);
+}
+
+/*
+ * Backlight device
+ */
+static int sony_backlight_update_status(struct backlight_device *bd)
+{
+	return acpi_callsetfunc(sony_acpi_handle, "SBRT",
+				bd->props.brightness + 1, NULL);
+}
+
+static int sony_backlight_get_brightness(struct backlight_device *bd)
+{
+	int value;
+
+	if (acpi_callgetfunc(sony_acpi_handle, "GBRT", &value))
+		return 0;
+	/* brightness levels are 1-based, while backlight ones are 0-based */
+	return value - 1;
+}
+
+static struct backlight_device *sony_backlight_device;
+static struct backlight_ops sony_backlight_ops = {
+	.update_status = sony_backlight_update_status,
+	.get_brightness = sony_backlight_get_brightness,
+};
+
+/*
+ * ACPI callbacks
+ */
+static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+	if (debug)
+		printk(LOG_PFX "sony_acpi_notify, event: %d\n", event);
+	acpi_bus_generate_event(sony_acpi_acpi_device, 1, event);
+}
+
+static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
+				      void *context, void **return_value)
+{
+	struct acpi_namespace_node *node;
+	union acpi_operand_object *operand;
+
+	node = (struct acpi_namespace_node *)handle;
+	operand = (union acpi_operand_object *)node->object;
+
+	printk(LOG_PFX "method: name: %4.4s, args %X\n", node->name.ascii,
+	       (u32) operand->method.param_count);
+
+	return AE_OK;
+}
+
+/*
+ * ACPI device
+ */
+static int sony_acpi_resume(struct acpi_device *device)
+{
+	struct sony_acpi_value *item;
+
+	for (item = sony_acpi_values; item->name; item++) {
+		int ret;
+
+		if (!item->valid)
+			continue;
+		ret = acpi_callsetfunc(sony_acpi_handle, *item->acpiset,
+				       item->value, NULL);
+		if (ret < 0) {
+			printk("%s: %d\n", __FUNCTION__, ret);
+			break;
+		}
+	}
+	return 0;
+}
+
+static int sony_acpi_add(struct acpi_device *device)
+{
+	acpi_status status;
+	int result;
+	acpi_handle handle;
+
+	sony_acpi_acpi_device = device;
+
+	sony_acpi_handle = device->handle;
+
+	if (debug) {
+		status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_acpi_handle,
+					     1, sony_walk_callback, NULL, NULL);
+		if (ACPI_FAILURE(status)) {
+			printk(LOG_PFX "unable to walk acpi resources\n");
+			result = -ENODEV;
+			goto outwalk;
+		}
+	}
+
+	status = acpi_install_notify_handler(sony_acpi_handle,
+					     ACPI_DEVICE_NOTIFY,
+					     sony_acpi_notify, NULL);
+	if (ACPI_FAILURE(status)) {
+		printk(LOG_PFX "unable to install notify handler\n");
+		result = -ENODEV;
+		goto outwalk;
+	}
+
+	if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle, "GBRT", &handle))) {
+		sony_backlight_device = backlight_device_register("sony", NULL,
+								  NULL,
+								  &sony_backlight_ops);
+
+		if (IS_ERR(sony_backlight_device)) {
+			printk(LOG_PFX "unable to register backlight device\n");
+			sony_backlight_device = NULL;
+		} else {
+			sony_backlight_device->props.brightness =
+			    sony_backlight_get_brightness
+			    (sony_backlight_device);
+			sony_backlight_device->props.max_brightness = 
+			    SONY_MAX_BRIGHTNESS - 1;
+		}
+
+	}
+
+	if (sony_snc_pf_add())
+		goto outbacklight;
+
+	printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully installed\n");
+
+	return 0;
+
+      outbacklight:
+	if (sony_backlight_device)
+		backlight_device_unregister(sony_backlight_device);
+
+	status = acpi_remove_notify_handler(sony_acpi_handle,
+					    ACPI_DEVICE_NOTIFY,
+					    sony_acpi_notify);
+	if (ACPI_FAILURE(status))
+		printk(LOG_PFX "unable to remove notify handler\n");
+      outwalk:
+	return result;
+}
+
+static int sony_acpi_remove(struct acpi_device *device, int type)
+{
+	acpi_status status;
+
+	if (sony_backlight_device)
+		backlight_device_unregister(sony_backlight_device);
+
+	sony_acpi_acpi_device = NULL;
+
+	status = acpi_remove_notify_handler(sony_acpi_handle,
+					    ACPI_DEVICE_NOTIFY,
+					    sony_acpi_notify);
+	if (ACPI_FAILURE(status))
+		printk(LOG_PFX "unable to remove notify handler\n");
+
+	sony_snc_pf_remove();
+
+	printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully removed\n");
+
+	return 0;
+}
+
+static struct acpi_driver sony_acpi_driver = {
+	.name = ACPI_SNC_DRIVER_NAME,
+	.class = ACPI_SNC_CLASS,
+	.ids = ACPI_SNC_HID,
+	.ops = {
+		.add = sony_acpi_add,
+		.remove = sony_acpi_remove,
+		.resume = sony_acpi_resume,
+		},
+};
+
+static int __init sony_acpi_init(void)
+{
+	return acpi_bus_register_driver(&sony_acpi_driver);
+}
+
+static void __exit sony_acpi_exit(void)
+{
+	acpi_bus_unregister_driver(&sony_acpi_driver);
+}
+
+module_init(sony_acpi_init);
+module_exit(sony_acpi_exit);
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index e21e490..bc60e2f 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -367,7 +367,7 @@
 	if (!fm->addr)
 		goto err_out_free;
 
-	rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm);
+	rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
 	if (rc)
 		goto err_out_unmap;
 
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 4224686..12af9c7 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -111,7 +111,7 @@
 
 config MMC_TIFM_SD
 	tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
-	depends on MMC && EXPERIMENTAL
+	depends on MMC && EXPERIMENTAL && PCI
 	select TIFM_CORE
 	help
 	  Say Y here if you want to be able to access MMC/SD cards with
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 2ce50f3..459f4b4fe 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -64,6 +64,7 @@
 #include <linux/err.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
+#include <linux/atmel_pdc.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/protocol.h>
@@ -75,7 +76,6 @@
 #include <asm/arch/cpu.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/at91_mci.h>
-#include <asm/arch/at91_pdc.h>
 
 #define DRIVER_NAME "at91_mci"
 
@@ -211,13 +211,13 @@
 
 		/* Check to see if this needs filling */
 		if (i == 0) {
-			if (at91_mci_read(host, AT91_PDC_RCR) != 0) {
+			if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
 				pr_debug("Transfer active in current\n");
 				continue;
 			}
 		}
 		else {
-			if (at91_mci_read(host, AT91_PDC_RNCR) != 0) {
+			if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
 				pr_debug("Transfer active in next\n");
 				continue;
 			}
@@ -234,12 +234,12 @@
 		pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
 
 		if (i == 0) {
-			at91_mci_write(host, AT91_PDC_RPR, sg->dma_address);
-			at91_mci_write(host, AT91_PDC_RCR, sg->length / 4);
+			at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
+			at91_mci_write(host, ATMEL_PDC_RCR, sg->length / 4);
 		}
 		else {
-			at91_mci_write(host, AT91_PDC_RNPR, sg->dma_address);
-			at91_mci_write(host, AT91_PDC_RNCR, sg->length / 4);
+			at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
+			at91_mci_write(host, ATMEL_PDC_RNCR, sg->length / 4);
 		}
 	}
 
@@ -303,7 +303,7 @@
 		at91mci_pre_dma_read(host);
 	else {
 		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
-		at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
 	}
 
 	pr_debug("post dma read done\n");
@@ -320,7 +320,7 @@
 	pr_debug("Handling the transmit\n");
 
 	/* Disable the transfer */
-	at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+	at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
 
 	/* Now wait for cmd ready */
 	at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
@@ -431,15 +431,15 @@
 		cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
 
 	if (!data) {
-		at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
-		at91_mci_write(host, AT91_PDC_RPR, 0);
-		at91_mci_write(host, AT91_PDC_RCR, 0);
-		at91_mci_write(host, AT91_PDC_RNPR, 0);
-		at91_mci_write(host, AT91_PDC_RNCR, 0);
-		at91_mci_write(host, AT91_PDC_TPR, 0);
-		at91_mci_write(host, AT91_PDC_TCR, 0);
-		at91_mci_write(host, AT91_PDC_TNPR, 0);
-		at91_mci_write(host, AT91_PDC_TNCR, 0);
+		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
+		at91_mci_write(host, ATMEL_PDC_RPR, 0);
+		at91_mci_write(host, ATMEL_PDC_RCR, 0);
+		at91_mci_write(host, ATMEL_PDC_RNPR, 0);
+		at91_mci_write(host, ATMEL_PDC_RNCR, 0);
+		at91_mci_write(host, ATMEL_PDC_TPR, 0);
+		at91_mci_write(host, ATMEL_PDC_TCR, 0);
+		at91_mci_write(host, ATMEL_PDC_TNPR, 0);
+		at91_mci_write(host, ATMEL_PDC_TNCR, 0);
 
 		at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
 		at91_mci_write(host, AT91_MCI_CMDR, cmdr);
@@ -452,7 +452,7 @@
 	/*
 	 * Disable the PDC controller
 	 */
-	at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+	at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
 
 	if (cmdr & AT91_MCI_TRCMD_START) {
 		data->bytes_xfered = 0;
@@ -481,8 +481,8 @@
 
 			pr_debug("Transmitting %d bytes\n", host->total_length);
 
-			at91_mci_write(host, AT91_PDC_TPR, host->physical_address);
-			at91_mci_write(host, AT91_PDC_TCR, host->total_length / 4);
+			at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
+			at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
 			ier = AT91_MCI_TXBUFE;
 		}
 	}
@@ -497,9 +497,9 @@
 
 	if (cmdr & AT91_MCI_TRCMD_START) {
 		if (cmdr & AT91_MCI_TRDIR)
-			at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTEN);
+			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
 		else
-			at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTEN);
+			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 	}
 	return ier;
 }
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 05ba8ac..86439a0 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/errno.h>
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 4bf1fea..7522f76 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -22,9 +22,6 @@
 #include "sdhci.h"
 
 #define DRIVER_NAME "sdhci"
-#define DRIVER_VERSION "0.12"
-
-#define BUGMAIL "<sdhci-devel@list.drzeus.cx>"
 
 #define DBG(f, x...) \
 	pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
@@ -154,8 +151,7 @@
 	/* hw clears the bit when it's done */
 	while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) {
 		if (timeout == 0) {
-			printk(KERN_ERR "%s: Reset 0x%x never completed. "
-				"Please report this to " BUGMAIL ".\n",
+			printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
 				mmc_hostname(host->mmc), (int)mask);
 			sdhci_dumpregs(host);
 			return;
@@ -474,12 +470,11 @@
 
 	if ((data->error == MMC_ERR_NONE) && blocks) {
 		printk(KERN_ERR "%s: Controller signalled completion even "
-			"though there were blocks left. Please report this "
-			"to " BUGMAIL ".\n", mmc_hostname(host->mmc));
+			"though there were blocks left.\n",
+			mmc_hostname(host->mmc));
 		data->error = MMC_ERR_FAILED;
 	} else if (host->size != 0) {
-		printk(KERN_ERR "%s: %d bytes were left untransferred. "
-			"Please report this to " BUGMAIL ".\n",
+		printk(KERN_ERR "%s: %d bytes were left untransferred.\n",
 			mmc_hostname(host->mmc), host->size);
 		data->error = MMC_ERR_FAILED;
 	}
@@ -526,8 +521,7 @@
 	while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
 		if (timeout == 0) {
 			printk(KERN_ERR "%s: Controller never released "
-				"inhibit bit(s). Please report this to "
-				BUGMAIL ".\n", mmc_hostname(host->mmc));
+				"inhibit bit(s).\n", mmc_hostname(host->mmc));
 			sdhci_dumpregs(host);
 			cmd->error = MMC_ERR_FAILED;
 			tasklet_schedule(&host->finish_tasklet);
@@ -548,8 +542,7 @@
 	sdhci_set_transfer_mode(host, cmd->data);
 
 	if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
-		printk(KERN_ERR "%s: Unsupported response type! "
-			"Please report this to " BUGMAIL ".\n",
+		printk(KERN_ERR "%s: Unsupported response type!\n",
 			mmc_hostname(host->mmc));
 		cmd->error = MMC_ERR_INVALID;
 		tasklet_schedule(&host->finish_tasklet);
@@ -647,9 +640,8 @@
 	while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL))
 		& SDHCI_CLOCK_INT_STABLE)) {
 		if (timeout == 0) {
-			printk(KERN_ERR "%s: Internal clock never stabilised. "
-				"Please report this to " BUGMAIL ".\n",
-				mmc_hostname(host->mmc));
+			printk(KERN_ERR "%s: Internal clock never "
+				"stabilised.\n", mmc_hostname(host->mmc));
 			sdhci_dumpregs(host);
 			return;
 		}
@@ -899,9 +891,8 @@
 	spin_lock_irqsave(&host->lock, flags);
 
 	if (host->mrq) {
-		printk(KERN_ERR "%s: Timeout waiting for hardware interrupt. "
-			"Please report this to " BUGMAIL ".\n",
-			mmc_hostname(host->mmc));
+		printk(KERN_ERR "%s: Timeout waiting for hardware "
+			"interrupt.\n", mmc_hostname(host->mmc));
 		sdhci_dumpregs(host);
 
 		if (host->data) {
@@ -935,8 +926,6 @@
 		printk(KERN_ERR "%s: Got command interrupt even though no "
 			"command operation was in progress.\n",
 			mmc_hostname(host->mmc));
-		printk(KERN_ERR "%s: Please report this to " BUGMAIL ".\n",
-			mmc_hostname(host->mmc));
 		sdhci_dumpregs(host);
 		return;
 	}
@@ -972,8 +961,6 @@
 		printk(KERN_ERR "%s: Got data interrupt even though no "
 			"data operation was in progress.\n",
 			mmc_hostname(host->mmc));
-		printk(KERN_ERR "%s: Please report this to " BUGMAIL ".\n",
-			mmc_hostname(host->mmc));
 		sdhci_dumpregs(host);
 
 		return;
@@ -1045,8 +1032,7 @@
 	intmask &= SDHCI_INT_BUS_POWER;
 
 	if (intmask) {
-		printk(KERN_ERR "%s: Unexpected interrupt 0x%08x. Please "
-			"report this to " BUGMAIL ".\n",
+		printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
 			mmc_hostname(host->mmc), intmask);
 		sdhci_dumpregs(host);
 
@@ -1528,8 +1514,7 @@
 static int __init sdhci_drv_init(void)
 {
 	printk(KERN_INFO DRIVER_NAME
-		": Secure Digital Host Controller Interface driver, "
-		DRIVER_VERSION "\n");
+		": Secure Digital Host Controller Interface driver\n");
 	printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
 
 	return pci_register_driver(&sdhci_driver);
@@ -1551,7 +1536,6 @@
 
 MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
 MODULE_DESCRIPTION("Secure Digital Host Controller Interface driver");
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 MODULE_PARM_DESC(debug_nodma, "Forcefully disable DMA transfers. (default 0)");
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c
index e65f8a0..0581d09 100644
--- a/drivers/mmc/tifm_sd.c
+++ b/drivers/mmc/tifm_sd.c
@@ -36,8 +36,8 @@
 #define TIFM_MMCSD_INAB       0x0080   /* abort / initialize command */
 #define TIFM_MMCSD_READ       0x8000
 
-#define TIFM_MMCSD_DATAMASK   0x001d   /* set bits: EOFB, BRS, CB, EOC */
-#define TIFM_MMCSD_ERRMASK    0x41e0   /* set bits: CERR, CCRC, CTO, DCRC, DTO */
+#define TIFM_MMCSD_DATAMASK   0x401d   /* set bits: CERR, EOFB, BRS, CB, EOC */
+#define TIFM_MMCSD_ERRMASK    0x01e0   /* set bits: CCRC, CTO, DCRC, DTO */
 #define TIFM_MMCSD_EOC        0x0001   /* end of command phase  */
 #define TIFM_MMCSD_CB         0x0004   /* card enter busy state */
 #define TIFM_MMCSD_BRS        0x0008   /* block received/sent   */
@@ -242,7 +242,7 @@
 	case IDLE:
 		return;
 	case CMD:
-		if (host_status & TIFM_MMCSD_EOC) {
+		if (host_status & (TIFM_MMCSD_EOC | TIFM_MMCSD_CERR)) {
 			tifm_sd_fetch_resp(cmd, sock);
 			if (cmd->data) {
 				host->state = BRS;
@@ -341,10 +341,7 @@
 			goto done;
 
 		if (host_status & TIFM_MMCSD_ERRMASK) {
-			if (host_status & TIFM_MMCSD_CERR)
-				error_code = MMC_ERR_FAILED;
-			else if (host_status
-				 & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO))
+			if (host_status & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO))
 				error_code = MMC_ERR_TIMEOUT;
 			else if (host_status
 				 & (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC))
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index a44d877..05ccfc4 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -42,7 +42,6 @@
 #include "wbsd.h"
 
 #define DRIVER_NAME "wbsd"
-#define DRIVER_VERSION "1.6"
 
 #define DBG(x...) \
 	pr_debug(DRIVER_NAME ": " x)
@@ -344,7 +343,6 @@
 			memcpy(sgbuf, dmabuf, size);
 		else
 			memcpy(sgbuf, dmabuf, sg[i].length);
-		kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
 		dmabuf += sg[i].length;
 
 		if (size < sg[i].length)
@@ -2101,8 +2099,7 @@
 	int result;
 
 	printk(KERN_INFO DRIVER_NAME
-		": Winbond W83L51xD SD/MMC card interface driver, "
-		DRIVER_VERSION "\n");
+		": Winbond W83L51xD SD/MMC card interface driver\n");
 	printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
 
 #ifdef CONFIG_PNP
@@ -2166,7 +2163,6 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
 MODULE_DESCRIPTION("Winbond W83L51xD SD/MMC card interface driver");
-MODULE_VERSION(DRIVER_VERSION);
 
 #ifdef CONFIG_PNP
 MODULE_PARM_DESC(nopnp, "Scan for device instead of relying on PNP. (default 0)");
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index f69184a..f334959 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -397,9 +397,23 @@
 	cfi_fixup(mtd, fixup_table);
 
 	for (i=0; i< cfi->numchips; i++) {
-		cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
-		cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
-		cfi->chips[i].erase_time = 1000<<cfi->cfiq->BlockEraseTimeoutTyp;
+		if (cfi->cfiq->WordWriteTimeoutTyp)
+			cfi->chips[i].word_write_time =
+				1<<cfi->cfiq->WordWriteTimeoutTyp;
+		else
+			cfi->chips[i].word_write_time = 50000;
+
+		if (cfi->cfiq->BufWriteTimeoutTyp)
+			cfi->chips[i].buffer_write_time =
+				1<<cfi->cfiq->BufWriteTimeoutTyp;
+		/* No default; if it isn't specified, we won't use it */
+
+		if (cfi->cfiq->BlockEraseTimeoutTyp)
+			cfi->chips[i].erase_time =
+				1000<<cfi->cfiq->BlockEraseTimeoutTyp;
+		else
+			cfi->chips[i].erase_time = 2000000;
+
 		cfi->chips[i].ref_point_counter = 0;
 		init_waitqueue_head(&(cfi->chips[i].wq));
 	}
@@ -546,13 +560,11 @@
 			struct cfi_intelext_programming_regioninfo *prinfo;
 			prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];
 			mtd->writesize = cfi->interleave << prinfo->ProgRegShift;
-			MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid;
-			MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid;
 			mtd->flags &= ~MTD_BIT_WRITEABLE;
 			printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",
 			       map->name, mtd->writesize,
-			       MTD_PROGREGION_CTRLMODE_VALID(mtd),
-			       MTD_PROGREGION_CTRLMODE_INVALID(mtd));
+			       cfi->interleave * prinfo->ControlValid,
+			       cfi->interleave * prinfo->ControlInvalid);
 		}
 
 		/*
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index d56849f..69d49e0 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -662,7 +662,7 @@
  * a small buffer for this.
  * XXX: If the buffer size is not a multiple of 2, this will break
  */
-#define ECCBUF_SIZE (mtd->eccsize)
+#define ECCBUF_SIZE (mtd->writesize)
 #define ECCBUF_DIV(x) ((x) & ~(ECCBUF_SIZE - 1))
 #define ECCBUF_MOD(x) ((x) &  (ECCBUF_SIZE - 1))
 static int
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index d8e7a02..2e51496 100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 6d917a4..f9f2ce7 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -278,7 +278,8 @@
 	kfree(dev->mtd.name);
 
 	if (dev->blkdev) {
-		invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping);
+		invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
+					0, -1);
 		close_bdev_excl(dev->blkdev);
 	}
 
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index 603a795..8a0c4de 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -569,7 +569,6 @@
 
 	mtd->type = MTD_NANDFLASH;
 	mtd->flags = MTD_CAP_NANDFLASH;
-	mtd->ecctype = MTD_ECC_RS_DiskOnChip;
 	mtd->size = 0;
 	mtd->erasesize = 0;
 	mtd->writesize = 512;
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index 0e2a932..6f368ae 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -16,7 +16,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
@@ -349,7 +348,6 @@
 
 	mtd->type = MTD_NANDFLASH;
 	mtd->flags = MTD_CAP_NANDFLASH;
-	mtd->ecctype = MTD_ECC_RS_DiskOnChip;
 	mtd->size = 0;
 
 	/* FIXME: erase size is not always 8KiB */
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 92dbb47..88ba82d 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -20,7 +20,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
@@ -473,7 +472,6 @@
 
 	mtd->type = MTD_NANDFLASH;
 	mtd->flags = MTD_CAP_NANDFLASH;
-	mtd->ecctype = MTD_ECC_RS_DiskOnChip;
 	mtd->size = 0;
 
 	mtd->erasesize = 0;
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c
index cd3db72..52b5d63 100644
--- a/drivers/mtd/devices/docecc.c
+++ b/drivers/mtd/devices/docecc.c
@@ -32,7 +32,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/types.h>
 
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index 354e165..a4873ab 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -86,7 +86,6 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index 5f49248..d293add 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -35,7 +35,6 @@
 #include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index 24235d4..c815d0f 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -61,7 +61,6 @@
 /*#define PSYCHO_DEBUG */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
index 8f6006f..acf3ba2 100644
--- a/drivers/mtd/inftlmount.c
+++ b/drivers/mtd/inftlmount.c
@@ -34,7 +34,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nftl.h>
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index f457315..bbf0553 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -204,7 +204,7 @@
 
 config MTD_CK804XROM
 	tristate "BIOS flash chip on Nvidia CK804"
-	depends on X86 && MTD_JEDECPROBE
+	depends on X86 && MTD_JEDECPROBE && PCI
 	help
 	  Support for treating the BIOS flash chip on nvidia motherboards
 	  as an MTD device - with this you can reprogram your BIOS.
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index 78b6711..728aed6 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -205,8 +205,8 @@
 			(((unsigned long)(window->virt)) + offset);
 		map->map.size = 0xffffffffUL - map_top + 1UL;
 		/* Set the name of the map to the address I am trying */
-		sprintf(map->map_name, "%s @%08lx",
-			MOD_NAME, map->map.phys);
+		sprintf(map->map_name, "%s @%08Lx",
+			MOD_NAME, (unsigned long long)map->map.phys);
 
 		/* There is no generic VPP support */
 		for(map->map.bankwidth = 32; map->map.bankwidth;
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 238d42e..3d4a4d8 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -207,8 +207,8 @@
 			(((unsigned long)(window->virt)) + offset);
 		map->map.size = 0xffffffffUL - map_top + 1UL;
 		/* Set the name of the map to the address I am trying */
-		sprintf(map->map_name, "%s @%08lx",
-			MOD_NAME, map->map.phys);
+		sprintf(map->map_name, "%s @%08Lx",
+			MOD_NAME, (unsigned long long)map->map.phys);
 
 		/* There is no generic VPP support */
 		for(map->map.bankwidth = 32; map->map.bankwidth;
@@ -327,7 +327,7 @@
 	pdev = NULL;
 
 	for(id = ck804xrom_pci_tbl; id->vendor; id++) {
-		pdev = pci_find_device(id->vendor, id->device, NULL);
+		pdev = pci_get_device(id->vendor, id->device, NULL);
 		if (pdev)
 			break;
 	}
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
index a9d808a..0bc013f 100644
--- a/drivers/mtd/maps/esb2rom.c
+++ b/drivers/mtd/maps/esb2rom.c
@@ -289,8 +289,8 @@
 			(((unsigned long)(window->virt)) + offset);
 		map->map.size = 0xffffffffUL - map_top + 1UL;
 		/* Set the name of the map to the address I am trying */
-		sprintf(map->map_name, "%s @%08lx",
-			MOD_NAME, map->map.phys);
+		sprintf(map->map_name, "%s @%08Lx",
+			MOD_NAME, (unsigned long long)map->map.phys);
 
 		/* Firmware hubs only use vpp when being programmed
 		 * in a factory setting.  So in-place programming
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
index 2bb3e636..2c884c4 100644
--- a/drivers/mtd/maps/ichxrom.c
+++ b/drivers/mtd/maps/ichxrom.c
@@ -227,8 +227,8 @@
 			(((unsigned long)(window->virt)) + offset);
 		map->map.size = 0xffffffffUL - map_top + 1UL;
 		/* Set the name of the map to the address I am trying */
-		sprintf(map->map_name, "%s @%08lx",
-			MOD_NAME, map->map.phys);
+		sprintf(map->map_name, "%s @%08Lx",
+			MOD_NAME, (unsigned long long)map->map.phys);
 
 		/* Firmware hubs only use vpp when being programmed
 		 * in a factory setting.  So in-place programming
diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c
index ed21547..95dcab2 100644
--- a/drivers/mtd/maps/netsc520.c
+++ b/drivers/mtd/maps/netsc520.c
@@ -94,7 +94,9 @@
 
 static int __init init_netsc520(void)
 {
-	printk(KERN_NOTICE "NetSc520 flash device: 0x%lx at 0x%lx\n", netsc520_map.size, netsc520_map.phys);
+	printk(KERN_NOTICE "NetSc520 flash device: 0x%Lx at 0x%Lx\n",
+			(unsigned long long)netsc520_map.size,
+			(unsigned long long)netsc520_map.phys);
 	netsc520_map.virt = ioremap_nocache(netsc520_map.phys, netsc520_map.size);
 
 	if (!netsc520_map.virt) {
diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c
index 9b50cfc..4045e37 100644
--- a/drivers/mtd/maps/sc520cdp.c
+++ b/drivers/mtd/maps/sc520cdp.c
@@ -237,8 +237,9 @@
 #endif
 
 	for (i = 0; i < NUM_FLASH_BANKS; i++) {
-		printk(KERN_NOTICE "SC520 CDP flash device: 0x%lx at 0x%lx\n",
-		       sc520cdp_map[i].size, sc520cdp_map[i].phys);
+		printk(KERN_NOTICE "SC520 CDP flash device: 0x%Lx at 0x%Lx\n",
+			(unsigned long long)sc520cdp_map[i].size,
+			(unsigned long long)sc520cdp_map[i].phys);
 
 		sc520cdp_map[i].virt = ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size);
 
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 3013d08..1592eac 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -419,8 +419,9 @@
 		info.erasesize	= mtd->erasesize;
 		info.writesize	= mtd->writesize;
 		info.oobsize	= mtd->oobsize;
-		info.ecctype	= mtd->ecctype;
-		info.eccsize	= mtd->eccsize;
+		/* The below fields are obsolete */
+		info.ecctype	= -1;
+		info.eccsize	= 0;
 		if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
 			return -EFAULT;
 		break;
@@ -759,7 +760,7 @@
 	return ret;
 } /* memory_ioctl */
 
-static struct file_operations mtd_fops = {
+static const struct file_operations mtd_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= mtd_lseek,
 	.read		= mtd_read,
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 0690268..880580c 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -727,8 +727,6 @@
 	concat->mtd.erasesize = subdev[0]->erasesize;
 	concat->mtd.writesize = subdev[0]->writesize;
 	concat->mtd.oobsize = subdev[0]->oobsize;
-	concat->mtd.ecctype = subdev[0]->ecctype;
-	concat->mtd.eccsize = subdev[0]->eccsize;
 	if (subdev[0]->writev)
 		concat->mtd.writev = concat_writev;
 	if (subdev[0]->read_oob)
@@ -774,8 +772,6 @@
 		if (concat->mtd.writesize   !=  subdev[i]->writesize ||
 		    concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
 		    concat->mtd.oobsize    !=  subdev[i]->oobsize ||
-		    concat->mtd.ecctype    !=  subdev[i]->ecctype ||
-		    concat->mtd.eccsize    !=  subdev[i]->eccsize ||
 		    !concat->mtd.read_oob  != !subdev[i]->read_oob ||
 		    !concat->mtd.write_oob != !subdev[i]->write_oob) {
 			kfree(concat);
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 7070110..c153b64 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -8,7 +8,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index bafd2fb..633def3 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -338,8 +338,6 @@
 		slave->mtd.size = parts[i].size;
 		slave->mtd.writesize = master->writesize;
 		slave->mtd.oobsize = master->oobsize;
-		slave->mtd.ecctype = master->ecctype;
-		slave->mtd.eccsize = master->eccsize;
 		slave->mtd.subpage_sft = master->subpage_sft;
 
 		slave->mtd.name = parts[i].name;
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 358f55a..2d12dcd 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -126,10 +126,6 @@
 	  incorrect ECC generation, and if using these, the default of
 	  software ECC is preferable.
 
-	  If you lay down a device with the hardware ECC, then you will
-	  currently not be able to switch to software, as there is no
-	  implementation for ECC method used by the S3C2410
-
 config MTD_NAND_NDFC
 	tristate "NDFC NanD Flash Controller"
 	depends on MTD_NAND && 44x
@@ -221,9 +217,17 @@
 	tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
 	depends on MTD_NAND && ARCH_PXA
 
+config MTD_NAND_BASLER_EXCITE
+	tristate  "Support for NAND Flash on Basler eXcite"
+	depends on MTD_NAND && BASLER_EXCITE
+	help
+          This enables the driver for the NAND flash device found on the
+          Basler eXcite Smart Camera. If built as a module, the driver
+          will be named "excite_nandflash.ko".
+
 config MTD_NAND_CAFE
        tristate "NAND support for OLPC CAFÉ chip"
-       depends on PCI
+       depends on MTD_NAND && PCI
        help
 	 Use NAND flash attached to the CAFÉ chip designed for the $100
 	 laptop.
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index f7a53f0..80f1dfc 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -24,6 +24,7 @@
 obj-$(CONFIG_MTD_NAND_CS553X)		+= cs553x_nand.o
 obj-$(CONFIG_MTD_NAND_NDFC)		+= ndfc.o
 obj-$(CONFIG_MTD_NAND_AT91)		+= at91_nand.o
+obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)	+= excite_nandflash.o
 
 nand-objs := nand_base.o nand_bbt.o
 cafe_nand-objs := cafe.o cafe_ecc.o
diff --git a/drivers/mtd/nand/cafe.c b/drivers/mtd/nand/cafe.c
index 65f9bd3..fd6bb3e 100644
--- a/drivers/mtd/nand/cafe.c
+++ b/drivers/mtd/nand/cafe.c
@@ -78,8 +78,9 @@
 static int checkecc = 1;
 module_param(checkecc, int, 0644);
 
-static int slowtiming = 0;
-module_param(slowtiming, int, 0644);
+static int numtimings;
+static int timing[3];
+module_param_array(timing, int, &numtimings, 0644);
 
 /* Hrm. Why isn't this already conditional on something in the struct device? */
 #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0)
@@ -264,10 +265,10 @@
 	ndelay(100);
 
 	if (1) {
-		int c = 500000;
+		int c;
 		uint32_t irqs;
 
-		while (c--) {
+		for (c = 500000; c != 0; c--) {
 			irqs = cafe_readl(cafe, NAND_IRQ);
 			if (irqs & doneint)
 				break;
@@ -529,6 +530,7 @@
 {
 	struct mtd_info *mtd;
 	struct cafe_priv *cafe;
+	uint32_t timing1, timing2, timing3;
 	uint32_t ctrl;
 	int err = 0;
 
@@ -580,30 +582,45 @@
 		cafe->nand.block_bad = cafe_nand_block_bad;
 	}
 
+	if (numtimings && numtimings != 3) {
+		dev_warn(&cafe->pdev->dev, "%d timing register values ignored; precisely three are required\n", numtimings);
+	}
+
+	if (numtimings == 3) {
+		timing1 = timing[0];
+		timing2 = timing[1];
+		timing3 = timing[2];
+		cafe_dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n",
+			     timing1, timing2, timing3);
+	} else {
+		timing1 = cafe_readl(cafe, NAND_TIMING1);
+		timing2 = cafe_readl(cafe, NAND_TIMING2);
+		timing3 = cafe_readl(cafe, NAND_TIMING3);
+
+		if (timing1 | timing2 | timing3) {
+			cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n", timing1, timing2, timing3);
+		} else {
+			dev_warn(&cafe->pdev->dev, "Timing registers unset; using most conservative defaults\n");
+			timing1 = timing2 = timing3 = 0xffffffff;
+		}
+	}
+
 	/* Start off by resetting the NAND controller completely */
 	cafe_writel(cafe, 1, NAND_RESET);
 	cafe_writel(cafe, 0, NAND_RESET);
 
-	cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
+	cafe_writel(cafe, timing1, NAND_TIMING1);
+	cafe_writel(cafe, timing2, NAND_TIMING2);
+	cafe_writel(cafe, timing3, NAND_TIMING3);
 
-	/* Timings from Marvell's test code (not verified or calculated by us) */
-	if (!slowtiming) {
-		cafe_writel(cafe, 0x01010a0a, NAND_TIMING1);
-		cafe_writel(cafe, 0x24121212, NAND_TIMING2);
-		cafe_writel(cafe, 0x11000000, NAND_TIMING3);
-	} else {
-		cafe_writel(cafe, 0xffffffff, NAND_TIMING1);
-		cafe_writel(cafe, 0xffffffff, NAND_TIMING2);
-		cafe_writel(cafe, 0xffffffff, NAND_TIMING3);
-	}
 	cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
-	err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd);
+	err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED,
+			  "CAFE NAND", mtd);
 	if (err) {
 		dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
-
 		goto out_free_dma;
 	}
-#if 1
+
 	/* Disable master reset, enable NAND clock */
 	ctrl = cafe_readl(cafe, GLOBAL_CTRL);
 	ctrl &= 0xffffeff0;
@@ -630,32 +647,8 @@
 	cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
 	cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
 		cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK));
-#endif
-#if 1
-	mtd->writesize=2048;
-	mtd->oobsize = 0x40;
-	memset(cafe->dmabuf, 0x5a, 2112);
-	cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1);
-	cafe->nand.read_byte(mtd);
-	cafe->nand.read_byte(mtd);
-	cafe->nand.read_byte(mtd);
-	cafe->nand.read_byte(mtd);
-	cafe->nand.read_byte(mtd);
-#endif
-#if 0
-	cafe->nand.cmdfunc(mtd, NAND_CMD_READ0, 0, 0);
-	//	nand_wait_ready(mtd);
-	cafe->nand.read_byte(mtd);
-	cafe->nand.read_byte(mtd);
-	cafe->nand.read_byte(mtd);
-	cafe->nand.read_byte(mtd);
-#endif
-#if 0
-	writel(0x84600070, cafe->mmio);
-	udelay(10);
-	cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", cafe_readl(cafe, NAND_NONMEM));
-#endif
-	/* Scan to find existance of the device */
+
+	/* Scan to find existence of the device */
 	if (nand_scan_ident(mtd, 1)) {
 		err = -ENXIO;
 		goto out_irq;
@@ -759,13 +752,4 @@
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
-MODULE_DESCRIPTION("NAND flash driver for OLPC CAFE chip");
-
-/* Correct ECC for 2048 bytes of 0xff:
-   41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */
-
-/* dwmw2's B-test board, in case of completely screwing it:
-Bad eraseblock 2394 at 0x12b40000
-Bad eraseblock 2627 at 0x14860000
-Bad eraseblock 3349 at 0x1a2a0000
-*/
+MODULE_DESCRIPTION("NAND flash driver for OLPC CAFÉ chip");
diff --git a/drivers/mtd/nand/cafe_ecc.c b/drivers/mtd/nand/cafe_ecc.c
index 1b9fa05..ea5c849 100644
--- a/drivers/mtd/nand/cafe_ecc.c
+++ b/drivers/mtd/nand/cafe_ecc.c
@@ -1045,7 +1045,7 @@
 
 static unsigned short err_pos(unsigned short din)
 {
-	BUG_ON(din > 4096);
+	BUG_ON(din >= ARRAY_SIZE(err_pos_lut));
 	return err_pos_lut[din];
 }
 static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
diff --git a/drivers/mtd/nand/excite_nandflash.c b/drivers/mtd/nand/excite_nandflash.c
new file mode 100644
index 0000000..7e9afc4
--- /dev/null
+++ b/drivers/mtd/nand/excite_nandflash.c
@@ -0,0 +1,248 @@
+/*
+*  Copyright (C) 2005 - 2007 by Basler Vision Technologies AG
+*  Author: Thomas Koeller <thomas.koeller.qbaslerweb.com>
+*  Original code by Thies Moeller <thies.moeller@baslerweb.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/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/io.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite_nandflash.h>
+
+#define EXCITE_NANDFLASH_VERSION "0.1"
+
+/* I/O register offsets */
+#define EXCITE_NANDFLASH_DATA_BYTE   0x00
+#define EXCITE_NANDFLASH_STATUS_BYTE 0x0c
+#define EXCITE_NANDFLASH_ADDR_BYTE   0x10
+#define EXCITE_NANDFLASH_CMD_BYTE    0x14
+
+/* prefix for debug output */
+static const char module_id[] = "excite_nandflash";
+
+/*
+ * partition definition
+ */
+static const struct mtd_partition partition_info[] = {
+	{
+		.name = "eXcite RootFS",
+		.offset = 0,
+		.size = MTDPART_SIZ_FULL
+	}
+};
+
+static inline const struct resource *
+excite_nand_get_resource(struct platform_device *d, unsigned long flags,
+			 const char *basename)
+{
+	char buf[80];
+
+	if (snprintf(buf, sizeof buf, "%s_%u", basename, d->id) >= sizeof buf)
+		return NULL;
+	return platform_get_resource_byname(d, flags, buf);
+}
+
+static inline void __iomem *
+excite_nand_map_regs(struct platform_device *d, const char *basename)
+{
+	void *result = NULL;
+	const struct resource *const r =
+	    excite_nand_get_resource(d, IORESOURCE_MEM, basename);
+
+	if (r)
+		result = ioremap_nocache(r->start, r->end + 1 - r->start);
+	return result;
+}
+
+/* controller and mtd information */
+struct excite_nand_drvdata {
+	struct mtd_info board_mtd;
+	struct nand_chip board_chip;
+	void __iomem *regs;
+	void __iomem *tgt;
+};
+
+/* Control function */
+static void excite_nand_control(struct mtd_info *mtd, int cmd,
+				       unsigned int ctrl)
+{
+	struct excite_nand_drvdata * const d =
+	    container_of(mtd, struct excite_nand_drvdata, board_mtd);
+
+	switch (ctrl) {
+	case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
+		d->tgt = d->regs + EXCITE_NANDFLASH_CMD_BYTE;
+		break;
+	case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
+		d->tgt = d->regs + EXCITE_NANDFLASH_ADDR_BYTE;
+		break;
+	case NAND_CTRL_CHANGE | NAND_NCE:
+		d->tgt = d->regs + EXCITE_NANDFLASH_DATA_BYTE;
+		break;
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		__raw_writeb(cmd, d->tgt);
+}
+
+/* Return 0 if flash is busy, 1 if ready */
+static int excite_nand_devready(struct mtd_info *mtd)
+{
+	struct excite_nand_drvdata * const drvdata =
+	    container_of(mtd, struct excite_nand_drvdata, board_mtd);
+
+	return __raw_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS_BYTE);
+}
+
+/*
+ * Called by device layer to remove the driver.
+ * The binding to the mtd and all allocated
+ * resources are released.
+ */
+static int __exit excite_nand_remove(struct device *dev)
+{
+	struct excite_nand_drvdata * const this = dev_get_drvdata(dev);
+
+	dev_set_drvdata(dev, NULL);
+
+	if (unlikely(!this)) {
+		printk(KERN_ERR "%s: called %s without private data!!",
+		       module_id, __func__);
+		return -EINVAL;
+	}
+
+	/* first thing we need to do is release our mtd
+	 * then go through freeing the resource used
+	 */
+	nand_release(&this->board_mtd);
+
+	/* free the common resources */
+	iounmap(this->regs);
+	kfree(this);
+
+	DEBUG(MTD_DEBUG_LEVEL1, "%s: removed\n", module_id);
+	return 0;
+}
+
+/*
+ * Called by device layer when it finds a device matching
+ * one our driver can handle. This code checks to see if
+ * it can allocate all necessary resources then calls the
+ * nand layer to look for devices.
+*/
+static int __init excite_nand_probe(struct device *dev)
+{
+	struct platform_device * const pdev = to_platform_device(dev);
+	struct excite_nand_drvdata *drvdata;	/* private driver data */
+	struct nand_chip *board_chip;	/* private flash chip data */
+	struct mtd_info *board_mtd;	/* mtd info for this board */
+	int scan_res;
+
+	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+	if (unlikely(!drvdata)) {
+		printk(KERN_ERR "%s: no memory for drvdata\n",
+		       module_id);
+		return -ENOMEM;
+	}
+
+	/* bind private data into driver */
+	dev_set_drvdata(dev, drvdata);
+
+	/* allocate and map the resource */
+	drvdata->regs =
+		excite_nand_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS);
+
+	if (unlikely(!drvdata->regs)) {
+		printk(KERN_ERR "%s: cannot reserve register region\n",
+		       module_id);
+		kfree(drvdata);
+		return -ENXIO;
+	}
+	
+	drvdata->tgt = drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE;
+
+	/* initialise our chip */
+	board_chip = &drvdata->board_chip;
+	board_chip->IO_ADDR_R = board_chip->IO_ADDR_W =
+		drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE;
+	board_chip->cmd_ctrl = excite_nand_control;
+	board_chip->dev_ready = excite_nand_devready;
+	board_chip->chip_delay = 25;
+	board_chip->ecc.mode = NAND_ECC_SOFT;
+
+	/* link chip to mtd */
+	board_mtd = &drvdata->board_mtd;
+	board_mtd->priv = board_chip;
+
+	DEBUG(MTD_DEBUG_LEVEL2, "%s: device scan\n", module_id);
+	scan_res = nand_scan(&drvdata->board_mtd, 1);
+
+	if (likely(!scan_res)) {
+		DEBUG(MTD_DEBUG_LEVEL2, "%s: register partitions\n", module_id);
+		add_mtd_partitions(&drvdata->board_mtd, partition_info,
+				   sizeof partition_info / sizeof partition_info[0]);
+	} else {
+		iounmap(drvdata->regs);
+		kfree(drvdata);
+		printk(KERN_ERR "%s: device scan failed\n", module_id);
+		return -EIO;
+	}
+	return 0;
+}
+
+static struct device_driver excite_nand_driver = {
+	.name = "excite_nand",
+	.bus = &platform_bus_type,
+	.probe = excite_nand_probe,
+	.remove = __exit_p(excite_nand_remove)
+};
+
+static int __init excite_nand_init(void)
+{
+	pr_info("Basler eXcite nand flash driver Version "
+		EXCITE_NANDFLASH_VERSION "\n");
+	return driver_register(&excite_nand_driver);
+}
+
+static void __exit excite_nand_exit(void)
+{
+	driver_unregister(&excite_nand_driver);
+}
+
+module_init(excite_nand_init);
+module_exit(excite_nand_exit);
+
+MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
+MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(EXCITE_NANDFLASH_VERSION)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index dfe56e0..acaf97b 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1272,10 +1272,25 @@
 	DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n",
 	      (unsigned long long)from, readlen);
 
-	if (ops->mode == MTD_OOB_RAW)
-		len = mtd->oobsize;
-	else
+	if (ops->mode == MTD_OOB_AUTO)
 		len = chip->ecc.layout->oobavail;
+	else
+		len = mtd->oobsize;
+
+	if (unlikely(ops->ooboffs >= len)) {
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+			"Attempt to start read outside oob\n");
+		return -EINVAL;
+	}
+
+	/* Do not allow reads past end of device */
+	if (unlikely(from >= mtd->size ||
+		     ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) -
+					(from >> chip->page_shift)) * len)) {
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+			"Attempt read beyond end of device\n");
+		return -EINVAL;
+	}
 
 	chipnr = (int)(from >> chip->chip_shift);
 	chip->select_chip(mtd, chipnr);
@@ -1742,19 +1757,40 @@
 static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 			     struct mtd_oob_ops *ops)
 {
-	int chipnr, page, status;
+	int chipnr, page, status, len;
 	struct nand_chip *chip = mtd->priv;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
 	      (unsigned int)to, (int)ops->ooblen);
 
+	if (ops->mode == MTD_OOB_AUTO)
+		len = chip->ecc.layout->oobavail;
+	else
+		len = mtd->oobsize;
+
 	/* Do not allow write past end of page */
-	if ((ops->ooboffs + ops->ooblen) > mtd->oobsize) {
+	if ((ops->ooboffs + ops->ooblen) > len) {
 		DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
 		      "Attempt to write past end of page\n");
 		return -EINVAL;
 	}
 
+	if (unlikely(ops->ooboffs >= len)) {
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+			"Attempt to start write outside oob\n");
+		return -EINVAL;
+	}
+
+	/* Do not allow reads past end of device */
+	if (unlikely(to >= mtd->size ||
+		     ops->ooboffs + ops->ooblen >
+			((mtd->size >> chip->page_shift) -
+			 (to >> chip->page_shift)) * len)) {
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+			"Attempt write beyond end of device\n");
+		return -EINVAL;
+	}
+
 	chipnr = (int)(to >> chip->chip_shift);
 	chip->select_chip(mtd, chipnr);
 
@@ -2530,7 +2566,6 @@
 	/* Fill in remaining MTD driver data */
 	mtd->type = MTD_NANDFLASH;
 	mtd->flags = MTD_CAP_NANDFLASH;
-	mtd->ecctype = MTD_ECC_SW;
 	mtd->erase = nand_erase;
 	mtd->point = NULL;
 	mtd->unpoint = NULL;
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 8b32035..0ddfd6d 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -337,17 +337,69 @@
 static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 				     u_char *read_ecc, u_char *calc_ecc)
 {
-	pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc);
+	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+	unsigned int diff0, diff1, diff2;
+	unsigned int bit, byte;
 
-	pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n",
-		 read_ecc[0], read_ecc[1], read_ecc[2], calc_ecc[0], calc_ecc[1], calc_ecc[2]);
+	pr_debug("%s(%p,%p,%p,%p)\n", __func__, mtd, dat, read_ecc, calc_ecc);
 
-	if (read_ecc[0] == calc_ecc[0] && read_ecc[1] == calc_ecc[1] && read_ecc[2] == calc_ecc[2])
-		return 0;
+	diff0 = read_ecc[0] ^ calc_ecc[0];
+	diff1 = read_ecc[1] ^ calc_ecc[1];
+	diff2 = read_ecc[2] ^ calc_ecc[2];
 
-	/* we curently have no method for correcting the error */
+	pr_debug("%s: rd %02x%02x%02x calc %02x%02x%02x diff %02x%02x%02x\n",
+		 __func__,
+		 read_ecc[0], read_ecc[1], read_ecc[2],
+		 calc_ecc[0], calc_ecc[1], calc_ecc[2],
+		 diff0, diff1, diff2);
 
-	return -1;
+	if (diff0 == 0 && diff1 == 0 && diff2 == 0)
+		return 0;		/* ECC is ok */
+
+	/* Can we correct this ECC (ie, one row and column change).
+	 * Note, this is similar to the 256 error code on smartmedia */
+
+	if (((diff0 ^ (diff0 >> 1)) & 0x55) == 0x55 &&
+	    ((diff1 ^ (diff1 >> 1)) & 0x55) == 0x55 &&
+	    ((diff2 ^ (diff2 >> 1)) & 0x55) == 0x55) {
+		/* calculate the bit position of the error */
+
+		bit  = (diff2 >> 2) & 1;
+		bit |= (diff2 >> 3) & 2;
+		bit |= (diff2 >> 4) & 4;
+
+		/* calculate the byte position of the error */
+
+		byte  = (diff1 << 1) & 0x80;
+		byte |= (diff1 << 2) & 0x40;
+		byte |= (diff1 << 3) & 0x20;
+		byte |= (diff1 << 4) & 0x10;
+
+		byte |= (diff0 >> 3) & 0x08;
+		byte |= (diff0 >> 2) & 0x04;
+		byte |= (diff0 >> 1) & 0x02;
+		byte |= (diff0 >> 0) & 0x01;
+
+		byte |= (diff2 << 8) & 0x100;
+
+		dev_dbg(info->device, "correcting error bit %d, byte %d\n",
+			bit, byte);
+
+		dat[byte] ^= (1 << bit);
+		return 1;
+	}
+
+	/* if there is only one bit difference in the ECC, then
+	 * one of only a row or column parity has changed, which
+	 * means the error is most probably in the ECC itself */
+
+	diff0 |= (diff1 << 8);
+	diff0 |= (diff2 << 16);
+
+	if ((diff0 & ~(1<<fls(diff0))) == 0)
+		return 1;
+
+	return 0;
 }
 
 /* ECC functions
@@ -366,6 +418,15 @@
 	writel(ctrl, info->regs + S3C2410_NFCONF);
 }
 
+static void s3c2412_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+	unsigned long ctrl;
+
+	ctrl = readl(info->regs + S3C2440_NFCONT);
+	writel(ctrl | S3C2412_NFCONT_INIT_MAIN_ECC, info->regs + S3C2440_NFCONT);
+}
+
 static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 {
 	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
@@ -383,6 +444,21 @@
 	ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
 	ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
 
+	pr_debug("%s: returning ecc %02x%02x%02x\n", __func__,
+		 ecc_code[0], ecc_code[1], ecc_code[2]);
+
+	return 0;
+}
+
+static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+{
+	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+	unsigned long ecc = readl(info->regs + S3C2412_NFMECC0);
+
+	ecc_code[0] = ecc;
+	ecc_code[1] = ecc >> 8;
+	ecc_code[2] = ecc >> 16;
+
 	pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
 
 	return 0;
@@ -397,7 +473,7 @@
 	ecc_code[1] = ecc >> 8;
 	ecc_code[2] = ecc >> 16;
 
-	pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
+	pr_debug("%s: returning ecc %06x\n", __func__, ecc);
 
 	return 0;
 }
@@ -565,6 +641,10 @@
 			break;
 
 		case TYPE_S3C2412:
+  			chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
+  			chip->ecc.calculate = s3c2412_nand_calculate_ecc;
+			break;
+
 		case TYPE_S3C2440:
   			chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
   			chip->ecc.calculate = s3c2440_nand_calculate_ecc;
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index 4b1ba4f..e6ef7d7 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -20,7 +20,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/hdreg.h>
 
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 2da6bb2..7f1cb6e 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mtd/onenand/onenand_base.c
  *
- *  Copyright (C) 2005-2006 Samsung Electronics
+ *  Copyright (C) 2005-2007 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -94,16 +94,9 @@
  */
 static int onenand_block_address(struct onenand_chip *this, int block)
 {
-	if (this->device_id & ONENAND_DEVICE_IS_DDP) {
-		/* Device Flash Core select, NAND Flash Block Address */
-		int dfs = 0;
-
-		if (block & this->density_mask)
-			dfs = 1;
-
-		return (dfs << ONENAND_DDP_SHIFT) |
-			(block & (this->density_mask - 1));
-	}
+	/* Device Flash Core select, NAND Flash Block Address */
+	if (block & this->density_mask)
+		return ONENAND_DDP_CHIP1 | (block ^ this->density_mask);
 
 	return block;
 }
@@ -118,17 +111,11 @@
  */
 static int onenand_bufferram_address(struct onenand_chip *this, int block)
 {
-	if (this->device_id & ONENAND_DEVICE_IS_DDP) {
-		/* Device BufferRAM Select */
-		int dbs = 0;
+	/* Device BufferRAM Select */
+	if (block & this->density_mask)
+		return ONENAND_DDP_CHIP1;
 
-		if (block & this->density_mask)
-			dbs = 1;
-
-		return (dbs << ONENAND_DDP_SHIFT);
-	}
-
-	return 0;
+	return ONENAND_DDP_CHIP0;
 }
 
 /**
@@ -317,22 +304,25 @@
 	ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
 
 	if (ctrl & ONENAND_CTRL_ERROR) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl);
+		printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl);
 		if (ctrl & ONENAND_CTRL_LOCK)
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error.\n");
+			printk(KERN_ERR "onenand_wait: it's locked error.\n");
 		return ctrl;
 	}
 
 	if (interrupt & ONENAND_INT_READ) {
 		int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
 		if (ecc) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);
+			printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
 			if (ecc & ONENAND_ECC_2BIT_ALL) {
 				mtd->ecc_stats.failed++;
 				return ecc;
 			} else if (ecc & ONENAND_ECC_1BIT_ALL)
 				mtd->ecc_stats.corrected++;
 		}
+	} else if (state == FL_READING) {
+		printk(KERN_ERR "onenand_wait: read timeout! ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
+		return -EIO;
 	}
 
 	return 0;
@@ -587,22 +577,32 @@
 static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
 {
 	struct onenand_chip *this = mtd->priv;
-	int block, page;
-	int i;
+	int blockpage, found = 0;
+	unsigned int i;
 
-	block = (int) (addr >> this->erase_shift);
-	page = (int) (addr >> this->page_shift);
-	page &= this->page_mask;
-
-	i = ONENAND_CURRENT_BUFFERRAM(this);
+	blockpage = (int) (addr >> this->page_shift);
 
 	/* Is there valid data? */
-	if (this->bufferram[i].block == block &&
-	    this->bufferram[i].page == page &&
-	    this->bufferram[i].valid)
-		return 1;
+	i = ONENAND_CURRENT_BUFFERRAM(this);
+	if (this->bufferram[i].blockpage == blockpage)
+		found = 1;
+	else {
+		/* Check another BufferRAM */
+		i = ONENAND_NEXT_BUFFERRAM(this);
+		if (this->bufferram[i].blockpage == blockpage) {
+			ONENAND_SET_NEXT_BUFFERRAM(this);
+			found = 1;
+		}
+	}
 
-	return 0;
+	if (found && ONENAND_IS_DDP(this)) {
+		/* Select DataRAM for DDP */
+		int block = (int) (addr >> this->erase_shift);
+		int value = onenand_bufferram_address(this, block);
+		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
+	}
+
+	return found;
 }
 
 /**
@@ -613,31 +613,49 @@
  *
  * Update BufferRAM information
  */
-static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
+static void onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
 		int valid)
 {
 	struct onenand_chip *this = mtd->priv;
-	int block, page;
-	int i;
+	int blockpage;
+	unsigned int i;
 
-	block = (int) (addr >> this->erase_shift);
-	page = (int) (addr >> this->page_shift);
-	page &= this->page_mask;
+	blockpage = (int) (addr >> this->page_shift);
 
-	/* Invalidate BufferRAM */
-	for (i = 0; i < MAX_BUFFERRAM; i++) {
-		if (this->bufferram[i].block == block &&
-		    this->bufferram[i].page == page)
-			this->bufferram[i].valid = 0;
-	}
+	/* Invalidate another BufferRAM */
+	i = ONENAND_NEXT_BUFFERRAM(this);
+	if (this->bufferram[i].blockpage == blockpage)
+		this->bufferram[i].blockpage = -1;
 
 	/* Update BufferRAM */
 	i = ONENAND_CURRENT_BUFFERRAM(this);
-	this->bufferram[i].block = block;
-	this->bufferram[i].page = page;
-	this->bufferram[i].valid = valid;
+	if (valid)
+		this->bufferram[i].blockpage = blockpage;
+	else
+		this->bufferram[i].blockpage = -1;
+}
 
-	return 0;
+/**
+ * onenand_invalidate_bufferram - [GENERIC] Invalidate BufferRAM information
+ * @param mtd		MTD data structure
+ * @param addr		start address to invalidate
+ * @param len		length to invalidate
+ *
+ * Invalidate BufferRAM information
+ */
+static void onenand_invalidate_bufferram(struct mtd_info *mtd, loff_t addr,
+		unsigned int len)
+{
+	struct onenand_chip *this = mtd->priv;
+	int i;
+	loff_t end_addr = addr + len;
+
+	/* Invalidate BufferRAM */
+	for (i = 0; i < MAX_BUFFERRAM; i++) {
+		loff_t buf_addr = this->bufferram[i].blockpage << this->page_shift;
+		if (buf_addr >= addr && buf_addr < end_addr)
+			this->bufferram[i].blockpage = -1;
+	}
 }
 
 /**
@@ -716,7 +734,7 @@
 
 	/* Do not allow reads past end of device */
 	if ((from + len) > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: Attempt read beyond end of device\n");
+		printk(KERN_ERR "onenand_read: Attempt read beyond end of device\n");
 		*retlen = 0;
 		return -EINVAL;
 	}
@@ -724,8 +742,6 @@
 	/* Grab the lock and see if the device is available */
 	onenand_get_device(mtd, FL_READING);
 
-	/* TODO handling oob */
-
 	stats = mtd->ecc_stats;
 
  	/* Read-while-load method */
@@ -754,9 +770,9 @@
  			 * Now we issued chip 1 read and pointed chip 1
  			 * bufferam so we have to point chip 0 bufferam.
  			 */
- 			if (this->device_id & ONENAND_DEVICE_IS_DDP &&
- 					unlikely(from == (this->chipsize >> 1))) {
- 				this->write_word(0, this->base + ONENAND_REG_START_ADDRESS2);
+ 			if (ONENAND_IS_DDP(this) &&
+ 			    unlikely(from == (this->chipsize >> 1))) {
+ 				this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2);
  				boundary = 1;
  			} else
  				boundary = 0;
@@ -770,7 +786,7 @@
  			break;
  		/* Set up for next read from bufferRAM */
  		if (unlikely(boundary))
- 			this->write_word(0x8000, this->base + ONENAND_REG_START_ADDRESS2);
+ 			this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
  		ONENAND_SET_NEXT_BUFFERRAM(this);
  		buf += thislen;
  		thislen = min_t(int, mtd->writesize, len - read);
@@ -801,20 +817,59 @@
 }
 
 /**
+ * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer
+ * @param mtd		MTD device structure
+ * @param buf		destination address
+ * @param column	oob offset to read from
+ * @param thislen	oob length to read
+ */
+static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int column,
+				int thislen)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct nand_oobfree *free;
+	int readcol = column;
+	int readend = column + thislen;
+	int lastgap = 0;
+	uint8_t *oob_buf = this->page_buf + mtd->writesize;
+
+	for (free = this->ecclayout->oobfree; free->length; ++free) {
+		if (readcol >= lastgap)
+			readcol += free->offset - lastgap;
+		if (readend >= lastgap)
+			readend += free->offset - lastgap;
+		lastgap = free->offset + free->length;
+	}
+	this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
+	for (free = this->ecclayout->oobfree; free->length; ++free) {
+		int free_end = free->offset + free->length;
+		if (free->offset < readend && free_end > readcol) {
+			int st = max_t(int,free->offset,readcol);
+			int ed = min_t(int,free_end,readend);
+			int n = ed - st;
+			memcpy(buf, oob_buf + st, n);
+			buf += n;
+		}
+	}
+	return 0;
+}
+
+/**
  * onenand_do_read_oob - [MTD Interface] OneNAND read out-of-band
  * @param mtd		MTD device structure
  * @param from		offset to read from
  * @param len		number of bytes to read
  * @param retlen	pointer to variable to store the number of read bytes
  * @param buf		the databuffer to put data
+ * @param mode		operation mode
  *
  * OneNAND read out-of-band data from the spare area
  */
-int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
-			size_t *retlen, u_char *buf)
+static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t *retlen, u_char *buf, mtd_oob_mode_t mode)
 {
 	struct onenand_chip *this = mtd->priv;
-	int read = 0, thislen, column;
+	int read = 0, thislen, column, oobsize;
 	int ret = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
@@ -822,21 +877,33 @@
 	/* Initialize return length value */
 	*retlen = 0;
 
+	if (mode == MTD_OOB_AUTO)
+		oobsize = this->ecclayout->oobavail;
+	else
+		oobsize = mtd->oobsize;
+
+	column = from & (mtd->oobsize - 1);
+
+	if (unlikely(column >= oobsize)) {
+		printk(KERN_ERR "onenand_read_oob: Attempted to start read outside oob\n");
+		return -EINVAL;
+	}
+
 	/* Do not allow reads past end of device */
-	if (unlikely((from + len) > mtd->size)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: Attempt read beyond end of device\n");
+	if (unlikely(from >= mtd->size ||
+		     column + len > ((mtd->size >> this->page_shift) -
+				     (from >> this->page_shift)) * oobsize)) {
+		printk(KERN_ERR "onenand_read_oob: Attempted to read beyond end of device\n");
 		return -EINVAL;
 	}
 
 	/* Grab the lock and see if the device is available */
 	onenand_get_device(mtd, FL_READING);
 
-	column = from & (mtd->oobsize - 1);
-
 	while (read < len) {
 		cond_resched();
 
-		thislen = mtd->oobsize - column;
+		thislen = oobsize - column;
 		thislen = min_t(int, thislen, len);
 
 		this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
@@ -846,11 +913,14 @@
 		ret = this->wait(mtd, FL_READING);
 		/* First copy data and check return value for ECC handling */
 
-		this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
+		if (mode == MTD_OOB_AUTO)
+			onenand_transfer_auto_oob(mtd, buf, column, thislen);
+		else
+			this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
 
 		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = 0x%x\n", ret);
-			goto out;
+			printk(KERN_ERR "onenand_read_oob: read failed = 0x%x\n", ret);
+			break;
 		}
 
 		read += thislen;
@@ -868,7 +938,6 @@
 		}
 	}
 
-out:
 	/* Deselect and wake up anyone waiting on the device */
 	onenand_release_device(mtd);
 
@@ -885,10 +954,132 @@
 static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
 			    struct mtd_oob_ops *ops)
 {
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
-
+	switch (ops->mode) {
+	case MTD_OOB_PLACE:
+	case MTD_OOB_AUTO:
+		break;
+	case MTD_OOB_RAW:
+		/* Not implemented yet */
+	default:
+		return -EINVAL;
+	}
 	return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->ooblen,
-				   &ops->oobretlen, ops->oobbuf);
+				   &ops->oobretlen, ops->oobbuf, ops->mode);
+}
+
+/**
+ * onenand_bbt_wait - [DEFAULT] wait until the command is done
+ * @param mtd		MTD device structure
+ * @param state		state to select the max. timeout value
+ *
+ * Wait for command done.
+ */
+static int onenand_bbt_wait(struct mtd_info *mtd, int state)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned long timeout;
+	unsigned int interrupt;
+	unsigned int ctrl;
+
+	/* The 20 msec is enough */
+	timeout = jiffies + msecs_to_jiffies(20);
+	while (time_before(jiffies, timeout)) {
+		interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
+		if (interrupt & ONENAND_INT_MASTER)
+			break;
+	}
+	/* To get correct interrupt status in timeout case */
+	interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
+	ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
+
+	if (ctrl & ONENAND_CTRL_ERROR) {
+		printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl);
+		/* Initial bad block case */
+		if (ctrl & ONENAND_CTRL_LOAD)
+			return ONENAND_BBT_READ_ERROR;
+		return ONENAND_BBT_READ_FATAL_ERROR;
+	}
+
+	if (interrupt & ONENAND_INT_READ) {
+		int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+		if (ecc & ONENAND_ECC_2BIT_ALL)
+			return ONENAND_BBT_READ_ERROR;
+	} else {
+		printk(KERN_ERR "onenand_bbt_wait: read timeout!"
+			"ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
+		return ONENAND_BBT_READ_FATAL_ERROR;
+	}
+
+	return 0;
+}
+
+/**
+ * onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan
+ * @param mtd		MTD device structure
+ * @param from		offset to read from
+ * @param @ops		oob operation description structure
+ *
+ * OneNAND read out-of-band data from the spare area for bbt scan
+ */
+int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, 
+			    struct mtd_oob_ops *ops)
+{
+	struct onenand_chip *this = mtd->priv;
+	int read = 0, thislen, column;
+	int ret = 0;
+	size_t len = ops->ooblen;
+	u_char *buf = ops->oobbuf;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %zi\n", (unsigned int) from, len);
+
+	/* Initialize return value */
+	ops->oobretlen = 0;
+
+	/* Do not allow reads past end of device */
+	if (unlikely((from + len) > mtd->size)) {
+		printk(KERN_ERR "onenand_bbt_read_oob: Attempt read beyond end of device\n");
+		return ONENAND_BBT_READ_FATAL_ERROR;
+	}
+
+	/* Grab the lock and see if the device is available */
+	onenand_get_device(mtd, FL_READING);
+
+	column = from & (mtd->oobsize - 1);
+
+	while (read < len) {
+		cond_resched();
+
+		thislen = mtd->oobsize - column;
+		thislen = min_t(int, thislen, len);
+
+		this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
+
+		onenand_update_bufferram(mtd, from, 0);
+
+		ret = onenand_bbt_wait(mtd, FL_READING);
+		if (ret)
+			break;
+
+		this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
+		read += thislen;
+		if (read == len)
+			break;
+
+		buf += thislen;
+
+		/* Read more? */
+		if (read < len) {
+			/* Update Page size */
+			from += mtd->writesize;
+			column = 0;
+		}
+	}
+
+	/* Deselect and wake up anyone waiting on the device */
+	onenand_release_device(mtd);
+
+	ops->oobretlen = read;
+	return ret;
 }
 
 #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
@@ -897,14 +1088,12 @@
  * @param mtd		MTD device structure
  * @param buf		the databuffer to verify
  * @param to		offset to read from
- * @param len		number of bytes to read and compare
  *
  */
-static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to, int len)
+static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to)
 {
 	struct onenand_chip *this = mtd->priv;
-	char *readp = this->page_buf;
-	int column = to & (mtd->oobsize - 1);
+	char *readp = this->page_buf + mtd->writesize;
 	int status, i;
 
 	this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
@@ -913,9 +1102,8 @@
 	if (status)
 		return status;
 
-	this->read_bufferram(mtd, ONENAND_SPARERAM, readp, column, len);
-
-	for(i = 0; i < len; i++)
+	this->read_bufferram(mtd, ONENAND_SPARERAM, readp, 0, mtd->oobsize);
+	for(i = 0; i < mtd->oobsize; i++)
 		if (buf[i] != 0xFF && buf[i] != readp[i])
 			return -EBADMSG;
 
@@ -923,41 +1111,51 @@
 }
 
 /**
- * onenand_verify_page - [GENERIC] verify the chip contents after a write
- * @param mtd		MTD device structure
- * @param buf		the databuffer to verify
+ * onenand_verify - [GENERIC] verify the chip contents after a write
+ * @param mtd          MTD device structure
+ * @param buf          the databuffer to verify
+ * @param addr         offset to read from
+ * @param len          number of bytes to read and compare
  *
- * Check DataRAM area directly
  */
-static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
+static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, size_t len)
 {
 	struct onenand_chip *this = mtd->priv;
-	void __iomem *dataram0, *dataram1;
+	void __iomem *dataram;
 	int ret = 0;
+	int thislen, column;
 
-	/* In partial page write, just skip it */
-	if ((addr & (mtd->writesize - 1)) != 0)
-		return 0;
+	while (len != 0) {
+		thislen = min_t(int, mtd->writesize, len);
+		column = addr & (mtd->writesize - 1);
+		if (column + thislen > mtd->writesize)
+			thislen = mtd->writesize - column;
 
-	this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
+		this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
 
-	ret = this->wait(mtd, FL_READING);
-	if (ret)
-		return ret;
+		onenand_update_bufferram(mtd, addr, 0);
 
-	onenand_update_bufferram(mtd, addr, 1);
+		ret = this->wait(mtd, FL_READING);
+		if (ret)
+			return ret;
 
-	/* Check, if the two dataram areas are same */
-	dataram0 = this->base + ONENAND_DATARAM;
-	dataram1 = dataram0 + mtd->writesize;
+		onenand_update_bufferram(mtd, addr, 1);
 
-	if (memcmp(dataram0, dataram1, mtd->writesize))
-		return -EBADMSG;
+		dataram = this->base + ONENAND_DATARAM;
+		dataram += onenand_bufferram_offset(mtd, ONENAND_DATARAM);
+
+		if (memcmp(buf, dataram + column, thislen))
+			return -EBADMSG;
+
+		len -= thislen;
+		buf += thislen;
+		addr += thislen;
+	}
 
 	return 0;
 }
 #else
-#define onenand_verify_page(...)	(0)
+#define onenand_verify(...)		(0)
 #define onenand_verify_oob(...)		(0)
 #endif
 
@@ -988,60 +1186,57 @@
 
 	/* Do not allow writes past end of device */
 	if (unlikely((to + len) > mtd->size)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt write to past end of device\n");
+		printk(KERN_ERR "onenand_write: Attempt write to past end of device\n");
 		return -EINVAL;
 	}
 
 	/* Reject writes, which are not page aligned */
         if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
-                DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt to write not page aligned data\n");
+                printk(KERN_ERR "onenand_write: Attempt to write not page aligned data\n");
                 return -EINVAL;
         }
 
 	column = to & (mtd->writesize - 1);
-	subpage = column || (len & (mtd->writesize - 1));
 
 	/* Grab the lock and see if the device is available */
 	onenand_get_device(mtd, FL_WRITING);
 
 	/* Loop until all data write */
 	while (written < len) {
-		int bytes = mtd->writesize;
-		int thislen = min_t(int, bytes, len - written);
+		int thislen = min_t(int, mtd->writesize - column, len - written);
 		u_char *wbuf = (u_char *) buf;
 
 		cond_resched();
 
-		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, bytes);
+		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, thislen);
 
 		/* Partial page write */
+		subpage = thislen < mtd->writesize;
 		if (subpage) {
-			bytes = min_t(int, bytes - column, (int) len);
 			memset(this->page_buf, 0xff, mtd->writesize);
-			memcpy(this->page_buf + column, buf, bytes);
+			memcpy(this->page_buf + column, buf, thislen);
 			wbuf = this->page_buf;
-			/* Even though partial write, we need page size */
-			thislen = mtd->writesize;
 		}
 
-		this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, thislen);
+		this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, mtd->writesize);
 		this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
 
 		this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
 
-		/* In partial page write we don't update bufferram */
-		onenand_update_bufferram(mtd, to, !subpage);
-
 		ret = this->wait(mtd, FL_WRITING);
+
+		/* In partial page write we don't update bufferram */
+		onenand_update_bufferram(mtd, to, !ret && !subpage);
+
 		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret);
+			printk(KERN_ERR "onenand_write: write filaed %d\n", ret);
 			break;
 		}
 
 		/* Only check verify write turn on */
-		ret = onenand_verify_page(mtd, (u_char *) wbuf, to);
+		ret = onenand_verify(mtd, (u_char *) wbuf, to, thislen);
 		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);
+			printk(KERN_ERR "onenand_write: verify failed %d\n", ret);
 			break;
 		}
 
@@ -1064,20 +1259,58 @@
 }
 
 /**
+ * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
+ * @param mtd		MTD device structure
+ * @param oob_buf	oob buffer
+ * @param buf		source address
+ * @param column	oob offset to write to
+ * @param thislen	oob length to write
+ */
+static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
+				  const u_char *buf, int column, int thislen)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct nand_oobfree *free;
+	int writecol = column;
+	int writeend = column + thislen;
+	int lastgap = 0;
+
+	for (free = this->ecclayout->oobfree; free->length; ++free) {
+		if (writecol >= lastgap)
+			writecol += free->offset - lastgap;
+		if (writeend >= lastgap)
+			writeend += free->offset - lastgap;
+		lastgap = free->offset + free->length;
+	}
+	for (free = this->ecclayout->oobfree; free->length; ++free) {
+		int free_end = free->offset + free->length;
+		if (free->offset < writeend && free_end > writecol) {
+			int st = max_t(int,free->offset,writecol);
+			int ed = min_t(int,free_end,writeend);
+			int n = ed - st;
+			memcpy(oob_buf + st, buf, n);
+			buf += n;
+		}
+	}
+	return 0;
+}
+
+/**
  * onenand_do_write_oob - [Internal] OneNAND write out-of-band
  * @param mtd		MTD device structure
  * @param to		offset to write to
  * @param len		number of bytes to write
  * @param retlen	pointer to variable to store the number of written bytes
  * @param buf		the data to write
+ * @param mode		operation mode
  *
  * OneNAND write out-of-band
  */
 static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
-				size_t *retlen, const u_char *buf)
+				size_t *retlen, const u_char *buf, mtd_oob_mode_t mode)
 {
 	struct onenand_chip *this = mtd->priv;
-	int column, ret = 0;
+	int column, ret = 0, oobsize;
 	int written = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
@@ -1085,9 +1318,30 @@
 	/* Initialize retlen, in case of early exit */
 	*retlen = 0;
 
-	/* Do not allow writes past end of device */
-	if (unlikely((to + len) > mtd->size)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: Attempt write to past end of device\n");
+	if (mode == MTD_OOB_AUTO)
+		oobsize = this->ecclayout->oobavail;
+	else
+		oobsize = mtd->oobsize;
+
+	column = to & (mtd->oobsize - 1);
+
+	if (unlikely(column >= oobsize)) {
+		printk(KERN_ERR "onenand_write_oob: Attempted to start write outside oob\n");
+		return -EINVAL;
+	}
+
+	/* For compatibility with NAND: Do not allow write past end of page */
+	if (column + len > oobsize) {
+		printk(KERN_ERR "onenand_write_oob: "
+		      "Attempt to write past end of page\n");
+		return -EINVAL;
+	}
+
+	/* Do not allow reads past end of device */
+	if (unlikely(to >= mtd->size ||
+		     column + len > ((mtd->size >> this->page_shift) -
+				     (to >> this->page_shift)) * oobsize)) {
+		printk(KERN_ERR "onenand_write_oob: Attempted to write past end of device\n");
 		return -EINVAL;
 	}
 
@@ -1096,18 +1350,19 @@
 
 	/* Loop until all data write */
 	while (written < len) {
-		int thislen = min_t(int, mtd->oobsize, len - written);
+		int thislen = min_t(int, oobsize, len - written);
 
 		cond_resched();
 
-		column = to & (mtd->oobsize - 1);
-
 		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
 
 		/* We send data to spare ram with oobsize
 		 * to prevent byte access */
 		memset(this->page_buf, 0xff, mtd->oobsize);
-		memcpy(this->page_buf + column, buf, thislen);
+		if (mode == MTD_OOB_AUTO)
+			onenand_fill_auto_oob(mtd, this->page_buf, buf, column, thislen);
+		else
+			memcpy(this->page_buf + column, buf, thislen);
 		this->write_bufferram(mtd, ONENAND_SPARERAM, this->page_buf, 0, mtd->oobsize);
 
 		this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
@@ -1116,26 +1371,25 @@
 
 		ret = this->wait(mtd, FL_WRITING);
 		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: write filaed %d\n", ret);
-			goto out;
+			printk(KERN_ERR "onenand_write_oob: write failed %d\n", ret);
+			break;
 		}
 
-		ret = onenand_verify_oob(mtd, buf, to, thislen);
+		ret = onenand_verify_oob(mtd, this->page_buf, to);
 		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: verify failed %d\n", ret);
-			goto out;
+			printk(KERN_ERR "onenand_write_oob: verify failed %d\n", ret);
+			break;
 		}
 
 		written += thislen;
-
 		if (written == len)
 			break;
 
-		to += thislen;
+		to += mtd->writesize;
 		buf += thislen;
+		column = 0;
 	}
 
-out:
 	/* Deselect and wake up anyone waiting on the device */
 	onenand_release_device(mtd);
 
@@ -1153,10 +1407,17 @@
 static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
 			     struct mtd_oob_ops *ops)
 {
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
-
+	switch (ops->mode) {
+	case MTD_OOB_PLACE:
+	case MTD_OOB_AUTO:
+		break;
+	case MTD_OOB_RAW:
+		/* Not implemented yet */
+	default:
+		return -EINVAL;
+	}
 	return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->ooblen,
-				    &ops->oobretlen, ops->oobbuf);
+				    &ops->oobretlen, ops->oobbuf, ops->mode);
 }
 
 /**
@@ -1199,19 +1460,19 @@
 
 	/* Start address must align on block boundary */
 	if (unlikely(instr->addr & (block_size - 1))) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Unaligned address\n");
+		printk(KERN_ERR "onenand_erase: Unaligned address\n");
 		return -EINVAL;
 	}
 
 	/* Length must align on block boundary */
 	if (unlikely(instr->len & (block_size - 1))) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Length not block aligned\n");
+		printk(KERN_ERR "onenand_erase: Length not block aligned\n");
 		return -EINVAL;
 	}
 
 	/* Do not allow erase past end of device */
 	if (unlikely((instr->len + instr->addr) > mtd->size)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Erase past end of device\n");
+		printk(KERN_ERR "onenand_erase: Erase past end of device\n");
 		return -EINVAL;
 	}
 
@@ -1238,10 +1499,12 @@
 
 		this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
 
+		onenand_invalidate_bufferram(mtd, addr, block_size);
+
 		ret = this->wait(mtd, FL_ERASING);
 		/* Check, if it is write protected */
 		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
+			printk(KERN_ERR "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
 			instr->state = MTD_ERASE_FAILED;
 			instr->fail_addr = addr;
 			goto erase_exit;
@@ -1322,7 +1585,7 @@
 
         /* We write two bytes, so we dont have to mess with 16 bit access */
         ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
-        return onenand_do_write_oob(mtd, ofs , 2, &retlen, buf);
+        return onenand_do_write_oob(mtd, ofs , 2, &retlen, buf, MTD_OOB_PLACE);
 }
 
 /**
@@ -1491,6 +1754,8 @@
 	struct onenand_chip *this = mtd->priv;
 
 	if (this->options & ONENAND_HAS_UNLOCK_ALL) {
+		/* Set start block address */
+		this->write_word(0, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
 		/* Write unlock command */
 		this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
 
@@ -1503,13 +1768,10 @@
 			continue;
 
 		/* Workaround for all block unlock in DDP */
-		if (this->device_id & ONENAND_DEVICE_IS_DDP) {
-			loff_t ofs;
-			size_t len;
-
+		if (ONENAND_IS_DDP(this)) {
 			/* 1st block on another chip */
-			ofs = this->chipsize >> 1;
-			len = 1 << this->erase_shift;
+			loff_t ofs = this->chipsize >> 1;
+			size_t len = mtd->erasesize;
 
 			onenand_unlock(mtd, ofs, len);
 		}
@@ -1617,7 +1879,7 @@
 	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
 	this->wait(mtd, FL_OTPING);
 
-	ret = onenand_do_write_oob(mtd, from, len, retlen, buf);
+	ret = onenand_do_write_oob(mtd, from, len, retlen, buf, MTD_OOB_PLACE);
 
 	/* Exit OTP access mode */
 	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
@@ -1823,12 +2085,13 @@
 #endif	/* CONFIG_MTD_ONENAND_OTP */
 
 /**
- * onenand_lock_scheme - Check and set OneNAND lock scheme
+ * onenand_check_features - Check and set OneNAND features
  * @param mtd		MTD data structure
  *
- * Check and set OneNAND lock scheme
+ * Check and set OneNAND features
+ * - lock scheme
  */
-static void onenand_lock_scheme(struct mtd_info *mtd)
+static void onenand_check_features(struct mtd_info *mtd)
 {
 	struct onenand_chip *this = mtd->priv;
 	unsigned int density, process;
@@ -1961,26 +2224,28 @@
 	density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
 	this->chipsize = (16 << density) << 20;
 	/* Set density mask. it is used for DDP */
-	this->density_mask = (1 << (density + 6));
+	if (ONENAND_IS_DDP(this))
+		this->density_mask = (1 << (density + 6));
+	else
+		this->density_mask = 0;
 
 	/* OneNAND page size & block size */
 	/* The data buffer size is equal to page size */
 	mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
 	mtd->oobsize = mtd->writesize >> 5;
-	/* Pagers per block is always 64 in OneNAND */
+	/* Pages per a block are always 64 in OneNAND */
 	mtd->erasesize = mtd->writesize << 6;
 
 	this->erase_shift = ffs(mtd->erasesize) - 1;
 	this->page_shift = ffs(mtd->writesize) - 1;
-	this->ppb_shift = (this->erase_shift - this->page_shift);
-	this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
+	this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1;
 
 	/* REVIST: Multichip handling */
 
 	mtd->size = this->chipsize;
 
-	/* Check OneNAND lock scheme */
-	onenand_lock_scheme(mtd);
+	/* Check OneNAND features */
+	onenand_check_features(mtd);
 
 	return 0;
 }
@@ -2021,6 +2286,7 @@
  */
 int onenand_scan(struct mtd_info *mtd, int maxchips)
 {
+	int i;
 	struct onenand_chip *this = mtd->priv;
 
 	if (!this->read_word)
@@ -2092,12 +2358,21 @@
 	}
 
 	this->subpagesize = mtd->writesize >> mtd->subpage_sft;
+
+	/*
+	 * The number of bytes available for a client to place data into
+	 * the out of band area
+	 */
+	this->ecclayout->oobavail = 0;
+	for (i = 0; this->ecclayout->oobfree[i].length; i++)
+		this->ecclayout->oobavail +=
+			this->ecclayout->oobfree[i].length;
+
 	mtd->ecclayout = this->ecclayout;
 
 	/* Fill in remaining MTD driver data */
 	mtd->type = MTD_NANDFLASH;
 	mtd->flags = MTD_CAP_NANDFLASH;
-	mtd->ecctype = MTD_ECC_SW;
 	mtd->erase = onenand_erase;
 	mtd->point = NULL;
 	mtd->unpoint = NULL;
@@ -2144,8 +2419,11 @@
 	del_mtd_device (mtd);
 
 	/* Free bad block table memory, if allocated */
-	if (this->bbm)
+	if (this->bbm) {
+		struct bbm_info *bbm = this->bbm;
+		kfree(bbm->bbt);
 		kfree(this->bbm);
+	}
 	/* Buffer allocated by onenand_scan */
 	if (this->options & ONENAND_PAGEBUF_ALLOC)
 		kfree(this->page_buf);
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index 98f8fd1..aecdd50 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -17,8 +17,8 @@
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/compatmac.h>
 
-extern int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
-			       size_t *retlen, u_char *buf);
+extern int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
+				struct mtd_oob_ops *ops);
 
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
@@ -65,10 +65,11 @@
 	int startblock;
 	loff_t from;
 	size_t readlen, ooblen;
+	struct mtd_oob_ops ops;
 
 	printk(KERN_INFO "Scanning device for bad blocks\n");
 
-	len = 1;
+	len = 2;
 
 	/* We need only read few bytes from the OOB area */
 	scanlen = ooblen = 0;
@@ -82,22 +83,24 @@
 	startblock = 0;
 	from = 0;
 
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooblen = readlen;
+	ops.oobbuf = buf;
+	ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
+
 	for (i = startblock; i < numblocks; ) {
 		int ret;
 
 		for (j = 0; j < len; j++) {
-			size_t retlen;
-
 			/* No need to read pages fully,
 			 * just read required OOB bytes */
-			ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs,
-						  readlen, &retlen, &buf[0]);
+			ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);
 
 			/* If it is a initial bad block, just ignore it */
-			if (ret && !(ret & ONENAND_CTRL_LOAD))
-				return ret;
+			if (ret == ONENAND_BBT_READ_FATAL_ERROR)
+				return -EIO;
 
-			if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
+			if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
 				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
 				printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
 					i >> 1, (unsigned int) from);
@@ -168,8 +171,8 @@
  * marked good / bad blocks and writes the bad block table(s) to
  * the selected place.
  *
- * The bad block table memory is allocated here. It must be freed
- * by calling the onenand_free_bbt function.
+ * The bad block table memory is allocated here. It is freed
+ * by the onenand_release function.
  *
  */
 int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index 035cd9b..a61351f 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -94,8 +94,19 @@
 			 * (NOTE: this is 'size' not 'data_length'; size is
 			 * the full size of the entry.)
 			 */
-			if (swab32(buf[i].size) == master->erasesize) {
+
+			/* RedBoot can combine the FIS directory and
+			   config partitions into a single eraseblock;
+			   we assume wrong-endian if either the swapped
+			   'size' matches the eraseblock size precisely,
+			   or if the swapped size actually fits in an
+			   eraseblock while the unswapped size doesn't. */
+			if (swab32(buf[i].size) == master->erasesize ||
+			    (buf[i].size > master->erasesize
+			     && swab32(buf[i].size) < master->erasesize)) {
 				int j;
+				/* Update numslots based on actual FIS directory size */
+				numslots = swab32(buf[i].size) / sizeof (struct fis_image_desc);
 				for (j = 0; j < numslots; ++j) {
 
 					/* A single 0xff denotes a deleted entry.
@@ -120,11 +131,11 @@
 					swab32s(&buf[j].desc_cksum);
 					swab32s(&buf[j].file_cksum);
 				}
+			} else if (buf[i].size < master->erasesize) {
+				/* Update numslots based on actual FIS directory size */
+				numslots = buf[i].size / sizeof(struct fis_image_desc);
 			}
 			break;
-		} else {
-			/* re-calculate of real numslots */
-			numslots = buf[i].size / sizeof(struct fis_image_desc);
 		}
 	}
 	if (i == numslots) {
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 7e34c4f..bc7e906 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -600,8 +600,7 @@
 	    count -= semi_count;
 	    memcpy_fromio(skb->data + semi_count, base + ei_status.priv, count);
 	} else {
-		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, base + ring_offset, count, 0);
+		memcpy_fromio(skb->data, base + ring_offset, count);
 	}
 	return;
     }
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index 2d5ba07..1b3d11e 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -500,7 +500,7 @@
 	int res;
 
         /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
-        if (request_irq(lp->irq, lance_interrupt, SA_SHIRQ, lp->name, dev))
+        if (request_irq(lp->irq, lance_interrupt, IRQF_SHARED, lp->name, dev))
                 return -EAGAIN;
 
         res = lance_reset(dev);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 35ad5cf..99304b2 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -1109,6 +1109,8 @@
 
 	assert (dev != NULL);
 
+	flush_scheduled_work();
+
 	unregister_netdev (dev);
 
 	__rtl8139_cleanup_dev (dev);
@@ -1603,18 +1605,21 @@
 	struct net_device *dev = tp->mii.dev;
 	unsigned long thr_delay = next_tick;
 
+	rtnl_lock();
+
+	if (!netif_running(dev))
+		goto out_unlock;
+
 	if (tp->watchdog_fired) {
 		tp->watchdog_fired = 0;
 		rtl8139_tx_timeout_task(work);
-	} else if (rtnl_trylock()) {
-		rtl8139_thread_iter (dev, tp, tp->mmio_addr);
-		rtnl_unlock ();
-	} else {
-		/* unlikely race.  mitigate with fast poll. */
-		thr_delay = HZ / 2;
-	}
+	} else
+		rtl8139_thread_iter(dev, tp, tp->mmio_addr);
 
-	schedule_delayed_work(&tp->thread, thr_delay);
+	if (tp->have_thread)
+		schedule_delayed_work(&tp->thread, thr_delay);
+out_unlock:
+	rtnl_unlock ();
 }
 
 static void rtl8139_start_thread(struct rtl8139_private *tp)
@@ -1626,19 +1631,11 @@
 		return;
 
 	tp->have_thread = 1;
+	tp->watchdog_fired = 0;
 
 	schedule_delayed_work(&tp->thread, next_tick);
 }
 
-static void rtl8139_stop_thread(struct rtl8139_private *tp)
-{
-	if (tp->have_thread) {
-		cancel_rearming_delayed_work(&tp->thread);
-		tp->have_thread = 0;
-	} else
-		flush_scheduled_work();
-}
-
 static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
 {
 	tp->cur_tx = 0;
@@ -1696,12 +1693,11 @@
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
 
+	tp->watchdog_fired = 1;
 	if (!tp->have_thread) {
-		INIT_DELAYED_WORK(&tp->thread, rtl8139_tx_timeout_task);
+		INIT_DELAYED_WORK(&tp->thread, rtl8139_thread);
 		schedule_delayed_work(&tp->thread, next_tick);
-	} else
-		tp->watchdog_fired = 1;
-
+	}
 }
 
 static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
@@ -2233,8 +2229,6 @@
 
 	netif_stop_queue (dev);
 
-	rtl8139_stop_thread(tp);
-
 	if (netif_msg_ifdown(tp))
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
 			dev->name, RTL_R16 (IntrStatus));
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ad92b6a..9d5c083 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1284,8 +1284,8 @@
 	  will be called pcnet32.
 
 config PCNET32_NAPI
-	bool "Use RX polling (NAPI) (EXPERIMENTAL)"
-	depends on PCNET32 && EXPERIMENTAL
+	bool "Use RX polling (NAPI)"
+	depends on PCNET32
 	help
 	  NAPI is a new driver API designed to reduce CPU and interrupt load
 	  when the driver is receiving lots of packets from the card. It is
@@ -2125,14 +2125,16 @@
 	  will be called sky2.  This is recommended.
 
 config SK98LIN
-	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
+	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
 	depends on PCI
 	---help---
 	  Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
 	  compliant Gigabit Ethernet Adapter.
 
-	  This driver supports the original Yukon chipset. A cleaner driver is 
-	  also available (skge) which seems to work better than this one.
+	  This driver supports the original Yukon chipset. This driver is
+	  deprecated and will be removed from the kernel in the near future,
+	  it has been replaced by the skge driver. skge is cleaner and
+	  seems to work better.
 
 	  This driver does not support the newer Yukon2 chipset. A separate
 	  driver, sky2, is provided to support Yukon2-based adapters.
@@ -2305,27 +2307,6 @@
 	  chipset which is used in the Momenco Ocelot C and Jaguar ATX and
 	  Pegasos II, amongst other PPC and MIPS boards.
 
-config MV643XX_ETH_0
-	bool "MV-643XX Port 0"
-	depends on MV643XX_ETH
-	help
-	  This enables support for Port 0 of the Marvell MV643XX Gigabit
-	  Ethernet.
-
-config MV643XX_ETH_1
-	bool "MV-643XX Port 1"
-	depends on MV643XX_ETH
-	help
-	  This enables support for Port 1 of the Marvell MV643XX Gigabit
-	  Ethernet.
-
-config MV643XX_ETH_2
-	bool "MV-643XX Port 2"
-	depends on MV643XX_ETH
-	help
-	  This enables support for Port 2 of the Marvell MV643XX Gigabit
-	  Ethernet.
-
 config QLA3XXX
 	tristate "QLogic QLA3XXX Network Driver Support"
 	depends on PCI
@@ -2335,6 +2316,17 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called qla3xxx.
 
+config ATL1
+	tristate "Attansic L1 Gigabit Ethernet support (EXPERIMENTAL)"
+	depends on PCI && EXPERIMENTAL
+	select CRC32
+	select MII
+	help
+	  This driver supports the Attansic L1 gigabit ethernet adapter.
+
+	  To compile this driver as a module, choose M here.  The module
+	  will be called atl1.
+
 endmenu
 
 #
@@ -2534,7 +2526,7 @@
 
 config FDDI
 	bool "FDDI driver support"
-	depends on (PCI || EISA)
+	depends on (PCI || EISA || TC)
 	help
 	  Fiber Distributed Data Interface is a high speed local area network
 	  design; essentially a replacement for high speed Ethernet. FDDI can
@@ -2544,11 +2536,31 @@
 	  will say N.
 
 config DEFXX
-	tristate "Digital DEFEA and DEFPA adapter support"
-	depends on FDDI && (PCI || EISA)
-	help
-	  This is support for the DIGITAL series of EISA (DEFEA) and PCI
-	  (DEFPA) controllers which can connect you to a local FDDI network.
+	tristate "Digital DEFTA/DEFEA/DEFPA adapter support"
+	depends on FDDI && (PCI || EISA || TC)
+	---help---
+	  This is support for the DIGITAL series of TURBOchannel (DEFTA),
+	  EISA (DEFEA) and PCI (DEFPA) controllers which can connect you
+	  to a local FDDI network.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called defxx.  If unsure, say N.
+
+config DEFXX_MMIO
+	bool
+	prompt "Use MMIO instead of PIO" if PCI || EISA
+	depends on DEFXX
+	default n if PCI || EISA
+	default y
+	---help---
+	  This instructs the driver to use EISA or PCI memory-mapped I/O
+	  (MMIO) as appropriate instead of programmed I/O ports (PIO).
+	  Enabling this gives an improvement in processing time in parts
+	  of the driver, but it may cause problems with EISA (DEFEA)
+	  adapters.  TURBOchannel does not have the concept of I/O ports,
+	  so MMIO is always used for these (DEFTA) adapters.
+
+	  If unsure, say N.
 
 config SKFP
 	tristate "SysKonnect FDDI PCI support"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 0878e3d..33af833 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_CHELSIO_T3) += cxgb3/
 obj-$(CONFIG_EHEA) += ehea/
 obj-$(CONFIG_BONDING) += bonding/
+obj-$(CONFIG_ATL1) += atl1/
 obj-$(CONFIG_GIANFAR) += gianfar_driver.o
 
 gianfar_driver-objs := gianfar.o \
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index c01f87f..644c408 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -327,8 +327,7 @@
 		memcpy_fromio(skb->data + semi_count,
 				ei_status.mem + TX_PAGES*256, count);
 	} else {
-		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, start, count, 0);
+		memcpy_fromio(skb->data, start, count);
 	}
 }
 
diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c
index e7555d4..6318814 100644
--- a/drivers/net/arcnet/arc-rawmode.c
+++ b/drivers/net/arcnet/arc-rawmode.c
@@ -94,7 +94,7 @@
 
 	BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
 
-	if (length >= MinTU)
+	if (length > MTU)
 		ofs = 512 - length;
 	else
 		ofs = 256 - length;
@@ -183,7 +183,7 @@
 		       length, XMTU);
 		length = XMTU;
 	}
-	if (length > MinTU) {
+	if (length >= MinTU) {
 		hard->offset[0] = 0;
 		hard->offset[1] = ofs = 512 - length;
 	} else if (length > MTU) {
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 4e91dab..83004fd 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -41,7 +41,7 @@
  *     <jojo@repas.de>
  */
 
-#define VERSION "arcnet: v3.93 BETA 2000/04/29 - by Avery Pennarun et al.\n"
+#define VERSION "arcnet: v3.94 BETA 2007/02/08 - by Avery Pennarun et al.\n"
 
 #include <linux/module.h>
 #include <linux/types.h>
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 98d326b..b8c0fa6 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -155,6 +155,7 @@
 	{ 0x1571, 0xa00b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
 	{ 0x1571, 0xa00c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
 	{ 0x1571, 0xa00d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
+	{ 0x1571, 0xa00e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
 	{ 0x1571, 0xa201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x1571, 0xa202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x1571, 0xa203, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
@@ -163,6 +164,8 @@
 	{ 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x10B5, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+	{ 0x14BA, 0x6000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+	{ 0x10B5, 0x2200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{0,}
 };
 
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index aa9dd8f..7cf0a25 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -104,7 +104,7 @@
 	SET_SUBADR(SUB_SETUP1);
 	outb(lp->setup, _XREG);
 
-	if (lp->card_flags & ARC_CAN_10MBIT)
+	if (lp->clockm != 0)
 	{
 		SET_SUBADR(SUB_SETUP2);
 		outb(lp->setup2, _XREG);
@@ -338,7 +338,8 @@
 }
 
 #if defined(CONFIG_ARCNET_COM20020_PCI_MODULE) || \
-    defined(CONFIG_ARCNET_COM20020_ISA_MODULE)
+    defined(CONFIG_ARCNET_COM20020_ISA_MODULE) || \
+    defined(CONFIG_ARCNET_COM20020_CS_MODULE)
 EXPORT_SYMBOL(com20020_check);
 EXPORT_SYMBOL(com20020_found);
 #endif
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index d6da3ce..a292188 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -33,7 +33,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 4fc2347..8411783 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -48,7 +48,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 72c41f5..61f574a 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -28,7 +28,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/net/atl1/Makefile b/drivers/net/atl1/Makefile
new file mode 100644
index 0000000..a6b707e
--- /dev/null
+++ b/drivers/net/atl1/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ATL1)	+= atl1.o
+atl1-y			+= atl1_main.o atl1_hw.o atl1_ethtool.o atl1_param.o
diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h
new file mode 100644
index 0000000..b1c6034
--- /dev/null
+++ b/drivers/net/atl1/atl1.h
@@ -0,0 +1,283 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * 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.
+ */
+
+#ifndef _ATL1_H_
+#define _ATL1_H_
+
+#include <linux/types.h>
+#include <linux/if_vlan.h>
+
+#include "atl1_hw.h"
+
+/* function prototypes needed by multiple files */
+s32 atl1_up(struct atl1_adapter *adapter);
+void atl1_down(struct atl1_adapter *adapter);
+int atl1_reset(struct atl1_adapter *adapter);
+s32 atl1_setup_ring_resources(struct atl1_adapter *adapter);
+void atl1_free_ring_resources(struct atl1_adapter *adapter);
+
+extern char atl1_driver_name[];
+extern char atl1_driver_version[];
+extern const struct ethtool_ops atl1_ethtool_ops;
+
+struct atl1_adapter;
+
+#define ATL1_MAX_INTR		3
+
+#define ATL1_DEFAULT_TPD	256
+#define ATL1_MAX_TPD		1024
+#define ATL1_MIN_TPD		64
+#define ATL1_DEFAULT_RFD	512
+#define ATL1_MIN_RFD		128
+#define ATL1_MAX_RFD		2048
+
+#define ATL1_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i]))
+#define ATL1_RFD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_free_desc)
+#define ATL1_TPD_DESC(R, i)	ATL1_GET_DESC(R, i, struct tx_packet_desc)
+#define ATL1_RRD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_return_desc)
+
+/*
+ * Some workarounds require millisecond delays and are run during interrupt
+ * context.  Most notably, when establishing link, the phy may need tweaking
+ * but cannot process phy register reads/writes faster than millisecond
+ * intervals...and we establish link due to a "link status change" interrupt.
+ */
+
+/*
+ * wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer
+ */
+struct atl1_buffer {
+	struct sk_buff *skb;
+	u16 length;
+	u16 alloced;
+	dma_addr_t dma;
+};
+
+#define MAX_TX_BUF_LEN		0x3000	/* 12KB */
+
+struct atl1_tpd_ring {
+	void *desc;		/* pointer to the descriptor ring memory */
+	dma_addr_t dma;		/* physical adress of the descriptor ring */
+	u16 size;		/* length of descriptor ring in bytes */
+	u16 count;		/* number of descriptors in the ring */
+	u16 hw_idx;		/* hardware index */
+	atomic_t next_to_clean;
+	atomic_t next_to_use;
+	struct atl1_buffer *buffer_info;
+};
+
+struct atl1_rfd_ring {
+	void *desc;
+	dma_addr_t dma;
+	u16 size;
+	u16 count;
+	atomic_t next_to_use;
+	u16 next_to_clean;
+	struct atl1_buffer *buffer_info;
+};
+
+struct atl1_rrd_ring {
+	void *desc;
+	dma_addr_t dma;
+	unsigned int size;
+	u16 count;
+	u16 next_to_use;
+	atomic_t next_to_clean;
+};
+
+struct atl1_ring_header {
+	void *desc;		/* pointer to the descriptor ring memory */
+	dma_addr_t dma;		/* physical adress of the descriptor ring */
+	unsigned int size;	/* length of descriptor ring in bytes */
+};
+
+struct atl1_cmb {
+	struct coals_msg_block *cmb;
+	dma_addr_t dma;
+};
+
+struct atl1_smb {
+	struct stats_msg_block *smb;
+	dma_addr_t dma;
+};
+
+/* Statistics counters */
+struct atl1_sft_stats {
+	u64 rx_packets;
+	u64 tx_packets;
+	u64 rx_bytes;
+	u64 tx_bytes;
+	u64 multicast;
+	u64 collisions;
+	u64 rx_errors;
+	u64 rx_length_errors;
+	u64 rx_crc_errors;
+	u64 rx_frame_errors;
+	u64 rx_fifo_errors;
+	u64 rx_missed_errors;
+	u64 tx_errors;
+	u64 tx_fifo_errors;
+	u64 tx_aborted_errors;
+	u64 tx_window_errors;
+	u64 tx_carrier_errors;
+
+	u64 tx_pause;		/* num Pause packet transmitted. */
+	u64 excecol;		/* num tx packets aborted due to excessive collisions. */
+	u64 deffer;		/* num deferred tx packets */
+	u64 scc;		/* num packets subsequently transmitted successfully w/ single prior collision. */
+	u64 mcc;		/* num packets subsequently transmitted successfully w/ multiple prior collisions. */
+	u64 latecol;		/* num tx packets  w/ late collisions. */
+	u64 tx_underun;		/* num tx packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+	u64 tx_trunc;		/* num tx packets truncated due to size exceeding MTU, regardless whether truncated by Selene or not. (The name doesn't really reflect the meaning in this case.) */
+	u64 rx_pause;		/* num Pause packets received. */
+	u64 rx_rrd_ov;
+	u64 rx_trunc;
+};
+
+/* board specific private data structure */
+#define ATL1_REGS_LEN	8
+
+/* Structure containing variables used by the shared code */
+struct atl1_hw {
+	u8 __iomem *hw_addr;
+	struct atl1_adapter *back;
+	enum atl1_dma_order dma_ord;
+	enum atl1_dma_rcb rcb_value;
+	enum atl1_dma_req_block dmar_block;
+	enum atl1_dma_req_block dmaw_block;
+	u8 preamble_len;
+	u8 max_retry;		/* Retransmission maximum, after which the packet will be discarded */
+	u8 jam_ipg;		/* IPG to start JAM for collision based flow control in half-duplex mode. In units of 8-bit time */
+	u8 ipgt;		/* Desired back to back inter-packet gap. The default is 96-bit time */
+	u8 min_ifg;		/* Minimum number of IFG to enforce in between RX frames. Frame gap below such IFP is dropped */
+	u8 ipgr1;		/* 64bit Carrier-Sense window */
+	u8 ipgr2;		/* 96-bit IPG window */
+	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned burst. Each TPD is 16 bytes long */
+	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned burst. Each RFD is 12 bytes long */
+	u8 rfd_fetch_gap;
+	u8 rrd_burst;		/* Threshold number of RRDs that can be retired in a burst. Each RRD is 16 bytes long */
+	u8 tpd_fetch_th;
+	u8 tpd_fetch_gap;
+	u16 tx_jumbo_task_th;
+	u16 txf_burst;		/* Number of data bytes to read in a cache-aligned burst. Each SRAM entry is
+				   8 bytes long */
+	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN packets should add 4 bytes */
+	u16 rx_jumbo_lkah;
+	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after every 512ns passes. */
+	u16 lcol;		/* Collision Window */
+
+	u16 cmb_tpd;
+	u16 cmb_rrd;
+	u16 cmb_rx_timer;
+	u16 cmb_tx_timer;
+	u32 smb_timer;
+	u16 media_type;
+	u16 autoneg_advertised;
+	u16 pci_cmd_word;
+
+	u16 mii_autoneg_adv_reg;
+	u16 mii_1000t_ctrl_reg;
+
+	u32 mem_rang;
+	u32 txcw;
+	u32 max_frame_size;
+	u32 min_frame_size;
+	u32 mc_filter_type;
+	u32 num_mc_addrs;
+	u32 collision_delta;
+	u32 tx_packet_delta;
+	u16 phy_spd_default;
+
+	u16 dev_rev;
+	u8 revision_id;
+
+	/* spi flash */
+	u8 flash_vendor;
+
+	u8 dma_fairness;
+	u8 mac_addr[ETH_ALEN];
+	u8 perm_mac_addr[ETH_ALEN];
+
+	/* bool phy_preamble_sup; */
+	bool phy_configured;
+};
+
+struct atl1_adapter {
+	/* OS defined structs */
+	struct net_device *netdev;
+	struct pci_dev *pdev;
+	struct net_device_stats net_stats;
+	struct atl1_sft_stats soft_stats;
+
+	struct vlan_group *vlgrp;
+	u32 rx_buffer_len;
+	u32 wol;
+	u16 link_speed;
+	u16 link_duplex;
+	spinlock_t lock;
+	atomic_t irq_sem;
+	struct work_struct tx_timeout_task;
+	struct work_struct link_chg_task;
+	struct work_struct pcie_dma_to_rst_task;
+	struct timer_list watchdog_timer;
+	struct timer_list phy_config_timer;
+	bool phy_timer_pending;
+
+	bool mac_disabled;
+
+	/* All descriptor rings' memory */
+	struct atl1_ring_header ring_header;
+
+	/* TX */
+	struct atl1_tpd_ring tpd_ring;
+	spinlock_t mb_lock;
+
+	/* RX */
+	struct atl1_rfd_ring rfd_ring;
+	struct atl1_rrd_ring rrd_ring;
+	u64 hw_csum_err;
+	u64 hw_csum_good;
+
+	u32 gorcl;
+	u64 gorcl_old;
+
+	/* Interrupt Moderator timer ( 2us resolution) */
+	u16 imt;
+	/* Interrupt Clear timer (2us resolution) */
+	u16 ict;
+
+	/* MII interface info */
+	struct mii_if_info mii;
+
+	/* structs defined in atl1_hw.h */
+	u32 bd_number;		/* board number */
+	bool pci_using_64;
+	struct atl1_hw hw;
+	struct atl1_smb smb;
+	struct atl1_cmb cmb;
+
+	u32 pci_state[16];
+};
+
+#endif	/* _ATL1_H_ */
diff --git a/drivers/net/atl1/atl1_ethtool.c b/drivers/net/atl1/atl1_ethtool.c
new file mode 100644
index 0000000..c11c277
--- /dev/null
+++ b/drivers/net/atl1/atl1_ethtool.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * 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/types.h>
+#include <linux/pci.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/mii.h>
+#include <asm/uaccess.h>
+
+#include "atl1.h"
+
+struct atl1_stats {
+	char stat_string[ETH_GSTRING_LEN];
+	int sizeof_stat;
+	int stat_offset;
+};
+
+#define ATL1_STAT(m) sizeof(((struct atl1_adapter *)0)->m), \
+	offsetof(struct atl1_adapter, m)
+
+static struct atl1_stats atl1_gstrings_stats[] = {
+	{"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
+	{"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
+	{"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
+	{"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
+	{"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
+	{"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
+	{"rx_dropped", ATL1_STAT(net_stats.rx_dropped)},
+	{"tx_dropped", ATL1_STAT(net_stats.tx_dropped)},
+	{"multicast", ATL1_STAT(soft_stats.multicast)},
+	{"collisions", ATL1_STAT(soft_stats.collisions)},
+	{"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
+	{"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+	{"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
+	{"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
+	{"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
+	{"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+	{"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
+	{"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
+	{"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
+	{"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
+	{"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
+	{"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
+	{"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
+	{"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
+	{"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
+	{"tx_underun", ATL1_STAT(soft_stats.tx_underun)},
+	{"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
+	{"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
+	{"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
+	{"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
+	{"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
+};
+
+static void atl1_get_ethtool_stats(struct net_device *netdev,
+				struct ethtool_stats *stats, u64 *data)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	int i;
+	char *p;
+
+	for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+		p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
+		data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
+			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+	}
+
+}
+
+static int atl1_get_stats_count(struct net_device *netdev)
+{
+	return ARRAY_SIZE(atl1_gstrings_stats);
+}
+
+static int atl1_get_settings(struct net_device *netdev,
+				struct ethtool_cmd *ecmd)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+
+	ecmd->supported = (SUPPORTED_10baseT_Half |
+			   SUPPORTED_10baseT_Full |
+			   SUPPORTED_100baseT_Half |
+			   SUPPORTED_100baseT_Full |
+			   SUPPORTED_1000baseT_Full |
+			   SUPPORTED_Autoneg | SUPPORTED_TP);
+	ecmd->advertising = ADVERTISED_TP;
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
+		ecmd->advertising |= ADVERTISED_Autoneg;
+		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
+			ecmd->advertising |= ADVERTISED_Autoneg;
+			ecmd->advertising |=
+			    (ADVERTISED_10baseT_Half |
+			     ADVERTISED_10baseT_Full |
+			     ADVERTISED_100baseT_Half |
+			     ADVERTISED_100baseT_Full |
+			     ADVERTISED_1000baseT_Full);
+		}
+		else
+			ecmd->advertising |= (ADVERTISED_1000baseT_Full);
+	}
+	ecmd->port = PORT_TP;
+	ecmd->phy_address = 0;
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	if (netif_carrier_ok(adapter->netdev)) {
+		u16 link_speed, link_duplex;
+		atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
+		ecmd->speed = link_speed;
+		if (link_duplex == FULL_DUPLEX)
+			ecmd->duplex = DUPLEX_FULL;
+		else
+			ecmd->duplex = DUPLEX_HALF;
+	} else {
+		ecmd->speed = -1;
+		ecmd->duplex = -1;
+	}
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL)
+		ecmd->autoneg = AUTONEG_ENABLE;
+	else
+		ecmd->autoneg = AUTONEG_DISABLE;
+
+	return 0;
+}
+
+static int atl1_set_settings(struct net_device *netdev,
+				struct ethtool_cmd *ecmd)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+	u16 phy_data;
+	int ret_val = 0;
+	u16 old_media_type = hw->media_type;
+
+	if (netif_running(adapter->netdev)) {
+		printk(KERN_DEBUG "%s: ethtool shutting down adapter\n",
+			atl1_driver_name);
+		atl1_down(adapter);
+	}
+
+	if (ecmd->autoneg == AUTONEG_ENABLE)
+		hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
+	else {
+		if (ecmd->speed == SPEED_1000) {
+			if (ecmd->duplex != DUPLEX_FULL) {
+				printk(KERN_WARNING
+				       "%s: can't force to 1000M half duplex\n",
+					atl1_driver_name);
+				ret_val = -EINVAL;
+				goto exit_sset;
+			}
+			hw->media_type = MEDIA_TYPE_1000M_FULL;
+		} else if (ecmd->speed == SPEED_100) {
+			if (ecmd->duplex == DUPLEX_FULL) {
+				hw->media_type = MEDIA_TYPE_100M_FULL;
+			} else
+				hw->media_type = MEDIA_TYPE_100M_HALF;
+		} else {
+			if (ecmd->duplex == DUPLEX_FULL)
+				hw->media_type = MEDIA_TYPE_10M_FULL;
+			else
+				hw->media_type = MEDIA_TYPE_10M_HALF;
+		}
+	}
+	switch (hw->media_type) {
+	case MEDIA_TYPE_AUTO_SENSOR:
+		ecmd->advertising =
+		    ADVERTISED_10baseT_Half |
+		    ADVERTISED_10baseT_Full |
+		    ADVERTISED_100baseT_Half |
+		    ADVERTISED_100baseT_Full |
+		    ADVERTISED_1000baseT_Full |
+		    ADVERTISED_Autoneg | ADVERTISED_TP;
+		break;
+	case MEDIA_TYPE_1000M_FULL:
+		ecmd->advertising =
+		    ADVERTISED_1000baseT_Full |
+		    ADVERTISED_Autoneg | ADVERTISED_TP;
+		break;
+	default:
+		ecmd->advertising = 0;
+		break;
+	}
+	if (atl1_phy_setup_autoneg_adv(hw)) {
+		ret_val = -EINVAL;
+		printk(KERN_WARNING
+			"%s: invalid ethtool speed/duplex setting\n",
+			atl1_driver_name);
+		goto exit_sset;
+	}
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL)
+		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+	else {
+		switch (hw->media_type) {
+		case MEDIA_TYPE_100M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+			    MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_100M_HALF:
+			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_10M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		default:	/* MEDIA_TYPE_10M_HALF: */
+			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		}
+	}
+	atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+exit_sset:
+	if (ret_val)
+		hw->media_type = old_media_type;
+
+	if (netif_running(adapter->netdev)) {
+		printk(KERN_DEBUG "%s: ethtool starting adapter\n",
+			atl1_driver_name);
+		atl1_up(adapter);
+	} else if (!ret_val) {
+		printk(KERN_DEBUG "%s: ethtool resetting adapter\n",
+			atl1_driver_name);
+		atl1_reset(adapter);
+	}
+	return ret_val;
+}
+
+static void atl1_get_drvinfo(struct net_device *netdev,
+				struct ethtool_drvinfo *drvinfo)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	strncpy(drvinfo->driver, atl1_driver_name, sizeof(drvinfo->driver));
+	strncpy(drvinfo->version, atl1_driver_version,
+		sizeof(drvinfo->version));
+	strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+		sizeof(drvinfo->bus_info));
+	drvinfo->eedump_len = ATL1_EEDUMP_LEN;
+}
+
+static void atl1_get_wol(struct net_device *netdev,
+			    struct ethtool_wolinfo *wol)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+	wol->wolopts = 0;
+	if (adapter->wol & ATL1_WUFC_EX)
+		wol->wolopts |= WAKE_UCAST;
+	if (adapter->wol & ATL1_WUFC_MC)
+		wol->wolopts |= WAKE_MCAST;
+	if (adapter->wol & ATL1_WUFC_BC)
+		wol->wolopts |= WAKE_BCAST;
+	if (adapter->wol & ATL1_WUFC_MAG)
+		wol->wolopts |= WAKE_MAGIC;
+	return;
+}
+
+static int atl1_set_wol(struct net_device *netdev,
+			struct ethtool_wolinfo *wol)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+		return -EOPNOTSUPP;
+	adapter->wol = 0;
+	if (wol->wolopts & WAKE_UCAST)
+		adapter->wol |= ATL1_WUFC_EX;
+	if (wol->wolopts & WAKE_MCAST)
+		adapter->wol |= ATL1_WUFC_MC;
+	if (wol->wolopts & WAKE_BCAST)
+		adapter->wol |= ATL1_WUFC_BC;
+	if (wol->wolopts & WAKE_MAGIC)
+		adapter->wol |= ATL1_WUFC_MAG;
+	return 0;
+}
+
+static void atl1_get_ringparam(struct net_device *netdev,
+			    struct ethtool_ringparam *ring)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
+
+	ring->rx_max_pending = ATL1_MAX_RFD;
+	ring->tx_max_pending = ATL1_MAX_TPD;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_pending = rxdr->count;
+	ring->tx_pending = txdr->count;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+
+static int atl1_set_ringparam(struct net_device *netdev,
+				struct ethtool_ringparam *ring)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
+	struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
+	struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
+
+	struct atl1_tpd_ring tpd_old, tpd_new;
+	struct atl1_rfd_ring rfd_old, rfd_new;
+	struct atl1_rrd_ring rrd_old, rrd_new;
+	struct atl1_ring_header rhdr_old, rhdr_new;
+	int err;
+
+	tpd_old = adapter->tpd_ring;
+	rfd_old = adapter->rfd_ring;
+	rrd_old = adapter->rrd_ring;
+	rhdr_old = adapter->ring_header;
+
+	if (netif_running(adapter->netdev))
+		atl1_down(adapter);
+
+	rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
+	rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
+			rfdr->count;
+	rfdr->count = (rfdr->count + 3) & ~3;
+	rrdr->count = rfdr->count;
+
+	tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
+	tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
+			tpdr->count;
+	tpdr->count = (tpdr->count + 3) & ~3;
+
+	if (netif_running(adapter->netdev)) {
+		/* try to get new resources before deleting old */
+		err = atl1_setup_ring_resources(adapter);
+		if (err)
+			goto err_setup_ring;
+
+		/*
+		 * save the new, restore the old in order to free it,
+		 * then restore the new back again
+		 */
+
+		rfd_new = adapter->rfd_ring;
+		rrd_new = adapter->rrd_ring;
+		tpd_new = adapter->tpd_ring;
+		rhdr_new = adapter->ring_header;
+		adapter->rfd_ring = rfd_old;
+		adapter->rrd_ring = rrd_old;
+		adapter->tpd_ring = tpd_old;
+		adapter->ring_header = rhdr_old;
+		atl1_free_ring_resources(adapter);
+		adapter->rfd_ring = rfd_new;
+		adapter->rrd_ring = rrd_new;
+		adapter->tpd_ring = tpd_new;
+		adapter->ring_header = rhdr_new;
+
+		err = atl1_up(adapter);
+		if (err)
+			return err;
+	}
+	return 0;
+
+err_setup_ring:
+	adapter->rfd_ring = rfd_old;
+	adapter->rrd_ring = rrd_old;
+	adapter->tpd_ring = tpd_old;
+	adapter->ring_header = rhdr_old;
+	atl1_up(adapter);
+	return err;
+}
+
+static void atl1_get_pauseparam(struct net_device *netdev,
+			     struct ethtool_pauseparam *epause)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
+		epause->autoneg = AUTONEG_ENABLE;
+	} else {
+		epause->autoneg = AUTONEG_DISABLE;
+	}
+	epause->rx_pause = 1;
+	epause->tx_pause = 1;
+}
+
+static int atl1_set_pauseparam(struct net_device *netdev,
+			     struct ethtool_pauseparam *epause)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
+		epause->autoneg = AUTONEG_ENABLE;
+	} else {
+		epause->autoneg = AUTONEG_DISABLE;
+	}
+
+	epause->rx_pause = 1;
+	epause->tx_pause = 1;
+
+	return 0;
+}
+
+static u32 atl1_get_rx_csum(struct net_device *netdev)
+{
+	return 1;
+}
+
+static void atl1_get_strings(struct net_device *netdev, u32 stringset,
+				u8 *data)
+{
+	u8 *p = data;
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+			memcpy(p, atl1_gstrings_stats[i].stat_string,
+				ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
+		break;
+	}
+}
+
+static int atl1_nway_reset(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+
+	if (netif_running(netdev)) {
+		u16 phy_data;
+		atl1_down(adapter);
+
+		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+			hw->media_type == MEDIA_TYPE_1000M_FULL) {
+			phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+		} else {
+			switch (hw->media_type) {
+			case MEDIA_TYPE_100M_FULL:
+				phy_data = MII_CR_FULL_DUPLEX |
+					MII_CR_SPEED_100 | MII_CR_RESET;
+				break;
+			case MEDIA_TYPE_100M_HALF:
+				phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+				break;
+			case MEDIA_TYPE_10M_FULL:
+				phy_data = MII_CR_FULL_DUPLEX |
+					MII_CR_SPEED_10 | MII_CR_RESET;
+				break;
+			default:  /* MEDIA_TYPE_10M_HALF */
+				phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+			}
+		}
+		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+		atl1_up(adapter);
+	}
+	return 0;
+}
+
+const struct ethtool_ops atl1_ethtool_ops = {
+	.get_settings		= atl1_get_settings,
+	.set_settings		= atl1_set_settings,
+	.get_drvinfo		= atl1_get_drvinfo,
+	.get_wol		= atl1_get_wol,
+	.set_wol		= atl1_set_wol,
+	.get_ringparam		= atl1_get_ringparam,
+	.set_ringparam		= atl1_set_ringparam,
+	.get_pauseparam		= atl1_get_pauseparam,
+	.set_pauseparam 	= atl1_set_pauseparam,
+	.get_rx_csum		= atl1_get_rx_csum,
+	.get_tx_csum		= ethtool_op_get_tx_csum,
+	.set_tx_csum		= ethtool_op_set_tx_hw_csum,
+	.get_link		= ethtool_op_get_link,
+	.get_sg			= ethtool_op_get_sg,
+	.set_sg			= ethtool_op_set_sg,
+	.get_strings		= atl1_get_strings,
+	.nway_reset		= atl1_nway_reset,
+	.get_ethtool_stats	= atl1_get_ethtool_stats,
+	.get_stats_count	= atl1_get_stats_count,
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= ethtool_op_set_tso,
+};
diff --git a/drivers/net/atl1/atl1_hw.c b/drivers/net/atl1/atl1_hw.c
new file mode 100644
index 0000000..314dbaa
--- /dev/null
+++ b/drivers/net/atl1/atl1_hw.c
@@ -0,0 +1,723 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ * 
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * 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/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/if_vlan.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32.h>
+#include <asm/byteorder.h>
+
+#include "atl1.h"
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : ATL1_SUCCESS  or  idle status (if error)
+ */
+s32 atl1_reset_hw(struct atl1_hw *hw)
+{
+	u32 icr;
+	int i;
+
+	/* 
+	 * Clear Interrupt mask to stop board from generating
+	 * interrupts & Clear any pending interrupt events 
+	 */
+	/*
+	 * iowrite32(0, hw->hw_addr + REG_IMR);
+	 * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
+	 */
+
+	/*
+	 * Issue Soft Reset to the MAC.  This will reset the chip's
+	 * transmit, receive, DMA.  It will not effect
+	 * the current PCI configuration.  The global reset bit is self-
+	 * clearing, and should clear within a microsecond.
+	 */
+	iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
+	ioread32(hw->hw_addr + REG_MASTER_CTRL);
+
+	iowrite16(1, hw->hw_addr + REG_GPHY_ENABLE);
+	ioread16(hw->hw_addr + REG_GPHY_ENABLE);
+
+	msleep(1);		/* delay about 1ms */
+
+	/* Wait at least 10ms for All module to be Idle */
+	for (i = 0; i < 10; i++) {
+		icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
+		if (!icr)
+			break;
+		msleep(1);	/* delay 1 ms */
+		cpu_relax();	/* FIXME: is this still the right way to do this? */
+	}
+
+	if (icr) {
+		printk (KERN_DEBUG "icr = %x\n", icr); 
+		return icr;
+	}
+
+	return ATL1_SUCCESS;
+}
+
+/* function about EEPROM
+ *
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+static int atl1_check_eeprom_exist(struct atl1_hw *hw)
+{
+	u32 value;
+	value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+	if (value & SPI_FLASH_CTRL_EN_VPD) {
+		value &= ~SPI_FLASH_CTRL_EN_VPD;
+		iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+	}
+
+	value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
+	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+}
+
+static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
+{
+	int i;
+	u32 control;
+
+	if (offset & 3)
+		return false;	/* address do not align */
+
+	iowrite32(0, hw->hw_addr + REG_VPD_DATA);
+	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+	iowrite32(control, hw->hw_addr + REG_VPD_CAP);
+	ioread32(hw->hw_addr + REG_VPD_CAP);
+
+	for (i = 0; i < 10; i++) {
+		msleep(2);
+		control = ioread32(hw->hw_addr + REG_VPD_CAP);
+		if (control & VPD_CAP_VPD_FLAG)
+			break;
+	}
+	if (control & VPD_CAP_VPD_FLAG) {
+		*p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
+		return true;
+	}
+	return false;		/* timeout */
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+	u32 val;
+	int i;
+
+	val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+	    	MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
+ 		MDIO_CLK_SEL_SHIFT;
+	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+	ioread32(hw->hw_addr + REG_MDIO_CTRL);
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+	}
+	if (!(val & (MDIO_START | MDIO_BUSY))) {
+		*phy_data = (u16) val;
+		return ATL1_SUCCESS;
+	}
+	return ATL1_ERR_PHY;
+}
+
+#define CUSTOM_SPI_CS_SETUP	2
+#define CUSTOM_SPI_CLK_HI	2
+#define CUSTOM_SPI_CLK_LO	2
+#define CUSTOM_SPI_CS_HOLD	2
+#define CUSTOM_SPI_CS_HI	3
+
+static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
+{
+	int i;
+	u32 value;
+
+	iowrite32(0, hw->hw_addr + REG_SPI_DATA);
+	iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
+
+	value = SPI_FLASH_CTRL_WAIT_READY |
+	    (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
+	    SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
+					     SPI_FLASH_CTRL_CLK_HI_MASK) <<
+	    SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
+					   SPI_FLASH_CTRL_CLK_LO_MASK) <<
+	    SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
+					   SPI_FLASH_CTRL_CS_HOLD_MASK) <<
+	    SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
+					    SPI_FLASH_CTRL_CS_HI_MASK) <<
+	    SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
+	    SPI_FLASH_CTRL_INS_SHIFT;
+
+	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+
+	value |= SPI_FLASH_CTRL_START;
+	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+	ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+
+	for (i = 0; i < 10; i++) {
+		msleep(1);	/* 1ms */
+		value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+		if (!(value & SPI_FLASH_CTRL_START))
+			break;
+	}
+
+	if (value & SPI_FLASH_CTRL_START)
+		return false;
+
+	*buf = ioread32(hw->hw_addr + REG_SPI_DATA);
+
+	return true;
+}
+
+/*
+ * get_permanent_address
+ * return 0 if get valid mac address, 
+ */
+static int atl1_get_permanent_address(struct atl1_hw *hw)
+{
+	u32 addr[2];
+	u32 i, control;
+	u16 reg;
+	u8 eth_addr[ETH_ALEN];
+	bool key_valid;
+
+	if (is_valid_ether_addr(hw->perm_mac_addr))
+		return 0;
+
+	/* init */
+	addr[0] = addr[1] = 0;
+
+	if (!atl1_check_eeprom_exist(hw)) {	/* eeprom exist */
+		reg = 0;
+		key_valid = false;
+		/* Read out all EEPROM content */
+		i = 0;
+		while (1) {
+			if (atl1_read_eeprom(hw, i + 0x100, &control)) {
+				if (key_valid) {
+					if (reg == REG_MAC_STA_ADDR)
+						addr[0] = control;
+					else if (reg == (REG_MAC_STA_ADDR + 4))
+						addr[1] = control;
+					key_valid = false;
+				} else if ((control & 0xff) == 0x5A) {
+					key_valid = true;
+					reg = (u16) (control >> 16);
+				} else
+					break;	/* assume data end while encount an invalid KEYWORD */
+			} else
+				break;	/* read error */
+			i += 4;
+		}
+
+		*(u32 *) &eth_addr[2] = swab32(addr[0]);
+		*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+		if (is_valid_ether_addr(eth_addr)) {
+			memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+			return 0;
+		}
+		return 1;
+	}
+
+	/* see if SPI FLAGS exist ? */
+	addr[0] = addr[1] = 0;
+	reg = 0;
+	key_valid = false;
+	i = 0;
+	while (1) {
+		if (atl1_spi_read(hw, i + 0x1f000, &control)) {
+			if (key_valid) {
+				if (reg == REG_MAC_STA_ADDR)
+					addr[0] = control;
+				else if (reg == (REG_MAC_STA_ADDR + 4))
+					addr[1] = control;
+				key_valid = false;
+			} else if ((control & 0xff) == 0x5A) {
+				key_valid = true;
+				reg = (u16) (control >> 16);
+			} else
+				break;	/* data end */
+		} else
+			break;	/* read error */
+		i += 4;
+	}
+
+	*(u32 *) &eth_addr[2] = swab32(addr[0]);
+	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+	if (is_valid_ether_addr(eth_addr)) {
+		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+		return 0;
+	}
+
+	/*
+	 * On some motherboards, the MAC address is written by the
+	 * BIOS directly to the MAC register during POST, and is
+	 * not stored in eeprom.  If all else thus far has failed
+	 * to fetch the permanent MAC address, try reading it directly.
+	 */
+	addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
+	addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+	*(u32 *) &eth_addr[2] = swab32(addr[0]);
+	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+	if (is_valid_ether_addr(eth_addr)) {
+		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Reads the adapter's MAC address from the EEPROM 
+ * hw - Struct containing variables accessed by shared code
+ */
+s32 atl1_read_mac_addr(struct atl1_hw *hw)
+{
+	u16 i;
+
+	if (atl1_get_permanent_address(hw))
+		random_ether_addr(hw->perm_mac_addr);
+
+	for (i = 0; i < ETH_ALEN; i++)
+		hw->mac_addr[i] = hw->perm_mac_addr[i];
+	return ATL1_SUCCESS;
+}
+
+/*
+ * Hashes an address to determine its location in the multicast table
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash
+ *
+ * atl1_hash_mc_addr
+ *  purpose
+ *      set hash value for a multicast address
+ *      hash calcu processing :
+ *          1. calcu 32bit CRC for multicast address
+ *          2. reverse crc with MSB to LSB
+ */
+u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
+{
+	u32 crc32, value = 0;
+	int i;
+
+	crc32 = ether_crc_le(6, mc_addr);
+	crc32 = ~crc32;
+	for (i = 0; i < 32; i++)
+		value |= (((crc32 >> i) & 1) << (31 - i));
+
+	return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
+{
+	u32 hash_bit, hash_reg;
+	u32 mta;
+
+	/*
+	 * The HASH Table  is a register array of 2 32-bit registers.
+	 * It is treated like an array of 64 bits.  We want to set
+	 * bit BitArray[hash_value]. So we figure out what register
+	 * the bit is in, read it, OR in the new bit, then write
+	 * back the new value.  The register is determined by the
+	 * upper 7 bits of the hash value and the bit within that
+	 * register are determined by the lower 5 bits of the value.
+	 */
+	hash_reg = (hash_value >> 31) & 0x1;
+	hash_bit = (hash_value >> 26) & 0x1F;
+	mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+	mta |= (1 << hash_bit);
+	iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
+{
+	int i;
+	u32 val;
+
+	val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+	    (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+	    MDIO_SUP_PREAMBLE |
+	    MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+	ioread32(hw->hw_addr + REG_MDIO_CTRL);
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+	}
+
+	if (!(val & (MDIO_START | MDIO_BUSY)))
+		return ATL1_SUCCESS;
+
+	return ATL1_ERR_PHY;
+}
+
+/*
+ * Make L001's PHY out of Power Saving State (bug)
+ * hw - Struct containing variables accessed by shared code
+ * when power on, L001's PHY always on Power saving State
+ * (Gigabit Link forbidden)
+ */
+static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
+{
+	s32 ret;
+	ret = atl1_write_phy_reg(hw, 29, 0x0029);
+	if (ret)
+		return ret;
+	return atl1_write_phy_reg(hw, 30, 0);
+}
+
+/*
+ *TODO: do something or get rid of this
+ */
+s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
+{
+/*    s32 ret_val;
+ *    u16 phy_data;
+ */
+
+/*
+    ret_val = atl1_write_phy_reg(hw, ...);
+    ret_val = atl1_write_phy_reg(hw, ...);
+    ....
+*/
+	return ATL1_SUCCESS;
+}
+
+/*
+ * Resets the PHY and make all config validate
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
+ */
+static s32 atl1_phy_reset(struct atl1_hw *hw)
+{
+	s32 ret_val;
+	u16 phy_data;
+
+	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+	    hw->media_type == MEDIA_TYPE_1000M_FULL)
+		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+	else {
+		switch (hw->media_type) {
+		case MEDIA_TYPE_100M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+			    MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_100M_HALF:
+			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_10M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		default:	/* MEDIA_TYPE_10M_HALF: */
+			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		}
+	}
+
+	ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+	if (ret_val) {
+		u32 val;
+		int i;
+		/* pcie serdes link may be down! */
+		printk(KERN_DEBUG "%s: autoneg caused pcie phy link down\n", 
+			atl1_driver_name);
+
+		for (i = 0; i < 25; i++) {
+			msleep(1);
+			val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+			if (!(val & (MDIO_START | MDIO_BUSY)))
+				break;
+		}
+
+		if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
+			printk(KERN_WARNING 
+				"%s: pcie link down at least for 25ms\n", 
+				atl1_driver_name);
+			return ret_val;
+		}
+	}
+	return ATL1_SUCCESS;
+}
+
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ * hw - Struct containing variables accessed by shared code
+ */
+s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
+{
+	s32 ret_val;
+	s16 mii_autoneg_adv_reg;
+	s16 mii_1000t_ctrl_reg;
+
+	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
+	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+
+	/* Read the MII 1000Base-T Control Register (Address 9). */
+	mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
+
+	/*
+	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
+	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
+	 * the  1000Base-T Control Register (Address 9).
+	 */
+	mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+	mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK;
+
+	/*
+	 * Need to parse media_type  and set up
+	 * the appropriate PHY registers.
+	 */
+	switch (hw->media_type) {
+	case MEDIA_TYPE_AUTO_SENSOR:
+		mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
+					MII_AR_10T_FD_CAPS |
+					MII_AR_100TX_HD_CAPS |
+					MII_AR_100TX_FD_CAPS);
+		mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
+		break;
+
+	case MEDIA_TYPE_1000M_FULL:
+		mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
+		break;
+
+	case MEDIA_TYPE_100M_FULL:
+		mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
+		break;
+
+	case MEDIA_TYPE_100M_HALF:
+		mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
+		break;
+
+	case MEDIA_TYPE_10M_FULL:
+		mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
+		break;
+
+	default:
+		mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
+		break;
+	}
+
+	/* flow control fixed to enable all */
+	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+
+	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+	hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
+
+	ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+	if (ret_val)
+		return ret_val;
+
+	ret_val = atl1_write_phy_reg(hw, MII_AT001_CR, mii_1000t_ctrl_reg);
+	if (ret_val)
+		return ret_val;
+
+	return ATL1_SUCCESS;
+}
+
+/*
+ * Configures link settings.
+ * hw - Struct containing variables accessed by shared code
+ * Assumes the hardware has previously been reset and the
+ * transmitter and receiver are not enabled.
+ */
+static s32 atl1_setup_link(struct atl1_hw *hw)
+{
+	s32 ret_val;
+
+	/*
+	 * Options:
+	 *  PHY will advertise value(s) parsed from
+	 *  autoneg_advertised and fc
+	 *  no matter what autoneg is , We will not wait link result.
+	 */
+	ret_val = atl1_phy_setup_autoneg_adv(hw);
+	if (ret_val) {
+		printk(KERN_DEBUG "%s: error setting up autonegotiation\n", 
+			atl1_driver_name);
+		return ret_val;
+	}
+	/* SW.Reset , En-Auto-Neg if needed */
+	ret_val = atl1_phy_reset(hw);
+	if (ret_val) {
+		printk(KERN_DEBUG "%s: error resetting the phy\n", 
+			atl1_driver_name);
+		return ret_val;
+	}
+	hw->phy_configured = true;
+	return ret_val;
+}
+
+static struct atl1_spi_flash_dev flash_table[] = {
+/*	MFR_NAME  WRSR  READ  PRGM  WREN  WRDI  RDSR  RDID  SECTOR_ERASE CHIP_ERASE */
+	{"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52,        0x62},
+	{"SST",   0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20,        0x60},
+	{"ST",    0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8,        0xC7},
+};
+
+static void atl1_init_flash_opcode(struct atl1_hw *hw)
+{
+	if (hw->flash_vendor >= sizeof(flash_table) / sizeof(flash_table[0]))
+		hw->flash_vendor = 0;	/* ATMEL */
+
+	/* Init OP table */
+	iowrite8(flash_table[hw->flash_vendor].cmd_program,
+		hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
+	iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
+		hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
+	iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
+		hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
+	iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
+		hw->hw_addr + REG_SPI_FLASH_OP_RDID);
+	iowrite8(flash_table[hw->flash_vendor].cmd_wren,
+		hw->hw_addr + REG_SPI_FLASH_OP_WREN);
+	iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
+		hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
+	iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
+		hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
+	iowrite8(flash_table[hw->flash_vendor].cmd_read,
+		hw->hw_addr + REG_SPI_FLASH_OP_READ);
+}
+
+/*
+ * Performs basic configuration of the adapter.
+ * hw - Struct containing variables accessed by shared code
+ * Assumes that the controller has previously been reset and is in a
+ * post-reset uninitialized state. Initializes multicast table, 
+ * and  Calls routines to setup link
+ * Leaves the transmit and receive units disabled and uninitialized.
+ */
+s32 atl1_init_hw(struct atl1_hw *hw)
+{
+	u32 ret_val = 0;
+
+	/* Zero out the Multicast HASH table */
+	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+	/* clear the old settings from the multicast hash table */
+	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+
+	atl1_init_flash_opcode(hw);
+
+	if (!hw->phy_configured) {
+		/* enable GPHY LinkChange Interrrupt */
+		ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
+		if (ret_val)
+			return ret_val;
+		/* make PHY out of power-saving state */
+		ret_val = atl1_phy_leave_power_saving(hw);
+		if (ret_val)
+			return ret_val;
+		/* Call a subroutine to configure the link */
+		ret_val = atl1_setup_link(hw);
+	}
+	return ret_val;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
+{
+	s32 ret_val;
+	u16 phy_data;
+
+	/* ; --- Read   PHY Specific Status Register (17) */
+	ret_val = atl1_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
+	if (ret_val)
+		return ret_val;
+
+	if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
+		return ATL1_ERR_PHY_RES;
+
+	switch (phy_data & MII_AT001_PSSR_SPEED) {
+	case MII_AT001_PSSR_1000MBS:
+		*speed = SPEED_1000;
+		break;
+	case MII_AT001_PSSR_100MBS:
+		*speed = SPEED_100;
+		break;
+	case MII_AT001_PSSR_10MBS:
+		*speed = SPEED_10;
+		break;
+	default:
+		printk(KERN_DEBUG "%s: error getting speed\n", 
+			atl1_driver_name);
+		return ATL1_ERR_PHY_SPEED;
+		break;
+	}
+	if (phy_data & MII_AT001_PSSR_DPLX)
+		*duplex = FULL_DUPLEX;
+	else
+		*duplex = HALF_DUPLEX;
+
+	return ATL1_SUCCESS;
+}
+
+void atl1_set_mac_addr(struct atl1_hw *hw)
+{
+	u32 value;
+	/*
+	 * 00-0B-6A-F6-00-DC
+	 * 0:  6AF600DC   1: 000B
+	 * low dword
+	 */
+	value = (((u32) hw->mac_addr[2]) << 24) |
+	    (((u32) hw->mac_addr[3]) << 16) |
+	    (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5]));
+	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+	/* high dword */
+	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+	iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
+}
diff --git a/drivers/net/atl1/atl1_hw.h b/drivers/net/atl1/atl1_hw.h
new file mode 100644
index 0000000..100c09c
--- /dev/null
+++ b/drivers/net/atl1/atl1_hw.h
@@ -0,0 +1,951 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * 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.
+ *
+ * There are a lot of defines in here that are unused and/or have cryptic
+ * names.  Please leave them alone, as they're the closest thing we have
+ * to a spec from Attansic at present. *ahem* -- CHS
+ */
+
+#ifndef _ATL1_HW_H_
+#define _ATL1_HW_H_
+
+#include <linux/types.h>
+#include <linux/mii.h>
+
+struct atl1_adapter;
+struct atl1_hw;
+
+/* function prototypes needed by multiple files */
+s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw);
+s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data);
+s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex);
+s32 atl1_read_mac_addr(struct atl1_hw *hw);
+s32 atl1_init_hw(struct atl1_hw *hw);
+s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex);
+s32 atl1_set_speed_and_duplex(struct atl1_hw *hw, u16 speed, u16 duplex);
+u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
+void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
+s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
+void atl1_set_mac_addr(struct atl1_hw *hw);
+s32 atl1_phy_enter_power_saving(struct atl1_hw *hw);
+s32 atl1_reset_hw(struct atl1_hw *hw);
+void atl1_check_options(struct atl1_adapter *adapter);
+
+/* register definitions */
+#define REG_PCIE_CAP_LIST			0x58
+
+#define REG_VPD_CAP				0x6C
+#define VPD_CAP_ID_MASK				0xff
+#define VPD_CAP_ID_SHIFT			0
+#define VPD_CAP_NEXT_PTR_MASK			0xFF
+#define VPD_CAP_NEXT_PTR_SHIFT			8
+#define VPD_CAP_VPD_ADDR_MASK			0x7FFF
+#define VPD_CAP_VPD_ADDR_SHIFT			16
+#define VPD_CAP_VPD_FLAG			0x80000000
+
+#define REG_VPD_DATA				0x70
+
+#define REG_SPI_FLASH_CTRL			0x200
+#define SPI_FLASH_CTRL_STS_NON_RDY		0x1
+#define SPI_FLASH_CTRL_STS_WEN			0x2
+#define SPI_FLASH_CTRL_STS_WPEN			0x80
+#define SPI_FLASH_CTRL_DEV_STS_MASK		0xFF
+#define SPI_FLASH_CTRL_DEV_STS_SHIFT		0
+#define SPI_FLASH_CTRL_INS_MASK			0x7
+#define SPI_FLASH_CTRL_INS_SHIFT		8
+#define SPI_FLASH_CTRL_START			0x800
+#define SPI_FLASH_CTRL_EN_VPD			0x2000
+#define SPI_FLASH_CTRL_LDSTART			0x8000
+#define SPI_FLASH_CTRL_CS_HI_MASK		0x3
+#define SPI_FLASH_CTRL_CS_HI_SHIFT		16
+#define SPI_FLASH_CTRL_CS_HOLD_MASK		0x3
+#define SPI_FLASH_CTRL_CS_HOLD_SHIFT		18
+#define SPI_FLASH_CTRL_CLK_LO_MASK		0x3
+#define SPI_FLASH_CTRL_CLK_LO_SHIFT		20
+#define SPI_FLASH_CTRL_CLK_HI_MASK		0x3
+#define SPI_FLASH_CTRL_CLK_HI_SHIFT		22
+#define SPI_FLASH_CTRL_CS_SETUP_MASK		0x3
+#define SPI_FLASH_CTRL_CS_SETUP_SHIFT		24
+#define SPI_FLASH_CTRL_EROM_PGSZ_MASK		0x3
+#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT		26
+#define SPI_FLASH_CTRL_WAIT_READY		0x10000000
+
+#define REG_SPI_ADDR				0x204
+
+#define REG_SPI_DATA				0x208
+
+#define REG_SPI_FLASH_CONFIG			0x20C
+#define SPI_FLASH_CONFIG_LD_ADDR_MASK		0xFFFFFF
+#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT		0
+#define SPI_FLASH_CONFIG_VPD_ADDR_MASK		0x3
+#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT		24
+#define SPI_FLASH_CONFIG_LD_EXIST		0x4000000
+
+#define REG_SPI_FLASH_OP_PROGRAM		0x210
+#define REG_SPI_FLASH_OP_SC_ERASE		0x211
+#define REG_SPI_FLASH_OP_CHIP_ERASE		0x212
+#define REG_SPI_FLASH_OP_RDID			0x213
+#define REG_SPI_FLASH_OP_WREN			0x214
+#define REG_SPI_FLASH_OP_RDSR			0x215
+#define REG_SPI_FLASH_OP_WRSR			0x216
+#define REG_SPI_FLASH_OP_READ			0x217
+
+#define REG_TWSI_CTRL				0x218
+#define TWSI_CTRL_LD_OFFSET_MASK		0xFF
+#define TWSI_CTRL_LD_OFFSET_SHIFT		0
+#define TWSI_CTRL_LD_SLV_ADDR_MASK		0x7
+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT		8
+#define TWSI_CTRL_SW_LDSTART			0x800
+#define TWSI_CTRL_HW_LDSTART			0x1000
+#define TWSI_CTRL_SMB_SLV_ADDR_MASK		0x7F
+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT		15
+#define TWSI_CTRL_LD_EXIST			0x400000
+#define TWSI_CTRL_READ_FREQ_SEL_MASK		0x3
+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT		23
+#define TWSI_CTRL_FREQ_SEL_100K			0
+#define TWSI_CTRL_FREQ_SEL_200K			1
+#define TWSI_CTRL_FREQ_SEL_300K			2
+#define TWSI_CTRL_FREQ_SEL_400K			3
+#define TWSI_CTRL_SMB_SLV_ADDR
+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK		0x3
+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT		24
+
+#define REG_PCIE_DEV_MISC_CTRL			0x21C
+#define PCIE_DEV_MISC_CTRL_EXT_PIPE		0x2
+#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS		0x1
+#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST		0x4
+#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN	0x8
+#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN	0x10
+
+/* Selene Master Control Register */
+#define REG_MASTER_CTRL				0x1400
+#define MASTER_CTRL_SOFT_RST			0x1
+#define MASTER_CTRL_MTIMER_EN			0x2
+#define MASTER_CTRL_ITIMER_EN			0x4
+#define MASTER_CTRL_MANUAL_INT			0x8
+#define MASTER_CTRL_REV_NUM_SHIFT		16
+#define MASTER_CTRL_REV_NUM_MASK		0xff
+#define MASTER_CTRL_DEV_ID_SHIFT		24
+#define MASTER_CTRL_DEV_ID_MASK			0xff
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT			0x1404
+
+/* IRQ ModeratorTimer Initial Value Register */
+#define REG_IRQ_MODU_TIMER_INIT			0x1408
+
+#define REG_GPHY_ENABLE				0x140C
+
+/* IRQ Anti-Lost Timer Initial Value Register */
+#define REG_CMBDISDMA_TIMER			0x140E
+
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS				0x1410
+#define IDLE_STATUS_RXMAC			1
+#define IDLE_STATUS_TXMAC			2
+#define IDLE_STATUS_RXQ				4
+#define IDLE_STATUS_TXQ				8
+#define IDLE_STATUS_DMAR			0x10
+#define IDLE_STATUS_DMAW			0x20
+#define IDLE_STATUS_SMB				0x40
+#define IDLE_STATUS_CMB				0x80
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL				0x1414
+#define MDIO_DATA_MASK				0xffff
+#define MDIO_DATA_SHIFT				0
+#define MDIO_REG_ADDR_MASK			0x1f
+#define MDIO_REG_ADDR_SHIFT			16
+#define MDIO_RW					0x200000
+#define MDIO_SUP_PREAMBLE			0x400000
+#define MDIO_START				0x800000
+#define MDIO_CLK_SEL_SHIFT			24
+#define MDIO_CLK_25_4				0
+#define MDIO_CLK_25_6				2
+#define MDIO_CLK_25_8				3
+#define MDIO_CLK_25_10				4
+#define MDIO_CLK_25_14				5
+#define MDIO_CLK_25_20				6
+#define MDIO_CLK_25_28				7
+#define MDIO_BUSY				0x8000000
+#define MDIO_WAIT_TIMES				30
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS				0x1418
+
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL				0x141c
+#define BIST0_NOW				0x1
+#define BIST0_SRAM_FAIL				0x2
+#define BIST0_FUSE_FLAG				0x4
+#define REG_BIST1_CTRL				0x1420
+#define BIST1_NOW				0x1
+#define BIST1_SRAM_FAIL				0x2
+#define BIST1_FUSE_FLAG				0x4
+
+/* MAC Control Register */
+#define REG_MAC_CTRL				0x1480
+#define MAC_CTRL_TX_EN				1
+#define MAC_CTRL_RX_EN				2
+#define MAC_CTRL_TX_FLOW			4
+#define MAC_CTRL_RX_FLOW			8
+#define MAC_CTRL_LOOPBACK			0x10
+#define MAC_CTRL_DUPLX				0x20
+#define MAC_CTRL_ADD_CRC			0x40
+#define MAC_CTRL_PAD				0x80
+#define MAC_CTRL_LENCHK				0x100
+#define MAC_CTRL_HUGE_EN			0x200
+#define MAC_CTRL_PRMLEN_SHIFT			10
+#define MAC_CTRL_PRMLEN_MASK			0xf
+#define MAC_CTRL_RMV_VLAN			0x4000
+#define MAC_CTRL_PROMIS_EN			0x8000
+#define MAC_CTRL_TX_PAUSE			0x10000
+#define MAC_CTRL_SCNT				0x20000
+#define MAC_CTRL_SRST_TX			0x40000
+#define MAC_CTRL_TX_SIMURST			0x80000
+#define MAC_CTRL_SPEED_SHIFT			20
+#define MAC_CTRL_SPEED_MASK			0x300000
+#define MAC_CTRL_SPEED_1000			2
+#define MAC_CTRL_SPEED_10_100			1
+#define MAC_CTRL_DBG_TX_BKPRESURE		0x400000
+#define MAC_CTRL_TX_HUGE			0x800000
+#define MAC_CTRL_RX_CHKSUM_EN			0x1000000
+#define MAC_CTRL_MC_ALL_EN			0x2000000
+#define MAC_CTRL_BC_EN				0x4000000
+#define MAC_CTRL_DBG				0x8000000
+
+/* MAC IPG/IFG Control Register */
+#define REG_MAC_IPG_IFG				0x1484
+#define MAC_IPG_IFG_IPGT_SHIFT			0
+#define MAC_IPG_IFG_IPGT_MASK			0x7f
+#define MAC_IPG_IFG_MIFG_SHIFT			8
+#define MAC_IPG_IFG_MIFG_MASK			0xff
+#define MAC_IPG_IFG_IPGR1_SHIFT			16
+#define MAC_IPG_IFG_IPGR1_MASK			0x7f
+#define MAC_IPG_IFG_IPGR2_SHIFT			24
+#define MAC_IPG_IFG_IPGR2_MASK			0x7f
+
+/* MAC STATION ADDRESS */
+#define REG_MAC_STA_ADDR			0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE			0x1490
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL			0x1498
+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT		0
+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK		0x3ff
+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT		12
+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK		0xf
+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN		0x10000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C		0x20000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P		0x40000
+#define MAC_HALF_DUPLX_CTRL_ABEBE		0x80000
+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT		20
+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK		0xf
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT	24
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK		0xf
+
+/* Maximum Frame Length Control Register */
+#define REG_MTU					0x149c
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL				0x14a0
+#define WOL_PATTERN_EN				0x00000001
+#define WOL_PATTERN_PME_EN			0x00000002
+#define WOL_MAGIC_EN				0x00000004
+#define WOL_MAGIC_PME_EN			0x00000008
+#define WOL_LINK_CHG_EN				0x00000010
+#define WOL_LINK_CHG_PME_EN			0x00000020
+#define WOL_PATTERN_ST				0x00000100
+#define WOL_MAGIC_ST				0x00000200
+#define WOL_LINKCHG_ST				0x00000400
+#define WOL_CLK_SWITCH_EN			0x00008000
+#define WOL_PT0_EN				0x00010000
+#define WOL_PT1_EN				0x00020000
+#define WOL_PT2_EN				0x00040000
+#define WOL_PT3_EN				0x00080000
+#define WOL_PT4_EN				0x00100000
+#define WOL_PT5_EN				0x00200000
+#define WOL_PT6_EN				0x00400000
+
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN			0x14a4
+#define WOL_PT_LEN_MASK				0x7f
+#define WOL_PT0_LEN_SHIFT			0
+#define WOL_PT1_LEN_SHIFT			8
+#define WOL_PT2_LEN_SHIFT			16
+#define WOL_PT3_LEN_SHIFT			24
+#define WOL_PT4_LEN_SHIFT			0
+#define WOL_PT5_LEN_SHIFT			8
+#define WOL_PT6_LEN_SHIFT			16
+
+/* Internal SRAM Partition Register */
+#define REG_SRAM_RFD_ADDR			0x1500
+#define REG_SRAM_RFD_LEN			(REG_SRAM_RFD_ADDR+ 4)
+#define REG_SRAM_RRD_ADDR			(REG_SRAM_RFD_ADDR+ 8)
+#define REG_SRAM_RRD_LEN			(REG_SRAM_RFD_ADDR+12)
+#define REG_SRAM_TPD_ADDR			(REG_SRAM_RFD_ADDR+16)
+#define REG_SRAM_TPD_LEN			(REG_SRAM_RFD_ADDR+20)
+#define REG_SRAM_TRD_ADDR			(REG_SRAM_RFD_ADDR+24)
+#define REG_SRAM_TRD_LEN			(REG_SRAM_RFD_ADDR+28)
+#define REG_SRAM_RXF_ADDR			(REG_SRAM_RFD_ADDR+32)
+#define REG_SRAM_RXF_LEN			(REG_SRAM_RFD_ADDR+36)
+#define REG_SRAM_TXF_ADDR			(REG_SRAM_RFD_ADDR+40)
+#define REG_SRAM_TXF_LEN			(REG_SRAM_RFD_ADDR+44)
+#define REG_SRAM_TCPH_PATH_ADDR			(REG_SRAM_RFD_ADDR+48)
+#define SRAM_TCPH_ADDR_MASK			0x0fff
+#define SRAM_TCPH_ADDR_SHIFT			0
+#define SRAM_PATH_ADDR_MASK			0x0fff
+#define SRAM_PATH_ADDR_SHIFT			16
+
+/* Load Ptr Register */
+#define REG_LOAD_PTR				(REG_SRAM_RFD_ADDR+52)
+
+/* Descriptor Control register */
+#define REG_DESC_BASE_ADDR_HI			0x1540
+#define REG_DESC_RFD_ADDR_LO			(REG_DESC_BASE_ADDR_HI+4)
+#define REG_DESC_RRD_ADDR_LO			(REG_DESC_BASE_ADDR_HI+8)
+#define REG_DESC_TPD_ADDR_LO			(REG_DESC_BASE_ADDR_HI+12)
+#define REG_DESC_CMB_ADDR_LO			(REG_DESC_BASE_ADDR_HI+16)
+#define REG_DESC_SMB_ADDR_LO			(REG_DESC_BASE_ADDR_HI+20)
+#define REG_DESC_RFD_RRD_RING_SIZE		(REG_DESC_BASE_ADDR_HI+24)
+#define DESC_RFD_RING_SIZE_MASK			0x7ff
+#define DESC_RFD_RING_SIZE_SHIFT		0
+#define DESC_RRD_RING_SIZE_MASK			0x7ff
+#define DESC_RRD_RING_SIZE_SHIFT		16
+#define REG_DESC_TPD_RING_SIZE			(REG_DESC_BASE_ADDR_HI+28)
+#define DESC_TPD_RING_SIZE_MASK			0x3ff
+#define DESC_TPD_RING_SIZE_SHIFT		0
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL				0x1580
+#define TXQ_CTRL_TPD_BURST_NUM_SHIFT		0
+#define TXQ_CTRL_TPD_BURST_NUM_MASK		0x1f
+#define TXQ_CTRL_EN				0x20
+#define TXQ_CTRL_ENH_MODE			0x40
+#define TXQ_CTRL_TPD_FETCH_TH_SHIFT		8
+#define TXQ_CTRL_TPD_FETCH_TH_MASK		0x3f
+#define TXQ_CTRL_TXF_BURST_NUM_SHIFT		16
+#define TXQ_CTRL_TXF_BURST_NUM_MASK		0xffff
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_JUMBO_TASK_TH_TPD_IPG		0x1584
+#define TX_JUMBO_TASK_TH_MASK			0x7ff
+#define TX_JUMBO_TASK_TH_SHIFT			0
+#define TX_TPD_MIN_IPG_MASK			0x1f
+#define TX_TPD_MIN_IPG_SHIFT			16
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL				0x15a0
+#define RXQ_CTRL_RFD_BURST_NUM_SHIFT		0
+#define RXQ_CTRL_RFD_BURST_NUM_MASK		0xff
+#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT		8
+#define RXQ_CTRL_RRD_BURST_THRESH_MASK		0xff
+#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT		16
+#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK		0x1f
+#define RXQ_CTRL_CUT_THRU_EN			0x40000000
+#define RXQ_CTRL_EN				0x80000000
+
+/* Rx jumbo packet threshold and rrd  retirement timer */
+#define REG_RXQ_JMBOSZ_RRDTIM			(REG_RXQ_CTRL+ 4)
+#define RXQ_JMBOSZ_TH_MASK			0x7ff
+#define RXQ_JMBOSZ_TH_SHIFT			0
+#define RXQ_JMBO_LKAH_MASK			0xf
+#define RXQ_JMBO_LKAH_SHIFT			11
+#define RXQ_RRD_TIMER_MASK			0xffff
+#define RXQ_RRD_TIMER_SHIFT			16
+
+/* RFD flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH		(REG_RXQ_CTRL+ 8)
+#define RXQ_RXF_PAUSE_TH_HI_SHIFT		16
+#define RXQ_RXF_PAUSE_TH_HI_MASK		0xfff
+#define RXQ_RXF_PAUSE_TH_LO_SHIFT		0
+#define RXQ_RXF_PAUSE_TH_LO_MASK		0xfff
+
+/* RRD flow control register */
+#define REG_RXQ_RRD_PAUSE_THRESH		(REG_RXQ_CTRL+12)
+#define RXQ_RRD_PAUSE_TH_HI_SHIFT		0
+#define RXQ_RRD_PAUSE_TH_HI_MASK		0xfff
+#define RXQ_RRD_PAUSE_TH_LO_SHIFT		16
+#define RXQ_RRD_PAUSE_TH_LO_MASK		0xfff
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL				0x15c0
+#define DMA_CTRL_DMAR_IN_ORDER			0x1
+#define DMA_CTRL_DMAR_ENH_ORDER			0x2
+#define DMA_CTRL_DMAR_OUT_ORDER			0x4
+#define DMA_CTRL_RCB_VALUE			0x8
+#define DMA_CTRL_DMAR_BURST_LEN_SHIFT		4
+#define DMA_CTRL_DMAR_BURST_LEN_MASK		7
+#define DMA_CTRL_DMAW_BURST_LEN_SHIFT		7
+#define DMA_CTRL_DMAW_BURST_LEN_MASK		7
+#define DMA_CTRL_DMAR_EN				0x400
+#define DMA_CTRL_DMAW_EN				0x800
+
+/* CMB/SMB Control Register */
+#define REG_CSMB_CTRL				0x15d0
+#define CSMB_CTRL_CMB_NOW			1
+#define CSMB_CTRL_SMB_NOW			2
+#define CSMB_CTRL_CMB_EN			4
+#define CSMB_CTRL_SMB_EN			8
+
+/* CMB DMA Write Threshold Register */
+#define REG_CMB_WRITE_TH			(REG_CSMB_CTRL+ 4)
+#define CMB_RRD_TH_SHIFT			0
+#define CMB_RRD_TH_MASK				0x7ff
+#define CMB_TPD_TH_SHIFT			16
+#define CMB_TPD_TH_MASK				0x7ff
+
+/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
+#define REG_CMB_WRITE_TIMER			(REG_CSMB_CTRL+ 8)
+#define CMB_RX_TM_SHIFT				0
+#define CMB_RX_TM_MASK				0xffff
+#define CMB_TX_TM_SHIFT				16
+#define CMB_TX_TM_MASK				0xffff
+
+/* Number of packet received since last CMB write */
+#define REG_CMB_RX_PKT_CNT			(REG_CSMB_CTRL+12)
+
+/* Number of packet transmitted since last CMB write */
+#define REG_CMB_TX_PKT_CNT			(REG_CSMB_CTRL+16)
+
+/* SMB auto DMA timer register */
+#define REG_SMB_TIMER				(REG_CSMB_CTRL+20)
+
+/* Mailbox Register */
+#define REG_MAILBOX				0x15f0
+#define MB_RFD_PROD_INDX_SHIFT			0
+#define MB_RFD_PROD_INDX_MASK			0x7ff
+#define MB_RRD_CONS_INDX_SHIFT			11
+#define MB_RRD_CONS_INDX_MASK			0x7ff
+#define MB_TPD_PROD_INDX_SHIFT			22
+#define MB_TPD_PROD_INDX_MASK			0x3ff
+
+/* Interrupt Status Register */
+#define REG_ISR					0x1600
+#define ISR_SMB					1
+#define ISR_TIMER				2
+#define ISR_MANUAL				4
+#define ISR_RXF_OV				8
+#define ISR_RFD_UNRUN				0x10
+#define ISR_RRD_OV				0x20
+#define ISR_TXF_UNRUN				0x40
+#define ISR_LINK				0x80
+#define ISR_HOST_RFD_UNRUN			0x100
+#define ISR_HOST_RRD_OV				0x200
+#define ISR_DMAR_TO_RST				0x400
+#define ISR_DMAW_TO_RST				0x800
+#define ISR_GPHY				0x1000
+#define ISR_RX_PKT				0x10000
+#define ISR_TX_PKT				0x20000
+#define ISR_TX_DMA				0x40000
+#define ISR_RX_DMA				0x80000
+#define ISR_CMB_RX				0x100000
+#define ISR_CMB_TX				0x200000
+#define ISR_MAC_RX				0x400000
+#define ISR_MAC_TX				0x800000
+#define ISR_UR_DETECTED				0x1000000
+#define ISR_FERR_DETECTED			0x2000000
+#define ISR_NFERR_DETECTED			0x4000000
+#define ISR_CERR_DETECTED			0x8000000
+#define ISR_PHY_LINKDOWN			0x10000000
+#define ISR_DIS_SMB				0x20000000
+#define ISR_DIS_DMA				0x40000000
+#define ISR_DIS_INT				0x80000000
+
+/* Interrupt Mask Register */
+#define REG_IMR					0x1604
+
+/* Normal Interrupt mask  */
+#define IMR_NORMAL_MASK	(\
+	ISR_SMB		|\
+	ISR_GPHY	|\
+	ISR_PHY_LINKDOWN|\
+	ISR_DMAR_TO_RST	|\
+	ISR_DMAW_TO_RST	|\
+	ISR_CMB_TX	|\
+	ISR_CMB_RX	)
+
+/* Debug Interrupt Mask  (enable all interrupt) */
+#define IMR_DEBUG_MASK	(\
+	ISR_SMB		|\
+	ISR_TIMER	|\
+	ISR_MANUAL	|\
+	ISR_RXF_OV	|\
+	ISR_RFD_UNRUN	|\
+	ISR_RRD_OV	|\
+	ISR_TXF_UNRUN	|\
+	ISR_LINK	|\
+	ISR_CMB_TX	|\
+	ISR_CMB_RX	|\
+	ISR_RX_PKT	|\
+	ISR_TX_PKT	|\
+	ISR_MAC_RX	|\
+	ISR_MAC_TX	)
+
+/* Interrupt Status Register */
+#define REG_RFD_RRD_IDX				0x1800
+#define REG_TPD_IDX				0x1804
+
+/*  MII definition */
+/* PHY Common Register */
+#define MII_AT001_CR					0x09
+#define MII_AT001_SR					0x0A
+#define MII_AT001_ESR					0x0F
+#define MII_AT001_PSCR					0x10
+#define MII_AT001_PSSR					0x11
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB				0x0040	/* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE				0x0080	/* Collision test enable */
+#define MII_CR_FULL_DUPLEX				0x0100	/* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG				0x0200	/* Restart auto negotiation */
+#define MII_CR_ISOLATE					0x0400	/* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN				0x0800	/* Power down */
+#define MII_CR_AUTO_NEG_EN				0x1000	/* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB				0x2000	/* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK					0x4000	/* 0 = normal, 1 = loopback */
+#define MII_CR_RESET					0x8000	/* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_MASK				0x2040
+#define MII_CR_SPEED_1000				0x0040
+#define MII_CR_SPEED_100				0x2000
+#define MII_CR_SPEED_10					0x0000
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS				0x0001	/* Extended register capabilities */
+#define MII_SR_JABBER_DETECT				0x0002	/* Jabber Detected */
+#define MII_SR_LINK_STATUS				0x0004	/* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS				0x0008	/* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT				0x0010	/* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE				0x0020	/* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS			0x0040	/* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS				0x0100	/* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS				0x0200	/* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS				0x0400	/* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS				0x0800	/* 10T   Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS				0x1000	/* 10T   Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS				0x2000	/* 100X  Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS				0x4000	/* 100X  Full Duplex Capable */
+#define MII_SR_100T4_CAPS				0x8000	/* 100T4 Capable */
+
+/* Link partner ability register. */
+#define MII_LPA_SLCT					0x001f	/* Same as advertise selector  */
+#define MII_LPA_10HALF					0x0020	/* Can do 10mbps half-duplex   */
+#define MII_LPA_10FULL					0x0040	/* Can do 10mbps full-duplex   */
+#define MII_LPA_100HALF					0x0080	/* Can do 100mbps half-duplex  */
+#define MII_LPA_100FULL					0x0100	/* Can do 100mbps full-duplex  */
+#define MII_LPA_100BASE4				0x0200	/* 100BASE-T4  */
+#define MII_LPA_PAUSE					0x0400	/* PAUSE */
+#define MII_LPA_ASYPAUSE				0x0800	/* Asymmetrical PAUSE */
+#define MII_LPA_RFAULT					0x2000	/* Link partner faulted        */
+#define MII_LPA_LPACK					0x4000	/* Link partner acked us       */
+#define MII_LPA_NPAGE					0x8000	/* Next page bit               */
+
+/* Autoneg Advertisement Register */
+#define MII_AR_SELECTOR_FIELD				0x0001	/* indicates IEEE 802.3 CSMA/CD */
+#define MII_AR_10T_HD_CAPS				0x0020	/* 10T   Half Duplex Capable */
+#define MII_AR_10T_FD_CAPS				0x0040	/* 10T   Full Duplex Capable */
+#define MII_AR_100TX_HD_CAPS				0x0080	/* 100TX Half Duplex Capable */
+#define MII_AR_100TX_FD_CAPS				0x0100	/* 100TX Full Duplex Capable */
+#define MII_AR_100T4_CAPS				0x0200	/* 100T4 Capable */
+#define MII_AR_PAUSE					0x0400	/* Pause operation desired */
+#define MII_AR_ASM_DIR					0x0800	/* Asymmetric Pause Direction bit */
+#define MII_AR_REMOTE_FAULT				0x2000	/* Remote Fault detected */
+#define MII_AR_NEXT_PAGE				0x8000	/* Next Page ability supported */
+#define MII_AR_SPEED_MASK				0x01E0
+#define MII_AR_DEFAULT_CAP_MASK				0x0DE0
+
+/* 1000BASE-T Control Register */
+#define MII_AT001_CR_1000T_HD_CAPS			0x0100	/* Advertise 1000T HD capability */
+#define MII_AT001_CR_1000T_FD_CAPS			0x0200	/* Advertise 1000T FD capability  */
+#define MII_AT001_CR_1000T_REPEATER_DTE			0x0400	/* 1=Repeater/switch device port, 0=DTE device */
+#define MII_AT001_CR_1000T_MS_VALUE			0x0800	/* 1=Configure PHY as Master, 0=Configure PHY as Slave */
+#define MII_AT001_CR_1000T_MS_ENABLE			0x1000	/* 1=Master/Slave manual config value, 0=Automatic Master/Slave config */
+#define MII_AT001_CR_1000T_TEST_MODE_NORMAL		0x0000	/* Normal Operation */
+#define MII_AT001_CR_1000T_TEST_MODE_1			0x2000	/* Transmit Waveform test */
+#define MII_AT001_CR_1000T_TEST_MODE_2			0x4000	/* Master Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_3			0x6000	/* Slave Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_4			0x8000	/* Transmitter Distortion test */
+#define MII_AT001_CR_1000T_SPEED_MASK			0x0300
+#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK		0x0300
+
+/* 1000BASE-T Status Register */
+#define MII_AT001_SR_1000T_LP_HD_CAPS			0x0400	/* LP is 1000T HD capable */
+#define MII_AT001_SR_1000T_LP_FD_CAPS			0x0800	/* LP is 1000T FD capable */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS		0x1000	/* Remote receiver OK */
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS		0x2000	/* Local receiver OK */
+#define MII_AT001_SR_1000T_MS_CONFIG_RES		0x4000	/* 1=Local TX is Master, 0=Slave */
+#define MII_AT001_SR_1000T_MS_CONFIG_FAULT		0x8000	/* Master/Slave config fault */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT	12
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT	13
+
+/* Extended Status Register */
+#define MII_AT001_ESR_1000T_HD_CAPS			0x1000	/* 1000T HD capable */
+#define MII_AT001_ESR_1000T_FD_CAPS			0x2000	/* 1000T FD capable */
+#define MII_AT001_ESR_1000X_HD_CAPS			0x4000	/* 1000X HD capable */
+#define MII_AT001_ESR_1000X_FD_CAPS			0x8000	/* 1000X FD capable */
+
+/* AT001 PHY Specific Control Register */
+#define MII_AT001_PSCR_JABBER_DISABLE			0x0001	/* 1=Jabber Function disabled */
+#define MII_AT001_PSCR_POLARITY_REVERSAL		0x0002	/* 1=Polarity Reversal enabled */
+#define MII_AT001_PSCR_SQE_TEST				0x0004	/* 1=SQE Test enabled */
+#define MII_AT001_PSCR_MAC_POWERDOWN			0x0008
+#define MII_AT001_PSCR_CLK125_DISABLE			0x0010	/* 1=CLK125 low, 0=CLK125 toggling */
+#define MII_AT001_PSCR_MDI_MANUAL_MODE			0x0000	/* MDI Crossover Mode bits 6:5, Manual MDI configuration */
+#define MII_AT001_PSCR_MDIX_MANUAL_MODE			0x0020	/* Manual MDIX configuration */
+#define MII_AT001_PSCR_AUTO_X_1000T			0x0040	/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
+#define MII_AT001_PSCR_AUTO_X_MODE			0x0060	/* Auto crossover enabled all speeds. */
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE		0x0080	/* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T RX Threshold), 0=Normal 10BASE-T RX Threshold */
+#define MII_AT001_PSCR_MII_5BIT_ENABLE			0x0100	/* 1=5-Bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */
+#define MII_AT001_PSCR_SCRAMBLER_DISABLE		0x0200	/* 1=Scrambler disable */
+#define MII_AT001_PSCR_FORCE_LINK_GOOD			0x0400	/* 1=Force link good */
+#define MII_AT001_PSCR_ASSERT_CRS_ON_TX			0x0800	/* 1=Assert CRS on Transmit */
+#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT		1
+#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT		5
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT	7
+
+/* AT001 PHY Specific Status Register */
+#define MII_AT001_PSSR_SPD_DPLX_RESOLVED		0x0800	/* 1=Speed & Duplex resolved */
+#define MII_AT001_PSSR_DPLX				0x2000	/* 1=Duplex 0=Half Duplex */
+#define MII_AT001_PSSR_SPEED				0xC000	/* Speed, bits 14:15 */
+#define MII_AT001_PSSR_10MBS				0x0000	/* 00=10Mbs */
+#define MII_AT001_PSSR_100MBS				0x4000	/* 01=100Mbs */
+#define MII_AT001_PSSR_1000MBS				0x8000	/* 10=1000Mbs */
+
+/* PCI Command Register Bit Definitions */
+#define PCI_REG_COMMAND					0x04	/* PCI Command Register */
+#define CMD_IO_SPACE					0x0001
+#define CMD_MEMORY_SPACE				0x0002
+#define CMD_BUS_MASTER					0x0004
+
+/* Wake Up Filter Control */
+#define ATL1_WUFC_LNKC	0x00000001	/* Link Status Change Wakeup Enable */
+#define ATL1_WUFC_MAG	0x00000002	/* Magic Packet Wakeup Enable */
+#define ATL1_WUFC_EX	0x00000004	/* Directed Exact Wakeup Enable */
+#define ATL1_WUFC_MC	0x00000008	/* Multicast Wakeup Enable */
+#define ATL1_WUFC_BC	0x00000010	/* Broadcast Wakeup Enable */
+
+/* Error Codes */
+#define ATL1_SUCCESS			0
+#define ATL1_ERR_EEPROM			1
+#define ATL1_ERR_PHY			2
+#define ATL1_ERR_CONFIG			3
+#define ATL1_ERR_PARAM			4
+#define ATL1_ERR_MAC_TYPE		5
+#define ATL1_ERR_PHY_TYPE		6
+#define ATL1_ERR_PHY_SPEED		7
+#define ATL1_ERR_PHY_RES		8
+
+#define SPEED_0		0xffff
+#define SPEED_10	10
+#define SPEED_100	100
+#define SPEED_1000	1000
+#define HALF_DUPLEX	1
+#define FULL_DUPLEX	2
+
+#define MEDIA_TYPE_AUTO_SENSOR	0
+#define MEDIA_TYPE_1000M_FULL	1
+#define MEDIA_TYPE_100M_FULL	2
+#define MEDIA_TYPE_100M_HALF	3
+#define MEDIA_TYPE_10M_FULL	4
+#define MEDIA_TYPE_10M_HALF	5
+
+#define ADVERTISE_10_HALF		0x0001
+#define ADVERTISE_10_FULL		0x0002
+#define ADVERTISE_100_HALF		0x0004
+#define ADVERTISE_100_FULL		0x0008
+#define ADVERTISE_1000_HALF		0x0010
+#define ADVERTISE_1000_FULL		0x0020
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT	0x002F	/* Everything but 1000-Half */
+#define AUTONEG_ADVERTISE_10_100_ALL	0x000F	/* All 10/100 speeds */
+#define AUTONEG_ADVERTISE_10_ALL	0x0003	/* 10Mbps Full & Half speeds */
+
+/* The size (in bytes) of a ethernet packet */
+#define ENET_HEADER_SIZE		14
+#define MAXIMUM_ETHERNET_FRAME_SIZE	1518	/* with FCS */
+#define MINIMUM_ETHERNET_FRAME_SIZE	64	/* with FCS */
+#define ETHERNET_FCS_SIZE		4
+#define MAX_JUMBO_FRAME_SIZE		0x2800
+
+#define PHY_AUTO_NEG_TIME	45	/* 4.5 Seconds */
+#define PHY_FORCE_TIME		20	/* 2.0 Seconds */
+
+/* For checksumming , the sum of all words in the EEPROM should equal 0xBABA */
+#define EEPROM_SUM		0xBABA
+
+#define ATL1_EEDUMP_LEN		48
+
+/* Statistics counters collected by the MAC */
+struct stats_msg_block {
+	/* rx */
+	u32 rx_ok;		/* The number of good packet received. */
+	u32 rx_bcast;		/* The number of good broadcast packet received. */
+	u32 rx_mcast;		/* The number of good multicast packet received. */
+	u32 rx_pause;		/* The number of Pause packet received. */
+	u32 rx_ctrl;		/* The number of Control packet received other than Pause frame. */
+	u32 rx_fcs_err;		/* The number of packets with bad FCS. */
+	u32 rx_len_err;		/* The number of packets with mismatch of length field and actual size. */
+	u32 rx_byte_cnt;	/* The number of bytes of good packet received. FCS is NOT included. */
+	u32 rx_runt;		/* The number of packets received that are less than 64 byte long and with good FCS. */
+	u32 rx_frag;		/* The number of packets received that are less than 64 byte long and with bad FCS. */
+	u32 rx_sz_64;		/* The number of good and bad packets received that are 64 byte long. */
+	u32 rx_sz_65_127;	/* The number of good and bad packets received that are between 65 and 127-byte long. */
+	u32 rx_sz_128_255;	/* The number of good and bad packets received that are between 128 and 255-byte long. */
+	u32 rx_sz_256_511;	/* The number of good and bad packets received that are between 256 and 511-byte long. */
+	u32 rx_sz_512_1023;	/* The number of good and bad packets received that are between 512 and 1023-byte long. */
+	u32 rx_sz_1024_1518;	/* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+	u32 rx_sz_1519_max;	/* The number of good and bad packets received that are between 1519-byte and MTU. */
+	u32 rx_sz_ov;		/* The number of good and bad packets received that are more than MTU size šC truncated by Selene. */
+	u32 rx_rxf_ov;		/* The number of frame dropped due to occurrence of RX FIFO overflow. */
+	u32 rx_rrd_ov;		/* The number of frame dropped due to occurrence of RRD overflow. */
+	u32 rx_align_err;	/* Alignment Error */
+	u32 rx_bcast_byte_cnt;	/* The byte count of broadcast packet received, excluding FCS. */
+	u32 rx_mcast_byte_cnt;	/* The byte count of multicast packet received, excluding FCS. */
+	u32 rx_err_addr;	/* The number of packets dropped due to address filtering. */
+
+	/* tx */
+	u32 tx_ok;		/* The number of good packet transmitted. */
+	u32 tx_bcast;		/* The number of good broadcast packet transmitted. */
+	u32 tx_mcast;		/* The number of good multicast packet transmitted. */
+	u32 tx_pause;		/* The number of Pause packet transmitted. */
+	u32 tx_exc_defer;	/* The number of packets transmitted with excessive deferral. */
+	u32 tx_ctrl;		/* The number of packets transmitted is a control frame, excluding Pause frame. */
+	u32 tx_defer;		/* The number of packets transmitted that is deferred. */
+	u32 tx_byte_cnt;	/* The number of bytes of data transmitted. FCS is NOT included. */
+	u32 tx_sz_64;		/* The number of good and bad packets transmitted that are 64 byte long. */
+	u32 tx_sz_65_127;	/* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+	u32 tx_sz_128_255;	/* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+	u32 tx_sz_256_511;	/* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+	u32 tx_sz_512_1023;	/* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+	u32 tx_sz_1024_1518;	/* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+	u32 tx_sz_1519_max;	/* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+	u32 tx_1_col;		/* The number of packets subsequently transmitted successfully with a single prior collision. */
+	u32 tx_2_col;		/* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+	u32 tx_late_col;	/* The number of packets transmitted with late collisions. */
+	u32 tx_abort_col;	/* The number of transmit packets aborted due to excessive collisions. */
+	u32 tx_underrun;	/* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+	u32 tx_rd_eop;		/* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+	u32 tx_len_err;		/* The number of transmit packets with length field does NOT match the actual frame size. */
+	u32 tx_trunc;		/* The number of transmit packets truncated due to size exceeding MTU. */
+	u32 tx_bcast_byte;	/* The byte count of broadcast packet transmitted, excluding FCS. */
+	u32 tx_mcast_byte;	/* The byte count of multicast packet transmitted, excluding FCS. */
+	u32 smb_updated;	/* 1: SMB Updated. This is used by software as the indication of the statistics update.
+				 * Software should clear this bit as soon as retrieving the statistics information. */
+};
+
+/* Coalescing Message Block */
+struct coals_msg_block {
+	u32 int_stats;		/* interrupt status */
+	u16 rrd_prod_idx;	/* TRD Producer Index. */
+	u16 rfd_cons_idx;	/* RFD Consumer Index. */
+	u16 update;		/* Selene sets this bit every time it DMA the CMB to host memory.
+				 * Software supposes to clear this bit when CMB information is processed. */
+	u16 tpd_cons_idx;	/* TPD Consumer Index. */
+};
+
+/* RRD descriptor */
+struct rx_return_desc {
+	u8 num_buf;		/* Number of RFD buffers used by the received packet */
+	u8 resved;
+	u16 buf_indx;		/* RFD Index of the first buffer */
+	union {
+		u32 valid;
+		struct {
+			u16 rx_chksum;
+			u16 pkt_size;
+		} xsum_sz;
+	} xsz;
+
+	u16 pkt_flg;		/* Packet flags */
+	u16 err_flg;		/* Error flags */
+	u16 resved2;
+	u16 vlan_tag;		/* VLAN TAG */
+};
+
+#define PACKET_FLAG_ETH_TYPE	0x0080
+#define PACKET_FLAG_VLAN_INS	0x0100
+#define PACKET_FLAG_ERR		0x0200
+#define PACKET_FLAG_IPV4	0x0400
+#define PACKET_FLAG_UDP		0x0800
+#define PACKET_FLAG_TCP		0x1000
+#define PACKET_FLAG_BCAST	0x2000
+#define PACKET_FLAG_MCAST	0x4000
+#define PACKET_FLAG_PAUSE	0x8000
+
+#define ERR_FLAG_CRC		0x0001
+#define ERR_FLAG_CODE		0x0002
+#define ERR_FLAG_DRIBBLE	0x0004
+#define ERR_FLAG_RUNT		0x0008
+#define ERR_FLAG_OV		0x0010
+#define ERR_FLAG_TRUNC		0x0020
+#define ERR_FLAG_IP_CHKSUM	0x0040
+#define ERR_FLAG_L4_CHKSUM	0x0080
+#define ERR_FLAG_LEN		0x0100
+#define ERR_FLAG_DES_ADDR	0x0200
+
+/* RFD descriptor */
+struct rx_free_desc {
+	__le64 buffer_addr;	/* Address of the descriptor's data buffer */
+	__le16 buf_len;		/* Size of the receive buffer in host memory, in byte */
+	u16 coalese;		/* Update consumer index to host after the reception of this frame */
+	/* __attribute__ ((packed)) is required */
+} __attribute__ ((packed));
+
+/* tsopu defines */
+#define TSO_PARAM_BUFLEN_MASK           0x3FFF
+#define TSO_PARAM_BUFLEN_SHIFT          0
+#define TSO_PARAM_DMAINT_MASK           0x0001
+#define TSO_PARAM_DMAINT_SHIFT          14
+#define TSO_PARAM_PKTNT_MASK            0x0001
+#define TSO_PARAM_PKTINT_SHIFT          15
+#define TSO_PARAM_VLANTAG_MASK          0xFFFF
+#define TSO_PARAM_VLAN_SHIFT            16
+
+/* tsopl defines */
+#define TSO_PARAM_EOP_MASK              0x0001
+#define TSO_PARAM_EOP_SHIFT             0
+#define TSO_PARAM_COALESCE_MASK         0x0001
+#define TSO_PARAM_COALESCE_SHIFT        1
+#define TSO_PARAM_INSVLAG_MASK          0x0001
+#define TSO_PARAM_INSVLAG_SHIFT         2
+#define TSO_PARAM_CUSTOMCKSUM_MASK      0x0001
+#define TSO_PARAM_CUSTOMCKSUM_SHIFT     3
+#define TSO_PARAM_SEGMENT_MASK          0x0001
+#define TSO_PARAM_SEGMENT_SHIFT         4
+#define TSO_PARAM_IPCKSUM_MASK          0x0001
+#define TSO_PARAM_IPCKSUM_SHIFT         5
+#define TSO_PARAM_TCPCKSUM_MASK         0x0001
+#define TSO_PARAM_TCPCKSUM_SHIFT        6
+#define TSO_PARAM_UDPCKSUM_MASK         0x0001
+#define TSO_PARAM_UDPCKSUM_SHIFT        7
+#define TSO_PARAM_VLANTAGGED_MASK       0x0001
+#define TSO_PARAM_VLANTAGGED_SHIFT      8
+#define TSO_PARAM_ETHTYPE_MASK          0x0001
+#define TSO_PARAM_ETHTYPE_SHIFT         9
+#define TSO_PARAM_IPHL_MASK             0x000F
+#define TSO_PARAM_IPHL_SHIFT            10
+#define TSO_PARAM_TCPHDRLEN_MASK        0x000F
+#define TSO_PARAM_TCPHDRLEN_SHIFT       14
+#define TSO_PARAM_HDRFLAG_MASK          0x0001
+#define TSO_PARAM_HDRFLAG_SHIFT         18
+#define TSO_PARAM_MSS_MASK              0x1FFF
+#define TSO_PARAM_MSS_SHIFT             19
+
+/* csumpu defines */
+#define CSUM_PARAM_BUFLEN_MASK          0x3FFF
+#define CSUM_PARAM_BUFLEN_SHIFT         0
+#define CSUM_PARAM_DMAINT_MASK          0x0001
+#define CSUM_PARAM_DMAINT_SHIFT         14
+#define CSUM_PARAM_PKTINT_MASK          0x0001
+#define CSUM_PARAM_PKTINT_SHIFT         15
+#define CSUM_PARAM_VALANTAG_MASK        0xFFFF
+#define CSUM_PARAM_VALAN_SHIFT          16
+
+/* csumpl defines*/
+#define CSUM_PARAM_EOP_MASK             0x0001
+#define CSUM_PARAM_EOP_SHIFT            0
+#define CSUM_PARAM_COALESCE_MASK        0x0001
+#define CSUM_PARAM_COALESCE_SHIFT       1
+#define CSUM_PARAM_INSVLAG_MASK         0x0001
+#define CSUM_PARAM_INSVLAG_SHIFT        2
+#define CSUM_PARAM_CUSTOMCKSUM_MASK     0x0001
+#define CSUM_PARAM_CUSTOMCKSUM_SHIFT    3
+#define CSUM_PARAM_SEGMENT_MASK         0x0001
+#define CSUM_PARAM_SEGMENT_SHIFT        4
+#define CSUM_PARAM_IPCKSUM_MASK         0x0001
+#define CSUM_PARAM_IPCKSUM_SHIFT        5
+#define CSUM_PARAM_TCPCKSUM_MASK        0x0001
+#define CSUM_PARAM_TCPCKSUM_SHIFT       6
+#define CSUM_PARAM_UDPCKSUM_MASK        0x0001
+#define CSUM_PARAM_UDPCKSUM_SHIFT       7
+#define CSUM_PARAM_VLANTAGGED_MASK      0x0001
+#define CSUM_PARAM_VLANTAGGED_SHIFT     8
+#define CSUM_PARAM_ETHTYPE_MASK         0x0001
+#define CSUM_PARAM_ETHTYPE_SHIFT        9
+#define CSUM_PARAM_IPHL_MASK            0x000F
+#define CSUM_PARAM_IPHL_SHIFT           10
+#define CSUM_PARAM_PLOADOFFSET_MASK     0x00FF
+#define CSUM_PARAM_PLOADOFFSET_SHIFT    16
+#define CSUM_PARAM_XSUMOFFSET_MASK      0x00FF
+#define CSUM_PARAM_XSUMOFFSET_SHIFT     24
+
+/* TPD descriptor */
+struct tso_param {
+        /* The order of these declarations is important -- don't change it */
+        u32 tsopu;      /* tso_param upper word */
+        u32 tsopl;      /* tso_param lower word */
+};
+
+struct csum_param {
+        /* The order of these declarations is important -- don't change it */
+        u32 csumpu;     /* csum_param upper word */
+        u32 csumpl;     /* csum_param lower word */
+};
+
+union tpd_descr {
+	u64 data;
+	struct csum_param csum;
+	struct tso_param tso;
+};
+
+struct tx_packet_desc {
+	__le64 buffer_addr;
+	union tpd_descr desc;
+};
+
+/* DMA Order Settings */
+enum atl1_dma_order {
+	atl1_dma_ord_in = 1,
+	atl1_dma_ord_enh = 2,
+	atl1_dma_ord_out = 4
+};
+
+enum atl1_dma_rcb {
+	atl1_rcb_64 = 0,
+	atl1_rcb_128 = 1
+};
+
+enum atl1_dma_req_block {
+	atl1_dma_req_128 = 0,
+	atl1_dma_req_256 = 1,
+	atl1_dma_req_512 = 2,
+	atl1_dam_req_1024 = 3,
+	atl1_dam_req_2048 = 4,
+	atl1_dma_req_4096 = 5
+};
+
+struct atl1_spi_flash_dev {
+	const char *manu_name;	/* manufacturer id */
+	/* op-code */
+	u8 cmd_wrsr;
+	u8 cmd_read;
+	u8 cmd_program;
+	u8 cmd_wren;
+	u8 cmd_wrdi;
+	u8 cmd_rdsr;
+	u8 cmd_rdid;
+	u8 cmd_sector_erase;
+	u8 cmd_chip_erase;
+};
+
+#endif	/* _ATL1_HW_H_ */
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
new file mode 100644
index 0000000..6567348
--- /dev/null
+++ b/drivers/net/atl1/atl1_main.c
@@ -0,0 +1,2467 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ *
+ * Contact Information:
+ * Xiong Huang <xiong_huang@attansic.com>
+ * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei,
+ * Xinzhu  302, TAIWAN, REPUBLIC OF CHINA
+ *
+ * Chris Snook <csnook@redhat.com>
+ * Jay Cliburn <jcliburn@gmail.com>
+ *
+ * This version is adapted from the Attansic reference driver for
+ * inclusion in the Linux kernel.  It is currently under heavy development.
+ * A very incomplete list of things that need to be dealt with:
+ *
+ * TODO:
+ * Fix TSO; tx performance is horrible with TSO enabled.
+ * Wake on LAN.
+ * Add more ethtool functions, including set ring parameters.
+ * Fix abstruse irq enable/disable condition described here:
+ *	http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
+ *
+ * NEEDS TESTING:
+ * VLAN
+ * multicast
+ * promiscuous mode
+ * interrupt coalescing
+ * SMP torture testing
+ */
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/irqreturn.h>
+#include <linux/workqueue.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
+#include <linux/irqflags.h>
+#include <linux/dma-mapping.h>
+#include <linux/net.h>
+#include <linux/pm.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <net/checksum.h>
+
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+
+#include "atl1.h"
+
+#define DRIVER_VERSION "2.0.7"
+
+char atl1_driver_name[] = "atl1";
+static const char atl1_driver_string[] = "Attansic L1 Ethernet Network Driver";
+static const char atl1_copyright[] = "Copyright(c) 2005-2006 Attansic Corporation.";
+char atl1_driver_version[] = DRIVER_VERSION;
+
+MODULE_AUTHOR
+    ("Attansic Corporation <xiong_huang@attansic.com>, Chris Snook <csnook@redhat.com>, Jay Cliburn <jcliburn@gmail.com>");
+MODULE_DESCRIPTION("Attansic 1000M Ethernet Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+
+/*
+ * atl1_pci_tbl - PCI Device ID Table
+ */
+static const struct pci_device_id atl1_pci_tbl[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
+	/* required last entry */
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
+
+/*
+ * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
+{
+	struct atl1_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+
+	/* PCI config space info */
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+
+	hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
+
+	adapter->wol = 0;
+	adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
+	adapter->ict = 50000;	/* 100ms */
+	adapter->link_speed = SPEED_0;	/* hardware init */
+	adapter->link_duplex = FULL_DUPLEX;
+
+	hw->phy_configured = false;
+	hw->preamble_len = 7;
+	hw->ipgt = 0x60;
+	hw->min_ifg = 0x50;
+	hw->ipgr1 = 0x40;
+	hw->ipgr2 = 0x60;
+	hw->max_retry = 0xf;
+	hw->lcol = 0x37;
+	hw->jam_ipg = 7;
+	hw->rfd_burst = 8;
+	hw->rrd_burst = 8;
+	hw->rfd_fetch_gap = 1;
+	hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
+	hw->rx_jumbo_lkah = 1;
+	hw->rrd_ret_timer = 16;
+	hw->tpd_burst = 4;
+	hw->tpd_fetch_th = 16;
+	hw->txf_burst = 0x100;
+	hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
+	hw->tpd_fetch_gap = 1;
+	hw->rcb_value = atl1_rcb_64;
+	hw->dma_ord = atl1_dma_ord_enh;
+	hw->dmar_block = atl1_dma_req_256;
+	hw->dmaw_block = atl1_dma_req_256;
+	hw->cmb_rrd = 4;
+	hw->cmb_tpd = 4;
+	hw->cmb_rx_timer = 1;	/* about 2us */
+	hw->cmb_tx_timer = 1;	/* about 2us */
+	hw->smb_timer = 100000;	/* about 200ms */
+
+	atomic_set(&adapter->irq_sem, 0);
+	spin_lock_init(&adapter->lock);
+	spin_lock_init(&adapter->mb_lock);
+
+	return 0;
+}
+
+/*
+ * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_ring_header *ring_header = &adapter->ring_header;
+	struct pci_dev *pdev = adapter->pdev;
+	int size;
+	u8 offset = 0;
+
+	size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
+	tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
+	if (unlikely(!tpd_ring->buffer_info)) {
+		printk(KERN_WARNING "%s: kzalloc failed , size = D%d\n",
+			atl1_driver_name, size);
+		goto err_nomem;
+	}
+	rfd_ring->buffer_info =
+	    (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
+
+	/* real ring DMA buffer */
+	ring_header->size = size = sizeof(struct tx_packet_desc) *
+					tpd_ring->count
+	    + sizeof(struct rx_free_desc) * rfd_ring->count
+	    + sizeof(struct rx_return_desc) * rrd_ring->count
+	    + sizeof(struct coals_msg_block)
+	    + sizeof(struct stats_msg_block)
+	    + 40;		/* "40: for 8 bytes align" huh? -- CHS */
+
+	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
+						&ring_header->dma);
+	if (unlikely(!ring_header->desc)) {
+		printk(KERN_WARNING
+			"%s: pci_alloc_consistent failed, size = D%d\n",
+			atl1_driver_name, size);
+		goto err_nomem;
+	}
+
+	memset(ring_header->desc, 0, ring_header->size);
+
+	/* init TPD ring */
+	tpd_ring->dma = ring_header->dma;
+	offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
+	tpd_ring->dma += offset;
+	tpd_ring->desc = (u8 *) ring_header->desc + offset;
+	tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
+	atomic_set(&tpd_ring->next_to_use, 0);
+	atomic_set(&tpd_ring->next_to_clean, 0);
+
+	/* init RFD ring */
+	rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
+	offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
+	rfd_ring->dma += offset;
+	rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
+	rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
+	rfd_ring->next_to_clean = 0;
+	/* rfd_ring->next_to_use = rfd_ring->count - 1; */
+	atomic_set(&rfd_ring->next_to_use, 0);
+
+	/* init RRD ring */
+	rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
+	offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
+	rrd_ring->dma += offset;
+	rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
+	rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
+	rrd_ring->next_to_use = 0;
+	atomic_set(&rrd_ring->next_to_clean, 0);
+
+	/* init CMB */
+	adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
+	offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
+	adapter->cmb.dma += offset;
+	adapter->cmb.cmb =
+	    (struct coals_msg_block *) ((u8 *) rrd_ring->desc +
+				   (rrd_ring->size + offset));
+
+	/* init SMB */
+	adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
+	offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
+	adapter->smb.dma += offset;
+	adapter->smb.smb = (struct stats_msg_block *)
+	    ((u8 *) adapter->cmb.cmb + (sizeof(struct coals_msg_block) + offset));
+
+	return ATL1_SUCCESS;
+
+err_nomem:
+	kfree(tpd_ring->buffer_info);
+	return -ENOMEM;
+}
+
+/*
+ * atl1_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static void atl1_irq_enable(struct atl1_adapter *adapter)
+{
+	if (likely(!atomic_dec_and_test(&adapter->irq_sem)))
+		iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
+}
+
+static void atl1_clear_phy_int(struct atl1_adapter *adapter)
+{
+	u16 phy_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	atl1_read_phy_reg(&adapter->hw, 19, &phy_data);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+static void atl1_inc_smb(struct atl1_adapter *adapter)
+{
+	struct stats_msg_block *smb = adapter->smb.smb;
+
+	/* Fill out the OS statistics structure */
+	adapter->soft_stats.rx_packets += smb->rx_ok;
+	adapter->soft_stats.tx_packets += smb->tx_ok;
+	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
+	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
+	adapter->soft_stats.multicast += smb->rx_mcast;
+	adapter->soft_stats.collisions += (smb->tx_1_col +
+					   smb->tx_2_col * 2 +
+					   smb->tx_late_col +
+					   smb->tx_abort_col *
+					   adapter->hw.max_retry);
+
+	/* Rx Errors */
+	adapter->soft_stats.rx_errors += (smb->rx_frag +
+					  smb->rx_fcs_err +
+					  smb->rx_len_err +
+					  smb->rx_sz_ov +
+					  smb->rx_rxf_ov +
+					  smb->rx_rrd_ov + smb->rx_align_err);
+	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
+	adapter->soft_stats.rx_length_errors += smb->rx_len_err;
+	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
+	adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
+	adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
+						 smb->rx_rxf_ov);
+
+	adapter->soft_stats.rx_pause += smb->rx_pause;
+	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
+	adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
+
+	/* Tx Errors */
+	adapter->soft_stats.tx_errors += (smb->tx_late_col +
+					  smb->tx_abort_col +
+					  smb->tx_underrun + smb->tx_trunc);
+	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
+	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
+	adapter->soft_stats.tx_window_errors += smb->tx_late_col;
+
+	adapter->soft_stats.excecol += smb->tx_abort_col;
+	adapter->soft_stats.deffer += smb->tx_defer;
+	adapter->soft_stats.scc += smb->tx_1_col;
+	adapter->soft_stats.mcc += smb->tx_2_col;
+	adapter->soft_stats.latecol += smb->tx_late_col;
+	adapter->soft_stats.tx_underun += smb->tx_underrun;
+	adapter->soft_stats.tx_trunc += smb->tx_trunc;
+	adapter->soft_stats.tx_pause += smb->tx_pause;
+
+	adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
+	adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
+	adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
+	adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
+	adapter->net_stats.multicast = adapter->soft_stats.multicast;
+	adapter->net_stats.collisions = adapter->soft_stats.collisions;
+	adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
+	adapter->net_stats.rx_over_errors =
+	    adapter->soft_stats.rx_missed_errors;
+	adapter->net_stats.rx_length_errors =
+	    adapter->soft_stats.rx_length_errors;
+	adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
+	adapter->net_stats.rx_frame_errors =
+	    adapter->soft_stats.rx_frame_errors;
+	adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
+	adapter->net_stats.rx_missed_errors =
+	    adapter->soft_stats.rx_missed_errors;
+	adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
+	adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
+	adapter->net_stats.tx_aborted_errors =
+	    adapter->soft_stats.tx_aborted_errors;
+	adapter->net_stats.tx_window_errors =
+	    adapter->soft_stats.tx_window_errors;
+	adapter->net_stats.tx_carrier_errors =
+	    adapter->soft_stats.tx_carrier_errors;
+}
+
+static void atl1_rx_checksum(struct atl1_adapter *adapter,
+					struct rx_return_desc *rrd,
+					struct sk_buff *skb)
+{
+	skb->ip_summed = CHECKSUM_NONE;
+
+	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
+					ERR_FLAG_CODE | ERR_FLAG_OV)) {
+			adapter->hw_csum_err++;
+			printk(KERN_DEBUG "%s: rx checksum error\n",
+				atl1_driver_name);
+			return;
+		}
+	}
+
+	/* not IPv4 */
+	if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
+		/* checksum is invalid, but it's not an IPv4 pkt, so ok */
+		return;
+
+	/* IPv4 packet */
+	if (likely(!(rrd->err_flg &
+		(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		adapter->hw_csum_good++;
+		return;
+	}
+
+	/* IPv4, but hardware thinks its checksum is wrong */
+	printk(KERN_DEBUG "%s: hw csum wrong pkt_flag:%x, err_flag:%x\n",
+		atl1_driver_name, rrd->pkt_flg, rrd->err_flg);
+	skb->ip_summed = CHECKSUM_COMPLETE;
+	skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
+	adapter->hw_csum_err++;
+	return;
+}
+
+/*
+ * atl1_alloc_rx_buffers - Replace used receive buffers
+ * @adapter: address of board private structure
+ */
+static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
+{
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct page *page;
+	unsigned long offset;
+	struct atl1_buffer *buffer_info, *next_info;
+	struct sk_buff *skb;
+	u16 num_alloc = 0;
+	u16 rfd_next_to_use, next_next;
+	struct rx_free_desc *rfd_desc;
+
+	next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
+	if (++next_next == rfd_ring->count)
+		next_next = 0;
+	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+	next_info = &rfd_ring->buffer_info[next_next];
+
+	while (!buffer_info->alloced && !next_info->alloced) {
+		if (buffer_info->skb) {
+			buffer_info->alloced = 1;
+			goto next;
+		}
+
+		rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
+
+		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+		if (unlikely(!skb)) {	/* Better luck next round */
+			adapter->net_stats.rx_dropped++;
+			break;
+		}
+
+		/*
+		 * Make buffer alignment 2 beyond a 16 byte boundary
+		 * this will result in a 16 byte aligned IP header after
+		 * the 14 byte MAC header is removed
+		 */
+		skb_reserve(skb, NET_IP_ALIGN);
+		skb->dev = netdev;
+
+		buffer_info->alloced = 1;
+		buffer_info->skb = skb;
+		buffer_info->length = (u16) adapter->rx_buffer_len;
+		page = virt_to_page(skb->data);
+		offset = (unsigned long)skb->data & ~PAGE_MASK;
+		buffer_info->dma = pci_map_page(pdev, page, offset,
+						adapter->rx_buffer_len,
+						PCI_DMA_FROMDEVICE);
+		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+		rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
+		rfd_desc->coalese = 0;
+
+next:
+		rfd_next_to_use = next_next;
+		if (unlikely(++next_next == rfd_ring->count))
+			next_next = 0;
+
+		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+		next_info = &rfd_ring->buffer_info[next_next];
+		num_alloc++;
+	}
+
+	if (num_alloc) {
+		/*
+		 * Force memory writes to complete before letting h/w
+		 * know there are new descriptors to fetch.  (Only
+		 * applicable for weak-ordered memory model archs,
+		 * such as IA-64).
+		 */
+		wmb();
+		atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
+	}
+	return num_alloc;
+}
+
+static void atl1_intr_rx(struct atl1_adapter *adapter)
+{
+	int i, count;
+	u16 length;
+	u16 rrd_next_to_clean;
+	u32 value;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_buffer *buffer_info;
+	struct rx_return_desc *rrd;
+	struct sk_buff *skb;
+
+	count = 0;
+
+	rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
+
+	while (1) {
+		rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
+		i = 1;
+		if (likely(rrd->xsz.valid)) {	/* packet valid */
+chk_rrd:
+			/* check rrd status */
+			if (likely(rrd->num_buf == 1))
+				goto rrd_ok;
+
+			/* rrd seems to be bad */
+			if (unlikely(i-- > 0)) {
+				/* rrd may not be DMAed completely */
+				printk(KERN_DEBUG
+					"%s: RRD may not be DMAed completely\n",
+					atl1_driver_name);
+				udelay(1);
+				goto chk_rrd;
+			}
+			/* bad rrd */
+			printk(KERN_DEBUG "%s: bad RRD\n", atl1_driver_name);
+			/* see if update RFD index */
+			if (rrd->num_buf > 1) {
+				u16 num_buf;
+				num_buf =
+				    (rrd->xsz.xsum_sz.pkt_size +
+				     adapter->rx_buffer_len -
+				     1) / adapter->rx_buffer_len;
+				if (rrd->num_buf == num_buf) {
+					/* clean alloc flag for bad rrd */
+					while (rfd_ring->next_to_clean !=
+					       (rrd->buf_indx + num_buf)) {
+						rfd_ring->buffer_info[rfd_ring->
+								      next_to_clean].alloced = 0;
+						if (++rfd_ring->next_to_clean ==
+						    rfd_ring->count) {
+							rfd_ring->
+							    next_to_clean = 0;
+						}
+					}
+				}
+			}
+
+			/* update rrd */
+			rrd->xsz.valid = 0;
+			if (++rrd_next_to_clean == rrd_ring->count)
+				rrd_next_to_clean = 0;
+			count++;
+			continue;
+		} else {	/* current rrd still not be updated */
+
+			break;
+		}
+rrd_ok:
+		/* clean alloc flag for bad rrd */
+		while (rfd_ring->next_to_clean != rrd->buf_indx) {
+			rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced =
+			    0;
+			if (++rfd_ring->next_to_clean == rfd_ring->count)
+				rfd_ring->next_to_clean = 0;
+		}
+
+		buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
+		if (++rfd_ring->next_to_clean == rfd_ring->count)
+			rfd_ring->next_to_clean = 0;
+
+		/* update rrd next to clean */
+		if (++rrd_next_to_clean == rrd_ring->count)
+			rrd_next_to_clean = 0;
+		count++;
+
+		if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+			if (!(rrd->err_flg &
+				(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
+				| ERR_FLAG_LEN))) {
+				/* packet error, don't need upstream */
+				buffer_info->alloced = 0;
+				rrd->xsz.valid = 0;
+				continue;
+			}
+		}
+
+		/* Good Receive */
+		pci_unmap_page(adapter->pdev, buffer_info->dma,
+			       buffer_info->length, PCI_DMA_FROMDEVICE);
+		skb = buffer_info->skb;
+		length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
+
+		skb_put(skb, length - ETHERNET_FCS_SIZE);
+
+		/* Receive Checksum Offload */
+		atl1_rx_checksum(adapter, rrd, skb);
+		skb->protocol = eth_type_trans(skb, adapter->netdev);
+
+		if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
+			u16 vlan_tag = (rrd->vlan_tag >> 4) |
+					((rrd->vlan_tag & 7) << 13) |
+					((rrd->vlan_tag & 8) << 9);
+			vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
+		} else
+			netif_rx(skb);
+
+		/* let protocol layer free skb */
+		buffer_info->skb = NULL;
+		buffer_info->alloced = 0;
+		rrd->xsz.valid = 0;
+
+		adapter->netdev->last_rx = jiffies;
+	}
+
+	atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
+
+	atl1_alloc_rx_buffers(adapter);
+
+	/* update mailbox ? */
+	if (count) {
+		u32 tpd_next_to_use;
+		u32 rfd_next_to_use;
+		u32 rrd_next_to_clean;
+
+		spin_lock(&adapter->mb_lock);
+
+		tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+		rfd_next_to_use =
+		    atomic_read(&adapter->rfd_ring.next_to_use);
+		rrd_next_to_clean =
+		    atomic_read(&adapter->rrd_ring.next_to_clean);
+		value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+			MB_RFD_PROD_INDX_SHIFT) |
+                        ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+			MB_RRD_CONS_INDX_SHIFT) |
+                        ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+			MB_TPD_PROD_INDX_SHIFT);
+		iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+		spin_unlock(&adapter->mb_lock);
+	}
+}
+
+static void atl1_intr_tx(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_buffer *buffer_info;
+	u16 sw_tpd_next_to_clean;
+	u16 cmb_tpd_next_to_clean;
+	u8 update = 0;
+
+	sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+	cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
+
+	while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
+		struct tx_packet_desc *tpd;
+		update = 1;
+		tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
+		buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
+		if (buffer_info->dma) {
+			pci_unmap_page(adapter->pdev, buffer_info->dma,
+				       buffer_info->length, PCI_DMA_TODEVICE);
+			buffer_info->dma = 0;
+		}
+
+		if (buffer_info->skb) {
+			dev_kfree_skb_irq(buffer_info->skb);
+			buffer_info->skb = NULL;
+		}
+		tpd->buffer_addr = 0;
+		tpd->desc.data = 0;
+
+		if (++sw_tpd_next_to_clean == tpd_ring->count)
+			sw_tpd_next_to_clean = 0;
+	}
+	atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
+
+	if (netif_queue_stopped(adapter->netdev)
+	    && netif_carrier_ok(adapter->netdev))
+		netif_wake_queue(adapter->netdev);
+}
+
+static void atl1_check_for_link(struct atl1_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	u16 phy_data = 0;
+
+	spin_lock(&adapter->lock);
+	adapter->phy_timer_pending = false;
+	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	spin_unlock(&adapter->lock);
+
+	/* notify upper layer link down ASAP */
+	if (!(phy_data & BMSR_LSTATUS)) {	/* Link Down */
+		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
+			printk(KERN_INFO "%s: %s link is down\n",
+			       atl1_driver_name, netdev->name);
+			adapter->link_speed = SPEED_0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+	}
+	schedule_work(&adapter->link_chg_task);
+}
+
+/*
+ * atl1_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+static irqreturn_t atl1_intr(int irq, void *data)
+{
+	/*struct atl1_adapter *adapter = ((struct net_device *)data)->priv;*/
+	struct atl1_adapter *adapter = netdev_priv(data);
+	u32 status;
+	u8 update_rx;
+	int max_ints = 10;
+
+	status = adapter->cmb.cmb->int_stats;
+	if (!status)
+		return IRQ_NONE;
+
+	update_rx = 0;
+
+	do {
+		/* clear CMB interrupt status at once */
+		adapter->cmb.cmb->int_stats = 0;
+
+		if (status & ISR_GPHY)	/* clear phy status */
+			atl1_clear_phy_int(adapter);
+
+		/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+		iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
+
+		/* check if SMB intr */
+		if (status & ISR_SMB)
+			atl1_inc_smb(adapter);
+
+		/* check if PCIE PHY Link down */
+		if (status & ISR_PHY_LINKDOWN) {
+			printk(KERN_DEBUG "%s: pcie phy link down %x\n",
+				atl1_driver_name, status);
+			if (netif_running(adapter->netdev)) {	/* reset MAC */
+				iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+				schedule_work(&adapter->pcie_dma_to_rst_task);
+				return IRQ_HANDLED;
+			}
+		}
+
+		/* check if DMA read/write error ? */
+		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+			printk(KERN_DEBUG
+				"%s: pcie DMA r/w error (status = 0x%x)\n",
+				atl1_driver_name, status);
+			iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+			schedule_work(&adapter->pcie_dma_to_rst_task);
+			return IRQ_HANDLED;
+		}
+
+		/* link event */
+		if (status & ISR_GPHY) {
+			adapter->soft_stats.tx_carrier_errors++;
+			atl1_check_for_link(adapter);
+		}
+
+		/* transmit event */
+		if (status & ISR_CMB_TX)
+			atl1_intr_tx(adapter);
+
+		/* rx exception */
+		if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+				ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+				ISR_HOST_RRD_OV | ISR_CMB_RX))) {
+			if (status &
+			    (ISR_RXF_OV | ISR_RFD_UNRUN | ISR_RRD_OV |
+			     ISR_HOST_RFD_UNRUN | ISR_HOST_RRD_OV))
+				printk(KERN_INFO
+					"%s: rx exception: status = 0x%x\n",
+					atl1_driver_name, status);
+			atl1_intr_rx(adapter);
+		}
+
+		if (--max_ints < 0)
+			break;
+
+	} while ((status = adapter->cmb.cmb->int_stats));
+
+	/* re-enable Interrupt */
+	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
+	return IRQ_HANDLED;
+}
+
+/*
+ * atl1_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1_set_multi(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+	struct dev_mc_list *mc_ptr;
+	u32 rctl;
+	u32 hash_value;
+
+	/* Check for Promiscuous and All Multicast modes */
+	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+	if (netdev->flags & IFF_PROMISC)
+		rctl |= MAC_CTRL_PROMIS_EN;
+	else if (netdev->flags & IFF_ALLMULTI) {
+		rctl |= MAC_CTRL_MC_ALL_EN;
+		rctl &= ~MAC_CTRL_PROMIS_EN;
+	} else
+		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+
+	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
+
+	/* clear the old settings from the multicast hash table */
+	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+
+	/* compute mc addresses' hash value ,and put it into hash table */
+	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+		hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
+		atl1_hash_set(hw, hash_value);
+	}
+}
+
+static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
+{
+	u32 value;
+	struct atl1_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	/* Config MAC CTRL Register */
+	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+	/* duplex */
+	if (FULL_DUPLEX == adapter->link_duplex)
+		value |= MAC_CTRL_DUPLX;
+	/* speed */
+	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
+			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+		  MAC_CTRL_SPEED_SHIFT);
+	/* flow control */
+	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+	/* PAD & CRC */
+	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+	/* preamble length */
+	value |= (((u32) adapter->hw.preamble_len
+		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+	/* vlan */
+	if (adapter->vlgrp)
+		value |= MAC_CTRL_RMV_VLAN;
+	/* rx checksum
+	   if (adapter->rx_csum)
+	   value |= MAC_CTRL_RX_CHKSUM_EN;
+	 */
+	/* filter mode */
+	value |= MAC_CTRL_BC_EN;
+	if (netdev->flags & IFF_PROMISC)
+		value |= MAC_CTRL_PROMIS_EN;
+	else if (netdev->flags & IFF_ALLMULTI)
+		value |= MAC_CTRL_MC_ALL_EN;
+	/* value |= MAC_CTRL_LOOPBACK; */
+	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
+}
+
+static u32 atl1_check_link(struct atl1_adapter *adapter)
+{
+	struct atl1_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	u32 ret_val;
+	u16 speed, duplex, phy_data;
+	int reconfig = 0;
+
+	/* MII_BMSR must read twice */
+	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+	if (!(phy_data & BMSR_LSTATUS)) {	/* link down */
+		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
+			printk(KERN_INFO "%s: link is down\n",
+				atl1_driver_name);
+			adapter->link_speed = SPEED_0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+		return ATL1_SUCCESS;
+	}
+
+	/* Link Up */
+	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
+	if (ret_val)
+		return ret_val;
+
+	switch (hw->media_type) {
+	case MEDIA_TYPE_1000M_FULL:
+		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_100M_FULL:
+		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_100M_HALF:
+		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_10M_FULL:
+		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
+			reconfig = 1;
+		break;
+	case MEDIA_TYPE_10M_HALF:
+		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
+			reconfig = 1;
+		break;
+	}
+
+	/* link result is our setting */
+	if (!reconfig) {
+		if (adapter->link_speed != speed
+		    || adapter->link_duplex != duplex) {
+			adapter->link_speed = speed;
+			adapter->link_duplex = duplex;
+			atl1_setup_mac_ctrl(adapter);
+			printk(KERN_INFO "%s: %s link is up %d Mbps %s\n",
+			       atl1_driver_name, netdev->name,
+			       adapter->link_speed,
+			       adapter->link_duplex ==
+			       FULL_DUPLEX ? "full duplex" : "half duplex");
+		}
+		if (!netif_carrier_ok(netdev)) {	/* Link down -> Up */
+			netif_carrier_on(netdev);
+			netif_wake_queue(netdev);
+		}
+		return ATL1_SUCCESS;
+	}
+
+	/* change orignal link status */
+	if (netif_carrier_ok(netdev)) {
+		adapter->link_speed = SPEED_0;
+		netif_carrier_off(netdev);
+		netif_stop_queue(netdev);
+	}
+
+	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
+	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
+		switch (hw->media_type) {
+		case MEDIA_TYPE_100M_FULL:
+			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+			           MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_100M_HALF:
+			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+			break;
+		case MEDIA_TYPE_10M_FULL:
+			phy_data =
+			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		default:	/* MEDIA_TYPE_10M_HALF: */
+			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+			break;
+		}
+		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+		return ATL1_SUCCESS;
+	}
+
+	/* auto-neg, insert timer to re-config phy */
+	if (!adapter->phy_timer_pending) {
+		adapter->phy_timer_pending = true;
+		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
+	}
+
+	return ATL1_SUCCESS;
+}
+
+static void set_flow_ctrl_old(struct atl1_adapter *adapter)
+{
+	u32 hi, lo, value;
+
+	/* RFD Flow Control */
+	value = adapter->rfd_ring.count;
+	hi = value / 16;
+	if (hi < 2)
+		hi = 2;
+	lo = value * 7 / 8;
+
+	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+	    ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+	/* RRD Flow Control */
+	value = adapter->rrd_ring.count;
+	lo = value / 16;
+	hi = value * 7 / 8;
+	if (lo < 2)
+		lo = 2;
+	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+	    ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+}
+
+static void set_flow_ctrl_new(struct atl1_hw *hw)
+{
+	u32 hi, lo, value;
+
+	/* RXF Flow Control */
+	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
+	lo = value / 16;
+	if (lo < 192)
+		lo = 192;
+	hi = value * 7 / 8;
+	if (hi < lo)
+		hi = lo + 16;
+	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+	    ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+	/* RRD Flow Control */
+	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
+	lo = value / 8;
+	hi = value * 7 / 8;
+	if (lo < 2)
+		lo = 2;
+	if (hi < lo)
+		hi = lo + 3;
+	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+	    ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+}
+
+/*
+ * atl1_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static u32 atl1_configure(struct atl1_adapter *adapter)
+{
+	struct atl1_hw *hw = &adapter->hw;
+	u32 value;
+
+	/* clear interrupt status */
+	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
+
+	/* set MAC Address */
+	value = (((u32) hw->mac_addr[2]) << 24) |
+		(((u32) hw->mac_addr[3]) << 16) |
+		(((u32) hw->mac_addr[4]) << 8) |
+		(((u32) hw->mac_addr[5]));
+	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+
+	/* tx / rx ring */
+
+	/* HI base address */
+	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
+		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
+	/* LO base address */
+	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
+	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
+	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
+	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
+	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
+		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
+
+	/* element count */
+	value = adapter->rrd_ring.count;
+	value <<= 16;
+	value += adapter->rfd_ring.count;
+	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
+	iowrite32(adapter->tpd_ring.count, hw->hw_addr + REG_DESC_TPD_RING_SIZE);
+
+	/* Load Ptr */
+	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
+
+	/* config Mailbox */
+	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
+		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
+	    ((atomic_read(&adapter->rrd_ring.next_to_clean)
+	      & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
+	    ((atomic_read(&adapter->rfd_ring.next_to_use)
+	      & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAILBOX);
+
+	/* config IPG/IFG */
+	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
+		 << MAC_IPG_IFG_IPGT_SHIFT) |
+	    (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
+	     << MAC_IPG_IFG_MIFG_SHIFT) |
+	    (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
+	     << MAC_IPG_IFG_IPGR1_SHIFT) |
+	    (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
+	     << MAC_IPG_IFG_IPGR2_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
+
+	/* config  Half-Duplex Control */
+	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
+	    (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
+	     << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
+	    MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
+	    (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
+	    (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
+	     << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
+
+	/* set Interrupt Moderator Timer */
+	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
+	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
+
+	/* set Interrupt Clear Timer */
+	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
+
+	/* set MTU, 4 : VLAN */
+	iowrite32(hw->max_frame_size + 4, hw->hw_addr + REG_MTU);
+
+	/* jumbo size & rrd retirement timer */
+	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
+		 << RXQ_JMBOSZ_TH_SHIFT) |
+	    (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
+	     << RXQ_JMBO_LKAH_SHIFT) |
+	    (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
+	     << RXQ_RRD_TIMER_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
+
+	/* Flow Control */
+	switch (hw->dev_rev) {
+	case 0x8001:
+	case 0x9001:
+	case 0x9002:
+	case 0x9003:
+		set_flow_ctrl_old(adapter);
+		break;
+	default:
+		set_flow_ctrl_new(hw);
+		break;
+	}
+
+	/* config TXQ */
+	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
+		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
+	    (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
+	     << TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
+	    (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
+	     << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN;
+	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
+
+	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
+	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
+		 << TX_JUMBO_TASK_TH_SHIFT) |
+	    (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
+	     << TX_TPD_MIN_IPG_SHIFT);
+	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
+
+	/* config RXQ */
+	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
+		 << RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
+	    (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
+	     << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
+	    (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
+	     << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) |
+	    RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
+	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
+
+	/* config DMA Engine */
+	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+		 << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+	    ((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+	     << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+	    DMA_CTRL_DMAR_EN | DMA_CTRL_DMAW_EN;
+	value |= (u32) hw->dma_ord;
+	if (atl1_rcb_128 == hw->rcb_value)
+		value |= DMA_CTRL_RCB_VALUE;
+	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
+
+	/* config CMB / SMB */
+	value = hw->cmb_rrd | ((u32) hw->cmb_tpd << 16);
+	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
+	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
+	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
+	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
+
+	/* --- enable CMB / SMB */
+	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
+	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
+
+	value = ioread32(adapter->hw.hw_addr + REG_ISR);
+	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
+		value = 1;	/* config failed */
+	else
+		value = 0;
+
+	/* clear all interrupt status */
+	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
+	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
+	return value;
+}
+
+/*
+ * atl1_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static void atl1_irq_disable(struct atl1_adapter *adapter)
+{
+	atomic_inc(&adapter->irq_sem);
+	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+	ioread32(adapter->hw.hw_addr + REG_IMR);
+	synchronize_irq(adapter->pdev->irq);
+}
+
+static void atl1_vlan_rx_register(struct net_device *netdev,
+				struct vlan_group *grp)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	u32 ctrl;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	/* atl1_irq_disable(adapter); */
+	adapter->vlgrp = grp;
+
+	if (grp) {
+		/* enable VLAN tag insert/strip */
+		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+		ctrl |= MAC_CTRL_RMV_VLAN;
+		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+	} else {
+		/* disable VLAN tag insert/strip */
+		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+		ctrl &= ~MAC_CTRL_RMV_VLAN;
+		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+	}
+
+	/* atl1_irq_enable(adapter); */
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+/* FIXME: justify or remove -- CHS */
+static void atl1_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+{
+	/* We don't do Vlan filtering */
+	return;
+}
+
+/* FIXME: this looks wrong too -- CHS */
+static void atl1_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	/* atl1_irq_disable(adapter); */
+	if (adapter->vlgrp)
+		adapter->vlgrp->vlan_devices[vid] = NULL;
+	/* atl1_irq_enable(adapter); */
+	spin_unlock_irqrestore(&adapter->lock, flags);
+	/* We don't do Vlan filtering */
+	return;
+}
+
+static void atl1_restore_vlan(struct atl1_adapter *adapter)
+{
+	atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+	if (adapter->vlgrp) {
+		u16 vid;
+		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+			if (!adapter->vlgrp->vlan_devices[vid])
+				continue;
+			atl1_vlan_rx_add_vid(adapter->netdev, vid);
+		}
+	}
+}
+
+static u16 tpd_avail(struct atl1_tpd_ring *tpd_ring)
+{
+	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+	u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
+	return ((next_to_clean >
+		 next_to_use) ? next_to_clean - next_to_use -
+		1 : tpd_ring->count + next_to_clean - next_to_use - 1);
+}
+
+static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
+			 struct tso_param *tso)
+{
+	/* We enter this function holding a spinlock. */
+	u8 ipofst;
+	int err;
+
+	if (skb_shinfo(skb)->gso_size) {
+		if (skb_header_cloned(skb)) {
+			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+			if (unlikely(err))
+				return err;
+		}
+
+		if (skb->protocol == ntohs(ETH_P_IP)) {
+			skb->nh.iph->tot_len = 0;
+			skb->nh.iph->check = 0;
+			skb->h.th->check =
+			    ~csum_tcpudp_magic(skb->nh.iph->saddr,
+					       skb->nh.iph->daddr, 0,
+					       IPPROTO_TCP, 0);
+			ipofst = skb->nh.raw - skb->data;
+			if (ipofst != ENET_HEADER_SIZE) /* 802.3 frame */
+				tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT;
+
+			tso->tsopl |= (skb->nh.iph->ihl &
+				CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT;
+			tso->tsopl |= ((skb->h.th->doff << 2) &
+				TSO_PARAM_TCPHDRLEN_MASK) << TSO_PARAM_TCPHDRLEN_SHIFT;
+			tso->tsopl |= (skb_shinfo(skb)->gso_size &
+				TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT;
+			tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT;
+			tso->tsopl |= 1 << TSO_PARAM_TCPCKSUM_SHIFT;
+			tso->tsopl |= 1 << TSO_PARAM_SEGMENT_SHIFT;
+			return true;
+		}
+	}
+	return false;
+}
+
+static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
+			struct csum_param *csum)
+{
+	u8 css, cso;
+
+	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+		cso = skb->h.raw - skb->data;
+		css = (skb->h.raw + skb->csum) - skb->data;
+		if (unlikely(cso & 0x1)) {
+			printk(KERN_DEBUG "%s: payload offset != even number\n",
+				atl1_driver_name);
+			return -1;
+		}
+		csum->csumpl |= (cso & CSUM_PARAM_PLOADOFFSET_MASK) <<
+			CSUM_PARAM_PLOADOFFSET_SHIFT;
+		csum->csumpl |= (css & CSUM_PARAM_XSUMOFFSET_MASK) <<
+			CSUM_PARAM_XSUMOFFSET_SHIFT;
+		csum->csumpl |= 1 << CSUM_PARAM_CUSTOMCKSUM_SHIFT;
+		return true;
+	}
+
+	return true;
+}
+
+static void atl1_tx_map(struct atl1_adapter *adapter,
+				struct sk_buff *skb, bool tcp_seg)
+{
+	/* We enter this function holding a spinlock. */
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_buffer *buffer_info;
+	struct page *page;
+	int first_buf_len = skb->len;
+	unsigned long offset;
+	unsigned int nr_frags;
+	unsigned int f;
+	u16 tpd_next_to_use;
+	u16 proto_hdr_len;
+	u16 i, m, len12;
+
+	first_buf_len -= skb->data_len;
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	tpd_next_to_use = atomic_read(&tpd_ring->next_to_use);
+	buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+	if (unlikely(buffer_info->skb))
+		BUG();
+	buffer_info->skb = NULL;	/* put skb in last TPD */
+
+	if (tcp_seg) {
+		/* TSO/GSO */
+		proto_hdr_len =
+		    ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+		buffer_info->length = proto_hdr_len;
+		page = virt_to_page(skb->data);
+		offset = (unsigned long)skb->data & ~PAGE_MASK;
+		buffer_info->dma = pci_map_page(adapter->pdev, page,
+						offset, proto_hdr_len,
+						PCI_DMA_TODEVICE);
+
+		if (++tpd_next_to_use == tpd_ring->count)
+			tpd_next_to_use = 0;
+
+		if (first_buf_len > proto_hdr_len) {
+			len12 = first_buf_len - proto_hdr_len;
+			m = (len12 + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+			for (i = 0; i < m; i++) {
+				buffer_info =
+				    &tpd_ring->buffer_info[tpd_next_to_use];
+				buffer_info->skb = NULL;
+				buffer_info->length =
+				    (MAX_TX_BUF_LEN >=
+				     len12) ? MAX_TX_BUF_LEN : len12;
+				len12 -= buffer_info->length;
+				page = virt_to_page(skb->data +
+						 (proto_hdr_len +
+						  i * MAX_TX_BUF_LEN));
+				offset = (unsigned long)(skb->data +
+							(proto_hdr_len +
+							i * MAX_TX_BUF_LEN)) &
+							~PAGE_MASK;
+				buffer_info->dma =
+				    pci_map_page(adapter->pdev, page, offset,
+						 buffer_info->length,
+						 PCI_DMA_TODEVICE);
+				if (++tpd_next_to_use == tpd_ring->count)
+					tpd_next_to_use = 0;
+			}
+		}
+	} else {
+		/* not TSO/GSO */
+		buffer_info->length = first_buf_len;
+		page = virt_to_page(skb->data);
+		offset = (unsigned long)skb->data & ~PAGE_MASK;
+		buffer_info->dma = pci_map_page(adapter->pdev, page,
+						offset, first_buf_len,
+						PCI_DMA_TODEVICE);
+		if (++tpd_next_to_use == tpd_ring->count)
+			tpd_next_to_use = 0;
+	}
+
+	for (f = 0; f < nr_frags; f++) {
+		struct skb_frag_struct *frag;
+		u16 lenf, i, m;
+
+		frag = &skb_shinfo(skb)->frags[f];
+		lenf = frag->size;
+
+		m = (lenf + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+		for (i = 0; i < m; i++) {
+			buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+			if (unlikely(buffer_info->skb))
+				BUG();
+			buffer_info->skb = NULL;
+			buffer_info->length =
+			    (lenf > MAX_TX_BUF_LEN) ? MAX_TX_BUF_LEN : lenf;
+			lenf -= buffer_info->length;
+			buffer_info->dma =
+			    pci_map_page(adapter->pdev, frag->page,
+					 frag->page_offset + i * MAX_TX_BUF_LEN,
+					 buffer_info->length, PCI_DMA_TODEVICE);
+
+			if (++tpd_next_to_use == tpd_ring->count)
+				tpd_next_to_use = 0;
+		}
+	}
+
+	/* last tpd's buffer-info */
+	buffer_info->skb = skb;
+}
+
+static void atl1_tx_queue(struct atl1_adapter *adapter, int count,
+			       union tpd_descr *descr)
+{
+	/* We enter this function holding a spinlock. */
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	int j;
+	u32 val;
+	struct atl1_buffer *buffer_info;
+	struct tx_packet_desc *tpd;
+	u16 tpd_next_to_use = atomic_read(&tpd_ring->next_to_use);
+
+	for (j = 0; j < count; j++) {
+		buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+		tpd = ATL1_TPD_DESC(&adapter->tpd_ring, tpd_next_to_use);
+		tpd->desc.csum.csumpu = descr->csum.csumpu;
+		tpd->desc.csum.csumpl = descr->csum.csumpl;
+		tpd->desc.tso.tsopu = descr->tso.tsopu;
+		tpd->desc.tso.tsopl = descr->tso.tsopl;
+		tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+		tpd->desc.data = descr->data;
+		tpd->desc.csum.csumpu |= (cpu_to_le16(buffer_info->length) &
+			CSUM_PARAM_BUFLEN_MASK) << CSUM_PARAM_BUFLEN_SHIFT;
+
+		val = (descr->tso.tsopl >> TSO_PARAM_SEGMENT_SHIFT) &
+			TSO_PARAM_SEGMENT_MASK;
+		if (val && !j)
+			tpd->desc.tso.tsopl |= 1 << TSO_PARAM_HDRFLAG_SHIFT;
+
+		if (j == (count - 1))
+			tpd->desc.csum.csumpl |= 1 << CSUM_PARAM_EOP_SHIFT;
+
+		if (++tpd_next_to_use == tpd_ring->count)
+			tpd_next_to_use = 0;
+	}
+	/*
+	 * Force memory writes to complete before letting h/w
+	 * know there are new descriptors to fetch.  (Only
+	 * applicable for weak-ordered memory model archs,
+	 * such as IA-64).
+	 */
+	wmb();
+
+	atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use);
+}
+
+static void atl1_update_mailbox(struct atl1_adapter *adapter)
+{
+	unsigned long flags;
+	u32 tpd_next_to_use;
+	u32 rfd_next_to_use;
+	u32 rrd_next_to_clean;
+	u32 value;
+
+	spin_lock_irqsave(&adapter->mb_lock, flags);
+
+	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
+	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
+
+	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+		MB_RFD_PROD_INDX_SHIFT) |
+		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+		MB_RRD_CONS_INDX_SHIFT) |
+		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+		MB_TPD_PROD_INDX_SHIFT);
+	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+
+	spin_unlock_irqrestore(&adapter->mb_lock, flags);
+}
+
+static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	int len = skb->len;
+	int tso;
+	int count = 1;
+	int ret_val;
+	u32 val;
+	union tpd_descr param;
+	u16 frag_size;
+	u16 vlan_tag;
+	unsigned long flags;
+	unsigned int nr_frags = 0;
+	unsigned int mss = 0;
+	unsigned int f;
+	unsigned int proto_hdr_len;
+
+	len -= skb->data_len;
+
+	if (unlikely(skb->len == 0)) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	param.data = 0;
+	param.tso.tsopu = 0;
+	param.tso.tsopl = 0;
+	param.csum.csumpu = 0;
+	param.csum.csumpl = 0;
+
+	/* nr_frags will be nonzero if we're doing scatter/gather (SG) */
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	for (f = 0; f < nr_frags; f++) {
+		frag_size = skb_shinfo(skb)->frags[f].size;
+		if (frag_size)
+			count +=
+			    (frag_size + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+	}
+
+	/* mss will be nonzero if we're doing segment offload (TSO/GSO) */
+	mss = skb_shinfo(skb)->gso_size;
+	if (mss) {
+		if (skb->protocol == ntohs(ETH_P_IP)) {
+			proto_hdr_len = ((skb->h.raw - skb->data) +
+					 (skb->h.th->doff << 2));
+			if (unlikely(proto_hdr_len > len)) {
+				dev_kfree_skb_any(skb);
+				return NETDEV_TX_OK;
+			}
+			/* need additional TPD ? */
+			if (proto_hdr_len != len)
+				count += (len - proto_hdr_len +
+					MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+		}
+	}
+
+	local_irq_save(flags);
+	if (!spin_trylock(&adapter->lock)) {
+		/* Can't get lock - tell upper layer to requeue */
+		local_irq_restore(flags);
+		printk(KERN_DEBUG "%s: TX locked\n", atl1_driver_name);
+		return NETDEV_TX_LOCKED;
+	}
+
+	if (tpd_avail(&adapter->tpd_ring) < count) {
+		/* not enough descriptors */
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&adapter->lock, flags);
+		printk(KERN_DEBUG "%s: TX busy\n", atl1_driver_name);
+		return NETDEV_TX_BUSY;
+	}
+
+	param.data = 0;
+
+	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+		vlan_tag = vlan_tx_tag_get(skb);
+		vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
+			((vlan_tag >> 9) & 0x8);
+		param.csum.csumpl |= 1 << CSUM_PARAM_INSVLAG_SHIFT;
+		param.csum.csumpu |= (vlan_tag & CSUM_PARAM_VALANTAG_MASK) <<
+			CSUM_PARAM_VALAN_SHIFT;
+	}
+
+	tso = atl1_tso(adapter, skb, &param.tso);
+	if (tso < 0) {
+		spin_unlock_irqrestore(&adapter->lock, flags);
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (!tso) {
+		ret_val = atl1_tx_csum(adapter, skb, &param.csum);
+		if (ret_val < 0) {
+			spin_unlock_irqrestore(&adapter->lock, flags);
+			dev_kfree_skb_any(skb);
+			return NETDEV_TX_OK;
+		}
+	}
+
+	val = (param.csum.csumpl >> CSUM_PARAM_SEGMENT_SHIFT) &
+		CSUM_PARAM_SEGMENT_MASK;
+	atl1_tx_map(adapter, skb, 1 == val);
+	atl1_tx_queue(adapter, count, &param);
+	netdev->trans_start = jiffies;
+	spin_unlock_irqrestore(&adapter->lock, flags);
+	atl1_update_mailbox(adapter);
+	return NETDEV_TX_OK;
+}
+
+/*
+ * atl1_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1_get_stats(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	return &adapter->net_stats;
+}
+
+/*
+ * atl1_clean_rx_ring - Free RFD Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
+{
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	unsigned int i;
+
+	/* Free all the Rx ring sk_buffs */
+	for (i = 0; i < rfd_ring->count; i++) {
+		buffer_info = &rfd_ring->buffer_info[i];
+		if (buffer_info->dma) {
+			pci_unmap_page(pdev,
+					buffer_info->dma,
+					buffer_info->length,
+					PCI_DMA_FROMDEVICE);
+			buffer_info->dma = 0;
+		}
+		if (buffer_info->skb) {
+			dev_kfree_skb(buffer_info->skb);
+			buffer_info->skb = NULL;
+		}
+	}
+
+	size = sizeof(struct atl1_buffer) * rfd_ring->count;
+	memset(rfd_ring->buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(rfd_ring->desc, 0, rfd_ring->size);
+
+	rfd_ring->next_to_clean = 0;
+	atomic_set(&rfd_ring->next_to_use, 0);
+
+	rrd_ring->next_to_use = 0;
+	atomic_set(&rrd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_clean_tx_ring - Free Tx Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+{
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	unsigned int i;
+
+	/* Free all the Tx ring sk_buffs */
+	for (i = 0; i < tpd_ring->count; i++) {
+		buffer_info = &tpd_ring->buffer_info[i];
+		if (buffer_info->dma) {
+			pci_unmap_page(pdev, buffer_info->dma,
+				       buffer_info->length, PCI_DMA_TODEVICE);
+			buffer_info->dma = 0;
+		}
+	}
+
+	for (i = 0; i < tpd_ring->count; i++) {
+		buffer_info = &tpd_ring->buffer_info[i];
+		if (buffer_info->skb) {
+			dev_kfree_skb_any(buffer_info->skb);
+			buffer_info->skb = NULL;
+		}
+	}
+
+	size = sizeof(struct atl1_buffer) * tpd_ring->count;
+	memset(tpd_ring->buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(tpd_ring->desc, 0, tpd_ring->size);
+
+	atomic_set(&tpd_ring->next_to_use, 0);
+	atomic_set(&tpd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+void atl1_free_ring_resources(struct atl1_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+	struct atl1_ring_header *ring_header = &adapter->ring_header;
+
+	atl1_clean_tx_ring(adapter);
+	atl1_clean_rx_ring(adapter);
+
+	kfree(tpd_ring->buffer_info);
+	pci_free_consistent(pdev, ring_header->size, ring_header->desc,
+			    ring_header->dma);
+
+	tpd_ring->buffer_info = NULL;
+	tpd_ring->desc = NULL;
+	tpd_ring->dma = 0;
+
+	rfd_ring->buffer_info = NULL;
+	rfd_ring->desc = NULL;
+	rfd_ring->dma = 0;
+
+	rrd_ring->desc = NULL;
+	rrd_ring->dma = 0;
+}
+
+s32 atl1_up(struct atl1_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	int err;
+	int irq_flags = IRQF_SAMPLE_RANDOM;
+
+	/* hardware has been reset, we need to reload some things */
+	atl1_set_multi(netdev);
+	atl1_restore_vlan(adapter);
+	err = atl1_alloc_rx_buffers(adapter);
+	if (unlikely(!err))		/* no RX BUFFER allocated */
+		return -ENOMEM;
+
+	if (unlikely(atl1_configure(adapter))) {
+		err = -EIO;
+		goto err_up;
+	}
+
+	err = pci_enable_msi(adapter->pdev);
+	if (err) {
+		dev_info(&adapter->pdev->dev,
+			"Unable to enable MSI: %d\n", err);
+		irq_flags |= IRQF_SHARED;
+	}
+
+	err = request_irq(adapter->pdev->irq, &atl1_intr, irq_flags,
+			netdev->name, netdev);
+	if (unlikely(err))
+		goto err_up;
+
+	mod_timer(&adapter->watchdog_timer, jiffies);
+	atl1_irq_enable(adapter);
+	atl1_check_link(adapter);
+	return 0;
+
+	/* FIXME: unreachable code! -- CHS */
+	/* free irq disable any interrupt */
+	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+	free_irq(adapter->pdev->irq, netdev);
+
+err_up:
+	pci_disable_msi(adapter->pdev);
+	/* free rx_buffers */
+	atl1_clean_rx_ring(adapter);
+	return err;
+}
+
+void atl1_down(struct atl1_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	del_timer_sync(&adapter->watchdog_timer);
+	del_timer_sync(&adapter->phy_config_timer);
+	adapter->phy_timer_pending = false;
+
+	atl1_irq_disable(adapter);
+	free_irq(adapter->pdev->irq, netdev);
+	pci_disable_msi(adapter->pdev);
+	atl1_reset_hw(&adapter->hw);
+	adapter->cmb.cmb->int_stats = 0;
+
+	adapter->link_speed = SPEED_0;
+	adapter->link_duplex = -1;
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	atl1_clean_tx_ring(adapter);
+	atl1_clean_rx_ring(adapter);
+}
+
+/*
+ * atl1_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	int old_mtu = netdev->mtu;
+	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+
+	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		printk(KERN_WARNING "%s: invalid MTU setting\n",
+			atl1_driver_name);
+		return -EINVAL;
+	}
+
+	adapter->hw.max_frame_size = max_frame;
+	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
+	adapter->rx_buffer_len = (max_frame + 7) & ~7;
+	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
+
+	netdev->mtu = new_mtu;
+	if ((old_mtu != new_mtu) && netif_running(netdev)) {
+		atl1_down(adapter);
+		atl1_up(adapter);
+	}
+
+	return 0;
+}
+
+/*
+ * atl1_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_set_mac(struct net_device *netdev, void *p)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *addr = p;
+
+	if (netif_running(netdev))
+		return -EBUSY;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+	atl1_set_mac_addr(&adapter->hw);
+	return 0;
+}
+
+/*
+ * atl1_watchdog - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_watchdog(unsigned long data)
+{
+	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+
+	/* Reset the timer */
+	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
+static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	u16 result;
+
+	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
+
+	return result;
+}
+
+static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, int val)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	atl1_write_phy_reg(&adapter->hw, reg_num, val);
+}
+
+/*
+ * atl1_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	int retval;
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+
+	return retval;
+}
+
+/*
+ * atl1_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		return atl1_mii_ioctl(netdev, ifr, cmd);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/*
+ * atl1_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1_tx_timeout(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	/* Do the reset outside of interrupt context */
+	schedule_work(&adapter->tx_timeout_task);
+}
+
+/*
+ * atl1_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_phy_config(unsigned long data)
+{
+	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+	struct atl1_hw *hw = &adapter->hw;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	adapter->phy_timer_pending = false;
+	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+	atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
+	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+int atl1_reset(struct atl1_adapter *adapter)
+{
+	int ret;
+
+	ret = atl1_reset_hw(&adapter->hw);
+	if (ret != ATL1_SUCCESS)
+		return ret;
+	return atl1_init_hw(&adapter->hw);
+}
+
+/*
+ * atl1_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP).  At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl1_open(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	int err;
+
+	/* allocate transmit descriptors */
+	err = atl1_setup_ring_resources(adapter);
+	if (err)
+		return err;
+
+	err = atl1_up(adapter);
+	if (err)
+		goto err_up;
+
+	return 0;
+
+err_up:
+	atl1_reset(adapter);
+	return err;
+}
+
+/*
+ * atl1_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled.  A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static int atl1_close(struct net_device *netdev)
+{
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	atl1_down(adapter);
+	atl1_free_ring_resources(adapter);
+	return 0;
+}
+
+/*
+ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
+ * will assert. We do soft reset <0x1400=1> according
+ * with the SPEC. BUT, it seemes that PCIE or DMA
+ * state-machine will not be reset. DMAR_TO_INT will
+ * assert again and again.
+ */
+static void atl1_tx_timeout_task(struct work_struct *work)
+{
+	struct atl1_adapter *adapter =
+		container_of(work, struct atl1_adapter, tx_timeout_task);
+	struct net_device *netdev = adapter->netdev;
+
+	netif_device_detach(netdev);
+	atl1_down(adapter);
+	atl1_up(adapter);
+	netif_device_attach(netdev);
+}
+
+/*
+ * atl1_link_chg_task - deal with link change event Out of interrupt context
+ */
+static void atl1_link_chg_task(struct work_struct *work)
+{
+	struct atl1_adapter *adapter =
+               container_of(work, struct atl1_adapter, link_chg_task);
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	atl1_check_link(adapter);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+/*
+ * atl1_pcie_patch - Patch for PCIE module
+ */
+static void atl1_pcie_patch(struct atl1_adapter *adapter)
+{
+	u32 value;
+	value = 0x6500;
+	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
+	/* pcie flow control mode change */
+	value = ioread32(adapter->hw.hw_addr + 0x1008);
+	value |= 0x8000;
+	iowrite32(value, adapter->hw.hw_addr + 0x1008);
+}
+
+/*
+ * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
+ * on PCI Command register is disable.
+ * The function enable this bit.
+ * Brackett, 2006/03/15
+ */
+static void atl1_via_workaround(struct atl1_adapter *adapter)
+{
+	unsigned long value;
+
+	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
+	if (value & PCI_COMMAND_INTX_DISABLE)
+		value &= ~PCI_COMMAND_INTX_DISABLE;
+	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
+}
+
+/*
+ * atl1_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int __devinit atl1_probe(struct pci_dev *pdev,
+			      const struct pci_device_id *ent)
+{
+	struct net_device *netdev;
+	struct atl1_adapter *adapter;
+	static int cards_found = 0;
+	bool pci_using_64 = true;
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+
+	err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+	if (err) {
+		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		if (err) {
+			printk(KERN_DEBUG
+				"%s: no usable DMA configuration, aborting\n",
+				atl1_driver_name);
+			goto err_dma;
+		}
+		pci_using_64 = false;
+	}
+	/* Mark all PCI regions associated with PCI device
+	 * pdev as being reserved by owner atl1_driver_name
+	 */
+	err = pci_request_regions(pdev, atl1_driver_name);
+	if (err)
+		goto err_request_regions;
+
+	/* Enables bus-mastering on the device and calls
+	 * pcibios_set_master to do the needed arch specific settings
+	 */
+	pci_set_master(pdev);
+
+	netdev = alloc_etherdev(sizeof(struct atl1_adapter));
+	if (!netdev) {
+		err = -ENOMEM;
+		goto err_alloc_etherdev;
+	}
+	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+
+	pci_set_drvdata(pdev, netdev);
+	adapter = netdev_priv(netdev);
+	adapter->netdev = netdev;
+	adapter->pdev = pdev;
+	adapter->hw.back = adapter;
+
+	adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);
+	if (!adapter->hw.hw_addr) {
+		err = -EIO;
+		goto err_pci_iomap;
+	}
+	/* get device revision number */
+	adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr + (REG_MASTER_CTRL + 2));
+
+	/* set default ring resource counts */
+	adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
+	adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
+
+	adapter->mii.dev = netdev;
+	adapter->mii.mdio_read = mdio_read;
+	adapter->mii.mdio_write = mdio_write;
+	adapter->mii.phy_id_mask = 0x1f;
+	adapter->mii.reg_num_mask = 0x1f;
+
+	netdev->open = &atl1_open;
+	netdev->stop = &atl1_close;
+	netdev->hard_start_xmit = &atl1_xmit_frame;
+	netdev->get_stats = &atl1_get_stats;
+	netdev->set_multicast_list = &atl1_set_multi;
+	netdev->set_mac_address = &atl1_set_mac;
+	netdev->change_mtu = &atl1_change_mtu;
+	netdev->do_ioctl = &atl1_ioctl;
+	netdev->tx_timeout = &atl1_tx_timeout;
+	netdev->watchdog_timeo = 5 * HZ;
+	netdev->vlan_rx_register = atl1_vlan_rx_register;
+	netdev->vlan_rx_add_vid = atl1_vlan_rx_add_vid;
+	netdev->vlan_rx_kill_vid = atl1_vlan_rx_kill_vid;
+	netdev->ethtool_ops = &atl1_ethtool_ops;
+	adapter->bd_number = cards_found;
+	adapter->pci_using_64 = pci_using_64;
+
+	/* setup the private structure */
+	err = atl1_sw_init(adapter);
+	if (err)
+		goto err_common;
+
+	netdev->features = NETIF_F_HW_CSUM;
+	netdev->features |= NETIF_F_SG;
+	netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+
+	/*
+	 * FIXME - Until tso performance gets fixed, disable the feature.
+	 * Enable it with ethtool -K if desired.
+	 */
+	/* netdev->features |= NETIF_F_TSO; */
+
+	if (pci_using_64)
+		netdev->features |= NETIF_F_HIGHDMA;
+
+	netdev->features |= NETIF_F_LLTX;
+
+	/*
+	 * patch for some L1 of old version,
+	 * the final version of L1 may not need these
+	 * patches
+	 */
+	/* atl1_pcie_patch(adapter); */
+
+	/* really reset GPHY core */
+	iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
+
+	/*
+	 * reset the controller to
+	 * put the device in a known good starting state
+	 */
+	if (atl1_reset_hw(&adapter->hw)) {
+		err = -EIO;
+		goto err_common;
+	}
+
+	/* copy the MAC address out of the EEPROM */
+	atl1_read_mac_addr(&adapter->hw);
+	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+
+	if (!is_valid_ether_addr(netdev->dev_addr)) {
+		err = -EIO;
+		goto err_common;
+	}
+
+	atl1_check_options(adapter);
+
+	/* pre-init the MAC, and setup link */
+	err = atl1_init_hw(&adapter->hw);
+	if (err) {
+		err = -EIO;
+		goto err_common;
+	}
+
+	atl1_pcie_patch(adapter);
+	/* assume we have no link for now */
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	init_timer(&adapter->watchdog_timer);
+	adapter->watchdog_timer.function = &atl1_watchdog;
+	adapter->watchdog_timer.data = (unsigned long)adapter;
+
+	init_timer(&adapter->phy_config_timer);
+	adapter->phy_config_timer.function = &atl1_phy_config;
+	adapter->phy_config_timer.data = (unsigned long)adapter;
+	adapter->phy_timer_pending = false;
+
+	INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
+
+	INIT_WORK(&adapter->link_chg_task, atl1_link_chg_task);
+
+	INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
+
+	err = register_netdev(netdev);
+	if (err)
+		goto err_common;
+
+	cards_found++;
+	atl1_via_workaround(adapter);
+	return 0;
+
+err_common:
+	pci_iounmap(pdev, adapter->hw.hw_addr);
+err_pci_iomap:
+	free_netdev(netdev);
+err_alloc_etherdev:
+	pci_release_regions(pdev);
+err_dma:
+err_request_regions:
+	pci_disable_device(pdev);
+	return err;
+}
+
+/*
+ * atl1_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.  The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void __devexit atl1_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter;
+	/* Device not available. Return. */
+	if (!netdev)
+		return;
+
+	adapter = netdev_priv(netdev);
+	iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
+	unregister_netdev(netdev);
+	pci_iounmap(pdev, adapter->hw.hw_addr);
+	pci_release_regions(pdev);
+	free_netdev(netdev);
+	pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM
+static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	struct atl1_hw *hw = &adapter->hw;
+	u32 ctrl = 0;
+	u32 wufc = adapter->wol;
+
+	netif_device_detach(netdev);
+	if (netif_running(netdev))
+		atl1_down(adapter);
+
+	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+	if (ctrl & BMSR_LSTATUS)
+		wufc &= ~ATL1_WUFC_LNKC;
+
+	/* reduce speed to 10/100M */
+	if (wufc) {
+		atl1_phy_enter_power_saving(hw);
+		/* if resume, let driver to re- setup link */
+		hw->phy_configured = false;
+		atl1_set_mac_addr(hw);
+		atl1_set_multi(netdev);
+
+		ctrl = 0;
+		/* turn on magic packet wol */
+		if (wufc & ATL1_WUFC_MAG)
+			ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+		/* turn on Link change WOL */
+		if (wufc & ATL1_WUFC_LNKC)
+			ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
+		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
+
+		/* turn on all-multi mode if wake on multicast is enabled */
+		ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+		ctrl &= ~MAC_CTRL_DBG;
+		ctrl &= ~MAC_CTRL_PROMIS_EN;
+		if (wufc & ATL1_WUFC_MC)
+			ctrl |= MAC_CTRL_MC_ALL_EN;
+		else
+			ctrl &= ~MAC_CTRL_MC_ALL_EN;
+
+		/* turn on broadcast mode if wake on-BC is enabled */
+		if (wufc & ATL1_WUFC_BC)
+			ctrl |= MAC_CTRL_BC_EN;
+		else
+			ctrl &= ~MAC_CTRL_BC_EN;
+
+		/* enable RX */
+		ctrl |= MAC_CTRL_RX_EN;
+		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
+		pci_enable_wake(pdev, PCI_D3hot, 1);
+		pci_enable_wake(pdev, PCI_D3cold, 1);	/* 4 == D3 cold */
+	} else {
+		iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		pci_enable_wake(pdev, PCI_D3cold, 0);	/* 4 == D3 cold */
+	}
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+
+static int atl1_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+	u32 ret_val;
+
+	pci_set_power_state(pdev, 0);
+	pci_restore_state(pdev);
+
+	ret_val = pci_enable_device(pdev);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
+	atl1_reset(adapter);
+
+	if (netif_running(netdev))
+		atl1_up(adapter);
+	netif_device_attach(netdev);
+
+	atl1_via_workaround(adapter);
+
+	return 0;
+}
+#else
+#define atl1_suspend NULL
+#define atl1_resume NULL
+#endif
+
+static struct pci_driver atl1_driver = {
+	.name = atl1_driver_name,
+	.id_table = atl1_pci_tbl,
+	.probe = atl1_probe,
+	.remove = __devexit_p(atl1_remove),
+	/* Power Managment Hooks */
+	/* probably broken right now -- CHS */
+	.suspend = atl1_suspend,
+	.resume = atl1_resume
+};
+
+/*
+ * atl1_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl1_exit_module is called just before the driver is removed
+ * from memory.
+ */
+static void __exit atl1_exit_module(void)
+{
+	pci_unregister_driver(&atl1_driver);
+}
+
+/*
+ * atl1_init_module - Driver Registration Routine
+ *
+ * atl1_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+static int __init atl1_init_module(void)
+{
+	printk(KERN_INFO "%s - version %s\n", atl1_driver_string, DRIVER_VERSION);
+	printk(KERN_INFO "%s\n", atl1_copyright);
+	return pci_register_driver(&atl1_driver);
+}
+
+module_init(atl1_init_module);
+module_exit(atl1_exit_module);
diff --git a/drivers/net/atl1/atl1_param.c b/drivers/net/atl1/atl1_param.c
new file mode 100644
index 0000000..c407214
--- /dev/null
+++ b/drivers/net/atl1/atl1_param.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * 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/types.h>
+#include <linux/pci.h>
+#include <linux/moduleparam.h>
+#include "atl1.h"
+
+/*
+ * This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+#define ATL1_MAX_NIC 4
+
+#define OPTION_UNSET    -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED  1
+
+#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
+
+/*
+ * Interrupt Moderate Timer in units of 2 us
+ *
+ * Valid Range: 10-65535
+ *
+ * Default Value: 100 (200us)
+ */
+static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+static int num_int_mod_timer = 0;
+module_param_array_named(int_mod_timer, int_mod_timer, int, &num_int_mod_timer, 0);
+MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
+
+/*
+ * flash_vendor
+ *
+ * Valid Range: 0-2
+ *
+ * 0 - Atmel
+ * 1 - SST
+ * 2 - ST
+ *
+ * Default Value: 0
+ */
+static int __devinitdata flash_vendor[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+static int num_flash_vendor = 0;
+module_param_array_named(flash_vendor, flash_vendor, int, &num_flash_vendor, 0);
+MODULE_PARM_DESC(flash_vendor, "SPI flash vendor");
+
+#define DEFAULT_INT_MOD_CNT	100	/* 200us */
+#define MAX_INT_MOD_CNT		65000
+#define MIN_INT_MOD_CNT		50
+
+#define FLASH_VENDOR_DEFAULT	0
+#define FLASH_VENDOR_MIN	0
+#define FLASH_VENDOR_MAX	2
+
+struct atl1_option {
+	enum { enable_option, range_option, list_option } type;
+	char *name;
+	char *err;
+	int def;
+	union {
+		struct {	/* range_option info */
+			int min;
+			int max;
+		} r;
+		struct {	/* list_option info */
+			int nr;
+			struct atl1_opt_list {
+				int i;
+				char *str;
+			} *p;
+		} l;
+	} arg;
+};
+
+static int __devinit atl1_validate_option(int *value, struct atl1_option *opt)
+{
+	if (*value == OPTION_UNSET) {
+		*value = opt->def;
+		return 0;
+	}
+
+	switch (opt->type) {
+	case enable_option:
+		switch (*value) {
+		case OPTION_ENABLED:
+			printk(KERN_INFO "%s: %s Enabled\n", atl1_driver_name,
+				opt->name);
+			return 0;
+		case OPTION_DISABLED:
+			printk(KERN_INFO "%s: %s Disabled\n", atl1_driver_name,
+				opt->name);
+			return 0;
+		}
+		break;
+	case range_option:
+		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+			printk(KERN_INFO "%s: %s set to %i\n",
+				atl1_driver_name, opt->name, *value);
+			return 0;
+		}
+		break;
+	case list_option:{
+			int i;
+			struct atl1_opt_list *ent;
+
+			for (i = 0; i < opt->arg.l.nr; i++) {
+				ent = &opt->arg.l.p[i];
+				if (*value == ent->i) {
+					if (ent->str[0] != '\0')
+						printk(KERN_INFO "%s: %s\n",
+						       atl1_driver_name, ent->str);
+					return 0;
+				}
+			}
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	printk(KERN_INFO "%s: invalid %s specified (%i) %s\n",
+	       atl1_driver_name, opt->name, *value, opt->err);
+	*value = opt->def;
+	return -1;
+}
+
+/*
+ * atl1_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input.  If an invalid value is given, or if no user specified
+ * value exists, a default value is used.  The final value is stored
+ * in a variable in the adapter structure.
+ */
+void __devinit atl1_check_options(struct atl1_adapter *adapter)
+{
+	int bd = adapter->bd_number;
+	if (bd >= ATL1_MAX_NIC) {
+		printk(KERN_NOTICE "%s: warning: no configuration for board #%i\n",
+			atl1_driver_name, bd);
+		printk(KERN_NOTICE "%s: using defaults for all values\n",
+			atl1_driver_name);
+	}
+	{			/* Interrupt Moderate Timer */
+		struct atl1_option opt = {
+			.type = range_option,
+			.name = "Interrupt Moderator Timer",
+			.err = "using default of "
+				__MODULE_STRING(DEFAULT_INT_MOD_CNT),
+			.def = DEFAULT_INT_MOD_CNT,
+			.arg = {.r =
+				{.min = MIN_INT_MOD_CNT,.max = MAX_INT_MOD_CNT}}
+		};
+		int val;
+		if (num_int_mod_timer > bd) {
+			val = int_mod_timer[bd];
+			atl1_validate_option(&val, &opt);
+			adapter->imt = (u16) val;
+		} else
+			adapter->imt = (u16) (opt.def);
+	}
+
+	{			/* Flash Vendor */
+		struct atl1_option opt = {
+			.type = range_option,
+			.name = "SPI Flash Vendor",
+			.err = "using default of "
+				__MODULE_STRING(FLASH_VENDOR_DEFAULT),
+			.def = DEFAULT_INT_MOD_CNT,
+			.arg = {.r =
+				{.min = FLASH_VENDOR_MIN,.max =
+				 FLASH_VENDOR_MAX}}
+		};
+		int val;
+		if (num_flash_vendor > bd) {
+			val = flash_vendor[bd];
+			atl1_validate_option(&val, &opt);
+			adapter->hw.flash_vendor = (u8) val;
+		} else
+			adapter->hw.flash_vendor = (u8) (opt.def);
+	}
+}
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index f0b6879..69ae229 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -37,7 +37,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 5ff7882..aaada57 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -59,7 +59,6 @@
 #define B44_DEF_TX_RING_PENDING		(B44_TX_RING_SIZE - 1)
 #define B44_TX_RING_BYTES	(sizeof(struct dma_desc) * \
 				 B44_TX_RING_SIZE)
-#define B44_DMA_MASK 0x3fffffff
 
 #define TX_RING_GAP(BP)	\
 	(B44_TX_RING_SIZE - (BP)->tx_pending)
@@ -665,7 +664,7 @@
 	/* Hardware bug work-around, the chip is unable to do PCI DMA
 	   to/from anything above 1GB :-( */
 	if (dma_mapping_error(mapping) ||
-		mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+		mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
 		/* Sigh... */
 		if (!dma_mapping_error(mapping))
 			pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
@@ -677,7 +676,7 @@
 					 RX_PKT_BUF_SZ,
 					 PCI_DMA_FROMDEVICE);
 		if (dma_mapping_error(mapping) ||
-			mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+			mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
 			if (!dma_mapping_error(mapping))
 				pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
 			dev_kfree_skb_any(skb);
@@ -988,7 +987,7 @@
 	}
 
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
-	if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
+	if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
 		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
 		if (!dma_mapping_error(mapping))
 			pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
@@ -1000,7 +999,7 @@
 
 		mapping = pci_map_single(bp->pdev, bounce_skb->data,
 					 len, PCI_DMA_TODEVICE);
-		if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
+		if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
 			if (!dma_mapping_error(mapping))
 				pci_unmap_single(bp->pdev, mapping,
 					 len, PCI_DMA_TODEVICE);
@@ -1227,7 +1226,7 @@
 		                             DMA_BIDIRECTIONAL);
 
 		if (dma_mapping_error(rx_ring_dma) ||
-			rx_ring_dma + size > B44_DMA_MASK) {
+			rx_ring_dma + size > DMA_30BIT_MASK) {
 			kfree(rx_ring);
 			goto out_err;
 		}
@@ -1254,7 +1253,7 @@
 		                             DMA_TO_DEVICE);
 
 		if (dma_mapping_error(tx_ring_dma) ||
-			tx_ring_dma + size > B44_DMA_MASK) {
+			tx_ring_dma + size > DMA_30BIT_MASK) {
 			kfree(tx_ring);
 			goto out_err;
 		}
@@ -1289,7 +1288,7 @@
 	if (ssb_is_core_up(bp)) {
 		bw32(bp, B44_RCV_LAZY, 0);
 		bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
-		b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 100, 1);
+		b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
 		bw32(bp, B44_DMATX_CTRL, 0);
 		bp->tx_prod = bp->tx_cons = 0;
 		if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK) {
@@ -2151,13 +2150,13 @@
 
 	pci_set_master(pdev);
 
-	err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK);
+	err = pci_set_dma_mask(pdev, (u64) DMA_30BIT_MASK);
 	if (err) {
 		dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
 		goto err_out_free_res;
 	}
 
-	err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
+	err = pci_set_consistent_dma_mask(pdev, (u64) DMA_30BIT_MASK);
 	if (err) {
 		dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
 		goto err_out_free_res;
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 3292316..217a2ee 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -184,7 +184,7 @@
 
 	spin_lock_init(&(bond_info->tx_hashtbl_lock));
 
-	new_hashtbl = kmalloc(size, GFP_KERNEL);
+	new_hashtbl = kzalloc(size, GFP_KERNEL);
 	if (!new_hashtbl) {
 		printk(KERN_ERR DRV_NAME
 		       ": %s: Error: Failed to allocate TLB hash table\n",
@@ -195,8 +195,6 @@
 
 	bond_info->tx_hashtbl = new_hashtbl;
 
-	memset(bond_info->tx_hashtbl, 0, size);
-
 	for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
 		tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
 	}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index d3801a0..a7c8f98 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -35,7 +35,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
@@ -1343,14 +1342,12 @@
 			"inaccurate.\n", bond_dev->name, slave_dev->name);
 	}
 
-	new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL);
+	new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
 	if (!new_slave) {
 		res = -ENOMEM;
 		goto err_undo_flags;
 	}
 
-	memset(new_slave, 0, sizeof(struct slave));
-
 	/* save slave's original flags before calling
 	 * netdev_set_master and dev_open
 	 */
@@ -3122,7 +3119,7 @@
 	return res;
 }
 
-static struct file_operations bond_info_fops = {
+static const struct file_operations bond_info_fops = {
 	.owner   = THIS_MODULE,
 	.open    = bond_info_open,
 	.read    = seq_read,
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 878f7aa..a122baa 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -22,7 +22,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/sysdev.h>
 #include <linux/fs.h>
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index a03d781..8eb5712 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -222,7 +222,6 @@
 #include <linux/module.h>
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
diff --git a/drivers/net/cxgb3/cxgb3_defs.h b/drivers/net/cxgb3/cxgb3_defs.h
index 16e0049..e14862b 100644
--- a/drivers/net/cxgb3/cxgb3_defs.h
+++ b/drivers/net/cxgb3/cxgb3_defs.h
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, 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
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index dfa035a..43583ed65 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -74,8 +74,6 @@
 
 #define EEPROM_MAGIC 0x38E2F10C
 
-#define to_net_dev(class) container_of(class, struct net_device, class_dev)
-
 #define CH_DEVICE(devid, ssid, idx) \
 	{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, ssid, 0, 0, idx }
 
@@ -434,11 +432,12 @@
 	return 0;
 }
 
-static ssize_t attr_show(struct class_device *cd, char *buf,
+static ssize_t attr_show(struct device *d, struct device_attribute *attr,
+			 char *buf,
 			 ssize_t(*format) (struct adapter *, char *))
 {
 	ssize_t len;
-	struct adapter *adap = to_net_dev(cd)->priv;
+	struct adapter *adap = to_net_dev(d)->priv;
 
 	/* Synchronize with ioctls that may shut down the device */
 	rtnl_lock();
@@ -447,14 +446,15 @@
 	return len;
 }
 
-static ssize_t attr_store(struct class_device *cd, const char *buf, size_t len,
+static ssize_t attr_store(struct device *d, struct device_attribute *attr,
+			  const char *buf, size_t len,
 			  ssize_t(*set) (struct adapter *, unsigned int),
 			  unsigned int min_val, unsigned int max_val)
 {
 	char *endp;
 	ssize_t ret;
 	unsigned int val;
-	struct adapter *adap = to_net_dev(cd)->priv;
+	struct adapter *adap = to_net_dev(d)->priv;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -476,9 +476,10 @@
 { \
 	return sprintf(buf, "%u\n", val_expr); \
 } \
-static ssize_t show_##name(struct class_device *cd, char *buf) \
+static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
+			   char *buf) \
 { \
-	return attr_show(cd, buf, format_##name); \
+	return attr_show(d, attr, buf, format_##name); \
 }
 
 static ssize_t set_nfilters(struct adapter *adap, unsigned int val)
@@ -493,10 +494,10 @@
 	return 0;
 }
 
-static ssize_t store_nfilters(struct class_device *cd, const char *buf,
-			      size_t len)
+static ssize_t store_nfilters(struct device *d, struct device_attribute *attr,
+			      const char *buf, size_t len)
 {
-	return attr_store(cd, buf, len, set_nfilters, 0, ~0);
+	return attr_store(d, attr, buf, len, set_nfilters, 0, ~0);
 }
 
 static ssize_t set_nservers(struct adapter *adap, unsigned int val)
@@ -509,38 +510,39 @@
 	return 0;
 }
 
-static ssize_t store_nservers(struct class_device *cd, const char *buf,
-			      size_t len)
+static ssize_t store_nservers(struct device *d, struct device_attribute *attr,
+			      const char *buf, size_t len)
 {
-	return attr_store(cd, buf, len, set_nservers, 0, ~0);
+	return attr_store(d, attr, buf, len, set_nservers, 0, ~0);
 }
 
 #define CXGB3_ATTR_R(name, val_expr) \
 CXGB3_SHOW(name, val_expr) \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
 
 #define CXGB3_ATTR_RW(name, val_expr, store_method) \
 CXGB3_SHOW(name, val_expr) \
-static CLASS_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_method)
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_method)
 
 CXGB3_ATTR_R(cam_size, t3_mc5_size(&adap->mc5));
 CXGB3_ATTR_RW(nfilters, adap->params.mc5.nfilters, store_nfilters);
 CXGB3_ATTR_RW(nservers, adap->params.mc5.nservers, store_nservers);
 
 static struct attribute *cxgb3_attrs[] = {
-	&class_device_attr_cam_size.attr,
-	&class_device_attr_nfilters.attr,
-	&class_device_attr_nservers.attr,
+	&dev_attr_cam_size.attr,
+	&dev_attr_nfilters.attr,
+	&dev_attr_nservers.attr,
 	NULL
 };
 
 static struct attribute_group cxgb3_attr_group = {.attrs = cxgb3_attrs };
 
-static ssize_t tm_attr_show(struct class_device *cd, char *buf, int sched)
+static ssize_t tm_attr_show(struct device *d, struct device_attribute *attr,
+			    char *buf, int sched)
 {
 	ssize_t len;
 	unsigned int v, addr, bpt, cpt;
-	struct adapter *adap = to_net_dev(cd)->priv;
+	struct adapter *adap = to_net_dev(d)->priv;
 
 	addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2;
 	rtnl_lock();
@@ -560,13 +562,13 @@
 	return len;
 }
 
-static ssize_t tm_attr_store(struct class_device *cd, const char *buf,
-			     size_t len, int sched)
+static ssize_t tm_attr_store(struct device *d, struct device_attribute *attr,
+			     const char *buf, size_t len, int sched)
 {
 	char *endp;
 	ssize_t ret;
 	unsigned int val;
-	struct adapter *adap = to_net_dev(cd)->priv;
+	struct adapter *adap = to_net_dev(d)->priv;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -584,15 +586,17 @@
 }
 
 #define TM_ATTR(name, sched) \
-static ssize_t show_##name(struct class_device *cd, char *buf) \
+static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
+			   char *buf) \
 { \
-	return tm_attr_show(cd, buf, sched); \
+	return tm_attr_show(d, attr, buf, sched); \
 } \
-static ssize_t store_##name(struct class_device *cd, const char *buf, size_t len) \
+static ssize_t store_##name(struct device *d, struct device_attribute *attr, \
+			    const char *buf, size_t len) \
 { \
-	return tm_attr_store(cd, buf, len, sched); \
+	return tm_attr_store(d, attr, buf, len, sched); \
 } \
-static CLASS_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)
 
 TM_ATTR(sched0, 0);
 TM_ATTR(sched1, 1);
@@ -604,14 +608,14 @@
 TM_ATTR(sched7, 7);
 
 static struct attribute *offload_attrs[] = {
-	&class_device_attr_sched0.attr,
-	&class_device_attr_sched1.attr,
-	&class_device_attr_sched2.attr,
-	&class_device_attr_sched3.attr,
-	&class_device_attr_sched4.attr,
-	&class_device_attr_sched5.attr,
-	&class_device_attr_sched6.attr,
-	&class_device_attr_sched7.attr,
+	&dev_attr_sched0.attr,
+	&dev_attr_sched1.attr,
+	&dev_attr_sched2.attr,
+	&dev_attr_sched3.attr,
+	&dev_attr_sched4.attr,
+	&dev_attr_sched5.attr,
+	&dev_attr_sched6.attr,
+	&dev_attr_sched7.attr,
 	NULL
 };
 
@@ -753,7 +757,8 @@
 				      t3_intr_handler(adap,
 						      adap->sge.qs[0].rspq.
 						      polling),
-				      (adap->flags & USING_MSI) ? 0 : SA_SHIRQ,
+				      (adap->flags & USING_MSI) ?
+				       0 : IRQF_SHARED,
 				      adap->name, adap)))
 		goto irq_err;
 
@@ -836,7 +841,7 @@
 	init_smt(adapter);
 
 	/* Never mind if the next step fails */
-	sysfs_create_group(&tdev->lldev->class_dev.kobj, &offload_attr_group);
+	sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group);
 
 	/* Call back all registered clients */
 	cxgb3_add_clients(tdev);
@@ -861,7 +866,7 @@
 	/* Call back all registered clients */
 	cxgb3_remove_clients(tdev);
 
-	sysfs_remove_group(&tdev->lldev->class_dev.kobj, &offload_attr_group);
+	sysfs_remove_group(&tdev->lldev->dev.kobj, &offload_attr_group);
 
 	tdev->lldev = NULL;
 	cxgb3_set_dummy_ops(tdev);
@@ -2420,7 +2425,7 @@
 	else if (msi > 0 && pci_enable_msi(pdev) == 0)
 		adapter->flags |= USING_MSI;
 
-	err = sysfs_create_group(&adapter->port[0]->class_dev.kobj,
+	err = sysfs_create_group(&adapter->port[0]->dev.kobj,
 				 &cxgb3_attr_group);
 
 	print_port_info(adapter, ai);
@@ -2452,7 +2457,7 @@
 		struct adapter *adapter = dev->priv;
 
 		t3_sge_stop(adapter);
-		sysfs_remove_group(&adapter->port[0]->class_dev.kobj,
+		sysfs_remove_group(&adapter->port[0]->dev.kobj,
 				   &cxgb3_attr_group);
 
 		for_each_port(adapter, i)
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index c3a02d6..b2cf5f6 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, 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
@@ -396,7 +395,7 @@
 				int n)
 {
 	CH_ERR(tdev2adap(dev), "%d unexpected offload packets, first data %u\n",
-	       n, ntohl(*(u32 *)skbs[0]->data));
+	       n, ntohl(*(__be32 *)skbs[0]->data));
 	while (n--)
 		dev_kfree_skb_any(skbs[n]);
 	return 0;
@@ -755,7 +754,7 @@
 {
 	struct cpl_trace_pkt *p = cplhdr(skb);
 
-	skb->protocol = 0xffff;
+	skb->protocol = htons(0xffff);
 	skb->dev = dev->lldev;
 	skb_pull(skb, sizeof(*p));
 	skb->mac.raw = skb->data;
diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/cxgb3/cxgb3_offload.h
index 0e6beb6..f15446a 100644
--- a/drivers/net/cxgb3/cxgb3_offload.h
+++ b/drivers/net/cxgb3/cxgb3_offload.h
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, 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
diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c
index 3c0cb85..d660af7 100644
--- a/drivers/net/cxgb3/l2t.c
+++ b/drivers/net/cxgb3/l2t.c
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, 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
diff --git a/drivers/net/cxgb3/l2t.h b/drivers/net/cxgb3/l2t.h
index ba5d2cb..d790013 100644
--- a/drivers/net/cxgb3/l2t.h
+++ b/drivers/net/cxgb3/l2t.h
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, 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
diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h
index 9af3bcd..fa4099b 100644
--- a/drivers/net/cxgb3/t3cdev.h
+++ b/drivers/net/cxgb3/t3cdev.h
@@ -1,6 +1,5 @@
 /*
  * Copyright (C) 2006-2007 Chelsio Communications.  All rights reserved.
- * Copyright (C) 2006-2007 Open Grid Computing, 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
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index dc3ab3b..07d2731 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -10,10 +10,12 @@
  *
  * Abstract:
  *   A Linux device driver supporting the Digital Equipment Corporation
- *   FDDI EISA and PCI controller families.  Supported adapters include:
+ *   FDDI TURBOchannel, EISA and PCI controller families.  Supported
+ *   adapters include:
  *
- *		DEC FDDIcontroller/EISA (DEFEA)
- *		DEC FDDIcontroller/PCI  (DEFPA)
+ *		DEC FDDIcontroller/TURBOchannel (DEFTA)
+ *		DEC FDDIcontroller/EISA         (DEFEA)
+ *		DEC FDDIcontroller/PCI          (DEFPA)
  *
  * The original author:
  *   LVS	Lawrence V. Stefani <lstefani@yahoo.com>
@@ -193,24 +195,27 @@
  *		14 Aug 2004	macro		Fix device names reported.
  *		14 Jun 2005	macro		Use irqreturn_t.
  *		23 Oct 2006	macro		Big-endian host support.
+ *		14 Dec 2006	macro		TURBOchannel support.
  */
 
 /* Include files */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/fddidevice.h>
-#include <linux/skbuff.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/eisa.h>
+#include <linux/errno.h>
+#include <linux/fddidevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/tc.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -219,8 +224,8 @@
 
 /* Version information string should be updated prior to each new release!  */
 #define DRV_NAME "defxx"
-#define DRV_VERSION "v1.09"
-#define DRV_RELDATE "2006/10/23"
+#define DRV_VERSION "v1.10"
+#define DRV_RELDATE "2006/12/14"
 
 static char version[] __devinitdata =
 	DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
@@ -235,12 +240,41 @@
  */
 #define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128)
 
+#define __unused __attribute__ ((unused))
+
+#ifdef CONFIG_PCI
+#define DFX_BUS_PCI(dev) (dev->bus == &pci_bus_type)
+#else
+#define DFX_BUS_PCI(dev) 0
+#endif
+
+#ifdef CONFIG_EISA
+#define DFX_BUS_EISA(dev) (dev->bus == &eisa_bus_type)
+#else
+#define DFX_BUS_EISA(dev) 0
+#endif
+
+#ifdef CONFIG_TC
+#define DFX_BUS_TC(dev) (dev->bus == &tc_bus_type)
+#else
+#define DFX_BUS_TC(dev) 0
+#endif
+
+#ifdef CONFIG_DEFXX_MMIO
+#define DFX_MMIO 1
+#else
+#define DFX_MMIO 0
+#endif
+
 /* Define module-wide (static) routines */
 
 static void		dfx_bus_init(struct net_device *dev);
+static void		dfx_bus_uninit(struct net_device *dev);
 static void		dfx_bus_config_check(DFX_board_t *bp);
 
-static int		dfx_driver_init(struct net_device *dev, const char *print_name);
+static int		dfx_driver_init(struct net_device *dev,
+					const char *print_name,
+					resource_size_t bar_start);
 static int		dfx_adap_init(DFX_board_t *bp, int get_buffers);
 
 static int		dfx_open(struct net_device *dev);
@@ -273,13 +307,13 @@
 
 /* Define module-wide (static) variables */
 
-static struct net_device *root_dfx_eisa_dev;
+static struct pci_driver dfx_pci_driver;
+static struct eisa_driver dfx_eisa_driver;
+static struct tc_driver dfx_tc_driver;
 
 
 /*
  * =======================
- * = dfx_port_write_byte =
- * = dfx_port_read_byte	 =
  * = dfx_port_write_long =
  * = dfx_port_read_long  =
  * =======================
@@ -291,12 +325,11 @@
  *   None
  *
  * Arguments:
- *   bp     - pointer to board information
- *   offset - register offset from base I/O address
- *   data   - for dfx_port_write_byte and dfx_port_write_long, this
- *			  is a value to write.
- *			  for dfx_port_read_byte and dfx_port_read_byte, this
- *			  is a pointer to store the read value.
+ *   bp		- pointer to board information
+ *   offset	- register offset from base I/O address
+ *   data	- for dfx_port_write_long, this is a value to write;
+ *		  for dfx_port_read_long, this is a pointer to store
+ *		  the read value
  *
  * Functional Description:
  *   These routines perform the correct operation to read or write
@@ -310,7 +343,7 @@
  *   registers using the register offsets defined in DEFXX.H.
  *
  *   PCI port block base addresses are assigned by the PCI BIOS or system
- *	 firmware.  There is one 128 byte port block which can be accessed.  It
+ *   firmware.  There is one 128 byte port block which can be accessed.  It
  *   allows for I/O mapping of both PDQ and PFI registers using the register
  *   offsets defined in DEFXX.H.
  *
@@ -318,7 +351,7 @@
  *   None
  *
  * Assumptions:
- *   bp->base_addr is a valid base I/O address for this adapter.
+ *   bp->base is a valid base I/O address for this adapter.
  *   offset is a valid register offset for this adapter.
  *
  * Side Effects:
@@ -329,69 +362,135 @@
  *   advantage of strict data type checking.
  */
 
-static inline void dfx_port_write_byte(
-	DFX_board_t	*bp,
-	int			offset,
-	u8			data
-	)
+static inline void dfx_writel(DFX_board_t *bp, int offset, u32 data)
+{
+	writel(data, bp->base.mem + offset);
+	mb();
+}
 
-	{
-	u16 port = bp->base_addr + offset;
+static inline void dfx_outl(DFX_board_t *bp, int offset, u32 data)
+{
+	outl(data, bp->base.port + offset);
+}
 
-	outb(data, port);
-	}
+static void dfx_port_write_long(DFX_board_t *bp, int offset, u32 data)
+{
+	struct device __unused *bdev = bp->bus_dev;
+	int dfx_bus_tc = DFX_BUS_TC(bdev);
+	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
 
-static inline void dfx_port_read_byte(
-	DFX_board_t	*bp,
-	int			offset,
-	u8			*data
-	)
+	if (dfx_use_mmio)
+		dfx_writel(bp, offset, data);
+	else
+		dfx_outl(bp, offset, data);
+}
 
-	{
-	u16 port = bp->base_addr + offset;
 
-	*data = inb(port);
-	}
+static inline void dfx_readl(DFX_board_t *bp, int offset, u32 *data)
+{
+	mb();
+	*data = readl(bp->base.mem + offset);
+}
 
-static inline void dfx_port_write_long(
-	DFX_board_t	*bp,
-	int			offset,
-	u32			data
-	)
+static inline void dfx_inl(DFX_board_t *bp, int offset, u32 *data)
+{
+	*data = inl(bp->base.port + offset);
+}
 
-	{
-	u16 port = bp->base_addr + offset;
+static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
+{
+	struct device __unused *bdev = bp->bus_dev;
+	int dfx_bus_tc = DFX_BUS_TC(bdev);
+	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
 
-	outl(data, port);
-	}
-
-static inline void dfx_port_read_long(
-	DFX_board_t	*bp,
-	int			offset,
-	u32			*data
-	)
-
-	{
-	u16 port = bp->base_addr + offset;
-
-	*data = inl(port);
-	}
+	if (dfx_use_mmio)
+		dfx_readl(bp, offset, data);
+	else
+		dfx_inl(bp, offset, data);
+}
 
 
 /*
- * =============
- * = dfx_init_one_pci_or_eisa =
- * =============
+ * ================
+ * = dfx_get_bars =
+ * ================
  *
  * Overview:
- *   Initializes a supported FDDI EISA or PCI controller
+ *   Retrieves the address range used to access control and status
+ *   registers.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bdev	- pointer to device information
+ *   bar_start	- pointer to store the start address
+ *   bar_len	- pointer to store the length of the area
+ *
+ * Assumptions:
+ *   I am sure there are some.
+ *
+ * Side Effects:
+ *   None
+ */
+static void dfx_get_bars(struct device *bdev,
+			 resource_size_t *bar_start, resource_size_t *bar_len)
+{
+	int dfx_bus_pci = DFX_BUS_PCI(bdev);
+	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+	int dfx_bus_tc = DFX_BUS_TC(bdev);
+	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+
+	if (dfx_bus_pci) {
+		int num = dfx_use_mmio ? 0 : 1;
+
+		*bar_start = pci_resource_start(to_pci_dev(bdev), num);
+		*bar_len = pci_resource_len(to_pci_dev(bdev), num);
+	}
+	if (dfx_bus_eisa) {
+		unsigned long base_addr = to_eisa_device(bdev)->base_addr;
+		resource_size_t bar;
+
+		if (dfx_use_mmio) {
+			bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2);
+			bar <<= 8;
+			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1);
+			bar <<= 8;
+			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0);
+			bar <<= 16;
+			*bar_start = bar;
+			bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2);
+			bar <<= 8;
+			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1);
+			bar <<= 8;
+			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0);
+			bar <<= 16;
+			*bar_len = (bar | PI_MEM_ADD_MASK_M) + 1;
+		} else {
+			*bar_start = base_addr;
+			*bar_len = PI_ESIC_K_CSR_IO_LEN;
+		}
+	}
+	if (dfx_bus_tc) {
+		*bar_start = to_tc_dev(bdev)->resource.start +
+			     PI_TC_K_CSR_OFFSET;
+		*bar_len = PI_TC_K_CSR_LEN;
+	}
+}
+
+/*
+ * ================
+ * = dfx_register =
+ * ================
+ *
+ * Overview:
+ *   Initializes a supported FDDI controller
  *
  * Returns:
  *   Condition code
  *
  * Arguments:
- *   pdev - pointer to pci device information (NULL for EISA)
- *   ioaddr - pointer to port (NULL for PCI)
+ *   bdev - pointer to device information
  *
  * Functional Description:
  *
@@ -407,56 +506,74 @@
  *   initialized and the board resources are read and stored in
  *   the device structure.
  */
-static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr)
+static int __devinit dfx_register(struct device *bdev)
 {
 	static int version_disp;
-	char *print_name = DRV_NAME;
+	int dfx_bus_pci = DFX_BUS_PCI(bdev);
+	int dfx_bus_tc = DFX_BUS_TC(bdev);
+	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+	char *print_name = bdev->bus_id;
 	struct net_device *dev;
 	DFX_board_t	  *bp;			/* board pointer */
+	resource_size_t bar_start = 0;		/* pointer to port */
+	resource_size_t bar_len = 0;		/* resource length */
 	int alloc_size;				/* total buffer size used */
-	int err;
+	struct resource *region;
+	int err = 0;
 
 	if (!version_disp) {	/* display version info if adapter is found */
 		version_disp = 1;	/* set display flag to TRUE so that */
 		printk(version);	/* we only display this string ONCE */
 	}
 
-	if (pdev != NULL)
-		print_name = pci_name(pdev);
-
 	dev = alloc_fddidev(sizeof(*bp));
 	if (!dev) {
-		printk(KERN_ERR "%s: unable to allocate fddidev, aborting\n",
+		printk(KERN_ERR "%s: Unable to allocate fddidev, aborting\n",
 		       print_name);
 		return -ENOMEM;
 	}
 
 	/* Enable PCI device. */
-	if (pdev != NULL) {
-		err = pci_enable_device (pdev);
-		if (err) goto err_out;
-		ioaddr = pci_resource_start (pdev, 1);
-	}
-
-	SET_MODULE_OWNER(dev);
-	if (pdev != NULL)
-		SET_NETDEV_DEV(dev, &pdev->dev);
-
-	bp = dev->priv;
-
-	if (!request_region(ioaddr,
-			    pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN,
-			    print_name)) {
-		printk(KERN_ERR "%s: Cannot reserve I/O resource "
-		       "0x%x @ 0x%lx, aborting\n", print_name,
-		       pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, ioaddr);
-		err = -EBUSY;
+	if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) {
+		printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n",
+		       print_name);
 		goto err_out;
 	}
 
-	/* Initialize new device structure */
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, bdev);
 
-	dev->base_addr			= ioaddr; /* save port (I/O) base address */
+	bp = netdev_priv(dev);
+	bp->bus_dev = bdev;
+	dev_set_drvdata(bdev, dev);
+
+	dfx_get_bars(bdev, &bar_start, &bar_len);
+
+	if (dfx_use_mmio)
+		region = request_mem_region(bar_start, bar_len, print_name);
+	else
+		region = request_region(bar_start, bar_len, print_name);
+	if (!region) {
+		printk(KERN_ERR "%s: Cannot reserve I/O resource "
+		       "0x%lx @ 0x%lx, aborting\n",
+		       print_name, (long)bar_len, (long)bar_start);
+		err = -EBUSY;
+		goto err_out_disable;
+	}
+
+	/* Set up I/O base address. */
+	if (dfx_use_mmio) {
+		bp->base.mem = ioremap_nocache(bar_start, bar_len);
+		if (!bp->base.mem) {
+			printk(KERN_ERR "%s: Cannot map MMIO\n", print_name);
+			goto err_out_region;
+		}
+	} else {
+		bp->base.port = bar_start;
+		dev->base_addr = bar_start;
+	}
+
+	/* Initialize new device structure */
 
 	dev->get_stats			= dfx_ctl_get_stats;
 	dev->open			= dfx_open;
@@ -465,22 +582,12 @@
 	dev->set_multicast_list		= dfx_ctl_set_multicast_list;
 	dev->set_mac_address		= dfx_ctl_set_mac_address;
 
-	if (pdev == NULL) {
-		/* EISA board */
-		bp->bus_type = DFX_BUS_TYPE_EISA;
-		bp->next = root_dfx_eisa_dev;
-		root_dfx_eisa_dev = dev;
-	} else {
-		/* PCI board */
-		bp->bus_type = DFX_BUS_TYPE_PCI;
-		bp->pci_dev = pdev;
-		pci_set_drvdata (pdev, dev);
-		pci_set_master (pdev);
-	}
+	if (dfx_bus_pci)
+		pci_set_master(to_pci_dev(bdev));
 
-	if (dfx_driver_init(dev, print_name) != DFX_K_SUCCESS) {
+	if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) {
 		err = -ENODEV;
-		goto err_out_region;
+		goto err_out_unmap;
 	}
 
 	err = register_netdev(dev);
@@ -499,44 +606,28 @@
 		     sizeof(PI_CONSUMER_BLOCK) +
 		     (PI_ALIGN_K_DESC_BLK - 1);
 	if (bp->kmalloced)
-		pci_free_consistent(pdev, alloc_size,
-				    bp->kmalloced, bp->kmalloced_dma);
+		dma_free_coherent(bdev, alloc_size,
+				  bp->kmalloced, bp->kmalloced_dma);
+
+err_out_unmap:
+	if (dfx_use_mmio)
+		iounmap(bp->base.mem);
+
 err_out_region:
-	release_region(ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN);
+	if (dfx_use_mmio)
+		release_mem_region(bar_start, bar_len);
+	else
+		release_region(bar_start, bar_len);
+
+err_out_disable:
+	if (dfx_bus_pci)
+		pci_disable_device(to_pci_dev(bdev));
+
 err_out:
 	free_netdev(dev);
 	return err;
 }
 
-static int __devinit dfx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	return dfx_init_one_pci_or_eisa(pdev, 0);
-}
-
-static int __init dfx_eisa_init(void)
-{
-	int rc = -ENODEV;
-	int i;			/* used in for loops */
-	u16 port;		/* temporary I/O (port) address */
-	u32 slot_id;		/* EISA hardware (slot) ID read from adapter */
-
-	DBG_printk("In dfx_eisa_init...\n");
-
-	/* Scan for FDDI EISA controllers */
-
-	for (i=0; i < DFX_MAX_EISA_SLOTS; i++)		/* only scan for up to 16 EISA slots */
-	{
-		port = (i << 12) + PI_ESIC_K_SLOT_ID;	/* port = I/O address for reading slot ID */
-		slot_id = inl(port);					/* read EISA HW (slot) ID */
-		if ((slot_id & 0xF0FFFFFF) == DEFEA_PRODUCT_ID)
-		{
-			port = (i << 12);					/* recalc base addr */
-
-			if (dfx_init_one_pci_or_eisa(NULL, port) == 0) rc = 0;
-		}
-	}
-	return rc;
-}
 
 /*
  * ================
@@ -544,7 +635,7 @@
  * ================
  *
  * Overview:
- *   Initializes EISA and PCI controller bus-specific logic.
+ *   Initializes the bus-specific controller logic.
  *
  * Returns:
  *   None
@@ -560,7 +651,7 @@
  *   None
  *
  * Assumptions:
- *   dev->base_addr has already been set with the proper
+ *   bp->base has already been set with the proper
  *	 base I/O address for this device.
  *
  * Side Effects:
@@ -571,87 +662,103 @@
 
 static void __devinit dfx_bus_init(struct net_device *dev)
 {
-	DFX_board_t *bp = dev->priv;
-	u8			val;	/* used for I/O read/writes */
+	DFX_board_t *bp = netdev_priv(dev);
+	struct device *bdev = bp->bus_dev;
+	int dfx_bus_pci = DFX_BUS_PCI(bdev);
+	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+	int dfx_bus_tc = DFX_BUS_TC(bdev);
+	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+	u8 val;
 
 	DBG_printk("In dfx_bus_init...\n");
 
-	/*
-	 * Initialize base I/O address field in bp structure
-	 *
-	 * Note: bp->base_addr is the same as dev->base_addr.
-	 *		 It's useful because often we'll need to read
-	 *		 or write registers where we already have the
-	 *		 bp pointer instead of the dev pointer.  Having
-	 *		 the base address in the bp structure will
-	 *		 save a pointer dereference.
-	 *
-	 *		 IMPORTANT!! This field must be defined before
-	 *		 any of the dfx_port_* inline functions are
-	 *		 called.
-	 */
-
-	bp->base_addr = dev->base_addr;
-
-	/* And a pointer back to the net_device struct */
+	/* Initialize a pointer back to the net_device struct */
 	bp->dev = dev;
 
 	/* Initialize adapter based on bus type */
 
-	if (bp->bus_type == DFX_BUS_TYPE_EISA)
-		{
-		/* Get the interrupt level from the ESIC chip */
+	if (dfx_bus_tc)
+		dev->irq = to_tc_dev(bdev)->interrupt;
+	if (dfx_bus_eisa) {
+		unsigned long base_addr = to_eisa_device(bdev)->base_addr;
 
-		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val);
-		switch ((val & PI_CONFIG_STAT_0_M_IRQ) >> PI_CONFIG_STAT_0_V_IRQ)
-			{
-			case PI_CONFIG_STAT_0_IRQ_K_9:
-				dev->irq = 9;
-				break;
+		/* Get the interrupt level from the ESIC chip.  */
+		val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+		val &= PI_CONFIG_STAT_0_M_IRQ;
+		val >>= PI_CONFIG_STAT_0_V_IRQ;
 
-			case PI_CONFIG_STAT_0_IRQ_K_10:
-				dev->irq = 10;
-				break;
+		switch (val) {
+		case PI_CONFIG_STAT_0_IRQ_K_9:
+			dev->irq = 9;
+			break;
 
-			case PI_CONFIG_STAT_0_IRQ_K_11:
-				dev->irq = 11;
-				break;
+		case PI_CONFIG_STAT_0_IRQ_K_10:
+			dev->irq = 10;
+			break;
 
-			case PI_CONFIG_STAT_0_IRQ_K_15:
-				dev->irq = 15;
-				break;
-			}
+		case PI_CONFIG_STAT_0_IRQ_K_11:
+			dev->irq = 11;
+			break;
 
-		/* Enable access to I/O on the board by writing 0x03 to Function Control Register */
-
-		dfx_port_write_byte(bp, PI_ESIC_K_FUNCTION_CNTRL, PI_ESIC_K_FUNCTION_CNTRL_IO_ENB);
-
-		/* Set the I/O decode range of the board */
-
-		val = ((dev->base_addr >> 12) << PI_IO_CMP_V_SLOT);
-		dfx_port_write_byte(bp, PI_ESIC_K_IO_CMP_0_1, val);
-		dfx_port_write_byte(bp, PI_ESIC_K_IO_CMP_1_1, val);
-
-		/* Enable access to rest of module (including PDQ and packet memory) */
-
-		dfx_port_write_byte(bp, PI_ESIC_K_SLOT_CNTRL, PI_SLOT_CNTRL_M_ENB);
+		case PI_CONFIG_STAT_0_IRQ_K_15:
+			dev->irq = 15;
+			break;
+		}
 
 		/*
-		 * Map PDQ registers into I/O space.  This is done by clearing a bit
-		 * in Burst Holdoff register.
+		 * Enable memory decoding (MEMCS0) and/or port decoding
+		 * (IOCS1/IOCS0) as appropriate in Function Control
+		 * Register.  One of the port chip selects seems to be
+		 * used for the Burst Holdoff register, but this bit of
+		 * documentation is missing and as yet it has not been
+		 * determined which of the two.  This is also the reason
+		 * the size of the decoded port range is twice as large
+		 * as one required by the PDQ.
 		 */
 
-		dfx_port_read_byte(bp, PI_ESIC_K_BURST_HOLDOFF, &val);
-		dfx_port_write_byte(bp, PI_ESIC_K_BURST_HOLDOFF, (val & ~PI_BURST_HOLDOFF_M_MEM_MAP));
+		/* Set the decode range of the board.  */
+		val = ((bp->base.port >> 12) << PI_IO_CMP_V_SLOT);
+		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_1, val);
+		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_0, 0);
+		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_1, val);
+		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_0, 0);
+		val = PI_ESIC_K_CSR_IO_LEN - 1;
+		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_1, (val >> 8) & 0xff);
+		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_0, val & 0xff);
+		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_1, (val >> 8) & 0xff);
+		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_0, val & 0xff);
+
+		/* Enable the decoders.  */
+		val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0;
+		if (dfx_use_mmio)
+			val |= PI_FUNCTION_CNTRL_M_MEMCS0;
+		outb(base_addr + PI_ESIC_K_FUNCTION_CNTRL, val);
+
+		/*
+		 * Enable access to the rest of the module
+		 * (including PDQ and packet memory).
+		 */
+		val = PI_SLOT_CNTRL_M_ENB;
+		outb(base_addr + PI_ESIC_K_SLOT_CNTRL, val);
+
+		/*
+		 * Map PDQ registers into memory or port space.  This is
+		 * done with a bit in the Burst Holdoff register.
+		 */
+		val = inb(base_addr + PI_DEFEA_K_BURST_HOLDOFF);
+		if (dfx_use_mmio)
+			val |= PI_BURST_HOLDOFF_V_MEM_MAP;
+		else
+			val &= ~PI_BURST_HOLDOFF_V_MEM_MAP;
+		outb(base_addr + PI_DEFEA_K_BURST_HOLDOFF, val);
 
 		/* Enable interrupts at EISA bus interface chip (ESIC) */
-
-		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val);
-		dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, (val | PI_CONFIG_STAT_0_M_INT_ENB));
-		}
-	else
-		{
-		struct pci_dev *pdev = bp->pci_dev;
+		val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+		val |= PI_CONFIG_STAT_0_M_INT_ENB;
+		outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);
+	}
+	if (dfx_bus_pci) {
+		struct pci_dev *pdev = to_pci_dev(bdev);
 
 		/* Get the interrupt level from the PCI Configuration Table */
 
@@ -660,17 +767,70 @@
 		/* Check Latency Timer and set if less than minimal */
 
 		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val);
-		if (val < PFI_K_LAT_TIMER_MIN)	/* if less than min, override with default */
-			{
+		if (val < PFI_K_LAT_TIMER_MIN) {
 			val = PFI_K_LAT_TIMER_DEF;
 			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val);
-			}
+		}
 
 		/* Enable interrupts at PCI bus interface chip (PFI) */
-
-		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, (PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB));
-		}
+		val = PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB;
+		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, val);
 	}
+}
+
+/*
+ * ==================
+ * = dfx_bus_uninit =
+ * ==================
+ *
+ * Overview:
+ *   Uninitializes the bus-specific controller logic.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Perform bus-specific logic uninitialization.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   bp->base has already been set with the proper
+ *	 base I/O address for this device.
+ *
+ * Side Effects:
+ *   Interrupts are disabled at the adapter bus-specific logic.
+ */
+
+static void __devinit dfx_bus_uninit(struct net_device *dev)
+{
+	DFX_board_t *bp = netdev_priv(dev);
+	struct device *bdev = bp->bus_dev;
+	int dfx_bus_pci = DFX_BUS_PCI(bdev);
+	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+	u8 val;
+
+	DBG_printk("In dfx_bus_uninit...\n");
+
+	/* Uninitialize adapter based on bus type */
+
+	if (dfx_bus_eisa) {
+		unsigned long base_addr = to_eisa_device(bdev)->base_addr;
+
+		/* Disable interrupts at EISA bus interface chip (ESIC) */
+		val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+		val &= ~PI_CONFIG_STAT_0_M_INT_ENB;
+		outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);
+	}
+	if (dfx_bus_pci) {
+		/* Disable interrupts at PCI bus interface chip (PFI) */
+		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, 0);
+	}
+}
 
 
 /*
@@ -705,18 +865,16 @@
 
 static void __devinit dfx_bus_config_check(DFX_board_t *bp)
 {
+	struct device __unused *bdev = bp->bus_dev;
+	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
 	int	status;				/* return code from adapter port control call */
-	u32	slot_id;			/* EISA-bus hardware id (DEC3001, DEC3002,...) */
 	u32	host_data;			/* LW data returned from port control call */
 
 	DBG_printk("In dfx_bus_config_check...\n");
 
 	/* Configuration check only valid for EISA adapter */
 
-	if (bp->bus_type == DFX_BUS_TYPE_EISA)
-		{
-		dfx_port_read_long(bp, PI_ESIC_K_SLOT_ID, &slot_id);
-
+	if (dfx_bus_eisa) {
 		/*
 		 * First check if revision 2 EISA controller.  Rev. 1 cards used
 		 * PDQ revision B, so no workaround needed in this case.  Rev. 3
@@ -724,14 +882,11 @@
 		 * case, either.  Only Rev. 2 cards used either Rev. D or E
 		 * chips, so we must verify the chip revision on Rev. 2 cards.
 		 */
-
-		if (slot_id == DEFEA_PROD_ID_2)
-			{
+		if (to_eisa_device(bdev)->id.driver_data == DEFEA_PROD_ID_2) {
 			/*
-			 * Revision 2 FDDI EISA controller found, so let's check PDQ
-			 * revision of adapter.
+			 * Revision 2 FDDI EISA controller found,
+			 * so let's check PDQ revision of adapter.
 			 */
-
 			status = dfx_hw_port_ctrl_req(bp,
 											PI_PCTRL_M_SUB_CMD,
 											PI_SUB_CMD_K_PDQ_REV_GET,
@@ -805,13 +960,20 @@
  */
 
 static int __devinit dfx_driver_init(struct net_device *dev,
-				     const char *print_name)
+				     const char *print_name,
+				     resource_size_t bar_start)
 {
-	DFX_board_t *bp = dev->priv;
-	int			alloc_size;			/* total buffer size needed */
-	char		*top_v, *curr_v;	/* virtual addrs into memory block */
-	dma_addr_t		top_p, curr_p;		/* physical addrs into memory block */
-	u32			data;				/* host data register value */
+	DFX_board_t *bp = netdev_priv(dev);
+	struct device *bdev = bp->bus_dev;
+	int dfx_bus_pci = DFX_BUS_PCI(bdev);
+	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+	int dfx_bus_tc = DFX_BUS_TC(bdev);
+	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+	int alloc_size;			/* total buffer size needed */
+	char *top_v, *curr_v;		/* virtual addrs into memory block */
+	dma_addr_t top_p, curr_p;	/* physical addrs into memory block */
+	u32 data, le32;			/* host data register value */
+	char *board_name = NULL;
 
 	DBG_printk("In dfx_driver_init...\n");
 
@@ -860,8 +1022,8 @@
 		       print_name);
 		return(DFX_K_FAILURE);
 	}
-	data = cpu_to_le32(data);
-	memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32));
+	le32 = cpu_to_le32(data);
+	memcpy(&bp->factory_mac_addr[0], &le32, sizeof(u32));
 
 	if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0,
 				 &data) != DFX_K_SUCCESS) {
@@ -869,8 +1031,8 @@
 		       print_name);
 		return(DFX_K_FAILURE);
 	}
-	data = cpu_to_le32(data);
-	memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16));
+	le32 = cpu_to_le32(data);
+	memcpy(&bp->factory_mac_addr[4], &le32, sizeof(u16));
 
 	/*
 	 * Set current address to factory address
@@ -880,20 +1042,18 @@
 	 */
 
 	memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
-	if (bp->bus_type == DFX_BUS_TYPE_EISA)
-		printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, "
-		       "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
-		       print_name, dev->base_addr, dev->irq,
-		       dev->dev_addr[0], dev->dev_addr[1],
-		       dev->dev_addr[2], dev->dev_addr[3],
-		       dev->dev_addr[4], dev->dev_addr[5]);
-	else
-		printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, "
-		       "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
-		       print_name, dev->base_addr, dev->irq,
-		       dev->dev_addr[0], dev->dev_addr[1],
-		       dev->dev_addr[2], dev->dev_addr[3],
-		       dev->dev_addr[4], dev->dev_addr[5]);
+	if (dfx_bus_tc)
+		board_name = "DEFTA";
+	if (dfx_bus_eisa)
+		board_name = "DEFEA";
+	if (dfx_bus_pci)
+		board_name = "DEFPA";
+	pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, "
+		"Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
+		print_name, board_name, dfx_use_mmio ? "" : "I/O ",
+		(long long)bar_start, dev->irq,
+		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
 	/*
 	 * Get memory for descriptor block, consumer block, and other buffers
@@ -908,8 +1068,9 @@
 #endif
 					sizeof(PI_CONSUMER_BLOCK) +
 					(PI_ALIGN_K_DESC_BLK - 1);
-	bp->kmalloced = top_v = pci_alloc_consistent(bp->pci_dev, alloc_size,
-						     &bp->kmalloced_dma);
+	bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size,
+						   &bp->kmalloced_dma,
+						   GFP_ATOMIC);
 	if (top_v == NULL) {
 		printk("%s: Could not allocate memory for host buffers "
 		       "and structures!\n", print_name);
@@ -1219,14 +1380,15 @@
 
 static int dfx_open(struct net_device *dev)
 {
+	DFX_board_t *bp = netdev_priv(dev);
 	int ret;
-	DFX_board_t	*bp = dev->priv;
 
 	DBG_printk("In dfx_open...\n");
 
 	/* Register IRQ - support shared interrupts by passing device ptr */
 
-	ret = request_irq(dev->irq, dfx_interrupt, IRQF_SHARED, dev->name, dev);
+	ret = request_irq(dev->irq, dfx_interrupt, IRQF_SHARED, dev->name,
+			  dev);
 	if (ret) {
 		printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
 		return ret;
@@ -1309,7 +1471,7 @@
 
 static int dfx_close(struct net_device *dev)
 {
-	DFX_board_t	*bp = dev->priv;
+	DFX_board_t *bp = netdev_priv(dev);
 
 	DBG_printk("In dfx_close...\n");
 
@@ -1645,7 +1807,7 @@
 
 static void dfx_int_common(struct net_device *dev)
 {
-	DFX_board_t 	*bp = dev->priv;
+	DFX_board_t *bp = netdev_priv(dev);
 	PI_UINT32	port_status;		/* Port Status register */
 
 	/* Process xmt interrupts - frequent case, so always call this routine */
@@ -1715,18 +1877,16 @@
 
 static irqreturn_t dfx_interrupt(int irq, void *dev_id)
 {
-	struct net_device	*dev = dev_id;
-	DFX_board_t		*bp;	/* private board structure pointer */
-
-	/* Get board pointer only if device structure is valid */
-
-	bp = dev->priv;
-
-	/* See if we're already servicing an interrupt */
+	struct net_device *dev = dev_id;
+	DFX_board_t *bp = netdev_priv(dev);
+	struct device *bdev = bp->bus_dev;
+	int dfx_bus_pci = DFX_BUS_PCI(bdev);
+	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+	int dfx_bus_tc = DFX_BUS_TC(bdev);
 
 	/* Service adapter interrupts */
 
-	if (bp->bus_type == DFX_BUS_TYPE_PCI) {
+	if (dfx_bus_pci) {
 		u32 status;
 
 		dfx_port_read_long(bp, PFI_K_REG_STATUS, &status);
@@ -1750,10 +1910,12 @@
 				     PFI_MODE_M_DMA_ENB));
 
 		spin_unlock(&bp->lock);
-	} else {
+	}
+	if (dfx_bus_eisa) {
+		unsigned long base_addr = to_eisa_device(bdev)->base_addr;
 		u8 status;
 
-		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status);
+		status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
 		if (!(status & PI_CONFIG_STAT_0_M_PEND))
 			return IRQ_NONE;
 
@@ -1761,15 +1923,35 @@
 
 		/* Disable interrupts at the ESIC */
 		status &= ~PI_CONFIG_STAT_0_M_INT_ENB;
-		dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status);
+		outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status);
 
 		/* Call interrupt service routine for this adapter */
 		dfx_int_common(dev);
 
 		/* Reenable interrupts at the ESIC */
-		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status);
+		status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
 		status |= PI_CONFIG_STAT_0_M_INT_ENB;
-		dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status);
+		outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status);
+
+		spin_unlock(&bp->lock);
+	}
+	if (dfx_bus_tc) {
+		u32 status;
+
+		dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &status);
+		if (!(status & (PI_PSTATUS_M_RCV_DATA_PENDING |
+				PI_PSTATUS_M_XMT_DATA_PENDING |
+				PI_PSTATUS_M_SMT_HOST_PENDING |
+				PI_PSTATUS_M_UNSOL_PENDING |
+				PI_PSTATUS_M_CMD_RSP_PENDING |
+				PI_PSTATUS_M_CMD_REQ_PENDING |
+				PI_PSTATUS_M_TYPE_0_PENDING)))
+			return IRQ_NONE;
+
+		spin_lock(&bp->lock);
+
+		/* Call interrupt service routine for this adapter */
+		dfx_int_common(dev);
 
 		spin_unlock(&bp->lock);
 	}
@@ -1823,7 +2005,7 @@
 
 static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
 	{
-	DFX_board_t	*bp = dev->priv;
+	DFX_board_t *bp = netdev_priv(dev);
 
 	/* Fill the bp->stats structure with driver-maintained counters */
 
@@ -2009,8 +2191,8 @@
  */
 
 static void dfx_ctl_set_multicast_list(struct net_device *dev)
-	{
-	DFX_board_t			*bp = dev->priv;
+{
+	DFX_board_t *bp = netdev_priv(dev);
 	int					i;			/* used as index in for loop */
 	struct dev_mc_list	*dmi;		/* ptr to multicast addr entry */
 
@@ -2124,8 +2306,8 @@
 
 static int dfx_ctl_set_mac_address(struct net_device *dev, void *addr)
 	{
-	DFX_board_t		*bp = dev->priv;
 	struct sockaddr	*p_sockaddr = (struct sockaddr *)addr;
+	DFX_board_t *bp = netdev_priv(dev);
 
 	/* Copy unicast address to driver-maintained structs and update count */
 
@@ -2764,9 +2946,9 @@
 
 			my_skb_align(newskb, 128);
 			bp->descr_block_virt->rcv_data[i + j].long_1 =
-				(u32)pci_map_single(bp->pci_dev, newskb->data,
+				(u32)dma_map_single(bp->bus_dev, newskb->data,
 						    NEW_SKB_SIZE,
-						    PCI_DMA_FROMDEVICE);
+						    DMA_FROM_DEVICE);
 			/*
 			 * p_rcv_buff_va is only used inside the
 			 * kernel so we put the skb pointer here.
@@ -2880,17 +3062,17 @@
 
 						my_skb_align(newskb, 128);
 						skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
-						pci_unmap_single(bp->pci_dev,
+						dma_unmap_single(bp->bus_dev,
 							bp->descr_block_virt->rcv_data[entry].long_1,
 							NEW_SKB_SIZE,
-							PCI_DMA_FROMDEVICE);
+							DMA_FROM_DEVICE);
 						skb_reserve(skb, RCV_BUFF_K_PADDING);
 						bp->p_rcv_buff_va[entry] = (char *)newskb;
 						bp->descr_block_virt->rcv_data[entry].long_1 =
-							(u32)pci_map_single(bp->pci_dev,
+							(u32)dma_map_single(bp->bus_dev,
 								newskb->data,
 								NEW_SKB_SIZE,
-								PCI_DMA_FROMDEVICE);
+								DMA_FROM_DEVICE);
 					} else
 						skb = NULL;
 				} else
@@ -3010,7 +3192,7 @@
 	)
 
 	{
-	DFX_board_t		*bp = dev->priv;
+	DFX_board_t		*bp = netdev_priv(dev);
 	u8			prod;				/* local transmit producer index */
 	PI_XMT_DESCR		*p_xmt_descr;		/* ptr to transmit descriptor block entry */
 	XMT_DRIVER_DESCR	*p_xmt_drv_descr;	/* ptr to transmit driver descriptor */
@@ -3116,8 +3298,8 @@
 	 */
 
 	p_xmt_descr->long_0	= (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN));
-	p_xmt_descr->long_1 = (u32)pci_map_single(bp->pci_dev, skb->data,
-						  skb->len, PCI_DMA_TODEVICE);
+	p_xmt_descr->long_1 = (u32)dma_map_single(bp->bus_dev, skb->data,
+						  skb->len, DMA_TO_DEVICE);
 
 	/*
 	 * Verify that descriptor is actually available
@@ -3220,10 +3402,10 @@
 
 		/* Return skb to operating system */
 		comp = bp->rcv_xmt_reg.index.xmt_comp;
-		pci_unmap_single(bp->pci_dev,
+		dma_unmap_single(bp->bus_dev,
 				 bp->descr_block_virt->xmt_data[comp].long_1,
 				 p_xmt_drv_descr->p_skb->len,
-				 PCI_DMA_TODEVICE);
+				 DMA_TO_DEVICE);
 		dev_kfree_skb_irq(p_xmt_drv_descr->p_skb);
 
 		/*
@@ -3344,10 +3526,10 @@
 
 		/* Return skb to operating system */
 		comp = bp->rcv_xmt_reg.index.xmt_comp;
-		pci_unmap_single(bp->pci_dev,
+		dma_unmap_single(bp->bus_dev,
 				 bp->descr_block_virt->xmt_data[comp].long_1,
 				 p_xmt_drv_descr->p_skb->len,
-				 PCI_DMA_TODEVICE);
+				 DMA_TO_DEVICE);
 		dev_kfree_skb(p_xmt_drv_descr->p_skb);
 
 		/* Increment transmit error counter */
@@ -3375,13 +3557,44 @@
 	bp->cons_block_virt->xmt_rcv_data = prod_cons;
 	}
 
-static void __devexit dfx_remove_one_pci_or_eisa(struct pci_dev *pdev, struct net_device *dev)
+/*
+ * ==================
+ * = dfx_unregister =
+ * ==================
+ *
+ * Overview:
+ *   Shuts down an FDDI controller
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   bdev - pointer to device information
+ *
+ * Functional Description:
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   It compiles so it should work :-( (PCI cards do :-)
+ *
+ * Side Effects:
+ *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
+ *   freed.
+ */
+static void __devexit dfx_unregister(struct device *bdev)
 {
-	DFX_board_t	*bp = dev->priv;
+	struct net_device *dev = dev_get_drvdata(bdev);
+	DFX_board_t *bp = netdev_priv(dev);
+	int dfx_bus_pci = DFX_BUS_PCI(bdev);
+	int dfx_bus_tc = DFX_BUS_TC(bdev);
+	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+	resource_size_t bar_start = 0;		/* pointer to port */
+	resource_size_t bar_len = 0;		/* resource length */
 	int		alloc_size;		/* total buffer size used */
 
 	unregister_netdev(dev);
-	release_region(dev->base_addr,  pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN );
 
 	alloc_size = sizeof(PI_DESCR_BLOCK) +
 		     PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +
@@ -3391,78 +3604,141 @@
 		     sizeof(PI_CONSUMER_BLOCK) +
 		     (PI_ALIGN_K_DESC_BLK - 1);
 	if (bp->kmalloced)
-		pci_free_consistent(pdev, alloc_size, bp->kmalloced,
-				    bp->kmalloced_dma);
+		dma_free_coherent(bdev, alloc_size,
+				  bp->kmalloced, bp->kmalloced_dma);
+
+	dfx_bus_uninit(dev);
+
+	dfx_get_bars(bdev, &bar_start, &bar_len);
+	if (dfx_use_mmio) {
+		iounmap(bp->base.mem);
+		release_mem_region(bar_start, bar_len);
+	} else
+		release_region(bar_start, bar_len);
+
+	if (dfx_bus_pci)
+		pci_disable_device(to_pci_dev(bdev));
+
 	free_netdev(dev);
 }
 
-static void __devexit dfx_remove_one (struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
 
-	dfx_remove_one_pci_or_eisa(pdev, dev);
-	pci_set_drvdata(pdev, NULL);
-}
+static int __devinit __unused dfx_dev_register(struct device *);
+static int __devexit __unused dfx_dev_unregister(struct device *);
 
-static struct pci_device_id dfx_pci_tbl[] = {
-	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0, }
+#ifdef CONFIG_PCI
+static int __devinit dfx_pci_register(struct pci_dev *,
+				      const struct pci_device_id *);
+static void __devexit dfx_pci_unregister(struct pci_dev *);
+
+static struct pci_device_id dfx_pci_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) },
+	{ }
 };
-MODULE_DEVICE_TABLE(pci, dfx_pci_tbl);
+MODULE_DEVICE_TABLE(pci, dfx_pci_table);
 
-static struct pci_driver dfx_driver = {
+static struct pci_driver dfx_pci_driver = {
 	.name		= "defxx",
-	.probe		= dfx_init_one,
-	.remove		= __devexit_p(dfx_remove_one),
-	.id_table	= dfx_pci_tbl,
+	.id_table	= dfx_pci_table,
+	.probe		= dfx_pci_register,
+	.remove		= __devexit_p(dfx_pci_unregister),
 };
 
-static int dfx_have_pci;
-static int dfx_have_eisa;
-
-
-static void __exit dfx_eisa_cleanup(void)
+static __devinit int dfx_pci_register(struct pci_dev *pdev,
+				      const struct pci_device_id *ent)
 {
-	struct net_device *dev = root_dfx_eisa_dev;
-
-	while (dev)
-	{
-		struct net_device *tmp;
-		DFX_board_t *bp;
-
-		bp = (DFX_board_t*)dev->priv;
-		tmp = bp->next;
-		dfx_remove_one_pci_or_eisa(NULL, dev);
-		dev = tmp;
-	}
+	return dfx_register(&pdev->dev);
 }
 
-static int __init dfx_init(void)
+static void __devexit dfx_pci_unregister(struct pci_dev *pdev)
 {
-	int rc_pci, rc_eisa;
+	dfx_unregister(&pdev->dev);
+}
+#endif /* CONFIG_PCI */
 
-	rc_pci = pci_register_driver(&dfx_driver);
-	if (rc_pci >= 0) dfx_have_pci = 1;
+#ifdef CONFIG_EISA
+static struct eisa_device_id dfx_eisa_table[] = {
+        { "DEC3001", DEFEA_PROD_ID_1 },
+        { "DEC3002", DEFEA_PROD_ID_2 },
+        { "DEC3003", DEFEA_PROD_ID_3 },
+        { "DEC3004", DEFEA_PROD_ID_4 },
+        { }
+};
+MODULE_DEVICE_TABLE(eisa, dfx_eisa_table);
 
-	rc_eisa = dfx_eisa_init();
-	if (rc_eisa >= 0) dfx_have_eisa = 1;
+static struct eisa_driver dfx_eisa_driver = {
+	.id_table	= dfx_eisa_table,
+	.driver		= {
+		.name	= "defxx",
+		.bus	= &eisa_bus_type,
+		.probe	= dfx_dev_register,
+		.remove	= __devexit_p(dfx_dev_unregister),
+	},
+};
+#endif /* CONFIG_EISA */
 
-	return ((rc_eisa < 0) ? 0 : rc_eisa)  + ((rc_pci < 0) ? 0 : rc_pci);
+#ifdef CONFIG_TC
+static struct tc_device_id const dfx_tc_table[] = {
+	{ "DEC     ", "PMAF-FA " },
+	{ "DEC     ", "PMAF-FD " },
+	{ "DEC     ", "PMAF-FS " },
+	{ "DEC     ", "PMAF-FU " },
+	{ }
+};
+MODULE_DEVICE_TABLE(tc, dfx_tc_table);
+
+static struct tc_driver dfx_tc_driver = {
+	.id_table	= dfx_tc_table,
+	.driver		= {
+		.name	= "defxx",
+		.bus	= &tc_bus_type,
+		.probe	= dfx_dev_register,
+		.remove	= __devexit_p(dfx_dev_unregister),
+	},
+};
+#endif /* CONFIG_TC */
+
+static int __devinit __unused dfx_dev_register(struct device *dev)
+{
+	int status;
+
+	status = dfx_register(dev);
+	if (!status)
+		get_device(dev);
+	return status;
 }
 
-static void __exit dfx_cleanup(void)
+static int __devexit __unused dfx_dev_unregister(struct device *dev)
 {
-	if (dfx_have_pci)
-		pci_unregister_driver(&dfx_driver);
-	if (dfx_have_eisa)
-		dfx_eisa_cleanup();
+	put_device(dev);
+	dfx_unregister(dev);
+	return 0;
+}
 
+
+static int __devinit dfx_init(void)
+{
+	int status;
+
+	status = pci_register_driver(&dfx_pci_driver);
+	if (!status)
+		status = eisa_driver_register(&dfx_eisa_driver);
+	if (!status)
+		status = tc_register_driver(&dfx_tc_driver);
+	return status;
+}
+
+static void __devexit dfx_cleanup(void)
+{
+	tc_unregister_driver(&dfx_tc_driver);
+	eisa_driver_unregister(&dfx_eisa_driver);
+	pci_unregister_driver(&dfx_pci_driver);
 }
 
 module_init(dfx_init);
 module_exit(dfx_cleanup);
 MODULE_AUTHOR("Lawrence V. Stefani");
-MODULE_DESCRIPTION("DEC FDDIcontroller EISA/PCI (DEFEA/DEFPA) driver "
+MODULE_DESCRIPTION("DEC FDDIcontroller TC/EISA/PCI (DEFTA/DEFEA/DEFPA) driver "
 		   DRV_VERSION " " DRV_RELDATE);
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/net/defxx.h b/drivers/net/defxx.h
index 2ce8f97..19a6f64 100644
--- a/drivers/net/defxx.h
+++ b/drivers/net/defxx.h
@@ -26,6 +26,7 @@
  *		12-Sep-96	LVS		Removed packet request header pointers.
  *		04 Aug 2003	macro		Converted to the DMA API.
  *		23 Oct 2006	macro		Big-endian host support.
+ *		14 Dec 2006	macro		TURBOchannel support.
  */
 
 #ifndef _DEFXX_H_
@@ -1471,9 +1472,17 @@
 
 #endif /* __BIG_ENDIAN */
 
+/* Define TC PDQ CSR offset and length */
+
+#define PI_TC_K_CSR_OFFSET		0x100000
+#define PI_TC_K_CSR_LEN			0x40		/* 64 bytes */
+
 /* Define EISA controller register offsets */
 
-#define PI_ESIC_K_BURST_HOLDOFF		0x040
+#define PI_ESIC_K_CSR_IO_LEN		0x80		/* 128 bytes */
+
+#define PI_DEFEA_K_BURST_HOLDOFF	0x040
+
 #define PI_ESIC_K_SLOT_ID            	0xC80
 #define PI_ESIC_K_SLOT_CNTRL		0xC84
 #define PI_ESIC_K_MEM_ADD_CMP_0     	0xC85
@@ -1488,14 +1497,14 @@
 #define PI_ESIC_K_MEM_ADD_LO_CMP_0  	0xC8E
 #define PI_ESIC_K_MEM_ADD_LO_CMP_1  	0xC8F
 #define PI_ESIC_K_MEM_ADD_LO_CMP_2  	0xC90
-#define PI_ESIC_K_IO_CMP_0_0		0xC91
-#define PI_ESIC_K_IO_CMP_0_1		0xC92
-#define PI_ESIC_K_IO_CMP_1_0		0xC93
-#define PI_ESIC_K_IO_CMP_1_1		0xC94
-#define PI_ESIC_K_IO_CMP_2_0		0xC95
-#define PI_ESIC_K_IO_CMP_2_1		0xC96
-#define PI_ESIC_K_IO_CMP_3_0		0xC97
-#define PI_ESIC_K_IO_CMP_3_1		0xC98
+#define PI_ESIC_K_IO_ADD_CMP_0_0	0xC91
+#define PI_ESIC_K_IO_ADD_CMP_0_1	0xC92
+#define PI_ESIC_K_IO_ADD_CMP_1_0	0xC93
+#define PI_ESIC_K_IO_ADD_CMP_1_1	0xC94
+#define PI_ESIC_K_IO_ADD_CMP_2_0	0xC95
+#define PI_ESIC_K_IO_ADD_CMP_2_1	0xC96
+#define PI_ESIC_K_IO_ADD_CMP_3_0	0xC97
+#define PI_ESIC_K_IO_ADD_CMP_3_1	0xC98
 #define PI_ESIC_K_IO_ADD_MASK_0_0    	0xC99
 #define PI_ESIC_K_IO_ADD_MASK_0_1    	0xC9A
 #define PI_ESIC_K_IO_ADD_MASK_1_0    	0xC9B
@@ -1518,11 +1527,16 @@
 #define PI_ESIC_K_INPUT_PORT         	0xCAC
 #define PI_ESIC_K_OUTPUT_PORT        	0xCAD
 #define PI_ESIC_K_FUNCTION_CNTRL	0xCAE
-#define PI_ESIC_K_CSR_IO_LEN		PI_ESIC_K_FUNCTION_CNTRL+1	/* always last reg + 1 */
 
-/* Define the value all drivers must write to the function control register. */
+/* Define the bits in the function control register. */
 
-#define PI_ESIC_K_FUNCTION_CNTRL_IO_ENB	0x03
+#define PI_FUNCTION_CNTRL_M_IOCS0	0x01
+#define PI_FUNCTION_CNTRL_M_IOCS1	0x02
+#define PI_FUNCTION_CNTRL_M_IOCS2	0x04
+#define PI_FUNCTION_CNTRL_M_IOCS3	0x08
+#define PI_FUNCTION_CNTRL_M_MEMCS0	0x10
+#define PI_FUNCTION_CNTRL_M_MEMCS1	0x20
+#define PI_FUNCTION_CNTRL_M_DMA		0x80
 
 /* Define the bits in the slot control register. */
 
@@ -1540,6 +1554,10 @@
 #define PI_BURST_HOLDOFF_V_RESERVED	1
 #define PI_BURST_HOLDOFF_V_MEM_MAP	0
 
+/* Define the implicit mask of the Memory Address Mask Register.  */
+
+#define PI_MEM_ADD_MASK_M		0x3ff
+
 /*
  * Define the fields in the IO Compare registers.
  * The driver must initialize the slot field with the slot ID shifted by the
@@ -1577,6 +1595,7 @@
 #define DEFEA_PROD_ID_1		0x0130A310		/* DEC product 300, rev 1	*/
 #define DEFEA_PROD_ID_2		0x0230A310		/* DEC product 300, rev 2	*/
 #define DEFEA_PROD_ID_3		0x0330A310		/* DEC product 300, rev 3	*/
+#define DEFEA_PROD_ID_4		0x0430A310		/* DEC product 300, rev 4	*/
 
 /**********************************************/
 /* Digital PFI Specification v1.0 Definitions */
@@ -1633,12 +1652,6 @@
 #define PFI_STATUS_V_FIFO_EMPTY		 1
 #define PFI_STATUS_V_DMA_IN_PROGRESS 0
 
-#define DFX_MAX_EISA_SLOTS		16			/* maximum number of EISA slots to scan */
-#define DFX_MAX_NUM_BOARDS		8			/* maximum number of adapters supported */
-
-#define DFX_BUS_TYPE_PCI		0			/* type code for DEC FDDIcontroller/PCI */
-#define DFX_BUS_TYPE_EISA		1			/* type code for DEC FDDIcontroller/EISA */
-
 #define DFX_FC_PRH2_PRH1_PRH0		0x54003820	/* Packet Request Header bytes + FC */
 #define DFX_PRH0_BYTE			0x20		/* Packet Request Header byte 0 */
 #define DFX_PRH1_BYTE			0x38		/* Packet Request Header byte 1 */
@@ -1756,10 +1769,11 @@
 	/* Store device, bus-specific, and parameter information for this adapter */
 
 	struct net_device		*dev;						/* pointer to device structure */
-	struct net_device		*next;
-	u32				bus_type;					/* bus type (0 == PCI, 1 == EISA) */
-	u16				base_addr;					/* base I/O address (same as dev->base_addr) */
-	struct pci_dev *		pci_dev;
+	union {
+		void __iomem *mem;
+		int port;
+	} base;										/* base address */
+	struct device			*bus_dev;
 	u32				full_duplex_enb;				/* FDDI Full Duplex enable (1 == on, 2 == off) */
 	u32				req_ttrt;					/* requested TTRT value (in 80ns units) */
 	u32				burst_size;					/* adapter burst size (enumerated) */
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 689f158..dd4b728 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -337,7 +337,6 @@
 	struct e1000_rx_ring test_rx_ring;
 
 
-	uint32_t *config_space;
 	int msg_enable;
 #ifdef CONFIG_PCI_MSI
 	boolean_t have_msi;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 44ebc72..6777887 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -166,7 +166,7 @@
 			ecmd->transceiver = XCVR_EXTERNAL;
 	}
 
-	if (netif_carrier_ok(adapter->netdev)) {
+	if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) {
 
 		e1000_get_speed_and_duplex(hw, &adapter->link_speed,
 		                                   &adapter->link_duplex);
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index d671058..bd000b80 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -3253,7 +3253,7 @@
 #define IFE_PMC_AUTO_MDIX                    0x0080  /* 1=enable MDI/MDI-X feature, default 0=disabled */
 #define IFE_PMC_FORCE_MDIX                   0x0040  /* 1=force MDIX-X, 0=force MDI */
 #define IFE_PMC_MDIX_STATUS                  0x0020  /* 1=MDI-X, 0=MDI */
-#define IFE_PMC_AUTO_MDIX_COMPLETE           0x0010  /* Resolution algorthm is completed */
+#define IFE_PMC_AUTO_MDIX_COMPLETE           0x0010  /* Resolution algorithm is completed */
 #define IFE_PMC_MDIX_MODE_SHIFT              6
 #define IFE_PHC_MDIX_RESET_ALL_MASK          0x0000  /* Disable auto MDI-X */
 
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 619c892..98215fd 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -5071,58 +5071,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
-/* Save/restore 16 or 64 dwords of PCI config space depending on which
- * bus we're on (PCI(X) vs. PCI-E)
- */
-#define PCIE_CONFIG_SPACE_LEN 256
-#define PCI_CONFIG_SPACE_LEN 64
-static int
-e1000_pci_save_state(struct e1000_adapter *adapter)
-{
-	struct pci_dev *dev = adapter->pdev;
-	int size;
-	int i;
-
-	if (adapter->hw.mac_type >= e1000_82571)
-		size = PCIE_CONFIG_SPACE_LEN;
-	else
-		size = PCI_CONFIG_SPACE_LEN;
-
-	WARN_ON(adapter->config_space != NULL);
-
-	adapter->config_space = kmalloc(size, GFP_KERNEL);
-	if (!adapter->config_space) {
-		DPRINTK(PROBE, ERR, "unable to allocate %d bytes\n", size);
-		return -ENOMEM;
-	}
-	for (i = 0; i < (size / 4); i++)
-		pci_read_config_dword(dev, i * 4, &adapter->config_space[i]);
-	return 0;
-}
-
-static void
-e1000_pci_restore_state(struct e1000_adapter *adapter)
-{
-	struct pci_dev *dev = adapter->pdev;
-	int size;
-	int i;
-
-	if (adapter->config_space == NULL)
-		return;
-
-	if (adapter->hw.mac_type >= e1000_82571)
-		size = PCIE_CONFIG_SPACE_LEN;
-	else
-		size = PCI_CONFIG_SPACE_LEN;
-	for (i = 0; i < (size / 4); i++)
-		pci_write_config_dword(dev, i * 4, adapter->config_space[i]);
-	kfree(adapter->config_space);
-	adapter->config_space = NULL;
-	return;
-}
-#endif /* CONFIG_PM */
-
 static int
 e1000_suspend(struct pci_dev *pdev, pm_message_t state)
 {
@@ -5142,9 +5090,7 @@
 	}
 
 #ifdef CONFIG_PM
-	/* Implement our own version of pci_save_state(pdev) because pci-
-	 * express adapters have 256-byte config spaces. */
-	retval = e1000_pci_save_state(adapter);
+	retval = pci_save_state(pdev);
 	if (retval)
 		return retval;
 #endif
@@ -5231,7 +5177,7 @@
 	uint32_t err;
 
 	pci_set_power_state(pdev, PCI_D0);
-	e1000_pci_restore_state(adapter);
+	pci_restore_state(pdev);
 	if ((err = pci_enable_device(pdev))) {
 		printk(KERN_ERR "e1000: Cannot enable PCI device from suspend\n");
 		return err;
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index c62d9c6..b2b0a96 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -355,8 +355,7 @@
 
 	mem_on(ioaddr, shared_mem, (ring_offset>>8));
 
-	/* Packet is always in one chunk -- we can copy + cksum. */
-	eth_io_copy_and_sum(skb, ei_status.mem + (ring_offset & 0xff), count, 0);
+	memcpy_fromio(skb->data, ei_status.mem + (ring_offset & 0xff), count);
 
 	mem_off(ioaddr);
 }
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 4a50fcb..3868b80 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -714,13 +714,6 @@
  * check to make sure we've not become wedged.
  */
 
-/*
- * Handle an EtherExpress interrupt
- * If we've finished initializing, start the RU and CU up.
- * If we've already started, reap tx buffers, handle any received packets,
- * check to make sure we've not become wedged.
- */
-
 static unsigned short eexp_start_irq(struct net_device *dev,
 				     unsigned short status)
 {
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 272e1ec..42295d6 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,7 +39,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ehea"
-#define DRV_VERSION	"EHEA_0045"
+#define DRV_VERSION	"EHEA_0046"
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
 	| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 9de2d38..88ad1c8 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -76,7 +76,7 @@
 	int x;
 	unsigned char *deb = adr;
 	for (x = 0; x < len; x += 16) {
-		printk(DRV_NAME "%s adr=%p ofs=%04x %016lx %016lx\n", msg,
+		printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg,
 			  deb, x, *((u64*)&deb[0]), *((u64*)&deb[8]));
 		deb += 16;
 	}
@@ -555,6 +555,7 @@
 {
 	struct ehea_port *port = param;
 	struct ehea_eqe *eqe;
+	struct ehea_qp *qp;
 	u32 qp_token;
 
 	eqe = ehea_poll_eq(port->qp_eq);
@@ -563,9 +564,14 @@
 		qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
 		ehea_error("QP aff_err: entry=0x%lx, token=0x%x",
 			   eqe->entry, qp_token);
+
+		qp = port->port_res[qp_token].qp;
+		ehea_error_data(port->adapter, qp->fw_handle);
 		eqe = ehea_poll_eq(port->qp_eq);
 	}
 
+	queue_work(port->adapter->ehea_wq, &port->reset_task);
+
 	return IRQ_HANDLED;
 }
 
@@ -882,7 +888,7 @@
 			 , "%s-recv%d", dev->name, i);
 		ret = ibmebus_request_irq(NULL, pr->recv_eq->attr.ist1,
 					  ehea_recv_irq_handler,
-					  SA_INTERRUPT, pr->int_recv_name, pr);
+					  IRQF_DISABLED, pr->int_recv_name, pr);
 		if (ret) {
 			ehea_error("failed registering irq for ehea_recv_int:"
 				   "port_res_nr:%d, ist=%X", i,
@@ -899,7 +905,7 @@
 
 	ret = ibmebus_request_irq(NULL, port->qp_eq->attr.ist1,
 				  ehea_qp_aff_irq_handler,
-				  SA_INTERRUPT, port->int_aff_name, port);
+				  IRQF_DISABLED, port->int_aff_name, port);
 	if (ret) {
 		ehea_error("failed registering irq for qp_aff_irq_handler:"
 			   "ist=%X", port->qp_eq->attr.ist1);
@@ -916,7 +922,7 @@
 			 "%s-send%d", dev->name, i);
 		ret = ibmebus_request_irq(NULL, pr->send_eq->attr.ist1,
 					  ehea_send_irq_handler,
-					  SA_INTERRUPT, pr->int_send_name,
+					  IRQF_DISABLED, pr->int_send_name,
 					  pr);
 		if (ret) {
 			ehea_error("failed registering irq for ehea_send "
@@ -2539,7 +2545,7 @@
 		     (unsigned long)adapter);
 
 	ret = ibmebus_request_irq(NULL, adapter->neq->attr.ist1,
-				  ehea_interrupt_neq, SA_INTERRUPT,
+				  ehea_interrupt_neq, IRQF_DISABLED,
 				  "ehea_neq", adapter);
 	if (ret) {
 		dev_err(&dev->ofdev.dev, "requesting NEQ IRQ failed");
diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c
index 37716e05e8..bc3c005 100644
--- a/drivers/net/ehea/ehea_phyp.c
+++ b/drivers/net/ehea/ehea_phyp.c
@@ -612,3 +612,13 @@
 				       event_mask,		/* R6 */
 				       0, 0, 0, 0);		/* R7-R12 */
 }
+
+u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
+		      void *rblock)
+{
+	return ehea_plpar_hcall_norets(H_ERROR_DATA,
+				       adapter_handle,          /* R4 */
+				       ressource_handle,        /* R5 */
+				       virt_to_abs(rblock),     /* R6 */
+				       0, 0, 0, 0);             /* R7-R12 */
+}
diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h
index 919f94b..90acddb0 100644
--- a/drivers/net/ehea/ehea_phyp.h
+++ b/drivers/net/ehea/ehea_phyp.h
@@ -454,4 +454,7 @@
 u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
 			const u64 event_mask);
 
+u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
+		      void *rblock);
+
 #endif	/* __EHEA_PHYP_H__ */
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index f143e13..96ff3b6 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -486,6 +486,7 @@
 	if (!qp)
 		return 0;
 
+	ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
 	hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle);
 	if (hret != H_SUCCESS) {
 		ehea_error("destroy_qp failed");
@@ -581,4 +582,45 @@
 	return ret;
 }
 
+void print_error_data(u64 *data)
+{
+	int length;
+	u64 type = EHEA_BMASK_GET(ERROR_DATA_TYPE, data[2]);
+	u64 resource = data[1];
 
+	length = EHEA_BMASK_GET(ERROR_DATA_LENGTH, data[0]);
+
+	if (length > EHEA_PAGESIZE)
+		length = EHEA_PAGESIZE;
+
+	if (type == 0x8) /* Queue Pair */
+		ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, "
+			   "port=%lX", resource, data[6], data[12], data[22]);
+
+	ehea_dump(data, length, "error data");
+}
+
+void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle)
+{
+	unsigned long ret;
+	u64 *rblock;
+
+	rblock = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!rblock) {
+		ehea_error("Cannot allocate rblock memory.");
+		return;
+	}
+
+	ret = ehea_h_error_data(adapter->handle,
+				res_handle,
+				rblock);
+
+	if (ret == H_R_STATE)
+		ehea_error("No error data is available: %lX.", res_handle);
+	else if (ret == H_SUCCESS)
+		print_error_data(rblock);
+	else
+		ehea_error("Error data could not be fetched: %lX", res_handle);
+
+	kfree(rblock);
+}
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h
index 7efdc96..1ff6098 100644
--- a/drivers/net/ehea/ehea_qmr.h
+++ b/drivers/net/ehea/ehea_qmr.h
@@ -180,6 +180,9 @@
 	u64 entry;
 };
 
+#define ERROR_DATA_LENGTH  EHEA_BMASK_IBM(52,63)
+#define ERROR_DATA_TYPE    EHEA_BMASK_IBM(0,7)
+
 static inline void *hw_qeit_calc(struct hw_queue *queue, u64 q_offset)
 {
 	struct ehea_page *current_page;
@@ -355,4 +358,6 @@
 
 int ehea_reg_mr_adapter(struct ehea_adapter *adapter);
 
+void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);
+
 #endif	/* __EHEA_QMR_H__ */
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 2d2ea94..822e5bf 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -375,7 +375,7 @@
 		memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
 	} else {
 		/* Packet is in one chunk. */
-		eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		memcpy_fromio(skb->data, xfer_start, count);
 	}
 }
 
diff --git a/drivers/net/fec_8xx/fec_8xx-netta.c b/drivers/net/fec_8xx/fec_8xx-netta.c
index 790d9db..e492eb8 100644
--- a/drivers/net/fec_8xx/fec_8xx-netta.c
+++ b/drivers/net/fec_8xx/fec_8xx-netta.c
@@ -4,7 +4,6 @@
 
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c
index 8e7a56f..77f747a 100644
--- a/drivers/net/fec_8xx/fec_main.c
+++ b/drivers/net/fec_8xx/fec_main.c
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
diff --git a/drivers/net/fec_8xx/fec_mii.c b/drivers/net/fec_8xx/fec_mii.c
index d3c16b8..e79700a 100644
--- a/drivers/net/fec_8xx/fec_mii.c
+++ b/drivers/net/fec_8xx/fec_mii.c
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 889d3a1..4a05c14 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -18,7 +18,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 1ff2597..8545e84 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index ff68394..cdcfb96 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index afd7fca..65925b5 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 0b9b8b5..f914478 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index baaae3d..235b177 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index baa3514..1f83988 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -10,6 +10,7 @@
  * Maintainer: Kumar Gala
  *
  * Copyright (c) 2002-2006 Freescale Semiconductor, Inc.
+ * Copyright (c) 2007 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
@@ -65,7 +66,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
@@ -1613,71 +1613,17 @@
 	/* Save ievent for future reference */
 	u32 events = gfar_read(&priv->regs->ievent);
 
-	/* Clear IEVENT */
-	gfar_write(&priv->regs->ievent, events);
-
 	/* Check for reception */
-	if ((events & IEVENT_RXF0) || (events & IEVENT_RXB0))
+	if (events & IEVENT_RX_MASK)
 		gfar_receive(irq, dev_id);
 
 	/* Check for transmit completion */
-	if ((events & IEVENT_TXF) || (events & IEVENT_TXB))
+	if (events & IEVENT_TX_MASK)
 		gfar_transmit(irq, dev_id);
 
-	/* Update error statistics */
-	if (events & IEVENT_TXE) {
-		priv->stats.tx_errors++;
-
-		if (events & IEVENT_LC)
-			priv->stats.tx_window_errors++;
-		if (events & IEVENT_CRL)
-			priv->stats.tx_aborted_errors++;
-		if (events & IEVENT_XFUN) {
-			if (netif_msg_tx_err(priv))
-				printk(KERN_WARNING "%s: tx underrun. dropped packet\n", dev->name);
-			priv->stats.tx_dropped++;
-			priv->extra_stats.tx_underrun++;
-
-			/* Reactivate the Tx Queues */
-			gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
-		}
-	}
-	if (events & IEVENT_BSY) {
-		priv->stats.rx_errors++;
-		priv->extra_stats.rx_bsy++;
-
-		gfar_receive(irq, dev_id);
-
-#ifndef CONFIG_GFAR_NAPI
-		/* Clear the halt bit in RSTAT */
-		gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
-#endif
-
-		if (netif_msg_rx_err(priv))
-			printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n",
-					dev->name,
-					gfar_read(&priv->regs->rstat));
-	}
-	if (events & IEVENT_BABR) {
-		priv->stats.rx_errors++;
-		priv->extra_stats.rx_babr++;
-
-		if (netif_msg_rx_err(priv))
-			printk(KERN_DEBUG "%s: babbling error\n", dev->name);
-	}
-	if (events & IEVENT_EBERR) {
-		priv->extra_stats.eberr++;
-		if (netif_msg_rx_err(priv))
-			printk(KERN_DEBUG "%s: EBERR\n", dev->name);
-	}
-	if ((events & IEVENT_RXC) && (netif_msg_rx_err(priv)))
-			printk(KERN_DEBUG "%s: control frame\n", dev->name);
-
-	if (events & IEVENT_BABT) {
-		priv->extra_stats.tx_babt++;
-		if (netif_msg_rx_err(priv))
-			printk(KERN_DEBUG "%s: babt error\n", dev->name);
-	}
+	/* Check for errors */
+	if (events & IEVENT_ERR_MASK)
+		gfar_error(irq, dev_id);
 
 	return IRQ_HANDLED;
 }
@@ -1939,7 +1885,7 @@
 	/* Hmm... */
 	if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
 		printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n",
-				dev->name, events, gfar_read(&priv->regs->imask));
+		       dev->name, events, gfar_read(&priv->regs->imask));
 
 	/* Update the error counters */
 	if (events & IEVENT_TXE) {
@@ -1951,8 +1897,8 @@
 			priv->stats.tx_aborted_errors++;
 		if (events & IEVENT_XFUN) {
 			if (netif_msg_tx_err(priv))
-				printk(KERN_DEBUG "%s: underrun.  packet dropped.\n",
-						dev->name);
+				printk(KERN_DEBUG "%s: TX FIFO underrun, "
+				       "packet dropped.\n", dev->name);
 			priv->stats.tx_dropped++;
 			priv->extra_stats.tx_underrun++;
 
@@ -1974,30 +1920,28 @@
 #endif
 
 		if (netif_msg_rx_err(priv))
-			printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n",
-					dev->name,
-					gfar_read(&priv->regs->rstat));
+			printk(KERN_DEBUG "%s: busy error (rstat: %x)\n",
+			       dev->name, gfar_read(&priv->regs->rstat));
 	}
 	if (events & IEVENT_BABR) {
 		priv->stats.rx_errors++;
 		priv->extra_stats.rx_babr++;
 
 		if (netif_msg_rx_err(priv))
-			printk(KERN_DEBUG "%s: babbling error\n", dev->name);
+			printk(KERN_DEBUG "%s: babbling RX error\n", dev->name);
 	}
 	if (events & IEVENT_EBERR) {
 		priv->extra_stats.eberr++;
 		if (netif_msg_rx_err(priv))
-			printk(KERN_DEBUG "%s: EBERR\n", dev->name);
+			printk(KERN_DEBUG "%s: bus error\n", dev->name);
 	}
 	if ((events & IEVENT_RXC) && netif_msg_rx_status(priv))
-		if (netif_msg_rx_status(priv))
-			printk(KERN_DEBUG "%s: control frame\n", dev->name);
+		printk(KERN_DEBUG "%s: control frame\n", dev->name);
 
 	if (events & IEVENT_BABT) {
 		priv->extra_stats.tx_babt++;
 		if (netif_msg_tx_err(priv))
-			printk(KERN_DEBUG "%s: babt error\n", dev->name);
+			printk(KERN_DEBUG "%s: babbling TX error\n", dev->name);
 	}
 	return IRQ_HANDLED;
 }
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 0d6943d..7b411c1 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -16,7 +16,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index ff684d4..bcc6b82 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -17,7 +17,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
index 9dd387f..aec9ab1 100644
--- a/drivers/net/gianfar_sysfs.c
+++ b/drivers/net/gianfar_sysfs.c
@@ -20,7 +20,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
@@ -39,13 +38,15 @@
 #include "gianfar.h"
 
 #define GFAR_ATTR(_name) \
-static ssize_t gfar_show_##_name(struct class_device *cdev, char *buf); \
-static ssize_t gfar_set_##_name(struct class_device *cdev, \
+static ssize_t gfar_show_##_name(struct device *dev, \
+	 struct device_attribute *attr, char *buf); \
+static ssize_t gfar_set_##_name(struct device *dev, \
+		struct device_attribute *attr, \
 		const char *buf, size_t count); \
-static CLASS_DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name)
+static DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name)
 
 #define GFAR_CREATE_FILE(_dev, _name) \
-	class_device_create_file(&_dev->class_dev, &class_device_attr_##_name)
+	device_create_file(&_dev->dev, &dev_attr_##_name)
 
 GFAR_ATTR(bd_stash);
 GFAR_ATTR(rx_stash_size);
@@ -54,29 +55,28 @@
 GFAR_ATTR(fifo_starve);
 GFAR_ATTR(fifo_starve_off);
 
-#define to_net_dev(cd) container_of(cd, struct net_device, class_dev)
-
-static ssize_t gfar_show_bd_stash(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_bd_stash(struct device *dev,
+				  struct device_attribute *attr, char *buf)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
-	return sprintf(buf, "%s\n", priv->bd_stash_en? "on" : "off");
+	return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off");
 }
 
-static ssize_t gfar_set_bd_stash(struct class_device *cdev,
-		const char *buf, size_t count)
+static ssize_t gfar_set_bd_stash(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 	int new_setting = 0;
 	u32 temp;
 	unsigned long flags;
 
 	/* Find out the new setting */
-	if (!strncmp("on", buf, count-1) || !strncmp("1", buf, count-1))
+	if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
 		new_setting = 1;
-	else if (!strncmp("off", buf, count-1) || !strncmp("0", buf, count-1))
+	else if (!strncmp("off", buf, count - 1)
+		 || !strncmp("0", buf, count - 1))
 		new_setting = 0;
 	else
 		return count;
@@ -100,19 +100,19 @@
 	return count;
 }
 
-static ssize_t gfar_show_rx_stash_size(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_rx_stash_size(struct device *dev,
+				       struct device_attribute *attr, char *buf)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
 	return sprintf(buf, "%d\n", priv->rx_stash_size);
 }
 
-static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
-		const char *buf, size_t count)
+static ssize_t gfar_set_rx_stash_size(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 	unsigned int length = simple_strtoul(buf, NULL, 0);
 	u32 temp;
 	unsigned long flags;
@@ -146,21 +146,21 @@
 	return count;
 }
 
-
 /* Stashing will only be enabled when rx_stash_size != 0 */
-static ssize_t gfar_show_rx_stash_index(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_rx_stash_index(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
 	return sprintf(buf, "%d\n", priv->rx_stash_index);
 }
 
-static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
-		const char *buf, size_t count)
+static ssize_t gfar_set_rx_stash_index(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 	unsigned short index = simple_strtoul(buf, NULL, 0);
 	u32 temp;
 	unsigned long flags;
@@ -184,19 +184,20 @@
 	return count;
 }
 
-static ssize_t gfar_show_fifo_threshold(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_fifo_threshold(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
 	return sprintf(buf, "%d\n", priv->fifo_threshold);
 }
 
-static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
-		const char *buf, size_t count)
+static ssize_t gfar_set_fifo_threshold(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 	unsigned int length = simple_strtoul(buf, NULL, 0);
 	u32 temp;
 	unsigned long flags;
@@ -218,20 +219,19 @@
 	return count;
 }
 
-static ssize_t gfar_show_fifo_starve(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_fifo_starve(struct device *dev,
+				     struct device_attribute *attr, char *buf)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
 	return sprintf(buf, "%d\n", priv->fifo_starve);
 }
 
-
-static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
-		const char *buf, size_t count)
+static ssize_t gfar_set_fifo_starve(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 	unsigned int num = simple_strtoul(buf, NULL, 0);
 	u32 temp;
 	unsigned long flags;
@@ -253,19 +253,20 @@
 	return count;
 }
 
-static ssize_t gfar_show_fifo_starve_off(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_fifo_starve_off(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 
 	return sprintf(buf, "%d\n", priv->fifo_starve_off);
 }
 
-static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
-		const char *buf, size_t count)
+static ssize_t gfar_set_fifo_starve_off(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
 {
-	struct net_device *dev = to_net_dev(cdev);
-	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
 	unsigned int num = simple_strtoul(buf, NULL, 0);
 	u32 temp;
 	unsigned long flags;
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index feb0ada..6e90619 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -138,7 +138,7 @@
 	---help---
 	  This is one of two drivers for Baycom style simple amateur radio
 	  modems that connect to a serial interface. The driver supports the
-	  ser12 design in full-duplex mode. This is the old driver.  It is
+	  ser12 design in half-duplex mode. This is the old driver.  It is
 	  still provided in case your serial interface chip does not work with
 	  the full-duplex driver. This driver is depreciated.  To configure
 	  the driver, use the sethdlc utility available in the standard ax25
@@ -190,3 +190,4 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called yam.
 
+ 
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 153b6dc..84aa211 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -52,6 +52,7 @@
 #include <linux/hdlcdrv.h>
 #include <linux/baycom.h>
 #include <linux/jiffies.h>
+#include <linux/random.h>
 #include <net/ax25.h> 
 #include <asm/uaccess.h>
 
@@ -433,16 +434,6 @@
 
 /* ---------------------------------------------------------------------- */
 
-static unsigned short random_seed;
-
-static inline unsigned short random_num(void)
-{
-	random_seed = 28629 * random_seed + 157;
-	return random_seed;
-}
-
-/* ---------------------------------------------------------------------- */
-
 static int transmit(struct baycom_state *bc, int cnt, unsigned char stat)
 {
 	struct parport *pp = bc->pdev->port;
@@ -464,7 +455,7 @@
 			if ((--bc->hdlctx.slotcnt) > 0)
 				return 0;
 			bc->hdlctx.slotcnt = bc->ch_params.slottime;
-			if ((random_num() % 256) > bc->ch_params.ppersist)
+			if ((random32() % 256) > bc->ch_params.ppersist)
 				return 0;
 		}
 	}
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 5b788d8..d254269 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -459,7 +459,7 @@
 	return seq_open(file, &bpq_seqops);
 }
 
-static struct file_operations bpq_info_fops = {
+static const struct file_operations bpq_info_fops = {
 	.owner = THIS_MODULE,
 	.open = bpq_info_open,
 	.read = seq_read,
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index 452873e..f5a17ad 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -56,6 +56,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <linux/hdlcdrv.h>
+#include <linux/random.h>
 #include <net/ax25.h> 
 #include <asm/uaccess.h>
 
@@ -371,16 +372,6 @@
 
 /* ---------------------------------------------------------------------- */
 
-static unsigned short random_seed;
-
-static inline unsigned short random_num(void)
-{
-	random_seed = 28629 * random_seed + 157;
-	return random_seed;
-}
-
-/* ---------------------------------------------------------------------- */
-
 void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
 {
 	if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt || !s->skb) 
@@ -396,7 +387,7 @@
 	if ((--s->hdlctx.slotcnt) > 0)
 		return;
 	s->hdlctx.slotcnt = s->ch_params.slottime;
-	if ((random_num() % 256) > s->ch_params.ppersist)
+	if ((random32() % 256) > s->ch_params.ppersist)
 		return;
 	start_tx(dev, s);
 }
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 2ce047e..6fdaad5 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -2083,7 +2083,7 @@
 	return seq_open(file, &scc_net_seq_ops);
 }
 
-static struct file_operations scc_net_seq_fops = {
+static const struct file_operations scc_net_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = scc_net_seq_open,
 	.read	 = seq_read,
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 6d74f08..ee3ea4f 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -50,6 +50,7 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/bitops.h>
+#include <linux/random.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <linux/interrupt.h>
@@ -566,14 +567,6 @@
 	ptt_on(dev);
 }
 
-static unsigned short random_seed;
-
-static inline unsigned short random_num(void)
-{
-	random_seed = 28629 * random_seed + 157;
-	return random_seed;
-}
-
 static void yam_arbitrate(struct net_device *dev)
 {
 	struct yam_port *yp = netdev_priv(dev);
@@ -600,7 +593,7 @@
 	yp->slotcnt = yp->slot / 10;
 
 	/* is random > persist ? */
-	if ((random_num() % 256) > yp->pers)
+	if ((random32() % 256) > yp->pers)
 		return;
 
 	yam_start_tx(dev, yp);
@@ -804,7 +797,7 @@
 	return seq_open(file, &yam_seqops);
 }
 
-static struct file_operations yam_info_fops = {
+static const struct file_operations yam_info_fops = {
 	.owner = THIS_MODULE,
 	.open = yam_info_open,
 	.read = seq_read,
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index ffeafb2..dd8ad87 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -21,7 +21,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 99343b5..458db05 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -1156,7 +1156,7 @@
 	return rc;
 }
 
-static struct file_operations ibmveth_proc_fops = {
+static const struct file_operations ibmveth_proc_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = ibmveth_proc_open,
 	.read    = seq_read,
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index f0d30cf..4ad7807 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -836,13 +836,17 @@
 	}
 
 	ip->mii.phy_id = i;
+
+out:
+	return res;
+}
+
+static void ioc3_mii_start(struct ioc3_private *ip)
+{
 	ip->ioc3_timer.expires = jiffies + (12 * HZ)/10;  /* 1.2 sec. */
 	ip->ioc3_timer.data = (unsigned long) ip;
 	ip->ioc3_timer.function = &ioc3_timer;
 	add_timer(&ip->ioc3_timer);
-
-out:
-	return res;
 }
 
 static inline void ioc3_clean_rx_ring(struct ioc3_private *ip)
@@ -1071,6 +1075,7 @@
 	ip->ehar_h = 0;
 	ip->ehar_l = 0;
 	ioc3_init(dev);
+	ioc3_mii_start(ip);
 
 	netif_start_queue(dev);
 	return 0;
@@ -1274,6 +1279,7 @@
 		goto out_stop;
 	}
 
+	ioc3_mii_start(ip);
 	ioc3_ssram_disc(ip);
 	ioc3_get_eaddr(ip);
 
@@ -1314,6 +1320,7 @@
 
 out_stop:
 	ioc3_stop(ip);
+	del_timer_sync(&ip->ioc3_timer);
 	ioc3_free_rings(ip);
 out_res:
 	pci_release_regions(pdev);
@@ -1335,6 +1342,8 @@
 	struct ioc3 *ioc3 = ip->regs;
 
 	unregister_netdev(dev);
+	del_timer_sync(&ip->ioc3_timer);
+
 	iounmap(ioc3);
 	pci_release_regions(pdev);
 	free_netdev(dev);
@@ -1492,6 +1501,7 @@
 	ioc3_stop(ip);
 	ioc3_init(dev);
 	ioc3_mii_init(ip);
+	ioc3_mii_start(ip);
 
 	spin_unlock_irq(&ip->ioc3_lock);
 
diff --git a/drivers/net/irda/ma600-sir.c b/drivers/net/irda/ma600-sir.c
index ebed168..809906d 100644
--- a/drivers/net/irda/ma600-sir.c
+++ b/drivers/net/irda/ma600-sir.c
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 
 #include <net/irda/irda.h>
 
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index e2b1af6..3457e9d 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -385,7 +385,7 @@
 	return single_open(file, vlsi_seq_show, PDE(inode)->data);
 }
 
-static struct file_operations vlsi_proc_fops = {
+static const struct file_operations vlsi_proc_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = vlsi_seq_open,
 	.read    = seq_read,
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index e67361e..2e9571b 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -881,27 +881,15 @@
 static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct macb *bp = netdev_priv(dev);
-	int ret;
-	unsigned long flags;
 
-	spin_lock_irqsave(&bp->lock, flags);
-	ret = mii_ethtool_gset(&bp->mii, cmd);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	return ret;
+	return mii_ethtool_gset(&bp->mii, cmd);
 }
 
 static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct macb *bp = netdev_priv(dev);
-	int ret;
-	unsigned long flags;
 
-	spin_lock_irqsave(&bp->lock, flags);
-	ret = mii_ethtool_sset(&bp->mii, cmd);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	return ret;
+	return mii_ethtool_sset(&bp->mii, cmd);
 }
 
 static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
@@ -930,17 +918,11 @@
 static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct macb *bp = netdev_priv(dev);
-	int ret;
-	unsigned long flags;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	spin_lock_irqsave(&bp->lock, flags);
-	ret = generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	return ret;
+	return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
 }
 
 static ssize_t macb_mii_show(const struct device *_dev, char *buf,
@@ -1077,7 +1059,7 @@
 	}
 
 	dev->irq = platform_get_irq(pdev, 0);
-	err = request_irq(dev->irq, macb_interrupt, SA_SAMPLE_RANDOM,
+	err = request_irq(dev->irq, macb_interrupt, IRQF_SAMPLE_RANDOM,
 			  dev->name, dev);
 	if (err) {
 		printk(KERN_ERR
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index 24f6050f..8ca57a0 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -49,6 +49,7 @@
 #include <linux/skbuff.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/bitrev.h>
 
 #include <asm/bootinfo.h>
 #include <asm/system.h>
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index e1d97cd..7e69ca6 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include <linux/sched.h>
 #include <linux/kernel.h> /* printk() */
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -171,7 +170,7 @@
 
 static void meth_check_link(struct net_device *dev)
 {
-	struct meth_private *priv = (struct meth_private *) dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 	unsigned long mii_advertising = mdio_read(priv, 4);
 	unsigned long mii_partner = mdio_read(priv, 5);
 	unsigned long negotiated = mii_advertising & mii_partner;
@@ -269,7 +268,7 @@
 
 int meth_reset(struct net_device *dev)
 {
-	struct meth_private *priv = (struct meth_private *) dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 
 	/* Reset card */
 	mace->eth.mac_ctrl = SGI_MAC_RESET;
@@ -311,7 +310,7 @@
  */
 static int meth_open(struct net_device *dev)
 {
-	struct meth_private *priv = dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 	int ret;
 
 	priv->phy_addr = -1;    /* No PHY is known yet... */
@@ -355,7 +354,7 @@
 
 static int meth_release(struct net_device *dev)
 {
-	struct meth_private *priv = dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 
 	DPRINTK("Stopping queue\n");
 	netif_stop_queue(dev); /* can't transmit any more */
@@ -377,7 +376,7 @@
 {
 	struct sk_buff *skb;
 	unsigned long status;
-	struct meth_private *priv = (struct meth_private *) dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 	unsigned long fifo_rptr = (int_status & METH_INT_RX_RPTR_MASK) >> 8;
 
 	spin_lock(&priv->meth_lock);
@@ -467,14 +466,14 @@
 
 static int meth_tx_full(struct net_device *dev)
 {
-	struct meth_private *priv = (struct meth_private *) dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 
 	return (priv->tx_count >= TX_RING_ENTRIES - 1);
 }
 
 static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
 {
-	struct meth_private *priv = dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 	unsigned long status;
 	struct sk_buff *skb;
 	unsigned long rptr = (int_status&TX_INFO_RPTR) >> 16;
@@ -537,7 +536,7 @@
 
 static void meth_error(struct net_device* dev, unsigned status)
 {
-	struct meth_private *priv = (struct meth_private *) dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 
 	printk(KERN_WARNING "meth: error status: 0x%08x\n",status);
 	/* check for errors too... */
@@ -571,7 +570,7 @@
 static irqreturn_t meth_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
-	struct meth_private *priv = (struct meth_private *) dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 	unsigned long status;
 
 	status = mace->eth.int_stat;
@@ -696,7 +695,7 @@
  */
 static int meth_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	struct meth_private *priv = (struct meth_private *) dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->meth_lock, flags);
@@ -727,7 +726,7 @@
  */
 static void meth_tx_timeout(struct net_device *dev)
 {
-	struct meth_private *priv = (struct meth_private *) dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 	unsigned long flags;
 
 	printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
@@ -779,7 +778,7 @@
  */
 static struct net_device_stats *meth_stats(struct net_device *dev)
 {
-	struct meth_private *priv = (struct meth_private *) dev->priv;
+	struct meth_private *priv = netdev_priv(dev);
 	return &priv->stats;
 }
 
@@ -808,7 +807,7 @@
 	dev->irq	     = MACE_ETHERNET_IRQ;
 	dev->base_addr	     = (unsigned long)&mace->eth;
 
-	priv = (struct meth_private *) dev->priv;
+	priv = netdev_priv(dev);
 	spin_lock_init(&priv->meth_lock);
 
 	ret = register_netdev(dev);
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index c946998..f42b9e2 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include <linux/sched.h>
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
 #include <linux/platform_device.h>
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index b3bf864..d98e53e 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -2780,7 +2780,6 @@
 	.get_link               = mv643xx_eth_get_link,
 	.get_sg			= ethtool_op_get_sg,
 	.set_sg			= ethtool_op_set_sg,
-	.get_strings            = mv643xx_get_strings,
 	.get_stats_count        = mv643xx_get_stats_count,
 	.get_ethtool_stats      = mv643xx_get_ethtool_stats,
 	.get_strings            = mv643xx_get_strings,
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index ffa0afd..adf29dd 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -244,6 +244,9 @@
 	MII_EN_SCRM	= 0x0004,	/* enable scrambler (tp) */
 };
 
+enum {
+	NATSEMI_FLAG_IGNORE_PHY		= 0x1,
+};
 
 /* array of board data directly indexed by pci_tbl[x].driver_data */
 static const struct {
@@ -251,10 +254,12 @@
 	unsigned long flags;
 	unsigned int eeprom_size;
 } natsemi_pci_info[] __devinitdata = {
+	{ "Aculab E1/T1 PMXc cPCI carrier card", NATSEMI_FLAG_IGNORE_PHY, 128 },
 	{ "NatSemi DP8381[56]", 0, 24 },
 };
 
 static const struct pci_device_id natsemi_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_NS, 0x0020, 0x12d9,     0x000c,     0, 0, 0 },
 	{ PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ }	/* terminate list */
 };
@@ -568,6 +573,8 @@
 	u32 intr_status;
 	/* Do not touch the nic registers */
 	int hands_off;
+	/* Don't pay attention to the reported link state. */
+	int ignore_phy;
 	/* external phy that is used: only valid if dev->if_port != PORT_TP */
 	int mii;
 	int phy_addr_external;
@@ -696,7 +703,10 @@
 	struct netdev_private *np = netdev_priv(dev);
 	u32 tmp;
 
-	netif_carrier_off(dev);
+	if (np->ignore_phy)
+		netif_carrier_on(dev);
+	else
+		netif_carrier_off(dev);
 
 	/* get the initial settings from hardware */
 	tmp            = mdio_read(dev, MII_BMCR);
@@ -806,8 +816,13 @@
 	np->hands_off = 0;
 	np->intr_status = 0;
 	np->eeprom_size = natsemi_pci_info[chip_idx].eeprom_size;
+	if (natsemi_pci_info[chip_idx].flags & NATSEMI_FLAG_IGNORE_PHY)
+		np->ignore_phy = 1;
+	else
+		np->ignore_phy = 0;
 
 	/* Initial port:
+	 * - If configured to ignore the PHY set up for external.
 	 * - If the nic was configured to use an external phy and if find_mii
 	 *   finds a phy: use external port, first phy that replies.
 	 * - Otherwise: internal port.
@@ -815,7 +830,7 @@
 	 * The address would be used to access a phy over the mii bus, but
 	 * the internal phy is accessed through mapped registers.
 	 */
-	if (readl(ioaddr + ChipConfig) & CfgExtPhy)
+	if (np->ignore_phy || readl(ioaddr + ChipConfig) & CfgExtPhy)
 		dev->if_port = PORT_MII;
 	else
 		dev->if_port = PORT_TP;
@@ -825,7 +840,9 @@
 
 	if (dev->if_port != PORT_TP) {
 		np->phy_addr_external = find_mii(dev);
-		if (np->phy_addr_external == PHY_ADDR_NONE) {
+		/* If we're ignoring the PHY it doesn't matter if we can't
+		 * find one. */
+		if (!np->ignore_phy && np->phy_addr_external == PHY_ADDR_NONE) {
 			dev->if_port = PORT_TP;
 			np->phy_addr_external = PHY_ADDR_INTERNAL;
 		}
@@ -891,6 +908,8 @@
 		printk("%02x, IRQ %d", dev->dev_addr[i], irq);
 		if (dev->if_port == PORT_TP)
 			printk(", port TP.\n");
+		else if (np->ignore_phy)
+			printk(", port MII, ignoring PHY\n");
 		else
 			printk(", port MII, phy ad %d.\n", np->phy_addr_external);
 	}
@@ -1571,9 +1590,13 @@
 {
 	struct netdev_private *np = netdev_priv(dev);
 	void __iomem * ioaddr = ns_ioaddr(dev);
-	int duplex;
+	int duplex = np->duplex;
 	u16 bmsr;
 
+	/* If we are ignoring the PHY then don't try reading it. */
+	if (np->ignore_phy)
+		goto propagate_state;
+
 	/* The link status field is latched: it remains low after a temporary
 	 * link failure until it's read. We need the current link status,
 	 * thus read twice.
@@ -1585,7 +1608,7 @@
 		if (netif_carrier_ok(dev)) {
 			if (netif_msg_link(np))
 				printk(KERN_NOTICE "%s: link down.\n",
-					dev->name);
+				       dev->name);
 			netif_carrier_off(dev);
 			undo_cable_magic(dev);
 		}
@@ -1609,6 +1632,7 @@
 			duplex = 1;
 	}
 
+propagate_state:
 	/* if duplex is set then bit 28 must be set, too */
 	if (duplex ^ !!(np->rx_config & RxAcceptTx)) {
 		if (netif_msg_link(np))
@@ -2819,6 +2843,15 @@
 	}
 
 	/*
+	 * If we're ignoring the PHY then autoneg and the internal
+	 * transciever are really not going to work so don't let the
+	 * user select them.
+	 */
+	if (np->ignore_phy && (ecmd->autoneg == AUTONEG_ENABLE ||
+			       ecmd->port == PORT_TP))
+		return -EINVAL;
+
+	/*
 	 * maxtxpkt, maxrxpkt: ignored for now.
 	 *
 	 * transceiver:
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 3f3896e..2807ef4 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -252,7 +252,7 @@
 #define netxen_set_msg_ctxid(config_word, val)	\
 	((config_word) &= ~(0x3ff<<18), (config_word) |= (val & 0x3ff) << 18)
 #define netxen_set_msg_opcode(config_word, val)	\
-	((config_word) &= ~(0xf<<24), (config_word) |= (val & 0xf) << 24)
+	((config_word) &= ~(0xf<<28), (config_word) |= (val & 0xf) << 28)
 
 struct netxen_rcv_context {
 	__le64 rcv_ring_addr;
@@ -303,14 +303,14 @@
 	(cmd_desc)->flags_opcode |= cpu_to_le16((val) & 0x7f))
 #define netxen_set_cmd_desc_opcode(cmd_desc, val)	\
 	((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x3f<<7), \
-	(cmd_desc)->flags_opcode |= cpu_to_le16((val) & (0x3f<<7)))
+	(cmd_desc)->flags_opcode |= cpu_to_le16(((val & 0x3f)<<7)))
 
 #define netxen_set_cmd_desc_num_of_buff(cmd_desc, val)	\
 	((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xff), \
 	(cmd_desc)->num_of_buffers_total_length |= cpu_to_le32((val) & 0xff))
 #define netxen_set_cmd_desc_totallength(cmd_desc, val)	\
-	((cmd_desc)->num_of_buffers_total_length &= cpu_to_le32(0xff), \
-	(cmd_desc)->num_of_buffers_total_length |= cpu_to_le32(val << 24))
+	((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xffffff00), \
+	(cmd_desc)->num_of_buffers_total_length |= cpu_to_le32(val << 8))
 
 #define netxen_get_cmd_desc_opcode(cmd_desc)	\
 	((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003F)
@@ -1040,6 +1040,7 @@
 int netxen_backup_crbinit(struct netxen_adapter *adapter);
 int netxen_flash_erase_secondary(struct netxen_adapter *adapter);
 int netxen_flash_erase_primary(struct netxen_adapter *adapter);
+void netxen_halt_pegs(struct netxen_adapter *adapter);
 
 int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data);
 int netxen_rom_se(struct netxen_adapter *adapter, int addr);
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index cc0efe2..6252e9a 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -402,7 +402,7 @@
 	wol->wolopts = 0;
 }
 
-static u32 netxen_nic_get_link(struct net_device *dev)
+static u32 netxen_nic_test_link(struct net_device *dev)
 {
 	struct netxen_port *port = netdev_priv(dev);
 	struct netxen_adapter *adapter = port->adapter;
@@ -459,6 +459,7 @@
 	int ret;
 
 	if (flash_start == 0) {
+		netxen_halt_pegs(adapter);
 		ret = netxen_flash_unlock(adapter);
 		if (ret < 0) {
 			printk(KERN_ERR "%s: Flash unlock failed.\n",
@@ -712,7 +713,7 @@
 {
 	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {	/* offline tests */
 		/* link test */
-		if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+		if (!(data[4] = (u64) netxen_nic_test_link(dev)))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		if (netif_running(dev))
@@ -727,7 +728,7 @@
 			dev->open(dev);
 	} else {		/* online tests */
 		/* link test */
-		if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+		if (!(data[4] = (u64) netxen_nic_test_link(dev)))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		/* other tests pass by default */
@@ -783,7 +784,7 @@
 	.get_regs_len = netxen_nic_get_regs_len,
 	.get_regs = netxen_nic_get_regs,
 	.get_wol = netxen_nic_get_wol,
-	.get_link = netxen_nic_get_link,
+	.get_link = ethtool_op_get_link,
 	.get_eeprom_len = netxen_nic_get_eeprom_len,
 	.get_eeprom = netxen_nic_get_eeprom,
 	.set_eeprom = netxen_nic_set_eeprom,
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index f263232..7195af3 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -420,6 +420,7 @@
 	for (i = 0; i < size / sizeof(u32); i++) {
 		if (netxen_rom_fast_read(adapter, addr, ptr32) == -1)
 			return -1;
+		*ptr32 = cpu_to_le32(*ptr32);
 		ptr32++;
 		addr += sizeof(u32);
 	}
@@ -428,6 +429,7 @@
 
 		if (netxen_rom_fast_read(adapter, addr, &local) == -1)
 			return -1;
+		local = cpu_to_le32(local);
 		memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
 	}
 
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index f7bb8c9..2f32436 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -717,6 +717,14 @@
 	return ret;
 }
 
+void netxen_halt_pegs(struct netxen_adapter *adapter)
+{
+	 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x3c, 1);
+	 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x3c, 1);
+	 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x3c, 1);
+	 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x3c, 1);
+}
+
 int netxen_flash_unlock(struct netxen_adapter *adapter)
 {
 	int ret = 0;
@@ -1246,7 +1254,7 @@
 	 * the netdev which is associated with that device.
 	 */
 
-	consumer = *(adapter->cmd_consumer);
+	consumer = le32_to_cpu(*(adapter->cmd_consumer));
 	if (last_consumer == consumer) {	/* Ring is empty    */
 		DPRINTK(INFO, "last_consumer %d == consumer %d\n",
 			last_consumer, consumer);
@@ -1340,7 +1348,7 @@
 	if (adapter->last_cmd_consumer == consumer &&
 	    (((adapter->cmd_producer + 1) %
 	      adapter->max_tx_desc_count) == adapter->last_cmd_consumer)) {
-		consumer = *(adapter->cmd_consumer);
+		consumer = le32_to_cpu(*(adapter->cmd_consumer));
 	}
 	done = (adapter->last_cmd_consumer == consumer);
 
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 69c1b9d..225ff55 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -434,12 +434,13 @@
 		adapter->port_count++;
 		adapter->port[i] = port;
 	}
-
+#ifndef CONFIG_PPC64
 	writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
 	netxen_pinit_from_rom(adapter, 0);
 	udelay(500);
 	netxen_load_firmware(adapter);
 	netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+#endif
 	/*
 	 * delay a while to ensure that the Pegs are up & running.
 	 * Otherwise, we might see some flaky behaviour.
@@ -619,8 +620,8 @@
 		}
 		adapter->irq = adapter->ahw.pdev->irq;
 		err = request_irq(adapter->ahw.pdev->irq, &netxen_intr,
-				  SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name,
-				  adapter);
+				  IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+				  netdev->name, adapter);
 		if (err) {
 			printk(KERN_ERR "request_irq failed with: %d\n", err);
 			netxen_free_hw_resources(adapter);
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 40d7003..d5d9507 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -458,7 +458,7 @@
 
 int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
 {
-	long reg = 0, ret = 0;
+	u32 reg = 0, ret = 0;
 
 	if (adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) {
 		netxen_crb_writelit_adapter(adapter,
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 448bf4a..c7bd9c1 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -915,7 +915,7 @@
 	if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) {
 		if (!lp->fast_poll)
 			printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-		el3_interrupt(dev->irq, lp);
+		el3_interrupt(dev->irq, dev);
 		lp->fast_poll = HZ;
 	}
 	if (lp->fast_poll) {
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 530df88..2561f76 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -1927,7 +1927,7 @@
     if (smc->watchdog++ && ((i>>8) & i)) {
 	if (!smc->fast_poll)
 	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-	smc_interrupt(dev->irq, smc);
+	smc_interrupt(dev->irq, dev);
 	smc->fast_poll = HZ;
     }
     if (smc->fast_poll) {
diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c
index ae60e6e..a1bd599 100644
--- a/drivers/net/phy/cicada.c
+++ b/drivers/net/phy/cicada.c
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index aa7983f..519baa3 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 8613539..66da91b 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 69d2325..4cf3324 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 0ad2532..22aec5c 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
@@ -43,6 +42,19 @@
 #define MII_M1011_IMASK_INIT		0x6400
 #define MII_M1011_IMASK_CLEAR		0x0000
 
+#define MII_M1011_PHY_SCR		0x10
+#define MII_M1011_PHY_SCR_AUTO_CROSS	0x0060
+
+#define MII_M1145_PHY_EXT_CR		0x14
+#define MII_M1145_RGMII_RX_DELAY	0x0080
+#define MII_M1145_RGMII_TX_DELAY	0x0002
+
+#define M1145_DEV_FLAGS_RESISTANCE	0x00000001
+
+#define MII_M1111_PHY_LED_CONTROL	0x18
+#define MII_M1111_PHY_LED_DIRECT	0x4100
+#define MII_M1111_PHY_LED_COMBINE	0x411c
+
 MODULE_DESCRIPTION("Marvell PHY driver");
 MODULE_AUTHOR("Andy Fleming");
 MODULE_LICENSE("GPL");
@@ -64,7 +76,7 @@
 {
 	int err;
 
-	if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
 		err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
 	else
 		err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
@@ -104,34 +116,153 @@
 	if (err < 0)
 		return err;
 
+	err = phy_write(phydev, MII_M1011_PHY_SCR,
+			MII_M1011_PHY_SCR_AUTO_CROSS);
+	if (err < 0)
+		return err;
+
+	err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
+			MII_M1111_PHY_LED_DIRECT);
+	if (err < 0)
+		return err;
 
 	err = genphy_config_aneg(phydev);
 
 	return err;
 }
 
+static int m88e1145_config_init(struct phy_device *phydev)
+{
+	int err;
+
+	/* Take care of errata E0 & E1 */
+	err = phy_write(phydev, 0x1d, 0x001b);
+	if (err < 0)
+		return err;
+
+	err = phy_write(phydev, 0x1e, 0x418f);
+	if (err < 0)
+		return err;
+
+	err = phy_write(phydev, 0x1d, 0x0016);
+	if (err < 0)
+		return err;
+
+	err = phy_write(phydev, 0x1e, 0xa2da);
+	if (err < 0)
+		return err;
+
+	if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
+		int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
+		if (temp < 0)
+			return temp;
+
+		temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY);
+
+		err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp);
+		if (err < 0)
+			return err;
+
+		if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) {
+			err = phy_write(phydev, 0x1d, 0x0012);
+			if (err < 0)
+				return err;
+
+			temp = phy_read(phydev, 0x1e);
+			if (temp < 0)
+				return temp;
+
+			temp &= 0xf03f;
+			temp |= 2 << 9;	/* 36 ohm */
+			temp |= 2 << 6;	/* 39 ohm */
+
+			err = phy_write(phydev, 0x1e, temp);
+			if (err < 0)
+				return err;
+
+			err = phy_write(phydev, 0x1d, 0x3);
+			if (err < 0)
+				return err;
+
+			err = phy_write(phydev, 0x1e, 0x8000);
+			if (err < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
 
 static struct phy_driver m88e1101_driver = {
-	.phy_id		= 0x01410c00,
-	.phy_id_mask	= 0xffffff00,
-	.name		= "Marvell 88E1101",
-	.features	= PHY_GBIT_FEATURES,
-	.flags		= PHY_HAS_INTERRUPT,
-	.config_aneg	= &marvell_config_aneg,
-	.read_status	= &genphy_read_status,
-	.ack_interrupt	= &marvell_ack_interrupt,
-	.config_intr	= &marvell_config_intr,
-	.driver 	= { .owner = THIS_MODULE,},
+	.phy_id = 0x01410c60,
+	.phy_id_mask = 0xfffffff0,
+	.name = "Marvell 88E1101",
+	.features = PHY_GBIT_FEATURES,
+	.flags = PHY_HAS_INTERRUPT,
+	.config_aneg = &marvell_config_aneg,
+	.read_status = &genphy_read_status,
+	.ack_interrupt = &marvell_ack_interrupt,
+	.config_intr = &marvell_config_intr,
+	.driver = {.owner = THIS_MODULE,},
+};
+
+static struct phy_driver m88e1111s_driver = {
+	.phy_id = 0x01410cc0,
+	.phy_id_mask = 0xfffffff0,
+	.name = "Marvell 88E1111",
+	.features = PHY_GBIT_FEATURES,
+	.flags = PHY_HAS_INTERRUPT,
+	.config_aneg = &marvell_config_aneg,
+	.read_status = &genphy_read_status,
+	.ack_interrupt = &marvell_ack_interrupt,
+	.config_intr = &marvell_config_intr,
+	.driver = {.owner = THIS_MODULE,},
+};
+
+static struct phy_driver m88e1145_driver = {
+	.phy_id = 0x01410cd0,
+	.phy_id_mask = 0xfffffff0,
+	.name = "Marvell 88E1145",
+	.features = PHY_GBIT_FEATURES,
+	.flags = PHY_HAS_INTERRUPT,
+	.config_init = &m88e1145_config_init,
+	.config_aneg = &marvell_config_aneg,
+	.read_status = &genphy_read_status,
+	.ack_interrupt = &marvell_ack_interrupt,
+	.config_intr = &marvell_config_intr,
+	.driver = {.owner = THIS_MODULE,},
 };
 
 static int __init marvell_init(void)
 {
-	return phy_driver_register(&m88e1101_driver);
+	int ret;
+
+	ret = phy_driver_register(&m88e1101_driver);
+	if (ret)
+		return ret;
+
+	ret = phy_driver_register(&m88e1111s_driver);
+	if (ret)
+		goto err1111s;
+
+	ret = phy_driver_register(&m88e1145_driver);
+	if (ret)
+		goto err1145;
+
+	return 0;
+
+      err1145:
+	phy_driver_unregister(&m88e1111s_driver);
+      err1111s:
+	phy_driver_unregister(&m88e1101_driver);
+	return ret;
 }
 
 static void __exit marvell_exit(void)
 {
 	phy_driver_unregister(&m88e1101_driver);
+	phy_driver_unregister(&m88e1111s_driver);
+	phy_driver_unregister(&m88e1145_driver);
 }
 
 module_init(marvell_init);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index cf6660c..b31ce27 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 9765fa6..c94a1fb 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -16,7 +16,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index a4d7529..7d5b6d1 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -15,7 +15,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
@@ -139,7 +138,7 @@
  */
 struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
 		void (*handler)(struct net_device *), u32 flags,
-		u32 interface)
+		phy_interface_t interface)
 {
 	struct phy_device *phydev;
 
@@ -188,7 +187,7 @@
 }
 
 struct phy_device *phy_attach(struct net_device *dev,
-		const char *phy_id, u32 flags, u32 interface)
+		const char *phy_id, u32 flags, phy_interface_t interface)
 {
 	struct bus_type *bus = &mdio_bus_type;
 	struct phy_device *phydev;
diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c
index 2b50e17..23062d0 100644
--- a/drivers/net/phy/qsemi.c
+++ b/drivers/net/phy/qsemi.c
@@ -14,7 +14,6 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index c6de566..11b575f 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -83,7 +83,7 @@
 	int		dead;		/* unit/channel has been shut down */
 };
 
-#define PF_TO_X(pf, X)		((X *)((char *)(pf) - offsetof(X, file)))
+#define PF_TO_X(pf, X)		container_of(pf, X, file)
 
 #define PF_TO_PPP(pf)		PF_TO_X(pf, struct ppp)
 #define PF_TO_CHANNEL(pf)	PF_TO_X(pf, struct channel)
@@ -834,7 +834,7 @@
 	return err;
 }
 
-static struct file_operations ppp_device_fops = {
+static const struct file_operations ppp_device_fops = {
 	.owner		= THIS_MODULE,
 	.read		= ppp_read,
 	.write		= ppp_write,
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 315d5c3..860bb0f 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -1043,7 +1043,7 @@
 	return seq_open(file, &pppoe_seq_ops);
 }
 
-static struct file_operations pppoe_seq_fops = {
+static const struct file_operations pppoe_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= pppoe_seq_open,
 	.read		= seq_read,
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 2429b27..a142cdf 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -3228,7 +3228,7 @@
 {
 	struct net_device *ndev = qdev->ndev;
 	int err;
-	unsigned long irq_flags = SA_SAMPLE_RANDOM | SA_SHIRQ;
+	unsigned long irq_flags = IRQF_SAMPLE_RANDOM | IRQF_SHARED;
 	unsigned long hw_flags;
 
 	if (ql_alloc_mem_resources(qdev)) {
@@ -3247,7 +3247,7 @@
 		} else {
 			printk(KERN_INFO PFX "%s: MSI Enabled...\n", qdev->ndev->name);
 			set_bit(QL_MSI_ENABLED,&qdev->flags);
-			irq_flags &= ~SA_SHIRQ;
+			irq_flags &= ~IRQF_SHARED;
 		}
 	}
 
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 577babd..13cf06e 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1733,6 +1733,8 @@
 	assert(dev != NULL);
 	assert(tp != NULL);
 
+	flush_scheduled_work();
+
 	unregister_netdev(dev);
 	rtl8169_release_board(pdev, dev, tp->mmio_addr);
 	pci_set_drvdata(pdev, NULL);
@@ -2016,7 +2018,7 @@
 	if (!skb)
 		goto err_out;
 
-	skb_reserve(skb, (align - 1) & (u32)skb->data);
+	skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
 	*sk_buff = skb;
 
 	mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
@@ -2161,10 +2163,13 @@
 	struct net_device *dev = tp->dev;
 	int ret;
 
-	if (netif_running(dev)) {
-		rtl8169_wait_for_quiescence(dev);
-		rtl8169_close(dev);
-	}
+	rtnl_lock();
+
+	if (!netif_running(dev))
+		goto out_unlock;
+
+	rtl8169_wait_for_quiescence(dev);
+	rtl8169_close(dev);
 
 	ret = rtl8169_open(dev);
 	if (unlikely(ret < 0)) {
@@ -2179,6 +2184,9 @@
 		}
 		rtl8169_schedule_work(dev, rtl8169_reinit_task);
 	}
+
+out_unlock:
+	rtnl_unlock();
 }
 
 static void rtl8169_reset_task(struct work_struct *work)
@@ -2187,8 +2195,10 @@
 		container_of(work, struct rtl8169_private, task.work);
 	struct net_device *dev = tp->dev;
 
+	rtnl_lock();
+
 	if (!netif_running(dev))
-		return;
+		goto out_unlock;
 
 	rtl8169_wait_for_quiescence(dev);
 
@@ -2210,6 +2220,9 @@
 		}
 		rtl8169_schedule_work(dev, rtl8169_reset_task);
 	}
+
+out_unlock:
+	rtnl_unlock();
 }
 
 static void rtl8169_tx_timeout(struct net_device *dev)
@@ -2487,7 +2500,7 @@
 
 		skb = dev_alloc_skb(pkt_size + align);
 		if (skb) {
-			skb_reserve(skb, (align - 1) & (u32)skb->data);
+			skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
 			eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
 			*sk_buff = skb;
 			rtl8169_mark_to_asic(desc, rx_buf_sz);
@@ -2722,8 +2735,6 @@
 
 	netif_stop_queue(dev);
 
-	flush_scheduled_work();
-
 core_down:
 	spin_lock_irq(&tp->lock);
 
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 639fbc0..fd85648 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -59,7 +59,6 @@
 #include <linux/stddef.h>
 #include <linux/ioctl.h>
 #include <linux/timex.h>
-#include <linux/sched.h>
 #include <linux/ethtool.h>
 #include <linux/workqueue.h>
 #include <linux/if_vlan.h>
@@ -3759,7 +3758,6 @@
 {
 	struct s2io_nic *sp = dev->priv;
 
-	flush_scheduled_work();
 	netif_stop_queue(dev);
 	/* Reset card, kill tasklet and free Tx and Rx buffers. */
 	s2io_card_down(sp);
@@ -5848,9 +5846,14 @@
 	register u64 val64;
 	u16 subid;
 
+	rtnl_lock();
+
+	if (!netif_running(dev))
+		goto out_unlock;
+
 	if (test_and_set_bit(0, &(nic->link_state))) {
 		/* The card is being reset, no point doing anything */
-		return;
+		goto out_unlock;
 	}
 
 	subid = nic->pdev->subsystem_device;
@@ -5904,6 +5907,9 @@
 		s2io_link(nic, LINK_DOWN);
 	}
 	clear_bit(0, &(nic->link_state));
+
+out_unlock:
+	rtnl_lock();
 }
 
 static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
@@ -6357,6 +6363,11 @@
 	struct s2io_nic *sp = container_of(work, struct s2io_nic, rst_timer_task);
 	struct net_device *dev = sp->dev;
 
+	rtnl_lock();
+
+	if (!netif_running(dev))
+		goto out_unlock;
+
 	s2io_card_down(sp);
 	if (s2io_card_up(sp)) {
 		DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
@@ -6365,7 +6376,8 @@
 	netif_wake_queue(dev);
 	DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
 		  dev->name);
-
+out_unlock:
+	rtnl_unlock();
 }
 
 /**
@@ -7174,6 +7186,8 @@
 		return;
 	}
 
+	flush_scheduled_work();
+
 	sp = dev->priv;
 	unregister_netdev(dev);
 
@@ -7298,7 +7312,7 @@
 {
 	struct iphdr *ip = lro->iph;
 	struct tcphdr *tcp = lro->tcph;
-	u16 nchk;
+	__sum16 nchk;
 	struct stat_block *statinfo = sp->mac_control.stats_info;
 	DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
 
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index a5e1a51..0de0c65 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -727,12 +727,12 @@
 	struct iphdr	*iph;
 	struct tcphdr	*tcph;
 	u32		tcp_next_seq;
-	u32		tcp_ack;
+	__be32		tcp_ack;
 	int		total_len;
 	int		frags_len;
 	int		sg_num;
 	int		in_use;
-	u16		window;
+	__be16		window;
 	u32		cur_tsval;
 	u32		cur_tsecr;
 	u8		saw_ts;
@@ -1005,7 +1005,7 @@
 static void s2io_card_down(struct s2io_nic *nic);
 static int s2io_card_up(struct s2io_nic *nic);
 static int get_xena_rev_id(struct pci_dev *pdev);
-static int wait_for_cmd_complete(void *addr, u64 busy_bit);
+static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit);
 static int s2io_add_isr(struct s2io_nic * sp);
 static void s2io_rem_isr(struct s2io_nic * sp);
 
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index 7f800fe..4a926f2 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -1035,7 +1035,7 @@
 	priv->tx_head = priv->tx_tail = 0;
 
 	err = request_irq(pdev->irq, sc92031_interrupt,
-			SA_SHIRQ, dev->name, dev);
+			IRQF_SHARED, dev->name, dev);
 	if (unlikely(err < 0))
 		goto out_request_irq;
 
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 45d91b1..b08508b 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -909,6 +909,9 @@
 
 	rtnl_lock();
 
+	if (!netif_running(dev))
+		goto out_unlock;
+
 	val = mdio_read(ioaddr, phy_id, MII_BMCR);
 	if (val & BMCR_RESET) {
 		// FIXME: needlessly high ?  -- FR 02/07/2005
@@ -981,6 +984,7 @@
 		netif_carrier_on(dev);
 	}
 
+out_unlock:
 	rtnl_unlock();
 }
 
@@ -1102,8 +1106,6 @@
 
 	netif_stop_queue(dev);
 
-	flush_scheduled_work();
-
 	do {
 		spin_lock_irq(&tp->lock);
 
@@ -1857,6 +1859,7 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 
 	sis190_mii_remove(dev);
+	flush_scheduled_work();
 	unregister_netdev(dev);
 	sis190_release_board(pdev);
 	pci_set_drvdata(pdev, NULL);
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 92d11b9..e94ab25 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -5188,6 +5188,9 @@
 
 static int __init skge_init(void)
 {
+	printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver"
+	       " and is scheduled for removal\n");
+
 	return pci_register_driver(&skge_driver);
 }
 
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index e482e7f..c3d2e0a 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -1419,7 +1419,8 @@
 	mutex_unlock(&hw->phy_mutex);
 
 nochange:
-	schedule_delayed_work(&skge->link_thread, LINK_HZ);
+	if (netif_running(dev))
+		schedule_delayed_work(&skge->link_thread, LINK_HZ);
 }
 
 static void genesis_mac_init(struct skge_hw *hw, int port)
@@ -2530,7 +2531,7 @@
 
 	netif_stop_queue(dev);
 	if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
-		cancel_rearming_delayed_work(&skge->link_thread);
+		cancel_delayed_work(&skge->link_thread);
 
 	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
 	if (hw->chip_id == CHIP_ID_GENESIS)
@@ -3690,6 +3691,8 @@
 	if (!hw)
 		return;
 
+	flush_scheduled_work();
+
 	if ((dev1 = hw->dev[1]))
 		unregister_netdev(dev1);
 	dev0 = hw->dev[0];
@@ -3704,8 +3707,6 @@
 	skge_write16(hw, B0_LED, LED_STAT_OFF);
 	skge_write8(hw, B0_CTST, CS_RST_SET);
 
-	flush_scheduled_work();
-
 	free_irq(pdev->irq, hw);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index f2ab3d5..52edbd7 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -49,7 +49,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"1.12"
+#define DRV_VERSION		"1.13"
 #define PFX			DRV_NAME " "
 
 /*
@@ -1742,13 +1742,6 @@
 	reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
 	gma_write16(hw, port, GM_GP_CTRL, reg);
 
-	if (sky2->flow_status == FC_RX) {
-		/* restore Asymmetric Pause bit */
-		gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
-			     gm_phy_read(hw, port, PHY_MARV_AUNE_ADV)
-			     | PHY_M_AN_ASP);
-	}
-
 	netif_carrier_off(sky2->netdev);
 	netif_stop_queue(sky2->netdev);
 
@@ -1773,10 +1766,10 @@
 {
 	struct sky2_hw *hw = sky2->hw;
 	unsigned port = sky2->port;
-	u16 lpa;
+	u16 advert, lpa;
 
+	advert = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV);
 	lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP);
-
 	if (lpa & PHY_M_AN_RF) {
 		printk(KERN_ERR PFX "%s: remote fault", sky2->netdev->name);
 		return -1;
@@ -1791,20 +1784,40 @@
 	sky2->speed = sky2_phy_speed(hw, aux);
 	sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
 
-	/* Pause bits are offset (9..8) */
-	if (hw->chip_id == CHIP_ID_YUKON_XL
-	    || hw->chip_id == CHIP_ID_YUKON_EC_U
-	    || hw->chip_id == CHIP_ID_YUKON_EX)
-		aux >>= 6;
+	/* Since the pause result bits seem to in different positions on
+	 * different chips. look at registers.
+	 */
+	if (!sky2_is_copper(hw)) {
+		/* Shift for bits in fiber PHY */
+		advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM);
+		lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM);
 
-	sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN,
-				      aux & PHY_M_PS_TX_P_EN);
+		if (advert & ADVERTISE_1000XPAUSE)
+			advert |= ADVERTISE_PAUSE_CAP;
+		if (advert & ADVERTISE_1000XPSE_ASYM)
+			advert |= ADVERTISE_PAUSE_ASYM;
+		if (lpa & LPA_1000XPAUSE)
+			lpa |= LPA_PAUSE_CAP;
+		if (lpa & LPA_1000XPAUSE_ASYM)
+			lpa |= LPA_PAUSE_ASYM;
+	}
+
+	sky2->flow_status = FC_NONE;
+	if (advert & ADVERTISE_PAUSE_CAP) {
+		if (lpa & LPA_PAUSE_CAP)
+			sky2->flow_status = FC_BOTH;
+		else if (advert & ADVERTISE_PAUSE_ASYM)
+			sky2->flow_status = FC_RX;
+	} else if (advert & ADVERTISE_PAUSE_ASYM) {
+		if ((lpa & LPA_PAUSE_CAP) && (lpa & LPA_PAUSE_ASYM))
+			sky2->flow_status = FC_TX;
+	}
 
 	if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000
 	    && !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX))
 		sky2->flow_status = FC_NONE;
 
-	if (aux & PHY_M_PS_RX_P_EN)
+	if (sky2->flow_status & FC_TX)
 		sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
 	else
 		sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
@@ -1853,16 +1866,13 @@
 	spin_unlock(&sky2->phy_lock);
 }
 
-
 /* Transmit timeout is only called if we are running, carrier is up
  * and tx queue is full (stopped).
- * Called with netif_tx_lock held.
  */
 static void sky2_tx_timeout(struct net_device *dev)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 	struct sky2_hw *hw = sky2->hw;
-	u32 imask;
 
 	if (netif_msg_timer(sky2))
 		printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
@@ -1872,19 +1882,8 @@
 	       sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
 	       sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE)));
 
-	imask = sky2_read32(hw, B0_IMSK);	/* block IRQ in hw */
-	sky2_write32(hw, B0_IMSK, 0);
-	sky2_read32(hw, B0_IMSK);
-
-	netif_poll_disable(hw->dev[0]);		/* stop NAPI poll */
-	synchronize_irq(hw->pdev->irq);
-
-	netif_start_queue(dev);			/* don't wakeup during flush */
-	sky2_tx_complete(sky2, sky2->tx_prod);	/* Flush transmit queue */
-
-	sky2_write32(hw, B0_IMSK, imask);
-
-	sky2_phy_reinit(sky2);			/* this clears flow control etc */
+	/* can't restart safely under softirq */
+	schedule_work(&hw->restart_work);
 }
 
 static int sky2_change_mtu(struct net_device *dev, int new_mtu)
@@ -2057,9 +2056,6 @@
 	if (!(status & GMR_FS_RX_OK))
 		goto resubmit;
 
-	if (length > dev->mtu + ETH_HLEN)
-		goto oversize;
-
 	if (length < copybreak)
 		skb = receive_copy(sky2, re, length);
 	else
@@ -2069,14 +2065,10 @@
 
 	return skb;
 
-oversize:
-	++sky2->net_stats.rx_over_errors;
-	goto resubmit;
-
 error:
 	++sky2->net_stats.rx_errors;
 	if (status & GMR_FS_RX_FF_OV) {
-		sky2->net_stats.rx_fifo_errors++;
+		sky2->net_stats.rx_over_errors++;
 		goto resubmit;
 	}
 
@@ -2638,6 +2630,49 @@
 	sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
 }
 
+static void sky2_restart(struct work_struct *work)
+{
+	struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work);
+	struct net_device *dev;
+	int i, err;
+
+	dev_dbg(&hw->pdev->dev, "restarting\n");
+
+	del_timer_sync(&hw->idle_timer);
+
+	rtnl_lock();
+	sky2_write32(hw, B0_IMSK, 0);
+	sky2_read32(hw, B0_IMSK);
+
+	netif_poll_disable(hw->dev[0]);
+
+	for (i = 0; i < hw->ports; i++) {
+		dev = hw->dev[i];
+		if (netif_running(dev))
+			sky2_down(dev);
+	}
+
+	sky2_reset(hw);
+	sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+	netif_poll_enable(hw->dev[0]);
+
+	for (i = 0; i < hw->ports; i++) {
+		dev = hw->dev[i];
+		if (netif_running(dev)) {
+			err = sky2_up(dev);
+			if (err) {
+				printk(KERN_INFO PFX "%s: could not restart %d\n",
+				       dev->name, err);
+				dev_close(dev);
+			}
+		}
+	}
+
+	sky2_idle_start(hw);
+
+	rtnl_unlock();
+}
+
 static inline u8 sky2_wol_supported(const struct sky2_hw *hw)
 {
 	return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0;
@@ -3600,6 +3635,8 @@
 	}
 
 	setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw);
+	INIT_WORK(&hw->restart_work, sky2_restart);
+
 	sky2_idle_start(hw);
 
 	pci_set_drvdata(pdev, hw);
@@ -3636,6 +3673,8 @@
 
 	del_timer_sync(&hw->idle_timer);
 
+	flush_scheduled_work();
+
 	sky2_write32(hw, B0_IMSK, 0);
 	synchronize_irq(hw->pdev->irq);
 
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 3b01895..ac24bdc 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1589,7 +1589,7 @@
 
 	GMR_FS_ANY_ERR	= GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR |
 			  GMR_FS_FRAGMENT | GMR_FS_LONG_ERR |
-		  	  GMR_FS_MII_ERR | GMR_FS_GOOD_FC | GMR_FS_BAD_FC |
+		  	  GMR_FS_MII_ERR | GMR_FS_BAD_FC |
 			  GMR_FS_UN_SIZE | GMR_FS_JABBER,
 };
 
@@ -1933,6 +1933,7 @@
 	dma_addr_t   	     st_dma;
 
 	struct timer_list    idle_timer;
+	struct work_struct   restart_work;
 	int		     msi;
 	wait_queue_head_t    msi_wait;
 };
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index a0806d2..2f4b1de 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -1343,15 +1343,12 @@
 	printk(KERN_INFO "SLIP linefill/keepalive option.\n");
 #endif
 
-	slip_devs = kmalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);
+	slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);
 	if (!slip_devs) {
 		printk(KERN_ERR "SLIP: Can't allocate slip devices array!  Uaargh! (-> No SLIP available)\n");
 		return -ENOMEM;
 	}
 
-	/* Clear the pointer array, we allocate devices when we need them */
-	memset(slip_devs, 0, sizeof(struct net_device *)*slip_maxdev);
-
 	/* Fill in our line protocol discipline, and register it */
 	if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
 		printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index 7122932..ae1ae34 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -482,8 +482,7 @@
 		count -= semi_count;
 		memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
 	} else {
-		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		memcpy_fromio(skb->data, xfer_start, count);
 	}
 
 }
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index d70bc97..a52b22d 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -454,8 +454,7 @@
 		count -= semi_count;
 		memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
 	} else {
-		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		memcpy_fromio(skb->data, xfer_start, count);
 	}
 
 	outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET);	/* Disable memory. */
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
index 2c5319c..88a30e5 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/smc-ultra32.c
@@ -395,8 +395,7 @@
 			memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
 		}
 	} else {
-		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		memcpy_fromio(skb->data, xfer_start, count);
 	}
 }
 
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index bf6ff39..64ed8ff 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1907,7 +1907,7 @@
 	spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
 
 	/* free_irq(netdev->irq, netdev);*/
-	free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
+	free_irq(to_pci_dev(netdev->dev.parent)->irq, netdev);
 
 	spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
 			     SPIDER_NET_DMA_TX_FEND_VALUE);
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index d21991e..701ba4f 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -22,7 +22,6 @@
 #include <linux/module.h>
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 135c098..81a1c2e 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4,7 +4,7 @@
  * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
  * Copyright (C) 2004 Sun Microsystems Inc.
- * Copyright (C) 2005 Broadcom Corporation.
+ * Copyright (C) 2005-2007 Broadcom Corporation.
  *
  * Firmware is:
  *	Derived from proprietary unpublished source code,
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.72"
-#define DRV_MODULE_RELDATE	"January 8, 2007"
+#define DRV_MODULE_VERSION	"3.73"
+#define DRV_MODULE_RELDATE	"February 12, 2007"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -1175,8 +1175,18 @@
 
 static void tg3_power_down_phy(struct tg3 *tp)
 {
-	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+			u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
+			u32 serdes_cfg = tr32(MAC_SERDES_CFG);
+
+			sg_dig_ctrl |=
+				SG_DIG_USING_HW_AUTONEG | SG_DIG_SOFT_RESET;
+			tw32(SG_DIG_CTRL, sg_dig_ctrl);
+			tw32(MAC_SERDES_CFG, serdes_cfg | (1 << 15));
+		}
 		return;
+	}
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 		u32 val;
@@ -1340,7 +1350,8 @@
 
 		tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK |
 			    CLOCK_CTRL_PWRDOWN_PLL133, 40);
-	} else if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
+	} else if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
+		   (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)) {
 		/* do nothing */
 	} else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
 		     (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
@@ -3380,7 +3391,7 @@
 		}
 next_pkt_nopost:
 		sw_idx++;
-		sw_idx %= TG3_RX_RCB_RING_SIZE(tp);
+		sw_idx &= (TG3_RX_RCB_RING_SIZE(tp) - 1);
 
 		/* Refresh hw_idx to see if there is new work */
 		if (sw_idx == hw_idx) {
@@ -3724,13 +3735,23 @@
 	tg3_full_unlock(tp);
 }
 
+static void tg3_dump_short_state(struct tg3 *tp)
+{
+	printk(KERN_ERR PFX "DEBUG: MAC_TX_STATUS[%08x] MAC_RX_STATUS[%08x]\n",
+	       tr32(MAC_TX_STATUS), tr32(MAC_RX_STATUS));
+	printk(KERN_ERR PFX "DEBUG: RDMAC_STATUS[%08x] WDMAC_STATUS[%08x]\n",
+	       tr32(RDMAC_STATUS), tr32(WDMAC_STATUS));
+}
+
 static void tg3_tx_timeout(struct net_device *dev)
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	if (netif_msg_tx_err(tp))
+	if (netif_msg_tx_err(tp)) {
 		printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
 		       dev->name);
+		tg3_dump_short_state(tp);
+	}
 
 	schedule_work(&tp->reset_task);
 }
@@ -6583,8 +6604,9 @@
 		u32 tmp;
 
 		/* Clear CRC stats. */
-		if (!tg3_readphy(tp, 0x1e, &tmp)) {
-			tg3_writephy(tp, 0x1e, tmp | 0x8000);
+		if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) {
+			tg3_writephy(tp, MII_TG3_TEST1,
+				     tmp | MII_TG3_TEST1_CRC_EN);
 			tg3_readphy(tp, 0x14, &tmp);
 		}
 	}
@@ -7408,8 +7430,9 @@
 		u32 val;
 
 		spin_lock_bh(&tp->lock);
-		if (!tg3_readphy(tp, 0x1e, &val)) {
-			tg3_writephy(tp, 0x1e, val | 0x8000);
+		if (!tg3_readphy(tp, MII_TG3_TEST1, &val)) {
+			tg3_writephy(tp, MII_TG3_TEST1,
+				     val | MII_TG3_TEST1_CRC_EN);
 			tg3_readphy(tp, 0x14, &val);
 		} else
 			val = 0;
@@ -10779,7 +10802,9 @@
 	if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
-			tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
+			if (tp->pdev->device != PCI_DEVICE_ID_TIGON3_5756 &&
+			    tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722)
+				tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
 			if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
 				tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM;
 		} else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
@@ -11314,6 +11339,7 @@
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
 			u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
+			u32 read_water = 0x7;
 
 			/* If the 5704 is behind the EPB bridge, we can
 			 * do the less restrictive ONE_DMA workaround for
@@ -11325,8 +11351,13 @@
 			else if (ccval == 0x6 || ccval == 0x7)
 				tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
 
+			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703)
+				read_water = 4;
 			/* Set bit 23 to enable PCIX hw bug fix */
-			tp->dma_rwctrl |= 0x009f0000;
+			tp->dma_rwctrl |=
+				(read_water << DMA_RWCTRL_READ_WATER_SHIFT) |
+				(0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
+				(1 << 23);
 		} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
 			/* 5780 always in PCIX mode */
 			tp->dma_rwctrl |= 0x00144000;
@@ -12016,6 +12047,9 @@
 	tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
 	tg3_full_unlock(tp);
 
+	/* Save MSI address and data for resume.  */
+	pci_save_state(pdev);
+
 	err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
 	if (err) {
 		tg3_full_lock(tp, 0);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 80f59ac..45d477e 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1660,6 +1660,7 @@
 
 #define MII_TG3_TEST1			0x1e
 #define MII_TG3_TEST1_TRIM_EN		0x0010
+#define MII_TG3_TEST1_CRC_EN		0x8000
 
 /* There are two ways to manage the TX descriptors on the tigon3.
  * Either the descriptors are in host DMA'able memory, or they
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index 893808a..d92c5c5 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -38,7 +38,6 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
 #include <linux/crc32.h>
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 151a2e1..5643d1e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -744,7 +744,7 @@
 	return 0;
 }
 
-static struct file_operations tun_fops = {
+static const struct file_operations tun_fops = {
 	.owner	= THIS_MODULE,
 	.llseek = no_llseek,
 	.read  = do_sync_read,
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index abb8611..a2fc2bb 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1709,75 +1709,13 @@
 		if (mii_info->speed != ugeth->oldspeed) {
 			switch (mii_info->speed) {
 			case 1000:
-#ifdef CONFIG_PPC_MPC836x
-/* FIXME: This code is for 100Mbs BUG fixing,
-remove this when it is fixed!!! */
-				if (ugeth->ug_info->enet_interface ==
-				    ENET_1000_GMII)
-				/* Run the commands which initialize the PHY */
-				{
-					tempval =
-					    (u32) mii_info->mdio_read(ugeth->
-						dev, mii_info->mii_id, 0x1b);
-					tempval |= 0x000f;
-					mii_info->mdio_write(ugeth->dev,
-						mii_info->mii_id, 0x1b,
-						(u16) tempval);
-					tempval =
-					    (u32) mii_info->mdio_read(ugeth->
-						dev, mii_info->mii_id,
-						MII_BMCR);
-					mii_info->mdio_write(ugeth->dev,
-						mii_info->mii_id, MII_BMCR,
-						(u16) (tempval | BMCR_RESET));
-				} else if (ugeth->ug_info->enet_interface ==
-					   ENET_1000_RGMII)
-				/* Run the commands which initialize the PHY */
-				{
-					tempval =
-					    (u32) mii_info->mdio_read(ugeth->
-						dev, mii_info->mii_id, 0x1b);
-					tempval = (tempval & ~0x000f) | 0x000b;
-					mii_info->mdio_write(ugeth->dev,
-						mii_info->mii_id, 0x1b,
-						(u16) tempval);
-					tempval =
-					    (u32) mii_info->mdio_read(ugeth->
-						dev, mii_info->mii_id,
-						MII_BMCR);
-					mii_info->mdio_write(ugeth->dev,
-						mii_info->mii_id, MII_BMCR,
-						(u16) (tempval | BMCR_RESET));
-				}
-				msleep(4000);
-#endif				/* CONFIG_MPC8360 */
-				adjust_enet_interface(ugeth);
+				ugeth->ug_info->enet_interface = ENET_1000_RGMII;
 				break;
 			case 100:
-			case 10:
-#ifdef CONFIG_PPC_MPC836x
-/* FIXME: This code is for 100Mbs BUG fixing,
-remove this lines when it will be fixed!!! */
 				ugeth->ug_info->enet_interface = ENET_100_RGMII;
-				tempval =
-				    (u32) mii_info->mdio_read(ugeth->dev,
-							      mii_info->mii_id,
-							      0x1b);
-				tempval = (tempval & ~0x000f) | 0x000b;
-				mii_info->mdio_write(ugeth->dev,
-						     mii_info->mii_id, 0x1b,
-						     (u16) tempval);
-				tempval =
-				    (u32) mii_info->mdio_read(ugeth->dev,
-							      mii_info->mii_id,
-							      MII_BMCR);
-				mii_info->mdio_write(ugeth->dev,
-						     mii_info->mii_id, MII_BMCR,
-						     (u16) (tempval |
-							    BMCR_RESET));
-				msleep(4000);
-#endif				/* CONFIG_MPC8360 */
-				adjust_enet_interface(ugeth);
+				break;
+			case 10:
+				ugeth->ug_info->enet_interface = ENET_10_RGMII;
 				break;
 			default:
 				ugeth_warn
@@ -1785,6 +1723,7 @@
 				     dev->name, mii_info->speed);
 				break;
 			}
+			adjust_enet_interface(ugeth);
 
 			ugeth_info("%s: Speed %dBT", dev->name,
 				   mii_info->speed);
@@ -4000,8 +3939,8 @@
 	/* Grab the PHY interrupt, if necessary/possible */
 	if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
 		if (request_irq(ugeth->ug_info->phy_interrupt,
-				phy_interrupt,
-				SA_SHIRQ, "phy_interrupt", mii_info->dev) < 0) {
+				phy_interrupt, IRQF_SHARED,
+				"phy_interrupt", mii_info->dev) < 0) {
 			ugeth_err("%s: Can't get IRQ %d (PHY)",
 				  mii_info->dev->name,
 				  ugeth->ug_info->phy_interrupt);
@@ -4133,6 +4072,7 @@
 	static int mii_mng_configured = 0;
 	const phandle *ph;
 	const unsigned int *prop;
+	const void *mac_addr;
 
 	ugeth_vdbg("%s: IN", __FUNCTION__);
 
@@ -4258,7 +4198,12 @@
 
 	ugeth->ug_info = ug_info;
 	ugeth->dev = dev;
-	memcpy(dev->dev_addr, get_property(np, "mac-address", NULL), 6);
+
+	mac_addr = get_property(np, "mac-address", NULL);
+	if (mac_addr == NULL)
+		mac_addr = get_property(np, "local-mac-address", NULL);
+	if (mac_addr)
+		memcpy(dev->dev_addr, mac_addr, 6);
 
 	return 0;
 }
diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c
index 3c86592..9373d895 100644
--- a/drivers/net/ucc_geth_phy.c
+++ b/drivers/net/ucc_geth_phy.c
@@ -18,7 +18,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
@@ -376,6 +375,8 @@
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
 	ucc_geth_phy_write(mii_info, 0x14, 0x0cd2);
+	ucc_geth_phy_write(mii_info, 0x1b,
+		(ucc_geth_phy_read(mii_info, 0x1b) & ~0x000f) | 0x000b);
 	ucc_geth_phy_write(mii_info, MII_BMCR,
 		  ucc_geth_phy_read(mii_info, MII_BMCR) | BMCR_RESET);
 	msleep(4000);
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 61708cf..8897f53 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -26,7 +26,7 @@
 # There is no way to detect a comtrol sv11 - force it modular for now.
 config HOSTESS_SV11
 	tristate "Comtrol Hostess SV-11 support"
-	depends on WAN && ISA && m && ISA_DMA_API
+	depends on WAN && ISA && m && ISA_DMA_API && INET
 	help
 	  Driver for Comtrol Hostess SV-11 network card which
 	  operates on low speed synchronous serial links at up to
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 6c7dfb5..e91b5a8 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -311,7 +311,7 @@
 static int cosa_fasync(struct inode *inode, struct file *file, int on);
 #endif
 
-static struct file_operations cosa_fops = {
+static const struct file_operations cosa_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= cosa_read,
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index e6d0057..d347d59 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -53,7 +53,6 @@
 #include <linux/kernel.h>	/* printk(), and other useful stuff */
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
-#include <linux/sched.h>	/* for jiffies, HZ, etc. */
 #include <linux/cycx_drv.h>	/* API definitions */
 #include <linux/cycx_cfm.h>	/* CYCX firmware module definitions */
 #include <linux/delay.h>	/* udelay, msleep_interruptible */
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index 79b2d54..aff05db 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -101,8 +101,8 @@
 typedef struct card_s {
 	int type;		/* RSV, X21, etc. */
 	int n_ports;		/* 1 or 2 ports */
-	u8* __iomem rambase;	/* buffer memory base (virtual) */
-	u8* __iomem scabase;	/* SCA memory base (virtual) */
+	u8 __iomem *rambase;	/* buffer memory base (virtual) */
+	u8 __iomem *scabase;	/* SCA memory base (virtual) */
 	plx9050 __iomem *plxbase; /* PLX registers memory base (virtual) */
 	u32 init_ctrl_value;	/* Saved value - 9050 bug workaround */
 	u16 rx_ring_buffers;	/* number of buffers in a ring */
@@ -134,7 +134,7 @@
 static void pc300_set_iface(port_t *port)
 {
 	card_t *card = port->card;
-	u32* init_ctrl = &card->plxbase->init_ctrl;
+	u32 __iomem * init_ctrl = &card->plxbase->init_ctrl;
 	u16 msci = get_msci(port);
 	u8 rxs = port->rxs & CLK_BRG_MASK;
 	u8 txs = port->txs & CLK_BRG_MASK;
@@ -393,7 +393,7 @@
 
 	/* PLX PCI 9050 workaround for local configuration register read bug */
 	pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, scaphys);
-	card->init_ctrl_value = readl(&((plx9050*)card->scabase)->init_ctrl);
+	card->init_ctrl_value = readl(&((plx9050 __iomem *)card->scabase)->init_ctrl);
 	pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, plxphys);
 
 	/* Reset PLX */
@@ -519,10 +519,10 @@
 
 
 static struct pci_driver pc300_pci_driver = {
-	name:           "PC300",
-	id_table:       pc300_pci_tbl,
-	probe:          pc300_pci_init_one,
-	remove:         pc300_pci_remove_one,
+	.name =          "PC300",
+	.id_table =      pc300_pci_tbl,
+	.probe =         pc300_pci_init_one,
+	.remove =        pc300_pci_remove_one,
 };
 
 
@@ -542,7 +542,7 @@
 
 	CLOCK_BASE = use_crystal_clock ? 24576000 : pci_clock_freq;
 
-	return pci_module_init(&pc300_pci_driver);
+	return pci_register_driver(&pc300_pci_driver);
 }
 
 
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index a6b9c33..ca06a00 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/in.h>
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index 7f38012..a032681 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -433,7 +433,7 @@
 		memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		memcpy_fromio(skb->data, xfer_start, count);
 	}
 
 	/* Turn off 16 bit access so that reboot works.	 ISA brain-damage */
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 44a2270..a8c2bfe 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1623,7 +1623,7 @@
 
 	crypto_cipher_setkey(tfm, pkey, 16);
 	counter = 0;
-	for (i = 0; i < (sizeof(context->coeff)/sizeof(context->coeff[0])); ) {
+	for (i = 0; i < ARRAY_SIZE(context->coeff); ) {
 		aes_counter[15] = (u8)(counter >> 0);
 		aes_counter[14] = (u8)(counter >> 8);
 		aes_counter[13] = (u8)(counter >> 16);
@@ -1632,7 +1632,7 @@
 		memcpy (plain, aes_counter, 16);
 		crypto_cipher_encrypt_one(tfm, plain, plain);
 		cipher = plain;
-		for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) {
+		for (j = 0; (j < 16) && (i < ARRAY_SIZE(context->coeff)); ) {
 			context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
 			j += 4;
 		}
@@ -4430,53 +4430,53 @@
 static int proc_config_open( struct inode *inode, struct file *file );
 static int proc_wepkey_open( struct inode *inode, struct file *file );
 
-static struct file_operations proc_statsdelta_ops = {
+static const struct file_operations proc_statsdelta_ops = {
 	.read		= proc_read,
 	.open		= proc_statsdelta_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_stats_ops = {
+static const struct file_operations proc_stats_ops = {
 	.read		= proc_read,
 	.open		= proc_stats_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_status_ops = {
+static const struct file_operations proc_status_ops = {
 	.read		= proc_read,
 	.open		= proc_status_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_SSID_ops = {
+static const struct file_operations proc_SSID_ops = {
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_SSID_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_BSSList_ops = {
+static const struct file_operations proc_BSSList_ops = {
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_BSSList_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_APList_ops = {
+static const struct file_operations proc_APList_ops = {
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_APList_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_config_ops = {
+static const struct file_operations proc_config_ops = {
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_config_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_wepkey_ops = {
+static const struct file_operations proc_wepkey_ops = {
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_wepkey_open,
diff --git a/drivers/net/wireless/arlan-proc.c b/drivers/net/wireless/arlan-proc.c
index 5fa9854..015abd9 100644
--- a/drivers/net/wireless/arlan-proc.c
+++ b/drivers/net/wireless/arlan-proc.c
@@ -1216,7 +1216,7 @@
 static ctl_table arlan_root_table[] =
 {
 	{
-		.ctl_name	= 254,
+		.ctl_name	= CTL_ARLAN,
 		.procname	= "arlan",
 		.maxlen		= 0,
 		.mode		= 0555,
@@ -1244,7 +1244,7 @@
 		return 0;
 	for (i = 0; i < MAX_ARLANS && arlan_device[i]; i++)
 		arlan_table[i].ctl_name = i + 1;
-	arlan_device_sysctl_header = register_sysctl_table(arlan_root_table, 0);
+	arlan_device_sysctl_header = register_sysctl_table(arlan_root_table);
 	if (!arlan_device_sysctl_header)
 		return -1;
 
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 10bcb48..23eba69 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -42,7 +42,6 @@
 #include <linux/init.h>
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 3a064de..95ff175d 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -21,7 +21,7 @@
 #define PFX				KBUILD_MODNAME ": "
 
 #define BCM43xx_SWITCH_CORE_MAX_RETRIES	50
-#define BCM43xx_IRQWAIT_MAX_RETRIES	50
+#define BCM43xx_IRQWAIT_MAX_RETRIES	100
 
 #define BCM43xx_IO_SIZE			8192
 
@@ -333,7 +333,7 @@
 #define BCM43xx_SBF_PS2			0x04000000
 #define BCM43xx_SBF_NO_SSID_BCAST	0x08000000
 #define BCM43xx_SBF_TIME_UPDATE		0x10000000
-#define BCM43xx_SBF_80000000		0x80000000 /*FIXME: fix name*/
+#define BCM43xx_SBF_MODE_G		0x80000000
 
 /* Microcode */
 #define BCM43xx_UCODE_REVISION		0x0000
@@ -507,8 +507,6 @@
 	u8 et1macaddr[6];
 	u8 et0phyaddr:5;
 	u8 et1phyaddr:5;
-	u8 et0mdcport:1;
-	u8 et1mdcport:1;
 	u8 boardrev;
 	u8 locale:4;
 	u8 antennas_aphy:2;
@@ -542,7 +540,7 @@
 
 struct bcm43xx_phyinfo {
 	/* Hardware Data */
-	u8 version;
+	u8 analog;
 	u8 type;
 	u8 rev;
 	u16 antenna_diversity;
@@ -771,6 +769,7 @@
 	 * This is currently always BCM43xx_BUSTYPE_PCI
 	 */
 	u8 bustype;
+	u64 dma_mask;
 
 	u16 board_vendor;
 	u16 board_type;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
index b9df06a..35dbe45 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -355,37 +355,37 @@
 #undef fappend
 
 
-static struct file_operations devinfo_fops = {
+static const struct file_operations devinfo_fops = {
 	.read = devinfo_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations spromdump_fops = {
+static const struct file_operations spromdump_fops = {
 	.read = spromdump_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations drvinfo_fops = {
+static const struct file_operations drvinfo_fops = {
 	.read = drvinfo_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations tsf_fops = {
+static const struct file_operations tsf_fops = {
 	.read = tsf_read_file,
 	.write = tsf_write_file,
 	.open = open_file_generic,
 };
 
-static struct file_operations txstat_fops = {
+static const struct file_operations txstat_fops = {
 	.read = txstat_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations restart_fops = {
+static const struct file_operations restart_fops = {
 	.write = restart_write_file,
 	.open = open_file_generic,
 };
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index 978ed09..6e0dc76 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -145,16 +145,14 @@
 			  int tx)
 {
 	dma_addr_t dmaaddr;
+	int direction = PCI_DMA_FROMDEVICE;
 
-	if (tx) {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+	if (tx)
+		direction = PCI_DMA_TODEVICE;
+
+	dmaaddr = pci_map_single(ring->bcm->pci_dev,
 					 buf, len,
-					 DMA_TO_DEVICE);
-	} else {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
-					 buf, len,
-					 DMA_FROM_DEVICE);
-	}
+					 direction);
 
 	return dmaaddr;
 }
@@ -166,13 +164,13 @@
 		      int tx)
 {
 	if (tx) {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		pci_unmap_single(ring->bcm->pci_dev,
 				 addr, len,
-				 DMA_TO_DEVICE);
+				 PCI_DMA_TODEVICE);
 	} else {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		pci_unmap_single(ring->bcm->pci_dev,
 				 addr, len,
-				 DMA_FROM_DEVICE);
+				 PCI_DMA_FROMDEVICE);
 	}
 }
 
@@ -183,8 +181,8 @@
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
-				addr, len, DMA_FROM_DEVICE);
+	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+				    addr, len, PCI_DMA_FROMDEVICE);
 }
 
 static inline
@@ -194,8 +192,8 @@
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
-				   addr, len, DMA_FROM_DEVICE);
+	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+				    addr, len, PCI_DMA_TODEVICE);
 }
 
 /* Unmap and free a descriptor buffer. */
@@ -214,17 +212,53 @@
 
 static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
 {
-	struct device *dev = &(ring->bcm->pci_dev->dev);
-
-	ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
-					    &(ring->dmabase), GFP_KERNEL);
+	ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
+					    &(ring->dmabase));
 	if (!ring->descbase) {
-		printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
-		return -ENOMEM;
+		/* Allocation may have failed due to pci_alloc_consistent
+		   insisting on use of GFP_DMA, which is more restrictive
+		   than necessary...  */
+		struct dma_desc *rx_ring;
+		dma_addr_t rx_ring_dma;
+
+		rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
+		if (!rx_ring)
+			goto out_err;
+
+		rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
+					     BCM43xx_DMA_RINGMEMSIZE,
+					     PCI_DMA_BIDIRECTIONAL);
+
+		if (pci_dma_mapping_error(rx_ring_dma) ||
+		    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+			/* Sigh... */
+			if (!pci_dma_mapping_error(rx_ring_dma))
+				pci_unmap_single(ring->bcm->pci_dev,
+						 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+						 PCI_DMA_BIDIRECTIONAL);
+			rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
+						 rx_ring, BCM43xx_DMA_RINGMEMSIZE,
+						 PCI_DMA_BIDIRECTIONAL);
+			if (pci_dma_mapping_error(rx_ring_dma) ||
+			    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+				assert(0);
+				if (!pci_dma_mapping_error(rx_ring_dma))
+					pci_unmap_single(ring->bcm->pci_dev,
+							 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+							 PCI_DMA_BIDIRECTIONAL);
+				goto out_err;
+			}
+                }
+
+                ring->descbase = rx_ring;
+                ring->dmabase = rx_ring_dma;
 	}
 	memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
 
 	return 0;
+out_err:
+	printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+	return -ENOMEM;
 }
 
 static void free_ringmemory(struct bcm43xx_dmaring *ring)
@@ -407,6 +441,29 @@
 	if (unlikely(!skb))
 		return -ENOMEM;
 	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+	/* This hardware bug work-around adapted from the b44 driver.
+	   The chip may be unable to do PCI DMA to/from anything above 1GB */
+	if (pci_dma_mapping_error(dmaaddr) ||
+	    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+		/* This one has 30-bit addressing... */
+		if (!pci_dma_mapping_error(dmaaddr))
+			pci_unmap_single(ring->bcm->pci_dev,
+					 dmaaddr, ring->rx_buffersize,
+					 PCI_DMA_FROMDEVICE);
+		dev_kfree_skb_any(skb);
+		skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
+		if (skb == NULL)
+			return -ENOMEM;
+		dmaaddr = pci_map_single(ring->bcm->pci_dev,
+					 skb->data, ring->rx_buffersize,
+					 PCI_DMA_FROMDEVICE);
+		if (pci_dma_mapping_error(dmaaddr) ||
+		    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+			assert(0);
+			dev_kfree_skb_any(skb);
+			return -ENOMEM;
+		}
+	}
 	meta->skb = skb;
 	meta->dmaaddr = dmaaddr;
 	skb->dev = ring->bcm->net_dev;
@@ -636,8 +693,10 @@
 	err = dmacontroller_setup(ring);
 	if (err)
 		goto err_free_ringmemory;
+	return ring;
 
 out:
+	printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
 	return ring;
 
 err_free_ringmemory:
@@ -705,30 +764,16 @@
 	struct bcm43xx_dmaring *ring;
 	int err = -ENOMEM;
 	int dma64 = 0;
-	u64 mask = bcm43xx_get_supported_dma_mask(bcm);
-	int nobits;
 
-	if (mask == DMA_64BIT_MASK) {
+	bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
+	if (bcm->dma_mask == DMA_64BIT_MASK)
 		dma64 = 1;
-		nobits = 64;
-	} else if (mask == DMA_32BIT_MASK)
-		nobits = 32;
-	else
-		nobits = 30;
-	err = pci_set_dma_mask(bcm->pci_dev, mask);
-	err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
-	if (err) {
-#ifdef CONFIG_BCM43XX_PIO
-		printk(KERN_WARNING PFX "DMA not supported on this device."
-					" Falling back to PIO.\n");
-		bcm->__using_pio = 1;
-		return -ENOSYS;
-#else
-		printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
-				    "Please recompile the driver with PIO support.\n");
-		return -ENODEV;
-#endif /* CONFIG_BCM43XX_PIO */
-	}
+	err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
+	if (err)
+		goto no_dma;
+	err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
+	if (err)
+		goto no_dma;
 
 	/* setup TX DMA channels. */
 	ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
@@ -774,7 +819,9 @@
 		dma->rx_ring3 = ring;
 	}
 
-	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
+	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
+		(bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
+		(bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
 	err = 0;
 out:
 	return err;
@@ -800,7 +847,17 @@
 err_destroy_tx0:
 	bcm43xx_destroy_dmaring(dma->tx_ring0);
 	dma->tx_ring0 = NULL;
-	goto out;
+no_dma:
+#ifdef CONFIG_BCM43XX_PIO
+	printk(KERN_WARNING PFX "DMA not supported on this device."
+				" Falling back to PIO.\n");
+	bcm->__using_pio = 1;
+	return -ENOSYS;
+#else
+	printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+			    "Please recompile the driver with PIO support.\n");
+	return -ENODEV;
+#endif /* CONFIG_BCM43XX_PIO */
 }
 
 /* Generate a cookie for the TX header. */
@@ -905,6 +962,7 @@
 	struct bcm43xx_dmadesc_generic *desc;
 	struct bcm43xx_dmadesc_meta *meta;
 	dma_addr_t dmaaddr;
+	struct sk_buff *bounce_skb;
 
 	assert(skb_shinfo(skb)->nr_frags == 0);
 
@@ -924,9 +982,28 @@
 			       skb->len - sizeof(struct bcm43xx_txhdr),
 			       (cur_frag == 0),
 			       generate_cookie(ring, slot));
+	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+	if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+		/* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
+		if (!dma_mapping_error(dmaaddr))
+			unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
+		if (!bounce_skb)
+			return;
+		dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
+		if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+			if (!dma_mapping_error(dmaaddr))
+				unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+			dev_kfree_skb_any(bounce_skb);
+			assert(0);
+			return;
+		}
+		memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+		dev_kfree_skb_any(skb);
+		skb = bounce_skb;
+	}
 
 	meta->skb = skb;
-	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 	meta->dmaaddr = dmaaddr;
 
 	fill_descriptor(ring, desc, dmaaddr,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
index ad8e569..f2b8dba 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
@@ -325,6 +325,21 @@
 	}
 }
 
+void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val)
+{
+	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+		mmiowb();
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (val & 0xFFFF0000) >> 16);
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val & 0x0000FFFF);
+	} else {
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+		mmiowb();
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16);
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val & 0x0000FFFF);
+	}
+}
+
 u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset)
 {
 	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
index 464521a..d7eaf5f 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
@@ -27,6 +27,7 @@
 
 
 void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val);
 u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset);
 
 #endif /* BCM43xx_ILT_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 23aaf1e..73c831a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -95,13 +95,9 @@
 module_param_named(noleds, modparam_noleds, int, 0444);
 MODULE_PARM_DESC(noleds, "Turn off all LED activity");
 
-#ifdef CONFIG_BCM43XX_DEBUG
 static char modparam_fwpostfix[64];
 module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
-MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
-#else
-# define modparam_fwpostfix  ""
-#endif /* CONFIG_BCM43XX_DEBUG*/
+MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
 
 
 /* If you want to debug with just a single device, enable this,
@@ -855,8 +851,6 @@
 	value = sprom[BCM43xx_SPROM_ETHPHY];
 	bcm->sprom.et0phyaddr = (value & 0x001F);
 	bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
-	bcm->sprom.et0mdcport = (value & (1 << 14)) >> 14;
-	bcm->sprom.et1mdcport = (value & (1 << 15)) >> 15;
 
 	/* boardrev, antennas, locale */
 	value = sprom[BCM43xx_SPROM_BOARDREV];
@@ -1453,12 +1447,10 @@
 
 		bcm43xx_debugfs_log_txstat(bcm, &stat);
 
-		if (stat.flags & BCM43xx_TXSTAT_FLAG_IGNORE)
+		if (stat.flags & BCM43xx_TXSTAT_FLAG_AMPDU)
 			continue;
-		if (!(stat.flags & BCM43xx_TXSTAT_FLAG_ACK)) {
-			//TODO: packet was not acked (was lost)
-		}
-		//TODO: There are more (unknown) flags to test. see bcm43xx_main.h
+		if (stat.flags & BCM43xx_TXSTAT_FLAG_INTER)
+			continue;
 
 		if (bcm43xx_using_pio(bcm))
 			bcm43xx_pio_handle_xmitstatus(bcm, &stat);
@@ -2983,8 +2975,10 @@
 	err = bcm43xx_pctl_set_crystal(bcm, 1);
 	if (err)
 		goto out;
-	bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
-	bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
+	err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
+	if (err)
+		goto out;
+	err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
 
 out:
 	return err;
@@ -3698,7 +3692,7 @@
 {
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	u16 value;
-	u8 phy_version;
+	u8 phy_analog;
 	u8 phy_type;
 	u8 phy_rev;
 	int phy_rev_ok = 1;
@@ -3706,12 +3700,12 @@
 
 	value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
 
-	phy_version = (value & 0xF000) >> 12;
+	phy_analog = (value & 0xF000) >> 12;
 	phy_type = (value & 0x0F00) >> 8;
 	phy_rev = (value & 0x000F);
 
-	dprintk(KERN_INFO PFX "Detected PHY: Version: %x, Type %x, Revision %x\n",
-		phy_version, phy_type, phy_rev);
+	dprintk(KERN_INFO PFX "Detected PHY: Analog: %x, Type %x, Revision %x\n",
+		phy_analog, phy_type, phy_rev);
 
 	switch (phy_type) {
 	case BCM43xx_PHYTYPE_A:
@@ -3754,7 +3748,7 @@
 		       phy_rev);
 	}
 
-	phy->version = phy_version;
+	phy->analog = phy_analog;
 	phy->type = phy_type;
 	phy->rev = phy_rev;
 	if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
@@ -3796,12 +3790,18 @@
 	}
 	net_dev->base_addr = (unsigned long)bcm->mmio_addr;
 
-	bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
+	err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
 	                          &bcm->board_vendor);
-	bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
+	if (err)
+		goto err_iounmap;
+	err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
 	                          &bcm->board_type);
-	bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
+	if (err)
+		goto err_iounmap;
+	err = bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
 	                          &bcm->board_revision);
+	if (err)
+		goto err_iounmap;
 
 	err = bcm43xx_chipset_attach(bcm);
 	if (err)
@@ -3892,6 +3892,7 @@
 	pci_release_regions(pci_dev);
 err_pci_disable:
 	pci_disable_device(pci_dev);
+	printk(KERN_ERR PFX "Unable to attach board\n");
 	goto out;
 }
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index 52ce2a9..3a5c9c2 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -205,8 +205,8 @@
 	    (bcm->board_type == 0x0416))
 		return;
 
-	bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
 	bcm43xx_phy_write(bcm, 0x0028, 0x8018);
+	bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
 
 	if (phy->type == BCM43xx_PHYTYPE_G) {
 		if (!phy->connected)
@@ -317,6 +317,13 @@
 	bcm43xx_ilt_write(bcm, offset + 0x0801, 7);
 	bcm43xx_ilt_write(bcm, offset + 0x0802, 16);
 	bcm43xx_ilt_write(bcm, offset + 0x0803, 28);
+
+	if (phy->rev >= 6) {
+		bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
+				  & 0xFFFC));
+		bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
+				  & 0xEFFF));
+	}
 }
 
 static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
@@ -337,7 +344,7 @@
 		for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++)
 			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]);
 		for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
-			bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+			bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
 	} else {
 		/* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
 		bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654);
@@ -377,7 +384,7 @@
 	
 	if (phy->rev == 1) {
 		for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
-			bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+			bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
 		for (i = 0; i < 4; i++) {
 			bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020);
 			bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020);
@@ -500,10 +507,10 @@
 		for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++)
 			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]);
 		for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
-			bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+			bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
 		bcm43xx_phy_init_noisescaletbl(bcm);
 		for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
-			bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+			bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
 		break;
 	case 3:
 		for (i = 0; i < 64; i++)
@@ -729,19 +736,19 @@
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
 	u16 offset;
+	u16 value;
+	u8 old_channel;
 
-	if (phy->version == 1 &&
-	    radio->version == 0x2050) {
+	if (phy->analog == 1)
 		bcm43xx_radio_write16(bcm, 0x007A,
 				      bcm43xx_radio_read16(bcm, 0x007A)
 				      | 0x0050);
-	}
 	if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) &&
 	    (bcm->board_type != 0x0416)) {
+		value = 0x2120;
 		for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
-			bcm43xx_phy_write(bcm, offset,
-					  (bcm43xx_phy_read(bcm, offset) + 0x2020)
-					  & 0x3F3F);
+			bcm43xx_phy_write(bcm, offset, value);
+			value += 0x0202;
 		}
 	}
 	bcm43xx_phy_write(bcm, 0x0035,
@@ -750,7 +757,7 @@
 	if (radio->version == 0x2050)
 		bcm43xx_phy_write(bcm, 0x0038, 0x0667);
 
-	if (phy->connected) {
+	if (phy->type == BCM43xx_PHYTYPE_G) {
 		if (radio->version == 0x2050) {
 			bcm43xx_radio_write16(bcm, 0x007A,
 					      bcm43xx_radio_read16(bcm, 0x007A)
@@ -776,7 +783,7 @@
 				  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
 	}
 
-	if (phy->version == 1 && radio->version == 0x2050) {
+	if (phy->analog == 1) {
 		bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
 		bcm43xx_phy_write(bcm, 0x0021, 0x3763);
 		bcm43xx_phy_write(bcm, 0x0022, 0x1BC3);
@@ -787,14 +794,15 @@
 	bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
 	bcm43xx_write16(bcm, 0x03EC, 0x3F22);
 
-	if (phy->version == 1 && radio->version == 0x2050)
+	if (phy->analog == 1)
 		bcm43xx_phy_write(bcm, 0x0020, 0x3E1C);
 	else
 		bcm43xx_phy_write(bcm, 0x0020, 0x301C);
 
-	if (phy->version == 0)
+	if (phy->analog == 0)
 		bcm43xx_write16(bcm, 0x03E4, 0x3000);
 
+	old_channel = radio->channel;
 	/* Force to channel 7, even if not supported. */
 	bcm43xx_radio_selectchannel(bcm, 7, 0);
 
@@ -816,11 +824,11 @@
 
 	bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007);
 
-	bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+	bcm43xx_radio_selectchannel(bcm, old_channel, 0);
 
 	bcm43xx_phy_write(bcm, 0x0014, 0x0080);
 	bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
-	bcm43xx_phy_write(bcm, 0x88A3, 0x002A);
+	bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
 
 	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
 
@@ -835,61 +843,24 @@
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
 	u16 offset, val;
+	u8 old_channel;
 
 	bcm43xx_phy_write(bcm, 0x003E, 0x817A);
 	bcm43xx_radio_write16(bcm, 0x007A,
 	                      (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058));
-	if ((radio->manufact == 0x17F) &&
-	    (radio->version == 0x2050) &&
-	    (radio->revision == 3 ||
-	     radio->revision == 4 ||
-	     radio->revision == 5)) {
-		bcm43xx_radio_write16(bcm, 0x0051, 0x001F);
-		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
-		bcm43xx_radio_write16(bcm, 0x0053, 0x005B);
-		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+	if (radio->revision == 4 ||
+	     radio->revision == 5) {
+		bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
+		bcm43xx_radio_write16(bcm, 0x0052, 0x0070);
+		bcm43xx_radio_write16(bcm, 0x0053, 0x00B3);
+		bcm43xx_radio_write16(bcm, 0x0054, 0x009B);
 		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
 		bcm43xx_radio_write16(bcm, 0x005B, 0x0088);
 		bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
 		bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
 		bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
 	}
-	if ((radio->manufact == 0x17F) &&
-	    (radio->version == 0x2050) &&
-	    (radio->revision == 6)) {
-		bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
-		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
-		bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
-		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
-		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
-		bcm43xx_radio_write16(bcm, 0x005B, 0x008B);
-		bcm43xx_radio_write16(bcm, 0x005C, 0x00B5);
-		bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
-		bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
-		bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
-		bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
-		bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
-	}
-	if ((radio->manufact == 0x17F) &&
-	    (radio->version == 0x2050) &&
-	    (radio->revision == 7)) {
-		bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
-		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
-		bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
-		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
-		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
-		bcm43xx_radio_write16(bcm, 0x005B, 0x00A8);
-		bcm43xx_radio_write16(bcm, 0x005C, 0x0075);
-		bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
-		bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
-		bcm43xx_radio_write16(bcm, 0x007D, 0x00E8);
-		bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
-		bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
-		bcm43xx_radio_write16(bcm, 0x007B, 0x0000);
-	}
-	if ((radio->manufact == 0x17F) &&
-	    (radio->version == 0x2050) &&
-	    (radio->revision == 8)) {
+	if (radio->revision == 8) {
 		bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
 		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
 		bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
@@ -933,20 +904,26 @@
 		                  bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
 		bcm43xx_phy_write(bcm, 0x042B,
 		                  bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+		bcm43xx_phy_write(bcm, 0x5B, 0x0000);
+		bcm43xx_phy_write(bcm, 0x5C, 0x0000);
 	}
 
-	/* Force to channel 7, even if not supported. */
-	bcm43xx_radio_selectchannel(bcm, 7, 0);
+	old_channel = radio->channel;
+	if (old_channel >= 8)
+		bcm43xx_radio_selectchannel(bcm, 1, 0);
+	else
+		bcm43xx_radio_selectchannel(bcm, 13, 0);
 
 	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
 	bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
 	udelay(40);
-	bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002));
-	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-	if (radio->manufact == 0x17F &&
-	    radio->version == 0x2050 &&
-	    radio->revision <= 2) {
+	if (radio->revision < 6 || radio-> revision == 8) {
+		bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C)
+				      | 0x0002));
 		bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+	}
+	if (radio->revision <= 2) {
+		bcm43xx_radio_write16(bcm, 0x007C, 0x0020);
 		bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
 		bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
 		bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
@@ -954,46 +931,41 @@
 	bcm43xx_radio_write16(bcm, 0x007A,
 	                      (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007);
 
-	bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+	bcm43xx_radio_selectchannel(bcm, old_channel, 0);
 
 	bcm43xx_phy_write(bcm, 0x0014, 0x0200);
-	if (radio->version == 0x2050){
-		if (radio->revision == 3 ||
-		    radio->revision == 4 ||
-		    radio->revision == 5)
-			bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
-		else
-			bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
-	}
+	if (radio->revision >= 6)
+		bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+	else
+		bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
 	bcm43xx_phy_write(bcm, 0x0038, 0x0668);
 	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
-	if (radio->version == 0x2050) {
-		if (radio->revision == 3 ||
-		    radio->revision == 4 ||
-		    radio->revision == 5)
-			bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003);
-		else if (radio->revision <= 2)
-			bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
-	}
+	if (radio->revision <= 5)
+		bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003);
+	if (radio->revision <= 2)
+		bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
 	
-	if (phy->rev == 4)
-		bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
-	else
+	if (phy->analog == 4){
 		bcm43xx_write16(bcm, 0x03E4, 0x0009);
+		bcm43xx_phy_write(bcm, 0x61, bcm43xx_phy_read(bcm, 0x61) & 0xFFF);
+	} else {
+		bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
+	}
+	if (phy->type == BCM43xx_PHYTYPE_G)
+		bcm43xx_write16(bcm, 0x03E6, 0x0);
 	if (phy->type == BCM43xx_PHYTYPE_B) {
 		bcm43xx_write16(bcm, 0x03E6, 0x8140);
 		bcm43xx_phy_write(bcm, 0x0016, 0x0410);
 		bcm43xx_phy_write(bcm, 0x0017, 0x0820);
 		bcm43xx_phy_write(bcm, 0x0062, 0x0007);
 		(void) bcm43xx_radio_calibrationvalue(bcm);
-		bcm43xx_phy_lo_b_measure(bcm);
+		bcm43xx_phy_lo_g_measure(bcm);
 		if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
 			bcm43xx_calc_nrssi_slope(bcm);
 			bcm43xx_calc_nrssi_threshold(bcm);
 		}
 		bcm43xx_phy_init_pctl(bcm);
-	} else
-		bcm43xx_write16(bcm, 0x03E6, 0x0);
+	}
 }
 
 static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
@@ -1063,7 +1035,7 @@
 	bcm43xx_phy_write(bcm, 0x005A, 0x0780);
 	bcm43xx_phy_write(bcm, 0x0059, 0xC810);
 	bcm43xx_phy_write(bcm, 0x0058, 0x000D);
-	if (phy->version == 0) {
+	if (phy->analog == 0) {
 		bcm43xx_phy_write(bcm, 0x0003, 0x0122);
 	} else {
 		bcm43xx_phy_write(bcm, 0x000A,
@@ -1205,27 +1177,30 @@
 	if (phy->rev >= 2) {
 		bcm43xx_phy_write(bcm, 0x0814, 0x0000);
 		bcm43xx_phy_write(bcm, 0x0815, 0x0000);
-		if (phy->rev == 2)
-			bcm43xx_phy_write(bcm, 0x0811, 0x0000);
-		else if (phy->rev >= 3)
-			bcm43xx_phy_write(bcm, 0x0811, 0x0400);
+	}
+	if (phy->rev == 2) {
+		bcm43xx_phy_write(bcm, 0x0811, 0x0000);
 		bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
-		if (phy->connected) {
-			tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
-			if (tmp < 6) {
-				bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
-				bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
-				if (tmp != 3) {
-					bcm43xx_phy_write(bcm, 0x04CC,
-							  (bcm43xx_phy_read(bcm, 0x04CC)
-							   & 0x00FF) | 0x1F00);
-				}
+	}
+	if (phy->rev >= 3) {
+		bcm43xx_phy_write(bcm, 0x0811, 0x0400);
+		bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
+	}
+	if (phy->connected) {
+		tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
+		if (tmp < 6) {
+			bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
+			bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
+			if (tmp != 3) {
+				bcm43xx_phy_write(bcm, 0x04CC,
+						  (bcm43xx_phy_read(bcm, 0x04CC)
+						   & 0x00FF) | 0x1F00);
 			}
 		}
 	}
 	if (phy->rev < 3 && phy->connected)
 		bcm43xx_phy_write(bcm, 0x047E, 0x0078);
-	if (phy->rev >= 6 && phy->rev <= 8) {
+	if (radio->revision == 8) {
 		bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
 		bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
 	}
@@ -1638,14 +1613,14 @@
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	u16 value;
 
-	if (phy->version == 0) {
+	if (phy->analog == 0) {
 		value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0);
 		value |= (baseband_attenuation & 0x000F);
 		bcm43xx_write16(bcm, 0x03E6, value);
 		return;
 	}
 
-	if (phy->version > 1) {
+	if (phy->analog > 1) {
 		value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
 		value |= (baseband_attenuation << 2) & 0x003C;
 	} else {
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
index af19a07..32beb91 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
@@ -1393,11 +1393,12 @@
 	backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
 
 	// Initialization
-	if (phy->version == 0) {
+	if (phy->analog == 0) {
 		bcm43xx_write16(bcm, 0x03E6, 0x0122);
 	} else {
-		if (phy->version >= 2)
-			bcm43xx_write16(bcm, 0x03E6, 0x0040);
+		if (phy->analog >= 2)
+			bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003)
+					& 0xFFBF) | 0x0040);
 		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
 		                (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000));
 	}
@@ -1405,7 +1406,7 @@
 	ret = bcm43xx_radio_calibrationvalue(bcm);
 
 	if (phy->type == BCM43xx_PHYTYPE_B)
-		bcm43xx_radio_write16(bcm, 0x0078, 0x0003);
+		bcm43xx_radio_write16(bcm, 0x0078, 0x0026);
 
 	bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);
 	bcm43xx_phy_write(bcm, 0x002B, 0x1403);
@@ -1416,7 +1417,7 @@
 	                      (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));
 	bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
 	bcm43xx_radio_write16(bcm, 0x0043,
-			      bcm43xx_radio_read16(bcm, 0x0043) | 0x0009);
+			      (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0) | 0x0009);
 	bcm43xx_phy_write(bcm, 0x0058, 0x0000);
 
 	for (i = 0; i < 16; i++) {
@@ -1488,7 +1489,7 @@
 	bcm43xx_phy_write(bcm, 0x0059, backup[17]);
 	bcm43xx_phy_write(bcm, 0x0058, backup[18]);
 	bcm43xx_write16(bcm, 0x03E6, backup[11]);
-	if (phy->version != 0)
+	if (phy->analog != 0)
 		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);
 	bcm43xx_phy_write(bcm, 0x0035, backup[10]);
 	bcm43xx_radio_selectchannel(bcm, radio->channel, 1);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index a659442..7b665e2 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -33,7 +33,6 @@
 #include <net/ieee80211softmac.h>
 #include <net/ieee80211softmac_wx.h>
 #include <linux/capability.h>
-#include <linux/sched.h> /* for capable() */
 #include <linux/delay.h>
 
 #include "bcm43xx.h"
@@ -261,22 +260,22 @@
 	if (phy->type == BCM43xx_PHYTYPE_A ||
 	    phy->type == BCM43xx_PHYTYPE_G) {
 		range->num_bitrates = 8;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
 	}
 	if (phy->type == BCM43xx_PHYTYPE_B ||
 	    phy->type == BCM43xx_PHYTYPE_G) {
 		range->num_bitrates += 4;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
 	}
 
 	geo = ieee80211_get_geo(bcm->ieee);
@@ -286,7 +285,7 @@
 		if (j == IW_MAX_FREQUENCIES)
 			break;
 		range->freq[j].i = j + 1;
-		range->freq[j].m = geo->a[i].freq;//FIXME?
+		range->freq[j].m = geo->a[i].freq * 100000;
 		range->freq[j].e = 1;
 		j++;
 	}
@@ -294,7 +293,7 @@
 		if (j == IW_MAX_FREQUENCIES)
 			break;
 		range->freq[j].i = j + 1;
-		range->freq[j].m = geo->bg[i].freq;//FIXME?
+		range->freq[j].m = geo->bg[i].freq * 100000;
 		range->freq[j].e = 1;
 		j++;
 	}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
index 2aed19e..9ecf2bf 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
@@ -137,14 +137,8 @@
 	u16 unknown; //FIXME
 };
 
-#define BCM43xx_TXSTAT_FLAG_ACK		0x01
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x02
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x04
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x08
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x10
-#define BCM43xx_TXSTAT_FLAG_IGNORE	0x20
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x40
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x80
+#define BCM43xx_TXSTAT_FLAG_AMPDU	0x10
+#define BCM43xx_TXSTAT_FLAG_INTER	0x20
 
 u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
 u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h
index e89c890..ef37a75 100644
--- a/drivers/net/wireless/hostap/hostap.h
+++ b/drivers/net/wireless/hostap/hostap.h
@@ -2,13 +2,14 @@
 #define HOSTAP_H
 
 #include <linux/ethtool.h>
+#include <linux/kernel.h>
 
 #include "hostap_wlan.h"
 #include "hostap_ap.h"
 
 static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
 				  2447, 2452, 2457, 2462, 2467, 2472, 2484 };
-#define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0]))
+#define FREQ_COUNT ARRAY_SIZE(freq_list)
 
 /* hostap.c */
 
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index b85857a..ad6e4a4 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -175,7 +175,7 @@
 
 /* Debugging stuff */
 #ifdef CONFIG_IPW2100_DEBUG
-#define CONFIG_IPW2100_RX_DEBUG	/* Reception debugging */
+#define IPW2100_RX_DEBUG	/* Reception debugging */
 #endif
 
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -2239,7 +2239,7 @@
 	priv->snapshot[0] = NULL;
 }
 
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
 {
 	int i;
@@ -2314,13 +2314,13 @@
  * The size of the constructed ethernet
  *
  */
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
 #endif
 
 static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
 {
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 	struct ipw2100_status *status = &priv->status_queue.drv[i];
 	u32 match, reg;
 	int j;
@@ -2342,7 +2342,7 @@
 	}
 #endif
 
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
 	/* Halt the fimrware so we can get a good image */
 	write_register(priv->net_dev, IPW_REG_RESET_REG,
 		       IPW_AUX_HOST_RESET_REG_STOP_MASTER);
@@ -2413,7 +2413,7 @@
 
 	skb_put(packet->skb, status->frame_size);
 
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 	/* Make a copy of the frame so we can dump it to the logs if
 	 * ieee80211_rx fails */
 	memcpy(packet_data, packet->skb->data,
@@ -2421,7 +2421,7 @@
 #endif
 
 	if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
 		IPW_DEBUG_DROP("%s: Non consumed packet:\n",
 			       priv->net_dev->name);
 		printk_buf(IPW_DL_DROP, packet_data, status->frame_size);
@@ -2888,7 +2888,7 @@
 
 #ifdef CONFIG_IPW2100_DEBUG
 		if (packet->info.c_struct.cmd->host_command_reg <
-		    sizeof(command_types) / sizeof(*command_types))
+		    ARRAY_SIZE(command_types))
 			IPW_DEBUG_TX("Command '%s (%d)' processed: %d.\n",
 				     command_types[packet->info.c_struct.cmd->
 						   host_command_reg],
@@ -3736,7 +3736,7 @@
 
 	out += sprintf(out, "%30s [Address ] : Hex\n", "Register");
 
-	for (i = 0; i < (sizeof(hw_data) / sizeof(*hw_data)); i++) {
+	for (i = 0; i < ARRAY_SIZE(hw_data); i++) {
 		read_register(dev, hw_data[i].addr, &val);
 		out += sprintf(out, "%30s [%08X] : %08X\n",
 			       hw_data[i].name, hw_data[i].addr, val);
@@ -3757,7 +3757,7 @@
 
 	out += sprintf(out, "%30s [Address ] : Hex\n", "NIC entry");
 
-	for (i = 0; i < (sizeof(nic_data) / sizeof(*nic_data)); i++) {
+	for (i = 0; i < ARRAY_SIZE(nic_data); i++) {
 		u8 tmp8;
 		u16 tmp16;
 		u32 tmp32;
@@ -3894,13 +3894,11 @@
 	if (priv->status & STATUS_RF_KILL_MASK)
 		return 0;
 
-	if (loop >= sizeof(ord_data) / sizeof(*ord_data))
+	if (loop >= ARRAY_SIZE(ord_data))
 		loop = 0;
 
 	/* sysfs provides us PAGE_SIZE buffer */
-	while (len < PAGE_SIZE - 128 &&
-	       loop < (sizeof(ord_data) / sizeof(*ord_data))) {
-
+	while (len < PAGE_SIZE - 128 && loop < ARRAY_SIZE(ord_data)) {
 		val_len = sizeof(u32);
 
 		if (ipw2100_get_ordinal(priv, ord_data[loop].index, &val,
@@ -4912,7 +4910,7 @@
 	else
 		priv->power_mode = IPW_POWER_ENABLED | power_level;
 
-#ifdef CONFIG_IPW2100_TX_POWER
+#ifdef IPW2100_TX_POWER
 	if (priv->port_type == IBSS && priv->adhoc_power != DFTL_IBSS_TX_POWER) {
 		/* Set beacon interval */
 		cmd.host_command = TX_POWER_INDEX;
@@ -6589,7 +6587,7 @@
 	11000000
 };
 
-#define RATE_COUNT (sizeof(ipw2100_rates_11b) / sizeof(ipw2100_rates_11b[0]))
+#define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b)
 
 static int ipw2100_wx_get_name(struct net_device *dev,
 			       struct iw_request_info *info,
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 838d510..841b3c1 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -1395,11 +1395,16 @@
 		break;
 
 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-		dot1x = param->value ? 1 : 0;
+		/* dot1x should be the opposite of RX_UNENCRYPTED_EAPOL;
+		 * turn off dot1x when allowing receipt of unencrypted EAPOL
+		 * frames, turn on dot1x when receipt should be disallowed
+		 */
+		dot1x = param->value ? 0 : 0x01;
 		break;
 
 	case IW_AUTH_PRIVACY_INVOKED:
 		privinvoked = param->value ? 1 : 0;
+		break;
 
 	case IW_AUTH_DROP_UNENCRYPTED:
 		exunencrypt = param->value ? 1 : 0;
@@ -1589,6 +1594,7 @@
 			}
 			key.type = DOT11_PRIV_TKIP;
 			key.length = KEY_SIZE_TKIP;
+			break;
 		default:
 			return -EINVAL;
 		}
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
index e6cf9df..4278032 100644
--- a/drivers/net/wireless/prism54/oid_mgt.c
+++ b/drivers/net/wireless/prism54/oid_mgt.c
@@ -16,6 +16,8 @@
  *
  */
 
+#include <linux/kernel.h>
+
 #include "prismcompat.h"
 #include "islpci_dev.h"
 #include "islpci_mgt.h"
@@ -692,7 +694,7 @@
 	return ret;
 }
 
-#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0]))
+#define VEC_SIZE(a) ARRAY_SIZE(a)
 
 int
 mgt_commit(islpci_private *priv)
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index ce3a8ba..f5ce1c6 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1160,7 +1160,7 @@
 	return seq_open(file, &strip_seq_ops);
 }
 
-static struct file_operations strip_seq_fops = {
+static const struct file_operations strip_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = strip_seq_open,
 	.read    = seq_read,
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index 24221e4..2aa3c76 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -28,7 +28,7 @@
  */
 static u8 wv_irq_to_psa(int irq)
 {
-	if (irq < 0 || irq >= NELS(irqvals))
+	if (irq < 0 || irq >= ARRAY_SIZE(irqvals))
 		return 0;
 
 	return irqvals[irq];
@@ -42,7 +42,7 @@
 {
 	int irq;
 
-	for (irq = 0; irq < NELS(irqvals); irq++)
+	for (irq = 0; irq < ARRAY_SIZE(irqvals); irq++)
 		if (irqvals[irq] == irqval)
 			return irq;
 
@@ -1695,7 +1695,7 @@
 		/* Look in the table if the frequency is allowed */
 		if (table[9 - (freq / 16)] & (1 << (freq % 16))) {
 			/* Compute approximate channel number */
-			while ((c < NELS(channel_bands)) &&
+			while ((c < ARRAY_SIZE(channel_bands)) &&
 				(((channel_bands[c] >> 1) - 24) < freq)) 
 				c++;
 			list[i].i = c;	/* Set the list index */
@@ -4269,7 +4269,7 @@
 		printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
 #endif
 	} else { /* Scan all possible addresses of the WaveLAN hardware. */
-		for (i = 0; i < NELS(iobase); i++) {
+		for (i = 0; i < ARRAY_SIZE(iobase); i++) {
 			dev->irq = def_irq;
 			if (wavelan_config(dev, iobase[i]) == 0) {
 #ifdef DEBUG_CALLBACK_TRACE
@@ -4280,7 +4280,7 @@
 				break;
 			}
 		}
-		if (i == NELS(iobase))
+		if (i == ARRAY_SIZE(iobase))
 			r = -ENODEV;
 	}
 	if (r) 
@@ -4327,14 +4327,14 @@
 #endif
 
 		/* Copy the basic set of address to be probed. */
-		for (i = 0; i < NELS(iobase); i++)
+		for (i = 0; i < ARRAY_SIZE(iobase); i++)
 			io[i] = iobase[i];
 	}
 
 
 	/* Loop on all possible base addresses. */
 	i = -1;
-	while ((io[++i] != 0) && (i < NELS(io))) {
+	while ((io[++i] != 0) && (i < ARRAY_SIZE(io))) {
 		struct net_device *dev = alloc_etherdev(sizeof(net_local));
 		if (!dev)
 			break;
diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
index 72b646c..fe24281 100644
--- a/drivers/net/wireless/wavelan.p.h
+++ b/drivers/net/wireless/wavelan.p.h
@@ -449,9 +449,6 @@
 /* Watchdog temporisation */
 #define	WATCHDOG_JIFFIES	(512*HZ/100)
 
-/* Macro to get the number of elements in an array */
-#define	NELS(a)				(sizeof(a) / sizeof(a[0]))
-
 /* ------------------------ PRIVATE IOCTL ------------------------ */
 
 #define SIOCSIPQTHR	SIOCIWFIRSTPRIV		/* Set quality threshold */
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 5eb8163..b042397 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -1168,7 +1168,7 @@
 	 m.mmr_unused0[6],
 	 m.mmr_unused0[7]);
 #endif	/* DEBUG_SHOW_UNUSED */
-  printk(KERN_DEBUG "Encryption algorythm: %02X - Status: %02X\n",
+  printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n",
 	 m.mmr_des_avail, m.mmr_des_status);
 #ifdef DEBUG_SHOW_UNUSED
   printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n",
@@ -3590,9 +3590,9 @@
   cfblk.acloc = TRUE;           /* Disable source addr insertion by i82593 */
   cfblk.preamb_len = 0;         /* 2 bytes preamble (SFD) */
   cfblk.loopback = FALSE;
-  cfblk.lin_prio = 0;   	/* conform to 802.3 backoff algoritm */
-  cfblk.exp_prio = 5;	        /* conform to 802.3 backoff algoritm */
-  cfblk.bof_met = 1;	        /* conform to 802.3 backoff algoritm */
+  cfblk.lin_prio = 0;   	/* conform to 802.3 backoff algorithm */
+  cfblk.exp_prio = 5;	        /* conform to 802.3 backoff algorithm */
+  cfblk.bof_met = 1;	        /* conform to 802.3 backoff algorithm */
   cfblk.ifrm_spc = 0x20 >> 4;	/* 32 bit times interframe spacing */
   cfblk.slottim_low = 0x20 >> 5;	/* 32 bit times slot time */
   cfblk.slottim_hi = 0x0;
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 12dfc0b..9c64f89 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -113,7 +113,7 @@
 
 	/* Allocate a single memory block for values and addresses. */
 	count16 = 2*count;
-	a16 = kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
+	a16 = (zd_addr_t *) kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
 		                   GFP_NOFS);
 	if (!a16) {
 		dev_dbg_f(zd_chip_dev(chip),
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index a085241..4c5f78e 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -156,7 +156,7 @@
 static int reset_mode(struct zd_mac *mac)
 {
 	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
-	struct zd_ioreq32 ioreqs[3] = {
+	struct zd_ioreq32 ioreqs[] = {
 		{ CR_RX_FILTER, STA_RX_FILTER },
 		{ CR_SNIFFER_ON, 0U },
 	};
@@ -164,10 +164,9 @@
 	if (ieee->iw_mode == IW_MODE_MONITOR) {
 		ioreqs[0].value = 0xffffffff;
 		ioreqs[1].value = 0x1;
-		ioreqs[2].value = ENC_SNIFFER;
 	}
 
-	return zd_iowrite32a(&mac->chip, ioreqs, 3);
+	return zd_iowrite32a(&mac->chip, ioreqs, ARRAY_SIZE(ioreqs));
 }
 
 int zd_mac_open(struct net_device *netdev)
@@ -904,16 +903,21 @@
 static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri)
 {
 	int i, r;
+	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 
 	for (i = 0; i < txb->nr_frags; i++) {
 		struct sk_buff *skb = txb->fragments[i];
 
 		r = fill_ctrlset(mac, txb, i);
-		if (r)
+		if (r) {
+			ieee->stats.tx_dropped++;
 			return r;
+		}
 		r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len);
-		if (r)
+		if (r) {
+			ieee->stats.tx_dropped++;
 			return r;
+		}
 	}
 
 	/* FIXME: shouldn't this be handled by the upper layers? */
@@ -1063,9 +1067,23 @@
 
 	*pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status));
 	if (status->frame_status & ZD_RX_ERROR) {
-		/* FIXME: update? */
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+		ieee->stats.rx_errors++;
+		if (status->frame_status & ZD_RX_TIMEOUT_ERROR)
+			ieee->stats.rx_missed_errors++;
+		else if (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR)
+			ieee->stats.rx_fifo_errors++;
+		else if (status->frame_status & ZD_RX_DECRYPTION_ERROR)
+			ieee->ieee_stats.rx_discards_undecryptable++;
+		else if (status->frame_status & ZD_RX_CRC32_ERROR) {
+			ieee->stats.rx_crc_errors++;
+			ieee->ieee_stats.rx_fcs_errors++;
+		}
+		else if (status->frame_status & ZD_RX_CRC16_ERROR)
+			ieee->stats.rx_crc_errors++;
 		return -EINVAL;
 	}
+
 	memset(stats, 0, sizeof(struct ieee80211_rx_stats));
 	stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN +
 		               + sizeof(struct rx_status));
@@ -1094,14 +1112,16 @@
 	if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
 	               IEEE80211_FCS_LEN + sizeof(struct rx_status))
 	{
-		dev_dbg_f(zd_mac_dev(mac), "Packet with length %u to small.\n",
-			 skb->len);
+		ieee->stats.rx_errors++;
+		ieee->stats.rx_length_errors++;
 		goto free_skb;
 	}
 
 	r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
 	if (r) {
-		/* Only packets with rx errors are included here. */
+		/* Only packets with rx errors are included here.
+		 * The error stats have already been set in fill_rx_stats.
+		 */
 		goto free_skb;
 	}
 
@@ -1114,8 +1134,10 @@
 
 	r = filter_rx(ieee, skb->data, skb->len, &stats);
 	if (r <= 0) {
-		if (r < 0)
+		if (r < 0) {
+			ieee->stats.rx_errors++;
 			dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
+		}
 		goto free_skb;
 	}
 
@@ -1146,7 +1168,9 @@
 
 	skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
 	if (!skb) {
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 		dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
+		ieee->stats.rx_dropped++;
 		return -ENOMEM;
 	}
 	skb_reserve(skb, sizeof(struct zd_rt_hdr));
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 75ef556..aac8a1c 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -313,6 +313,12 @@
 
 static inline void handle_retry_failed_int(struct urb *urb)
 {
+	struct zd_usb *usb = urb->context;
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+
+	ieee->stats.tx_errors++;
+	ieee->ieee_stats.tx_retry_limit_exceeded++;
 	dev_dbg_f(urb_dev(urb), "retry failed interrupt\n");
 }
 
@@ -487,6 +493,9 @@
 
 	if (length < sizeof(struct rx_length_info)) {
 		/* It's not a complete packet anyhow. */
+		struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+		ieee->stats.rx_errors++;
+		ieee->stats.rx_length_errors++;
 		return;
 	}
 	length_info = (struct rx_length_info *)
@@ -923,6 +932,8 @@
 		goto error;
 	}
 
+	usb_reset_device(interface_to_usbdev(intf));
+
 	netdev = zd_netdev_alloc(intf);
 	if (netdev == NULL) {
 		r = -ENOMEM;
@@ -1024,6 +1035,7 @@
 
 	r = usb_register(&driver);
 	if (r) {
+		destroy_workqueue(zd_workqueue);
 		printk(KERN_ERR "%s usb_register() failed. Error number %d\n",
 		       driver.name, r);
 		return r;
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index 04d6417..00e937e 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -181,7 +181,7 @@
 	return retval;
 }
  
-struct file_operations event_buffer_fops = {
+const struct file_operations event_buffer_fops = {
 	.open		= event_buffer_open,
 	.release	= event_buffer_release,
 	.read		= event_buffer_read,
diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h
index 9241627..9b6a4eb 100644
--- a/drivers/oprofile/event_buffer.h
+++ b/drivers/oprofile/event_buffer.h
@@ -41,7 +41,7 @@
 /* add data to the event buffer */
 void add_event_entry(unsigned long data);
  
-extern struct file_operations event_buffer_fops;
+extern const struct file_operations event_buffer_fops;
  
 /* mutex between sync_cpu_buffers() and the
  * file reading code.
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c
index a72006c..ef953ba 100644
--- a/drivers/oprofile/oprofile_files.c
+++ b/drivers/oprofile/oprofile_files.c
@@ -44,7 +44,7 @@
 }
 
 
-static struct file_operations depth_fops = {
+static const struct file_operations depth_fops = {
 	.read		= depth_read,
 	.write		= depth_write
 };
@@ -56,7 +56,7 @@
 }
 
 
-static struct file_operations pointer_size_fops = {
+static const struct file_operations pointer_size_fops = {
 	.read		= pointer_size_read,
 };
 
@@ -67,7 +67,7 @@
 }
  
  
-static struct file_operations cpu_type_fops = {
+static const struct file_operations cpu_type_fops = {
 	.read		= cpu_type_read,
 };
  
@@ -101,7 +101,7 @@
 }
 
  
-static struct file_operations enable_fops = {
+static const struct file_operations enable_fops = {
 	.read		= enable_read,
 	.write		= enable_write,
 };
@@ -114,7 +114,7 @@
 }
 
 
-static struct file_operations dump_fops = {
+static const struct file_operations dump_fops = {
 	.write		= dump_write,
 };
  
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index 5756401..6e67b42 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -115,14 +115,14 @@
 }
 
 
-static struct file_operations ulong_fops = {
+static const struct file_operations ulong_fops = {
 	.read		= ulong_read_file,
 	.write		= ulong_write_file,
 	.open		= default_open,
 };
 
 
-static struct file_operations ulong_ro_fops = {
+static const struct file_operations ulong_ro_fops = {
 	.read		= ulong_read_file,
 	.open		= default_open,
 };
@@ -182,7 +182,7 @@
 }
  
 
-static struct file_operations atomic_ro_fops = {
+static const struct file_operations atomic_ro_fops = {
 	.read		= atomic_read_file,
 	.open		= default_open,
 };
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index fe3f5f5..894fdb9 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -1091,7 +1091,7 @@
 	return single_open(file, &ccio_proc_info, NULL);
 }
 
-static struct file_operations ccio_proc_info_fops = {
+static const struct file_operations ccio_proc_info_fops = {
 	.owner = THIS_MODULE,
 	.open = ccio_proc_info_open,
 	.read = seq_read,
@@ -1127,7 +1127,7 @@
 	return single_open(file, &ccio_proc_bitmap_info, NULL);
 }
 
-static struct file_operations ccio_proc_bitmap_fops = {
+static const struct file_operations ccio_proc_bitmap_fops = {
 	.owner = THIS_MODULE,
 	.open = ccio_proc_bitmap_open,
 	.read = seq_read,
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index e97cecb..309076b 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -33,7 +33,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/eisa.h>
 
diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
index e13aafa..86e9c84 100644
--- a/drivers/parisc/eisa_eeprom.c
+++ b/drivers/parisc/eisa_eeprom.c
@@ -97,7 +97,7 @@
 /*
  *	The various file operations we support.
  */
-static struct file_operations eisa_eeprom_fops = {
+static const struct file_operations eisa_eeprom_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	eisa_eeprom_llseek,
 	.read =		eisa_eeprom_read,
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 8dac2ba..9a731c1 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -252,7 +252,6 @@
 	proc_pdc_root->owner = THIS_MODULE;
 	ent = create_proc_entry("led", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root);
 	if (!ent) return -1;
-	ent->nlink = 1;
 	ent->data = (void *)LED_NOLCD; /* LED */
 	ent->read_proc = led_proc_read;
 	ent->write_proc = led_proc_write;
@@ -262,7 +261,6 @@
 	{
 		ent = create_proc_entry("lcd", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root);
 		if (!ent) return -1;
-		ent->nlink = 1;
 		ent->data = (void *)LED_HASLCD; /* LCD */
 		ent->read_proc = led_proc_read;
 		ent->write_proc = led_proc_write;
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index f1e7ccd..76a29da 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -1799,7 +1799,7 @@
 	return single_open(f, &sba_proc_info, NULL);
 }
 
-static struct file_operations sba_proc_fops = {
+static const struct file_operations sba_proc_fops = {
 	.owner = THIS_MODULE,
 	.open = sba_proc_open,
 	.read = seq_read,
@@ -1831,7 +1831,7 @@
 	return single_open(f, &sba_proc_bitmap_info, NULL);
 }
 
-static struct file_operations sba_proc_bitmap_fops = {
+static const struct file_operations sba_proc_bitmap_fops = {
 	.owner = THIS_MODULE,
 	.open = sba_proc_bitmap_open,
 	.read = seq_read,
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index e60b4bf..316c06f 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index a7c5ead..17bf993 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index b61c17b..3de2623 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -1546,7 +1546,7 @@
 }
 #endif /* CONFIG_PARPORT_PC_SUPERIO */
 
-static int __devinit get_superio_dma (struct parport *p)
+static int get_superio_dma (struct parport *p)
 {
 	int i=0;
 	while( (superios[i].io != p->base) && (i<NR_SUPERIOS))
@@ -2106,7 +2106,7 @@
 /* --- DMA detection -------------------------------------- */
 
 /* Only if chipset conforms to ECP ISA Interface Standard */
-static int __devinit programmable_dma_support (struct parport *p)
+static int programmable_dma_support (struct parport *p)
 {
 	unsigned char oecr = inb (ECONTROL (p));
 	int dma;
@@ -2123,7 +2123,7 @@
 	return dma;
 }
 
-static int __devinit parport_dma_probe (struct parport *p)
+static int parport_dma_probe (struct parport *p)
 {
 	const struct parport_pc_private *priv = p->private_data;
 	if (priv->ecr)
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
index 2e744a2..bdbdab9 100644
--- a/drivers/parport/procfs.c
+++ b/drivers/parport/procfs.c
@@ -233,12 +233,12 @@
 	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
 }
 
-#define PARPORT_PORT_DIR(child) { 0, NULL, NULL, 0, 0555, child }
-#define PARPORT_PARPORT_DIR(child) { DEV_PARPORT, "parport", \
-                                     NULL, 0, 0555, child }
-#define PARPORT_DEV_DIR(child) { CTL_DEV, "dev", NULL, 0, 0555, child }
-#define PARPORT_DEVICES_ROOT_DIR  { DEV_PARPORT_DEVICES, "devices", \
-                                    NULL, 0, 0555, NULL }
+#define PARPORT_PORT_DIR(CHILD) { .ctl_name = 0, .procname = NULL, .mode = 0555, .child = CHILD }
+#define PARPORT_PARPORT_DIR(CHILD) { .ctl_name = DEV_PARPORT, .procname = "parport", \
+                                     .mode = 0555, .child = CHILD }
+#define PARPORT_DEV_DIR(CHILD) { .ctl_name = CTL_DEV, .procname = "dev", .mode = 0555, .child = CHILD }
+#define PARPORT_DEVICES_ROOT_DIR  { .ctl_name = DEV_PARPORT_DEVICES, .procname = "devices", \
+                                    .mode = 0555, .child = NULL }
 
 static const unsigned long parport_min_timeslice_value =
 PARPORT_MIN_TIMESLICE_VALUE;
@@ -263,50 +263,118 @@
 };
 
 static const struct parport_sysctl_table parport_sysctl_template = {
-	NULL,
+	.sysctl_header = NULL,
         {
-		{ DEV_PARPORT_SPINTIME, "spintime",
-		  NULL, sizeof(int), 0644, NULL,
-		  &proc_dointvec_minmax, NULL, NULL,
-		  (void*) &parport_min_spintime_value,
-		  (void*) &parport_max_spintime_value },
-		{ DEV_PARPORT_BASE_ADDR, "base-addr",
-		  NULL, 0, 0444, NULL,
-		  &do_hardware_base_addr },
-		{ DEV_PARPORT_IRQ, "irq",
-		  NULL, 0, 0444, NULL,
-		  &do_hardware_irq },
-		{ DEV_PARPORT_DMA, "dma",
-		  NULL, 0, 0444, NULL,
-		  &do_hardware_dma },
-		{ DEV_PARPORT_MODES, "modes",
-		  NULL, 0, 0444, NULL,
-		  &do_hardware_modes },
+		{
+			.ctl_name	= DEV_PARPORT_SPINTIME,
+			.procname	= "spintime",
+			.data		= NULL,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= &proc_dointvec_minmax,
+			.extra1		= (void*) &parport_min_spintime_value,
+			.extra2		= (void*) &parport_max_spintime_value
+		},
+		{
+			.ctl_name	= DEV_PARPORT_BASE_ADDR,
+			.procname	= "base-addr",
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0444,
+			.proc_handler	= &do_hardware_base_addr
+		},
+		{
+			.ctl_name	= DEV_PARPORT_IRQ,
+			.procname	= "irq",
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0444,
+			.proc_handler	= &do_hardware_irq
+		},
+		{
+			.ctl_name	= DEV_PARPORT_DMA,
+			.procname	= "dma",
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0444,
+			.proc_handler	= &do_hardware_dma
+		},
+		{
+			.ctl_name	= DEV_PARPORT_MODES,
+			.procname	= "modes",
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0444,
+			.proc_handler	= &do_hardware_modes
+		},
 		PARPORT_DEVICES_ROOT_DIR,
 #ifdef CONFIG_PARPORT_1284
-		{ DEV_PARPORT_AUTOPROBE, "autoprobe",
-		  NULL, 0, 0444, NULL,
-		  &do_autoprobe },
-		{ DEV_PARPORT_AUTOPROBE + 1, "autoprobe0",
-		 NULL, 0, 0444, NULL,
-		 &do_autoprobe },
-		{ DEV_PARPORT_AUTOPROBE + 2, "autoprobe1",
-		  NULL, 0, 0444, NULL,
-		  &do_autoprobe },
-		{ DEV_PARPORT_AUTOPROBE + 3, "autoprobe2",
-		  NULL, 0, 0444, NULL,
-		  &do_autoprobe },
-		{ DEV_PARPORT_AUTOPROBE + 4, "autoprobe3",
-		  NULL, 0, 0444, NULL,
-		  &do_autoprobe },
+		{
+			.ctl_name	= DEV_PARPORT_AUTOPROBE,
+			.procname	= "autoprobe",
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0444,
+			.proc_handler	= &do_autoprobe
+		},
+		{
+			.ctl_name	= DEV_PARPORT_AUTOPROBE + 1,
+			.procname	= "autoprobe0",
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0444,
+			.proc_handler	=  &do_autoprobe
+		},
+		{
+			.ctl_name	= DEV_PARPORT_AUTOPROBE + 2,
+			.procname	= "autoprobe1",
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0444,
+			.proc_handler	= &do_autoprobe
+		},
+		{
+			.ctl_name	= DEV_PARPORT_AUTOPROBE + 3,
+			.procname	= "autoprobe2",
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0444,
+			.proc_handler	= &do_autoprobe
+		},
+		{
+			.ctl_name	= DEV_PARPORT_AUTOPROBE + 4,
+			.procname	= "autoprobe3",
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0444,
+			.proc_handler	= &do_autoprobe
+		},
 #endif /* IEEE 1284 support */
-		{0}
+		{}
 	},
-	{ {DEV_PARPORT_DEVICES_ACTIVE, "active", NULL, 0, 0444, NULL,
-	  &do_active_device }, {0}},
-	{ PARPORT_PORT_DIR(NULL), {0}},
-	{ PARPORT_PARPORT_DIR(NULL), {0}},
-	{ PARPORT_DEV_DIR(NULL), {0}}
+	{
+		{
+			.ctl_name	= DEV_PARPORT_DEVICES_ACTIVE,
+			.procname	= "active",
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0444,
+			.proc_handler	= &do_active_device
+		},
+		{}
+	},
+	{
+		PARPORT_PORT_DIR(NULL),
+		{}
+	},
+	{
+		PARPORT_PARPORT_DIR(NULL),
+		{}
+	},
+	{
+		PARPORT_DEV_DIR(NULL),
+		{}
+	}
 };
 
 struct parport_device_sysctl_table
@@ -322,19 +390,46 @@
 
 static const struct parport_device_sysctl_table
 parport_device_sysctl_template = {
-	NULL,
+	.sysctl_header = NULL,
 	{
-		{ DEV_PARPORT_DEVICE_TIMESLICE, "timeslice",
-		  NULL, sizeof(int), 0644, NULL,
-		  &proc_doulongvec_ms_jiffies_minmax, NULL, NULL,
-		  (void*) &parport_min_timeslice_value,
-		  (void*) &parport_max_timeslice_value },
+		{
+			.ctl_name 	= DEV_PARPORT_DEVICE_TIMESLICE,
+			.procname 	= "timeslice",
+			.data		= NULL,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= &proc_doulongvec_ms_jiffies_minmax,
+			.extra1		= (void*) &parport_min_timeslice_value,
+			.extra2		= (void*) &parport_max_timeslice_value
+		},
 	},
-	{ {0, NULL, NULL, 0, 0555, NULL}, {0}},
-	{ PARPORT_DEVICES_ROOT_DIR, {0}},
-	{ PARPORT_PORT_DIR(NULL), {0}},
-	{ PARPORT_PARPORT_DIR(NULL), {0}},
-	{ PARPORT_DEV_DIR(NULL), {0}}
+	{
+		{
+			.ctl_name	= 0,
+			.procname	= NULL,
+			.data		= NULL,
+			.maxlen		= 0,
+			.mode		= 0555,
+			.child		= NULL
+		},
+		{}
+	},
+	{
+		PARPORT_DEVICES_ROOT_DIR,
+		{}
+	},
+	{
+		PARPORT_PORT_DIR(NULL),
+		{}
+	},
+	{
+		PARPORT_PARPORT_DIR(NULL),
+		{}
+	},
+	{
+		PARPORT_DEV_DIR(NULL),
+		{}
+	}
 };
 
 struct parport_default_sysctl_table
@@ -351,28 +446,47 @@
 
 static struct parport_default_sysctl_table
 parport_default_sysctl_table = {
-	NULL,
+	.sysctl_header	= NULL,
 	{
-		{ DEV_PARPORT_DEFAULT_TIMESLICE, "timeslice",
-		  &parport_default_timeslice,
-		  sizeof(parport_default_timeslice), 0644, NULL,
-		  &proc_doulongvec_ms_jiffies_minmax, NULL, NULL,
-		  (void*) &parport_min_timeslice_value,
-		  (void*) &parport_max_timeslice_value },
-		{ DEV_PARPORT_DEFAULT_SPINTIME, "spintime",
-		  &parport_default_spintime,
-		  sizeof(parport_default_spintime), 0644, NULL,
-		  &proc_dointvec_minmax, NULL, NULL,
-		  (void*) &parport_min_spintime_value,
-		  (void*) &parport_max_spintime_value },
-		{0}
+		{
+			.ctl_name	= DEV_PARPORT_DEFAULT_TIMESLICE,
+			.procname	= "timeslice",
+			.data		= &parport_default_timeslice,
+			.maxlen		= sizeof(parport_default_timeslice),
+			.mode		= 0644,
+			.proc_handler	= &proc_doulongvec_ms_jiffies_minmax,
+			.extra1		= (void*) &parport_min_timeslice_value,
+			.extra2		= (void*) &parport_max_timeslice_value
+		},
+		{
+			.ctl_name	= DEV_PARPORT_DEFAULT_SPINTIME,
+			.procname	= "spintime",
+			.data		= &parport_default_spintime,
+			.maxlen		= sizeof(parport_default_spintime),
+			.mode		= 0644,
+			.proc_handler	= &proc_dointvec_minmax,
+			.extra1		= (void*) &parport_min_spintime_value,
+			.extra2		= (void*) &parport_max_spintime_value
+		},
+		{}
 	},
-	{ { DEV_PARPORT_DEFAULT, "default", NULL, 0, 0555,
-	    parport_default_sysctl_table.vars },{0}},
 	{
-	PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir), 
-	{0}},
-	{ PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir), {0}}
+		{
+			.ctl_name	= DEV_PARPORT_DEFAULT,
+			.procname	= "default",
+			.mode		= 0555,
+			.child		= parport_default_sysctl_table.vars
+		},
+		{}
+	},
+	{
+		PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir),
+		{}
+	},
+	{
+		PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir),
+		{}
+	}
 };
 
 
@@ -404,7 +518,7 @@
 	t->parport_dir[0].child = t->port_dir;
 	t->dev_dir[0].child = t->parport_dir;
 
-	t->sysctl_header = register_sysctl_table(t->dev_dir, 0);
+	t->sysctl_header = register_sysctl_table(t->dev_dir);
 	if (t->sysctl_header == NULL) {
 		kfree(t);
 		t = NULL;
@@ -460,7 +574,7 @@
 	t->device_dir[0].child = t->vars;
 	t->vars[0].data = &device->timeslice;
 
-	t->sysctl_header = register_sysctl_table(t->dev_dir, 0);
+	t->sysctl_header = register_sysctl_table(t->dev_dir);
 	if (t->sysctl_header == NULL) {
 		kfree(t);
 		t = NULL;
@@ -483,7 +597,7 @@
 static int __init parport_default_proc_register(void)
 {
 	parport_default_sysctl_table.sysctl_header =
-		register_sysctl_table(parport_default_sysctl_table.dev_dir, 0);
+		register_sysctl_table(parport_default_sysctl_table.dev_dir);
 	return 0;
 }
 
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 3cfb0a3..5ea5bc7 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -4,7 +4,7 @@
 config PCI_MSI
 	bool "Message Signaled Interrupts (MSI and MSI-X)"
 	depends on PCI
-	depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64
+	depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 || SPARC64
 	help
 	   This allows device drivers to enable MSI (Message Signaled
 	   Interrupts).  Message Signaled Interrupts enable a device to
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 634f74d..a13abf5 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -202,7 +202,7 @@
 	return 0;
 }
 
-static struct file_operations debug_ops = {
+static const struct file_operations debug_ops = {
 	.owner = THIS_MODULE,
 	.open = open,
 	.llseek = lseek,
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
index 05e4f5a..600ed7b6 100644
--- a/drivers/pci/hotplug/ibmphp_ebda.c
+++ b/drivers/pci/hotplug/ibmphp_ebda.c
@@ -28,7 +28,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 4438ae1..a3c1755 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -415,6 +415,7 @@
  * __pci_register_driver - register a new pci driver
  * @drv: the driver structure to register
  * @owner: owner module of drv
+ * @mod_name: module name string
  * 
  * Adds the driver structure to the list of registered drivers.
  * Returns a negative value on error, otherwise 0. 
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7a94076..cd913a2 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -143,6 +143,14 @@
 	return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt));
 }
 
+#ifdef CONFIG_NUMA
+static ssize_t
+numa_node_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf (buf, "%d\n", dev->numa_node);
+}
+#endif
+
 static ssize_t
 msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -194,6 +202,9 @@
 	__ATTR_RO(irq),
 	__ATTR_RO(local_cpus),
 	__ATTR_RO(modalias),
+#ifdef CONFIG_NUMA
+	__ATTR_RO(numa_node),
+#endif
 	__ATTR(enable, 0600, is_enabled_show, is_enabled_store),
 	__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
 		broken_parity_status_show,broken_parity_status_store),
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 84c757b..1e74e1e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -21,6 +21,12 @@
 
 unsigned int pci_pm_d3_delay = 10;
 
+#define DEFAULT_CARDBUS_IO_SIZE		(256)
+#define DEFAULT_CARDBUS_MEM_SIZE	(64*1024*1024)
+/* pci=cbmemsize=nnM,cbiosize=nn can override this */
+unsigned long pci_cardbus_io_size = DEFAULT_CARDBUS_IO_SIZE;
+unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
+
 /**
  * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
  * @bus: pointer to PCI bus structure to search
@@ -744,6 +750,104 @@
 	return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
 }
 
+/*
+ * Managed PCI resources.  This manages device on/off, intx/msi/msix
+ * on/off and BAR regions.  pci_dev itself records msi/msix status, so
+ * there's no need to track it separately.  pci_devres is initialized
+ * when a device is enabled using managed PCI device enable interface.
+ */
+struct pci_devres {
+	unsigned int disable:1;
+	unsigned int orig_intx:1;
+	unsigned int restore_intx:1;
+	u32 region_mask;
+};
+
+static void pcim_release(struct device *gendev, void *res)
+{
+	struct pci_dev *dev = container_of(gendev, struct pci_dev, dev);
+	struct pci_devres *this = res;
+	int i;
+
+	if (dev->msi_enabled)
+		pci_disable_msi(dev);
+	if (dev->msix_enabled)
+		pci_disable_msix(dev);
+
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+		if (this->region_mask & (1 << i))
+			pci_release_region(dev, i);
+
+	if (this->restore_intx)
+		pci_intx(dev, this->orig_intx);
+
+	if (this->disable)
+		pci_disable_device(dev);
+}
+
+static struct pci_devres * get_pci_dr(struct pci_dev *pdev)
+{
+	struct pci_devres *dr, *new_dr;
+
+	dr = devres_find(&pdev->dev, pcim_release, NULL, NULL);
+	if (dr)
+		return dr;
+
+	new_dr = devres_alloc(pcim_release, sizeof(*new_dr), GFP_KERNEL);
+	if (!new_dr)
+		return NULL;
+	return devres_get(&pdev->dev, new_dr, NULL, NULL);
+}
+
+static struct pci_devres * find_pci_dr(struct pci_dev *pdev)
+{
+	if (pci_is_managed(pdev))
+		return devres_find(&pdev->dev, pcim_release, NULL, NULL);
+	return NULL;
+}
+
+/**
+ * pcim_enable_device - Managed pci_enable_device()
+ * @pdev: PCI device to be initialized
+ *
+ * Managed pci_enable_device().
+ */
+int pcim_enable_device(struct pci_dev *pdev)
+{
+	struct pci_devres *dr;
+	int rc;
+
+	dr = get_pci_dr(pdev);
+	if (unlikely(!dr))
+		return -ENOMEM;
+	WARN_ON(!!dr->disable);
+
+	rc = pci_enable_device(pdev);
+	if (!rc) {
+		pdev->is_managed = 1;
+		dr->disable = 1;
+	}
+	return rc;
+}
+
+/**
+ * pcim_pin_device - Pin managed PCI device
+ * @pdev: PCI device to pin
+ *
+ * Pin managed PCI device @pdev.  Pinned device won't be disabled on
+ * driver detach.  @pdev must have been enabled with
+ * pcim_enable_device().
+ */
+void pcim_pin_device(struct pci_dev *pdev)
+{
+	struct pci_devres *dr;
+
+	dr = find_pci_dr(pdev);
+	WARN_ON(!dr || !dr->disable);
+	if (dr)
+		dr->disable = 0;
+}
+
 /**
  * pcibios_disable_device - disable arch specific PCI resources for device dev
  * @dev: the PCI device to disable
@@ -767,8 +871,13 @@
 void
 pci_disable_device(struct pci_dev *dev)
 {
+	struct pci_devres *dr;
 	u16 pci_command;
 
+	dr = find_pci_dr(dev);
+	if (dr)
+		dr->disable = 0;
+
 	if (atomic_sub_return(1, &dev->enable_cnt) != 0)
 		return;
 
@@ -867,6 +976,8 @@
  */
 void pci_release_region(struct pci_dev *pdev, int bar)
 {
+	struct pci_devres *dr;
+
 	if (pci_resource_len(pdev, bar) == 0)
 		return;
 	if (pci_resource_flags(pdev, bar) & IORESOURCE_IO)
@@ -875,6 +986,10 @@
 	else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM)
 		release_mem_region(pci_resource_start(pdev, bar),
 				pci_resource_len(pdev, bar));
+
+	dr = find_pci_dr(pdev);
+	if (dr)
+		dr->region_mask &= ~(1 << bar);
 }
 
 /**
@@ -893,6 +1008,8 @@
  */
 int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
 {
+	struct pci_devres *dr;
+
 	if (pci_resource_len(pdev, bar) == 0)
 		return 0;
 		
@@ -906,7 +1023,11 @@
 				        pci_resource_len(pdev, bar), res_name))
 			goto err_out;
 	}
-	
+
+	dr = find_pci_dr(pdev);
+	if (dr)
+		dr->region_mask |= 1 << bar;
+
 	return 0;
 
 err_out:
@@ -1144,7 +1265,15 @@
 	}
 
 	if (new != pci_command) {
+		struct pci_devres *dr;
+
 		pci_write_config_word(pdev, PCI_COMMAND, new);
+
+		dr = find_pci_dr(pdev);
+		if (dr && !dr->restore_intx) {
+			dr->restore_intx = 1;
+			dr->orig_intx = !enable;
+		}
 	}
 }
 
@@ -1177,7 +1306,7 @@
 
 /**
  * pci_select_bars - Make BAR mask from the type of resource
- * @pdev: the PCI device for which BAR mask is made
+ * @dev: the PCI device for which BAR mask is made
  * @flags: resource type mask to be selected
  *
  * This helper routine makes bar mask from the type of resource.
@@ -1210,6 +1339,10 @@
 		if (*str && (str = pcibios_setup(str)) && *str) {
 			if (!strcmp(str, "nomsi")) {
 				pci_no_msi();
+			} else if (!strncmp(str, "cbiosize=", 9)) {
+				pci_cardbus_io_size = memparse(str + 9, &str);
+			} else if (!strncmp(str, "cbmemsize=", 10)) {
+				pci_cardbus_mem_size = memparse(str + 10, &str);
 			} else {
 				printk(KERN_ERR "PCI: Unknown option `%s'\n",
 						str);
@@ -1226,6 +1359,8 @@
 EXPORT_SYMBOL_GPL(pci_restore_bars);
 EXPORT_SYMBOL(pci_enable_device_bars);
 EXPORT_SYMBOL(pci_enable_device);
+EXPORT_SYMBOL(pcim_enable_device);
+EXPORT_SYMBOL(pcim_pin_device);
 EXPORT_SYMBOL(pci_disable_device);
 EXPORT_SYMBOL(pci_find_capability);
 EXPORT_SYMBOL(pci_bus_find_capability);
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 6f5fabb..b164de0 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -220,7 +220,7 @@
 	}
 
 	/* Request IRQ ISR */
-	if ((status = request_irq(dev->irq, aer_irq, SA_SHIRQ, "aerdrv",
+	if ((status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv",
 				dev))) {
 		printk(KERN_DEBUG "%s: Request ISR fails on PCIE device[%s]\n",
 			__FUNCTION__, device->bus_id);
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index 3c0a58f..bf655db 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -85,7 +85,7 @@
 	struct mutex rpc_mutex;		/*
 					 * only one thread could do
 					 * recovery on the same
-					 * root port hierachy
+					 * root port hierarchy
 					 */
 	wait_queue_head_t wait_release;
 };
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 4a6760a..ed87aa5 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -287,7 +287,7 @@
 }
 #endif /* HAVE_PCI_MMAP */
 
-static struct file_operations proc_bus_pci_operations = {
+static const struct file_operations proc_bus_pci_operations = {
 	.llseek		= proc_bus_pci_lseek,
 	.read		= proc_bus_pci_read,
 	.write		= proc_bus_pci_write,
@@ -456,7 +456,7 @@
 {
 	return seq_open(file, &proc_bus_pci_devices_op);
 }
-static struct file_operations proc_bus_pci_dev_operations = {
+static const struct file_operations proc_bus_pci_dev_operations = {
 	.open		= proc_bus_pci_dev_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 11217bd..1e6eda2 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -871,7 +871,7 @@
 		pci_write_config_byte(pdev, 0xa, 6);
 		pci_write_config_byte(pdev, 0x40, tmp);
 
-		pdev->class = 0x010601;
+		pdev->class = PCI_CLASS_STORAGE_SATA_AHCI;
 	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_sb600_sata);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 89f3036..3554f39 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -36,13 +36,6 @@
 
 #define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
 
-/*
- * FIXME: IO should be max 256 bytes.  However, since we may
- * have a P2P bridge below a cardbus bridge, we need 4K.
- */
-#define CARDBUS_IO_SIZE		(256)
-#define CARDBUS_MEM_SIZE	(64*1024*1024)
-
 static void __devinit
 pbus_assign_resources_sorted(struct pci_bus *bus)
 {
@@ -415,12 +408,12 @@
 	 * Reserve some resources for CardBus.  We reserve
 	 * a fixed amount of bus space for CardBus bridges.
 	 */
-	b_res[0].start = CARDBUS_IO_SIZE;
-	b_res[0].end = b_res[0].start + CARDBUS_IO_SIZE - 1;
+	b_res[0].start = pci_cardbus_io_size;
+	b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1;
 	b_res[0].flags |= IORESOURCE_IO;
 
-	b_res[1].start = CARDBUS_IO_SIZE;
-	b_res[1].end = b_res[1].start + CARDBUS_IO_SIZE - 1;
+	b_res[1].start = pci_cardbus_io_size;
+	b_res[1].end = b_res[1].start + pci_cardbus_io_size - 1;
 	b_res[1].flags |= IORESOURCE_IO;
 
 	/*
@@ -440,16 +433,16 @@
 	 * twice the size.
 	 */
 	if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
-		b_res[2].start = CARDBUS_MEM_SIZE;
-		b_res[2].end = b_res[2].start + CARDBUS_MEM_SIZE - 1;
+		b_res[2].start = pci_cardbus_mem_size;
+		b_res[2].end = b_res[2].start + pci_cardbus_mem_size - 1;
 		b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
 
-		b_res[3].start = CARDBUS_MEM_SIZE;
-		b_res[3].end = b_res[3].start + CARDBUS_MEM_SIZE - 1;
+		b_res[3].start = pci_cardbus_mem_size;
+		b_res[3].end = b_res[3].start + pci_cardbus_mem_size - 1;
 		b_res[3].flags |= IORESOURCE_MEM;
 	} else {
-		b_res[3].start = CARDBUS_MEM_SIZE * 2;
-		b_res[3].end = b_res[3].start + CARDBUS_MEM_SIZE * 2 - 1;
+		b_res[3].start = pci_cardbus_mem_size * 2;
+		b_res[3].end = b_res[3].start + pci_cardbus_mem_size * 2 - 1;
 		b_res[3].flags |= IORESOURCE_MEM;
 	}
 }
diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
index a251289..568f187 100644
--- a/drivers/pci/setup-irq.c
+++ b/drivers/pci/setup-irq.c
@@ -24,7 +24,7 @@
 	       int (*map_irq)(struct pci_dev *, u8, u8))
 {
 	u8 pin, slot;
-	int irq;
+	int irq = 0;
 
 	/* If this device is not on the primary bus, we need to figure out
 	   which interrupt pin it will come in on.   We know which slot it
@@ -33,16 +33,18 @@
 	   apply the swizzle function.  */
 
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-	/* Cope with 0 and illegal. */
-	if (pin == 0 || pin > 4)
+	/* Cope with illegal. */
+	if (pin > 4)
 		pin = 1;
 
-	/* Follow the chain of bridges, swizzling as we go.  */
-	slot = (*swizzle)(dev, &pin);
+	if (pin != 0) {
+		/* Follow the chain of bridges, swizzling as we go.  */
+		slot = (*swizzle)(dev, &pin);
 
-	irq = (*map_irq)(dev, slot, pin);
-	if (irq == -1)
-		irq = 0;
+		irq = (*map_irq)(dev, slot, pin);
+		if (irq == -1)
+			irq = 0;
+	}
 	dev->irq = irq;
 
 	pr_debug("PCI: fixup irq: (%s) got %d\n",
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index 87fafc0..9d37fec 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -7,7 +7,6 @@
  * magic northbridge registers..
  */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 3334f22..99baabc 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -11,7 +11,6 @@
 
 #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>
@@ -278,7 +277,7 @@
 		board->det_pin, board->irq_pin);
 
 	cf->socket.owner = THIS_MODULE;
-	cf->socket.dev.dev = &pdev->dev;
+	cf->socket.dev.parent = &pdev->dev;
 	cf->socket.ops = &at91_cf_ops;
 	cf->socket.resource_ops = &pccard_static_ops;
 	cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 2d7effe..a1bd763 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -40,8 +40,6 @@
 
 /*====================================================================*/
 
-#define FIND_FIRST_BIT(n)	((n) - ((n) & ((n)-1)))
-
 /* Offsets in the Expansion ROM Image Header */
 #define ROM_SIGNATURE		0x0000	/* 2 bytes */
 #define ROM_DATA_PTR		0x0018	/* 2 bytes */
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 912c03e..d154dee 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -21,7 +21,6 @@
 #include <linux/timer.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index caca0dc..f2e810f 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -907,7 +907,7 @@
 
 	for (i=0; i<HS_MAX_SOCKETS; i++) {
 		unsigned int ret;
-		hs_sockets[i].socket.dev.dev = &hd64465_device.dev;		
+		hs_sockets[i].socket.dev.parent = &hd64465_device.dev;
 		hs_sockets[i].number = i;
 		ret = pcmcia_register_socket(&hs_sockets[i].socket);
 		if (ret && i)
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 72ff2f6..71b3370 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -40,7 +40,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 3c22ac4..91da15b 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -761,7 +760,7 @@
 	/* Set up interrupt handler(s) */
 
 	for (i = 0 ; i < pcc_sockets ; i++) {
-		socket[i].socket.dev.dev = &pcc_device.dev;
+		socket[i].socket.dev.parent = &pcc_device.dev;
 		socket[i].socket.ops = &pcc_operations;
 		socket[i].socket.resource_ops = &pccard_nonstatic_ops;
 		socket[i].socket.owner = THIS_MODULE;
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index bbf0258..67d28ee 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -722,7 +721,7 @@
 	/* Set up interrupt handler(s) */
 
 	for (i = 0 ; i < pcc_sockets ; i++) {
-		socket[i].socket.dev.dev = &pcc_device.dev;
+		socket[i].socket.dev.parent = &pcc_device.dev;
 		socket[i].socket.ops = &pcc_operations;
 		socket[i].socket.resource_ops = &pccard_static_ops;
 		socket[i].socket.owner = THIS_MODULE;
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 3b72be8..9721ed7 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -46,7 +46,6 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/ioport.h>
@@ -1322,7 +1321,7 @@
 		socket[i].socket.ops = &m8xx_services;
 		socket[i].socket.resource_ops = &pccard_iodyn_ops;
 		socket[i].socket.cb_dev = NULL;
-		socket[i].socket.dev.dev = &m8xx_device.dev;
+		socket[i].socket.dev.parent = &m8xx_device.dev;
 	}
 
 	for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index e65a6b8..d77f751 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -11,7 +11,6 @@
 
 #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>
@@ -292,7 +291,7 @@
 		omap_cf_present() ? "present" : "(not present)");
 
 	cf->socket.owner = THIS_MODULE;
-	cf->socket.dev.dev = dev;
+	cf->socket.dev.parent = dev;
 	cf->socket.ops = &omap_cf_ops;
 	cf->socket.resource_ops = &pccard_static_ops;
 	cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 8849414..27523c5 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -765,7 +765,7 @@
 
 /*====================================================================*/
 
-static struct file_operations ds_fops = {
+static const struct file_operations ds_fops = {
 	.owner		= THIS_MODULE,
 	.open		= ds_open,
 	.release	= ds_release,
diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c
index a92f111..5e9b9a3 100644
--- a/drivers/pcmcia/pxa2xx_lubbock.c
+++ b/drivers/pcmcia/pxa2xx_lubbock.c
@@ -16,7 +16,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 81dfc2c..ce22262 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -232,7 +232,7 @@
 		unsigned long align, struct pcmcia_socket *s)
 {
 	struct resource *res = make_resource(0, num, IORESOURCE_IO,
-					     s->dev.class_id);
+					     s->dev.bus_id);
 	struct pcmcia_align_data data;
 	unsigned long min = base;
 	int ret;
diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c
index 19b1e12..62bfc75 100644
--- a/drivers/pcmcia/sa1100_badge4.c
+++ b/drivers/pcmcia/sa1100_badge4.c
@@ -14,7 +14,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c
index eb89928..549a152 100644
--- a/drivers/pcmcia/sa1100_cerf.c
+++ b/drivers/pcmcia/sa1100_cerf.c
@@ -7,7 +7,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/delay.h>
diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c
index 64fd5e3..e549187 100644
--- a/drivers/pcmcia/sa1100_h3600.c
+++ b/drivers/pcmcia/sa1100_h3600.c
@@ -6,7 +6,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1100_jornada720.c
index 7a87298..af485ae 100644
--- a/drivers/pcmcia/sa1100_jornada720.c
+++ b/drivers/pcmcia/sa1100_jornada720.c
@@ -6,7 +6,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
diff --git a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1100_neponset.c
index 5e34b3e..5bc9e95 100644
--- a/drivers/pcmcia/sa1100_neponset.c
+++ b/drivers/pcmcia/sa1100_neponset.c
@@ -5,7 +5,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c
index 7bc9e59..9456f54 100644
--- a/drivers/pcmcia/sa1100_shannon.c
+++ b/drivers/pcmcia/sa1100_shannon.c
@@ -6,7 +6,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/init.h>
 
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index c2ecf11..04d6f7f 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -6,7 +6,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/init.h>
 
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index d2a3bea..aa7779d 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -478,7 +478,7 @@
  *
  * Returns: the number of characters added to the buffer
  */
-static ssize_t show_status(struct device *dev, char *buf)
+static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct soc_pcmcia_socket *skt =
 		container_of(dev, struct soc_pcmcia_socket, socket.dev);
@@ -501,7 +501,7 @@
 
 	return p-buf;
 }
-static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
 
 
 static struct pccard_operations soc_common_pcmcia_operations = {
@@ -660,7 +660,7 @@
 
 		skt->socket.ops = &soc_common_pcmcia_operations;
 		skt->socket.owner = ops->owner;
-		skt->socket.dev.dev = dev;
+		skt->socket.dev.parent = dev;
 
 		init_timer(&skt->poll_timer);
 		skt->poll_timer.function = soc_common_pcmcia_poll_event;
@@ -747,7 +747,7 @@
 
 		add_timer(&skt->poll_timer);
 
-		device_create_file(&skt->socket.dev, &device_attr_status);
+		device_create_file(&skt->socket.dev, &dev_attr_status);
 	}
 
 	dev_set_drvdata(dev, sinfo);
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index e90d8e8..eee2f1c 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -22,7 +22,6 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 
@@ -597,7 +596,7 @@
 		}
 
 		sprintf(socket->name, "NEC VRC4171 Card Slot %1c", 'A' + slot);
-		socket->pcmcia_socket.dev.dev = &vrc4171_card_device.dev;
+		socket->pcmcia_socket.dev.parent = &vrc4171_card_device.dev;
 		socket->pcmcia_socket.ops = &vrc4171_pccard_operations;
 		socket->pcmcia_socket.owner = THIS_MODULE;
 
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index a61d768..20853a0 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -12,7 +12,6 @@
  */
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 6b8c4cf..31a633f 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -1,4 +1,3 @@
-extern struct bus_type pnp_bus_type;
 extern spinlock_t pnp_lock;
 void *pnp_alloc(long size);
 int pnp_interface_attach_device(struct pnp_dev *dev);
diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
index d21f3c1..40b724e 100644
--- a/drivers/pnp/isapnp/proc.c
+++ b/drivers/pnp/isapnp/proc.c
@@ -85,7 +85,7 @@
 	return nbytes;
 }
 
-static struct file_operations isapnp_proc_bus_file_operations =
+static const struct file_operations isapnp_proc_bus_file_operations =
 {
 	.llseek		= isapnp_proc_bus_lseek,
 	.read		= isapnp_proc_bus_read,
diff --git a/drivers/pnp/pnpacpi/Kconfig b/drivers/pnp/pnpacpi/Kconfig
index ad27e5e..b04767c 100644
--- a/drivers/pnp/pnpacpi/Kconfig
+++ b/drivers/pnp/pnpacpi/Kconfig
@@ -2,17 +2,5 @@
 # Plug and Play ACPI configuration
 #
 config PNPACPI
-	bool "Plug and Play ACPI support"
-	depends on PNP && ACPI
-	default y
-	---help---
-	  Linux uses the PNPACPI to autodetect built-in
-	  mainboard resources (e.g. parallel port resources).
-
-          Some features (e.g. real hotplug) are not currently
-          implemented.
-
-          If you would like the kernel to detect and allocate resources to
-          your mainboard devices (on some systems they are disabled by the
-          BIOS) say Y here.  Also the PNPACPI can help prevent resource
-          conflicts between mainboard devices and other bus devices.
+	bool
+	default (PNP && ACPI)
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index 95b7968..3c2ab839 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -530,7 +530,6 @@
 			dev_id =  kzalloc(sizeof (struct pnp_id), GFP_KERNEL);
 			if (!dev_id)
 				return NULL;
-			memset(dev_id, 0, sizeof(struct pnp_id));
 			pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24,id);
 			memcpy(&dev_id->id, id, 7);
 			pnp_add_id(dev_id, dev);
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index d547cf5..e251d1c 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1 +1,3 @@
 obj-$(CONFIG_PS3_VUART) += vuart.o
+obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
new file mode 100644
index 0000000..1926b4d
--- /dev/null
+++ b/drivers/ps3/ps3av.c
@@ -0,0 +1,974 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ *
+ * AV backend support for PS3
+ *
+ * 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.
+ *
+ * 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/module.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/kernel.h>
+#include <linux/ioctl.h>
+#include <asm/lv1call.h>
+#include <asm/ps3av.h>
+#include <asm/ps3.h>
+
+#include "vuart.h"
+
+#define BUFSIZE          4096	/* vuart buf size */
+#define PS3AV_BUF_SIZE   512	/* max packet size */
+
+static int timeout = 5000;	/* in msec ( 5 sec ) */
+module_param(timeout, int, 0644);
+
+static struct ps3av ps3av;
+
+static struct ps3_vuart_port_device ps3av_dev = {
+	.match_id = PS3_MATCH_ID_AV_SETTINGS
+};
+
+/* color space */
+#define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
+#define RGB8   PS3AV_CMD_VIDEO_CS_RGB_8
+/* format */
+#define XRGB   PS3AV_CMD_VIDEO_FMT_X8R8G8B8
+/* aspect */
+#define A_N    PS3AV_CMD_AV_ASPECT_4_3
+#define A_W    PS3AV_CMD_AV_ASPECT_16_9
+static const struct avset_video_mode {
+	u32 cs;
+	u32 fmt;
+	u32 vid;
+	u32 aspect;
+	u32 x;
+	u32 y;
+	u32 interlace;
+	u32 freq;
+} video_mode_table[] = {
+	{     0, }, /* auto */
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I,       A_N,  720,  480, 1, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P,       A_N,  720,  480, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ,  A_N, 1280,  720, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I,       A_N,  720,  576, 1, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P,       A_N,  720,  576, 0, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ,  A_N, 1280,  720, 0, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA,       A_W, 1280,  768, 0, 60},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA,       A_N, 1280, 1024, 0, 60},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA,      A_W, 1920, 1200, 0, 60},
+};
+
+/* supported CIDs */
+static u32 cmd_table[] = {
+	/* init */
+	PS3AV_CID_AV_INIT,
+	PS3AV_CID_AV_FIN,
+	PS3AV_CID_VIDEO_INIT,
+	PS3AV_CID_AUDIO_INIT,
+
+	/* set */
+	PS3AV_CID_AV_ENABLE_EVENT,
+	PS3AV_CID_AV_DISABLE_EVENT,
+
+	PS3AV_CID_AV_VIDEO_CS,
+	PS3AV_CID_AV_VIDEO_MUTE,
+	PS3AV_CID_AV_VIDEO_DISABLE_SIG,
+	PS3AV_CID_AV_AUDIO_PARAM,
+	PS3AV_CID_AV_AUDIO_MUTE,
+	PS3AV_CID_AV_HDMI_MODE,
+	PS3AV_CID_AV_TV_MUTE,
+
+	PS3AV_CID_VIDEO_MODE,
+	PS3AV_CID_VIDEO_FORMAT,
+	PS3AV_CID_VIDEO_PITCH,
+
+	PS3AV_CID_AUDIO_MODE,
+	PS3AV_CID_AUDIO_MUTE,
+	PS3AV_CID_AUDIO_ACTIVE,
+	PS3AV_CID_AUDIO_INACTIVE,
+	PS3AV_CID_AVB_PARAM,
+
+	/* get */
+	PS3AV_CID_AV_GET_HW_CONF,
+	PS3AV_CID_AV_GET_MONITOR_INFO,
+
+	/* event */
+	PS3AV_CID_EVENT_UNPLUGGED,
+	PS3AV_CID_EVENT_PLUGGED,
+	PS3AV_CID_EVENT_HDCP_DONE,
+	PS3AV_CID_EVENT_HDCP_FAIL,
+	PS3AV_CID_EVENT_HDCP_AUTH,
+	PS3AV_CID_EVENT_HDCP_ERROR,
+
+	0
+};
+
+#define PS3AV_EVENT_CMD_MASK           0x10000000
+#define PS3AV_EVENT_ID_MASK            0x0000ffff
+#define PS3AV_CID_MASK                 0xffffffff
+#define PS3AV_REPLY_BIT                0x80000000
+
+#define ps3av_event_get_port_id(cid)   ((cid >> 16) & 0xff)
+
+static u32 *ps3av_search_cmd_table(u32 cid, u32 mask)
+{
+	u32 *table;
+	int i;
+
+	table = cmd_table;
+	for (i = 0;; table++, i++) {
+		if ((*table & mask) == (cid & mask))
+			break;
+		if (*table == 0)
+			return NULL;
+	}
+	return table;
+}
+
+static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
+{
+	u32 *table;
+
+	if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
+		table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
+		if (table)
+			dev_dbg(&ps3av_dev.core,
+				"recv event packet cid:%08x port:0x%x size:%d\n",
+				hdr->cid, ps3av_event_get_port_id(hdr->cid),
+				hdr->size);
+		else
+			printk(KERN_ERR
+			       "%s: failed event packet, cid:%08x size:%d\n",
+			       __FUNCTION__, hdr->cid, hdr->size);
+		return 1;	/* receive event packet */
+	}
+	return 0;
+}
+
+static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
+			      struct ps3av_reply_hdr *recv_buf, int write_len,
+			      int read_len)
+{
+	int res;
+	u32 cmd;
+	int event;
+
+	if (!ps3av.available)
+		return -ENODEV;
+
+	/* send pkt */
+	res = ps3av_vuart_write(ps3av.dev, send_buf, write_len);
+	if (res < 0) {
+		dev_dbg(&ps3av_dev.core,
+			"%s: ps3av_vuart_write() failed (result=%d)\n",
+			__FUNCTION__, res);
+		return res;
+	}
+
+	/* recv pkt */
+	cmd = send_buf->cid;
+	do {
+		/* read header */
+		res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE,
+				       timeout);
+		if (res != PS3AV_HDR_SIZE) {
+			dev_dbg(&ps3av_dev.core,
+				"%s: ps3av_vuart_read() failed (result=%d)\n",
+				__FUNCTION__, res);
+			return res;
+		}
+
+		/* read body */
+		res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid,
+				       recv_buf->size, timeout);
+		if (res < 0) {
+			dev_dbg(&ps3av_dev.core,
+				"%s: ps3av_vuart_read() failed (result=%d)\n",
+				__FUNCTION__, res);
+			return res;
+		}
+		res += PS3AV_HDR_SIZE;	/* total len */
+		event = ps3av_parse_event_packet(recv_buf);
+		/* ret > 0 event packet */
+	} while (event);
+
+	if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
+		dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n",
+			__FUNCTION__, recv_buf->cid);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf,
+				      const struct ps3av_reply_hdr *recv_buf,
+				      int user_buf_size)
+{
+	int return_len;
+
+	if (recv_buf->version != PS3AV_VERSION) {
+		dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n",
+			recv_buf->version);
+		return -EFAULT;
+	}
+	return_len = recv_buf->size + PS3AV_HDR_SIZE;
+	if (return_len > user_buf_size)
+		return_len = user_buf_size;
+	memcpy(cmd_buf, recv_buf, return_len);
+	return 0;		/* success */
+}
+
+void ps3av_set_hdr(u32 cid, u16 size, struct ps3av_send_hdr *hdr)
+{
+	hdr->version = PS3AV_VERSION;
+	hdr->size = size - PS3AV_HDR_SIZE;
+	hdr->cid = cid;
+}
+
+int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
+		 struct ps3av_send_hdr *buf)
+{
+	int res = 0;
+	union {
+		struct ps3av_reply_hdr reply_hdr;
+		u8 raw[PS3AV_BUF_SIZE];
+	} recv_buf;
+
+	u32 *table;
+
+	BUG_ON(!ps3av.available);
+
+	if (down_interruptible(&ps3av.sem))
+		return -ERESTARTSYS;
+
+	table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
+	BUG_ON(!table);
+	BUG_ON(send_len < PS3AV_HDR_SIZE);
+	BUG_ON(usr_buf_size < send_len);
+	BUG_ON(usr_buf_size > PS3AV_BUF_SIZE);
+
+	/* create header */
+	ps3av_set_hdr(cid, send_len, buf);
+
+	/* send packet via vuart */
+	res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len,
+				 usr_buf_size);
+	if (res < 0) {
+		printk(KERN_ERR
+		       "%s: ps3av_send_cmd_pkt() failed (result=%d)\n",
+		       __FUNCTION__, res);
+		goto err;
+	}
+
+	/* process reply packet */
+	res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr,
+					 usr_buf_size);
+	if (res < 0) {
+		printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
+		       __FUNCTION__, res);
+		goto err;
+	}
+
+	up(&ps3av.sem);
+	return 0;
+
+      err:
+	up(&ps3av.sem);
+	printk(KERN_ERR "%s: failed cid:%x res:%d\n", __FUNCTION__, cid, res);
+	return res;
+}
+
+static int ps3av_set_av_video_mute(u32 mute)
+{
+	int i, num_of_av_port, res;
+
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
+			 ps3av.av_hw_conf.num_of_avmulti;
+	/* video mute on */
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int ps3av_set_video_disable_sig(void)
+{
+	int i, num_of_hdmi_port, num_of_av_port, res;
+
+	num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi;
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
+			 ps3av.av_hw_conf.num_of_avmulti;
+
+	/* tv mute */
+	for (i = 0; i < num_of_hdmi_port; i++) {
+		res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+					   PS3AV_CMD_MUTE_ON);
+		if (res < 0)
+			return -1;
+	}
+	msleep(100);
+
+	/* video mute on */
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
+		if (res < 0)
+			return -1;
+		if (i < num_of_hdmi_port) {
+			res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+						   PS3AV_CMD_MUTE_OFF);
+			if (res < 0)
+				return -1;
+		}
+	}
+	msleep(300);
+
+	return 0;
+}
+
+static int ps3av_set_audio_mute(u32 mute)
+{
+	int i, num_of_av_port, num_of_opt_port, res;
+
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
+			 ps3av.av_hw_conf.num_of_avmulti;
+	num_of_opt_port = ps3av.av_hw_conf.num_of_spdif;
+
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+	for (i = 0; i < num_of_opt_port; i++) {
+		res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
+{
+	struct ps3av_pkt_avb_param avb_param;
+	int i, num_of_audio, vid, res;
+	struct ps3av_pkt_audio_mode audio_mode;
+	u32 len = 0;
+
+	num_of_audio = ps3av.av_hw_conf.num_of_hdmi +
+		       ps3av.av_hw_conf.num_of_avmulti +
+		       ps3av.av_hw_conf.num_of_spdif;
+
+	avb_param.num_of_video_pkt = 0;
+	avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO;	/* always 0 */
+	avb_param.num_of_av_video_pkt = 0;
+	avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi;
+
+	vid = video_mode_table[ps3av.ps3av_mode].vid;
+
+	/* audio mute */
+	ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
+
+	/* audio inactive */
+	res = ps3av_cmd_audio_active(0, ps3av.audio_port);
+	if (res < 0)
+		dev_dbg(&ps3av_dev.core,
+			"ps3av_cmd_audio_active OFF failed\n");
+
+	/* audio_pkt */
+	for (i = 0; i < num_of_audio; i++) {
+		ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs,
+					 word_bits, format, source);
+		if (i < ps3av.av_hw_conf.num_of_hdmi) {
+			/* hdmi only */
+			len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len],
+							    ps3av.av_port[i],
+							    &audio_mode, vid);
+		}
+		/* audio_mode pkt should be sent separately */
+		res = ps3av_cmd_audio_mode(&audio_mode);
+		if (res < 0)
+			dev_dbg(&ps3av_dev.core,
+				"ps3av_cmd_audio_mode failed, port:%x\n", i);
+	}
+
+	/* send command using avb pkt */
+	len += offsetof(struct ps3av_pkt_avb_param, buf);
+	res = ps3av_cmd_avb_param(&avb_param, len);
+	if (res < 0)
+		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+
+	/* audio mute */
+	ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
+
+	/* audio active */
+	res = ps3av_cmd_audio_active(1, ps3av.audio_port);
+	if (res < 0)
+		dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n");
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_set_audio_mode);
+
+static int ps3av_set_videomode(void)
+{
+	/* av video mute */
+	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
+
+	/* wake up ps3avd to do the actual video mode setting */
+	up(&ps3av.ping);
+
+	return 0;
+}
+
+static void ps3av_set_videomode_cont(u32 id, u32 old_id)
+{
+	struct ps3av_pkt_avb_param avb_param;
+	int i;
+	u32 len = 0, av_video_cs;
+	const struct avset_video_mode *video_mode;
+	int res;
+
+	video_mode = &video_mode_table[id & PS3AV_MODE_MASK];
+
+	avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO;	/* num of head */
+	avb_param.num_of_audio_pkt = 0;
+	avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi +
+					ps3av.av_hw_conf.num_of_avmulti;
+	avb_param.num_of_av_audio_pkt = 0;
+
+	/* video signal off */
+	ps3av_set_video_disable_sig();
+
+	/* Retail PS3 product doesn't support this */
+	if (id & PS3AV_MODE_HDCP_OFF) {
+		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
+		if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+			dev_dbg(&ps3av_dev.core, "Not supported\n");
+		else if (res)
+			dev_dbg(&ps3av_dev.core,
+				"ps3av_cmd_av_hdmi_mode failed\n");
+	} else if (old_id & PS3AV_MODE_HDCP_OFF) {
+		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
+		if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+			dev_dbg(&ps3av_dev.core,
+				"ps3av_cmd_av_hdmi_mode failed\n");
+	}
+
+	/* video_pkt */
+	for (i = 0; i < avb_param.num_of_video_pkt; i++)
+		len += ps3av_cmd_set_video_mode(&avb_param.buf[len],
+						ps3av.head[i], video_mode->vid,
+						video_mode->fmt, id);
+	/* av_video_pkt */
+	for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
+		if (id & PS3AV_MODE_DVI || id & PS3AV_MODE_RGB)
+			av_video_cs = RGB8;
+		else
+			av_video_cs = video_mode->cs;
+#ifndef PS3AV_HDMI_YUV
+		if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
+		    ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
+			av_video_cs = RGB8;	/* use RGB for HDMI */
+#endif
+		len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
+						 ps3av.av_port[i],
+						 video_mode->vid, av_video_cs,
+						 video_mode->aspect, id);
+	}
+	/* send command using avb pkt */
+	len += offsetof(struct ps3av_pkt_avb_param, buf);
+	res = ps3av_cmd_avb_param(&avb_param, len);
+	if (res == PS3AV_STATUS_NO_SYNC_HEAD)
+		printk(KERN_WARNING
+		       "%s: Command failed. Please try your request again. \n",
+		       __FUNCTION__);
+	else if (res)
+		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+
+	msleep(1500);
+	/* av video mute */
+	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF);
+}
+
+static int ps3avd(void *p)
+{
+	struct ps3av *info = p;
+
+	daemonize("ps3avd");
+	while (1) {
+		down(&info->ping);
+		ps3av_set_videomode_cont(info->ps3av_mode,
+					 info->ps3av_mode_old);
+		up(&info->pong);
+	}
+	return 0;
+}
+
+static int ps3av_vid2table_id(int vid)
+{
+	int i;
+
+	for (i = 1; i < ARRAY_SIZE(video_mode_table); i++)
+		if (video_mode_table[i].vid == vid)
+			return i;
+	return -1;
+}
+
+static int ps3av_resbit2vid(u32 res_50, u32 res_60)
+{
+	int vid = -1;
+
+	if (res_50 > res_60) {	/* if res_50 == res_60, res_60 will be used */
+		if (res_50 & PS3AV_RESBIT_1920x1080P)
+			vid = PS3AV_CMD_VIDEO_VID_1080P_50HZ;
+		else if (res_50 & PS3AV_RESBIT_1920x1080I)
+			vid = PS3AV_CMD_VIDEO_VID_1080I_50HZ;
+		else if (res_50 & PS3AV_RESBIT_1280x720P)
+			vid = PS3AV_CMD_VIDEO_VID_720P_50HZ;
+		else if (res_50 & PS3AV_RESBIT_720x576P)
+			vid = PS3AV_CMD_VIDEO_VID_576P;
+		else
+			vid = -1;
+	} else {
+		if (res_60 & PS3AV_RESBIT_1920x1080P)
+			vid = PS3AV_CMD_VIDEO_VID_1080P_60HZ;
+		else if (res_60 & PS3AV_RESBIT_1920x1080I)
+			vid = PS3AV_CMD_VIDEO_VID_1080I_60HZ;
+		else if (res_60 & PS3AV_RESBIT_1280x720P)
+			vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+		else if (res_60 & PS3AV_RESBIT_720x480P)
+			vid = PS3AV_CMD_VIDEO_VID_480P;
+		else
+			vid = -1;
+	}
+	return vid;
+}
+
+static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info)
+{
+	u32 res_50, res_60;
+	int vid = -1;
+
+	if (info->monitor_type != PS3AV_MONITOR_TYPE_HDMI)
+		return -1;
+
+	/* check native resolution */
+	res_50 = info->res_50.native & PS3AV_RES_MASK_50;
+	res_60 = info->res_60.native & PS3AV_RES_MASK_60;
+	if (res_50 || res_60) {
+		vid = ps3av_resbit2vid(res_50, res_60);
+		return vid;
+	}
+
+	/* check resolution */
+	res_50 = info->res_50.res_bits & PS3AV_RES_MASK_50;
+	res_60 = info->res_60.res_bits & PS3AV_RES_MASK_60;
+	if (res_50 || res_60) {
+		vid = ps3av_resbit2vid(res_50, res_60);
+		return vid;
+	}
+
+	if (ps3av.region & PS3AV_REGION_60)
+		vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+	else
+		vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+	return vid;
+}
+
+static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf,
+				int boot)
+{
+	int i, res, vid = -1, dvi = 0, rgb = 0;
+	struct ps3av_pkt_av_get_monitor_info monitor_info;
+	struct ps3av_info_monitor *info;
+
+	/* get vid for hdmi */
+	for (i = 0; i < av_hw_conf->num_of_hdmi; i++) {
+		res = ps3av_cmd_video_get_monitor_info(&monitor_info,
+						       PS3AV_CMD_AVPORT_HDMI_0 +
+						       i);
+		if (res < 0)
+			return -1;
+
+		ps3av_cmd_av_monitor_info_dump(&monitor_info);
+		info = &monitor_info.info;
+		/* check DVI */
+		if (info->monitor_type == PS3AV_MONITOR_TYPE_DVI) {
+			dvi = PS3AV_MODE_DVI;
+			break;
+		}
+		/* check HDMI */
+		vid = ps3av_hdmi_get_vid(info);
+		if (vid != -1) {
+			/* got valid vid */
+			break;
+		}
+	}
+
+	if (dvi) {
+		/* DVI mode */
+		vid = PS3AV_DEFAULT_DVI_VID;
+	} else if (vid == -1) {
+		/* no HDMI interface or HDMI is off */
+		if (ps3av.region & PS3AV_REGION_60)
+			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
+		else
+			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
+		if (ps3av.region & PS3AV_REGION_RGB)
+			rgb = PS3AV_MODE_RGB;
+	} else if (boot) {
+		/* HDMI: using DEFAULT HDMI_VID while booting up */
+		info = &monitor_info.info;
+		if (ps3av.region & PS3AV_REGION_60) {
+			if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			else {
+				/* default */
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			}
+		} else {
+			if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			else if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			else {
+				/* default */
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			}
+		}
+	}
+
+	return (ps3av_vid2table_id(vid) | dvi | rgb);
+}
+
+static int ps3av_get_hw_conf(struct ps3av *ps3av)
+{
+	int i, j, k, res;
+
+	/* get av_hw_conf */
+	res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf);
+	if (res < 0)
+		return -1;
+
+	ps3av_cmd_av_hw_conf_dump(&ps3av->av_hw_conf);
+
+	for (i = 0; i < PS3AV_HEAD_MAX; i++)
+		ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i;
+	for (i = 0; i < PS3AV_OPT_PORT_MAX; i++)
+		ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i;
+	for (i = 0; i < ps3av->av_hw_conf.num_of_hdmi; i++)
+		ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i;
+	for (j = 0; j < ps3av->av_hw_conf.num_of_avmulti; j++)
+		ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j;
+	for (k = 0; k < ps3av->av_hw_conf.num_of_spdif; k++)
+		ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k;
+
+	/* set all audio port */
+	ps3av->audio_port = PS3AV_CMD_AUDIO_PORT_HDMI_0
+	    | PS3AV_CMD_AUDIO_PORT_HDMI_1
+	    | PS3AV_CMD_AUDIO_PORT_AVMULTI_0
+	    | PS3AV_CMD_AUDIO_PORT_SPDIF_0 | PS3AV_CMD_AUDIO_PORT_SPDIF_1;
+
+	return 0;
+}
+
+/* set mode using id */
+int ps3av_set_video_mode(u32 id, int boot)
+{
+	int size;
+	u32 option;
+
+	size = ARRAY_SIZE(video_mode_table);
+	if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
+		dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __FUNCTION__,
+			id);
+		return -EINVAL;
+	}
+
+	/* auto mode */
+	option = id & ~PS3AV_MODE_MASK;
+	if ((id & PS3AV_MODE_MASK) == 0) {
+		id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+		if (id < 1) {
+			printk(KERN_ERR "%s: invalid id :%d\n", __FUNCTION__,
+			       id);
+			return -EINVAL;
+		}
+		id |= option;
+	}
+
+	/* set videomode */
+	down(&ps3av.pong);
+	ps3av.ps3av_mode_old = ps3av.ps3av_mode;
+	ps3av.ps3av_mode = id;
+	if (ps3av_set_videomode())
+		ps3av.ps3av_mode = ps3av.ps3av_mode_old;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
+
+int ps3av_set_mode(u32 id, int boot)
+{
+	int res;
+
+	res = ps3av_set_video_mode(id, boot);
+	if (res)
+		return res;
+
+	res = ps3av_set_audio_mode(PS3AV_CMD_AUDIO_NUM_OF_CH_2,
+				   PS3AV_CMD_AUDIO_FS_48K,
+				   PS3AV_CMD_AUDIO_WORD_BITS_16,
+				   PS3AV_CMD_AUDIO_FORMAT_PCM,
+				   PS3AV_CMD_AUDIO_SOURCE_SERIAL);
+	if (res)
+		return res;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_set_mode);
+
+int ps3av_get_mode(void)
+{
+	return ps3av.ps3av_mode;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_get_mode);
+
+int ps3av_get_scanmode(int id)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -EINVAL;
+	}
+	return video_mode_table[id].interlace;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_get_scanmode);
+
+int ps3av_get_refresh_rate(int id)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -EINVAL;
+	}
+	return video_mode_table[id].freq;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_get_refresh_rate);
+
+/* get resolution by video_mode */
+int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -EINVAL;
+	}
+	*xres = video_mode_table[id].x;
+	*yres = video_mode_table[id].y;
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_video_mode2res);
+
+/* mute */
+int ps3av_video_mute(int mute)
+{
+	return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON
+					    : PS3AV_CMD_MUTE_OFF);
+}
+
+EXPORT_SYMBOL_GPL(ps3av_video_mute);
+
+int ps3av_audio_mute(int mute)
+{
+	return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
+					 : PS3AV_CMD_MUTE_OFF);
+}
+
+EXPORT_SYMBOL_GPL(ps3av_audio_mute);
+
+int ps3av_dev_open(void)
+{
+	int status = 0;
+
+	mutex_lock(&ps3av.mutex);
+	if (!ps3av.open_count++) {
+		status = lv1_gpu_open(0);
+		if (status) {
+			printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
+			       __FUNCTION__, status);
+			ps3av.open_count--;
+		}
+	}
+	mutex_unlock(&ps3av.mutex);
+
+	return status;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_dev_open);
+
+int ps3av_dev_close(void)
+{
+	int status = 0;
+
+	mutex_lock(&ps3av.mutex);
+	if (ps3av.open_count <= 0) {
+		printk(KERN_ERR "%s: GPU already closed\n", __FUNCTION__);
+		status = -1;
+	} else if (!--ps3av.open_count) {
+		status = lv1_gpu_close();
+		if (status)
+			printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
+			       __FUNCTION__, status);
+	}
+	mutex_unlock(&ps3av.mutex);
+
+	return status;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_dev_close);
+
+static int ps3av_probe(struct ps3_vuart_port_device *dev)
+{
+	int res;
+	u32 id;
+
+	dev_dbg(&ps3av_dev.core, "init ...\n");
+	dev_dbg(&ps3av_dev.core, "  timeout=%d\n", timeout);
+
+	memset(&ps3av, 0, sizeof(ps3av));
+
+	init_MUTEX(&ps3av.sem);
+	init_MUTEX_LOCKED(&ps3av.ping);
+	init_MUTEX(&ps3av.pong);
+	mutex_init(&ps3av.mutex);
+	ps3av.ps3av_mode = 0;
+	ps3av.dev = dev;
+	kernel_thread(ps3avd, &ps3av, CLONE_KERNEL);
+
+	ps3av.available = 1;
+	switch (ps3_os_area_get_av_multi_out()) {
+	case PS3_PARAM_AV_MULTI_OUT_NTSC:
+		ps3av.region = PS3AV_REGION_60;
+		break;
+	case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
+	case PS3_PARAM_AV_MULTI_OUT_SECAM:
+		ps3av.region = PS3AV_REGION_50;
+		break;
+	case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
+		ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
+		break;
+	default:
+		ps3av.region = PS3AV_REGION_60;
+		break;
+	}
+
+	/* init avsetting modules */
+	res = ps3av_cmd_init();
+	if (res < 0)
+		printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __FUNCTION__,
+		       res);
+
+	ps3av_get_hw_conf(&ps3av);
+	id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1);
+	mutex_lock(&ps3av.mutex);
+	ps3av.ps3av_mode = id;
+	mutex_unlock(&ps3av.mutex);
+
+	dev_dbg(&ps3av_dev.core, "init...done\n");
+
+	return 0;
+}
+
+static int ps3av_remove(struct ps3_vuart_port_device *dev)
+{
+	if (ps3av.available) {
+		ps3av_cmd_fin();
+		ps3av.available = 0;
+	}
+
+	return 0;
+}
+
+static void ps3av_shutdown(struct ps3_vuart_port_device *dev)
+{
+	ps3av_remove(dev);
+}
+
+static struct ps3_vuart_port_driver ps3av_driver = {
+	.match_id = PS3_MATCH_ID_AV_SETTINGS,
+	.core = {
+		.name = "ps3_av",
+	},
+	.probe = ps3av_probe,
+	.remove = ps3av_remove,
+	.shutdown = ps3av_shutdown,
+};
+
+static int ps3av_module_init(void)
+{
+	int error = ps3_vuart_port_driver_register(&ps3av_driver);
+	if (error) {
+		printk(KERN_ERR
+		       "%s: ps3_vuart_port_driver_register failed %d\n",
+		       __FUNCTION__, error);
+		return error;
+	}
+
+	error = ps3_vuart_port_device_register(&ps3av_dev);
+	if (error)
+		printk(KERN_ERR
+		       "%s: ps3_vuart_port_device_register failed %d\n",
+		       __FUNCTION__, error);
+
+	return error;
+}
+
+static void __exit ps3av_module_exit(void)
+{
+	device_unregister(&ps3av_dev.core);
+	ps3_vuart_port_driver_unregister(&ps3av_driver);
+}
+
+subsys_initcall(ps3av_module_init);
+module_exit(ps3av_module_exit);
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
new file mode 100644
index 0000000..21c97c8
--- /dev/null
+++ b/drivers/ps3/ps3av_cmd.c
@@ -0,0 +1,1020 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ *
+ * AV backend support for PS3
+ *
+ * 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.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/ps3av.h>
+#include <asm/ps3fb.h>
+#include <asm/ps3.h>
+
+#include "vuart.h"
+
+static const struct video_fmt {
+	u32 format;
+	u32 order;
+} ps3av_video_fmt_table[] = {
+	{ PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_RGB },
+	{ PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_BGR },
+};
+
+static const struct {
+	int cs;
+	u32 av;
+	u32 bl;
+} ps3av_cs_video2av_table[] = {
+	{
+		.cs = PS3AV_CMD_VIDEO_CS_RGB_8,
+		.av = PS3AV_CMD_AV_CS_RGB_8,
+		.bl = PS3AV_CMD_AV_CS_8
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_RGB_10,
+		.av = PS3AV_CMD_AV_CS_RGB_8,
+		.bl = PS3AV_CMD_AV_CS_8
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_RGB_12,
+		.av = PS3AV_CMD_AV_CS_RGB_8,
+		.bl = PS3AV_CMD_AV_CS_8
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV444_8,
+		.av = PS3AV_CMD_AV_CS_YUV444_8,
+		.bl = PS3AV_CMD_AV_CS_8
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV444_10,
+		.av = PS3AV_CMD_AV_CS_YUV444_8,
+		.bl = PS3AV_CMD_AV_CS_10
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV444_12,
+		.av = PS3AV_CMD_AV_CS_YUV444_8,
+		.bl = PS3AV_CMD_AV_CS_10
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV422_8,
+		.av = PS3AV_CMD_AV_CS_YUV422_8,
+		.bl = PS3AV_CMD_AV_CS_10
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV422_10,
+		.av = PS3AV_CMD_AV_CS_YUV422_8,
+		.bl = PS3AV_CMD_AV_CS_10
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV422_12,
+		.av = PS3AV_CMD_AV_CS_YUV422_8,
+		.bl = PS3AV_CMD_AV_CS_12
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_XVYCC_8,
+		.av = PS3AV_CMD_AV_CS_XVYCC_8,
+		.bl = PS3AV_CMD_AV_CS_12
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_XVYCC_10,
+		.av = PS3AV_CMD_AV_CS_XVYCC_8,
+		.bl = PS3AV_CMD_AV_CS_12
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_XVYCC_12,
+		.av = PS3AV_CMD_AV_CS_XVYCC_8,
+		.bl = PS3AV_CMD_AV_CS_12
+	}
+};
+
+static u32 ps3av_cs_video2av(int cs)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ps3av_cs_video2av_table); i++)
+		if (ps3av_cs_video2av_table[i].cs == cs)
+			return ps3av_cs_video2av_table[i].av;
+
+	return PS3AV_CMD_AV_CS_RGB_8;
+}
+
+static u32 ps3av_cs_video2av_bitlen(int cs)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ps3av_cs_video2av_table); i++)
+		if (ps3av_cs_video2av_table[i].cs == cs)
+			return ps3av_cs_video2av_table[i].bl;
+
+	return PS3AV_CMD_AV_CS_8;
+}
+
+static const struct {
+	int vid;
+	u32 av;
+} ps3av_vid_video2av_table[] = {
+	{ PS3AV_CMD_VIDEO_VID_480I, PS3AV_CMD_AV_VID_480I },
+	{ PS3AV_CMD_VIDEO_VID_480P, PS3AV_CMD_AV_VID_480P },
+	{ PS3AV_CMD_VIDEO_VID_576I, PS3AV_CMD_AV_VID_576I },
+	{ PS3AV_CMD_VIDEO_VID_576P, PS3AV_CMD_AV_VID_576P },
+	{ PS3AV_CMD_VIDEO_VID_1080I_60HZ, PS3AV_CMD_AV_VID_1080I_60HZ },
+	{ PS3AV_CMD_VIDEO_VID_720P_60HZ, PS3AV_CMD_AV_VID_720P_60HZ },
+	{ PS3AV_CMD_VIDEO_VID_1080P_60HZ, PS3AV_CMD_AV_VID_1080P_60HZ },
+	{ PS3AV_CMD_VIDEO_VID_1080I_50HZ, PS3AV_CMD_AV_VID_1080I_50HZ },
+	{ PS3AV_CMD_VIDEO_VID_720P_50HZ, PS3AV_CMD_AV_VID_720P_50HZ },
+	{ PS3AV_CMD_VIDEO_VID_1080P_50HZ, PS3AV_CMD_AV_VID_1080P_50HZ },
+	{ PS3AV_CMD_VIDEO_VID_WXGA, PS3AV_CMD_AV_VID_WXGA },
+	{ PS3AV_CMD_VIDEO_VID_SXGA, PS3AV_CMD_AV_VID_SXGA },
+	{ PS3AV_CMD_VIDEO_VID_WUXGA, PS3AV_CMD_AV_VID_WUXGA }
+};
+
+static u32 ps3av_vid_video2av(int vid)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ps3av_vid_video2av_table); i++)
+		if (ps3av_vid_video2av_table[i].vid == vid)
+			return ps3av_vid_video2av_table[i].av;
+
+	return PS3AV_CMD_AV_VID_480P;
+}
+
+int ps3av_cmd_init(void)
+{
+	int res;
+	struct ps3av_pkt_av_init av_init;
+	struct ps3av_pkt_video_init video_init;
+	struct ps3av_pkt_audio_init audio_init;
+
+	/* video init */
+	memset(&video_init, 0, sizeof(video_init));
+
+	res = ps3av_do_pkt(PS3AV_CID_VIDEO_INIT, sizeof(video_init.send_hdr),
+			   sizeof(video_init), &video_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&video_init);
+	if (res) {
+		printk(KERN_ERR "PS3AV_CID_VIDEO_INIT: failed %x\n", res);
+		return res;
+	}
+
+	/* audio init */
+	memset(&audio_init, 0, sizeof(audio_init));
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_INIT, sizeof(audio_init.send_hdr),
+			   sizeof(audio_init), &audio_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_init);
+	if (res) {
+		printk(KERN_ERR "PS3AV_CID_AUDIO_INIT: failed %x\n", res);
+		return res;
+	}
+
+	/* av init */
+	memset(&av_init, 0, sizeof(av_init));
+	av_init.event_bit = 0;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_INIT, sizeof(av_init), sizeof(av_init),
+			   &av_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_init);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_INIT: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_fin(void)
+{
+	int res;
+	struct ps3av_pkt_av_fin av_fin;
+
+	memset(&av_fin, 0, sizeof(av_fin));
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_FIN, sizeof(av_fin.send_hdr),
+			   sizeof(av_fin), &av_fin.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_fin);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_FIN: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_video_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, send_len, res;
+	struct ps3av_pkt_av_video_mute av_video_mute;
+
+	if (num_of_port > PS3AV_MUTE_PORT_MAX)
+		return -EINVAL;
+
+	memset(&av_video_mute, 0, sizeof(av_video_mute));
+	for (i = 0; i < num_of_port; i++) {
+		av_video_mute.mute[i].avport = port[i];
+		av_video_mute.mute[i].mute = mute;
+	}
+
+	send_len = sizeof(av_video_mute.send_hdr) +
+	    sizeof(struct ps3av_av_mute) * num_of_port;
+	res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_MUTE, send_len,
+			   sizeof(av_video_mute), &av_video_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_video_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_VIDEO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_video_disable_sig(u32 port)
+{
+	int res;
+	struct ps3av_pkt_av_video_disable_sig av_video_sig;
+
+	memset(&av_video_sig, 0, sizeof(av_video_sig));
+	av_video_sig.avport = port;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_DISABLE_SIG,
+			   sizeof(av_video_sig), sizeof(av_video_sig),
+			   &av_video_sig.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_video_sig);
+	if (res)
+		printk(KERN_ERR
+		       "PS3AV_CID_AV_VIDEO_DISABLE_SIG: failed %x port:%x\n",
+		       res, port);
+
+	return res;
+}
+
+int ps3av_cmd_av_tv_mute(u32 avport, u32 mute)
+{
+	int res;
+	struct ps3av_pkt_av_tv_mute tv_mute;
+
+	memset(&tv_mute, 0, sizeof(tv_mute));
+	tv_mute.avport = avport;
+	tv_mute.mute = mute;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_TV_MUTE, sizeof(tv_mute),
+			   sizeof(tv_mute), &tv_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&tv_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_TV_MUTE: failed %x port:%x\n",
+		       res, avport);
+
+	return res;
+}
+
+int ps3av_cmd_enable_event(void)
+{
+	int res;
+	struct ps3av_pkt_av_event av_event;
+
+	memset(&av_event, 0, sizeof(av_event));
+	av_event.event_bit = PS3AV_CMD_EVENT_BIT_UNPLUGGED |
+	    PS3AV_CMD_EVENT_BIT_PLUGGED | PS3AV_CMD_EVENT_BIT_HDCP_DONE;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_ENABLE_EVENT, sizeof(av_event),
+			   sizeof(av_event), &av_event.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_event);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_ENABLE_EVENT: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_hdmi_mode(u8 mode)
+{
+	int res;
+	struct ps3av_pkt_av_hdmi_mode hdmi_mode;
+
+	memset(&hdmi_mode, 0, sizeof(hdmi_mode));
+	hdmi_mode.mode = mode;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_HDMI_MODE, sizeof(hdmi_mode),
+			   sizeof(hdmi_mode), &hdmi_mode.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&hdmi_mode);
+	if (res && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+		printk(KERN_ERR "PS3AV_CID_AV_HDMI_MODE: failed %x\n", res);
+
+	return res;
+}
+
+u32 ps3av_cmd_set_av_video_cs(void *p, u32 avport, int video_vid, int cs_out,
+			      int aspect, u32 id)
+{
+	struct ps3av_pkt_av_video_cs *av_video_cs;
+
+	av_video_cs = (struct ps3av_pkt_av_video_cs *)p;
+	if (video_vid == -1)
+		video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+	if (cs_out == -1)
+		cs_out = PS3AV_CMD_VIDEO_CS_YUV444_8;
+	if (aspect == -1)
+		aspect = 0;
+
+	memset(av_video_cs, 0, sizeof(*av_video_cs));
+	ps3av_set_hdr(PS3AV_CID_AV_VIDEO_CS, sizeof(*av_video_cs),
+		      &av_video_cs->send_hdr);
+	av_video_cs->avport = avport;
+	/* should be same as video_mode.resolution */
+	av_video_cs->av_vid = ps3av_vid_video2av(video_vid);
+	av_video_cs->av_cs_out = ps3av_cs_video2av(cs_out);
+	/* should be same as video_mode.video_cs_out */
+	av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8);
+	av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out);
+	av_video_cs->aspect = aspect;
+	if (id & PS3AV_MODE_DITHER) {
+		av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON
+		    | PS3AV_CMD_AV_DITHER_8BIT;
+	} else {
+		/* default off */
+		av_video_cs->dither = PS3AV_CMD_AV_DITHER_OFF;
+	}
+
+	return sizeof(*av_video_cs);
+}
+
+u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt,
+			     u32 id)
+{
+	struct ps3av_pkt_video_mode *video_mode;
+	u32 x, y;
+
+	video_mode = (struct ps3av_pkt_video_mode *)p;
+	if (video_vid == -1)
+		video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+	if (video_fmt == -1)
+		video_fmt = PS3AV_CMD_VIDEO_FMT_X8R8G8B8;
+
+	if (ps3av_video_mode2res(id, &x, &y))
+		return 0;
+
+	/* video mode */
+	memset(video_mode, 0, sizeof(*video_mode));
+	ps3av_set_hdr(PS3AV_CID_VIDEO_MODE, sizeof(*video_mode),
+		      &video_mode->send_hdr);
+	video_mode->video_head = head;
+	if (video_vid == PS3AV_CMD_VIDEO_VID_480I
+	    && head == PS3AV_CMD_VIDEO_HEAD_B)
+		video_mode->video_vid = PS3AV_CMD_VIDEO_VID_480I_A;
+	else
+		video_mode->video_vid = video_vid;
+	video_mode->width = (u16) x;
+	video_mode->height = (u16) y;
+	video_mode->pitch = video_mode->width * 4;	/* line_length */
+	video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT;
+	video_mode->video_format = ps3av_video_fmt_table[video_fmt].format;
+	video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
+
+	pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
+		__FUNCTION__, video_vid, video_mode->width, video_mode->height,
+		video_mode->pitch, video_mode->video_out_format,
+		video_mode->video_format, video_mode->video_order);
+	return sizeof(*video_mode);
+}
+
+int ps3av_cmd_video_format_black(u32 head, u32 video_fmt, u32 mute)
+{
+	int res;
+	struct ps3av_pkt_video_format video_format;
+
+	memset(&video_format, 0, sizeof(video_format));
+	video_format.video_head = head;
+	if (mute != PS3AV_CMD_MUTE_OFF)
+		video_format.video_format = PS3AV_CMD_VIDEO_FORMAT_BLACK;
+	else
+		video_format.video_format =
+		    ps3av_video_fmt_table[video_fmt].format;
+	video_format.video_order = ps3av_video_fmt_table[video_fmt].order;
+
+	res = ps3av_do_pkt(PS3AV_CID_VIDEO_FORMAT, sizeof(video_format),
+			   sizeof(video_format), &video_format.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&video_format);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_VIDEO_FORMAT: failed %x\n", res);
+
+	return res;
+}
+
+
+int ps3av_cmd_av_audio_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, res;
+	struct ps3av_pkt_av_audio_mute av_audio_mute;
+
+	if (num_of_port > PS3AV_MUTE_PORT_MAX)
+		return -EINVAL;
+
+	/* audio mute */
+	memset(&av_audio_mute, 0, sizeof(av_audio_mute));
+	for (i = 0; i < num_of_port; i++) {
+		av_audio_mute.mute[i].avport = port[i];
+		av_audio_mute.mute[i].mute = mute;
+	}
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_AUDIO_MUTE,
+			   sizeof(av_audio_mute.send_hdr) +
+			   sizeof(struct ps3av_av_mute) * num_of_port,
+			   sizeof(av_audio_mute), &av_audio_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_audio_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_AUDIO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+static const struct {
+	u32 fs;
+	u8 mclk;
+} ps3av_cnv_mclk_table[] = {
+	{ PS3AV_CMD_AUDIO_FS_44K, PS3AV_CMD_AV_MCLK_512 },
+	{ PS3AV_CMD_AUDIO_FS_48K, PS3AV_CMD_AV_MCLK_512 },
+	{ PS3AV_CMD_AUDIO_FS_88K, PS3AV_CMD_AV_MCLK_256 },
+	{ PS3AV_CMD_AUDIO_FS_96K, PS3AV_CMD_AV_MCLK_256 },
+	{ PS3AV_CMD_AUDIO_FS_176K, PS3AV_CMD_AV_MCLK_128 },
+	{ PS3AV_CMD_AUDIO_FS_192K, PS3AV_CMD_AV_MCLK_128 }
+};
+
+static u8 ps3av_cnv_mclk(u32 fs)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ps3av_cnv_mclk_table); i++)
+		if (ps3av_cnv_mclk_table[i].fs == fs)
+			return ps3av_cnv_mclk_table[i].mclk;
+
+	printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+	return 0;
+}
+
+#define BASE	PS3AV_CMD_AUDIO_FS_44K
+
+static const u32 ps3av_ns_table[][5] = {
+					/*   D1,    D2,    D3,    D4,    D5 */
+	[PS3AV_CMD_AUDIO_FS_44K-BASE]	{  6272,  6272, 17836, 17836,  8918 },
+	[PS3AV_CMD_AUDIO_FS_48K-BASE]	{  6144,  6144, 11648, 11648,  5824 },
+	[PS3AV_CMD_AUDIO_FS_88K-BASE]	{ 12544, 12544, 35672, 35672, 17836 },
+	[PS3AV_CMD_AUDIO_FS_96K-BASE]	{ 12288, 12288, 23296, 23296, 11648 },
+	[PS3AV_CMD_AUDIO_FS_176K-BASE]	{ 25088, 25088, 71344, 71344, 35672 },
+	[PS3AV_CMD_AUDIO_FS_192K-BASE]	{ 24576, 24576, 46592, 46592, 23296 }
+};
+
+static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid)
+{
+	u32 av_vid, ns_val;
+	u8 *p = ns;
+	int d;
+
+	d = ns_val = 0;
+	av_vid = ps3av_vid_video2av(video_vid);
+	switch (av_vid) {
+	case PS3AV_CMD_AV_VID_480I:
+	case PS3AV_CMD_AV_VID_576I:
+		d = 0;
+		break;
+	case PS3AV_CMD_AV_VID_480P:
+	case PS3AV_CMD_AV_VID_576P:
+		d = 1;
+		break;
+	case PS3AV_CMD_AV_VID_1080I_60HZ:
+	case PS3AV_CMD_AV_VID_1080I_50HZ:
+		d = 2;
+		break;
+	case PS3AV_CMD_AV_VID_720P_60HZ:
+	case PS3AV_CMD_AV_VID_720P_50HZ:
+		d = 3;
+		break;
+	case PS3AV_CMD_AV_VID_1080P_60HZ:
+	case PS3AV_CMD_AV_VID_1080P_50HZ:
+	case PS3AV_CMD_AV_VID_WXGA:
+	case PS3AV_CMD_AV_VID_SXGA:
+	case PS3AV_CMD_AV_VID_WUXGA:
+		d = 4;
+		break;
+	default:
+		printk(KERN_ERR "%s failed, vid:%x\n", __FUNCTION__,
+		       video_vid);
+		break;
+	}
+
+	if (fs < PS3AV_CMD_AUDIO_FS_44K || fs > PS3AV_CMD_AUDIO_FS_192K)
+		printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+	else
+		ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d];
+
+	*p++ = ns_val & 0x000000FF;
+	*p++ = (ns_val & 0x0000FF00) >> 8;
+	*p = (ns_val & 0x00FF0000) >> 16;
+}
+
+#undef BASE
+
+static u8 ps3av_cnv_enable(u32 source, u8 *enable)
+{
+	u8 *p, ret = 0;
+
+	if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) {
+		ret = 0x03;
+	} else if (source == PS3AV_CMD_AUDIO_SOURCE_SERIAL) {
+		p = enable;
+		ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) |
+		      0x01;
+	} else
+		printk(KERN_ERR "%s failed, source:%x\n", __FUNCTION__,
+		       source);
+	return ret;
+}
+
+static u8 ps3av_cnv_fifomap(u8 *map)
+{
+	u8 *p, ret = 0;
+
+	p = map;
+	ret = p[0] + (p[1] << 2) + (p[2] << 4) + (p[3] << 6);
+	return ret;
+}
+
+static u8 ps3av_cnv_inputlen(u32 word_bits)
+{
+	u8 ret = 0;
+
+	switch (word_bits) {
+	case PS3AV_CMD_AUDIO_WORD_BITS_16:
+		ret = PS3AV_CMD_AV_INPUTLEN_16;
+		break;
+	case PS3AV_CMD_AUDIO_WORD_BITS_20:
+		ret = PS3AV_CMD_AV_INPUTLEN_20;
+		break;
+	case PS3AV_CMD_AUDIO_WORD_BITS_24:
+		ret = PS3AV_CMD_AV_INPUTLEN_24;
+		break;
+	default:
+		printk(KERN_ERR "%s failed, word_bits:%x\n", __FUNCTION__,
+		       word_bits);
+		break;
+	}
+	return ret;
+}
+
+static u8 ps3av_cnv_layout(u32 num_of_ch)
+{
+	if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) {
+		printk(KERN_ERR "%s failed, num_of_ch:%x\n", __FUNCTION__,
+		       num_of_ch);
+		return 0;
+	}
+
+	return num_of_ch == PS3AV_CMD_AUDIO_NUM_OF_CH_2 ? 0x0 : 0x1;
+}
+
+static void ps3av_cnv_info(struct ps3av_audio_info_frame *info,
+			   const struct ps3av_pkt_audio_mode *mode)
+{
+	info->pb1.cc = mode->audio_num_of_ch + 1;	/* CH2:0x01 --- CH8:0x07 */
+	info->pb1.ct = 0;
+	info->pb2.sf = 0;
+	info->pb2.ss = 0;
+
+	info->pb3 = 0;		/* check mode->audio_format ?? */
+	info->pb4 = mode->audio_layout;
+	info->pb5.dm = mode->audio_downmix;
+	info->pb5.lsv = mode->audio_downmix_level;
+}
+
+static void ps3av_cnv_chstat(u8 *chstat, u8 *cs_info)
+{
+	memcpy(chstat, cs_info, 5);
+}
+
+u32 ps3av_cmd_set_av_audio_param(void *p, u32 port,
+				 const struct ps3av_pkt_audio_mode *audio_mode,
+				 u32 video_vid)
+{
+	struct ps3av_pkt_av_audio_param *param;
+
+	param = (struct ps3av_pkt_av_audio_param *)p;
+
+	memset(param, 0, sizeof(*param));
+	ps3av_set_hdr(PS3AV_CID_AV_AUDIO_PARAM, sizeof(*param),
+		      &param->send_hdr);
+
+	param->avport = port;
+	param->mclk = ps3av_cnv_mclk(audio_mode->audio_fs) | 0x80;
+	ps3av_cnv_ns(param->ns, audio_mode->audio_fs, video_vid);
+	param->enable = ps3av_cnv_enable(audio_mode->audio_source,
+					 audio_mode->audio_enable);
+	param->swaplr = 0x09;
+	param->fifomap = ps3av_cnv_fifomap(audio_mode->audio_map);
+	param->inputctrl = 0x49;
+	param->inputlen = ps3av_cnv_inputlen(audio_mode->audio_word_bits);
+	param->layout = ps3av_cnv_layout(audio_mode->audio_num_of_ch);
+	ps3av_cnv_info(&param->info, audio_mode);
+	ps3av_cnv_chstat(param->chstat, audio_mode->audio_cs_info);
+
+	return sizeof(*param);
+}
+
+/* default cs val */
+static const u8 ps3av_mode_cs_info[] = {
+	0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
+};
+
+#define CS_44	0x00
+#define CS_48	0x02
+#define CS_88	0x08
+#define CS_96	0x0a
+#define CS_176	0x0c
+#define CS_192	0x0e
+#define CS_MASK	0x0f
+#define CS_BIT	0x40
+
+void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
+			      u32 ch, u32 fs, u32 word_bits, u32 format,
+			      u32 source)
+{
+	int spdif_through, spdif_bitstream;
+	int i;
+
+	if (!(ch | fs | format | word_bits | source)) {
+		ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2;
+		fs = PS3AV_CMD_AUDIO_FS_48K;
+		word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
+		format = PS3AV_CMD_AUDIO_FORMAT_PCM;
+		source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
+	}
+	spdif_through = spdif_bitstream = 0;	/* XXX not supported */
+
+	/* audio mode */
+	memset(audio, 0, sizeof(*audio));
+	ps3av_set_hdr(PS3AV_CID_AUDIO_MODE, sizeof(*audio), &audio->send_hdr);
+
+	audio->avport = (u8) avport;
+	audio->mask = 0x0FFF;	/* XXX set all */
+	audio->audio_num_of_ch = ch;
+	audio->audio_fs = fs;
+	audio->audio_word_bits = word_bits;
+	audio->audio_format = format;
+	audio->audio_source = source;
+
+	switch (ch) {
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_8:
+		audio->audio_enable[3] = 1;
+		/* fall through */
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_6:
+		audio->audio_enable[2] = 1;
+		audio->audio_enable[1] = 1;
+		/* fall through */
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_2:
+	default:
+		audio->audio_enable[0] = 1;
+	}
+
+	/* audio swap L/R */
+	for (i = 0; i < 4; i++)
+		audio->audio_swap[i] = PS3AV_CMD_AUDIO_SWAP_0;	/* no swap */
+
+	/* audio serial input mapping */
+	audio->audio_map[0] = PS3AV_CMD_AUDIO_MAP_OUTPUT_0;
+	audio->audio_map[1] = PS3AV_CMD_AUDIO_MAP_OUTPUT_1;
+	audio->audio_map[2] = PS3AV_CMD_AUDIO_MAP_OUTPUT_2;
+	audio->audio_map[3] = PS3AV_CMD_AUDIO_MAP_OUTPUT_3;
+
+	/* audio speaker layout */
+	if (avport == PS3AV_CMD_AVPORT_HDMI_0 ||
+	    avport == PS3AV_CMD_AVPORT_HDMI_1) {
+		switch (ch) {
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_8:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_8CH;
+			break;
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_6:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_6CH;
+			break;
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_2:
+		default:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;
+			break;
+		}
+	} else {
+		audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;
+	}
+
+	/* audio downmix permission */
+	audio->audio_downmix = PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED;
+	/* audio downmix level shift (0:0dB to 15:15dB) */
+	audio->audio_downmix_level = 0;	/* 0dB */
+
+	/* set ch status */
+	for (i = 0; i < 8; i++)
+		audio->audio_cs_info[i] = ps3av_mode_cs_info[i];
+
+	switch (fs) {
+	case PS3AV_CMD_AUDIO_FS_44K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_44;
+		break;
+	case PS3AV_CMD_AUDIO_FS_88K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_88;
+		break;
+	case PS3AV_CMD_AUDIO_FS_96K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_96;
+		break;
+	case PS3AV_CMD_AUDIO_FS_176K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_176;
+		break;
+	case PS3AV_CMD_AUDIO_FS_192K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_192;
+		break;
+	default:
+		break;
+	}
+
+	/* pass through setting */
+	if (spdif_through &&
+	    (avport == PS3AV_CMD_AVPORT_SPDIF_0 ||
+	     avport == PS3AV_CMD_AVPORT_SPDIF_1)) {
+		audio->audio_word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
+		audio->audio_source = PS3AV_CMD_AUDIO_SOURCE_SPDIF;
+		if (spdif_bitstream) {
+			audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;
+			audio->audio_cs_info[0] |= CS_BIT;
+		}
+	}
+}
+
+int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *audio_mode)
+{
+	int res;
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_MODE, sizeof(*audio_mode),
+			   sizeof(*audio_mode), &audio_mode->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(audio_mode);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_MODE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_audio_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, res;
+	struct ps3av_pkt_audio_mute audio_mute;
+
+	if (num_of_port > PS3AV_OPT_PORT_MAX)
+		return -EINVAL;
+
+	/* audio mute */
+	memset(&audio_mute, 0, sizeof(audio_mute));
+	for (i = 0; i < num_of_port; i++) {
+		audio_mute.mute[i].avport = port[i];
+		audio_mute.mute[i].mute = mute;
+	}
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_MUTE,
+			   sizeof(audio_mute.send_hdr) +
+			   sizeof(struct ps3av_audio_mute) * num_of_port,
+			   sizeof(audio_mute), &audio_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_audio_active(int active, u32 port)
+{
+	int res;
+	struct ps3av_pkt_audio_active audio_active;
+	u32 cid;
+
+	/* audio active */
+	memset(&audio_active, 0, sizeof(audio_active));
+	audio_active.audio_port = port;
+	cid = active ? PS3AV_CID_AUDIO_ACTIVE : PS3AV_CID_AUDIO_INACTIVE;
+
+	res = ps3av_do_pkt(cid, sizeof(audio_active), sizeof(audio_active),
+			   &audio_active.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_active);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_ACTIVE:%x failed %x\n", cid,
+		       res);
+
+	return res;
+}
+
+int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
+{
+	int res;
+
+	ps3fb_flip_ctl(0);	/* flip off */
+
+	/* avb packet */
+	res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
+			   &avb->send_hdr);
+	if (res < 0)
+		goto out;
+
+	res = get_status(avb);
+	if (res)
+		pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __FUNCTION__,
+			 res);
+
+      out:
+	ps3fb_flip_ctl(1);	/* flip on */
+	return res;
+}
+
+int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *hw_conf)
+{
+	int res;
+
+	memset(hw_conf, 0, sizeof(*hw_conf));
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_GET_HW_CONF, sizeof(hw_conf->send_hdr),
+			   sizeof(*hw_conf), &hw_conf->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(hw_conf);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_GET_HW_CONF: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *info,
+				     u32 avport)
+{
+	int res;
+
+	memset(info, 0, sizeof(*info));
+	info->avport = avport;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_GET_MONITOR_INFO,
+			   sizeof(info->send_hdr) + sizeof(info->avport) +
+			   sizeof(info->reserved),
+			   sizeof(*info), &info->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(info);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_GET_MONITOR_INFO: failed %x\n",
+		       res);
+
+	return res;
+}
+
+#ifdef PS3AV_DEBUG
+void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf)
+{
+	printk("av_h_conf:num of hdmi:%d\n", hw_conf->num_of_hdmi);
+	printk("av_h_conf:num of avmulti:%d\n", hw_conf->num_of_avmulti);
+	printk("av_h_conf:num of spdif:%d\n", hw_conf->num_of_spdif);
+}
+
+void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info)
+{
+	const struct ps3av_info_monitor *info = &monitor_info->info;
+	const struct ps3av_info_audio *audio = info->audio;
+	int i;
+
+	printk("Monitor Info: size%d\n", monitor_info->send_hdr.size);
+
+	printk("avport:%02x\n", info->avport);
+	printk("monitor_id:");
+	for (i = 0; i < 10; i++)
+		printk("%02x ", info->monitor_id[i]);
+	printk("\nmonitor_type:%02x\n", info->monitor_type);
+	printk("monitor_name:");
+	for (i = 0; i < 16; i++)
+		printk("%c", info->monitor_name[i]);
+
+	/* resolution */
+	printk("\nresolution_60: bits:%08x native:%08x\n",
+	       info->res_60.res_bits, info->res_60.native);
+	printk("resolution_50: bits:%08x native:%08x\n",
+	       info->res_50.res_bits, info->res_50.native);
+	printk("resolution_other: bits:%08x native:%08x\n",
+	       info->res_other.res_bits, info->res_other.native);
+	printk("resolution_vesa: bits:%08x native:%08x\n",
+	       info->res_vesa.res_bits, info->res_vesa.native);
+
+	/* color space */
+	printk("color space    rgb:%02x\n", info->cs.rgb);
+	printk("color space yuv444:%02x\n", info->cs.yuv444);
+	printk("color space yuv422:%02x\n", info->cs.yuv422);
+
+	/* color info */
+	printk("color info   red:X %04x Y %04x\n",
+	       info->color.red_x, info->color.red_y);
+	printk("color info green:X %04x Y %04x\n",
+	       info->color.green_x, info->color.green_y);
+	printk("color info  blue:X %04x Y %04x\n",
+	       info->color.blue_x, info->color.blue_y);
+	printk("color info white:X %04x Y %04x\n",
+	       info->color.white_x, info->color.white_y);
+	printk("color info gamma: %08x\n", info->color.gamma);
+
+	/* other info */
+	printk("supported_AI:%02x\n", info->supported_ai);
+	printk("speaker_info:%02x\n", info->speaker_info);
+	printk("num of audio:%02x\n", info->num_of_audio_block);
+
+	/* audio block */
+	for (i = 0; i < info->num_of_audio_block; i++) {
+		printk("audio[%d] type:%02x max_ch:%02x fs:%02x sbit:%02x\n",
+		       i, audio->type, audio->max_num_of_ch, audio->fs,
+		       audio->sbit);
+		audio++;
+	}
+}
+#endif /* PS3AV_DEBUG */
+
+#define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \
+		| PS3AV_CMD_AV_LAYOUT_44 \
+		| PS3AV_CMD_AV_LAYOUT_48)
+
+#define PS3AV_AV_LAYOUT_1 (PS3AV_AV_LAYOUT_0 \
+		| PS3AV_CMD_AV_LAYOUT_88 \
+		| PS3AV_CMD_AV_LAYOUT_96 \
+		| PS3AV_CMD_AV_LAYOUT_176 \
+		| PS3AV_CMD_AV_LAYOUT_192)
+
+/************************* vuart ***************************/
+
+#define POLLING_INTERVAL  25	/* in msec */
+
+int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
+		      unsigned long size)
+{
+	int error = ps3_vuart_write(dev, buf, size);
+	return error ? error : size;
+}
+
+int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
+		     unsigned long size, int timeout)
+{
+	int error;
+	int loopcnt = 0;
+
+	timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
+	while (loopcnt++ <= timeout) {
+		error = ps3_vuart_read(dev, buf, size);
+		if (!error)
+			return size;
+		if (error != -EAGAIN) {
+			printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
+			       __FUNCTION__, error);
+			return error;
+		}
+		msleep(POLLING_INTERVAL);
+	}
+	return -EWOULDBLOCK;
+}
diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/sys-manager.c
new file mode 100644
index 0000000..0fc30be
--- /dev/null
+++ b/drivers/ps3/sys-manager.c
@@ -0,0 +1,604 @@
+/*
+ *  PS3 System Manager.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  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.
+ *
+ *  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/kernel.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/reboot.h>
+#include <asm/ps3.h>
+#include "vuart.h"
+
+MODULE_AUTHOR("Sony Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PS3 System Manager");
+
+/**
+ * ps3_sys_manager - PS3 system manager driver.
+ *
+ * The system manager provides an asyncronous system event notification
+ * mechanism for reporting events like thermal alert and button presses to
+ * guests.  It also provides support to control system shutdown and startup.
+ *
+ * The actual system manager is implemented as an application running in the
+ * system policy module in lpar_1.  Guests communicate with the system manager
+ * through port 2 of the vuart using a simple packet message protocol.
+ * Messages are comprised of a fixed field header followed by a message
+ * specific payload.
+ */
+
+/**
+ * struct ps3_sys_manager_header - System manager message header.
+ * @version: Header version, currently 1.
+ * @size: Header size in bytes, curently 16.
+ * @payload_size: Message payload size in bytes.
+ * @service_id: Message type, one of enum ps3_sys_manager_service_id.
+ */
+
+struct ps3_sys_manager_header {
+	/* version 1 */
+	u8 version;
+	u8 size;
+	u16 reserved_1;
+	u32 payload_size;
+	u16 service_id;
+	u16 reserved_2[3];
+};
+
+/**
+ * @PS3_SM_RX_MSG_LEN - System manager received message length.
+ *
+ * Currently all messages received from the system manager are the same length
+ * (16 bytes header + 16 bytes payload = 32 bytes).  This knowlege is used to
+ * simplify the logic.
+ */
+
+enum {
+	PS3_SM_RX_MSG_LEN = 32,
+};
+
+/**
+ * enum ps3_sys_manager_service_id - Message header service_id.
+ * @PS3_SM_SERVICE_ID_REQUEST:      guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_COMMAND:      guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_RESPONSE:     guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_ATTR:     guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_NEXT_OP:  guest --> sys_manager.
+ */
+
+enum ps3_sys_manager_service_id {
+	/* version 1 */
+	PS3_SM_SERVICE_ID_REQUEST = 1,
+	PS3_SM_SERVICE_ID_RESPONSE = 2,
+	PS3_SM_SERVICE_ID_COMMAND = 3,
+	PS3_SM_SERVICE_ID_EXTERN_EVENT = 4,
+	PS3_SM_SERVICE_ID_SET_NEXT_OP = 5,
+	PS3_SM_SERVICE_ID_SET_ATTR = 8,
+};
+
+/**
+ * enum ps3_sys_manager_attr - Notification attribute (bit position mask).
+ * @PS3_SM_ATTR_POWER: Power button.
+ * @PS3_SM_ATTR_RESET: Reset button, not available on retail console.
+ * @PS3_SM_ATTR_THERMAL: Sytem thermal alert.
+ * @PS3_SM_ATTR_CONTROLLER: Remote controller event.
+ * @PS3_SM_ATTR_ALL: Logical OR of all.
+ *
+ * The guest tells the system manager which events it is interested in receiving
+ * notice of by sending the system manager a logical OR of notification
+ * attributes via the ps3_sys_manager_send_attr() routine.
+ */
+
+enum ps3_sys_manager_attr {
+	/* version 1 */
+	PS3_SM_ATTR_POWER = 1,
+	PS3_SM_ATTR_RESET = 2,
+	PS3_SM_ATTR_THERMAL = 4,
+	PS3_SM_ATTR_CONTROLLER = 8, /* bogus? */
+	PS3_SM_ATTR_ALL = 0x0f,
+};
+
+/**
+ * enum ps3_sys_manager_event - External event type, reported by system manager.
+ * @PS3_SM_EVENT_POWER_PRESSED: payload.value not used.
+ * @PS3_SM_EVENT_POWER_RELEASED: payload.value = time pressed in millisec.
+ * @PS3_SM_EVENT_RESET_PRESSED: payload.value not used.
+ * @PS3_SM_EVENT_RESET_RELEASED: payload.value = time pressed in millisec.
+ * @PS3_SM_EVENT_THERMAL_ALERT: payload.value = thermal zone id.
+ * @PS3_SM_EVENT_THERMAL_CLEARED: payload.value = thermal zone id.
+ */
+
+enum ps3_sys_manager_event {
+	/* version 1 */
+	PS3_SM_EVENT_POWER_PRESSED = 3,
+	PS3_SM_EVENT_POWER_RELEASED = 4,
+	PS3_SM_EVENT_RESET_PRESSED = 5,
+	PS3_SM_EVENT_RESET_RELEASED = 6,
+	PS3_SM_EVENT_THERMAL_ALERT = 7,
+	PS3_SM_EVENT_THERMAL_CLEARED = 8,
+	/* no info on controller events */
+};
+
+/**
+ * enum ps3_sys_manager_next_op - Operation to perform after lpar is destroyed.
+ */
+
+enum ps3_sys_manager_next_op {
+	/* version 3 */
+	PS3_SM_NEXT_OP_SYS_SHUTDOWN = 1,
+	PS3_SM_NEXT_OP_SYS_REBOOT = 2,
+	PS3_SM_NEXT_OP_LPAR_REBOOT = 0x82,
+};
+
+/**
+ * enum ps3_sys_manager_wake_source - Next-op wakeup source (bit position mask).
+ * @PS3_SM_WAKE_DEFAULT: Disk insert, power button, eject button, IR
+ * controller, and bluetooth controller.
+ * @PS3_SM_WAKE_RTC:
+ * @PS3_SM_WAKE_RTC_ERROR:
+ * @PS3_SM_WAKE_P_O_R: Power on reset.
+ *
+ * Additional wakeup sources when specifying PS3_SM_NEXT_OP_SYS_SHUTDOWN.
+ * System will always wake from the PS3_SM_WAKE_DEFAULT sources.
+ */
+
+enum ps3_sys_manager_wake_source {
+	/* version 3 */
+	PS3_SM_WAKE_DEFAULT   = 0,
+	PS3_SM_WAKE_RTC       = 0x00000040,
+	PS3_SM_WAKE_RTC_ERROR = 0x00000080,
+	PS3_SM_WAKE_P_O_R     = 0x10000000,
+};
+
+/**
+ * enum ps3_sys_manager_cmd - Command from system manager to guest.
+ *
+ * The guest completes the actions needed, then acks or naks the command via
+ * ps3_sys_manager_send_response().  In the case of @PS3_SM_CMD_SHUTDOWN,
+ * the guest must be fully prepared for a system poweroff prior to acking the
+ * command.
+ */
+
+enum ps3_sys_manager_cmd {
+	/* version 1 */
+	PS3_SM_CMD_SHUTDOWN = 1, /* shutdown guest OS */
+};
+
+/**
+ * ps3_sys_manager_write - Helper to write a two part message to the vuart.
+ *
+ */
+
+static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
+	const struct ps3_sys_manager_header *header, const void *payload)
+{
+	int result;
+
+	BUG_ON(header->version != 1);
+	BUG_ON(header->size != 16);
+	BUG_ON(header->payload_size != 8 && header->payload_size != 16);
+	BUG_ON(header->service_id > 8);
+
+	result = ps3_vuart_write(dev, header,
+		sizeof(struct ps3_sys_manager_header));
+
+	if (!result)
+		result = ps3_vuart_write(dev, payload, header->payload_size);
+
+	return result;
+}
+
+/**
+ * ps3_sys_manager_send_attr - Send a 'set attribute' to the system manager.
+ *
+ */
+
+static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
+	enum ps3_sys_manager_attr attr)
+{
+	static const struct ps3_sys_manager_header header = {
+		.version = 1,
+		.size = 16,
+		.payload_size = 16,
+		.service_id = PS3_SM_SERVICE_ID_SET_ATTR,
+	};
+	struct {
+		u8 version;
+		u8 reserved_1[3];
+		u32 attribute;
+	} payload;
+
+	BUILD_BUG_ON(sizeof(payload) != 8);
+
+	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr);
+
+	memset(&payload, 0, sizeof(payload));
+	payload.version = 1;
+	payload.attribute = attr;
+
+	return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_send_next_op - Send a 'set next op' to the system manager.
+ *
+ * Tell the system manager what to do after this lpar is destroyed.
+ */
+
+static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
+	enum ps3_sys_manager_next_op op,
+	enum ps3_sys_manager_wake_source wake_source)
+{
+	static const struct ps3_sys_manager_header header = {
+		.version = 1,
+		.size = 16,
+		.payload_size = 16,
+		.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP,
+	};
+	struct {
+		u8 version;
+		u8 type;
+		u8 gos_id;
+		u8 reserved_1;
+		u32 wake_source;
+		u8 reserved_2[8];
+	} payload;
+
+	BUILD_BUG_ON(sizeof(payload) != 16);
+
+	dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op);
+
+	memset(&payload, 0, sizeof(payload));
+	payload.version = 3;
+	payload.type = op;
+	payload.gos_id = 3; /* other os */
+	payload.wake_source = wake_source;
+
+	return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_send_request_shutdown - Send 'request' to the system manager.
+ *
+ * The guest sends this message to request an operation or action of the system
+ * manager.  The reply is a command message from the system manager.  In the
+ * command handler the guest performs the requested operation.  The result of
+ * the command is then communicated back to the system manager with a response
+ * message.
+ *
+ * Currently, the only supported request it the 'shutdown self' request.
+ */
+
+static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev)
+{
+	static const struct ps3_sys_manager_header header = {
+		.version = 1,
+		.size = 16,
+		.payload_size = 16,
+		.service_id = PS3_SM_SERVICE_ID_REQUEST,
+	};
+	struct {
+		u8 version;
+		u8 type;
+		u8 gos_id;
+		u8 reserved_1[13];
+	} static const payload = {
+		.version = 1,
+		.type = 1, /* shutdown */
+		.gos_id = 0, /* self */
+	};
+
+	BUILD_BUG_ON(sizeof(payload) != 16);
+
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_send_response - Send a 'response' to the system manager.
+ * @status: zero = success, others fail.
+ *
+ * The guest sends this message to the system manager to acnowledge success or
+ * failure of a command sent by the system manager.
+ */
+
+static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
+	u64 status)
+{
+	static const struct ps3_sys_manager_header header = {
+		.version = 1,
+		.size = 16,
+		.payload_size = 16,
+		.service_id = PS3_SM_SERVICE_ID_RESPONSE,
+	};
+	struct {
+		u8 version;
+		u8 reserved_1[3];
+		u8 status;
+		u8 reserved_2[11];
+	} payload;
+
+	BUILD_BUG_ON(sizeof(payload) != 16);
+
+	dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
+		(status ? "nak" : "ack"));
+
+	memset(&payload, 0, sizeof(payload));
+	payload.version = 1;
+	payload.status = status;
+
+	return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_handle_event - Second stage event msg handler.
+ *
+ */
+
+static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
+{
+	int result;
+	struct {
+		u8 version;
+		u8 type;
+		u8 reserved_1[2];
+		u32 value;
+		u8 reserved_2[8];
+	} event;
+
+	BUILD_BUG_ON(sizeof(event) != 16);
+
+	result = ps3_vuart_read(dev, &event, sizeof(event));
+	BUG_ON(result);
+
+	if (event.version != 1) {
+		dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
+			__func__, __LINE__, event.version);
+		return -EIO;
+	}
+
+	switch (event.type) {
+	case PS3_SM_EVENT_POWER_PRESSED:
+		dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n",
+			__func__, __LINE__);
+		break;
+	case PS3_SM_EVENT_POWER_RELEASED:
+		dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
+			__func__, __LINE__, event.value);
+		kill_cad_pid(SIGINT, 1);
+		break;
+	case PS3_SM_EVENT_THERMAL_ALERT:
+		dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
+			__func__, __LINE__, event.value);
+		printk(KERN_INFO "PS3 Thermal Alert Zone %u\n", event.value);
+		break;
+	case PS3_SM_EVENT_THERMAL_CLEARED:
+		dev_dbg(&dev->core, "%s:%d: THERMAL_CLEARED (zone %u)\n",
+			__func__, __LINE__, event.value);
+		break;
+	default:
+		dev_dbg(&dev->core, "%s:%d: unknown event (%u)\n",
+			__func__, __LINE__, event.type);
+		return -EIO;
+	}
+
+	return 0;
+}
+/**
+ * ps3_sys_manager_handle_cmd - Second stage command msg handler.
+ *
+ * The system manager sends this in reply to a 'request' message from the guest.
+ */
+
+static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
+{
+	int result;
+	struct {
+		u8 version;
+		u8 type;
+		u8 reserved_1[14];
+	} cmd;
+
+	BUILD_BUG_ON(sizeof(cmd) != 16);
+
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
+
+	if(result)
+		return result;
+
+	if (cmd.version != 1) {
+		dev_dbg(&dev->core, "%s:%d: unsupported cmd version (%u)\n",
+			__func__, __LINE__, cmd.version);
+		return -EIO;
+	}
+
+	if (cmd.type != PS3_SM_CMD_SHUTDOWN) {
+		dev_dbg(&dev->core, "%s:%d: unknown cmd (%u)\n",
+			__func__, __LINE__, cmd.type);
+		return -EIO;
+	}
+
+	ps3_sys_manager_send_response(dev, 0);
+	return 0;
+}
+
+/**
+ * ps3_sys_manager_handle_msg - First stage msg handler.
+ *
+ */
+
+static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
+{
+	int result;
+	struct ps3_sys_manager_header header;
+
+	result = ps3_vuart_read(dev, &header,
+		sizeof(struct ps3_sys_manager_header));
+
+	if(result)
+		return result;
+
+	if (header.version != 1) {
+		dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
+			__func__, __LINE__, header.version);
+		goto fail_header;
+	}
+
+	BUILD_BUG_ON(sizeof(header) != 16);
+	BUG_ON(header.size != 16);
+	BUG_ON(header.payload_size != 16);
+
+	switch (header.service_id) {
+	case PS3_SM_SERVICE_ID_EXTERN_EVENT:
+		dev_dbg(&dev->core, "%s:%d: EVENT\n", __func__, __LINE__);
+		return ps3_sys_manager_handle_event(dev);
+	case PS3_SM_SERVICE_ID_COMMAND:
+		dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
+		return ps3_sys_manager_handle_cmd(dev);
+	default:
+		dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
+			__func__, __LINE__, header.service_id);
+		break;
+	}
+	goto fail_id;
+
+fail_header:
+	ps3_vuart_clear_rx_bytes(dev, 0);
+	return -EIO;
+fail_id:
+	ps3_vuart_clear_rx_bytes(dev, header.payload_size);
+	return -EIO;
+}
+
+/**
+ * ps3_sys_manager_work - Asyncronous read handler.
+ *
+ * Signaled when a complete message arrives at the vuart port.
+ */
+
+static void ps3_sys_manager_work(struct work_struct *work)
+{
+	struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work);
+
+	ps3_sys_manager_handle_msg(dev);
+	ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN);
+}
+
+struct {
+	struct ps3_vuart_port_device *dev;
+} static drv_priv;
+
+/**
+ * ps3_sys_manager_restart - The final platform machine_restart routine.
+ *
+ * This routine never returns.  The routine disables asyncronous vuart reads
+ * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
+ * the shutdown command sent from the system manager.  Soon after the
+ * acknowledgement is sent the lpar is destroyed by the HV.  This routine
+ * should only be called from ps3_restart().
+ */
+
+void ps3_sys_manager_restart(void)
+{
+	struct ps3_vuart_port_device *dev = drv_priv.dev;
+
+	BUG_ON(!drv_priv.dev);
+
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	ps3_vuart_cancel_async(dev);
+
+	ps3_sys_manager_send_attr(dev, 0);
+	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
+		PS3_SM_WAKE_DEFAULT);
+	ps3_sys_manager_send_request_shutdown(dev);
+
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+
+	while(1)
+		ps3_sys_manager_handle_msg(dev);
+}
+
+/**
+ * ps3_sys_manager_power_off - The final platform machine_power_off routine.
+ *
+ * This routine never returns.  The routine disables asyncronous vuart reads
+ * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
+ * the shutdown command sent from the system manager.  Soon after the
+ * acknowledgement is sent the lpar is destroyed by the HV.  This routine
+ * should only be called from ps3_power_off().
+ */
+
+void ps3_sys_manager_power_off(void)
+{
+	struct ps3_vuart_port_device *dev = drv_priv.dev;
+
+	BUG_ON(!drv_priv.dev);
+
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	ps3_vuart_cancel_async(dev);
+
+	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
+		PS3_SM_WAKE_DEFAULT);
+	ps3_sys_manager_send_request_shutdown(dev);
+
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+
+	while(1)
+		ps3_sys_manager_handle_msg(dev);
+}
+
+static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev)
+{
+	int result;
+
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	BUG_ON(drv_priv.dev);
+	drv_priv.dev = dev;
+
+	result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL);
+	BUG_ON(result);
+
+	result = ps3_vuart_read_async(dev, ps3_sys_manager_work,
+		PS3_SM_RX_MSG_LEN);
+	BUG_ON(result);
+
+	return result;
+}
+
+static struct ps3_vuart_port_driver ps3_sys_manager = {
+	.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
+	.core = {
+		.name = "ps3_sys_manager",
+	},
+	.probe = ps3_sys_manager_probe,
+};
+
+static int __init ps3_sys_manager_init(void)
+{
+	return ps3_vuart_port_driver_register(&ps3_sys_manager);
+}
+
+module_init(ps3_sys_manager_init);
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index a72da8f..7462981 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -21,8 +21,10 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/workqueue.h>
 #include <asm/ps3.h>
 
+#include <asm/firmware.h>
 #include <asm/lv1call.h>
 #include <asm/bitops.h>
 
@@ -30,7 +32,7 @@
 
 MODULE_AUTHOR("Sony Corporation");
 MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("ps3 vuart");
+MODULE_DESCRIPTION("PS3 vuart");
 
 /**
  * vuart - An inter-partition data link service.
@@ -157,7 +159,7 @@
 	unsigned long size;
 	unsigned long val;
 
-	result = lv1_get_virtual_uart_param(dev->port_number,
+	result = lv1_get_virtual_uart_param(dev->priv->port_number,
 		PARAM_TX_TRIGGER, &trig->tx);
 
 	if (result) {
@@ -166,7 +168,7 @@
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->port_number,
+	result = lv1_get_virtual_uart_param(dev->priv->port_number,
 		PARAM_RX_BUF_SIZE, &size);
 
 	if (result) {
@@ -175,7 +177,7 @@
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->port_number,
+	result = lv1_get_virtual_uart_param(dev->priv->port_number,
 		PARAM_RX_TRIGGER, &val);
 
 	if (result) {
@@ -198,7 +200,7 @@
 	int result;
 	unsigned long size;
 
-	result = lv1_set_virtual_uart_param(dev->port_number,
+	result = lv1_set_virtual_uart_param(dev->priv->port_number,
 		PARAM_TX_TRIGGER, tx);
 
 	if (result) {
@@ -207,7 +209,7 @@
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->port_number,
+	result = lv1_get_virtual_uart_param(dev->priv->port_number,
 		PARAM_RX_BUF_SIZE, &size);
 
 	if (result) {
@@ -216,7 +218,7 @@
 		return result;
 	}
 
-	result = lv1_set_virtual_uart_param(dev->port_number,
+	result = lv1_set_virtual_uart_param(dev->priv->port_number,
 		PARAM_RX_TRIGGER, size - rx);
 
 	if (result) {
@@ -232,9 +234,9 @@
 }
 
 static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
-	unsigned long *bytes_waiting)
+	u64 *bytes_waiting)
 {
-	int result = lv1_get_virtual_uart_param(dev->port_number,
+	int result = lv1_get_virtual_uart_param(dev->priv->port_number,
 		PARAM_RX_BYTES, bytes_waiting);
 
 	if (result)
@@ -253,10 +255,10 @@
 
 	dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
 
-	dev->interrupt_mask = mask;
+	dev->priv->interrupt_mask = mask;
 
-	result = lv1_set_virtual_uart_param(dev->port_number,
-		PARAM_INTERRUPT_MASK, dev->interrupt_mask);
+	result = lv1_set_virtual_uart_param(dev->priv->port_number,
+		PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask);
 
 	if (result)
 		dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
@@ -265,62 +267,64 @@
 	return result;
 }
 
-static int ps3_vuart_get_interrupt_mask(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev,
 	unsigned long *status)
 {
-	int result = lv1_get_virtual_uart_param(dev->port_number,
-		PARAM_INTERRUPT_STATUS, status);
+	u64 tmp;
+	int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+		PARAM_INTERRUPT_STATUS, &tmp);
 
 	if (result)
 		dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
+	*status = tmp & dev->priv->interrupt_mask;
+
 	dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
-		__func__, __LINE__, dev->interrupt_mask, *status,
-		dev->interrupt_mask & *status);
+		__func__, __LINE__, dev->priv->interrupt_mask, tmp, *status);
 
 	return result;
 }
 
 int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev)
 {
-	return (dev->interrupt_mask & INTERRUPT_MASK_TX) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+	return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
 		| INTERRUPT_MASK_TX);
 }
 
 int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev)
 {
-	return (dev->interrupt_mask & INTERRUPT_MASK_RX) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+	return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
 		| INTERRUPT_MASK_RX);
 }
 
 int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
 {
-	return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+	return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
 		| INTERRUPT_MASK_DISCONNECT);
 }
 
 int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev)
 {
-	return (dev->interrupt_mask & INTERRUPT_MASK_TX)
-		? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+	return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX)
+		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
 		& ~INTERRUPT_MASK_TX) : 0;
 }
 
 int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev)
 {
-	return (dev->interrupt_mask & INTERRUPT_MASK_RX)
-		? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+	return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX)
+		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
 		& ~INTERRUPT_MASK_RX) : 0;
 }
 
 int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
 {
-	return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
-		? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+	return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
+		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
 		& ~INTERRUPT_MASK_DISCONNECT) : 0;
 }
 
@@ -335,9 +339,7 @@
 {
 	int result;
 
-	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
-
-	result = lv1_write_virtual_uart(dev->port_number,
+	result = lv1_write_virtual_uart(dev->priv->port_number,
 		ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
 
 	if (result) {
@@ -346,10 +348,10 @@
 		return result;
 	}
 
-	dev->stats.bytes_written += *bytes_written;
+	dev->priv->stats.bytes_written += *bytes_written;
 
-	dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__,
-		__LINE__, *bytes_written, bytes, dev->stats.bytes_written);
+	dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
+		*bytes_written, bytes, dev->priv->stats.bytes_written);
 
 	return result;
 }
@@ -367,7 +369,7 @@
 
 	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
 
-	result = lv1_read_virtual_uart(dev->port_number,
+	result = lv1_read_virtual_uart(dev->priv->port_number,
 		ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
 
 	if (result) {
@@ -376,15 +378,58 @@
 		return result;
 	}
 
-	dev->stats.bytes_read += *bytes_read;
+	dev->priv->stats.bytes_read += *bytes_read;
 
 	dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
-		*bytes_read, bytes, dev->stats.bytes_read);
+		*bytes_read, bytes, dev->priv->stats.bytes_read);
 
 	return result;
 }
 
 /**
+ * ps3_vuart_clear_rx_bytes - Discard bytes received.
+ * @bytes: Max byte count to discard, zero = all pending.
+ *
+ * Used to clear pending rx interrupt source.  Will not block.
+ */
+
+void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+	unsigned int bytes)
+{
+	int result;
+	u64 bytes_waiting;
+	void* tmp;
+
+	result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes_waiting);
+
+	BUG_ON(result);
+
+	bytes = bytes ? min(bytes, (unsigned int)bytes_waiting) : bytes_waiting;
+
+	dev_dbg(&dev->core, "%s:%d: %u\n", __func__, __LINE__, bytes);
+
+	if (!bytes)
+		return;
+
+	/* Add some extra space for recently arrived data. */
+
+	bytes += 128;
+
+	tmp = kmalloc(bytes, GFP_KERNEL);
+
+	if (!tmp)
+		return;
+
+	ps3_vuart_raw_read(dev, tmp, bytes, &bytes_waiting);
+
+	kfree(tmp);
+
+	/* Don't include these bytes in the stats. */
+
+	dev->priv->stats.bytes_read -= bytes_waiting;
+}
+
+/**
  * struct list_buffer - An element for a port device fifo buffer list.
  */
 
@@ -416,14 +461,14 @@
 	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
 		bytes, bytes);
 
-	spin_lock_irqsave(&dev->tx_list.lock, flags);
+	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
 
-	if (list_empty(&dev->tx_list.head)) {
+	if (list_empty(&dev->priv->tx_list.head)) {
 		unsigned long bytes_written;
 
 		result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
 
-		spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+		spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
 
 		if (result) {
 			dev_dbg(&dev->core,
@@ -441,7 +486,7 @@
 		bytes -= bytes_written;
 		buf += bytes_written;
 	} else
-		spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+		spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
 
 	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
 
@@ -454,10 +499,10 @@
 	lb->tail = lb->data + bytes;
 	lb->dbg_number = ++dbg_number;
 
-	spin_lock_irqsave(&dev->tx_list.lock, flags);
-	list_add_tail(&lb->link, &dev->tx_list.head);
+	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+	list_add_tail(&lb->link, &dev->priv->tx_list.head);
 	ps3_vuart_enable_interrupt_tx(dev);
-	spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+	spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
 
 	dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
 		__func__, __LINE__, lb->dbg_number, bytes);
@@ -484,47 +529,83 @@
 	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
 		bytes, bytes);
 
-	spin_lock_irqsave(&dev->rx_list.lock, flags);
+	spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
 
-	if (dev->rx_list.bytes_held < bytes) {
-		spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+	if (dev->priv->rx_list.bytes_held < bytes) {
+		spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
 		dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
-			__func__, __LINE__, bytes - dev->rx_list.bytes_held);
+			__func__, __LINE__,
+			bytes - dev->priv->rx_list.bytes_held);
 		return -EAGAIN;
 	}
 
-	list_for_each_entry_safe(lb, n, &dev->rx_list.head, link) {
+	list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) {
 		bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
 
 		memcpy(buf, lb->head, bytes_read);
 		buf += bytes_read;
 		bytes -= bytes_read;
-		dev->rx_list.bytes_held -= bytes_read;
+		dev->priv->rx_list.bytes_held -= bytes_read;
 
 		if (bytes_read < lb->tail - lb->head) {
 			lb->head += bytes_read;
-			spin_unlock_irqrestore(&dev->rx_list.lock, flags);
-
-			dev_dbg(&dev->core,
-				"%s:%d: dequeued buf_%lu, %lxh bytes\n",
-				__func__, __LINE__, lb->dbg_number, bytes_read);
+			dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
+				"bytes\n", __func__, __LINE__, lb->dbg_number,
+				bytes_read);
+			spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
 			return 0;
 		}
 
-		dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__,
-			lb->dbg_number);
+		dev_dbg(&dev->core, "%s:%d: buf_%lu: free, dequeued %lxh "
+			"bytes\n", __func__, __LINE__, lb->dbg_number,
+			bytes_read);
 
 		list_del(&lb->link);
 		kfree(lb);
 	}
-	spin_unlock_irqrestore(&dev->rx_list.lock, flags);
 
-	dev_dbg(&dev->core, "%s:%d: dequeued buf_%lu, %xh bytes\n",
-		__func__, __LINE__, lb->dbg_number, bytes);
+	spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+	return 0;
+}
+
+int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
+	unsigned int bytes)
+{
+	unsigned long flags;
+
+	if(dev->priv->work.trigger) {
+		dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
+			__func__, __LINE__);
+		return -EAGAIN;
+	}
+
+	BUG_ON(!bytes);
+
+	PREPARE_WORK(&dev->priv->work.work, func);
+
+	spin_lock_irqsave(&dev->priv->work.lock, flags);
+	if(dev->priv->rx_list.bytes_held >= bytes) {
+		dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
+			__func__, __LINE__, bytes);
+		schedule_work(&dev->priv->work.work);
+		spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+		return 0;
+	}
+
+	dev->priv->work.trigger = bytes;
+	spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+
+	dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
+		__LINE__, bytes, bytes);
 
 	return 0;
 }
 
+void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
+{
+	dev->priv->work.trigger = 0;
+}
+
 /**
  * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
  *
@@ -542,9 +623,9 @@
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-	spin_lock_irqsave(&dev->tx_list.lock, flags);
+	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
 
-	list_for_each_entry_safe(lb, n, &dev->tx_list.head, link) {
+	list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) {
 
 		unsigned long bytes_written;
 
@@ -578,7 +659,7 @@
 
 	ps3_vuart_disable_interrupt_tx(dev);
 port_full:
-	spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+	spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
 	dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
 		__func__, __LINE__, bytes_total);
 	return result;
@@ -609,7 +690,7 @@
 
 	BUG_ON(!bytes);
 
-	/* add some extra space for recently arrived data */
+	/* Add some extra space for recently arrived data. */
 
 	bytes += 128;
 
@@ -624,14 +705,23 @@
 	lb->tail = lb->data + bytes;
 	lb->dbg_number = ++dbg_number;
 
-	spin_lock_irqsave(&dev->rx_list.lock, flags);
-	list_add_tail(&lb->link, &dev->rx_list.head);
-	dev->rx_list.bytes_held += bytes;
-	spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+	spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
+	list_add_tail(&lb->link, &dev->priv->rx_list.head);
+	dev->priv->rx_list.bytes_held += bytes;
+	spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
 
-	dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %lxh bytes\n",
+	dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
 		__func__, __LINE__, lb->dbg_number, bytes);
 
+	spin_lock_irqsave(&dev->priv->work.lock, flags);
+	if(dev->priv->work.trigger
+		&& dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) {
+		dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
+			__func__, __LINE__, dev->priv->work.trigger);
+		dev->priv->work.trigger = 0;
+		schedule_work(&dev->priv->work.work);
+	}
+	spin_unlock_irqrestore(&dev->priv->work.lock, flags);
 	return 0;
 }
 
@@ -656,7 +746,7 @@
 	int result;
 	unsigned long status;
 
-	result = ps3_vuart_get_interrupt_mask(dev, &status);
+	result = ps3_vuart_get_interrupt_status(dev, &status);
 
 	if (result)
 		return result;
@@ -665,21 +755,21 @@
 		status);
 
 	if (status & INTERRUPT_MASK_DISCONNECT) {
-		dev->stats.disconnect_interrupts++;
+		dev->priv->stats.disconnect_interrupts++;
 		result = ps3_vuart_handle_interrupt_disconnect(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_disconnect(dev);
 	}
 
 	if (status & INTERRUPT_MASK_TX) {
-		dev->stats.tx_interrupts++;
+		dev->priv->stats.tx_interrupts++;
 		result = ps3_vuart_handle_interrupt_tx(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_tx(dev);
 	}
 
 	if (status & INTERRUPT_MASK_RX) {
-		dev->stats.rx_interrupts++;
+		dev->priv->stats.rx_interrupts++;
 		result = ps3_vuart_handle_interrupt_rx(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_rx(dev);
@@ -688,12 +778,13 @@
 	return 0;
 }
 
-struct vuart_private {
-	unsigned int in_use;
-	unsigned int virq;
-	struct ps3_vuart_port_device *devices[PORT_COUNT];
+struct vuart_bus_priv {
 	const struct ports_bmp bmp;
-};
+	unsigned int virq;
+	struct semaphore probe_mutex;
+	int use_count;
+	struct ps3_vuart_port_device *devices[PORT_COUNT];
+} static vuart_bus_priv;
 
 /**
  * ps3_vuart_irq_handler - first stage interrupt handler
@@ -705,25 +796,25 @@
 
 static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
 {
-	struct vuart_private *private;
+	struct vuart_bus_priv *bus_priv;
 
 	BUG_ON(!_private);
-	private = (struct vuart_private *)_private;
+	bus_priv = (struct vuart_bus_priv *)_private;
 
 	while (1) {
 		unsigned int port;
 
-		dump_ports_bmp(&private->bmp);
+		dump_ports_bmp(&bus_priv->bmp);
 
-		port = (BITS_PER_LONG - 1) - __ilog2(private->bmp.status);
+		port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status);
 
 		if (port == BITS_PER_LONG)
 			break;
 
 		BUG_ON(port >= PORT_COUNT);
-		BUG_ON(!private->devices[port]);
+		BUG_ON(!bus_priv->devices[port]);
 
-		ps3_vuart_handle_port_interrupt(private->devices[port]);
+		ps3_vuart_handle_port_interrupt(bus_priv->devices[port]);
 	}
 
 	return IRQ_HANDLED;
@@ -744,12 +835,10 @@
 	return result;
 }
 
-static struct vuart_private vuart_private;
-
 static int ps3_vuart_probe(struct device *_dev)
 {
 	int result;
-	unsigned long tmp;
+	unsigned int port_number;
 	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
 	struct ps3_vuart_port_driver *drv =
 		to_ps3_vuart_port_driver(_dev->driver);
@@ -758,7 +847,12 @@
 
 	BUG_ON(!drv);
 
-	result = ps3_vuart_match_id_to_port(dev->match_id, &dev->port_number);
+	down(&vuart_bus_priv.probe_mutex);
+
+	/* Setup vuart_bus_priv.devices[]. */
+
+	result = ps3_vuart_match_id_to_port(dev->match_id,
+		&port_number);
 
 	if (result) {
 		dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
@@ -767,24 +861,41 @@
 		goto fail_match;
 	}
 
-	if (vuart_private.devices[dev->port_number]) {
+	if (vuart_bus_priv.devices[port_number]) {
 		dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
-			__LINE__, dev->port_number);
+			__LINE__, port_number);
 		result = -EBUSY;
 		goto fail_match;
 	}
 
-	vuart_private.devices[dev->port_number] = dev;
+	vuart_bus_priv.devices[port_number] = dev;
 
-	INIT_LIST_HEAD(&dev->tx_list.head);
-	spin_lock_init(&dev->tx_list.lock);
-	INIT_LIST_HEAD(&dev->rx_list.head);
-	spin_lock_init(&dev->rx_list.lock);
+	/* Setup dev->priv. */
 
-	vuart_private.in_use++;
-	if (vuart_private.in_use == 1) {
+	dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL);
+
+	if (!dev->priv) {
+		result = -ENOMEM;
+		goto fail_alloc;
+	}
+
+	dev->priv->port_number = port_number;
+
+	INIT_LIST_HEAD(&dev->priv->tx_list.head);
+	spin_lock_init(&dev->priv->tx_list.lock);
+
+	INIT_LIST_HEAD(&dev->priv->rx_list.head);
+	spin_lock_init(&dev->priv->rx_list.lock);
+
+	INIT_WORK(&dev->priv->work.work, NULL);
+	spin_lock_init(&dev->priv->work.lock);
+	dev->priv->work.trigger = 0;
+	dev->priv->work.dev = dev;
+
+	if (++vuart_bus_priv.use_count == 1) {
+
 		result = ps3_alloc_vuart_irq(PS3_BINDING_CPU_ANY,
-			(void*)&vuart_private.bmp.status, &vuart_private.virq);
+			(void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
 
 		if (result) {
 			dev_dbg(&dev->core,
@@ -794,8 +905,8 @@
 			goto fail_alloc_irq;
 		}
 
-		result = request_irq(vuart_private.virq, ps3_vuart_irq_handler,
-			IRQF_DISABLED, "vuart", &vuart_private);
+		result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
+			IRQF_DISABLED, "vuart", &vuart_bus_priv);
 
 		if (result) {
 			dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
@@ -804,10 +915,11 @@
 		}
 	}
 
-	ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX);
-
 	/* clear stale pending interrupts */
-	ps3_vuart_get_interrupt_mask(dev, &tmp);
+
+	ps3_vuart_clear_rx_bytes(dev, 0);
+
+	ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX);
 
 	ps3_vuart_set_triggers(dev, 1, 1);
 
@@ -822,20 +934,27 @@
 	if (result) {
 		dev_dbg(&dev->core, "%s:%d: drv->probe failed\n",
 			__func__, __LINE__);
+		down(&vuart_bus_priv.probe_mutex);
 		goto fail_probe;
 	}
 
+	up(&vuart_bus_priv.probe_mutex);
+
 	return result;
 
 fail_probe:
+	ps3_vuart_set_interrupt_mask(dev, 0);
 fail_request_irq:
-	vuart_private.in_use--;
-	if (!vuart_private.in_use) {
-		ps3_free_vuart_irq(vuart_private.virq);
-		vuart_private.virq = NO_IRQ;
-	}
+	ps3_free_vuart_irq(vuart_bus_priv.virq);
+	vuart_bus_priv.virq = NO_IRQ;
 fail_alloc_irq:
+	--vuart_bus_priv.use_count;
+	kfree(dev->priv);
+	dev->priv = NULL;
+fail_alloc:
+	vuart_bus_priv.devices[port_number] = 0;
 fail_match:
+	up(&vuart_bus_priv.probe_mutex);
 	dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
 	return result;
 }
@@ -846,10 +965,12 @@
 	struct ps3_vuart_port_driver *drv =
 		to_ps3_vuart_port_driver(_dev->driver);
 
+	down(&vuart_bus_priv.probe_mutex);
+
 	dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
 		dev->core.bus_id);
 
-	BUG_ON(vuart_private.in_use < 1);
+	BUG_ON(vuart_bus_priv.use_count < 1);
 
 	if (drv->remove)
 		drv->remove(dev);
@@ -857,47 +978,76 @@
 		dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
 			__LINE__, dev->core.bus_id);
 
-	vuart_private.in_use--;
+	vuart_bus_priv.devices[dev->priv->port_number] = 0;
 
-	if (!vuart_private.in_use) {
-		free_irq(vuart_private.virq, &vuart_private);
-		ps3_free_vuart_irq(vuart_private.virq);
-		vuart_private.virq = NO_IRQ;
+	if (--vuart_bus_priv.use_count == 0) {
+		BUG();
+		free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
+		ps3_free_vuart_irq(vuart_bus_priv.virq);
+		vuart_bus_priv.virq = NO_IRQ;
 	}
+
+	kfree(dev->priv);
+	dev->priv = NULL;
+
+	up(&vuart_bus_priv.probe_mutex);
 	return 0;
 }
 
+static void ps3_vuart_shutdown(struct device *_dev)
+{
+	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+	struct ps3_vuart_port_driver *drv =
+		to_ps3_vuart_port_driver(_dev->driver);
+
+	dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
+		dev->core.bus_id);
+
+	if (drv->shutdown)
+		drv->shutdown(dev);
+	else
+		dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__,
+			__LINE__, dev->core.bus_id);
+}
+
 /**
- * ps3_vuart - The vuart instance.
+ * ps3_vuart_bus - The vuart bus instance.
  *
  * The vuart is managed as a bus that port devices connect to.
  */
 
-struct bus_type ps3_vuart = {
+struct bus_type ps3_vuart_bus = {
         .name = "ps3_vuart",
 	.match = ps3_vuart_match,
 	.probe = ps3_vuart_probe,
 	.remove = ps3_vuart_remove,
+	.shutdown = ps3_vuart_shutdown,
 };
 
-int __init ps3_vuart_init(void)
+int __init ps3_vuart_bus_init(void)
 {
 	int result;
 
 	pr_debug("%s:%d:\n", __func__, __LINE__);
-	result = bus_register(&ps3_vuart);
+
+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+		return 0;
+
+	init_MUTEX(&vuart_bus_priv.probe_mutex);
+	result = bus_register(&ps3_vuart_bus);
 	BUG_ON(result);
+
 	return result;
 }
 
-void __exit ps3_vuart_exit(void)
+void __exit ps3_vuart_bus_exit(void)
 {
 	pr_debug("%s:%d:\n", __func__, __LINE__);
-	bus_unregister(&ps3_vuart);
+	bus_unregister(&ps3_vuart_bus);
 }
 
-core_initcall(ps3_vuart_init);
-module_exit(ps3_vuart_exit);
+core_initcall(ps3_vuart_bus_init);
+module_exit(ps3_vuart_bus_exit);
 
 /**
  * ps3_vuart_port_release_device - Remove a vuart port device.
@@ -905,11 +1055,14 @@
 
 static void ps3_vuart_port_release_device(struct device *_dev)
 {
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
 #if defined(DEBUG)
-	memset(dev, 0xad, sizeof(struct ps3_vuart_port_device));
+	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	BUG_ON(dev->priv && "forgot to free");
+	memset(&dev->core, 0, sizeof(dev->core));
 #endif
-	kfree(dev);
 }
 
 /**
@@ -918,11 +1071,12 @@
 
 int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
 {
-	int result;
 	static unsigned int dev_count = 1;
 
+	BUG_ON(dev->priv && "forgot to free");
+
 	dev->core.parent = NULL;
-	dev->core.bus = &ps3_vuart;
+	dev->core.bus = &ps3_vuart_bus;
 	dev->core.release = ps3_vuart_port_release_device;
 
 	snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
@@ -930,9 +1084,7 @@
 
 	dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
 
-	result = device_register(&dev->core);
-
-	return result;
+	return device_register(&dev->core);
 }
 
 EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
@@ -946,7 +1098,7 @@
 	int result;
 
 	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
-	drv->core.bus = &ps3_vuart;
+	drv->core.bus = &ps3_vuart_bus;
 	result = driver_register(&drv->core);
 	return result;
 }
@@ -959,6 +1111,7 @@
 
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
 {
+	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
 	driver_unregister(&drv->core);
 }
 
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
index 11c421c..1be992d 100644
--- a/drivers/ps3/vuart.h
+++ b/drivers/ps3/vuart.h
@@ -21,6 +21,44 @@
 #if !defined(_PS3_VUART_H)
 #define _PS3_VUART_H
 
+#include <asm/ps3.h>
+
+struct ps3_vuart_stats {
+	unsigned long bytes_written;
+	unsigned long bytes_read;
+	unsigned long tx_interrupts;
+	unsigned long rx_interrupts;
+	unsigned long disconnect_interrupts;
+};
+
+struct ps3_vuart_work {
+	struct work_struct work;
+	unsigned long trigger;
+	spinlock_t lock;
+	struct ps3_vuart_port_device* dev; /* to convert work to device */
+};
+
+/**
+ * struct ps3_vuart_port_priv - private vuart device data.
+ */
+
+struct ps3_vuart_port_priv {
+	unsigned int port_number;
+	u64 interrupt_mask;
+
+	struct {
+		spinlock_t lock;
+		struct list_head head;
+	} tx_list;
+	struct {
+		unsigned long bytes_held;
+		spinlock_t lock;
+		struct list_head head;
+	} rx_list;
+	struct ps3_vuart_stats stats;
+	struct ps3_vuart_work work;
+};
+
 /**
  * struct ps3_vuart_port_driver - a driver for a device on a vuart port
  */
@@ -30,6 +68,7 @@
 	struct device_driver core;
 	int (*probe)(struct ps3_vuart_port_device *);
 	int (*remove)(struct ps3_vuart_port_device *);
+	void (*shutdown)(struct ps3_vuart_port_device *);
 	int (*tx_event)(struct ps3_vuart_port_device *dev);
 	int (*rx_event)(struct ps3_vuart_port_device *dev);
 	int (*disconnect_event)(struct ps3_vuart_port_device *dev);
@@ -40,10 +79,6 @@
 int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
 
-int ps3_vuart_write(struct ps3_vuart_port_device *dev,
-	const void* buf, unsigned int bytes);
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
-	unsigned int bytes);
 static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver(
 	struct device_driver *_drv)
 {
@@ -54,5 +89,22 @@
 {
 	return container_of(_dev, struct ps3_vuart_port_device, core);
 }
+static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
+	struct work_struct *_work)
+{
+	struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work,
+		work);
+	return vw->dev;
+}
+
+int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+	unsigned int bytes);
+int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+	unsigned int bytes);
+int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
+	unsigned int bytes);
+void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev);
+void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+	unsigned int bytes);
 
 #endif
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 7bf7b2c..f935c1f 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -326,14 +326,17 @@
 	rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
 				 &rdev->dst_ops);
 
-	if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)
-	    && do_enum) {
-		rio_set_device_id(port, destid, hopcount, next_destid);
-		rdev->destid = next_destid++;
-		if (next_destid == port->host_deviceid)
-			next_destid++;
+	if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) {
+		if (do_enum) {
+			rio_set_device_id(port, destid, hopcount, next_destid);
+			rdev->destid = next_destid++;
+			if (next_destid == port->host_deviceid)
+				next_destid++;
+		} else
+			rdev->destid = rio_get_device_id(port, destid, hopcount);
 	} else
-		rdev->destid = rio_get_device_id(port, destid, hopcount);
+		/* Switch device has an associated destID */
+		rdev->destid = RIO_INVALID_DESTID;
 
 	/* If a PE has both switch and other functions, show it as a switch */
 	if (rio_is_switch(rdev)) {
@@ -347,7 +350,7 @@
 		}
 		rswitch->switchid = next_switchid;
 		rswitch->hopcount = hopcount;
-		rswitch->destid = 0xffff;
+		rswitch->destid = destid;
 		/* Initialize switch route table */
 		for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES; rdid++)
 			rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
@@ -422,7 +425,7 @@
 /**
  * rio_route_add_entry- Add a route entry to a switch routing table
  * @mport: Master port to send transaction
- * @rdev: Switch device
+ * @rswitch: Switch device
  * @table: Routing table ID
  * @route_destid: Destination ID to be routed
  * @route_port: Port number to be routed
@@ -434,18 +437,18 @@
  * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL
  * on failure.
  */
-static int rio_route_add_entry(struct rio_mport *mport, struct rio_dev *rdev,
+static int rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch,
 			       u16 table, u16 route_destid, u8 route_port)
 {
-	return rdev->rswitch->add_entry(mport, rdev->rswitch->destid,
-					rdev->rswitch->hopcount, table,
+	return rswitch->add_entry(mport, rswitch->destid,
+					rswitch->hopcount, table,
 					route_destid, route_port);
 }
 
 /**
  * rio_route_get_entry- Read a route entry in a switch routing table
  * @mport: Master port to send transaction
- * @rdev: Switch device
+ * @rswitch: Switch device
  * @table: Routing table ID
  * @route_destid: Destination ID to be routed
  * @route_port: Pointer to read port number into
@@ -458,11 +461,11 @@
  * on failure.
  */
 static int
-rio_route_get_entry(struct rio_mport *mport, struct rio_dev *rdev, u16 table,
+rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table,
 		    u16 route_destid, u8 * route_port)
 {
-	return rdev->rswitch->get_entry(mport, rdev->rswitch->destid,
-					rdev->rswitch->hopcount, table,
+	return rswitch->get_entry(mport, rswitch->destid,
+					rswitch->hopcount, table,
 					route_destid, route_port);
 }
 
@@ -552,6 +555,8 @@
 	int port_num;
 	int num_ports;
 	int cur_destid;
+	int sw_destid;
+	int sw_inport;
 	struct rio_dev *rdev;
 	u16 destid;
 	int tmp;
@@ -594,15 +599,17 @@
 
 	if (rio_is_switch(rdev)) {
 		next_switchid++;
+		sw_inport = rio_get_swpinfo_inport(port, RIO_ANY_DESTID, hopcount);
+		rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
+				    port->host_deviceid, sw_inport);
+		rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
 
 		for (destid = 0; destid < next_destid; destid++) {
-			rio_route_add_entry(port, rdev, RIO_GLOBAL_TABLE,
-					    destid, rio_get_swpinfo_inport(port,
-									   RIO_ANY_DESTID,
-									   hopcount));
-			rdev->rswitch->route_table[destid] =
-			    rio_get_swpinfo_inport(port, RIO_ANY_DESTID,
-						   hopcount);
+			if (destid == port->host_deviceid)
+				continue;
+			rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
+					    destid, sw_inport);
+			rdev->rswitch->route_table[destid] = sw_inport;
 		}
 
 		num_ports =
@@ -610,9 +617,9 @@
 		pr_debug(
 		    "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
 		    rio_name(rdev), rdev->vid, rdev->did, num_ports);
+		sw_destid = next_destid;
 		for (port_num = 0; port_num < num_ports; port_num++) {
-			if (rio_get_swpinfo_inport
-			    (port, RIO_ANY_DESTID, hopcount) == port_num)
+			if (sw_inport == port_num)
 				continue;
 
 			cur_destid = next_destid;
@@ -622,7 +629,7 @@
 				pr_debug(
 				    "RIO: scanning device on port %d\n",
 				    port_num);
-				rio_route_add_entry(port, rdev,
+				rio_route_add_entry(port, rdev->rswitch,
 						    RIO_GLOBAL_TABLE,
 						    RIO_ANY_DESTID, port_num);
 
@@ -633,7 +640,9 @@
 				if (next_destid > cur_destid) {
 					for (destid = cur_destid;
 					     destid < next_destid; destid++) {
-						rio_route_add_entry(port, rdev,
+						if (destid == port->host_deviceid)
+							continue;
+						rio_route_add_entry(port, rdev->rswitch,
 								    RIO_GLOBAL_TABLE,
 								    destid,
 								    port_num);
@@ -641,10 +650,18 @@
 						    route_table[destid] =
 						    port_num;
 					}
-					rdev->rswitch->destid = cur_destid;
 				}
 			}
 		}
+
+		/* Check for empty switch */
+		if (next_destid == sw_destid) {
+			next_destid++;
+			if (next_destid == port->host_deviceid)
+				next_destid++;
+		}
+
+		rdev->rswitch->destid = sw_destid;
 	} else
 		pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n",
 		    rio_name(rdev), rdev->vid, rdev->did);
@@ -721,7 +738,7 @@
 				    port_num);
 				for (ndestid = 0; ndestid < RIO_ANY_DESTID;
 				     ndestid++) {
-					rio_route_get_entry(port, rdev,
+					rio_route_get_entry(port, rdev->rswitch,
 							    RIO_GLOBAL_TABLE,
 							    ndestid,
 							    &route_port);
@@ -798,6 +815,44 @@
 }
 
 /**
+ * rio_update_route_tables- Updates route tables in switches
+ * @port: Master port associated with the RIO network
+ *
+ * For each enumerated device, ensure that each switch in a system
+ * has correct routing entries. Add routes for devices that where
+ * unknown dirung the first enumeration pass through the switch.
+ */
+static void rio_update_route_tables(struct rio_mport *port)
+{
+	struct rio_dev *rdev;
+	struct rio_switch *rswitch;
+	u8 sport;
+	u16 destid;
+
+	list_for_each_entry(rdev, &rio_devices, global_list) {
+
+		destid = (rio_is_switch(rdev))?rdev->rswitch->destid:rdev->destid;
+
+		list_for_each_entry(rswitch, &rio_switches, node) {
+
+			if (rio_is_switch(rdev)	&& (rdev->rswitch == rswitch))
+				continue;
+
+			if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) {
+
+				sport = rio_get_swpinfo_inport(port,
+						rswitch->destid, rswitch->hopcount);
+
+				if (rswitch->add_entry)	{
+					rio_route_add_entry(port, rswitch, RIO_GLOBAL_TABLE, destid, sport);
+					rswitch->route_table[destid] = sport;
+				}
+			}
+		}
+	}
+}
+
+/**
  * rio_enum_mport- Start enumeration through a master port
  * @mport: Master port to send transactions
  *
@@ -838,6 +893,7 @@
 			rc = -EBUSY;
 			goto out;
 		}
+		rio_update_route_tables(mport);
 		rio_clear_locks(mport);
 	} else {
 		printk(KERN_INFO "RIO: master port %d link inactive\n",
@@ -865,8 +921,8 @@
 	    if (rio_is_switch(rdev))
 		for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) {
 			if (rio_route_get_entry
-			    (rdev->net->hport, rdev, RIO_GLOBAL_TABLE, i,
-			     &sport) < 0)
+			    (rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE,
+			     i, &sport) < 0)
 				continue;
 			rdev->rswitch->route_table[i] = sport;
 		}
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index 5687b8f..eed9143 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -14,7 +14,6 @@
 #include <linux/rio.h>
 #include <linux/rio_drv.h>
 #include <linux/stat.h>
-#include <linux/sched.h>	/* for capable() */
 
 #include "rio.h"
 
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 09660e2..deef296 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1,4 +1,4 @@
-\#
+#
 # RTC class/drivers configuration
 #
 
@@ -95,6 +95,29 @@
 comment "RTC drivers"
 	depends on RTC_CLASS
 
+# this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h>
+# requires <asm/mc146818rtc.h> defining CMOS_READ/CMOS_WRITE, and a
+# global rtc_lock ... it's not yet just another platform_device.
+
+config RTC_DRV_CMOS
+	tristate "PC-style 'CMOS' real time clock"
+	depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \
+		|| M32R || ATARI || POWERPC)
+	help
+	  Say "yes" here to get direct support for the real time clock
+	  found in every PC or ACPI-based system, and some other boards.
+	  Specifically the original MC146818, compatibles like those in
+	  PC south bridges, the DS12887 or M48T86, some multifunction
+	  or LPC bus chips, and so on.
+
+	  Your system will need to define the platform device used by
+	  this driver, otherwise it won't be accessible.  This means
+	  you can safely enable this driver if you don't know whether
+	  or not your board has this kind of hardware.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-cmos.
+
 config RTC_DRV_X1205
 	tristate "Xicor/Intersil X1205"
 	depends on RTC_CLASS && I2C
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index e6beeda..92bfe1b 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_RTC_INTF_PROC)	+= rtc-proc.o
 obj-$(CONFIG_RTC_INTF_DEV)	+= rtc-dev.o
 
+obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc-cmos.o
 obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o
 obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index a724ab4..ac0e68e 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -164,6 +164,7 @@
 	tm.tm_min = alrm->time.tm_min;
 	tm.tm_sec = alrm->time.tm_sec;
 
+	at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
 	at91_sys_write(AT91_RTC_TIMALR,
 		  BIN2BCD(tm.tm_sec) << 0
 		| BIN2BCD(tm.tm_min) << 8
@@ -174,6 +175,9 @@
 		| BIN2BCD(tm.tm_mday) << 24
 		| AT91_RTC_DATEEN | AT91_RTC_MTHEN);
 
+	if (alrm->enabled)
+		at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
+
 	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
 		at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
 		tm.tm_min, tm.tm_sec);
@@ -303,6 +307,12 @@
 		return ret;
 	}
 
+	/* cpu init code should really have flagged this device as
+	 * being wake-capable; if it didn't, do that here.
+	 */
+	if (!device_can_wakeup(&pdev->dev))
+		device_init_wakeup(&pdev->dev, 1);
+
 	rtc = rtc_device_register(pdev->name, &pdev->dev,
 				&at91_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
@@ -310,7 +320,6 @@
 		return PTR_ERR(rtc);
 	}
 	platform_set_drvdata(pdev, rtc);
-	device_init_wakeup(&pdev->dev, 1);
 
 	printk(KERN_INFO "AT91 Real Time Clock driver.\n");
 	return 0;
@@ -319,7 +328,7 @@
 /*
  * Disable and remove the RTC driver
  */
-static int __devexit at91_rtc_remove(struct platform_device *pdev)
+static int __exit at91_rtc_remove(struct platform_device *pdev)
 {
 	struct rtc_device *rtc = platform_get_drvdata(pdev);
 
@@ -331,7 +340,6 @@
 
 	rtc_device_unregister(rtc);
 	platform_set_drvdata(pdev, NULL);
-	device_init_wakeup(&pdev->dev, 0);
 
 	return 0;
 }
@@ -404,8 +412,7 @@
 #endif
 
 static struct platform_driver at91_rtc_driver = {
-	.probe		= at91_rtc_probe,
-	.remove		= at91_rtc_remove,
+	.remove		= __exit_p(at91_rtc_remove),
 	.suspend	= at91_rtc_suspend,
 	.resume		= at91_rtc_resume,
 	.driver		= {
@@ -416,7 +423,7 @@
 
 static int __init at91_rtc_init(void)
 {
-	return platform_driver_register(&at91_rtc_driver);
+	return platform_driver_probe(&at91_rtc_driver, at91_rtc_probe);
 }
 
 static void __exit at91_rtc_exit(void)
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
new file mode 100644
index 0000000..85bf795
--- /dev/null
+++ b/drivers/rtc/rtc-cmos.c
@@ -0,0 +1,725 @@
+/*
+ * RTC class driver for "CMOS RTC":  PCs, ACPI, etc
+ *
+ * Copyright (C) 1996 Paul Gortmaker (drivers/char/rtc.c)
+ * Copyright (C) 2006 David Brownell (convert to new framework)
+ *
+ * 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.
+ */
+
+/*
+ * The original "cmos clock" chip was an MC146818 chip, now obsolete.
+ * That defined the register interface now provided by all PCs, some
+ * non-PC systems, and incorporated into ACPI.  Modern PC chipsets
+ * integrate an MC146818 clone in their southbridge, and boards use
+ * that instead of discrete clones like the DS12887 or M48T86.  There
+ * are also clones that connect using the LPC bus.
+ *
+ * That register API is also used directly by various other drivers
+ * (notably for integrated NVRAM), infrastructure (x86 has code to
+ * bypass the RTC framework, directly reading the RTC during boot
+ * and updating minutes/seconds for systems using NTP synch) and
+ * utilities (like userspace 'hwclock', if no /dev node exists).
+ *
+ * So **ALL** calls to CMOS_READ and CMOS_WRITE must be done with
+ * interrupts disabled, holding the global rtc_lock, to exclude those
+ * other drivers and utilities on correctly configured systems.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
+
+/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
+#include <asm-generic/rtc.h>
+
+
+struct cmos_rtc {
+	struct rtc_device	*rtc;
+	struct device		*dev;
+	int			irq;
+	struct resource		*iomem;
+
+	u8			suspend_ctrl;
+
+	/* newer hardware extends the original register set */
+	u8			day_alrm;
+	u8			mon_alrm;
+	u8			century;
+};
+
+/* both platform and pnp busses use negative numbers for invalid irqs */
+#define is_valid_irq(n)		((n) >= 0)
+
+static const char driver_name[] = "rtc_cmos";
+
+/*----------------------------------------------------------------*/
+
+static int cmos_read_time(struct device *dev, struct rtc_time *t)
+{
+	/* REVISIT:  if the clock has a "century" register, use
+	 * that instead of the heuristic in get_rtc_time().
+	 * That'll make Y3K compatility (year > 2070) easy!
+	 */
+	get_rtc_time(t);
+	return 0;
+}
+
+static int cmos_set_time(struct device *dev, struct rtc_time *t)
+{
+	/* REVISIT:  set the "century" register if available
+	 *
+	 * NOTE: this ignores the issue whereby updating the seconds
+	 * takes effect exactly 500ms after we write the register.
+	 * (Also queueing and other delays before we get this far.)
+	 */
+	return set_rtc_time(t);
+}
+
+static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
+	unsigned char	rtc_control;
+
+	if (!is_valid_irq(cmos->irq))
+		return -EIO;
+
+	/* Basic alarms only support hour, minute, and seconds fields.
+	 * Some also support day and month, for alarms up to a year in
+	 * the future.
+	 */
+	t->time.tm_mday = -1;
+	t->time.tm_mon = -1;
+
+	spin_lock_irq(&rtc_lock);
+	t->time.tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
+	t->time.tm_min = CMOS_READ(RTC_MINUTES_ALARM);
+	t->time.tm_hour = CMOS_READ(RTC_HOURS_ALARM);
+
+	if (cmos->day_alrm) {
+		t->time.tm_mday = CMOS_READ(cmos->day_alrm);
+		if (!t->time.tm_mday)
+			t->time.tm_mday = -1;
+
+		if (cmos->mon_alrm) {
+			t->time.tm_mon = CMOS_READ(cmos->mon_alrm);
+			if (!t->time.tm_mon)
+				t->time.tm_mon = -1;
+		}
+	}
+
+	rtc_control = CMOS_READ(RTC_CONTROL);
+	spin_unlock_irq(&rtc_lock);
+
+	/* REVISIT this assumes PC style usage:  always BCD */
+
+	if (((unsigned)t->time.tm_sec) < 0x60)
+		t->time.tm_sec = BCD2BIN(t->time.tm_sec);
+	else
+		t->time.tm_sec = -1;
+	if (((unsigned)t->time.tm_min) < 0x60)
+		t->time.tm_min = BCD2BIN(t->time.tm_min);
+	else
+		t->time.tm_min = -1;
+	if (((unsigned)t->time.tm_hour) < 0x24)
+		t->time.tm_hour = BCD2BIN(t->time.tm_hour);
+	else
+		t->time.tm_hour = -1;
+
+	if (cmos->day_alrm) {
+		if (((unsigned)t->time.tm_mday) <= 0x31)
+			t->time.tm_mday = BCD2BIN(t->time.tm_mday);
+		else
+			t->time.tm_mday = -1;
+		if (cmos->mon_alrm) {
+			if (((unsigned)t->time.tm_mon) <= 0x12)
+				t->time.tm_mon = BCD2BIN(t->time.tm_mon) - 1;
+			else
+				t->time.tm_mon = -1;
+		}
+	}
+	t->time.tm_year = -1;
+
+	t->enabled = !!(rtc_control & RTC_AIE);
+	t->pending = 0;
+
+	return 0;
+}
+
+static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
+	unsigned char	mon, mday, hrs, min, sec;
+	unsigned char	rtc_control, rtc_intr;
+
+	if (!is_valid_irq(cmos->irq))
+		return -EIO;
+
+	/* REVISIT this assumes PC style usage:  always BCD */
+
+	/* Writing 0xff means "don't care" or "match all".  */
+
+	mon = t->time.tm_mon;
+	mon = (mon < 12) ? BIN2BCD(mon) : 0xff;
+	mon++;
+
+	mday = t->time.tm_mday;
+	mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff;
+
+	hrs = t->time.tm_hour;
+	hrs = (hrs < 24) ? BIN2BCD(hrs) : 0xff;
+
+	min = t->time.tm_min;
+	min = (min < 60) ? BIN2BCD(min) : 0xff;
+
+	sec = t->time.tm_sec;
+	sec = (sec < 60) ? BIN2BCD(sec) : 0xff;
+
+	spin_lock_irq(&rtc_lock);
+
+	/* next rtc irq must not be from previous alarm setting */
+	rtc_control = CMOS_READ(RTC_CONTROL);
+	rtc_control &= ~RTC_AIE;
+	CMOS_WRITE(rtc_control, RTC_CONTROL);
+	rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
+	if (rtc_intr)
+		rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr);
+
+	/* update alarm */
+	CMOS_WRITE(hrs, RTC_HOURS_ALARM);
+	CMOS_WRITE(min, RTC_MINUTES_ALARM);
+	CMOS_WRITE(sec, RTC_SECONDS_ALARM);
+
+	/* the system may support an "enhanced" alarm */
+	if (cmos->day_alrm) {
+		CMOS_WRITE(mday, cmos->day_alrm);
+		if (cmos->mon_alrm)
+			CMOS_WRITE(mon, cmos->mon_alrm);
+	}
+
+	if (t->enabled) {
+		rtc_control |= RTC_AIE;
+		CMOS_WRITE(rtc_control, RTC_CONTROL);
+		rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
+		if (rtc_intr)
+			rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr);
+	}
+
+	spin_unlock_irq(&rtc_lock);
+
+	return 0;
+}
+
+static int cmos_set_freq(struct device *dev, int freq)
+{
+	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
+	int		f;
+	unsigned long	flags;
+
+	if (!is_valid_irq(cmos->irq))
+		return -ENXIO;
+
+	/* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */
+	f = ffs(freq);
+	if (f != 0) {
+		if (f-- > 16 || freq != (1 << f))
+			return -EINVAL;
+		f = 16 - f;
+	}
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+
+	return 0;
+}
+
+#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
+
+static int
+cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
+	unsigned char	rtc_control, rtc_intr;
+	unsigned long	flags;
+
+	switch (cmd) {
+	case RTC_AIE_OFF:
+	case RTC_AIE_ON:
+	case RTC_UIE_OFF:
+	case RTC_UIE_ON:
+	case RTC_PIE_OFF:
+	case RTC_PIE_ON:
+		if (!is_valid_irq(cmos->irq))
+			return -EINVAL;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	rtc_control = CMOS_READ(RTC_CONTROL);
+	switch (cmd) {
+	case RTC_AIE_OFF:	/* alarm off */
+		rtc_control &= ~RTC_AIE;
+		break;
+	case RTC_AIE_ON:	/* alarm on */
+		rtc_control |= RTC_AIE;
+		break;
+	case RTC_UIE_OFF:	/* update off */
+		rtc_control &= ~RTC_UIE;
+		break;
+	case RTC_UIE_ON:	/* update on */
+		rtc_control |= RTC_UIE;
+		break;
+	case RTC_PIE_OFF:	/* periodic off */
+		rtc_control &= ~RTC_PIE;
+		break;
+	case RTC_PIE_ON:	/* periodic on */
+		rtc_control |= RTC_PIE;
+		break;
+	}
+	CMOS_WRITE(rtc_control, RTC_CONTROL);
+	rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
+	if (rtc_intr)
+		rtc_update_irq(&cmos->rtc->class_dev, 1, rtc_intr);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return 0;
+}
+
+#else
+#define	cmos_rtc_ioctl	NULL
+#endif
+
+#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
+
+static int cmos_procfs(struct device *dev, struct seq_file *seq)
+{
+	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
+	unsigned char	rtc_control, valid;
+
+	spin_lock_irq(&rtc_lock);
+	rtc_control = CMOS_READ(RTC_CONTROL);
+	valid = CMOS_READ(RTC_VALID);
+	spin_unlock_irq(&rtc_lock);
+
+	/* NOTE:  at least ICH6 reports battery status using a different
+	 * (non-RTC) bit; and SQWE is ignored on many current systems.
+	 */
+	return seq_printf(seq,
+			"periodic_IRQ\t: %s\n"
+			"update_IRQ\t: %s\n"
+			// "square_wave\t: %s\n"
+			// "BCD\t\t: %s\n"
+			"DST_enable\t: %s\n"
+			"periodic_freq\t: %d\n"
+			"batt_status\t: %s\n",
+			(rtc_control & RTC_PIE) ? "yes" : "no",
+			(rtc_control & RTC_UIE) ? "yes" : "no",
+			// (rtc_control & RTC_SQWE) ? "yes" : "no",
+			// (rtc_control & RTC_DM_BINARY) ? "no" : "yes",
+			(rtc_control & RTC_DST_EN) ? "yes" : "no",
+			cmos->rtc->irq_freq,
+			(valid & RTC_VRT) ? "okay" : "dead");
+}
+
+#else
+#define	cmos_procfs	NULL
+#endif
+
+static const struct rtc_class_ops cmos_rtc_ops = {
+	.ioctl		= cmos_rtc_ioctl,
+	.read_time	= cmos_read_time,
+	.set_time	= cmos_set_time,
+	.read_alarm	= cmos_read_alarm,
+	.set_alarm	= cmos_set_alarm,
+	.proc		= cmos_procfs,
+	.irq_set_freq	= cmos_set_freq,
+};
+
+/*----------------------------------------------------------------*/
+
+static struct cmos_rtc	cmos_rtc;
+
+static irqreturn_t cmos_interrupt(int irq, void *p)
+{
+	u8		irqstat;
+
+	spin_lock(&rtc_lock);
+	irqstat = CMOS_READ(RTC_INTR_FLAGS);
+	spin_unlock(&rtc_lock);
+
+	if (irqstat) {
+		/* NOTE: irqstat may have e.g. RTC_PF set
+		 * even when RTC_PIE is clear...
+		 */
+		rtc_update_irq(p, 1, irqstat);
+		return IRQ_HANDLED;
+	} else
+		return IRQ_NONE;
+}
+
+#ifdef	CONFIG_PNPACPI
+#define	is_pnpacpi()	1
+#define	INITSECTION
+
+#else
+#define	is_pnpacpi()	0
+#define	INITSECTION	__init
+#endif
+
+static int INITSECTION
+cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
+{
+	struct cmos_rtc_board_info	*info = dev->platform_data;
+	int				retval = 0;
+	unsigned char			rtc_control;
+
+	/* there can be only one ... */
+	if (cmos_rtc.dev)
+		return -EBUSY;
+
+	if (!ports)
+		return -ENODEV;
+
+	cmos_rtc.irq = rtc_irq;
+	cmos_rtc.iomem = ports;
+
+	/* For ACPI systems the info comes from the FADT.  On others,
+	 * board specific setup provides it as appropriate.
+	 */
+	if (info) {
+		cmos_rtc.day_alrm = info->rtc_day_alarm;
+		cmos_rtc.mon_alrm = info->rtc_mon_alarm;
+		cmos_rtc.century = info->rtc_century;
+	}
+
+	cmos_rtc.rtc = rtc_device_register(driver_name, dev,
+				&cmos_rtc_ops, THIS_MODULE);
+	if (IS_ERR(cmos_rtc.rtc))
+		return PTR_ERR(cmos_rtc.rtc);
+
+	cmos_rtc.dev = dev;
+	dev_set_drvdata(dev, &cmos_rtc);
+
+	/* platform and pnp busses handle resources incompatibly.
+	 *
+	 * REVISIT for non-x86 systems we may need to handle io memory
+	 * resources: ioremap them, and request_mem_region().
+	 */
+	if (is_pnpacpi()) {
+		retval = request_resource(&ioport_resource, ports);
+		if (retval < 0) {
+			dev_dbg(dev, "i/o registers already in use\n");
+			goto cleanup0;
+		}
+	}
+	rename_region(ports, cmos_rtc.rtc->class_dev.class_id);
+
+	spin_lock_irq(&rtc_lock);
+
+	/* force periodic irq to CMOS reset default of 1024Hz;
+	 *
+	 * REVISIT it's been reported that at least one x86_64 ALI mobo
+	 * doesn't use 32KHz here ... for portability we might need to
+	 * do something about other clock frequencies.
+	 */
+	CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
+	cmos_rtc.rtc->irq_freq = 1024;
+
+	/* disable irqs.
+	 *
+	 * NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
+	 * allegedly some older rtcs need that to handle irqs properly
+	 */
+	rtc_control = CMOS_READ(RTC_CONTROL);
+	rtc_control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
+	CMOS_WRITE(rtc_control, RTC_CONTROL);
+	CMOS_READ(RTC_INTR_FLAGS);
+
+	spin_unlock_irq(&rtc_lock);
+
+	/* FIXME teach the alarm code how to handle binary mode;
+	 * <asm-generic/rtc.h> doesn't know 12-hour mode either.
+	 */
+	if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) {
+		dev_dbg(dev, "only 24-hr BCD mode supported\n");
+		retval = -ENXIO;
+		goto cleanup1;
+	}
+
+	if (is_valid_irq(rtc_irq))
+		retval = request_irq(rtc_irq, cmos_interrupt, IRQF_DISABLED,
+				cmos_rtc.rtc->class_dev.class_id,
+				&cmos_rtc.rtc->class_dev);
+	if (retval < 0) {
+		dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
+		goto cleanup1;
+	}
+
+	/* REVISIT optionally make 50 or 114 bytes NVRAM available,
+	 * like rtc-ds1553, rtc-ds1742 ... this will often include
+	 * registers for century, and day/month alarm.
+	 */
+
+	pr_info("%s: alarms up to one %s%s\n",
+			cmos_rtc.rtc->class_dev.class_id,
+			is_valid_irq(rtc_irq)
+				?  (cmos_rtc.mon_alrm
+					? "year"
+					: (cmos_rtc.day_alrm
+						? "month" : "day"))
+				: "no",
+			cmos_rtc.century ? ", y3k" : ""
+			);
+
+	return 0;
+
+cleanup1:
+	rename_region(ports, NULL);
+cleanup0:
+	rtc_device_unregister(cmos_rtc.rtc);
+	return retval;
+}
+
+static void cmos_do_shutdown(void)
+{
+	unsigned char	rtc_control;
+
+	spin_lock_irq(&rtc_lock);
+	rtc_control = CMOS_READ(RTC_CONTROL);
+	rtc_control &= ~(RTC_PIE|RTC_AIE|RTC_UIE);
+	CMOS_WRITE(rtc_control, RTC_CONTROL);
+	CMOS_READ(RTC_INTR_FLAGS);
+	spin_unlock_irq(&rtc_lock);
+}
+
+static void __exit cmos_do_remove(struct device *dev)
+{
+	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
+
+	cmos_do_shutdown();
+
+	if (is_pnpacpi())
+		release_resource(cmos->iomem);
+	rename_region(cmos->iomem, NULL);
+
+	if (is_valid_irq(cmos->irq))
+		free_irq(cmos->irq, &cmos_rtc.rtc->class_dev);
+
+	rtc_device_unregister(cmos_rtc.rtc);
+
+	cmos_rtc.dev = NULL;
+	dev_set_drvdata(dev, NULL);
+}
+
+#ifdef	CONFIG_PM
+
+static int cmos_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
+	int		do_wake = device_may_wakeup(dev);
+	unsigned char	tmp, irqstat;
+
+	/* only the alarm might be a wakeup event source */
+	spin_lock_irq(&rtc_lock);
+	cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL);
+	if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
+		if (do_wake)
+			tmp &= ~(RTC_PIE|RTC_UIE);
+		else
+			tmp &= ~(RTC_PIE|RTC_AIE|RTC_UIE);
+		CMOS_WRITE(tmp, RTC_CONTROL);
+		irqstat = CMOS_READ(RTC_INTR_FLAGS);
+	} else
+		irqstat = 0;
+	spin_unlock_irq(&rtc_lock);
+
+	if (irqstat)
+		rtc_update_irq(&cmos->rtc->class_dev, 1, irqstat);
+
+	/* ACPI HOOK:  enable ACPI_EVENT_RTC when (tmp & RTC_AIE)
+	 * ... it'd be best if we could do that under rtc_lock.
+	 */
+
+	pr_debug("%s: suspend%s, ctrl %02x\n",
+			cmos_rtc.rtc->class_dev.class_id,
+			(tmp & RTC_AIE) ? ", alarm may wake" : "",
+			tmp);
+
+	return 0;
+}
+
+static int cmos_resume(struct device *dev)
+{
+	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
+	unsigned char	tmp = cmos->suspend_ctrl;
+
+	/* REVISIT:  a mechanism to resync the system clock (jiffies)
+	 * on resume should be portable between platforms ...
+	 */
+
+	/* re-enable any irqs previously active */
+	if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
+
+		/* ACPI HOOK:  disable ACPI_EVENT_RTC when (tmp & RTC_AIE) */
+
+		spin_lock_irq(&rtc_lock);
+		CMOS_WRITE(tmp, RTC_CONTROL);
+		tmp = CMOS_READ(RTC_INTR_FLAGS);
+		spin_unlock_irq(&rtc_lock);
+		if (tmp)
+			rtc_update_irq(&cmos->rtc->class_dev, 1, tmp);
+	}
+
+	pr_debug("%s: resume, ctrl %02x\n",
+			cmos_rtc.rtc->class_dev.class_id,
+			cmos->suspend_ctrl);
+
+
+	return 0;
+}
+
+#else
+#define	cmos_suspend	NULL
+#define	cmos_resume	NULL
+#endif
+
+/*----------------------------------------------------------------*/
+
+/* The "CMOS" RTC normally lives on the platform_bus.  On ACPI systems,
+ * the device node may alternatively be created as a PNP device.
+ */
+
+#ifdef	CONFIG_PNPACPI
+
+#include <linux/pnp.h>
+
+static int __devinit
+cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
+{
+	/* REVISIT paranoia argues for a shutdown notifier, since PNP
+	 * drivers can't provide shutdown() methods to disable IRQs.
+	 * Or better yet, fix PNP to allow those methods...
+	 */
+	return cmos_do_probe(&pnp->dev,
+			&pnp->res.port_resource[0],
+			pnp->res.irq_resource[0].start);
+}
+
+static void __exit cmos_pnp_remove(struct pnp_dev *pnp)
+{
+	cmos_do_remove(&pnp->dev);
+}
+
+#ifdef	CONFIG_PM
+
+static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg)
+{
+	return cmos_suspend(&pnp->dev, mesg);
+}
+
+static int cmos_pnp_resume(struct pnp_dev *pnp)
+{
+	return cmos_resume(&pnp->dev);
+}
+
+#else
+#define	cmos_pnp_suspend	NULL
+#define	cmos_pnp_resume		NULL
+#endif
+
+
+static const struct pnp_device_id rtc_ids[] = {
+	{ .id = "PNP0b00", },
+	{ .id = "PNP0b01", },
+	{ .id = "PNP0b02", },
+	{ },
+};
+MODULE_DEVICE_TABLE(pnp, rtc_ids);
+
+static struct pnp_driver cmos_pnp_driver = {
+	.name		= (char *) driver_name,
+	.id_table	= rtc_ids,
+	.probe		= cmos_pnp_probe,
+	.remove		= __exit_p(cmos_pnp_remove),
+
+	/* flag ensures resume() gets called, and stops syslog spam */
+	.flags		= PNP_DRIVER_RES_DO_NOT_CHANGE,
+	.suspend	= cmos_pnp_suspend,
+	.resume		= cmos_pnp_resume,
+};
+
+static int __init cmos_init(void)
+{
+	return pnp_register_driver(&cmos_pnp_driver);
+}
+module_init(cmos_init);
+
+static void __exit cmos_exit(void)
+{
+	pnp_unregister_driver(&cmos_pnp_driver);
+}
+module_exit(cmos_exit);
+
+#else	/* no PNPACPI */
+
+/*----------------------------------------------------------------*/
+
+/* Platform setup should have set up an RTC device, when PNPACPI is
+ * unavailable ... this is the normal case, common even on PCs.
+ */
+
+static int __init cmos_platform_probe(struct platform_device *pdev)
+{
+	return cmos_do_probe(&pdev->dev,
+			platform_get_resource(pdev, IORESOURCE_IO, 0),
+			platform_get_irq(pdev, 0));
+}
+
+static int __exit cmos_platform_remove(struct platform_device *pdev)
+{
+	cmos_do_remove(&pdev->dev);
+	return 0;
+}
+
+static void cmos_platform_shutdown(struct platform_device *pdev)
+{
+	cmos_do_shutdown();
+}
+
+static struct platform_driver cmos_platform_driver = {
+	.remove		= __exit_p(cmos_platform_remove),
+	.shutdown	= cmos_platform_shutdown,
+	.driver = {
+		.name		= (char *) driver_name,
+		.suspend	= cmos_suspend,
+		.resume		= cmos_resume,
+	}
+};
+
+static int __init cmos_init(void)
+{
+	return platform_driver_probe(&cmos_platform_driver,
+			cmos_platform_probe);
+}
+module_init(cmos_init);
+
+static void __exit cmos_exit(void)
+{
+	platform_driver_unregister(&cmos_platform_driver);
+}
+module_exit(cmos_exit);
+
+
+#endif	/* !PNPACPI */
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("Driver for PC-style 'CMOS' RTCs");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 94d3df6..137330b 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -305,7 +305,7 @@
 
 	case RTC_IRQP_READ:
 		if (ops->irq_set_freq)
-			err = put_user(rtc->irq_freq, (unsigned long *) arg);
+			err = put_user(rtc->irq_freq, (unsigned long __user *)uarg);
 		break;
 
 	case RTC_IRQP_SET:
@@ -384,7 +384,7 @@
 	return fasync_helper(fd, file, on, &rtc->async_queue);
 }
 
-static struct file_operations rtc_dev_fops = {
+static const struct file_operations rtc_dev_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= rtc_dev_read,
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 001eb11..e27176c 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -297,7 +297,7 @@
 	.write = ds1553_nvram_write,
 };
 
-static int __init ds1553_rtc_probe(struct platform_device *pdev)
+static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 	struct resource *res;
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 205fa28..dfef163 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -199,7 +199,7 @@
 	struct i2c_client *client;
 	struct rtc_device *rtc;
 
-	dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
+	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
 		err = -ENODEV;
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 17633bf..d68288b 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -165,7 +165,7 @@
 	.write = ds1742_nvram_write,
 };
 
-static int __init ds1742_rtc_probe(struct platform_device *pdev)
+static int __devinit ds1742_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 	struct resource *res;
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index d59880d..9de8d67 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -417,13 +417,13 @@
 		rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
 
 	/* handle periodic and alarm irqs */
-	if (request_irq(omap_rtc_timer, rtc_irq, SA_INTERRUPT,
+	if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED,
 			rtc->class_dev.class_id, &rtc->class_dev)) {
 		pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
 			pdev->name, omap_rtc_timer);
 		goto fail0;
 	}
-	if (request_irq(omap_rtc_alarm, rtc_irq, SA_INTERRUPT,
+	if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED,
 			rtc->class_dev.class_id, &rtc->class_dev)) {
 		pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
 			pdev->name, omap_rtc_alarm);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 4b72b8e..0242d80 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -53,6 +53,25 @@
 #define PCF8563_SC_LV		0x80 /* low voltage */
 #define PCF8563_MO_C		0x80 /* century */
 
+struct pcf8563 {
+	struct i2c_client client;
+	/*
+	 * The meaning of MO_C bit varies by the chip type.
+	 * From PCF8563 datasheet: this bit is toggled when the years
+	 * register overflows from 99 to 00
+	 *   0 indicates the century is 20xx
+	 *   1 indicates the century is 19xx
+	 * From RTC8564 datasheet: this bit indicates change of
+	 * century. When the year digit data overflows from 99 to 00,
+	 * this bit is set. By presetting it to 0 while still in the
+	 * 20th century, it will be set in year 2000, ...
+	 * There seems no reliable way to know how the system use this
+	 * bit.  So let's do it heuristically, assuming we are live in
+	 * 1970...2069.
+	 */
+	int c_polarity;	/* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
+};
+
 static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind);
 static int pcf8563_detach(struct i2c_client *client);
 
@@ -62,6 +81,7 @@
  */
 static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
+	struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
 	unsigned char buf[13] = { PCF8563_REG_ST1 };
 
 	struct i2c_msg msgs[] = {
@@ -94,8 +114,12 @@
 	tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F);
 	tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
 	tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
-	tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR])
-		+ (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 0 : 100);
+	tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]);
+	if (tm->tm_year < 70)
+		tm->tm_year += 100;	/* assume we are in 1970...2069 */
+	/* detect the polarity heuristically. see note above. */
+	pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
+		(tm->tm_year >= 100) : (tm->tm_year < 100);
 
 	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
 		"mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -114,6 +138,7 @@
 
 static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
+	struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
 	int i, err;
 	unsigned char buf[9];
 
@@ -135,7 +160,7 @@
 
 	/* year and century */
 	buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100);
-	if (tm->tm_year < 100)
+	if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
 		buf[PCF8563_REG_MO] |= PCF8563_MO_C;
 
 	buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
@@ -248,23 +273,25 @@
 
 static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
 {
+	struct pcf8563 *pcf8563;
 	struct i2c_client *client;
 	struct rtc_device *rtc;
 
 	int err = 0;
 
-	dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
+	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
 		err = -ENODEV;
 		goto exit;
 	}
 
-	if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+	if (!(pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
 
+	client = &pcf8563->client;
 	client->addr = address;
 	client->driver = &pcf8563_driver;
 	client->adapter	= adapter;
@@ -301,7 +328,7 @@
 	i2c_detach_client(client);
 
 exit_kfree:
-	kfree(client);
+	kfree(pcf8563);
 
 exit:
 	return err;
@@ -309,6 +336,7 @@
 
 static int pcf8563_detach(struct i2c_client *client)
 {
+	struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
 	int err;
 	struct rtc_device *rtc = i2c_get_clientdata(client);
 
@@ -318,7 +346,7 @@
 	if ((err = i2c_detach_client(client)))
 		return err;
 
-	kfree(client);
+	kfree(pcf8563);
 
 	return 0;
 }
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index c272afd..1bd624f 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -96,7 +96,7 @@
 	return res;
 }
 
-static struct file_operations rtc_proc_fops = {
+static const struct file_operations rtc_proc_fops = {
 	.open		= rtc_proc_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index e7851e3..09bbe575 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -499,7 +499,7 @@
 	struct rs5c372 *rs5c372;
 	struct rtc_time tm;
 
-	dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
+	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
 		err = -ENODEV;
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index f406a2b..9a79a24 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -350,7 +350,7 @@
 	int ret;
 
 	ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
-			  SA_INTERRUPT,  "s3c2410-rtc alarm", rtc_dev);
+			  IRQF_DISABLED,  "s3c2410-rtc alarm", rtc_dev);
 
 	if (ret) {
 		dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
@@ -358,7 +358,7 @@
 	}
 
 	ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
-			  SA_INTERRUPT,  "s3c2410-rtc tick", rtc_dev);
+			  IRQF_DISABLED,  "s3c2410-rtc tick", rtc_dev);
 
 	if (ret) {
 		dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 9c8ead4..677bae8 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -263,8 +263,12 @@
 
 static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
+	u32	rtsr;
+
 	memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
-	alrm->pending = RTSR & RTSR_AL ? 1 : 0;
+	rtsr = RTSR;
+	alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
+	alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
 	return 0;
 }
 
@@ -275,12 +279,10 @@
 	spin_lock_irq(&sa1100_rtc_lock);
 	ret = rtc_update_alarm(&alrm->time);
 	if (ret == 0) {
-		memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time));
-
 		if (alrm->enabled)
-			enable_irq_wake(IRQ_RTCAlrm);
+			RTSR |= RTSR_ALE;
 		else
-			disable_irq_wake(IRQ_RTCAlrm);
+			RTSR &= ~RTSR_ALE;
 	}
 	spin_unlock_irq(&sa1100_rtc_lock);
 
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 2ddd0cf..899ab8c 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -78,6 +78,92 @@
 	.attrs = rtc_attrs,
 };
 
+
+static ssize_t
+rtc_sysfs_show_wakealarm(struct class_device *dev, char *buf)
+{
+	ssize_t retval;
+	unsigned long alarm;
+	struct rtc_wkalrm alm;
+
+	/* Don't show disabled alarms; but the RTC could leave the
+	 * alarm enabled after it's already triggered.  Alarms are
+	 * conceptually one-shot, even though some common hardware
+	 * (PCs) doesn't actually work that way.
+	 *
+	 * REVISIT maybe we should require RTC implementations to
+	 * disable the RTC alarm after it triggers, for uniformity.
+	 */
+	retval = rtc_read_alarm(dev, &alm);
+	if (retval == 0 && alm.enabled) {
+		rtc_tm_to_time(&alm.time, &alarm);
+		retval = sprintf(buf, "%lu\n", alarm);
+	}
+
+	return retval;
+}
+
+static ssize_t
+rtc_sysfs_set_wakealarm(struct class_device *dev, const char *buf, size_t n)
+{
+	ssize_t retval;
+	unsigned long now, alarm;
+	struct rtc_wkalrm alm;
+
+	/* Only request alarms that trigger in the future.  Disable them
+	 * by writing another time, e.g. 0 meaning Jan 1 1970 UTC.
+	 */
+	retval = rtc_read_time(dev, &alm.time);
+	if (retval < 0)
+		return retval;
+	rtc_tm_to_time(&alm.time, &now);
+
+	alarm = simple_strtoul(buf, NULL, 0);
+	if (alarm > now) {
+		/* Avoid accidentally clobbering active alarms; we can't
+		 * entirely prevent that here, without even the minimal
+		 * locking from the /dev/rtcN api.
+		 */
+		retval = rtc_read_alarm(dev, &alm);
+		if (retval < 0)
+			return retval;
+		if (alm.enabled)
+			return -EBUSY;
+
+		alm.enabled = 1;
+	} else {
+		alm.enabled = 0;
+
+		/* Provide a valid future alarm time.  Linux isn't EFI,
+		 * this time won't be ignored when disabling the alarm.
+		 */
+		alarm = now + 300;
+	}
+	rtc_time_to_tm(alarm, &alm.time);
+
+	retval = rtc_set_alarm(dev, &alm);
+	return (retval < 0) ? retval : n;
+}
+static const CLASS_DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR,
+		rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm);
+
+
+/* The reason to trigger an alarm with no process watching it (via sysfs)
+ * is its side effect:  waking from a system state like suspend-to-RAM or
+ * suspend-to-disk.  So: no attribute unless that side effect is possible.
+ * (Userspace may disable that mechanism later.)
+ */
+static inline int rtc_does_wakealarm(struct class_device *class_dev)
+{
+	struct rtc_device *rtc;
+
+	if (!device_can_wakeup(class_dev->dev))
+		return 0;
+	rtc = to_rtc_device(class_dev);
+	return rtc->ops->set_alarm != NULL;
+}
+
+
 static int rtc_sysfs_add_device(struct class_device *class_dev,
 					struct class_interface *class_intf)
 {
@@ -87,8 +173,18 @@
 
 	err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group);
 	if (err)
-		dev_err(class_dev->dev,
-			"failed to create sysfs attributes\n");
+		dev_err(class_dev->dev, "failed to create %s\n",
+				"sysfs attributes");
+	else if (rtc_does_wakealarm(class_dev)) {
+		/* not all RTCs support both alarms and wakeup */
+		err = class_device_create_file(class_dev,
+					&class_device_attr_wakealarm);
+		if (err) {
+			dev_err(class_dev->dev, "failed to create %s\n",
+					"alarm attribute");
+			sysfs_remove_group(&class_dev->kobj, &rtc_attr_group);
+		}
+	}
 
 	return err;
 }
@@ -96,6 +192,9 @@
 static void rtc_sysfs_remove_device(struct class_device *class_dev,
 				struct class_interface *class_intf)
 {
+	if (rtc_does_wakealarm(class_dev))
+		class_device_remove_file(class_dev,
+				&class_device_attr_wakealarm);
 	sysfs_remove_group(&class_dev->kobj, &rtc_attr_group);
 }
 
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index 019ae25..513d1a6 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -506,7 +506,7 @@
 	struct i2c_client *client;
 	struct rtc_device *rtc;
 
-	dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
+	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
 		err = -ENODEV;
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 6cedc91..4b8a95f 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -650,7 +650,7 @@
 	return mask;
 }
 
-static struct file_operations dasd_eer_fops = {
+static const struct file_operations dasd_eer_fops = {
 	.open		= &dasd_eer_open,
 	.release	= &dasd_eer_close,
 	.read		= &dasd_eer_read,
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 8b7e118..8b3b0f4 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -147,7 +147,7 @@
 	return seq_open(file, &dasd_devices_seq_ops);
 }
 
-static struct file_operations dasd_devices_file_ops = {
+static const struct file_operations dasd_devices_file_ops = {
 	.open		= dasd_devices_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index e1a7462..ef36f213 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -493,7 +493,7 @@
 	return 0;
 }
 
-static struct file_operations fs3270_fops = {
+static const struct file_operations fs3270_fops = {
 	.owner		 = THIS_MODULE,		/* owner */
 	.read		 = fs3270_read,		/* read */
 	.write		 = fs3270_write,	/* write */
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index a138b15..8df7b13 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -3,7 +3,7 @@
  *
  * Character device driver for reading z/VM *MONITOR service records.
  *
- * Copyright (C) 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Copyright 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
  *
  * Author: Gerald Schaefer <geraldsc@de.ibm.com>
  */
@@ -22,7 +22,7 @@
 #include <asm/ebcdic.h>
 #include <asm/extmem.h>
 #include <linux/poll.h>
-#include "../net/iucv.h"
+#include <net/iucv/iucv.h>
 
 
 //#define MON_DEBUG			/* Debug messages on/off */
@@ -50,14 +50,13 @@
 struct mon_msg {
 	u32 pos;
 	u32 mca_offset;
-	iucv_MessagePending local_eib;
+	struct iucv_message msg;
 	char msglim_reached;
 	char replied_msglim;
 };
 
 struct mon_private {
-	u16 pathid;
-	iucv_handle_t iucv_handle;
+	struct iucv_path *path;
 	struct mon_msg *msg_array[MON_MSGLIM];
 	unsigned int   write_index;
 	unsigned int   read_index;
@@ -75,8 +74,6 @@
 static DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue);
 static DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue);
 
-static u8 iucv_host[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
 static u8 user_data_connect[16] = {
 	/* Version code, must be 0x01 for shared mode */
 	0x01,
@@ -100,8 +97,7 @@
  * Create the 8 bytes EBCDIC DCSS segment name from
  * an ASCII name, incl. padding
  */
-static inline void
-dcss_mkname(char *ascii_name, char *ebcdic_name)
+static inline void dcss_mkname(char *ascii_name, char *ebcdic_name)
 {
 	int i;
 
@@ -119,8 +115,7 @@
  * print appropriate error message for segment_load()/segment_type()
  * return code
  */
-static void
-mon_segment_warn(int rc, char* seg_name)
+static void mon_segment_warn(int rc, char* seg_name)
 {
 	switch (rc) {
 	case -ENOENT:
@@ -166,44 +161,37 @@
 	}
 }
 
-static inline unsigned long
-mon_mca_start(struct mon_msg *monmsg)
+static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
 {
-	return monmsg->local_eib.ln1msg1.iprmmsg1_u32;
+	return *(u32 *) &monmsg->msg.rmmsg;
 }
 
-static inline unsigned long
-mon_mca_end(struct mon_msg *monmsg)
+static inline unsigned long mon_mca_end(struct mon_msg *monmsg)
 {
-	return monmsg->local_eib.ln1msg2.ipbfln1f;
+	return *(u32 *) &monmsg->msg.rmmsg[4];
 }
 
-static inline u8
-mon_mca_type(struct mon_msg *monmsg, u8 index)
+static inline u8 mon_mca_type(struct mon_msg *monmsg, u8 index)
 {
 	return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index);
 }
 
-static inline u32
-mon_mca_size(struct mon_msg *monmsg)
+static inline u32 mon_mca_size(struct mon_msg *monmsg)
 {
 	return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1;
 }
 
-static inline u32
-mon_rec_start(struct mon_msg *monmsg)
+static inline u32 mon_rec_start(struct mon_msg *monmsg)
 {
 	return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4));
 }
 
-static inline u32
-mon_rec_end(struct mon_msg *monmsg)
+static inline u32 mon_rec_end(struct mon_msg *monmsg)
 {
 	return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8));
 }
 
-static inline int
-mon_check_mca(struct mon_msg *monmsg)
+static inline int mon_check_mca(struct mon_msg *monmsg)
 {
 	if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
 	    (mon_rec_start(monmsg) < mon_dcss_start) ||
@@ -221,20 +209,17 @@
 	return 0;
 }
 
-static inline int
-mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv)
+static inline int mon_send_reply(struct mon_msg *monmsg,
+				 struct mon_private *monpriv)
 {
-	u8 prmmsg[8];
 	int rc;
 
 	P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
 		"0x%08X\n\n",
-		monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid,
-		monmsg->local_eib.iptrgcls);
-	rc = iucv_reply_prmmsg(monmsg->local_eib.ippathid,
-				monmsg->local_eib.ipmsgid,
-				monmsg->local_eib.iptrgcls,
-				0, prmmsg);
+		monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
+
+	rc = iucv_message_reply(monpriv->path, &monmsg->msg,
+				IUCV_IPRMDATA, NULL, 0);
 	atomic_dec(&monpriv->msglim_count);
 	if (likely(!monmsg->msglim_reached)) {
 		monmsg->pos = 0;
@@ -251,10 +236,19 @@
 	return 0;
 }
 
-static inline struct mon_private *
-mon_alloc_mem(void)
+static inline void mon_free_mem(struct mon_private *monpriv)
 {
-	int i,j;
+	int i;
+
+	for (i = 0; i < MON_MSGLIM; i++)
+		if (monpriv->msg_array[i])
+			kfree(monpriv->msg_array[i]);
+	kfree(monpriv);
+}
+
+static inline struct mon_private *mon_alloc_mem(void)
+{
+	int i;
 	struct mon_private *monpriv;
 
 	monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
@@ -267,16 +261,15 @@
 						    GFP_KERNEL);
 		if (!monpriv->msg_array[i]) {
 			P_ERROR("open, no memory for msg_array\n");
-			for (j = 0; j < i; j++)
-				kfree(monpriv->msg_array[j]);
+			mon_free_mem(monpriv);
 			return NULL;
 		}
 	}
 	return monpriv;
 }
 
-static inline void
-mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
+static inline void mon_read_debug(struct mon_msg *monmsg,
+				  struct mon_private *monpriv)
 {
 #ifdef MON_DEBUG
 	u8 msg_type[2], mca_type;
@@ -284,7 +277,7 @@
 
 	records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;
 
-	memcpy(msg_type, &monmsg->local_eib.iptrgcls, 2);
+	memcpy(msg_type, &monmsg->msg.class, 2);
 	EBCASC(msg_type, 2);
 	mca_type = mon_mca_type(monmsg, 0);
 	EBCASC(&mca_type, 1);
@@ -292,8 +285,7 @@
 	P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
 		monpriv->read_index, monpriv->write_index);
 	P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
-		monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid,
-		monmsg->local_eib.iptrgcls);
+		monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
 	P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",
 		msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
 		mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
@@ -306,8 +298,7 @@
 #endif
 }
 
-static inline void
-mon_next_mca(struct mon_msg *monmsg)
+static inline void mon_next_mca(struct mon_msg *monmsg)
 {
 	if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
 		return;
@@ -316,8 +307,7 @@
 	monmsg->pos = 0;
 }
 
-static inline struct mon_msg *
-mon_next_message(struct mon_private *monpriv)
+static inline struct mon_msg *mon_next_message(struct mon_private *monpriv)
 {
 	struct mon_msg *monmsg;
 
@@ -342,39 +332,37 @@
 /******************************************************************************
  *                               IUCV handler                                 *
  *****************************************************************************/
-static void
-mon_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data)
+static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
 {
-	struct mon_private *monpriv = (struct mon_private *) pgm_data;
+	struct mon_private *monpriv = path->private;
 
 	P_DEBUG("IUCV connection completed\n");
 	P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
 		"0x%02X, Sample = 0x%02X\n",
-		eib->ipuser[0], eib->ipuser[1], eib->ipuser[2]);
+		ipuser[0], ipuser[1], ipuser[2]);
 	atomic_set(&monpriv->iucv_connected, 1);
 	wake_up(&mon_conn_wait_queue);
 }
 
-static void
-mon_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data)
+static void mon_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
 {
-	struct mon_private *monpriv = (struct mon_private *) pgm_data;
+	struct mon_private *monpriv = path->private;
 
-	P_ERROR("IUCV connection severed with rc = 0x%X\n",
-		(u8) eib->ipuser[0]);
+	P_ERROR("IUCV connection severed with rc = 0x%X\n", ipuser[0]);
+	iucv_path_sever(path, NULL);
 	atomic_set(&monpriv->iucv_severed, 1);
 	wake_up(&mon_conn_wait_queue);
 	wake_up_interruptible(&mon_read_wait_queue);
 }
 
-static void
-mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data)
+static void mon_iucv_message_pending(struct iucv_path *path,
+				     struct iucv_message *msg)
 {
-	struct mon_private *monpriv = (struct mon_private *) pgm_data;
+	struct mon_private *monpriv = path->private;
 
 	P_DEBUG("IUCV message pending\n");
-	memcpy(&monpriv->msg_array[monpriv->write_index]->local_eib, eib,
-	       sizeof(iucv_MessagePending));
+	memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
+	       msg, sizeof(*msg));
 	if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
 		P_WARNING("IUCV message pending, message limit (%i) reached\n",
 			  MON_MSGLIM);
@@ -385,54 +373,45 @@
 	wake_up_interruptible(&mon_read_wait_queue);
 }
 
-static iucv_interrupt_ops_t mon_iucvops = {
-	.ConnectionComplete = mon_iucv_ConnectionComplete,
-	.ConnectionSevered  = mon_iucv_ConnectionSevered,
-	.MessagePending     = mon_iucv_MessagePending,
+static struct iucv_handler monreader_iucv_handler = {
+	.path_complete	 = mon_iucv_path_complete,
+	.path_severed	 = mon_iucv_path_severed,
+	.message_pending = mon_iucv_message_pending,
 };
 
 /******************************************************************************
  *                               file operations                              *
  *****************************************************************************/
-static int
-mon_open(struct inode *inode, struct file *filp)
+static int mon_open(struct inode *inode, struct file *filp)
 {
-	int rc, i;
 	struct mon_private *monpriv;
+	int rc;
 
 	/*
 	 * only one user allowed
 	 */
+	rc = -EBUSY;
 	if (test_and_set_bit(MON_IN_USE, &mon_in_use))
-		return -EBUSY;
+		goto out;
 
+	rc = -ENOMEM;
 	monpriv = mon_alloc_mem();
 	if (!monpriv)
-		return -ENOMEM;
+		goto out_use;
 
 	/*
-	 * Register with IUCV and connect to *MONITOR service
+	 * Connect to *MONITOR service
 	 */
-	monpriv->iucv_handle = iucv_register_program("my_monreader    ",
-							MON_SERVICE,
-							NULL,
-							&mon_iucvops,
-							monpriv);
-	if (!monpriv->iucv_handle) {
-		P_ERROR("failed to register with iucv driver\n");
-		rc = -EIO;
-		goto out_error;
-	}
-	P_INFO("open, registered with IUCV\n");
-
-	rc = iucv_connect(&monpriv->pathid, MON_MSGLIM, user_data_connect,
-			  MON_SERVICE, iucv_host, IPRMDATA, NULL, NULL,
-			  monpriv->iucv_handle, NULL);
+	monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL);
+	if (!monpriv->path)
+		goto out_priv;
+	rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler,
+			       MON_SERVICE, NULL, user_data_connect, monpriv);
 	if (rc) {
 		P_ERROR("iucv connection to *MONITOR failed with "
 			"IPUSER SEVER code = %i\n", rc);
 		rc = -EIO;
-		goto out_unregister;
+		goto out_path;
 	}
 	/*
 	 * Wait for connection confirmation
@@ -444,24 +423,23 @@
 		atomic_set(&monpriv->iucv_severed, 0);
 		atomic_set(&monpriv->iucv_connected, 0);
 		rc = -EIO;
-		goto out_unregister;
+		goto out_path;
 	}
 	P_INFO("open, established connection to *MONITOR service\n\n");
 	filp->private_data = monpriv;
 	return nonseekable_open(inode, filp);
 
-out_unregister:
-	iucv_unregister_program(monpriv->iucv_handle);
-out_error:
-	for (i = 0; i < MON_MSGLIM; i++)
-		kfree(monpriv->msg_array[i]);
-	kfree(monpriv);
+out_path:
+	kfree(monpriv->path);
+out_priv:
+	mon_free_mem(monpriv);
+out_use:
 	clear_bit(MON_IN_USE, &mon_in_use);
+out:
 	return rc;
 }
 
-static int
-mon_close(struct inode *inode, struct file *filp)
+static int mon_close(struct inode *inode, struct file *filp)
 {
 	int rc, i;
 	struct mon_private *monpriv = filp->private_data;
@@ -469,18 +447,12 @@
 	/*
 	 * Close IUCV connection and unregister
 	 */
-	rc = iucv_sever(monpriv->pathid, user_data_sever);
+	rc = iucv_path_sever(monpriv->path, user_data_sever);
 	if (rc)
 		P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
 	else
 		P_INFO("close, terminated connection to *MONITOR service\n");
 
-	rc = iucv_unregister_program(monpriv->iucv_handle);
-	if (rc)
-		P_ERROR("close, iucv_unregister failed with rc = %i\n", rc);
-	else
-		P_INFO("close, unregistered with IUCV\n");
-
 	atomic_set(&monpriv->iucv_severed, 0);
 	atomic_set(&monpriv->iucv_connected, 0);
 	atomic_set(&monpriv->read_ready, 0);
@@ -495,8 +467,8 @@
 	return 0;
 }
 
-static ssize_t
-mon_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
+static ssize_t mon_read(struct file *filp, char __user *data,
+			size_t count, loff_t *ppos)
 {
 	struct mon_private *monpriv = filp->private_data;
 	struct mon_msg *monmsg;
@@ -563,8 +535,7 @@
 	return count;
 }
 
-static unsigned int
-mon_poll(struct file *filp, struct poll_table_struct *p)
+static unsigned int mon_poll(struct file *filp, struct poll_table_struct *p)
 {
 	struct mon_private *monpriv = filp->private_data;
 
@@ -576,7 +547,7 @@
 	return 0;
 }
 
-static struct file_operations mon_fops = {
+static const struct file_operations mon_fops = {
 	.owner   = THIS_MODULE,
 	.open    = &mon_open,
 	.release = &mon_close,
@@ -593,8 +564,7 @@
 /******************************************************************************
  *                              module init/exit                              *
  *****************************************************************************/
-static int __init
-mon_init(void)
+static int __init mon_init(void)
 {
 	int rc;
 
@@ -603,22 +573,34 @@
 		return -ENODEV;
 	}
 
+	/*
+	 * Register with IUCV and connect to *MONITOR service
+	 */
+	rc = iucv_register(&monreader_iucv_handler, 1);
+	if (rc) {
+		P_ERROR("failed to register with iucv driver\n");
+		return rc;
+	}
+	P_INFO("open, registered with IUCV\n");
+
 	rc = segment_type(mon_dcss_name);
 	if (rc < 0) {
 		mon_segment_warn(rc, mon_dcss_name);
-		return rc;
+		goto out_iucv;
 	}
 	if (rc != SEG_TYPE_SC) {
 		P_ERROR("segment %s has unsupported type, should be SC\n",
 			mon_dcss_name);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out_iucv;
 	}
 
 	rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
 			  &mon_dcss_start, &mon_dcss_end);
 	if (rc < 0) {
 		mon_segment_warn(rc, mon_dcss_name);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out_iucv;
 	}
 	dcss_mkname(mon_dcss_name, &user_data_connect[8]);
 
@@ -634,14 +616,16 @@
 
 out:
 	segment_unload(mon_dcss_name);
+out_iucv:
+	iucv_unregister(&monreader_iucv_handler, 1);
 	return rc;
 }
 
-static void __exit
-mon_exit(void)
+static void __exit mon_exit(void)
 {
 	segment_unload(mon_dcss_name);
 	WARN_ON(misc_deregister(&mon_dev) != 0);
+	iucv_unregister(&monreader_iucv_handler, 1);
 	return;
 }
 
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 9e451ac..268598e 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -255,7 +255,7 @@
 	return rc;
 }
 
-static struct file_operations monwrite_fops = {
+static const struct file_operations monwrite_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = &monwrite_open,
 	.release = &monwrite_close,
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index ffa9282..baa8fe6 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -16,6 +16,7 @@
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/sigp.h>
+#include <asm/smp.h>
 
 #include "sclp.h"
 
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 90536f6..076816b 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -13,7 +13,6 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/err.h>
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 544f137..f77dc33 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -16,7 +16,6 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/major.h>
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 9faea04..b830a8c 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -39,7 +39,7 @@
 static long tapechar_compat_ioctl(struct file *, unsigned int,
 			  unsigned long);
 
-static struct file_operations tape_fops =
+static const struct file_operations tape_fops =
 {
 	.owner = THIS_MODULE,
 	.read = tapechar_read,
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 56b8761..2e0d297 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -36,7 +36,7 @@
 struct tape_class_device *register_tape_dev(
 	struct device *		device,
 	dev_t			dev,
-	struct file_operations *fops,
+	const struct file_operations *fops,
 	char *			device_name,
 	char *			mode_name)
 {
diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
index 3d0ca05..a8bd9b4 100644
--- a/drivers/s390/char/tape_class.h
+++ b/drivers/s390/char/tape_class.h
@@ -52,7 +52,7 @@
 struct tape_class_device *register_tape_dev(
 	struct device *		device,
 	dev_t			dev,
-	struct file_operations *fops,
+	const struct file_operations *fops,
 	char *			device_name,
 	char *			node_name
 );
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index 655d375..cea49f0 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -109,7 +109,7 @@
 	return seq_open(file, &tape_proc_seq);
 }
 
-static struct file_operations tape_proc_ops =
+static const struct file_operations tape_proc_ops =
 {
 	.open		= tape_proc_open,
 	.read		= seq_read,
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index a420cd0..fce3dac 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -173,7 +173,7 @@
 	}
 }
 
-static struct file_operations vmcp_fops = {
+static const struct file_operations vmcp_fops = {
 	.owner		= THIS_MODULE,
 	.open		= &vmcp_open,
 	.release	= &vmcp_release,
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 4f894dc..b87d3b0 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -3,7 +3,7 @@
  *	character device driver for reading z/VM system service records
  *
  *
- *	Copyright (C) 2004 IBM Corporation
+ *	Copyright 2004 IBM Corporation
  *	character device driver for reading z/VM system service records,
  *	Version 1.0
  *	Author(s): Xenia Tkatschow <xenia@us.ibm.com>
@@ -21,7 +21,7 @@
 #include <asm/cpcmd.h>
 #include <asm/debug.h>
 #include <asm/ebcdic.h>
-#include "../net/iucv.h"
+#include <net/iucv/iucv.h>
 #include <linux/kmod.h>
 #include <linux/cdev.h>
 #include <linux/device.h>
@@ -60,12 +60,11 @@
 	char system_service[8];
 	char internal_name[8];
 	char recording_name[8];
-	u16 pathid;
+	struct iucv_path *path;
 	int connection_established;
 	int iucv_path_severed;
-	iucv_MessagePending local_interrupt_buffer;
+	struct iucv_message local_interrupt_buffer;
 	atomic_t receive_ready;
-	iucv_handle_t iucv_handle;
 	int minor_num;
 	char * buffer;
 	char * current_position;
@@ -89,7 +88,7 @@
 static ssize_t vmlogrdr_read (struct file *filp, char __user *data,
 			      size_t count, loff_t * ppos);
 
-static struct file_operations vmlogrdr_fops = {
+static const struct file_operations vmlogrdr_fops = {
 	.owner   = THIS_MODULE,
 	.open    = vmlogrdr_open,
 	.release = vmlogrdr_release,
@@ -97,37 +96,19 @@
 };
 
 
-static u8 iucvMagic[16] = {
-	0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
-	0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
+static void vmlogrdr_iucv_path_complete(struct iucv_path *, u8 ipuser[16]);
+static void vmlogrdr_iucv_path_severed(struct iucv_path *, u8 ipuser[16]);
+static void vmlogrdr_iucv_message_pending(struct iucv_path *,
+					  struct iucv_message *);
+
+
+static struct iucv_handler vmlogrdr_iucv_handler = {
+	.path_complete	 = vmlogrdr_iucv_path_complete,
+	.path_severed	 = vmlogrdr_iucv_path_severed,
+	.message_pending = vmlogrdr_iucv_message_pending,
 };
 
 
-static u8 mask[] = {
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-
-static u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-
-static void
-vmlogrdr_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data);
-static void
-vmlogrdr_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data);
-static void
-vmlogrdr_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data);
-
-
-static iucv_interrupt_ops_t vmlogrdr_iucvops = {
-	.ConnectionComplete = vmlogrdr_iucv_ConnectionComplete,
-	.ConnectionSevered  = vmlogrdr_iucv_ConnectionSevered,
-	.MessagePending     = vmlogrdr_iucv_MessagePending,
-};
-
 static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
 static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
 
@@ -176,28 +157,29 @@
 static int recording_class_AB;
 
 
-static void
-vmlogrdr_iucv_ConnectionComplete (iucv_ConnectionComplete * eib,
-				   void * pgm_data)
+static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
 {
-	struct vmlogrdr_priv_t * logptr = pgm_data;
+	struct vmlogrdr_priv_t * logptr = path->private;
+
 	spin_lock(&logptr->priv_lock);
 	logptr->connection_established = 1;
 	spin_unlock(&logptr->priv_lock);
 	wake_up(&conn_wait_queue);
-	return;
 }
 
 
-static void
-vmlogrdr_iucv_ConnectionSevered (iucv_ConnectionSevered * eib, void * pgm_data)
+static void vmlogrdr_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
 {
-	u8 reason = (u8) eib->ipuser[8];
-	struct vmlogrdr_priv_t * logptr = pgm_data;
+	struct vmlogrdr_priv_t * logptr = path->private;
+	u8 reason = (u8) ipuser[8];
 
 	printk (KERN_ERR "vmlogrdr: connection severed with"
 		" reason %i\n", reason);
 
+	iucv_path_sever(path, NULL);
+	kfree(path);
+	logptr->path = NULL;
+
 	spin_lock(&logptr->priv_lock);
 	logptr->connection_established = 0;
 	logptr->iucv_path_severed = 1;
@@ -209,10 +191,10 @@
 }
 
 
-static void
-vmlogrdr_iucv_MessagePending (iucv_MessagePending * eib, void * pgm_data)
+static void vmlogrdr_iucv_message_pending(struct iucv_path *path,
+					  struct iucv_message *msg)
 {
-	struct vmlogrdr_priv_t * logptr = pgm_data;
+	struct vmlogrdr_priv_t * logptr = path->private;
 
 	/*
 	 * This function is the bottom half so it should be quick.
@@ -220,15 +202,15 @@
 	 * the usage count
 	 */
 	spin_lock(&logptr->priv_lock);
-	memcpy(&(logptr->local_interrupt_buffer), eib, sizeof(*eib));
+	memcpy(&logptr->local_interrupt_buffer, msg, sizeof(*msg));
 	atomic_inc(&logptr->receive_ready);
 	spin_unlock(&logptr->priv_lock);
 	wake_up_interruptible(&read_wait_queue);
 }
 
 
-static int
-vmlogrdr_get_recording_class_AB(void) {
+static int vmlogrdr_get_recording_class_AB(void)
+{
 	char cp_command[]="QUERY COMMAND RECORDING ";
 	char cp_response[80];
 	char *tail;
@@ -258,8 +240,9 @@
 }
 
 
-static int
-vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
+static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr,
+			      int action, int purge)
+{
 
 	char cp_command[80];
 	char cp_response[160];
@@ -317,8 +300,7 @@
 }
 
 
-static int
-vmlogrdr_open (struct inode *inode, struct file *filp)
+static int vmlogrdr_open (struct inode *inode, struct file *filp)
 {
 	int dev_num = 0;
 	struct vmlogrdr_priv_t * logptr = NULL;
@@ -328,10 +310,7 @@
 	dev_num = iminor(inode);
 	if (dev_num > MAXMINOR)
 		return -ENODEV;
-
 	logptr = &sys_ser[dev_num];
-	if (logptr == NULL)
-		return -ENODEV;
 
 	/*
 	 * only allow for blocking reads to be open
@@ -344,52 +323,38 @@
 	if (logptr->dev_in_use)	{
 		spin_unlock_bh(&logptr->priv_lock);
 		return -EBUSY;
-	} else {
-		logptr->dev_in_use = 1;
-		spin_unlock_bh(&logptr->priv_lock);
 	}
-
+	logptr->dev_in_use = 1;
+	logptr->connection_established = 0;
+	logptr->iucv_path_severed = 0;
 	atomic_set(&logptr->receive_ready, 0);
 	logptr->buffer_free = 1;
+	spin_unlock_bh(&logptr->priv_lock);
 
 	/* set the file options */
 	filp->private_data = logptr;
 	filp->f_op = &vmlogrdr_fops;
 
 	/* start recording for this service*/
-	ret=0;
-	if (logptr->autorecording)
+	if (logptr->autorecording) {
 		ret = vmlogrdr_recording(logptr,1,logptr->autopurge);
-	if (ret)
-		printk (KERN_WARNING "vmlogrdr: failed to start "
-			"recording automatically\n");
-
-	/* Register with iucv driver */
-	logptr->iucv_handle = iucv_register_program(iucvMagic,
-			logptr->system_service, mask, &vmlogrdr_iucvops,
-			logptr);
-
-	if (logptr->iucv_handle == NULL) {
-		printk (KERN_ERR "vmlogrdr: failed to register with"
-			"iucv driver\n");
-		goto not_registered;
+		if (ret)
+			printk (KERN_WARNING "vmlogrdr: failed to start "
+				"recording automatically\n");
 	}
 
 	/* create connection to the system service */
-	spin_lock_bh(&logptr->priv_lock);
-	logptr->connection_established = 0;
-	logptr->iucv_path_severed = 0;
-	spin_unlock_bh(&logptr->priv_lock);
-
-	connect_rc = iucv_connect (&(logptr->pathid), 10, iucvMagic,
-					logptr->system_service, iucv_host, 0,
-					NULL, NULL,
-					logptr->iucv_handle, NULL);
+	logptr->path = iucv_path_alloc(10, 0, GFP_KERNEL);
+	if (!logptr->path)
+		goto out_dev;
+	connect_rc = iucv_path_connect(logptr->path, &vmlogrdr_iucv_handler,
+				       logptr->system_service, NULL, NULL,
+				       logptr);
 	if (connect_rc) {
 		printk (KERN_ERR "vmlogrdr: iucv connection to %s "
 			"failed with rc %i \n", logptr->system_service,
 			connect_rc);
-		goto not_connected;
+		goto out_path;
 	}
 
 	/* We've issued the connect and now we must wait for a
@@ -398,35 +363,28 @@
 	 */
 	wait_event(conn_wait_queue, (logptr->connection_established)
 		   || (logptr->iucv_path_severed));
-	if (logptr->iucv_path_severed) {
-		goto not_connected;
-	}
-
+	if (logptr->iucv_path_severed)
+		goto out_record;
  	return nonseekable_open(inode, filp);
 
-not_connected:
-	iucv_unregister_program(logptr->iucv_handle);
-	logptr->iucv_handle = NULL;
-not_registered:
+out_record:
 	if (logptr->autorecording)
 		vmlogrdr_recording(logptr,0,logptr->autopurge);
+out_path:
+	kfree(logptr->path);	/* kfree(NULL) is ok. */
+	logptr->path = NULL;
+out_dev:
 	logptr->dev_in_use = 0;
 	return -EIO;
-
-
 }
 
 
-static int
-vmlogrdr_release (struct inode *inode, struct file *filp)
+static int vmlogrdr_release (struct inode *inode, struct file *filp)
 {
 	int ret;
 
 	struct vmlogrdr_priv_t * logptr = filp->private_data;
 
-	iucv_unregister_program(logptr->iucv_handle);
-	logptr->iucv_handle = NULL;
-
 	if (logptr->autorecording) {
 		ret = vmlogrdr_recording(logptr,0,logptr->autopurge);
 		if (ret)
@@ -439,8 +397,8 @@
 }
 
 
-static int
-vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
+static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv)
+{
 	int rc, *temp;
 	/* we need to keep track of two data sizes here:
 	 * The number of bytes we need to receive from iucv and
@@ -461,8 +419,7 @@
 			 * We need to return the total length of the record
                          * + size of FENCE in the first 4 bytes of the buffer.
 		         */
-			iucv_data_count =
-				priv->local_interrupt_buffer.ln1msg2.ipbfln1f;
+			iucv_data_count = priv->local_interrupt_buffer.length;
 			user_data_count = sizeof(int);
 			temp = (int*)priv->buffer;
 			*temp= iucv_data_count + sizeof(FENCE);
@@ -474,14 +431,10 @@
 		 */
 		if (iucv_data_count > NET_BUFFER_SIZE)
 			iucv_data_count = NET_BUFFER_SIZE;
-		rc = iucv_receive(priv->pathid,
-				  priv->local_interrupt_buffer.ipmsgid,
-				  priv->local_interrupt_buffer.iptrgcls,
-				  buffer,
-				  iucv_data_count,
-				  NULL,
-				  NULL,
-				  &priv->residual_length);
+		rc = iucv_message_receive(priv->path,
+					  &priv->local_interrupt_buffer,
+					  0, buffer, iucv_data_count,
+					  &priv->residual_length);
 		spin_unlock_bh(&priv->priv_lock);
 		/* An rc of 5 indicates that the record was bigger then
 		 * the buffer, which is OK for us. A 9 indicates that the
@@ -513,8 +466,8 @@
 }
 
 
-static ssize_t
-vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos)
+static ssize_t vmlogrdr_read(struct file *filp, char __user *data,
+			     size_t count, loff_t * ppos)
 {
 	int rc;
 	struct vmlogrdr_priv_t * priv = filp->private_data;
@@ -546,8 +499,10 @@
 	return count;
 }
 
-static ssize_t
-vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
+static ssize_t vmlogrdr_autopurge_store(struct device * dev,
+					struct device_attribute *attr,
+					const char * buf, size_t count)
+{
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret = count;
 
@@ -565,8 +520,10 @@
 }
 
 
-static ssize_t
-vmlogrdr_autopurge_show(struct device *dev, struct device_attribute *attr, char *buf) {
+static ssize_t vmlogrdr_autopurge_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	return sprintf(buf, "%u\n", priv->autopurge);
 }
@@ -576,8 +533,10 @@
 		   vmlogrdr_autopurge_store);
 
 
-static ssize_t
-vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
+static ssize_t vmlogrdr_purge_store(struct device * dev,
+				    struct device_attribute *attr,
+				    const char * buf, size_t count)
+{
 
 	char cp_command[80];
 	char cp_response[80];
@@ -617,9 +576,10 @@
 static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store);
 
 
-static ssize_t
-vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr, const char *buf,
-			     size_t count) {
+static ssize_t vmlogrdr_autorecording_store(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t count)
+{
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret = count;
 
@@ -637,8 +597,10 @@
 }
 
 
-static ssize_t
-vmlogrdr_autorecording_show(struct device *dev, struct device_attribute *attr, char *buf) {
+static ssize_t vmlogrdr_autorecording_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	return sprintf(buf, "%u\n", priv->autorecording);
 }
@@ -648,9 +610,10 @@
 		   vmlogrdr_autorecording_store);
 
 
-static ssize_t
-vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
-
+static ssize_t vmlogrdr_recording_store(struct device * dev,
+					struct device_attribute *attr,
+					const char * buf, size_t count)
+{
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret;
 
@@ -675,8 +638,9 @@
 static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store);
 
 
-static ssize_t
-vmlogrdr_recording_status_show(struct device_driver *driver, char *buf) {
+static ssize_t vmlogrdr_recording_status_show(struct device_driver *driver,
+					      char *buf)
+{
 
 	char cp_command[] = "QUERY RECORDING ";
 	int len;
@@ -709,52 +673,63 @@
 };
 
 
-static int
-vmlogrdr_register_driver(void) {
+static int vmlogrdr_register_driver(void)
+{
 	int ret;
 
+	/* Register with iucv driver */
+	ret = iucv_register(&vmlogrdr_iucv_handler, 1);
+	if (ret) {
+		printk (KERN_ERR "vmlogrdr: failed to register with"
+			"iucv driver\n");
+		goto out;
+	}
+
 	ret = driver_register(&vmlogrdr_driver);
 	if (ret) {
 		printk(KERN_ERR "vmlogrdr: failed to register driver.\n");
-		return ret;
+		goto out_iucv;
 	}
 
 	ret = driver_create_file(&vmlogrdr_driver,
 				 &driver_attr_recording_status);
 	if (ret) {
 		printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");
-		goto unregdriver;
+		goto out_driver;
 	}
 
 	vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
 	if (IS_ERR(vmlogrdr_class)) {
 		printk(KERN_ERR "vmlogrdr: failed to create class.\n");
-		ret=PTR_ERR(vmlogrdr_class);
-		vmlogrdr_class=NULL;
-		goto unregattr;
+		ret = PTR_ERR(vmlogrdr_class);
+		vmlogrdr_class = NULL;
+		goto out_attr;
 	}
 	return 0;
 
-unregattr:
+out_attr:
 	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
-unregdriver:
+out_driver:
 	driver_unregister(&vmlogrdr_driver);
+out_iucv:
+	iucv_unregister(&vmlogrdr_iucv_handler, 1);
+out:
 	return ret;
 }
 
 
-static void
-vmlogrdr_unregister_driver(void) {
+static void vmlogrdr_unregister_driver(void)
+{
 	class_destroy(vmlogrdr_class);
 	vmlogrdr_class = NULL;
 	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
 	driver_unregister(&vmlogrdr_driver);
-	return;
+	iucv_unregister(&vmlogrdr_iucv_handler, 1);
 }
 
 
-static int
-vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
+static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
+{
 	struct device *dev;
 	int ret;
 
@@ -803,9 +778,10 @@
 }
 
 
-static int
-vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
-	class_device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
+static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv)
+{
+	class_device_destroy(vmlogrdr_class,
+			     MKDEV(vmlogrdr_major, priv->minor_num));
 	if (priv->device != NULL) {
 		sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
 		device_unregister(priv->device);
@@ -815,8 +791,8 @@
 }
 
 
-static int
-vmlogrdr_register_cdev(dev_t dev) {
+static int vmlogrdr_register_cdev(dev_t dev)
+{
 	int rc = 0;
 	vmlogrdr_cdev = cdev_alloc();
 	if (!vmlogrdr_cdev) {
@@ -836,9 +812,10 @@
 }
 
 
-static void
-vmlogrdr_cleanup(void) {
+static void vmlogrdr_cleanup(void)
+{
         int i;
+
 	if (vmlogrdr_cdev) {
 		cdev_del(vmlogrdr_cdev);
 		vmlogrdr_cdev=NULL;
@@ -855,8 +832,7 @@
 }
 
 
-static int
-vmlogrdr_init(void)
+static int vmlogrdr_init(void)
 {
 	int rc;
 	int i;
@@ -906,8 +882,7 @@
 }
 
 
-static void
-vmlogrdr_exit(void)
+static void vmlogrdr_exit(void)
 {
 	vmlogrdr_cleanup();
 	printk (KERN_INFO "vmlogrdr: driver unloaded\n");
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 4b868f7..680b9b5 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -228,7 +228,7 @@
 	return count;
 }
 
-static struct file_operations vmwdt_fops = {
+static const struct file_operations vmwdt_fops = {
 	.open    = &vmwdt_open,
 	.release = &vmwdt_close,
 	.ioctl   = &vmwdt_ioctl,
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index aa65df4d..ec04048 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -364,7 +364,7 @@
 	return seq_open(file, &cio_ignore_proc_seq_ops);
 }
 
-static struct file_operations cio_ignore_proc_fops = {
+static const struct file_operations cio_ignore_proc_fops = {
 	.open    = cio_ignore_proc_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index b3a56dc..9cb129a 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -21,6 +21,7 @@
 #include <asm/irq_regs.h>
 #include <asm/setup.h>
 #include <asm/reset.h>
+#include <asm/ipl.h>
 #include "airq.h"
 #include "cio.h"
 #include "css.h"
@@ -1047,7 +1048,7 @@
 	do_reipl_asm(*((__u32*)&schid));
 }
 
-extern struct schib ipl_schib;
+static struct schib __initdata ipl_schib;
 
 /*
  * ipl_save_parameters gets called very early. It is not allowed to access
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index f172759..997f468 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -11,6 +11,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 
 #include <asm/ccwdev.h>
 #include <asm/delay.h>
@@ -138,7 +139,7 @@
 		ps->cu_model = 0x60;
 		return;
 	}
-	for (i = 0; i < sizeof(vm_devices) / sizeof(vm_devices[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(vm_devices); i++)
 		if (diag_data.vrdcvcla == vm_devices[i].vrdcvcla &&
 		    diag_data.vrdcvtyp == vm_devices[i].vrdcvtyp) {
 			ps->cu_type = vm_devices[i].cu_type;
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index d7b25b8..7c7775a 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -23,8 +23,7 @@
 #include "chsc.h"
 #include "device.h"
 
-int
-ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
+int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
 {
        /*
 	* The flag usage is mutal exclusive ...
@@ -39,6 +38,33 @@
 	return 0;
 }
 
+int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
+{
+       /*
+	* The flag usage is mutal exclusive ...
+	*/
+	if (((flags & CCWDEV_EARLY_NOTIFICATION) &&
+	    (flags & CCWDEV_REPORT_ALL)) ||
+	    ((flags & CCWDEV_EARLY_NOTIFICATION) &&
+	     cdev->private->options.repall) ||
+	    ((flags & CCWDEV_REPORT_ALL) &&
+	     cdev->private->options.fast))
+		return -EINVAL;
+	cdev->private->options.fast |= (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
+	cdev->private->options.repall |= (flags & CCWDEV_REPORT_ALL) != 0;
+	cdev->private->options.pgroup |= (flags & CCWDEV_DO_PATHGROUP) != 0;
+	cdev->private->options.force |= (flags & CCWDEV_ALLOW_FORCE) != 0;
+	return 0;
+}
+
+void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)
+{
+	cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0;
+	cdev->private->options.repall &= (flags & CCWDEV_REPORT_ALL) == 0;
+	cdev->private->options.pgroup &= (flags & CCWDEV_DO_PATHGROUP) == 0;
+	cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0;
+}
+
 int
 ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
 {
@@ -601,7 +627,9 @@
 
 
 MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(ccw_device_set_options_mask);
 EXPORT_SYMBOL(ccw_device_set_options);
+EXPORT_SYMBOL(ccw_device_clear_options);
 EXPORT_SYMBOL(ccw_device_clear);
 EXPORT_SYMBOL(ccw_device_halt);
 EXPORT_SYMBOL(ccw_device_resume);
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index d726cd5..5b1e3ff 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -3194,7 +3194,7 @@
 
 	spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags);
 
-	ccw_device_set_options(cdev, 0);
+	ccw_device_set_options_mask(cdev, 0);
 	result=ccw_device_start_timeout(cdev,&irq_ptr->ccw,
 					QDIO_DOING_ESTABLISH,0, 0,
 					QDIO_ESTABLISH_TIMEOUT);
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index b9e59bc..9976139 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -807,7 +807,7 @@
 /**
  * Misc device file operations.
  */
-static struct file_operations zcrypt_fops = {
+static const struct file_operations zcrypt_fops = {
 	.owner		= THIS_MODULE,
 	.read		= zcrypt_read,
 	.write		= zcrypt_write,
@@ -1063,7 +1063,6 @@
 		rc = -ENOMEM;
 		goto out_misc;
 	}
-	zcrypt_entry->nlink = 1;
 	zcrypt_entry->data = NULL;
 	zcrypt_entry->read_proc = zcrypt_status_read;
 	zcrypt_entry->write_proc = zcrypt_status_write;
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 5262515..f98fa46 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -22,13 +22,6 @@
 	  available.  This option is also available as a module which will be
 	  called ctc.ko.  If you do not know what it is, it's safe to say "Y".
 
-config IUCV
-	tristate "IUCV support (VM only)"
-	help
-	  Select this option if you want to use inter-user communication
-	  under VM or VIF. If unsure, say "Y" to enable a fast communication
-	  link between VM guests.
-
 config NETIUCV
 	tristate "IUCV network device support (VM only)"
 	depends on IUCV && NETDEVICES
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 4777e36..bbe3ab2 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -4,7 +4,6 @@
 
 ctc-objs := ctcmain.o ctcdbug.o
 
-obj-$(CONFIG_IUCV) += iucv.o
 obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
 obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
 obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 5a84fbb..0d6d5fc 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -45,7 +45,6 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/bitops.h>
 
 #include <linux/signal.h>
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
deleted file mode 100644
index 229aeb5..0000000
--- a/drivers/s390/net/iucv.c
+++ /dev/null
@@ -1,2540 +0,0 @@
-/*
- * IUCV network driver
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s):
- *    Original source:
- *      Alan Altmark (Alan_Altmark@us.ibm.com)  Sept. 2000
- *      Xenia Tkatschow (xenia@us.ibm.com)
- *    2Gb awareness and general cleanup:
- *      Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- *
- * Documentation used:
- *    The original source
- *    CP Programming Service, IBM document # SC24-5760
- *
- * 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.
- *
- * 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.
- *
- */
-
-/* #define DEBUG */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include <linux/spinlock.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <asm/atomic.h>
-#include "iucv.h"
-#include <asm/io.h>
-#include <asm/s390_ext.h>
-#include <asm/ebcdic.h>
-#include <asm/smp.h>
-#include <asm/s390_rdev.h>
-
-/* FLAGS:
- * All flags are defined in the field IPFLAGS1 of each function
- * and can be found in CP Programming Services.
- * IPSRCCLS - Indicates you have specified a source class
- * IPFGMCL  - Indicates you have specified a target class
- * IPFGPID  - Indicates you have specified a pathid
- * IPFGMID  - Indicates you have specified a message ID
- * IPANSLST - Indicates that you are using an address list for
- *            reply data
- * IPBUFLST - Indicates that you are using an address list for
- *            message data
- */
-
-#define IPSRCCLS 	0x01
-#define IPFGMCL         0x01
-#define IPFGPID         0x02
-#define IPFGMID         0x04
-#define IPANSLST        0x08
-#define IPBUFLST        0x40
-
-static int
-iucv_bus_match (struct device *dev, struct device_driver *drv)
-{
-	return 0;
-}
-
-struct bus_type iucv_bus = {
-	.name = "iucv",
-	.match = iucv_bus_match,
-};
-
-struct device *iucv_root;
-
-/* General IUCV interrupt structure */
-typedef struct {
-	__u16 ippathid;
-	__u8  res1;
-	__u8  iptype;
-	__u32 res2;
-	__u8  ipvmid[8];
-	__u8  res3[24];
-} iucv_GeneralInterrupt;
-
-static iucv_GeneralInterrupt *iucv_external_int_buffer = NULL;
-
-/* Spin Lock declaration */
-
-static DEFINE_SPINLOCK(iucv_lock);
-
-static int messagesDisabled = 0;
-
-/***************INTERRUPT HANDLING ***************/
-
-typedef struct {
-	struct list_head queue;
-	iucv_GeneralInterrupt data;
-} iucv_irqdata;
-
-static struct list_head  iucv_irq_queue;
-static DEFINE_SPINLOCK(iucv_irq_queue_lock);
-
-/*
- *Internal function prototypes
- */
-static void iucv_tasklet_handler(unsigned long);
-static void iucv_irq_handler(__u16);
-
-static DECLARE_TASKLET(iucv_tasklet,iucv_tasklet_handler,0);
-
-/************ FUNCTION ID'S ****************************/
-
-#define ACCEPT          10
-#define CONNECT         11
-#define DECLARE_BUFFER  12
-#define PURGE           9
-#define QUERY           0
-#define QUIESCE         13
-#define RECEIVE         5
-#define REJECT          8
-#define REPLY           6
-#define RESUME          14
-#define RETRIEVE_BUFFER 2
-#define SEND            4
-#define SETMASK         16
-#define SEVER           15
-
-/**
- * Structure: handler
- * members: list - list management.
- *          structure: id
- *             userid - 8 char array of machine identification
- *             user_data - 16 char array for user identification
- *             mask - 24 char array used to compare the 2 previous
- *          interrupt_table - vector of interrupt functions.
- *          pgm_data -  ulong, application data that is passed
- *                      to the interrupt handlers
-*/
-typedef struct handler_t {
-	struct list_head list;
-	struct {
-		__u8 userid[8];
-		__u8 user_data[16];
-		__u8 mask[24];
-	}                    id;
-	iucv_interrupt_ops_t *interrupt_table;
-	void                 *pgm_data;
-} handler;
-
-/**
- * iucv_handler_table: List of registered handlers.
- */
-static struct list_head iucv_handler_table;
-
-/**
- * iucv_pathid_table: an array of *handler pointing into
- *                    iucv_handler_table for fast indexing by pathid;
- */
-static handler **iucv_pathid_table;
-
-static unsigned long max_connections;
-
-/**
- * iucv_cpuid: contains the logical cpu number of the cpu which
- * has declared the iucv buffer by issuing DECLARE_BUFFER.
- * If no cpu has done the initialization iucv_cpuid contains -1.
- */
-static int iucv_cpuid = -1;
-/**
- * register_flag: is 0 when external interrupt has not been registered
- */
-static int register_flag;
-
-/****************FIVE 40-BYTE PARAMETER STRUCTURES******************/
-/* Data struct 1: iparml_control
- * Used for iucv_accept
- *          iucv_connect
- *          iucv_quiesce
- *          iucv_resume
- *          iucv_sever
- *          iucv_retrieve_buffer
- * Data struct 2: iparml_dpl     (data in parameter list)
- * Used for iucv_send_prmmsg
- *          iucv_send2way_prmmsg
- *          iucv_send2way_prmmsg_array
- *          iucv_reply_prmmsg
- * Data struct 3: iparml_db       (data in a buffer)
- * Used for iucv_receive
- *          iucv_receive_array
- *          iucv_reject
- *          iucv_reply
- *          iucv_reply_array
- *          iucv_send
- *          iucv_send_array
- *          iucv_send2way
- *          iucv_send2way_array
- *          iucv_declare_buffer
- * Data struct 4: iparml_purge
- * Used for iucv_purge
- *          iucv_query
- * Data struct 5: iparml_set_mask
- * Used for iucv_set_mask
- */
-
-typedef struct {
-	__u16 ippathid;
-	__u8  ipflags1;
-	__u8  iprcode;
-	__u16 ipmsglim;
-	__u16 res1;
-	__u8  ipvmid[8];
-	__u8  ipuser[16];
-	__u8  iptarget[8];
-} iparml_control;
-
-typedef struct {
-	__u16 ippathid;
-	__u8  ipflags1;
-	__u8  iprcode;
-	__u32 ipmsgid;
-	__u32 iptrgcls;
-	__u8  iprmmsg[8];
-	__u32 ipsrccls;
-	__u32 ipmsgtag;
-	__u32 ipbfadr2;
-	__u32 ipbfln2f;
-	__u32 res;
-} iparml_dpl;
-
-typedef struct {
-	__u16 ippathid;
-	__u8  ipflags1;
-	__u8  iprcode;
-	__u32 ipmsgid;
-	__u32 iptrgcls;
-	__u32 ipbfadr1;
-	__u32 ipbfln1f;
-	__u32 ipsrccls;
-	__u32 ipmsgtag;
-	__u32 ipbfadr2;
-	__u32 ipbfln2f;
-	__u32 res;
-} iparml_db;
-
-typedef struct {
-	__u16 ippathid;
-	__u8  ipflags1;
-	__u8  iprcode;
-	__u32 ipmsgid;
-	__u8  ipaudit[3];
-	__u8  res1[5];
-	__u32 res2;
-	__u32 ipsrccls;
-	__u32 ipmsgtag;
-	__u32 res3[3];
-} iparml_purge;
-
-typedef struct {
-	__u8  ipmask;
-	__u8  res1[2];
-	__u8  iprcode;
-	__u32 res2[9];
-} iparml_set_mask;
-
-typedef struct {
-	union {
-		iparml_control  p_ctrl;
-		iparml_dpl      p_dpl;
-		iparml_db       p_db;
-		iparml_purge    p_purge;
-		iparml_set_mask p_set_mask;
-	} param;
-	atomic_t in_use;
-	__u32    res;
-}  __attribute__ ((aligned(8))) iucv_param;
-#define PARAM_POOL_SIZE (PAGE_SIZE / sizeof(iucv_param))
-
-static iucv_param * iucv_param_pool;
-
-MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
-MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver");
-MODULE_LICENSE("GPL");
-
-/*
- * Debugging stuff
- *******************************************************************************/
-
-
-#ifdef DEBUG
-static int debuglevel = 0;
-
-module_param(debuglevel, int, 0);
-MODULE_PARM_DESC(debuglevel,
- "Specifies the debug level (0=off ... 3=all)");
-
-static void
-iucv_dumpit(char *title, void *buf, int len)
-{
-	int i;
-	__u8 *p = (__u8 *)buf;
-
-	if (debuglevel < 3)
-		return;
-
-	printk(KERN_DEBUG "%s\n", title);
-	printk("  ");
-	for (i = 0; i < len; i++) {
-		if (!(i % 16) && i != 0)
-			printk ("\n  ");
-		else if (!(i % 4) && i != 0)
-			printk(" ");
-		printk("%02X", *p++);
-	}
-	if (len % 16)
-		printk ("\n");
-	return;
-}
-#define iucv_debug(lvl, fmt, args...) \
-do { \
-	if (debuglevel >= lvl) \
-		printk(KERN_DEBUG "%s: " fmt "\n", __FUNCTION__ , ## args); \
-} while (0)
-
-#else
-
-#define iucv_debug(lvl, fmt, args...)	do { } while (0)
-#define iucv_dumpit(title, buf, len)	do { } while (0)
-
-#endif
-
-/*
- * Internal functions
- *******************************************************************************/
-
-/**
- * print start banner
- */
-static void
-iucv_banner(void)
-{
-	printk(KERN_INFO "IUCV lowlevel driver initialized\n");
-}
-
-/**
- * iucv_init - Initialization
- *
- * Allocates and initializes various data structures.
- */
-static int
-iucv_init(void)
-{
-	int ret;
-
-	if (iucv_external_int_buffer)
-		return 0;
-
-	if (!MACHINE_IS_VM) {
-		printk(KERN_ERR "IUCV: IUCV connection needs VM as base\n");
-		return -EPROTONOSUPPORT;
-	}
-
-	ret = bus_register(&iucv_bus);
-	if (ret) {
-		printk(KERN_ERR "IUCV: failed to register bus.\n");
-		return ret;
-	}
-
-	iucv_root = s390_root_dev_register("iucv");
-	if (IS_ERR(iucv_root)) {
-		printk(KERN_ERR "IUCV: failed to register iucv root.\n");
-		bus_unregister(&iucv_bus);
-		return PTR_ERR(iucv_root);
-	}
-
-	/* Note: GFP_DMA used used to get memory below 2G */
-	iucv_external_int_buffer = kzalloc(sizeof(iucv_GeneralInterrupt),
-					   GFP_KERNEL|GFP_DMA);
-	if (!iucv_external_int_buffer) {
-		printk(KERN_WARNING
-		       "%s: Could not allocate external interrupt buffer\n",
-		       __FUNCTION__);
-		s390_root_dev_unregister(iucv_root);
-		bus_unregister(&iucv_bus);
-		return -ENOMEM;
-	}
-
-	/* Initialize parameter pool */
-	iucv_param_pool = kzalloc(sizeof(iucv_param) * PARAM_POOL_SIZE,
-				  GFP_KERNEL|GFP_DMA);
-	if (!iucv_param_pool) {
-		printk(KERN_WARNING "%s: Could not allocate param pool\n",
-		       __FUNCTION__);
-		kfree(iucv_external_int_buffer);
-		iucv_external_int_buffer = NULL;
-		s390_root_dev_unregister(iucv_root);
-		bus_unregister(&iucv_bus);
-		return -ENOMEM;
-	}
-
-	/* Initialize irq queue */
-	INIT_LIST_HEAD(&iucv_irq_queue);
-
-	/* Initialize handler table */
-	INIT_LIST_HEAD(&iucv_handler_table);
-
-	iucv_banner();
-	return 0;
-}
-
-/**
- * iucv_exit - De-Initialization
- *
- * Frees everything allocated from iucv_init.
- */
-static int iucv_retrieve_buffer (void);
-
-static void
-iucv_exit(void)
-{
-	iucv_retrieve_buffer();
-	kfree(iucv_external_int_buffer);
-	iucv_external_int_buffer = NULL;
-	kfree(iucv_param_pool);
-	iucv_param_pool = NULL;
-	s390_root_dev_unregister(iucv_root);
-	bus_unregister(&iucv_bus);
-	printk(KERN_INFO "IUCV lowlevel driver unloaded\n");
-}
-
-/**
- * grab_param: - Get a parameter buffer from the pre-allocated pool.
- *
- * This function searches for an unused element in the pre-allocated pool
- * of parameter buffers. If one is found, it marks it "in use" and returns
- * a pointer to it. The calling function is responsible for releasing it
- * when it has finished its usage.
- *
- * Returns: A pointer to iucv_param.
- */
-static __inline__ iucv_param *
-grab_param(void)
-{
-	iucv_param *ptr;
-        static int hint = 0;
-
-	ptr = iucv_param_pool + hint;
-	do {
-		ptr++;
-		if (ptr >= iucv_param_pool + PARAM_POOL_SIZE)
-			ptr = iucv_param_pool;
-	} while (atomic_cmpxchg(&ptr->in_use, 0, 1) != 0);
-	hint = ptr - iucv_param_pool;
-
-	memset(&ptr->param, 0, sizeof(ptr->param));
-	return ptr;
-}
-
-/**
- * release_param - Release a parameter buffer.
- * @p: A pointer to a struct iucv_param, previously obtained by calling
- *     grab_param().
- *
- * This function marks the specified parameter buffer "unused".
- */
-static __inline__ void
-release_param(void *p)
-{
-	atomic_set(&((iucv_param *)p)->in_use, 0);
-}
-
-/**
- * iucv_add_handler: - Add a new handler
- * @new_handler: handle that is being entered into chain.
- *
- * Places new handle on iucv_handler_table, if identical handler is not
- * found.
- *
- * Returns: 0 on success, !0 on failure (handler already in chain).
- */
-static int
-iucv_add_handler (handler *new)
-{
-	ulong flags;
-
-	iucv_debug(1, "entering");
-	iucv_dumpit("handler:", new, sizeof(handler));
-
-	spin_lock_irqsave (&iucv_lock, flags);
-	if (!list_empty(&iucv_handler_table)) {
-		struct list_head *lh;
-
-		/**
-		 * Search list for handler with identical id. If one
-		 * is found, the new handler is _not_ added.
-		 */
-		list_for_each(lh, &iucv_handler_table) {
-			handler *h = list_entry(lh, handler, list);
-			if (!memcmp(&new->id, &h->id, sizeof(h->id))) {
-				iucv_debug(1, "ret 1");
-				spin_unlock_irqrestore (&iucv_lock, flags);
-				return 1;
-			}
-		}
-	}
-	/**
-	 * If we get here, no handler was found.
-	 */
-	INIT_LIST_HEAD(&new->list);
-	list_add(&new->list, &iucv_handler_table);
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	iucv_debug(1, "exiting");
-	return 0;
-}
-
-/**
- * b2f0:
- * @code: identifier of IUCV call to CP.
- * @parm: pointer to 40 byte iparml area passed to CP
- *
- * Calls CP to execute IUCV commands.
- *
- * Returns: return code from CP's IUCV call
- */
-static inline ulong b2f0(__u32 code, void *parm)
-{
-	register unsigned long reg0 asm ("0");
-	register unsigned long reg1 asm ("1");
-	iucv_dumpit("iparml before b2f0 call:", parm, sizeof(iucv_param));
-
-	reg0 = code;
-	reg1 = virt_to_phys(parm);
-	asm volatile(".long 0xb2f01000" : : "d" (reg0), "a" (reg1));
-
-	iucv_dumpit("iparml after b2f0 call:", parm, sizeof(iucv_param));
-
-	return (unsigned long)*((__u8 *)(parm + 3));
-}
-
-/*
- * Name: iucv_add_pathid
- * Purpose: Adds a path id to the system.
- * Input: pathid -  pathid that is going to be entered into system
- *        handle -  address of handler that the pathid will be associated
- *		   with.
- *        pgm_data - token passed in by application.
- * Output: 0: successful addition of pathid
- *	   - EINVAL - pathid entry is being used by another application
- *	   - ENOMEM - storage allocation for a new pathid table failed
-*/
-static int
-__iucv_add_pathid(__u16 pathid, handler *handler)
-{
-
-	iucv_debug(1, "entering");
-
-	iucv_debug(1, "handler is pointing to %p", handler);
-
-	if (pathid > (max_connections - 1))
-		return -EINVAL;
-
-	if (iucv_pathid_table[pathid]) {
-		iucv_debug(1, "pathid entry is %p", iucv_pathid_table[pathid]);
-		printk(KERN_WARNING
-		       "%s: Pathid being used, error.\n", __FUNCTION__);
-		return -EINVAL;
-	}
-	iucv_pathid_table[pathid] = handler;
-
-	iucv_debug(1, "exiting");
-	return 0;
-}				/* end of add_pathid function */
-
-static int
-iucv_add_pathid(__u16 pathid, handler *handler)
-{
-	ulong flags;
-	int rc;
-
-	spin_lock_irqsave (&iucv_lock, flags);
-	rc = __iucv_add_pathid(pathid, handler);
-	spin_unlock_irqrestore (&iucv_lock, flags);
-	return rc;
-}
-
-static void
-iucv_remove_pathid(__u16 pathid)
-{
-	ulong flags;
-
-	if (pathid > (max_connections - 1))
-		return;
-
-	spin_lock_irqsave (&iucv_lock, flags);
-	iucv_pathid_table[pathid] = NULL;
-	spin_unlock_irqrestore (&iucv_lock, flags);
-}
-
-/**
- * iucv_declare_buffer_cpuid
- * Register at VM for subsequent IUCV operations. This is executed
- * on the reserved CPU iucv_cpuid. Called from iucv_declare_buffer().
- */
-static void
-iucv_declare_buffer_cpuid (void *result)
-{
-	iparml_db *parm;
-
-	parm = (iparml_db *)grab_param();
-	parm->ipbfadr1 = virt_to_phys(iucv_external_int_buffer);
-	if ((*((ulong *)result) = b2f0(DECLARE_BUFFER, parm)) == 1)
-		*((ulong *)result) = parm->iprcode;
-	release_param(parm);
-}
-
-/**
- * iucv_retrieve_buffer_cpuid:
- * Unregister IUCV usage at VM. This is always executed on the same
- * cpu that registered the buffer to VM.
- * Called from iucv_retrieve_buffer().
- */
-static void
-iucv_retrieve_buffer_cpuid (void *cpu)
-{
-	iparml_control *parm;
-
-	parm = (iparml_control *)grab_param();
-	b2f0(RETRIEVE_BUFFER, parm);
-	release_param(parm);
-}
-
-/**
- * Name: iucv_declare_buffer
- * Purpose: Specifies the guests real address of an external
- *          interrupt.
- * Input: void
- * Output: iprcode - return code from b2f0 call
- */
-static int
-iucv_declare_buffer (void)
-{
-	unsigned long flags;
-	ulong b2f0_result;
-
-	iucv_debug(1, "entering");
-	b2f0_result = -ENODEV;
-	spin_lock_irqsave (&iucv_lock, flags);
-	if (iucv_cpuid == -1) {
-		/* Reserve any cpu for use by iucv. */
-		iucv_cpuid = smp_get_cpu(CPU_MASK_ALL);
-		spin_unlock_irqrestore (&iucv_lock, flags);
-		smp_call_function_on(iucv_declare_buffer_cpuid,
-			&b2f0_result, 0, 1, iucv_cpuid);
-		if (b2f0_result) {
-			smp_put_cpu(iucv_cpuid);
-			iucv_cpuid = -1;
-		}
-		iucv_debug(1, "Address of EIB = %p", iucv_external_int_buffer);
-	} else {
-		spin_unlock_irqrestore (&iucv_lock, flags);
-		b2f0_result = 0;
-	}
-	iucv_debug(1, "exiting");
-	return b2f0_result;
-}
-
-/**
- * iucv_retrieve_buffer:
- *
- * Terminates all use of IUCV.
- * Returns: return code from CP
- */
-static int
-iucv_retrieve_buffer (void)
-{
-	iucv_debug(1, "entering");
-	if (iucv_cpuid != -1) {
-		smp_call_function_on(iucv_retrieve_buffer_cpuid,
-				     NULL, 0, 1, iucv_cpuid);
-		/* Release the cpu reserved by iucv_declare_buffer. */
-		smp_put_cpu(iucv_cpuid);
-		iucv_cpuid = -1;
-	}
-	iucv_debug(1, "exiting");
-	return 0;
-}
-
-/**
- * iucv_remove_handler:
- * @users_handler: handler to be removed
- *
- * Remove handler when application unregisters.
- */
-static void
-iucv_remove_handler(handler *handler)
-{
-	unsigned long flags;
-
-	if ((!iucv_pathid_table) || (!handler))
-		return;
-
-	iucv_debug(1, "entering");
-
-	spin_lock_irqsave (&iucv_lock, flags);
-	list_del(&handler->list);
-	if (list_empty(&iucv_handler_table)) {
-		if (register_flag) {
-			unregister_external_interrupt(0x4000, iucv_irq_handler);
-			register_flag = 0;
-		}
-	}
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	iucv_debug(1, "exiting");
-	return;
-}
-
-/**
- * iucv_register_program:
- * @pgmname:  user identification
- * @userid:   machine identification
- * @pgmmask:  Indicates which bits in the pgmname and userid combined will be
- *            used to determine who is given control.
- * @ops:      Address of interrupt handler table.
- * @pgm_data: Application data to be passed to interrupt handlers.
- *
- * Registers an application with IUCV.
- * Returns:
- *           The address of handler, or NULL on failure.
- * NOTE on pgmmask:
- *   If pgmname, userid and pgmmask are provided, pgmmask is entered into the
- *   handler as is.
- *   If pgmmask is NULL, the internal mask is set to all 0xff's
- *   When userid is NULL, the first 8 bytes of the internal mask are forced
- *   to 0x00.
- *   If pgmmask and userid are NULL, the first 8 bytes of the internal mask
- *   are forced to 0x00 and the last 16 bytes to 0xff.
- */
-
-iucv_handle_t
-iucv_register_program (__u8 pgmname[16],
-		       __u8 userid[8],
-		       __u8 pgmmask[24],
-		       iucv_interrupt_ops_t * ops, void *pgm_data)
-{
-	ulong rc = 0;		/* return code from function calls */
-	handler *new_handler;
-
-	iucv_debug(1, "entering");
-
-	if (ops == NULL) {
-		/* interrupt table is not defined */
-		printk(KERN_WARNING "%s: Interrupt table is not defined, "
-		       "exiting\n", __FUNCTION__);
-		return NULL;
-	}
-	if (!pgmname) {
-		printk(KERN_WARNING "%s: pgmname not provided\n", __FUNCTION__);
-		return NULL;
-	}
-
-	/* Allocate handler entry */
-	new_handler = kmalloc(sizeof(handler), GFP_ATOMIC);
-	if (new_handler == NULL) {
-		printk(KERN_WARNING "%s: storage allocation for new handler "
-		       "failed.\n", __FUNCTION__);
-		return NULL;
-	}
-
-	if (!iucv_pathid_table) {
-		if (iucv_init()) {
-			kfree(new_handler);
-			return NULL;
-		}
-
-		max_connections = iucv_query_maxconn();
-		iucv_pathid_table = kcalloc(max_connections, sizeof(handler *),
-					GFP_ATOMIC);
-		if (iucv_pathid_table == NULL) {
-			printk(KERN_WARNING "%s: iucv_pathid_table storage "
-			       "allocation failed\n", __FUNCTION__);
-			kfree(new_handler);
-			return NULL;
-		}
-	}
-	memset(new_handler, 0, sizeof (handler));
-	memcpy(new_handler->id.user_data, pgmname,
-		sizeof (new_handler->id.user_data));
-	if (userid) {
-		memcpy (new_handler->id.userid, userid,
-			sizeof (new_handler->id.userid));
-		ASCEBC (new_handler->id.userid,
-			sizeof (new_handler->id.userid));
-		EBC_TOUPPER (new_handler->id.userid,
-			     sizeof (new_handler->id.userid));
-
-		if (pgmmask) {
-			memcpy (new_handler->id.mask, pgmmask,
-				sizeof (new_handler->id.mask));
-		} else {
-			memset (new_handler->id.mask, 0xFF,
-				sizeof (new_handler->id.mask));
-		}
-	} else {
-		if (pgmmask) {
-			memcpy (new_handler->id.mask, pgmmask,
-				sizeof (new_handler->id.mask));
-		} else {
-			memset (new_handler->id.mask, 0xFF,
-				sizeof (new_handler->id.mask));
-		}
-		memset (new_handler->id.userid, 0x00,
-			sizeof (new_handler->id.userid));
-	}
-	/* fill in the rest of handler */
-	new_handler->pgm_data = pgm_data;
-	new_handler->interrupt_table = ops;
-
-	/*
-	 * Check if someone else is registered with same pgmname, userid
-	 * and mask. If someone is already registered with same pgmname,
-	 * userid and mask, registration will fail and NULL will be returned
-	 * to the application.
-	 * If identical handler not found, then handler is added to list.
-	 */
-	rc = iucv_add_handler(new_handler);
-	if (rc) {
-		printk(KERN_WARNING "%s: Someone already registered with same "
-		       "pgmname, userid, pgmmask\n", __FUNCTION__);
-		kfree (new_handler);
-		return NULL;
-	}
-
-	rc = iucv_declare_buffer();
-	if (rc) {
-		char *err = "Unknown";
-		iucv_remove_handler(new_handler);
-		kfree(new_handler);
-		switch(rc) {
-		case 0x03:
-			err = "Directory error";
-			break;
-		case 0x0a:
-			err = "Invalid length";
-			break;
-		case 0x13:
-			err = "Buffer already exists";
-			break;
-		case 0x3e:
-			err = "Buffer overlap";
-			break;
-		case 0x5c:
-			err = "Paging or storage error";
-			break;
-		}
-		printk(KERN_WARNING "%s: iucv_declare_buffer "
-		       "returned error 0x%02lx (%s)\n", __FUNCTION__, rc, err);
-		return NULL;
-	}
-	if (!register_flag) {
-		/* request the 0x4000 external interrupt */
-		rc = register_external_interrupt (0x4000, iucv_irq_handler);
-		if (rc) {
-			iucv_remove_handler(new_handler);
-			kfree (new_handler);
-			printk(KERN_WARNING "%s: "
-			       "register_external_interrupt returned %ld\n",
-			       __FUNCTION__, rc);
-			return NULL;
-
-		}
-		register_flag = 1;
-	}
-	iucv_debug(1, "exiting");
-	return new_handler;
-}				/* end of register function */
-
-/**
- * iucv_unregister_program:
- * @handle: address of handler
- *
- * Unregister application with IUCV.
- * Returns:
- *   0 on success, -EINVAL, if specified handle is invalid.
- */
-
-int
-iucv_unregister_program (iucv_handle_t handle)
-{
-	handler *h = NULL;
-	struct list_head *lh;
-	int i;
-	ulong flags;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "address of handler is %p", h);
-
-	/* Checking if handle is valid  */
-	spin_lock_irqsave (&iucv_lock, flags);
-	list_for_each(lh, &iucv_handler_table) {
-		if ((handler *)handle == list_entry(lh, handler, list)) {
-			h = (handler *)handle;
-			break;
-		}
-	}
-	if (!h) {
-		spin_unlock_irqrestore (&iucv_lock, flags);
-		if (handle)
-			printk(KERN_WARNING
-			       "%s: Handler not found in iucv_handler_table.\n",
-			       __FUNCTION__);
-		else
-			printk(KERN_WARNING
-			       "%s: NULL handle passed by application.\n",
-			       __FUNCTION__);
-		return -EINVAL;
-	}
-
-	/**
-	 * First, walk thru iucv_pathid_table and sever any pathid which is
-	 * still pointing to the handler to be removed.
-	 */
-	for (i = 0; i < max_connections; i++)
-		if (iucv_pathid_table[i] == h) {
-			spin_unlock_irqrestore (&iucv_lock, flags);
-			iucv_sever(i, h->id.user_data);
-			spin_lock_irqsave(&iucv_lock, flags);
-		}
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	iucv_remove_handler(h);
-	kfree(h);
-
-	iucv_debug(1, "exiting");
-	return 0;
-}
-
-/**
- * iucv_accept:
- * @pathid:             Path identification number
- * @msglim_reqstd:      The number of outstanding messages requested.
- * @user_data:          Data specified by the iucv_connect function.
- * @flags1:             Contains options for this path.
- *     - IPPRTY (0x20)   Specifies if you want to send priority message.
- *     - IPRMDATA (0x80) Specifies whether your program can handle a message
- *                       in the parameter list.
- *     - IPQUSCE (0x40)  Specifies whether you want to quiesce the path being
- *		         established.
- * @handle:             Address of handler.
- * @pgm_data:           Application data passed to interrupt handlers.
- * @flags1_out:         Pointer to an int. If not NULL, on return the options for
- *                      the path are stored at the given location:
- *     - IPPRTY (0x20)  Indicates you may send a priority message.
- * @msglim:             Pointer to an __u16. If not NULL, on return the maximum
- *                      number of outstanding messages is stored at the given
- *                      location.
- *
- * This function is issued after the user receives a Connection Pending external
- * interrupt and now wishes to complete the IUCV communication path.
- * Returns:
- *   return code from CP
- */
-int
-iucv_accept(__u16 pathid, __u16 msglim_reqstd,
-	     __u8 user_data[16], int flags1,
-	     iucv_handle_t handle, void *pgm_data,
-	     int *flags1_out, __u16 * msglim)
-{
-	ulong b2f0_result = 0;
-	ulong flags;
-	struct list_head *lh;
-	handler *h = NULL;
-	iparml_control *parm;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "pathid = %d", pathid);
-
-	/* Checking if handle is valid  */
-	spin_lock_irqsave (&iucv_lock, flags);
-	list_for_each(lh, &iucv_handler_table) {
-		if ((handler *)handle == list_entry(lh, handler, list)) {
-			h = (handler *)handle;
-			break;
-		}
-	}
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	if (!h) {
-		if (handle)
-			printk(KERN_WARNING
-			       "%s: Handler not found in iucv_handler_table.\n",
-			       __FUNCTION__);
-		else
-			printk(KERN_WARNING
-			       "%s: NULL handle passed by application.\n",
-			       __FUNCTION__);
-		return -EINVAL;
-	}
-
-	parm = (iparml_control *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->ipmsglim = msglim_reqstd;
-	if (user_data)
-		memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
-
-	parm->ipflags1 = (__u8)flags1;
-	b2f0_result = b2f0(ACCEPT, parm);
-
-	if (!b2f0_result) {
-		if (msglim)
-			*msglim = parm->ipmsglim;
-		if (pgm_data)
-			h->pgm_data = pgm_data;
-		if (flags1_out)
-			*flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
-	}
-	release_param(parm);
-
-	iucv_debug(1, "exiting");
-	return b2f0_result;
-}
-
-/**
- * iucv_connect:
- * @pathid:        Path identification number
- * @msglim_reqstd: Number of outstanding messages requested
- * @user_data:     16-byte user data
- * @userid:        8-byte of user identification
- * @system_name:   8-byte identifying the system name
- * @flags1:        Specifies options for this path:
- *     - IPPRTY (0x20)   Specifies if you want to send priority message.
- *     - IPRMDATA (0x80) Specifies whether your program can handle a message
- *                       in  the parameter list.
- *     - IPQUSCE (0x40)  Specifies whether you want to quiesce the path being
- *                       established.
- *     - IPLOCAL (0x01)  Allows an application to force the partner to be on the
- *                       local system. If local is specified then target class
- *                       cannot be specified.
- * @flags1_out:    Pointer to an int. If not NULL, on return the options for
- *                 the path are stored at the given location:
- *     - IPPRTY (0x20)   Indicates you may send a priority message.
- * @msglim:        Pointer to an __u16. If not NULL, on return the maximum
- *                 number of outstanding messages is stored at the given
- *                 location.
- * @handle:        Address of handler.
- * @pgm_data:      Application data to be passed to interrupt handlers.
- *
- * This function establishes an IUCV path. Although the connect may complete
- * successfully, you are not able to use the path until you receive an IUCV
- * Connection Complete external interrupt.
- * Returns: return code from CP, or one of the following
- *     - ENOMEM
- *     - return code from iucv_declare_buffer
- *     - EINVAL - invalid handle passed by application
- *     - EINVAL - pathid address is NULL
- *     - ENOMEM - pathid table storage allocation failed
- *     - return code from internal function add_pathid
- */
-int
-iucv_connect (__u16 *pathid, __u16 msglim_reqstd,
-	      __u8 user_data[16], __u8 userid[8],
-	      __u8 system_name[8], int flags1,
-	      int *flags1_out, __u16 * msglim,
-	      iucv_handle_t handle, void *pgm_data)
-{
-	iparml_control *parm;
-	iparml_control local_parm;
-	struct list_head *lh;
-	ulong b2f0_result = 0;
-	ulong flags;
-	int add_pathid_result = 0;
-	handler *h = NULL;
-	__u8 no_memory[16] = "NO MEMORY";
-
-	iucv_debug(1, "entering");
-
-	/* Checking if handle is valid  */
-	spin_lock_irqsave (&iucv_lock, flags);
-	list_for_each(lh, &iucv_handler_table) {
-		if ((handler *)handle == list_entry(lh, handler, list)) {
-			h = (handler *)handle;
-			break;
-		}
-	}
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	if (!h) {
-		if (handle)
-			printk(KERN_WARNING
-			       "%s: Handler not found in iucv_handler_table.\n",
-			       __FUNCTION__);
-		else
-			printk(KERN_WARNING
-			       "%s: NULL handle passed by application.\n",
-			       __FUNCTION__);
-		return -EINVAL;
-	}
-
-	if (pathid == NULL) {
-		printk(KERN_WARNING "%s: NULL pathid pointer\n",
-		       __FUNCTION__);
-		return -EINVAL;
-	}
-
-	parm = (iparml_control *)grab_param();
-
-	parm->ipmsglim = msglim_reqstd;
-
-	if (user_data)
-		memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
-
-	if (userid) {
-		memcpy(parm->ipvmid, userid, sizeof(parm->ipvmid));
-		ASCEBC(parm->ipvmid, sizeof(parm->ipvmid));
-		EBC_TOUPPER(parm->ipvmid, sizeof(parm->ipvmid));
-	}
-
-	if (system_name) {
-		memcpy(parm->iptarget, system_name, sizeof(parm->iptarget));
-		ASCEBC(parm->iptarget, sizeof(parm->iptarget));
-		EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget));
-	}
-
-	/* In order to establish an IUCV connection, the procedure is:
-         *
-         * b2f0(CONNECT)
-         * take the ippathid from the b2f0 call
-         * register the handler to the ippathid
-         *
-         * Unfortunately, the ConnectionEstablished message gets sent after the
-         * b2f0(CONNECT) call but before the register is handled.
-         *
-         * In order for this race condition to be eliminated, the IUCV Control
-         * Interrupts must be disabled for the above procedure.
-         *
-         * David Kennedy <dkennedy@linuxcare.com>
-         */
-
-	/* Enable everything but IUCV Control messages */
-	iucv_setmask(~(AllInterrupts));
-	messagesDisabled = 1;
-
-	spin_lock_irqsave (&iucv_lock, flags);
-	parm->ipflags1 = (__u8)flags1;
-	b2f0_result = b2f0(CONNECT, parm);
-	memcpy(&local_parm, parm, sizeof(local_parm));
-	release_param(parm);
-	parm = &local_parm;
-	if (!b2f0_result)
-		add_pathid_result = __iucv_add_pathid(parm->ippathid, h);
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	if (b2f0_result) {
-		iucv_setmask(~0);
-		messagesDisabled = 0;
-		return b2f0_result;
-	}
-
-	*pathid = parm->ippathid;
-
-	/* Enable everything again */
-	iucv_setmask(IUCVControlInterruptsFlag);
-
-	if (msglim)
-		*msglim = parm->ipmsglim;
-	if (flags1_out)
-		*flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
-
-	if (add_pathid_result) {
-		iucv_sever(*pathid, no_memory);
-		printk(KERN_WARNING "%s: add_pathid failed with rc ="
-			" %d\n", __FUNCTION__, add_pathid_result);
-		return(add_pathid_result);
-	}
-
-	iucv_debug(1, "exiting");
-	return b2f0_result;
-}
-
-/**
- * iucv_purge:
- * @pathid: Path identification number
- * @msgid:  Message ID of message to purge.
- * @srccls: Message class of the message to purge.
- * @audit:  Pointer to an __u32. If not NULL, on return, information about
- *          asynchronous errors that may have affected the normal completion
- *          of this message ist stored at the given location.
- *
- * Cancels a message you have sent.
- * Returns: return code from CP
- */
-int
-iucv_purge (__u16 pathid, __u32 msgid, __u32 srccls, __u32 *audit)
-{
-	iparml_purge *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "pathid = %d", pathid);
-
-	parm = (iparml_purge *)grab_param();
-
-	parm->ipmsgid = msgid;
-	parm->ippathid = pathid;
-	parm->ipsrccls = srccls;
-	parm->ipflags1 |= (IPSRCCLS | IPFGMID | IPFGPID);
-	b2f0_result = b2f0(PURGE, parm);
-
-	if (!b2f0_result && audit) {
-		memcpy(audit, parm->ipaudit, sizeof(parm->ipaudit));
-		/* parm->ipaudit has only 3 bytes */
-		*audit >>= 8;
-	}
-
-	release_param(parm);
-
-	iucv_debug(1, "b2f0_result = %ld", b2f0_result);
-	iucv_debug(1, "exiting");
-	return b2f0_result;
-}
-
-/**
- * iucv_query_generic:
- * @want_maxconn: Flag, describing which value is to be returned.
- *
- * Helper function for iucv_query_maxconn() and iucv_query_bufsize().
- *
- * Returns: The buffersize, if want_maxconn is 0; the maximum number of
- *           connections, if want_maxconn is 1 or an error-code < 0 on failure.
- */
-static int
-iucv_query_generic(int want_maxconn)
-{
-	register unsigned long reg0 asm ("0");
-	register unsigned long reg1 asm ("1");
-	iparml_purge *parm = (iparml_purge *)grab_param();
-	int bufsize, maxconn;
-	int ccode;
-
-	/**
-	 * Call b2f0 and store R0 (max buffer size),
-	 * R1 (max connections) and CC.
-	 */
-	reg0 = QUERY;
-	reg1 = virt_to_phys(parm);
-	asm volatile(
-		"	.long	0xb2f01000\n"
-		"	ipm	%0\n"
-		"	srl	%0,28\n"
-		: "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
-	bufsize = reg0;
-	maxconn = reg1;
-	release_param(parm);
-
-	if (ccode)
-		return -EPERM;
-	if (want_maxconn)
-		return maxconn;
-	return bufsize;
-}
-
-/**
- * iucv_query_maxconn:
- *
- * Determines the maximum number of connections thay may be established.
- *
- * Returns: Maximum number of connections that can be.
- */
-ulong
-iucv_query_maxconn(void)
-{
-	return iucv_query_generic(1);
-}
-
-/**
- * iucv_query_bufsize:
- *
- * Determines the size of the external interrupt buffer.
- *
- * Returns: Size of external interrupt buffer.
- */
-ulong
-iucv_query_bufsize (void)
-{
-	return iucv_query_generic(0);
-}
-
-/**
- * iucv_quiesce:
- * @pathid:    Path identification number
- * @user_data: 16-byte user data
- *
- * Temporarily suspends incoming messages on an IUCV path.
- * You can later reactivate the path by invoking the iucv_resume function.
- * Returns: return code from CP
- */
-int
-iucv_quiesce (__u16 pathid, __u8 user_data[16])
-{
-	iparml_control *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "pathid = %d", pathid);
-
-	parm = (iparml_control *)grab_param();
-
-	memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
-	parm->ippathid = pathid;
-
-	b2f0_result = b2f0(QUIESCE, parm);
-	release_param(parm);
-
-	iucv_debug(1, "b2f0_result = %ld", b2f0_result);
-	iucv_debug(1, "exiting");
-
-	return b2f0_result;
-}
-
-/**
- * iucv_receive:
- * @pathid: Path identification number.
- * @buffer: Address of buffer to receive. Must be below 2G.
- * @buflen: Length of buffer to receive.
- * @msgid:  Specifies the message ID.
- * @trgcls: Specifies target class.
- * @flags1_out: Receives options for path on return.
- *    - IPNORPY (0x10)  Specifies whether a reply is required
- *    - IPPRTY (0x20)   Specifies if you want to send priority message
- *    - IPRMDATA (0x80) Specifies the data is contained in the parameter list
- * @residual_buffer: Receives the address of buffer updated by the number
- *                   of bytes you have received on return.
- * @residual_length: On return, receives one of the following values:
- *    - 0                          If the receive buffer is the same length as
- *                                 the message.
- *    - Remaining bytes in buffer  If the receive buffer is longer than the
- *                                 message.
- *    - Remaining bytes in message If the receive buffer is shorter than the
- *                                 message.
- *
- * This function receives messages that are being sent to you over established
- * paths.
- * Returns: return code from CP IUCV call; If the receive buffer is shorter
- *   than the message, always 5
- *   -EINVAL - buffer address is pointing to NULL
- */
-int
-iucv_receive (__u16 pathid, __u32 msgid, __u32 trgcls,
-	      void *buffer, ulong buflen,
-	      int *flags1_out, ulong * residual_buffer, ulong * residual_length)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-	int moved = 0;	/* number of bytes moved from parmlist to buffer */
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ipbfadr1 = (__u32) (addr_t) buffer;
-	parm->ipbfln1f = (__u32) ((ulong) buflen);
-	parm->ipmsgid = msgid;
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipflags1 = (IPFGPID | IPFGMID | IPFGMCL);
-
-	b2f0_result = b2f0(RECEIVE, parm);
-
-	if (!b2f0_result || b2f0_result == 5) {
-		if (flags1_out) {
-			iucv_debug(2, "*flags1_out = %d", *flags1_out);
-			*flags1_out = (parm->ipflags1 & (~0x07));
-			iucv_debug(2, "*flags1_out = %d", *flags1_out);
-		}
-
-		if (!(parm->ipflags1 & IPRMDATA)) {	/*msg not in parmlist */
-			if (residual_length)
-				*residual_length = parm->ipbfln1f;
-
-			if (residual_buffer)
-				*residual_buffer = parm->ipbfadr1;
-		} else {
-			moved = min_t (unsigned long, buflen, 8);
-
-			memcpy ((char *) buffer,
-				(char *) &parm->ipbfadr1, moved);
-
-			if (buflen < 8)
-				b2f0_result = 5;
-
-			if (residual_length)
-				*residual_length = abs (buflen - 8);
-
-			if (residual_buffer)
-				*residual_buffer = (ulong) (buffer + moved);
-		}
-	}
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_receive_array
- * Purpose: This function receives messages that are being sent to you
- *          over established paths.
- * Input: pathid - path identification number
- *        buffer - address of array of buffers
- *        buflen - total length of buffers
- *        msgid - specifies the message ID.
- *        trgcls - specifies target class
- * Output:
- *        flags1_out: Options for path.
- *          IPNORPY - 0x10 specifies whether a reply is required
- *          IPPRTY - 0x20 specifies if you want to send priority message
- *         IPRMDATA - 0x80 specifies the data is contained in the parameter list
- *       residual_buffer - address points to the current list entry IUCV
- *                         is working on.
- *       residual_length -
- *              Contains one of the following values, if the receive buffer is:
- *               The same length as the message, this field is zero.
- *               Longer than the message, this field contains the number of
- *                bytes remaining in the buffer.
- *               Shorter than the message, this field contains the residual
- *                count (that is, the number of bytes remaining in the
- *                message that does not fit into the buffer. In this case
- *		  b2f0_result = 5.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer address is NULL
- */
-int
-iucv_receive_array (__u16 pathid,
-		    __u32 msgid, __u32 trgcls,
-		    iucv_array_t * buffer, ulong buflen,
-		    int *flags1_out,
-		    ulong * residual_buffer, ulong * residual_length)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-	int i = 0, moved = 0, need_to_move = 8, dyn_len;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ipbfadr1 = (__u32) ((ulong) buffer);
-	parm->ipbfln1f = (__u32) buflen;
-	parm->ipmsgid = msgid;
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipflags1 = (IPBUFLST | IPFGPID | IPFGMID | IPFGMCL);
-
-	b2f0_result = b2f0(RECEIVE, parm);
-
-	if (!b2f0_result || b2f0_result == 5) {
-
-		if (flags1_out) {
-			iucv_debug(2, "*flags1_out = %d", *flags1_out);
-			*flags1_out = (parm->ipflags1 & (~0x07));
-			iucv_debug(2, "*flags1_out = %d", *flags1_out);
-		}
-
-		if (!(parm->ipflags1 & IPRMDATA)) {	/*msg not in parmlist */
-
-			if (residual_length)
-				*residual_length = parm->ipbfln1f;
-
-			if (residual_buffer)
-				*residual_buffer = parm->ipbfadr1;
-
-		} else {
-			/* copy msg from parmlist to users array. */
-
-			while ((moved < 8) && (moved < buflen)) {
-				dyn_len =
-				    min_t (unsigned int,
-					 (buffer + i)->length, need_to_move);
-
-				memcpy ((char *)((ulong)((buffer + i)->address)),
-					((char *) &parm->ipbfadr1) + moved,
-					dyn_len);
-
-				moved += dyn_len;
-				need_to_move -= dyn_len;
-
-				(buffer + i)->address =
-				    	(__u32)
-				((ulong)(__u8 *) ((ulong)(buffer + i)->address)
-						+ dyn_len);
-
-				(buffer + i)->length -= dyn_len;
-				i++;
-			}
-
-			if (need_to_move)	/* buflen < 8 bytes */
-				b2f0_result = 5;
-
-			if (residual_length)
-				*residual_length = abs (buflen - 8);
-
-			if (residual_buffer) {
-				if (!moved)
-					*residual_buffer = (ulong) buffer;
-				else
-					*residual_buffer =
-					    (ulong) (buffer + (i - 1));
-			}
-
-		}
-	}
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-	return b2f0_result;
-}
-
-/**
- * iucv_reject:
- * @pathid: Path identification number.
- * @msgid:  Message ID of the message to reject.
- * @trgcls: Target class of the message to reject.
- * Returns: return code from CP
- *
- * Refuses a specified message. Between the time you are notified of a
- * message and the time that you complete the message, the message may
- * be rejected.
- */
-int
-iucv_reject (__u16 pathid, __u32 msgid, __u32 trgcls)
-{
-	iparml_db *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "pathid = %d", pathid);
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->ipmsgid = msgid;
-	parm->iptrgcls = trgcls;
-	parm->ipflags1 = (IPFGMCL | IPFGMID | IPFGPID);
-
-	b2f0_result = b2f0(REJECT, parm);
-	release_param(parm);
-
-	iucv_debug(1, "b2f0_result = %ld", b2f0_result);
-	iucv_debug(1, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_reply
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- * Input: pathid - path identification number
- *        msgid - specifies the message ID.
- *        trgcls - specifies target class
- *        flags1 - option for path
- *                 IPPRTY- 0x20 - specifies if you want to send priority message
- *        buffer - address of reply buffer
- *        buflen - length of reply buffer
- * Output: ipbfadr2 - Address of buffer updated by the number
- *                    of bytes you have moved.
- *         ipbfln2f - Contains one of the following values:
- *              If the answer buffer is the same length as the reply, this field
- *               contains zero.
- *              If the answer buffer is longer than the reply, this field contains
- *               the number of bytes remaining in the buffer.
- *              If the answer buffer is shorter than the reply, this field contains
- *               a residual count (that is, the number of bytes remianing in the
- *               reply that does not fit into the buffer. In this
- *                case b2f0_result = 5.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer address is NULL
- */
-int
-iucv_reply (__u16 pathid,
-	    __u32 msgid, __u32 trgcls,
-	    int flags1,
-	    void *buffer, ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ipbfadr2 = (__u32) ((ulong) buffer);
-	parm->ipbfln2f = (__u32) buflen;	/* length of message */
-	parm->ippathid = pathid;
-	parm->ipmsgid = msgid;
-	parm->iptrgcls = trgcls;
-	parm->ipflags1 = (__u8) flags1;	/* priority message */
-
-	b2f0_result = b2f0(REPLY, parm);
-
-	if ((!b2f0_result) || (b2f0_result == 5)) {
-		if (ipbfadr2)
-			*ipbfadr2 = parm->ipbfadr2;
-		if (ipbfln2f)
-			*ipbfln2f = parm->ipbfln2f;
-	}
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_reply_array
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- *          The array identifies a list of addresses and lengths of
- *          discontiguous buffers that contains the reply data.
- * Input: pathid - path identification number
- *        msgid - specifies the message ID.
- *        trgcls - specifies target class
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        buffer - address of array of reply buffers
- *        buflen - total length of reply buffers
- * Output: ipbfadr2 - Address of buffer which IUCV is currently working on.
- *         ipbfln2f - Contains one of the following values:
- *              If the answer buffer is the same length as the reply, this field
- *               contains zero.
- *              If the answer buffer is longer than the reply, this field contains
- *               the number of bytes remaining in the buffer.
- *              If the answer buffer is shorter than the reply, this field contains
- *               a residual count (that is, the number of bytes remianing in the
- *               reply that does not fit into the buffer. In this
- *               case b2f0_result = 5.
- * Return: b2f0_result - return code from CP
- *             (-EINVAL) - buffer address is NULL
-*/
-int
-iucv_reply_array (__u16 pathid,
-		  __u32 msgid, __u32 trgcls,
-		  int flags1,
-		  iucv_array_t * buffer,
-		  ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ipbfadr2 = (__u32) ((ulong) buffer);
-	parm->ipbfln2f = buflen;	/* length of message */
-	parm->ippathid = pathid;
-	parm->ipmsgid = msgid;
-	parm->iptrgcls = trgcls;
-	parm->ipflags1 = (IPANSLST | flags1);
-
-	b2f0_result = b2f0(REPLY, parm);
-
-	if ((!b2f0_result) || (b2f0_result == 5)) {
-
-		if (ipbfadr2)
-			*ipbfadr2 = parm->ipbfadr2;
-		if (ipbfln2f)
-			*ipbfln2f = parm->ipbfln2f;
-	}
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_reply_prmmsg
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- *          Prmmsg signifies the data is moved into the
- *          parameter list.
- * Input: pathid - path identification number
- *        msgid - specifies the message ID.
- *        trgcls - specifies target class
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        prmmsg - 8-bytes of data to be placed into the parameter
- *                 list.
- * Output: NA
- * Return: b2f0_result - return code from CP
-*/
-int
-iucv_reply_prmmsg (__u16 pathid,
-		   __u32 msgid, __u32 trgcls, int flags1, __u8 prmmsg[8])
-{
-	iparml_dpl *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	parm = (iparml_dpl *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->ipmsgid = msgid;
-	parm->iptrgcls = trgcls;
-	memcpy(parm->iprmmsg, prmmsg, sizeof (parm->iprmmsg));
-	parm->ipflags1 = (IPRMDATA | flags1);
-
-	b2f0_result = b2f0(REPLY, parm);
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/**
- * iucv_resume:
- * @pathid:    Path identification number
- * @user_data: 16-byte of user data
- *
- * This function restores communication over a quiesced path.
- * Returns: return code from CP
- */
-int
-iucv_resume (__u16 pathid, __u8 user_data[16])
-{
-	iparml_control *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "pathid = %d", pathid);
-
-	parm = (iparml_control *)grab_param();
-
-	memcpy (parm->ipuser, user_data, sizeof (*user_data));
-	parm->ippathid = pathid;
-
-	b2f0_result = b2f0(RESUME, parm);
-	release_param(parm);
-
-	iucv_debug(1, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send
- * Purpose: sends messages
- * Input: pathid - ushort, pathid
- *        msgid  - ulong *, id of message returned to caller
- *        trgcls - ulong, target message class
- *        srccls - ulong, source message class
- *        msgtag - ulong, message tag
- *	  flags1  - Contains options for this path.
- *		IPPRTY - Ox20 - specifies if you want to send a priority message.
- *        buffer - pointer to buffer
- *        buflen - ulong, length of buffer
- * Output: b2f0_result - return code from b2f0 call
- *         msgid - returns message id
- */
-int
-iucv_send (__u16 pathid, __u32 * msgid,
-	   __u32 trgcls, __u32 srccls,
-	   __u32 msgtag, int flags1, void *buffer, ulong buflen)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ipbfadr1 = (__u32) ((ulong) buffer);
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipbfln1f = (__u32) buflen;	/* length of message */
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipflags1 = (IPNORPY | flags1);	/* one way priority message */
-
-	b2f0_result = b2f0(SEND, parm);
-
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send_array
- * Purpose: This function transmits data to another application.
- *          The contents of buffer is the address of the array of
- *          addresses and lengths of discontiguous buffers that hold
- *          the message text. This is a one-way message and the
- *          receiver will not reply to the message.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - specifies a tag to be associated witht the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        buffer - address of array of send buffers
- *        buflen - total length of send buffers
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer address is NULL
- */
-int
-iucv_send_array (__u16 pathid,
-		 __u32 * msgid,
-		 __u32 trgcls,
-		 __u32 srccls,
-		 __u32 msgtag, int flags1, iucv_array_t * buffer, ulong buflen)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipbfadr1 = (__u32) ((ulong) buffer);
-	parm->ipbfln1f = (__u32) buflen;	/* length of message */
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipflags1 = (IPNORPY | IPBUFLST | flags1);
-	b2f0_result = b2f0(SEND, parm);
-
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send_prmmsg
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a one-way message and the
- *          receiver will not reply to the message.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - specifies a tag to be associated with the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        prmmsg - 8-bytes of data to be placed into parameter list
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
-*/
-int
-iucv_send_prmmsg (__u16 pathid,
-		  __u32 * msgid,
-		  __u32 trgcls,
-		  __u32 srccls, __u32 msgtag, int flags1, __u8 prmmsg[8])
-{
-	iparml_dpl *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	parm = (iparml_dpl *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipflags1 = (IPRMDATA | IPNORPY | flags1);
-	memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
-
-	b2f0_result = b2f0(SEND, parm);
-
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way
- * Purpose: This function transmits data to another application.
- *          Data to be transmitted is in a buffer. The receiver
- *          of the send is expected to reply to the message and
- *          a buffer is provided into which IUCV moves the reply
- *          to this message.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - specifies a tag associated with the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        buffer - address of send buffer
- *        buflen - length of send buffer
- *        ansbuf - address of buffer to reply with
- *        anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer or ansbuf address is NULL
- */
-int
-iucv_send2way (__u16 pathid,
-	       __u32 * msgid,
-	       __u32 trgcls,
-	       __u32 srccls,
-	       __u32 msgtag,
-	       int flags1,
-	       void *buffer, ulong buflen, void *ansbuf, ulong anslen)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer || !ansbuf)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipbfadr1 = (__u32) ((ulong) buffer);
-	parm->ipbfln1f = (__u32) buflen;	/* length of message */
-	parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
-	parm->ipbfln2f = (__u32) anslen;
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipflags1 = flags1;	/* priority message */
-
-	b2f0_result = b2f0(SEND, parm);
-
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way_array
- * Purpose: This function transmits data to another application.
- *          The contents of buffer is the address of the array of
- *          addresses and lengths of discontiguous buffers that hold
- *          the message text. The receiver of the send is expected to
- *          reply to the message and a buffer is provided into which
- *          IUCV moves the reply to this message.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - spcifies a tag to be associated with the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        buffer - address of array of send buffers
- *        buflen - total length of send buffers
- *        ansbuf - address of buffer to reply with
- *        anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer address is NULL
- */
-int
-iucv_send2way_array (__u16 pathid,
-		     __u32 * msgid,
-		     __u32 trgcls,
-		     __u32 srccls,
-		     __u32 msgtag,
-		     int flags1,
-		     iucv_array_t * buffer,
-		     ulong buflen, iucv_array_t * ansbuf, ulong anslen)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer || !ansbuf)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipbfadr1 = (__u32) ((ulong) buffer);
-	parm->ipbfln1f = (__u32) buflen;	/* length of message */
-	parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
-	parm->ipbfln2f = (__u32) anslen;
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipflags1 = (IPBUFLST | IPANSLST | flags1);
-	b2f0_result = b2f0(SEND, parm);
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way_prmmsg
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a two-way message and the
- *          receiver of the message is expected to reply. A buffer
- *          is provided into which IUCV moves the reply to this
- *          message.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - specifies a tag to be associated with the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        prmmsg - 8-bytes of data to be placed in parameter list
- *        ansbuf - address of buffer to reply with
- *        anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer address is NULL
-*/
-int
-iucv_send2way_prmmsg (__u16 pathid,
-		      __u32 * msgid,
-		      __u32 trgcls,
-		      __u32 srccls,
-		      __u32 msgtag,
-		      ulong flags1, __u8 prmmsg[8], void *ansbuf, ulong anslen)
-{
-	iparml_dpl *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!ansbuf)
-		return -EINVAL;
-
-	parm = (iparml_dpl *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
-	parm->ipbfln2f = (__u32) anslen;
-	parm->ipflags1 = (IPRMDATA | flags1);	/* message in prmlist */
-	memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
-
-	b2f0_result = b2f0(SEND, parm);
-
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way_prmmsg_array
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a two-way message and the
- *          receiver of the message is expected to reply. A buffer
- *          is provided into which IUCV moves the reply to this
- *          message. The contents of ansbuf is the address of the
- *          array of addresses and lengths of discontiguous buffers
- *          that contain the reply.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - specifies a tag to be associated with the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        prmmsg - 8-bytes of data to be placed into the parameter list
- *        ansbuf - address of buffer to reply with
- *        anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - ansbuf address is NULL
- */
-int
-iucv_send2way_prmmsg_array (__u16 pathid,
-			    __u32 * msgid,
-			    __u32 trgcls,
-			    __u32 srccls,
-			    __u32 msgtag,
-			    int flags1,
-			    __u8 prmmsg[8],
-			    iucv_array_t * ansbuf, ulong anslen)
-{
-	iparml_dpl *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!ansbuf)
-		return -EINVAL;
-
-	parm = (iparml_dpl *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
-	parm->ipbfln2f = (__u32) anslen;
-	parm->ipflags1 = (IPRMDATA | IPANSLST | flags1);
-	memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
-	b2f0_result = b2f0(SEND, parm);
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-	return b2f0_result;
-}
-
-void
-iucv_setmask_cpuid (void *result)
-{
-        iparml_set_mask *parm;
-
-        iucv_debug(1, "entering");
-        parm = (iparml_set_mask *)grab_param();
-        parm->ipmask = *((__u8*)result);
-        *((ulong *)result) = b2f0(SETMASK, parm);
-        release_param(parm);
-
-        iucv_debug(1, "b2f0_result = %ld", *((ulong *)result));
-        iucv_debug(1, "exiting");
-}
-
-/*
- * Name: iucv_setmask
- * Purpose: This function enables or disables the following IUCV
- *          external interruptions: Nonpriority and priority message
- *          interrupts, nonpriority and priority reply interrupts.
- * Input: SetMaskFlag - options for interrupts
- *           0x80 - Nonpriority_MessagePendingInterruptsFlag
- *           0x40 - Priority_MessagePendingInterruptsFlag
- *           0x20 - Nonpriority_MessageCompletionInterruptsFlag
- *           0x10 - Priority_MessageCompletionInterruptsFlag
- *           0x08 - IUCVControlInterruptsFlag
- * Output: NA
- * Return: b2f0_result - return code from CP
-*/
-int
-iucv_setmask (int SetMaskFlag)
-{
-	union {
-		ulong result;
-		__u8  param;
-	} u;
-	int cpu;
-
-	u.param = SetMaskFlag;
-	cpu = get_cpu();
-	smp_call_function_on(iucv_setmask_cpuid, &u, 0, 1, iucv_cpuid);
-	put_cpu();
-
-	return u.result;
-}
-
-/**
- * iucv_sever:
- * @pathid:    Path identification number
- * @user_data: 16-byte of user data
- *
- * This function terminates an iucv path.
- * Returns: return code from CP
- */
-int
-iucv_sever(__u16 pathid, __u8 user_data[16])
-{
-	iparml_control *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-	parm = (iparml_control *)grab_param();
-
-	memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
-	parm->ippathid = pathid;
-
-	b2f0_result = b2f0(SEVER, parm);
-
-	if (!b2f0_result)
-		iucv_remove_pathid(pathid);
-	release_param(parm);
-
-	iucv_debug(1, "exiting");
-	return b2f0_result;
-}
-
-/*
- * Interrupt Handlers
- *******************************************************************************/
-
-/**
- * iucv_irq_handler:
- * @regs: Current registers
- * @code: irq code
- *
- * Handles external interrupts coming in from CP.
- * Places the interrupt buffer on a queue and schedules iucv_tasklet_handler().
- */
-static void
-iucv_irq_handler(__u16 code)
-{
-	iucv_irqdata *irqdata;
-
-	irqdata = kmalloc(sizeof(iucv_irqdata), GFP_ATOMIC);
-	if (!irqdata) {
-		printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
-		return;
-	}
-
-	memcpy(&irqdata->data, iucv_external_int_buffer,
-	       sizeof(iucv_GeneralInterrupt));
-
-	spin_lock(&iucv_irq_queue_lock);
-	list_add_tail(&irqdata->queue, &iucv_irq_queue);
-	spin_unlock(&iucv_irq_queue_lock);
-
-	tasklet_schedule(&iucv_tasklet);
-}
-
-/**
- * iucv_do_int:
- * @int_buf: Pointer to copy of external interrupt buffer
- *
- * The workhorse for handling interrupts queued by iucv_irq_handler().
- * This function is called from the bottom half iucv_tasklet_handler().
- */
-static void
-iucv_do_int(iucv_GeneralInterrupt * int_buf)
-{
-	handler *h = NULL;
-	struct list_head *lh;
-	ulong flags;
-	iucv_interrupt_ops_t *interrupt = NULL;	/* interrupt addresses */
-	__u8 temp_buff1[24], temp_buff2[24];	/* masked handler id. */
-	int rc = 0, j = 0;
-	__u8 no_listener[16] = "NO LISTENER";
-
-	iucv_debug(2, "entering, pathid %d, type %02X",
-		 int_buf->ippathid, int_buf->iptype);
-	iucv_dumpit("External Interrupt Buffer:",
-		    int_buf, sizeof(iucv_GeneralInterrupt));
-
-	ASCEBC (no_listener, 16);
-
-	if (int_buf->iptype != 01) {
-		if ((int_buf->ippathid) > (max_connections - 1)) {
-			printk(KERN_WARNING "%s: Got interrupt with pathid %d"
-			       " > max_connections (%ld)\n", __FUNCTION__,
-			       int_buf->ippathid, max_connections - 1);
-		} else {
-			h = iucv_pathid_table[int_buf->ippathid];
-			interrupt = h->interrupt_table;
-			iucv_dumpit("Handler:", h, sizeof(handler));
-		}
-	}
-
-	/* end of if statement */
-	switch (int_buf->iptype) {
-		case 0x01:		/* connection pending */
-			if (messagesDisabled) {
-			    iucv_setmask(~0);
-			    messagesDisabled = 0;
-			}
-			spin_lock_irqsave(&iucv_lock, flags);
-			list_for_each(lh, &iucv_handler_table) {
-				h = list_entry(lh, handler, list);
-				memcpy(temp_buff1, &(int_buf->ipvmid), 24);
-				memcpy(temp_buff2, &(h->id.userid), 24);
-				for (j = 0; j < 24; j++) {
-					temp_buff1[j] &= (h->id.mask)[j];
-					temp_buff2[j] &= (h->id.mask)[j];
-				}
-
-				iucv_dumpit("temp_buff1:",
-					    temp_buff1, sizeof(temp_buff1));
-				iucv_dumpit("temp_buff2",
-					    temp_buff2, sizeof(temp_buff2));
-
-				if (!memcmp (temp_buff1, temp_buff2, 24)) {
-
-					iucv_debug(2,
-						   "found a matching handler");
-					break;
-				} else
-					h = NULL;
-			}
-			spin_unlock_irqrestore (&iucv_lock, flags);
-			if (h) {
-				/* ADD PATH TO PATHID TABLE */
-				rc = iucv_add_pathid(int_buf->ippathid, h);
-				if (rc) {
-					iucv_sever (int_buf->ippathid,
-						    no_listener);
-					iucv_debug(1,
-						   "add_pathid failed, rc = %d",
-						   rc);
-				} else {
-					interrupt = h->interrupt_table;
-					if (interrupt->ConnectionPending) {
-						EBCASC (int_buf->ipvmid, 8);
-						interrupt->ConnectionPending(
-							(iucv_ConnectionPending *)int_buf,
-							h->pgm_data);
-					} else
-						iucv_sever(int_buf->ippathid,
-							   no_listener);
-				}
-			} else
-				iucv_sever(int_buf->ippathid, no_listener);
-			break;
-
-		case 0x02:		/*connection complete */
-			if (messagesDisabled) {
-			    iucv_setmask(~0);
-			    messagesDisabled = 0;
-			}
-			if (h) {
-				if (interrupt->ConnectionComplete)
-				{
-					interrupt->ConnectionComplete(
-						(iucv_ConnectionComplete *)int_buf,
-						h->pgm_data);
-				}
-				else
-					iucv_debug(1,
-						   "ConnectionComplete not called");
-			} else
-				iucv_sever(int_buf->ippathid, no_listener);
-			break;
-
-		case 0x03:		/* connection severed */
-			if (messagesDisabled) {
-			    iucv_setmask(~0);
-			    messagesDisabled = 0;
-			}
-			if (h) {
-				if (interrupt->ConnectionSevered)
-					interrupt->ConnectionSevered(
-						(iucv_ConnectionSevered *)int_buf,
-						h->pgm_data);
-
-				else
-					iucv_sever (int_buf->ippathid, no_listener);
-			} else
-				iucv_sever(int_buf->ippathid, no_listener);
-			break;
-
-		case 0x04:		/* connection quiesced */
-			if (messagesDisabled) {
-			    iucv_setmask(~0);
-			    messagesDisabled = 0;
-			}
-			if (h) {
-				if (interrupt->ConnectionQuiesced)
-					interrupt->ConnectionQuiesced(
-						(iucv_ConnectionQuiesced *)int_buf,
-						h->pgm_data);
-				else
-					iucv_debug(1,
-						   "ConnectionQuiesced not called");
-			}
-			break;
-
-		case 0x05:		/* connection resumed */
-			if (messagesDisabled) {
-			    iucv_setmask(~0);
-			    messagesDisabled = 0;
-			}
-			if (h) {
-				if (interrupt->ConnectionResumed)
-					interrupt->ConnectionResumed(
-						(iucv_ConnectionResumed *)int_buf,
-						h->pgm_data);
-				else
-					iucv_debug(1,
-						   "ConnectionResumed not called");
-			}
-			break;
-
-		case 0x06:		/* priority message complete */
-		case 0x07:		/* nonpriority message complete */
-			if (h) {
-				if (interrupt->MessageComplete)
-					interrupt->MessageComplete(
-						(iucv_MessageComplete *)int_buf,
-						h->pgm_data);
-				else
-					iucv_debug(2,
-						   "MessageComplete not called");
-			}
-			break;
-
-		case 0x08:		/* priority message pending  */
-		case 0x09:		/* nonpriority message pending  */
-			if (h) {
-				if (interrupt->MessagePending)
-					interrupt->MessagePending(
-						(iucv_MessagePending *) int_buf,
-						h->pgm_data);
-				else
-					iucv_debug(2,
-						   "MessagePending not called");
-			}
-			break;
-		default:		/* unknown iucv type */
-			printk(KERN_WARNING "%s: unknown iucv interrupt\n",
-			       __FUNCTION__);
-			break;
-	}			/* end switch */
-
-	iucv_debug(2, "exiting pathid %d, type %02X",
-		 int_buf->ippathid, int_buf->iptype);
-
-	return;
-}
-
-/**
- * iucv_tasklet_handler:
- *
- * This function loops over the queue of irq buffers and runs iucv_do_int()
- * on every queue element.
- */
-static void
-iucv_tasklet_handler(unsigned long ignored)
-{
-	struct list_head head;
-	struct list_head *next;
-	ulong  flags;
-
-	spin_lock_irqsave(&iucv_irq_queue_lock, flags);
-	list_add(&head, &iucv_irq_queue);
-	list_del_init(&iucv_irq_queue);
-	spin_unlock_irqrestore (&iucv_irq_queue_lock, flags);
-
-	next = head.next;
-	while (next != &head) {
-		iucv_irqdata *p = list_entry(next, iucv_irqdata, queue);
-
-		next = next->next;
-		iucv_do_int(&p->data);
-		kfree(p);
-	}
-
-	return;
-}
-
-subsys_initcall(iucv_init);
-module_exit(iucv_exit);
-
-/**
- * Export all public stuff
- */
-EXPORT_SYMBOL (iucv_bus);
-EXPORT_SYMBOL (iucv_root);
-EXPORT_SYMBOL (iucv_accept);
-EXPORT_SYMBOL (iucv_connect);
-#if 0
-EXPORT_SYMBOL (iucv_purge);
-EXPORT_SYMBOL (iucv_query_maxconn);
-EXPORT_SYMBOL (iucv_query_bufsize);
-EXPORT_SYMBOL (iucv_quiesce);
-#endif
-EXPORT_SYMBOL (iucv_receive);
-#if 0
-EXPORT_SYMBOL (iucv_receive_array);
-#endif
-EXPORT_SYMBOL (iucv_reject);
-#if 0
-EXPORT_SYMBOL (iucv_reply);
-EXPORT_SYMBOL (iucv_reply_array);
-EXPORT_SYMBOL (iucv_resume);
-#endif
-EXPORT_SYMBOL (iucv_reply_prmmsg);
-EXPORT_SYMBOL (iucv_send);
-EXPORT_SYMBOL (iucv_send2way);
-EXPORT_SYMBOL (iucv_send2way_array);
-EXPORT_SYMBOL (iucv_send2way_prmmsg);
-EXPORT_SYMBOL (iucv_send2way_prmmsg_array);
-#if 0
-EXPORT_SYMBOL (iucv_send_array);
-EXPORT_SYMBOL (iucv_send_prmmsg);
-EXPORT_SYMBOL (iucv_setmask);
-#endif
-EXPORT_SYMBOL (iucv_sever);
-EXPORT_SYMBOL (iucv_register_program);
-EXPORT_SYMBOL (iucv_unregister_program);
diff --git a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h
deleted file mode 100644
index 5b6b1b7..0000000
--- a/drivers/s390/net/iucv.h
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- *  drivers/s390/net/iucv.h
- *    IUCV base support.
- *
- *  S390 version
- *    Copyright (C) 2000 IBM Corporation
- *    Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
- *		Xenia Tkatschow (xenia@us.ibm.com)
- *
- *
- * Functionality:
- * To explore any of the IUCV functions, one must first register
- * their program using iucv_register_program(). Once your program has
- * successfully completed a register, it can exploit the other functions.
- * For furthur reference on all IUCV functionality, refer to the
- * CP Programming Services book, also available on the web
- * thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
- *
- *      Definition of Return Codes
- *      -All positive return codes including zero are reflected back
- *       from CP except for iucv_register_program. The definition of each
- *       return code can be found in CP Programming Services book.
- *       Also available on the web thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
- *      - Return Code of:
- *             (-EINVAL) Invalid value
- *             (-ENOMEM) storage allocation failed
- *	pgmask defined in iucv_register_program will be set depending on input
- *	paramters.
- *
- */
-
-#include <linux/types.h>
-#include <asm/debug.h>
-
-/**
- * Debug Facility stuff
- */
-#define IUCV_DBF_SETUP_NAME "iucv_setup"
-#define IUCV_DBF_SETUP_LEN 32
-#define IUCV_DBF_SETUP_PAGES 2
-#define IUCV_DBF_SETUP_NR_AREAS 1
-#define IUCV_DBF_SETUP_LEVEL 3
-
-#define IUCV_DBF_DATA_NAME "iucv_data"
-#define IUCV_DBF_DATA_LEN 128
-#define IUCV_DBF_DATA_PAGES 2
-#define IUCV_DBF_DATA_NR_AREAS 1
-#define IUCV_DBF_DATA_LEVEL 2
-
-#define IUCV_DBF_TRACE_NAME "iucv_trace"
-#define IUCV_DBF_TRACE_LEN 16
-#define IUCV_DBF_TRACE_PAGES 4
-#define IUCV_DBF_TRACE_NR_AREAS 1
-#define IUCV_DBF_TRACE_LEVEL 3
-
-#define IUCV_DBF_TEXT(name,level,text) \
-	do { \
-		debug_text_event(iucv_dbf_##name,level,text); \
-	} while (0)
-
-#define IUCV_DBF_HEX(name,level,addr,len) \
-	do { \
-		debug_event(iucv_dbf_##name,level,(void*)(addr),len); \
-	} while (0)
-
-DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
-
-#define IUCV_DBF_TEXT_(name,level,text...)				\
-	do {								\
-		char* iucv_dbf_txt_buf = get_cpu_var(iucv_dbf_txt_buf);	\
-		sprintf(iucv_dbf_txt_buf, text);		  	\
-		debug_text_event(iucv_dbf_##name,level,iucv_dbf_txt_buf); \
-		put_cpu_var(iucv_dbf_txt_buf);				\
-	} while (0)
-
-#define IUCV_DBF_SPRINTF(name,level,text...) \
-	do { \
-		debug_sprintf_event(iucv_dbf_trace, level, ##text ); \
-		debug_sprintf_event(iucv_dbf_trace, level, text ); \
-	} while (0)
-
-/**
- * some more debug stuff
- */
-#define IUCV_HEXDUMP16(importance,header,ptr) \
-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
-		   *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
-		   *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
-		   *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
-		   *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
-		   *(((char*)ptr)+12),*(((char*)ptr)+13), \
-		   *(((char*)ptr)+14),*(((char*)ptr)+15)); \
-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
-		   *(((char*)ptr)+16),*(((char*)ptr)+17), \
-		   *(((char*)ptr)+18),*(((char*)ptr)+19), \
-		   *(((char*)ptr)+20),*(((char*)ptr)+21), \
-		   *(((char*)ptr)+22),*(((char*)ptr)+23), \
-		   *(((char*)ptr)+24),*(((char*)ptr)+25), \
-		   *(((char*)ptr)+26),*(((char*)ptr)+27), \
-		   *(((char*)ptr)+28),*(((char*)ptr)+29), \
-		   *(((char*)ptr)+30),*(((char*)ptr)+31));
-
-static inline void
-iucv_hex_dump(unsigned char *buf, size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < len; i++) {
-		if (i && !(i % 16))
-			printk("\n");
-		printk("%02x ", *(buf + i));
-	}
-	printk("\n");
-}
-/**
- * end of debug stuff
- */
-
-#define uchar  unsigned char
-#define ushort unsigned short
-#define ulong  unsigned long
-#define iucv_handle_t void *
-
-/* flags1:
- * All flags are defined in the field IPFLAGS1 of each function
- * and can be found in CP Programming Services.
- * IPLOCAL  - Indicates the connect can only be satisfied on the
- *            local system
- * IPPRTY   - Indicates a priority message
- * IPQUSCE  - Indicates you do not want to receive messages on a
- *            path until an iucv_resume is issued
- * IPRMDATA - Indicates that the message is in the parameter list
- */
-#define IPLOCAL   	0x01
-#define IPPRTY         	0x20
-#define IPQUSCE        	0x40
-#define IPRMDATA       	0x80
-
-/* flags1_out:
- * All flags are defined in the output field of IPFLAGS1 for each function
- * and can be found in CP Programming Services.
- * IPNORPY - Specifies this is a one-way message and no reply is expected.
- * IPPRTY   - Indicates a priority message is permitted. Defined in flags1.
- */
-#define IPNORPY         0x10
-
-#define Nonpriority_MessagePendingInterruptsFlag         0x80
-#define Priority_MessagePendingInterruptsFlag            0x40
-#define Nonpriority_MessageCompletionInterruptsFlag      0x20
-#define Priority_MessageCompletionInterruptsFlag         0x10
-#define IUCVControlInterruptsFlag                        0x08
-#define AllInterrupts                                    0xf8
-/*
- * Mapping of external interrupt buffers should be used with the corresponding
- * interrupt types.
- * Names: iucv_ConnectionPending    ->  connection pending
- *        iucv_ConnectionComplete   ->  connection complete
- *        iucv_ConnectionSevered    ->  connection severed
- *        iucv_ConnectionQuiesced   ->  connection quiesced
- *        iucv_ConnectionResumed    ->  connection resumed
- *        iucv_MessagePending       ->  message pending
- *        iucv_MessageComplete      ->  message complete
- */
-typedef struct {
-	u16 ippathid;
-	uchar ipflags1;
-	uchar iptype;
-	u16 ipmsglim;
-	u16 res1;
-	uchar ipvmid[8];
-	uchar ipuser[16];
-	u32 res3;
-	uchar ippollfg;
-	uchar res4[3];
-} iucv_ConnectionPending;
-
-typedef struct {
-	u16 ippathid;
-	uchar ipflags1;
-	uchar iptype;
-	u16 ipmsglim;
-	u16 res1;
-	uchar res2[8];
-	uchar ipuser[16];
-	u32 res3;
-	uchar ippollfg;
-	uchar res4[3];
-} iucv_ConnectionComplete;
-
-typedef struct {
-	u16 ippathid;
-	uchar res1;
-	uchar iptype;
-	u32 res2;
-	uchar res3[8];
-	uchar ipuser[16];
-	u32 res4;
-	uchar ippollfg;
-	uchar res5[3];
-} iucv_ConnectionSevered;
-
-typedef struct {
-	u16 ippathid;
-	uchar res1;
-	uchar iptype;
-	u32 res2;
-	uchar res3[8];
-	uchar ipuser[16];
-	u32 res4;
-	uchar ippollfg;
-	uchar res5[3];
-} iucv_ConnectionQuiesced;
-
-typedef struct {
-	u16 ippathid;
-	uchar res1;
-	uchar iptype;
-	u32 res2;
-	uchar res3[8];
-	uchar ipuser[16];
-	u32 res4;
-	uchar ippollfg;
-	uchar res5[3];
-} iucv_ConnectionResumed;
-
-typedef struct {
-	u16 ippathid;
-	uchar ipflags1;
-	uchar iptype;
-	u32 ipmsgid;
-	u32 iptrgcls;
-	union u2 {
-		u32 iprmmsg1_u32;
-		uchar iprmmsg1[4];
-	} ln1msg1;
-	union u1 {
-		u32 ipbfln1f;
-		uchar iprmmsg2[4];
-	} ln1msg2;
-	u32 res1[3];
-	u32 ipbfln2f;
-	uchar ippollfg;
-	uchar res2[3];
-} iucv_MessagePending;
-
-typedef struct {
-	u16 ippathid;
-	uchar ipflags1;
-	uchar iptype;
-	u32 ipmsgid;
-	u32 ipaudit;
-	uchar iprmmsg[8];
-	u32 ipsrccls;
-	u32 ipmsgtag;
-	u32 res;
-	u32 ipbfln2f;
-	uchar ippollfg;
-	uchar res2[3];
-} iucv_MessageComplete;
-
-/*
- * iucv_interrupt_ops_t: Is a vector of functions that handle
- * IUCV interrupts.
- * Parameter list:
- *         eib - is a pointer to a 40-byte area described
- *               with one of the structures above.
- *         pgm_data - this data is strictly for the
- *                    interrupt handler that is passed by
- *                    the application. This may be an address
- *                    or token.
-*/
-typedef struct {
-	void (*ConnectionPending) (iucv_ConnectionPending * eib,
-				   void *pgm_data);
-	void (*ConnectionComplete) (iucv_ConnectionComplete * eib,
-				    void *pgm_data);
-	void (*ConnectionSevered) (iucv_ConnectionSevered * eib,
-				   void *pgm_data);
-	void (*ConnectionQuiesced) (iucv_ConnectionQuiesced * eib,
-				    void *pgm_data);
-	void (*ConnectionResumed) (iucv_ConnectionResumed * eib,
-				   void *pgm_data);
-	void (*MessagePending) (iucv_MessagePending * eib, void *pgm_data);
-	void (*MessageComplete) (iucv_MessageComplete * eib, void *pgm_data);
-} iucv_interrupt_ops_t;
-
-/*
- *iucv_array_t : Defines buffer array.
- * Inside the array may be 31- bit addresses and 31-bit lengths.
-*/
-typedef struct {
-	u32 address;
-	u32 length;
-} iucv_array_t __attribute__ ((aligned (8)));
-
-extern struct bus_type iucv_bus;
-extern struct device *iucv_root;
-
-/*   -prototypes-    */
-/*
- * Name: iucv_register_program
- * Purpose: Registers an application with IUCV
- * Input: prmname - user identification
- *        userid  - machine identification
- *        pgmmask - indicates which bits in the prmname and userid combined will be
- *  		    used to determine who is given control
- *        ops     - address of vector of interrupt handlers
- *        pgm_data- application data passed to interrupt handlers
- * Output: NA
- * Return: address of handler
- *         (0) - Error occurred, registration not completed.
- * NOTE: Exact cause of failure will be recorded in syslog.
-*/
-iucv_handle_t iucv_register_program (uchar pgmname[16],
-				     uchar userid[8],
-				     uchar pgmmask[24],
-				     iucv_interrupt_ops_t * ops,
-				     void *pgm_data);
-
-/*
- * Name: iucv_unregister_program
- * Purpose: Unregister application with IUCV
- * Input: address of handler
- * Output: NA
- * Return: (0) - Normal return
- *         (-EINVAL) - Internal error, wild pointer
-*/
-int iucv_unregister_program (iucv_handle_t handle);
-
-/*
- * Name: iucv_accept
- * Purpose: This function is issued after the user receives a Connection Pending external
- *          interrupt and now wishes to complete the IUCV communication path.
- * Input:  pathid - u16 , Path identification number
- *         msglim_reqstd - u16, The number of outstanding messages requested.
- *         user_data - uchar[16], Data specified by the iucv_connect function.
- *	   flags1 - int, Contains options for this path.
- *           -IPPRTY   - 0x20- Specifies if you want to send priority message.
- *           -IPRMDATA - 0x80, Specifies whether your program can handle a message
- *            	in  the parameter list.
- *           -IPQUSCE  - 0x40, Specifies whether you want to quiesce the path being
- *		established.
- *         handle - iucv_handle_t, Address of handler.
- *         pgm_data - void *, Application data passed to interrupt handlers.
- *         flags1_out - int * Contains information about the path
- *           - IPPRTY - 0x20, Indicates you may send priority messages.
- *         msglim - *u16, Number of outstanding messages.
- * Output: return code from CP IUCV call.
-*/
-
-int iucv_accept (u16 pathid,
-		 u16 msglim_reqstd,
-		 uchar user_data[16],
-		 int flags1,
-		 iucv_handle_t handle,
-		 void *pgm_data, int *flags1_out, u16 * msglim);
-
-/*
- * Name: iucv_connect
- * Purpose: This function establishes an IUCV path. Although the connect may complete
- *	    successfully, you are not able to use the path until you receive an IUCV
- *          Connection Complete external interrupt.
- * Input: pathid - u16 *, Path identification number
- *        msglim_reqstd - u16, Number of outstanding messages requested
- *        user_data - uchar[16], 16-byte user data
- *	  userid - uchar[8], User identification
- *        system_name - uchar[8], 8-byte identifying the system name
- *	  flags1 - int, Contains options for this path.
- *          -IPPRTY -   0x20, Specifies if you want to send priority message.
- *          -IPRMDATA - 0x80, Specifies whether your program can handle a message
- *            	 in  the parameter list.
- *          -IPQUSCE -  0x40, Specifies whether you want to quiesce the path being
- *		established.
- *          -IPLOCAL -  0X01, Allows an application to force the partner to be on
- *		the local system. If local is specified then target class cannot be
- *		specified.
- *        flags1_out - int * Contains information about the path
- *           - IPPRTY - 0x20, Indicates you may send priority messages.
- *        msglim - * u16, Number of outstanding messages
- *        handle - iucv_handle_t, Address of handler
- *        pgm_data - void *, Application data passed to interrupt handlers
- * Output: return code from CP IUCV call
- *         rc - return code from iucv_declare_buffer
- *         -EINVAL - Invalid handle passed by application
- *         -EINVAL - Pathid address is NULL
- *         add_pathid_result - Return code from internal function add_pathid
-*/
-int
-    iucv_connect (u16 * pathid,
-		  u16 msglim_reqstd,
-		  uchar user_data[16],
-		  uchar userid[8],
-		  uchar system_name[8],
-		  int flags1,
-		  int *flags1_out,
-		  u16 * msglim, iucv_handle_t handle, void *pgm_data);
-
-/*
- * Name: iucv_purge
- * Purpose: This function cancels a message that you have sent.
- * Input: pathid - Path identification number.
- *        msgid - Specifies the message ID of the message to be purged.
- *        srccls - Specifies the source message class.
- * Output: audit - Contains information about asynchronous error
- *                 that may have affected the normal completion
- *                 of this message.
- * Return: Return code from CP IUCV call.
-*/
-int iucv_purge (u16 pathid, u32 msgid, u32 srccls, __u32 *audit);
-/*
- * Name: iucv_query_maxconn
- * Purpose: This function determines the maximum number of communication paths you
- *	    may establish.
- * Return:  maxconn - ulong, Maximum number of connection the virtual machine may
- *          establish.
-*/
-ulong iucv_query_maxconn (void);
-
-/*
- * Name: iucv_query_bufsize
- * Purpose: This function determines how large an external interrupt
- *          buffer IUCV requires to store information.
- * Return:  bufsize - ulong, Size of external interrupt buffer.
- */
-ulong iucv_query_bufsize (void);
-
-/*
- * Name: iucv_quiesce
- * Purpose: This function temporarily suspends incoming messages on an
- *          IUCV path. You can later reactivate the path by invoking
- *          the iucv_resume function.
- * Input: pathid - Path identification number
- *        user_data  - 16-bytes of user data
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_quiesce (u16 pathid, uchar user_data[16]);
-
-/*
- * Name: iucv_receive
- * Purpose: This function receives messages that are being sent to you
- *          over established paths. Data will be returned in buffer for length of
- *          buflen.
- * Input:
- *       pathid - Path identification number.
- *       buffer - Address of buffer to receive.
- *       buflen - Length of buffer to receive.
- *       msgid - Specifies the message ID.
- *       trgcls - Specifies target class.
- * Output:
- *	 flags1_out: int *, Contains information about this path.
- *         IPNORPY - 0x10 Specifies this is a one-way message and no reply is
- *	   expected.
- *         IPPRTY  - 0x20 Specifies if you want to send priority message.
- *         IPRMDATA - 0x80 specifies the data is contained in the parameter list
- *       residual_buffer - address of buffer updated by the number
- *                         of bytes you have received.
- *       residual_length -
- *              Contains one of the following values, if the receive buffer is:
- *               The same length as the message, this field is zero.
- *               Longer than the message, this field contains the number of
- *                bytes remaining in the buffer.
- *               Shorter than the message, this field contains the residual
- *                count (that is, the number of bytes remaining in the
- *                message that does not fit into the buffer. In this
- *                case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - buffer address is pointing to NULL
-*/
-int iucv_receive (u16 pathid,
-		  u32 msgid,
-		  u32 trgcls,
-		  void *buffer,
-		  ulong buflen,
-		  int *flags1_out,
-		  ulong * residual_buffer, ulong * residual_length);
-
- /*
-  * Name: iucv_receive_array
-  * Purpose: This function receives messages that are being sent to you
-  *          over established paths. Data will be returned in first buffer for
-  *          length of first buffer.
-  * Input: pathid - Path identification number.
-  *        msgid - specifies the message ID.
-  *        trgcls - Specifies target class.
-  *        buffer - Address of array of buffers.
-  *        buflen - Total length of buffers.
-  * Output:
-  *        flags1_out: int *, Contains information about this path.
-  *          IPNORPY - 0x10 Specifies this is a one-way message and no reply is
-  *          expected.
-  *          IPPRTY  - 0x20 Specifies if you want to send priority message.
-  *          IPRMDATA - 0x80 specifies the data is contained in the parameter list
-  *       residual_buffer - address points to the current list entry IUCV
-  *                         is working on.
-  *       residual_length -
-  *              Contains one of the following values, if the receive buffer is:
-  *               The same length as the message, this field is zero.
-  *               Longer than the message, this field contains the number of
-  *                bytes remaining in the buffer.
-  *               Shorter than the message, this field contains the residual
-  *                count (that is, the number of bytes remaining in the
-  *                message that does not fit into the buffer. In this
-  *                case b2f0_result = 5.
-  * Return: Return code from CP IUCV call.
-  *         (-EINVAL) - Buffer address is NULL.
-  */
-int iucv_receive_array (u16 pathid,
-			u32 msgid,
-			u32 trgcls,
-			iucv_array_t * buffer,
-			ulong buflen,
-			int *flags1_out,
-			ulong * residual_buffer, ulong * residual_length);
-
-/*
- * Name: iucv_reject
- * Purpose: The reject function refuses a specified message. Between the
- *          time you are notified of a message and the time that you
- *          complete the message, the message may be rejected.
- * Input: pathid - Path identification number.
- *        msgid - Specifies the message ID.
- *        trgcls - Specifies target class.
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_reject (u16 pathid, u32 msgid, u32 trgcls);
-
-/*
- * Name: iucv_reply
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- * Input: pathid - Path identification number.
- *        msgid - Specifies the message ID.
- *        trgcls - Specifies target class.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20, Specifies if you want to send priority message.
- *        buffer - Address of reply buffer.
- *        buflen - Length of reply buffer.
- * Output: residual_buffer - Address of buffer updated by the number
- *                    of bytes you have moved.
- *         residual_length - Contains one of the following values:
- *		If the answer buffer is the same length as the reply, this field
- *		 contains zero.
- *		If the answer buffer is longer than the reply, this field contains
- *		 the number of bytes remaining in the buffer.
- *		If the answer buffer is shorter than the reply, this field contains
- *		 a residual count (that is, the number of bytes remianing in the
- *		 reply that does not fit into the buffer. In this
- *               case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_reply (u16 pathid,
-		u32 msgid,
-		u32 trgcls,
-		int flags1,
-		void *buffer, ulong buflen, ulong * residual_buffer,
-		ulong * residual_length);
-
-/*
- * Name: iucv_reply_array
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- *          The array identifies a list of addresses and lengths of
- *          discontiguous buffers that contains the reply data.
- * Input: pathid - Path identification number
- *        msgid - Specifies the message ID.
- *        trgcls - Specifies target class.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20, Specifies if you want to send priority message.
- *        buffer - Address of array of reply buffers.
- *        buflen - Total length of reply buffers.
- * Output: residual_buffer - Address of buffer which IUCV is currently working on.
- *         residual_length - Contains one of the following values:
- *              If the answer buffer is the same length as the reply, this field
- *               contains zero.
- *              If the answer buffer is longer than the reply, this field contains
- *               the number of bytes remaining in the buffer.
- *              If the answer buffer is shorter than the reply, this field contains
- *               a residual count (that is, the number of bytes remianing in the
- *               reply that does not fit into the buffer. In this
- *               case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_reply_array (u16 pathid,
-		      u32 msgid,
-		      u32 trgcls,
-		      int flags1,
-		      iucv_array_t * buffer,
-		      ulong buflen, ulong * residual_address,
-		      ulong * residual_length);
-
-/*
- * Name: iucv_reply_prmmsg
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- *          Prmmsg signifies the data is moved into the
- *          parameter list.
- * Input: pathid - Path identification number.
- *        msgid - Specifies the message ID.
- *        trgcls - Specifies target class.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed into the parameter.
- *                 list.
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_reply_prmmsg (u16 pathid,
-		       u32 msgid, u32 trgcls, int flags1, uchar prmmsg[8]);
-
-/*
- * Name: iucv_resume
- * Purpose: This function restores communications over a quiesced path
- * Input: pathid - Path identification number.
- *        user_data  - 16-bytes of user data.
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_resume (u16 pathid, uchar user_data[16]);
-
-/*
- * Name: iucv_send
- * Purpose: This function transmits data to another application.
- *          Data to be transmitted is in a buffer and this is a
- *          one-way message and the receiver will not reply to the
- *          message.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        buffer - Address of send buffer.
- *        buflen - Length of send buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send (u16 pathid,
-	       u32 * msgid,
-	       u32 trgcls,
-	       u32 srccls, u32 msgtag, int flags1, void *buffer, ulong buflen);
-
-/*
- * Name: iucv_send_array
- * Purpose: This function transmits data to another application.
- *          The contents of buffer is the address of the array of
- *          addresses and lengths of discontiguous buffers that hold
- *          the message text. This is a one-way message and the
- *          receiver will not reply to the message.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated witht the message.
- *        flags1 - Option for path.
- *          IPPRTY- specifies if you want to send priority message.
- *        buffer - Address of array of send buffers.
- *        buflen - Total length of send buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send_array (u16 pathid,
-		     u32 * msgid,
-		     u32 trgcls,
-		     u32 srccls,
-		     u32 msgtag,
-		     int flags1, iucv_array_t * buffer, ulong buflen);
-
-/*
- * Name: iucv_send_prmmsg
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a one-way message and the
- *          receiver will not reply to the message.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed into parameter list.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
-*/
-int iucv_send_prmmsg (u16 pathid,
-		      u32 * msgid,
-		      u32 trgcls,
-		      u32 srccls, u32 msgtag, int flags1, uchar prmmsg[8]);
-
-/*
- * Name: iucv_send2way
- * Purpose: This function transmits data to another application.
- *          Data to be transmitted is in a buffer. The receiver
- *          of the send is expected to reply to the message and
- *          a buffer is provided into which IUCV moves the reply
- *          to this message.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        buffer - Address of send buffer.
- *        buflen - Length of send buffer.
- *        ansbuf - Address of buffer into which IUCV moves the reply of
- *                 this message.
- *        anslen - Address of length of buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer or ansbuf address is NULL.
-*/
-int iucv_send2way (u16 pathid,
-		   u32 * msgid,
-		   u32 trgcls,
-		   u32 srccls,
-		   u32 msgtag,
-		   int flags1,
-		   void *buffer, ulong buflen, void *ansbuf, ulong anslen);
-
-/*
- * Name: iucv_send2way_array
- * Purpose: This function transmits data to another application.
- *          The contents of buffer is the address of the array of
- *          addresses and lengths of discontiguous buffers that hold
- *          the message text. The receiver of the send is expected to
- *          reply to the message and a buffer is provided into which
- *          IUCV moves the reply to this message.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        buffer - Sddress of array of send buffers.
- *        buflen - Total length of send buffers.
- *        ansbuf - Address of array of buffer into which IUCV moves the reply
- *                 of this message.
- *        anslen - Address of length reply buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send2way_array (u16 pathid,
-			 u32 * msgid,
-			 u32 trgcls,
-			 u32 srccls,
-			 u32 msgtag,
-			 int flags1,
-			 iucv_array_t * buffer,
-			 ulong buflen, iucv_array_t * ansbuf, ulong anslen);
-
-/*
- * Name: iucv_send2way_prmmsg
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a two-way message and the
- *          receiver of the message is expected to reply. A buffer
- *          is provided into which IUCV moves the reply to this
- *          message.
- * Input: pathid - Rath identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed in parameter list.
- *        ansbuf - Address of buffer into which IUCV moves the reply of
- *                 this message.
- *        anslen - Address of length of buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send2way_prmmsg (u16 pathid,
-			  u32 * msgid,
-			  u32 trgcls,
-			  u32 srccls,
-			  u32 msgtag,
-			  ulong flags1,
-			  uchar prmmsg[8], void *ansbuf, ulong anslen);
-
-/*
- * Name: iucv_send2way_prmmsg_array
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a two-way message and the
- *          receiver of the message is expected to reply. A buffer
- *          is provided into which IUCV moves the reply to this
- *          message. The contents of ansbuf is the address of the
- *          array of addresses and lengths of discontiguous buffers
- *          that contain the reply.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed into the parameter list.
- *        ansbuf - Address of array of buffer into which IUCV moves the reply
- *                 of this message.
- *        anslen - Address of length of reply buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Ansbuf address is NULL.
-*/
-int iucv_send2way_prmmsg_array (u16 pathid,
-				u32 * msgid,
-				u32 trgcls,
-				u32 srccls,
-				u32 msgtag,
-				int flags1,
-				uchar prmmsg[8],
-				iucv_array_t * ansbuf, ulong anslen);
-
-/*
- * Name: iucv_setmask
- * Purpose: This function enables or disables the following IUCV
- *          external interruptions: Nonpriority and priority message
- *          interrupts, nonpriority and priority reply interrupts.
- * Input: SetMaskFlag - options for interrupts
- *           0x80 - Nonpriority_MessagePendingInterruptsFlag
- *           0x40 - Priority_MessagePendingInterruptsFlag
- *           0x20 - Nonpriority_MessageCompletionInterruptsFlag
- *           0x10 - Priority_MessageCompletionInterruptsFlag
- *           0x08 - IUCVControlInterruptsFlag
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_setmask (int SetMaskFlag);
-
-/*
- * Name: iucv_sever
- * Purpose: This function terminates an IUCV path.
- * Input: pathid - Path identification number.
- *        user_data - 16-bytes of user data.
- * Output: NA
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Interal error, wild pointer.
-*/
-int iucv_sever (u16 pathid, uchar user_data[16]);
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index b97dd15..ecca104 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1511,8 +1511,7 @@
 	LCS_DBF_TEXT(5, trace, "txbuffcb");
 	/* Put buffer back to pool. */
 	lcs_release_buffer(channel, buffer);
-	card = (struct lcs_card *)
-		((char *) channel - offsetof(struct lcs_card, write));
+	card = container_of(channel, struct lcs_card, write);
 	if (netif_queue_stopped(card->dev) && netif_carrier_ok(card->dev))
 		netif_wake_queue(card->dev);
 	spin_lock(&card->lock);
@@ -1810,8 +1809,7 @@
 		LCS_DBF_TEXT(4, trace, "-eiogpkt");
 		return;
 	}
-	card = (struct lcs_card *)
-		((char *) channel - offsetof(struct lcs_card, read));
+	card = container_of(channel, struct lcs_card, read);
 	offset = 0;
 	while (lcs_hdr->offset != 0) {
 		if (lcs_hdr->offset <= 0 ||
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 3346088..594320c 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,7 +1,7 @@
 /*
  * IUCV network driver
  *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
  * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
  *
  * Sysfs integration and all bugs therein by Cornelia Huck
@@ -41,7 +41,6 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/bitops.h>
 
 #include <linux/signal.h>
@@ -58,13 +57,94 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#include "iucv.h"
+#include <net/iucv/iucv.h>
 #include "fsm.h"
 
 MODULE_AUTHOR
     ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
 MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
 
+/**
+ * Debug Facility stuff
+ */
+#define IUCV_DBF_SETUP_NAME "iucv_setup"
+#define IUCV_DBF_SETUP_LEN 32
+#define IUCV_DBF_SETUP_PAGES 2
+#define IUCV_DBF_SETUP_NR_AREAS 1
+#define IUCV_DBF_SETUP_LEVEL 3
+
+#define IUCV_DBF_DATA_NAME "iucv_data"
+#define IUCV_DBF_DATA_LEN 128
+#define IUCV_DBF_DATA_PAGES 2
+#define IUCV_DBF_DATA_NR_AREAS 1
+#define IUCV_DBF_DATA_LEVEL 2
+
+#define IUCV_DBF_TRACE_NAME "iucv_trace"
+#define IUCV_DBF_TRACE_LEN 16
+#define IUCV_DBF_TRACE_PAGES 4
+#define IUCV_DBF_TRACE_NR_AREAS 1
+#define IUCV_DBF_TRACE_LEVEL 3
+
+#define IUCV_DBF_TEXT(name,level,text) \
+	do { \
+		debug_text_event(iucv_dbf_##name,level,text); \
+	} while (0)
+
+#define IUCV_DBF_HEX(name,level,addr,len) \
+	do { \
+		debug_event(iucv_dbf_##name,level,(void*)(addr),len); \
+	} while (0)
+
+DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
+
+#define IUCV_DBF_TEXT_(name,level,text...)				\
+	do {								\
+		char* iucv_dbf_txt_buf = get_cpu_var(iucv_dbf_txt_buf);	\
+		sprintf(iucv_dbf_txt_buf, text);			\
+		debug_text_event(iucv_dbf_##name,level,iucv_dbf_txt_buf); \
+		put_cpu_var(iucv_dbf_txt_buf);				\
+	} while (0)
+
+#define IUCV_DBF_SPRINTF(name,level,text...) \
+	do { \
+		debug_sprintf_event(iucv_dbf_trace, level, ##text ); \
+		debug_sprintf_event(iucv_dbf_trace, level, text ); \
+	} while (0)
+
+/**
+ * some more debug stuff
+ */
+#define IUCV_HEXDUMP16(importance,header,ptr) \
+PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
+		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
+		   *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
+		   *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
+		   *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
+		   *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
+		   *(((char*)ptr)+12),*(((char*)ptr)+13), \
+		   *(((char*)ptr)+14),*(((char*)ptr)+15)); \
+PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
+		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
+		   *(((char*)ptr)+16),*(((char*)ptr)+17), \
+		   *(((char*)ptr)+18),*(((char*)ptr)+19), \
+		   *(((char*)ptr)+20),*(((char*)ptr)+21), \
+		   *(((char*)ptr)+22),*(((char*)ptr)+23), \
+		   *(((char*)ptr)+24),*(((char*)ptr)+25), \
+		   *(((char*)ptr)+26),*(((char*)ptr)+27), \
+		   *(((char*)ptr)+28),*(((char*)ptr)+29), \
+		   *(((char*)ptr)+30),*(((char*)ptr)+31));
+
+static inline void iucv_hex_dump(unsigned char *buf, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++) {
+		if (i && !(i % 16))
+			printk("\n");
+		printk("%02x ", *(buf + i));
+	}
+	printk("\n");
+}
 
 #define PRINTK_HEADER " iucv: "       /* for debugging */
 
@@ -73,6 +153,25 @@
 	.bus  = &iucv_bus,
 };
 
+static int netiucv_callback_connreq(struct iucv_path *,
+				    u8 ipvmid[8], u8 ipuser[16]);
+static void netiucv_callback_connack(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_connsusp(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_connres(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_rx(struct iucv_path *, struct iucv_message *);
+static void netiucv_callback_txdone(struct iucv_path *, struct iucv_message *);
+
+static struct iucv_handler netiucv_handler = {
+	.path_pending	  = netiucv_callback_connreq,
+	.path_complete	  = netiucv_callback_connack,
+	.path_severed	  = netiucv_callback_connrej,
+	.path_quiesced	  = netiucv_callback_connsusp,
+	.path_resumed	  = netiucv_callback_connres,
+	.message_pending  = netiucv_callback_rx,
+	.message_complete = netiucv_callback_txdone
+};
+
 /**
  * Per connection profiling data
  */
@@ -92,9 +191,8 @@
  * Representation of one iucv connection
  */
 struct iucv_connection {
-	struct iucv_connection    *next;
-	iucv_handle_t             handle;
-	__u16                     pathid;
+	struct list_head	  list;
+	struct iucv_path	  *path;
 	struct sk_buff            *rx_buff;
 	struct sk_buff            *tx_buff;
 	struct sk_buff_head       collect_queue;
@@ -112,12 +210,9 @@
 /**
  * Linked list of all connection structs.
  */
-struct iucv_connection_struct {
-	struct iucv_connection *iucv_connections;
-	rwlock_t iucv_rwlock;
-};
-
-static struct iucv_connection_struct iucv_conns;
+static struct list_head iucv_connection_list =
+	LIST_HEAD_INIT(iucv_connection_list);
+static rwlock_t iucv_connection_rwlock = RW_LOCK_UNLOCKED;
 
 /**
  * Representation of event-data for the
@@ -142,11 +237,11 @@
 /**
  * Link level header for a packet.
  */
-typedef struct ll_header_t {
-	__u16 next;
-} ll_header;
+struct ll_header {
+	u16 next;
+};
 
-#define NETIUCV_HDRLEN           (sizeof(ll_header))
+#define NETIUCV_HDRLEN		 (sizeof(struct ll_header))
 #define NETIUCV_BUFSIZE_MAX      32768
 #define NETIUCV_BUFSIZE_DEFAULT  NETIUCV_BUFSIZE_MAX
 #define NETIUCV_MTU_MAX          (NETIUCV_BUFSIZE_MAX - NETIUCV_HDRLEN)
@@ -158,36 +253,26 @@
  * Compatibility macros for busy handling
  * of network devices.
  */
-static __inline__ void netiucv_clear_busy(struct net_device *dev)
+static inline void netiucv_clear_busy(struct net_device *dev)
 {
-	clear_bit(0, &(((struct netiucv_priv *)dev->priv)->tbusy));
+	struct netiucv_priv *priv = netdev_priv(dev);
+	clear_bit(0, &priv->tbusy);
 	netif_wake_queue(dev);
 }
 
-static __inline__ int netiucv_test_and_set_busy(struct net_device *dev)
+static inline int netiucv_test_and_set_busy(struct net_device *dev)
 {
+	struct netiucv_priv *priv = netdev_priv(dev);
 	netif_stop_queue(dev);
-	return test_and_set_bit(0, &((struct netiucv_priv *)dev->priv)->tbusy);
+	return test_and_set_bit(0, &priv->tbusy);
 }
 
-static __u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static __u8 iucvMagic[16] = {
+static u8 iucvMagic[16] = {
 	0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
 	0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
 };
 
 /**
- * This mask means the 16-byte IUCV "magic" and the origin userid must
- * match exactly as specified in order to give connection_pending()
- * control.
- */
-static __u8 netiucv_mask[] = {
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-/**
  * Convert an iucv userId to its printable
  * form (strip whitespace at end).
  *
@@ -195,8 +280,7 @@
  *
  * @returns The printable string (static data!!)
  */
-static __inline__ char *
-netiucv_printname(char *name)
+static inline char *netiucv_printname(char *name)
 {
 	static char tmp[9];
 	char *p = tmp;
@@ -379,8 +463,7 @@
 
 DEFINE_PER_CPU(char[256], iucv_dbf_txt_buf);
 
-static void
-iucv_unregister_dbf_views(void)
+static void iucv_unregister_dbf_views(void)
 {
 	if (iucv_dbf_setup)
 		debug_unregister(iucv_dbf_setup);
@@ -389,8 +472,7 @@
 	if (iucv_dbf_trace)
 		debug_unregister(iucv_dbf_trace);
 }
-static int
-iucv_register_dbf_views(void)
+static int iucv_register_dbf_views(void)
 {
 	iucv_dbf_setup = debug_register(IUCV_DBF_SETUP_NAME,
 					IUCV_DBF_SETUP_PAGES,
@@ -422,125 +504,111 @@
 	return 0;
 }
 
-/**
+/*
  * Callback-wrappers, called from lowlevel iucv layer.
- *****************************************************************************/
+ */
 
-static void
-netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data)
+static void netiucv_callback_rx(struct iucv_path *path,
+				struct iucv_message *msg)
 {
-	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
+	struct iucv_connection *conn = path->private;
 	struct iucv_event ev;
 
 	ev.conn = conn;
-	ev.data = (void *)eib;
-
+	ev.data = msg;
 	fsm_event(conn->fsm, CONN_EVENT_RX, &ev);
 }
 
-static void
-netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data)
+static void netiucv_callback_txdone(struct iucv_path *path,
+				    struct iucv_message *msg)
 {
-	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
+	struct iucv_connection *conn = path->private;
 	struct iucv_event ev;
 
 	ev.conn = conn;
-	ev.data = (void *)eib;
+	ev.data = msg;
 	fsm_event(conn->fsm, CONN_EVENT_TXDONE, &ev);
 }
 
-static void
-netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data)
+static void netiucv_callback_connack(struct iucv_path *path, u8 ipuser[16])
 {
-	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
-	struct iucv_event ev;
+	struct iucv_connection *conn = path->private;
 
-	ev.conn = conn;
-	ev.data = (void *)eib;
-	fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, &ev);
+	fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, conn);
 }
 
-static void
-netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data)
+static int netiucv_callback_connreq(struct iucv_path *path,
+				    u8 ipvmid[8], u8 ipuser[16])
 {
-	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
+	struct iucv_connection *conn = path->private;
 	struct iucv_event ev;
+	int rc;
 
-	ev.conn = conn;
-	ev.data = (void *)eib;
-	fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev);
+	if (memcmp(iucvMagic, ipuser, sizeof(ipuser)))
+		/* ipuser must match iucvMagic. */
+		return -EINVAL;
+	rc = -EINVAL;
+	read_lock_bh(&iucv_connection_rwlock);
+	list_for_each_entry(conn, &iucv_connection_list, list) {
+		if (strncmp(ipvmid, conn->userid, 8))
+			continue;
+		/* Found a matching connection for this path. */
+		conn->path = path;
+		ev.conn = conn;
+		ev.data = path;
+		fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev);
+		rc = 0;
+	}
+	read_unlock_bh(&iucv_connection_rwlock);
+	return rc;
 }
 
-static void
-netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data)
+static void netiucv_callback_connrej(struct iucv_path *path, u8 ipuser[16])
 {
-	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
-	struct iucv_event ev;
+	struct iucv_connection *conn = path->private;
 
-	ev.conn = conn;
-	ev.data = (void *)eib;
-	fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, &ev);
+	fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, conn);
 }
 
-static void
-netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data)
+static void netiucv_callback_connsusp(struct iucv_path *path, u8 ipuser[16])
 {
-	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
-	struct iucv_event ev;
+	struct iucv_connection *conn = path->private;
 
-	ev.conn = conn;
-	ev.data = (void *)eib;
-	fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, &ev);
+	fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, conn);
 }
 
-static void
-netiucv_callback_connres(iucv_ConnectionResumed *eib, void *pgm_data)
+static void netiucv_callback_connres(struct iucv_path *path, u8 ipuser[16])
 {
-	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
-	struct iucv_event ev;
+	struct iucv_connection *conn = path->private;
 
-	ev.conn = conn;
-	ev.data = (void *)eib;
-	fsm_event(conn->fsm, CONN_EVENT_CONN_RES, &ev);
+	fsm_event(conn->fsm, CONN_EVENT_CONN_RES, conn);
 }
 
-static iucv_interrupt_ops_t netiucv_ops = {
-	.ConnectionPending  = netiucv_callback_connreq,
-	.ConnectionComplete = netiucv_callback_connack,
-	.ConnectionSevered  = netiucv_callback_connrej,
-	.ConnectionQuiesced = netiucv_callback_connsusp,
-	.ConnectionResumed  = netiucv_callback_connres,
-	.MessagePending     = netiucv_callback_rx,
-	.MessageComplete    = netiucv_callback_txdone
-};
-
 /**
  * Dummy NOP action for all statemachines
  */
-static void
-fsm_action_nop(fsm_instance *fi, int event, void *arg)
+static void fsm_action_nop(fsm_instance *fi, int event, void *arg)
 {
 }
 
-/**
+/*
  * Actions of the connection statemachine
- *****************************************************************************/
+ */
 
 /**
- * Helper function for conn_action_rx()
- * Unpack a just received skb and hand it over to
- * upper layers.
+ * netiucv_unpack_skb
+ * @conn: The connection where this skb has been received.
+ * @pskb: The received skb.
  *
- * @param conn The connection where this skb has been received.
- * @param pskb The received skb.
+ * Unpack a just received skb and hand it over to upper layers.
+ * Helper function for conn_action_rx.
  */
-//static __inline__ void
-static void
-netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
+static void netiucv_unpack_skb(struct iucv_connection *conn,
+			       struct sk_buff *pskb)
 {
 	struct net_device     *dev = conn->netdev;
-	struct netiucv_priv   *privptr = dev->priv;
-	__u16          offset = 0;
+	struct netiucv_priv   *privptr = netdev_priv(dev);
+	u16 offset = 0;
 
 	skb_put(pskb, NETIUCV_HDRLEN);
 	pskb->dev = dev;
@@ -549,7 +617,7 @@
 
 	while (1) {
 		struct sk_buff *skb;
-		ll_header *header = (ll_header *)pskb->data;
+		struct ll_header *header = (struct ll_header *) pskb->data;
 
 		if (!header->next)
 			break;
@@ -595,40 +663,37 @@
 	}
 }
 
-static void
-conn_action_rx(fsm_instance *fi, int event, void *arg)
+static void conn_action_rx(fsm_instance *fi, int event, void *arg)
 {
-	struct iucv_event *ev = (struct iucv_event *)arg;
+	struct iucv_event *ev = arg;
 	struct iucv_connection *conn = ev->conn;
-	iucv_MessagePending *eib = (iucv_MessagePending *)ev->data;
-	struct netiucv_priv *privptr =(struct netiucv_priv *)conn->netdev->priv;
-
-	__u32 msglen = eib->ln1msg2.ipbfln1f;
+	struct iucv_message *msg = ev->data;
+	struct netiucv_priv *privptr = netdev_priv(conn->netdev);
 	int rc;
 
 	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
 
 	if (!conn->netdev) {
-		/* FRITZ: How to tell iucv LL to drop the msg? */
+		iucv_message_reject(conn->path, msg);
 		PRINT_WARN("Received data for unlinked connection\n");
 		IUCV_DBF_TEXT(data, 2,
-			"Received data for unlinked connection\n");
+			      "Received data for unlinked connection\n");
 		return;
 	}
-	if (msglen > conn->max_buffsize) {
-		/* FRITZ: How to tell iucv LL to drop the msg? */
+	if (msg->length > conn->max_buffsize) {
+		iucv_message_reject(conn->path, msg);
 		privptr->stats.rx_dropped++;
 		PRINT_WARN("msglen %d > max_buffsize %d\n",
-			msglen, conn->max_buffsize);
+			   msg->length, conn->max_buffsize);
 		IUCV_DBF_TEXT_(data, 2, "msglen %d > max_buffsize %d\n",
-			msglen, conn->max_buffsize);
+			       msg->length, conn->max_buffsize);
 		return;
 	}
 	conn->rx_buff->data = conn->rx_buff->tail = conn->rx_buff->head;
 	conn->rx_buff->len = 0;
-	rc = iucv_receive(conn->pathid, eib->ipmsgid, eib->iptrgcls,
-			  conn->rx_buff->data, msglen, NULL, NULL, NULL);
-	if (rc || msglen < 5) {
+	rc = iucv_message_receive(conn->path, msg, 0, conn->rx_buff->data,
+				  msg->length, NULL);
+	if (rc || msg->length < 5) {
 		privptr->stats.rx_errors++;
 		PRINT_WARN("iucv_receive returned %08x\n", rc);
 		IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_receive\n", rc);
@@ -637,26 +702,26 @@
 	netiucv_unpack_skb(conn, conn->rx_buff);
 }
 
-static void
-conn_action_txdone(fsm_instance *fi, int event, void *arg)
+static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
 {
-	struct iucv_event *ev = (struct iucv_event *)arg;
+	struct iucv_event *ev = arg;
 	struct iucv_connection *conn = ev->conn;
-	iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data;
+	struct iucv_message *msg = ev->data;
+	struct iucv_message txmsg;
 	struct netiucv_priv *privptr = NULL;
-			         /* Shut up, gcc! skb is always below 2G. */
-	__u32 single_flag = eib->ipmsgtag;
-	__u32 txbytes = 0;
-	__u32 txpackets = 0;
-	__u32 stat_maxcq = 0;
+	u32 single_flag = msg->tag;
+	u32 txbytes = 0;
+	u32 txpackets = 0;
+	u32 stat_maxcq = 0;
 	struct sk_buff *skb;
 	unsigned long saveflags;
-	ll_header header;
+	struct ll_header header;
+	int rc;
 
 	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
 
-	if (conn && conn->netdev && conn->netdev->priv)
-		privptr = (struct netiucv_priv *)conn->netdev->priv;
+	if (conn && conn->netdev)
+		privptr = netdev_priv(conn->netdev);
 	conn->prof.tx_pending--;
 	if (single_flag) {
 		if ((skb = skb_dequeue(&conn->commit_queue))) {
@@ -688,56 +753,55 @@
 		conn->prof.maxmulti = conn->collect_len;
 	conn->collect_len = 0;
 	spin_unlock_irqrestore(&conn->collect_lock, saveflags);
-	if (conn->tx_buff->len) {
-		int rc;
-
-		header.next = 0;
-		memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,
-		       NETIUCV_HDRLEN);
-
-		conn->prof.send_stamp = xtime;
-		rc = iucv_send(conn->pathid, NULL, 0, 0, 0, 0,
-			       conn->tx_buff->data, conn->tx_buff->len);
-		conn->prof.doios_multi++;
-		conn->prof.txlen += conn->tx_buff->len;
-		conn->prof.tx_pending++;
-		if (conn->prof.tx_pending > conn->prof.tx_max_pending)
-			conn->prof.tx_max_pending = conn->prof.tx_pending;
-		if (rc) {
-			conn->prof.tx_pending--;
-			fsm_newstate(fi, CONN_STATE_IDLE);
-			if (privptr)
-				privptr->stats.tx_errors += txpackets;
-			PRINT_WARN("iucv_send returned %08x\n",	rc);
-			IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
-		} else {
-			if (privptr) {
-				privptr->stats.tx_packets += txpackets;
-				privptr->stats.tx_bytes += txbytes;
-			}
-			if (stat_maxcq > conn->prof.maxcqueue)
-				conn->prof.maxcqueue = stat_maxcq;
-		}
-	} else
+	if (conn->tx_buff->len == 0) {
 		fsm_newstate(fi, CONN_STATE_IDLE);
+		return;
+	}
+
+	header.next = 0;
+	memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);
+	conn->prof.send_stamp = xtime;
+	txmsg.class = 0;
+	txmsg.tag = 0;
+	rc = iucv_message_send(conn->path, &txmsg, 0, 0,
+			       conn->tx_buff->data, conn->tx_buff->len);
+	conn->prof.doios_multi++;
+	conn->prof.txlen += conn->tx_buff->len;
+	conn->prof.tx_pending++;
+	if (conn->prof.tx_pending > conn->prof.tx_max_pending)
+		conn->prof.tx_max_pending = conn->prof.tx_pending;
+	if (rc) {
+		conn->prof.tx_pending--;
+		fsm_newstate(fi, CONN_STATE_IDLE);
+		if (privptr)
+			privptr->stats.tx_errors += txpackets;
+		PRINT_WARN("iucv_send returned %08x\n",	rc);
+		IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
+	} else {
+		if (privptr) {
+			privptr->stats.tx_packets += txpackets;
+			privptr->stats.tx_bytes += txbytes;
+		}
+		if (stat_maxcq > conn->prof.maxcqueue)
+			conn->prof.maxcqueue = stat_maxcq;
+	}
 }
 
-static void
-conn_action_connaccept(fsm_instance *fi, int event, void *arg)
+static void conn_action_connaccept(fsm_instance *fi, int event, void *arg)
 {
-	struct iucv_event *ev = (struct iucv_event *)arg;
+	struct iucv_event *ev = arg;
 	struct iucv_connection *conn = ev->conn;
-	iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
+	struct iucv_path *path = ev->data;
 	struct net_device *netdev = conn->netdev;
-	struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
+	struct netiucv_priv *privptr = netdev_priv(netdev);
 	int rc;
-	__u16 msglimit;
-	__u8 udata[16];
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 
-	rc = iucv_accept(eib->ippathid, NETIUCV_QUEUELEN_DEFAULT, udata, 0,
-			 conn->handle, conn, NULL, &msglimit);
+	conn->path = path;
+	path->msglim = NETIUCV_QUEUELEN_DEFAULT;
+	path->flags = 0;
+	rc = iucv_path_accept(path, &netiucv_handler, NULL, conn);
 	if (rc) {
 		PRINT_WARN("%s: IUCV accept failed with error %d\n",
 		       netdev->name, rc);
@@ -745,183 +809,126 @@
 		return;
 	}
 	fsm_newstate(fi, CONN_STATE_IDLE);
-	conn->pathid = eib->ippathid;
-	netdev->tx_queue_len = msglimit;
+	netdev->tx_queue_len = conn->path->msglim;
 	fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
 }
 
-static void
-conn_action_connreject(fsm_instance *fi, int event, void *arg)
+static void conn_action_connreject(fsm_instance *fi, int event, void *arg)
 {
-	struct iucv_event *ev = (struct iucv_event *)arg;
-	struct iucv_connection *conn = ev->conn;
-	struct net_device *netdev = conn->netdev;
-	iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
-	__u8 udata[16];
+	struct iucv_event *ev = arg;
+	struct iucv_path *path = ev->data;
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-
-	iucv_sever(eib->ippathid, udata);
-	if (eib->ippathid != conn->pathid) {
-		PRINT_INFO("%s: IR Connection Pending; "
-			"pathid %d does not match original pathid %d\n",
-			netdev->name, eib->ippathid, conn->pathid);
-		IUCV_DBF_TEXT_(data, 2,
-			"connreject: IR pathid %d, conn. pathid %d\n",
-			eib->ippathid, conn->pathid);
-		iucv_sever(conn->pathid, udata);
-	}
+	iucv_path_sever(path, NULL);
 }
 
-static void
-conn_action_connack(fsm_instance *fi, int event, void *arg)
+static void conn_action_connack(fsm_instance *fi, int event, void *arg)
 {
-	struct iucv_event *ev = (struct iucv_event *)arg;
-	struct iucv_connection *conn = ev->conn;
-	iucv_ConnectionComplete *eib = (iucv_ConnectionComplete *)ev->data;
+	struct iucv_connection *conn = arg;
 	struct net_device *netdev = conn->netdev;
-	struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
+	struct netiucv_priv *privptr = netdev_priv(netdev);
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-
 	fsm_deltimer(&conn->timer);
 	fsm_newstate(fi, CONN_STATE_IDLE);
-	if (eib->ippathid != conn->pathid) {
-		PRINT_INFO("%s: IR Connection Complete; "
-			"pathid %d does not match original pathid %d\n",
-			netdev->name, eib->ippathid, conn->pathid);
-		IUCV_DBF_TEXT_(data, 2,
-			"connack: IR pathid %d, conn. pathid %d\n",
-			eib->ippathid, conn->pathid);
-		conn->pathid = eib->ippathid;
-	}
-	netdev->tx_queue_len = eib->ipmsglim;
+	netdev->tx_queue_len = conn->path->msglim;
 	fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
 }
 
-static void
-conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
+static void conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
 {
-	struct iucv_connection *conn = (struct iucv_connection *)arg;
-	__u8 udata[16];
+	struct iucv_connection *conn = arg;
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-
 	fsm_deltimer(&conn->timer);
-	iucv_sever(conn->pathid, udata);
+	iucv_path_sever(conn->path, NULL);
 	fsm_newstate(fi, CONN_STATE_STARTWAIT);
 }
 
-static void
-conn_action_connsever(fsm_instance *fi, int event, void *arg)
+static void conn_action_connsever(fsm_instance *fi, int event, void *arg)
 {
-	struct iucv_event *ev = (struct iucv_event *)arg;
-	struct iucv_connection *conn = ev->conn;
+	struct iucv_connection *conn = arg;
 	struct net_device *netdev = conn->netdev;
-	struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
-	__u8 udata[16];
+	struct netiucv_priv *privptr = netdev_priv(netdev);
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 
 	fsm_deltimer(&conn->timer);
-	iucv_sever(conn->pathid, udata);
+	iucv_path_sever(conn->path, NULL);
 	PRINT_INFO("%s: Remote dropped connection\n", netdev->name);
 	IUCV_DBF_TEXT(data, 2,
-		"conn_action_connsever: Remote dropped connection\n");
+		      "conn_action_connsever: Remote dropped connection\n");
 	fsm_newstate(fi, CONN_STATE_STARTWAIT);
 	fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
 }
 
-static void
-conn_action_start(fsm_instance *fi, int event, void *arg)
+static void conn_action_start(fsm_instance *fi, int event, void *arg)
 {
-	struct iucv_event *ev = (struct iucv_event *)arg;
-	struct iucv_connection *conn = ev->conn;
-	__u16 msglimit;
+	struct iucv_connection *conn = arg;
 	int rc;
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 
-	if (!conn->handle) {
-		IUCV_DBF_TEXT(trace, 5, "calling iucv_register_program\n");
-		conn->handle =
-			iucv_register_program(iucvMagic, conn->userid,
-					      netiucv_mask,
-					      &netiucv_ops, conn);
-		fsm_newstate(fi, CONN_STATE_STARTWAIT);
-		if (!conn->handle) {
-			fsm_newstate(fi, CONN_STATE_REGERR);
-			conn->handle = NULL;
-			IUCV_DBF_TEXT(setup, 2,
-				"NULL from iucv_register_program\n");
-			return;
-		}
-
-		PRINT_DEBUG("%s('%s'): registered successfully\n",
-			 conn->netdev->name, conn->userid);
-	}
-
+	fsm_newstate(fi, CONN_STATE_STARTWAIT);
 	PRINT_DEBUG("%s('%s'): connecting ...\n",
-		 conn->netdev->name, conn->userid);
+		    conn->netdev->name, conn->userid);
 
-	/* We must set the state before calling iucv_connect because the callback
-	 * handler could be called at any point after the connection request is
-	 * sent */
+	/*
+	 * We must set the state before calling iucv_connect because the
+	 * callback handler could be called at any point after the connection
+	 * request is sent
+	 */
 
 	fsm_newstate(fi, CONN_STATE_SETUPWAIT);
-	rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,
-			  conn->userid, iucv_host, 0, NULL, &msglimit,
-			  conn->handle, conn);
+	conn->path = iucv_path_alloc(NETIUCV_QUEUELEN_DEFAULT, 0, GFP_KERNEL);
+	rc = iucv_path_connect(conn->path, &netiucv_handler, conn->userid,
+			       NULL, iucvMagic, conn);
 	switch (rc) {
-		case 0:
-			conn->netdev->tx_queue_len = msglimit;
-			fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
-				CONN_EVENT_TIMER, conn);
-			return;
-		case 11:
-			PRINT_INFO("%s: User %s is currently not available.\n",
-			       conn->netdev->name,
-			       netiucv_printname(conn->userid));
-			fsm_newstate(fi, CONN_STATE_STARTWAIT);
-			return;
-		case 12:
-			PRINT_INFO("%s: User %s is currently not ready.\n",
-			       conn->netdev->name,
-			       netiucv_printname(conn->userid));
-			fsm_newstate(fi, CONN_STATE_STARTWAIT);
-			return;
-		case 13:
-			PRINT_WARN("%s: Too many IUCV connections.\n",
-			       conn->netdev->name);
-			fsm_newstate(fi, CONN_STATE_CONNERR);
-			break;
-		case 14:
-			PRINT_WARN(
-			       "%s: User %s has too many IUCV connections.\n",
-			       conn->netdev->name,
-			       netiucv_printname(conn->userid));
-			fsm_newstate(fi, CONN_STATE_CONNERR);
-			break;
-		case 15:
-			PRINT_WARN(
-			       "%s: No IUCV authorization in CP directory.\n",
-			       conn->netdev->name);
-			fsm_newstate(fi, CONN_STATE_CONNERR);
-			break;
-		default:
-			PRINT_WARN("%s: iucv_connect returned error %d\n",
-			       conn->netdev->name, rc);
-			fsm_newstate(fi, CONN_STATE_CONNERR);
-			break;
+	case 0:
+		conn->netdev->tx_queue_len = conn->path->msglim;
+		fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
+			     CONN_EVENT_TIMER, conn);
+		return;
+	case 11:
+		PRINT_INFO("%s: User %s is currently not available.\n",
+			   conn->netdev->name,
+			   netiucv_printname(conn->userid));
+		fsm_newstate(fi, CONN_STATE_STARTWAIT);
+		break;
+	case 12:
+		PRINT_INFO("%s: User %s is currently not ready.\n",
+			   conn->netdev->name,
+			   netiucv_printname(conn->userid));
+		fsm_newstate(fi, CONN_STATE_STARTWAIT);
+		break;
+	case 13:
+		PRINT_WARN("%s: Too many IUCV connections.\n",
+			   conn->netdev->name);
+		fsm_newstate(fi, CONN_STATE_CONNERR);
+		break;
+	case 14:
+		PRINT_WARN("%s: User %s has too many IUCV connections.\n",
+			   conn->netdev->name,
+			   netiucv_printname(conn->userid));
+		fsm_newstate(fi, CONN_STATE_CONNERR);
+		break;
+	case 15:
+		PRINT_WARN("%s: No IUCV authorization in CP directory.\n",
+			   conn->netdev->name);
+		fsm_newstate(fi, CONN_STATE_CONNERR);
+		break;
+	default:
+		PRINT_WARN("%s: iucv_connect returned error %d\n",
+			   conn->netdev->name, rc);
+		fsm_newstate(fi, CONN_STATE_CONNERR);
+		break;
 	}
 	IUCV_DBF_TEXT_(setup, 5, "iucv_connect rc is %d\n", rc);
-	IUCV_DBF_TEXT(trace, 5, "calling iucv_unregister_program\n");
-	iucv_unregister_program(conn->handle);
-	conn->handle = NULL;
+	kfree(conn->path);
+	conn->path = NULL;
 }
 
-static void
-netiucv_purge_skb_queue(struct sk_buff_head *q)
+static void netiucv_purge_skb_queue(struct sk_buff_head *q)
 {
 	struct sk_buff *skb;
 
@@ -931,36 +938,34 @@
 	}
 }
 
-static void
-conn_action_stop(fsm_instance *fi, int event, void *arg)
+static void conn_action_stop(fsm_instance *fi, int event, void *arg)
 {
-	struct iucv_event *ev = (struct iucv_event *)arg;
+	struct iucv_event *ev = arg;
 	struct iucv_connection *conn = ev->conn;
 	struct net_device *netdev = conn->netdev;
-	struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
+	struct netiucv_priv *privptr = netdev_priv(netdev);
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 
 	fsm_deltimer(&conn->timer);
 	fsm_newstate(fi, CONN_STATE_STOPPED);
 	netiucv_purge_skb_queue(&conn->collect_queue);
-	if (conn->handle)
-		IUCV_DBF_TEXT(trace, 5, "calling iucv_unregister_program\n");
-		iucv_unregister_program(conn->handle);
-	conn->handle = NULL;
+	if (conn->path) {
+		IUCV_DBF_TEXT(trace, 5, "calling iucv_path_sever\n");
+		iucv_path_sever(conn->path, iucvMagic);
+		kfree(conn->path);
+		conn->path = NULL;
+	}
 	netiucv_purge_skb_queue(&conn->commit_queue);
 	fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
 }
 
-static void
-conn_action_inval(fsm_instance *fi, int event, void *arg)
+static void conn_action_inval(fsm_instance *fi, int event, void *arg)
 {
-	struct iucv_event *ev = (struct iucv_event *)arg;
-	struct iucv_connection *conn = ev->conn;
+	struct iucv_connection *conn = arg;
 	struct net_device *netdev = conn->netdev;
 
-	PRINT_WARN("%s: Cannot connect without username\n",
-	       netdev->name);
+	PRINT_WARN("%s: Cannot connect without username\n", netdev->name);
 	IUCV_DBF_TEXT(data, 2, "conn_action_inval called\n");
 }
 
@@ -999,29 +1004,27 @@
 static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
 
 
-/**
+/*
  * Actions for interface - statemachine.
- *****************************************************************************/
+ */
 
 /**
- * Startup connection by sending CONN_EVENT_START to it.
+ * dev_action_start
+ * @fi: An instance of an interface statemachine.
+ * @event: The event, just happened.
+ * @arg: Generic pointer, casted from struct net_device * upon call.
  *
- * @param fi    An instance of an interface statemachine.
- * @param event The event, just happened.
- * @param arg   Generic pointer, casted from struct net_device * upon call.
+ * Startup connection by sending CONN_EVENT_START to it.
  */
-static void
-dev_action_start(fsm_instance *fi, int event, void *arg)
+static void dev_action_start(fsm_instance *fi, int event, void *arg)
 {
-	struct net_device   *dev = (struct net_device *)arg;
-	struct netiucv_priv *privptr = dev->priv;
-	struct iucv_event   ev;
+	struct net_device   *dev = arg;
+	struct netiucv_priv *privptr = netdev_priv(dev);
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 
-	ev.conn = privptr->conn;
 	fsm_newstate(fi, DEV_STATE_STARTWAIT);
-	fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
+	fsm_event(privptr->conn->fsm, CONN_EVENT_START, privptr->conn);
 }
 
 /**
@@ -1034,8 +1037,8 @@
 static void
 dev_action_stop(fsm_instance *fi, int event, void *arg)
 {
-	struct net_device   *dev = (struct net_device *)arg;
-	struct netiucv_priv *privptr = dev->priv;
+	struct net_device   *dev = arg;
+	struct netiucv_priv *privptr = netdev_priv(dev);
 	struct iucv_event   ev;
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
@@ -1057,8 +1060,8 @@
 static void
 dev_action_connup(fsm_instance *fi, int event, void *arg)
 {
-	struct net_device   *dev = (struct net_device *)arg;
-	struct netiucv_priv *privptr = dev->priv;
+	struct net_device   *dev = arg;
+	struct netiucv_priv *privptr = netdev_priv(dev);
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 
@@ -1131,11 +1134,13 @@
  *
  * @return 0 on success, -ERRNO on failure. (Never fails.)
  */
-static int
-netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
+static int netiucv_transmit_skb(struct iucv_connection *conn,
+				struct sk_buff *skb)
+{
+	struct iucv_message msg;
 	unsigned long saveflags;
-	ll_header header;
-	int       rc = 0;
+	struct ll_header header;
+	int rc;
 
 	if (fsm_getstate(conn->fsm) != CONN_STATE_IDLE) {
 		int l = skb->len + NETIUCV_HDRLEN;
@@ -1145,11 +1150,12 @@
 		    (conn->max_buffsize - NETIUCV_HDRLEN)) {
 			rc = -EBUSY;
 			IUCV_DBF_TEXT(data, 2,
-				"EBUSY from netiucv_transmit_skb\n");
+				      "EBUSY from netiucv_transmit_skb\n");
 		} else {
 			atomic_inc(&skb->users);
 			skb_queue_tail(&conn->collect_queue, skb);
 			conn->collect_len += l;
+			rc = 0;
 		}
 		spin_unlock_irqrestore(&conn->collect_lock, saveflags);
 	} else {
@@ -1188,9 +1194,10 @@
 		fsm_newstate(conn->fsm, CONN_STATE_TX);
 		conn->prof.send_stamp = xtime;
 
-		rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */,
-			0, nskb->data, nskb->len);
-			       /* Shut up, gcc! nskb is always below 2G. */
+		msg.tag = 1;
+		msg.class = 0;
+		rc = iucv_message_send(conn->path, &msg, 0, 0,
+				       nskb->data, nskb->len);
 		conn->prof.doios_single++;
 		conn->prof.txlen += skb->len;
 		conn->prof.tx_pending++;
@@ -1200,7 +1207,7 @@
 			struct netiucv_priv *privptr;
 			fsm_newstate(conn->fsm, CONN_STATE_IDLE);
 			conn->prof.tx_pending--;
-			privptr = (struct netiucv_priv *)conn->netdev->priv;
+			privptr = netdev_priv(conn->netdev);
 			if (privptr)
 				privptr->stats.tx_errors++;
 			if (copied)
@@ -1226,9 +1233,9 @@
 	return rc;
 }
 
-/**
+/*
  * Interface API for upper network layers
- *****************************************************************************/
+ */
 
 /**
  * Open an interface.
@@ -1238,9 +1245,11 @@
  *
  * @return 0 on success, -ERRNO on failure. (Never fails.)
  */
-static int
-netiucv_open(struct net_device *dev) {
-	fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_START,dev);
+static int netiucv_open(struct net_device *dev)
+{
+	struct netiucv_priv *priv = netdev_priv(dev);
+
+	fsm_event(priv->fsm, DEV_EVENT_START, dev);
 	return 0;
 }
 
@@ -1252,9 +1261,11 @@
  *
  * @return 0 on success, -ERRNO on failure. (Never fails.)
  */
-static int
-netiucv_close(struct net_device *dev) {
-	fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_STOP, dev);
+static int netiucv_close(struct net_device *dev)
+{
+	struct netiucv_priv *priv = netdev_priv(dev);
+
+	fsm_event(priv->fsm, DEV_EVENT_STOP, dev);
 	return 0;
 }
 
@@ -1271,8 +1282,8 @@
  */
 static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	int          rc = 0;
-	struct netiucv_priv *privptr = dev->priv;
+	struct netiucv_priv *privptr = netdev_priv(dev);
+	int rc;
 
 	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
 	/**
@@ -1312,40 +1323,41 @@
 		return -EBUSY;
 	}
 	dev->trans_start = jiffies;
-	if (netiucv_transmit_skb(privptr->conn, skb))
-		rc = 1;
+	rc = netiucv_transmit_skb(privptr->conn, skb) != 0;
 	netiucv_clear_busy(dev);
 	return rc;
 }
 
 /**
+ * netiucv_stats
+ * @dev: Pointer to interface struct.
+ *
  * Returns interface statistics of a device.
  *
- * @param dev Pointer to interface struct.
- *
- * @return Pointer to stats struct of this interface.
+ * Returns pointer to stats struct of this interface.
  */
-static struct net_device_stats *
-netiucv_stats (struct net_device * dev)
+static struct net_device_stats *netiucv_stats (struct net_device * dev)
 {
+	struct netiucv_priv *priv = netdev_priv(dev);
+
 	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
-	return &((struct netiucv_priv *)dev->priv)->stats;
+	return &priv->stats;
 }
 
 /**
+ * netiucv_change_mtu
+ * @dev: Pointer to interface struct.
+ * @new_mtu: The new MTU to use for this interface.
+ *
  * Sets MTU of an interface.
  *
- * @param dev     Pointer to interface struct.
- * @param new_mtu The new MTU to use for this interface.
- *
- * @return 0 on success, -EINVAL if MTU is out of valid range.
+ * Returns 0 on success, -EINVAL if MTU is out of valid range.
  *         (valid range is 576 .. NETIUCV_MTU_MAX).
  */
-static int
-netiucv_change_mtu (struct net_device * dev, int new_mtu)
+static int netiucv_change_mtu(struct net_device * dev, int new_mtu)
 {
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-	if ((new_mtu < 576) || (new_mtu > NETIUCV_MTU_MAX)) {
+	if (new_mtu < 576 || new_mtu > NETIUCV_MTU_MAX) {
 		IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n");
 		return -EINVAL;
 	}
@@ -1353,12 +1365,12 @@
 	return 0;
 }
 
-/**
+/*
  * attributes in sysfs
- *****************************************************************************/
+ */
 
-static ssize_t
-user_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t user_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1366,8 +1378,8 @@
 	return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid));
 }
 
-static ssize_t
-user_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t user_write(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 	struct net_device *ndev = priv->conn->netdev;
@@ -1375,80 +1387,70 @@
 	char    *tmp;
 	char 	username[9];
 	int 	i;
-	struct iucv_connection **clist = &iucv_conns.iucv_connections;
-	unsigned long flags;
+	struct iucv_connection *cp;
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-	if (count>9) {
-		PRINT_WARN("netiucv: username too long (%d)!\n", (int)count);
+	if (count > 9) {
+		PRINT_WARN("netiucv: username too long (%d)!\n", (int) count);
 		IUCV_DBF_TEXT_(setup, 2,
-			"%d is length of username\n", (int)count);
+			       "%d is length of username\n", (int) count);
 		return -EINVAL;
 	}
 
 	tmp = strsep((char **) &buf, "\n");
-	for (i=0, p=tmp; i<8 && *p; i++, p++) {
-		if (isalnum(*p) || (*p == '$'))
+	for (i = 0, p = tmp; i < 8 && *p; i++, p++) {
+		if (isalnum(*p) || (*p == '$')) {
 			username[i]= toupper(*p);
-		else if (*p == '\n') {
+			continue;
+		}
+		if (*p == '\n') {
 			/* trailing lf, grr */
 			break;
-		} else {
-			PRINT_WARN("netiucv: Invalid char %c in username!\n",
-				*p);
-			IUCV_DBF_TEXT_(setup, 2,
-				"username: invalid character %c\n",
-				*p);
-			return -EINVAL;
 		}
+		PRINT_WARN("netiucv: Invalid char %c in username!\n", *p);
+		IUCV_DBF_TEXT_(setup, 2,
+			       "username: invalid character %c\n", *p);
+		return -EINVAL;
 	}
-	while (i<8)
+	while (i < 8)
 		username[i++] = ' ';
 	username[8] = '\0';
 
-	if (memcmp(username, priv->conn->userid, 9)) {
-		/* username changed */
-		if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
-			PRINT_WARN(
-				"netiucv: device %s active, connected to %s\n",
-				dev->bus_id, priv->conn->userid);
-			PRINT_WARN("netiucv: user cannot be updated\n");
-			IUCV_DBF_TEXT(setup, 2, "user_write: device active\n");
-			return -EBUSY;
+	if (memcmp(username, priv->conn->userid, 9) &&
+	    (ndev->flags & (IFF_UP | IFF_RUNNING))) {
+		/* username changed while the interface is active. */
+		PRINT_WARN("netiucv: device %s active, connected to %s\n",
+			   dev->bus_id, priv->conn->userid);
+		PRINT_WARN("netiucv: user cannot be updated\n");
+		IUCV_DBF_TEXT(setup, 2, "user_write: device active\n");
+		return -EBUSY;
+	}
+	read_lock_bh(&iucv_connection_rwlock);
+	list_for_each_entry(cp, &iucv_connection_list, list) {
+		if (!strncmp(username, cp->userid, 9) && cp->netdev != ndev) {
+			read_unlock_bh(&iucv_connection_rwlock);
+			PRINT_WARN("netiucv: Connection to %s already "
+				   "exists\n", username);
+			return -EEXIST;
 		}
 	}
-	read_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
-	while (*clist) {
-                if (!strncmp(username, (*clist)->userid, 9) ||
-		    ((*clist)->netdev != ndev))
-                        break;
-                clist = &((*clist)->next);
-        }
-	read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
-        if (*clist) {
-                PRINT_WARN("netiucv: Connection to %s already exists\n",
-                        username);
-                return -EEXIST;
-        }
+	read_unlock_bh(&iucv_connection_rwlock);
 	memcpy(priv->conn->userid, username, 9);
-
 	return count;
-
 }
 
 static DEVICE_ATTR(user, 0644, user_show, user_write);
 
-static ssize_t
-buffer_show (struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct netiucv_priv *priv = dev->driver_data;
+static ssize_t buffer_show (struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{	struct netiucv_priv *priv = dev->driver_data;
 
 	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
 	return sprintf(buf, "%d\n", priv->conn->max_buffsize);
 }
 
-static ssize_t
-buffer_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t buffer_write (struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 	struct net_device *ndev = priv->conn->netdev;
@@ -1502,8 +1504,8 @@
 
 static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
 
-static ssize_t
-dev_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t dev_fsm_show (struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1513,8 +1515,8 @@
 
 static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL);
 
-static ssize_t
-conn_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t conn_fsm_show (struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1524,8 +1526,8 @@
 
 static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL);
 
-static ssize_t
-maxmulti_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t maxmulti_show (struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1533,8 +1535,9 @@
 	return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti);
 }
 
-static ssize_t
-maxmulti_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t maxmulti_write (struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1545,8 +1548,8 @@
 
 static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write);
 
-static ssize_t
-maxcq_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t maxcq_show (struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1554,8 +1557,8 @@
 	return sprintf(buf, "%ld\n", priv->conn->prof.maxcqueue);
 }
 
-static ssize_t
-maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t maxcq_write (struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1566,8 +1569,8 @@
 
 static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write);
 
-static ssize_t
-sdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t sdoio_show (struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1575,8 +1578,8 @@
 	return sprintf(buf, "%ld\n", priv->conn->prof.doios_single);
 }
 
-static ssize_t
-sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t sdoio_write (struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1587,8 +1590,8 @@
 
 static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write);
 
-static ssize_t
-mdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t mdoio_show (struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1596,8 +1599,8 @@
 	return sprintf(buf, "%ld\n", priv->conn->prof.doios_multi);
 }
 
-static ssize_t
-mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t mdoio_write (struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1608,8 +1611,8 @@
 
 static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write);
 
-static ssize_t
-txlen_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t txlen_show (struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1617,8 +1620,8 @@
 	return sprintf(buf, "%ld\n", priv->conn->prof.txlen);
 }
 
-static ssize_t
-txlen_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t txlen_write (struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1629,8 +1632,8 @@
 
 static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write);
 
-static ssize_t
-txtime_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t txtime_show (struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1638,8 +1641,8 @@
 	return sprintf(buf, "%ld\n", priv->conn->prof.tx_time);
 }
 
-static ssize_t
-txtime_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t txtime_write (struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1650,8 +1653,8 @@
 
 static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write);
 
-static ssize_t
-txpend_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t txpend_show (struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1659,8 +1662,8 @@
 	return sprintf(buf, "%ld\n", priv->conn->prof.tx_pending);
 }
 
-static ssize_t
-txpend_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t txpend_write (struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1671,8 +1674,8 @@
 
 static DEVICE_ATTR(tx_pending, 0644, txpend_show, txpend_write);
 
-static ssize_t
-txmpnd_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t txmpnd_show (struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1680,8 +1683,8 @@
 	return sprintf(buf, "%ld\n", priv->conn->prof.tx_max_pending);
 }
 
-static ssize_t
-txmpnd_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t txmpnd_write (struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1721,8 +1724,7 @@
 	.attrs = netiucv_stat_attrs,
 };
 
-static inline int
-netiucv_add_files(struct device *dev)
+static inline int netiucv_add_files(struct device *dev)
 {
 	int ret;
 
@@ -1736,18 +1738,16 @@
 	return ret;
 }
 
-static inline void
-netiucv_remove_files(struct device *dev)
+static inline void netiucv_remove_files(struct device *dev)
 {
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 	sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group);
 	sysfs_remove_group(&dev->kobj, &netiucv_attr_group);
 }
 
-static int
-netiucv_register_device(struct net_device *ndev)
+static int netiucv_register_device(struct net_device *ndev)
 {
-	struct netiucv_priv *priv = ndev->priv;
+	struct netiucv_priv *priv = netdev_priv(ndev);
 	struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL);
 	int ret;
 
@@ -1786,8 +1786,7 @@
 	return ret;
 }
 
-static void
-netiucv_unregister_device(struct device *dev)
+static void netiucv_unregister_device(struct device *dev)
 {
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 	netiucv_remove_files(dev);
@@ -1798,107 +1797,89 @@
  * Allocate and initialize a new connection structure.
  * Add it to the list of netiucv connections;
  */
-static struct iucv_connection *
-netiucv_new_connection(struct net_device *dev, char *username)
+static struct iucv_connection *netiucv_new_connection(struct net_device *dev,
+						      char *username)
 {
-	unsigned long flags;
-	struct iucv_connection **clist = &iucv_conns.iucv_connections;
-	struct iucv_connection *conn =
-		kzalloc(sizeof(struct iucv_connection), GFP_KERNEL);
+	struct iucv_connection *conn;
 
-	if (conn) {
-		skb_queue_head_init(&conn->collect_queue);
-		skb_queue_head_init(&conn->commit_queue);
-		spin_lock_init(&conn->collect_lock);
-		conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
-		conn->netdev = dev;
+	conn = kzalloc(sizeof(*conn), GFP_KERNEL);
+	if (!conn)
+		goto out;
+	skb_queue_head_init(&conn->collect_queue);
+	skb_queue_head_init(&conn->commit_queue);
+	spin_lock_init(&conn->collect_lock);
+	conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
+	conn->netdev = dev;
 
-		conn->rx_buff = alloc_skb(NETIUCV_BUFSIZE_DEFAULT,
-					  GFP_KERNEL | GFP_DMA);
-		if (!conn->rx_buff) {
-			kfree(conn);
-			return NULL;
-		}
-		conn->tx_buff = alloc_skb(NETIUCV_BUFSIZE_DEFAULT,
-					  GFP_KERNEL | GFP_DMA);
-		if (!conn->tx_buff) {
-			kfree_skb(conn->rx_buff);
-			kfree(conn);
-			return NULL;
-		}
-		conn->fsm = init_fsm("netiucvconn", conn_state_names,
-				     conn_event_names, NR_CONN_STATES,
-				     NR_CONN_EVENTS, conn_fsm, CONN_FSM_LEN,
-				     GFP_KERNEL);
-		if (!conn->fsm) {
-			kfree_skb(conn->tx_buff);
-			kfree_skb(conn->rx_buff);
-			kfree(conn);
-			return NULL;
-		}
-		fsm_settimer(conn->fsm, &conn->timer);
-		fsm_newstate(conn->fsm, CONN_STATE_INVALID);
+	conn->rx_buff = alloc_skb(conn->max_buffsize, GFP_KERNEL | GFP_DMA);
+	if (!conn->rx_buff)
+		goto out_conn;
+	conn->tx_buff = alloc_skb(conn->max_buffsize, GFP_KERNEL | GFP_DMA);
+	if (!conn->tx_buff)
+		goto out_rx;
+	conn->fsm = init_fsm("netiucvconn", conn_state_names,
+			     conn_event_names, NR_CONN_STATES,
+			     NR_CONN_EVENTS, conn_fsm, CONN_FSM_LEN,
+			     GFP_KERNEL);
+	if (!conn->fsm)
+		goto out_tx;
 
-		if (username) {
-			memcpy(conn->userid, username, 9);
-			fsm_newstate(conn->fsm, CONN_STATE_STOPPED);
-		}
+	fsm_settimer(conn->fsm, &conn->timer);
+	fsm_newstate(conn->fsm, CONN_STATE_INVALID);
 
-		write_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
-		conn->next = *clist;
-		*clist = conn;
-		write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
+	if (username) {
+		memcpy(conn->userid, username, 9);
+		fsm_newstate(conn->fsm, CONN_STATE_STOPPED);
 	}
+
+	write_lock_bh(&iucv_connection_rwlock);
+	list_add_tail(&conn->list, &iucv_connection_list);
+	write_unlock_bh(&iucv_connection_rwlock);
 	return conn;
+
+out_tx:
+	kfree_skb(conn->tx_buff);
+out_rx:
+	kfree_skb(conn->rx_buff);
+out_conn:
+	kfree(conn);
+out:
+	return NULL;
 }
 
 /**
  * Release a connection structure and remove it from the
  * list of netiucv connections.
  */
-static void
-netiucv_remove_connection(struct iucv_connection *conn)
+static void netiucv_remove_connection(struct iucv_connection *conn)
 {
-	struct iucv_connection **clist = &iucv_conns.iucv_connections;
-	unsigned long flags;
-
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-	if (conn == NULL)
-		return;
-	write_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
-	while (*clist) {
-		if (*clist == conn) {
-			*clist = conn->next;
-			write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
-			if (conn->handle) {
-				iucv_unregister_program(conn->handle);
-				conn->handle = NULL;
-			}
-			fsm_deltimer(&conn->timer);
-			kfree_fsm(conn->fsm);
-			kfree_skb(conn->rx_buff);
-			kfree_skb(conn->tx_buff);
-			return;
-		}
-		clist = &((*clist)->next);
+	write_lock_bh(&iucv_connection_rwlock);
+	list_del_init(&conn->list);
+	write_unlock_bh(&iucv_connection_rwlock);
+	if (conn->path) {
+		iucv_path_sever(conn->path, iucvMagic);
+		kfree(conn->path);
+		conn->path = NULL;
 	}
-	write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
+	fsm_deltimer(&conn->timer);
+	kfree_fsm(conn->fsm);
+	kfree_skb(conn->rx_buff);
+	kfree_skb(conn->tx_buff);
 }
 
 /**
  * Release everything of a net device.
  */
-static void
-netiucv_free_netdevice(struct net_device *dev)
+static void netiucv_free_netdevice(struct net_device *dev)
 {
-	struct netiucv_priv *privptr;
+	struct netiucv_priv *privptr = netdev_priv(dev);
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 
 	if (!dev)
 		return;
 
-	privptr = (struct netiucv_priv *)dev->priv;
 	if (privptr) {
 		if (privptr->conn)
 			netiucv_remove_connection(privptr->conn);
@@ -1913,11 +1894,8 @@
 /**
  * Initialize a net device. (Called from kernel in alloc_netdev())
  */
-static void
-netiucv_setup_netdevice(struct net_device *dev)
+static void netiucv_setup_netdevice(struct net_device *dev)
 {
-        memset(dev->priv, 0, sizeof(struct netiucv_priv));
-
 	dev->mtu	         = NETIUCV_MTU_DEFAULT;
 	dev->hard_start_xmit     = netiucv_tx;
 	dev->open	         = netiucv_open;
@@ -1936,8 +1914,7 @@
 /**
  * Allocate and initialize everything of a net device.
  */
-static struct net_device *
-netiucv_init_netdevice(char *username)
+static struct net_device *netiucv_init_netdevice(char *username)
 {
 	struct netiucv_priv *privptr;
 	struct net_device *dev;
@@ -1946,40 +1923,40 @@
 			   netiucv_setup_netdevice);
 	if (!dev)
 		return NULL;
-	if (dev_alloc_name(dev, dev->name) < 0) {
-		free_netdev(dev);
-		return NULL;
-	}
+	if (dev_alloc_name(dev, dev->name) < 0)
+		goto out_netdev;
 
-	privptr = (struct netiucv_priv *)dev->priv;
+	privptr = netdev_priv(dev);
 	privptr->fsm = init_fsm("netiucvdev", dev_state_names,
 				dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
 				dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
-	if (!privptr->fsm) {
-		free_netdev(dev);
-		return NULL;
-	}
+	if (!privptr->fsm)
+		goto out_netdev;
+
 	privptr->conn = netiucv_new_connection(dev, username);
 	if (!privptr->conn) {
-		kfree_fsm(privptr->fsm);
-		free_netdev(dev);
 		IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_new_connection\n");
-		return NULL;
+		goto out_fsm;
 	}
 	fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
-
 	return dev;
+
+out_fsm:
+	kfree_fsm(privptr->fsm);
+out_netdev:
+	free_netdev(dev);
+	return NULL;
 }
 
-static ssize_t
-conn_write(struct device_driver *drv, const char *buf, size_t count)
+static ssize_t conn_write(struct device_driver *drv,
+			  const char *buf, size_t count)
 {
-	char *p;
+	const char *p;
 	char username[9];
-	int i, ret;
+	int i, rc;
 	struct net_device *dev;
-	struct iucv_connection **clist = &iucv_conns.iucv_connections;
-	unsigned long flags;
+	struct netiucv_priv *priv;
+	struct iucv_connection *cp;
 
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
 	if (count>9) {
@@ -1988,83 +1965,82 @@
 		return -EINVAL;
 	}
 
-	for (i=0, p=(char *)buf; i<8 && *p; i++, p++) {
-		if (isalnum(*p) || (*p == '$'))
-			username[i]= toupper(*p);
-		else if (*p == '\n') {
+	for (i = 0, p = buf; i < 8 && *p; i++, p++) {
+		if (isalnum(*p) || *p == '$') {
+			username[i] = toupper(*p);
+			continue;
+		}
+		if (*p == '\n')
 			/* trailing lf, grr */
 			break;
-		} else {
-			PRINT_WARN("netiucv: Invalid character in username!\n");
-			IUCV_DBF_TEXT_(setup, 2,
-				"conn_write: invalid character %c\n", *p);
-			return -EINVAL;
-		}
+		PRINT_WARN("netiucv: Invalid character in username!\n");
+		IUCV_DBF_TEXT_(setup, 2,
+			       "conn_write: invalid character %c\n", *p);
+		return -EINVAL;
 	}
-	while (i<8)
+	while (i < 8)
 		username[i++] = ' ';
 	username[8] = '\0';
 
-	read_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
-	while (*clist) {
-		if (!strncmp(username, (*clist)->userid, 9))
-			break;
-		clist = &((*clist)->next);
+	read_lock_bh(&iucv_connection_rwlock);
+	list_for_each_entry(cp, &iucv_connection_list, list) {
+		if (!strncmp(username, cp->userid, 9)) {
+			read_unlock_bh(&iucv_connection_rwlock);
+			PRINT_WARN("netiucv: Connection to %s already "
+				   "exists\n", username);
+			return -EEXIST;
+		}
 	}
-	read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
-	if (*clist) {
-		PRINT_WARN("netiucv: Connection to %s already exists\n",
-			username);
-		return -EEXIST;
-	}
+	read_unlock_bh(&iucv_connection_rwlock);
+
 	dev = netiucv_init_netdevice(username);
 	if (!dev) {
-		PRINT_WARN(
-		       "netiucv: Could not allocate network device structure "
-		       "for user '%s'\n", netiucv_printname(username));
+		PRINT_WARN("netiucv: Could not allocate network device "
+			   "structure for user '%s'\n",
+			   netiucv_printname(username));
 		IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_init_netdevice\n");
 		return -ENODEV;
 	}
 
-	if ((ret = netiucv_register_device(dev))) {
+	rc = netiucv_register_device(dev);
+	if (rc) {
 		IUCV_DBF_TEXT_(setup, 2,
-			"ret %d from netiucv_register_device\n", ret);
+			"ret %d from netiucv_register_device\n", rc);
 		goto out_free_ndev;
 	}
 
 	/* sysfs magic */
-	SET_NETDEV_DEV(dev,
-			(struct device*)((struct netiucv_priv*)dev->priv)->dev);
+	priv = netdev_priv(dev);
+	SET_NETDEV_DEV(dev, priv->dev);
 
-	if ((ret = register_netdev(dev))) {
-		netiucv_unregister_device((struct device*)
-			((struct netiucv_priv*)dev->priv)->dev);
-		goto out_free_ndev;
-	}
+	rc = register_netdev(dev);
+	if (rc)
+		goto out_unreg;
 
 	PRINT_INFO("%s: '%s'\n", dev->name, netiucv_printname(username));
 
 	return count;
 
+out_unreg:
+	netiucv_unregister_device(priv->dev);
 out_free_ndev:
 	PRINT_WARN("netiucv: Could not register '%s'\n", dev->name);
 	IUCV_DBF_TEXT(setup, 2, "conn_write: could not register\n");
 	netiucv_free_netdevice(dev);
-	return ret;
+	return rc;
 }
 
 static DRIVER_ATTR(connection, 0200, NULL, conn_write);
 
-static ssize_t
-remove_write (struct device_driver *drv, const char *buf, size_t count)
+static ssize_t remove_write (struct device_driver *drv,
+			     const char *buf, size_t count)
 {
-	struct iucv_connection **clist = &iucv_conns.iucv_connections;
-	unsigned long flags;
+	struct iucv_connection *cp;
         struct net_device *ndev;
         struct netiucv_priv *priv;
         struct device *dev;
         char name[IFNAMSIZ];
-        char *p;
+	const char *p;
         int i;
 
         IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
@@ -2072,33 +2048,27 @@
         if (count >= IFNAMSIZ)
                 count = IFNAMSIZ - 1;;
 
-        for (i=0, p=(char *)buf; i<count && *p; i++, p++) {
-                if ((*p == '\n') || (*p == ' ')) {
+	for (i = 0, p = buf; i < count && *p; i++, p++) {
+		if (*p == '\n' || *p == ' ')
                         /* trailing lf, grr */
                         break;
-                } else {
-                        name[i]=*p;
-                }
+		name[i] = *p;
         }
         name[i] = '\0';
 
-	read_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
-        while (*clist) {
-                ndev = (*clist)->netdev;
-                priv = (struct netiucv_priv*)ndev->priv;
+	read_lock_bh(&iucv_connection_rwlock);
+	list_for_each_entry(cp, &iucv_connection_list, list) {
+		ndev = cp->netdev;
+		priv = netdev_priv(ndev);
                 dev = priv->dev;
-
-                if (strncmp(name, ndev->name, count)) {
-                        clist = &((*clist)->next);
-                        continue;
-                }
-		read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
+		if (strncmp(name, ndev->name, count))
+			continue;
+		read_unlock_bh(&iucv_connection_rwlock);
                 if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
-                        PRINT_WARN(
-                                "netiucv: net device %s active with peer %s\n",
-                                ndev->name, priv->conn->userid);
+			PRINT_WARN("netiucv: net device %s active with peer "
+				   "%s\n", ndev->name, priv->conn->userid);
                         PRINT_WARN("netiucv: %s cannot be removed\n",
-                                ndev->name);
+				   ndev->name);
 			IUCV_DBF_TEXT(data, 2, "remove_write: still active\n");
                         return -EBUSY;
                 }
@@ -2106,7 +2076,7 @@
                 netiucv_unregister_device(dev);
                 return count;
         }
-	read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
+	read_unlock_bh(&iucv_connection_rwlock);
         PRINT_WARN("netiucv: net device %s unknown\n", name);
 	IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n");
         return -EINVAL;
@@ -2114,67 +2084,86 @@
 
 static DRIVER_ATTR(remove, 0200, NULL, remove_write);
 
-static void
-netiucv_banner(void)
+static struct attribute * netiucv_drv_attrs[] = {
+	&driver_attr_connection.attr,
+	&driver_attr_remove.attr,
+	NULL,
+};
+
+static struct attribute_group netiucv_drv_attr_group = {
+	.attrs = netiucv_drv_attrs,
+};
+
+static void netiucv_banner(void)
 {
 	PRINT_INFO("NETIUCV driver initialized\n");
 }
 
-static void __exit
-netiucv_exit(void)
+static void __exit netiucv_exit(void)
 {
+	struct iucv_connection *cp;
+	struct net_device *ndev;
+	struct netiucv_priv *priv;
+	struct device *dev;
+
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-	while (iucv_conns.iucv_connections) {
-		struct net_device *ndev = iucv_conns.iucv_connections->netdev;
-		struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv;
-		struct device *dev = priv->dev;
+	while (!list_empty(&iucv_connection_list)) {
+		cp = list_entry(iucv_connection_list.next,
+				struct iucv_connection, list);
+		list_del(&cp->list);
+		ndev = cp->netdev;
+		priv = netdev_priv(ndev);
+		dev = priv->dev;
 
 		unregister_netdev(ndev);
 		netiucv_unregister_device(dev);
 	}
 
-	driver_remove_file(&netiucv_driver, &driver_attr_connection);
-	driver_remove_file(&netiucv_driver, &driver_attr_remove);
+	sysfs_remove_group(&netiucv_driver.kobj, &netiucv_drv_attr_group);
 	driver_unregister(&netiucv_driver);
+	iucv_unregister(&netiucv_handler, 1);
 	iucv_unregister_dbf_views();
 
 	PRINT_INFO("NETIUCV driver unloaded\n");
 	return;
 }
 
-static int __init
-netiucv_init(void)
+static int __init netiucv_init(void)
 {
-	int ret;
+	int rc;
 
-	ret = iucv_register_dbf_views();
-	if (ret) {
-		PRINT_WARN("netiucv_init failed, "
-			"iucv_register_dbf_views rc = %d\n", ret);
-		return ret;
-	}
+	rc = iucv_register_dbf_views();
+	if (rc)
+		goto out;
+	rc = iucv_register(&netiucv_handler, 1);
+	if (rc)
+		goto out_dbf;
 	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-	ret = driver_register(&netiucv_driver);
-	if (ret) {
+	rc = driver_register(&netiucv_driver);
+	if (rc) {
 		PRINT_ERR("NETIUCV: failed to register driver.\n");
-		IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_register\n", ret);
-		iucv_unregister_dbf_views();
-		return ret;
+		IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_register\n", rc);
+		goto out_iucv;
 	}
 
-	/* Add entry for specifying connections. */
-	ret = driver_create_file(&netiucv_driver, &driver_attr_connection);
-	if (!ret) {
-		ret = driver_create_file(&netiucv_driver, &driver_attr_remove);
-		netiucv_banner();
-		rwlock_init(&iucv_conns.iucv_rwlock);
-	} else {
-		PRINT_ERR("NETIUCV: failed to add driver attribute.\n");
-		IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_create_file\n", ret);
-		driver_unregister(&netiucv_driver);
-		iucv_unregister_dbf_views();
+	rc = sysfs_create_group(&netiucv_driver.kobj, &netiucv_drv_attr_group);
+	if (rc) {
+		PRINT_ERR("NETIUCV: failed to add driver attributes.\n");
+		IUCV_DBF_TEXT_(setup, 2,
+			       "ret %d - netiucv_drv_attr_group\n", rc);
+		goto out_driver;
 	}
-	return ret;
+	netiucv_banner();
+	return rc;
+
+out_driver:
+	driver_unregister(&netiucv_driver);
+out_iucv:
+	iucv_unregister(&netiucv_handler, 1);
+out_dbf:
+	iucv_unregister_dbf_views();
+out:
+	return rc;
 }
 
 module_init(netiucv_init);
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index faa768e..81f805c 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -161,7 +161,7 @@
 	return seq_open(file, &qeth_procfile_seq_ops);
 }
 
-static struct file_operations qeth_procfile_fops = {
+static const struct file_operations qeth_procfile_fops = {
 	.owner   = THIS_MODULE,
 	.open    = qeth_procfile_open,
 	.read    = seq_read,
@@ -273,7 +273,7 @@
 	return seq_open(file, &qeth_perf_procfile_seq_ops);
 }
 
-static struct file_operations qeth_perf_procfile_fops = {
+static const struct file_operations qeth_perf_procfile_fops = {
 	.owner   = THIS_MODULE,
 	.open    = qeth_perf_procfile_open,
 	.read    = seq_read,
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index b8179c2..3ccca58 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -1,7 +1,7 @@
 /*
  * IUCV special message driver
  *
- * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
  * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -23,10 +23,10 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/device.h>
+#include <net/iucv/iucv.h>
 #include <asm/cpcmd.h>
 #include <asm/ebcdic.h>
-
-#include "iucv.h"
+#include "smsgiucv.h"
 
 struct smsg_callback {
 	struct list_head list;
@@ -39,38 +39,46 @@
    ("(C) 2003 IBM Corporation by Martin Schwidefsky (schwidefsky@de.ibm.com)");
 MODULE_DESCRIPTION ("Linux for S/390 IUCV special message driver");
 
-static iucv_handle_t smsg_handle;
-static unsigned short smsg_pathid;
+static struct iucv_path *smsg_path;
+
 static DEFINE_SPINLOCK(smsg_list_lock);
 static struct list_head smsg_list = LIST_HEAD_INIT(smsg_list);
 
-static void
-smsg_connection_complete(iucv_ConnectionComplete *eib, void *pgm_data)
+static int smsg_path_pending(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+static void smsg_message_pending(struct iucv_path *, struct iucv_message *);
+
+static struct iucv_handler smsg_handler = {
+	.path_pending	 = smsg_path_pending,
+	.message_pending = smsg_message_pending,
+};
+
+static int smsg_path_pending(struct iucv_path *path, u8 ipvmid[8],
+			     u8 ipuser[16])
 {
+	if (strncmp(ipvmid, "*MSG    ", sizeof(ipvmid)) != 0)
+		return -EINVAL;
+	/* Path pending from *MSG. */
+	return iucv_path_accept(path, &smsg_handler, "SMSGIUCV        ", NULL);
 }
 
-
-static void
-smsg_message_pending(iucv_MessagePending *eib, void *pgm_data)
+static void smsg_message_pending(struct iucv_path *path,
+				 struct iucv_message *msg)
 {
 	struct smsg_callback *cb;
-	unsigned char *msg;
+	unsigned char *buffer;
 	unsigned char sender[9];
-	unsigned short len;
 	int rc, i;
 
-	len = eib->ln1msg2.ipbfln1f;
-	msg = kmalloc(len + 1, GFP_ATOMIC|GFP_DMA);
-	if (!msg) {
-		iucv_reject(eib->ippathid, eib->ipmsgid, eib->iptrgcls);
+	buffer = kmalloc(msg->length + 1, GFP_ATOMIC | GFP_DMA);
+	if (!buffer) {
+		iucv_message_reject(path, msg);
 		return;
 	}
-	rc = iucv_receive(eib->ippathid, eib->ipmsgid, eib->iptrgcls,
-			  msg, len, NULL, NULL, NULL);
+	rc = iucv_message_receive(path, msg, 0, buffer, msg->length, NULL);
 	if (rc == 0) {
-		msg[len] = 0;
-		EBCASC(msg, len);
-		memcpy(sender, msg, 8);
+		buffer[msg->length] = 0;
+		EBCASC(buffer, msg->length);
+		memcpy(sender, buffer, 8);
 		sender[8] = 0;
 		/* Remove trailing whitespace from the sender name. */
 		for (i = 7; i >= 0; i--) {
@@ -80,27 +88,17 @@
 		}
 		spin_lock(&smsg_list_lock);
 		list_for_each_entry(cb, &smsg_list, list)
-			if (strncmp(msg + 8, cb->prefix, cb->len) == 0) {
-				cb->callback(sender, msg + 8);
+			if (strncmp(buffer + 8, cb->prefix, cb->len) == 0) {
+				cb->callback(sender, buffer + 8);
 				break;
 			}
 		spin_unlock(&smsg_list_lock);
 	}
-	kfree(msg);
+	kfree(buffer);
 }
 
-static iucv_interrupt_ops_t smsg_ops = {
-	.ConnectionComplete = smsg_connection_complete,
-	.MessagePending     = smsg_message_pending,
-};
-
-static struct device_driver smsg_driver = {
-	.name = "SMSGIUCV",
-	.bus  = &iucv_bus,
-};
-
-int
-smsg_register_callback(char *prefix, void (*callback)(char *from, char *str))
+int smsg_register_callback(char *prefix,
+			   void (*callback)(char *from, char *str))
 {
 	struct smsg_callback *cb;
 
@@ -110,18 +108,18 @@
 	cb->prefix = prefix;
 	cb->len = strlen(prefix);
 	cb->callback = callback;
-	spin_lock(&smsg_list_lock);
+	spin_lock_bh(&smsg_list_lock);
 	list_add_tail(&cb->list, &smsg_list);
-	spin_unlock(&smsg_list_lock);
+	spin_unlock_bh(&smsg_list_lock);
 	return 0;
 }
 
-void
-smsg_unregister_callback(char *prefix, void (*callback)(char *from, char *str))
+void smsg_unregister_callback(char *prefix,
+			      void (*callback)(char *from, char *str))
 {
 	struct smsg_callback *cb, *tmp;
 
-	spin_lock(&smsg_list_lock);
+	spin_lock_bh(&smsg_list_lock);
 	cb = NULL;
 	list_for_each_entry(tmp, &smsg_list, list)
 		if (tmp->callback == callback &&
@@ -130,55 +128,58 @@
 			list_del(&cb->list);
 			break;
 		}
-	spin_unlock(&smsg_list_lock);
+	spin_unlock_bh(&smsg_list_lock);
 	kfree(cb);
 }
 
-static void __exit
-smsg_exit(void)
+static struct device_driver smsg_driver = {
+	.name = "SMSGIUCV",
+	.bus  = &iucv_bus,
+};
+
+static void __exit smsg_exit(void)
 {
-	if (smsg_handle > 0) {
-		cpcmd("SET SMSG OFF", NULL, 0, NULL);
-		iucv_sever(smsg_pathid, NULL);
-		iucv_unregister_program(smsg_handle);
-		driver_unregister(&smsg_driver);
-	}
-	return;
+	cpcmd("SET SMSG IUCV", NULL, 0, NULL);
+	iucv_unregister(&smsg_handler, 1);
+	driver_unregister(&smsg_driver);
 }
 
-static int __init
-smsg_init(void)
+static int __init smsg_init(void)
 {
-	static unsigned char pgmmask[24] = {
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-	};
 	int rc;
 
 	rc = driver_register(&smsg_driver);
-	if (rc != 0) {
-		printk(KERN_ERR "SMSGIUCV: failed to register driver.\n");
-		return rc;
-	}
-	smsg_handle = iucv_register_program("SMSGIUCV        ", "*MSG    ",
-					    pgmmask, &smsg_ops, NULL);
-	if (!smsg_handle) {
+	if (rc != 0)
+		goto out;
+	rc = iucv_register(&smsg_handler, 1);
+	if (rc) {
 		printk(KERN_ERR "SMSGIUCV: failed to register to iucv");
-		driver_unregister(&smsg_driver);
-		return -EIO;	/* better errno ? */
+		rc = -EIO;	/* better errno ? */
+		goto out_driver;
 	}
-	rc = iucv_connect (&smsg_pathid, 255, NULL, "*MSG    ", NULL, 0,
-			   NULL, NULL, smsg_handle, NULL);
+	smsg_path = iucv_path_alloc(255, 0, GFP_KERNEL);
+	if (!smsg_path) {
+		rc = -ENOMEM;
+		goto out_register;
+	}
+	rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG    ",
+			       NULL, NULL, NULL);
 	if (rc) {
 		printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG");
-		iucv_unregister_program(smsg_handle);
-		driver_unregister(&smsg_driver);
-		smsg_handle = NULL;
-		return -EIO;
+		rc = -EIO;	/* better errno ? */
+		goto out_free;
 	}
 	cpcmd("SET SMSG IUCV", NULL, 0, NULL);
 	return 0;
+
+out_free:
+	iucv_path_free(smsg_path);
+out_register:
+	iucv_unregister(&smsg_handler, 1);
+out_driver:
+	driver_unregister(&smsg_driver);
+out:
+	return rc;
 }
 
 module_init(smsg_init);
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 39a8852..1f9554e 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -60,7 +60,7 @@
 	_IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_sense_data)
 
 
-static struct file_operations zfcp_cfdc_fops = {
+static const struct file_operations zfcp_cfdc_fops = {
 	.unlocked_ioctl = zfcp_cfdc_dev_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = zfcp_cfdc_dev_ioctl
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 88642de..421da1e 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -838,32 +838,28 @@
  *		and does appropriate preparations (dismiss fsf request, ...)
  *
  * locks:	called under erp_lock (disabled interrupts)
- *
- * returns:	0
  */
-static int
+static void
 zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
 {
-	int retval = 0;
-	struct zfcp_fsf_req *fsf_req = NULL;
 	struct zfcp_adapter *adapter = erp_action->adapter;
 
 	if (erp_action->fsf_req) {
 		/* take lock to ensure that request is not deleted meanwhile */
 		spin_lock(&adapter->req_list_lock);
-		if ((!zfcp_reqlist_ismember(adapter,
-					    erp_action->fsf_req->req_id)) &&
-		    (fsf_req->erp_action == erp_action)) {
+		if (zfcp_reqlist_ismember(adapter,
+					    erp_action->fsf_req->req_id)) {
 			/* fsf_req still exists */
 			debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
-			debug_event(adapter->erp_dbf, 3, &fsf_req,
+			debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req,
 				    sizeof (unsigned long));
 			/* dismiss fsf_req of timed out/dismissed erp_action */
 			if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED |
 						  ZFCP_STATUS_ERP_TIMEDOUT)) {
 				debug_text_event(adapter->erp_dbf, 3,
 						 "a_ca_disreq");
-				fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
+				erp_action->fsf_req->status |=
+					ZFCP_STATUS_FSFREQ_DISMISSED;
 			}
 			if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
 				ZFCP_LOG_NORMAL("error: erp step timed out "
@@ -876,11 +872,11 @@
 			 * then keep it running asynchronously and don't mess
 			 * with the association of erp_action and fsf_req.
 			 */
-			if (fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED |
+			if (erp_action->fsf_req->status &
+					(ZFCP_STATUS_FSFREQ_COMPLETED |
 					       ZFCP_STATUS_FSFREQ_DISMISSED)) {
 				/* forget about association between fsf_req
 				   and erp_action */
-				fsf_req->erp_action = NULL;
 				erp_action->fsf_req = NULL;
 			}
 		} else {
@@ -894,8 +890,6 @@
 		spin_unlock(&adapter->req_list_lock);
 	} else
 		debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
-
-	return retval;
 }
 
 /**
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index cda0cc0..01386ac 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -89,7 +89,7 @@
 				  u32, u32, struct zfcp_sg_list *);
 extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long);
 extern void zfcp_erp_start_timer(struct zfcp_fsf_req *);
-extern int  zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
+extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
 extern int  zfcp_fsf_status_read(struct zfcp_adapter *, int);
 extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *,
 			       unsigned long *, struct zfcp_fsf_req **);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 4b3ae3f..ef16f7c 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -176,28 +176,25 @@
 /**
  * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests
  */
-int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
+void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
 {
 	struct zfcp_fsf_req *request, *tmp;
 	unsigned long flags;
+	LIST_HEAD(remove_queue);
 	unsigned int i, counter;
 
 	spin_lock_irqsave(&adapter->req_list_lock, flags);
 	atomic_set(&adapter->reqs_active, 0);
-	for (i=0; i<REQUEST_LIST_SIZE; i++) {
-		if (list_empty(&adapter->req_list[i]))
-			continue;
+	for (i=0; i<REQUEST_LIST_SIZE; i++)
+		list_splice_init(&adapter->req_list[i], &remove_queue);
 
-		counter = 0;
-		list_for_each_entry_safe(request, tmp,
-					 &adapter->req_list[i], list) {
-			zfcp_fsf_req_dismiss(adapter, request, counter);
-			counter++;
-		}
-	}
 	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
 
-	return 0;
+	counter = 0;
+	list_for_each_entry_safe(request, tmp, &remove_queue, list) {
+		zfcp_fsf_req_dismiss(adapter, request, counter);
+		counter++;
+	}
 }
 
 /*
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index ac7d125..a39ee80 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -846,7 +846,7 @@
       return errno;
 }
 
-static struct file_operations bpp_fops = {
+static const struct file_operations bpp_fops = {
 	.owner =	THIS_MODULE,
 	.read =		bpp_read,
 	.write =	bpp_write,
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index ad1c7db..022e869 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -20,7 +20,6 @@
 #include <linux/major.h>
 #include <linux/init.h>
 #include <linux/miscdevice.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timer.h>
@@ -459,7 +458,7 @@
 	return IRQ_HANDLED;
 }
 
-static struct file_operations wd_fops = {
+static const struct file_operations wd_fops = {
 	.owner =	THIS_MODULE,
 	.ioctl =	wd_ioctl,
 	.compat_ioctl =	wd_compat_ioctl,
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index a4909e0..2d14a29 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -166,7 +166,7 @@
 	return error;
 }
 
-static struct file_operations d7s_fops = {
+static const struct file_operations d7s_fops = {
 	.owner =		THIS_MODULE,
 	.unlocked_ioctl =	d7s_ioctl,
 	.compat_ioctl =		d7s_ioctl,
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index fff4660..2cea4f5 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -705,7 +705,7 @@
 	return 0;
 }
 
-static struct file_operations envctrl_fops = {
+static const struct file_operations envctrl_fops = {
 	.owner =		THIS_MODULE,
 	.read =			envctrl_read,
 	.unlocked_ioctl =	envctrl_ioctl,
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index fa2418f..6e99507 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -142,7 +142,7 @@
 	return 0;
 }
 
-static struct file_operations flash_fops = {
+static const struct file_operations flash_fops = {
 	/* no write to the Flash, use mmap
 	 * and play flash dependent tricks.
 	 */
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 14631ac..512857a 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -431,7 +431,7 @@
 	return 0;
 }
 
-static struct file_operations jsf_fops = {
+static const struct file_operations jsf_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	jsf_lseek,
 	.read =		jsf_read,
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 4e2a0e2..eec28c1 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -31,7 +31,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -704,7 +703,7 @@
 	return 0;
 }
 
-static struct file_operations openprom_fops = {
+static const struct file_operations openprom_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.ioctl =	openprom_ioctl,
diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/sbus/char/riowatchdog.c
index 2a9cc82..a2fc6b8 100644
--- a/drivers/sbus/char/riowatchdog.c
+++ b/drivers/sbus/char/riowatchdog.c
@@ -193,7 +193,7 @@
 	return 0;
 }
 
-static struct file_operations riowd_fops = {
+static const struct file_operations riowd_fops = {
 	.owner =	THIS_MODULE,
 	.ioctl =	riowd_ioctl,
 	.open =		riowd_open,
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c
index 9b988ba..94d1858 100644
--- a/drivers/sbus/char/rtc.c
+++ b/drivers/sbus/char/rtc.c
@@ -233,7 +233,7 @@
 	return 0;
 }
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.ioctl =	rtc_ioctl,
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index b30372f..45cf5bc 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -5,7 +5,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -224,7 +223,7 @@
 	return IRQ_HANDLED;
 }
 
-static struct file_operations uctrl_fops = {
+static const struct file_operations uctrl_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.ioctl =	uctrl_ioctl,
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 386e7de..8bfb67c 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -19,7 +19,6 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
@@ -44,7 +43,7 @@
 #include "vfc.h"
 #include <asm/vfc_ioctls.h>
 
-static struct file_operations vfc_fops;
+static const struct file_operations vfc_fops;
 struct vfc_dev **vfc_dev_lst;
 static char vfcstr[]="vfc";
 static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {
@@ -633,7 +632,7 @@
 }
 
 
-static struct file_operations vfc_fops = {
+static const struct file_operations vfc_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.ioctl =	vfc_ioctl,
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c
index ceec306..9efed77 100644
--- a/drivers/sbus/char/vfc_i2c.c
+++ b/drivers/sbus/char/vfc_i2c.c
@@ -14,7 +14,7 @@
 /* NOTE: It seems to me that the documentation regarding the
 pcd8584t/pcf8584 does not show the correct way to address the i2c bus.
 Based on the information on the I2C bus itself and the remainder of
-the Phillips docs the following algorithims apper to be correct.  I am
+the Phillips docs the following algorithms appear to be correct.  I am
 fairly certain that the flowcharts in the phillips docs are wrong. */
 
 
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index 98fcbb3..6349dd6 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/device.h>
 
 #include <asm/system.h>
 #include <asm/sbus.h>
@@ -17,13 +18,25 @@
 #include <asm/bpp.h>
 #include <asm/irq.h>
 
+static ssize_t
+show_sbusobppath_attr(struct device * dev, struct device_attribute * attr, char * buf)
+{
+	struct sbus_dev *sbus;
+
+	sbus = to_sbus_device(dev);
+
+	return snprintf (buf, PAGE_SIZE, "%s\n", sbus->ofdev.node->full_name);
+}
+
+static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_sbusobppath_attr, NULL);
+
 struct sbus_bus *sbus_root;
 
 static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev)
 {
 	unsigned long base;
 	void *pval;
-	int len;
+	int len, err;
 
 	sdev->prom_node = dp->node;
 	strcpy(sdev->prom_name, dp->name);
@@ -66,6 +79,9 @@
 	if (of_device_register(&sdev->ofdev) != 0)
 		printk(KERN_DEBUG "sbus: device registration error for %s!\n",
 		       dp->path_component_name);
+
+	/* WE HAVE BEEN INVADED BY ALIENS! */
+	err = sysfs_create_file(&sdev->ofdev.dev.kobj, &dev_attr_obppath.attr);
 }
 
 static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus)
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index b091a0f..eb766c3 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -197,7 +197,7 @@
 };
 
 /* File operations struct for character device */
-static struct file_operations twa_fops = {
+static const struct file_operations twa_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= twa_chrdev_ioctl,
 	.open		= twa_chrdev_open,
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index e1b44d6..bf5d63e 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1040,7 +1040,7 @@
 } /* End tw_chrdev_open() */
 
 /* File operations struct for character device */
-static struct file_operations tw_fops = {
+static const struct file_operations tw_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= tw_chrdev_ioctl,
 	.open		= tw_chrdev_open,
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 68103e5..cb02656 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -121,7 +121,6 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/blkdev.h>
@@ -667,12 +666,30 @@
 	__u8 min_xferp = (hostdata->chip710 ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP);
 
 	if(hostdata->chip710) {
-		__u8 burst_disable = hostdata->burst_disable
-			? BURST_DISABLE : 0;
+		__u8 burst_disable = 0;
+		__u8 burst_length = 0;
+
+		switch (hostdata->burst_length) {
+			case 1:
+			        burst_length = BURST_LENGTH_1;
+			        break;
+			case 2:
+			        burst_length = BURST_LENGTH_2;
+			        break;
+			case 4:
+			        burst_length = BURST_LENGTH_4;
+			        break;
+			case 8:
+			        burst_length = BURST_LENGTH_8;
+			        break;
+			default:
+			        burst_disable = BURST_DISABLE;
+			        break;
+		}
 		dcntl_extra = COMPAT_700_MODE;
 
 		NCR_700_writeb(dcntl_extra, host, DCNTL_REG);
-		NCR_700_writeb(BURST_LENGTH_8  | hostdata->dmode_extra,
+		NCR_700_writeb(burst_length | hostdata->dmode_extra,
 			       host, DMODE_710_REG);
 		NCR_700_writeb(burst_disable | (hostdata->differential ? 
 						DIFF : 0), host, CTEST7_REG);
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index f38822d..841e1bb 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -203,7 +203,7 @@
 	__u32	force_le_on_be:1;
 #endif
 	__u32	chip710:1;	/* set if really a 710 not 700 */
-	__u32	burst_disable:1;	/* set to 1 to disable 710 bursting */
+	__u32	burst_length:4;	/* set to 0 to disable 710 bursting */
 
 	/* NOTHING BELOW HERE NEEDS ALTERING */
 	__u32	fast:1;		/* if we can alter the SCSI bus clock
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
index 640536e..93b41f4 100644
--- a/drivers/scsi/53c7xx.c
+++ b/drivers/scsi/53c7xx.c
@@ -3099,7 +3099,6 @@
         real = get_zeroed_page(GFP_ATOMIC);
         if (real == 0)
         	return NULL;
-        memset((void *)real, 0, 4096);
         cache_push(virt_to_phys((void *)real), 4096);
         cache_clear(virt_to_phys((void *)real), 4096);
         kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER);
@@ -4400,7 +4399,7 @@
  * account the current synchronous offset) 
  */
 
-    sstat = (NCR53c8x0_read8 (SSTAT2_REG);
+    sstat = NCR53c8x0_read8 (SSTAT2_REG);
     offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
     phase = sstat & SSTAT2_PHASE_MASK;
 
@@ -5423,7 +5422,7 @@
     	    	     --buffers, offset += segment->length, ++segment)
 #if 0
 		    printk("scsi%d: comparing 0x%p to 0x%p\n", 
-			cmd->device->host->host_no, saved, page_address(segment->page+segment->offset);
+			cmd->device->host->host_no, saved, page_address(segment->page+segment->offset));
 #else
 		    ;
 #endif
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 3075204..e874b89 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -192,7 +192,7 @@
   BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter.
 */
 
-static boolean __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter)
 {
 	int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
 	void *BlockPointer;
@@ -238,7 +238,7 @@
   multiple host adapters share the same IRQ Channel.
 */
 
-static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, boolean SuccessMessageP)
+static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, bool SuccessMessageP)
 {
 	int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
 	int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
@@ -362,10 +362,8 @@
 	   interrupt could occur if the IRQ Channel was previously enabled by another
 	   BusLogic Host Adapter or another driver sharing the same IRQ Channel.
 	 */
-	if (!HostAdapter->IRQ_ChannelAcquired) {
+	if (!HostAdapter->IRQ_ChannelAcquired)
 		local_irq_save(ProcessorFlags);
-		local_irq_disable();
-	}
 	/*
 	   Wait for the Host Adapter Ready bit to be set and the Command/Parameter
 	   Register Busy bit to be reset in the Status Register.
@@ -639,9 +637,9 @@
 	struct BusLogic_ProbeInfo *PrimaryProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
 	int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
 	int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
-	boolean ForceBusDeviceScanningOrder = false;
-	boolean ForceBusDeviceScanningOrderChecked = false;
-	boolean StandardAddressSeen[6];
+	bool ForceBusDeviceScanningOrder = false;
+	bool ForceBusDeviceScanningOrderChecked = false;
+	bool StandardAddressSeen[6];
 	struct pci_dev *PCI_Device = NULL;
 	int i;
 	if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters)
@@ -1011,7 +1009,7 @@
   BusLogic_Failure prints a standardized error message, and then returns false.
 */
 
-static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage)
+static bool BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage)
 {
 	BusLogic_AnnounceDriver(HostAdapter);
 	if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) {
@@ -1030,7 +1028,7 @@
   BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
 */
 
-static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
 	union BusLogic_StatusRegister StatusRegister;
 	union BusLogic_InterruptRegister InterruptRegister;
@@ -1101,8 +1099,8 @@
   SCSI Bus Reset.
 */
 
-static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
-						 *HostAdapter, boolean HardReset)
+static bool BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
+						 *HostAdapter, bool HardReset)
 {
 	union BusLogic_StatusRegister StatusRegister;
 	int TimeoutCounter;
@@ -1205,11 +1203,11 @@
   Host Adapter.
 */
 
-static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
 	struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
 	unsigned char RequestedReplyLength;
-	boolean Result = true;
+	bool Result = true;
 	/*
 	   FlashPoint Host Adapters do not require this protection.
 	 */
@@ -1239,7 +1237,7 @@
   from Host Adapter and initializes the Host Adapter structure.
 */
 
-static boolean __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter
+static bool __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter
 							    *HostAdapter)
 {
 	struct BusLogic_BoardID BoardID;
@@ -1686,14 +1684,14 @@
   Host Adapter.
 */
 
-static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter
+static bool __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter
 							      *HostAdapter)
 {
 	unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
 	unsigned short SynchronousPermitted, FastPermitted;
 	unsigned short UltraPermitted, WidePermitted;
 	unsigned short DisconnectPermitted, TaggedQueuingPermitted;
-	boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth;
+	bool CommonSynchronousNegotiation, CommonTaggedQueueDepth;
 	char SynchronousString[BusLogic_MaxTargetDevices + 1];
 	char WideString[BusLogic_MaxTargetDevices + 1];
 	char DisconnectString[BusLogic_MaxTargetDevices + 1];
@@ -1835,7 +1833,7 @@
   Host Adapter.
 */
 
-static boolean __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter)
 {
 	if (HostAdapter->IRQ_Channel == 0) {
 		BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", HostAdapter);
@@ -1903,7 +1901,7 @@
   of the Host Adapter from its initial power on or hard reset state.
 */
 
-static boolean BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter
+static bool BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter
 					      *HostAdapter)
 {
 	struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest;
@@ -2002,7 +2000,7 @@
   through Host Adapter.
 */
 
-static boolean __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
+static bool __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
 						   *HostAdapter)
 {
 	u16 InstalledDevices;
@@ -2739,7 +2737,7 @@
   already have been acquired by the caller.
 */
 
-static boolean BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter
+static bool BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter
 					     *HostAdapter, enum BusLogic_ActionCode ActionCode, struct BusLogic_CCB *CCB)
 {
 	struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
@@ -3058,7 +3056,7 @@
   currently executing SCSI Commands as having been Reset.
 */
 
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, boolean HardReset)
+static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, bool HardReset)
 {
 	struct BusLogic_CCB *CCB;
 	int TargetID;
@@ -3309,7 +3307,7 @@
 static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Format, struct BusLogic_HostAdapter *HostAdapter, ...)
 {
 	static char Buffer[BusLogic_LineBufferSize];
-	static boolean BeginningOfLine = true;
+	static bool BeginningOfLine = true;
 	va_list Arguments;
 	int Length = 0;
 	va_start(Arguments, HostAdapter);
@@ -3347,7 +3345,7 @@
   and updates the pointer if the keyword is recognized and false otherwise.
 */
 
-static boolean __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
+static bool __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
 {
 	char *Pointer = *StringPointer;
 	while (*Keyword != '\0') {
diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
index cca6d45..bfbfb5c 100644
--- a/drivers/scsi/BusLogic.h
+++ b/drivers/scsi/BusLogic.h
@@ -234,12 +234,6 @@
 
 
 /*
-  Define a Boolean data type.
-*/
-
-typedef bool boolean;
-
-/*
   Define a 10^18 Statistics Byte Counter data type.
 */
 
@@ -269,19 +263,19 @@
 */
 
 struct BusLogic_ProbeOptions {
-	boolean NoProbe:1;	/* Bit 0 */
-	boolean NoProbeISA:1;	/* Bit 1 */
-	boolean NoProbePCI:1;	/* Bit 2 */
-	boolean NoSortPCI:1;	/* Bit 3 */
-	boolean MultiMasterFirst:1;	/* Bit 4 */
-	boolean FlashPointFirst:1;	/* Bit 5 */
-	boolean LimitedProbeISA:1;	/* Bit 6 */
-	boolean Probe330:1;	/* Bit 7 */
-	boolean Probe334:1;	/* Bit 8 */
-	boolean Probe230:1;	/* Bit 9 */
-	boolean Probe234:1;	/* Bit 10 */
-	boolean Probe130:1;	/* Bit 11 */
-	boolean Probe134:1;	/* Bit 12 */
+	bool NoProbe:1;		/* Bit 0 */
+	bool NoProbeISA:1;	/* Bit 1 */
+	bool NoProbePCI:1;	/* Bit 2 */
+	bool NoSortPCI:1;	/* Bit 3 */
+	bool MultiMasterFirst:1;/* Bit 4 */
+	bool FlashPointFirst:1;	/* Bit 5 */
+	bool LimitedProbeISA:1;	/* Bit 6 */
+	bool Probe330:1;	/* Bit 7 */
+	bool Probe334:1;	/* Bit 8 */
+	bool Probe230:1;	/* Bit 9 */
+	bool Probe234:1;	/* Bit 10 */
+	bool Probe130:1;	/* Bit 11 */
+	bool Probe134:1;	/* Bit 12 */
 };
 
 /*
@@ -289,10 +283,10 @@
 */
 
 struct BusLogic_GlobalOptions {
-	boolean TraceProbe:1;	/* Bit 0 */
-	boolean TraceHardwareReset:1;	/* Bit 1 */
-	boolean TraceConfiguration:1;	/* Bit 2 */
-	boolean TraceErrors:1;	/* Bit 3 */
+	bool TraceProbe:1;	/* Bit 0 */
+	bool TraceHardwareReset:1;	/* Bit 1 */
+	bool TraceConfiguration:1;	/* Bit 2 */
+	bool TraceErrors:1;	/* Bit 3 */
 };
 
 /*
@@ -300,7 +294,7 @@
 */
 
 struct BusLogic_LocalOptions {
-	boolean InhibitTargetInquiry:1;	/* Bit 0 */
+	bool InhibitTargetInquiry:1;	/* Bit 0 */
 };
 
 /*
@@ -322,10 +316,10 @@
 	unsigned char All;
 	struct {
 		unsigned char:4;	/* Bits 0-3 */
-		boolean SCSIBusReset:1;	/* Bit 4 */
-		boolean InterruptReset:1;	/* Bit 5 */
-		boolean SoftReset:1;	/* Bit 6 */
-		boolean HardReset:1;	/* Bit 7 */
+		bool SCSIBusReset:1;	/* Bit 4 */
+		bool InterruptReset:1;	/* Bit 5 */
+		bool SoftReset:1;	/* Bit 6 */
+		bool HardReset:1;	/* Bit 7 */
 	} cr;
 };
 
@@ -336,14 +330,14 @@
 union BusLogic_StatusRegister {
 	unsigned char All;
 	struct {
-		boolean CommandInvalid:1;	/* Bit 0 */
-		boolean Reserved:1;	/* Bit 1 */
-		boolean DataInRegisterReady:1;	/* Bit 2 */
-		boolean CommandParameterRegisterBusy:1;	/* Bit 3 */
-		boolean HostAdapterReady:1;	/* Bit 4 */
-		boolean InitializationRequired:1;	/* Bit 5 */
-		boolean DiagnosticFailure:1;	/* Bit 6 */
-		boolean DiagnosticActive:1;	/* Bit 7 */
+		bool CommandInvalid:1;		/* Bit 0 */
+		bool Reserved:1;		/* Bit 1 */
+		bool DataInRegisterReady:1;	/* Bit 2 */
+		bool CommandParameterRegisterBusy:1;	/* Bit 3 */
+		bool HostAdapterReady:1;	/* Bit 4 */
+		bool InitializationRequired:1;	/* Bit 5 */
+		bool DiagnosticFailure:1;	/* Bit 6 */
+		bool DiagnosticActive:1;	/* Bit 7 */
 	} sr;
 };
 
@@ -354,12 +348,12 @@
 union BusLogic_InterruptRegister {
 	unsigned char All;
 	struct {
-		boolean IncomingMailboxLoaded:1;	/* Bit 0 */
-		boolean OutgoingMailboxAvailable:1;	/* Bit 1 */
-		boolean CommandComplete:1;	/* Bit 2 */
-		boolean ExternalBusReset:1;	/* Bit 3 */
+		bool IncomingMailboxLoaded:1;	/* Bit 0 */
+		bool OutgoingMailboxAvailable:1;/* Bit 1 */
+		bool CommandComplete:1;		/* Bit 2 */
+		bool ExternalBusReset:1;	/* Bit 3 */
 		unsigned char Reserved:3;	/* Bits 4-6 */
-		boolean InterruptValid:1;	/* Bit 7 */
+		bool InterruptValid:1;		/* Bit 7 */
 	} ir;
 };
 
@@ -373,7 +367,7 @@
 		enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2;	/* Bits 0-1 */
 		enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2;	/* Bits 2-3 */
 		unsigned char:3;	/* Bits 4-6 */
-		boolean ExtendedTranslationEnabled:1;	/* Bit 7 */
+		bool ExtendedTranslationEnabled:1;	/* Bit 7 */
 	} gr;
 };
 
@@ -445,16 +439,16 @@
 
 struct BusLogic_Configuration {
 	unsigned char:5;	/* Byte 0 Bits 0-4 */
-	boolean DMA_Channel5:1;	/* Byte 0 Bit 5 */
-	boolean DMA_Channel6:1;	/* Byte 0 Bit 6 */
-	boolean DMA_Channel7:1;	/* Byte 0 Bit 7 */
-	boolean IRQ_Channel9:1;	/* Byte 1 Bit 0 */
-	boolean IRQ_Channel10:1;	/* Byte 1 Bit 1 */
-	boolean IRQ_Channel11:1;	/* Byte 1 Bit 2 */
-	boolean IRQ_Channel12:1;	/* Byte 1 Bit 3 */
+	bool DMA_Channel5:1;	/* Byte 0 Bit 5 */
+	bool DMA_Channel6:1;	/* Byte 0 Bit 6 */
+	bool DMA_Channel7:1;	/* Byte 0 Bit 7 */
+	bool IRQ_Channel9:1;	/* Byte 1 Bit 0 */
+	bool IRQ_Channel10:1;	/* Byte 1 Bit 1 */
+	bool IRQ_Channel11:1;	/* Byte 1 Bit 2 */
+	bool IRQ_Channel12:1;	/* Byte 1 Bit 3 */
 	unsigned char:1;	/* Byte 1 Bit 4 */
-	boolean IRQ_Channel14:1;	/* Byte 1 Bit 5 */
-	boolean IRQ_Channel15:1;	/* Byte 1 Bit 6 */
+	bool IRQ_Channel14:1;	/* Byte 1 Bit 5 */
+	bool IRQ_Channel15:1;	/* Byte 1 Bit 6 */
 	unsigned char:1;	/* Byte 1 Bit 7 */
 	unsigned char HostAdapterID:4;	/* Byte 2 Bits 0-3 */
 	unsigned char:4;	/* Byte 2 Bits 4-7 */
@@ -467,12 +461,12 @@
 struct BusLogic_SynchronousValue {
 	unsigned char Offset:4;	/* Bits 0-3 */
 	unsigned char TransferPeriod:3;	/* Bits 4-6 */
-	boolean Synchronous:1;	/* Bit 7 */
+	bool Synchronous:1;	/* Bit 7 */
 };
 
 struct BusLogic_SetupInformation {
-	boolean SynchronousInitiationEnabled:1;	/* Byte 0 Bit 0 */
-	boolean ParityCheckingEnabled:1;	/* Byte 0 Bit 1 */
+	bool SynchronousInitiationEnabled:1;	/* Byte 0 Bit 0 */
+	bool ParityCheckingEnabled:1;		/* Byte 0 Bit 1 */
 	unsigned char:6;	/* Byte 0 Bits 2-7 */
 	unsigned char BusTransferRate;	/* Byte 1 */
 	unsigned char PreemptTimeOnBus;	/* Byte 2 */
@@ -523,13 +517,13 @@
 struct BusLogic_PCIHostAdapterInformation {
 	enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort;	/* Byte 0 */
 	unsigned char PCIAssignedIRQChannel;	/* Byte 1 */
-	boolean LowByteTerminated:1;	/* Byte 2 Bit 0 */
-	boolean HighByteTerminated:1;	/* Byte 2 Bit 1 */
+	bool LowByteTerminated:1;	/* Byte 2 Bit 0 */
+	bool HighByteTerminated:1;	/* Byte 2 Bit 1 */
 	unsigned char:2;	/* Byte 2 Bits 2-3 */
-	boolean JP1:1;		/* Byte 2 Bit 4 */
-	boolean JP2:1;		/* Byte 2 Bit 5 */
-	boolean JP3:1;		/* Byte 2 Bit 6 */
-	boolean GenericInfoValid:1;	/* Byte 2 Bit 7 */
+	bool JP1:1;		/* Byte 2 Bit 4 */
+	bool JP2:1;		/* Byte 2 Bit 5 */
+	bool JP3:1;		/* Byte 2 Bit 6 */
+	bool GenericInfoValid:1;/* Byte 2 Bit 7 */
 	unsigned char:8;	/* Byte 3 */
 };
 
@@ -545,17 +539,17 @@
 	u32 BaseMailboxAddress;	/* Bytes 5-8 */
 	struct {
 		unsigned char:2;	/* Byte 9 Bits 0-1 */
-		boolean FastOnEISA:1;	/* Byte 9 Bit 2 */
+		bool FastOnEISA:1;	/* Byte 9 Bit 2 */
 		unsigned char:3;	/* Byte 9 Bits 3-5 */
-		boolean LevelSensitiveInterrupt:1;	/* Byte 9 Bit 6 */
+		bool LevelSensitiveInterrupt:1;	/* Byte 9 Bit 6 */
 		unsigned char:1;	/* Byte 9 Bit 7 */
 	} Misc;
 	unsigned char FirmwareRevision[3];	/* Bytes 10-12 */
-	boolean HostWideSCSI:1;	/* Byte 13 Bit 0 */
-	boolean HostDifferentialSCSI:1;	/* Byte 13 Bit 1 */
-	boolean HostSupportsSCAM:1;	/* Byte 13 Bit 2 */
-	boolean HostUltraSCSI:1;	/* Byte 13 Bit 3 */
-	boolean HostSmartTermination:1;	/* Byte 13 Bit 4 */
+	bool HostWideSCSI:1;		/* Byte 13 Bit 0 */
+	bool HostDifferentialSCSI:1;	/* Byte 13 Bit 1 */
+	bool HostSupportsSCAM:1;	/* Byte 13 Bit 2 */
+	bool HostUltraSCSI:1;		/* Byte 13 Bit 3 */
+	bool HostSmartTermination:1;	/* Byte 13 Bit 4 */
 	unsigned char:3;	/* Byte 13 Bits 5-7 */
 } PACKED;
 
@@ -590,35 +584,35 @@
 	unsigned char InformationByteCount;	/* Byte 2 */
 	unsigned char HostAdapterType[6];	/* Bytes 3-8 */
 	unsigned char:8;	/* Byte 9 */
-	boolean FloppyEnabled:1;	/* Byte 10 Bit 0 */
-	boolean FloppySecondary:1;	/* Byte 10 Bit 1 */
-	boolean LevelSensitiveInterrupt:1;	/* Byte 10 Bit 2 */
+	bool FloppyEnabled:1;		/* Byte 10 Bit 0 */
+	bool FloppySecondary:1;		/* Byte 10 Bit 1 */
+	bool LevelSensitiveInterrupt:1;	/* Byte 10 Bit 2 */
 	unsigned char:2;	/* Byte 10 Bits 3-4 */
 	unsigned char SystemRAMAreaForBIOS:3;	/* Byte 10 Bits 5-7 */
 	unsigned char DMA_Channel:7;	/* Byte 11 Bits 0-6 */
-	boolean DMA_AutoConfiguration:1;	/* Byte 11 Bit 7 */
+	bool DMA_AutoConfiguration:1;	/* Byte 11 Bit 7 */
 	unsigned char IRQ_Channel:7;	/* Byte 12 Bits 0-6 */
-	boolean IRQ_AutoConfiguration:1;	/* Byte 12 Bit 7 */
+	bool IRQ_AutoConfiguration:1;	/* Byte 12 Bit 7 */
 	unsigned char DMA_TransferRate;	/* Byte 13 */
 	unsigned char SCSI_ID;	/* Byte 14 */
-	boolean LowByteTerminated:1;	/* Byte 15 Bit 0 */
-	boolean ParityCheckingEnabled:1;	/* Byte 15 Bit 1 */
-	boolean HighByteTerminated:1;	/* Byte 15 Bit 2 */
-	boolean NoisyCablingEnvironment:1;	/* Byte 15 Bit 3 */
-	boolean FastSynchronousNegotiation:1;	/* Byte 15 Bit 4 */
-	boolean BusResetEnabled:1;	/* Byte 15 Bit 5 */
-	 boolean:1;		/* Byte 15 Bit 6 */
-	boolean ActiveNegationEnabled:1;	/* Byte 15 Bit 7 */
+	bool LowByteTerminated:1;	/* Byte 15 Bit 0 */
+	bool ParityCheckingEnabled:1;	/* Byte 15 Bit 1 */
+	bool HighByteTerminated:1;	/* Byte 15 Bit 2 */
+	bool NoisyCablingEnvironment:1;	/* Byte 15 Bit 3 */
+	bool FastSynchronousNegotiation:1;	/* Byte 15 Bit 4 */
+	bool BusResetEnabled:1;		/* Byte 15 Bit 5 */
+	 bool:1;		/* Byte 15 Bit 6 */
+	bool ActiveNegationEnabled:1;	/* Byte 15 Bit 7 */
 	unsigned char BusOnDelay;	/* Byte 16 */
 	unsigned char BusOffDelay;	/* Byte 17 */
-	boolean HostAdapterBIOSEnabled:1;	/* Byte 18 Bit 0 */
-	boolean BIOSRedirectionOfINT19Enabled:1;	/* Byte 18 Bit 1 */
-	boolean ExtendedTranslationEnabled:1;	/* Byte 18 Bit 2 */
-	boolean MapRemovableAsFixedEnabled:1;	/* Byte 18 Bit 3 */
-	 boolean:1;		/* Byte 18 Bit 4 */
-	boolean BIOSSupportsMoreThan2DrivesEnabled:1;	/* Byte 18 Bit 5 */
-	boolean BIOSInterruptModeEnabled:1;	/* Byte 18 Bit 6 */
-	boolean FlopticalSupportEnabled:1;	/* Byte 19 Bit 7 */
+	bool HostAdapterBIOSEnabled:1;		/* Byte 18 Bit 0 */
+	bool BIOSRedirectionOfINT19Enabled:1;	/* Byte 18 Bit 1 */
+	bool ExtendedTranslationEnabled:1;	/* Byte 18 Bit 2 */
+	bool MapRemovableAsFixedEnabled:1;	/* Byte 18 Bit 3 */
+	 bool:1;		/* Byte 18 Bit 4 */
+	bool BIOSSupportsMoreThan2DrivesEnabled:1;	/* Byte 18 Bit 5 */
+	bool BIOSInterruptModeEnabled:1;	/* Byte 18 Bit 6 */
+	bool FlopticalSupportEnabled:1;		/* Byte 19 Bit 7 */
 	unsigned short DeviceEnabled;	/* Bytes 19-20 */
 	unsigned short WidePermitted;	/* Bytes 21-22 */
 	unsigned short FastPermitted;	/* Bytes 23-24 */
@@ -628,22 +622,22 @@
 	unsigned short IgnoreInBIOSScan;	/* Bytes 31-32 */
 	unsigned char PCIInterruptPin:2;	/* Byte 33 Bits 0-1 */
 	unsigned char HostAdapterIOPortAddress:2;	/* Byte 33 Bits 2-3 */
-	boolean StrictRoundRobinModeEnabled:1;	/* Byte 33 Bit 4 */
-	boolean VESABusSpeedGreaterThan33MHz:1;	/* Byte 33 Bit 5 */
-	boolean VESABurstWriteEnabled:1;	/* Byte 33 Bit 6 */
-	boolean VESABurstReadEnabled:1;	/* Byte 33 Bit 7 */
+	bool StrictRoundRobinModeEnabled:1;	/* Byte 33 Bit 4 */
+	bool VESABusSpeedGreaterThan33MHz:1;	/* Byte 33 Bit 5 */
+	bool VESABurstWriteEnabled:1;	/* Byte 33 Bit 6 */
+	bool VESABurstReadEnabled:1;	/* Byte 33 Bit 7 */
 	unsigned short UltraPermitted;	/* Bytes 34-35 */
 	unsigned int:32;	/* Bytes 36-39 */
 	unsigned char:8;	/* Byte 40 */
 	unsigned char AutoSCSIMaximumLUN;	/* Byte 41 */
-	 boolean:1;		/* Byte 42 Bit 0 */
-	boolean SCAM_Dominant:1;	/* Byte 42 Bit 1 */
-	boolean SCAM_Enabled:1;	/* Byte 42 Bit 2 */
-	boolean SCAM_Level2:1;	/* Byte 42 Bit 3 */
+	 bool:1;		/* Byte 42 Bit 0 */
+	bool SCAM_Dominant:1;	/* Byte 42 Bit 1 */
+	bool SCAM_Enabled:1;	/* Byte 42 Bit 2 */
+	bool SCAM_Level2:1;	/* Byte 42 Bit 3 */
 	unsigned char:4;	/* Byte 42 Bits 4-7 */
-	boolean INT13ExtensionEnabled:1;	/* Byte 43 Bit 0 */
-	 boolean:1;		/* Byte 43 Bit 1 */
-	boolean CDROMBootEnabled:1;	/* Byte 43 Bit 2 */
+	bool INT13ExtensionEnabled:1;	/* Byte 43 Bit 0 */
+	 bool:1;		/* Byte 43 Bit 1 */
+	bool CDROMBootEnabled:1;	/* Byte 43 Bit 2 */
 	unsigned char:5;	/* Byte 43 Bits 3-7 */
 	unsigned char BootTargetID:4;	/* Byte 44 Bits 0-3 */
 	unsigned char BootChannel:4;	/* Byte 44 Bits 4-7 */
@@ -852,7 +846,7 @@
 	enum BusLogic_CCB_Opcode Opcode;	/* Byte 0 */
 	unsigned char:3;	/* Byte 1 Bits 0-2 */
 	enum BusLogic_DataDirection DataDirection:2;	/* Byte 1 Bits 3-4 */
-	boolean TagEnable:1;	/* Byte 1 Bit 5 */
+	bool TagEnable:1;	/* Byte 1 Bit 5 */
 	enum BusLogic_QueueTag QueueTag:2;	/* Byte 1 Bits 6-7 */
 	unsigned char CDB_Length;	/* Byte 2 */
 	unsigned char SenseDataLength;	/* Byte 3 */
@@ -864,7 +858,7 @@
 	enum BusLogic_TargetDeviceStatus TargetDeviceStatus;	/* Byte 15 */
 	unsigned char TargetID;	/* Byte 16 */
 	unsigned char LogicalUnit:5;	/* Byte 17 Bits 0-4 */
-	boolean LegacyTagEnable:1;	/* Byte 17 Bit 5 */
+	bool LegacyTagEnable:1;	/* Byte 17 Bit 5 */
 	enum BusLogic_QueueTag LegacyQueueTag:2;	/* Byte 17 Bits 6-7 */
 	SCSI_CDB_T CDB;		/* Bytes 18-29 */
 	unsigned char:8;	/* Byte 30 */
@@ -939,13 +933,13 @@
 */
 
 struct BusLogic_TargetFlags {
-	boolean TargetExists:1;
-	boolean TaggedQueuingSupported:1;
-	boolean WideTransfersSupported:1;
-	boolean TaggedQueuingActive:1;
-	boolean WideTransfersActive:1;
-	boolean CommandSuccessfulFlag:1;
-	boolean TargetInfoReported:1;
+	bool TargetExists:1;
+	bool TaggedQueuingSupported:1;
+	bool WideTransfersSupported:1;
+	bool TaggedQueuingActive:1;
+	bool WideTransfersActive:1;
+	bool CommandSuccessfulFlag:1;
+	bool TargetInfoReported:1;
 };
 
 /*
@@ -992,7 +986,7 @@
 
 struct FlashPoint_Info {
 	u32 BaseAddress;	/* Bytes 0-3 */
-	boolean Present;	/* Byte 4 */
+	bool Present;		/* Byte 4 */
 	unsigned char IRQ_Channel;	/* Byte 5 */
 	unsigned char SCSI_ID;	/* Byte 6 */
 	unsigned char SCSI_LUN;	/* Byte 7 */
@@ -1002,15 +996,15 @@
 	unsigned short UltraPermitted;	/* Bytes 14-15 */
 	unsigned short DisconnectPermitted;	/* Bytes 16-17 */
 	unsigned short WidePermitted;	/* Bytes 18-19 */
-	boolean ParityCheckingEnabled:1;	/* Byte 20 Bit 0 */
-	boolean HostWideSCSI:1;	/* Byte 20 Bit 1 */
-	boolean HostSoftReset:1;	/* Byte 20 Bit 2 */
-	boolean ExtendedTranslationEnabled:1;	/* Byte 20 Bit 3 */
-	boolean LowByteTerminated:1;	/* Byte 20 Bit 4 */
-	boolean HighByteTerminated:1;	/* Byte 20 Bit 5 */
-	boolean ReportDataUnderrun:1;	/* Byte 20 Bit 6 */
-	boolean SCAM_Enabled:1;	/* Byte 20 Bit 7 */
-	boolean SCAM_Level2:1;	/* Byte 21 Bit 0 */
+	bool ParityCheckingEnabled:1;	/* Byte 20 Bit 0 */
+	bool HostWideSCSI:1;		/* Byte 20 Bit 1 */
+	bool HostSoftReset:1;		/* Byte 20 Bit 2 */
+	bool ExtendedTranslationEnabled:1;	/* Byte 20 Bit 3 */
+	bool LowByteTerminated:1;	/* Byte 20 Bit 4 */
+	bool HighByteTerminated:1;	/* Byte 20 Bit 5 */
+	bool ReportDataUnderrun:1;	/* Byte 20 Bit 6 */
+	bool SCAM_Enabled:1;	/* Byte 20 Bit 7 */
+	bool SCAM_Level2:1;	/* Byte 21 Bit 0 */
 	unsigned char:7;	/* Byte 21 Bits 1-7 */
 	unsigned char Family;	/* Byte 22 */
 	unsigned char BusType;	/* Byte 23 */
@@ -1044,29 +1038,29 @@
 	unsigned char IRQ_Channel;
 	unsigned char DMA_Channel;
 	unsigned char SCSI_ID;
-	boolean IRQ_ChannelAcquired:1;
-	boolean DMA_ChannelAcquired:1;
-	boolean ExtendedTranslationEnabled:1;
-	boolean ParityCheckingEnabled:1;
-	boolean BusResetEnabled:1;
-	boolean LevelSensitiveInterrupt:1;
-	boolean HostWideSCSI:1;
-	boolean HostDifferentialSCSI:1;
-	boolean HostSupportsSCAM:1;
-	boolean HostUltraSCSI:1;
-	boolean ExtendedLUNSupport:1;
-	boolean TerminationInfoValid:1;
-	boolean LowByteTerminated:1;
-	boolean HighByteTerminated:1;
-	boolean BounceBuffersRequired:1;
-	boolean StrictRoundRobinModeSupport:1;
-	boolean SCAM_Enabled:1;
-	boolean SCAM_Level2:1;
-	boolean HostAdapterInitialized:1;
-	boolean HostAdapterExternalReset:1;
-	boolean HostAdapterInternalError:1;
-	boolean ProcessCompletedCCBsActive;
-	volatile boolean HostAdapterCommandCompleted;
+	bool IRQ_ChannelAcquired:1;
+	bool DMA_ChannelAcquired:1;
+	bool ExtendedTranslationEnabled:1;
+	bool ParityCheckingEnabled:1;
+	bool BusResetEnabled:1;
+	bool LevelSensitiveInterrupt:1;
+	bool HostWideSCSI:1;
+	bool HostDifferentialSCSI:1;
+	bool HostSupportsSCAM:1;
+	bool HostUltraSCSI:1;
+	bool ExtendedLUNSupport:1;
+	bool TerminationInfoValid:1;
+	bool LowByteTerminated:1;
+	bool HighByteTerminated:1;
+	bool BounceBuffersRequired:1;
+	bool StrictRoundRobinModeSupport:1;
+	bool SCAM_Enabled:1;
+	bool SCAM_Level2:1;
+	bool HostAdapterInitialized:1;
+	bool HostAdapterExternalReset:1;
+	bool HostAdapterInternalError:1;
+	bool ProcessCompletedCCBsActive;
+	volatile bool HostAdapterCommandCompleted;
 	unsigned short HostAdapterScatterGatherLimit;
 	unsigned short DriverScatterGatherLimit;
 	unsigned short MaxTargetDevices;
@@ -1141,25 +1135,25 @@
 	unsigned char PeripheralDeviceType:5;	/* Byte 0 Bits 0-4 */
 	unsigned char PeripheralQualifier:3;	/* Byte 0 Bits 5-7 */
 	unsigned char DeviceTypeModifier:7;	/* Byte 1 Bits 0-6 */
-	boolean RMB:1;		/* Byte 1 Bit 7 */
+	bool RMB:1;		/* Byte 1 Bit 7 */
 	unsigned char ANSI_ApprovedVersion:3;	/* Byte 2 Bits 0-2 */
 	unsigned char ECMA_Version:3;	/* Byte 2 Bits 3-5 */
 	unsigned char ISO_Version:2;	/* Byte 2 Bits 6-7 */
 	unsigned char ResponseDataFormat:4;	/* Byte 3 Bits 0-3 */
 	unsigned char:2;	/* Byte 3 Bits 4-5 */
-	boolean TrmIOP:1;	/* Byte 3 Bit 6 */
-	boolean AENC:1;		/* Byte 3 Bit 7 */
+	bool TrmIOP:1;		/* Byte 3 Bit 6 */
+	bool AENC:1;		/* Byte 3 Bit 7 */
 	unsigned char AdditionalLength;	/* Byte 4 */
 	unsigned char:8;	/* Byte 5 */
 	unsigned char:8;	/* Byte 6 */
-	boolean SftRe:1;	/* Byte 7 Bit 0 */
-	boolean CmdQue:1;	/* Byte 7 Bit 1 */
-	 boolean:1;		/* Byte 7 Bit 2 */
-	boolean Linked:1;	/* Byte 7 Bit 3 */
-	boolean Sync:1;		/* Byte 7 Bit 4 */
-	boolean WBus16:1;	/* Byte 7 Bit 5 */
-	boolean WBus32:1;	/* Byte 7 Bit 6 */
-	boolean RelAdr:1;	/* Byte 7 Bit 7 */
+	bool SftRe:1;		/* Byte 7 Bit 0 */
+	bool CmdQue:1;		/* Byte 7 Bit 1 */
+	 bool:1;		/* Byte 7 Bit 2 */
+	bool Linked:1;		/* Byte 7 Bit 3 */
+	bool Sync:1;		/* Byte 7 Bit 4 */
+	bool WBus16:1;		/* Byte 7 Bit 5 */
+	bool WBus32:1;		/* Byte 7 Bit 6 */
+	bool RelAdr:1;		/* Byte 7 Bit 7 */
 	unsigned char VendorIdentification[8];	/* Bytes 8-15 */
 	unsigned char ProductIdentification[16];	/* Bytes 16-31 */
 	unsigned char ProductRevisionLevel[4];	/* Bytes 32-35 */
@@ -1348,7 +1342,7 @@
 static int BusLogic_SlaveConfigure(struct scsi_device *);
 static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *);
 static irqreturn_t BusLogic_InterruptHandler(int, void *);
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, boolean HardReset);
+static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, bool HardReset);
 static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...);
 static int __init BusLogic_Setup(char *);
 
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
index 7c00680..a7f916c 100644
--- a/drivers/scsi/FlashPoint.c
+++ b/drivers/scsi/FlashPoint.c
@@ -7609,7 +7609,7 @@
 	FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
 }
 
-static inline boolean
+static inline bool
 FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
 {
 	return FlashPoint_InterruptPending(CardHandle);
@@ -7640,7 +7640,7 @@
 FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *);
 extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
 extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
-extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
+extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
 extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
 extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
 
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 7869c34..4cd280e 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -230,6 +230,7 @@
 	  The SCSI subsystem can probe for devices while the rest of the
 	  system continues booting, and even probe devices on different
 	  busses in parallel, leading to a significant speed-up.
+
 	  If you have built SCSI as modules, enabling this option can
 	  be a problem as the devices may not have been found by the
 	  time your system expects them to have been.  You can load the
@@ -237,8 +238,8 @@
 	  If you build your SCSI drivers into the kernel, then everything
 	  will work fine if you say Y here.
 
-	  You can override this choice by specifying scsi_mod.scan="sync"
-	  or "async" on the kernel's command line.
+	  You can override this choice by specifying "scsi_mod.scan=sync"
+	  or async on the kernel's command line.
 
 menu "SCSI Transports"
 	depends on SCSI
@@ -973,6 +974,15 @@
 	  many PA-RISC workstations & servers.  If you do not know whether you
 	  have a Lasi chip, it is safe to say "Y" here.
 
+config SCSI_SNI_53C710
+	tristate "SNI RM SCSI support for 53c710"
+	depends on SNI_RM && SCSI
+	select SCSI_SPI_ATTRS
+	select 53C700_LE_ON_BE
+	help
+	  This is a driver for the onboard SCSI controller found in older
+	  SNI RM workstations & servers.
+
 config 53C700_LE_ON_BE
 	bool
 	depends on SCSI_LASI700
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index bd7c988..79ecf4e 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -124,6 +124,7 @@
 obj-$(CONFIG_SUN3X_ESP)		+= NCR53C9x.o	sun3x_esp.o
 obj-$(CONFIG_SCSI_FCAL)		+= fcal.o
 obj-$(CONFIG_SCSI_LASI700)	+= 53c700.o lasi700.o
+obj-$(CONFIG_SCSI_SNI_53C710)	+= 53c700.o sni_53c710.o
 obj-$(CONFIG_SCSI_NSP32)	+= nsp32.o
 obj-$(CONFIG_SCSI_IPR)		+= ipr.o
 obj-$(CONFIG_SCSI_SRP)		+= libsrp.o
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index 3c912ee..8b5334c 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -528,12 +528,16 @@
 /* Allocate structure and insert basic data such as SCSI chip frequency
  * data and a pointer to the device
  */
-struct NCR_ESP* esp_allocate(struct scsi_host_template *tpnt, void *esp_dev)
+struct NCR_ESP* esp_allocate(struct scsi_host_template *tpnt, void *esp_dev,
+			     int hotplug)
 {
 	struct NCR_ESP *esp, *elink;
 	struct Scsi_Host *esp_host;
 
-	esp_host = scsi_register(tpnt, sizeof(struct NCR_ESP));
+	if (hotplug)
+		esp_host = scsi_host_alloc(tpnt, sizeof(struct NCR_ESP));
+	else
+		esp_host = scsi_register(tpnt, sizeof(struct NCR_ESP));
 	if(!esp_host)
 		panic("Cannot register ESP SCSI host");
 	esp = (struct NCR_ESP *) esp_host->hostdata;
diff --git a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h
index 521e3f8..d85cb73 100644
--- a/drivers/scsi/NCR53C9x.h
+++ b/drivers/scsi/NCR53C9x.h
@@ -652,7 +652,7 @@
 
 /* External functions */
 extern void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs);
-extern struct NCR_ESP *esp_allocate(struct scsi_host_template *, void *);
+extern struct NCR_ESP *esp_allocate(struct scsi_host_template *, void *, int);
 extern void esp_deallocate(struct NCR_ESP *);
 extern void esp_release(void);
 extern void esp_initialize(struct NCR_ESP *);
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 8578555..7c0b17f 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -41,7 +41,6 @@
 
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
index 9859cd1..f12864a 100644
--- a/drivers/scsi/NCR_D700.c
+++ b/drivers/scsi/NCR_D700.c
@@ -200,6 +200,7 @@
 	hostdata->base = ioport_map(region, 64);
 	hostdata->differential = (((1<<siop) & differential) != 0);
 	hostdata->clock = NCR_D700_CLOCK_MHZ;
+	hostdata->burst_length = 8;
 
 	/* and register the siop */
 	host = NCR_700_detect(&NCR_D700_driver_template, hostdata, p->dev);
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 2650a5d..7f4241b 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -1067,7 +1067,7 @@
 		goto out_disable_device;
 	}
 
-	/* <02> read from base address + 0x50 offset to get the bios balue. */
+	/* <02> read from base address + 0x50 offset to get the bios value. */
 	bios = ORC_RDWORD(port, 0x50);
 
 
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index f77016d..b7c5385 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -1,7 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index 1299bc8..796f1c4 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -1,7 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
diff --git a/drivers/scsi/aacraid/Makefile b/drivers/scsi/aacraid/Makefile
index 28d133a..f1cca4e 100644
--- a/drivers/scsi/aacraid/Makefile
+++ b/drivers/scsi/aacraid/Makefile
@@ -3,6 +3,6 @@
 obj-$(CONFIG_SCSI_AACRAID) := aacraid.o
 
 aacraid-objs	:= linit.o aachba.o commctrl.o comminit.o commsup.o \
-		   dpcsup.o rx.o sa.o rkt.o
+		   dpcsup.o rx.o sa.o rkt.o nark.o
 
 EXTRA_CFLAGS	:= -Idrivers/scsi
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 426cd6f..d789e61 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -26,7 +26,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -170,9 +169,9 @@
 module_param(acbsize, int, S_IRUGO|S_IWUSR);
 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.");
 
-int expose_physicals = 0;
+int expose_physicals = -1;
 module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. 0=off, 1=on");
+MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
 /**
  *	aac_get_config_status	-	check the adapter configuration
  *	@common: adapter to query
@@ -706,6 +705,309 @@
 	}
 }
 
+static int aac_bounds_32(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
+{
+	if (lba & 0xffffffff00000000LL) {
+		int cid = scmd_id(cmd);
+		dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
+		cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
+			SAM_STAT_CHECK_CONDITION;
+		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
+			    HARDWARE_ERROR,
+			    SENCODE_INTERNAL_TARGET_FAILURE,
+			    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
+			    0, 0);
+		memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+		  (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(cmd->sense_buffer))
+		    ? sizeof(cmd->sense_buffer)
+		    : sizeof(dev->fsa_dev[cid].sense_data));
+		cmd->scsi_done(cmd);
+		return 1;
+	}
+	return 0;
+}
+
+static int aac_bounds_64(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
+{
+	return 0;
+}
+
+static void io_callback(void *context, struct fib * fibptr);
+
+static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_raw_io *readcmd;
+	aac_fib_init(fib);
+	readcmd = (struct aac_raw_io *) fib_data(fib);
+	readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
+	readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+	readcmd->count = cpu_to_le32(count<<9);
+	readcmd->cid = cpu_to_le16(scmd_id(cmd));
+	readcmd->flags = cpu_to_le16(1);
+	readcmd->bpTotal = 0;
+	readcmd->bpComplete = 0;
+
+	aac_build_sgraw(cmd, &readcmd->sg);
+	fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
+	BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerRawIo,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_read64 *readcmd;
+	aac_fib_init(fib);
+	readcmd = (struct aac_read64 *) fib_data(fib);
+	readcmd->command = cpu_to_le32(VM_CtHostRead64);
+	readcmd->cid = cpu_to_le16(scmd_id(cmd));
+	readcmd->sector_count = cpu_to_le16(count);
+	readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
+	readcmd->pad   = 0;
+	readcmd->flags = 0;
+
+	aac_build_sg64(cmd, &readcmd->sg);
+	fibsize = sizeof(struct aac_read64) +
+		((le32_to_cpu(readcmd->sg.count) - 1) *
+		 sizeof (struct sgentry64));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerCommand64,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_read *readcmd;
+	aac_fib_init(fib);
+	readcmd = (struct aac_read *) fib_data(fib);
+	readcmd->command = cpu_to_le32(VM_CtBlockRead);
+	readcmd->cid = cpu_to_le16(scmd_id(cmd));
+	readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
+	readcmd->count = cpu_to_le32(count * 512);
+
+	aac_build_sg(cmd, &readcmd->sg);
+	fibsize = sizeof(struct aac_read) +
+			((le32_to_cpu(readcmd->sg.count) - 1) *
+			 sizeof (struct sgentry));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerCommand,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_raw_io *writecmd;
+	aac_fib_init(fib);
+	writecmd = (struct aac_raw_io *) fib_data(fib);
+	writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
+	writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+	writecmd->count = cpu_to_le32(count<<9);
+	writecmd->cid = cpu_to_le16(scmd_id(cmd));
+	writecmd->flags = 0;
+	writecmd->bpTotal = 0;
+	writecmd->bpComplete = 0;
+
+	aac_build_sgraw(cmd, &writecmd->sg);
+	fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
+	BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerRawIo,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_write64 *writecmd;
+	aac_fib_init(fib);
+	writecmd = (struct aac_write64 *) fib_data(fib);
+	writecmd->command = cpu_to_le32(VM_CtHostWrite64);
+	writecmd->cid = cpu_to_le16(scmd_id(cmd));
+	writecmd->sector_count = cpu_to_le16(count);
+	writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
+	writecmd->pad	= 0;
+	writecmd->flags	= 0;
+
+	aac_build_sg64(cmd, &writecmd->sg);
+	fibsize = sizeof(struct aac_write64) +
+		((le32_to_cpu(writecmd->sg.count) - 1) *
+		 sizeof (struct sgentry64));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerCommand64,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_write *writecmd;
+	aac_fib_init(fib);
+	writecmd = (struct aac_write *) fib_data(fib);
+	writecmd->command = cpu_to_le32(VM_CtBlockWrite);
+	writecmd->cid = cpu_to_le16(scmd_id(cmd));
+	writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
+	writecmd->count = cpu_to_le32(count * 512);
+	writecmd->sg.count = cpu_to_le32(1);
+	/* ->stable is not used - it did mean which type of write */
+
+	aac_build_sg(cmd, &writecmd->sg);
+	fibsize = sizeof(struct aac_write) +
+		((le32_to_cpu(writecmd->sg.count) - 1) *
+		 sizeof (struct sgentry));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerCommand,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd)
+{
+	struct aac_srb * srbcmd;
+	u32 flag;
+	u32 timeout;
+
+	aac_fib_init(fib);
+	switch(cmd->sc_data_direction){
+	case DMA_TO_DEVICE:
+		flag = SRB_DataOut;
+		break;
+	case DMA_BIDIRECTIONAL:
+		flag = SRB_DataIn | SRB_DataOut;
+		break;
+	case DMA_FROM_DEVICE:
+		flag = SRB_DataIn;
+		break;
+	case DMA_NONE:
+	default:	/* shuts up some versions of gcc */
+		flag = SRB_NoDataXfer;
+		break;
+	}
+
+	srbcmd = (struct aac_srb*) fib_data(fib);
+	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
+	srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scmd_channel(cmd)));
+	srbcmd->id       = cpu_to_le32(scmd_id(cmd));
+	srbcmd->lun      = cpu_to_le32(cmd->device->lun);
+	srbcmd->flags    = cpu_to_le32(flag);
+	timeout = cmd->timeout_per_command/HZ;
+	if (timeout == 0)
+		timeout = 1;
+	srbcmd->timeout  = cpu_to_le32(timeout);  // timeout in seconds
+	srbcmd->retry_limit = 0; /* Obsolete parameter */
+	srbcmd->cdb_size = cpu_to_le32(cmd->cmd_len);
+	return srbcmd;
+}
+
+static void aac_srb_callback(void *context, struct fib * fibptr);
+
+static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd)
+{
+	u16 fibsize;
+	struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
+
+	aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg);
+	srbcmd->count = cpu_to_le32(cmd->request_bufflen);
+
+	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
+	memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
+	/*
+	 *	Build Scatter/Gather list
+	 */
+	fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
+		((le32_to_cpu(srbcmd->sg.count) & 0xff) *
+		 sizeof (struct sgentry64));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ScsiPortCommand64, fib,
+				fibsize, FsaNormal, 0, 1,
+				  (fib_callback) aac_srb_callback,
+				  (void *) cmd);
+}
+
+static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd)
+{
+	u16 fibsize;
+	struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
+
+	aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg);
+	srbcmd->count = cpu_to_le32(cmd->request_bufflen);
+
+	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
+	memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
+	/*
+	 *	Build Scatter/Gather list
+	 */
+	fibsize = sizeof (struct aac_srb) +
+		(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
+		 sizeof (struct sgentry));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ScsiPortCommand, fib, fibsize, FsaNormal, 0, 1,
+				  (fib_callback) aac_srb_callback, (void *) cmd);
+}
+
 int aac_get_adapter_info(struct aac_dev* dev)
 {
 	struct fib* fibptr;
@@ -874,14 +1176,27 @@
 		}
 	}
 	/* 
-	 * 57 scatter gather elements 
+	 * Deal with configuring for the individualized limits of each packet
+	 * interface.
 	 */
-	if (!(dev->raw_io_interface)) {
+	dev->a_ops.adapter_scsi = (dev->dac_support)
+				? aac_scsi_64
+				: aac_scsi_32;
+	if (dev->raw_io_interface) {
+		dev->a_ops.adapter_bounds = (dev->raw_io_64)
+					? aac_bounds_64
+					: aac_bounds_32;
+		dev->a_ops.adapter_read = aac_read_raw_io;
+		dev->a_ops.adapter_write = aac_write_raw_io;
+	} else {
+		dev->a_ops.adapter_bounds = aac_bounds_32;
 		dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
 			sizeof(struct aac_fibhdr) -
 			sizeof(struct aac_write) + sizeof(struct sgentry)) /
 				sizeof(struct sgentry);
 		if (dev->dac_support) {
+			dev->a_ops.adapter_read = aac_read_block64;
+			dev->a_ops.adapter_write = aac_write_block64;
 			/* 
 			 * 38 scatter gather elements 
 			 */
@@ -891,6 +1206,9 @@
 				sizeof(struct aac_write64) +
 				sizeof(struct sgentry64)) /
 					sizeof(struct sgentry64);
+		} else {
+			dev->a_ops.adapter_read = aac_read_block;
+			dev->a_ops.adapter_write = aac_write_block;
 		}
 		dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
 		if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
@@ -1004,8 +1322,6 @@
 	u64 lba;
 	u32 count;
 	int status;
-
-	u16 fibsize;
 	struct aac_dev *dev;
 	struct fib * cmd_fibcontext;
 
@@ -1059,23 +1375,8 @@
 	}
 	dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
 	  smp_processor_id(), (unsigned long long)lba, jiffies));
-	if ((!(dev->raw_io_interface) || !(dev->raw_io_64)) &&
-		(lba & 0xffffffff00000000LL)) {
-		dprintk((KERN_DEBUG "aac_read: Illegal lba\n"));
-		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | 
-			SAM_STAT_CHECK_CONDITION;
-		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-			    HARDWARE_ERROR,
-			    SENCODE_INTERNAL_TARGET_FAILURE,
-			    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
-			    0, 0);
-		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
-		  (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer))
-		    ? sizeof(scsicmd->sense_buffer)
-		    : sizeof(dev->fsa_dev[cid].sense_data));
-		scsicmd->scsi_done(scsicmd);
+	if (aac_adapter_bounds(dev,scsicmd,lba))
 		return 0;
-	}
 	/*
 	 *	Alocate and initialize a Fib
 	 */
@@ -1083,85 +1384,7 @@
 		return -1;
 	}
 
-	aac_fib_init(cmd_fibcontext);
-
-	if (dev->raw_io_interface) {
-		struct aac_raw_io *readcmd;
-		readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
-		readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
-		readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
-		readcmd->count = cpu_to_le32(count<<9);
-		readcmd->cid = cpu_to_le16(cid);
-		readcmd->flags = cpu_to_le16(1);
-		readcmd->bpTotal = 0;
-		readcmd->bpComplete = 0;
-		
-		aac_build_sgraw(scsicmd, &readcmd->sg);
-		fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
-		BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerRawIo,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	} else if (dev->dac_support == 1) {
-		struct aac_read64 *readcmd;
-		readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
-		readcmd->command = cpu_to_le32(VM_CtHostRead64);
-		readcmd->cid = cpu_to_le16(cid);
-		readcmd->sector_count = cpu_to_le16(count);
-		readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
-		readcmd->pad   = 0;
-		readcmd->flags = 0; 
-
-		aac_build_sg64(scsicmd, &readcmd->sg);
-		fibsize = sizeof(struct aac_read64) + 
-			((le32_to_cpu(readcmd->sg.count) - 1) * 
-			 sizeof (struct sgentry64));
-		BUG_ON (fibsize > (dev->max_fib_size - 
-					sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerCommand64,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	} else {
-		struct aac_read *readcmd;
-		readcmd = (struct aac_read *) fib_data(cmd_fibcontext);
-		readcmd->command = cpu_to_le32(VM_CtBlockRead);
-		readcmd->cid = cpu_to_le32(cid);
-		readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
-		readcmd->count = cpu_to_le32(count * 512);
-
-		aac_build_sg(scsicmd, &readcmd->sg);
-		fibsize = sizeof(struct aac_read) + 
-			((le32_to_cpu(readcmd->sg.count) - 1) * 
-			 sizeof (struct sgentry));
-		BUG_ON (fibsize > (dev->max_fib_size -
-					sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerCommand,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	}
-
-	
+	status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count);
 
 	/*
 	 *	Check that the command queued to the controller
@@ -1187,7 +1410,6 @@
 	u64 lba;
 	u32 count;
 	int status;
-	u16 fibsize;
 	struct aac_dev *dev;
 	struct fib * cmd_fibcontext;
 
@@ -1227,22 +1449,8 @@
 	}
 	dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
 	  smp_processor_id(), (unsigned long long)lba, jiffies));
-	if ((!(dev->raw_io_interface) || !(dev->raw_io_64))
-	 && (lba & 0xffffffff00000000LL)) {
-		dprintk((KERN_DEBUG "aac_write: Illegal lba\n"));
-		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
-		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-			    HARDWARE_ERROR,
-			    SENCODE_INTERNAL_TARGET_FAILURE,
-			    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
-			    0, 0);
-		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
-		  (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer))
-		    ? sizeof(scsicmd->sense_buffer)
-		    : sizeof(dev->fsa_dev[cid].sense_data));
-		scsicmd->scsi_done(scsicmd);
+	if (aac_adapter_bounds(dev,scsicmd,lba))
 		return 0;
-	}
 	/*
 	 *	Allocate and initialize a Fib then setup a BlockWrite command
 	 */
@@ -1251,85 +1459,8 @@
 		scsicmd->scsi_done(scsicmd);
 		return 0;
 	}
-	aac_fib_init(cmd_fibcontext);
 
-	if (dev->raw_io_interface) {
-		struct aac_raw_io *writecmd;
-		writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
-		writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
-		writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
-		writecmd->count = cpu_to_le32(count<<9);
-		writecmd->cid = cpu_to_le16(cid);
-		writecmd->flags = 0; 
-		writecmd->bpTotal = 0;
-		writecmd->bpComplete = 0;
-		
-		aac_build_sgraw(scsicmd, &writecmd->sg);
-		fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
-		BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerRawIo,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	} else if (dev->dac_support == 1) {
-		struct aac_write64 *writecmd;
-		writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
-		writecmd->command = cpu_to_le32(VM_CtHostWrite64);
-		writecmd->cid = cpu_to_le16(cid);
-		writecmd->sector_count = cpu_to_le16(count); 
-		writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
-		writecmd->pad	= 0;
-		writecmd->flags	= 0;
-
-		aac_build_sg64(scsicmd, &writecmd->sg);
-		fibsize = sizeof(struct aac_write64) + 
-			((le32_to_cpu(writecmd->sg.count) - 1) * 
-			 sizeof (struct sgentry64));
-		BUG_ON (fibsize > (dev->max_fib_size -
-					sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerCommand64,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	} else {
-		struct aac_write *writecmd;
-		writecmd = (struct aac_write *) fib_data(cmd_fibcontext);
-		writecmd->command = cpu_to_le32(VM_CtBlockWrite);
-		writecmd->cid = cpu_to_le32(cid);
-		writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
-		writecmd->count = cpu_to_le32(count * 512);
-		writecmd->sg.count = cpu_to_le32(1);
-		/* ->stable is not used - it did mean which type of write */
-
-		aac_build_sg(scsicmd, &writecmd->sg);
-		fibsize = sizeof(struct aac_write) + 
-			((le32_to_cpu(writecmd->sg.count) - 1) * 
-			 sizeof (struct sgentry));
-		BUG_ON (fibsize > (dev->max_fib_size -
-					sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerCommand,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	}
+	status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count);
 
 	/*
 	 *	Check that the command queued to the controller
@@ -2099,10 +2230,6 @@
 	struct fib* cmd_fibcontext;
 	struct aac_dev* dev;
 	int status;
-	struct aac_srb *srbcmd;
-	u16 fibsize;
-	u32 flag;
-	u32 timeout;
 
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 	if (scmd_id(scsicmd) >= dev->maximum_num_physicals ||
@@ -2112,88 +2239,14 @@
 		return 0;
 	}
 
-	switch(scsicmd->sc_data_direction){
-	case DMA_TO_DEVICE:
-		flag = SRB_DataOut;
-		break;
-	case DMA_BIDIRECTIONAL:
-		flag = SRB_DataIn | SRB_DataOut;
-		break;
-	case DMA_FROM_DEVICE:
-		flag = SRB_DataIn;
-		break;
-	case DMA_NONE:
-	default:	/* shuts up some versions of gcc */
-		flag = SRB_NoDataXfer;
-		break;
-	}
-
-
 	/*
 	 *	Allocate and initialize a Fib then setup a BlockWrite command
 	 */
 	if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
 		return -1;
 	}
-	aac_fib_init(cmd_fibcontext);
+	status = aac_adapter_scsi(cmd_fibcontext, scsicmd);
 
-	srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
-	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
-	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;
-	if(timeout == 0){
-		timeout = 1;
-	}
-	srbcmd->timeout  = cpu_to_le32(timeout);  // timeout in seconds
-	srbcmd->retry_limit = 0; /* Obsolete parameter */
-	srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len);
-	
-	if( dev->dac_support == 1 ) {
-		aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg);
-		srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
-
-		memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
-		memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len);
-		/*
-		 *	Build Scatter/Gather list
-		 */
-		fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
-			((le32_to_cpu(srbcmd->sg.count) & 0xff) * 
-			 sizeof (struct sgentry64));
-		BUG_ON (fibsize > (dev->max_fib_size -
-					sizeof(struct aac_fibhdr)));
-
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ScsiPortCommand64, cmd_fibcontext,
-				fibsize, FsaNormal, 0, 1,
-				  (fib_callback) aac_srb_callback, 
-				  (void *) scsicmd);
-	} else {
-		aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg);
-		srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
-
-		memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
-		memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len);
-		/*
-		 *	Build Scatter/Gather list
-		 */
-		fibsize = sizeof (struct aac_srb) + 
-			(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * 
-			 sizeof (struct sgentry));
-		BUG_ON (fibsize > (dev->max_fib_size -
-					sizeof(struct aac_fibhdr)));
-
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
-				  (fib_callback) aac_srb_callback, (void *) scsicmd);
-	}
 	/*
 	 *	Check that the command queued to the controller
 	 */
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 4f8b4c5..39ecd0d 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -5,6 +5,7 @@
 #define _nblank(x) #x
 #define nblank(x) _nblank(x)[0]
 
+#include <linux/interrupt.h>
 
 /*------------------------------------------------------------------------------
  *              D E F I N E S
@@ -485,16 +486,28 @@
 
 struct aac_dev;
 struct fib;
+struct scsi_cmnd;
 
 struct adapter_ops
 {
+	/* Low level operations */
 	void (*adapter_interrupt)(struct aac_dev *dev);
 	void (*adapter_notify)(struct aac_dev *dev, u32 event);
 	void (*adapter_disable_int)(struct aac_dev *dev);
+	void (*adapter_enable_int)(struct aac_dev *dev);
 	int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
 	int  (*adapter_check_health)(struct aac_dev *dev);
-	int  (*adapter_send)(struct fib * fib);
+	/* Transport operations */
 	int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
+	irqreturn_t (*adapter_intr)(int irq, void *dev_id);
+	/* Packet operations */
+	int  (*adapter_deliver)(struct fib * fib);
+	int  (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba);
+	int  (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
+	int  (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
+	int  (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd);
+	/* Administrative operations */
+	int  (*adapter_comm)(struct aac_dev * dev, int comm);
 };
 
 /*
@@ -1018,7 +1031,9 @@
 	u8			nondasd_support; 
 	u8			dac_support;
 	u8			raid_scsi_mode;
-	u8			new_comm_interface;
+	u8			comm_interface;
+#	define AAC_COMM_PRODUCER 0
+#	define AAC_COMM_MESSAGE  1
 	/* macro side-effects BEWARE */
 #	define			raw_io_interface \
 	  init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
@@ -1036,18 +1051,36 @@
 #define aac_adapter_disable_int(dev) \
 	(dev)->a_ops.adapter_disable_int(dev)
 
+#define aac_adapter_enable_int(dev) \
+	(dev)->a_ops.adapter_enable_int(dev)
+
 #define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
 	(dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
 
 #define aac_adapter_check_health(dev) \
 	(dev)->a_ops.adapter_check_health(dev)
 
-#define aac_adapter_send(fib) \
-	((fib)->dev)->a_ops.adapter_send(fib)
-
 #define aac_adapter_ioremap(dev, size) \
 	(dev)->a_ops.adapter_ioremap(dev, size)
 
+#define aac_adapter_deliver(fib) \
+	((fib)->dev)->a_ops.adapter_deliver(fib)
+
+#define aac_adapter_bounds(dev,cmd,lba) \
+	dev->a_ops.adapter_bounds(dev,cmd,lba)
+
+#define aac_adapter_read(fib,cmd,lba,count) \
+	((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count)
+
+#define aac_adapter_write(fib,cmd,lba,count) \
+	((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count)
+
+#define aac_adapter_scsi(fib,cmd) \
+	((fib)->dev)->a_ops.adapter_scsi(fib,cmd)
+
+#define aac_adapter_comm(dev,comm) \
+	(dev)->a_ops.adapter_comm(dev, comm)
+
 #define FIB_CONTEXT_FLAG_TIMED_OUT		(0x00000001)
 
 /*
@@ -1767,7 +1800,6 @@
 	return (u32)capacity;
 }
 
-struct scsi_cmnd;
 /* SCp.phase values */
 #define AAC_OWNER_MIDLEVEL	0x101
 #define AAC_OWNER_LOWLEVEL	0x102
@@ -1794,7 +1826,9 @@
 int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg);
 int aac_rx_init(struct aac_dev *dev);
 int aac_rkt_init(struct aac_dev *dev);
+int aac_nark_init(struct aac_dev *dev);
 int aac_sa_init(struct aac_dev *dev);
+int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify);
 unsigned int aac_response_normal(struct aac_queue * q);
 unsigned int aac_command_normal(struct aac_queue * q);
 unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index da1d3a9..e21070f 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 6d305b2..ae34768 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -32,7 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -95,7 +94,7 @@
 	init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
 
 	init->InitFlags = 0;
-	if (dev->new_comm_interface) {
+	if (dev->comm_interface == AAC_COMM_MESSAGE) {
 		init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
 		dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
 	}
@@ -297,21 +296,23 @@
 		- sizeof(struct aac_fibhdr)
 		- sizeof(struct aac_write) + sizeof(struct sgentry))
 			/ sizeof(struct sgentry);
-	dev->new_comm_interface = 0;
+	dev->comm_interface = AAC_COMM_PRODUCER;
 	dev->raw_io_64 = 0;
 	if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
 		0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
 	 		(status[0] == 0x00000001)) {
 		if (status[1] & AAC_OPT_NEW_COMM_64)
 			dev->raw_io_64 = 1;
-		if (status[1] & AAC_OPT_NEW_COMM)
-			dev->new_comm_interface = dev->a_ops.adapter_send != 0;
-		if (dev->new_comm_interface && (status[2] > dev->base_size)) {
+		if (dev->a_ops.adapter_comm &&
+		    (status[1] & AAC_OPT_NEW_COMM))
+			dev->comm_interface = AAC_COMM_MESSAGE;
+		if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
+		    (status[2] > dev->base_size)) {
 			aac_adapter_ioremap(dev, 0);
 			dev->base_size = status[2];
 			if (aac_adapter_ioremap(dev, status[2])) {
 				/* remap failed, go back ... */
-				dev->new_comm_interface = 0;
+				dev->comm_interface = AAC_COMM_PRODUCER;
 				if (aac_adapter_ioremap(dev, AAC_MIN_FOOTPRINT_SIZE)) {
 					printk(KERN_WARNING
 					  "aacraid: unable to map adapter.\n");
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 4893a6d..1b97f60 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -317,7 +317,7 @@
  *	success.
  */
 
-static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify)
+int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify)
 {
 	struct aac_entry * entry = NULL;
 	int map = 0;
@@ -387,7 +387,6 @@
 {
 	struct aac_dev * dev = fibptr->dev;
 	struct hw_fib * hw_fib = fibptr->hw_fib;
-	struct aac_queue * q;
 	unsigned long flags = 0;
 	unsigned long qflags;
 
@@ -469,38 +468,10 @@
 
 	if (!dev->queues)
 		return -EBUSY;
-	q = &dev->queues->queue[AdapNormCmdQueue];
 
 	if(wait)
 		spin_lock_irqsave(&fibptr->event_lock, flags);
-	spin_lock_irqsave(q->lock, qflags);
-	if (dev->new_comm_interface) {
-		unsigned long count = 10000000L; /* 50 seconds */
-		q->numpending++;
-		spin_unlock_irqrestore(q->lock, qflags);
-		while (aac_adapter_send(fibptr) != 0) {
-			if (--count == 0) {
-				if (wait)
-					spin_unlock_irqrestore(&fibptr->event_lock, flags);
-				spin_lock_irqsave(q->lock, qflags);
-				q->numpending--;
-				spin_unlock_irqrestore(q->lock, qflags);
-				return -ETIMEDOUT;
-			}
-			udelay(5);
-		}
-	} else {
-		u32 index;
-		unsigned long nointr = 0;
-		aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr);
-
-		q->numpending++;
-		*(q->headers.producer) = cpu_to_le32(index + 1);
-		spin_unlock_irqrestore(q->lock, qflags);
-		dprintk((KERN_DEBUG "aac_fib_send: inserting a queue entry at index %d.\n",index));
-		if (!(nointr & aac_config.irq_mod))
-			aac_adapter_notify(dev, AdapNormCmdQueue);
-	}
+	aac_adapter_deliver(fibptr);
 
 	/*
 	 *	If the caller wanted us to wait for response wait now. 
@@ -520,6 +491,7 @@
 			while (down_trylock(&fibptr->event_wait)) {
 				int blink;
 				if (--count == 0) {
+					struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue];
 					spin_lock_irqsave(q->lock, qflags);
 					q->numpending--;
 					spin_unlock_irqrestore(q->lock, qflags);
@@ -659,7 +631,7 @@
 	unsigned long qflags;
 
 	if (hw_fib->header.XferState == 0) {
-		if (dev->new_comm_interface)
+		if (dev->comm_interface == AAC_COMM_MESSAGE)
 			kfree (hw_fib);
         	return 0;
 	}
@@ -667,7 +639,7 @@
 	 *	If we plan to do anything check the structure type first.
 	 */ 
 	if ( hw_fib->header.StructType != FIB_MAGIC ) {
-		if (dev->new_comm_interface)
+		if (dev->comm_interface == AAC_COMM_MESSAGE)
 			kfree (hw_fib);
         	return -EINVAL;
 	}
@@ -679,7 +651,7 @@
 	 *	send the completed cdb to the adapter.
 	 */
 	if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) {
-		if (dev->new_comm_interface) {
+		if (dev->comm_interface == AAC_COMM_MESSAGE) {
 			kfree (hw_fib);
 		} else {
 	       		u32 index;
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index 8335f07..d38b628 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -32,7 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index d2cf875..0f948c2 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -157,6 +157,7 @@
 	{ 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 58 }, /* Legend Catchall */
 	{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */
 	{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */
+	{ 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
@@ -230,7 +231,8 @@
 	{ aac_rx_init, "aacraid",  "DELL    ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */
 	{ aac_rx_init, "aacraid",  "Legend  ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec Catch All */
-	{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec Rocket Catch All */
+	{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Rocket Catch All */
+	{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec NEMER/ARK Catch All */
 };
 
 /**
@@ -396,11 +398,15 @@
 		sdev->skip_ms_page_3f = 1;
 	}
 	if ((sdev->type == TYPE_DISK) &&
-			!expose_physicals &&
 			(sdev_channel(sdev) != CONTAINER_CHANNEL)) {
-		struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
-		if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
-			sdev->no_uld_attach = 1;
+		if (expose_physicals == 0)
+			return -ENXIO;
+		if (expose_physicals < 0) {
+			struct aac_dev *aac =
+				(struct aac_dev *)sdev->host->hostdata;
+			if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
+				sdev->no_uld_attach = 1;
+		}
 	}
 	if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
 			(sdev_channel(sdev) == CONTAINER_CHANNEL)) {
@@ -768,7 +774,7 @@
 };
 
 
-static struct file_operations aac_cfg_fops = {
+static const struct file_operations aac_cfg_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= aac_cfg_ioctl,
 #ifdef CONFIG_COMPAT
@@ -804,7 +810,6 @@
 	.emulated                       = 1,
 };
 
-
 static int __devinit aac_probe_one(struct pci_dev *pdev,
 		const struct pci_device_id *id)
 {
diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c
new file mode 100644
index 0000000..c76b611
--- /dev/null
+++ b/drivers/scsi/aacraid/nark.c
@@ -0,0 +1,87 @@
+/*
+ *	Adaptec AAC series RAID controller driver
+ *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
+ *
+ * based on the old aacraid driver that is..
+ * Adaptec aacraid device driver for Linux.
+ *
+ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Module Name:
+ *  nark.c
+ *
+ * Abstract: Hardware Device Interface for NEMER/ARK
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/blkdev.h>
+
+#include <scsi/scsi_host.h>
+
+#include "aacraid.h"
+
+/**
+ *	aac_nark_ioremap
+ *	@size: mapping resize request
+ *
+ */
+static int aac_nark_ioremap(struct aac_dev * dev, u32 size)
+{
+	if (!size) {
+		iounmap(dev->regs.rx);
+		dev->regs.rx = NULL;
+		iounmap(dev->base);
+		dev->base = NULL;
+		return 0;
+	}
+	dev->scsi_host_ptr->base = pci_resource_start(dev->pdev, 2);
+	dev->regs.rx = ioremap((u64)pci_resource_start(dev->pdev, 0) |
+	  ((u64)pci_resource_start(dev->pdev, 1) << 32),
+	  sizeof(struct rx_registers) - sizeof(struct rx_inbound));
+	dev->base = NULL;
+	if (dev->regs.rx == NULL)
+		return -1;
+	dev->base = ioremap(dev->scsi_host_ptr->base, size);
+	if (dev->base == NULL) {
+		iounmap(dev->regs.rx);
+		dev->regs.rx = NULL;
+		return -1;
+	}
+	dev->IndexRegs = &((struct rx_registers __iomem *)dev->base)->IndexRegs;
+	return 0;
+}
+
+/**
+ *	aac_nark_init	-	initialize an NEMER/ARK Split Bar card
+ *	@dev: device to configure
+ *
+ */
+
+int aac_nark_init(struct aac_dev * dev)
+{
+	extern int _aac_rx_init(struct aac_dev *dev);
+	extern int aac_rx_select_comm(struct aac_dev *dev, int comm);
+
+	/*
+	 *	Fill in the function dispatch table.
+	 */
+	dev->a_ops.adapter_ioremap = aac_nark_ioremap;
+	dev->a_ops.adapter_comm = aac_rx_select_comm;
+
+	return _aac_rx_init(dev);
+}
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 643f23b..d953c3f 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -34,6 +34,40 @@
 
 #include "aacraid.h"
 
+#define AAC_NUM_IO_FIB_RKT      (246 - AAC_NUM_MGT_FIB)
+
+/**
+ *	aac_rkt_select_comm	-	Select communications method
+ *	@dev: Adapter
+ *	@comm: communications method
+ */
+
+static int aac_rkt_select_comm(struct aac_dev *dev, int comm)
+{
+	int retval;
+	extern int aac_rx_select_comm(struct aac_dev *dev, int comm);
+	retval = aac_rx_select_comm(dev, comm);
+	if (comm == AAC_COMM_MESSAGE) {
+		/*
+		 * FIB Setup has already been done, but we can minimize the
+		 * damage by at least ensuring the OS never issues more
+		 * commands than we can handle. The Rocket adapters currently
+		 * can only handle 246 commands and 8 AIFs at the same time,
+		 * and in fact do notify us accordingly if we negotiate the
+		 * FIB size. The problem that causes us to add this check is
+		 * to ensure that we do not overdo it with the adapter when a
+		 * hard coded FIB override is being utilized. This special
+		 * case warrants this half baked, but convenient, check here.
+		 */
+		if (dev->scsi_host_ptr->can_queue > AAC_NUM_IO_FIB_RKT) {
+			dev->init->MaxIoCommands =
+				cpu_to_le32(AAC_NUM_IO_FIB_RKT + AAC_NUM_MGT_FIB);
+			dev->scsi_host_ptr->can_queue = AAC_NUM_IO_FIB_RKT;
+		}
+	}
+	return retval;
+}
+
 /**
  *	aac_rkt_ioremap
  *	@size: mapping resize request
@@ -63,39 +97,13 @@
 
 int aac_rkt_init(struct aac_dev *dev)
 {
-	int retval;
 	extern int _aac_rx_init(struct aac_dev *dev);
-	extern void aac_rx_start_adapter(struct aac_dev *dev);
 
 	/*
 	 *	Fill in the function dispatch table.
 	 */
 	dev->a_ops.adapter_ioremap = aac_rkt_ioremap;
+	dev->a_ops.adapter_comm = aac_rkt_select_comm;
 
-	retval = _aac_rx_init(dev);
-	if (retval)
-		return retval;
-	if (dev->new_comm_interface) {
-		/*
-		 * FIB Setup has already been done, but we can minimize the
-		 * damage by at least ensuring the OS never issues more
-		 * commands than we can handle. The Rocket adapters currently
-		 * can only handle 246 commands and 8 AIFs at the same time,
-		 * and in fact do notify us accordingly if we negotiate the
-		 * FIB size. The problem that causes us to add this check is
-		 * to ensure that we do not overdo it with the adapter when a
-		 * hard coded FIB override is being utilized. This special
-		 * case warrants this half baked, but convenient, check here.
-		 */
-		if (dev->scsi_host_ptr->can_queue > (246 - AAC_NUM_MGT_FIB)) {
-			dev->init->MaxIoCommands = cpu_to_le32(246);
-			dev->scsi_host_ptr->can_queue = 246 - AAC_NUM_MGT_FIB;
-		}
-	}
-	/*
-	 *	Tell the adapter that all is configured, and it can start
-	 *	accepting requests
-	 */
-	aac_rx_start_adapter(dev);
-	return 0;
+	return _aac_rx_init(dev);
 }
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index dcc8b0e..d242e26 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -46,60 +45,60 @@
 
 #include "aacraid.h"
 
-static irqreturn_t aac_rx_intr(int irq, void *dev_id)
+static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id)
 {
 	struct aac_dev *dev = dev_id;
+	unsigned long bellbits;
+	u8 intstat = rx_readb(dev, MUnit.OISR);
 
-	dprintk((KERN_DEBUG "aac_rx_intr(%d,%p)\n", irq, dev_id));
-	if (dev->new_comm_interface) {
-		u32 Index = rx_readl(dev, MUnit.OutboundQueue);
-		if (Index == 0xFFFFFFFFL)
+	/*
+	 *	Read mask and invert because drawbridge is reversed.
+	 *	This allows us to only service interrupts that have
+	 *	been enabled.
+	 *	Check to see if this is our interrupt.  If it isn't just return
+	 */
+	if (intstat & ~(dev->OIMR)) {
+		bellbits = rx_readl(dev, OutboundDoorbellReg);
+		if (bellbits & DoorBellPrintfReady) {
+			aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
+			rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
+			rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
+		}
+		else if (bellbits & DoorBellAdapterNormCmdReady) {
+			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
+			aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
+		}
+		else if (bellbits & DoorBellAdapterNormRespReady) {
+			rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
+			aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
+		}
+		else if (bellbits & DoorBellAdapterNormCmdNotFull) {
+			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
+		}
+		else if (bellbits & DoorBellAdapterNormRespNotFull) {
+			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
+			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
+		}
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static irqreturn_t aac_rx_intr_message(int irq, void *dev_id)
+{
+	struct aac_dev *dev = dev_id;
+	u32 Index = rx_readl(dev, MUnit.OutboundQueue);
+	if (Index == 0xFFFFFFFFL)
+		Index = rx_readl(dev, MUnit.OutboundQueue);
+	if (Index != 0xFFFFFFFFL) {
+		do {
+			if (aac_intr_normal(dev, Index)) {
+				rx_writel(dev, MUnit.OutboundQueue, Index);
+				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
+			}
 			Index = rx_readl(dev, MUnit.OutboundQueue);
-		if (Index != 0xFFFFFFFFL) {
-			do {
-				if (aac_intr_normal(dev, Index)) {
-					rx_writel(dev, MUnit.OutboundQueue, Index);
-					rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
-				}
-				Index = rx_readl(dev, MUnit.OutboundQueue);
-			} while (Index != 0xFFFFFFFFL);
-			return IRQ_HANDLED;
-		}
-	} else {
-		unsigned long bellbits;
-		u8 intstat;
-		intstat = rx_readb(dev, MUnit.OISR);
-		/*
-		 *	Read mask and invert because drawbridge is reversed.
-		 *	This allows us to only service interrupts that have 
-		 *	been enabled.
-		 *	Check to see if this is our interrupt.  If it isn't just return
-		 */
-		if (intstat & ~(dev->OIMR)) 
-		{
-			bellbits = rx_readl(dev, OutboundDoorbellReg);
-			if (bellbits & DoorBellPrintfReady) {
-				aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
-				rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
-				rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
-			}
-			else if (bellbits & DoorBellAdapterNormCmdReady) {
-				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
-				aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
-			}
-			else if (bellbits & DoorBellAdapterNormRespReady) {
-				rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
-				aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
-			}
-			else if (bellbits & DoorBellAdapterNormCmdNotFull) {
-				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
-			}
-			else if (bellbits & DoorBellAdapterNormRespNotFull) {
-				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
-				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
-			}
-			return IRQ_HANDLED;
-		}
+		} while (Index != 0xFFFFFFFFL);
+		return IRQ_HANDLED;
 	}
 	return IRQ_NONE;
 }
@@ -115,6 +114,26 @@
 }
 
 /**
+ *	aac_rx_enable_interrupt_producer	-	Enable interrupts
+ *	@dev: Adapter
+ */
+
+static void aac_rx_enable_interrupt_producer(struct aac_dev *dev)
+{
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+}
+
+/**
+ *	aac_rx_enable_interrupt_message	-	Enable interrupts
+ *	@dev: Adapter
+ */
+
+static void aac_rx_enable_interrupt_message(struct aac_dev *dev)
+{
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
+}
+
+/**
  *	rx_sync_cmd	-	send a command and wait
  *	@dev: Adapter
  *	@command: Command to execute
@@ -189,10 +208,7 @@
 		/*
 		 *	Restore interrupt mask even though we timed out
 		 */
-		if (dev->new_comm_interface)
-			rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
-		else
-			rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+		aac_adapter_enable_int(dev);
 		return -ETIMEDOUT;
 	}
 	/*
@@ -215,10 +231,7 @@
 	/*
 	 *	Restore interrupt mask
 	 */
-	if (dev->new_comm_interface)
-		rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
-	else
-		rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+	aac_adapter_enable_int(dev);
 	return 0;
 
 }
@@ -360,35 +373,72 @@
 }
 
 /**
- *	aac_rx_send
+ *	aac_rx_deliver_producer
  *	@fib: fib to issue
  *
  *	Will send a fib, returning 0 if successful.
  */
-static int aac_rx_send(struct fib * fib)
+static int aac_rx_deliver_producer(struct fib * fib)
 {
-	u64 addr = fib->hw_fib_pa;
 	struct aac_dev *dev = fib->dev;
-	volatile void __iomem *device = dev->regs.rx;
+	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
+	unsigned long qflags;
 	u32 Index;
+	unsigned long nointr = 0;
 
-	dprintk((KERN_DEBUG "%p->aac_rx_send(%p->%llx)\n", dev, fib, addr));
-	Index = rx_readl(dev, MUnit.InboundQueue);
-	if (Index == 0xFFFFFFFFL)
+	spin_lock_irqsave(q->lock, qflags);
+	aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib, 1, fib, &nointr);
+
+	q->numpending++;
+	*(q->headers.producer) = cpu_to_le32(Index + 1);
+	spin_unlock_irqrestore(q->lock, qflags);
+	if (!(nointr & aac_config.irq_mod))
+		aac_adapter_notify(dev, AdapNormCmdQueue);
+
+	return 0;
+}
+
+/**
+ *	aac_rx_deliver_message
+ *	@fib: fib to issue
+ *
+ *	Will send a fib, returning 0 if successful.
+ */
+static int aac_rx_deliver_message(struct fib * fib)
+{
+	struct aac_dev *dev = fib->dev;
+	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
+	unsigned long qflags;
+	u32 Index;
+	u64 addr;
+	volatile void __iomem *device;
+
+	unsigned long count = 10000000L; /* 50 seconds */
+	spin_lock_irqsave(q->lock, qflags);
+	q->numpending++;
+	spin_unlock_irqrestore(q->lock, qflags);
+	for(;;) {
 		Index = rx_readl(dev, MUnit.InboundQueue);
-	dprintk((KERN_DEBUG "Index = 0x%x\n", Index));
-	if (Index == 0xFFFFFFFFL)
-		return Index;
+		if (Index == 0xFFFFFFFFL)
+			Index = rx_readl(dev, MUnit.InboundQueue);
+		if (Index != 0xFFFFFFFFL)
+			break;
+		if (--count == 0) {
+			spin_lock_irqsave(q->lock, qflags);
+			q->numpending--;
+			spin_unlock_irqrestore(q->lock, qflags);
+			return -ETIMEDOUT;
+		}
+		udelay(5);
+	}
 	device = dev->base + Index;
-	dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff),
-	  (u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size)));
+	addr = fib->hw_fib_pa;
 	writel((u32)(addr & 0xffffffff), device);
 	device += sizeof(u32);
 	writel((u32)(addr >> 32), device);
 	device += sizeof(u32);
 	writel(le16_to_cpu(fib->hw_fib->header.Size), device);
 	rx_writel(dev, MUnit.InboundQueue, Index);
-	dprintk((KERN_DEBUG "aac_rx_send - return 0\n"));
 	return 0;
 }
 
@@ -430,6 +480,31 @@
 }
 
 /**
+ *	aac_rx_select_comm	-	Select communications method
+ *	@dev: Adapter
+ *	@comm: communications method
+ */
+
+int aac_rx_select_comm(struct aac_dev *dev, int comm)
+{
+	switch (comm) {
+	case AAC_COMM_PRODUCER:
+		dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_producer;
+		dev->a_ops.adapter_intr = aac_rx_intr_producer;
+		dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
+		break;
+	case AAC_COMM_MESSAGE:
+		dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_message;
+		dev->a_ops.adapter_intr = aac_rx_intr_message;
+		dev->a_ops.adapter_deliver = aac_rx_deliver_message;
+		break;
+	default:
+		return 1;
+	}
+	return 0;
+}
+
+/**
  *	aac_rx_init	-	initialize an i960 based AAC card
  *	@dev: device to configure
  *
@@ -489,40 +564,42 @@
 		}
 		msleep(1);
 	}
-	if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, IRQF_SHARED|IRQF_DISABLED, "aacraid", (void *)dev)<0)
-	{
-		printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance);
-		goto error_iounmap;
-	}
 	/*
-	 *	Fill in the function dispatch table.
+	 *	Fill in the common function dispatch table.
 	 */
 	dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
 	dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
 	dev->a_ops.adapter_notify = aac_rx_notify_adapter;
 	dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
 	dev->a_ops.adapter_check_health = aac_rx_check_health;
-	dev->a_ops.adapter_send = aac_rx_send;
 
 	/*
 	 *	First clear out all interrupts.  Then enable the one's that we
 	 *	can handle.
 	 */
-	rx_writeb(dev, MUnit.OIMR, 0xff);
+	aac_adapter_comm(dev, AAC_COMM_PRODUCER);
+	aac_adapter_disable_int(dev);
 	rx_writel(dev, MUnit.ODR, 0xffffffff);
-	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+	aac_adapter_enable_int(dev);
 
 	if (aac_init_adapter(dev) == NULL)
-		goto error_irq;
-	if (dev->new_comm_interface)
-		rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
+		goto error_iounmap;
+	aac_adapter_comm(dev, dev->comm_interface);
+	if (request_irq(dev->scsi_host_ptr->irq, dev->a_ops.adapter_intr,
+			IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) {
+		printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
+			name, instance);
+		goto error_iounmap;
+	}
+	aac_adapter_enable_int(dev);
+	/*
+	 *	Tell the adapter that all is configured, and it can
+	 * start accepting requests
+	 */
+	aac_rx_start_adapter(dev);
 
 	return 0;
 
-error_irq:
-	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
-	free_irq(dev->scsi_host_ptr->irq, (void *)dev);
-
 error_iounmap:
 
 	return -1;
@@ -530,20 +607,11 @@
 
 int aac_rx_init(struct aac_dev *dev)
 {
-	int retval;
-
 	/*
 	 *	Fill in the function dispatch table.
 	 */
 	dev->a_ops.adapter_ioremap = aac_rx_ioremap;
+	dev->a_ops.adapter_comm = aac_rx_select_comm;
 
-	retval = _aac_rx_init(dev);
-	if (!retval) {
-		/*
-		 *	Tell the adapter that all is configured, and it can
-		 * start accepting requests
-		 */
-		aac_rx_start_adapter(dev);
-	}
-	return retval;
+	return _aac_rx_init(dev);
 }
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 511b0a9..6f1a178 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -92,6 +91,17 @@
 }
 
 /**
+ *	aac_sa_enable_interrupt	-	enable interrupt
+ *	@dev: Which adapter to enable.
+ */
+
+static void aac_sa_enable_interrupt (struct aac_dev *dev)
+{
+	sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 |
+				DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
+}
+
+/**
  *	aac_sa_notify_adapter		-	handle adapter notification
  *	@dev:	Adapter that notification is for
  *	@event:	Event to notidy
@@ -347,32 +357,36 @@
 		msleep(1);
 	}
 
-	if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, IRQF_SHARED|IRQF_DISABLED, "aacraid", (void *)dev ) < 0) {
-		printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance);
-		goto error_iounmap;
-	}
-
 	/*
 	 *	Fill in the function dispatch table.
 	 */
 
 	dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
 	dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
+	dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt;
 	dev->a_ops.adapter_notify = aac_sa_notify_adapter;
 	dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
 	dev->a_ops.adapter_check_health = aac_sa_check_health;
+	dev->a_ops.adapter_intr = aac_sa_intr;
 	dev->a_ops.adapter_ioremap = aac_sa_ioremap;
 
 	/*
 	 *	First clear out all interrupts.  Then enable the one's that 
 	 *	we can handle.
 	 */
-	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
-	sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | 
-				DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
+	aac_adapter_disable_int(dev);
+	aac_adapter_enable_int(dev);
 
 	if(aac_init_adapter(dev) == NULL)
 		goto error_irq;
+	if (request_irq(dev->scsi_host_ptr->irq, dev->a_ops.adapter_intr,
+			IRQF_SHARED|IRQF_DISABLED,
+			"aacraid", (void *)dev ) < 0) {
+		printk(KERN_WARNING "%s%d: Interrupt unavailable.\n",
+			name, instance);
+		goto error_iounmap;
+	}
+	aac_adapter_enable_int(dev);
 
 	/*
 	 *	Tell the adapter that all is configure, and it can start 
@@ -382,7 +396,7 @@
 	return 0;
 
 error_irq:
-	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
+	aac_sa_disable_interrupt(dev);
 	free_irq(dev->scsi_host_ptr->irq, (void *)dev);
 
 error_iounmap:
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 306bec3..9b3303b 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -4403,7 +4403,7 @@
                         ASC_DBG1(1,
                                 "advansys_detect: probing I/O port 0x%x...\n",
                             iop);
-                        if (check_region(iop, ASC_IOADR_GAP) != 0) {
+			if (!request_region(iop, ASC_IOADR_GAP, "advansys")){
                             printk(
 "AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop);
                             /* Don't try this I/O port twice. */
@@ -4413,6 +4413,7 @@
                             printk(
 "AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop);
                             /* Don't try this I/O port twice. */
+			    release_region(iop, ASC_IOADR_GAP);
                             asc_ioport[ioport] = 0;
                             goto ioport_try_again;
                         } else {
@@ -4431,6 +4432,7 @@
                                   * 'ioport' past this board.
                                   */
                                  ioport++;
+				 release_region(iop, ASC_IOADR_GAP);
                                  goto ioport_try_again;
                             }
                         }
@@ -9740,13 +9742,14 @@
     }
     for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
         iop_base = _asc_def_iop_base[i];
-        if (check_region(iop_base, ASC_IOADR_GAP) != 0) {
+	if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")){
             ASC_DBG1(1,
                "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n",
                      iop_base);
             continue;
         }
         ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n", iop_base);
+	release_region(iop_base, ASC_IOADR_GAP);
         if (AscFindSignature(iop_base)) {
             return (iop_base);
         }
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 0cec742..4b4d123 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -236,7 +236,6 @@
  **************************************************************************/
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <asm/irq.h>
 #include <linux/io.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 170a434..27adbb2 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1337,9 +1337,6 @@
 /************************** SCB and SCB queue management **********************/
 void		ahd_qinfifo_requeue_tail(struct ahd_softc *ahd,
 					 struct scb *scb);
-int		ahd_match_scb(struct ahd_softc *ahd, struct scb *scb,
-			      int target, char channel, int lun,
-			      u_int tag, role_t role);
 
 /****************************** Initialization ********************************/
 struct ahd_softc	*ahd_alloc(void *platform_arg, char *name);
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 07a86a3..9ddc6e4 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -262,6 +262,9 @@
 						     u_int mincmds);
 static int		ahd_verify_vpd_cksum(struct vpd_config *vpd);
 static int		ahd_wait_seeprom(struct ahd_softc *ahd);
+static int		ahd_match_scb(struct ahd_softc *ahd, struct scb *scb,
+				      int target, char channel, int lun,
+				      u_int tag, role_t role);
 
 /******************************** Private Inlines *****************************/
 
@@ -7256,7 +7259,7 @@
 }
 
 /************************** SCB and SCB queue management **********************/
-int
+static int
 ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target,
 	      char channel, int lun, u_int tag, role_t role)
 {
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 9bfcca5..2be03e9 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -418,7 +418,6 @@
 	strcat(bp, "        ");
 	ahd_controller_info(ahd, ahd_info);
 	strcat(bp, ahd_info);
-	strcat(bp, "\n");
 
 	return (bp);
 }
@@ -1126,15 +1125,6 @@
 	return 0;
 }
 
-uint64_t
-ahd_linux_get_memsize(void)
-{
-	struct sysinfo si;
-
-	si_meminfo(&si);
-	return ((uint64_t)si.totalram << PAGE_SHIFT);
-}
-
 /*
  * Place the SCSI bus into a known state by either resetting it,
  * or forcing transfer negotiations on the next command to any
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 3a67fc5..147c83c 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -496,8 +496,6 @@
 int		ahd_linux_register_host(struct ahd_softc *,
 					struct scsi_host_template *);
 
-uint64_t	ahd_linux_get_memsize(void);
-
 /*************************** Pretty Printing **********************************/
 struct info_str {
 	char *buffer;
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 1a3ab6a..c62ce41 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -132,6 +132,7 @@
 	struct		 ahd_pci_identity *entry;
 	char		*name;
 	int		 error;
+	struct device	*dev = &pdev->dev;
 
 	pci = pdev;
 	entry = ahd_find_pci_device(pci);
@@ -161,20 +162,18 @@
 	pci_set_master(pdev);
 
 	if (sizeof(dma_addr_t) > 4) {
-		uint64_t   memsize;
-		const uint64_t mask_39bit = 0x7FFFFFFFFFULL;
+		const u64 required_mask = dma_get_required_mask(dev);
 
-		memsize = ahd_linux_get_memsize();
-
-		if (memsize >= 0x8000000000ULL
-	 	 && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
+		if (required_mask > DMA_39BIT_MASK &&
+		    dma_set_mask(dev, DMA_64BIT_MASK) == 0)
 			ahd->flags |= AHD_64BIT_ADDRESSING;
-		} else if (memsize > 0x80000000
-			&& pci_set_dma_mask(pdev, mask_39bit) == 0) {
+		else if (required_mask > DMA_32BIT_MASK &&
+			 dma_set_mask(dev, DMA_39BIT_MASK) == 0)
 			ahd->flags |= AHD_39BIT_ADDRESSING;
-		}
+		else
+			dma_set_mask(dev, DMA_32BIT_MASK);
 	} else {
-		pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		dma_set_mask(dev, DMA_32BIT_MASK);
 	}
 	ahd->dev_softc = pci;
 	error = ahd_pci_config(ahd, entry);
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 2cf7bb3..8d72bba 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -88,7 +88,7 @@
 
 #define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20)
 
-#define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6)
+#define SUBID_9005_SEEPTYPE(id) (((id) & 0x0C0) >> 6)
 #define		SUBID_9005_SEEPTYPE_NONE	0x0
 #define		SUBID_9005_SEEPTYPE_4K		0x1
 
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 7d1fec6..a988d5a 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -229,7 +229,6 @@
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c
index 6f8901b..c520e5b 100644
--- a/drivers/scsi/aic94xx/aic94xx_dev.c
+++ b/drivers/scsi/aic94xx/aic94xx_dev.c
@@ -37,18 +37,14 @@
 
 static inline int asd_get_ddb(struct asd_ha_struct *asd_ha)
 {
-	unsigned long flags;
 	int ddb, i;
 
-	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
 	ddb = FIND_FREE_DDB(asd_ha);
 	if (ddb >= asd_ha->hw_prof.max_ddbs) {
 		ddb = -ENOMEM;
-		spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
 		goto out;
 	}
 	SET_DDB(ddb, asd_ha);
-	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
 
 	for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4)
 		asd_ddbsite_write_dword(asd_ha, ddb, i, 0);
@@ -77,14 +73,10 @@
 
 static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
 {
-	unsigned long flags;
-
 	if (!ddb || ddb >= 0xFFFF)
 		return;
 	asd_ddbsite_write_byte(asd_ha, ddb, DDB_TYPE, DDB_TYPE_UNUSED);
-	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
 	CLEAR_DDB(ddb, asd_ha);
-	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
 }
 
 static inline void asd_set_ddb_type(struct domain_device *dev)
@@ -320,8 +312,11 @@
 
 int asd_dev_found(struct domain_device *dev)
 {
+	unsigned long flags;
 	int res = 0;
+	struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
 
+	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
 	switch (dev->dev_type) {
 	case SATA_PM:
 		res = asd_init_sata_pm_ddb(dev);
@@ -335,14 +330,18 @@
 		else
 			res = asd_init_initiator_ddb(dev);
 	}
+	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
+
 	return res;
 }
 
 void asd_dev_gone(struct domain_device *dev)
 {
 	int ddb, sister_ddb;
+	unsigned long flags;
 	struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
 
+	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
 	ddb = (int) (unsigned long) dev->lldd_dev;
 	sister_ddb = asd_ddbsite_read_word(asd_ha, ddb, SISTER_DDB);
 
@@ -350,4 +349,5 @@
 		asd_free_ddb(asd_ha, sister_ddb);
 	asd_free_ddb(asd_ha, ddb);
 	dev->lldd_dev = NULL;
+	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
 }
diff --git a/drivers/scsi/aic94xx/aic94xx_dump.c b/drivers/scsi/aic94xx/aic94xx_dump.c
index e6ade59..6bd8e30 100644
--- a/drivers/scsi/aic94xx/aic94xx_dump.c
+++ b/drivers/scsi/aic94xx/aic94xx_dump.c
@@ -556,7 +556,7 @@
 	PRINT_LMIP_word(asd_ha, lseq, Q_TGTXFR_TAIL);
 	PRINT_LMIP_byte(asd_ha, lseq, LINK_NUMBER);
 	PRINT_LMIP_byte(asd_ha, lseq, SCRATCH_FLAGS);
-	PRINT_LMIP_qword(asd_ha, lseq, CONNECTION_STATE);
+	PRINT_LMIP_dword(asd_ha, lseq, CONNECTION_STATE);
 	PRINT_LMIP_word(asd_ha, lseq, CONCTL);
 	PRINT_LMIP_byte(asd_ha, lseq, CONSTAT);
 	PRINT_LMIP_byte(asd_ha, lseq, CONNECTION_MODES);
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
index da94e12..0cd7eed 100644
--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
+++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
@@ -1052,10 +1052,9 @@
 	struct asd_ascb *ascb;
 	unsigned long flags;
 
-	ascb = kmem_cache_alloc(asd_ascb_cache, gfp_flags);
+	ascb = kmem_cache_zalloc(asd_ascb_cache, gfp_flags);
 
 	if (ascb) {
-		memset(ascb, 0, sizeof(*ascb));
 		ascb->dma_scb.size = sizeof(struct scb);
 		ascb->dma_scb.vaddr = dma_pool_alloc(asd_ha->scb_pool,
 						     gfp_flags,
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index fbc82b0..27852b4 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -38,7 +38,7 @@
 #include "aic94xx_seq.h"
 
 /* The format is "version.release.patchlevel" */
-#define ASD_DRIVER_VERSION "1.0.2"
+#define ASD_DRIVER_VERSION "1.0.3"
 
 static int use_msi = 0;
 module_param_named(use_msi, use_msi, int, S_IRUGO);
@@ -57,6 +57,8 @@
 char sas_addr_str[2*SAS_ADDR_SIZE + 1] = "";
 
 static struct scsi_transport_template *aic94xx_transport_template;
+static int asd_scan_finished(struct Scsi_Host *, unsigned long);
+static void asd_scan_start(struct Scsi_Host *);
 
 static struct scsi_host_template aic94xx_sht = {
 	.module			= THIS_MODULE,
@@ -66,6 +68,8 @@
 	.target_alloc		= sas_target_alloc,
 	.slave_configure	= sas_slave_configure,
 	.slave_destroy		= sas_slave_destroy,
+	.scan_finished		= asd_scan_finished,
+	.scan_start		= asd_scan_start,
 	.change_queue_depth	= sas_change_queue_depth,
 	.change_queue_type	= sas_change_queue_type,
 	.bios_param		= sas_bios_param,
@@ -75,6 +79,8 @@
 	.sg_tablesize		= SG_ALL,
 	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
 	.use_clustering		= ENABLE_CLUSTERING,
+	.eh_device_reset_handler	= sas_eh_device_reset_handler,
+	.eh_bus_reset_handler	= sas_eh_bus_reset_handler,
 };
 
 static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha)
@@ -234,7 +240,7 @@
 	}
 	/* Provide some sane default values. */
 	asd_ha->hw_prof.max_scbs = 512;
-	asd_ha->hw_prof.max_ddbs = 128;
+	asd_ha->hw_prof.max_ddbs = ASD_MAX_DDBS;
 	asd_ha->hw_prof.num_phys = ASD_MAX_PHYS;
 	/* All phys are enabled, by default. */
 	asd_ha->hw_prof.enabled_phys = 0xFF;
@@ -526,6 +532,7 @@
 	asd_ha->sas_ha.num_phys= ASD_MAX_PHYS;
 
 	asd_ha->sas_ha.lldd_queue_size = asd_ha->seq.can_queue;
+	asd_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num;
 
 	return sas_register_ha(&asd_ha->sas_ha);
 }
@@ -646,7 +653,7 @@
 	if (use_msi)
 		pci_enable_msi(asd_ha->pcidev);
 
-	err = request_irq(asd_ha->pcidev->irq, asd_hw_isr, SA_SHIRQ,
+	err = request_irq(asd_ha->pcidev->irq, asd_hw_isr, IRQF_SHARED,
 			  ASD_DRIVER_NAME, asd_ha);
 	if (err) {
 		asd_printk("couldn't get irq %d for %s\n",
@@ -671,21 +678,10 @@
 	if (err)
 		goto Err_reg_sas;
 
-	err = asd_enable_phys(asd_ha, asd_ha->hw_prof.enabled_phys);
-	if (err) {
-		asd_printk("coudln't enable phys, err:%d\n", err);
-		goto Err_en_phys;
-	}
-	ASD_DPRINTK("enabled phys\n");
-	/* give the phy enabling interrupt event time to come in (1s
-	 * is empirically about all it takes) */
-	ssleep(1);
-	/* Wait for discovery to finish */
-	scsi_flush_work(asd_ha->sas_ha.core.shost);
+	scsi_scan_host(shost);
 
 	return 0;
-Err_en_phys:
-	asd_unregister_sas_ha(asd_ha);
+
 Err_reg_sas:
 	asd_remove_dev_attrs(asd_ha);
 Err_dev_attrs:
@@ -778,6 +774,28 @@
 	return;
 }
 
+static void asd_scan_start(struct Scsi_Host *shost)
+{
+	struct asd_ha_struct *asd_ha;
+	int err;
+
+	asd_ha = SHOST_TO_SAS_HA(shost)->lldd_ha;
+	err = asd_enable_phys(asd_ha, asd_ha->hw_prof.enabled_phys);
+	if (err)
+		asd_printk("Couldn't enable phys, err:%d\n", err);
+}
+
+static int asd_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+	/* give the phy enabling interrupt event time to come in (1s
+	 * is empirically about all it takes) */
+	if (time < HZ)
+		return 0;
+	/* Wait for discovery to finish */
+	scsi_flush_work(shost);
+	return 1;
+}
+
 static ssize_t asd_version_show(struct device_driver *driver, char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%s\n", ASD_DRIVER_VERSION);
@@ -885,6 +903,7 @@
 	asd_remove_driver_attrs(&aic94xx_pci_driver.driver);
 	pci_unregister_driver(&aic94xx_pci_driver);
 	sas_release_transport(aic94xx_transport_template);
+	asd_release_firmware();
 	asd_destroy_global_caches();
 	asd_printk("%s version %s unloaded\n", ASD_DRIVER_DESCRIPTION,
 		   ASD_DRIVER_VERSION);
diff --git a/drivers/scsi/aic94xx/aic94xx_reg_def.h b/drivers/scsi/aic94xx/aic94xx_reg_def.h
index a11f4e6..a43e8cd 100644
--- a/drivers/scsi/aic94xx/aic94xx_reg_def.h
+++ b/drivers/scsi/aic94xx/aic94xx_reg_def.h
@@ -2226,9 +2226,10 @@
 #define LmSEQ_SAS_RESET_MODE(LinkNum)		(LmSCRATCH(LinkNum) + 0x0074)
 #define LmSEQ_LINK_RESET_RETRY_COUNT(LinkNum)	(LmSCRATCH(LinkNum) + 0x0075)
 #define LmSEQ_NUM_LINK_RESET_RETRIES(LinkNum)	(LmSCRATCH(LinkNum) + 0x0076)
-#define LmSEQ_OOB_INT_ENABLES(LinkNum)		(LmSCRATCH(LinkNum) + 0x007A)
+#define LmSEQ_OOB_INT_ENABLES(LinkNum)		(LmSCRATCH(LinkNum) + 0x0078)
+#define LmSEQ_NOTIFY_TIMER_DOWN_COUNT(LinkNum)	(LmSCRATCH(LinkNum) + 0x007A)
 #define LmSEQ_NOTIFY_TIMER_TIMEOUT(LinkNum)	(LmSCRATCH(LinkNum) + 0x007C)
-#define LmSEQ_NOTIFY_TIMER_DOWN_COUNT(LinkNum)	(LmSCRATCH(LinkNum) + 0x007E)
+#define LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(LinkNum) (LmSCRATCH(LinkNum) + 0x007E)
 
 /* Mode dependent scratch page 1, mode 0 and mode 1 */
 #define LmSEQ_SG_LIST_PTR_ADDR0(LinkNum)        (LmSCRATCH(LinkNum) + 0x0020)
diff --git a/drivers/scsi/aic94xx/aic94xx_sas.h b/drivers/scsi/aic94xx/aic94xx_sas.h
index 9050e93..fa7c529 100644
--- a/drivers/scsi/aic94xx/aic94xx_sas.h
+++ b/drivers/scsi/aic94xx/aic94xx_sas.h
@@ -34,6 +34,7 @@
  * domain that this sequencer can maintain low-level connections for
  * us.  They are be 64 bytes.
  */
+#define ASD_MAX_DDBS	128
 
 struct asd_ddb_ssp_smp_target_port {
 	u8     conn_type;	  /* byte 0 */
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index 75ed6b0..8f43ff7 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -413,40 +413,6 @@
 	}
 }
 
-/* hard reset a phy later */
-static void do_phy_reset_later(struct work_struct *work)
-{
-	struct sas_phy *sas_phy =
-		container_of(work, struct sas_phy, reset_work);
-	int error;
-
-	ASD_DPRINTK("%s: About to hard reset phy %d\n", __FUNCTION__,
-		    sas_phy->identify.phy_identifier);
-	/* Reset device port */
-	error = sas_phy_reset(sas_phy, 1);
-	if (error)
-		ASD_DPRINTK("%s: Hard reset of phy %d failed (%d).\n",
-			    __FUNCTION__, sas_phy->identify.phy_identifier, error);
-}
-
-static void phy_reset_later(struct sas_phy *sas_phy, struct Scsi_Host *shost)
-{
-	INIT_WORK(&sas_phy->reset_work, do_phy_reset_later);
-	queue_work(shost->work_q, &sas_phy->reset_work);
-}
-
-/* start up the ABORT TASK tmf... */
-static void task_kill_later(struct asd_ascb *ascb)
-{
-	struct asd_ha_struct *asd_ha = ascb->ha;
-	struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
-	struct Scsi_Host *shost = sas_ha->core.shost;
-	struct sas_task *task = ascb->uldd_task;
-
-	INIT_WORK(&task->abort_work, sas_task_abort);
-	queue_work(shost->work_q, &task->abort_work);
-}
-
 static void escb_tasklet_complete(struct asd_ascb *ascb,
 				  struct done_list_struct *dl)
 {
@@ -479,26 +445,55 @@
 	case REQ_TASK_ABORT: {
 		struct asd_ascb *a, *b;
 		u16 tc_abort;
-
-		tc_abort = *((u16*)(&dl->status_block[1]));
-		tc_abort = le16_to_cpu(tc_abort);
+		struct domain_device *failed_dev = NULL;
 
 		ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n",
 			    __FUNCTION__, dl->status_block[3]);
 
-		/* Find the pending task and abort it. */
-		list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list)
-			if (a->tc_index == tc_abort) {
-				task_kill_later(a);
+		/*
+		 * Find the task that caused the abort and abort it first.
+		 * The sequencer won't put anything on the done list until
+		 * that happens.
+		 */
+		tc_abort = *((u16*)(&dl->status_block[1]));
+		tc_abort = le16_to_cpu(tc_abort);
+
+		list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
+			struct sas_task *task = ascb->uldd_task;
+
+			if (task && a->tc_index == tc_abort) {
+				failed_dev = task->dev;
+				sas_task_abort(task);
 				break;
 			}
+		}
+
+		if (!failed_dev) {
+			ASD_DPRINTK("%s: Can't find task (tc=%d) to abort!\n",
+				    __FUNCTION__, tc_abort);
+			goto out;
+		}
+
+		/*
+		 * Now abort everything else for that device (hba?) so
+		 * that the EH will wake up and do something.
+		 */
+		list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
+			struct sas_task *task = ascb->uldd_task;
+
+			if (task &&
+			    task->dev == failed_dev &&
+			    a->tc_index != tc_abort)
+				sas_task_abort(task);
+		}
+
 		goto out;
 	}
 	case REQ_DEVICE_RESET: {
-		struct Scsi_Host *shost = sas_ha->core.shost;
-		struct sas_phy *dev_phy;
 		struct asd_ascb *a;
 		u16 conn_handle;
+		unsigned long flags;
+		struct sas_task *last_dev_task = NULL;
 
 		conn_handle = *((u16*)(&dl->status_block[1]));
 		conn_handle = le16_to_cpu(conn_handle);
@@ -506,32 +501,47 @@
 		ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__,
 			    dl->status_block[3]);
 
-		/* Kill all pending tasks and reset the device */
-		dev_phy = NULL;
+		/* Find the last pending task for the device... */
 		list_for_each_entry(a, &asd_ha->seq.pend_q, list) {
-			struct sas_task *task;
-			struct domain_device *dev;
 			u16 x;
+			struct domain_device *dev;
+			struct sas_task *task = a->uldd_task;
 
-			task = a->uldd_task;
 			if (!task)
 				continue;
 			dev = task->dev;
 
 			x = (unsigned long)dev->lldd_dev;
-			if (x == conn_handle) {
-				dev_phy = dev->port->phy;
-				task_kill_later(a);
-			}
+			if (x == conn_handle)
+				last_dev_task = task;
 		}
 
-		/* Reset device port */
-		if (!dev_phy) {
-			ASD_DPRINTK("%s: No pending commands; can't reset.\n",
-				    __FUNCTION__);
+		if (!last_dev_task) {
+			ASD_DPRINTK("%s: Device reset for idle device %d?\n",
+				    __FUNCTION__, conn_handle);
 			goto out;
 		}
-		phy_reset_later(dev_phy, shost);
+
+		/* ...and set the reset flag */
+		spin_lock_irqsave(&last_dev_task->task_state_lock, flags);
+		last_dev_task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
+		spin_unlock_irqrestore(&last_dev_task->task_state_lock, flags);
+
+		/* Kill all pending tasks for the device */
+		list_for_each_entry(a, &asd_ha->seq.pend_q, list) {
+			u16 x;
+			struct domain_device *dev;
+			struct sas_task *task = a->uldd_task;
+
+			if (!task)
+				continue;
+			dev = task->dev;
+
+			x = (unsigned long)dev->lldd_dev;
+			if (x == conn_handle)
+				sas_task_abort(task);
+		}
+
 		goto out;
 	}
 	case SIGNAL_NCQ_ERROR:
diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c
index e5a0ec3..5b0932f 100644
--- a/drivers/scsi/aic94xx/aic94xx_sds.c
+++ b/drivers/scsi/aic94xx/aic94xx_sds.c
@@ -427,7 +427,7 @@
 
 struct asd_manuf_phy_desc {
 	u8    state;         /* low 4 bits */
-#define MS_PHY_STATE_ENABLEABLE 0
+#define MS_PHY_STATE_ENABLED    0
 #define MS_PHY_STATE_REPORTED   1
 #define MS_PHY_STATE_HIDDEN     2
 	u8    phy_id;
@@ -756,11 +756,11 @@
  *
  * HIDDEN phys do not count in the total count.  REPORTED phys cannot
  * be enabled but are reported and counted towards the total.
- * ENEBLEABLE phys are enabled by default and count towards the total.
+ * ENABLED phys are enabled by default and count towards the total.
  * The absolute total phy number is ASD_MAX_PHYS.  hw_prof->num_phys
  * merely specifies the number of phys the host adapter decided to
  * report.  E.g., it is possible for phys 0, 1 and 2 to be HIDDEN,
- * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENEBLEABLE.
+ * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENABLED.
  * In this case ASD_MAX_PHYS is 8, hw_prof->num_phys is 5, and only 2
  * are actually enabled (enabled by default, max number of phys
  * enableable in this case).
@@ -816,8 +816,8 @@
 			asd_ha->hw_prof.enabled_phys &= ~(1 << i);
 			rep_phys++;
 			continue;
-		case MS_PHY_STATE_ENABLEABLE:
-			ASD_DPRINTK("ms: phy%d: ENEBLEABLE\n", i);
+		case MS_PHY_STATE_ENABLED:
+			ASD_DPRINTK("ms: phy%d: ENABLED\n", i);
 			asd_ha->hw_prof.enabled_phys |= (1 << i);
 			en_phys++;
 			break;
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c
index 8451125..c750fbf 100644
--- a/drivers/scsi/aic94xx/aic94xx_seq.c
+++ b/drivers/scsi/aic94xx/aic94xx_seq.c
@@ -44,7 +44,6 @@
 #define PAUSE_TRIES 1000
 
 static const struct firmware *sequencer_fw;
-static const char *sequencer_version;
 static u16 cseq_vecs[CSEQ_NUM_VECS], lseq_vecs[LSEQ_NUM_VECS], mode2_task,
 	cseq_idle_loop, lseq_idle_loop;
 static u8 *cseq_code, *lseq_code;
@@ -810,6 +809,8 @@
 	/* No delay for the first NOTIFY to be sent to the attached target. */
 	asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_DOWN_COUNT(lseq),
 			   ASD_NOTIFY_DOWN_COUNT);
+	asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(lseq),
+			   ASD_NOTIFY_DOWN_COUNT);
 
 	/* LSEQ Mode dependent, mode 0 and 1, page 1 setup. */
 	for (i = 0; i < 2; i++)	{
@@ -907,6 +908,16 @@
 		for (i = 0; i < ASD_SCB_SIZE; i += 4)
 			asd_scbsite_write_dword(asd_ha, site_no, i, 0);
 
+		/* Initialize SCB Site Opcode field to invalid. */
+		asd_scbsite_write_byte(asd_ha, site_no,
+				       offsetof(struct scb_header, opcode),
+				       0xFF);
+
+		/* Initialize SCB Site Flags field to mean a response
+		 * frame has been received.  This means inadvertent
+		 * frames received to be dropped. */
+		asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01);
+
 		/* Workaround needed by SEQ to fix a SATA issue is to exclude
 		 * certain SCB sites from the free list. */
 		if (!SCB_SITE_VALID(site_no))
@@ -922,16 +933,6 @@
 		/* Q_NEXT field of the last SCB is invalidated. */
 		asd_scbsite_write_word(asd_ha, site_no, 0, first_scb_site_no);
 
-		/* Initialize SCB Site Opcode field to invalid. */
-		asd_scbsite_write_byte(asd_ha, site_no,
-				       offsetof(struct scb_header, opcode),
-				       0xFF);
-
-		/* Initialize SCB Site Flags field to mean a response
-		 * frame has been received.  This means inadvertent
-		 * frames received to be dropped. */
-		asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01);
-
 		first_scb_site_no = site_no;
 		max_scbs++;
 	}
@@ -1173,6 +1174,16 @@
 	set_bit(0, asd_ha->hw_prof.ddb_bitmap);
 }
 
+static void asd_seq_init_ddb_sites(struct asd_ha_struct *asd_ha)
+{
+	unsigned int i;
+	unsigned int ddb_site;
+
+	for (ddb_site = 0 ; ddb_site < ASD_MAX_DDBS; ddb_site++)
+		for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4)
+			asd_ddbsite_write_dword(asd_ha, ddb_site, i, 0);
+}
+
 /**
  * asd_seq_setup_seqs -- setup and initialize central and link sequencers
  * @asd_ha: pointer to host adapter structure
@@ -1182,6 +1193,9 @@
 	int 		lseq;
 	u8		lseq_mask;
 
+	/* Initialize DDB sites */
+	asd_seq_init_ddb_sites(asd_ha);
+
 	/* Initialize SCB sites. Done first to compute some values which
 	 * the rest of the init code depends on. */
 	asd_init_scb_sites(asd_ha);
@@ -1232,6 +1246,13 @@
 	return asd_seq_unpause_lseq(asd_ha, lseq);
 }
 
+int asd_release_firmware(void)
+{
+	if (sequencer_fw)
+		release_firmware(sequencer_fw);
+	return 0;
+}
+
 static int asd_request_firmware(struct asd_ha_struct *asd_ha)
 {
 	int err, i;
@@ -1254,7 +1275,6 @@
 	header.csum = le32_to_cpu(hdr_ptr->csum);
 	header.major = le32_to_cpu(hdr_ptr->major);
 	header.minor = le32_to_cpu(hdr_ptr->minor);
-	sequencer_version = hdr_ptr->version;
 	header.cseq_table_offset = le32_to_cpu(hdr_ptr->cseq_table_offset);
 	header.cseq_table_size = le32_to_cpu(hdr_ptr->cseq_table_size);
 	header.lseq_table_offset = le32_to_cpu(hdr_ptr->lseq_table_offset);
@@ -1281,6 +1301,16 @@
 		return -EINVAL;
 	}
 
+	asd_printk("Found sequencer Firmware version %d.%d (%s)\n",
+		   header.major, header.minor, hdr_ptr->version);
+
+	if (header.major != SAS_RAZOR_SEQUENCER_FW_MAJOR) {
+		asd_printk("Firmware Major Version Mismatch;"
+			   "driver requires version %d.X",
+			   SAS_RAZOR_SEQUENCER_FW_MAJOR);
+		return -EINVAL;
+	}
+
 	ptr_cseq_vecs = (u16 *)&sequencer_fw->data[header.cseq_table_offset];
 	ptr_lseq_vecs = (u16 *)&sequencer_fw->data[header.lseq_table_offset];
 	mode2_task = header.mode2_task;
@@ -1313,7 +1343,6 @@
 		return err;
 	}
 
-	asd_printk("using sequencer %s\n", sequencer_version);
 	err = asd_seq_download_seqs(asd_ha);
 	if (err) {
 		asd_printk("couldn't download sequencers for %s\n",
@@ -1375,7 +1404,9 @@
 	u8  phy_is_up;
 	u8  mask;
 	int i, err;
+	unsigned long flags;
 
+	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
 	for_each_phy(phy_mask, mask, i)
 		asd_ddbsite_write_byte(asd_ha, 0,
 				       offsetof(struct asd_ddb_seq_shared,
@@ -1395,6 +1426,7 @@
 			break;
 		}
 	}
+	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
 
 	if (err)
 		asd_printk("couldn't update DDB 0:error:%d\n", err);
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.h b/drivers/scsi/aic94xx/aic94xx_seq.h
index 9e715e5..2ea6a0d 100644
--- a/drivers/scsi/aic94xx/aic94xx_seq.h
+++ b/drivers/scsi/aic94xx/aic94xx_seq.h
@@ -31,6 +31,7 @@
 #define LSEQ_NUM_VECS	11
 
 #define SAS_RAZOR_SEQUENCER_FW_FILE "aic94xx-seq.fw"
+#define SAS_RAZOR_SEQUENCER_FW_MAJOR	1
 
 /* Note:  All quantites in the sequencer file are little endian */
 struct sequencer_file_header {
@@ -63,6 +64,7 @@
 int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
 int asd_init_seqs(struct asd_ha_struct *asd_ha);
 int asd_start_seqs(struct asd_ha_struct *asd_ha);
+int asd_release_firmware(void);
 
 void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy);
 #endif
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
index d202ed5..e2ad5be 100644
--- a/drivers/scsi/aic94xx/aic94xx_task.c
+++ b/drivers/scsi/aic94xx/aic94xx_task.c
@@ -349,6 +349,7 @@
 
 	spin_lock_irqsave(&task->task_state_lock, flags);
 	task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+	task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
 	task->task_state_flags |= SAS_TASK_STATE_DONE;
 	if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) {
 		spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -557,6 +558,7 @@
 	struct sas_task *t = task;
 	struct asd_ascb *ascb = NULL, *a;
 	struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
+	unsigned long flags;
 
 	res = asd_can_queue(asd_ha, num);
 	if (res)
@@ -599,6 +601,10 @@
 		}
 		if (res)
 			goto out_err_unmap;
+
+		spin_lock_irqsave(&t->task_state_lock, flags);
+		t->task_state_flags |= SAS_TASK_AT_INITIATOR;
+		spin_unlock_irqrestore(&t->task_state_lock, flags);
 	}
 	list_del_init(&alist);
 
@@ -617,6 +623,9 @@
 			if (a == b)
 				break;
 			t = a->uldd_task;
+			spin_lock_irqsave(&t->task_state_lock, flags);
+			t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+			spin_unlock_irqrestore(&t->task_state_lock, flags);
 			switch (t->task_proto) {
 			case SATA_PROTO:
 			case SAS_PROTO_STP:
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index 6123438..9a14a6d 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -566,9 +566,7 @@
 		res = TMF_RESP_FUNC_ESUPP;
 		break;
 	default:
-		ASD_DPRINTK("%s: converting result 0x%x to TMF_RESP_FUNC_FAILED\n",
-			    __FUNCTION__, res);
-		res = TMF_RESP_FUNC_FAILED;
+		/* Allow TMF response codes to propagate upwards */
 		break;
 	}
 out_err:
diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c
index 9099d53..d5d3c4d 100644
--- a/drivers/scsi/amiga7xx.c
+++ b/drivers/scsi/amiga7xx.c
@@ -10,7 +10,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/zorro.h>
 #include <linux/stat.h>
 
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 086cc97..8b46158 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -322,7 +322,7 @@
 		goto out_iounmap;
 
 	error = request_irq(pdev->irq, arcmsr_do_interrupt,
-			SA_INTERRUPT | SA_SHIRQ, "arcmsr", acb);
+			IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb);
 	if (error)
 		goto out_free_ccb_pool;
 
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 9cf902b..eceacf6 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -131,7 +131,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
index 4385e9e..7e132c5 100644
--- a/drivers/scsi/arm/arxescsi.c
+++ b/drivers/scsi/arm/arxescsi.c
@@ -23,7 +23,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/unistd.h>
 #include <linux/stat.h>
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index 3bdfc36..cf9a21c 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -5,7 +5,6 @@
  */
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 19edd9c..d2d51dc 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -21,7 +21,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c
index 6adcccb..378e7af 100644
--- a/drivers/scsi/arm/ecoscsi.c
+++ b/drivers/scsi/arm/ecoscsi.c
@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/init.h>
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 3f876fb..d413652 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -197,7 +196,7 @@
 	const void __iomem *reg_fas = base + EESOX_FAS216_OFFSET;
 	const void __iomem *reg_dmastat = base + EESOX_DMASTAT;
 	const void __iomem *reg_dmadata = base + EESOX_DMADATA;
-	const register unsigned long mask = 0xffff;
+	register const unsigned long mask = 0xffff;
 
 	do {
 		unsigned int status;
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index e05f0c2..2969cc0 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -39,7 +39,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/bitops.h>
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index d806b02..c21b839 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -6,7 +6,6 @@
 
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index ce159c1..f9cd20b 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index dfb1bcf..642de7b 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -86,7 +86,6 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/nvram.h>
diff --git a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c
index 329a8f2..23f7c24 100644
--- a/drivers/scsi/blz1230.c
+++ b/drivers/scsi/blz1230.c
@@ -121,7 +121,8 @@
 		 */
 		address = ZTWO_VADDR(board);
 		eregs = (struct ESP_regs *)(address + REAL_BLZ1230_ESP_ADDR);
-		esp = esp_allocate(tpnt, (void *)board+REAL_BLZ1230_ESP_ADDR);
+		esp = esp_allocate(tpnt, (void *)board + REAL_BLZ1230_ESP_ADDR,
+				   0);
 
 		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
 		udelay(5);
diff --git a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c
index b6c137b..b6203ec 100644
--- a/drivers/scsi/blz2060.c
+++ b/drivers/scsi/blz2060.c
@@ -100,7 +100,7 @@
 	    unsigned long board = z->resource.start;
 	    if (request_mem_region(board+BLZ2060_ESP_ADDR,
 				   sizeof(struct ESP_regs), "NCR53C9x")) {
-		esp = esp_allocate(tpnt, (void *)board+BLZ2060_ESP_ADDR);
+		esp = esp_allocate(tpnt, (void *)board + BLZ2060_ESP_ADDR, 0);
 
 		/* Do command transfer with programmed I/O */
 		esp->do_pio_cmds = 1;
diff --git a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c
index 2958b8c..599b400 100644
--- a/drivers/scsi/bvme6000.c
+++ b/drivers/scsi/bvme6000.c
@@ -6,7 +6,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/zorro.h>
 
 #include <asm/setup.h>
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index f6caa43..2a2cc6c 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/major.h>
 #include <linux/string.h>
@@ -129,7 +128,7 @@
 	},
 };
 
-static struct file_operations changer_fops =
+static const struct file_operations changer_fops =
 {
 	.owner        = THIS_MODULE,
 	.open         = ch_open,
diff --git a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c
index 7c7cfb5..c6b98a4 100644
--- a/drivers/scsi/cyberstorm.c
+++ b/drivers/scsi/cyberstorm.c
@@ -126,7 +126,7 @@
 					   sizeof(struct ESP_regs));
 			return 0;
 		}
-		esp = esp_allocate(tpnt, (void *)board+CYBER_ESP_ADDR);
+		esp = esp_allocate(tpnt, (void *)board + CYBER_ESP_ADDR, 0);
 
 		/* Do command transfer with programmed I/O */
 		esp->do_pio_cmds = 1;
diff --git a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c
index d88cb9c..e336e85 100644
--- a/drivers/scsi/cyberstormII.c
+++ b/drivers/scsi/cyberstormII.c
@@ -98,7 +98,7 @@
 		address = (unsigned long)ZTWO_VADDR(board);
 		eregs = (struct ESP_regs *)(address + CYBERII_ESP_ADDR);
 
-		esp = esp_allocate(tpnt, (void *)board+CYBERII_ESP_ADDR);
+		esp = esp_allocate(tpnt, (void *)board + CYBERII_ESP_ADDR, 0);
 
 		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
 		udelay(5);
diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c
index c29ccbc..d42ad66 100644
--- a/drivers/scsi/dec_esp.c
+++ b/drivers/scsi/dec_esp.c
@@ -18,7 +18,7 @@
  * 20001005	- Initialization fixes for 2.4.0-test9
  * 			  Florian Lohoff <flo@rfc822.org>
  *
- *	Copyright (C) 2002, 2003, 2005  Maciej W. Rozycki
+ *	Copyright (C) 2002, 2003, 2005, 2006  Maciej W. Rozycki
  */
 
 #include <linux/kernel.h>
@@ -30,6 +30,7 @@
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/stat.h>
+#include <linux/tc.h>
 
 #include <asm/dma.h>
 #include <asm/irq.h>
@@ -42,7 +43,6 @@
 #include <asm/dec/ioasic_ints.h>
 #include <asm/dec/machtype.h>
 #include <asm/dec/system.h>
-#include <asm/dec/tc.h>
 
 #define DEC_SCSI_SREG 0
 #define DEC_SCSI_DMAREG 0x40000
@@ -98,51 +98,33 @@
 static irqreturn_t scsi_dma_err_int(int, void *);
 static irqreturn_t scsi_dma_int(int, void *);
 
-static int dec_esp_detect(struct scsi_host_template * tpnt);
-
-static int dec_esp_release(struct Scsi_Host *shost)
-{
-	if (shost->irq)
-		free_irq(shost->irq, NULL);
-	if (shost->io_port && shost->n_io_port)
-		release_region(shost->io_port, shost->n_io_port);
-	scsi_unregister(shost);
-	return 0;
-}
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "dec_esp",
-	.proc_info		= esp_proc_info,
+static struct scsi_host_template dec_esp_template = {
+	.module			= THIS_MODULE,
 	.name			= "NCR53C94",
-	.detect			= dec_esp_detect,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.release		= dec_esp_release,
 	.info			= esp_info,
 	.queuecommand		= esp_queue,
 	.eh_abort_handler	= esp_abort,
 	.eh_bus_reset_handler	= esp_reset,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
+	.proc_info		= esp_proc_info,
+	.proc_name		= "dec_esp",
 	.can_queue		= 7,
-	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
 	.cmd_per_lun		= 1,
 	.use_clustering		= DISABLE_CLUSTERING,
 };
 
-
-#include "scsi_module.c"
+static struct NCR_ESP *dec_esp_platform;
 
 /***************************************************************** Detection */
-static int dec_esp_detect(struct scsi_host_template * tpnt)
+static int dec_esp_platform_probe(void)
 {
 	struct NCR_ESP *esp;
-	struct ConfigDev *esp_dev;
-	int slot;
-	unsigned long mem_start;
+	int err = 0;
 
 	if (IOASIC) {
-		esp_dev = 0;
-		esp = esp_allocate(tpnt, (void *) esp_dev);
+		esp = esp_allocate(&dec_esp_template, NULL, 1);
 
 		/* Do command transfer with programmed I/O */
 		esp->do_pio_cmds = 1;
@@ -200,112 +182,175 @@
 		/* Check for differential SCSI-bus */
 		esp->diff = 0;
 
+		err = request_irq(esp->irq, esp_intr, IRQF_DISABLED,
+				  "ncr53c94", esp->ehost);
+		if (err)
+			goto err_alloc;
+		err = request_irq(dec_interrupt[DEC_IRQ_ASC_MERR],
+				  scsi_dma_merr_int, IRQF_DISABLED,
+				  "ncr53c94 error", esp->ehost);
+		if (err)
+			goto err_irq;
+		err = request_irq(dec_interrupt[DEC_IRQ_ASC_ERR],
+				  scsi_dma_err_int, IRQF_DISABLED,
+				  "ncr53c94 overrun", esp->ehost);
+		if (err)
+			goto err_irq_merr;
+		err = request_irq(dec_interrupt[DEC_IRQ_ASC_DMA], scsi_dma_int,
+				  IRQF_DISABLED, "ncr53c94 dma", esp->ehost);
+		if (err)
+			goto err_irq_err;
+
 		esp_initialize(esp);
 
-		if (request_irq(esp->irq, esp_intr, IRQF_DISABLED,
-				"ncr53c94", esp->ehost))
-			goto err_dealloc;
-		if (request_irq(dec_interrupt[DEC_IRQ_ASC_MERR],
-				scsi_dma_merr_int, IRQF_DISABLED,
-				"ncr53c94 error", esp->ehost))
-			goto err_free_irq;
-		if (request_irq(dec_interrupt[DEC_IRQ_ASC_ERR],
-				scsi_dma_err_int, IRQF_DISABLED,
-				"ncr53c94 overrun", esp->ehost))
-			goto err_free_irq_merr;
-		if (request_irq(dec_interrupt[DEC_IRQ_ASC_DMA],
-				scsi_dma_int, IRQF_DISABLED,
-				"ncr53c94 dma", esp->ehost))
-			goto err_free_irq_err;
-
-	}
-
-	if (TURBOCHANNEL) {
-		while ((slot = search_tc_card("PMAZ-AA")) >= 0) {
-			claim_tc_card(slot);
-
-			esp_dev = 0;
-			esp = esp_allocate(tpnt, (void *) esp_dev);
-
-			mem_start = get_tc_base_addr(slot);
-
-			/* Store base addr into esp struct */
-			esp->slot = CPHYSADDR(mem_start);
-
-			esp->dregs = 0;
-			esp->eregs = (void *)CKSEG1ADDR(mem_start +
-							DEC_SCSI_SREG);
-			esp->do_pio_cmds = 1;
-
-			/* Set the command buffer */
-			esp->esp_command = (volatile unsigned char *) pmaz_cmd_buffer;
-
-			/* get virtual dma address for command buffer */
-			esp->esp_command_dvma = virt_to_phys(pmaz_cmd_buffer);
-
-			esp->cfreq = get_tc_speed();
-
-			esp->irq = get_tc_irq_nr(slot);
-
-			/* Required functions */
-			esp->dma_bytes_sent = &dma_bytes_sent;
-			esp->dma_can_transfer = &dma_can_transfer;
-			esp->dma_dump_state = &dma_dump_state;
-			esp->dma_init_read = &pmaz_dma_init_read;
-			esp->dma_init_write = &pmaz_dma_init_write;
-			esp->dma_ints_off = &pmaz_dma_ints_off;
-			esp->dma_ints_on = &pmaz_dma_ints_on;
-			esp->dma_irq_p = &dma_irq_p;
-			esp->dma_ports_p = &dma_ports_p;
-			esp->dma_setup = &pmaz_dma_setup;
-
-			/* Optional functions */
-			esp->dma_barrier = 0;
-			esp->dma_drain = &pmaz_dma_drain;
-			esp->dma_invalidate = 0;
-			esp->dma_irq_entry = 0;
-			esp->dma_irq_exit = 0;
-			esp->dma_poll = 0;
-			esp->dma_reset = 0;
-			esp->dma_led_off = 0;
-			esp->dma_led_on = 0;
-
-			esp->dma_mmu_get_scsi_one = pmaz_dma_mmu_get_scsi_one;
-			esp->dma_mmu_get_scsi_sgl = 0;
-			esp->dma_mmu_release_scsi_one = 0;
-			esp->dma_mmu_release_scsi_sgl = 0;
-			esp->dma_advance_sg = 0;
-
- 			if (request_irq(esp->irq, esp_intr, IRQF_DISABLED,
- 					 "PMAZ_AA", esp->ehost)) {
- 				esp_deallocate(esp);
- 				release_tc_card(slot);
- 				continue;
- 			}
-			esp->scsi_id = 7;
-			esp->diff = 0;
-			esp_initialize(esp);
+		err = scsi_add_host(esp->ehost, NULL);
+		if (err) {
+			printk(KERN_ERR "ESP: Unable to register adapter\n");
+			goto err_irq_dma;
 		}
+
+		scsi_scan_host(esp->ehost);
+
+		dec_esp_platform = esp;
 	}
 
-	if(nesps) {
-		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
-		esps_running = esps_in_use;
-		return esps_in_use;
-	}
 	return 0;
 
-err_free_irq_err:
-	free_irq(dec_interrupt[DEC_IRQ_ASC_ERR], scsi_dma_err_int);
-err_free_irq_merr:
-	free_irq(dec_interrupt[DEC_IRQ_ASC_MERR], scsi_dma_merr_int);
-err_free_irq:
-	free_irq(esp->irq, esp_intr);
-err_dealloc:
+err_irq_dma:
+	free_irq(dec_interrupt[DEC_IRQ_ASC_DMA], esp->ehost);
+err_irq_err:
+	free_irq(dec_interrupt[DEC_IRQ_ASC_ERR], esp->ehost);
+err_irq_merr:
+	free_irq(dec_interrupt[DEC_IRQ_ASC_MERR], esp->ehost);
+err_irq:
+	free_irq(esp->irq, esp->ehost);
+err_alloc:
 	esp_deallocate(esp);
-	return 0;
+	scsi_host_put(esp->ehost);
+	return err;
 }
 
+static int __init dec_esp_probe(struct device *dev)
+{
+	struct NCR_ESP *esp;
+	resource_size_t start, len;
+	int err;
+
+	esp = esp_allocate(&dec_esp_template,  NULL, 1);
+
+	dev_set_drvdata(dev, esp);
+
+	start = to_tc_dev(dev)->resource.start;
+	len = to_tc_dev(dev)->resource.end - start + 1;
+
+	if (!request_mem_region(start, len, dev->bus_id)) {
+		printk(KERN_ERR "%s: Unable to reserve MMIO resource\n",
+		       dev->bus_id);
+		err = -EBUSY;
+		goto err_alloc;
+	}
+
+	/* Store base addr into esp struct.  */
+	esp->slot = start;
+
+	esp->dregs = 0;
+	esp->eregs = (void *)CKSEG1ADDR(start + DEC_SCSI_SREG);
+	esp->do_pio_cmds = 1;
+
+	/* Set the command buffer.  */
+	esp->esp_command = (volatile unsigned char *)pmaz_cmd_buffer;
+
+	/* Get virtual dma address for command buffer.  */
+	esp->esp_command_dvma = virt_to_phys(pmaz_cmd_buffer);
+
+	esp->cfreq = tc_get_speed(to_tc_dev(dev)->bus);
+
+	esp->irq = to_tc_dev(dev)->interrupt;
+
+	/* Required functions.  */
+	esp->dma_bytes_sent = &dma_bytes_sent;
+	esp->dma_can_transfer = &dma_can_transfer;
+	esp->dma_dump_state = &dma_dump_state;
+	esp->dma_init_read = &pmaz_dma_init_read;
+	esp->dma_init_write = &pmaz_dma_init_write;
+	esp->dma_ints_off = &pmaz_dma_ints_off;
+	esp->dma_ints_on = &pmaz_dma_ints_on;
+	esp->dma_irq_p = &dma_irq_p;
+	esp->dma_ports_p = &dma_ports_p;
+	esp->dma_setup = &pmaz_dma_setup;
+
+	/* Optional functions.  */
+	esp->dma_barrier = 0;
+	esp->dma_drain = &pmaz_dma_drain;
+	esp->dma_invalidate = 0;
+	esp->dma_irq_entry = 0;
+	esp->dma_irq_exit = 0;
+	esp->dma_poll = 0;
+	esp->dma_reset = 0;
+	esp->dma_led_off = 0;
+	esp->dma_led_on = 0;
+
+	esp->dma_mmu_get_scsi_one = pmaz_dma_mmu_get_scsi_one;
+	esp->dma_mmu_get_scsi_sgl = 0;
+	esp->dma_mmu_release_scsi_one = 0;
+	esp->dma_mmu_release_scsi_sgl = 0;
+	esp->dma_advance_sg = 0;
+
+	err = request_irq(esp->irq, esp_intr, IRQF_DISABLED, "PMAZ_AA",
+			  esp->ehost);
+	if (err) {
+		printk(KERN_ERR "%s: Unable to get IRQ %d\n",
+		       dev->bus_id, esp->irq);
+		goto err_resource;
+	}
+
+	esp->scsi_id = 7;
+	esp->diff = 0;
+	esp_initialize(esp);
+
+	err = scsi_add_host(esp->ehost, dev);
+	if (err) {
+		printk(KERN_ERR "%s: Unable to register adapter\n",
+		       dev->bus_id);
+		goto err_irq;
+	}
+
+	scsi_scan_host(esp->ehost);
+
+	return 0;
+
+err_irq:
+	free_irq(esp->irq, esp->ehost);
+
+err_resource:
+	release_mem_region(start, len);
+
+err_alloc:
+	esp_deallocate(esp);
+	scsi_host_put(esp->ehost);
+	return err;
+}
+
+static void __exit dec_esp_platform_remove(void)
+{
+	struct NCR_ESP *esp = dec_esp_platform;
+
+	free_irq(esp->irq, esp->ehost);
+	esp_deallocate(esp);
+	scsi_host_put(esp->ehost);
+	dec_esp_platform = NULL;
+}
+
+static void __exit dec_esp_remove(struct device *dev)
+{
+	struct NCR_ESP *esp = dev_get_drvdata(dev);
+
+	free_irq(esp->irq, esp->ehost);
+	esp_deallocate(esp);
+	scsi_host_put(esp->ehost);
+}
+
+
 /************************************************************* DMA Functions */
 static irqreturn_t scsi_dma_merr_int(int irq, void *dev_id)
 {
@@ -576,3 +621,67 @@
 {
 	sp->SCp.ptr = (char *)virt_to_phys(sp->request_buffer);
 }
+
+
+#ifdef CONFIG_TC
+static int __init dec_esp_tc_probe(struct device *dev);
+static int __exit dec_esp_tc_remove(struct device *dev);
+
+static const struct tc_device_id dec_esp_tc_table[] = {
+        { "DEC     ", "PMAZ-AA " },
+        { }
+};
+MODULE_DEVICE_TABLE(tc, dec_esp_tc_table);
+
+static struct tc_driver dec_esp_tc_driver = {
+        .id_table       = dec_esp_tc_table,
+        .driver         = {
+                .name   = "dec_esp",
+                .bus    = &tc_bus_type,
+                .probe  = dec_esp_tc_probe,
+                .remove = __exit_p(dec_esp_tc_remove),
+        },
+};
+
+static int __init dec_esp_tc_probe(struct device *dev)
+{
+	int status = dec_esp_probe(dev);
+	if (!status)
+		get_device(dev);
+	return status;
+}
+
+static int __exit dec_esp_tc_remove(struct device *dev)
+{
+	put_device(dev);
+	dec_esp_remove(dev);
+	return 0;
+}
+#endif
+
+static int __init dec_esp_init(void)
+{
+	int status;
+
+	status = tc_register_driver(&dec_esp_tc_driver);
+	if (!status)
+		dec_esp_platform_probe();
+
+	if (nesps) {
+		pr_info("ESP: Total of %d ESP hosts found, "
+			"%d actually in use.\n", nesps, esps_in_use);
+		esps_running = esps_in_use;
+	}
+
+	return status;
+}
+
+static void __exit dec_esp_exit(void)
+{
+	dec_esp_platform_remove();
+	tc_unregister_driver(&dec_esp_tc_driver);
+}
+
+
+module_init(dec_esp_init);
+module_exit(dec_esp_exit);
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 365db53..cd36e81 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -116,7 +116,7 @@
 static adpt_hba* hba_chain = NULL;
 static int hba_count = 0;
 
-static struct file_operations adpt_fops = {
+static const struct file_operations adpt_fops = {
 	.ioctl		= adpt_ioctl,
 	.open		= adpt_open,
 	.release	= adpt_close
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index 5475672..9d52e45 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -75,7 +75,6 @@
 #include <asm/system.h>
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/stat.h>
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index 2dbb66d..f33ad01 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -48,7 +48,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
diff --git a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c
index 2a1c5c2..4266a21 100644
--- a/drivers/scsi/fastlane.c
+++ b/drivers/scsi/fastlane.c
@@ -142,7 +142,7 @@
 		if (board < 0x1000000) {
 			goto err_release;
 		}
-		esp = esp_allocate(tpnt, (void *)board+FASTLANE_ESP_ADDR);
+		esp = esp_allocate(tpnt, (void *)board + FASTLANE_ESP_ADDR, 0);
 
 		/* Do command transfer with programmed I/O */
 		esp->do_pio_cmds = 1;
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index cdd893b..880f70d 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -103,7 +103,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/blkdev.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 4c698a7..8c81cec 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -387,7 +387,6 @@
 #include <linux/ctype.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/proc_fs.h>
@@ -687,7 +686,7 @@
 MODULE_LICENSE("GPL");
 
 /* ioctl interface */
-static struct file_operations gdth_fops = {
+static const struct file_operations gdth_fops = {
     .ioctl   = gdth_ioctl,
     .open    = gdth_open,
     .release = gdth_close,
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index 2f6c113..37741e9 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -1,7 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
index e28260f..4368ca0 100644
--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
+++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
@@ -580,7 +580,7 @@
 	}
 
 	err = request_irq(vport->dma_dev->irq, &ibmvstgt_interrupt,
-			  SA_INTERRUPT, "ibmvstgt", target);
+			  IRQF_DISABLED, "ibmvstgt", target);
 	if (err)
 		goto req_irq_failed;
 
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 8f6b5bf..2b5b8a9 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -801,15 +801,10 @@
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct ide_scsi_obj *scsi;
-	ide_drive_t *drive;
 
 	if (!(scsi = ide_scsi_get(disk)))
 		return -ENXIO;
 
-	drive = scsi->drive;
-
-	drive->usage++;
-
 	return 0;
 }
 
@@ -817,9 +812,6 @@
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct ide_scsi_obj *scsi = ide_scsi_g(disk);
-	ide_drive_t *drive = scsi->drive;
-
-	drive->usage--;
 
 	ide_scsi_put(scsi);
 
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index d561663..7e7635c 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -123,7 +123,6 @@
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/dma-mapping.h>
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 821386c..95045e3 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -595,10 +595,8 @@
 {
 	int pcix_cmd_reg = pci_find_capability(ioa_cfg->pdev, PCI_CAP_ID_PCIX);
 
-	if (pcix_cmd_reg == 0) {
-		dev_err(&ioa_cfg->pdev->dev, "Failed to save PCI-X command register\n");
-		return -EIO;
-	}
+	if (pcix_cmd_reg == 0)
+		return 0;
 
 	if (pci_read_config_word(ioa_cfg->pdev, pcix_cmd_reg + PCI_X_CMD,
 				 &ioa_cfg->saved_pcix_cmd_reg) != PCIBIOS_SUCCESSFUL) {
@@ -627,10 +625,6 @@
 			dev_err(&ioa_cfg->pdev->dev, "Failed to setup PCI-X command register\n");
 			return -EIO;
 		}
-	} else {
-		dev_err(&ioa_cfg->pdev->dev,
-			"Failed to setup PCI-X command register\n");
-		return -EIO;
 	}
 
 	return 0;
@@ -6314,7 +6308,6 @@
 	int rc;
 
 	ENTER;
-	pci_unblock_user_cfg_access(ioa_cfg->pdev);
 	rc = pci_restore_state(ioa_cfg->pdev);
 
 	if (rc != PCIBIOS_SUCCESSFUL) {
@@ -6355,6 +6348,24 @@
 }
 
 /**
+ * ipr_reset_bist_done - BIST has completed on the adapter.
+ * @ipr_cmd:	ipr command struct
+ *
+ * Description: Unblock config space and resume the reset process.
+ *
+ * Return value:
+ * 	IPR_RC_JOB_CONTINUE
+ **/
+static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd)
+{
+	ENTER;
+	pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
+	ipr_cmd->job_step = ipr_reset_restore_cfg_space;
+	LEAVE;
+	return IPR_RC_JOB_CONTINUE;
+}
+
+/**
  * ipr_reset_start_bist - Run BIST on the adapter.
  * @ipr_cmd:	ipr command struct
  *
@@ -6376,7 +6387,7 @@
 		ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
 		rc = IPR_RC_JOB_CONTINUE;
 	} else {
-		ipr_cmd->job_step = ipr_reset_restore_cfg_space;
+		ipr_cmd->job_step = ipr_reset_bist_done;
 		ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
 		rc = IPR_RC_JOB_RETURN;
 	}
@@ -7166,9 +7177,6 @@
 {
 	int i;
 
-	if (dev_id->driver_data)
-		return (const struct ipr_chip_cfg_t *)dev_id->driver_data;
-
 	for (i = 0; i < ARRAY_SIZE(ipr_chip); i++)
 		if (ipr_chip[i].vendor == dev_id->vendor &&
 		    ipr_chip[i].device == dev_id->device)
@@ -7517,62 +7525,43 @@
 
 static struct pci_device_id ipr_pci_table[] __devinitdata = {
 	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702, 0, 0, 0 },
 	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5703,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5703, 0, 0, 0 },
 	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D, 0, 0, 0 },
 	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573E,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573E, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572E,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572E, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, ipr_pci_table);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 9f62a1d..88f285d 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -37,8 +37,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.3.0"
-#define IPR_DRIVER_DATE "(November 8, 2006)"
+#define IPR_DRIVER_VERSION "2.3.1"
+#define IPR_DRIVER_DATE "(January 23, 2007)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 4376840..8f55e14 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1375,7 +1375,7 @@
 	}
 
 	BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE);
-	if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
+	if (mtask->hdr->itt == RESERVED_ITT) {
 		struct iscsi_session *session = conn->session;
 
 		spin_lock_bh(&session->lock);
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index bfac444..19dd4b9 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -75,7 +75,7 @@
      */
     if (1) {
 	esp_dev = NULL;
-	esp = esp_allocate(tpnt, (void *) esp_dev);
+	esp = esp_allocate(tpnt, esp_dev, 0);
 	
 	/* Do command transfer with programmed I/O */
 	esp->do_pio_cmds = 1;
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index f0871c3..5c32a69 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -38,7 +38,6 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/dma-mapping.h>
 
@@ -123,6 +122,7 @@
 		hostdata->force_le_on_be = 0;
 		hostdata->chip710 = 1;
 		hostdata->dmode_extra = DMODE_FC2;
+		hostdata->burst_length = 8;
 	}
 
 	host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index d37048c..7c75771 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -113,8 +113,7 @@
         hdr->opcode = ISCSI_OP_SCSI_CMD;
         hdr->flags = ISCSI_ATTR_SIMPLE;
         int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
-        hdr->itt = ctask->itt | (conn->id << ISCSI_CID_SHIFT) |
-                         (session->age << ISCSI_AGE_SHIFT);
+        hdr->itt = build_itt(ctask->itt, conn->id, session->age);
         hdr->data_length = cpu_to_be32(sc->request_bufflen);
         hdr->cmdsn = cpu_to_be32(session->cmdsn);
         session->cmdsn++;
@@ -270,7 +269,7 @@
 			goto out;
 		}
 
-		senselen = be16_to_cpu(*(uint16_t *)data);
+		senselen = be16_to_cpu(*(__be16 *)data);
 		if (datalen < senselen)
 			goto invalid_datalen;
 
@@ -338,7 +337,7 @@
 
 		if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) {
 			memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
-			itt = rejected_pdu.itt & ISCSI_ITT_MASK;
+			itt = get_itt(rejected_pdu.itt);
 			printk(KERN_ERR "itt 0x%x had pdu (op 0x%x) rejected "
 				"due to DataDigest error.\n", itt,
 				rejected_pdu.opcode);
@@ -367,10 +366,10 @@
 	struct iscsi_mgmt_task *mtask;
 	uint32_t itt;
 
-	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG))
-		itt = hdr->itt & ISCSI_ITT_MASK;
+	if (hdr->itt != RESERVED_ITT)
+		itt = get_itt(hdr->itt);
 	else
-		itt = hdr->itt;
+		itt = ~0U;
 
 	if (itt < session->cmds_max) {
 		ctask = session->cmds[itt];
@@ -440,7 +439,7 @@
 			iscsi_tmf_rsp(conn, hdr);
 			break;
 		case ISCSI_OP_NOOP_IN:
-			if (hdr->ttt != ISCSI_RESERVED_TAG || datalen) {
+			if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) {
 				rc = ISCSI_ERR_PROTO;
 				break;
 			}
@@ -457,7 +456,7 @@
 			rc = ISCSI_ERR_BAD_OPCODE;
 			break;
 		}
-	} else if (itt == ISCSI_RESERVED_TAG) {
+	} else if (itt == ~0U) {
 		rc = iscsi_check_assign_cmdsn(session,
 					     (struct iscsi_nopin*)hdr);
 		if (rc)
@@ -470,7 +469,7 @@
 				break;
 			}
 
-			if (hdr->ttt == ISCSI_RESERVED_TAG)
+			if (hdr->ttt == cpu_to_be32(ISCSI_RESERVED_TAG))
 				break;
 
 			if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0))
@@ -516,24 +515,24 @@
 	struct iscsi_cmd_task *ctask;
 	uint32_t itt;
 
-	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
-		if ((hdr->itt & ISCSI_AGE_MASK) !=
+	if (hdr->itt != RESERVED_ITT) {
+		if (((__force u32)hdr->itt & ISCSI_AGE_MASK) !=
 		    (session->age << ISCSI_AGE_SHIFT)) {
 			printk(KERN_ERR "iscsi: received itt %x expected "
-				"session age (%x)\n", hdr->itt,
+				"session age (%x)\n", (__force u32)hdr->itt,
 				session->age & ISCSI_AGE_MASK);
 			return ISCSI_ERR_BAD_ITT;
 		}
 
-		if ((hdr->itt & ISCSI_CID_MASK) !=
+		if (((__force u32)hdr->itt & ISCSI_CID_MASK) !=
 		    (conn->id << ISCSI_CID_SHIFT)) {
 			printk(KERN_ERR "iscsi: received itt %x, expected "
-				"CID (%x)\n", hdr->itt, conn->id);
+				"CID (%x)\n", (__force u32)hdr->itt, conn->id);
 			return ISCSI_ERR_BAD_ITT;
 		}
-		itt = hdr->itt & ISCSI_ITT_MASK;
+		itt = get_itt(hdr->itt);
 	} else
-		itt = hdr->itt;
+		itt = ~0U;
 
 	if (itt < session->cmds_max) {
 		ctask = session->cmds[itt];
@@ -896,9 +895,8 @@
 	/*
 	 * pre-format CmdSN for outgoing PDU.
 	 */
-	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
-		hdr->itt = mtask->itt | (conn->id << ISCSI_CID_SHIFT) |
-			   (session->age << ISCSI_AGE_SHIFT);
+	if (hdr->itt != RESERVED_ITT) {
+		hdr->itt = build_itt(mtask->itt, conn->id, session->age);
 		nop->cmdsn = cpu_to_be32(session->cmdsn);
 		if (conn->c_stage == ISCSI_CONN_STARTED &&
 		    !(hdr->opcode & ISCSI_OP_IMMEDIATE))
@@ -1064,7 +1062,7 @@
 
 	spin_lock_bh(&session->lock);
 	ctask->mtask = (struct iscsi_mgmt_task *)
-			session->mgmt_cmds[(hdr->itt & ISCSI_ITT_MASK) -
+			session->mgmt_cmds[get_itt(hdr->itt) -
 					ISCSI_MGMT_ITT_OFFSET];
 
 	if (conn->tmabort_state == TMABORT_INITIAL) {
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index fb7df7b..a65598b 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -548,7 +548,7 @@
 
 	res = sas_notify_lldd_dev_found(dev);
 	if (res)
-		return res;
+		goto out_err2;
 
 	switch (dev->dev_type) {
 	case SATA_DEV:
@@ -560,11 +560,23 @@
 	default:
 		break;
 	}
+	if (res)
+		goto out_err;
 
 	sas_notify_lldd_dev_gone(dev);
-	if (!res) {
-		sas_notify_lldd_dev_found(dev);
-	}
+	res = sas_notify_lldd_dev_found(dev);
+	if (res)
+		goto out_err2;
+
+	res = sas_rphy_add(dev->rphy);
+	if (res)
+		goto out_err;
+
+	return res;
+
+out_err:
+	sas_notify_lldd_dev_gone(dev);
+out_err2:
 	return res;
 }
 
@@ -580,21 +592,17 @@
 
 	res = sas_notify_lldd_dev_found(dev);
 	if (res)
-		return res;
+		goto out_err2;
 
 	res = sas_rphy_add(dev->rphy);
 	if (res)
 		goto out_err;
 
-	/* do this to get the end device port attributes which will have
-	 * been scanned in sas_rphy_add */
-	sas_notify_lldd_dev_gone(dev);
-	sas_notify_lldd_dev_found(dev);
-
 	return 0;
 
 out_err:
 	sas_notify_lldd_dev_gone(dev);
+out_err2:
 	return res;
 }
 
@@ -649,6 +657,7 @@
  */
 static void sas_discover_domain(struct work_struct *work)
 {
+	struct domain_device *dev;
 	int error = 0;
 	struct sas_discovery_event *ev =
 		container_of(work, struct sas_discovery_event, work);
@@ -658,35 +667,42 @@
 			&port->disc.pending);
 
 	if (port->port_dev)
-		return ;
-	else {
-		error = sas_get_port_device(port);
-		if (error)
-			return;
-	}
+		return;
+
+	error = sas_get_port_device(port);
+	if (error)
+		return;
+	dev = port->port_dev;
 
 	SAS_DPRINTK("DOING DISCOVERY on port %d, pid:%d\n", port->id,
 		    current->pid);
 
-	switch (port->port_dev->dev_type) {
+	switch (dev->dev_type) {
 	case SAS_END_DEV:
-		error = sas_discover_end_dev(port->port_dev);
+		error = sas_discover_end_dev(dev);
 		break;
 	case EDGE_DEV:
 	case FANOUT_DEV:
-		error = sas_discover_root_expander(port->port_dev);
+		error = sas_discover_root_expander(dev);
 		break;
 	case SATA_DEV:
 	case SATA_PM:
-		error = sas_discover_sata(port->port_dev);
+		error = sas_discover_sata(dev);
 		break;
 	default:
-		SAS_DPRINTK("unhandled device %d\n", port->port_dev->dev_type);
+		SAS_DPRINTK("unhandled device %d\n", dev->dev_type);
 		break;
 	}
 
 	if (error) {
-		kfree(port->port_dev); /* not kobject_register-ed yet */
+		sas_rphy_free(dev->rphy);
+		dev->rphy = NULL;
+
+		spin_lock(&port->dev_list_lock);
+		list_del_init(&dev->dev_list_node);
+		spin_unlock(&port->dev_list_lock);
+
+		kfree(dev); /* not kobject_register-ed yet */
 		port->port_dev = NULL;
 	}
 
@@ -726,7 +742,7 @@
 	BUG_ON(ev >= DISC_NUM_EVENTS);
 
 	sas_queue_event(ev, &disc->disc_event_lock, &disc->pending,
-			&disc->disc_work[ev].work, port->ha->core.shost);
+			&disc->disc_work[ev].work, port->ha);
 
 	return 0;
 }
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index d83392e..9db30fb 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -31,7 +31,7 @@
 	BUG_ON(event >= HA_NUM_EVENTS);
 
 	sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending,
-			&sas_ha->ha_events[event].work, sas_ha->core.shost);
+			&sas_ha->ha_events[event].work, sas_ha);
 }
 
 static void notify_port_event(struct asd_sas_phy *phy, enum port_event event)
@@ -41,7 +41,7 @@
 	BUG_ON(event >= PORT_NUM_EVENTS);
 
 	sas_queue_event(event, &ha->event_lock, &phy->port_events_pending,
-			&phy->port_events[event].work, ha->core.shost);
+			&phy->port_events[event].work, ha);
 }
 
 static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
@@ -51,7 +51,7 @@
 	BUG_ON(event >= PHY_NUM_EVENTS);
 
 	sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending,
-			&phy->phy_events[event].work, ha->core.shost);
+			&phy->phy_events[event].work, ha);
 }
 
 int sas_init_events(struct sas_ha_struct *sas_ha)
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index d31e6fa..dc70c18 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -667,8 +667,9 @@
 	return child;
 
  out_list_del:
+	sas_rphy_free(child->rphy);
+	child->rphy = NULL;
 	list_del(&child->dev_list_node);
-	sas_rphy_free(rphy);
  out_free:
 	sas_port_delete(phy->port);
  out_err:
@@ -677,6 +678,29 @@
 	return NULL;
 }
 
+/* See if this phy is part of a wide port */
+static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
+{
+	struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id];
+	int i;
+
+	for (i = 0; i < parent->ex_dev.num_phys; i++) {
+		struct ex_phy *ephy = &parent->ex_dev.ex_phy[i];
+
+		if (ephy == phy)
+			continue;
+
+		if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr,
+			    SAS_ADDR_SIZE) && ephy->port) {
+			sas_port_add_phy(ephy->port, phy->phy);
+			phy->phy_state = PHY_DEVICE_DISCOVERED;
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
 static struct domain_device *sas_ex_discover_expander(
 	struct domain_device *parent, int phy_id)
 {
@@ -809,6 +833,13 @@
 		return res;
 	}
 
+	res = sas_ex_join_wide_port(dev, phy_id);
+	if (!res) {
+		SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",
+			    phy_id, SAS_ADDR(ex_phy->attached_sas_addr));
+		return res;
+	}
+
 	switch (ex_phy->attached_dev_type) {
 	case SAS_END_DEV:
 		child = sas_ex_discover_end_dev(dev, phy_id);
@@ -1431,13 +1462,22 @@
 	int res;
 	struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy);
 
-	sas_rphy_add(dev->rphy);
+	res = sas_rphy_add(dev->rphy);
+	if (res)
+		goto out_err;
 
 	ex->level = dev->port->disc.max_level; /* 0 */
 	res = sas_discover_expander(dev);
-	if (!res)
-		sas_ex_bfs_disc(dev->port);
+	if (res)
+		goto out_err2;
 
+	sas_ex_bfs_disc(dev->port);
+
+	return res;
+
+out_err2:
+	sas_rphy_remove(dev->rphy);
+out_err:
 	return res;
 }
 
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2f0c07f..965698c 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -87,6 +87,9 @@
 	else if (sas_ha->lldd_queue_size == -1)
 		sas_ha->lldd_queue_size = 128; /* Sanity */
 
+	sas_ha->state = SAS_HA_REGISTERED;
+	spin_lock_init(&sas_ha->state_lock);
+
 	error = sas_register_phys(sas_ha);
 	if (error) {
 		printk(KERN_NOTICE "couldn't register sas phys:%d\n", error);
@@ -127,12 +130,22 @@
 
 int sas_unregister_ha(struct sas_ha_struct *sas_ha)
 {
-	if (sas_ha->lldd_max_execute_num > 1) {
-		sas_shutdown_queue(sas_ha);
-	}
+	unsigned long flags;
+
+	/* Set the state to unregistered to avoid further
+	 * events to be queued */
+	spin_lock_irqsave(&sas_ha->state_lock, flags);
+	sas_ha->state = SAS_HA_UNREGISTERED;
+	spin_unlock_irqrestore(&sas_ha->state_lock, flags);
+	scsi_flush_work(sas_ha->core.shost);
 
 	sas_unregister_ports(sas_ha);
 
+	if (sas_ha->lldd_max_execute_num > 1) {
+		sas_shutdown_queue(sas_ha);
+		sas_ha->lldd_max_execute_num = 1;
+	}
+
 	return 0;
 }
 
@@ -146,6 +159,36 @@
 	return sas_smp_get_phy_events(phy);
 }
 
+int sas_phy_enable(struct sas_phy *phy, int enable)
+{
+	int ret;
+	enum phy_func command;
+
+	if (enable)
+		command = PHY_FUNC_LINK_RESET;
+	else
+		command = PHY_FUNC_DISABLE;
+
+	if (scsi_is_sas_phy_local(phy)) {
+		struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+		struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+		struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
+		struct sas_internal *i =
+			to_sas_internal(sas_ha->core.shost->transportt);
+
+		if (!enable) {
+			sas_phy_disconnected(asd_phy);
+			sas_ha->notify_phy_event(asd_phy, PHYE_LOSS_OF_SIGNAL);
+		}
+		ret = i->dft->lldd_control_phy(asd_phy, command, NULL);
+	} else {
+		struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
+		struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
+		ret = sas_smp_phy_control(ddev, phy->number, command, NULL);
+	}
+	return ret;
+}
+
 int sas_phy_reset(struct sas_phy *phy, int hard_reset)
 {
 	int ret;
@@ -172,8 +215,8 @@
 	return ret;
 }
 
-static int sas_set_phy_speed(struct sas_phy *phy,
-			     struct sas_phy_linkrates *rates)
+int sas_set_phy_speed(struct sas_phy *phy,
+		      struct sas_phy_linkrates *rates)
 {
 	int ret;
 
@@ -212,6 +255,7 @@
 }
 
 static struct sas_function_template sft = {
+	.phy_enable = sas_phy_enable,
 	.phy_reset = sas_phy_reset,
 	.set_phy_speed = sas_set_phy_speed,
 	.get_linkerrors = sas_get_linkerrors,
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 137d7e4..a78638d 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -80,7 +80,7 @@
 static inline void sas_queue_event(int event, spinlock_t *lock,
 				   unsigned long *pending,
 				   struct work_struct *work,
-				   struct Scsi_Host *shost)
+				   struct sas_ha_struct *sas_ha)
 {
 	unsigned long flags;
 
@@ -91,7 +91,12 @@
 	}
 	__set_bit(event, pending);
 	spin_unlock_irqrestore(lock, flags);
-	scsi_queue_work(shost, work);
+
+	spin_lock_irqsave(&sas_ha->state_lock, flags);
+	if (sas_ha->state != SAS_HA_UNREGISTERED) {
+		scsi_queue_work(sas_ha->core.shost, work);
+	}
+	spin_unlock_irqrestore(&sas_ha->state_lock, flags);
 }
 
 static inline void sas_begin_event(int event, spinlock_t *lock,
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index 971c37c..e1e2d08 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -42,10 +42,11 @@
 	struct asd_sas_port *port = phy->port;
 	struct sas_internal *si =
 		to_sas_internal(sas_ha->core.shost->transportt);
+	unsigned long flags;
 
 	if (port) {
 		if (memcmp(port->attached_sas_addr, phy->attached_sas_addr,
-			   SAS_ADDR_SIZE) == 0)
+			   SAS_ADDR_SIZE) != 0)
 			sas_deform_port(phy);
 		else {
 			SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n",
@@ -56,7 +57,7 @@
 	}
 
 	/* find a port */
-	spin_lock(&sas_ha->phy_port_lock);
+	spin_lock_irqsave(&sas_ha->phy_port_lock, flags);
 	for (i = 0; i < sas_ha->num_phys; i++) {
 		port = sas_ha->sas_port[i];
 		spin_lock(&port->phy_list_lock);
@@ -78,7 +79,7 @@
 	if (i >= sas_ha->num_phys) {
 		printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n",
 		       __FUNCTION__);
-		spin_unlock(&sas_ha->phy_port_lock);
+		spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
 		return;
 	}
 
@@ -105,7 +106,7 @@
 	} else
 		port->linkrate = max(port->linkrate, phy->linkrate);
 	spin_unlock(&port->phy_list_lock);
-	spin_unlock(&sas_ha->phy_port_lock);
+	spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
 
 	if (!port->port) {
 		port->port = sas_port_alloc(phy->phy->dev.parent, port->id);
@@ -137,6 +138,7 @@
 	struct asd_sas_port *port = phy->port;
 	struct sas_internal *si =
 		to_sas_internal(sas_ha->core.shost->transportt);
+	unsigned long flags;
 
 	if (!port)
 		return;		  /* done by a phy event */
@@ -155,7 +157,7 @@
 	if (si->dft->lldd_port_deformed)
 		si->dft->lldd_port_deformed(phy);
 
-	spin_lock(&sas_ha->phy_port_lock);
+	spin_lock_irqsave(&sas_ha->phy_port_lock, flags);
 	spin_lock(&port->phy_list_lock);
 
 	list_del_init(&phy->port_phy_el);
@@ -174,7 +176,7 @@
 		port->phy_mask = 0;
 	}
 	spin_unlock(&port->phy_list_lock);
-	spin_unlock(&sas_ha->phy_port_lock);
+	spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
 
 	return;
 }
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 22672d5..897a5e2 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -34,6 +34,7 @@
 #include <scsi/scsi_transport_sas.h>
 #include "../scsi_sas_internal.h"
 #include "../scsi_transport_api.h"
+#include "../scsi_priv.h"
 
 #include <linux/err.h>
 #include <linux/blkdev.h>
@@ -130,7 +131,7 @@
 	if (cmd->request && blk_rq_tagged(cmd->request)) {
 		if (cmd->device->ordered_tags &&
 		    (cmd->request->cmd_flags & REQ_HARDBARRIER))
-			ta = TASK_ATTR_HOQ;
+			ta = TASK_ATTR_ORDERED;
 	}
 	return ta;
 }
@@ -281,6 +282,7 @@
 	TASK_IS_ABORTED,
 	TASK_IS_AT_LU,
 	TASK_IS_NOT_AT_LU,
+	TASK_ABORT_FAILED,
 };
 
 static enum task_disposition sas_scsi_find_task(struct sas_task *task)
@@ -310,15 +312,6 @@
 		spin_unlock_irqrestore(&core->task_queue_lock, flags);
 	}
 
-	spin_lock_irqsave(&task->task_state_lock, flags);
-	if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
-		spin_unlock_irqrestore(&task->task_state_lock, flags);
-		SAS_DPRINTK("%s: task 0x%p already aborted\n",
-			    __FUNCTION__, task);
-		return TASK_IS_ABORTED;
-	}
-	spin_unlock_irqrestore(&task->task_state_lock, flags);
-
 	for (i = 0; i < 5; i++) {
 		SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task);
 		res = si->dft->lldd_abort_task(task);
@@ -340,15 +333,21 @@
 			SAS_DPRINTK("%s: querying task 0x%p\n",
 				    __FUNCTION__, task);
 			res = si->dft->lldd_query_task(task);
-			if (res == TMF_RESP_FUNC_SUCC) {
+			switch (res) {
+			case TMF_RESP_FUNC_SUCC:
 				SAS_DPRINTK("%s: task 0x%p at LU\n",
 					    __FUNCTION__, task);
 				return TASK_IS_AT_LU;
-			} else if (res == TMF_RESP_FUNC_COMPLETE) {
+			case TMF_RESP_FUNC_COMPLETE:
 				SAS_DPRINTK("%s: task 0x%p not at LU\n",
 					    __FUNCTION__, task);
 				return TASK_IS_NOT_AT_LU;
-			}
+			case TMF_RESP_FUNC_FAILED:
+                                SAS_DPRINTK("%s: task 0x%p failed to abort\n",
+                                                __FUNCTION__, task);
+                                return TASK_ABORT_FAILED;
+                        }
+
 		}
 	}
 	return res;
@@ -398,35 +397,113 @@
 	return res;
 }
 
-void sas_scsi_recover_host(struct Scsi_Host *shost)
+/* Find the sas_phy that's attached to this device */
+struct sas_phy *find_local_sas_phy(struct domain_device *dev)
 {
-	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
-	unsigned long flags;
-	LIST_HEAD(error_q);
+	struct domain_device *pdev = dev->parent;
+	struct ex_phy *exphy = NULL;
+	int i;
+
+	/* Directly attached device */
+	if (!pdev)
+		return dev->port->phy;
+
+	/* Otherwise look in the expander */
+	for (i = 0; i < pdev->ex_dev.num_phys; i++)
+		if (!memcmp(dev->sas_addr,
+			    pdev->ex_dev.ex_phy[i].attached_sas_addr,
+			    SAS_ADDR_SIZE)) {
+			exphy = &pdev->ex_dev.ex_phy[i];
+			break;
+		}
+
+	BUG_ON(!exphy);
+	return exphy->phy;
+}
+
+/* Attempt to send a LUN reset message to a device */
+int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
+{
+	struct domain_device *dev = cmd_to_domain_dev(cmd);
+	struct sas_internal *i =
+		to_sas_internal(dev->port->ha->core.shost->transportt);
+	struct scsi_lun lun;
+	int res;
+
+	int_to_scsilun(cmd->device->lun, &lun);
+
+	if (!i->dft->lldd_lu_reset)
+		return FAILED;
+
+	res = i->dft->lldd_lu_reset(dev, lun.scsi_lun);
+	if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
+		return SUCCESS;
+
+	return FAILED;
+}
+
+/* Attempt to send a phy (bus) reset */
+int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
+{
+	struct domain_device *dev = cmd_to_domain_dev(cmd);
+	struct sas_phy *phy = find_local_sas_phy(dev);
+	int res;
+
+	res = sas_phy_reset(phy, 1);
+	if (res)
+		SAS_DPRINTK("Bus reset of %s failed 0x%x\n",
+			    phy->dev.kobj.k_name,
+			    res);
+	if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
+		return SUCCESS;
+
+	return FAILED;
+}
+
+/* Try to reset a device */
+static int try_to_reset_cmd_device(struct Scsi_Host *shost,
+				   struct scsi_cmnd *cmd)
+{
+	int res;
+
+	if (!shost->hostt->eh_device_reset_handler)
+		goto try_bus_reset;
+
+	res = shost->hostt->eh_device_reset_handler(cmd);
+	if (res == SUCCESS)
+		return res;
+
+try_bus_reset:
+	if (shost->hostt->eh_bus_reset_handler)
+		return shost->hostt->eh_bus_reset_handler(cmd);
+
+	return FAILED;
+}
+
+static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
+				    struct list_head *work_q,
+				    struct list_head *done_q)
+{
 	struct scsi_cmnd *cmd, *n;
 	enum task_disposition res = TASK_IS_DONE;
-	int tmf_resp;
+	int tmf_resp, need_reset;
 	struct sas_internal *i = to_sas_internal(shost->transportt);
+	unsigned long flags;
+	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
 
-	spin_lock_irqsave(shost->host_lock, flags);
-	list_splice_init(&shost->eh_cmd_q, &error_q);
-	spin_unlock_irqrestore(shost->host_lock, flags);
-
-	SAS_DPRINTK("Enter %s\n", __FUNCTION__);
-
-	/* All tasks on this list were marked SAS_TASK_STATE_ABORTED
-	 * by sas_scsi_timed_out() callback.
-	 */
 Again:
-	SAS_DPRINTK("going over list...\n");
-	list_for_each_entry_safe(cmd, n, &error_q, eh_entry) {
+	list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
 		struct sas_task *task = TO_SAS_TASK(cmd);
+
+		if (!task)
+			continue;
+
 		list_del_init(&cmd->eh_entry);
 
-		if (!task) {
-			SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__);
-			continue;
-		}
+		spin_lock_irqsave(&task->task_state_lock, flags);
+		need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET;
+		spin_unlock_irqrestore(&task->task_state_lock, flags);
+
 		SAS_DPRINTK("trying to find task 0x%p\n", task);
 		res = sas_scsi_find_task(task);
 
@@ -437,11 +514,15 @@
 			SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
 				    task);
 			task->task_done(task);
+			if (need_reset)
+				try_to_reset_cmd_device(shost, cmd);
 			continue;
 		case TASK_IS_ABORTED:
 			SAS_DPRINTK("%s: task 0x%p is aborted\n",
 				    __FUNCTION__, task);
 			task->task_done(task);
+			if (need_reset)
+				try_to_reset_cmd_device(shost, cmd);
 			continue;
 		case TASK_IS_AT_LU:
 			SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
@@ -452,11 +533,14 @@
 					    SAS_ADDR(task->dev),
 					    cmd->device->lun);
 				task->task_done(task);
-				sas_scsi_clear_queue_lu(&error_q, cmd);
+				if (need_reset)
+					try_to_reset_cmd_device(shost, cmd);
+				sas_scsi_clear_queue_lu(work_q, cmd);
 				goto Again;
 			}
 			/* fallthrough */
 		case TASK_IS_NOT_AT_LU:
+		case TASK_ABORT_FAILED:
 			SAS_DPRINTK("task 0x%p is not at LU: I_T recover\n",
 				    task);
 			tmf_resp = sas_recover_I_T(task->dev);
@@ -464,7 +548,9 @@
 				SAS_DPRINTK("I_T %016llx recovered\n",
 					    SAS_ADDR(task->dev->sas_addr));
 				task->task_done(task);
-				sas_scsi_clear_queue_I_T(&error_q, task->dev);
+				if (need_reset)
+					try_to_reset_cmd_device(shost, cmd);
+				sas_scsi_clear_queue_I_T(work_q, task->dev);
 				goto Again;
 			}
 			/* Hammer time :-) */
@@ -477,7 +563,9 @@
 					SAS_DPRINTK("clear nexus port:%d "
 						    "succeeded\n", port->id);
 					task->task_done(task);
-					sas_scsi_clear_queue_port(&error_q,
+					if (need_reset)
+						try_to_reset_cmd_device(shost, cmd);
+					sas_scsi_clear_queue_port(work_q,
 								  port);
 					goto Again;
 				}
@@ -489,6 +577,8 @@
 					SAS_DPRINTK("clear nexus ha "
 						    "succeeded\n");
 					task->task_done(task);
+					if (need_reset)
+						try_to_reset_cmd_device(shost, cmd);
 					goto out;
 				}
 			}
@@ -502,20 +592,54 @@
 				    cmd->device->lun);
 
 			task->task_done(task);
+			if (need_reset)
+				try_to_reset_cmd_device(shost, cmd);
 			goto clear_q;
 		}
 	}
 out:
-	scsi_eh_flush_done_q(&ha->eh_done_q);
-	SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
-	return;
+	return list_empty(work_q);
 clear_q:
 	SAS_DPRINTK("--- Exit %s -- clear_q\n", __FUNCTION__);
-	list_for_each_entry_safe(cmd, n, &error_q, eh_entry) {
+	list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
 		struct sas_task *task = TO_SAS_TASK(cmd);
 		list_del_init(&cmd->eh_entry);
 		task->task_done(task);
 	}
+	return list_empty(work_q);
+}
+
+void sas_scsi_recover_host(struct Scsi_Host *shost)
+{
+	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
+	unsigned long flags;
+	LIST_HEAD(eh_work_q);
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	list_splice_init(&shost->eh_cmd_q, &eh_work_q);
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	SAS_DPRINTK("Enter %s\n", __FUNCTION__);
+	/*
+	 * Deal with commands that still have SAS tasks (i.e. they didn't
+	 * complete via the normal sas_task completion mechanism)
+	 */
+	if (sas_eh_handle_sas_errors(shost, &eh_work_q, &ha->eh_done_q))
+		goto out;
+
+	/*
+	 * Now deal with SCSI commands that completed ok but have a an error
+	 * code (and hopefully sense data) attached.  This is roughly what
+	 * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any
+	 * command we see here has no sas_task and is thus unknown to the HA.
+	 */
+	if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
+		scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
+
+out:
+	scsi_eh_flush_done_q(&ha->eh_done_q);
+	SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
+	return;
 }
 
 enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
@@ -524,24 +648,30 @@
 	unsigned long flags;
 
 	if (!task) {
-		SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n",
-			    cmd, task);
-		return EH_HANDLED;
+		cmd->timeout_per_command /= 2;
+		SAS_DPRINTK("command 0x%p, task 0x%p, gone: %s\n",
+			    cmd, task, (cmd->timeout_per_command ?
+			    "EH_RESET_TIMER" : "EH_NOT_HANDLED"));
+		if (!cmd->timeout_per_command)
+			return EH_NOT_HANDLED;
+		return EH_RESET_TIMER;
 	}
 
 	spin_lock_irqsave(&task->task_state_lock, flags);
-	if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
-		spin_unlock_irqrestore(&task->task_state_lock, flags);
-		SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: "
-			    "EH_NOT_HANDLED\n", cmd, task);
-		return EH_NOT_HANDLED;
-	}
+	BUG_ON(task->task_state_flags & SAS_TASK_STATE_ABORTED);
 	if (task->task_state_flags & SAS_TASK_STATE_DONE) {
 		spin_unlock_irqrestore(&task->task_state_lock, flags);
 		SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
 			    cmd, task);
 		return EH_HANDLED;
 	}
+	if (!(task->task_state_flags & SAS_TASK_AT_INITIATOR)) {
+		spin_unlock_irqrestore(&task->task_state_lock, flags);
+		SAS_DPRINTK("command 0x%p, task 0x%p, not at initiator: "
+			    "EH_RESET_TIMER\n",
+			    cmd, task);
+		return EH_RESET_TIMER;
+	}
 	task->task_state_flags |= SAS_TASK_STATE_ABORTED;
 	spin_unlock_irqrestore(&task->task_state_lock, flags);
 
@@ -557,8 +687,9 @@
 	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
 	struct domain_device *found_dev = NULL;
 	int i;
+	unsigned long flags;
 
-	spin_lock(&ha->phy_port_lock);
+	spin_lock_irqsave(&ha->phy_port_lock, flags);
 	for (i = 0; i < ha->num_phys; i++) {
 		struct asd_sas_port *port = ha->sas_port[i];
 		struct domain_device *dev;
@@ -574,7 +705,7 @@
 		spin_unlock(&port->dev_list_lock);
 	}
  found:
-	spin_unlock(&ha->phy_port_lock);
+	spin_unlock_irqrestore(&ha->phy_port_lock, flags);
 
 	return found_dev;
 }
@@ -623,6 +754,8 @@
 		scsi_deactivate_tcq(scsi_dev, 1);
 	}
 
+	scsi_dev->allow_restart = 1;
+
 	return 0;
 }
 
@@ -799,46 +932,42 @@
 	spin_unlock_irqrestore(&core->task_queue_lock, flags);
 }
 
-static int do_sas_task_abort(struct sas_task *task)
+/*
+ * Call the LLDD task abort routine directly.  This function is intended for
+ * use by upper layers that need to tell the LLDD to abort a task.
+ */
+int __sas_task_abort(struct sas_task *task)
 {
-	struct scsi_cmnd *sc = task->uldd_task;
 	struct sas_internal *si =
 		to_sas_internal(task->dev->port->ha->core.shost->transportt);
 	unsigned long flags;
 	int res;
 
 	spin_lock_irqsave(&task->task_state_lock, flags);
-	if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+	if (task->task_state_flags & SAS_TASK_STATE_ABORTED ||
+	    task->task_state_flags & SAS_TASK_STATE_DONE) {
 		spin_unlock_irqrestore(&task->task_state_lock, flags);
-		SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__,
+		SAS_DPRINTK("%s: Task %p already finished.\n", __FUNCTION__,
 			    task);
 		return 0;
 	}
-
-	task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED;
-	if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
-		task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+	task->task_state_flags |= SAS_TASK_STATE_ABORTED;
 	spin_unlock_irqrestore(&task->task_state_lock, flags);
 
 	if (!si->dft->lldd_abort_task)
 		return -ENODEV;
 
 	res = si->dft->lldd_abort_task(task);
+
+	spin_lock_irqsave(&task->task_state_lock, flags);
 	if ((task->task_state_flags & SAS_TASK_STATE_DONE) ||
 	    (res == TMF_RESP_FUNC_COMPLETE))
 	{
-		/* SMP commands don't have scsi_cmds(?) */
-		if (!sc) {
-			task->task_done(task);
-			return 0;
-		}
-		scsi_req_abort_cmd(sc);
-		scsi_schedule_eh(sc->device->host);
+		spin_unlock_irqrestore(&task->task_state_lock, flags);
+		task->task_done(task);
 		return 0;
 	}
 
-	spin_lock_irqsave(&task->task_state_lock, flags);
-	task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED;
 	if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
 		task->task_state_flags &= ~SAS_TASK_STATE_ABORTED;
 	spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -846,17 +975,24 @@
 	return -EAGAIN;
 }
 
-void sas_task_abort(struct work_struct *work)
+/*
+ * Tell an upper layer that it needs to initiate an abort for a given task.
+ * This should only ever be called by an LLDD.
+ */
+void sas_task_abort(struct sas_task *task)
 {
-	struct sas_task *task =
-		container_of(work, struct sas_task, abort_work);
-	int i;
+	struct scsi_cmnd *sc = task->uldd_task;
 
-	for (i = 0; i < 5; i++)
-		if (!do_sas_task_abort(task))
+	/* Escape for libsas internal commands */
+	if (!sc) {
+		if (!del_timer(&task->timer))
 			return;
+		task->timer.function(task->timer.data);
+		return;
+	}
 
-	SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__);
+	scsi_req_abort_cmd(sc);
+	scsi_schedule_eh(sc->device->host);
 }
 
 EXPORT_SYMBOL_GPL(sas_queuecommand);
@@ -866,5 +1002,9 @@
 EXPORT_SYMBOL_GPL(sas_change_queue_depth);
 EXPORT_SYMBOL_GPL(sas_change_queue_type);
 EXPORT_SYMBOL_GPL(sas_bios_param);
+EXPORT_SYMBOL_GPL(__sas_task_abort);
 EXPORT_SYMBOL_GPL(sas_task_abort);
 EXPORT_SYMBOL_GPL(sas_phy_reset);
+EXPORT_SYMBOL_GPL(sas_phy_enable);
+EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
+EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index afca45c..9d014e5 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -518,6 +518,10 @@
 	struct lpfc_sli *psli = &phba->sli;
 	struct lpfc_sli_ring  *pring;
 	uint32_t event_data;
+	/* If the pci channel is offline, ignore possible errors,
+	 * since we cannot communicate with the pci card anyway. */
+	if (pci_channel_offline(phba->pcidev))
+		return;
 
 	if (phba->work_hs & HS_FFER6 ||
 	    phba->work_hs & HS_FFER5) {
@@ -1797,6 +1801,92 @@
 	pci_set_drvdata(pdev, NULL);
 }
 
+/**
+ * lpfc_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci conneection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
+				pci_channel_state_t state)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata;
+	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_sli_ring  *pring;
+
+	if (state == pci_channel_io_perm_failure) {
+		lpfc_pci_remove_one(pdev);
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	pci_disable_device(pdev);
+	/*
+	 * There may be I/Os dropped by the firmware.
+	 * Error iocb (I/O) on txcmplq and let the SCSI layer
+	 * retry it after re-establishing link.
+	 */
+	pring = &psli->ring[psli->fcp_ring];
+	lpfc_sli_abort_iocb_ring(phba, pring);
+
+	/* Request a slot reset. */
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * lpfc_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ */
+static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata;
+	struct lpfc_sli *psli = &phba->sli;
+	int bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+	dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
+	if (pci_enable_device_bars(pdev, bars)) {
+		printk(KERN_ERR "lpfc: Cannot re-enable "
+			"PCI device after reset.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	pci_set_master(pdev);
+
+	/* Re-establishing Link */
+	spin_lock_irq(phba->host->host_lock);
+	phba->fc_flag |= FC_ESTABLISH_LINK;
+	psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+	spin_unlock_irq(phba->host->host_lock);
+
+
+	/* Take device offline; this will perform cleanup */
+	lpfc_offline(phba);
+	lpfc_sli_brdrestart(phba);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * lpfc_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation.
+ */
+static void lpfc_io_resume(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata;
+
+	if (lpfc_online(phba) == 0) {
+		mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+	}
+}
+
 static struct pci_device_id lpfc_id_table[] = {
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
 		PCI_ANY_ID, PCI_ANY_ID, },
@@ -1857,11 +1947,18 @@
 
 MODULE_DEVICE_TABLE(pci, lpfc_id_table);
 
+static struct pci_error_handlers lpfc_err_handler = {
+	.error_detected = lpfc_io_error_detected,
+	.slot_reset = lpfc_io_slot_reset,
+	.resume = lpfc_io_resume,
+};
+
 static struct pci_driver lpfc_driver = {
 	.name		= LPFC_DRIVER_NAME,
 	.id_table	= lpfc_id_table,
 	.probe		= lpfc_pci_probe_one,
 	.remove		= __devexit_p(lpfc_pci_remove_one),
+	.err_handler = &lpfc_err_handler,
 };
 
 static int __init
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index a4128e1..9fb6960 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -2104,6 +2104,10 @@
 	volatile uint32_t word0, ldata;
 	void __iomem *to_slim;
 
+	/* If the PCI channel is in offline state, do not post mbox. */
+	if (unlikely(pci_channel_offline(phba->pcidev)))
+		return MBX_NOT_FINISHED;
+
 	psli = &phba->sli;
 
 	spin_lock_irqsave(phba->host->host_lock, drvr_flag);
@@ -2407,6 +2411,10 @@
 	struct lpfc_iocbq *nextiocb;
 	IOCB_t *iocb;
 
+	/* If the PCI channel is in offline state, do not post iocbs. */
+	if (unlikely(pci_channel_offline(phba->pcidev)))
+		return IOCB_ERROR;
+
 	/*
 	 * We should never get an IOCB if we are in a < LINK_DOWN state
 	 */
@@ -3154,6 +3162,10 @@
 	if (unlikely(!phba))
 		return IRQ_NONE;
 
+	/* If the pci channel is offline, ignore all the interrupts. */
+	if (unlikely(pci_channel_offline(phba->pcidev)))
+		return IRQ_NONE;
+
 	phba->sli.slistat.sli_intr++;
 
 	/*
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index 3586fac..bcb4902 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -351,7 +351,7 @@
 	for (chipnum = 0; chipnum < chipspresent; chipnum ++) {
 		struct NCR_ESP * esp;
 
-		esp = esp_allocate(tpnt, (void *) NULL);
+		esp = esp_allocate(tpnt, NULL, 0);
 		esp->eregs = (struct ESP_regs *) get_base(chipnum);
 
 		esp->dma_irq_p = &esp_dafb_dma_irq_p;
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index a942a21..cdbcaa5 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -36,7 +36,6 @@
 
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c
index 998a8bb..d693d0f 100644
--- a/drivers/scsi/mca_53c9x.c
+++ b/drivers/scsi/mca_53c9x.c
@@ -122,7 +122,7 @@
 		if ((slot = mca_find_adapter(*id_to_check, 0)) !=
 		  MCA_NOTFOUND) 
 		{
-			esp = esp_allocate(tpnt, (void *) NULL);
+			esp = esp_allocate(tpnt, NULL, 0);
 
 			pos[0] = mca_read_stored_pos(slot, 2);
 			pos[1] = mca_read_stored_pos(slot, 3);
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 77d9d38..0aa3304 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -92,7 +92,7 @@
 /*
  * The File Operations structure for the serial/ioctl interface of the driver
  */
-static struct file_operations megadev_fops = {
+static const struct file_operations megadev_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= megadev_ioctl,
 	.open		= megadev_open,
@@ -5072,7 +5072,7 @@
 				"megaraid: failed to create megaraid root\n");
 	}
 #endif
-	error = pci_module_init(&megaraid_pci_driver);
+	error = pci_register_driver(&megaraid_pci_driver);
 	if (error) {
 #ifdef CONFIG_PROC_FS
 		remove_proc_entry("megaraid", &proc_root);
diff --git a/drivers/scsi/megaraid/mbox_defs.h b/drivers/scsi/megaraid/mbox_defs.h
index 3052869..170399e 100644
--- a/drivers/scsi/megaraid/mbox_defs.h
+++ b/drivers/scsi/megaraid/mbox_defs.h
@@ -748,7 +748,7 @@
 
 
 /**
- * private_bios_data - bios private data for boot devices
+ * struct private_bios_data - bios private data for boot devices
  * @geometry	: bits 0-3 - BIOS geometry, 0x0001 - 1GB, 0x0010 - 2GB,
  *		0x1000 - 8GB, Others values are invalid
  * @unused	: bits 4-7 are unused
diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
index b50e27e..26e1e6c 100644
--- a/drivers/scsi/megaraid/mega_common.h
+++ b/drivers/scsi/megaraid/mega_common.h
@@ -46,17 +46,17 @@
 
 /**
  * scb_t - scsi command control block
- * @param ccb		: command control block for individual driver
- * @param list		: list of control blocks
- * @param gp		: general purpose field for LLDs
- * @param sno		: all SCBs have a serial number
- * @param scp		: associated scsi command
- * @param state		: current state of scb
- * @param dma_dir	: direction of data transfer
- * @param dma_type	: transfer with sg list, buffer, or no data transfer
- * @param dev_channel	: actual channel on the device
- * @param dev_target	: actual target on the device
- * @param status	: completion status
+ * @ccb			: command control block for individual driver
+ * @list		: list of control blocks
+ * @gp			: general purpose field for LLDs
+ * @sno			: all SCBs have a serial number
+ * @scp			: associated scsi command
+ * @state		: current state of scb
+ * @dma_dir		: direction of data transfer
+ * @dma_type		: transfer with sg list, buffer, or no data transfer
+ * @dev_channel		: actual channel on the device
+ * @dev_target		: actual target on the device
+ * @status		: completion status
  *
  * This is our central data structure to issue commands the each driver.
  * Driver specific data structures are maintained in the ccb field.
@@ -99,42 +99,42 @@
 
 /**
  * struct adapter_t - driver's initialization structure
- * @param dpc_h			: tasklet handle
- * @param pdev			: pci configuration pointer for kernel
- * @param host			: pointer to host structure of mid-layer
- * @param lock			: synchronization lock for mid-layer and driver
- * @param quiescent		: driver is quiescent for now.
- * @param outstanding_cmds	: number of commands pending in the driver
- * @param kscb_list		: pointer to the bulk of SCBs pointers for IO
- * @param kscb_pool		: pool of free scbs for IO
- * @param kscb_pool_lock	: lock for pool of free scbs
- * @param pend_list		: pending commands list
- * @param pend_list_lock	: exlusion lock for pending commands list
- * @param completed_list	: list of completed commands
- * @param completed_list_lock	: exclusion lock for list of completed commands
- * @param sglen			: max sg elements supported
- * @param device_ids		: to convert kernel device addr to our devices.
- * @param raid_device		: raid adapter specific pointer
- * @param max_channel		: maximum channel number supported - inclusive
- * @param max_target		: max target supported - inclusive
- * @param max_lun		: max lun supported - inclusive
- * @param unique_id		: unique identifier for each adapter
- * @param irq			: IRQ for this adapter
- * @param ito			: internal timeout value, (-1) means no timeout
- * @param ibuf			: buffer to issue internal commands
- * @param ibuf_dma_h		: dma handle for the above buffer
- * @param uscb_list		: SCB pointers for user cmds, common mgmt module
- * @param uscb_pool		: pool of SCBs for user commands
- * @param uscb_pool_lock	: exclusion lock for these SCBs
- * @param max_cmds		: max outstanding commands
- * @param fw_version		: firmware version
- * @param bios_version		: bios version
- * @param max_cdb_sz		: biggest CDB size supported.
- * @param ha			: is high availability present - clustering
- * @param init_id		: initiator ID, the default value should be 7
- * @param max_sectors		: max sectors per request
- * @param cmd_per_lun		: max outstanding commands per LUN
- * @param being_detached	: set when unloading, no more mgmt calls
+ * @aram dpc_h			: tasklet handle
+ * @pdev			: pci configuration pointer for kernel
+ * @host			: pointer to host structure of mid-layer
+ * @lock			: synchronization lock for mid-layer and driver
+ * @quiescent			: driver is quiescent for now.
+ * @outstanding_cmds		: number of commands pending in the driver
+ * @kscb_list			: pointer to the bulk of SCBs pointers for IO
+ * @kscb_pool			: pool of free scbs for IO
+ * @kscb_pool_lock		: lock for pool of free scbs
+ * @pend_list			: pending commands list
+ * @pend_list_lock		: exclusion lock for pending commands list
+ * @completed_list		: list of completed commands
+ * @completed_list_lock		: exclusion lock for list of completed commands
+ * @sglen			: max sg elements supported
+ * @device_ids			: to convert kernel device addr to our devices.
+ * @raid_device			: raid adapter specific pointer
+ * @max_channel			: maximum channel number supported - inclusive
+ * @max_target			: max target supported - inclusive
+ * @max_lun			: max lun supported - inclusive
+ * @unique_id			: unique identifier for each adapter
+ * @irq				: IRQ for this adapter
+ * @ito				: internal timeout value, (-1) means no timeout
+ * @ibuf			: buffer to issue internal commands
+ * @ibuf_dma_h			: dma handle for the above buffer
+ * @uscb_list			: SCB pointers for user cmds, common mgmt module
+ * @uscb_pool			: pool of SCBs for user commands
+ * @uscb_pool_lock		: exclusion lock for these SCBs
+ * @max_cmds			: max outstanding commands
+ * @fw_version			: firmware version
+ * @bios_version		: bios version
+ * @max_cdb_sz			: biggest CDB size supported.
+ * @ha				: is high availability present - clustering
+ * @init_id			: initiator ID, the default value should be 7
+ * @max_sectors			: max sectors per request
+ * @cmd_per_lun			: max outstanding commands per LUN
+ * @being_detached		: set when unloading, no more mgmt calls
  *
  *
  * mraid_setup_device_map() can be called anytime after the device map is
@@ -211,23 +211,23 @@
 #define SCP2ADAPTER(scp)	(adapter_t *)SCSIHOST2ADAP(SCP2HOST(scp))
 
 
-/**
- * MRAID_GET_DEVICE_MAP - device ids
- * @param adp		- Adapter's soft state
- * @param scp		- mid-layer scsi command pointer
- * @param p_chan	- physical channel on the controller
- * @param target	- target id of the device or logical drive number
- * @param islogical	- set if the command is for the logical drive
- *
- * Macro to retrieve information about device class, logical or physical and
- * the corresponding physical channel and target or logical drive number
- **/
 #define MRAID_IS_LOGICAL(adp, scp)	\
 	(SCP2CHANNEL(scp) == (adp)->max_channel) ? 1 : 0
 
 #define MRAID_IS_LOGICAL_SDEV(adp, sdev)	\
 	(sdev->channel == (adp)->max_channel) ? 1 : 0
 
+/**
+ * MRAID_GET_DEVICE_MAP - device ids
+ * @adp			: adapter's soft state
+ * @scp			: mid-layer scsi command pointer
+ * @p_chan		: physical channel on the controller
+ * @target		: target id of the device or logical drive number
+ * @islogical		: set if the command is for the logical drive
+ *
+ * Macro to retrieve information about device class, logical or physical and
+ * the corresponding physical channel and target or logical drive number
+ */
 #define MRAID_GET_DEVICE_MAP(adp, scp, p_chan, target, islogical)	\
 	/*								\
 	 * Is the request coming for the virtual channel		\
@@ -271,10 +271,10 @@
 #define ASSERT(expression)
 #endif
 
-/*
+/**
  * struct mraid_pci_blk - structure holds DMA memory block info
- * @param vaddr		: virtual address to a memory block
- * @param dma_addr	: DMA handle to a memory block
+ * @vaddr		: virtual address to a memory block
+ * @dma_addr		: DMA handle to a memory block
  *
  * This structure is filled up for the caller. It is the responsibilty of the
  * caller to allocate this array big enough to store addresses for all
diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h
index b8aa342..706fa05 100644
--- a/drivers/scsi/megaraid/megaraid_ioctl.h
+++ b/drivers/scsi/megaraid/megaraid_ioctl.h
@@ -22,23 +22,23 @@
 
 #include "mbox_defs.h"
 
-/**
- * con_log() - console log routine
- * @param level		: indicates the severity of the message.
- * @fparam mt		: format string
- *
- * con_log displays the error messages on the console based on the current
- * debug level. Also it attaches the appropriate kernel severity level with
- * the message.
- *
- *
- * consolge messages debug levels
+/*
+ * console messages debug levels
  */
 #define	CL_ANN		0	/* print unconditionally, announcements */
 #define CL_DLEVEL1	1	/* debug level 1, informative */
 #define CL_DLEVEL2	2	/* debug level 2, verbose */
 #define CL_DLEVEL3	3	/* debug level 3, very verbose */
 
+/**
+ * con_log() - console log routine
+ * @level		: indicates the severity of the message.
+ * @fmt			: format string
+ *
+ * con_log displays the error messages on the console based on the current
+ * debug level. Also it attaches the appropriate kernel severity level with
+ * the message.
+ */
 #define	con_log(level, fmt) if (LSI_DBGLVL >= level) printk fmt;
 
 /*
@@ -157,14 +157,14 @@
 /**
  * struct mraid_hba_info - information about the controller
  *
- * @param pci_vendor_id		: PCI vendor id
- * @param pci_device_id		: PCI device id
- * @param subsystem_vendor_id	: PCI subsystem vendor id
- * @param subsystem_device_id	: PCI subsystem device id
- * @param baseport		: base port of hba memory
- * @param pci_bus		: PCI bus
- * @param pci_dev_fn		: PCI device/function values
- * @param irq			: interrupt vector for the device
+ * @pci_vendor_id		: PCI vendor id
+ * @pci_device_id		: PCI device id
+ * @subsystem_vendor_id		: PCI subsystem vendor id
+ * @subsystem_device_id		: PCI subsystem device id
+ * @baseport			: base port of hba memory
+ * @pci_bus			: PCI bus
+ * @pci_dev_fn			: PCI device/function values
+ * @irq				: interrupt vector for the device
  *
  * Extended information of 256 bytes about the controller. Align on the single
  * byte boundary so that 32-bit applications can be run on 64-bit platform
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 7bac86d..04d0b69 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -10,13 +10,13 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_mbox.c
- * Version	: v2.20.4.9 (Jul 16 2006)
+ * Version	: v2.20.5.1 (Nov 16 2006)
  *
  * Authors:
- * 	Atul Mukker		<Atul.Mukker@lsil.com>
- * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsil.com>
- * 	Manoj Jose		<Manoj.Jose@lsil.com>
- * 	Seokmann Ju		<Seokmann.Ju@lsil.com>
+ * 	Atul Mukker		<Atul.Mukker@lsi.com>
+ * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsi.com>
+ * 	Manoj Jose		<Manoj.Jose@lsi.com>
+ * 	Seokmann Ju
  *
  * List of supported controllers
  *
@@ -107,6 +107,7 @@
 static int megaraid_mbox_get_max_sg(adapter_t *);
 static void megaraid_mbox_enum_raid_scsi(adapter_t *);
 static void megaraid_mbox_flush_cache(adapter_t *);
+static int megaraid_mbox_fire_sync_cmd(adapter_t *);
 
 static void megaraid_mbox_display_scb(adapter_t *, scb_t *);
 static void megaraid_mbox_setup_device_map(adapter_t *);
@@ -137,7 +138,7 @@
 
 
 
-MODULE_AUTHOR("sju@lsil.com");
+MODULE_AUTHOR("megaraidlinux@lsi.com");
 MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(MEGARAID_VERSION);
@@ -146,7 +147,7 @@
  * ### modules parameters for driver ###
  */
 
-/**
+/*
  * Set to enable driver to expose unconfigured disk to kernel
  */
 static int megaraid_expose_unconf_disks = 0;
@@ -154,7 +155,7 @@
 MODULE_PARM_DESC(unconf_disks,
 	"Set to expose unconfigured disks to kernel (default=0)");
 
-/**
+/*
  * driver wait time if the adapter's mailbox is busy
  */
 static unsigned int max_mbox_busy_wait = MBOX_BUSY_WAIT;
@@ -162,7 +163,7 @@
 MODULE_PARM_DESC(busy_wait,
 	"Max wait for mailbox in microseconds if busy (default=10)");
 
-/**
+/*
  * number of sectors per IO command
  */
 static unsigned int megaraid_max_sectors = MBOX_MAX_SECTORS;
@@ -170,7 +171,7 @@
 MODULE_PARM_DESC(max_sectors,
 	"Maximum number of sectors per IO command (default=128)");
 
-/**
+/*
  * number of commands per logical unit
  */
 static unsigned int megaraid_cmd_per_lun = MBOX_DEF_CMD_PER_LUN;
@@ -179,7 +180,7 @@
 	"Maximum number of commands per logical unit (default=64)");
 
 
-/**
+/*
  * Fast driver load option, skip scanning for physical devices during load.
  * This would result in non-disk devices being skipped during driver load
  * time. These can be later added though, using /proc/scsi/scsi
@@ -190,7 +191,7 @@
 	"Faster loading of the driver, skips physical devices! (default=0)");
 
 
-/**
+/*
  * mraid_debug level - threshold for amount of information to be displayed by
  * the driver. This level can be changed through modules parameters, ioctl or
  * sysfs/proc interface. By default, print the announcement messages only.
@@ -337,7 +338,7 @@
  *
  * Return value:
  * 	actual depth set
- **/
+ */
 static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
 	if (qdepth > MBOX_MAX_SCSI_CMDS)
@@ -369,8 +370,8 @@
  * megaraid_init - module load hook
  *
  * We register ourselves as hotplug enabled module and let PCI subsystem
- * discover our adaters
- **/
+ * discover our adapters.
+ */
 static int __init
 megaraid_init(void)
 {
@@ -405,7 +406,7 @@
 /**
  * megaraid_exit - driver unload entry point
  *
- * We simply unwrap the megaraid_init routine here
+ * We simply unwrap the megaraid_init routine here.
  */
 static void __exit
 megaraid_exit(void)
@@ -421,12 +422,12 @@
 
 /**
  * megaraid_probe_one - PCI hotplug entry point
- * @param pdev	: handle to this controller's PCI configuration space
- * @param id	: pci device id of the class of controllers
+ * @pdev	: handle to this controller's PCI configuration space
+ * @id		: pci device id of the class of controllers
  *
  * This routine should be called whenever a new adapter is detected by the
  * PCI hotplug susbsytem.
- **/
+ */
 static int __devinit
 megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -542,16 +543,15 @@
 
 
 /**
- * megaraid_detach_one - release the framework resources and call LLD release
- * routine
- * @param pdev	: handle for our PCI cofiguration space
+ * megaraid_detach_one - release framework resources and call LLD release routine
+ * @pdev	: handle for our PCI cofiguration space
  *
  * This routine is called during driver unload. We free all the allocated
  * resources and call the corresponding LLD so that it can also release all
  * its resources.
  *
- * This routine is also called from the PCI hotplug system
- **/
+ * This routine is also called from the PCI hotplug system.
+ */
 static void
 megaraid_detach_one(struct pci_dev *pdev)
 {
@@ -615,9 +615,9 @@
 
 /**
  * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA
- * @param device	: generice driver model device
+ * @pdev		: generic driver model device
  *
- * Shutdown notification, perform flush cache
+ * Shutdown notification, perform flush cache.
  */
 static void
 megaraid_mbox_shutdown(struct pci_dev *pdev)
@@ -643,10 +643,10 @@
 
 /**
  * megaraid_io_attach - attach a device with the IO subsystem
- * @param adapter	: controller's soft state
+ * @adapter		: controller's soft state
  *
- * Attach this device with the IO subsystem
- **/
+ * Attach this device with the IO subsystem.
+ */
 static int
 megaraid_io_attach(adapter_t *adapter)
 {
@@ -695,10 +695,10 @@
 
 /**
  * megaraid_io_detach - detach a device from the IO subsystem
- * @param adapter	: controller's soft state
+ * @adapter		: controller's soft state
  *
- * Detach this device from the IO subsystem
- **/
+ * Detach this device from the IO subsystem.
+ */
 static void
 megaraid_io_detach(adapter_t *adapter)
 {
@@ -722,13 +722,13 @@
 
 /**
  * megaraid_init_mbox - initialize controller
- * @param adapter	- our soft state
+ * @adapter		: our soft state
  *
- * . Allocate 16-byte aligned mailbox memory for firmware handshake
- * . Allocate controller's memory resources
- * . Find out all initialization data
- * . Allocate memory required for all the commands
- * . Use internal library of FW routines, build up complete soft state
+ * - Allocate 16-byte aligned mailbox memory for firmware handshake
+ * - Allocate controller's memory resources
+ * - Find out all initialization data
+ * - Allocate memory required for all the commands
+ * - Use internal library of FW routines, build up complete soft state
  */
 static int __devinit
 megaraid_init_mbox(adapter_t *adapter)
@@ -779,33 +779,39 @@
 		goto out_release_regions;
 	}
 
-	//
-	// Setup the rest of the soft state using the library of FW routines
-	//
+	/* initialize the mutual exclusion lock for the mailbox */
+	spin_lock_init(&raid_dev->mailbox_lock);
 
-	// request IRQ and register the interrupt service routine
+	/* allocate memory required for commands */
+	if (megaraid_alloc_cmd_packets(adapter) != 0)
+		goto out_iounmap;
+
+	/*
+	 * Issue SYNC cmd to flush the pending cmds in the adapter
+	 * and initialize its internal state
+	 */
+
+	if (megaraid_mbox_fire_sync_cmd(adapter))
+		con_log(CL_ANN, ("megaraid: sync cmd failed\n"));
+
+	/*
+	 * Setup the rest of the soft state using the library of
+	 * FW routines
+	 */
+
+	/* request IRQ and register the interrupt service routine */
 	if (request_irq(adapter->irq, megaraid_isr, IRQF_SHARED, "megaraid",
 		adapter)) {
 
 		con_log(CL_ANN, (KERN_WARNING
 			"megaraid: Couldn't register IRQ %d!\n", adapter->irq));
+		goto out_alloc_cmds;
 
-		goto out_iounmap;
-	}
-
-
-	// initialize the mutual exclusion lock for the mailbox
-	spin_lock_init(&raid_dev->mailbox_lock);
-
-	// allocate memory required for commands
-	if (megaraid_alloc_cmd_packets(adapter) != 0) {
-		goto out_free_irq;
 	}
 
 	// Product info
-	if (megaraid_mbox_product_info(adapter) != 0) {
-		goto out_alloc_cmds;
-	}
+	if (megaraid_mbox_product_info(adapter) != 0)
+		goto out_free_irq;
 
 	// Do we support extended CDBs
 	adapter->max_cdb_sz = 10;
@@ -874,9 +880,8 @@
 	 * Allocate resources required to issue FW calls, when sysfs is
 	 * accessed
 	 */
-	if (megaraid_sysfs_alloc_resources(adapter) != 0) {
-		goto out_alloc_cmds;
-	}
+	if (megaraid_sysfs_alloc_resources(adapter) != 0)
+		goto out_free_irq;
 
 	// Set the DMA mask to 64-bit. All supported controllers as capable of
 	// DMA in this range
@@ -920,10 +925,10 @@
 
 out_free_sysfs_res:
 	megaraid_sysfs_free_resources(adapter);
-out_alloc_cmds:
-	megaraid_free_cmd_packets(adapter);
 out_free_irq:
 	free_irq(adapter->irq, adapter);
+out_alloc_cmds:
+	megaraid_free_cmd_packets(adapter);
 out_iounmap:
 	iounmap(raid_dev->baseaddr);
 out_release_regions:
@@ -937,7 +942,7 @@
 
 /**
  * megaraid_fini_mbox - undo controller initialization
- * @param adapter	: our soft state
+ * @adapter		: our soft state
  */
 static void
 megaraid_fini_mbox(adapter_t *adapter)
@@ -967,12 +972,12 @@
 
 /**
  * megaraid_alloc_cmd_packets - allocate shared mailbox
- * @param adapter	: soft state of the raid controller
+ * @adapter		: soft state of the raid controller
  *
  * Allocate and align the shared mailbox. This maibox is used to issue
  * all the commands. For IO based controllers, the mailbox is also regsitered
  * with the FW. Allocate memory for all commands as well.
- * This is our big allocator
+ * This is our big allocator.
  */
 static int
 megaraid_alloc_cmd_packets(adapter_t *adapter)
@@ -1132,9 +1137,9 @@
 
 /**
  * megaraid_free_cmd_packets - free memory
- * @param adapter	: soft state of the raid controller
+ * @adapter		: soft state of the raid controller
  *
- * Release memory resources allocated for commands
+ * Release memory resources allocated for commands.
  */
 static void
 megaraid_free_cmd_packets(adapter_t *adapter)
@@ -1156,10 +1161,10 @@
 
 /**
  * megaraid_mbox_setup_dma_pools - setup dma pool for command packets
- * @param adapter	: HBA soft state
+ * @adapter		: HBA soft state
  *
- * setup the dma pools for mailbox, passthru and extended passthru structures,
- * and scatter-gather lists
+ * Setup the dma pools for mailbox, passthru and extended passthru structures,
+ * and scatter-gather lists.
  */
 static int
 megaraid_mbox_setup_dma_pools(adapter_t *adapter)
@@ -1252,10 +1257,10 @@
 
 /**
  * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets
- * @param adapter	: HBA soft state
+ * @adapter		: HBA soft state
  *
- * teardown the dma pool for mailbox, passthru and extended passthru
- * structures, and scatter-gather lists
+ * Teardown the dma pool for mailbox, passthru and extended passthru
+ * structures, and scatter-gather lists.
  */
 static void
 megaraid_mbox_teardown_dma_pools(adapter_t *adapter)
@@ -1300,10 +1305,11 @@
 /**
  * megaraid_alloc_scb - detach and return a scb from the free list
  * @adapter	: controller's soft state
+ * @scp		: pointer to the scsi command to be executed
  *
- * return the scb from the head of the free list. NULL if there are none
- * available
- **/
+ * Return the scb from the head of the free list. %NULL if there are none
+ * available.
+ */
 static scb_t *
 megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp)
 {
@@ -1337,11 +1343,11 @@
  * @adapter	: controller's soft state
  * @scb		: scb to be freed
  *
- * return the scb back to the free list of scbs. The caller must 'flush' the
+ * Return the scb back to the free list of scbs. The caller must 'flush' the
  * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc.
  * NOTE NOTE: Make sure the scb is not on any list before calling this
  * routine.
- **/
+ */
 static inline void
 megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb)
 {
@@ -1362,10 +1368,10 @@
 
 /**
  * megaraid_mbox_mksgl - make the scatter-gather list
- * @adapter	- controller's soft state
- * @scb		- scsi control block
+ * @adapter	: controller's soft state
+ * @scb		: scsi control block
  *
- * prepare the scatter-gather list
+ * Prepare the scatter-gather list.
  */
 static int
 megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
@@ -1435,10 +1441,10 @@
 
 /**
  * mbox_post_cmd - issue a mailbox command
- * @adapter	- controller's soft state
- * @scb		- command to be issued
+ * @adapter	: controller's soft state
+ * @scb		: command to be issued
  *
- * post the command to the controller if mailbox is availble.
+ * Post the command to the controller if mailbox is available.
  */
 static int
 mbox_post_cmd(adapter_t *adapter, scb_t *scb)
@@ -1518,7 +1524,7 @@
  * Queue entry point for mailbox based controllers.
  */
 static int
-megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *))
+megaraid_queue_command(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 {
 	adapter_t	*adapter;
 	scb_t		*scb;
@@ -1548,15 +1554,15 @@
 }
 
 /**
- * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid
- * firmware lingua
- * @adapter	- controller's soft state
- * @scp		- mid-layer scsi command pointer
- * @busy	- set if request could not be completed because of lack of
+ * megaraid_mbox_build_cmd - transform the mid-layer scsi commands
+ * @adapter	: controller's soft state
+ * @scp		: mid-layer scsi command pointer
+ * @busy	: set if request could not be completed because of lack of
  *		resources
  *
- * convert the command issued by mid-layer to format understood by megaraid
- * firmware. We also complete certain command without sending them to firmware
+ * Transform the mid-layer scsi command to megaraid firmware lingua.
+ * Convert the command issued by mid-layer to format understood by megaraid
+ * firmware. We also complete certain commands without sending them to firmware.
  */
 static scb_t *
 megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
@@ -1937,9 +1943,9 @@
 /**
  * megaraid_mbox_runpendq - execute commands queued in the pending queue
  * @adapter	: controller's soft state
- * @scb		: SCB to be queued in the pending list
+ * @scb_q	: SCB to be queued in the pending list
  *
- * scan the pending list for commands which are not yet issued and try to
+ * Scan the pending list for commands which are not yet issued and try to
  * post to the controller. The SCB can be a null pointer, which would indicate
  * no SCB to be queue, just try to execute the ones in the pending list.
  *
@@ -2012,11 +2018,11 @@
 
 /**
  * megaraid_mbox_prepare_pthru - prepare a command for physical devices
- * @adapter	- pointer to controller's soft state
- * @scb		- scsi control block
- * @scp		- scsi command from the mid-layer
+ * @adapter	: pointer to controller's soft state
+ * @scb		: scsi control block
+ * @scp		: scsi command from the mid-layer
  *
- * prepare a command for the scsi physical devices
+ * Prepare a command for the scsi physical devices.
  */
 static void
 megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb,
@@ -2060,12 +2066,12 @@
 
 /**
  * megaraid_mbox_prepare_epthru - prepare a command for physical devices
- * @adapter	- pointer to controller's soft state
- * @scb		- scsi control block
- * @scp		- scsi command from the mid-layer
+ * @adapter	: pointer to controller's soft state
+ * @scb		: scsi control block
+ * @scp		: scsi command from the mid-layer
  *
- * prepare a command for the scsi physical devices. This rountine prepares
- * commands for devices which can take extended CDBs (>10 bytes)
+ * Prepare a command for the scsi physical devices. This rountine prepares
+ * commands for devices which can take extended CDBs (>10 bytes).
  */
 static void
 megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,
@@ -2109,9 +2115,9 @@
 
 /**
  * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs
- * @adapter	- controller's soft state
+ * @adapter	: controller's soft state
  *
- * Interrupt ackrowledgement sequence for memory mapped HBAs. Find out the
+ * Interrupt acknowledgement sequence for memory mapped HBAs. Find out the
  * completed command and put them on the completed list for later processing.
  *
  * Returns:	1 if the interrupt is valid, 0 otherwise
@@ -2224,9 +2230,8 @@
 
 /**
  * megaraid_isr - isr for memory based mailbox based controllers
- * @irq		- irq
- * @devp	- pointer to our soft state
- * @regs	- unused
+ * @irq		: irq
+ * @devp	: pointer to our soft state
  *
  * Interrupt service routine for memory-mapped mailbox controllers.
  */
@@ -2671,7 +2676,7 @@
  * the FW is still live, in which case the outstanding commands counter mut go
  * down to 0. If that happens, also issue the reservation reset command to
  * relinquish (possible) reservations on the logical drives connected to this
- * host
+ * host.
  **/
 static int
 megaraid_reset_handler(struct scsi_cmnd *scp)
@@ -2823,11 +2828,11 @@
 
 /**
  * mbox_post_sync_cmd() - blocking command to the mailbox based controllers
- * @adapter	- controller's soft state
- * @raw_mbox	- the mailbox
+ * @adapter	: controller's soft state
+ * @raw_mbox	: the mailbox
  *
  * Issue a scb in synchronous and non-interrupt mode for mailbox based
- * controllers
+ * controllers.
  */
 static int
 mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[])
@@ -2955,12 +2960,12 @@
 
 /**
  * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers
- * @adapter	- controller's soft state
- * @raw_mbox	- the mailbox
+ * @adapter	: controller's soft state
+ * @raw_mbox	: the mailbox
  *
  * Issue a scb in synchronous and non-interrupt mode for mailbox based
  * controllers. This is a faster version of the synchronous command and
- * therefore can be called in interrupt-context as well
+ * therefore can be called in interrupt-context as well.
  */
 static int
 mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
@@ -3008,10 +3013,10 @@
 
 /**
  * megaraid_busywait_mbox() - Wait until the controller's mailbox is available
- * @raid_dev	- RAID device (HBA) soft state
+ * @raid_dev	: RAID device (HBA) soft state
  *
- * wait until the controller's mailbox is available to accept more commands.
- * wait for at most 1 second
+ * Wait until the controller's mailbox is available to accept more commands.
+ * Wait for at most 1 second.
  */
 static int
 megaraid_busywait_mbox(mraid_device_t *raid_dev)
@@ -3032,9 +3037,9 @@
 
 /**
  * megaraid_mbox_product_info - some static information about the controller
- * @adapter	- our soft state
+ * @adapter	: our soft state
  *
- * issue commands to the controller to grab some parameters required by our
+ * Issue commands to the controller to grab some parameters required by our
  * caller.
  */
 static int
@@ -3157,10 +3162,10 @@
 
 /**
  * megaraid_mbox_extended_cdb - check for support for extended CDBs
- * @adapter	- soft state for the controller
+ * @adapter	: soft state for the controller
  *
- * this routine check whether the controller in question supports extended
- * ( > 10 bytes ) CDBs
+ * This routine check whether the controller in question supports extended
+ * ( > 10 bytes ) CDBs.
  */
 static int
 megaraid_mbox_extended_cdb(adapter_t *adapter)
@@ -3193,8 +3198,8 @@
 
 /**
  * megaraid_mbox_support_ha - Do we support clustering
- * @adapter	- soft state for the controller
- * @init_id	- ID of the initiator
+ * @adapter	: soft state for the controller
+ * @init_id	: ID of the initiator
  *
  * Determine if the firmware supports clustering and the ID of the initiator.
  */
@@ -3236,9 +3241,9 @@
 
 /**
  * megaraid_mbox_support_random_del - Do we support random deletion
- * @adapter	- soft state for the controller
+ * @adapter	: soft state for the controller
  *
- * Determine if the firmware supports random deletion
+ * Determine if the firmware supports random deletion.
  * Return:	1 is operation supported, 0 otherwise
  */
 static int
@@ -3271,10 +3276,10 @@
 
 /**
  * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware
- * @adapter	- soft state for the controller
+ * @adapter	: soft state for the controller
  *
  * Find out the maximum number of scatter-gather elements supported by the
- * firmware
+ * firmware.
  */
 static int
 megaraid_mbox_get_max_sg(adapter_t *adapter)
@@ -3311,10 +3316,10 @@
 
 /**
  * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels
- * @adapter	- soft state for the controller
+ * @adapter	: soft state for the controller
  *
- * Enumerate the RAID and SCSI channels for ROMB platoforms so that channels
- * can be exported as regular SCSI channels
+ * Enumerate the RAID and SCSI channels for ROMB platforms so that channels
+ * can be exported as regular SCSI channels.
  */
 static void
 megaraid_mbox_enum_raid_scsi(adapter_t *adapter)
@@ -3348,9 +3353,9 @@
 
 /**
  * megaraid_mbox_flush_cache - flush adapter and disks cache
- * @param adapter	: soft state for the controller
+ * @adapter		: soft state for the controller
  *
- * Flush adapter cache followed by disks cache
+ * Flush adapter cache followed by disks cache.
  */
 static void
 megaraid_mbox_flush_cache(adapter_t *adapter)
@@ -3380,13 +3385,91 @@
 
 
 /**
+ * megaraid_mbox_fire_sync_cmd - fire the sync cmd
+ * @adapter		: soft state for the controller
+ *
+ * Clears the pending cmds in FW and reinits its RAID structs.
+ */
+static int
+megaraid_mbox_fire_sync_cmd(adapter_t *adapter)
+{
+	mbox_t	*mbox;
+	uint8_t	raw_mbox[sizeof(mbox_t)];
+	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
+	mbox64_t *mbox64;
+	int	status = 0;
+	int i;
+	uint32_t dword;
+
+	mbox = (mbox_t *)raw_mbox;
+
+	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+	raw_mbox[0] = 0xFF;
+
+	mbox64	= raid_dev->mbox64;
+	mbox	= raid_dev->mbox;
+
+	/* Wait until mailbox is free */
+	if (megaraid_busywait_mbox(raid_dev) != 0) {
+		status = 1;
+		goto blocked_mailbox;
+	}
+
+	/* Copy mailbox data into host structure */
+	memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16);
+	mbox->cmdid		= 0xFE;
+	mbox->busy		= 1;
+	mbox->poll		= 0;
+	mbox->ack		= 0;
+	mbox->numstatus		= 0;
+	mbox->status		= 0;
+
+	wmb();
+	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+
+	/* Wait for maximum 1 min for status to post.
+	 * If the Firmware SUPPORTS the ABOVE COMMAND,
+	 * mbox->cmd will be set to 0
+	 * else
+	 * the firmware will reject the command with
+	 * mbox->numstatus set to 1
+	 */
+
+	i = 0;
+	status = 0;
+	while (!mbox->numstatus && mbox->cmd == 0xFF) {
+		rmb();
+		msleep(1);
+		i++;
+		if (i > 1000 * 60) {
+			status = 1;
+			break;
+		}
+	}
+	if (mbox->numstatus == 1)
+		status = 1; /*cmd not supported*/
+
+	/* Check for interrupt line */
+	dword = RDOUTDOOR(raid_dev);
+	WROUTDOOR(raid_dev, dword);
+	WRINDOOR(raid_dev,2);
+
+	return status;
+
+blocked_mailbox:
+	con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n"));
+	return status;
+}
+
+/**
  * megaraid_mbox_display_scb - display SCB information, mostly debug purposes
- * @param adapter	: controllers' soft state
- * @param scb		: SCB to be displayed
- * @param level	: debug level for console print
+ * @adapter		: controller's soft state
+ * @scb			: SCB to be displayed
+ * @level		: debug level for console print
  *
  * Diplay information about the given SCB iff the current debug level is
- * verbose
+ * verbose.
  */
 static void
 megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb)
@@ -3434,7 +3517,7 @@
  * scsi addresses and megaraid scsi and logical drive addresses. We export
  * scsi devices on their actual addresses, whereas the logical drives are
  * exported on a virtual scsi channel.
- **/
+ */
 static void
 megaraid_mbox_setup_device_map(adapter_t *adapter)
 {
@@ -3472,7 +3555,7 @@
 
 /**
  * megaraid_cmm_register - register with the mangement module
- * @param adapter	: HBA soft state
+ * @adapter		: HBA soft state
  *
  * Register with the management module, which allows applications to issue
  * ioctl calls to the drivers. This interface is used by the management module
@@ -3562,11 +3645,11 @@
 
 /**
  * megaraid_cmm_unregister - un-register with the mangement module
- * @param adapter	: HBA soft state
+ * @adapter		: HBA soft state
  *
  * Un-register with the management module.
  * FIXME: mgmt module must return failure for unregister if it has pending
- * commands in LLD
+ * commands in LLD.
  */
 static int
 megaraid_cmm_unregister(adapter_t *adapter)
@@ -3579,9 +3662,9 @@
 
 /**
  * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD
- * @param drvr_data	: LLD specific data
- * @param kioc		: CMM interface packet
- * @param action	: command action
+ * @drvr_data		: LLD specific data
+ * @kioc		: CMM interface packet
+ * @action		: command action
  *
  * This routine is invoked whenever the Common Mangement Module (CMM) has a
  * command for us. The 'action' parameter specifies if this is a new command
@@ -3634,8 +3717,8 @@
 
 /**
  * megaraid_mbox_mm_command - issues commands routed through CMM
- * @param adapter	: HBA soft state
- * @param kioc		: management command packet
+ * @adapter		: HBA soft state
+ * @kioc		: management command packet
  *
  * Issues commands, which are routed through the management module.
  */
@@ -3804,8 +3887,8 @@
 
 /**
  * gather_hbainfo - HBA characteristics for the applications
- * @param adapter	: HBA soft state
- * @param hinfo		: pointer to the caller's host info strucuture
+ * @adapter		: HBA soft state
+ * @hinfo		: pointer to the caller's host info strucuture
  */
 static int
 gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo)
@@ -3839,16 +3922,15 @@
 
 /**
  * megaraid_sysfs_alloc_resources - allocate sysfs related resources
+ * @adapter	: controller's soft state
  *
  * Allocate packets required to issue FW calls whenever the sysfs attributes
  * are read. These attributes would require up-to-date information from the
  * FW. Also set up resources for mutual exclusion to share these resources and
  * the wait queue.
  *
- * @param adapter : controller's soft state
- *
- * @return 0 on success
- * @return -ERROR_CODE on failure
+ * Return 0 on success.
+ * Return -ERROR_CODE on failure.
  */
 static int
 megaraid_sysfs_alloc_resources(adapter_t *adapter)
@@ -3885,10 +3967,9 @@
 
 /**
  * megaraid_sysfs_free_resources - free sysfs related resources
+ * @adapter	: controller's soft state
  *
  * Free packets allocated for sysfs FW commands
- *
- * @param adapter : controller's soft state
  */
 static void
 megaraid_sysfs_free_resources(adapter_t *adapter)
@@ -3907,10 +3988,9 @@
 
 /**
  * megaraid_sysfs_get_ldmap_done - callback for get ldmap
+ * @uioc	: completed packet
  *
  * Callback routine called in the ISR/tasklet context for get ldmap call
- *
- * @param uioc : completed packet
  */
 static void
 megaraid_sysfs_get_ldmap_done(uioc_t *uioc)
@@ -3926,12 +4006,11 @@
 
 /**
  * megaraid_sysfs_get_ldmap_timeout - timeout handling for get ldmap
+ * @data	: timed out packet
  *
  * Timeout routine to recover and return to application, in case the adapter
- * has stopped responding. A timeout of 60 seconds for this command seem like
- * a good value
- *
- * @param uioc : timed out packet
+ * has stopped responding. A timeout of 60 seconds for this command seems like
+ * a good value.
  */
 static void
 megaraid_sysfs_get_ldmap_timeout(unsigned long data)
@@ -3948,6 +4027,7 @@
 
 /**
  * megaraid_sysfs_get_ldmap - get update logical drive map
+ * @adapter	: controller's soft state
  *
  * This routine will be called whenever user reads the logical drive
  * attributes, go get the current logical drive mapping table from the
@@ -3959,10 +4039,8 @@
  * standalone libary. For now, this should suffice since there is no other
  * user of this interface.
  *
- * @param adapter : controller's soft state
- *
- * @return 0 on success
- * @return -1 on failure
+ * Return 0 on success.
+ * Return -1 on failure.
  */
 static int
 megaraid_sysfs_get_ldmap(adapter_t *adapter)
@@ -4064,13 +4142,12 @@
 
 /**
  * megaraid_sysfs_show_app_hndl - display application handle for this adapter
+ * @cdev	: class device object representation for the host
+ * @buf		: buffer to send data to
  *
  * Display the handle used by the applications while executing management
  * tasks on the adapter. We invoke a management module API to get the adapter
  * handle, since we do not interface with applications directly.
- *
- * @param cdev	: class device object representation for the host
- * @param buf	: buffer to send data to
  */
 static ssize_t
 megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf)
@@ -4087,16 +4164,18 @@
 
 /**
  * megaraid_sysfs_show_ldnum - display the logical drive number for this device
+ * @dev		: device object representation for the scsi device
+ * @attr	: device attribute to show
+ * @buf		: buffer to send data to
  *
  * Display the logical drive number for the device in question, if it a valid
- * logical drive. For physical devices, "-1" is returned
- * The logical drive number is displayed in following format
+ * logical drive. For physical devices, "-1" is returned.
+ *
+ * The logical drive number is displayed in following format:
  *
  * <SCSI ID> <LD NUM> <LD STICKY ID> <APP ADAPTER HANDLE>
- *   <int>     <int>       <int>            <int>
  *
- * @param dev	: device object representation for the scsi device
- * @param buf	: buffer to send data to
+ *   <int>     <int>       <int>            <int>
  */
 static ssize_t
 megaraid_sysfs_show_ldnum(struct device *dev, struct device_attribute *attr, char *buf)
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 2b5a328..9de803c 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.h
+++ b/drivers/scsi/megaraid/megaraid_mbox.h
@@ -21,8 +21,8 @@
 #include "megaraid_ioctl.h"
 
 
-#define MEGARAID_VERSION	"2.20.4.9"
-#define MEGARAID_EXT_VERSION	"(Release Date: Sun Jul 16 12:27:22 EST 2006)"
+#define MEGARAID_VERSION	"2.20.5.1"
+#define MEGARAID_EXT_VERSION	"(Release Date: Thu Nov 16 15:32:35 EST 2006)"
 
 
 /*
@@ -146,27 +146,27 @@
 
 /**
  * mraid_device_t - adapter soft state structure for mailbox controllers
- * @param una_mbox64		: 64-bit mbox - unaligned
- * @param una_mbox64_dma	: mbox dma addr - unaligned
- * @param mbox			: 32-bit mbox - aligned
- * @param mbox64		: 64-bit mbox - aligned
- * @param mbox_dma		: mbox dma addr - aligned
- * @param mailbox_lock		: exclusion lock for the mailbox
- * @param baseport		: base port of hba memory
- * @param baseaddr		: mapped addr of hba memory
- * @param mbox_pool		: pool of mailboxes
- * @param mbox_pool_handle	: handle for the mailbox pool memory
- * @param epthru_pool		: a pool for extended passthru commands
- * @param epthru_pool_handle	: handle to the pool above
- * @param sg_pool		: pool of scatter-gather lists for this driver
- * @param sg_pool_handle	: handle to the pool above
- * @param ccb_list		: list of our command control blocks
- * @param uccb_list		: list of cmd control blocks for mgmt module
- * @param umbox64		: array of mailbox for user commands (cmm)
- * @param pdrv_state		: array for state of each physical drive.
- * @param last_disp		: flag used to show device scanning
- * @param hw_error		: set if FW not responding
- * @param fast_load		: If set, skip physical device scanning
+ * @una_mbox64			: 64-bit mbox - unaligned
+ * @una_mbox64_dma		: mbox dma addr - unaligned
+ * @mbox			: 32-bit mbox - aligned
+ * @mbox64			: 64-bit mbox - aligned
+ * @mbox_dma			: mbox dma addr - aligned
+ * @mailbox_lock		: exclusion lock for the mailbox
+ * @baseport			: base port of hba memory
+ * @baseaddr			: mapped addr of hba memory
+ * @mbox_pool			: pool of mailboxes
+ * @mbox_pool_handle		: handle for the mailbox pool memory
+ * @epthru_pool			: a pool for extended passthru commands
+ * @epthru_pool_handle		: handle to the pool above
+ * @sg_pool			: pool of scatter-gather lists for this driver
+ * @sg_pool_handle		: handle to the pool above
+ * @ccb_list			: list of our command control blocks
+ * @uccb_list			: list of cmd control blocks for mgmt module
+ * @umbox64			: array of mailbox for user commands (cmm)
+ * @pdrv_state			: array for state of each physical drive.
+ * @last_disp			: flag used to show device scanning
+ * @hw_error			: set if FW not responding
+ * @fast_load			: If set, skip physical device scanning
  * @channel_class		: channel class, RAID or SCSI
  * @sysfs_sem			: semaphore to serialize access to sysfs res.
  * @sysfs_uioc			: management packet to issue FW calls from sysfs
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index d85b9a8..f33a678 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -67,7 +67,7 @@
 
 static wait_queue_head_t wait_q;
 
-static struct file_operations lsi_fops = {
+static const struct file_operations lsi_fops = {
 	.open	= mraid_mm_open,
 	.ioctl	= mraid_mm_ioctl,
 #ifdef CONFIG_COMPAT
@@ -78,10 +78,10 @@
 
 /**
  * mraid_mm_open - open routine for char node interface
- * @inod	: unused
+ * @inode	: unused
  * @filep	: unused
  *
- * allow ioctl operations by apps only if they superuser privilege
+ * Allow ioctl operations by apps only if they have superuser privilege.
  */
 static int
 mraid_mm_open(struct inode *inode, struct file *filep)
@@ -214,7 +214,9 @@
 /**
  * mraid_mm_get_adapter - Returns corresponding adapters for the mimd packet
  * @umimd	: User space mimd_t ioctl packet
- * @adapter	: pointer to the adapter (OUT)
+ * @rval	: returned success/error status
+ *
+ * The function return value is a pointer to the located @adapter.
  */
 static mraid_mmadp_t *
 mraid_mm_get_adapter(mimd_t __user *umimd, int *rval)
@@ -252,11 +254,11 @@
 	return adapter;
 }
 
-/*
- * handle_drvrcmd - This routine checks if the opcode is a driver
- * 			  cmd and if it is, handles it.
+/**
+ * handle_drvrcmd - Checks if the opcode is a driver cmd and if it is, handles it.
  * @arg		: packet sent by the user app
  * @old_ioctl	: mimd if 1; uioc otherwise
+ * @rval	: pointer for command's returned value (not function status)
  */
 static int
 handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval)
@@ -322,8 +324,8 @@
 
 /**
  * mimd_to_kioc	- Converter from old to new ioctl format
- *
  * @umimd	: user space old MIMD IOCTL
+ * @adp		: adapter softstate
  * @kioc	: kernel space new format IOCTL
  *
  * Routine to convert MIMD interface IOCTL to new interface IOCTL packet. The
@@ -474,7 +476,6 @@
 
 /**
  * mraid_mm_attch_buf - Attach a free dma buffer for required size
- *
  * @adp		: Adapter softstate
  * @kioc	: kioc that the buffer needs to be attached to
  * @xferlen	: required length for buffer
@@ -607,7 +608,6 @@
 
 /**
  * mraid_mm_dealloc_kioc - Return kioc to free pool
- *
  * @adp		: Adapter softstate
  * @kioc	: uioc_t node to be returned to free pool
  */
@@ -652,7 +652,6 @@
 
 /**
  * lld_ioctl - Routine to issue ioctl to low level drvr
- *
  * @adp		: The adapter handle
  * @kioc	: The ioctl packet with kernel addresses
  */
@@ -705,7 +704,6 @@
 
 /**
  * ioctl_done - callback from the low level driver
- *
  * @kioc	: completed ioctl packet
  */
 static void
@@ -756,9 +754,8 @@
 }
 
 
-/*
- * lld_timedout	: callback from the expired timer
- *
+/**
+ * lld_timedout	- callback from the expired timer
  * @ptr		: ioctl packet that timed out
  */
 static void
@@ -776,8 +773,7 @@
 
 
 /**
- * kioc_to_mimd	: Converter from new back to old format
- *
+ * kioc_to_mimd	- Converter from new back to old format
  * @kioc	: Kernel space IOCTL packet (successfully issued)
  * @mimd	: User space MIMD packet
  */
@@ -855,7 +851,6 @@
 
 /**
  * hinfo_to_cinfo - Convert new format hba info into old format
- *
  * @hinfo	: New format, more comprehensive adapter info
  * @cinfo	: Old format adapter info to support mimd_t apps
  */
@@ -878,10 +873,9 @@
 }
 
 
-/*
- * mraid_mm_register_adp - Registration routine for low level drvrs
- *
- * @adp	: Adapter objejct
+/**
+ * mraid_mm_register_adp - Registration routine for low level drivers
+ * @lld_adp	: Adapter objejct
  */
 int
 mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
@@ -1007,15 +1001,14 @@
 
 /**
  * mraid_mm_adapter_app_handle - return the application handle for this adapter
+ * @unique_id	: adapter unique identifier
  *
- * For the given driver data, locate the adadpter in our global list and
+ * For the given driver data, locate the adapter in our global list and
  * return the corresponding handle, which is also used by applications to
  * uniquely identify an adapter.
  *
- * @param unique_id : adapter unique identifier
- *
- * @return adapter handle if found in the list
- * @return 0 if adapter could not be located, should never happen though
+ * Return adapter handle if found in the list.
+ * Return 0 if adapter could not be located, should never happen though.
  */
 uint32_t
 mraid_mm_adapter_app_handle(uint32_t unique_id)
@@ -1040,7 +1033,6 @@
 
 /**
  * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter
- *
  * @adp	: Adapter softstate
  *
  * We maintain a pool of dma buffers per each adapter. Each pool has one
@@ -1093,11 +1085,11 @@
 }
 
 
-/*
+/**
  * mraid_mm_unregister_adp - Unregister routine for low level drivers
- *				  Assume no outstanding ioctls to llds.
- *
  * @unique_id	: UID of the adpater
+ *
+ * Assumes no outstanding ioctls to llds.
  */
 int
 mraid_mm_unregister_adp(uint32_t unique_id)
@@ -1131,7 +1123,6 @@
 
 /**
  * mraid_mm_free_adp_resources - Free adapter softstate
- *
  * @adp	: Adapter softstate
  */
 static void
@@ -1162,7 +1153,6 @@
 
 /**
  * mraid_mm_teardown_dma_pools - Free all per adapter dma buffers
- *
  * @adp	: Adapter softstate
  */
 static void
@@ -1190,7 +1180,7 @@
 }
 
 /**
- * mraid_mm_init	: Module entry point
+ * mraid_mm_init	- Module entry point
  */
 static int __init
 mraid_mm_init(void)
@@ -1214,10 +1204,13 @@
 }
 
 
-/**
- * mraid_mm_compat_ioctl	: 32bit to 64bit ioctl conversion routine
- */
 #ifdef CONFIG_COMPAT
+/**
+ * mraid_mm_compat_ioctl	- 32bit to 64bit ioctl conversion routine
+ * @filep	: file operations pointer (ignored)
+ * @cmd		: ioctl command
+ * @arg		: user ioctl packet
+ */
 static long
 mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd,
 		      unsigned long arg)
@@ -1231,7 +1224,7 @@
 #endif
 
 /**
- * mraid_mm_exit	: Module exit point
+ * mraid_mm_exit	- Module exit point
  */
 static void __exit
 mraid_mm_exit(void)
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index b5bdd0d..7a81267 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,11 +10,13 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_sas.c
- * Version	: v00.00.03.05
+ * Version	: v00.00.03.10-rc1
  *
  * Authors:
- * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsi.com>
- * 	Sumant Patro		<Sumant.Patro@lsi.com>
+ *	(email-id : megaraidlinux@lsi.com)
+ * 	Sreenivas Bagalkote
+ * 	Sumant Patro
+ *	Bo Yang
  *
  * List of supported controllers
  *
@@ -35,6 +37,7 @@
 #include <asm/uaccess.h>
 #include <linux/fs.h>
 #include <linux/compat.h>
+#include <linux/blkdev.h>
 #include <linux/mutex.h>
 
 #include <scsi/scsi.h>
@@ -841,6 +844,11 @@
 
 	instance = (struct megasas_instance *)
 	    scmd->device->host->hostdata;
+
+	/* Don't process if we have already declared adapter dead */
+	if (instance->hw_crit_error)
+		return SCSI_MLQUEUE_HOST_BUSY;
+
 	scmd->scsi_done = done;
 	scmd->result = 0;
 
@@ -850,6 +858,18 @@
 		goto out_done;
 	}
 
+	switch (scmd->cmnd[0]) {
+	case SYNCHRONIZE_CACHE:
+		/*
+		 * FW takes care of flush cache on its own
+		 * No need to send it down
+		 */
+		scmd->result = DID_OK << 16;
+		goto out_done;
+	default:
+		break;
+	}
+
 	cmd = megasas_get_cmd(instance);
 	if (!cmd)
 		return SCSI_MLQUEUE_HOST_BUSY;
@@ -1010,6 +1030,49 @@
 }
 
 /**
+ * megasas_bios_param - Returns disk geometry for a disk
+ * @sdev: 		device handle
+ * @bdev:		block device
+ * @capacity:		drive capacity
+ * @geom:		geometry parameters
+ */
+static int
+megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+		 sector_t capacity, int geom[])
+{
+	int heads;
+	int sectors;
+	sector_t cylinders;
+	unsigned long tmp;
+	/* Default heads (64) & sectors (32) */
+	heads = 64;
+	sectors = 32;
+
+	tmp = heads * sectors;
+	cylinders = capacity;
+
+	sector_div(cylinders, tmp);
+
+	/*
+	 * Handle extended translation size for logical drives > 1Gb
+	 */
+
+	if (capacity >= 0x200000) {
+		heads = 255;
+		sectors = 63;
+		tmp = heads*sectors;
+		cylinders = capacity;
+		sector_div(cylinders, tmp);
+	}
+
+	geom[0] = heads;
+	geom[1] = sectors;
+	geom[2] = cylinders;
+
+	return 0;
+}
+
+/**
  * megasas_service_aen -	Processes an event notification
  * @instance:			Adapter soft state
  * @cmd:			AEN command completed by the ISR
@@ -1049,6 +1112,7 @@
 	.eh_device_reset_handler = megasas_reset_device,
 	.eh_bus_reset_handler = megasas_reset_bus_host,
 	.eh_host_reset_handler = megasas_reset_bus_host,
+	.bios_param = megasas_bios_param,
 	.use_clustering = ENABLE_CLUSTERING,
 };
 
@@ -1282,11 +1346,13 @@
 	if(instance->instancet->clear_intr(instance->reg_set))
 		return IRQ_NONE;
 
+	if (instance->hw_crit_error)
+		goto out_done;
         /*
 	 * Schedule the tasklet for cmd completion
 	 */
 	tasklet_schedule(&instance->isr_tasklet);
-
+out_done:
 	return IRQ_HANDLED;
 }
 
@@ -1741,6 +1807,10 @@
 	struct megasas_cmd *cmd;
 	struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
 
+	/* If we have already declared adapter dead, donot complete cmds */
+	if (instance->hw_crit_error)
+		return;
+
 	producer = *instance->producer;
 	consumer = *instance->consumer;
 
@@ -2655,9 +2725,9 @@
 	 * For each user buffer, create a mirror buffer and copy in
 	 */
 	for (i = 0; i < ioc->sge_count; i++) {
-		kbuff_arr[i] = pci_alloc_consistent(instance->pdev,
+		kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev,
 						    ioc->sgl[i].iov_len,
-						    &buf_handle);
+						    &buf_handle, GFP_KERNEL);
 		if (!kbuff_arr[i]) {
 			printk(KERN_DEBUG "megasas: Failed to alloc "
 			       "kernel SGL buffer for IOCTL \n");
@@ -2684,8 +2754,8 @@
 	}
 
 	if (ioc->sense_len) {
-		sense = pci_alloc_consistent(instance->pdev, ioc->sense_len,
-					     &sense_handle);
+		sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len,
+					     &sense_handle, GFP_KERNEL);
 		if (!sense) {
 			error = -ENOMEM;
 			goto out;
@@ -2744,12 +2814,12 @@
 
       out:
 	if (sense) {
-		pci_free_consistent(instance->pdev, ioc->sense_len,
+		dma_free_coherent(&instance->pdev->dev, ioc->sense_len,
 				    sense, sense_handle);
 	}
 
 	for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
-		pci_free_consistent(instance->pdev,
+		dma_free_coherent(&instance->pdev->dev,
 				    kern_sge32[i].length,
 				    kbuff_arr[i], kern_sge32[i].phys_addr);
 	}
@@ -2913,7 +2983,7 @@
 /*
  * File operations structure for management interface
  */
-static struct file_operations megasas_mgmt_fops = {
+static const struct file_operations megasas_mgmt_fops = {
 	.owner = THIS_MODULE,
 	.open = megasas_mgmt_open,
 	.release = megasas_mgmt_release,
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 55eddcf..e862992 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -15,12 +15,12 @@
 #ifndef LSI_MEGARAID_SAS_H
 #define LSI_MEGARAID_SAS_H
 
-/**
+/*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION				"00.00.03.05"
-#define MEGASAS_RELDATE				"Oct 02, 2006"
-#define MEGASAS_EXT_VERSION			"Mon Oct 02 11:21:32 PDT 2006"
+#define MEGASAS_VERSION				"00.00.03.10-rc1"
+#define MEGASAS_RELDATE				"Feb 14, 2007"
+#define MEGASAS_EXT_VERSION			"Wed Feb 14 10:14:25 PST 2007"
 
 /*
  * Device IDs
@@ -40,7 +40,7 @@
  * "message frames"
  */
 
-/**
+/*
  * FW posts its state in upper 4 bits of outbound_msg_0 register
  */
 #define MFI_STATE_MASK				0xF0000000
@@ -58,7 +58,7 @@
 
 #define MEGAMFI_FRAME_SIZE			64
 
-/**
+/*
  * During FW init, clear pending cmds & reset state using inbound_msg_0
  *
  * ABORT	: Abort all pending cmds
@@ -78,7 +78,7 @@
 						MFI_INIT_MFIMODE| \
 						MFI_INIT_ABORT
 
-/**
+/*
  * MFI frame flags
  */
 #define MFI_FRAME_POST_IN_REPLY_QUEUE		0x0000
@@ -92,12 +92,12 @@
 #define MFI_FRAME_DIR_READ			0x0010
 #define MFI_FRAME_DIR_BOTH			0x0018
 
-/**
+/*
  * Definition for cmd_status
  */
 #define MFI_CMD_STATUS_POLL_MODE		0xFF
 
-/**
+/*
  * MFI command opcodes
  */
 #define MFI_CMD_INIT				0x00
@@ -128,7 +128,7 @@
 #define MR_DCMD_CLUSTER_RESET_ALL		0x08010100
 #define MR_DCMD_CLUSTER_RESET_LD		0x08010200
 
-/**
+/*
  * MFI command completion codes
  */
 enum MFI_STAT {
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index 1ddd7a1..be41aad 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -1,7 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 
 #include <asm/page.h>
diff --git a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c
index 890e9e2..575fe6f 100644
--- a/drivers/scsi/mvme16x.c
+++ b/drivers/scsi/mvme16x.c
@@ -6,7 +6,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blkdev.h>
-#include <linux/sched.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 7c13f6f..f6f561d 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c
index c116a6a..26a6d55 100644
--- a/drivers/scsi/oktagon_esp.c
+++ b/drivers/scsi/oktagon_esp.c
@@ -133,7 +133,7 @@
 		eregs = (struct ESP_regs *)(address + OKTAGON_ESP_ADDR);
 
 		/* This line was 5 lines lower */
-		esp = esp_allocate(tpnt, (void *)board+OKTAGON_ESP_ADDR);
+		esp = esp_allocate(tpnt, (void *)board + OKTAGON_ESP_ADDR, 0);
 
 		/* we have to shift the registers only one bit for oktagon */
 		esp->shift = 1;
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 7d23110..a967fad 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -521,10 +521,10 @@
 		break;
 	  default: ; /* probably FILL */
 	}
-	aux->filemark_cnt = ntohl(STp->filemark_cnt);
-	aux->phys_fm = ntohl(0xffffffff);
-	aux->last_mark_ppos = ntohl(STp->last_mark_ppos);
-	aux->last_mark_lbn  = ntohl(STp->last_mark_lbn);
+	aux->filemark_cnt = htonl(STp->filemark_cnt);
+	aux->phys_fm = htonl(0xffffffff);
+	aux->last_mark_ppos = htonl(STp->last_mark_ppos);
+	aux->last_mark_lbn  = htonl(STp->last_mark_lbn);
 }
 
 /*
@@ -5522,7 +5522,7 @@
 
 #endif
 
-static struct file_operations osst_fops = {
+static const struct file_operations osst_fops = {
 	.owner =        THIS_MODULE,
 	.read =         osst_read,
 	.write =        osst_write,
@@ -5574,14 +5574,14 @@
 
 static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
 
-static int osst_create_driverfs_files(struct device_driver *driverfs)
+static int osst_create_sysfs_files(struct device_driver *sysfs)
 {
-	return driver_create_file(driverfs, &driver_attr_version);
+	return driver_create_file(sysfs, &driver_attr_version);
 }
 
-static void osst_remove_driverfs_files(struct device_driver *driverfs)
+static void osst_remove_sysfs_files(struct device_driver *sysfs)
 {
-	driver_remove_file(driverfs, &driver_attr_version);
+	driver_remove_file(sysfs, &driver_attr_version);
 }
 
 /*
@@ -5953,7 +5953,7 @@
 	if (err)
 		goto err_out_chrdev;
 
-	err = osst_create_driverfs_files(&osst_template.gendrv);
+	err = osst_create_sysfs_files(&osst_template.gendrv);
 	if (err)
 		goto err_out_scsidrv;
 
@@ -5973,7 +5973,7 @@
 	int i;
 	struct osst_tape * STp;
 
-	osst_remove_driverfs_files(&osst_template.gendrv);
+	osst_remove_sysfs_files(&osst_template.gendrv);
 	scsi_unregister_driver(&osst_template.gendrv);
 	unregister_chrdev(OSST_MAJOR, "osst");
 	osst_sysfs_cleanup();
diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h
index 1e426f5..2cc7b5a 100644
--- a/drivers/scsi/osst.h
+++ b/drivers/scsi/osst.h
@@ -288,11 +288,11 @@
 #else
 #error "Please fix <asm/byteorder.h>"
 #endif
-        u16             max_speed;              /* Maximum speed supported in KBps */
+        __be16          max_speed;              /* Maximum speed supported in KBps */
         u8              reserved10, reserved11;
-        u16             ctl;                    /* Continuous Transfer Limit in blocks */
-        u16             speed;                  /* Current Speed, in KBps */
-        u16             buffer_size;            /* Buffer Size, in 512 bytes */
+        __be16          ctl;                    /* Continuous Transfer Limit in blocks */
+        __be16          speed;                  /* Current Speed, in KBps */
+        __be16          buffer_size;            /* Buffer Size, in 512 bytes */
         u8              reserved18, reserved19;
 } osst_capabilities_page_t;
 
@@ -352,8 +352,8 @@
 	u8		reserved2;
 	u8		density;
 	u8		reserved3,reserved4;
-	u16		segtrk;
-	u16		trks;
+	__be16		segtrk;
+	__be16		trks;
 	u8		reserved5,reserved6,reserved7,reserved8,reserved9,reserved10;
 } osst_tape_paramtr_page_t;
 
@@ -369,18 +369,18 @@
 typedef struct os_partition_s {
         __u8    partition_num;
         __u8    par_desc_ver;
-        __u16   wrt_pass_cntr;
-        __u32   first_frame_ppos;
-        __u32   last_frame_ppos;
-        __u32   eod_frame_ppos;
+        __be16  wrt_pass_cntr;
+        __be32  first_frame_ppos;
+        __be32  last_frame_ppos;
+        __be32  eod_frame_ppos;
 } os_partition_t;
 
 /*
  * DAT entry
  */
 typedef struct os_dat_entry_s {
-        __u32   blk_sz;
-        __u16   blk_cnt;
+        __be32  blk_sz;
+        __be16  blk_cnt;
         __u8    flags;
         __u8    reserved;
 } os_dat_entry_t;
@@ -412,23 +412,23 @@
  * AUX
  */
 typedef struct os_aux_s {
-        __u32           format_id;              /* hardware compability AUX is based on */
+        __be32          format_id;              /* hardware compability AUX is based on */
         char            application_sig[4];     /* driver used to write this media */
-        __u32           hdwr;                   /* reserved */
-        __u32           update_frame_cntr;      /* for configuration frame */
+        __be32          hdwr;                   /* reserved */
+        __be32          update_frame_cntr;      /* for configuration frame */
         __u8            frame_type;
         __u8            frame_type_reserved;
         __u8            reserved_18_19[2];
         os_partition_t  partition;
         __u8            reserved_36_43[8];
-        __u32           frame_seq_num;
-        __u32           logical_blk_num_high;
-        __u32           logical_blk_num;
+        __be32          frame_seq_num;
+        __be32          logical_blk_num_high;
+        __be32          logical_blk_num;
         os_dat_t        dat;
         __u8            reserved188_191[4];
-        __u32           filemark_cnt;
-        __u32           phys_fm;
-        __u32           last_mark_ppos;
+        __be32          filemark_cnt;
+        __be32          phys_fm;
+        __be32          last_mark_ppos;
         __u8            reserved204_223[20];
 
         /*
@@ -436,8 +436,8 @@
          *
          * Linux specific fields:
          */
-         __u32          next_mark_ppos;         /* when known, points to next marker */
-	 __u32		last_mark_lbn;		/* storing log_blk_num of last mark is extends ADR spec */
+         __be32         next_mark_ppos;         /* when known, points to next marker */
+	 __be32		last_mark_lbn;		/* storing log_blk_num of last mark is extends ADR spec */
          __u8           linux_specific[24];
 
         __u8            reserved_256_511[256];
@@ -450,19 +450,19 @@
 	__u8		reserved_1;
 	__u8		fm_tab_ent_sz;
 	__u8		reserved_3;
-	__u16		fm_tab_ent_cnt;
+	__be16		fm_tab_ent_cnt;
 	__u8		reserved6_15[10];
-	__u32		fm_tab_ent[OS_FM_TAB_MAX];
+	__be32		fm_tab_ent[OS_FM_TAB_MAX];
 } os_fm_tab_t;
 
 typedef struct os_ext_trk_ey_s {
 	__u8		et_part_num;
 	__u8		fmt;
-	__u16		fm_tab_off;
+	__be16		fm_tab_off;
 	__u8		reserved4_7[4];
-	__u32		last_hlb_hi;
-	__u32		last_hlb;
-	__u32		last_pp;
+	__be32		last_hlb_hi;
+	__be32		last_hlb;
+	__be32		last_pp;
 	__u8		reserved20_31[12];
 } os_ext_trk_ey_t;
 
@@ -479,17 +479,17 @@
         char            ident_str[8];
         __u8            major_rev;
         __u8            minor_rev;
-	__u16		ext_trk_tb_off;
+	__be16		ext_trk_tb_off;
         __u8            reserved12_15[4];
         __u8            pt_par_num;
         __u8            pt_reserved1_3[3];
         os_partition_t  partition[16];
-	__u32		cfg_col_width;
-	__u32		dat_col_width;
-	__u32		qfa_col_width;
+	__be32		cfg_col_width;
+	__be32		dat_col_width;
+	__be32		qfa_col_width;
 	__u8		cartridge[16];
 	__u8		reserved304_511[208];
-	__u32		old_filemark_list[16680/4];		/* in ADR 1.4 __u8 track_table[16680] */
+	__be32		old_filemark_list[16680/4];		/* in ADR 1.4 __u8 track_table[16680] */
 	os_ext_trk_tb_t	ext_track_tb;
 	__u8		reserved17272_17735[464];
 	os_fm_tab_t	dat_fm_tab;
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index 1434209..ee59656 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -116,7 +116,6 @@
 #include <asm/system.h>
 #include <linux/signal.h>
 #include <linux/proc_fs.h>
-#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index aad362b..370802d 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -37,7 +37,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index a1c5f26..4b82b20 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index e16fe36..c6f8c6e 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -31,7 +31,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index 625ca97..9102cbd 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -290,7 +290,6 @@
 #endif
 } nsp_hw_data;
 
-
 /****************************************************************************
  *
  */
@@ -302,22 +301,13 @@
 
 /* Linux SCSI subsystem specific functions */
 static struct Scsi_Host *nsp_detect     (struct scsi_host_template *sht);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static        int        nsp_detect_old (struct scsi_host_template *sht);
-static        int        nsp_release_old(struct Scsi_Host *shpnt);
-#endif
 static const  char      *nsp_info       (struct Scsi_Host *shpnt);
 static        int        nsp_proc_info  (
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 	                                 struct Scsi_Host *host,
-#endif
 					 char   *buffer,
 					 char  **start,
 					 off_t   offset,
 					 int     length,
-#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-					 int     hostno,
-#endif
 					 int     inout);
 static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 			    void (* done)(struct scsi_cmnd *SCpnt));
@@ -356,7 +346,6 @@
 static int  __init nsp_cs_init(void);
 static void __exit nsp_cs_exit(void);
 
-
 /* Debug */
 #ifdef NSP_DEBUG
 static void show_command (struct scsi_cmnd *SCpnt);
@@ -401,7 +390,6 @@
 	BURST_MEM32 = 2,
 };
 
-
 /**************************************************************************
  * SCSI messaage
  */
@@ -413,62 +401,8 @@
 
 #define MSG_EXT_SDTR         0x01
 
-
-/**************************************************************************
- * Compatibility functions
- */
-
-/* for Kernel 2.4 */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-#  define scsi_register_host(template)   scsi_register_module(MODULE_SCSI_HA, template)
-#  define scsi_unregister_host(template) scsi_unregister_module(MODULE_SCSI_HA, template)
-#  define scsi_host_put(host)            scsi_unregister(host)
-
-typedef void irqreturn_t;
-#  define IRQ_NONE      /* */
-#  define IRQ_HANDLED   /* */
-#  define IRQ_RETVAL(x) /* */
-
-/* This is ad-hoc version of scsi_host_get_next() */
-static inline struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *host)
-{
-	if (host == NULL) {
-		return scsi_hostlist;
-	} else {
-		return host->next;
-	}
-}
-
-/* This is ad-hoc version of scsi_host_hn_get() */
-static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno)
-{
-	struct Scsi_Host *host;
-
-	for (host = scsi_host_get_next(NULL); host != NULL;
-	     host = scsi_host_get_next(host)) {
-		if (host->host_no == hostno) {
-			break;
-		}
-	}
-
-	return host;
-}
-
-static void cs_error(struct pcmcia_device *handle, int func, int ret)
-{
-	error_info_t err = { func, ret };
-	pcmcia_report_error(handle, &err);
-}
-
-/* scatter-gather table */
-#  define BUFFER_ADDR (SCpnt->SCp.buffer->address)
-#endif
-
-/* for Kernel 2.6 */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
 /* scatter-gather table */
 #  define BUFFER_ADDR ((char *)((unsigned int)(SCpnt->SCp.buffer->page) + SCpnt->SCp.buffer->offset))
-#endif
 
 #endif  /*__nsp_cs__*/
 /* end */
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 9d431fe..697cfb7 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 5b458d24..ffe75c4 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -54,7 +54,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 1548d42..6777e8a 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -341,7 +341,6 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 7b18a6c..8081b63 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -140,6 +140,8 @@
 	ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
+	set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+
 	return (count);
 }
 
@@ -653,6 +655,43 @@
 	return count;
 }
 
+static ssize_t
+qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+
+	return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1],
+	    ha->bios_revision[0]);
+}
+
+static ssize_t
+qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+
+	return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1],
+	    ha->efi_revision[0]);
+}
+
+static ssize_t
+qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+
+	return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1],
+	    ha->fcode_revision[0]);
+}
+
+static ssize_t
+qla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+
+	return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n",
+	    ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2],
+	    ha->fw_revision[3]);
+}
+
 static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
 	NULL);
 static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
@@ -669,6 +708,14 @@
     qla2x00_zio_timer_store);
 static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
     qla2x00_beacon_store);
+static CLASS_DEVICE_ATTR(optrom_bios_version, S_IRUGO,
+    qla2x00_optrom_bios_version_show, NULL);
+static CLASS_DEVICE_ATTR(optrom_efi_version, S_IRUGO,
+    qla2x00_optrom_efi_version_show, NULL);
+static CLASS_DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
+    qla2x00_optrom_fcode_version_show, NULL);
+static CLASS_DEVICE_ATTR(optrom_fw_version, S_IRUGO,
+    qla2x00_optrom_fw_version_show, NULL);
 
 struct class_device_attribute *qla2x00_host_attrs[] = {
 	&class_device_attr_driver_version,
@@ -683,6 +730,10 @@
 	&class_device_attr_zio,
 	&class_device_attr_zio_timer,
 	&class_device_attr_beacon,
+	&class_device_attr_optrom_bios_version,
+	&class_device_attr_optrom_efi_version,
+	&class_device_attr_optrom_fcode_version,
+	&class_device_attr_optrom_fw_version,
 	NULL,
 };
 
@@ -836,21 +887,24 @@
 	link_stat_t stat_buf;
 	struct fc_host_statistics *pfc_host_stat;
 
+	rval = QLA_FUNCTION_FAILED;
 	pfc_host_stat = &ha->fc_host_stat;
 	memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
 
 	if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
 		rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf,
 		    sizeof(stat_buf) / 4, mb_stat);
-	} else {
+	} else if (atomic_read(&ha->loop_state) == LOOP_READY &&
+		    !test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) &&
+		    !test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) &&
+		    !ha->dpc_active) {
+		/* Must be in a 'READY' state for statistics retrieval. */
 		rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf,
 		    mb_stat);
 	}
-	if (rval != 0) {
-		qla_printk(KERN_WARNING, ha,
-		    "Unable to retrieve host statistics (%d).\n", mb_stat[0]);
-		return pfc_host_stat;
-	}
+
+	if (rval != QLA_SUCCESS)
+		goto done;
 
 	pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt;
 	pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt;
@@ -858,7 +912,7 @@
 	pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt;
 	pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt;
 	pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt;
-
+done:
 	return pfc_host_stat;
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 2c10130..05f4f2a 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2045,6 +2045,29 @@
 		uint32_t, uint32_t);
 	int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t,
 		uint32_t);
+
+	int (*get_flash_version) (struct scsi_qla_host *, void *);
+};
+
+/* MSI-X Support *************************************************************/
+
+#define QLA_MSIX_CHIP_REV_24XX	3
+#define QLA_MSIX_FW_MODE(m)	(((m) & (BIT_7|BIT_8|BIT_9)) >> 7)
+#define QLA_MSIX_FW_MODE_1(m)	(QLA_MSIX_FW_MODE(m) == 1)
+
+#define QLA_MSIX_DEFAULT	0x00
+#define QLA_MSIX_RSP_Q		0x01
+
+#define QLA_MSIX_ENTRIES	2
+#define QLA_MIDX_DEFAULT	0
+#define QLA_MIDX_RSP_Q		1
+
+struct scsi_qla_host;
+
+struct qla_msix_entry {
+	int have_irq;
+	uint16_t msix_vector;
+	uint16_t msix_entry;
 };
 
 /*
@@ -2077,6 +2100,7 @@
 		uint32_t	enable_lip_full_login	:1;
 		uint32_t	enable_target_reset	:1;
 		uint32_t	enable_led_scheme	:1;
+		uint32_t	inta_enabled		:1;
 		uint32_t	msi_enabled		:1;
 		uint32_t	msix_enabled		:1;
 		uint32_t	disable_serdes		:1;
@@ -2316,8 +2340,6 @@
 #define MBX_INTR_WAIT	2
 #define MBX_UPDATE_FLASH_ACTIVE	3
 
-	spinlock_t	mbx_reg_lock;   /* Mbx Cmd Register Lock */
-
 	struct semaphore mbx_cmd_sem;	/* Serialialize mbx access */
 	struct semaphore mbx_intr_sem;  /* Used for completion notification */
 
@@ -2358,6 +2380,7 @@
 
 	uint8_t		host_str[16];
 	uint32_t	pci_attr;
+	uint16_t	chip_revision;
 
 	uint16_t	product_id[4];
 
@@ -2379,6 +2402,15 @@
 #define QLA_SREADING	1
 #define QLA_SWRITING	2
 
+        /* PCI expansion ROM image information. */
+#define ROM_CODE_TYPE_BIOS	0
+#define ROM_CODE_TYPE_FCODE	1
+#define ROM_CODE_TYPE_EFI	3
+	uint8_t		bios_revision[2];
+	uint8_t		efi_revision[2];
+	uint8_t		fcode_revision[16];
+	uint32_t	fw_revision[4];
+
 	/* Needed for BEACON */
 	uint16_t	beacon_blink_led;
 	uint8_t		beacon_color_state;
@@ -2391,6 +2423,8 @@
 	uint16_t	zio_mode;
 	uint16_t	zio_timer;
 	struct fc_host_statistics fc_host_stat;
+
+	struct qla_msix_entry msix_entries[QLA_MSIX_ENTRIES];
 } scsi_qla_host_t;
 
 
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index e4dd12f..74544ae 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -224,6 +224,9 @@
 extern void qla2x00_process_response_queue(struct scsi_qla_host *);
 extern void qla24xx_process_response_queue(struct scsi_qla_host *);
 
+extern int qla2x00_request_irqs(scsi_qla_host_t *);
+extern void qla2x00_free_irqs(scsi_qla_host_t *);
+
 /*
  * Global Function Prototypes in qla_sup.c source file.
  */
@@ -259,6 +262,9 @@
 extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
     uint32_t, uint32_t);
 
+extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
+extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
+
 /*
  * Global Function Prototypes in qla_dbg.c source file.
  */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index b3dac26..98c01cd 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -65,7 +65,7 @@
 	ha->flags.reset_active = 0;
 	atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
 	atomic_set(&ha->loop_state, LOOP_DOWN);
-	ha->device_flags = 0;
+	ha->device_flags = DFLG_NO_CABLE;
 	ha->dpc_flags = 0;
 	ha->flags.management_server_logged_in = 0;
 	ha->marker_needed = 0;
@@ -77,16 +77,23 @@
 	qla_printk(KERN_INFO, ha, "Configuring PCI space...\n");
 	rval = ha->isp_ops.pci_config(ha);
 	if (rval) {
-		DEBUG2(printk("scsi(%ld): Unable to configure PCI space=n",
+		DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n",
 		    ha->host_no));
 		return (rval);
 	}
 
 	ha->isp_ops.reset_chip(ha);
 
+	ha->isp_ops.get_flash_version(ha, ha->request_ring);
+
 	qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
 
-	ha->isp_ops.nvram_config(ha);
+	rval = ha->isp_ops.nvram_config(ha);
+	if (rval) {
+		DEBUG2(printk("scsi(%ld): Unable to verify NVRAM data.\n",
+		    ha->host_no));
+		return rval;
+	}
 
 	if (ha->flags.disable_serdes) {
 		/* Mask HBA via NVRAM settings? */
@@ -293,6 +300,8 @@
 	d &= ~PCI_ROM_ADDRESS_ENABLE;
 	pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
 
+	pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->chip_revision);
+
 	/* Get PCI bus information. */
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	ha->pci_attr = RD_REG_DWORD(&reg->ctrl_status);
@@ -1351,6 +1360,39 @@
 	return(rval);
 }
 
+static inline void
+qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *def)
+{
+	char *st, *en;
+	uint16_t index;
+
+	if (memcmp(model, BINZERO, len) != 0) {
+		strncpy(ha->model_number, model, len);
+		st = en = ha->model_number;
+		en += len - 1;
+		while (en > st) {
+			if (*en != 0x20 && *en != 0x00)
+				break;
+			*en-- = '\0';
+		}
+
+		index = (ha->pdev->subsystem_device & 0xff);
+		if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
+		    index < QLA_MODEL_NAMES)
+			ha->model_desc = qla2x00_model_name[index * 2 + 1];
+	} else {
+		index = (ha->pdev->subsystem_device & 0xff);
+		if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
+		    index < QLA_MODEL_NAMES) {
+			strcpy(ha->model_number,
+			    qla2x00_model_name[index * 2]);
+			ha->model_desc = qla2x00_model_name[index * 2 + 1];
+		} else {
+			strcpy(ha->model_number, def);
+		}
+	}
+}
+
 /*
 * NVRAM configuration for ISP 2xxx
 *
@@ -1367,7 +1409,6 @@
 int
 qla2x00_nvram_config(scsi_qla_host_t *ha)
 {
-	int             rval;
 	uint8_t         chksum = 0;
 	uint16_t        cnt;
 	uint8_t         *dptr1, *dptr2;
@@ -1376,8 +1417,6 @@
 	uint8_t         *ptr = (uint8_t *)ha->request_ring;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
-	rval = QLA_SUCCESS;
-
 	/* Determine NVRAM starting address. */
 	ha->nvram_size = sizeof(nvram_t);
 	ha->nvram_base = 0;
@@ -1401,55 +1440,7 @@
 		qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
 		    "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
 		    nv->nvram_version);
-		qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
-		    "invalid -- WWPN) defaults.\n");
-
-		/*
-		 * Set default initialization control block.
-		 */
-		memset(nv, 0, ha->nvram_size);
-		nv->parameter_block_version = ICB_VERSION;
-
-		if (IS_QLA23XX(ha)) {
-			nv->firmware_options[0] = BIT_2 | BIT_1;
-			nv->firmware_options[1] = BIT_7 | BIT_5;
-			nv->add_firmware_options[0] = BIT_5;
-			nv->add_firmware_options[1] = BIT_5 | BIT_4;
-			nv->frame_payload_size = __constant_cpu_to_le16(2048);
-			nv->special_options[1] = BIT_7;
-		} else if (IS_QLA2200(ha)) {
-			nv->firmware_options[0] = BIT_2 | BIT_1;
-			nv->firmware_options[1] = BIT_7 | BIT_5;
-			nv->add_firmware_options[0] = BIT_5;
-			nv->add_firmware_options[1] = BIT_5 | BIT_4;
-			nv->frame_payload_size = __constant_cpu_to_le16(1024);
-		} else if (IS_QLA2100(ha)) {
-			nv->firmware_options[0] = BIT_3 | BIT_1;
-			nv->firmware_options[1] = BIT_5;
-			nv->frame_payload_size = __constant_cpu_to_le16(1024);
-		}
-
-		nv->max_iocb_allocation = __constant_cpu_to_le16(256);
-		nv->execution_throttle = __constant_cpu_to_le16(16);
-		nv->retry_count = 8;
-		nv->retry_delay = 1;
-
-		nv->port_name[0] = 33;
-		nv->port_name[3] = 224;
-		nv->port_name[4] = 139;
-
-		nv->login_timeout = 4;
-
-		/*
-		 * Set default host adapter parameters
-		 */
-		nv->host_p[1] = BIT_2;
-		nv->reset_delay = 5;
-		nv->port_down_retry_count = 8;
-		nv->max_luns_per_target = __constant_cpu_to_le16(8);
-		nv->link_down_timeout = 60;
-
-		rval = 1;
+		return QLA_FUNCTION_FAILED;
 	}
 
 #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
@@ -1489,33 +1480,8 @@
 				strcpy(ha->model_number, "QLA2300");
 			}
 		} else {
-			if (rval == 0 &&
-			    memcmp(nv->model_number, BINZERO,
-				    sizeof(nv->model_number)) != 0) {
-				char *st, *en;
-
-				strncpy(ha->model_number, nv->model_number,
-				    sizeof(nv->model_number));
-				st = en = ha->model_number;
-				en += sizeof(nv->model_number) - 1;
-				while (en > st) {
-					if (*en != 0x20 && *en != 0x00)
-						break;
-					*en-- = '\0';
-				}
-			} else {
-				uint16_t        index;
-
-				index = (ha->pdev->subsystem_device & 0xff);
-				if (index < QLA_MODEL_NAMES) {
-					strcpy(ha->model_number,
-					    qla2x00_model_name[index * 2]);
-					ha->model_desc =
-					    qla2x00_model_name[index * 2 + 1];
-				} else {
-					strcpy(ha->model_number, "QLA23xx");
-				}
-			}
+			qla2x00_set_model_info(ha, nv->model_number,
+			    sizeof(nv->model_number), "QLA23xx");
 		}
 	} else if (IS_QLA2200(ha)) {
 		nv->firmware_options[0] |= BIT_2;
@@ -1687,11 +1653,7 @@
 		}
 	}
 
-	if (rval) {
-		DEBUG2_3(printk(KERN_WARNING
-		    "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
-	}
-	return (rval);
+	return QLA_SUCCESS;
 }
 
 static void
@@ -3107,7 +3069,11 @@
 		}
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-		ha->isp_ops.nvram_config(ha);
+		ha->isp_ops.get_flash_version(ha, ha->request_ring);
+
+		rval = ha->isp_ops.nvram_config(ha);
+		if (rval)
+			goto isp_abort_retry;
 
 		if (!qla2x00_restart_isp(ha)) {
 			clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
@@ -3137,6 +3103,7 @@
 				}
 			}
 		} else {	/* failed the ISP abort */
+isp_abort_retry:
 			ha->flags.online = 1;
 			if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
 				if (ha->isp_abort_cnt == 0) {
@@ -3326,7 +3293,6 @@
 int
 qla24xx_nvram_config(scsi_qla_host_t *ha)
 {
-	int   rval;
 	struct init_cb_24xx *icb;
 	struct nvram_24xx *nv;
 	uint32_t *dptr;
@@ -3334,7 +3300,6 @@
 	uint32_t chksum;
 	uint16_t cnt;
 
-	rval = QLA_SUCCESS;
 	icb = (struct init_cb_24xx *)ha->init_cb;
 	nv = (struct nvram_24xx *)ha->request_ring;
 
@@ -3367,51 +3332,7 @@
 		qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
 		    "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
 		    le16_to_cpu(nv->nvram_version));
-		qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
-		    "invalid -- WWPN) defaults.\n");
-
-		/*
-		 * Set default initialization control block.
-		 */
-		memset(nv, 0, ha->nvram_size);
-		nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION);
-		nv->version = __constant_cpu_to_le16(ICB_VERSION);
-		nv->frame_payload_size = __constant_cpu_to_le16(2048);
-		nv->execution_throttle = __constant_cpu_to_le16(0xFFFF);
-		nv->exchange_count = __constant_cpu_to_le16(0);
-		nv->hard_address = __constant_cpu_to_le16(124);
-		nv->port_name[0] = 0x21;
-		nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn);
-		nv->port_name[2] = 0x00;
-		nv->port_name[3] = 0xe0;
-		nv->port_name[4] = 0x8b;
-		nv->port_name[5] = 0x1c;
-		nv->port_name[6] = 0x55;
-		nv->port_name[7] = 0x86;
-		nv->node_name[0] = 0x20;
-		nv->node_name[1] = 0x00;
-		nv->node_name[2] = 0x00;
-		nv->node_name[3] = 0xe0;
-		nv->node_name[4] = 0x8b;
-		nv->node_name[5] = 0x1c;
-		nv->node_name[6] = 0x55;
-		nv->node_name[7] = 0x86;
-		nv->login_retry_count = __constant_cpu_to_le16(8);
-		nv->interrupt_delay_timer = __constant_cpu_to_le16(0);
-		nv->login_timeout = __constant_cpu_to_le16(0);
-		nv->firmware_options_1 =
-		    __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
-		nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4);
-		nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12);
-		nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13);
-		nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10);
-		nv->efi_parameters = __constant_cpu_to_le32(0);
-		nv->reset_delay = 5;
-		nv->max_luns_per_target = __constant_cpu_to_le16(128);
-		nv->port_down_retry_count = __constant_cpu_to_le16(30);
-		nv->link_down_timeout = __constant_cpu_to_le16(30);
-
-		rval = 1;
+		return QLA_FUNCTION_FAILED;
 	}
 
 	/* Reset Initialization control block */
@@ -3438,25 +3359,8 @@
 	/*
 	 * Setup driver NVRAM options.
 	 */
-	if (memcmp(nv->model_name, BINZERO, sizeof(nv->model_name)) != 0) {
-		char *st, *en;
-		uint16_t index;
-
-		strncpy(ha->model_number, nv->model_name,
-		    sizeof(nv->model_name));
-		st = en = ha->model_number;
-		en += sizeof(nv->model_name) - 1;
-		while (en > st) {
-			if (*en != 0x20 && *en != 0x00)
-				break;
-			*en-- = '\0';
-		}
-
-		index = (ha->pdev->subsystem_device & 0xff);
-		if (index < QLA_MODEL_NAMES)
-			ha->model_desc = qla2x00_model_name[index * 2 + 1];
-	} else
-		strcpy(ha->model_number, "QLA2462");
+	qla2x00_set_model_info(ha, nv->model_name, sizeof(nv->model_name),
+	    "QLA2462");
 
 	/* Use alternate WWN? */
 	if (nv->host_p & __constant_cpu_to_le32(BIT_15)) {
@@ -3575,11 +3479,7 @@
 		ha->flags.process_response_queue = 1;
 	}
 
-	if (rval) {
-		DEBUG2_3(printk(KERN_WARNING
-		    "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
-	}
-	return (rval);
+	return QLA_SUCCESS;
 }
 
 static int
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 39fd17b..d488561 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -86,12 +86,8 @@
 
 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
-		spin_lock_irqsave(&ha->mbx_reg_lock, flags);
-
 		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 		up(&ha->mbx_intr_sem);
-
-		spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
 	}
 
 	return (IRQ_HANDLED);
@@ -199,12 +195,8 @@
 
 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
-		spin_lock_irqsave(&ha->mbx_reg_lock, flags);
-
 		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 		up(&ha->mbx_intr_sem);
-
-		spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
 	}
 
 	return (IRQ_HANDLED);
@@ -654,10 +646,8 @@
 	    fcport->last_queue_full + ql2xqfullrampup * HZ))
 		return;
 
-	spin_unlock_irq(&ha->hardware_lock);
 	starget_for_each_device(sdev->sdev_target, fcport,
 	    qla2x00_adjust_sdev_qdepth_up);
-	spin_lock_irq(&ha->hardware_lock);
 }
 
 /**
@@ -927,10 +917,8 @@
 
 			/* Adjust queue depth for all luns on the port. */
 			fcport->last_queue_full = jiffies;
-			spin_unlock_irq(&ha->hardware_lock);
 			starget_for_each_device(cp->device->sdev_target,
 			    fcport, qla2x00_adjust_sdev_qdepth_down);
-			spin_lock_irq(&ha->hardware_lock);
 			break;
 		}
 		if (lscsi_status != SS_CHECK_CONDITION)
@@ -995,6 +983,22 @@
 		if (lscsi_status != 0) {
 			cp->result = DID_OK << 16 | lscsi_status;
 
+			if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
+				DEBUG2(printk(KERN_INFO
+				    "scsi(%ld): QUEUE FULL status detected "
+				    "0x%x-0x%x.\n", ha->host_no, comp_status,
+				    scsi_status));
+
+				/*
+				 * Adjust queue depth for all luns on the
+				 * port.
+				 */
+				fcport->last_queue_full = jiffies;
+				starget_for_each_device(
+				    cp->device->sdev_target, fcport,
+				    qla2x00_adjust_sdev_qdepth_down);
+				break;
+			}
 			if (lscsi_status != SS_CHECK_CONDITION)
 				break;
 
@@ -1482,12 +1486,8 @@
 
 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
-		spin_lock_irqsave(&ha->mbx_reg_lock, flags);
-
 		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 		up(&ha->mbx_intr_sem);
-
-		spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
 	}
 
 	return IRQ_HANDLED;
@@ -1536,3 +1536,216 @@
 	qla2x00_sp_compl(ha, sp);
 }
 
+static irqreturn_t
+qla24xx_msix_rsp_q(int irq, void *dev_id)
+{
+	scsi_qla_host_t	*ha;
+	struct device_reg_24xx __iomem *reg;
+	unsigned long flags;
+
+	ha = dev_id;
+	reg = &ha->iobase->isp24;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	qla24xx_process_response_queue(ha);
+
+	WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+	RD_REG_DWORD_RELAXED(&reg->hccr);
+
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+qla24xx_msix_default(int irq, void *dev_id)
+{
+	scsi_qla_host_t	*ha;
+	struct device_reg_24xx __iomem *reg;
+	int		status;
+	unsigned long	flags;
+	unsigned long	iter;
+	uint32_t	stat;
+	uint32_t	hccr;
+	uint16_t	mb[4];
+
+	ha = dev_id;
+	reg = &ha->iobase->isp24;
+	status = 0;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	for (iter = 50; iter--; ) {
+		stat = RD_REG_DWORD(&reg->host_status);
+		if (stat & HSRX_RISC_PAUSED) {
+			hccr = RD_REG_DWORD(&reg->hccr);
+
+			qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
+			    "Dumping firmware!\n", hccr);
+			ha->isp_ops.fw_dump(ha, 1);
+			set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+			break;
+		} else if ((stat & HSRX_RISC_INT) == 0)
+			break;
+
+		switch (stat & 0xff) {
+		case 0x1:
+		case 0x2:
+		case 0x10:
+		case 0x11:
+			qla24xx_mbx_completion(ha, MSW(stat));
+			status |= MBX_INTERRUPT;
+
+			break;
+		case 0x12:
+			mb[0] = MSW(stat);
+			mb[1] = RD_REG_WORD(&reg->mailbox1);
+			mb[2] = RD_REG_WORD(&reg->mailbox2);
+			mb[3] = RD_REG_WORD(&reg->mailbox3);
+			qla2x00_async_event(ha, mb);
+			break;
+		case 0x13:
+			qla24xx_process_response_queue(ha);
+			break;
+		default:
+			DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
+			    "(%d).\n",
+			    ha->host_no, stat & 0xff));
+			break;
+		}
+		WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+		RD_REG_DWORD_RELAXED(&reg->hccr);
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+		up(&ha->mbx_intr_sem);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/* Interrupt handling helpers. */
+
+struct qla_init_msix_entry {
+	uint16_t entry;
+	uint16_t index;
+	const char *name;
+	irqreturn_t (*handler)(int, void *);
+};
+
+static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
+	{ QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT,
+		"qla2xxx (default)", qla24xx_msix_default },
+
+	{ QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q,
+		"qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
+};
+
+static void
+qla24xx_disable_msix(scsi_qla_host_t *ha)
+{
+	int i;
+	struct qla_msix_entry *qentry;
+
+	for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
+		qentry = &ha->msix_entries[imsix_entries[i].index];
+		if (qentry->have_irq)
+			free_irq(qentry->msix_vector, ha);
+	}
+	pci_disable_msix(ha->pdev);
+}
+
+static int
+qla24xx_enable_msix(scsi_qla_host_t *ha)
+{
+	int i, ret;
+	struct msix_entry entries[QLA_MSIX_ENTRIES];
+	struct qla_msix_entry *qentry;
+
+	for (i = 0; i < QLA_MSIX_ENTRIES; i++)
+		entries[i].entry = imsix_entries[i].entry;
+
+	ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries));
+	if (ret) {
+		qla_printk(KERN_WARNING, ha,
+		    "MSI-X: Failed to enable support -- %d/%d\n",
+		    QLA_MSIX_ENTRIES, ret);
+		goto msix_out;
+	}
+	ha->flags.msix_enabled = 1;
+
+	for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
+		qentry = &ha->msix_entries[imsix_entries[i].index];
+		qentry->msix_vector = entries[i].vector;
+		qentry->msix_entry = entries[i].entry;
+		qentry->have_irq = 0;
+		ret = request_irq(qentry->msix_vector,
+		    imsix_entries[i].handler, 0, imsix_entries[i].name, ha);
+		if (ret) {
+			qla_printk(KERN_WARNING, ha,
+			    "MSI-X: Unable to register handler -- %x/%d.\n",
+			    imsix_entries[i].index, ret);
+			qla24xx_disable_msix(ha);
+			goto msix_out;
+		}
+		qentry->have_irq = 1;
+	}
+
+msix_out:
+	return ret;
+}
+
+int
+qla2x00_request_irqs(scsi_qla_host_t *ha)
+{
+	int ret;
+
+	/* If possible, enable MSI-X. */
+	if (!IS_QLA2432(ha))
+		goto skip_msix;
+
+        if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
+	    !QLA_MSIX_FW_MODE_1(ha->fw_attributes)) {
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
+		    ha->chip_revision, ha->fw_attributes));
+
+		goto skip_msix;
+	}
+
+	ret = qla24xx_enable_msix(ha);
+	if (!ret) {
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision,
+		    ha->fw_attributes));
+		return ret;
+	}
+	qla_printk(KERN_WARNING, ha,
+	    "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
+skip_msix:
+	ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler,
+	    IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
+	if (!ret) {
+		ha->flags.inta_enabled = 1;
+		ha->host->irq = ha->pdev->irq;
+	} else {
+		qla_printk(KERN_WARNING, ha,
+		    "Failed to reserve interrupt %d already in use.\n",
+		    ha->pdev->irq);
+	}
+
+	return ret;
+}
+
+void
+qla2x00_free_irqs(scsi_qla_host_t *ha)
+{
+
+	if (ha->flags.msix_enabled)
+		qla24xx_disable_msix(ha);
+	else if (ha->flags.inta_enabled)
+		free_irq(ha->host->irq, ha);
+}
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 077e578..83376f6 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -55,7 +55,6 @@
 	uint16_t __iomem *optr;
 	uint32_t	cnt;
 	uint32_t	mboxes;
-	unsigned long	mbx_flags = 0;
 	unsigned long	wait_time;
 
 	rval = QLA_SUCCESS;
@@ -81,10 +80,6 @@
 	/* Save mailbox command for debug */
 	ha->mcp = mcp;
 
-	/* Try to get mailbox register access */
-	if (!abort_active)
-		spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags);
-
 	DEBUG11(printk("scsi(%ld): prepare to issue mbox cmd=0x%x.\n",
 	    ha->host_no, mcp->mb[0]));
 
@@ -161,9 +156,6 @@
 			WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-		if (!abort_active)
-			spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags);
-
 		/* Wait for either the timer to expire
 		 * or the mbox completion interrupt
 		 */
@@ -184,8 +176,6 @@
 		else
 			WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
-		if (!abort_active)
-			spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags);
 
 		wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */
 		while (!ha->flags.mbox_int) {
@@ -201,9 +191,6 @@
 		} /* while */
 	}
 
-	if (!abort_active)
-		spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags);
-
 	/* Check whether we timed out */
 	if (ha->flags.mbox_int) {
 		uint16_t *iptr2;
@@ -256,9 +243,6 @@
 		rval = QLA_FUNCTION_TIMEOUT;
 	}
 
-	if (!abort_active)
-		spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags);
-
 	ha->flags.mbox_busy = 0;
 
 	/* Clean up */
@@ -1713,7 +1697,7 @@
 	lg->entry_count = 1;
 	lg->nport_handle = cpu_to_le16(loop_id);
 	lg->control_flags =
-	    __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_EXPL_LOGO);
+	    __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
 	lg->port_id[0] = al_pa;
 	lg->port_id[1] = area;
 	lg->port_id[2] = domain;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index d6445ae8..68f5d24 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1485,6 +1485,7 @@
 	ha->isp_ops.fw_dump		= qla2100_fw_dump;
 	ha->isp_ops.read_optrom		= qla2x00_read_optrom_data;
 	ha->isp_ops.write_optrom	= qla2x00_write_optrom_data;
+	ha->isp_ops.get_flash_version	= qla2x00_get_flash_version;
 	if (IS_QLA2100(ha)) {
 		host->max_id = MAX_TARGETS_2100;
 		ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
@@ -1550,6 +1551,7 @@
 		ha->isp_ops.beacon_on = qla24xx_beacon_on;
 		ha->isp_ops.beacon_off = qla24xx_beacon_off;
 		ha->isp_ops.beacon_blink = qla24xx_beacon_blink;
+		ha->isp_ops.get_flash_version = qla24xx_get_flash_version;
 		ha->gid_list_info_size = 8;
 		ha->optrom_size = OPTROM_SIZE_24XX;
 	}
@@ -1564,14 +1566,6 @@
 	INIT_LIST_HEAD(&ha->list);
 	INIT_LIST_HEAD(&ha->fcports);
 
-	/*
-	 * These locks are used to prevent more than one CPU
-	 * from modifying the queue at the same time. The
-	 * higher level "host_lock" will reduce most
-	 * contention for these locks.
-	 */
-	spin_lock_init(&ha->mbx_reg_lock);
-
 	qla2x00_config_dma_addressing(ha);
 	if (qla2x00_mem_alloc(ha)) {
 		qla_printk(KERN_WARNING, ha,
@@ -1615,15 +1609,9 @@
 	host->max_lun = MAX_LUNS;
 	host->transportt = qla2xxx_transport_template;
 
-	ret = request_irq(pdev->irq, ha->isp_ops.intr_handler,
-	    IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
-	if (ret) {
-		qla_printk(KERN_WARNING, ha,
-		    "Failed to reserve interrupt %d already in use.\n",
-		    pdev->irq);
+	ret = qla2x00_request_irqs(ha);
+	if (ret)
 		goto probe_failed;
-	}
-	host->irq = pdev->irq;
 
 	/* Initialized the timer */
 	qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL);
@@ -1753,9 +1741,7 @@
 
 	qla2x00_mem_free(ha);
 
-	/* Detach interrupts */
-	if (ha->host->irq)
-		free_irq(ha->host->irq, ha);
+	qla2x00_free_irqs(ha);
 
 	/* release io space registers  */
 	if (ha->iobase)
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 15390ad..ff1dd41 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -611,7 +611,6 @@
 					    flash_conf_to_access_addr(0x0339),
 					    (fdata & 0xff00) | ((fdata << 16) &
 					    0xff0000) | ((fdata >> 16) & 0xff));
-				fdata = (faddr & sec_mask) << 2;
 				ret = qla24xx_write_flash_dword(ha, conf_addr,
 				    (fdata & 0xff00) |((fdata << 16) &
 				    0xff0000) | ((fdata >> 16) & 0xff));
@@ -1383,6 +1382,29 @@
 	qla2x00_write_flash_byte(ha, 0x5555, 0xf0);
 }
 
+static void
+qla2x00_read_flash_data(scsi_qla_host_t *ha, uint8_t *tmp_buf, uint32_t saddr,
+        uint32_t length)
+{
+	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+	uint32_t midpoint, ilength;
+	uint8_t data;
+
+	midpoint = length / 2;
+
+	WRT_REG_WORD(&reg->nvram, 0);
+	RD_REG_WORD(&reg->nvram);
+	for (ilength = 0; ilength < length; saddr++, ilength++, tmp_buf++) {
+		if (ilength == midpoint) {
+			WRT_REG_WORD(&reg->nvram, NVR_SELECT);
+			RD_REG_WORD(&reg->nvram);
+		}
+		data = qla2x00_read_flash_byte(ha, saddr);
+		if (saddr % 100)
+			udelay(10);
+		*tmp_buf = data;
+	}
+}
 
 static inline void
 qla2x00_suspend_hba(struct scsi_qla_host *ha)
@@ -1722,3 +1744,327 @@
 
 	return rval;
 }
+
+/**
+ * qla2x00_get_fcode_version() - Determine an FCODE image's version.
+ * @ha: HA context
+ * @pcids: Pointer to the FCODE PCI data structure
+ *
+ * The process of retrieving the FCODE version information is at best
+ * described as interesting.
+ *
+ * Within the first 100h bytes of the image an ASCII string is present
+ * which contains several pieces of information including the FCODE
+ * version.  Unfortunately it seems the only reliable way to retrieve
+ * the version is by scanning for another sentinel within the string,
+ * the FCODE build date:
+ *
+ *	... 2.00.02 10/17/02 ...
+ *
+ * Returns QLA_SUCCESS on successful retrieval of version.
+ */
+static void
+qla2x00_get_fcode_version(scsi_qla_host_t *ha, uint32_t pcids)
+{
+	int ret = QLA_FUNCTION_FAILED;
+	uint32_t istart, iend, iter, vend;
+	uint8_t do_next, rbyte, *vbyte;
+
+	memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
+
+	/* Skip the PCI data structure. */
+	istart = pcids +
+	    ((qla2x00_read_flash_byte(ha, pcids + 0x0B) << 8) |
+		qla2x00_read_flash_byte(ha, pcids + 0x0A));
+	iend = istart + 0x100;
+	do {
+		/* Scan for the sentinel date string...eeewww. */
+		do_next = 0;
+		iter = istart;
+		while ((iter < iend) && !do_next) {
+			iter++;
+			if (qla2x00_read_flash_byte(ha, iter) == '/') {
+				if (qla2x00_read_flash_byte(ha, iter + 2) ==
+				    '/')
+					do_next++;
+				else if (qla2x00_read_flash_byte(ha,
+				    iter + 3) == '/')
+					do_next++;
+			}
+		}
+		if (!do_next)
+			break;
+
+		/* Backtrack to previous ' ' (space). */
+		do_next = 0;
+		while ((iter > istart) && !do_next) {
+			iter--;
+			if (qla2x00_read_flash_byte(ha, iter) == ' ')
+				do_next++;
+		}
+		if (!do_next)
+			break;
+
+		/*
+		 * Mark end of version tag, and find previous ' ' (space) or
+		 * string length (recent FCODE images -- major hack ahead!!!).
+		 */
+		vend = iter - 1;
+		do_next = 0;
+		while ((iter > istart) && !do_next) {
+			iter--;
+			rbyte = qla2x00_read_flash_byte(ha, iter);
+			if (rbyte == ' ' || rbyte == 0xd || rbyte == 0x10)
+				do_next++;
+		}
+		if (!do_next)
+			break;
+
+		/* Mark beginning of version tag, and copy data. */
+		iter++;
+		if ((vend - iter) &&
+		    ((vend - iter) < sizeof(ha->fcode_revision))) {
+			vbyte = ha->fcode_revision;
+			while (iter <= vend) {
+				*vbyte++ = qla2x00_read_flash_byte(ha, iter);
+				iter++;
+			}
+			ret = QLA_SUCCESS;
+		}
+	} while (0);
+
+	if (ret != QLA_SUCCESS)
+		memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
+}
+
+int
+qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
+{
+	int ret = QLA_SUCCESS;
+	uint8_t code_type, last_image;
+	uint32_t pcihdr, pcids;
+	uint8_t *dbyte;
+	uint16_t *dcode;
+
+	if (!ha->pio_address || !mbuf)
+		return QLA_FUNCTION_FAILED;
+
+	memset(ha->bios_revision, 0, sizeof(ha->bios_revision));
+	memset(ha->efi_revision, 0, sizeof(ha->efi_revision));
+	memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
+	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
+
+	qla2x00_flash_enable(ha);
+
+	/* Begin with first PCI expansion ROM header. */
+	pcihdr = 0;
+	last_image = 1;
+	do {
+		/* Verify PCI expansion ROM header. */
+		if (qla2x00_read_flash_byte(ha, pcihdr) != 0x55 ||
+		    qla2x00_read_flash_byte(ha, pcihdr + 0x01) != 0xaa) {
+			/* No signature */
+			DEBUG2(printk("scsi(%ld): No matching ROM "
+			    "signature.\n", ha->host_no));
+			ret = QLA_FUNCTION_FAILED;
+			break;
+		}
+
+		/* Locate PCI data structure. */
+		pcids = pcihdr +
+		    ((qla2x00_read_flash_byte(ha, pcihdr + 0x19) << 8) |
+			qla2x00_read_flash_byte(ha, pcihdr + 0x18));
+
+		/* Validate signature of PCI data structure. */
+		if (qla2x00_read_flash_byte(ha, pcids) != 'P' ||
+		    qla2x00_read_flash_byte(ha, pcids + 0x1) != 'C' ||
+		    qla2x00_read_flash_byte(ha, pcids + 0x2) != 'I' ||
+		    qla2x00_read_flash_byte(ha, pcids + 0x3) != 'R') {
+			/* Incorrect header. */
+			DEBUG2(printk("%s(): PCI data struct not found "
+			    "pcir_adr=%x.\n", __func__, pcids));
+			ret = QLA_FUNCTION_FAILED;
+			break;
+		}
+
+		/* Read version */
+		code_type = qla2x00_read_flash_byte(ha, pcids + 0x14);
+		switch (code_type) {
+		case ROM_CODE_TYPE_BIOS:
+			/* Intel x86, PC-AT compatible. */
+			ha->bios_revision[0] =
+			    qla2x00_read_flash_byte(ha, pcids + 0x12);
+			ha->bios_revision[1] =
+			    qla2x00_read_flash_byte(ha, pcids + 0x13);
+			DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__,
+			    ha->bios_revision[1], ha->bios_revision[0]));
+			break;
+		case ROM_CODE_TYPE_FCODE:
+			/* Open Firmware standard for PCI (FCode). */
+			/* Eeeewww... */
+			qla2x00_get_fcode_version(ha, pcids);
+			break;
+		case ROM_CODE_TYPE_EFI:
+			/* Extensible Firmware Interface (EFI). */
+			ha->efi_revision[0] =
+			    qla2x00_read_flash_byte(ha, pcids + 0x12);
+			ha->efi_revision[1] =
+			    qla2x00_read_flash_byte(ha, pcids + 0x13);
+			DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__,
+			    ha->efi_revision[1], ha->efi_revision[0]));
+			break;
+		default:
+			DEBUG2(printk("%s(): Unrecognized code type %x at "
+			    "pcids %x.\n", __func__, code_type, pcids));
+			break;
+		}
+
+		last_image = qla2x00_read_flash_byte(ha, pcids + 0x15) & BIT_7;
+
+		/* Locate next PCI expansion ROM. */
+		pcihdr += ((qla2x00_read_flash_byte(ha, pcids + 0x11) << 8) |
+		    qla2x00_read_flash_byte(ha, pcids + 0x10)) * 512;
+	} while (!last_image);
+
+	if (IS_QLA2322(ha)) {
+		/* Read firmware image information. */
+		memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
+		dbyte = mbuf;
+		memset(dbyte, 0, 8);
+		dcode = (uint16_t *)dbyte;
+
+		qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10,
+		    8);
+		DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n",
+		    __func__, ha->host_no));
+		DEBUG3(qla2x00_dump_buffer((uint8_t *)dbyte, 8));
+
+		if ((dcode[0] == 0xffff && dcode[1] == 0xffff &&
+		    dcode[2] == 0xffff && dcode[3] == 0xffff) ||
+		    (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
+		    dcode[3] == 0)) {
+			DEBUG2(printk("%s(): Unrecognized fw revision at "
+			    "%x.\n", __func__, FA_RISC_CODE_ADDR * 4));
+		} else {
+			/* values are in big endian */
+			ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1];
+			ha->fw_revision[1] = dbyte[2] << 16 | dbyte[3];
+			ha->fw_revision[2] = dbyte[4] << 16 | dbyte[5];
+		}
+	}
+
+	qla2x00_flash_disable(ha);
+
+	return ret;
+}
+
+int
+qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
+{
+	int ret = QLA_SUCCESS;
+	uint32_t pcihdr, pcids;
+	uint32_t *dcode;
+	uint8_t *bcode;
+	uint8_t code_type, last_image;
+	int i;
+
+	if (!mbuf)
+		return QLA_FUNCTION_FAILED;
+
+	memset(ha->bios_revision, 0, sizeof(ha->bios_revision));
+	memset(ha->efi_revision, 0, sizeof(ha->efi_revision));
+	memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
+	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
+
+	dcode = mbuf;
+
+	/* Begin with first PCI expansion ROM header. */
+	pcihdr = 0;
+	last_image = 1;
+	do {
+		/* Verify PCI expansion ROM header. */
+		qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20);
+		bcode = mbuf + (pcihdr % 4);
+		if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) {
+			/* No signature */
+			DEBUG2(printk("scsi(%ld): No matching ROM "
+			    "signature.\n", ha->host_no));
+			ret = QLA_FUNCTION_FAILED;
+			break;
+		}
+
+		/* Locate PCI data structure. */
+		pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]);
+
+		qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20);
+		bcode = mbuf + (pcihdr % 4);
+
+		/* Validate signature of PCI data structure. */
+		if (bcode[0x0] != 'P' || bcode[0x1] != 'C' ||
+		    bcode[0x2] != 'I' || bcode[0x3] != 'R') {
+			/* Incorrect header. */
+			DEBUG2(printk("%s(): PCI data struct not found "
+			    "pcir_adr=%x.\n", __func__, pcids));
+			ret = QLA_FUNCTION_FAILED;
+			break;
+		}
+
+		/* Read version */
+		code_type = bcode[0x14];
+		switch (code_type) {
+		case ROM_CODE_TYPE_BIOS:
+			/* Intel x86, PC-AT compatible. */
+			ha->bios_revision[0] = bcode[0x12];
+			ha->bios_revision[1] = bcode[0x13];
+			DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__,
+			    ha->bios_revision[1], ha->bios_revision[0]));
+			break;
+		case ROM_CODE_TYPE_FCODE:
+			/* Open Firmware standard for PCI (FCode). */
+			ha->fcode_revision[0] = bcode[0x12];
+			ha->fcode_revision[1] = bcode[0x13];
+			DEBUG3(printk("%s(): read FCODE %d.%d.\n", __func__,
+			    ha->fcode_revision[1], ha->fcode_revision[0]));
+			break;
+		case ROM_CODE_TYPE_EFI:
+			/* Extensible Firmware Interface (EFI). */
+			ha->efi_revision[0] = bcode[0x12];
+			ha->efi_revision[1] = bcode[0x13];
+			DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__,
+			    ha->efi_revision[1], ha->efi_revision[0]));
+			break;
+		default:
+			DEBUG2(printk("%s(): Unrecognized code type %x at "
+			    "pcids %x.\n", __func__, code_type, pcids));
+			break;
+		}
+
+		last_image = bcode[0x15] & BIT_7;
+
+		/* Locate next PCI expansion ROM. */
+		pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512;
+	} while (!last_image);
+
+	/* Read firmware image information. */
+	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
+	dcode = mbuf;
+
+	qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4);
+	for (i = 0; i < 4; i++)
+		dcode[i] = be32_to_cpu(dcode[i]);
+
+	if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
+	    dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
+	    (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
+	    dcode[3] == 0)) {
+		DEBUG2(printk("%s(): Unrecognized fw version at %x.\n",
+		    __func__, FA_RISC_CODE_ADDR));
+	} else {
+		ha->fw_revision[0] = dcode[0];
+		ha->fw_revision[1] = dcode[1];
+		ha->fw_revision[2] = dcode[2];
+		ha->fw_revision[3] = dcode[3];
+	}
+
+	return ret;
+}
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 459e0d6..61347ae 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.07-k4"
+#define QLA2XXX_VERSION      "8.01.07-k5"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	1
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 81fb7bd..0bfddf8 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -1270,7 +1270,7 @@
 	INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);
 
 	ret = request_irq(pdev->irq, qla4xxx_intr_handler,
-			  SA_INTERRUPT|SA_SHIRQ, "qla4xxx", ha);
+			  IRQF_DISABLED | IRQF_SHARED, "qla4xxx", ha);
 	if (ret) {
 		dev_warn(&ha->pdev->dev, "Failed to reserve interrupt %d"
 			" already in use.\n", pdev->irq);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 24cffd9..1c89ee3 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/slab.h>
@@ -673,27 +672,6 @@
 }
 
 /*
- * Function:    scsi_retry_command
- *
- * Purpose:     Send a command back to the low level to be retried.
- *
- * Notes:       This command is always executed in the context of the
- *              bottom half handler, or the error handler thread. Low
- *              level drivers should not become re-entrant as a result of
- *              this.
- */
-int scsi_retry_command(struct scsi_cmnd *cmd)
-{
-        /*
-         * Zero the sense information from the last time we tried
-         * this command.
-         */
-	memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
-
-	return scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
-}
-
-/*
  * Function:    scsi_finish_command
  *
  * Purpose:     Pass command off to upper layer for finishing of I/O
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 30ee3d7..3e2930b 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -28,7 +28,6 @@
 #include <linux/module.h>
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/types.h>
@@ -51,10 +50,10 @@
 #include "scsi_logging.h"
 #include "scsi_debug.h"
 
-#define SCSI_DEBUG_VERSION "1.80"
-static const char * scsi_debug_version_date = "20061018";
+#define SCSI_DEBUG_VERSION "1.81"
+static const char * scsi_debug_version_date = "20070104";
 
-/* Additional Sense Code (ASC) used */
+/* Additional Sense Code (ASC) */
 #define NO_ADDITIONAL_SENSE 0x0
 #define LOGICAL_UNIT_NOT_READY 0x4
 #define UNRECOVERED_READ_ERR 0x11
@@ -65,9 +64,13 @@
 #define INVALID_FIELD_IN_PARAM_LIST 0x26
 #define POWERON_RESET 0x29
 #define SAVING_PARAMS_UNSUP 0x39
+#define TRANSPORT_PROBLEM 0x4b
 #define THRESHOLD_EXCEEDED 0x5d
 #define LOW_POWER_COND_ON 0x5e
 
+/* Additional Sense Code Qualifier (ASCQ) */
+#define ACK_NAK_TO 0x3
+
 #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
 
 /* Default values for driver parameters */
@@ -95,15 +98,20 @@
 #define SCSI_DEBUG_OPT_MEDIUM_ERR   2
 #define SCSI_DEBUG_OPT_TIMEOUT   4
 #define SCSI_DEBUG_OPT_RECOVERED_ERR   8
+#define SCSI_DEBUG_OPT_TRANSPORT_ERR   16
 /* When "every_nth" > 0 then modulo "every_nth" commands:
  *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
  *     commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
+ *   - a TRANSPORT_ERROR is simulated on successful read and write
+ *     commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
  *
  * When "every_nth" < 0 then after "- every_nth" commands:
  *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
  *     commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
+ *   - a TRANSPORT_ERROR is simulated on successful read and write
+ *     commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
  * This will continue until some other action occurs (e.g. the user
  * writing a new value (other than -1 or 1) to every_nth via sysfs).
  */
@@ -315,6 +323,7 @@
 	int target = SCpnt->device->id;
 	struct sdebug_dev_info * devip = NULL;
 	int inj_recovered = 0;
+	int inj_transport = 0;
 	int delay_override = 0;
 
 	if (done == NULL)
@@ -352,6 +361,8 @@
 			return 0; /* ignore command causing timeout */
 		else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
 			inj_recovered = 1; /* to reads and writes below */
+		else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
+			inj_transport = 1; /* to reads and writes below */
         }
 
 	if (devip->wlun) {
@@ -468,7 +479,11 @@
 			mk_sense_buffer(devip, RECOVERED_ERROR,
 					THRESHOLD_EXCEEDED, 0);
 			errsts = check_condition_result;
-		}
+		} else if (inj_transport && (0 == errsts)) {
+                        mk_sense_buffer(devip, ABORTED_COMMAND,
+                                        TRANSPORT_PROBLEM, ACK_NAK_TO);
+                        errsts = check_condition_result;
+                }
 		break;
 	case REPORT_LUNS:	/* mandatory, ignore unit attention */
 		delay_override = 1;
@@ -531,6 +546,9 @@
 		delay_override = 1;
 		errsts = check_readiness(SCpnt, 0, devip);
 		break;
+	case WRITE_BUFFER:
+		errsts = check_readiness(SCpnt, 1, devip);
+		break;
 	default:
 		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
 			printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
@@ -954,7 +972,9 @@
 	int alloc_len, n, ret;
 
 	alloc_len = (cmd[3] << 8) + cmd[4];
-	arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_KERNEL);
+	arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
+	if (! arr)
+		return DID_REQUEUE << 16;
 	if (devip->wlun)
 		pq_pdt = 0x1e;	/* present, wlun */
 	else if (scsi_debug_no_lun_0 && (0 == devip->lun))
@@ -1217,7 +1237,9 @@
 	alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8)
 		+ cmd[9]);
 
-	arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_KERNEL);
+	arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC);
+	if (! arr)
+		return DID_REQUEUE << 16;
 	/*
 	 * EVPD page 0x88 states we have two ports, one
 	 * real and a fake port with no device connected.
@@ -1996,6 +2018,8 @@
 	if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
 		sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
 	devip = devInfoReg(sdp);
+	if (NULL == devip)
+		return 1;	/* no resources, will be marked offline */
 	sdp->hostdata = devip;
 	if (sdp->host->cmd_per_lun)
 		scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING,
@@ -2044,7 +2068,7 @@
 		}
 	}
 	if (NULL == open_devip) { /* try and make a new one */
-		open_devip = kzalloc(sizeof(*open_devip),GFP_KERNEL);
+		open_devip = kzalloc(sizeof(*open_devip),GFP_ATOMIC);
 		if (NULL == open_devip) {
 			printk(KERN_ERR "%s: out of memory at line %d\n",
 				__FUNCTION__, __LINE__);
@@ -2388,7 +2412,7 @@
 MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
 MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
 MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
-MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->... (def=0)");
+MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
 MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
 MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
 MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
@@ -2943,7 +2967,6 @@
         struct list_head *lh, *lh_sf;
 
         sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
-
         if (NULL == sdbg_host) {
                 printk(KERN_ERR "%s: out of memory at line %d\n",
                        __FUNCTION__, __LINE__);
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 2ecb6ff..b8edcf5 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -359,6 +359,11 @@
 		return SUCCESS;
 
 	case MEDIUM_ERROR:
+		if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */
+		    sshdr.asc == 0x13 || /* AMNF DATA FIELD */
+		    sshdr.asc == 0x14) { /* RECORD NOT FOUND */
+			return SUCCESS;
+		}
 		return NEEDS_RETRY;
 
 	case HARDWARE_ERROR:
@@ -453,6 +458,128 @@
 }
 
 /**
+ * scsi_try_host_reset - ask host adapter to reset itself
+ * @scmd:	SCSI cmd to send hsot reset.
+ **/
+static int scsi_try_host_reset(struct scsi_cmnd *scmd)
+{
+	unsigned long flags;
+	int rtn;
+
+	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
+					  __FUNCTION__));
+
+	if (!scmd->device->host->hostt->eh_host_reset_handler)
+		return FAILED;
+
+	rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd);
+
+	if (rtn == SUCCESS) {
+		if (!scmd->device->host->hostt->skip_settle_delay)
+			ssleep(HOST_RESET_SETTLE_TIME);
+		spin_lock_irqsave(scmd->device->host->host_lock, flags);
+		scsi_report_bus_reset(scmd->device->host,
+				      scmd_channel(scmd));
+		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+	}
+
+	return rtn;
+}
+
+/**
+ * scsi_try_bus_reset - ask host to perform a bus reset
+ * @scmd:	SCSI cmd to send bus reset.
+ **/
+static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
+{
+	unsigned long flags;
+	int rtn;
+
+	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
+					  __FUNCTION__));
+
+	if (!scmd->device->host->hostt->eh_bus_reset_handler)
+		return FAILED;
+
+	rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd);
+
+	if (rtn == SUCCESS) {
+		if (!scmd->device->host->hostt->skip_settle_delay)
+			ssleep(BUS_RESET_SETTLE_TIME);
+		spin_lock_irqsave(scmd->device->host->host_lock, flags);
+		scsi_report_bus_reset(scmd->device->host,
+				      scmd_channel(scmd));
+		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+	}
+
+	return rtn;
+}
+
+/**
+ * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
+ * @scmd:	SCSI cmd used to send BDR
+ *
+ * Notes:
+ *    There is no timeout for this operation.  if this operation is
+ *    unreliable for a given host, then the host itself needs to put a
+ *    timer on it, and set the host back to a consistent state prior to
+ *    returning.
+ **/
+static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
+{
+	int rtn;
+
+	if (!scmd->device->host->hostt->eh_device_reset_handler)
+		return FAILED;
+
+	rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
+	if (rtn == SUCCESS) {
+		scmd->device->was_reset = 1;
+		scmd->device->expecting_cc_ua = 1;
+	}
+
+	return rtn;
+}
+
+static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
+{
+	if (!scmd->device->host->hostt->eh_abort_handler)
+		return FAILED;
+
+	return scmd->device->host->hostt->eh_abort_handler(scmd);
+}
+
+/**
+ * scsi_try_to_abort_cmd - Ask host to abort a running command.
+ * @scmd:	SCSI cmd to abort from Lower Level.
+ *
+ * Notes:
+ *    This function will not return until the user's completion function
+ *    has been called.  there is no timeout on this operation.  if the
+ *    author of the low-level driver wishes this operation to be timed,
+ *    they can provide this facility themselves.  helper functions in
+ *    scsi_error.c can be supplied to make this easier to do.
+ **/
+static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
+{
+	/*
+	 * scsi_done was called just after the command timed out and before
+	 * we had a chance to process it. (db)
+	 */
+	if (scmd->serial_number == 0)
+		return SUCCESS;
+	return __scsi_try_to_abort_cmd(scmd);
+}
+
+static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
+{
+	if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
+		if (scsi_try_bus_device_reset(scmd) != SUCCESS)
+			if (scsi_try_bus_reset(scmd) != SUCCESS)
+				scsi_try_host_reset(scmd);
+}
+
+/**
  * scsi_send_eh_cmnd  - submit a scsi command as part of error recory
  * @scmd:       SCSI command structure to hijack
  * @cmnd:       CDB to send
@@ -579,13 +706,7 @@
 			break;
 		}
 	} else {
-		/*
-		 * FIXME(eric) - we are not tracking whether we could
-		 * abort a timed out command or not.  not sure how
-		 * we should treat them differently anyways.
-		 */
-		if (shost->hostt->eh_abort_handler)
-			shost->hostt->eh_abort_handler(scmd);
+		scsi_abort_eh_cmnd(scmd);
 		rtn = FAILED;
 	}
 
@@ -672,8 +793,8 @@
  *    XXX: Long term this code should go away, but that needs an audit of
  *         all LLDDs first.
  **/
-static int scsi_eh_get_sense(struct list_head *work_q,
-			     struct list_head *done_q)
+int scsi_eh_get_sense(struct list_head *work_q,
+		      struct list_head *done_q)
 {
 	struct scsi_cmnd *scmd, *next;
 	int rtn;
@@ -715,31 +836,7 @@
 
 	return list_empty(work_q);
 }
-
-/**
- * scsi_try_to_abort_cmd - Ask host to abort a running command.
- * @scmd:	SCSI cmd to abort from Lower Level.
- *
- * Notes:
- *    This function will not return until the user's completion function
- *    has been called.  there is no timeout on this operation.  if the
- *    author of the low-level driver wishes this operation to be timed,
- *    they can provide this facility themselves.  helper functions in
- *    scsi_error.c can be supplied to make this easier to do.
- **/
-static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
-{
-	if (!scmd->device->host->hostt->eh_abort_handler)
-		return FAILED;
-
-	/*
-	 * scsi_done was called just after the command timed out and before
-	 * we had a chance to process it. (db)
-	 */
-	if (scmd->serial_number == 0)
-		return SUCCESS;
-	return scmd->device->host->hostt->eh_abort_handler(scmd);
-}
+EXPORT_SYMBOL_GPL(scsi_eh_get_sense);
 
 /**
  * scsi_eh_tur - Send TUR to device.
@@ -815,32 +912,6 @@
 }
 
 /**
- * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
- * @scmd:	SCSI cmd used to send BDR	
- *
- * Notes:
- *    There is no timeout for this operation.  if this operation is
- *    unreliable for a given host, then the host itself needs to put a
- *    timer on it, and set the host back to a consistent state prior to
- *    returning.
- **/
-static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
-{
-	int rtn;
-
-	if (!scmd->device->host->hostt->eh_device_reset_handler)
-		return FAILED;
-
-	rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
-	if (rtn == SUCCESS) {
-		scmd->device->was_reset = 1;
-		scmd->device->expecting_cc_ua = 1;
-	}
-
-	return rtn;
-}
-
-/**
  * scsi_eh_try_stu - Send START_UNIT to device.
  * @scmd:	Scsi cmd to send START_UNIT
  *
@@ -971,64 +1042,6 @@
 }
 
 /**
- * scsi_try_bus_reset - ask host to perform a bus reset
- * @scmd:	SCSI cmd to send bus reset.
- **/
-static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
-{
-	unsigned long flags;
-	int rtn;
-
-	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
-					  __FUNCTION__));
-
-	if (!scmd->device->host->hostt->eh_bus_reset_handler)
-		return FAILED;
-
-	rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd);
-
-	if (rtn == SUCCESS) {
-		if (!scmd->device->host->hostt->skip_settle_delay)
-			ssleep(BUS_RESET_SETTLE_TIME);
-		spin_lock_irqsave(scmd->device->host->host_lock, flags);
-		scsi_report_bus_reset(scmd->device->host,
-				      scmd_channel(scmd));
-		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
-	}
-
-	return rtn;
-}
-
-/**
- * scsi_try_host_reset - ask host adapter to reset itself
- * @scmd:	SCSI cmd to send hsot reset.
- **/
-static int scsi_try_host_reset(struct scsi_cmnd *scmd)
-{
-	unsigned long flags;
-	int rtn;
-
-	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
-					  __FUNCTION__));
-
-	if (!scmd->device->host->hostt->eh_host_reset_handler)
-		return FAILED;
-
-	rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd);
-
-	if (rtn == SUCCESS) {
-		if (!scmd->device->host->hostt->skip_settle_delay)
-			ssleep(HOST_RESET_SETTLE_TIME);
-		spin_lock_irqsave(scmd->device->host->host_lock, flags);
-		scsi_report_bus_reset(scmd->device->host,
-				      scmd_channel(scmd));
-		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
-	}
-
-	return rtn;
-}
-
-/**
  * scsi_eh_bus_reset - send a bus reset 
  * @shost:	scsi host being recovered.
  * @eh_done_q:	list_head for processed commands.
@@ -1411,9 +1424,9 @@
  * @eh_done_q:	list_head for processed commands.
  *
  **/
-static void scsi_eh_ready_devs(struct Scsi_Host *shost,
-			       struct list_head *work_q,
-			       struct list_head *done_q)
+void scsi_eh_ready_devs(struct Scsi_Host *shost,
+			struct list_head *work_q,
+			struct list_head *done_q)
 {
 	if (!scsi_eh_stu(shost, work_q, done_q))
 		if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
@@ -1421,6 +1434,7 @@
 				if (!scsi_eh_host_reset(work_q, done_q))
 					scsi_eh_offline_sdevs(work_q, done_q);
 }
+EXPORT_SYMBOL_GPL(scsi_eh_ready_devs);
 
 /**
  * scsi_eh_flush_done_q - finish processed commands or retry them.
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f02f48a..9f7482d 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -388,10 +388,9 @@
 	int err = 0;
 	int write = (data_direction == DMA_TO_DEVICE);
 
-	sioc = kmem_cache_alloc(scsi_io_context_cache, gfp);
+	sioc = kmem_cache_zalloc(scsi_io_context_cache, gfp);
 	if (!sioc)
 		return DRIVER_ERROR << 24;
-	memset(sioc, 0, sizeof(*sioc));
 
 	req = blk_get_request(sdev->request_queue, write, gfp);
 	if (!req)
@@ -1400,7 +1399,7 @@
 			scsi_finish_command(cmd);
 			break;
 		case NEEDS_RETRY:
-			scsi_retry_command(cmd);
+			scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
 			break;
 		case ADD_TO_MLQUEUE:
 			scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
@@ -2250,6 +2249,8 @@
 	size_t sg_len = 0, len_complete = 0;
 	struct page *page;
 
+	WARN_ON(!irqs_disabled());
+
 	for (i = 0; i < sg_count; i++) {
 		len_complete = sg_len; /* Complete sg-entries */
 		sg_len += sg[i].length;
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index f458c2f..ee8efe8 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -28,7 +28,6 @@
 extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
 extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
 extern void __scsi_done(struct scsi_cmnd *cmd);
-extern int scsi_retry_command(struct scsi_cmnd *cmd);
 #ifdef CONFIG_SCSI_LOGGING
 void scsi_log_send(struct scsi_cmnd *cmd);
 void scsi_log_completion(struct scsi_cmnd *cmd, int disposition);
@@ -58,6 +57,11 @@
 extern int scsi_decide_disposition(struct scsi_cmnd *cmd);
 extern void scsi_eh_wakeup(struct Scsi_Host *shost);
 extern int scsi_eh_scmd_add(struct scsi_cmnd *, int);
+void scsi_eh_ready_devs(struct Scsi_Host *shost,
+			struct list_head *work_q,
+			struct list_head *done_q);
+int scsi_eh_get_sense(struct list_head *work_q,
+		      struct list_head *done_q);
 
 /* scsi_lib.c */
 extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index 524a5f7..bb6f051 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -179,9 +179,8 @@
 	seq_printf(s, "\n");
 
 	seq_printf(s, "  Type:   %s ", scsi_device_type(sdev->type));
-	seq_printf(s, "               ANSI"
-		     " SCSI revision: %02x", (sdev->scsi_level - 1) ?
-		     sdev->scsi_level - 1 : 1);
+	seq_printf(s, "               ANSI  SCSI revision: %02x",
+			sdev->scsi_level - (sdev->scsi_level > 1));
 	if (sdev->scsi_level == 2)
 		seq_printf(s, " CCS\n");
 	else
@@ -308,7 +307,7 @@
 	return single_open(file, proc_scsi_show, NULL);
 }
 
-static struct file_operations proc_scsi_operations = {
+static const struct file_operations proc_scsi_operations = {
 	.open		= proc_scsi_open,
 	.read		= seq_read,
 	.write		= proc_scsi_write,
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 96b7cbd..0949145 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -54,7 +54,7 @@
 #define SCSI_TIMEOUT (2*HZ)
 
 /*
- * Prefix values for the SCSI id's (stored in driverfs name field)
+ * Prefix values for the SCSI id's (stored in sysfs name field)
  */
 #define SCSI_UID_SER_NUM 'S'
 #define SCSI_UID_UNKNOWN 'Z'
@@ -385,6 +385,7 @@
 	INIT_LIST_HEAD(&starget->siblings);
 	INIT_LIST_HEAD(&starget->devices);
 	starget->state = STARGET_RUNNING;
+	starget->scsi_level = SCSI_2;
  retry:
 	spin_lock_irqsave(shost->host_lock, flags);
 
@@ -654,6 +655,19 @@
 	 * short INQUIRY), an abort here prevents any further use of the
 	 * device, including spin up.
 	 *
+	 * On the whole, the best approach seems to be to assume the first
+	 * 36 bytes are valid no matter what the device says.  That's
+	 * better than copying < 36 bytes to the inquiry-result buffer
+	 * and displaying garbage for the Vendor, Product, or Revision
+	 * strings.
+	 */
+	if (sdev->inquiry_len < 36) {
+		printk(KERN_INFO "scsi scan: INQUIRY result too short (%d),"
+				" using 36\n", sdev->inquiry_len);
+		sdev->inquiry_len = 36;
+	}
+
+	/*
 	 * Related to the above issue:
 	 *
 	 * XXX Devices (disk or all?) should be sent a TEST UNIT READY,
@@ -1029,7 +1043,7 @@
 
 				sdev_printk(KERN_INFO, sdev,
 					"scsi scan: consider passing scsi_mod."
-					"dev_flags=%s:%s:0x240 or 0x800240\n",
+					"dev_flags=%s:%s:0x240 or 0x1000240\n",
 					scsi_inq_str(vend, result, 8, 16),
 					scsi_inq_str(mod, result, 16, 32));
 			});
diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c
index 04d06c2..6cfaaa2 100644
--- a/drivers/scsi/scsi_sysctl.c
+++ b/drivers/scsi/scsi_sysctl.c
@@ -41,7 +41,7 @@
 
 int __init scsi_init_sysctl(void)
 {
-	scsi_table_header = register_sysctl_table(scsi_root_table, 1);
+	scsi_table_header = register_sysctl_table(scsi_root_table);
 	if (!scsi_table_header)
 		return -ENOMEM;
 	return 0;
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 259c90c..c275dca 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -922,7 +922,7 @@
 	snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
 		 "%d:%d:%d:%d", sdev->host->host_no,
 		 sdev->channel, sdev->id, sdev->lun);
-	sdev->scsi_level = SCSI_2;
+	sdev->scsi_level = starget->scsi_level;
 	transport_setup_device(&sdev->sdev_gendev);
 	spin_lock_irqsave(shost->host_lock, flags);
 	list_add_tail(&sdev->same_target_siblings, &starget->devices);
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c
index 37bbfbd..0e08817 100644
--- a/drivers/scsi/scsi_tgt_if.c
+++ b/drivers/scsi/scsi_tgt_if.c
@@ -33,6 +33,14 @@
 
 #include "scsi_tgt_priv.h"
 
+#if TGT_RING_SIZE < PAGE_SIZE
+#  define TGT_RING_SIZE PAGE_SIZE
+#endif
+
+#define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT)
+#define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event))
+#define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES)
+
 struct tgt_ring {
 	u32 tr_idx;
 	unsigned long tr_pages[TGT_RING_PAGES];
@@ -280,7 +288,7 @@
 	return 0;
 }
 
-static struct file_operations tgt_fops = {
+static const struct file_operations tgt_fops = {
 	.owner		= THIS_MODULE,
 	.open		= tgt_open,
 	.poll		= tgt_poll,
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 3571ce8..58afdb4 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -26,7 +26,6 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>	/* workqueue stuff, HZ */
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport.h>
@@ -856,7 +855,7 @@
 
 /*
  * Note: in the target show function we recognize when the remote
- *  port is in the heirarchy and do not allow the driver to get
+ *  port is in the hierarchy and do not allow the driver to get
  *  involved in sysfs functions. The driver only gets involved if
  *  it's the "old" style that doesn't use rports.
  */
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 5c0b75b..b2ef71a 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -336,6 +336,51 @@
 }
 static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
 
+static ssize_t do_sas_phy_enable(struct class_device *cdev,
+		size_t count, int enable)
+{
+	struct sas_phy *phy = transport_class_to_phy(cdev);
+	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+	struct sas_internal *i = to_sas_internal(shost->transportt);
+	int error;
+
+	error = i->f->phy_enable(phy, enable);
+	if (error)
+		return error;
+	phy->enabled = enable;
+	return count;
+};
+
+static ssize_t store_sas_phy_enable(struct class_device *cdev,
+		const char *buf, size_t count)
+{
+	if (count < 1)
+		return -EINVAL;
+
+	switch (buf[0]) {
+	case '0':
+		do_sas_phy_enable(cdev, count, 0);
+		break;
+	case '1':
+		do_sas_phy_enable(cdev, count, 1);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static ssize_t show_sas_phy_enable(struct class_device *cdev, char *buf)
+{
+	struct sas_phy *phy = transport_class_to_phy(cdev);
+
+	return snprintf(buf, 20, "%d", phy->enabled);
+}
+
+static CLASS_DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
+			 store_sas_phy_enable);
+
 static ssize_t do_sas_phy_reset(struct class_device *cdev,
 		size_t count, int hard_reset)
 {
@@ -435,6 +480,7 @@
 		return NULL;
 
 	phy->number = number;
+	phy->enabled = 1;
 
 	device_initialize(&phy->dev);
 	phy->dev.parent = get_device(parent);
@@ -454,7 +500,7 @@
 EXPORT_SYMBOL(sas_phy_alloc);
 
 /**
- * sas_phy_add  --  add a SAS PHY to the device hierachy
+ * sas_phy_add  --  add a SAS PHY to the device hierarchy
  * @phy:	The PHY to be added
  *
  * Publishes a SAS PHY to the rest of the system.
@@ -579,8 +625,19 @@
 static void sas_port_create_link(struct sas_port *port,
 				 struct sas_phy *phy)
 {
-	sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, phy->dev.bus_id);
-	sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port");
+	int res;
+
+	res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj,
+				phy->dev.bus_id);
+	if (res)
+		goto err;
+	res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port");
+	if (res)
+		goto err;
+	return;
+err:
+	printk(KERN_ERR "%s: Cannot create port links, err=%d\n",
+	       __FUNCTION__, res);
 }
 
 static void sas_port_delete_link(struct sas_port *port,
@@ -818,13 +875,20 @@
 
 void sas_port_mark_backlink(struct sas_port *port)
 {
+	int res;
 	struct device *parent = port->dev.parent->parent->parent;
 
 	if (port->is_backlink)
 		return;
 	port->is_backlink = 1;
-	sysfs_create_link(&port->dev.kobj, &parent->kobj,
-			  parent->bus_id);
+	res = sysfs_create_link(&port->dev.kobj, &parent->kobj,
+				parent->bus_id);
+	if (res)
+		goto err;
+	return;
+err:
+	printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n",
+	       __FUNCTION__, res);
 
 }
 EXPORT_SYMBOL(sas_port_mark_backlink);
@@ -1201,7 +1265,7 @@
 EXPORT_SYMBOL(sas_expander_alloc);
 
 /**
- * sas_rphy_add  --  add a SAS remote PHY to the device hierachy
+ * sas_rphy_add  --  add a SAS remote PHY to the device hierarchy
  * @rphy:	The remote PHY to be added
  *
  * Publishes a SAS remote PHY to the rest of the system.
@@ -1237,7 +1301,7 @@
 	if (identify->device_type == SAS_END_DEVICE &&
 	    rphy->scsi_target_id != -1) {
 		scsi_scan_target(&rphy->dev, 0,
-				rphy->scsi_target_id, ~0, 0);
+				rphy->scsi_target_id, SCAN_WILD_CARD, 0);
 	}
 
 	return 0;
@@ -1253,7 +1317,7 @@
  * Note:
  *   This function must only be called on a remote
  *   PHY that has not sucessfully been added using
- *   sas_rphy_add().
+ *   sas_rphy_add() (or has been sas_rphy_remove()'d)
  */
 void sas_rphy_free(struct sas_rphy *rphy)
 {
@@ -1272,18 +1336,30 @@
 EXPORT_SYMBOL(sas_rphy_free);
 
 /**
- * sas_rphy_delete  --  remove SAS remote PHY
- * @rphy:	SAS remote PHY to remove
+ * sas_rphy_delete  --  remove and free SAS remote PHY
+ * @rphy:	SAS remote PHY to remove and free
  *
- * Removes the specified SAS remote PHY.
+ * Removes the specified SAS remote PHY and frees it.
  */
 void
 sas_rphy_delete(struct sas_rphy *rphy)
 {
+	sas_rphy_remove(rphy);
+	sas_rphy_free(rphy);
+}
+EXPORT_SYMBOL(sas_rphy_delete);
+
+/**
+ * sas_rphy_remove  --  remove SAS remote PHY
+ * @rphy:	SAS remote phy to remove
+ *
+ * Removes the specified SAS remote PHY.
+ */
+void
+sas_rphy_remove(struct sas_rphy *rphy)
+{
 	struct device *dev = &rphy->dev;
 	struct sas_port *parent = dev_to_sas_port(dev->parent);
-	struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
-	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 
 	switch (rphy->identify.device_type) {
 	case SAS_END_DEVICE:
@@ -1299,17 +1375,10 @@
 
 	transport_remove_device(dev);
 	device_del(dev);
-	transport_destroy_device(dev);
-
-	mutex_lock(&sas_host->lock);
-	list_del(&rphy->list);
-	mutex_unlock(&sas_host->lock);
 
 	parent->rphy = NULL;
-
-	put_device(dev);
 }
-EXPORT_SYMBOL(sas_rphy_delete);
+EXPORT_SYMBOL(sas_rphy_remove);
 
 /**
  * scsi_is_sas_rphy  --  check if a struct device represents a SAS remote PHY
@@ -1389,6 +1458,10 @@
 	SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1,	\
 			!i->f->set_phy_speed, S_IRUGO)
 
+#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func)			\
+	SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1,	\
+			  !i->f->func, S_IRUGO)
+
 #define SETUP_PORT_ATTRIBUTE(field)					\
 	SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
 
@@ -1396,10 +1469,10 @@
 	SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func)
 
 #define SETUP_PHY_ATTRIBUTE_WRONLY(field)				\
-	SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1)
+	SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1)
 
 #define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func)		\
-	SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func)
+	SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func)
 
 #define SETUP_END_DEV_ATTRIBUTE(field)					\
 	SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1)
@@ -1479,6 +1552,7 @@
 	SETUP_PHY_ATTRIBUTE(phy_reset_problem_count);
 	SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset);
 	SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset);
+	SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable);
 	i->phy_attrs[count] = NULL;
 
 	count = 0;
@@ -1587,7 +1661,7 @@
 }
 
 MODULE_AUTHOR("Christoph Hellwig");
-MODULE_DESCRIPTION("SAS Transphy Attributes");
+MODULE_DESCRIPTION("SAS Transport Attributes");
 MODULE_LICENSE("GPL");
 
 module_init(sas_transport_init);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 014d7fe..6f56f87 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -46,7 +46,6 @@
 				 * two cc/ua clears */
 
 /* Private data accessors (keep these out of the header file) */
-#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
 #define spi_dv_in_progress(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_in_progress)
 #define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex)
 
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index b781a90..5a8f55f 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -35,7 +35,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/bio.h>
 #include <linux/genhd.h>
@@ -1270,9 +1269,18 @@
 
 	/* Some devices return the total number of sectors, not the
 	 * highest sector number.  Make the necessary adjustment. */
-	if (sdp->fix_capacity)
+	if (sdp->fix_capacity) {
 		--sdkp->capacity;
 
+	/* Some devices have version which report the correct sizes
+	 * and others which do not. We guess size according to a heuristic
+	 * and err on the side of lowering the capacity. */
+	} else {
+		if (sdp->guess_capacity)
+			if (sdkp->capacity & 0x01) /* odd sizes are odd */
+				--sdkp->capacity;
+	}
+
 got_data:
 	if (sector_size == 0) {
 		sector_size = 512;
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index e81f97a..a15752b 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -244,9 +244,10 @@
 	regs.SASR = wdregs + 3;
 	regs.SCMD = wdregs + 7;
 
-	wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_16_20);
+	wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
 
-	hdata->wh.no_sync = 0;
+	if (hdata->wh.no_sync == 0xff)
+		hdata->wh.no_sync = 0;
 
 	if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) {
 		printk(KERN_WARNING "sgiwd93: Could not register irq %d "
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index 551bacc..018c65f 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -123,6 +123,7 @@
 	hostdata->differential = differential;
 	hostdata->clock = clock;
 	hostdata->chip710 = 1;
+	hostdata->burst_length = 8;
 
 	/* and register the chip */
 	if((host = NCR_700_detect(&sim710_driver_template, hostdata, dev))
diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c
new file mode 100644
index 0000000..6bc5051
--- /dev/null
+++ b/drivers/scsi/sni_53c710.c
@@ -0,0 +1,159 @@
+/* -*- mode: c; c-basic-offset: 8 -*- */
+
+/* SNI RM driver
+ *
+ * Copyright (C) 2001 by James.Bottomley@HansenPartnership.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**-----------------------------------------------------------------------------
+ */
+
+/*
+ * Based on lasi700.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/mm.h>
+#include <linux/blkdev.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
+
+#include "53c700.h"
+
+MODULE_AUTHOR("Thomas Bogendörfer");
+MODULE_DESCRIPTION("SNI RM 53c710 SCSI Driver");
+MODULE_LICENSE("GPL");
+
+#define SNIRM710_CLOCK	32
+
+static struct scsi_host_template snirm710_template = {
+	.name		= "SNI RM SCSI 53c710",
+	.proc_name	= "snirm_53c710",
+	.this_id	= 7,
+	.module		= THIS_MODULE,
+};
+
+static int __init snirm710_probe(struct platform_device *dev)
+{
+	unsigned long base;
+	struct NCR_700_Host_Parameters *hostdata;
+	struct Scsi_Host *host;
+	struct  resource *res;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	base = res->start;
+	hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL);
+	if (!hostdata) {
+		printk(KERN_ERR "%s: Failed to allocate host data\n",
+		       dev->dev.bus_id);
+		return -ENOMEM;
+	}
+
+	hostdata->dev = &dev->dev;
+	dma_set_mask(&dev->dev, DMA_32BIT_MASK);
+	hostdata->base = ioremap_nocache(CPHYSADDR(base), 0x100);
+	hostdata->differential = 0;
+
+	hostdata->clock = SNIRM710_CLOCK;
+	hostdata->force_le_on_be = 1;
+	hostdata->chip710 = 1;
+	hostdata->burst_length = 4;
+
+	host = NCR_700_detect(&snirm710_template, hostdata, &dev->dev);
+	if (!host)
+		goto out_kfree;
+	host->this_id = 7;
+	host->base = base;
+	host->irq = platform_get_irq(dev, 0);
+	if(request_irq(host->irq, NCR_700_intr, SA_SHIRQ, "snirm710", host)) {
+		printk(KERN_ERR "snirm710: request_irq failed!\n");
+		goto out_put_host;
+	}
+
+	dev_set_drvdata(&dev->dev, host);
+	scsi_scan_host(host);
+
+	return 0;
+
+ out_put_host:
+	scsi_host_put(host);
+ out_kfree:
+	iounmap(hostdata->base);
+	kfree(hostdata);
+	return -ENODEV;
+}
+
+static int __exit snirm710_driver_remove(struct platform_device *dev)
+{
+	struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
+	struct NCR_700_Host_Parameters *hostdata =
+		(struct NCR_700_Host_Parameters *)host->hostdata[0];
+
+	scsi_remove_host(host);
+	NCR_700_release(host);
+	free_irq(host->irq, host);
+	iounmap(hostdata->base);
+	kfree(hostdata);
+
+	return 0;
+}
+
+static struct platform_driver snirm710_driver = {
+	.probe	= snirm710_probe,
+	.remove	= __devexit_p(snirm710_driver_remove),
+	.driver	= {
+		.name	= "snirm_53c710",
+	},
+};
+
+static int __init snirm710_init(void)
+{
+	int err;
+
+	if ((err = platform_driver_register(&snirm710_driver))) {
+		printk(KERN_ERR "Driver registration failed\n");
+		return err;
+	}
+	return 0;
+}
+
+static void __exit snirm710_exit(void)
+{
+	platform_driver_unregister(&snirm710_driver);
+}
+
+module_init(snirm710_init);
+module_exit(snirm710_exit);
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 89e9b36..1857d68 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -35,7 +35,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/bio.h>
 #include <linux/string.h>
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 0578ba4..e1589f9 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/errno.h>
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 488ec79..98d8411 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -9,7 +9,7 @@
    Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
    Michael Schaefer, J"org Weule, and Eric Youngdale.
 
-   Copyright 1992 - 2006 Kai Makisara
+   Copyright 1992 - 2007 Kai Makisara
    email Kai.Makisara@kolumbus.fi
 
    Some small formal changes - aeb, 950809
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static const char *verstr = "20061107";
+static const char *verstr = "20070203";
 
 #include <linux/module.h>
 
@@ -195,8 +195,8 @@
 static int st_probe(struct device *);
 static int st_remove(struct device *);
 
-static int do_create_driverfs_files(void);
-static void do_remove_driverfs_files(void);
+static int do_create_sysfs_files(void);
+static void do_remove_sysfs_files(void);
 static int do_create_class_files(struct scsi_tape *, int, int);
 
 static struct scsi_driver st_template = {
@@ -1168,6 +1168,7 @@
 		STps = &(STp->ps[i]);
 		STps->rw = ST_IDLE;
 	}
+	STp->try_dio_now = STp->try_dio;
 	STp->recover_count = 0;
 	DEB( STp->nbr_waits = STp->nbr_finished = 0;
 	     STp->nbr_requests = STp->nbr_dio = STp->nbr_pages = STp->nbr_combinable = 0; )
@@ -1400,9 +1401,9 @@
 	struct st_buffer *STbp = STp->buffer;
 
 	if (is_read)
-		i = STp->try_dio && try_rdio;
+		i = STp->try_dio_now && try_rdio;
 	else
-		i = STp->try_dio && try_wdio;
+		i = STp->try_dio_now && try_wdio;
 
 	if (i && ((unsigned long)buf & queue_dma_alignment(
 					STp->device->request_queue)) == 0) {
@@ -1599,7 +1600,7 @@
 			STm->do_async_writes && STps->eof < ST_EOM_OK;
 
 		if (STp->block_size != 0 && STm->do_buffer_writes &&
-		    !(STp->try_dio && try_wdio) && STps->eof < ST_EOM_OK &&
+		    !(STp->try_dio_now && try_wdio) && STps->eof < ST_EOM_OK &&
 		    STbp->buffer_bytes < STbp->buffer_size) {
 			STp->dirty = 1;
 			/* Don't write a buffer that is not full enough. */
@@ -1769,7 +1770,7 @@
 	if (STp->block_size == 0)
 		blks = bytes = count;
 	else {
-		if (!(STp->try_dio && try_rdio) && STm->do_read_ahead) {
+		if (!(STp->try_dio_now && try_rdio) && STm->do_read_ahead) {
 			blks = (STp->buffer)->buffer_blocks;
 			bytes = blks * STp->block_size;
 		} else {
@@ -1948,10 +1949,12 @@
 		goto out;
 
 	STm = &(STp->modes[STp->current_mode]);
-	if (!(STm->do_read_ahead) && STp->block_size != 0 &&
-	    (count % STp->block_size) != 0) {
-		retval = (-EINVAL);	/* Read must be integral number of blocks */
-		goto out;
+	if (STp->block_size != 0 && (count % STp->block_size) != 0) {
+		if (!STm->do_read_ahead) {
+			retval = (-EINVAL);	/* Read must be integral number of blocks */
+			goto out;
+		}
+		STp->try_dio_now = 0;  /* Direct i/o can't handle split blocks */
 	}
 
 	STps = &(STp->ps[STp->partition]);
@@ -3861,7 +3864,7 @@
 
 #endif
 
-static struct file_operations st_fops =
+static const struct file_operations st_fops =
 {
 	.owner =	THIS_MODULE,
 	.read =		st_read,
@@ -4190,7 +4193,7 @@
 	if (err)
 		goto err_chrdev;
 
-	err = do_create_driverfs_files();
+	err = do_create_sysfs_files();
 	if (err)
 		goto err_scsidrv;
 
@@ -4208,7 +4211,7 @@
 
 static void __exit exit_st(void)
 {
-	do_remove_driverfs_files();
+	do_remove_sysfs_files();
 	scsi_unregister_driver(&st_template.gendrv);
 	unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
 				 ST_MAX_TAPE_ENTRIES);
@@ -4246,43 +4249,43 @@
 }
 static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);
 
-static int do_create_driverfs_files(void)
+static int do_create_sysfs_files(void)
 {
-	struct device_driver *driverfs = &st_template.gendrv;
+	struct device_driver *sysfs = &st_template.gendrv;
 	int err;
 
-	err = driver_create_file(driverfs, &driver_attr_try_direct_io);
+	err = driver_create_file(sysfs, &driver_attr_try_direct_io);
 	if (err)
 		return err;
-	err = driver_create_file(driverfs, &driver_attr_fixed_buffer_size);
+	err = driver_create_file(sysfs, &driver_attr_fixed_buffer_size);
 	if (err)
 		goto err_try_direct_io;
-	err = driver_create_file(driverfs, &driver_attr_max_sg_segs);
+	err = driver_create_file(sysfs, &driver_attr_max_sg_segs);
 	if (err)
 		goto err_attr_fixed_buf;
-	err = driver_create_file(driverfs, &driver_attr_version);
+	err = driver_create_file(sysfs, &driver_attr_version);
 	if (err)
 		goto err_attr_max_sg;
 
 	return 0;
 
 err_attr_max_sg:
-	driver_remove_file(driverfs, &driver_attr_max_sg_segs);
+	driver_remove_file(sysfs, &driver_attr_max_sg_segs);
 err_attr_fixed_buf:
-	driver_remove_file(driverfs, &driver_attr_fixed_buffer_size);
+	driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
 err_try_direct_io:
-	driver_remove_file(driverfs, &driver_attr_try_direct_io);
+	driver_remove_file(sysfs, &driver_attr_try_direct_io);
 	return err;
 }
 
-static void do_remove_driverfs_files(void)
+static void do_remove_sysfs_files(void)
 {
-	struct device_driver *driverfs = &st_template.gendrv;
+	struct device_driver *sysfs = &st_template.gendrv;
 
-	driver_remove_file(driverfs, &driver_attr_version);
-	driver_remove_file(driverfs, &driver_attr_max_sg_segs);
-	driver_remove_file(driverfs, &driver_attr_fixed_buffer_size);
-	driver_remove_file(driverfs, &driver_attr_try_direct_io);
+	driver_remove_file(sysfs, &driver_attr_version);
+	driver_remove_file(sysfs, &driver_attr_max_sg_segs);
+	driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
+	driver_remove_file(sysfs, &driver_attr_try_direct_io);
 }
 
 
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 05a5cae..50f3deb 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -117,7 +117,8 @@
 	unsigned char cln_sense_value;
 	unsigned char cln_sense_mask;
 	unsigned char use_pf;			/* Set Page Format bit in all mode selects? */
-	unsigned char try_dio;			/* try direct i/o? */
+	unsigned char try_dio;			/* try direct i/o in general? */
+	unsigned char try_dio_now;		/* try direct i/o before next close? */
 	unsigned char c_algo;			/* compression algorithm */
 	unsigned char pos_unknown;			/* after reset position unknown */
 	int tape_type;
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index ba6bcda..69be132 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -17,7 +17,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/pci.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index 69ee3e4..5e46d84 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -58,7 +58,6 @@
 
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c
index bb0c9fd9..7cb4a31 100644
--- a/drivers/scsi/sun3_scsi_vme.c
+++ b/drivers/scsi/sun3_scsi_vme.c
@@ -20,7 +20,6 @@
 
 #include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index 6b60536..80fb3f8 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -53,7 +53,7 @@
 	struct ConfigDev *esp_dev;
 
 	esp_dev = 0;
-	esp = esp_allocate(tpnt, (void *) esp_dev);
+	esp = esp_allocate(tpnt, esp_dev, 0);
 
 	/* Do command transfer with DMA */
 	esp->do_pio_cmds = 0;
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index 32c883f..2ca9505 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -32,7 +32,6 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw1.h b/drivers/scsi/sym53c8xx_2/sym_fw1.h
index 7b39f4a..7b08d6c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw1.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw1.h
@@ -1020,7 +1020,7 @@
 	 *  It shall be a tagged command.
 	 *  Read SIMPLE+TAG.
 	 *  The C code will deal with errors.
-	 *  Agressive optimization, is'nt it? :)
+	 *  Aggressive optimization, isn't it? :)
 	 */
 	SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
 		HADDR_1 (msgin),
@@ -1044,7 +1044,7 @@
 		RADDR_1 (dsa),
 	/*
 	 *  The SIDL still contains the TAG value.
-	 *  Agressive optimization, isn't it? :):)
+	 *  Aggressive optimization, isn't it? :):)
 	 */
 	SCR_REG_SFBR (sidl, SCR_SHL, 0),
 		0,
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw2.h b/drivers/scsi/sym53c8xx_2/sym_fw2.h
index 851f270..6e5b952 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw2.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw2.h
@@ -956,7 +956,7 @@
 	 *  It shall be a tagged command.
 	 *  Read SIMPLE+TAG.
 	 *  The C code will deal with errors.
-	 *  Agressive optimization, is'nt it? :)
+	 *  Aggressive optimization, isn't it? :)
 	 */
 	SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
 		HADDR_1 (msgin),
@@ -968,7 +968,7 @@
 		offsetof(struct sym_lcb, head.itlq_tbl_sa),
 	/*
 	 *  The SIDL still contains the TAG value.
-	 *  Agressive optimization, isn't it? :):)
+	 *  Aggressive optimization, isn't it? :):)
 	 */
 	SCR_REG_SFBR (sidl, SCR_SHL, 0),
 		0,
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c
index 0b7a70f..248d60b 100644
--- a/drivers/scsi/t128.c
+++ b/drivers/scsi/t128.c
@@ -108,7 +108,6 @@
 
 #include <asm/system.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/io.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index fa5382e..a583e89 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -221,7 +221,6 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index 2083454..fa4e08e 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -69,11 +69,15 @@
  * Added support for pre -A chips, which don't have advanced features
  * and will generate CSR_RESEL rather than CSR_RESEL_AM.
  *	Richard Hirst <richard@sleepie.demon.co.uk>  August 2000
+ *
+ * Added support for Burst Mode DMA and Fast SCSI. Enabled the use of
+ * default_sx_per for asynchronous data transfers. Added adjustment
+ * of transfer periods in sx_table to the actual input-clock.
+ *  peter fuerst <post@pfrst.de>  February 2007
  */
 
 #include <linux/module.h>
 
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -87,9 +91,11 @@
 
 #include "wd33c93.h"
 
+#define optimum_sx_per(hostdata) (hostdata)->sx_table[1].period_ns
 
-#define WD33C93_VERSION    "1.26"
-#define WD33C93_DATE       "22/Feb/2003"
+
+#define WD33C93_VERSION    "1.26++"
+#define WD33C93_DATE       "10/Feb/2007"
 
 MODULE_AUTHOR("John Shifflett");
 MODULE_DESCRIPTION("Generic WD33C93 SCSI driver");
@@ -123,6 +129,13 @@
  *                    defines in wd33c93.h
  * -  clock:x        -x = clock input in MHz for WD33c93 chip. Normal values
  *                    would be from 8 through 20. Default is 8.
+ * -  burst:x        -x = 1 to use Burst Mode (or Demand-Mode) DMA, x = 0 to use
+ *                    Single Byte DMA, which is the default. Argument is
+ *                    optional - if not present, same as "burst:1".
+ * -  fast:x         -x = 1 to enable Fast SCSI, which is only effective with
+ *                    input-clock divisor 4 (WD33C93_FS_16_20), x = 0 to disable
+ *                    it, which is the default.  Argument is optional - if not
+ *                    present, same as "fast:1".
  * -  next           -No argument. Used to separate blocks of keywords when
  *                    there's more than one host adapter in the system.
  *
@@ -149,7 +162,7 @@
  */
 
 /* Normally, no defaults are specified */
-static char *setup_args[] = { "", "", "", "", "", "", "", "", "" };
+static char *setup_args[] = { "", "", "", "", "", "", "", "", "", "" };
 
 static char *setup_strings;
 module_param(setup_strings, charp, 0);
@@ -299,20 +312,8 @@
 	return x;
 }
 
-static struct sx_period sx_table[] = {
-	{1, 0x20},
-	{252, 0x20},
-	{376, 0x30},
-	{500, 0x40},
-	{624, 0x50},
-	{752, 0x60},
-	{876, 0x70},
-	{1000, 0x00},
-	{0, 0}
-};
-
 static int
-round_period(unsigned int period)
+round_period(unsigned int period, const struct sx_period *sx_table)
 {
 	int x;
 
@@ -325,17 +326,49 @@
 	return 7;
 }
 
+/*
+ * Calculate Synchronous Transfer Register value from SDTR code.
+ */
 static uchar
-calc_sync_xfer(unsigned int period, unsigned int offset)
+calc_sync_xfer(unsigned int period, unsigned int offset, unsigned int fast,
+               const struct sx_period *sx_table)
 {
+	/* When doing Fast SCSI synchronous data transfers, the corresponding
+	 * value in 'sx_table' is two times the actually used transfer period.
+	 */
 	uchar result;
 
+	if (offset && fast) {
+		fast = STR_FSS;
+		period *= 2;
+	} else {
+		fast = 0;
+	}
 	period *= 4;		/* convert SDTR code to ns */
-	result = sx_table[round_period(period)].reg_value;
+	result = sx_table[round_period(period,sx_table)].reg_value;
 	result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF;
+	result |= fast;
 	return result;
 }
 
+/*
+ * Calculate SDTR code bytes [3],[4] from period and offset.
+ */
+static inline void
+calc_sync_msg(unsigned int period, unsigned int offset, unsigned int fast,
+                uchar  msg[2])
+{
+	/* 'period' is a "normal"-mode value, like the ones in 'sx_table'. The
+	 * actually used transfer period for Fast SCSI synchronous data
+	 * transfers is half that value.
+	 */
+	period /= 4;
+	if (offset && fast)
+		period /= 2;
+	msg[0] = period;
+	msg[1] = offset;
+}
+
 int
 wd33c93_queuecommand(struct scsi_cmnd *cmd,
 		void (*done)(struct scsi_cmnd *))
@@ -633,7 +666,7 @@
 				write_wd33c93_count(regs,
 						    cmd->SCp.this_residual);
 				write_wd33c93(regs, WD_CONTROL,
-					      CTRL_IDI | CTRL_EDI | CTRL_DMA);
+					      CTRL_IDI | CTRL_EDI | hostdata->dma_mode);
 				hostdata->dma = D_DMA_RUNNING;
 			}
 		} else
@@ -713,6 +746,8 @@
 		cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
 		    cmd->SCp.buffer->offset;
 	}
+	if (!cmd->SCp.this_residual) /* avoid bogus setups */
+		return;
 
 	write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
 		      hostdata->sync_xfer[cmd->device->id]);
@@ -745,7 +780,7 @@
 #ifdef PROC_STATISTICS
 		hostdata->dma_cnt++;
 #endif
-		write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA);
+		write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | hostdata->dma_mode);
 		write_wd33c93_count(regs, cmd->SCp.this_residual);
 
 		if ((hostdata->level2 >= L2_DATA) ||
@@ -863,9 +898,6 @@
 			hostdata->outgoing_msg[0] |= 0x40;
 
 		if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) {
-#ifdef SYNC_DEBUG
-			printk(" sending SDTR ");
-#endif
 
 			hostdata->sync_stat[cmd->device->id] = SS_WAITING;
 
@@ -879,14 +911,20 @@
 			hostdata->outgoing_msg[2] = 3;
 			hostdata->outgoing_msg[3] = EXTENDED_SDTR;
 			if (hostdata->no_sync & (1 << cmd->device->id)) {
-				hostdata->outgoing_msg[4] =
-				    hostdata->default_sx_per / 4;
-				hostdata->outgoing_msg[5] = 0;
+				calc_sync_msg(hostdata->default_sx_per, 0,
+						0, hostdata->outgoing_msg + 4);
 			} else {
-				hostdata->outgoing_msg[4] = OPTIMUM_SX_PER / 4;
-				hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
+				calc_sync_msg(optimum_sx_per(hostdata),
+						OPTIMUM_SX_OFF,
+						hostdata->fast,
+						hostdata->outgoing_msg + 4);
 			}
 			hostdata->outgoing_len = 6;
+#ifdef SYNC_DEBUG
+			ucp = hostdata->outgoing_msg + 1;
+			printk(" sending SDTR %02x03%02x%02x%02x ",
+				ucp[0], ucp[2], ucp[3], ucp[4]);
+#endif
 		} else
 			hostdata->outgoing_len = 1;
 
@@ -1002,8 +1040,13 @@
 #ifdef SYNC_DEBUG
 			    printk("-REJ-");
 #endif
-			if (hostdata->sync_stat[cmd->device->id] == SS_WAITING)
+			if (hostdata->sync_stat[cmd->device->id] == SS_WAITING) {
 				hostdata->sync_stat[cmd->device->id] = SS_SET;
+				/* we want default_sx_per, not DEFAULT_SX_PER */
+				hostdata->sync_xfer[cmd->device->id] =
+					calc_sync_xfer(hostdata->default_sx_per
+						/ 4, 0, 0, hostdata->sx_table);
+			}
 			write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
 			hostdata->state = S_CONNECTED;
 			break;
@@ -1023,7 +1066,10 @@
 
 				switch (ucp[2]) {	/* what's the EXTENDED code? */
 				case EXTENDED_SDTR:
-					id = calc_sync_xfer(ucp[3], ucp[4]);
+					/* default to default async period */
+					id = calc_sync_xfer(hostdata->
+							default_sx_per / 4, 0,
+							0, hostdata->sx_table);
 					if (hostdata->sync_stat[cmd->device->id] !=
 					    SS_WAITING) {
 
@@ -1042,20 +1088,22 @@
 						hostdata->outgoing_msg[1] = 3;
 						hostdata->outgoing_msg[2] =
 						    EXTENDED_SDTR;
-						hostdata->outgoing_msg[3] =
-						    hostdata->default_sx_per /
-						    4;
-						hostdata->outgoing_msg[4] = 0;
+						calc_sync_msg(hostdata->
+							default_sx_per, 0,
+							0, hostdata->outgoing_msg + 3);
 						hostdata->outgoing_len = 5;
-						hostdata->sync_xfer[cmd->device->id] =
-						    calc_sync_xfer(hostdata->
-								   default_sx_per
-								   / 4, 0);
 					} else {
-						hostdata->sync_xfer[cmd->device->id] = id;
+						if (ucp[4]) /* well, sync transfer */
+							id = calc_sync_xfer(ucp[3], ucp[4],
+									hostdata->fast,
+									hostdata->sx_table);
+						else if (ucp[3]) /* very unlikely... */
+							id = calc_sync_xfer(ucp[3], ucp[4],
+									0, hostdata->sx_table);
 					}
+					hostdata->sync_xfer[cmd->device->id] = id;
 #ifdef SYNC_DEBUG
-					printk("sync_xfer=%02x",
+					printk(" sync_xfer=%02x\n",
 					       hostdata->sync_xfer[cmd->device->id]);
 #endif
 					hostdata->sync_stat[cmd->device->id] =
@@ -1487,7 +1535,7 @@
 	write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
 	write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
 		      calc_sync_xfer(hostdata->default_sx_per / 4,
-				     DEFAULT_SX_OFF));
+				     DEFAULT_SX_OFF, 0, hostdata->sx_table));
 	write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET);
 
 
@@ -1513,6 +1561,9 @@
 	} else
 		hostdata->chip = C_UNKNOWN_CHIP;
 
+	if (hostdata->chip != C_WD33C93B)	/* Fast SCSI unavailable */
+		hostdata->fast = 0;
+
 	write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
 	write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
 }
@@ -1534,7 +1585,8 @@
 	for (i = 0; i < 8; i++) {
 		hostdata->busy[i] = 0;
 		hostdata->sync_xfer[i] =
-		    calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF);
+			calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
+					0, hostdata->sx_table);
 		hostdata->sync_stat[i] = SS_UNSET;	/* using default sync values */
 	}
 	hostdata->input_Q = NULL;
@@ -1783,6 +1835,98 @@
 	return ++x;
 }
 
+/*
+ * Calculate internal data-transfer-clock cycle from input-clock
+ * frequency (/MHz) and fill 'sx_table'.
+ *
+ * The original driver used to rely on a fixed sx_table, containing periods
+ * for (only) the lower limits of the respective input-clock-frequency ranges
+ * (8-10/12-15/16-20 MHz). Although it seems, that no problems ocurred with
+ * this setting so far, it might be desirable to adjust the transfer periods
+ * closer to the really attached, possibly 25% higher, input-clock, since
+ * - the wd33c93 may really use a significant shorter period, than it has
+ *   negotiated (eg. thrashing the target, which expects 4/8MHz, with 5/10MHz
+ *   instead).
+ * - the wd33c93 may ask the target for a lower transfer rate, than the target
+ *   is capable of (eg. negotiating for an assumed minimum of 252ns instead of
+ *   possible 200ns, which indeed shows up in tests as an approx. 10% lower
+ *   transfer rate).
+ */
+static inline unsigned int
+round_4(unsigned int x)
+{
+	switch (x & 3) {
+		case 1: --x;
+			break;
+		case 2: ++x;
+		case 3: ++x;
+	}
+	return x;
+}
+
+static void
+calc_sx_table(unsigned int mhz, struct sx_period sx_table[9])
+{
+	unsigned int d, i;
+	if (mhz < 11)
+		d = 2;	/* divisor for  8-10 MHz input-clock */
+	else if (mhz < 16)
+		d = 3;	/* divisor for 12-15 MHz input-clock */
+	else
+		d = 4;	/* divisor for 16-20 MHz input-clock */
+
+	d = (100000 * d) / 2 / mhz; /* 100 x DTCC / nanosec */
+
+	sx_table[0].period_ns = 1;
+	sx_table[0].reg_value = 0x20;
+	for (i = 1; i < 8; i++) {
+		sx_table[i].period_ns = round_4((i+1)*d / 100);
+		sx_table[i].reg_value = (i+1)*0x10;
+	}
+	sx_table[7].reg_value = 0;
+	sx_table[8].period_ns = 0;
+	sx_table[8].reg_value = 0;
+}
+
+/*
+ * check and, maybe, map an init- or "clock:"- argument.
+ */
+static uchar
+set_clk_freq(int freq, int *mhz)
+{
+	int x = freq;
+	if (WD33C93_FS_8_10 == freq)
+		freq = 8;
+	else if (WD33C93_FS_12_15 == freq)
+		freq = 12;
+	else if (WD33C93_FS_16_20 == freq)
+		freq = 16;
+	else if (freq > 7 && freq < 11)
+		x = WD33C93_FS_8_10;
+		else if (freq > 11 && freq < 16)
+		x = WD33C93_FS_12_15;
+		else if (freq > 15 && freq < 21)
+		x = WD33C93_FS_16_20;
+	else {
+			/* Hmm, wouldn't it be safer to assume highest freq here? */
+		x = WD33C93_FS_8_10;
+		freq = 8;
+	}
+	*mhz = freq;
+	return x;
+}
+
+/*
+ * to be used with the resync: fast: ... options
+ */
+static inline void set_resync ( struct WD33C93_hostdata *hd, int mask )
+{
+	int i;
+	for (i = 0; i < 8; i++)
+		if (mask & (1 << i))
+			hd->sync_stat[i] = SS_UNSET;
+}
+
 void
 wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
 	     dma_setup_t setup, dma_stop_t stop, int clock_freq)
@@ -1799,7 +1943,8 @@
 	hostdata = (struct WD33C93_hostdata *) instance->hostdata;
 
 	hostdata->regs = regs;
-	hostdata->clock_freq = clock_freq;
+	hostdata->clock_freq = set_clk_freq(clock_freq, &i);
+	calc_sx_table(i, hostdata->sx_table);
 	hostdata->dma_setup = setup;
 	hostdata->dma_stop = stop;
 	hostdata->dma_bounce_buffer = NULL;
@@ -1807,7 +1952,8 @@
 	for (i = 0; i < 8; i++) {
 		hostdata->busy[i] = 0;
 		hostdata->sync_xfer[i] =
-		    calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF);
+			calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
+					0, hostdata->sx_table);
 		hostdata->sync_stat[i] = SS_UNSET;	/* using default sync values */
 #ifdef PROC_STATISTICS
 		hostdata->cmd_cnt[i] = 0;
@@ -1829,6 +1975,8 @@
 	hostdata->default_sx_per = DEFAULT_SX_PER;
 	hostdata->no_sync = 0xff;	/* sync defaults to off */
 	hostdata->no_dma = 0;	/* default is DMA enabled */
+	hostdata->fast = 0;	/* default is Fast SCSI transfers disabled */
+	hostdata->dma_mode = CTRL_DMA;	/* default is Single Byte DMA */
 
 #ifdef PROC_INTERFACE
 	hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
@@ -1840,6 +1988,11 @@
 #endif
 #endif
 
+	if (check_setup_args("clock", &flags, &val, buf)) {
+		hostdata->clock_freq = set_clk_freq(val, &val);
+		calc_sx_table(val, hostdata->sx_table);
+	}
+
 	if (check_setup_args("nosync", &flags, &val, buf))
 		hostdata->no_sync = val;
 
@@ -1848,7 +2001,8 @@
 
 	if (check_setup_args("period", &flags, &val, buf))
 		hostdata->default_sx_per =
-		    sx_table[round_period((unsigned int) val)].period_ns;
+		    hostdata->sx_table[round_period((unsigned int) val,
+		                                    hostdata->sx_table)].period_ns;
 
 	if (check_setup_args("disconnect", &flags, &val, buf)) {
 		if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
@@ -1863,17 +2017,12 @@
 	if (check_setup_args("debug", &flags, &val, buf))
 		hostdata->args = val & DB_MASK;
 
-	if (check_setup_args("clock", &flags, &val, buf)) {
-		if (val > 7 && val < 11)
-			val = WD33C93_FS_8_10;
-		else if (val > 11 && val < 16)
-			val = WD33C93_FS_12_15;
-		else if (val > 15 && val < 21)
-			val = WD33C93_FS_16_20;
-		else
-			val = WD33C93_FS_8_10;
-		hostdata->clock_freq = val;
-	}
+	if (check_setup_args("burst", &flags, &val, buf))
+		hostdata->dma_mode = val ? CTRL_BURST:CTRL_DMA;
+
+	if (WD33C93_FS_16_20 == hostdata->clock_freq /* divisor 4 */
+		&& check_setup_args("fast", &flags, &val, buf))
+		hostdata->fast = !!val;
 
 	if ((i = check_setup_args("next", &flags, &val, buf))) {
 		while (i)
@@ -1918,53 +2067,65 @@
 	char tbuf[128];
 	struct WD33C93_hostdata *hd;
 	struct scsi_cmnd *cmd;
-	int x, i;
+	int x;
 	static int stop = 0;
 
 	hd = (struct WD33C93_hostdata *) instance->hostdata;
 
 /* If 'in' is TRUE we need to _read_ the proc file. We accept the following
- * keywords (same format as command-line, but only ONE per read):
+ * keywords (same format as command-line, but arguments are not optional):
  *    debug
  *    disconnect
  *    period
  *    resync
  *    proc
  *    nodma
+ *    level2
+ *    burst
+ *    fast
+ *    nosync
  */
 
 	if (in) {
 		buf[len] = '\0';
-		bp = buf;
+		for (bp = buf; *bp; ) {
+			while (',' == *bp || ' ' == *bp)
+				++bp;
 		if (!strncmp(bp, "debug:", 6)) {
-			bp += 6;
-			hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
+				hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
 		} else if (!strncmp(bp, "disconnect:", 11)) {
-			bp += 11;
-			x = simple_strtoul(bp, NULL, 0);
+				x = simple_strtoul(bp+11, &bp, 0);
 			if (x < DIS_NEVER || x > DIS_ALWAYS)
 				x = DIS_ADAPTIVE;
 			hd->disconnect = x;
 		} else if (!strncmp(bp, "period:", 7)) {
-			bp += 7;
-			x = simple_strtoul(bp, NULL, 0);
+			x = simple_strtoul(bp+7, &bp, 0);
 			hd->default_sx_per =
-			    sx_table[round_period((unsigned int) x)].period_ns;
+				hd->sx_table[round_period((unsigned int) x,
+							  hd->sx_table)].period_ns;
 		} else if (!strncmp(bp, "resync:", 7)) {
-			bp += 7;
-			x = simple_strtoul(bp, NULL, 0);
-			for (i = 0; i < 7; i++)
-				if (x & (1 << i))
-					hd->sync_stat[i] = SS_UNSET;
+				set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
 		} else if (!strncmp(bp, "proc:", 5)) {
-			bp += 5;
-			hd->proc = simple_strtoul(bp, NULL, 0);
+				hd->proc = simple_strtoul(bp+5, &bp, 0);
 		} else if (!strncmp(bp, "nodma:", 6)) {
-			bp += 6;
-			hd->no_dma = simple_strtoul(bp, NULL, 0);
+				hd->no_dma = simple_strtoul(bp+6, &bp, 0);
 		} else if (!strncmp(bp, "level2:", 7)) {
-			bp += 7;
-			hd->level2 = simple_strtoul(bp, NULL, 0);
+				hd->level2 = simple_strtoul(bp+7, &bp, 0);
+			} else if (!strncmp(bp, "burst:", 6)) {
+				hd->dma_mode =
+					simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
+			} else if (!strncmp(bp, "fast:", 5)) {
+				x = !!simple_strtol(bp+5, &bp, 0);
+				if (x != hd->fast)
+					set_resync(hd, 0xff);
+				hd->fast = x;
+			} else if (!strncmp(bp, "nosync:", 7)) {
+				x = simple_strtoul(bp+7, &bp, 0);
+				set_resync(hd, x ^ hd->no_sync);
+				hd->no_sync = x;
+			} else {
+				break; /* unknown keyword,syntax-error,... */
+			}
 		}
 		return len;
 	}
@@ -1978,8 +2139,9 @@
 		strcat(bp, tbuf);
 	}
 	if (hd->proc & PR_INFO) {
-		sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d",
-			hd->clock_freq, hd->no_sync, hd->no_dma);
+		sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
+			" dma_mode=%02x fast=%d",
+			hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast);
 		strcat(bp, tbuf);
 		strcat(bp, "\nsync_xfer[] =       ");
 		for (x = 0; x < 7; x++) {
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h
index edcb036..61ffb86 100644
--- a/drivers/scsi/wd33c93.h
+++ b/drivers/scsi/wd33c93.h
@@ -155,6 +155,9 @@
 #define WD33C93_FS_12_15 OWNID_FS_12
 #define WD33C93_FS_16_20 OWNID_FS_16
 
+   /* pass input-clock explicitely. accepted mhz values are 8-10,12-20 */
+#define WD33C93_FS_MHZ(mhz) (mhz)
+
    /* Control register */
 #define CTRL_HSP     0x01
 #define CTRL_HA      0x02
@@ -253,6 +256,9 @@
     uchar            sync_stat[8];     /* status of sync negotiation per target */
     uchar            no_sync;          /* bitmask: don't do sync on these targets */
     uchar            no_dma;           /* set this flag to disable DMA */
+    uchar            dma_mode;         /* DMA Burst Mode or Single Byte DMA */
+    uchar            fast;             /* set this flag to enable Fast SCSI */
+    struct sx_period sx_table[9];      /* transfer periods for actual DTC-setting */
 #ifdef PROC_INTERFACE
     uchar            proc;             /* bitmask: what's in proc output */
 #ifdef PROC_STATISTICS
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 5261f0a..c129a0e 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -364,6 +364,23 @@
 	}
 }
 
+static void
+serial_out_sync(struct uart_8250_port *up, int offset, int value)
+{
+	switch (up->port.iotype) {
+	case UPIO_MEM:
+	case UPIO_MEM32:
+#ifdef CONFIG_SERIAL_8250_AU1X00
+	case UPIO_AU:
+#endif
+		serial_out(up, offset, value);
+		serial_in(up, UART_LCR);	/* safe, no side-effects */
+		break;
+	default:
+		serial_out(up, offset, value);
+	}
+}
+
 /*
  * We used to support using pause I/O for certain machines.  We
  * haven't supported this for a while, but just in case it's badly
@@ -920,12 +937,16 @@
 #ifdef __i386__
 		outb(0xff, 0x080);
 #endif
-		scratch2 = serial_inp(up, UART_IER);
+		/*
+		 * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
+		 * 16C754B) allow only to modify them if an EFR bit is set.
+		 */
+		scratch2 = serial_inp(up, UART_IER) & 0x0f;
 		serial_outp(up, UART_IER, 0x0F);
 #ifdef __i386__
 		outb(0, 0x080);
 #endif
-		scratch3 = serial_inp(up, UART_IER);
+		scratch3 = serial_inp(up, UART_IER) & 0x0f;
 		serial_outp(up, UART_IER, scratch);
 		if (scratch2 != 0 || scratch3 != 0x0F) {
 			/*
@@ -1041,7 +1062,7 @@
 #endif
 	serial_outp(up, UART_MCR, save_mcr);
 	serial8250_clear_fifos(up);
-	(void)serial_in(up, UART_RX);
+	serial_in(up, UART_RX);
 	if (up->capabilities & UART_CAP_UUE)
 		serial_outp(up, UART_IER, UART_IER_UUE);
 	else
@@ -1175,7 +1196,7 @@
 }
 
 static void
-receive_chars(struct uart_8250_port *up, int *status)
+receive_chars(struct uart_8250_port *up, unsigned int *status)
 {
 	struct tty_struct *tty = up->port.info->tty;
 	unsigned char ch, lsr = *status;
@@ -1447,6 +1468,12 @@
 	serial_do_unlink(i, up);
 }
 
+/* Base timer interval for polling */
+static inline int poll_timeout(int timeout)
+{
+	return timeout > 6 ? (timeout / 2 - 2) : 1;
+}
+
 /*
  * This function is used to handle ports that do not have an
  * interrupt.  This doesn't work very well for 16450's, but gives
@@ -1456,16 +1483,51 @@
 static void serial8250_timeout(unsigned long data)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)data;
-	unsigned int timeout;
 	unsigned int iir;
 
 	iir = serial_in(up, UART_IIR);
 	if (!(iir & UART_IIR_NO_INT))
 		serial8250_handle_port(up);
+	mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+}
 
-	timeout = up->port.timeout;
-	timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-	mod_timer(&up->timer, jiffies + timeout);
+static void serial8250_backup_timeout(unsigned long data)
+{
+	struct uart_8250_port *up = (struct uart_8250_port *)data;
+	unsigned int iir, ier = 0;
+
+	/*
+	 * Must disable interrupts or else we risk racing with the interrupt
+	 * based handler.
+	 */
+	if (is_real_interrupt(up->port.irq)) {
+		ier = serial_in(up, UART_IER);
+		serial_out(up, UART_IER, 0);
+	}
+
+	iir = serial_in(up, UART_IIR);
+
+	/*
+	 * This should be a safe test for anyone who doesn't trust the
+	 * IIR bits on their UART, but it's specifically designed for
+	 * the "Diva" UART used on the management processor on many HP
+	 * ia64 and parisc boxes.
+	 */
+	if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
+	    (!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
+	    (serial_in(up, UART_LSR) & UART_LSR_THRE)) {
+		iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
+		iir |= UART_IIR_THRI;
+	}
+
+	if (!(iir & UART_IIR_NO_INT))
+		serial8250_handle_port(up);
+
+	if (is_real_interrupt(up->port.irq))
+		serial_out(up, UART_IER, ier);
+
+	/* Standard timer interval plus 0.2s to keep the port running */
+	mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout) + HZ/5);
 }
 
 static unsigned int serial8250_tx_empty(struct uart_port *port)
@@ -1536,6 +1598,37 @@
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/*
+ *	Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+	unsigned int status, tmout = 10000;
+
+	/* Wait up to 10ms for the character(s) to be sent. */
+	do {
+		status = serial_in(up, UART_LSR);
+
+		if (status & UART_LSR_BI)
+			up->lsr_break_flag = UART_LSR_BI;
+
+		if (--tmout == 0)
+			break;
+		udelay(1);
+	} while ((status & bits) != bits);
+
+	/* Wait up to 1s for flow control if necessary */
+	if (up->port.flags & UPF_CONS_FLOW) {
+		tmout = 1000000;
+		while (!(serial_in(up, UART_MSR) & UART_MSR_CTS) && --tmout) {
+			udelay(1);
+			touch_nmi_watchdog();
+		}
+	}
+}
+
 static int serial8250_startup(struct uart_port *port)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1609,18 +1702,50 @@
 		serial_outp(up, UART_LCR, 0);
 	}
 
+	if (is_real_interrupt(up->port.irq)) {
+		/*
+		 * Test for UARTs that do not reassert THRE when the
+		 * transmitter is idle and the interrupt has already
+		 * been cleared.  Real 16550s should always reassert
+		 * this interrupt whenever the transmitter is idle and
+		 * the interrupt is enabled.  Delays are necessary to
+		 * allow register changes to become visible.
+		 */
+		spin_lock_irqsave(&up->port.lock, flags);
+
+		wait_for_xmitr(up, UART_LSR_THRE);
+		serial_out_sync(up, UART_IER, UART_IER_THRI);
+		udelay(1); /* allow THRE to set */
+		serial_in(up, UART_IIR);
+		serial_out(up, UART_IER, 0);
+		serial_out_sync(up, UART_IER, UART_IER_THRI);
+		udelay(1); /* allow a working UART time to re-assert THRE */
+		iir = serial_in(up, UART_IIR);
+		serial_out(up, UART_IER, 0);
+
+		spin_unlock_irqrestore(&up->port.lock, flags);
+
+		/*
+		 * If the interrupt is not reasserted, setup a timer to
+		 * kick the UART on a regular basis.
+		 */
+		if (iir & UART_IIR_NO_INT) {
+			pr_debug("ttyS%d - using backup timer\n", port->line);
+			up->timer.function = serial8250_backup_timeout;
+			up->timer.data = (unsigned long)up;
+			mod_timer(&up->timer, jiffies +
+			          poll_timeout(up->port.timeout) + HZ/5);
+		}
+	}
+
 	/*
 	 * If the "interrupt" for this port doesn't correspond with any
 	 * hardware interrupt, we use a timer-based system.  The original
 	 * driver used to do this with IRQ0.
 	 */
 	if (!is_real_interrupt(up->port.irq)) {
-		unsigned int timeout = up->port.timeout;
-
-		timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-
 		up->timer.data = (unsigned long)up;
-		mod_timer(&up->timer, jiffies + timeout);
+		mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
 	} else {
 		retval = serial_link_irq_chain(up);
 		if (retval)
@@ -1736,9 +1861,9 @@
 	 */
 	(void) serial_in(up, UART_RX);
 
-	if (!is_real_interrupt(up->port.irq))
-		del_timer_sync(&up->timer);
-	else
+	del_timer_sync(&up->timer);
+	up->timer.function = serial8250_timeout;
+	if (is_real_interrupt(up->port.irq))
 		serial_unlink_irq_chain(up);
 }
 
@@ -2208,37 +2333,6 @@
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = serial_in(up, UART_LSR);
-
-		if (status & UART_LSR_BI)
-			up->lsr_break_flag = UART_LSR_BI;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & bits) != bits);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (up->port.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (!(serial_in(up, UART_MSR) & UART_MSR_CTS) && --tmout) {
-			udelay(1);
-			touch_nmi_watchdog();
-		}
-	}
-}
-
 static void serial8250_console_putchar(struct uart_port *port, int ch)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
diff --git a/drivers/serial/8250_acorn.c b/drivers/serial/8250_acorn.c
index ef8cc8a..562ba74 100644
--- a/drivers/serial/8250_acorn.c
+++ b/drivers/serial/8250_acorn.c
@@ -47,11 +47,10 @@
 	unsigned long bus_addr;
 	unsigned int i;
 
-	info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL);
+	info = kzalloc(sizeof(struct serial_card_info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	memset(info, 0, sizeof(struct serial_card_info));
 	info->num_ports = type->num_ports;
 
 	bus_addr = ecard_resource_start(ec, type->type);
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 52e2e64..6d7d616 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -679,6 +678,13 @@
 	 */
 	{
 		.vendor		= PCI_VENDOR_ID_PLX,
+		.device		= PCI_DEVICE_ID_PLX_9030,
+		.subvendor	= PCI_SUBVENDOR_ID_PERLE,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_default_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_PLX,
 		.device		= PCI_DEVICE_ID_PLX_9050,
 		.subvendor	= PCI_SUBVENDOR_ID_EXSYS,
 		.subdevice	= PCI_SUBDEVICE_ID_EXSYS_4055,
@@ -936,6 +942,7 @@
 
 	pbn_b2_1_115200,
 	pbn_b2_2_115200,
+	pbn_b2_4_115200,
 	pbn_b2_8_115200,
 
 	pbn_b2_1_460800,
@@ -1249,6 +1256,12 @@
 		.base_baud	= 115200,
 		.uart_offset	= 8,
 	},
+	[pbn_b2_4_115200] = {
+		.flags          = FL_BASE2,
+		.num_ports      = 4,
+		.base_baud      = 115200,
+		.uart_offset    = 8,
+	},
 	[pbn_b2_8_115200] = {
 		.flags		= FL_BASE2,
 		.num_ports	= 8,
@@ -1614,7 +1627,7 @@
 			nr_ports = rc;
 	}
 
-	priv = kmalloc(sizeof(struct serial_private) +
+	priv = kzalloc(sizeof(struct serial_private) +
 		       sizeof(unsigned int) * nr_ports,
 		       GFP_KERNEL);
 	if (!priv) {
@@ -1622,9 +1635,6 @@
 		goto err_deinit;
 	}
 
-	memset(priv, 0, sizeof(struct serial_private) +
-			sizeof(unsigned int) * nr_ports);
-
 	priv->dev = dev;
 	priv->quirk = quirk;
 
@@ -1990,6 +2000,10 @@
 	{	PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_panacom2 },
+	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+		PCI_VENDOR_ID_ESDGMBH,
+		PCI_DEVICE_ID_ESDGMBH_CPCIASIO4, 0, 0,
+		pbn_b2_4_115200 },
 	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
 		PCI_SUBVENDOR_ID_CHASE_PCIFAST,
 		PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0, 
@@ -2379,6 +2393,15 @@
 		pbn_b2_2_115200 },
 
 	/*
+	 * Perle PCI-RAS cards
+	 */
+	{       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+		PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS4,
+		0, 0, pbn_b2_4_921600 },
+	{       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+		PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8,
+		0, 0, pbn_b2_8_921600 },
+	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
 	 */
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index d3d6b82..cde5db4 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -450,11 +450,11 @@
 	port.dev = &dev->dev;
 
 	line = serial8250_register_port(&port);
+	if (line < 0)
+		return -ENODEV;
 
-	if (line >= 0)
-		pnp_set_drvdata(dev, (void *)((long)line + 1));
-	return line >= 0 ? 0 : -ENODEV;
-
+	pnp_set_drvdata(dev, (void *)((long)line + 1));
+	return 0;
 }
 
 static void __devexit serial_pnp_remove(struct pnp_dev *dev)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 2978c09..ad9f321 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -262,7 +262,8 @@
 	select SERIAL_CORE
 	help
 	  This selects the ARM(R) AMBA(R) PrimeCell PL010 UART.  If you have
-	  an Integrator/AP or Integrator/PP2 platform, say Y or M here.
+	  an Integrator/AP or Integrator/PP2 platform, or if you have a
+	  Cirrus Logic EP93xx CPU, say Y or M here.
 
 	  If unsure, say N.
 
@@ -686,6 +687,22 @@
 	depends on SERIAL_SH_SCI=y
 	select SERIAL_CORE_CONSOLE
 
+config SERIAL_PNX8XXX
+	bool "Enable PNX8XXX SoCs' UART Support"
+	depends on MIPS && SOC_PNX8550
+	select SERIAL_CORE
+	help
+	  If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
+	  and you want to use serial ports, say Y.  Otherwise, say N.
+
+config SERIAL_PNX8XXX_CONSOLE
+	bool "Enable PNX8XX0 serial console"
+	depends on SERIAL_PNX8XXX
+	select SERIAL_CORE_CONSOLE
+	help
+	  If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
+	  and you want to use serial console, say Y. Otherwise, say N.
+
 config SERIAL_CORE
 	tristate
 
@@ -916,6 +933,11 @@
 config HAS_TXX9_SERIAL
 	bool
 
+config SERIAL_TXX9_NR_UARTS
+	int "Maximum number of TMPTX39XX/49XX SIO ports"
+	depends on SERIAL_TXX9
+	default "6"
+
 config SERIAL_TXX9_CONSOLE
 	bool "TMPTX39XX/49XX SIO Console support"
 	depends on SERIAL_TXX9=y
@@ -994,4 +1016,14 @@
 	  If you have enabled the serial port on the Motorola IMX
 	  CPU you can make it the console by answering Y to this option.
 
+config SERIAL_OF_PLATFORM
+	tristate "Serial port on Open Firmware platform bus"
+	depends on PPC_OF
+	depends on SERIAL_8250
+	help
+	  If you have a PowerPC based system that has serial ports
+	  on a platform specific bus, you should enable this option.
+	  Currently, only 8250 compatible ports are supported, but
+	  others can easily be added.
+
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index df3632c..6b3560c 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -25,6 +25,7 @@
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
 obj-$(CONFIG_SERIAL_PXA) += pxa.o
+obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
 obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
@@ -58,3 +59,4 @@
 obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
 obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
 obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
+obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 881f886..935f48f 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -33,12 +33,13 @@
 #include <linux/sysrq.h>
 #include <linux/tty_flip.h>
 #include <linux/platform_device.h>
+#include <linux/atmel_pdc.h>
 
 #include <asm/io.h>
 
 #include <asm/mach/serial_at91.h>
 #include <asm/arch/board.h>
-#include <asm/arch/at91_pdc.h>
+
 #ifdef CONFIG_ARM
 #include <asm/arch/cpu.h>
 #include <asm/arch/gpio.h>
@@ -73,35 +74,35 @@
 
 #define ATMEL_ISR_PASS_LIMIT	256
 
-#define UART_PUT_CR(port,v)	writel(v, (port)->membase + ATMEL_US_CR)
-#define UART_GET_MR(port)	readl((port)->membase + ATMEL_US_MR)
-#define UART_PUT_MR(port,v)	writel(v, (port)->membase + ATMEL_US_MR)
-#define UART_PUT_IER(port,v)	writel(v, (port)->membase + ATMEL_US_IER)
-#define UART_PUT_IDR(port,v)	writel(v, (port)->membase + ATMEL_US_IDR)
-#define UART_GET_IMR(port)	readl((port)->membase + ATMEL_US_IMR)
-#define UART_GET_CSR(port)	readl((port)->membase + ATMEL_US_CSR)
-#define UART_GET_CHAR(port)	readl((port)->membase + ATMEL_US_RHR)
-#define UART_PUT_CHAR(port,v)	writel(v, (port)->membase + ATMEL_US_THR)
-#define UART_GET_BRGR(port)	readl((port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_BRGR(port,v)	writel(v, (port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_RTOR(port,v)	writel(v, (port)->membase + ATMEL_US_RTOR)
+#define UART_PUT_CR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_CR)
+#define UART_GET_MR(port)	__raw_readl((port)->membase + ATMEL_US_MR)
+#define UART_PUT_MR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_MR)
+#define UART_PUT_IER(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IER)
+#define UART_PUT_IDR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IDR)
+#define UART_GET_IMR(port)	__raw_readl((port)->membase + ATMEL_US_IMR)
+#define UART_GET_CSR(port)	__raw_readl((port)->membase + ATMEL_US_CSR)
+#define UART_GET_CHAR(port)	__raw_readl((port)->membase + ATMEL_US_RHR)
+#define UART_PUT_CHAR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_THR)
+#define UART_GET_BRGR(port)	__raw_readl((port)->membase + ATMEL_US_BRGR)
+#define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
+#define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
 
-// #define UART_GET_CR(port)	readl((port)->membase + ATMEL_US_CR)		// is write-only
+// #define UART_GET_CR(port)	__raw_readl((port)->membase + ATMEL_US_CR)		// is write-only
 
  /* PDC registers */
-#define UART_PUT_PTCR(port,v)	writel(v, (port)->membase + ATMEL_PDC_PTCR)
-#define UART_GET_PTSR(port)	readl((port)->membase + ATMEL_PDC_PTSR)
+#define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
+#define UART_GET_PTSR(port)	__raw_readl((port)->membase + ATMEL_PDC_PTSR)
 
-#define UART_PUT_RPR(port,v)	writel(v, (port)->membase + ATMEL_PDC_RPR)
-#define UART_GET_RPR(port)	readl((port)->membase + ATMEL_PDC_RPR)
-#define UART_PUT_RCR(port,v)	writel(v, (port)->membase + ATMEL_PDC_RCR)
-#define UART_PUT_RNPR(port,v)	writel(v, (port)->membase + ATMEL_PDC_RNPR)
-#define UART_PUT_RNCR(port,v)	writel(v, (port)->membase + ATMEL_PDC_RNCR)
+#define UART_PUT_RPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
+#define UART_GET_RPR(port)	__raw_readl((port)->membase + ATMEL_PDC_RPR)
+#define UART_PUT_RCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
+#define UART_PUT_RNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
+#define UART_PUT_RNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
 
-#define UART_PUT_TPR(port,v)	writel(v, (port)->membase + ATMEL_PDC_TPR)
-#define UART_PUT_TCR(port,v)	writel(v, (port)->membase + ATMEL_PDC_TCR)
-//#define UART_PUT_TNPR(port,v)	writel(v, (port)->membase + ATMEL_PDC_TNPR)
-//#define UART_PUT_TNCR(port,v)	writel(v, (port)->membase + ATMEL_PDC_TNCR)
+#define UART_PUT_TPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
+#define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
+//#define UART_PUT_TNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TNPR)
+//#define UART_PUT_TNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TNCR)
 
 static int (*atmel_open_hook)(struct uart_port *);
 static void (*atmel_close_hook)(struct uart_port *);
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index 787a8f1..fa45599 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -285,7 +285,7 @@
 int __init cpm_uart_init_portdesc(void)
 {
 #if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2)
-	u32 addr;
+	u16 *addr;
 #endif
 	pr_debug("CPM uart[-]:init portdesc\n");
 
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 42b050c..312bef6 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -3173,12 +3173,8 @@
 	if (!tty)
 		return;
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
+		tty_wakeup(tty);
 }
 
 static int
@@ -3798,11 +3794,7 @@
 	info->xmit.head = info->xmit.tail = 0;
 	restore_flags(flags);
 
-	wake_up_interruptible(&tty->write_wait);
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index 71e6a24..41431d0 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
@@ -1417,14 +1416,12 @@
 	struct list_head *tmp;
 
 	icom_adapter = (struct icom_adapter *)
-	    kmalloc(sizeof(struct icom_adapter), GFP_KERNEL);
+	    kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
 
 	if (!icom_adapter) {
 		return -ENOMEM;
 	}
 
-	memset(icom_adapter, 0, sizeof(struct icom_adapter));
-
 	list_for_each(tmp, &icom_adapter_head) {
 		cur_adapter_entry =
 		    list_entry(tmp, struct icom_adapter,
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index e216dcf..04cc88c 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -154,7 +154,7 @@
 {
 	struct circ_buf *xmit = &sport->port.info->xmit;
 
-	do {
+	while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)) {
 		/* send xmit->buf[xmit->tail]
 		 * out the port here */
 		URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail];
@@ -163,7 +163,7 @@
 		sport->port.icount.tx++;
 		if (uart_circ_empty(xmit))
 			break;
-	} while (!(UTS((u32)sport->port.membase) & UTS_TXFULL));
+	}
 
 	if (uart_circ_empty(xmit))
 		imx_stop_tx(&sport->port);
@@ -178,8 +178,7 @@
 
 	UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN;
 
-	if(UTS((u32)sport->port.membase) & UTS_TXEMPTY)
-		imx_transmit_buffer(sport);
+	imx_transmit_buffer(sport);
 }
 
 static irqreturn_t imx_rtsint(int irq, void *dev_id)
@@ -404,7 +403,8 @@
 	if (retval) goto error_out2;
 
 	retval = request_irq(sport->rtsirq, imx_rtsint,
-			     IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			     (sport->rtsirq < IMX_IRQS) ? 0 :
+			       IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
 			     DRIVER_NAME, sport);
 	if (retval) goto error_out3;
 
@@ -678,7 +678,7 @@
 		.mapbase	= IMX_UART1_BASE, /* FIXME */
 		.irq		= UART1_MINT_RX,
 		.uartclk	= 16000000,
-		.fifosize	= 8,
+		.fifosize	= 32,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.ops		= &imx_pops,
 		.line		= 0,
@@ -694,7 +694,7 @@
 		.mapbase	= IMX_UART2_BASE, /* FIXME */
 		.irq		= UART2_MINT_RX,
 		.uartclk	= 16000000,
-		.fifosize	= 8,
+		.fifosize	= 32,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.ops		= &imx_pops,
 		.line		= 1,
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c
index 9cc0be9..168073f 100644
--- a/drivers/serial/ioc3_serial.c
+++ b/drivers/serial/ioc3_serial.c
@@ -2019,13 +2019,12 @@
 
 	DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, is, idd));
 
-	card_ptr = kmalloc(sizeof(struct ioc3_card), GFP_KERNEL);
+	card_ptr = kzalloc(sizeof(struct ioc3_card), GFP_KERNEL);
 	if (!card_ptr) {
 		printk(KERN_WARNING "ioc3_attach_one"
 		       ": unable to get memory for the IOC3\n");
 		return -ENOMEM;
 	}
-	memset(card_ptr, 0, sizeof(struct ioc3_card));
 	idd->data[is->id] = card_ptr;
 	Submodule_slot = is->id;
 
@@ -2040,13 +2039,12 @@
 
 	/* Create port structures for each port */
 	for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) {
-		port = kmalloc(sizeof(struct ioc3_port), GFP_KERNEL);
+		port = kzalloc(sizeof(struct ioc3_port), GFP_KERNEL);
 		if (!port) {
 			printk(KERN_WARNING
 			       "IOC3 serial memory not available for port\n");
 			goto out4;
 		}
-		memset(port, 0, sizeof(struct ioc3_port));
 		spin_lock_init(&port->ip_lock);
 
 		/* we need to remember the previous ones, to point back to
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index c862f67..0c17938 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -1076,13 +1076,12 @@
 	/* Create port structures for each port */
 	for (port_number = 0; port_number < IOC4_NUM_SERIAL_PORTS;
 							port_number++) {
-		port = kmalloc(sizeof(struct ioc4_port), GFP_KERNEL);
+		port = kzalloc(sizeof(struct ioc4_port), GFP_KERNEL);
 		if (!port) {
 			printk(KERN_WARNING
 				"IOC4 serial memory not available for port\n");
 			return -ENOMEM;
 		}
-		memset(port, 0, sizeof(struct ioc4_port));
 		spin_lock_init(&port->ip_lock);
 
 		/* we need to remember the previous ones, to point back to
@@ -2685,7 +2684,7 @@
 		free_irq(control->ic_irq, soft);
 		if (soft->is_ioc4_serial_addr) {
 			iounmap(soft->is_ioc4_serial_addr);
-			release_region((unsigned long)
+			release_mem_region((unsigned long)
 			     soft->is_ioc4_serial_addr,
 				sizeof(struct ioc4_serial));
 		}
@@ -2790,7 +2789,7 @@
 	/* request serial registers */
 	tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET;
 
-	if (!request_region(tmp_addr1, sizeof(struct ioc4_serial),
+	if (!request_mem_region(tmp_addr1, sizeof(struct ioc4_serial),
 					"sioc4_uart")) {
 		printk(KERN_WARNING
 			"ioc4 (%p): unable to get request region for "
@@ -2811,7 +2810,7 @@
 				(void *)serial));
 
 	/* Get memory for the new card */
-	control = kmalloc(sizeof(struct ioc4_control), GFP_KERNEL);
+	control = kzalloc(sizeof(struct ioc4_control), GFP_KERNEL);
 
 	if (!control) {
 		printk(KERN_WARNING "ioc4_attach_one"
@@ -2819,11 +2818,10 @@
 		ret = -ENOMEM;
 		goto out2;
 	}
-	memset(control, 0, sizeof(struct ioc4_control));
 	idd->idd_serial_data = control;
 
 	/* Allocate the soft structure */
-	soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
+	soft = kzalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
 	if (!soft) {
 		printk(KERN_WARNING
 		       "ioc4 (%p): unable to get memory for the soft struct\n",
@@ -2831,7 +2829,6 @@
 		ret = -ENOMEM;
 		goto out3;
 	}
-	memset(soft, 0, sizeof(struct ioc4_soft));
 
 	spin_lock_init(&soft->is_ir_lock);
 	soft->is_ioc4_misc_addr = idd->idd_misc_regs;
@@ -2889,7 +2886,7 @@
 out2:
 	if (serial)
 		iounmap(serial);
-	release_region(tmp_addr1, sizeof(struct ioc4_serial));
+	release_mem_region(tmp_addr1, sizeof(struct ioc4_serial));
 out1:
 
 	return ret;
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index 0746c94..c3abfb3 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -14,7 +14,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/tty.h>
@@ -922,13 +921,7 @@
 
 static void * __init alloc_one_table(unsigned long size)
 {
-	void *ret;
-
-	ret = kmalloc(size, GFP_KERNEL);
-	if (ret != NULL)
-		memset(ret, 0, size);
-
-	return ret;
+	return kzalloc(size, GFP_KERNEL);
 }
 
 static void __init ip22zilog_alloc_tables(void)
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index 244f63b..81792e6 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -71,14 +71,13 @@
 		goto out_disable_device;
 	}
 
-	brd = kmalloc(sizeof(struct jsm_board), GFP_KERNEL);
+	brd = kzalloc(sizeof(struct jsm_board), GFP_KERNEL);
 	if (!brd) {
 		dev_err(&pdev->dev,
 			"memory allocation for board structure failed\n");
 		rc = -ENOMEM;
 		goto out_release_regions;
 	}
-	memset(brd, 0, sizeof(struct jsm_board));
 
 	/* store the info for the board we've found */
 	brd->boardnum = adapter_count++;
@@ -152,7 +151,7 @@
 	 * Okay to malloc with GFP_KERNEL, we are not at interrupt
 	 * context, and there are no locks held.
 	 */
-	brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL);
+	brd->flipbuf = kzalloc(MYFLIPLEN, GFP_KERNEL);
 	if (!brd->flipbuf) {
 		/* XXX: leaking all resources from jsm_tty_init and
 		 	jsm_uart_port_init here! */
@@ -160,7 +159,6 @@
 		retval = -ENOMEM;
 		goto out_free_irq;
 	}
-	memset(brd->flipbuf, 0, MYFLIPLEN);
 
 	pci_set_drvdata(pdev, brd);
 
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 7cf1c60..be22bbd 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -194,31 +194,28 @@
 	/* Drop locks, as malloc with GFP_KERNEL can sleep */
 
 	if (!channel->ch_rqueue) {
-		channel->ch_rqueue = (u8 *) kmalloc(RQUEUESIZE, GFP_KERNEL);
+		channel->ch_rqueue = kzalloc(RQUEUESIZE, GFP_KERNEL);
 		if (!channel->ch_rqueue) {
 			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
 				"unable to allocate read queue buf");
 			return -ENOMEM;
 		}
-		memset(channel->ch_rqueue, 0, RQUEUESIZE);
 	}
 	if (!channel->ch_equeue) {
-		channel->ch_equeue = (u8 *) kmalloc(EQUEUESIZE, GFP_KERNEL);
+		channel->ch_equeue = kzalloc(EQUEUESIZE, GFP_KERNEL);
 		if (!channel->ch_equeue) {
 			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
 				"unable to allocate error queue buf");
 			return -ENOMEM;
 		}
-		memset(channel->ch_equeue, 0, EQUEUESIZE);
 	}
 	if (!channel->ch_wqueue) {
-		channel->ch_wqueue = (u8 *) kmalloc(WQUEUESIZE, GFP_KERNEL);
+		channel->ch_wqueue = kzalloc(WQUEUESIZE, GFP_KERNEL);
 		if (!channel->ch_wqueue) {
 			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
 				"unable to allocate write queue buf");
 			return -ENOMEM;
 		}
-		memset(channel->ch_wqueue, 0, WQUEUESIZE);
 	}
 
 	channel->ch_flags &= ~(CH_OPENING);
@@ -392,13 +389,12 @@
 			 * Okay to malloc with GFP_KERNEL, we are not at
 			 * interrupt context, and there are no locks held.
 			 */
-			brd->channels[i] = kmalloc(sizeof(struct jsm_channel), GFP_KERNEL);
+			brd->channels[i] = kzalloc(sizeof(struct jsm_channel), GFP_KERNEL);
 			if (!brd->channels[i]) {
 				jsm_printk(CORE, ERR, &brd->pci_dev,
 					"%s:%d Unable to allocate memory for channel struct\n",
 							 __FILE__, __LINE__);
 			}
-			memset(brd->channels[i], 0, sizeof(struct jsm_channel));
 		}
 	}
 
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 3c4b6c2..8d24cd5 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -127,8 +127,7 @@
 
 #if defined(CONFIG_PPC_MERGE)
 static struct of_device_id mpc52xx_uart_of_match[] = {
-	{ .type = "serial", .compatible = "mpc52xx-psc-uart", },
-	{ .type = "serial", .compatible = "mpc5200-psc", }, /* Efika only! */
+	{ .type = "serial", .compatible = "mpc5200-psc-uart", },
 	{},
 };
 #endif
@@ -996,8 +995,10 @@
 	struct uart_port *port = dev_get_drvdata(&op->dev);
 	dev_set_drvdata(&op->dev, NULL);
 
-	if (port)
+	if (port) {
 		uart_remove_one_port(&mpc52xx_uart_driver, port);
+		irq_dispose_mapping(port->irq);
+	}
 
 	return 0;
 }
@@ -1068,7 +1069,7 @@
 			continue;
 
 		/* Is a particular device number requested? */
-		devno = get_property(np, "device_no", NULL);
+		devno = get_property(np, "port-number", NULL);
 		mpc52xx_uart_of_assign(of_node_get(np), devno ? *devno : -1);
 	}
 
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
new file mode 100644
index 0000000..09b0b73
--- /dev/null
+++ b/drivers/serial/of_serial.c
@@ -0,0 +1,143 @@
+/*
+ *  Serial Port driver for Open Firmware platform devices
+ *
+ *    Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#include <asm/of_platform.h>
+#include <asm/prom.h>
+
+/*
+ * Fill a struct uart_port for a given device node
+ */
+static int __devinit of_platform_serial_setup(struct of_device *ofdev,
+					int type, struct uart_port *port)
+{
+	struct resource resource;
+	struct device_node *np = ofdev->node;
+	const unsigned int *clk, *spd;
+	int ret;
+
+	memset(port, 0, sizeof *port);
+	spd = get_property(np, "current-speed", NULL);
+	clk = get_property(np, "clock-frequency", NULL);
+	if (!clk) {
+		dev_warn(&ofdev->dev, "no clock-frequency property set\n");
+		return -ENODEV;
+	}
+
+	ret = of_address_to_resource(np, 0, &resource);
+	if (ret) {
+		dev_warn(&ofdev->dev, "invalid address\n");
+		return ret;
+	}
+
+	spin_lock_init(&port->lock);
+	port->mapbase = resource.start;
+	port->irq = irq_of_parse_and_map(np, 0);
+	port->iotype = UPIO_MEM;
+	port->type = type;
+	port->uartclk = *clk;
+	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP;
+	port->dev = &ofdev->dev;
+	port->custom_divisor = *clk / (16 * (*spd));
+
+	return 0;
+}
+
+/*
+ * Try to register a serial port
+ */
+static int __devinit of_platform_serial_probe(struct of_device *ofdev,
+						const struct of_device_id *id)
+{
+	struct uart_port port;
+	int port_type;
+	int ret;
+
+	if (of_find_property(ofdev->node, "used-by-rtas", NULL))
+		return -EBUSY;
+
+	port_type = (unsigned long)id->data;
+	ret = of_platform_serial_setup(ofdev, port_type, &port);
+	if (ret)
+		goto out;
+
+	switch (port_type) {
+	case PORT_UNKNOWN:
+		dev_info(&ofdev->dev, "Unknown serial port found, "
+			"attempting to use 8250 driver\n");
+		/* fallthrough */
+	case PORT_8250 ... PORT_MAX_8250:
+		ret = serial8250_register_port(&port);
+		break;
+	default:
+		/* need to add code for these */
+		ret = -ENODEV;
+		break;
+	}
+	if (ret < 0)
+		goto out;
+
+	ofdev->dev.driver_data = (void *)(unsigned long)ret;
+	return 0;
+out:
+	irq_dispose_mapping(port.irq);
+	return ret;
+}
+
+/*
+ * Release a line
+ */
+static int of_platform_serial_remove(struct of_device *ofdev)
+{
+	int line = (unsigned long)ofdev->dev.driver_data;
+	serial8250_unregister_port(line);
+	return 0;
+}
+
+/*
+ * A few common types, add more as needed.
+ */
+static struct of_device_id __devinitdata of_platform_serial_table[] = {
+	{ .type = "serial", .compatible = "ns8250",   .data = (void *)PORT_8250, },
+	{ .type = "serial", .compatible = "ns16450",  .data = (void *)PORT_16450, },
+	{ .type = "serial", .compatible = "ns16550",  .data = (void *)PORT_16550, },
+	{ .type = "serial", .compatible = "ns16750",  .data = (void *)PORT_16750, },
+	{ .type = "serial",			      .data = (void *)PORT_UNKNOWN, },
+	{ /* end of list */ },
+};
+
+static struct of_platform_driver __devinitdata of_platform_serial_driver = {
+	.owner = THIS_MODULE,
+	.name = "of_serial",
+	.probe = of_platform_serial_probe,
+	.remove = of_platform_serial_remove,
+	.match_table = of_platform_serial_table,
+};
+
+static int __init of_platform_serial_init(void)
+{
+	return of_register_platform_driver(&of_platform_serial_driver);
+}
+module_init(of_platform_serial_init);
+
+static void __exit of_platform_serial_exit(void)
+{
+	return of_unregister_platform_driver(&of_platform_serial_driver);
+};
+module_exit(of_platform_serial_exit);
+
+MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Serial Port driver for Open Firmware platform devices");
diff --git a/drivers/serial/pnx8xxx_uart.c b/drivers/serial/pnx8xxx_uart.c
new file mode 100644
index 0000000..8d01c59
--- /dev/null
+++ b/drivers/serial/pnx8xxx_uart.c
@@ -0,0 +1,852 @@
+/*
+ * UART driver for PNX8XXX SoCs
+ *
+ * Author: Per Hallsmark per.hallsmark@mvista.com
+ * Ported to 2.6 kernel by EmbeddedAlley
+ * Reworked by Vitaly Wool <vitalywool@gmail.com>
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * 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.
+ *
+ */
+
+#if defined(CONFIG_SERIAL_PNX8XXX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/serial_pnx8xxx.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+/* We'll be using StrongARM sa1100 serial port major/minor */
+#define SERIAL_PNX8XXX_MAJOR	204
+#define MINOR_START		5
+
+#define NR_PORTS		2
+
+#define PNX8XXX_ISR_PASS_LIMIT	256
+
+/*
+ * Convert from ignore_status_mask or read_status_mask to FIFO
+ * and interrupt status bits
+ */
+#define SM_TO_FIFO(x)	((x) >> 10)
+#define SM_TO_ISTAT(x)	((x) & 0x000001ff)
+#define FIFO_TO_SM(x)	((x) << 10)
+#define ISTAT_TO_SM(x)	((x) & 0x000001ff)
+
+/*
+ * This is the size of our serial port register set.
+ */
+#define UART_PORT_SIZE	0x1000
+
+/*
+ * This determines how often we check the modem status signals
+ * for any change.  They generally aren't connected to an IRQ
+ * so we have to poll them.  We also check immediately before
+ * filling the TX fifo incase CTS has been dropped.
+ */
+#define MCTRL_TIMEOUT	(250*HZ/1000)
+
+extern struct pnx8xxx_port pnx8xxx_ports[];
+
+static inline int serial_in(struct pnx8xxx_port *sport, int offset)
+{
+	return (__raw_readl(sport->port.membase + offset));
+}
+
+static inline void serial_out(struct pnx8xxx_port *sport, int offset, int value)
+{
+	__raw_writel(value, sport->port.membase + offset);
+}
+
+/*
+ * Handle any change of modem status signal since we were last called.
+ */
+static void pnx8xxx_mctrl_check(struct pnx8xxx_port *sport)
+{
+	unsigned int status, changed;
+
+	status = sport->port.ops->get_mctrl(&sport->port);
+	changed = status ^ sport->old_status;
+
+	if (changed == 0)
+		return;
+
+	sport->old_status = status;
+
+	if (changed & TIOCM_RI)
+		sport->port.icount.rng++;
+	if (changed & TIOCM_DSR)
+		sport->port.icount.dsr++;
+	if (changed & TIOCM_CAR)
+		uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
+	if (changed & TIOCM_CTS)
+		uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
+
+	wake_up_interruptible(&sport->port.info->delta_msr_wait);
+}
+
+/*
+ * This is our per-port timeout handler, for checking the
+ * modem status signals.
+ */
+static void pnx8xxx_timeout(unsigned long data)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)data;
+	unsigned long flags;
+
+	if (sport->port.info) {
+		spin_lock_irqsave(&sport->port.lock, flags);
+		pnx8xxx_mctrl_check(sport);
+		spin_unlock_irqrestore(&sport->port.lock, flags);
+
+		mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
+	}
+}
+
+/*
+ * interrupts disabled on entry
+ */
+static void pnx8xxx_stop_tx(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	u32 ien;
+
+	/* Disable TX intr */
+	ien = serial_in(sport, PNX8XXX_IEN);
+	serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLTX);
+
+	/* Clear all pending TX intr */
+	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX);
+}
+
+/*
+ * interrupts may not be disabled on entry
+ */
+static void pnx8xxx_start_tx(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	u32 ien;
+
+	/* Clear all pending TX intr */
+	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX);
+
+	/* Enable TX intr */
+	ien = serial_in(sport, PNX8XXX_IEN);
+	serial_out(sport, PNX8XXX_IEN, ien | PNX8XXX_UART_INT_ALLTX);
+}
+
+/*
+ * Interrupts enabled
+ */
+static void pnx8xxx_stop_rx(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	u32 ien;
+
+	/* Disable RX intr */
+	ien = serial_in(sport, PNX8XXX_IEN);
+	serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLRX);
+
+	/* Clear all pending RX intr */
+	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX);
+}
+
+/*
+ * Set the modem control timer to fire immediately.
+ */
+static void pnx8xxx_enable_ms(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+
+	mod_timer(&sport->timer, jiffies);
+}
+
+static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
+{
+	struct tty_struct *tty = sport->port.info->tty;
+	unsigned int status, ch, flg;
+
+	status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
+		 ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
+	while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) {
+		ch = serial_in(sport, PNX8XXX_FIFO);
+
+		sport->port.icount.rx++;
+
+		flg = TTY_NORMAL;
+
+		/*
+		 * note that the error handling code is
+		 * out of the main execution path
+		 */
+		if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE |
+					PNX8XXX_UART_FIFO_RXPAR) |
+			      ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) {
+			if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
+				sport->port.icount.parity++;
+			else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
+				sport->port.icount.frame++;
+			if (status & ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))
+				sport->port.icount.overrun++;
+
+			status &= sport->port.read_status_mask;
+
+			if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
+				flg = TTY_PARITY;
+			else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
+				flg = TTY_FRAME;
+
+#ifdef SUPPORT_SYSRQ
+			sport->port.sysrq = 0;
+#endif
+		}
+
+		if (uart_handle_sysrq_char(&sport->port, ch))
+			goto ignore_char;
+
+		uart_insert_char(&sport->port, status,
+				ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN), ch, flg);
+
+	ignore_char:
+		serial_out(sport, PNX8XXX_LCR, serial_in(sport, PNX8XXX_LCR) |
+				PNX8XXX_UART_LCR_RX_NEXT);
+		status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
+			 ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
+	}
+	tty_flip_buffer_push(tty);
+}
+
+static void pnx8xxx_tx_chars(struct pnx8xxx_port *sport)
+{
+	struct circ_buf *xmit = &sport->port.info->xmit;
+
+	if (sport->port.x_char) {
+		serial_out(sport, PNX8XXX_FIFO, sport->port.x_char);
+		sport->port.icount.tx++;
+		sport->port.x_char = 0;
+		return;
+	}
+
+	/*
+	 * Check the modem control lines before
+	 * transmitting anything.
+	 */
+	pnx8xxx_mctrl_check(sport);
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
+		pnx8xxx_stop_tx(&sport->port);
+		return;
+	}
+
+	/*
+	 * TX while bytes available
+	 */
+	while (((serial_in(sport, PNX8XXX_FIFO) &
+					PNX8XXX_UART_FIFO_TXFIFO) >> 16) < 16) {
+		serial_out(sport, PNX8XXX_FIFO, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		sport->port.icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&sport->port);
+
+	if (uart_circ_empty(xmit))
+		pnx8xxx_stop_tx(&sport->port);
+}
+
+static irqreturn_t pnx8xxx_int(int irq, void *dev_id)
+{
+	struct pnx8xxx_port *sport = dev_id;
+	unsigned int status;
+
+	spin_lock(&sport->port.lock);
+	/* Get the interrupts */
+	status  = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN);
+
+	/* Break signal received */
+	if (status & PNX8XXX_UART_INT_BREAK) {
+		sport->port.icount.brk++;
+		uart_handle_break(&sport->port);
+	}
+
+	/* Byte received */
+	if (status & PNX8XXX_UART_INT_RX)
+		pnx8xxx_rx_chars(sport);
+
+	/* TX holding register empty - transmit a byte */
+	if (status & PNX8XXX_UART_INT_TX)
+		pnx8xxx_tx_chars(sport);
+
+	/* Clear the ISTAT register */
+	serial_out(sport, PNX8XXX_ICLR, status);
+
+	spin_unlock(&sport->port.lock);
+	return IRQ_HANDLED;
+}
+
+/*
+ * Return TIOCSER_TEMT when transmitter is not busy.
+ */
+static unsigned int pnx8xxx_tx_empty(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+
+	return serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA ? 0 : TIOCSER_TEMT;
+}
+
+static unsigned int pnx8xxx_get_mctrl(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	unsigned int mctrl = TIOCM_DSR;
+	unsigned int msr;
+
+	/* REVISIT */
+
+	msr = serial_in(sport, PNX8XXX_MCR);
+
+	mctrl |= msr & PNX8XXX_UART_MCR_CTS ? TIOCM_CTS : 0;
+	mctrl |= msr & PNX8XXX_UART_MCR_DCD ? TIOCM_CAR : 0;
+
+	return mctrl;
+}
+
+static void pnx8xxx_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+#if	0	/* FIXME */
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	unsigned int msr;
+#endif
+}
+
+/*
+ * Interrupts always disabled.
+ */
+static void pnx8xxx_break_ctl(struct uart_port *port, int break_state)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	unsigned long flags;
+	unsigned int lcr;
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+	lcr = serial_in(sport, PNX8XXX_LCR);
+	if (break_state == -1)
+		lcr |= PNX8XXX_UART_LCR_TXBREAK;
+	else
+		lcr &= ~PNX8XXX_UART_LCR_TXBREAK;
+	serial_out(sport, PNX8XXX_LCR, lcr);
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static int pnx8xxx_startup(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	int retval;
+
+	/*
+	 * Allocate the IRQ
+	 */
+	retval = request_irq(sport->port.irq, pnx8xxx_int, 0,
+			     "pnx8xxx-uart", sport);
+	if (retval)
+		return retval;
+
+	/*
+	 * Finally, clear and enable interrupts
+	 */
+
+	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX |
+			     PNX8XXX_UART_INT_ALLTX);
+
+	serial_out(sport, PNX8XXX_IEN, serial_in(sport, PNX8XXX_IEN) |
+			    PNX8XXX_UART_INT_ALLRX |
+			    PNX8XXX_UART_INT_ALLTX);
+
+	/*
+	 * Enable modem status interrupts
+	 */
+	spin_lock_irq(&sport->port.lock);
+	pnx8xxx_enable_ms(&sport->port);
+	spin_unlock_irq(&sport->port.lock);
+
+	return 0;
+}
+
+static void pnx8xxx_shutdown(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	int lcr;
+
+	/*
+	 * Stop our timer.
+	 */
+	del_timer_sync(&sport->timer);
+
+	/*
+	 * Disable all interrupts
+	 */
+	serial_out(sport, PNX8XXX_IEN, 0);
+
+	/*
+	 * Reset the Tx and Rx FIFOS, disable the break condition
+	 */
+	lcr = serial_in(sport, PNX8XXX_LCR);
+	lcr &= ~PNX8XXX_UART_LCR_TXBREAK;
+	lcr |= PNX8XXX_UART_LCR_TX_RST | PNX8XXX_UART_LCR_RX_RST;
+	serial_out(sport, PNX8XXX_LCR, lcr);
+
+	/*
+	 * Clear all interrupts
+	 */
+	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX |
+			     PNX8XXX_UART_INT_ALLTX);
+
+	/*
+	 * Free the interrupt
+	 */
+	free_irq(sport->port.irq, sport);
+}
+
+static void
+pnx8xxx_set_termios(struct uart_port *port, struct ktermios *termios,
+		   struct ktermios *old)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	unsigned long flags;
+	unsigned int lcr_fcr, old_ien, baud, quot;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+
+	/*
+	 * We only support CS7 and CS8.
+	 */
+	while ((termios->c_cflag & CSIZE) != CS7 &&
+	       (termios->c_cflag & CSIZE) != CS8) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	if ((termios->c_cflag & CSIZE) == CS8)
+		lcr_fcr = PNX8XXX_UART_LCR_8BIT;
+	else
+		lcr_fcr = 0;
+
+	if (termios->c_cflag & CSTOPB)
+		lcr_fcr |= PNX8XXX_UART_LCR_2STOPB;
+	if (termios->c_cflag & PARENB) {
+		lcr_fcr |= PNX8XXX_UART_LCR_PAREN;
+		if (!(termios->c_cflag & PARODD))
+			lcr_fcr |= PNX8XXX_UART_LCR_PAREVN;
+	}
+
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+	quot = uart_get_divisor(port, baud);
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	sport->port.read_status_mask = ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN) |
+				ISTAT_TO_SM(PNX8XXX_UART_INT_EMPTY) |
+				ISTAT_TO_SM(PNX8XXX_UART_INT_RX);
+	if (termios->c_iflag & INPCK)
+		sport->port.read_status_mask |=
+			FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
+			FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR);
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		sport->port.read_status_mask |=
+			ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK);
+
+	/*
+	 * Characters to ignore
+	 */
+	sport->port.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		sport->port.ignore_status_mask |=
+			FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
+			FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR);
+	if (termios->c_iflag & IGNBRK) {
+		sport->port.ignore_status_mask |=
+			ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK);
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			sport->port.ignore_status_mask |=
+				ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN);
+	}
+
+	/*
+	 * ignore all characters if CREAD is not set
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		sport->port.ignore_status_mask |=
+			ISTAT_TO_SM(PNX8XXX_UART_INT_RX);
+
+	del_timer_sync(&sport->timer);
+
+	/*
+	 * Update the per-port timeout.
+	 */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	/*
+	 * disable interrupts and drain transmitter
+	 */
+	old_ien = serial_in(sport, PNX8XXX_IEN);
+	serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX |
+					PNX8XXX_UART_INT_ALLRX));
+
+	while (serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA)
+		barrier();
+
+	/* then, disable everything */
+	serial_out(sport, PNX8XXX_IEN, 0);
+
+	/* Reset the Rx and Tx FIFOs too */
+	lcr_fcr |= PNX8XXX_UART_LCR_TX_RST;
+	lcr_fcr |= PNX8XXX_UART_LCR_RX_RST;
+
+	/* set the parity, stop bits and data size */
+	serial_out(sport, PNX8XXX_LCR, lcr_fcr);
+
+	/* set the baud rate */
+	quot -= 1;
+	serial_out(sport, PNX8XXX_BAUD, quot);
+
+	serial_out(sport, PNX8XXX_ICLR, -1);
+
+	serial_out(sport, PNX8XXX_IEN, old_ien);
+
+	if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
+		pnx8xxx_enable_ms(&sport->port);
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static const char *pnx8xxx_type(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+
+	return sport->port.type == PORT_PNX8XXX ? "PNX8XXX" : NULL;
+}
+
+/*
+ * Release the memory region(s) being used by 'port'.
+ */
+static void pnx8xxx_release_port(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+
+	release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
+}
+
+/*
+ * Request the memory region(s) being used by 'port'.
+ */
+static int pnx8xxx_request_port(struct uart_port *port)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
+			"pnx8xxx-uart") != NULL ? 0 : -EBUSY;
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void pnx8xxx_config_port(struct uart_port *port, int flags)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+
+	if (flags & UART_CONFIG_TYPE &&
+	    pnx8xxx_request_port(&sport->port) == 0)
+		sport->port.type = PORT_PNX8XXX;
+}
+
+/*
+ * Verify the new serial_struct (for TIOCSSERIAL).
+ * The only change we allow are to the flags and type, and
+ * even then only between PORT_PNX8XXX and PORT_UNKNOWN
+ */
+static int
+pnx8xxx_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	int ret = 0;
+
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_PNX8XXX)
+		ret = -EINVAL;
+	if (sport->port.irq != ser->irq)
+		ret = -EINVAL;
+	if (ser->io_type != SERIAL_IO_MEM)
+		ret = -EINVAL;
+	if (sport->port.uartclk / 16 != ser->baud_base)
+		ret = -EINVAL;
+	if ((void *)sport->port.mapbase != ser->iomem_base)
+		ret = -EINVAL;
+	if (sport->port.iobase != ser->port)
+		ret = -EINVAL;
+	if (ser->hub6 != 0)
+		ret = -EINVAL;
+	return ret;
+}
+
+static struct uart_ops pnx8xxx_pops = {
+	.tx_empty	= pnx8xxx_tx_empty,
+	.set_mctrl	= pnx8xxx_set_mctrl,
+	.get_mctrl	= pnx8xxx_get_mctrl,
+	.stop_tx	= pnx8xxx_stop_tx,
+	.start_tx	= pnx8xxx_start_tx,
+	.stop_rx	= pnx8xxx_stop_rx,
+	.enable_ms	= pnx8xxx_enable_ms,
+	.break_ctl	= pnx8xxx_break_ctl,
+	.startup	= pnx8xxx_startup,
+	.shutdown	= pnx8xxx_shutdown,
+	.set_termios	= pnx8xxx_set_termios,
+	.type		= pnx8xxx_type,
+	.release_port	= pnx8xxx_release_port,
+	.request_port	= pnx8xxx_request_port,
+	.config_port	= pnx8xxx_config_port,
+	.verify_port	= pnx8xxx_verify_port,
+};
+
+
+/*
+ * Setup the PNX8XXX serial ports.
+ *
+ * Note also that we support "console=ttySx" where "x" is either 0 or 1.
+ */
+static void __init pnx8xxx_init_ports(void)
+{
+	static int first = 1;
+	int i;
+
+	if (!first)
+		return;
+	first = 0;
+
+	for (i = 0; i < NR_PORTS; i++) {
+		init_timer(&pnx8xxx_ports[i].timer);
+		pnx8xxx_ports[i].timer.function = pnx8xxx_timeout;
+		pnx8xxx_ports[i].timer.data     = (unsigned long)&pnx8xxx_ports[i];
+		pnx8xxx_ports[i].port.ops = &pnx8xxx_pops;
+	}
+}
+
+#ifdef CONFIG_SERIAL_PNX8XXX_CONSOLE
+
+static void pnx8xxx_console_putchar(struct uart_port *port, int ch)
+{
+	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
+	int status;
+
+	do {
+		/* Wait for UART_TX register to empty */
+		status = serial_in(sport, PNX8XXX_FIFO);
+	} while (status & PNX8XXX_UART_FIFO_TXFIFO);
+	serial_out(sport, PNX8XXX_FIFO, ch);
+}
+
+/*
+ * Interrupts are disabled on entering
+ */static void
+pnx8xxx_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct pnx8xxx_port *sport = &pnx8xxx_ports[co->index];
+	unsigned int old_ien, status;
+
+	/*
+	 *	First, save IEN and then disable interrupts
+	 */
+	old_ien = serial_in(sport, PNX8XXX_IEN);
+	serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX |
+					PNX8XXX_UART_INT_ALLRX));
+
+	uart_console_write(&sport->port, s, count, pnx8xxx_console_putchar);
+
+	/*
+	 *	Finally, wait for transmitter to become empty
+	 *	and restore IEN
+	 */
+	do {
+		/* Wait for UART_TX register to empty */
+		status = serial_in(sport, PNX8XXX_FIFO);
+	} while (status & PNX8XXX_UART_FIFO_TXFIFO);
+
+	/* Clear TX and EMPTY interrupt */
+	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_TX |
+			     PNX8XXX_UART_INT_EMPTY);
+
+	serial_out(sport, PNX8XXX_IEN, old_ien);
+}
+
+static int __init
+pnx8xxx_console_setup(struct console *co, char *options)
+{
+	struct pnx8xxx_port *sport;
+	int baud = 38400;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	/*
+	 * Check whether an invalid uart number has been specified, and
+	 * if so, search for the first available port that does have
+	 * console support.
+	 */
+	if (co->index == -1 || co->index >= NR_PORTS)
+		co->index = 0;
+	sport = &pnx8xxx_ports[co->index];
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(&sport->port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver pnx8xxx_reg;
+static struct console pnx8xxx_console = {
+	.name		= "ttyS",
+	.write		= pnx8xxx_console_write,
+	.device		= uart_console_device,
+	.setup		= pnx8xxx_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &pnx8xxx_reg,
+};
+
+static int __init pnx8xxx_rs_console_init(void)
+{
+	pnx8xxx_init_ports();
+	register_console(&pnx8xxx_console);
+	return 0;
+}
+console_initcall(pnx8xxx_rs_console_init);
+
+#define PNX8XXX_CONSOLE	&pnx8xxx_console
+#else
+#define PNX8XXX_CONSOLE	NULL
+#endif
+
+static struct uart_driver pnx8xxx_reg = {
+	.owner			= THIS_MODULE,
+	.driver_name		= "ttyS",
+	.dev_name		= "ttyS",
+	.major			= SERIAL_PNX8XXX_MAJOR,
+	.minor			= MINOR_START,
+	.nr			= NR_PORTS,
+	.cons			= PNX8XXX_CONSOLE,
+};
+
+static int pnx8xxx_serial_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
+
+	return uart_suspend_port(&pnx8xxx_reg, &sport->port);
+}
+
+static int pnx8xxx_serial_resume(struct platform_device *pdev)
+{
+	struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
+
+	return uart_resume_port(&pnx8xxx_reg, &sport->port);
+}
+
+static int pnx8xxx_serial_probe(struct platform_device *pdev)
+{
+	struct resource *res = pdev->resource;
+	int i;
+
+	for (i = 0; i < pdev->num_resources; i++, res++) {
+		if (!(res->flags & IORESOURCE_MEM))
+			continue;
+
+		for (i = 0; i < NR_PORTS; i++) {
+			if (pnx8xxx_ports[i].port.mapbase != res->start)
+				continue;
+
+			pnx8xxx_ports[i].port.dev = &pdev->dev;
+			uart_add_one_port(&pnx8xxx_reg, &pnx8xxx_ports[i].port);
+			platform_set_drvdata(pdev, &pnx8xxx_ports[i]);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int pnx8xxx_serial_remove(struct platform_device *pdev)
+{
+	struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (sport)
+		uart_remove_one_port(&pnx8xxx_reg, &sport->port);
+
+	return 0;
+}
+
+static struct platform_driver pnx8xxx_serial_driver = {
+	.driver		= {
+		.name	= "pnx8xxx-uart",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pnx8xxx_serial_probe,
+	.remove		= pnx8xxx_serial_remove,
+	.suspend	= pnx8xxx_serial_suspend,
+	.resume		= pnx8xxx_serial_resume,
+};
+
+static int __init pnx8xxx_serial_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "Serial: PNX8XXX driver $Revision: 1.2 $\n");
+
+	pnx8xxx_init_ports();
+
+	ret = uart_register_driver(&pnx8xxx_reg);
+	if (ret == 0) {
+		ret = platform_driver_register(&pnx8xxx_serial_driver);
+		if (ret)
+			uart_unregister_driver(&pnx8xxx_reg);
+	}
+	return ret;
+}
+
+static void __exit pnx8xxx_serial_exit(void)
+{
+	platform_driver_unregister(&pnx8xxx_serial_driver);
+	uart_unregister_driver(&pnx8xxx_reg);
+}
+
+module_init(pnx8xxx_serial_init);
+module_exit(pnx8xxx_serial_exit);
+
+MODULE_AUTHOR("Embedded Alley Solutions, Inc.");
+MODULE_DESCRIPTION("PNX8XXX SoCs serial port driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_PNX8XXX_MAJOR);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index f84982e..0422c0f 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1523,9 +1523,8 @@
 	}
 
 	if (!state->info) {
-		state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
+		state->info = kzalloc(sizeof(struct uart_info), GFP_KERNEL);
 		if (state->info) {
-			memset(state->info, 0, sizeof(struct uart_info));
 			init_waitqueue_head(&state->info->open_wait);
 			init_waitqueue_head(&state->info->delta_msr_wait);
 
@@ -1660,6 +1659,7 @@
 static int uart_line_info(char *buf, struct uart_driver *drv, int i)
 {
 	struct uart_state *state = drv->state + i;
+	int pm_state;
 	struct uart_port *port = state->port;
 	char stat_buf[32];
 	unsigned int status;
@@ -1682,9 +1682,16 @@
 
 	if(capable(CAP_SYS_ADMIN))
 	{
+		mutex_lock(&state->mutex);
+		pm_state = state->pm_state;
+		if (pm_state)
+			uart_change_pm(state, 0);
 		spin_lock_irq(&port->lock);
 		status = port->ops->get_mctrl(port);
 		spin_unlock_irq(&port->lock);
+		if (pm_state)
+			uart_change_pm(state, pm_state);
+		mutex_unlock(&state->mutex);
 
 		ret += sprintf(buf + ret, " tx:%d rx:%d",
 				port->icount.tx, port->icount.rx);
@@ -2100,6 +2107,9 @@
 
 		uart_report_port(drv, port);
 
+		/* Power up port for set_mctrl() */
+		uart_change_pm(state, 0);
+
 		/*
 		 * Ensure that the modem control lines are de-activated.
 		 * We probably don't need a spinlock around this, but
@@ -2167,13 +2177,11 @@
 	 * Maybe we should be using a slab cache for this, especially if
 	 * we have a large number of ports to handle.
 	 */
-	drv->state = kmalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
+	drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
 	retval = -ENOMEM;
 	if (!drv->state)
 		goto out;
 
-	memset(drv->state, 0, sizeof(struct uart_state) * drv->nr);
-
 	normal  = alloc_tty_driver(drv->nr);
 	if (!normal)
 		goto out;
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 431433f..6b76bab 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -35,7 +35,6 @@
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -249,6 +248,10 @@
 		.multi	= 2,
 	}, {
 		.manfid	= MANFID_QUATECH,
+		.prodid	= PRODID_QUATECH_DUAL_RS232_G,
+		.multi	= 2,
+	}, {
+		.manfid	= MANFID_QUATECH,
 		.prodid	= PRODID_QUATECH_QUAD_RS232,
 		.multi	= 4,
 	}, {
@@ -334,10 +337,9 @@
 	DEBUG(0, "serial_attach()\n");
 
 	/* Create new serial device */
-	info = kmalloc(sizeof (*info), GFP_KERNEL);
+	info = kzalloc(sizeof (*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
-	memset(info, 0, sizeof (*info));
 	info->p_dev = link;
 	link->priv = info;
 
@@ -893,6 +895,7 @@
 	PCMCIA_DEVICE_PROD_ID12("OEM      ", "C288MX     ", 0xb572d360, 0xd2385b7a),
 	PCMCIA_DEVICE_PROD_ID12("PCMCIA   ", "C336MX     ", 0x99bcafe9, 0xaa25bcab),
 	PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
+	PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
 	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
 	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
 	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 7186a82..509ace7 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -37,6 +37,9 @@
  *	1.06	Do not insert a char caused previous overrun.
  *		Fix some spin_locks.
  *		Do not call uart_add_one_port for absent ports.
+ *	1.07	Use CONFIG_SERIAL_TXX9_NR_UARTS.  Cleanup.
+ *	1.08	Use platform_device.
+ *		Fix and cleanup suspend/resume/initialization codes.
  */
 
 #if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@@ -49,7 +52,7 @@
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/pci.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
@@ -58,9 +61,8 @@
 #include <linux/mutex.h>
 
 #include <asm/io.h>
-#include <asm/irq.h>
 
-static char *serial_version = "1.06";
+static char *serial_version = "1.08";
 static char *serial_name = "TX39/49 Serial driver";
 
 #define PASS_LIMIT	256
@@ -88,23 +90,13 @@
 /*
  * Number of serial ports
  */
-#ifdef ENABLE_SERIAL_TXX9_PCI
-#define NR_PCI_BOARDS	4
-#define UART_NR  (4 + NR_PCI_BOARDS)
-#else
-#define UART_NR  4
-#endif
+#define UART_NR  CONFIG_SERIAL_TXX9_NR_UARTS
 
 #define HIGH_BITS_OFFSET	((sizeof(long)-sizeof(int))*8)
 
 struct uart_txx9_port {
 	struct uart_port	port;
-
-	/*
-	 * We provide a per-port pm hook.
-	 */
-	void			(*pm)(struct uart_port *port,
-				      unsigned int state, unsigned int old);
+	/* No additional info for now */
 };
 
 #define TXX9_REGION_SIZE	0x24
@@ -282,6 +274,31 @@
 	/* TXX9-SIO can not control DTR... */
 }
 
+static void serial_txx9_initialize(struct uart_port *port)
+{
+	struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+	unsigned int tmout = 10000;
+
+	sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
+	/* TX4925 BUG WORKAROUND.  Accessing SIOC register
+	 * immediately after soft reset causes bus error. */
+	mmiowb();
+	udelay(1);
+	while ((sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST) && --tmout)
+		udelay(1);
+	/* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
+	sio_set(up, TXX9_SIFCR,
+		TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1);
+	/* initial settings */
+	sio_out(up, TXX9_SILCR,
+		TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
+		((up->port.flags & UPF_TXX9_USE_SCLK) ?
+		 TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
+	sio_quot_set(up, uart_get_divisor(port, 9600));
+	sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
+	sio_out(up, TXX9_SIDICR, 0);
+}
+
 static inline void
 receive_chars(struct uart_txx9_port *up, unsigned int *status)
 {
@@ -662,9 +679,8 @@
 serial_txx9_pm(struct uart_port *port, unsigned int state,
 	      unsigned int oldstate)
 {
-	struct uart_txx9_port *up = (struct uart_txx9_port *)port;
-	if (up->pm)
-		up->pm(port, state, oldstate);
+	if (state == 0)
+		serial_txx9_initialize(port);
 }
 
 static int serial_txx9_request_resource(struct uart_txx9_port *up)
@@ -737,7 +753,6 @@
 static void serial_txx9_config_port(struct uart_port *port, int uflags)
 {
 	struct uart_txx9_port *up = (struct uart_txx9_port *)port;
-	unsigned long flags;
 	int ret;
 
 	/*
@@ -754,30 +769,7 @@
 	if (up->port.line == up->port.cons->index)
 		return;
 #endif
-	spin_lock_irqsave(&up->port.lock, flags);
-	/*
-	 * Reset the UART.
-	 */
-	sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
-#ifdef CONFIG_CPU_TX49XX
-	/* TX4925 BUG WORKAROUND.  Accessing SIOC register
-	 * immediately after soft reset causes bus error. */
-	iob();
-	udelay(1);
-#endif
-	while (sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST)
-		;
-	/* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
-	sio_set(up, TXX9_SIFCR,
-		TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1);
-	/* initial settings */
-	sio_out(up, TXX9_SILCR,
-		TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
-		((up->port.flags & UPF_TXX9_USE_SCLK) ?
-		 TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
-	sio_quot_set(up, uart_get_divisor(port, 9600));
-	sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
-	spin_unlock_irqrestore(&up->port.lock, flags);
+	serial_txx9_initialize(port);
 }
 
 static int
@@ -823,7 +815,8 @@
 
 static struct uart_txx9_port serial_txx9_ports[UART_NR];
 
-static void __init serial_txx9_register_ports(struct uart_driver *drv)
+static void __init serial_txx9_register_ports(struct uart_driver *drv,
+					      struct device *dev)
 {
 	int i;
 
@@ -832,6 +825,7 @@
 
 		up->port.line = i;
 		up->port.ops = &serial_txx9_pops;
+		up->port.dev = dev;
 		if (up->port.iobase || up->port.mapbase)
 			uart_add_one_port(drv, &up->port);
 	}
@@ -903,7 +897,7 @@
 	sio_out(up, TXX9_SIDICR, ier);
 }
 
-static int serial_txx9_console_setup(struct console *co, char *options)
+static int __init serial_txx9_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	struct uart_txx9_port *up;
@@ -924,17 +918,7 @@
 	if (!port->ops)
 		return -ENODEV;
 
-	/*
-	 *	Disable UART interrupts, set DTR and RTS high
-	 *	and set speed.
-	 */
-	sio_out(up, TXX9_SIDICR, 0);
-	/* initial settings */
-	sio_out(up, TXX9_SILCR,
-		TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
-		((port->flags & UPF_TXX9_USE_SCLK) ?
-		 TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
-	sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
+	serial_txx9_initialize(&up->port);
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -986,29 +970,6 @@
 	return 0;
 }
 
-#ifdef ENABLE_SERIAL_TXX9_PCI
-/**
- *	serial_txx9_suspend_port - suspend one serial port
- *	@line:  serial line number
- *
- *	Suspend one serial port.
- */
-static void serial_txx9_suspend_port(int line)
-{
-	uart_suspend_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
-}
-
-/**
- *	serial_txx9_resume_port - resume one serial port
- *	@line:  serial line number
- *
- *	Resume one serial port.
- */
-static void serial_txx9_resume_port(int line)
-{
-	uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
-}
-
 static DEFINE_MUTEX(serial_txx9_mutex);
 
 /**
@@ -1031,8 +992,18 @@
 	mutex_lock(&serial_txx9_mutex);
 	for (i = 0; i < UART_NR; i++) {
 		uart = &serial_txx9_ports[i];
-		if (!(uart->port.iobase || uart->port.mapbase))
+		if (uart_match_port(&uart->port, port)) {
+			uart_remove_one_port(&serial_txx9_reg, &uart->port);
 			break;
+		}
+	}
+	if (i == UART_NR) {
+		/* Find unused port */
+		for (i = 0; i < UART_NR; i++) {
+			uart = &serial_txx9_ports[i];
+			if (!(uart->port.iobase || uart->port.mapbase))
+				break;
+		}
 	}
 	if (i < UART_NR) {
 		uart->port.iobase = port->iobase;
@@ -1075,6 +1046,95 @@
 }
 
 /*
+ * Register a set of serial devices attached to a platform device.
+ */
+static int __devinit serial_txx9_probe(struct platform_device *dev)
+{
+	struct uart_port *p = dev->dev.platform_data;
+	struct uart_port port;
+	int ret, i;
+
+	memset(&port, 0, sizeof(struct uart_port));
+	for (i = 0; p && p->uartclk != 0; p++, i++) {
+		port.iobase	= p->iobase;
+		port.membase	= p->membase;
+		port.irq	= p->irq;
+		port.uartclk	= p->uartclk;
+		port.iotype	= p->iotype;
+		port.flags	= p->flags;
+		port.mapbase	= p->mapbase;
+		port.dev	= &dev->dev;
+		ret = serial_txx9_register_port(&port);
+		if (ret < 0) {
+			dev_err(&dev->dev, "unable to register port at index %d "
+				"(IO%x MEM%lx IRQ%d): %d\n", i,
+				p->iobase, p->mapbase, p->irq, ret);
+		}
+	}
+	return 0;
+}
+
+/*
+ * Remove serial ports registered against a platform device.
+ */
+static int __devexit serial_txx9_remove(struct platform_device *dev)
+{
+	int i;
+
+	for (i = 0; i < UART_NR; i++) {
+		struct uart_txx9_port *up = &serial_txx9_ports[i];
+
+		if (up->port.dev == &dev->dev)
+			serial_txx9_unregister_port(i);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int serial_txx9_suspend(struct platform_device *dev, pm_message_t state)
+{
+	int i;
+
+	for (i = 0; i < UART_NR; i++) {
+		struct uart_txx9_port *up = &serial_txx9_ports[i];
+
+		if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
+			uart_suspend_port(&serial_txx9_reg, &up->port);
+	}
+
+	return 0;
+}
+
+static int serial_txx9_resume(struct platform_device *dev)
+{
+	int i;
+
+	for (i = 0; i < UART_NR; i++) {
+		struct uart_txx9_port *up = &serial_txx9_ports[i];
+
+		if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
+			uart_resume_port(&serial_txx9_reg, &up->port);
+	}
+
+	return 0;
+}
+#endif
+
+static struct platform_driver serial_txx9_plat_driver = {
+	.probe		= serial_txx9_probe,
+	.remove		= __devexit_p(serial_txx9_remove),
+#ifdef CONFIG_PM
+	.suspend	= serial_txx9_suspend,
+	.resume		= serial_txx9_resume,
+#endif
+	.driver		= {
+		.name	= "serial_txx9",
+		.owner	= THIS_MODULE,
+	},
+};
+
+#ifdef ENABLE_SERIAL_TXX9_PCI
+/*
  * Probe one serial board.  Unfortunately, there is no rhyme nor reason
  * to the arrangement of serial ports on a PCI card.
  */
@@ -1100,30 +1160,33 @@
 	line = serial_txx9_register_port(&port);
 	if (line < 0) {
 		printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line);
+		pci_disable_device(dev);
+		return line;
 	}
-	pci_set_drvdata(dev, (void *)(long)line);
+	pci_set_drvdata(dev, &serial_txx9_ports[line]);
 
 	return 0;
 }
 
 static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
 {
-	int line = (int)(long)pci_get_drvdata(dev);
+	struct uart_txx9_port *up = pci_get_drvdata(dev);
 
 	pci_set_drvdata(dev, NULL);
 
-	if (line) {
-		serial_txx9_unregister_port(line);
+	if (up) {
+		serial_txx9_unregister_port(up->port.line);
 		pci_disable_device(dev);
 	}
 }
 
+#ifdef CONFIG_PM
 static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
 {
-	int line = (int)(long)pci_get_drvdata(dev);
+	struct uart_txx9_port *up = pci_get_drvdata(dev);
 
-	if (line)
-		serial_txx9_suspend_port(line);
+	if (up)
+		uart_suspend_port(&serial_txx9_reg, &up->port);
 	pci_save_state(dev);
 	pci_set_power_state(dev, pci_choose_state(dev, state));
 	return 0;
@@ -1131,22 +1194,18 @@
 
 static int pciserial_txx9_resume_one(struct pci_dev *dev)
 {
-	int line = (int)(long)pci_get_drvdata(dev);
+	struct uart_txx9_port *up = pci_get_drvdata(dev);
 
 	pci_set_power_state(dev, PCI_D0);
 	pci_restore_state(dev);
-
-	if (line) {
-		pci_enable_device(dev);
-		serial_txx9_resume_port(line);
-	}
+	if (up)
+		uart_resume_port(&serial_txx9_reg, &up->port);
 	return 0;
 }
+#endif
 
-static struct pci_device_id serial_txx9_pci_tbl[] = {
-	{	PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC,
-		PCI_ANY_ID, PCI_ANY_ID,
-		0, 0, 0 },
+static const struct pci_device_id serial_txx9_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC) },
 	{ 0, }
 };
 
@@ -1154,14 +1213,18 @@
 	.name		= "serial_txx9",
 	.probe		= pciserial_txx9_init_one,
 	.remove		= __devexit_p(pciserial_txx9_remove_one),
+#ifdef CONFIG_PM
 	.suspend	= pciserial_txx9_suspend_one,
 	.resume		= pciserial_txx9_resume_one,
+#endif
 	.id_table	= serial_txx9_pci_tbl,
 };
 
 MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl);
 #endif /* ENABLE_SERIAL_TXX9_PCI */
 
+static struct platform_device *serial_txx9_plat_devs;
+
 static int __init serial_txx9_init(void)
 {
 	int ret;
@@ -1169,13 +1232,39 @@
  	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
 
 	ret = uart_register_driver(&serial_txx9_reg);
-	if (ret >= 0) {
-		serial_txx9_register_ports(&serial_txx9_reg);
+	if (ret)
+		goto out;
+
+	serial_txx9_plat_devs = platform_device_alloc("serial_txx9", -1);
+	if (!serial_txx9_plat_devs) {
+		ret = -ENOMEM;
+		goto unreg_uart_drv;
+	}
+
+	ret = platform_device_add(serial_txx9_plat_devs);
+	if (ret)
+		goto put_dev;
+
+	serial_txx9_register_ports(&serial_txx9_reg,
+				   &serial_txx9_plat_devs->dev);
+
+	ret = platform_driver_register(&serial_txx9_plat_driver);
+	if (ret)
+		goto del_dev;
 
 #ifdef ENABLE_SERIAL_TXX9_PCI
-		ret = pci_register_driver(&serial_txx9_pci_driver);
+	ret = pci_register_driver(&serial_txx9_pci_driver);
 #endif
-	}
+	if (ret == 0)
+		goto out;
+
+ del_dev:
+	platform_device_del(serial_txx9_plat_devs);
+ put_dev:
+	platform_device_put(serial_txx9_plat_devs);
+ unreg_uart_drv:
+	uart_unregister_driver(&serial_txx9_reg);
+ out:
 	return ret;
 }
 
@@ -1186,6 +1275,8 @@
 #ifdef ENABLE_SERIAL_TXX9_PCI
 	pci_unregister_driver(&serial_txx9_pci_driver);
 #endif
+	platform_driver_unregister(&serial_txx9_plat_driver);
+	platform_device_unregister(serial_txx9_plat_devs);
 	for (i = 0; i < UART_NR; i++) {
 		struct uart_txx9_port *up = &serial_txx9_ports[i];
 		if (up->port.iobase || up->port.mapbase)
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 145d623..deb9ab4 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -17,7 +17,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 3ec3df2..96a852a 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -17,7 +17,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 244f796..da73205 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -14,7 +14,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/tty.h>
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index db8607e..f5051cf 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -256,7 +256,7 @@
 {
 	release_mem_region(port->mapbase, ULITE_REGION);
 	iounmap(port->membase);
-	port->membase = 0;
+	port->membase = NULL;
 }
 
 static int ulite_request_port(struct uart_port *port)
@@ -438,7 +438,7 @@
 	port->iotype	= UPIO_MEM;
 	port->iobase	= 1; /* mark port in use */
 	port->mapbase	= res->start;
-	port->membase	= 0;
+	port->membase	= NULL;
 	port->ops	= &ulite_ops;
 	port->irq	= res2->start;
 	port->flags	= UPF_BOOT_AUTOCONF;
@@ -462,7 +462,7 @@
 		uart_remove_one_port(&ulite_uart_driver, port);
 
 	/* mark port as free */
-	port->membase = 0;
+	port->membase = NULL;
 
 	return 0;
 }
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
index cd6b653..2dd6eed 100644
--- a/drivers/sn/ioc3.c
+++ b/drivers/sn/ioc3.c
@@ -654,7 +654,7 @@
 		ret = -ENODEV;
 		goto out_pci;
 	}
-	if (!request_region(idd->pma, IOC3_PCI_SIZE, "ioc3")) {
+	if (!request_mem_region(idd->pma, IOC3_PCI_SIZE, "ioc3")) {
 		printk(KERN_WARNING
 		       "%s: Unable to request IOC3 region "
 		       "for pci_dev %s.\n",
@@ -744,7 +744,7 @@
 	return 0;
 
 out_misc_region:
-	release_region(idd->pma, IOC3_PCI_SIZE);
+	release_mem_region(idd->pma, IOC3_PCI_SIZE);
 out_pci:
 	kfree(idd);
 out_idd:
@@ -785,7 +785,7 @@
 	if(idd->dual_irq)
 		free_irq(idd->irq_eth, (void *)idd);
 	iounmap(idd->vma);
-	release_region(idd->pma, IOC3_PCI_SIZE);
+	release_mem_region(idd->pma, IOC3_PCI_SIZE);
 
 	/* Disable IOC3 and relinquish */
 	pci_disable_device(pdev);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index d895a1a..7e54e48e 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -51,6 +51,13 @@
 comment "SPI Master Controller Drivers"
 	depends on SPI_MASTER
 
+config SPI_ATMEL
+	tristate "Atmel SPI Controller"
+	depends on (ARCH_AT91 || AVR32) && SPI_MASTER
+	help
+	  This selects a driver for the Atmel SPI Controller, present on
+	  many AT32 (AVR32) and AT91 (ARM) chips.
+
 config SPI_BITBANG
 	tristate "Bitbanging SPI master"
 	depends on SPI_MASTER && EXPERIMENTAL
@@ -75,6 +82,13 @@
 	  inexpensive battery powered microcontroller evaluation board.
 	  This same cable can be used to flash new firmware.
 
+config SPI_IMX
+	tristate "Freescale iMX SPI controller"
+	depends on SPI_MASTER && ARCH_IMX && EXPERIMENTAL
+	help
+	  This enables using the Freescale iMX SPI controller in master
+	  mode.
+
 config SPI_MPC83xx
 	tristate "Freescale MPC83xx SPI controller"
 	depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL
@@ -87,6 +101,14 @@
 	  family of PowerPC processors.  The MPC83xx uses a simple set of shift
 	  registers for data (opposed to the CPM based descriptor model).
 
+config SPI_OMAP_UWIRE
+	tristate "OMAP1 MicroWire"
+	depends on SPI_MASTER && ARCH_OMAP1
+	select SPI_BITBANG
+	help
+	  This hooks up to the MicroWire controller on OMAP1 chips.
+
+
 config SPI_PXA2XX
 	tristate "PXA2xx SSP SPI master"
 	depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL
@@ -95,6 +117,12 @@
 	  The driver can be configured to use any SSP port and additional
 	  documentation can be found a Documentation/spi/pxa2xx.
 
+config SPI_S3C24XX
+	tristate "Samsung S3C24XX series SPI"
+	depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+	help
+	  SPI driver for Samsung S3C24XX series ARM SoCs
+
 config SPI_S3C24XX_GPIO
 	tristate "Samsung S3C24XX series SPI by GPIO"
 	depends on SPI_MASTER && ARCH_S3C2410 && SPI_BITBANG && EXPERIMENTAL
@@ -107,13 +135,6 @@
 # Add new SPI master controllers in alphabetical order above this line
 #
 
-
-config SPI_S3C24XX
-	tristate "Samsung S3C24XX series SPI"
-	depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
-	help
-	  SPI driver for Samsung S3C24XX series ARM SoCs
-
 #
 # There are lots of SPI device types, with sensors and memory
 # being probably the most widely used ones.
@@ -121,6 +142,16 @@
 comment "SPI Protocol Masters"
 	depends on SPI_MASTER
 
+config SPI_AT25
+	tristate "SPI EEPROMs from most vendors"
+	depends on SPI_MASTER && SYSFS
+	help
+	  Enable this driver to get read/write support to most SPI EEPROMs,
+	  after you configure the board init code to know about each eeprom
+	  on your target board.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called at25.
 
 #
 # Add new SPI protocol masters in alphabetical order above this line
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 8f4cb67..3c280ad 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -12,14 +12,18 @@
 
 # SPI master controller drivers (bus)
 obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o
+obj-$(CONFIG_SPI_ATMEL)			+= atmel_spi.o
 obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
+obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
+obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
 obj-$(CONFIG_SPI_MPC83xx)		+= spi_mpc83xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx.o
 # 	... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
+obj-$(CONFIG_SPI_AT25)		+= at25.o
 # 	... add above this line ...
 
 # SPI slave controller drivers (upstream link)
diff --git a/drivers/spi/at25.c b/drivers/spi/at25.c
new file mode 100644
index 0000000..48e4f48
--- /dev/null
+++ b/drivers/spi/at25.c
@@ -0,0 +1,381 @@
+/*
+ * at25.c -- support most SPI EEPROMs, such as Atmel AT25 models
+ *
+ * Copyright (C) 2006 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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
+
+
+struct at25_data {
+	struct spi_device	*spi;
+	struct mutex		lock;
+	struct spi_eeprom	chip;
+	struct bin_attribute	bin;
+	unsigned		addrlen;
+};
+
+#define	AT25_WREN	0x06		/* latch the write enable */
+#define	AT25_WRDI	0x04		/* reset the write enable */
+#define	AT25_RDSR	0x05		/* read status register */
+#define	AT25_WRSR	0x01		/* write status register */
+#define	AT25_READ	0x03		/* read byte(s) */
+#define	AT25_WRITE	0x02		/* write byte(s)/sector */
+
+#define	AT25_SR_nRDY	0x01		/* nRDY = write-in-progress */
+#define	AT25_SR_WEN	0x02		/* write enable (latched) */
+#define	AT25_SR_BP0	0x04		/* BP for software writeprotect */
+#define	AT25_SR_BP1	0x08
+#define	AT25_SR_WPEN	0x80		/* writeprotect enable */
+
+
+#define EE_MAXADDRLEN	3		/* 24 bit addresses, up to 2 MBytes */
+
+/* Specs often allow 5 msec for a page write, sometimes 20 msec;
+ * it's important to recover from write timeouts.
+ */
+#define	EE_TIMEOUT	25
+
+/*-------------------------------------------------------------------------*/
+
+#define	io_limit	PAGE_SIZE	/* bytes */
+
+static ssize_t
+at25_ee_read(
+	struct at25_data	*at25,
+	char			*buf,
+	unsigned		offset,
+	size_t			count
+)
+{
+	u8			command[EE_MAXADDRLEN + 1];
+	u8			*cp;
+	ssize_t			status;
+	struct spi_transfer	t[2];
+	struct spi_message	m;
+
+	cp = command;
+	*cp++ = AT25_READ;
+
+	/* 8/16/24-bit address is written MSB first */
+	switch (at25->addrlen) {
+	default:	/* case 3 */
+		*cp++ = offset >> 16;
+	case 2:
+		*cp++ = offset >> 8;
+	case 1:
+	case 0:	/* can't happen: for better codegen */
+		*cp++ = offset >> 0;
+	}
+
+	spi_message_init(&m);
+	memset(t, 0, sizeof t);
+
+	t[0].tx_buf = command;
+	t[0].len = at25->addrlen + 1;
+	spi_message_add_tail(&t[0], &m);
+
+	t[1].rx_buf = buf;
+	t[1].len = count;
+	spi_message_add_tail(&t[1], &m);
+
+	mutex_lock(&at25->lock);
+
+	/* Read it all at once.
+	 *
+	 * REVISIT that's potentially a problem with large chips, if
+	 * other devices on the bus need to be accessed regularly or
+	 * this chip is clocked very slowly
+	 */
+	status = spi_sync(at25->spi, &m);
+	dev_dbg(&at25->spi->dev,
+		"read %Zd bytes at %d --> %d\n",
+		count, offset, (int) status);
+
+	mutex_unlock(&at25->lock);
+	return status ? status : count;
+}
+
+static ssize_t
+at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct device		*dev;
+	struct at25_data	*at25;
+
+	dev = container_of(kobj, struct device, kobj);
+	at25 = dev_get_drvdata(dev);
+
+	if (unlikely(off >= at25->bin.size))
+		return 0;
+	if ((off + count) > at25->bin.size)
+		count = at25->bin.size - off;
+	if (unlikely(!count))
+		return count;
+
+	return at25_ee_read(at25, buf, off, count);
+}
+
+
+static ssize_t
+at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count)
+{
+	ssize_t			status = 0;
+	unsigned		written = 0;
+	unsigned		buf_size;
+	u8			*bounce;
+
+	/* Temp buffer starts with command and address */
+	buf_size = at25->chip.page_size;
+	if (buf_size > io_limit)
+		buf_size = io_limit;
+	bounce = kmalloc(buf_size + at25->addrlen + 1, GFP_KERNEL);
+	if (!bounce)
+		return -ENOMEM;
+
+	/* For write, rollover is within the page ... so we write at
+	 * most one page, then manually roll over to the next page.
+	 */
+	bounce[0] = AT25_WRITE;
+	mutex_lock(&at25->lock);
+	do {
+		unsigned long	timeout, retries;
+		unsigned	segment;
+		unsigned	offset = (unsigned) off;
+		u8		*cp = bounce + 1;
+
+		*cp = AT25_WREN;
+		status = spi_write(at25->spi, cp, 1);
+		if (status < 0) {
+			dev_dbg(&at25->spi->dev, "WREN --> %d\n",
+					(int) status);
+			break;
+		}
+
+		/* 8/16/24-bit address is written MSB first */
+		switch (at25->addrlen) {
+		default:	/* case 3 */
+			*cp++ = offset >> 16;
+		case 2:
+			*cp++ = offset >> 8;
+		case 1:
+		case 0:	/* can't happen: for better codegen */
+			*cp++ = offset >> 0;
+		}
+
+		/* Write as much of a page as we can */
+		segment = buf_size - (offset % buf_size);
+		if (segment > count)
+			segment = count;
+		memcpy(cp, buf, segment);
+		status = spi_write(at25->spi, bounce,
+				segment + at25->addrlen + 1);
+		dev_dbg(&at25->spi->dev,
+				"write %u bytes at %u --> %d\n",
+				segment, offset, (int) status);
+		if (status < 0)
+			break;
+
+		/* REVISIT this should detect (or prevent) failed writes
+		 * to readonly sections of the EEPROM...
+		 */
+
+		/* Wait for non-busy status */
+		timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT);
+		retries = 0;
+		do {
+			int	sr;
+
+			sr = spi_w8r8(at25->spi, AT25_RDSR);
+			if (sr < 0 || (sr & AT25_SR_nRDY)) {
+				dev_dbg(&at25->spi->dev,
+					"rdsr --> %d (%02x)\n", sr, sr);
+				/* at HZ=100, this is sloooow */
+				msleep(1);
+				continue;
+			}
+			if (!(sr & AT25_SR_nRDY))
+				break;
+		} while (retries++ < 3 || time_before_eq(jiffies, timeout));
+
+		if (time_after(jiffies, timeout)) {
+			dev_err(&at25->spi->dev,
+				"write %d bytes offset %d, "
+				"timeout after %u msecs\n",
+				segment, offset,
+				jiffies_to_msecs(jiffies -
+					(timeout - EE_TIMEOUT)));
+			status = -ETIMEDOUT;
+			break;
+		}
+
+		off += segment;
+		buf += segment;
+		count -= segment;
+		written += segment;
+
+	} while (count > 0);
+
+	mutex_unlock(&at25->lock);
+
+	kfree(bounce);
+	return written ? written : status;
+}
+
+static ssize_t
+at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct device		*dev;
+	struct at25_data	*at25;
+
+	dev = container_of(kobj, struct device, kobj);
+	at25 = dev_get_drvdata(dev);
+
+	if (unlikely(off >= at25->bin.size))
+		return -EFBIG;
+	if ((off + count) > at25->bin.size)
+		count = at25->bin.size - off;
+	if (unlikely(!count))
+		return count;
+
+	return at25_ee_write(at25, buf, off, count);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int at25_probe(struct spi_device *spi)
+{
+	struct at25_data	*at25 = NULL;
+	const struct spi_eeprom *chip;
+	int			err;
+	int			sr;
+	int			addrlen;
+
+	/* Chip description */
+	chip = spi->dev.platform_data;
+	if (!chip) {
+		dev_dbg(&spi->dev, "no chip description\n");
+		err = -ENODEV;
+		goto fail;
+	}
+
+	/* For now we only support 8/16/24 bit addressing */
+	if (chip->flags & EE_ADDR1)
+		addrlen = 1;
+	else if (chip->flags & EE_ADDR2)
+		addrlen = 2;
+	else if (chip->flags & EE_ADDR3)
+		addrlen = 3;
+	else {
+		dev_dbg(&spi->dev, "unsupported address type\n");
+		err = -EINVAL;
+		goto fail;
+	}
+
+	/* Ping the chip ... the status register is pretty portable,
+	 * unlike probing manufacturer IDs.  We do expect that system
+	 * firmware didn't write it in the past few milliseconds!
+	 */
+	sr = spi_w8r8(spi, AT25_RDSR);
+	if (sr < 0 || sr & AT25_SR_nRDY) {
+		dev_dbg(&at25->spi->dev, "rdsr --> %d (%02x)\n", sr, sr);
+		err = -ENXIO;
+		goto fail;
+	}
+
+	if (!(at25 = kzalloc(sizeof *at25, GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	mutex_init(&at25->lock);
+	at25->chip = *chip;
+	at25->spi = spi_dev_get(spi);
+	dev_set_drvdata(&spi->dev, at25);
+	at25->addrlen = addrlen;
+
+	/* Export the EEPROM bytes through sysfs, since that's convenient.
+	 * Default to root-only access to the data; EEPROMs often hold data
+	 * that's sensitive for read and/or write, like ethernet addresses,
+	 * security codes, board-specific manufacturing calibrations, etc.
+	 */
+	at25->bin.attr.name = "eeprom";
+	at25->bin.attr.mode = S_IRUSR;
+	at25->bin.attr.owner = THIS_MODULE;
+	at25->bin.read = at25_bin_read;
+
+	at25->bin.size = at25->chip.byte_len;
+	if (!(chip->flags & EE_READONLY)) {
+		at25->bin.write = at25_bin_write;
+		at25->bin.attr.mode |= S_IWUSR;
+	}
+
+	err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin);
+	if (err)
+		goto fail;
+
+	dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n",
+		(at25->bin.size < 1024)
+			? at25->bin.size
+			: (at25->bin.size / 1024),
+		(at25->bin.size < 1024) ? "Byte" : "KByte",
+		at25->chip.name,
+		(chip->flags & EE_READONLY) ? " (readonly)" : "",
+		at25->chip.page_size);
+	return 0;
+fail:
+	dev_dbg(&spi->dev, "probe err %d\n", err);
+	kfree(at25);
+	return err;
+}
+
+static int __devexit at25_remove(struct spi_device *spi)
+{
+	struct at25_data	*at25;
+
+	at25 = dev_get_drvdata(&spi->dev);
+	sysfs_remove_bin_file(&spi->dev.kobj, &at25->bin);
+	kfree(at25);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct spi_driver at25_driver = {
+	.driver = {
+		.name		= "at25",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= at25_probe,
+	.remove		= __devexit_p(at25_remove),
+};
+
+static int __init at25_init(void)
+{
+	return spi_register_driver(&at25_driver);
+}
+module_init(at25_init);
+
+static void __exit at25_exit(void)
+{
+	spi_unregister_driver(&at25_driver);
+}
+module_exit(at25_exit);
+
+MODULE_DESCRIPTION("Driver for most SPI EEPROMs");
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
new file mode 100644
index 0000000..6fa260d
--- /dev/null
+++ b/drivers/spi/atmel_spi.c
@@ -0,0 +1,682 @@
+/*
+ * Driver for Atmel AT32 and AT91 SPI Controllers
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+
+#include <asm/io.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#ifdef CONFIG_ARCH_AT91
+#include <asm/arch/cpu.h>
+#endif
+
+#include "atmel_spi.h"
+
+/*
+ * The core SPI transfer engine just talks to a register bank to set up
+ * DMA transfers; transfer queue progress is driven by IRQs.  The clock
+ * framework provides the base clock, subdivided for each spi_device.
+ *
+ * Newer controllers, marked with "new_1" flag, have:
+ *  - CR.LASTXFER
+ *  - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero)
+ *  - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
+ *  - SPI_CSRx.CSAAT
+ *  - SPI_CSRx.SBCR allows faster clocking
+ */
+struct atmel_spi {
+	spinlock_t		lock;
+
+	void __iomem		*regs;
+	int			irq;
+	struct clk		*clk;
+	struct platform_device	*pdev;
+	unsigned		new_1:1;
+
+	u8			stopping;
+	struct list_head	queue;
+	struct spi_transfer	*current_transfer;
+	unsigned long		remaining_bytes;
+
+	void			*buffer;
+	dma_addr_t		buffer_dma;
+};
+
+#define BUFFER_SIZE		PAGE_SIZE
+#define INVALID_DMA_ADDRESS	0xffffffff
+
+/*
+ * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
+ * they assume that spi slave device state will not change on deselect, so
+ * that automagic deselection is OK.  Not so!  Workaround uses nCSx pins
+ * as GPIOs; or newer controllers have CSAAT and friends.
+ *
+ * Since the CSAAT functionality is a bit weird on newer controllers
+ * as well, we use GPIO to control nCSx pins on all controllers.
+ */
+
+static inline void cs_activate(struct spi_device *spi)
+{
+	unsigned gpio = (unsigned) spi->controller_data;
+	unsigned active = spi->mode & SPI_CS_HIGH;
+
+	dev_dbg(&spi->dev, "activate %u%s\n", gpio, active ? " (high)" : "");
+	gpio_set_value(gpio, active);
+}
+
+static inline void cs_deactivate(struct spi_device *spi)
+{
+	unsigned gpio = (unsigned) spi->controller_data;
+	unsigned active = spi->mode & SPI_CS_HIGH;
+
+	dev_dbg(&spi->dev, "DEactivate %u%s\n", gpio, active ? " (low)" : "");
+	gpio_set_value(gpio, !active);
+}
+
+/*
+ * Submit next transfer for DMA.
+ * lock is held, spi irq is blocked
+ */
+static void atmel_spi_next_xfer(struct spi_master *master,
+				struct spi_message *msg)
+{
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	struct spi_transfer	*xfer;
+	u32			len;
+	dma_addr_t		tx_dma, rx_dma;
+
+	xfer = as->current_transfer;
+	if (!xfer || as->remaining_bytes == 0) {
+		if (xfer)
+			xfer = list_entry(xfer->transfer_list.next,
+					struct spi_transfer, transfer_list);
+		else
+			xfer = list_entry(msg->transfers.next,
+					struct spi_transfer, transfer_list);
+		as->remaining_bytes = xfer->len;
+		as->current_transfer = xfer;
+	}
+
+	len = as->remaining_bytes;
+
+	tx_dma = xfer->tx_dma;
+	rx_dma = xfer->rx_dma;
+
+	/* use scratch buffer only when rx or tx data is unspecified */
+	if (rx_dma == INVALID_DMA_ADDRESS) {
+		rx_dma = as->buffer_dma;
+		if (len > BUFFER_SIZE)
+			len = BUFFER_SIZE;
+	}
+	if (tx_dma == INVALID_DMA_ADDRESS) {
+		tx_dma = as->buffer_dma;
+		if (len > BUFFER_SIZE)
+			len = BUFFER_SIZE;
+		memset(as->buffer, 0, len);
+		dma_sync_single_for_device(&as->pdev->dev,
+				as->buffer_dma, len, DMA_TO_DEVICE);
+	}
+
+	spi_writel(as, RPR, rx_dma);
+	spi_writel(as, TPR, tx_dma);
+
+	as->remaining_bytes -= len;
+	if (msg->spi->bits_per_word > 8)
+		len >>= 1;
+
+	/* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer"
+	 * mechanism might help avoid the IRQ latency between transfers
+	 *
+	 * We're also waiting for ENDRX before we start the next
+	 * transfer because we need to handle some difficult timing
+	 * issues otherwise. If we wait for ENDTX in one transfer and
+	 * then starts waiting for ENDRX in the next, it's difficult
+	 * to tell the difference between the ENDRX interrupt we're
+	 * actually waiting for and the ENDRX interrupt of the
+	 * previous transfer.
+	 *
+	 * It should be doable, though. Just not now...
+	 */
+	spi_writel(as, TNCR, 0);
+	spi_writel(as, RNCR, 0);
+	spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES));
+
+	dev_dbg(&msg->spi->dev,
+		"  start xfer %p: len %u tx %p/%08x rx %p/%08x imr %03x\n",
+		xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+		xfer->rx_buf, xfer->rx_dma, spi_readl(as, IMR));
+
+	spi_writel(as, TCR, len);
+	spi_writel(as, RCR, len);
+	spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
+}
+
+static void atmel_spi_next_message(struct spi_master *master)
+{
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	struct spi_message	*msg;
+	u32			mr;
+
+	BUG_ON(as->current_transfer);
+
+	msg = list_entry(as->queue.next, struct spi_message, queue);
+
+	/* Select the chip */
+	mr = spi_readl(as, MR);
+	mr = SPI_BFINS(PCS, ~(1 << msg->spi->chip_select), mr);
+	spi_writel(as, MR, mr);
+	cs_activate(msg->spi);
+
+	atmel_spi_next_xfer(master, msg);
+}
+
+static void
+atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
+{
+	xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
+	if (xfer->tx_buf)
+		xfer->tx_dma = dma_map_single(&as->pdev->dev,
+				(void *) xfer->tx_buf, xfer->len,
+				DMA_TO_DEVICE);
+	if (xfer->rx_buf)
+		xfer->rx_dma = dma_map_single(&as->pdev->dev,
+				xfer->rx_buf, xfer->len,
+				DMA_FROM_DEVICE);
+}
+
+static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
+				     struct spi_transfer *xfer)
+{
+	if (xfer->tx_dma != INVALID_DMA_ADDRESS)
+		dma_unmap_single(master->cdev.dev, xfer->tx_dma,
+				 xfer->len, DMA_TO_DEVICE);
+	if (xfer->rx_dma != INVALID_DMA_ADDRESS)
+		dma_unmap_single(master->cdev.dev, xfer->rx_dma,
+				 xfer->len, DMA_FROM_DEVICE);
+}
+
+static void
+atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
+		   struct spi_message *msg, int status)
+{
+	cs_deactivate(msg->spi);
+	list_del(&msg->queue);
+	msg->status = status;
+
+	dev_dbg(master->cdev.dev,
+		"xfer complete: %u bytes transferred\n",
+		msg->actual_length);
+
+	spin_unlock(&as->lock);
+	msg->complete(msg->context);
+	spin_lock(&as->lock);
+
+	as->current_transfer = NULL;
+
+	/* continue if needed */
+	if (list_empty(&as->queue) || as->stopping)
+		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+	else
+		atmel_spi_next_message(master);
+}
+
+static irqreturn_t
+atmel_spi_interrupt(int irq, void *dev_id)
+{
+	struct spi_master	*master = dev_id;
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	struct spi_message	*msg;
+	struct spi_transfer	*xfer;
+	u32			status, pending, imr;
+	int			ret = IRQ_NONE;
+
+	spin_lock(&as->lock);
+
+	xfer = as->current_transfer;
+	msg = list_entry(as->queue.next, struct spi_message, queue);
+
+	imr = spi_readl(as, IMR);
+	status = spi_readl(as, SR);
+	pending = status & imr;
+
+	if (pending & SPI_BIT(OVRES)) {
+		int timeout;
+
+		ret = IRQ_HANDLED;
+
+		spi_writel(as, IDR, (SPI_BIT(ENDTX) | SPI_BIT(ENDRX)
+				     | SPI_BIT(OVRES)));
+
+		/*
+		 * When we get an overrun, we disregard the current
+		 * transfer. Data will not be copied back from any
+		 * bounce buffer and msg->actual_len will not be
+		 * updated with the last xfer.
+		 *
+		 * We will also not process any remaning transfers in
+		 * the message.
+		 *
+		 * First, stop the transfer and unmap the DMA buffers.
+		 */
+		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+		if (!msg->is_dma_mapped)
+			atmel_spi_dma_unmap_xfer(master, xfer);
+
+		/* REVISIT: udelay in irq is unfriendly */
+		if (xfer->delay_usecs)
+			udelay(xfer->delay_usecs);
+
+		dev_warn(master->cdev.dev, "fifo overrun (%u/%u remaining)\n",
+			 spi_readl(as, TCR), spi_readl(as, RCR));
+
+		/*
+		 * Clean up DMA registers and make sure the data
+		 * registers are empty.
+		 */
+		spi_writel(as, RNCR, 0);
+		spi_writel(as, TNCR, 0);
+		spi_writel(as, RCR, 0);
+		spi_writel(as, TCR, 0);
+		for (timeout = 1000; timeout; timeout--)
+			if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
+				break;
+		if (!timeout)
+			dev_warn(master->cdev.dev,
+				 "timeout waiting for TXEMPTY");
+		while (spi_readl(as, SR) & SPI_BIT(RDRF))
+			spi_readl(as, RDR);
+
+		/* Clear any overrun happening while cleaning up */
+		spi_readl(as, SR);
+
+		atmel_spi_msg_done(master, as, msg, -EIO);
+	} else if (pending & SPI_BIT(ENDRX)) {
+		ret = IRQ_HANDLED;
+
+		spi_writel(as, IDR, pending);
+
+		if (as->remaining_bytes == 0) {
+			msg->actual_length += xfer->len;
+
+			if (!msg->is_dma_mapped)
+				atmel_spi_dma_unmap_xfer(master, xfer);
+
+			/* REVISIT: udelay in irq is unfriendly */
+			if (xfer->delay_usecs)
+				udelay(xfer->delay_usecs);
+
+			if (msg->transfers.prev == &xfer->transfer_list) {
+				/* report completed message */
+				atmel_spi_msg_done(master, as, msg, 0);
+			} else {
+				if (xfer->cs_change) {
+					cs_deactivate(msg->spi);
+					udelay(1);
+					cs_activate(msg->spi);
+				}
+
+				/*
+				 * Not done yet. Submit the next transfer.
+				 *
+				 * FIXME handle protocol options for xfer
+				 */
+				atmel_spi_next_xfer(master, msg);
+			}
+		} else {
+			/*
+			 * Keep going, we still have data to send in
+			 * the current transfer.
+			 */
+			atmel_spi_next_xfer(master, msg);
+		}
+	}
+
+	spin_unlock(&as->lock);
+
+	return ret;
+}
+
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
+static int atmel_spi_setup(struct spi_device *spi)
+{
+	struct atmel_spi	*as;
+	u32			scbr, csr;
+	unsigned int		bits = spi->bits_per_word;
+	unsigned long		bus_hz, sck_hz;
+	unsigned int		npcs_pin;
+	int			ret;
+
+	as = spi_master_get_devdata(spi->master);
+
+	if (as->stopping)
+		return -ESHUTDOWN;
+
+	if (spi->chip_select > spi->master->num_chipselect) {
+		dev_dbg(&spi->dev,
+				"setup: invalid chipselect %u (%u defined)\n",
+				spi->chip_select, spi->master->num_chipselect);
+		return -EINVAL;
+	}
+
+	if (bits == 0)
+		bits = 8;
+	if (bits < 8 || bits > 16) {
+		dev_dbg(&spi->dev,
+				"setup: invalid bits_per_word %u (8 to 16)\n",
+				bits);
+		return -EINVAL;
+	}
+
+	if (spi->mode & ~MODEBITS) {
+		dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+			spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
+	/* speed zero convention is used by some upper layers */
+	bus_hz = clk_get_rate(as->clk);
+	if (spi->max_speed_hz) {
+		/* assume div32/fdiv/mbz == 0 */
+		if (!as->new_1)
+			bus_hz /= 2;
+		scbr = ((bus_hz + spi->max_speed_hz - 1)
+			/ spi->max_speed_hz);
+		if (scbr >= (1 << SPI_SCBR_SIZE)) {
+			dev_dbg(&spi->dev, "setup: %d Hz too slow, scbr %u\n",
+					spi->max_speed_hz, scbr);
+			return -EINVAL;
+		}
+	} else
+		scbr = 0xff;
+	sck_hz = bus_hz / scbr;
+
+	csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
+	if (spi->mode & SPI_CPOL)
+		csr |= SPI_BIT(CPOL);
+	if (!(spi->mode & SPI_CPHA))
+		csr |= SPI_BIT(NCPHA);
+
+	/* TODO: DLYBS and DLYBCT */
+	csr |= SPI_BF(DLYBS, 10);
+	csr |= SPI_BF(DLYBCT, 10);
+
+	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
+	npcs_pin = (unsigned int)spi->controller_data;
+	if (!spi->controller_state) {
+		ret = gpio_request(npcs_pin, "spi_npcs");
+		if (ret)
+			return ret;
+		spi->controller_state = (void *)npcs_pin;
+		gpio_direction_output(npcs_pin);
+	}
+
+	dev_dbg(&spi->dev,
+		"setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
+		sck_hz, bits, spi->mode, spi->chip_select, csr);
+
+	spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
+
+	return 0;
+}
+
+static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct atmel_spi	*as;
+	struct spi_transfer	*xfer;
+	unsigned long		flags;
+	struct device		*controller = spi->master->cdev.dev;
+
+	as = spi_master_get_devdata(spi->master);
+
+	dev_dbg(controller, "new message %p submitted for %s\n",
+			msg, spi->dev.bus_id);
+
+	if (unlikely(list_empty(&msg->transfers)
+			|| !spi->max_speed_hz))
+		return -EINVAL;
+
+	if (as->stopping)
+		return -ESHUTDOWN;
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		if (!(xfer->tx_buf || xfer->rx_buf)) {
+			dev_dbg(&spi->dev, "missing rx or tx buf\n");
+			return -EINVAL;
+		}
+
+		/* FIXME implement these protocol options!! */
+		if (xfer->bits_per_word || xfer->speed_hz) {
+			dev_dbg(&spi->dev, "no protocol options yet\n");
+			return -ENOPROTOOPT;
+		}
+	}
+
+	/* scrub dcache "early" */
+	if (!msg->is_dma_mapped) {
+		list_for_each_entry(xfer, &msg->transfers, transfer_list)
+			atmel_spi_dma_map_xfer(as, xfer);
+	}
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		dev_dbg(controller,
+			"  xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+			xfer, xfer->len,
+			xfer->tx_buf, xfer->tx_dma,
+			xfer->rx_buf, xfer->rx_dma);
+	}
+
+	msg->status = -EINPROGRESS;
+	msg->actual_length = 0;
+
+	spin_lock_irqsave(&as->lock, flags);
+	list_add_tail(&msg->queue, &as->queue);
+	if (!as->current_transfer)
+		atmel_spi_next_message(spi->master);
+	spin_unlock_irqrestore(&as->lock, flags);
+
+	return 0;
+}
+
+static void atmel_spi_cleanup(struct spi_device *spi)
+{
+	if (spi->controller_state)
+		gpio_free((unsigned int)spi->controller_data);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init atmel_spi_probe(struct platform_device *pdev)
+{
+	struct resource		*regs;
+	int			irq;
+	struct clk		*clk;
+	int			ret;
+	struct spi_master	*master;
+	struct atmel_spi	*as;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs)
+		return -ENXIO;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	clk = clk_get(&pdev->dev, "spi_clk");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	/* setup spi core then atmel-specific driver state */
+	ret = -ENOMEM;
+	master = spi_alloc_master(&pdev->dev, sizeof *as);
+	if (!master)
+		goto out_free;
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = 4;
+	master->setup = atmel_spi_setup;
+	master->transfer = atmel_spi_transfer;
+	master->cleanup = atmel_spi_cleanup;
+	platform_set_drvdata(pdev, master);
+
+	as = spi_master_get_devdata(master);
+
+	as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE,
+					&as->buffer_dma, GFP_KERNEL);
+	if (!as->buffer)
+		goto out_free;
+
+	spin_lock_init(&as->lock);
+	INIT_LIST_HEAD(&as->queue);
+	as->pdev = pdev;
+	as->regs = ioremap(regs->start, (regs->end - regs->start) + 1);
+	if (!as->regs)
+		goto out_free_buffer;
+	as->irq = irq;
+	as->clk = clk;
+#ifdef CONFIG_ARCH_AT91
+	if (!cpu_is_at91rm9200())
+		as->new_1 = 1;
+#endif
+
+	ret = request_irq(irq, atmel_spi_interrupt, 0,
+			pdev->dev.bus_id, master);
+	if (ret)
+		goto out_unmap_regs;
+
+	/* Initialize the hardware */
+	clk_enable(clk);
+	spi_writel(as, CR, SPI_BIT(SWRST));
+	spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
+	spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+	spi_writel(as, CR, SPI_BIT(SPIEN));
+
+	/* go! */
+	dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n",
+			(unsigned long)regs->start, irq);
+
+	ret = spi_register_master(master);
+	if (ret)
+		goto out_reset_hw;
+
+	return 0;
+
+out_reset_hw:
+	spi_writel(as, CR, SPI_BIT(SWRST));
+	clk_disable(clk);
+	free_irq(irq, master);
+out_unmap_regs:
+	iounmap(as->regs);
+out_free_buffer:
+	dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
+			as->buffer_dma);
+out_free:
+	clk_put(clk);
+	spi_master_put(master);
+	return ret;
+}
+
+static int __exit atmel_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master	*master = platform_get_drvdata(pdev);
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	struct spi_message	*msg;
+
+	/* reset the hardware and block queue progress */
+	spin_lock_irq(&as->lock);
+	as->stopping = 1;
+	spi_writel(as, CR, SPI_BIT(SWRST));
+	spi_readl(as, SR);
+	spin_unlock_irq(&as->lock);
+
+	/* Terminate remaining queued transfers */
+	list_for_each_entry(msg, &as->queue, queue) {
+		/* REVISIT unmapping the dma is a NOP on ARM and AVR32
+		 * but we shouldn't depend on that...
+		 */
+		msg->status = -ESHUTDOWN;
+		msg->complete(msg->context);
+	}
+
+	dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
+			as->buffer_dma);
+
+	clk_disable(as->clk);
+	clk_put(as->clk);
+	free_irq(as->irq, master);
+	iounmap(as->regs);
+
+	spi_unregister_master(master);
+
+	return 0;
+}
+
+#ifdef	CONFIG_PM
+
+static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	struct spi_master	*master = platform_get_drvdata(pdev);
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+
+	clk_disable(as->clk);
+	return 0;
+}
+
+static int atmel_spi_resume(struct platform_device *pdev)
+{
+	struct spi_master	*master = platform_get_drvdata(pdev);
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+
+	clk_enable(as->clk);
+	return 0;
+}
+
+#else
+#define	atmel_spi_suspend	NULL
+#define	atmel_spi_resume	NULL
+#endif
+
+
+static struct platform_driver atmel_spi_driver = {
+	.driver		= {
+		.name	= "atmel_spi",
+		.owner	= THIS_MODULE,
+	},
+	.suspend	= atmel_spi_suspend,
+	.resume		= atmel_spi_resume,
+	.remove		= __exit_p(atmel_spi_remove),
+};
+
+static int __init atmel_spi_init(void)
+{
+	return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe);
+}
+module_init(atmel_spi_init);
+
+static void __exit atmel_spi_exit(void)
+{
+	platform_driver_unregister(&atmel_spi_driver);
+}
+module_exit(atmel_spi_exit);
+
+MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver");
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/atmel_spi.h b/drivers/spi/atmel_spi.h
new file mode 100644
index 0000000..6e06b6a
--- /dev/null
+++ b/drivers/spi/atmel_spi.h
@@ -0,0 +1,167 @@
+/*
+ * Register definitions for Atmel Serial Peripheral Interface (SPI)
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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 __ATMEL_SPI_H__
+#define __ATMEL_SPI_H__
+
+/* SPI register offsets */
+#define SPI_CR					0x0000
+#define SPI_MR					0x0004
+#define SPI_RDR					0x0008
+#define SPI_TDR					0x000c
+#define SPI_SR					0x0010
+#define SPI_IER					0x0014
+#define SPI_IDR					0x0018
+#define SPI_IMR					0x001c
+#define SPI_CSR0				0x0030
+#define SPI_CSR1				0x0034
+#define SPI_CSR2				0x0038
+#define SPI_CSR3				0x003c
+#define SPI_RPR					0x0100
+#define SPI_RCR					0x0104
+#define SPI_TPR					0x0108
+#define SPI_TCR					0x010c
+#define SPI_RNPR				0x0110
+#define SPI_RNCR				0x0114
+#define SPI_TNPR				0x0118
+#define SPI_TNCR				0x011c
+#define SPI_PTCR				0x0120
+#define SPI_PTSR				0x0124
+
+/* Bitfields in CR */
+#define SPI_SPIEN_OFFSET			0
+#define SPI_SPIEN_SIZE				1
+#define SPI_SPIDIS_OFFSET			1
+#define SPI_SPIDIS_SIZE				1
+#define SPI_SWRST_OFFSET			7
+#define SPI_SWRST_SIZE				1
+#define SPI_LASTXFER_OFFSET			24
+#define SPI_LASTXFER_SIZE			1
+
+/* Bitfields in MR */
+#define SPI_MSTR_OFFSET				0
+#define SPI_MSTR_SIZE				1
+#define SPI_PS_OFFSET				1
+#define SPI_PS_SIZE				1
+#define SPI_PCSDEC_OFFSET			2
+#define SPI_PCSDEC_SIZE				1
+#define SPI_FDIV_OFFSET				3
+#define SPI_FDIV_SIZE				1
+#define SPI_MODFDIS_OFFSET			4
+#define SPI_MODFDIS_SIZE			1
+#define SPI_LLB_OFFSET				7
+#define SPI_LLB_SIZE				1
+#define SPI_PCS_OFFSET				16
+#define SPI_PCS_SIZE				4
+#define SPI_DLYBCS_OFFSET			24
+#define SPI_DLYBCS_SIZE				8
+
+/* Bitfields in RDR */
+#define SPI_RD_OFFSET				0
+#define SPI_RD_SIZE				16
+
+/* Bitfields in TDR */
+#define SPI_TD_OFFSET				0
+#define SPI_TD_SIZE				16
+
+/* Bitfields in SR */
+#define SPI_RDRF_OFFSET				0
+#define SPI_RDRF_SIZE				1
+#define SPI_TDRE_OFFSET				1
+#define SPI_TDRE_SIZE				1
+#define SPI_MODF_OFFSET				2
+#define SPI_MODF_SIZE				1
+#define SPI_OVRES_OFFSET			3
+#define SPI_OVRES_SIZE				1
+#define SPI_ENDRX_OFFSET			4
+#define SPI_ENDRX_SIZE				1
+#define SPI_ENDTX_OFFSET			5
+#define SPI_ENDTX_SIZE				1
+#define SPI_RXBUFF_OFFSET			6
+#define SPI_RXBUFF_SIZE				1
+#define SPI_TXBUFE_OFFSET			7
+#define SPI_TXBUFE_SIZE				1
+#define SPI_NSSR_OFFSET				8
+#define SPI_NSSR_SIZE				1
+#define SPI_TXEMPTY_OFFSET			9
+#define SPI_TXEMPTY_SIZE			1
+#define SPI_SPIENS_OFFSET			16
+#define SPI_SPIENS_SIZE				1
+
+/* Bitfields in CSR0 */
+#define SPI_CPOL_OFFSET				0
+#define SPI_CPOL_SIZE				1
+#define SPI_NCPHA_OFFSET			1
+#define SPI_NCPHA_SIZE				1
+#define SPI_CSAAT_OFFSET			3
+#define SPI_CSAAT_SIZE				1
+#define SPI_BITS_OFFSET				4
+#define SPI_BITS_SIZE				4
+#define SPI_SCBR_OFFSET				8
+#define SPI_SCBR_SIZE				8
+#define SPI_DLYBS_OFFSET			16
+#define SPI_DLYBS_SIZE				8
+#define SPI_DLYBCT_OFFSET			24
+#define SPI_DLYBCT_SIZE				8
+
+/* Bitfields in RCR */
+#define SPI_RXCTR_OFFSET			0
+#define SPI_RXCTR_SIZE				16
+
+/* Bitfields in TCR */
+#define SPI_TXCTR_OFFSET			0
+#define SPI_TXCTR_SIZE				16
+
+/* Bitfields in RNCR */
+#define SPI_RXNCR_OFFSET			0
+#define SPI_RXNCR_SIZE				16
+
+/* Bitfields in TNCR */
+#define SPI_TXNCR_OFFSET			0
+#define SPI_TXNCR_SIZE				16
+
+/* Bitfields in PTCR */
+#define SPI_RXTEN_OFFSET			0
+#define SPI_RXTEN_SIZE				1
+#define SPI_RXTDIS_OFFSET			1
+#define SPI_RXTDIS_SIZE				1
+#define SPI_TXTEN_OFFSET			8
+#define SPI_TXTEN_SIZE				1
+#define SPI_TXTDIS_OFFSET			9
+#define SPI_TXTDIS_SIZE				1
+
+/* Constants for BITS */
+#define SPI_BITS_8_BPT				0
+#define SPI_BITS_9_BPT				1
+#define SPI_BITS_10_BPT				2
+#define SPI_BITS_11_BPT				3
+#define SPI_BITS_12_BPT				4
+#define SPI_BITS_13_BPT				5
+#define SPI_BITS_14_BPT				6
+#define SPI_BITS_15_BPT				7
+#define SPI_BITS_16_BPT				8
+
+/* Bit manipulation macros */
+#define SPI_BIT(name) \
+	(1 << SPI_##name##_OFFSET)
+#define SPI_BF(name,value) \
+	(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
+#define SPI_BFEXT(name,value) \
+	(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
+#define SPI_BFINS(name,value,old) \
+	( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
+	  | SPI_BF(name,value))
+
+/* Register access macros */
+#define spi_readl(port,reg) \
+	__raw_readl((port)->regs + SPI_##reg)
+#define spi_writel(port,reg,value) \
+	__raw_writel((value), (port)->regs + SPI_##reg)
+
+#endif /* __ATMEL_SPI_H__ */
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
new file mode 100644
index 0000000..96f62b2
--- /dev/null
+++ b/drivers/spi/omap_uwire.c
@@ -0,0 +1,572 @@
+/*
+ * omap_uwire.c -- MicroWire interface driver for OMAP
+ *
+ * Copyright 2003 MontaVista Software Inc. <source@mvista.com>
+ *
+ * Ported to 2.6 OMAP uwire interface.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * Generalization patches by Juha Yrjola <juha.yrjola@nokia.com>
+ *
+ * Copyright (C) 2005 David Brownell (ported to 2.6 SPI interface)
+ * Copyright (C) 2006 Nokia
+ *
+ * Many updates by Imre Deak <imre.deak@nokia.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/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/omap730.h>	/* OMAP730_IO_CONF registers */
+
+
+/* FIXME address is now a platform device resource,
+ * and irqs should show there too...
+ */
+#define UWIRE_BASE_PHYS		0xFFFB3000
+#define UWIRE_BASE		((void *__iomem)IO_ADDRESS(UWIRE_BASE_PHYS))
+
+/* uWire Registers: */
+#define UWIRE_IO_SIZE 0x20
+#define UWIRE_TDR     0x00
+#define UWIRE_RDR     0x00
+#define UWIRE_CSR     0x01
+#define UWIRE_SR1     0x02
+#define UWIRE_SR2     0x03
+#define UWIRE_SR3     0x04
+#define UWIRE_SR4     0x05
+#define UWIRE_SR5     0x06
+
+/* CSR bits */
+#define	RDRB	(1 << 15)
+#define	CSRB	(1 << 14)
+#define	START	(1 << 13)
+#define	CS_CMD	(1 << 12)
+
+/* SR1 or SR2 bits */
+#define UWIRE_READ_FALLING_EDGE		0x0001
+#define UWIRE_READ_RISING_EDGE		0x0000
+#define UWIRE_WRITE_FALLING_EDGE	0x0000
+#define UWIRE_WRITE_RISING_EDGE		0x0002
+#define UWIRE_CS_ACTIVE_LOW		0x0000
+#define UWIRE_CS_ACTIVE_HIGH		0x0004
+#define UWIRE_FREQ_DIV_2		0x0000
+#define UWIRE_FREQ_DIV_4		0x0008
+#define UWIRE_FREQ_DIV_8		0x0010
+#define UWIRE_CHK_READY			0x0020
+#define UWIRE_CLK_INVERTED		0x0040
+
+
+struct uwire_spi {
+	struct spi_bitbang	bitbang;
+	struct clk		*ck;
+};
+
+struct uwire_state {
+	unsigned	bits_per_word;
+	unsigned	div1_idx;
+};
+
+/* REVISIT compile time constant for idx_shift? */
+static unsigned int uwire_idx_shift;
+
+static inline void uwire_write_reg(int idx, u16 val)
+{
+	__raw_writew(val, UWIRE_BASE + (idx << uwire_idx_shift));
+}
+
+static inline u16 uwire_read_reg(int idx)
+{
+	return __raw_readw(UWIRE_BASE + (idx << uwire_idx_shift));
+}
+
+static inline void omap_uwire_configure_mode(u8 cs, unsigned long flags)
+{
+	u16	w, val = 0;
+	int	shift, reg;
+
+	if (flags & UWIRE_CLK_INVERTED)
+		val ^= 0x03;
+	val = flags & 0x3f;
+	if (cs & 1)
+		shift = 6;
+	else
+		shift = 0;
+	if (cs <= 1)
+		reg = UWIRE_SR1;
+	else
+		reg = UWIRE_SR2;
+
+	w = uwire_read_reg(reg);
+	w &= ~(0x3f << shift);
+	w |= val << shift;
+	uwire_write_reg(reg, w);
+}
+
+static int wait_uwire_csr_flag(u16 mask, u16 val, int might_not_catch)
+{
+	u16 w;
+	int c = 0;
+	unsigned long max_jiffies = jiffies + HZ;
+
+	for (;;) {
+		w = uwire_read_reg(UWIRE_CSR);
+		if ((w & mask) == val)
+			break;
+		if (time_after(jiffies, max_jiffies)) {
+			printk(KERN_ERR "%s: timeout. reg=%#06x "
+					"mask=%#06x val=%#06x\n",
+			       __FUNCTION__, w, mask, val);
+			return -1;
+		}
+		c++;
+		if (might_not_catch && c > 64)
+			break;
+	}
+	return 0;
+}
+
+static void uwire_set_clk1_div(int div1_idx)
+{
+	u16 w;
+
+	w = uwire_read_reg(UWIRE_SR3);
+	w &= ~(0x03 << 1);
+	w |= div1_idx << 1;
+	uwire_write_reg(UWIRE_SR3, w);
+}
+
+static void uwire_chipselect(struct spi_device *spi, int value)
+{
+	struct	uwire_state *ust = spi->controller_state;
+	u16	w;
+	int	old_cs;
+
+
+	BUG_ON(wait_uwire_csr_flag(CSRB, 0, 0));
+
+	w = uwire_read_reg(UWIRE_CSR);
+	old_cs = (w >> 10) & 0x03;
+	if (value == BITBANG_CS_INACTIVE || old_cs != spi->chip_select) {
+		/* Deselect this CS, or the previous CS */
+		w &= ~CS_CMD;
+		uwire_write_reg(UWIRE_CSR, w);
+	}
+	/* activate specfied chipselect */
+	if (value == BITBANG_CS_ACTIVE) {
+		uwire_set_clk1_div(ust->div1_idx);
+		/* invert clock? */
+		if (spi->mode & SPI_CPOL)
+			uwire_write_reg(UWIRE_SR4, 1);
+		else
+			uwire_write_reg(UWIRE_SR4, 0);
+
+		w = spi->chip_select << 10;
+		w |= CS_CMD;
+		uwire_write_reg(UWIRE_CSR, w);
+	}
+}
+
+static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct uwire_state *ust = spi->controller_state;
+	unsigned	len = t->len;
+	unsigned	bits = ust->bits_per_word;
+	unsigned	bytes;
+	u16		val, w;
+	int		status = 0;;
+
+	if (!t->tx_buf && !t->rx_buf)
+		return 0;
+
+	/* Microwire doesn't read and write concurrently */
+	if (t->tx_buf && t->rx_buf)
+		return -EPERM;
+
+	w = spi->chip_select << 10;
+	w |= CS_CMD;
+
+	if (t->tx_buf) {
+		const u8	*buf = t->tx_buf;
+
+		/* NOTE:  DMA could be used for TX transfers */
+
+		/* write one or two bytes at a time */
+		while (len >= 1) {
+			/* tx bit 15 is first sent; we byteswap multibyte words
+			 * (msb-first) on the way out from memory.
+			 */
+			val = *buf++;
+			if (bits > 8) {
+				bytes = 2;
+				val |= *buf++ << 8;
+			} else
+				bytes = 1;
+			val <<= 16 - bits;
+
+#ifdef	VERBOSE
+			pr_debug("%s: write-%d =%04x\n",
+					spi->dev.bus_id, bits, val);
+#endif
+			if (wait_uwire_csr_flag(CSRB, 0, 0))
+				goto eio;
+
+			uwire_write_reg(UWIRE_TDR, val);
+
+			/* start write */
+			val = START | w | (bits << 5);
+
+			uwire_write_reg(UWIRE_CSR, val);
+			len -= bytes;
+
+			/* Wait till write actually starts.
+			 * This is needed with MPU clock 60+ MHz.
+			 * REVISIT: we may not have time to catch it...
+			 */
+			if (wait_uwire_csr_flag(CSRB, CSRB, 1))
+				goto eio;
+
+			status += bytes;
+		}
+
+		/* REVISIT:  save this for later to get more i/o overlap */
+		if (wait_uwire_csr_flag(CSRB, 0, 0))
+			goto eio;
+
+	} else if (t->rx_buf) {
+		u8		*buf = t->rx_buf;
+
+		/* read one or two bytes at a time */
+		while (len) {
+			if (bits > 8) {
+				bytes = 2;
+			} else
+				bytes = 1;
+
+			/* start read */
+			val = START | w | (bits << 0);
+			uwire_write_reg(UWIRE_CSR, val);
+			len -= bytes;
+
+			/* Wait till read actually starts */
+			(void) wait_uwire_csr_flag(CSRB, CSRB, 1);
+
+			if (wait_uwire_csr_flag(RDRB | CSRB,
+						RDRB, 0))
+				goto eio;
+
+			/* rx bit 0 is last received; multibyte words will
+			 * be properly byteswapped on the way to memory.
+			 */
+			val = uwire_read_reg(UWIRE_RDR);
+			val &= (1 << bits) - 1;
+			*buf++ = (u8) val;
+			if (bytes == 2)
+				*buf++ = val >> 8;
+			status += bytes;
+#ifdef	VERBOSE
+			pr_debug("%s: read-%d =%04x\n",
+					spi->dev.bus_id, bits, val);
+#endif
+
+		}
+	}
+	return status;
+eio:
+	return -EIO;
+}
+
+static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct uwire_state	*ust = spi->controller_state;
+	struct uwire_spi	*uwire;
+	unsigned		flags = 0;
+	unsigned		bits;
+	unsigned		hz;
+	unsigned long		rate;
+	int			div1_idx;
+	int			div1;
+	int			div2;
+	int			status;
+
+	uwire = spi_master_get_devdata(spi->master);
+
+	if (spi->chip_select > 3) {
+		pr_debug("%s: cs%d?\n", spi->dev.bus_id, spi->chip_select);
+		status = -ENODEV;
+		goto done;
+	}
+
+	bits = spi->bits_per_word;
+	if (t != NULL && t->bits_per_word)
+		bits = t->bits_per_word;
+	if (!bits)
+		bits = 8;
+
+	if (bits > 16) {
+		pr_debug("%s: wordsize %d?\n", spi->dev.bus_id, bits);
+		status = -ENODEV;
+		goto done;
+	}
+	ust->bits_per_word = bits;
+
+	/* mode 0..3, clock inverted separately;
+	 * standard nCS signaling;
+	 * don't treat DI=high as "not ready"
+	 */
+	if (spi->mode & SPI_CS_HIGH)
+		flags |= UWIRE_CS_ACTIVE_HIGH;
+
+	if (spi->mode & SPI_CPOL)
+		flags |= UWIRE_CLK_INVERTED;
+
+	switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
+	case SPI_MODE_0:
+	case SPI_MODE_3:
+		flags |= UWIRE_WRITE_RISING_EDGE | UWIRE_READ_FALLING_EDGE;
+		break;
+	case SPI_MODE_1:
+	case SPI_MODE_2:
+		flags |= UWIRE_WRITE_FALLING_EDGE | UWIRE_READ_RISING_EDGE;
+		break;
+	}
+
+	/* assume it's already enabled */
+	rate = clk_get_rate(uwire->ck);
+
+	hz = spi->max_speed_hz;
+	if (t != NULL && t->speed_hz)
+		hz = t->speed_hz;
+
+	if (!hz) {
+		pr_debug("%s: zero speed?\n", spi->dev.bus_id);
+		status = -EINVAL;
+		goto done;
+	}
+
+	/* F_INT = mpu_xor_clk / DIV1 */
+	for (div1_idx = 0; div1_idx < 4; div1_idx++) {
+		switch (div1_idx) {
+		case 0:
+			div1 = 2;
+			break;
+		case 1:
+			div1 = 4;
+			break;
+		case 2:
+			div1 = 7;
+			break;
+		default:
+		case 3:
+			div1 = 10;
+			break;
+		}
+		div2 = (rate / div1 + hz - 1) / hz;
+		if (div2 <= 8)
+			break;
+	}
+	if (div1_idx == 4) {
+		pr_debug("%s: lowest clock %ld, need %d\n",
+			spi->dev.bus_id, rate / 10 / 8, hz);
+		status = -EDOM;
+		goto done;
+	}
+
+	/* we have to cache this and reset in uwire_chipselect as this is a
+	 * global parameter and another uwire device can change it under
+	 * us */
+	ust->div1_idx = div1_idx;
+	uwire_set_clk1_div(div1_idx);
+
+	rate /= div1;
+
+	switch (div2) {
+	case 0:
+	case 1:
+	case 2:
+		flags |= UWIRE_FREQ_DIV_2;
+		rate /= 2;
+		break;
+	case 3:
+	case 4:
+		flags |= UWIRE_FREQ_DIV_4;
+		rate /= 4;
+		break;
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+		flags |= UWIRE_FREQ_DIV_8;
+		rate /= 8;
+		break;
+	}
+	omap_uwire_configure_mode(spi->chip_select, flags);
+	pr_debug("%s: uwire flags %02x, armxor %lu KHz, SCK %lu KHz\n",
+			__FUNCTION__, flags,
+			clk_get_rate(uwire->ck) / 1000,
+			rate / 1000);
+	status = 0;
+done:
+	return status;
+}
+
+static int uwire_setup(struct spi_device *spi)
+{
+	struct uwire_state *ust = spi->controller_state;
+
+	if (ust == NULL) {
+		ust = kzalloc(sizeof(*ust), GFP_KERNEL);
+		if (ust == NULL)
+			return -ENOMEM;
+		spi->controller_state = ust;
+	}
+
+	return uwire_setup_transfer(spi, NULL);
+}
+
+static void uwire_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+static void uwire_off(struct uwire_spi *uwire)
+{
+	uwire_write_reg(UWIRE_SR3, 0);
+	clk_disable(uwire->ck);
+	clk_put(uwire->ck);
+	spi_master_put(uwire->bitbang.master);
+}
+
+static int uwire_probe(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct uwire_spi	*uwire;
+	int			status;
+
+	master = spi_alloc_master(&pdev->dev, sizeof *uwire);
+	if (!master)
+		return -ENODEV;
+
+	uwire = spi_master_get_devdata(master);
+	dev_set_drvdata(&pdev->dev, uwire);
+
+	uwire->ck = clk_get(&pdev->dev, "armxor_ck");
+	if (!uwire->ck || IS_ERR(uwire->ck)) {
+		dev_dbg(&pdev->dev, "no mpu_xor_clk ?\n");
+		spi_master_put(master);
+		return -ENODEV;
+	}
+	clk_enable(uwire->ck);
+
+	if (cpu_is_omap730())
+		uwire_idx_shift = 1;
+	else
+		uwire_idx_shift = 2;
+
+	uwire_write_reg(UWIRE_SR3, 1);
+
+	master->bus_num = 2;	/* "official" */
+	master->num_chipselect = 4;
+	master->setup = uwire_setup;
+	master->cleanup = uwire_cleanup;
+
+	uwire->bitbang.master = master;
+	uwire->bitbang.chipselect = uwire_chipselect;
+	uwire->bitbang.setup_transfer = uwire_setup_transfer;
+	uwire->bitbang.txrx_bufs = uwire_txrx;
+
+	status = spi_bitbang_start(&uwire->bitbang);
+	if (status < 0)
+		uwire_off(uwire);
+	return status;
+}
+
+static int uwire_remove(struct platform_device *pdev)
+{
+	struct uwire_spi	*uwire = dev_get_drvdata(&pdev->dev);
+	int			status;
+
+	// FIXME remove all child devices, somewhere ...
+
+	status = spi_bitbang_stop(&uwire->bitbang);
+	uwire_off(uwire);
+	return status;
+}
+
+static struct platform_driver uwire_driver = {
+	.driver = {
+		.name		= "omap_uwire",
+		.bus		= &platform_bus_type,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= uwire_probe,
+	.remove		= uwire_remove,
+	// suspend ... unuse ck
+	// resume ... use ck
+};
+
+static int __init omap_uwire_init(void)
+{
+	/* FIXME move these into the relevant board init code. also, include
+	 * H3 support; it uses tsc2101 like H2 (on a different chipselect).
+	 */
+
+	if (machine_is_omap_h2()) {
+		/* defaults: W21 SDO, U18 SDI, V19 SCL */
+		omap_cfg_reg(N14_1610_UWIRE_CS0);
+		omap_cfg_reg(N15_1610_UWIRE_CS1);
+	}
+	if (machine_is_omap_perseus2()) {
+		/* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */
+		int val = omap_readl(OMAP730_IO_CONF_9) & ~0x00EEE000;
+		omap_writel(val | 0x00AAA000, OMAP730_IO_CONF_9);
+	}
+
+	return platform_driver_register(&uwire_driver);
+}
+
+static void __exit omap_uwire_exit(void)
+{
+	platform_driver_unregister(&uwire_driver);
+}
+
+subsys_initcall(omap_uwire_init);
+module_exit(omap_uwire_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 8b41f9c..9f2c887 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1214,9 +1214,9 @@
 	return 0;
 }
 
-static void cleanup(const struct spi_device *spi)
+static void cleanup(struct spi_device *spi)
 {
-	struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
+	struct chip_data *chip = spi_get_ctldata(spi);
 
 	kfree(chip);
 }
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 6307428..2328128 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -32,7 +32,7 @@
  */
 static void spidev_release(struct device *dev)
 {
-	const struct spi_device	*spi = to_spi_device(dev);
+	struct spi_device	*spi = to_spi_device(dev);
 
 	/* spi masters may cleanup for released devices */
 	if (spi->master->cleanup)
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 57289b6..24a330d 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -210,7 +210,7 @@
 	if (!cs->txrx_word)
 		return -EINVAL;
 
-	retval = spi_bitbang_setup_transfer(spi, NULL);
+	retval = bitbang->setup_transfer(spi, NULL);
 	if (retval < 0)
 		return retval;
 
@@ -238,7 +238,7 @@
 /**
  * spi_bitbang_cleanup - default cleanup for per-word I/O loops
  */
-void spi_bitbang_cleanup(const struct spi_device *spi)
+void spi_bitbang_cleanup(struct spi_device *spi)
 {
 	kfree(spi->controller_state);
 }
@@ -442,9 +442,10 @@
  * hardware that basically exposes a shift register) or per-spi_transfer
  * (which takes better advantage of hardware like fifos or DMA engines).
  *
- * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup and
- * spi_bitbang_cleanup to handle those spi master methods.  Those methods are
- * the defaults if the bitbang->txrx_bufs routine isn't initialized.
+ * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup,
+ * spi_bitbang_cleanup and spi_bitbang_setup_transfer to handle those spi
+ * master methods.  Those methods are the defaults if the bitbang->txrx_bufs
+ * routine isn't initialized.
  *
  * This routine registers the spi_master, which will process requests in a
  * dedicated task, keeping IRQs unblocked most of the time.  To stop
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
new file mode 100644
index 0000000..51daa21
--- /dev/null
+++ b/drivers/spi/spi_imx.c
@@ -0,0 +1,1768 @@
+/*
+ * drivers/spi/spi_imx.c
+ *
+ * Copyright (C) 2006 SWAPP
+ *	Andrea Paterniani <a.paterniani@swapp-eng.it>
+ *
+ * Initial version inspired by:
+ *	linux-2.6.17-rc3-mm1/drivers/spi/pxa2xx_spi.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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/delay.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/imx-dma.h>
+#include <asm/arch/spi_imx.h>
+
+/*-------------------------------------------------------------------------*/
+/* SPI Registers offsets from peripheral base address */
+#define SPI_RXDATA		(0x00)
+#define SPI_TXDATA		(0x04)
+#define SPI_CONTROL		(0x08)
+#define SPI_INT_STATUS		(0x0C)
+#define SPI_TEST		(0x10)
+#define SPI_PERIOD		(0x14)
+#define SPI_DMA			(0x18)
+#define SPI_RESET		(0x1C)
+
+/* SPI Control Register Bit Fields & Masks */
+#define SPI_CONTROL_BITCOUNT_MASK	(0xF)		/* Bit Count Mask */
+#define SPI_CONTROL_BITCOUNT(n)		(((n) - 1) & SPI_CONTROL_BITCOUNT_MASK)
+#define SPI_CONTROL_POL			(0x1 << 4)      /* Clock Polarity Mask */
+#define SPI_CONTROL_POL_ACT_HIGH	(0x0 << 4)      /* Active high pol. (0=idle) */
+#define SPI_CONTROL_POL_ACT_LOW		(0x1 << 4)      /* Active low pol. (1=idle) */
+#define SPI_CONTROL_PHA			(0x1 << 5)      /* Clock Phase Mask */
+#define SPI_CONTROL_PHA_0		(0x0 << 5)      /* Clock Phase 0 */
+#define SPI_CONTROL_PHA_1		(0x1 << 5)      /* Clock Phase 1 */
+#define SPI_CONTROL_SSCTL		(0x1 << 6)      /* /SS Waveform Select Mask */
+#define SPI_CONTROL_SSCTL_0		(0x0 << 6)      /* Master: /SS stays low between SPI burst
+							   Slave: RXFIFO advanced by BIT_COUNT */
+#define SPI_CONTROL_SSCTL_1		(0x1 << 6)      /* Master: /SS insert pulse between SPI burst
+							   Slave: RXFIFO advanced by /SS rising edge */
+#define SPI_CONTROL_SSPOL		(0x1 << 7)      /* /SS Polarity Select Mask */
+#define SPI_CONTROL_SSPOL_ACT_LOW	(0x0 << 7)      /* /SS Active low */
+#define SPI_CONTROL_SSPOL_ACT_HIGH	(0x1 << 7)      /* /SS Active high */
+#define SPI_CONTROL_XCH			(0x1 << 8)      /* Exchange */
+#define SPI_CONTROL_SPIEN		(0x1 << 9)      /* SPI Module Enable */
+#define SPI_CONTROL_MODE		(0x1 << 10)     /* SPI Mode Select Mask */
+#define SPI_CONTROL_MODE_SLAVE		(0x0 << 10)     /* SPI Mode Slave */
+#define SPI_CONTROL_MODE_MASTER		(0x1 << 10)     /* SPI Mode Master */
+#define SPI_CONTROL_DRCTL		(0x3 << 11)     /* /SPI_RDY Control Mask */
+#define SPI_CONTROL_DRCTL_0		(0x0 << 11)     /* Ignore /SPI_RDY */
+#define SPI_CONTROL_DRCTL_1		(0x1 << 11)     /* /SPI_RDY falling edge triggers input */
+#define SPI_CONTROL_DRCTL_2		(0x2 << 11)     /* /SPI_RDY active low level triggers input */
+#define SPI_CONTROL_DATARATE		(0x7 << 13)     /* Data Rate Mask */
+#define SPI_PERCLK2_DIV_MIN		(0)		/* PERCLK2:4 */
+#define SPI_PERCLK2_DIV_MAX		(7)		/* PERCLK2:512 */
+#define SPI_CONTROL_DATARATE_MIN	(SPI_PERCLK2_DIV_MAX << 13)
+#define SPI_CONTROL_DATARATE_MAX	(SPI_PERCLK2_DIV_MIN << 13)
+#define SPI_CONTROL_DATARATE_BAD	(SPI_CONTROL_DATARATE_MIN + 1)
+
+/* SPI Interrupt/Status Register Bit Fields & Masks */
+#define SPI_STATUS_TE	(0x1 << 0)	/* TXFIFO Empty Status */
+#define SPI_STATUS_TH	(0x1 << 1)      /* TXFIFO Half Status */
+#define SPI_STATUS_TF	(0x1 << 2)      /* TXFIFO Full Status */
+#define SPI_STATUS_RR	(0x1 << 3)      /* RXFIFO Data Ready Status */
+#define SPI_STATUS_RH	(0x1 << 4)      /* RXFIFO Half Status */
+#define SPI_STATUS_RF	(0x1 << 5)      /* RXFIFO Full Status */
+#define SPI_STATUS_RO	(0x1 << 6)      /* RXFIFO Overflow */
+#define SPI_STATUS_BO	(0x1 << 7)      /* Bit Count Overflow */
+#define SPI_STATUS	(0xFF)		/* SPI Status Mask */
+#define SPI_INTEN_TE	(0x1 << 8)      /* TXFIFO Empty Interrupt Enable */
+#define SPI_INTEN_TH	(0x1 << 9)      /* TXFIFO Half Interrupt Enable */
+#define SPI_INTEN_TF	(0x1 << 10)     /* TXFIFO Full Interrupt Enable */
+#define SPI_INTEN_RE	(0x1 << 11)     /* RXFIFO Data Ready Interrupt Enable */
+#define SPI_INTEN_RH	(0x1 << 12)     /* RXFIFO Half Interrupt Enable */
+#define SPI_INTEN_RF	(0x1 << 13)     /* RXFIFO Full Interrupt Enable */
+#define SPI_INTEN_RO	(0x1 << 14)     /* RXFIFO Overflow Interrupt Enable */
+#define SPI_INTEN_BO	(0x1 << 15)     /* Bit Count Overflow Interrupt Enable */
+#define SPI_INTEN	(0xFF << 8)	/* SPI Interrupt Enable Mask */
+
+/* SPI Test Register Bit Fields & Masks */
+#define SPI_TEST_TXCNT		(0xF << 0)	/* TXFIFO Counter */
+#define SPI_TEST_RXCNT_LSB	(4)		/* RXFIFO Counter LSB */
+#define SPI_TEST_RXCNT		(0xF << 4)	/* RXFIFO Counter */
+#define SPI_TEST_SSTATUS	(0xF << 8)	/* State Machine Status */
+#define SPI_TEST_LBC		(0x1 << 14)	/* Loop Back Control */
+
+/* SPI Period Register Bit Fields & Masks */
+#define SPI_PERIOD_WAIT		(0x7FFF << 0)	/* Wait Between Transactions */
+#define SPI_PERIOD_MAX_WAIT	(0x7FFF)	/* Max Wait Between
+							Transactions */
+#define SPI_PERIOD_CSRC		(0x1 << 15)	/* Period Clock Source Mask */
+#define SPI_PERIOD_CSRC_BCLK	(0x0 << 15)	/* Period Clock Source is
+							Bit Clock */
+#define SPI_PERIOD_CSRC_32768	(0x1 << 15)	/* Period Clock Source is
+							32.768 KHz Clock */
+
+/* SPI DMA Register Bit Fields & Masks */
+#define SPI_DMA_RHDMA	(0xF << 4)	/* RXFIFO Half Status */
+#define SPI_DMA_RFDMA	(0x1 << 5)      /* RXFIFO Full Status */
+#define SPI_DMA_TEDMA	(0x1 << 6)      /* TXFIFO Empty Status */
+#define SPI_DMA_THDMA	(0x1 << 7)      /* TXFIFO Half Status */
+#define SPI_DMA_RHDEN	(0x1 << 12)	/* RXFIFO Half DMA Request Enable */
+#define SPI_DMA_RFDEN	(0x1 << 13)     /* RXFIFO Full DMA Request Enable */
+#define SPI_DMA_TEDEN	(0x1 << 14)     /* TXFIFO Empty DMA Request Enable */
+#define SPI_DMA_THDEN	(0x1 << 15)     /* TXFIFO Half DMA Request Enable */
+
+/* SPI Soft Reset Register Bit Fields & Masks */
+#define SPI_RESET_START	(0x1)		/* Start */
+
+/* Default SPI configuration values */
+#define SPI_DEFAULT_CONTROL		\
+(					\
+	SPI_CONTROL_BITCOUNT(16) | 	\
+	SPI_CONTROL_POL_ACT_HIGH |	\
+	SPI_CONTROL_PHA_0 |		\
+	SPI_CONTROL_SPIEN |		\
+	SPI_CONTROL_SSCTL_1 |		\
+	SPI_CONTROL_MODE_MASTER |	\
+	SPI_CONTROL_DRCTL_0 |		\
+	SPI_CONTROL_DATARATE_MIN	\
+)
+#define SPI_DEFAULT_ENABLE_LOOPBACK	(0)
+#define SPI_DEFAULT_ENABLE_DMA		(0)
+#define SPI_DEFAULT_PERIOD_WAIT		(8)
+/*-------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/* TX/RX SPI FIFO size */
+#define SPI_FIFO_DEPTH			(8)
+#define SPI_FIFO_BYTE_WIDTH		(2)
+#define SPI_FIFO_OVERFLOW_MARGIN	(2)
+
+/* DMA burst lenght for half full/empty request trigger */
+#define SPI_DMA_BLR			(SPI_FIFO_DEPTH * SPI_FIFO_BYTE_WIDTH / 2)
+
+/* Dummy char output to achieve reads.
+   Choosing something different from all zeroes may help pattern recogition
+   for oscilloscope analysis, but may break some drivers. */
+#define SPI_DUMMY_u8			0
+#define SPI_DUMMY_u16			((SPI_DUMMY_u8 << 8) | SPI_DUMMY_u8)
+#define SPI_DUMMY_u32			((SPI_DUMMY_u16 << 16) | SPI_DUMMY_u16)
+
+/**
+ * Macro to change a u32 field:
+ * @r : register to edit
+ * @m : bit mask
+ * @v : new value for the field correctly bit-alligned
+*/
+#define u32_EDIT(r, m, v)		r = (r & ~(m)) | (v)
+
+/* Message state */
+#define START_STATE			((void*)0)
+#define RUNNING_STATE			((void*)1)
+#define DONE_STATE			((void*)2)
+#define ERROR_STATE			((void*)-1)
+
+/* Queue state */
+#define QUEUE_RUNNING			(0)
+#define QUEUE_STOPPED			(1)
+
+#define IS_DMA_ALIGNED(x) 		(((u32)(x) & 0x03) == 0)
+/*-------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/* Driver data structs */
+
+/* Context */
+struct driver_data {
+	/* Driver model hookup */
+	struct platform_device *pdev;
+
+	/* SPI framework hookup */
+	struct spi_master *master;
+
+	/* IMX hookup */
+	struct spi_imx_master *master_info;
+
+	/* Memory resources and SPI regs virtual address */
+	struct resource *ioarea;
+	void __iomem *regs;
+
+	/* SPI RX_DATA physical address */
+	dma_addr_t rd_data_phys;
+
+	/* Driver message queue */
+	struct workqueue_struct	*workqueue;
+	struct work_struct work;
+	spinlock_t lock;
+	struct list_head queue;
+	int busy;
+	int run;
+
+	/* Message Transfer pump */
+	struct tasklet_struct pump_transfers;
+
+	/* Current message, transfer and state */
+	struct spi_message *cur_msg;
+	struct spi_transfer *cur_transfer;
+	struct chip_data *cur_chip;
+
+	/* Rd / Wr buffers pointers */
+	size_t len;
+	void *tx;
+	void *tx_end;
+	void *rx;
+	void *rx_end;
+
+	u8 rd_only;
+	u8 n_bytes;
+	int cs_change;
+
+	/* Function pointers */
+	irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
+	void (*cs_control)(u32 command);
+
+	/* DMA setup */
+	int rx_channel;
+	int tx_channel;
+	dma_addr_t rx_dma;
+	dma_addr_t tx_dma;
+	int rx_dma_needs_unmap;
+	int tx_dma_needs_unmap;
+	size_t tx_map_len;
+	u32 dummy_dma_buf ____cacheline_aligned;
+};
+
+/* Runtime state */
+struct chip_data {
+	u32 control;
+	u32 period;
+	u32 test;
+
+	u8 enable_dma:1;
+	u8 bits_per_word;
+	u8 n_bytes;
+	u32 max_speed_hz;
+
+	void (*cs_control)(u32 command);
+};
+/*-------------------------------------------------------------------------*/
+
+
+static void pump_messages(struct work_struct *work);
+
+static int flush(struct driver_data *drv_data)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+	void __iomem *regs = drv_data->regs;
+	volatile u32 d;
+
+	dev_dbg(&drv_data->pdev->dev, "flush\n");
+	do {
+		while (readl(regs + SPI_INT_STATUS) & SPI_STATUS_RR)
+			d = readl(regs + SPI_RXDATA);
+	} while ((readl(regs + SPI_CONTROL) & SPI_CONTROL_XCH) && limit--);
+
+	return limit;
+}
+
+static void restore_state(struct driver_data *drv_data)
+{
+	void __iomem *regs = drv_data->regs;
+	struct chip_data *chip = drv_data->cur_chip;
+
+	/* Load chip registers */
+	dev_dbg(&drv_data->pdev->dev,
+		"restore_state\n"
+		"    test    = 0x%08X\n"
+		"    control = 0x%08X\n",
+		chip->test,
+		chip->control);
+	writel(chip->test, regs + SPI_TEST);
+	writel(chip->period, regs + SPI_PERIOD);
+	writel(0, regs + SPI_INT_STATUS);
+	writel(chip->control, regs + SPI_CONTROL);
+}
+
+static void null_cs_control(u32 command)
+{
+}
+
+static inline u32 data_to_write(struct driver_data *drv_data)
+{
+	return ((u32)(drv_data->tx_end - drv_data->tx)) / drv_data->n_bytes;
+}
+
+static inline u32 data_to_read(struct driver_data *drv_data)
+{
+	return ((u32)(drv_data->rx_end - drv_data->rx)) / drv_data->n_bytes;
+}
+
+static int write(struct driver_data *drv_data)
+{
+	void __iomem *regs = drv_data->regs;
+	void *tx = drv_data->tx;
+	void *tx_end = drv_data->tx_end;
+	u8 n_bytes = drv_data->n_bytes;
+	u32 remaining_writes;
+	u32 fifo_avail_space;
+	u32 n;
+	u16 d;
+
+	/* Compute how many fifo writes to do */
+	remaining_writes = (u32)(tx_end - tx) / n_bytes;
+	fifo_avail_space = SPI_FIFO_DEPTH -
+				(readl(regs + SPI_TEST) & SPI_TEST_TXCNT);
+	if (drv_data->rx && (fifo_avail_space > SPI_FIFO_OVERFLOW_MARGIN))
+		/* Fix misunderstood receive overflow */
+		fifo_avail_space -= SPI_FIFO_OVERFLOW_MARGIN;
+	n = min(remaining_writes, fifo_avail_space);
+
+	dev_dbg(&drv_data->pdev->dev,
+		"write type %s\n"
+		"    remaining writes = %d\n"
+		"    fifo avail space = %d\n"
+		"    fifo writes      = %d\n",
+		(n_bytes == 1) ? "u8" : "u16",
+		remaining_writes,
+		fifo_avail_space,
+		n);
+
+	if (n > 0) {
+		/* Fill SPI TXFIFO */
+		if (drv_data->rd_only) {
+			tx += n * n_bytes;
+			while (n--)
+				writel(SPI_DUMMY_u16, regs + SPI_TXDATA);
+		} else {
+			if (n_bytes == 1) {
+				while (n--) {
+					d = *(u8*)tx;
+					writel(d, regs + SPI_TXDATA);
+					tx += 1;
+				}
+			} else {
+				while (n--) {
+					d = *(u16*)tx;
+					writel(d, regs + SPI_TXDATA);
+					tx += 2;
+				}
+			}
+		}
+
+		/* Trigger transfer */
+		writel(readl(regs + SPI_CONTROL) | SPI_CONTROL_XCH,
+			regs + SPI_CONTROL);
+
+		/* Update tx pointer */
+		drv_data->tx = tx;
+	}
+
+	return (tx >= tx_end);
+}
+
+static int read(struct driver_data *drv_data)
+{
+	void __iomem *regs = drv_data->regs;
+	void *rx = drv_data->rx;
+	void *rx_end = drv_data->rx_end;
+	u8 n_bytes = drv_data->n_bytes;
+	u32 remaining_reads;
+	u32 fifo_rxcnt;
+	u32 n;
+	u16 d;
+
+	/* Compute how many fifo reads to do */
+	remaining_reads = (u32)(rx_end - rx) / n_bytes;
+	fifo_rxcnt = (readl(regs + SPI_TEST) & SPI_TEST_RXCNT) >>
+			SPI_TEST_RXCNT_LSB;
+	n = min(remaining_reads, fifo_rxcnt);
+
+	dev_dbg(&drv_data->pdev->dev,
+		"read type %s\n"
+		"    remaining reads = %d\n"
+		"    fifo rx count   = %d\n"
+		"    fifo reads      = %d\n",
+		(n_bytes == 1) ? "u8" : "u16",
+		remaining_reads,
+		fifo_rxcnt,
+		n);
+
+	if (n > 0) {
+		/* Read SPI RXFIFO */
+		if (n_bytes == 1) {
+			while (n--) {
+				d = readl(regs + SPI_RXDATA);
+				*((u8*)rx) = d;
+				rx += 1;
+			}
+		} else {
+			while (n--) {
+				d = readl(regs + SPI_RXDATA);
+				*((u16*)rx) = d;
+				rx += 2;
+			}
+		}
+
+		/* Update rx pointer */
+		drv_data->rx = rx;
+	}
+
+	return (rx >= rx_end);
+}
+
+static void *next_transfer(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	struct spi_transfer *trans = drv_data->cur_transfer;
+
+	/* Move to next transfer */
+	if (trans->transfer_list.next != &msg->transfers) {
+		drv_data->cur_transfer =
+			list_entry(trans->transfer_list.next,
+					struct spi_transfer,
+					transfer_list);
+		return RUNNING_STATE;
+	}
+
+	return DONE_STATE;
+}
+
+static int map_dma_buffers(struct driver_data *drv_data)
+{
+	struct spi_message *msg;
+	struct device *dev;
+	void *buf;
+
+	drv_data->rx_dma_needs_unmap = 0;
+	drv_data->tx_dma_needs_unmap = 0;
+
+	if (!drv_data->master_info->enable_dma ||
+		!drv_data->cur_chip->enable_dma)
+			return -1;
+
+	msg = drv_data->cur_msg;
+	dev = &msg->spi->dev;
+	if (msg->is_dma_mapped) {
+		if (drv_data->tx_dma)
+			/* The caller provided at least dma and cpu virtual
+			   address for write; pump_transfers() will consider the
+			   transfer as write only if cpu rx virtual address is
+			   NULL */
+			return 0;
+
+		if (drv_data->rx_dma) {
+			/* The caller provided dma and cpu virtual address to
+			   performe read only transfer -->
+			   use drv_data->dummy_dma_buf for dummy writes to
+			   achive reads */
+			buf = &drv_data->dummy_dma_buf;
+			drv_data->tx_map_len = sizeof(drv_data->dummy_dma_buf);
+			drv_data->tx_dma = dma_map_single(dev,
+							buf,
+							drv_data->tx_map_len,
+							DMA_TO_DEVICE);
+			if (dma_mapping_error(drv_data->tx_dma))
+				return -1;
+
+			drv_data->tx_dma_needs_unmap = 1;
+
+			/* Flags transfer as rd_only for pump_transfers() DMA
+			   regs programming (should be redundant) */
+			drv_data->tx = NULL;
+
+			return 0;
+		}
+	}
+
+	if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
+		return -1;
+
+	/* NULL rx means write-only transfer and no map needed
+	   since rx DMA will not be used */
+	if (drv_data->rx) {
+		buf = drv_data->rx;
+		drv_data->rx_dma = dma_map_single(
+					dev,
+					buf,
+					drv_data->len,
+					DMA_FROM_DEVICE);
+		if (dma_mapping_error(drv_data->rx_dma))
+			return -1;
+		drv_data->rx_dma_needs_unmap = 1;
+	}
+
+	if (drv_data->tx == NULL) {
+		/* Read only message --> use drv_data->dummy_dma_buf for dummy
+		   writes to achive reads */
+		buf = &drv_data->dummy_dma_buf;
+		drv_data->tx_map_len = sizeof(drv_data->dummy_dma_buf);
+	} else {
+		buf = drv_data->tx;
+		drv_data->tx_map_len = drv_data->len;
+	}
+	drv_data->tx_dma = dma_map_single(dev,
+					buf,
+					drv_data->tx_map_len,
+					DMA_TO_DEVICE);
+	if (dma_mapping_error(drv_data->tx_dma)) {
+		if (drv_data->rx_dma) {
+			dma_unmap_single(dev,
+					drv_data->rx_dma,
+					drv_data->len,
+					DMA_FROM_DEVICE);
+			drv_data->rx_dma_needs_unmap = 0;
+		}
+		return -1;
+	}
+	drv_data->tx_dma_needs_unmap = 1;
+
+	return 0;
+}
+
+static void unmap_dma_buffers(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	struct device *dev = &msg->spi->dev;
+
+	if (drv_data->rx_dma_needs_unmap) {
+		dma_unmap_single(dev,
+				drv_data->rx_dma,
+				drv_data->len,
+				DMA_FROM_DEVICE);
+		drv_data->rx_dma_needs_unmap = 0;
+	}
+	if (drv_data->tx_dma_needs_unmap) {
+		dma_unmap_single(dev,
+				drv_data->tx_dma,
+				drv_data->tx_map_len,
+				DMA_TO_DEVICE);
+		drv_data->tx_dma_needs_unmap = 0;
+	}
+}
+
+/* Caller already set message->status (dma is already blocked) */
+static void giveback(struct spi_message *message, struct driver_data *drv_data)
+{
+	void __iomem *regs = drv_data->regs;
+
+	/* Bring SPI to sleep; restore_state() and pump_transfer()
+	   will do new setup */
+	writel(0, regs + SPI_INT_STATUS);
+	writel(0, regs + SPI_DMA);
+
+	drv_data->cs_control(SPI_CS_DEASSERT);
+
+	message->state = NULL;
+	if (message->complete)
+		message->complete(message->context);
+
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	queue_work(drv_data->workqueue, &drv_data->work);
+}
+
+static void dma_err_handler(int channel, void *data, int errcode)
+{
+	struct driver_data *drv_data = data;
+	struct spi_message *msg = drv_data->cur_msg;
+
+	dev_dbg(&drv_data->pdev->dev, "dma_err_handler\n");
+
+	/* Disable both rx and tx dma channels */
+	imx_dma_disable(drv_data->rx_channel);
+	imx_dma_disable(drv_data->tx_channel);
+
+	if (flush(drv_data) == 0)
+		dev_err(&drv_data->pdev->dev,
+				"dma_err_handler - flush failed\n");
+
+	unmap_dma_buffers(drv_data);
+
+	msg->state = ERROR_STATE;
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static void dma_tx_handler(int channel, void *data)
+{
+	struct driver_data *drv_data = data;
+
+	dev_dbg(&drv_data->pdev->dev, "dma_tx_handler\n");
+
+	imx_dma_disable(channel);
+
+	/* Now waits for TX FIFO empty */
+	writel(readl(drv_data->regs + SPI_INT_STATUS) | SPI_INTEN_TE,
+			drv_data->regs + SPI_INT_STATUS);
+}
+
+static irqreturn_t dma_transfer(struct driver_data *drv_data)
+{
+	u32 status;
+	struct spi_message *msg = drv_data->cur_msg;
+	void __iomem *regs = drv_data->regs;
+	unsigned long limit;
+
+	status = readl(regs + SPI_INT_STATUS);
+
+	if ((status & SPI_INTEN_RO) && (status & SPI_STATUS_RO)) {
+		writel(status & ~SPI_INTEN, regs + SPI_INT_STATUS);
+
+		imx_dma_disable(drv_data->rx_channel);
+		unmap_dma_buffers(drv_data);
+
+		if (flush(drv_data) == 0)
+			dev_err(&drv_data->pdev->dev,
+				"dma_transfer - flush failed\n");
+
+		dev_warn(&drv_data->pdev->dev,
+				"dma_transfer - fifo overun\n");
+
+		msg->state = ERROR_STATE;
+		tasklet_schedule(&drv_data->pump_transfers);
+
+		return IRQ_HANDLED;
+	}
+
+	if (status & SPI_STATUS_TE) {
+		writel(status & ~SPI_INTEN_TE, regs + SPI_INT_STATUS);
+
+		if (drv_data->rx) {
+			/* Wait end of transfer before read trailing data */
+			limit = loops_per_jiffy << 1;
+			while ((readl(regs + SPI_CONTROL) & SPI_CONTROL_XCH) &&
+					limit--);
+
+			if (limit == 0)
+				dev_err(&drv_data->pdev->dev,
+					"dma_transfer - end of tx failed\n");
+			else
+				dev_dbg(&drv_data->pdev->dev,
+					"dma_transfer - end of tx\n");
+
+			imx_dma_disable(drv_data->rx_channel);
+			unmap_dma_buffers(drv_data);
+
+			/* Calculate number of trailing data and read them */
+			dev_dbg(&drv_data->pdev->dev,
+				"dma_transfer - test = 0x%08X\n",
+				readl(regs + SPI_TEST));
+			drv_data->rx = drv_data->rx_end -
+					((readl(regs + SPI_TEST) &
+					SPI_TEST_RXCNT) >>
+					SPI_TEST_RXCNT_LSB)*drv_data->n_bytes;
+			read(drv_data);
+		} else {
+			/* Write only transfer */
+			unmap_dma_buffers(drv_data);
+
+			if (flush(drv_data) == 0)
+				dev_err(&drv_data->pdev->dev,
+					"dma_transfer - flush failed\n");
+		}
+
+		/* End of transfer, update total byte transfered */
+		msg->actual_length += drv_data->len;
+
+		/* Release chip select if requested, transfer delays are
+		   handled in pump_transfers() */
+		if (drv_data->cs_change)
+			drv_data->cs_control(SPI_CS_DEASSERT);
+
+		/* Move to next transfer */
+		msg->state = next_transfer(drv_data);
+
+		/* Schedule transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+
+		return IRQ_HANDLED;
+	}
+
+	/* Opps problem detected */
+	return IRQ_NONE;
+}
+
+static irqreturn_t interrupt_wronly_transfer(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	void __iomem *regs = drv_data->regs;
+	u32 status;
+	irqreturn_t handled = IRQ_NONE;
+
+	status = readl(regs + SPI_INT_STATUS);
+
+	while (status & SPI_STATUS_TH) {
+		dev_dbg(&drv_data->pdev->dev,
+			"interrupt_wronly_transfer - status = 0x%08X\n", status);
+
+		/* Pump data */
+		if (write(drv_data)) {
+			writel(readl(regs + SPI_INT_STATUS) & ~SPI_INTEN,
+				regs + SPI_INT_STATUS);
+
+			dev_dbg(&drv_data->pdev->dev,
+				"interrupt_wronly_transfer - end of tx\n");
+
+			if (flush(drv_data) == 0)
+				dev_err(&drv_data->pdev->dev,
+					"interrupt_wronly_transfer - "
+					"flush failed\n");
+
+			/* End of transfer, update total byte transfered */
+			msg->actual_length += drv_data->len;
+
+			/* Release chip select if requested, transfer delays are
+			   handled in pump_transfers */
+			if (drv_data->cs_change)
+				drv_data->cs_control(SPI_CS_DEASSERT);
+
+			/* Move to next transfer */
+			msg->state = next_transfer(drv_data);
+
+			/* Schedule transfer tasklet */
+			tasklet_schedule(&drv_data->pump_transfers);
+
+			return IRQ_HANDLED;
+		}
+
+		status = readl(regs + SPI_INT_STATUS);
+
+		/* We did something */
+		handled = IRQ_HANDLED;
+	}
+
+	return handled;
+}
+
+static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	void __iomem *regs = drv_data->regs;
+	u32 status;
+	irqreturn_t handled = IRQ_NONE;
+	unsigned long limit;
+
+	status = readl(regs + SPI_INT_STATUS);
+
+	while (status & (SPI_STATUS_TH | SPI_STATUS_RO)) {
+		dev_dbg(&drv_data->pdev->dev,
+			"interrupt_transfer - status = 0x%08X\n", status);
+
+		if (status & SPI_STATUS_RO) {
+			writel(readl(regs + SPI_INT_STATUS) & ~SPI_INTEN,
+				regs + SPI_INT_STATUS);
+
+			dev_warn(&drv_data->pdev->dev,
+				"interrupt_transfer - fifo overun\n"
+				"    data not yet written = %d\n"
+				"    data not yet read    = %d\n",
+				data_to_write(drv_data),
+				data_to_read(drv_data));
+
+			if (flush(drv_data) == 0)
+				dev_err(&drv_data->pdev->dev,
+					"interrupt_transfer - flush failed\n");
+
+			msg->state = ERROR_STATE;
+			tasklet_schedule(&drv_data->pump_transfers);
+
+			return IRQ_HANDLED;
+		}
+
+		/* Pump data */
+		read(drv_data);
+		if (write(drv_data)) {
+			writel(readl(regs + SPI_INT_STATUS) & ~SPI_INTEN,
+				regs + SPI_INT_STATUS);
+
+			dev_dbg(&drv_data->pdev->dev,
+				"interrupt_transfer - end of tx\n");
+
+			/* Read trailing bytes */
+			limit = loops_per_jiffy << 1;
+			while ((read(drv_data) == 0) && limit--);
+
+			if (limit == 0)
+				dev_err(&drv_data->pdev->dev,
+					"interrupt_transfer - "
+					"trailing byte read failed\n");
+			else
+				dev_dbg(&drv_data->pdev->dev,
+					"interrupt_transfer - end of rx\n");
+
+			/* End of transfer, update total byte transfered */
+			msg->actual_length += drv_data->len;
+
+			/* Release chip select if requested, transfer delays are
+			   handled in pump_transfers */
+			if (drv_data->cs_change)
+				drv_data->cs_control(SPI_CS_DEASSERT);
+
+			/* Move to next transfer */
+			msg->state = next_transfer(drv_data);
+
+			/* Schedule transfer tasklet */
+			tasklet_schedule(&drv_data->pump_transfers);
+
+			return IRQ_HANDLED;
+		}
+
+		status = readl(regs + SPI_INT_STATUS);
+
+		/* We did something */
+		handled = IRQ_HANDLED;
+	}
+
+	return handled;
+}
+
+static irqreturn_t spi_int(int irq, void *dev_id)
+{
+	struct driver_data *drv_data = (struct driver_data *)dev_id;
+
+	if (!drv_data->cur_msg) {
+		dev_err(&drv_data->pdev->dev,
+			"spi_int - bad message state\n");
+		/* Never fail */
+		return IRQ_HANDLED;
+	}
+
+	return drv_data->transfer_handler(drv_data);
+}
+
+static inline u32 spi_speed_hz(u32 data_rate)
+{
+	return imx_get_perclk2() / (4 << ((data_rate) >> 13));
+}
+
+static u32 spi_data_rate(u32 speed_hz)
+{
+	u32 div;
+	u32 quantized_hz = imx_get_perclk2() >> 2;
+
+	for (div = SPI_PERCLK2_DIV_MIN;
+		div <= SPI_PERCLK2_DIV_MAX;
+		div++, quantized_hz >>= 1) {
+			if (quantized_hz <= speed_hz)
+				/* Max available speed LEQ required speed */
+				return div << 13;
+	}
+	return SPI_CONTROL_DATARATE_BAD;
+}
+
+static void pump_transfers(unsigned long data)
+{
+	struct driver_data *drv_data = (struct driver_data *)data;
+	struct spi_message *message;
+	struct spi_transfer *transfer, *previous;
+	struct chip_data *chip;
+	void __iomem *regs;
+	u32 tmp, control;
+
+	dev_dbg(&drv_data->pdev->dev, "pump_transfer\n");
+
+	message = drv_data->cur_msg;
+
+	/* Handle for abort */
+	if (message->state == ERROR_STATE) {
+		message->status = -EIO;
+		giveback(message, drv_data);
+		return;
+	}
+
+	/* Handle end of message */
+	if (message->state == DONE_STATE) {
+		message->status = 0;
+		giveback(message, drv_data);
+		return;
+	}
+
+	chip = drv_data->cur_chip;
+
+	/* Delay if requested at end of transfer*/
+	transfer = drv_data->cur_transfer;
+	if (message->state == RUNNING_STATE) {
+		previous = list_entry(transfer->transfer_list.prev,
+					struct spi_transfer,
+					transfer_list);
+		if (previous->delay_usecs)
+			udelay(previous->delay_usecs);
+	} else {
+		/* START_STATE */
+		message->state = RUNNING_STATE;
+		drv_data->cs_control = chip->cs_control;
+	}
+
+	transfer = drv_data->cur_transfer;
+	drv_data->tx = (void *)transfer->tx_buf;
+	drv_data->tx_end = drv_data->tx + transfer->len;
+	drv_data->rx = transfer->rx_buf;
+	drv_data->rx_end = drv_data->rx + transfer->len;
+	drv_data->rx_dma = transfer->rx_dma;
+	drv_data->tx_dma = transfer->tx_dma;
+	drv_data->len = transfer->len;
+	drv_data->cs_change = transfer->cs_change;
+	drv_data->rd_only = (drv_data->tx == NULL);
+
+	regs = drv_data->regs;
+	control = readl(regs + SPI_CONTROL);
+
+	/* Bits per word setup */
+	tmp = transfer->bits_per_word;
+	if (tmp == 0) {
+		/* Use device setup */
+		tmp = chip->bits_per_word;
+		drv_data->n_bytes = chip->n_bytes;
+	} else
+		/* Use per-transfer setup */
+		drv_data->n_bytes = (tmp <= 8) ? 1 : 2;
+	u32_EDIT(control, SPI_CONTROL_BITCOUNT_MASK, tmp - 1);
+
+	/* Speed setup (surely valid because already checked) */
+	tmp = transfer->speed_hz;
+	if (tmp == 0)
+		tmp = chip->max_speed_hz;
+	tmp = spi_data_rate(tmp);
+	u32_EDIT(control, SPI_CONTROL_DATARATE, tmp);
+
+	writel(control, regs + SPI_CONTROL);
+
+	/* Assert device chip-select */
+	drv_data->cs_control(SPI_CS_ASSERT);
+
+	/* DMA cannot read/write SPI FIFOs other than 16 bits at a time; hence
+	   if bits_per_word is less or equal 8 PIO transfers are performed.
+	   Moreover DMA is convinient for transfer length bigger than FIFOs
+	   byte size. */
+	if ((drv_data->n_bytes == 2) &&
+		(drv_data->len > SPI_FIFO_DEPTH*SPI_FIFO_BYTE_WIDTH) &&
+		(map_dma_buffers(drv_data) == 0)) {
+		dev_dbg(&drv_data->pdev->dev,
+			"pump dma transfer\n"
+			"    tx      = %p\n"
+			"    tx_dma  = %08X\n"
+			"    rx      = %p\n"
+			"    rx_dma  = %08X\n"
+			"    len     = %d\n",
+			drv_data->tx,
+			(unsigned int)drv_data->tx_dma,
+			drv_data->rx,
+			(unsigned int)drv_data->rx_dma,
+			drv_data->len);
+
+		/* Ensure we have the correct interrupt handler */
+		drv_data->transfer_handler = dma_transfer;
+
+		/* Trigger transfer */
+		writel(readl(regs + SPI_CONTROL) | SPI_CONTROL_XCH,
+			regs + SPI_CONTROL);
+
+		/* Setup tx DMA */
+		if (drv_data->tx)
+			/* Linear source address */
+			CCR(drv_data->tx_channel) =
+				CCR_DMOD_FIFO |
+				CCR_SMOD_LINEAR |
+				CCR_SSIZ_32 | CCR_DSIZ_16 |
+				CCR_REN;
+		else
+			/* Read only transfer -> fixed source address for
+			   dummy write to achive read */
+			CCR(drv_data->tx_channel) =
+				CCR_DMOD_FIFO |
+				CCR_SMOD_FIFO |
+				CCR_SSIZ_32 | CCR_DSIZ_16 |
+				CCR_REN;
+
+		imx_dma_setup_single(
+			drv_data->tx_channel,
+			drv_data->tx_dma,
+			drv_data->len,
+			drv_data->rd_data_phys + 4,
+			DMA_MODE_WRITE);
+
+		if (drv_data->rx) {
+			/* Setup rx DMA for linear destination address */
+			CCR(drv_data->rx_channel) =
+				CCR_DMOD_LINEAR |
+				CCR_SMOD_FIFO |
+				CCR_DSIZ_32 | CCR_SSIZ_16 |
+				CCR_REN;
+			imx_dma_setup_single(
+				drv_data->rx_channel,
+				drv_data->rx_dma,
+				drv_data->len,
+				drv_data->rd_data_phys,
+				DMA_MODE_READ);
+			imx_dma_enable(drv_data->rx_channel);
+
+			/* Enable SPI interrupt */
+			writel(SPI_INTEN_RO, regs + SPI_INT_STATUS);
+
+			/* Set SPI to request DMA service on both
+			   Rx and Tx half fifo watermark */
+			writel(SPI_DMA_RHDEN | SPI_DMA_THDEN, regs + SPI_DMA);
+		} else
+			/* Write only access -> set SPI to request DMA
+			   service on Tx half fifo watermark */
+			writel(SPI_DMA_THDEN, regs + SPI_DMA);
+
+		imx_dma_enable(drv_data->tx_channel);
+	} else {
+		dev_dbg(&drv_data->pdev->dev,
+			"pump pio transfer\n"
+			"    tx      = %p\n"
+			"    rx      = %p\n"
+			"    len     = %d\n",
+			drv_data->tx,
+			drv_data->rx,
+			drv_data->len);
+
+		/* Ensure we have the correct interrupt handler	*/
+		if (drv_data->rx)
+			drv_data->transfer_handler = interrupt_transfer;
+		else
+			drv_data->transfer_handler = interrupt_wronly_transfer;
+
+		/* Enable SPI interrupt */
+		if (drv_data->rx)
+			writel(SPI_INTEN_TH | SPI_INTEN_RO,
+				regs + SPI_INT_STATUS);
+		else
+			writel(SPI_INTEN_TH, regs + SPI_INT_STATUS);
+	}
+}
+
+static void pump_messages(struct work_struct *work)
+{
+	struct driver_data *drv_data =
+				container_of(work, struct driver_data, work);
+	unsigned long flags;
+
+	/* Lock queue and check for queue work */
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
+		drv_data->busy = 0;
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Make sure we are not already running a message */
+	if (drv_data->cur_msg) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Extract head of queue */
+	drv_data->cur_msg = list_entry(drv_data->queue.next,
+					struct spi_message, queue);
+	list_del_init(&drv_data->cur_msg->queue);
+	drv_data->busy = 1;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	/* Initial message state */
+	drv_data->cur_msg->state = START_STATE;
+	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+						struct spi_transfer,
+						transfer_list);
+
+	/* Setup the SPI using the per chip configuration */
+	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+	restore_state(drv_data);
+
+	/* Mark as busy and launch transfers */
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static int transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	u32 min_speed_hz, max_speed_hz, tmp;
+	struct spi_transfer *trans;
+	unsigned long flags;
+
+	msg->actual_length = 0;
+
+	/* Per transfer setup check */
+	min_speed_hz = spi_speed_hz(SPI_CONTROL_DATARATE_MIN);
+	max_speed_hz = spi->max_speed_hz;
+	list_for_each_entry(trans, &msg->transfers, transfer_list) {
+		tmp = trans->bits_per_word;
+		if (tmp > 16) {
+			dev_err(&drv_data->pdev->dev,
+				"message rejected : "
+				"invalid transfer bits_per_word (%d bits)\n",
+				tmp);
+			goto msg_rejected;
+		}
+		tmp = trans->speed_hz;
+		if (tmp) {
+			if (tmp < min_speed_hz) {
+				dev_err(&drv_data->pdev->dev,
+					"message rejected : "
+					"device min speed (%d Hz) exceeds "
+					"required transfer speed (%d Hz)\n",
+					min_speed_hz,
+					tmp);
+				goto msg_rejected;
+			} else if (tmp > max_speed_hz) {
+				dev_err(&drv_data->pdev->dev,
+					"message rejected : "
+					"transfer speed (%d Hz) exceeds "
+					"device max speed (%d Hz)\n",
+					tmp,
+					max_speed_hz);
+				goto msg_rejected;
+			}
+		}
+	}
+
+	/* Message accepted */
+	msg->status = -EINPROGRESS;
+	msg->state = START_STATE;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (drv_data->run == QUEUE_STOPPED) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	list_add_tail(&msg->queue, &drv_data->queue);
+	if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
+		queue_work(drv_data->workqueue, &drv_data->work);
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+	return 0;
+
+msg_rejected:
+	/* Message rejected and not queued */
+	msg->status = -EINVAL;
+	msg->state = ERROR_STATE;
+	if (msg->complete)
+		msg->complete(msg->context);
+	return -EINVAL;
+}
+
+/* On first setup bad values must free chip_data memory since will cause
+   spi_new_device to fail. Bad value setup from protocol driver are simply not
+   applied and notified to the calling driver. */
+static int setup(struct spi_device *spi)
+{
+	struct spi_imx_chip *chip_info;
+	struct chip_data *chip;
+	int first_setup = 0;
+	u32 tmp;
+	int status = 0;
+
+	/* Get controller data */
+	chip_info = spi->controller_data;
+
+	/* Get controller_state */
+	chip = spi_get_ctldata(spi);
+	if (chip == NULL) {
+		first_setup = 1;
+
+		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+		if (!chip) {
+			dev_err(&spi->dev,
+				"setup - cannot allocate controller state");
+			return -ENOMEM;
+		}
+		chip->control = SPI_DEFAULT_CONTROL;
+
+		if (chip_info == NULL) {
+			/* spi_board_info.controller_data not is supplied */
+			chip_info = kzalloc(sizeof(struct spi_imx_chip),
+						GFP_KERNEL);
+			if (!chip_info) {
+				dev_err(&spi->dev,
+					"setup - "
+					"cannot allocate controller data");
+				status = -ENOMEM;
+				goto err_first_setup;
+			}
+			/* Set controller data default value */
+			chip_info->enable_loopback =
+						SPI_DEFAULT_ENABLE_LOOPBACK;
+			chip_info->enable_dma = SPI_DEFAULT_ENABLE_DMA;
+			chip_info->ins_ss_pulse = 1;
+			chip_info->bclk_wait = SPI_DEFAULT_PERIOD_WAIT;
+			chip_info->cs_control = null_cs_control;
+		}
+	}
+
+	/* Now set controller state based on controller data */
+
+	if (first_setup) {
+		/* SPI loopback */
+		if (chip_info->enable_loopback)
+			chip->test = SPI_TEST_LBC;
+		else
+			chip->test = 0;
+
+		/* SPI dma driven */
+		chip->enable_dma = chip_info->enable_dma;
+
+		/* SPI /SS pulse between spi burst */
+		if (chip_info->ins_ss_pulse)
+			u32_EDIT(chip->control,
+				SPI_CONTROL_SSCTL, SPI_CONTROL_SSCTL_1);
+		else
+			u32_EDIT(chip->control,
+				SPI_CONTROL_SSCTL, SPI_CONTROL_SSCTL_0);
+
+		/* SPI bclk waits between each bits_per_word spi burst */
+		if (chip_info->bclk_wait > SPI_PERIOD_MAX_WAIT) {
+			dev_err(&spi->dev,
+				"setup - "
+				"bclk_wait exceeds max allowed (%d)\n",
+				SPI_PERIOD_MAX_WAIT);
+			goto err_first_setup;
+		}
+		chip->period = SPI_PERIOD_CSRC_BCLK |
+				(chip_info->bclk_wait & SPI_PERIOD_WAIT);
+	}
+
+	/* SPI mode */
+	tmp = spi->mode;
+	if (tmp & SPI_LSB_FIRST) {
+		status = -EINVAL;
+		if (first_setup) {
+			dev_err(&spi->dev,
+				"setup - "
+				"HW doesn't support LSB first transfer\n");
+			goto err_first_setup;
+		} else {
+			dev_err(&spi->dev,
+				"setup - "
+				"HW doesn't support LSB first transfer, "
+				"default to MSB first\n");
+			spi->mode &= ~SPI_LSB_FIRST;
+		}
+	}
+	if (tmp & SPI_CS_HIGH) {
+		u32_EDIT(chip->control,
+				SPI_CONTROL_SSPOL, SPI_CONTROL_SSPOL_ACT_HIGH);
+	}
+	switch (tmp & SPI_MODE_3) {
+	case SPI_MODE_0:
+		tmp = 0;
+		break;
+	case SPI_MODE_1:
+		tmp = SPI_CONTROL_PHA_1;
+		break;
+	case SPI_MODE_2:
+		tmp = SPI_CONTROL_POL_ACT_LOW;
+		break;
+	default:
+		/* SPI_MODE_3 */
+		tmp = SPI_CONTROL_PHA_1 | SPI_CONTROL_POL_ACT_LOW;
+		break;
+	}
+	u32_EDIT(chip->control, SPI_CONTROL_POL | SPI_CONTROL_PHA, tmp);
+
+	/* SPI word width */
+	tmp = spi->bits_per_word;
+	if (tmp == 0) {
+		tmp = 8;
+		spi->bits_per_word = 8;
+	} else if (tmp > 16) {
+		status = -EINVAL;
+		dev_err(&spi->dev,
+			"setup - "
+			"invalid bits_per_word (%d)\n",
+			tmp);
+		if (first_setup)
+			goto err_first_setup;
+		else {
+			/* Undo setup using chip as backup copy */
+			tmp = chip->bits_per_word;
+			spi->bits_per_word = tmp;
+		}
+	}
+	chip->bits_per_word = tmp;
+	u32_EDIT(chip->control, SPI_CONTROL_BITCOUNT_MASK, tmp - 1);
+	chip->n_bytes = (tmp <= 8) ? 1 : 2;
+
+	/* SPI datarate */
+	tmp = spi_data_rate(spi->max_speed_hz);
+	if (tmp == SPI_CONTROL_DATARATE_BAD) {
+		status = -EINVAL;
+		dev_err(&spi->dev,
+			"setup - "
+			"HW min speed (%d Hz) exceeds required "
+			"max speed (%d Hz)\n",
+			spi_speed_hz(SPI_CONTROL_DATARATE_MIN),
+			spi->max_speed_hz);
+		if (first_setup)
+			goto err_first_setup;
+		else
+			/* Undo setup using chip as backup copy */
+			spi->max_speed_hz = chip->max_speed_hz;
+	} else {
+		u32_EDIT(chip->control, SPI_CONTROL_DATARATE, tmp);
+		/* Actual rounded max_speed_hz */
+		tmp = spi_speed_hz(tmp);
+		spi->max_speed_hz = tmp;
+		chip->max_speed_hz = tmp;
+	}
+
+	/* SPI chip-select management */
+	if (chip_info->cs_control)
+		chip->cs_control = chip_info->cs_control;
+	else
+		chip->cs_control = null_cs_control;
+
+	/* Save controller_state */
+	spi_set_ctldata(spi, chip);
+
+	/* Summary */
+	dev_dbg(&spi->dev,
+		"setup succeded\n"
+		"    loopback enable   = %s\n"
+		"    dma enable        = %s\n"
+		"    insert /ss pulse  = %s\n"
+		"    period wait       = %d\n"
+		"    mode              = %d\n"
+		"    bits per word     = %d\n"
+		"    min speed         = %d Hz\n"
+		"    rounded max speed = %d Hz\n",
+		chip->test & SPI_TEST_LBC ? "Yes" : "No",
+		chip->enable_dma ? "Yes" : "No",
+		chip->control & SPI_CONTROL_SSCTL ? "Yes" : "No",
+		chip->period & SPI_PERIOD_WAIT,
+		spi->mode,
+		spi->bits_per_word,
+		spi_speed_hz(SPI_CONTROL_DATARATE_MIN),
+		spi->max_speed_hz);
+
+err_first_setup:
+	kfree(chip);
+	return status;
+}
+
+static void cleanup(struct spi_device *spi)
+{
+	kfree(spi_get_ctldata(spi));
+}
+
+static int init_queue(struct driver_data *drv_data)
+{
+	INIT_LIST_HEAD(&drv_data->queue);
+	spin_lock_init(&drv_data->lock);
+
+	drv_data->run = QUEUE_STOPPED;
+	drv_data->busy = 0;
+
+	tasklet_init(&drv_data->pump_transfers,
+			pump_transfers,	(unsigned long)drv_data);
+
+	INIT_WORK(&drv_data->work, pump_messages);
+	drv_data->workqueue = create_singlethread_workqueue(
+					drv_data->master->cdev.dev->bus_id);
+	if (drv_data->workqueue == NULL)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int start_queue(struct driver_data *drv_data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -EBUSY;
+	}
+
+	drv_data->run = QUEUE_RUNNING;
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	queue_work(drv_data->workqueue, &drv_data->work);
+
+	return 0;
+}
+
+static int stop_queue(struct driver_data *drv_data)
+{
+	unsigned long flags;
+	unsigned limit = 500;
+	int status = 0;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	/* This is a bit lame, but is optimized for the common execution path.
+	 * A wait_queue on the drv_data->busy could be used, but then the common
+	 * execution path (pump_messages) would be required to call wake_up or
+	 * friends on every SPI message. Do this instead */
+	drv_data->run = QUEUE_STOPPED;
+	while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&drv_data->lock, flags);
+	}
+
+	if (!list_empty(&drv_data->queue) || drv_data->busy)
+		status = -EBUSY;
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return status;
+}
+
+static int destroy_queue(struct driver_data *drv_data)
+{
+	int status;
+
+	status = stop_queue(drv_data);
+	if (status != 0)
+		return status;
+
+	if (drv_data->workqueue)
+		destroy_workqueue(drv_data->workqueue);
+
+	return 0;
+}
+
+static int spi_imx_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct spi_imx_master *platform_info;
+	struct spi_master *master;
+	struct driver_data *drv_data = NULL;
+	struct resource *res;
+	int irq, status = 0;
+
+	platform_info = dev->platform_data;
+	if (platform_info == NULL) {
+		dev_err(&pdev->dev, "probe - no platform data supplied\n");
+		status = -ENODEV;
+		goto err_no_pdata;
+	}
+
+	/* Allocate master with space for drv_data */
+	master = spi_alloc_master(dev, sizeof(struct driver_data));
+	if (!master) {
+		dev_err(&pdev->dev, "probe - cannot alloc spi_master\n");
+		status = -ENOMEM;
+		goto err_no_mem;
+	}
+	drv_data = spi_master_get_devdata(master);
+	drv_data->master = master;
+	drv_data->master_info = platform_info;
+	drv_data->pdev = pdev;
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = platform_info->num_chipselect;
+	master->cleanup = cleanup;
+	master->setup = setup;
+	master->transfer = transfer;
+
+	drv_data->dummy_dma_buf = SPI_DUMMY_u32;
+
+	/* Find and map resources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "probe - MEM resources not defined\n");
+		status = -ENODEV;
+		goto err_no_iores;
+	}
+	drv_data->ioarea = request_mem_region(res->start,
+						res->end - res->start + 1,
+						pdev->name);
+	if (drv_data->ioarea == NULL) {
+		dev_err(&pdev->dev, "probe - cannot reserve region\n");
+		status = -ENXIO;
+		goto err_no_iores;
+	}
+	drv_data->regs = ioremap(res->start, res->end - res->start + 1);
+	if (drv_data->regs == NULL) {
+		dev_err(&pdev->dev, "probe - cannot map IO\n");
+		status = -ENXIO;
+		goto err_no_iomap;
+	}
+	drv_data->rd_data_phys = (dma_addr_t)res->start;
+
+	/* Attach to IRQ */
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "probe - IRQ resource not defined\n");
+		status = -ENODEV;
+		goto err_no_irqres;
+	}
+	status = request_irq(irq, spi_int, IRQF_DISABLED, dev->bus_id, drv_data);
+	if (status < 0) {
+		dev_err(&pdev->dev, "probe - cannot get IRQ (%d)\n", status);
+		goto err_no_irqres;
+	}
+
+	/* Setup DMA if requested */
+	drv_data->tx_channel = -1;
+	drv_data->rx_channel = -1;
+	if (platform_info->enable_dma) {
+		/* Get rx DMA channel */
+		status = imx_dma_request_by_prio(&drv_data->rx_channel,
+			"spi_imx_rx", DMA_PRIO_HIGH);
+		if (status < 0) {
+			dev_err(dev,
+				"probe - problem (%d) requesting rx channel\n",
+				status);
+			goto err_no_rxdma;
+		} else
+			imx_dma_setup_handlers(drv_data->rx_channel, NULL,
+						dma_err_handler, drv_data);
+
+		/* Get tx DMA channel */
+		status = imx_dma_request_by_prio(&drv_data->tx_channel,
+						"spi_imx_tx", DMA_PRIO_MEDIUM);
+		if (status < 0) {
+			dev_err(dev,
+				"probe - problem (%d) requesting tx channel\n",
+				status);
+			imx_dma_free(drv_data->rx_channel);
+			goto err_no_txdma;
+		} else
+			imx_dma_setup_handlers(drv_data->tx_channel,
+						dma_tx_handler, dma_err_handler,
+						drv_data);
+
+		/* Set request source and burst length for allocated channels */
+		switch (drv_data->pdev->id) {
+		case 1:
+			/* Using SPI1 */
+			RSSR(drv_data->rx_channel) = DMA_REQ_SPI1_R;
+			RSSR(drv_data->tx_channel) = DMA_REQ_SPI1_T;
+			break;
+		case 2:
+			/* Using SPI2 */
+			RSSR(drv_data->rx_channel) = DMA_REQ_SPI2_R;
+			RSSR(drv_data->tx_channel) = DMA_REQ_SPI2_T;
+			break;
+		default:
+			dev_err(dev, "probe - bad SPI Id\n");
+			imx_dma_free(drv_data->rx_channel);
+			imx_dma_free(drv_data->tx_channel);
+			status = -ENODEV;
+			goto err_no_devid;
+		}
+		BLR(drv_data->rx_channel) = SPI_DMA_BLR;
+		BLR(drv_data->tx_channel) = SPI_DMA_BLR;
+	}
+
+	/* Load default SPI configuration */
+	writel(SPI_RESET_START, drv_data->regs + SPI_RESET);
+	writel(0, drv_data->regs + SPI_RESET);
+	writel(SPI_DEFAULT_CONTROL, drv_data->regs + SPI_CONTROL);
+
+	/* Initial and start queue */
+	status = init_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "probe - problem initializing queue\n");
+		goto err_init_queue;
+	}
+	status = start_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "probe - problem starting queue\n");
+		goto err_start_queue;
+	}
+
+	/* Register with the SPI framework */
+	platform_set_drvdata(pdev, drv_data);
+	status = spi_register_master(master);
+	if (status != 0) {
+		dev_err(&pdev->dev, "probe - problem registering spi master\n");
+		goto err_spi_register;
+	}
+
+	dev_dbg(dev, "probe succeded\n");
+	return 0;
+
+err_init_queue:
+err_start_queue:
+err_spi_register:
+	destroy_queue(drv_data);
+
+err_no_rxdma:
+err_no_txdma:
+err_no_devid:
+	free_irq(irq, drv_data);
+
+err_no_irqres:
+	iounmap(drv_data->regs);
+
+err_no_iomap:
+	release_resource(drv_data->ioarea);
+	kfree(drv_data->ioarea);
+
+err_no_iores:
+	spi_master_put(master);
+
+err_no_pdata:
+err_no_mem:
+	return status;
+}
+
+static int __devexit spi_imx_remove(struct platform_device *pdev)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	int irq;
+	int status = 0;
+
+	if (!drv_data)
+		return 0;
+
+	tasklet_kill(&drv_data->pump_transfers);
+
+	/* Remove the queue */
+	status = destroy_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "queue remove failed (%d)\n", status);
+		return status;
+	}
+
+	/* Reset SPI */
+	writel(SPI_RESET_START, drv_data->regs + SPI_RESET);
+	writel(0, drv_data->regs + SPI_RESET);
+
+	/* Release DMA */
+	if (drv_data->master_info->enable_dma) {
+		RSSR(drv_data->rx_channel) = 0;
+		RSSR(drv_data->tx_channel) = 0;
+		imx_dma_free(drv_data->tx_channel);
+		imx_dma_free(drv_data->rx_channel);
+	}
+
+	/* Release IRQ */
+	irq = platform_get_irq(pdev, 0);
+	if (irq >= 0)
+		free_irq(irq, drv_data);
+
+	/* Release map resources */
+	iounmap(drv_data->regs);
+	release_resource(drv_data->ioarea);
+	kfree(drv_data->ioarea);
+
+	/* Disconnect from the SPI framework */
+	spi_unregister_master(drv_data->master);
+	spi_master_put(drv_data->master);
+
+	/* Prevent double remove */
+	platform_set_drvdata(pdev, NULL);
+
+	dev_dbg(&pdev->dev, "remove succeded\n");
+
+	return 0;
+}
+
+static void spi_imx_shutdown(struct platform_device *pdev)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+
+	/* Reset SPI */
+	writel(SPI_RESET_START, drv_data->regs + SPI_RESET);
+	writel(0, drv_data->regs + SPI_RESET);
+
+	dev_dbg(&pdev->dev, "shutdown succeded\n");
+}
+
+#ifdef CONFIG_PM
+static int suspend_devices(struct device *dev, void *pm_message)
+{
+	pm_message_t *state = pm_message;
+
+	if (dev->power.power_state.event != state->event) {
+		dev_warn(dev, "pm state does not match request\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int spi_imx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	int status = 0;
+
+	status = stop_queue(drv_data);
+	if (status != 0) {
+		dev_warn(&pdev->dev, "suspend cannot stop queue\n");
+		return status;
+	}
+
+	dev_dbg(&pdev->dev, "suspended\n");
+
+	return 0;
+}
+
+static int spi_imx_resume(struct platform_device *pdev)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	int status = 0;
+
+	/* Start the queue running */
+	status = start_queue(drv_data);
+	if (status != 0)
+		dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
+	else
+		dev_dbg(&pdev->dev, "resumed\n");
+
+	return status;
+}
+#else
+#define spi_imx_suspend NULL
+#define spi_imx_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver driver = {
+	.driver = {
+		.name = "imx-spi",
+		.bus = &platform_bus_type,
+		.owner = THIS_MODULE,
+	},
+	.probe = spi_imx_probe,
+	.remove = __devexit_p(spi_imx_remove),
+	.shutdown = spi_imx_shutdown,
+	.suspend = spi_imx_suspend,
+	.resume = spi_imx_resume,
+};
+
+static int __init spi_imx_init(void)
+{
+	return platform_driver_register(&driver);
+}
+module_init(spi_imx_init);
+
+static void __exit spi_imx_exit(void)
+{
+	platform_driver_unregister(&driver);
+}
+module_exit(spi_imx_exit);
+
+MODULE_AUTHOR("Andrea Paterniani, <a.paterniani@swapp-eng.it>");
+MODULE_DESCRIPTION("iMX SPI Contoller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
index eda53ed..611ac22 100644
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ b/drivers/spi/spi_s3c24xx_gpio.c
@@ -73,6 +73,19 @@
 	return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
 }
 
+static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi,
+				      unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
+}
+
+static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi,
+				      unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
+}
+
+
 static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
 {
 	struct s3c2410_spigpio *sg = spidev_to_sg(dev);
@@ -108,6 +121,8 @@
 
 	sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
 	sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
+	sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2;
+	sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3;
 
 	/* set state of spi pins */
 	s3c2410_gpio_setpin(sp->info->pin_clk, 0);
diff --git a/drivers/tc/Makefile b/drivers/tc/Makefile
index 83b5bd7..9673426 100644
--- a/drivers/tc/Makefile
+++ b/drivers/tc/Makefile
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-$(CONFIG_TC) += tc.o
+obj-$(CONFIG_TC) += tc.o tc-driver.o
 obj-$(CONFIG_ZS) += zs.o
 obj-$(CONFIG_VT) += lk201.o lk201-map.o lk201-remap.o
 
diff --git a/drivers/tc/lk201.c b/drivers/tc/lk201.c
index 757dec9..a90c255 100644
--- a/drivers/tc/lk201.c
+++ b/drivers/tc/lk201.c
@@ -10,7 +10,6 @@
 
 
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
diff --git a/drivers/tc/tc-driver.c b/drivers/tc/tc-driver.c
new file mode 100644
index 0000000..16b5bae
--- /dev/null
+++ b/drivers/tc/tc-driver.c
@@ -0,0 +1,110 @@
+/*
+ *	TURBOchannel driver services.
+ *
+ *	Copyright (c) 2005  James Simmons
+ *	Copyright (c) 2006  Maciej W. Rozycki
+ *
+ *	Loosely based on drivers/dio/dio-driver.c and
+ *	drivers/pci/pci-driver.c.
+ *
+ *	This file is subject to the terms and conditions of the GNU
+ *	General Public License.  See the file "COPYING" in the main
+ *	directory of this archive for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/tc.h>
+
+/**
+ * tc_register_driver - register a new TC driver
+ * @drv: the driver structure to register
+ *
+ * Adds the driver structure to the list of registered drivers
+ * Returns a negative value on error, otherwise 0.
+ * If no error occurred, the driver remains registered even if
+ * no device was claimed during registration.
+ */
+int tc_register_driver(struct tc_driver *tdrv)
+{
+	return driver_register(&tdrv->driver);
+}
+EXPORT_SYMBOL(tc_register_driver);
+
+/**
+ * tc_unregister_driver - unregister a TC driver
+ * @drv: the driver structure to unregister
+ *
+ * Deletes the driver structure from the list of registered TC drivers,
+ * gives it a chance to clean up by calling its remove() function for
+ * each device it was responsible for, and marks those devices as
+ * driverless.
+ */
+void tc_unregister_driver(struct tc_driver *tdrv)
+{
+	driver_unregister(&tdrv->driver);
+}
+EXPORT_SYMBOL(tc_unregister_driver);
+
+/**
+ * tc_match_device - tell if a TC device structure has a matching
+ *                   TC device ID structure
+ * @tdrv: the TC driver to earch for matching TC device ID strings
+ * @tdev: the TC device structure to match against
+ *
+ * Used by a driver to check whether a TC device present in the
+ * system is in its list of supported devices.  Returns the matching
+ * tc_device_id structure or %NULL if there is no match.
+ */
+const struct tc_device_id *tc_match_device(struct tc_driver *tdrv,
+					   struct tc_dev *tdev)
+{
+	const struct tc_device_id *id = tdrv->id_table;
+
+	if (id) {
+		while (id->name[0] || id->vendor[0]) {
+			if (strcmp(tdev->name, id->name) == 0 &&
+			    strcmp(tdev->vendor, id->vendor) == 0)
+				return id;
+			id++;
+		}
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(tc_match_device);
+
+/**
+ * tc_bus_match - Tell if a device structure has a matching
+ *                TC device ID structure
+ * @dev: the device structure to match against
+ * @drv: the device driver to search for matching TC device ID strings
+ *
+ * Used by a driver to check whether a TC device present in the
+ * system is in its list of supported devices.  Returns 1 if there
+ * is a match or 0 otherwise.
+ */
+static int tc_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct tc_dev *tdev = to_tc_dev(dev);
+	struct tc_driver *tdrv = to_tc_driver(drv);
+	const struct tc_device_id *id;
+
+	id = tc_match_device(tdrv, tdev);
+	if (id)
+		return 1;
+
+	return 0;
+}
+
+struct bus_type tc_bus_type = {
+	.name	= "tc",
+	.match	= tc_bus_match,
+};
+EXPORT_SYMBOL(tc_bus_type);
+
+static int __init tc_driver_init(void)
+{
+	return bus_register(&tc_bus_type);
+}
+
+postcore_initcall(tc_driver_init);
diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c
index 4a51e56..f77f62a 100644
--- a/drivers/tc/tc.c
+++ b/drivers/tc/tc.c
@@ -1,254 +1,193 @@
 /*
- * tc-init: We assume the TURBOchannel to be up and running so
- * just probe for Modules and fill in the global data structure
- * tc_bus.
+ *	TURBOchannel bus services.
  *
- * 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) Harald Koerfgen, 1998
+ *	Copyright (c) 2001, 2003, 2005, 2006  Maciej W. Rozycki
+ *	Copyright (c) 2005  James Simmons
  *
- * Copyright (c) Harald Koerfgen, 1998
- * Copyright (c) 2001, 2003, 2005  Maciej W. Rozycki
+ *	This file is subject to the terms and conditions of the GNU
+ *	General Public License.  See the file "COPYING" in the main
+ *	directory of this archive for more details.
  */
+#include <linux/compiler.h>
+#include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 #include <linux/kernel.h>
+#include <linux/list.h>
 #include <linux/module.h>
 #include <linux/string.h>
+#include <linux/tc.h>
 #include <linux/types.h>
 
-#include <asm/addrspace.h>
-#include <asm/errno.h>
 #include <asm/io.h>
-#include <asm/paccess.h>
 
-#include <asm/dec/machtype.h>
-#include <asm/dec/prom.h>
-#include <asm/dec/tcinfo.h>
-#include <asm/dec/tcmodule.h>
-#include <asm/dec/interrupts.h>
-
-MODULE_LICENSE("GPL");
-slot_info tc_bus[MAX_SLOT];
-static int num_tcslots;
-static tcinfo *info;
+static struct tc_bus tc_bus = {
+	.name = "TURBOchannel",
+};
 
 /*
- * Interface to the world. Read comment in include/asm-mips/tc.h.
+ * Probing for TURBOchannel modules.
  */
-
-int search_tc_card(const char *name)
+static void __init tc_bus_add_devices(struct tc_bus *tbus)
 {
-	int slot;
-	slot_info *sip;
-
-	for (slot = 0; slot < num_tcslots; slot++) {
-		sip = &tc_bus[slot];
-		if ((sip->flags & FREE) &&
-		    (strncmp(sip->name, name, strlen(name)) == 0)) {
-			return slot;
-		}
-	}
-
-	return -ENODEV;
-}
-
-void claim_tc_card(int slot)
-{
-	if (tc_bus[slot].flags & IN_USE) {
-		printk("claim_tc_card: attempting to claim a card already in use\n");
-		return;
-	}
-	tc_bus[slot].flags &= ~FREE;
-	tc_bus[slot].flags |= IN_USE;
-}
-
-void release_tc_card(int slot)
-{
-	if (tc_bus[slot].flags & FREE) {
-		printk("release_tc_card: "
-		       "attempting to release a card already free\n");
-		return;
-	}
-	tc_bus[slot].flags &= ~IN_USE;
-	tc_bus[slot].flags |= FREE;
-}
-
-unsigned long get_tc_base_addr(int slot)
-{
-	return tc_bus[slot].base_addr;
-}
-
-unsigned long get_tc_irq_nr(int slot)
-{
-	return tc_bus[slot].interrupt;
-}
-
-unsigned long get_tc_speed(void)
-{
-	return 100000 * (10000 / (unsigned long)info->clk_period);
-}
-
-/*
- * Probing for TURBOchannel modules
- */
-static void __init tc_probe(unsigned long startaddr, unsigned long size,
-			    int slots)
-{
-	unsigned long slotaddr;
+	resource_size_t slotsize = tbus->info.slot_size << 20;
+	resource_size_t extslotsize = tbus->ext_slot_size;
+	resource_size_t slotaddr;
+	resource_size_t extslotaddr;
+	resource_size_t devsize;
+	void __iomem *module;
+	struct tc_dev *tdev;
 	int i, slot, err;
-	long offset;
 	u8 pattern[4];
-	volatile u8 *module;
+	long offset;
 
-	for (slot = 0; slot < slots; slot++) {
-		slotaddr = startaddr + slot * size;
-		module = ioremap_nocache(slotaddr, size);
+	for (slot = 0; slot < tbus->num_tcslots; slot++) {
+		slotaddr = tbus->slot_base + slot * slotsize;
+		extslotaddr = tbus->ext_slot_base + slot * extslotsize;
+		module = ioremap_nocache(slotaddr, slotsize);
 		BUG_ON(!module);
 
-		offset = OLDCARD;
+		offset = TC_OLDCARD;
 
 		err = 0;
-		err |= get_dbe(pattern[0], module + OLDCARD + TC_PATTERN0);
-		err |= get_dbe(pattern[1], module + OLDCARD + TC_PATTERN1);
-		err |= get_dbe(pattern[2], module + OLDCARD + TC_PATTERN2);
-		err |= get_dbe(pattern[3], module + OLDCARD + TC_PATTERN3);
-		if (err) {
-			iounmap(module);
-			continue;
-		}
+		err |= tc_preadb(pattern + 0, module + offset + TC_PATTERN0);
+		err |= tc_preadb(pattern + 1, module + offset + TC_PATTERN1);
+		err |= tc_preadb(pattern + 2, module + offset + TC_PATTERN2);
+		err |= tc_preadb(pattern + 3, module + offset + TC_PATTERN3);
+		if (err)
+			goto out_err;
 
 		if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
 		    pattern[2] != 0xaa || pattern[3] != 0xff) {
-			offset = NEWCARD;
+			offset = TC_NEWCARD;
 
 			err = 0;
-			err |= get_dbe(pattern[0], module + TC_PATTERN0);
-			err |= get_dbe(pattern[1], module + TC_PATTERN1);
-			err |= get_dbe(pattern[2], module + TC_PATTERN2);
-			err |= get_dbe(pattern[3], module + TC_PATTERN3);
-			if (err) {
-				iounmap(module);
-				continue;
-			}
+			err |= tc_preadb(pattern + 0,
+					 module + offset + TC_PATTERN0);
+			err |= tc_preadb(pattern + 1,
+					 module + offset + TC_PATTERN1);
+			err |= tc_preadb(pattern + 2,
+					 module + offset + TC_PATTERN2);
+			err |= tc_preadb(pattern + 3,
+					 module + offset + TC_PATTERN3);
+			if (err)
+				goto out_err;
 		}
 
 		if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
-		    pattern[2] != 0xaa || pattern[3] != 0xff) {
-			iounmap(module);
-			continue;
-		}
+		    pattern[2] != 0xaa || pattern[3] != 0xff)
+			goto out_err;
 
-		tc_bus[slot].base_addr = slotaddr;
+		/* Found a board, allocate it an entry in the list */
+		tdev = kzalloc(sizeof(*tdev), GFP_KERNEL);
+		if (!tdev) {
+			printk(KERN_ERR "tc%x: unable to allocate tc_dev\n",
+			       slot);
+			goto out_err;
+		}
+		sprintf(tdev->dev.bus_id, "tc%x", slot);
+		tdev->bus = tbus;
+		tdev->dev.parent = &tbus->dev;
+		tdev->dev.bus = &tc_bus_type;
+		tdev->slot = slot;
+
 		for (i = 0; i < 8; i++) {
-			tc_bus[slot].firmware[i] =
-				module[TC_FIRM_VER + offset + 4 * i];
-			tc_bus[slot].vendor[i] =
-				module[TC_VENDOR + offset + 4 * i];
-			tc_bus[slot].name[i] =
-				module[TC_MODULE + offset + 4 * i];
+			tdev->firmware[i] =
+				readb(module + offset + TC_FIRM_VER + 4 * i);
+			tdev->vendor[i] =
+				readb(module + offset + TC_VENDOR + 4 * i);
+			tdev->name[i] =
+				readb(module + offset + TC_MODULE + 4 * i);
 		}
-		tc_bus[slot].firmware[8] = 0;
-		tc_bus[slot].vendor[8] = 0;
-		tc_bus[slot].name[8] = 0;
-		/*
-		 * Looks unneccesary, but we may change
-		 * TC? in the future
-		 */
-		switch (slot) {
-		case 0:
-			tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC0];
-			break;
-		case 1:
-			tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC1];
-			break;
-		case 2:
-			tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC2];
-			break;
-		/*
-		 * Yuck! DS5000/200 onboard devices
-		 */
-		case 5:
-			tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC5];
-			break;
-		case 6:
-			tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC6];
-			break;
-		default:
-			tc_bus[slot].interrupt = -1;
-			break;
-		}
+		tdev->firmware[8] = 0;
+		tdev->vendor[8] = 0;
+		tdev->name[8] = 0;
 
+		pr_info("%s: %s %s %s\n", tdev->dev.bus_id, tdev->vendor,
+			tdev->name, tdev->firmware);
+
+		devsize = readb(module + offset + TC_SLOT_SIZE);
+		devsize <<= 22;
+		if (devsize <= slotsize) {
+			tdev->resource.start = slotaddr;
+			tdev->resource.end = slotaddr + devsize - 1;
+		} else if (devsize <= extslotsize) {
+			tdev->resource.start = extslotaddr;
+			tdev->resource.end = extslotaddr + devsize - 1;
+		} else {
+			printk(KERN_ERR "%s: Cannot provide slot space "
+			       "(%dMiB required, up to %dMiB supported)\n",
+			       tdev->dev.bus_id, devsize >> 20,
+			       max(slotsize, extslotsize) >> 20);
+			kfree(tdev);
+			goto out_err;
+		}
+		tdev->resource.name = tdev->name;
+		tdev->resource.flags = IORESOURCE_MEM;
+
+		tc_device_get_irq(tdev);
+
+		device_register(&tdev->dev);
+		list_add_tail(&tdev->node, &tbus->devices);
+
+out_err:
 		iounmap(module);
 	}
 }
 
 /*
- * the main entry
+ * The main entry.
  */
 static int __init tc_init(void)
 {
-	int tc_clock;
-	int i;
-	unsigned long slot0addr;
-	unsigned long slot_size;
-
-	if (!TURBOCHANNEL)
+	/* Initialize the TURBOchannel bus */
+	if (tc_bus_get_info(&tc_bus))
 		return 0;
 
-	for (i = 0; i < MAX_SLOT; i++) {
-		tc_bus[i].base_addr = 0;
-		tc_bus[i].name[0] = 0;
-		tc_bus[i].vendor[0] = 0;
-		tc_bus[i].firmware[0] = 0;
-		tc_bus[i].interrupt = -1;
-		tc_bus[i].flags = FREE;
-	}
+	INIT_LIST_HEAD(&tc_bus.devices);
+	strcpy(tc_bus.dev.bus_id, "tc");
+	device_register(&tc_bus.dev);
 
-	info = rex_gettcinfo();
-	slot0addr = CPHYSADDR((long)rex_slot_address(0));
+	if (tc_bus.info.slot_size) {
+		unsigned int tc_clock = tc_get_speed(&tc_bus) / 100000;
 
-	switch (mips_machtype) {
-	case MACH_DS5000_200:
-		num_tcslots = 7;
-		break;
-	case MACH_DS5000_1XX:
-	case MACH_DS5000_2X0:
-	case MACH_DS5900:
-		num_tcslots = 3;
-		break;
-	case MACH_DS5000_XX:
-	default:
-		num_tcslots = 2;
-		break;
-	}
+		pr_info("tc: TURBOchannel rev. %d at %d.%d MHz "
+			"(with%s parity)\n", tc_bus.info.revision,
+			tc_clock / 10, tc_clock % 10,
+			tc_bus.info.parity ? "" : "out");
 
-	tc_clock = 10000 / info->clk_period;
-
-	if (info->slot_size && slot0addr) {
-		pr_info("TURBOchannel rev. %d at %d.%d MHz (with%s parity)\n",
-			info->revision, tc_clock / 10, tc_clock % 10,
-			info->parity ? "" : "out");
-
-		slot_size = info->slot_size << 20;
-
-		tc_probe(slot0addr, slot_size, num_tcslots);
-
-		for (i = 0; i < num_tcslots; i++) {
-			if (!tc_bus[i].base_addr)
-				continue;
-			pr_info("    slot %d: %s %s %s\n", i, tc_bus[i].vendor,
-				tc_bus[i].name, tc_bus[i].firmware);
+		tc_bus.resource[0].start = tc_bus.slot_base;
+		tc_bus.resource[0].end = tc_bus.slot_base +
+					 (tc_bus.info.slot_size << 20) *
+					 tc_bus.num_tcslots - 1;
+		tc_bus.resource[0].name = tc_bus.name;
+		tc_bus.resource[0].flags = IORESOURCE_MEM;
+		if (request_resource(&iomem_resource,
+				     &tc_bus.resource[0]) < 0) {
+			printk(KERN_ERR "tc: Cannot reserve resource\n");
+			return 0;
 		}
+		if (tc_bus.ext_slot_size) {
+			tc_bus.resource[1].start = tc_bus.ext_slot_base;
+			tc_bus.resource[1].end = tc_bus.ext_slot_base +
+						 tc_bus.ext_slot_size *
+						 tc_bus.num_tcslots - 1;
+			tc_bus.resource[1].name = tc_bus.name;
+			tc_bus.resource[1].flags = IORESOURCE_MEM;
+			if (request_resource(&iomem_resource,
+					     &tc_bus.resource[1]) < 0) {
+				printk(KERN_ERR
+				       "tc: Cannot reserve resource\n");
+				release_resource(&tc_bus.resource[0]);
+				return 0;
+			}
+		}
+
+		tc_bus_add_devices(&tc_bus);
 	}
 
 	return 0;
 }
 
 subsys_initcall(tc_init);
-
-EXPORT_SYMBOL(search_tc_card);
-EXPORT_SYMBOL(claim_tc_card);
-EXPORT_SYMBOL(release_tc_card);
-EXPORT_SYMBOL(get_tc_base_addr);
-EXPORT_SYMBOL(get_tc_irq_nr);
-EXPORT_SYMBOL(get_tc_speed);
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index fc31972..3d72aa5 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -626,10 +626,8 @@
 	if (!tty)
 		return;
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
 		tty_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
 }
 
 static int zs_startup(struct dec_serial * info)
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index df4cc1f..71cb64e 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -648,9 +648,9 @@
 	return j->pld_slicr.bits.state;
 }
 
-static BOOL SLIC_SetState(BYTE byState, IXJ *j)
+static bool SLIC_SetState(BYTE byState, IXJ *j)
 {
-	BOOL fRetVal = FALSE;
+	bool fRetVal = false;
 
 	if (j->cardtype == QTI_PHONECARD) {
 		if (j->flags.pcmciasct) {
@@ -659,14 +659,14 @@
 			case PLD_SLIC_STATE_OC:
 				j->pslic.bits.powerdown = 1;
 				j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0;
-				fRetVal = TRUE;
+				fRetVal = true;
 				break;
 			case PLD_SLIC_STATE_RINGING:
 				if (j->readers || j->writers) {
 					j->pslic.bits.powerdown = 0;
 					j->pslic.bits.ring0 = 1;
 					j->pslic.bits.ring1 = 0;
-					fRetVal = TRUE;
+					fRetVal = true;
 				}
 				break;
 			case PLD_SLIC_STATE_OHT:	/* On-hook transmit */
@@ -679,14 +679,14 @@
 					j->pslic.bits.powerdown = 1;
 				}
 				j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0;
-				fRetVal = TRUE;
+				fRetVal = true;
 				break;
 			case PLD_SLIC_STATE_APR:	/* Active polarity reversal */
 
 			case PLD_SLIC_STATE_OHTPR:	/* OHT polarity reversal */
 
 			default:
-				fRetVal = FALSE;
+				fRetVal = false;
 				break;
 			}
 			j->psccr.bits.dev = 3;
@@ -703,7 +703,7 @@
 			j->pld_slicw.bits.c3 = 0;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_RINGING:
 			j->pld_slicw.bits.c1 = 1;
@@ -711,7 +711,7 @@
 			j->pld_slicw.bits.c3 = 0;
 			j->pld_slicw.bits.b2en = 1;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_ACTIVE:
 			j->pld_slicw.bits.c1 = 0;
@@ -719,7 +719,7 @@
 			j->pld_slicw.bits.c3 = 0;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_OHT:	/* On-hook transmit */
 
@@ -728,7 +728,7 @@
 			j->pld_slicw.bits.c3 = 0;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_TIPOPEN:
 			j->pld_slicw.bits.c1 = 0;
@@ -736,7 +736,7 @@
 			j->pld_slicw.bits.c3 = 1;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_STANDBY:
 			j->pld_slicw.bits.c1 = 1;
@@ -744,7 +744,7 @@
 			j->pld_slicw.bits.c3 = 1;
 			j->pld_slicw.bits.b2en = 1;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_APR:	/* Active polarity reversal */
 
@@ -753,7 +753,7 @@
 			j->pld_slicw.bits.c3 = 1;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_OHTPR:	/* OHT polarity reversal */
 
@@ -762,10 +762,10 @@
 			j->pld_slicw.bits.c3 = 1;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		default:
-			fRetVal = FALSE;
+			fRetVal = false;
 			break;
 		}
 	}
@@ -4969,7 +4969,8 @@
 {
 	int i;
 	BYTES bytes;
-	char CID[ALISDAA_CALLERID_SIZE], mContinue;
+	char CID[ALISDAA_CALLERID_SIZE];
+	bool mContinue;
 	char *pIn, *pOut;
 
 	if (!SCI_Prepare(j))
@@ -5013,7 +5014,7 @@
 
 	pIn = CID;
 	pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID;
-	mContinue = 1;
+	mContinue = true;
 	while (mContinue) {
 		if ((pIn[1] & 0x03) == 0x01) {
 			pOut[0] = pIn[0];
@@ -5027,7 +5028,7 @@
 		if ((pIn[4] & 0xc0) == 0x40) {
 			pOut[3] = ((pIn[4] & 0x3f) << 2) | ((pIn[3] & 0xc0) >> 6);
 		} else {
-			mContinue = FALSE;
+			mContinue = false;
 		}
 		pIn += 5, pOut += 4;
 	}
@@ -6662,7 +6663,7 @@
 	return fasync_helper(fd, file_p, mode, &j->async_queue);
 }
 
-static struct file_operations ixj_fops =
+static const struct file_operations ixj_fops =
 {
         .owner          = THIS_MODULE,
         .read           = ixj_enhanced_read,
@@ -7498,7 +7499,7 @@
 	return ((inb(wEEPROMAddress) >> 3) & 1);
 }
 
-static BOOL PCIEE_ReadWord(WORD wAddress, WORD wLoc, WORD * pwResult)
+static bool PCIEE_ReadWord(WORD wAddress, WORD wLoc, WORD * pwResult)
 {
 	BYTE lastLCC;
 	WORD wEEPROMAddress = wAddress + 3;
diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h
index 8d69bcd..4c32a43 100644
--- a/drivers/telephony/ixj.h
+++ b/drivers/telephony/ixj.h
@@ -48,15 +48,11 @@
 typedef __u16 WORD;
 typedef __u32 DWORD;
 typedef __u8 BYTE;
-typedef __u8 BOOL;
 
 #ifndef IXJMAX
 #define IXJMAX 16
 #endif
 
-#define TRUE 1
-#define FALSE 0
-
 /******************************************************************************
 *
 *  This structure when unioned with the structures below makes simple byte
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index 164a5dc..3e658dc 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -3,7 +3,6 @@
 #include <linux/module.h>
 
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>	/* printk() */
 #include <linux/fs.h>		/* everything... */
 #include <linux/errno.h>	/* error codes */
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c
index e41f49a..4d8c2a5 100644
--- a/drivers/telephony/phonedev.c
+++ b/drivers/telephony/phonedev.c
@@ -127,7 +127,7 @@
 }
 
 
-static struct file_operations phone_fops =
+static const struct file_operations phone_fops =
 {
 	.owner		= THIS_MODULE,
 	.open		= phone_open,
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 825bf88..8b7ff46 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -51,6 +51,7 @@
 obj-$(CONFIG_USB_ADUTUX)	+= misc/
 obj-$(CONFIG_USB_APPLEDISPLAY)	+= misc/
 obj-$(CONFIG_USB_AUERSWALD)	+= misc/
+obj-$(CONFIG_USB_BERRY_CHARGE)	+= misc/
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
 obj-$(CONFIG_USB_CYTHERM)	+= misc/
 obj-$(CONFIG_USB_EMI26)		+= misc/
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index dae4ef1..4973e14 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -61,6 +61,7 @@
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/ctype.h>
+#include <linux/sched.h>
 #include <linux/kthread.h>
 #include <linux/version.h>
 #include <linux/mutex.h>
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 9819962..d38a25f 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -326,10 +326,16 @@
 	struct tty_struct *tty = acm->tty;
 	struct acm_ru *rcv;
 	unsigned long flags;
-	int i = 0;
+	unsigned char throttled;
 	dbg("Entering acm_rx_tasklet");
 
-	if (!ACM_READY(acm) || acm->throttle)
+	if (!ACM_READY(acm))
+		return;
+
+	spin_lock(&acm->throttle_lock);
+	throttled = acm->throttle;
+	spin_unlock(&acm->throttle_lock);
+	if (throttled)
 		return;
 
 next_buffer:
@@ -346,22 +352,20 @@
 	dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
 
 	tty_buffer_request_room(tty, buf->size);
-	if (!acm->throttle)
+	spin_lock(&acm->throttle_lock);
+	throttled = acm->throttle;
+	spin_unlock(&acm->throttle_lock);
+	if (!throttled)
 		tty_insert_flip_string(tty, buf->base, buf->size);
 	tty_flip_buffer_push(tty);
 
-	spin_lock(&acm->throttle_lock);
-	if (acm->throttle) {
-		dbg("Throtteling noticed");
-		memmove(buf->base, buf->base + i, buf->size - i);
-		buf->size -= i;
-		spin_unlock(&acm->throttle_lock);
+	if (throttled) {
+		dbg("Throttling noticed");
 		spin_lock_irqsave(&acm->read_lock, flags);
 		list_add(&buf->list, &acm->filled_read_bufs);
 		spin_unlock_irqrestore(&acm->read_lock, flags);
 		return;
 	}
-	spin_unlock(&acm->throttle_lock);
 
 	spin_lock_irqsave(&acm->read_lock, flags);
 	list_add(&buf->list, &acm->spare_read_bufs);
@@ -467,7 +471,8 @@
 		goto bail_out;
 	}
 
-	if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
+	if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
+	    (acm->ctrl_caps & USB_CDC_CAP_LINE))
 		goto full_bailout;
 
 	INIT_LIST_HEAD(&acm->spare_read_urbs);
@@ -480,6 +485,8 @@
 		list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
 	}
 
+	acm->throttle = 0;
+
 	tasklet_schedule(&acm->urb_task);
 
 done:
@@ -1092,6 +1099,10 @@
 	{ USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */
 	.driver_info = SINGLE_RX_URB, /* firmware bug */
 	},
+	{ USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */
+	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+	},
+
 	/* control interfaces with various AT-command sets */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_ACM_PROTO_AT_V25TER) },
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 34e9bac..b607870 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -4,7 +4,7 @@
 
 usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o driver.o \
 			config.o file.o buffer.o sysfs.o endpoint.o \
-			devio.o notify.o generic.o
+			devio.o notify.o generic.o quirks.o
 
 ifeq ($(CONFIG_PCI),y)
 	usbcore-objs	+= hcd-pci.o
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index a47c30b..aefc798 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -604,10 +604,6 @@
 	lock_kernel();
 	if (!st) {
 		st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
-		if (!st) {
-			unlock_kernel();
-			return POLLIN;
-		}
 
 		/* we may have dropped BKL - need to check for having lost the race */
 		if (file->private_data) {
@@ -615,6 +611,11 @@
 			st = file->private_data;
 			goto lost_race;
 		}
+		/* we haven't lost - check for allocation failure now */
+		if (!st) {
+			unlock_kernel();
+			return POLLIN;
+		}
 
 		/*
 		 * need to prevent the module from being unloaded, since
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 2087766..274f14f 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -857,11 +857,11 @@
 
 static int proc_setconfig(struct dev_state *ps, void __user *arg)
 {
-	unsigned int u;
+	int u;
 	int status = 0;
  	struct usb_host_config *actconfig;
 
-	if (get_user(u, (unsigned int __user *)arg))
+	if (get_user(u, (int __user *)arg))
 		return -EFAULT;
 
  	actconfig = ps->dev->actconfig;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 600d1bc..9e3e943 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -366,19 +366,8 @@
 EXPORT_SYMBOL(usb_driver_release_interface);
 
 /* returns 0 if no match, 1 if match */
-int usb_match_one_id(struct usb_interface *interface,
-		     const struct usb_device_id *id)
+int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
 {
-	struct usb_host_interface *intf;
-	struct usb_device *dev;
-
-	/* proc_connectinfo in devio.c may call us with id == NULL. */
-	if (id == NULL)
-		return 0;
-
-	intf = interface->cur_altsetting;
-	dev = interface_to_usbdev(interface);
-
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
 	    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
 		return 0;
@@ -409,6 +398,26 @@
 	    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
 		return 0;
 
+	return 1;
+}
+
+/* returns 0 if no match, 1 if match */
+int usb_match_one_id(struct usb_interface *interface,
+		     const struct usb_device_id *id)
+{
+	struct usb_host_interface *intf;
+	struct usb_device *dev;
+
+	/* proc_connectinfo in devio.c may call us with id == NULL. */
+	if (id == NULL)
+		return 0;
+
+	intf = interface->cur_altsetting;
+	dev = interface_to_usbdev(interface);
+
+	if (!usb_match_device(dev, id))
+		return 0;
+
 	/* The interface class, subclass, and protocol should never be
 	 * checked for a match if the device class is Vendor Specific,
 	 * unless the match record specifies the Vendor ID. */
@@ -743,6 +752,7 @@
  * usb_register_driver - register a USB interface driver
  * @new_driver: USB operations for the interface driver
  * @owner: module owner of this driver.
+ * @mod_name: module name string
  *
  * Registers a USB interface driver with the USB core.  The list of
  * unattached interfaces will be rescanned whenever a new driver is
@@ -953,12 +963,16 @@
 	int			i;
 	struct usb_interface	*intf;
 
-	/* For autosuspend, fail fast if anything is in use.
-	 * Also fail if any interfaces require remote wakeup but it
-	 * isn't available. */
+	/* For autosuspend, fail fast if anything is in use or autosuspend
+	 * is disabled.  Also fail if any interfaces require remote wakeup
+	 * but it isn't available.
+	 */
 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
 	if (udev->pm_usage_cnt > 0)
 		return -EBUSY;
+	if (!udev->autosuspend_delay)
+		return -EPERM;
+
 	if (udev->actconfig) {
 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
 			intf = udev->actconfig->interface[i];
@@ -981,7 +995,7 @@
 
 #define autosuspend_check(udev)		0
 
-#endif
+#endif	/* CONFIG_USB_SUSPEND */
 
 /**
  * usb_suspend_both - suspend a USB device and its interfaces
@@ -1176,7 +1190,7 @@
 			udev->pm_usage_cnt -= inc_usage_cnt;
 	} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
 		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-				USB_AUTOSUSPEND_DELAY);
+				udev->autosuspend_delay);
 	usb_pm_unlock(udev);
 	return status;
 }
@@ -1211,6 +1225,26 @@
 }
 
 /**
+ * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
+ * @udev: the usb_device to autosuspend
+ *
+ * This routine should be called when a core subsystem thinks @udev may
+ * be ready to autosuspend.
+ *
+ * @udev's usage counter left unchanged.  If it or any of the usage counters
+ * for an active interface is greater than 0, or autosuspend is not allowed
+ * for any other reason, no autosuspend request will be queued.
+ *
+ * This routine can run only in process context.
+ */
+void usb_try_autosuspend_device(struct usb_device *udev)
+{
+	usb_autopm_do_device(udev, 0);
+	// dev_dbg(&udev->dev, "%s: cnt %d\n",
+	// 		__FUNCTION__, udev->pm_usage_cnt);
+}
+
+/**
  * usb_autoresume_device - immediately autoresume a USB device and its interfaces
  * @udev: the usb_device to autoresume
  *
@@ -1260,7 +1294,7 @@
 				intf->pm_usage_cnt -= inc_usage_cnt;
 		} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
 			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-					USB_AUTOSUSPEND_DELAY);
+					udev->autosuspend_delay);
 	}
 	usb_pm_unlock(udev);
 	return status;
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 5e628ae..e0ec704 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -229,7 +229,7 @@
 	kref_init(&ep_class->kref);
 	ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
 	if (IS_ERR(ep_class->class)) {
-		result = IS_ERR(ep_class->class);
+		result = PTR_ERR(ep_class->class);
 		goto class_create_error;
 	}
 
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index b531a4f..9bbcb20 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -184,7 +184,7 @@
 	/* if this is only an unbind, not a physical disconnect, then
 	 * unconfigure the device */
 	if (udev->actconfig)
-		usb_set_configuration(udev, 0);
+		usb_set_configuration(udev, -1);
 
 	usb_remove_sysfs_dev_files(udev);
 }
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 590ec82..4140074 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -44,6 +44,7 @@
 		struct usb_hub_status	hub;
 		struct usb_port_status	port;
 	}			*status;	/* buffer for status reports */
+	struct mutex		status_mutex;	/* for the status buffer */
 
 	int			error;		/* last reported error */
 	int			nerrors;	/* track consecutive errors */
@@ -535,6 +536,7 @@
 {
 	int ret;
 
+	mutex_lock(&hub->status_mutex);
 	ret = get_hub_status(hub->hdev, &hub->status->hub);
 	if (ret < 0)
 		dev_err (hub->intfdev,
@@ -544,6 +546,7 @@
 		*change = le16_to_cpu(hub->status->hub.wHubChange); 
 		ret = 0;
 	}
+	mutex_unlock(&hub->status_mutex);
 	return ret;
 }
 
@@ -617,6 +620,7 @@
 		ret = -ENOMEM;
 		goto fail;
 	}
+	mutex_init(&hub->status_mutex);
 
 	hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
 	if (!hub->descriptor) {
@@ -1283,6 +1287,9 @@
 	if (!try_module_get(THIS_MODULE))
 		return -EINVAL;
 
+	/* Determine quirks */
+	usb_detect_quirks(udev);
+
 	err = usb_get_configuration(udev);
 	if (err < 0) {
 		dev_err(&udev->dev, "can't read configurations, error %d\n",
@@ -1396,6 +1403,7 @@
 {
 	int ret;
 
+	mutex_lock(&hub->status_mutex);
 	ret = get_port_status(hub->hdev, port1, &hub->status->port);
 	if (ret < 4) {
 		dev_err (hub->intfdev,
@@ -1407,6 +1415,7 @@
 		*change = le16_to_cpu(hub->status->port.wPortChange); 
 		ret = 0;
 	}
+	mutex_unlock(&hub->status_mutex);
 	return ret;
 }
 
@@ -1904,6 +1913,7 @@
 	struct usb_hub		*hub = usb_get_intfdata (intf);
 	struct usb_device	*hdev = hub->hdev;
 	unsigned		port1;
+	int			status = 0;
 
 	/* fail if children aren't already suspended */
 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -1927,24 +1937,18 @@
 
 	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
 
-	/* "global suspend" of the downstream HC-to-USB interface */
-	if (!hdev->parent) {
-		struct usb_bus	*bus = hdev->bus;
-		if (bus) {
-			int	status = hcd_bus_suspend (bus);
-
-			if (status != 0) {
-				dev_dbg(&hdev->dev, "'global' suspend %d\n",
-					status);
-				return status;
-			}
-		} else
-			return -EOPNOTSUPP;
-	}
-
 	/* stop khubd and related activity */
 	hub_quiesce(hub);
-	return 0;
+
+	/* "global suspend" of the downstream HC-to-USB interface */
+	if (!hdev->parent) {
+		status = hcd_bus_suspend(hdev->bus);
+		if (status != 0) {
+			dev_dbg(&hdev->dev, "'global' suspend %d\n", status);
+			hub_activate(hub);
+		}
+	}
+	return status;
 }
 
 static int hub_resume(struct usb_interface *intf)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 8aca357..2f17468 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -11,6 +11,7 @@
 #include <linux/timer.h>
 #include <linux/ctype.h>
 #include <linux/device.h>
+#include <linux/usb/quirks.h>
 #include <asm/byteorder.h>
 #include <asm/scatterlist.h>
 
@@ -685,7 +686,10 @@
 
 	/* Try to read the string descriptor by asking for the maximum
 	 * possible number of bytes */
-	rc = usb_get_string(dev, langid, index, buf, 255);
+	if (dev->quirks & USB_QUIRK_STRING_FETCH_255)
+		rc = -EIO;
+	else
+		rc = usb_get_string(dev, langid, index, buf, 255);
 
 	/* If that failed try to read the descriptor length, then
 	 * ask for just that many bytes */
@@ -1316,6 +1320,14 @@
  * use this kind of configurability; many devices only have one
  * configuration.
  *
+ * @configuration is the value of the configuration to be installed.
+ * According to the USB spec (e.g. section 9.1.1.5), configuration values
+ * must be non-zero; a value of zero indicates that the device in
+ * unconfigured.  However some devices erroneously use 0 as one of their
+ * configuration values.  To help manage such devices, this routine will
+ * accept @configuration = -1 as indicating the device should be put in
+ * an unconfigured state.
+ *
  * USB device configurations may affect Linux interoperability,
  * power consumption and the functionality available.  For example,
  * the default configuration is limited to using 100mA of bus power,
@@ -1347,10 +1359,15 @@
 	struct usb_interface **new_interfaces = NULL;
 	int n, nintf;
 
-	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
-		if (dev->config[i].desc.bConfigurationValue == configuration) {
-			cp = &dev->config[i];
-			break;
+	if (configuration == -1)
+		configuration = 0;
+	else {
+		for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+			if (dev->config[i].desc.bConfigurationValue ==
+					configuration) {
+				cp = &dev->config[i];
+				break;
+			}
 		}
 	}
 	if ((!cp && configuration != 0))
@@ -1359,6 +1376,7 @@
 	/* The USB spec says configuration 0 means unconfigured.
 	 * But if a device includes a configuration numbered 0,
 	 * we will accept it as a correctly configured state.
+	 * Use -1 if you really want to unconfigure the device.
 	 */
 	if (cp && configuration == 0)
 		dev_warn(&dev->dev, "config 0 descriptor??\n");
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index 627a5a2..7f31a49 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -31,7 +31,7 @@
 { USB_DEVICE_INFO(7, 1, 3) },
 #endif
 
-#ifdef	CONFIG_USB_CDCETHER
+#ifdef	CONFIG_USB_NET_CDCETHER
 /* Linux-USB CDC Ethernet gadget */
 { USB_DEVICE(0x0525, 0xa4a1), },
 /* Linux-USB CDC Ethernet + RNDIS gadget */
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
new file mode 100644
index 0000000..0e5c646
--- /dev/null
+++ b/drivers/usb/core/quirks.c
@@ -0,0 +1,77 @@
+/*
+ * USB device quirk handling logic and table
+ *
+ * Copyright (c) 2007 Oliver Neukum
+ * Copyright (c) 2007 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 as published by the Free
+ * Software Foundation, version 2.
+ *
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/usb/quirks.h>
+#include "usb.h"
+
+/* List of quirky USB devices.  Please keep this list ordered by:
+ * 	1) Vendor ID
+ * 	2) Product ID
+ * 	3) Class ID
+ *
+ * as we want specific devices to be overridden first, and only after that, any
+ * class specific quirks.
+ *
+ * Right now the logic aborts if it finds a valid device in the table, we might
+ * want to change that in the future if it turns out that a whole class of
+ * devices is broken...
+ */
+static const struct usb_device_id usb_quirk_list[] = {
+	/* HP 5300/5370C scanner */
+	{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+
+	/* Elsa MicroLink 56k (V.250) */
+	{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+
+	{ }  /* terminating entry must be last */
+};
+
+static void usb_autosuspend_quirk(struct usb_device *udev)
+{
+#ifdef	CONFIG_USB_SUSPEND
+	/* disable autosuspend, but allow the user to re-enable it via sysfs */
+	udev->autosuspend_delay = 0;
+#endif
+}
+
+static const struct usb_device_id *find_id(struct usb_device *udev)
+{
+	const struct usb_device_id *id = usb_quirk_list;
+
+	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
+			id->driver_info; id++) {
+		if (usb_match_device(udev, id))
+			return id;
+	}
+	return NULL;
+}
+
+/*
+ * Detect any quirks the device has, and do any housekeeping for it if needed.
+ */
+void usb_detect_quirks(struct usb_device *udev)
+{
+	const struct usb_device_id *id = usb_quirk_list;
+
+	id = find_id(udev);
+	if (id)
+		udev->quirks = (u32)(id->driver_info);
+	if (udev->quirks)
+		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
+				udev->quirks);
+
+	/* do any special quirk handling here if needed */
+	if (udev->quirks & USB_QUIRK_NO_AUTOSUSPEND)
+		usb_autosuspend_quirk(udev);
+}
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 4eaa0ee..311d5df 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -63,7 +63,7 @@
 	struct usb_device	*udev = to_usb_device(dev);
 	int			config, value;
 
-	if (sscanf(buf, "%u", &config) != 1 || config > 255)
+	if (sscanf(buf, "%d", &config) != 1 || config < -1 || config > 255)
 		return -EINVAL;
 	usb_lock_device(udev);
 	value = usb_set_configuration(udev, config);
@@ -148,6 +148,75 @@
 }
 static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
 
+static ssize_t
+show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev;
+
+	udev = to_usb_device(dev);
+	return sprintf(buf, "0x%x\n", udev->quirks);
+}
+static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
+
+#ifdef	CONFIG_USB_SUSPEND
+
+static ssize_t
+show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev = to_usb_device(dev);
+
+	return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ);
+}
+
+static ssize_t
+set_autosuspend(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct usb_device *udev = to_usb_device(dev);
+	unsigned value, old;
+
+	if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ)
+		return -EINVAL;
+	value *= HZ;
+
+	old = udev->autosuspend_delay;
+	udev->autosuspend_delay = value;
+	if (value > 0 && old == 0)
+		usb_try_autosuspend_device(udev);
+
+	return count;
+}
+
+static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
+		show_autosuspend, set_autosuspend);
+
+static char power_group[] = "power";
+
+static int add_power_attributes(struct device *dev)
+{
+	int rc = 0;
+
+	if (is_usb_device(dev))
+		rc = sysfs_add_file_to_group(&dev->kobj,
+				&dev_attr_autosuspend.attr,
+				power_group);
+	return rc;
+}
+
+static void remove_power_attributes(struct device *dev)
+{
+	sysfs_remove_file_from_group(&dev->kobj,
+			&dev_attr_autosuspend.attr,
+			power_group);
+}
+
+#else
+
+#define add_power_attributes(dev)	0
+#define remove_power_attributes(dev)	do {} while (0)
+
+#endif	/* CONFIG_USB_SUSPEND */
+
 /* Descriptor fields */
 #define usb_descriptor_attr_le16(field, format_string)			\
 static ssize_t								\
@@ -204,6 +273,7 @@
 	&dev_attr_devnum.attr,
 	&dev_attr_version.attr,
 	&dev_attr_maxchild.attr,
+	&dev_attr_quirks.attr,
 	NULL,
 };
 static struct attribute_group dev_attr_grp = {
@@ -219,6 +289,10 @@
 	if (retval)
 		return retval;
 
+	retval = add_power_attributes(dev);
+	if (retval)
+		goto error;
+
 	if (udev->manufacturer) {
 		retval = device_create_file(dev, &dev_attr_manufacturer);
 		if (retval)
@@ -239,10 +313,7 @@
 		goto error;
 	return 0;
 error:
-	usb_remove_ep_files(&udev->ep0);
-	device_remove_file(dev, &dev_attr_manufacturer);
-	device_remove_file(dev, &dev_attr_product);
-	device_remove_file(dev, &dev_attr_serial);
+	usb_remove_sysfs_dev_files(udev);
 	return retval;
 }
 
@@ -251,14 +322,11 @@
 	struct device *dev = &udev->dev;
 
 	usb_remove_ep_files(&udev->ep0);
+	device_remove_file(dev, &dev_attr_manufacturer);
+	device_remove_file(dev, &dev_attr_product);
+	device_remove_file(dev, &dev_attr_serial);
+	remove_power_attributes(dev);
 	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
-
-	if (udev->manufacturer)
-		device_remove_file(dev, &dev_attr_manufacturer);
-	if (udev->product)
-		device_remove_file(dev, &dev_attr_product);
-	if (udev->serial)
-		device_remove_file(dev, &dev_attr_serial);
 }
 
 /* Interface fields */
@@ -362,33 +430,28 @@
 
 int usb_create_sysfs_intf_files(struct usb_interface *intf)
 {
+	struct device *dev = &intf->dev;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct usb_host_interface *alt = intf->cur_altsetting;
 	int retval;
 
-	retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+	retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
 	if (retval)
-		goto error;
+		return retval;
 
 	if (alt->string == NULL)
 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
 	if (alt->string)
-		retval = device_create_file(&intf->dev, &dev_attr_interface);
+		retval = device_create_file(dev, &dev_attr_interface);
 	usb_create_intf_ep_files(intf, udev);
 	return 0;
-error:
-	if (alt->string)
-		device_remove_file(&intf->dev, &dev_attr_interface);
-	sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
-	usb_remove_intf_ep_files(intf);
-	return retval;
 }
 
 void usb_remove_sysfs_intf_files(struct usb_interface *intf)
 {
-	usb_remove_intf_ep_files(intf);
-	sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
+	struct device *dev = &intf->dev;
 
-	if (intf->cur_altsetting->string)
-		device_remove_file(&intf->dev, &dev_attr_interface);
+	usb_remove_intf_ep_files(intf);
+	device_remove_file(dev, &dev_attr_interface);
+	sysfs_remove_group(&dev->kobj, &intf_attr_grp);
 }
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 3db721c..54b42ce 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -22,6 +22,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
@@ -50,6 +51,16 @@
 
 struct workqueue_struct *ksuspend_usb_wq;	/* For autosuspend */
 
+#ifdef	CONFIG_USB_SUSPEND
+static int usb_autosuspend_delay = 2;		/* Default delay value,
+						 * in seconds */
+module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644);
+MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
+
+#else
+#define usb_autosuspend_delay		0
+#endif
+
 
 /**
  * usb_ifnum_to_if - get the interface object with a given interface number
@@ -306,6 +317,7 @@
 #ifdef	CONFIG_PM
 	mutex_init(&dev->pm_mutex);
 	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
+	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
 #endif
 	return dev;
 }
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 17830a8..08b5a04 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -13,6 +13,7 @@
 		struct usb_interface *intf);
 extern void usb_release_interface_cache(struct kref *ref);
 extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
+extern void usb_detect_quirks(struct usb_device *udev);
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
 		unsigned int size);
@@ -21,6 +22,8 @@
 
 extern void usb_kick_khubd(struct usb_device *dev);
 extern void usb_resume_root_hub(struct usb_device *dev);
+extern int usb_match_device(struct usb_device *dev,
+			    const struct usb_device_id *id);
 
 extern int  usb_hub_init(void);
 extern void usb_hub_cleanup(void);
@@ -62,14 +65,14 @@
 
 #ifdef CONFIG_USB_SUSPEND
 
-#define USB_AUTOSUSPEND_DELAY	(HZ*2)
-
 extern void usb_autosuspend_device(struct usb_device *udev);
+extern void usb_try_autosuspend_device(struct usb_device *udev);
 extern int usb_autoresume_device(struct usb_device *udev);
 
 #else
 
-#define usb_autosuspend_device(udev)	do {} while (0)
+#define usb_autosuspend_device(udev)		do {} while (0)
+#define usb_try_autosuspend_device(udev)	do {} while (0)
 static inline int usb_autoresume_device(struct usb_device *udev)
 {
 	return 0;
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index f390501..a467780 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -30,7 +30,6 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
@@ -785,7 +784,7 @@
 	return status;
 }
 
-static struct usb_ep_ops at91_ep_ops = {
+static const struct usb_ep_ops at91_ep_ops = {
 	.enable		= at91_ep_enable,
 	.disable	= at91_ep_disable,
 	.alloc_request	= at91_ep_alloc_request,
@@ -913,7 +912,7 @@
 		at91_udp_write(udc, AT91_UDP_TXVC, 0);
 		if (cpu_is_at91rm9200())
 			at91_set_gpio_value(udc->board.pullup_pin, 1);
-		else if (cpu_is_at91sam9260()) {
+		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
 			txvc |= AT91_UDP_TXVC_PUON;
@@ -930,7 +929,7 @@
 		at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
 		if (cpu_is_at91rm9200())
 			at91_set_gpio_value(udc->board.pullup_pin, 0);
-		else if (cpu_is_at91sam9260()) {
+		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
 			txvc &= ~AT91_UDP_TXVC_PUON;
@@ -1652,7 +1651,7 @@
 	pullup(platform_get_drvdata(dev), 0);
 }
 
-static int __devinit at91udc_probe(struct platform_device *pdev)
+static int __init at91udc_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	struct at91_udc	*udc;
@@ -1763,7 +1762,7 @@
 	return retval;
 }
 
-static int __devexit at91udc_remove(struct platform_device *pdev)
+static int __exit at91udc_remove(struct platform_device *pdev)
 {
 	struct at91_udc *udc = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -1837,8 +1836,7 @@
 #endif
 
 static struct platform_driver at91_udc = {
-	.probe		= at91udc_probe,
-	.remove		= __devexit_p(at91udc_remove),
+	.remove		= __exit_p(at91udc_remove),
 	.shutdown	= at91udc_shutdown,
 	.suspend	= at91udc_suspend,
 	.resume		= at91udc_resume,
@@ -1848,13 +1846,13 @@
 	},
 };
 
-static int __devinit udc_init_module(void)
+static int __init udc_init_module(void)
 {
-	return platform_driver_register(&at91_udc);
+	return platform_driver_probe(&at91_udc, at91udc_probe);
 }
 module_init(udc_init_module);
 
-static void __devexit udc_exit_module(void)
+static void __exit udc_exit_module(void)
 {
 	platform_driver_unregister(&at91_udc);
 }
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 3c2bc07..7d7909c 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -40,7 +40,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 22e3c94..04e6b85 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index f04a29a..c6b6479 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1953,7 +1953,7 @@
 	struct inode	*inode = filp->f_path.dentry->d_inode;
 	unsigned long	rc;
 
-	rc = invalidate_inode_pages(inode->i_mapping);
+	rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
 	VLDBG(curlun, "invalidate_inode_pages -> %ld\n", rc);
 }
 
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index e873cf4..7b3a326 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -29,7 +29,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 34296e7..188c74a 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -553,6 +553,7 @@
 {
 	struct kiocb_priv	*priv = iocb->private;
 	ssize_t			len, total;
+	void			*to_copy;
 	int			i;
 
 	/* we "retry" to get the right mm context for this: */
@@ -560,10 +561,11 @@
 	/* copy stuff into user buffers */
 	total = priv->actual;
 	len = 0;
+	to_copy = priv->buf;
 	for (i=0; i < priv->nr_segs; i++) {
 		ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total);
 
-		if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) {
+		if (copy_to_user(priv->iv[i].iov_base, to_copy, this)) {
 			if (len == 0)
 				len = -EFAULT;
 			break;
@@ -571,6 +573,7 @@
 
 		total -= this;
 		len += this;
+		to_copy += this;
 		if (total == 0)
 			break;
 	}
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 7617ff7..49d7377 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -53,7 +53,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 1401043..8f9a2b6 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -28,7 +28,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/timer.h>
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 0d22536..f01890d 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -33,7 +33,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/timer.h>
@@ -156,7 +155,7 @@
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 	if (mach->gpio_vbus)
-		return pxa_gpio_get(mach->gpio_vbus);
+		return udc_gpio_get(mach->gpio_vbus);
 	if (mach->udc_is_connected)
 		return mach->udc_is_connected();
 	return 1;
@@ -168,7 +167,7 @@
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 	if (mach->gpio_pullup)
-		pxa_gpio_set(mach->gpio_pullup, 0);
+		udc_gpio_set(mach->gpio_pullup, 0);
 	else if (mach->udc_command)
 		mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
 }
@@ -178,7 +177,7 @@
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 	if (mach->gpio_pullup)
-		pxa_gpio_set(mach->gpio_pullup, 1);
+		udc_gpio_set(mach->gpio_pullup, 1);
 	else if (mach->udc_command)
 		mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
 }
@@ -1756,7 +1755,7 @@
 static irqreturn_t udc_vbus_irq(int irq, void *_dev)
 {
 	struct pxa2xx_udc	*dev = _dev;
-	int			vbus = pxa_gpio_get(dev->mach->gpio_vbus);
+	int			vbus = udc_gpio_get(dev->mach->gpio_vbus);
 
 	pxa2xx_udc_vbus_session(&dev->gadget, vbus);
 	return IRQ_HANDLED;
@@ -2546,15 +2545,13 @@
 	dev->dev = &pdev->dev;
 	dev->mach = pdev->dev.platform_data;
 	if (dev->mach->gpio_vbus) {
-		vbus_irq = IRQ_GPIO(dev->mach->gpio_vbus & GPIO_MD_MASK_NR);
-		pxa_gpio_mode((dev->mach->gpio_vbus & GPIO_MD_MASK_NR)
-				| GPIO_IN);
+		udc_gpio_init_vbus(dev->mach->gpio_vbus);
+		vbus_irq = udc_gpio_to_irq(dev->mach->gpio_vbus);
 		set_irq_type(vbus_irq, IRQT_BOTHEDGE);
 	} else
 		vbus_irq = 0;
 	if (dev->mach->gpio_pullup)
-		pxa_gpio_mode((dev->mach->gpio_pullup & GPIO_MD_MASK_NR)
-				| GPIO_OUT | GPIO_DFLT_LOW);
+		udc_gpio_init_pullup(dev->mach->gpio_pullup);
 
 	init_timer(&dev->timer);
 	dev->timer.function = udc_watchdog;
@@ -2614,7 +2611,7 @@
 #endif
 	if (vbus_irq) {
 		retval = request_irq(vbus_irq, udc_vbus_irq,
-				SA_INTERRUPT | SA_SAMPLE_RANDOM,
+				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
 				driver_name, dev);
 		if (retval != 0) {
 			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 8e598c8..773e549 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -177,21 +177,6 @@
 
 static struct pxa2xx_udc *the_controller;
 
-static inline int pxa_gpio_get(unsigned gpio)
-{
-	return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
-}
-
-static inline void pxa_gpio_set(unsigned gpio, int is_on)
-{
-	int mask = GPIO_bit(gpio);
-
-	if (is_on)
-		GPSR(gpio) = mask;
-	else
-		GPCR(gpio) = mask;
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 408c338..6ec8cf1 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1419,7 +1419,6 @@
 			return -EIO;
 		}
 
-		rndis_connect_state [i]->nlink = 1;
 		rndis_connect_state [i]->write_proc = rndis_proc_write;
 		rndis_connect_state [i]->read_proc = rndis_proc_read;
 		rndis_connect_state [i]->data = (void *)
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 6c742a9..e552668 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -21,7 +21,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
@@ -1700,6 +1699,7 @@
 			memcpy(&port->port_line_coding, req->buf, ret);
 			spin_unlock(&port->port_lock);
 		}
+		ret = 0;
 		break;
 
 	case USB_CDC_REQ_GET_LINE_CODING:
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index ebe04e0..8c85e33 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -66,7 +66,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 246afea..43eddae 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -322,7 +322,7 @@
 
 #else
 
-/* troubleshooting help: expose state in driverfs */
+/* troubleshooting help: expose state in sysfs */
 
 #define speed_char(info1) ({ char tmp; \
 		switch (info1 & (3 << 12)) { \
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 185721d..a740564 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -42,6 +42,9 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
+#ifdef CONFIG_PPC_PS3
+#include <asm/firmware.h>
+#endif
 
 
 /*-------------------------------------------------------------------------*/
@@ -299,6 +302,19 @@
 	spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
+/* On some systems, leaving remote wakeup enabled prevents system shutdown.
+ * The firmware seems to think that powering off is a wakeup event!
+ * This routine turns off remote wakeup and everything else, on all ports.
+ */
+static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
+{
+	int	port = HCS_N_PORTS(ehci->hcs_params);
+
+	while (port--)
+		ehci_writel(ehci, PORT_RWC_BITS,
+				&ehci->regs->port_status[port]);
+}
+
 /* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
  * This forcibly disables dma and IRQs, helping kexec and other cases
  * where the next system software may expect clean state.
@@ -310,9 +326,13 @@
 
 	ehci = hcd_to_ehci (hcd);
 	(void) ehci_halt (ehci);
+	ehci_turn_off_all_ports(ehci);
 
 	/* make BIOS/etc use companion controller during reboot */
 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+
+	/* unblock posted writes */
+	ehci_readl(ehci, &ehci->regs->configured_flag);
 }
 
 static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
@@ -951,15 +971,18 @@
 #endif
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER);
-	if (retval < 0) {
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
+		retval = ps3_system_bus_driver_register(
+				&PS3_SYSTEM_BUS_DRIVER);
+		if (retval < 0) {
 #ifdef PLATFORM_DRIVER
-		platform_driver_unregister(&PLATFORM_DRIVER);
+			platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PCI_DRIVER
-		pci_unregister_driver(&PCI_DRIVER);
+			pci_unregister_driver(&PCI_DRIVER);
 #endif
-		return retval;
+			return retval;
+		}
 	}
 #endif
 
@@ -976,7 +999,8 @@
 	pci_unregister_driver(&PCI_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ehci_hcd_cleanup);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 0d83c6d..9af529d 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -36,6 +36,8 @@
 	int			port;
 	int			mask;
 
+	ehci_dbg(ehci, "suspend root hub\n");
+
 	if (time_before (jiffies, ehci->next_statechange))
 		msleep(5);
 
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 371f194..4d781a2 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -104,7 +104,7 @@
 	dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
 		__LINE__, dev->m_region->lpar_addr);
 
-	result = ps3_alloc_io_irq(dev->interrupt_id, &virq);
+	result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
 
 	if (result) {
 		dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index ec0da03..46fa57a 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -677,10 +677,10 @@
 {
 #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
 	return ehci_big_endian_mmio(ehci) ?
-		readl_be((__force u32 *)regs) :
-		readl((__force u32 *)regs);
+		readl_be(regs) :
+		readl(regs);
 #else
-	return readl((__force u32 *)regs);
+	return readl(regs);
 #endif
 }
 
@@ -689,10 +689,10 @@
 {
 #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
 	ehci_big_endian_mmio(ehci) ?
-		writel_be(val, (__force u32 *)regs) :
-		writel(val, (__force u32 *)regs);
+		writel_be(val, regs) :
+		writel(val, regs);
 #else
-	writel(val, (__force u32 *)regs);
+	writel(val, regs);
 #endif
 }
 
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 282d82e..32f7caf 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
@@ -2163,9 +2162,8 @@
 
 	maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
 
-	sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
+	sb_desc = kmem_cache_zalloc(usb_desc_cache, SLAB_FLAG);
 	assert(sb_desc != NULL);
-	memset(sb_desc, 0, sizeof(USB_SB_Desc_t));
 
 
 	if (usb_pipeout(urb->pipe)) {
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 2718b5d..46873f2 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1577,7 +1577,7 @@
 
 #define resource_len(r) (((r)->end - (r)->start) + 1)
 
-static int __init isp116x_probe(struct platform_device *pdev)
+static int __devinit isp116x_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
 	struct isp116x *isp116x;
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 9303464..d849c80 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -18,19 +18,38 @@
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
 
 #ifndef CONFIG_ARCH_AT91
 #error "CONFIG_ARCH_AT91 must be defined."
 #endif
 
-/* interface and function clocks */
-static struct clk *iclk, *fclk;
+/* interface and function clocks; sometimes also an AHB clock */
+static struct clk *iclk, *fclk, *hclk;
 static int clocked;
 
 extern int usb_disabled(void);
 
 /*-------------------------------------------------------------------------*/
 
+static void at91_start_clock(void)
+{
+	if (cpu_is_at91sam9261())
+		clk_enable(hclk);
+	clk_enable(iclk);
+	clk_enable(fclk);
+	clocked = 1;
+}
+
+static void at91_stop_clock(void)
+{
+	clk_disable(fclk);
+	clk_disable(iclk);
+	if (cpu_is_at91sam9261())
+		clk_disable(hclk);
+	clocked = 0;
+}
+
 static void at91_start_hc(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -41,9 +60,7 @@
 	/*
 	 * Start the USB clocks.
 	 */
-	clk_enable(iclk);
-	clk_enable(fclk);
-	clocked = 1;
+	at91_start_clock();
 
 	/*
 	 * The USB host controller must remain in reset.
@@ -66,9 +83,7 @@
 	/*
 	 * Stop the USB clocks.
 	 */
-	clk_disable(fclk);
-	clk_disable(iclk);
-	clocked = 0;
+	at91_stop_clock();
 }
 
 
@@ -126,6 +141,8 @@
 
 	iclk = clk_get(&pdev->dev, "ohci_clk");
 	fclk = clk_get(&pdev->dev, "uhpck");
+	if (cpu_is_at91sam9261())
+		hclk = clk_get(&pdev->dev, "hck0");
 
 	at91_start_hc(pdev);
 	ohci_hcd_init(hcd_to_ohci(hcd));
@@ -137,6 +154,8 @@
 	/* Error handling */
 	at91_stop_hc(pdev);
 
+	if (cpu_is_at91sam9261())
+		clk_put(hclk);
 	clk_put(fclk);
 	clk_put(iclk);
 
@@ -171,9 +190,11 @@
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 
+	if (cpu_is_at91sam9261())
+		clk_put(hclk);
 	clk_put(fclk);
 	clk_put(iclk);
-	fclk = iclk = NULL;
+	fclk = iclk = hclk = NULL;
 
 	dev_set_drvdata(&pdev->dev, NULL);
 	return 0;
@@ -280,9 +301,7 @@
 	 */
 	if (at91_suspend_entering_slow_clock()) {
 		ohci_usb_reset (ohci);
-		clk_disable(fclk);
-		clk_disable(iclk);
-		clocked = 0;
+		at91_stop_clock();
 	}
 
 	return 0;
@@ -295,11 +314,8 @@
 	if (device_may_wakeup(&pdev->dev))
 		disable_irq_wake(hcd->irq);
 
-	if (!clocked) {
-		clk_enable(iclk);
-		clk_enable(fclk);
-		clocked = 1;
-	}
+	if (!clocked)
+		at91_start_clock();
 
 	return 0;
 }
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index 44c60fba..a68ce9d 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -78,7 +78,7 @@
 
 	ohci_hcd_init(hcd_to_ohci(hcd));
 
-	retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
+	retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED);
 	if (retval == 0)
 		return retval;
 
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index fa6a7ce..f0d29ed 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -42,6 +42,9 @@
 #include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
+#ifdef CONFIG_PPC_PS3
+#include <asm/firmware.h>
+#endif
 
 #include "../core/hcd.h"
 
@@ -944,9 +947,12 @@
 		sizeof (struct ed), sizeof (struct td));
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER);
-	if (retval < 0)
-		goto error_ps3;
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
+		retval = ps3_system_bus_driver_register(
+				&PS3_SYSTEM_BUS_DRIVER);
+		if (retval < 0)
+			goto error_ps3;
+	}
 #endif
 
 #ifdef PLATFORM_DRIVER
@@ -992,7 +998,8 @@
  error_platform:
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
  error_ps3:
 #endif
 	return retval;
@@ -1014,7 +1021,8 @@
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ohci_hcd_mod_exit);
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 893b172..d601bbb 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -421,7 +421,7 @@
 	ohci_hcd_init(ohci);
 
 	dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
-	ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
 	if (ret == 0)
 		return ret;
 
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
index de45eb0..85fdfd2 100644
--- a/drivers/usb/host/ohci-pnx8550.c
+++ b/drivers/usb/host/ohci-pnx8550.c
@@ -107,7 +107,7 @@
 
 	ohci_hcd_init(hcd_to_ohci(hcd));
 
-	retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+	retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);
 	if (retval == 0)
 		return retval;
 
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index 69d948b..62283a3 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -107,7 +107,7 @@
 	dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
 		__LINE__, dev->m_region->lpar_addr);
 
-	result = ps3_alloc_io_irq(dev->interrupt_id, &virq);
+	result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
 
 	if (result) {
 		dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 0dafcda..c2b5ecf 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -507,10 +507,10 @@
 {
 #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
 	return big_endian_mmio(ohci) ?
-		readl_be ((__force u32 *)regs) :
-		readl ((__force u32 *)regs);
+		readl_be (regs) :
+		readl (regs);
 #else
-	return readl ((__force u32 *)regs);
+	return readl (regs);
 #endif
 }
 
@@ -519,10 +519,10 @@
 {
 #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
 	big_endian_mmio(ohci) ?
-		writel_be (val, (__force u32 *)regs) :
-		writel (val, (__force u32 *)regs);
+		writel_be (val, regs) :
+		writel (val, regs);
 #else
-		writel (val, (__force u32 *)regs);
+		writel (val, regs);
 #endif
 }
 
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index ac9f11d..2d0e73b 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -13,7 +13,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 5d6c06b..8d24d3d 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -196,7 +196,7 @@
 		struct uhci_td *td = list_entry(urbp->td_list.next,
 				struct uhci_td, list);
 
-		if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
+		if (element != LINK_TO_TD(td))
 			out += sprintf(out, "%*s Element != First TD\n",
 					space, "");
 		i = nurbs = 0;
@@ -220,16 +220,6 @@
 	return out - buf;
 }
 
-static const char * const qh_names[] = {
-  "skel_unlink_qh", "skel_iso_qh",
-  "skel_int128_qh", "skel_int64_qh",
-  "skel_int32_qh", "skel_int16_qh",
-  "skel_int8_qh", "skel_int4_qh",
-  "skel_int2_qh", "skel_int1_qh",
-  "skel_ls_control_qh", "skel_fs_control_qh",
-  "skel_bulk_qh", "skel_term_qh"
-};
-
 static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
 {
 	char *out = buf;
@@ -352,6 +342,12 @@
 	struct uhci_td *td;
 	struct list_head *tmp, *head;
 	int nframes, nerrs;
+	__le32 link;
+
+	static const char * const qh_names[] = {
+		"unlink", "iso", "int128", "int64", "int32", "int16",
+		"int8", "int4", "int2", "async", "term"
+	};
 
 	out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
 	out += sprintf(out, "HC status\n");
@@ -374,7 +370,7 @@
 	nframes = 10;
 	nerrs = 0;
 	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
-		__le32 link, qh_dma;
+		__le32 qh_dma;
 
 		j = 0;
 		td = uhci->frame_cpu[i];
@@ -393,7 +389,7 @@
 		do {
 			td = list_entry(tmp, struct uhci_td, fl_list);
 			tmp = tmp->next;
-			if (cpu_to_le32(td->dma_handle) != link) {
+			if (link != LINK_TO_TD(td)) {
 				if (nframes > 0)
 					out += sprintf(out, "    link does "
 						"not match list entry!\n");
@@ -430,23 +426,21 @@
 
 	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
 		int cnt = 0;
+		__le32 fsbr_link = 0;
 
 		qh = uhci->skelqh[i];
-		out += sprintf(out, "- %s\n", qh_names[i]); \
+		out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \
 		out += uhci_show_qh(qh, out, len - (out - buf), 4);
 
 		/* Last QH is the Terminating QH, it's different */
-		if (i == UHCI_NUM_SKELQH - 1) {
-			if (qh->link != UHCI_PTR_TERM)
-				out += sprintf(out, "    bandwidth reclamation on!\n");
-
-			if (qh_element(qh) != cpu_to_le32(uhci->term_td->dma_handle))
+		if (i == SKEL_TERM) {
+			if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
 				out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");
-
+			if (link == LINK_TO_QH(uhci->skel_term_qh))
+				goto check_qh_link;
 			continue;
 		}
 
-		j = (i < 9) ? 9 : i+1;		/* Next skeleton */
 		head = &qh->node;
 		tmp = head->next;
 
@@ -456,15 +450,26 @@
 			if (++cnt <= 10)
 				out += uhci_show_qh(qh, out,
 						len - (out - buf), 4);
+			if (!fsbr_link && qh->skel >= SKEL_FSBR)
+				fsbr_link = LINK_TO_QH(qh);
 		}
 		if ((cnt -= 10) > 0)
 			out += sprintf(out, "    Skipped %d QHs\n", cnt);
 
-		if (i > 1 && i < UHCI_NUM_SKELQH - 1) {
-			if (qh->link !=
-			    (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH))
-				out += sprintf(out, "    last QH not linked to next skeleton!\n");
-		}
+		link = UHCI_PTR_TERM;
+		if (i <= SKEL_ISO)
+			;
+		else if (i < SKEL_ASYNC)
+			link = LINK_TO_QH(uhci->skel_async_qh);
+		else if (!uhci->fsbr_is_on)
+			;
+		else if (fsbr_link)
+			link = fsbr_link;
+		else
+			link = LINK_TO_QH(uhci->skel_term_qh);
+check_qh_link:
+		if (qh->link != link)
+			out += sprintf(out, "    last QH not linked to next skeleton!\n");
 	}
 
 	return out - buf;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 49b9d39..44da433 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -13,7 +13,7 @@
  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
+ * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
  *
  * Intel documents this fairly well, and as far as I know there
  * are no royalties or anything like that, but even so there are
@@ -28,7 +28,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
@@ -108,16 +107,16 @@
 	 * interrupt QHs, which will help spread out bandwidth utilization.
 	 *
 	 * ffs (Find First bit Set) does exactly what we need:
-	 * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[8],
-	 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
+	 * 1,3,5,...  => ffs = 0 => use period-2 QH = skelqh[8],
+	 * 2,6,10,... => ffs = 1 => use period-4 QH = skelqh[7], etc.
 	 * ffs >= 7 => not on any high-period queue, so use
-	 *	skel_int1_qh = skelqh[9].
+	 *	period-1 QH = skelqh[9].
 	 * Add in UHCI_NUMFRAMES to insure at least one bit is set.
 	 */
 	skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
 	if (skelnum <= 1)
 		skelnum = 9;
-	return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle);
+	return LINK_TO_QH(uhci->skelqh[skelnum]);
 }
 
 #include "uhci-debug.c"
@@ -541,16 +540,18 @@
  *
  * The hardware doesn't really know any difference
  * in the queues, but the order does matter for the
- * protocols higher up. The order is:
+ * protocols higher up.  The order in which the queues
+ * are encountered by the hardware is:
  *
- *  - any isochronous events handled before any
+ *  - All isochronous events are handled before any
  *    of the queues. We don't do that here, because
  *    we'll create the actual TD entries on demand.
- *  - The first queue is the interrupt queue.
- *  - The second queue is the control queue, split into low- and full-speed
- *  - The third queue is bulk queue.
- *  - The fourth queue is the bandwidth reclamation queue, which loops back
- *    to the full-speed control queue.
+ *  - The first queue is the high-period interrupt queue.
+ *  - The second queue is the period-1 interrupt and async
+ *    (low-speed control, full-speed control, then bulk) queue.
+ *  - The third queue is the terminating bandwidth reclamation queue,
+ *    which contains no members, loops back to itself, and is present
+ *    only when FSBR is on and there are no full-speed control or bulk QHs.
  */
 static int uhci_start(struct usb_hcd *hcd)
 {
@@ -627,34 +628,18 @@
 	}
 
 	/*
-	 * 8 Interrupt queues; link all higher int queues to int1,
-	 * then link int1 to control and control to bulk
+	 * 8 Interrupt queues; link all higher int queues to int1 = async
 	 */
-	uhci->skel_int128_qh->link =
-			uhci->skel_int64_qh->link =
-			uhci->skel_int32_qh->link =
-			uhci->skel_int16_qh->link =
-			uhci->skel_int8_qh->link =
-			uhci->skel_int4_qh->link =
-			uhci->skel_int2_qh->link = UHCI_PTR_QH |
-			cpu_to_le32(uhci->skel_int1_qh->dma_handle);
-
-	uhci->skel_int1_qh->link = UHCI_PTR_QH |
-			cpu_to_le32(uhci->skel_ls_control_qh->dma_handle);
-	uhci->skel_ls_control_qh->link = UHCI_PTR_QH |
-			cpu_to_le32(uhci->skel_fs_control_qh->dma_handle);
-	uhci->skel_fs_control_qh->link = UHCI_PTR_QH |
-			cpu_to_le32(uhci->skel_bulk_qh->dma_handle);
-	uhci->skel_bulk_qh->link = UHCI_PTR_QH |
-			cpu_to_le32(uhci->skel_term_qh->dma_handle);
+	for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
+		uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh);
+	uhci->skel_async_qh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
 
 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
 	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
-		(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
-	uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
-
-	uhci->skel_term_qh->link = UHCI_PTR_TERM;
-	uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle);
+			(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
+	uhci->term_td->link = UHCI_PTR_TERM;
+	uhci->skel_async_qh->element = uhci->skel_term_qh->element =
+			LINK_TO_TD(uhci->term_td);
 
 	/*
 	 * Fill the frame list: make all entries point to the proper
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 74469b5..1b3d234 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -129,11 +129,12 @@
 	__le32 element;			/* Queue element (TD) pointer */
 
 	/* Software fields */
+	dma_addr_t dma_handle;
+
 	struct list_head node;		/* Node in the list of QHs */
 	struct usb_host_endpoint *hep;	/* Endpoint information */
 	struct usb_device *udev;
 	struct list_head queue;		/* Queue of urbps for this QH */
-	struct uhci_qh *skel;		/* Skeleton for this QH */
 	struct uhci_td *dummy_td;	/* Dummy TD to end the queue */
 	struct uhci_td *post_td;	/* Last TD completed */
 
@@ -149,8 +150,7 @@
 
 	int state;			/* QH_STATE_xxx; see above */
 	int type;			/* Queue type (control, bulk, etc) */
-
-	dma_addr_t dma_handle;
+	int skel;			/* Skeleton queue number */
 
 	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
 	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
@@ -171,6 +171,8 @@
 	return element;
 }
 
+#define LINK_TO_QH(qh)		(UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle))
+
 
 /*
  *	Transfer Descriptors
@@ -264,6 +266,8 @@
 	return le32_to_cpu(status);
 }
 
+#define LINK_TO_TD(td)		(cpu_to_le32((td)->dma_handle))
+
 
 /*
  *	Skeleton Queue Headers
@@ -272,12 +276,13 @@
 /*
  * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for
  * automatic queuing. To make it easy to insert entries into the schedule,
- * we have a skeleton of QHs for each predefined Interrupt latency,
- * low-speed control, full-speed control, bulk, and terminating QH
- * (see explanation for the terminating QH below).
+ * we have a skeleton of QHs for each predefined Interrupt latency.
+ * Asynchronous QHs (low-speed control, full-speed control, and bulk)
+ * go onto the period-1 interrupt list, since they all get accessed on
+ * every frame.
  *
- * When we want to add a new QH, we add it to the end of the list for the
- * skeleton QH.  For instance, the schedule list can look like this:
+ * When we want to add a new QH, we add it to the list starting from the
+ * appropriate skeleton QH.  For instance, the schedule can look like this:
  *
  * skel int128 QH
  * dev 1 interrupt QH
@@ -285,50 +290,47 @@
  * skel int64 QH
  * skel int32 QH
  * ...
- * skel int1 QH
- * skel low-speed control QH
- * dev 5 control QH
- * skel full-speed control QH
- * skel bulk QH
+ * skel int1 + async QH
+ * dev 5 low-speed control QH
  * dev 1 bulk QH
  * dev 2 bulk QH
- * skel terminating QH
  *
- * The terminating QH is used for 2 reasons:
- * - To place a terminating TD which is used to workaround a PIIX bug
- *   (see Intel errata for explanation), and
- * - To loop back to the full-speed control queue for full-speed bandwidth
- *   reclamation.
+ * There is a special terminating QH used to keep full-speed bandwidth
+ * reclamation active when no full-speed control or bulk QHs are linked
+ * into the schedule.  It has an inactive TD (to work around a PIIX bug,
+ * see the Intel errata) and it points back to itself.
  *
- * There's a special skeleton QH for Isochronous QHs.  It never appears
- * on the schedule, and Isochronous TDs go on the schedule before the
+ * There's a special skeleton QH for Isochronous QHs which never appears
+ * on the schedule.  Isochronous TDs go on the schedule before the
  * the skeleton QHs.  The hardware accesses them directly rather than
  * through their QH, which is used only for bookkeeping purposes.
  * While the UHCI spec doesn't forbid the use of QHs for Isochronous,
  * it doesn't use them either.  And the spec says that queues never
  * advance on an error completion status, which makes them totally
  * unsuitable for Isochronous transfers.
+ *
+ * There's also a special skeleton QH used for QHs which are in the process
+ * of unlinking and so may still be in use by the hardware.  It too never
+ * appears on the schedule.
  */
 
-#define UHCI_NUM_SKELQH		14
-#define skel_unlink_qh		skelqh[0]
-#define skel_iso_qh		skelqh[1]
-#define skel_int128_qh		skelqh[2]
-#define skel_int64_qh		skelqh[3]
-#define skel_int32_qh		skelqh[4]
-#define skel_int16_qh		skelqh[5]
-#define skel_int8_qh		skelqh[6]
-#define skel_int4_qh		skelqh[7]
-#define skel_int2_qh		skelqh[8]
-#define skel_int1_qh		skelqh[9]
-#define skel_ls_control_qh	skelqh[10]
-#define skel_fs_control_qh	skelqh[11]
-#define skel_bulk_qh		skelqh[12]
-#define skel_term_qh		skelqh[13]
+#define UHCI_NUM_SKELQH		11
+#define SKEL_UNLINK		0
+#define skel_unlink_qh		skelqh[SKEL_UNLINK]
+#define SKEL_ISO		1
+#define skel_iso_qh		skelqh[SKEL_ISO]
+	/* int128, int64, ..., int1 = 2, 3, ..., 9 */
+#define SKEL_INDEX(exponent)	(9 - exponent)
+#define SKEL_ASYNC		9
+#define skel_async_qh		skelqh[SKEL_ASYNC]
+#define SKEL_TERM		10
+#define skel_term_qh		skelqh[SKEL_TERM]
 
-/* Find the skelqh entry corresponding to an interval exponent */
-#define UHCI_SKEL_INDEX(exponent)	(9 - exponent)
-
+/* The following entries refer to sublists of skel_async_qh */
+#define SKEL_LS_CONTROL		20
+#define SKEL_FS_CONTROL		21
+#define SKEL_FSBR		SKEL_FS_CONTROL
+#define SKEL_BULK		22
 
 /*
  *	The UHCI controller and root hub
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 2cbb239..f4ebdb3 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -13,7 +13,7 @@
  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
+ * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
  */
 
 
@@ -45,15 +45,43 @@
  */
 static void uhci_fsbr_on(struct uhci_hcd *uhci)
 {
+	struct uhci_qh *fsbr_qh, *lqh, *tqh;
+
 	uhci->fsbr_is_on = 1;
-	uhci->skel_term_qh->link = cpu_to_le32(
-			uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
+	lqh = list_entry(uhci->skel_async_qh->node.prev,
+			struct uhci_qh, node);
+
+	/* Find the first FSBR QH.  Linear search through the list is
+	 * acceptable because normally FSBR gets turned on as soon as
+	 * one QH needs it. */
+	fsbr_qh = NULL;
+	list_for_each_entry_reverse(tqh, &uhci->skel_async_qh->node, node) {
+		if (tqh->skel < SKEL_FSBR)
+			break;
+		fsbr_qh = tqh;
+	}
+
+	/* No FSBR QH means we must insert the terminating skeleton QH */
+	if (!fsbr_qh) {
+		uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);
+		wmb();
+		lqh->link = uhci->skel_term_qh->link;
+
+	/* Otherwise loop the last QH to the first FSBR QH */
+	} else
+		lqh->link = LINK_TO_QH(fsbr_qh);
 }
 
 static void uhci_fsbr_off(struct uhci_hcd *uhci)
 {
+	struct uhci_qh *lqh;
+
 	uhci->fsbr_is_on = 0;
-	uhci->skel_term_qh->link = UHCI_PTR_TERM;
+	lqh = list_entry(uhci->skel_async_qh->node.prev,
+			struct uhci_qh, node);
+
+	/* End the async list normally and unlink the terminating QH */
+	lqh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
 }
 
 static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
@@ -158,11 +186,11 @@
 
 		td->link = ltd->link;
 		wmb();
-		ltd->link = cpu_to_le32(td->dma_handle);
+		ltd->link = LINK_TO_TD(td);
 	} else {
 		td->link = uhci->frame[framenum];
 		wmb();
-		uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
+		uhci->frame[framenum] = LINK_TO_TD(td);
 		uhci->frame_cpu[framenum] = td;
 	}
 }
@@ -184,7 +212,7 @@
 			struct uhci_td *ntd;
 
 			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
-			uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
+			uhci->frame[td->frame] = LINK_TO_TD(ntd);
 			uhci->frame_cpu[td->frame] = ntd;
 		}
 	} else {
@@ -405,12 +433,81 @@
 }
 
 /*
+ * Link an Isochronous QH into its skeleton's list
+ */
+static inline void link_iso(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	list_add_tail(&qh->node, &uhci->skel_iso_qh->node);
+
+	/* Isochronous QHs aren't linked by the hardware */
+}
+
+/*
+ * Link a high-period interrupt QH into the schedule at the end of its
+ * skeleton's list
+ */
+static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	struct uhci_qh *pqh;
+
+	list_add_tail(&qh->node, &uhci->skelqh[qh->skel]->node);
+
+	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
+	qh->link = pqh->link;
+	wmb();
+	pqh->link = LINK_TO_QH(qh);
+}
+
+/*
+ * Link a period-1 interrupt or async QH into the schedule at the
+ * correct spot in the async skeleton's list, and update the FSBR link
+ */
+static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	struct uhci_qh *pqh, *lqh;
+	__le32 link_to_new_qh;
+	__le32 *extra_link = &link_to_new_qh;
+
+	/* Find the predecessor QH for our new one and insert it in the list.
+	 * The list of QHs is expected to be short, so linear search won't
+	 * take too long. */
+	list_for_each_entry_reverse(pqh, &uhci->skel_async_qh->node, node) {
+		if (pqh->skel <= qh->skel)
+			break;
+	}
+	list_add(&qh->node, &pqh->node);
+	qh->link = pqh->link;
+
+	link_to_new_qh = LINK_TO_QH(qh);
+
+	/* If this is now the first FSBR QH, take special action */
+	if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR &&
+			qh->skel >= SKEL_FSBR) {
+		lqh = list_entry(uhci->skel_async_qh->node.prev,
+				struct uhci_qh, node);
+
+		/* If the new QH is also the last one, we must unlink
+		 * the terminating skeleton QH and make the new QH point
+		 * back to itself. */
+		if (qh == lqh) {
+			qh->link = link_to_new_qh;
+			extra_link = &uhci->skel_term_qh->link;
+
+		/* Otherwise the last QH must point to the new QH */
+		} else
+			extra_link = &lqh->link;
+	}
+
+	/* Link it into the schedule */
+	wmb();
+	*extra_link = pqh->link = link_to_new_qh;
+}
+
+/*
  * Put a QH on the schedule in both hardware and software
  */
 static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
-	struct uhci_qh *pqh;
-
 	WARN_ON(list_empty(&qh->queue));
 
 	/* Set the element pointer if it isn't set already.
@@ -421,7 +518,7 @@
 		struct uhci_td *td = list_entry(urbp->td_list.next,
 				struct uhci_td, list);
 
-		qh->element = cpu_to_le32(td->dma_handle);
+		qh->element = LINK_TO_TD(td);
 	}
 
 	/* Treat the queue as if it has just advanced */
@@ -432,18 +529,64 @@
 		return;
 	qh->state = QH_STATE_ACTIVE;
 
-	/* Move the QH from its old list to the end of the appropriate
+	/* Move the QH from its old list to the correct spot in the appropriate
 	 * skeleton's list */
 	if (qh == uhci->next_qh)
 		uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
 				node);
-	list_move_tail(&qh->node, &qh->skel->node);
+	list_del(&qh->node);
 
-	/* Link it into the schedule */
+	if (qh->skel == SKEL_ISO)
+		link_iso(uhci, qh);
+	else if (qh->skel < SKEL_ASYNC)
+		link_interrupt(uhci, qh);
+	else
+		link_async(uhci, qh);
+}
+
+/*
+ * Unlink a high-period interrupt QH from the schedule
+ */
+static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	struct uhci_qh *pqh;
+
 	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
-	qh->link = pqh->link;
-	wmb();
-	pqh->link = UHCI_PTR_QH | cpu_to_le32(qh->dma_handle);
+	pqh->link = qh->link;
+	mb();
+}
+
+/*
+ * Unlink a period-1 interrupt or async QH from the schedule
+ */
+static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	struct uhci_qh *pqh, *lqh;
+	__le32 link_to_next_qh = qh->link;
+
+	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
+
+	/* If this is the first FSBQ QH, take special action */
+	if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR &&
+			qh->skel >= SKEL_FSBR) {
+		lqh = list_entry(uhci->skel_async_qh->node.prev,
+				struct uhci_qh, node);
+
+		/* If this QH is also the last one, we must link in
+		 * the terminating skeleton QH. */
+		if (qh == lqh) {
+			link_to_next_qh = LINK_TO_QH(uhci->skel_term_qh);
+			uhci->skel_term_qh->link = link_to_next_qh;
+			wmb();
+			qh->link = link_to_next_qh;
+
+		/* Otherwise the last QH must point to the new first FSBR QH */
+		} else
+			lqh->link = link_to_next_qh;
+	}
+
+	pqh->link = link_to_next_qh;
+	mb();
 }
 
 /*
@@ -451,17 +594,18 @@
  */
 static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
-	struct uhci_qh *pqh;
-
 	if (qh->state == QH_STATE_UNLINKING)
 		return;
 	WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev);
 	qh->state = QH_STATE_UNLINKING;
 
 	/* Unlink the QH from the schedule and record when we did it */
-	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
-	pqh->link = qh->link;
-	mb();
+	if (qh->skel == SKEL_ISO)
+		;
+	else if (qh->skel < SKEL_ASYNC)
+		unlink_interrupt(uhci, qh);
+	else
+		unlink_async(uhci, qh);
 
 	uhci_get_current_frame_number(uhci);
 	qh->unlink_frame = uhci->frame_number;
@@ -624,12 +768,10 @@
 {
 	struct urb_priv *urbp;
 
-	urbp = kmem_cache_alloc(uhci_up_cachep, GFP_ATOMIC);
+	urbp = kmem_cache_zalloc(uhci_up_cachep, GFP_ATOMIC);
 	if (!urbp)
 		return NULL;
 
-	memset((void *)urbp, 0, sizeof(*urbp));
-
 	urbp->urb = urb;
 	urb->hcpriv = urbp;
 	
@@ -699,6 +841,7 @@
 	dma_addr_t data = urb->transfer_dma;
 	__le32 *plink;
 	struct urb_priv *urbp = urb->hcpriv;
+	int skel;
 
 	/* The "pipe" thing contains the destination in bits 8--18 */
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
@@ -739,7 +882,7 @@
 		td = uhci_alloc_td(uhci);
 		if (!td)
 			goto nomem;
-		*plink = cpu_to_le32(td->dma_handle);
+		*plink = LINK_TO_TD(td);
 
 		/* Alternate Data0/1 (start with Data1) */
 		destination ^= TD_TOKEN_TOGGLE;
@@ -759,7 +902,7 @@
 	td = uhci_alloc_td(uhci);
 	if (!td)
 		goto nomem;
-	*plink = cpu_to_le32(td->dma_handle);
+	*plink = LINK_TO_TD(td);
 
 	/*
 	 * It's IN if the pipe is an output pipe or we're not expecting
@@ -786,7 +929,7 @@
 	td = uhci_alloc_td(uhci);
 	if (!td)
 		goto nomem;
-	*plink = cpu_to_le32(td->dma_handle);
+	*plink = LINK_TO_TD(td);
 
 	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
 	wmb();
@@ -799,11 +942,13 @@
 	 * isn't in the CONFIGURED state. */
 	if (urb->dev->speed == USB_SPEED_LOW ||
 			urb->dev->state != USB_STATE_CONFIGURED)
-		qh->skel = uhci->skel_ls_control_qh;
+		skel = SKEL_LS_CONTROL;
 	else {
-		qh->skel = uhci->skel_fs_control_qh;
+		skel = SKEL_FS_CONTROL;
 		uhci_add_fsbr(uhci, urb);
 	}
+	if (qh->state != QH_STATE_ACTIVE)
+		qh->skel = skel;
 
 	urb->actual_length = -8;	/* Account for the SETUP packet */
 	return 0;
@@ -862,7 +1007,7 @@
 			td = uhci_alloc_td(uhci);
 			if (!td)
 				goto nomem;
-			*plink = cpu_to_le32(td->dma_handle);
+			*plink = LINK_TO_TD(td);
 		}
 		uhci_add_td_to_urbp(td, urbp);
 		uhci_fill_td(td, status,
@@ -890,7 +1035,7 @@
 		td = uhci_alloc_td(uhci);
 		if (!td)
 			goto nomem;
-		*plink = cpu_to_le32(td->dma_handle);
+		*plink = LINK_TO_TD(td);
 
 		uhci_add_td_to_urbp(td, urbp);
 		uhci_fill_td(td, status,
@@ -916,7 +1061,7 @@
 	td = uhci_alloc_td(uhci);
 	if (!td)
 		goto nomem;
-	*plink = cpu_to_le32(td->dma_handle);
+	*plink = LINK_TO_TD(td);
 
 	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
 	wmb();
@@ -933,7 +1078,7 @@
 	return -ENOMEM;
 }
 
-static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
+static int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
 		struct uhci_qh *qh)
 {
 	int ret;
@@ -942,7 +1087,8 @@
 	if (urb->dev->speed == USB_SPEED_LOW)
 		return -EINVAL;
 
-	qh->skel = uhci->skel_bulk_qh;
+	if (qh->state != QH_STATE_ACTIVE)
+		qh->skel = SKEL_BULK;
 	ret = uhci_submit_common(uhci, urb, qh);
 	if (ret == 0)
 		uhci_add_fsbr(uhci, urb);
@@ -970,7 +1116,7 @@
 		if (exponent < 0)
 			return -EINVAL;
 		qh->period = 1 << exponent;
-		qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)];
+		qh->skel = SKEL_INDEX(exponent);
 
 		/* For now, interrupt phase is fixed by the layout
 		 * of the QH lists. */
@@ -1007,7 +1153,7 @@
 		 * the queue at the status stage transaction, which is
 		 * the last TD. */
 		WARN_ON(list_empty(&urbp->td_list));
-		qh->element = cpu_to_le32(td->dma_handle);
+		qh->element = LINK_TO_TD(td);
 		tmp = td->list.prev;
 		ret = -EINPROGRESS;
 
@@ -1218,7 +1364,7 @@
 		qh->iso_status = 0;
 	}
 
-	qh->skel = uhci->skel_iso_qh;
+	qh->skel = SKEL_ISO;
 	if (!qh->bandwidth_reserved)
 		uhci_reserve_bandwidth(uhci, qh);
 	return 0;
@@ -1568,8 +1714,7 @@
 	if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
 
 		/* Detect the Intel bug and work around it */
-		if (qh->post_td && qh_element(qh) ==
-				cpu_to_le32(qh->post_td->dma_handle)) {
+		if (qh->post_td && qh_element(qh) == LINK_TO_TD(qh->post_td)) {
 			qh->element = qh->post_td->link;
 			qh->advance_jiffies = jiffies;
 			ret = 1;
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 8ccddf7..896cb2b 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -121,7 +121,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/random.h>
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 2e71d3c..69a9f3b 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -58,13 +58,17 @@
 	  devices.
 
 config LOGITECH_FF
-	bool "Logitech WingMan *3D support"
+	bool "Logitech devices support"
 	depends on HID_FF
 	select INPUT_FF_MEMLESS if USB_HID
 	help
 	  Say Y here if you have one of these devices:
 	  - Logitech WingMan Cordless RumblePad
+	  - Logitech WingMan Cordless RumblePad 2
 	  - Logitech WingMan Force 3D
+	  - Logitech Formula Force EX
+	  - Logitech MOMO Force wheel
+
 	  and if you want to enable force feedback for them.
 	  Note: if you say N here, this device will still be supported, but without
 	  force feedback.
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index 9f52429..f857935 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -76,7 +76,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb/input.h>
-#include <linux/sched.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 84983d1..ef09952 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -18,7 +18,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
@@ -516,6 +515,7 @@
 
 #define USB_VENDOR_ID_TURBOX		0x062a
 #define USB_DEVICE_ID_TURBOX_KEYBOARD	0x0201
+#define USB_VENDOR_ID_CIDC		0x1677
 
 /*
  * Initialize all reports
@@ -549,7 +549,6 @@
 }
 
 #define USB_VENDOR_ID_GTCO		0x078c
-#define USB_VENDOR_ID_GTCO_IPANEL_2     0x5543
 #define USB_DEVICE_ID_GTCO_90		0x0090
 #define USB_DEVICE_ID_GTCO_100		0x0100
 #define USB_DEVICE_ID_GTCO_101		0x0101
@@ -595,8 +594,6 @@
 #define USB_DEVICE_ID_GTCO_1004		0x1004
 #define USB_DEVICE_ID_GTCO_1005		0x1005
 #define USB_DEVICE_ID_GTCO_1006		0x1006
-#define USB_DEVICE_ID_GTCO_8		0x0008
-#define USB_DEVICE_ID_GTCO_d            0x000d
 
 #define USB_VENDOR_ID_WACOM		0x056a
 
@@ -855,8 +852,6 @@
 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_8, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_d, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
@@ -954,6 +949,8 @@
 
 	{ USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER },
 
+	{ USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
+
 	{ 0, 0 }
 };
 
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
index 5d14505..e431faa 100644
--- a/drivers/usb/input/hid-ff.c
+++ b/drivers/usb/input/hid-ff.c
@@ -54,9 +54,11 @@
 static struct hid_ff_initializer inits[] = {
 #ifdef CONFIG_LOGITECH_FF
 	{ 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */
-	{ 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */
-	{ 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
 	{ 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
+	{ 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */
+	{ 0x46d, 0xc294, hid_lgff_init }, /* Logitech Formula Force EX */
+	{ 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
+	{ 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
 #endif
 #ifdef CONFIG_PANTHERLORD_FF
 	{ 0x810, 0x0001, hid_plff_init },
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
index 4f4fc3b..e6f3af3 100644
--- a/drivers/usb/input/hid-lgff.c
+++ b/drivers/usb/input/hid-lgff.c
@@ -52,7 +52,9 @@
 	{ 0x046d, 0xc211, ff_rumble },
 	{ 0x046d, 0xc219, ff_rumble },
 	{ 0x046d, 0xc283, ff_joystick },
-	{ 0x0000, 0x0000, ff_joystick }
+	{ 0x046d, 0xc294, ff_joystick },
+	{ 0x046d, 0xc295, ff_joystick },
+	{ 0x046d, 0xca03, ff_joystick },
 };
 
 static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
@@ -104,8 +106,9 @@
 	struct input_dev *dev = hidinput->input;
 	struct hid_report *report;
 	struct hid_field *field;
+	const signed short *ff_bits = ff_joystick;
 	int error;
-	int i, j;
+	int i;
 
 	/* Find the report to use */
 	if (list_empty(report_list)) {
@@ -129,12 +132,14 @@
 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
 		if (dev->id.vendor == devices[i].idVendor &&
 		    dev->id.product == devices[i].idProduct) {
-			for (j = 0; devices[i].ff[j] >= 0; j++)
-				set_bit(devices[i].ff[j], dev->ffbit);
+			ff_bits = devices[i].ff;
 			break;
 		}
 	}
 
+	for (i = 0; ff_bits[i] >= 0; i++)
+		set_bit(ff_bits[i], dev->ffbit);
+
 	error = input_ff_create_memless(dev, NULL, hid_lgff_play);
 	if (error)
 		return error;
diff --git a/drivers/usb/input/hid-pidff.c b/drivers/usb/input/hid-pidff.c
index cbd2d53..f5a90e9 100644
--- a/drivers/usb/input/hid-pidff.c
+++ b/drivers/usb/input/hid-pidff.c
@@ -24,7 +24,6 @@
 
 #define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg)
 
-#include <linux/sched.h>
 #include <linux/input.h>
 #include <linux/usb.h>
 
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 8505824..3749f4a 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb/input.h>
+#include <linux/hid.h>
 
 /*
  * Version Information
@@ -330,7 +331,8 @@
 }
 
 static struct usb_device_id usb_kbd_id_table [] = {
-	{ USB_INTERFACE_INFO(3, 1, 1) },
+	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
+		USB_INTERFACE_PROTOCOL_KEYBOARD) },
 	{ }						/* Terminating entry */
 };
 
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 64a33e4..692fd60 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb/input.h>
+#include <linux/hid.h>
 
 /*
  * Version Information
@@ -213,7 +214,8 @@
 }
 
 static struct usb_device_id usb_mouse_id_table [] = {
-	{ USB_INTERFACE_INFO(3, 1, 2) },
+	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
+		USB_INTERFACE_PROTOCOL_MOUSE) },
 	{ }	/* Terminating entry */
 };
 
diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c
index 4142e36..4f3e9bc 100644
--- a/drivers/usb/input/wacom_wac.c
+++ b/drivers/usb/input/wacom_wac.c
@@ -163,7 +163,7 @@
 	}
 
 	id = STYLUS_DEVICE_ID;
-	if (data[1] & 0x10) { /* in prox */
+	if (data[1] & 0x80) { /* in prox */
 
 		switch ((data[1] >> 5) & 3) {
 
@@ -196,9 +196,6 @@
 					wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
 				break;
 		}
-	}
-
-	if (data[1] & 0x90) {
 		x = wacom_le16_to_cpu(&data[2]);
 		y = wacom_le16_to_cpu(&data[4]);
 		wacom_report_abs(wcombo, ABS_X, x);
@@ -210,19 +207,28 @@
 			wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
 		}
 		wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
-	}
-	else
-		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
-
-	if (data[1] & 0x10)  /* only report prox-in when in area */
 		wacom_report_key(wcombo, wacom->tool[0], 1);
-	if (!(data[1] & 0x90))  /* report prox-out when physically out */
+	} else if (!(data[1] & 0x90)) {
+		wacom_report_abs(wcombo, ABS_X, 0);
+		wacom_report_abs(wcombo, ABS_Y, 0);
+		if (wacom->tool[0] == BTN_TOOL_MOUSE) {
+			wacom_report_key(wcombo, BTN_LEFT, 0);
+			wacom_report_key(wcombo, BTN_RIGHT, 0);
+			wacom_report_abs(wcombo, ABS_DISTANCE, 0);
+		} else {
+			wacom_report_abs(wcombo, ABS_PRESSURE, 0);
+			wacom_report_key(wcombo, BTN_TOUCH, 0);
+			wacom_report_key(wcombo, BTN_STYLUS, 0);
+			wacom_report_key(wcombo, BTN_STYLUS2, 0);
+		}
+		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
 		wacom_report_key(wcombo, wacom->tool[0], 0);
-	wacom_input_sync(wcombo);
+	}
 
 	/* send pad data */
 	if (wacom->features->type == WACOM_G4) {
-		if ( (wacom->serial[1] & 0xc0) != (data[7] & 0xf8) ) {
+		if (data[7] & 0xf8) {
+			wacom_input_sync(wcombo); /* sync last event */
 			wacom->id[1] = 1;
 			wacom->serial[1] = (data[7] & 0xf8);
 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
@@ -230,10 +236,15 @@
 			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
 			wacom_report_rel(wcombo, REL_WHEEL, rw);
 			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+			wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 		} else if (wacom->id[1]) {
+			wacom_input_sync(wcombo); /* sync last event */
 			wacom->id[1] = 0;
+			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
+			wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
 			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+			wacom_report_abs(wcombo, ABS_MISC, 0);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 		}
 	}
@@ -304,28 +315,35 @@
 			default: /* Unknown tool */
 				wacom->tool[idx] = BTN_TOOL_PEN;
 		}
-		/* only large I3 support Lens Cursor */
-		if(!((wacom->tool[idx] == BTN_TOOL_LENS)
-				 && ((wacom->features->type == INTUOS3)
-				 || (wacom->features->type == INTUOS3S)))) {
-			wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
-			wacom_report_key(wcombo, wacom->tool[idx], 1);
-			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-			return 2;
-		}
 		return 1;
 	}
 
 	/* Exit report */
 	if ((data[1] & 0xfe) == 0x80) {
- 		if(!((wacom->tool[idx] == BTN_TOOL_LENS)
-				 && ((wacom->features->type == INTUOS3)
-				 || (wacom->features->type == INTUOS3S)))) {
-			wacom_report_key(wcombo, wacom->tool[idx], 0);
-			wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
-			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-			return 2;
+		wacom_report_abs(wcombo, ABS_X, 0);
+		wacom_report_abs(wcombo, ABS_Y, 0);
+		wacom_report_abs(wcombo, ABS_DISTANCE, 0);
+		if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
+			wacom_report_key(wcombo, BTN_LEFT, 0);
+			wacom_report_key(wcombo, BTN_MIDDLE, 0);
+			wacom_report_key(wcombo, BTN_RIGHT, 0);
+			wacom_report_key(wcombo, BTN_SIDE, 0);
+			wacom_report_key(wcombo, BTN_EXTRA, 0);
+			wacom_report_abs(wcombo, ABS_THROTTLE, 0);
+			wacom_report_abs(wcombo, ABS_RZ, 0);
+ 		} else {
+			wacom_report_abs(wcombo, ABS_PRESSURE, 0);
+			wacom_report_abs(wcombo, ABS_TILT_X, 0);
+			wacom_report_abs(wcombo, ABS_TILT_Y, 0);
+			wacom_report_key(wcombo, BTN_STYLUS, 0);
+			wacom_report_key(wcombo, BTN_STYLUS2, 0);
+			wacom_report_key(wcombo, BTN_TOUCH, 0);
+			wacom_report_abs(wcombo, ABS_WHEEL, 0);
 		}
+		wacom_report_key(wcombo, wacom->tool[idx], 0);
+		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
+		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+		return 2;
 	}
 	return 0;
 }
@@ -394,6 +412,7 @@
 			wacom_report_key(wcombo, wacom->tool[1], 1);
 		else
 			wacom_report_key(wcombo, wacom->tool[1], 0);
+		wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
 		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
                 return 1;
 	}
@@ -403,6 +422,12 @@
 	if (result)
                 return result-1;
 
+	/* Only large I3 and I1 & I2 support Lense Cursor */
+ 	if((wacom->tool[idx] == BTN_TOOL_LENS)
+			&& ((wacom->features->type == INTUOS3)
+		 	|| (wacom->features->type == INTUOS3S)))
+		return 0;
+
 	/* Cintiq doesn't send data when RDY bit isn't set */
 	if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
                  return 0;
@@ -554,11 +579,11 @@
 	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511, 63, GRAPHIRE },
 	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511, 63, GRAPHIRE },
 	{ "Wacom PenPartner2",   8,   3250,  2320,  255, 63, GRAPHIRE },
-	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 63, INTUOS },
-	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 63, INTUOS },
-	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 63, INTUOS },
-	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 63, INTUOS },
-	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 63, INTUOS },
+	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 31, INTUOS },
+	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 31, INTUOS },
+	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 31, INTUOS },
+	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 31, INTUOS },
+	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 31, INTUOS },
 	{ "Wacom PL400",         8,   5408,  4056,  255,  0, PL },
 	{ "Wacom PL500",         8,   6144,  4608,  255,  0, PL },
 	{ "Wacom PL600",         8,   6126,  4604,  255,  0, PL },
@@ -571,11 +596,11 @@
 	{ "Wacom DTF521",        8,   6282,  4762,  511,  0, PL },
 	{ "Wacom DTF720",        8,   6858,  5506,  511,  0, PL },
 	{ "Wacom Cintiq Partner",8,  20480, 15360,  511,  0, PTU },
-	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 63, INTUOS },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 63, INTUOS },
-	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 63, INTUOS },
-	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 63, INTUOS },
-	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 63, INTUOS },
+	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS },
 	{ "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 63, INTUOS3S },
 	{ "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 63, INTUOS3 },
 	{ "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 63, INTUOS3 },
@@ -584,7 +609,7 @@
 	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
 	{ "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S },
 	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 63, INTUOS },
+	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
 	{ }
 };
 
diff --git a/drivers/usb/input/wacom_wac.h b/drivers/usb/input/wacom_wac.h
index a1d9ce0..a230222 100644
--- a/drivers/usb/input/wacom_wac.h
+++ b/drivers/usb/input/wacom_wac.h
@@ -12,6 +12,7 @@
 #define STYLUS_DEVICE_ID	0x02
 #define CURSOR_DEVICE_ID	0x06
 #define ERASER_DEVICE_ID	0x0A
+#define PAD_DEVICE_ID		0x0F
 
 enum {
 	PENPARTNER = 0,
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a74bf86..9c7eb61 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -88,6 +88,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called usblcd.
 
+config USB_BERRY_CHARGE
+	tristate "USB BlackBerry recharge support"
+	depends on USB
+	help
+	  Say Y here if you want to connect a BlackBerry device to your
+	  computer's USB port and have it automatically switch to "recharge"
+	  mode.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called berry_charge.
+
 config USB_LED
 	tristate "USB LED driver support"
 	depends on USB
@@ -233,6 +244,20 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called trancevibrator.
 
+config USB_IOWARRIOR
+	tristate "IO Warrior driver support"
+	depends on USB
+	help
+	  Say Y here if you want to support the IO Warrior devices from Code
+	  Mercenaries.  This includes support for the following devices:
+	  	IO Warrior 40
+		IO Warrior 24
+		IO Warrior 56
+		IO Warrior 24 Power Vampire
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called iowarrior.
+
 config USB_TEST
 	tristate "USB testing driver (DEVELOPMENT)"
 	depends on USB && USB_DEVICEFS && EXPERIMENTAL
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 2cba07d..b68e6b7 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -6,12 +6,14 @@
 obj-$(CONFIG_USB_ADUTUX)	+= adutux.o
 obj-$(CONFIG_USB_APPLEDISPLAY)	+= appledisplay.o
 obj-$(CONFIG_USB_AUERSWALD)	+= auerswald.o
+obj-$(CONFIG_USB_BERRY_CHARGE)	+= berry_charge.o
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
 obj-$(CONFIG_USB_CYTHERM)	+= cytherm.o
 obj-$(CONFIG_USB_EMI26)		+= emi26.o
 obj-$(CONFIG_USB_EMI62)		+= emi62.o
 obj-$(CONFIG_USB_FTDI_ELAN)	+= ftdi-elan.o
 obj-$(CONFIG_USB_IDMOUSE)	+= idmouse.o
+obj-$(CONFIG_USB_IOWARRIOR)	+= iowarrior.o
 obj-$(CONFIG_USB_LCD)		+= usblcd.o
 obj-$(CONFIG_USB_LD)		+= ldusb.o
 obj-$(CONFIG_USB_LED)		+= usbled.o
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index af2934e..75bfab9 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -644,7 +644,7 @@
 }
 
 /* file operations needed when we register this driver */
-static struct file_operations adu_fops = {
+static const struct file_operations adu_fops = {
 	.owner = THIS_MODULE,
 	.read  = adu_read,
 	.write = adu_write,
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index a7932a7..cf70c16 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -141,7 +141,7 @@
 	int retval;
 
 	pdata->msgdata[0] = 0x10;
-	pdata->msgdata[1] = bd->props->brightness;
+	pdata->msgdata[1] = bd->props.brightness;
 
 	retval = usb_control_msg(
 		pdata->udev,
@@ -177,11 +177,9 @@
 		return pdata->msgdata[1];
 }
 
-static struct backlight_properties appledisplay_bl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops appledisplay_bl_data = {
 	.get_brightness	= appledisplay_bl_get_brightness,
 	.update_status	= appledisplay_bl_update_status,
-	.max_brightness	= 0xFF
 };
 
 static void appledisplay_work(struct work_struct *work)
@@ -190,11 +188,9 @@
 		container_of(work, struct appledisplay, work.work);
 	int retval;
 
-	up(&pdata->bd->sem);
 	retval = appledisplay_bl_get_brightness(pdata->bd);
 	if (retval >= 0)
-		pdata->bd->props->brightness = retval;
-	down(&pdata->bd->sem);
+		pdata->bd->props.brightness = retval;
 
 	/* Poll again in about 125ms if there's still a button pressed */
 	if (pdata->button_pressed)
@@ -281,17 +277,17 @@
 	/* Register backlight device */
 	snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
 		atomic_inc_return(&count_displays) - 1);
-	pdata->bd = backlight_device_register(bl_name, NULL, NULL,
+	pdata->bd = backlight_device_register(bl_name, NULL, pdata,
 						&appledisplay_bl_data);
 	if (IS_ERR(pdata->bd)) {
 		err("appledisplay: Backlight registration failed");
 		goto error;
 	}
 
+	pdata->bd->props.max_brightness = 0xff;
+
 	/* Try to get brightness */
-	up(&pdata->bd->sem);
 	brightness = appledisplay_bl_get_brightness(pdata->bd);
-	down(&pdata->bd->sem);
 
 	if (brightness < 0) {
 		retval = brightness;
@@ -300,9 +296,7 @@
 	}
 
 	/* Set brightness in backlight device */
-	up(&pdata->bd->sem);
-	pdata->bd->props->brightness = brightness;
-	down(&pdata->bd->sem);
+	pdata->bd->props.brightness = brightness;
 
 	/* save our data pointer in the interface device */
 	usb_set_intfdata(iface, pdata);
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c
new file mode 100644
index 0000000..60893c6
--- /dev/null
+++ b/drivers/usb/misc/berry_charge.c
@@ -0,0 +1,140 @@
+/*
+ * USB BlackBerry charging module
+ *
+ * Copyright (C) 2007 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 as
+ *	published by the Free Software Foundation, version 2.
+ *
+ * Information on how to switch configs was taken by the bcharge.cc file
+ * created by the barry.sf.net project.
+ *
+ * bcharge.cc has the following copyright:
+ * 	Copyright (C) 2006, Net Direct Inc. (http://www.netdirect.ca/)
+ * and is released under the GPLv2.
+ *
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#define RIM_VENDOR		0x0fca
+#define BLACKBERRY		0x0001
+
+static int debug;
+
+#ifdef dbg
+#undef dbg
+#endif
+#define dbg(dev, format, arg...)				\
+	if (debug)						\
+		dev_printk(KERN_DEBUG , dev , format , ## arg)
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
+	{ },					/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int magic_charge(struct usb_device *udev)
+{
+	char *dummy_buffer = kzalloc(2, GFP_KERNEL);
+	int retval;
+
+	if (!dummy_buffer)
+		return -ENOMEM;
+
+	/* send two magic commands and then set the configuration.  The device
+	 * will then reset itself with the new power usage and should start
+	 * charging. */
+
+	/* Note, with testing, it only seems that the first message is really
+	 * needed (at least for the 8700c), but to be safe, we emulate what
+	 * other operating systems seem to be sending to their device.  We
+	 * really need to get some specs for this device to be sure about what
+	 * is going on here.
+	 */
+	dbg(&udev->dev, "Sending first magic command\n");
+	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 0xa5, 0xc0, 0, 1, dummy_buffer, 2, 100);
+	if (retval != 2) {
+		dev_err(&udev->dev, "First magic command failed: %d.\n",
+			retval);
+		return retval;
+	}
+
+	dbg(&udev->dev, "Sending first magic command\n");
+	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100);
+	if (retval != 0) {
+		dev_err(&udev->dev, "Second magic command failed: %d.\n",
+			retval);
+		return retval;
+	}
+
+	dbg(&udev->dev, "Calling set_configuration\n");
+	retval = usb_driver_set_configuration(udev, 1);
+	if (retval)
+		dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
+
+	return retval;
+}
+
+static int berry_probe(struct usb_interface *intf,
+		       const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+
+	dbg(&udev->dev, "Power is set to %dmA\n",
+	    udev->actconfig->desc.bMaxPower * 2);
+
+	/* check the power usage so we don't try to enable something that is
+	 * already enabled */
+	if ((udev->actconfig->desc.bMaxPower * 2) == 500) {
+		dbg(&udev->dev, "device is already charging, power is "
+		    "set to %dmA\n", udev->actconfig->desc.bMaxPower * 2);
+		return -ENODEV;
+	}
+
+	/* turn the power on */
+	magic_charge(udev);
+
+	/* we don't really want to bind to the device, userspace programs can
+	 * handle the syncing just fine, so get outta here. */
+	return -ENODEV;
+}
+
+static void berry_disconnect(struct usb_interface *intf)
+{
+}
+
+static struct usb_driver berry_driver = {
+	.name =		"berry_charge",
+	.probe =	berry_probe,
+	.disconnect =	berry_disconnect,
+	.id_table =	id_table,
+};
+
+static int __init berry_init(void)
+{
+	return usb_register(&berry_driver);
+}
+
+static void __exit berry_exit(void)
+{
+	usb_deregister(&berry_driver);
+}
+
+module_init(berry_init);
+module_exit(berry_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 41c0161..0c1d66d 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -1209,7 +1209,7 @@
 	return retval;
 }
 
-static struct file_operations ftdi_elan_fops = {
+static const struct file_operations ftdi_elan_fops = {
         .owner = THIS_MODULE,
         .llseek = no_llseek,
         .ioctl = ftdi_elan_ioctl,
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
new file mode 100644
index 0000000..d69665c
--- /dev/null
+++ b/drivers/usb/misc/iowarrior.c
@@ -0,0 +1,925 @@
+/*
+ *  Native support for the I/O-Warrior USB devices
+ *
+ *  Copyright (c) 2003-2005  Code Mercenaries GmbH
+ *  written by Christian Lucht <lucht@codemercs.com>
+ *
+ *  based on
+
+ *  usb-skeleton.c by Greg Kroah-Hartman  <greg@kroah.com>
+ *  brlvger.c by Stephane Dalton  <sdalton@videotron.ca>
+ *           and St�hane Doyon   <s.doyon@videotron.ca>
+ *
+ *  Released under the GPLv2.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/version.h>
+#include <linux/usb/iowarrior.h>
+
+/* Version Information */
+#define DRIVER_VERSION "v0.4.0"
+#define DRIVER_AUTHOR "Christian Lucht <lucht@codemercs.com>"
+#define DRIVER_DESC "USB IO-Warrior driver (Linux 2.6.x)"
+
+#define USB_VENDOR_ID_CODEMERCS		1984
+/* low speed iowarrior */
+#define USB_DEVICE_ID_CODEMERCS_IOW40	0x1500
+#define USB_DEVICE_ID_CODEMERCS_IOW24	0x1501
+#define USB_DEVICE_ID_CODEMERCS_IOWPV1	0x1511
+#define USB_DEVICE_ID_CODEMERCS_IOWPV2	0x1512
+/* full speed iowarrior */
+#define USB_DEVICE_ID_CODEMERCS_IOW56	0x1503
+
+/* Get a minor range for your devices from the usb maintainer */
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define IOWARRIOR_MINOR_BASE	0
+#else
+#define IOWARRIOR_MINOR_BASE	208	// SKELETON_MINOR_BASE 192 + 16, not offical yet
+#endif
+
+/* interrupt input queue size */
+#define MAX_INTERRUPT_BUFFER 16
+/*
+   maximum number of urbs that are submitted for writes at the same time,
+   this applies to the IOWarrior56 only!
+   IOWarrior24 and IOWarrior40 use synchronous usb_control_msg calls.
+*/
+#define MAX_WRITES_IN_FLIGHT 4
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg( format, arg... ) do { if( debug ) printk( KERN_DEBUG __FILE__ ": " format "\n" , ## arg ); } while ( 0 )
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/* Module parameters */
+static int debug = 0;
+module_param(debug, bool, 0644);
+MODULE_PARM_DESC(debug, "debug=1 enables debugging messages");
+
+static struct usb_driver iowarrior_driver;
+
+/*--------------*/
+/*     data     */
+/*--------------*/
+
+/* Structure to hold all of our device specific stuff */
+struct iowarrior {
+	struct mutex mutex;			/* locks this structure */
+	struct usb_device *udev;		/* save off the usb device pointer */
+	struct usb_interface *interface;	/* the interface for this device */
+	unsigned char minor;			/* the starting minor number for this device */
+	struct usb_endpoint_descriptor *int_out_endpoint;	/* endpoint for reading (needed for IOW56 only) */
+	struct usb_endpoint_descriptor *int_in_endpoint;	/* endpoint for reading */
+	struct urb *int_in_urb;		/* the urb for reading data */
+	unsigned char *int_in_buffer;	/* buffer for data to be read */
+	unsigned char serial_number;	/* to detect lost packages */
+	unsigned char *read_queue;	/* size is MAX_INTERRUPT_BUFFER * packet size */
+	wait_queue_head_t read_wait;
+	wait_queue_head_t write_wait;	/* wait-queue for writing to the device */
+	atomic_t write_busy;		/* number of write-urbs submitted */
+	atomic_t read_idx;
+	atomic_t intr_idx;
+	spinlock_t intr_idx_lock;	/* protects intr_idx */
+	atomic_t overflow_flag;		/* signals an index 'rollover' */
+	int present;			/* this is 1 as long as the device is connected */
+	int opened;			/* this is 1 if the device is currently open */
+	char chip_serial[9];		/* the serial number string of the chip connected */
+	int report_size;		/* number of bytes in a report */
+	u16 product_id;
+};
+
+/*--------------*/
+/*    globals   */
+/*--------------*/
+/* prevent races between open() and disconnect() */
+static DECLARE_MUTEX(disconnect_sem);
+
+/*
+ *  USB spec identifies 5 second timeouts.
+ */
+#define GET_TIMEOUT 5
+#define USB_REQ_GET_REPORT  0x01
+//#if 0
+static int usb_get_report(struct usb_device *dev,
+			  struct usb_host_interface *inter, unsigned char type,
+			  unsigned char id, void *buf, int size)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			       USB_REQ_GET_REPORT,
+			       USB_DIR_IN | USB_TYPE_CLASS |
+			       USB_RECIP_INTERFACE, (type << 8) + id,
+			       inter->desc.bInterfaceNumber, buf, size,
+			       GET_TIMEOUT);
+}
+//#endif
+
+#define USB_REQ_SET_REPORT 0x09
+
+static int usb_set_report(struct usb_interface *intf, unsigned char type,
+			  unsigned char id, void *buf, int size)
+{
+	return usb_control_msg(interface_to_usbdev(intf),
+			       usb_sndctrlpipe(interface_to_usbdev(intf), 0),
+			       USB_REQ_SET_REPORT,
+			       USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			       (type << 8) + id,
+			       intf->cur_altsetting->desc.bInterfaceNumber, buf,
+			       size, 1);
+}
+
+/*---------------------*/
+/* driver registration */
+/*---------------------*/
+/* table of devices that work with this driver */
+static struct usb_device_id iowarrior_ids[] = {
+	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40)},
+	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24)},
+	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV1)},
+	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV2)},
+	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56)},
+	{}			/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, iowarrior_ids);
+
+/*
+ * USB callback handler for reading data
+ */
+static void iowarrior_callback(struct urb *urb)
+{
+	struct iowarrior *dev = (struct iowarrior *)urb->context;
+	int intr_idx;
+	int read_idx;
+	int aux_idx;
+	int offset;
+	int status;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	default:
+		goto exit;
+	}
+
+	spin_lock(&dev->intr_idx_lock);
+	intr_idx = atomic_read(&dev->intr_idx);
+	/* aux_idx become previous intr_idx */
+	aux_idx = (intr_idx == 0) ? (MAX_INTERRUPT_BUFFER - 1) : (intr_idx - 1);
+	read_idx = atomic_read(&dev->read_idx);
+
+	/* queue is not empty and it's interface 0 */
+	if ((intr_idx != read_idx)
+	    && (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0)) {
+		/* + 1 for serial number */
+		offset = aux_idx * (dev->report_size + 1);
+		if (!memcmp
+		    (dev->read_queue + offset, urb->transfer_buffer,
+		     dev->report_size)) {
+			/* equal values on interface 0 will be ignored */
+			spin_unlock(&dev->intr_idx_lock);
+			goto exit;
+		}
+	}
+
+	/* aux_idx become next intr_idx */
+	aux_idx = (intr_idx == (MAX_INTERRUPT_BUFFER - 1)) ? 0 : (intr_idx + 1);
+	if (read_idx == aux_idx) {
+		/* queue full, dropping oldest input */
+		read_idx = (++read_idx == MAX_INTERRUPT_BUFFER) ? 0 : read_idx;
+		atomic_set(&dev->read_idx, read_idx);
+		atomic_set(&dev->overflow_flag, 1);
+	}
+
+	/* +1 for serial number */
+	offset = intr_idx * (dev->report_size + 1);
+	memcpy(dev->read_queue + offset, urb->transfer_buffer,
+	       dev->report_size);
+	*(dev->read_queue + offset + (dev->report_size)) = dev->serial_number++;
+
+	atomic_set(&dev->intr_idx, aux_idx);
+	spin_unlock(&dev->intr_idx_lock);
+	/* tell the blocking read about the new data */
+	wake_up_interruptible(&dev->read_wait);
+
+exit:
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status)
+		dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d",
+			__FUNCTION__, status);
+
+}
+
+/*
+ * USB Callback handler for write-ops
+ */
+static void iowarrior_write_callback(struct urb *urb)
+{
+	struct iowarrior *dev;
+	dev = (struct iowarrior *)urb->context;
+	/* sync/async unlink faults aren't errors */
+	if (urb->status &&
+	    !(urb->status == -ENOENT ||
+	      urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __func__, urb->status);
+	}
+	/* free up our allocated buffer */
+	usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+			urb->transfer_buffer, urb->transfer_dma);
+	/* tell a waiting writer the interrupt-out-pipe is available again */
+	atomic_dec(&dev->write_busy);
+	wake_up_interruptible(&dev->write_wait);
+}
+
+/**
+ *	iowarrior_delete
+ */
+static inline void iowarrior_delete(struct iowarrior *dev)
+{
+	dbg("%s - minor %d", __func__, dev->minor);
+	kfree(dev->int_in_buffer);
+	usb_free_urb(dev->int_in_urb);
+	kfree(dev->read_queue);
+	kfree(dev);
+}
+
+/*---------------------*/
+/* fops implementation */
+/*---------------------*/
+
+static int read_index(struct iowarrior *dev)
+{
+	int intr_idx, read_idx;
+
+	read_idx = atomic_read(&dev->read_idx);
+	intr_idx = atomic_read(&dev->intr_idx);
+
+	return (read_idx == intr_idx ? -1 : read_idx);
+}
+
+/**
+ *  iowarrior_read
+ */
+static ssize_t iowarrior_read(struct file *file, char __user *buffer,
+			      size_t count, loff_t *ppos)
+{
+	struct iowarrior *dev;
+	int read_idx;
+	int offset;
+
+	dev = (struct iowarrior *)file->private_data;
+
+	/* verify that the device wasn't unplugged */
+	if (dev == NULL || !dev->present)
+		return -ENODEV;
+
+	dbg("%s - minor %d, count = %zd", __func__, dev->minor, count);
+
+	/* read count must be packet size (+ time stamp) */
+	if ((count != dev->report_size)
+	    && (count != (dev->report_size + 1)))
+		return -EINVAL;
+
+	/* repeat until no buffer overrun in callback handler occur */
+	do {
+		atomic_set(&dev->overflow_flag, 0);
+		if ((read_idx = read_index(dev)) == -1) {
+			/* queue emty */
+			if (file->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+			else {
+				//next line will return when there is either new data, or the device is unplugged
+				int r = wait_event_interruptible(dev->read_wait,
+								 (!dev->present
+								  || (read_idx =
+								      read_index
+								      (dev)) !=
+								  -1));
+				if (r) {
+					//we were interrupted by a signal
+					return -ERESTART;
+				}
+				if (!dev->present) {
+					//The device was unplugged
+					return -ENODEV;
+				}
+				if (read_idx == -1) {
+					// Can this happen ???
+					return 0;
+				}
+			}
+		}
+
+		offset = read_idx * (dev->report_size + 1);
+		if (copy_to_user(buffer, dev->read_queue + offset, count)) {
+			return -EFAULT;
+		}
+	} while (atomic_read(&dev->overflow_flag));
+
+	read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx;
+	atomic_set(&dev->read_idx, read_idx);
+	return count;
+}
+
+/*
+ * iowarrior_write
+ */
+static ssize_t iowarrior_write(struct file *file,
+			       const char __user *user_buffer,
+			       size_t count, loff_t *ppos)
+{
+	struct iowarrior *dev;
+	int retval = 0;
+	char *buf = NULL;	/* for IOW24 and IOW56 we need a buffer */
+	struct urb *int_out_urb = NULL;
+
+	dev = (struct iowarrior *)file->private_data;
+
+	mutex_lock(&dev->mutex);
+	/* verify that the device wasn't unplugged */
+	if (dev == NULL || !dev->present) {
+		retval = -ENODEV;
+		goto exit;
+	}
+	dbg("%s - minor %d, count = %zd", __func__, dev->minor, count);
+	/* if count is 0 we're already done */
+	if (count == 0) {
+		retval = 0;
+		goto exit;
+	}
+	/* We only accept full reports */
+	if (count != dev->report_size) {
+		retval = -EINVAL;
+		goto exit;
+	}
+	switch (dev->product_id) {
+	case USB_DEVICE_ID_CODEMERCS_IOW24:
+	case USB_DEVICE_ID_CODEMERCS_IOWPV1:
+	case USB_DEVICE_ID_CODEMERCS_IOWPV2:
+	case USB_DEVICE_ID_CODEMERCS_IOW40:
+		/* IOW24 and IOW40 use a synchronous call */
+		buf = kmalloc(8, GFP_KERNEL);	/* 8 bytes are enough for both products */
+		if (!buf) {
+			retval = -ENOMEM;
+			goto exit;
+		}
+		if (copy_from_user(buf, user_buffer, count)) {
+			retval = -EFAULT;
+			kfree(buf);
+			goto exit;
+		}
+		retval = usb_set_report(dev->interface, 2, 0, buf, count);
+		kfree(buf);
+		goto exit;
+		break;
+	case USB_DEVICE_ID_CODEMERCS_IOW56:
+		/* The IOW56 uses asynchronous IO and more urbs */
+		if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) {
+			/* Wait until we are below the limit for submitted urbs */
+			if (file->f_flags & O_NONBLOCK) {
+				retval = -EAGAIN;
+				goto exit;
+			} else {
+				retval = wait_event_interruptible(dev->write_wait,
+								  (!dev->present || (atomic_read (&dev-> write_busy) < MAX_WRITES_IN_FLIGHT)));
+				if (retval) {
+					/* we were interrupted by a signal */
+					retval = -ERESTART;
+					goto exit;
+				}
+				if (!dev->present) {
+					/* The device was unplugged */
+					retval = -ENODEV;
+					goto exit;
+				}
+				if (!dev->opened) {
+					/* We were closed while waiting for an URB */
+					retval = -ENODEV;
+					goto exit;
+				}
+			}
+		}
+		atomic_inc(&dev->write_busy);
+		int_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!int_out_urb) {
+			retval = -ENOMEM;
+			dbg("%s Unable to allocate urb ", __func__);
+			goto error;
+		}
+		buf = usb_buffer_alloc(dev->udev, dev->report_size,
+				       GFP_KERNEL, &int_out_urb->transfer_dma);
+		if (!buf) {
+			retval = -ENOMEM;
+			dbg("%s Unable to allocate buffer ", __func__);
+			goto error;
+		}
+		usb_fill_int_urb(int_out_urb, dev->udev,
+				 usb_sndintpipe(dev->udev,
+						dev->int_out_endpoint->bEndpointAddress),
+				 buf, dev->report_size,
+				 iowarrior_write_callback, dev,
+				 dev->int_out_endpoint->bInterval);
+		int_out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		if (copy_from_user(buf, user_buffer, count)) {
+			retval = -EFAULT;
+			goto error;
+		}
+		retval = usb_submit_urb(int_out_urb, GFP_KERNEL);
+		if (retval) {
+			dbg("%s submit error %d for urb nr.%d", __func__,
+			    retval, atomic_read(&dev->write_busy));
+			goto error;
+		}
+		/* submit was ok */
+		retval = count;
+		usb_free_urb(int_out_urb);
+		goto exit;
+		break;
+	default:
+		/* what do we have here ? An unsupported Product-ID ? */
+		dev_err(&dev->interface->dev, "%s - not supported for product=0x%x",
+			__FUNCTION__, dev->product_id);
+		retval = -EFAULT;
+		goto exit;
+		break;
+	}
+error:
+	usb_buffer_free(dev->udev, dev->report_size, buf,
+			int_out_urb->transfer_dma);
+	usb_free_urb(int_out_urb);
+	atomic_dec(&dev->write_busy);
+	wake_up_interruptible(&dev->write_wait);
+exit:
+	mutex_unlock(&dev->mutex);
+	return retval;
+}
+
+/**
+ *	iowarrior_ioctl
+ */
+static int iowarrior_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, unsigned long arg)
+{
+	struct iowarrior *dev = NULL;
+	__u8 *buffer;
+	__u8 __user *user_buffer;
+	int retval;
+	int io_res;		/* checks for bytes read/written and copy_to/from_user results */
+
+	dev = (struct iowarrior *)file->private_data;
+	if (dev == NULL) {
+		return -ENODEV;
+	}
+
+	buffer = kzalloc(dev->report_size, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	/* lock this object */
+	mutex_lock(&dev->mutex);
+
+	/* verify that the device wasn't unplugged */
+	if (!dev->present) {
+		mutex_unlock(&dev->mutex);
+		return -ENODEV;
+	}
+
+	dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __func__, dev->minor, cmd,
+	    arg);
+
+	retval = 0;
+	io_res = 0;
+	switch (cmd) {
+	case IOW_WRITE:
+		if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24 ||
+		    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV1 ||
+		    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV2 ||
+		    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW40) {
+			user_buffer = (__u8 __user *)arg;
+			io_res = copy_from_user(buffer, user_buffer,
+						dev->report_size);
+			if (io_res) {
+				retval = -EFAULT;
+			} else {
+				io_res = usb_set_report(dev->interface, 2, 0,
+							buffer,
+							dev->report_size);
+				if (io_res < 0)
+					retval = io_res;
+			}
+		} else {
+			retval = -EINVAL;
+			dev_err(&dev->interface->dev,
+				"ioctl 'IOW_WRITE' is not supported for product=0x%x.",
+				dev->product_id);
+		}
+		break;
+	case IOW_READ:
+		user_buffer = (__u8 __user *)arg;
+		io_res = usb_get_report(dev->udev,
+					dev->interface->cur_altsetting, 1, 0,
+					buffer, dev->report_size);
+		if (io_res < 0)
+			retval = io_res;
+		else {
+			io_res = copy_to_user(user_buffer, buffer, dev->report_size);
+			if (io_res < 0)
+				retval = -EFAULT;
+		}
+		break;
+	case IOW_GETINFO:
+		{
+			/* Report available information for the device */
+			struct iowarrior_info info;
+			/* needed for power consumption */
+			struct usb_config_descriptor *cfg_descriptor = &dev->udev->actconfig->desc;
+
+			/* directly from the descriptor */
+			info.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+			info.product = dev->product_id;
+			info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice);
+
+			/* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */
+			info.speed = le16_to_cpu(dev->udev->speed);
+			info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber;
+			info.report_size = dev->report_size;
+
+			/* serial number string has been read earlier 8 chars or empty string */
+			memcpy(info.serial, dev->chip_serial,
+			       sizeof(dev->chip_serial));
+			if (cfg_descriptor == NULL) {
+				info.power = -1;	/* no information available */
+			} else {
+				/* the MaxPower is stored in units of 2mA to make it fit into a byte-value */
+				info.power = cfg_descriptor->bMaxPower * 2;
+			}
+			io_res = copy_to_user((struct iowarrior_info __user *)arg, &info,
+					 sizeof(struct iowarrior_info));
+			if (io_res < 0)
+				retval = -EFAULT;
+			break;
+		}
+	default:
+		/* return that we did not understand this ioctl call */
+		retval = -ENOTTY;
+		break;
+	}
+
+	/* unlock the device */
+	mutex_unlock(&dev->mutex);
+	return retval;
+}
+
+/**
+ *	iowarrior_open
+ */
+static int iowarrior_open(struct inode *inode, struct file *file)
+{
+	struct iowarrior *dev = NULL;
+	struct usb_interface *interface;
+	int subminor;
+	int retval = 0;
+
+	dbg("%s", __func__);
+
+	subminor = iminor(inode);
+
+	/* prevent disconnects */
+	down(&disconnect_sem);
+
+	interface = usb_find_interface(&iowarrior_driver, subminor);
+	if (!interface) {
+		err("%s - error, can't find device for minor %d", __FUNCTION__,
+		    subminor);
+		retval = -ENODEV;
+		goto out;
+	}
+
+	dev = usb_get_intfdata(interface);
+	if (!dev) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	/* Only one process can open each device, no sharing. */
+	if (dev->opened) {
+		retval = -EBUSY;
+		goto out;
+	}
+
+	/* setup interrupt handler for receiving values */
+	if ((retval = usb_submit_urb(dev->int_in_urb, GFP_KERNEL)) < 0) {
+		dev_err(&interface->dev, "Error %d while submitting URB\n", retval);
+		retval = -EFAULT;
+		goto out;
+	}
+	/* increment our usage count for the driver */
+	++dev->opened;
+	/* save our object in the file's private structure */
+	file->private_data = dev;
+	retval = 0;
+
+out:
+	up(&disconnect_sem);
+	return retval;
+}
+
+/**
+ *	iowarrior_release
+ */
+static int iowarrior_release(struct inode *inode, struct file *file)
+{
+	struct iowarrior *dev;
+	int retval = 0;
+
+	dev = (struct iowarrior *)file->private_data;
+	if (dev == NULL) {
+		return -ENODEV;
+	}
+
+	dbg("%s - minor %d", __func__, dev->minor);
+
+	/* lock our device */
+	mutex_lock(&dev->mutex);
+
+	if (dev->opened <= 0) {
+		retval = -ENODEV;	/* close called more than once */
+		mutex_unlock(&dev->mutex);
+	} else {
+		dev->opened = 0;	/* we're closeing now */
+		retval = 0;
+		if (dev->present) {
+			/*
+			   The device is still connected so we only shutdown
+			   pending read-/write-ops.
+			 */
+			usb_kill_urb(dev->int_in_urb);
+			wake_up_interruptible(&dev->read_wait);
+			wake_up_interruptible(&dev->write_wait);
+			mutex_unlock(&dev->mutex);
+		} else {
+			/* The device was unplugged, cleanup resources */
+			mutex_unlock(&dev->mutex);
+			iowarrior_delete(dev);
+		}
+	}
+	return retval;
+}
+
+static unsigned iowarrior_poll(struct file *file, poll_table * wait)
+{
+	struct iowarrior *dev = file->private_data;
+	unsigned int mask = 0;
+
+	if (!dev->present)
+		return POLLERR | POLLHUP;
+
+	poll_wait(file, &dev->read_wait, wait);
+	poll_wait(file, &dev->write_wait, wait);
+
+	if (!dev->present)
+		return POLLERR | POLLHUP;
+
+	if (read_index(dev) != -1)
+		mask |= POLLIN | POLLRDNORM;
+
+	if (atomic_read(&dev->write_busy) < MAX_WRITES_IN_FLIGHT)
+		mask |= POLLOUT | POLLWRNORM;
+	return mask;
+}
+
+/*
+ * File operations needed when we register this driver.
+ * This assumes that this driver NEEDS file operations,
+ * of course, which means that the driver is expected
+ * to have a node in the /dev directory. If the USB
+ * device were for a network interface then the driver
+ * would use "struct net_driver" instead, and a serial
+ * device would use "struct tty_driver".
+ */
+static struct file_operations iowarrior_fops = {
+	.owner = THIS_MODULE,
+	.write = iowarrior_write,
+	.read = iowarrior_read,
+	.ioctl = iowarrior_ioctl,
+	.open = iowarrior_open,
+	.release = iowarrior_release,
+	.poll = iowarrior_poll,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
+ */
+static struct usb_class_driver iowarrior_class = {
+	.name = "iowarrior%d",
+	.fops = &iowarrior_fops,
+	.minor_base = IOWARRIOR_MINOR_BASE,
+};
+
+/*---------------------------------*/
+/*  probe and disconnect functions */
+/*---------------------------------*/
+/**
+ *	iowarrior_probe
+ *
+ *	Called by the usb core when a new device is connected that it thinks
+ *	this driver might be interested in.
+ */
+static int iowarrior_probe(struct usb_interface *interface,
+			   const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct iowarrior *dev = NULL;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int i;
+	int retval = -ENOMEM;
+	int idele = 0;
+
+	/* allocate memory for our device state and intialize it */
+	dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&interface->dev, "Out of memory");
+		return retval;
+	}
+
+	mutex_init(&dev->mutex);
+
+	atomic_set(&dev->intr_idx, 0);
+	atomic_set(&dev->read_idx, 0);
+	spin_lock_init(&dev->intr_idx_lock);
+	atomic_set(&dev->overflow_flag, 0);
+	init_waitqueue_head(&dev->read_wait);
+	atomic_set(&dev->write_busy, 0);
+	init_waitqueue_head(&dev->write_wait);
+
+	dev->udev = udev;
+	dev->interface = interface;
+
+	iface_desc = interface->cur_altsetting;
+	dev->product_id = le16_to_cpu(udev->descriptor.idProduct);
+
+	/* set up the endpoint information */
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (usb_endpoint_is_int_in(endpoint))
+			dev->int_in_endpoint = endpoint;
+		if (usb_endpoint_is_int_out(endpoint))
+			/* this one will match for the IOWarrior56 only */
+			dev->int_out_endpoint = endpoint;
+	}
+	/* we have to check the report_size often, so remember it in the endianess suitable for our machine */
+	dev->report_size = le16_to_cpu(dev->int_in_endpoint->wMaxPacketSize);
+	if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&
+	    (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56))
+		/* IOWarrior56 has wMaxPacketSize different from report size */
+		dev->report_size = 7;
+
+	/* create the urb and buffer for reading */
+	dev->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->int_in_urb) {
+		dev_err(&interface->dev, "Couldn't allocate interrupt_in_urb\n");
+		goto error;
+	}
+	dev->int_in_buffer = kmalloc(dev->report_size, GFP_KERNEL);
+	if (!dev->int_in_buffer) {
+		dev_err(&interface->dev, "Couldn't allocate int_in_buffer\n");
+		goto error;
+	}
+	usb_fill_int_urb(dev->int_in_urb, dev->udev,
+			 usb_rcvintpipe(dev->udev,
+					dev->int_in_endpoint->bEndpointAddress),
+			 dev->int_in_buffer, dev->report_size,
+			 iowarrior_callback, dev,
+			 dev->int_in_endpoint->bInterval);
+	/* create an internal buffer for interrupt data from the device */
+	dev->read_queue =
+	    kmalloc(((dev->report_size + 1) * MAX_INTERRUPT_BUFFER),
+		    GFP_KERNEL);
+	if (!dev->read_queue) {
+		dev_err(&interface->dev, "Couldn't allocate read_queue\n");
+		goto error;
+	}
+	/* Get the serial-number of the chip */
+	memset(dev->chip_serial, 0x00, sizeof(dev->chip_serial));
+	usb_string(udev, udev->descriptor.iSerialNumber, dev->chip_serial,
+		   sizeof(dev->chip_serial));
+	if (strlen(dev->chip_serial) != 8)
+		memset(dev->chip_serial, 0x00, sizeof(dev->chip_serial));
+
+	/* Set the idle timeout to 0, if this is interface 0 */
+	if (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) {
+		idele = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+					0x0A,
+					USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
+					0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+		dbg("idele = %d", idele);
+	}
+	/* allow device read and ioctl */
+	dev->present = 1;
+
+	/* we can register the device now, as it is ready */
+	usb_set_intfdata(interface, dev);
+
+	retval = usb_register_dev(interface, &iowarrior_class);
+	if (retval) {
+		/* something prevented us from registering this driver */
+		dev_err(&interface->dev, "Not able to get a minor for this device.\n");
+		usb_set_intfdata(interface, NULL);
+		goto error;
+	}
+
+	dev->minor = interface->minor;
+
+	/* let the user know what node this device is now attached to */
+	dev_info(&interface->dev, "IOWarrior product=0x%x, serial=%s interface=%d "
+		 "now attached to iowarrior%d\n", dev->product_id, dev->chip_serial,
+		 iface_desc->desc.bInterfaceNumber, dev->minor - IOWARRIOR_MINOR_BASE);
+	return retval;
+
+error:
+	iowarrior_delete(dev);
+	return retval;
+}
+
+/**
+ *	iowarrior_disconnect
+ *
+ *	Called by the usb core when the device is removed from the system.
+ */
+static void iowarrior_disconnect(struct usb_interface *interface)
+{
+	struct iowarrior *dev;
+	int minor;
+
+	/* prevent races with open() */
+	down(&disconnect_sem);
+
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	mutex_lock(&dev->mutex);
+
+	minor = dev->minor;
+
+	/* give back our minor */
+	usb_deregister_dev(interface, &iowarrior_class);
+
+	/* prevent device read, write and ioctl */
+	dev->present = 0;
+
+	mutex_unlock(&dev->mutex);
+
+	if (dev->opened) {
+		/* There is a process that holds a filedescriptor to the device ,
+		   so we only shutdown read-/write-ops going on.
+		   Deleting the device is postponed until close() was called.
+		 */
+		usb_kill_urb(dev->int_in_urb);
+		wake_up_interruptible(&dev->read_wait);
+		wake_up_interruptible(&dev->write_wait);
+	} else {
+		/* no process is using the device, cleanup now */
+		iowarrior_delete(dev);
+	}
+	up(&disconnect_sem);
+
+	dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
+		 minor - IOWARRIOR_MINOR_BASE);
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver iowarrior_driver = {
+	.name = "iowarrior",
+	.probe = iowarrior_probe,
+	.disconnect = iowarrior_disconnect,
+	.id_table = iowarrior_ids,
+};
+
+static int __init iowarrior_init(void)
+{
+	return usb_register(&iowarrior_driver);
+}
+
+static void __exit iowarrior_exit(void)
+{
+	usb_deregister(&iowarrior_driver);
+}
+
+module_init(iowarrior_init);
+module_exit(iowarrior_exit);
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 0398908..6f8b134 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index 9148694..1730d86 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -51,7 +51,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/tty.h>
 #include <linux/console.h>
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index c01dfe6..b2bedd9 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1165,7 +1165,7 @@
 	return rc;
 }
 
-void __exit mon_bin_exit(void)
+void mon_bin_exit(void)
 {
 	cdev_del(&mon_bin_cdev);
 	unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index d38a127..494ee3b 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -520,7 +520,7 @@
 	return 0;
 }
 
-void __exit mon_text_exit(void)
+void mon_text_exit(void)
 {
 	debugfs_remove(mon_dir);
 }
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
index 4f949ce..efdfd89 100644
--- a/drivers/usb/mon/usb_mon.h
+++ b/drivers/usb/mon/usb_mon.h
@@ -57,9 +57,9 @@
 // void mon_bin_add(struct mon_bus *);
 
 int __init mon_text_init(void);
-void __exit mon_text_exit(void);
+void mon_text_exit(void);
 int __init mon_bin_init(void);
-void __exit mon_bin_exit(void);
+void mon_bin_exit(void);
 
 /*
  * DMA interface.
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index a2b94ef5..3de564b 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -84,6 +84,7 @@
 config USB_RTL8150
 	tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
+	select MII
 	help
 	  Say Y here if you have RTL8150 based usb-ethernet adapter.
 	  Send me <petkan@users.sourceforge.net> any comments you may have.
@@ -98,7 +99,7 @@
 
 config USB_USBNET
 	tristate "Multi-purpose USB Networking Framework"
-	select MII if USBNET_MII != n
+	select MII if USB_USBNET_MII != n
 	---help---
 	  This driver supports several kinds of network links over USB,
 	  with "minidrivers" built around a common network driver core
@@ -185,6 +186,15 @@
 	  IEEE 802 "local assignment" bit is set in the address, a "usbX"
 	  name is used instead.
 
+config USB_NET_DM9601
+	tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
+	depends on USB_USBNET
+	select CRC32
+	select USB_USBNET_MII
+	help
+	  This option adds support for Davicom DM9601 based USB 1.1
+	  10/100 Ethernet adapters.
+
 config USB_NET_GL620A
 	tristate "GeneSys GL620USB-A based cables"
 	depends on USB_USBNET
@@ -239,6 +249,7 @@
 config USB_NET_CDC_SUBSET
 	tristate "Simple USB Network Links (CDC Ethernet subset)"
 	depends on USB_USBNET
+	default y
 	help
 	  This driver module supports USB network devices that can work
 	  without any device-specific information.  Select it if you have
@@ -298,6 +309,13 @@
 	  Choose this option to support the usb networking links used
 	  by some sample firmware from Epson.
 
+config USB_KC2190
+	boolean "KT Technology KC2190 based cables (InstaNet)"
+	depends on USB_NET_CDC_SUBSET && EXPERIMENTAL
+	help
+	  Choose this option if you're using a host-to-host cable
+	  with one of these chips.
+
 config USB_NET_ZAURUS
 	tristate "Sharp Zaurus (stock ROMs) and compatible"
 	depends on USB_USBNET
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index 7b51964..595a539 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -8,6 +8,7 @@
 obj-$(CONFIG_USB_RTL8150)	+= rtl8150.o
 obj-$(CONFIG_USB_NET_AX8817X)	+= asix.o
 obj-$(CONFIG_USB_NET_CDCETHER)	+= cdc_ether.o
+obj-$(CONFIG_USB_NET_DM9601)	+= dm9601.o
 obj-$(CONFIG_USB_NET_GL620A)	+= gl620a.o
 obj-$(CONFIG_USB_NET_NET1080)	+= net1080.o
 obj-$(CONFIG_USB_NET_PLUSB)	+= plusb.o
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 4206df2..5808ea0 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -25,7 +25,6 @@
 
 #include <linux/module.h>
 #include <linux/kmod.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -352,9 +351,11 @@
 
 	skb_push(skb, 4);
 	packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+	cpu_to_le32s(&packet_len);
 	memcpy(skb->data, &packet_len, sizeof(packet_len));
 
 	if ((skb->len % 512) == 0) {
+		cpu_to_le32s(&padbytes);
 		memcpy( skb->tail, &padbytes, sizeof(padbytes));
 		skb_put(skb, sizeof(padbytes));
 	}
@@ -1394,9 +1395,9 @@
 	USB_DEVICE (0x07b8, 0x420a),
 	.driver_info =  (unsigned long) &hawking_uf200_info,
 }, {
-        // Billionton Systems, USB2AR
-        USB_DEVICE (0x08dd, 0x90ff),
-        .driver_info =  (unsigned long) &ax8817x_info,
+	// Billionton Systems, USB2AR
+	USB_DEVICE (0x08dd, 0x90ff),
+	.driver_info =  (unsigned long) &ax8817x_info,
 }, {
 	// ATEN UC210T
 	USB_DEVICE (0x0557, 0x2009),
@@ -1422,9 +1423,13 @@
 	USB_DEVICE (0x1631, 0x6200),
 	.driver_info = (unsigned long) &ax8817x_info,
 }, {
+	// JVC MP-PRX1 Port Replicator
+	USB_DEVICE (0x04f1, 0x3008),
+	.driver_info = (unsigned long) &ax8817x_info,
+}, {
 	// ASIX AX88772 10/100
-        USB_DEVICE (0x0b95, 0x7720),
-        .driver_info = (unsigned long) &ax88772_info,
+	USB_DEVICE (0x0b95, 0x7720),
+	.driver_info = (unsigned long) &ax88772_info,
 }, {
 	// ASIX AX88178 10/100/1000
 	USB_DEVICE (0x0b95, 0x1780),
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
index e5cdafa..5a21f06 100644
--- a/drivers/usb/net/cdc_ether.c
+++ b/drivers/usb/net/cdc_ether.c
@@ -22,7 +22,6 @@
 // #define	VERBOSE			// more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c
index e2fae85..bc62b01 100644
--- a/drivers/usb/net/cdc_subset.c
+++ b/drivers/usb/net/cdc_subset.c
@@ -19,7 +19,6 @@
 
 #include <linux/module.h>
 #include <linux/kmod.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -80,13 +79,19 @@
  *
  * ALi M5632 driver ... does high speed
  *
+ * NOTE that the MS-Windows drivers for this chip use some funky and
+ * (naturally) undocumented 7-byte prefix to each packet, so this is a
+ * case where we don't currently interoperate.  Also, once you unplug
+ * one end of the cable, you need to replug the other end too ... since
+ * chip docs are unavailable, there's no way to reset the relevant state
+ * short of a power cycle.
+ *
  *-------------------------------------------------------------------------*/
 
 static const struct driver_info	ali_m5632_info = {
 	.description =	"ALi M5632",
 };
 
-
 #endif
 
 
@@ -160,6 +165,11 @@
 #endif	/* CONFIG_USB_EPSON2888 */
 
 
+/*-------------------------------------------------------------------------
+ *
+ * info from Jonathan McDowell <noodles@earth.li>
+ *
+ *-------------------------------------------------------------------------*/
 #ifdef CONFIG_USB_KC2190
 #define HAVE_HARDWARE
 static const struct driver_info kc2190_info = {
@@ -224,6 +234,10 @@
 	USB_DEVICE (0x0402, 0x5632),	// ALi defaults
 	.driver_info =	(unsigned long) &ali_m5632_info,
 },
+{
+	USB_DEVICE (0x182d,0x207c),	// SiteCom CN-124
+	.driver_info =	(unsigned long) &ali_m5632_info,
+},
 #endif
 
 #ifdef	CONFIG_USB_AN2720
@@ -315,13 +329,13 @@
 
 static int __init cdc_subset_init(void)
 {
- 	return usb_register(&cdc_subset_driver);
+	return usb_register(&cdc_subset_driver);
 }
 module_init(cdc_subset_init);
 
 static void __exit cdc_subset_exit(void)
 {
- 	usb_deregister(&cdc_subset_driver);
+	usb_deregister(&cdc_subset_driver);
 }
 module_exit(cdc_subset_exit);
 
diff --git a/drivers/usb/net/dm9601.c b/drivers/usb/net/dm9601.c
new file mode 100644
index 0000000..4a932e1
--- /dev/null
+++ b/drivers/usb/net/dm9601.c
@@ -0,0 +1,606 @@
+/*
+ * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices
+ *
+ * Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * 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.
+ */
+
+//#define DEBUG
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+
+#include "usbnet.h"
+
+/* datasheet:
+ http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf
+*/
+
+/* control requests */
+#define DM_READ_REGS	0x00
+#define DM_WRITE_REGS	0x01
+#define DM_READ_MEMS	0x02
+#define DM_WRITE_REG	0x03
+#define DM_WRITE_MEMS	0x05
+#define DM_WRITE_MEM	0x07
+
+/* registers */
+#define DM_NET_CTRL	0x00
+#define DM_RX_CTRL	0x05
+#define DM_SHARED_CTRL	0x0b
+#define DM_SHARED_ADDR	0x0c
+#define DM_SHARED_DATA	0x0d	/* low + high */
+#define DM_PHY_ADDR	0x10	/* 6 bytes */
+#define DM_MCAST_ADDR	0x16	/* 8 bytes */
+#define DM_GPR_CTRL	0x1e
+#define DM_GPR_DATA	0x1f
+
+#define DM_MAX_MCAST	64
+#define DM_MCAST_SIZE	8
+#define DM_EEPROM_LEN	256
+#define DM_TX_OVERHEAD	2	/* 2 byte header */
+#define DM_RX_OVERHEAD	7	/* 3 byte header + 4 byte crc tail */
+#define DM_TIMEOUT	1000
+
+
+static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+	devdbg(dev, "dm_read() reg=0x%02x length=%d", reg, length);
+	return usb_control_msg(dev->udev,
+			       usb_rcvctrlpipe(dev->udev, 0),
+			       DM_READ_REGS,
+			       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			       0, reg, data, length, USB_CTRL_SET_TIMEOUT);
+}
+
+static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
+{
+	return dm_read(dev, reg, 1, value);
+}
+
+static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+	devdbg(dev, "dm_write() reg=0x%02x, length=%d", reg, length);
+	return usb_control_msg(dev->udev,
+			       usb_sndctrlpipe(dev->udev, 0),
+			       DM_WRITE_REGS,
+			       USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
+			       0, reg, data, length, USB_CTRL_SET_TIMEOUT);
+}
+
+static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
+{
+	devdbg(dev, "dm_write_reg() reg=0x%02x, value=0x%02x", reg, value);
+	return usb_control_msg(dev->udev,
+			       usb_sndctrlpipe(dev->udev, 0),
+			       DM_WRITE_REG,
+			       USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
+			       value, reg, 0, 0, USB_CTRL_SET_TIMEOUT);
+}
+
+static void dm_write_async_callback(struct urb *urb)
+{
+	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+
+	if (urb->status < 0)
+		printk(KERN_DEBUG "dm_write_async_callback() failed with %d",
+		       urb->status);
+
+	kfree(req);
+	usb_free_urb(urb);
+}
+
+static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
+{
+	struct usb_ctrlrequest *req;
+	struct urb *urb;
+	int status;
+
+	devdbg(dev, "dm_write_async() reg=0x%02x length=%d", reg, length);
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		deverr(dev, "Error allocating URB in dm_write_async!");
+		return;
+	}
+
+	req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+	if (!req) {
+		deverr(dev, "Failed to allocate memory for control request");
+		usb_free_urb(urb);
+		return;
+	}
+
+	req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+	req->bRequest = DM_WRITE_REGS;
+	req->wValue = 0;
+	req->wIndex = cpu_to_le16(reg);
+	req->wLength = cpu_to_le16(length);
+
+	usb_fill_control_urb(urb, dev->udev,
+			     usb_sndctrlpipe(dev->udev, 0),
+			     (void *)req, data, length,
+			     dm_write_async_callback, req);
+
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status < 0) {
+		deverr(dev, "Error submitting the control message: status=%d",
+		       status);
+		kfree(req);
+		usb_free_urb(urb);
+	}
+}
+
+static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
+{
+	struct usb_ctrlrequest *req;
+	struct urb *urb;
+	int status;
+
+	devdbg(dev, "dm_write_reg_async() reg=0x%02x value=0x%02x",
+	       reg, value);
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		deverr(dev, "Error allocating URB in dm_write_async!");
+		return;
+	}
+
+	req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+	if (!req) {
+		deverr(dev, "Failed to allocate memory for control request");
+		usb_free_urb(urb);
+		return;
+	}
+
+	req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+	req->bRequest = DM_WRITE_REG;
+	req->wValue = cpu_to_le16(value);
+	req->wIndex = cpu_to_le16(reg);
+	req->wLength = 0;
+
+	usb_fill_control_urb(urb, dev->udev,
+			     usb_sndctrlpipe(dev->udev, 0),
+			     (void *)req, 0, 0, dm_write_async_callback, req);
+
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status < 0) {
+		deverr(dev, "Error submitting the control message: status=%d",
+		       status);
+		kfree(req);
+		usb_free_urb(urb);
+	}
+}
+
+static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, u16 *value)
+{
+	int ret, i;
+
+	mutex_lock(&dev->phy_mutex);
+
+	dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
+	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0xc : 0x4);
+
+	for (i = 0; i < DM_TIMEOUT; i++) {
+		u8 tmp;
+
+		udelay(1);
+		ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
+		if (ret < 0)
+			goto out;
+
+		/* ready */
+		if ((tmp & 1) == 0)
+			break;
+	}
+
+	if (i == DM_TIMEOUT) {
+		deverr(dev, "%s read timed out!", phy ? "phy" : "eeprom");
+		ret = -EIO;
+		goto out;
+	}
+
+	dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
+	ret = dm_read(dev, DM_SHARED_DATA, 2, value);
+
+	devdbg(dev, "read shared %d 0x%02x returned 0x%04x, %d",
+	       phy, reg, *value, ret);
+
+ out:
+	mutex_unlock(&dev->phy_mutex);
+	return ret;
+}
+
+static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, u16 value)
+{
+	int ret, i;
+
+	mutex_lock(&dev->phy_mutex);
+
+	ret = dm_write(dev, DM_SHARED_DATA, 2, &value);
+	if (ret < 0)
+		goto out;
+
+	dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
+	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1c : 0x14);
+
+	for (i = 0; i < DM_TIMEOUT; i++) {
+		u8 tmp;
+
+		udelay(1);
+		ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
+		if (ret < 0)
+			goto out;
+
+		/* ready */
+		if ((tmp & 1) == 0)
+			break;
+	}
+
+	if (i == DM_TIMEOUT) {
+		deverr(dev, "%s write timed out!", phy ? "phy" : "eeprom");
+		ret = -EIO;
+		goto out;
+	}
+
+	dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
+
+out:
+	mutex_unlock(&dev->phy_mutex);
+	return ret;
+}
+
+static int dm_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)
+{
+	return dm_read_shared_word(dev, 0, offset, value);
+}
+
+
+
+static int dm9601_get_eeprom_len(struct net_device *dev)
+{
+	return DM_EEPROM_LEN;
+}
+
+static int dm9601_get_eeprom(struct net_device *net,
+			     struct ethtool_eeprom *eeprom, u8 * data)
+{
+	struct usbnet *dev = netdev_priv(net);
+	u16 *ebuf = (u16 *) data;
+	int i;
+
+	/* access is 16bit */
+	if ((eeprom->offset % 2) || (eeprom->len % 2))
+		return -EINVAL;
+
+	for (i = 0; i < eeprom->len / 2; i++) {
+		if (dm_read_eeprom_word(dev, eeprom->offset / 2 + i,
+					&ebuf[i]) < 0)
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc)
+{
+	struct usbnet *dev = netdev_priv(netdev);
+
+	u16 res;
+
+	if (phy_id) {
+		devdbg(dev, "Only internal phy supported");
+		return 0;
+	}
+
+	dm_read_shared_word(dev, 1, loc, &res);
+
+	devdbg(dev,
+	       "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x",
+	       phy_id, loc, le16_to_cpu(res));
+
+	return le16_to_cpu(res);
+}
+
+static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc,
+			      int val)
+{
+	struct usbnet *dev = netdev_priv(netdev);
+	u16 res = cpu_to_le16(val);
+
+	if (phy_id) {
+		devdbg(dev, "Only internal phy supported");
+		return;
+	}
+
+	devdbg(dev,"dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x",
+	       phy_id, loc, val);
+
+	dm_write_shared_word(dev, 1, loc, res);
+}
+
+static void dm9601_get_drvinfo(struct net_device *net,
+			       struct ethtool_drvinfo *info)
+{
+	/* Inherit standard device info */
+	usbnet_get_drvinfo(net, info);
+	info->eedump_len = DM_EEPROM_LEN;
+}
+
+static u32 dm9601_get_link(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+
+	return mii_link_ok(&dev->mii);
+}
+
+static int dm9601_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 struct ethtool_ops dm9601_ethtool_ops = {
+	.get_drvinfo	= dm9601_get_drvinfo,
+	.get_link	= dm9601_get_link,
+	.get_msglevel	= usbnet_get_msglevel,
+	.set_msglevel	= usbnet_set_msglevel,
+	.get_eeprom_len	= dm9601_get_eeprom_len,
+	.get_eeprom	= dm9601_get_eeprom,
+	.get_settings	= usbnet_get_settings,
+	.set_settings	= usbnet_set_settings,
+	.nway_reset	= usbnet_nway_reset,
+};
+
+static void dm9601_set_multicast(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+	/* We use the 20 byte dev->data for our 8 byte filter buffer
+	 * to avoid allocating memory that is tricky to free later */
+	u8 *hashes = (u8 *) & dev->data;
+	u8 rx_ctl = 0x01;
+
+	memset(hashes, 0x00, DM_MCAST_SIZE);
+	hashes[DM_MCAST_SIZE - 1] |= 0x80;	/* broadcast address */
+
+	if (net->flags & IFF_PROMISC) {
+		rx_ctl |= 0x02;
+	} else if (net->flags & IFF_ALLMULTI || net->mc_count > DM_MAX_MCAST) {
+		rx_ctl |= 0x04;
+	} else if (net->mc_count) {
+		struct dev_mc_list *mc_list = net->mc_list;
+		int i;
+
+		for (i = 0; i < net->mc_count; i++) {
+			u32 crc = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26;
+			hashes[crc >> 3] |= 1 << (crc & 0x7);
+		}
+	}
+
+	dm_write_async(dev, DM_MCAST_ADDR, DM_MCAST_SIZE, hashes);
+	dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl);
+}
+
+static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int ret;
+
+	ret = usbnet_get_endpoints(dev, intf);
+	if (ret)
+		goto out;
+
+	dev->net->do_ioctl = dm9601_ioctl;
+	dev->net->set_multicast_list = dm9601_set_multicast;
+	dev->net->ethtool_ops = &dm9601_ethtool_ops;
+	dev->net->hard_header_len += DM_TX_OVERHEAD;
+	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+	dev->rx_urb_size = dev->net->mtu + DM_RX_OVERHEAD;
+
+	dev->mii.dev = dev->net;
+	dev->mii.mdio_read = dm9601_mdio_read;
+	dev->mii.mdio_write = dm9601_mdio_write;
+	dev->mii.phy_id_mask = 0x1f;
+	dev->mii.reg_num_mask = 0x1f;
+
+	/* reset */
+	ret = dm_write_reg(dev, DM_NET_CTRL, 1);
+	udelay(20);
+
+	/* read MAC */
+	ret = dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
+	if (ret < 0) {
+		printk(KERN_ERR "Error reading MAC address\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+
+	/* power up phy */
+	dm_write_reg(dev, DM_GPR_CTRL, 1);
+	dm_write_reg(dev, DM_GPR_DATA, 0);
+
+	/* receive broadcast packets */
+	dm9601_set_multicast(dev->net);
+
+	dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+	dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+			  ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+	mii_nway_restart(&dev->mii);
+
+out:
+	return ret;
+}
+
+static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	u8 status;
+	int len;
+
+	/* format:
+	   b0: rx status
+	   b1: packet length (incl crc) low
+	   b2: packet length (incl crc) high
+	   b3..n-4: packet data
+	   bn-3..bn: ethernet crc
+	 */
+
+	if (unlikely(skb->len < DM_RX_OVERHEAD)) {
+		dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
+		return 0;
+	}
+
+	status = skb->data[0];
+	len = (skb->data[1] | (skb->data[2] << 8)) - 4;
+
+	if (unlikely(status & 0xbf)) {
+		if (status & 0x01) dev->stats.rx_fifo_errors++;
+		if (status & 0x02) dev->stats.rx_crc_errors++;
+		if (status & 0x04) dev->stats.rx_frame_errors++;
+		if (status & 0x20) dev->stats.rx_missed_errors++;
+		if (status & 0x90) dev->stats.rx_length_errors++;
+		return 0;
+	}
+
+	skb_pull(skb, 3);
+	skb_trim(skb, len);
+
+	return 1;
+}
+
+static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+				       gfp_t flags)
+{
+	int len;
+
+	/* format:
+	   b0: packet length low
+	   b1: packet length high
+	   b3..n: packet data
+	*/
+
+	if (skb_headroom(skb) < DM_TX_OVERHEAD) {
+		struct sk_buff *skb2;
+
+		skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags);
+		dev_kfree_skb_any(skb);
+		skb = skb2;
+		if (!skb)
+			return NULL;
+	}
+
+	__skb_push(skb, DM_TX_OVERHEAD);
+
+	len = skb->len;
+	/* usbnet adds padding if length is a multiple of packet size
+	   if so, adjust length value in header */
+	if ((len % dev->maxpacket) == 0)
+		len++;
+
+	skb->data[0] = len;
+	skb->data[1] = len >> 8;
+
+	return skb;
+}
+
+static void dm9601_status(struct usbnet *dev, struct urb *urb)
+{
+	int link;
+	u8 *buf;
+
+	/* format:
+	   b0: net status
+	   b1: tx status 1
+	   b2: tx status 2
+	   b3: rx status
+	   b4: rx overflow
+	   b5: rx count
+	   b6: tx count
+	   b7: gpr
+	*/
+
+	if (urb->actual_length < 8)
+		return;
+
+	buf = urb->transfer_buffer;
+
+	link = !!(buf[0] & 0x40);
+	if (netif_carrier_ok(dev->net) != link) {
+		if (link) {
+			netif_carrier_on(dev->net);
+			usbnet_defer_kevent (dev, EVENT_LINK_RESET);
+		}
+		else
+			netif_carrier_off(dev->net);
+		devdbg(dev, "Link Status is: %d", link);
+	}
+}
+
+static int dm9601_link_reset(struct usbnet *dev)
+{
+	struct ethtool_cmd ecmd;
+
+	mii_check_media(&dev->mii, 1, 1);
+	mii_ethtool_gset(&dev->mii, &ecmd);
+
+	devdbg(dev, "link_reset() speed: %d duplex: %d",
+	       ecmd.speed, ecmd.duplex);
+
+	return 0;
+}
+
+static const struct driver_info dm9601_info = {
+	.description	= "Davicom DM9601 USB Ethernet",
+	.flags		= FLAG_ETHER,
+	.bind		= dm9601_bind,
+	.rx_fixup	= dm9601_rx_fixup,
+	.tx_fixup	= dm9601_tx_fixup,
+	.status		= dm9601_status,
+	.link_reset	= dm9601_link_reset,
+	.reset		= dm9601_link_reset,
+};
+
+static const struct usb_device_id products[] = {
+	{
+	 USB_DEVICE(0x0a46, 0x9601),	/* Davicom USB-100 */
+	 .driver_info = (unsigned long)&dm9601_info,
+	 },
+	{},			// END
+};
+
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver dm9601_driver = {
+	.name = "dm9601",
+	.id_table = products,
+	.probe = usbnet_probe,
+	.disconnect = usbnet_disconnect,
+	.suspend = usbnet_suspend,
+	.resume = usbnet_resume,
+};
+
+static int __init dm9601_init(void)
+{
+	return usb_register(&dm9601_driver);
+}
+
+static void __exit dm9601_exit(void)
+{
+	usb_deregister(&dm9601_driver);
+}
+
+module_init(dm9601_init);
+module_exit(dm9601_exit);
+
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index a6f0f4d..d257a8e 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -22,7 +22,6 @@
 // #define	VERBOSE			// more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -70,12 +69,12 @@
 	(((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
 
 struct gl_packet {
-	u32		packet_length;
+	__le32		packet_length;
 	char		packet_data [1];
 };
 
 struct gl_header {
-	u32			packet_count;
+	__le32			packet_count;
 	struct gl_packet	packets;
 };
 
@@ -85,15 +84,14 @@
 	struct gl_packet	*packet;
 	struct sk_buff		*gl_skb;
 	u32			size;
+	u32			count;
 
 	header = (struct gl_header *) skb->data;
 
 	// get the packet count of the received skb
-	le32_to_cpus(&header->packet_count);
-	if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS)
-			|| (header->packet_count < 0)) {
-		dbg("genelink: invalid received packet count %d",
-			header->packet_count);
+	count = le32_to_cpu(header->packet_count);
+	if (count > GL_MAX_TRANSMIT_PACKETS) {
+		dbg("genelink: invalid received packet count %u", count);
 		return 0;
 	}
 
@@ -103,7 +101,7 @@
 	// decrement the length for the packet count size 4 bytes
 	skb_pull(skb, 4);
 
-	while (header->packet_count > 1) {
+	while (count > 1) {
 		// get the packet length
 		size = le32_to_cpu(packet->packet_length);
 
@@ -124,9 +122,8 @@
 		}
 
 		// advance to the next packet
-		packet = (struct gl_packet *)
-			&packet->packet_data [size];
-		header->packet_count--;
+		packet = (struct gl_packet *)&packet->packet_data[size];
+		count--;
 
 		// shift the data pointer to the next gl_packet
 		skb_pull(skb, size + 4);
@@ -149,8 +146,8 @@
 	int	length = skb->len;
 	int	headroom = skb_headroom(skb);
 	int	tailroom = skb_tailroom(skb);
-	u32	*packet_count;
-	u32	*packet_len;
+	__le32	*packet_count;
+	__le32	*packet_len;
 
 	// FIXME:  magic numbers, bleech
 	padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
@@ -172,7 +169,7 @@
 	}
 
 	// attach the packet count to the header
-	packet_count = (u32 *) skb_push(skb, (4 + 4*1));
+	packet_count = (__le32 *) skb_push(skb, (4 + 4*1));
 	packet_len = packet_count + 1;
 
 	*packet_count = cpu_to_le32(1);
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 36a9891..de95268 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -46,7 +46,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index 4936359..ccebfde 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -21,7 +21,6 @@
 // #define	VERBOSE			// more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/usb/net/plusb.c b/drivers/usb/net/plusb.c
index 5d17cdf..4530093 100644
--- a/drivers/usb/net/plusb.c
+++ b/drivers/usb/net/plusb.c
@@ -21,7 +21,6 @@
 // #define	VERBOSE			// more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index be888d2..39a21c7 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -21,7 +21,6 @@
 // #define	VERBOSE			// more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 670262a..ea153dc 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -6,7 +6,6 @@
  * version 2 as published by the Free Software Foundation.
  */
 
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/signal.h>
 #include <linux/slab.h>
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 6e39e99..de69b18 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -34,7 +34,6 @@
 // #define	VERBOSE			// more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -148,7 +147,7 @@
 		if (tmp < 0)
 			return tmp;
 	}
-	
+
 	dev->in = usb_rcvbulkpipe (dev->udev,
 			in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
 	dev->out = usb_sndbulkpipe (dev->udev,
@@ -328,7 +327,7 @@
 	if (netif_running (dev->net)
 			&& netif_device_present (dev->net)
 			&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
-		switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){ 
+		switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
 		case -EPIPE:
 			usbnet_defer_kevent (dev, EVENT_RX_HALT);
 			break;
@@ -444,7 +443,7 @@
 	    case -EOVERFLOW:
 		dev->stats.rx_over_errors++;
 		// FALLTHROUGH
-	    
+
 	    default:
 		entry->state = rx_cleanup;
 		dev->stats.rx_errors++;
@@ -561,7 +560,7 @@
 
 	if (netif_msg_ifdown (dev))
 		devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
-			dev->stats.rx_packets, dev->stats.tx_packets, 
+			dev->stats.rx_packets, dev->stats.tx_packets,
 			dev->stats.rx_errors, dev->stats.tx_errors
 			);
 
@@ -579,7 +578,7 @@
 			devdbg (dev, "waited for %d urb completions", temp);
 	}
 	dev->wait = NULL;
-	remove_wait_queue (&unlink_wakeup, &wait); 
+	remove_wait_queue (&unlink_wakeup, &wait);
 
 	usb_kill_urb(dev->interrupt);
 
@@ -835,7 +834,7 @@
 	}
 
 	if (test_bit (EVENT_LINK_RESET, &dev->flags)) {
-		struct driver_info 	*info = dev->driver_info;
+		struct driver_info	*info = dev->driver_info;
 		int			retval = 0;
 
 		clear_bit (EVENT_LINK_RESET, &dev->flags);
@@ -1067,7 +1066,7 @@
  * USB Device Driver support
  *
  *-------------------------------------------------------------------------*/
- 
+
 // precondition: never called in_interrupt
 
 void usbnet_disconnect (struct usb_interface *intf)
@@ -1088,7 +1087,7 @@
 			intf->dev.driver->name,
 			xdev->bus->bus_name, xdev->devpath,
 			dev->driver_info->description);
-	
+
 	net = dev->net;
 	unregister_netdev (net);
 
@@ -1112,7 +1111,7 @@
 usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 {
 	struct usbnet			*dev;
-	struct net_device 		*net;
+	struct net_device		*net;
 	struct usb_host_interface	*interface;
 	struct driver_info		*info;
 	struct usb_device		*xdev;
@@ -1182,6 +1181,9 @@
 	// NOTE net->name still not usable ...
 	if (info->bind) {
 		status = info->bind (dev, udev);
+		if (status < 0)
+			goto out1;
+
 		// heuristic:  "usb%d" for links we know are two-host,
 		// else "eth%d" when there's reasonable doubt.  userspace
 		// can rename the link if it knows better.
@@ -1208,12 +1210,12 @@
 	if (status == 0 && dev->status)
 		status = init_status (dev, udev);
 	if (status < 0)
-		goto out1;
+		goto out3;
 
 	if (!dev->rx_urb_size)
 		dev->rx_urb_size = dev->hard_mtu;
 	dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
-	
+
 	SET_NETDEV_DEV(net, &udev->dev);
 	status = register_netdev (net);
 	if (status)
@@ -1256,7 +1258,7 @@
 int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
 {
 	struct usbnet		*dev = usb_get_intfdata(intf);
-	
+
 	/* accelerate emptying of the rx and queues, to avoid
 	 * having everything error out.
 	 */
@@ -1287,7 +1289,7 @@
 			< sizeof (struct skb_data));
 
 	random_ether_addr(node_id);
- 	return 0;
+	return 0;
 }
 module_init(usbnet_init);
 
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
index 144566b..9f98e8c 100644
--- a/drivers/usb/net/zaurus.c
+++ b/drivers/usb/net/zaurus.c
@@ -21,7 +21,6 @@
 // #define	VERBOSE			// more; success messages
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 0af42e3..18816bf 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -58,11 +58,6 @@
 	if (urb->status) {
 		dbg("%s - nonzero read bulk status received: %d",
 		    __FUNCTION__, urb->status);
-		/* something happened, so free up the memory for this urb */
-		if (urb->transfer_buffer) {
-			kfree (urb->transfer_buffer);
-			urb->transfer_buffer = NULL;
-		}
 		return;
 	}
 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
@@ -146,6 +141,8 @@
 				  airprime_read_bulk_callback, port);
 		result = usb_submit_urb(urb, GFP_KERNEL);
 		if (result) {
+			usb_free_urb(urb);
+			kfree(buffer);
 			dev_err(&port->dev,
 				"%s - failed submitting read urb %d for port %d, error %d\n",
 				__FUNCTION__, i, port->number, result);
@@ -160,27 +157,12 @@
 	/* some error happened, cancel any submitted urbs and clean up anything that
 	   got allocated successfully */
 
-	for ( ; i >= 0; --i) {
+	while (i-- != 0) {
 		urb = priv->read_urbp[i];
-		if (urb) {
-			/* This urb was submitted successfully. So we have to
-			   cancel it.
-			   Unlinking the urb will invoke read_bulk_callback()
-			   with an error status, so its transfer buffer will
-			   be freed there */
-			if (usb_unlink_urb (urb) != -EINPROGRESS) {
-				/* comments in drivers/usb/core/urb.c say this
-				   can only happen if the urb was never submitted,
-				   or has completed already.
-				   Either way we may have to free the transfer
-				   buffer here. */
-				if (urb->transfer_buffer) {
-					kfree (urb->transfer_buffer);
-					urb->transfer_buffer = NULL;
-				}
-			}
-			usb_free_urb (urb);
-		}
+		buffer = urb->transfer_buffer;
+		usb_kill_urb (urb);
+		usb_free_urb (urb);
+		kfree (buffer);
 	}
 
  out:
@@ -194,10 +176,9 @@
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	/* killing the urb will invoke read_bulk_callback() with an error status,
-	   so the transfer buffer will be freed there */
 	for (i = 0; i < NUM_READ_URBS; ++i) {
 		usb_kill_urb (priv->read_urbp[i]);
+		kfree (priv->read_urbp[i]->transfer_buffer);
 		usb_free_urb (priv->read_urbp[i]);
 	}
 
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 06b4fff..db623e7 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -69,6 +69,7 @@
 	{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
 	{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
 	{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
 	{ } /* Terminating Entry */
@@ -170,13 +171,13 @@
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
-	u32 *buf;
+	__le32 *buf;
 	int result, i, length;
 
 	/* Number of integers required to contain the array */
 	length = (((size - 1) | 3) + 1)/4;
 
-	buf = kcalloc(length, sizeof(u32), GFP_KERNEL);
+	buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
 	if (!buf) {
 		dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
 		return -ENOMEM;
@@ -216,13 +217,13 @@
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
-	u32 *buf;
+	__le32 *buf;
 	int result, i, length;
 
 	/* Number of integers required to contain the array */
 	length = (((size - 1) | 3) + 1)/4;
 
-	buf = kmalloc(length * sizeof(u32), GFP_KERNEL);
+	buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
 	if (!buf) {
 		dev_err(&port->dev, "%s - out of memory.\n",
 				__FUNCTION__);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 0b0fb51..d78692c 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -616,15 +616,7 @@
 
 static void digi_wakeup_write( struct usb_serial_port *port )
 {
-
-	struct tty_struct *tty = port->tty;
-
-
-	/* wake up port processes */
-	wake_up_interruptible( &port->write_wait );
-
-	/* wake up line discipline */
-	tty_wakeup(tty);
+	tty_wakeup(port->tty);
 }
 
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 4695952..c525b42 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -513,6 +513,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
 	{ USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
+	{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 7eff1c0..1bdda93 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -491,6 +491,12 @@
 #define FTDI_TACTRIX_OPENPORT_13S_PID	0xCC49	/* OpenPort 1.3 Subaru */
 #define FTDI_TACTRIX_OPENPORT_13U_PID	0xCC4A	/* OpenPort 1.3 Universal */
 
+/*
+ * Telldus Technologies
+ */
+#define TELLDUS_VID			0x1781	/* Vendor ID */
+#define TELLDUS_TELLSTICK_PID		0x0C30	/* RF control dongle 433 MHz using FT232RL */
+
 /* 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/generic.c b/drivers/usb/serial/generic.c
index 601e064..53baeec 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -66,6 +66,8 @@
 	.num_bulk_out =		NUM_DONT_CARE,
 	.num_ports =		1,
 	.shutdown =		usb_serial_generic_shutdown,
+	.throttle =		usb_serial_generic_throttle,
+	.unthrottle =		usb_serial_generic_unthrottle,
 };
 
 static int generic_probe(struct usb_interface *interface,
@@ -115,6 +117,7 @@
 {
 	struct usb_serial *serial = port->serial;
 	int result = 0;
+	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -124,7 +127,13 @@
 	if (port->tty)
 		port->tty->low_latency = 1;
 
-	/* if we have a bulk interrupt, start reading from it */
+	/* clear the throttle flags */
+	spin_lock_irqsave(&port->lock, flags);
+	port->throttled = 0;
+	port->throttle_req = 0;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	/* if we have a bulk endpoint, start reading from it */
 	if (serial->num_bulk_in) {
 		/* Start reading from the device */
 		usb_fill_bulk_urb (port->read_urb, serial->dev,
@@ -253,31 +262,22 @@
 	return (chars);
 }
 
-void usb_serial_generic_read_bulk_callback (struct urb *urb)
+/* Push data to tty layer and resubmit the bulk read URB */
+static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
 {
-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial = port->serial;
-	struct tty_struct *tty;
-	unsigned char *data = urb->transfer_buffer;
+	struct urb *urb = port->read_urb;
+	struct tty_struct *tty = port->tty;
 	int result;
 
-	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
-		return;
-	}
-
-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
-
-	tty = port->tty;
+	/* Push data to tty */
 	if (tty && urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length);
-		tty_insert_flip_string(tty, data, urb->actual_length);
-	  	tty_flip_buffer_push(tty);
+		tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
+	  	tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
 	}
 
-	/* Continue trying to always read  */
+	/* Continue reading from device */
 	usb_fill_bulk_urb (port->read_urb, serial->dev,
 			   usb_rcvbulkpipe (serial->dev,
 				   	    port->bulk_in_endpointAddress),
@@ -290,6 +290,40 @@
 	if (result)
 		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
 }
+
+void usb_serial_generic_read_bulk_callback (struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	unsigned char *data = urb->transfer_buffer;
+	int is_throttled;
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (urb->status) {
+		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+		return;
+	}
+
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+
+	/* Throttle the device if requested by tty */
+	if (urb->actual_length) {
+		spin_lock_irqsave(&port->lock, flags);
+		is_throttled = port->throttled = port->throttle_req;
+		spin_unlock_irqrestore(&port->lock, flags);
+		if (is_throttled) {
+			/* Let the received data linger in the read URB;
+			 * usb_serial_generic_unthrottle() will pick it
+			 * up later. */
+			dbg("%s - throttling device", __FUNCTION__);
+			return;
+		}
+	}
+
+	/* Handle data and continue reading from device */
+	flush_and_resubmit_read_urb(port);
+}
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
 void usb_serial_generic_write_bulk_callback (struct urb *urb)
@@ -308,6 +342,38 @@
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
 
+void usb_serial_generic_throttle (struct usb_serial_port *port)
+{
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* Set the throttle request flag. It will be picked up
+	 * by usb_serial_generic_read_bulk_callback(). */
+	spin_lock_irqsave(&port->lock, flags);
+	port->throttle_req = 1;
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+void usb_serial_generic_unthrottle (struct usb_serial_port *port)
+{
+	int was_throttled;
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* Clear the throttle flags */
+	spin_lock_irqsave(&port->lock, flags);
+	was_throttled = port->throttled;
+	port->throttled = port->throttle_req = 0;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (was_throttled) {
+		/* Handle pending data and resume reading from device */
+		flush_and_resubmit_read_urb(port);
+	}
+}
+
 void usb_serial_generic_shutdown (struct usb_serial *serial)
 {
 	int i;
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index da514cb..dd0b66a 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -182,13 +182,8 @@
 	struct keyspan_pda_private *priv =
 		container_of(work, struct keyspan_pda_private, wakeup_work);
 	struct usb_serial_port *port = priv->port;
-	struct tty_struct *tty = port->tty;
 
-	/* wake up port processes */
-	wake_up_interruptible( &port->write_wait );
-
-	/* wake up line discipline */
-	tty_wakeup(tty);
+	tty_wakeup(port->tty);
 }
 
 static void keyspan_pda_request_unthrottle(struct work_struct *work)
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 6109c67..2d588fb 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -269,18 +269,8 @@
 
 	tty = mos7720_port->port->tty;
 
-	if (tty && mos7720_port->open) {
-		/* let the tty driver wakeup if it has a special *
-		 * write_wakeup function */
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		     tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-
-		/* tell the tty driver that something has changed */
-		wake_up_interruptible(&tty->write_wait);
-	}
-
-	/* schedule_work(&mos7720_port->port->work); */
+	if (tty && mos7720_port->open)
+		tty_wakeup(tty);
 }
 
 /*
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index b2264a8..c6cca85 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -755,18 +755,8 @@
 
 	tty = mos7840_port->port->tty;
 
-	if (tty && mos7840_port->open) {
-		/* let the tty driver wakeup if it has a special *
-		 * write_wakeup function                         */
-
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-		    && tty->ldisc.write_wakeup) {
-			(tty->ldisc.write_wakeup) (tty);
-		}
-
-		/* tell the tty driver that something has changed */
-		wake_up_interruptible(&tty->write_wait);
-	}
+	if (tty && mos7840_port->open)
+		tty_wakeup(tty);
 
 }
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index ced9f32..db92a7f 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -67,54 +67,95 @@
 static int  option_send_setup(struct usb_serial_port *port);
 
 /* Vendor and product IDs */
-#define OPTION_VENDOR_ID                0x0AF0
-#define HUAWEI_VENDOR_ID                0x12D1
-#define AUDIOVOX_VENDOR_ID              0x0F3D
-#define NOVATELWIRELESS_VENDOR_ID       0x1410
-#define ANYDATA_VENDOR_ID               0x16d5
+#define OPTION_VENDOR_ID			0x0AF0
+#define OPTION_PRODUCT_COLT			0x5000
+#define OPTION_PRODUCT_RICOLA			0x6000
+#define OPTION_PRODUCT_RICOLA_LIGHT		0x6100
+#define OPTION_PRODUCT_RICOLA_QUAD		0x6200
+#define OPTION_PRODUCT_RICOLA_QUAD_LIGHT	0x6300
+#define OPTION_PRODUCT_RICOLA_NDIS		0x6050
+#define OPTION_PRODUCT_RICOLA_NDIS_LIGHT	0x6150
+#define OPTION_PRODUCT_RICOLA_NDIS_QUAD		0x6250
+#define OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT	0x6350
+#define OPTION_PRODUCT_COBRA			0x6500
+#define OPTION_PRODUCT_COBRA_BUS		0x6501
+#define OPTION_PRODUCT_VIPER			0x6600
+#define OPTION_PRODUCT_VIPER_BUS		0x6601
+#define OPTION_PRODUCT_GT_MAX_READY		0x6701
+#define OPTION_PRODUCT_GT_MAX			0x6711
+#define OPTION_PRODUCT_FUJI_MODEM_LIGHT		0x6721
+#define OPTION_PRODUCT_FUJI_MODEM_GT		0x6741
+#define OPTION_PRODUCT_FUJI_MODEM_EX		0x6761
+#define OPTION_PRODUCT_FUJI_NETWORK_LIGHT	0x6731
+#define OPTION_PRODUCT_FUJI_NETWORK_GT		0x6751
+#define OPTION_PRODUCT_FUJI_NETWORK_EX		0x6771
+#define OPTION_PRODUCT_KOI_MODEM		0x6800
+#define OPTION_PRODUCT_KOI_NETWORK		0x6811
+#define OPTION_PRODUCT_SCORPION_MODEM		0x6901
+#define OPTION_PRODUCT_SCORPION_NETWORK		0x6911
+#define OPTION_PRODUCT_ETNA_MODEM		0x7001
+#define OPTION_PRODUCT_ETNA_NETWORK		0x7011
+#define OPTION_PRODUCT_ETNA_MODEM_LITE		0x7021
+#define OPTION_PRODUCT_ETNA_MODEM_GT		0x7041
+#define OPTION_PRODUCT_ETNA_MODEM_EX		0x7061
+#define OPTION_PRODUCT_ETNA_NETWORK_LITE	0x7031
+#define OPTION_PRODUCT_ETNA_NETWORK_GT		0x7051
+#define OPTION_PRODUCT_ETNA_NETWORK_EX		0x7071
+#define OPTION_PRODUCT_ETNA_KOI_MODEM		0x7100
+#define OPTION_PRODUCT_ETNA_KOI_NETWORK		0x7111
 
-#define OPTION_PRODUCT_OLD              0x5000
-#define OPTION_PRODUCT_FUSION           0x6000
-#define OPTION_PRODUCT_FUSION2          0x6300
-#define OPTION_PRODUCT_COBRA            0x6500
-#define OPTION_PRODUCT_COBRA2           0x6600
-#define OPTION_PRODUCT_GTMAX36          0x6701
-#define HUAWEI_PRODUCT_E600             0x1001
-#define HUAWEI_PRODUCT_E220             0x1003
-#define AUDIOVOX_PRODUCT_AIRCARD        0x0112
-#define NOVATELWIRELESS_PRODUCT_U740    0x1400
-#define ANYDATA_PRODUCT_ID              0x6501
+#define HUAWEI_VENDOR_ID			0x12D1
+#define HUAWEI_PRODUCT_E600			0x1001
+#define HUAWEI_PRODUCT_E220			0x1003
+
+#define NOVATELWIRELESS_VENDOR_ID		0x1410
+#define NOVATELWIRELESS_PRODUCT_U740		0x1400
+
+#define ANYDATA_VENDOR_ID			0x16d5
+#define ANYDATA_PRODUCT_ID			0x6501
 
 static struct usb_device_id option_ids[] = {
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD_LIGHT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_LIGHT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA_BUS) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER_BUS) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX_READY) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_LIGHT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_GT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_EX) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_LIGHT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_GT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_EX) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_MODEM) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_NETWORK) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_MODEM) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_NETWORK) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_LITE) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_LITE) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_GT) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
-	{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
 	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
 	{ } /* Terminating entry */
 };
-
-static struct usb_device_id option_ids1[] = {
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
-	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
-	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
-	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
-	{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
-	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
-	{ } /* Terminating entry */
-};
-
 MODULE_DEVICE_TABLE(usb, option_ids);
 
 static struct usb_driver option_driver = {
@@ -136,7 +177,7 @@
 	},
 	.description       = "GSM modem (1-port)",
 	.usb_driver        = &option_driver,
-	.id_table          = option_ids1,
+	.id_table          = option_ids,
 	.num_interrupt_in  = NUM_DONT_CARE,
 	.num_bulk_in       = NUM_DONT_CARE,
 	.num_bulk_out      = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 6c083d4..83dfae9 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -83,6 +83,7 @@
 	{ USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
 	{ USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
+	{ USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 65a50396..f9a71d0 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -97,3 +97,8 @@
 /* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */
 #define HUAWEI_VENDOR_ID	0x12d1
 #define HUAWEI_PRODUCT_ID	0x1001
+
+/* Willcom WS002IN Data Driver (by NetIndex Inc.) */
+#define WS002IN_VENDOR_ID	0x11f6
+#define WS002IN_PRODUCT_ID	0x2001
+
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 01d8971..c87ad1b 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -50,7 +50,6 @@
  * in that routine.
  */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index 5b06f92..3a41740 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -37,7 +37,6 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 
 #include "usb.h"
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index 5031aa9..003fcf5 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -47,7 +47,6 @@
   * in that routine.
   */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 70234f5..e227f64 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -153,6 +153,12 @@
 		if (us->flags & US_FL_FIX_CAPACITY)
 			sdev->fix_capacity = 1;
 
+		/* A few disks have two indistinguishable version, one of
+		 * which reports the correct capacity and the other does not.
+		 * The sd driver has to guess which is the case. */
+		if (us->flags & US_FL_CAPACITY_HEURISTICS)
+			sdev->guess_capacity = 1;
+
 		/* Some devices report a SCSI revision level above 2 but are
 		 * unable to handle the REPORT LUNS command (for which
 		 * support is mandatory at level 3).  Since we already have
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index e3528ec..b2ed2a3 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -41,7 +41,6 @@
  * EF: compute checksum (?)
  */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 8fcec01..5e27297 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -43,7 +43,6 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/cdrom.h>
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index f49a62f..9644a8e 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1101,6 +1101,15 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
+/* Submitted by Dylan Taft <d13f00l@gmail.com>
+ * US_FL_IGNORE_RESIDUE Needed
+ */
+UNUSUAL_DEV(  0x08ca, 0x3103, 0x0100, 0x0100,
+                "AIPTEK",
+                "Aiptek USB Keychain MP3 Player",
+                US_SC_DEVICE, US_PR_DEVICE, NULL,
+                US_FL_IGNORE_RESIDUE),
+
 /* Entry needed for flags. Moreover, all devices with this ID use
  * bulk-only transport, but _some_ falsely report Control/Bulk instead.
  * One example is "Trumpion Digital Research MYMP3".
@@ -1311,12 +1320,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_NO_WP_DETECT ),
 
-/* Reported by Jan Mate <mate@fiit.stuba.sk> */
+/* Reported by Jan Mate <mate@fiit.stuba.sk>
+ * and by Soeren Sonnenburg <kernel@nn7.de> */
 UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"P990i",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_CAPACITY ),
+		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */
 UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
@@ -1385,6 +1395,16 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Thomas Baechler <thomas@archlinux.org>
+ * Fixes I/O errors with Teac HD-35PU devices
+ */
+
+UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
+               "Super Top",
+               "USB 2.0  IDE DEVICE",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE),
+
 /* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
  * and Renato Perini <rperini@email.it>
  */
@@ -1423,7 +1443,7 @@
 		"DataStor",
 		"USB4500 FW1.04",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_CAPACITY),
+		US_FL_CAPACITY_HEURISTICS),
 
 /* Control/Bulk transport for all SubClass values */
 USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 296b091..46929a1 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -90,14 +90,16 @@
 		goto exit;
 	}
 
-	/* prevent the device from being autosuspended */
-	retval = usb_autopm_get_interface(interface);
-	if (retval)
-		goto exit;
-
 	/* increment our usage count for the device */
 	kref_get(&dev->kref);
 
+	/* prevent the device from being autosuspended */
+	retval = usb_autopm_get_interface(interface);
+	if (retval) {
+		kref_put(&dev->kref, skel_delete);
+		goto exit;
+	}
+
 	/* save our object in the file's private structure */
 	file->private_data = dev;
 
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4e83f01..c1536d7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -4,20 +4,7 @@
 
 menu "Graphics support"
 
-config FIRMWARE_EDID
-       bool "Enable firmware EDID"
-       default y
-       ---help---
-         This enables access to the EDID transferred from the firmware.
-	 On the i386, this is from the Video BIOS. Enable this if DDC/I2C
-	 transfers do not work for your driver and if you are using
-	 nvidiafb, i810fb or savagefb.
-
-	 In general, choosing Y for this option is safe.  If you
-	 experience extremely long delays while booting before you get
-	 something on your display, try setting this to N.  Matrox cards in
-	 combination with certain motherboards and monitors are known to
-	 suffer from this problem.
+source "drivers/video/backlight/Kconfig"
 
 config FB
 	tristate "Support for frame buffer devices"
@@ -53,9 +40,27 @@
 	  (e.g. an accelerated X server) and that are not frame buffer
 	  device-aware may cause unexpected results. If unsure, say N.
 
+config FIRMWARE_EDID
+       bool "Enable firmware EDID"
+       depends on FB
+       default n
+       ---help---
+         This enables access to the EDID transferred from the firmware.
+	 On the i386, this is from the Video BIOS. Enable this if DDC/I2C
+	 transfers do not work for your driver and if you are using
+	 nvidiafb, i810fb or savagefb.
+
+	 In general, choosing Y for this option is safe.  If you
+	 experience extremely long delays while booting before you get
+	 something on your display, try setting this to N.  Matrox cards in
+	 combination with certain motherboards and monitors are known to
+	 suffer from this problem.
+
 config FB_DDC
        tristate
-       depends on FB && I2C && I2C_ALGOBIT
+       depends on FB
+       select I2C_ALGOBIT
+       select I2C
        default n
 
 config FB_CFB_FILLRECT
@@ -85,6 +90,14 @@
 	  blitting. This is used by drivers that don't provide their own
 	  (accelerated) version.
 
+config FB_SVGALIB
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Common utility functions useful to fbdev drivers of VGA-based
+	  cards.
+
 config FB_MACMODES
        tristate
        depends on FB
@@ -126,6 +139,9 @@
 	 This is particularly important to one driver, matroxfb.  If
 	 unsure, say N.
 
+comment "Frambuffer hardware drivers"
+	depends on FB
+
 config FB_CIRRUS
 	tristate "Cirrus Logic support"
 	depends on FB && (ZORRO || PCI)
@@ -346,42 +362,6 @@
 	  and CD32. If you intend to run Linux on any of these systems, say Y;
 	  otherwise say N.
 
-config FB_CYBER
-	tristate "Amiga CyberVision 64 support"
-	depends on FB && ZORRO && BROKEN
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This enables support for the Cybervision 64 graphics card from
-	  Phase5. Please note that its use is not all that intuitive (i.e. if
-	  you have any questions, be sure to ask!). Say N unless you have a
-	  Cybervision 64 or plan to get one before you next recompile the
-	  kernel. Please note that this driver DOES NOT support the
-	  Cybervision 64/3D card, as they use incompatible video chips.
-
-config FB_VIRGE
-	bool "Amiga CyberVision 64/3D support "
-	depends on (FB = y) && ZORRO && BROKEN
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This enables support for the Cybervision 64/3D graphics card from
-	  Phase5. Please note that its use is not all that intuitive (i.e. if
-	  you have any questions, be sure to ask!). Say N unless you have a
-	  Cybervision 64/3D or plan to get one before you next recompile the
-	  kernel. Please note that this driver DOES NOT support the older
-	  Cybervision 64 card, as they use incompatible video chips.
-
-config FB_RETINAZ3
-	tristate "Amiga Retina Z3 support"
-	depends on (FB = y) && ZORRO && BROKEN
-	help
-	  This enables support for the Retina Z3 graphics card. Say N unless
-	  you have a Retina Z3 or plan to get one before you next recompile
-	  the kernel.
-
 config FB_FM2
 	bool "Amiga FrameMaster II/Rainbow II support"
 	depends on (FB = y) && ZORRO
@@ -617,10 +597,6 @@
 	  This is the amount of memory reserved for the framebuffer,
 	  which can be any value between 1MB and 8MB.
 
-config FB_SUN3
-	bool "Sun3 framebuffer support"
-	depends on (FB = y) && (SUN3 || SUN3X) && BROKEN
-
 config FB_SBUS
 	bool "SBUS and UPA framebuffers"
 	depends on (FB = y) && SPARC
@@ -629,7 +605,7 @@
 
 config FB_BW2
 	bool "BWtwo support"
-	depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && (SPARC && FB_SBUS)
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -638,7 +614,7 @@
 
 config FB_CG3
 	bool "CGthree support"
-	depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && (SPARC && FB_SBUS)
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -647,7 +623,7 @@
 
 config FB_CG6
 	bool "CGsix (GX,TurboGX) support"
-	depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && (SPARC && FB_SBUS)
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
 	help
@@ -703,6 +679,7 @@
 	depends on FB && PCI
 	select I2C_ALGOBIT if FB_NVIDIA_I2C
 	select I2C if FB_NVIDIA_I2C
+	select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT
 	select FB_MODE_HELPERS
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
@@ -731,8 +708,7 @@
 
 config FB_NVIDIA_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_NVIDIA && PMAC_BACKLIGHT
-	select FB_BACKLIGHT
+	depends on FB_NVIDIA
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -740,9 +716,8 @@
 config FB_RIVA
 	tristate "nVidia Riva support"
 	depends on FB && PCI
-	select I2C_ALGOBIT if FB_RIVA_I2C
-	select I2C if FB_RIVA_I2C
 	select FB_DDC if FB_RIVA_I2C
+	select FB_BACKLIGHT if FB_RIVA_BACKLIGHT
 	select FB_MODE_HELPERS
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
@@ -779,8 +754,7 @@
 
 config FB_RIVA_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_RIVA && PMAC_BACKLIGHT
-	select FB_BACKLIGHT
+	depends on FB_RIVA
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -830,8 +804,6 @@
 config FB_I810_I2C
 	bool "Enable DDC Support"
 	depends on FB_I810 && FB_I810_GTF
-	select I2C
-	select I2C_ALGOBIT
 	select FB_DDC
 	help
 
@@ -1021,9 +993,8 @@
 config FB_RADEON
 	tristate "ATI Radeon display support"
 	depends on FB && PCI
-	select I2C_ALGOBIT if FB_RADEON_I2C
-	select I2C if FB_RADEON_I2C
 	select FB_DDC if FB_RADEON_I2C
+	select FB_BACKLIGHT if FB_RADEON_BACKLIGHT
 	select FB_MODE_HELPERS
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
@@ -1053,8 +1024,7 @@
 
 config FB_RADEON_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_RADEON && PMAC_BACKLIGHT
-	select FB_BACKLIGHT
+	depends on FB_RADEON
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -1074,6 +1044,7 @@
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	select FB_BACKLIGHT if FB_ATY128_BACKLIGHT
 	select FB_MACMODES if PPC_PMAC
 	help
 	  This driver supports graphics boards with the ATI Rage128 chips.
@@ -1085,8 +1056,7 @@
 
 config FB_ATY128_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_ATY128 && PMAC_BACKLIGHT
-	select FB_BACKLIGHT
+	depends on FB_ATY128
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -1097,6 +1067,7 @@
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	select FB_BACKLIGHT if FB_ATY_BACKLIGHT
 	select FB_MACMODES if PPC
 	help
 	  This driver supports graphics boards with the ATI Mach64 chips.
@@ -1135,23 +1106,25 @@
 
 config FB_ATY_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_ATY && PMAC_BACKLIGHT
-	select FB_BACKLIGHT
+	depends on FB_ATY
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
 
-config FB_S3TRIO
-	bool "S3 Trio display support"
-	depends on (FB = y) && PPC && BROKEN
-	help
-	  If you have a S3 Trio say Y. Say N for S3 Virge.
+config FB_S3
+	tristate "S3 Trio/Virge support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_TILEBLITTING
+	select FB_SVGALIB
+	---help---
+	  Driver for graphics boards with S3 Trio / S3 Virge chip.
 
 config FB_SAVAGE
 	tristate "S3 Savage support"
 	depends on FB && PCI && EXPERIMENTAL
-	select I2C_ALGOBIT if FB_SAVAGE_I2C
-	select I2C if FB_SAVAGE_I2C
 	select FB_DDC if FB_SAVAGE_I2C
 	select FB_MODE_HELPERS
 	select FB_CFB_FILLRECT
@@ -1444,8 +1417,8 @@
 	  used mainly in the MIPS-based DECstation series.
 
 config FB_PMAG_BA
-	bool "PMAG-BA TURBOchannel framebuffer support"
-	depends on (FB = y) && TC
+	tristate "PMAG-BA TURBOchannel framebuffer support"
+	depends on FB && TC
  	select FB_CFB_FILLRECT
  	select FB_CFB_COPYAREA
  	select FB_CFB_IMAGEBLIT
@@ -1454,8 +1427,8 @@
 	  used mainly in the MIPS-based DECstation series.
 
 config FB_PMAGB_B
-	bool "PMAGB-B TURBOchannel framebuffer support"
-	depends on (FB = y) && TC
+	tristate "PMAGB-B TURBOchannel framebuffer support"
+	depends on TC
  	select FB_CFB_FILLRECT
  	select FB_CFB_COPYAREA
  	select FB_CFB_IMAGEBLIT
@@ -1600,6 +1573,24 @@
 	  Turn on debugging messages. Note that you can set/unset at run time
 	  through sysfs
 
+config FB_SM501
+	tristate "Silicon Motion SM501 framebuffer support"
+	depends on FB && MFD_SM501
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Frame buffer driver for the CRT and LCD controllers in the Silicon
+	  Motion SM501.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted and removed from the running kernel whenever you want). The
+	  module will be called sm501fb. If you want to compile it as a module,
+	  say M here and read <file:Documentation/modules.txt>.
+
+	  If unsure, say N.
+
+
 config FB_PNX4008_DUM
 	tristate "Display Update Module support on Philips PNX4008 board"
 	depends on FB && ARCH_PNX4008
@@ -1625,6 +1616,26 @@
 	  Say Y here to enable support for the IBM GXT4500P display
 	  adaptor, found on some IBM System P (pSeries) machines.
 
+config FB_PS3
+	bool "PS3 GPU framebuffer driver"
+	depends on FB && PPC_PS3
+	select PS3_PS3AV
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Include support for the virtual frame buffer in the PS3 platform.
+
+config FB_PS3_DEFAULT_SIZE_M
+	int "PS3 default frame buffer size (in MiB)"
+	depends on FB_PS3
+	default 18
+	---help---
+	  This is the default size (in MiB) of the virtual frame buffer in
+	  the PS3.
+	  The default value can be overridden on the kernel command line
+	  using the "ps3fb" option (e.g. "ps3fb=9M");
+
 config FB_VIRTUAL
 	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
 	depends on FB
@@ -1646,6 +1657,7 @@
 	  the vfb_enable=1 option.
 
 	  If unsure, say N.
+
 if VT
 	source "drivers/video/console/Kconfig"
 endif
@@ -1654,9 +1666,5 @@
 	source "drivers/video/logo/Kconfig"
 endif
 
-if SYSFS
-	source "drivers/video/backlight/Kconfig"
-endif
-
 endmenu
 
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 309a26d..760305c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -12,20 +12,19 @@
 
 obj-$(CONFIG_VT)		  += console/
 obj-$(CONFIG_LOGO)		  += logo/
-obj-$(CONFIG_SYSFS)		  += backlight/
+obj-y				  += backlight/
 
 obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
 obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
 obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
+obj-$(CONFIG_FB_SVGALIB)       += svgalib.o
 obj-$(CONFIG_FB_MACMODES)      += macmodes.o
 obj-$(CONFIG_FB_DDC)           += fb_ddc.o
 
 # Hardware specific drivers go first
-obj-$(CONFIG_FB_RETINAZ3)         += retz3fb.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
 obj-$(CONFIG_FB_ARC)              += arcfb.o
 obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
-obj-$(CONFIG_FB_CYBER)            += cyberfb.o
 obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
 obj-$(CONFIG_FB_PM2)              += pm2fb.o
 obj-$(CONFIG_FB_PM3)		  += pm3fb.o
@@ -43,17 +42,16 @@
 obj-$(CONFIG_FB_MBX)		  += mbx/
 obj-$(CONFIG_FB_I810)             += vgastate.o
 obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o vgastate.o
-obj-$(CONFIG_FB_VIRGE)            += virgefb.o
 obj-$(CONFIG_FB_3DFX)             += tdfxfb.o
 obj-$(CONFIG_FB_CONTROL)          += controlfb.o
 obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o
 obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o
 obj-$(CONFIG_FB_CT65550)          += chipsfb.o
 obj-$(CONFIG_FB_IMSTT)            += imsttfb.o
-obj-$(CONFIG_FB_S3TRIO)           += S3triofb.o
 obj-$(CONFIG_FB_FM2)              += fm2fb.o
 obj-$(CONFIG_FB_CYBLA)            += cyblafb.o
 obj-$(CONFIG_FB_TRIDENT)          += tridentfb.o
+obj-$(CONFIG_FB_S3)               += s3fb.o vgastate.o
 obj-$(CONFIG_FB_STI)              += stifb.o
 obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o
 obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o
@@ -75,7 +73,6 @@
 obj-$(CONFIG_FB_HP300)            += hpfb.o
 obj-$(CONFIG_FB_G364)             += g364fb.o
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
-obj-$(CONFIG_FB_SUN3)             += sun3fb.o
 obj-$(CONFIG_FB_HIT)              += hitfb.o
 obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
@@ -100,6 +97,8 @@
 obj-$(CONFIG_FB_PNX4008_DUM)	  += pnx4008/
 obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/
 obj-$(CONFIG_FB_IBM_GXT4500)	  += gxt4500.o
+obj-$(CONFIG_FB_PS3)		  += ps3fb.o
+obj-$(CONFIG_FB_SM501)            += sm501fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c
deleted file mode 100644
index b3717c8..0000000
--- a/drivers/video/S3triofb.c
+++ /dev/null
@@ -1,790 +0,0 @@
-/*
- *  linux/drivers/video/S3Triofb.c -- Open Firmware based frame buffer device
- *
- *	Copyright (C) 1997 Peter De Schrijver
- *
- *  This driver is partly based on the PowerMac console driver:
- *
- *	Copyright (C) 1996 Paul Mackerras
- *
- *  and on the Open Firmware based frame buffer device:
- *
- *	Copyright (C) 1997 Geert Uytterhoeven
- *
- *  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.
- */
-
-/*
-	Bugs : + OF dependencies should be removed.
-               + This driver should be merged with the CyberVision driver. The
-                 CyberVision is a Zorro III implementation of the S3Trio64 chip.
-
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/selection.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <linux/pci.h>
-
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/s3blit.h>
-
-
-#define mem_in8(addr)           in_8((void *)(addr))
-#define mem_in16(addr)          in_le16((void *)(addr))
-#define mem_in32(addr)          in_le32((void *)(addr))
-
-#define mem_out8(val, addr)     out_8((void *)(addr), val)
-#define mem_out16(val, addr)    out_le16((void *)(addr), val)
-#define mem_out32(val, addr)    out_le32((void *)(addr), val)
-
-#define IO_OUT16VAL(v, r)       (((v) << 8) | (r))
-
-static struct display disp;
-static struct fb_info fb_info;
-static struct { u_char red, green, blue, pad; } palette[256];
-static char s3trio_name[16] = "S3Trio ";
-static char *s3trio_base;
-
-static struct fb_fix_screeninfo fb_fix;
-static struct fb_var_screeninfo fb_var = { 0, };
-
-
-    /*
-     *  Interface used by the world
-     */
-
-static void __init s3triofb_of_init(struct device_node *dp);
-static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con,
-			  struct fb_info *info);
-static int s3trio_get_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info);
-static int s3trio_set_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info);
-static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			   struct fb_info *info);
-static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                         u_int transp, struct fb_info *info);
-static int s3trio_pan_display(struct fb_var_screeninfo *var, int con,
-			      struct fb_info *info);
-static void s3triofb_blank(int blank, struct fb_info *info);
-
-    /*
-     *  Interface to the low level console driver
-     */
-
-int s3triofb_init(void);
-static int s3triofbcon_switch(int con, struct fb_info *info);
-static int s3triofbcon_updatevar(int con, struct fb_info *info);
-
-    /*
-     *  Text console acceleration
-     */
-
-#ifdef FBCON_HAS_CFB8
-static struct display_switch fbcon_trio8;
-#endif
-
-    /*
-     *    Accelerated Functions used by the low level console driver
-     */
-
-static void Trio_WaitQueue(u_short fifo);
-static void Trio_WaitBlit(void);
-static void Trio_BitBLT(u_short curx, u_short cury, u_short destx,
-			u_short desty, u_short width, u_short height,
-			u_short mode);
-static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height,
-			  u_short mode, u_short color);
-static void Trio_MoveCursor(u_short x, u_short y);
-
-
-    /*
-     *  Internal routines
-     */
-
-static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-                         u_int *transp, struct fb_info *info);
-
-static struct fb_ops s3trio_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	s3trio_get_fix,
-	.fb_get_var =	s3trio_get_var,
-	.fb_set_var =	s3trio_set_var,
-	.fb_get_cmap =	s3trio_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_setcolreg =	s3trio_setcolreg,
-	.fb_pan_display =s3trio_pan_display,
-	.fb_blank =	s3triofb_blank,
-};
-
-    /*
-     *  Get the Fixed Part of the Display
-     */
-
-static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con,
-			  struct fb_info *info)
-{
-    memcpy(fix, &fb_fix, sizeof(fb_fix));
-    return 0;
-}
-
-
-    /*
-     *  Get the User Defined Part of the Display
-     */
-
-static int s3trio_get_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info)
-{
-    memcpy(var, &fb_var, sizeof(fb_var));
-    return 0;
-}
-
-
-    /*
-     *  Set the User Defined Part of the Display
-     */
-
-static int s3trio_set_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info)
-{
-    if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
-	var->bits_per_pixel > fb_var.bits_per_pixel )
-	/* || var->nonstd || var->vmode != FB_VMODE_NONINTERLACED) */
-	return -EINVAL;
-    if (var->xres_virtual > fb_var.xres_virtual) {
-	outw(IO_OUT16VAL((var->xres_virtual /8) & 0xff, 0x13), 0x3d4);
-	outw(IO_OUT16VAL(((var->xres_virtual /8 ) & 0x300) >> 3, 0x51), 0x3d4);
-	fb_var.xres_virtual = var->xres_virtual;
-	fb_fix.line_length = var->xres_virtual;
-    }
-    fb_var.yres_virtual = var->yres_virtual;
-    memcpy(var, &fb_var, sizeof(fb_var));
-    return 0;
-}
-
-
-    /*
-     *  Pan or Wrap the Display
-     *
-     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-     */
-
-static int s3trio_pan_display(struct fb_var_screeninfo *var, int con,
-			      struct fb_info *info)
-{
-    unsigned int base;
-
-    if (var->xoffset > (var->xres_virtual - var->xres))
-	return -EINVAL;
-    if (var->yoffset > (var->yres_virtual - var->yres))
-	return -EINVAL;
-
-    fb_var.xoffset = var->xoffset;
-    fb_var.yoffset = var->yoffset;
-
-    base = var->yoffset * fb_fix.line_length + var->xoffset;
-
-    outw(IO_OUT16VAL((base >> 8) & 0xff, 0x0c),0x03D4);
-    outw(IO_OUT16VAL(base  & 0xff, 0x0d),0x03D4);
-    outw(IO_OUT16VAL((base >> 16) & 0xf, 0x69),0x03D4);
-    return 0;
-}
-
-
-    /*
-     *  Get the Colormap
-     */
-
-static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			   struct fb_info *info)
-{
-    if (con == info->currcon) /* current console? */
-	return fb_get_cmap(cmap, kspc, s3trio_getcolreg, info);
-    else if (fb_display[con].cmap.len) /* non default colormap? */
-	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-    else
-	fb_copy_cmap(fb_default_cmap(1 << fb_display[con].var.bits_per_pixel),
-		     cmap, kspc ? 0 : 2);
-    return 0;
-}
-
-int __init s3triofb_init(void)
-{
-	struct device_node *dp;
-
-	dp = find_devices("S3Trio");
-	if (dp != 0)
-	    s3triofb_of_init(dp);
-	return 0;
-}
-
-void __init s3trio_resetaccel(void){
-
-
-#define EC01_ENH_ENB    0x0005
-#define EC01_LAW_ENB    0x0010
-#define EC01_MMIO_ENB   0x0020
-
-#define EC00_RESET      0x8000
-#define EC00_ENABLE     0x4000
-#define MF_MULT_MISC    0xE000
-#define SRC_FOREGROUND  0x0020
-#define SRC_BACKGROUND  0x0000
-#define MIX_SRC                 0x0007
-#define MF_T_CLIP       0x1000
-#define MF_L_CLIP       0x2000
-#define MF_B_CLIP       0x3000
-#define MF_R_CLIP       0x4000
-#define MF_PIX_CONTROL  0xA000
-#define MFA_SRC_FOREGR_MIX      0x0000
-#define MF_PIX_CONTROL  0xA000
-
-	outw(EC00_RESET,  0x42e8);
-	inw(  0x42e8);
-	outw(EC00_ENABLE,  0x42e8);
-	inw(  0x42e8);
-	outw(EC01_ENH_ENB | EC01_LAW_ENB,
-		   0x4ae8);
-	outw(MF_MULT_MISC,  0xbee8); /* 16 bit I/O registers */
-
-	/* Now set some basic accelerator registers */
-	Trio_WaitQueue(0x0400);
-	outw(SRC_FOREGROUND | MIX_SRC, 0xbae8);
-	outw(SRC_BACKGROUND | MIX_SRC,  0xb6e8);/* direct color*/
-	outw(MF_T_CLIP | 0, 0xbee8 );     /* clip virtual area  */
-	outw(MF_L_CLIP | 0, 0xbee8 );
-	outw(MF_R_CLIP | (640 - 1), 0xbee8);
-	outw(MF_B_CLIP | (480 - 1),  0xbee8);
-	Trio_WaitQueue(0x0400);
-	outw(0xffff,  0xaae8);       /* Enable all planes */
-	outw(0xffff, 0xaae8);       /* Enable all planes */
-	outw( MF_PIX_CONTROL | MFA_SRC_FOREGR_MIX,  0xbee8);
-}
-
-int __init s3trio_init(struct device_node *dp){
-
-    u_char bus, dev;
-    unsigned int t32;
-    unsigned short cmd;
-
-	pci_device_loc(dp,&bus,&dev);
-                pcibios_read_config_dword(bus, dev, PCI_VENDOR_ID, &t32);
-                if(t32 == (PCI_DEVICE_ID_S3_TRIO << 16) + PCI_VENDOR_ID_S3) {
-                        pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32);
-                        pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_1, &t32);
-			pcibios_read_config_word(bus, dev, PCI_COMMAND,&cmd);
-
-			pcibios_write_config_word(bus, dev, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-
-			pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_0,0xffffffff);
-                        pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32);
-
-/* This is a gross hack as OF only maps enough memory for the framebuffer and
-   we want to use MMIO too. We should find out which chunk of address space
-   we can use here */
-			pcibios_write_config_dword(bus,dev,PCI_BASE_ADDRESS_0,0xc6000000);
-
-			/* unlock s3 */
-
-			outb(0x01, 0x3C3);
-
-			outb(inb(0x03CC) | 1, 0x3c2);
-
-			outw(IO_OUT16VAL(0x48, 0x38),0x03D4);
-			outw(IO_OUT16VAL(0xA0, 0x39),0x03D4);
-			outb(0x33,0x3d4);
-			outw(IO_OUT16VAL((inb(0x3d5) & ~(0x2 | 0x10 |  0x40)) |
-					  0x20, 0x33), 0x3d4);
-
-			outw(IO_OUT16VAL(0x6, 0x8), 0x3c4);
-
-			/* switch to MMIO only mode */
-
-			outb(0x58, 0x3d4);
-			outw(IO_OUT16VAL(inb(0x3d5) | 3 | 0x10, 0x58), 0x3d4);
-			outw(IO_OUT16VAL(8, 0x53), 0x3d4);
-
-			/* switch off I/O accesses */
-
-#if 0
-			pcibios_write_config_word(bus, dev, PCI_COMMAND,
-				        PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-#endif
-			return 1;
-                }
-
-	return 0;
-}
-
-
-    /*
-     *  Initialisation
-     *  We heavily rely on OF for the moment. This needs fixing.
-     */
-
-static void __init s3triofb_of_init(struct device_node *dp)
-{
-    int i, *pp, len;
-    unsigned long address, size;
-    u_long *CursorBase;
-
-    strncat(s3trio_name, dp->name, sizeof(s3trio_name));
-    s3trio_name[sizeof(s3trio_name)-1] = '\0';
-    strcpy(fb_fix.id, s3trio_name);
-
-    if((pp = get_property(dp, "vendor-id", &len)) != NULL
-	&& *pp!=PCI_VENDOR_ID_S3) {
-	printk("%s: can't find S3 Trio board\n", dp->full_name);
-	return;
-    }
-
-    if((pp = get_property(dp, "device-id", &len)) != NULL
-	&& *pp!=PCI_DEVICE_ID_S3_TRIO) {
-	printk("%s: can't find S3 Trio board\n", dp->full_name);
-	return;
-    }
-
-    if ((pp = get_property(dp, "depth", &len)) != NULL
-	&& len == sizeof(int) && *pp != 8) {
-	printk("%s: can't use depth = %d\n", dp->full_name, *pp);
-	return;
-    }
-    if ((pp = get_property(dp, "width", &len)) != NULL
-	&& len == sizeof(int))
-	fb_var.xres = fb_var.xres_virtual = *pp;
-    if ((pp = get_property(dp, "height", &len)) != NULL
-	&& len == sizeof(int))
-	fb_var.yres = fb_var.yres_virtual = *pp;
-    if ((pp = get_property(dp, "linebytes", &len)) != NULL
-	&& len == sizeof(int))
-	fb_fix.line_length = *pp;
-    else
-	fb_fix.line_length = fb_var.xres_virtual;
-    fb_fix.smem_len = fb_fix.line_length*fb_var.yres;
-
-    address = 0xc6000000;
-    size = 64*1024*1024;
-    if (!request_mem_region(address, size, "S3triofb"))
-	return;
-
-    s3trio_init(dp);
-    s3trio_base = ioremap(address, size);
-    fb_fix.smem_start = address;
-    fb_fix.type = FB_TYPE_PACKED_PIXELS;
-    fb_fix.type_aux = 0;
-    fb_fix.accel = FB_ACCEL_S3_TRIO64;
-    fb_fix.mmio_start = address+0x1000000;
-    fb_fix.mmio_len = 0x1000000;
-
-    fb_fix.xpanstep = 1;
-    fb_fix.ypanstep = 1;
-
-    s3trio_resetaccel();
-
-    mem_out8(0x30, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0x2d, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0x2e, s3trio_base+0x1008000 + 0x03D4);
-
-    mem_out8(0x50, s3trio_base+0x1008000 + 0x03D4);
-
-    /* disable HW cursor */
-
-    mem_out8(0x39, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0xa0, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x4e, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x4f, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
-
-    /* init HW cursor */
-
-    CursorBase = (u_long *)(s3trio_base + 2*1024*1024 - 0x400);
-	for (i = 0; i < 8; i++) {
-		*(CursorBase  +(i*4)) = 0xffffff00;
-		*(CursorBase+1+(i*4)) = 0xffff0000;
-		*(CursorBase+2+(i*4)) = 0xffff0000;
-		*(CursorBase+3+(i*4)) = 0xffff0000;
-	}
-	for (i = 8; i < 64; i++) {
-		*(CursorBase  +(i*4)) = 0xffff0000;
-		*(CursorBase+1+(i*4)) = 0xffff0000;
-		*(CursorBase+2+(i*4)) = 0xffff0000;
-		*(CursorBase+3+(i*4)) = 0xffff0000;
-	}
-
-
-    mem_out8(0x4c, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(((2*1024 - 1)&0xf00)>>8, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x4d, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8((2*1024 - 1) & 0xff, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4);
-    mem_in8(s3trio_base+0x1008000 + 0x03D4);
-
-    mem_out8(0x4a, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5);
-    mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5);
-    mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x4b, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5);
-    mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5);
-    mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
-
-    /* setup default color table */
-
-	for(i = 0; i < 16; i++) {
-		int j = color_table[i];
-		palette[i].red=default_red[j];
-		palette[i].green=default_grn[j];
-		palette[i].blue=default_blu[j];
-	}
-
-    s3trio_setcolreg(255, 56, 100, 160, 0, NULL /* not used */);
-    s3trio_setcolreg(254, 0, 0, 0, 0, NULL /* not used */);
-    memset((char *)s3trio_base, 0, 640*480);
-
-#if 0
-    Trio_RectFill(0, 0, 90, 90, 7, 1);
-#endif
-
-    fb_fix.visual = FB_VISUAL_PSEUDOCOLOR ;
-    fb_var.xoffset = fb_var.yoffset = 0;
-    fb_var.bits_per_pixel = 8;
-    fb_var.grayscale = 0;
-    fb_var.red.offset = fb_var.green.offset = fb_var.blue.offset = 0;
-    fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
-    fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
-    fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
-    fb_var.nonstd = 0;
-    fb_var.activate = 0;
-    fb_var.height = fb_var.width = -1;
-    fb_var.accel_flags = FB_ACCELF_TEXT;
-#warning FIXME: always obey fb_var.accel_flags
-    fb_var.pixclock = 1;
-    fb_var.left_margin = fb_var.right_margin = 0;
-    fb_var.upper_margin = fb_var.lower_margin = 0;
-    fb_var.hsync_len = fb_var.vsync_len = 0;
-    fb_var.sync = 0;
-    fb_var.vmode = FB_VMODE_NONINTERLACED;
-
-    disp.var = fb_var;
-    disp.cmap.start = 0;
-    disp.cmap.len = 0;
-    disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
-    disp.visual = fb_fix.visual;
-    disp.type = fb_fix.type;
-    disp.type_aux = fb_fix.type_aux;
-    disp.ypanstep = 0;
-    disp.ywrapstep = 0;
-    disp.line_length = fb_fix.line_length;
-    disp.can_soft_blank = 1;
-    disp.inverse = 0;
-#ifdef FBCON_HAS_CFB8
-    if (fb_var.accel_flags & FB_ACCELF_TEXT)
-	disp.dispsw = &fbcon_trio8;
-    else
-	disp.dispsw = &fbcon_cfb8;
-#else
-    disp.dispsw = &fbcon_dummy;
-#endif
-    disp.scrollmode = fb_var.accel_flags & FB_ACCELF_TEXT ? 0 : SCROLL_YREDRAW;
-
-    strcpy(fb_info.modename, "Trio64 ");
-    strncat(fb_info.modename, dp->full_name, sizeof(fb_info.modename));
-    fb_info.currcon = -1;
-    fb_info.fbops = &s3trio_ops;
-    fb_info.screen_base = s3trio_base;	
-#if 0
-    fb_info.fbvar_num = 1;
-    fb_info.fbvar = &fb_var;
-#endif
-    fb_info.disp = &disp;
-    fb_info.fontname[0] = '\0';
-    fb_info.changevar = NULL;
-    fb_info.switch_con = &s3triofbcon_switch;
-    fb_info.updatevar = &s3triofbcon_updatevar;
-#if 0
-    fb_info.setcmap = &s3triofbcon_setcmap;
-#endif
-
-    fb_info.flags = FBINFO_FLAG_DEFAULT;
-    if (register_framebuffer(&fb_info) < 0) {
-		iounmap(fb_info.screen_base);
-		fb_info.screen_base = NULL;
-		return;
-    }
-
-    printk("fb%d: S3 Trio frame buffer device on %s\n",
-	   fb_info.node, dp->full_name);
-}
-
-
-static int s3triofbcon_switch(int con, struct fb_info *info)
-{
-    /* Do we have to save the colormap? */
-    if (fb_display[info->currcon].cmap.len)
-	fb_get_cmap(&fb_display[info->currcon].cmap, 1, s3trio_getcolreg, info);
-
-    info->currcon = con;
-    /* Install new colormap */
-    do_install_cmap(con,info);
-    return 0;
-}
-
-    /*
-     *  Update the `var' structure (called by fbcon.c)
-     */
-
-static int s3triofbcon_updatevar(int con, struct fb_info *info)
-{
-    /* Nothing */
-    return 0;
-}
-
-    /*
-     *  Blank the display.
-     */
-
-static int s3triofb_blank(int blank, struct fb_info *info)
-{
-    unsigned char x;
-
-    mem_out8(0x1, s3trio_base+0x1008000 + 0x03c4);
-    x = mem_in8(s3trio_base+0x1008000 + 0x03c5);
-    mem_out8((x & (~0x20)) | (blank << 5), s3trio_base+0x1008000 + 0x03c5);
-    return 0;	
-}
-
-    /*
-     *  Read a single color register and split it into
-     *  colors/transparent. Return != 0 for invalid regno.
-     */
-
-static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-                         u_int *transp, struct fb_info *info)
-{
-    if (regno > 255)
-	return 1;
-    *red = (palette[regno].red << 8) | palette[regno].red;
-    *green = (palette[regno].green << 8) | palette[regno].green;
-    *blue = (palette[regno].blue << 8) | palette[regno].blue;
-    *transp = 0;
-    return 0;
-}
-
-
-    /*
-     *  Set a single color register. Return != 0 for invalid regno.
-     */
-
-static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                            u_int transp, struct fb_info *info)
-{
-    if (regno > 255)
-	return 1;
-
-    red >>= 8;
-    green >>= 8;
-    blue >>= 8;
-    palette[regno].red = red;
-    palette[regno].green = green;
-    palette[regno].blue = blue;
-
-    mem_out8(regno,s3trio_base+0x1008000 + 0x3c8);
-    mem_out8((red & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9);
-    mem_out8((green & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9);
-    mem_out8((blue & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9);
-
-    return 0;
-}
-
-static void Trio_WaitQueue(u_short fifo) {
-
-	u_short status;
-
-        do
-        {
-		status = mem_in16(s3trio_base + 0x1000000 + 0x9AE8);
-	}  while (!(status & fifo));
-
-}
-
-static void Trio_WaitBlit(void) {
-
-	u_short status;
-
-        do
-        {
-		status = mem_in16(s3trio_base + 0x1000000 + 0x9AE8);
-	}  while (status & 0x200);
-
-}
-
-static void Trio_BitBLT(u_short curx, u_short cury, u_short destx,
-			u_short desty, u_short width, u_short height,
-			u_short mode) {
-
-	u_short blitcmd = 0xc011;
-
-	/* Set drawing direction */
-        /* -Y, X maj, -X (default) */
-
-	if (curx > destx)
-		blitcmd |= 0x0020;  /* Drawing direction +X */
-	else {
-		curx  += (width - 1);
-		destx += (width - 1);
-	}
-
-	if (cury > desty)
-		blitcmd |= 0x0080;  /* Drawing direction +Y */
-	else {
-		cury  += (height - 1);
-		desty += (height - 1);
-	}
-
-	Trio_WaitQueue(0x0400);
-
-	outw(0xa000,  0xBEE8);
-	outw(0x60 | mode,  0xBAE8);
-
-	outw(curx,  0x86E8);
-	outw(cury,  0x82E8);
-
-	outw(destx,  0x8EE8);
-	outw(desty,  0x8AE8);
-
-	outw(height - 1,  0xBEE8);
-	outw(width - 1,  0x96E8);
-
-	outw(blitcmd,  0x9AE8);
-
-}
-
-static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height,
-			  u_short mode, u_short color) {
-
-	u_short blitcmd = 0x40b1;
-
-	Trio_WaitQueue(0x0400);
-
-	outw(0xa000,  0xBEE8);
-	outw((0x20 | mode),  0xBAE8);
-	outw(0xe000,  0xBEE8);
-	outw(color,  0xA6E8);
-	outw(x,  0x86E8);
-	outw(y,  0x82E8);
-	outw((height - 1), 0xBEE8);
-	outw((width - 1), 0x96E8);
-	outw(blitcmd,  0x9AE8);
-
-}
-
-
-static void Trio_MoveCursor(u_short x, u_short y) {
-
-	mem_out8(0x39, s3trio_base + 0x1008000 + 0x3d4);
-	mem_out8(0xa0, s3trio_base + 0x1008000 + 0x3d5);
-
-	mem_out8(0x46, s3trio_base + 0x1008000 + 0x3d4);
-	mem_out8((x & 0x0700) >> 8, s3trio_base + 0x1008000 + 0x3d5);
-	mem_out8(0x47, s3trio_base + 0x1008000 + 0x3d4);
-	mem_out8(x & 0x00ff, s3trio_base + 0x1008000 + 0x3d5);
-
-	mem_out8(0x48, s3trio_base + 0x1008000 + 0x3d4);
-	mem_out8((y & 0x0700) >> 8, s3trio_base + 0x1008000 + 0x3d5);
-	mem_out8(0x49, s3trio_base + 0x1008000 + 0x3d4);
-	mem_out8(y & 0x00ff, s3trio_base + 0x1008000 + 0x3d5);
-
-}
-
-
-    /*
-     *  Text console acceleration
-     */
-
-#ifdef FBCON_HAS_CFB8
-static void fbcon_trio8_bmove(struct display *p, int sy, int sx, int dy,
-			      int dx, int height, int width)
-{
-    sx *= 8; dx *= 8; width *= 8;
-    Trio_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
-		 (u_short)(dy*fontheight(p)), (u_short)width,
-		 (u_short)(height*fontheight(p)), (u_short)S3_NEW);
-}
-
-static void fbcon_trio8_clear(struct vc_data *conp, struct display *p, int sy,
-			      int sx, int height, int width)
-{
-    unsigned char bg;
-
-    sx *= 8; width *= 8;
-    bg = attr_bgcol_ec(p,conp);
-    Trio_RectFill((u_short)sx,
-		   (u_short)(sy*fontheight(p)),
-		   (u_short)width,
-		   (u_short)(height*fontheight(p)),
-		   (u_short)S3_NEW,
-		   (u_short)bg);
-}
-
-static void fbcon_trio8_putc(struct vc_data *conp, struct display *p, int c,
-			     int yy, int xx)
-{
-    Trio_WaitBlit();
-    fbcon_cfb8_putc(conp, p, c, yy, xx);
-}
-
-static void fbcon_trio8_putcs(struct vc_data *conp, struct display *p,
-			      const unsigned short *s, int count, int yy, int xx)
-{
-    Trio_WaitBlit();
-    fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
-}
-
-static void fbcon_trio8_revc(struct display *p, int xx, int yy)
-{
-    Trio_WaitBlit();
-    fbcon_cfb8_revc(p, xx, yy);
-}
-
-static struct display_switch fbcon_trio8 = {
-   .setup =		fbcon_cfb8_setup,
-   .bmove =		fbcon_trio8_bmove,
-   .clear =		fbcon_trio8_clear,
-   .putc =		fbcon_trio8_putc,
-   .putcs =		fbcon_trio8_putcs,
-   .revc =		fbcon_trio8_revc,
-   .clear_margins =	fbcon_cfb8_clear_margins,
-   .fontwidthmask =	FONTWIDTH(8)
-};
-#endif
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 602db66..bffe2b9 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -49,7 +49,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 2e976ff..8726c36 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1695,9 +1695,6 @@
 #ifdef CONFIG_FB_ATY128_BACKLIGHT
 #define MAX_LEVEL 0xFF
 
-static struct backlight_properties aty128_bl_data;
-
-/* Call with fb_info->bl_mutex held */
 static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
 		int level)
 {
@@ -1705,6 +1702,7 @@
 	int atylevel;
 
 	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
 	atylevel = MAX_LEVEL -
 		(info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
 
@@ -1724,19 +1722,18 @@
 /* That one prevents proper CRT output with LCD off */
 #undef BACKLIGHT_DAC_OFF
 
-/* Call with fb_info->bl_mutex held */
-static int __aty128_bl_update_status(struct backlight_device *bd)
+static int aty128_bl_update_status(struct backlight_device *bd)
 {
 	struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
 	unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
 	int level;
 
-	if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK ||
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK ||
 	    !par->lcd_on)
 		level = 0;
 	else
-		level = bd->props->brightness;
+		level = bd->props.brightness;
 
 	reg |= LVDS_BL_MOD_EN | LVDS_BLON;
 	if (level > 0) {
@@ -1778,43 +1775,22 @@
 	return 0;
 }
 
-static int aty128_bl_update_status(struct backlight_device *bd)
-{
-	struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	int ret;
-
-	mutex_lock(&info->bl_mutex);
-	ret = __aty128_bl_update_status(bd);
-	mutex_unlock(&info->bl_mutex);
-
-	return ret;
-}
-
 static int aty128_bl_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties aty128_bl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops aty128_bl_data = {
 	.get_brightness	= aty128_bl_get_brightness,
 	.update_status	= aty128_bl_update_status,
-	.max_brightness	= (FB_BACKLIGHT_LEVELS - 1),
 };
 
 static void aty128_bl_set_power(struct fb_info *info, int power)
 {
-	mutex_lock(&info->bl_mutex);
-
 	if (info->bl_dev) {
-		down(&info->bl_dev->sem);
-		info->bl_dev->props->power = power;
-		__aty128_bl_update_status(info->bl_dev);
-		up(&info->bl_dev->sem);
+		info->bl_dev->props.power = power;
+		backlight_update_status(info->bl_dev);
 	}
-
-	mutex_unlock(&info->bl_mutex);
 }
 
 static void aty128_bl_init(struct aty128fb_par *par)
@@ -1841,25 +1817,15 @@
 		goto error;
 	}
 
-	mutex_lock(&info->bl_mutex);
 	info->bl_dev = bd;
 	fb_bl_default_curve(info, 0,
 		 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
 		219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
-	mutex_unlock(&info->bl_mutex);
 
-	down(&bd->sem);
-	bd->props->brightness = aty128_bl_data.max_brightness;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("aty128: Backlight initialized (%s)\n", name);
 
@@ -1869,31 +1835,10 @@
 	return;
 }
 
-static void aty128_bl_exit(struct aty128fb_par *par)
+static void aty128_bl_exit(struct backlight_device *bd)
 {
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-#endif
-
-	mutex_lock(&info->bl_mutex);
-	if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-		if (pmac_backlight == info->bl_dev)
-			pmac_backlight = NULL;
-#endif
-
-		backlight_device_unregister(info->bl_dev);
-		info->bl_dev = NULL;
-
-		printk("aty128: Backlight unloaded\n");
-	}
-	mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	backlight_device_unregister(bd);
+	printk("aty128: Backlight unloaded\n");
 }
 #endif /* CONFIG_FB_ATY128_BACKLIGHT */
 
@@ -2180,11 +2125,12 @@
 
 	par = info->par;
 
+	unregister_framebuffer(info);
+
 #ifdef CONFIG_FB_ATY128_BACKLIGHT
-	aty128_bl_exit(par);
+	aty128_bl_exit(info->bl_dev);
 #endif
 
-	unregister_framebuffer(info);
 #ifdef CONFIG_MTRR
 	if (par->mtrr.vram_valid)
 		mtrr_del(par->mtrr.vram, info->fix.smem_start,
@@ -2214,11 +2160,6 @@
 	if (par->lock_blank || par->asleep)
 		return 0;
 
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-	if (machine_is(powermac) && blank)
-		aty128_bl_set_power(fb, FB_BLANK_POWERDOWN);
-#endif
-
 	if (blank & FB_BLANK_VSYNC_SUSPEND)
 		state |= 2;
 	if (blank & FB_BLANK_HSYNC_SUSPEND)
@@ -2233,11 +2174,6 @@
 		aty128_set_lcd_enable(par, par->lcd_on && !blank);
 	}
 
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-	if (machine_is(powermac) && !blank)
-		aty128_bl_set_power(fb, FB_BLANK_UNBLANK);
-#endif
-
 	return 0;
 }
 
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index f2ebdd8..a7e0062 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2114,15 +2114,13 @@
 #ifdef CONFIG_FB_ATY_BACKLIGHT
 #define MAX_LEVEL 0xFF
 
-static struct backlight_properties aty_bl_data;
-
-/* Call with fb_info->bl_mutex held */
 static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
 {
 	struct fb_info *info = pci_get_drvdata(par->pdev);
 	int atylevel;
 
 	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
 	atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
 
 	if (atylevel < 0)
@@ -2133,18 +2131,17 @@
 	return atylevel;
 }
 
-/* Call with fb_info->bl_mutex held */
-static int __aty_bl_update_status(struct backlight_device *bd)
+static int aty_bl_update_status(struct backlight_device *bd)
 {
 	struct atyfb_par *par = class_get_devdata(&bd->class_dev);
 	unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
 	int level;
 
-	if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 	else
-		level = bd->props->brightness;
+		level = bd->props.brightness;
 
 	reg |= (BLMOD_EN | BIASMOD_EN);
 	if (level > 0) {
@@ -2159,45 +2156,16 @@
 	return 0;
 }
 
-static int aty_bl_update_status(struct backlight_device *bd)
-{
-	struct atyfb_par *par = class_get_devdata(&bd->class_dev);
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	int ret;
-
-	mutex_lock(&info->bl_mutex);
-	ret = __aty_bl_update_status(bd);
-	mutex_unlock(&info->bl_mutex);
-
-	return ret;
-}
-
 static int aty_bl_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties aty_bl_data = {
-	.owner	  = THIS_MODULE,
+static struct backlight_ops aty_bl_data = {
 	.get_brightness = aty_bl_get_brightness,
 	.update_status	= aty_bl_update_status,
-	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
-static void aty_bl_set_power(struct fb_info *info, int power)
-{
-	mutex_lock(&info->bl_mutex);
-
-	if (info->bl_dev) {
-		down(&info->bl_dev->sem);
-		info->bl_dev->props->power = power;
-		__aty_bl_update_status(info->bl_dev);
-		up(&info->bl_dev->sem);
-	}
-
-	mutex_unlock(&info->bl_mutex);
-}
-
 static void aty_bl_init(struct atyfb_par *par)
 {
 	struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -2218,25 +2186,15 @@
 		goto error;
 	}
 
-	mutex_lock(&info->bl_mutex);
 	info->bl_dev = bd;
 	fb_bl_default_curve(info, 0,
 		0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
 		0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
-	mutex_unlock(&info->bl_mutex);
 
-	down(&bd->sem);
-	bd->props->brightness = aty_bl_data.max_brightness;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("aty: Backlight initialized (%s)\n", name);
 
@@ -2246,30 +2204,10 @@
 	return;
 }
 
-static void aty_bl_exit(struct atyfb_par *par)
+static void aty_bl_exit(struct backlight_device *bd)
 {
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-#endif
-
-	mutex_lock(&info->bl_mutex);
-	if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-		if (pmac_backlight == info->bl_dev)
-			pmac_backlight = NULL;
-#endif
-
-		backlight_device_unregister(info->bl_dev);
-
-		printk("aty: Backlight unloaded\n");
-	}
-	mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	backlight_device_unregister(bd);
+	printk("aty: Backlight unloaded\n");
 }
 
 #endif /* CONFIG_FB_ATY_BACKLIGHT */
@@ -2566,7 +2504,7 @@
 	       info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, par->pll_limits.pll_max,
 	       par->pll_limits.mclk, par->pll_limits.xclk);
 
-#if defined(DEBUG) && defined(CONFIG_ATY_CT)
+#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
 	if (M64_HAS(INTEGRATED)) {
 		int i;
 		printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
@@ -2814,8 +2752,6 @@
 		return 0;
 
 #ifdef CONFIG_FB_ATY_BACKLIGHT
-	if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
-		aty_bl_set_power(info, FB_BLANK_POWERDOWN);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
 	if (par->lcd_table && blank > FB_BLANK_NORMAL &&
 	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2846,8 +2782,6 @@
 	aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
 
 #ifdef CONFIG_FB_ATY_BACKLIGHT
-	if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
-		aty_bl_set_power(info, FB_BLANK_UNBLANK);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
 	if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
 	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2957,8 +2891,6 @@
 static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
 			struct fb_info *info, unsigned long addr)
 {
-	extern int con_is_present(void);
-
 	struct atyfb_par *par = info->par;
 	struct pcidev_cookie *pcp;
 	char prop[128];
@@ -3728,13 +3660,13 @@
 	aty_set_crtc(par, &saved_crtc);
 	par->pll_ops->set_pll(info, &saved_pll);
 
+	unregister_framebuffer(info);
+
 #ifdef CONFIG_FB_ATY_BACKLIGHT
 	if (M64_HAS(MOBIL_BUS))
-		aty_bl_exit(par);
+		aty_bl_exit(info->bl_dev);
 #endif
 
-	unregister_framebuffer(info);
-
 #ifdef CONFIG_MTRR
 	if (par->mtrr_reg >= 0) {
 	    mtrr_del(par->mtrr_reg, 0, 0);
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
index 1490e5e..a8f60c3 100644
--- a/drivers/video/aty/mach64_accel.c
+++ b/drivers/video/aty/mach64_accel.c
@@ -3,7 +3,6 @@
  *  ATI Mach64 Hardware Acceleration
  */
 
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <video/mach64.h>
diff --git a/drivers/video/aty/mach64_gx.c b/drivers/video/aty/mach64_gx.c
index 2045639..10c988a 100644
--- a/drivers/video/aty/mach64_gx.c
+++ b/drivers/video/aty/mach64_gx.c
@@ -5,7 +5,6 @@
 
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/sched.h>
 
 #include <asm/io.h>
 
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 3abfd4a..0be25fa 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -19,8 +19,6 @@
 
 #define MAX_RADEON_LEVEL 0xFF
 
-static struct backlight_properties radeon_bl_data;
-
 struct radeon_bl_privdata {
 	struct radeonfb_info *rinfo;
 	uint8_t negative;
@@ -29,17 +27,13 @@
 static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
 		int level)
 {
-	struct fb_info *info = pdata->rinfo->info;
 	int rlevel;
 
-	mutex_lock(&info->bl_mutex);
-
 	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
 	rlevel = pdata->rinfo->info->bl_curve[level] *
 		 FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;
 
-	mutex_unlock(&info->bl_mutex);
-
 	if (rlevel < 0)
 		rlevel = 0;
 	else if (rlevel > MAX_RADEON_LEVEL)
@@ -65,11 +59,11 @@
 	 * backlight. This provides some greater power saving and the display
 	 * is useless without backlight anyway.
 	 */
-        if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+        if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 	else
-		level = bd->props->brightness;
+		level = bd->props.brightness;
 
 	del_timer_sync(&rinfo->lvds_timer);
 	radeon_engine_idle();
@@ -130,14 +124,12 @@
 
 static int radeon_bl_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties radeon_bl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops radeon_bl_data = {
 	.get_brightness = radeon_bl_get_brightness,
 	.update_status	= radeon_bl_update_status,
-	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
 void radeonfb_bl_init(struct radeonfb_info *rinfo)
@@ -188,25 +180,15 @@
 		machine_is_compatible("PowerBook6,5");
 #endif
 
-	mutex_lock(&rinfo->info->bl_mutex);
 	rinfo->info->bl_dev = bd;
 	fb_bl_default_curve(rinfo->info, 0,
 		 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
 		217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
-	mutex_unlock(&rinfo->info->bl_mutex);
 
-	down(&bd->sem);
-	bd->props->brightness = radeon_bl_data.max_brightness;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("radeonfb: Backlight initialized (%s)\n", name);
 
@@ -219,29 +201,16 @@
 
 void radeonfb_bl_exit(struct radeonfb_info *rinfo)
 {
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-#endif
+	struct backlight_device *bd = rinfo->info->bl_dev;
 
-	mutex_lock(&rinfo->info->bl_mutex);
-	if (rinfo->info->bl_dev) {
+	if (bd) {
 		struct radeon_bl_privdata *pdata;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-		if (pmac_backlight == rinfo->info->bl_dev)
-			pmac_backlight = NULL;
-#endif
-
-		pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev);
-		backlight_device_unregister(rinfo->info->bl_dev);
+		pdata = class_get_devdata(&bd->class_dev);
+		backlight_device_unregister(bd);
 		kfree(pdata);
 		rinfo->info->bl_dev = NULL;
 
 		printk("radeonfb: Backlight unloaded\n");
 	}
-	mutex_unlock(&rinfo->info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
 }
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 0ed577e..7e228ad 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2393,7 +2393,6 @@
         if (!rinfo)
                 return;
 
-	radeonfb_bl_exit(rinfo);
 	radeonfb_pm_exit(rinfo);
 
 	if (rinfo->mon1_EDID)
@@ -2420,6 +2419,8 @@
 
         unregister_framebuffer(info);
 
+        radeonfb_bl_exit(rinfo);
+
         iounmap(rinfo->mmio_base);
         iounmap(rinfo->fb_base);
  
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index e7c5b21..5084799 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -1,6 +1,5 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index ef5c16f..80a81ec 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -468,11 +468,10 @@
 			return -EINVAL;
 
 	/* Allocate new device private */
-	if (!(fbdev = kmalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) {
+	if (!(fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) {
 		print_err("fail to allocate device private record");
 		return -ENOMEM;
 	}
-	memset((void*)fbdev, 0, sizeof(struct au1100fb_device));
 
 	fbdev->panel = &known_lcd_panels[drv_info.panel_idx];
 
@@ -549,10 +548,9 @@
 	fbdev->info.fbops = &au1100fb_ops;
 	fbdev->info.fix = au1100fb_fix;
 
-	if (!(fbdev->info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL))) {
+	if (!(fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL))) {
 		return -ENOMEM;
 	}
-	memset(fbdev->info.pseudo_palette, 0, sizeof(u32) * 16);
 
 	if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
 		print_err("Fail to allocate colormap (%d entries)",
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 02f1529..47d15b5 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -19,11 +19,6 @@
 	  To have support for your specific LCD panel you will have to
 	  select the proper drivers which depend on this option.
 
-config BACKLIGHT_DEVICE
-	bool
-	depends on BACKLIGHT_CLASS_DEVICE
-	default y
-
 config LCD_CLASS_DEVICE
         tristate "Lowlevel LCD controls"
 	depends on BACKLIGHT_LCD_SUPPORT
@@ -37,14 +32,9 @@
 	  To have support for your specific LCD panel you will have to
 	  select the proper drivers which depend on this option.
 
-config LCD_DEVICE
-	bool
-	depends on LCD_CLASS_DEVICE
-	default y
-
 config BACKLIGHT_CORGI
 	tristate "Sharp Corgi Backlight Driver (SL Series)"
-	depends on BACKLIGHT_DEVICE && PXA_SHARPSL
+	depends on BACKLIGHT_CLASS_DEVICE && PXA_SHARPSL
 	default y
 	help
 	  If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
@@ -52,7 +42,7 @@
 
 config BACKLIGHT_LOCOMO
 	tristate "Sharp LOCOMO LCD/Backlight Driver"
-	depends on BACKLIGHT_DEVICE && SHARP_LOCOMO
+	depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO
 	default y
 	help
 	  If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to
@@ -60,9 +50,16 @@
 
 config BACKLIGHT_HP680
 	tristate "HP Jornada 680 Backlight Driver"
-	depends on BACKLIGHT_DEVICE && SH_HP6XX
+	depends on BACKLIGHT_CLASS_DEVICE && SH_HP6XX
 	default y
 	help
 	  If you have a HP Jornada 680, say y to enable the
 	  backlight driver.
 
+config BACKLIGHT_PROGEAR
+	tristate "Frontpath ProGear Backlight Driver"
+	depends on BACKLIGHT_CLASS_DEVICE && PCI && X86
+	default n
+	help
+	  If you have a Frontpath ProGear say Y to enable the
+	  backlight driver.
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 65e5553..0c3ce46f 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_BACKLIGHT_CORGI)	+= corgi_bl.o
 obj-$(CONFIG_BACKLIGHT_HP680)	+= hp680_bl.o
 obj-$(CONFIG_BACKLIGHT_LOCOMO)	+= locomolcd.o
+obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 9601bfe..c65e81f 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -14,6 +14,9 @@
 #include <linux/err.h>
 #include <linux/fb.h>
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
 
 #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
 			   defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
@@ -28,19 +31,18 @@
 	struct fb_event *evdata = data;
 
 	/* If we aren't interested in this event, skip it immediately ... */
-	if (event != FB_EVENT_BLANK)
+	if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK)
 		return 0;
 
 	bd = container_of(self, struct backlight_device, fb_notif);
-	down(&bd->sem);
-	if (bd->props)
-		if (!bd->props->check_fb ||
-		    bd->props->check_fb(evdata->info)) {
-			bd->props->fb_blank = *(int *)evdata->data;
-			if (likely(bd->props && bd->props->update_status))
-				bd->props->update_status(bd);
+	mutex_lock(&bd->ops_lock);
+	if (bd->ops)
+		if (!bd->ops->check_fb ||
+		    bd->ops->check_fb(evdata->info)) {
+			bd->props.fb_blank = *(int *)evdata->data;
+			backlight_update_status(bd);
 		}
-	up(&bd->sem);
+	mutex_unlock(&bd->ops_lock);
 	return 0;
 }
 
@@ -69,15 +71,9 @@
 
 static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
 {
-	int rc = -ENXIO;
 	struct backlight_device *bd = to_backlight_device(cdev);
 
-	down(&bd->sem);
-	if (likely(bd->props))
-		rc = sprintf(buf, "%d\n", bd->props->power);
-	up(&bd->sem);
-
-	return rc;
+	return sprintf(buf, "%d\n", bd->props.power);
 }
 
 static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count)
@@ -93,30 +89,23 @@
 	if (size != count)
 		return -EINVAL;
 
-	down(&bd->sem);
-	if (likely(bd->props)) {
+	mutex_lock(&bd->ops_lock);
+	if (bd->ops) {
 		pr_debug("backlight: set power to %d\n", power);
-		bd->props->power = power;
-		if (likely(bd->props->update_status))
-			bd->props->update_status(bd);
+		bd->props.power = power;
+		backlight_update_status(bd);
 		rc = count;
 	}
-	up(&bd->sem);
+	mutex_unlock(&bd->ops_lock);
 
 	return rc;
 }
 
 static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf)
 {
-	int rc = -ENXIO;
 	struct backlight_device *bd = to_backlight_device(cdev);
 
-	down(&bd->sem);
-	if (likely(bd->props))
-		rc = sprintf(buf, "%d\n", bd->props->brightness);
-	up(&bd->sem);
-
-	return rc;
+	return sprintf(buf, "%d\n", bd->props.brightness);
 }
 
 static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count)
@@ -132,35 +121,28 @@
 	if (size != count)
 		return -EINVAL;
 
-	down(&bd->sem);
-	if (likely(bd->props)) {
-		if (brightness > bd->props->max_brightness)
+	mutex_lock(&bd->ops_lock);
+	if (bd->ops) {
+		if (brightness > bd->props.max_brightness)
 			rc = -EINVAL;
 		else {
 			pr_debug("backlight: set brightness to %d\n",
 				 brightness);
-			bd->props->brightness = brightness;
-			if (likely(bd->props->update_status))
-				bd->props->update_status(bd);
+			bd->props.brightness = brightness;
+			backlight_update_status(bd);
 			rc = count;
 		}
 	}
-	up(&bd->sem);
+	mutex_unlock(&bd->ops_lock);
 
 	return rc;
 }
 
 static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf)
 {
-	int rc = -ENXIO;
 	struct backlight_device *bd = to_backlight_device(cdev);
 
-	down(&bd->sem);
-	if (likely(bd->props))
-		rc = sprintf(buf, "%d\n", bd->props->max_brightness);
-	up(&bd->sem);
-
-	return rc;
+	return sprintf(buf, "%d\n", bd->props.max_brightness);
 }
 
 static ssize_t backlight_show_actual_brightness(struct class_device *cdev,
@@ -169,10 +151,10 @@
 	int rc = -ENXIO;
 	struct backlight_device *bd = to_backlight_device(cdev);
 
-	down(&bd->sem);
-	if (likely(bd->props && bd->props->get_brightness))
-		rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd));
-	up(&bd->sem);
+	mutex_lock(&bd->ops_lock);
+	if (bd->ops && bd->ops->get_brightness)
+		rc = sprintf(buf, "%d\n", bd->ops->get_brightness(bd));
+	mutex_unlock(&bd->ops_lock);
 
 	return rc;
 }
@@ -211,7 +193,7 @@
  *   respective framebuffer device).
  * @devdata: an optional pointer to be stored in the class_device. The
  *   methods may retrieve it by using class_get_devdata(&bd->class_dev).
- * @bp: the backlight properties structure.
+ * @ops: the backlight operations structure.
  *
  * Creates and registers new backlight class_device. Returns either an
  * ERR_PTR() or a pointer to the newly allocated device.
@@ -219,39 +201,42 @@
 struct backlight_device *backlight_device_register(const char *name,
 	struct device *dev,
 	void *devdata,
-	struct backlight_properties *bp)
+	struct backlight_ops *ops)
 {
 	int i, rc;
 	struct backlight_device *new_bd;
 
 	pr_debug("backlight_device_alloc: name=%s\n", name);
 
-	new_bd = kmalloc(sizeof(struct backlight_device), GFP_KERNEL);
-	if (unlikely(!new_bd))
+	new_bd = kzalloc(sizeof(struct backlight_device), GFP_KERNEL);
+	if (!new_bd)
 		return ERR_PTR(-ENOMEM);
 
-	init_MUTEX(&new_bd->sem);
-	new_bd->props = bp;
-	memset(&new_bd->class_dev, 0, sizeof(new_bd->class_dev));
+	mutex_init(&new_bd->update_lock);
+	mutex_init(&new_bd->ops_lock);
+	new_bd->ops = ops;
 	new_bd->class_dev.class = &backlight_class;
 	new_bd->class_dev.dev = dev;
 	strlcpy(new_bd->class_dev.class_id, name, KOBJ_NAME_LEN);
 	class_set_devdata(&new_bd->class_dev, devdata);
 
 	rc = class_device_register(&new_bd->class_dev);
-	if (unlikely(rc)) {
-error:		kfree(new_bd);
+	if (rc) {
+		kfree(new_bd);
 		return ERR_PTR(rc);
 	}
 
 	rc = backlight_register_fb(new_bd);
-	if (unlikely(rc))
-		goto error;
+	if (rc) {
+		class_device_unregister(&new_bd->class_dev);
+		return ERR_PTR(rc);
+	}
+
 
 	for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++) {
 		rc = class_device_create_file(&new_bd->class_dev,
 					      &bl_class_device_attributes[i]);
-		if (unlikely(rc)) {
+		if (rc) {
 			while (--i >= 0)
 				class_device_remove_file(&new_bd->class_dev,
 							 &bl_class_device_attributes[i]);
@@ -261,6 +246,13 @@
 		}
 	}
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+	if (!pmac_backlight)
+		pmac_backlight = new_bd;
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+
 	return new_bd;
 }
 EXPORT_SYMBOL(backlight_device_register);
@@ -280,13 +272,20 @@
 
 	pr_debug("backlight_device_unregister: name=%s\n", bd->class_dev.class_id);
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+	if (pmac_backlight == bd)
+		pmac_backlight = NULL;
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+
 	for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++)
 		class_device_remove_file(&bd->class_dev,
 					 &bl_class_device_attributes[i]);
 
-	down(&bd->sem);
-	bd->props = NULL;
-	up(&bd->sem);
+	mutex_lock(&bd->ops_lock);
+	bd->ops = NULL;
+	mutex_unlock(&bd->ops_lock);
 
 	backlight_unregister_fb(bd);
 
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index fde1d95..ce00e18 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -22,7 +22,6 @@
 #include <asm/hardware/sharpsl_pm.h>
 
 static int corgibl_intensity;
-static DEFINE_MUTEX(bl_mutex);
 static struct backlight_properties corgibl_data;
 static struct backlight_device *corgi_backlight_device;
 static struct corgibl_machinfo *bl_machinfo;
@@ -34,20 +33,18 @@
 static int corgibl_send_intensity(struct backlight_device *bd)
 {
 	void (*corgi_kick_batt)(void);
-	int intensity = bd->props->brightness;
+	int intensity = bd->props.brightness;
 
-	if (bd->props->power != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK)
 		intensity = 0;
-	if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
 		intensity = 0;
 	if (corgibl_flags & CORGIBL_SUSPENDED)
 		intensity = 0;
 	if (corgibl_flags & CORGIBL_BATTLOW)
 		intensity &= bl_machinfo->limit_mask;
 
- 	mutex_lock(&bl_mutex);
 	bl_machinfo->set_bl_intensity(intensity);
-	mutex_unlock(&bl_mutex);
 
 	corgibl_intensity = intensity;
 
@@ -61,17 +58,21 @@
 }
 
 #ifdef CONFIG_PM
-static int corgibl_suspend(struct platform_device *dev, pm_message_t state)
+static int corgibl_suspend(struct platform_device *pdev, pm_message_t state)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	corgibl_flags |= CORGIBL_SUSPENDED;
-	corgibl_send_intensity(corgi_backlight_device);
+	backlight_update_status(bd);
 	return 0;
 }
 
-static int corgibl_resume(struct platform_device *dev)
+static int corgibl_resume(struct platform_device *pdev)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	corgibl_flags &= ~CORGIBL_SUSPENDED;
-	corgibl_send_intensity(corgi_backlight_device);
+	backlight_update_status(bd);
 	return 0;
 }
 #else
@@ -84,12 +85,6 @@
 	return corgibl_intensity;
 }
 
-static int corgibl_set_intensity(struct backlight_device *bd)
-{
-	corgibl_send_intensity(corgi_backlight_device);
-	return 0;
-}
-
 /*
  * Called when the battery is low to limit the backlight intensity.
  * If limit==0 clear any limit, otherwise limit the intensity
@@ -100,15 +95,14 @@
 		corgibl_flags |= CORGIBL_BATTLOW;
 	else
 		corgibl_flags &= ~CORGIBL_BATTLOW;
-	corgibl_send_intensity(corgi_backlight_device);
+	backlight_update_status(corgi_backlight_device);
 }
 EXPORT_SYMBOL(corgibl_limit_intensity);
 
 
-static struct backlight_properties corgibl_data = {
-	.owner          = THIS_MODULE,
+static struct backlight_ops corgibl_ops = {
 	.get_brightness = corgibl_get_intensity,
-	.update_status  = corgibl_set_intensity,
+	.update_status  = corgibl_send_intensity,
 };
 
 static int corgibl_probe(struct platform_device *pdev)
@@ -116,30 +110,34 @@
 	struct corgibl_machinfo *machinfo = pdev->dev.platform_data;
 
 	bl_machinfo = machinfo;
-	corgibl_data.max_brightness = machinfo->max_intensity;
 	if (!machinfo->limit_mask)
 		machinfo->limit_mask = -1;
 
 	corgi_backlight_device = backlight_device_register ("corgi-bl",
-		&pdev->dev, NULL, &corgibl_data);
+		&pdev->dev, NULL, &corgibl_ops);
 	if (IS_ERR (corgi_backlight_device))
 		return PTR_ERR (corgi_backlight_device);
 
-	corgibl_data.power = FB_BLANK_UNBLANK;
-	corgibl_data.brightness = machinfo->default_intensity;
-	corgibl_send_intensity(corgi_backlight_device);
+	platform_set_drvdata(pdev, corgi_backlight_device);
+
+	corgi_backlight_device->props.max_brightness = machinfo->max_intensity;
+	corgi_backlight_device->props.power = FB_BLANK_UNBLANK;
+	corgi_backlight_device->props.brightness = machinfo->default_intensity;
+	backlight_update_status(corgi_backlight_device);
 
 	printk("Corgi Backlight Driver Initialized.\n");
 	return 0;
 }
 
-static int corgibl_remove(struct platform_device *dev)
+static int corgibl_remove(struct platform_device *pdev)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	corgibl_data.power = 0;
 	corgibl_data.brightness = 0;
-	corgibl_send_intensity(corgi_backlight_device);
+	backlight_update_status(bd);
 
-	backlight_device_unregister(corgi_backlight_device);
+	backlight_device_unregister(bd);
 
 	printk("Corgi Backlight Driver Unloaded\n");
 	return 0;
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index c07d820..0899fcc 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -28,17 +28,16 @@
 static int hp680bl_suspended;
 static int current_intensity = 0;
 static DEFINE_SPINLOCK(bl_lock);
-static struct backlight_device *hp680_backlight_device;
 
 static void hp680bl_send_intensity(struct backlight_device *bd)
 {
 	unsigned long flags;
 	u16 v;
-	int intensity = bd->props->brightness;
+	int intensity = bd->props.brightness;
 
-	if (bd->props->power != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK)
 		intensity = 0;
-	if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
 		intensity = 0;
 	if (hp680bl_suspended)
 		intensity = 0;
@@ -66,17 +65,21 @@
 
 
 #ifdef CONFIG_PM
-static int hp680bl_suspend(struct platform_device *dev, pm_message_t state)
+static int hp680bl_suspend(struct platform_device *pdev, pm_message_t state)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	hp680bl_suspended = 1;
-	hp680bl_send_intensity(hp680_backlight_device);
+	hp680bl_send_intensity(bd);
 	return 0;
 }
 
-static int hp680bl_resume(struct platform_device *dev)
+static int hp680bl_resume(struct platform_device *pdev)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	hp680bl_suspended = 0;
-	hp680bl_send_intensity(hp680_backlight_device);
+	hp680bl_send_intensity(bd);
 	return 0;
 }
 #else
@@ -95,33 +98,38 @@
 	return current_intensity;
 }
 
-static struct backlight_properties hp680bl_data = {
-	.owner		= THIS_MODULE,
-	.max_brightness = HP680_MAX_INTENSITY,
+static struct backlight_ops hp680bl_ops = {
 	.get_brightness = hp680bl_get_intensity,
 	.update_status  = hp680bl_set_intensity,
 };
 
-static int __init hp680bl_probe(struct platform_device *dev)
+static int __init hp680bl_probe(struct platform_device *pdev)
 {
-	hp680_backlight_device = backlight_device_register ("hp680-bl",
-		&dev->dev, NULL, &hp680bl_data);
-	if (IS_ERR (hp680_backlight_device))
-		return PTR_ERR (hp680_backlight_device);
+	struct backlight_device *bd;
 
-	hp680_backlight_device->props->brightness = HP680_DEFAULT_INTENSITY;
-	hp680bl_send_intensity(hp680_backlight_device);
+	bd = backlight_device_register ("hp680-bl", &pdev->dev, NULL,
+		    &hp680bl_ops);
+	if (IS_ERR(bd))
+		return PTR_ERR(bd);
+
+	platform_set_drvdata(pdev, bd);
+
+	bd->props.max_brightness = HP680_MAX_INTENSITY;
+	bd->props.brightness = HP680_DEFAULT_INTENSITY;
+	hp680bl_send_intensity(bd);
 
 	return 0;
 }
 
-static int hp680bl_remove(struct platform_device *dev)
+static int hp680bl_remove(struct platform_device *pdev)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	hp680bl_data.brightness = 0;
 	hp680bl_data.power = 0;
-	hp680bl_send_intensity(hp680_backlight_device);
+	hp680bl_send_intensity(bd);
 
-	backlight_device_unregister(hp680_backlight_device);
+	backlight_device_unregister(bd);
 
 	return 0;
 }
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index f6e0416..6ef8f0a 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -31,11 +31,11 @@
 		return 0;
 
 	ld = container_of(self, struct lcd_device, fb_notif);
-	down(&ld->sem);
-	if (ld->props)
-		if (!ld->props->check_fb || ld->props->check_fb(evdata->info))
-			ld->props->set_power(ld, *(int *)evdata->data);
-	up(&ld->sem);
+	mutex_lock(&ld->ops_lock);
+	if (ld->ops)
+		if (!ld->ops->check_fb || ld->ops->check_fb(evdata->info))
+			ld->ops->set_power(ld, *(int *)evdata->data);
+	mutex_unlock(&ld->ops_lock);
 	return 0;
 }
 
@@ -66,12 +66,12 @@
 	int rc;
 	struct lcd_device *ld = to_lcd_device(cdev);
 
-	down(&ld->sem);
-	if (likely(ld->props && ld->props->get_power))
-		rc = sprintf(buf, "%d\n", ld->props->get_power(ld));
+	mutex_lock(&ld->ops_lock);
+	if (ld->ops && ld->ops->get_power)
+		rc = sprintf(buf, "%d\n", ld->ops->get_power(ld));
 	else
 		rc = -ENXIO;
-	up(&ld->sem);
+	mutex_unlock(&ld->ops_lock);
 
 	return rc;
 }
@@ -89,13 +89,13 @@
 	if (size != count)
 		return -EINVAL;
 
-	down(&ld->sem);
-	if (likely(ld->props && ld->props->set_power)) {
+	mutex_lock(&ld->ops_lock);
+	if (ld->ops && ld->ops->set_power) {
 		pr_debug("lcd: set power to %d\n", power);
-		ld->props->set_power(ld, power);
+		ld->ops->set_power(ld, power);
 		rc = count;
 	}
-	up(&ld->sem);
+	mutex_unlock(&ld->ops_lock);
 
 	return rc;
 }
@@ -105,10 +105,10 @@
 	int rc = -ENXIO;
 	struct lcd_device *ld = to_lcd_device(cdev);
 
-	down(&ld->sem);
-	if (likely(ld->props && ld->props->get_contrast))
-		rc = sprintf(buf, "%d\n", ld->props->get_contrast(ld));
-	up(&ld->sem);
+	mutex_lock(&ld->ops_lock);
+	if (ld->ops && ld->ops->get_contrast)
+		rc = sprintf(buf, "%d\n", ld->ops->get_contrast(ld));
+	mutex_unlock(&ld->ops_lock);
 
 	return rc;
 }
@@ -126,28 +126,22 @@
 	if (size != count)
 		return -EINVAL;
 
-	down(&ld->sem);
-	if (likely(ld->props && ld->props->set_contrast)) {
+	mutex_lock(&ld->ops_lock);
+	if (ld->ops && ld->ops->set_contrast) {
 		pr_debug("lcd: set contrast to %d\n", contrast);
-		ld->props->set_contrast(ld, contrast);
+		ld->ops->set_contrast(ld, contrast);
 		rc = count;
 	}
-	up(&ld->sem);
+	mutex_unlock(&ld->ops_lock);
 
 	return rc;
 }
 
 static ssize_t lcd_show_max_contrast(struct class_device *cdev, char *buf)
 {
-	int rc = -ENXIO;
 	struct lcd_device *ld = to_lcd_device(cdev);
 
-	down(&ld->sem);
-	if (likely(ld->props))
-		rc = sprintf(buf, "%d\n", ld->props->max_contrast);
-	up(&ld->sem);
-
-	return rc;
+	return sprintf(buf, "%d\n", ld->props.max_contrast);
 }
 
 static void lcd_class_release(struct class_device *dev)
@@ -180,45 +174,46 @@
  *   respective framebuffer device).
  * @devdata: an optional pointer to be stored in the class_device. The
  *   methods may retrieve it by using class_get_devdata(ld->class_dev).
- * @lp: the lcd properties structure.
+ * @ops: the lcd operations structure.
  *
  * Creates and registers a new lcd class_device. Returns either an ERR_PTR()
  * or a pointer to the newly allocated device.
  */
 struct lcd_device *lcd_device_register(const char *name, void *devdata,
-				       struct lcd_properties *lp)
+				       struct lcd_ops *ops)
 {
 	int i, rc;
 	struct lcd_device *new_ld;
 
 	pr_debug("lcd_device_register: name=%s\n", name);
 
-	new_ld = kmalloc(sizeof(struct lcd_device), GFP_KERNEL);
-	if (unlikely(!new_ld))
+	new_ld = kzalloc(sizeof(struct lcd_device), GFP_KERNEL);
+	if (!new_ld)
 		return ERR_PTR(-ENOMEM);
 
-	init_MUTEX(&new_ld->sem);
-	new_ld->props = lp;
-	memset(&new_ld->class_dev, 0, sizeof(new_ld->class_dev));
+	mutex_init(&new_ld->ops_lock);
+	mutex_init(&new_ld->update_lock);
+	new_ld->ops = ops;
 	new_ld->class_dev.class = &lcd_class;
 	strlcpy(new_ld->class_dev.class_id, name, KOBJ_NAME_LEN);
 	class_set_devdata(&new_ld->class_dev, devdata);
 
 	rc = class_device_register(&new_ld->class_dev);
-	if (unlikely(rc)) {
-error:		kfree(new_ld);
+	if (rc) {
+		kfree(new_ld);
 		return ERR_PTR(rc);
 	}
 
 	rc = lcd_register_fb(new_ld);
-
-	if (unlikely(rc))
-		goto error;
+	if (rc) {
+		class_device_unregister(&new_ld->class_dev);
+		return ERR_PTR(rc);
+	}
 
 	for (i = 0; i < ARRAY_SIZE(lcd_class_device_attributes); i++) {
 		rc = class_device_create_file(&new_ld->class_dev,
 					      &lcd_class_device_attributes[i]);
-		if (unlikely(rc)) {
+		if (rc) {
 			while (--i >= 0)
 				class_device_remove_file(&new_ld->class_dev,
 							 &lcd_class_device_attributes[i]);
@@ -251,9 +246,9 @@
 		class_device_remove_file(&ld->class_dev,
 					 &lcd_class_device_attributes[i]);
 
-	down(&ld->sem);
-	ld->props = NULL;
-	up(&ld->sem);
+	mutex_lock(&ld->ops_lock);
+	ld->ops = NULL;
+	mutex_unlock(&ld->ops_lock);
 	lcd_unregister_fb(ld);
 	class_device_unregister(&ld->class_dev);
 }
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index fc812d9..d131247 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -112,11 +112,11 @@
 
 static int locomolcd_set_intensity(struct backlight_device *bd)
 {
-	int intensity = bd->props->brightness;
+	int intensity = bd->props.brightness;
 
-	if (bd->props->power != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK)
 		intensity = 0;
-	if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
 		intensity = 0;
 	if (locomolcd_flags & LOCOMOLCD_SUSPENDED)
 		intensity = 0;
@@ -141,11 +141,9 @@
 	return current_intensity;
 }
 
-static struct backlight_properties locomobl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops locomobl_data = {
 	.get_brightness = locomolcd_get_intensity,
 	.update_status  = locomolcd_set_intensity,
-	.max_brightness = 4,
 };
 
 #ifdef CONFIG_PM
@@ -190,7 +188,8 @@
 		return PTR_ERR (locomolcd_bl_device);
 
 	/* Set up frontlight so that screen is readable */
-	locomobl_data.brightness = 2;
+	locomolcd_bl_device->props.max_brightness = 4,
+	locomolcd_bl_device->props.brightness = 2;
 	locomolcd_set_intensity(locomolcd_bl_device);
 
 	return 0;
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
new file mode 100644
index 0000000..7022693
--- /dev/null
+++ b/drivers/video/backlight/progear_bl.c
@@ -0,0 +1,153 @@
+/*
+ *  Backlight Driver for Frontpath ProGear HX1050+
+ *
+ *  Copyright (c) 2006 Marcin Juszkiewicz
+ *
+ *  Based on Progear LCD driver by M Schacht
+ *  <mschacht at alumni dot washington dot edu>
+ *
+ *  Based on Sharp's Corgi Backlight Driver
+ *  Based on Backlight Driver for HP Jornada 680
+ *
+ *  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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+
+#define PMU_LPCR               0xB0
+#define SB_MPS1                0x61
+#define HW_LEVEL_MAX           0x77
+#define HW_LEVEL_MIN           0x4f
+
+static struct pci_dev *pmu_dev = NULL;
+static struct pci_dev *sb_dev = NULL;
+
+static int progearbl_set_intensity(struct backlight_device *bd)
+{
+	int intensity = bd->props.brightness;
+
+	if (bd->props.power != FB_BLANK_UNBLANK)
+		intensity = 0;
+	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+		intensity = 0;
+
+	pci_write_config_byte(pmu_dev, PMU_LPCR, intensity + HW_LEVEL_MIN);
+
+	return 0;
+}
+
+static int progearbl_get_intensity(struct backlight_device *bd)
+{
+	u8 intensity;
+	pci_read_config_byte(pmu_dev, PMU_LPCR, &intensity);
+
+	return intensity - HW_LEVEL_MIN;
+}
+
+static struct backlight_ops progearbl_ops = {
+	.get_brightness = progearbl_get_intensity,
+	.update_status = progearbl_set_intensity,
+};
+
+static int progearbl_probe(struct platform_device *pdev)
+{
+	u8 temp;
+	struct backlight_device *progear_backlight_device;
+
+	pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, 0);
+	if (!pmu_dev) {
+		printk("ALI M7101 PMU not found.\n");
+		return -ENODEV;
+	}
+
+	sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 0);
+	if (!sb_dev) {
+		printk("ALI 1533 SB not found.\n");
+		pci_dev_put(pmu_dev);
+		return -ENODEV;
+	}
+
+	/*     Set SB_MPS1 to enable brightness control. */
+	pci_read_config_byte(sb_dev, SB_MPS1, &temp);
+	pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
+
+	progear_backlight_device = backlight_device_register("progear-bl",
+							     &pdev->dev, NULL,
+							     &progearbl_ops);
+	if (IS_ERR(progear_backlight_device))
+		return PTR_ERR(progear_backlight_device);
+
+	platform_set_drvdata(pdev, progear_backlight_device);
+
+	progear_backlight_device->props.power = FB_BLANK_UNBLANK;
+	progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
+	progear_backlight_device->props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
+	progearbl_set_intensity(progear_backlight_device);
+
+	return 0;
+}
+
+static int progearbl_remove(struct platform_device *pdev)
+{
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+	backlight_device_unregister(bd);
+
+	return 0;
+}
+
+static struct platform_driver progearbl_driver = {
+	.probe = progearbl_probe,
+	.remove = progearbl_remove,
+	.driver = {
+		   .name = "progear-bl",
+		   },
+};
+
+static struct platform_device *progearbl_device;
+
+static int __init progearbl_init(void)
+{
+	int ret = platform_driver_register(&progearbl_driver);
+
+	if (!ret) {
+		progearbl_device = platform_device_alloc("progear-bl", -1);
+		if (!progearbl_device)
+			return -ENOMEM;
+
+		ret = platform_device_add(progearbl_device);
+
+		if (ret) {
+			platform_device_put(progearbl_device);
+			platform_driver_unregister(&progearbl_driver);
+		}
+	}
+
+	return ret;
+}
+
+static void __exit progearbl_exit(void)
+{
+	pci_dev_put(pmu_dev);
+	pci_dev_put(sb_dev);
+
+	platform_device_unregister(progearbl_device);
+	platform_driver_unregister(&progearbl_driver);
+}
+
+module_init(progearbl_init);
+module_exit(progearbl_exit);
+
+MODULE_AUTHOR("Marcin Juszkiewicz <linux@hrw.one.pl>");
+MODULE_DESCRIPTION("ProGear Backlight Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 73cb426..af313bf1 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -145,26 +145,6 @@
 
 static int chipsfb_blank(int blank, struct fb_info *info)
 {
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-
-	if (pmac_backlight) {
-		/* used to disable backlight only for blank > 1, but it seems
-		 * useful at blank = 1 too (saves battery, extends backlight
-		 * life)
-	 	 */
-		down(&pmac_backlight->sem);
-		if (blank)
-			pmac_backlight->props->power = FB_BLANK_POWERDOWN;
-		else
-			pmac_backlight->props->power = FB_BLANK_UNBLANK;
-		pmac_backlight->props->update_status(pmac_backlight);
-		up(&pmac_backlight->sem);
-	}
-
-	mutex_unlock(&pmac_backlight_mutex);
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
 	return 1;	/* get fb_blank to set the colormap to all black */
 }
 
@@ -415,10 +395,8 @@
 	/* turn on the backlight */
 	mutex_lock(&pmac_backlight_mutex);
 	if (pmac_backlight) {
-		down(&pmac_backlight->sem);
-		pmac_backlight->props->power = FB_BLANK_UNBLANK;
-		pmac_backlight->props->update_status(pmac_backlight);
-		up(&pmac_backlight->sem);
+		pmac_backlight->props.power = FB_BLANK_UNBLANK;
+		backlight_update_status(pmac_backlight);
 	}
 	mutex_unlock(&pmac_backlight_mutex);
 #endif /* CONFIG_PMAC_BACKLIGHT */
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 31f476a..0429fd2 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -60,7 +60,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>	/* MSch: for IRQ probe */
@@ -2071,7 +2070,7 @@
 	y_diff = info->var.yres - var.yres;
 	if (x_diff < 0 || x_diff > virt_fw ||
 	    y_diff < 0 || y_diff > virt_fh) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
 		mode = fb_find_best_mode(&var, &info->modelist);
@@ -2234,6 +2233,8 @@
 static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
 				int blank)
 {
+	struct fb_event event;
+
 	if (blank) {
 		unsigned short charmask = vc->vc_hi_font_mask ?
 			0x1ff : 0xff;
@@ -2244,6 +2245,11 @@
 		fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
 		vc->vc_video_erase_char = oldc;
 	}
+
+
+	event.info = info;
+	event.data = &blank;
+	fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
 }
 
 static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
@@ -2975,7 +2981,7 @@
 	int i;
 	struct vc_data *vc;
 	struct fb_var_screeninfo var;
-	struct fb_videomode *mode;
+	const struct fb_videomode *mode;
 
 	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		if (registered_fb[con2fb_map[i]] != info)
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index b9386d1..71f24e0 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -48,7 +48,7 @@
     struct fb_bitfield green;
     struct fb_bitfield blue;
     struct fb_bitfield transp;
-    struct fb_videomode *mode;
+    const struct fb_videomode *mode;
 };
 
 struct fbcon_ops {
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index eb4d03f..124ecbe 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -27,7 +27,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 4a9bde2..91a2078 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -35,7 +35,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/console.h>
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 04c6d92..fd60dba 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -696,11 +696,10 @@
 		printk(KERN_ERR "can't get 2 addresses for control\n");
 		return -ENXIO;
 	}
-	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
 	if (p == 0)
 		return -ENXIO;
 	control_fb = p;	/* save it for cleanups */
-	memset(p, 0, sizeof(*p));
 
 	/* Map in frame buffer and registers */
 	p->fb_orig_base = fb_res.start;
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index aae6d9c..7a6eeda 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1539,16 +1539,21 @@
 	/*
 	 * Allow the CyberPro to accept PCI burst accesses
 	 */
-	val = cyber2000_grphr(EXT_BUS_CTL, cfb);
-	if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
-		printk(KERN_INFO "%s: enabling PCI bursts\n", cfb->fb.fix.id);
+	if (cfb->id == ID_CYBERPRO_2010) {
+		printk(KERN_INFO "%s: NOT enabling PCI bursts\n", cfb->fb.fix.id);
+	} else {
+		val = cyber2000_grphr(EXT_BUS_CTL, cfb);
+		if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
+			printk(KERN_INFO "%s: enabling PCI bursts\n",
+				cfb->fb.fix.id);
 
-		val |= EXT_BUS_CTL_PCIBURST_WRITE;
+			val |= EXT_BUS_CTL_PCIBURST_WRITE;
 
-		if (cfb->id == ID_CYBERPRO_5000)
-			val |= EXT_BUS_CTL_PCIBURST_READ;
+			if (cfb->id == ID_CYBERPRO_5000)
+				val |= EXT_BUS_CTL_PCIBURST_READ;
 
-		cyber2000_grphw(EXT_BUS_CTL, val, cfb);
+			cyber2000_grphw(EXT_BUS_CTL, val, cfb);
+		}
 	}
 
 	return 0;
diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c
deleted file mode 100644
index 0b8d5b1..0000000
--- a/drivers/video/cyberfb.c
+++ /dev/null
@@ -1,2295 +0,0 @@
-/*
-* linux/drivers/video/cyberfb.c -- CyberVision64 frame buffer device
-* $Id: cyberfb.c,v 1.6 1998/09/11 04:54:58 abair Exp $
-*
-*    Copyright (C) 1998 Alan Bair
-*
-* This file is based on two CyberVision64 frame buffer device drivers
-*
-* The second CyberVision64 frame buffer device (cvision.c cvision_core.c):
-*
-*   Copyright (c) 1997 Antonio Santos
-*
-* Released as a patch to 2.1.35, but never included in the source tree.
-* This is based on work from the NetBSD CyberVision64 frame buffer driver 
-* and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):
-* Permission to use the source of this driver was obtained from the
-* author Michael Teske by Alan Bair.
-*
-*   Copyright (c) 1995 Michael Teske
-*
-* The first CyberVision64 frame buffer device (cyberfb.c):
-*
-*    Copyright (C) 1996 Martin Apel
-*                       Geert Uytterhoeven
-*
-* Which is based on the Amiga frame buffer device (amifb.c):
-*
-*    Copyright (C) 1995 Geert Uytterhoeven
-*
-*
-* History:
-*   - 22 Dec 95: Original version by Martin Apel
-*   - 05 Jan 96: Geert: integration into the current source tree
-*   - 01 Aug 98: Alan: Merge in code from cvision.c and cvision_core.c
-* $Log: cyberfb.c,v $
-* Revision 1.6  1998/09/11 04:54:58  abair
-* Update for 2.1.120 change in include file location.
-* Clean up for public release.
-*
-* Revision 1.5  1998/09/03 04:27:13  abair
-* Move cv64_load_video_mode to cyber_set_video so a new video mode is install
-* with each change of the 'var' data.
-*
-* Revision 1.4  1998/09/01 00:31:17  abair
-* Put in a set of default 8,16,24 bpp modes and map cyber8,16 to them.
-* Update operations with 'par' to handle a more complete set of parameter
-* values for encode/decode process.
-*
-* Revision 1.3  1998/08/31 21:31:33  abair
-* Swap 800x490 for 640x480 video mode and more cleanup.
-* Abandon idea to resurrect "custom" mode setting via kernel opts,
-* instead work on making use of fbset program to do this.
-*
-* Revision 1.2  1998/08/31 06:17:08  abair
-* Make updates for changes in cyberfb.c released in 2.1.119
-* and do some cleanup of the code.
-*
-* Revision 1.1  1998/08/29 18:38:31  abair
-* Initial revision
-*
-* Revision 1.3  1998/08/17 06:21:53  abair
-* Remove more redundant code after merging in cvision_core.c
-* Set blanking by colormap to pale red to detect this vs trying to
-* use video blanking. More formating to Linux code style.
-*
-* Revision 1.2  1998/08/15 17:51:37  abair
-* Added cvision_core.c code from 2.1.35 patches.
-* Changed to compile correctly and switch to using initialization
-* code. Added debugging and dropping of duplicate code.
-*
-*
-*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file COPYING in the main directory of this archive
-* for more details.
-*/
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/zorro.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/amigahw.h>
-#include <asm/io.h>
-
-#include "cyberfb.h"
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-
-/*#define CYBERFBDEBUG*/
-#ifdef CYBERFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-static void cv64_dump(void);
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
-#define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
-
-struct cyberfb_par {
-	struct fb_var_screeninfo var;
-	__u32 type;
-	__u32 type_aux;
-	__u32 visual;
-	__u32 line_length;
-};
-
-static struct cyberfb_par current_par;
-
-static int current_par_valid = 0;
-
-static struct display disp;
-static struct fb_info fb_info;
-
-
-/*
- *    Frame Buffer Name
- */
-
-static char cyberfb_name[16] = "Cybervision";
-
-
-/*
- *    CyberVision Graphics Board
- */
-
-static unsigned char Cyber_colour_table [256][3];
-static unsigned long CyberSize;
-static volatile unsigned char *CyberBase;
-static volatile unsigned char *CyberMem;
-static volatile unsigned char *CyberRegs;
-static unsigned long CyberMem_phys;
-static unsigned long CyberRegs_phys;
-
-/*
- *    Predefined Video Modes
- */
-
-static struct {
-    const char *name;
-    struct fb_var_screeninfo var;
-} cyberfb_predefined[] __initdata = {
-	{ "640x480-8", {		/* Default 8 BPP mode (cyber8) */
-		640, 480, 640, 480, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
-		FB_VMODE_NONINTERLACED
-	}}, 
-	{ "640x480-16", {		/* Default 16 BPP mode (cyber16) */
-		640, 480, 640, 480, 0, 0, 16, 0,
-		{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
-		FB_VMODE_NONINTERLACED
-	}}, 
-	{ "640x480-24", {		/* Default 24 BPP mode */
-		640, 480, 640, 480, 0, 0, 24, 0,
-		{16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
-		FB_VMODE_NONINTERLACED
-	}}, 
-	{ "800x490-8", {		/* Cybervision 8 bpp */
-		/* NO Acceleration */
-		800, 490, 800, 490, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCEL_NONE, 33333, 80, 24, 23, 1, 56, 8,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED
-	}},
-/* I can't test these with my monitor, but I suspect they will
- * be OK, since Antonio Santos indicated he had tested them in
- * his system.
- */
-	{ "800x600-8", {		/* Cybervision 8 bpp */
-		800, 600, 800, 600, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 72, 2,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED
-	}},
-	{ "1024x768-8", {		/* Cybervision 8 bpp */
-		1024, 768, 1024, 768, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 224, 72, 60, 12, 168, 4,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED
-	}},
-	{ "1152x886-8", {		/* Cybervision 8 bpp */
-		1152, 886, 1152, 886, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 15873, 184, 40, 24, 1, 56, 16,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED
-	}},
-	{ "1280x1024-8", {	/* Cybervision 8 bpp */
-		1280, 1024, 1280, 1024, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 256, 48, 50, 12, 72, 4,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_INTERLACED
-	}}
-};
-
-#define NUM_TOTAL_MODES    ARRAY_SIZE(cyberfb_predefined)
-
-static int Cyberfb_inverse = 0;
-
-/*
- *    Some default modes
- */
-
-#define CYBER8_DEFMODE     (0)
-#define CYBER16_DEFMODE    (1)
-
-static struct fb_var_screeninfo cyberfb_default;
-static int cyberfb_usermode __initdata = 0;
-
-/*
- *    Interface used by the world
- */
-
-int cyberfb_setup(char *options);
-
-static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info);
-static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			    struct fb_info *info);
-static int cyberfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info);
-static int cyberfb_blank(int blank, struct fb_info *info);
-
-/*
- *    Interface to the low level console driver
- */
-
-int cyberfb_init(void);
-static int Cyberfb_switch(int con, struct fb_info *info);
-static int Cyberfb_updatevar(int con, struct fb_info *info);
-
-/*
- *    Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static struct display_switch fbcon_cyber8;
-#endif
-
-/*
- *    Accelerated Functions used by the low level console driver
- */
-
-static void Cyber_WaitQueue(u_short fifo);
-static void Cyber_WaitBlit(void);
-static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
-			 u_short desty, u_short width, u_short height,
-			 u_short mode);
-static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
-			   u_short mode, u_short color);
-#if 0
-static void Cyber_MoveCursor(u_short x, u_short y);
-#endif
-
-/*
- *   Hardware Specific Routines
- */
-
-static int Cyber_init(void);
-static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
-			    struct cyberfb_par *par);
-static int Cyber_decode_var(struct fb_var_screeninfo *var,
-			    struct cyberfb_par *par);
-static int Cyber_encode_var(struct fb_var_screeninfo *var,
-			    struct cyberfb_par *par);
-static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			   u_int *transp, struct fb_info *info);
-
-/*
- *    Internal routines
- */
-
-static void cyberfb_get_par(struct cyberfb_par *par);
-static void cyberfb_set_par(struct cyberfb_par *par);
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
-static void cyberfb_set_disp(int con, struct fb_info *info);
-static int get_video_mode(const char *name);
-
-/* For cvision_core.c */
-static unsigned short cv64_compute_clock(unsigned long);
-static int cv_has_4mb (volatile unsigned char *);
-static void cv64_board_init (void);
-static void cv64_load_video_mode (struct fb_var_screeninfo *);
-
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-
-/*
- *    Initialization
- *
- *    Set the default video mode for this chipset. If a video mode was
- *    specified on the command line, it will override the default mode.
- */
-
-static int Cyber_init(void)
-{
-	volatile unsigned char *regs = CyberRegs;
-	volatile unsigned long *CursorBase;
-	int i;
-	DPRINTK("ENTER\n");
-
-/* Init local cmap as greyscale levels */
-	for (i = 0; i < 256; i++) {
-		Cyber_colour_table [i][0] = i;
-		Cyber_colour_table [i][1] = i;
-		Cyber_colour_table [i][2] = i;
-	}
-
-/* Initialize the board and determine fbmem size */
-	cv64_board_init(); 
-#ifdef CYBERFBDEBUG
-	DPRINTK("Register state after initing board\n");
-	cv64_dump();
-#endif
-/* Clear framebuffer memory */
-	DPRINTK("Clear framebuffer memory\n");
-	memset ((char *)CyberMem, 0, CyberSize);
-
-/* Disable hardware cursor */
-	DPRINTK("Disable HW cursor\n");
-	wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2);
-	wb_64(regs, S3_CRTC_DATA, 0xa0);
-	wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE);
-	wb_64(regs, S3_CRTC_DATA, 0x00);
-	wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX);
-	wb_64(regs, S3_CRTC_DATA, 0x00);
-	wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY);
-	wb_64(regs, S3_CRTC_DATA, 0x00);
-
-/* Initialize hardware cursor */
-	DPRINTK("Init HW cursor\n");
-	CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
-	for (i=0; i < 8; i++)
-	{
-		*(CursorBase  +(i*4)) = 0xffffff00;
-		*(CursorBase+1+(i*4)) = 0xffff0000;
-		*(CursorBase+2+(i*4)) = 0xffff0000;
-		*(CursorBase+3+(i*4)) = 0xffff0000;
-	}
-	for (i=8; i < 64; i++)
-	{
-		*(CursorBase  +(i*4)) = 0xffff0000;
-		*(CursorBase+1+(i*4)) = 0xffff0000;
-		*(CursorBase+2+(i*4)) = 0xffff0000;
-		*(CursorBase+3+(i*4)) = 0xffff0000;
-	}
-
-	cyberfb_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
-	cyberfb_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
-
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    This function should fill in the `fix' structure based on the
- *    values in the `par' structure.
- */
-
-static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
-			    struct cyberfb_par *par)
-{
-	DPRINTK("ENTER\n");
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, cyberfb_name);
-	fix->smem_start = CyberMem_phys;
-	fix->smem_len = CyberSize;
-	fix->mmio_start = CyberRegs_phys;
-	fix->mmio_len = 0x10000;
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-	if (par->var.bits_per_pixel == 15 || par->var.bits_per_pixel == 16 ||
-	    par->var.bits_per_pixel == 24 || par->var.bits_per_pixel == 32) {
-		fix->visual = FB_VISUAL_DIRECTCOLOR;
-	} else {
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	}
-
-	fix->xpanstep = 0;
-	fix->ypanstep = 0;
-	fix->ywrapstep = 0;
-	fix->line_length = 0;
-	fix->accel = FB_ACCEL_S3_TRIO64;
-
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-
-/*
-*    Fill the `par' structure based on the values in `var'.
-*    TODO: Verify and adjust values, return -EINVAL if bad.
-*/
-
-static int Cyber_decode_var(struct fb_var_screeninfo *var,
-			    struct cyberfb_par *par)
-{
-	DPRINTK("ENTER\n");
-	par->var.xres = var->xres;
-	par->var.yres = var->yres;
-	par->var.xres_virtual = var->xres_virtual;
-	par->var.yres_virtual = var->yres_virtual;
-	par->var.xoffset = var->xoffset;
-	par->var.yoffset = var->yoffset;
-	par->var.bits_per_pixel = var->bits_per_pixel;
-	par->var.grayscale = var->grayscale;
-	par->var.red = var->red;
-	par->var.green = var->green;
-	par->var.blue = var->blue;
-	par->var.transp = var->transp;
-	par->var.nonstd = var->nonstd;
-	par->var.activate = var->activate;
-	par->var.height = var->height;
-	par->var.width = var->width;
-	if (var->accel_flags & FB_ACCELF_TEXT) {
-		par->var.accel_flags = FB_ACCELF_TEXT;
-	} else {
-		par->var.accel_flags = 0;
-	}
-	par->var.pixclock = var->pixclock;
-	par->var.left_margin = var->left_margin;
-	par->var.right_margin = var->right_margin;
-	par->var.upper_margin = var->upper_margin;
-	par->var.lower_margin = var->lower_margin;
-	par->var.hsync_len = var->hsync_len;
-	par->var.vsync_len = var->vsync_len;
-	par->var.sync = var->sync;
-	par->var.vmode = var->vmode;
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-/*
-*    Fill the `var' structure based on the values in `par' and maybe
-*    other values read out of the hardware.
-*/
-
-static int Cyber_encode_var(struct fb_var_screeninfo *var,
-			    struct cyberfb_par *par)
-{
-	DPRINTK("ENTER\n");
-	var->xres = par->var.xres;
-	var->yres = par->var.yres;
-	var->xres_virtual = par->var.xres_virtual;
-	var->yres_virtual = par->var.yres_virtual;
-	var->xoffset = par->var.xoffset;
-	var->yoffset = par->var.yoffset;
-
-	var->bits_per_pixel = par->var.bits_per_pixel;
-	var->grayscale = par->var.grayscale;
-
-	var->red = par->var.red;
-	var->green = par->var.green;
-	var->blue = par->var.blue;
-	var->transp = par->var.transp;
-
-	var->nonstd = par->var.nonstd;
-	var->activate = par->var.activate;
-
-	var->height = par->var.height;
-	var->width = par->var.width;
-
-	var->accel_flags = par->var.accel_flags;
-
-	var->pixclock = par->var.pixclock;
-	var->left_margin = par->var.left_margin;
-	var->right_margin = par->var.right_margin;
-	var->upper_margin = par->var.upper_margin;
-	var->lower_margin = par->var.lower_margin;
-	var->hsync_len = par->var.hsync_len;
-	var->vsync_len = par->var.vsync_len;
-	var->sync = par->var.sync;
-	var->vmode = par->var.vmode;
-	
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-
-/*
- *    Set a single color register. Return != 0 for invalid regno.
- */
-
-static int cyberfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info)
-{
-	volatile unsigned char *regs = CyberRegs;
-
-	/*DPRINTK("ENTER\n");*/
-	if (regno > 255) {
-		DPRINTK("EXIT - Register # > 255\n");
-		return (1);
-	}
-
-	wb_64(regs, 0x3c8, (unsigned char) regno);
-
- 	red >>= 10;
- 	green >>= 10;
- 	blue >>= 10;
-
-	Cyber_colour_table [regno][0] = red;
-	Cyber_colour_table [regno][1] = green;
-	Cyber_colour_table [regno][2] = blue;
-
-	wb_64(regs, 0x3c9, red);
-	wb_64(regs, 0x3c9, green);
-	wb_64(regs, 0x3c9, blue);
-
-	/*DPRINTK("EXIT\n");*/
-	return (0);
-}
-
-
-/*
-*    Read a single color register and split it into
-*    colors/transparent. Return != 0 for invalid regno.
-*/
-
-static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			   u_int *transp, struct fb_info *info)
-{
-	int t;
-
-	/*DPRINTK("ENTER\n");*/
-	if (regno > 255) {
-		DPRINTK("EXIT - Register # > 255\n");
-		return (1);
-	}
-	/* ARB This shifting & oring seems VERY strange */
- 	t	= Cyber_colour_table [regno][0];
- 	*red	= (t<<10) | (t<<4) | (t>>2);
- 	t	= Cyber_colour_table [regno][1];
- 	*green	= (t<<10) | (t<<4) | (t>>2);
- 	t	= Cyber_colour_table [regno][2];
- 	*blue	= (t<<10) | (t<<4) | (t>>2);
- 	*transp = 0;
-	/*DPRINTK("EXIT\n");*/
-	return (0);
-}
-
-
-/*
-*    (Un)Blank the screen
-*    blank: 1 = zero fb cmap
-*           0 = restore fb cmap from local cmap
-*/
-static int cyberfb_blank(int blank, struct fb_info *info)
-{
-	volatile unsigned char *regs = CyberRegs;
-	int i;
-
-	DPRINTK("ENTER\n");
-#if 0
-/* Blank by turning gfx off */
-	gfx_on_off (1, regs);
-#else
-	if (blank) {
-		for (i = 0; i < 256; i++) {
-			wb_64(regs, 0x3c8, (unsigned char) i);
-			/* ARB Pale red to detect this blanking method */
-			wb_64(regs, 0x3c9, 48); 
-			wb_64(regs, 0x3c9, 0);
-			wb_64(regs, 0x3c9, 0);
-		}
-	} else {
-		for (i = 0; i < 256; i++) {
-			wb_64(regs, 0x3c8, (unsigned char) i);
-			wb_64(regs, 0x3c9, Cyber_colour_table[i][0]);
-			wb_64(regs, 0x3c9, Cyber_colour_table[i][1]);
-			wb_64(regs, 0x3c9, Cyber_colour_table[i][2]);
-		}
-	}
-#endif
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/**************************************************************
- * We are waiting for "fifo" FIFO-slots empty
- */
-static void Cyber_WaitQueue (u_short fifo)
-{
-	unsigned short status;
-
-	DPRINTK("ENTER\n");
-	do {
-		status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
-	} while (status & fifo);
-	DPRINTK("EXIT\n");
-}
-
-/**************************************************************
- * We are waiting for Hardware (Graphics Engine) not busy
- */
-static void Cyber_WaitBlit (void)
-{
-	unsigned short status;
-
-	DPRINTK("ENTER\n");
-	do {
-		status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
-	} while (status & S3_HDW_BUSY);
-	DPRINTK("EXIT\n");
-}
-
-/**************************************************************
- * BitBLT - Through the Plane
- */
-static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
-			  u_short desty, u_short width, u_short height,
-			  u_short mode)
-{
-	volatile unsigned char *regs = CyberRegs;
-	u_short blitcmd = S3_BITBLT;
-
-	DPRINTK("ENTER\n");
-	/* Set drawing direction */
-	/* -Y, X maj, -X (default) */
-	if (curx > destx) {
-		blitcmd |= 0x0020;  /* Drawing direction +X */
-	} else {
-		curx  += (width - 1);
-		destx += (width - 1);
-	}
-
-	if (cury > desty) {
-		blitcmd |= 0x0080;  /* Drawing direction +Y */
-	} else {
-		cury  += (height - 1);
-		desty += (height - 1);
-	}
-
-	Cyber_WaitQueue (0x8000);
-
-	*((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
-	*((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
-
-	*((u_short volatile *)(regs + S3_CUR_X)) = curx;
-	*((u_short volatile *)(regs + S3_CUR_Y)) = cury;
-
-	*((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
-	*((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
-
-	*((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
-	*((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
-
-	*((u_short volatile *)(regs + S3_CMD)) = blitcmd;
-	DPRINTK("EXIT\n");
-}
-
-/**************************************************************
- * Rectangle Fill Solid
- */
-static void Cyber_RectFill (u_short x, u_short y, u_short width,
-			    u_short height, u_short mode, u_short color)
-{
-	volatile unsigned char *regs = CyberRegs;
-	u_short blitcmd = S3_FILLEDRECT;
-
-	DPRINTK("ENTER\n");
-	Cyber_WaitQueue (0x8000);
-
-	*((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
-	*((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
-
-	*((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
-	*((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
-
-	*((u_short volatile *)(regs + S3_CUR_X)) = x;
-	*((u_short volatile *)(regs + S3_CUR_Y)) = y;
-
-	*((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
-	*((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
-
-	*((u_short volatile *)(regs + S3_CMD)) = blitcmd;
-	DPRINTK("EXIT\n");
-}
-
-
-#if 0
-/**************************************************************
- * Move cursor to x, y
- */
-static void Cyber_MoveCursor (u_short x, u_short y)
-{
-	volatile unsigned char *regs = CyberRegs;
-	DPRINTK("ENTER\n");
-	*(regs + S3_CRTC_ADR)  = 0x39;
-	*(regs + S3_CRTC_DATA) = 0xa0;
-
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
-	*(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
-	*(regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
-
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
-	*(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
-	*(regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
-	DPRINTK("EXIT\n");
-}
-#endif
-
-
-/* -------------------- Generic routines ---------------------------------- */
-
-
-/*
- *    Fill the hardware's `par' structure.
- */
-
-static void cyberfb_get_par(struct cyberfb_par *par)
-{
-	DPRINTK("ENTER\n");
-	if (current_par_valid) {
-		*par = current_par;
-	} else {
-		Cyber_decode_var(&cyberfb_default, par);
-	}
-	DPRINTK("EXIT\n");
-}
-
-
-static void cyberfb_set_par(struct cyberfb_par *par)
-{
-	DPRINTK("ENTER\n");
-	current_par = *par;
-	current_par_valid = 1;
-	DPRINTK("EXIT\n");
-}
-
-
-static void cyber_set_video(struct fb_var_screeninfo *var)
-{
-
-	/* Load the video mode defined by the 'var' data */
-	cv64_load_video_mode (var);
-#ifdef CYBERFBDEBUG
-	DPRINTK("Register state after loading video mode\n");
-	cv64_dump();
-#endif
-}
-
-
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
-{
-	int err, activate;
-	struct cyberfb_par par;
-
-	DPRINTK("ENTER\n");
-	if ((err = Cyber_decode_var(var, &par))) {
-		DPRINTK("EXIT - decode_var failed\n");
-		return(err);
-	}
-	activate = var->activate;
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
-		cyberfb_set_par(&par);
-	Cyber_encode_var(var, &par);
-	var->activate = activate;
-
-	cyber_set_video(var);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-/*
- *    Get the Fixed Part of the Display
- */
-
-static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info)
-{
-	struct cyberfb_par par;
-	int error = 0;
-
-	DPRINTK("ENTER\n");
-	if (con == -1) {
-		cyberfb_get_par(&par);
-	} else {
-		error = Cyber_decode_var(&fb_display[con].var, &par);
-	}
-	DPRINTK("EXIT\n");
-	return(error ? error : Cyber_encode_fix(fix, &par));
-}
-
-
-/*
- *    Get the User Defined Part of the Display
- */
-
-static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	struct cyberfb_par par;
-	int error = 0;
-
-	DPRINTK("ENTER\n");
-	if (con == -1) {
-		cyberfb_get_par(&par);
-		error = Cyber_encode_var(var, &par);
-		disp.var = *var;   /* ++Andre: don't know if this is the right place */
-	} else {
-		*var = fb_display[con].var;
-	}
-
-	DPRINTK("EXIT\n");
-	return(error);
-}
-
-
-static void cyberfb_set_disp(int con, struct fb_info *info)
-{
-	struct fb_fix_screeninfo fix;
-	struct display *display;
-
-	DPRINTK("ENTER\n");
-	if (con >= 0)
-		display = &fb_display[con];
-	else
-		display = &disp;	/* used during initialization */
-
-	cyberfb_get_fix(&fix, con, info);
-	if (con == -1)
-		con = 0;
-	display->visual = fix.visual;
-	display->type = fix.type;
-	display->type_aux = fix.type_aux;
-	display->ypanstep = fix.ypanstep;
-	display->ywrapstep = fix.ywrapstep;
-	display->can_soft_blank = 1;
-	display->inverse = Cyberfb_inverse;
-	switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-	    case 8:
-		if (display->var.accel_flags & FB_ACCELF_TEXT) {
-		    display->dispsw = &fbcon_cyber8;
-#warning FIXME: We should reinit the graphics engine here
-		} else
-		    display->dispsw = &fbcon_cfb8;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	    case 16:
-		display->dispsw = &fbcon_cfb16;
-		break;
-#endif
-	    default:
-		display->dispsw = NULL;
-		break;
-	}
-	DPRINTK("EXIT\n");
-}
-
-
-/*
- *    Set the User Defined Part of the Display
- */
-
-static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
-
-	DPRINTK("ENTER\n");
-	if ((err = do_fb_set_var(var, con == info->currcon))) {
-		DPRINTK("EXIT - do_fb_set_var failed\n");
-		return(err);
-	}
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-		oldxres = fb_display[con].var.xres;
-		oldyres = fb_display[con].var.yres;
-		oldvxres = fb_display[con].var.xres_virtual;
-		oldvyres = fb_display[con].var.yres_virtual;
-		oldbpp = fb_display[con].var.bits_per_pixel;
-		oldaccel = fb_display[con].var.accel_flags;
-		fb_display[con].var = *var;
-		if (oldxres != var->xres || oldyres != var->yres ||
-		    oldvxres != var->xres_virtual ||
-		    oldvyres != var->yres_virtual ||
-		    oldbpp != var->bits_per_pixel ||
-		    oldaccel != var->accel_flags) {
-			cyberfb_set_disp(con, info);
-			(*fb_info.changevar)(con);
-			fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
-			do_install_cmap(con, info);
-		}
-	}
-	var->activate = 0;
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-
-/*
- *    Get the Colormap
- */
-
-static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			    struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	if (con == info->currcon) { /* current console? */
-		DPRINTK("EXIT - console is current console\n");
-		return(fb_get_cmap(cmap, kspc, Cyber_getcolreg, info));
-	} else if (fb_display[con].cmap.len) { /* non default colormap? */
-		DPRINTK("Use console cmap\n");
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	} else {
-		DPRINTK("Use default cmap\n");
-		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-			     cmap, kspc ? 0 : 2);
-	}
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-static struct fb_ops cyberfb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	cyberfb_get_fix,
-	.fb_get_var =	cyberfb_get_var,
-	.fb_set_var =	cyberfb_set_var,
-	.fb_get_cmap =	cyberfb_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_setcolreg =	cyberfb_setcolreg,
-	.fb_blank =	cyberfb_blank,
-};
-
-int __init cyberfb_setup(char *options)
-{
-	char *this_opt;
-	DPRINTK("ENTER\n");
-
-	fb_info.fontname[0] = '\0';
-
-	if (!options || !*options) {
-		DPRINTK("EXIT - no options\n");
-		return 0;
-	}
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strcmp(this_opt, "inverse")) {
-			Cyberfb_inverse = 1;
-			fb_invert_cmaps();
-		} else if (!strncmp(this_opt, "font:", 5)) {
-			strcpy(fb_info.fontname, this_opt+5);
-		} else if (!strcmp (this_opt, "cyber8")) {
-			cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
-			cyberfb_usermode = 1;
-		} else if (!strcmp (this_opt, "cyber16")) {
-			cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
-			cyberfb_usermode = 1;
-		} else get_video_mode(this_opt);
-	}
-
-	DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
-		cyberfb_default.xres,
-		cyberfb_default.yres,
-		cyberfb_default.bits_per_pixel);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-/*
- *    Initialization
- */
-
-int __init cyberfb_init(void)
-{
-	unsigned long board_addr, board_size;
-	struct cyberfb_par par;
-	struct zorro_dev *z = NULL;
-	DPRINTK("ENTER\n");
-
-	while ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64, z))) {
-	    board_addr = z->resource.start;
-	    board_size = z->resource.end-z->resource.start+1;
-	    CyberMem_phys = board_addr + 0x01400000;
-	    CyberRegs_phys = CyberMem_phys + 0x00c00000;
-	    if (!request_mem_region(CyberRegs_phys, 0x10000, "S3 Trio64"))
-		continue;
-	    if (!request_mem_region(CyberMem_phys, 0x400000, "RAM")) {
-		release_mem_region(CyberRegs_phys, 0x10000);
-		continue;
-	    }
-	    DPRINTK("board_addr=%08lx\n", board_addr);
-	    DPRINTK("board_size=%08lx\n", board_size);
-
-	    CyberBase = ioremap(board_addr, board_size);
-	    CyberRegs = CyberBase + 0x02000000;
-	    CyberMem = CyberBase + 0x01400000;
-	    DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
-		    CyberBase, (long unsigned int)CyberRegs, CyberMem);
-
-#ifdef CYBERFBDEBUG
-	    DPRINTK("Register state just after mapping memory\n");
-	    cv64_dump();
-#endif
-
-	    strcpy(fb_info.modename, cyberfb_name);
-	    fb_info.changevar = NULL;
-	    fb_info.fbops = &cyberfb_ops;
-	    fb_info.screen_base = (unsigned char *)CyberMem;
-	    fb_info.disp = &disp;
-	    fb_info.currcon = -1;
-	    fb_info.switch_con = &Cyberfb_switch;
-	    fb_info.updatevar = &Cyberfb_updatevar;
-
-	    Cyber_init();
-	    /* ++Andre: set cyberfb default mode */
-	    if (!cyberfb_usermode) {
-		    cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
-		    DPRINTK("Use default cyber8 mode\n");
-	    }
-	    Cyber_decode_var(&cyberfb_default, &par);
-	    Cyber_encode_var(&cyberfb_default, &par);
-
-	    do_fb_set_var(&cyberfb_default, 1);
-	    cyberfb_get_var(&fb_display[0].var, -1, &fb_info);
-	    cyberfb_set_disp(-1, &fb_info);
-	    do_install_cmap(0, &fb_info);
-
-	    if (register_framebuffer(&fb_info) < 0) {
-		    DPRINTK("EXIT - register_framebuffer failed\n");
-			if (CyberBase)
-				iounmap(CyberBase);
-		    release_mem_region(CyberMem_phys, 0x400000);
-		    release_mem_region(CyberRegs_phys, 0x10000);
-		    return -EINVAL;
-	    }
-
-	    printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
-		   fb_info.node, fb_info.modename, CyberSize>>10);
-
-	    /* TODO: This driver cannot be unloaded yet */
-	    DPRINTK("EXIT\n");
-	    return 0;
-	}
-	return -ENXIO;
-}
-
-
-static int Cyberfb_switch(int con, struct fb_info *info)
-{
-        DPRINTK("ENTER\n");
-	/* Do we have to save the colormap? */
-	if (fb_display[info->currcon].cmap.len) {
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1, Cyber_getcolreg,
-			    info);
-	}
-
-	do_fb_set_var(&fb_display[con].var, 1);
-	info->currcon = con;
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-
-/*
- *    Update the `var' structure (called by fbcon.c)
- *
- *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
- *    Since it's called by a kernel driver, no range checking is done.
- */
-
-static int Cyberfb_updatevar(int con, struct fb_info *info)
-{
-	DPRINTK("Enter - Exit\n");
-	return(0);
-}
-
-
-/*
- *    Get a Video Mode
- */
-
-static int __init get_video_mode(const char *name)
-{
-	int i;
-
-	DPRINTK("ENTER\n");
-	for (i = 0; i < NUM_TOTAL_MODES; i++) {
-		if (!strcmp(name, cyberfb_predefined[i].name)) {
-			cyberfb_default = cyberfb_predefined[i].var;
-			cyberfb_usermode = 1;
-			DPRINTK("EXIT - Matched predefined mode\n");
-			return(i);
-		}
-	}
-	return(0);
-}
-
-
-/*
- *    Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy,
-			       int dx, int height, int width)
-{
-	DPRINTK("ENTER\n");
-	sx *= 8; dx *= 8; width *= 8;
-	Cyber_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
-		     (u_short)(dy*fontheight(p)), (u_short)width,
-		     (u_short)(height*fontheight(p)), (u_short)S3_NEW);
-	DPRINTK("EXIT\n");
-}
-
-static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
-			       int sx, int height, int width)
-{
-	unsigned char bg;
-
-	DPRINTK("ENTER\n");
-	sx *= 8; width *= 8;
-	bg = attr_bgcol_ec(p,conp);
-	Cyber_RectFill((u_short)sx,
-		       (u_short)(sy*fontheight(p)),
-		       (u_short)width,
-		       (u_short)(height*fontheight(p)),
-		       (u_short)S3_NEW,
-		       (u_short)bg);
-	DPRINTK("EXIT\n");
-}
-
-static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c,
-			      int yy, int xx)
-{
-	DPRINTK("ENTER\n");
-	Cyber_WaitBlit();
-	fbcon_cfb8_putc(conp, p, c, yy, xx);
-	DPRINTK("EXIT\n");
-}
-
-static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p,
-			       const unsigned short *s, int count,
-			       int yy, int xx)
-{
-	DPRINTK("ENTER\n");
-	Cyber_WaitBlit();
-	fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
-	DPRINTK("EXIT\n");
-}
-
-static void fbcon_cyber8_revc(struct display *p, int xx, int yy)
-{
-	DPRINTK("ENTER\n");
-	Cyber_WaitBlit();
-	fbcon_cfb8_revc(p, xx, yy);
-	DPRINTK("EXIT\n");
-}
-
-static struct display_switch fbcon_cyber8 = {
-	.setup =	fbcon_cfb8_setup,
-	.bmove =	fbcon_cyber8_bmove,
-	.clear =	fbcon_cyber8_clear,
-	.putc =		fbcon_cyber8_putc,
-	.putcs =	fbcon_cyber8_putcs,
-	.revc =		fbcon_cyber8_revc,
-	.clear_margins =fbcon_cfb8_clear_margins,
-	.fontwidthmask =FONTWIDTH(8)
-};
-#endif
-
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return cyberfb_init();
-}
-#endif /* MODULE */
-
-/*
- *
- * Low level initialization routines for the CyberVision64 graphics card
- *
- * Most of the following code is from cvision_core.c
- *
- */
-
-#define MAXPIXELCLOCK 135000000 /* safety */
-
-#ifdef CV_AGGRESSIVE_TIMING
-long cv64_memclk = 55000000;
-#else
-long cv64_memclk = 50000000;
-#endif
-
-/*********************/
-
-static unsigned char clocks[]={
-  0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
-  0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
-  0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
-  0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
-  0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
-  0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
-  0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
-  0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
-  0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
-  0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
-  0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
-  0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
-  0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
-  0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
-  0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
-  0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
-  0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
-  0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
-  0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
-  0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
-  0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
-  0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
-  0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
-  0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
-  0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
-  0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
-  0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
-  0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
-  0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
-  0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
-  0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
-  0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
-  0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
-  0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
-  0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
-  0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
-  0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
-  0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
-  0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
-  0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
-  0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
-  0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
-  0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
-  0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
-  0x13, 0x1,  0x13, 0x1,  0x7d, 0x27, 0x4c, 0x9,
-  0x37, 0x22, 0x5b, 0xb,  0x71, 0x26, 0x5c, 0xb,
-  0x6b, 0xd,  0x47, 0x23, 0x14, 0x1,  0x4f, 0x9,
-  0x23, 0x3,  0x75, 0x26, 0x7d, 0xf,  0x1c, 0x2,
-  0x51, 0x9,  0x59, 0x24, 0x61, 0xb,  0x69, 0x25,
-  0x79, 0x26, 0x34, 0x5,  0x1d, 0x2,  0x6b, 0x25,
-  0x54, 0x9,  0x35, 0x5,  0x45, 0x7,  0x6d, 0x25,
-  0x7d, 0x26, 0x16, 0x1,  0x7f, 0x26, 0x77, 0xd,
-  0x4f, 0x23, 0x78, 0xd,  0x2f, 0x21, 0x27, 0x3,
-  0x1f, 0x2,  0x59, 0x9,  0x6a, 0xb,  0x73, 0x25,
-  0x6b, 0xb,  0x63, 0x24, 0x5b, 0x9,  0x20, 0x2,
-  0x7e, 0xd,  0x4b, 0x7,  0x65, 0x24, 0x43, 0x22,
-  0x18, 0x1,  0x6f, 0xb,  0x5e, 0x9,  0x70, 0xb,
-  0x2a, 0x3,  0x33, 0x4,  0x45, 0x6,  0x60, 0x9,
-  0x7b, 0xc,  0x19, 0x1,  0x19, 0x1,  0x7d, 0xc,
-  0x74, 0xb,  0x50, 0x7,  0x75, 0xb,  0x63, 0x9,
-  0x51, 0x7,  0x23, 0x2,  0x3f, 0x5,  0x1a, 0x1,
-  0x65, 0x9,  0x2d, 0x3,  0x40, 0x5,  0x0,  0x0,
-};
-
-/* Console colors */
-unsigned char cvconscolors[16][3] = {	/* background, foreground, hilite */
-  /*  R     G     B  */
-  {0x30, 0x30, 0x30},
-  {0x00, 0x00, 0x00},
-  {0x80, 0x00, 0x00},
-  {0x00, 0x80, 0x00},
-  {0x00, 0x00, 0x80},
-  {0x80, 0x80, 0x00},
-  {0x00, 0x80, 0x80},
-  {0x80, 0x00, 0x80},
-  {0xff, 0xff, 0xff},
-  {0x40, 0x40, 0x40},
-  {0xff, 0x00, 0x00},
-  {0x00, 0xff, 0x00},
-  {0x00, 0x00, 0xff},
-  {0xff, 0xff, 0x00},
-  {0x00, 0xff, 0xff},
-  {0x00, 0x00, 0xff}
-};
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-/* Read Attribute Controller Register=idx */
-inline unsigned char RAttr (volatile unsigned char *regs, short idx)
-{
-	wb_64 (regs, ACT_ADDRESS_W, idx);
-	mb();
-	udelay(100);
-	return (rb_64(regs, ACT_ADDRESS_R));
-}
-
-/* Read Sequencer Register=idx */
-inline unsigned char RSeq (volatile unsigned char *regs, short idx)
-{
-	wb_64 (regs, SEQ_ADDRESS, idx);
-	mb();
-	return (rb_64(regs, SEQ_ADDRESS_R));
-}
-
-/* Read CRT Controller Register=idx */
-inline unsigned char RCrt (volatile unsigned char *regs, short idx)
-{
-	wb_64 (regs, CRT_ADDRESS, idx);
-	mb();
-	return (rb_64(regs, CRT_ADDRESS_R));
-}
-
-/* Read Graphics Controller Register=idx */
-inline unsigned char RGfx (volatile unsigned char *regs, short idx)
-{
-	wb_64 (regs, GCT_ADDRESS, idx);
-	mb();
-	return (rb_64(regs, GCT_ADDRESS_R));
-}
-
-/*
- * Special wakeup/passthrough registers on graphics boards
- */
-
-inline void cv64_write_port (unsigned short bits,
-			     volatile unsigned char *base)
-{
-	volatile unsigned char *addr;
-	static unsigned char cvportbits = 0; /* Mirror port bits here */
-	DPRINTK("ENTER\n");
-
-	addr = base + 0x40001;
-	if (bits & 0x8000) {
-		cvportbits |= bits & 0xff; /* Set bits */
-		DPRINTK("Set bits: %04x\n", bits);
-	} else {
-		bits = bits & 0xff;
-		bits = (~bits) & 0xff;
-		cvportbits &= bits; /* Clear bits */
-		DPRINTK("Clear bits: %04x\n", bits);
-	}
-
-	*addr = cvportbits;
-	DPRINTK("EXIT\n");
-}
-
-/*
- * Monitor switch on CyberVision board
- *
- *  toggle:
- *    0 = CyberVision Signal
- *    1 = Amiga Signal
- *  board = board addr
- *
- */
-inline void cvscreen (int toggle, volatile unsigned char *board)
-{
-	DPRINTK("ENTER\n");
-	if (toggle == 1) {
-		DPRINTK("Show Amiga video\n");
-		cv64_write_port (0x10, board);
-	} else {
-		DPRINTK("Show CyberVision video\n");
-		cv64_write_port (0x8010, board);
-	}
-	DPRINTK("EXIT\n");
-}
-
-/* Control screen display */
-/* toggle: 0 = on, 1 = off */
-/* board = registerbase */
-inline void gfx_on_off(int toggle, volatile unsigned char *regs)
-{
-	int r;
-	DPRINTK("ENTER\n");
-	
-	toggle &= 0x1;
-	toggle = toggle << 5;
-	DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
-	
-	r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE);
-	r &= 0xdf;	/* Set bit 5 to 0 */
-	
-	WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
-	DPRINTK("EXIT\n");
-}
-
-/*
- * Computes M, N, and R values from
- * given input frequency. It uses a table of
- * precomputed values, to keep CPU time low.
- *
- * The return value consist of:
- * lower byte:  Bits 4-0: N Divider Value
- *	        Bits 5-6: R Value          for e.g. SR10 or SR12
- * higher byte: Bits 0-6: M divider value  for e.g. SR11 or SR13
- */
-static unsigned short cv64_compute_clock(unsigned long freq)
-{
-	static unsigned char *mnr, *save;	/* M, N + R vals */
-	unsigned long work_freq, r;
-	unsigned short erg;
-	long diff, d2;
-
-	DPRINTK("ENTER\n");
-	if (freq < 12500000 || freq > MAXPIXELCLOCK) {
-		printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
-		       freq);
-		freq = 25000000;
-	}
-	DPRINTK("Freq = %ld\n", freq);
-	mnr = clocks;	/* there the vals are stored */
-	d2 = 0x7fffffff;
-
-	while (*mnr) {	/* mnr vals are 0-terminated */
-		work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
-
-		r = (mnr[1] >> 5) & 0x03;
-		if (r != 0) {
-			work_freq = work_freq >> r;	/* r is the freq divider */
-		}
-
-		work_freq *= 0x3E8;	/* 2nd part of OSC */
-
-		diff = abs(freq - work_freq);
-
-		if (d2 >= diff) {
-			d2 = diff;
-			/* In save are the vals for minimal diff */
-			save = mnr;
-		}
-		mnr += 2;
-	}
-	erg = *((unsigned short *)save);
-
-	DPRINTK("EXIT\n");
-	return (erg);
-}
-
-static int cv_has_4mb (volatile unsigned char *fb)
-{
-	volatile unsigned long *tr, *tw;
-	DPRINTK("ENTER\n");
-
-	/* write patterns in memory and test if they can be read */
-	tw = (volatile unsigned long *) fb;
-	tr = (volatile unsigned long *) (fb + 0x02000000);
-
-	*tw = 0x87654321;
-	
-	if (*tr != 0x87654321) {
-		DPRINTK("EXIT - <4MB\n");
-		return (0);
-	}
-
-	/* upper memory region */
-	tw = (volatile unsigned long *) (fb + 0x00200000);
-	tr = (volatile unsigned long *) (fb + 0x02200000);
-
-	*tw = 0x87654321;
-
-	if (*tr != 0x87654321) {
-		DPRINTK("EXIT - <4MB\n");
-		return (0);
-	}
-
-	*tw = 0xAAAAAAAA;
-
-	if (*tr != 0xAAAAAAAA) {
-		DPRINTK("EXIT - <4MB\n");
-		return (0);
-	}
-
-	*tw = 0x55555555;
-
-	if (*tr != 0x55555555) {
-		DPRINTK("EXIT - <4MB\n");
-		return (0);
-	}
-
-	DPRINTK("EXIT\n");
-	return (1);
-}
-
-static void cv64_board_init (void)
-{
-	volatile unsigned char *regs = CyberRegs;
-	int i;
-	unsigned int clockpar;
-	unsigned char test;
-	
-	DPRINTK("ENTER\n");
-
-	/*
-	 * Special CyberVision 64 board operations
-	 */
-	/* Reset board */
-	for (i = 0; i < 6; i++) {
-		cv64_write_port (0xff, CyberBase);
-	}
-	/* Return to operational mode */
-	cv64_write_port (0x8004, CyberBase);
-	
-	/*
-	 * Generic (?) S3 chip wakeup
-	 */
-	/* Disable I/O & memory decoders, video in setup mode */
-	wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
-	/* Video responds to cmds, addrs & data */
-	wb_64 (regs, SREG_OPTION_SELECT, 0x1);
-	/* Enable I/O & memory decoders, video in operational mode */
-	wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
-	/* VGA color emulation, enable cpu access to display mem */ 
-	wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03);
-	/* Unlock S3 VGA regs */
-	WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48); 
-	/* Unlock system control & extension registers */
-	WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
-/* GRF - Enable interrupts */
-	/* Enable enhanced regs access, Ready cntl 0 wait states */
-	test = RCrt (regs, CRT_ID_SYSTEM_CONFIG);
-	test = test | 0x01;		/* enable enhanced register access */
-	test = test & 0xEF;		/* clear bit 4, 0 wait state */
-	WCrt (regs, CRT_ID_SYSTEM_CONFIG, test);
-	/*
-	 * bit 0=1: Enable enhaced mode functions
-	 * bit 2=0: Enhanced mode 8+ bits/pixel
-	 * bit 4=1: Enable linear addressing
-	 * bit 5=1: Enable MMIO
-	 */
-	wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
-	/*
-	 * bit 0=1: Color emulation
-	 * bit 1=1: Enable CPU access to display memory
-	 * bit 5=1: Select high 64K memory page
-	 */
-/* GRF - 0xE3 */
-	wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
-	
-	/* Cpu base addr */
-	WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
-	
-	/* Reset. This does nothing on Trio, but standard VGA practice */
-	/* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
-	/* Character clocks 8 dots wide */
-	WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
-	/* Enable cpu write to all color planes */
-	WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
-	/* Font table in 1st 8k of plane 2, font A=B disables swtich */
-	WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
-	/* Allow mem access to 256kb */
-	WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2);
-	/* Unlock S3 extensions to VGA Sequencer regs */
-	WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
-	
-	/* Enable 4MB fast page mode */
-	test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL);
-	test = test | 1 << 6;
-	WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test);
-	
-	/* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
-	WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
-
-	/* Clear immediate clock load bit */
-	test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
-	test = test & 0xDF;
-	/* If > 55MHz, enable 2 cycle memory write */
-	if (cv64_memclk >= 55000000) {
-		test |= 0x80;
-	}
-	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
-
-	/* Set MCLK value */
-	clockpar = cv64_compute_clock (cv64_memclk);
-	test = (clockpar & 0xFF00) >> 8;
-	WSeq (regs, SEQ_ID_MCLK_HI, test);
-	test = clockpar & 0xFF;
-	WSeq (regs, SEQ_ID_MCLK_LO, test);
-
-	/* Chip rev specific: Not in my Trio manual!!! */
-	if (RCrt (regs, CRT_ID_REVISION) == 0x10)
-		WSeq (regs, SEQ_ID_MORE_MAGIC, test);
-
-	/* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
-
-	/* Set DCLK value */
-	WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
-	WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
-
-	/* Load DCLK (and MCLK?) immediately */
-	test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
-	test = test | 0x22;
-	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
-
-	/* Enable loading of DCLK */
-	test = rb_64(regs, GREG_MISC_OUTPUT_R);
-	test = test | 0x0C;
-	wb_64 (regs, GREG_MISC_OUTPUT_W, test);
-
-	/* Turn off immediate xCLK load */
-	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
-
-	/* Horizontal character clock counts */
-	/* 8 LSB of 9 bits = total line - 5 */
-	WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F);
-	/* Active display line */
-	WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
-	/* Blank assertion start */
-	WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50);
-	/* Blank assertion end */
-	WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82);
-	/* HSYNC assertion start */
-	WCrt (regs, CRT_ID_START_HOR_RETR, 0x54);
-	/* HSYNC assertion end */
-	WCrt (regs, CRT_ID_END_HOR_RETR, 0x80);
-	WCrt (regs, CRT_ID_VER_TOTAL, 0xBF);
-	WCrt (regs, CRT_ID_OVERFLOW, 0x1F);
-	WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
-	WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40);
-	WCrt (regs, CRT_ID_CURSOR_START, 0x00);
-	WCrt (regs, CRT_ID_CURSOR_END, 0x00);
-	WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
-	WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
-	WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
-	WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
-	WCrt (regs, CRT_ID_START_VER_RETR, 0x9C);
-	WCrt (regs, CRT_ID_END_VER_RETR, 0x0E);
-	WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
-	WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50);
-	WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00);
-	WCrt (regs, CRT_ID_START_VER_BLANK, 0x96);
-	WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9);
-	WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
-	WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
-	WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10);	/* FIFO enabled */
-	WCrt (regs, CRT_ID_MISC_1, 0x35);
-	WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A);
-	WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
-	WCrt (regs, CRT_ID_LAW_POS_LO, 0x40);
-	WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
-
-	WGfx (regs, GCT_ID_SET_RESET, 0x0);
-	WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0);
-	WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0);
-	WGfx (regs, GCT_ID_DATA_ROTATE, 0x0);
-	WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0);
-	WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40);
-	WGfx (regs, GCT_ID_MISC, 0x01);
-	WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F);
-	WGfx (regs, GCT_ID_BITMASK, 0xFF);
-
-	/* Colors for text mode */
-	for (i = 0; i < 0xf; i++)
-		WAttr (regs, i, i);
-
-	WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
-	WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01);
-	WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
-	WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0);
-	WAttr (regs, ACT_ID_COLOR_SELECT, 0x0);
-
-	wb_64 (regs, VDAC_MASK, 0xFF);
-
-	*((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
-	*((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
-
-	/* Colors initially set to grayscale */
-
-	wb_64 (regs, VDAC_ADDRESS_W, 0);
-	for (i = 255; i >= 0; i--) {
-		wb_64(regs, VDAC_DATA, i);
-		wb_64(regs, VDAC_DATA, i);
-		wb_64(regs, VDAC_DATA, i);
-	}
-
-	/* GFx hardware cursor off */
-	WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
-
-	/* Set first to 4MB, so test will work */
-	WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
-	/* Find "correct" size of fbmem of Z3 board */
-	if (cv_has_4mb (CyberMem)) {
-		CyberSize = 1024 * 1024 * 4;
-		WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
-		DPRINTK("4MB board\n");
-	} else {
-		CyberSize = 1024 * 1024 * 2;
-		WCrt (regs, CRT_ID_LAW_CNTL, 0x12);
-		DPRINTK("2MB board\n");
-	}
-
-	/* Initialize graphics engine */
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_FRGD_MIX, 0x27);
-	vgaw16 (regs, ECR_BKGD_MIX, 0x07);
-	vgaw16 (regs, ECR_READ_REG_DATA, 0x1000);
-	udelay(200);
-	vgaw16 (regs, ECR_READ_REG_DATA, 0x2000);
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF);
-	Cyber_WaitBlit();
-	udelay(200);
-	vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0);
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_READ_REG_DATA, 0xE000);
-	vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00);
-	vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00);
-	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
-	vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00);
-	vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00);
-	vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00);
-	vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00);
-	vgaw16 (regs, ECR_SHORT_STROKE, 0x00);
-	vgaw16 (regs, ECR_DRAW_CMD, 0x01);
-
-	Cyber_WaitBlit();
-
-	vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
-	vgaw16 (regs, ECR_BKGD_COLOR, 0x01);
-	vgaw16 (regs, ECR_FRGD_COLOR, 0x00);
-
-
-	/* Enable video display (set bit 5) */
-/* ARB - Would also seem to write to AR13.
- *       May want to use parts of WAttr to set JUST bit 5
- */
-	WAttr (regs, 0x33, 0);
-	
-/* GRF - function code ended here */
-
-	/* Turn gfx on again */
-	gfx_on_off (0, regs);
-
-	/* Pass-through */
-	cvscreen (0, CyberBase);
-
-	DPRINTK("EXIT\n");
-}
-
-static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
-{
-  volatile unsigned char *regs = CyberRegs;
-  int fx, fy;
-  unsigned short mnr;
-  unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
-  char LACE, DBLSCAN, TEXT, CONSOLE;
-  int cr50, sr15, sr18, clock_mode, test;
-  int m, n;
-  int tfillm, temptym;
-  int hmul;
-	
-  /* ---------------- */
-  int xres, hfront, hsync, hback;
-  int yres, vfront, vsync, vback;
-  int bpp;
-#if 0
-  float freq_f;
-#endif
-  long freq;
-  /* ---------------- */
-	
-  DPRINTK("ENTER\n");
-  TEXT = 0;	/* if depth == 4 */
-  CONSOLE = 0;	/* mode num == 255 (console) */
-  fx = fy = 8;	/* force 8x8 font */
-
-/* GRF - Disable interrupts */	
-	
-  gfx_on_off (1, regs);
-	
-  switch (video_mode->bits_per_pixel) {
-  case 15:
-  case 16:
-    hmul = 2;
-    break;
-		
-  default:
-    hmul = 1;
-    break;
-  }
-	
-  bpp = video_mode->bits_per_pixel;
-  xres = video_mode->xres;
-  hfront = video_mode->right_margin;
-  hsync = video_mode->hsync_len;
-  hback = video_mode->left_margin;
-
-  LACE = 0;
-  DBLSCAN = 0;
-
-  if (video_mode->vmode & FB_VMODE_DOUBLE) {
-    yres = video_mode->yres * 2;
-    vfront = video_mode->lower_margin * 2;
-    vsync = video_mode->vsync_len * 2;
-    vback = video_mode->upper_margin * 2;
-    DBLSCAN = 1;
-  } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
-    yres = (video_mode->yres + 1) / 2;
-    vfront = (video_mode->lower_margin + 1) / 2;
-    vsync = (video_mode->vsync_len + 1) / 2;
-    vback = (video_mode->upper_margin + 1) / 2;
-    LACE = 1;
-  } else {
-    yres = video_mode->yres;
-    vfront = video_mode->lower_margin;
-    vsync = video_mode->vsync_len;
-    vback = video_mode->upper_margin;
-  }
-
-  /* ARB Dropping custom setup method from cvision.c */
-#if 0
-  if (cvision_custom_mode) {
-    HBS = hbs / 8 * hmul;
-    HBE = hbe / 8 * hmul;
-    HSS = hss / 8 * hmul;
-    HSE = hse / 8 * hmul;
-    HT  = ht / 8 * hmul - 5;
-		
-    VBS = vbs - 1;
-    VSS = vss;
-    VSE = vse;
-    VBE = vbe;
-    VT  = vt - 2;
-  } else {
-#else
-    {
-#endif
-    HBS = hmul * (xres / 8);
-    HBE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8) - 2);
-    HSS = hmul * ((xres/8) + (hfront/8) + 2);
-    HSE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + 1);
-    HT  = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8));
-	
-    VBS = yres;
-    VBE = yres + vfront + vsync + vback - 2;
-    VSS = yres + vfront - 1;
-    VSE = yres + vfront + vsync - 1;
-    VT  = yres + vfront + vsync + vback - 2;
-  }
-
-  wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
-	
-  if (TEXT)
-    HDE = ((video_mode->xres + fx - 1) / fx) - 1;
-  else
-    HDE = (video_mode->xres + 3) * hmul / 8 - 1;
-	
-  VDE = video_mode->yres - 1;
-
-  WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
-  WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00);
-	
-  WSeq (regs, SEQ_ID_MEMORY_MODE,
-	(TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e);
-  WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x00);
-  WSeq (regs, SEQ_ID_MAP_MASK,
-	(video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF);
-  WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
-	
-  /* cv64_compute_clock accepts arguments in Hz */
-  /* pixclock is in ps ... convert to Hz */
-	
-#if 0
-  freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
-  freq = ((long) freq_f) * 1000;
-#else
-/* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
- */
-  freq = (1000000000 / video_mode->pixclock) * 1000;
-#endif
-
-  mnr = cv64_compute_clock (freq);
-  WSeq (regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
-  WSeq (regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
-	
-  /* Load display parameters into board */
-  WCrt (regs, CRT_ID_EXT_HOR_OVF,
-	((HT & 0x100) ? 0x01 : 0x00) |
-	((HDE & 0x100) ? 0x02 : 0x00) |
-	((HBS & 0x100) ? 0x04 : 0x00) |
-	/* ((HBE & 0x40) ? 0x08 : 0x00) | */
-	((HSS & 0x100) ? 0x10 : 0x00) |
-	/* ((HSE & 0x20) ? 0x20 : 0x00) | */
-	(((HT-5) & 0x100) ? 0x40 : 0x00)
-	);
-	
-  WCrt (regs, CRT_ID_EXT_VER_OVF,
-	0x40 |
-	((VT & 0x400) ? 0x01 : 0x00) |
-	((VDE & 0x400) ? 0x02 : 0x00) |
-	((VBS & 0x400) ? 0x04 : 0x00) |
-	((VSS & 0x400) ? 0x10 : 0x00)
-	);
-	
-  WCrt (regs, CRT_ID_HOR_TOTAL, HT);
-  WCrt (regs, CRT_ID_DISPLAY_FIFO, HT - 5);
-  WCrt (regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
-  WCrt (regs, CRT_ID_START_HOR_BLANK, HBS);
-  WCrt (regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
-  WCrt (regs, CRT_ID_START_HOR_RETR, HSS);
-  WCrt (regs, CRT_ID_END_HOR_RETR,
-	(HSE & 0x1F) |
-	((HBE & 0x20) ? 0x80 : 0x00)
-	);
-  WCrt (regs, CRT_ID_VER_TOTAL, VT);
-  WCrt (regs, CRT_ID_OVERFLOW,
-	0x10 |
-	((VT & 0x100) ? 0x01 : 0x00) |
-	((VDE & 0x100) ? 0x02 : 0x00) |
-	((VSS & 0x100) ? 0x04 : 0x00) |
-	((VBS & 0x100) ? 0x08 : 0x00) |
-	((VT & 0x200) ? 0x20 : 0x00) |
-	((VDE & 0x200) ? 0x40 : 0x00) |
-	((VSS & 0x200) ? 0x80 : 0x00)
-	);
-  WCrt (regs, CRT_ID_MAX_SCAN_LINE,
-	0x40 |
-	(DBLSCAN ? 0x80 : 0x00) |
-	((VBS & 0x200) ? 0x20 : 0x00) |
-	(TEXT ? ((fy - 1) & 0x1F) : 0x00)
-	);
-	
-  WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
-
-  /* Text cursor */
-	
-  if (TEXT) {
-#if 1
-    WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
-    WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
-#else
-    WCrt (regs, CRT_ID_CURSOR_START, 0x00);
-    WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F);
-#endif
-    WCrt (regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
-    WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
-    WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
-  }
-	
-  WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
-  WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
-  WCrt (regs, CRT_ID_START_VER_RETR, VSS);
-  WCrt (regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
-  WCrt (regs, CRT_ID_VER_DISP_ENA_END, VDE);
-  WCrt (regs, CRT_ID_START_VER_BLANK, VBS);
-  WCrt (regs, CRT_ID_END_VER_BLANK, VBE);
-  WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
-  WCrt (regs, CRT_ID_LACE_RETR_START, HT / 2);
-  WCrt (regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
-  WGfx (regs, GCT_ID_GRAPHICS_MODE,
-	((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40));
-  WGfx (regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
-  WSeq (regs, SEQ_ID_MEMORY_MODE,
-	((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02));
-	
-  wb_64 (regs, VDAC_MASK, 0xFF);
-	
-  /* Blank border */
-  test = RCrt (regs, CRT_ID_BACKWAD_COMP_2);
-  WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
-	
-  sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
-  sr15 &= 0xEF;
-  sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL);
-  sr18 &= 0x7F;
-  clock_mode = 0x00;
-  cr50 = 0x00;
-	
-  test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
-  test &= 0xD;
-	
-  /* Clear roxxler byte-swapping... */
-  cv64_write_port (0x0040, CyberBase);
-  cv64_write_port (0x0020, CyberBase);
-	
-  switch (video_mode->bits_per_pixel) {
-  case 1:
-  case 4:	/* text */
-    HDE = video_mode->xres / 16;
-    break;
-		
-  case 8:
-    if (freq > 80000000) {
-      clock_mode = 0x10 | 0x02;
-      sr15 |= 0x10;
-      sr18 |= 0x80;
-    }
-    HDE = video_mode->xres / 8;
-    cr50 |= 0x00;
-    break;
-		
-  case 15:
-    cv64_write_port (0x8020, CyberBase);
-    clock_mode = 0x30;
-    HDE = video_mode->xres / 4;
-    cr50 |= 0x10;
-    break;
-		
-  case 16:
-    cv64_write_port (0x8020, CyberBase);
-    clock_mode = 0x50;
-    HDE = video_mode->xres / 4;
-    cr50 |= 0x10;
-    break;
-		
-  case 24:
-  case 32:
-    cv64_write_port (0x8040, CyberBase);
-    clock_mode = 0xD0;
-    HDE = video_mode->xres / 2;
-    cr50 |= 0x30;
-    break;
-  }
-
-  WCrt (regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
-  WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
-  WSeq (regs, SEQ_ID_RAMDAC_CNTL, sr18);
-  WCrt (regs, CRT_ID_SCREEN_OFFSET, HDE);
-
-  WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
-	
-  test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2);
-  test &= ~0x30;
-  test |= (HDE >> 4) & 0x30;
-  WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test);
-	
-  /* Set up graphics engine */
-  switch (video_mode->xres) {
-  case 1024:
-    cr50 |= 0x00;
-    break;
-		
-  case 640:
-    cr50 |= 0x40;
-    break;
-		
-  case 800:
-    cr50 |= 0x80;
-    break;
-		
-  case 1280:
-    cr50 |= 0xC0;
-    break;
-		
-  case 1152:
-    cr50 |= 0x01;
-    break;
-		
-  case 1600:
-    cr50 |= 0x81;
-    break;
-		
-  default:	/* XXX */
-    break;
-  }
-	
-  WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
-	
-  udelay(100);
-  WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
-  udelay(100);
-  WAttr (regs, ACT_ID_COLOR_PLANE_ENA,
-	 (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
-  udelay(100);
-	
-  tfillm = (96 * (cv64_memclk / 1000)) / 240000;
-	
-  switch (video_mode->bits_per_pixel) {
-  case 32:
-  case 24:
-    temptym = (24 * (cv64_memclk / 1000)) / (freq / 1000);
-    break;
-  case 15:
-  case 16:
-    temptym = (48 * (cv64_memclk / 1000)) / (freq / 1000);
-    break;
-  case 4:
-    temptym = (192 * (cv64_memclk / 1000)) / (freq / 1000);
-    break;
-  default:
-    temptym = (96 * (cv64_memclk / 1000)) / (freq / 1000);
-    break;
-  }
-	
-  m = (temptym - tfillm - 9) / 2;
-  if (m < 0)
-    m = 0;
-  m = (m & 0x1F) << 3;
-  if (m < 0x18)
-    m = 0x18;
-  n = 0xFF;
-	
-  WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m);
-  WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n);
-  udelay(10);
-	
-  /* Text initialization */
-	
-  if (TEXT) {
-    /* Do text initialization here ! */
-  }
-	
-  if (CONSOLE) {
-    int i;
-    wb_64 (regs, VDAC_ADDRESS_W, 0);
-    for (i = 0; i < 4; i++) {
-      wb_64 (regs, VDAC_DATA, cvconscolors [i][0]);
-      wb_64 (regs, VDAC_DATA, cvconscolors [i][1]);
-      wb_64 (regs, VDAC_DATA, cvconscolors [i][2]);
-    }
-  }
-	
-  WAttr (regs, 0x33, 0);
-	
-  /* Turn gfx on again */
-  gfx_on_off (0, (volatile unsigned char *) regs);
-	
-  /* Pass-through */
-  cvscreen (0, CyberBase);
-
-DPRINTK("EXIT\n");
-}
-
-void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
-		     u_short w, u_short h)
-{
-	volatile unsigned char *regs = CyberRegs;
-	unsigned short drawdir = 0;
-	
-	DPRINTK("ENTER\n");
-	if (sx > dx) {
-		drawdir |= 1 << 5;
-	} else {
-		sx += w - 1;
-		dx += w - 1;
-	}
-	
-	if (sy > dy) {
-		drawdir |= 1 << 7;
-	} else {
-		sy += h - 1;
-		dy += h - 1;
-	}
-	
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
-	vgaw16 (regs, ECR_BKGD_MIX, 0x7);
-	vgaw16 (regs, ECR_FRGD_MIX, 0x67);
-	vgaw16 (regs, ECR_BKGD_COLOR, 0x0);
-	vgaw16 (regs, ECR_FRGD_COLOR, 0x1);
-	vgaw16 (regs, ECR_BITPLANE_READ_MASK, 0x1);
-	vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
-	vgaw16 (regs, ECR_CURRENT_Y_POS, sy);
-	vgaw16 (regs, ECR_CURRENT_X_POS, sx);
-	vgaw16 (regs, ECR_DEST_Y__AX_STEP, dy);
-	vgaw16 (regs, ECR_DEST_X__DIA_STEP, dx);
-	vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
-	vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
-	vgaw16 (regs, ECR_DRAW_CMD, 0xC051 | drawdir);
-	DPRINTK("EXIT\n");
-}
-
-void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
-{
-	volatile unsigned char *regs = CyberRegs;
-	DPRINTK("ENTER\n");
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_FRGD_MIX, 0x0027);
-	vgaw16 (regs, ECR_FRGD_COLOR, bg);
-	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
-	vgaw16 (regs, ECR_CURRENT_Y_POS, dy);
-	vgaw16 (regs, ECR_CURRENT_X_POS, dx);
-	vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
-	vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
-	vgaw16 (regs, ECR_DRAW_CMD, 0x40B1);	
-	DPRINTK("EXIT\n");
-}
-
-#ifdef CYBERFBDEBUG
-/*
- * Dump internal settings of CyberVision board
- */
-static void cv64_dump (void)
-{
-	volatile unsigned char *regs = CyberRegs;
-	DPRINTK("ENTER\n");
-        /* Dump the VGA setup values */
-	*(regs + S3_CRTC_ADR) = 0x00;
-	DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x01;
-	DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x02;
-	DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x03;
-	DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x04;
-	DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x05;
-	DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x06;
-	DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x07;
-	DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x08;
-	DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x09;
-	DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x10;
-	DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x11;
-	DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x12;
-	DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x13;
-	DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x15;
-	DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x16;
-	DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x36;
-	DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x37;
-	DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x42;
-	DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x43;
-	DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x50;
-	DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x51;
-	DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x53;
-	DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x58;
-	DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x59;
-	DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x5A;
-	DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x5D;
-	DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x5E;
-	DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA));
-	DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R));
-	*(regs + SEQ_ADDRESS) = 0x01;
-	DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x02;
-	DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x03;
-	DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x09;
-	DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x10;
-	DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x11;
-	DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x12;
-	DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x13;
-	DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x15;
-	DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R));
-	
-	return;
-}
-#endif
diff --git a/drivers/video/cyberfb.h b/drivers/video/cyberfb.h
deleted file mode 100644
index 8435c43..0000000
--- a/drivers/video/cyberfb.h
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * linux/arch/m68k/console/cvision.h -- CyberVision64 definitions for the
- *                                      text console driver.
- *
- *   Copyright (c) 1998 Alan Bair
- *
- * This file is based on the initial port to Linux of grf_cvreg.h:
- *
- *   Copyright (c) 1997 Antonio Santos
- *
- * The original work is from the NetBSD CyberVision 64 framebuffer driver 
- * and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):
- * Permission to use the source of this driver was obtained from the
- * author Michael Teske by Alan Bair.
- *
- *   Copyright (c) 1995 Michael Teske
- *
- * History:
- *
- *
- *
- * 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.
- */
-
-/* s3 commands */
-#define S3_BITBLT       0xc011
-#define S3_TWOPOINTLINE 0x2811
-#define S3_FILLEDRECT   0x40b1
-
-#define S3_FIFO_EMPTY 0x0400
-#define S3_HDW_BUSY   0x0200
-
-/* Enhanced register mapping (MMIO mode) */
-
-#define S3_READ_SEL      0xbee8 /* offset f */
-#define S3_MULT_MISC     0xbee8 /* offset e */
-#define S3_ERR_TERM      0x92e8
-#define S3_FRGD_COLOR    0xa6e8
-#define S3_BKGD_COLOR    0xa2e8
-#define S3_PIXEL_CNTL    0xbee8 /* offset a */
-#define S3_FRGD_MIX      0xbae8
-#define S3_BKGD_MIX      0xb6e8
-#define S3_CUR_Y         0x82e8
-#define S3_CUR_X         0x86e8
-#define S3_DESTY_AXSTP   0x8ae8
-#define S3_DESTX_DIASTP  0x8ee8
-#define S3_MIN_AXIS_PCNT 0xbee8 /* offset 0 */
-#define S3_MAJ_AXIS_PCNT 0x96e8
-#define S3_CMD           0x9ae8
-#define S3_GP_STAT       0x9ae8
-#define S3_ADVFUNC_CNTL  0x4ae8
-#define S3_WRT_MASK      0xaae8
-#define S3_RD_MASK       0xaee8
-
-/* Enhanced register mapping (Packed MMIO mode, write only) */
-#define S3_ALT_CURXY     0x8100
-#define S3_ALT_CURXY2    0x8104
-#define S3_ALT_STEP      0x8108
-#define S3_ALT_STEP2     0x810c
-#define S3_ALT_ERR       0x8110
-#define S3_ALT_CMD       0x8118
-#define S3_ALT_MIX       0x8134
-#define S3_ALT_PCNT      0x8148
-#define S3_ALT_PAT       0x8168
-
-/* Drawing modes */
-#define S3_NOTCUR          0x0000
-#define S3_LOGICALZERO     0x0001
-#define S3_LOGICALONE      0x0002
-#define S3_LEAVEASIS       0x0003
-#define S3_NOTNEW          0x0004
-#define S3_CURXORNEW       0x0005
-#define S3_NOT_CURXORNEW   0x0006
-#define S3_NEW             0x0007
-#define S3_NOTCURORNOTNEW  0x0008
-#define S3_CURORNOTNEW     0x0009
-#define S3_NOTCURORNEW     0x000a
-#define S3_CURORNEW        0x000b
-#define S3_CURANDNEW       0x000c
-#define S3_NOTCURANDNEW    0x000d
-#define S3_CURANDNOTNEW    0x000e
-#define S3_NOTCURANDNOTNEW 0x000f
-
-#define S3_CRTC_ADR    0x03d4
-#define S3_CRTC_DATA   0x03d5
-
-#define S3_REG_LOCK2 0x39
-#define S3_HGC_MODE  0x45
-
-#define S3_HWGC_ORGX_H 0x46
-#define S3_HWGC_ORGX_L 0x47
-#define S3_HWGC_ORGY_H 0x48
-#define S3_HWGC_ORGY_L 0x49
-#define S3_HWGC_DX     0x4e
-#define S3_HWGC_DY     0x4f
-
-#define S3_LAW_CTL 0x58
-
-/**************************************************/
-
-/* support for a BitBlt operation. The op-codes are identical
-   to X11 GCs */
-#define	GRFBBOPclear		0x0	/* 0 */
-#define GRFBBOPand		0x1	/* src AND dst */
-#define GRFBBOPandReverse	0x2	/* src AND NOT dst */
-#define GRFBBOPcopy		0x3	/* src */
-#define GRFBBOPandInverted	0x4	/* NOT src AND dst */
-#define	GRFBBOPnoop		0x5	/* dst */
-#define GRFBBOPxor		0x6	/* src XOR dst */
-#define GRFBBOPor		0x7	/* src OR dst */
-#define GRFBBOPnor		0x8	/* NOT src AND NOT dst */
-#define GRFBBOPequiv		0x9	/* NOT src XOR dst */
-#define GRFBBOPinvert		0xa	/* NOT dst */
-#define GRFBBOPorReverse	0xb	/* src OR NOT dst */
-#define GRFBBOPcopyInverted	0xc	/* NOT src */
-#define GRFBBOPorInverted	0xd	/* NOT src OR dst */
-#define GRFBBOPnand		0xe	/* NOT src OR NOT dst */
-#define GRFBBOPset		0xf	/* 1 */
-
-
-/* Write 16 Bit VGA register */
-#define vgaw16(ba, reg, val) \
-*((unsigned short *)  (((volatile unsigned char *)ba)+reg)) = val
-
-/*
- * Defines for the used register addresses (mw)
- *
- * NOTE: There are some registers that have different addresses when
- *       in mono or color mode. We only support color mode, and thus
- *       some addresses won't work in mono-mode!
- *
- * General and VGA-registers taken from retina driver. Fixed a few
- * bugs in it. (SR and GR read address is Port + 1, NOT Port)
- *
- */
-
-/* General Registers: */
-#define GREG_MISC_OUTPUT_R	0x03CC
-#define GREG_MISC_OUTPUT_W	0x03C2	
-#define GREG_FEATURE_CONTROL_R	0x03CA
-#define GREG_FEATURE_CONTROL_W	0x03DA
-#define GREG_INPUT_STATUS0_R	0x03C2
-#define GREG_INPUT_STATUS1_R	0x03DA
-
-/* Setup Registers: */
-#define SREG_OPTION_SELECT	0x0102
-#define SREG_VIDEO_SUBS_ENABLE	0x46E8
-
-/* Attribute Controller: */
-#define ACT_ADDRESS		0x03C0
-#define ACT_ADDRESS_R		0x03C1
-#define ACT_ADDRESS_W		0x03C0
-#define ACT_ADDRESS_RESET	0x03DA
-#define ACT_ID_PALETTE0		0x00
-#define ACT_ID_PALETTE1		0x01
-#define ACT_ID_PALETTE2		0x02
-#define ACT_ID_PALETTE3		0x03
-#define ACT_ID_PALETTE4		0x04
-#define ACT_ID_PALETTE5		0x05
-#define ACT_ID_PALETTE6		0x06
-#define ACT_ID_PALETTE7		0x07
-#define ACT_ID_PALETTE8		0x08
-#define ACT_ID_PALETTE9		0x09
-#define ACT_ID_PALETTE10	0x0A
-#define ACT_ID_PALETTE11	0x0B
-#define ACT_ID_PALETTE12	0x0C
-#define ACT_ID_PALETTE13	0x0D
-#define ACT_ID_PALETTE14	0x0E
-#define ACT_ID_PALETTE15	0x0F
-#define ACT_ID_ATTR_MODE_CNTL	0x10
-#define ACT_ID_OVERSCAN_COLOR	0x11
-#define ACT_ID_COLOR_PLANE_ENA	0x12
-#define ACT_ID_HOR_PEL_PANNING	0x13
-#define ACT_ID_COLOR_SELECT	0x14
-
-/* Graphics Controller: */
-#define GCT_ADDRESS		0x03CE
-#define GCT_ADDRESS_R		0x03CF
-#define GCT_ADDRESS_W		0x03CF
-#define GCT_ID_SET_RESET	0x00
-#define GCT_ID_ENABLE_SET_RESET	0x01
-#define GCT_ID_COLOR_COMPARE	0x02
-#define GCT_ID_DATA_ROTATE	0x03
-#define GCT_ID_READ_MAP_SELECT	0x04
-#define GCT_ID_GRAPHICS_MODE	0x05
-#define GCT_ID_MISC		0x06
-#define GCT_ID_COLOR_XCARE	0x07
-#define GCT_ID_BITMASK		0x08
-
-/* Sequencer: */
-#define SEQ_ADDRESS		0x03C4
-#define SEQ_ADDRESS_R		0x03C5
-#define SEQ_ADDRESS_W		0x03C5
-#define SEQ_ID_RESET		0x00
-#define SEQ_ID_CLOCKING_MODE	0x01
-#define SEQ_ID_MAP_MASK		0x02
-#define SEQ_ID_CHAR_MAP_SELECT	0x03
-#define SEQ_ID_MEMORY_MODE	0x04
-#define SEQ_ID_UNKNOWN1		0x05
-#define SEQ_ID_UNKNOWN2		0x06
-#define SEQ_ID_UNKNOWN3		0x07
-/* S3 extensions */
-#define SEQ_ID_UNLOCK_EXT	0x08
-#define SEQ_ID_EXT_SEQ_REG9	0x09
-#define SEQ_ID_BUS_REQ_CNTL	0x0A
-#define SEQ_ID_EXT_MISC_SEQ	0x0B
-#define SEQ_ID_UNKNOWN4		0x0C
-#define SEQ_ID_EXT_SEQ		0x0D
-#define SEQ_ID_UNKNOWN5		0x0E
-#define SEQ_ID_UNKNOWN6		0x0F
-#define SEQ_ID_MCLK_LO		0x10
-#define SEQ_ID_MCLK_HI		0x11
-#define SEQ_ID_DCLK_LO		0x12
-#define SEQ_ID_DCLK_HI		0x13
-#define SEQ_ID_CLKSYN_CNTL_1	0x14
-#define SEQ_ID_CLKSYN_CNTL_2	0x15
-#define SEQ_ID_CLKSYN_TEST_HI	0x16	/* reserved for S3 testing of the */
-#define SEQ_ID_CLKSYN_TEST_LO	0x17	/*   internal clock synthesizer   */
-#define SEQ_ID_RAMDAC_CNTL	0x18
-#define SEQ_ID_MORE_MAGIC	0x1A
-
-/* CRT Controller: */
-#define CRT_ADDRESS		0x03D4
-#define CRT_ADDRESS_R		0x03D5
-#define CRT_ADDRESS_W		0x03D5
-#define CRT_ID_HOR_TOTAL	0x00
-#define CRT_ID_HOR_DISP_ENA_END	0x01
-#define CRT_ID_START_HOR_BLANK	0x02
-#define CRT_ID_END_HOR_BLANK	0x03
-#define CRT_ID_START_HOR_RETR	0x04
-#define CRT_ID_END_HOR_RETR	0x05
-#define CRT_ID_VER_TOTAL	0x06
-#define CRT_ID_OVERFLOW		0x07
-#define CRT_ID_PRESET_ROW_SCAN	0x08
-#define CRT_ID_MAX_SCAN_LINE	0x09
-#define CRT_ID_CURSOR_START	0x0A
-#define CRT_ID_CURSOR_END	0x0B
-#define CRT_ID_START_ADDR_HIGH	0x0C
-#define CRT_ID_START_ADDR_LOW	0x0D
-#define CRT_ID_CURSOR_LOC_HIGH	0x0E
-#define CRT_ID_CURSOR_LOC_LOW	0x0F
-#define CRT_ID_START_VER_RETR	0x10
-#define CRT_ID_END_VER_RETR	0x11
-#define CRT_ID_VER_DISP_ENA_END	0x12
-#define CRT_ID_SCREEN_OFFSET	0x13
-#define CRT_ID_UNDERLINE_LOC	0x14
-#define CRT_ID_START_VER_BLANK	0x15
-#define CRT_ID_END_VER_BLANK	0x16
-#define CRT_ID_MODE_CONTROL	0x17
-#define CRT_ID_LINE_COMPARE	0x18
-#define CRT_ID_GD_LATCH_RBACK	0x22
-#define CRT_ID_ACT_TOGGLE_RBACK	0x24
-#define CRT_ID_ACT_INDEX_RBACK	0x26
-/* S3 extensions: S3 VGA Registers */
-#define CRT_ID_DEVICE_HIGH	0x2D
-#define CRT_ID_DEVICE_LOW	0x2E
-#define CRT_ID_REVISION 	0x2F
-#define CRT_ID_CHIP_ID_REV	0x30
-#define CRT_ID_MEMORY_CONF	0x31
-#define CRT_ID_BACKWAD_COMP_1	0x32
-#define CRT_ID_BACKWAD_COMP_2	0x33
-#define CRT_ID_BACKWAD_COMP_3	0x34
-#define CRT_ID_REGISTER_LOCK	0x35
-#define CRT_ID_CONFIG_1 	0x36
-#define CRT_ID_CONFIG_2 	0x37
-#define CRT_ID_REGISTER_LOCK_1	0x38
-#define CRT_ID_REGISTER_LOCK_2	0x39
-#define CRT_ID_MISC_1		0x3A
-#define CRT_ID_DISPLAY_FIFO	0x3B
-#define CRT_ID_LACE_RETR_START	0x3C
-/* S3 extensions: System Control Registers  */
-#define CRT_ID_SYSTEM_CONFIG	0x40
-#define CRT_ID_BIOS_FLAG	0x41
-#define CRT_ID_LACE_CONTROL	0x42
-#define CRT_ID_EXT_MODE 	0x43
-#define CRT_ID_HWGC_MODE	0x45	/* HWGC = Hardware Graphics Cursor */
-#define CRT_ID_HWGC_ORIGIN_X_HI	0x46
-#define CRT_ID_HWGC_ORIGIN_X_LO	0x47
-#define CRT_ID_HWGC_ORIGIN_Y_HI	0x48
-#define CRT_ID_HWGC_ORIGIN_Y_LO	0x49
-#define CRT_ID_HWGC_FG_STACK	0x4A
-#define CRT_ID_HWGC_BG_STACK	0x4B
-#define CRT_ID_HWGC_START_AD_HI	0x4C
-#define CRT_ID_HWGC_START_AD_LO	0x4D
-#define CRT_ID_HWGC_DSTART_X	0x4E
-#define CRT_ID_HWGC_DSTART_Y	0x4F
-/* S3 extensions: System Extension Registers  */
-#define CRT_ID_EXT_SYS_CNTL_1	0x50
-#define CRT_ID_EXT_SYS_CNTL_2	0x51
-#define CRT_ID_EXT_BIOS_FLAG_1	0x52
-#define CRT_ID_EXT_MEM_CNTL_1	0x53
-#define CRT_ID_EXT_MEM_CNTL_2	0x54
-#define CRT_ID_EXT_DAC_CNTL	0x55
-#define CRT_ID_EX_SYNC_1	0x56
-#define CRT_ID_EX_SYNC_2	0x57
-#define CRT_ID_LAW_CNTL		0x58	/* LAW = Linear Address Window */
-#define CRT_ID_LAW_POS_HI	0x59
-#define CRT_ID_LAW_POS_LO	0x5A
-#define CRT_ID_GOUT_PORT	0x5C
-#define CRT_ID_EXT_HOR_OVF	0x5D
-#define CRT_ID_EXT_VER_OVF	0x5E
-#define CRT_ID_EXT_MEM_CNTL_3	0x60
-#define CRT_ID_EX_SYNC_3	0x63
-#define CRT_ID_EXT_MISC_CNTL	0x65
-#define CRT_ID_EXT_MISC_CNTL_1	0x66
-#define CRT_ID_EXT_MISC_CNTL_2	0x67
-#define CRT_ID_CONFIG_3 	0x68
-#define CRT_ID_EXT_SYS_CNTL_3	0x69
-#define CRT_ID_EXT_SYS_CNTL_4	0x6A
-#define CRT_ID_EXT_BIOS_FLAG_3	0x6B
-#define CRT_ID_EXT_BIOS_FLAG_4	0x6C
-
-/* Enhanced Commands Registers: */
-#define ECR_SUBSYSTEM_STAT	0x42E8
-#define ECR_SUBSYSTEM_CNTL	0x42E8
-#define ECR_ADV_FUNC_CNTL	0x4AE8
-#define ECR_CURRENT_Y_POS	0x82E8
-#define ECR_CURRENT_Y_POS2	0x82EA	/* Trio64 only */
-#define ECR_CURRENT_X_POS	0x86E8
-#define ECR_CURRENT_X_POS2	0x86EA	/* Trio64 only */
-#define ECR_DEST_Y__AX_STEP	0x8AE8
-#define ECR_DEST_Y2__AX_STEP2	0x8AEA	/* Trio64 only */
-#define ECR_DEST_X__DIA_STEP	0x8EE8
-#define ECR_DEST_X2__DIA_STEP2	0x8EEA	/* Trio64 only */
-#define ECR_ERR_TERM		0x92E8
-#define ECR_ERR_TERM2		0x92EA	/* Trio64 only */
-#define ECR_MAJ_AXIS_PIX_CNT	0x96E8
-#define ECR_MAJ_AXIS_PIX_CNT2	0x96EA	/* Trio64 only */
-#define ECR_GP_STAT		0x9AE8	/* GP = Graphics Processor */
-#define ECR_DRAW_CMD		0x9AE8
-#define ECR_DRAW_CMD2		0x9AEA	/* Trio64 only */
-#define ECR_SHORT_STROKE	0x9EE8
-#define ECR_BKGD_COLOR		0xA2E8	/* BKGD = Background */
-#define ECR_FRGD_COLOR		0xA6E8	/* FRGD = Foreground */
-#define ECR_BITPLANE_WRITE_MASK	0xAAE8
-#define ECR_BITPLANE_READ_MASK	0xAEE8
-#define ECR_COLOR_COMPARE	0xB2E8
-#define ECR_BKGD_MIX		0xB6E8
-#define ECR_FRGD_MIX		0xBAE8
-#define ECR_READ_REG_DATA	0xBEE8
-#define ECR_ID_MIN_AXIS_PIX_CNT	0x00
-#define ECR_ID_SCISSORS_TOP	0x01
-#define ECR_ID_SCISSORS_LEFT	0x02
-#define ECR_ID_SCISSORS_BUTTOM	0x03
-#define ECR_ID_SCISSORS_RIGHT	0x04
-#define ECR_ID_PIX_CNTL		0x0A
-#define ECR_ID_MULT_CNTL_MISC_2	0x0D
-#define ECR_ID_MULT_CNTL_MISC	0x0E
-#define ECR_ID_READ_SEL		0x0F
-#define ECR_PIX_TRANS		0xE2E8
-#define ECR_PIX_TRANS_EXT	0xE2EA
-#define ECR_PATTERN_Y		0xEAE8	/* Trio64 only */
-#define ECR_PATTERN_X		0xEAEA	/* Trio64 only */
-
-
-/* Pass-through */
-#define PASS_ADDRESS		0x40001
-#define PASS_ADDRESS_W		0x40001
-
-/* Video DAC */
-#define VDAC_ADDRESS		0x03c8
-#define VDAC_ADDRESS_W		0x03c8
-#define VDAC_ADDRESS_R		0x03c7
-#define VDAC_STATE		0x03c7
-#define VDAC_DATA		0x03c9
-#define VDAC_MASK		0x03c6
-
-
-#define WGfx(ba, idx, val) \
-do { wb_64(ba, GCT_ADDRESS, idx); wb_64(ba, GCT_ADDRESS_W , val); } while (0)
-
-#define WSeq(ba, idx, val) \
-do { wb_64(ba, SEQ_ADDRESS, idx); wb_64(ba, SEQ_ADDRESS_W , val); } while (0)
-
-#define WCrt(ba, idx, val) \
-do { wb_64(ba, CRT_ADDRESS, idx); wb_64(ba, CRT_ADDRESS_W , val); } while (0)
-
-#define WAttr(ba, idx, val) \
-do { \
-  unsigned char tmp;\
-  tmp = rb_64(ba, ACT_ADDRESS_RESET);\
-  wb_64(ba, ACT_ADDRESS_W, idx);\
-  wb_64(ba, ACT_ADDRESS_W, val);\
-} while (0)
-
-#define SetTextPlane(ba, m) \
-do { \
-  WGfx(ba, GCT_ID_READ_MAP_SELECT, m & 3 );\
-  WSeq(ba, SEQ_ID_MAP_MASK, (1 << (m & 3)));\
-} while (0)
-
-     /* --------------------------------- */
-     /* prototypes                        */
-     /* --------------------------------- */
-
-inline unsigned char RAttr(volatile unsigned char * board, short idx);
-inline unsigned char RSeq(volatile unsigned char * board, short idx);
-inline unsigned char RCrt(volatile unsigned char * board, short idx);
-inline unsigned char RGfx(volatile unsigned char * board, short idx);
-inline void cv64_write_port(unsigned short bits,
-			    volatile unsigned char *board);
-inline void cvscreen(int toggle, volatile unsigned char *board);
-inline void gfx_on_off(int toggle, volatile unsigned char *board);
-#if 0
-unsigned short cv64_compute_clock(unsigned long freq);
-int cv_has_4mb(volatile unsigned char * fb);
-void cv64_board_init(void);
-void cv64_load_video_mode(struct fb_var_screeninfo *video_mode);
-#endif
-
-void cvision_bitblt(u_short sx, u_short sy, u_short dx, u_short dy, u_short w,
-		    u_short h);
-void cvision_clear(u_short dx, u_short dy, u_short w, u_short h, u_short bg);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 3cfea31..2822526 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -16,7 +16,6 @@
 #include <linux/compat.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 323bdf6..40c80c8 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -59,7 +59,7 @@
 	info->device = dev;
 
 #ifdef CONFIG_FB_BACKLIGHT
-	mutex_init(&info->bl_mutex);
+	mutex_init(&info->bl_curve_mutex);
 #endif
 
 	return info;
@@ -175,7 +175,7 @@
 
 	acquire_console_sem();
 	list_splice(&fb_info->modelist, &old_list);
-	fb_videomode_to_modelist((struct fb_videomode *)buf, i,
+	fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
 				 &fb_info->modelist);
 	if (fb_new_modelist(fb_info)) {
 		fb_destroy_modelist(&fb_info->modelist);
@@ -445,10 +445,10 @@
 	/* If there has been an error in the input data, we won't
 	 * reach this loop.
 	 */
-	mutex_lock(&fb_info->bl_mutex);
+	mutex_lock(&fb_info->bl_curve_mutex);
 	for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i)
 		fb_info->bl_curve[i] = tmp_curve[i];
-	mutex_unlock(&fb_info->bl_mutex);
+	mutex_unlock(&fb_info->bl_curve_mutex);
 
 	return count;
 }
@@ -466,7 +466,7 @@
 	if (!fb_info || !fb_info->bl_dev)
 		return -ENODEV;
 
-	mutex_lock(&fb_info->bl_mutex);
+	mutex_lock(&fb_info->bl_curve_mutex);
 	for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8)
 		len += snprintf(&buf[len], PAGE_SIZE,
 				"%02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -478,7 +478,7 @@
 				fb_info->bl_curve[i + 5],
 				fb_info->bl_curve[i + 6],
 				fb_info->bl_curve[i + 7]);
-	mutex_unlock(&fb_info->bl_mutex);
+	mutex_unlock(&fb_info->bl_curve_mutex);
 
 	return len;
 }
@@ -552,6 +552,8 @@
 {
 	unsigned int i, flat, count, range = (max - min);
 
+	mutex_lock(&fb_info->bl_curve_mutex);
+
 	fb_info->bl_curve[0] = off;
 
 	for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
@@ -560,6 +562,8 @@
 	count = FB_BACKLIGHT_LEVELS * 15 / 16;
 	for (i = 0; i < count; ++i)
 		fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count);
+
+	mutex_unlock(&fb_info->bl_curve_mutex);
 }
 EXPORT_SYMBOL_GPL(fb_bl_default_curve);
 #endif
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c
index 1b981b6..ca93a75 100644
--- a/drivers/video/g364fb.c
+++ b/drivers/video/g364fb.c
@@ -16,7 +16,6 @@
 
 #include <linux/module.h>
 #include <linux/console.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index bcf9cea..bb20a22 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -401,6 +401,30 @@
 	framebuffer_release(info);
 }
 
+#ifndef MODULE
+static void __init gx1fb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return;
+
+	while ((this_opt = strsep(&options, ","))) {
+		if (!*this_opt)
+			continue;
+
+		if (!strncmp(this_opt, "mode:", 5))
+			strlcpy(mode_option, this_opt + 5, sizeof(mode_option));
+		else if (!strncmp(this_opt, "crt:", 4))
+			crt_option = !!simple_strtoul(this_opt + 4, NULL, 0);
+		else if (!strncmp(this_opt, "panel:", 6))
+			strlcpy(panel_option, this_opt + 6, sizeof(panel_option));
+		else
+			strlcpy(mode_option, this_opt, sizeof(mode_option));
+	}
+}
+#endif
+
 static struct pci_device_id gx1fb_id_table[] = {
 	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_VIDEO,
 	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
@@ -420,8 +444,11 @@
 static int __init gx1fb_init(void)
 {
 #ifndef MODULE
-	if (fb_get_options("gx1fb", NULL))
+	char *option = NULL;
+
+	if (fb_get_options("gx1fb", &option))
 		return -ENODEV;
+	gx1fb_setup(option);
 #endif
 	return pci_register_driver(&gx1fb_driver);
 }
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 3dc4942..756c0ce 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index 9ab9b83..b18486a 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -7,7 +7,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index 961f4d4..7787c33 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -10,7 +10,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index 579195c..aa65ffc 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -264,7 +264,8 @@
 	struct heap_data         cursor_heap;
 	struct vgastate          state;
 	struct i810fb_i2c_chan   chan[3];
-	atomic_t                 use_count;
+	struct mutex		 open_lock;
+	unsigned int		 use_count;
 	u32 pseudo_palette[17];
 	unsigned long mmio_start_phys;
 	u8 __iomem *mmio_start_virtual;
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index b55a12d..7e76019 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -142,7 +142,7 @@
 static int vsync1     __devinitdata;
 static int vsync2     __devinitdata;
 static int xres       __devinitdata;
-static int yres       __devinitdata;
+static int yres;
 static int vyres      __devinitdata;
 static int sync       __devinitdata;
 static int extvga     __devinitdata;
@@ -1049,7 +1049,7 @@
 		mode_valid = 1;
 
 	if (!mode_valid && info->monspecs.modedb_len) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -1235,9 +1235,9 @@
 static int i810fb_open(struct fb_info *info, int user)
 {
 	struct i810fb_par *par = info->par;
-	u32 count = atomic_read(&par->use_count);
-	
-	if (count == 0) {
+
+	mutex_lock(&par->open_lock);
+	if (par->use_count == 0) {
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_CMAP;
 		par->state.vgabase = par->mmio_start_virtual;
@@ -1246,7 +1246,8 @@
 		i810_save_vga_state(par);
 	}
 
-	atomic_inc(&par->use_count);
+	par->use_count++;
+	mutex_unlock(&par->open_lock);
 	
 	return 0;
 }
@@ -1254,18 +1255,20 @@
 static int i810fb_release(struct fb_info *info, int user)
 {
 	struct i810fb_par *par = info->par;
-	u32 count;
-	
-	count = atomic_read(&par->use_count);
-	if (count == 0)
-		return -EINVAL;
 
-	if (count == 1) {
+	mutex_lock(&par->open_lock);
+	if (par->use_count == 0) {
+		mutex_unlock(&par->open_lock);
+		return -EINVAL;
+	}
+
+	if (par->use_count == 1) {
 		i810_restore_vga_state(par);
 		restore_vga(&par->state);
 	}
 
-	atomic_dec(&par->use_count);
+	par->use_count--;
+	mutex_unlock(&par->open_lock);
 	
 	return 0;
 }
@@ -1752,6 +1755,8 @@
 static void __devinit i810_init_defaults(struct i810fb_par *par, 
 				      struct fb_info *info)
 {
+	mutex_init(&par->open_lock);
+
 	if (voffset) 
 		v_offset_default = voffset;
 	else if (par->aperture.size > 32 * 1024 * 1024)
@@ -1919,7 +1924,7 @@
 	fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
 				 &info->modelist);
 	if (specs->modedb != NULL) {
-		struct fb_videomode *m;
+		const struct fb_videomode *m;
 
 		if (xres && yres) {
 			if ((m = fb_find_best_mode(&var, &info->modelist))) {
@@ -2016,11 +2021,10 @@
 	par = info->par;
 	par->dev = dev;
 
-	if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) {
+	if (!(info->pixmap.addr = kzalloc(8*1024, GFP_KERNEL))) {
 		i810fb_release_resource(info, par);
 		return -ENOMEM;
 	}
-	memset(info->pixmap.addr, 0, 8*1024);
 	info->pixmap.size = 8*1024;
 	info->pixmap.buf_align = 8;
 	info->pixmap.access_align = 32;
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 655ae0f..90592fb 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -370,7 +370,6 @@
 
 int __init igafb_init(void)
 {
-        extern int con_is_present(void);
         struct fb_info *info;
         struct pci_dev *pdev;
         struct iga_par *par;
@@ -402,12 +401,11 @@
 	
 	size = sizeof(struct fb_info) + sizeof(struct iga_par) + sizeof(u32)*16;
 
-        info = kmalloc(size, GFP_ATOMIC);
+        info = kzalloc(size, GFP_ATOMIC);
         if (!info) {
                 printk("igafb_init: can't alloc fb_info\n");
                 return -ENOMEM;
         }
-        memset(info, 0, size);
 
 	par = (struct iga_par *) (info + 1);
 	
@@ -466,7 +464,7 @@
 	 * one additional region with size == 0. 
 	 */
 
-	par->mmap_map = kmalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC);
+	par->mmap_map = kzalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC);
 	if (!par->mmap_map) {
 		printk("igafb_init: can't alloc mmap_map\n");
 		iounmap((void *)par->io_base);
@@ -475,8 +473,6 @@
 		return -ENOMEM;
 	}
 
-	memset(par->mmap_map, 0, 4 * sizeof(*par->mmap_map));
-
 	/*
 	 * Set default vmode and cmode from PROM properties.
 	 */
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 0f9b2fd..267c1ff 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -20,7 +20,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/interrupt.h>
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index 33bc41f..f4ede5f 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -27,7 +27,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 664fc5c..b75eda8 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -540,12 +540,11 @@
 	dinfo->pdev  = pdev;
 
 	/* Reserve pixmap space. */
-	info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL);
+	info->pixmap.addr = kzalloc(64 * 1024, GFP_KERNEL);
 	if (info->pixmap.addr == NULL) {
 		ERR_MSG("Cannot reserve pixmap memory.\n");
 		goto err_out_pixmap;
 	}
-	memset(info->pixmap.addr, 0, 64 * 1024);
 
 	/* set early this option because it could be changed by tv encoder
 	   driver */
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index a958368..c1eb18b 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -1990,7 +1990,8 @@
 intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable) {
 
 	if (!test_and_set_bit(0, &dinfo->irq_flags)) {
-		if (request_irq(dinfo->pdev->irq, intelfbhw_irq, SA_SHIRQ, "intelfb", dinfo)) {
+		if (request_irq(dinfo->pdev->irq, intelfbhw_irq, IRQF_SHARED,
+		     "intelfb", dinfo)) {
 			clear_bit(0, &dinfo->irq_flags);
 			return -EINVAL;
 		}
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index f0d614a..1c55799 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/string.h>
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index 180d94c..f7d647d 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -20,7 +20,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index fe28848..5ec718a 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -115,6 +115,7 @@
 		minfo->fbcon.node);
 	i2c_set_adapdata(&b->adapter, b);
 	b->adapter.algo_data = &b->bac;
+	b->adapter.dev.parent = &ACCESS_FBINFO(pcidev)->dev;
 	b->bac = matrox_i2c_algo_template;
 	b->bac.data = b;
 	err = i2c_bit_add_bus(&b->adapter);
@@ -146,7 +147,7 @@
 	unsigned long flags;
 	struct matroxfb_dh_maven_info* m2info;
 
-	m2info = kmalloc(sizeof(*m2info), GFP_KERNEL);
+	m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
 	if (!m2info)
 		return NULL;
 
@@ -155,8 +156,6 @@
 	matroxfb_DAC_out(PMINFO DAC_XGENIOCTRL, 0x00);
 	matroxfb_DAC_unlock_irqrestore(flags);
 
-	memset(m2info, 0, sizeof(*m2info));
-
 	switch (ACCESS_FBINFO(chip)) {
 		case MGA_2064:
 		case MGA_2164:
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 2c98010..03ae55b 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -694,12 +694,11 @@
 	/* hardware is CRTC2 incapable... */
 	if (!ACCESS_FBINFO(devflags.crtc2))
 		return NULL;
-	m2info = kmalloc(sizeof(*m2info), GFP_KERNEL);
+	m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
 	if (!m2info) {
 		printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");
 		return NULL;
 	}
-	memset(m2info, 0, sizeof(*m2info));
 	m2info->primary_dev = MINFO;
 	if (matroxfb_dh_registerfb(m2info)) {
 		kfree(m2info);
diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
index 38c8d38..5e91c2b 100644
--- a/drivers/video/maxinefb.c
+++ b/drivers/video/maxinefb.c
@@ -25,7 +25,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c
index 472a3ca..15b8b3c4 100644
--- a/drivers/video/mbx/mbxdebugfs.c
+++ b/drivers/video/mbx/mbxdebugfs.c
@@ -170,37 +170,37 @@
 }
 
 
-static struct file_operations sysconf_fops = {
+static const struct file_operations sysconf_fops = {
 	.read = sysconf_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations clock_fops = {
+static const struct file_operations clock_fops = {
 	.read = clock_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations display_fops = {
+static const struct file_operations display_fops = {
 	.read = display_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations gsctl_fops = {
+static const struct file_operations gsctl_fops = {
 	.read = gsctl_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations sdram_fops = {
+static const struct file_operations sdram_fops = {
 	.read = sdram_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations misc_fops = {
+static const struct file_operations misc_fops = {
 	.read = misc_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 5df41f6..3e51794 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/fb.h>
-#include <linux/sched.h>
 
 #undef DEBUG
 
@@ -610,10 +609,8 @@
 	diff = refresh;
 	best = -1;
 	for (i = 0; i < dbsize; i++) {
-		if ((name_matches(db[i], name, namelen) &&
-			!fb_try_mode(var, info, &db[i], bpp)))
-			return 1;
-		if (res_specified && res_matches(db[i], xres, yres)) {
+		if (name_matches(db[i], name, namelen) ||
+		    (res_specified && res_matches(db[i], xres, yres))) {
 			if(!fb_try_mode(var, info, &db[i], bpp)) {
 				if(!refresh_specified || db[i].refresh == refresh)
 					return 1;
@@ -670,7 +667,7 @@
  * @var: pointer to struct fb_var_screeninfo
  */
 void fb_var_to_videomode(struct fb_videomode *mode,
-			 struct fb_var_screeninfo *var)
+			 const struct fb_var_screeninfo *var)
 {
 	u32 pixclock, hfreq, htotal, vtotal;
 
@@ -714,17 +711,21 @@
  * @mode: pointer to struct fb_videomode
  */
 void fb_videomode_to_var(struct fb_var_screeninfo *var,
-			       struct fb_videomode *mode)
+			 const struct fb_videomode *mode)
 {
 	var->xres = mode->xres;
 	var->yres = mode->yres;
+	var->xres_virtual = mode->xres;
+	var->yres_virtual = mode->yres;
+	var->xoffset = 0;
+	var->yoffset = 0;
 	var->pixclock = mode->pixclock;
 	var->left_margin = mode->left_margin;
-	var->hsync_len = mode->hsync_len;
-	var->vsync_len = mode->vsync_len;
 	var->right_margin = mode->right_margin;
 	var->upper_margin = mode->upper_margin;
 	var->lower_margin = mode->lower_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
 	var->sync = mode->sync;
 	var->vmode = mode->vmode & FB_VMODE_MASK;
 }
@@ -737,8 +738,8 @@
  * RETURNS:
  * 1 if equal, 0 if not
  */
-int fb_mode_is_equal(struct fb_videomode *mode1,
-		     struct fb_videomode *mode2)
+int fb_mode_is_equal(const struct fb_videomode *mode1,
+		     const struct fb_videomode *mode2)
 {
 	return (mode1->xres         == mode2->xres &&
 		mode1->yres         == mode2->yres &&
@@ -770,8 +771,8 @@
  * var->xres and var->yres.  If more than 1 videomode is found, will return
  * the videomode with the highest refresh rate
  */
-struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
-				       struct list_head *head)
+const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
+					     struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -808,8 +809,8 @@
  * If more than 1 videomode is found, will return the videomode with
  * the closest refresh rate.
  */
-struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
-					  struct list_head *head)
+const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
+					        struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -847,8 +848,8 @@
  * RETURNS:
  * struct fb_videomode, NULL if none found
  */
-struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
-				   struct list_head *head)
+const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
+					 struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -872,7 +873,7 @@
  * NOTES:
  * Will only add unmatched mode entries
  */
-int fb_add_videomode(struct fb_videomode *mode, struct list_head *head)
+int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -907,7 +908,8 @@
  * NOTES:
  * Will remove all matching mode entries
  */
-void fb_delete_videomode(struct fb_videomode *mode, struct list_head *head)
+void fb_delete_videomode(const struct fb_videomode *mode,
+			 struct list_head *head)
 {
 	struct list_head *pos, *n;
 	struct fb_modelist *modelist;
@@ -943,7 +945,7 @@
  * @num: number of entries in array
  * @head: struct list_head of modelist
  */
-void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
 			      struct list_head *head)
 {
 	int i;
@@ -956,12 +958,12 @@
 	}
 }
 
-struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
-					  struct list_head *head)
+const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
+					        struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
-	struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
+	const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
 	int first = 0;
 
 	if (!head->prev || !head->next || list_empty(head))
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index deaf820..395cced 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -66,7 +66,6 @@
 #include <linux/init.h>
 #ifdef CONFIG_TOSHIBA
 #include <linux/toshiba.h>
-extern int tosh_smm(SMMRegisters *regs);
 #endif
 
 #include <asm/io.h>
@@ -557,14 +556,16 @@
 neofb_open(struct fb_info *info, int user)
 {
 	struct neofb_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
-	if (!cnt) {
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
 		save_vga(&par->state);
 	}
-	atomic_inc(&par->ref_count);
+	par->ref_count++;
+	mutex_unlock(&par->open_lock);
+
 	return 0;
 }
 
@@ -572,14 +573,18 @@
 neofb_release(struct fb_info *info, int user)
 {
 	struct neofb_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
-	if (!cnt)
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
+		mutex_unlock(&par->open_lock);
 		return -EINVAL;
-	if (cnt == 1) {
+	}
+	if (par->ref_count == 1) {
 		restore_vga(&par->state);
 	}
-	atomic_dec(&par->ref_count);
+	par->ref_count--;
+	mutex_unlock(&par->open_lock);
+
 	return 0;
 }
 
@@ -2048,6 +2053,7 @@
 
 	info->fix.accel = id->driver_data;
 
+	mutex_init(&par->open_lock);
 	par->pci_burst = !nopciburst;
 	par->lcd_stretch = !nostretch;
 	par->libretto = libretto;
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
index df934bd..b7016e9 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -16,11 +16,6 @@
 #include "nv_type.h"
 #include "nv_proto.h"
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#include <asm/machdep.h>
-#endif
-
 /* We do not have any information about which values are allowed, thus
  * we used safe values.
  */
@@ -30,7 +25,6 @@
 
 static struct backlight_properties nvidia_bl_data;
 
-/* Call with fb_info->bl_mutex held */
 static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
 		int level)
 {
@@ -38,6 +32,7 @@
 	int nlevel;
 
 	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
 	nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
 
 	if (nlevel < 0)
@@ -50,8 +45,7 @@
 	return nlevel;
 }
 
-/* Call with fb_info->bl_mutex held */
-static int __nvidia_bl_update_status(struct backlight_device *bd)
+static int nvidia_bl_update_status(struct backlight_device *bd)
 {
 	struct nvidia_par *par = class_get_devdata(&bd->class_dev);
 	u32 tmp_pcrt, tmp_pmc, fpcontrol;
@@ -60,11 +54,11 @@
 	if (!par->FlatPanel)
 		return 0;
 
-	if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 	else
-		level = bd->props->brightness;
+		level = bd->props.brightness;
 
 	tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
 	tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
@@ -85,45 +79,16 @@
 	return 0;
 }
 
-static int nvidia_bl_update_status(struct backlight_device *bd)
-{
-	struct nvidia_par *par = class_get_devdata(&bd->class_dev);
-	struct fb_info *info = pci_get_drvdata(par->pci_dev);
-	int ret;
-
-	mutex_lock(&info->bl_mutex);
-	ret = __nvidia_bl_update_status(bd);
-	mutex_unlock(&info->bl_mutex);
-
-	return ret;
-}
-
 static int nvidia_bl_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties nvidia_bl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops nvidia_bl_ops = {
 	.get_brightness = nvidia_bl_get_brightness,
 	.update_status	= nvidia_bl_update_status,
-	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
-void nvidia_bl_set_power(struct fb_info *info, int power)
-{
-	mutex_lock(&info->bl_mutex);
-
-	if (info->bl_dev) {
-		down(&info->bl_dev->sem);
-		info->bl_dev->props->power = power;
-		__nvidia_bl_update_status(info->bl_dev);
-		up(&info->bl_dev->sem);
-	}
-
-	mutex_unlock(&info->bl_mutex);
-}
-
 void nvidia_bl_init(struct nvidia_par *par)
 {
 	struct fb_info *info = pci_get_drvdata(par->pci_dev);
@@ -141,32 +106,22 @@
 
 	snprintf(name, sizeof(name), "nvidiabl%d", info->node);
 
-	bd = backlight_device_register(name, info->dev, par, &nvidia_bl_data);
+	bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops);
 	if (IS_ERR(bd)) {
 		info->bl_dev = NULL;
 		printk(KERN_WARNING "nvidia: Backlight registration failed\n");
 		goto error;
 	}
 
-	mutex_lock(&info->bl_mutex);
 	info->bl_dev = bd;
 	fb_bl_default_curve(info, 0,
 		0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
 		0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
-	mutex_unlock(&info->bl_mutex);
 
-	down(&bd->sem);
-	bd->props->brightness = nvidia_bl_data.max_brightness;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd->props.brightness = nvidia_bl_data.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("nvidia: Backlight initialized (%s)\n", name);
 
@@ -179,25 +134,8 @@
 void nvidia_bl_exit(struct nvidia_par *par)
 {
 	struct fb_info *info = pci_get_drvdata(par->pci_dev);
+	struct backlight_device *bd = info->bl_dev;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-#endif
-
-	mutex_lock(&info->bl_mutex);
-	if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-		if (pmac_backlight == info->bl_dev)
-			pmac_backlight = NULL;
-#endif
-
-		backlight_device_unregister(info->bl_dev);
-
-		printk("nvidia: Backlight unloaded\n");
-	}
-	mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	backlight_device_unregister(bd);
+	printk("nvidia: Backlight unloaded\n");
 }
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 8454adf..b858897 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
index 181875f..163a774 100644
--- a/drivers/video/nvidia/nv_of.c
+++ b/drivers/video/nvidia/nv_of.c
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 43058d0..ff5c410 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -67,11 +67,9 @@
 #ifdef CONFIG_FB_NVIDIA_BACKLIGHT
 extern void nvidia_bl_init(struct nvidia_par *par);
 extern void nvidia_bl_exit(struct nvidia_par *par);
-extern void nvidia_bl_set_power(struct fb_info *info, int power);
 #else
 static inline void nvidia_bl_init(struct nvidia_par *par) {}
 static inline void nvidia_bl_exit(struct nvidia_par *par) {}
-static inline void nvidia_bl_set_power(struct fb_info *info, int power) {}
 #endif
 
 #endif				/* __NV_PROTO_H__ */
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 538e947..c18e955 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -829,7 +829,7 @@
 	}
 
 	if (!mode_valid) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -938,8 +938,6 @@
 	NVWriteSeq(par, 0x01, tmp);
 	NVWriteCrtc(par, 0x1a, vesa);
 
-	nvidia_bl_set_power(info, blank);
-
 	NVTRACE_LEAVE();
 
 	return 0;
@@ -1046,10 +1044,10 @@
 	}
 
 	if (specs->modedb != NULL) {
-		struct fb_videomode *modedb;
+		const struct fb_videomode *mode;
 
-		modedb = fb_find_best_display(specs, &info->modelist);
-		fb_videomode_to_var(&nvidiafb_default_var, modedb);
+		mode = fb_find_best_display(specs, &info->modelist);
+		fb_videomode_to_var(&nvidiafb_default_var, mode);
 		nvidiafb_default_var.bits_per_pixel = bpp;
 	} else if (par->fpWidth && par->fpHeight) {
 		char buf[16];
@@ -1205,13 +1203,11 @@
 	par = info->par;
 	par->pci_dev = pd;
 
-	info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
+	info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
 
 	if (info->pixmap.addr == NULL)
 		goto err_out_kfree;
 
-	memset(info->pixmap.addr, 0, 8 * 1024);
-
 	if (pci_enable_device(pd)) {
 		printk(KERN_ERR PFX "cannot enable PCI device\n");
 		goto err_out_enable;
@@ -1347,16 +1343,17 @@
 	return -ENODEV;
 }
 
-static void __exit nvidiafb_remove(struct pci_dev *pd)
+static void __devexit nvidiafb_remove(struct pci_dev *pd)
 {
 	struct fb_info *info = pci_get_drvdata(pd);
 	struct nvidia_par *par = info->par;
 
 	NVTRACE_ENTER();
 
+	unregister_framebuffer(info);
+
 	nvidia_bl_exit(par);
 
-	unregister_framebuffer(info);
 #ifdef CONFIG_MTRR
 	if (par->mtrr.vram_valid)
 		mtrr_del(par->mtrr.vram, info->fix.smem_start,
@@ -1433,7 +1430,7 @@
 	.probe    = nvidiafb_probe,
 	.suspend  = nvidiafb_suspend,
 	.resume   = nvidiafb_resume,
-	.remove   = __exit_p(nvidiafb_remove),
+	.remove   = __devexit_p(nvidiafb_remove),
 };
 
 /* ------------------------------------------------------------------------- *
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 1d81ef4..bd787e8 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -3299,14 +3299,12 @@
 		fb_info[i].dev = NULL;
 	}
 
-	dev =
-	    pci_find_device(PCI_VENDOR_ID_3DLABS,
+	dev = pci_get_device(PCI_VENDOR_ID_3DLABS,
 			    PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev);
 
 	for (i = 0; ((i < PM3_MAX_BOARD) && dev); i++) {
 		dev_array[i] = dev;
-		dev =
-		    pci_find_device(PCI_VENDOR_ID_3DLABS,
+		dev = pci_get_device(PCI_VENDOR_ID_3DLABS,
 				    PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev);
 	}
 
@@ -3353,7 +3351,7 @@
 	/* now, initialize... or not */
 	for (i = 0; i < PM3_MAX_BOARD; i++) {
 		l_fb_info = &(fb_info[i]);
-		if ((l_fb_info->dev) && (!disable[i])) {	/* PCI device was found and not disabled by user */
+		if (l_fb_info->dev && !disable[i]) {	/* PCI device was found and not disabled by user */
 			DPRINTK(2,
 				"found @%lx Vendor %lx Device %lx ; base @ : %lx - %lx - %lx - %lx - %lx - %lx, irq %ld\n",
 				(unsigned long) l_fb_info->dev,
@@ -3608,7 +3606,7 @@
 
 	pm3fb_init();
 
-	return (0);
+	return 0;
 }
 
 void cleanup_module(void)
@@ -3619,23 +3617,18 @@
 		struct pm3fb_info *l_fb_info;
 		for (i = 0; i < PM3_MAX_BOARD; i++) {
 			l_fb_info = &(fb_info[i]);
-			if ((l_fb_info->dev != NULL)
-			    && (!(disable[l_fb_info->board_num]))) {
-				if (l_fb_info->vIOBase !=
-				    (unsigned char *) -1) {
+			pci_dev_put(l_fb_info->dev);
+			if (l_fb_info->dev != NULL  && !(disable[l_fb_info->board_num])) {
+				if (l_fb_info->vIOBase != (unsigned char *) -1) {
 					pm3fb_unmapIO(l_fb_info);
 					release_mem_region(l_fb_info->p_fb,
-							   l_fb_info->
-							   fb_size);
-					release_mem_region(l_fb_info->
-							   pIOBase,
-							   PM3_REGS_SIZE);
+						   l_fb_info->fb_size);
+					release_mem_region(l_fb_info->pIOBase,
+						   PM3_REGS_SIZE);
 				}
-				unregister_framebuffer(&l_fb_info->gen.
-						       info);
+				unregister_framebuffer(&l_fb_info->gen.info);
 			}
 		}
 	}
-	return;
 }
 #endif /* MODULE */
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c
index 68ca3cc..a864438 100644
--- a/drivers/video/pmag-aa-fb.c
+++ b/drivers/video/pmag-aa-fb.c
@@ -24,7 +24,6 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/timer.h>
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index f5361cd..264d372 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -15,7 +15,8 @@
  *	Michael Engel <engel@unix-ag.org>,
  *	Karsten Merker <merker@linuxtag.org> and
  *	Harald Koerfgen.
- *	Copyright (c) 2005  Maciej W. Rozycki
+ *	Copyright (c) 2005, 2006  Maciej W. Rozycki
+ *	Copyright (c) 2005  James Simmons
  *
  *	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
@@ -28,26 +29,21 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/tc.h>
 #include <linux/types.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <asm/dec/tc.h>
-
 #include <video/pmag-ba-fb.h>
 
 
 struct pmagbafb_par {
-	struct fb_info *next;
 	volatile void __iomem *mmio;
 	volatile u32 __iomem *dac;
-	int slot;
 };
 
 
-static struct fb_info *root_pmagbafb_dev;
-
 static struct fb_var_screeninfo pmagbafb_defined __initdata = {
 	.xres		= 1024,
 	.yres		= 864,
@@ -145,24 +141,19 @@
 }
 
 
-static int __init pmagbafb_init_one(int slot)
+static int __init pmagbafb_probe(struct device *dev)
 {
+	struct tc_dev *tdev = to_tc_dev(dev);
+	resource_size_t start, len;
 	struct fb_info *info;
 	struct pmagbafb_par *par;
-	unsigned long base_addr;
 
-	info = framebuffer_alloc(sizeof(struct pmagbafb_par), NULL);
+	info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev);
 	if (!info)
 		return -ENOMEM;
 
 	par = info->par;
-	par->slot = slot;
-	claim_tc_card(par->slot);
-
-	base_addr = get_tc_base_addr(par->slot);
-
-	par->next = root_pmagbafb_dev;
-	root_pmagbafb_dev = info;
+	dev_set_drvdata(dev, info);
 
 	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
 		goto err_alloc;
@@ -172,15 +163,21 @@
 	info->var = pmagbafb_defined;
 	info->flags = FBINFO_DEFAULT;
 
+	/* Request the I/O MEM resource.  */
+	start = tdev->resource.start;
+	len = tdev->resource.end - start + 1;
+	if (!request_mem_region(start, len, dev->bus_id))
+		goto err_cmap;
+
 	/* MMIO mapping setup.  */
-	info->fix.mmio_start = base_addr;
+	info->fix.mmio_start = start;
 	par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
 	if (!par->mmio)
-		goto err_cmap;
+		goto err_resource;
 	par->dac = par->mmio + PMAG_BA_BT459;
 
 	/* Frame buffer mapping setup.  */
-	info->fix.smem_start = base_addr + PMAG_BA_FBMEM;
+	info->fix.smem_start = start + PMAG_BA_FBMEM;
 	info->screen_base = ioremap_nocache(info->fix.smem_start,
 					    info->fix.smem_len);
 	if (!info->screen_base)
@@ -192,8 +189,10 @@
 	if (register_framebuffer(info) < 0)
 		goto err_smem_map;
 
-	pr_info("fb%d: %s frame buffer device in slot %d\n",
-		info->node, info->fix.id, par->slot);
+	get_device(dev);
+
+	pr_info("fb%d: %s frame buffer device at %s\n",
+		info->node, info->fix.id, dev->bus_id);
 
 	return 0;
 
@@ -204,54 +203,68 @@
 err_mmio_map:
 	iounmap(par->mmio);
 
+err_resource:
+	release_mem_region(start, len);
+
 err_cmap:
 	fb_dealloc_cmap(&info->cmap);
 
 err_alloc:
-	root_pmagbafb_dev = par->next;
-	release_tc_card(par->slot);
 	framebuffer_release(info);
 	return -ENXIO;
 }
 
-static void __exit pmagbafb_exit_one(void)
+static int __exit pmagbafb_remove(struct device *dev)
 {
-	struct fb_info *info = root_pmagbafb_dev;
+	struct tc_dev *tdev = to_tc_dev(dev);
+	struct fb_info *info = dev_get_drvdata(dev);
 	struct pmagbafb_par *par = info->par;
+	resource_size_t start, len;
 
+	put_device(dev);
 	unregister_framebuffer(info);
 	iounmap(info->screen_base);
 	iounmap(par->mmio);
+	start = tdev->resource.start;
+	len = tdev->resource.end - start + 1;
+	release_mem_region(start, len);
 	fb_dealloc_cmap(&info->cmap);
-	root_pmagbafb_dev = par->next;
-	release_tc_card(par->slot);
 	framebuffer_release(info);
+	return 0;
 }
 
 
 /*
- * Initialise the framebuffer.
+ * Initialize the framebuffer.
  */
+static const struct tc_device_id pmagbafb_tc_table[] = {
+	{ "DEC     ", "PMAG-BA " },
+	{ }
+};
+MODULE_DEVICE_TABLE(tc, pmagbafb_tc_table);
+
+static struct tc_driver pmagbafb_driver = {
+	.id_table	= pmagbafb_tc_table,
+	.driver		= {
+		.name	= "pmagbafb",
+		.bus	= &tc_bus_type,
+		.probe	= pmagbafb_probe,
+		.remove	= __exit_p(pmagbafb_remove),
+	},
+};
+
 static int __init pmagbafb_init(void)
 {
-	int count = 0;
-	int slot;
-
+#ifndef MODULE
 	if (fb_get_options("pmagbafb", NULL))
 		return -ENXIO;
-
-	while ((slot = search_tc_card("PMAG-BA")) >= 0) {
-		if (pmagbafb_init_one(slot) < 0)
-			break;
-		count++;
-	}
-	return (count > 0) ? 0 : -ENXIO;
+#endif
+	return tc_register_driver(&pmagbafb_driver);
 }
 
 static void __exit pmagbafb_exit(void)
 {
-	while (root_pmagbafb_dev)
-		pmagbafb_exit_one();
+	tc_unregister_driver(&pmagbafb_driver);
 }
 
 
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index a06a064..7a0ce7d 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -11,7 +11,7 @@
  *	Michael Engel <engel@unix-ag.org>,
  *	Karsten Merker <merker@linuxtag.org> and
  *	Harald Koerfgen.
- *	Copyright (c) 2005  Maciej W. Rozycki
+ *	Copyright (c) 2005, 2006  Maciej W. Rozycki
  *
  *	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
@@ -25,18 +25,16 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/tc.h>
 #include <linux/types.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <asm/dec/tc.h>
-
 #include <video/pmagb-b-fb.h>
 
 
 struct pmagbbfb_par {
-	struct fb_info *next;
 	volatile void __iomem *mmio;
 	volatile void __iomem *smem;
 	volatile u32 __iomem *sfb;
@@ -47,8 +45,6 @@
 };
 
 
-static struct fb_info *root_pmagbbfb_dev;
-
 static struct fb_var_screeninfo pmagbbfb_defined __initdata = {
 	.bits_per_pixel	= 8,
 	.red.length	= 8,
@@ -190,8 +186,9 @@
 		69197, 66000, 65000, 50350, 36000, 32000, 25175
 	};
 	struct pmagbbfb_par *par = info->par;
+	struct tc_bus *tbus = to_tc_dev(info->device)->bus;
 	u32 count0 = 8, count1 = 8, counttc = 16 * 256 + 8;
-	u32 freq0, freq1, freqtc = get_tc_speed() / 250;
+	u32 freq0, freq1, freqtc = tc_get_speed(tbus) / 250;
 	int i, j;
 
 	gp0_write(par, 0);				/* select Osc0 */
@@ -249,26 +246,21 @@
 };
 
 
-static int __init pmagbbfb_init_one(int slot)
+static int __init pmagbbfb_probe(struct device *dev)
 {
-	char freq0[12], freq1[12];
+	struct tc_dev *tdev = to_tc_dev(dev);
+	resource_size_t start, len;
 	struct fb_info *info;
 	struct pmagbbfb_par *par;
-	unsigned long base_addr;
+	char freq0[12], freq1[12];
 	u32 vid_base;
 
-	info = framebuffer_alloc(sizeof(struct pmagbbfb_par), NULL);
+	info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev);
 	if (!info)
 		return -ENOMEM;
 
 	par = info->par;
-	par->slot = slot;
-	claim_tc_card(par->slot);
-
-	base_addr = get_tc_base_addr(par->slot);
-
-	par->next = root_pmagbbfb_dev;
-	root_pmagbbfb_dev = info;
+	dev_set_drvdata(dev, info);
 
 	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
 		goto err_alloc;
@@ -278,16 +270,22 @@
 	info->var = pmagbbfb_defined;
 	info->flags = FBINFO_DEFAULT;
 
+	/* Request the I/O MEM resource.  */
+	start = tdev->resource.start;
+	len = tdev->resource.end - start + 1;
+	if (!request_mem_region(start, len, dev->bus_id))
+		goto err_cmap;
+
 	/* MMIO mapping setup.  */
-	info->fix.mmio_start = base_addr;
+	info->fix.mmio_start = start;
 	par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
 	if (!par->mmio)
-		goto err_cmap;
+		goto err_resource;
 	par->sfb = par->mmio + PMAGB_B_SFB;
 	par->dac = par->mmio + PMAGB_B_BT459;
 
 	/* Frame buffer mapping setup.  */
-	info->fix.smem_start = base_addr + PMAGB_B_FBMEM;
+	info->fix.smem_start = start + PMAGB_B_FBMEM;
 	par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
 	if (!par->smem)
 		goto err_mmio_map;
@@ -302,13 +300,15 @@
 	if (register_framebuffer(info) < 0)
 		goto err_smem_map;
 
+	get_device(dev);
+
 	snprintf(freq0, sizeof(freq0), "%u.%03uMHz",
 		 par->osc0 / 1000, par->osc0 % 1000);
 	snprintf(freq1, sizeof(freq1), "%u.%03uMHz",
 		 par->osc1 / 1000, par->osc1 % 1000);
 
-	pr_info("fb%d: %s frame buffer device in slot %d\n",
-		info->node, info->fix.id, par->slot);
+	pr_info("fb%d: %s frame buffer device at %s\n",
+		info->node, info->fix.id, dev->bus_id);
 	pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected\n",
 		info->node, freq0, par->osc1 ? freq1 : "disabled",
 		par->osc1 != 0);
@@ -322,54 +322,68 @@
 err_mmio_map:
 	iounmap(par->mmio);
 
+err_resource:
+	release_mem_region(start, len);
+
 err_cmap:
 	fb_dealloc_cmap(&info->cmap);
 
 err_alloc:
-	root_pmagbbfb_dev = par->next;
-	release_tc_card(par->slot);
 	framebuffer_release(info);
 	return -ENXIO;
 }
 
-static void __exit pmagbbfb_exit_one(void)
+static int __exit pmagbbfb_remove(struct device *dev)
 {
-	struct fb_info *info = root_pmagbbfb_dev;
+	struct tc_dev *tdev = to_tc_dev(dev);
+	struct fb_info *info = dev_get_drvdata(dev);
 	struct pmagbbfb_par *par = info->par;
+	resource_size_t start, len;
 
+	put_device(dev);
 	unregister_framebuffer(info);
 	iounmap(par->smem);
 	iounmap(par->mmio);
+	start = tdev->resource.start;
+	len = tdev->resource.end - start + 1;
+	release_mem_region(start, len);
 	fb_dealloc_cmap(&info->cmap);
-	root_pmagbbfb_dev = par->next;
-	release_tc_card(par->slot);
 	framebuffer_release(info);
+	return 0;
 }
 
 
 /*
- * Initialise the framebuffer.
+ * Initialize the framebuffer.
  */
+static const struct tc_device_id pmagbbfb_tc_table[] = {
+	{ "DEC     ", "PMAGB-BA" },
+	{ }
+};
+MODULE_DEVICE_TABLE(tc, pmagbbfb_tc_table);
+
+static struct tc_driver pmagbbfb_driver = {
+	.id_table	= pmagbbfb_tc_table,
+	.driver		= {
+		.name	= "pmagbbfb",
+		.bus	= &tc_bus_type,
+		.probe	= pmagbbfb_probe,
+		.remove	= __exit_p(pmagbbfb_remove),
+	},
+};
+
 static int __init pmagbbfb_init(void)
 {
-	int count = 0;
-	int slot;
-
+#ifndef MODULE
 	if (fb_get_options("pmagbbfb", NULL))
 		return -ENXIO;
-
-	while ((slot = search_tc_card("PMAGB-BA")) >= 0) {
-		if (pmagbbfb_init_one(slot) < 0)
-			break;
-		count++;
-	}
-	return (count > 0) ? 0 : -ENXIO;
+#endif
+	return tc_register_driver(&pmagbbfb_driver);
 }
 
 static void __exit pmagbbfb_exit(void)
 {
-	while (root_pmagbbfb_dev)
-		pmagbbfb_exit_one();
+	tc_unregister_driver(&pmagbbfb_driver);
 }
 
 
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
new file mode 100644
index 0000000..81e43cd
--- /dev/null
+++ b/drivers/video/ps3fb.c
@@ -0,0 +1,1229 @@
+/*
+ *  linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device
+ *
+ *	Copyright (C) 2006 Sony Computer Entertainment Inc.
+ *	Copyright 2006, 2007 Sony Corporation
+ *
+ *  This file is based on :
+ *
+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
+ *
+ *	Copyright (C) 2002 James Simmons
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/console.h>
+#include <linux/ioctl.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/uaccess.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <asm/time.h>
+
+#include <asm/abs_addr.h>
+#include <asm/lv1call.h>
+#include <asm/ps3av.h>
+#include <asm/ps3fb.h>
+#include <asm/ps3.h>
+
+#ifdef PS3FB_DEBUG
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC	0x101
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP	0x102
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP	0x600
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT		0x601
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT_SYNC	0x602
+
+#define L1GPU_FB_BLIT_WAIT_FOR_COMPLETION	(1ULL << 32)
+
+#define L1GPU_DISPLAY_SYNC_HSYNC		1
+#define L1GPU_DISPLAY_SYNC_VSYNC		2
+
+#define DDR_SIZE				(0)	/* used no ddr */
+#define GPU_OFFSET				(64 * 1024)
+#define GPU_IOIF				(0x0d000000UL)
+
+#define PS3FB_FULL_MODE_BIT			0x80
+
+#define GPU_INTR_STATUS_VSYNC_0			0	/* vsync on head A */
+#define GPU_INTR_STATUS_VSYNC_1			1	/* vsync on head B */
+#define GPU_INTR_STATUS_FLIP_0			3	/* flip head A */
+#define GPU_INTR_STATUS_FLIP_1			4	/* flip head B */
+#define GPU_INTR_STATUS_QUEUE_0			5	/* queue head A */
+#define GPU_INTR_STATUS_QUEUE_1			6	/* queue head B */
+
+#define GPU_DRIVER_INFO_VERSION			0x211
+
+/* gpu internals */
+struct display_head {
+	u64 be_time_stamp;
+	u32 status;
+	u32 offset;
+	u32 res1;
+	u32 res2;
+	u32 field;
+	u32 reserved1;
+
+	u64 res3;
+	u32 raster;
+
+	u64 vblank_count;
+	u32 field_vsync;
+	u32 reserved2;
+};
+
+struct gpu_irq {
+	u32 irq_outlet;
+	u32 status;
+	u32 mask;
+	u32 video_cause;
+	u32 graph_cause;
+	u32 user_cause;
+
+	u32 res1;
+	u64 res2;
+
+	u32 reserved[4];
+};
+
+struct gpu_driver_info {
+	u32 version_driver;
+	u32 version_gpu;
+	u32 memory_size;
+	u32 hardware_channel;
+
+	u32 nvcore_frequency;
+	u32 memory_frequency;
+
+	u32 reserved[1063];
+	struct display_head display_head[8];
+	struct gpu_irq irq;
+};
+
+struct ps3fb_priv {
+	unsigned int irq_no;
+	void *dev;
+
+	u64 context_handle, memory_handle;
+	void *xdr_ea;
+	struct gpu_driver_info *dinfo;
+	struct semaphore sem;
+	u32 res_index;
+
+	u64 vblank_count;	/* frame count */
+	wait_queue_head_t wait_vsync;
+
+	u32 num_frames;		/* num of frame buffers */
+	atomic_t ext_flip;	/* on/off flip with vsync */
+	atomic_t f_count;	/* fb_open count */
+	int is_blanked;
+};
+static struct ps3fb_priv ps3fb;
+
+struct ps3fb_res_table {
+	u32 xres;
+	u32 yres;
+	u32 xoff;
+	u32 yoff;
+	u32 type;
+};
+#define PS3FB_RES_FULL 1
+static const struct ps3fb_res_table ps3fb_res[] = {
+	/* res_x,y   margin_x,y  full */
+	{  720,  480,  72,  48 , 0},
+	{  720,  576,  72,  58 , 0},
+	{ 1280,  720,  78,  38 , 0},
+	{ 1920, 1080, 116,  58 , 0},
+	/* full mode */
+	{  720,  480,   0,   0 , PS3FB_RES_FULL},
+	{  720,  576,   0,   0 , PS3FB_RES_FULL},
+	{ 1280,  720,   0,   0 , PS3FB_RES_FULL},
+	{ 1920, 1080,   0,   0 , PS3FB_RES_FULL},
+	/* vesa: normally full mode */
+	{ 1280,  768,   0,   0 , 0},
+	{ 1280, 1024,   0,   0 , 0},
+	{ 1920, 1200,   0,   0 , 0},
+	{    0,    0,   0,   0 , 0} };
+
+/* default resolution */
+#define GPU_RES_INDEX 0		/* 720 x 480 */
+
+static const struct fb_videomode ps3fb_modedb[] = {
+    /* 60 Hz broadcast modes (modes "1" to "5") */
+    {
+        /* 480i */
+        "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 480p */
+        "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 720p */
+        "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 1080i */
+        "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 1080p */
+        "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* 50 Hz broadcast modes (modes "6" to "10") */
+    {
+        /* 576i */
+        "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 576p */
+        "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 720p */
+        "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 1080 */
+        "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 1080p */
+        "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* VESA modes (modes "11" to "13") */
+    {
+	/* WXGA */
+	"wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* SXGA */
+	"sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* WUXGA */
+	"wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
+	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    },
+
+    /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */
+    {
+	/* 480if */
+	"480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 480pf */
+	"480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 720pf */
+	"720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1080if */
+	"1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 1080pf */
+	"1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* 50 Hz broadcast modes (full resolution versions of modes "6" to "10") */
+    {
+	/* 576if */
+	"576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 576pf */
+	"576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 720pf */
+	"720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1080if */
+	"1080f", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 1080pf */
+	"1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }
+};
+
+
+#define HEAD_A
+#define HEAD_B
+
+#define X_OFF(i)	(ps3fb_res[i].xoff)	/* left/right margin (pixel) */
+#define Y_OFF(i)	(ps3fb_res[i].yoff)	/* top/bottom margin (pixel) */
+#define WIDTH(i)	(ps3fb_res[i].xres)	/* width of FB */
+#define HEIGHT(i)	(ps3fb_res[i].yres)	/* height of FB */
+#define BPP	4		/* number of bytes per pixel */
+#define VP_OFF(i)	(WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP)
+#define FB_OFF(i)	(GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
+
+static int ps3fb_mode = 0;
+module_param(ps3fb_mode, bool, 0);
+
+static char *mode_option __initdata = NULL;
+
+
+static int ps3fb_get_res_table(u32 xres, u32 yres)
+{
+	int full_mode;
+	unsigned int i;
+	u32 x, y, f;
+
+	full_mode = (ps3fb_mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0;
+	for (i = 0;; i++) {
+		x = ps3fb_res[i].xres;
+		y = ps3fb_res[i].yres;
+		f = ps3fb_res[i].type;
+
+		if (!x) {
+			DPRINTK("ERROR: ps3fb_get_res_table()\n");
+			return -1;
+		}
+
+		if (full_mode == PS3FB_RES_FULL && f != PS3FB_RES_FULL)
+			continue;
+
+		if (x == xres && (yres == 0 || y == yres))
+			break;
+
+		x = x - 2 * ps3fb_res[i].xoff;
+		y = y - 2 * ps3fb_res[i].yoff;
+		if (x == xres && (yres == 0 || y == yres))
+			break;
+	}
+	return i;
+}
+
+static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var,
+				    u32 *line_length)
+{
+	unsigned int i, mode;
+
+	for (i = 0; i < ARRAY_SIZE(ps3fb_modedb); i++)
+		if (var->xres == ps3fb_modedb[i].xres &&
+		    var->yres == ps3fb_modedb[i].yres &&
+		    var->pixclock == ps3fb_modedb[i].pixclock &&
+		    var->hsync_len == ps3fb_modedb[i].hsync_len &&
+		    var->vsync_len == ps3fb_modedb[i].vsync_len &&
+		    var->left_margin == ps3fb_modedb[i].left_margin &&
+		    var->right_margin == ps3fb_modedb[i].right_margin &&
+		    var->upper_margin == ps3fb_modedb[i].upper_margin &&
+		    var->lower_margin == ps3fb_modedb[i].lower_margin &&
+		    var->sync == ps3fb_modedb[i].sync &&
+		    (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode) {
+			/* Cropped broadcast modes use the full line_length */
+			*line_length =
+			    ps3fb_modedb[i < 10 ? i + 13 : i].xres * 4;
+			/* Full broadcast modes have the full mode bit set */
+			mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;
+
+			DPRINTK("ps3fb_find_mode: mode %u\n", mode);
+			return mode;
+		}
+
+	DPRINTK("ps3fb_find_mode: mode not found\n");
+	return 0;
+
+}
+
+static const struct fb_videomode *ps3fb_default_mode(void)
+{
+	u32 mode = ps3fb_mode & PS3AV_MODE_MASK;
+	u32 flags;
+
+	if (mode < 1 || mode > 13)
+		return NULL;
+
+	flags = ps3fb_mode & ~PS3AV_MODE_MASK;
+
+	if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) {
+		/* Full broadcast mode */
+		return &ps3fb_modedb[mode + 12];
+	}
+
+	return &ps3fb_modedb[mode - 1];
+}
+
+static int ps3fb_sync(u32 frame)
+{
+	int i, status;
+	u32 xres, yres;
+	u64 fb_ioif, offset;
+
+	i = ps3fb.res_index;
+	xres = ps3fb_res[i].xres;
+	yres = ps3fb_res[i].yres;
+
+	if (frame > ps3fb.num_frames - 1) {
+		printk(KERN_WARNING "%s: invalid frame number (%u)\n",
+		       __FUNCTION__, frame);
+		return -EINVAL;
+	}
+	offset = xres * yres * BPP * frame;
+
+	fb_ioif = GPU_IOIF + FB_OFF(i) + offset;
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
+					   offset, fb_ioif,
+					   L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |
+					   (xres << 16) | yres,
+					   xres * BPP);	/* line_length */
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
+		       __FUNCTION__, status);
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
+					   0, offset, 0, 0);
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		       __FUNCTION__, status);
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
+					   1, offset, 0, 0);
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		       __FUNCTION__, status);
+#endif
+	return 0;
+}
+
+
+static int ps3fb_open(struct fb_info *info, int user)
+{
+	atomic_inc(&ps3fb.f_count);
+	return 0;
+}
+
+static int ps3fb_release(struct fb_info *info, int user)
+{
+	if (atomic_dec_and_test(&ps3fb.f_count)) {
+		if (atomic_read(&ps3fb.ext_flip)) {
+			atomic_set(&ps3fb.ext_flip, 0);
+			ps3fb_sync(0);	/* single buffer */
+		}
+	}
+	return 0;
+}
+
+    /*
+     *  Setting the video mode has been split into two parts.
+     *  First part, xxxfb_check_var, must not write anything
+     *  to hardware, it should only verify and adjust var.
+     *  This means it doesn't alter par but it does use hardware
+     *  data from it to check this var.
+     */
+
+static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u32 line_length;
+	int mode;
+	int i;
+
+	DPRINTK("var->xres:%u info->var.xres:%u\n", var->xres, info->var.xres);
+	DPRINTK("var->yres:%u info->var.yres:%u\n", var->yres, info->var.yres);
+
+	/* FIXME For now we do exact matches only */
+	mode = ps3fb_find_mode(var, &line_length);
+	if (!mode)
+		return -EINVAL;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/* Virtual screen and panning are not supported */
+	if (var->xres_virtual > var->xres || var->yres_virtual > var->yres ||
+	    var->xoffset || var->yoffset) {
+		DPRINTK("Virtual screen and panning are not supported\n");
+		return -EINVAL;
+	}
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	/* We support ARGB8888 only */
+	if (var->bits_per_pixel > 32 || var->grayscale ||
+	    var->red.offset > 16 || var->green.offset > 8 ||
+	    var->blue.offset > 0 || var->transp.offset > 24 ||
+	    var->red.length > 8 || var->green.length > 8 ||
+	    var->blue.length > 8 || var->transp.length > 8 ||
+	    var->red.msb_right || var->green.msb_right ||
+	    var->blue.msb_right || var->transp.msb_right || var->nonstd) {
+		DPRINTK("We support ARGB8888 only\n");
+		return -EINVAL;
+	}
+
+	var->bits_per_pixel = 32;
+	var->red.offset = 16;
+	var->green.offset = 8;
+	var->blue.offset = 0;
+	var->transp.offset = 24;
+	var->red.length = 8;
+	var->green.length = 8;
+	var->blue.length = 8;
+	var->transp.length = 8;
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	/* Rotation is not supported */
+	if (var->rotate) {
+		DPRINTK("Rotation is not supported\n");
+		return -EINVAL;
+	}
+
+	/* Memory limit */
+	i = ps3fb_get_res_table(var->xres, var->yres);
+	if (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP > ps3fb_videomemory.size) {
+		DPRINTK("Not enough memory\n");
+		return -ENOMEM;
+	}
+
+	var->height = -1;
+	var->width = -1;
+
+	return 0;
+}
+
+    /*
+     * This routine actually sets the video mode.
+     */
+
+static int ps3fb_set_par(struct fb_info *info)
+{
+	unsigned int mode;
+	int i;
+	unsigned long offset;
+	static int first = 1;
+
+	DPRINTK("xres:%d xv:%d yres:%d yv:%d clock:%d\n",
+		info->var.xres, info->var.xres_virtual,
+		info->var.yres, info->var.yres_virtual, info->var.pixclock);
+	i = ps3fb_get_res_table(info->var.xres, info->var.yres);
+	ps3fb.res_index = i;
+
+	mode = ps3fb_find_mode(&info->var, &info->fix.line_length);
+	if (!mode)
+		return -EINVAL;
+
+	offset = FB_OFF(i) + VP_OFF(i);
+	info->fix.smem_len = ps3fb_videomemory.size - offset;
+	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
+	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
+
+	ps3fb.num_frames = ps3fb_videomemory.size/
+			   (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
+
+	/* Keep the special bits we cannot set using fb_var_screeninfo */
+	ps3fb_mode = (ps3fb_mode & ~PS3AV_MODE_MASK) | mode;
+
+	if (ps3av_set_video_mode(ps3fb_mode, first))
+		return -EINVAL;
+
+	first = 0;
+	return 0;
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int ps3fb_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp, struct fb_info *info)
+{
+	if (regno >= 16)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	transp >>= 8;
+
+	((u32 *)info->pseudo_palette)[regno] = transp << 24 | red << 16 |
+					       green << 8 | blue;
+	return 0;
+}
+
+    /*
+     *  As we have a virtual frame buffer, we need our own mmap function
+     */
+
+static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	unsigned long size, offset;
+	int i;
+
+	i = ps3fb_get_res_table(info->var.xres, info->var.yres);
+	if (i == -1)
+		return -EINVAL;
+
+	size = vma->vm_end - vma->vm_start;
+	offset = vma->vm_pgoff << PAGE_SHIFT;
+	if (offset + size > info->fix.smem_len)
+		return -EINVAL;
+
+	offset += info->fix.smem_start + FB_OFF(i) + VP_OFF(i);
+	if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
+			    size, vma->vm_page_prot))
+		return -EAGAIN;
+
+	printk(KERN_DEBUG "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", offset,
+	       vma->vm_start);
+	return 0;
+}
+
+    /*
+     * Blank the display
+     */
+
+static int ps3fb_blank(int blank, struct fb_info *info)
+{
+	int retval;
+
+	DPRINTK("%s: blank:%d\n", __FUNCTION__, blank);
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		retval = ps3av_video_mute(1);	/* mute on */
+		if (!retval)
+			ps3fb.is_blanked = 1;
+		break;
+
+	default:		/* unblank */
+		retval = ps3av_video_mute(0);	/* mute off */
+		if (!retval)
+			ps3fb.is_blanked = 0;
+		break;
+	}
+	return retval;
+}
+
+static int ps3fb_get_vblank(struct fb_vblank *vblank)
+{
+	memset(vblank, 0, sizeof(&vblank));
+	vblank->flags = FB_VBLANK_HAVE_VSYNC;
+	return 0;
+}
+
+int ps3fb_wait_for_vsync(u32 crtc)
+{
+	int ret;
+	u64 count;
+
+	count = ps3fb.vblank_count;
+	ret = wait_event_interruptible_timeout(ps3fb.wait_vsync,
+					       count != ps3fb.vblank_count,
+					       HZ / 10);
+	if (!ret)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync);
+
+void ps3fb_flip_ctl(int on)
+{
+	if (on) {
+		if (atomic_read(&ps3fb.ext_flip) > 0) {
+			atomic_dec(&ps3fb.ext_flip);
+		}
+	} else {
+		atomic_inc(&ps3fb.ext_flip);
+	}
+}
+
+EXPORT_SYMBOL_GPL(ps3fb_flip_ctl);
+
+    /*
+     * ioctl
+     */
+
+static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	u32 val, old_mode;
+	int retval = -EFAULT;
+
+	switch (cmd) {
+	case FBIOGET_VBLANK:
+		{
+			struct fb_vblank vblank;
+			DPRINTK("FBIOGET_VBLANK:\n");
+			retval = ps3fb_get_vblank(&vblank);
+			if (retval)
+				break;
+
+			if (copy_to_user(argp, &vblank, sizeof(vblank)))
+				retval = -EFAULT;
+			break;
+		}
+
+	case FBIO_WAITFORVSYNC:
+		{
+			u32 crt;
+			DPRINTK("FBIO_WAITFORVSYNC:\n");
+			if (get_user(crt, (u32 __user *) arg))
+				break;
+
+			retval = ps3fb_wait_for_vsync(crt);
+			break;
+		}
+
+	case PS3FB_IOCTL_SETMODE:
+		{
+			const struct fb_videomode *mode;
+			struct fb_var_screeninfo var;
+
+			if (copy_from_user(&val, argp, sizeof(val)))
+				break;
+
+			DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val);
+			retval = -EINVAL;
+			old_mode = ps3fb_mode;
+			ps3fb_mode = val;
+			mode = ps3fb_default_mode();
+			if (mode) {
+				var = info->var;
+				fb_videomode_to_var(&var, mode);
+				acquire_console_sem();
+				info->flags |= FBINFO_MISC_USEREVENT;
+				/* Force, in case only special bits changed */
+				var.activate |= FB_ACTIVATE_FORCE;
+				retval = fb_set_var(info, &var);
+				info->flags &= ~FBINFO_MISC_USEREVENT;
+				release_console_sem();
+			}
+			if (retval)
+				ps3fb_mode = old_mode;
+			break;
+		}
+
+	case PS3FB_IOCTL_GETMODE:
+		val = ps3av_get_mode();
+		DPRINTK("PS3FB_IOCTL_GETMODE:%x\n", val);
+		if (!copy_to_user(argp, &val, sizeof(val)))
+			retval = 0;
+		break;
+
+	case PS3FB_IOCTL_SCREENINFO:
+		{
+			struct ps3fb_ioctl_res res;
+			int i = ps3fb.res_index;
+			DPRINTK("PS3FB_IOCTL_SCREENINFO:\n");
+			res.xres = ps3fb_res[i].xres;
+			res.yres = ps3fb_res[i].yres;
+			res.xoff = ps3fb_res[i].xoff;
+			res.yoff = ps3fb_res[i].yoff;
+			res.num_frames = ps3fb.num_frames;
+			if (!copy_to_user(argp, &res, sizeof(res)))
+				retval = 0;
+			break;
+		}
+
+	case PS3FB_IOCTL_ON:
+		DPRINTK("PS3FB_IOCTL_ON:\n");
+		atomic_inc(&ps3fb.ext_flip);
+		retval = 0;
+		break;
+
+	case PS3FB_IOCTL_OFF:
+		DPRINTK("PS3FB_IOCTL_OFF:\n");
+		if (atomic_read(&ps3fb.ext_flip) > 0)
+			atomic_dec(&ps3fb.ext_flip);
+		retval = 0;
+		break;
+
+	case PS3FB_IOCTL_FSEL:
+		if (copy_from_user(&val, argp, sizeof(val)))
+			break;
+
+		DPRINTK("PS3FB_IOCTL_FSEL:%d\n", val);
+		retval = ps3fb_sync(val);
+		break;
+
+	default:
+		retval = -ENOIOCTLCMD;
+		break;
+	}
+	return retval;
+}
+
+static int ps3fbd(void *arg)
+{
+	daemonize("ps3fbd");
+	for (;;) {
+		down(&ps3fb.sem);
+		if (atomic_read(&ps3fb.ext_flip) == 0)
+			ps3fb_sync(0);	/* single buffer */
+	}
+	return 0;
+}
+
+static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
+{
+	u64 v1;
+	int status;
+	struct display_head *head = &ps3fb.dinfo->display_head[1];
+
+	status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n",
+		       __FUNCTION__, status);
+		return IRQ_NONE;
+	}
+
+	if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
+		/* VSYNC */
+		ps3fb.vblank_count = head->vblank_count;
+		if (!ps3fb.is_blanked)
+			up(&ps3fb.sem);
+		wake_up_interruptible(&ps3fb.wait_vsync);
+	}
+
+	return IRQ_HANDLED;
+}
+
+#ifndef MODULE
+static int __init ps3fb_setup(char *options)
+{
+	char *this_opt;
+	int mode = 0;
+
+	if (!options || !*options)
+		return 0;	/* no options */
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "mode:", 5))
+			mode = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_option = this_opt;
+	}
+	return mode;
+}
+#endif	/* MODULE */
+
+    /*
+     *  Initialisation
+     */
+
+static void ps3fb_platform_release(struct device *device)
+{
+	/* This is called when the reference count goes to zero. */
+}
+
+static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
+{
+	int error;
+
+	DPRINTK("version_driver:%x\n", dinfo->version_driver);
+	DPRINTK("irq outlet:%x\n", dinfo->irq.irq_outlet);
+	DPRINTK("version_gpu:%x memory_size:%x ch:%x core_freq:%d mem_freq:%d\n",
+		dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel,
+		dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000);
+
+	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
+		printk(KERN_ERR "%s: version_driver err:%x\n", __FUNCTION__,
+		       dinfo->version_driver);
+		return -EINVAL;
+	}
+
+	ps3fb.dev = dev;
+	error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
+			      &ps3fb.irq_no);
+	if (error) {
+		printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__,
+		       error);
+		return error;
+	}
+
+	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
+			    "ps3fb vsync", ps3fb.dev);
+	if (error) {
+		printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__,
+		       error);
+		ps3_free_irq(ps3fb.irq_no);
+		return error;
+	}
+
+	dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
+			  (1 << GPU_INTR_STATUS_FLIP_1);
+	return 0;
+}
+
+static int ps3fb_xdr_settings(u64 xdr_lpar)
+{
+	int status;
+
+	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
+				       xdr_lpar, ps3fb_videomemory.size, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n",
+		       __FUNCTION__, status);
+		return -ENXIO;
+	}
+	DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
+		ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar,
+		virt_to_abs(ps3fb.xdr_ea), ps3fb_videomemory.size);
+
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,
+					   xdr_lpar, ps3fb_videomemory.size,
+					   GPU_IOIF, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
+		       __FUNCTION__, status);
+		return -ENXIO;
+	}
+	return 0;
+}
+
+static struct fb_ops ps3fb_ops = {
+	.fb_open	= ps3fb_open,
+	.fb_release	= ps3fb_release,
+	.fb_check_var	= ps3fb_check_var,
+	.fb_set_par	= ps3fb_set_par,
+	.fb_setcolreg	= ps3fb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_mmap	= ps3fb_mmap,
+	.fb_blank	= ps3fb_blank,
+	.fb_ioctl	= ps3fb_ioctl,
+	.fb_compat_ioctl = ps3fb_ioctl
+};
+
+static struct fb_fix_screeninfo ps3fb_fix __initdata = {
+	.id =		"PS3 FB",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static int __init ps3fb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int retval = -ENOMEM;
+	u64 ddr_lpar = 0;
+	u64 lpar_dma_control = 0;
+	u64 lpar_driver_info = 0;
+	u64 lpar_reports = 0;
+	u64 lpar_reports_size = 0;
+	u64 xdr_lpar;
+	int status;
+	unsigned long offset;
+
+	/* get gpu context handle */
+	status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
+					 &ps3fb.memory_handle, &ddr_lpar);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n",
+		       __FUNCTION__, status);
+		goto err;
+	}
+	DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar);
+
+	status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
+					  &ps3fb.context_handle,
+					  &lpar_dma_control, &lpar_driver_info,
+					  &lpar_reports, &lpar_reports_size);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n",
+		       __FUNCTION__, status);
+		goto err_gpu_memory_free;
+	}
+
+	/* vsync interrupt */
+	ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024);
+	if (!ps3fb.dinfo) {
+		printk(KERN_ERR "%s: ioremap failed\n", __FUNCTION__);
+		goto err_gpu_context_free;
+	}
+
+	retval = ps3fb_vsync_settings(ps3fb.dinfo, dev);
+	if (retval)
+		goto err_iounmap_dinfo;
+
+	/* xdr frame buffer */
+	ps3fb.xdr_ea = ps3fb_videomemory.address;
+	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea));
+	retval = ps3fb_xdr_settings(xdr_lpar);
+	if (retval)
+		goto err_free_irq;
+
+	/*
+	 * ps3fb must clear memory to prevent kernel info
+	 * leakage into userspace
+	 */
+	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	if (!info)
+		goto err_free_irq;
+
+	offset = FB_OFF(ps3fb.res_index) + VP_OFF(ps3fb.res_index);
+	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
+	info->fbops = &ps3fb_ops;
+
+	info->fix = ps3fb_fix;
+	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
+	info->fix.smem_len = ps3fb_videomemory.size - offset;
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err_framebuffer_release;
+
+	if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
+			  ARRAY_SIZE(ps3fb_modedb), ps3fb_default_mode(), 32)) {
+		retval = -EINVAL;
+		goto err_fb_dealloc;
+	}
+
+	fb_videomode_to_modelist(ps3fb_modedb, ARRAY_SIZE(ps3fb_modedb),
+				 &info->modelist);
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_fb_dealloc;
+
+	platform_set_drvdata(dev, info);
+
+	printk(KERN_INFO
+	       "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
+	       info->node, ps3fb_videomemory.size >> 10);
+
+	kernel_thread(ps3fbd, info, CLONE_KERNEL);
+	return 0;
+
+err_fb_dealloc:
+	fb_dealloc_cmap(&info->cmap);
+err_framebuffer_release:
+	framebuffer_release(info);
+err_free_irq:
+	free_irq(ps3fb.irq_no, ps3fb.dev);
+	ps3_free_irq(ps3fb.irq_no);
+err_iounmap_dinfo:
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+err_gpu_context_free:
+	lv1_gpu_context_free(ps3fb.context_handle);
+err_gpu_memory_free:
+	lv1_gpu_memory_free(ps3fb.memory_handle);
+err:
+	return retval;
+}
+
+static void ps3fb_shutdown(struct platform_device *dev)
+{
+	ps3fb_flip_ctl(0);	/* flip off */
+	ps3fb.dinfo->irq.mask = 0;
+	free_irq(ps3fb.irq_no, ps3fb.dev);
+	ps3_free_irq(ps3fb.irq_no);
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+}
+
+void ps3fb_cleanup(void)
+{
+	int status;
+
+	if (ps3fb.irq_no) {
+		free_irq(ps3fb.irq_no, ps3fb.dev);
+		ps3_free_irq(ps3fb.irq_no);
+	}
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+
+	status = lv1_gpu_context_free(ps3fb.context_handle);
+	if (status)
+		DPRINTK("lv1_gpu_context_free failed: %d\n", status);
+
+	status = lv1_gpu_memory_free(ps3fb.memory_handle);
+	if (status)
+		DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
+
+	ps3av_dev_close();
+}
+
+EXPORT_SYMBOL_GPL(ps3fb_cleanup);
+
+static int ps3fb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	ps3fb_cleanup();
+	return 0;
+}
+
+static struct platform_driver ps3fb_driver = {
+	.probe	= ps3fb_probe,
+	.remove = ps3fb_remove,
+	.shutdown = ps3fb_shutdown,
+	.driver = { .name = "ps3fb" }
+};
+
+static struct platform_device ps3fb_device = {
+	.name	= "ps3fb",
+	.id	= 0,
+	.dev	= { .release = ps3fb_platform_release }
+};
+
+int ps3fb_set_sync(void)
+{
+	int status;
+
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
+		       __FUNCTION__, status);
+		return -1;
+	}
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+		       __FUNCTION__, status);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3fb_set_sync);
+
+static int __init ps3fb_init(void)
+{
+	int error;
+#ifndef MODULE
+	int mode;
+	char *option = NULL;
+
+	if (fb_get_options("ps3fb", &option))
+		goto err;
+#endif
+
+	if (!ps3fb_videomemory.address)
+		goto err;
+
+	error = ps3av_dev_open();
+	if (error) {
+		printk(KERN_ERR "%s: ps3av_dev_open failed\n", __FUNCTION__);
+		goto err;
+	}
+
+	ps3fb_mode = ps3av_get_mode();
+	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+#ifndef MODULE
+	mode = ps3fb_setup(option);	/* check boot option */
+	if (mode)
+		ps3fb_mode = mode;
+#endif
+	if (ps3fb_mode > 0) {
+		u32 xres, yres;
+		ps3av_video_mode2res(ps3fb_mode, &xres, &yres);
+		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
+		DPRINTK("res_index:%d\n", ps3fb.res_index);
+	} else
+		ps3fb.res_index = GPU_RES_INDEX;
+
+	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
+	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
+	init_MUTEX(&ps3fb.sem);
+	init_waitqueue_head(&ps3fb.wait_vsync);
+	ps3fb.num_frames = 1;
+
+	error = platform_driver_register(&ps3fb_driver);
+	if (!error) {
+		error = platform_device_register(&ps3fb_device);
+		if (error)
+			platform_driver_unregister(&ps3fb_driver);
+	}
+
+	ps3fb_set_sync();
+
+	return error;
+
+err:
+	return -ENXIO;
+}
+
+module_init(ps3fb_init);
+
+#ifdef MODULE
+static void __exit ps3fb_exit(void)
+{
+	platform_device_unregister(&ps3fb_device);
+	platform_driver_unregister(&ps3fb_driver);
+}
+
+module_exit(ps3fb_exit);
+
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */
diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c
deleted file mode 100644
index bc7ffc8..0000000
--- a/drivers/video/retz3fb.c
+++ /dev/null
@@ -1,1588 +0,0 @@
-/*
- * Linux/drivers/video/retz3fb.c -- RetinaZ3 frame buffer device
- *
- *    Copyright (C) 1997 Jes Sorensen
- *
- * This file is based on the CyberVision64 frame buffer device and
- * the generic Cirrus Logic driver.
- *
- * cyberfb.c: Copyright (C) 1996 Martin Apel,
- *                               Geert Uytterhoeven
- * clgen.c:   Copyright (C) 1996 Frank Neumann
- *
- * History:
- *   - 22 Jan 97: Initial work
- *   - 14 Feb 97: Screen initialization works somewhat, still only
- *                8-bit packed pixel is supported.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/zorro.h>
-#include <linux/init.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-
-#include "retz3fb.h"
-
-/* #define DEBUG if(1) */
-#define DEBUG if(0)
-
-/*
- * Reserve space for one pattern line.
- *
- * For the time being we only support 4MB boards!
- */
-
-#define PAT_MEM_SIZE 16*3
-#define PAT_MEM_OFF  (4*1024*1024 - PAT_MEM_SIZE)
-
-struct retz3fb_par {
-	int xres;
-	int yres;
-	int xres_vir;
-	int yres_vir;
-	int xoffset;
-	int yoffset;
-	int bpp;
-
-	struct fb_bitfield red;
-	struct fb_bitfield green;
-	struct fb_bitfield blue;
-	struct fb_bitfield transp;
-
-	int pixclock;
-	int left_margin;	/* time from sync to picture	*/
-	int right_margin;	/* time from picture to sync	*/
-	int upper_margin;	/* time from sync to picture	*/
-	int lower_margin;
-	int hsync_len;	/* length of horizontal sync	*/
-	int vsync_len;	/* length of vertical sync	*/
-	int vmode;
-
-	int accel;
-};
-
-struct display_data {
-	long h_total;		/* Horizontal Total */
-	long h_sstart;		/* Horizontal Sync Start */
-	long h_sstop;		/* Horizontal Sync Stop */
-	long h_bstart;		/* Horizontal Blank Start */
-	long h_bstop;		/* Horizontal Blank Stop */
-	long h_dispend;		/* Horizontal Display End */
-	long v_total;		/* Vertical Total */
-	long v_sstart;		/* Vertical Sync Start */
-	long v_sstop;		/* Vertical Sync Stop */
-	long v_bstart;		/* Vertical Blank Start */
-	long v_bstop;		/* Vertical Blank Stop */
-	long v_dispend;		/* Horizontal Display End */
-};
-
-struct retz3_fb_info {
-	struct fb_info info;
-	unsigned char *base;
-	unsigned char *fbmem;
-	unsigned long fbsize;
-	volatile unsigned char *regs;
-	unsigned long physfbmem;
-	unsigned long physregs;
-	int current_par_valid; /* set to 0 by memset */
-	int blitbusy;
-	struct display disp;
-	struct retz3fb_par current_par;
-	unsigned char color_table [256][3];
-};
-
-
-static char fontname[40] __initdata = { 0 };
-
-#define retz3info(info) ((struct retz3_fb_info *)(info))
-#define fbinfo(info) ((struct fb_info *)(info))
-
-
-/*
- *    Frame Buffer Name
- */
-
-static char retz3fb_name[16] = "RetinaZ3";
-
-
-/*
- * A small info on how to convert XFree86 timing values into fb
- * timings - by Frank Neumann:
- *
-An XFree86 mode line consists of the following fields:
- "800x600"     50      800  856  976 1040    600  637  643  666
- < name >     DCF       HR  SH1  SH2  HFL     VR  SV1  SV2  VFL
-
-The fields in the fb_var_screeninfo structure are:
-        unsigned long pixclock;         * pixel clock in ps (pico seconds) *
-        unsigned long left_margin;      * time from sync to picture    *
-        unsigned long right_margin;     * time from picture to sync    *
-        unsigned long upper_margin;     * time from sync to picture    *
-        unsigned long lower_margin;
-        unsigned long hsync_len;        * length of horizontal sync    *
-        unsigned long vsync_len;        * length of vertical sync      *
-
-1) Pixelclock:
-   xfree: in MHz
-   fb: In Picoseconds (ps)
-
-   pixclock = 1000000 / DCF
-
-2) horizontal timings:
-   left_margin = HFL - SH2
-   right_margin = SH1 - HR
-   hsync_len = SH2 - SH1
-
-3) vertical timings:
-   upper_margin = VFL - SV2
-   lower_margin = SV1 - VR
-   vsync_len = SV2 - SV1
-
-Good examples for VESA timings can be found in the XFree86 source tree,
-under "programs/Xserver/hw/xfree86/doc/modeDB.txt".
-*/
-
-/*
- *    Predefined Video Modes
- */
-
-static struct {
-    const char *name;
-    struct fb_var_screeninfo var;
-} retz3fb_predefined[] __initdata = {
-    /*
-     * NB: it is very important to adjust the pixel-clock to the color-depth.
-     */
-
-    {
-	"640x480", {		/* 640x480, 8 bpp */
-	    640, 480, 640, 480, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCEL_NONE, 39722, 48, 16, 33, 10, 96, 2,
-	    FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
-	}
-    },
-    /*
-     ModeLine "800x600" 36 800 824 896 1024 600 601 603 625
-	      < name > DCF HR  SH1 SH2  HFL VR  SV1 SV2 VFL
-     */
-    {
-	"800x600", {		/* 800x600, 8 bpp */
-	    800, 600, 800, 600, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 120, 2,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}
-    },
-    {
-	"800x600-60", {		/* 800x600, 8 bpp */
-	    800, 600, 800, 600, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 25000, 88, 40, 23, 1, 128, 4,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}
-    },
-    {
-	"800x600-70", {		/* 800x600, 8 bpp */
-	    800, 600, 800, 600, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 22272, 40, 24, 15, 9, 144, 12,
-	    FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}
-    },
-    /*
-      ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
-	       < name >   DCF HR  SH1  SH2  HFL  VR  SV1 SV2 VFL
-     */
-    {
-	"1024x768i", {		/* 1024x768, 8 bpp, interlaced */
-	    1024, 768, 1024, 768, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 22222, 40, 40, 32, 9, 160, 8,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED
-	}
-    },
-    {
-	"1024x768", {
-	    1024, 768, 1024, 768, 0, 0, 8, 0, 
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 
-	    0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
-	    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	 }
-    },
-    {
-	"640x480-16", {		/* 640x480, 16 bpp */
-	    640, 480, 640, 480, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, 38461/2, 28, 32, 12, 10, 96, 2,
-	    FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
-	}
-    },
-    {
-	"640x480-24", {		/* 640x480, 24 bpp */
-	    640, 480, 640, 480, 0, 0, 24, 0,
-	    {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0},
-	    0, 0, -1, -1, 0, 38461/3, 28, 32, 12, 10, 96, 2,
-	    FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
-	}
-    },
-};
-
-
-#define NUM_TOTAL_MODES    ARRAY_SIZE(retz3fb_predefined)
-
-static struct fb_var_screeninfo retz3fb_default;
-
-static int z3fb_inverse = 0;
-static int z3fb_mode __initdata = 0;
-
-
-/*
- *    Interface used by the world
- */
-
-int retz3fb_setup(char *options);
-
-static int retz3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info);
-static int retz3fb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int retz3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			    struct fb_info *info);
-static int retz3fb_setcolreg(unsigned int regno, unsigned int red,
-			     unsigned int green, unsigned int blue,
-			     unsigned int transp, struct fb_info *info);
-static int retz3fb_blank(int blank, struct fb_info *info);
-
-
-/*
- *    Interface to the low level console driver
- */
-
-int retz3fb_init(void);
-static int z3fb_switch(int con, struct fb_info *info);
-static int z3fb_updatevar(int con, struct fb_info *info);
-
-
-/*
- *    Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static struct display_switch fbcon_retz3_8;
-#endif
-
-
-/*
- *    Accelerated Functions used by the low level console driver
- */
-
-static void retz3_bitblt(struct display *p,
-			 unsigned short curx, unsigned short cury, unsigned
-			 short destx, unsigned short desty, unsigned short
-			 width, unsigned short height, unsigned short cmd,
-			 unsigned short mask);
-
-/*
- *   Hardware Specific Routines
- */
-
-static int retz3_encode_fix(struct fb_info *info,
-			    struct fb_fix_screeninfo *fix,
-			    struct retz3fb_par *par);
-static int retz3_decode_var(struct fb_var_screeninfo *var,
-			    struct retz3fb_par *par);
-static int retz3_encode_var(struct fb_var_screeninfo *var,
-			    struct retz3fb_par *par);
-static int retz3_getcolreg(unsigned int regno, unsigned int *red,
-			   unsigned int *green, unsigned int *blue,
-			   unsigned int *transp, struct fb_info *info);
-
-/*
- *    Internal routines
- */
-
-static void retz3fb_get_par(struct fb_info *info, struct retz3fb_par *par);
-static void retz3fb_set_par(struct fb_info *info, struct retz3fb_par *par);
-static int do_fb_set_var(struct fb_info *info,
-			 struct fb_var_screeninfo *var, int isactive);
-static void retz3fb_set_disp(int con, struct fb_info *info);
-static int get_video_mode(const char *name);
-
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-static unsigned short find_fq(unsigned int freq)
-{
-	unsigned long f;
-	long tmp;
-	long prev = 0x7fffffff;
-	long n2, n1 = 3;
-	unsigned long m;
-	unsigned short res = 0;
-
-	if (freq <= 31250000)
-		n2 = 3;
-	else if (freq <= 62500000)
-		n2 = 2;
-	else if (freq <= 125000000)
-		n2 = 1;
-	else if (freq <= 250000000)
-		n2 = 0;
-	else
-		return 0;
-
-
-	do {
-		f = freq >> (10 - n2);
-
-		m = (f * n1) / (14318180/1024);
-
-		if (m > 129)
-			break;
-
-		tmp =  (((m * 14318180) >> n2) / n1) - freq;
-		if (tmp < 0)
-			tmp = -tmp;
-
-		if (tmp < prev) {
-			prev = tmp;
-			res = (((n2 << 5) | (n1-2)) << 8) | (m-2);
-		}
-
-	} while ( (++n1) <= 21);
-
-	return res;
-}
-
-
-static int retz3_set_video(struct fb_info *info,
-			   struct fb_var_screeninfo *var,
-			   struct retz3fb_par *par)
-{
-	volatile unsigned char *regs = retz3info(info)->regs;
-	unsigned int freq;
-
-	int xres, hfront, hsync, hback;
-	int yres, vfront, vsync, vback;
-	unsigned char tmp;
-	unsigned short best_freq;
-	struct display_data data;
-
-	short clocksel = 0; /* Apparantly this is always zero */
-
-	int bpp = var->bits_per_pixel;
-
-	/*
-	 * XXX
-	 */
-	if (bpp == 24)
-		return 0;
-
-	if ((bpp != 8) && (bpp != 16) && (bpp != 24))
-		return -EFAULT;
-
-	par->xoffset = 0;
-	par->yoffset = 0;
-
-	xres   = var->xres * bpp / 4;
-	hfront = var->right_margin * bpp / 4;
-	hsync  = var->hsync_len * bpp / 4;
-	hback  = var->left_margin * bpp / 4;
-
-	if (var->vmode & FB_VMODE_DOUBLE)
-	{
-		yres = var->yres * 2;
-		vfront = var->lower_margin * 2;
-		vsync  = var->vsync_len * 2;
-		vback  = var->upper_margin * 2;
-	}
-	else if (var->vmode & FB_VMODE_INTERLACED)
-	{
-		yres   = (var->yres + 1) / 2;
-		vfront = (var->lower_margin + 1) / 2;
-		vsync  = (var->vsync_len + 1) / 2;
-		vback  = (var->upper_margin + 1) / 2;
-	}
-	else
-	{
-		yres   = var->yres; /* -1 ? */
-		vfront = var->lower_margin;
-		vsync  = var->vsync_len;
-		vback  = var->upper_margin;
-	}
-
-	data.h_total	= (hback / 8) + (xres / 8)
-			+ (hfront / 8) + (hsync / 8) - 1 /* + 1 */;
-	data.h_dispend	= ((xres + bpp - 1)/ 8) - 1;
-	data.h_bstart	= xres / 8 - 1 /* + 1 */;
-
-	data.h_bstop	= data.h_total+1 + 2 + 1;
-	data.h_sstart	= (xres / 8) + (hfront / 8) + 1;
-	data.h_sstop	= (xres / 8) + (hfront / 8) + (hsync / 8) + 1;
-
-	data.v_total	= yres + vfront + vsync + vback - 1;
-
-	data.v_dispend	= yres - 1;
-	data.v_bstart	= yres - 1;
-
-	data.v_bstop	= data.v_total;
-	data.v_sstart	= yres + vfront - 1 - 2;
-	data.v_sstop	= yres + vfront + vsync - 1;
-
-#if 0 /* testing */
-
-	printk("HBS: %i\n", data.h_bstart);
-	printk("HSS: %i\n", data.h_sstart);
-	printk("HSE: %i\n", data.h_sstop);
-	printk("HBE: %i\n", data.h_bstop);
-	printk("HT: %i\n", data.h_total);
-
-	printk("hsync: %i\n", hsync);
-	printk("hfront: %i\n", hfront);
-	printk("hback: %i\n", hback);
-
-	printk("VBS: %i\n", data.v_bstart);
-	printk("VSS: %i\n", data.v_sstart);
-	printk("VSE: %i\n", data.v_sstop);
-	printk("VBE: %i\n", data.v_bstop);
-	printk("VT: %i\n", data.v_total);
-
-	printk("vsync: %i\n", vsync);
-	printk("vfront: %i\n", vfront);
-	printk("vback: %i\n", vback);
-#endif
-
-	if (data.v_total >= 1024)
-		printk(KERN_ERR "MAYDAY: v_total >= 1024; bailing out!\n");
-
-	reg_w(regs, GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04));
-	reg_w(regs, GREG_FEATURE_CONTROL_W, 0x00);
-
-	seq_w(regs, SEQ_RESET, 0x00);
-	seq_w(regs, SEQ_RESET, 0x03);	/* reset sequencer logic */
-
-	/*
-	 * CLOCKING_MODE bits:
-	 * 2: This one is only set for certain text-modes, wonder if
-	 *    it may be for EGA-lines? (it was referred to as CLKDIV2)
-	 * (The CL drivers sets it to 0x21 with the comment:
-	 *  FullBandwidth (video off) and 8/9 dot clock)
-	 */
-	seq_w(regs, SEQ_CLOCKING_MODE, 0x01 | 0x00 /* 0x08 */);
-
-	seq_w(regs, SEQ_MAP_MASK, 0x0f);        /* enable writing to plane 0-3 */
-	seq_w(regs, SEQ_CHAR_MAP_SELECT, 0x00); /* doesn't matter in gfx-mode */
-	seq_w(regs, SEQ_MEMORY_MODE, 0x06); /* CL driver says 0x0e for 256 col mode*/
-	seq_w(regs, SEQ_RESET, 0x01);
-	seq_w(regs, SEQ_RESET, 0x03);
-
-	seq_w(regs, SEQ_EXTENDED_ENABLE, 0x05);
-
-	seq_w(regs, SEQ_CURSOR_CONTROL, 0x00);	/* disable cursor */
-	seq_w(regs, SEQ_PRIM_HOST_OFF_HI, 0x00);
-	seq_w(regs, SEQ_PRIM_HOST_OFF_HI, 0x00);
-	seq_w(regs, SEQ_LINEAR_0, 0x4a);
-	seq_w(regs, SEQ_LINEAR_1, 0x00);
-
-	seq_w(regs, SEQ_SEC_HOST_OFF_HI, 0x00);
-	seq_w(regs, SEQ_SEC_HOST_OFF_LO, 0x00);
-	seq_w(regs, SEQ_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
-
-	/*
-	 * The lower 4 bits (0-3) are used to set the font-width for
-	 * text-mode - DON'T try to set this for gfx-mode.
-	 */
-	seq_w(regs, SEQ_EXT_CLOCK_MODE, 0x10);
-	seq_w(regs, SEQ_EXT_VIDEO_ADDR, 0x03);
-
-	/*
-	 * Extended Pixel Control:
-	 * bit 0:   text-mode=0, gfx-mode=1 (Graphics Byte ?)
-	 * bit 1: (Packed/Nibble Pixel Format ?)
-	 * bit 4-5: depth, 0=1-8bpp, 1=9-16bpp, 2=17-24bpp
-	 */
-	seq_w(regs, SEQ_EXT_PIXEL_CNTL, 0x01 | (((bpp / 8) - 1) << 4));
-
-	seq_w(regs, SEQ_BUS_WIDTH_FEEDB, 0x04);
-	seq_w(regs, SEQ_COLOR_EXP_WFG, 0x01);
-	seq_w(regs, SEQ_COLOR_EXP_WBG, 0x00);
-	seq_w(regs, SEQ_EXT_RW_CONTROL, 0x00);
-	seq_w(regs, SEQ_MISC_FEATURE_SEL, (0x51 | (clocksel & 8)));
-	seq_w(regs, SEQ_COLOR_KEY_CNTL, 0x40);
-	seq_w(regs, SEQ_COLOR_KEY_MATCH0, 0x00);
-	seq_w(regs, SEQ_COLOR_KEY_MATCH1, 0x00);
-	seq_w(regs, SEQ_COLOR_KEY_MATCH2, 0x00);
-	seq_w(regs, SEQ_CRC_CONTROL, 0x00);
-	seq_w(regs, SEQ_PERF_SELECT, 0x10);
-	seq_w(regs, SEQ_ACM_APERTURE_1, 0x00);
-	seq_w(regs, SEQ_ACM_APERTURE_2, 0x30);
-	seq_w(regs, SEQ_ACM_APERTURE_3, 0x00);
-	seq_w(regs, SEQ_MEMORY_MAP_CNTL, 0x03);
-
-
-	/* unlock register CRT0..CRT7 */
-	crt_w(regs, CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20);
-
-	/* Zuerst zu schreibende Werte nur per printk ausgeben */
-	DEBUG printk("CRT_HOR_TOTAL: %ld\n", data.h_total);
-	crt_w(regs, CRT_HOR_TOTAL, data.h_total & 0xff);
-
-	DEBUG printk("CRT_HOR_DISP_ENA_END: %ld\n", data.h_dispend);
-	crt_w(regs, CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff);
-
-	DEBUG printk("CRT_START_HOR_BLANK: %ld\n", data.h_bstart);
-	crt_w(regs, CRT_START_HOR_BLANK, data.h_bstart & 0xff);
-
-	DEBUG printk("CRT_END_HOR_BLANK: 128+%ld\n", data.h_bstop % 32);
-	crt_w(regs, CRT_END_HOR_BLANK,  0x80 | (data.h_bstop & 0x1f));
-
-	DEBUG printk("CRT_START_HOR_RETR: %ld\n", data.h_sstart);
-	crt_w(regs, CRT_START_HOR_RETR, data.h_sstart & 0xff);
-
-	tmp = (data.h_sstop & 0x1f);
-	if (data.h_bstop & 0x20)
-		tmp |= 0x80;
-	DEBUG printk("CRT_END_HOR_RETR: %d\n", tmp);
-	crt_w(regs, CRT_END_HOR_RETR, tmp);
-
-	DEBUG printk("CRT_VER_TOTAL: %ld\n", data.v_total & 0xff);
-	crt_w(regs, CRT_VER_TOTAL, (data.v_total & 0xff));
-
-	tmp = 0x10;  /* LineCompare bit #9 */
-	if (data.v_total & 256)
-		tmp |= 0x01;
-	if (data.v_dispend & 256)
-		tmp |= 0x02;
-	if (data.v_sstart & 256)
-		tmp |= 0x04;
-	if (data.v_bstart & 256)
-		tmp |= 0x08;
-	if (data.v_total & 512)
-		tmp |= 0x20;
-	if (data.v_dispend & 512)
-		tmp |= 0x40;
-	if (data.v_sstart & 512)
-		tmp |= 0x80;
-	DEBUG printk("CRT_OVERFLOW: %d\n", tmp);
-	crt_w(regs, CRT_OVERFLOW, tmp);
-
-	crt_w(regs, CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */
-
-	tmp = 0x40; /* LineCompare bit #8 */
-	if (data.v_bstart & 512)
-		tmp |= 0x20;
-	if (var->vmode & FB_VMODE_DOUBLE)
-		tmp |= 0x80;
- 	DEBUG printk("CRT_MAX_SCAN_LINE: %d\n", tmp);
-	crt_w(regs, CRT_MAX_SCAN_LINE, tmp);
-
-	crt_w(regs, CRT_CURSOR_START, 0x00);
-	crt_w(regs, CRT_CURSOR_END, 8 & 0x1f); /* font height */
-
-	crt_w(regs, CRT_START_ADDR_HIGH, 0x00);
-	crt_w(regs, CRT_START_ADDR_LOW, 0x00);
-
-	crt_w(regs, CRT_CURSOR_LOC_HIGH, 0x00);
-	crt_w(regs, CRT_CURSOR_LOC_LOW, 0x00);
-
- 	DEBUG printk("CRT_START_VER_RETR: %ld\n", data.v_sstart & 0xff);
-	crt_w(regs, CRT_START_VER_RETR, (data.v_sstart & 0xff));
-
-#if 1
-	/* 5 refresh cycles per scanline */
-	DEBUG printk("CRT_END_VER_RETR: 64+32+%ld\n", data.v_sstop % 16);
-	crt_w(regs, CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20));
-#else
-	DEBUG printk("CRT_END_VER_RETR: 128+32+%ld\n", data.v_sstop % 16);
-	crt_w(regs, CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32));
-#endif
-	DEBUG printk("CRT_VER_DISP_ENA_END: %ld\n", data.v_dispend & 0xff);
-	crt_w(regs, CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff));
-
-	DEBUG printk("CRT_START_VER_BLANK: %ld\n", data.v_bstart & 0xff);
-	crt_w(regs, CRT_START_VER_BLANK, (data.v_bstart & 0xff));
-
-	DEBUG printk("CRT_END_VER_BLANK: %ld\n", data.v_bstop & 0xff);
-	crt_w(regs, CRT_END_VER_BLANK, (data.v_bstop & 0xff));
-
-	DEBUG printk("CRT_MODE_CONTROL: 0xe3\n");
-	crt_w(regs, CRT_MODE_CONTROL, 0xe3);
-
-	DEBUG printk("CRT_LINE_COMPARE: 0xff\n");
-	crt_w(regs, CRT_LINE_COMPARE, 0xff);
-
-	tmp = (var->xres_virtual / 8) * (bpp / 8);
-	crt_w(regs, CRT_OFFSET, tmp);
-
-	crt_w(regs, CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */
-
-	tmp = 0x20;			/* Enable extended end bits */
-	if (data.h_total & 0x100)
-		tmp |= 0x01;
-	if ((data.h_dispend) & 0x100)
-		tmp |= 0x02;
-	if (data.h_bstart & 0x100)
-		tmp |= 0x04;
-	if (data.h_sstart & 0x100)
-		tmp |= 0x08;
-	if (var->vmode & FB_VMODE_INTERLACED)
-		tmp |= 0x10;
- 	DEBUG printk("CRT_EXT_HOR_TIMING1: %d\n", tmp);
-	crt_w(regs, CRT_EXT_HOR_TIMING1, tmp);
-
-	tmp = 0x00;
-	if (((var->xres_virtual / 8) * (bpp / 8)) & 0x100)
-		tmp |= 0x10;
-	crt_w(regs, CRT_EXT_START_ADDR, tmp);
-
-	tmp = 0x00;
-	if (data.h_total & 0x200)
-		tmp |= 0x01;
-	if ((data.h_dispend) & 0x200)
-		tmp |= 0x02;
-	if (data.h_bstart & 0x200)
-		tmp |= 0x04;
-	if (data.h_sstart & 0x200)
-		tmp |= 0x08;
-	tmp |= ((data.h_bstop & 0xc0) >> 2);
-	tmp |= ((data.h_sstop & 0x60) << 1);
-	crt_w(regs, CRT_EXT_HOR_TIMING2, tmp);
- 	DEBUG printk("CRT_EXT_HOR_TIMING2: %d\n", tmp);
-
-	tmp = 0x10;			/* Line compare bit 10 */
-	if (data.v_total & 0x400)
-		tmp |= 0x01;
-	if ((data.v_dispend) & 0x400)
-		tmp |= 0x02;
-	if (data.v_bstart & 0x400)
-		tmp |= 0x04;
-	if (data.v_sstart & 0x400)
-		tmp |= 0x08;
-	tmp |= ((data.v_bstop & 0x300) >> 3);
-	if (data.v_sstop & 0x10)
-		tmp |= 0x80;
-	crt_w(regs, CRT_EXT_VER_TIMING, tmp);
- 	DEBUG printk("CRT_EXT_VER_TIMING: %d\n", tmp);
-
-	crt_w(regs, CRT_MONITOR_POWER, 0x00);
-
-	/*
-	 * Convert from ps to Hz.
-	 */
-	freq = 2000000000 / var->pixclock;
-	freq = freq * 500;
-
-	best_freq = find_fq(freq);
-	pll_w(regs, 0x02, best_freq);
-	best_freq = find_fq(61000000);
-	pll_w(regs, 0x0a, best_freq);
-	pll_w(regs, 0x0e, 0x22);
-
-	gfx_w(regs, GFX_SET_RESET, 0x00);
-	gfx_w(regs, GFX_ENABLE_SET_RESET, 0x00);
-	gfx_w(regs, GFX_COLOR_COMPARE, 0x00);
-	gfx_w(regs, GFX_DATA_ROTATE, 0x00);
-	gfx_w(regs, GFX_READ_MAP_SELECT, 0x00);
-	gfx_w(regs, GFX_GRAPHICS_MODE, 0x00);
-	gfx_w(regs, GFX_MISC, 0x05);
-	gfx_w(regs, GFX_COLOR_XCARE, 0x0f);
-	gfx_w(regs, GFX_BITMASK, 0xff);
-
-	reg_r(regs, ACT_ADDRESS_RESET);
-	attr_w(regs, ACT_PALETTE0 , 0x00);
-	attr_w(regs, ACT_PALETTE1 , 0x01);
-	attr_w(regs, ACT_PALETTE2 , 0x02);
-	attr_w(regs, ACT_PALETTE3 , 0x03);
-	attr_w(regs, ACT_PALETTE4 , 0x04);
-	attr_w(regs, ACT_PALETTE5 , 0x05);
-	attr_w(regs, ACT_PALETTE6 , 0x06);
-	attr_w(regs, ACT_PALETTE7 , 0x07);
-	attr_w(regs, ACT_PALETTE8 , 0x08);
-	attr_w(regs, ACT_PALETTE9 , 0x09);
-	attr_w(regs, ACT_PALETTE10, 0x0a);
-	attr_w(regs, ACT_PALETTE11, 0x0b);
-	attr_w(regs, ACT_PALETTE12, 0x0c);
-	attr_w(regs, ACT_PALETTE13, 0x0d);
-	attr_w(regs, ACT_PALETTE14, 0x0e);
-	attr_w(regs, ACT_PALETTE15, 0x0f);
-	reg_r(regs, ACT_ADDRESS_RESET);
-
-	attr_w(regs, ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */
-
-	attr_w(regs, ACT_OVERSCAN_COLOR, 0x00);
-	attr_w(regs, ACT_COLOR_PLANE_ENA, 0x0f);
-	attr_w(regs, ACT_HOR_PEL_PANNING, 0x00);
-	attr_w(regs, ACT_COLOR_SELECT, 0x00);
-
-	reg_r(regs, ACT_ADDRESS_RESET);
-	reg_w(regs, ACT_DATA, 0x20);
-
-	reg_w(regs, VDAC_MASK, 0xff);
-
-	/*
-	 * Extended palette addressing ???
-	 */
-	switch (bpp){
-	case 8:
-		reg_w(regs, 0x83c6, 0x00);
-		break;
-	case 16:
-		reg_w(regs, 0x83c6, 0x60);
-		break;
-	case 24:
-		reg_w(regs, 0x83c6, 0xe0);
-		break;
-	default:
-		printk(KERN_INFO "Illegal color-depth: %i\n", bpp);
-	}
-
-	reg_w(regs, VDAC_ADDRESS, 0x00);
-
-	seq_w(regs, SEQ_MAP_MASK, 0x0f );
-
-	return 0;
-}
-
-
-/*
- *    This function should fill in the `fix' structure based on the
- *    values in the `par' structure.
- */
-
-static int retz3_encode_fix(struct fb_info *info,
-			    struct fb_fix_screeninfo *fix,
-			    struct retz3fb_par *par)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, retz3fb_name);
-	fix->smem_start = zinfo->physfbmem;
-	fix->smem_len = zinfo->fbsize;
-	fix->mmio_start = zinfo->physregs;
-	fix->mmio_len = 0x00c00000;
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-	if (par->bpp == 8)
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-		fix->visual = FB_VISUAL_TRUECOLOR;
-
-	fix->xpanstep = 0;
-	fix->ypanstep = 0;
-	fix->ywrapstep = 0;
-	fix->line_length = 0;
-
-	fix->accel = FB_ACCEL_NCR_77C32BLT;
-
-	return 0;
-}
-
-
-/*
- *    Get the video params out of `var'. If a value doesn't fit, round
- *    it up, if it's too big, return -EINVAL.
- */
-
-static int retz3_decode_var(struct fb_var_screeninfo *var,
-			    struct retz3fb_par *par)
-{
-	par->xres = var->xres;
-	par->yres = var->yres;
-	par->xres_vir = var->xres_virtual;
-	par->yres_vir = var->yres_virtual;
-	par->bpp = var->bits_per_pixel;
-	par->pixclock = var->pixclock;
-	par->vmode = var->vmode;
-
-	par->red = var->red;
-	par->green = var->green;
-	par->blue = var->blue;
-	par->transp = var->transp;
-
-	par->left_margin = var->left_margin;
-	par->right_margin = var->right_margin;
-	par->upper_margin = var->upper_margin;
-	par->lower_margin = var->lower_margin;
-	par->hsync_len = var->hsync_len;
-	par->vsync_len = var->vsync_len;
-
-	if (var->accel_flags & FB_ACCELF_TEXT)
-	    par->accel = FB_ACCELF_TEXT;
-	else
-	    par->accel = 0;
-
-	return 0;
-}
-
-
-/*
- *    Fill the `var' structure based on the values in `par' and maybe
- *    other values read out of the hardware.
- */
-
-static int retz3_encode_var(struct fb_var_screeninfo *var,
-			    struct retz3fb_par *par)
-{
-	memset(var, 0, sizeof(struct fb_var_screeninfo));
-	var->xres = par->xres;
-	var->yres = par->yres;
-	var->xres_virtual = par->xres_vir;
-	var->yres_virtual = par->yres_vir;
-	var->xoffset = 0;
-	var->yoffset = 0;
-
-	var->bits_per_pixel = par->bpp;
-	var->grayscale = 0;
-
-	var->red = par->red;
-	var->green = par->green;
-	var->blue = par->blue;
-	var->transp = par->transp;
-
-	var->nonstd = 0;
-	var->activate = 0;
-
-	var->height = -1;
-	var->width = -1;
-
-	var->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0;
-
-	var->pixclock = par->pixclock;
-
-	var->sync = 0;				/* ??? */
-	var->left_margin = par->left_margin;
-	var->right_margin = par->right_margin;
-	var->upper_margin = par->upper_margin;
-	var->lower_margin = par->lower_margin;
-	var->hsync_len = par->hsync_len;
-	var->vsync_len = par->vsync_len;
-
-	var->vmode = par->vmode;
-	return 0;
-}
-
-
-/*
- *    Set a single color register. Return != 0 for invalid regno.
- */
-
-static int retz3fb_setcolreg(unsigned int regno, unsigned int red,
-			     unsigned int green, unsigned int blue,
-			     unsigned int transp, struct fb_info *info)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-	volatile unsigned char *regs = zinfo->regs;
-
-	/* We'll get to this */
-
-	if (regno > 255)
-		return 1;
-
-	red >>= 10;
-	green >>= 10;
-	blue >>= 10;
-
-	zinfo->color_table[regno][0] = red;
-	zinfo->color_table[regno][1] = green;
-	zinfo->color_table[regno][2] = blue;
-
-	reg_w(regs, VDAC_ADDRESS_W, regno);
-	reg_w(regs, VDAC_DATA, red);
-	reg_w(regs, VDAC_DATA, green);
-	reg_w(regs, VDAC_DATA, blue);
-
-	return 0;
-}
-
-
-/*
- *    Read a single color register and split it into
- *    colors/transparent. Return != 0 for invalid regno.
- */
-
-static int retz3_getcolreg(unsigned int regno, unsigned int *red,
-			   unsigned int *green, unsigned int *blue,
-			   unsigned int *transp, struct fb_info *info)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-	int t;
-
-	if (regno > 255)
-		return 1;
-	t       = zinfo->color_table[regno][0];
-	*red    = (t<<10) | (t<<4) | (t>>2);
-	t       = zinfo->color_table[regno][1];
-	*green  = (t<<10) | (t<<4) | (t>>2);
-	t       = zinfo->color_table[regno][2];
-	*blue   = (t<<10) | (t<<4) | (t>>2);
-	*transp = 0;
-	return 0;
-}
-
-
-static inline void retz3_busy(struct display *p)
-{
-	struct retz3_fb_info *zinfo = retz3info(p->fb_info);
-	volatile unsigned char *acm = zinfo->base + ACM_OFFSET;
-	unsigned char blt_status;
-
-	if (zinfo->blitbusy) {
-		do{
-			blt_status = *((acm) + (ACM_START_STATUS + 2));
-		}while ((blt_status & 1) == 0);
-		zinfo->blitbusy = 0;
-	}
-}
-
-
-static void retz3_bitblt (struct display *p,
-			  unsigned short srcx, unsigned short srcy,
-			  unsigned short destx, unsigned short desty,
-			  unsigned short width, unsigned short height,
-			  unsigned short cmd, unsigned short mask)
-{
-	struct fb_var_screeninfo *var = &p->var;
-	struct retz3_fb_info *zinfo = retz3info(p->fb_info);
-	volatile unsigned long *acm = (unsigned long *)(zinfo->base + ACM_OFFSET);
-	unsigned long *pattern = (unsigned long *)(zinfo->fbmem + PAT_MEM_OFF);
-
-	unsigned short mod;
-	unsigned long tmp;
-	unsigned long pat, src, dst;
-
-	int i, xres_virtual = var->xres_virtual;
-	short bpp = (var->bits_per_pixel & 0xff);
-
-	if (bpp < 8)
-		bpp = 8;
-
-	tmp = mask | (mask << 16);
-
-	retz3_busy(p);
-
-	i = 0;
-	do{
-		*pattern++ = tmp;
-	}while(i++ < bpp/4);
-
-	tmp = cmd << 8;
-	*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
-
-	mod = 0xc0c2;
-
-	pat = 8 * PAT_MEM_OFF;
-	dst = bpp * (destx + desty * xres_virtual);
-
-	/*
-	 * Source is not set for clear.
-	 */
-	if ((cmd != Z3BLTclear) && (cmd != Z3BLTset)) {
-		src = bpp * (srcx + srcy * xres_virtual);
-
-		if (destx > srcx) {
-			mod &= ~0x8000;
-			src += bpp * (width - 1);
-			dst += bpp * (width - 1);
-			pat += bpp * 2;
-		}
-		if (desty > srcy) {
-			mod &= ~0x4000;
-			src += bpp * (height - 1) * xres_virtual;
-			dst += bpp * (height - 1) * xres_virtual;
-			pat += bpp * 4;
-		}
-
-		*(acm + ACM_SOURCE/4) = cpu_to_le32(src);
-	}
-
-	*(acm + ACM_PATTERN/4) = cpu_to_le32(pat);
-
-	*(acm + ACM_DESTINATION/4) = cpu_to_le32(dst);
-
-	tmp = mod << 16;
-	*(acm + ACM_CONTROL/4) = tmp;
-
-	tmp  = width | (height << 16);
-
-	*(acm + ACM_BITMAP_DIMENSION/4) = cpu_to_le32(tmp);
-
-	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
-	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
-	zinfo->blitbusy = 1;
-}
-
-#if 0
-/*
- * Move cursor to x, y
- */
-static void retz3_MoveCursor (unsigned short x, unsigned short y)
-{
-	/* Guess we gotta deal with the cursor at some point */
-}
-#endif
-
-
-/*
- *    Fill the hardware's `par' structure.
- */
-
-static void retz3fb_get_par(struct fb_info *info, struct retz3fb_par *par)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	if (zinfo->current_par_valid)
-		*par = zinfo->current_par;
-	else
-		retz3_decode_var(&retz3fb_default, par);
-}
-
-
-static void retz3fb_set_par(struct fb_info *info, struct retz3fb_par *par)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	zinfo->current_par = *par;
-	zinfo->current_par_valid = 1;
-}
-
-
-static int do_fb_set_var(struct fb_info *info,
-			 struct fb_var_screeninfo *var, int isactive)
-{
-	int err, activate;
-	struct retz3fb_par par;
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	if ((err = retz3_decode_var(var, &par)))
-		return err;
-	activate = var->activate;
-
-	/* XXX ... what to do about isactive ? */
-
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
-		retz3fb_set_par(info, &par);
-	retz3_encode_var(var, &par);
-	var->activate = activate;
-
-	retz3_set_video(info, var, &zinfo->current_par);
-
-	return 0;
-}
-
-/*
- *    Get the Fixed Part of the Display
- */
-
-static int retz3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info)
-{
-	struct retz3fb_par par;
-	int error = 0;
-
-	if (con == -1)
-		retz3fb_get_par(info, &par);
-	else
-		error = retz3_decode_var(&fb_display[con].var, &par);
-	return(error ? error : retz3_encode_fix(info, fix, &par));
-}
-
-
-/*
- *    Get the User Defined Part of the Display
- */
-
-static int retz3fb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	struct retz3fb_par par;
-	int error = 0;
-
-	if (con == -1) {
-		retz3fb_get_par(info, &par);
-		error = retz3_encode_var(var, &par);
-	} else
-		*var = fb_display[con].var;
-	return error;
-}
-
-
-static void retz3fb_set_disp(int con, struct fb_info *info)
-{
-	struct fb_fix_screeninfo fix;
-	struct display *display;
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	if (con >= 0)
-		display = &fb_display[con];
-	else
-		display = &zinfo->disp;	/* used during initialization */
-
-	retz3fb_get_fix(&fix, con, info);
-
-	if (con == -1)
-		con = 0;
-
-	display->visual = fix.visual;
-	display->type = fix.type;
-	display->type_aux = fix.type_aux;
-	display->ypanstep = fix.ypanstep;
-	display->ywrapstep = fix.ywrapstep;
-	display->can_soft_blank = 1;
-	display->inverse = z3fb_inverse;
-
-	/*
-	 * This seems to be about 20% faster.
-	 */
-	display->scrollmode = SCROLL_YREDRAW;
-
-	switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		if (display->var.accel_flags & FB_ACCELF_TEXT) {
-		    display->dispsw = &fbcon_retz3_8;
-		    retz3_set_video(info, &display->var, &zinfo->current_par);
-		} else
-		    display->dispsw = &fbcon_cfb8;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	case 16:
-		display->dispsw = &fbcon_cfb16;
-		break;
-#endif
-	default:
-		display->dispsw = &fbcon_dummy;
-		break;
-	}
-}
-
-
-/*
- *    Set the User Defined Part of the Display
- */
-
-static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
-	struct display *display;
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	if (con >= 0)
-		display = &fb_display[con];
-	else
-		display = &zinfo->disp;	/* used during initialization */
-
-	if ((err = do_fb_set_var(info, var, con == info->currcon)))
-		return err;
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-		oldxres = display->var.xres;
-		oldyres = display->var.yres;
-		oldvxres = display->var.xres_virtual;
-		oldvyres = display->var.yres_virtual;
-		oldbpp = display->var.bits_per_pixel;
-		oldaccel = display->var.accel_flags;
-		display->var = *var;
-
-		if (oldxres != var->xres || oldyres != var->yres ||
-		    oldvxres != var->xres_virtual ||
-		    oldvyres != var->yres_virtual ||
-		    oldbpp != var->bits_per_pixel ||
-		    oldaccel != var->accel_flags) {
-
-			struct fb_fix_screeninfo fix;
-			retz3fb_get_fix(&fix, con, info);
-
-			display->visual = fix.visual;
-			display->type = fix.type;
-			display->type_aux = fix.type_aux;
-			display->ypanstep = fix.ypanstep;
-			display->ywrapstep = fix.ywrapstep;
-			display->line_length = fix.line_length;
-			display->can_soft_blank = 1;
-			display->inverse = z3fb_inverse;
-			switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-			case 8:
-				if (var->accel_flags & FB_ACCELF_TEXT) {
-					display->dispsw = &fbcon_retz3_8;
-				} else
-					display->dispsw = &fbcon_cfb8;
-				break;
-#endif
-#ifdef FBCON_HAS_CFB16
-			case 16:
-				display->dispsw = &fbcon_cfb16;
-				break;
-#endif
-			default:
-				display->dispsw = &fbcon_dummy;
-				break;
-			}
-			/*
-			 * We still need to find a way to tell the X
-			 * server that the video mem has been fiddled with
-			 * so it redraws the entire screen when switching
-			 * between X and a text console.
-			 */
-			retz3_set_video(info, var, &zinfo->current_par);
-
-			if (info->changevar)
-				(*info->changevar)(con);
-		}
-
-		if (oldbpp != var->bits_per_pixel) {
-			if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
-				return err;
-			do_install_cmap(con, info);
-		}
-	}
-	return 0;
-}
-
-
-/*
- *    Get the Colormap
- */
-
-static int retz3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			    struct fb_info *info)
-{
-	if (con == info->currcon) /* current console? */
-		return(fb_get_cmap(cmap, kspc, retz3_getcolreg, info));
-	else if (fb_display[con].cmap.len) /* non default colormap? */
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	else
-		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-			     cmap, kspc ? 0 : 2);
-	return 0;
-}
-
-/*
- *    Blank the display.
- */
-
-static int retz3fb_blank(int blank, struct fb_info *info)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-	volatile unsigned char *regs = retz3info(info)->regs;
-	short i;
-
-	if (blank)
-		for (i = 0; i < 256; i++){
-			reg_w(regs, VDAC_ADDRESS_W, i);
-			reg_w(regs, VDAC_DATA, 0);
-			reg_w(regs, VDAC_DATA, 0);
-			reg_w(regs, VDAC_DATA, 0);
-		}
-	else
-		for (i = 0; i < 256; i++){
-			reg_w(regs, VDAC_ADDRESS_W, i);
-			reg_w(regs, VDAC_DATA, zinfo->color_table[i][0]);
-			reg_w(regs, VDAC_DATA, zinfo->color_table[i][1]);
-			reg_w(regs, VDAC_DATA, zinfo->color_table[i][2]);
-		}
-	return 0;
-}
-
-static struct fb_ops retz3fb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	retz3fb_get_fix,
-	.fb_get_var =	retz3fb_get_var,
-	.fb_set_var =	retz3fb_set_var,
-	.fb_get_cmap =	retz3fb_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_setcolreg =	retz3fb_setcolreg,
-	.fb_blank =	retz3fb_blank,
-};
-
-int __init retz3fb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strcmp(this_opt, "inverse")) {
-			z3fb_inverse = 1;
-			fb_invert_cmaps();
-		} else if (!strncmp(this_opt, "font:", 5)) {
-			strlcpy(fontname, this_opt+5, sizeof(fontname));
-		} else
-			z3fb_mode = get_video_mode(this_opt);
-	}
-	return 0;
-}
-
-
-/*
- *    Initialization
- */
-
-int __init retz3fb_init(void)
-{
-	unsigned long board_addr, board_size;
-	struct zorro_dev *z = NULL;
-	volatile unsigned char *regs;
-	struct retz3fb_par par;
-	struct retz3_fb_info *zinfo;
-	struct fb_info *fb_info;
-	short i;
-	int res = -ENXIO;
-
-	while ((z = zorro_find_device(ZORRO_PROD_MACROSYSTEMS_RETINA_Z3, z))) {
-		board_addr = z->resource.start;
-		board_size = z->resource.end-z->resource.start+1;
-		if (!request_mem_region(board_addr, 0x0c00000,
-			    		"ncr77c32blt")) {
-			continue;
-		if (!request_mem_region(board_addr+VIDEO_MEM_OFFSET,
-			    		0x00400000, "RAM"))
-			release_mem_region(board_addr, 0x00c00000);
-			continue;
-		}
-		if (!(zinfo = kmalloc(sizeof(struct retz3_fb_info),
-				      GFP_KERNEL)))
-			return -ENOMEM;
-		memset(zinfo, 0, sizeof(struct retz3_fb_info));
-
-		zinfo->base = ioremap(board_addr, board_size);
-		zinfo->regs = zinfo->base;
-		zinfo->fbmem = zinfo->base + VIDEO_MEM_OFFSET;
-		/* Get memory size - for now we asume it's a 4MB board */
-		zinfo->fbsize = 0x00400000; /* 4 MB */
-		zinfo->physregs = board_addr;
-		zinfo->physfbmem = board_addr + VIDEO_MEM_OFFSET;
-
-		fb_info = fbinfo(zinfo);
-
-		for (i = 0; i < 256; i++){
-			for (i = 0; i < 256; i++){
-				zinfo->color_table[i][0] = i;
-				zinfo->color_table[i][1] = i;
-				zinfo->color_table[i][2] = i;
-			}
-		}
-
-		regs = zinfo->regs;
-		/* Disable hardware cursor */
-		seq_w(regs, SEQ_CURSOR_Y_INDEX, 0x00);
-
-		retz3fb_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, fb_info);
-		retz3fb_setcolreg (254, 0, 0, 0, 0, fb_info);
-
-		strcpy(fb_info->modename, retz3fb_name);
-		fb_info->changevar = NULL;
-		fb_info->fbops = &retz3fb_ops;
-		fb_info->screen_base = zinfo->fbmem;
-		fb_info->disp = &zinfo->disp;
-		fb_info->currcon = -1;
-		fb_info->switch_con = &z3fb_switch;
-		fb_info->updatevar = &z3fb_updatevar;
-		fb_info->flags = FBINFO_FLAG_DEFAULT;
-		strlcpy(fb_info->fontname, fontname, sizeof(fb_info->fontname));
-
-		if (z3fb_mode == -1)
-			retz3fb_default = retz3fb_predefined[0].var;
-
-		retz3_decode_var(&retz3fb_default, &par);
-		retz3_encode_var(&retz3fb_default, &par);
-
-		do_fb_set_var(fb_info, &retz3fb_default, 0);
-		retz3fb_get_var(&zinfo->disp.var, -1, fb_info);
-
-		retz3fb_set_disp(-1, fb_info);
-
-		do_install_cmap(0, fb_info);
-
-		if (register_framebuffer(fb_info) < 0) {
-			iounmap(zinfo->base);
-			return -EINVAL;
-		}
-
-		printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of "
-		       "video memory\n", fb_info->node,
-		       fb_info->modename, zinfo->fbsize>>10);
-
-		/* FIXME: This driver cannot be unloaded yet */
-		res = 0;
-	}
-	return res;
-}
-
-
-static int z3fb_switch(int con, struct fb_info *info)
-{
-	/* Do we have to save the colormap? */
-	if (fb_display[info->currcon].cmap.len)
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1,
-			    retz3_getcolreg, info);
-
-	do_fb_set_var(info, &fb_display[con].var, 1);
-	info->currcon = con;
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	return 0;
-}
-
-
-/*
- *    Update the `var' structure (called by fbcon.c)
- *
- *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
- *    Since it's called by a kernel driver, no range checking is done.
- */
-
-static int z3fb_updatevar(int con, struct fb_info *info)
-{
-	return 0;
-}
-
-/*
- *    Get a Video Mode
- */
-
-static int __init get_video_mode(const char *name)
-{
-	short i;
-
-	for (i = 0; i < NUM_TOTAL_MODES; i++)
-		if (!strcmp(name, retz3fb_predefined[i].name)){
-			retz3fb_default = retz3fb_predefined[i].var;
-			return i;
-		}
-	return -1;
-}
-
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return retz3fb_init();
-}
-#endif
-
-
-/*
- *  Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static void retz3_8_bmove(struct display *p, int sy, int sx,
-			  int dy, int dx, int height, int width)
-{
-	int fontwidth = fontwidth(p);
-
-	sx *= fontwidth;
-	dx *= fontwidth;
-	width *= fontwidth;
-
-	retz3_bitblt(p,
-		     (unsigned short)sx,
-		     (unsigned short)(sy*fontheight(p)),
-		     (unsigned short)dx,
-		     (unsigned short)(dy*fontheight(p)),
-		     (unsigned short)width,
-		     (unsigned short)(height*fontheight(p)),
-		     Z3BLTcopy,
-		     0xffff);
-}
-
-static void retz3_8_clear(struct vc_data *conp, struct display *p,
-			  int sy, int sx, int height, int width)
-{
-	unsigned short col;
-	int fontwidth = fontwidth(p);
-
-	sx *= fontwidth;
-	width *= fontwidth;
-
-	col = attr_bgcol_ec(p, conp);
-	col &= 0xff;
-	col |= (col << 8);
-
-	retz3_bitblt(p,
-		     (unsigned short)sx,
-		     (unsigned short)(sy*fontheight(p)),
-		     (unsigned short)sx,
-		     (unsigned short)(sy*fontheight(p)),
-		     (unsigned short)width,
-		     (unsigned short)(height*fontheight(p)),
-		     Z3BLTset,
-		     col);
-}
-
-
-static void retz3_putc(struct vc_data *conp, struct display *p, int c,
-		       int yy, int xx)
-{
-	retz3_busy(p);
-	fbcon_cfb8_putc(conp, p, c, yy, xx);
-}
-
-
-static void retz3_putcs(struct vc_data *conp, struct display *p,
-			const unsigned short *s, int count,
-			int yy, int xx)
-{
-	retz3_busy(p);
-	fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
-}
-
-
-static void retz3_revc(struct display *p, int xx, int yy)
-{
-	retz3_busy(p);
-	fbcon_cfb8_revc(p, xx, yy);
-}
-
-
-static void retz3_clear_margins(struct vc_data* conp, struct display* p,
-				int bottom_only)
-{
-	retz3_busy(p);
-	fbcon_cfb8_clear_margins(conp, p, bottom_only);
-}
-
-
-static struct display_switch fbcon_retz3_8 = {
-	.setup		= fbcon_cfb8_setup,
-	.bmove		= retz3_8_bmove,
-	.clear		= retz3_8_clear,
-	.putc		= retz3_putc,
-	.putcs		= retz3_putcs,
-	.revc		= retz3_revc,
-	.clear_margins	= retz3_clear_margins,
-	.fontwidthmask	= FONTWIDTH(8)
-};
-#endif
diff --git a/drivers/video/retz3fb.h b/drivers/video/retz3fb.h
deleted file mode 100644
index 5cc7510..0000000
--- a/drivers/video/retz3fb.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * linux/drivers/video/retz3fb.h -- Defines and macros for the RetinaZ3 frame
- *				    buffer device
- *
- *    Copyright (C) 1997 Jes Sorensen
- *
- * History:
- *   - 22 Jan 97: Initial work
- *
- *
- * 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.
- */
-
-/*
- * Macros to read and write to registers.
- */
-#define reg_w(regs, reg,dat) (*(regs + reg) = dat)
-#define reg_r(regs, reg) (*(regs + reg))
-
-/*
- * Macro to access the sequencer.
- */
-#define seq_w(regs, sreg, sdat) \
-	do{ reg_w(regs, SEQ_IDX, sreg); reg_w(regs, SEQ_DATA, sdat); } while(0)
-
-/*
- * Macro to access the CRT controller.
- */
-#define crt_w(regs, creg, cdat) \
-	do{ reg_w(regs, CRT_IDX, creg); reg_w(regs, CRT_DATA, cdat); } while(0)
-
-/*
- * Macro to access the graphics controller.
- */
-#define gfx_w(regs, greg, gdat) \
-	do{ reg_w(regs, GFX_IDX, greg); reg_w(regs, GFX_DATA, gdat); } while(0)
-
-/*
- * Macro to access the attribute controller.
- */
-#define attr_w(regs, areg, adat) \
-	do{ reg_w(regs, ACT_IDX, areg); reg_w(regs, ACT_DATA, adat); } while(0)
-
-/*
- * Macro to access the pll.
- */
-#define pll_w(regs, preg, pdat) \
-	do{ reg_w(regs, PLL_IDX, preg); \
-	    reg_w(regs, PLL_DATA, (pdat & 0xff)); \
-	    reg_w(regs, PLL_DATA, (pdat >> 8));\
-	} while(0)
-
-/*
- * Offsets
- */
-#define VIDEO_MEM_OFFSET	0x00c00000
-#define ACM_OFFSET		0x00b00000
-
-/*
- * Accelerator Control Menu
- */
-#define ACM_PRIMARY_OFFSET	0x00
-#define ACM_SECONDARY_OFFSET	0x04
-#define ACM_MODE_CONTROL	0x08
-#define ACM_CURSOR_POSITION	0x0c
-#define ACM_START_STATUS	0x30
-#define ACM_CONTROL		0x34
-#define ACM_RASTEROP_ROTATION	0x38
-#define ACM_BITMAP_DIMENSION	0x3c
-#define ACM_DESTINATION		0x40
-#define ACM_SOURCE		0x44
-#define ACM_PATTERN		0x48
-#define ACM_FOREGROUND		0x4c
-#define ACM_BACKGROUND		0x50
-
-/*
- * Video DAC addresses
- */
-#define VDAC_ADDRESS		0x03c8
-#define VDAC_ADDRESS_W		0x03c8
-#define VDAC_ADDRESS_R		0x03c7
-#define VDAC_STATE		0x03c7
-#define VDAC_DATA		0x03c9
-#define VDAC_MASK		0x03c6
-
-/*
- * Sequencer
- */
-#define SEQ_IDX			0x03c4	/* Sequencer Index */
-#define SEQ_DATA		0x03c5
-#define SEQ_RESET		0x00
-#define SEQ_CLOCKING_MODE	0x01
-#define SEQ_MAP_MASK		0x02
-#define SEQ_CHAR_MAP_SELECT	0x03
-#define SEQ_MEMORY_MODE		0x04
-#define SEQ_EXTENDED_ENABLE	0x05	/* NCR extensions */
-#define SEQ_UNKNOWN1         	0x06
-#define SEQ_UNKNOWN2         	0x07
-#define SEQ_CHIP_ID		0x08
-#define SEQ_UNKNOWN3         	0x09
-#define SEQ_CURSOR_COLOR1	0x0a
-#define SEQ_CURSOR_COLOR0	0x0b
-#define SEQ_CURSOR_CONTROL	0x0c
-#define SEQ_CURSOR_X_LOC_HI	0x0d
-#define SEQ_CURSOR_X_LOC_LO	0x0e
-#define SEQ_CURSOR_Y_LOC_HI	0x0f
-#define SEQ_CURSOR_Y_LOC_LO	0x10
-#define SEQ_CURSOR_X_INDEX	0x11
-#define SEQ_CURSOR_Y_INDEX	0x12
-#define SEQ_CURSOR_STORE_HI	0x13
-#define SEQ_CURSOR_STORE_LO	0x14
-#define SEQ_CURSOR_ST_OFF_HI	0x15
-#define SEQ_CURSOR_ST_OFF_LO	0x16
-#define SEQ_CURSOR_PIXELMASK	0x17
-#define SEQ_PRIM_HOST_OFF_HI	0x18
-#define SEQ_PRIM_HOST_OFF_LO	0x19
-#define SEQ_LINEAR_0		0x1a
-#define SEQ_LINEAR_1		0x1b
-#define SEQ_SEC_HOST_OFF_HI	0x1c
-#define SEQ_SEC_HOST_OFF_LO	0x1d
-#define SEQ_EXTENDED_MEM_ENA	0x1e
-#define SEQ_EXT_CLOCK_MODE	0x1f
-#define SEQ_EXT_VIDEO_ADDR	0x20
-#define SEQ_EXT_PIXEL_CNTL	0x21
-#define SEQ_BUS_WIDTH_FEEDB	0x22
-#define SEQ_PERF_SELECT		0x23
-#define SEQ_COLOR_EXP_WFG	0x24
-#define SEQ_COLOR_EXP_WBG	0x25
-#define SEQ_EXT_RW_CONTROL	0x26
-#define SEQ_MISC_FEATURE_SEL	0x27
-#define SEQ_COLOR_KEY_CNTL	0x28
-#define SEQ_COLOR_KEY_MATCH0	0x29
-#define SEQ_COLOR_KEY_MATCH1 	0x2a
-#define SEQ_COLOR_KEY_MATCH2 	0x2b
-#define SEQ_UNKNOWN6         	0x2c
-#define SEQ_CRC_CONTROL		0x2d
-#define SEQ_CRC_DATA_LOW	0x2e
-#define SEQ_CRC_DATA_HIGH	0x2f
-#define SEQ_MEMORY_MAP_CNTL	0x30
-#define SEQ_ACM_APERTURE_1	0x31
-#define SEQ_ACM_APERTURE_2	0x32
-#define SEQ_ACM_APERTURE_3	0x33
-#define SEQ_BIOS_UTILITY_0	0x3e
-#define SEQ_BIOS_UTILITY_1	0x3f
-
-/*
- * Graphics Controller
- */
-#define GFX_IDX			0x03ce
-#define GFX_DATA		0x03cf
-#define GFX_SET_RESET		0x00
-#define GFX_ENABLE_SET_RESET	0x01
-#define GFX_COLOR_COMPARE	0x02
-#define GFX_DATA_ROTATE		0x03
-#define GFX_READ_MAP_SELECT	0x04
-#define GFX_GRAPHICS_MODE	0x05
-#define GFX_MISC		0x06
-#define GFX_COLOR_XCARE		0x07
-#define GFX_BITMASK		0x08
-
-/*
- * CRT Controller
- */
-#define CRT_IDX			0x03d4
-#define CRT_DATA		0x03d5
-#define CRT_HOR_TOTAL		0x00
-#define CRT_HOR_DISP_ENA_END	0x01
-#define CRT_START_HOR_BLANK	0x02
-#define CRT_END_HOR_BLANK	0x03
-#define CRT_START_HOR_RETR	0x04
-#define CRT_END_HOR_RETR	0x05
-#define CRT_VER_TOTAL		0x06
-#define CRT_OVERFLOW		0x07
-#define CRT_PRESET_ROW_SCAN	0x08
-#define CRT_MAX_SCAN_LINE	0x09
-#define CRT_CURSOR_START	0x0a
-#define CRT_CURSOR_END		0x0b
-#define CRT_START_ADDR_HIGH	0x0c
-#define CRT_START_ADDR_LOW	0x0d
-#define CRT_CURSOR_LOC_HIGH	0x0e
-#define CRT_CURSOR_LOC_LOW	0x0f
-#define CRT_START_VER_RETR	0x10
-#define CRT_END_VER_RETR	0x11
-#define CRT_VER_DISP_ENA_END	0x12
-#define CRT_OFFSET		0x13
-#define CRT_UNDERLINE_LOC	0x14
-#define CRT_START_VER_BLANK	0x15
-#define CRT_END_VER_BLANK	0x16
-#define CRT_MODE_CONTROL	0x17
-#define CRT_LINE_COMPARE	0x18
-#define CRT_UNKNOWN1         	0x19
-#define CRT_UNKNOWN2         	0x1a
-#define CRT_UNKNOWN3         	0x1b
-#define CRT_UNKNOWN4         	0x1c
-#define CRT_UNKNOWN5         	0x1d
-#define CRT_UNKNOWN6         	0x1e
-#define CRT_UNKNOWN7         	0x1f
-#define CRT_UNKNOWN8         	0x20
-#define CRT_UNKNOWN9		0x21
-#define CRT_UNKNOWN10		0x22
-#define CRT_UNKNOWN11      	0x23
-#define CRT_UNKNOWN12      	0x24
-#define CRT_UNKNOWN13      	0x25
-#define CRT_UNKNOWN14      	0x26
-#define CRT_UNKNOWN15      	0x27
-#define CRT_UNKNOWN16      	0x28
-#define CRT_UNKNOWN17      	0x29
-#define CRT_UNKNOWN18      	0x2a
-#define CRT_UNKNOWN19      	0x2b
-#define CRT_UNKNOWN20      	0x2c
-#define CRT_UNKNOWN21      	0x2d
-#define CRT_UNKNOWN22      	0x2e
-#define CRT_UNKNOWN23      	0x2f
-#define CRT_EXT_HOR_TIMING1	0x30	/* NCR crt extensions */
-#define CRT_EXT_START_ADDR	0x31
-#define CRT_EXT_HOR_TIMING2	0x32
-#define CRT_EXT_VER_TIMING	0x33
-#define CRT_MONITOR_POWER	0x34
-
-/*
- * General Registers
- */
-#define GREG_STATUS0_R		0x03c2
-#define GREG_STATUS1_R		0x03da
-#define GREG_MISC_OUTPUT_R	0x03cc
-#define GREG_MISC_OUTPUT_W	0x03c2	
-#define GREG_FEATURE_CONTROL_R	0x03ca
-#define GREG_FEATURE_CONTROL_W	0x03da
-#define GREG_POS		0x0102
-
-/*
- * Attribute Controller
- */
-#define ACT_IDX			0x03C0
-#define ACT_ADDRESS_R		0x03C0
-#define ACT_DATA		0x03C0
-#define ACT_ADDRESS_RESET	0x03DA
-#define ACT_PALETTE0		0x00
-#define ACT_PALETTE1		0x01
-#define ACT_PALETTE2		0x02
-#define ACT_PALETTE3		0x03
-#define ACT_PALETTE4		0x04
-#define ACT_PALETTE5		0x05
-#define ACT_PALETTE6		0x06
-#define ACT_PALETTE7		0x07
-#define ACT_PALETTE8		0x08
-#define ACT_PALETTE9		0x09
-#define ACT_PALETTE10		0x0A
-#define ACT_PALETTE11		0x0B
-#define ACT_PALETTE12		0x0C
-#define ACT_PALETTE13		0x0D
-#define ACT_PALETTE14		0x0E
-#define ACT_PALETTE15		0x0F
-#define ACT_ATTR_MODE_CNTL	0x10
-#define ACT_OVERSCAN_COLOR	0x11
-#define ACT_COLOR_PLANE_ENA	0x12
-#define ACT_HOR_PEL_PANNING	0x13
-#define ACT_COLOR_SELECT	0x14
-
-/*
- * PLL
- */
-#define PLL_IDX			0x83c8
-#define PLL_DATA		0x83c9
-
-/*
- * Blitter operations
- */
-#define	Z3BLTclear		0x00	/* 0 */
-#define Z3BLTand		0x80	/* src AND dst */
-#define Z3BLTandReverse		0x40	/* src AND NOT dst */
-#define Z3BLTcopy		0xc0	/* src */
-#define Z3BLTandInverted	0x20	/* NOT src AND dst */
-#define	Z3BLTnoop		0xa0	/* dst */
-#define Z3BLTxor		0x60	/* src XOR dst */
-#define Z3BLTor			0xe0	/* src OR dst */
-#define Z3BLTnor		0x10	/* NOT src AND NOT dst */
-#define Z3BLTequiv		0x90	/* NOT src XOR dst */
-#define Z3BLTinvert		0x50	/* NOT dst */
-#define Z3BLTorReverse		0xd0	/* src OR NOT dst */
-#define Z3BLTcopyInverted	0x30	/* NOT src */
-#define Z3BLTorInverted		0xb0	/* NOT src OR dst */
-#define Z3BLTnand		0x70	/* NOT src OR NOT dst */
-#define Z3BLTset		0xf0	/* 1 */
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 1a13966..f8a3d60 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -282,7 +282,6 @@
 
 static struct backlight_properties riva_bl_data;
 
-/* Call with fb_info->bl_mutex held */
 static int riva_bl_get_level_brightness(struct riva_par *par,
 		int level)
 {
@@ -290,6 +289,7 @@
 	int nlevel;
 
 	/* Get and convert the value */
+	/* No locking on bl_curve since accessing a single value */
 	nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
 
 	if (nlevel < 0)
@@ -302,18 +302,17 @@
 	return nlevel;
 }
 
-/* Call with fb_info->bl_mutex held */
-static int __riva_bl_update_status(struct backlight_device *bd)
+static int riva_bl_update_status(struct backlight_device *bd)
 {
 	struct riva_par *par = class_get_devdata(&bd->class_dev);
 	U032 tmp_pcrt, tmp_pmc;
 	int level;
 
-	if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 	else
-		level = bd->props->brightness;
+		level = bd->props.brightness;
 
 	tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
 	tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
@@ -328,45 +327,16 @@
 	return 0;
 }
 
-static int riva_bl_update_status(struct backlight_device *bd)
-{
-	struct riva_par *par = class_get_devdata(&bd->class_dev);
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	int ret;
-
-	mutex_lock(&info->bl_mutex);
-	ret = __riva_bl_update_status(bd);
-	mutex_unlock(&info->bl_mutex);
-
-	return ret;
-}
-
 static int riva_bl_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties riva_bl_data = {
-	.owner    = THIS_MODULE,
+static struct backlight_ops riva_bl_ops = {
 	.get_brightness = riva_bl_get_brightness,
 	.update_status	= riva_bl_update_status,
-	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
-static void riva_bl_set_power(struct fb_info *info, int power)
-{
-	mutex_lock(&info->bl_mutex);
-
-	if (info->bl_dev) {
-		down(&info->bl_dev->sem);
-		info->bl_dev->props->power = power;
-		__riva_bl_update_status(info->bl_dev);
-		up(&info->bl_dev->sem);
-	}
-
-	mutex_unlock(&info->bl_mutex);
-}
-
 static void riva_bl_init(struct riva_par *par)
 {
 	struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -384,32 +354,22 @@
 
 	snprintf(name, sizeof(name), "rivabl%d", info->node);
 
-	bd = backlight_device_register(name, info->dev, par, &riva_bl_data);
+	bd = backlight_device_register(name, info->dev, par, &riva_bl_ops);
 	if (IS_ERR(bd)) {
 		info->bl_dev = NULL;
 		printk(KERN_WARNING "riva: Backlight registration failed\n");
 		goto error;
 	}
 
-	mutex_lock(&info->bl_mutex);
 	info->bl_dev = bd;
 	fb_bl_default_curve(info, 0,
 		MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL,
 		FB_BACKLIGHT_MAX);
-	mutex_unlock(&info->bl_mutex);
 
-	down(&bd->sem);
-	bd->props->brightness = riva_bl_data.max_brightness;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd->props.brightness = riva_bl_data.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("riva: Backlight initialized (%s)\n", name);
 
@@ -419,35 +379,16 @@
 	return;
 }
 
-static void riva_bl_exit(struct riva_par *par)
+static void riva_bl_exit(struct fb_info *info)
 {
-	struct fb_info *info = pci_get_drvdata(par->pdev);
+	struct backlight_device *bd = info->bl_dev;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-#endif
-
-	mutex_lock(&info->bl_mutex);
-	if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-		if (pmac_backlight == info->bl_dev)
-			pmac_backlight = NULL;
-#endif
-
-		backlight_device_unregister(info->bl_dev);
-
-		printk("riva: Backlight unloaded\n");
-	}
-	mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	backlight_device_unregister(bd);
+	printk("riva: Backlight unloaded\n");
 }
 #else
 static inline void riva_bl_init(struct riva_par *par) {}
-static inline void riva_bl_exit(struct riva_par *par) {}
-static inline void riva_bl_set_power(struct fb_info *info, int power) {}
+static inline void riva_bl_exit(struct fb_info *info) {}
 #endif /* CONFIG_FB_RIVA_BACKLIGHT */
 
 /* ------------------------------------------------------------------------- *
@@ -894,7 +835,8 @@
 	return rc;
 }
 
-static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+static void riva_update_var(struct fb_var_screeninfo *var,
+			    const struct fb_videomode *modedb)
 {
 	NVTRACE_ENTER();
 	var->xres = var->xres_virtual = modedb->xres;
@@ -1101,10 +1043,10 @@
 static int rivafb_open(struct fb_info *info, int user)
 {
 	struct riva_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
 	NVTRACE_ENTER();
-	if (!cnt) {
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
 #ifdef CONFIG_X86
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_MODE  | VGA_SAVE_FONTS;
@@ -1119,7 +1061,8 @@
 	
 		riva_save_state(par, &par->initial_state);
 	}
-	atomic_inc(&par->ref_count);
+	par->ref_count++;
+	mutex_unlock(&par->open_lock);
 	NVTRACE_LEAVE();
 	return 0;
 }
@@ -1127,12 +1070,14 @@
 static int rivafb_release(struct fb_info *info, int user)
 {
 	struct riva_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
 	NVTRACE_ENTER();
-	if (!cnt)
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
+		mutex_unlock(&par->open_lock);
 		return -EINVAL;
-	if (cnt == 1) {
+	}
+	if (par->ref_count == 1) {
 		par->riva.LockUnlock(&par->riva, 0);
 		par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
 		riva_load_state(par, &par->initial_state);
@@ -1141,14 +1086,15 @@
 #endif
 		par->riva.LockUnlock(&par->riva, 1);
 	}
-	atomic_dec(&par->ref_count);
+	par->ref_count--;
+	mutex_unlock(&par->open_lock);
 	NVTRACE_LEAVE();
 	return 0;
 }
 
 static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct fb_videomode *mode;
+	const struct fb_videomode *mode;
 	struct riva_par *par = info->par;
 	int nom, den;		/* translating from pixels->bytes */
 	int mode_valid = 0;
@@ -1343,8 +1289,6 @@
 	SEQout(par, 0x01, tmp);
 	CRTCout(par, 0x1a, vesa);
 
-	riva_bl_set_power(info, blank);
-
 	NVTRACE_LEAVE();
 
 	return 0;
@@ -1980,12 +1924,11 @@
 	default_par = info->par;
 	default_par->pdev = pd;
 
-	info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
+	info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
 	if (info->pixmap.addr == NULL) {
 	    	ret = -ENOMEM;
 		goto err_framebuffer_release;
 	}
-	memset(info->pixmap.addr, 0, 8 * 1024);
 
 	ret = pci_enable_device(pd);
 	if (ret < 0) {
@@ -1999,6 +1942,7 @@
 		goto err_disable_device;
 	}
 
+	mutex_init(&default_par->open_lock);
 	default_par->riva.Architecture = riva_get_arch(pd);
 
 	default_par->Chipset = (pd->vendor << 16) | pd->device;
@@ -2161,14 +2105,15 @@
 	
 	NVTRACE_ENTER();
 
-	riva_bl_exit(par);
-
 #ifdef CONFIG_FB_RIVA_I2C
 	riva_delete_i2c_busses(par);
 	kfree(par->EDID);
 #endif
 
 	unregister_framebuffer(info);
+
+	riva_bl_exit(info);
+
 #ifdef CONFIG_MTRR
 	if (par->mtrr.vram_valid)
 		mtrr_del(par->mtrr.vram, info->fix.smem_start,
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index 01b85e3..0405e83 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -14,7 +14,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
diff --git a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h
index 7fa13fc..48ead6d 100644
--- a/drivers/video/riva/rivafb.h
+++ b/drivers/video/riva/rivafb.h
@@ -53,7 +53,8 @@
 #ifdef CONFIG_X86
 	struct vgastate state;
 #endif
-	atomic_t ref_count;
+	struct mutex open_lock;
+	unsigned int ref_count;
 	unsigned char *EDID;
 	unsigned int Chipset;
 	int forceCRTC;
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index ccef56d..ed34260 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -791,6 +791,8 @@
 
 	info = fbinfo->par;
 	info->fb = fbinfo;
+	info->dev = &pdev->dev;
+
 	platform_set_drvdata(pdev, fbinfo);
 
 	dprintk("devinit\n");
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
new file mode 100644
index 0000000..3162c37
--- /dev/null
+++ b/drivers/video/s3fb.c
@@ -0,0 +1,1180 @@
+/*
+ * linux/drivers/video/s3fb.c -- Frame buffer device driver for S3 Trio/Virge
+ *
+ * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ * 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.
+ *
+ * Code is based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
+ * which is based on the code of neofb.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/svga.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+struct s3fb_info {
+	int chip, rev, mclk_freq;
+	int mtrr_reg;
+	struct vgastate state;
+	struct mutex open_lock;
+	unsigned int ref_count;
+	u32 pseudo_palette[16];
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+static const struct svga_fb_format s3fb_formats[] = {
+	{ 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4,	FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
+		FB_TYPE_INTERLEAVED_PLANES, 1,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 4, 8},
+	{16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 4},
+	{16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 4},
+	{24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 1, 2},
+	{32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 1, 2},
+	SVGA_FORMAT_END
+};
+
+
+static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3,
+	60000, 240000, 14318};
+
+static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512};
+
+static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+",
+			"S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
+			"S3 Plato/PX", "S3 Aurora64VP", "S3 Virge",
+			"S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
+			"S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P"};
+
+#define CHIP_UNKNOWN		0x00
+#define CHIP_732_TRIO32		0x01
+#define CHIP_764_TRIO64		0x02
+#define CHIP_765_TRIO64VP	0x03
+#define CHIP_767_TRIO64UVP	0x04
+#define CHIP_775_TRIO64V2_DX	0x05
+#define CHIP_785_TRIO64V2_GX	0x06
+#define CHIP_551_PLATO_PX	0x07
+#define CHIP_M65_AURORA64VP	0x08
+#define CHIP_325_VIRGE		0x09
+#define CHIP_988_VIRGE_VX	0x0A
+#define CHIP_375_VIRGE_DX	0x0B
+#define CHIP_385_VIRGE_GX	0x0C
+#define CHIP_356_VIRGE_GX2	0x0D
+#define CHIP_357_VIRGE_GX2P	0x0E
+#define CHIP_359_VIRGE_GX2P	0x0F
+
+#define CHIP_XXX_TRIO		0x80
+#define CHIP_XXX_TRIO64V2_DXGX	0x81
+#define CHIP_XXX_VIRGE_DXGX	0x82
+
+#define CHIP_UNDECIDED_FLAG	0x80
+#define CHIP_MASK		0xFF
+
+/* CRT timing register sets */
+
+static const struct vga_regset s3_h_total_regs[]        = {{0x00, 0, 7}, {0x5D, 0, 0}, VGA_REGSET_END};
+static const struct vga_regset s3_h_display_regs[]      = {{0x01, 0, 7}, {0x5D, 1, 1}, VGA_REGSET_END};
+static const struct vga_regset s3_h_blank_start_regs[]  = {{0x02, 0, 7}, {0x5D, 2, 2}, VGA_REGSET_END};
+static const struct vga_regset s3_h_blank_end_regs[]    = {{0x03, 0, 4}, {0x05, 7, 7}, VGA_REGSET_END};
+static const struct vga_regset s3_h_sync_start_regs[]   = {{0x04, 0, 7}, {0x5D, 4, 4}, VGA_REGSET_END};
+static const struct vga_regset s3_h_sync_end_regs[]     = {{0x05, 0, 4}, VGA_REGSET_END};
+
+static const struct vga_regset s3_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x5E, 0, 0}, VGA_REGSET_END};
+static const struct vga_regset s3_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x5E, 1, 1}, VGA_REGSET_END};
+static const struct vga_regset s3_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x5E, 2, 2}, VGA_REGSET_END};
+static const struct vga_regset s3_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
+static const struct vga_regset s3_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x5E, 4, 4}, VGA_REGSET_END};
+static const struct vga_regset s3_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
+
+static const struct vga_regset s3_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END};
+static const struct vga_regset s3_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x31, 4, 5}, {0x51, 0, 1}, VGA_REGSET_END};
+static const struct vga_regset s3_offset_regs[]         = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */
+
+static const struct svga_timing_regs s3_timing_regs     = {
+	s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs,
+	s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs,
+	s3_v_total_regs, s3_v_display_regs, s3_v_blank_start_regs,
+	s3_v_blank_end_regs, s3_v_sync_start_regs, s3_v_sync_end_regs,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+/* Module parameters */
+
+
+static char *mode = "640x480-8@60";
+
+#ifdef CONFIG_MTRR
+static int mtrr = 1;
+#endif
+
+static int fasttext = 1;
+
+
+MODULE_AUTHOR("(c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for S3 Trio/Virge");
+
+module_param(mode, charp, 0444);
+MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
+
+module_param(fasttext, int, 0644);
+MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, default=1)");
+
+
+/* ------------------------------------------------------------------------- */
+
+/* Set font in S3 fast text mode */
+
+static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
+{
+	const u8 *font = map->data;
+	u8* fb = (u8 *) info->screen_base;
+	int i, c;
+
+	if ((map->width != 8) || (map->height != 16) ||
+	    (map->depth != 1) || (map->length != 256)) {
+	    	printk(KERN_ERR "fb%d: unsupported font parameters: width %d, height %d, depth %d, length %d\n",
+			info->node, map->width, map->height, map->depth, map->length);
+		return;
+	}
+
+	fb += 2;
+	for (i = 0; i < map->height; i++) {
+		for (c = 0; c < map->length; c++) {
+			fb[c * 4] = font[c * map->height + i];
+		}
+		fb += 1024;
+	}
+}
+
+
+
+static struct fb_tile_ops s3fb_tile_ops = {
+	.fb_settile	= svga_settile,
+	.fb_tilecopy	= svga_tilecopy,
+	.fb_tilefill    = svga_tilefill,
+	.fb_tileblit    = svga_tileblit,
+	.fb_tilecursor  = svga_tilecursor,
+};
+
+static struct fb_tile_ops s3fb_fast_tile_ops = {
+	.fb_settile	= s3fb_settile_fast,
+	.fb_tilecopy	= svga_tilecopy,
+	.fb_tilefill    = svga_tilefill,
+	.fb_tileblit    = svga_tileblit,
+	.fb_tilecursor  = svga_tilecursor,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+/* image data is MSB-first, fb structure is MSB-first too */
+static inline u32 expand_color(u32 c)
+{
+	return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
+}
+
+/* s3fb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void s3fb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u32 fg = expand_color(image->fg_color);
+	u32 bg = expand_color(image->bg_color);
+	const u8 *src1, *src;
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	u32 val;
+	int x, y;
+
+	src1 = image->data;
+	dst1 = info->screen_base + (image->dy * info->fix.line_length)
+		 + ((image->dx / 8) * 4);
+
+	for (y = 0; y < image->height; y++) {
+		src = src1;
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < image->width; x += 8) {
+			val = *(src++) * 0x01010101;
+			val = (val & fg) | (~val & bg);
+			fb_writel(val, dst++);
+		}
+		src1 += image->width / 8;
+		dst1 += info->fix.line_length;
+	}
+
+}
+
+/* s3fb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
+static void s3fb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	u32 fg = expand_color(rect->color);
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	int x, y;
+
+	dst1 = info->screen_base + (rect->dy * info->fix.line_length)
+		 + ((rect->dx / 8) * 4);
+
+	for (y = 0; y < rect->height; y++) {
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < rect->width; x += 8) {
+			fb_writel(fg, dst++);
+		}
+		dst1 += info->fix.line_length;
+	}
+}
+
+
+/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
+static inline u32 expand_pixel(u32 c)
+{
+	return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
+		((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
+}
+
+/* s3fb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void s3fb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u32 fg = image->fg_color * 0x11111111;
+	u32 bg = image->bg_color * 0x11111111;
+	const u8 *src1, *src;
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	u32 val;
+	int x, y;
+
+	src1 = image->data;
+	dst1 = info->screen_base + (image->dy * info->fix.line_length)
+		 + ((image->dx / 8) * 4);
+
+	for (y = 0; y < image->height; y++) {
+		src = src1;
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < image->width; x += 8) {
+			val = expand_pixel(*(src++));
+			val = (val & fg) | (~val & bg);
+			fb_writel(val, dst++);
+		}
+		src1 += image->width / 8;
+		dst1 += info->fix.line_length;
+	}
+}
+
+static void s3fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
+	    && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
+		if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
+			s3fb_iplan_imageblit(info, image);
+		else
+			s3fb_cfb4_imageblit(info, image);
+	} else
+		cfb_imageblit(info, image);
+}
+
+static void s3fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	if ((info->var.bits_per_pixel == 4)
+	    && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
+	    && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
+		s3fb_iplan_fillrect(info, rect);
+	 else
+		cfb_fillrect(info, rect);
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
+{
+	u16 m, n, r;
+	u8 regval;
+
+	svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node);
+
+	/* Set VGA misc register  */
+	regval = vga_r(NULL, VGA_MIS_R);
+	vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
+
+	/* Set S3 clock registers */
+	vga_wseq(NULL, 0x12, ((n - 2) | (r << 5)));
+	vga_wseq(NULL, 0x13, m - 2);
+
+	udelay(1000);
+
+	/* Activate clock - write 0, 1, 0 to seq/15 bit 5 */
+	regval = vga_rseq (NULL, 0x15); /* | 0x80; */
+	vga_wseq(NULL, 0x15, regval & ~(1<<5));
+	vga_wseq(NULL, 0x15, regval |  (1<<5));
+	vga_wseq(NULL, 0x15, regval & ~(1<<5));
+}
+
+
+/* Open framebuffer */
+
+static int s3fb_open(struct fb_info *info, int user)
+{
+	struct s3fb_info *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		memset(&(par->state), 0, sizeof(struct vgastate));
+		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
+		par->state.num_crtc = 0x70;
+		par->state.num_seq = 0x20;
+		save_vga(&(par->state));
+	}
+
+	par->ref_count++;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+/* Close framebuffer */
+
+static int s3fb_release(struct fb_info *info, int user)
+{
+	struct s3fb_info *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		mutex_unlock(&(par->open_lock));
+		return -EINVAL;
+	}
+
+	if (par->ref_count == 1)
+		restore_vga(&(par->state));
+
+	par->ref_count--;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+/* Validate passed in var */
+
+static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct s3fb_info *par = info->par;
+	int rv, mem, step;
+
+	/* Find appropriate format */
+	rv = svga_match_format (s3fb_formats, var, NULL);
+	if ((rv < 0) || ((par->chip == CHIP_988_VIRGE_VX) ? (rv == 7) : (rv == 6)))
+	{		/* 24bpp on VIRGE VX, 32bpp on others */
+		printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node);
+		return rv;
+	}
+
+	/* Do not allow to have real resoulution larger than virtual */
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+
+	/* Round up xres_virtual to have proper alignment of lines */
+	step = s3fb_formats[rv].xresstep - 1;
+	var->xres_virtual = (var->xres_virtual+step) & ~step;
+
+	/* Check whether have enough memory */
+	mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
+	if (mem > info->screen_size)
+	{
+		printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n",
+			info->node, mem >> 10, (unsigned int) (info->screen_size >> 10));
+		return -EINVAL;
+	}
+
+	rv = svga_check_timings (&s3_timing_regs, var, info->node);
+	if (rv < 0)
+	{
+		printk(KERN_ERR "fb%d: invalid timings requested\n", info->node);
+		return rv;
+	}
+
+	return 0;
+}
+
+/* Set video mode from par */
+
+static int s3fb_set_par(struct fb_info *info)
+{
+	struct s3fb_info *par = info->par;
+	u32 value, mode, hmul, offset_value, screen_size, multiplex;
+	u32 bpp = info->var.bits_per_pixel;
+
+	if (bpp != 0) {
+		info->fix.ypanstep = 1;
+		info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
+
+		info->flags &= ~FBINFO_MISC_TILEBLITTING;
+		info->tileops = NULL;
+
+		offset_value = (info->var.xres_virtual * bpp) / 64;
+		screen_size = info->var.yres_virtual * info->fix.line_length;
+	} else {
+		info->fix.ypanstep = 16;
+		info->fix.line_length = 0;
+
+		info->flags |= FBINFO_MISC_TILEBLITTING;
+		info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops;
+
+		offset_value = info->var.xres_virtual / 16;
+		screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
+	}
+
+	info->var.xoffset = 0;
+	info->var.yoffset = 0;
+	info->var.activate = FB_ACTIVATE_NOW;
+
+	/* Unlock registers */
+	vga_wcrt(NULL, 0x38, 0x48);
+	vga_wcrt(NULL, 0x39, 0xA5);
+	vga_wseq(NULL, 0x08, 0x06);
+	svga_wcrt_mask(0x11, 0x00, 0x80);
+
+	/* Blank screen and turn off sync */
+	svga_wseq_mask(0x01, 0x20, 0x20);
+	svga_wcrt_mask(0x17, 0x00, 0x80);
+
+	/* Set default values */
+	svga_set_default_gfx_regs();
+	svga_set_default_atc_regs();
+	svga_set_default_seq_regs();
+	svga_set_default_crt_regs();
+	svga_wcrt_multi(s3_line_compare_regs, 0xFFFFFFFF);
+	svga_wcrt_multi(s3_start_address_regs, 0);
+
+	/* S3 specific initialization */
+	svga_wcrt_mask(0x58, 0x10, 0x10); /* enable linear framebuffer */
+	svga_wcrt_mask(0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */
+
+/*	svga_wcrt_mask(0x33, 0x08, 0x08); */ /* DDR ?	*/
+/*	svga_wcrt_mask(0x43, 0x01, 0x01); */ /* DDR ?	*/
+	svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ?	*/
+	svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ?	*/
+
+	svga_wcrt_mask(0x5D, 0x00, 0x28); // Clear strange HSlen bits
+
+/*	svga_wcrt_mask(0x58, 0x03, 0x03); */
+
+/*	svga_wcrt_mask(0x53, 0x12, 0x13); */ /* enable MMIO */
+/*	svga_wcrt_mask(0x40, 0x08, 0x08); */ /* enable write buffer */
+
+
+	/* Set the offset register */
+	pr_debug("fb%d: offset register       : %d\n", info->node, offset_value);
+	svga_wcrt_multi(s3_offset_regs, offset_value);
+
+	vga_wcrt(NULL, 0x54, 0x18); /* M parameter */
+	vga_wcrt(NULL, 0x60, 0xff); /* N parameter */
+	vga_wcrt(NULL, 0x61, 0xff); /* L parameter */
+	vga_wcrt(NULL, 0x62, 0xff); /* L parameter */
+
+	vga_wcrt(NULL, 0x3A, 0x35);
+	svga_wattr(0x33, 0x00);
+
+	if (info->var.vmode & FB_VMODE_DOUBLE)
+		svga_wcrt_mask(0x09, 0x80, 0x80);
+	else
+		svga_wcrt_mask(0x09, 0x00, 0x80);
+
+	if (info->var.vmode & FB_VMODE_INTERLACED)
+		svga_wcrt_mask(0x42, 0x20, 0x20);
+	else
+		svga_wcrt_mask(0x42, 0x00, 0x20);
+
+	/* Disable hardware graphics cursor */
+	svga_wcrt_mask(0x45, 0x00, 0x01);
+	/* Disable Streams engine */
+	svga_wcrt_mask(0x67, 0x00, 0x0C);
+
+	mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix));
+
+	/* S3 virge DX hack */
+	if (par->chip == CHIP_375_VIRGE_DX) {
+		vga_wcrt(NULL, 0x86, 0x80);
+		vga_wcrt(NULL, 0x90, 0x00);
+	}
+
+	/* S3 virge VX hack */
+	if (par->chip == CHIP_988_VIRGE_VX) {
+		vga_wcrt(NULL, 0x50, 0x00);
+		vga_wcrt(NULL, 0x67, 0x50);
+
+		vga_wcrt(NULL, 0x63, (mode <= 2) ? 0x90 : 0x09);
+		vga_wcrt(NULL, 0x66, 0x90);
+	}
+
+	svga_wcrt_mask(0x31, 0x00, 0x40);
+	multiplex = 0;
+	hmul = 1;
+
+	/* Set mode-specific register values */
+	switch (mode) {
+	case 0:
+		pr_debug("fb%d: text mode\n", info->node);
+		svga_set_textmode_vga_regs();
+
+		/* Set additional registers like in 8-bit mode */
+		svga_wcrt_mask(0x50, 0x00, 0x30);
+		svga_wcrt_mask(0x67, 0x00, 0xF0);
+
+		/* Disable enhanced mode */
+		svga_wcrt_mask(0x3A, 0x00, 0x30);
+
+		if (fasttext) {
+			pr_debug("fb%d: high speed text mode set\n", info->node);
+			svga_wcrt_mask(0x31, 0x40, 0x40);
+		}
+		break;
+	case 1:
+		pr_debug("fb%d: 4 bit pseudocolor\n", info->node);
+		vga_wgfx(NULL, VGA_GFX_MODE, 0x40);
+
+		/* Set additional registers like in 8-bit mode */
+		svga_wcrt_mask(0x50, 0x00, 0x30);
+		svga_wcrt_mask(0x67, 0x00, 0xF0);
+
+		/* disable enhanced mode */
+		svga_wcrt_mask(0x3A, 0x00, 0x30);
+		break;
+	case 2:
+		pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);
+
+		/* Set additional registers like in 8-bit mode */
+		svga_wcrt_mask(0x50, 0x00, 0x30);
+		svga_wcrt_mask(0x67, 0x00, 0xF0);
+
+		/* disable enhanced mode */
+		svga_wcrt_mask(0x3A, 0x00, 0x30);
+		break;
+	case 3:
+		pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
+		if (info->var.pixclock > 20000) {
+			svga_wcrt_mask(0x50, 0x00, 0x30);
+			svga_wcrt_mask(0x67, 0x00, 0xF0);
+		} else {
+			svga_wcrt_mask(0x50, 0x00, 0x30);
+			svga_wcrt_mask(0x67, 0x10, 0xF0);
+			multiplex = 1;
+		}
+		break;
+	case 4:
+		pr_debug("fb%d: 5/5/5 truecolor\n", info->node);
+		if (par->chip == CHIP_988_VIRGE_VX) {
+			if (info->var.pixclock > 20000)
+				svga_wcrt_mask(0x67, 0x20, 0xF0);
+			else
+				svga_wcrt_mask(0x67, 0x30, 0xF0);
+		} else {
+			svga_wcrt_mask(0x50, 0x10, 0x30);
+			svga_wcrt_mask(0x67, 0x30, 0xF0);
+			hmul = 2;
+		}
+		break;
+	case 5:
+		pr_debug("fb%d: 5/6/5 truecolor\n", info->node);
+		if (par->chip == CHIP_988_VIRGE_VX) {
+			if (info->var.pixclock > 20000)
+				svga_wcrt_mask(0x67, 0x40, 0xF0);
+			else
+				svga_wcrt_mask(0x67, 0x50, 0xF0);
+		} else {
+			svga_wcrt_mask(0x50, 0x10, 0x30);
+			svga_wcrt_mask(0x67, 0x50, 0xF0);
+			hmul = 2;
+		}
+		break;
+	case 6:
+		/* VIRGE VX case */
+		pr_debug("fb%d: 8/8/8 truecolor\n", info->node);
+		svga_wcrt_mask(0x67, 0xD0, 0xF0);
+		break;
+	case 7:
+		pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node);
+		svga_wcrt_mask(0x50, 0x30, 0x30);
+		svga_wcrt_mask(0x67, 0xD0, 0xF0);
+		break;
+	default:
+		printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node);
+		return -EINVAL;
+	}
+
+	if (par->chip != CHIP_988_VIRGE_VX) {
+		svga_wseq_mask(0x15, multiplex ? 0x10 : 0x00, 0x10);
+		svga_wseq_mask(0x18, multiplex ? 0x80 : 0x00, 0x80);
+	}
+
+	s3_set_pixclock(info, info->var.pixclock);
+	svga_set_timings(&s3_timing_regs, &(info->var), hmul, 1,
+			 (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,
+			 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
+			 hmul, info->node);
+
+	/* Set interlaced mode start/end register */
+	value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
+	value = ((value * hmul) / 8) - 5;
+	vga_wcrt(NULL, 0x3C, (value + 1) / 2);
+
+	memset((u8*)info->screen_base, 0x00, screen_size);
+	/* Device and screen back on */
+	svga_wcrt_mask(0x17, 0x80, 0x80);
+	svga_wseq_mask(0x01, 0x00, 0x20);
+
+	return 0;
+}
+
+/* Set a colour register */
+
+static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+				u_int transp, struct fb_info *fb)
+{
+	switch (fb->var.bits_per_pixel) {
+	case 0:
+	case 4:
+		if (regno >= 16)
+			return -EINVAL;
+
+		if ((fb->var.bits_per_pixel == 4) &&
+		    (fb->var.nonstd == 0)) {
+			outb(0xF0, VGA_PEL_MSK);
+			outb(regno*16, VGA_PEL_IW);
+		} else {
+			outb(0x0F, VGA_PEL_MSK);
+			outb(regno, VGA_PEL_IW);
+		}
+		outb(red >> 10, VGA_PEL_D);
+		outb(green >> 10, VGA_PEL_D);
+		outb(blue >> 10, VGA_PEL_D);
+		break;
+	case 8:
+		if (regno >= 256)
+			return -EINVAL;
+
+		outb(0xFF, VGA_PEL_MSK);
+		outb(regno, VGA_PEL_IW);
+		outb(red >> 10, VGA_PEL_D);
+		outb(green >> 10, VGA_PEL_D);
+		outb(blue >> 10, VGA_PEL_D);
+		break;
+	case 16:
+		if (regno >= 16)
+			return -EINVAL;
+
+		if (fb->var.green.length == 5)
+			((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
+				((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+		else if (fb->var.green.length == 6)
+			((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
+				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+		else return -EINVAL;
+		break;
+	case 24:
+	case 32:
+		if (regno >= 16)
+			return -EINVAL;
+
+		((u32*)fb->pseudo_palette)[regno] = ((transp & 0xFF00) << 16) | ((red & 0xFF00) << 8) |
+			(green & 0xFF00) | ((blue & 0xFF00) >> 8);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+/* Set the display blanking state */
+
+static int s3fb_blank(int blank_mode, struct fb_info *info)
+{
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		pr_debug("fb%d: unblank\n", info->node);
+		svga_wcrt_mask(0x56, 0x00, 0x06);
+		svga_wseq_mask(0x01, 0x00, 0x20);
+		break;
+	case FB_BLANK_NORMAL:
+		pr_debug("fb%d: blank\n", info->node);
+		svga_wcrt_mask(0x56, 0x00, 0x06);
+		svga_wseq_mask(0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		pr_debug("fb%d: hsync\n", info->node);
+		svga_wcrt_mask(0x56, 0x02, 0x06);
+		svga_wseq_mask(0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		pr_debug("fb%d: vsync\n", info->node);
+		svga_wcrt_mask(0x56, 0x04, 0x06);
+		svga_wseq_mask(0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_POWERDOWN:
+		pr_debug("fb%d: sync down\n", info->node);
+		svga_wcrt_mask(0x56, 0x06, 0x06);
+		svga_wseq_mask(0x01, 0x20, 0x20);
+		break;
+	}
+
+	return 0;
+}
+
+
+/* Pan the display */
+
+static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) {
+
+	unsigned int offset;
+
+	/* Validate the offsets */
+	if ((var->xoffset + var->xres) > var->xres_virtual)
+		return -EINVAL;
+	if ((var->yoffset + var->yres) > var->yres_virtual)
+		return -EINVAL;
+
+	/* Calculate the offset */
+	if (var->bits_per_pixel == 0) {
+		offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
+		offset = offset >> 2;
+	} else {
+		offset = (var->yoffset * info->fix.line_length) +
+			 (var->xoffset * var->bits_per_pixel / 8);
+		offset = offset >> 2;
+	}
+
+	/* Set the offset */
+	svga_wcrt_multi(s3_start_address_regs, offset);
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Frame buffer operations */
+
+static struct fb_ops s3fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= s3fb_open,
+	.fb_release	= s3fb_release,
+	.fb_check_var	= s3fb_check_var,
+	.fb_set_par	= s3fb_set_par,
+	.fb_setcolreg	= s3fb_setcolreg,
+	.fb_blank	= s3fb_blank,
+	.fb_pan_display	= s3fb_pan_display,
+	.fb_fillrect	= s3fb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= s3fb_imageblit,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static int __devinit s3_identification(int chip)
+{
+	if (chip == CHIP_XXX_TRIO) {
+		u8 cr30 = vga_rcrt(NULL, 0x30);
+		u8 cr2e = vga_rcrt(NULL, 0x2e);
+		u8 cr2f = vga_rcrt(NULL, 0x2f);
+
+		if ((cr30 == 0xE0) || (cr30 == 0xE1)) {
+			if (cr2e == 0x10)
+				return CHIP_732_TRIO32;
+			if (cr2e == 0x11) {
+				if (! (cr2f & 0x40))
+					return CHIP_764_TRIO64;
+				else
+					return CHIP_765_TRIO64VP;
+			}
+		}
+	}
+
+	if (chip == CHIP_XXX_TRIO64V2_DXGX) {
+		u8 cr6f = vga_rcrt(NULL, 0x6f);
+
+		if (! (cr6f & 0x01))
+			return CHIP_775_TRIO64V2_DX;
+		else
+			return CHIP_785_TRIO64V2_GX;
+	}
+
+	if (chip == CHIP_XXX_VIRGE_DXGX) {
+		u8 cr6f = vga_rcrt(NULL, 0x6f);
+
+		if (! (cr6f & 0x01))
+			return CHIP_375_VIRGE_DX;
+		else
+			return CHIP_385_VIRGE_GX;
+	}
+
+	return CHIP_UNKNOWN;
+}
+
+
+/* PCI probe */
+
+static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct fb_info *info;
+	struct s3fb_info *par;
+	int rc;
+	u8 regval, cr38, cr39;
+
+	/* Ignore secondary VGA device because there is no VGA arbitration */
+	if (! svga_primary_device(dev)) {
+		dev_info(&(dev->dev), "ignoring secondary device\n");
+		return -ENODEV;
+	}
+
+	/* Allocate and fill driver data structure */
+	info = framebuffer_alloc(sizeof(struct s3fb_info), NULL);
+	if (!info) {
+		dev_err(&(dev->dev), "cannot allocate memory\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	mutex_init(&par->open_lock);
+
+	info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
+	info->fbops = &s3fb_ops;
+
+	/* Prepare PCI device */
+	rc = pci_enable_device(dev);
+	if (rc < 0) {
+		dev_err(&(dev->dev), "cannot enable PCI device\n");
+		goto err_enable_device;
+	}
+
+	rc = pci_request_regions(dev, "s3fb");
+	if (rc < 0) {
+		dev_err(&(dev->dev), "cannot reserve framebuffer region\n");
+		goto err_request_regions;
+	}
+
+
+	info->fix.smem_start = pci_resource_start(dev, 0);
+	info->fix.smem_len = pci_resource_len(dev, 0);
+
+	/* Map physical IO memory address into kernel space */
+	info->screen_base = pci_iomap(dev, 0, 0);
+	if (! info->screen_base) {
+		rc = -ENOMEM;
+		dev_err(&(dev->dev), "iomap for framebuffer failed\n");
+		goto err_iomap;
+	}
+
+	/* Unlock regs */
+	cr38 = vga_rcrt(NULL, 0x38);
+	cr39 = vga_rcrt(NULL, 0x39);
+	vga_wseq(NULL, 0x08, 0x06);
+	vga_wcrt(NULL, 0x38, 0x48);
+	vga_wcrt(NULL, 0x39, 0xA5);
+
+	/* Find how many physical memory there is on card */
+	/* 0x36 register is accessible even if other registers are locked */
+	regval = vga_rcrt(NULL, 0x36);
+	info->screen_size = s3_memsizes[regval >> 5] << 10;
+	info->fix.smem_len = info->screen_size;
+
+	par->chip = id->driver_data & CHIP_MASK;
+	par->rev = vga_rcrt(NULL, 0x2f);
+	if (par->chip & CHIP_UNDECIDED_FLAG)
+		par->chip = s3_identification(par->chip);
+
+	/* Find MCLK frequency */
+	regval = vga_rseq(NULL, 0x10);
+	par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F)  + 2);
+	par->mclk_freq = par->mclk_freq >> (regval >> 5);
+
+	/* Restore locks */
+	vga_wcrt(NULL, 0x38, cr38);
+	vga_wcrt(NULL, 0x39, cr39);
+
+	strcpy(info->fix.id, s3_names [par->chip]);
+	info->fix.mmio_start = 0;
+	info->fix.mmio_len = 0;
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	info->fix.ypanstep = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->pseudo_palette = (void*) (par->pseudo_palette);
+
+	/* Prepare startup mode */
+	rc = fb_find_mode(&(info->var), info, mode, NULL, 0, NULL, 8);
+	if (! ((rc == 1) || (rc == 2))) {
+		rc = -EINVAL;
+		dev_err(&(dev->dev), "mode %s not found\n", mode);
+		goto err_find_mode;
+	}
+
+	rc = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (rc < 0) {
+		dev_err(&(dev->dev), "cannot allocate colormap\n");
+		goto err_alloc_cmap;
+	}
+
+	rc = register_framebuffer(info);
+	if (rc < 0) {
+		dev_err(&(dev->dev), "cannot register framebuffer\n");
+		goto err_reg_fb;
+	}
+
+	printk(KERN_INFO "fb%d: %s on %s, %d MB RAM, %d MHz MCLK\n", info->node, info->fix.id,
+		 pci_name(dev), info->fix.smem_len >> 20, (par->mclk_freq + 500) / 1000);
+
+	if (par->chip == CHIP_UNKNOWN)
+		printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n",
+			info->node, vga_rcrt(NULL, 0x2d), vga_rcrt(NULL, 0x2e),
+			vga_rcrt(NULL, 0x2f), vga_rcrt(NULL, 0x30));
+
+	/* Record a reference to the driver data */
+	pci_set_drvdata(dev, info);
+
+#ifdef CONFIG_MTRR
+	if (mtrr) {
+		par->mtrr_reg = -1;
+		par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+	}
+#endif
+
+	return 0;
+
+	/* Error handling */
+err_reg_fb:
+	fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+	pci_iounmap(dev, info->screen_base);
+err_iomap:
+	pci_release_regions(dev);
+err_request_regions:
+/*	pci_disable_device(dev); */
+err_enable_device:
+	framebuffer_release(info);
+	return rc;
+}
+
+
+/* PCI remove */
+
+static void __devexit s3_pci_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct s3fb_info *par = info->par;
+
+	if (info) {
+
+#ifdef CONFIG_MTRR
+		if (par->mtrr_reg >= 0) {
+			mtrr_del(par->mtrr_reg, 0, 0);
+			par->mtrr_reg = -1;
+		}
+#endif
+
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+
+		pci_iounmap(dev, info->screen_base);
+		pci_release_regions(dev);
+/*		pci_disable_device(dev); */
+
+		pci_set_drvdata(dev, NULL);
+		framebuffer_release(info);
+	}
+}
+
+/* PCI suspend */
+
+static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct s3fb_info *par = info->par;
+
+	dev_info(&(dev->dev), "suspend\n");
+
+	acquire_console_sem();
+	mutex_lock(&(par->open_lock));
+
+	if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
+		mutex_unlock(&(par->open_lock));
+		release_console_sem();
+		return 0;
+	}
+
+	fb_set_suspend(info, 1);
+
+	pci_save_state(dev);
+	pci_disable_device(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, state));
+
+	mutex_unlock(&(par->open_lock));
+	release_console_sem();
+
+	return 0;
+}
+
+
+/* PCI resume */
+
+static int s3_pci_resume(struct pci_dev* dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct s3fb_info *par = info->par;
+
+	dev_info(&(dev->dev), "resume\n");
+
+	acquire_console_sem();
+	mutex_lock(&(par->open_lock));
+
+	if (par->ref_count == 0) {
+		mutex_unlock(&(par->open_lock));
+		release_console_sem();
+		return 0;
+	}
+
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+	pci_enable_device(dev);
+	pci_set_master(dev);
+
+	s3fb_set_par(info);
+	fb_set_suspend(info, 0);
+
+	mutex_unlock(&(par->open_lock));
+	release_console_sem();
+
+	return 0;
+}
+
+
+/* List of boards that we are trying to support */
+
+static struct pci_device_id s3_devices[] __devinitdata = {
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8810), .driver_data = CHIP_XXX_TRIO},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8811), .driver_data = CHIP_XXX_TRIO},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8812), .driver_data = CHIP_M65_AURORA64VP},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8814), .driver_data = CHIP_767_TRIO64UVP},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8901), .driver_data = CHIP_XXX_TRIO64V2_DXGX},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8902), .driver_data = CHIP_551_PLATO_PX},
+
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
+
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+
+MODULE_DEVICE_TABLE(pci, s3_devices);
+
+static struct pci_driver s3fb_pci_driver = {
+	.name		= "s3fb",
+	.id_table	= s3_devices,
+	.probe		= s3_pci_probe,
+	.remove		= __devexit_p(s3_pci_remove),
+	.suspend	= s3_pci_suspend,
+	.resume		= s3_pci_resume,
+};
+
+/* Parse user speficied options */
+
+#ifndef MODULE
+static int  __init s3fb_setup(char *options)
+{
+	char *opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+
+		if (!*opt)
+			continue;
+#ifdef CONFIG_MTRR
+		else if (!strcmp(opt, "mtrr:"))
+			mtrr = simple_strtoul(opt + 5, NULL, 0);
+#endif
+		else if (!strcmp(opt, "fasttext:"))
+			mtrr = simple_strtoul(opt + 9, NULL, 0);
+		else
+			mode = opt;
+	}
+
+	return 0;
+}
+#endif
+
+/* Cleanup */
+
+static void __exit s3fb_cleanup(void)
+{
+	pr_debug("s3fb: cleaning up\n");
+	pci_unregister_driver(&s3fb_pci_driver);
+}
+
+/* Driver Initialisation */
+
+static int __init s3fb_init(void)
+{
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("s3fb", &option))
+		return -ENODEV;
+	s3fb_setup(option);
+#endif
+
+	pr_debug("s3fb: initializing\n");
+	return pci_register_driver(&s3fb_pci_driver);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Modularization */
+
+module_init(s3fb_init);
+module_exit(s3fb_cleanup);
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
index 0b07f6a..48066ef 100644
--- a/drivers/video/sa1100fb.h
+++ b/drivers/video/sa1100fb.h
@@ -110,9 +110,7 @@
 #endif
 };
 
-#define __type_entry(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))
-
-#define TO_INF(ptr,member)	__type_entry(ptr,struct sa1100fb_info,member)
+#define TO_INF(ptr,member)	container_of(ptr,struct sa1100fb_info,member)
 
 #define SA1100_PALETTE_MODE_VAL(bpp)    (((bpp) & 0x018) << 9)
 
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 1411f3b..8db066c 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/fb.h>
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 82b3dea..4afa305 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -833,7 +833,8 @@
 	vga_out8(0x3d5, cr66, par);
 }
 
-static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+static void savage_update_var(struct fb_var_screeninfo *var,
+			      const struct fb_videomode *modedb)
 {
 	var->xres = var->xres_virtual = modedb->xres;
 	var->yres = modedb->yres;
@@ -902,7 +903,7 @@
 	}
 
 	if (!mode_valid) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -2206,11 +2207,10 @@
 			     info->monspecs.modedb, info->monspecs.modedb_len,
 			     NULL, 8);
 	} else if (info->monspecs.modedb != NULL) {
-		struct fb_videomode *modedb;
+		const struct fb_videomode *mode;
 
-		modedb = fb_find_best_display(&info->monspecs,
-					      &info->modelist);
-		savage_update_var(&info->var, modedb);
+		mode = fb_find_best_display(&info->monspecs, &info->modelist);
+		savage_update_var(&info->var, mode);
 	}
 
 	/* maximize virtual vertical length */
diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c
index 2ab3868..c311ad3 100644
--- a/drivers/video/sis/init.c
+++ b/drivers/video/sis/init.c
@@ -317,23 +317,23 @@
 }
 #endif
 
-BOOLEAN
+bool
 SiSInitPtr(struct SiS_Private *SiS_Pr)
 {
    if(SiS_Pr->ChipType < SIS_315H) {
 #ifdef SIS300
       InitTo300Pointer(SiS_Pr);
 #else
-      return FALSE;
+      return false;
 #endif
    } else {
 #ifdef SIS315H
       InitTo310Pointer(SiS_Pr);
 #else
-      return FALSE;
+      return false;
 #endif
    }
-   return TRUE;
+   return true;
 }
 
 /*********************************************/
@@ -345,7 +345,7 @@
 #endif
 unsigned short
 SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
-		int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
+		int Depth, bool FSTN, int LCDwidth, int LCDheight)
 {
    unsigned short ModeIndex = 0;
 
@@ -483,7 +483,7 @@
 
 unsigned short
 SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
-		int Depth, BOOLEAN FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
+		int Depth, bool FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
 		unsigned int VBFlags2)
 {
    unsigned short ModeIndex = 0;
@@ -873,7 +873,7 @@
 		break;
    }
 
-   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, FALSE, 0, 0);
+   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, false, 0, 0);
 }
 
 
@@ -1020,12 +1020,12 @@
 
    /* 661 and newer: NEVER write non-zero to SR11[7:4] */
    /* (SR11 is used for DDC and in enable/disablebridge) */
-   SiS_Pr->SiS_SensibleSR11 = FALSE;
+   SiS_Pr->SiS_SensibleSR11 = false;
    SiS_Pr->SiS_MyCR63 = 0x63;
    if(SiS_Pr->ChipType >= SIS_330) {
       SiS_Pr->SiS_MyCR63 = 0x53;
       if(SiS_Pr->ChipType >= SIS_661) {
-         SiS_Pr->SiS_SensibleSR11 = TRUE;
+         SiS_Pr->SiS_SensibleSR11 = true;
       }
    }
 
@@ -1253,7 +1253,7 @@
 /*        HELPER: Determine ROM usage        */
 /*********************************************/
 
-BOOLEAN
+bool
 SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
 {
    unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
@@ -1261,16 +1261,16 @@
 
    if(SiS_Pr->ChipType >= XGI_20) {
       /* XGI ROMs don't qualify */
-      return FALSE;
+      return false;
    } else if(SiS_Pr->ChipType >= SIS_761) {
       /* I very much assume 761, 340 and newer will use new layout */
-      return TRUE;
+      return true;
    } else if(SiS_Pr->ChipType >= SIS_661) {
       if((ROMAddr[0x1a] == 'N') &&
 	 (ROMAddr[0x1b] == 'e') &&
 	 (ROMAddr[0x1c] == 'w') &&
 	 (ROMAddr[0x1d] == 'V')) {
-	 return TRUE;
+	 return true;
       }
       romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
       if(romversoffs) {
@@ -1280,17 +1280,17 @@
 	 }
       }
       if((romvmaj != 0) || (romvmin >= 92)) {
-	 return TRUE;
+	 return true;
       }
    } else if(IS_SIS650740) {
       if((ROMAddr[0x1a] == 'N') &&
 	 (ROMAddr[0x1b] == 'e') &&
 	 (ROMAddr[0x1c] == 'w') &&
 	 (ROMAddr[0x1d] == 'V')) {
-	 return TRUE;
+	 return true;
       }
    }
-   return FALSE;
+   return false;
 }
 
 static void
@@ -1299,8 +1299,8 @@
    unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
    unsigned short romptr = 0;
 
-   SiS_Pr->SiS_UseROM = FALSE;
-   SiS_Pr->SiS_ROMNew = FALSE;
+   SiS_Pr->SiS_UseROM = false;
+   SiS_Pr->SiS_ROMNew = false;
    SiS_Pr->SiS_PWDOffset = 0;
 
    if(SiS_Pr->ChipType >= XGI_20) return;
@@ -1312,15 +1312,15 @@
 	  * of the BIOS image.
 	  */
 	 if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
-	    SiS_Pr->SiS_UseROM = TRUE;
+	    SiS_Pr->SiS_UseROM = true;
       } else if(SiS_Pr->ChipType < SIS_315H) {
 	 /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
 	  * the others do as well
 	  */
-	 SiS_Pr->SiS_UseROM = TRUE;
+	 SiS_Pr->SiS_UseROM = true;
       } else {
 	 /* 315/330 series stick to the standard(s) */
-	 SiS_Pr->SiS_UseROM = TRUE;
+	 SiS_Pr->SiS_UseROM = true;
 	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
 	    SiS_Pr->SiS_EMIOffset = 14;
 	    SiS_Pr->SiS_PWDOffset = 17;
@@ -1488,7 +1488,7 @@
 /*********************************************/
 
 #ifdef SIS_LINUX_KERNEL
-static BOOLEAN
+static bool
 SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 		unsigned short ModeIdIndex)
 {
@@ -1496,10 +1496,10 @@
    unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
    unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
 
-   if(!AdapterMemSize) return TRUE;
+   if(!AdapterMemSize) return true;
 
-   if(AdapterMemSize < memorysize) return FALSE;
-   return TRUE;
+   if(AdapterMemSize < memorysize) return false;
+   return true;
 }
 #endif
 
@@ -1605,7 +1605,7 @@
 /*           HELPER: SearchModeID            */
 /*********************************************/
 
-BOOLEAN
+bool
 SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
 		unsigned short *ModeIdIndex)
 {
@@ -1617,7 +1617,7 @@
 
       for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
 	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
-	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return FALSE;
+	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return false;
       }
 
       if((*ModeNo) == 0x07) {
@@ -1635,11 +1635,11 @@
 
       for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
 	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
-	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return FALSE;
+	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return false;
       }
 
    }
-   return TRUE;
+   return true;
 }
 
 /*********************************************/
@@ -1696,13 +1696,13 @@
 /*           HELPER: LowModeTests            */
 /*********************************************/
 
-static BOOLEAN
+static bool
 SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
    unsigned short temp, temp1, temp2;
 
    if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
-      return TRUE;
+      return true;
    temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
    SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
    temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
@@ -1712,13 +1712,13 @@
    SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
    if((SiS_Pr->ChipType >= SIS_315H) ||
       (SiS_Pr->ChipType == SIS_300)) {
-      if(temp2 == 0x55) return FALSE;
-      else return TRUE;
+      if(temp2 == 0x55) return false;
+      else return true;
    } else {
-      if(temp2 != 0x55) return TRUE;
+      if(temp2 != 0x55) return true;
       else {
 	 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
-	 return FALSE;
+	 return false;
       }
    }
 }
@@ -3237,14 +3237,14 @@
 SiS_SetPitch(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
 {
    SISPtr pSiS = SISPTR(pScrn);
-   BOOLEAN isslavemode = FALSE;
+   bool isslavemode = false;
 
    if( (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) &&
        ( ((pSiS->VGAEngine == SIS_300_VGA) &&
 	  (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
 	 ((pSiS->VGAEngine == SIS_315_VGA) &&
 	  (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
-      isslavemode = TRUE;
+      isslavemode = true;
    }
 
    /* We need to set pitch for CRT1 if bridge is in slave mode, too */
@@ -3264,10 +3264,10 @@
 
 #ifdef SIS_XORG_XF86
 /* We need pScrn for setting the pitch correctly */
-BOOLEAN
-SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, BOOLEAN dosetpitch)
+bool
+SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, bool dosetpitch)
 #else
-BOOLEAN
+bool
 SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 #endif
 {
@@ -3277,8 +3277,8 @@
 #ifdef SIS_LINUX_KERNEL
    unsigned short KeepLockReg;
 
-   SiS_Pr->UseCustomMode = FALSE;
-   SiS_Pr->CRT1UsesCustomMode = FALSE;
+   SiS_Pr->UseCustomMode = false;
+   SiS_Pr->CRT1UsesCustomMode = false;
 #endif
 
    SiS_Pr->SiS_flag_clearbuffer = 0;
@@ -3317,7 +3317,7 @@
    SiS_UnLockCRT2(SiS_Pr);
 
    if(!SiS_Pr->UseCustomMode) {
-      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
    } else {
       ModeIdIndex = 0;
    }
@@ -3347,18 +3347,18 @@
 #ifdef SIS_LINUX_KERNEL
    /* Check memory size (kernel framebuffer driver only) */
    if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
-      return FALSE;
+      return false;
    }
 #endif
 
    SiS_OpenCRTC(SiS_Pr);
 
    if(SiS_Pr->UseCustomMode) {
-      SiS_Pr->CRT1UsesCustomMode = TRUE;
+      SiS_Pr->CRT1UsesCustomMode = true;
       SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
       SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
    } else {
-      SiS_Pr->CRT1UsesCustomMode = FALSE;
+      SiS_Pr->CRT1UsesCustomMode = false;
    }
 
    /* Set mode on CRT1 */
@@ -3445,7 +3445,7 @@
    if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
 #endif
 
-   return TRUE;
+   return true;
 }
 
 /*********************************************/
@@ -3454,14 +3454,14 @@
 /*********************************************/
 
 #ifdef SIS_XORG_XF86
-BOOLEAN
+bool
 SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-               DisplayModePtr mode, BOOLEAN IsCustom)
+               DisplayModePtr mode, bool IsCustom)
 {
    SISPtr pSiS = SISPTR(pScrn);
    unsigned short ModeNo = 0;
 
-   SiS_Pr->UseCustomMode = FALSE;
+   SiS_Pr->UseCustomMode = false;
 
    if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
 
@@ -3475,13 +3475,13 @@
 
       /* Don't need vbflags here; checks done earlier */
       ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
-      if(!ModeNo) return FALSE;
+      if(!ModeNo) return false;
 
       xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
 
    }
 
-   return(SiSSetMode(SiS_Pr, pScrn, ModeNo, TRUE));
+   return(SiSSetMode(SiS_Pr, pScrn, ModeNo, true));
 }
 
 /*********************************************/
@@ -3489,9 +3489,9 @@
 /*           for Dual-Head modes             */
 /*********************************************/
 
-BOOLEAN
+bool
 SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-               DisplayModePtr mode, BOOLEAN IsCustom)
+               DisplayModePtr mode, bool IsCustom)
 {
    SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
    SISPtr  pSiS = SISPTR(pScrn);
@@ -3502,7 +3502,7 @@
    unsigned short ModeNo = 0;
    unsigned char  backupreg = 0;
 
-   SiS_Pr->UseCustomMode = FALSE;
+   SiS_Pr->UseCustomMode = false;
 
    /* Remember: Custom modes for CRT2 are ONLY supported
     *     -) on the 30x/B/C, and
@@ -3516,7 +3516,7 @@
    } else {
 
 	 ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
-	 if(!ModeNo) return FALSE;
+	 if(!ModeNo) return false;
 
    }
 
@@ -3550,10 +3550,10 @@
       if(pSiSEnt->CRT1ModeNo == -1) {
 	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
 		"Setting CRT2 mode delayed until after setting CRT1 mode\n");
-	 return TRUE;
+	 return true;
       }
 #endif
-      pSiSEnt->CRT2ModeSet = TRUE;
+      pSiSEnt->CRT2ModeSet = true;
    }
 #endif
 
@@ -3578,7 +3578,7 @@
    SiS_UnLockCRT2(SiS_Pr);
 
    if(!SiS_Pr->UseCustomMode) {
-      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
    } else {
       ModeIdIndex = 0;
    }
@@ -3658,7 +3658,7 @@
 
    SiS_Handle760(SiS_Pr);
 
-   return TRUE;
+   return true;
 }
 
 /*********************************************/
@@ -3666,9 +3666,9 @@
 /*           for Dual-Head modes             */
 /*********************************************/
 
-BOOLEAN
+bool
 SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-                   DisplayModePtr mode, BOOLEAN IsCustom)
+                   DisplayModePtr mode, bool IsCustom)
 {
    SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
    SISPtr  pSiS = SISPTR(pScrn);
@@ -3677,10 +3677,10 @@
 #ifdef SISDUALHEAD
    SISEntPtr pSiSEnt = pSiS->entityPrivate;
    unsigned char  backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
-   BOOLEAN backupcustom;
+   bool backupcustom;
 #endif
 
-   SiS_Pr->UseCustomMode = FALSE;
+   SiS_Pr->UseCustomMode = false;
 
    if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
 
@@ -3697,7 +3697,7 @@
    } else {
 
 	 ModeNo = SiS_GetModeNumber(pScrn, mode, 0); /* don't give VBFlags */
-	 if(!ModeNo) return FALSE;
+	 if(!ModeNo) return false;
 
 	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
 	 	"Setting standard mode 0x%x on CRT1\n", ModeNo);
@@ -3721,7 +3721,7 @@
    SiS_UnLockCRT2(SiS_Pr);
 
    if(!SiS_Pr->UseCustomMode) {
-      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
    } else {
       ModeIdIndex = 0;
    }
@@ -3771,11 +3771,11 @@
 #endif
 
    if(SiS_Pr->UseCustomMode) {
-      SiS_Pr->CRT1UsesCustomMode = TRUE;
+      SiS_Pr->CRT1UsesCustomMode = true;
       SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
       SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
    } else {
-      SiS_Pr->CRT1UsesCustomMode = FALSE;
+      SiS_Pr->CRT1UsesCustomMode = false;
    }
 
    /* Reset CRT2 if changing mode on CRT1 */
@@ -3838,7 +3838,7 @@
    /* Backup/Set ModeNo in BIOS scratch area */
    SiS_GetSetModeID(pScrn,ModeNo);
 
-   return TRUE;
+   return true;
 }
 #endif /* Linux_XF86 */
 
@@ -4082,7 +4082,7 @@
 			DisplayModePtr current
 #endif
 #ifdef SIS_LINUX_KERNEL
-			struct fb_var_screeninfo *var, BOOLEAN writeres
+			struct fb_var_screeninfo *var, bool writeres
 #endif
 )
 {
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
index 59d1284..f40a680 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/sis/init.h
@@ -1521,13 +1521,13 @@
    0x00}}
 };
 
-BOOLEAN		SiSInitPtr(struct SiS_Private *SiS_Pr);
+bool		SiSInitPtr(struct SiS_Private *SiS_Pr);
 #ifdef SIS_XORG_XF86
 unsigned short	SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
-				int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
+				int Depth, bool FSTN, int LCDwith, int LCDheight);
 #endif
 unsigned short	SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
-				int VDisplay, int Depth, BOOLEAN FSTN,
+				int VDisplay, int Depth, bool FSTN,
 				unsigned short CustomT, int LCDwith, int LCDheight,
 				unsigned int VBFlags2);
 unsigned short	SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
@@ -1558,12 +1558,12 @@
 void		SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
 unsigned short	SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 				unsigned short ModeIdIndex);
-BOOLEAN		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+bool		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
 #ifndef SIS_LINUX_KERNEL
 void		SiS_GetVBType(struct SiS_Private *SiS_Pr);
 #endif
 
-BOOLEAN		SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+bool		SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
 				unsigned short *ModeIdIndex);
 unsigned short	SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 				unsigned short ModeIdIndex);
@@ -1581,17 +1581,17 @@
 #endif
 void		SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
 #ifdef SIS_XORG_XF86
-BOOLEAN		SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo,
-				BOOLEAN dosetpitch);
-BOOLEAN		SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-				DisplayModePtr mode, BOOLEAN IsCustom);
-BOOLEAN		SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-				DisplayModePtr mode, BOOLEAN IsCustom);
-BOOLEAN		SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-				DisplayModePtr mode, BOOLEAN IsCustom);
+bool		SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo,
+				bool dosetpitch);
+bool		SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+				DisplayModePtr mode, bool IsCustom);
+bool		SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+				DisplayModePtr mode, bool IsCustom);
+bool		SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+				DisplayModePtr mode, bool IsCustom);
 #endif
 #ifdef SIS_LINUX_KERNEL
-BOOLEAN		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+bool		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 #endif
 void		SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
 void		SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
@@ -1602,7 +1602,7 @@
 #endif
 #ifdef SIS_LINUX_KERNEL
 void		SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
-				int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
+				int yres, struct fb_var_screeninfo *var, bool writeres);
 #endif
 
 /* From init301.c: */
@@ -1615,7 +1615,7 @@
 				unsigned short ModeIdIndex);
 extern void		SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
 extern void		SiS_DisableBridge(struct SiS_Private *);
-extern BOOLEAN		SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
+extern bool		SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
 extern unsigned short	SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 				unsigned short ModeIdIndex);
 extern void		SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
@@ -1624,8 +1624,8 @@
 extern unsigned short	SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
 extern unsigned short	SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 				unsigned short ModeIdIndex, unsigned short RRTI);
-extern BOOLEAN		SiS_IsVAMode(struct SiS_Private *);
-extern BOOLEAN		SiS_IsDualEdge(struct SiS_Private *);
+extern bool		SiS_IsVAMode(struct SiS_Private *);
+extern bool		SiS_IsDualEdge(struct SiS_Private *);
 
 #ifdef SIS_XORG_XF86
 /* From other modules: */
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
index 47e1896..da33d80 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/sis/init301.c
@@ -200,7 +200,7 @@
 /*           Adjust Rate for CRT2            */
 /*********************************************/
 
-static BOOLEAN
+static bool
 SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
 		unsigned short RRTI, unsigned short *i)
 {
@@ -269,7 +269,7 @@
    /* Look backwards in table for matching CRT2 mode */
    for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
       infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
-      if(infoflag & checkmask) return TRUE;
+      if(infoflag & checkmask) return true;
       if((*i) == 0) break;
    }
 
@@ -279,9 +279,9 @@
    for((*i) = 0; ; (*i)++) {
       if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
       infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
-      if(infoflag & checkmask) return TRUE;
+      if(infoflag & checkmask) return true;
    }
-   return FALSE;
+   return false;
 }
 
 /*********************************************/
@@ -405,7 +405,7 @@
 /*********************************************/
 
 #ifdef SIS300
-static BOOLEAN
+static bool
 SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
 {
    unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
@@ -415,13 +415,13 @@
       if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 	 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
 	 temp1 = SISGETROMW(0x23b);
-	 if(temp1 & temp) return TRUE;
+	 if(temp1 & temp) return true;
       }
    }
-   return FALSE;
+   return false;
 }
 
-static BOOLEAN
+static bool
 SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
 {
    unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
@@ -431,10 +431,10 @@
       if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 	 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
 	 temp1 = SISGETROMW(0x23d);
-	 if(temp1 & temp) return TRUE;
+	 if(temp1 & temp) return true;
       }
    }
-   return FALSE;
+   return false;
 }
 #endif
 
@@ -687,38 +687,38 @@
 /*********************************************/
 
 #ifdef SIS300
-static BOOLEAN
+static bool
 SiS_Is301B(struct SiS_Private *SiS_Pr)
 {
-   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
-   return FALSE;
+   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true;
+   return false;
 }
 #endif
 
-static BOOLEAN
+static bool
 SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
 {
    if(SiS_Pr->ChipType == SIS_730) {
-      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return TRUE;
+      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true;
    }
-   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return TRUE;
-   return FALSE;
+   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true;
+   return false;
 }
 
-BOOLEAN
+bool
 SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
    if(SiS_Pr->ChipType >= SIS_315H) {
       if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
-	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return TRUE;
+	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
       }
    }
 #endif
-   return FALSE;
+   return false;
 }
 
-BOOLEAN
+bool
 SiS_IsVAMode(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
@@ -726,70 +726,70 @@
 
    if(SiS_Pr->ChipType >= SIS_315H) {
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
+      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true;
    }
 #endif
-   return FALSE;
+   return false;
 }
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
 {
-   if(SiS_IsVAMode(SiS_Pr))  return TRUE;
-   if(SiS_CRT2IsLCD(SiS_Pr)) return TRUE;
-   return FALSE;
+   if(SiS_IsVAMode(SiS_Pr))  return true;
+   if(SiS_CRT2IsLCD(SiS_Pr)) return true;
+   return false;
 }
 #endif
 
-static BOOLEAN
+static bool
 SiS_IsDualLink(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
    if(SiS_Pr->ChipType >= SIS_315H) {
       if((SiS_CRT2IsLCD(SiS_Pr)) ||
          (SiS_IsVAMode(SiS_Pr))) {
-	 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
+	 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true;
       }
    }
 #endif
-   return FALSE;
+   return false;
 }
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_TVEnabled(struct SiS_Private *SiS_Pr)
 {
-   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
+   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true;
    if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
-      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
+      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
 {
-   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
-   return FALSE;
+   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
 {
    if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag;
@@ -798,90 +798,90 @@
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
       /* Check for revision != A0 only */
       if((flag == 0xe0) || (flag == 0xc0) ||
-         (flag == 0xb0) || (flag == 0x90)) return FALSE;
-   } else if(SiS_Pr->ChipType >= SIS_661) return FALSE;
-   return TRUE;
+         (flag == 0xb0) || (flag == 0x90)) return false;
+   } else if(SiS_Pr->ChipType >= SIS_661) return false;
+   return true;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
 {
    if(SiS_Pr->ChipType >= SIS_315H) {
       /* YPrPb = 0x08 */
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return TRUE;
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsChScart(struct SiS_Private *SiS_Pr)
 {
    if(SiS_Pr->ChipType >= SIS_315H) {
       /* Scart = 0x04 */
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return TRUE;
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag;
 
    if(SiS_Pr->ChipType >= SIS_315H) {
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToTV)        return TRUE;
+      if(flag & SetCRT2ToTV)        return true;
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      if(flag & EnableCHYPbPr)      return TRUE;  /* = YPrPb = 0x08 */
-      if(flag & EnableCHScart)      return TRUE;  /* = Scart = 0x04 - TW */
+      if(flag & EnableCHYPbPr)      return true;  /* = YPrPb = 0x08 */
+      if(flag & EnableCHScart)      return true;  /* = Scart = 0x04 - TW */
    } else {
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToTV)        return TRUE;
+      if(flag & SetCRT2ToTV)        return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag;
 
    if(SiS_Pr->ChipType >= SIS_315H) {
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToLCD) return TRUE;
+      if(flag & SetCRT2ToLCD) return true;
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      if(flag & SetToLCDA)    return TRUE;
+      if(flag & SetToLCDA)    return true;
    } else {
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToLCD) return TRUE;
+      if(flag & SetCRT2ToLCD) return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
-static BOOLEAN
+static bool
 SiS_HaveBridge(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag;
 
    if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-      return TRUE;
+      return true;
    } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
       flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-      if((flag == 1) || (flag == 2)) return TRUE;
+      if((flag == 1) || (flag == 2)) return true;
    }
-   return FALSE;
+   return false;
 }
 
-static BOOLEAN
+static bool
 SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag;
@@ -890,23 +890,23 @@
       flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
       if(SiS_Pr->ChipType < SIS_315H) {
 	flag &= 0xa0;
-	if((flag == 0x80) || (flag == 0x20)) return TRUE;
+	if((flag == 0x80) || (flag == 0x20)) return true;
       } else {
 	flag &= 0x50;
-	if((flag == 0x40) || (flag == 0x10)) return TRUE;
+	if((flag == 0x40) || (flag == 0x10)) return true;
       }
    }
-   return FALSE;
+   return false;
 }
 
-static BOOLEAN
+static bool
 SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag1;
 
    flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
-   if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
-   return FALSE;
+   if(flag1 & (SetInSlaveMode >> 8)) return true;
+   return false;
 }
 
 /*********************************************/
@@ -1461,11 +1461,11 @@
 
    if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
       if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
-	 SiS_Pr->SiS_NeedRomModeData = TRUE;
+	 SiS_Pr->SiS_NeedRomModeData = true;
 	 SiS_Pr->PanelHT  = temp;
       }
       if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
-	 SiS_Pr->SiS_NeedRomModeData = TRUE;
+	 SiS_Pr->SiS_NeedRomModeData = true;
 	 SiS_Pr->PanelVT  = temp;
       }
       SiS_Pr->PanelHRS = SISGETROMW(10);
@@ -1516,7 +1516,7 @@
 SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
   unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
-  BOOLEAN panelcanscale = FALSE;
+  bool panelcanscale = false;
 #ifdef SIS300
   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
   static const unsigned char SiS300SeriesLCDRes[] =
@@ -1534,10 +1534,10 @@
   SiS_Pr->PanelHRE        = 999; /* HSync end */
   SiS_Pr->PanelVRS        = 999; /* VSync start */
   SiS_Pr->PanelVRE        = 999; /* VSync end */
-  SiS_Pr->SiS_NeedRomModeData = FALSE;
+  SiS_Pr->SiS_NeedRomModeData = false;
 
   /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
-  SiS_Pr->Alternate1600x1200 = FALSE;
+  SiS_Pr->Alternate1600x1200 = false;
 
   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
 
@@ -1633,7 +1633,7 @@
       SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
   }
 
-  panelcanscale = (SiS_Pr->SiS_LCDInfo & DontExpandLCD) ? TRUE : FALSE;
+  panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD);
 
   if(!SiS_Pr->UsePanelScaler)          SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
   else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
@@ -1833,7 +1833,7 @@
 				  SiS_Pr->PanelHRS =   48; SiS_Pr->PanelHRE =   32;
 				  SiS_Pr->PanelVRS =    2; SiS_Pr->PanelVRE =    4;
 				  SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
-				  SiS_Pr->Alternate1600x1200 = TRUE;
+				  SiS_Pr->Alternate1600x1200 = true;
 			       }
 			    } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
 			       SiS_Pr->PanelHT  = 2048; SiS_Pr->PanelVT  = 1320;
@@ -3448,7 +3448,7 @@
 
      } else {
 
-	BOOLEAN gotit = FALSE;
+	bool gotit = false;
 
 	if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
 
@@ -3456,7 +3456,7 @@
 	   SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
 	   SiS_Pr->SiS_HT    = SiS_Pr->PanelHT;
 	   SiS_Pr->SiS_VT    = SiS_Pr->PanelVT;
-	   gotit = TRUE;
+	   gotit = true;
 
 	} else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
 
@@ -3474,7 +3474,7 @@
 	      if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
 	      else                         SiS_Pr->SiS_RVBHRS2 += tempax;
 	   }
-	   if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
+	   if(SiS_Pr->SiS_VGAHT) gotit = true;
 	   else {
 	      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
 	      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
@@ -3485,7 +3485,7 @@
 	      SiS_Pr->SiS_HT      = SiS_Pr->PanelHT;
 	      SiS_Pr->SiS_VT      = SiS_Pr->PanelVT;
 	      SiS_Pr->SiS_RVBHRS2 = 0;
-	      gotit = TRUE;
+	      gotit = true;
 	   }
 #endif
 
@@ -3960,8 +3960,8 @@
 #ifdef SIS315H	   /* 315 series */
 
 	   int didpwd = 0;
-	   BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	                      (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
+	   bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
+	                  (SiS_Pr->SiS_CustomT == CUT_CLEVO1400);
 
 	   modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
 
@@ -4313,7 +4313,7 @@
   unsigned short temp=0, tempah;
 #ifdef SIS315H
   unsigned short temp1, pushax=0;
-  BOOLEAN delaylong = FALSE;
+  bool delaylong = false;
 #endif
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
@@ -4448,7 +4448,7 @@
 
 	    if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
 	       SiS_PanelDelayLoop(SiS_Pr, 3, 10);
-	       delaylong = TRUE;
+	       delaylong = true;
 	    }
 
 	 }
@@ -4530,7 +4530,7 @@
 			SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
 			if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
 			/* emidelay = SISGETROMW((romptr + 0x22)); */
-			SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = TRUE;
+			SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = true;
 		     }
 		  }
 
@@ -4644,7 +4644,7 @@
 			SiS_PanelDelayLoop(SiS_Pr, 3, 5);
 			if(delaylong) {
 			   SiS_PanelDelayLoop(SiS_Pr, 3, 5);
-			   delaylong = FALSE;
+			   delaylong = false;
 			}
 			SiS_WaitVBRetrace(SiS_Pr);
 			SiS_WaitVBRetrace(SiS_Pr);
@@ -5454,7 +5454,7 @@
   unsigned short modeflag, resinfo = 0;
   unsigned short push2, tempax, tempbx, tempcx, temp;
   unsigned int   tempeax = 0, tempebx, tempecx, tempvcfact = 0;
-  BOOLEAN islvds = FALSE, issis  = FALSE, chkdclkfirst = FALSE;
+  bool islvds = false, issis  = false, chkdclkfirst = false;
 #ifdef SIS300
   unsigned short crt2crtc = 0;
 #endif
@@ -5480,17 +5480,17 @@
 
   /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
   if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-     islvds = TRUE;
+     islvds = true;
   }
 
   /* is really sis if sis bridge, but not 301B-DH */
   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
-     issis = TRUE;
+     issis = true;
   }
 
   if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
      if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        chkdclkfirst = TRUE;
+        chkdclkfirst = true;
      }
   }
 
@@ -6447,13 +6447,13 @@
    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
 }
 
-static BOOLEAN
+static bool
 SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
 		    unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
 		    unsigned short *ResIndex)
 {
 
-  if(SiS_Pr->ChipType < SIS_315H) return FALSE;
+  if(SiS_Pr->ChipType < SIS_315H) return false;
 
   if(ModeNo <= 0x13)
      (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -6688,7 +6688,7 @@
   unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
   unsigned short push2, modeflag, crt2crtc, bridgeoffset;
   unsigned int   longtemp, PhaseIndex;
-  BOOLEAN        newtvphase;
+  bool           newtvphase;
   const unsigned char *TimingPoint;
 #ifdef SIS315H
   unsigned short resindex, CRT2Index;
@@ -6721,11 +6721,11 @@
   PhaseIndex  = 0x01; /* SiS_PALPhase */
   TimingPoint = SiS_Pr->SiS_PALTiming;
 
-  newtvphase = FALSE;
+  newtvphase = false;
   if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
       ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
 	(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-     newtvphase = TRUE;
+     newtvphase = true;
   }
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
@@ -7754,13 +7754,13 @@
 /*     MODIFY CRT1 GROUP FOR SLAVE MODE      */
 /*********************************************/
 
-static BOOLEAN
+static bool
 SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
 		   unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
 		   unsigned short *DisplayType)
  {
   unsigned short modeflag = 0;
-  BOOLEAN checkhd = TRUE;
+  bool checkhd = true;
 
   /* Pass 1:1 not supported here */
 
@@ -7792,7 +7792,7 @@
      (*DisplayType = 0);
      switch(SiS_Pr->SiS_LCDResInfo) {
      case Panel_320x240_1: (*DisplayType) = 50;
-			   checkhd = FALSE;
+			   checkhd = false;
 			   break;
      case Panel_320x240_2: (*DisplayType) = 14;
 			   break;
@@ -7802,7 +7802,7 @@
 			   break;
      case Panel_1024x600:  (*DisplayType) = 26;
 			   break;
-     default: return TRUE;
+     default: return true;
      }
 
      if(checkhd) {
@@ -7815,7 +7815,7 @@
 
   }
 
-  return TRUE;
+  return true;
 }
 
 static void
@@ -8654,7 +8654,7 @@
 /*      MAIN: SET CRT2 REGISTER GROUP        */
 /*********************************************/
 
-BOOLEAN
+bool
 SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
 #ifdef SIS300
@@ -8690,7 +8690,7 @@
    if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
       SiS_LockCRT2(SiS_Pr);
       SiS_DisplayOn(SiS_Pr);
-      return TRUE;
+      return true;
    }
 
    SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
@@ -8828,7 +8828,7 @@
       SiS_LockCRT2(SiS_Pr);
    }
 
-   return TRUE;
+   return true;
 }
 
 
@@ -8908,7 +8908,7 @@
   return NULL;
 }
 
-static BOOLEAN
+static bool
 SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
 {
   SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;  		/* DAB (Device Address Byte) */
@@ -8921,14 +8921,14 @@
 
   while(*dataptr) {
      dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
-     if(!dataptr) return FALSE;
+     if(!dataptr) return false;
   }
 #ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
   xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
 #endif
 #endif
-  return TRUE;
+  return true;
 }
 #endif
 
@@ -8939,7 +8939,7 @@
  * 0x0a, possibly for working around the DDC problems
  */
 
-static BOOLEAN
+static bool
 SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
 {
   unsigned short temp, i;
@@ -8958,9 +8958,9 @@
      if(temp) continue;							/*    (ERROR: no ack) */
      if(SiS_SetStop(SiS_Pr)) continue;					/* Set stop condition */
      SiS_Pr->SiS_ChrontelInit = 1;
-     return TRUE;
+     return true;
   }
-  return FALSE;
+  return false;
 }
 
 /* Write to Chrontel 700x */
@@ -9119,7 +9119,7 @@
 #endif
 unsigned short
 SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
-                unsigned short adaptnum, unsigned short DDCdatatype, BOOLEAN checkcr32,
+                unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
 		unsigned int VBFlags2)
 {
      unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
@@ -9287,7 +9287,7 @@
 {
     unsigned char mask, value;
     unsigned short  temp, ret=0;
-    BOOLEAN failed = FALSE;
+    bool failed = false;
 
     SiS_SetSwitchDDC2(SiS_Pr);
     if(SiS_PrepareDDC(SiS_Pr)) {
@@ -9308,7 +9308,7 @@
            mask = 0xff;
 	   value = 0xff;
        } else {
-           failed = TRUE;
+           failed = true;
 	   ret = 0xFFFF;
 #ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
@@ -9317,7 +9317,7 @@
 #endif
        }
     }
-    if(failed == FALSE) {
+    if(!failed) {
        temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
        SiS_SendACK(SiS_Pr, 1);
        temp &= mask;
@@ -9431,7 +9431,7 @@
    if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
       return 0xFFFF;
 
-   if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE, VBFlags2) == 0xFFFF)
+   if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
       return 0xFFFF;
 
    sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
@@ -9829,7 +9829,7 @@
 {
   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
   unsigned short delay=0,index,myindex,temp,romptr=0;
-  BOOLEAN dochiptest = TRUE;
+  bool dochiptest = true;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
@@ -9864,7 +9864,7 @@
 
   } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {  /* ----------	LCD/LCDA */
 
-     BOOLEAN gotitfrompci = FALSE;
+     bool gotitfrompci = false;
 
      /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
 
@@ -9916,22 +9916,22 @@
      case CUT_COMPAQ1280:
      case CUT_COMPAQ12802:
 	if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
-	   gotitfrompci = TRUE;
-	   dochiptest = FALSE;
+	   gotitfrompci = true;
+	   dochiptest = false;
 	   delay = 0x03;
 	}
 	break;
      case CUT_CLEVO1400:
      case CUT_CLEVO14002:
-	gotitfrompci = TRUE;
-	dochiptest = FALSE;
+	gotitfrompci = true;
+	dochiptest = false;
 	delay = 0x02;
 	break;
      case CUT_CLEVO1024:
      case CUT_CLEVO10242:
         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	   gotitfrompci = TRUE;
-	   dochiptest = FALSE;
+	   gotitfrompci = true;
+	   dochiptest = false;
 	   delay = 0x33;
 	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
 	   delay &= 0x0f;
@@ -10009,7 +10009,7 @@
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
 	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
-	dochiptest = FALSE;
+	dochiptest = false;
      }
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {			/* ------------ TV */
@@ -10043,12 +10043,12 @@
 	   case CUT_CLEVO1400:
 	   case CUT_CLEVO14002:
 	      delay = 0x02;
-	      dochiptest = FALSE;
+	      dochiptest = false;
 	      break;
 	   case CUT_CLEVO1024:
 	   case CUT_CLEVO10242:
 	      delay = 0x03;
-	      dochiptest = FALSE;
+	      dochiptest = false;
    	      break;
 	   default:
               delay = SiS310_TVDelayCompensation_651301LV[index];
@@ -10085,7 +10085,7 @@
 
      if(SiS_LCDAEnabled(SiS_Pr)) {
 	delay &= 0x0f;
-	dochiptest = FALSE;
+	dochiptest = false;
      }
 
   } else return;
@@ -10728,7 +10728,7 @@
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
 	   }
-	   if((SiS_Pr->Backup == TRUE) && (SiS_Pr->Backup_Mode == ModeNo)) {
+	   if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
index 4f3a286..7708e1e 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/sis/init301.h
@@ -363,8 +363,8 @@
 void		SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
 unsigned short	SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
 void		SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
-BOOLEAN		SiS_IsDualEdge(struct SiS_Private *SiS_Pr);
-BOOLEAN		SiS_IsVAMode(struct SiS_Private *SiS_Pr);
+bool		SiS_IsDualEdge(struct SiS_Private *SiS_Pr);
+bool		SiS_IsVAMode(struct SiS_Private *SiS_Pr);
 void		SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 			unsigned short ModeIdIndex, int checkcrt2mode);
 void		SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
@@ -379,7 +379,7 @@
 #ifndef SIS_LINUX_KERNEL
 void		SiS_EnableBridge(struct SiS_Private *SiS_Pr);
 #endif
-BOOLEAN		SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+bool		SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 void		SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
 void		SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
 
@@ -403,7 +403,7 @@
 #endif /* 315 */
 
 #ifdef SIS300
-static  BOOLEAN	SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
+static  bool	SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
 void		SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
 #endif
 
@@ -416,14 +416,14 @@
 #ifdef SIS_XORG_XF86
 unsigned short		SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
 				int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
-				BOOLEAN checkcr32, unsigned int VBFlags2);
+				bool checkcr32, unsigned int VBFlags2);
 unsigned short		SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
 unsigned short		SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
 				unsigned char *buffer);
 #else
 static unsigned short	SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
 				int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
-				BOOLEAN checkcr32, unsigned int VBFlags2);
+				bool checkcr32, unsigned int VBFlags2);
 static unsigned short	SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
 static unsigned short	SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
 				unsigned char *buffer);
@@ -469,7 +469,7 @@
 extern void		SiS_SetRegAND(SISIOADDRESS, unsigned short, unsigned short);
 extern void		SiS_DisplayOff(struct SiS_Private *SiS_Pr);
 extern void		SiS_DisplayOn(struct SiS_Private *SiS_Pr);
-extern BOOLEAN		SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
+extern bool		SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
 extern unsigned short	SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 				unsigned short ModeIdIndex);
 extern unsigned short	SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
index c3884a2..47a3350 100644
--- a/drivers/video/sis/initextlfb.c
+++ b/drivers/video/sis/initextlfb.c
@@ -38,14 +38,14 @@
 			unsigned char modeno, unsigned char rateindex);
 int		sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
 			unsigned char rateindex, struct fb_var_screeninfo *var);
-BOOLEAN		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+bool		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
 			int *htotal, int *vtotal, unsigned char rateindex);
 
-extern BOOLEAN	SiSInitPtr(struct SiS_Private *SiS_Pr);
-extern BOOLEAN	SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+extern bool	SiSInitPtr(struct SiS_Private *SiS_Pr);
+extern bool	SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
 			unsigned short *ModeIdIndex);
 extern void	SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
-			int xres, int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
+			int xres, int yres, struct fb_var_screeninfo *var, bool writeres);
 
 int
 sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
@@ -131,7 +131,7 @@
 			(unsigned char *)&SiS_Pr->SiS_CRT1Table[index].CR[0],
 			SiS_Pr->SiS_RefIndex[RRTI].XRes,
 			SiS_Pr->SiS_RefIndex[RRTI].YRes,
-			var, FALSE);
+			var, false);
 
     if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x8000)
        var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
@@ -175,7 +175,7 @@
     return 1;
 }
 
-BOOLEAN
+bool
 sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal,
 			int *vtotal, unsigned char rateindex)
 {
@@ -184,7 +184,7 @@
     unsigned short RRTI = 0;
     unsigned char  sr_data, cr_data, cr_data2;
 
-    if(!SiSInitPtr(SiS_Pr)) return FALSE;
+    if(!SiSInitPtr(SiS_Pr)) return false;
 
     if(rateindex > 0) rateindex--;
 
@@ -195,7 +195,7 @@
     }
 #endif
 
-    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
 
     RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
     if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
@@ -226,7 +226,7 @@
     if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & InterlaceMode)
        *vtotal *= 2;
 
-    return TRUE;
+    return true;
 }
 
 
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index a259446..7d5ee21 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -526,7 +526,7 @@
 		u16 vmax;
 		u32 dclockmax;
 		u8  feature;
-		BOOLEAN datavalid;
+		bool datavalid;
 	}		sisfb_thismonitor;
 
 	unsigned short	chip_id;	/* PCI ID of chip */
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index baaf495..01197d7 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -110,7 +110,7 @@
 /* ------------- Parameter parsing -------------- */
 
 static void __devinit
-sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
+sisfb_search_vesamode(unsigned int vesamode, bool quiet)
 {
 	int i = 0, j = 0;
 
@@ -150,7 +150,7 @@
 }
 
 static void __devinit
-sisfb_search_mode(char *name, BOOLEAN quiet)
+sisfb_search_mode(char *name, bool quiet)
 {
 	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
 	int i = 0;
@@ -251,7 +251,7 @@
 			"sisfb: Using vga mode %s pre-set by kernel as default\n",
 			mymode);
 
-		sisfb_search_mode(mymode, TRUE);
+		sisfb_search_mode(mymode, true);
 	}
 #endif
 	return;
@@ -307,7 +307,7 @@
 sisfb_search_specialtiming(const char *name)
 {
 	int i = 0;
-	BOOLEAN found = FALSE;
+	bool found = false;
 
 	/* We don't know the hardware specs yet and there is no ivideo */
 
@@ -322,7 +322,7 @@
 			if(!strnicmp(name,mycustomttable[i].optionName,
 			   strlen(mycustomttable[i].optionName))) {
 				sisfb_specialtiming = mycustomttable[i].SpecialID;
-				found = TRUE;
+				found = true;
 				printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
 					mycustomttable[i].vendorName,
 					mycustomttable[i].cardName,
@@ -353,7 +353,7 @@
 {
 	unsigned char *biosver = NULL;
 	unsigned char *biosdate = NULL;
-	BOOLEAN footprint;
+	bool footprint;
 	u32 chksum = 0;
 	int i, j;
 
@@ -380,16 +380,16 @@
 		      (mycustomttable[i].bioschksum == chksum)))		&&
 		    (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
 		    (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
-			footprint = TRUE;
+			footprint = true;
 			for(j = 0; j < 5; j++) {
 				if(mycustomttable[i].biosFootprintAddr[j]) {
 					if(ivideo->SiS_Pr.UseROM) {
 						if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
 							mycustomttable[i].biosFootprintData[j]) {
-							footprint = FALSE;
+							footprint = false;
 						}
 					} else
-						footprint = FALSE;
+						footprint = false;
 				}
 			}
 			if(footprint) {
@@ -406,7 +406,7 @@
 	} while(mycustomttable[i].chipID);
 }
 
-static BOOLEAN __devinit
+static bool __devinit
 sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
 {
 	int i, j, xres, yres, refresh, index;
@@ -417,13 +417,13 @@
 	   buffer[4] != 0xff || buffer[5] != 0xff ||
 	   buffer[6] != 0xff || buffer[7] != 0x00) {
 		printk(KERN_DEBUG "sisfb: Bad EDID header\n");
-		return FALSE;
+		return false;
 	}
 
 	if(buffer[0x12] != 0x01) {
 		printk(KERN_INFO "sisfb: EDID version %d not supported\n",
 			buffer[0x12]);
-		return FALSE;
+		return false;
 	}
 
 	monitor->feature = buffer[0x18];
@@ -449,7 +449,7 @@
 		  monitor->vmin = buffer[j + 5];
 		  monitor->vmax = buffer[j + 6];
 		  monitor->dclockmax = buffer[j + 9] * 10 * 1000;
-		  monitor->datavalid = TRUE;
+		  monitor->datavalid = true;
 		  break;
 	       }
 	       j += 18;
@@ -501,7 +501,7 @@
 	      index += 2;
 	   }
 	   if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
-	      monitor->datavalid = TRUE;
+	      monitor->datavalid = true;
 	   }
 	}
 
@@ -514,7 +514,7 @@
 	unsigned short temp, i, realcrtno = crtno;
 	unsigned char  buffer[256];
 
-	monitor->datavalid = FALSE;
+	monitor->datavalid = false;
 
 	if(crtno) {
 	   if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
@@ -563,7 +563,7 @@
 
 /* -------------- Mode validation --------------- */
 
-static BOOLEAN
+static bool
 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
 		int mode_idx, int rate_idx, int rate)
 {
@@ -571,10 +571,10 @@
 	unsigned int dclock, hsync;
 
 	if(!monitor->datavalid)
-		return TRUE;
+		return true;
 
 	if(mode_idx < 0)
-		return FALSE;
+		return false;
 
 	/* Skip for 320x200, 320x240, 640x400 */
 	switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
@@ -587,34 +587,34 @@
 	case 0x2f:
 	case 0x5d:
 	case 0x5e:
-		return TRUE;
+		return true;
 #ifdef CONFIG_FB_SIS_315
 	case 0x5a:
 	case 0x5b:
-		if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE;
+		if(ivideo->sisvga_engine == SIS_315_VGA) return true;
 #endif
 	}
 
 	if(rate < (monitor->vmin - 1))
-		return FALSE;
+		return false;
 	if(rate > (monitor->vmax + 1))
-		return FALSE;
+		return false;
 
 	if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
 				  sisbios_mode[mode_idx].mode_no[ivideo->mni],
 				  &htotal, &vtotal, rate_idx)) {
 		dclock = (htotal * vtotal * rate) / 1000;
 		if(dclock > (monitor->dclockmax + 1000))
-			return FALSE;
+			return false;
 		hsync = dclock / htotal;
 		if(hsync < (monitor->hmin - 1))
-			return FALSE;
+			return false;
 		if(hsync > (monitor->hmax + 1))
-			return FALSE;
+			return false;
         } else {
-		return FALSE;
+		return false;
 	}
-	return TRUE;
+	return true;
 }
 
 static int
@@ -732,49 +732,49 @@
 	}
 }
 
-static BOOLEAN
+static bool
 sisfb_bridgeisslave(struct sis_video_info *ivideo)
 {
 	unsigned char P1_00;
 
 	if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
-		return FALSE;
+		return false;
 
 	inSISIDXREG(SISPART1,0x00,P1_00);
 	if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
 	    ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
-		return TRUE;
+		return true;
 	} else {
-		return FALSE;
+		return false;
 	}
 }
 
-static BOOLEAN
+static bool
 sisfballowretracecrt1(struct sis_video_info *ivideo)
 {
 	u8 temp;
 
 	inSISIDXREG(SISCR,0x17,temp);
 	if(!(temp & 0x80))
-		return FALSE;
+		return false;
 
 	inSISIDXREG(SISSR,0x1f,temp);
 	if(temp & 0xc0)
-		return FALSE;
+		return false;
 
-	return TRUE;
+	return true;
 }
 
-static BOOLEAN
+static bool
 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
 {
 	if(!sisfballowretracecrt1(ivideo))
-		return FALSE;
+		return false;
 
 	if(inSISREG(SISINPSTAT) & 0x08)
-		return TRUE;
+		return true;
 	else
-		return FALSE;
+		return false;
 }
 
 static void
@@ -791,7 +791,7 @@
 	while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
 }
 
-static BOOLEAN
+static bool
 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
 {
 	unsigned char temp, reg;
@@ -799,17 +799,17 @@
 	switch(ivideo->sisvga_engine) {
 	case SIS_300_VGA: reg = 0x25; break;
 	case SIS_315_VGA: reg = 0x30; break;
-	default:	  return FALSE;
+	default:	  return false;
 	}
 
 	inSISIDXREG(SISPART1, reg, temp);
 	if(temp & 0x02)
-		return TRUE;
+		return true;
 	else
-		return FALSE;
+		return false;
 }
 
-static BOOLEAN
+static bool
 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
 {
 	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
@@ -874,7 +874,7 @@
 sisfb_myblank(struct sis_video_info *ivideo, int blank)
 {
 	u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
-	BOOLEAN backlight = TRUE;
+	bool backlight = true;
 
 	switch(blank) {
 		case FB_BLANK_UNBLANK:	/* on */
@@ -884,7 +884,7 @@
 			cr63  = 0x00;
 			p2_0  = 0x20;
 			p1_13 = 0x00;
-			backlight = TRUE;
+			backlight = true;
 			break;
 		case FB_BLANK_NORMAL:	/* blank */
 			sr01  = 0x20;
@@ -893,7 +893,7 @@
 			cr63  = 0x00;
 			p2_0  = 0x20;
 			p1_13 = 0x00;
-			backlight = TRUE;
+			backlight = true;
 			break;
 		case FB_BLANK_VSYNC_SUSPEND:	/* no vsync */
 			sr01  = 0x20;
@@ -902,7 +902,7 @@
 			cr63  = 0x40;
 			p2_0  = 0x40;
 			p1_13 = 0x80;
-			backlight = FALSE;
+			backlight = false;
 			break;
 		case FB_BLANK_HSYNC_SUSPEND:	/* no hsync */
 			sr01  = 0x20;
@@ -911,7 +911,7 @@
 			cr63  = 0x40;
 			p2_0  = 0x80;
 			p1_13 = 0x40;
-			backlight = FALSE;
+			backlight = false;
 			break;
 		case FB_BLANK_POWERDOWN:	/* off */
 			sr01  = 0x20;
@@ -920,7 +920,7 @@
 			cr63  = 0x40;
 			p2_0  = 0xc0;
 			p1_13 = 0xc0;
-			backlight = FALSE;
+			backlight = false;
 			break;
 		default:
 			return 1;
@@ -1109,11 +1109,11 @@
 static void
 sisfb_set_pitch(struct sis_video_info *ivideo)
 {
-	BOOLEAN isslavemode = FALSE;
+	bool isslavemode = false;
 	unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
 	unsigned short HDisplay2 = ivideo->video_linelength >> 3;
 
-	if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
+	if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
 
 	/* We need to set pitch for CRT1 if bridge is in slave mode, too */
 	if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
@@ -1178,7 +1178,7 @@
 
 	sisfb_pre_setmode(ivideo);
 
-	if(SiSSetMode(&ivideo->SiS_Pr, modeno) == 0) {
+	if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
 		printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
 		return -EINVAL;
 	}
@@ -1446,7 +1446,7 @@
 	unsigned int drate = 0, hrate = 0, maxyres;
 	int found_mode = 0;
 	int refresh_rate, search_idx, tidx;
-	BOOLEAN recalc_clock = FALSE;
+	bool recalc_clock = false;
 	u32 pixclock;
 
 	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
@@ -1524,7 +1524,7 @@
 	    (var->bits_per_pixel == 8) ) {
 		/* Slave modes on LVDS and 301B-DH */
 		refresh_rate = 60;
-		recalc_clock = TRUE;
+		recalc_clock = true;
 	} else if( (ivideo->current_htotal == htotal) &&
 		   (ivideo->current_vtotal == vtotal) &&
 		   (ivideo->current_pixclock == pixclock) ) {
@@ -1545,17 +1545,17 @@
 		} else {
 			refresh_rate = 60;
 		}
-		recalc_clock = TRUE;
+		recalc_clock = true;
 	} else if((pixclock) && (htotal) && (vtotal)) {
 		drate = 1000000000 / pixclock;
 		hrate = (drate * 1000) / htotal;
 		refresh_rate = (unsigned int) (hrate * 2 / vtotal);
 	} else if(ivideo->current_refresh_rate) {
 		refresh_rate = ivideo->current_refresh_rate;
-		recalc_clock = TRUE;
+		recalc_clock = true;
 	} else {
 		refresh_rate = 60;
-		recalc_clock = TRUE;
+		recalc_clock = true;
 	}
 
 	myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
@@ -2181,7 +2181,7 @@
 
 /* ------------------ Sensing routines ------------------ */
 
-static BOOLEAN __devinit
+static bool __devinit
 sisfb_test_DDC1(struct sis_video_info *ivideo)
 {
     unsigned short old;
@@ -2191,13 +2191,13 @@
     do {
 	if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
     } while(count--);
-    return (count == -1) ? FALSE : TRUE;
+    return (count != -1);
 }
 
 static void __devinit
 sisfb_sense_crt1(struct sis_video_info *ivideo)
 {
-    BOOLEAN mustwait = FALSE;
+    bool mustwait = false;
     u8  sr1F, cr17;
 #ifdef CONFIG_FB_SIS_315
     u8  cr63=0;
@@ -2208,7 +2208,7 @@
     inSISIDXREG(SISSR,0x1F,sr1F);
     orSISIDXREG(SISSR,0x1F,0x04);
     andSISIDXREG(SISSR,0x1F,0x3F);
-    if(sr1F & 0xc0) mustwait = TRUE;
+    if(sr1F & 0xc0) mustwait = true;
 
 #ifdef CONFIG_FB_SIS_315
     if(ivideo->sisvga_engine == SIS_315_VGA) {
@@ -2222,7 +2222,7 @@
     cr17 &= 0x80;
     if(!cr17) {
        orSISIDXREG(SISCR,0x17,0x80);
-       mustwait = TRUE;
+       mustwait = true;
        outSISIDXREG(SISSR, 0x00, 0x01);
        outSISIDXREG(SISSR, 0x00, 0x03);
     }
@@ -2284,7 +2284,7 @@
 	u8 reg, cr37 = 0, paneltype = 0;
 	u16 xres, yres;
 
-	ivideo->SiS_Pr.PanelSelfDetected = FALSE;
+	ivideo->SiS_Pr.PanelSelfDetected = false;
 
 	/* LCD detection only for TMDS bridges */
 	if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
@@ -2361,7 +2361,7 @@
 	setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
 	orSISIDXREG(SISCR, 0x32, 0x08);
 
-	ivideo->SiS_Pr.PanelSelfDetected = TRUE;
+	ivideo->SiS_Pr.PanelSelfDetected = true;
 }
 
 static int __devinit
@@ -3016,7 +3016,7 @@
 			int tmp;
 			inSISIDXREG(SISPART1,0x13,tmp);
 			if(tmp & 0x04) {
-				ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
+				ivideo->SiS_Pr.SiS_UseLCDA = true;
 				ivideo->detectedlcda = 0x03;
 			}
 		}
@@ -3071,9 +3071,9 @@
 				inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
 				inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
 				inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
-				ivideo->SiS_Pr.HaveEMI = TRUE;
+				ivideo->SiS_Pr.HaveEMI = true;
 				if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
-					ivideo->SiS_Pr.HaveEMILCD = TRUE;
+					ivideo->SiS_Pr.HaveEMILCD = true;
 				}
 			}
 		}
@@ -3558,8 +3558,8 @@
 	}
 #endif
 
-	SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
-	SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
 	ivideo->curFSTN = ivideo->curDSTN = 0;
 
 	switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
@@ -3814,8 +3814,8 @@
 static void
 sisfb_post_setmode(struct sis_video_info *ivideo)
 {
-	BOOLEAN crt1isoff = FALSE;
-	BOOLEAN doit = TRUE;
+	bool crt1isoff = false;
+	bool doit = true;
 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 	u8 reg;
 #endif
@@ -3834,17 +3834,17 @@
 
 	/* We can't switch off CRT1 if bridge is in slave mode */
 	if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
-		if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
+		if(sisfb_bridgeisslave(ivideo)) doit = false;
 	} else
 		ivideo->sisfb_crt1off = 0;
 
 #ifdef CONFIG_FB_SIS_300
 	if(ivideo->sisvga_engine == SIS_300_VGA) {
 		if((ivideo->sisfb_crt1off) && (doit)) {
-			crt1isoff = TRUE;
+			crt1isoff = true;
 			reg = 0x00;
 		} else {
-			crt1isoff = FALSE;
+			crt1isoff = false;
 			reg = 0x80;
 		}
 		setSISIDXREG(SISCR, 0x17, 0x7f, reg);
@@ -3853,11 +3853,11 @@
 #ifdef CONFIG_FB_SIS_315
 	if(ivideo->sisvga_engine == SIS_315_VGA) {
 		if((ivideo->sisfb_crt1off) && (doit)) {
-			crt1isoff = TRUE;
+			crt1isoff = true;
 			reg  = 0x40;
 			reg1 = 0xc0;
 		} else {
-			crt1isoff = FALSE;
+			crt1isoff = false;
 			reg  = 0x00;
 			reg1 = 0x00;
 		}
@@ -4004,9 +4004,9 @@
 		} else if(!strnicmp(this_opt, "tvstandard:",11)) {
 			sisfb_search_tvstd(this_opt + 11);
 		} else if(!strnicmp(this_opt, "mode:", 5)) {
-			sisfb_search_mode(this_opt + 5, FALSE);
+			sisfb_search_mode(this_opt + 5, false);
 		} else if(!strnicmp(this_opt, "vesa:", 5)) {
-			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE);
+			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
 		} else if(!strnicmp(this_opt, "rate:", 5)) {
 			sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
 		} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
@@ -4062,7 +4062,7 @@
 			   sisfb_lvdshl = temp;
 			}
 		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
-			sisfb_search_mode(this_opt, TRUE);
+			sisfb_search_mode(this_opt, true);
 #if !defined(__i386__) && !defined(__x86_64__)
 		} else if(!strnicmp(this_opt, "resetcard", 9)) {
 			sisfb_resetcard = 1;
@@ -4564,9 +4564,9 @@
 	sisfb_sense_crt1(ivideo);
 
 	/* Set default mode, don't clear screen */
-	ivideo->SiS_Pr.SiS_UseOEM = FALSE;
-	SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
-	SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+	ivideo->SiS_Pr.SiS_UseOEM = false;
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
 	ivideo->curFSTN = ivideo->curDSTN = 0;
 	ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
 	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
@@ -5680,9 +5680,9 @@
 	} else {
 
 		/* Set default mode, don't clear screen */
-		ivideo->SiS_Pr.SiS_UseOEM = FALSE;
-		SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
-		SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+		ivideo->SiS_Pr.SiS_UseOEM = false;
+		SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+		SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
 		ivideo->curFSTN = ivideo->curDSTN = 0;
 		ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
 		SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
@@ -5723,9 +5723,9 @@
 	}
 
 	/* Set default mode, don't clear screen */
-	ivideo->SiS_Pr.SiS_UseOEM = FALSE;
-	SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
-	SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+	ivideo->SiS_Pr.SiS_UseOEM = false;
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
 	ivideo->curFSTN = ivideo->curDSTN = 0;
 	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
 
@@ -5819,7 +5819,7 @@
 	ivideo->detectedpdca = 0xff;
 	ivideo->detectedlcda = 0xff;
 
-	ivideo->sisfb_thismonitor.datavalid = FALSE;
+	ivideo->sisfb_thismonitor.datavalid = false;
 
 	ivideo->current_base = 0;
 
@@ -5871,21 +5871,21 @@
 
 	ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
 	ivideo->SiS_Pr.SiS_CHOverScan = -1;
-	ivideo->SiS_Pr.SiS_ChSW = FALSE;
-	ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
-	ivideo->SiS_Pr.HaveEMI = FALSE;
-	ivideo->SiS_Pr.HaveEMILCD = FALSE;
-	ivideo->SiS_Pr.OverruleEMI = FALSE;
-	ivideo->SiS_Pr.SiS_SensibleSR11 = FALSE;
+	ivideo->SiS_Pr.SiS_ChSW = false;
+	ivideo->SiS_Pr.SiS_UseLCDA = false;
+	ivideo->SiS_Pr.HaveEMI = false;
+	ivideo->SiS_Pr.HaveEMILCD = false;
+	ivideo->SiS_Pr.OverruleEMI = false;
+	ivideo->SiS_Pr.SiS_SensibleSR11 = false;
 	ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
 	ivideo->SiS_Pr.PDC  = -1;
 	ivideo->SiS_Pr.PDCA = -1;
-	ivideo->SiS_Pr.DDCPortMixup = FALSE;
+	ivideo->SiS_Pr.DDCPortMixup = false;
 #ifdef CONFIG_FB_SIS_315
 	if(ivideo->chip >= SIS_330) {
 		ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
 		if(ivideo->chip >= SIS_661) {
-			ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
+			ivideo->SiS_Pr.SiS_SensibleSR11 = true;
 		}
 	}
 #endif
@@ -5969,7 +5969,7 @@
         	do {
 			if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
 			   mychswtable[i].subsysCard   == ivideo->subsysdevice) {
-				ivideo->SiS_Pr.SiS_ChSW = TRUE;
+				ivideo->SiS_Pr.SiS_ChSW = true;
 				printk(KERN_DEBUG "sisfb: Identified [%s %s] "
 					"requiring Chrontel/GPIO setup\n",
 					mychswtable[i].vendorName,
@@ -6018,20 +6018,20 @@
 	/* Search and copy ROM image */
 	ivideo->bios_abase = NULL;
 	ivideo->SiS_Pr.VirtualRomBase = NULL;
-	ivideo->SiS_Pr.UseROM = FALSE;
-	ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = FALSE;
+	ivideo->SiS_Pr.UseROM = false;
+	ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
 	if(ivideo->sisfb_userom) {
 		ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
 		ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
-		ivideo->SiS_Pr.UseROM = (ivideo->SiS_Pr.VirtualRomBase) ? TRUE : FALSE;
+		ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
 		printk(KERN_INFO "sisfb: Video ROM %sfound\n",
 			ivideo->SiS_Pr.UseROM ? "" : "not ");
 		if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
-		   ivideo->SiS_Pr.UseROM = FALSE;
-		   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = TRUE;
+		   ivideo->SiS_Pr.UseROM = false;
+		   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
 		   if( (ivideo->revision_id == 2) &&
 		       (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
-			ivideo->SiS_Pr.DDCPortMixup = TRUE;
+			ivideo->SiS_Pr.DDCPortMixup = true;
 		   }
 		}
 	} else {
@@ -6677,9 +6677,9 @@
 		sisfb_search_tvstd(tvstandard);
 
 	if(mode)
-		sisfb_search_mode(mode, FALSE);
+		sisfb_search_mode(mode, false);
 	else if(vesa != -1)
-		sisfb_search_vesamode(vesa, FALSE);
+		sisfb_search_vesamode(vesa, false);
 
 	sisfb_crt1off = (crt1off == 0) ? 1 : 0;
 
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index 88e4f1e..3e3b7fa 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -411,54 +411,54 @@
 	u16 xres;
 	u16 yres;
 	u16 refresh;
-	BOOLEAN SiS730valid32bpp;
+	bool SiS730valid32bpp;
 } sisfb_vrate[] = {
-	{1,  320,  200,  70,  TRUE},
-	{1,  320,  240,  60,  TRUE},
-	{1,  400,  300,  60,  TRUE},
-	{1,  512,  384,  60,  TRUE},
-	{1,  640,  400,  72,  TRUE},
-	{1,  640,  480,  60,  TRUE}, {2,  640,  480,  72,  TRUE}, {3,  640,  480,  75,  TRUE},
-	{4,  640,  480,  85,  TRUE}, {5,  640,  480, 100,  TRUE}, {6,  640,  480, 120,  TRUE},
-	{7,  640,  480, 160,  TRUE}, {8,  640,  480, 200,  TRUE},
-	{1,  720,  480,  60,  TRUE},
-	{1,  720,  576,  58,  TRUE},
-	{1,  768,  576,  58,  TRUE},
-	{1,  800,  480,  60,  TRUE}, {2,  800,  480,  75,  TRUE}, {3,  800,  480,  85,  TRUE},
-	{1,  800,  600,  56,  TRUE}, {2,  800,  600,  60,  TRUE}, {3,  800,  600,  72,  TRUE},
-	{4,  800,  600,  75,  TRUE}, {5,  800,  600,  85,  TRUE}, {6,  800,  600, 105,  TRUE},
-	{7,  800,  600, 120,  TRUE}, {8,  800,  600, 160,  TRUE},
-	{1,  848,  480,  39,  TRUE}, {2,  848,  480,  60,  TRUE},
-	{1,  856,  480,  39,  TRUE}, {2,  856,  480,  60,  TRUE},
-	{1,  960,  540,  60,  TRUE},
-	{1,  960,  600,  60,  TRUE},
-	{1, 1024,  576,  60,  TRUE}, {2, 1024,  576,  75,  TRUE}, {3, 1024,  576,  85,  TRUE},
-	{1, 1024,  600,  60,  TRUE},
-	{1, 1024,  768,  43,  TRUE}, {2, 1024,  768,  60,  TRUE}, {3, 1024,  768,  70, FALSE},
-	{4, 1024,  768,  75, FALSE}, {5, 1024,  768,  85,  TRUE}, {6, 1024,  768, 100,  TRUE},
-	{7, 1024,  768, 120,  TRUE},
-	{1, 1152,  768,  60,  TRUE},
-	{1, 1152,  864,  60,  TRUE}, {2, 1152,  864,  75,  TRUE}, {3, 1152,  864,  84,  TRUE},
-	{1, 1280,  720,  60,  TRUE}, {2, 1280,  720,  75,  TRUE}, {3, 1280,  720,  85,  TRUE},
-	{1, 1280,  768,  60,  TRUE},
-	{1, 1280,  800,  60,  TRUE},
-	{1, 1280,  854,  60,  TRUE},
-	{1, 1280,  960,  60,  TRUE}, {2, 1280,  960,  85,  TRUE},
-	{1, 1280, 1024,  43,  TRUE}, {2, 1280, 1024,  60,  TRUE}, {3, 1280, 1024,  75,  TRUE},
-	{4, 1280, 1024,  85,  TRUE},
-	{1, 1360,  768,  60,  TRUE},
-	{1, 1360, 1024,  59,  TRUE},
-	{1, 1400, 1050,  60,  TRUE}, {2, 1400, 1050,  75,  TRUE},
-	{1, 1600, 1200,  60,  TRUE}, {2, 1600, 1200,  65,  TRUE}, {3, 1600, 1200,  70,  TRUE},
-	{4, 1600, 1200,  75,  TRUE}, {5, 1600, 1200,  85,  TRUE}, {6, 1600, 1200, 100,  TRUE},
-	{7, 1600, 1200, 120,  TRUE},
-	{1, 1680, 1050,  60,  TRUE},
-	{1, 1920, 1080,  30,  TRUE},
-	{1, 1920, 1440,  60,  TRUE}, {2, 1920, 1440,  65,  TRUE}, {3, 1920, 1440,  70,  TRUE},
-	{4, 1920, 1440,  75,  TRUE}, {5, 1920, 1440,  85,  TRUE}, {6, 1920, 1440, 100,  TRUE},
-	{1, 2048, 1536,  60,  TRUE}, {2, 2048, 1536,  65,  TRUE}, {3, 2048, 1536,  70,  TRUE},
-	{4, 2048, 1536,  75,  TRUE}, {5, 2048, 1536,  85,  TRUE},
-	{0,    0,    0,   0, FALSE}
+	{1,  320,  200,  70,  true},
+	{1,  320,  240,  60,  true},
+	{1,  400,  300,  60,  true},
+	{1,  512,  384,  60,  true},
+	{1,  640,  400,  72,  true},
+	{1,  640,  480,  60,  true}, {2,  640,  480,  72,  true}, {3,  640,  480,  75,  true},
+	{4,  640,  480,  85,  true}, {5,  640,  480, 100,  true}, {6,  640,  480, 120,  true},
+	{7,  640,  480, 160,  true}, {8,  640,  480, 200,  true},
+	{1,  720,  480,  60,  true},
+	{1,  720,  576,  58,  true},
+	{1,  768,  576,  58,  true},
+	{1,  800,  480,  60,  true}, {2,  800,  480,  75,  true}, {3,  800,  480,  85,  true},
+	{1,  800,  600,  56,  true}, {2,  800,  600,  60,  true}, {3,  800,  600,  72,  true},
+	{4,  800,  600,  75,  true}, {5,  800,  600,  85,  true}, {6,  800,  600, 105,  true},
+	{7,  800,  600, 120,  true}, {8,  800,  600, 160,  true},
+	{1,  848,  480,  39,  true}, {2,  848,  480,  60,  true},
+	{1,  856,  480,  39,  true}, {2,  856,  480,  60,  true},
+	{1,  960,  540,  60,  true},
+	{1,  960,  600,  60,  true},
+	{1, 1024,  576,  60,  true}, {2, 1024,  576,  75,  true}, {3, 1024,  576,  85,  true},
+	{1, 1024,  600,  60,  true},
+	{1, 1024,  768,  43,  true}, {2, 1024,  768,  60,  true}, {3, 1024,  768,  70, false},
+	{4, 1024,  768,  75, false}, {5, 1024,  768,  85,  true}, {6, 1024,  768, 100,  true},
+	{7, 1024,  768, 120,  true},
+	{1, 1152,  768,  60,  true},
+	{1, 1152,  864,  60,  true}, {2, 1152,  864,  75,  true}, {3, 1152,  864,  84,  true},
+	{1, 1280,  720,  60,  true}, {2, 1280,  720,  75,  true}, {3, 1280,  720,  85,  true},
+	{1, 1280,  768,  60,  true},
+	{1, 1280,  800,  60,  true},
+	{1, 1280,  854,  60,  true},
+	{1, 1280,  960,  60,  true}, {2, 1280,  960,  85,  true},
+	{1, 1280, 1024,  43,  true}, {2, 1280, 1024,  60,  true}, {3, 1280, 1024,  75,  true},
+	{4, 1280, 1024,  85,  true},
+	{1, 1360,  768,  60,  true},
+	{1, 1360, 1024,  59,  true},
+	{1, 1400, 1050,  60,  true}, {2, 1400, 1050,  75,  true},
+	{1, 1600, 1200,  60,  true}, {2, 1600, 1200,  65,  true}, {3, 1600, 1200,  70,  true},
+	{4, 1600, 1200,  75,  true}, {5, 1600, 1200,  85,  true}, {6, 1600, 1200, 100,  true},
+	{7, 1600, 1200, 120,  true},
+	{1, 1680, 1050,  60,  true},
+	{1, 1920, 1080,  30,  true},
+	{1, 1920, 1440,  60,  true}, {2, 1920, 1440,  65,  true}, {3, 1920, 1440,  70,  true},
+	{4, 1920, 1440,  75,  true}, {5, 1920, 1440,  85,  true}, {6, 1920, 1440, 100,  true},
+	{1, 2048, 1536,  60,  true}, {2, 2048, 1536,  65,  true}, {3, 2048, 1536,  70,  true},
+	{4, 2048, 1536,  75,  true}, {5, 2048, 1536,  85,  true},
+	{0,    0,    0,   0, false}
 };
 
 static struct _sisfbddcsmodes {
@@ -691,7 +691,7 @@
 extern void	sisfb_syncaccel(struct sis_video_info *ivideo);
 
 /* Internal general routines */
-static void	sisfb_search_mode(char *name, BOOLEAN quiet);
+static void	sisfb_search_mode(char *name, bool quiet);
 static int	sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
 static u8	sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
 				int index);
@@ -702,10 +702,10 @@
 				struct fb_info *info);
 static void	sisfb_pre_setmode(struct sis_video_info *ivideo);
 static void	sisfb_post_setmode(struct sis_video_info *ivideo);
-static BOOLEAN	sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
-static BOOLEAN	sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
-static BOOLEAN	sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
-static BOOLEAN	sisfb_bridgeisslave(struct sis_video_info *ivideo);
+static bool	sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
+static bool	sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
+static bool	sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
+static bool	sisfb_bridgeisslave(struct sis_video_info *ivideo);
 static void	sisfb_detect_VB_connect(struct sis_video_info *ivideo);
 static void	sisfb_get_VB_type(struct sis_video_info *ivideo);
 static void	sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
@@ -737,20 +737,20 @@
 
 /* Routines from init.c/init301.c */
 extern unsigned short	SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
-				int VDisplay, int Depth, BOOLEAN FSTN, unsigned short CustomT,
+				int VDisplay, int Depth, bool FSTN, unsigned short CustomT,
 				int LCDwith, int LCDheight, unsigned int VBFlags2);
 extern unsigned short	SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
 				int VDisplay, int Depth, unsigned int VBFlags2);
 extern unsigned short	SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
 				int VDisplay, int Depth, unsigned int VBFlags2);
 extern void		SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-extern BOOLEAN		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern bool		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 extern void		SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
 extern void		SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
 
-extern BOOLEAN		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+extern bool		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
 
-extern BOOLEAN		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+extern bool		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
 				int *htotal, int *vtotal, unsigned char rateindex);
 extern int		sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
 				unsigned char modeno, unsigned char rateindex);
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h
index 05d08b7..b532fbd 100644
--- a/drivers/video/sis/vgatypes.h
+++ b/drivers/video/sis/vgatypes.h
@@ -57,18 +57,6 @@
 #include <linux/version.h>
 #endif
 
-#ifndef FALSE
-#define FALSE   0
-#endif
-
-#ifndef TRUE
-#define TRUE    1
-#endif
-
-#ifndef BOOLEAN
-typedef unsigned int BOOLEAN;
-#endif
-
 #define SISIOMEMTYPE
 
 #ifdef SIS_LINUX_KERNEL
diff --git a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h
index 9ae3292..705c853 100644
--- a/drivers/video/sis/vstruct.h
+++ b/drivers/video/sis/vstruct.h
@@ -240,7 +240,7 @@
 	void				*ivideo;
 #endif
 	unsigned char 			*VirtualRomBase;
-	BOOLEAN				UseROM;
+	bool				UseROM;
 #ifdef SIS_LINUX_KERNEL
 	unsigned char SISIOMEMTYPE	*VideoMemoryAddress;
 	unsigned int			VideoMemorySize;
@@ -283,24 +283,24 @@
 #ifdef SIS_XORG_XF86
 	unsigned short			SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
 #endif
-	BOOLEAN				SiS_UseROM;
-	BOOLEAN				SiS_ROMNew;
-	BOOLEAN				SiS_XGIROM;
-	BOOLEAN				SiS_NeedRomModeData;
-	BOOLEAN				PanelSelfDetected;
-	BOOLEAN				DDCPortMixup;
+	bool				SiS_UseROM;
+	bool				SiS_ROMNew;
+	bool				SiS_XGIROM;
+	bool				SiS_NeedRomModeData;
+	bool				PanelSelfDetected;
+	bool				DDCPortMixup;
 	int				SiS_CHOverScan;
-	BOOLEAN				SiS_CHSOverScan;
-	BOOLEAN				SiS_ChSW;
-	BOOLEAN				SiS_UseLCDA;
+	bool				SiS_CHSOverScan;
+	bool				SiS_ChSW;
+	bool				SiS_UseLCDA;
 	int				SiS_UseOEM;
 	unsigned int			SiS_CustomT;
 	int				SiS_UseWide, SiS_UseWideCRT2;
 	int				SiS_TVBlue;
 	unsigned short			SiS_Backup70xx;
-	BOOLEAN				HaveEMI;
-	BOOLEAN				HaveEMILCD;
-	BOOLEAN				OverruleEMI;
+	bool				HaveEMI;
+	bool				HaveEMILCD;
+	bool				OverruleEMI;
 	unsigned char			EMI_30,EMI_31,EMI_32,EMI_33;
 	unsigned short			SiS_EMIOffset;
 	unsigned short			SiS_PWDOffset;
@@ -352,7 +352,7 @@
 	unsigned short			SiS_DDC_ReadAddr;
 	unsigned short			SiS_DDC_SecAddr;
 	unsigned short			SiS_ChrontelInit;
-	BOOLEAN				SiS_SensibleSR11;
+	bool				SiS_SensibleSR11;
 	unsigned short			SiS661LCD2TableSize;
 
 	unsigned short			SiS_PanelMinLVDS;
@@ -494,10 +494,10 @@
 	unsigned short			PanelVRS,  PanelVRE;
 	unsigned short			PanelVCLKIdx300;
 	unsigned short			PanelVCLKIdx315;
-	BOOLEAN				Alternate1600x1200;
+	bool				Alternate1600x1200;
 
-	BOOLEAN				UseCustomMode;
-	BOOLEAN				CRT1UsesCustomMode;
+	bool				UseCustomMode;
+	bool				CRT1UsesCustomMode;
 	unsigned short			CHDisplay;
 	unsigned short			CHSyncStart;
 	unsigned short			CHSyncEnd;
@@ -523,7 +523,7 @@
 
 	int				LVDSHL;
 
-	BOOLEAN				Backup;
+	bool				Backup;
 	unsigned char			Backup_Mode;
 	unsigned char			Backup_14;
 	unsigned char			Backup_15;
@@ -542,12 +542,12 @@
 	int				CenterScreen;
 
 	unsigned short			CP_Vendor, CP_Product;
-	BOOLEAN				CP_HaveCustomData;
+	bool				CP_HaveCustomData;
 	int				CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
 	int				CP_MaxX, CP_MaxY, CP_MaxClock;
 	unsigned char			CP_PrefSR2B, CP_PrefSR2C;
 	unsigned short			CP_PrefClock;
-	BOOLEAN				CP_Supports64048075;
+	bool				CP_Supports64048075;
 	int				CP_HDisplay[7], CP_VDisplay[7];	/* For Custom LCD panel dimensions */
 	int				CP_HTotal[7], CP_VTotal[7];
 	int				CP_HSyncStart[7], CP_VSyncStart[7];
@@ -555,8 +555,8 @@
 	int				CP_HBlankStart[7], CP_VBlankStart[7];
 	int				CP_HBlankEnd[7], CP_VBlankEnd[7];
 	int				CP_Clock[7];
-	BOOLEAN				CP_DataValid[7];
-	BOOLEAN				CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
+	bool				CP_DataValid[7];
+	bool				CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
 };
 
 #endif
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
new file mode 100644
index 0000000..02b290c
--- /dev/null
+++ b/drivers/video/sm501fb.c
@@ -0,0 +1,1786 @@
+/* linux/drivers/video/sm501fb.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Vincent Sanders <vince@simtec.co.uk>
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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.
+ *
+ * Framebuffer driver for the Silicon Motion SM501
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/div64.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
+#define NR_PALETTE	256
+
+enum sm501_controller {
+	HEAD_CRT	= 0,
+	HEAD_PANEL	= 1,
+};
+
+/* SM501 memory adress */
+struct sm501_mem {
+	unsigned long	 size;
+	unsigned long	 sm_addr;
+	void __iomem	*k_addr;
+};
+
+/* private data that is shared between all frambuffers* */
+struct sm501fb_info {
+	struct device		*dev;
+	struct fb_info		*fb[2];		/* fb info for both heads */
+	struct resource		*fbmem_res;	/* framebuffer resource */
+	struct resource		*regs_res;	/* registers resource */
+	struct sm501_platdata_fb *pdata;	/* our platform data */
+
+	int			 irq;
+	int			 swap_endian;	/* set to swap rgb=>bgr */
+	void __iomem		*regs;		/* remapped registers */
+	void __iomem		*fbmem;		/* remapped framebuffer */
+	size_t			 fbmem_len;	/* length of remapped region */
+};
+
+/* per-framebuffer private data */
+struct sm501fb_par {
+	u32			 pseudo_palette[16];
+
+	enum sm501_controller	 head;
+	struct sm501_mem	 cursor;
+	struct sm501_mem	 screen;
+	struct fb_ops		 ops;
+
+	void			*store_fb;
+	void			*store_cursor;
+	void __iomem		*cursor_regs;
+	struct sm501fb_info	*info;
+};
+
+/* Helper functions */
+
+static inline int h_total(struct fb_var_screeninfo *var)
+{
+	return var->xres + var->left_margin +
+		var->right_margin + var->hsync_len;
+}
+
+static inline int v_total(struct fb_var_screeninfo *var)
+{
+	return var->yres + var->upper_margin +
+		var->lower_margin + var->vsync_len;
+}
+
+/* sm501fb_sync_regs()
+ *
+ * This call is mainly for PCI bus systems where we need to
+ * ensure that any writes to the bus are completed before the
+ * next phase, or after completing a function.
+*/
+
+static inline void sm501fb_sync_regs(struct sm501fb_info *info)
+{
+	readl(info->regs);
+}
+
+/* sm501_alloc_mem
+ *
+ * This is an attempt to lay out memory for the two framebuffers and
+ * everything else
+ *
+ * |fbmem_res->start	                                       fbmem_res->end|
+ * |                                                                         |
+ * |fb[0].fix.smem_start    |         |fb[1].fix.smem_start    |     2K      |
+ * |-> fb[0].fix.smem_len <-| spare   |-> fb[1].fix.smem_len <-|-> cursors <-|
+ *
+ * The "spare" space is for the 2d engine data
+ * the fixed is space for the cursors (2x1Kbyte)
+ *
+ * we need to allocate memory for the 2D acceleration engine
+ * command list and the data for the engine to deal with.
+ *
+ * - all allocations must be 128bit aligned
+ * - cursors are 64x64x2 bits (1Kbyte)
+ *
+ */
+
+#define SM501_MEMF_CURSOR		(1)
+#define SM501_MEMF_PANEL		(2)
+#define SM501_MEMF_CRT			(4)
+#define SM501_MEMF_ACCEL		(8)
+
+int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
+		    unsigned int why, size_t size)
+{
+	unsigned int ptr = 0;
+
+	switch (why) {
+	case SM501_MEMF_CURSOR:
+		ptr = inf->fbmem_len - size;
+		inf->fbmem_len = ptr;
+		break;
+
+	case SM501_MEMF_PANEL:
+		ptr = inf->fbmem_len - size;
+		if (ptr < inf->fb[0]->fix.smem_len)
+			return -ENOMEM;
+
+		break;
+
+	case SM501_MEMF_CRT:
+		ptr = 0;
+		break;
+
+	case SM501_MEMF_ACCEL:
+		ptr = inf->fb[0]->fix.smem_len;
+
+		if ((ptr + size) >
+		    (inf->fb[1]->fix.smem_start - inf->fbmem_res->start))
+			return -ENOMEM;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	mem->size    = size;
+	mem->sm_addr = ptr;
+	mem->k_addr  = inf->fbmem + ptr;
+
+	dev_dbg(inf->dev, "%s: result %08lx, %p - %u, %zd\n",
+		__func__, mem->sm_addr, mem->k_addr, why, size);
+
+	return 0;
+}
+
+/* sm501fb_ps_to_hz
+ *
+ * Converts a period in picoseconds to Hz.
+ *
+ * Note, we try to keep this in Hz to minimise rounding with
+ * the limited PLL settings on the SM501.
+*/
+
+static unsigned long sm501fb_ps_to_hz(unsigned long psvalue)
+{
+	unsigned long long numerator=1000000000000ULL;
+
+	/* 10^12 / picosecond period gives frequency in Hz */
+	do_div(numerator, psvalue);
+	return (unsigned long)numerator;
+}
+
+/* sm501fb_hz_to_ps is identical to the oposite transform */
+
+#define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x)
+
+/* sm501fb_setup_gamma
+ *
+ * Programs a linear 1.0 gamma ramp in case the gamma
+ * correction is enabled without programming anything else.
+*/
+
+static void sm501fb_setup_gamma(struct sm501fb_info *fbi,
+				unsigned long palette)
+{
+	unsigned long value = 0;
+	int offset;
+
+	/* set gamma values */
+	for (offset = 0; offset < 256 * 4; offset += 4) {
+		writel(value, fbi->regs + palette + offset);
+		value += 0x010101; 	/* Advance RGB by 1,1,1.*/
+	}
+}
+
+/* sm501fb_check_var
+ *
+ * check common variables for both panel and crt
+*/
+
+static int sm501fb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *sm  = par->info;
+	unsigned long tmp;
+
+	/* check we can fit these values into the registers */
+
+	if (var->hsync_len > 255 || var->vsync_len > 255)
+		return -EINVAL;
+
+	if ((var->xres + var->right_margin) >= 4096)
+		return -EINVAL;
+
+	if ((var->yres + var->lower_margin) > 2048)
+		return -EINVAL;
+
+	/* hard limits of device */
+
+	if (h_total(var) > 4096 || v_total(var) > 2048)
+		return -EINVAL;
+
+	/* check our line length is going to be 128 bit aligned */
+
+	tmp = (var->xres * var->bits_per_pixel) / 8;
+	if ((tmp & 15) != 0)
+		return -EINVAL;
+
+	/* check the virtual size */
+
+	if (var->xres_virtual > 4096 || var->yres_virtual > 2048)
+		return -EINVAL;
+
+	/* can cope with 8,16 or 32bpp */
+
+	if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel == 24)
+		var->bits_per_pixel = 32;
+
+	/* set r/g/b positions and validate bpp */
+	switch(var->bits_per_pixel) {
+	case 8:
+		var->red.length		= var->bits_per_pixel;
+		var->red.offset		= 0;
+		var->green.length	= var->bits_per_pixel;
+		var->green.offset	= 0;
+		var->blue.length	= var->bits_per_pixel;
+		var->blue.offset	= 0;
+		var->transp.length	= 0;
+
+		break;
+
+	case 16:
+		if (sm->pdata->flags & SM501_FBPD_SWAP_FB_ENDIAN) {
+			var->red.offset		= 11;
+			var->green.offset	= 5;
+			var->blue.offset	= 0;
+		} else {
+			var->blue.offset	= 11;
+			var->green.offset	= 5;
+			var->red.offset		= 0;
+		}
+
+		var->red.length		= 5;
+		var->green.length	= 6;
+		var->blue.length	= 5;
+		var->transp.length	= 0;
+		break;
+
+	case 32:
+		if (sm->pdata->flags & SM501_FBPD_SWAP_FB_ENDIAN) {
+			var->transp.offset	= 0;
+			var->red.offset		= 8;
+			var->green.offset	= 16;
+			var->blue.offset	= 24;
+		} else {
+			var->transp.offset	= 24;
+			var->red.offset		= 16;
+			var->green.offset	= 8;
+			var->blue.offset	= 0;
+		}
+
+		var->red.length		= 8;
+		var->green.length	= 8;
+		var->blue.length	= 8;
+		var->transp.length	= 0;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * sm501fb_check_var_crt():
+ *
+ * check the parameters for the CRT head, and either bring them
+ * back into range, or return -EINVAL.
+*/
+
+static int sm501fb_check_var_crt(struct fb_var_screeninfo *var,
+				 struct fb_info *info)
+{
+	return sm501fb_check_var(var, info);
+}
+
+/* sm501fb_check_var_pnl():
+ *
+ * check the parameters for the CRT head, and either bring them
+ * back into range, or return -EINVAL.
+*/
+
+static int sm501fb_check_var_pnl(struct fb_var_screeninfo *var,
+				 struct fb_info *info)
+{
+	return sm501fb_check_var(var, info);
+}
+
+/* sm501fb_set_par_common
+ *
+ * set common registers for framebuffers
+*/
+
+static int sm501fb_set_par_common(struct fb_info *info,
+				  struct fb_var_screeninfo *var)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	unsigned long pixclock;      /* pixelclock in Hz */
+	unsigned long sm501pixclock; /* pixelclock the 501 can achive in Hz */
+	unsigned int mem_type;
+	unsigned int clock_type;
+	unsigned int head_addr;
+
+	dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n",
+		__func__, var->xres, var->yres, var->bits_per_pixel,
+		var->xres_virtual, var->yres_virtual);
+
+	switch (par->head) {
+	case HEAD_CRT:
+		mem_type = SM501_MEMF_CRT;
+		clock_type = SM501_CLOCK_V2XCLK;
+		head_addr = SM501_DC_CRT_FB_ADDR;
+		break;
+
+	case HEAD_PANEL:
+		mem_type = SM501_MEMF_PANEL;
+		clock_type = SM501_CLOCK_P2XCLK;
+		head_addr = SM501_DC_PANEL_FB_ADDR;
+		break;
+
+	default:
+		mem_type = 0;		/* stop compiler warnings */
+		head_addr = 0;
+		clock_type = 0;
+	}
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+
+	case 16:
+		info->fix.visual = FB_VISUAL_DIRECTCOLOR;
+		break;
+
+	case 32:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	}
+
+	/* allocate fb memory within 501 */
+	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8;
+	info->fix.smem_len    = info->fix.line_length * var->yres_virtual;
+
+	dev_dbg(fbi->dev, "%s: line length = %u\n", __func__,
+		info->fix.line_length);
+
+	if (sm501_alloc_mem(fbi, &par->screen, mem_type,
+			    info->fix.smem_len)) {
+		dev_err(fbi->dev, "no memory available\n");
+		return -ENOMEM;
+	}
+
+	info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr;
+
+	info->screen_base = fbi->fbmem + par->screen.sm_addr;
+	info->screen_size = info->fix.smem_len;
+
+	/* set start of framebuffer to the screen */
+
+	writel(par->screen.sm_addr | SM501_ADDR_FLIP, fbi->regs + head_addr);
+
+	/* program CRT clock  */
+
+	pixclock = sm501fb_ps_to_hz(var->pixclock);
+
+	sm501pixclock = sm501_set_clock(fbi->dev->parent, clock_type,
+					pixclock);
+
+	/* update fb layer with actual clock used */
+	var->pixclock = sm501fb_hz_to_ps(sm501pixclock);
+
+	dev_dbg(fbi->dev, "%s: pixclock(ps) = %u, pixclock(Hz)  = %lu, "
+	       "sm501pixclock = %lu,  error = %ld%%\n",
+	       __func__, var->pixclock, pixclock, sm501pixclock,
+	       ((pixclock - sm501pixclock)*100)/pixclock);
+
+	return 0;
+}
+
+/* sm501fb_set_par_geometry
+ *
+ * set the geometry registers for specified framebuffer.
+*/
+
+static void sm501fb_set_par_geometry(struct fb_info *info,
+				     struct fb_var_screeninfo *var)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	void __iomem *base = fbi->regs;
+	unsigned long reg;
+
+	if (par->head == HEAD_CRT)
+		base += SM501_DC_CRT_H_TOT;
+	else
+		base += SM501_DC_PANEL_H_TOT;
+
+	/* set framebuffer width and display width */
+
+	reg = info->fix.line_length;
+	reg |= ((var->xres * var->bits_per_pixel)/8) << 16;
+
+	writel(reg, fbi->regs + (par->head == HEAD_CRT ?
+		    SM501_DC_CRT_FB_OFFSET :  SM501_DC_PANEL_FB_OFFSET));
+
+	/* program horizontal total */
+
+	reg  = (h_total(var) - 1) << 16;
+	reg |= (var->xres - 1);
+
+	writel(reg, base + SM501_OFF_DC_H_TOT);
+
+	/* program horizontal sync */
+
+	reg  = var->hsync_len << 16;
+	reg |= var->xres + var->right_margin - 1;
+
+	writel(reg, base + SM501_OFF_DC_H_SYNC);
+
+	/* program vertical total */
+
+	reg  = (v_total(var) - 1) << 16;
+	reg |= (var->yres - 1);
+
+	writel(reg, base + SM501_OFF_DC_V_TOT);
+
+	/* program vertical sync */
+	reg  = var->vsync_len << 16;
+	reg |= var->yres + var->lower_margin - 1;
+
+	writel(reg, base + SM501_OFF_DC_V_SYNC);
+}
+
+/* sm501fb_pan_crt
+ *
+ * pan the CRT display output within an virtual framebuffer
+*/
+
+static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	unsigned int bytes_pixel = var->bits_per_pixel / 8;
+	unsigned long reg;
+	unsigned long xoffs;
+
+	xoffs = var->xoffset * bytes_pixel;
+
+	reg = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+
+	reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK;
+	reg |= ((xoffs & 15) / bytes_pixel) << 4;
+	writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
+
+	reg = (par->screen.sm_addr + xoffs +
+	       var->yoffset * info->fix.line_length);
+	writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
+
+	sm501fb_sync_regs(fbi);
+	return 0;
+}
+
+/* sm501fb_pan_pnl
+ *
+ * pan the panel display output within an virtual framebuffer
+*/
+
+static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	unsigned long reg;
+
+	reg = var->xoffset | (var->xres_virtual << 16);
+	writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
+
+	reg = var->yoffset | (var->yres_virtual << 16);
+	writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
+
+	sm501fb_sync_regs(fbi);
+	return 0;
+}
+
+/* sm501fb_set_par_crt
+ *
+ * Set the CRT video mode from the fb_info structure
+*/
+
+static int sm501fb_set_par_crt(struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	struct fb_var_screeninfo *var = &info->var;
+	unsigned long control;       /* control register */
+	int ret;
+
+	/* activate new configuration */
+
+	dev_dbg(fbi->dev, "%s(%p)\n", __func__, info);
+
+	/* enable CRT DAC - note 0 is on!*/
+	sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
+
+	control = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+
+	control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK |
+		    SM501_DC_CRT_CONTROL_GAMMA |
+		    SM501_DC_CRT_CONTROL_BLANK |
+		    SM501_DC_CRT_CONTROL_SEL |
+		    SM501_DC_CRT_CONTROL_CP |
+		    SM501_DC_CRT_CONTROL_TVP);
+
+	/* set the sync polarities before we check data source  */
+
+	if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
+		control |= SM501_DC_CRT_CONTROL_HSP;
+
+	if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
+		control |= SM501_DC_CRT_CONTROL_VSP;
+
+	if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) {
+		/* the head is displaying panel data... */
+
+		sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0);
+		goto out_update;
+	}
+
+	ret = sm501fb_set_par_common(info, var);
+	if (ret) {
+		dev_err(fbi->dev, "failed to set common parameters\n");
+		return ret;
+	}
+
+	sm501fb_pan_crt(var, info);
+	sm501fb_set_par_geometry(info, var);
+
+	control |= SM501_FIFO_3;	/* fill if >3 free slots */
+
+	switch(var->bits_per_pixel) {
+	case 8:
+		control |= SM501_DC_CRT_CONTROL_8BPP;
+		break;
+
+	case 16:
+		control |= SM501_DC_CRT_CONTROL_16BPP;
+		break;
+
+	case 32:
+		control |= SM501_DC_CRT_CONTROL_32BPP;
+		sm501fb_setup_gamma(fbi, SM501_DC_CRT_PALETTE);
+		break;
+
+	default:
+		BUG();
+	}
+
+	control |= SM501_DC_CRT_CONTROL_SEL;	/* CRT displays CRT data */
+	control |= SM501_DC_CRT_CONTROL_TE;	/* enable CRT timing */
+	control |= SM501_DC_CRT_CONTROL_ENABLE;	/* enable CRT plane */
+
+ out_update:
+	dev_dbg(fbi->dev, "new control is %08lx\n", control);
+
+	writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
+	sm501fb_sync_regs(fbi);
+
+	return 0;
+}
+
+static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
+{
+	unsigned long control;
+	void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
+
+	control = readl(ctrl_reg);
+
+	if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) {
+		/* enable panel power */
+
+		control |= SM501_DC_PANEL_CONTROL_VDD;	/* FPVDDEN */
+		writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+
+		control |= SM501_DC_PANEL_CONTROL_DATA;	/* DATA */
+		writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+
+		control |= SM501_DC_PANEL_CONTROL_BIAS;	/* VBIASEN */
+		writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+
+		control |= SM501_DC_PANEL_CONTROL_FPEN;
+		writel(control, ctrl_reg);
+
+	} else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
+		/* disable panel power */
+
+		control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+		writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+
+		control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+		writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+
+		control &= ~SM501_DC_PANEL_CONTROL_DATA;
+		writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+
+		control &= ~SM501_DC_PANEL_CONTROL_VDD;
+		writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+	}
+
+	sm501fb_sync_regs(fbi);
+}
+
+/* sm501fb_set_par_pnl
+ *
+ * Set the panel video mode from the fb_info structure
+*/
+
+static int sm501fb_set_par_pnl(struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	struct fb_var_screeninfo *var = &info->var;
+	unsigned long control;
+	unsigned long reg;
+	int ret;
+
+	dev_dbg(fbi->dev, "%s(%p)\n", __func__, info);
+
+	/* activate this new configuration */
+
+	ret = sm501fb_set_par_common(info, var);
+	if (ret)
+		return ret;
+
+	sm501fb_pan_pnl(var, info);
+	sm501fb_set_par_geometry(info, var);
+
+	/* update control register */
+
+	control = readl(fbi->regs + SM501_DC_PANEL_CONTROL);
+	control &= (SM501_DC_PANEL_CONTROL_GAMMA |
+		    SM501_DC_PANEL_CONTROL_VDD  |
+		    SM501_DC_PANEL_CONTROL_DATA |
+		    SM501_DC_PANEL_CONTROL_BIAS |
+		    SM501_DC_PANEL_CONTROL_FPEN |
+		    SM501_DC_PANEL_CONTROL_CP |
+		    SM501_DC_PANEL_CONTROL_CK |
+		    SM501_DC_PANEL_CONTROL_HP |
+		    SM501_DC_PANEL_CONTROL_VP |
+		    SM501_DC_PANEL_CONTROL_HPD |
+		    SM501_DC_PANEL_CONTROL_VPD);
+
+	control |= SM501_FIFO_3;	/* fill if >3 free slots */
+
+	switch(var->bits_per_pixel) {
+	case 8:
+		control |= SM501_DC_PANEL_CONTROL_8BPP;
+		break;
+
+	case 16:
+		control |= SM501_DC_PANEL_CONTROL_16BPP;
+		break;
+
+	case 32:
+		control |= SM501_DC_PANEL_CONTROL_32BPP;
+		sm501fb_setup_gamma(fbi, SM501_DC_PANEL_PALETTE);
+		break;
+
+	default:
+		BUG();
+	}
+
+	writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
+
+	/* panel plane top left and bottom right location */
+
+	writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
+
+	reg  = var->xres - 1;
+	reg |= (var->yres - 1) << 16;
+
+	writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
+
+	/* program panel control register */
+
+	control |= SM501_DC_PANEL_CONTROL_TE;	/* enable PANEL timing */
+	control |= SM501_DC_PANEL_CONTROL_EN;	/* enable PANEL gfx plane */
+
+	if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
+		control |= SM501_DC_PANEL_CONTROL_HSP;
+
+	if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
+		control |= SM501_DC_PANEL_CONTROL_VSP;
+
+	writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
+	sm501fb_sync_regs(fbi);
+
+	/* power the panel up */
+	sm501fb_panel_power(fbi, 1);
+	return 0;
+}
+
+
+/* chan_to_field
+ *
+ * convert a colour value into a field position
+ *
+ * from pxafb.c
+*/
+
+static inline unsigned int chan_to_field(unsigned int chan,
+					 struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+/* sm501fb_setcolreg
+ *
+ * set the colour mapping for modes that support palettised data
+*/
+
+static int sm501fb_setcolreg(unsigned regno,
+			     unsigned red, unsigned green, unsigned blue,
+			     unsigned transp, struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	void __iomem *base = fbi->regs;
+	unsigned int val;
+
+	if (par->head == HEAD_CRT)
+		base += SM501_DC_CRT_PALETTE;
+	else
+		base += SM501_DC_PANEL_PALETTE;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/* true-colour, use pseuo-palette */
+
+		if (regno < 16) {
+			u32 *pal = par->pseudo_palette;
+
+			val  = chan_to_field(red,   &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue,  &info->var.blue);
+
+			pal[regno] = val;
+		}
+		break;
+
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno < 256) {
+			val = (red >> 8) << 16;
+			val |= (green >> 8) << 8;
+			val |= blue >> 8;
+
+			writel(val, base + (regno * 4));
+		}
+
+		break;
+
+	default:
+		return 1;   /* unknown type */
+	}
+
+	return 0;
+}
+
+/* sm501fb_blank_pnl
+ *
+ * Blank or un-blank the panel interface
+*/
+
+static int sm501fb_blank_pnl(int blank_mode, struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+
+	dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
+
+	switch (blank_mode) {
+	case FB_BLANK_POWERDOWN:
+		sm501fb_panel_power(fbi, 0);
+		break;
+
+	case FB_BLANK_UNBLANK:
+		sm501fb_panel_power(fbi, 1);
+		break;
+
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+/* sm501fb_blank_crt
+ *
+ * Blank or un-blank the crt interface
+*/
+
+static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	unsigned long ctrl;
+
+	dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
+
+	ctrl = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+
+	switch (blank_mode) {
+	case FB_BLANK_POWERDOWN:
+		ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE;
+		sm501_misc_control(fbi->dev->parent, SM501_MISC_DAC_POWER, 0);
+
+	case FB_BLANK_NORMAL:
+		ctrl |= SM501_DC_CRT_CONTROL_BLANK;
+		break;
+
+	case FB_BLANK_UNBLANK:
+		ctrl &= ~SM501_DC_CRT_CONTROL_BLANK;
+		ctrl |=  SM501_DC_CRT_CONTROL_ENABLE;
+		sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
+		break;
+
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	default:
+		return 1;
+
+	}
+
+	writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
+	sm501fb_sync_regs(fbi);
+
+	return 0;
+}
+
+/* sm501fb_cursor
+ *
+ * set or change the hardware cursor parameters
+*/
+
+int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	void __iomem *base = fbi->regs;
+	unsigned long hwc_addr;
+	unsigned long fg, bg;
+
+	dev_dbg(fbi->dev, "%s(%p,%p)\n", __func__, info, cursor);
+
+	if (par->head == HEAD_CRT)
+		base += SM501_DC_CRT_HWC_BASE;
+	else
+		base += SM501_DC_PANEL_HWC_BASE;
+
+	/* check not being asked to exceed capabilities */
+
+	if (cursor->image.width > 64)
+		return -EINVAL;
+
+	if (cursor->image.height > 64)
+		return -EINVAL;
+
+	if (cursor->image.depth > 1)
+		return -EINVAL;
+
+	hwc_addr = readl(base + SM501_OFF_HWC_ADDR);
+
+	if (cursor->enable)
+		writel(hwc_addr | SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+	else
+		writel(hwc_addr & ~SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+
+	/* set data */
+	if (cursor->set & FB_CUR_SETPOS) {
+		unsigned int x = cursor->image.dx;
+		unsigned int y = cursor->image.dy;
+
+		if (x >= 2048 || y >= 2048 )
+			return -EINVAL;
+
+		dev_dbg(fbi->dev, "set position %d,%d\n", x, y);
+
+		//y += cursor->image.height;
+
+		writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
+	}
+
+	if (cursor->set & FB_CUR_SETCMAP) {
+		unsigned int bg_col = cursor->image.bg_color;
+		unsigned int fg_col = cursor->image.fg_color;
+
+		dev_dbg(fbi->dev, "%s: update cmap (%08x,%08x)\n",
+			__func__, bg_col, fg_col);
+
+		bg = ((info->cmap.red[bg_col] & 0xF8) << 8) |
+			((info->cmap.green[bg_col] & 0xFC) << 3) |
+			((info->cmap.blue[bg_col] & 0xF8) >> 3);
+
+		fg = ((info->cmap.red[fg_col] & 0xF8) << 8) |
+			((info->cmap.green[fg_col] & 0xFC) << 3) |
+			((info->cmap.blue[fg_col] & 0xF8) >> 3);
+
+		dev_dbg(fbi->dev, "fgcol %08x, bgcol %08x\n", fg, bg);
+
+		writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
+		writel(fg, base + SM501_OFF_HWC_COLOR_3);
+	}
+
+	if (cursor->set & FB_CUR_SETSIZE ||
+	    cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {
+		/* SM501 cursor is a two bpp 64x64 bitmap this routine
+		 * clears it to transparent then combines the cursor
+		 * shape plane with the colour plane to set the
+		 * cursor */
+		int x, y;
+		const unsigned char *pcol = cursor->image.data;
+		const unsigned char *pmsk = cursor->mask;
+		void __iomem   *dst = par->cursor.k_addr;
+		unsigned char  dcol = 0;
+		unsigned char  dmsk = 0;
+		unsigned int   op;
+
+		dev_dbg(fbi->dev, "%s: setting shape (%d,%d)\n",
+			__func__, cursor->image.width, cursor->image.height);
+
+		for (op = 0; op < (64*64*2)/8; op+=4)
+			writel(0x0, dst + op);
+
+		for (y = 0; y < cursor->image.height; y++) {
+			for (x = 0; x < cursor->image.width; x++) {
+				if ((x % 8) == 0) {
+					dcol = *pcol++;
+					dmsk = *pmsk++;
+				} else {
+					dcol >>= 1;
+					dmsk >>= 1;
+				}
+
+				if (dmsk & 1) {
+					op = (dcol & 1) ? 1 : 3;
+					op <<= ((x % 4) * 2);
+
+					op |= readb(dst + (x / 4));
+					writeb(op, dst + (x / 4));
+				}
+			}
+			dst += (64*2)/8;
+		}
+	}
+
+	sm501fb_sync_regs(fbi);	/* ensure cursor data flushed */
+	return 0;
+}
+
+/* sm501fb_crtsrc_show
+ *
+ * device attribute code to show where the crt output is sourced from
+*/
+
+static ssize_t sm501fb_crtsrc_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct sm501fb_info *info = dev_get_drvdata(dev);
+	unsigned long ctrl;
+
+	ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+	ctrl &= SM501_DC_CRT_CONTROL_SEL;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel");
+}
+
+/* sm501fb_crtsrc_show
+ *
+ * device attribute code to set where the crt output is sourced from
+*/
+
+static ssize_t sm501fb_crtsrc_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t len)
+{
+	struct sm501fb_info *info = dev_get_drvdata(dev);
+	enum sm501_controller head;
+	unsigned long ctrl;
+
+	if (len < 1)
+		return -EINVAL;
+
+	if (strnicmp(buf, "crt", sizeof("crt")) == 0)
+		head = HEAD_CRT;
+	else if (strnicmp(buf, "panel", sizeof("panel")) == 0)
+		head = HEAD_PANEL;
+	else
+		return -EINVAL;
+
+	dev_info(dev, "setting crt source to head %d\n", head);
+
+	ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+
+	if (head == HEAD_CRT) {
+		ctrl |= SM501_DC_CRT_CONTROL_SEL;
+		ctrl |= SM501_DC_CRT_CONTROL_ENABLE;
+		ctrl |= SM501_DC_CRT_CONTROL_TE;
+	} else {
+		ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
+		ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE;
+		ctrl &= ~SM501_DC_CRT_CONTROL_TE;
+	}
+
+	writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+	sm501fb_sync_regs(info);
+
+	return (head == HEAD_CRT) ? 3 : 5;
+}
+
+/* Prepare the device_attr for registration with sysfs later */
+static DEVICE_ATTR(crt_src, 0666, sm501fb_crtsrc_show, sm501fb_crtsrc_store);
+
+/* sm501fb_show_regs
+ *
+ * show the primary sm501 registers
+*/
+static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr,
+			     unsigned int start, unsigned int len)
+{
+	void __iomem *mem = info->regs;
+	char *buf = ptr;
+	unsigned int reg;
+
+	for (reg = start; reg < (len + start); reg += 4)
+		ptr += sprintf(ptr, "%08x = %08x\n", reg, readl(mem + reg));
+
+	return ptr - buf;
+}
+
+/* sm501fb_debug_show_crt
+ *
+ * show the crt control and cursor registers
+*/
+
+static ssize_t sm501fb_debug_show_crt(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct sm501fb_info *info = dev_get_drvdata(dev);
+	char *ptr = buf;
+
+	ptr += sm501fb_show_regs(info, ptr, SM501_DC_CRT_CONTROL, 0x40);
+	ptr += sm501fb_show_regs(info, ptr, SM501_DC_CRT_HWC_BASE, 0x10);
+
+	return ptr - buf;
+}
+
+static DEVICE_ATTR(fbregs_crt, 0444, sm501fb_debug_show_crt, NULL);
+
+/* sm501fb_debug_show_pnl
+ *
+ * show the panel control and cursor registers
+*/
+
+static ssize_t sm501fb_debug_show_pnl(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct sm501fb_info *info = dev_get_drvdata(dev);
+	char *ptr = buf;
+
+	ptr += sm501fb_show_regs(info, ptr, 0x0, 0x40);
+	ptr += sm501fb_show_regs(info, ptr, SM501_DC_PANEL_HWC_BASE, 0x10);
+
+	return ptr - buf;
+}
+
+static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL);
+
+/* framebuffer ops */
+
+static struct fb_ops sm501fb_ops_crt = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= sm501fb_check_var_crt,
+	.fb_set_par	= sm501fb_set_par_crt,
+	.fb_blank	= sm501fb_blank_crt,
+	.fb_setcolreg	= sm501fb_setcolreg,
+	.fb_pan_display	= sm501fb_pan_crt,
+	.fb_cursor	= sm501fb_cursor,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static struct fb_ops sm501fb_ops_pnl = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= sm501fb_check_var_pnl,
+	.fb_set_par	= sm501fb_set_par_pnl,
+	.fb_pan_display	= sm501fb_pan_pnl,
+	.fb_blank	= sm501fb_blank_pnl,
+	.fb_setcolreg	= sm501fb_setcolreg,
+	.fb_cursor	= sm501fb_cursor,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+/* sm501fb_info_alloc
+ *
+ * creates and initialises an sm501fb_info structure
+*/
+
+static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
+					       struct fb_info *fbinfo_pnl)
+{
+	struct sm501fb_info *info;
+	struct sm501fb_par  *par;
+
+	info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
+	if (info) {
+		/* set the references back */
+
+		par = fbinfo_crt->par;
+		par->info = info;
+		par->head = HEAD_CRT;
+		fbinfo_crt->pseudo_palette = &par->pseudo_palette;
+
+		par = fbinfo_pnl->par;
+		par->info = info;
+		par->head = HEAD_PANEL;
+		fbinfo_pnl->pseudo_palette = &par->pseudo_palette;
+
+		/* store the two fbs into our info */
+		info->fb[HEAD_CRT] = fbinfo_crt;
+		info->fb[HEAD_PANEL] = fbinfo_pnl;
+	}
+
+	return info;
+}
+
+/* sm501_init_cursor
+ *
+ * initialise hw cursor parameters
+*/
+
+int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
+{
+	struct sm501fb_par *par = fbi->par;
+	struct sm501fb_info *info = par->info;
+	int ret;
+
+	par->cursor_regs = info->regs + reg_base;
+
+	ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024);
+	if (ret < 0)
+		return ret;
+
+	/* initialise the colour registers */
+
+	writel(par->cursor.sm_addr, par->cursor_regs + SM501_OFF_HWC_ADDR);
+
+	writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
+	writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
+	writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
+	sm501fb_sync_regs(info);
+
+	return 0;
+}
+
+/* sm501fb_info_start
+ *
+ * fills the par structure claiming resources and remapping etc.
+*/
+
+static int sm501fb_start(struct sm501fb_info *info,
+			 struct platform_device *pdev)
+{
+	struct resource	*res;
+	struct device *dev;
+	int ret;
+
+	info->dev = dev = &pdev->dev;
+	platform_set_drvdata(pdev, info);
+
+	info->irq = ret = platform_get_irq(pdev, 0);
+	if (ret < 0) {
+		/* we currently do not use the IRQ */
+		dev_warn(dev, "no irq for device\n");
+	}
+
+	/* allocate, reserve and remap resources for registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(dev, "no resource definition for registers\n");
+		ret = -ENOENT;
+		goto err_release;
+	}
+
+	info->regs_res = request_mem_region(res->start,
+					    res->end - res->start,
+					    pdev->name);
+
+	if (info->regs_res == NULL) {
+		dev_err(dev, "cannot claim registers\n");
+		ret = -ENXIO;
+		goto err_release;
+	}
+
+	info->regs = ioremap(res->start, (res->end - res->start)+1);
+	if (info->regs == NULL) {
+		dev_err(dev, "cannot remap registers\n");
+		ret = -ENXIO;
+		goto err_regs_res;
+	}
+
+	/* allocate, reserve resources for framebuffer */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (res == NULL) {
+		dev_err(dev, "no memory resource defined\n");
+		ret = -ENXIO;
+		goto err_regs_map;
+	}
+
+	info->fbmem_res = request_mem_region(res->start,
+					     (res->end - res->start)+1,
+					     pdev->name);
+	if (info->fbmem_res == NULL) {
+		dev_err(dev, "cannot claim framebuffer\n");
+		ret = -ENXIO;
+		goto err_regs_map;
+	}
+
+	info->fbmem = ioremap(res->start, (res->end - res->start)+1);
+	if (info->fbmem == NULL) {
+		dev_err(dev, "cannot remap framebuffer\n");
+		goto err_mem_res;
+	}
+
+	info->fbmem_len = (res->end - res->start)+1;
+
+	/* enable display controller */
+	sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
+
+	/* setup cursors */
+
+	sm501_init_cursor(info->fb[HEAD_CRT], SM501_DC_CRT_HWC_ADDR);
+	sm501_init_cursor(info->fb[HEAD_PANEL], SM501_DC_PANEL_HWC_ADDR);
+
+	return 0; /* everything is setup */
+
+ err_mem_res:
+	release_resource(info->fbmem_res);
+	kfree(info->fbmem_res);
+
+ err_regs_map:
+	iounmap(info->regs);
+
+ err_regs_res:
+	release_resource(info->regs_res);
+	kfree(info->regs_res);
+
+ err_release:
+	return ret;
+}
+
+static void sm501fb_stop(struct sm501fb_info *info)
+{
+	/* disable display controller */
+	sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0);
+
+	iounmap(info->fbmem);
+	release_resource(info->fbmem_res);
+	kfree(info->fbmem_res);
+
+	iounmap(info->regs);
+	release_resource(info->regs_res);
+	kfree(info->regs_res);
+}
+
+static void sm501fb_info_release(struct sm501fb_info *info)
+{
+	kfree(info);
+}
+
+static int sm501fb_init_fb(struct fb_info *fb,
+			   enum sm501_controller head,
+			   const char *fbname)
+{
+	struct sm501_platdata_fbsub *pd;
+	struct sm501fb_par *par = fb->par;
+	struct sm501fb_info *info = par->info;
+	unsigned long ctrl;
+	unsigned int enable;
+	int ret;
+
+	switch (head) {
+	case HEAD_CRT:
+		pd = info->pdata->fb_crt;
+		ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+		enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0;
+
+		/* ensure we set the correct source register */
+		if (info->pdata->fb_route != SM501_FB_CRT_PANEL) {
+			ctrl |= SM501_DC_CRT_CONTROL_SEL;
+			writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+		}
+
+		break;
+
+	case HEAD_PANEL:
+		pd = info->pdata->fb_pnl;
+		ctrl = readl(info->regs + SM501_DC_PANEL_CONTROL);
+		enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0;
+		break;
+
+	default:
+		pd = NULL;		/* stop compiler warnings */
+		ctrl = 0;
+		enable = 0;
+		BUG();
+	}
+
+	dev_info(info->dev, "fb %s %sabled at start\n",
+		 fbname, enable ? "en" : "dis");
+
+	/* check to see if our routing allows this */
+
+	if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) {
+		ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
+		writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+		enable = 0;
+	}
+
+	strlcpy(fb->fix.id, fbname, sizeof(fb->fix.id));
+
+	memcpy(&par->ops,
+	       (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl,
+	       sizeof(struct fb_ops));
+
+	/* update ops dependant on what we've been passed */
+
+	if ((pd->flags & SM501FB_FLAG_USE_HWCURSOR) == 0)
+		par->ops.fb_cursor = NULL;
+
+	fb->fbops = &par->ops;
+	fb->flags = FBINFO_FLAG_DEFAULT |
+		FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
+
+	/* fixed data */
+
+	fb->fix.type		= FB_TYPE_PACKED_PIXELS;
+	fb->fix.type_aux	= 0;
+	fb->fix.xpanstep	= 1;
+	fb->fix.ypanstep	= 1;
+	fb->fix.ywrapstep	= 0;
+	fb->fix.accel		= FB_ACCEL_NONE;
+
+	/* screenmode */
+
+	fb->var.nonstd		= 0;
+	fb->var.activate	= FB_ACTIVATE_NOW;
+	fb->var.accel_flags	= 0;
+	fb->var.vmode		= FB_VMODE_NONINTERLACED;
+	fb->var.bits_per_pixel  = 16;
+
+	if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
+		/* TODO read the mode from the current display */
+
+	} else {
+		if (pd->def_mode) {
+			dev_info(info->dev, "using supplied mode\n");
+			fb_videomode_to_var(&fb->var, pd->def_mode);
+
+			fb->var.bits_per_pixel = pd->def_bpp ? pd->def_bpp : 8;
+			fb->var.xres_virtual = fb->var.xres;
+			fb->var.yres_virtual = fb->var.yres;
+		} else {
+			ret = fb_find_mode(&fb->var, fb,
+					   NULL, NULL, 0, NULL, 8);
+
+			if (ret == 0 || ret == 4) {
+				dev_err(info->dev,
+					"failed to get initial mode\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	/* initialise and set the palette */
+	fb_alloc_cmap(&fb->cmap, NR_PALETTE, 0);
+	fb_set_cmap(&fb->cmap, fb);
+
+	ret = (fb->fbops->fb_check_var)(&fb->var, fb);
+	if (ret)
+		dev_err(info->dev, "check_var() failed on initial setup?\n");
+
+	/* ensure we've activated our new configuration */
+	(fb->fbops->fb_set_par)(fb);
+
+	return 0;
+}
+
+/* default platform data if none is supplied (ie, PCI device) */
+
+static struct sm501_platdata_fbsub sm501fb_pdata_crt = {
+	.flags		= (SM501FB_FLAG_USE_INIT_MODE |
+			   SM501FB_FLAG_USE_HWCURSOR |
+			   SM501FB_FLAG_USE_HWACCEL |
+			   SM501FB_FLAG_DISABLE_AT_EXIT),
+
+};
+
+static struct sm501_platdata_fbsub sm501fb_pdata_pnl = {
+	.flags		= (SM501FB_FLAG_USE_INIT_MODE |
+			   SM501FB_FLAG_USE_HWCURSOR |
+			   SM501FB_FLAG_USE_HWACCEL |
+			   SM501FB_FLAG_DISABLE_AT_EXIT),
+};
+
+static struct sm501_platdata_fb sm501fb_def_pdata = {
+	.fb_route		= SM501_FB_OWN,
+	.fb_crt			= &sm501fb_pdata_crt,
+	.fb_pnl			= &sm501fb_pdata_pnl,
+};
+
+static char driver_name_crt[] = "sm501fb-crt";
+static char driver_name_pnl[] = "sm501fb-panel";
+
+static int __init sm501fb_probe(struct platform_device *pdev)
+{
+	struct sm501fb_info *info;
+	struct device	    *dev = &pdev->dev;
+	struct fb_info	    *fbinfo_crt;
+	struct fb_info	    *fbinfo_pnl;
+	int		     ret;
+
+	/* allocate our framebuffers */
+
+	fbinfo_crt = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
+	if (fbinfo_crt == NULL) {
+		dev_err(dev, "cannot allocate crt framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fbinfo_pnl = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
+	if (fbinfo_pnl == NULL) {
+		dev_err(dev, "cannot allocate panel framebuffer\n");
+		ret = -ENOMEM;
+		goto fbinfo_crt_alloc_fail;
+	}
+
+	info = sm501fb_info_alloc(fbinfo_crt, fbinfo_pnl);
+	if (info == NULL) {
+		dev_err(dev, "cannot allocate par\n");
+		ret = -ENOMEM;
+		goto sm501fb_alloc_fail;
+	}
+
+	if (dev->parent->platform_data) {
+		struct sm501_platdata *pd = dev->parent->platform_data;
+		info->pdata = pd->fb;
+	}
+
+	if (info->pdata == NULL) {
+		dev_info(dev, "using default configuration data\n");
+		info->pdata = &sm501fb_def_pdata;
+	}
+
+	/* start the framebuffers */
+
+	ret = sm501fb_start(info, pdev);
+	if (ret) {
+		dev_err(dev, "cannot initialise SM501\n");
+		goto sm501fb_start_fail;
+	}
+
+	/* CRT framebuffer setup */
+
+	ret = sm501fb_init_fb(fbinfo_crt, HEAD_CRT, driver_name_crt);
+	if (ret) {
+		dev_err(dev, "cannot initialise CRT fb\n");
+		goto sm501fb_start_fail;
+	}
+
+	/* Panel framebuffer setup */
+
+	ret = sm501fb_init_fb(fbinfo_pnl, HEAD_PANEL, driver_name_pnl);
+	if (ret) {
+		dev_err(dev, "cannot initialise Panel fb\n");
+		goto sm501fb_start_fail;
+	}
+
+	/* register framebuffers */
+
+	ret = register_framebuffer(fbinfo_crt);
+	if (ret < 0) {
+		dev_err(dev, "failed to register CRT fb (%d)\n", ret);
+		goto register_crt_fail;
+	}
+
+	ret = register_framebuffer(fbinfo_pnl);
+	if (ret < 0) {
+		dev_err(dev, "failed to register panel fb (%d)\n", ret);
+		goto register_pnl_fail;
+	}
+
+	dev_info(dev, "fb%d: %s frame buffer device\n",
+		 fbinfo_crt->node, fbinfo_crt->fix.id);
+
+	dev_info(dev, "fb%d: %s frame buffer device\n",
+	       fbinfo_pnl->node, fbinfo_pnl->fix.id);
+
+	/* create device files */
+
+	ret = device_create_file(dev, &dev_attr_crt_src);
+	if (ret)
+		goto crtsrc_fail;
+
+	ret = device_create_file(dev, &dev_attr_fbregs_pnl);
+	if (ret)
+		goto fbregs_pnl_fail;
+
+	ret = device_create_file(dev, &dev_attr_fbregs_crt);
+	if (ret)
+		goto fbregs_crt_fail;
+
+	/* we registered, return ok */
+	return 0;
+
+ fbregs_crt_fail:
+	device_remove_file(dev, &dev_attr_fbregs_pnl);
+
+ fbregs_pnl_fail:
+	device_remove_file(dev, &dev_attr_crt_src);
+
+ crtsrc_fail:
+	unregister_framebuffer(fbinfo_pnl);
+
+ register_pnl_fail:
+	unregister_framebuffer(fbinfo_crt);
+
+ register_crt_fail:
+	sm501fb_stop(info);
+
+ sm501fb_start_fail:
+	sm501fb_info_release(info);
+
+ sm501fb_alloc_fail:
+	framebuffer_release(fbinfo_pnl);
+
+ fbinfo_crt_alloc_fail:
+	framebuffer_release(fbinfo_crt);
+
+	return ret;
+}
+
+
+/*
+ *  Cleanup
+ */
+static int sm501fb_remove(struct platform_device *pdev)
+{
+	struct sm501fb_info *info = platform_get_drvdata(pdev);
+	struct fb_info	   *fbinfo_crt = info->fb[0];
+	struct fb_info	   *fbinfo_pnl = info->fb[1];
+
+	device_remove_file(&pdev->dev, &dev_attr_fbregs_crt);
+	device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl);
+	device_remove_file(&pdev->dev, &dev_attr_crt_src);
+
+	unregister_framebuffer(fbinfo_crt);
+	unregister_framebuffer(fbinfo_pnl);
+
+	sm501fb_stop(info);
+	sm501fb_info_release(info);
+
+	framebuffer_release(fbinfo_pnl);
+	framebuffer_release(fbinfo_crt);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int sm501fb_suspend_fb(struct sm501fb_info *info,
+			      enum sm501_controller head)
+{
+	struct fb_info *fbi = info->fb[head];
+	struct sm501fb_par *par = fbi->par;
+
+	if (par->screen.size == 0)
+		return 0;
+
+	/* backup copies in case chip is powered down over suspend */
+
+	par->store_fb = vmalloc(par->screen.size);
+	if (par->store_fb == NULL) {
+		dev_err(info->dev, "no memory to store screen\n");
+		return -ENOMEM;
+	}
+
+	par->store_cursor = vmalloc(par->cursor.size);
+	if (par->store_cursor == NULL) {
+		dev_err(info->dev, "no memory to store cursor\n");
+		goto err_nocursor;
+	}
+
+	memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size);
+	memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size);
+
+	/* blank the relevant interface to ensure unit power minimised */
+	(par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi);
+
+	return 0;
+
+ err_nocursor:
+	vfree(par->store_fb);
+
+	return -ENOMEM;
+
+}
+
+static void sm501fb_resume_fb(struct sm501fb_info *info,
+			      enum sm501_controller head)
+{
+	struct fb_info *fbi = info->fb[head];
+	struct sm501fb_par *par = fbi->par;
+
+	if (par->screen.size == 0)
+		return;
+
+	/* re-activate the configuration */
+
+	(par->ops.fb_set_par)(fbi);
+
+	/* restore the data */
+
+	memcpy_toio(par->screen.k_addr, par->store_fb, par->screen.size);
+	memcpy_toio(par->cursor.k_addr, par->store_cursor, par->cursor.size);
+
+	vfree(par->store_fb);
+	vfree(par->store_cursor);
+}
+
+
+/* suspend and resume support */
+
+static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct sm501fb_info *info = platform_get_drvdata(pdev);
+
+	sm501fb_suspend_fb(info, HEAD_CRT);
+	sm501fb_suspend_fb(info, HEAD_PANEL);
+
+	/* turn off the clocks, in case the device is not powered down */
+	sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0);
+
+	return 0;
+}
+
+static int sm501fb_resume(struct platform_device *pdev)
+{
+	struct sm501fb_info *info = platform_get_drvdata(pdev);
+
+	sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 1);
+
+	sm501fb_resume_fb(info, HEAD_CRT);
+	sm501fb_resume_fb(info, HEAD_PANEL);
+
+	return 0;
+}
+
+#else
+#define sm501fb_suspend NULL
+#define sm501fb_resume  NULL
+#endif
+
+static struct platform_driver sm501fb_driver = {
+	.probe		= sm501fb_probe,
+	.remove		= sm501fb_remove,
+	.suspend	= sm501fb_suspend,
+	.resume		= sm501fb_resume,
+	.driver		= {
+		.name	= "sm501-fb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+int __devinit sm501fb_init(void)
+{
+	return platform_driver_register(&sm501fb_driver);
+}
+
+static void __exit sm501fb_cleanup(void)
+{
+	platform_driver_unregister(&sm501fb_driver);
+}
+
+module_init(sm501fb_init);
+module_exit(sm501fb_cleanup);
+
+MODULE_AUTHOR("Ben Dooks, Vincent Sanders");
+MODULE_DESCRIPTION("SM501 Framebuffer driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sun3fb.c b/drivers/video/sun3fb.c
deleted file mode 100644
index f80356d..0000000
--- a/drivers/video/sun3fb.c
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- *  linux/drivers/video/sun3fb.c -- Frame buffer driver for Sun3
- *
- * (C) 1998 Thomas Bogendoerfer
- *
- * This driver is bases on sbusfb.c, which is
- *
- *	Copyright (C) 1998 Jakub Jelinek
- *
- *  This driver is partly based on the Open Firmware console driver
- *
- *	Copyright (C) 1997 Geert Uytterhoeven
- *
- *  and SPARC console subsystem
- *
- *      Copyright (C) 1995 Peter Zaitcev (zaitcev@yahoo.com)
- *      Copyright (C) 1995-1997 David S. Miller (davem@caip.rutgers.edu)
- *      Copyright (C) 1995-1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
- *      Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
- *      Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *      Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/selection.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>	/* io_remap_page_range() */
-
-#ifdef CONFIG_SUN3
-#include <asm/oplib.h>
-#include <asm/machines.h>
-#include <asm/idprom.h>
-
-#define CGFOUR_OBMEM_ADDR 0x1f300000
-#define BWTWO_OBMEM_ADDR 0x1f000000
-#define BWTWO_OBMEM50_ADDR 0x00100000
-
-#endif
-#ifdef CONFIG_SUN3X
-#include <asm/sun3x.h>
-#endif
-#include <video/sbusfb.h>
-
-#define DEFAULT_CURSOR_BLINK_RATE       (2*HZ/5)
-
-#define CURSOR_SHAPE			1
-#define CURSOR_BLINK			2
-
-#define mymemset(x,y) memset(x,0,y)
-
-    /*
-     *  Interface used by the world
-     */
-
-int sun3fb_init(void);
-void sun3fb_setup(char *options);
-
-static char fontname[40] __initdata = { 0 };
-static int curblink __initdata = 1;
-
-static int sun3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			struct fb_info *info);
-static int sun3fb_get_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info);
-static int sun3fb_set_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info);
-static int sun3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			struct fb_info *info);
-static int sun3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			struct fb_info *info);
-static int sun3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			    u_int transp, struct fb_info *info);
-static int sun3fb_blank(int blank, struct fb_info *info);
-static void sun3fb_cursor(struct display *p, int mode, int x, int y);
-static void sun3fb_clear_margin(struct display *p, int s);
-
-    /*
-     *  Interface to the low level console driver
-     */
-
-static int sun3fbcon_switch(int con, struct fb_info *info);
-static int sun3fbcon_updatevar(int con, struct fb_info *info);
-
-    /*
-     *  Internal routines
-     */
-
-static int sun3fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			    u_int *transp, struct fb_info *info);
-
-static struct fb_ops sun3fb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	sun3fb_get_fix,
-	.fb_get_var =	sun3fb_get_var,
-	.fb_set_var =	sun3fb_set_var,
-	.fb_get_cmap =	sun3fb_get_cmap,
-	.fb_set_cmap =	sun3fb_set_cmap,
-	.fb_setcolreg =	sun3fb_setcolreg,
-	.fb_blank =	sun3fb_blank,
-};
-
-static void sun3fb_clear_margin(struct display *p, int s)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-	
-	return;
-
-	if (fb->switch_from_graph)
-		(*fb->switch_from_graph)(fb);
-	if (fb->fill) {
-		unsigned short rects [16];
-
-		rects [0] = 0;
-		rects [1] = 0;
-		rects [2] = fb->var.xres_virtual;
-		rects [3] = fb->y_margin;
-		rects [4] = 0;
-		rects [5] = fb->y_margin;
-		rects [6] = fb->x_margin;
-		rects [7] = fb->var.yres_virtual;
-		rects [8] = fb->var.xres_virtual - fb->x_margin;
-		rects [9] = fb->y_margin;
-		rects [10] = fb->var.xres_virtual;
-		rects [11] = fb->var.yres_virtual;
-		rects [12] = fb->x_margin;
-		rects [13] = fb->var.yres_virtual - fb->y_margin;
-		rects [14] = fb->var.xres_virtual - fb->x_margin;
-		rects [15] = fb->var.yres_virtual;
-		(*fb->fill)(fb, p, s, 4, rects);
-	} else {
-		unsigned char *fb_base = fb->info.screen_base, *q;
-		int skip_bytes = fb->y_margin * fb->var.xres_virtual;
-		int scr_size = fb->var.xres_virtual * fb->var.yres_virtual;
-		int h, he, incr, size;
-
-		he = fb->var.yres;
-		if (fb->var.bits_per_pixel == 1) {
-			fb_base -= (skip_bytes + fb->x_margin) / 8;
-			skip_bytes /= 8;
-			scr_size /= 8;
-			mymemset (fb_base, skip_bytes - fb->x_margin / 8);
-			mymemset (fb_base + scr_size - skip_bytes + fb->x_margin / 8, skip_bytes - fb->x_margin / 8);
-			incr = fb->var.xres_virtual / 8;
-			size = fb->x_margin / 8 * 2;
-			for (q = fb_base + skip_bytes - fb->x_margin / 8, h = 0;
-			     h <= he; q += incr, h++)
-				mymemset (q, size);
-		} else {
-			fb_base -= (skip_bytes + fb->x_margin);
-			memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin);
-			memset (fb_base + scr_size - skip_bytes + fb->x_margin, attr_bgcol(p,s), skip_bytes - fb->x_margin);
-			incr = fb->var.xres_virtual;
-			size = fb->x_margin * 2;
-			for (q = fb_base + skip_bytes - fb->x_margin, h = 0;
-			     h <= he; q += incr, h++)
-				memset (q, attr_bgcol(p,s), size);
-		}
-	}
-}
-
-static void sun3fb_disp_setup(struct display *p)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-
-	if (fb->setup)
-		fb->setup(p);	
-	sun3fb_clear_margin(p, 0);
-}
-
-    /*
-     *  Get the Fixed Part of the Display
-     */
-
-static int sun3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			  struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo));
-	return 0;
-}
-
-    /*
-     *  Get the User Defined Part of the Display
-     */
-
-static int sun3fb_get_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
-	return 0;
-}
-
-    /*
-     *  Set the User Defined Part of the Display
-     */
-
-static int sun3fb_set_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	if (var->xres > fb->var.xres || var->yres > fb->var.yres ||
-	    var->xres_virtual > fb->var.xres_virtual ||
-	    var->yres_virtual > fb->var.yres_virtual ||
-	    var->bits_per_pixel != fb->var.bits_per_pixel ||
-	    var->nonstd ||
-	    (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-	memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
-	return 0;
-}
-
-    /*
-     *  Hardware cursor
-     */
-     
-static unsigned char hw_cursor_cmap[2] = { 0, 0xff };
-
-static void
-sun3fb_cursor_timer_handler(unsigned long dev_addr)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)dev_addr;
-        
-	if (!fb->setcursor) return;
-                                
-	if (fb->cursor.mode & CURSOR_BLINK) {
-		fb->cursor.enable ^= 1;
-		fb->setcursor(fb);
-	}
-	
-	fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
-	add_timer(&fb->cursor.timer);
-}
-
-static void sun3fb_cursor(struct display *p, int mode, int x, int y)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-	
-	switch (mode) {
-	case CM_ERASE:
-		fb->cursor.mode &= ~CURSOR_BLINK;
-		fb->cursor.enable = 0;
-		(*fb->setcursor)(fb);
-		break;
-				  
-	case CM_MOVE:
-	case CM_DRAW:
-		if (fb->cursor.mode & CURSOR_SHAPE) {
-			fb->cursor.size.fbx = fontwidth(p);
-			fb->cursor.size.fby = fontheight(p);
-			fb->cursor.chot.fbx = 0;
-			fb->cursor.chot.fby = 0;
-			fb->cursor.enable = 1;
-			memset (fb->cursor.bits, 0, sizeof (fb->cursor.bits));
-			fb->cursor.bits[0][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
-			fb->cursor.bits[1][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
-			fb->cursor.bits[0][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
-			fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
-			(*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap);
-			(*fb->setcurshape) (fb);
-		}
-		fb->cursor.mode = CURSOR_BLINK;
-		if (fontwidthlog(p))
-			fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + fb->x_margin;
-		else
-			fb->cursor.cpos.fbx = (x * fontwidth(p)) + fb->x_margin;
-		if (fontheightlog(p))
-			fb->cursor.cpos.fby = (y << fontheightlog(p)) + fb->y_margin;
-		else
-			fb->cursor.cpos.fby = (y * fontheight(p)) + fb->y_margin;
-		(*fb->setcursor)(fb);
-		break;
-	}
-}
-
-    /*
-     *  Get the Colormap
-     */
-
-static int sun3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			 struct fb_info *info)
-{
-	if (con == info->currcon) /* current console? */
-		return fb_get_cmap(cmap, kspc, sun3fb_getcolreg, info);
-	else if (fb_display[con].cmap.len) /* non default colormap? */
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	else
-		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2);
-	return 0;
-}
-
-    /*
-     *  Set the Colormap
-     */
-
-static int sun3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			 struct fb_info *info)
-{
-	int err;
-
-	if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
-		if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<<fb_display[con].var.bits_per_pixel, 0)))
-			return err;
-	}
-	if (con == info->currcon) {			/* current console? */
-		err = fb_set_cmap(cmap, kspc, info);
-		if (!err) {
-			struct fb_info_sbusfb *fb = sbusfbinfo(info);
-			
-			if (fb->loadcmap)
-				(*fb->loadcmap)(fb, &fb_display[con], cmap->start, cmap->len);
-		}
-		return err;
-	} else
-		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-	return 0;
-}
-
-    /*
-     *  Setup: parse used options
-     */
-
-void __init sun3fb_setup(char *options)
-{
-	char *p;
-	
-	for (p = options;;) {
-		if (!strncmp(p, "font=", 5)) {
-			int i;
-			
-			for (i = 0; i < sizeof(fontname) - 1; i++)
-				if (p[i+5] == ' ' || !p[i+5])
-					break;
-			memcpy(fontname, p+5, i);
-			fontname[i] = 0;
-		} else if (!strncmp(p, "noblink", 7))
-			curblink = 0;
-		while (*p && *p != ' ' && *p != ',') p++;
-		if (*p != ',') break;
-		p++;
-	}
-
-	return;
-}
-
-static int sun3fbcon_switch(int con, struct fb_info *info)
-{
-	int x_margin, y_margin;
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-	int lastconsole;
-    
-	/* Do we have to save the colormap? */
-	if (fb_display[info->currcon].cmap.len)
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1, sun3fb_getcolreg, info);
-
-	if (info->display_fg) {
-		lastconsole = info->display_fg->vc_num;
-		if (lastconsole != con && 
-		    (fontwidth(&fb_display[lastconsole]) != fontwidth(&fb_display[con]) ||
-		     fontheight(&fb_display[lastconsole]) != fontheight(&fb_display[con])))
-			fb->cursor.mode |= CURSOR_SHAPE;
-	}
-	x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2;
-	y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2;
-	if (fb->margins)
-		fb->margins(fb, &fb_display[con], x_margin, y_margin);
-	if (fb->graphmode || fb->x_margin != x_margin || fb->y_margin != y_margin) {
-		fb->x_margin = x_margin; fb->y_margin = y_margin;
-		sun3fb_clear_margin(&fb_display[con], 0);
-	}
-	info->currcon = con;
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	return 0;
-}
-
-    /*
-     *  Update the `var' structure (called by fbcon.c)
-     */
-
-static int sun3fbcon_updatevar(int con, struct fb_info *info)
-{
-	/* Nothing */
-	return 0;
-}
-
-    /*
-     *  Blank the display.
-     */
-
-static int sun3fb_blank(int blank, struct fb_info *info)
-{
-    struct fb_info_sbusfb *fb = sbusfbinfo(info);
-    
-    if (blank && fb->blank)
-    	return fb->blank(fb);
-    else if (!blank && fb->unblank)
-    	return fb->unblank(fb);
-    return 0;
-}
-
-    /*
-     *  Read a single color register and split it into
-     *  colors/transparent. Return != 0 for invalid regno.
-     */
-
-static int sun3fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			  u_int *transp, struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	if (!fb->color_map || regno > 255)
-		return 1;
-	*red = (fb->color_map CM(regno, 0)<<8) | fb->color_map CM(regno, 0);
-	*green = (fb->color_map CM(regno, 1)<<8) | fb->color_map CM(regno, 1);
-	*blue = (fb->color_map CM(regno, 2)<<8) | fb->color_map CM(regno, 2);
-	*transp = 0;
-	return 0;
-}
-
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-
-static int sun3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			    u_int transp, struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	if (!fb->color_map || regno > 255)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	fb->color_map CM(regno, 0) = red;
-	fb->color_map CM(regno, 1) = green;
-	fb->color_map CM(regno, 2) = blue;
-	return 0;
-}
-
-static int sun3fb_set_font(struct display *p, int width, int height)
-{
-	int w = p->var.xres_virtual, h = p->var.yres_virtual;
-	int depth = p->var.bits_per_pixel;
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-	int x_margin, y_margin;
-	
-	if (depth > 8) depth = 8;
-	x_margin = (w % width) / 2;
-	y_margin = (h % height) / 2;
-
-	p->var.xres = w - 2*x_margin;
-	p->var.yres = h - 2*y_margin;
-	
-	fb->cursor.mode |= CURSOR_SHAPE;
-	
-	if (fb->margins)
-		fb->margins(fb, p, x_margin, y_margin);
-	if (fb->x_margin != x_margin || fb->y_margin != y_margin) {
-		fb->x_margin = x_margin; fb->y_margin = y_margin;
-		sun3fb_clear_margin(p, 0);
-	}
-
-	return 1;
-}
-
-void sun3fb_palette(int enter)
-{
-	int i;
-	struct display *p;
-	
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
-		p = &fb_display[i];
-		if (p->dispsw && p->dispsw->setup == sun3fb_disp_setup &&
-		    p->fb_info->display_fg &&
-		    p->fb_info->display_fg->vc_num == i) {
-			struct fb_info_sbusfb *fb = sbusfbinfod(p);
-
-			if (fb->restore_palette) {
-				if (enter)
-					fb->restore_palette(fb);
-				else if (vc_cons[i].d->vc_mode != KD_GRAPHICS)
-				         vc_cons[i].d->vc_sw->con_set_palette(vc_cons[i].d, color_table);
-			}
-		}
-	}
-}
-
-    /*
-     *  Initialisation
-     */
-static int __init sun3fb_init_fb(int fbtype, unsigned long addr)
-{
-	static struct sbus_dev sdb;
-	struct fb_fix_screeninfo *fix;
-	struct fb_var_screeninfo *var;
-	struct display *disp;
-	struct fb_info_sbusfb *fb;
-	struct fbtype *type;
-	int linebytes, w, h, depth;
-	char *p = NULL;
-	
-	fb = kmalloc(sizeof(struct fb_info_sbusfb), GFP_ATOMIC);
-	if (!fb)
-		return -ENOMEM;
-	
-	memset(fb, 0, sizeof(struct fb_info_sbusfb));
-	fix = &fb->fix;
-	var = &fb->var;
-	disp = &fb->disp;
-	type = &fb->type;
-	
-	sdb.reg_addrs[0].phys_addr = addr;
-	fb->sbdp = &sdb;
-
-	type->fb_type = fbtype;
-	
-	type->fb_height = h = 900;
-	type->fb_width  = w = 1152;
-sizechange:
-	type->fb_depth  = depth = (fbtype == FBTYPE_SUN2BW) ? 1 : 8;
-	linebytes = w * depth / 8;
-	type->fb_size   = PAGE_ALIGN((linebytes) * h);
-/*	
-	fb->x_margin = (w & 7) / 2;
-	fb->y_margin = (h & 15) / 2;
-*/
-	fb->x_margin = fb->y_margin = 0;
-
-	var->xres_virtual = w;
-	var->yres_virtual = h;
-	var->xres = w - 2*fb->x_margin;
-	var->yres = h - 2*fb->y_margin;
-	
-	var->bits_per_pixel = depth;
-	var->height = var->width = -1;
-	var->pixclock = 10000;
-	var->vmode = FB_VMODE_NONINTERLACED;
-	var->red.length = var->green.length = var->blue.length = 8;
-
-	fix->line_length = linebytes;
-	fix->smem_len = type->fb_size;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	
-	fb->info.fbops = &sun3fb_ops;
-	fb->info.disp = disp;
-	fb->info.currcon = -1;
-	strcpy(fb->info.fontname, fontname);
-	fb->info.changevar = NULL;
-	fb->info.switch_con = &sun3fbcon_switch;
-	fb->info.updatevar = &sun3fbcon_updatevar;
-	fb->info.flags = FBINFO_FLAG_DEFAULT;
-	
-	fb->cursor.hwsize.fbx = 32;
-	fb->cursor.hwsize.fby = 32;
-	
-	if (depth > 1 && !fb->color_map) {
-		if((fb->color_map = kmalloc(256 * 3, GFP_ATOMIC))==NULL)
-			return -ENOMEM;
-	}
-			
-	switch(fbtype) {
-#ifdef CONFIG_FB_CGSIX
-	case FBTYPE_SUNFAST_COLOR:
-		p = cgsixfb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_BWTWO
-	case FBTYPE_SUN2BW:
-		p = bwtwofb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_CGTHREE
-	case FBTYPE_SUN4COLOR:
-	case FBTYPE_SUN3COLOR:
-		type->fb_size = 0x100000;
-		p = cgthreefb_init(fb); break;
-#endif
-	}
-	fix->smem_start = (unsigned long)fb->info.screen_base;	// FIXME
-	
-	if (!p) {
-		kfree(fb);
-		return -ENODEV;
-	}
-	
-	if (p == SBUSFBINIT_SIZECHANGE)
-		goto sizechange;
-
-	disp->dispsw = &fb->dispsw;
-	if (fb->setcursor) {
-		fb->dispsw.cursor = sun3fb_cursor;
-		if (curblink) {
-			fb->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
-			init_timer(&fb->cursor.timer);
-			fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
-			fb->cursor.timer.data = (unsigned long)fb;
-			fb->cursor.timer.function = sun3fb_cursor_timer_handler;
-			add_timer(&fb->cursor.timer);
-		}
-	}
-	fb->cursor.mode = CURSOR_SHAPE;
-	fb->dispsw.set_font = sun3fb_set_font;
-	fb->setup = fb->dispsw.setup;
-	fb->dispsw.setup = sun3fb_disp_setup;
-	fb->dispsw.clear_margins = NULL;
-
-	disp->var = *var;
-	disp->visual = fix->visual;
-	disp->type = fix->type;
-	disp->type_aux = fix->type_aux;
-	disp->line_length = fix->line_length;
-	
-	if (fb->blank)
-		disp->can_soft_blank = 1;
-
-	sun3fb_set_var(var, -1, &fb->info);
-
-	if (register_framebuffer(&fb->info) < 0) {
-		kfree(fb);
-		return -EINVAL;
-	}
-	printk("fb%d: %s\n", fb->info.node, p);
-
-	return 0;
-}
-
-
-int __init sun3fb_init(void)
-{
-	extern int con_is_present(void);
-	unsigned long addr;
-	char p4id;
-	
-	if (!con_is_present()) return -ENODEV;
-#ifdef CONFIG_SUN3
-        switch(*(romvec->pv_fbtype))
-        {
-	case FBTYPE_SUN2BW:
-		addr = 0xfe20000;
-		return sun3fb_init_fb(FBTYPE_SUN2BW, addr);
-	case FBTYPE_SUN3COLOR:
-	case FBTYPE_SUN4COLOR:
-		if(idprom->id_machtype != (SM_SUN3|SM_3_60)) {
-			printk("sun3fb: cgthree/four only supported on 3/60\n");
-			return -ENODEV;
-		}
-		
-		addr = CGFOUR_OBMEM_ADDR;
-		return sun3fb_init_fb(*(romvec->pv_fbtype), addr);
-	default:
-		printk("sun3fb: unsupported framebuffer\n");
-		return -ENODEV;
-	}
-#else
-	addr = SUN3X_VIDEO_BASE;
-	p4id = *(char *)SUN3X_VIDEO_P4ID;
-
-	p4id = (p4id == 0x45) ? p4id : (p4id & 0xf0);
-	switch (p4id) {
-		case 0x00:
-			return sun3fb_init_fb(FBTYPE_SUN2BW, addr);
-#if 0 /* not yet */
-		case 0x40:
-			return sun3fb_init_fb(FBTYPE_SUN4COLOR, addr);
-			break;
-		case 0x45:
-			return sun3fb_init_fb(FBTYPE_SUN8COLOR, addr);
-			break;
-#endif
-		case 0x60:
-			return sun3fb_init_fb(FBTYPE_SUNFAST_COLOR, addr);
-	}
-#endif			
-	
-	return -ENODEV;
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/svgalib.c b/drivers/video/svgalib.c
new file mode 100644
index 0000000..68b30d9
--- /dev/null
+++ b/drivers/video/svgalib.c
@@ -0,0 +1,632 @@
+/*
+ * Common utility functions for VGA-based graphics cards.
+ *
+ * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ * 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.
+ *
+ * Some parts are based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/svga.h>
+#include <linux/slab.h>
+#include <asm/types.h>
+#include <asm/io.h>
+
+
+/* Write a CRT register value spread across multiple registers */
+void svga_wcrt_multi(const struct vga_regset *regset, u32 value) {
+
+	u8 regval, bitval, bitnum;
+
+	while (regset->regnum != VGA_REGSET_END_VAL) {
+		regval = vga_rcrt(NULL, regset->regnum);
+		bitnum = regset->lowbit;
+		while (bitnum <= regset->highbit) {
+			bitval = 1 << bitnum;
+			regval = regval & ~bitval;
+			if (value & 1) regval = regval | bitval;
+			bitnum ++;
+			value = value >> 1;
+		}
+		vga_wcrt(NULL, regset->regnum, regval);
+		regset ++;
+	}
+}
+
+/* Write a sequencer register value spread across multiple registers */
+void svga_wseq_multi(const struct vga_regset *regset, u32 value) {
+
+	u8 regval, bitval, bitnum;
+
+	while (regset->regnum != VGA_REGSET_END_VAL) {
+		regval = vga_rseq(NULL, regset->regnum);
+		bitnum = regset->lowbit;
+		while (bitnum <= regset->highbit) {
+			bitval = 1 << bitnum;
+			regval = regval & ~bitval;
+			if (value & 1) regval = regval | bitval;
+			bitnum ++;
+			value = value >> 1;
+		}
+		vga_wseq(NULL, regset->regnum, regval);
+		regset ++;
+	}
+}
+
+static unsigned int svga_regset_size(const struct vga_regset *regset)
+{
+	u8 count = 0;
+
+	while (regset->regnum != VGA_REGSET_END_VAL) {
+		count += regset->highbit - regset->lowbit + 1;
+		regset ++;
+	}
+	return 1 << count;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Set graphics controller registers to sane values */
+void svga_set_default_gfx_regs(void)
+{
+	/* All standard GFX registers (GR00 - GR08) */
+	vga_wgfx(NULL, VGA_GFX_SR_VALUE, 0x00);
+	vga_wgfx(NULL, VGA_GFX_SR_ENABLE, 0x00);
+	vga_wgfx(NULL, VGA_GFX_COMPARE_VALUE, 0x00);
+	vga_wgfx(NULL, VGA_GFX_DATA_ROTATE, 0x00);
+	vga_wgfx(NULL, VGA_GFX_PLANE_READ, 0x00);
+	vga_wgfx(NULL, VGA_GFX_MODE, 0x00);
+/*	vga_wgfx(NULL, VGA_GFX_MODE, 0x20); */
+/*	vga_wgfx(NULL, VGA_GFX_MODE, 0x40); */
+	vga_wgfx(NULL, VGA_GFX_MISC, 0x05);
+/*	vga_wgfx(NULL, VGA_GFX_MISC, 0x01); */
+	vga_wgfx(NULL, VGA_GFX_COMPARE_MASK, 0x0F);
+	vga_wgfx(NULL, VGA_GFX_BIT_MASK, 0xFF);
+}
+
+/* Set attribute controller registers to sane values */
+void svga_set_default_atc_regs(void)
+{
+	u8 count;
+
+	vga_r(NULL, 0x3DA);
+	vga_w(NULL, VGA_ATT_W, 0x00);
+
+	/* All standard ATC registers (AR00 - AR14) */
+	for (count = 0; count <= 0xF; count ++)
+		svga_wattr(count, count);
+
+	svga_wattr(VGA_ATC_MODE, 0x01);
+/*	svga_wattr(VGA_ATC_MODE, 0x41); */
+	svga_wattr(VGA_ATC_OVERSCAN, 0x00);
+	svga_wattr(VGA_ATC_PLANE_ENABLE, 0x0F);
+	svga_wattr(VGA_ATC_PEL, 0x00);
+	svga_wattr(VGA_ATC_COLOR_PAGE, 0x00);
+
+	vga_r(NULL, 0x3DA);
+	vga_w(NULL, VGA_ATT_W, 0x20);
+}
+
+/* Set sequencer registers to sane values */
+void svga_set_default_seq_regs(void)
+{
+	/* Standard sequencer registers (SR01 - SR04), SR00 is not set */
+	vga_wseq(NULL, VGA_SEQ_CLOCK_MODE, VGA_SR01_CHAR_CLK_8DOTS);
+	vga_wseq(NULL, VGA_SEQ_PLANE_WRITE, VGA_SR02_ALL_PLANES);
+	vga_wseq(NULL, VGA_SEQ_CHARACTER_MAP, 0x00);
+/*	vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE | VGA_SR04_CHN_4M); */
+	vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE);
+}
+
+/* Set CRTC registers to sane values */
+void svga_set_default_crt_regs(void)
+{
+	/* Standard CRT registers CR03 CR08 CR09 CR14 CR17 */
+	svga_wcrt_mask(0x03, 0x80, 0x80);	/* Enable vertical retrace EVRA */
+	vga_wcrt(NULL, VGA_CRTC_PRESET_ROW, 0);
+	svga_wcrt_mask(VGA_CRTC_MAX_SCAN, 0, 0x1F);
+	vga_wcrt(NULL, VGA_CRTC_UNDERLINE, 0);
+	vga_wcrt(NULL, VGA_CRTC_MODE, 0xE3);
+}
+
+void svga_set_textmode_vga_regs(void)
+{
+	/* svga_wseq_mask(0x1, 0x00, 0x01); */   /* Switch 8/9 pixel per char */
+	vga_wseq(NULL, VGA_SEQ_MEMORY_MODE,	VGA_SR04_EXT_MEM);
+	vga_wseq(NULL, VGA_SEQ_PLANE_WRITE,	0x03);
+
+	vga_wcrt(NULL, VGA_CRTC_MAX_SCAN,	0x0f); /* 0x4f */
+	vga_wcrt(NULL, VGA_CRTC_UNDERLINE,	0x1f);
+	svga_wcrt_mask(VGA_CRTC_MODE,		0x23, 0x7f);
+
+	vga_wcrt(NULL, VGA_CRTC_CURSOR_START,	0x0d);
+	vga_wcrt(NULL, VGA_CRTC_CURSOR_END,	0x0e);
+	vga_wcrt(NULL, VGA_CRTC_CURSOR_HI,	0x00);
+	vga_wcrt(NULL, VGA_CRTC_CURSOR_LO,	0x00);
+
+	vga_wgfx(NULL, VGA_GFX_MODE,		0x10); /* Odd/even memory mode */
+	vga_wgfx(NULL, VGA_GFX_MISC,		0x0E); /* Misc graphics register - text mode enable */
+	vga_wgfx(NULL, VGA_GFX_COMPARE_MASK,	0x00);
+
+	vga_r(NULL, 0x3DA);
+	vga_w(NULL, VGA_ATT_W, 0x00);
+
+	svga_wattr(0x10, 0x0C);			/* Attribute Mode Control Register - text mode, blinking and line graphics */
+	svga_wattr(0x13, 0x08);			/* Horizontal Pixel Panning Register  */
+
+	vga_r(NULL, 0x3DA);
+	vga_w(NULL, VGA_ATT_W, 0x20);
+}
+
+#if 0
+void svga_dump_var(struct fb_var_screeninfo *var, int node)
+{
+	pr_debug("fb%d: var.vmode         : 0x%X\n", node, var->vmode);
+	pr_debug("fb%d: var.xres          : %d\n", node, var->xres);
+	pr_debug("fb%d: var.yres          : %d\n", node, var->yres);
+	pr_debug("fb%d: var.bits_per_pixel: %d\n", node, var->bits_per_pixel);
+	pr_debug("fb%d: var.xres_virtual  : %d\n", node, var->xres_virtual);
+	pr_debug("fb%d: var.yres_virtual  : %d\n", node, var->yres_virtual);
+	pr_debug("fb%d: var.left_margin   : %d\n", node, var->left_margin);
+	pr_debug("fb%d: var.right_margin  : %d\n", node, var->right_margin);
+	pr_debug("fb%d: var.upper_margin  : %d\n", node, var->upper_margin);
+	pr_debug("fb%d: var.lower_margin  : %d\n", node, var->lower_margin);
+	pr_debug("fb%d: var.hsync_len     : %d\n", node, var->hsync_len);
+	pr_debug("fb%d: var.vsync_len     : %d\n", node, var->vsync_len);
+	pr_debug("fb%d: var.sync          : 0x%X\n", node, var->sync);
+	pr_debug("fb%d: var.pixclock      : %d\n\n", node, var->pixclock);
+}
+#endif  /*  0  */
+
+
+/* ------------------------------------------------------------------------- */
+
+
+void svga_settile(struct fb_info *info, struct fb_tilemap *map)
+{
+	const u8 *font = map->data;
+	u8* fb = (u8 *) info->screen_base;
+	int i, c;
+
+	if ((map->width != 8) || (map->height != 16) ||
+	    (map->depth != 1) || (map->length != 256)) {
+	    	printk(KERN_ERR "fb%d: unsupported font parameters: width %d, height %d, depth %d, length %d\n",
+			info->node, map->width, map->height, map->depth, map->length);
+		return;
+	}
+
+	fb += 2;
+	for (c = 0; c < map->length; c++) {
+		for (i = 0; i < map->height; i++) {
+			fb[i * 4] = font[i];
+		}
+		fb += 128;
+		font += map->height;
+	}
+}
+
+/* Copy area in text (tileblit) mode */
+void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area)
+{
+	int dx, dy;
+	/*  colstride is halved in this function because u16 are used */
+	int colstride = 1 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	u16 *fb = (u16 *) info->screen_base;
+	u16 *src, *dst;
+
+	if ((area->sy > area->dy) ||
+	    ((area->sy == area->dy) && (area->sx > area->dx))) {
+		src = fb + area->sx * colstride + area->sy * rowstride;
+		dst = fb + area->dx * colstride + area->dy * rowstride;
+	    } else {
+		src = fb + (area->sx + area->width - 1) * colstride
+			 + (area->sy + area->height - 1) * rowstride;
+		dst = fb + (area->dx + area->width - 1) * colstride
+			 + (area->dy + area->height - 1) * rowstride;
+
+		colstride = -colstride;
+		rowstride = -rowstride;
+	    }
+
+	for (dy = 0; dy < area->height; dy++) {
+		u16* src2 = src;
+		u16* dst2 = dst;
+		for (dx = 0; dx < area->width; dx++) {
+			*dst2 = *src2;
+			src2 += colstride;
+			dst2 += colstride;
+		}
+		src += rowstride;
+		dst += rowstride;
+	}
+}
+
+/* Fill area in text (tileblit) mode */
+void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect)
+{
+	int dx, dy;
+	int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	int attr = (0x0F & rect->bg) << 4 | (0x0F & rect->fg);
+	u8  *fb = (u8 *) info->screen_base;
+	fb += rect->sx * colstride + rect->sy * rowstride;
+
+	for (dy = 0; dy < rect->height; dy++) {
+		u8* fb2 = fb;
+		for (dx = 0; dx < rect->width; dx++) {
+			fb2[0] = rect->index;
+			fb2[1] = attr;
+			fb2 += colstride;
+		}
+		fb += rowstride;
+	}
+}
+
+/* Write text in text (tileblit) mode */
+void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit)
+{
+	int dx, dy, i;
+	int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	int attr = (0x0F & blit->bg) << 4 | (0x0F & blit->fg);
+	u8* fb = (u8 *) info->screen_base;
+	fb += blit->sx * colstride + blit->sy * rowstride;
+
+	i=0;
+	for (dy=0; dy < blit->height; dy ++) {
+		u8* fb2 = fb;
+		for (dx = 0; dx < blit->width; dx ++) {
+			fb2[0] = blit->indices[i];
+			fb2[1] = attr;
+			fb2 += colstride;
+			i ++;
+			if (i == blit->length) return;
+		}
+		fb += rowstride;
+	}
+
+}
+
+/* Set cursor in text (tileblit) mode */
+void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
+{
+	u8 cs = 0x0d;
+	u8 ce = 0x0e;
+	u16 pos =  cursor->sx + (info->var.xoffset /  8)
+		+ (cursor->sy + (info->var.yoffset / 16))
+		   * (info->var.xres_virtual / 8);
+
+	if (! cursor -> mode)
+		return;
+
+	svga_wcrt_mask(0x0A, 0x20, 0x20); /* disable cursor */
+
+	if (cursor -> shape == FB_TILE_CURSOR_NONE)
+		return;
+
+	switch (cursor -> shape) {
+	case FB_TILE_CURSOR_UNDERLINE:
+		cs = 0x0d;
+		break;
+	case FB_TILE_CURSOR_LOWER_THIRD:
+		cs = 0x09;
+		break;
+	case FB_TILE_CURSOR_LOWER_HALF:
+		cs = 0x07;
+		break;
+	case FB_TILE_CURSOR_TWO_THIRDS:
+		cs = 0x05;
+		break;
+	case FB_TILE_CURSOR_BLOCK:
+		cs = 0x01;
+		break;
+	}
+
+	/* set cursor position */
+	vga_wcrt(NULL, 0x0E, pos >> 8);
+	vga_wcrt(NULL, 0x0F, pos & 0xFF);
+
+	vga_wcrt(NULL, 0x0B, ce); /* set cursor end */
+	vga_wcrt(NULL, 0x0A, cs); /* set cursor start and enable it */
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/*
+ *  Compute PLL settings (M, N, R)
+ *  F_VCO = (F_BASE * M) / N
+ *  F_OUT = F_VCO / (2^R)
+ */
+
+static inline u32 abs_diff(u32 a, u32 b)
+{
+	return (a > b) ? (a - b) : (b - a);
+}
+
+int svga_compute_pll(const struct svga_pll *pll, u32 f_wanted, u16 *m, u16 *n, u16 *r, int node)
+{
+	u16 am, an, ar;
+	u32 f_vco, f_current, delta_current, delta_best;
+
+	pr_debug("fb%d: ideal frequency: %d kHz\n", node, (unsigned int) f_wanted);
+
+	ar = pll->r_max;
+	f_vco = f_wanted << ar;
+
+	/* overflow check */
+	if ((f_vco >> ar) != f_wanted)
+		return -EINVAL;
+
+	/* It is usually better to have greater VCO clock
+	   because of better frequency stability.
+	   So first try r_max, then r smaller. */
+	while ((ar > pll->r_min) && (f_vco > pll->f_vco_max)) {
+		ar--;
+		f_vco = f_vco >> 1;
+	}
+
+	/* VCO bounds check */
+	if ((f_vco < pll->f_vco_min) || (f_vco > pll->f_vco_max))
+		return -EINVAL;
+
+	delta_best = 0xFFFFFFFF;
+	*m = 0;
+	*n = 0;
+	*r = ar;
+
+	am = pll->m_min;
+	an = pll->n_min;
+
+	while ((am <= pll->m_max) && (an <= pll->n_max)) {
+		f_current = (pll->f_base * am) / an;
+		delta_current = abs_diff (f_current, f_vco);
+
+		if (delta_current < delta_best) {
+			delta_best = delta_current;
+			*m = am;
+			*n = an;
+		}
+
+		if (f_current <= f_vco) {
+			am ++;
+		} else {
+			an ++;
+		}
+	}
+
+	f_current = (pll->f_base * *m) / *n;
+	pr_debug("fb%d: found frequency: %d kHz (VCO %d kHz)\n", node, (int) (f_current >> ar), (int) f_current);
+	pr_debug("fb%d: m = %d n = %d r = %d\n", node, (unsigned int) *m, (unsigned int) *n, (unsigned int) *r);
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Check CRT timing values */
+int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, int node)
+{
+	u32 value;
+
+	var->xres         = (var->xres+7)&~7;
+	var->left_margin  = (var->left_margin+7)&~7;
+	var->right_margin = (var->right_margin+7)&~7;
+	var->hsync_len    = (var->hsync_len+7)&~7;
+
+	/* Check horizontal total */
+	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
+	if (((value / 8) - 5) >= svga_regset_size (tm->h_total_regs))
+		return -EINVAL;
+
+	/* Check horizontal display and blank start */
+	value = var->xres;
+	if (((value / 8) - 1) >= svga_regset_size (tm->h_display_regs))
+		return -EINVAL;
+	if (((value / 8) - 1) >= svga_regset_size (tm->h_blank_start_regs))
+		return -EINVAL;
+
+	/* Check horizontal sync start */
+	value = var->xres + var->right_margin;
+	if (((value / 8) - 1) >= svga_regset_size (tm->h_sync_start_regs))
+		return -EINVAL;
+
+	/* Check horizontal blank end (or length) */
+	value = var->left_margin + var->right_margin + var->hsync_len;
+	if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_blank_end_regs)))
+		return -EINVAL;
+
+	/* Check horizontal sync end (or length) */
+	value = var->hsync_len;
+	if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_sync_end_regs)))
+		return -EINVAL;
+
+	/* Check vertical total */
+	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+	if ((value - 1) >= svga_regset_size(tm->v_total_regs))
+		return -EINVAL;
+
+	/* Check vertical display and blank start */
+	value = var->yres;
+	if ((value - 1) >= svga_regset_size(tm->v_display_regs))
+		return -EINVAL;
+	if ((value - 1) >= svga_regset_size(tm->v_blank_start_regs))
+		return -EINVAL;
+
+	/* Check vertical sync start */
+	value = var->yres + var->lower_margin;
+	if ((value - 1) >= svga_regset_size(tm->v_sync_start_regs))
+		return -EINVAL;
+
+	/* Check vertical blank end (or length) */
+	value = var->upper_margin + var->lower_margin + var->vsync_len;
+	if ((value == 0) || (value >= svga_regset_size (tm->v_blank_end_regs)))
+		return -EINVAL;
+
+	/* Check vertical sync end  (or length) */
+	value = var->vsync_len;
+	if ((value == 0) || (value >= svga_regset_size (tm->v_sync_end_regs)))
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Set CRT timing registers */
+void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var,
+			u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node)
+{
+	u8 regval;
+	u32 value;
+
+	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal total      : %d\n", node, value);
+	svga_wcrt_multi(tm->h_total_regs, (value / 8) - 5);
+
+	value = var->xres;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal display    : %d\n", node, value);
+	svga_wcrt_multi(tm->h_display_regs, (value / 8) - 1);
+
+	value = var->xres;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal blank start: %d\n", node, value);
+	svga_wcrt_multi(tm->h_blank_start_regs, (value / 8) - 1 + hborder);
+
+	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal blank end  : %d\n", node, value);
+	svga_wcrt_multi(tm->h_blank_end_regs, (value / 8) - 1 - hborder);
+
+	value = var->xres + var->right_margin;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal sync start : %d\n", node, value);
+	svga_wcrt_multi(tm->h_sync_start_regs, (value / 8));
+
+	value = var->xres + var->right_margin + var->hsync_len;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal sync end   : %d\n", node, value);
+	svga_wcrt_multi(tm->h_sync_end_regs, (value / 8));
+
+	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical total        : %d\n", node, value);
+	svga_wcrt_multi(tm->v_total_regs, value - 2);
+
+	value = var->yres;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical display      : %d\n", node, value);
+	svga_wcrt_multi(tm->v_display_regs, value - 1);
+
+	value = var->yres;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical blank start  : %d\n", node, value);
+	svga_wcrt_multi(tm->v_blank_start_regs, value);
+
+	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical blank end    : %d\n", node, value);
+	svga_wcrt_multi(tm->v_blank_end_regs, value - 2);
+
+	value = var->yres + var->lower_margin;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical sync start   : %d\n", node, value);
+	svga_wcrt_multi(tm->v_sync_start_regs, value);
+
+	value = var->yres + var->lower_margin + var->vsync_len;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical sync end     : %d\n", node, value);
+	svga_wcrt_multi(tm->v_sync_end_regs, value);
+
+	/* Set horizontal and vertical sync pulse polarity in misc register */
+
+	regval = vga_r(NULL, VGA_MIS_R);
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT) {
+		pr_debug("fb%d: positive horizontal sync\n", node);
+		regval = regval & ~0x80;
+	} else {
+		pr_debug("fb%d: negative horizontal sync\n", node);
+		regval = regval | 0x80;
+	}
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT) {
+		pr_debug("fb%d: positive vertical sync\n", node);
+		regval = regval & ~0x40;
+	} else {
+		pr_debug("fb%d: negative vertical sync\n\n", node);
+		regval = regval | 0x40;
+	}
+	vga_w(NULL, VGA_MIS_W, regval);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+int svga_match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
+{
+	int i = 0;
+
+	while (frm->bits_per_pixel != SVGA_FORMAT_END_VAL)
+	{
+		if ((var->bits_per_pixel == frm->bits_per_pixel) &&
+		    (var->red.length     <= frm->red.length)     &&
+		    (var->green.length   <= frm->green.length)   &&
+		    (var->blue.length    <= frm->blue.length)    &&
+		    (var->transp.length  <= frm->transp.length)  &&
+		    (var->nonstd	 == frm->nonstd)) {
+		    	var->bits_per_pixel = frm->bits_per_pixel;
+			var->red            = frm->red;
+			var->green          = frm->green;
+			var->blue           = frm->blue;
+			var->transp         = frm->transp;
+			var->nonstd         = frm->nonstd;
+			if (fix != NULL) {
+				fix->type      = frm->type;
+				fix->type_aux  = frm->type_aux;
+				fix->visual    = frm->visual;
+				fix->xpanstep  = frm->xpanstep;
+			}
+			return i;
+		}
+		i++;
+		frm++;
+	}
+	return -EINVAL;
+}
+
+
+EXPORT_SYMBOL(svga_wcrt_multi);
+EXPORT_SYMBOL(svga_wseq_multi);
+
+EXPORT_SYMBOL(svga_set_default_gfx_regs);
+EXPORT_SYMBOL(svga_set_default_atc_regs);
+EXPORT_SYMBOL(svga_set_default_seq_regs);
+EXPORT_SYMBOL(svga_set_default_crt_regs);
+EXPORT_SYMBOL(svga_set_textmode_vga_regs);
+
+EXPORT_SYMBOL(svga_settile);
+EXPORT_SYMBOL(svga_tilecopy);
+EXPORT_SYMBOL(svga_tilefill);
+EXPORT_SYMBOL(svga_tileblit);
+EXPORT_SYMBOL(svga_tilecursor);
+
+EXPORT_SYMBOL(svga_compute_pll);
+EXPORT_SYMBOL(svga_check_timings);
+EXPORT_SYMBOL(svga_set_timings);
+EXPORT_SYMBOL(svga_match_format);
+
+MODULE_AUTHOR("Ondrej Zajicek <santiago@crfreenet.org>");
+MODULE_DESCRIPTION("Common utility functions for VGA-based graphics cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 4b88fab..7478d0e 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -43,8 +42,9 @@
 static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *);
 static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
 
-static int tgafb_pci_register(struct pci_dev *, const struct pci_device_id *);
-static void tgafb_pci_unregister(struct pci_dev *);
+static int __devinit tgafb_pci_register(struct pci_dev *,
+					const struct pci_device_id *);
+static void __devexit tgafb_pci_unregister(struct pci_dev *);
 
 static const char *mode_option = "640x480@60";
 
@@ -70,9 +70,10 @@
  */
 
 static struct pci_device_id const tgafb_pci_table[] = {
-	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, PCI_ANY_ID, PCI_ANY_ID,
-	  0, 0, 0 }
+	{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) },
+	{ }
 };
+MODULE_DEVICE_TABLE(pci, tgafb_pci_table);
 
 static struct pci_driver tgafb_driver = {
 	.name			= "tgafb",
@@ -99,6 +100,12 @@
 		if (var->bits_per_pixel != 32)
 			return -EINVAL;
 	}
+	var->red.length = var->green.length = var->blue.length = 8;
+	if (var->bits_per_pixel == 32) {
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+	}
 
 	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
 		return -EINVAL;
@@ -137,10 +144,10 @@
 		0x00000303
 	};
 	static unsigned int const mode_presets[4] = {
-		0x00002000,
-		0x00002300,
+		0x00000000,
+		0x00000300,
 		0xffffffff,
-		0x00002300
+		0x00000300
 	};
 	static unsigned int const base_addr_presets[4] = {
 		0x00000000,
@@ -152,7 +159,7 @@
 	struct tga_par *par = (struct tga_par *) info->par;
 	u32 htimings, vtimings, pll_freq;
 	u8 tga_type;
-	int i, j;
+	int i;
 
 	/* Encode video timings.  */
 	htimings = (((info->var.xres/4) & TGA_HORIZ_ACT_LSB)
@@ -190,7 +197,9 @@
 	while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
 		continue;
 	mb();
-	TGA_WRITE_REG(par, deep_presets[tga_type], TGA_DEEP_REG);
+	TGA_WRITE_REG(par, deep_presets[tga_type] |
+			   (par->sync_on_green ? 0x0 : 0x00010000),
+		      TGA_DEEP_REG);
 	while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
 		continue;
 	mb();
@@ -227,8 +236,10 @@
 		BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE);
 		TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
 
+#ifdef CONFIG_HW_CONSOLE
 		for (i = 0; i < 16; i++) {
-			j = color_table[i];
+			int j = color_table[i];
+
 			TGA_WRITE_REG(par, default_red[j]|(BT485_DATA_PAL<<8),
 				      TGA_RAMDAC_REG);
 			TGA_WRITE_REG(par, default_grn[j]|(BT485_DATA_PAL<<8),
@@ -236,24 +247,27 @@
 			TGA_WRITE_REG(par, default_blu[j]|(BT485_DATA_PAL<<8),
 				      TGA_RAMDAC_REG);
 		}
-		for (i = 0; i < 240*3; i += 4) {
-			TGA_WRITE_REG(par, 0x55|(BT485_DATA_PAL<<8),
+		for (i = 0; i < 240 * 3; i += 4) {
+#else
+		for (i = 0; i < 256 * 3; i += 4) {
+#endif
+			TGA_WRITE_REG(par, 0x55 | (BT485_DATA_PAL << 8),
 				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT485_DATA_PAL<<8),
+			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
 				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT485_DATA_PAL<<8),
+			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
 				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT485_DATA_PAL<<8),
+			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
 				      TGA_RAMDAC_REG);
 		}
 
 	} else { /* 24-plane or 24plusZ */
 
-		/* Init BT463 registers.  */
+		/* Init BT463 RAMDAC registers.  */
 		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
 		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
 		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_2,
-			    (par->sync_on_green ? 0x80 : 0x40));
+			    (par->sync_on_green ? 0xc0 : 0x40));
 
 		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
 		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
@@ -267,26 +281,24 @@
 
 		/* Fill the palette.  */
 		BT463_LOAD_ADDR(par, 0x0000);
-		TGA_WRITE_REG(par, BT463_PALETTE<<2, TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
 
+#ifdef CONFIG_HW_CONSOLE
 		for (i = 0; i < 16; i++) {
-			j = color_table[i];
-			TGA_WRITE_REG(par, default_red[j]|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, default_grn[j]|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, default_blu[j]|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
+			int j = color_table[i];
+
+			TGA_WRITE_REG(par, default_red[j], TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, default_grn[j], TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, default_blu[j], TGA_RAMDAC_REG);
 		}
-		for (i = 0; i < 512*3; i += 4) {
-			TGA_WRITE_REG(par, 0x55|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
+		for (i = 0; i < 512 * 3; i += 4) {
+#else
+		for (i = 0; i < 528 * 3; i += 4) {
+#endif
+			TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
 		}
 
 		/* Fill window type table after start of vertical retrace.  */
@@ -299,15 +311,12 @@
 		TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
 
 		BT463_LOAD_ADDR(par, BT463_WINDOW_TYPE_BASE);
-		TGA_WRITE_REG(par, BT463_REG_ACC<<2, TGA_RAMDAC_SETUP_REG);
+		TGA_WRITE_REG(par, BT463_REG_ACC << 2, TGA_RAMDAC_SETUP_REG);
 
 		for (i = 0; i < 16; i++) {
-			TGA_WRITE_REG(par, 0x00|(BT463_REG_ACC<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x01|(BT463_REG_ACC<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x80|(BT463_REG_ACC<<10),
-				      TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x01, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
 		}
 
 	}
@@ -435,9 +444,16 @@
 		TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
 		TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
 		TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-	} else if (regno < 16) {
-		u32 value = (red << 16) | (green << 8) | blue;
-		((u32 *)info->pseudo_palette)[regno] = value;
+	} else {
+		if (regno < 16) {
+			u32 value = (regno << 16) | (regno << 8) | regno;
+			((u32 *)info->pseudo_palette)[regno] = value;
+		}
+		BT463_LOAD_ADDR(par, regno);
+		TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
+		TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
 	}
 
 	return 0;
@@ -885,7 +901,7 @@
 
 	n64 = (height * width) / 64;
 
-	if (dy < sy) {
+	if (sy < dy) {
 		spos = (sy + height) * width;
 		dpos = (dy + height) * width;
 
@@ -933,7 +949,7 @@
 
 	n16 = (height * width) / 16;
 
-	if (dy < sy) {
+	if (sy < dy) {
 		src = tga_fb + (sy + height) * width * 4;
 		dst = tga_fb + (dy + height) * width * 4;
 
@@ -1317,7 +1333,7 @@
 	info->fix.type_aux = 0;
 	info->fix.visual = (tga_type == TGA_TYPE_8PLANE
 			    ? FB_VISUAL_PSEUDOCOLOR
-			    : FB_VISUAL_TRUECOLOR);
+			    : FB_VISUAL_DIRECTCOLOR);
 
 	info->fix.line_length = par->xres * (par->bits_per_pixel >> 3);
 	info->fix.smem_start = (size_t) par->tga_fb_base;
@@ -1342,14 +1358,10 @@
 		TGA_24PLUSZ_FB_OFFSET
 	};
 
-	struct all_info {
-		struct fb_info info;
-		struct tga_par par;
-		u32 pseudo_palette[16];
-	} *all;
-
 	void __iomem *mem_base;
 	unsigned long bar0_start, bar0_len;
+	struct fb_info *info;
+	struct tga_par *par;
 	u8 tga_type;
 	int ret;
 
@@ -1360,13 +1372,14 @@
 	}
 
 	/* Allocate the fb and par structures.  */
-	all = kmalloc(sizeof(*all), GFP_KERNEL);
-	if (!all) {
+	info = framebuffer_alloc(sizeof(struct tga_par), &pdev->dev);
+	if (!info) {
 		printk(KERN_ERR "tgafb: Cannot allocate memory\n");
 		return -ENOMEM;
 	}
-	memset(all, 0, sizeof(*all));
-	pci_set_drvdata(pdev, all);
+
+	par = info->par;
+	pci_set_drvdata(pdev, info);
 
 	/* Request the mem regions.  */
 	bar0_start = pci_resource_start(pdev, 0);
@@ -1386,25 +1399,23 @@
 
 	/* Grab info about the card.  */
 	tga_type = (readl(mem_base) >> 12) & 0x0f;
-	all->par.pdev = pdev;
-	all->par.tga_mem_base = mem_base;
-	all->par.tga_fb_base = mem_base + fb_offset_presets[tga_type];
-	all->par.tga_regs_base = mem_base + TGA_REGS_OFFSET;
-	all->par.tga_type = tga_type;
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &all->par.tga_chip_rev);
+	par->pdev = pdev;
+	par->tga_mem_base = mem_base;
+	par->tga_fb_base = mem_base + fb_offset_presets[tga_type];
+	par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
+	par->tga_type = tga_type;
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &par->tga_chip_rev);
 
 	/* Setup framebuffer.  */
-	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
-                          FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
-	all->info.fbops = &tgafb_ops;
-	all->info.screen_base = all->par.tga_fb_base;
-	all->info.par = &all->par;
-	all->info.pseudo_palette = all->pseudo_palette;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
+		      FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
+	info->fbops = &tgafb_ops;
+	info->screen_base = par->tga_fb_base;
+	info->pseudo_palette = (void *)(par + 1);
 
 	/* This should give a reasonable default video mode.  */
 
-	ret = fb_find_mode(&all->info.var, &all->info, mode_option,
-			   NULL, 0, NULL,
+	ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL,
 			   tga_type == TGA_TYPE_8PLANE ? 8 : 32);
 	if (ret == 0 || ret == 4) {
 		printk(KERN_ERR "tgafb: Could not find valid video mode\n");
@@ -1412,29 +1423,28 @@
 		goto err1;
 	}
 
-	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
 		printk(KERN_ERR "tgafb: Could not allocate color map\n");
 		ret = -ENOMEM;
 		goto err1;
 	}
 
-	tgafb_set_par(&all->info);
-	tgafb_init_fix(&all->info);
+	tgafb_set_par(info);
+	tgafb_init_fix(info);
 
-	all->info.device = &pdev->dev;
-	if (register_framebuffer(&all->info) < 0) {
+	if (register_framebuffer(info) < 0) {
 		printk(KERN_ERR "tgafb: Could not register framebuffer\n");
 		ret = -EINVAL;
 		goto err1;
 	}
 
 	printk(KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
-	       all->par.tga_chip_rev);
+	       par->tga_chip_rev);
 	printk(KERN_INFO "tgafb: at PCI bus %d, device %d, function %d\n",
 	       pdev->bus->number, PCI_SLOT(pdev->devfn),
 	       PCI_FUNC(pdev->devfn));
 	printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lx\n",
-	       all->info.node, all->info.fix.id, bar0_start);
+	       info->node, info->fix.id, bar0_start);
 
 	return 0;
 
@@ -1443,11 +1453,11 @@
 		iounmap(mem_base);
 	release_mem_region(bar0_start, bar0_len);
  err0:
-	kfree(all);
+	framebuffer_release(info);
 	return ret;
 }
 
-static void __exit
+static void __devexit
 tgafb_pci_unregister(struct pci_dev *pdev)
 {
 	struct fb_info *info = pci_get_drvdata(pdev);
@@ -1456,22 +1466,21 @@
 	if (!info)
 		return;
 	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
 	iounmap(par->tga_mem_base);
 	release_mem_region(pci_resource_start(pdev, 0),
 			   pci_resource_len(pdev, 0));
-	kfree(info);
+	framebuffer_release(info);
 }
 
-#ifdef MODULE
-static void __exit
+static void __devexit
 tgafb_exit(void)
 {
 	pci_unregister_driver(&tgafb_driver);
 }
-#endif /* MODULE */
 
 #ifndef MODULE
-int __init
+static int __devinit
 tgafb_setup(char *arg)
 {
 	char *this_opt;
@@ -1493,7 +1502,7 @@
 }
 #endif /* !MODULE */
 
-int __init
+static int __devinit
 tgafb_init(void)
 {
 #ifndef MODULE
@@ -1511,10 +1520,7 @@
  */
 
 module_init(tgafb_init);
-
-#ifdef MODULE
 module_exit(tgafb_exit);
-#endif
 
 MODULE_DESCRIPTION("framebuffer driver for TGA chipset");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 6aff63d..ec4c7dc 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -70,7 +70,8 @@
 		unsigned char	ClockingMode;	  /* Seq-Controller:01h */
 	} vga_state;
 	struct vgastate state;
-	atomic_t ref_count;
+	struct mutex open_lock;
+	unsigned int ref_count;
 	int palette_blanked, vesa_blanked, mode, isVGA;
 	u8 misc, pel_msk, vss, clkdiv;
 	u8 crtc[VGA_CRT_C];
@@ -300,28 +301,33 @@
 static int vga16fb_open(struct fb_info *info, int user)
 {
 	struct vga16fb_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
-	if (!cnt) {
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
 			VGA_SAVE_CMAP;
 		save_vga(&par->state);
 	}
-	atomic_inc(&par->ref_count);
+	par->ref_count++;
+	mutex_unlock(&par->open_lock);
+
 	return 0;
 }
 
 static int vga16fb_release(struct fb_info *info, int user)
 {
 	struct vga16fb_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
-	if (!cnt)
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
+		mutex_unlock(&par->open_lock);
 		return -EINVAL;
-	if (cnt == 1)
+	}
+	if (par->ref_count == 1)
 		restore_vga(&par->state);
-	atomic_dec(&par->ref_count);
+	par->ref_count--;
+	mutex_unlock(&par->open_lock);
 
 	return 0;
 }
@@ -1357,6 +1363,7 @@
 	printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
 	par = info->par;
 
+	mutex_init(&par->open_lock);
 	par->isVGA = ORIG_VIDEO_ISVGA;
 	par->palette_blanked = 0;
 	par->vesa_blanked = 0;
diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c
deleted file mode 100644
index b9fb6fb..0000000
--- a/drivers/video/virgefb.c
+++ /dev/null
@@ -1,2526 +0,0 @@
-/*
- * linux/drivers/video/virgefb.c -- CyberVision64/3D frame buffer device
- *
- *    Copyright (C) 1997 André Heynatz
- *
- *
- * This file is based on the CyberVision frame buffer device (cyberfb.c):
- *
- *    Copyright (C) 1996 Martin Apel
- *                       Geert Uytterhoeven
- *
- * Zorro II additions :
- *
- *    Copyright (C) 1998-2000 Christian T. Steigies
- *
- * Initialization additions :
- *
- *    Copyright (C) 1998-2000 Ken Tyler
- *
- * Parts of the Initialization code are based on Cyberfb.c by Allan Bair,
- * and on the NetBSD CyberVision64 frame buffer driver by Michael Teske who gave
- * permission for its use.
- *
- * Many thanks to Frank Mariak for his assistance with ZORRO 2 access and other
- * mysteries.
- *
- *
- *
- * 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.
- */
-
-#undef VIRGEFBDEBUG
-#undef VIRGEFBDUMP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/zorro.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/amigahw.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb32.h>
-
-#include "virgefb.h"
-
-#ifdef VIRGEFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#ifdef VIRGEFBDUMP
-static void cv64_dump(void);
-#define DUMP cv64_dump()
-#else
-#define DUMP
-#endif
-
-/*
- *	Macros for register access and zorro control
- */
-
-static inline void mb_inline(void) { mb(); }	/* for use in comma expressions */
-
-/* Set zorro 2 map */
-
-#define SelectIO \
-	mb(); \
-	if (on_zorro2) { \
-		(*(volatile u16 *)((u8 *)(vcode_switch_base + 0x04)) = 0x01); \
-		mb(); \
-	}
-
-#define	SelectMMIO \
-	mb(); \
-	if (on_zorro2) { \
-		(*(volatile u16 *)((u8 *)(vcode_switch_base + 0x04)) = 0x02); \
-		mb(); \
-	}
-
-#define	SelectCFG \
-	mb(); \
-	if (on_zorro2) { \
-		(*(volatile u16 *)((u8 *)(vcode_switch_base + 0x04)) = 0x03); \
-		mb(); \
-	}
-
-/* Set pass through, 0 = amiga, !=0 = cv64/3d */
-
-#define SetVSwitch(x) \
-	mb(); \
-	(*(volatile u16 *)((u8 *)(vcode_switch_base)) = \
-	(u16)(x ? 0 : 1)); \
-	mb();
-
-/* Zorro2 endian 'aperture' */
-
-#define ENDIAN_BYTE	2
-#define ENDIAN_WORD	1
-#define ENDIAN_LONG	0
-
-#define Select_Zorro2_FrameBuffer(x) \
-	do { \
-		if (on_zorro2) { \
-			mb(); \
-			(*(volatile u16 *)((u8 *)(vcode_switch_base + 0x08)) = \
-			(x * 0x40)); \
-			mb(); \
-		} \
-	} while (0)
-
-/* SetPortVal - only used for interrupt enable (not yet implemented) */
-
-#if 0
-#define SetPortVal(x) \
-	mb(); \
-	(*(volatile u16 *)((u8 *)(vcode_switch_base + 0x0c)) = \
-	(u16)x); \
-	mb();
-#endif
-
-/* IO access */
-
-#define byte_access_io(x)	(((x) & 0x3ffc) | (((x) & 3)^3) | (((x) & 3) <<14))
-#define byte_access_mmio(x)	(((x) & 0xfffc) | (((x) & 3)^3))
-
-/* Write 8 bit VGA register - used once for chip wakeup */
-
-#define wb_vgaio(reg, dat) \
-	SelectIO; \
-	(*(volatile u8 *)(vgaio_regs + ((u32)byte_access_io(reg) & 0xffff)) = \
-	(dat & 0xff)); \
-	SelectMMIO;
-
-/* Read 8 bit VGA register - only used in dump (SelectIO not needed on read ?) */
-
-#ifdef VIRGEFBDUMP
-#define rb_vgaio(reg) \
-	({ \
-	u8 __zzyzx; \
-	SelectIO; \
-	__zzyzx = (*(volatile u8 *)((vgaio_regs)+(u32)byte_access_io(reg))); \
-	SelectMMIO; \
-	__zzyzx; \
-	})
-#endif
-
-/* MMIO access */
-
-/* Read 8 bit MMIO register */
-
-#define rb_mmio(reg) \
-	(mb_inline(), \
-	(*(volatile u8 *)(mmio_regs + 0x8000 + (u32)byte_access_mmio(reg))))
-
-/* Write 8 bit MMIO register */
-
-#define wb_mmio(reg,dat) \
-	mb(); \
-	(*(volatile u8 *)(mmio_regs + 0x8000 + (byte_access_mmio((reg) & 0xffff))) = \
-	(dat & 0xff)); \
-	mb();
-
-/* Read 32 bit MMIO register */
-
-#define rl_mmio(reg) \
-	(mb_inline(), \
-	(*((volatile u32 *)((u8 *)((mmio_regs + (on_zorro2 ? 0x20000 : 0)) + (reg))))))
-
-/* Write 32 bit MMIO register */
-
-#define wl_mmio(reg,dat) \
-	mb(); \
-	((*(volatile u32 *)((u8 *)((mmio_regs + (on_zorro2 ? 0x20000 : 0)) + (reg)))) = \
-	(u32)(dat)); \
-	mb();
-
-/* Write to virge graphics register */
-
-#define wgfx(reg, dat)	do { wb_mmio(GCT_ADDRESS, (reg)); wb_mmio(GCT_ADDRESS_W, (dat)); } while (0)
-
-/* Write to virge sequencer register */
-
-#define wseq(reg, dat)	do { wb_mmio(SEQ_ADDRESS, (reg)); wb_mmio(SEQ_ADDRESS_W, (dat)); } while (0)
-
-/* Write to virge CRT controller register */
-
-#define wcrt(reg, dat)	do { wb_mmio(CRT_ADDRESS, (reg)); wb_mmio(CRT_ADDRESS_W, (dat)); } while (0)
-
-/* Write to virge attribute register */
-
-#define watr(reg, dat) \
-	do { \
-		volatile unsigned char watr_tmp; \
-		watr_tmp = rb_mmio(ACT_ADDRESS_RESET); \
-		wb_mmio(ACT_ADDRESS_W, (reg)); \
-		wb_mmio(ACT_ADDRESS_W, (dat)); \
-		udelay(10); \
-	} while (0)
-
-/* end of macros */
-
-struct virgefb_par {
-   struct fb_var_screeninfo var;
-   __u32 type;
-   __u32 type_aux;
-   __u32 visual;
-   __u32 line_length;
-};
-
-static struct virgefb_par current_par;
-
-static int current_par_valid = 0;
-
-static struct display disp;
-static struct fb_info fb_info;
-
-static union {
-#ifdef FBCON_HAS_CFB16
-    u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-    u32 cfb32[16];
-#endif
-} fbcon_cmap;
-
-/*
- *    Switch for Chipset Independency
- */
-
-static struct fb_hwswitch {
-
-   /* Initialisation */
-
-   int (*init)(void);
-
-   /* Display Control */
-
-   int (*encode_fix)(struct fb_fix_screeninfo *fix, struct virgefb_par *par);
-   int (*decode_var)(struct fb_var_screeninfo *var, struct virgefb_par *par);
-   int (*encode_var)(struct fb_var_screeninfo *var, struct virgefb_par *par);
-   int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
-                    u_int *transp, struct fb_info *info);
-   void (*blank)(int blank);
-} *fbhw;
-
-static unsigned char blit_maybe_busy = 0;
-
-/*
- *    Frame Buffer Name
- */
-
-static char virgefb_name[16] = "CyberVision/3D";
-
-/*
- *    CyberVision64/3d Graphics Board
- */
-
-static unsigned char virgefb_colour_table [256][3];
-static unsigned long v_ram;
-static unsigned long v_ram_size;
-static volatile unsigned char *mmio_regs;
-static volatile unsigned char *vgaio_regs;
-
-static unsigned long v_ram_phys;
-static unsigned long mmio_regs_phys;
-static unsigned long vcode_switch_base;
-static unsigned char on_zorro2;
-
-/*
- * Offsets from start of video ram to appropriate ZIII aperture
- */
-
-#ifdef FBCON_HAS_CFB8
-#define CYBMEM_OFFSET_8  0x800000	/* BGRX */
-#endif
-#ifdef FBCON_HAS_CFB16
-#define CYBMEM_OFFSET_16 0x400000	/* GBXR */
-#endif
-#ifdef FBCON_HAS_CFB32
-#define CYBMEM_OFFSET_32 0x000000	/* XRGB */
-#endif
-
-/*
- *    MEMCLOCK was 32MHz, 64MHz works, 72MHz doesn't (on my board)
- */
-
-#define MEMCLOCK 50000000
-
-/*
- *    Predefined Video Modes
- */
-
-static struct {
-    const char *name;
-    struct fb_var_screeninfo var;
-} virgefb_predefined[] __initdata = {
-#ifdef FBCON_HAS_CFB8
-    {
-	"640x480-8", {		/* Cybervision 8 bpp */
-	    640, 480, 640, 480, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 31250, 160, 136, 82, 61, 88, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"768x576-8", {		/* Cybervision 8 bpp */
-	    768, 576, 768, 576, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 29411, 144, 112, 32, 15, 64, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"800x600-8", {		/* Cybervision 8 bpp */
-	    800, 600, 800, 600, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 28571, 168, 104, 22, 1, 48, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-  #if 0 
-	"1024x768-8", {		/* Cybervision 8 bpp */
-	    1024, 768, 1024, 768, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-  #else
-	"1024x768-8", {
-	    1024, 768, 1024, 768, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-   #if 0
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 12500, 184, 40, 40, 2, 96, 1,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
-    #else
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 12699, 176, 16, 28, 1, 96, 3,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
-    #endif
-  #endif
-    }, {
-	"1152x886-8", {		/* Cybervision 8 bpp */
-	    1152, 886, 1152, 886, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 19230, 280, 168, 45, 1, 64, 10,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1280x1024-8", { 	/* Cybervision 8 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-  #if 0
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    }
-  #else
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 7414, 232, 64, 38, 1, 112, 3,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
-  #endif
-    }, {
-	"1600x1200-8", { 	/* Cybervision 8 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-  #if 0
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-  #else
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 6411, 256, 32, 52, 10, 160, 8,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
-  #endif
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB16
-    {
-	"640x480-16", {		/* Cybervision 16 bpp */
-	    640, 480, 640, 480, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 31250, 152, 144, 82, 61, 88, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"768x576-16", {		/* Cybervision 16 bpp */
-	    768, 576, 768, 576, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 29411, 144, 112, 32, 15, 64, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"800x600-16", {		/* Cybervision 16 bpp */
-	    800, 600, 800, 600, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 28571, 168, 104, 22, 1, 48, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-#if 0
-	"1024x768-16", { 	/* Cybervision 16 bpp */
-	    1024, 768, 1024, 768, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-#else
-         "1024x768-16", {
-             1024, 768, 1024, 768, 0, 0, 16, 0,
-             {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-             0, 0, -1, -1, FB_ACCELF_TEXT, 12500, 184, 40, 40, 2, 96, 1,
-             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-         }
-#endif
-    }, {
-	"1152x886-16", { 	/* Cybervision 16 bpp */
-	    1152, 886, 1152, 886, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 19230, 280, 168, 45, 1, 64, 10,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1280x1024-16", { 	/* Cybervision 16 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1600x1200-16", { 	/* Cybervision 16 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB32
-    {
-	"640x480-32", {		/* Cybervision 32 bpp */
-	    640, 480, 640, 480, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 31250, 160, 136, 82, 61, 88, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-     }, {
-	"768x576-32", {		/* Cybervision 32 bpp */
-	    768, 576, 768, 576, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 29411, 144, 112, 32, 15, 64, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-     }, {
-	"800x600-32", {		/* Cybervision 32 bpp */
-	    800, 600, 800, 600, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-  	    0, 0, -1, -1, FB_ACCELF_TEXT, 28571, 168, 104, 22, 1, 48, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-     }, {
-	"1024x768-32", {	/* Cybervision 32 bpp */
-	    1024, 768, 1024, 768, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1152x886-32", {	/* Cybervision 32 bpp */
-	    1152, 886, 1152, 886, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 19230, 280, 168, 45, 1, 64, 10,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1280x1024-32", {	/* Cybervision 32 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1600x1200-32", {	/* Cybervision 32 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    },
-#endif
-
-/* interlaced modes */
-
-#ifdef FBCON_HAS_CFB8
-    {
-	"1024x768-8i", {	/* Cybervision 8 bpp */
-	    1024, 768, 1024, 768, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1280x1024-8i", {	/* Cybervision 8 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1600x1200-8i", {	/* Cybervision 8 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB16
-    {
-	"1024x768-16i", {	/* Cybervision 16 bpp */
-	    1024, 768, 1024, 768, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1280x1024-16i", {	/* Cybervision 16 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1600x1200-16i", {	/* Cybervision 16 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB32
-    {
-	"1024x768-32i", {	/* Cybervision 32 bpp */
-	    1024, 768, 1024, 768, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 22222, 216, 144, 39, 2, 72, 1,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1280x1024-32i", {	/* Cybervision 32 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {23, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1600x1200-32i", {	/* Cybervision 32 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    },
-#endif
-
-/* doublescan modes */
-
-#ifdef FBCON_HAS_CFB8
-    {
-	"320x240-8d", {		/* Cybervision 8 bpp */
-	    320, 240, 320, 240, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 59259, 80, 80, 45, 26, 32, 1,
-	    0, FB_VMODE_DOUBLE
-	    }
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB16
-    {
-	"320x240-16d", {	/* Cybervision 16 bpp */
-	    320, 240, 320, 240, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 59259, 80, 80, 45, 26, 32, 1,
-	    0, FB_VMODE_DOUBLE
-	    }
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB32
-    {
-	"320x240-32d", {	/* Cybervision 32 bpp */
-	    320, 240, 320, 240, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 59259, 80, 80, 45, 26, 32, 1,
-	    0, FB_VMODE_DOUBLE
-	    }
-    },
-#endif
-};
-
-#define NUM_TOTAL_MODES	ARRAY_SIZE(virgefb_predefined)
-
-/*
- *    Default to 800x600 for video=virge8:, virge16: or virge32:
- */
-
-#ifdef FBCON_HAS_CFB8
-#define VIRGE8_DEFMODE	(2)
-#endif
-
-#ifdef FBCON_HAS_CFB16
-#define VIRGE16_DEFMODE	(9)
-#endif
-
-#ifdef FBCON_HAS_CFB32
-#define VIRGE32_DEFMODE	(16)
-#endif
-
-static struct fb_var_screeninfo virgefb_default;
-static int virgefb_inverse = 0;
-
-/*
- *    Interface used by the world
- */
-
-int virgefb_setup(char*);
-static int virgefb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info);
-static int virgefb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int virgefb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			   struct fb_info *info);
-static int virgefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info);
-static int virgefb_blank(int blank, struct fb_info *info);
-
-/*
- *    Interface to the low level console driver
- */
-
-int virgefb_init(void);
-static int virgefb_switch(int con, struct fb_info *info);
-static int virgefb_updatevar(int con, struct fb_info *info);
-
-/*
- *    Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static struct display_switch fbcon_virge8;
-#endif
-
-#ifdef FBCON_HAS_CFB16
-static struct display_switch fbcon_virge16;
-#endif
-
-#ifdef FBCON_HAS_CFB32
-static struct display_switch fbcon_virge32;
-#endif
-
-/*
- *   Hardware Specific Routines
- */
-
-static int virge_init(void);
-static int virgefb_encode_fix(struct fb_fix_screeninfo *fix,
-				struct virgefb_par *par);
-static int virgefb_decode_var(struct fb_var_screeninfo *var,
-				struct virgefb_par *par);
-static int virgefb_encode_var(struct fb_var_screeninfo *var,
-				struct virgefb_par *par);
-static int virgefb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-				u_int *transp, struct fb_info *info);
-static void virgefb_gfx_on_off(int blank);
-static inline void virgefb_wait_for_idle(void);
-static void virgefb_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
-		u_short width, u_short height, u_short stride, u_short depth);
-static void virgefb_RectFill(u_short x, u_short y, u_short width, u_short height,
-		u_short color, u_short stride, u_short depth);
-
-/*
- *    Internal routines
- */
-
-static void virgefb_get_par(struct virgefb_par *par);
-static void virgefb_set_par(struct virgefb_par *par);
-static int virgefb_do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
-static void virgefb_set_disp(int con, struct fb_info *info);
-static int virgefb_get_video_mode(const char *name);
-static void virgefb_set_video(struct fb_var_screeninfo *var);
-
-/*
- *    Additions for Initialization
- */
-
-static void virgefb_load_video_mode(struct fb_var_screeninfo *video_mode);
-static int cv3d_has_4mb(void);
-static unsigned short virgefb_compute_clock(unsigned long freq);
-static inline unsigned char rattr(short);
-static inline unsigned char rseq(short);
-static inline unsigned char rcrt(short);
-static inline unsigned char rgfx(short);
-static inline void gfx_on_off(int toggle);
-static void virgefb_pci_init(void);
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-/*
- *	Functions for register access
- */
-
-/* Read attribute controller register */
-
-static inline unsigned char rattr(short idx)
-{
-	volatile unsigned char rattr_tmp;
-
-	rattr_tmp = rb_mmio(ACT_ADDRESS_RESET);
-	wb_mmio(ACT_ADDRESS_W, idx);
-	return (rb_mmio(ACT_ADDRESS_R));
-}
-
-/* Read sequencer register */
-
-static inline unsigned char rseq(short idx)
-{
-	wb_mmio(SEQ_ADDRESS, idx);
-	return (rb_mmio(SEQ_ADDRESS_R));
-}
-
-/* Read CRT controller register */
-
-static inline unsigned char rcrt(short idx)
-{
-	wb_mmio(CRT_ADDRESS, idx);
-	return (rb_mmio(CRT_ADDRESS_R));
-}
-
-/* Read graphics controller register */
-
-static inline unsigned char rgfx(short idx)
-{
-	wb_mmio(GCT_ADDRESS, idx);
-	return (rb_mmio(GCT_ADDRESS_R));
-}
-
-
-/*
- *	Initialization
- */
-
-/* PCI init */
-
-void virgefb_pci_init(void) {
-
-	DPRINTK("ENTER\n");
-
-	SelectCFG;
-
-	if (on_zorro2) {
-		*((short *)(vgaio_regs + 0x00000010)) = 0;
-		*((long  *)(vgaio_regs + 0x00000004)) = 0x02000003;
-	} else {
-		*((short *)(vgaio_regs + 0x000e0010)) = 0;
-		*((long  *)(vgaio_regs + 0x000e0004)) = 0x02000003;
-	}
-
-	/* SelectIO is in wb_vgaio macro */
-	wb_vgaio(SREG_VIDEO_SUBS_ENABLE, 0x01);
-	/* SelectMMIO is in wb_vgaio macro */
-
-	DPRINTK("EXIT\n");
-
-	return;
-}
-
-/* 
- * Initalize all mode independent regs, find mem size and clear mem
-*/
-
-static int virge_init(void)
-{
-	int i;
-	unsigned char tmp;
-
-	DPRINTK("ENTER\n");
-
-	virgefb_pci_init();
-
-	wb_mmio(GREG_MISC_OUTPUT_W, 0x07);	/* colour, ram enable, clk sel */
-
-	wseq(SEQ_ID_UNLOCK_EXT, 0x06);		/* unlock extensions */
-	tmp = rb_mmio(GREG_MISC_OUTPUT_R);
-	wcrt(CRT_ID_REGISTER_LOCK_1, 0x48);	/* unlock CR2D to CR3F */
-
-	wcrt(CRT_ID_BACKWAD_COMP_1, 0x00);	/* irq disable */
-
-	wcrt(CRT_ID_REGISTER_LOCK_2, 0xa5);	/* unlock CR40 to CRFF and more */
-	wcrt(CRT_ID_REGISTER_LOCK,0x00);	/* unlock h and v timing */
-	wcrt(CRT_ID_SYSTEM_CONFIG, 0x01);	/* unlock enhanced programming registers */
-
-	wb_mmio(GREG_FEATURE_CONTROL_W, 0x00);
-
-	wcrt(CRT_ID_EXT_MISC_CNTL, 0x00);	/* b2 = 0 to allow VDAC mmio access */
-#if 0
-	/* write strap options ... ? */
-	wcrt(CRT_ID_CONFIG_1, 0x08);
-	wcrt(CRT_ID_CONFIG_2, 0xff);		/* 0x0x2 bit needs to be set ?? */
-	wcrt(CRT_ID_CONFIG_3, 0x0f);
-	wcrt(CRT_ID_CONFIG_4, 0x1a);
-#endif
-	wcrt(CRT_ID_EXT_MISC_CNTL_1, 0x82);	 /* PCI DE and software reset S3D engine */
-	/* EXT_MISC_CNTL_1, CR66 bit 0 should be the same as bit 0 MR_ADVANCED_FUNCTION_CONTROL - check */
-	wl_mmio(MR_ADVANCED_FUNCTION_CONTROL, 0x00000011); /* enhanced mode, linear addressing */
-
-/* crtc registers */
-
-	wcrt(CRT_ID_PRESET_ROW_SCAN, 0x00);
-
-	/* Disable h/w cursor */
-
-	wcrt(CRT_ID_CURSOR_START, 0x00);
-	wcrt(CRT_ID_CURSOR_END, 0x00);
-	wcrt(CRT_ID_START_ADDR_HIGH, 0x00);
-	wcrt(CRT_ID_START_ADDR_LOW, 0x00);
-	wcrt(CRT_ID_CURSOR_LOC_HIGH, 0x00);
-	wcrt(CRT_ID_CURSOR_LOC_LOW, 0x00);
-	wcrt(CRT_ID_EXT_MODE, 0x00);
-	wcrt(CRT_ID_HWGC_MODE, 0x00);
-	wcrt(CRT_ID_HWGC_ORIGIN_X_HI, 0x00);
-	wcrt(CRT_ID_HWGC_ORIGIN_X_LO, 0x00);
-	wcrt(CRT_ID_HWGC_ORIGIN_Y_HI, 0x00);
-	wcrt(CRT_ID_HWGC_ORIGIN_Y_LO, 0x00);
-	i = rcrt(CRT_ID_HWGC_MODE);
-	wcrt(CRT_ID_HWGC_FG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_FG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_FG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_BG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_BG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_BG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_START_AD_HI, 0x00);
-	wcrt(CRT_ID_HWGC_START_AD_LO, 0x00);
-	wcrt(CRT_ID_HWGC_DSTART_X, 0x00);
-	wcrt(CRT_ID_HWGC_DSTART_Y, 0x00);
-
-	wcrt(CRT_ID_UNDERLINE_LOC, 0x00);
-
-	wcrt(CRT_ID_MODE_CONTROL, 0xe3);
-	wcrt(CRT_ID_BACKWAD_COMP_2, 0x22);	/* blank bdr bit 5 blanking only on 8 bit */
-
-	wcrt(CRT_ID_EX_SYNC_1, 0x00);
-
-	/* memory */
-
-	wcrt(CRT_ID_EXT_SYS_CNTL_3, 0x00);
-	wcrt(CRT_ID_MEMORY_CONF, 0x08);		/* config enhanced map */
-	wcrt(CRT_ID_EXT_MEM_CNTL_1, 0x08);	/* MMIO Select (0x0c works as well)*/
-	wcrt(CRT_ID_EXT_MEM_CNTL_2, 0x02);	/* why 02 big endian 00 works ? */
-	wcrt(CRT_ID_EXT_MEM_CNTL_4, 0x9f);	/* config big endian - 0x00 ?  */
-	wcrt(CRT_ID_LAW_POS_HI, 0x00);
-	wcrt(CRT_ID_LAW_POS_LO, 0x00);
-	wcrt(CRT_ID_EXT_MISC_CNTL_1, 0x81);
-	wcrt(CRT_ID_MISC_1, 0x90);		/* must follow CRT_ID_EXT_MISC_CNTL_1 */
-	wcrt(CRT_ID_LAW_CNTL, 0x13);		/* force 4 Meg for test */
-	if (cv3d_has_4mb()) {
-		v_ram_size = 0x00400000;
-		wcrt(CRT_ID_LAW_CNTL, 0x13);	/* 4 MB */
-	} else {
-		v_ram_size = 0x00200000;
-		wcrt(CRT_ID_LAW_CNTL, 0x12); 	/* 2 MB */
-	}
-
-	if (on_zorro2)
-		v_ram_size -= 0x60000;		/* we need some space for the registers */
-
-	wcrt(CRT_ID_EXT_SYS_CNTL_4, 0x00);
-	wcrt(CRT_ID_EXT_DAC_CNTL, 0x00);	/* 0x10 for X11 cursor mode */
-
-/* sequencer registers */
-
-	wseq(SEQ_ID_CLOCKING_MODE, 0x01);	/* 8 dot clock */
-	wseq(SEQ_ID_MAP_MASK, 0xff);
-	wseq(SEQ_ID_CHAR_MAP_SELECT, 0x00);
-	wseq(SEQ_ID_MEMORY_MODE, 0x02);
-	wseq(SEQ_ID_RAMDAC_CNTL, 0x00);
-	wseq(SEQ_ID_SIGNAL_SELECT, 0x00);
-	wseq(SEQ_ID_EXT_SEQ_REG9, 0x00);	/* MMIO and PIO reg access enabled */
-	wseq(SEQ_ID_EXT_MISC_SEQ, 0x00);
-	wseq(SEQ_ID_CLKSYN_CNTL_1, 0x00);
-	wseq(SEQ_ID_EXT_SEQ, 0x00);
-
-/* graphic registers */
-
-	wgfx(GCT_ID_SET_RESET, 0x00);
-	wgfx(GCT_ID_ENABLE_SET_RESET, 0x00);
-	wgfx(GCT_ID_COLOR_COMPARE, 0x00);
-	wgfx(GCT_ID_DATA_ROTATE, 0x00);
-	wgfx(GCT_ID_READ_MAP_SELECT, 0x00);
-	wgfx(GCT_ID_GRAPHICS_MODE, 0x40);
-	wgfx(GCT_ID_MISC, 0x01);
-	wgfx(GCT_ID_COLOR_XCARE, 0x0f);
-	wgfx(GCT_ID_BITMASK, 0xff);
-
-/* attribute  registers */
-
-	for(i = 0; i <= 15; i++)
-		watr(ACT_ID_PALETTE0 + i, i);
-	watr(ACT_ID_ATTR_MODE_CNTL, 0x41);
-	watr(ACT_ID_OVERSCAN_COLOR, 0xff);
-	watr(ACT_ID_COLOR_PLANE_ENA, 0x0f);
-	watr(ACT_ID_HOR_PEL_PANNING, 0x00);
-	watr(ACT_ID_COLOR_SELECT, 0x00);
-
-	wb_mmio(VDAC_MASK, 0xff);
-
-/* init local cmap as greyscale levels */
-
-	for (i = 0; i < 256; i++) {
-		virgefb_colour_table [i][0] = i;
-		virgefb_colour_table [i][1] = i;
-		virgefb_colour_table [i][2] = i;
-	}
-
-/* clear framebuffer memory */
-
-	memset((char*)v_ram, 0x00, v_ram_size);
-
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    This function should fill in the `fix' structure based on the
- *    values in the `par' structure.
- */
-
-static int virgefb_encode_fix(struct fb_fix_screeninfo *fix,
-			    struct virgefb_par *par)
-{
-	DPRINTK("ENTER set video phys addr\n");
-
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, virgefb_name);
-	if (on_zorro2)
-		fix->smem_start = v_ram_phys;
-	switch (par->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-		case 8:
-			if (on_zorro2)
-				Select_Zorro2_FrameBuffer(ENDIAN_BYTE);
-			else
-				fix->smem_start = (v_ram_phys + CYBMEM_OFFSET_8);
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16:
-			if (on_zorro2)
-				Select_Zorro2_FrameBuffer(ENDIAN_WORD);
-			else
-				fix->smem_start = (v_ram_phys + CYBMEM_OFFSET_16);
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32:
-			if (on_zorro2)
-				Select_Zorro2_FrameBuffer(ENDIAN_LONG);
-			else
-				fix->smem_start = (v_ram_phys + CYBMEM_OFFSET_32);
-			break;
-#endif
-	}
-
-	fix->smem_len = v_ram_size;
-	fix->mmio_start = mmio_regs_phys;
-	fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-	if (par->var.bits_per_pixel == 8)
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-		fix->visual = FB_VISUAL_TRUECOLOR;
-
-	fix->xpanstep = 0;
-	fix->ypanstep = 0;
-	fix->ywrapstep = 0;
-	fix->line_length = par->var.xres_virtual*par->var.bits_per_pixel/8;
-	fix->accel = FB_ACCEL_S3_VIRGE;
-	DPRINTK("EXIT v_ram_phys = 0x%8.8lx\n", (unsigned long)fix->smem_start);
-	return 0;
-}
-
-
-/*
- *	Fill the `par' structure based on the values in `var'.
- *	TODO: Verify and adjust values, return -EINVAL if bad.
- */
-
-static int virgefb_decode_var(struct fb_var_screeninfo *var,
-			    struct virgefb_par *par)
-{
-	DPRINTK("ENTER\n");
-	par->var.xres = var->xres;
-	par->var.yres = var->yres;
-	par->var.xres_virtual = var->xres_virtual;
-	par->var.yres_virtual = var->yres_virtual;
-	/* roundup and validate */
-	par->var.xres = (par->var.xres+7) & ~7;
-	par->var.xres_virtual = (par->var.xres_virtual+7) & ~7;
-	if (par->var.xres_virtual < par->var.xres)
-		par->var.xres_virtual = par->var.xres;
-	if (par->var.yres_virtual < par->var.yres)
-		par->var.yres_virtual = par->var.yres;
-	par->var.xoffset = var->xoffset;
-	par->var.yoffset = var->yoffset;
-	par->var.bits_per_pixel = var->bits_per_pixel;
-	if (par->var.bits_per_pixel <= 8)
-		par->var.bits_per_pixel = 8;
-	else if (par->var.bits_per_pixel <= 16)
-		par->var.bits_per_pixel = 16;
-	else
-		par->var.bits_per_pixel = 32;
-#ifndef FBCON_HAS_CFB32
-	if (par->var.bits_per_pixel == 32)
-		par->var.bits_per_pixel = 16;
-#endif
-#ifndef FBCON_HAS_CFB16
-	if (par->var.bits_per_pixel == 16)
-		par->var.bits_per_pixel = 8;
-#endif
-	par->var.grayscale = var->grayscale;
-	par->var.red = var->red;
-	par->var.green = var->green;
-	par->var.blue = var->blue;
-	par->var.transp = var->transp;
-	par->var.nonstd = var->nonstd;
-	par->var.activate = var->activate;
-	par->var.height = var->height;
-	par->var.width = var->width;
-	if (var->accel_flags & FB_ACCELF_TEXT) {
-		par->var.accel_flags = FB_ACCELF_TEXT;
-	} else {
-		par->var.accel_flags = 0;
-	}
-	par->var.pixclock = var->pixclock;
-	par->var.left_margin = var->left_margin;
-	par->var.right_margin = var->right_margin;
-	par->var.upper_margin = var->upper_margin;
-	par->var.lower_margin = var->lower_margin;
-	par->var.hsync_len = var->hsync_len;
-	par->var.vsync_len = var->vsync_len;
-	par->var.sync = var->sync;
-	par->var.vmode = var->vmode;
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-/*
- *	Fill the `var' structure based on the values in `par' and maybe
- *	other values read out of the hardware.
- */
-
-static int virgefb_encode_var(struct fb_var_screeninfo *var,
-				struct virgefb_par *par)
-{
-	DPRINTK("ENTER\n");
-	memset(var, 0, sizeof(struct fb_var_screeninfo));	/* need this ? */
-	var->xres = par->var.xres;
-	var->yres = par->var.yres;
-	var->xres_virtual = par->var.xres_virtual;
-	var->yres_virtual = par->var.yres_virtual;
-	var->xoffset = par->var.xoffset;
-	var->yoffset = par->var.yoffset;
-	var->bits_per_pixel = par->var.bits_per_pixel;
-	var->grayscale = par->var.grayscale;
-	var->red = par->var.red;
-	var->green = par->var.green;
-	var->blue = par->var.blue;
-	var->transp = par->var.transp;
-	var->nonstd = par->var.nonstd;
-	var->activate = par->var.activate;
-	var->height = par->var.height;
-	var->width = par->var.width;
-	var->accel_flags = par->var.accel_flags;
-	var->pixclock = par->var.pixclock;
-	var->left_margin = par->var.left_margin;
-	var->right_margin = par->var.right_margin;
-	var->upper_margin = par->var.upper_margin;
-	var->lower_margin = par->var.lower_margin;
-	var->hsync_len = par->var.hsync_len;
-	var->vsync_len = par->var.vsync_len;
-	var->sync = par->var.sync;
-	var->vmode = par->var.vmode;
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-/*
- *    Set a single color register. The values supplied are already
- *    rounded down to the hardware's capabilities (according to the
- *    entries in the var structure). Return != 0 for invalid regno.
- */
-
-static int virgefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	if (((current_par.var.bits_per_pixel==8) && (regno>255)) ||
-		((current_par.var.bits_per_pixel!=8) && (regno>15))) {
-			DPRINTK("EXIT\n");
-			return 1;
-	}
-	if (((current_par.var.bits_per_pixel==8) && (regno<256)) ||
-			((current_par.var.bits_per_pixel!=8) && (regno<16))) {
-		virgefb_colour_table [regno][0] = red >> 10;
-		virgefb_colour_table [regno][1] = green >> 10;
-		virgefb_colour_table [regno][2] = blue >> 10;
-	}
-
-	switch (current_par.var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-		case 8:
-			wb_mmio(VDAC_ADDRESS_W, (unsigned char)regno);
-			wb_mmio(VDAC_DATA, ((unsigned char)(red >> 10)));
-			wb_mmio(VDAC_DATA, ((unsigned char)(green >> 10)));
-			wb_mmio(VDAC_DATA, ((unsigned char)(blue >> 10)));
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16:
-			fbcon_cmap.cfb16[regno] =
-				((red  & 0xf800) |
-				((green & 0xfc00) >> 5) |
-				((blue  & 0xf800) >> 11));
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32:
-			fbcon_cmap.cfb32[regno] =
-				/* transp = 0's or 1's  ? */
-				(((red  & 0xff00) << 8) |
-				((green & 0xff00) >> 0) |
-				((blue  & 0xff00) >> 8));
-			break;
-#endif
-	}
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Read a single color register and split it into
- *    colors/transparent. Return != 0 for invalid regno.
- */
-
-static int virgefb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			   u_int *transp, struct fb_info *info)
-{
-	int t;
-
-	DPRINTK("ENTER\n");
-	if (regno > 255) {
-		DPRINTK("EXIT\n");
-		return 1;
-	}
-	if (((current_par.var.bits_per_pixel==8) && (regno<256)) ||
-			((current_par.var.bits_per_pixel!=8) && (regno<16))) {
-
-		t = virgefb_colour_table [regno][0];
-		*red = (t<<10) | (t<<4) | (t>>2);
-		t = virgefb_colour_table [regno][1];
-		*green = (t<<10) | (t<<4) | (t>>2);
-		t = virgefb_colour_table [regno][2];
-		*blue = (t<<10) | (t<<4) | (t>>2);
-	}
-	*transp = 0;
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    (Un)Blank the screen
- */
-
-static void virgefb_gfx_on_off(int blank)
-{
-	DPRINTK("ENTER\n");
-	gfx_on_off(blank);
-	DPRINTK("EXIT\n");
-}
-
-/*
- * CV3D low-level support
- */
-
-
-static inline void wait_3d_fifo_slots(int n)	/* WaitQueue */
-{
-	do {
-		mb();
-	} while (((rl_mmio(MR_SUBSYSTEM_STATUS_R) >> 8) & 0x1f) < (n + 2));
-}
-
-static inline void virgefb_wait_for_idle(void)	/* WaitIdle */
-{
-	while(!(rl_mmio(MR_SUBSYSTEM_STATUS_R) & 0x2000)) ;
-	blit_maybe_busy = 0;
-}
-
- /*
-  * BitBLT - Through the Plane
-  */
-
-static void virgefb_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
-			u_short width, u_short height, u_short stride, u_short depth)
-{
-	unsigned int blitcmd = S3V_BITBLT | S3V_DRAW | S3V_BLT_COPY;
-
-	switch (depth) {
-#ifdef FBCON_HAS_CFB8
-		case 8 :
-			blitcmd |= S3V_DST_8BPP;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16 :
-			blitcmd |= S3V_DST_16BPP;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32 :
-			/* 32 bit uses 2 by 16 bit values, see fbcon_virge32_bmove */
-			blitcmd |= S3V_DST_16BPP;
-			break;
-#endif
-	}
-
-	/* Set drawing direction */
-	/* -Y, X maj, -X (default) */
-	if (curx > destx) {
-		blitcmd |= (1 << 25);  /* Drawing direction +X */
-	} else {
-		curx  += (width - 1);
-		destx += (width - 1);
-	}
-
-	if (cury > desty) {
-		blitcmd |= (1 << 26);  /* Drawing direction +Y */
-	} else {
-		cury  += (height - 1);
-		desty += (height - 1);
-	}
-
-	wait_3d_fifo_slots(8);		/* wait on fifo slots for 8 writes */
-
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	blit_maybe_busy = 1;
-
-	wl_mmio(BLT_PATTERN_COLOR, 1);	/* pattern fb color */
-	wl_mmio(BLT_MONO_PATTERN_0, ~0);
-	wl_mmio(BLT_MONO_PATTERN_1, ~0);
-	wl_mmio(BLT_SIZE_X_Y, ((width << 16) | height));
-	wl_mmio(BLT_SRC_X_Y, ((curx << 16)  | cury));
-	wl_mmio(BLT_DEST_X_Y, ((destx << 16) | desty));
-	wl_mmio(BLT_SRC_DEST_STRIDE, (((stride << 16) | stride) /* & 0x0ff80ff8 */)); /* why is this needed now ? */
-	wl_mmio(BLT_COMMAND_SET, blitcmd);
-}
-
-/*
- * Rectangle Fill Solid
- */
-
-static void virgefb_RectFill(u_short x, u_short y, u_short width, u_short height,
-			u_short color,  u_short stride, u_short depth)
-{
-	unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW |
-		S3V_BLT_CLEAR | S3V_MONO_PAT | (1 << 26) | (1 << 25);
-
-	switch (depth) {
-#ifdef FBCON_HAS_CFB8
-		case 8 :
-			blitcmd |= S3V_DST_8BPP;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16 :
-			blitcmd |= S3V_DST_16BPP;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32 :
-			/* 32 bit uses 2 times 16 bit values, see fbcon_virge32_clear */
-			blitcmd |= S3V_DST_16BPP;
-			break;
-#endif
-	}
-
-	wait_3d_fifo_slots(5);		/* wait on fifo slots for 5 writes */
-
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	blit_maybe_busy = 1;
-
-	wl_mmio(BLT_PATTERN_COLOR, (color & 0xff));
-	wl_mmio(BLT_SIZE_X_Y, ((width << 16) | height));
-	wl_mmio(BLT_DEST_X_Y, ((x << 16) | y));
-	wl_mmio(BLT_SRC_DEST_STRIDE, (((stride << 16) | stride) /* & 0x0ff80ff8 */));
-	wl_mmio(BLT_COMMAND_SET, blitcmd);
-}
-
-/*
- * Move cursor to x, y
- */
-
-#if 0
-static void virgefb_move_cursor(u_short x, u_short y)
-{
-	DPRINTK("Yuck .... MoveCursor on a 3D\n");
-	return 0;
-}
-#endif
-
-/* -------------------- Interfaces to hardware functions -------------------- */
-
-static struct fb_hwswitch virgefb_hw_switch = {
-	.init		= virge_init,
-	.encode_fix	= virgefb_encode_fix,
-	.decode_var	= virgefb_decode_var,
-	.encode_var	= virgefb_encode_var,
-	.getcolreg	= virgefb_getcolreg,
-	.blank		= virgefb_gfx_on_off
-};
-
-
-/* -------------------- Generic routines ------------------------------------ */
-
-
-/*
- *    Fill the hardware's `par' structure.
- */
-
-static void virgefb_get_par(struct virgefb_par *par)
-{
-	DPRINTK("ENTER\n");
-	if (current_par_valid) {
-		*par = current_par;
-	} else {
-		fbhw->decode_var(&virgefb_default, par);
-	}
-	DPRINTK("EXIT\n");
-}
-
-
-static void virgefb_set_par(struct virgefb_par *par)
-{
-	DPRINTK("ENTER\n");
-	current_par = *par;
-	current_par_valid = 1;
-	DPRINTK("EXIT\n");
-}
-
-
-static void virgefb_set_video(struct fb_var_screeninfo *var)
-{
-/* Set clipping rectangle to current screen size */
-
-	unsigned int clip;
-
-	DPRINTK("ENTER\n");
-	wait_3d_fifo_slots(4);
-	clip = ((0 << 16) | (var->xres - 1));
-	wl_mmio(BLT_CLIP_LEFT_RIGHT, clip);
-	clip = ((0 << 16) | (var->yres - 1));
-	wl_mmio(BLT_CLIP_TOP_BOTTOM, clip);
-	wl_mmio(BLT_SRC_BASE, 0);		/* seems we need to clear these two */
-	wl_mmio(BLT_DEST_BASE, 0);
-
-/* Load the video mode defined by the 'var' data */
-
-	virgefb_load_video_mode(var);
-	DPRINTK("EXIT\n");
-}
-
-/*
-Merge these two functions, Geert's suggestion.
-static int virgefb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);
-static int virgefb_do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
-*/
-
-static int virgefb_do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
-{
-	int err, activate;
-	struct virgefb_par par;
-
-	DPRINTK("ENTER\n");
-	if ((err = fbhw->decode_var(var, &par))) {
-		DPRINTK("EXIT\n");
-		return (err);
-	}
-
-	activate = var->activate;
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
-		virgefb_set_par(&par);
-	fbhw->encode_var(var, &par);
-	var->activate = activate;
-        if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
-		virgefb_set_video(var);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Get the Fixed Part of the Display
- */
-
-static int virgefb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info)
-{
-	struct virgefb_par par;
-	int error = 0;
-
-	DPRINTK("ENTER\n");
-	if (con == -1)
-		virgefb_get_par(&par);
-	else
-		error = fbhw->decode_var(&fb_display[con].var, &par);
-
-	if (!error)
-		error = fbhw->encode_fix(fix, &par);
-	DPRINTK("EXIT\n");
-	return(error);
-}
-
-
-/*
- *    Get the User Defined Part of the Display
- */
-
-static int virgefb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	struct virgefb_par par;
-	int error = 0;
-
-	DPRINTK("ENTER\n");
-	if (con == -1) {
-		virgefb_get_par(&par);
-		error = fbhw->encode_var(var, &par);
-		disp.var = *var;   /* ++Andre: don't know if this is the right place */
-	} else {
-		*var = fb_display[con].var;
-	}
-	DPRINTK("EXIT\n");
-	return(error);
-}
-
-static void virgefb_set_disp(int con, struct fb_info *info)
-{
-	struct fb_fix_screeninfo fix;
-	struct display *display;
-
-	DPRINTK("ENTER\n");
-	if (con >= 0)
-		display = &fb_display[con];
-	else
-		display = &disp;	/* used during initialization */
-
-	virgefb_get_fix(&fix, con, info);
-	if (con == -1)
-		con = 0;
-	if(on_zorro2) {
-		info->screen_base = (char*)v_ram;
-	} else {
-	        switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-			case 8:
-				info->screen_base = (char*)(v_ram + CYBMEM_OFFSET_8);
-				break;
-#endif
-#ifdef FBCON_HAS_CFB16
-			case 16:
-				info->screen_base = (char*)(v_ram + CYBMEM_OFFSET_16);
-				break;
-#endif
-#ifdef FBCON_HAS_CFB32
-			case 32:
-				info->screen_base = (char*)(v_ram + CYBMEM_OFFSET_32);
-				break;
-#endif
-		}
-	}
-	display->visual = fix.visual;
-	display->type = fix.type;
-	display->type_aux = fix.type_aux;
-	display->ypanstep = fix.ypanstep;
-	display->ywrapstep = fix.ywrapstep;
-	display->can_soft_blank = 1;
-	display->inverse = virgefb_inverse;
-	display->line_length = display->var.xres_virtual*
-			       display->var.bits_per_pixel/8;
-
-	switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-		case 8:
-			if (display->var.accel_flags & FB_ACCELF_TEXT) {
-		   		display->dispsw = &fbcon_virge8;
-#warning FIXME: We should reinit the graphics engine here
-			} else
-				display->dispsw = &fbcon_cfb8;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16:
-			if (display->var.accel_flags & FB_ACCELF_TEXT) {
-				display->dispsw = &fbcon_virge16;
-			} else
-				display->dispsw = &fbcon_cfb16;
-			display->dispsw_data = &fbcon_cmap.cfb16;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32:
-			if (display->var.accel_flags & FB_ACCELF_TEXT) {
-				display->dispsw = &fbcon_virge32;
-			} else
-				display->dispsw = &fbcon_cfb32;
-			display->dispsw_data = &fbcon_cmap.cfb32;
-			break;
-#endif
-		default:
-			display->dispsw = &fbcon_dummy;
-			break;
-	}
-	DPRINTK("EXIT v_ram virt = 0x%8.8lx\n",(unsigned long)display->screen_base);
-}
-
-
-/*
- *    Set the User Defined Part of the Display
- */
-
-static int virgefb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
-
-	DPRINTK("ENTER\n");
-
-	if ((err = virgefb_do_fb_set_var(var, con == info->currcon))) {
-		DPRINTK("EXIT\n");
-		return(err);
-	}
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-		oldxres = fb_display[con].var.xres;
-		oldyres = fb_display[con].var.yres;
-		oldvxres = fb_display[con].var.xres_virtual;
-		oldvyres = fb_display[con].var.yres_virtual;
-		oldbpp = fb_display[con].var.bits_per_pixel;
-		oldaccel = fb_display[con].var.accel_flags;
-		fb_display[con].var = *var;
-		if (oldxres != var->xres || oldyres != var->yres ||
-		    oldvxres != var->xres_virtual ||
-		    oldvyres != var->yres_virtual ||
-		    oldbpp != var->bits_per_pixel ||
-		    oldaccel != var->accel_flags) {
-			virgefb_set_disp(con, info);
-			if (fb_info.changevar)
-				(*fb_info.changevar)(con);
-			fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
-			do_install_cmap(con, info);
-		}
-	}
-	var->activate = 0;
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Get the Colormap
- */
-
-static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			    struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	if (con == info->currcon) { /* current console? */
-		DPRINTK("EXIT - console is current console, fb_get_cmap\n");
-		return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
-	} else if (fb_display[con].cmap.len) { /* non default colormap? */
-		DPRINTK("Use console cmap\n");
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	} else {
-		DPRINTK("Use default cmap\n");
-		fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel==8 ? 256 : 16),
-			     cmap, kspc ? 0 : 2);
-	}
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-static struct fb_ops virgefb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	virgefb_get_fix,
-	.fb_get_var =	virgefb_get_var,
-	.fb_set_var =	virgefb_set_var,
-	.fb_get_cmap =	virgefb_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_setcolreg =	virgefb_setcolreg,
-	.fb_blank =	virgefb_blank,
-};
-
-int __init virgefb_setup(char *options)
-{
-	char *this_opt;
-	fb_info.fontname[0] = '\0';
-
-	DPRINTK("ENTER\n");
-	if (!options || !*options) {
-		DPRINTK("EXIT\n");
-		return 0;
-	}
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strcmp(this_opt, "inverse")) {
-			virgefb_inverse = 1;
-			fb_invert_cmaps();
-		} else if (!strncmp(this_opt, "font:", 5))
-			strcpy(fb_info.fontname, this_opt+5);
-#ifdef FBCON_HAS_CFB8
-		else if (!strcmp (this_opt, "virge8")){
-			virgefb_default = virgefb_predefined[VIRGE8_DEFMODE].var;
-		}
-#endif
-#ifdef FBCON_HAS_CFB16
-		else if (!strcmp (this_opt, "virge16")){
-			virgefb_default = virgefb_predefined[VIRGE16_DEFMODE].var;
-		}
-#endif
-#ifdef FBCON_HAS_CFB32
-		else if (!strcmp (this_opt, "virge32")){
-			virgefb_default = virgefb_predefined[VIRGE32_DEFMODE].var;
-		}
-#endif
-		else
-			virgefb_get_video_mode(this_opt);
-	}
-
-	printk(KERN_INFO "mode : xres=%d, yres=%d, bpp=%d\n", virgefb_default.xres,
-			virgefb_default.yres, virgefb_default.bits_per_pixel);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Get a Video Mode
- */
-
-static int __init virgefb_get_video_mode(const char *name)
-{
-	int i;
-
-	DPRINTK("ENTER\n");
-	for (i = 0; i < NUM_TOTAL_MODES; i++) {
-		if (!strcmp(name, virgefb_predefined[i].name)) {
-			virgefb_default = virgefb_predefined[i].var;
-			DPRINTK("EXIT\n");
-			return(i);
-		}
-	}
-	/* ++Andre: set virgefb default mode */
-
-/* prefer 16 bit depth, 8 if no 16, if no 8 or 16 use 32 */
-
-#ifdef FBCON_HAS_CFB32
-	virgefb_default = virgefb_predefined[VIRGE32_DEFMODE].var;
-#endif
-#ifdef FBCON_HAS_CFB8
-	virgefb_default = virgefb_predefined[VIRGE8_DEFMODE].var;
-#endif
-#ifdef FBCON_HAS_CFB16
-	virgefb_default = virgefb_predefined[VIRGE16_DEFMODE].var;
-#endif
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-/*
- *    Initialization
- */
-
-int __init virgefb_init(void)
-{
-	struct virgefb_par par;
-	unsigned long board_addr, board_size;
-	struct zorro_dev *z = NULL;
-
-	DPRINTK("ENTER\n");
-
-	z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64_3D, NULL);
-	if (!z)
-		return -ENODEV;
-
-	board_addr = z->resource.start;
-	if (board_addr < 0x01000000) {
-
-		/* board running in Z2 space. This includes the video memory
-		    as well as the S3 register set */
-
-		on_zorro2 = 1;
-		board_size = 0x00400000;
-
-		if (!request_mem_region(board_addr, board_size, "S3 ViRGE"))
-			return -ENOMEM;
-
-		v_ram_phys = board_addr;
-		v_ram = ZTWO_VADDR(v_ram_phys);
-		mmio_regs_phys = (unsigned long)(board_addr + 0x003c0000);
-		vgaio_regs = (unsigned char *) ZTWO_VADDR(board_addr + 0x003c0000);
-		mmio_regs = (unsigned char *)ZTWO_VADDR(mmio_regs_phys);
-		vcode_switch_base = (unsigned long) ZTWO_VADDR(board_addr + 0x003a0000);
-		printk(KERN_INFO "CV3D detected running in Z2 mode.\n");
-
-	} else {
-
-		/* board running in Z3 space. Separate video memory (3 apertures)
-		   and S3 register set */
-
-		on_zorro2 = 0;
-		board_size = 0x01000000;
-
-		if (!request_mem_region(board_addr, board_size, "S3 ViRGE"))
-			return -ENOMEM;
-
-		v_ram_phys  = board_addr + 0x04000000;
-		v_ram = (unsigned long)ioremap(v_ram_phys, 0x01000000);
-		mmio_regs_phys = board_addr + 0x05000000;
-		vgaio_regs = (unsigned char *)ioremap(board_addr +0x0c000000, 0x00100000); /* includes PCI regs */
-		mmio_regs = ioremap(mmio_regs_phys, 0x00010000);
-		vcode_switch_base = (unsigned long)ioremap(board_addr + 0x08000000, 0x1000);
-		printk(KERN_INFO "CV3D detected running in Z3 mode\n");
-	}
-
-#if defined (VIRGEFBDEBUG)
-	DPRINTK("board_addr     : 0x%8.8lx\n",board_addr);
-	DPRINTK("board_size     : 0x%8.8lx\n",board_size);
-	DPRINTK("mmio_regs_phy  : 0x%8.8lx\n",mmio_regs_phys);
-	DPRINTK("v_ram_phys     : 0x%8.8lx\n",v_ram_phys);
-	DPRINTK("vgaio_regs     : 0x%8.8lx\n",(unsigned long)vgaio_regs);
-	DPRINTK("mmio_regs      : 0x%8.8lx\n",(unsigned long)mmio_regs);
-	DPRINTK("v_ram          : 0x%8.8lx\n",v_ram);
-	DPRINTK("vcode sw base  : 0x%8.8lx\n",vcode_switch_base);
-#endif
-	fbhw = &virgefb_hw_switch;
-	strcpy(fb_info.modename, virgefb_name);
-	fb_info.changevar = NULL;
-	fb_info.fbops = &virgefb_ops;
-	fb_info.disp = &disp;
-	fb_info.currcon = -1;
-	fb_info.switch_con = &virgefb_switch;
-	fb_info.updatevar = &virgefb_updatevar;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
-	fbhw->init();
-	fbhw->decode_var(&virgefb_default, &par);
-	fbhw->encode_var(&virgefb_default, &par);
-	virgefb_do_fb_set_var(&virgefb_default, 1);
-	virgefb_get_var(&fb_display[0].var, -1, &fb_info);
-	virgefb_set_disp(-1, &fb_info);
-	do_install_cmap(0, &fb_info);
-
-	if (register_framebuffer(&fb_info) < 0) {
-		#warning release resources
-		printk(KERN_ERR "virgefb.c: register_framebuffer failed\n");
-		DPRINTK("EXIT\n");
-		goto out_unmap;
-	}
-
-	printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n",
-	       fb_info.node, fb_info.modename, v_ram_size>>10);
-
-	/* TODO: This driver cannot be unloaded yet */
-
-	DPRINTK("EXIT\n");
-	return 0;
-
-out_unmap:
-	if (board_addr >= 0x01000000) {
-		if (v_ram)
-			iounmap((void*)v_ram);
-		if (vgaio_regs)
-			iounmap(vgaio_regs);
-		if (mmio_regs)
-			iounmap(mmio_regs);
-		if (vcode_switch_base)
-			iounmap((void*)vcode_switch_base);
-		v_ram = vcode_switch_base = 0;
-		vgaio_regs = mmio_regs = NULL;
-	}
-	return -EINVAL;
-}
-
-
-static int virgefb_switch(int con, struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	/* Do we have to save the colormap? */
-	if (fb_display[info->currcon].cmap.len)
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1,
-			    fbhw->getcolreg, info);
-	virgefb_do_fb_set_var(&fb_display[con].var, 1);
-	info->currcon = con;
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Update the `var' structure (called by fbcon.c)
- *
- *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
- *    Since it's called by a kernel driver, no range checking is done.
- */
-
-static int virgefb_updatevar(int con, struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	return 0;
-	DPRINTK("EXIT\n");
-}
-
-/*
- *    Blank the display.
- */
-
-static int virgefb_blank(int blank, struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	fbhw->blank(blank);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static void fbcon_virge8_bmove(struct display *p, int sy, int sx, int dy,
-			       int dx, int height, int width)
-{
-        sx *= 8; dx *= 8; width *= 8;
-        virgefb_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
-                       (u_short)(dy*fontheight(p)), (u_short)width,
-                       (u_short)(height*fontheight(p)), (u_short)p->next_line, 8);
-}
-
-static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy,
-			       int sx, int height, int width)
-{
-        unsigned char bg;
-
-        sx *= 8; width *= 8;
-        bg = attr_bgcol_ec(p,conp);
-        virgefb_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
-                         (u_short)width, (u_short)(height*fontheight(p)),
-                         (u_short)bg, (u_short)p->next_line, 8);
-}
-
-static void fbcon_virge8_putc(struct vc_data *conp, struct display *p, int c, int yy,
-                              int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb8_putc(conp, p, c, yy, xx);
-}
-
-static void fbcon_virge8_putcs(struct vc_data *conp, struct display *p,
-                      const unsigned short *s, int count, int yy, int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
-}
-
-static void fbcon_virge8_revc(struct display *p, int xx, int yy)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb8_revc(p, xx, yy);
-}
-
-static void fbcon_virge8_clear_margins(struct vc_data *conp, struct display *p,
-                              int bottom_only)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb8_clear_margins(conp, p, bottom_only);
-}
-
-static struct display_switch fbcon_virge8 = {
-	.setup		= fbcon_cfb8_setup,
-	.bmove		= fbcon_virge8_bmove,
-	.clear		= fbcon_virge8_clear,
-	.putc		= fbcon_virge8_putc,
-	.putcs		= fbcon_virge8_putcs,
-	.revc		= fbcon_virge8_revc,
-	.clear_margins	= fbcon_virge8_clear_margins,
-	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-
-#ifdef FBCON_HAS_CFB16
-static void fbcon_virge16_bmove(struct display *p, int sy, int sx, int dy,
-                               int dx, int height, int width)
-{
-        sx *= 8; dx *= 8; width *= 8;
-        virgefb_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
-                       (u_short)(dy*fontheight(p)), (u_short)width,
-                       (u_short)(height*fontheight(p)), (u_short)p->next_line, 16);
-}
-
-static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy,
-                               int sx, int height, int width)
-{
-        unsigned char bg;
-
-        sx *= 8; width *= 8;
-        bg = attr_bgcol_ec(p,conp);
-        virgefb_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
-                         (u_short)width, (u_short)(height*fontheight(p)),
-                         (u_short)bg, (u_short)p->next_line, 16);
-}
-
-static void fbcon_virge16_putc(struct vc_data *conp, struct display *p, int c, int yy,
-                              int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb16_putc(conp, p, c, yy, xx);
-}
-
-static void fbcon_virge16_putcs(struct vc_data *conp, struct display *p,
-                      const unsigned short *s, int count, int yy, int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
-}
-
-static void fbcon_virge16_revc(struct display *p, int xx, int yy)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb16_revc(p, xx, yy);
-}
-
-static void fbcon_virge16_clear_margins(struct vc_data *conp, struct display *p,
-                              int bottom_only)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb16_clear_margins(conp, p, bottom_only);
-}
-
-static struct display_switch fbcon_virge16 = {
-	.setup		= fbcon_cfb16_setup,
-	.bmove		= fbcon_virge16_bmove,
-	.clear		= fbcon_virge16_clear,
-	.putc		= fbcon_virge16_putc,
-	.putcs		= fbcon_virge16_putcs,
-	.revc		= fbcon_virge16_revc,
-	.clear_margins	= fbcon_virge16_clear_margins,
-	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-
-#ifdef FBCON_HAS_CFB32
-static void fbcon_virge32_bmove(struct display *p, int sy, int sx, int dy,
-			       int dx, int height, int width)
-{
-        sx *= 16; dx *= 16; width *= 16;	/* doubled these values to do 32 bit blit */
-        virgefb_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
-                       (u_short)(dy*fontheight(p)), (u_short)width,
-                       (u_short)(height*fontheight(p)), (u_short)p->next_line, 16);
-}
-
-static void fbcon_virge32_clear(struct vc_data *conp, struct display *p, int sy,
-			       int sx, int height, int width)
-{
-        unsigned char bg;
-
-        sx *= 16; width *= 16;			/* doubled these values to do 32 bit blit */
-        bg = attr_bgcol_ec(p,conp);
-        virgefb_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
-                         (u_short)width, (u_short)(height*fontheight(p)),
-                         (u_short)bg, (u_short)p->next_line, 16);
-}
-
-static void fbcon_virge32_putc(struct vc_data *conp, struct display *p, int c, int yy,
-                              int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb32_putc(conp, p, c, yy, xx);
-}
-
-static void fbcon_virge32_putcs(struct vc_data *conp, struct display *p,
-                      const unsigned short *s, int count, int yy, int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
-}
-
-static void fbcon_virge32_revc(struct display *p, int xx, int yy)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb32_revc(p, xx, yy);
-}
-
-static void fbcon_virge32_clear_margins(struct vc_data *conp, struct display *p,
-                              int bottom_only)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb32_clear_margins(conp, p, bottom_only);
-}
-
-static struct display_switch fbcon_virge32 = {
-	.setup		= fbcon_cfb32_setup,
-	.bmove		= fbcon_virge32_bmove,
-	.clear		= fbcon_virge32_clear,
-	.putc		= fbcon_virge32_putc,
-	.putcs		= fbcon_virge32_putcs,
-	.revc		= fbcon_virge32_revc,
-	.clear_margins	= fbcon_virge32_clear_margins,
-	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return virgefb_init();
-}
-#endif /* MODULE */
-
-static int cv3d_has_4mb(void)
-{
-	/* cyberfb version didn't work, neither does this (not reliably)
-	forced to return 4MB */
-#if 0
-	volatile unsigned long *t0, *t2;
-#endif
-	DPRINTK("ENTER\n");
-#if 0
-	/* write patterns in memory and test if they can be read */
-	t0 = (volatile unsigned long *)v_ram;
-	t2 = (volatile unsigned long *)(v_ram + 0x00200000);
-	*t0 = 0x87654321;
-	*t2 = 0x12345678;
-
-	if (*t0 != 0x87654321) {
-		/* read of first location failed */
-		DPRINTK("EXIT - 0MB !\n");
-		return 0;
-	}
-
-	if (*t2 == 0x87654321) {
-		/* should read 0x12345678 if 4MB */
-		DPRINTK("EXIT - 2MB(a) \n");
-		return 0;
-	}
-
-	if (*t2 != 0x12345678) {
-		/* upper 2MB read back match failed */
-		DPRINTK("EXIT - 2MB(b)\n");
-		return 0;
-	}
-
-	/* may have 4MB */
-
-	*t2 = 0xAAAAAAAA;
-
-	if(*t2 != 0xAAAAAAAA) {
-		/* upper 2MB read back match failed */
-		DPRINTK("EXIT - 2MB(c)\n");
-		return 0;
-	}
-
-	*t2 = 0x55555555;
-
-	if(*t2 != 0x55555555) {
-		/* upper 2MB read back match failed */
-		DPRINTK("EXIT - 2MB(d)\n");
-		return 0;
-	}
-
-#endif
-	DPRINTK("EXIT - 4MB\n");
-	return 1;
-}
-
-
-/*
- * Computes M, N, and R pll params for freq arg.
- * Returns 16 bits - hi 0MMMMMM lo 0RRNNNNN
- */
-
-#define REFCLOCK 14318000
-
-static unsigned short virgefb_compute_clock(unsigned long freq)
-{
-
-	unsigned char m, n, r, rpwr;
-	unsigned long diff, ftry, save = ~0UL;
-	unsigned short mnr;
-
-	DPRINTK("ENTER\n");
-
-	for (r = 0, rpwr = 1 ; r < 4 ; r++, rpwr *= 2) {
-		if ((135000000 <= (rpwr * freq)) && ((rpwr * freq) <= 270000000)) {
-			for (n = 1 ; n < 32 ; n++) {
-				m = ((freq * (n + 2) * rpwr)/REFCLOCK) - 2;
-				if (m == 0 || m >127)
-					break;
-				ftry = ((REFCLOCK / (n + 2)) * (m + 2)) / rpwr;
-				if (ftry > freq)
-					diff = ftry - freq;
-				else
-					diff = freq - ftry;
-				if (diff < save) {
-					save = diff;
-					mnr =  (m << 8) | (r<<5) | (n & 0x7f);
-				}
-			}
-		}
-	}
-	if (save == ~0UL)
-		printk("Can't compute clock PLL values for %ld Hz clock\n", freq);
-	DPRINTK("EXIT\n");
-	return(mnr);
-}
-
-static void virgefb_load_video_mode(struct fb_var_screeninfo *video_mode)
-{
-	unsigned char lace, dblscan, tmp;
-	unsigned short mnr;
-	unsigned short HT, HDE, HBS, HBW, HSS, HSW;
-	unsigned short VT, VDE, VBS, VBW, VSS, VSW;
-	unsigned short SCO;
-	int cr11;
-	int cr67;
-	int hmul;
-	int xres, xres_virtual, hfront, hsync, hback;
-	int yres, vfront, vsync, vback;
-	int bpp;
-	int i;
-	long freq;
-
-	DPRINTK("ENTER : %dx%d-%d\n",video_mode->xres, video_mode->yres,
-				video_mode->bits_per_pixel);
-
-	bpp = video_mode->bits_per_pixel;
-	xres = video_mode->xres;
-	xres_virtual = video_mode->xres_virtual;
-	hfront = video_mode->right_margin;
-	hsync = video_mode->hsync_len;
-	hback = video_mode->left_margin;
-
-	lace = 0;
-	dblscan = 0;
-
-	if (video_mode->vmode & FB_VMODE_DOUBLE) {
-		yres = video_mode->yres * 2;
-		vfront = video_mode->lower_margin * 2;
-		vsync = video_mode->vsync_len * 2;
-		vback = video_mode->upper_margin * 2;
-		dblscan = 1;
-	} else if (video_mode->vmode & FB_VMODE_INTERLACED) {
-		yres = (video_mode->yres + 1) / 2;
-		vfront = (video_mode->lower_margin + 1) / 2;
-		vsync = (video_mode->vsync_len + 1) / 2;
-		vback = (video_mode->upper_margin + 1) / 2;
-		lace = 1;
-	} else {
-		yres = video_mode->yres;
-		vfront = video_mode->lower_margin;
-		vsync = video_mode->vsync_len;
-		vback = video_mode->upper_margin;
-	}
-
-	switch (bpp) {
-		case 8:
-			video_mode->red.offset = 0;
-			video_mode->green.offset = 0;
-			video_mode->blue.offset = 0;
-			video_mode->transp.offset = 0;
-			video_mode->red.length = 8;
-			video_mode->green.length = 8;
-			video_mode->blue.length = 8;
-			video_mode->transp.length = 0;
-			hmul = 1;
-			cr67 = 0x00;
-			SCO = xres_virtual / 8;
-			break;
-		case 16:
-			video_mode->red.offset = 11;
-			video_mode->green.offset = 5;
-			video_mode->blue.offset = 0;
-			video_mode->transp.offset = 0;
-			video_mode->red.length = 5;
-			video_mode->green.length = 6;
-			video_mode->blue.length = 5;
-			video_mode->transp.length = 0;
-			hmul = 2;
-			cr67 = 0x50;
-			SCO = xres_virtual / 4;
-			break;
-		case 32:
-			video_mode->red.offset = 16;
-			video_mode->green.offset = 8;
-			video_mode->blue.offset = 0;
-			video_mode->transp.offset = 24;
-			video_mode->red.length = 8;
-			video_mode->green.length = 8;
-			video_mode->blue.length = 8;
-			video_mode->transp.length = 8;
-			hmul = 1;
-			cr67 = 0xd0;
-			SCO = xres_virtual / 2;
-			break;
-	}
-
-	HT  = (((xres + hfront + hsync + hback) / 8) * hmul) - 5;
-	HDE = ((xres / 8) * hmul) - 1;
-	HBS = (xres / 8) * hmul;
-	HSS = ((xres + hfront) / 8) * hmul;
-	HSW = (hsync / 8) * hmul;
-	HBW = (((hfront + hsync + hback) / 8) * hmul) - 2;
-
-	VT  = yres + vfront + vsync + vback - 2;
-	VDE = yres - 1;
-	VBS = yres - 1;
-	VSS = yres + vfront;
-	VSW = vsync;
-	VBW = vfront + vsync + vback - 2;
-
-#ifdef VIRGEFBDEBUG
-	DPRINTK("HDE       : 0x%4.4x, %4.4d\n", HDE, HDE);
-	DPRINTK("HBS       : 0x%4.4x, %4.4d\n", HBS, HBS);
-	DPRINTK("HSS       : 0x%4.4x, %4.4d\n", HSS, HSS);
-	DPRINTK("HSW       : 0x%4.4x, %4.4d\n", HSW, HSW);
-	DPRINTK("HBW       : 0x%4.4x, %4.4d\n", HBW, HBW);
-	DPRINTK("HSS + HSW : 0x%4.4x, %4.4d\n", HSS+HSW, HSS+HSW);
-	DPRINTK("HBS + HBW : 0x%4.4x, %4.4d\n", HBS+HBW, HBS+HBW);
-	DPRINTK("HT        : 0x%4.4x, %4.4d\n", HT, HT);
-	DPRINTK("VDE       : 0x%4.4x, %4.4d\n", VDE, VDE);
-	DPRINTK("VBS       : 0x%4.4x, %4.4d\n", VBS, VBS);
-	DPRINTK("VSS       : 0x%4.4x, %4.4d\n", VSS, VSS);
-	DPRINTK("VSW       : 0x%4.4x, %4.4d\n", VSW, VSW);
-	DPRINTK("VBW       : 0x%4.4x, %4.4d\n", VBW, VBW);
-	DPRINTK("VT        : 0x%4.4x, %4.4d\n", VT, VT);
-#endif
-
-/* turn gfx off, don't mess up the display */
-
- 	gfx_on_off(1);
-
-/* H and V sync polarity */
-
-	tmp = rb_mmio(GREG_MISC_OUTPUT_R) & 0x2f;		/* colour, ram enable, clk sr12/s13 sel */
-	if (!(video_mode->sync & FB_SYNC_HOR_HIGH_ACT))
-		tmp |= 0x40;					/* neg H sync polarity */
-	if (!(video_mode->sync & FB_SYNC_VERT_HIGH_ACT))
-		tmp |= 0x80;					/* neg V sync polarity */
-	tmp |= 0x0c;						/* clk from sr12/sr13 */
-	wb_mmio(GREG_MISC_OUTPUT_W, tmp);
-
-/* clocks */
-
-	wseq(SEQ_ID_BUS_REQ_CNTL, 0xc0);			/* 2 clk mem wr and /RAS1 */
-	wseq(SEQ_ID_CLKSYN_CNTL_2, 0x80);			/* b7 is 2 mem clk wr */
-	mnr = virgefb_compute_clock(MEMCLOCK);
-	DPRINTK("mem clock %d, m %d, n %d, r %d.\n", MEMCLOCK, ((mnr>>8)&0x7f), (mnr&0x1f), ((mnr >> 5)&0x03));
-	wseq(SEQ_ID_MCLK_LO, (mnr & 0x7f));
-	wseq(SEQ_ID_MCLK_HI, ((mnr & 0x7f00) >> 8));
-	freq = (1000000000 / video_mode->pixclock) * 1000;	/* pixclock is in ps ... convert to Hz */
-	mnr = virgefb_compute_clock(freq);
-	DPRINTK("dot clock %ld, m %d, n %d, r %d.\n", freq, ((mnr>>8)&0x7f), (mnr&0x1f), ((mnr>>5)&0x03));
-	wseq(SEQ_ID_DCLK_LO, (mnr & 0x7f));
-	wseq(SEQ_ID_DCLK_HI, ((mnr & 0x7f00) >> 8));
-	wseq(SEQ_ID_CLKSYN_CNTL_2, 0xa0);
-	wseq(SEQ_ID_CLKSYN_CNTL_2, 0x80);
-	udelay(100);
-
-/* load display parameters into board */
-
-	/* not sure about sync and blanking extensions bits in cr5d and cr5 */
-
-	wcrt(CRT_ID_EXT_HOR_OVF,			/* 0x5d */
-		((HT & 0x100) ?         0x01 : 0x00) |
-		((HDE & 0x100) ?        0x02 : 0x00) |
-		((HBS & 0x100) ?        0x04 : 0x00) |
-	/*	(((HBS + HBW) & 0x40) ? 0x08 : 0x00) |	*/
-		((HSS & 0x100) ?        0x10 : 0x00) |
-	/*	(((HSS + HSW) & 0x20) ? 0x20 : 0x00) |	*/
-		((HSW >= 0x20) ?        0x20 : 0x00) |
-		(((HT-5) & 0x100) ?     0x40 : 0x00));
-
-	wcrt(CRT_ID_EXT_VER_OVF,			/* 0x5e */
-		((VT & 0x400) ? 0x01 : 0x00) |
-		((VDE & 0x400) ? 0x02 : 0x00) |
-		((VBS & 0x400) ? 0x04 : 0x00) |
-		((VSS & 0x400) ? 0x10 : 0x00) |
-		0x40);					/* line compare */
-
-	wcrt(CRT_ID_START_VER_RETR, VSS);
-	cr11 = rcrt(CRT_ID_END_VER_RETR) | 0x20;	/* vert interrupt flag */
-	wcrt(CRT_ID_END_VER_RETR, ((cr11 & 0x20) | ((VSS + VSW) & 0x0f)));	/* keeps vert irq enable state, also has unlock bit cr0 to 7 */
-	wcrt(CRT_ID_VER_DISP_ENA_END, VDE);
-	wcrt(CRT_ID_START_VER_BLANK, VBS);
-	wcrt(CRT_ID_END_VER_BLANK, VBS + VBW);		/* might be +/- 1 out */
-	wcrt(CRT_ID_HOR_TOTAL, HT);
-	wcrt(CRT_ID_DISPLAY_FIFO, HT - 5);
-	wcrt(CRT_ID_BACKWAD_COMP_3, 0x10);		/* enable display fifo */
-	wcrt(CRT_ID_HOR_DISP_ENA_END, HDE);
-	wcrt(CRT_ID_START_HOR_BLANK , HBS);
-	wcrt(CRT_ID_END_HOR_BLANK, (HBS + HBW) & 0x1f);
-	wcrt(CRT_ID_START_HOR_RETR, HSS);
-	wcrt(CRT_ID_END_HOR_RETR,			/* cr5 */
-		((HSS + HSW) & 0x1f) |
-		(((HBS + HBW) & 0x20) ? 0x80 : 0x00));
-	wcrt(CRT_ID_VER_TOTAL, VT);
-	wcrt(CRT_ID_OVERFLOW,
-		((VT & 0x100) ? 0x01 : 0x00) |
-		((VDE & 0x100) ? 0x02 : 0x00) |
-		((VSS & 0x100) ? 0x04 : 0x00) |
-		((VBS & 0x100) ? 0x08 : 0x00) |
-		0x10 |
-		((VT & 0x200) ? 0x20 : 0x00) |
-		((VDE & 0x200) ? 0x40 : 0x00) |
-		((VSS & 0x200) ? 0x80 : 0x00));
-	wcrt(CRT_ID_MAX_SCAN_LINE,
-		(dblscan ? 0x80 : 0x00) |
-		0x40 |
-		((VBS & 0x200) ? 0x20 : 0x00));
-	wcrt(CRT_ID_LINE_COMPARE, 0xff);
-	wcrt(CRT_ID_LACE_RETR_START, HT / 2);		/* (HT-5)/2 ? */
-	wcrt(CRT_ID_LACE_CONTROL, (lace ? 0x20 : 0x00));
-
-	wcrt(CRT_ID_SCREEN_OFFSET, SCO);
-	wcrt(CRT_ID_EXT_SYS_CNTL_2, (SCO >> 4) & 0x30 );
-
-	/* wait for vert sync before cr67 update */
-
-	for (i=0; i < 10000; i++) {
-		udelay(10);
-		mb();
-		if (rb_mmio(GREG_INPUT_STATUS1_R) & 0x08)
-			break;
-	}
-
-	wl_mmio(0x8200, 0x0000c000);	/* fifo control  (0x00110400 ?) */
-	wcrt(CRT_ID_EXT_MISC_CNTL_2, cr67);
-
-/* enable video */
-
-	tmp = rb_mmio(ACT_ADDRESS_RESET);
-	wb_mmio(ACT_ADDRESS_W, ((bpp == 8) ? 0x20 : 0x00));	/* set b5, ENB PLT in attr idx reg) */
-	tmp = rb_mmio(ACT_ADDRESS_RESET);
-
-/* turn gfx on again */
-
-	gfx_on_off(0);
-
-/* pass-through */
-
-	SetVSwitch(1);		/* cv3d */
-
-	DUMP;
-	DPRINTK("EXIT\n");
-}
-
-static inline void gfx_on_off(int toggle)
-{
-	unsigned char tmp;
-
-	DPRINTK("ENTER gfx %s\n", (toggle ? "off" : "on"));
-
-	toggle = (toggle & 0x01) << 5;
-	tmp = rseq(SEQ_ID_CLOCKING_MODE) & (~(0x01 << 5));
-	wseq(SEQ_ID_CLOCKING_MODE, tmp | toggle);
-
-	DPRINTK("EXIT\n");
-}
-
-#if defined (VIRGEFBDUMP)
-
-/*
- * Dump board registers
- */
-
-static void cv64_dump(void)
-{
-	int i;
-	u8 c, b;
-        u16 w;
-	u32 l;
-
-	/* crt, seq, gfx and atr regs */
-
-	SelectMMIO;
-
-	printk("\n");
-	for (i = 0; i <= 0x6f; i++) {
-		wb_mmio(CRT_ADDRESS, i);
-		printk("crt idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(CRT_ADDRESS_R));
-	}
-	for (i = 0; i <= 0x1c; i++) {
-		wb_mmio(SEQ_ADDRESS, i);
-		printk("seq idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(SEQ_ADDRESS_R));
-	}
-	for (i = 0; i <= 8; i++) {
-		wb_mmio(GCT_ADDRESS, i);
-		printk("gfx idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(GCT_ADDRESS_R));
-	}
-	for (i = 0; i <= 0x14; i++) {
-		c = rb_mmio(ACT_ADDRESS_RESET);
-		wb_mmio(ACT_ADDRESS_W, i);
-		printk("atr idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(ACT_ADDRESS_R));
-	}
-
-	/* re-enable video access to palette */
-
-	c = rb_mmio(ACT_ADDRESS_RESET);
-	udelay(10);
-	wb_mmio(ACT_ADDRESS_W, 0x20);
-	c = rb_mmio(ACT_ADDRESS_RESET);
-	udelay(10);
-
-	/* general regs */
-
-	printk("0x3cc(w 0x3c2) : 0x%2.2x\n", rb_mmio(0x3cc));	/* GREG_MISC_OUTPUT READ */
-	printk("0x3c2(-------) : 0x%2.2x\n", rb_mmio(0x3c2));	/* GREG_INPUT_STATUS 0 READ */
-	printk("0x3c3(w 0x3c3) : 0x%2.2x\n", rb_vgaio(0x3c3));	/* GREG_VIDEO_SUBS_ENABLE */
-	printk("0x3ca(w 0x3da) : 0x%2.2x\n", rb_vgaio(0x3ca));	/* GREG_FEATURE_CONTROL read */
-	printk("0x3da(-------) : 0x%2.2x\n", rb_mmio(0x3da));	/* GREG_INPUT_STATUS 1 READ */
-
-	/* engine regs */
-
-	for (i = 0x8180; i <= 0x8200; i = i + 4)
-		printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
-
-	i = 0x8504;
-	printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
-	i = 0x850c;
-	printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
-	for (i = 0xa4d4; i <= 0xa50c; i = i + 4)
-		printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
-
-	/* PCI regs */
-
-	SelectCFG;
-
-	for (c = 0; c < 0x08; c = c + 2) {
-		w = (*((u16 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 2)));
-		printk("pci 0x%2.2x : 0x%4.4x\n", c, w);
-	}
-	c = 8;
-	l = (*((u32 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)))));
-	printk("pci 0x%2.2x : 0x%8.8x\n", c, l);
-	c = 0x0d;
-	b = (*((u8 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 3)));
-	printk("pci 0x%2.2x : 0x%2.2x\n", c, b);
-	c = 0x10;
-	l = (*((u32 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)))));
-	printk("pci 0x%2.2x : 0x%8.8x\n", c, l);
-	c = 0x30;
-	l = (*((u32 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)))));
-	printk("pci 0x%2.2x : 0x%8.8x\n", c, l);
-	c = 0x3c;
-	b = (*((u8 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 3)));
-	printk("pci 0x%2.2x : 0x%2.2x\n", c, b);
-	c = 0x3d;
-	b = (*((u8 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 3)));
-	printk("pci 0x%2.2x : 0x%2.2x\n", c, b);
-	c = 0x3e;
-	w = (*((u16 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 2)));
-	printk("pci 0x%2.2x : 0x%4.4x\n", c, w);
-	SelectMMIO;
-}
-#endif
diff --git a/drivers/video/virgefb.h b/drivers/video/virgefb.h
deleted file mode 100644
index 157d66d..0000000
--- a/drivers/video/virgefb.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * linux/drivers/video/virgefb.h -- CyberVision64 definitions for the
- *                                  text console driver.
- *
- *   Copyright (c) 1998 Alan Bair
- *
- * This file is based on the initial port to Linux of grf_cvreg.h:
- *
- *   Copyright (c) 1997 Antonio Santos
- *
- * The original work is from the NetBSD CyberVision 64 framebuffer driver 
- * and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):
- * Permission to use the source of this driver was obtained from the
- * author Michael Teske by Alan Bair.
- *
- *   Copyright (c) 1995 Michael Teske
- *
- * History:
- *
- *
- *
- * 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.
- */
-
-/* Enhanced register mapping (MMIO mode) */
-
-#define S3_CRTC_ADR    0x03d4
-#define S3_CRTC_DATA   0x03d5
-
-#define S3_REG_LOCK2	0x39
-#define S3_HGC_MODE	0x45
-
-#define S3_HWGC_ORGX_H	0x46
-#define S3_HWGC_ORGX_L	0x47
-#define S3_HWGC_ORGY_H	0x48
-#define S3_HWGC_ORGY_L	0x49
-#define S3_HWGC_DX	0x4e
-#define S3_HWGC_DY	0x4f
-
-#define S3_LAW_CTL	0x58
-
-/**************************************************/
-
-/*
- * Defines for the used register addresses (mw)
- *
- * NOTE: There are some registers that have different addresses when
- *       in mono or color mode. We only support color mode, and thus
- *       some addresses won't work in mono-mode!
- *
- * General and VGA-registers taken from retina driver. Fixed a few
- * bugs in it. (SR and GR read address is Port + 1, NOT Port)
- *
- */
-
-/* General Registers: */
-#define GREG_MISC_OUTPUT_R	0x03CC
-#define GREG_MISC_OUTPUT_W	0x03C2	
-#define GREG_FEATURE_CONTROL_R	0x03CA 
-#define GREG_FEATURE_CONTROL_W	0x03DA
-#define GREG_INPUT_STATUS0_R	0x03C2
-#define GREG_INPUT_STATUS1_R	0x03DA
-
-/* Setup Registers: */
-#define SREG_VIDEO_SUBS_ENABLE	0x03C3	/* virge */
-
-/* Attribute Controller: */
-#define ACT_ADDRESS		0x03C0
-#define ACT_ADDRESS_R		0x03C1
-#define ACT_ADDRESS_W		0x03C0
-#define ACT_ADDRESS_RESET	0x03DA
-#define ACT_ID_PALETTE0		0x00
-#define ACT_ID_PALETTE1		0x01
-#define ACT_ID_PALETTE2		0x02
-#define ACT_ID_PALETTE3		0x03
-#define ACT_ID_PALETTE4		0x04
-#define ACT_ID_PALETTE5		0x05
-#define ACT_ID_PALETTE6		0x06
-#define ACT_ID_PALETTE7		0x07
-#define ACT_ID_PALETTE8		0x08
-#define ACT_ID_PALETTE9		0x09
-#define ACT_ID_PALETTE10	0x0A
-#define ACT_ID_PALETTE11	0x0B
-#define ACT_ID_PALETTE12	0x0C
-#define ACT_ID_PALETTE13	0x0D
-#define ACT_ID_PALETTE14	0x0E
-#define ACT_ID_PALETTE15	0x0F
-#define ACT_ID_ATTR_MODE_CNTL	0x10
-#define ACT_ID_OVERSCAN_COLOR	0x11
-#define ACT_ID_COLOR_PLANE_ENA	0x12
-#define ACT_ID_HOR_PEL_PANNING	0x13
-#define ACT_ID_COLOR_SELECT	0x14    /* virge PX_PADD  pixel padding register */
-
-/* Graphics Controller: */
-#define GCT_ADDRESS		0x03CE
-#define GCT_ADDRESS_R		0x03CF
-#define GCT_ADDRESS_W		0x03CF
-#define GCT_ID_SET_RESET	0x00
-#define GCT_ID_ENABLE_SET_RESET	0x01
-#define GCT_ID_COLOR_COMPARE	0x02
-#define GCT_ID_DATA_ROTATE	0x03
-#define GCT_ID_READ_MAP_SELECT	0x04
-#define GCT_ID_GRAPHICS_MODE	0x05
-#define GCT_ID_MISC		0x06
-#define GCT_ID_COLOR_XCARE	0x07
-#define GCT_ID_BITMASK		0x08
-
-/* Sequencer: */
-#define SEQ_ADDRESS		0x03C4
-#define SEQ_ADDRESS_R		0x03C5
-#define SEQ_ADDRESS_W		0x03C5
-#define SEQ_ID_RESET		0x00
-#define SEQ_ID_CLOCKING_MODE	0x01
-#define SEQ_ID_MAP_MASK		0x02
-#define SEQ_ID_CHAR_MAP_SELECT	0x03
-#define SEQ_ID_MEMORY_MODE	0x04
-#define SEQ_ID_UNKNOWN1		0x05
-#define SEQ_ID_UNKNOWN2		0x06
-#define SEQ_ID_UNKNOWN3		0x07
-/* S3 extensions */
-#define SEQ_ID_UNLOCK_EXT	0x08
-#define SEQ_ID_EXT_SEQ_REG9	0x09	/* b7 = 1 extended reg access by MMIO only */
-#define SEQ_ID_BUS_REQ_CNTL	0x0A
-#define SEQ_ID_EXT_MISC_SEQ	0x0B
-#define SEQ_ID_UNKNOWN4		0x0C
-#define SEQ_ID_EXT_SEQ		0x0D
-#define SEQ_ID_UNKNOWN5		0x0E
-#define SEQ_ID_UNKNOWN6		0x0F
-#define SEQ_ID_MCLK_LO		0x10
-#define SEQ_ID_MCLK_HI		0x11
-#define SEQ_ID_DCLK_LO		0x12
-#define SEQ_ID_DCLK_HI		0x13
-#define SEQ_ID_CLKSYN_CNTL_1	0x14
-#define SEQ_ID_CLKSYN_CNTL_2	0x15
-#define SEQ_ID_CLKSYN_TEST_HI	0x16	/* reserved for S3 testing of the */
-#define SEQ_ID_CLKSYN_TEST_LO	0x17	/* internal clock synthesizer   */
-#define SEQ_ID_RAMDAC_CNTL	0x18
-#define SEQ_ID_MORE_MAGIC	0x1A
-#define SEQ_ID_SIGNAL_SELECT	0x1C	/* new for virge */
-
-/* CRT Controller: */
-#define CRT_ADDRESS		0x03D4
-#define CRT_ADDRESS_R		0x03D5
-#define CRT_ADDRESS_W		0x03D5
-#define CRT_ID_HOR_TOTAL	0x00
-#define CRT_ID_HOR_DISP_ENA_END	0x01
-#define CRT_ID_START_HOR_BLANK	0x02
-#define CRT_ID_END_HOR_BLANK	0x03
-#define CRT_ID_START_HOR_RETR	0x04
-#define CRT_ID_END_HOR_RETR	0x05
-#define CRT_ID_VER_TOTAL	0x06
-#define CRT_ID_OVERFLOW		0x07
-#define CRT_ID_PRESET_ROW_SCAN	0x08
-#define CRT_ID_MAX_SCAN_LINE	0x09
-#define CRT_ID_CURSOR_START	0x0A
-#define CRT_ID_CURSOR_END	0x0B
-#define CRT_ID_START_ADDR_HIGH	0x0C
-#define CRT_ID_START_ADDR_LOW	0x0D
-#define CRT_ID_CURSOR_LOC_HIGH	0x0E
-#define CRT_ID_CURSOR_LOC_LOW	0x0F
-#define CRT_ID_START_VER_RETR	0x10
-#define CRT_ID_END_VER_RETR	0x11
-#define CRT_ID_VER_DISP_ENA_END	0x12
-#define CRT_ID_SCREEN_OFFSET	0x13
-#define CRT_ID_UNDERLINE_LOC	0x14
-#define CRT_ID_START_VER_BLANK	0x15
-#define CRT_ID_END_VER_BLANK	0x16
-#define CRT_ID_MODE_CONTROL	0x17
-#define CRT_ID_LINE_COMPARE	0x18
-#define CRT_ID_GD_LATCH_RBACK	0x22
-#define CRT_ID_ACT_TOGGLE_RBACK	0x24
-#define CRT_ID_ACT_INDEX_RBACK	0x26
-/* S3 extensions: S3 VGA Registers */
-#define CRT_ID_DEVICE_HIGH	0x2D
-#define CRT_ID_DEVICE_LOW	0x2E
-#define CRT_ID_REVISION 	0x2F
-#define CRT_ID_CHIP_ID_REV	0x30
-#define CRT_ID_MEMORY_CONF	0x31
-#define CRT_ID_BACKWAD_COMP_1	0x32
-#define CRT_ID_BACKWAD_COMP_2	0x33
-#define CRT_ID_BACKWAD_COMP_3	0x34
-#define CRT_ID_REGISTER_LOCK	0x35
-#define CRT_ID_CONFIG_1 	0x36
-#define CRT_ID_CONFIG_2 	0x37
-#define CRT_ID_REGISTER_LOCK_1	0x38
-#define CRT_ID_REGISTER_LOCK_2	0x39
-#define CRT_ID_MISC_1		0x3A
-#define CRT_ID_DISPLAY_FIFO	0x3B
-#define CRT_ID_LACE_RETR_START	0x3C
-/* S3 extensions: System Control Registers  */
-#define CRT_ID_SYSTEM_CONFIG	0x40
-#define CRT_ID_BIOS_FLAG	0x41
-#define CRT_ID_LACE_CONTROL	0x42
-#define CRT_ID_EXT_MODE 	0x43
-#define CRT_ID_HWGC_MODE	0x45	/* HWGC = Hardware Graphics Cursor */
-#define CRT_ID_HWGC_ORIGIN_X_HI	0x46
-#define CRT_ID_HWGC_ORIGIN_X_LO	0x47
-#define CRT_ID_HWGC_ORIGIN_Y_HI	0x48
-#define CRT_ID_HWGC_ORIGIN_Y_LO	0x49
-#define CRT_ID_HWGC_FG_STACK	0x4A
-#define CRT_ID_HWGC_BG_STACK	0x4B
-#define CRT_ID_HWGC_START_AD_HI	0x4C
-#define CRT_ID_HWGC_START_AD_LO	0x4D
-#define CRT_ID_HWGC_DSTART_X	0x4E
-#define CRT_ID_HWGC_DSTART_Y	0x4F
-/* S3 extensions: System Extension Registers  */
-#define CRT_ID_EXT_SYS_CNTL_1	0x50	/* NOT a virge register */
-#define CRT_ID_EXT_SYS_CNTL_2	0x51
-#define CRT_ID_EXT_BIOS_FLAG_1	0x52
-#define CRT_ID_EXT_MEM_CNTL_1	0x53
-#define CRT_ID_EXT_MEM_CNTL_2	0x54
-#define CRT_ID_EXT_DAC_CNTL	0x55
-#define CRT_ID_EX_SYNC_1	0x56
-#define CRT_ID_EX_SYNC_2	0x57
-#define CRT_ID_LAW_CNTL		0x58	/* LAW = Linear Address Window */
-#define CRT_ID_LAW_POS_HI	0x59
-#define CRT_ID_LAW_POS_LO	0x5A
-#define CRT_ID_GOUT_PORT	0x5C
-#define CRT_ID_EXT_HOR_OVF	0x5D
-#define CRT_ID_EXT_VER_OVF	0x5E
-#define CRT_ID_EXT_MEM_CNTL_3	0x60	/* NOT a virge register */
-#define CRT_ID_EXT_MEM_CNTL_4	0x61
-#define CRT_ID_EX_SYNC_3	0x63	/* NOT a virge register */
-#define CRT_ID_EXT_MISC_CNTL	0x65
-#define CRT_ID_EXT_MISC_CNTL_1	0x66
-#define CRT_ID_EXT_MISC_CNTL_2	0x67
-#define CRT_ID_CONFIG_3 	0x68
-#define CRT_ID_EXT_SYS_CNTL_3	0x69
-#define CRT_ID_EXT_SYS_CNTL_4	0x6A
-#define CRT_ID_EXT_BIOS_FLAG_3	0x6B
-#define CRT_ID_EXT_BIOS_FLAG_4	0x6C
-/* S3 virge extensions: more System Extension Registers  */
-#define CRT_ID_EXT_BIOS_FLAG_5	0x6D
-#define CRT_ID_EXT_DAC_TEST	0x6E
-#define CRT_ID_CONFIG_4 	0x6F
-
-/* Video DAC */
-#define VDAC_ADDRESS		0x03c8
-#define VDAC_ADDRESS_W		0x03c8
-#define VDAC_ADDRESS_R		0x03c7
-#define VDAC_STATE		0x03c7
-#define VDAC_DATA		0x03c9
-#define VDAC_MASK		0x03c6
-
-/* Miscellaneous Registers */
-#define MR_SUBSYSTEM_STATUS_R		0x8504	/* new for virge */
-#define MR_SUBSYSTEM_CNTL_W		0x8504	/* new for virge */
-#define MR_ADVANCED_FUNCTION_CONTROL	0x850C	/* new for virge */
-
-/* Blitter  */
-#define BLT_COMMAND_SET		0xA500
-#define BLT_SIZE_X_Y		0xA504
-#define BLT_SRC_X_Y		0xA508
-#define BLT_DEST_X_Y		0xA50C
-
-#define BLT_SRC_BASE		0xa4d4
-#define BLT_DEST_BASE		0xa4d8
-#define BLT_CLIP_LEFT_RIGHT	0xa4dc
-#define BLT_CLIP_TOP_BOTTOM	0xa4e0
-#define BLT_SRC_DEST_STRIDE	0xa4e4
-#define BLT_MONO_PATTERN_0	0xa4e8
-#define BLT_MONO_PATTERN_1	0xa4ec
-#define BLT_PATTERN_COLOR	0xa4f4
-
-#define L2D_COMMAND_SET		0xA900
-#define L2D_CLIP_LEFT_RIGHT	0xA8DC
-#define L2D_CLIP_TOP_BOTTOM	0xA8E0
-
-#define P2D_COMMAND_SET		0xAD00
-#define P2D_CLIP_LEFT_RIGHT	0xACDC
-#define P2D_CLIP_TOP_BOTTOM	0xACE0
-
-#define CMD_NOP		(0xf << 27)	/* %1111 << 27, was 0x07 */ 
-#define S3V_BITBLT	(0x0 << 27)
-#define S3V_RECTFILL	(0x2 << 27)
-#define S3V_AUTOEXE	0x01
-#define S3V_HWCLIP	0x02
-#define S3V_DRAW	0x20
-#define S3V_DST_8BPP	0x00
-#define S3V_DST_16BPP	0x04
-#define S3V_DST_24BPP	0x08
-#define S3V_MONO_PAT	0x100
-
-#define S3V_BLT_COPY	(0xcc<<17)
-#define S3V_BLT_CLEAR	(0x00<<17)
-#define S3V_BLT_SET	(0xff<<17)
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index b022fff..732db47 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -141,7 +141,7 @@
 {
 	int i;
 
-	for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+	for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i)
 		if (w1_therm_families[i].f->fid == fid)
 			return w1_therm_families[i].convert(rom);
 
@@ -238,7 +238,7 @@
 {
 	int err, i;
 
-	for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i) {
+	for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) {
 		err = w1_register_family(w1_therm_families[i].f);
 		if (err)
 			w1_therm_families[i].broken = 1;
@@ -251,7 +251,7 @@
 {
 	int i;
 
-	for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+	for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i)
 		if (!w1_therm_families[i].broken)
 			w1_unregister_family(w1_therm_families[i].f);
 }
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
index 60b05bc..b3ce885 100644
--- a/drivers/zorro/proc.c
+++ b/drivers/zorro/proc.c
@@ -75,7 +75,7 @@
 	return nbytes;
 }
 
-static struct file_operations proc_bus_zorro_operations = {
+static const struct file_operations proc_bus_zorro_operations = {
 	.llseek		= proc_bus_zorro_lseek,
 	.read		= proc_bus_zorro_read,
 };
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index a9b6301..9041971 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -136,7 +136,8 @@
 }
 
 /**
- * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and release it
+ * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
+ * 			release it
  * @dentry: dentry to look for fid in
  *
  * find a fid in the dentry and then clone to a new private fid
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index 147ceef..c783874 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -256,7 +256,7 @@
 	vpt->muxnum--;
 	if (!vpt->muxnum) {
 		dprintk(DEBUG_MUX, "destroy proc %p\n", vpt);
-		send_sig(SIGKILL, vpt->task, 1);
+		kthread_stop(vpt->task);
 		vpt->task = NULL;
 		v9fs_mux_poll_task_num--;
 	}
@@ -438,11 +438,8 @@
 
 	vpt = a;
 	dprintk(DEBUG_MUX, "start %p %p\n", current, vpt);
-	allow_signal(SIGKILL);
 	while (!kthread_should_stop()) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		if (signal_pending(current))
-			break;
 
 		list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) {
 			v9fs_poll_mux(m);
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index d9b561b..6ad6f19 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -53,6 +53,8 @@
 	Opt_uname, Opt_remotename,
 	/* Options that take no arguments */
 	Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd,
+	/* Cache options */
+	Opt_cache_loose,
 	/* Error token */
 	Opt_err
 };
@@ -76,6 +78,8 @@
 	{Opt_fd, "fd"},
 	{Opt_legacy, "noextend"},
 	{Opt_nodevmap, "nodevmap"},
+	{Opt_cache_loose, "cache=loose"},
+	{Opt_cache_loose, "loose"},
 	{Opt_err, NULL}
 };
 
@@ -106,6 +110,7 @@
 	v9ses->debug = 0;
 	v9ses->rfdno = ~0;
 	v9ses->wfdno = ~0;
+	v9ses->cache = 0;
 
 	if (!options)
 		return;
@@ -121,7 +126,6 @@
 					"integer field, but no integer?\n");
 				continue;
 			}
-
 		}
 		switch (token) {
 		case Opt_port:
@@ -169,6 +173,9 @@
 		case Opt_nodevmap:
 			v9ses->nodev = 1;
 			break;
+		case Opt_cache_loose:
+			v9ses->cache = CACHE_LOOSE;
+			break;
 		default:
 			continue;
 		}
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index c134d10..820bf5ca 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -47,7 +47,7 @@
 	unsigned int afid;	/* authentication fid */
 	unsigned int rfdno;	/* read file descriptor number */
 	unsigned int wfdno;	/* write file descriptor number */
-
+	unsigned int cache;	/* cache mode */
 
 	char *name;		/* user name to mount as */
 	char *remotename;	/* name of remote hierarchy being mounted */
@@ -73,6 +73,13 @@
 	PROTO_FD,
 };
 
+/* possible values of ->cache */
+/* eventually support loose, tight, time, session, default always none */
+enum {
+	CACHE_NONE,		/* default */
+	CACHE_LOOSE,		/* no consistency */
+};
+
 extern struct dentry *v9fs_debugfs_root;
 
 int v9fs_session_init(struct v9fs_session_info *, const char *, char *);
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 450b0c1..8ada4c5 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -40,8 +40,10 @@
 extern struct file_system_type v9fs_fs_type;
 extern const struct address_space_operations v9fs_addr_operations;
 extern const struct file_operations v9fs_file_operations;
+extern const struct file_operations v9fs_cached_file_operations;
 extern const struct file_operations v9fs_dir_operations;
 extern struct dentry_operations v9fs_dentry_operations;
+extern struct dentry_operations v9fs_cached_dentry_operations;
 
 struct inode *v9fs_get_inode(struct super_block *sb, int mode);
 ino_t v9fs_qid2ino(struct v9fs_qid *qid);
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index cc24abf..bed48fa 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -63,6 +63,8 @@
 	int total = 0;
 	int result = 0;
 
+	dprintk(DEBUG_VFS, "\n");
+
 	buffer = kmap(page);
 	do {
 		if (count < rsize)
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 062daa6..ddffd8a 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -53,10 +53,31 @@
 static int v9fs_dentry_delete(struct dentry *dentry)
 {
 	dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+
 	return 1;
 }
 
 /**
+ * v9fs_cached_dentry_delete - called when dentry refcount equals 0
+ * @dentry:  dentry in question
+ *
+ * Only return 1 if our inode is invalid.  Only non-synthetic files
+ * (ones without mtime == 0) should be calling this function.
+ *
+ */
+
+static int v9fs_cached_dentry_delete(struct dentry *dentry)
+{
+	struct inode *inode = dentry->d_inode;
+	dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+
+	if(!inode)
+		return 1;
+
+	return 0;
+}
+
+/**
  * v9fs_dentry_release - called when dentry is going to be freed
  * @dentry:  dentry that is being release
  *
@@ -87,6 +108,11 @@
 	}
 }
 
+struct dentry_operations v9fs_cached_dentry_operations = {
+	.d_delete = v9fs_cached_dentry_delete,
+	.d_release = v9fs_dentry_release,
+};
+
 struct dentry_operations v9fs_dentry_operations = {
 	.d_delete = v9fs_dentry_delete,
 	.d_release = v9fs_dentry_release,
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 9f17b0c..653dfa5 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -79,6 +79,13 @@
 	vfid->filp = file;
 	kfree(fcall);
 
+	if((vfid->qid.version) && (v9ses->cache)) {
+		dprintk(DEBUG_VFS, "cached");
+		/* enable cached file options */
+		if(file->f_op == &v9fs_file_operations)
+			file->f_op = &v9fs_cached_file_operations;
+	}
+
 	return 0;
 
 Clunk_Fid:
@@ -110,7 +117,7 @@
 
 	if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
 		filemap_write_and_wait(inode->i_mapping);
-		invalidate_inode_pages(&inode->i_data);
+		invalidate_mapping_pages(&inode->i_data, 0, -1);
 	}
 
 	return res;
@@ -234,10 +241,21 @@
 		total += result;
 	} while (count);
 
-		invalidate_inode_pages2(inode->i_mapping);
+	invalidate_inode_pages2(inode->i_mapping);
 	return total;
 }
 
+const struct file_operations v9fs_cached_file_operations = {
+	.llseek = generic_file_llseek,
+	.read = do_sync_read,
+	.aio_read = generic_file_aio_read,
+	.write = v9fs_file_write,
+	.open = v9fs_file_open,
+	.release = v9fs_dir_release,
+	.lock = v9fs_file_lock,
+	.mmap = generic_file_mmap,
+};
+
 const struct file_operations v9fs_file_operations = {
 	.llseek = generic_file_llseek,
 	.read = v9fs_file_read,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 9109ba1..124a085 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -41,10 +41,10 @@
 #include "v9fs_vfs.h"
 #include "fid.h"
 
-static struct inode_operations v9fs_dir_inode_operations;
-static struct inode_operations v9fs_dir_inode_operations_ext;
-static struct inode_operations v9fs_file_inode_operations;
-static struct inode_operations v9fs_symlink_inode_operations;
+static const struct inode_operations v9fs_dir_inode_operations;
+static const struct inode_operations v9fs_dir_inode_operations_ext;
+static const struct inode_operations v9fs_file_inode_operations;
+static const struct inode_operations v9fs_symlink_inode_operations;
 
 /**
  * unixmode2p9mode - convert unix mode bits to plan 9
@@ -504,7 +504,10 @@
 		goto error;
 	}
 
-	dentry->d_op = &v9fs_dentry_operations;
+	if(v9ses->cache)
+		dentry->d_op = &v9fs_cached_dentry_operations;
+	else
+		dentry->d_op = &v9fs_dentry_operations;
 	d_instantiate(dentry, inode);
 
 	if (nd && nd->flags & LOOKUP_OPEN) {
@@ -585,17 +588,17 @@
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
 		inode = NULL;
-		goto clean_up_fids;
+		v9fs_fid_destroy(vfid);
+		goto error;
 	}
 
-	dentry->d_op = &v9fs_dentry_operations;
+	if(v9ses->cache)
+		dentry->d_op = &v9fs_cached_dentry_operations;
+	else
+		dentry->d_op = &v9fs_dentry_operations;
 	d_instantiate(dentry, inode);
 	return 0;
 
-clean_up_fids:
-	if (vfid)
-		v9fs_fid_destroy(vfid);
-
 clean_up_dfid:
 	v9fs_fid_clunk(v9ses, dfid);
 
@@ -629,7 +632,6 @@
 
 	sb = dir->i_sb;
 	v9ses = v9fs_inode2v9ses(dir);
-	dentry->d_op = &v9fs_dentry_operations;
 	dirfid = v9fs_fid_lookup(dentry->d_parent);
 
 	if(IS_ERR(dirfid))
@@ -700,6 +702,10 @@
 
 	fid->qid = fcall->params.rstat.stat.qid;
 	v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
+	if((fid->qid.version)&&(v9ses->cache))
+		dentry->d_op = &v9fs_cached_dentry_operations;
+	else
+		dentry->d_op = &v9fs_dentry_operations;
 
 	d_add(dentry, inode);
 	kfree(fcall);
@@ -1187,7 +1193,10 @@
 		goto free_vfid;
 	}
 
-	dentry->d_op = &v9fs_dentry_operations;
+	if(v9ses->cache)
+		dentry->d_op = &v9fs_cached_dentry_operations;
+	else
+		dentry->d_op = &v9fs_dentry_operations;
 	d_instantiate(dentry, inode);
 	return 0;
 
@@ -1306,7 +1315,7 @@
 	return retval;
 }
 
-static struct inode_operations v9fs_dir_inode_operations_ext = {
+static const struct inode_operations v9fs_dir_inode_operations_ext = {
 	.create = v9fs_vfs_create,
 	.lookup = v9fs_vfs_lookup,
 	.symlink = v9fs_vfs_symlink,
@@ -1321,7 +1330,7 @@
 	.setattr = v9fs_vfs_setattr,
 };
 
-static struct inode_operations v9fs_dir_inode_operations = {
+static const struct inode_operations v9fs_dir_inode_operations = {
 	.create = v9fs_vfs_create,
 	.lookup = v9fs_vfs_lookup,
 	.unlink = v9fs_vfs_unlink,
@@ -1333,12 +1342,12 @@
 	.setattr = v9fs_vfs_setattr,
 };
 
-static struct inode_operations v9fs_file_inode_operations = {
+static const struct inode_operations v9fs_file_inode_operations = {
 	.getattr = v9fs_vfs_getattr,
 	.setattr = v9fs_vfs_setattr,
 };
 
-static struct inode_operations v9fs_symlink_inode_operations = {
+static const struct inode_operations v9fs_symlink_inode_operations = {
 	.readlink = v9fs_vfs_readlink,
 	.follow_link = v9fs_vfs_follow_link,
 	.put_link = v9fs_vfs_put_link,
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 63320d4..0ec42f6 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -45,7 +45,7 @@
 #include "fid.h"
 
 static void v9fs_clear_inode(struct inode *);
-static struct super_operations v9fs_super_ops;
+static const struct super_operations v9fs_super_ops;
 
 /**
  * v9fs_clear_inode - release an inode
@@ -263,7 +263,7 @@
 		v9fs_session_cancel(v9ses);
 }
 
-static struct super_operations v9fs_super_ops = {
+static const struct super_operations v9fs_super_ops = {
 	.statfs = simple_statfs,
 	.clear_inode = v9fs_clear_inode,
 	.show_options = v9fs_show_options,
diff --git a/fs/Kconfig b/fs/Kconfig
index 5e8e9d9..3c4886b 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -674,12 +674,6 @@
 	  necessary to create such a filesystem.  Say Y here if you want to be
 	  able to read such compressed CD-ROMs.
 
-config ZISOFS_FS
-# for fs/nls/Config.in
-	tristate
-	depends on ZISOFS
-	default ISO9660_FS
-
 config UDF_FS
 	tristate "UDF file system support"
 	help
@@ -1094,7 +1088,7 @@
 
 config ECRYPT_FS
 	tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && KEYS && CRYPTO
+	depends on EXPERIMENTAL && KEYS && CRYPTO && NET
 	help
 	  Encrypted filesystem that operates on the VFS layer.  See
 	  <file:Documentation/ecryptfs.txt> to learn more about
@@ -1195,32 +1189,6 @@
 	  To compile the EFS file system support as a module, choose M here: the
 	  module will be called efs.
 
-config JFFS_FS
-	tristate "Journalling Flash File System (JFFS) support"
-	depends on MTD && BLOCK && BROKEN
-	help
-	  JFFS is the Journalling Flash File System developed by Axis
-	  Communications in Sweden, aimed at providing a crash/powerdown-safe
-	  file system for disk-less embedded devices. Further information is
-	  available at (<http://developer.axis.com/software/jffs/>).
-
-	  NOTE: This filesystem is deprecated and is scheduled for removal in
-	  2.6.21.  See Documentation/feature-removal-schedule.txt
-
-config JFFS_FS_VERBOSE
-	int "JFFS debugging verbosity (0 = quiet, 3 = noisy)"
-	depends on JFFS_FS
-	default "0"
-	help
-	  Determines the verbosity level of the JFFS debugging messages.
-
-config JFFS_PROC_FS
-	bool "JFFS stats available in /proc filesystem"
-	depends on JFFS_FS && PROC_FS
-	help
-	  Enabling this option will cause statistics from mounted JFFS file systems
-	  to be made available to the user in the /proc/fs/jffs/ directory.
-
 config JFFS2_FS
 	tristate "Journalling Flash File System v2 (JFFS2) support"
 	select CRC32
@@ -1870,20 +1838,14 @@
 	  file servers such as Windows 2000 (including Windows 2003, NT 4  
 	  and Windows XP) as well by Samba (which provides excellent CIFS
 	  server support for Linux and many other operating systems). Limited
-	  support for Windows ME and similar servers is provided as well. 
-	  You must use the smbfs client filesystem to access older SMB servers
-	  such as OS/2 and DOS.
+	  support for OS/2 and Windows ME and similar servers is provided as well.
 
 	  The intent of the cifs module is to provide an advanced
-	  network file system client for mounting to CIFS compliant servers, 
+	  network file system client for mounting to CIFS compliant servers,
 	  including support for dfs (hierarchical name space), secure per-user
 	  session establishment, safe distributed caching (oplock), optional
-	  packet signing, Unicode and other internationalization improvements, 
-	  and optional Winbind (nsswitch) integration. You do not need to enable
-	  cifs if running only a (Samba) server. It is possible to enable both
-	  smbfs and cifs (e.g. if you are using CIFS for accessing Windows 2003
-	  and Samba 3 servers, and smbfs for accessing old servers). If you need 
-	  to mount to Samba or Windows from this machine, say Y.
+	  packet signing, Unicode and other internationalization improvements. 
+	  If you need to mount to Samba or Windows from this machine, say Y.
 
 config CIFS_STATS
         bool "CIFS statistics"
@@ -1976,14 +1938,13 @@
 	  depends on CIFS && EXPERIMENTAL
 	  help
 	    Enables cifs features under testing. These features are
-	    experimental and currently include support for writepages
-	    (multipage writebehind performance improvements) and directory
-	    change notification ie fcntl(F_DNOTIFY) as well as some security
-	    improvements.  Some also depend on setting at runtime the
-	    pseudo-file /proc/fs/cifs/Experimental (which is disabled by
-	    default). See the file fs/cifs/README for more details.
-
-	    If unsure, say N.
+	    experimental and currently include DFS support and directory 
+	    change notification ie fcntl(F_DNOTIFY), as well as the upcall
+	    mechanism which will be used for Kerberos session negotiation
+	    and uid remapping.  Some of these features also may depend on 
+	    setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental
+	    (which is disabled by default). See the file fs/cifs/README 
+	    for more details.  If unsure, say N.
 
 config CIFS_UPCALL
 	  bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
diff --git a/fs/Makefile b/fs/Makefile
index b9ffa63f..9edf411 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -94,7 +94,6 @@
 obj-$(CONFIG_NTFS_FS)		+= ntfs/
 obj-$(CONFIG_UFS_FS)		+= ufs/
 obj-$(CONFIG_EFS_FS)		+= efs/
-obj-$(CONFIG_JFFS_FS)		+= jffs/
 obj-$(CONFIG_JFFS2_FS)		+= jffs2/
 obj-$(CONFIG_AFFS_FS)		+= affs/
 obj-$(CONFIG_ROMFS_FS)		+= romfs/
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index 29217ff..936f2af 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -84,7 +84,7 @@
  */
 
 /* dir_*.c */
-extern struct inode_operations adfs_dir_inode_operations;
+extern const struct inode_operations adfs_dir_inode_operations;
 extern const struct file_operations adfs_dir_operations;
 extern struct dentry_operations adfs_dentry_operations;
 extern struct adfs_dir_ops adfs_f_dir_ops;
@@ -93,7 +93,7 @@
 extern int adfs_dir_update(struct super_block *sb, struct object_info *obj);
 
 /* file.c */
-extern struct inode_operations adfs_file_inode_operations;
+extern const struct inode_operations adfs_file_inode_operations;
 extern const struct file_operations adfs_file_operations;
 
 static inline __u32 signed_asl(__u32 val, signed int shift)
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index 2b89038..fc1a8dc 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -295,7 +295,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations adfs_dir_inode_operations = {
+const struct inode_operations adfs_dir_inode_operations = {
 	.lookup		= adfs_lookup,
 	.setattr	= adfs_notify_change,
 };
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index 6101ea6..f544a28 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -36,6 +36,6 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-struct inode_operations adfs_file_inode_operations = {
+const struct inode_operations adfs_file_inode_operations = {
 	.setattr	= adfs_notify_change,
 };
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 5023351..2e5f2c8 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -254,7 +254,7 @@
 	kmem_cache_destroy(adfs_inode_cachep);
 }
 
-static struct super_operations adfs_sops = {
+static const struct super_operations adfs_sops = {
 	.alloc_inode	= adfs_alloc_inode,
 	.destroy_inode	= adfs_destroy_inode,
 	.write_inode	= adfs_write_inode,
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 1dc8438..232c694 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -171,6 +171,7 @@
 extern struct inode		*affs_new_inode(struct inode *dir);
 extern int			 affs_notify_change(struct dentry *dentry, struct iattr *attr);
 extern void			 affs_put_inode(struct inode *inode);
+extern void			 affs_drop_inode(struct inode *inode);
 extern void			 affs_delete_inode(struct inode *inode);
 extern void			 affs_clear_inode(struct inode *inode);
 extern void			 affs_read_inode(struct inode *inode);
@@ -188,9 +189,9 @@
 
 /* jump tables */
 
-extern struct inode_operations	 affs_file_inode_operations;
-extern struct inode_operations	 affs_dir_inode_operations;
-extern struct inode_operations   affs_symlink_inode_operations;
+extern const struct inode_operations	 affs_file_inode_operations;
+extern const struct inode_operations	 affs_dir_inode_operations;
+extern const struct inode_operations   affs_symlink_inode_operations;
 extern const struct file_operations	 affs_file_operations;
 extern const struct file_operations	 affs_file_operations_ofs;
 extern const struct file_operations	 affs_dir_operations;
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index cad3ee3..6e3f282 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -26,7 +26,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations affs_dir_inode_operations = {
+const struct inode_operations affs_dir_inode_operations = {
 	.create		= affs_create,
 	.lookup		= affs_lookup,
 	.link		= affs_link,
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 05b5e22..4aa8079 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -38,7 +38,7 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-struct inode_operations affs_file_inode_operations = {
+const struct inode_operations affs_file_inode_operations = {
 	.truncate	= affs_truncate,
 	.setattr	= affs_notify_change,
 };
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 44d439c..c5b9d73c 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -12,7 +12,7 @@
 
 #include "affs.h"
 
-extern struct inode_operations affs_symlink_inode_operations;
+extern const struct inode_operations affs_symlink_inode_operations;
 extern struct timezone sys_tz;
 
 void
@@ -243,12 +243,17 @@
 {
 	pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
 	affs_free_prealloc(inode);
-	if (atomic_read(&inode->i_count) == 1) {
-		mutex_lock(&inode->i_mutex);
-		if (inode->i_size != AFFS_I(inode)->mmu_private)
-			affs_truncate(inode);
-		mutex_unlock(&inode->i_mutex);
-	}
+}
+
+void
+affs_drop_inode(struct inode *inode)
+{
+	mutex_lock(&inode->i_mutex);
+	if (inode->i_size != AFFS_I(inode)->mmu_private)
+		affs_truncate(inode);
+	mutex_unlock(&inode->i_mutex);
+
+	generic_drop_inode(inode);
 }
 
 void
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 3de93e7..c3986a1 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -112,12 +112,13 @@
 	kmem_cache_destroy(affs_inode_cachep);
 }
 
-static struct super_operations affs_sops = {
+static const struct super_operations affs_sops = {
 	.alloc_inode	= affs_alloc_inode,
 	.destroy_inode	= affs_destroy_inode,
 	.read_inode	= affs_read_inode,
 	.write_inode	= affs_write_inode,
 	.put_inode	= affs_put_inode,
+	.drop_inode	= affs_drop_inode,
 	.delete_inode	= affs_delete_inode,
 	.clear_inode	= affs_clear_inode,
 	.put_super	= affs_put_super,
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c
index f802256..4178253 100644
--- a/fs/affs/symlink.c
+++ b/fs/affs/symlink.c
@@ -70,7 +70,7 @@
 	.readpage	= affs_symlink_readpage,
 };
 
-struct inode_operations affs_symlink_inode_operations = {
+const struct inode_operations affs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index bfc1fd2..1fc5783 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -10,7 +10,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <rxrpc/peer.h>
 #include <rxrpc/connection.h>
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 4acd041..b6dc2eb 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
@@ -37,7 +36,7 @@
 	.readdir	= afs_dir_readdir,
 };
 
-struct inode_operations afs_dir_inode_operations = {
+const struct inode_operations afs_dir_inode_operations = {
 	.lookup		= afs_dir_lookup,
 	.getattr	= afs_inode_getattr,
 #if 0 /* TODO */
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 2e8c426..b176345 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
@@ -30,7 +29,7 @@
 static void afs_file_invalidatepage(struct page *page, unsigned long offset);
 static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
 
-struct inode_operations afs_file_inode_operations = {
+const struct inode_operations afs_file_inode_operations = {
 	.getattr	= afs_inode_getattr,
 };
 
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 6f37754..9d9bca6 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index e88b3b6..5151d5d 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -63,14 +63,14 @@
 /*
  * dir.c
  */
-extern struct inode_operations afs_dir_inode_operations;
+extern const struct inode_operations afs_dir_inode_operations;
 extern const struct file_operations afs_dir_file_operations;
 
 /*
  * file.c
  */
 extern const struct address_space_operations afs_fs_aops;
-extern struct inode_operations afs_file_inode_operations;
+extern const struct inode_operations afs_file_inode_operations;
 
 #ifdef AFS_CACHING_SUPPORT
 extern int afs_cache_get_page_cookie(struct page *page,
@@ -104,7 +104,7 @@
 /*
  * mntpt.c
  */
-extern struct inode_operations afs_mntpt_inode_operations;
+extern const struct inode_operations afs_mntpt_inode_operations;
 extern const struct file_operations afs_mntpt_file_operations;
 extern struct afs_timer afs_mntpt_expiry_timer;
 extern struct afs_timer_ops afs_mntpt_expiry_timer_ops;
diff --git a/fs/afs/main.c b/fs/afs/main.c
index 913c689..f2704ba 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/completion.h>
 #include <rxrpc/rxrpc.h>
 #include <rxrpc/transport.h>
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 8f74e84..68495f0 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
@@ -36,7 +35,7 @@
 	.open		= afs_mntpt_open,
 };
 
-struct inode_operations afs_mntpt_inode_operations = {
+const struct inode_operations afs_mntpt_inode_operations = {
 	.lookup		= afs_mntpt_lookup,
 	.follow_link	= afs_mntpt_follow_link,
 	.readlink	= page_readlink,
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 86463ec..ae6b85b 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 18d9b77..eb7e323 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -56,7 +56,7 @@
 	.fs_flags	= FS_BINARY_MOUNTDATA,
 };
 
-static struct super_operations afs_super_ops = {
+static const struct super_operations afs_super_ops = {
 	.statfs		= simple_statfs,
 	.alloc_inode	= afs_alloc_inode,
 	.drop_inode	= generic_delete_inode,
diff --git a/fs/aio.c b/fs/aio.c
index 55991e4..0b4ee0a 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -132,7 +132,7 @@
 	dprintk("attempting mmap of %lu bytes\n", info->mmap_size);
 	down_write(&ctx->mm->mmap_sem);
 	info->mmap_base = do_mmap(NULL, 0, info->mmap_size, 
-				  PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE,
+				  PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,
 				  0);
 	if (IS_ERR((void *)info->mmap_base)) {
 		up_write(&ctx->mm->mmap_sem);
@@ -211,11 +211,10 @@
 	if ((unsigned long)nr_events > aio_max_nr)
 		return ERR_PTR(-EAGAIN);
 
-	ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL);
+	ctx = kmem_cache_zalloc(kioctx_cachep, GFP_KERNEL);
 	if (!ctx)
 		return ERR_PTR(-ENOMEM);
 
-	memset(ctx, 0, sizeof(*ctx));
 	ctx->max_reqs = nr_events;
 	mm = ctx->mm = current->mm;
 	atomic_inc(&mm->mm_count);
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 906ba5c..4ef5444 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -142,8 +142,8 @@
 
 /* Operations structures */
 
-extern struct inode_operations autofs_root_inode_operations;
-extern struct inode_operations autofs_symlink_inode_operations;
+extern const struct inode_operations autofs_root_inode_operations;
+extern const struct inode_operations autofs_symlink_inode_operations;
 extern const struct file_operations autofs_root_operations;
 
 /* Initializing function */
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index f968d13..aa0b61f 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -52,7 +52,7 @@
 
 static void autofs_read_inode(struct inode *inode);
 
-static struct super_operations autofs_sops = {
+static const struct super_operations autofs_sops = {
 	.read_inode	= autofs_read_inode,
 	.statfs		= simple_statfs,
 };
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index e698c51..f259720 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -32,7 +32,7 @@
 	.ioctl		= autofs_root_ioctl,
 };
 
-struct inode_operations autofs_root_inode_operations = {
+const struct inode_operations autofs_root_inode_operations = {
         .lookup		= autofs_root_lookup,
         .unlink		= autofs_root_unlink,
         .symlink	= autofs_root_symlink,
diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c
index c74f2eb..7ce9cb2 100644
--- a/fs/autofs/symlink.c
+++ b/fs/autofs/symlink.c
@@ -20,7 +20,7 @@
 	return NULL;
 }
 
-struct inode_operations autofs_symlink_inode_operations = {
+const struct inode_operations autofs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= autofs_follow_link
 };
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 216b1a3..d85f42f 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -52,6 +52,8 @@
 
 	int		flags;
 
+	struct list_head rehash;
+
 	struct autofs_sb_info *sbi;
 	unsigned long last_used;
 	atomic_t count;
@@ -110,6 +112,8 @@
 	struct mutex wq_mutex;
 	spinlock_t fs_lock;
 	struct autofs_wait_queue *queues; /* Wait queue pointer */
+	spinlock_t rehash_lock;
+	struct list_head rehash_list;
 };
 
 static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb)
@@ -168,11 +172,11 @@
 
 /* Operations structures */
 
-extern struct inode_operations autofs4_symlink_inode_operations;
-extern struct inode_operations autofs4_dir_inode_operations;
-extern struct inode_operations autofs4_root_inode_operations;
-extern struct inode_operations autofs4_indirect_root_inode_operations;
-extern struct inode_operations autofs4_direct_root_inode_operations;
+extern const struct inode_operations autofs4_symlink_inode_operations;
+extern const struct inode_operations autofs4_dir_inode_operations;
+extern const struct inode_operations autofs4_root_inode_operations;
+extern const struct inode_operations autofs4_indirect_root_inode_operations;
+extern const struct inode_operations autofs4_direct_root_inode_operations;
 extern const struct file_operations autofs4_dir_operations;
 extern const struct file_operations autofs4_root_operations;
 
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index e8f6c5a..26063dc 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -48,6 +48,8 @@
 	ino->dentry = NULL;
 	ino->size = 0;
 
+	INIT_LIST_HEAD(&ino->rehash);
+
 	ino->last_used = jiffies;
 	atomic_set(&ino->count, 0);
 
@@ -158,14 +160,13 @@
 	if (!sbi)
 		goto out_kill_sb;
 
-	sb->s_fs_info = NULL;
-
-	if ( !sbi->catatonic )
+	if (!sbi->catatonic)
 		autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */
 
 	/* Clean up and release dangling references */
 	autofs4_force_release(sbi);
 
+	sb->s_fs_info = NULL;
 	kfree(sbi);
 
 out_kill_sb:
@@ -196,7 +197,7 @@
 	return 0;
 }
 
-static struct super_operations autofs4_sops = {
+static const struct super_operations autofs4_sops = {
 	.statfs		= simple_statfs,
 	.show_options	= autofs4_show_options,
 };
@@ -336,6 +337,8 @@
 	mutex_init(&sbi->wq_mutex);
 	spin_lock_init(&sbi->fs_lock);
 	sbi->queues = NULL;
+	spin_lock_init(&sbi->rehash_lock);
+	INIT_LIST_HEAD(&sbi->rehash_list);
 	s->s_blocksize = 1024;
 	s->s_blocksize_bits = 10;
 	s->s_magic = AUTOFS_SUPER_MAGIC;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 8d05b9f..b463104 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -47,7 +47,7 @@
 	.readdir	= autofs4_dir_readdir,
 };
 
-struct inode_operations autofs4_indirect_root_inode_operations = {
+const struct inode_operations autofs4_indirect_root_inode_operations = {
 	.lookup		= autofs4_lookup,
 	.unlink		= autofs4_dir_unlink,
 	.symlink	= autofs4_dir_symlink,
@@ -55,7 +55,7 @@
 	.rmdir		= autofs4_dir_rmdir,
 };
 
-struct inode_operations autofs4_direct_root_inode_operations = {
+const struct inode_operations autofs4_direct_root_inode_operations = {
 	.lookup		= autofs4_lookup,
 	.unlink		= autofs4_dir_unlink,
 	.mkdir		= autofs4_dir_mkdir,
@@ -63,7 +63,7 @@
 	.follow_link	= autofs4_follow_link,
 };
 
-struct inode_operations autofs4_dir_inode_operations = {
+const struct inode_operations autofs4_dir_inode_operations = {
 	.lookup		= autofs4_lookup,
 	.unlink		= autofs4_dir_unlink,
 	.symlink	= autofs4_dir_symlink,
@@ -263,7 +263,7 @@
 		 */
 		status = d_invalidate(dentry);
 		if (status != -EBUSY)
-			return -ENOENT;
+			return -EAGAIN;
 	}
 
 	DPRINTK("dentry=%p %.*s ino=%p",
@@ -413,7 +413,16 @@
 		 */
 		status = try_to_fill_dentry(dentry, flags);
 		if (status == 0)
-				return 1;
+			return 1;
+
+		/*
+		 * A status of EAGAIN here means that the dentry has gone
+		 * away while waiting for an expire to complete. If we are
+		 * racing with expire lookup will wait for it so this must
+		 * be a revalidate and we need to send it to lookup.
+		 */
+		if (status == -EAGAIN)
+			return 0;
 
 		return status;
 	}
@@ -459,9 +468,18 @@
 	de->d_fsdata = NULL;
 
 	if (inf) {
+		struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb);
+
 		inf->dentry = NULL;
 		inf->inode = NULL;
 
+		if (sbi) {
+			spin_lock(&sbi->rehash_lock);
+			if (!list_empty(&inf->rehash))
+				list_del(&inf->rehash);
+			spin_unlock(&sbi->rehash_lock);
+		}
+
 		autofs4_free_ino(inf);
 	}
 }
@@ -478,10 +496,80 @@
 	.d_release	= autofs4_dentry_release,
 };
 
+static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
+{
+	unsigned int len = name->len;
+	unsigned int hash = name->hash;
+	const unsigned char *str = name->name;
+	struct list_head *p, *head;
+
+	spin_lock(&dcache_lock);
+	spin_lock(&sbi->rehash_lock);
+	head = &sbi->rehash_list;
+	list_for_each(p, head) {
+		struct autofs_info *ino;
+		struct dentry *dentry;
+		struct qstr *qstr;
+
+		ino = list_entry(p, struct autofs_info, rehash);
+		dentry = ino->dentry;
+
+		spin_lock(&dentry->d_lock);
+
+		/* Bad luck, we've already been dentry_iput */
+		if (!dentry->d_inode)
+			goto next;
+
+		qstr = &dentry->d_name;
+
+		if (dentry->d_name.hash != hash)
+			goto next;
+		if (dentry->d_parent != parent)
+			goto next;
+
+		if (qstr->len != len)
+			goto next;
+		if (memcmp(qstr->name, str, len))
+			goto next;
+
+		if (d_unhashed(dentry)) {
+			struct autofs_info *ino = autofs4_dentry_ino(dentry);
+			struct inode *inode = dentry->d_inode;
+
+			list_del_init(&ino->rehash);
+			dget(dentry);
+			/*
+			 * Make the rehashed dentry negative so the VFS
+			 * behaves as it should.
+			 */
+			if (inode) {
+				dentry->d_inode = NULL;
+				list_del_init(&dentry->d_alias);
+				spin_unlock(&dentry->d_lock);
+				spin_unlock(&sbi->rehash_lock);
+				spin_unlock(&dcache_lock);
+				iput(inode);
+				return dentry;
+			}
+			spin_unlock(&dentry->d_lock);
+			spin_unlock(&sbi->rehash_lock);
+			spin_unlock(&dcache_lock);
+			return dentry;
+		}
+next:
+		spin_unlock(&dentry->d_lock);
+	}
+	spin_unlock(&sbi->rehash_lock);
+	spin_unlock(&dcache_lock);
+
+	return NULL;
+}
+
 /* Lookups in the root directory */
 static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct autofs_sb_info *sbi;
+	struct dentry *unhashed;
 	int oz_mode;
 
 	DPRINTK("name = %.*s",
@@ -497,25 +585,46 @@
 	DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
 		 current->pid, process_group(current), sbi->catatonic, oz_mode);
 
-	/*
-	 * Mark the dentry incomplete, but add it. This is needed so
-	 * that the VFS layer knows about the dentry, and we can count
-	 * on catching any lookups through the revalidate.
-	 *
-	 * Let all the hard work be done by the revalidate function that
-	 * needs to be able to do this anyway..
-	 *
-	 * We need to do this before we release the directory semaphore.
-	 */
-	dentry->d_op = &autofs4_root_dentry_operations;
+	unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name);
+	if (!unhashed) {
+		/*
+		 * Mark the dentry incomplete, but add it. This is needed so
+		 * that the VFS layer knows about the dentry, and we can count
+		 * on catching any lookups through the revalidate.
+		 *
+		 * Let all the hard work be done by the revalidate function that
+		 * needs to be able to do this anyway..
+		 *
+		 * We need to do this before we release the directory semaphore.
+		 */
+		dentry->d_op = &autofs4_root_dentry_operations;
+
+		dentry->d_fsdata = NULL;
+		d_add(dentry, NULL);
+	} else {
+		struct autofs_info *ino = autofs4_dentry_ino(unhashed);
+		DPRINTK("rehash %p with %p", dentry, unhashed);
+		/*
+		 * If we are racing with expire the request might not
+		 * be quite complete but the directory has been removed
+		 * so it must have been successful, so just wait for it.
+		 */
+		if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
+			DPRINTK("wait for incomplete expire %p name=%.*s",
+				unhashed, unhashed->d_name.len,
+				unhashed->d_name.name);
+			autofs4_wait(sbi, unhashed, NFY_NONE);
+			DPRINTK("request completed");
+		}
+		d_rehash(unhashed);
+		dentry = unhashed;
+	}
 
 	if (!oz_mode) {
 		spin_lock(&dentry->d_lock);
 		dentry->d_flags |= DCACHE_AUTOFS_PENDING;
 		spin_unlock(&dentry->d_lock);
 	}
-	dentry->d_fsdata = NULL;
-	d_add(dentry, NULL);
 
 	if (dentry->d_op && dentry->d_op->d_revalidate) {
 		mutex_unlock(&dir->i_mutex);
@@ -534,6 +643,8 @@
 			if (sigismember (sigset, SIGKILL) ||
 			    sigismember (sigset, SIGQUIT) ||
 			    sigismember (sigset, SIGINT)) {
+			    if (unhashed)
+				dput(unhashed);
 			    return ERR_PTR(-ERESTARTNOINTR);
 			}
 		}
@@ -544,12 +655,33 @@
 
 	/*
 	 * If this dentry is unhashed, then we shouldn't honour this
-	 * lookup even if the dentry is positive.  Returning ENOENT here
-	 * doesn't do the right thing for all system calls, but it should
-	 * be OK for the operations we permit from an autofs.
+	 * lookup.  Returning ENOENT here doesn't do the right thing
+	 * for all system calls, but it should be OK for the operations
+	 * we permit from an autofs.
 	 */
-	if (dentry->d_inode && d_unhashed(dentry))
-		return ERR_PTR(-ENOENT);
+	if (dentry->d_inode && d_unhashed(dentry)) {
+		/*
+		 * A user space application can (and has done in the past)
+		 * remove and re-create this directory during the callback.
+		 * This can leave us with an unhashed dentry, but a
+		 * successful mount!  So we need to perform another
+		 * cached lookup in case the dentry now exists.
+		 */
+		struct dentry *parent = dentry->d_parent;
+		struct dentry *new = d_lookup(parent, &dentry->d_name);
+		if (new != NULL)
+			dentry = new;
+		else
+			dentry = ERR_PTR(-ENOENT);
+
+		if (unhashed)
+			dput(unhashed);
+
+		return dentry;
+	}
+
+	if (unhashed)
+		return dentry;
 
 	return NULL;
 }
@@ -611,9 +743,10 @@
  * Normal filesystems would do a "d_delete()" to tell the VFS dcache
  * that the file no longer exists. However, doing that means that the
  * VFS layer can turn the dentry into a negative dentry.  We don't want
- * this, because since the unlink is probably the result of an expire.
- * We simply d_drop it, which allows the dentry lookup to remount it
- * if necessary.
+ * this, because the unlink is probably the result of an expire.
+ * We simply d_drop it and add it to a rehash candidates list in the
+ * super block, which allows the dentry lookup to reuse it retaining
+ * the flags, such as expire in progress, in case we're racing with expire.
  *
  * If a process is blocked on the dentry waiting for the expire to finish,
  * it will invalidate the dentry and try to mount with a new one.
@@ -642,7 +775,14 @@
 
 	dir->i_mtime = CURRENT_TIME;
 
-	d_drop(dentry);
+	spin_lock(&dcache_lock);
+	spin_lock(&sbi->rehash_lock);
+	list_add(&ino->rehash, &sbi->rehash_list);
+	spin_unlock(&sbi->rehash_lock);
+	spin_lock(&dentry->d_lock);
+	__d_drop(dentry);
+	spin_unlock(&dentry->d_lock);
+	spin_unlock(&dcache_lock);
 
 	return 0;
 }
@@ -653,6 +793,9 @@
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
 	struct autofs_info *p_ino;
 	
+	DPRINTK("dentry %p, removing %.*s",
+		dentry, dentry->d_name.len, dentry->d_name.name);
+
 	if (!autofs4_oz_mode(sbi))
 		return -EACCES;
 
@@ -661,6 +804,9 @@
 		spin_unlock(&dcache_lock);
 		return -ENOTEMPTY;
 	}
+	spin_lock(&sbi->rehash_lock);
+	list_add(&ino->rehash, &sbi->rehash_list);
+	spin_unlock(&sbi->rehash_lock);
 	spin_lock(&dentry->d_lock);
 	__d_drop(dentry);
 	spin_unlock(&dentry->d_lock);
diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c
index 2ea2c98..b4ea829 100644
--- a/fs/autofs4/symlink.c
+++ b/fs/autofs4/symlink.c
@@ -19,7 +19,7 @@
 	return NULL;
 }
 
-struct inode_operations autofs4_symlink_inode_operations = {
+const struct inode_operations autofs4_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= autofs4_follow_link
 };
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 1e4a539..0d041a9 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -84,7 +84,11 @@
 				 struct autofs_wait_queue *wq,
 				 int type)
 {
-	union autofs_packet_union pkt;
+	union {
+		struct autofs_packet_hdr hdr;
+		union autofs_packet_union v4_pkt;
+		union autofs_v5_packet_union v5_pkt;
+	} pkt;
 	size_t pktsz;
 
 	DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d",
@@ -98,7 +102,7 @@
 	/* Kernel protocol v4 missing and expire packets */
 	case autofs_ptype_missing:
 	{
-		struct autofs_packet_missing *mp = &pkt.missing;
+		struct autofs_packet_missing *mp = &pkt.v4_pkt.missing;
 
 		pktsz = sizeof(*mp);
 
@@ -110,7 +114,7 @@
 	}
 	case autofs_ptype_expire_multi:
 	{
-		struct autofs_packet_expire_multi *ep = &pkt.expire_multi;
+		struct autofs_packet_expire_multi *ep = &pkt.v4_pkt.expire_multi;
 
 		pktsz = sizeof(*ep);
 
@@ -129,7 +133,7 @@
 	case autofs_ptype_missing_direct:
 	case autofs_ptype_expire_direct:
 	{
-		struct autofs_v5_packet *packet = &pkt.v5_packet;
+		struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet;
 
 		pktsz = sizeof(*packet);
 
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 869f519..efeab2f 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -291,7 +291,7 @@
 	return -EIO;
 }
 
-static struct inode_operations bad_inode_ops =
+static const struct inode_operations bad_inode_ops =
 {
 	.create		= bad_inode_create,
 	.lookup		= bad_inode_lookup,
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 481e59b..cc6cc8e 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -68,7 +68,7 @@
 	.readdir	= befs_readdir,
 };
 
-static struct inode_operations befs_dir_inode_operations = {
+static const struct inode_operations befs_dir_inode_operations = {
 	.lookup		= befs_lookup,
 };
 
@@ -78,7 +78,7 @@
 	.bmap		= befs_bmap,
 };
 
-static struct inode_operations befs_symlink_inode_operations = {
+static const struct inode_operations befs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= befs_follow_link,
 	.put_link	= befs_put_link,
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 31973bb..130f6c6 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -48,12 +48,12 @@
 
 
 /* file.c */
-extern struct inode_operations bfs_file_inops;
+extern const struct inode_operations bfs_file_inops;
 extern const struct file_operations bfs_file_operations;
 extern const struct address_space_operations bfs_aops;
 
 /* dir.c */
-extern struct inode_operations bfs_dir_inops;
+extern const struct inode_operations bfs_dir_inops;
 extern const struct file_operations bfs_dir_operations;
 
 #endif /* _FS_BFS_BFS_H */
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 2a746e6..097f149 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -260,7 +260,7 @@
 	return error;
 }
 
-struct inode_operations bfs_dir_inops = {
+const struct inode_operations bfs_dir_inops = {
 	.create			= bfs_create,
 	.lookup			= bfs_lookup,
 	.link			= bfs_link,
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index a9164a8..ef4d1fa 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -164,4 +164,4 @@
 	.bmap		= bfs_bmap,
 };
 
-struct inode_operations bfs_file_inops;
+const struct inode_operations bfs_file_inops;
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 134c999..93d6219 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -270,7 +270,7 @@
 	kmem_cache_destroy(bfs_inode_cachep);
 }
 
-static struct super_operations bfs_sops = {
+static const struct super_operations bfs_sops = {
 	.alloc_inode	= bfs_alloc_inode,
 	.destroy_inode	= bfs_destroy_inode,
 	.read_inode	= bfs_read_inode,
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 669dbe5..51db118 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -76,7 +76,8 @@
 		.load_binary	= load_elf_binary,
 		.load_shlib	= load_elf_library,
 		.core_dump	= elf_core_dump,
-		.min_coredump	= ELF_EXEC_PAGESIZE
+		.min_coredump	= ELF_EXEC_PAGESIZE,
+		.hasvdso	= 1
 };
 
 #define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index a4d933a..5810aa1 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -372,7 +372,7 @@
 	down_write(&current->mm->mmap_sem);
 	current->mm->start_brk = do_mmap(NULL, 0, stack_size,
 					 PROT_READ | PROT_WRITE | PROT_EXEC,
-					 MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN,
+					 MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN,
 					 0);
 
 	if (IS_ERR_VALUE(current->mm->start_brk)) {
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index ae8595d..7b0265d 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -419,7 +419,7 @@
 	unsigned long textpos = 0, datapos = 0, result;
 	unsigned long realdatastart = 0;
 	unsigned long text_len, data_len, bss_len, stack_len, flags;
-	unsigned long memp = 0; /* for finding the brk area */
+	unsigned long len, reallen, memp = 0;
 	unsigned long extra, rlim;
 	unsigned long *reloc = 0, *rp;
 	struct inode *inode;
@@ -540,10 +540,18 @@
 			goto err;
 		}
 
+		len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
 		down_write(&current->mm->mmap_sem);
-		realdatastart = do_mmap(0, 0, data_len + extra +
-				MAX_SHARED_LIBS * sizeof(unsigned long),
-				PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
+		realdatastart = do_mmap(0, 0, len,
+			PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
+		/* Remap to use all availabe slack region space */
+		if (realdatastart && (realdatastart < (unsigned long)-4096)) {
+			reallen = ksize(realdatastart);
+			if (reallen > len) {
+				realdatastart = do_mremap(realdatastart, len,
+					reallen, MREMAP_FIXED, realdatastart);
+			}
+		}
 		up_write(&current->mm->mmap_sem);
 
 		if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
@@ -584,11 +592,20 @@
 
 	} else {
 
+		len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
 		down_write(&current->mm->mmap_sem);
-		textpos = do_mmap(0, 0, text_len + data_len + extra +
-					MAX_SHARED_LIBS * sizeof(unsigned long),
-				PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
+		textpos = do_mmap(0, 0, len,
+			PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
+		/* Remap to use all availabe slack region space */
+		if (textpos && (textpos < (unsigned long) -4096)) {
+			reallen = ksize(textpos);
+			if (reallen > len) {
+				textpos = do_mremap(textpos, len, reallen,
+					MREMAP_FIXED, textpos);
+			}
+		}
 		up_write(&current->mm->mmap_sem);
+
 		if (!textpos  || textpos >= (unsigned long) -4096) {
 			if (!textpos)
 				textpos = (unsigned long) -ENOMEM;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index c2e0825..e6f5799 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -719,7 +719,7 @@
 
 /* Superblock handling */
 
-static struct super_operations s_ops = {
+static const struct super_operations s_ops = {
 	.statfs		= simple_statfs,
 	.clear_inode	= bm_clear_inode,
 };
diff --git a/fs/block_dev.c b/fs/block_dev.c
index fc7028b6..575076c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -489,7 +489,7 @@
 	spin_unlock(&bdev_lock);
 }
 
-static struct super_operations bdev_sops = {
+static const struct super_operations bdev_sops = {
 	.statfs = simple_statfs,
 	.alloc_inode = bdev_alloc_inode,
 	.destroy_inode = bdev_destroy_inode,
@@ -1101,6 +1101,13 @@
 			int for_part);
 static int __blkdev_put(struct block_device *bdev, int for_part);
 
+/*
+ * bd_mutex locking:
+ *
+ *  mutex_lock(part->bd_mutex)
+ *    mutex_lock_nested(whole->bd_mutex, 1)
+ */
+
 static int do_open(struct block_device *bdev, struct file *file, int for_part)
 {
 	struct module *owner = NULL;
diff --git a/fs/buffer.c b/fs/buffer.c
index 1ad674f..e8504b6 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -78,6 +78,7 @@
 
 void fastcall unlock_buffer(struct buffer_head *bh)
 {
+	smp_mb__before_clear_bit();
 	clear_buffer_locked(bh);
 	smp_mb__after_clear_bit();
 	wake_up_bit(&bh->b_state, BH_Lock);
@@ -345,7 +346,7 @@
 	 * We really want to use invalidate_inode_pages2() for
 	 * that, but not until that's cleaned up.
 	 */
-	invalidate_inode_pages(mapping);
+	invalidate_mapping_pages(mapping, 0, -1);
 }
 
 /*
@@ -1282,11 +1283,11 @@
  * Look up the bh in this cpu's LRU.  If it's there, move it to the head.
  */
 static struct buffer_head *
-lookup_bh_lru(struct block_device *bdev, sector_t block, int size)
+lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *ret = NULL;
 	struct bh_lru *lru;
-	int i;
+	unsigned int i;
 
 	check_irqs_on();
 	bh_lru_lock();
@@ -1318,7 +1319,7 @@
  * NULL
  */
 struct buffer_head *
-__find_get_block(struct block_device *bdev, sector_t block, int size)
+__find_get_block(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *bh = lookup_bh_lru(bdev, block, size);
 
@@ -1346,7 +1347,7 @@
  * attempt is failing.  FIXME, perhaps?
  */
 struct buffer_head *
-__getblk(struct block_device *bdev, sector_t block, int size)
+__getblk(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *bh = __find_get_block(bdev, block, size);
 
@@ -1360,7 +1361,7 @@
 /*
  * Do async read-ahead on a buffer..
  */
-void __breadahead(struct block_device *bdev, sector_t block, int size)
+void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *bh = __getblk(bdev, block, size);
 	if (likely(bh)) {
@@ -1380,7 +1381,7 @@
  *  It returns NULL if the block was unreadable.
  */
 struct buffer_head *
-__bread(struct block_device *bdev, sector_t block, int size)
+__bread(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *bh = __getblk(bdev, block, size);
 
@@ -1439,6 +1440,7 @@
 	clear_buffer_req(bh);
 	clear_buffer_new(bh);
 	clear_buffer_delay(bh);
+	clear_buffer_unwritten(bh);
 	unlock_buffer(bh);
 }
 
@@ -1741,7 +1743,6 @@
 	SetPageError(page);
 	BUG_ON(PageWriteback(page));
 	set_page_writeback(page);
-	unlock_page(page);
 	do {
 		struct buffer_head *next = bh->b_this_page;
 		if (buffer_async_write(bh)) {
@@ -1751,6 +1752,7 @@
 		}
 		bh = next;
 	} while (bh != head);
+	unlock_page(page);
 	goto done;
 }
 
@@ -1822,6 +1824,7 @@
 			continue; 
 		}
 		if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
+		    !buffer_unwritten(bh) &&
 		     (block_start < from || block_end > to)) {
 			ll_rw_block(READ, 1, &bh);
 			*wait_bh++=bh;
@@ -2245,7 +2248,6 @@
 	int i;
 	int ret = 0;
 	int is_mapped_to_disk = 1;
-	int dirtied_it = 0;
 
 	if (PageMappedToDisk(page))
 		return 0;
@@ -2282,14 +2284,10 @@
 			continue;
 		if (buffer_new(&map_bh) || !buffer_mapped(&map_bh)) {
 			kaddr = kmap_atomic(page, KM_USER0);
-			if (block_start < from) {
+			if (block_start < from)
 				memset(kaddr+block_start, 0, from-block_start);
-				dirtied_it = 1;
-			}
-			if (block_end > to) {
+			if (block_end > to)
 				memset(kaddr + to, 0, block_end - to);
-				dirtied_it = 1;
-			}
 			flush_dcache_page(page);
 			kunmap_atomic(kaddr, KM_USER0);
 			continue;
@@ -2344,17 +2342,6 @@
 
 	if (is_mapped_to_disk)
 		SetPageMappedToDisk(page);
-	SetPageUptodate(page);
-
-	/*
-	 * Setting the page dirty here isn't necessary for the prepare_write
-	 * function - commit_write will do that.  But if/when this function is
-	 * used within the pagefault handler to ensure that all mmapped pages
-	 * have backing space in the filesystem, we will need to dirty the page
-	 * if its contents were altered.
-	 */
-	if (dirtied_it)
-		set_page_dirty(page);
 
 	return 0;
 
@@ -2384,6 +2371,7 @@
 	struct inode *inode = page->mapping->host;
 	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
+	SetPageUptodate(page);
 	set_page_dirty(page);
 	if (pos > inode->i_size) {
 		i_size_write(inode, pos);
@@ -2543,7 +2531,7 @@
 	if (PageUptodate(page))
 		set_buffer_uptodate(bh);
 
-	if (!buffer_uptodate(bh) && !buffer_delay(bh)) {
+	if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) {
 		err = -EIO;
 		ll_rw_block(READ, 1, &bh);
 		wait_on_buffer(bh);
diff --git a/fs/char_dev.c b/fs/char_dev.c
index a885f46..78ced72 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -6,6 +6,7 @@
 
 #include <linux/init.h>
 #include <linux/fs.h>
+#include <linux/kdev_t.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 
@@ -108,6 +109,8 @@
 	/* temporary */
 	if (major == 0) {
 		for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {
+			if (is_lanana_major(i))
+				continue;
 			if (chrdevs[i] == NULL)
 				break;
 		}
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 85e3850..5fe1359 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,8 +1,15 @@
 Version 1.47
 ------------
 Fix oops in list_del during mount caused by unaligned string.
+Fix file corruption which could occur on some large file
+copies caused by writepages page i/o completion bug.
 Seek to SEEK_END forces check for update of file size for non-cached
-files.
+files. Allow file size to be updated on remote extend of locally open,
+non-cached file.  Fix reconnect to newer Samba servers (or other servers
+which support the CIFS Unix/POSIX extensions) so that we again tell the
+server the Unix/POSIX cifs capabilities which we support (SetFSInfo).
+Add experimental support for new POSIX Open/Mkdir (which returns
+stat information on the open, and allows setting the mode).
 
 Version 1.46
 ------------
diff --git a/fs/cifs/README b/fs/cifs/README
index 432e515..080c5eb 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -1,5 +1,5 @@
 The CIFS VFS support for Linux supports many advanced network filesystem 
-features such as heirarchical dfs like namespace, hardlinks, locking and more.  
+features such as hierarchical dfs like namespace, hardlinks, locking and more.  
 It was designed to comply with the SNIA CIFS Technical Reference (which 
 supersedes the 1992 X/Open SMB Standard) as well as to perform best practice 
 practical interoperability with Windows 2000, Windows XP, Samba and equivalent 
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index fc34c74..6837294 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -128,3 +128,11 @@
 
 4) More exhaustively test against less common servers.  More testing
 against Windows 9x, Windows ME servers.
+
+DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
+
+mount check for unmatched uids - and uid override
+
+Add mount option for Linux extension disable per mount, and partial disable per mount (uid off, symlink/fifo/mknod on but what about posix acls?) 
+
+Free threads at umount --force that are stuck on the sesSem
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 93ef099..bc2c0ac 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -64,7 +64,7 @@
 struct task_struct * oplockThread = NULL;
 extern struct task_struct * dnotifyThread; /* remove sparse warning */
 struct task_struct * dnotifyThread = NULL;
-static struct super_operations cifs_super_ops; 
+static const struct super_operations cifs_super_ops;
 unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
 module_param(CIFSMaxBufSize, int, 0);
 MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
@@ -91,8 +91,9 @@
 	struct inode *inode;
 	struct cifs_sb_info *cifs_sb;
 	int rc = 0;
-
-	sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
+	
+	/* BB should we make this contingent on mount parm? */
+	sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
 	sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
 	cifs_sb = CIFS_SB(sb);
 	if(cifs_sb == NULL)
@@ -258,7 +259,10 @@
 	cifs_inode->clientCanCacheRead = FALSE;
 	cifs_inode->clientCanCacheAll = FALSE;
 	cifs_inode->vfs_inode.i_blkbits = 14;  /* 2**14 = CIFS_MAX_MSGSIZE */
-	cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;
+	
+	/* Can not set i_flags here - they get immediately overwritten
+	   to zero by the VFS */
+/*	cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
 	INIT_LIST_HEAD(&cifs_inode->openFileList);
 	return &cifs_inode->vfs_inode;
 }
@@ -283,6 +287,7 @@
 
 	if (cifs_sb) {
 		if (cifs_sb->tcon) {
+/* BB add prepath to mount options displayed */
 			seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
 			if (cifs_sb->tcon->ses) {
 				if (cifs_sb->tcon->ses->userName)
@@ -453,7 +458,7 @@
 	return 0;
 }
 
-static struct super_operations cifs_super_ops = {
+static const struct super_operations cifs_super_ops = {
 	.read_inode = cifs_read_inode,
 	.put_super = cifs_put_super,
 	.statfs = cifs_statfs,
@@ -533,7 +538,7 @@
 	.kill_sb = kill_anon_super,
 	/*  .fs_flags */
 };
-struct inode_operations cifs_dir_inode_ops = {
+const struct inode_operations cifs_dir_inode_ops = {
 	.create = cifs_create,
 	.lookup = cifs_lookup,
 	.getattr = cifs_getattr,
@@ -555,7 +560,7 @@
 #endif
 };
 
-struct inode_operations cifs_file_inode_ops = {
+const struct inode_operations cifs_file_inode_ops = {
 /*	revalidate:cifs_revalidate, */
 	.setattr = cifs_setattr,
 	.getattr = cifs_getattr, /* do we need this anymore? */
@@ -569,7 +574,7 @@
 #endif 
 };
 
-struct inode_operations cifs_symlink_inode_ops = {
+const struct inode_operations cifs_symlink_inode_ops = {
 	.readlink = generic_readlink, 
 	.follow_link = cifs_follow_link,
 	.put_link = cifs_put_link,
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 8aa66dc..c97c08e 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -36,13 +36,13 @@
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
 
 /* Functions related to super block operations */
-/* extern struct super_operations cifs_super_ops;*/
+/* extern const struct super_operations cifs_super_ops;*/
 extern void cifs_read_inode(struct inode *);
 extern void cifs_delete_inode(struct inode *);
 /* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
 
 /* Functions related to inodes */
-extern struct inode_operations cifs_dir_inode_ops;
+extern const struct inode_operations cifs_dir_inode_ops;
 extern int cifs_create(struct inode *, struct dentry *, int, 
 		       struct nameidata *);
 extern struct dentry * cifs_lookup(struct inode *, struct dentry *,
@@ -58,8 +58,8 @@
 extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int cifs_setattr(struct dentry *, struct iattr *);
 
-extern struct inode_operations cifs_file_inode_ops;
-extern struct inode_operations cifs_symlink_inode_ops;
+extern const struct inode_operations cifs_file_inode_ops;
+extern const struct inode_operations cifs_symlink_inode_ops;
 
 /* Functions related to files and directories */
 extern const struct file_operations cifs_file_ops;
@@ -100,5 +100,5 @@
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
 		       unsigned int command, unsigned long arg);
-#define CIFS_VERSION   "1.47"
+#define CIFS_VERSION   "1.48"
 #endif				/* _CIFSFS_H */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 068ef51e..2498d64 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifspdu.h
  *
- *   Copyright (c) International Business Machines  Corp., 2002,2005
+ *   Copyright (c) International Business Machines  Corp., 2002,2007
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -35,9 +35,11 @@
 #define BAD_PROT 0xFFFF
 
 /* SMB command codes */
-/* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
- (ie which include no useful data other than the SMB error code itself).
- Knowing this helps avoid response buffer allocations and copy in some cases */
+/*
+ * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
+ * (ie which include no useful data other than the SMB error code itself).
+ * Knowing this helps avoid response buffer allocations and copy in some cases
+ */
 #define SMB_COM_CREATE_DIRECTORY      0x00 /* trivial response */
 #define SMB_COM_DELETE_DIRECTORY      0x01 /* trivial response */
 #define SMB_COM_CLOSE                 0x04 /* triv req/rsp, timestamp ignored */
@@ -544,7 +546,8 @@
 /*      unsigned char  * NativeOS;      */
 /*	unsigned char  * NativeLanMan;  */
 /*      unsigned char  * PrimaryDomain; */
-	} __attribute__((packed)) resp;	/* NTLM response with or without extended sec*/
+	} __attribute__((packed)) resp;	/* NTLM response 
+					   (with or without extended sec) */
 
 	struct {		/* request format */
 		struct smb_hdr hdr;	/* wct = 10 */
@@ -795,6 +798,8 @@
 	__u16  ByteCount;
 } __attribute__((packed)) OPENX_RSP; 
 
+/* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */
+
 /* Legacy write request for older servers */
 typedef struct smb_com_writex_req {
         struct smb_hdr hdr;     /* wct = 12 */
@@ -1352,11 +1357,13 @@
 #define SMB_QUERY_FILE_UNIX_BASIC       0x200
 #define SMB_QUERY_FILE_UNIX_LINK        0x201
 #define SMB_QUERY_POSIX_ACL             0x204
-#define SMB_QUERY_XATTR                 0x205
+#define SMB_QUERY_XATTR                 0x205  /* e.g. system EA name space */
 #define SMB_QUERY_ATTR_FLAGS            0x206  /* append,immutable etc. */
 #define SMB_QUERY_POSIX_PERMISSION      0x207
 #define SMB_QUERY_POSIX_LOCK            0x208
-/* #define SMB_POSIX_OPEN  		0x209 */
+/* #define SMB_POSIX_OPEN               0x209 */
+/* #define SMB_POSIX_UNLINK             0x20a */
+#define SMB_QUERY_FILE__UNIX_INFO2      0x20b
 #define SMB_QUERY_FILE_INTERNAL_INFO    0x3ee
 #define SMB_QUERY_FILE_ACCESS_INFO      0x3f0
 #define SMB_QUERY_FILE_NAME_INFO2       0x3f1 /* 0x30 bytes */
@@ -1377,8 +1384,10 @@
 #define SMB_SET_ATTR_FLAGS              0x206  /* append, immutable etc. */
 #define SMB_SET_POSIX_LOCK              0x208
 #define SMB_POSIX_OPEN                  0x209
+#define SMB_POSIX_UNLINK                0x20a
+#define SMB_SET_FILE_UNIX_INFO2
 #define SMB_SET_FILE_BASIC_INFO2        0x3ec
-#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
+#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo too */
 #define SMB_FILE_ALL_INFO2              0x3fa
 #define SMB_SET_FILE_ALLOCATION_INFO2   0x3fb
 #define SMB_SET_FILE_END_OF_FILE_INFO2  0x3fc
@@ -1428,7 +1437,7 @@
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
 	struct trans2_resp t2;
 	__u16 ByteCount;
-	__u16 Reserved2;	/* parameter word reserved - present for infolevels > 100 */
+	__u16 Reserved2; /* parameter word is present for infolevels > 100 */
 } __attribute__((packed)) TRANSACTION2_QPI_RSP;
 
 typedef struct smb_com_transaction2_spi_req {
@@ -1461,7 +1470,7 @@
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
 	struct trans2_resp t2;
 	__u16 ByteCount;
-	__u16 Reserved2;	/* parameter word reserved - present for infolevels > 100 */
+	__u16 Reserved2; /* parameter word is present for infolevels > 100 */
 } __attribute__((packed)) TRANSACTION2_SPI_RSP;
 
 struct set_file_rename {
@@ -1627,6 +1636,7 @@
 #define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
 #define SMB_QUERY_CIFS_UNIX_INFO    0x200
 #define SMB_QUERY_POSIX_FS_INFO     0x201
+#define SMB_QUERY_POSIX_WHO_AM_I    0x202
 #define SMB_QUERY_LABEL_INFO        0x3ea
 #define SMB_QUERY_FS_QUOTA_INFO     0x3ee
 #define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
@@ -1659,9 +1669,21 @@
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
 	struct trans2_resp t2;
 	__u16 ByteCount;
-	__u8 Pad;		/* may be three bytes *//* followed by data area */
+	__u8 Pad;	/* may be three bytes? *//* followed by data area */
 } __attribute__((packed)) TRANSACTION2_QFSI_RSP;
 
+typedef struct whoami_rsp_data { /* Query level 0x202 */
+	__u32 flags; /* 0 = Authenticated user 1 = GUEST */
+	__u32 mask; /* which flags bits server understands ie 0x0001 */
+	__u64 unix_user_id;
+	__u64 unix_user_gid;
+	__u32 number_of_supplementary_gids; /* may be zero */
+	__u32 number_of_sids; /* may be zero */
+	__u32 length_of_sid_array; /* in bytes - may be zero */
+	__u32 pad; /* reserved - MBZ */
+	/* __u64 gid_array[0]; */  /* may be empty */
+	/* __u8 * psid_list */  /* may be empty */
+} __attribute__((packed)) WHOAMI_RSP_DATA;
 
 /* SETFSInfo Levels */
 #define SMB_SET_CIFS_UNIX_INFO    0x200
@@ -1858,8 +1880,11 @@
 #define CIFS_UNIX_XATTR_CAP             0x00000004 /* support new namespace   */
 #define CIFS_UNIX_EXTATTR_CAP           0x00000008 /* support chattr/chflag   */
 #define CIFS_UNIX_POSIX_PATHNAMES_CAP   0x00000010 /* Allow POSIX path chars  */
+#define CIFS_UNIX_POSIX_PATH_OPS_CAP    0x00000020 /* Allow new POSIX path based
+						      calls including posix open
+						      and posix unlink */ 
 #ifdef CONFIG_CIFS_POSIX
-#define CIFS_UNIX_CAP_MASK              0x0000001b
+#define CIFS_UNIX_CAP_MASK              0x0000003b
 #else 
 #define CIFS_UNIX_CAP_MASK              0x00000013
 #endif /* CONFIG_CIFS_POSIX */
@@ -1946,7 +1971,7 @@
 	__le32 AlignmentRequirement;
 	__le32 FileNameLength;
 	char FileName[1];
-} __attribute__((packed)) FILE_ALL_INFO;		/* level 0x107 QPathInfo */
+} __attribute__((packed)) FILE_ALL_INFO;	/* level 0x107 QPathInfo */
 
 /* defines for enumerating possible values of the Unix type field below */
 #define UNIX_FILE      0
@@ -1970,11 +1995,11 @@
 	__u64 UniqueId;
 	__le64 Permissions;
 	__le64 Nlinks;
-} __attribute__((packed)) FILE_UNIX_BASIC_INFO;		/* level 0x200 QPathInfo */
+} __attribute__((packed)) FILE_UNIX_BASIC_INFO;	/* level 0x200 QPathInfo */
 
 typedef struct {
 	char LinkDest[1];
-} __attribute__((packed)) FILE_UNIX_LINK_INFO;		/* level 0x201 QPathInfo */
+} __attribute__((packed)) FILE_UNIX_LINK_INFO;	/* level 0x201 QPathInfo */
 
 /* The following three structures are needed only for
 	setting time to NT4 and some older servers via
@@ -2011,7 +2036,7 @@
 	__le64 ChangeTime;
 	__le32 Attributes;
 	__u32 Pad;
-} __attribute__((packed)) FILE_BASIC_INFO;		/* size info, level 0x101 */
+} __attribute__((packed)) FILE_BASIC_INFO;	/* size info, level 0x101 */
 
 struct file_allocation_info {
 	__le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
@@ -2020,7 +2045,7 @@
 
 struct file_end_of_file_info {
 	__le64 FileSize;		/* offset to end of file */
-} __attribute__((packed));	/* size info, level 0x104 for set, 0x106 for query */
+} __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */
 
 struct file_alt_name_info {
 	__u8   alt_name[1];
@@ -2075,6 +2100,19 @@
 
 /* end of POSIX ACL definitions */
 
+typedef struct {
+	__u32 OpenFlags; /* same as NT CreateX */
+	__u32 PosixOpenFlags;
+	__u32 Mode;
+	__u16 Level; /* reply level requested (see QPathInfo levels) */
+	__u16 Pad;  /* reserved - MBZ */
+} __attribute__((packed)) OPEN_PSX_REQ; /* level 0x209 SetPathInfo data */
+
+typedef struct {
+	/* reply varies based on requested level */
+} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
+
+
 struct file_internal_info {
 	__u64  UniqueId; /* inode number */
 } __attribute__((packed));      /* level 0x3ee */
@@ -2238,7 +2276,8 @@
 	1) PosixCreateX - to set and return the mode, inode#, device info and
 	perhaps add a CreateDevice - to create Pipes and other special .inodes
 	Also note POSIX open flags
-	2) Close - to return the last write time to do cache across close more safely
+	2) Close - to return the last write time to do cache across close 
+		more safely
 	3) FindFirst return unique inode number - what about resume key, two 
 	forms short (matches readdir) and full (enough info to cache inodes)
 	4) Mkdir - set mode
@@ -2273,7 +2312,8 @@
 	TRANSACTION2 (18 cases)
 		SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
 		(BB verify that never need to set allocation size)
-		SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
+		SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via
+			 Unix ext?)
 	
 	COPY (note support for copy across directories) - FUTURE, OPTIONAL
 	setting/getting OS/2 EAs - FUTURE (BB can this handle
@@ -2293,13 +2333,13 @@
 	T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
 					Actually need QUERY_FILE_UNIX_INFO since has inode num
 					BB what about a) blksize/blkbits/blocks
-								  b) i_version
-								  c) i_rdev
-								  d) notify mask?
-								  e) generation
-								  f) size_seqcount
+							  b) i_version
+							  c) i_rdev
+							  d) notify mask?
+							  e) generation
+							  f) size_seqcount
 	T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
-	TRANS2_GET_DFS_REFERRAL				  - OPTIONAL but recommended
+	TRANS2_GET_DFS_REFERRAL			  - OPTIONAL but recommended
 	T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
 	
 	
@@ -2338,7 +2378,7 @@
 	__u32 xattr_value_len;
 	char  xattr_name[0];
 	/* followed by xattr_value[xattr_value_len], no pad */
-} __attribute__((packed)) FILE_XATTR_INFO;	/* extended attribute, info level 0x205 */
+} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
 
 
 /* flags for chattr command */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index f1f8225..6148b82 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -23,6 +23,7 @@
 #include <linux/nls.h>
 
 struct statfs;
+struct smb_vol;
 
 /*
  *****************************************************************
@@ -57,7 +58,7 @@
 				int * /* bytes returned */);
 extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
 extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
-extern int is_size_safe_to_change(struct cifsInodeInfo *);
+extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
 extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
 extern unsigned int smbCalcSize(struct smb_hdr *ptr);
 extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
@@ -147,6 +148,8 @@
 			unsigned int *pnum_referrals, 
 			unsigned char ** preferrals,
 			int remap);
+extern void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
+				 struct super_block * sb, struct smb_vol * vol);
 extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
 			struct kstatfs *FSData);
 extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 472e33e..2436410 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -158,9 +158,15 @@
 							nls_codepage);
 			if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
 				mark_open_files_invalid(tcon);
-				rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
-					, nls_codepage);
+				rc = CIFSTCon(0, tcon->ses, tcon->treeName, 
+					      tcon, nls_codepage);
 				up(&tcon->ses->sesSem);
+				/* tell server which Unix caps we support */
+				if (tcon->ses->capabilities & CAP_UNIX)
+					reset_cifs_unix_caps(0 /* no xid */,
+						tcon, 
+						NULL /* we do not know sb */,
+						NULL /* no vol info */);	
 				/* BB FIXME add code to check if wsize needs
 				   update due to negotiated smb buffer size
 				   shrinking */
@@ -298,6 +304,12 @@
 				rc = CIFSTCon(0, tcon->ses, tcon->treeName,
 					      tcon, nls_codepage);
 				up(&tcon->ses->sesSem);
+				/* tell server which Unix caps we support */
+				if (tcon->ses->capabilities & CAP_UNIX)
+					reset_cifs_unix_caps(0 /* no xid */,
+						tcon, 
+						NULL /* do not know sb */,
+						NULL /* no vol info */);
 				/* BB FIXME add code to check if wsize needs
 				update due to negotiated smb buffer size
 				shrinking */
@@ -2812,10 +2824,10 @@
 
 
 /* security id for everyone */
-const static struct cifs_sid sid_everyone = 
+static const struct cifs_sid sid_everyone =
 		{1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
 /* group users */
-const static struct cifs_sid sid_user = 
+static const struct cifs_sid sid_user =
 		{1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
 
 /* Convert CIFS ACL to POSIX form */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2caca06..20ba7dc 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1613,6 +1613,76 @@
 	return rc;
 }
 
+void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon, 
+			  struct super_block * sb, struct smb_vol * vol_info)
+{
+	/* if we are reconnecting then should we check to see if
+	 * any requested capabilities changed locally e.g. via
+	 * remount but we can not do much about it here
+	 * if they have (even if we could detect it by the following)
+	 * Perhaps we could add a backpointer to array of sb from tcon
+	 * or if we change to make all sb to same share the same
+	 * sb as NFS - then we only have one backpointer to sb.
+	 * What if we wanted to mount the server share twice once with
+	 * and once without posixacls or posix paths? */
+	__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
+	   
+	 
+	if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
+		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
+		
+		/* check for reconnect case in which we do not
+		   want to change the mount behavior if we can avoid it */
+		if(vol_info == NULL) {
+			/* turn off POSIX ACL and PATHNAMES if not set 
+			   originally at mount time */
+			if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
+				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
+			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
+				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
+				
+
+			 
+			
+		}
+		
+		cap &= CIFS_UNIX_CAP_MASK;
+		if(vol_info && vol_info->no_psx_acl)
+			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
+		else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
+			cFYI(1,("negotiated posix acl support"));
+			if(sb)
+				sb->s_flags |= MS_POSIXACL;
+		}
+
+		if(vol_info && vol_info->posix_paths == 0)
+			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
+		else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+			cFYI(1,("negotiate posix pathnames"));
+			if(sb)
+				CIFS_SB(sb)->mnt_cifs_flags |= 
+					CIFS_MOUNT_POSIX_PATHS;
+		}
+			
+		cFYI(1,("Negotiate caps 0x%x",(int)cap));
+#ifdef CONFIG_CIFS_DEBUG2
+		if(cap & CIFS_UNIX_FCNTL_CAP)
+			cFYI(1,("FCNTL cap"));
+		if(cap & CIFS_UNIX_EXTATTR_CAP)
+			cFYI(1,("EXTATTR cap"));
+		if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
+			cFYI(1,("POSIX path cap"));
+		if(cap & CIFS_UNIX_XATTR_CAP)
+			cFYI(1,("XATTR cap"));
+		if(cap & CIFS_UNIX_POSIX_ACL_CAP)
+			cFYI(1,("POSIX ACL cap"));
+#endif /* CIFS_DEBUG2 */
+		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
+			cFYI(1,("setting capabilities failed"));
+		}
+	}
+}
+
 int
 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 	   char *mount_data, const char *devname)
@@ -1928,20 +1998,25 @@
 			if (tcon == NULL)
 				rc = -ENOMEM;
 			else {
-				/* check for null share name ie connect to dfs root */
+				/* check for null share name ie connecting to 
+				 * dfs root */
 
-				/* BB check if this works for exactly length three strings */
+				/* BB check if this works for exactly length 
+				 * three strings */
 				if ((strchr(volume_info.UNC + 3, '\\') == NULL)
 				    && (strchr(volume_info.UNC + 3, '/') ==
 					NULL)) {
 					rc = connect_to_dfs_path(xid, pSesInfo,
-							"", cifs_sb->local_nls,
-							cifs_sb->mnt_cifs_flags & 
-							  CIFS_MOUNT_MAP_SPECIAL_CHR);
+						"", cifs_sb->local_nls,
+						cifs_sb->mnt_cifs_flags & 
+						  CIFS_MOUNT_MAP_SPECIAL_CHR);
 					kfree(volume_info.UNC);
 					FreeXid(xid);
 					return -ENODEV;
 				} else {
+					/* BB Do we need to wrap sesSem around
+					 * this TCon call and Unix SetFS as
+					 * we do on SessSetup and reconnect? */
 					rc = CIFSTCon(xid, pSesInfo, 
 						volume_info.UNC,
 						tcon, cifs_sb->local_nls);
@@ -1962,6 +2037,7 @@
 			sb->s_maxbytes = (u64) 1 << 31;	/* 2 GB */
 	}
 
+	/* BB FIXME fix time_gran to be larger for LANMAN sessions */
 	sb->s_time_gran = 100;
 
 /* on error free sesinfo and tcon struct if needed */
@@ -2006,45 +2082,11 @@
 		/* do not care if following two calls succeed - informational */
 		CIFSSMBQFSDeviceInfo(xid, tcon);
 		CIFSSMBQFSAttributeInfo(xid, tcon);
-
-		if (tcon->ses->capabilities & CAP_UNIX) {
-			if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
-				__u64 cap = 
-				       le64_to_cpu(tcon->fsUnixInfo.Capability);
-				cap &= CIFS_UNIX_CAP_MASK;
-				if(volume_info.no_psx_acl)
-					cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
-				else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
-					cFYI(1,("negotiated posix acl support"));
-					sb->s_flags |= MS_POSIXACL;
-				}
-
-				if(volume_info.posix_paths == 0)
-					cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
-				else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
-					cFYI(1,("negotiate posix pathnames"));
-					cifs_sb->mnt_cifs_flags |= 
-						CIFS_MOUNT_POSIX_PATHS;
-				}
-					
-				cFYI(1,("Negotiate caps 0x%x",(int)cap));
-#ifdef CONFIG_CIFS_DEBUG2
-				if(cap & CIFS_UNIX_FCNTL_CAP)
-					cFYI(1,("FCNTL cap"));
-				if(cap & CIFS_UNIX_EXTATTR_CAP)
-					cFYI(1,("EXTATTR cap"));
-				if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
-					cFYI(1,("POSIX path cap"));
-				if(cap & CIFS_UNIX_XATTR_CAP)
-					cFYI(1,("XATTR cap"));
-				if(cap & CIFS_UNIX_POSIX_ACL_CAP)
-					cFYI(1,("POSIX ACL cap"));
-#endif /* CIFS_DEBUG2 */
-				if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
-					cFYI(1,("setting capabilities failed"));
-				}
-			}
-		}
+		
+		/* tell server which Unix caps we support */
+		if (tcon->ses->capabilities & CAP_UNIX)
+			reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
+		
 		if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
 			cifs_sb->wsize = min(cifs_sb->wsize,
 					     (tcon->ses->server->maxBuf -
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index e9dcf5e..a1265c9 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1014,8 +1014,9 @@
 	/* since the write may have blocked check these pointers again */
 	if (file->f_path.dentry) {
 		if (file->f_path.dentry->d_inode) {
-			file->f_path.dentry->d_inode->i_ctime =
-			file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;
+/*BB We could make this contingent on superblock ATIME flag too */
+/*			file->f_path.dentry->d_inode->i_ctime =
+			file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/
 			if (total_written > 0) {
 				if (*poffset > file->f_path.dentry->d_inode->i_size)
 					i_size_write(file->f_path.dentry->d_inode,
@@ -1954,7 +1955,7 @@
    refreshing the inode only on increases in the file size 
    but this is tricky to do without racing with writebehind
    page caching in the current Linux kernel design */
-int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
+int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
 {
 	struct cifsFileInfo *open_file = NULL;
 
@@ -1976,6 +1977,9 @@
 			return 1;
 		}
 
+		if(i_size_read(&cifsInode->vfs_inode) < end_of_file)
+			return 1;
+
 		return 0;
 	} else
 		return 1;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index c4fa91b..37c6ce8 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -90,6 +90,9 @@
 				(*pinode)->i_ino =
 					(unsigned long)findData.UniqueId;
 			} /* note ino incremented to unique num in new_inode */
+			if(sb->s_flags & MS_NOATIME)
+				(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
+				
 			insert_inode_hash(*pinode);
 		}
 
@@ -140,7 +143,7 @@
 		inode->i_gid = le64_to_cpu(findData.Gid);
 		inode->i_nlink = le64_to_cpu(findData.Nlinks);
 
-		if (is_size_safe_to_change(cifsInfo)) {
+		if (is_size_safe_to_change(cifsInfo, end_of_file)) {
 		/* can not safely change the file size here if the
 		   client is writing to it due to potential races */
 
@@ -421,6 +424,8 @@
 				} else /* do we need cast or hash to ino? */
 					(*pinode)->i_ino = inode_num;
 			} /* else ino incremented to unique num in new_inode*/
+			if(sb->s_flags & MS_NOATIME)
+				(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
 			insert_inode_hash(*pinode);
 		}
 		inode = *pinode;
@@ -491,8 +496,8 @@
 		/* BB add code here -
 		   validate if device or weird share or device type? */
 		}
-		if (is_size_safe_to_change(cifsInfo)) {
-			/* can not safely change the file size here if the
+		if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
+			/* can not safely shrink the file size here if the
 			   client is writing to it due to potential races */
 			i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
 
@@ -1359,7 +1364,7 @@
 		and this check ensures that we are not being called from
 		sys_utimes in which case we ought to fail the call back to
 		the user when the server rejects the call */
-		if((rc) && (attrs->ia_valid &&
+		if((rc) && (attrs->ia_valid &
 			 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
 			rc = 0;
 	}
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 8e25996..6baea85 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -77,7 +77,8 @@
 		cifsInode = CIFS_I(old_file->d_inode);
 		if(rc == 0) {
 			old_file->d_inode->i_nlink++;
-			old_file->d_inode->i_ctime = CURRENT_TIME;
+/* BB should we make this contingent on superblock flag NOATIME? */
+/*			old_file->d_inode->i_ctime = CURRENT_TIME;*/
 			/* parent dir timestamps will update from srv
 			within a second, would it really be worth it
 			to set the parent dir cifs inode time to zero
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 782940b..c444798 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -83,6 +83,8 @@
 				return rc;
 			rc = 1;
 		}
+		if(file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
+			(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
 	} else {
 		tmp_dentry = d_alloc(file->f_path.dentry, qstring);
 		if(tmp_dentry == NULL) {
@@ -98,6 +100,8 @@
 			tmp_dentry->d_op = &cifs_dentry_ops;
 		if(*ptmp_inode == NULL)
 			return rc;
+		if(file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
+			(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;			
 		rc = 2;
 	}
 
@@ -222,7 +226,7 @@
 		atomic_set(&cifsInfo->inUse, 1);
 	}
 
-	if (is_size_safe_to_change(cifsInfo)) {
+	if (is_size_safe_to_change(cifsInfo, end_of_file)) {
 		/* can not safely change the file size here if the 
 		client is writing to it due to potential races */
 		i_size_write(tmp_inode, end_of_file);
@@ -351,10 +355,10 @@
 	tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
 	tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
 
-	if (is_size_safe_to_change(cifsInfo)) {
+	if (is_size_safe_to_change(cifsInfo, end_of_file)) {
 		/* can not safely change the file size here if the 
 		client is writing to it due to potential races */
-		i_size_write(tmp_inode,end_of_file);
+		i_size_write(tmp_inode, end_of_file);
 
 	/* 512 bytes (2**9) is the fake blocksize that must be used */
 	/* for this calculation, not the real blocksize */
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
index 4c9fecb..28c8727 100644
--- a/fs/coda/cnode.c
+++ b/fs/coda/cnode.c
@@ -16,7 +16,7 @@
 	return memcmp(fid1, fid2, sizeof(*fid1)) == 0;
 }
 
-static struct inode_operations coda_symlink_inode_operations = {
+static const struct inode_operations coda_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 0c6f7f3..9ddf5ed 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -66,7 +66,7 @@
 	.d_delete	= coda_dentry_delete,
 };
 
-struct inode_operations coda_dir_inode_operations =
+const struct inode_operations coda_dir_inode_operations =
 {
 	.create		= coda_create,
 	.lookup		= coda_lookup,
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 01395de..614175a 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -90,7 +90,7 @@
 }
 
 /* exported operations */
-static struct super_operations coda_super_operations =
+static const struct super_operations coda_super_operations =
 {
 	.alloc_inode	= coda_alloc_inode,
 	.destroy_inode	= coda_destroy_inode,
@@ -271,7 +271,7 @@
 	return error;
 }
 
-struct inode_operations coda_file_inode_operations = {
+const struct inode_operations coda_file_inode_operations = {
 	.permission	= coda_permission,
 	.getattr	= coda_getattr,
 	.setattr	= coda_setattr,
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 214822b..2bf3026 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -30,7 +30,7 @@
                        unsigned int cmd, unsigned long user_data);
 
 /* exported from this file */
-struct inode_operations coda_ioctl_inode_operations =
+const struct inode_operations coda_ioctl_inode_operations =
 {
 	.permission	= coda_ioctl_permission,
 	.setattr	= coda_setattr,
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index 1c82e9a..c57a1fa 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/ctype.h>
@@ -32,8 +33,6 @@
 
 static struct ctl_table_header *fs_table_header;
 
-#define FS_CODA         1       /* Coda file system */
-
 #define CODA_TIMEOUT    3       /* timeout on upcalls to become intrble */
 #define CODA_HARD       5       /* mount type "hard" or "soft" */
 #define CODA_VFS 	 6       /* vfs statistics */
@@ -84,15 +83,11 @@
 	return 0;
 }
 
-static int coda_vfs_stats_get_info( char * buffer, char ** start,
-				    off_t offset, int length)
+static int proc_vfs_stats_show(struct seq_file *m, void *v)
 {
-	int len=0;
-	off_t begin;
 	struct coda_vfs_stats * ps = & coda_vfs_stat;
   
-  /* this works as long as we are below 1024 characters! */
-	len += sprintf( buffer,
+	seq_printf(m,
 			"Coda VFS statistics\n"
 			"===================\n\n"
 			"File Operations:\n"
@@ -132,28 +127,14 @@
 			ps->rmdir,
 			ps->rename,
 			ps->permission); 
-
-	begin = offset;
-	*start = buffer + begin;
-	len -= begin;
-
-	if ( len > length )
-		len = length;
-	if ( len < 0 )
-		len = 0;
-
-	return len;
+	return 0;
 }
 
-static int coda_cache_inv_stats_get_info( char * buffer, char ** start,
-					  off_t offset, int length)
+static int proc_cache_inv_stats_show(struct seq_file *m, void *v)
 {
-	int len=0;
-	off_t begin;
 	struct coda_cache_inv_stats * ps = & coda_cache_inv_stat;
   
-	/* this works as long as we are below 1024 characters! */
-	len += sprintf( buffer,
+	seq_printf(m,
 			"Coda cache invalidation statistics\n"
 			"==================================\n\n"
 			"flush\t\t%9d\n"
@@ -170,31 +151,87 @@
 			ps->zap_vnode,
 			ps->purge_fid,
 			ps->replace );
-  
-	begin = offset;
-	*start = buffer + begin;
-	len -= begin;
-
-	if ( len > length )
-		len = length;
-	if ( len < 0 )
-		len = 0;
-
-	return len;
+	return 0;
 }
 
+static int proc_vfs_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_vfs_stats_show, NULL);
+}
+
+static int proc_cache_inv_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_cache_inv_stats_show, NULL);
+}
+
+static const struct file_operations proc_vfs_stats_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_vfs_stats_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_cache_inv_stats_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_cache_inv_stats_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static ctl_table coda_table[] = {
- 	{CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
- 	{CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec},
- 	{CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats},
- 	{CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats},
- 	{CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec},
-	{ 0 }
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "timeout",
+		.data		= &coda_timeout,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "hard",
+		.data		= &coda_hard,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "vfs_stats",
+		.data		= NULL,
+		.maxlen		= 0,
+		.mode		= 0644,
+		.proc_handler	= &do_reset_coda_vfs_stats
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "cache_inv_stats",
+		.data		= NULL,
+		.maxlen		= 0,
+		.mode		= 0644,
+		.proc_handler	= &do_reset_coda_cache_inv_stats
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "fake_statfs",
+		.data		= &coda_fake_statfs,
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= &proc_dointvec
+	},
+	{}
 };
 
 static ctl_table fs_table[] = {
-       {FS_CODA, "coda",    NULL, 0, 0555, coda_table},
-       {0}
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "coda",
+		.mode		= 0555,
+		.child		= coda_table
+	},
+	{}
 };
 
 
@@ -212,9 +249,6 @@
 
 #endif
 
-#define coda_proc_create(name,get_info) \
-	create_proc_info_entry(name, 0, proc_fs_coda, get_info)
-
 void coda_sysctl_init(void)
 {
 	reset_coda_vfs_stats();
@@ -223,15 +257,21 @@
 #ifdef CONFIG_PROC_FS
 	proc_fs_coda = proc_mkdir("coda", proc_root_fs);
 	if (proc_fs_coda) {
+		struct proc_dir_entry *pde;
+
 		proc_fs_coda->owner = THIS_MODULE;
-		coda_proc_create("vfs_stats", coda_vfs_stats_get_info);
-		coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info);
+		pde = create_proc_entry("vfs_stats", 0, proc_fs_coda);
+		if (pde)
+			pde->proc_fops = &proc_vfs_stats_fops;
+		pde = create_proc_entry("cache_inv_stats", 0, proc_fs_coda);
+		if (pde)
+			pde->proc_fops = &proc_cache_inv_stats_fops;
 	}
 #endif
 
 #ifdef CONFIG_SYSCTL
 	if ( !fs_table_header )
-		fs_table_header = register_sysctl_table(fs_table, 0);
+		fs_table_header = register_sysctl_table(fs_table);
 #endif 
 }
 
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index f92cd30..7b48c03 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -75,8 +75,8 @@
 extern const struct file_operations configfs_dir_operations;
 extern const struct file_operations configfs_file_operations;
 extern const struct file_operations bin_fops;
-extern struct inode_operations configfs_dir_inode_operations;
-extern struct inode_operations configfs_symlink_inode_operations;
+extern const struct inode_operations configfs_dir_inode_operations;
+extern const struct inode_operations configfs_symlink_inode_operations;
 
 extern int configfs_symlink(struct inode *dir, struct dentry *dentry,
 			    const char *symname);
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 1814ba446..34750d5 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -72,11 +72,10 @@
 {
 	struct configfs_dirent * sd;
 
-	sd = kmem_cache_alloc(configfs_dir_cachep, GFP_KERNEL);
+	sd = kmem_cache_zalloc(configfs_dir_cachep, GFP_KERNEL);
 	if (!sd)
 		return NULL;
 
-	memset(sd, 0, sizeof(*sd));
 	atomic_set(&sd->s_count, 1);
 	INIT_LIST_HEAD(&sd->s_links);
 	INIT_LIST_HEAD(&sd->s_children);
@@ -931,7 +930,7 @@
 	return 0;
 }
 
-struct inode_operations configfs_dir_inode_operations = {
+const struct inode_operations configfs_dir_inode_operations = {
 	.mkdir		= configfs_mkdir,
 	.rmdir		= configfs_rmdir,
 	.symlink	= configfs_symlink,
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index fb18917..2ec9bea 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -49,7 +49,7 @@
 	.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
 };
 
-static struct inode_operations configfs_inode_operations ={
+static const struct inode_operations configfs_inode_operations ={
 	.setattr	= configfs_setattr,
 };
 
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index ed67852..6f57300 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -41,7 +41,7 @@
 struct kmem_cache *configfs_dir_cachep;
 static int configfs_mnt_count = 0;
 
-static struct super_operations configfs_ops = {
+static const struct super_operations configfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= generic_delete_inode,
 };
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index fb65e08..22700d2 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -272,7 +272,7 @@
 	}
 }
 
-struct inode_operations configfs_symlink_inode_operations = {
+const struct inode_operations configfs_symlink_inode_operations = {
 	.follow_link = configfs_follow_link,
 	.readlink = generic_readlink,
 	.put_link = configfs_put_link,
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 6db03fb..facd0c8 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -27,8 +27,8 @@
 
 #include <asm/uaccess.h>
 
-static struct super_operations cramfs_ops;
-static struct inode_operations cramfs_dir_inode_operations;
+static const struct super_operations cramfs_ops;
+static const struct inode_operations cramfs_dir_inode_operations;
 static const struct file_operations cramfs_directory_operations;
 static const struct address_space_operations cramfs_aops;
 
@@ -518,11 +518,11 @@
 	.readdir	= cramfs_readdir,
 };
 
-static struct inode_operations cramfs_dir_inode_operations = {
+static const struct inode_operations cramfs_dir_inode_operations = {
 	.lookup		= cramfs_lookup,
 };
 
-static struct super_operations cramfs_ops = {
+static const struct super_operations cramfs_ops = {
 	.put_super	= cramfs_put_super,
 	.remount_fs	= cramfs_remount,
 	.statfs		= cramfs_statfs,
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index bf3901a..682f928 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/namei.h>
 #include <linux/debugfs.h>
 
 static ssize_t default_read_file(struct file *file, char __user *buf,
@@ -44,6 +45,17 @@
 	.open =		default_open,
 };
 
+static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	nd_set_link(nd, dentry->d_inode->i_private);
+	return NULL;
+}
+
+const struct inode_operations debugfs_link_operations = {
+	.readlink       = generic_readlink,
+	.follow_link    = debugfs_follow_link,
+};
+
 static void debugfs_u8_set(void *data, u64 val)
 {
 	*(u8 *)data = val;
@@ -254,7 +266,7 @@
 			blob->size);
 }
 
-static struct file_operations fops_blob = {
+static const struct file_operations fops_blob = {
 	.read =		read_file_blob,
 	.open =		default_open,
 };
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index c692487..7b324cf 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -25,11 +25,13 @@
 #include <linux/namei.h>
 #include <linux/debugfs.h>
 #include <linux/fsnotify.h>
+#include <linux/string.h>
 
 #define DEBUGFS_MAGIC	0x64626720
 
 /* declared over in file.c */
 extern struct file_operations debugfs_file_operations;
+extern struct inode_operations debugfs_link_operations;
 
 static struct vfsmount *debugfs_mount;
 static int debugfs_mount_count;
@@ -51,6 +53,9 @@
 		case S_IFREG:
 			inode->i_fop = &debugfs_file_operations;
 			break;
+		case S_IFLNK:
+			inode->i_op = &debugfs_link_operations;
+			break;
 		case S_IFDIR:
 			inode->i_op = &simple_dir_inode_operations;
 			inode->i_fop = &simple_dir_operations;
@@ -96,6 +101,12 @@
 	return res;
 }
 
+static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode)
+{
+	mode = (mode & S_IALLUGO) | S_IFLNK;
+	return debugfs_mknod(dir, dentry, mode, 0);
+}
+
 static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
 {
 	int res;
@@ -158,10 +169,17 @@
 	mutex_lock(&parent->d_inode->i_mutex);
 	*dentry = lookup_one_len(name, parent, strlen(name));
 	if (!IS_ERR(*dentry)) {
-		if ((mode & S_IFMT) == S_IFDIR)
+		switch (mode & S_IFMT) {
+		case S_IFDIR:
 			error = debugfs_mkdir(parent->d_inode, *dentry, mode);
-		else 
+			break;
+		case S_IFLNK:
+			error = debugfs_link(parent->d_inode, *dentry, mode);
+			break;
+		default:
 			error = debugfs_create(parent->d_inode, *dentry, mode);
+			break;
+		}
 		dput(*dentry);
 	} else
 		error = PTR_ERR(*dentry);
@@ -194,9 +212,7 @@
  * you are responsible here.)  If an error occurs, %NULL will be returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
- * returned.  It is not wise to check for this value, but rather, check for
- * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
- * code.
+ * returned.
  */
 struct dentry *debugfs_create_file(const char *name, mode_t mode,
 				   struct dentry *parent, void *data,
@@ -246,9 +262,7 @@
  * you are responsible here.)  If an error occurs, %NULL will be returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
- * returned.  It is not wise to check for this value, but rather, check for
- * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
- * code.
+ * returned.
  */
 struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
 {
@@ -259,6 +273,47 @@
 EXPORT_SYMBOL_GPL(debugfs_create_dir);
 
 /**
+ * debugfs_create_symlink- create a symbolic link in the debugfs filesystem
+ * @name: a pointer to a string containing the name of the symbolic link to
+ *        create.
+ * @parent: a pointer to the parent dentry for this symbolic link.  This
+ *          should be a directory dentry if set.  If this paramater is NULL,
+ *          then the symbolic link will be created in the root of the debugfs
+ *          filesystem.
+ * @target: a pointer to a string containing the path to the target of the
+ *          symbolic link.
+ *
+ * This function creates a symbolic link with the given name in debugfs that
+ * links to the given target path.
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the debugfs_remove() function when the symbolic
+ * link is to be removed (no automatic cleanup happens if your module is
+ * unloaded, you are responsible here.)  If an error occurs, %NULL will be
+ * returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
+				      const char *target)
+{
+	struct dentry *result;
+	char *link;
+
+	link = kstrdup(target, GFP_KERNEL);
+	if (!link)
+		return NULL;
+
+	result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link,
+				     NULL);
+	if (!result)
+		kfree(link);
+	return result;
+}
+EXPORT_SYMBOL_GPL(debugfs_create_symlink);
+
+/**
  * debugfs_remove - removes a file or directory from the debugfs filesystem
  * @dentry: a pointer to a the dentry of the file or directory to be
  *          removed.
@@ -287,15 +342,22 @@
 	if (debugfs_positive(dentry)) {
 		if (dentry->d_inode) {
 			dget(dentry);
-			if (S_ISDIR(dentry->d_inode->i_mode)) {
+			switch (dentry->d_inode->i_mode & S_IFMT) {
+			case S_IFDIR:
 				ret = simple_rmdir(parent->d_inode, dentry);
 				if (ret)
 					printk(KERN_ERR
 						"DebugFS rmdir on %s failed : "
 						"directory not empty.\n",
 						dentry->d_name.name);
-			} else
+				break;
+			case S_IFLNK:
+				kfree(dentry->d_inode->i_private);
+				/* fall through */
+			default:
 				simple_unlink(parent->d_inode, dentry);
+				break;
+			}
 			if (!ret)
 				d_delete(dentry);
 			dput(dentry);
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 5f7b5a6..643e57b 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -91,7 +91,7 @@
 	return 0;
 }
 
-static struct super_operations devpts_sops = {
+static const struct super_operations devpts_sops = {
 	.statfs		= simple_statfs,
 	.remount_fs	= devpts_remount,
 };
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index ca94a83..61ba670 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -287,7 +287,7 @@
 	return 0;
 }
 
-static struct file_operations rsb_fops = {
+static const struct file_operations rsb_fops = {
 	.owner   = THIS_MODULE,
 	.open    = rsb_open,
 	.read    = seq_read,
@@ -331,7 +331,7 @@
 	return rv;
 }
 
-static struct file_operations waiters_fops = {
+static const struct file_operations waiters_fops = {
 	.owner   = THIS_MODULE,
 	.open    = waiters_open,
 	.read    = waiters_read
diff --git a/fs/dlm/lowcomms-tcp.c b/fs/dlm/lowcomms-tcp.c
index f1efd17..07e0a12 100644
--- a/fs/dlm/lowcomms-tcp.c
+++ b/fs/dlm/lowcomms-tcp.c
@@ -268,12 +268,12 @@
 static int receive_from_sock(struct connection *con)
 {
 	int ret = 0;
-	struct msghdr msg;
-	struct iovec iov[2];
-	mm_segment_t fs;
+	struct msghdr msg = {};
+	struct kvec iov[2];
 	unsigned len;
 	int r;
 	int call_again_soon = 0;
+	int nvec;
 
 	mutex_lock(&con->sock_mutex);
 
@@ -293,21 +293,13 @@
 		cbuf_init(&con->cb, PAGE_CACHE_SIZE);
 	}
 
-	msg.msg_control = NULL;
-	msg.msg_controllen = 0;
-	msg.msg_iovlen = 1;
-	msg.msg_iov = iov;
-	msg.msg_name = NULL;
-	msg.msg_namelen = 0;
-	msg.msg_flags = 0;
-
 	/*
 	 * iov[0] is the bit of the circular buffer between the current end
 	 * point (cb.base + cb.len) and the end of the buffer.
 	 */
 	iov[0].iov_len = con->cb.base - cbuf_data(&con->cb);
 	iov[0].iov_base = page_address(con->rx_page) + cbuf_data(&con->cb);
-	iov[1].iov_len = 0;
+	nvec = 1;
 
 	/*
 	 * iov[1] is the bit of the circular buffer between the start of the
@@ -317,15 +309,12 @@
 		iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&con->cb);
 		iov[1].iov_len = con->cb.base;
 		iov[1].iov_base = page_address(con->rx_page);
-		msg.msg_iovlen = 2;
+		nvec = 2;
 	}
 	len = iov[0].iov_len + iov[1].iov_len;
 
-	fs = get_fs();
-	set_fs(get_ds());
-	r = ret = sock_recvmsg(con->sock, &msg, len,
+	r = ret = kernel_recvmsg(con->sock, &msg, iov, nvec, len,
 			       MSG_DONTWAIT | MSG_NOSIGNAL);
-	set_fs(fs);
 
 	if (ret <= 0)
 		goto out_close;
diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c
index 5352b03..f858fef 100644
--- a/fs/dlm/memory.c
+++ b/fs/dlm/memory.c
@@ -76,9 +76,7 @@
 {
 	struct dlm_lkb *lkb;
 
-	lkb = kmem_cache_alloc(lkb_cache, GFP_KERNEL);
-	if (lkb)
-		memset(lkb, 0, sizeof(*lkb));
+	lkb = kmem_cache_zalloc(lkb_cache, GFP_KERNEL);
 	return lkb;
 }
 
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index d378b7f..40db61d 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -25,7 +25,7 @@
 
 static const char *name_prefix="dlm";
 static struct miscdevice ctl_device;
-static struct file_operations device_fops;
+static const struct file_operations device_fops;
 
 #ifdef CONFIG_COMPAT
 
@@ -759,7 +759,7 @@
 	return 0;
 }
 
-static struct file_operations device_fops = {
+static const struct file_operations device_fops = {
 	.open    = device_open,
 	.release = device_close,
 	.read    = device_read,
@@ -768,7 +768,7 @@
 	.owner   = THIS_MODULE,
 };
 
-static struct file_operations ctl_device_fops = {
+static const struct file_operations ctl_device_fops = {
 	.open    = ctl_device_open,
 	.release = ctl_device_close,
 	.write   = device_write,
diff --git a/fs/dquot.c b/fs/dquot.c
index 0952cc4..b16f991 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -79,6 +79,7 @@
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
 #include <linux/quotaops.h>
+#include <linux/writeback.h> /* for inode_lock, oddly enough.. */
 
 #include <asm/uaccess.h>
 
@@ -600,11 +601,10 @@
 {
 	struct dquot *dquot;
 
-	dquot = kmem_cache_alloc(dquot_cachep, GFP_NOFS);
+	dquot = kmem_cache_zalloc(dquot_cachep, GFP_NOFS);
 	if(!dquot)
 		return NODQUOT;
 
-	memset((caddr_t)dquot, 0, sizeof(struct dquot));
 	mutex_init(&dquot->dq_lock);
 	INIT_LIST_HEAD(&dquot->dq_free);
 	INIT_LIST_HEAD(&dquot->dq_inuse);
@@ -688,23 +688,27 @@
 /* This routine is guarded by dqonoff_mutex mutex */
 static void add_dquot_ref(struct super_block *sb, int type)
 {
-	struct list_head *p;
+	struct inode *inode;
 
 restart:
-	file_list_lock();
-	list_for_each(p, &sb->s_files) {
-		struct file *filp = list_entry(p, struct file, f_u.fu_list);
-		struct inode *inode = filp->f_path.dentry->d_inode;
-		if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
-			struct dentry *dentry = dget(filp->f_path.dentry);
-			file_list_unlock();
-			sb->dq_op->initialize(inode, type);
-			dput(dentry);
-			/* As we may have blocked we had better restart... */
-			goto restart;
-		}
+	spin_lock(&inode_lock);
+	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+		if (!atomic_read(&inode->i_writecount))
+			continue;
+		if (!dqinit_needed(inode, type))
+			continue;
+		if (inode->i_state & (I_FREEING|I_WILL_FREE))
+			continue;
+
+		__iget(inode);
+		spin_unlock(&inode_lock);
+
+		sb->dq_op->initialize(inode, type);
+		iput(inode);
+		/* As we may have blocked we had better restart... */
+		goto restart;
 	}
-	file_list_unlock();
+	spin_unlock(&inode_lock);
 }
 
 /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
@@ -756,15 +760,30 @@
 	}
 }
 
+static void remove_dquot_ref(struct super_block *sb, int type,
+		struct list_head *tofree_head)
+{
+	struct inode *inode;
+
+	spin_lock(&inode_lock);
+	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+		if (!IS_NOQUOTA(inode))
+			remove_inode_dquot_ref(inode, type, tofree_head);
+	}
+	spin_unlock(&inode_lock);
+}
+
 /* Gather all references from inodes and drop them */
 static void drop_dquot_ref(struct super_block *sb, int type)
 {
 	LIST_HEAD(tofree_head);
 
-	down_write(&sb_dqopt(sb)->dqptr_sem);
-	remove_dquot_ref(sb, type, &tofree_head);
-	up_write(&sb_dqopt(sb)->dqptr_sem);
-	put_dquot_list(&tofree_head);
+	if (sb->dq_op) {
+		down_write(&sb_dqopt(sb)->dqptr_sem);
+		remove_dquot_ref(sb, type, &tofree_head);
+		up_write(&sb_dqopt(sb)->dqptr_sem);
+		put_dquot_list(&tofree_head);
+	}
 }
 
 static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
@@ -1822,7 +1841,7 @@
 
 	printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__);
 
-	register_sysctl_table(sys_table, 0);
+	register_sysctl_table(sys_table);
 
 	dquot_cachep = kmem_cache_create("dquot", 
 			sizeof(struct dquot), sizeof(unsigned long) * 4,
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index 4e47623..03ea769 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -20,7 +20,7 @@
 	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
 		if (inode->i_state & (I_FREEING|I_WILL_FREE))
 			continue;
-		invalidate_inode_pages(inode->i_mapping);
+		invalidate_mapping_pages(inode->i_mapping, 0, -1);
 	}
 	spin_unlock(&inode_lock);
 }
diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile
index ca65624..1f11072 100644
--- a/fs/ecryptfs/Makefile
+++ b/fs/ecryptfs/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
 
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o debug.o
+ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o messaging.o netlink.o debug.o
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 7196f50..6ac6306 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1997-2004 Erez Zadok
  * Copyright (C) 2001-2004 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *   		Michael C. Thompson <mcthomps@us.ibm.com>
  *
@@ -207,7 +207,7 @@
 	mutex_init(&crypt_stat->cs_mutex);
 	mutex_init(&crypt_stat->cs_tfm_mutex);
 	mutex_init(&crypt_stat->cs_hash_tfm_mutex);
-	ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED);
+	crypt_stat->flags |= ECRYPTFS_STRUCT_INITIALIZED;
 }
 
 /**
@@ -305,8 +305,7 @@
 	int rc = 0;
 
 	BUG_ON(!crypt_stat || !crypt_stat->tfm
-	       || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-				       ECRYPTFS_STRUCT_INITIALIZED));
+	       || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
 	if (unlikely(ecryptfs_verbosity > 0)) {
 		ecryptfs_printk(KERN_DEBUG, "Key size [%d]; key:\n",
 				crypt_stat->key_size);
@@ -429,10 +428,10 @@
 			goto out;
 		}
 	} else {
-		rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL,
-						      lower_inode,
-						      lower_page_idx);
-		if (rc) {
+		*lower_page = grab_cache_page(lower_inode->i_mapping,
+					      lower_page_idx);
+		if (!(*lower_page)) {
+			rc = -EINVAL;
 			ecryptfs_printk(
 				KERN_ERR, "Error attempting to grab and map "
 				"lower page with index [0x%.16x]; rc = [%d]\n",
@@ -485,7 +484,7 @@
 	lower_inode = ecryptfs_inode_to_lower(ctx->page->mapping->host);
 	inode_info = ecryptfs_inode_to_private(ctx->page->mapping->host);
 	crypt_stat = &inode_info->crypt_stat;
-	if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) {
+	if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
 		rc = ecryptfs_copy_page_to_lower(ctx->page, lower_inode,
 						 ctx->param.lower_file);
 		if (rc)
@@ -617,7 +616,7 @@
 	crypt_stat = &(ecryptfs_inode_to_private(
 			       page->mapping->host)->crypt_stat);
 	lower_inode = ecryptfs_inode_to_lower(page->mapping->host);
-	if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) {
+	if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
 		rc = ecryptfs_do_readpage(file, page, page->index);
 		if (rc)
 			ecryptfs_printk(KERN_ERR, "Error attempting to copy "
@@ -828,9 +827,7 @@
 		mutex_unlock(&crypt_stat->cs_tfm_mutex);
 		goto out;
 	}
-	crypto_blkcipher_set_flags(crypt_stat->tfm,
-				   (ECRYPTFS_DEFAULT_CHAINING_MODE
-				    | CRYPTO_TFM_REQ_WEAK_KEY));
+	crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
 	mutex_unlock(&crypt_stat->cs_tfm_mutex);
 	rc = 0;
 out:
@@ -865,7 +862,10 @@
 			ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
 	} else
 		crypt_stat->header_extent_size = PAGE_CACHE_SIZE;
-	crypt_stat->num_header_extents_at_front = 1;
+	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+		crypt_stat->num_header_extents_at_front = 0;
+	else
+		crypt_stat->num_header_extents_at_front = 1;
 }
 
 /**
@@ -881,7 +881,7 @@
 
 	BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE);
 	BUG_ON(crypt_stat->iv_bytes <= 0);
-	if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID)) {
+	if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
 		rc = -EINVAL;
 		ecryptfs_printk(KERN_WARNING, "Session key not valid; "
 				"cannot generate root IV\n");
@@ -898,8 +898,7 @@
 out:
 	if (rc) {
 		memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes);
-		ECRYPTFS_SET_FLAG(crypt_stat->flags,
-				  ECRYPTFS_SECURITY_WARNING);
+		crypt_stat->flags |= ECRYPTFS_SECURITY_WARNING;
 	}
 	return rc;
 }
@@ -907,7 +906,7 @@
 static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat)
 {
 	get_random_bytes(crypt_stat->key, crypt_stat->key_size);
-	ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+	crypt_stat->flags |= ECRYPTFS_KEY_VALID;
 	ecryptfs_compute_root_iv(crypt_stat);
 	if (unlikely(ecryptfs_verbosity > 0)) {
 		ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n");
@@ -917,6 +916,22 @@
 }
 
 /**
+ * ecryptfs_copy_mount_wide_flags_to_inode_flags
+ *
+ * This function propagates the mount-wide flags to individual inode
+ * flags.
+ */
+static void ecryptfs_copy_mount_wide_flags_to_inode_flags(
+	struct ecryptfs_crypt_stat *crypt_stat,
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
+{
+	if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED)
+		crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+	if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
+		crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED;
+}
+
+/**
  * ecryptfs_set_default_crypt_stat_vals
  * @crypt_stat
  *
@@ -926,10 +941,12 @@
 	struct ecryptfs_crypt_stat *crypt_stat,
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
 {
+	ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
+						      mount_crypt_stat);
 	ecryptfs_set_default_sizes(crypt_stat);
 	strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER);
 	crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES;
-	ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+	crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
 	crypt_stat->file_version = ECRYPTFS_FILE_VERSION;
 	crypt_stat->mount_crypt_stat = mount_crypt_stat;
 }
@@ -969,8 +986,10 @@
 	if (mount_crypt_stat->global_auth_tok) {
 		ecryptfs_printk(KERN_DEBUG, "Initializing context for new "
 				"file using mount_crypt_stat\n");
-		ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
-		ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+		crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
+		crypt_stat->flags |= ECRYPTFS_KEY_VALID;
+		ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
+							      mount_crypt_stat);
 		memcpy(crypt_stat->keysigs[crypt_stat->num_keysigs++],
 		       mount_crypt_stat->global_auth_tok_sig,
 		       ECRYPTFS_SIG_SIZE_HEX);
@@ -1003,7 +1022,7 @@
  *
  * Returns one if marker found; zero if not found
  */
-int contains_ecryptfs_marker(char *data)
+static int contains_ecryptfs_marker(char *data)
 {
 	u32 m_1, m_2;
 
@@ -1029,7 +1048,8 @@
 /* Add support for additional flags by adding elements here. */
 static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {
 	{0x00000001, ECRYPTFS_ENABLE_HMAC},
-	{0x00000002, ECRYPTFS_ENCRYPTED}
+	{0x00000002, ECRYPTFS_ENCRYPTED},
+	{0x00000004, ECRYPTFS_METADATA_IN_XATTR}
 };
 
 /**
@@ -1052,11 +1072,9 @@
 	for (i = 0; i < ((sizeof(ecryptfs_flag_map)
 			  / sizeof(struct ecryptfs_flag_map_elem))); i++)
 		if (flags & ecryptfs_flag_map[i].file_flag) {
-			ECRYPTFS_SET_FLAG(crypt_stat->flags,
-					  ecryptfs_flag_map[i].local_flag);
+			crypt_stat->flags |= ecryptfs_flag_map[i].local_flag;
 		} else
-			ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
-					    ecryptfs_flag_map[i].local_flag);
+			crypt_stat->flags &= ~(ecryptfs_flag_map[i].local_flag);
 	/* Version is in top 8 bits of the 32-bit flag vector */
 	crypt_stat->file_version = ((flags >> 24) & 0xFF);
 	(*bytes_read) = 4;
@@ -1093,8 +1111,7 @@
 
 	for (i = 0; i < ((sizeof(ecryptfs_flag_map)
 			  / sizeof(struct ecryptfs_flag_map_elem))); i++)
-		if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-					ecryptfs_flag_map[i].local_flag))
+		if (crypt_stat->flags & ecryptfs_flag_map[i].local_flag)
 			flags |= ecryptfs_flag_map[i].file_flag;
 	/* Version is in top 8 bits of the 32-bit flag vector */
 	flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000);
@@ -1189,8 +1206,8 @@
  *
  * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_read_header_region(char *data, struct dentry *dentry,
-				struct vfsmount *mnt)
+static int ecryptfs_read_header_region(char *data, struct dentry *dentry,
+				       struct vfsmount *mnt)
 {
 	struct file *lower_file;
 	mm_segment_t oldfs;
@@ -1219,9 +1236,25 @@
 	return rc;
 }
 
-static void
-write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat,
-		      size_t *written)
+int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry,
+					     struct vfsmount *mnt)
+{
+	int rc;
+
+	rc = ecryptfs_read_header_region(data, dentry, mnt);
+	if (rc)
+		goto out;
+	if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES))
+		rc = -EINVAL;
+out:
+	return rc;
+}
+
+
+void
+ecryptfs_write_header_metadata(char *virt,
+			       struct ecryptfs_crypt_stat *crypt_stat,
+			       size_t *written)
 {
 	u32 header_extent_size;
 	u16 num_header_extents_at_front;
@@ -1270,9 +1303,9 @@
  *
  * Returns zero on success
  */
-int ecryptfs_write_headers_virt(char *page_virt,
-				struct ecryptfs_crypt_stat *crypt_stat,
-				struct dentry *ecryptfs_dentry)
+static int ecryptfs_write_headers_virt(char *page_virt, size_t *size,
+				       struct ecryptfs_crypt_stat *crypt_stat,
+				       struct dentry *ecryptfs_dentry)
 {
 	int rc;
 	size_t written;
@@ -1283,7 +1316,8 @@
 	offset += written;
 	write_ecryptfs_flags((page_virt + offset), crypt_stat, &written);
 	offset += written;
-	write_header_metadata((page_virt + offset), crypt_stat, &written);
+	ecryptfs_write_header_metadata((page_virt + offset), crypt_stat,
+				       &written);
 	offset += written;
 	rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat,
 					      ecryptfs_dentry, &written,
@@ -1291,11 +1325,70 @@
 	if (rc)
 		ecryptfs_printk(KERN_WARNING, "Error generating key packet "
 				"set; rc = [%d]\n", rc);
+	if (size) {
+		offset += written;
+		*size = offset;
+	}
+	return rc;
+}
+
+static int ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
+					       struct file *lower_file,
+					       char *page_virt)
+{
+	mm_segment_t oldfs;
+	int current_header_page;
+	int header_pages;
+	ssize_t size;
+	int rc = 0;
+
+	lower_file->f_pos = 0;
+	oldfs = get_fs();
+	set_fs(get_ds());
+	size = vfs_write(lower_file, (char __user *)page_virt, PAGE_CACHE_SIZE,
+			 &lower_file->f_pos);
+	if (size < 0) {
+		rc = (int)size;
+		printk(KERN_ERR "Error attempting to write lower page; "
+		       "rc = [%d]\n", rc);
+		set_fs(oldfs);
+		goto out;
+	}
+	header_pages = ((crypt_stat->header_extent_size
+			 * crypt_stat->num_header_extents_at_front)
+			/ PAGE_CACHE_SIZE);
+	memset(page_virt, 0, PAGE_CACHE_SIZE);
+	current_header_page = 1;
+	while (current_header_page < header_pages) {
+		size = vfs_write(lower_file, (char __user *)page_virt,
+				 PAGE_CACHE_SIZE, &lower_file->f_pos);
+		if (size < 0) {
+			rc = (int)size;
+			printk(KERN_ERR "Error attempting to write lower page; "
+			       "rc = [%d]\n", rc);
+			set_fs(oldfs);
+			goto out;
+		}
+		current_header_page++;
+	}
+	set_fs(oldfs);
+out:
+	return rc;
+}
+
+static int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
+					    struct ecryptfs_crypt_stat *crypt_stat,
+					    char *page_virt, size_t size)
+{
+	int rc;
+
+	rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt,
+			       size, 0);
 	return rc;
 }
 
 /**
- * ecryptfs_write_headers
+ * ecryptfs_write_metadata
  * @lower_file: The lower file struct, which was returned from dentry_open
  *
  * Write the file headers out.  This will likely involve a userspace
@@ -1306,22 +1399,18 @@
  *
  * Returns zero on success; non-zero on error
  */
-int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
-			   struct file *lower_file)
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
+			    struct file *lower_file)
 {
-	mm_segment_t oldfs;
 	struct ecryptfs_crypt_stat *crypt_stat;
 	char *page_virt;
-	int current_header_page;
-	int header_pages;
+	size_t size;
 	int rc = 0;
 
 	crypt_stat = &ecryptfs_inode_to_private(
 		ecryptfs_dentry->d_inode)->crypt_stat;
-	if (likely(ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-				       ECRYPTFS_ENCRYPTED))) {
-		if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-					 ECRYPTFS_KEY_VALID)) {
+	if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
+		if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
 			ecryptfs_printk(KERN_DEBUG, "Key is "
 					"invalid; bailing out\n");
 			rc = -EINVAL;
@@ -1334,54 +1423,42 @@
 		goto out;
 	}
 	/* Released in this function */
-	page_virt = kmem_cache_alloc(ecryptfs_header_cache_0, GFP_USER);
+	page_virt = kmem_cache_zalloc(ecryptfs_header_cache_0, GFP_USER);
 	if (!page_virt) {
 		ecryptfs_printk(KERN_ERR, "Out of memory\n");
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(page_virt, 0, PAGE_CACHE_SIZE);
-	rc = ecryptfs_write_headers_virt(page_virt, crypt_stat,
-					 ecryptfs_dentry);
+	rc = ecryptfs_write_headers_virt(page_virt, &size, crypt_stat,
+  					 ecryptfs_dentry);
 	if (unlikely(rc)) {
 		ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n");
 		memset(page_virt, 0, PAGE_CACHE_SIZE);
 		goto out_free;
 	}
-	ecryptfs_printk(KERN_DEBUG,
-			"Writing key packet set to underlying file\n");
-	lower_file->f_pos = 0;
-	oldfs = get_fs();
-	set_fs(get_ds());
-	ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->"
-			"write() w/ header page; lower_file->f_pos = "
-			"[0x%.16x]\n", lower_file->f_pos);
-	lower_file->f_op->write(lower_file, (char __user *)page_virt,
-				PAGE_CACHE_SIZE, &lower_file->f_pos);
-	header_pages = ((crypt_stat->header_extent_size
-			 * crypt_stat->num_header_extents_at_front)
-			/ PAGE_CACHE_SIZE);
-	memset(page_virt, 0, PAGE_CACHE_SIZE);
-	current_header_page = 1;
-	while (current_header_page < header_pages) {
-		ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->"
-				"write() w/ zero'd page; lower_file->f_pos = "
-				"[0x%.16x]\n", lower_file->f_pos);
-		lower_file->f_op->write(lower_file, (char __user *)page_virt,
-					PAGE_CACHE_SIZE, &lower_file->f_pos);
-		current_header_page++;
+	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+		rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry,
+						      crypt_stat, page_virt,
+						      size);
+	else
+		rc = ecryptfs_write_metadata_to_contents(crypt_stat, lower_file,
+							 page_virt);
+	if (rc) {
+		printk(KERN_ERR "Error writing metadata out to lower file; "
+		       "rc = [%d]\n", rc);
+		goto out_free;
 	}
-	set_fs(oldfs);
-	ecryptfs_printk(KERN_DEBUG,
-			"Done writing key packet set to underlying file.\n");
 out_free:
 	kmem_cache_free(ecryptfs_header_cache_0, page_virt);
 out:
 	return rc;
 }
 
+#define ECRYPTFS_DONT_VALIDATE_HEADER_SIZE 0
+#define ECRYPTFS_VALIDATE_HEADER_SIZE 1
 static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
-				 char *virt, int *bytes_read)
+				 char *virt, int *bytes_read,
+				 int validate_header_size)
 {
 	int rc = 0;
 	u32 header_extent_size;
@@ -1396,9 +1473,10 @@
 	crypt_stat->num_header_extents_at_front =
 		(int)num_header_extents_at_front;
 	(*bytes_read) = 6;
-	if ((crypt_stat->header_extent_size
-	     * crypt_stat->num_header_extents_at_front)
-	    < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
+	if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE)
+	    && ((crypt_stat->header_extent_size
+		 * crypt_stat->num_header_extents_at_front)
+		< ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) {
 		rc = -EINVAL;
 		ecryptfs_printk(KERN_WARNING, "Invalid header extent size: "
 				"[%d]\n", crypt_stat->header_extent_size);
@@ -1429,7 +1507,8 @@
  */
 static int ecryptfs_read_headers_virt(char *page_virt,
 				      struct ecryptfs_crypt_stat *crypt_stat,
-				      struct dentry *ecryptfs_dentry)
+				      struct dentry *ecryptfs_dentry,
+				      int validate_header_size)
 {
 	int rc = 0;
 	int offset;
@@ -1463,7 +1542,7 @@
 	offset += bytes_read;
 	if (crypt_stat->file_version >= 1) {
 		rc = parse_header_metadata(crypt_stat, (page_virt + offset),
-					   &bytes_read);
+					   &bytes_read, validate_header_size);
 		if (rc) {
 			ecryptfs_printk(KERN_WARNING, "Error reading header "
 					"metadata; rc = [%d]\n", rc);
@@ -1478,12 +1557,60 @@
 }
 
 /**
- * ecryptfs_read_headers
+ * ecryptfs_read_xattr_region
+ *
+ * Attempts to read the crypto metadata from the extended attribute
+ * region of the lower file.
+ */
+int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry)
+{
+	ssize_t size;
+	int rc = 0;
+
+	size = ecryptfs_getxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME,
+				 page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE);
+	if (size < 0) {
+		printk(KERN_DEBUG "Error attempting to read the [%s] "
+		       "xattr from the lower file; return value = [%zd]\n",
+		       ECRYPTFS_XATTR_NAME, size);
+		rc = -EINVAL;
+		goto out;
+	}
+out:
+	return rc;
+}
+
+int ecryptfs_read_and_validate_xattr_region(char *page_virt,
+					    struct dentry *ecryptfs_dentry)
+{
+	int rc;
+
+	rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_dentry);
+	if (rc)
+		goto out;
+	if (!contains_ecryptfs_marker(page_virt	+ ECRYPTFS_FILE_SIZE_BYTES)) {
+		printk(KERN_WARNING "Valid data found in [%s] xattr, but "
+			"the marker is invalid\n", ECRYPTFS_XATTR_NAME);
+		rc = -EINVAL;
+	}
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_read_metadata
+ *
+ * Common entry point for reading file metadata. From here, we could
+ * retrieve the header information from the header region of the file,
+ * the xattr region of the file, or some other repostory that is
+ * stored separately from the file itself. The current implementation
+ * supports retrieving the metadata information from the file contents
+ * and from the xattr region.
  *
  * Returns zero if valid headers found and parsed; non-zero otherwise
  */
-int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
-			  struct file *lower_file)
+int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry,
+			   struct file *lower_file)
 {
 	int rc = 0;
 	char *page_virt = NULL;
@@ -1491,7 +1618,12 @@
 	ssize_t bytes_read;
 	struct ecryptfs_crypt_stat *crypt_stat =
 	    &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
+		&ecryptfs_superblock_to_private(
+			ecryptfs_dentry->d_sb)->mount_crypt_stat;
 
+	ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
+						      mount_crypt_stat);
 	/* Read the first page from the underlying file */
 	page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER);
 	if (!page_virt) {
@@ -1512,11 +1644,36 @@
 		goto out;
 	}
 	rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
-					ecryptfs_dentry);
+					ecryptfs_dentry,
+					ECRYPTFS_VALIDATE_HEADER_SIZE);
 	if (rc) {
-		ecryptfs_printk(KERN_DEBUG, "Valid eCryptfs headers not "
-				"found\n");
-		rc = -EINVAL;
+		rc = ecryptfs_read_xattr_region(page_virt,
+						ecryptfs_dentry);
+		if (rc) {
+			printk(KERN_DEBUG "Valid eCryptfs headers not found in "
+			       "file header region or xattr region\n");
+			rc = -EINVAL;
+			goto out;
+		}
+		rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
+						ecryptfs_dentry,
+						ECRYPTFS_DONT_VALIDATE_HEADER_SIZE);
+		if (rc) {
+			printk(KERN_DEBUG "Valid eCryptfs headers not found in "
+			       "file xattr region either\n");
+			rc = -EINVAL;
+		}
+		if (crypt_stat->mount_crypt_stat->flags
+		    & ECRYPTFS_XATTR_METADATA_ENABLED) {
+			crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+		} else {
+			printk(KERN_WARNING "Attempt to access file with "
+			       "crypto metadata only in the extended attribute "
+			       "region, but eCryptfs was mounted without "
+			       "xattr support enabled. eCryptfs will not treat "
+			       "this like an encrypted file.\n");
+			rc = -EINVAL;
+		}
 	}
 out:
 	if (page_virt) {
diff --git a/fs/ecryptfs/debug.c b/fs/ecryptfs/debug.c
index 61f8e89..434c7ef 100644
--- a/fs/ecryptfs/debug.c
+++ b/fs/ecryptfs/debug.c
@@ -36,7 +36,7 @@
 
 	ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n",
 			auth_tok);
-	if (ECRYPTFS_CHECK_FLAG(auth_tok->flags, ECRYPTFS_PRIVATE_KEY)) {
+	if (auth_tok->flags & ECRYPTFS_PRIVATE_KEY) {
 		ecryptfs_printk(KERN_DEBUG, " * private key type\n");
 		ecryptfs_printk(KERN_DEBUG, " * (NO PRIVATE KEY SUPPORT "
 				"IN ECRYPTFS VERSION 0.1)\n");
@@ -46,8 +46,8 @@
 				ECRYPTFS_SALT_SIZE);
 		salt[ECRYPTFS_SALT_SIZE * 2] = '\0';
 		ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt);
-		if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags,
-					ECRYPTFS_PERSISTENT_PASSWORD)) {
+		if (auth_tok->token.password.flags &
+		    ECRYPTFS_PERSISTENT_PASSWORD) {
 			ecryptfs_printk(KERN_DEBUG, " * persistent\n");
 		}
 		memcpy(sig, auth_tok->token.password.signature,
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index afb64bd..403e3ba 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -4,8 +4,10 @@
  *
  * Copyright (C) 1997-2003 Erez Zadok
  * Copyright (C) 2001-2003 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
+ *              Trevor S. Highland <trevor.highland@gmail.com>
+ *              Tyler Hicks <tyhicks@ou.edu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -31,22 +33,25 @@
 #include <linux/fs_stack.h>
 #include <linux/namei.h>
 #include <linux/scatterlist.h>
+#include <linux/hash.h>
 
 /* Version verification for shared data structures w/ userspace */
 #define ECRYPTFS_VERSION_MAJOR 0x00
 #define ECRYPTFS_VERSION_MINOR 0x04
-#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x01
+#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x02
 /* These flags indicate which features are supported by the kernel
  * module; userspace tools such as the mount helper read
  * ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine
  * how to behave. */
-#define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001
-#define ECRYPTFS_VERSIONING_PUBKEY 0x00000002
+#define ECRYPTFS_VERSIONING_PASSPHRASE            0x00000001
+#define ECRYPTFS_VERSIONING_PUBKEY                0x00000002
 #define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
-#define ECRYPTFS_VERSIONING_POLICY 0x00000008
+#define ECRYPTFS_VERSIONING_POLICY                0x00000008
+#define ECRYPTFS_VERSIONING_XATTR                 0x00000010
 #define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
-                                  | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH)
-
+				  | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
+				  | ECRYPTFS_VERSIONING_PUBKEY \
+				  | ECRYPTFS_VERSIONING_XATTR)
 #define ECRYPTFS_MAX_PASSWORD_LENGTH 64
 #define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
 #define ECRYPTFS_SALT_SIZE 8
@@ -60,10 +65,25 @@
 #define ECRYPTFS_MAX_KEY_BYTES 64
 #define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512
 #define ECRYPTFS_DEFAULT_IV_BYTES 16
-#define ECRYPTFS_FILE_VERSION 0x01
+#define ECRYPTFS_FILE_VERSION 0x02
 #define ECRYPTFS_DEFAULT_HEADER_EXTENT_SIZE 8192
 #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
 #define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192
+#define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32
+#define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ
+#define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3)
+#define ECRYPTFS_NLMSG_HELO 100
+#define ECRYPTFS_NLMSG_QUIT 101
+#define ECRYPTFS_NLMSG_REQUEST 102
+#define ECRYPTFS_NLMSG_RESPONSE 103
+#define ECRYPTFS_MAX_PKI_NAME_BYTES 16
+#define ECRYPTFS_DEFAULT_NUM_USERS 4
+#define ECRYPTFS_MAX_NUM_USERS 32768
+#define ECRYPTFS_TRANSPORT_NETLINK 0
+#define ECRYPTFS_TRANSPORT_CONNECTOR 1
+#define ECRYPTFS_TRANSPORT_RELAYFS 2
+#define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_NETLINK
+#define ECRYPTFS_XATTR_NAME "user.ecryptfs"
 
 #define RFC2440_CIPHER_DES3_EDE 0x02
 #define RFC2440_CIPHER_CAST_5 0x03
@@ -74,9 +94,7 @@
 #define RFC2440_CIPHER_TWOFISH 0x0a
 #define RFC2440_CIPHER_CAST_6 0x0b
 
-#define ECRYPTFS_SET_FLAG(flag_bit_vector, flag) (flag_bit_vector |= (flag))
-#define ECRYPTFS_CLEAR_FLAG(flag_bit_vector, flag) (flag_bit_vector &= ~(flag))
-#define ECRYPTFS_CHECK_FLAG(flag_bit_vector, flag) (flag_bit_vector & (flag))
+#define RFC2440_CIPHER_RSA 0x01
 
 /**
  * For convenience, we may need to pass around the encrypted session
@@ -114,6 +132,14 @@
 
 enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY};
 
+struct ecryptfs_private_key {
+	u32 key_size;
+	u32 data_len;
+	u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
+	char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1];
+	u8 data[];
+};
+
 /* May be a password or a private key */
 struct ecryptfs_auth_tok {
 	u16 version; /* 8-bit major and 8-bit minor */
@@ -123,7 +149,7 @@
 	u8 reserved[32];
 	union {
 		struct ecryptfs_password password;
-		/* Private key is in future eCryptfs releases */
+		struct ecryptfs_private_key private_key;
 	} token;
 } __attribute__ ((packed));
 
@@ -176,10 +202,14 @@
 #define ECRYPTFS_FILE_SIZE_BYTES 8
 #define ECRYPTFS_DEFAULT_CIPHER "aes"
 #define ECRYPTFS_DEFAULT_KEY_BYTES 16
-#define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC
 #define ECRYPTFS_DEFAULT_HASH "md5"
+#define ECRYPTFS_TAG_1_PACKET_TYPE 0x01
 #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C
 #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED
+#define ECRYPTFS_TAG_64_PACKET_TYPE 0x40
+#define ECRYPTFS_TAG_65_PACKET_TYPE 0x41
+#define ECRYPTFS_TAG_66_PACKET_TYPE 0x42
+#define ECRYPTFS_TAG_67_PACKET_TYPE 0x43
 #define MD5_DIGEST_SIZE 16
 
 /**
@@ -196,6 +226,8 @@
 #define ECRYPTFS_ENABLE_HMAC        0x00000020
 #define ECRYPTFS_ENCRYPT_IV_PAGES   0x00000040
 #define ECRYPTFS_KEY_VALID          0x00000080
+#define ECRYPTFS_METADATA_IN_XATTR  0x00000100
+#define ECRYPTFS_VIEW_AS_ENCRYPTED  0x00000200
 	u32 flags;
 	unsigned int file_version;
 	size_t iv_bytes;
@@ -242,6 +274,8 @@
 struct ecryptfs_mount_crypt_stat {
 	/* Pointers to memory we do not own, do not free these */
 #define ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED 0x00000001
+#define ECRYPTFS_XATTR_METADATA_ENABLED        0x00000002
+#define ECRYPTFS_ENCRYPTED_VIEW_ENABLED        0x00000004
 	u32 flags;
 	struct ecryptfs_auth_tok *global_auth_tok;
 	struct key *global_auth_tok_key;
@@ -272,6 +306,33 @@
 	struct ecryptfs_auth_tok auth_tok;
 };
 
+struct ecryptfs_message {
+	u32 index;
+	u32 data_len;
+	u8 data[];
+};
+
+struct ecryptfs_msg_ctx {
+#define ECRYPTFS_MSG_CTX_STATE_FREE      0x0001
+#define ECRYPTFS_MSG_CTX_STATE_PENDING   0x0002
+#define ECRYPTFS_MSG_CTX_STATE_DONE      0x0003
+	u32 state;
+	unsigned int index;
+	unsigned int counter;
+	struct ecryptfs_message *msg;
+	struct task_struct *task;
+	struct list_head node;
+	struct mutex mux;
+};
+
+extern unsigned int ecryptfs_transport;
+
+struct ecryptfs_daemon_id {
+	pid_t pid;
+	uid_t uid;
+	struct hlist_node id_chain;
+};
+
 static inline struct ecryptfs_file_info *
 ecryptfs_file_to_private(struct file *file)
 {
@@ -385,13 +446,16 @@
 
 extern const struct file_operations ecryptfs_main_fops;
 extern const struct file_operations ecryptfs_dir_fops;
-extern struct inode_operations ecryptfs_main_iops;
-extern struct inode_operations ecryptfs_dir_iops;
-extern struct inode_operations ecryptfs_symlink_iops;
-extern struct super_operations ecryptfs_sops;
+extern const struct inode_operations ecryptfs_main_iops;
+extern const struct inode_operations ecryptfs_dir_iops;
+extern const struct inode_operations ecryptfs_symlink_iops;
+extern const struct super_operations ecryptfs_sops;
 extern struct dentry_operations ecryptfs_dops;
 extern struct address_space_operations ecryptfs_aops;
 extern int ecryptfs_verbosity;
+extern unsigned int ecryptfs_message_buf_len;
+extern signed long ecryptfs_message_wait_timeout;
+extern unsigned int ecryptfs_number_of_users;
 
 extern struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
 extern struct kmem_cache *ecryptfs_file_info_cache;
@@ -401,7 +465,9 @@
 extern struct kmem_cache *ecryptfs_header_cache_0;
 extern struct kmem_cache *ecryptfs_header_cache_1;
 extern struct kmem_cache *ecryptfs_header_cache_2;
+extern struct kmem_cache *ecryptfs_xattr_cache;
 extern struct kmem_cache *ecryptfs_lower_page_cache;
+extern struct kmem_cache *ecryptfs_key_record_cache;
 
 int ecryptfs_interpose(struct dentry *hidden_dentry,
 		       struct dentry *this_dentry, struct super_block *sb,
@@ -427,9 +493,13 @@
 int ecryptfs_crypto_api_algify_cipher_name(char **algified_name,
 					   char *cipher_name,
 					   char *chaining_modifier);
-int ecryptfs_write_inode_size_to_header(struct file *lower_file,
-					struct inode *lower_inode,
-					struct inode *inode);
+#define ECRYPTFS_LOWER_I_MUTEX_NOT_HELD 0
+#define ECRYPTFS_LOWER_I_MUTEX_HELD 1
+int ecryptfs_write_inode_size_to_metadata(struct file *lower_file,
+					  struct inode *lower_inode,
+					  struct inode *inode,
+					  struct dentry *ecryptfs_dentry,
+					  int lower_i_mutex_held);
 int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
 			    struct file *lower_file,
 			    unsigned long lower_page_index, int byte_offset,
@@ -442,26 +512,20 @@
 				struct file *lower_file);
 int ecryptfs_do_readpage(struct file *file, struct page *page,
 			 pgoff_t lower_page_index);
-int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
-				     char **lower_virt,
-				     struct inode *lower_inode,
-				     unsigned long lower_page_index);
 int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
 					      struct inode *lower_inode,
 					      struct writeback_control *wbc);
 int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx);
 int ecryptfs_decrypt_page(struct file *file, struct page *page);
-int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
+			    struct file *lower_file);
+int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry,
 			   struct file *lower_file);
-int ecryptfs_write_headers_virt(char *page_virt,
-				struct ecryptfs_crypt_stat *crypt_stat,
-				struct dentry *ecryptfs_dentry);
-int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
-			  struct file *lower_file);
 int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry);
-int contains_ecryptfs_marker(char *data);
-int ecryptfs_read_header_region(char *data, struct dentry *dentry,
-				struct vfsmount *mnt);
+int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry,
+					     struct vfsmount *mnt);
+int ecryptfs_read_and_validate_xattr_region(char *page_virt,
+					    struct dentry *ecryptfs_dentry);
 u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat);
 int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code);
 void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat);
@@ -484,5 +548,37 @@
 			     struct dentry *lower_dentry,
 			     struct vfsmount *lower_mnt, int flags);
 int ecryptfs_close_lower_file(struct file *lower_file);
+ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
+			  size_t size);
+int
+ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+		  size_t size, int flags);
+int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry);
+int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid);
+int ecryptfs_process_quit(uid_t uid, pid_t pid);
+int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
+			      pid_t pid, u32 seq);
+int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+			  struct ecryptfs_msg_ctx **msg_ctx);
+int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
+			       struct ecryptfs_message **emsg);
+int ecryptfs_init_messaging(unsigned int transport);
+void ecryptfs_release_messaging(unsigned int transport);
+
+int ecryptfs_send_netlink(char *data, int data_len,
+			  struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+			  u16 msg_flags, pid_t daemon_pid);
+int ecryptfs_init_netlink(void);
+void ecryptfs_release_netlink(void);
+
+int ecryptfs_send_connector(char *data, int data_len,
+			    struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+			    u16 msg_flags, pid_t daemon_pid);
+int ecryptfs_init_connector(void);
+void ecryptfs_release_connector(void);
+void
+ecryptfs_write_header_metadata(char *virt,
+			       struct ecryptfs_crypt_stat *crypt_stat,
+			       size_t *written);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index c5a2e52..bd969ad 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1997-2004 Erez Zadok
  * Copyright (C) 2001-2004 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
  *   		Michael C. Thompson <mcthomps@us.ibm.com>
  *
@@ -250,8 +250,19 @@
 	struct ecryptfs_file_info *file_info;
 	int lower_flags;
 
+	mount_crypt_stat = &ecryptfs_superblock_to_private(
+		ecryptfs_dentry->d_sb)->mount_crypt_stat;
+	if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
+	    && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR)
+		|| (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC)
+		|| (file->f_flags & O_APPEND))) {
+		printk(KERN_WARNING "Mount has encrypted view enabled; "
+		       "files may only be read\n");
+		rc = -EPERM;
+		goto out;
+	}
 	/* Released in ecryptfs_release or end of function if failure */
-	file_info = kmem_cache_alloc(ecryptfs_file_info_cache, GFP_KERNEL);
+	file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
 	ecryptfs_set_file_private(file, file_info);
 	if (!file_info) {
 		ecryptfs_printk(KERN_ERR,
@@ -259,17 +270,14 @@
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(file_info, 0, sizeof(*file_info));
 	lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
 	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
-	mount_crypt_stat = &ecryptfs_superblock_to_private(
-		ecryptfs_dentry->d_sb)->mount_crypt_stat;
 	mutex_lock(&crypt_stat->cs_mutex);
-	if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) {
+	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) {
 		ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
 		/* Policy code enabled in future release */
-		ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED);
-		ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+		crypt_stat->flags |= ECRYPTFS_POLICY_APPLIED;
+		crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
 	}
 	mutex_unlock(&crypt_stat->cs_mutex);
 	lower_flags = file->f_flags;
@@ -289,31 +297,14 @@
 	lower_inode = lower_dentry->d_inode;
 	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
 		ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
-		ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
 		rc = 0;
 		goto out;
 	}
 	mutex_lock(&crypt_stat->cs_mutex);
-	if (i_size_read(lower_inode) < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
-		if (!(mount_crypt_stat->flags
-		      & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
-			rc = -EIO;
-			printk(KERN_WARNING "Attempt to read file that is "
-			       "not in a valid eCryptfs format, and plaintext "
-			       "passthrough mode is not enabled; returning "
-			       "-EIO\n");
-			mutex_unlock(&crypt_stat->cs_mutex);
-			goto out_puts;
-		}
-		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
-		rc = 0;
-		mutex_unlock(&crypt_stat->cs_mutex);
-		goto out;
-	} else if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-					ECRYPTFS_POLICY_APPLIED)
-		   || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-					   ECRYPTFS_KEY_VALID)) {
-		rc = ecryptfs_read_headers(ecryptfs_dentry, lower_file);
+	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
+	    || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
+		rc = ecryptfs_read_metadata(ecryptfs_dentry, lower_file);
 		if (rc) {
 			ecryptfs_printk(KERN_DEBUG,
 					"Valid headers not found\n");
@@ -327,9 +318,8 @@
 				mutex_unlock(&crypt_stat->cs_mutex);
 				goto out_puts;
 			}
-			ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
-					    ECRYPTFS_ENCRYPTED);
 			rc = 0;
+			crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
 			mutex_unlock(&crypt_stat->cs_mutex);
 			goto out;
 		}
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 11f5e50..9fa7e0b 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1997-2004 Erez Zadok
  * Copyright (C) 2001-2004 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *              Michael C. Thompsion <mcthomps@us.ibm.com>
  *
@@ -161,17 +161,17 @@
 	ecryptfs_set_file_lower(&fake_file, lower_file);
 	rc = ecryptfs_fill_zeros(&fake_file, 1);
 	if (rc) {
-		ECRYPTFS_SET_FLAG(
-			ecryptfs_inode_to_private(inode)->crypt_stat.flags,
-			ECRYPTFS_SECURITY_WARNING);
+		ecryptfs_inode_to_private(inode)->crypt_stat.flags |=
+			ECRYPTFS_SECURITY_WARNING;
 		ecryptfs_printk(KERN_WARNING, "Error attempting to fill zeros "
 				"in file; rc = [%d]\n", rc);
 		goto out;
 	}
 	i_size_write(inode, 0);
-	ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode);
-	ECRYPTFS_SET_FLAG(ecryptfs_inode_to_private(inode)->crypt_stat.flags,
-			  ECRYPTFS_NEW_FILE);
+	ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, inode,
+					      ecryptfs_dentry,
+					      ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
+	ecryptfs_inode_to_private(inode)->crypt_stat.flags |= ECRYPTFS_NEW_FILE;
 out:
 	return rc;
 }
@@ -199,7 +199,7 @@
 			lower_dentry->d_name.name);
 	inode = ecryptfs_dentry->d_inode;
 	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
-	lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR;
+	lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR;
 #if BITS_PER_LONG != 32
 	lower_flags |= O_LARGEFILE;
 #endif
@@ -214,10 +214,10 @@
 	lower_inode = lower_dentry->d_inode;
 	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
 		ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
-		ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
 		goto out_fput;
 	}
-	ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE);
+	crypt_stat->flags |= ECRYPTFS_NEW_FILE;
 	ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n");
 	rc = ecryptfs_new_file_context(ecryptfs_dentry);
 	if (rc) {
@@ -225,7 +225,7 @@
 				"context\n");
 		goto out_fput;
 	}
-	rc = ecryptfs_write_headers(ecryptfs_dentry, lower_file);
+	rc = ecryptfs_write_metadata(ecryptfs_dentry, lower_file);
 	if (rc) {
 		ecryptfs_printk(KERN_DEBUG, "Error writing headers\n");
 		goto out_fput;
@@ -287,6 +287,7 @@
 	char *encoded_name;
 	unsigned int encoded_namelen;
 	struct ecryptfs_crypt_stat *crypt_stat = NULL;
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
 	char *page_virt = NULL;
 	struct inode *lower_inode;
 	u64 file_size;
@@ -361,34 +362,44 @@
 		goto out;
 	}
 	/* Released in this function */
-	page_virt =
-	    (char *)kmem_cache_alloc(ecryptfs_header_cache_2,
-				     GFP_USER);
+	page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2,
+				      GFP_USER);
 	if (!page_virt) {
 		rc = -ENOMEM;
 		ecryptfs_printk(KERN_ERR,
 				"Cannot ecryptfs_kmalloc a page\n");
 		goto out_dput;
 	}
-	memset(page_virt, 0, PAGE_CACHE_SIZE);
-	rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt);
 	crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
-	if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED))
+	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
 		ecryptfs_set_default_sizes(crypt_stat);
+	rc = ecryptfs_read_and_validate_header_region(page_virt, lower_dentry,
+						      nd->mnt);
 	if (rc) {
-		rc = 0;
-		ecryptfs_printk(KERN_WARNING, "Error reading header region;"
-				" assuming unencrypted\n");
-	} else {
-		if (!contains_ecryptfs_marker(page_virt
-					      + ECRYPTFS_FILE_SIZE_BYTES)) {
+		rc = ecryptfs_read_and_validate_xattr_region(page_virt, dentry);
+		if (rc) {
+			printk(KERN_DEBUG "Valid metadata not found in header "
+			       "region or xattr region; treating file as "
+			       "unencrypted\n");
+			rc = 0;
 			kmem_cache_free(ecryptfs_header_cache_2, page_virt);
 			goto out;
 		}
+		crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+	}
+	mount_crypt_stat = &ecryptfs_superblock_to_private(
+		dentry->d_sb)->mount_crypt_stat;
+	if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
+		if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+			file_size = (crypt_stat->header_extent_size
+				     + i_size_read(lower_dentry->d_inode));
+		else
+			file_size = i_size_read(lower_dentry->d_inode);
+	} else {
 		memcpy(&file_size, page_virt, sizeof(file_size));
 		file_size = be64_to_cpu(file_size);
-		i_size_write(dentry->d_inode, (loff_t)file_size);
 	}
+	i_size_write(dentry->d_inode, (loff_t)file_size);
 	kmem_cache_free(ecryptfs_header_cache_2, page_virt);
 	goto out;
 
@@ -782,20 +793,26 @@
 			goto out_fput;
 		}
 		i_size_write(inode, new_length);
-		rc = ecryptfs_write_inode_size_to_header(lower_file,
-							 lower_dentry->d_inode,
-							 inode);
+		rc = ecryptfs_write_inode_size_to_metadata(
+			lower_file, lower_dentry->d_inode, inode, dentry,
+			ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
 		if (rc) {
-			ecryptfs_printk(KERN_ERR,
-					"Problem with ecryptfs_write"
-					"_inode_size\n");
+			printk(KERN_ERR	"Problem with "
+			       "ecryptfs_write_inode_size_to_metadata; "
+			       "rc = [%d]\n", rc);
 			goto out_fput;
 		}
 	} else { /* new_length < i_size_read(inode) */
 		vmtruncate(inode, new_length);
-		ecryptfs_write_inode_size_to_header(lower_file,
-						    lower_dentry->d_inode,
-						    inode);
+		rc = ecryptfs_write_inode_size_to_metadata(
+			lower_file, lower_dentry->d_inode, inode, dentry,
+			ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
+		if (rc) {
+			printk(KERN_ERR	"Problem with "
+			       "ecryptfs_write_inode_size_to_metadata; "
+			       "rc = [%d]\n", rc);
+			goto out_fput;
+		}
 		/* We are reducing the size of the ecryptfs file, and need to
 		 * know if we need to reduce the size of the lower file. */
 		lower_size_before_truncate =
@@ -882,7 +899,7 @@
 	return rc;
 }
 
-static int
+int
 ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		  size_t size, int flags)
 {
@@ -902,7 +919,7 @@
 	return rc;
 }
 
-static ssize_t
+ssize_t
 ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
 		  size_t size)
 {
@@ -972,7 +989,7 @@
 	return 0;
 }
 
-struct inode_operations ecryptfs_symlink_iops = {
+const struct inode_operations ecryptfs_symlink_iops = {
 	.readlink = ecryptfs_readlink,
 	.follow_link = ecryptfs_follow_link,
 	.put_link = ecryptfs_put_link,
@@ -984,7 +1001,7 @@
 	.removexattr = ecryptfs_removexattr
 };
 
-struct inode_operations ecryptfs_dir_iops = {
+const struct inode_operations ecryptfs_dir_iops = {
 	.create = ecryptfs_create,
 	.lookup = ecryptfs_lookup,
 	.link = ecryptfs_link,
@@ -1002,7 +1019,7 @@
 	.removexattr = ecryptfs_removexattr
 };
 
-struct inode_operations ecryptfs_main_iops = {
+const struct inode_operations ecryptfs_main_iops = {
 	.permission = ecryptfs_permission,
 	.setattr = ecryptfs_setattr,
 	.setxattr = ecryptfs_setxattr,
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 745c0f1..b550dea 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -7,6 +7,7 @@
  * Copyright (C) 2004-2006 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
  *              Michael C. Thompson <mcthomps@us.ibm.com>
+ *              Trevor S. Highland <trevor.highland@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -25,7 +26,6 @@
  */
 
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/syscalls.h>
 #include <linux/pagemap.h>
 #include <linux/key.h>
@@ -64,26 +64,6 @@
 	return rc;
 }
 
-static void wipe_auth_tok_list(struct list_head *auth_tok_list_head)
-{
-	struct list_head *walker;
-	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
-
-	walker = auth_tok_list_head->next;
-	while (walker != auth_tok_list_head) {
-		auth_tok_list_item =
-		    list_entry(walker, struct ecryptfs_auth_tok_list_item,
-			       list);
-		walker = auth_tok_list_item->list.next;
-		memset(auth_tok_list_item, 0,
-		       sizeof(struct ecryptfs_auth_tok_list_item));
-		kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
-				auth_tok_list_item);
-	}
-}
-
-struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
-
 /**
  * parse_packet_length
  * @data: Pointer to memory containing length at offset
@@ -102,12 +82,12 @@
 	(*size) = 0;
 	if (data[0] < 192) {
 		/* One-byte length */
-		(*size) = data[0];
+		(*size) = (unsigned char)data[0];
 		(*length_size) = 1;
 	} else if (data[0] < 224) {
 		/* Two-byte length */
-		(*size) = ((data[0] - 192) * 256);
-		(*size) += (data[1] + 192);
+		(*size) = (((unsigned char)(data[0]) - 192) * 256);
+		(*size) += ((unsigned char)(data[1]) + 192);
 		(*length_size) = 2;
 	} else if (data[0] == 255) {
 		/* Five-byte length; we're not supposed to see this */
@@ -154,6 +134,499 @@
 	return rc;
 }
 
+static int
+write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key,
+		    char **packet, size_t *packet_len)
+{
+	size_t i = 0;
+	size_t data_len;
+	size_t packet_size_len;
+	char *message;
+	int rc;
+
+	/*
+	 *              ***** TAG 64 Packet Format *****
+	 *    | Content Type                       | 1 byte       |
+	 *    | Key Identifier Size                | 1 or 2 bytes |
+	 *    | Key Identifier                     | arbitrary    |
+	 *    | Encrypted File Encryption Key Size | 1 or 2 bytes |
+	 *    | Encrypted File Encryption Key      | arbitrary    |
+	 */
+	data_len = (5 + ECRYPTFS_SIG_SIZE_HEX
+		    + session_key->encrypted_key_size);
+	*packet = kmalloc(data_len, GFP_KERNEL);
+	message = *packet;
+	if (!message) {
+		ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+	message[i++] = ECRYPTFS_TAG_64_PACKET_TYPE;
+	rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
+				 &packet_size_len);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
+				"header; cannot generate packet length\n");
+		goto out;
+	}
+	i += packet_size_len;
+	memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
+	i += ECRYPTFS_SIG_SIZE_HEX;
+	rc = write_packet_length(&message[i], session_key->encrypted_key_size,
+				 &packet_size_len);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
+				"header; cannot generate packet length\n");
+		goto out;
+	}
+	i += packet_size_len;
+	memcpy(&message[i], session_key->encrypted_key,
+	       session_key->encrypted_key_size);
+	i += session_key->encrypted_key_size;
+	*packet_len = i;
+out:
+	return rc;
+}
+
+static int
+parse_tag_65_packet(struct ecryptfs_session_key *session_key, u16 *cipher_code,
+		    struct ecryptfs_message *msg)
+{
+	size_t i = 0;
+	char *data;
+	size_t data_len;
+	size_t m_size;
+	size_t message_len;
+	u16 checksum = 0;
+	u16 expected_checksum = 0;
+	int rc;
+
+	/*
+	 *              ***** TAG 65 Packet Format *****
+	 *         | Content Type             | 1 byte       |
+	 *         | Status Indicator         | 1 byte       |
+	 *         | File Encryption Key Size | 1 or 2 bytes |
+	 *         | File Encryption Key      | arbitrary    |
+	 */
+	message_len = msg->data_len;
+	data = msg->data;
+	if (message_len < 4) {
+		rc = -EIO;
+		goto out;
+	}
+	if (data[i++] != ECRYPTFS_TAG_65_PACKET_TYPE) {
+		ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_65\n");
+		rc = -EIO;
+		goto out;
+	}
+	if (data[i++]) {
+		ecryptfs_printk(KERN_ERR, "Status indicator has non-zero value "
+				"[%d]\n", data[i-1]);
+		rc = -EIO;
+		goto out;
+	}
+	rc = parse_packet_length(&data[i], &m_size, &data_len);
+	if (rc) {
+		ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+				"rc = [%d]\n", rc);
+		goto out;
+	}
+	i += data_len;
+	if (message_len < (i + m_size)) {
+		ecryptfs_printk(KERN_ERR, "The received netlink message is "
+				"shorter than expected\n");
+		rc = -EIO;
+		goto out;
+	}
+	if (m_size < 3) {
+		ecryptfs_printk(KERN_ERR,
+				"The decrypted key is not long enough to "
+				"include a cipher code and checksum\n");
+		rc = -EIO;
+		goto out;
+	}
+	*cipher_code = data[i++];
+	/* The decrypted key includes 1 byte cipher code and 2 byte checksum */
+	session_key->decrypted_key_size = m_size - 3;
+	if (session_key->decrypted_key_size > ECRYPTFS_MAX_KEY_BYTES) {
+		ecryptfs_printk(KERN_ERR, "key_size [%d] larger than "
+				"the maximum key size [%d]\n",
+				session_key->decrypted_key_size,
+				ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
+		rc = -EIO;
+		goto out;
+	}
+	memcpy(session_key->decrypted_key, &data[i],
+	       session_key->decrypted_key_size);
+	i += session_key->decrypted_key_size;
+	expected_checksum += (unsigned char)(data[i++]) << 8;
+	expected_checksum += (unsigned char)(data[i++]);
+	for (i = 0; i < session_key->decrypted_key_size; i++)
+		checksum += session_key->decrypted_key[i];
+	if (expected_checksum != checksum) {
+		ecryptfs_printk(KERN_ERR, "Invalid checksum for file "
+				"encryption  key; expected [%x]; calculated "
+				"[%x]\n", expected_checksum, checksum);
+		rc = -EIO;
+	}
+out:
+	return rc;
+}
+
+
+static int
+write_tag_66_packet(char *signature, size_t cipher_code,
+		    struct ecryptfs_crypt_stat *crypt_stat, char **packet,
+		    size_t *packet_len)
+{
+	size_t i = 0;
+	size_t j;
+	size_t data_len;
+	size_t checksum = 0;
+	size_t packet_size_len;
+	char *message;
+	int rc;
+
+	/*
+	 *              ***** TAG 66 Packet Format *****
+	 *         | Content Type             | 1 byte       |
+	 *         | Key Identifier Size      | 1 or 2 bytes |
+	 *         | Key Identifier           | arbitrary    |
+	 *         | File Encryption Key Size | 1 or 2 bytes |
+	 *         | File Encryption Key      | arbitrary    |
+	 */
+	data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size);
+	*packet = kmalloc(data_len, GFP_KERNEL);
+	message = *packet;
+	if (!message) {
+		ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+	message[i++] = ECRYPTFS_TAG_66_PACKET_TYPE;
+	rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
+				 &packet_size_len);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
+				"header; cannot generate packet length\n");
+		goto out;
+	}
+	i += packet_size_len;
+	memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
+	i += ECRYPTFS_SIG_SIZE_HEX;
+	/* The encrypted key includes 1 byte cipher code and 2 byte checksum */
+	rc = write_packet_length(&message[i], crypt_stat->key_size + 3,
+				 &packet_size_len);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
+				"header; cannot generate packet length\n");
+		goto out;
+	}
+	i += packet_size_len;
+	message[i++] = cipher_code;
+	memcpy(&message[i], crypt_stat->key, crypt_stat->key_size);
+	i += crypt_stat->key_size;
+	for (j = 0; j < crypt_stat->key_size; j++)
+		checksum += crypt_stat->key[j];
+	message[i++] = (checksum / 256) % 256;
+	message[i++] = (checksum % 256);
+	*packet_len = i;
+out:
+	return rc;
+}
+
+static int
+parse_tag_67_packet(struct ecryptfs_key_record *key_rec,
+		    struct ecryptfs_message *msg)
+{
+	size_t i = 0;
+	char *data;
+	size_t data_len;
+	size_t message_len;
+	int rc;
+
+	/*
+	 *              ***** TAG 65 Packet Format *****
+	 *    | Content Type                       | 1 byte       |
+	 *    | Status Indicator                   | 1 byte       |
+	 *    | Encrypted File Encryption Key Size | 1 or 2 bytes |
+	 *    | Encrypted File Encryption Key      | arbitrary    |
+	 */
+	message_len = msg->data_len;
+	data = msg->data;
+	/* verify that everything through the encrypted FEK size is present */
+	if (message_len < 4) {
+		rc = -EIO;
+		goto out;
+	}
+	if (data[i++] != ECRYPTFS_TAG_67_PACKET_TYPE) {
+		ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_67\n");
+		rc = -EIO;
+		goto out;
+	}
+	if (data[i++]) {
+		ecryptfs_printk(KERN_ERR, "Status indicator has non zero value"
+				" [%d]\n", data[i-1]);
+		rc = -EIO;
+		goto out;
+	}
+	rc = parse_packet_length(&data[i], &key_rec->enc_key_size, &data_len);
+	if (rc) {
+		ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+				"rc = [%d]\n", rc);
+		goto out;
+	}
+	i += data_len;
+	if (message_len < (i + key_rec->enc_key_size)) {
+		ecryptfs_printk(KERN_ERR, "message_len [%d]; max len is [%d]\n",
+				message_len, (i + key_rec->enc_key_size));
+		rc = -EIO;
+		goto out;
+	}
+	if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
+		ecryptfs_printk(KERN_ERR, "Encrypted key_size [%d] larger than "
+				"the maximum key size [%d]\n",
+				key_rec->enc_key_size,
+				ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
+		rc = -EIO;
+		goto out;
+	}
+	memcpy(key_rec->enc_key, &data[i], key_rec->enc_key_size);
+out:
+	return rc;
+}
+
+/**
+ * decrypt_pki_encrypted_session_key - Decrypt the session key with
+ * the given auth_tok.
+ *
+ * Returns Zero on success; non-zero error otherwise.
+ */
+static int decrypt_pki_encrypted_session_key(
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+	struct ecryptfs_auth_tok *auth_tok,
+	struct ecryptfs_crypt_stat *crypt_stat)
+{
+	u16 cipher_code = 0;
+	struct ecryptfs_msg_ctx *msg_ctx;
+	struct ecryptfs_message *msg = NULL;
+	char *netlink_message;
+	size_t netlink_message_length;
+	int rc;
+
+	rc = write_tag_64_packet(mount_crypt_stat->global_auth_tok_sig,
+				 &(auth_tok->session_key),
+				 &netlink_message, &netlink_message_length);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet");
+		goto out;
+	}
+	rc = ecryptfs_send_message(ecryptfs_transport, netlink_message,
+				   netlink_message_length, &msg_ctx);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error sending netlink message\n");
+		goto out;
+	}
+	rc = ecryptfs_wait_for_response(msg_ctx, &msg);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Failed to receive tag 65 packet "
+				"from the user space daemon\n");
+		rc = -EIO;
+		goto out;
+	}
+	rc = parse_tag_65_packet(&(auth_tok->session_key),
+				 &cipher_code, msg);
+	if (rc) {
+		printk(KERN_ERR "Failed to parse tag 65 packet; rc = [%d]\n",
+		       rc);
+		goto out;
+	}
+	auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY;
+	memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
+	       auth_tok->session_key.decrypted_key_size);
+	crypt_stat->key_size = auth_tok->session_key.decrypted_key_size;
+	rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, cipher_code);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Cipher code [%d] is invalid\n",
+				cipher_code)
+		goto out;
+	}
+	crypt_stat->flags |= ECRYPTFS_KEY_VALID;
+	if (ecryptfs_verbosity > 0) {
+		ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");
+		ecryptfs_dump_hex(crypt_stat->key,
+				  crypt_stat->key_size);
+	}
+out:
+	if (msg)
+		kfree(msg);
+	return rc;
+}
+
+static void wipe_auth_tok_list(struct list_head *auth_tok_list_head)
+{
+	struct list_head *walker;
+	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
+
+	walker = auth_tok_list_head->next;
+	while (walker != auth_tok_list_head) {
+		auth_tok_list_item =
+		    list_entry(walker, struct ecryptfs_auth_tok_list_item,
+			       list);
+		walker = auth_tok_list_item->list.next;
+		memset(auth_tok_list_item, 0,
+		       sizeof(struct ecryptfs_auth_tok_list_item));
+		kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
+				auth_tok_list_item);
+	}
+	auth_tok_list_head->next = NULL;
+}
+
+struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
+
+
+/**
+ * parse_tag_1_packet
+ * @crypt_stat: The cryptographic context to modify based on packet
+ *              contents.
+ * @data: The raw bytes of the packet.
+ * @auth_tok_list: eCryptfs parses packets into authentication tokens;
+ *                 a new authentication token will be placed at the end
+ *                 of this list for this packet.
+ * @new_auth_tok: Pointer to a pointer to memory that this function
+ *                allocates; sets the memory address of the pointer to
+ *                NULL on error. This object is added to the
+ *                auth_tok_list.
+ * @packet_size: This function writes the size of the parsed packet
+ *               into this memory location; zero on error.
+ *
+ * Returns zero on success; non-zero on error.
+ */
+static int
+parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
+		   unsigned char *data, struct list_head *auth_tok_list,
+		   struct ecryptfs_auth_tok **new_auth_tok,
+		   size_t *packet_size, size_t max_packet_size)
+{
+	size_t body_size;
+	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
+	size_t length_size;
+	int rc = 0;
+
+	(*packet_size) = 0;
+	(*new_auth_tok) = NULL;
+
+	/* we check that:
+	 *   one byte for the Tag 1 ID flag
+	 *   two bytes for the body size
+	 * do not exceed the maximum_packet_size
+	 */
+	if (unlikely((*packet_size) + 3 > max_packet_size)) {
+		ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+		rc = -EINVAL;
+		goto out;
+	}
+	/* check for Tag 1 identifier - one byte */
+	if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) {
+		ecryptfs_printk(KERN_ERR, "Enter w/ first byte != 0x%.2x\n",
+				ECRYPTFS_TAG_1_PACKET_TYPE);
+		rc = -EINVAL;
+		goto out;
+	}
+	/* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or
+	 * at end of function upon failure */
+	auth_tok_list_item =
+		kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache,
+				 GFP_KERNEL);
+	if (!auth_tok_list_item) {
+		ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(auth_tok_list_item, 0,
+	       sizeof(struct ecryptfs_auth_tok_list_item));
+	(*new_auth_tok) = &auth_tok_list_item->auth_tok;
+	/* check for body size - one to two bytes
+	 *
+	 *              ***** TAG 1 Packet Format *****
+	 *    | version number                     | 1 byte       |
+	 *    | key ID                             | 8 bytes      |
+	 *    | public key algorithm               | 1 byte       |
+	 *    | encrypted session key              | arbitrary    |
+	 */
+	rc = parse_packet_length(&data[(*packet_size)], &body_size,
+				 &length_size);
+	if (rc) {
+		ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+				"rc = [%d]\n", rc);
+		goto out_free;
+	}
+	if (unlikely(body_size < (0x02 + ECRYPTFS_SIG_SIZE))) {
+		ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n",
+				body_size);
+		rc = -EINVAL;
+		goto out_free;
+	}
+	(*packet_size) += length_size;
+	if (unlikely((*packet_size) + body_size > max_packet_size)) {
+		ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+		rc = -EINVAL;
+		goto out_free;
+	}
+	/* Version 3 (from RFC2440) - one byte */
+	if (unlikely(data[(*packet_size)++] != 0x03)) {
+		ecryptfs_printk(KERN_DEBUG, "Unknown version number "
+				"[%d]\n", data[(*packet_size) - 1]);
+		rc = -EINVAL;
+		goto out_free;
+	}
+	/* Read Signature */
+	ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature,
+			&data[(*packet_size)], ECRYPTFS_SIG_SIZE);
+	*packet_size += ECRYPTFS_SIG_SIZE;
+	/* This byte is skipped because the kernel does not need to
+	 * know which public key encryption algorithm was used */
+	(*packet_size)++;
+	(*new_auth_tok)->session_key.encrypted_key_size =
+		body_size - (0x02 + ECRYPTFS_SIG_SIZE);
+	if ((*new_auth_tok)->session_key.encrypted_key_size
+	    > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
+		ecryptfs_printk(KERN_ERR, "Tag 1 packet contains key larger "
+				"than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES");
+		rc = -EINVAL;
+		goto out;
+	}
+	ecryptfs_printk(KERN_DEBUG, "Encrypted key size = [%d]\n",
+			(*new_auth_tok)->session_key.encrypted_key_size);
+	memcpy((*new_auth_tok)->session_key.encrypted_key,
+	       &data[(*packet_size)], (body_size - 0x02 - ECRYPTFS_SIG_SIZE));
+	(*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size;
+	(*new_auth_tok)->session_key.flags &=
+		~ECRYPTFS_CONTAINS_DECRYPTED_KEY;
+	(*new_auth_tok)->session_key.flags |=
+		ECRYPTFS_CONTAINS_ENCRYPTED_KEY;
+	(*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY;
+	(*new_auth_tok)->flags |= ECRYPTFS_PRIVATE_KEY;
+	/* TODO: Why are we setting this flag here? Don't we want the
+	 * userspace to decrypt the session key? */
+	(*new_auth_tok)->session_key.flags &=
+		~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
+	(*new_auth_tok)->session_key.flags &=
+		~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
+	list_add(&auth_tok_list_item->list, auth_tok_list);
+	goto out;
+out_free:
+	(*new_auth_tok) = NULL;
+	memset(auth_tok_list_item, 0,
+	       sizeof(struct ecryptfs_auth_tok_list_item));
+	kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
+			auth_tok_list_item);
+out:
+	if (rc)
+		(*packet_size) = 0;
+	return rc;
+}
+
 /**
  * parse_tag_3_packet
  * @crypt_stat: The cryptographic context to modify based on packet
@@ -178,10 +651,10 @@
 		   struct ecryptfs_auth_tok **new_auth_tok,
 		   size_t *packet_size, size_t max_packet_size)
 {
-	int rc = 0;
 	size_t body_size;
 	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
 	size_t length_size;
+	int rc = 0;
 
 	(*packet_size) = 0;
 	(*new_auth_tok) = NULL;
@@ -207,14 +680,12 @@
 	/* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or
 	 * at end of function upon failure */
 	auth_tok_list_item =
-	    kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL);
+	    kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL);
 	if (!auth_tok_list_item) {
 		ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(auth_tok_list_item, 0,
-	       sizeof(struct ecryptfs_auth_tok_list_item));
 	(*new_auth_tok) = &auth_tok_list_item->auth_tok;
 
 	/* check for body size - one to two bytes */
@@ -321,10 +792,10 @@
 	(*new_auth_tok)->token_type = ECRYPTFS_PASSWORD;
 	/* TODO: Parametarize; we might actually want userspace to
 	 * decrypt the session key. */
-	ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags,
-			    ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
-	ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags,
-			    ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
+	(*new_auth_tok)->session_key.flags &=
+			    ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
+	(*new_auth_tok)->session_key.flags &=
+			    ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
 	list_add(&auth_tok_list_item->list, auth_tok_list);
 	goto out;
 out_free:
@@ -360,9 +831,9 @@
 		    size_t max_contents_bytes, size_t *tag_11_contents_size,
 		    size_t *packet_size, size_t max_packet_size)
 {
-	int rc = 0;
 	size_t body_size;
 	size_t length_size;
+	int rc = 0;
 
 	(*packet_size) = 0;
 	(*tag_11_contents_size) = 0;
@@ -461,7 +932,6 @@
 	struct ecryptfs_password *password_s_ptr;
 	struct scatterlist src_sg[2], dst_sg[2];
 	struct mutex *tfm_mutex = NULL;
-	/* TODO: Use virt_to_scatterlist for these */
 	char *encrypted_session_key;
 	char *session_key;
 	struct blkcipher_desc desc = {
@@ -470,8 +940,7 @@
 	int rc = 0;
 
 	password_s_ptr = &auth_tok->token.password;
-	if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags,
-				ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET))
+	if (password_s_ptr->flags & ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)
 		ecryptfs_printk(KERN_DEBUG, "Session key encryption key "
 				"set; skipping key generation\n");
 	ecryptfs_printk(KERN_DEBUG, "Session key encryption key (size [%d])"
@@ -553,7 +1022,7 @@
 	auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY;
 	memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
 	       auth_tok->session_key.decrypted_key_size);
-	ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+	crypt_stat->flags |= ECRYPTFS_KEY_VALID;
 	ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");
 	if (ecryptfs_verbosity > 0)
 		ecryptfs_dump_hex(crypt_stat->key,
@@ -589,7 +1058,6 @@
 			      struct dentry *ecryptfs_dentry)
 {
 	size_t i = 0;
-	int rc = 0;
 	size_t found_auth_tok = 0;
 	size_t next_packet_is_auth_tok_packet;
 	char sig[ECRYPTFS_SIG_SIZE_HEX];
@@ -605,6 +1073,7 @@
 	unsigned char sig_tmp_space[ECRYPTFS_SIG_SIZE];
 	size_t tag_11_contents_size;
 	size_t tag_11_packet_size;
+	int rc = 0;
 
 	INIT_LIST_HEAD(&auth_tok_list);
 	/* Parse the header to find as many packets as we can, these will be
@@ -656,8 +1125,21 @@
 					sig_tmp_space, tag_11_contents_size);
 			new_auth_tok->token.password.signature[
 				ECRYPTFS_PASSWORD_SIG_SIZE] = '\0';
-			ECRYPTFS_SET_FLAG(crypt_stat->flags,
-					  ECRYPTFS_ENCRYPTED);
+			crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
+			break;
+		case ECRYPTFS_TAG_1_PACKET_TYPE:
+			rc = parse_tag_1_packet(crypt_stat,
+						(unsigned char *)&src[i],
+						&auth_tok_list, &new_auth_tok,
+						&packet_size, max_packet_size);
+			if (rc) {
+				ecryptfs_printk(KERN_ERR, "Error parsing "
+						"tag 1 packet\n");
+				rc = -EIO;
+				goto out_wipe_list;
+			}
+			i += packet_size;
+			crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
 			break;
 		case ECRYPTFS_TAG_11_PACKET_TYPE:
 			ecryptfs_printk(KERN_WARNING, "Invalid packet set "
@@ -706,31 +1188,46 @@
 			goto leave_list;
 			/* TODO: Transfer the common salt into the
 			 * crypt_stat salt */
+		} else if ((candidate_auth_tok->token_type
+			    == ECRYPTFS_PRIVATE_KEY)
+			   && !strncmp(candidate_auth_tok->token.private_key.signature,
+				     sig, ECRYPTFS_SIG_SIZE_HEX)) {
+			found_auth_tok = 1;
+			goto leave_list;
 		}
 	}
-leave_list:
 	if (!found_auth_tok) {
 		ecryptfs_printk(KERN_ERR, "Could not find authentication "
 				"token on temporary list for sig [%.*s]\n",
 				ECRYPTFS_SIG_SIZE_HEX, sig);
 		rc = -EIO;
 		goto out_wipe_list;
-	} else {
+	}
+leave_list:
+	rc = -ENOTSUPP;
+	if (candidate_auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
+		memcpy(&(candidate_auth_tok->token.private_key),
+		       &(chosen_auth_tok->token.private_key),
+		       sizeof(struct ecryptfs_private_key));
+		rc = decrypt_pki_encrypted_session_key(mount_crypt_stat,
+						       candidate_auth_tok,
+						       crypt_stat);
+	} else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) {
 		memcpy(&(candidate_auth_tok->token.password),
 		       &(chosen_auth_tok->token.password),
 		       sizeof(struct ecryptfs_password));
 		rc = decrypt_session_key(candidate_auth_tok, crypt_stat);
-		if (rc) {
-			ecryptfs_printk(KERN_ERR, "Error decrypting the "
-					"session key\n");
-			goto out_wipe_list;
-		}
-		rc = ecryptfs_compute_root_iv(crypt_stat);
-		if (rc) {
-			ecryptfs_printk(KERN_ERR, "Error computing "
-					"the root IV\n");
-			goto out_wipe_list;
-		}
+	}
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error decrypting the "
+				"session key; rc = [%d]\n", rc);
+		goto out_wipe_list;
+	}
+	rc = ecryptfs_compute_root_iv(crypt_stat);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error computing "
+				"the root IV\n");
+		goto out_wipe_list;
 	}
 	rc = ecryptfs_init_crypt_ctx(crypt_stat);
 	if (rc) {
@@ -743,6 +1240,145 @@
 out:
 	return rc;
 }
+static int
+pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
+			struct ecryptfs_crypt_stat *crypt_stat,
+			struct ecryptfs_key_record *key_rec)
+{
+	struct ecryptfs_msg_ctx *msg_ctx = NULL;
+	char *netlink_payload;
+	size_t netlink_payload_length;
+	struct ecryptfs_message *msg;
+	int rc;
+
+	rc = write_tag_66_packet(auth_tok->token.private_key.signature,
+				 ecryptfs_code_for_cipher_string(crypt_stat),
+				 crypt_stat, &netlink_payload,
+				 &netlink_payload_length);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n");
+		goto out;
+	}
+	rc = ecryptfs_send_message(ecryptfs_transport, netlink_payload,
+				   netlink_payload_length, &msg_ctx);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error sending netlink message\n");
+		goto out;
+	}
+	rc = ecryptfs_wait_for_response(msg_ctx, &msg);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Failed to receive tag 67 packet "
+				"from the user space daemon\n");
+		rc = -EIO;
+		goto out;
+	}
+	rc = parse_tag_67_packet(key_rec, msg);
+	if (rc)
+		ecryptfs_printk(KERN_ERR, "Error parsing tag 67 packet\n");
+	kfree(msg);
+out:
+	if (netlink_payload)
+		kfree(netlink_payload);
+	return rc;
+}
+/**
+ * write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet
+ * @dest: Buffer into which to write the packet
+ * @max: Maximum number of bytes that can be writtn
+ * @packet_size: This function will write the number of bytes that end
+ *               up constituting the packet; set to zero on error
+ *
+ * Returns zero on success; non-zero on error.
+ */
+static int
+write_tag_1_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
+		   struct ecryptfs_crypt_stat *crypt_stat,
+		   struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+		   struct ecryptfs_key_record *key_rec, size_t *packet_size)
+{
+	size_t i;
+	size_t encrypted_session_key_valid = 0;
+	size_t key_rec_size;
+	size_t packet_size_length;
+	int rc = 0;
+
+	(*packet_size) = 0;
+	ecryptfs_from_hex(key_rec->sig, auth_tok->token.private_key.signature,
+			  ECRYPTFS_SIG_SIZE);
+	encrypted_session_key_valid = 0;
+	for (i = 0; i < crypt_stat->key_size; i++)
+		encrypted_session_key_valid |=
+			auth_tok->session_key.encrypted_key[i];
+	if (encrypted_session_key_valid) {
+		memcpy(key_rec->enc_key,
+		       auth_tok->session_key.encrypted_key,
+		       auth_tok->session_key.encrypted_key_size);
+		goto encrypted_session_key_set;
+	}
+	if (auth_tok->session_key.encrypted_key_size == 0)
+		auth_tok->session_key.encrypted_key_size =
+			auth_tok->token.private_key.key_size;
+	rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Failed to encrypt session key "
+				"via a pki");
+		goto out;
+	}
+	if (ecryptfs_verbosity > 0) {
+		ecryptfs_printk(KERN_DEBUG, "Encrypted key:\n");
+		ecryptfs_dump_hex(key_rec->enc_key, key_rec->enc_key_size);
+	}
+encrypted_session_key_set:
+	/* Now we have a valid key_rec.  Append it to the
+	 * key_rec set. */
+	key_rec_size = (sizeof(struct ecryptfs_key_record)
+			- ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES
+			+ (key_rec->enc_key_size));
+	/* TODO: Include a packet size limit as a parameter to this
+	 * function once we have multi-packet headers (for versions
+	 * later than 0.1 */
+	if (key_rec_size >= ECRYPTFS_MAX_KEYSET_SIZE) {
+		ecryptfs_printk(KERN_ERR, "Keyset too large\n");
+		rc = -EINVAL;
+		goto out;
+	}
+	/*              ***** TAG 1 Packet Format *****
+	 *    | version number                     | 1 byte       |
+	 *    | key ID                             | 8 bytes      |
+	 *    | public key algorithm               | 1 byte       |
+	 *    | encrypted session key              | arbitrary    |
+	 */
+	if ((0x02 + ECRYPTFS_SIG_SIZE + key_rec->enc_key_size) >= max) {
+		ecryptfs_printk(KERN_ERR,
+				"Authentication token is too large\n");
+		rc = -EINVAL;
+		goto out;
+	}
+	dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE;
+	/* This format is inspired by OpenPGP; see RFC 2440
+	 * packet tag 1 */
+	rc = write_packet_length(&dest[(*packet_size)],
+				 (0x02 + ECRYPTFS_SIG_SIZE +
+				 key_rec->enc_key_size),
+				 &packet_size_length);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet "
+				"header; cannot generate packet length\n");
+		goto out;
+	}
+	(*packet_size) += packet_size_length;
+	dest[(*packet_size)++] = 0x03; /* version 3 */
+	memcpy(&dest[(*packet_size)], key_rec->sig, ECRYPTFS_SIG_SIZE);
+	(*packet_size) += ECRYPTFS_SIG_SIZE;
+	dest[(*packet_size)++] = RFC2440_CIPHER_RSA;
+	memcpy(&dest[(*packet_size)], key_rec->enc_key,
+	       key_rec->enc_key_size);
+	(*packet_size) += key_rec->enc_key_size;
+out:
+	if (rc)
+		(*packet_size) = 0;
+	return rc;
+}
 
 /**
  * write_tag_11_packet
@@ -758,8 +1394,8 @@
 write_tag_11_packet(char *dest, int max, char *contents, size_t contents_length,
 		    size_t *packet_length)
 {
-	int rc = 0;
 	size_t packet_size_length;
+	int rc = 0;
 
 	(*packet_length) = 0;
 	if ((13 + contents_length) > max) {
@@ -817,7 +1453,6 @@
 		   struct ecryptfs_key_record *key_rec, size_t *packet_size)
 {
 	size_t i;
-	size_t signature_is_valid = 0;
 	size_t encrypted_session_key_valid = 0;
 	char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
 	struct scatterlist dest_sg[2];
@@ -833,19 +1468,14 @@
 	int rc = 0;
 
 	(*packet_size) = 0;
-	/* Check for a valid signature on the auth_tok */
-	for (i = 0; i < ECRYPTFS_SIG_SIZE_HEX; i++)
-		signature_is_valid |= auth_tok->token.password.signature[i];
-	if (!signature_is_valid)
-		BUG();
-	ecryptfs_from_hex((*key_rec).sig, auth_tok->token.password.signature,
+	ecryptfs_from_hex(key_rec->sig, auth_tok->token.password.signature,
 			  ECRYPTFS_SIG_SIZE);
 	encrypted_session_key_valid = 0;
 	for (i = 0; i < crypt_stat->key_size; i++)
 		encrypted_session_key_valid |=
 			auth_tok->session_key.encrypted_key[i];
 	if (encrypted_session_key_valid) {
-		memcpy((*key_rec).enc_key,
+		memcpy(key_rec->enc_key,
 		       auth_tok->session_key.encrypted_key,
 		       auth_tok->session_key.encrypted_key_size);
 		goto encrypted_session_key_set;
@@ -858,10 +1488,10 @@
 		memset((crypt_stat->key + 24), 0, 8);
 		auth_tok->session_key.encrypted_key_size = 32;
 	}
-	(*key_rec).enc_key_size =
+	key_rec->enc_key_size =
 		auth_tok->session_key.encrypted_key_size;
-	if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags,
-				ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)) {
+	if (auth_tok->token.password.flags &
+	    ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) {
 		ecryptfs_printk(KERN_DEBUG, "Using previously generated "
 				"session key encryption key of size [%d]\n",
 				auth_tok->token.password.
@@ -879,15 +1509,15 @@
 		ecryptfs_dump_hex(session_key_encryption_key, 16);
 	}
 	rc = virt_to_scatterlist(crypt_stat->key,
-				 (*key_rec).enc_key_size, src_sg, 2);
+				 key_rec->enc_key_size, src_sg, 2);
 	if (!rc) {
 		ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
 				"for crypt_stat session key\n");
 		rc = -ENOMEM;
 		goto out;
 	}
-	rc = virt_to_scatterlist((*key_rec).enc_key,
-				 (*key_rec).enc_key_size, dest_sg, 2);
+	rc = virt_to_scatterlist(key_rec->enc_key,
+				 key_rec->enc_key_size, dest_sg, 2);
 	if (!rc) {
 		ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
 				"for crypt_stat encrypted session key\n");
@@ -943,14 +1573,14 @@
 		mutex_unlock(tfm_mutex);
 	ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n");
 	if (ecryptfs_verbosity > 0)
-		ecryptfs_dump_hex((*key_rec).enc_key,
-				  (*key_rec).enc_key_size);
+		ecryptfs_dump_hex(key_rec->enc_key,
+				  key_rec->enc_key_size);
 encrypted_session_key_set:
 	/* Now we have a valid key_rec.  Append it to the
 	 * key_rec set. */
 	key_rec_size = (sizeof(struct ecryptfs_key_record)
 			- ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES
-			+ ((*key_rec).enc_key_size));
+			+ (key_rec->enc_key_size));
 	/* TODO: Include a packet size limit as a parameter to this
 	 * function once we have multi-packet headers (for versions
 	 * later than 0.1 */
@@ -962,7 +1592,7 @@
 	/* TODO: Packet size limit */
 	/* We have 5 bytes of surrounding packet data */
 	if ((0x05 + ECRYPTFS_SALT_SIZE
-	     + (*key_rec).enc_key_size) >= max) {
+	     + key_rec->enc_key_size) >= max) {
 		ecryptfs_printk(KERN_ERR, "Authentication token is too "
 				"large\n");
 		rc = -EINVAL;
@@ -974,7 +1604,7 @@
 	/* ver+cipher+s2k+hash+salt+iter+enc_key */
 	rc = write_packet_length(&dest[(*packet_size)],
 				 (0x05 + ECRYPTFS_SALT_SIZE
-				  + (*key_rec).enc_key_size),
+				  + key_rec->enc_key_size),
 				 &packet_size_length);
 	if (rc) {
 		ecryptfs_printk(KERN_ERR, "Error generating tag 3 packet "
@@ -997,9 +1627,9 @@
 	       ECRYPTFS_SALT_SIZE);
 	(*packet_size) += ECRYPTFS_SALT_SIZE;	/* salt */
 	dest[(*packet_size)++] = 0x60;	/* hash iterations (65536) */
-	memcpy(&dest[(*packet_size)], (*key_rec).enc_key,
-	       (*key_rec).enc_key_size);
-	(*packet_size) += (*key_rec).enc_key_size;
+	memcpy(&dest[(*packet_size)], key_rec->enc_key,
+	       key_rec->enc_key_size);
+	(*packet_size) += key_rec->enc_key_size;
 out:
 	if (desc.tfm && !tfm_mutex)
 		crypto_free_blkcipher(desc.tfm);
@@ -1008,6 +1638,8 @@
 	return rc;
 }
 
+struct kmem_cache *ecryptfs_key_record_cache;
+
 /**
  * ecryptfs_generate_key_packet_set
  * @dest: Virtual address from which to write the key record set
@@ -1029,52 +1661,60 @@
 				 struct dentry *ecryptfs_dentry, size_t *len,
 				 size_t max)
 {
-	int rc = 0;
 	struct ecryptfs_auth_tok *auth_tok;
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
 		&ecryptfs_superblock_to_private(
 			ecryptfs_dentry->d_sb)->mount_crypt_stat;
 	size_t written;
-	struct ecryptfs_key_record key_rec;
+	struct ecryptfs_key_record *key_rec;
+	int rc = 0;
 
 	(*len) = 0;
+	key_rec = kmem_cache_alloc(ecryptfs_key_record_cache, GFP_KERNEL);
+	if (!key_rec) {
+		rc = -ENOMEM;
+		goto out;
+	}
 	if (mount_crypt_stat->global_auth_tok) {
 		auth_tok = mount_crypt_stat->global_auth_tok;
 		if (auth_tok->token_type == ECRYPTFS_PASSWORD) {
 			rc = write_tag_3_packet((dest_base + (*len)),
 						max, auth_tok,
-						crypt_stat, &key_rec,
+						crypt_stat, key_rec,
 						&written);
 			if (rc) {
 				ecryptfs_printk(KERN_WARNING, "Error "
 						"writing tag 3 packet\n");
-				goto out;
+				goto out_free;
 			}
 			(*len) += written;
 			/* Write auth tok signature packet */
 			rc = write_tag_11_packet(
 				(dest_base + (*len)),
 				(max - (*len)),
-				key_rec.sig, ECRYPTFS_SIG_SIZE, &written);
+				key_rec->sig, ECRYPTFS_SIG_SIZE, &written);
 			if (rc) {
 				ecryptfs_printk(KERN_ERR, "Error writing "
 						"auth tok signature packet\n");
-				goto out;
+				goto out_free;
+			}
+			(*len) += written;
+		} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
+			rc = write_tag_1_packet(dest_base + (*len),
+						max, auth_tok,
+						crypt_stat,mount_crypt_stat,
+						key_rec, &written);
+			if (rc) {
+				ecryptfs_printk(KERN_WARNING, "Error "
+						"writing tag 1 packet\n");
+				goto out_free;
 			}
 			(*len) += written;
 		} else {
 			ecryptfs_printk(KERN_WARNING, "Unsupported "
 					"authentication token type\n");
 			rc = -EINVAL;
-			goto out;
-		}
-		if (rc) {
-			ecryptfs_printk(KERN_WARNING, "Error writing "
-					"authentication token packet with sig "
-					"= [%s]\n",
-					mount_crypt_stat->global_auth_tok_sig);
-			rc = -EIO;
-			goto out;
+			goto out_free;
 		}
 	} else
 		BUG();
@@ -1084,6 +1724,9 @@
 		ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n");
 		rc = -EIO;
 	}
+
+out_free:
+	kmem_cache_free(ecryptfs_key_record_cache, key_rec);
 out:
 	if (rc)
 		(*len) = 0;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index d0541ae8..80044d1 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -3,9 +3,10 @@
  *
  * Copyright (C) 1997-2003 Erez Zadok
  * Copyright (C) 2001-2003 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *              Michael C. Thompson <mcthomps@us.ibm.com>
+ *              Tyler Hicks <tyhicks@ou.edu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -48,6 +49,43 @@
 		 "Initial verbosity level (0 or 1; defaults to "
 		 "0, which is Quiet)");
 
+/**
+ * Module parameter that defines the number of netlink message buffer
+ * elements
+ */
+unsigned int ecryptfs_message_buf_len = ECRYPTFS_DEFAULT_MSG_CTX_ELEMS;
+
+module_param(ecryptfs_message_buf_len, uint, 0);
+MODULE_PARM_DESC(ecryptfs_message_buf_len,
+		 "Number of message buffer elements");
+
+/**
+ * Module parameter that defines the maximum guaranteed amount of time to wait
+ * for a response through netlink.  The actual sleep time will be, more than
+ * likely, a small amount greater than this specified value, but only less if
+ * the netlink message successfully arrives.
+ */
+signed long ecryptfs_message_wait_timeout = ECRYPTFS_MAX_MSG_CTX_TTL / HZ;
+
+module_param(ecryptfs_message_wait_timeout, long, 0);
+MODULE_PARM_DESC(ecryptfs_message_wait_timeout,
+		 "Maximum number of seconds that an operation will "
+		 "sleep while waiting for a message response from "
+		 "userspace");
+
+/**
+ * Module parameter that is an estimate of the maximum number of users
+ * that will be concurrently using eCryptfs. Set this to the right
+ * value to balance performance and memory use.
+ */
+unsigned int ecryptfs_number_of_users = ECRYPTFS_DEFAULT_NUM_USERS;
+
+module_param(ecryptfs_number_of_users, uint, 0);
+MODULE_PARM_DESC(ecryptfs_number_of_users, "An estimate of the number of "
+		 "concurrent users of eCryptfs");
+
+unsigned int ecryptfs_transport = ECRYPTFS_DEFAULT_TRANSPORT;
+
 void __ecryptfs_printk(const char *fmt, ...)
 {
 	va_list args;
@@ -124,7 +162,8 @@
 enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug,
        ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher,
        ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes,
-       ecryptfs_opt_passthrough, ecryptfs_opt_err };
+       ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
+       ecryptfs_opt_encrypted_view, ecryptfs_opt_err };
 
 static match_table_t tokens = {
 	{ecryptfs_opt_sig, "sig=%s"},
@@ -135,6 +174,8 @@
 	{ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"},
 	{ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"},
 	{ecryptfs_opt_passthrough, "ecryptfs_passthrough"},
+	{ecryptfs_opt_xattr_metadata, "ecryptfs_xattr_metadata"},
+	{ecryptfs_opt_encrypted_view, "ecryptfs_encrypted_view"},
 	{ecryptfs_opt_err, NULL}
 };
 
@@ -275,6 +316,16 @@
 			mount_crypt_stat->flags |=
 				ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED;
 			break;
+		case ecryptfs_opt_xattr_metadata:
+			mount_crypt_stat->flags |=
+				ECRYPTFS_XATTR_METADATA_ENABLED;
+			break;
+		case ecryptfs_opt_encrypted_view:
+			mount_crypt_stat->flags |=
+				ECRYPTFS_XATTR_METADATA_ENABLED;
+			mount_crypt_stat->flags |=
+				ECRYPTFS_ENCRYPTED_VIEW_ENABLED;
+			break;
 		case ecryptfs_opt_err:
 		default:
 			ecryptfs_printk(KERN_WARNING,
@@ -347,9 +398,10 @@
 		rc = -EINVAL;
 		goto out;
 	}
-	if (auth_tok->token_type != ECRYPTFS_PASSWORD) {
+	if (auth_tok->token_type != ECRYPTFS_PASSWORD
+	    && auth_tok->token_type != ECRYPTFS_PRIVATE_KEY) {
 		ecryptfs_printk(KERN_ERR, "Invalid auth_tok structure "
-				"returned from key\n");
+				"returned from key query\n");
 		rc = -EINVAL;
 		goto out;
 	}
@@ -378,15 +430,13 @@
 
 	/* Released in ecryptfs_put_super() */
 	ecryptfs_set_superblock_private(sb,
-					kmem_cache_alloc(ecryptfs_sb_info_cache,
+					kmem_cache_zalloc(ecryptfs_sb_info_cache,
 							 GFP_KERNEL));
 	if (!ecryptfs_superblock_to_private(sb)) {
 		ecryptfs_printk(KERN_WARNING, "Out of memory\n");
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(ecryptfs_superblock_to_private(sb), 0,
-	       sizeof(struct ecryptfs_sb_info));
 	sb->s_op = &ecryptfs_sops;
 	/* Released through deactivate_super(sb) from get_sb_nodev */
 	sb->s_root = d_alloc(NULL, &(const struct qstr) {
@@ -402,7 +452,7 @@
 	/* Released in d_release when dput(sb->s_root) is called */
 	/* through deactivate_super(sb) from get_sb_nodev() */
 	ecryptfs_set_dentry_private(sb->s_root,
-				    kmem_cache_alloc(ecryptfs_dentry_info_cache,
+				    kmem_cache_zalloc(ecryptfs_dentry_info_cache,
 						     GFP_KERNEL));
 	if (!ecryptfs_dentry_to_private(sb->s_root)) {
 		ecryptfs_printk(KERN_ERR,
@@ -410,8 +460,6 @@
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(ecryptfs_dentry_to_private(sb->s_root), 0,
-	       sizeof(struct ecryptfs_dentry_info));
 	rc = 0;
 out:
 	/* Should be able to rely on deactivate_super called from
@@ -594,10 +642,20 @@
 		.size = PAGE_CACHE_SIZE,
 	},
 	{
+		.cache = &ecryptfs_xattr_cache,
+		.name = "ecryptfs_xattr_cache",
+		.size = PAGE_CACHE_SIZE,
+	},
+	{
 		.cache = &ecryptfs_lower_page_cache,
 		.name = "ecryptfs_lower_page_cache",
 		.size = PAGE_CACHE_SIZE,
 	},
+	{
+		.cache = &ecryptfs_key_record_cache,
+		.name = "ecryptfs_key_record_cache",
+		.size = sizeof(struct ecryptfs_key_record),
+	},
 };
 
 static void ecryptfs_free_kmem_caches(void)
@@ -699,7 +757,8 @@
 	{ECRYPTFS_VERSIONING_PASSPHRASE, "passphrase"},
 	{ECRYPTFS_VERSIONING_PUBKEY, "pubkey"},
 	{ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH, "plaintext passthrough"},
-	{ECRYPTFS_VERSIONING_POLICY, "policy"}
+	{ECRYPTFS_VERSIONING_POLICY, "policy"},
+	{ECRYPTFS_VERSIONING_XATTR, "metadata in extended attribute"}
 };
 
 static ssize_t version_str_show(struct ecryptfs_obj *obj, char *buff)
@@ -798,6 +857,11 @@
 		ecryptfs_free_kmem_caches();
 		goto out;
 	}
+	rc = ecryptfs_init_messaging(ecryptfs_transport);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Failure occured while attempting to "
+				"initialize the eCryptfs netlink socket\n");
+	}
 out:
 	return rc;
 }
@@ -809,6 +873,7 @@
 	sysfs_remove_file(&ecryptfs_subsys.kset.kobj,
 			  &sysfs_attr_version_str.attr);
 	subsystem_unregister(&ecryptfs_subsys);
+	ecryptfs_release_messaging(ecryptfs_transport);
 	unregister_filesystem(&ecryptfs_fs_type);
 	ecryptfs_free_kmem_caches();
 }
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
new file mode 100644
index 0000000..3baf253
--- /dev/null
+++ b/fs/ecryptfs/messaging.c
@@ -0,0 +1,516 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2004-2006 International Business Machines Corp.
+ *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
+ *		Tyler Hicks <tyhicks@ou.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "ecryptfs_kernel.h"
+
+static LIST_HEAD(ecryptfs_msg_ctx_free_list);
+static LIST_HEAD(ecryptfs_msg_ctx_alloc_list);
+static struct mutex ecryptfs_msg_ctx_lists_mux;
+
+static struct hlist_head *ecryptfs_daemon_id_hash;
+static struct mutex ecryptfs_daemon_id_hash_mux;
+static int ecryptfs_hash_buckets;
+#define ecryptfs_uid_hash(uid) \
+        hash_long((unsigned long)uid, ecryptfs_hash_buckets)
+
+static unsigned int ecryptfs_msg_counter;
+static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr;
+
+/**
+ * ecryptfs_acquire_free_msg_ctx
+ * @msg_ctx: The context that was acquired from the free list
+ *
+ * Acquires a context element from the free list and locks the mutex
+ * on the context.  Returns zero on success; non-zero on error or upon
+ * failure to acquire a free context element.  Be sure to lock the
+ * list mutex before calling.
+ */
+static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx)
+{
+	struct list_head *p;
+	int rc;
+
+	if (list_empty(&ecryptfs_msg_ctx_free_list)) {
+		ecryptfs_printk(KERN_WARNING, "The eCryptfs free "
+				"context list is empty.  It may be helpful to "
+				"specify the ecryptfs_message_buf_len "
+				"parameter to be greater than the current "
+				"value of [%d]\n", ecryptfs_message_buf_len);
+		rc = -ENOMEM;
+		goto out;
+	}
+	list_for_each(p, &ecryptfs_msg_ctx_free_list) {
+		*msg_ctx = list_entry(p, struct ecryptfs_msg_ctx, node);
+		if (mutex_trylock(&(*msg_ctx)->mux)) {
+			(*msg_ctx)->task = current;
+			rc = 0;
+			goto out;
+		}
+	}
+	rc = -ENOMEM;
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_msg_ctx_free_to_alloc
+ * @msg_ctx: The context to move from the free list to the alloc list
+ *
+ * Be sure to lock the list mutex and the context mutex before
+ * calling.
+ */
+static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx)
+{
+	list_move(&msg_ctx->node, &ecryptfs_msg_ctx_alloc_list);
+	msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_PENDING;
+	msg_ctx->counter = ++ecryptfs_msg_counter;
+}
+
+/**
+ * ecryptfs_msg_ctx_alloc_to_free
+ * @msg_ctx: The context to move from the alloc list to the free list
+ *
+ * Be sure to lock the list mutex and the context mutex before
+ * calling.
+ */
+static void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)
+{
+	list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list);
+	if (msg_ctx->msg)
+		kfree(msg_ctx->msg);
+	msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE;
+}
+
+/**
+ * ecryptfs_find_daemon_id
+ * @uid: The user id which maps to the desired daemon id
+ * @id: If return value is zero, points to the desired daemon id
+ *      pointer
+ *
+ * Search the hash list for the given user id.  Returns zero if the
+ * user id exists in the list; non-zero otherwise.  The daemon id hash
+ * mutex should be held before calling this function.
+ */
+static int ecryptfs_find_daemon_id(uid_t uid, struct ecryptfs_daemon_id **id)
+{
+	struct hlist_node *elem;
+	int rc;
+
+	hlist_for_each_entry(*id, elem,
+			     &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)],
+			     id_chain) {
+		if ((*id)->uid == uid) {
+			rc = 0;
+			goto out;
+		}
+	}
+	rc = -EINVAL;
+out:
+	return rc;
+}
+
+static int ecryptfs_send_raw_message(unsigned int transport, u16 msg_type,
+				     pid_t pid)
+{
+	int rc;
+
+	switch(transport) {
+	case ECRYPTFS_TRANSPORT_NETLINK:
+		rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0, pid);
+		break;
+	case ECRYPTFS_TRANSPORT_CONNECTOR:
+	case ECRYPTFS_TRANSPORT_RELAYFS:
+	default:
+		rc = -ENOSYS;
+	}
+	return rc;
+}
+
+/**
+ * ecryptfs_process_helo
+ * @transport: The underlying transport (netlink, etc.)
+ * @uid: The user ID owner of the message
+ * @pid: The process ID for the userspace program that sent the
+ *       message
+ *
+ * Adds the uid and pid values to the daemon id hash.  If a uid
+ * already has a daemon pid registered, the daemon will be
+ * unregistered before the new daemon id is put into the hash list.
+ * Returns zero after adding a new daemon id to the hash list;
+ * non-zero otherwise.
+ */
+int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid)
+{
+	struct ecryptfs_daemon_id *new_id;
+	struct ecryptfs_daemon_id *old_id;
+	int rc;
+
+	mutex_lock(&ecryptfs_daemon_id_hash_mux);
+	new_id = kmalloc(sizeof(*new_id), GFP_KERNEL);
+	if (!new_id) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable "
+				"to register daemon [%d] for user [%d]\n",
+				pid, uid);
+		goto unlock;
+	}
+	if (!ecryptfs_find_daemon_id(uid, &old_id)) {
+		printk(KERN_WARNING "Received request from user [%d] "
+		       "to register daemon [%d]; unregistering daemon "
+		       "[%d]\n", uid, pid, old_id->pid);
+		hlist_del(&old_id->id_chain);
+		rc = ecryptfs_send_raw_message(transport, ECRYPTFS_NLMSG_QUIT,
+					       old_id->pid);
+		if (rc)
+			printk(KERN_WARNING "Failed to send QUIT "
+			       "message to daemon [%d]; rc = [%d]\n",
+			       old_id->pid, rc);
+		kfree(old_id);
+	}
+	new_id->uid = uid;
+	new_id->pid = pid;
+	hlist_add_head(&new_id->id_chain,
+		       &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)]);
+	rc = 0;
+unlock:
+	mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+	return rc;
+}
+
+/**
+ * ecryptfs_process_quit
+ * @uid: The user ID owner of the message
+ * @pid: The process ID for the userspace program that sent the
+ *       message
+ *
+ * Deletes the corresponding daemon id for the given uid and pid, if
+ * it is the registered that is requesting the deletion. Returns zero
+ * after deleting the desired daemon id; non-zero otherwise.
+ */
+int ecryptfs_process_quit(uid_t uid, pid_t pid)
+{
+	struct ecryptfs_daemon_id *id;
+	int rc;
+
+	mutex_lock(&ecryptfs_daemon_id_hash_mux);
+	if (ecryptfs_find_daemon_id(uid, &id)) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_ERR, "Received request from user [%d] to "
+				"unregister unrecognized daemon [%d]\n", uid,
+				pid);
+		goto unlock;
+	}
+	if (id->pid != pid) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_WARNING, "Received request from user [%d] "
+				"with pid [%d] to unregister daemon [%d]\n",
+				uid, pid, id->pid);
+		goto unlock;
+	}
+	hlist_del(&id->id_chain);
+	kfree(id);
+	rc = 0;
+unlock:
+	mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+	return rc;
+}
+
+/**
+ * ecryptfs_process_reponse
+ * @msg: The ecryptfs message received; the caller should sanity check
+ *       msg->data_len
+ * @pid: The process ID of the userspace application that sent the
+ *       message
+ * @seq: The sequence number of the message
+ *
+ * Processes a response message after sending a operation request to
+ * userspace. Returns zero upon delivery to desired context element;
+ * non-zero upon delivery failure or error.
+ */
+int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
+			      pid_t pid, u32 seq)
+{
+	struct ecryptfs_daemon_id *id;
+	struct ecryptfs_msg_ctx *msg_ctx;
+	int msg_size;
+	int rc;
+
+	if (msg->index >= ecryptfs_message_buf_len) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_ERR, "Attempt to reference "
+				"context buffer at index [%d]; maximum "
+				"allowable is [%d]\n", msg->index,
+				(ecryptfs_message_buf_len - 1));
+		goto out;
+	}
+	msg_ctx = &ecryptfs_msg_ctx_arr[msg->index];
+	mutex_lock(&msg_ctx->mux);
+	if (ecryptfs_find_daemon_id(msg_ctx->task->euid, &id)) {
+		rc = -EBADMSG;
+		ecryptfs_printk(KERN_WARNING, "User [%d] received a "
+				"message response from process [%d] but does "
+				"not have a registered daemon\n",
+				msg_ctx->task->euid, pid);
+		goto wake_up;
+	}
+	if (msg_ctx->task->euid != uid) {
+		rc = -EBADMSG;
+		ecryptfs_printk(KERN_WARNING, "Received message from user "
+				"[%d]; expected message from user [%d]\n",
+				uid, msg_ctx->task->euid);
+		goto unlock;
+	}
+	if (id->pid != pid) {
+		rc = -EBADMSG;
+		ecryptfs_printk(KERN_ERR, "User [%d] received a "
+				"message response from an unrecognized "
+				"process [%d]\n", msg_ctx->task->euid, pid);
+		goto unlock;
+	}
+	if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_WARNING, "Desired context element is not "
+				"pending a response\n");
+		goto unlock;
+	} else if (msg_ctx->counter != seq) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_WARNING, "Invalid message sequence; "
+				"expected [%d]; received [%d]\n",
+				msg_ctx->counter, seq);
+		goto unlock;
+	}
+	msg_size = sizeof(*msg) + msg->data_len;
+	msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL);
+	if (!msg_ctx->msg) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+		goto unlock;
+	}
+	memcpy(msg_ctx->msg, msg, msg_size);
+	msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE;
+	rc = 0;
+wake_up:
+	wake_up_process(msg_ctx->task);
+unlock:
+	mutex_unlock(&msg_ctx->mux);
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_send_message
+ * @transport: The transport over which to send the message (i.e.,
+ *             netlink)
+ * @data: The data to send
+ * @data_len: The length of data
+ * @msg_ctx: The message context allocated for the send
+ */
+int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+			  struct ecryptfs_msg_ctx **msg_ctx)
+{
+	struct ecryptfs_daemon_id *id;
+	int rc;
+
+	mutex_lock(&ecryptfs_daemon_id_hash_mux);
+	if (ecryptfs_find_daemon_id(current->euid, &id)) {
+		mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+		rc = -ENOTCONN;
+		ecryptfs_printk(KERN_ERR, "User [%d] does not have a daemon "
+				"registered\n", current->euid);
+		goto out;
+	}
+	mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+	mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+	rc = ecryptfs_acquire_free_msg_ctx(msg_ctx);
+	if (rc) {
+		mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+		ecryptfs_printk(KERN_WARNING, "Could not claim a free "
+				"context element\n");
+		goto out;
+	}
+	ecryptfs_msg_ctx_free_to_alloc(*msg_ctx);
+	mutex_unlock(&(*msg_ctx)->mux);
+	mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+	switch (transport) {
+	case ECRYPTFS_TRANSPORT_NETLINK:
+		rc = ecryptfs_send_netlink(data, data_len, *msg_ctx,
+					   ECRYPTFS_NLMSG_REQUEST, 0, id->pid);
+		break;
+	case ECRYPTFS_TRANSPORT_CONNECTOR:
+	case ECRYPTFS_TRANSPORT_RELAYFS:
+	default:
+		rc = -ENOSYS;
+	}
+	if (rc) {
+		printk(KERN_ERR "Error attempting to send message to userspace "
+		       "daemon; rc = [%d]\n", rc);
+	}
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_wait_for_response
+ * @msg_ctx: The context that was assigned when sending a message
+ * @msg: The incoming message from userspace; not set if rc != 0
+ *
+ * Sleeps until awaken by ecryptfs_receive_message or until the amount
+ * of time exceeds ecryptfs_message_wait_timeout.  If zero is
+ * returned, msg will point to a valid message from userspace; a
+ * non-zero value is returned upon failure to receive a message or an
+ * error occurs.
+ */
+int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
+			       struct ecryptfs_message **msg)
+{
+	signed long timeout = ecryptfs_message_wait_timeout * HZ;
+	int rc = 0;
+
+sleep:
+	timeout = schedule_timeout_interruptible(timeout);
+	mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+	mutex_lock(&msg_ctx->mux);
+	if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_DONE) {
+		if (timeout) {
+			mutex_unlock(&msg_ctx->mux);
+			mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+			goto sleep;
+		}
+		rc = -ENOMSG;
+	} else {
+		*msg = msg_ctx->msg;
+		msg_ctx->msg = NULL;
+	}
+	ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
+	mutex_unlock(&msg_ctx->mux);
+	mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+	return rc;
+}
+
+int ecryptfs_init_messaging(unsigned int transport)
+{
+	int i;
+	int rc = 0;
+
+	if (ecryptfs_number_of_users > ECRYPTFS_MAX_NUM_USERS) {
+		ecryptfs_number_of_users = ECRYPTFS_MAX_NUM_USERS;
+		ecryptfs_printk(KERN_WARNING, "Specified number of users is "
+				"too large, defaulting to [%d] users\n",
+				ecryptfs_number_of_users);
+	}
+	mutex_init(&ecryptfs_daemon_id_hash_mux);
+	mutex_lock(&ecryptfs_daemon_id_hash_mux);
+	ecryptfs_hash_buckets = 0;
+	while (ecryptfs_number_of_users >> ++ecryptfs_hash_buckets);
+	ecryptfs_daemon_id_hash = kmalloc(sizeof(struct hlist_head)
+					  * ecryptfs_hash_buckets, GFP_KERNEL);
+	if (!ecryptfs_daemon_id_hash) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+		goto out;
+	}
+	for (i = 0; i < ecryptfs_hash_buckets; i++)
+		INIT_HLIST_HEAD(&ecryptfs_daemon_id_hash[i]);
+	mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+
+	ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx)
+				      * ecryptfs_message_buf_len), GFP_KERNEL);
+	if (!ecryptfs_msg_ctx_arr) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+		goto out;
+	}
+	mutex_init(&ecryptfs_msg_ctx_lists_mux);
+	mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+	ecryptfs_msg_counter = 0;
+	for (i = 0; i < ecryptfs_message_buf_len; i++) {
+		INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].node);
+		mutex_init(&ecryptfs_msg_ctx_arr[i].mux);
+		mutex_lock(&ecryptfs_msg_ctx_arr[i].mux);
+		ecryptfs_msg_ctx_arr[i].index = i;
+		ecryptfs_msg_ctx_arr[i].state = ECRYPTFS_MSG_CTX_STATE_FREE;
+		ecryptfs_msg_ctx_arr[i].counter = 0;
+		ecryptfs_msg_ctx_arr[i].task = NULL;
+		ecryptfs_msg_ctx_arr[i].msg = NULL;
+		list_add_tail(&ecryptfs_msg_ctx_arr[i].node,
+			      &ecryptfs_msg_ctx_free_list);
+		mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux);
+	}
+	mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+	switch(transport) {
+	case ECRYPTFS_TRANSPORT_NETLINK:
+		rc = ecryptfs_init_netlink();
+		if (rc)
+			ecryptfs_release_messaging(transport);
+		break;
+	case ECRYPTFS_TRANSPORT_CONNECTOR:
+	case ECRYPTFS_TRANSPORT_RELAYFS:
+	default:
+		rc = -ENOSYS;
+	}
+out:
+	return rc;
+}
+
+void ecryptfs_release_messaging(unsigned int transport)
+{
+	if (ecryptfs_msg_ctx_arr) {
+		int i;
+
+		mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+		for (i = 0; i < ecryptfs_message_buf_len; i++) {
+			mutex_lock(&ecryptfs_msg_ctx_arr[i].mux);
+			if (ecryptfs_msg_ctx_arr[i].msg)
+				kfree(ecryptfs_msg_ctx_arr[i].msg);
+			mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux);
+		}
+		kfree(ecryptfs_msg_ctx_arr);
+		mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+	}
+	if (ecryptfs_daemon_id_hash) {
+		struct hlist_node *elem;
+		struct ecryptfs_daemon_id *id;
+		int i;
+
+		mutex_lock(&ecryptfs_daemon_id_hash_mux);
+		for (i = 0; i < ecryptfs_hash_buckets; i++) {
+			hlist_for_each_entry(id, elem,
+					     &ecryptfs_daemon_id_hash[i],
+					     id_chain) {
+				hlist_del(elem);
+				kfree(id);
+			}
+		}
+		kfree(ecryptfs_daemon_id_hash);
+		mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+	}
+	switch(transport) {
+	case ECRYPTFS_TRANSPORT_NETLINK:
+		ecryptfs_release_netlink();
+		break;
+	case ECRYPTFS_TRANSPORT_CONNECTOR:
+	case ECRYPTFS_TRANSPORT_RELAYFS:
+	default:
+		break;
+	}
+	return;
+}
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 06843d2..3a6f65c 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -6,7 +6,7 @@
  *
  * Copyright (C) 1997-2003 Erez Zadok
  * Copyright (C) 2001-2003 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -234,22 +234,13 @@
 		goto out;
 	}
 	wait_on_page_locked(lower_page);
-	page_data = (char *)kmap(page);
-	if (!page_data) {
-		rc = -ENOMEM;
-		ecryptfs_printk(KERN_ERR, "Error mapping page\n");
-		goto out;
-	}
-	lower_page_data = (char *)kmap(lower_page);
-	if (!lower_page_data) {
-		rc = -ENOMEM;
-		ecryptfs_printk(KERN_ERR, "Error mapping page\n");
-		kunmap(page);
-		goto out;
-	}
+	page_data = kmap_atomic(page, KM_USER0);
+	lower_page_data = kmap_atomic(lower_page, KM_USER1);
 	memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
-	kunmap(lower_page);
-	kunmap(page);
+	kunmap_atomic(lower_page_data, KM_USER1);
+	flush_dcache_page(lower_page);
+	kunmap_atomic(page_data, KM_USER0);
+	flush_dcache_page(page);
 	rc = 0;
 out:
 	if (likely(lower_page))
@@ -260,6 +251,33 @@
 		ClearPageUptodate(page);
 	return rc;
 }
+/**
+ *   Header Extent:
+ *     Octets 0-7:        Unencrypted file size (big-endian)
+ *     Octets 8-15:       eCryptfs special marker
+ *     Octets 16-19:      Flags
+ *      Octet 16:         File format version number (between 0 and 255)
+ *      Octets 17-18:     Reserved
+ *      Octet 19:         Bit 1 (lsb): Reserved
+ *                        Bit 2: Encrypted?
+ *                        Bits 3-8: Reserved
+ *     Octets 20-23:      Header extent size (big-endian)
+ *     Octets 24-25:      Number of header extents at front of file
+ *                        (big-endian)
+ *     Octet  26:         Begin RFC 2440 authentication token packet set
+ */
+static void set_header_info(char *page_virt,
+			    struct ecryptfs_crypt_stat *crypt_stat)
+{
+	size_t written;
+	int save_num_header_extents_at_front =
+		crypt_stat->num_header_extents_at_front;
+
+	crypt_stat->num_header_extents_at_front = 1;
+	ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written);
+	crypt_stat->num_header_extents_at_front =
+		save_num_header_extents_at_front;
+}
 
 /**
  * ecryptfs_readpage
@@ -279,8 +297,8 @@
 	crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
 			->crypt_stat;
 	if (!crypt_stat
-	    || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)
-	    || ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
+	    || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
+	    || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
 		ecryptfs_printk(KERN_DEBUG,
 				"Passing through unencrypted page\n");
 		rc = ecryptfs_do_readpage(file, page, page->index);
@@ -289,10 +307,51 @@
 					"[%d]\n", rc);
 			goto out;
 		}
+	} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
+		if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
+			int num_pages_in_header_region =
+				(crypt_stat->header_extent_size
+				 / PAGE_CACHE_SIZE);
+
+			if (page->index < num_pages_in_header_region) {
+				char *page_virt;
+
+				page_virt = kmap_atomic(page, KM_USER0);
+				memset(page_virt, 0, PAGE_CACHE_SIZE);
+				if (page->index == 0) {
+					rc = ecryptfs_read_xattr_region(
+						page_virt, file->f_path.dentry);
+					set_header_info(page_virt, crypt_stat);
+				}
+				kunmap_atomic(page_virt, KM_USER0);
+				flush_dcache_page(page);
+				if (rc) {
+					printk(KERN_ERR "Error reading xattr "
+					       "region\n");
+					goto out;
+				}
+			} else {
+				rc = ecryptfs_do_readpage(
+					file, page,
+					(page->index
+					 - num_pages_in_header_region));
+				if (rc) {
+					printk(KERN_ERR "Error reading page; "
+					       "rc = [%d]\n", rc);
+					goto out;
+				}
+			}
+		} else {
+			rc = ecryptfs_do_readpage(file, page, page->index);
+			if (rc) {
+				printk(KERN_ERR "Error reading page; rc = "
+				       "[%d]\n", rc);
+				goto out;
+			}
+		}
 	} else {
 		rc = ecryptfs_decrypt_page(file, page);
 		if (rc) {
-
 			ecryptfs_printk(KERN_ERR, "Error decrypting page; "
 					"rc = [%d]\n", rc);
 			goto out;
@@ -308,30 +367,27 @@
 	return rc;
 }
 
+/**
+ * Called with lower inode mutex held.
+ */
 static int fill_zeros_to_end_of_page(struct page *page, unsigned int to)
 {
 	struct inode *inode = page->mapping->host;
 	int end_byte_in_page;
-	int rc = 0;
 	char *page_virt;
 
-	if ((i_size_read(inode) / PAGE_CACHE_SIZE) == page->index) {
-		end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
-		if (to > end_byte_in_page)
-			end_byte_in_page = to;
-		page_virt = kmap(page);
-		if (!page_virt) {
-			rc = -ENOMEM;
-			ecryptfs_printk(KERN_WARNING,
-					"Could not map page\n");
-			goto out;
-		}
-		memset((page_virt + end_byte_in_page), 0,
-		       (PAGE_CACHE_SIZE - end_byte_in_page));
-		kunmap(page);
-	}
+	if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index)
+		goto out;
+	end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
+	if (to > end_byte_in_page)
+		end_byte_in_page = to;
+	page_virt = kmap_atomic(page, KM_USER0);
+	memset((page_virt + end_byte_in_page), 0,
+	       (PAGE_CACHE_SIZE - end_byte_in_page));
+	kunmap_atomic(page_virt, KM_USER0);
+	flush_dcache_page(page);
 out:
-	return rc;
+	return 0;
 }
 
 static int ecryptfs_prepare_write(struct file *file, struct page *page,
@@ -339,7 +395,6 @@
 {
 	int rc = 0;
 
-	kmap(page);
 	if (from == 0 && to == PAGE_CACHE_SIZE)
 		goto out;	/* If we are writing a full page, it will be
 				   up to date. */
@@ -349,30 +404,6 @@
 	return rc;
 }
 
-int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
-				     char **lower_virt,
-				     struct inode *lower_inode,
-				     unsigned long lower_page_index)
-{
-	int rc = 0;
-
-	(*lower_page) = grab_cache_page(lower_inode->i_mapping,
-					lower_page_index);
-	if (!(*lower_page)) {
-		ecryptfs_printk(KERN_ERR, "grab_cache_page for "
-				"lower_page_index = [0x%.16x] failed\n",
-				lower_page_index);
-		rc = -EINVAL;
-		goto out;
-	}
-	if (lower_virt)
-		(*lower_virt) = kmap((*lower_page));
-	else
-		kmap((*lower_page));
-out:
-	return rc;
-}
-
 int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
 					      struct inode *lower_inode,
 					      struct writeback_control *wbc)
@@ -391,11 +422,8 @@
 	return rc;
 }
 
-static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page)
+static void ecryptfs_release_lower_page(struct page *lower_page)
 {
-	kunmap(lower_page);
-	ecryptfs_printk(KERN_DEBUG, "Unlocking lower page with index = "
-			"[0x%.16x]\n", lower_page->index);
 	unlock_page(lower_page);
 	page_cache_release(lower_page);
 }
@@ -407,10 +435,9 @@
  *
  * Returns zero on success; non-zero on error.
  */
-int
-ecryptfs_write_inode_size_to_header(struct file *lower_file,
-				    struct inode *lower_inode,
-				    struct inode *inode)
+static int ecryptfs_write_inode_size_to_header(struct file *lower_file,
+					       struct inode *lower_inode,
+					       struct inode *inode)
 {
 	int rc = 0;
 	struct page *header_page;
@@ -418,11 +445,11 @@
 	const struct address_space_operations *lower_a_ops;
 	u64 file_size;
 
-	rc = ecryptfs_grab_and_map_lower_page(&header_page, &header_virt,
-					      lower_inode, 0);
-	if (rc) {
-		ecryptfs_printk(KERN_ERR, "grab_cache_page for header page "
-				"failed\n");
+	header_page = grab_cache_page(lower_inode->i_mapping, 0);
+	if (!header_page) {
+		ecryptfs_printk(KERN_ERR, "grab_cache_page for "
+				"lower_page_index 0 failed\n");
+		rc = -EINVAL;
 		goto out;
 	}
 	lower_a_ops = lower_inode->i_mapping->a_ops;
@@ -430,18 +457,95 @@
 	file_size = (u64)i_size_read(inode);
 	ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size);
 	file_size = cpu_to_be64(file_size);
+	header_virt = kmap_atomic(header_page, KM_USER0);
 	memcpy(header_virt, &file_size, sizeof(u64));
+	kunmap_atomic(header_virt, KM_USER0);
+	flush_dcache_page(header_page);
 	rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8);
 	if (rc < 0)
 		ecryptfs_printk(KERN_ERR, "Error commiting header page "
 				"write\n");
-	ecryptfs_unmap_and_release_lower_page(header_page);
+	ecryptfs_release_lower_page(header_page);
 	lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
 	mark_inode_dirty_sync(inode);
 out:
 	return rc;
 }
 
+static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode,
+					      struct inode *inode,
+					      struct dentry *ecryptfs_dentry,
+					      int lower_i_mutex_held)
+{
+	ssize_t size;
+	void *xattr_virt;
+	struct dentry *lower_dentry;
+	u64 file_size;
+	int rc;
+
+	xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL);
+	if (!xattr_virt) {
+		printk(KERN_ERR "Out of memory whilst attempting to write "
+		       "inode size to xattr\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+	lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
+	if (!lower_dentry->d_inode->i_op->getxattr) {
+		printk(KERN_WARNING
+		       "No support for setting xattr in lower filesystem\n");
+		rc = -ENOSYS;
+		kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
+		goto out;
+	}
+	if (!lower_i_mutex_held)
+		mutex_lock(&lower_dentry->d_inode->i_mutex);
+	size = lower_dentry->d_inode->i_op->getxattr(lower_dentry,
+						     ECRYPTFS_XATTR_NAME,
+						     xattr_virt,
+						     PAGE_CACHE_SIZE);
+	if (!lower_i_mutex_held)
+		mutex_unlock(&lower_dentry->d_inode->i_mutex);
+	if (size < 0)
+		size = 8;
+	file_size = (u64)i_size_read(inode);
+	file_size = cpu_to_be64(file_size);
+	memcpy(xattr_virt, &file_size, sizeof(u64));
+	if (!lower_i_mutex_held)
+		mutex_lock(&lower_dentry->d_inode->i_mutex);
+	rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry,
+						   ECRYPTFS_XATTR_NAME,
+						   xattr_virt, size, 0);
+	if (!lower_i_mutex_held)
+		mutex_unlock(&lower_dentry->d_inode->i_mutex);
+	if (rc)
+		printk(KERN_ERR "Error whilst attempting to write inode size "
+		       "to lower file xattr; rc = [%d]\n", rc);
+	kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
+out:
+	return rc;
+}
+
+int
+ecryptfs_write_inode_size_to_metadata(struct file *lower_file,
+				      struct inode *lower_inode,
+				      struct inode *inode,
+				      struct dentry *ecryptfs_dentry,
+				      int lower_i_mutex_held)
+{
+	struct ecryptfs_crypt_stat *crypt_stat;
+
+	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+		return ecryptfs_write_inode_size_to_xattr(lower_inode, inode,
+							  ecryptfs_dentry,
+							  lower_i_mutex_held);
+	else
+		return ecryptfs_write_inode_size_to_header(lower_file,
+							   lower_inode,
+							   inode);
+}
+
 int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
 			    struct file *lower_file,
 			    unsigned long lower_page_index, int byte_offset,
@@ -449,10 +553,10 @@
 {
 	int rc = 0;
 
-	rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL, lower_inode,
-					      lower_page_index);
-	if (rc) {
-		ecryptfs_printk(KERN_ERR, "Error attempting to grab and map "
+	*lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index);
+	if (!(*lower_page)) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_ERR, "Error attempting to grab "
 				"lower page with index [0x%.16x]\n",
 				lower_page_index);
 		goto out;
@@ -468,7 +572,7 @@
 	}
 out:
 	if (rc && (*lower_page)) {
-		ecryptfs_unmap_and_release_lower_page(*lower_page);
+		ecryptfs_release_lower_page(*lower_page);
 		(*lower_page) = NULL;
 	}
 	return rc;
@@ -493,7 +597,7 @@
 				"Error committing write; rc = [%d]\n", rc);
 	} else
 		rc = 0;
-	ecryptfs_unmap_and_release_lower_page(lower_page);
+	ecryptfs_release_lower_page(lower_page);
 	return rc;
 }
 
@@ -528,89 +632,7 @@
 	return rc;
 }
 
-static int
-process_new_file(struct ecryptfs_crypt_stat *crypt_stat,
-		 struct file *file, struct inode *inode)
-{
-	struct page *header_page;
-	const struct address_space_operations *lower_a_ops;
-	struct inode *lower_inode;
-	struct file *lower_file;
-	char *header_virt;
-	int rc = 0;
-	int current_header_page = 0;
-	int header_pages;
-	int more_header_data_to_be_written = 1;
-
-	lower_inode = ecryptfs_inode_to_lower(inode);
-	lower_file = ecryptfs_file_to_lower(file);
-	lower_a_ops = lower_inode->i_mapping->a_ops;
-	header_pages = ((crypt_stat->header_extent_size
-			 * crypt_stat->num_header_extents_at_front)
-			/ PAGE_CACHE_SIZE);
-	BUG_ON(header_pages < 1);
-	while (current_header_page < header_pages) {
-		rc = ecryptfs_grab_and_map_lower_page(&header_page,
-						      &header_virt,
-						      lower_inode,
-						      current_header_page);
-		if (rc) {
-			ecryptfs_printk(KERN_ERR, "grab_cache_page for "
-					"header page [%d] failed; rc = [%d]\n",
-					current_header_page, rc);
-			goto out;
-		}
-		rc = lower_a_ops->prepare_write(lower_file, header_page, 0,
-						PAGE_CACHE_SIZE);
-		if (rc) {
-			ecryptfs_printk(KERN_ERR, "Error preparing to write "
-					"header page out; rc = [%d]\n", rc);
-			goto out;
-		}
-		memset(header_virt, 0, PAGE_CACHE_SIZE);
-		if (more_header_data_to_be_written) {
-			rc = ecryptfs_write_headers_virt(header_virt,
-							 crypt_stat,
-							 file->f_dentry);
-			if (rc) {
-				ecryptfs_printk(KERN_WARNING, "Error "
-						"generating header; rc = "
-						"[%d]\n", rc);
-				rc = -EIO;
-				memset(header_virt, 0, PAGE_CACHE_SIZE);
-				ecryptfs_unmap_and_release_lower_page(
-					header_page);
-				goto out;
-			}
-			if (current_header_page == 0)
-				memset(header_virt, 0, 8);
-			more_header_data_to_be_written = 0;
-		}
-		rc = lower_a_ops->commit_write(lower_file, header_page, 0,
-					       PAGE_CACHE_SIZE);
-		ecryptfs_unmap_and_release_lower_page(header_page);
-		if (rc < 0) {
-			ecryptfs_printk(KERN_ERR,
-					"Error commiting header page write; "
-					"rc = [%d]\n", rc);
-			break;
-		}
-		current_header_page++;
-	}
-	if (rc >= 0) {
-		rc = 0;
-		ecryptfs_printk(KERN_DEBUG, "lower_inode->i_blocks = "
-				"[0x%.16x]\n", lower_inode->i_blocks);
-		i_size_write(inode, 0);
-		lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
-		mark_inode_dirty_sync(inode);
-	}
-	ecryptfs_printk(KERN_DEBUG, "Clearing ECRYPTFS_NEW_FILE flag in "
-			"crypt_stat at memory location [%p]\n", crypt_stat);
-	ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE);
-out:
-	return rc;
-}
+struct kmem_cache *ecryptfs_xattr_cache;
 
 /**
  * ecryptfs_commit_write
@@ -640,15 +662,10 @@
 	mutex_lock(&lower_inode->i_mutex);
 	crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
 				->crypt_stat;
-	if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
+	if (crypt_stat->flags & ECRYPTFS_NEW_FILE) {
 		ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
 			"crypt_stat at memory location [%p]\n", crypt_stat);
-		rc = process_new_file(crypt_stat, file, inode);
-		if (rc) {
-			ecryptfs_printk(KERN_ERR, "Error processing new "
-					"file; rc = [%d]\n", rc);
-			goto out;
-		}
+		crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE);
 	} else
 		ecryptfs_printk(KERN_DEBUG, "Not a new file\n");
 	ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
@@ -670,7 +687,6 @@
 				"index [0x%.16x])\n", page->index);
 		goto out;
 	}
-	rc = 0;
 	inode->i_blocks = lower_inode->i_blocks;
 	pos = (page->index << PAGE_CACHE_SHIFT) + to;
 	if (pos > i_size_read(inode)) {
@@ -678,11 +694,15 @@
 		ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
 				"[0x%.16x]\n", i_size_read(inode));
 	}
-	ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode);
+	rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode,
+						   inode, file->f_dentry,
+						   ECRYPTFS_LOWER_I_MUTEX_HELD);
+	if (rc)
+		printk(KERN_ERR "Error writing inode size to metadata; "
+		       "rc = [%d]\n", rc);
 	lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
 	mark_inode_dirty_sync(inode);
 out:
-	kunmap(page); /* mapped in prior call (prepare_write) */
 	if (rc < 0)
 		ClearPageUptodate(page);
 	else
@@ -707,6 +727,7 @@
 {
 	int rc = 0;
 	struct page *tmp_page;
+	char *tmp_page_virt;
 
 	tmp_page = ecryptfs_get1page(file, index);
 	if (IS_ERR(tmp_page)) {
@@ -715,28 +736,27 @@
 		rc = PTR_ERR(tmp_page);
 		goto out;
 	}
-	kmap(tmp_page);
 	rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros);
 	if (rc) {
 		ecryptfs_printk(KERN_ERR, "Error preparing to write zero's "
 				"to remainder of page at index [0x%.16x]\n",
 				index);
-		kunmap(tmp_page);
 		page_cache_release(tmp_page);
 		goto out;
 	}
-	memset(((char *)page_address(tmp_page) + start), 0, num_zeros);
+	tmp_page_virt = kmap_atomic(tmp_page, KM_USER0);
+	memset(((char *)tmp_page_virt + start), 0, num_zeros);
+	kunmap_atomic(tmp_page_virt, KM_USER0);
+	flush_dcache_page(tmp_page);
 	rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros);
 	if (rc < 0) {
 		ecryptfs_printk(KERN_ERR, "Error attempting to write zero's "
 				"to remainder of page at index [0x%.16x]\n",
 				index);
-		kunmap(tmp_page);
 		page_cache_release(tmp_page);
 		goto out;
 	}
 	rc = 0;
-	kunmap(tmp_page);
 	page_cache_release(tmp_page);
 out:
 	return rc;
diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c
new file mode 100644
index 0000000..e3aa225
--- /dev/null
+++ b/fs/ecryptfs/netlink.c
@@ -0,0 +1,255 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2004-2006 International Business Machines Corp.
+ *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
+ *		Tyler Hicks <tyhicks@ou.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <net/sock.h>
+#include <linux/hash.h>
+#include <linux/random.h>
+#include "ecryptfs_kernel.h"
+
+static struct sock *ecryptfs_nl_sock;
+
+/**
+ * ecryptfs_send_netlink
+ * @data: The data to include as the payload
+ * @data_len: The byte count of the data
+ * @msg_ctx: The netlink context that will be used to handle the
+ *          response message
+ * @msg_type: The type of netlink message to send
+ * @msg_flags: The flags to include in the netlink header
+ * @daemon_pid: The process id of the daemon to send the message to
+ *
+ * Sends the data to the specified daemon pid and uses the netlink
+ * context element to store the data needed for validation upon
+ * receiving the response.  The data and the netlink context can be
+ * null if just sending a netlink header is sufficient.  Returns zero
+ * upon sending the message; non-zero upon error.
+ */
+int ecryptfs_send_netlink(char *data, int data_len,
+			  struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+			  u16 msg_flags, pid_t daemon_pid)
+{
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	struct ecryptfs_message *msg;
+	size_t payload_len;
+	int rc;
+
+	payload_len = ((data && data_len) ? (sizeof(*msg) + data_len) : 0);
+	skb = alloc_skb(NLMSG_SPACE(payload_len), GFP_KERNEL);
+	if (!skb) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Failed to allocate socket buffer\n");
+		goto out;
+	}
+	nlh = NLMSG_PUT(skb, daemon_pid, msg_ctx ? msg_ctx->counter : 0,
+			msg_type, payload_len);
+	nlh->nlmsg_flags = msg_flags;
+	if (msg_ctx && payload_len) {
+		msg = (struct ecryptfs_message *)NLMSG_DATA(nlh);
+		msg->index = msg_ctx->index;
+		msg->data_len = data_len;
+		memcpy(msg->data, data, data_len);
+	}
+	rc = netlink_unicast(ecryptfs_nl_sock, skb, daemon_pid, 0);
+	if (rc < 0) {
+		ecryptfs_printk(KERN_ERR, "Failed to send eCryptfs netlink "
+				"message; rc = [%d]\n", rc);
+		goto out;
+	}
+	rc = 0;
+	goto out;
+nlmsg_failure:
+	rc = -EMSGSIZE;
+	kfree_skb(skb);
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_process_nl_reponse
+ * @skb: The socket buffer containing the netlink message of state
+ *       RESPONSE
+ *
+ * Processes a response message after sending a operation request to
+ * userspace.  Attempts to assign the msg to a netlink context element
+ * at the index specified in the msg.  The sk_buff and nlmsghdr must
+ * be validated before this function. Returns zero upon delivery to
+ * desired context element; non-zero upon delivery failure or error.
+ */
+static int ecryptfs_process_nl_response(struct sk_buff *skb)
+{
+	struct nlmsghdr *nlh = (struct nlmsghdr*)skb->data;
+	struct ecryptfs_message *msg = NLMSG_DATA(nlh);
+	int rc;
+
+	if (skb->len - NLMSG_HDRLEN - sizeof(*msg) != msg->data_len) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_ERR, "Received netlink message with "
+				"incorrectly specified data length\n");
+		goto out;
+	}
+	rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid,
+				       NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq);
+	if (rc)
+		printk(KERN_ERR
+		       "Error processing response message; rc = [%d]\n", rc);
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_process_nl_helo
+ * @skb: The socket buffer containing the nlmsghdr in HELO state
+ *
+ * Gets uid and pid of the skb and adds the values to the daemon id
+ * hash. Returns zero after adding a new daemon id to the hash list;
+ * non-zero otherwise.
+ */
+static int ecryptfs_process_nl_helo(struct sk_buff *skb)
+{
+	int rc;
+
+	rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_NETLINK,
+				   NETLINK_CREDS(skb)->uid,
+				   NETLINK_CREDS(skb)->pid);
+	if (rc)
+		printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
+	return rc;
+}
+
+/**
+ * ecryptfs_process_nl_quit
+ * @skb: The socket buffer containing the nlmsghdr in QUIT state
+ *
+ * Gets uid and pid of the skb and deletes the corresponding daemon
+ * id, if it is the registered that is requesting the
+ * deletion. Returns zero after deleting the desired daemon id;
+ * non-zero otherwise.
+ */
+static int ecryptfs_process_nl_quit(struct sk_buff *skb)
+{
+	int rc;
+
+	rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid,
+				   NETLINK_CREDS(skb)->pid);
+	if (rc)
+		printk(KERN_WARNING
+		       "Error processing QUIT message; rc = [%d]\n", rc);
+	return rc;
+}
+
+/**
+ * ecryptfs_receive_nl_message
+ *
+ * Callback function called by netlink system when a message arrives.
+ * If the message looks to be valid, then an attempt is made to assign
+ * it to its desired netlink context element and wake up the process
+ * that is waiting for a response.
+ */
+static void ecryptfs_receive_nl_message(struct sock *sk, int len)
+{
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	int rc = 0;	/* skb_recv_datagram requires this */
+
+receive:
+	skb = skb_recv_datagram(sk, 0, 0, &rc);
+	if (rc == -EINTR)
+		goto receive;
+	else if (rc < 0) {
+		ecryptfs_printk(KERN_ERR, "Error occurred while "
+				"receiving eCryptfs netlink message; "
+				"rc = [%d]\n", rc);
+		return;
+	}
+	nlh = (struct nlmsghdr *)skb->data;
+	if (!NLMSG_OK(nlh, skb->len)) {
+		ecryptfs_printk(KERN_ERR, "Received corrupt netlink "
+				"message\n");
+		goto free;
+	}
+	switch (nlh->nlmsg_type) {
+		case ECRYPTFS_NLMSG_RESPONSE:
+			if (ecryptfs_process_nl_response(skb)) {
+				ecryptfs_printk(KERN_WARNING, "Failed to "
+						"deliver netlink response to "
+						"requesting operation\n");
+			}
+			break;
+		case ECRYPTFS_NLMSG_HELO:
+			if (ecryptfs_process_nl_helo(skb)) {
+				ecryptfs_printk(KERN_WARNING, "Failed to "
+						"fulfill HELO request\n");
+			}
+			break;
+		case ECRYPTFS_NLMSG_QUIT:
+			if (ecryptfs_process_nl_quit(skb)) {
+				ecryptfs_printk(KERN_WARNING, "Failed to "
+						"fulfill QUIT request\n");
+			}
+			break;
+		default:
+			ecryptfs_printk(KERN_WARNING, "Dropping netlink "
+					"message of unrecognized type [%d]\n",
+					nlh->nlmsg_type);
+			break;
+	}
+free:
+	kfree_skb(skb);
+}
+
+/**
+ * ecryptfs_init_netlink
+ *
+ * Initializes the daemon id hash list, netlink context array, and
+ * necessary locks.  Returns zero upon success; non-zero upon error.
+ */
+int ecryptfs_init_netlink(void)
+{
+	int rc;
+
+	ecryptfs_nl_sock = netlink_kernel_create(NETLINK_ECRYPTFS, 0,
+						 ecryptfs_receive_nl_message,
+						 THIS_MODULE);
+	if (!ecryptfs_nl_sock) {
+		rc = -EIO;
+		ecryptfs_printk(KERN_ERR, "Failed to create netlink socket\n");
+		goto out;
+	}
+	ecryptfs_nl_sock->sk_sndtimeo = ECRYPTFS_DEFAULT_SEND_TIMEOUT;
+	rc = 0;
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_release_netlink
+ *
+ * Frees all memory used by the netlink context array and releases the
+ * netlink socket.
+ */
+void ecryptfs_release_netlink(void)
+{
+	if (ecryptfs_nl_sock && ecryptfs_nl_sock->sk_socket)
+		sock_release(ecryptfs_nl_sock->sk_socket);
+	ecryptfs_nl_sock = NULL;
+}
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index eaa5daa..7b3f0cc 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -168,7 +168,7 @@
 	return rc;
 }
 
-struct super_operations ecryptfs_sops = {
+const struct super_operations ecryptfs_sops = {
 	.alloc_inode = ecryptfs_alloc_inode,
 	.destroy_inode = ecryptfs_destroy_inode,
 	.drop_inode = generic_delete_inode,
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
index b46c488..dfb5cb4 100644
--- a/fs/efs/dir.c
+++ b/fs/efs/dir.c
@@ -15,7 +15,7 @@
 	.readdir	= efs_readdir,
 };
 
-struct inode_operations efs_dir_inode_operations = {
+const struct inode_operations efs_dir_inode_operations = {
 	.lookup		= efs_lookup,
 };
 
diff --git a/fs/efs/super.c b/fs/efs/super.c
index dfebf21..c2235e4 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -105,7 +105,7 @@
 	return 0;
 }
 
-static struct super_operations efs_superblock_operations = {
+static const struct super_operations efs_superblock_operations = {
 	.alloc_inode	= efs_alloc_inode,
 	.destroy_inode	= efs_destroy_inode,
 	.read_inode	= efs_read_inode,
diff --git a/fs/exec.c b/fs/exec.c
index 11fe93f..7e36c6f 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -405,12 +405,10 @@
 		bprm->loader += stack_base;
 	bprm->exec += stack_base;
 
-	mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+	mpnt = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 	if (!mpnt)
 		return -ENOMEM;
 
-	memset(mpnt, 0, sizeof(*mpnt));
-
 	down_write(&mm->mmap_sem);
 	{
 		mpnt->vm_mm = mm;
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index b1981d0..baf71dd 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -29,7 +29,7 @@
  * The file system contains group descriptors which are located after the
  * super block.  Each descriptor contains the number of the bitmap block and
  * the free blocks count in the block.  The descriptors are loaded in memory
- * when a file system is mounted (see ext2_read_super).
+ * when a file system is mounted (see ext2_fill_super).
  */
 
 
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 0b02ba9..e89bfc8 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -368,6 +368,14 @@
 		}
 		if (++n >= npages)
 			n = 0;
+		/* next page is past the blocks we've got */
+		if (unlikely(n > (dir->i_blocks >> (PAGE_CACHE_SHIFT - 9)))) {
+			ext2_error(dir->i_sb, __FUNCTION__,
+				"dir %lu size %lld exceeds block count %llu",
+				dir->i_ino, dir->i_size,
+				(unsigned long long)dir->i_blocks);
+			goto out;
+		}
 	} while (n != start);
 out:
 	return NULL;
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index c19ac15..e2a0ea5 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -158,7 +158,7 @@
 extern const struct file_operations ext2_dir_operations;
 
 /* file.c */
-extern struct inode_operations ext2_file_inode_operations;
+extern const struct inode_operations ext2_file_inode_operations;
 extern const struct file_operations ext2_file_operations;
 extern const struct file_operations ext2_xip_file_operations;
 
@@ -168,9 +168,9 @@
 extern const struct address_space_operations ext2_nobh_aops;
 
 /* namei.c */
-extern struct inode_operations ext2_dir_inode_operations;
-extern struct inode_operations ext2_special_inode_operations;
+extern const struct inode_operations ext2_dir_inode_operations;
+extern const struct inode_operations ext2_special_inode_operations;
 
 /* symlink.c */
-extern struct inode_operations ext2_fast_symlink_inode_operations;
-extern struct inode_operations ext2_symlink_inode_operations;
+extern const struct inode_operations ext2_fast_symlink_inode_operations;
+extern const struct inode_operations ext2_symlink_inode_operations;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 2dba473..566d4e2 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -75,7 +75,7 @@
 };
 #endif
 
-struct inode_operations ext2_file_inode_operations = {
+const struct inode_operations ext2_file_inode_operations = {
 	.truncate	= ext2_truncate,
 #ifdef CONFIG_EXT2_FS_XATTR
 	.setxattr	= generic_setxattr,
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index e1af5b4..e69beed 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -373,7 +373,7 @@
 	return err;
 }
 
-struct inode_operations ext2_dir_inode_operations = {
+const struct inode_operations ext2_dir_inode_operations = {
 	.create		= ext2_create,
 	.lookup		= ext2_lookup,
 	.link		= ext2_link,
@@ -393,7 +393,7 @@
 	.permission	= ext2_permission,
 };
 
-struct inode_operations ext2_special_inode_operations = {
+const struct inode_operations ext2_special_inode_operations = {
 #ifdef CONFIG_EXT2_FS_XATTR
 	.setxattr	= generic_setxattr,
 	.getxattr	= generic_getxattr,
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 6347c2d..a046a41 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -231,7 +231,7 @@
 static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off);
 #endif
 
-static struct super_operations ext2_sops = {
+static const struct super_operations ext2_sops = {
 	.alloc_inode	= ext2_alloc_inode,
 	.destroy_inode	= ext2_destroy_inode,
 	.read_inode	= ext2_read_inode,
@@ -708,10 +708,14 @@
 		set_opt(sbi->s_mount_opt, GRPID);
 	if (def_mount_opts & EXT2_DEFM_UID16)
 		set_opt(sbi->s_mount_opt, NO_UID32);
+#ifdef CONFIG_EXT2_FS_XATTR
 	if (def_mount_opts & EXT2_DEFM_XATTR_USER)
 		set_opt(sbi->s_mount_opt, XATTR_USER);
+#endif
+#ifdef CONFIG_EXT2_FS_POSIX_ACL
 	if (def_mount_opts & EXT2_DEFM_ACL)
 		set_opt(sbi->s_mount_opt, POSIX_ACL);
+#endif
 	
 	if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC)
 		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c
index 1e67d87..4e2426e 100644
--- a/fs/ext2/symlink.c
+++ b/fs/ext2/symlink.c
@@ -28,7 +28,7 @@
 	return NULL;
 }
 
-struct inode_operations ext2_symlink_inode_operations = {
+const struct inode_operations ext2_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -40,7 +40,7 @@
 #endif
 };
  
-struct inode_operations ext2_fast_symlink_inode_operations = {
+const struct inode_operations ext2_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= ext2_follow_link,
 #ifdef CONFIG_EXT2_FS_XATTR
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 2216174..ca8aee6 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -32,7 +32,7 @@
  * The file system contains group descriptors which are located after the
  * super block.  Each descriptor contains the number of the bitmap block and
  * the free blocks count in the block.  The descriptors are loaded in memory
- * when a file system is mounted (see ext3_read_super).
+ * when a file system is mounted (see ext3_fill_super).
  */
 
 
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 881f636..1e6f138 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -125,7 +125,7 @@
 	.splice_write	= generic_file_splice_write,
 };
 
-struct inode_operations ext3_file_inode_operations = {
+const struct inode_operations ext3_file_inode_operations = {
 	.truncate	= ext3_truncate,
 	.setattr	= ext3_setattr,
 #ifdef CONFIG_EXT3_FS_XATTR
diff --git a/fs/ext3/hash.c b/fs/ext3/hash.c
index deeb27b..c30e149 100644
--- a/fs/ext3/hash.c
+++ b/fs/ext3/hash.c
@@ -11,7 +11,6 @@
 
 #include <linux/fs.h>
 #include <linux/jbd.h>
-#include <linux/sched.h>
 #include <linux/ext3_fs.h>
 #include <linux/cryptohash.h>
 
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index beaf25f..8a824f4 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -947,7 +947,7 @@
 static int ext3_get_block(struct inode *inode, sector_t iblock,
 			struct buffer_head *bh_result, int create)
 {
-	handle_t *handle = journal_current_handle();
+	handle_t *handle = ext3_journal_current_handle();
 	int ret = 0;
 	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
 
@@ -1717,7 +1717,7 @@
 	/*
 	 * Reacquire the handle: ext3_get_block() can restart the transaction
 	 */
-	handle = journal_current_handle();
+	handle = ext3_journal_current_handle();
 
 out_stop:
 	if (handle) {
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 4df39c4..49159f1 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1618,21 +1618,6 @@
 	return -ENOENT;
 }
 
-/*
- * ext3_mark_inode_dirty is somewhat expensive, so unlike ext2 we
- * do not perform it in these functions.  We perform it at the call site,
- * if it is needed.
- */
-static inline void ext3_inc_count(handle_t *handle, struct inode *inode)
-{
-	inc_nlink(inode);
-}
-
-static inline void ext3_dec_count(handle_t *handle, struct inode *inode)
-{
-	drop_nlink(inode);
-}
-
 static int ext3_add_nondir(handle_t *handle,
 		struct dentry *dentry, struct inode *inode)
 {
@@ -1642,7 +1627,7 @@
 		d_instantiate(dentry, inode);
 		return 0;
 	}
-	ext3_dec_count(handle, inode);
+	drop_nlink(inode);
 	iput(inode);
 	return err;
 }
@@ -2163,7 +2148,7 @@
 		err = __page_symlink(inode, symname, l,
 				mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
 		if (err) {
-			ext3_dec_count(handle, inode);
+			drop_nlink(inode);
 			ext3_mark_inode_dirty(handle, inode);
 			iput (inode);
 			goto out_stop;
@@ -2191,6 +2176,12 @@
 
 	if (inode->i_nlink >= EXT3_LINK_MAX)
 		return -EMLINK;
+	/*
+	 * Return -ENOENT if we've raced with unlink and i_nlink is 0.  Doing
+	 * otherwise has the potential to corrupt the orphan inode list.
+	 */
+	if (inode->i_nlink == 0)
+		return -ENOENT;
 
 retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
@@ -2202,7 +2193,7 @@
 		handle->h_sync = 1;
 
 	inode->i_ctime = CURRENT_TIME_SEC;
-	ext3_inc_count(handle, inode);
+	inc_nlink(inode);
 	atomic_inc(&inode->i_count);
 
 	err = ext3_add_nondir(handle, dentry, inode);
@@ -2374,7 +2365,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations ext3_dir_inode_operations = {
+const struct inode_operations ext3_dir_inode_operations = {
 	.create		= ext3_create,
 	.lookup		= ext3_lookup,
 	.link		= ext3_link,
@@ -2394,7 +2385,7 @@
 	.permission	= ext3_permission,
 };
 
-struct inode_operations ext3_special_inode_operations = {
+const struct inode_operations ext3_special_inode_operations = {
 	.setattr	= ext3_setattr,
 #ifdef CONFIG_EXT3_FS_XATTR
 	.setxattr	= generic_setxattr,
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index b73cba1..ecf8990 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -11,7 +11,6 @@
 
 #define EXT3FS_DEBUG
 
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/ext3_jbd.h>
 
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index b348867..4a4fcd6 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -639,7 +639,7 @@
 };
 #endif
 
-static struct super_operations ext3_sops = {
+static const struct super_operations ext3_sops = {
 	.alloc_inode	= ext3_alloc_inode,
 	.destroy_inode	= ext3_destroy_inode,
 	.read_inode	= ext3_read_inode,
@@ -1459,10 +1459,14 @@
 		set_opt(sbi->s_mount_opt, GRPID);
 	if (def_mount_opts & EXT3_DEFM_UID16)
 		set_opt(sbi->s_mount_opt, NO_UID32);
+#ifdef CONFIG_EXT3_FS_XATTR
 	if (def_mount_opts & EXT3_DEFM_XATTR_USER)
 		set_opt(sbi->s_mount_opt, XATTR_USER);
+#endif
+#ifdef CONFIG_EXT3_FS_POSIX_ACL
 	if (def_mount_opts & EXT3_DEFM_ACL)
 		set_opt(sbi->s_mount_opt, POSIX_ACL);
+#endif
 	if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_DATA)
 		sbi->s_mount_opt |= EXT3_MOUNT_JOURNAL_DATA;
 	else if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_ORDERED)
@@ -2344,6 +2348,22 @@
 				err = -EROFS;
 				goto restore_opts;
 			}
+
+			/*
+			 * If we have an unprocessed orphan list hanging
+			 * around from a previously readonly bdev mount,
+			 * require a full umount/remount for now.
+			 */
+			if (es->s_last_orphan) {
+				printk(KERN_WARNING "EXT3-fs: %s: couldn't "
+				       "remount RDWR because of unprocessed "
+				       "orphan inode list.  Please "
+				       "umount/remount instead.\n",
+				       sb->s_id);
+				err = -EINVAL;
+				goto restore_opts;
+			}
+
 			/*
 			 * Mounting a RDONLY partition read-write, so reread
 			 * and store the current valid flag.  (It may have
diff --git a/fs/ext3/symlink.c b/fs/ext3/symlink.c
index 4f79122..ff7b4cc 100644
--- a/fs/ext3/symlink.c
+++ b/fs/ext3/symlink.c
@@ -30,7 +30,7 @@
 	return NULL;
 }
 
-struct inode_operations ext3_symlink_inode_operations = {
+const struct inode_operations ext3_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -42,7 +42,7 @@
 #endif
 };
 
-struct inode_operations ext3_fast_symlink_inode_operations = {
+const struct inode_operations ext3_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= ext3_follow_link,
 #ifdef CONFIG_EXT3_FS_XATTR
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index c4dd110..8a23483 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -50,7 +50,7 @@
  * The file system contains group descriptors which are located after the
  * super block.  Each descriptor contains the number of the bitmap block and
  * the free blocks count in the block.  The descriptors are loaded in memory
- * when a file system is mounted (see ext4_read_super).
+ * when a file system is mounted (see ext4_fill_super).
  */
 
 
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index dc2724f..7916b50 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -222,7 +222,7 @@
 
 	size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
 			/ sizeof(struct ext4_extent);
-#ifdef AGRESSIVE_TEST
+#ifdef AGGRESSIVE_TEST
 	if (size > 6)
 		size = 6;
 #endif
@@ -235,7 +235,7 @@
 
 	size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
 			/ sizeof(struct ext4_extent_idx);
-#ifdef AGRESSIVE_TEST
+#ifdef AGGRESSIVE_TEST
 	if (size > 5)
 		size = 5;
 #endif
@@ -249,7 +249,7 @@
 	size = sizeof(EXT4_I(inode)->i_data);
 	size -= sizeof(struct ext4_extent_header);
 	size /= sizeof(struct ext4_extent);
-#ifdef AGRESSIVE_TEST
+#ifdef AGGRESSIVE_TEST
 	if (size > 3)
 		size = 3;
 #endif
@@ -263,7 +263,7 @@
 	size = sizeof(EXT4_I(inode)->i_data);
 	size -= sizeof(struct ext4_extent_header);
 	size /= sizeof(struct ext4_extent_idx);
-#ifdef AGRESSIVE_TEST
+#ifdef AGGRESSIVE_TEST
 	if (size > 4)
 		size = 4;
 #endif
@@ -1118,7 +1118,7 @@
 	 */
 	if (le16_to_cpu(ex1->ee_len) + le16_to_cpu(ex2->ee_len) > EXT_MAX_LEN)
 		return 0;
-#ifdef AGRESSIVE_TEST
+#ifdef AGGRESSIVE_TEST
 	if (le16_to_cpu(ex1->ee_len) >= 4)
 		return 0;
 #endif
@@ -1891,8 +1891,8 @@
 
 	if (test_opt(sb, EXTENTS)) {
 		printk("EXT4-fs: file extents enabled");
-#ifdef AGRESSIVE_TEST
-		printk(", agressive tests");
+#ifdef AGGRESSIVE_TEST
+		printk(", aggressive tests");
 #endif
 #ifdef CHECK_BINSEARCH
 		printk(", check binsearch");
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 3bbc24b..3c6c1fd 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -125,7 +125,7 @@
 	.splice_write	= generic_file_splice_write,
 };
 
-struct inode_operations ext4_file_inode_operations = {
+const struct inode_operations ext4_file_inode_operations = {
 	.truncate	= ext4_truncate,
 	.setattr	= ext4_setattr,
 #ifdef CONFIG_EXT4DEV_FS_XATTR
diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
index a679663..1555024 100644
--- a/fs/ext4/hash.c
+++ b/fs/ext4/hash.c
@@ -11,7 +11,6 @@
 
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/sched.h>
 #include <linux/ext4_fs.h>
 #include <linux/cryptohash.h>
 
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index a127cc0..fbff4b9 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -946,7 +946,7 @@
 static int ext4_get_block(struct inode *inode, sector_t iblock,
 			struct buffer_head *bh_result, int create)
 {
-	handle_t *handle = journal_current_handle();
+	handle_t *handle = ext4_journal_current_handle();
 	int ret = 0;
 	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
 
@@ -1716,7 +1716,7 @@
 	/*
 	 * Reacquire the handle: ext4_get_block() can restart the transaction
 	 */
-	handle = journal_current_handle();
+	handle = ext4_journal_current_handle();
 
 out_stop:
 	if (handle) {
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index e5a74a5..e7e1d79 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1616,21 +1616,6 @@
 	return -ENOENT;
 }
 
-/*
- * ext4_mark_inode_dirty is somewhat expensive, so unlike ext2 we
- * do not perform it in these functions.  We perform it at the call site,
- * if it is needed.
- */
-static inline void ext4_inc_count(handle_t *handle, struct inode *inode)
-{
-	inc_nlink(inode);
-}
-
-static inline void ext4_dec_count(handle_t *handle, struct inode *inode)
-{
-	drop_nlink(inode);
-}
-
 static int ext4_add_nondir(handle_t *handle,
 		struct dentry *dentry, struct inode *inode)
 {
@@ -1640,7 +1625,7 @@
 		d_instantiate(dentry, inode);
 		return 0;
 	}
-	ext4_dec_count(handle, inode);
+	drop_nlink(inode);
 	iput(inode);
 	return err;
 }
@@ -2161,7 +2146,7 @@
 		err = __page_symlink(inode, symname, l,
 				mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
 		if (err) {
-			ext4_dec_count(handle, inode);
+			drop_nlink(inode);
 			ext4_mark_inode_dirty(handle, inode);
 			iput (inode);
 			goto out_stop;
@@ -2189,6 +2174,12 @@
 
 	if (inode->i_nlink >= EXT4_LINK_MAX)
 		return -EMLINK;
+	/*
+	 * Return -ENOENT if we've raced with unlink and i_nlink is 0.  Doing
+	 * otherwise has the potential to corrupt the orphan inode list.
+	 */
+	if (inode->i_nlink == 0)
+		return -ENOENT;
 
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
@@ -2200,7 +2191,7 @@
 		handle->h_sync = 1;
 
 	inode->i_ctime = CURRENT_TIME_SEC;
-	ext4_inc_count(handle, inode);
+	inc_nlink(inode);
 	atomic_inc(&inode->i_count);
 
 	err = ext4_add_nondir(handle, dentry, inode);
@@ -2372,7 +2363,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations ext4_dir_inode_operations = {
+const struct inode_operations ext4_dir_inode_operations = {
 	.create		= ext4_create,
 	.lookup		= ext4_lookup,
 	.link		= ext4_link,
@@ -2392,7 +2383,7 @@
 	.permission	= ext4_permission,
 };
 
-struct inode_operations ext4_special_inode_operations = {
+const struct inode_operations ext4_special_inode_operations = {
 	.setattr	= ext4_setattr,
 #ifdef CONFIG_EXT4DEV_FS_XATTR
 	.setxattr	= generic_setxattr,
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 4fe49c3..ea99f6c 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -11,7 +11,6 @@
 
 #define EXT4FS_DEBUG
 
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/ext4_jbd2.h>
 
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 486a641..61c4718 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -690,7 +690,7 @@
 };
 #endif
 
-static struct super_operations ext4_sops = {
+static const struct super_operations ext4_sops = {
 	.alloc_inode	= ext4_alloc_inode,
 	.destroy_inode	= ext4_destroy_inode,
 	.read_inode	= ext4_read_inode,
@@ -1518,10 +1518,14 @@
 		set_opt(sbi->s_mount_opt, GRPID);
 	if (def_mount_opts & EXT4_DEFM_UID16)
 		set_opt(sbi->s_mount_opt, NO_UID32);
+#ifdef CONFIG_EXT4DEV_FS_XATTR
 	if (def_mount_opts & EXT4_DEFM_XATTR_USER)
 		set_opt(sbi->s_mount_opt, XATTR_USER);
+#endif
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
 	if (def_mount_opts & EXT4_DEFM_ACL)
 		set_opt(sbi->s_mount_opt, POSIX_ACL);
+#endif
 	if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
 		sbi->s_mount_opt |= EXT4_MOUNT_JOURNAL_DATA;
 	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)
@@ -2419,6 +2423,22 @@
 				err = -EROFS;
 				goto restore_opts;
 			}
+
+			/*
+			 * If we have an unprocessed orphan list hanging
+			 * around from a previously readonly bdev mount,
+			 * require a full umount/remount for now.
+			 */
+			if (es->s_last_orphan) {
+				printk(KERN_WARNING "EXT4-fs: %s: couldn't "
+				       "remount RDWR because of unprocessed "
+				       "orphan inode list.  Please "
+				       "umount/remount instead.\n",
+				       sb->s_id);
+				err = -EINVAL;
+				goto restore_opts;
+			}
+
 			/*
 			 * Mounting a RDONLY partition read-write, so reread
 			 * and store the current valid flag.  (It may have
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index fcf5272..e6f9da4 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -30,7 +30,7 @@
 	return NULL;
 }
 
-struct inode_operations ext4_symlink_inode_operations = {
+const struct inode_operations ext4_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -42,7 +42,7 @@
 #endif
 };
 
-struct inode_operations ext4_fast_symlink_inode_operations = {
+const struct inode_operations ext4_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= ext4_follow_link,
 #ifdef CONFIG_EXT4DEV_FS_XATTR
diff --git a/fs/fat/file.c b/fs/fat/file.c
index c1237b7..55d3c74 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -312,7 +312,7 @@
 }
 EXPORT_SYMBOL_GPL(fat_getattr);
 
-struct inode_operations fat_file_inode_operations = {
+const struct inode_operations fat_file_inode_operations = {
 	.truncate	= fat_truncate,
 	.setattr	= fat_notify_change,
 	.getattr	= fat_getattr,
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index a9e4688..9bfe607 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -173,10 +173,12 @@
 		 *
 		 * But we must fill the remaining area or hole by nul for
 		 * updating ->mmu_private.
+		 *
+		 * Return 0, and fallback to normal buffered write.
 		 */
 		loff_t size = offset + iov_length(iov, nr_segs);
 		if (MSDOS_I(inode)->mmu_private < size)
-			return -EINVAL;
+			return 0;
 	}
 
 	/*
@@ -618,7 +620,7 @@
 EXPORT_SYMBOL_GPL(fat_sync_inode);
 
 static int fat_show_options(struct seq_file *m, struct vfsmount *mnt);
-static struct super_operations fat_sops = {
+static const struct super_operations fat_sops = {
 	.alloc_inode	= fat_alloc_inode,
 	.destroy_inode	= fat_destroy_inode,
 	.write_inode	= fat_write_inode,
@@ -1151,7 +1153,7 @@
  * Read the super block of an MS-DOS FS.
  */
 int fat_fill_super(struct super_block *sb, void *data, int silent,
-		   struct inode_operations *fs_dir_inode_ops, int isvfat)
+		   const struct inode_operations *fs_dir_inode_ops, int isvfat)
 {
 	struct inode *root_inode = NULL;
 	struct buffer_head *bh;
diff --git a/fs/filesystems.c b/fs/filesystems.c
index e3fa77c..7a4f61a 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -12,7 +12,6 @@
 #include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/sched.h>	/* for 'current' */
 #include <asm/uaccess.h>
 
 /*
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 1cf1fe8..91ccee8 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -62,7 +62,7 @@
 extern void			vxfs_clear_inode(struct inode *);
 
 /* vxfs_lookup.c */
-extern struct inode_operations	vxfs_dir_inode_ops;
+extern const struct inode_operations	vxfs_dir_inode_ops;
 extern const struct file_operations	vxfs_dir_operations;
 
 /* vxfs_olt.c */
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c
index 4e25f3f..24b5a77 100644
--- a/fs/freevxfs/vxfs_immed.c
+++ b/fs/freevxfs/vxfs_immed.c
@@ -48,7 +48,7 @@
  * Unliked all other operations we do not go through the pagecache,
  * but do all work directly on the inode.
  */
-struct inode_operations vxfs_immed_symlink_iops = {
+const struct inode_operations vxfs_immed_symlink_iops = {
 	.readlink =		generic_readlink,
 	.follow_link =		vxfs_immed_follow_link,
 };
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 0b7ae89..098a915 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -44,7 +44,7 @@
 extern const struct address_space_operations vxfs_aops;
 extern const struct address_space_operations vxfs_immed_aops;
 
-extern struct inode_operations vxfs_immed_symlink_iops;
+extern const struct inode_operations vxfs_immed_symlink_iops;
 
 struct kmem_cache		*vxfs_inode_cachep;
 
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 3995d7f..bf86e54 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -52,7 +52,7 @@
 static struct dentry *	vxfs_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int		vxfs_readdir(struct file *, void *, filldir_t);
 
-struct inode_operations vxfs_dir_inode_ops = {
+const struct inode_operations vxfs_dir_inode_ops = {
 	.lookup =		vxfs_lookup,
 };
 
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index ac28b08..647d600 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -59,7 +59,7 @@
 static int		vxfs_statfs(struct dentry *, struct kstatfs *);
 static int		vxfs_remount(struct super_block *, int *, char *);
 
-static struct super_operations vxfs_super_ops = {
+static const struct super_operations vxfs_super_ops = {
 	.read_inode =		vxfs_read_inode,
 	.clear_inode =		vxfs_clear_inode,
 	.put_super =		vxfs_put_super,
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 1794305..105d4a2 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -73,7 +73,7 @@
 					  struct fuse_conn *fc,
 					  const char *name,
 					  int mode, int nlink,
-					  struct inode_operations *iop,
+					  const struct inode_operations *iop,
 					  const struct file_operations *fop)
 {
 	struct dentry *dentry;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 4008047..406bf61 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1242,7 +1242,7 @@
 	return err;
 }
 
-static struct inode_operations fuse_dir_inode_operations = {
+static const struct inode_operations fuse_dir_inode_operations = {
 	.lookup		= fuse_lookup,
 	.mkdir		= fuse_mkdir,
 	.symlink	= fuse_symlink,
@@ -1270,7 +1270,7 @@
 	.fsync		= fuse_dir_fsync,
 };
 
-static struct inode_operations fuse_common_inode_operations = {
+static const struct inode_operations fuse_common_inode_operations = {
 	.setattr	= fuse_setattr,
 	.permission	= fuse_permission,
 	.getattr	= fuse_getattr,
@@ -1280,7 +1280,7 @@
 	.removexattr	= fuse_removexattr,
 };
 
-static struct inode_operations fuse_symlink_inode_operations = {
+static const struct inode_operations fuse_symlink_inode_operations = {
 	.setattr	= fuse_setattr,
 	.follow_link	= fuse_follow_link,
 	.put_link	= fuse_put_link,
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index f63efe1..2fd0692 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -69,7 +69,7 @@
 	if (outarg->open_flags & FOPEN_DIRECT_IO)
 		file->f_op = &fuse_direct_io_file_operations;
 	if (!(outarg->open_flags & FOPEN_KEEP_CACHE))
-		invalidate_inode_pages(inode->i_mapping);
+		invalidate_mapping_pages(inode->i_mapping, 0, -1);
 	ff->fh = outarg->fh;
 	file->private_data = ff;
 }
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 12450d2..5ab8e50 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -112,7 +112,7 @@
 {
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size)
-		invalidate_inode_pages(inode->i_mapping);
+		invalidate_mapping_pages(inode->i_mapping, 0, -1);
 
 	inode->i_ino     = attr->ino;
 	inode->i_mode    = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
@@ -446,7 +446,7 @@
 	return fuse_iget(sb, 1, 0, &attr);
 }
 
-static struct super_operations fuse_super_operations = {
+static const struct super_operations fuse_super_operations = {
 	.alloc_inode    = fuse_alloc_inode,
 	.destroy_inode  = fuse_destroy_inode,
 	.read_inode	= fuse_read_inode,
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 113f6c9..c53a5d2 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index c93ca8f..82a1ac7 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -53,7 +53,6 @@
  * but never before the maximum hash table size has been reached.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/buffer_head.h>
diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c
index cd747c0..c1f4400 100644
--- a/fs/gfs2/eaops.c
+++ b/fs/gfs2/eaops.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index 0c83c7f..5b83ca6 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index c4b0391..46af553 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/lm.c b/fs/gfs2/lm.c
index e30673d..cfcc39b 100644
--- a/fs/gfs2/lm.c
+++ b/fs/gfs2/lm.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
index 3799f19..1dd4215 100644
--- a/fs/gfs2/locking/dlm/plock.c
+++ b/fs/gfs2/locking/dlm/plock.c
@@ -264,7 +264,7 @@
 	return 0;
 }
 
-static struct file_operations dev_fops = {
+static const struct file_operations dev_fops = {
 	.read    = dev_read,
 	.write   = dev_write,
 	.poll    = dev_poll,
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index 7c1a9e2..6e8a598 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 0e34d99..e62d4f6 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -282,8 +282,7 @@
 		return;
 	}
 
-	bd = kmem_cache_alloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL),
-	memset(bd, 0, sizeof(struct gfs2_bufdata));
+	bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL),
 	bd->bd_bh = bh;
 	bd->bd_gl = gl;
 
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c
index ef3092e..32caecd 100644
--- a/fs/gfs2/mount.c
+++ b/fs/gfs2/mount.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c
index f2495f1..d9ecfd2 100644
--- a/fs/gfs2/ondisk.c
+++ b/fs/gfs2/ondisk.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
index 9187eb1..c6bac6b 100644
--- a/fs/gfs2/ops_dentry.c
+++ b/fs/gfs2/ops_dentry.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index 4855e8c..1de05b6 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index c996aa7..b50180e 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index f40a848..d85f6e0 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
@@ -1115,7 +1114,7 @@
 	return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er);
 }
 
-struct inode_operations gfs2_file_iops = {
+const struct inode_operations gfs2_file_iops = {
 	.permission = gfs2_permission,
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
@@ -1125,7 +1124,7 @@
 	.removexattr = gfs2_removexattr,
 };
 
-struct inode_operations gfs2_dev_iops = {
+const struct inode_operations gfs2_dev_iops = {
 	.permission = gfs2_permission,
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
@@ -1135,7 +1134,7 @@
 	.removexattr = gfs2_removexattr,
 };
 
-struct inode_operations gfs2_dir_iops = {
+const struct inode_operations gfs2_dir_iops = {
 	.create = gfs2_create,
 	.lookup = gfs2_lookup,
 	.link = gfs2_link,
@@ -1154,7 +1153,7 @@
 	.removexattr = gfs2_removexattr,
 };
 
-struct inode_operations gfs2_symlink_iops = {
+const struct inode_operations gfs2_symlink_iops = {
 	.readlink = gfs2_readlink,
 	.follow_link = gfs2_follow_link,
 	.permission = gfs2_permission,
diff --git a/fs/gfs2/ops_inode.h b/fs/gfs2/ops_inode.h
index b15acb4..34f0caa 100644
--- a/fs/gfs2/ops_inode.h
+++ b/fs/gfs2/ops_inode.h
@@ -12,9 +12,9 @@
 
 #include <linux/fs.h>
 
-extern struct inode_operations gfs2_file_iops;
-extern struct inode_operations gfs2_dir_iops;
-extern struct inode_operations gfs2_symlink_iops;
-extern struct inode_operations gfs2_dev_iops;
+extern const struct inode_operations gfs2_file_iops;
+extern const struct inode_operations gfs2_dir_iops;
+extern const struct inode_operations gfs2_symlink_iops;
+extern const struct inode_operations gfs2_dev_iops;
 
 #endif /* __OPS_INODE_DOT_H__ */
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 47369d0..b89999d3 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -468,7 +468,7 @@
 	kmem_cache_free(gfs2_inode_cachep, inode);
 }
 
-struct super_operations gfs2_super_ops = {
+const struct super_operations gfs2_super_ops = {
 	.alloc_inode		= gfs2_alloc_inode,
 	.destroy_inode		= gfs2_destroy_inode,
 	.write_inode		= gfs2_write_inode,
diff --git a/fs/gfs2/ops_super.h b/fs/gfs2/ops_super.h
index 9de73f0..442a274 100644
--- a/fs/gfs2/ops_super.h
+++ b/fs/gfs2/ops_super.h
@@ -12,6 +12,6 @@
 
 #include <linux/fs.h>
 
-extern struct super_operations gfs2_super_ops;
+extern const struct super_operations gfs2_super_ops;
 
 #endif /* __OPS_SUPER_DOT_H__ */
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c
index 14b380f..aa0dbd2 100644
--- a/fs/gfs2/ops_vm.c
+++ b/fs/gfs2/ops_vm.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index d0c806b..8bc182c 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index ff08465..8d9c08b 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index e5707a9..601eaa1 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index e2e0358..7c69b98 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -320,7 +320,7 @@
 	.release	= hfs_dir_release,
 };
 
-struct inode_operations hfs_dir_inode_operations = {
+const struct inode_operations hfs_dir_inode_operations = {
 	.create		= hfs_create,
 	.lookup		= hfs_lookup,
 	.unlink		= hfs_unlink,
diff --git a/fs/hfs/hfs.h b/fs/hfs/hfs.h
index 88099ab..1445e3a 100644
--- a/fs/hfs/hfs.h
+++ b/fs/hfs/hfs.h
@@ -83,8 +83,6 @@
 
 /*======== HFS structures as they appear on the disk ========*/
 
-#define __packed __attribute__ ((packed))
-
 /* Pascal-style string of up to 31 characters */
 struct hfs_name {
 	u8 len;
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 735332d..147374b 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -170,7 +170,7 @@
 
 /* dir.c */
 extern const struct file_operations hfs_dir_operations;
-extern struct inode_operations hfs_dir_inode_operations;
+extern const struct inode_operations hfs_dir_inode_operations;
 
 /* extent.c */
 extern int hfs_ext_keycmp(const btree_key *, const btree_key *);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 5cb7f8f..fafcba5 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -18,7 +18,7 @@
 #include "btree.h"
 
 static const struct file_operations hfs_file_operations;
-static struct inode_operations hfs_file_inode_operations;
+static const struct inode_operations hfs_file_inode_operations;
 
 /*================ Variable-like macros ================*/
 
@@ -612,7 +612,7 @@
 	.release	= hfs_file_release,
 };
 
-static struct inode_operations hfs_file_inode_operations = {
+static const struct inode_operations hfs_file_inode_operations = {
 	.lookup		= hfs_file_lookup,
 	.truncate	= hfs_file_truncate,
 	.setattr	= hfs_inode_setattr,
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index a369879..623f509 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -154,7 +154,7 @@
 	kmem_cache_free(hfs_inode_cachep, HFS_I(inode));
 }
 
-static struct super_operations hfs_super_operations = {
+static const struct super_operations hfs_super_operations = {
 	.alloc_inode	= hfs_alloc_inode,
 	.destroy_inode	= hfs_destroy_inode,
 	.write_inode	= hfs_write_inode,
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index f2d7c49..ba117c4 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -8,7 +8,6 @@
  * Handling of catalog records
  */
 
-#include <linux/sched.h>
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index e886ac8..80b5682 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -10,7 +10,6 @@
 
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 
@@ -471,7 +470,7 @@
 	return res;
 }
 
-struct inode_operations hfsplus_dir_inode_operations = {
+const struct inode_operations hfsplus_dir_inode_operations = {
 	.lookup		= hfsplus_lookup,
 	.create		= hfsplus_create,
 	.link		= hfsplus_link,
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index 4920553..fe99fe8 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -15,8 +15,6 @@
 
 #include <linux/types.h>
 
-#define __packed __attribute__ ((packed))
-
 /* Some constants */
 #define HFSPLUS_SECTOR_SIZE        512
 #define HFSPLUS_SECTOR_SHIFT         9
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 75e8c4d..642012a 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -268,10 +268,10 @@
 	return 0;
 }
 
-extern struct inode_operations hfsplus_dir_inode_operations;
+extern const struct inode_operations hfsplus_dir_inode_operations;
 extern struct file_operations hfsplus_dir_operations;
 
-static struct inode_operations hfsplus_file_inode_operations = {
+static const struct inode_operations hfsplus_file_inode_operations = {
 	.lookup		= hfsplus_file_lookup,
 	.truncate	= hfsplus_file_truncate,
 	.permission	= hfsplus_permission,
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 0f513c6..1a97f92 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/pagemap.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/vfs.h>
 #include <linux/nls.h>
@@ -260,7 +259,7 @@
 	return 0;
 }
 
-static struct super_operations hfsplus_sops = {
+static const struct super_operations hfsplus_sops = {
 	.alloc_inode	= hfsplus_alloc_inode,
 	.destroy_inode	= hfsplus_destroy_inode,
 	.read_inode	= hfsplus_read_inode,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 69a376f..e965eb1 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -52,8 +52,8 @@
 
 #define HOSTFS_SUPER_MAGIC 0x00c0ffee
 
-static struct inode_operations hostfs_iops;
-static struct inode_operations hostfs_dir_iops;
+static const struct inode_operations hostfs_iops;
+static const struct inode_operations hostfs_dir_iops;
 static const struct address_space_operations hostfs_link_aops;
 
 #ifndef MODULE
@@ -309,7 +309,7 @@
 	read_inode(inode);
 }
 
-static struct super_operations hostfs_sbops = {
+static const struct super_operations hostfs_sbops = {
 	.alloc_inode	= hostfs_alloc_inode,
 	.drop_inode	= generic_delete_inode,
 	.delete_inode   = hostfs_delete_inode,
@@ -880,7 +880,7 @@
 	return(0);
 }
 
-static struct inode_operations hostfs_iops = {
+static const struct inode_operations hostfs_iops = {
 	.create		= hostfs_create,
 	.link		= hostfs_link,
 	.unlink		= hostfs_unlink,
@@ -894,7 +894,7 @@
 	.getattr	= hostfs_getattr,
 };
 
-static struct inode_operations hostfs_dir_iops = {
+static const struct inode_operations hostfs_dir_iops = {
 	.create		= hostfs_create,
 	.lookup		= hostfs_lookup,
 	.link		= hostfs_link,
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index fb4c891..b4eafc0 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -132,7 +132,7 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-struct inode_operations hpfs_file_iops =
+const struct inode_operations hpfs_file_iops =
 {
 	.truncate	= hpfs_truncate,
 	.setattr	= hpfs_notify_change,
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 1c07aa8..42ff60c 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -266,7 +266,7 @@
 
 int hpfs_file_fsync(struct file *, struct dentry *, int);
 extern const struct file_operations hpfs_file_ops;
-extern struct inode_operations hpfs_file_iops;
+extern const struct inode_operations hpfs_file_iops;
 extern const struct address_space_operations hpfs_aops;
 
 /* inode.c */
@@ -302,7 +302,7 @@
 
 /* namei.c */
 
-extern struct inode_operations hpfs_dir_iops;
+extern const struct inode_operations hpfs_dir_iops;
 extern const struct address_space_operations hpfs_symlink_aops;
 
 static inline struct hpfs_inode_info *hpfs_i(struct inode *inode)
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 2507e73..9953cf9 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -659,7 +659,7 @@
 	return err;
 }
 
-struct inode_operations hpfs_dir_iops =
+const struct inode_operations hpfs_dir_iops =
 {
 	.create		= hpfs_create,
 	.lookup		= hpfs_lookup,
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index d4abc1a..e0174e3 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -426,7 +426,7 @@
 
 /* Super operations */
 
-static struct super_operations hpfs_sops =
+static const struct super_operations hpfs_sops =
 {
 	.alloc_inode	= hpfs_alloc_inode,
 	.destroy_inode	= hpfs_destroy_inode,
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index afd340a..affb741 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -43,7 +43,7 @@
 
 #define HPPFS_SUPER_MAGIC 0xb00000ee
 
-static struct super_operations hppfs_sbops;
+static const struct super_operations hppfs_sbops;
 
 static int is_pid(struct dentry *dentry)
 {
@@ -212,7 +212,7 @@
 	return(ERR_PTR(err));
 }
 
-static struct inode_operations hppfs_file_iops = {
+static const struct inode_operations hppfs_file_iops = {
 };
 
 static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count,
@@ -649,7 +649,7 @@
 	kfree(HPPFS_I(inode));
 }
 
-static struct super_operations hppfs_sbops = {
+static const struct super_operations hppfs_sbops = {
 	.alloc_inode	= hppfs_alloc_inode,
 	.destroy_inode	= hppfs_destroy_inode,
 	.read_inode	= hppfs_read_inode,
@@ -693,11 +693,11 @@
 	return ret;
 }
 
-static struct inode_operations hppfs_dir_iops = {
+static const struct inode_operations hppfs_dir_iops = {
 	.lookup		= hppfs_lookup,
 };
 
-static struct inode_operations hppfs_link_iops = {
+static const struct inode_operations hppfs_link_iops = {
 	.readlink	= hppfs_readlink,
 	.follow_link	= hppfs_follow_link,
 };
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 4f4cd13..8c718a3 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -33,11 +33,11 @@
 /* some random number */
 #define HUGETLBFS_MAGIC	0x958458f6
 
-static struct super_operations hugetlbfs_ops;
+static const struct super_operations hugetlbfs_ops;
 static const struct address_space_operations hugetlbfs_aops;
 const struct file_operations hugetlbfs_file_operations;
-static struct inode_operations hugetlbfs_dir_inode_operations;
-static struct inode_operations hugetlbfs_inode_operations;
+static const struct inode_operations hugetlbfs_dir_inode_operations;
+static const struct inode_operations hugetlbfs_inode_operations;
 
 static struct backing_dev_info hugetlbfs_backing_dev_info = {
 	.ra_pages	= 0,	/* No readahead */
@@ -449,10 +449,13 @@
 }
 
 /*
- * For direct-IO reads into hugetlb pages
+ * mark the head page dirty
  */
 static int hugetlbfs_set_page_dirty(struct page *page)
 {
+	struct page *head = (struct page *)page_private(page);
+
+	SetPageDirty(head);
 	return 0;
 }
 
@@ -560,7 +563,7 @@
 	.get_unmapped_area	= hugetlb_get_unmapped_area,
 };
 
-static struct inode_operations hugetlbfs_dir_inode_operations = {
+static const struct inode_operations hugetlbfs_dir_inode_operations = {
 	.create		= hugetlbfs_create,
 	.lookup		= simple_lookup,
 	.link		= simple_link,
@@ -573,11 +576,11 @@
 	.setattr	= hugetlbfs_setattr,
 };
 
-static struct inode_operations hugetlbfs_inode_operations = {
+static const struct inode_operations hugetlbfs_inode_operations = {
 	.setattr	= hugetlbfs_setattr,
 };
 
-static struct super_operations hugetlbfs_ops = {
+static const struct super_operations hugetlbfs_ops = {
 	.alloc_inode    = hugetlbfs_alloc_inode,
 	.destroy_inode  = hugetlbfs_destroy_inode,
 	.statfs		= hugetlbfs_statfs,
diff --git a/fs/inode.c b/fs/inode.c
index bf21dc6..5abb097 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -414,7 +414,8 @@
 			__iget(inode);
 			spin_unlock(&inode_lock);
 			if (remove_inode_buffers(inode))
-				reap += invalidate_inode_pages(&inode->i_data);
+				reap += invalidate_mapping_pages(&inode->i_data,
+								0, -1);
 			iput(inode);
 			spin_lock(&inode_lock);
 
@@ -709,7 +710,7 @@
 struct inode *igrab(struct inode *inode)
 {
 	spin_lock(&inode_lock);
-	if (!(inode->i_state & (I_FREEING|I_WILL_FREE)))
+	if (!(inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)))
 		__iget(inode);
 	else
 		/*
@@ -999,7 +1000,7 @@
  */
 void generic_delete_inode(struct inode *inode)
 {
-	struct super_operations *op = inode->i_sb->s_op;
+	const struct super_operations *op = inode->i_sb->s_op;
 
 	list_del_init(&inode->i_list);
 	list_del_init(&inode->i_sb_list);
@@ -1092,7 +1093,7 @@
  */
 static inline void iput_final(struct inode *inode)
 {
-	struct super_operations *op = inode->i_sb->s_op;
+	const struct super_operations *op = inode->i_sb->s_op;
 	void (*drop)(struct inode *) = generic_drop_inode;
 
 	if (op && op->drop_inode)
@@ -1112,7 +1113,7 @@
 void iput(struct inode *inode)
 {
 	if (inode) {
-		struct super_operations *op = inode->i_sb->s_op;
+		const struct super_operations *op = inode->i_sb->s_op;
 
 		BUG_ON(inode->i_state == I_CLEAR);
 
@@ -1160,11 +1161,9 @@
 	struct inode *inode = dentry->d_inode;
 	struct timespec now;
 
-	if (IS_RDONLY(inode))
-		return;
 	if (inode->i_flags & S_NOATIME)
 		return;
-	if (inode->i_sb->s_flags & MS_NOATIME)
+	if (IS_NOATIME(inode))
 		return;
 	if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
 		return;
@@ -1252,33 +1251,6 @@
 
 EXPORT_SYMBOL(inode_needs_sync);
 
-/*
- *	Quota functions that want to walk the inode lists..
- */
-#ifdef CONFIG_QUOTA
-
-void remove_dquot_ref(struct super_block *sb, int type,
-			struct list_head *tofree_head)
-{
-	struct inode *inode;
-
-	if (!sb->dq_op)
-		return;	/* nothing to do */
-	spin_lock(&inode_lock);	/* This lock is for inodes code */
-
-	/*
-	 * We don't have to lock against quota code - test IS_QUOTAINIT is
-	 * just for speedup...
-	 */
-	list_for_each_entry(inode, &sb->s_inodes, i_sb_list)
-		if (!IS_NOQUOTA(inode))
-			remove_inode_dquot_ref(inode, type, tofree_head);
-
-	spin_unlock(&inode_lock);
-}
-
-#endif
-
 int inode_wait(void *word)
 {
 	schedule();
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 55f6da5..9f2224f 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -455,8 +455,16 @@
 			break;
 
 		kevent = inotify_dev_get_event(dev);
-		if (event_size + kevent->event.len > count)
+		if (event_size + kevent->event.len > count) {
+			if (ret == 0 && count > 0) {
+				/*
+				 * could not get a single event because we
+				 * didn't have enough buffer space.
+				 */
+				ret = -EINVAL;
+			}
 			break;
+		}
 
 		if (copy_to_user(buf, &kevent->event, event_size)) {
 			ret = -EFAULT;
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 89e8da1..10d2c21 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -60,6 +60,7 @@
 	int data = IOPRIO_PRIO_DATA(ioprio);
 	struct task_struct *p, *g;
 	struct user_struct *user;
+	struct pid *pgrp;
 	int ret;
 
 	switch (class) {
@@ -98,12 +99,14 @@
 			break;
 		case IOPRIO_WHO_PGRP:
 			if (!who)
-				who = process_group(current);
-			do_each_task_pid(who, PIDTYPE_PGID, p) {
+				pgrp = task_pgrp(current);
+			else
+				pgrp = find_pid(who);
+			do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 				ret = set_task_ioprio(p, ioprio);
 				if (ret)
 					break;
-			} while_each_task_pid(who, PIDTYPE_PGID, p);
+			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 			break;
 		case IOPRIO_WHO_USER:
 			if (!who)
@@ -167,6 +170,7 @@
 {
 	struct task_struct *g, *p;
 	struct user_struct *user;
+	struct pid *pgrp;
 	int ret = -ESRCH;
 	int tmpio;
 
@@ -182,8 +186,10 @@
 			break;
 		case IOPRIO_WHO_PGRP:
 			if (!who)
-				who = process_group(current);
-			do_each_task_pid(who, PIDTYPE_PGID, p) {
+				pgrp = task_pgrp(current);
+			else
+				pgrp = find_pid(who);
+			do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 				tmpio = get_task_ioprio(p);
 				if (tmpio < 0)
 					continue;
@@ -191,7 +197,7 @@
 					ret = tmpio;
 				else
 					ret = ioprio_best(ret, tmpio);
-			} while_each_task_pid(who, PIDTYPE_PGID, p);
+			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 			break;
 		case IOPRIO_WHO_USER:
 			if (!who)
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 4af2548..0e94c31 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -24,7 +24,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations isofs_dir_inode_operations =
+const struct inode_operations isofs_dir_inode_operations =
 {
 	.lookup		= isofs_lookup,
 };
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index ea55b6c..64a96cd 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -106,7 +106,7 @@
 	return 0;
 }
 
-static struct super_operations isofs_sops = {
+static const struct super_operations isofs_sops = {
 	.alloc_inode	= isofs_alloc_inode,
 	.destroy_inode	= isofs_destroy_inode,
 	.read_inode	= isofs_read_inode,
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index e6308c8..efe2872 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -174,7 +174,7 @@
 	}
 }
 
-extern struct inode_operations isofs_dir_inode_operations;
+extern const struct inode_operations isofs_dir_inode_operations;
 extern const struct file_operations isofs_dir_operations;
 extern const struct address_space_operations isofs_symlink_aops;
 extern struct export_operations isofs_export_ops;
diff --git a/fs/jffs/Makefile b/fs/jffs/Makefile
deleted file mode 100644
index 9c1c0bb..0000000
--- a/fs/jffs/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the linux Journalling Flash FileSystem (JFFS) routines.
-#
-# $Id: Makefile,v 1.11 2001/09/25 20:59:41 dwmw2 Exp $
-#
-
-obj-$(CONFIG_JFFS_FS) += jffs.o
-
-jffs-y 				:= jffs_fm.o intrep.o inode-v23.o
-jffs-$(CONFIG_JFFS_PROC_FS)	+= jffs_proc.o
-jffs-objs			:= $(jffs-y)
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
deleted file mode 100644
index 43baa1a..0000000
--- a/fs/jffs/inode-v23.c
+++ /dev/null
@@ -1,1847 +0,0 @@
-/*
- * JFFS -- Journalling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This 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.
- *
- * $Id: inode-v23.c,v 1.70 2001/10/02 09:16:02 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- * Copyright 2000, 2001  Red Hat, Inc.
- */
-
-/* inode.c -- Contains the code that is called from the VFS.  */
-
-/* TODO-ALEX:
- * uid and gid are just 16 bit.
- * jffs_file_write reads from user-space pointers without xx_from_user
- * maybe other stuff do to.
- */
-
-#include <linux/time.h>
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/jffs.h>
-#include <linux/fs.h>
-#include <linux/smp_lock.h>
-#include <linux/ioctl.h>
-#include <linux/stat.h>
-#include <linux/blkdev.h>
-#include <linux/quotaops.h>
-#include <linux/highmem.h>
-#include <linux/vfs.h>
-#include <linux/mutex.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#include "jffs_fm.h"
-#include "intrep.h"
-#ifdef CONFIG_JFFS_PROC_FS
-#include "jffs_proc.h"
-#endif
-
-static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
-
-static struct super_operations jffs_ops;
-static const struct file_operations jffs_file_operations;
-static struct inode_operations jffs_file_inode_operations;
-static const struct file_operations jffs_dir_operations;
-static struct inode_operations jffs_dir_inode_operations;
-static const struct address_space_operations jffs_address_operations;
-
-struct kmem_cache     *node_cache = NULL;
-struct kmem_cache     *fm_cache = NULL;
-
-/* Called by the VFS at mount time to initialize the whole file system.  */
-static int jffs_fill_super(struct super_block *sb, void *data, int silent)
-{
-	struct inode *root_inode;
-	struct jffs_control *c;
-
-	sb->s_flags |= MS_NODIRATIME;
-
-	D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
-		  sb->s_id));
-
-	if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) {
-		printk(KERN_WARNING "JFFS: Trying to mount a "
-		       "non-mtd device.\n");
-		return -EINVAL;
-	}
-
-	sb->s_blocksize = PAGE_CACHE_SIZE;
-	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_fs_info = (void *) 0;
-	sb->s_maxbytes = 0xFFFFFFFF;
-
-	/* Build the file system.  */
-	if (jffs_build_fs(sb) < 0) {
-		goto jffs_sb_err1;
-	}
-
-	/*
-	 * set up enough so that we can read an inode
-	 */
-	sb->s_magic = JFFS_MAGIC_SB_BITMASK;
-	sb->s_op = &jffs_ops;
-
-	root_inode = iget(sb, JFFS_MIN_INO);
-	if (!root_inode)
-	        goto jffs_sb_err2;
-
-	/* Get the root directory of this file system.  */
-	if (!(sb->s_root = d_alloc_root(root_inode))) {
-		goto jffs_sb_err3;
-	}
-
-	c = (struct jffs_control *) sb->s_fs_info;
-
-#ifdef CONFIG_JFFS_PROC_FS
-	/* Set up the jffs proc file system.  */
-	if (jffs_register_jffs_proc_dir(MINOR(sb->s_dev), c) < 0) {
-		printk(KERN_WARNING "JFFS: Failed to initialize the JFFS "
-			"proc file system for device %s.\n",
-			sb->s_id);
-	}
-#endif
-
-	/* Set the Garbage Collection thresholds */
-
-	/* GC if free space goes below 5% of the total size */
-	c->gc_minfree_threshold = c->fmc->flash_size / 20;
-
-	if (c->gc_minfree_threshold < c->fmc->sector_size)
-		c->gc_minfree_threshold = c->fmc->sector_size;
-
-	/* GC if dirty space exceeds 33% of the total size. */
-	c->gc_maxdirty_threshold = c->fmc->flash_size / 3;
-
-	if (c->gc_maxdirty_threshold < c->fmc->sector_size)
-		c->gc_maxdirty_threshold = c->fmc->sector_size;
-
-
-	c->thread_pid = kernel_thread (jffs_garbage_collect_thread, 
-				        (void *) c, 
-				        CLONE_KERNEL);
-	D1(printk(KERN_NOTICE "JFFS: GC thread pid=%d.\n", (int) c->thread_pid));
-
-	D1(printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n",
-	       sb->s_id));
-	return 0;
-
-jffs_sb_err3:
-	iput(root_inode);
-jffs_sb_err2:
-	jffs_cleanup_control((struct jffs_control *)sb->s_fs_info);
-jffs_sb_err1:
-	printk(KERN_WARNING "JFFS: Failed to mount device %s.\n",
-	       sb->s_id);
-	return -EINVAL;
-}
-
-
-/* This function is called when the file system is umounted.  */
-static void
-jffs_put_super(struct super_block *sb)
-{
-	struct jffs_control *c = (struct jffs_control *) sb->s_fs_info;
-
-	D2(printk("jffs_put_super()\n"));
-
-#ifdef CONFIG_JFFS_PROC_FS
-	jffs_unregister_jffs_proc_dir(c);
-#endif
-
-	if (c->gc_task) {
-		D1(printk (KERN_NOTICE "jffs_put_super(): Telling gc thread to die.\n"));
-		send_sig(SIGKILL, c->gc_task, 1);
-	}
-	wait_for_completion(&c->gc_thread_comp);
-
-	D1(printk (KERN_NOTICE "jffs_put_super(): Successfully waited on thread.\n"));
-
-	jffs_cleanup_control((struct jffs_control *)sb->s_fs_info);
-	D1(printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
-	       sb->s_id));
-}
-
-
-/* This function is called when user commands like chmod, chgrp and
-   chown are executed. System calls like trunc() results in a call
-   to this function.  */
-static int
-jffs_setattr(struct dentry *dentry, struct iattr *iattr)
-{
-	struct inode *inode = dentry->d_inode;
-	struct jffs_raw_inode raw_inode;
-	struct jffs_control *c;
-	struct jffs_fmcontrol *fmc;
-	struct jffs_file *f;
-	struct jffs_node *new_node;
-	int update_all;
-	int res = 0;
-	int recoverable = 0;
-
-	lock_kernel();
-
-	if ((res = inode_change_ok(inode, iattr))) 
-		goto out;
-
-	c = (struct jffs_control *)inode->i_sb->s_fs_info;
-	fmc = c->fmc;
-
-	D3(printk (KERN_NOTICE "notify_change(): down biglock\n"));
-	mutex_lock(&fmc->biglock);
-
-	f = jffs_find_file(c, inode->i_ino);
-
-	ASSERT(if (!f) {
-		printk("jffs_setattr(): Invalid inode number: %lu\n",
-		       inode->i_ino);
-		D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
-		mutex_unlock(&fmc->biglock);
-		res = -EINVAL;
-		goto out;
-	});
-
-	D1(printk("***jffs_setattr(): file: \"%s\", ino: %u\n",
-		  f->name, f->ino));
-
-	update_all = iattr->ia_valid & ATTR_FORCE;
-
-	if ( (update_all || iattr->ia_valid & ATTR_SIZE)
-	     && (iattr->ia_size + 128 < f->size) ) {
-		/* We're shrinking the file by more than 128 bytes.
-		   We'll be able to GC and recover this space, so
-		   allow it to go into the reserved space. */
-		recoverable = 1;
-        }
-
-	if (!(new_node = jffs_alloc_node())) {
-		D(printk("jffs_setattr(): Allocation failed!\n"));
-		D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
-		mutex_unlock(&fmc->biglock);
-		res = -ENOMEM;
-		goto out;
-	}
-
-	new_node->data_offset = 0;
-	new_node->removed_size = 0;
-	raw_inode.magic = JFFS_MAGIC_BITMASK;
-	raw_inode.ino = f->ino;
-	raw_inode.pino = f->pino;
-	raw_inode.mode = f->mode;
-	raw_inode.uid = f->uid;
-	raw_inode.gid = f->gid;
-	raw_inode.atime = f->atime;
-	raw_inode.mtime = f->mtime;
-	raw_inode.ctime = f->ctime;
-	raw_inode.dsize = 0;
-	raw_inode.offset = 0;
-	raw_inode.rsize = 0;
-	raw_inode.dsize = 0;
-	raw_inode.nsize = f->nsize;
-	raw_inode.nlink = f->nlink;
-	raw_inode.spare = 0;
-	raw_inode.rename = 0;
-	raw_inode.deleted = 0;
-
-	if (update_all || iattr->ia_valid & ATTR_MODE) {
-		raw_inode.mode = iattr->ia_mode;
-		inode->i_mode = iattr->ia_mode;
-	}
-	if (update_all || iattr->ia_valid & ATTR_UID) {
-		raw_inode.uid = iattr->ia_uid;
-		inode->i_uid = iattr->ia_uid;
-	}
-	if (update_all || iattr->ia_valid & ATTR_GID) {
-		raw_inode.gid = iattr->ia_gid;
-		inode->i_gid = iattr->ia_gid;
-	}
-	if (update_all || iattr->ia_valid & ATTR_SIZE) {
-		int len;
-		D1(printk("jffs_notify_change(): Changing size "
-			  "to %lu bytes!\n", (long)iattr->ia_size));
-		raw_inode.offset = iattr->ia_size;
-
-		/* Calculate how many bytes need to be removed from
-		   the end.  */
-		if (f->size < iattr->ia_size) {
-			len = 0;
-		}
-		else {
-			len = f->size - iattr->ia_size;
-		}
-
-		raw_inode.rsize = len;
-
-		/* The updated node will be a removal node, with
-		   base at the new size and size of the nbr of bytes
-		   to be removed.  */
-		new_node->data_offset = iattr->ia_size;
-		new_node->removed_size = len;
-		inode->i_size = iattr->ia_size;
-		inode->i_blocks = (inode->i_size + 511) >> 9;
-
-		if (len) {
-			invalidate_inode_pages(inode->i_mapping);
-		}
-		inode->i_ctime = CURRENT_TIME_SEC;
-		inode->i_mtime = inode->i_ctime;
-	}
-	if (update_all || iattr->ia_valid & ATTR_ATIME) {
-		raw_inode.atime = iattr->ia_atime.tv_sec;
-		inode->i_atime = iattr->ia_atime;
-	}
-	if (update_all || iattr->ia_valid & ATTR_MTIME) {
-		raw_inode.mtime = iattr->ia_mtime.tv_sec;
-		inode->i_mtime = iattr->ia_mtime;
-	}
-	if (update_all || iattr->ia_valid & ATTR_CTIME) {
-		raw_inode.ctime = iattr->ia_ctime.tv_sec;
-		inode->i_ctime = iattr->ia_ctime;
-	}
-
-	/* Write this node to the flash.  */
-	if ((res = jffs_write_node(c, new_node, &raw_inode, f->name, NULL, recoverable, f)) < 0) {
-		D(printk("jffs_notify_change(): The write failed!\n"));
-		jffs_free_node(new_node);
-		D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
-		mutex_unlock(&c->fmc->biglock);
-		goto out;
-	}
-
-	jffs_insert_node(c, f, &raw_inode, NULL, new_node);
-
-	mark_inode_dirty(inode);
-	D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-out:
-	unlock_kernel();
-	return res;
-} /* jffs_notify_change()  */
-
-
-static struct inode *
-jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
-	       int * err)
-{
-	struct super_block * sb;
-	struct inode * inode;
-	struct jffs_control *c;
-	struct jffs_file *f;
-
-	sb = dir->i_sb;
-	inode = new_inode(sb);
-	if (!inode) {
-		*err = -ENOMEM;
-		return NULL;
-	}
-
-	c = (struct jffs_control *)sb->s_fs_info;
-
-	inode->i_ino = raw_inode->ino;
-	inode->i_mode = raw_inode->mode;
-	inode->i_nlink = raw_inode->nlink;
-	inode->i_uid = raw_inode->uid;
-	inode->i_gid = raw_inode->gid;
-	inode->i_size = raw_inode->dsize;
-	inode->i_atime.tv_sec = raw_inode->atime;
-	inode->i_mtime.tv_sec = raw_inode->mtime;
-	inode->i_ctime.tv_sec = raw_inode->ctime;
-	inode->i_ctime.tv_nsec = 0;
-	inode->i_mtime.tv_nsec = 0;
-	inode->i_atime.tv_nsec = 0;
-	inode->i_blocks = (inode->i_size + 511) >> 9;
-
-	f = jffs_find_file(c, raw_inode->ino);
-
-	inode->i_private = (void *)f;
-	insert_inode_hash(inode);
-
-	return inode;
-}
-
-/* Get statistics of the file system.  */
-static int
-jffs_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
-	struct jffs_control *c = (struct jffs_control *) dentry->d_sb->s_fs_info;
-	struct jffs_fmcontrol *fmc;
-
-	lock_kernel();
-
-	fmc = c->fmc;
-
-	D2(printk("jffs_statfs()\n"));
-
-	buf->f_type = JFFS_MAGIC_SB_BITMASK;
-	buf->f_bsize = PAGE_CACHE_SIZE;
-	buf->f_blocks = (fmc->flash_size / PAGE_CACHE_SIZE)
-		       - (fmc->min_free_size / PAGE_CACHE_SIZE);
-	buf->f_bfree = (jffs_free_size1(fmc) + jffs_free_size2(fmc) +
-		       fmc->dirty_size - fmc->min_free_size)
-			       >> PAGE_CACHE_SHIFT;
-	buf->f_bavail = buf->f_bfree;
-
-	/* Find out how many files there are in the filesystem.  */
-	buf->f_files = jffs_foreach_file(c, jffs_file_count);
-	buf->f_ffree = buf->f_bfree;
-	/* buf->f_fsid = 0; */
-	buf->f_namelen = JFFS_MAX_NAME_LEN;
-
-	unlock_kernel();
-
-	return 0;
-}
-
-
-/* Rename a file.  */
-static int
-jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
-	    struct inode *new_dir, struct dentry *new_dentry)
-{
-	struct jffs_raw_inode raw_inode;
-	struct jffs_control *c;
-	struct jffs_file *old_dir_f;
-	struct jffs_file *new_dir_f;
-	struct jffs_file *del_f;
-	struct jffs_file *f;
-	struct jffs_node *node;
-	struct inode *inode;
-	int result = 0;
-	__u32 rename_data = 0;
-
-	D2(printk("***jffs_rename()\n"));
-
-	D(printk("jffs_rename(): old_dir: 0x%p, old name: 0x%p, "
-		 "new_dir: 0x%p, new name: 0x%p\n",
-		 old_dir, old_dentry->d_name.name,
-		 new_dir, new_dentry->d_name.name));
-
-	lock_kernel();
-	c = (struct jffs_control *)old_dir->i_sb->s_fs_info;
-	ASSERT(if (!c) {
-		printk(KERN_ERR "jffs_rename(): The old_dir inode "
-		       "didn't have a reference to a jffs_file struct\n");
-		unlock_kernel();
-		return -EIO;
-	});
-
-	result = -ENOTDIR;
-	if (!(old_dir_f = old_dir->i_private)) {
-		D(printk("jffs_rename(): Old dir invalid.\n"));
-		goto jffs_rename_end;
-	}
-
-	/* Try to find the file to move.  */
-	result = -ENOENT;
-	if (!(f = jffs_find_child(old_dir_f, old_dentry->d_name.name,
-				  old_dentry->d_name.len))) {
-		goto jffs_rename_end;
-	}
-
-	/* Find the new directory.  */
-	result = -ENOTDIR;
-	if (!(new_dir_f = new_dir->i_private)) {
-		D(printk("jffs_rename(): New dir invalid.\n"));
-		goto jffs_rename_end;
-	}
-	D3(printk (KERN_NOTICE "rename(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-	/* Create a node and initialize as much as needed.  */
-	result = -ENOMEM;
-	if (!(node = jffs_alloc_node())) {
-		D(printk("jffs_rename(): Allocation failed: node == 0\n"));
-		goto jffs_rename_end;
-	}
-	node->data_offset = 0;
-	node->removed_size = 0;
-
-	/* Initialize the raw inode.  */
-	raw_inode.magic = JFFS_MAGIC_BITMASK;
-	raw_inode.ino = f->ino;
-	raw_inode.pino = new_dir_f->ino;
-/*  	raw_inode.version = f->highest_version + 1; */
-	raw_inode.mode = f->mode;
-	raw_inode.uid = current->fsuid;
-	raw_inode.gid = current->fsgid;
-#if 0
-	raw_inode.uid = f->uid;
-	raw_inode.gid = f->gid;
-#endif
-	raw_inode.atime = get_seconds();
-	raw_inode.mtime = raw_inode.atime;
-	raw_inode.ctime = f->ctime;
-	raw_inode.offset = 0;
-	raw_inode.dsize = 0;
-	raw_inode.rsize = 0;
-	raw_inode.nsize = new_dentry->d_name.len;
-	raw_inode.nlink = f->nlink;
-	raw_inode.spare = 0;
-	raw_inode.rename = 0;
-	raw_inode.deleted = 0;
-
-	/* See if there already exists a file with the same name as
-	   new_name.  */
-	if ((del_f = jffs_find_child(new_dir_f, new_dentry->d_name.name,
-				     new_dentry->d_name.len))) {
-		raw_inode.rename = 1;
-		raw_inode.dsize = sizeof(__u32);
-		rename_data = del_f->ino;
-	}
-
-	/* Write the new node to the flash memory.  */
-	if ((result = jffs_write_node(c, node, &raw_inode,
-				      new_dentry->d_name.name,
-				      (unsigned char*)&rename_data, 0, f)) < 0) {
-		D(printk("jffs_rename(): Failed to write node to flash.\n"));
-		jffs_free_node(node);
-		goto jffs_rename_end;
-	}
-	raw_inode.dsize = 0;
-
-	if (raw_inode.rename) {
-		/* The file with the same name must be deleted.  */
-		//FIXME deadlock	        down(&c->fmc->gclock);
-		if ((result = jffs_remove(new_dir, new_dentry,
-					  del_f->mode)) < 0) {
-			/* This is really bad.  */
-			printk(KERN_ERR "JFFS: An error occurred in "
-			       "rename().\n");
-		}
-		//		up(&c->fmc->gclock);
-	}
-
-	if (old_dir_f != new_dir_f) {
-		/* Remove the file from its old position in the
-		   filesystem tree.  */
-		jffs_unlink_file_from_tree(f);
-	}
-
-	/* Insert the new node into the file system.  */
-	if ((result = jffs_insert_node(c, f, &raw_inode,
-				       new_dentry->d_name.name, node)) < 0) {
-		D(printk(KERN_ERR "jffs_rename(): jffs_insert_node() "
-			 "failed!\n"));
-	}
-
-	if (old_dir_f != new_dir_f) {
-		/* Insert the file to its new position in the
-		   file system.  */
-		jffs_insert_file_into_tree(f);
-	}
-
-	/* This is a kind of update of the inode we're about to make
-	   here.  This is what they do in ext2fs.  Kind of.  */
-	if ((inode = iget(new_dir->i_sb, f->ino))) {
-		inode->i_ctime = CURRENT_TIME_SEC;
-		mark_inode_dirty(inode);
-		iput(inode);
-	}
-
-jffs_rename_end:
-	D3(printk (KERN_NOTICE "rename(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-	unlock_kernel();
-	return result;
-} /* jffs_rename()  */
-
-
-/* Read the contents of a directory.  Used by programs like `ls'
-   for instance.  */
-static int
-jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
-{
-	struct jffs_file *f;
-	struct dentry *dentry = filp->f_path.dentry;
-	struct inode *inode = dentry->d_inode;
-	struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
-	int j;
-	int ddino;
-	lock_kernel();
-	D3(printk (KERN_NOTICE "readdir(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-
-	D2(printk("jffs_readdir(): inode: 0x%p, filp: 0x%p\n", inode, filp));
-	if (filp->f_pos == 0) {
-		D3(printk("jffs_readdir(): \".\" %lu\n", inode->i_ino));
-		if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) {
-			D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
-			mutex_unlock(&c->fmc->biglock);
-			unlock_kernel();
-			return 0;
-		}
-		filp->f_pos = 1;
-	}
-	if (filp->f_pos == 1) {
-		if (inode->i_ino == JFFS_MIN_INO) {
-			ddino = JFFS_MIN_INO;
-		}
-		else {
-			ddino = ((struct jffs_file *)
-				 inode->i_private)->pino;
-		}
-		D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
-		if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0) {
-			D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
-			mutex_unlock(&c->fmc->biglock);
-			unlock_kernel();
-			return 0;
-		}
-		filp->f_pos++;
-	}
-	f = ((struct jffs_file *)inode->i_private)->children;
-
-	j = 2;
-	while(f && (f->deleted || j++ < filp->f_pos )) {
-		f = f->sibling_next;
-	}
-
-	while (f) {
-		D3(printk("jffs_readdir(): \"%s\" ino: %u\n",
-			  (f->name ? f->name : ""), f->ino));
-		if (filldir(dirent, f->name, f->nsize,
-			    filp->f_pos , f->ino, DT_UNKNOWN) < 0) {
-		        D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
-			mutex_unlock(&c->fmc->biglock);
-			unlock_kernel();
-			return 0;
-		}
-		filp->f_pos++;
-		do {
-			f = f->sibling_next;
-		} while(f && f->deleted);
-	}
-	D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-	unlock_kernel();
-	return filp->f_pos;
-} /* jffs_readdir()  */
-
-
-/* Find a file in a directory. If the file exists, return its
-   corresponding dentry.  */
-static struct dentry *
-jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-	struct jffs_file *d;
-	struct jffs_file *f;
-	struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
-	int len;
-	int r = 0;
-	const char *name;
-	struct inode *inode = NULL;
-
-	len = dentry->d_name.len;
-	name = dentry->d_name.name;
-
-	lock_kernel();
-
-	D3({
-		char *s = kmalloc(len + 1, GFP_KERNEL);
-		memcpy(s, name, len);
-		s[len] = '\0';
-		printk("jffs_lookup(): dir: 0x%p, name: \"%s\"\n", dir, s);
-		kfree(s);
-	});
-
-	D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-
-	r = -ENAMETOOLONG;
-	if (len > JFFS_MAX_NAME_LEN) {
-		goto jffs_lookup_end;
-	}
-
-	r = -EACCES;
-	if (!(d = (struct jffs_file *)dir->i_private)) {
-		D(printk("jffs_lookup(): No such inode! (%lu)\n",
-			 dir->i_ino));
-		goto jffs_lookup_end;
-	}
-
-	/* Get the corresponding inode to the file.  */
-
-	/* iget calls jffs_read_inode, so we need to drop the biglock
-           before calling iget.  Unfortunately, the GC has a tendency
-           to sneak in here, because iget sometimes calls schedule ().
-	*/
-
-	if ((len == 1) && (name[0] == '.')) {
-		D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
-		mutex_unlock(&c->fmc->biglock);
-		if (!(inode = iget(dir->i_sb, d->ino))) {
-			D(printk("jffs_lookup(): . iget() ==> NULL\n"));
-			goto jffs_lookup_end_no_biglock;
-		}
-		D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
-		mutex_lock(&c->fmc->biglock);
-	} else if ((len == 2) && (name[0] == '.') && (name[1] == '.')) {
-	        D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
-		mutex_unlock(&c->fmc->biglock);
- 		if (!(inode = iget(dir->i_sb, d->pino))) {
-			D(printk("jffs_lookup(): .. iget() ==> NULL\n"));
-			goto jffs_lookup_end_no_biglock;
-		}
-		D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
-		mutex_lock(&c->fmc->biglock);
-	} else if ((f = jffs_find_child(d, name, len))) {
-	        D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
-		mutex_unlock(&c->fmc->biglock);
-		if (!(inode = iget(dir->i_sb, f->ino))) {
-			D(printk("jffs_lookup(): iget() ==> NULL\n"));
-			goto jffs_lookup_end_no_biglock;
-		}
-		D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
-		mutex_lock(&c->fmc->biglock);
-	} else {
-		D3(printk("jffs_lookup(): Couldn't find the file. "
-			  "f = 0x%p, name = \"%s\", d = 0x%p, d->ino = %u\n",
-			  f, name, d, d->ino));
-		inode = NULL;
-	}
-
-	d_add(dentry, inode);
-	D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-	unlock_kernel();
-	return NULL;
-
-jffs_lookup_end:
-	D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-
-jffs_lookup_end_no_biglock:
-	unlock_kernel();
-	return ERR_PTR(r);
-} /* jffs_lookup()  */
-
-
-/* Try to read a page of data from a file.  */
-static int
-jffs_do_readpage_nolock(struct file *file, struct page *page)
-{
-	void *buf;
-	unsigned long read_len;
-	int result;
-	struct inode *inode = (struct inode*)page->mapping->host;
-	struct jffs_file *f = (struct jffs_file *)inode->i_private;
-	struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
-	int r;
-	loff_t offset;
-
-	D2(printk("***jffs_readpage(): file = \"%s\", page->index = %lu\n",
-		  (f->name ? f->name : ""), (long)page->index));
-
-	get_page(page);
-	/* Don't SetPageLocked(page), should be locked already */
-	ClearPageUptodate(page);
-	ClearPageError(page);
-
-	D3(printk (KERN_NOTICE "readpage(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-
-	read_len = 0;
-	result = 0;
-	offset = page_offset(page);
-
-	kmap(page);
-	buf = page_address(page);
-	if (offset < inode->i_size) {
-		read_len = min_t(long, inode->i_size - offset, PAGE_SIZE);
-		r = jffs_read_data(f, buf, offset, read_len);
-		if (r != read_len) {
-			result = -EIO;
-			D(
-			        printk("***jffs_readpage(): Read error! "
-				       "Wanted to read %lu bytes but only "
-				       "read %d bytes.\n", read_len, r);
-			  );
-		}
-
-	}
-
-	/* This handles the case of partial or no read in above */
-	if(read_len < PAGE_SIZE)
-	        memset(buf + read_len, 0, PAGE_SIZE - read_len);
-	flush_dcache_page(page);
-	kunmap(page);
-
-	D3(printk (KERN_NOTICE "readpage(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-
-	if (result) {
-	        SetPageError(page);
-	}else {
-	        SetPageUptodate(page);	        
-	}
-
-	page_cache_release(page);
-
-	D3(printk("jffs_readpage(): Leaving...\n"));
-
-	return result;
-} /* jffs_do_readpage_nolock()  */
-
-static int jffs_readpage(struct file *file, struct page *page)
-{
-	int ret = jffs_do_readpage_nolock(file, page);
-	unlock_page(page);
-	return ret;
-}
-
-/* Create a new directory.  */
-static int
-jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
-	struct jffs_raw_inode raw_inode;
-	struct jffs_control *c;
-	struct jffs_node *node;
-	struct jffs_file *dir_f;
-	struct inode *inode;
-	int dir_mode;
-	int result = 0;
-	int err;
-
-	D1({
-	        int len = dentry->d_name.len;
-		char *_name = kmalloc(len + 1, GFP_KERNEL);
-		memcpy(_name, dentry->d_name.name, len);
-		_name[len] = '\0';
-		printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", "
-		       "len = %d, mode = 0x%08x\n", dir, _name, len, mode);
-		kfree(_name);
-	});
-
-	lock_kernel();
-	dir_f = dir->i_private;
-
-	ASSERT(if (!dir_f) {
-		printk(KERN_ERR "jffs_mkdir(): No reference to a "
-		       "jffs_file struct in inode.\n");
-		unlock_kernel();
-		return -EIO;
-	});
-
-	c = dir_f->c;
-	D3(printk (KERN_NOTICE "mkdir(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-
-	dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX)
-			      & ~current->fs->umask);
-	if (dir->i_mode & S_ISGID) {
-		dir_mode |= S_ISGID;
-	}
-
-	/* Create a node and initialize it as much as needed.  */
-	if (!(node = jffs_alloc_node())) {
-		D(printk("jffs_mkdir(): Allocation failed: node == 0\n"));
-		result = -ENOMEM;
-		goto jffs_mkdir_end;
-	}
-	node->data_offset = 0;
-	node->removed_size = 0;
-
-	/* Initialize the raw inode.  */
-	raw_inode.magic = JFFS_MAGIC_BITMASK;
-	raw_inode.ino = c->next_ino++;
-	raw_inode.pino = dir_f->ino;
-	raw_inode.version = 1;
-	raw_inode.mode = dir_mode;
-	raw_inode.uid = current->fsuid;
-	raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-	/*	raw_inode.gid = current->fsgid; */
-	raw_inode.atime = get_seconds();
-	raw_inode.mtime = raw_inode.atime;
-	raw_inode.ctime = raw_inode.atime;
-	raw_inode.offset = 0;
-	raw_inode.dsize = 0;
-	raw_inode.rsize = 0;
-	raw_inode.nsize = dentry->d_name.len;
-	raw_inode.nlink = 1;
-	raw_inode.spare = 0;
-	raw_inode.rename = 0;
-	raw_inode.deleted = 0;
-
-	/* Write the new node to the flash.  */
-	if ((result = jffs_write_node(c, node, &raw_inode,
-				     dentry->d_name.name, NULL, 0, NULL)) < 0) {
-		D(printk("jffs_mkdir(): jffs_write_node() failed.\n"));
-		jffs_free_node(node);
-		goto jffs_mkdir_end;
-	}
-
-	/* Insert the new node into the file system.  */
-	if ((result = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
-				       node)) < 0) {
-		goto jffs_mkdir_end;
-	}
-
-	inode = jffs_new_inode(dir, &raw_inode, &err);
-	if (inode == NULL) {
-		result = err;
-		goto jffs_mkdir_end;
-	}
-
-	inode->i_op = &jffs_dir_inode_operations;
-	inode->i_fop = &jffs_dir_operations;
-
-	mark_inode_dirty(dir);
-	d_instantiate(dentry, inode);
-
-	result = 0;
-jffs_mkdir_end:
-	D3(printk (KERN_NOTICE "mkdir(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-	unlock_kernel();
-	return result;
-} /* jffs_mkdir()  */
-
-
-/* Remove a directory.  */
-static int
-jffs_rmdir(struct inode *dir, struct dentry *dentry)
-{
-	struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
-	int ret;
-	D3(printk("***jffs_rmdir()\n"));
-	D3(printk (KERN_NOTICE "rmdir(): down biglock\n"));
-	lock_kernel();
-	mutex_lock(&c->fmc->biglock);
-	ret = jffs_remove(dir, dentry, S_IFDIR);
-	D3(printk (KERN_NOTICE "rmdir(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-	unlock_kernel();
-	return ret;
-}
-
-
-/* Remove any kind of file except for directories.  */
-static int
-jffs_unlink(struct inode *dir, struct dentry *dentry)
-{
-	struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
-	int ret; 
-
-	lock_kernel();
-	D3(printk("***jffs_unlink()\n"));
-	D3(printk (KERN_NOTICE "unlink(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-	ret = jffs_remove(dir, dentry, 0);
-	D3(printk (KERN_NOTICE "unlink(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-	unlock_kernel();
-	return ret;
-}
-
-
-/* Remove a JFFS entry, i.e. plain files, directories, etc.  Here we
-   shouldn't test for free space on the device.  */
-static int
-jffs_remove(struct inode *dir, struct dentry *dentry, int type)
-{
-	struct jffs_raw_inode raw_inode;
-	struct jffs_control *c;
-	struct jffs_file *dir_f; /* The file-to-remove's parent.  */
-	struct jffs_file *del_f; /* The file to remove.  */
-	struct jffs_node *del_node;
-	struct inode *inode = NULL;
-	int result = 0;
-
-	D1({
-		int len = dentry->d_name.len;
-		const char *name = dentry->d_name.name;
-		char *_name = kmalloc(len + 1, GFP_KERNEL);
-		memcpy(_name, name, len);
-		_name[len] = '\0';
-		printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino);
-		kfree(_name);
-	});
-
-	dir_f = dir->i_private;
-	c = dir_f->c;
-
-	result = -ENOENT;
-	if (!(del_f = jffs_find_child(dir_f, dentry->d_name.name,
-				      dentry->d_name.len))) {
-		D(printk("jffs_remove(): jffs_find_child() failed.\n"));
-		goto jffs_remove_end;
-	}
-
-	if (S_ISDIR(type)) {
-		struct jffs_file *child = del_f->children;
-		while(child) {
-			if( !child->deleted ) {
-				result = -ENOTEMPTY;
-				goto jffs_remove_end;
-			}
-			child = child->sibling_next;
-		}
-	}            
-	else if (S_ISDIR(del_f->mode)) {
-		D(printk("jffs_remove(): node is a directory "
-			 "but it shouldn't be.\n"));
-		result = -EPERM;
-		goto jffs_remove_end;
-	}
-
-	inode = dentry->d_inode;
-
-	result = -EIO;
-	if (del_f->ino != inode->i_ino)
-		goto jffs_remove_end;
-
-	if (!inode->i_nlink) {
-		printk("Deleting nonexistent file inode: %lu, nlink: %d\n",
-		       inode->i_ino, inode->i_nlink);
-		inode->i_nlink=1;
-	}
-
-	/* Create a node for the deletion.  */
-	result = -ENOMEM;
-	if (!(del_node = jffs_alloc_node())) {
-		D(printk("jffs_remove(): Allocation failed!\n"));
-		goto jffs_remove_end;
-	}
-	del_node->data_offset = 0;
-	del_node->removed_size = 0;
-
-	/* Initialize the raw inode.  */
-	raw_inode.magic = JFFS_MAGIC_BITMASK;
-	raw_inode.ino = del_f->ino;
-	raw_inode.pino = del_f->pino;
-/*  	raw_inode.version = del_f->highest_version + 1; */
-	raw_inode.mode = del_f->mode;
-	raw_inode.uid = current->fsuid;
-	raw_inode.gid = current->fsgid;
-	raw_inode.atime = get_seconds();
-	raw_inode.mtime = del_f->mtime;
-	raw_inode.ctime = raw_inode.atime;
-	raw_inode.offset = 0;
-	raw_inode.dsize = 0;
-	raw_inode.rsize = 0;
-	raw_inode.nsize = 0;
-	raw_inode.nlink = del_f->nlink;
-	raw_inode.spare = 0;
-	raw_inode.rename = 0;
-	raw_inode.deleted = 1;
-
-	/* Write the new node to the flash memory.  */
-	if (jffs_write_node(c, del_node, &raw_inode, NULL, NULL, 1, del_f) < 0) {
-		jffs_free_node(del_node);
-		result = -EIO;
-		goto jffs_remove_end;
-	}
-
-	/* Update the file.  This operation will make the file disappear
-	   from the in-memory file system structures.  */
-	jffs_insert_node(c, del_f, &raw_inode, NULL, del_node);
-
-	dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
-	mark_inode_dirty(dir);
-	inode->i_ctime = dir->i_ctime;
-	inode_dec_link_count(inode);
-
-	d_delete(dentry);	/* This also frees the inode */
-
-	result = 0;
-jffs_remove_end:
-	return result;
-} /* jffs_remove()  */
-
-
-static int
-jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
-{
-	struct jffs_raw_inode raw_inode;
-	struct jffs_file *dir_f;
-	struct jffs_node *node = NULL;
-	struct jffs_control *c;
-	struct inode *inode;
-	int result = 0;
-	u16 data = old_encode_dev(rdev);
-	int err;
-
-	D1(printk("***jffs_mknod()\n"));
-
-	if (!old_valid_dev(rdev))
-		return -EINVAL;
-	lock_kernel();
-	dir_f = dir->i_private;
-	c = dir_f->c;
-
-	D3(printk (KERN_NOTICE "mknod(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-
-	/* Create and initialize a new node.  */
-	if (!(node = jffs_alloc_node())) {
-		D(printk("jffs_mknod(): Allocation failed!\n"));
-		result = -ENOMEM;
-		goto jffs_mknod_err;
-	}
-	node->data_offset = 0;
-	node->removed_size = 0;
-
-	/* Initialize the raw inode.  */
-	raw_inode.magic = JFFS_MAGIC_BITMASK;
-	raw_inode.ino = c->next_ino++;
-	raw_inode.pino = dir_f->ino;
-	raw_inode.version = 1;
-	raw_inode.mode = mode;
-	raw_inode.uid = current->fsuid;
-	raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-	/*	raw_inode.gid = current->fsgid; */
-	raw_inode.atime = get_seconds();
-	raw_inode.mtime = raw_inode.atime;
-	raw_inode.ctime = raw_inode.atime;
-	raw_inode.offset = 0;
-	raw_inode.dsize = 2;
-	raw_inode.rsize = 0;
-	raw_inode.nsize = dentry->d_name.len;
-	raw_inode.nlink = 1;
-	raw_inode.spare = 0;
-	raw_inode.rename = 0;
-	raw_inode.deleted = 0;
-
-	/* Write the new node to the flash.  */
-	if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
-				   (unsigned char *)&data, 0, NULL)) < 0) {
-		D(printk("jffs_mknod(): jffs_write_node() failed.\n"));
-		result = err;
-		goto jffs_mknod_err;
-	}
-
-	/* Insert the new node into the file system.  */
-	if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
-				    node)) < 0) {
-		result = err;
-		goto jffs_mknod_end;
-	}
-
-	inode = jffs_new_inode(dir, &raw_inode, &err);
-	if (inode == NULL) {
-		result = err;
-		goto jffs_mknod_end;
-	}
-
-	init_special_inode(inode, mode, rdev);
-
-	d_instantiate(dentry, inode);
-
-	goto jffs_mknod_end;
-
-jffs_mknod_err:
-	if (node) {
-		jffs_free_node(node);
-	}
-
-jffs_mknod_end:
-	D3(printk (KERN_NOTICE "mknod(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-	unlock_kernel();
-	return result;
-} /* jffs_mknod()  */
-
-
-static int
-jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
-{
-	struct jffs_raw_inode raw_inode;
-	struct jffs_control *c;
-	struct jffs_file *dir_f;
-	struct jffs_node *node;
-	struct inode *inode;
-
-	int symname_len = strlen(symname);
-	int err;
-
-	lock_kernel();
-	D1({
-		int len = dentry->d_name.len; 
-		char *_name = kmalloc(len + 1, GFP_KERNEL);
-		char *_symname = kmalloc(symname_len + 1, GFP_KERNEL);
-		memcpy(_name, dentry->d_name.name, len);
-		_name[len] = '\0';
-		memcpy(_symname, symname, symname_len);
-		_symname[symname_len] = '\0';
-		printk("***jffs_symlink(): dir = 0x%p, "
-		       "dentry->dname.name = \"%s\", "
-		       "symname = \"%s\"\n", dir, _name, _symname);
-		kfree(_name);
-		kfree(_symname);
-	});
-
-	dir_f = dir->i_private;
-	ASSERT(if (!dir_f) {
-		printk(KERN_ERR "jffs_symlink(): No reference to a "
-		       "jffs_file struct in inode.\n");
-		unlock_kernel();
-		return -EIO;
-	});
-
-	c = dir_f->c;
-
-	/* Create a node and initialize it as much as needed.  */
-	if (!(node = jffs_alloc_node())) {
-		D(printk("jffs_symlink(): Allocation failed: node = NULL\n"));
-		unlock_kernel();
-		return -ENOMEM;
-	}
-	D3(printk (KERN_NOTICE "symlink(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-
-	node->data_offset = 0;
-	node->removed_size = 0;
-
-	/* Initialize the raw inode.  */
-	raw_inode.magic = JFFS_MAGIC_BITMASK;
-	raw_inode.ino = c->next_ino++;
-	raw_inode.pino = dir_f->ino;
-	raw_inode.version = 1;
-	raw_inode.mode = S_IFLNK | S_IRWXUGO;
-	raw_inode.uid = current->fsuid;
-	raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-	raw_inode.atime = get_seconds();
-	raw_inode.mtime = raw_inode.atime;
-	raw_inode.ctime = raw_inode.atime;
-	raw_inode.offset = 0;
-	raw_inode.dsize = symname_len;
-	raw_inode.rsize = 0;
-	raw_inode.nsize = dentry->d_name.len;
-	raw_inode.nlink = 1;
-	raw_inode.spare = 0;
-	raw_inode.rename = 0;
-	raw_inode.deleted = 0;
-
-	/* Write the new node to the flash.  */
-	if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
-				   (const unsigned char *)symname, 0, NULL)) < 0) {
-		D(printk("jffs_symlink(): jffs_write_node() failed.\n"));
-		jffs_free_node(node);
-		goto jffs_symlink_end;
-	}
-
-	/* Insert the new node into the file system.  */
-	if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
-				    node)) < 0) {
-		goto jffs_symlink_end;
-	}
-
-	inode = jffs_new_inode(dir, &raw_inode, &err);
-	if (inode == NULL) {
-		goto jffs_symlink_end;
-	}
-	err = 0;
-	inode->i_op = &page_symlink_inode_operations;
-	inode->i_mapping->a_ops = &jffs_address_operations;
-
-	d_instantiate(dentry, inode);
- jffs_symlink_end:
-	D3(printk (KERN_NOTICE "symlink(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-	unlock_kernel();
-	return err;
-} /* jffs_symlink()  */
-
-
-/* Create an inode inside a JFFS directory (dir) and return it.
- *
- * By the time this is called, we already have created
- * the directory cache entry for the new file, but it
- * is so far negative - it has no inode.
- *
- * If the create succeeds, we fill in the inode information
- * with d_instantiate().
- */
-static int
-jffs_create(struct inode *dir, struct dentry *dentry, int mode,
-		struct nameidata *nd)
-{
-	struct jffs_raw_inode raw_inode;
-	struct jffs_control *c;
-	struct jffs_node *node;
-	struct jffs_file *dir_f; /* JFFS representation of the directory.  */
-	struct inode *inode;
-	int err;
-
-	lock_kernel();
-	D1({
-		int len = dentry->d_name.len;
-		char *s = kmalloc(len + 1, GFP_KERNEL);
-		memcpy(s, dentry->d_name.name, len);
-		s[len] = '\0';
-		printk("jffs_create(): dir: 0x%p, name: \"%s\"\n", dir, s);
-		kfree(s);
-	});
-
-	dir_f = dir->i_private;
-	ASSERT(if (!dir_f) {
-		printk(KERN_ERR "jffs_create(): No reference to a "
-		       "jffs_file struct in inode.\n");
-		unlock_kernel();
-		return -EIO;
-	});
-
-	c = dir_f->c;
-
-	/* Create a node and initialize as much as needed.  */
-	if (!(node = jffs_alloc_node())) {
-		D(printk("jffs_create(): Allocation failed: node == 0\n"));
-		unlock_kernel();
-		return -ENOMEM;
-	}
-	D3(printk (KERN_NOTICE "create(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-
-	node->data_offset = 0;
-	node->removed_size = 0;
-
-	/* Initialize the raw inode.  */
-	raw_inode.magic = JFFS_MAGIC_BITMASK;
-	raw_inode.ino = c->next_ino++;
-	raw_inode.pino = dir_f->ino;
-	raw_inode.version = 1;
-	raw_inode.mode = mode;
-	raw_inode.uid = current->fsuid;
-	raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-	raw_inode.atime = get_seconds();
-	raw_inode.mtime = raw_inode.atime;
-	raw_inode.ctime = raw_inode.atime;
-	raw_inode.offset = 0;
-	raw_inode.dsize = 0;
-	raw_inode.rsize = 0;
-	raw_inode.nsize = dentry->d_name.len;
-	raw_inode.nlink = 1;
-	raw_inode.spare = 0;
-	raw_inode.rename = 0;
-	raw_inode.deleted = 0;
-
-	/* Write the new node to the flash.  */
-	if ((err = jffs_write_node(c, node, &raw_inode,
-				   dentry->d_name.name, NULL, 0, NULL)) < 0) {
-		D(printk("jffs_create(): jffs_write_node() failed.\n"));
-		jffs_free_node(node);
-		goto jffs_create_end;
-	}
-
-	/* Insert the new node into the file system.  */
-	if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
-				    node)) < 0) {
-		goto jffs_create_end;
-	}
-
-	/* Initialize an inode.  */
-	inode = jffs_new_inode(dir, &raw_inode, &err);
-	if (inode == NULL) {
-		goto jffs_create_end;
-	}
-	err = 0;
-	inode->i_op = &jffs_file_inode_operations;
-	inode->i_fop = &jffs_file_operations;
-	inode->i_mapping->a_ops = &jffs_address_operations;
-	inode->i_mapping->nrpages = 0;
-
-	d_instantiate(dentry, inode);
- jffs_create_end:
-	D3(printk (KERN_NOTICE "create(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-	unlock_kernel();
-	return err;
-} /* jffs_create()  */
-
-
-/* Write, append or rewrite data to an existing file.  */
-static ssize_t
-jffs_file_write(struct file *filp, const char *buf, size_t count,
-		loff_t *ppos)
-{
-	struct jffs_raw_inode raw_inode;
-	struct jffs_control *c;
-	struct jffs_file *f;
-	struct jffs_node *node;
-	struct dentry *dentry = filp->f_path.dentry;
-	struct inode *inode = dentry->d_inode;
-	int recoverable = 0;
-	size_t written = 0;
-	__u32 thiscount = count;
-	loff_t pos = *ppos;
-	int err;
-
-	inode = filp->f_path.dentry->d_inode;
-
-	D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), "
-		  "filp: 0x%p, buf: 0x%p, count: %d\n",
-		  inode, inode->i_ino, filp, buf, count));
-
-#if 0
-	if (inode->i_sb->s_flags & MS_RDONLY) {
-		D(printk("jffs_file_write(): MS_RDONLY\n"));
-		err = -EROFS;
-		goto out_isem;
-	}
-#endif	
-	err = -EINVAL;
-
-	if (!S_ISREG(inode->i_mode)) {
-		D(printk("jffs_file_write(): inode->i_mode == 0x%08x\n",
-				inode->i_mode));
-		goto out_isem;
-	}
-
-	if (!(f = inode->i_private)) {
-		D(printk("jffs_file_write(): inode->i_private = 0x%p\n",
-				inode->i_private));
-		goto out_isem;
-	}
-
-	c = f->c;
-
-	/*
-	 * This will never trigger with sane page sizes.  leave it in
-	 * anyway, since I'm thinking about how to merge larger writes
-	 * (the current idea is to poke a thread that does the actual
-	 * I/O and starts by doing a mutex_lock(&inode->i_mutex).  then we
-	 * would need to get the page cache pages and have a list of
-	 * I/O requests and do write-merging here.
-	 * -- prumpf
-	 */
-	thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
-
-	D3(printk (KERN_NOTICE "file_write(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-
-	/* Urgh. POSIX says we can do short writes if we feel like it. 
-	 * In practice, we can't. Nothing will cope. So we loop until
-	 * we're done.
-	 *
-	 * <_Anarchy_> posix and reality are not interconnected on this issue
-	 */
-	while (count) {
-		/* Things are going to be written so we could allocate and
-		   initialize the necessary data structures now.  */
-		if (!(node = jffs_alloc_node())) {
-			D(printk("jffs_file_write(): node == 0\n"));
-			err = -ENOMEM;
-			goto out;
-		}
-
-		node->data_offset = pos;
-		node->removed_size = 0;
-
-		/* Initialize the raw inode.  */
-		raw_inode.magic = JFFS_MAGIC_BITMASK;
-		raw_inode.ino = f->ino;
-		raw_inode.pino = f->pino;
-
-		raw_inode.mode = f->mode;
-
-		raw_inode.uid = f->uid;
-		raw_inode.gid = f->gid;
-		raw_inode.atime = get_seconds();
-		raw_inode.mtime = raw_inode.atime;
-		raw_inode.ctime = f->ctime;
-		raw_inode.offset = pos;
-		raw_inode.dsize = thiscount;
-		raw_inode.rsize = 0;
-		raw_inode.nsize = f->nsize;
-		raw_inode.nlink = f->nlink;
-		raw_inode.spare = 0;
-		raw_inode.rename = 0;
-		raw_inode.deleted = 0;
-
-		if (pos < f->size) {
-			node->removed_size = raw_inode.rsize = min(thiscount, (__u32)(f->size - pos));
-
-			/* If this node is going entirely over the top of old data,
-			   we can allow it to go into the reserved space, because
-			   we know that GC can reclaim the space later.
-			*/
-			if (pos + thiscount < f->size) {
-				/* If all the data we're overwriting are _real_,
-				   not just holes, then:
-				   recoverable = 1;
-				*/
-			}
-		}
-
-		/* Write the new node to the flash.  */
-		/* NOTE: We would be quite happy if jffs_write_node() wrote a
-		   smaller node than we were expecting. There's no need for it
-		   to waste the space at the end of the flash just because it's
-		   a little smaller than what we asked for. But that's a whole
-		   new can of worms which I'm not going to open this week. 
-		   -- dwmw2.
-		*/
-		if ((err = jffs_write_node(c, node, &raw_inode, f->name,
-					   (const unsigned char *)buf,
-					   recoverable, f)) < 0) {
-			D(printk("jffs_file_write(): jffs_write_node() failed.\n"));
-			jffs_free_node(node);
-			goto out;
-		}
-
-		written += err;
-		buf += err;
-		count -= err;
-		pos += err;
-
-		/* Insert the new node into the file system.  */
-		if ((err = jffs_insert_node(c, f, &raw_inode, NULL, node)) < 0) {
-			goto out;
-		}
-
-		D3(printk("jffs_file_write(): new f_pos %ld.\n", (long)pos));
-
-		thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
-	}
- out:
-	D3(printk (KERN_NOTICE "file_write(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-
-	/* Fix things in the real inode.  */
-	if (pos > inode->i_size) {
-		inode->i_size = pos;
-		inode->i_blocks = (inode->i_size + 511) >> 9;
-	}
-	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
-	mark_inode_dirty(inode);
-	invalidate_inode_pages(inode->i_mapping);
-
- out_isem:
-	return err;
-} /* jffs_file_write()  */
-
-static int
-jffs_prepare_write(struct file *filp, struct page *page,
-                  unsigned from, unsigned to)
-{
-	/* FIXME: we should detect some error conditions here */
-
-	/* Bugger that. We should make sure the page is uptodate */
-	if (!PageUptodate(page) && (from || to < PAGE_CACHE_SIZE))
-		return jffs_do_readpage_nolock(filp, page);
-
-	return 0;
-} /* jffs_prepare_write() */
-
-static int
-jffs_commit_write(struct file *filp, struct page *page,
-                 unsigned from, unsigned to)
-{
-       void *addr = page_address(page) + from;
-       /* XXX: PAGE_CACHE_SHIFT or PAGE_SHIFT */
-       loff_t pos = page_offset(page) + from;
-
-       return jffs_file_write(filp, addr, to-from, &pos);
-} /* jffs_commit_write() */
-
-/* This is our ioctl() routine.  */
-static int
-jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-	   unsigned long arg)
-{
-	struct jffs_control *c;
-	int ret = 0;
-
-	D2(printk("***jffs_ioctl(): cmd = 0x%08x, arg = 0x%08lx\n",
-		  cmd, arg));
-
-	if (!(c = (struct jffs_control *)inode->i_sb->s_fs_info)) {
-		printk(KERN_ERR "JFFS: Bad inode in ioctl() call. "
-		       "(cmd = 0x%08x)\n", cmd);
-		return -EIO;
-	}
-	D3(printk (KERN_NOTICE "ioctl(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-
-	switch (cmd) {
-	case JFFS_PRINT_HASH:
-		jffs_print_hash_table(c);
-		break;
-	case JFFS_PRINT_TREE:
-		jffs_print_tree(c->root, 0);
-		break;
-	case JFFS_GET_STATUS:
-		{
-			struct jffs_flash_status fst;
-			struct jffs_fmcontrol *fmc = c->fmc;
-			printk("Flash status -- ");
-			if (!access_ok(VERIFY_WRITE,
-				       (struct jffs_flash_status __user *)arg,
-				       sizeof(struct jffs_flash_status))) {
-				D(printk("jffs_ioctl(): Bad arg in "
-					 "JFFS_GET_STATUS ioctl!\n"));
-				ret = -EFAULT;
-				break;
-			}
-			fst.size = fmc->flash_size;
-			fst.used = fmc->used_size;
-			fst.dirty = fmc->dirty_size;
-			fst.begin = fmc->head->offset;
-			fst.end = fmc->tail->offset + fmc->tail->size;
-			printk("size: %d, used: %d, dirty: %d, "
-			       "begin: %d, end: %d\n",
-			       fst.size, fst.used, fst.dirty,
-			       fst.begin, fst.end);
-			if (copy_to_user((struct jffs_flash_status __user *)arg,
-					 &fst,
-					 sizeof(struct jffs_flash_status))) {
-				ret = -EFAULT;
-			}
-		}
-		break;
-	default:
-		ret = -ENOTTY;
-	}
-	D3(printk (KERN_NOTICE "ioctl(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-	return ret;
-} /* jffs_ioctl()  */
-
-
-static const struct address_space_operations jffs_address_operations = {
-	.readpage	= jffs_readpage,
-	.prepare_write	= jffs_prepare_write,
-	.commit_write	= jffs_commit_write,
-};
-
-static int jffs_fsync(struct file *f, struct dentry *d, int datasync)
-{
-	/* We currently have O_SYNC operations at all times.
-	   Do nothing.
-	*/
-	return 0;
-}
-
-
-static const struct file_operations jffs_file_operations =
-{
-	.open		= generic_file_open,
-	.llseek		= generic_file_llseek,
-	.read		= do_sync_read,
-	.aio_read	= generic_file_aio_read,
-	.write		= do_sync_write,
-	.aio_write	= generic_file_aio_write,
-	.ioctl		= jffs_ioctl,
-	.mmap		= generic_file_readonly_mmap,
-	.fsync		= jffs_fsync,
-	.sendfile	= generic_file_sendfile,
-};
-
-
-static struct inode_operations jffs_file_inode_operations =
-{
-	.lookup		= jffs_lookup,          /* lookup */
-	.setattr	= jffs_setattr,
-};
-
-
-static const struct file_operations jffs_dir_operations =
-{
-	.readdir	= jffs_readdir,
-};
-
-
-static struct inode_operations jffs_dir_inode_operations =
-{
-	.create		= jffs_create,
-	.lookup		= jffs_lookup,
-	.unlink		= jffs_unlink,
-	.symlink	= jffs_symlink,
-	.mkdir		= jffs_mkdir,
-	.rmdir		= jffs_rmdir,
-	.mknod		= jffs_mknod,
-	.rename		= jffs_rename,
-	.setattr	= jffs_setattr,
-};
-
-
-/* Initialize an inode for the VFS.  */
-static void
-jffs_read_inode(struct inode *inode)
-{
-	struct jffs_file *f;
-	struct jffs_control *c;
-
-	D3(printk("jffs_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
-
-	if (!inode->i_sb) {
-		D(printk("jffs_read_inode(): !inode->i_sb ==> "
-			 "No super block!\n"));
-		return;
-	}
-	c = (struct jffs_control *)inode->i_sb->s_fs_info;
-	D3(printk (KERN_NOTICE "read_inode(): down biglock\n"));
-	mutex_lock(&c->fmc->biglock);
-	if (!(f = jffs_find_file(c, inode->i_ino))) {
-		D(printk("jffs_read_inode(): No such inode (%lu).\n",
-			 inode->i_ino));
-		D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
-		mutex_unlock(&c->fmc->biglock);
-		return;
-	}
-	inode->i_private = f;
-	inode->i_mode = f->mode;
-	inode->i_nlink = f->nlink;
-	inode->i_uid = f->uid;
-	inode->i_gid = f->gid;
-	inode->i_size = f->size;
-	inode->i_atime.tv_sec = f->atime;
-	inode->i_mtime.tv_sec = f->mtime;
-	inode->i_ctime.tv_sec = f->ctime;
-	inode->i_atime.tv_nsec = 
-	inode->i_mtime.tv_nsec = 
-	inode->i_ctime.tv_nsec = 0;
-
-	inode->i_blocks = (inode->i_size + 511) >> 9;
-	if (S_ISREG(inode->i_mode)) {
-		inode->i_op = &jffs_file_inode_operations;
-		inode->i_fop = &jffs_file_operations;
-		inode->i_mapping->a_ops = &jffs_address_operations;
-	}
-	else if (S_ISDIR(inode->i_mode)) {
-		inode->i_op = &jffs_dir_inode_operations;
-		inode->i_fop = &jffs_dir_operations;
-	}
-	else if (S_ISLNK(inode->i_mode)) {
-		inode->i_op = &page_symlink_inode_operations;
-		inode->i_mapping->a_ops = &jffs_address_operations;
-	}
-	else {
-		/* If the node is a device of some sort, then the number of
-		   the device should be read from the flash memory and then
-		   added to the inode's i_rdev member.  */
-		u16 val;
-		jffs_read_data(f, (char *)&val, 0, 2);
-		init_special_inode(inode, inode->i_mode,
-			old_decode_dev(val));
-	}
-
-	D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
-	mutex_unlock(&c->fmc->biglock);
-}
-
-
-static void
-jffs_delete_inode(struct inode *inode)
-{
-	struct jffs_file *f;
-	struct jffs_control *c;
-	D3(printk("jffs_delete_inode(): inode->i_ino == %lu\n",
-		  inode->i_ino));
-
-	truncate_inode_pages(&inode->i_data, 0);
-	lock_kernel();
-	inode->i_size = 0;
-	inode->i_blocks = 0;
-	inode->i_private = NULL;
-	clear_inode(inode);
-	if (inode->i_nlink == 0) {
-		c = (struct jffs_control *) inode->i_sb->s_fs_info;
-		f = (struct jffs_file *) jffs_find_file (c, inode->i_ino);
-		jffs_possibly_delete_file(f);
-	}
-
-	unlock_kernel();
-}
-
-
-static void
-jffs_write_super(struct super_block *sb)
-{
-	struct jffs_control *c = (struct jffs_control *)sb->s_fs_info;
-	lock_kernel();
-	jffs_garbage_collect_trigger(c);
-	unlock_kernel();
-}
-
-static int jffs_remount(struct super_block *sb, int *flags, char *data)
-{
-	*flags |= MS_NODIRATIME;
-	return 0;
-}
-
-static struct super_operations jffs_ops =
-{
-	.read_inode	= jffs_read_inode,
-	.delete_inode 	= jffs_delete_inode,
-	.put_super	= jffs_put_super,
-	.write_super	= jffs_write_super,
-	.statfs		= jffs_statfs,
-	.remount_fs	= jffs_remount,
-};
-
-static int jffs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
-{
-	return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super,
-			   mnt);
-}
-
-static struct file_system_type jffs_fs_type = {
-	.owner		= THIS_MODULE,
-	.name		= "jffs",
-	.get_sb		= jffs_get_sb,
-	.kill_sb	= kill_block_super,
-	.fs_flags	= FS_REQUIRES_DEV,
-};
-
-static int __init
-init_jffs_fs(void)
-{
-	printk(KERN_INFO "JFFS version " JFFS_VERSION_STRING
-		", (C) 1999, 2000  Axis Communications AB\n");
-	
-#ifdef CONFIG_JFFS_PROC_FS
-	jffs_proc_root = proc_mkdir("jffs", proc_root_fs);
-	if (!jffs_proc_root) {
-		printk(KERN_WARNING "cannot create /proc/jffs entry\n");
-	}
-#endif
-	fm_cache = kmem_cache_create("jffs_fm", sizeof(struct jffs_fm),
-		       0,
-		       SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
-		       NULL, NULL);
-	if (!fm_cache) {
-		return -ENOMEM;
-	}
-
-	node_cache = kmem_cache_create("jffs_node",sizeof(struct jffs_node),
-		       0,
-		       SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
-		       NULL, NULL);
-	if (!node_cache) {
-		kmem_cache_destroy(fm_cache);
-		return -ENOMEM;
-	}
-
-	return register_filesystem(&jffs_fs_type);
-}
-
-static void __exit
-exit_jffs_fs(void)
-{
-	unregister_filesystem(&jffs_fs_type);
-	kmem_cache_destroy(fm_cache);
-	kmem_cache_destroy(node_cache);
-}
-
-module_init(init_jffs_fs)
-module_exit(exit_jffs_fs)
-
-MODULE_DESCRIPTION("The Journalling Flash File System");
-MODULE_AUTHOR("Axis Communications AB.");
-MODULE_LICENSE("GPL");
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
deleted file mode 100644
index 6dd1891..0000000
--- a/fs/jffs/intrep.c
+++ /dev/null
@@ -1,3449 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications, Inc.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This 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.
- *
- * $Id: intrep.c,v 1.102 2001/09/23 23:28:36 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-
-/* This file contains the code for the internal structure of the
-   Journaling Flash File System, JFFS.  */
-
-/*
- * Todo list:
- *
- * memcpy_to_flash() and memcpy_from_flash() functions.
- *
- * Implementation of hard links.
- *
- * Organize the source code in a better way. Against the VFS we could
- * have jffs_ext.c, and against the block device jffs_int.c.
- * A better file-internal organization too.
- *
- * A better checksum algorithm.
- *
- * Consider endianness stuff. ntohl() etc.
- *
- * Are we handling the atime, mtime, ctime members of the inode right?
- *
- * Remove some duplicated code. Take a look at jffs_write_node() and
- * jffs_rewrite_data() for instance.
- *
- * Implement more meaning of the nlink member in various data structures.
- * nlink could be used in conjunction with hard links for instance.
- *
- * Better memory management. Allocate data structures in larger chunks
- * if possible.
- *
- * If too much meta data is stored, a garbage collect should be issued.
- * We have experienced problems with too much meta data with for instance
- * log files.
- *
- * Improve the calls to jffs_ioctl(). We would like to retrieve more
- * information to be able to debug (or to supervise) JFFS during run-time.
- *
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/jffs.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/pagemap.h>
-#include <linux/mutex.h>
-#include <asm/byteorder.h>
-#include <linux/smp_lock.h>
-#include <linux/time.h>
-#include <linux/ctype.h>
-#include <linux/freezer.h>
-
-#include "intrep.h"
-#include "jffs_fm.h"
-
-long no_jffs_node = 0;
-static long no_jffs_file = 0;
-#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
-long no_jffs_control = 0;
-long no_jffs_raw_inode = 0;
-long no_jffs_node_ref = 0;
-long no_jffs_fm = 0;
-long no_jffs_fmcontrol = 0;
-long no_hash = 0;
-long no_name = 0;
-#endif
-
-static int jffs_scan_flash(struct jffs_control *c);
-static int jffs_update_file(struct jffs_file *f, struct jffs_node *node);
-static int jffs_build_file(struct jffs_file *f);
-static int jffs_free_file(struct jffs_file *f);
-static int jffs_free_node_list(struct jffs_file *f);
-static int jffs_garbage_collect_now(struct jffs_control *c);
-static int jffs_insert_file_into_hash(struct jffs_file *f);
-static int jffs_remove_redundant_nodes(struct jffs_file *f);
-
-/* Is there enough space on the flash?  */
-static inline int JFFS_ENOUGH_SPACE(struct jffs_control *c, __u32 space)
-{
-	struct jffs_fmcontrol *fmc = c->fmc;
-
-	while (1) {
-		if ((fmc->flash_size - (fmc->used_size + fmc->dirty_size))
-			>= fmc->min_free_size + space) {
-			return 1;
-		}
-		if (fmc->dirty_size < fmc->sector_size)
-			return 0;
-
-		if (jffs_garbage_collect_now(c)) {
-		  D1(printk("JFFS_ENOUGH_SPACE: jffs_garbage_collect_now() failed.\n"));
-		  return 0;
-		}
-	}
-}
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-static __u8
-flash_read_u8(struct mtd_info *mtd, loff_t from)
-{
-	size_t retlen;
-	__u8 ret;
-	int res;
-
-	res = MTD_READ(mtd, from, 1, &retlen, &ret);
-	if (retlen != 1) {
-		printk("Didn't read a byte in flash_read_u8(). Returned %d\n", res);
-		return 0;
-	}
-
-	return ret;
-}
-
-static void
-jffs_hexdump(struct mtd_info *mtd, loff_t pos, int size)
-{
-	char line[16];
-	int j = 0;
-
-	while (size > 0) {
-		int i;
-
-		printk("%ld:", (long) pos);
-		for (j = 0; j < 16; j++) {
-			line[j] = flash_read_u8(mtd, pos++);
-		}
-		for (i = 0; i < j; i++) {
-			if (!(i & 1)) {
-				printk(" %.2x", line[i] & 0xff);
-			}
-			else {
-				printk("%.2x", line[i] & 0xff);
-			}
-		}
-
-		/* Print empty space */
-		for (; i < 16; i++) {
-			if (!(i & 1)) {
-				printk("   ");
-			}
-			else {
-				printk("  ");
-			}
-		}
-		printk("  ");
-
-		for (i = 0; i < j; i++) {
-			if (isgraph(line[i])) {
-				printk("%c", line[i]);
-			}
-			else {
-				printk(".");
-			}
-		}
-		printk("\n");
-		size -= 16;
-	}
-}
-
-/* Print the contents of a node.  */
-static void
-jffs_print_node(struct jffs_node *n)
-{
-	D(printk("jffs_node: 0x%p\n", n));
-	D(printk("{\n"));
-	D(printk("        0x%08x, /* version  */\n", n->version));
-	D(printk("        0x%08x, /* data_offset  */\n", n->data_offset));
-	D(printk("        0x%08x, /* data_size  */\n", n->data_size));
-	D(printk("        0x%08x, /* removed_size  */\n", n->removed_size));
-	D(printk("        0x%08x, /* fm_offset  */\n", n->fm_offset));
-	D(printk("        0x%02x,       /* name_size  */\n", n->name_size));
-	D(printk("        0x%p, /* fm,  fm->offset: %u  */\n",
-		 n->fm, (n->fm ? n->fm->offset : 0)));
-	D(printk("        0x%p, /* version_prev  */\n", n->version_prev));
-	D(printk("        0x%p, /* version_next  */\n", n->version_next));
-	D(printk("        0x%p, /* range_prev  */\n", n->range_prev));
-	D(printk("        0x%p, /* range_next  */\n", n->range_next));
-	D(printk("}\n"));
-}
-
-#endif
-
-/* Print the contents of a raw inode.  */
-static void
-jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
-{
-	D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
-	D(printk("{\n"));
-	D(printk("        0x%08x, /* magic  */\n", raw_inode->magic));
-	D(printk("        0x%08x, /* ino  */\n", raw_inode->ino));
-	D(printk("        0x%08x, /* pino  */\n", raw_inode->pino));
-	D(printk("        0x%08x, /* version  */\n", raw_inode->version));
-	D(printk("        0x%08x, /* mode  */\n", raw_inode->mode));
-	D(printk("        0x%04x,     /* uid  */\n", raw_inode->uid));
-	D(printk("        0x%04x,     /* gid  */\n", raw_inode->gid));
-	D(printk("        0x%08x, /* atime  */\n", raw_inode->atime));
-	D(printk("        0x%08x, /* mtime  */\n", raw_inode->mtime));
-	D(printk("        0x%08x, /* ctime  */\n", raw_inode->ctime));
-	D(printk("        0x%08x, /* offset  */\n", raw_inode->offset));
-	D(printk("        0x%08x, /* dsize  */\n", raw_inode->dsize));
-	D(printk("        0x%08x, /* rsize  */\n", raw_inode->rsize));
-	D(printk("        0x%02x,       /* nsize  */\n", raw_inode->nsize));
-	D(printk("        0x%02x,       /* nlink  */\n", raw_inode->nlink));
-	D(printk("        0x%02x,       /* spare  */\n",
-		 raw_inode->spare));
-	D(printk("        %u,          /* rename  */\n",
-		 raw_inode->rename));
-	D(printk("        %u,          /* deleted  */\n",
-		 raw_inode->deleted));
-	D(printk("        0x%02x,       /* accurate  */\n",
-		 raw_inode->accurate));
-	D(printk("        0x%08x, /* dchksum  */\n", raw_inode->dchksum));
-	D(printk("        0x%04x,     /* nchksum  */\n", raw_inode->nchksum));
-	D(printk("        0x%04x,     /* chksum  */\n", raw_inode->chksum));
-	D(printk("}\n"));
-}
-
-#define flash_safe_acquire(arg)
-#define flash_safe_release(arg)
-
-
-static int
-flash_safe_read(struct mtd_info *mtd, loff_t from,
-		u_char *buf, size_t count)
-{
-	size_t retlen;
-	int res;
-
-	D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n",
-		  mtd, (unsigned int) from, buf, count));
-
-	res = mtd->read(mtd, from, count, &retlen, buf);
-	if (retlen != count) {
-		panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res);
-	}
-	return res?res:retlen;
-}
-
-
-static __u32
-flash_read_u32(struct mtd_info *mtd, loff_t from)
-{
-	size_t retlen;
-	__u32 ret;
-	int res;
-
-	res = mtd->read(mtd, from, 4, &retlen, (unsigned char *)&ret);
-	if (retlen != 4) {
-		printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res);
-		return 0;
-	}
-
-	return ret;
-}
-
-
-static int
-flash_safe_write(struct mtd_info *mtd, loff_t to,
-		 const u_char *buf, size_t count)
-{
-	size_t retlen;
-	int res;
-
-	D3(printk(KERN_NOTICE "flash_safe_write(%p, %08x, %p, %08x)\n",
-		  mtd, (unsigned int) to, buf, count));
-
-	res = mtd->write(mtd, to, count, &retlen, buf);
-	if (retlen != count) {
-		printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res);
-	}
-	return res?res:retlen;
-}
-
-
-static int
-flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs,
-			unsigned long iovec_cnt, loff_t to)
-{
-	size_t retlen, retlen_a;
-	int i;
-	int res;
-
-	D3(printk(KERN_NOTICE "flash_safe_writev(%p, %08x, %p)\n",
-		  mtd, (unsigned int) to, vecs));
-
-	if (mtd->writev) {
-		res = mtd->writev(mtd, vecs, iovec_cnt, to, &retlen);
-		return res ? res : retlen;
-	}
-	/* Not implemented writev. Repeatedly use write - on the not so
-	   unreasonable assumption that the mtd driver doesn't care how
-	   many write cycles we use. */
-	res=0;
-	retlen=0;
-
-	for (i=0; !res && i<iovec_cnt; i++) {
-		res = mtd->write(mtd, to, vecs[i].iov_len, &retlen_a,
-				 vecs[i].iov_base);
-		if (retlen_a != vecs[i].iov_len) {
-			printk("Didn't write all bytes in flash_safe_writev(). Returned %d\n", res);
-			if (i != iovec_cnt-1)
-				return -EIO;
-		}
-		/* If res is non-zero, retlen_a is undefined, but we don't
-		   care because in that case it's not going to be 
-		   returned anyway.
-		*/
-		to += retlen_a;
-		retlen += retlen_a;
-	}
-	return res?res:retlen;
-}
-
-
-static int
-flash_memset(struct mtd_info *mtd, loff_t to,
-	     const u_char c, size_t size)
-{
-	static unsigned char pattern[64];
-	int i;
-
-	/* fill up pattern */
-
-	for(i = 0; i < 64; i++)
-		pattern[i] = c;
-
-	/* write as many 64-byte chunks as we can */
-
-	while (size >= 64) {
-		flash_safe_write(mtd, to, pattern, 64);
-		size -= 64;
-		to += 64;
-	}
-
-	/* and the rest */
-
-	if(size)
-		flash_safe_write(mtd, to, pattern, size);
-
-	return size;
-}
-
-
-static void
-intrep_erase_callback(struct erase_info *done)
-{
-	wait_queue_head_t *wait_q;
-
-	wait_q = (wait_queue_head_t *)done->priv;
-
-	wake_up(wait_q);
-}
-
-
-static int
-flash_erase_region(struct mtd_info *mtd, loff_t start,
-		   size_t size)
-{
-	struct erase_info *erase;
-	DECLARE_WAITQUEUE(wait, current);
-	wait_queue_head_t wait_q;
-
-	erase = kmalloc(sizeof(struct erase_info), GFP_KERNEL);
-	if (!erase)
-		return -ENOMEM;
-
-	init_waitqueue_head(&wait_q);
-
-	erase->mtd = mtd;
-	erase->callback = intrep_erase_callback;
-	erase->addr = start;
-	erase->len = size;
-	erase->priv = (u_long)&wait_q;
-
-	/* FIXME: Use TASK_INTERRUPTIBLE and deal with being interrupted */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(&wait_q, &wait);
-
-	if (mtd->erase(mtd, erase) < 0) {
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&wait_q, &wait);
-		kfree(erase);
-
-		printk(KERN_WARNING "flash: erase of region [0x%lx, 0x%lx] "
-		       "totally failed\n", (long)start, (long)start + size);
-
-		return -1;
-	}
-
-	schedule(); /* Wait for flash to finish. */
-	remove_wait_queue(&wait_q, &wait);
-
-	kfree(erase);
-
-	return 0;
-}
-
-/* This routine calculates checksums in JFFS.  */
-static __u32
-jffs_checksum(const void *data, int size)
-{
-	__u32 sum = 0;
-	__u8 *ptr = (__u8 *)data;
-	while (size-- > 0) {
-		sum += *ptr++;
-	}
-	D3(printk(", result: 0x%08x\n", sum));
-	return sum;
-}
-
-
-static int
-jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size, __u32 *result)
-{
-	__u32 sum = 0;
-	loff_t ptr = start;
-	__u8 *read_buf;
-	int i, length;
-
-	/* Allocate read buffer */
-	read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
-	if (!read_buf) {
-		printk(KERN_NOTICE "kmalloc failed in jffs_checksum_flash()\n");
-		return -ENOMEM;
-	}
-	/* Loop until checksum done */
-	while (size) {
-		/* Get amount of data to read */
-		if (size < 4096)
-			length = size;
-		else
-			length = 4096;
-
-		/* Perform flash read */
-		D3(printk(KERN_NOTICE "jffs_checksum_flash\n"));
-		flash_safe_read(mtd, ptr, &read_buf[0], length);
-
-		/* Compute checksum */
-		for (i=0; i < length ; i++)
-			sum += read_buf[i];
-
-		/* Update pointer and size */
-		size -= length;
-		ptr += length;
-	}
-
-	/* Free read buffer */
-	kfree(read_buf);
-
-	/* Return result */
-	D3(printk("checksum result: 0x%08x\n", sum));
-	*result = sum;
-	return 0;
-}
-
-static __inline__ void jffs_fm_write_lock(struct jffs_fmcontrol *fmc)
-{
-  //	down(&fmc->wlock);
-}
-
-static __inline__ void jffs_fm_write_unlock(struct jffs_fmcontrol *fmc)
-{
-  //	up(&fmc->wlock);
-}
-
-
-/* Create and initialize a new struct jffs_file.  */
-static struct jffs_file *
-jffs_create_file(struct jffs_control *c,
-		 const struct jffs_raw_inode *raw_inode)
-{
-	struct jffs_file *f;
-
-	if (!(f = kzalloc(sizeof(*f), GFP_KERNEL))) {
-		D(printk("jffs_create_file(): Failed!\n"));
-		return NULL;
-	}
-	no_jffs_file++;
-	f->ino = raw_inode->ino;
-	f->pino = raw_inode->pino;
-	f->nlink = raw_inode->nlink;
-	f->deleted = raw_inode->deleted;
-	f->c = c;
-
-	return f;
-}
-
-
-/* Build a control block for the file system.  */
-static struct jffs_control *
-jffs_create_control(struct super_block *sb)
-{
-	struct jffs_control *c;
-	register int s = sizeof(struct jffs_control);
-	int i;
-	D(char *t = 0);
-
-	D2(printk("jffs_create_control()\n"));
-
-	if (!(c = kmalloc(s, GFP_KERNEL))) {
-		goto fail_control;
-	}
-	DJM(no_jffs_control++);
-	c->root = NULL;
-	c->gc_task = NULL;
-	c->hash_len = JFFS_HASH_SIZE;
-	s = sizeof(struct list_head) * c->hash_len;
-	if (!(c->hash = kmalloc(s, GFP_KERNEL))) {
-		goto fail_hash;
-	}
-	DJM(no_hash++);
-	for (i = 0; i < c->hash_len; i++)
-		INIT_LIST_HEAD(&c->hash[i]);
-	if (!(c->fmc = jffs_build_begin(c, MINOR(sb->s_dev)))) {
-		goto fail_fminit;
-	}
-	c->next_ino = JFFS_MIN_INO + 1;
-	c->delete_list = (struct jffs_delete_list *) 0;
-	return c;
-
-fail_fminit:
-	D(t = "c->fmc");
-fail_hash:
-	kfree(c);
-	DJM(no_jffs_control--);
-	D(t = t ? t : "c->hash");
-fail_control:
-	D(t = t ? t : "control");
-	D(printk("jffs_create_control(): Allocation failed: (%s)\n", t));
-	return (struct jffs_control *)0;
-}
-
-
-/* Clean up all data structures associated with the file system.  */
-void
-jffs_cleanup_control(struct jffs_control *c)
-{
-	D2(printk("jffs_cleanup_control()\n"));
-
-	if (!c) {
-		D(printk("jffs_cleanup_control(): c == NULL !!!\n"));
-		return;
-	}
-
-	while (c->delete_list) {
-		struct jffs_delete_list *delete_list_element;
-		delete_list_element = c->delete_list;
-		c->delete_list = c->delete_list->next;
-		kfree(delete_list_element);
-	}
-
-	/* Free all files and nodes.  */
-	if (c->hash) {
-		jffs_foreach_file(c, jffs_free_node_list);
-		jffs_foreach_file(c, jffs_free_file);
-		kfree(c->hash);
-		DJM(no_hash--);
-	}
-	jffs_cleanup_fmcontrol(c->fmc);
-	kfree(c);
-	DJM(no_jffs_control--);
-	D3(printk("jffs_cleanup_control(): Leaving...\n"));
-}
-
-
-/* This function adds a virtual root node to the in-RAM representation.
-   Called by jffs_build_fs().  */
-static int
-jffs_add_virtual_root(struct jffs_control *c)
-{
-	struct jffs_file *root;
-	struct jffs_node *node;
-
-	D2(printk("jffs_add_virtual_root(): "
-		  "Creating a virtual root directory.\n"));
-
-	if (!(root = kzalloc(sizeof(struct jffs_file), GFP_KERNEL))) {
-		return -ENOMEM;
-	}
-	no_jffs_file++;
-	if (!(node = jffs_alloc_node())) {
-		kfree(root);
-		no_jffs_file--;
-		return -ENOMEM;
-	}
-	DJM(no_jffs_node++);
-	memset(node, 0, sizeof(struct jffs_node));
-	node->ino = JFFS_MIN_INO;
-	root->ino = JFFS_MIN_INO;
-	root->mode = S_IFDIR | S_IRWXU | S_IRGRP
-		     | S_IXGRP | S_IROTH | S_IXOTH;
-	root->atime = root->mtime = root->ctime = get_seconds();
-	root->nlink = 1;
-	root->c = c;
-	root->version_head = root->version_tail = node;
-	jffs_insert_file_into_hash(root);
-	return 0;
-}
-
-
-/* This is where the file system is built and initialized.  */
-int
-jffs_build_fs(struct super_block *sb)
-{
-	struct jffs_control *c;
-	int err = 0;
-
-	D2(printk("jffs_build_fs()\n"));
-
-	if (!(c = jffs_create_control(sb))) {
-		return -ENOMEM;
-	}
-	c->building_fs = 1;
-	c->sb = sb;
-	if ((err = jffs_scan_flash(c)) < 0) {
-		if(err == -EAGAIN){
-			/* scan_flash() wants us to try once more. A flipping 
-			   bits sector was detect in the middle of the scan flash.
-			   Clean up old allocated memory before going in.
-			*/
-			D1(printk("jffs_build_fs: Cleaning up all control structures,"
-				  " reallocating them and trying mount again.\n"));
-			jffs_cleanup_control(c);
-			if (!(c = jffs_create_control(sb))) {
-				return -ENOMEM;
-			}
-			c->building_fs = 1;
-			c->sb = sb;
-
-			if ((err = jffs_scan_flash(c)) < 0) {
-				goto jffs_build_fs_fail;
-			}			
-		}else{
-			goto jffs_build_fs_fail;
-		}
-	}
-
-	/* Add a virtual root node if no one exists.  */
-	if (!jffs_find_file(c, JFFS_MIN_INO)) {
-		if ((err = jffs_add_virtual_root(c)) < 0) {
-			goto jffs_build_fs_fail;
-		}
-	}
-
-	while (c->delete_list) {
-		struct jffs_file *f;
-		struct jffs_delete_list *delete_list_element;
-
-		if ((f = jffs_find_file(c, c->delete_list->ino))) {
-			f->deleted = 1;
-		}
-		delete_list_element = c->delete_list;
-		c->delete_list = c->delete_list->next;
-		kfree(delete_list_element);
-	}
-
-	/* Remove deleted nodes.  */
-	if ((err = jffs_foreach_file(c, jffs_possibly_delete_file)) < 0) {
-		printk(KERN_ERR "JFFS: Failed to remove deleted nodes.\n");
-		goto jffs_build_fs_fail;
-	}
-	/* Remove redundant nodes.  (We are not interested in the
-	   return value in this case.)  */
-	jffs_foreach_file(c, jffs_remove_redundant_nodes);
-	/* Try to build a tree from all the nodes.  */
-	if ((err = jffs_foreach_file(c, jffs_insert_file_into_tree)) < 0) {
-		printk("JFFS: Failed to build tree.\n");
-		goto jffs_build_fs_fail;
-	}
-	/* Compute the sizes of all files in the filesystem.  Adjust if
-	   necessary.  */
-	if ((err = jffs_foreach_file(c, jffs_build_file)) < 0) {
-		printk("JFFS: Failed to build file system.\n");
-		goto jffs_build_fs_fail;
-	}
-	sb->s_fs_info = (void *)c;
-	c->building_fs = 0;
-
-	D1(jffs_print_hash_table(c));
-	D1(jffs_print_tree(c->root, 0));
-
-	return 0;
-
-jffs_build_fs_fail:
-	jffs_cleanup_control(c);
-	return err;
-} /* jffs_build_fs()  */
-
-
-/*
-  This checks for sectors that were being erased in their previous 
-  lifetimes and for some reason or the other (power fail etc.), 
-  the erase cycles never completed.
-  As the flash array would have reverted back to read status, 
-  these sectors are detected by the symptom of the "flipping bits",
-  i.e. bits being read back differently from the same location in
-  flash if read multiple times.
-  The only solution to this is to re-erase the entire
-  sector.
-  Unfortunately detecting "flipping bits" is not a simple exercise
-  as a bit may be read back at 1 or 0 depending on the alignment 
-  of the stars in the universe.
-  The level of confidence is in direct proportion to the number of 
-  scans done. By power fail testing I (Vipin) have been able to 
-  proove that reading twice is not enough.
-  Maybe 4 times? Change NUM_REREADS to a higher number if you want
-  a (even) higher degree of confidence in your mount process. 
-  A higher number would of course slow down your mount.
-*/
-static int check_partly_erased_sectors(struct jffs_fmcontrol *fmc){
-
-#define NUM_REREADS             4 /* see note above */
-#define READ_AHEAD_BYTES        4096 /* must be a multiple of 4, 
-					usually set to kernel page size */
-
-	__u8 *read_buf1;
-	__u8 *read_buf2;
-
-	int err = 0;
-	int retlen;
-	int i;
-	int cnt;
-	__u32 offset;
-	loff_t pos = 0;
-	loff_t end = fmc->flash_size;
-
-
-	/* Allocate read buffers */
-	read_buf1 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
-	if (!read_buf1)
-		return -ENOMEM;
-
-	read_buf2 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
-	if (!read_buf2) {
-		kfree(read_buf1);
-		return -ENOMEM;
-	}
-
- CHECK_NEXT:
-	while(pos < end){
-		
-		D1(printk("check_partly_erased_sector():checking sector which contains"
-			  " offset 0x%x for flipping bits..\n", (__u32)pos));
-		
-		retlen = flash_safe_read(fmc->mtd, pos,
-					 &read_buf1[0], READ_AHEAD_BYTES);
-		retlen &= ~3;
-		
-		for(cnt = 0; cnt < NUM_REREADS; cnt++){
-			(void)flash_safe_read(fmc->mtd, pos,
-					      &read_buf2[0], READ_AHEAD_BYTES);
-			
-			for (i=0 ; i < retlen ; i+=4) {
-				/* buffers MUST match, double word for word! */
-				if(*((__u32 *) &read_buf1[i]) !=
-				   *((__u32 *) &read_buf2[i])
-				   ){
-				        /* flipping bits detected, time to erase sector */
-					/* This will help us log some statistics etc. */
-					D1(printk("Flipping bits detected in re-read round:%i of %i\n",
-					       cnt, NUM_REREADS));
-					D1(printk("check_partly_erased_sectors:flipping bits detected"
-						  " @offset:0x%x(0x%x!=0x%x)\n",
-						  (__u32)pos+i, *((__u32 *) &read_buf1[i]), 
-						  *((__u32 *) &read_buf2[i])));
-					
-				        /* calculate start of present sector */
-					offset = (((__u32)pos+i)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size;
-					
-					D1(printk("check_partly_erased_sector():erasing sector starting 0x%x.\n",
-						  offset));
-					
-					if (flash_erase_region(fmc->mtd,
-							       offset, fmc->sector_size) < 0) {
-						printk(KERN_ERR "JFFS: Erase of flash failed. "
-						       "offset = %u, erase_size = %d\n",
-						       offset , fmc->sector_size);
-						
-						err = -EIO;
-						goto returnBack;
-
-					}else{
-						D1(printk("JFFS: Erase of flash sector @0x%x successful.\n",
-						       offset));
-						/* skip ahead to the next sector */
-						pos = (((__u32)pos+i)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size;
-						pos += fmc->sector_size;
-						goto CHECK_NEXT;
-					}
-				}
-			}
-		}
-		pos += READ_AHEAD_BYTES;
-	}
-
- returnBack:
-	kfree(read_buf1);
-	kfree(read_buf2);
-
-	D2(printk("check_partly_erased_sector():Done checking all sectors till offset 0x%x for flipping bits.\n",
-		  (__u32)pos));
-
-	return err;
-
-}/* end check_partly_erased_sectors() */
-
-
-
-/* Scan the whole flash memory in order to find all nodes in the
-   file systems.  */
-static int
-jffs_scan_flash(struct jffs_control *c)
-{
-	char name[JFFS_MAX_NAME_LEN + 2];
-	struct jffs_raw_inode raw_inode;
-	struct jffs_node *node = NULL;
-	struct jffs_fmcontrol *fmc = c->fmc;
-	__u32 checksum;
-	__u8 tmp_accurate;
-	__u16 tmp_chksum;
-	__u32 deleted_file;
-	loff_t pos = 0;
-	loff_t start;
-	loff_t test_start;
-	loff_t end = fmc->flash_size;
-	__u8 *read_buf;
-	int i, len, retlen;
-	__u32 offset;
-
-	__u32 free_chunk_size1;
-	__u32 free_chunk_size2;
-
-	
-#define NUMFREEALLOWED     2        /* 2 chunks of at least erase size space allowed */
-	int num_free_space = 0;       /* Flag err if more than TWO
-				       free blocks found. This is NOT allowed
-				       by the current jffs design.
-				    */
-	int num_free_spc_not_accp = 0; /* For debugging purposed keep count 
-					of how much free space was rejected and
-					marked dirty
-				     */
-
-	D1(printk("jffs_scan_flash(): start pos = 0x%lx, end = 0x%lx\n",
-		  (long)pos, (long)end));
-
-	flash_safe_acquire(fmc->mtd);
-
-	/*
-	  check and make sure that any sector does not suffer
-	  from the "partly erased, bit flipping syndrome" (TM Vipin :)
-	  If so, offending sectors will be erased.
-	*/
-	if(check_partly_erased_sectors(fmc) < 0){
-
-		flash_safe_release(fmc->mtd);
-		return -EIO; /* bad, bad, bad error. Cannot continue.*/
-	}
-
-	/* Allocate read buffer */
-	read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
-	if (!read_buf) {
-		flash_safe_release(fmc->mtd);
-		return -ENOMEM;
-	}
-			      
-	/* Start the scan.  */
-	while (pos < end) {
-		deleted_file = 0;
-
-		/* Remember the position from where we started this scan.  */
-		start = pos;
-
-		switch (flash_read_u32(fmc->mtd, pos)) {
-		case JFFS_EMPTY_BITMASK:
-			/* We have found 0xffffffff at this position.  We have to
-			   scan the rest of the flash till the end or till
-			   something else than 0xffffffff is found.
-		           Keep going till we do not find JFFS_EMPTY_BITMASK 
-			   anymore */
-
-			D1(printk("jffs_scan_flash(): 0xffffffff at pos 0x%lx.\n",
-				  (long)pos));
-
-		        while(pos < end){
-
-			      len = end - pos < 4096 ? end - pos : 4096;
-			      
-			      retlen = flash_safe_read(fmc->mtd, pos,
-						 &read_buf[0], len);
-
-			      retlen &= ~3;
-			      
-			      for (i=0 ; i < retlen ; i+=4, pos += 4) {
-				      if(*((__u32 *) &read_buf[i]) !=
-					 JFFS_EMPTY_BITMASK)
-					break;
-			      }
-			      if (i == retlen)
-				    continue;
-			      else
-				    break;
-			}
-
-			D1(printk("jffs_scan_flash():0xffffffff ended at pos 0x%lx.\n",
-				  (long)pos));
-			
-			/* If some free space ends in the middle of a sector,
-			   treat it as dirty rather than clean.
-			   This is to handle the case where one thread 
-			   allocated space for a node, but didn't get to
-			   actually _write_ it before power was lost, leaving
-			   a gap in the log. Shifting all node writes into
-			   a single kernel thread will fix the original problem.
-			*/
-			if ((__u32) pos % fmc->sector_size) {
-				/* If there was free space in previous 
-				   sectors, don't mark that dirty too - 
-				   only from the beginning of this sector
-				   (or from start) 
-				*/
-
-			        test_start = pos & ~(fmc->sector_size-1); /* end of last sector */
-
-				if (start < test_start) {
-
-				        /* free space started in the previous sector! */
-
-					if((num_free_space < NUMFREEALLOWED) && 
-					   ((unsigned int)(test_start - start) >= fmc->sector_size)){
-
-				                /*
-						  Count it in if we are still under NUMFREEALLOWED *and* it is 
-						  at least 1 erase sector in length. This will keep us from 
-						  picking any little ole' space as "free".
-						*/
-					  
-					        D1(printk("Reducing end of free space to 0x%x from 0x%x\n",
-							  (unsigned int)test_start, (unsigned int)pos));
-
-						D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
-							  (unsigned int) start,
-							  (unsigned int)(test_start - start)));
-
-						/* below, space from "start" to "pos" will be marked dirty. */
-						start = test_start; 
-						
-						/* Being in here means that we have found at least an entire 
-						   erase sector size of free space ending on a sector boundary.
-						   Keep track of free spaces accepted.
-						*/
-						num_free_space++;
-					}else{
-					        num_free_spc_not_accp++;
-					        D1(printk("Free space (#%i) found but *Not* accepted: Starting"
-							  " 0x%x for 0x%x bytes\n",
-							  num_free_spc_not_accp, (unsigned int)start, 
-							  (unsigned int)((unsigned int)(pos & ~(fmc->sector_size-1)) - (unsigned int)start)));
-					        
-					}
-					
-				}
-				if((((__u32)(pos - start)) != 0)){
-
-				        D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n",
-						  (unsigned int) start, (unsigned int) (pos - start)));
-					jffs_fmalloced(fmc, (__u32) start,
-						       (__u32) (pos - start), NULL);
-				}else{
-					/* "Flipping bits" detected. This means that our scan for them
-					   did not catch this offset. See check_partly_erased_sectors() for
-					   more info.
-					*/
-				        
-					D1(printk("jffs_scan_flash():wants to allocate dirty flash "
-						  "space for 0 bytes.\n"));
-					D1(printk("jffs_scan_flash(): Flipping bits! We will free "
-						  "all allocated memory, erase this sector and remount\n"));
-
-					/* calculate start of present sector */
-					offset = (((__u32)pos)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size;
-					
-					D1(printk("jffs_scan_flash():erasing sector starting 0x%x.\n",
-						  offset));
-					
-					if (flash_erase_region(fmc->mtd,
-							       offset, fmc->sector_size) < 0) {
-						printk(KERN_ERR "JFFS: Erase of flash failed. "
-						       "offset = %u, erase_size = %d\n",
-						       offset , fmc->sector_size);
-
-						flash_safe_release(fmc->mtd);
-						kfree(read_buf);
-						return -1; /* bad, bad, bad! */
-
-					}
-					flash_safe_release(fmc->mtd);
-					kfree(read_buf);
-
-					return -EAGAIN; /* erased offending sector. Try mount one more time please. */
-				}
-			}else{
-			        /* Being in here means that we have found free space that ends on an erase sector
-				   boundary.
-				   Count it in if we are still under NUMFREEALLOWED *and* it is at least 1 erase 
-				   sector in length. This will keep us from picking any little ole' space as "free".
-				 */
-			         if((num_free_space < NUMFREEALLOWED) && 
-				    ((unsigned int)(pos - start) >= fmc->sector_size)){
-				           /* We really don't do anything to mark space as free, except *not* 
-					      mark it dirty and just advance the "pos" location pointer. 
-					      It will automatically be picked up as free space.
-					    */ 
-				           num_free_space++;
-				           D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
-						     (unsigned int) start, (unsigned int) (pos - start)));
-				 }else{
-				         num_free_spc_not_accp++;
-					 D1(printk("Free space (#%i) found but *Not* accepted: Starting "
-						   "0x%x for 0x%x bytes\n", num_free_spc_not_accp, 
-						   (unsigned int) start, 
-						   (unsigned int) (pos - start)));
-					 
-					 /* Mark this space as dirty. We already have our free space. */
-					 D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n",
-						   (unsigned int) start, (unsigned int) (pos - start)));
-					 jffs_fmalloced(fmc, (__u32) start,
-							(__u32) (pos - start), NULL);				           
-				 }
-				 
-			}
-			if(num_free_space > NUMFREEALLOWED){
-			         printk(KERN_WARNING "jffs_scan_flash(): Found free space "
-					"number %i. Only %i free space is allowed.\n",
-					num_free_space, NUMFREEALLOWED);			      
-			}
-			continue;
-
-		case JFFS_DIRTY_BITMASK:
-			/* We have found 0x00000000 at this position.  Scan as far
-			   as possible to find out how much is dirty.  */
-			D1(printk("jffs_scan_flash(): 0x00000000 at pos 0x%lx.\n",
-				  (long)pos));
-			for (; pos < end
-			       && JFFS_DIRTY_BITMASK == flash_read_u32(fmc->mtd, pos);
-			     pos += 4);
-			D1(printk("jffs_scan_flash(): 0x00 ended at "
-				  "pos 0x%lx.\n", (long)pos));
-			jffs_fmalloced(fmc, (__u32) start,
-				       (__u32) (pos - start), NULL);
-			continue;
-
-		case JFFS_MAGIC_BITMASK:
-			/* We have probably found a new raw inode.  */
-			break;
-
-		default:
-		bad_inode:
-			/* We're f*cked.  This is not solved yet.  We have
-			   to scan for the magic pattern.  */
-			D1(printk("*************** Dirty flash memory or "
-				  "bad inode: "
-				  "hexdump(pos = 0x%lx, len = 128):\n",
-				  (long)pos));
-			D1(jffs_hexdump(fmc->mtd, pos, 128));
-
-			for (pos += 4; pos < end; pos += 4) {
-				switch (flash_read_u32(fmc->mtd, pos)) {
-				case JFFS_MAGIC_BITMASK:
-				case JFFS_EMPTY_BITMASK:
-					/* handle these in the main switch() loop */
-					goto cont_scan;
-
-				default:
-					break;
-				}
-			}
-
-			cont_scan:
-			/* First, mark as dirty the region
-			   which really does contain crap. */
-			jffs_fmalloced(fmc, (__u32) start,
-				       (__u32) (pos - start),
-				       NULL);
-			
-			continue;
-		}/* switch */
-
-		/* We have found the beginning of an inode.  Create a
-		   node for it unless there already is one available.  */
-		if (!node) {
-			if (!(node = jffs_alloc_node())) {
-				/* Free read buffer */
-				kfree(read_buf);
-
-				/* Release the flash device */
-				flash_safe_release(fmc->mtd);
-	
-				return -ENOMEM;
-			}
-			DJM(no_jffs_node++);
-		}
-
-		/* Read the next raw inode.  */
-
-		flash_safe_read(fmc->mtd, pos, (u_char *) &raw_inode,
-				sizeof(struct jffs_raw_inode));
-
-		/* When we compute the checksum for the inode, we never
-		   count the 'accurate' or the 'checksum' fields.  */
-		tmp_accurate = raw_inode.accurate;
-		tmp_chksum = raw_inode.chksum;
-		raw_inode.accurate = 0;
-		raw_inode.chksum = 0;
-		checksum = jffs_checksum(&raw_inode,
-					 sizeof(struct jffs_raw_inode));
-		raw_inode.accurate = tmp_accurate;
-		raw_inode.chksum = tmp_chksum;
-
-		D3(printk("*** We have found this raw inode at pos 0x%lx "
-			  "on the flash:\n", (long)pos));
-		D3(jffs_print_raw_inode(&raw_inode));
-
-		if (checksum != raw_inode.chksum) {
-			D1(printk("jffs_scan_flash(): Bad checksum: "
-				  "checksum = %u, "
-				  "raw_inode.chksum = %u\n",
-				  checksum, raw_inode.chksum));
-			pos += sizeof(struct jffs_raw_inode);
-			jffs_fmalloced(fmc, (__u32) start,
-				       (__u32) (pos - start), NULL);
-			/* Reuse this unused struct jffs_node.  */
-			continue;
-		}
-
-		/* Check the raw inode read so far.  Start with the
-		   maximum length of the filename.  */
-		if (raw_inode.nsize > JFFS_MAX_NAME_LEN) {
-			printk(KERN_WARNING "jffs_scan_flash: Found a "
-			       "JFFS node with name too large\n");
-			goto bad_inode;
-		}
-
-		if (raw_inode.rename && raw_inode.dsize != sizeof(__u32)) {
-			printk(KERN_WARNING "jffs_scan_flash: Found a "
-			       "rename node with dsize %u.\n",
-			       raw_inode.dsize);
-			jffs_print_raw_inode(&raw_inode);
-			goto bad_inode;
-		}
-
-		/* The node's data segment should not exceed a
-		   certain length.  */
-		if (raw_inode.dsize > fmc->max_chunk_size) {
-			printk(KERN_WARNING "jffs_scan_flash: Found a "
-			       "JFFS node with dsize (0x%x) > max_chunk_size (0x%x)\n",
-			       raw_inode.dsize, fmc->max_chunk_size);
-			goto bad_inode;
-		}
-
-		pos += sizeof(struct jffs_raw_inode);
-
-		/* This shouldn't be necessary because a node that
-		   violates the flash boundaries shouldn't be written
-		   in the first place. */
-		if (pos >= end) {
-			goto check_node;
-		}
-
-		/* Read the name.  */
-		*name = 0;
-		if (raw_inode.nsize) {
-		        flash_safe_read(fmc->mtd, pos, name, raw_inode.nsize);
-			name[raw_inode.nsize] = '\0';
-			pos += raw_inode.nsize
-			       + JFFS_GET_PAD_BYTES(raw_inode.nsize);
-			D3(printk("name == \"%s\"\n", name));
-			checksum = jffs_checksum(name, raw_inode.nsize);
-			if (checksum != raw_inode.nchksum) {
-				D1(printk("jffs_scan_flash(): Bad checksum: "
-					  "checksum = %u, "
-					  "raw_inode.nchksum = %u\n",
-					  checksum, raw_inode.nchksum));
-				jffs_fmalloced(fmc, (__u32) start,
-					       (__u32) (pos - start), NULL);
-				/* Reuse this unused struct jffs_node.  */
-				continue;
-			}
-			if (pos >= end) {
-				goto check_node;
-			}
-		}
-
-		/* Read the data, if it exists, in order to be sure it
-		   matches the checksum.  */
-		if (raw_inode.dsize) {
-			if (raw_inode.rename) {
-				deleted_file = flash_read_u32(fmc->mtd, pos);
-			}
-			if (jffs_checksum_flash(fmc->mtd, pos, raw_inode.dsize, &checksum)) {
-				printk("jffs_checksum_flash() failed to calculate a checksum\n");
-				jffs_fmalloced(fmc, (__u32) start,
-					       (__u32) (pos - start), NULL);
-				/* Reuse this unused struct jffs_node.  */
-				continue;
-			}				
-			pos += raw_inode.dsize
-			       + JFFS_GET_PAD_BYTES(raw_inode.dsize);
-
-			if (checksum != raw_inode.dchksum) {
-				D1(printk("jffs_scan_flash(): Bad checksum: "
-					  "checksum = %u, "
-					  "raw_inode.dchksum = %u\n",
-					  checksum, raw_inode.dchksum));
-				jffs_fmalloced(fmc, (__u32) start,
-					       (__u32) (pos - start), NULL);
-				/* Reuse this unused struct jffs_node.  */
-				continue;
-			}
-		}
-
-		check_node:
-
-		/* Remember the highest inode number in the whole file
-		   system.  This information will be used when assigning
-		   new files new inode numbers.  */
-		if (c->next_ino <= raw_inode.ino) {
-			c->next_ino = raw_inode.ino + 1;
-		}
-
-		if (raw_inode.accurate) {
-			int err;
-			node->data_offset = raw_inode.offset;
-			node->data_size = raw_inode.dsize;
-			node->removed_size = raw_inode.rsize;
-			/* Compute the offset to the actual data in the
-			   on-flash node.  */
-			node->fm_offset
-			= sizeof(struct jffs_raw_inode)
-			  + raw_inode.nsize
-			  + JFFS_GET_PAD_BYTES(raw_inode.nsize);
-			node->fm = jffs_fmalloced(fmc, (__u32) start,
-						  (__u32) (pos - start),
-						  node);
-			if (!node->fm) {
-				D(printk("jffs_scan_flash(): !node->fm\n"));
-				jffs_free_node(node);
-				DJM(no_jffs_node--);
-
-				/* Free read buffer */
-				kfree(read_buf);
-
-				/* Release the flash device */
-				flash_safe_release(fmc->mtd);
-
-				return -ENOMEM;
-			}
-			if ((err = jffs_insert_node(c, NULL, &raw_inode,
-						    name, node)) < 0) {
-				printk("JFFS: Failed to handle raw inode. "
-				       "(err = %d)\n", err);
-				break;
-			}
-			if (raw_inode.rename) {
-				struct jffs_delete_list *dl
-				= (struct jffs_delete_list *)
-				  kmalloc(sizeof(struct jffs_delete_list),
-					  GFP_KERNEL);
-				if (!dl) {
-					D(printk("jffs_scan_flash: !dl\n"));
-					jffs_free_node(node);
-					DJM(no_jffs_node--);
-
-					/* Release the flash device */
-					flash_safe_release(fmc->flash_part);
-
-					/* Free read buffer */
-					kfree(read_buf);
-
-					return -ENOMEM;
-				}
-				dl->ino = deleted_file;
-				dl->next = c->delete_list;
-				c->delete_list = dl;
-				node->data_size = 0;
-			}
-			D3(jffs_print_node(node));
-			node = NULL; /* Don't free the node!  */
-		}
-		else {
-			jffs_fmalloced(fmc, (__u32) start,
-				       (__u32) (pos - start), NULL);
-			D3(printk("jffs_scan_flash(): Just found an obsolete "
-				  "raw_inode. Continuing the scan...\n"));
-			/* Reuse this unused struct jffs_node.  */
-		}
-	}
-
-	if (node) {
-		jffs_free_node(node);
-		DJM(no_jffs_node--);
-	}
-	jffs_build_end(fmc);
-
-	/* Free read buffer */
-	kfree(read_buf);
-
-	if(!num_free_space){
-	        printk(KERN_WARNING "jffs_scan_flash(): Did not find even a single "
-		       "chunk of free space. This is BAD!\n");
-	}
-
-	/* Return happy */
-	D3(printk("jffs_scan_flash(): Leaving...\n"));
-	flash_safe_release(fmc->mtd);
-
-	/* This is to trap the "free size accounting screwed error. */
-	free_chunk_size1 = jffs_free_size1(fmc);
-	free_chunk_size2 = jffs_free_size2(fmc);
-
-	if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) {
-
-		printk(KERN_WARNING "jffs_scan_falsh():Free size accounting screwed\n");
-		printk(KERN_WARNING "jfffs_scan_flash():free_chunk_size1 == 0x%x, "
-		       "free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", 
-		       free_chunk_size1, free_chunk_size2, fmc->free_size);
-
-		return -1; /* Do NOT mount f/s so that we can inspect what happened.
-			      Mounting this  screwed up f/s will screw us up anyway.
-			    */
-	}	
-
-	return 0; /* as far as we are concerned, we are happy! */
-} /* jffs_scan_flash()  */
-
-
-/* Insert any kind of node into the file system.  Take care of data
-   insertions and deletions.  Also remove redundant information. The
-   memory allocated for the `name' is regarded as "given away" in the
-   caller's perspective.  */
-int
-jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
-		 const struct jffs_raw_inode *raw_inode,
-		 const char *name, struct jffs_node *node)
-{
-	int update_name = 0;
-	int insert_into_tree = 0;
-
-	D2(printk("jffs_insert_node(): ino = %u, version = %u, "
-		  "name = \"%s\", deleted = %d\n",
-		  raw_inode->ino, raw_inode->version,
-		  ((name && *name) ? name : ""), raw_inode->deleted));
-
-	/* If there doesn't exist an associated jffs_file, then
-	   create, initialize and insert one into the file system.  */
-	if (!f && !(f = jffs_find_file(c, raw_inode->ino))) {
-		if (!(f = jffs_create_file(c, raw_inode))) {
-			return -ENOMEM;
-		}
-		jffs_insert_file_into_hash(f);
-		insert_into_tree = 1;
-	}
-	node->ino = raw_inode->ino;
-	node->version = raw_inode->version;
-	node->data_size = raw_inode->dsize;
-	node->fm_offset = sizeof(struct jffs_raw_inode) + raw_inode->nsize
-			  + JFFS_GET_PAD_BYTES(raw_inode->nsize);
-	node->name_size = raw_inode->nsize;
-
-	/* Now insert the node at the correct position into the file's
-	   version list.  */
-	if (!f->version_head) {
-		/* This is the first node.  */
-		f->version_head = node;
-		f->version_tail = node;
-		node->version_prev = NULL;
-		node->version_next = NULL;
-		f->highest_version = node->version;
-		update_name = 1;
-		f->mode = raw_inode->mode;
-		f->uid = raw_inode->uid;
-		f->gid = raw_inode->gid;
-		f->atime = raw_inode->atime;
-		f->mtime = raw_inode->mtime;
-		f->ctime = raw_inode->ctime;
-	}
-	else if ((f->highest_version < node->version)
-		 || (node->version == 0)) {
-		/* Insert at the end of the list.  I.e. this node is the
-		   newest one so far.  */
-		node->version_prev = f->version_tail;
-		node->version_next = NULL;
-		f->version_tail->version_next = node;
-		f->version_tail = node;
-		f->highest_version = node->version;
-		update_name = 1;
-		f->pino = raw_inode->pino;
-		f->mode = raw_inode->mode;
-		f->uid = raw_inode->uid;
-		f->gid = raw_inode->gid;
-		f->atime = raw_inode->atime;
-		f->mtime = raw_inode->mtime;
-		f->ctime = raw_inode->ctime;
-	}
-	else if (f->version_head->version > node->version) {
-		/* Insert at the bottom of the list.  */
-		node->version_prev = NULL;
-		node->version_next = f->version_head;
-		f->version_head->version_prev = node;
-		f->version_head = node;
-		if (!f->name) {
-			update_name = 1;
-		}
-	}
-	else {
-		struct jffs_node *n;
-		int newer_name = 0;
-		/* Search for the insertion position starting from
-		   the tail (newest node).  */
-		for (n = f->version_tail; n; n = n->version_prev) {
-			if (n->version < node->version) {
-				node->version_prev = n;
-				node->version_next = n->version_next;
-				node->version_next->version_prev = node;
-				n->version_next = node;
-				if (!newer_name) {
-					update_name = 1;
-				}
-				break;
-			}
-			if (n->name_size) {
-				newer_name = 1;
-			}
-		}
-	}
-
-	/* Deletion is irreversible. If any 'deleted' node is ever
-	   written, the file is deleted */
-	if (raw_inode->deleted)
-		f->deleted = raw_inode->deleted;
-
-	/* Perhaps update the name.  */
-	if (raw_inode->nsize && update_name && name && *name && (name != f->name)) {
-		if (f->name) {
-			kfree(f->name);
-			DJM(no_name--);
-		}
-		if (!(f->name = kmalloc(raw_inode->nsize + 1,
-						 GFP_KERNEL))) {
-			return -ENOMEM;
-		}
-		DJM(no_name++);
-		memcpy(f->name, name, raw_inode->nsize);
-		f->name[raw_inode->nsize] = '\0';
-		f->nsize = raw_inode->nsize;
-		D3(printk("jffs_insert_node(): Updated the name of "
-			  "the file to \"%s\".\n", name));
-	}
-
-	if (!c->building_fs) {
-		D3(printk("jffs_insert_node(): ---------------------------"
-			  "------------------------------------------- 1\n"));
-		if (insert_into_tree) {
-			jffs_insert_file_into_tree(f);
-		}
-		/* Once upon a time, we would call jffs_possibly_delete_file()
-		   here. That causes an oops if someone's still got the file
-		   open, so now we only do it in jffs_delete_inode()
-		   -- dwmw2
-		*/
-		if (node->data_size || node->removed_size) {
-			jffs_update_file(f, node);
-		}
-		jffs_remove_redundant_nodes(f);
-
-		jffs_garbage_collect_trigger(c);
-
-		D3(printk("jffs_insert_node(): ---------------------------"
-			  "------------------------------------------- 2\n"));
-	}
-
-	return 0;
-} /* jffs_insert_node()  */
-
-
-/* Unlink a jffs_node from the version list it is in.  */
-static inline void
-jffs_unlink_node_from_version_list(struct jffs_file *f,
-				   struct jffs_node *node)
-{
-	if (node->version_prev) {
-		node->version_prev->version_next = node->version_next;
-	} else {
-		f->version_head = node->version_next;
-	}
-	if (node->version_next) {
-		node->version_next->version_prev = node->version_prev;
-	} else {
-		f->version_tail = node->version_prev;
-	}
-}
-
-
-/* Unlink a jffs_node from the range list it is in.  */
-static inline void
-jffs_unlink_node_from_range_list(struct jffs_file *f, struct jffs_node *node)
-{
-	if (node->range_prev) {
-		node->range_prev->range_next = node->range_next;
-	}
-	else {
-		f->range_head = node->range_next;
-	}
-	if (node->range_next) {
-		node->range_next->range_prev = node->range_prev;
-	}
-	else {
-		f->range_tail = node->range_prev;
-	}
-}
-
-
-/* Function used by jffs_remove_redundant_nodes() below.  This function
-   classifies what kind of information a node adds to a file.  */
-static inline __u8
-jffs_classify_node(struct jffs_node *node)
-{
-	__u8 mod_type = JFFS_MODIFY_INODE;
-
-	if (node->name_size) {
-		mod_type |= JFFS_MODIFY_NAME;
-	}
-	if (node->data_size || node->removed_size) {
-		mod_type |= JFFS_MODIFY_DATA;
-	}
-	return mod_type;
-}
-
-
-/* Remove redundant nodes from a file.  Mark the on-flash memory
-   as dirty.  */
-static int
-jffs_remove_redundant_nodes(struct jffs_file *f)
-{
-	struct jffs_node *newest_node;
-	struct jffs_node *cur;
-	struct jffs_node *prev;
-	__u8 newest_type;
-	__u8 mod_type;
-	__u8 node_with_name_later = 0;
-
-	if (!(newest_node = f->version_tail)) {
-		return 0;
-	}
-
-	/* What does the `newest_node' modify?  */
-	newest_type = jffs_classify_node(newest_node);
-	node_with_name_later = newest_type & JFFS_MODIFY_NAME;
-
-	D3(printk("jffs_remove_redundant_nodes(): ino: %u, name: \"%s\", "
-		  "newest_type: %u\n", f->ino, (f->name ? f->name : ""),
-		  newest_type));
-
-	/* Traverse the file's nodes and determine which of them that are
-	   superfluous.  Yeah, this might look very complex at first
-	   glance but it is actually very simple.  */
-	for (cur = newest_node->version_prev; cur; cur = prev) {
-		prev = cur->version_prev;
-		mod_type = jffs_classify_node(cur);
-		if ((mod_type <= JFFS_MODIFY_INODE)
-		    || ((newest_type & JFFS_MODIFY_NAME)
-			&& (mod_type
-			    <= (JFFS_MODIFY_INODE + JFFS_MODIFY_NAME)))
-		    || (cur->data_size == 0 && cur->removed_size
-			&& !cur->version_prev && node_with_name_later)) {
-			/* Yes, this node is redundant. Remove it.  */
-			D2(printk("jffs_remove_redundant_nodes(): "
-				  "Removing node: ino: %u, version: %u, "
-				  "mod_type: %u\n", cur->ino, cur->version,
-				  mod_type));
-			jffs_unlink_node_from_version_list(f, cur);
-			jffs_fmfree(f->c->fmc, cur->fm, cur);
-			jffs_free_node(cur);
-			DJM(no_jffs_node--);
-		}
-		else {
-			node_with_name_later |= (mod_type & JFFS_MODIFY_NAME);
-		}
-	}
-
-	return 0;
-}
-
-
-/* Insert a file into the hash table.  */
-static int
-jffs_insert_file_into_hash(struct jffs_file *f)
-{
-	int i = f->ino % f->c->hash_len;
-
-	D3(printk("jffs_insert_file_into_hash(): f->ino: %u\n", f->ino));
-
-	list_add(&f->hash, &f->c->hash[i]);
-	return 0;
-}
-
-
-/* Insert a file into the file system tree.  */
-int
-jffs_insert_file_into_tree(struct jffs_file *f)
-{
-	struct jffs_file *parent;
-
-	D3(printk("jffs_insert_file_into_tree(): name: \"%s\"\n",
-		  (f->name ? f->name : "")));
-
-	if (!(parent = jffs_find_file(f->c, f->pino))) {
-		if (f->pino == 0) {
-			f->c->root = f;
-			f->parent = NULL;
-			f->sibling_prev = NULL;
-			f->sibling_next = NULL;
-			return 0;
-		}
-		else {
-			D1(printk("jffs_insert_file_into_tree(): Found "
-				  "inode with no parent and pino == %u\n",
-				  f->pino));
-			return -1;
-		}
-	}
-	f->parent = parent;
-	f->sibling_next = parent->children;
-	if (f->sibling_next) {
-		f->sibling_next->sibling_prev = f;
-	}
-	f->sibling_prev = NULL;
-	parent->children = f;
-	return 0;
-}
-
-
-/* Remove a file from the hash table.  */
-static int
-jffs_unlink_file_from_hash(struct jffs_file *f)
-{
-	D3(printk("jffs_unlink_file_from_hash(): f: 0x%p, "
-		  "ino %u\n", f, f->ino));
-
-	list_del(&f->hash);
-	return 0;
-}
-
-
-/* Just remove the file from the parent's children.  Don't free
-   any memory.  */
-int
-jffs_unlink_file_from_tree(struct jffs_file *f)
-{
-	D3(printk("jffs_unlink_file_from_tree(): ino: %d, pino: %d, name: "
-		  "\"%s\"\n", f->ino, f->pino, (f->name ? f->name : "")));
-
-	if (f->sibling_prev) {
-		f->sibling_prev->sibling_next = f->sibling_next;
-	}
-	else if (f->parent) {
-	        D3(printk("f->parent=%p\n", f->parent));
-		f->parent->children = f->sibling_next;
-	}
-	if (f->sibling_next) {
-		f->sibling_next->sibling_prev = f->sibling_prev;
-	}
-	return 0;
-}
-
-
-/* Find a file with its inode number.  */
-struct jffs_file *
-jffs_find_file(struct jffs_control *c, __u32 ino)
-{
-	struct jffs_file *f;
-	int i = ino % c->hash_len;
-
-	D3(printk("jffs_find_file(): ino: %u\n", ino));
-
-	list_for_each_entry(f, &c->hash[i], hash) {
-		if (ino != f->ino)
-			continue;
-		D3(printk("jffs_find_file(): Found file with ino "
-			       "%u. (name: \"%s\")\n",
-			       ino, (f->name ? f->name : ""));
-		);
-		return f;
-	}
-	D3(printk("jffs_find_file(): Didn't find file "
-			 "with ino %u.\n", ino);
-	);
-	return NULL;
-}
-
-
-/* Find a file in a directory.  We are comparing the names.  */
-struct jffs_file *
-jffs_find_child(struct jffs_file *dir, const char *name, int len)
-{
-	struct jffs_file *f;
-
-	D3(printk("jffs_find_child()\n"));
-
-	for (f = dir->children; f; f = f->sibling_next) {
-		if (!f->deleted && f->name
-		    && !strncmp(f->name, name, len)
-		    && f->name[len] == '\0') {
-			break;
-		}
-	}
-
-	D3(if (f) {
-		printk("jffs_find_child(): Found \"%s\".\n", f->name);
-	}
-	else {
-		char *copy = kmalloc(len + 1, GFP_KERNEL);
-		if (copy) {
-			memcpy(copy, name, len);
-			copy[len] = '\0';
-		}
-		printk("jffs_find_child(): Didn't find the file \"%s\".\n",
-		       (copy ? copy : ""));
-		kfree(copy);
-	});
-
-	return f;
-}
-
-
-/* Write a raw inode that takes up a certain amount of space in the flash
-   memory.  At the end of the flash device, there is often space that is
-   impossible to use.  At these times we want to mark this space as not
-   used.  In the cases when the amount of space is greater or equal than
-   a struct jffs_raw_inode, we write a "dummy node" that takes up this
-   space.  The space after the raw inode, if it exists, is left as it is.
-   Since this space after the raw inode contains JFFS_EMPTY_BITMASK bytes,
-   we can compute the checksum of it; we don't have to manipulate it any
-   further.
-
-   If the space left on the device is less than the size of a struct
-   jffs_raw_inode, this space is filled with JFFS_DIRTY_BITMASK bytes.
-   No raw inode is written this time.  */
-static int
-jffs_write_dummy_node(struct jffs_control *c, struct jffs_fm *dirty_fm)
-{
-	struct jffs_fmcontrol *fmc = c->fmc;
-	int err;
-
-	D1(printk("jffs_write_dummy_node(): dirty_fm->offset = 0x%08x, "
-		  "dirty_fm->size = %u\n",
-		  dirty_fm->offset, dirty_fm->size));
-
-	if (dirty_fm->size >= sizeof(struct jffs_raw_inode)) {
-		struct jffs_raw_inode raw_inode;
-		memset(&raw_inode, 0, sizeof(struct jffs_raw_inode));
-		raw_inode.magic = JFFS_MAGIC_BITMASK;
-		raw_inode.dsize = dirty_fm->size
-				  - sizeof(struct jffs_raw_inode);
-		raw_inode.dchksum = raw_inode.dsize * 0xff;
-		raw_inode.chksum
-		= jffs_checksum(&raw_inode, sizeof(struct jffs_raw_inode));
-
-		if ((err = flash_safe_write(fmc->mtd,
-					    dirty_fm->offset,
-					    (u_char *)&raw_inode,
-					    sizeof(struct jffs_raw_inode)))
-		    < 0) {
-			printk(KERN_ERR "JFFS: jffs_write_dummy_node: "
-			       "flash_safe_write failed!\n");
-			return err;
-		}
-	}
-	else {
-		flash_safe_acquire(fmc->mtd);
-		flash_memset(fmc->mtd, dirty_fm->offset, 0, dirty_fm->size);
-		flash_safe_release(fmc->mtd);
-	}
-
-	D3(printk("jffs_write_dummy_node(): Leaving...\n"));
-	return 0;
-}
-
-
-/* Write a raw inode, possibly its name and possibly some data.  */
-int
-jffs_write_node(struct jffs_control *c, struct jffs_node *node,
-		struct jffs_raw_inode *raw_inode,
-		const char *name, const unsigned char *data,
-		int recoverable,
-		struct jffs_file *f)
-{
-	struct jffs_fmcontrol *fmc = c->fmc;
-	struct jffs_fm *fm;
-	struct kvec node_iovec[4];
-	unsigned long iovec_cnt;
-
-	__u32 pos;
-	int err;
-	__u32 slack = 0;
-
-	__u32 total_name_size = raw_inode->nsize
-				+ JFFS_GET_PAD_BYTES(raw_inode->nsize);
-	__u32 total_data_size = raw_inode->dsize
-				+ JFFS_GET_PAD_BYTES(raw_inode->dsize);
-	__u32 total_size = sizeof(struct jffs_raw_inode)
-			   + total_name_size + total_data_size;
-	
-	/* If this node isn't something that will eventually let
-	   GC free even more space, then don't allow it unless
-	   there's at least max_chunk_size space still available
-	*/
-	if (!recoverable)
-		slack = fmc->max_chunk_size;
-		
-
-	/* Fire the retrorockets and shoot the fruiton torpedoes, sir!  */
-
-	ASSERT(if (!node) {
-		printk("jffs_write_node(): node == NULL\n");
-		return -EINVAL;
-	});
-	ASSERT(if (raw_inode && raw_inode->nsize && !name) {
-		printk("*** jffs_write_node(): nsize = %u but name == NULL\n",
-		       raw_inode->nsize);
-		return -EINVAL;
-	});
-
-	D1(printk("jffs_write_node(): filename = \"%s\", ino = %u, "
-		  "total_size = %u\n",
-		  (name ? name : ""), raw_inode->ino,
-		  total_size));
-
-	jffs_fm_write_lock(fmc);
-
-retry:
-	fm = NULL;
-	err = 0;
-	while (!fm) {
-
-		/* Deadlocks suck. */
-		while(fmc->free_size < fmc->min_free_size + total_size + slack) {
-			jffs_fm_write_unlock(fmc);
-			if (!JFFS_ENOUGH_SPACE(c, total_size + slack))
-				return -ENOSPC;
-			jffs_fm_write_lock(fmc);
-		}
-
-		/* First try to allocate some flash memory.  */
-		err = jffs_fmalloc(fmc, total_size, node, &fm);
-		
-		if (err == -ENOSPC) {
-			/* Just out of space. GC and try again */
-			if (fmc->dirty_size < fmc->sector_size) {
-				D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "
-					 "failed, no dirty space to GC\n", fmc,
-					 total_size));
-				return err;
-			}
-			
-			D1(printk(KERN_INFO "jffs_write_node(): Calling jffs_garbage_collect_now()\n"));
-			jffs_fm_write_unlock(fmc);
-			if ((err = jffs_garbage_collect_now(c))) {
-				D(printk("jffs_write_node(): jffs_garbage_collect_now() failed\n"));
-				return err;
-			}
-			jffs_fm_write_lock(fmc);
-			continue;
-		} 
-
-		if (err < 0) {
-			jffs_fm_write_unlock(fmc);
-
-			D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "
-				 "failed!\n", fmc, total_size));
-			return err;
-		}
-
-		if (!fm->nodes) {
-			/* The jffs_fm struct that we got is not good enough.
-			   Make that space dirty and try again  */
-			if ((err = jffs_write_dummy_node(c, fm)) < 0) {
-				kfree(fm);
-				DJM(no_jffs_fm--);
-				jffs_fm_write_unlock(fmc);
-				D(printk("jffs_write_node(): "
-					 "jffs_write_dummy_node(): Failed!\n"));
-				return err;
-			}
-			fm = NULL;
-		}
-	} /* while(!fm) */
-	node->fm = fm;
-
-	ASSERT(if (fm->nodes == 0) {
-		printk(KERN_ERR "jffs_write_node(): fm->nodes == 0\n");
-	});
-
-	pos = node->fm->offset;
-
-	/* Increment the version number here. We can't let the caller
-	   set it beforehand, because we might have had to do GC on a node
-	   of this file - and we'd end up reusing version numbers.
-	*/
-	if (f) {
-		raw_inode->version = f->highest_version + 1;
-		D1(printk (KERN_NOTICE "jffs_write_node(): setting version of %s to %d\n", f->name, raw_inode->version));
-
-		/* if the file was deleted, set the deleted bit in the raw inode */
-		if (f->deleted)
-			raw_inode->deleted = 1;
-	}
-
-	/* Compute the checksum for the data and name chunks.  */
-	raw_inode->dchksum = jffs_checksum(data, raw_inode->dsize);
-	raw_inode->nchksum = jffs_checksum(name, raw_inode->nsize);
-
-	/* The checksum is calculated without the chksum and accurate
-	   fields so set them to zero first.  */
-	raw_inode->accurate = 0;
-	raw_inode->chksum = 0;
-	raw_inode->chksum = jffs_checksum(raw_inode,
-					  sizeof(struct jffs_raw_inode));
-	raw_inode->accurate = 0xff;
-
-	D3(printk("jffs_write_node(): About to write this raw inode to the "
-		  "flash at pos 0x%lx:\n", (long)pos));
-	D3(jffs_print_raw_inode(raw_inode));
-
-	/* The actual raw JFFS node */
-	node_iovec[0].iov_base = (void *) raw_inode;
-	node_iovec[0].iov_len = (size_t) sizeof(struct jffs_raw_inode);
-	iovec_cnt = 1;
-
-	/* Get name and size if there is one */
-	if (raw_inode->nsize) {
-		node_iovec[iovec_cnt].iov_base = (void *) name;
-		node_iovec[iovec_cnt].iov_len = (size_t) raw_inode->nsize;
-		iovec_cnt++;
-
-		if (JFFS_GET_PAD_BYTES(raw_inode->nsize)) {
-			static unsigned char allff[3]={255,255,255};
-			/* Add some extra padding if necessary */
-			node_iovec[iovec_cnt].iov_base = allff;
-			node_iovec[iovec_cnt].iov_len =
-				JFFS_GET_PAD_BYTES(raw_inode->nsize);
-			iovec_cnt++;
-		}
-	}
-
-	/* Get data and size if there is any */
-	if (raw_inode->dsize) {
-		node_iovec[iovec_cnt].iov_base = (void *) data;
-		node_iovec[iovec_cnt].iov_len = (size_t) raw_inode->dsize;
-		iovec_cnt++;
-		/* No need to pad this because we're not actually putting
-		   anything after it.
-		*/
-	}
-
-	if ((err = flash_safe_writev(fmc->mtd, node_iovec, iovec_cnt,
-				    pos)) < 0) {
-		jffs_fmfree_partly(fmc, fm, 0);
-		jffs_fm_write_unlock(fmc);
-		printk(KERN_ERR "JFFS: jffs_write_node: Failed to write, "
-		       "requested %i, wrote %i\n", total_size, err);
-		goto retry;
-	}
-	if (raw_inode->deleted)
-		f->deleted = 1;
-
-	jffs_fm_write_unlock(fmc);
-	D3(printk("jffs_write_node(): Leaving...\n"));
-	return raw_inode->dsize;
-} /* jffs_write_node()  */
-
-
-/* Read data from the node and write it to the buffer.  'node_offset'
-   is how much we have read from this particular node before and which
-   shouldn't be read again.  'max_size' is how much space there is in
-   the buffer.  */
-static int
-jffs_get_node_data(struct jffs_file *f, struct jffs_node *node, 
-		   unsigned char *buf,__u32 node_offset, __u32 max_size)
-{
-	struct jffs_fmcontrol *fmc = f->c->fmc;
-	__u32 pos = node->fm->offset + node->fm_offset + node_offset;
-	__u32 avail = node->data_size - node_offset;
-	__u32 r;
-
-	D2(printk("  jffs_get_node_data(): file: \"%s\", ino: %u, "
-		  "version: %u, node_offset: %u\n",
-		  f->name, node->ino, node->version, node_offset));
-
-	r = min(avail, max_size);
-	D3(printk(KERN_NOTICE "jffs_get_node_data\n"));
-	flash_safe_read(fmc->mtd, pos, buf, r);
-
-	D3(printk("  jffs_get_node_data(): Read %u byte%s.\n",
-		  r, (r == 1 ? "" : "s")));
-
-	return r;
-}
-
-
-/* Read data from the file's nodes.  Write the data to the buffer
-   'buf'.  'read_offset' tells how much data we should skip.  */
-int
-jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset,
-	       __u32 size)
-{
-	struct jffs_node *node;
-	__u32 read_data = 0; /* Total amount of read data.  */
-	__u32 node_offset = 0;
-	__u32 pos = 0; /* Number of bytes traversed.  */
-
-	D2(printk("jffs_read_data(): file = \"%s\", read_offset = %d, "
-		  "size = %u\n",
-		  (f->name ? f->name : ""), read_offset, size));
-
-	if (read_offset >= f->size) {
-		D(printk("  f->size: %d\n", f->size));
-		return 0;
-	}
-
-	/* First find the node to read data from.  */
-	node = f->range_head;
-	while (pos <= read_offset) {
-		node_offset = read_offset - pos;
-		if (node_offset >= node->data_size) {
-			pos += node->data_size;
-			node = node->range_next;
-		}
-		else {
-			break;
-		}
-	}
-
-	/* "Cats are living proof that not everything in nature
-	   has to be useful."
-	   - Garrison Keilor ('97)  */
-
-	/* Fill the buffer.  */
-	while (node && (read_data < size)) {
-		int r;
-		if (!node->fm) {
-			/* This node does not refer to real data.  */
-			r = min(size - read_data,
-				     node->data_size - node_offset);
-			memset(&buf[read_data], 0, r);
-		}
-		else if ((r = jffs_get_node_data(f, node, &buf[read_data],
-						 node_offset,
-						 size - read_data)) < 0) {
-			return r;
-		}
-		read_data += r;
-		node_offset = 0;
-		node = node->range_next;
-	}
-	D3(printk("  jffs_read_data(): Read %u bytes.\n", read_data));
-	return read_data;
-}
-
-
-/* Used for traversing all nodes in the hash table.  */
-int
-jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *))
-{
-	int pos;
-	int r;
-	int result = 0;
-
-	for (pos = 0; pos < c->hash_len; pos++) {
-		struct jffs_file *f, *next;
-
-		/* We must do _safe, because 'func' might remove the
-		   current file 'f' from the list.  */
-		list_for_each_entry_safe(f, next, &c->hash[pos], hash) {
-			r = func(f);
-			if (r < 0)
-				return r;
-			result += r;
-		}
-	}
-
-	return result;
-}
-
-
-/* Free all nodes associated with a file.  */
-static int
-jffs_free_node_list(struct jffs_file *f)
-{
-	struct jffs_node *node;
-	struct jffs_node *p;
-
-	D3(printk("jffs_free_node_list(): f #%u, \"%s\"\n",
-		  f->ino, (f->name ? f->name : "")));
-	node = f->version_head;
-	while (node) {
-		p = node;
-		node = node->version_next;
-		jffs_free_node(p);
-		DJM(no_jffs_node--);
-	}
-	return 0;
-}
-
-
-/* Free a file and its name.  */
-static int
-jffs_free_file(struct jffs_file *f)
-{
-	D3(printk("jffs_free_file: f #%u, \"%s\"\n",
-		  f->ino, (f->name ? f->name : "")));
-
-	if (f->name) {
-		kfree(f->name);
-		DJM(no_name--);
-	}
-	kfree(f);
-	no_jffs_file--;
-	return 0;
-}
-
-static long
-jffs_get_file_count(void)
-{
-	return no_jffs_file;
-}
-
-/* See if a file is deleted. If so, mark that file's nodes as obsolete.  */
-int
-jffs_possibly_delete_file(struct jffs_file *f)
-{
-	struct jffs_node *n;
-
-	D3(printk("jffs_possibly_delete_file(): ino: %u\n",
-		  f->ino));
-
-	ASSERT(if (!f) {
-		printk(KERN_ERR "jffs_possibly_delete_file(): f == NULL\n");
-		return -1;
-	});
-
-	if (f->deleted) {
-		/* First try to remove all older versions.  Commence with
-		   the oldest node.  */
-		for (n = f->version_head; n; n = n->version_next) {
-			if (!n->fm) {
-				continue;
-			}
-			if (jffs_fmfree(f->c->fmc, n->fm, n) < 0) {
-				break;
-			}
-		}
-		/* Unlink the file from the filesystem.  */
-		if (!f->c->building_fs) {
-			jffs_unlink_file_from_tree(f);
-		}
-		jffs_unlink_file_from_hash(f);
-		jffs_free_node_list(f);
-		jffs_free_file(f);
-	}
-	return 0;
-}
-
-
-/* Used in conjunction with jffs_foreach_file() to count the number
-   of files in the file system.  */
-int
-jffs_file_count(struct jffs_file *f)
-{
-	return 1;
-}
-
-
-/* Build up a file's range list from scratch by going through the
-   version list.  */
-static int
-jffs_build_file(struct jffs_file *f)
-{
-	struct jffs_node *n;
-
-	D3(printk("jffs_build_file(): ino: %u, name: \"%s\"\n",
-		  f->ino, (f->name ? f->name : "")));
-
-	for (n = f->version_head; n; n = n->version_next) {
-		jffs_update_file(f, n);
-	}
-	return 0;
-}
-
-
-/* Remove an amount of data from a file. If this amount of data is
-   zero, that could mean that a node should be split in two parts.
-   We remove or change the appropriate nodes in the lists.
-
-   Starting offset of area to be removed is node->data_offset,
-   and the length of the area is in node->removed_size.   */
-static int
-jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
-{
-	struct jffs_node *n;
-	__u32 offset = node->data_offset;
-	__u32 remove_size = node->removed_size;
-
-	D3(printk("jffs_delete_data(): offset = %u, remove_size = %u\n",
-		  offset, remove_size));
-
-	if (remove_size == 0
-	    && f->range_tail
-	    && f->range_tail->data_offset + f->range_tail->data_size
-	       == offset) {
-		/* A simple append; nothing to remove or no node to split.  */
-		return 0;
-	}
-
-	/* Find the node where we should begin the removal.  */
-	for (n = f->range_head; n; n = n->range_next) {
-		if (n->data_offset + n->data_size > offset) {
-			break;
-		}
-	}
-	if (!n) {
-		/* If there's no data in the file there's no data to
-		   remove either.  */
-		return 0;
-	}
-
-	if (n->data_offset > offset) {
-		/* XXX: Not implemented yet.  */
-		printk(KERN_WARNING "JFFS: An unexpected situation "
-		       "occurred in jffs_delete_data.\n");
-	}
-	else if (n->data_offset < offset) {
-		/* See if the node has to be split into two parts.  */
-		if (n->data_offset + n->data_size > offset + remove_size) {
-			/* Do the split.  */
-			struct jffs_node *new_node;
-			D3(printk("jffs_delete_data(): Split node with "
-				  "version number %u.\n", n->version));
-
-			if (!(new_node = jffs_alloc_node())) {
-				D(printk("jffs_delete_data(): -ENOMEM\n"));
-				return -ENOMEM;
-			}
-			DJM(no_jffs_node++);
-
-			new_node->ino = n->ino;
-			new_node->version = n->version;
-			new_node->data_offset = offset;
-			new_node->data_size = n->data_size - (remove_size + (offset - n->data_offset));
-			new_node->fm_offset = n->fm_offset + (remove_size + (offset - n->data_offset));
-			new_node->name_size = n->name_size;
-			new_node->fm = n->fm;
-			new_node->version_prev = n;
-			new_node->version_next = n->version_next;
-			if (new_node->version_next) {
-				new_node->version_next->version_prev
-				= new_node;
-			}
-			else {
-				f->version_tail = new_node;
-			}
-			n->version_next = new_node;
-			new_node->range_prev = n;
-			new_node->range_next = n->range_next;
-			if (new_node->range_next) {
-				new_node->range_next->range_prev = new_node;
-			}
-			else {
-				f->range_tail = new_node;
-			}
-			/* A very interesting can of worms.  */
-			n->range_next = new_node;
-			n->data_size = offset - n->data_offset;
-			if (new_node->fm)
-				jffs_add_node(new_node);
-			else {
-				D1(printk(KERN_WARNING "jffs_delete_data(): Splitting an empty node (file hold).\n!"));
-				D1(printk(KERN_WARNING "FIXME: Did dwmw2 do the right thing here?\n"));
-			}
-			n = new_node->range_next;
-			remove_size = 0;
-		}
-		else {
-			/* No.  No need to split the node.  Just remove
-			   the end of the node.  */
-			int r = min(n->data_offset + n->data_size
-					 - offset, remove_size);
-			n->data_size -= r;
-			remove_size -= r;
-			n = n->range_next;
-		}
-	}
-
-	/* Remove as many nodes as necessary.  */
-	while (n && remove_size) {
-		if (n->data_size <= remove_size) {
-			struct jffs_node *p = n;
-			remove_size -= n->data_size;
-			n = n->range_next;
-			D3(printk("jffs_delete_data(): Removing node: "
-				  "ino: %u, version: %u%s\n",
-				  p->ino, p->version,
-				  (p->fm ? "" : " (virtual)")));
-			if (p->fm) {
-				jffs_fmfree(f->c->fmc, p->fm, p);
-			}
-			jffs_unlink_node_from_range_list(f, p);
-			jffs_unlink_node_from_version_list(f, p);
-			jffs_free_node(p);
-			DJM(no_jffs_node--);
-		}
-		else {
-			n->data_size -= remove_size;
-			n->fm_offset += remove_size;
-			n->data_offset -= (node->removed_size - remove_size);
-			n = n->range_next;
-			break;
-		}
-	}
-
-	/* Adjust the following nodes' information about offsets etc.  */
-	while (n && node->removed_size) {
-		n->data_offset -= node->removed_size;
-		n = n->range_next;
-	}
-
-	if (node->removed_size > (f->size - node->data_offset)) {
-		/* It's possible that the removed_size is in fact
-		 * greater than the amount of data we actually thought
-		 * were present in the first place - some of the nodes 
-		 * which this node originally obsoleted may already have
-		 * been deleted from the flash by subsequent garbage 
-		 * collection.
-		 *
-		 * If this is the case, don't let f->size go negative.
-		 * Bad things would happen :)
-		 */
-		f->size = node->data_offset;
-	} else {
-		f->size -= node->removed_size;
-	}
-	D3(printk("jffs_delete_data(): f->size = %d\n", f->size));
-	return 0;
-} /* jffs_delete_data()  */
-
-
-/* Insert some data into a file.  Prior to the call to this function,
-   jffs_delete_data should be called.  */
-static int
-jffs_insert_data(struct jffs_file *f, struct jffs_node *node)
-{
-	D3(printk("jffs_insert_data(): node->data_offset = %u, "
-		  "node->data_size = %u, f->size = %u\n",
-		  node->data_offset, node->data_size, f->size));
-
-	/* Find the position where we should insert data.  */
-	retry:
-	if (node->data_offset == f->size) {
-		/* A simple append.  This is the most common operation.  */
-		node->range_next = NULL;
-		node->range_prev = f->range_tail;
-		if (node->range_prev) {
-			node->range_prev->range_next = node;
-		}
-		f->range_tail = node;
-		f->size += node->data_size;
-		if (!f->range_head) {
-			f->range_head = node;
-		}
-	}
-	else if (node->data_offset < f->size) {
-		/* Trying to insert data into the middle of the file.  This
-		   means no problem because jffs_delete_data() has already
-		   prepared the range list for us.  */
-		struct jffs_node *n;
-
-		/* Find the correct place for the insertion and then insert
-		   the node.  */
-		for (n = f->range_head; n; n = n->range_next) {
-			D2(printk("Cool stuff's happening!\n"));
-
-			if (n->data_offset == node->data_offset) {
-				node->range_prev = n->range_prev;
-				if (node->range_prev) {
-					node->range_prev->range_next = node;
-				}
-				else {
-					f->range_head = node;
-				}
-				node->range_next = n;
-				n->range_prev = node;
-				break;
-			}
-			ASSERT(else if (n->data_offset + n->data_size >
-					node->data_offset) {
-				printk(KERN_ERR "jffs_insert_data(): "
-				       "Couldn't find a place to insert "
-				       "the data!\n");
-				return -1;
-			});
-		}
-
-		/* Adjust later nodes' offsets etc.  */
-		n = node->range_next;
-		while (n) {
-			n->data_offset += node->data_size;
-			n = n->range_next;
-		}
-		f->size += node->data_size;
-	}
-	else if (node->data_offset > f->size) {
-		/* Okay.  This is tricky.  This means that we want to insert
-		   data at a place that is beyond the limits of the file as
-		   it is constructed right now.  This is actually a common
-		   event that for instance could occur during the mounting
-		   of the file system if a large file have been truncated,
-		   rewritten and then only partially garbage collected.  */
-
-		struct jffs_node *n;
-
-		/* We need a place holder for the data that is missing in
-		   front of this insertion.  This "virtual node" will not
-		   be associated with any space on the flash device.  */
-		struct jffs_node *virtual_node;
-		if (!(virtual_node = jffs_alloc_node())) {
-			return -ENOMEM;
-		}
-
-		D(printk("jffs_insert_data: Inserting a virtual node.\n"));
-		D(printk("  node->data_offset = %u\n", node->data_offset));
-		D(printk("  f->size = %u\n", f->size));
-
-		virtual_node->ino = node->ino;
-		virtual_node->version = node->version;
-		virtual_node->removed_size = 0;
-		virtual_node->fm_offset = 0;
-		virtual_node->name_size = 0;
-		virtual_node->fm = NULL; /* This is a virtual data holder.  */
-		virtual_node->version_prev = NULL;
-		virtual_node->version_next = NULL;
-		virtual_node->range_next = NULL;
-
-		/* Are there any data at all in the file yet?  */
-		if (f->range_head) {
-			virtual_node->data_offset
-			= f->range_tail->data_offset
-			  + f->range_tail->data_size;
-			virtual_node->data_size
-			= node->data_offset - virtual_node->data_offset;
-			virtual_node->range_prev = f->range_tail;
-			f->range_tail->range_next = virtual_node;
-		}
-		else {
-			virtual_node->data_offset = 0;
-			virtual_node->data_size = node->data_offset;
-			virtual_node->range_prev = NULL;
-			f->range_head = virtual_node;
-		}
-
-		f->range_tail = virtual_node;
-		f->size += virtual_node->data_size;
-
-		/* Insert this virtual node in the version list as well.  */
-		for (n = f->version_head; n ; n = n->version_next) {
-			if (n->version == virtual_node->version) {
-				virtual_node->version_prev = n->version_prev;
-				n->version_prev = virtual_node;
-				if (virtual_node->version_prev) {
-					virtual_node->version_prev
-					->version_next = virtual_node;
-				}
-				else {
-					f->version_head = virtual_node;
-				}
-				virtual_node->version_next = n;
-				break;
-			}
-		}
-
-		D(jffs_print_node(virtual_node));
-
-		/* Make a new try to insert the node.  */
-		goto retry;
-	}
-
-	D3(printk("jffs_insert_data(): f->size = %d\n", f->size));
-	return 0;
-}
-
-
-/* A new node (with data) has been added to the file and now the range
-   list has to be modified.  */
-static int
-jffs_update_file(struct jffs_file *f, struct jffs_node *node)
-{
-	int err;
-
-	D3(printk("jffs_update_file(): ino: %u, version: %u\n",
-		  f->ino, node->version));
-
-	if (node->data_size == 0) {
-		if (node->removed_size == 0) {
-			/* data_offset == X  */
-			/* data_size == 0  */
-			/* remove_size == 0  */
-		}
-		else {
-			/* data_offset == X  */
-			/* data_size == 0  */
-			/* remove_size != 0  */
-			if ((err = jffs_delete_data(f, node)) < 0) {
-				return err;
-			}
-		}
-	}
-	else {
-		/* data_offset == X  */
-		/* data_size != 0  */
-		/* remove_size == Y  */
-		if ((err = jffs_delete_data(f, node)) < 0) {
-			return err;
-		}
-		if ((err = jffs_insert_data(f, node)) < 0) {
-			return err;
-		}
-	}
-	return 0;
-}
-
-/* Print the contents of a file.  */
-#if 0
-int
-jffs_print_file(struct jffs_file *f)
-{
-	D(int i);
-	D(printk("jffs_file: 0x%p\n", f));
-	D(printk("{\n"));
-	D(printk("        0x%08x, /* ino  */\n", f->ino));
-	D(printk("        0x%08x, /* pino  */\n", f->pino));
-	D(printk("        0x%08x, /* mode  */\n", f->mode));
-	D(printk("        0x%04x,     /* uid  */\n", f->uid));
-	D(printk("        0x%04x,     /* gid  */\n", f->gid));
-	D(printk("        0x%08x, /* atime  */\n", f->atime));
-	D(printk("        0x%08x, /* mtime  */\n", f->mtime));
-	D(printk("        0x%08x, /* ctime  */\n", f->ctime));
-	D(printk("        0x%02x,       /* nsize  */\n", f->nsize));
-	D(printk("        0x%02x,       /* nlink  */\n", f->nlink));
-	D(printk("        0x%02x,       /* deleted  */\n", f->deleted));
-	D(printk("        \"%s\", ", (f->name ? f->name : "")));
-	D(for (i = strlen(f->name ? f->name : ""); i < 8; ++i) {
-		printk(" ");
-	});
-	D(printk("/* name  */\n"));
-	D(printk("        0x%08x, /* size  */\n", f->size));
-	D(printk("        0x%08x, /* highest_version  */\n",
-		 f->highest_version));
-	D(printk("        0x%p, /* c  */\n", f->c));
-	D(printk("        0x%p, /* parent  */\n", f->parent));
-	D(printk("        0x%p, /* children  */\n", f->children));
-	D(printk("        0x%p, /* sibling_prev  */\n", f->sibling_prev));
-	D(printk("        0x%p, /* sibling_next  */\n", f->sibling_next));
-	D(printk("        0x%p, /* hash_prev  */\n", f->hash.prev));
-	D(printk("        0x%p, /* hash_next  */\n", f->hash.next));
-	D(printk("        0x%p, /* range_head  */\n", f->range_head));
-	D(printk("        0x%p, /* range_tail  */\n", f->range_tail));
-	D(printk("        0x%p, /* version_head  */\n", f->version_head));
-	D(printk("        0x%p, /* version_tail  */\n", f->version_tail));
-	D(printk("}\n"));
-	return 0;
-}
-#endif  /*  0  */
-
-void
-jffs_print_hash_table(struct jffs_control *c)
-{
-	int i;
-
-	printk("JFFS: Dumping the file system's hash table...\n");
-	for (i = 0; i < c->hash_len; i++) {
-		struct jffs_file *f;
-		list_for_each_entry(f, &c->hash[i], hash) {
-			printk("*** c->hash[%u]: \"%s\" "
-			       "(ino: %u, pino: %u)\n",
-			       i, (f->name ? f->name : ""),
-			       f->ino, f->pino);
-		}
-	}
-}
-
-
-void
-jffs_print_tree(struct jffs_file *first_file, int indent)
-{
-	struct jffs_file *f;
-	char *space;
-	int dir;
-
-	if (!first_file) {
-		return;
-	}
-
-	if (!(space = kmalloc(indent + 1, GFP_KERNEL))) {
-		printk("jffs_print_tree(): Out of memory!\n");
-		return;
-	}
-
-	memset(space, ' ', indent);
-	space[indent] = '\0';
-
-	for (f = first_file; f; f = f->sibling_next) {
-		dir = S_ISDIR(f->mode);
-		printk("%s%s%s (ino: %u, highest_version: %u, size: %u)\n",
-		       space, (f->name ? f->name : ""), (dir ? "/" : ""),
-		       f->ino, f->highest_version, f->size);
-		if (dir) {
-			jffs_print_tree(f->children, indent + 2);
-		}
-	}
-
-	kfree(space);
-}
-
-
-#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
-void
-jffs_print_memory_allocation_statistics(void)
-{
-	static long printout;
-	printk("________ Memory printout #%ld ________\n", ++printout);
-	printk("no_jffs_file = %ld\n", no_jffs_file);
-	printk("no_jffs_node = %ld\n", no_jffs_node);
-	printk("no_jffs_control = %ld\n", no_jffs_control);
-	printk("no_jffs_raw_inode = %ld\n", no_jffs_raw_inode);
-	printk("no_jffs_node_ref = %ld\n", no_jffs_node_ref);
-	printk("no_jffs_fm = %ld\n", no_jffs_fm);
-	printk("no_jffs_fmcontrol = %ld\n", no_jffs_fmcontrol);
-	printk("no_hash = %ld\n", no_hash);
-	printk("no_name = %ld\n", no_name);
-	printk("\n");
-}
-#endif
-
-
-/* Rewrite `size' bytes, and begin at `node'.  */
-static int
-jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, __u32 size)
-{
-	struct jffs_control *c = f->c;
-	struct jffs_fmcontrol *fmc = c->fmc;
-	struct jffs_raw_inode raw_inode;
-	struct jffs_node *new_node;
-	struct jffs_fm *fm;
-	__u32 pos;
-	__u32 pos_dchksum;
-	__u32 total_name_size;
-	__u32 total_data_size;
-	__u32 total_size;
-	int err;
-
-	D1(printk("***jffs_rewrite_data(): node: %u, name: \"%s\", size: %u\n",
-		  f->ino, (f->name ? f->name : "(null)"), size));
-
-	/* Create and initialize the new node.  */
-	if (!(new_node = jffs_alloc_node())) {
-		D(printk("jffs_rewrite_data(): "
-			 "Failed to allocate node.\n"));
-		return -ENOMEM;
-	}
-	DJM(no_jffs_node++);
-	new_node->data_offset = node->data_offset;
-	new_node->removed_size = size;
-	total_name_size = JFFS_PAD(f->nsize);
-	total_data_size = JFFS_PAD(size);
-	total_size = sizeof(struct jffs_raw_inode)
-		     + total_name_size + total_data_size;
-	new_node->fm_offset = sizeof(struct jffs_raw_inode)
-			      + total_name_size;
-
-retry:
-	jffs_fm_write_lock(fmc);
-	err = 0;
-
-	if ((err = jffs_fmalloc(fmc, total_size, new_node, &fm)) < 0) {
-		DJM(no_jffs_node--);
-		jffs_fm_write_unlock(fmc);
-		D(printk("jffs_rewrite_data(): Failed to allocate fm.\n"));
-		jffs_free_node(new_node);
-		return err;
-	}
-	else if (!fm->nodes) {
-		/* The jffs_fm struct that we got is not big enough.  */
-		/* This should never happen, because we deal with this case
-		   in jffs_garbage_collect_next().*/
-		printk(KERN_WARNING "jffs_rewrite_data(): Allocated node is too small (%d bytes of %d)\n", fm->size, total_size);
-		if ((err = jffs_write_dummy_node(c, fm)) < 0) {
-			D(printk("jffs_rewrite_data(): "
-				 "jffs_write_dummy_node() Failed!\n"));
-		} else {
-			err = -ENOSPC;
-		}
-		DJM(no_jffs_fm--);
-		jffs_fm_write_unlock(fmc);
-		kfree(fm);
-		
-		return err;
-	}
-	new_node->fm = fm;
-
-	/* Initialize the raw inode.  */
-	raw_inode.magic = JFFS_MAGIC_BITMASK;
-	raw_inode.ino = f->ino;
-	raw_inode.pino = f->pino;
-	raw_inode.version = f->highest_version + 1;
-	raw_inode.mode = f->mode;
-	raw_inode.uid = f->uid;
-	raw_inode.gid = f->gid;
-	raw_inode.atime = f->atime;
-	raw_inode.mtime = f->mtime;
-	raw_inode.ctime = f->ctime;
-	raw_inode.offset = node->data_offset;
-	raw_inode.dsize = size;
-	raw_inode.rsize = size;
-	raw_inode.nsize = f->nsize;
-	raw_inode.nlink = f->nlink;
-	raw_inode.spare = 0;
-	raw_inode.rename = 0;
-	raw_inode.deleted = f->deleted;
-	raw_inode.accurate = 0xff;
-	raw_inode.dchksum = 0;
-	raw_inode.nchksum = 0;
-
-	pos = new_node->fm->offset;
-	pos_dchksum = pos +JFFS_RAW_INODE_DCHKSUM_OFFSET;
-
-	D3(printk("jffs_rewrite_data(): Writing this raw inode "
-		  "to pos 0x%ul.\n", pos));
-	D3(jffs_print_raw_inode(&raw_inode));
-
-	if ((err = flash_safe_write(fmc->mtd, pos,
-				    (u_char *) &raw_inode,
-				    sizeof(struct jffs_raw_inode)
-				    - sizeof(__u32)
-				    - sizeof(__u16) - sizeof(__u16))) < 0) {
-		jffs_fmfree_partly(fmc, fm,
-				   total_name_size + total_data_size);
-		jffs_fm_write_unlock(fmc);
-		printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
-			"rewrite. (raw inode)\n");
-		printk(KERN_ERR "JFFS: jffs_rewrite_data: Now retrying "
-			"rewrite. (raw inode)\n");
-		goto retry;
-	}
-	pos += sizeof(struct jffs_raw_inode);
-
-	/* Write the name to the flash memory.  */
-	if (f->nsize) {
-		D3(printk("jffs_rewrite_data(): Writing name \"%s\" to "
-			  "pos 0x%ul.\n", f->name, (unsigned int) pos));
-		if ((err = flash_safe_write(fmc->mtd, pos,
-					    (u_char *)f->name,
-					    f->nsize)) < 0) {
-			jffs_fmfree_partly(fmc, fm, total_data_size);
-			jffs_fm_write_unlock(fmc);
-			printk(KERN_ERR "JFFS: jffs_rewrite_data: Write "
-				"error during rewrite. (name)\n");
-			printk(KERN_ERR "JFFS: jffs_rewrite_data: Now retrying "
-				"rewrite. (name)\n");
-			goto retry;
-		}
-		pos += total_name_size;
-		raw_inode.nchksum = jffs_checksum(f->name, f->nsize);
-	}
-
-	/* Write the data.  */
-	if (size) {
-		int r;
-		unsigned char *page;
-		__u32 offset = node->data_offset;
-
-		if (!(page = (unsigned char *)__get_free_page(GFP_KERNEL))) {
-			jffs_fmfree_partly(fmc, fm, 0);
-			return -1;
-		}
-
-		while (size) {
-			__u32 s = min(size, (__u32)PAGE_SIZE);
-			if ((r = jffs_read_data(f, (char *)page,
-						offset, s)) < s) {
-				free_page((unsigned long)page);
-				jffs_fmfree_partly(fmc, fm, 0);
-				jffs_fm_write_unlock(fmc);
-				printk(KERN_ERR "JFFS: jffs_rewrite_data: "
-					 "jffs_read_data() "
-					 "failed! (r = %d)\n", r);
-				return -1;
-			}
-			if ((err = flash_safe_write(fmc->mtd,
-						    pos, page, r)) < 0) {
-				free_page((unsigned long)page);
-				jffs_fmfree_partly(fmc, fm, 0);
-				jffs_fm_write_unlock(fmc);
-				printk(KERN_ERR "JFFS: jffs_rewrite_data: "
-				       "Write error during rewrite. "
-				       "(data)\n");
-				goto retry;
-			}
-			pos += r;
-			size -= r;
-			offset += r;
-			raw_inode.dchksum += jffs_checksum(page, r);
-		}
-
-	        free_page((unsigned long)page);
-	}
-
-	raw_inode.accurate = 0;
-	raw_inode.chksum = jffs_checksum(&raw_inode,
-					 sizeof(struct jffs_raw_inode)
-					 - sizeof(__u16));
-
-	/* Add the checksum.  */
-	if ((err
-	     = flash_safe_write(fmc->mtd, pos_dchksum,
-				&((u_char *)
-				&raw_inode)[JFFS_RAW_INODE_DCHKSUM_OFFSET],
-				sizeof(__u32) + sizeof(__u16)
-				+ sizeof(__u16))) < 0) {
-		jffs_fmfree_partly(fmc, fm, 0);
-		jffs_fm_write_unlock(fmc);
-		printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
-		       "rewrite. (checksum)\n");
-		goto retry;
-	}
-
-	/* Now make the file system aware of the newly written node.  */
-	jffs_insert_node(c, f, &raw_inode, f->name, new_node);
-	jffs_fm_write_unlock(fmc);
-
-	D3(printk("jffs_rewrite_data(): Leaving...\n"));
-	return 0;
-} /* jffs_rewrite_data()  */
-
-
-/* jffs_garbage_collect_next implements one step in the garbage collect
-   process and is often called multiple times at each occasion of a
-   garbage collect.  */
-
-static int
-jffs_garbage_collect_next(struct jffs_control *c)
-{
-	struct jffs_fmcontrol *fmc = c->fmc;
-	struct jffs_node *node;
-	struct jffs_file *f;
-	int err = 0;
-	__u32 size;
-	__u32 data_size;
-	__u32 total_name_size;
-	__u32 extra_available;
-	__u32 space_needed;
-	__u32 free_chunk_size1 = jffs_free_size1(fmc);
-	D2(__u32 free_chunk_size2 = jffs_free_size2(fmc));
-
-	/* Get the oldest node in the flash.  */
-	node = jffs_get_oldest_node(fmc);
-	ASSERT(if (!node) {
-		printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
-		       "No oldest node found!\n");
-                err = -1;
-                goto jffs_garbage_collect_next_end;
-		
-
-	});
-
-	/* Find its corresponding file too.  */
-	f = jffs_find_file(c, node->ino);
-
-	if (!f) {
-	  printk (KERN_ERR "JFFS: jffs_garbage_collect_next: "
-                  "No file to garbage collect! "
-		  "(ino = 0x%08x)\n", node->ino);
-          /* FIXME: Free the offending node and recover. */
-          err = -1;
-          goto jffs_garbage_collect_next_end;
-	}
-
-	/* We always write out the name. Theoretically, we don't need
-	   to, but for now it's easier - because otherwise we'd have
-	   to keep track of how many times the current name exists on
-	   the flash and make sure it never reaches zero.
-
-	   The current approach means that would be possible to cause
-	   the GC to end up eating its tail by writing lots of nodes
-	   with no name for it to garbage-collect. Hence the change in
-	   inode.c to write names with _every_ node.
-
-	   It sucks, but it _should_ work.
-	*/
-	total_name_size = JFFS_PAD(f->nsize);
-
-	D1(printk("jffs_garbage_collect_next(): \"%s\", "
-		  "ino: %u, version: %u, location 0x%x, dsize %u\n",
-		  (f->name ? f->name : ""), node->ino, node->version, 
-		  node->fm->offset, node->data_size));
-
-	/* Compute how many data it's possible to rewrite at the moment.  */
-	data_size = f->size - node->data_offset;
-
-	/* And from that, the total size of the chunk we want to write */
-	size = sizeof(struct jffs_raw_inode) + total_name_size
-	       + data_size + JFFS_GET_PAD_BYTES(data_size);
-
-	/* If that's more than max_chunk_size, reduce it accordingly */
-	if (size > fmc->max_chunk_size) {
-		size = fmc->max_chunk_size;
-		data_size = size - sizeof(struct jffs_raw_inode)
-			    - total_name_size;
-	}
-
-	/* If we're asking to take up more space than free_chunk_size1
-	   but we _could_ fit in it, shrink accordingly.
-	*/
-	if (size > free_chunk_size1) {
-
-		if (free_chunk_size1 <
-		    (sizeof(struct jffs_raw_inode) + total_name_size + BLOCK_SIZE)){
-			/* The space left is too small to be of any
-			   use really.  */
-			struct jffs_fm *dirty_fm
-			= jffs_fmalloced(fmc,
-					 fmc->tail->offset + fmc->tail->size,
-					 free_chunk_size1, NULL);
-			if (!dirty_fm) {
-				printk(KERN_ERR "JFFS: "
-				       "jffs_garbage_collect_next: "
-				       "Failed to allocate `dirty' "
-				       "flash memory!\n");
-				err = -1;
-                                goto jffs_garbage_collect_next_end;
-			}
-			D1(printk("Dirtying end of flash - too small\n"));
-			jffs_write_dummy_node(c, dirty_fm);
-                        err = 0;
-			goto jffs_garbage_collect_next_end;
-		}
-		D1(printk("Reducing size of new node from %d to %d to avoid "
-			  " exceeding free_chunk_size1\n",
-			  size, free_chunk_size1));
-
-		size = free_chunk_size1;
-		data_size = size - sizeof(struct jffs_raw_inode)
-			    - total_name_size;
-	}
-
-
-	/* Calculate the amount of space needed to hold the nodes
-	   which are remaining in the tail */
-	space_needed = fmc->min_free_size - (node->fm->offset % fmc->sector_size);
-
-	/* From that, calculate how much 'extra' space we can use to
-	   increase the size of the node we're writing from the size
-	   of the node we're obsoleting
-	*/
-	if (space_needed > fmc->free_size) {
-		/* If we've gone below min_free_size for some reason,
-		   don't fuck up. This is why we have 
-		   min_free_size > sector_size. Whinge about it though,
-		   just so I can convince myself my maths is right.
-		*/
-		D1(printk(KERN_WARNING "jffs_garbage_collect_next(): "
-			  "space_needed %d exceeded free_size %d\n",
-			  space_needed, fmc->free_size));
-		extra_available = 0;
-	} else {
-		extra_available = fmc->free_size - space_needed;
-	}
-
-	/* Check that we don't use up any more 'extra' space than
-	   what's available */
-	if (size > JFFS_PAD(node->data_size) + total_name_size + 
-	    sizeof(struct jffs_raw_inode) + extra_available) {
-		D1(printk("Reducing size of new node from %d to %ld to avoid "
-		       "catching our tail\n", size, 
-			  (long) (JFFS_PAD(node->data_size) + JFFS_PAD(node->name_size) + 
-			  sizeof(struct jffs_raw_inode) + extra_available)));
-		D1(printk("space_needed = %d, extra_available = %d\n", 
-			  space_needed, extra_available));
-
-		size = JFFS_PAD(node->data_size) + total_name_size + 
-		  sizeof(struct jffs_raw_inode) + extra_available;
-		data_size = size - sizeof(struct jffs_raw_inode)
-			- total_name_size;
-	};
-
-	D2(printk("  total_name_size: %u\n", total_name_size));
-	D2(printk("  data_size: %u\n", data_size));
-	D2(printk("  size: %u\n", size));
-	D2(printk("  f->nsize: %u\n", f->nsize));
-	D2(printk("  f->size: %u\n", f->size));
-	D2(printk("  node->data_offset: %u\n", node->data_offset));
-	D2(printk("  free_chunk_size1: %u\n", free_chunk_size1));
-	D2(printk("  free_chunk_size2: %u\n", free_chunk_size2));
-	D2(printk("  node->fm->offset: 0x%08x\n", node->fm->offset));
-
-	if ((err = jffs_rewrite_data(f, node, data_size))) {
-		printk(KERN_WARNING "jffs_rewrite_data() failed: %d\n", err);
-		return err;
-	}
-	  
-jffs_garbage_collect_next_end:
-	D3(printk("jffs_garbage_collect_next: Leaving...\n"));
-	return err;
-} /* jffs_garbage_collect_next */
-
-
-/* If an obsolete node is partly going to be erased due to garbage
-   collection, the part that isn't going to be erased must be filled
-   with zeroes so that the scan of the flash will work smoothly next
-   time.  (The data in the file could for instance be a JFFS image
-   which could cause enormous confusion during a scan of the flash
-   device if we didn't do this.)
-     There are two phases in this procedure: First, the clearing of
-   the name and data parts of the node. Second, possibly also clearing
-   a part of the raw inode as well.  If the box is power cycled during
-   the first phase, only the checksum of this node-to-be-cleared-at-
-   the-end will be wrong.  If the box is power cycled during, or after,
-   the clearing of the raw inode, the information like the length of
-   the name and data parts are zeroed.  The next time the box is
-   powered up, the scanning algorithm manages this faulty data too
-   because:
-
-   - The checksum is invalid and thus the raw inode must be discarded
-     in any case.
-   - If the lengths of the data part or the name part are zeroed, the
-     scanning just continues after the raw inode.  But after the inode
-     the scanning procedure just finds zeroes which is the same as
-     dirt.
-
-   So, in the end, this could never fail. :-)  Even if it does fail,
-   the scanning algorithm should manage that too.  */
-
-static int
-jffs_clear_end_of_node(struct jffs_control *c, __u32 erase_size)
-{
-	struct jffs_fm *fm;
-	struct jffs_fmcontrol *fmc = c->fmc;
-	__u32 zero_offset;
-	__u32 zero_size;
-	__u32 zero_offset_data;
-	__u32 zero_size_data;
-	__u32 cutting_raw_inode = 0;
-
-	if (!(fm = jffs_cut_node(fmc, erase_size))) {
-		D3(printk("jffs_clear_end_of_node(): fm == NULL\n"));
-		return 0;
-	}
-
-	/* Where and how much shall we clear?  */
-	zero_offset = fmc->head->offset + erase_size;
-	zero_size = fm->offset + fm->size - zero_offset;
-
-	/* Do we have to clear the raw_inode explicitly?  */
-	if (fm->size - zero_size < sizeof(struct jffs_raw_inode)) {
-		cutting_raw_inode = sizeof(struct jffs_raw_inode)
-				    - (fm->size - zero_size);
-	}
-
-	/* First, clear the name and data fields.  */
-	zero_offset_data = zero_offset + cutting_raw_inode;
-	zero_size_data = zero_size - cutting_raw_inode;
-	flash_safe_acquire(fmc->mtd);
-	flash_memset(fmc->mtd, zero_offset_data, 0, zero_size_data);
-	flash_safe_release(fmc->mtd);
-
-	/* Should we clear a part of the raw inode?  */
-	if (cutting_raw_inode) {
-		/* I guess it is ok to clear the raw inode in this order.  */
-		flash_safe_acquire(fmc->mtd);
-		flash_memset(fmc->mtd, zero_offset, 0,
-			     cutting_raw_inode);
-		flash_safe_release(fmc->mtd);
-	}
-
-	return 0;
-} /* jffs_clear_end_of_node()  */
-
-/* Try to erase as much as possible of the dirt in the flash memory.  */
-static long
-jffs_try_to_erase(struct jffs_control *c)
-{
-	struct jffs_fmcontrol *fmc = c->fmc;
-	long erase_size;
-	int err;
-	__u32 offset;
-
-	D3(printk("jffs_try_to_erase()\n"));
-
-	erase_size = jffs_erasable_size(fmc);
-
-	D2(printk("jffs_try_to_erase(): erase_size = %ld\n", erase_size));
-
-	if (erase_size == 0) {
-		return 0;
-	}
-	else if (erase_size < 0) {
-		printk(KERN_ERR "JFFS: jffs_try_to_erase: "
-		       "jffs_erasable_size returned %ld.\n", erase_size);
-		return erase_size;
-	}
-
-	if ((err = jffs_clear_end_of_node(c, erase_size)) < 0) {
-		printk(KERN_ERR "JFFS: jffs_try_to_erase: "
-		       "Clearing of node failed.\n");
-		return err;
-	}
-
-	offset = fmc->head->offset;
-
-	/* Now, let's try to do the erase.  */
-	if ((err = flash_erase_region(fmc->mtd,
-				      offset, erase_size)) < 0) {
-		printk(KERN_ERR "JFFS: Erase of flash failed. "
-		       "offset = %u, erase_size = %ld\n",
-		       offset, erase_size);
-		/* XXX: Here we should allocate this area as dirty
-		   with jffs_fmalloced or something similar.  Now
-		   we just report the error.  */
-		return err;
-	}
-
-#if 0
-	/* Check if the erased sectors really got erased.  */
-	{
-		__u32 pos;
-		__u32 end;
-
-		pos = (__u32)flash_get_direct_pointer(to_kdev_t(c->sb->s_dev), offset);
-		end = pos + erase_size;
-
-		D2(printk("JFFS: Checking erased sector(s)...\n"));
-
-		flash_safe_acquire(fmc->mtd);
-
-		for (; pos < end; pos += 4) {
-			if (*(__u32 *)pos != JFFS_EMPTY_BITMASK) {
-				printk("JFFS: Erase failed! pos = 0x%lx\n",
-				       (long)pos);
-				jffs_hexdump(fmc->mtd, pos,
-					     jffs_min(256, end - pos));
-				err = -1;
-				break;
-			}
-		}
-
-		flash_safe_release(fmc->mtd);
-
-		if (!err) {
-			D2(printk("JFFS: Erase succeeded.\n"));
-		}
-		else {
-			/* XXX: Here we should allocate the memory
-			   with jffs_fmalloced() in order to prevent
-			   JFFS from using this area accidentally.  */
-			return err;
-		}
-	}
-#endif
-
-	/* Update the flash memory data structures.  */
-	jffs_sync_erase(fmc, erase_size);
-
-	return erase_size;
-}
-
-
-/* There are different criteria that should trigger a garbage collect:
-
-   1. There is too much dirt in the memory.
-   2. The free space is becoming small.
-   3. There are many versions of a node.
-
-   The garbage collect should always be done in a manner that guarantees
-   that future garbage collects cannot be locked.  E.g. Rewritten chunks
-   should not be too large (span more than one sector in the flash memory
-   for exemple).  Of course there is a limit on how intelligent this garbage
-   collection can be.  */
-
-
-static int
-jffs_garbage_collect_now(struct jffs_control *c)
-{
-	struct jffs_fmcontrol *fmc = c->fmc;
-	long erased = 0;
-	int result = 0;
-	D1(int i = 1);
-	D2(printk("***jffs_garbage_collect_now(): fmc->dirty_size = %u, fmc->free_size = 0x%x\n, fcs1=0x%x, fcs2=0x%x",
-		  fmc->dirty_size, fmc->free_size, jffs_free_size1(fmc), jffs_free_size2(fmc)));
-	D2(jffs_print_fmcontrol(fmc));
-
-	//	down(&fmc->gclock);
-
-	/* If it is possible to garbage collect, do so.  */
-	
-	while (erased == 0) {
-		D1(printk("***jffs_garbage_collect_now(): round #%u, "
-			  "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
-		D2(jffs_print_fmcontrol(fmc));
-
-		if ((erased = jffs_try_to_erase(c)) < 0) {
-			printk(KERN_WARNING "JFFS: Error in "
-			       "garbage collector.\n");
-			result = erased;
-			goto gc_end;
-		}
-		if (erased)
-			break;
-		
-		if (fmc->free_size == 0) {
-			/* Argh */
-			printk(KERN_ERR "jffs_garbage_collect_now(): free_size == 0. This is BAD.\n");
-			result = -ENOSPC;
-			break;
-		}
-
-		if (fmc->dirty_size < fmc->sector_size) {
-			/* Actually, we _may_ have been able to free some, 
-			 * if there are many overlapping nodes which aren't
-			 * actually marked dirty because they still have
-			 * some valid data in each.
-			 */
-			result = -ENOSPC;
-			break;
-		}
-
-		/* Let's dare to make a garbage collect.  */
-		if ((result = jffs_garbage_collect_next(c)) < 0) {
-			printk(KERN_ERR "JFFS: Something "
-			       "has gone seriously wrong "
-			       "with a garbage collect.\n");
-			goto gc_end;
-		}
-
-		D1(printk("   jffs_garbage_collect_now(): erased: %ld\n", erased));
-		DJM(jffs_print_memory_allocation_statistics());
-	}
-	
-gc_end:
-	//	up(&fmc->gclock);
-
-	D3(printk("   jffs_garbage_collect_now(): Leaving...\n"));
-	D1(if (erased) {
-		printk("jffs_g_c_now(): erased = %ld\n", erased);
-		jffs_print_fmcontrol(fmc);
-	});
-
-	if (!erased && !result)
-		return -ENOSPC;
-
-	return result;
-} /* jffs_garbage_collect_now() */
-
-
-/* Determine if it is reasonable to start garbage collection.
-   We start a gc pass if either:
-   - The number of free bytes < MIN_FREE_BYTES && at least one
-     block is dirty, OR
-   - The number of dirty bytes > MAX_DIRTY_BYTES
-*/
-static inline int thread_should_wake (struct jffs_control *c)
-{
-	D1(printk (KERN_NOTICE "thread_should_wake(): free=%d, dirty=%d, blocksize=%d.\n",
-		   c->fmc->free_size, c->fmc->dirty_size, c->fmc->sector_size));
-
-	/* If there's not enough dirty space to free a block, there's no point. */
-	if (c->fmc->dirty_size < c->fmc->sector_size) {
-		D2(printk(KERN_NOTICE "thread_should_wake(): Not waking. Insufficient dirty space\n"));
-		return 0;
-	}
-#if 1
-	/* If there is too much RAM used by the various structures, GC */
-	if (jffs_get_node_inuse() > (c->fmc->used_size/c->fmc->max_chunk_size * 5 + jffs_get_file_count() * 2 + 50)) {
-		/* FIXME: Provide proof that this test can be satisfied. We
-		   don't want a filesystem doing endless GC just because this
-		   condition cannot ever be false.
-		*/
-		D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to number of nodes\n"));
-		return 1;
-	}
-#endif
-	/* If there are fewer free bytes than the threshold, GC */
-	if (c->fmc->free_size < c->gc_minfree_threshold) {
-		D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to insufficent free space\n"));
-		return 1;
-	}
-	/* If there are more dirty bytes than the threshold, GC */
-	if (c->fmc->dirty_size > c->gc_maxdirty_threshold) {
-		D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to excessive dirty space\n"));
-		return 1;
-	}	
-	/* FIXME: What about the "There are many versions of a node" condition? */
-
-	return 0;
-}
-
-
-void jffs_garbage_collect_trigger(struct jffs_control *c)
-{
-	/* NOTE: We rely on the fact that we have the BKL here.
-	 * Otherwise, the gc_task could go away between the check
-	 * and the wake_up_process()
-	 */
-	if (c->gc_task && thread_should_wake(c))
-		send_sig(SIGHUP, c->gc_task, 1);
-}
-  
-
-/* Kernel threads  take (void *) as arguments.   Thus we pass
-   the jffs_control data as a (void *) and then cast it. */
-int
-jffs_garbage_collect_thread(void *ptr)
-{
-        struct jffs_control *c = (struct jffs_control *) ptr;
-	struct jffs_fmcontrol *fmc = c->fmc;
-	long erased;
-	int result = 0;
-	D1(int i = 1);
-
-	daemonize("jffs_gcd");
-
-	c->gc_task = current;
-
-	lock_kernel();
-	init_completion(&c->gc_thread_comp); /* barrier */ 
-	spin_lock_irq(&current->sighand->siglock);
-	siginitsetinv (&current->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT));
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): Starting infinite loop.\n"));
-
-	for (;;) {
-
-		/* See if we need to start gc.  If we don't, go to sleep.
-		   
-		   Current implementation is a BAD THING(tm).  If we try 
-		   to unmount the FS, the unmount operation will sleep waiting
-		   for this thread to exit.  We need to arrange to send it a
-		   sig before the umount process sleeps.
-		*/
-
-		if (!thread_should_wake(c))
-			set_current_state (TASK_INTERRUPTIBLE);
-		
-		schedule(); /* Yes, we do this even if we want to go
-				       on immediately - we're a low priority 
-				       background task. */
-
-		/* Put_super will send a SIGKILL and then wait on the sem. 
-		 */
-		while (signal_pending(current)) {
-			siginfo_t info;
-			unsigned long signr = 0;
-
-			if (try_to_freeze())
-				continue;
-
-			spin_lock_irq(&current->sighand->siglock);
-			signr = dequeue_signal(current, &current->blocked, &info);
-			spin_unlock_irq(&current->sighand->siglock);
-
-			switch(signr) {
-			case SIGSTOP:
-				D1(printk("jffs_garbage_collect_thread(): SIGSTOP received.\n"));
-				set_current_state(TASK_STOPPED);
-				schedule();
-				break;
-
-			case SIGKILL:
-				D1(printk("jffs_garbage_collect_thread(): SIGKILL received.\n"));
-				c->gc_task = NULL;
-				complete_and_exit(&c->gc_thread_comp, 0);
-			}
-		}
-
-
-		D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): collecting.\n"));
-
-		D3(printk (KERN_NOTICE "g_c_thread(): down biglock\n"));
-		mutex_lock(&fmc->biglock);
-		
-		D1(printk("***jffs_garbage_collect_thread(): round #%u, "
-			  "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
-		D2(jffs_print_fmcontrol(fmc));
-
-		if ((erased = jffs_try_to_erase(c)) < 0) {
-			printk(KERN_WARNING "JFFS: Error in "
-			       "garbage collector: %ld.\n", erased);
-		}
-
-		if (erased)
-			goto gc_end;
-
-		if (fmc->free_size == 0) {
-			/* Argh. Might as well commit suicide. */
-			printk(KERN_ERR "jffs_garbage_collect_thread(): free_size == 0. This is BAD.\n");
-			send_sig(SIGQUIT, c->gc_task, 1);
-			// panic()
-			goto gc_end;
-		}
-		
-		/* Let's dare to make a garbage collect.  */
-		if ((result = jffs_garbage_collect_next(c)) < 0) {
-			printk(KERN_ERR "JFFS: Something "
-			       "has gone seriously wrong "
-			       "with a garbage collect: %d\n", result);
-		}
-		
-	gc_end:
-		D3(printk (KERN_NOTICE "g_c_thread(): up biglock\n"));
-		mutex_unlock(&fmc->biglock);
-	} /* for (;;) */
-} /* jffs_garbage_collect_thread() */
diff --git a/fs/jffs/intrep.h b/fs/jffs/intrep.h
deleted file mode 100644
index 5c7abe0..0000000
--- a/fs/jffs/intrep.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This 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.
- *
- * $Id: intrep.h,v 1.14 2001/09/23 23:28:37 dwmw2 Exp $
- *
- */
-
-#ifndef __LINUX_JFFS_INTREP_H__
-#define __LINUX_JFFS_INTREP_H__
-#include "jffs_fm.h"
-struct jffs_node *jffs_alloc_node(void);
-void jffs_free_node(struct jffs_node *n);
-int jffs_get_node_inuse(void);
-
-void jffs_cleanup_control(struct jffs_control *c);
-int jffs_build_fs(struct super_block *sb);
-
-int jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
-		     const struct jffs_raw_inode *raw_inode,
-		     const char *name, struct jffs_node *node);
-struct jffs_file *jffs_find_file(struct jffs_control *c, __u32 ino);
-struct jffs_file *jffs_find_child(struct jffs_file *dir, const char *name, int len);
-
-void jffs_free_node(struct jffs_node *node);
-
-int jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *));
-int jffs_possibly_delete_file(struct jffs_file *f);
-int jffs_insert_file_into_tree(struct jffs_file *f);
-int jffs_unlink_file_from_tree(struct jffs_file *f);
-int jffs_file_count(struct jffs_file *f);
-
-int jffs_write_node(struct jffs_control *c, struct jffs_node *node,
-		    struct jffs_raw_inode *raw_inode,
-		    const char *name, const unsigned char *buf,
-		    int recoverable, struct jffs_file *f);
-int jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset, __u32 size);
-
-/* Garbage collection stuff.  */
-int jffs_garbage_collect_thread(void *c);
-void jffs_garbage_collect_trigger(struct jffs_control *c);
-
-/* For debugging purposes.  */
-#if 0
-int jffs_print_file(struct jffs_file *f);
-#endif  /*  0  */
-void jffs_print_hash_table(struct jffs_control *c);
-void jffs_print_tree(struct jffs_file *first_file, int indent);
-
-#endif /* __LINUX_JFFS_INTREP_H__  */
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
deleted file mode 100644
index 5a95fbd..0000000
--- a/fs/jffs/jffs_fm.c
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This 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.
- *
- * $Id: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/blkdev.h>
-#include <linux/jffs.h>
-#include "jffs_fm.h"
-#include "intrep.h"
-
-#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
-static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
-#endif
-
-static struct jffs_fm *jffs_alloc_fm(void);
-static void jffs_free_fm(struct jffs_fm *n);
-
-extern struct kmem_cache     *fm_cache;
-extern struct kmem_cache     *node_cache;
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-void
-jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
-{
-	D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
-	D(printk("{\n"));
-	D(printk("        %u, /* flash_size  */\n", fmc->flash_size));
-	D(printk("        %u, /* used_size  */\n", fmc->used_size));
-	D(printk("        %u, /* dirty_size  */\n", fmc->dirty_size));
-	D(printk("        %u, /* free_size  */\n", fmc->free_size));
-	D(printk("        %u, /* sector_size  */\n", fmc->sector_size));
-	D(printk("        %u, /* min_free_size  */\n", fmc->min_free_size));
-	D(printk("        %u, /* max_chunk_size  */\n", fmc->max_chunk_size));
-	D(printk("        0x%p, /* mtd  */\n", fmc->mtd));
-	D(printk("        0x%p, /* head  */    "
-		 "(head->offset = 0x%08x)\n",
-		 fmc->head, (fmc->head ? fmc->head->offset : 0)));
-	D(printk("        0x%p, /* tail  */    "
-		 "(tail->offset + tail->size = 0x%08x)\n",
-		 fmc->tail,
-		 (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
-	D(printk("        0x%p, /* head_extra  */\n", fmc->head_extra));
-	D(printk("        0x%p, /* tail_extra  */\n", fmc->tail_extra));
-	D(printk("}\n"));
-}
-#endif  /*  CONFIG_JFFS_FS_VERBOSE > 0  */
-
-#if CONFIG_JFFS_FS_VERBOSE > 2
-static void
-jffs_print_fm(struct jffs_fm *fm)
-{
-	D(printk("struct jffs_fm: 0x%p\n", fm));
-	D(printk("{\n"));
-	D(printk("       0x%08x, /* offset  */\n", fm->offset));
-	D(printk("       %u, /* size  */\n", fm->size));
-	D(printk("       0x%p, /* prev  */\n", fm->prev));
-	D(printk("       0x%p, /* next  */\n", fm->next));
-	D(printk("       0x%p, /* nodes  */\n", fm->nodes));
-	D(printk("}\n"));
-}
-#endif  /*  CONFIG_JFFS_FS_VERBOSE > 2  */
-
-#if 0
-void
-jffs_print_node_ref(struct jffs_node_ref *ref)
-{
-	D(printk("struct jffs_node_ref: 0x%p\n", ref));
-	D(printk("{\n"));
-	D(printk("       0x%p, /* node  */\n", ref->node));
-	D(printk("       0x%p, /* next  */\n", ref->next));
-	D(printk("}\n"));
-}
-#endif  /*  0  */
-
-/* This function creates a new shiny flash memory control structure.  */
-struct jffs_fmcontrol *
-jffs_build_begin(struct jffs_control *c, int unit)
-{
-	struct jffs_fmcontrol *fmc;
-	struct mtd_info *mtd;
-	
-	D3(printk("jffs_build_begin()\n"));
-	fmc = kmalloc(sizeof(*fmc), GFP_KERNEL);
-	if (!fmc) {
-		D(printk("jffs_build_begin(): Allocation of "
-			 "struct jffs_fmcontrol failed!\n"));
-		return (struct jffs_fmcontrol *)0;
-	}
-	DJM(no_jffs_fmcontrol++);
-
-	mtd = get_mtd_device(NULL, unit);
-
-	if (IS_ERR(mtd)) {
-		kfree(fmc);
-		DJM(no_jffs_fmcontrol--);
-		return NULL;
-	}
-	
-	/* Retrieve the size of the flash memory.  */
-	fmc->flash_size = mtd->size;
-	D3(printk("  fmc->flash_size = %d bytes\n", fmc->flash_size));
-
-	fmc->used_size = 0;
-	fmc->dirty_size = 0;
-	fmc->free_size = mtd->size;
-	fmc->sector_size = mtd->erasesize;
-	fmc->max_chunk_size = fmc->sector_size >> 1;
-	/* min_free_size:
-	   1 sector, obviously.
-	   + 1 x max_chunk_size, for when a nodes overlaps the end of a sector
-	   + 1 x max_chunk_size again, which ought to be enough to handle 
-		   the case where a rename causes a name to grow, and GC has
-		   to write out larger nodes than the ones it's obsoleting.
-		   We should fix it so it doesn't have to write the name
-		   _every_ time. Later.
-	   + another 2 sectors because people keep getting GC stuck and
-	           we don't know why. This scares me - I want formal proof
-		   of correctness of whatever number we put here. dwmw2.
-	*/
-	fmc->min_free_size = fmc->sector_size << 2;
-	fmc->mtd = mtd;
-	fmc->c = c;
-	fmc->head = NULL;
-	fmc->tail = NULL;
-	fmc->head_extra = NULL;
-	fmc->tail_extra = NULL;
-	mutex_init(&fmc->biglock);
-	return fmc;
-}
-
-
-/* When the flash memory scan has completed, this function should be called
-   before use of the control structure.  */
-void
-jffs_build_end(struct jffs_fmcontrol *fmc)
-{
-	D3(printk("jffs_build_end()\n"));
-
-	if (!fmc->head) {
-		fmc->head = fmc->head_extra;
-		fmc->tail = fmc->tail_extra;
-	}
-	else if (fmc->head_extra) {
-		fmc->tail_extra->next = fmc->head;
-		fmc->head->prev = fmc->tail_extra;
-		fmc->head = fmc->head_extra;
-	}
-	fmc->head_extra = NULL; /* These two instructions should be omitted.  */
-	fmc->tail_extra = NULL;
-	D3(jffs_print_fmcontrol(fmc));
-}
-
-
-/* Call this function when the file system is unmounted.  This function
-   frees all memory used by this module.  */
-void
-jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc)
-{
-	if (fmc) {
-		struct jffs_fm *next = fmc->head;
-		while (next) {
-			struct jffs_fm *cur = next;
-			next = next->next;
-			jffs_free_fm(cur);
-		}
-		put_mtd_device(fmc->mtd);
-		kfree(fmc);
-		DJM(no_jffs_fmcontrol--);
-	}
-}
-
-
-/* This function returns the size of the first chunk of free space on the
-   flash memory.  This function will return something nonzero if the flash
-   memory contains any free space.  */
-__u32
-jffs_free_size1(struct jffs_fmcontrol *fmc)
-{
-	__u32 head;
-	__u32 tail;
-	__u32 end = fmc->flash_size;
-
-	if (!fmc->head) {
-		/* There is nothing on the flash.  */
-		return fmc->flash_size;
-	}
-
-	/* Compute the beginning and ending of the contents of the flash.  */
-	head = fmc->head->offset;
-	tail = fmc->tail->offset + fmc->tail->size;
-	if (tail == end) {
-		tail = 0;
-	}
-	ASSERT(else if (tail > end) {
-		printk(KERN_WARNING "jffs_free_size1(): tail > end\n");
-		tail = 0;
-	});
-
-	if (head <= tail) {
-		return end - tail;
-	}
-	else {
-		return head - tail;
-	}
-}
-
-/* This function will return something nonzero in case there are two free
-   areas on the flash.  Like this:
-
-     +----------------+------------------+----------------+
-     |     FREE 1     |   USED / DIRTY   |     FREE 2     |
-     +----------------+------------------+----------------+
-       fmc->head -----^
-       fmc->tail ------------------------^
-
-   The value returned, will be the size of the first empty area on the
-   flash, in this case marked "FREE 1".  */
-__u32
-jffs_free_size2(struct jffs_fmcontrol *fmc)
-{
-	if (fmc->head) {
-		__u32 head = fmc->head->offset;
-		__u32 tail = fmc->tail->offset + fmc->tail->size;
-		if (tail == fmc->flash_size) {
-			tail = 0;
-		}
-
-		if (tail >= head) {
-			return head;
-		}
-	}
-	return 0;
-}
-
-
-/* Allocate a chunk of flash memory.  If there is enough space on the
-   device, a reference to the associated node is stored in the jffs_fm
-   struct.  */
-int
-jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node,
-	     struct jffs_fm **result)
-{
-	struct jffs_fm *fm;
-	__u32 free_chunk_size1;
-	__u32 free_chunk_size2;
-
-	D2(printk("jffs_fmalloc(): fmc = 0x%p, size = %d, "
-		  "node = 0x%p\n", fmc, size, node));
-
-	*result = NULL;
-
-	if (!(fm = jffs_alloc_fm())) {
-		D(printk("jffs_fmalloc(): kmalloc() failed! (fm)\n"));
-		return -ENOMEM;
-	}
-
-	free_chunk_size1 = jffs_free_size1(fmc);
-	free_chunk_size2 = jffs_free_size2(fmc);
-	if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) {
-		printk(KERN_WARNING "Free size accounting screwed\n");
-		printk(KERN_WARNING "free_chunk_size1 == 0x%x, free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", free_chunk_size1, free_chunk_size2, fmc->free_size);
-	}
-
-	D3(printk("jffs_fmalloc(): free_chunk_size1 = %u, "
-		  "free_chunk_size2 = %u\n",
-		  free_chunk_size1, free_chunk_size2));
-
-	if (size <= free_chunk_size1) {
-		if (!(fm->nodes = (struct jffs_node_ref *)
-				  kmalloc(sizeof(struct jffs_node_ref),
-					  GFP_KERNEL))) {
-			D(printk("jffs_fmalloc(): kmalloc() failed! "
-				 "(node_ref)\n"));
-			jffs_free_fm(fm);
-			return -ENOMEM;
-		}
-		DJM(no_jffs_node_ref++);
-		fm->nodes->node = node;
-		fm->nodes->next = NULL;
-		if (fmc->tail) {
-			fm->offset = fmc->tail->offset + fmc->tail->size;
-			if (fm->offset == fmc->flash_size) {
-				fm->offset = 0;
-			}
-			ASSERT(else if (fm->offset > fmc->flash_size) {
-				printk(KERN_WARNING "jffs_fmalloc(): "
-				       "offset > flash_end\n");
-				fm->offset = 0;
-			});
-		}
-		else {
-			/* There don't have to be files in the file
-			   system yet.  */
-			fm->offset = 0;
-		}
-		fm->size = size;
-		fmc->free_size -= size;
-		fmc->used_size += size;
-	}
-	else if (size > free_chunk_size2) {
-		printk(KERN_WARNING "JFFS: Tried to allocate a too "
-		       "large flash memory chunk. (size = %u)\n", size);
-		jffs_free_fm(fm);
-		return -ENOSPC;
-	}
-	else {
-		fm->offset = fmc->tail->offset + fmc->tail->size;
-		fm->size = free_chunk_size1;
-		fm->nodes = NULL;
-		fmc->free_size -= fm->size;
-		fmc->dirty_size += fm->size; /* Changed by simonk. This seemingly fixes a 
-						bug that caused infinite garbage collection.
-						It previously set fmc->dirty_size to size (which is the
-						size of the requested chunk).
-					     */
-	}
-
-	fm->next = NULL;
-	if (!fmc->head) {
-		fm->prev = NULL;
-		fmc->head = fm;
-		fmc->tail = fm;
-	}
-	else {
-		fm->prev = fmc->tail;
-		fmc->tail->next = fm;
-		fmc->tail = fm;
-	}
-
-	D3(jffs_print_fmcontrol(fmc));
-	D3(jffs_print_fm(fm));
-	*result = fm;
-	return 0;
-}
-
-
-/* The on-flash space is not needed anymore by the passed node.  Remove
-   the reference to the node from the node list.  If the data chunk in
-   the flash memory isn't used by any more nodes anymore (fm->nodes == 0),
-   then mark that chunk as dirty.  */
-int
-jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, struct jffs_node *node)
-{
-	struct jffs_node_ref *ref;
-	struct jffs_node_ref *prev;
-	ASSERT(int del = 0);
-
-	D2(printk("jffs_fmfree(): node->ino = %u, node->version = %u\n",
-		 node->ino, node->version));
-
-	ASSERT(if (!fmc || !fm || !fm->nodes) {
-		printk(KERN_ERR "jffs_fmfree(): fmc: 0x%p, fm: 0x%p, "
-		       "fm->nodes: 0x%p\n",
-		       fmc, fm, (fm ? fm->nodes : NULL));
-		return -1;
-	});
-
-	/* Find the reference to the node that is going to be removed
-	   and remove it.  */
-	for (ref = fm->nodes, prev = NULL; ref; ref = ref->next) {
-		if (ref->node == node) {
-			if (prev) {
-				prev->next = ref->next;
-			}
-			else {
-				fm->nodes = ref->next;
-			}
-			kfree(ref);
-			DJM(no_jffs_node_ref--);
-			ASSERT(del = 1);
-			break;
-		}
-		prev = ref;
-	}
-
-	/* If the data chunk in the flash memory isn't used anymore
-	   just mark it as obsolete.  */
-	if (!fm->nodes) {
-		/* No node uses this chunk so let's remove it.  */
-		fmc->used_size -= fm->size;
-		fmc->dirty_size += fm->size;
-#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
-		if (jffs_mark_obsolete(fmc, fm->offset) < 0) {
-			D1(printk("jffs_fmfree(): Failed to mark an on-flash "
-				  "node obsolete!\n"));
-			return -1;
-		}
-#endif
-	}
-
-	ASSERT(if (!del) {
-		printk(KERN_WARNING "***jffs_fmfree(): "
-		       "Didn't delete any node reference!\n");
-	});
-
-	return 0;
-}
-
-
-/* This allocation function is used during the initialization of
-   the file system.  */
-struct jffs_fm *
-jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, __u32 size,
-	       struct jffs_node *node)
-{
-	struct jffs_fm *fm;
-
-	D3(printk("jffs_fmalloced()\n"));
-
-	if (!(fm = jffs_alloc_fm())) {
-		D(printk("jffs_fmalloced(0x%p, %u, %u, 0x%p): failed!\n",
-			 fmc, offset, size, node));
-		return NULL;
-	}
-	fm->offset = offset;
-	fm->size = size;
-	fm->prev = NULL;
-	fm->next = NULL;
-	fm->nodes = NULL;
-	if (node) {
-		/* `node' exists and it should be associated with the
-		    jffs_fm structure `fm'.  */
-		if (!(fm->nodes = (struct jffs_node_ref *)
-				  kmalloc(sizeof(struct jffs_node_ref),
-					  GFP_KERNEL))) {
-			D(printk("jffs_fmalloced(): !fm->nodes\n"));
-			jffs_free_fm(fm);
-			return NULL;
-		}
-		DJM(no_jffs_node_ref++);
-		fm->nodes->node = node;
-		fm->nodes->next = NULL;
-		fmc->used_size += size;
-		fmc->free_size -= size;
-	}
-	else {
-		/* If there is no node, then this is just a chunk of dirt.  */
-		fmc->dirty_size += size;
-		fmc->free_size -= size;
-	}
-
-	if (fmc->head_extra) {
-		fm->prev = fmc->tail_extra;
-		fmc->tail_extra->next = fm;
-		fmc->tail_extra = fm;
-	}
-	else if (!fmc->head) {
-		fmc->head = fm;
-		fmc->tail = fm;
-	}
-	else if (fmc->tail->offset + fmc->tail->size < offset) {
-		fmc->head_extra = fm;
-		fmc->tail_extra = fm;
-	}
-	else {
-		fm->prev = fmc->tail;
-		fmc->tail->next = fm;
-		fmc->tail = fm;
-	}
-	D3(jffs_print_fmcontrol(fmc));
-	D3(jffs_print_fm(fm));
-	return fm;
-}
-
-
-/* Add a new node to an already existing jffs_fm struct.  */
-int
-jffs_add_node(struct jffs_node *node)
-{
-	struct jffs_node_ref *ref;
-
-	D3(printk("jffs_add_node(): ino = %u\n", node->ino));
-
-	ref = kmalloc(sizeof(*ref), GFP_KERNEL);
-	if (!ref)
-		return -ENOMEM;
-
-	DJM(no_jffs_node_ref++);
-	ref->node = node;
-	ref->next = node->fm->nodes;
-	node->fm->nodes = ref;
-	return 0;
-}
-
-
-/* Free a part of some allocated space.  */
-void
-jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, __u32 size)
-{
-	D1(printk("***jffs_fmfree_partly(): fm = 0x%p, fm->nodes = 0x%p, "
-		  "fm->nodes->node->ino = %u, size = %u\n",
-		  fm, (fm ? fm->nodes : 0),
-		  (!fm ? 0 : (!fm->nodes ? 0 : fm->nodes->node->ino)), size));
-
-	if (fm->nodes) {
-		kfree(fm->nodes);
-		DJM(no_jffs_node_ref--);
-		fm->nodes = NULL;
-	}
-	fmc->used_size -= fm->size;
-	if (fm == fmc->tail) {
-		fm->size -= size;
-		fmc->free_size += size;
-	}
-	fmc->dirty_size += fm->size;
-}
-
-
-/* Find the jffs_fm struct that contains the end of the data chunk that
-   begins at the logical beginning of the flash memory and spans `size'
-   bytes.  If we want to erase a sector of the flash memory, we use this
-   function to find where the sector limit cuts a chunk of data.  */
-struct jffs_fm *
-jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size)
-{
-	struct jffs_fm *fm;
-	__u32 pos = 0;
-
-	if (size == 0) {
-		return NULL;
-	}
-
-	ASSERT(if (!fmc) {
-		printk(KERN_ERR "jffs_cut_node(): fmc == NULL\n");
-		return NULL;
-	});
-
-	fm = fmc->head;
-
-	while (fm) {
-		pos += fm->size;
-		if (pos < size) {
-			fm = fm->next;
-		}
-		else if (pos > size) {
-			break;
-		}
-		else {
-			fm = NULL;
-			break;
-		}
-	}
-
-	return fm;
-}
-
-
-/* Move the head of the fmc structures and delete the obsolete parts.  */
-void
-jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size)
-{
-	struct jffs_fm *fm;
-	struct jffs_fm *del;
-
-	ASSERT(if (!fmc) {
-		printk(KERN_ERR "jffs_sync_erase(): fmc == NULL\n");
-		return;
-	});
-
-	fmc->dirty_size -= erased_size;
-	fmc->free_size += erased_size;
-
-	for (fm = fmc->head; fm && (erased_size > 0);) {
-		if (erased_size >= fm->size) {
-			erased_size -= fm->size;
-			del = fm;
-			fm = fm->next;
-			fm->prev = NULL;
-			fmc->head = fm;
-			jffs_free_fm(del);
-		}
-		else {
-			fm->size -= erased_size;
-			fm->offset += erased_size;
-			break;
-		}
-	}
-}
-
-
-/* Return the oldest used node in the flash memory.  */
-struct jffs_node *
-jffs_get_oldest_node(struct jffs_fmcontrol *fmc)
-{
-	struct jffs_fm *fm;
-	struct jffs_node_ref *nref;
-	struct jffs_node *node = NULL;
-
-	ASSERT(if (!fmc) {
-		printk(KERN_ERR "jffs_get_oldest_node(): fmc == NULL\n");
-		return NULL;
-	});
-
-	for (fm = fmc->head; fm && !fm->nodes; fm = fm->next);
-
-	if (!fm) {
-		return NULL;
-	}
-
-	/* The oldest node is the last one in the reference list.  This list
-	   shouldn't be too long; just one or perhaps two elements.  */
-	for (nref = fm->nodes; nref; nref = nref->next) {
-		node = nref->node;
-	}
-
-	D2(printk("jffs_get_oldest_node(): ino = %u, version = %u\n",
-		  (node ? node->ino : 0), (node ? node->version : 0)));
-
-	return node;
-}
-
-
-#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
-
-/* Mark an on-flash node as obsolete.
-
-   Note that this is just an optimization that isn't necessary for the
-   filesystem to work.  */
-
-static int
-jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset)
-{
-	/* The `accurate_pos' holds the position of the accurate byte
-	   in the jffs_raw_inode structure that we are going to mark
-	   as obsolete.  */
-	__u32 accurate_pos = fm_offset + JFFS_RAW_INODE_ACCURATE_OFFSET;
-	unsigned char zero = 0x00;
-	size_t len;
-
-	D3(printk("jffs_mark_obsolete(): accurate_pos = %u\n", accurate_pos));
-	ASSERT(if (!fmc) {
-		printk(KERN_ERR "jffs_mark_obsolete(): fmc == NULL\n");
-		return -1;
-	});
-
-	/* Write 0x00 to the raw inode's accurate member.  Don't care
-	   about the return value.  */
-	MTD_WRITE(fmc->mtd, accurate_pos, 1, &len, &zero);
-	return 0;
-}
-
-#endif /* JFFS_MARK_OBSOLETE  */
-
-/* check if it's possible to erase the wanted range, and if not, return
- * the range that IS erasable, or a negative error code.
- */
-static long
-jffs_flash_erasable_size(struct mtd_info *mtd, __u32 offset, __u32 size)
-{
-         u_long ssize;
-
-	/* assume that sector size for a partition is constant even
-	 * if it spans more than one chip (you usually put the same
-	 * type of chips in a system)
-	 */
-
-        ssize = mtd->erasesize;
-
-	if (offset % ssize) {
-		printk(KERN_WARNING "jffs_flash_erasable_size() given non-aligned offset %x (erasesize %lx)\n", offset, ssize);
-		/* The offset is not sector size aligned.  */
-		return -1;
-	}
-	else if (offset > mtd->size) {
-		printk(KERN_WARNING "jffs_flash_erasable_size given offset off the end of device (%x > %x)\n", offset, mtd->size);
-		return -2;
-	}
-	else if (offset + size > mtd->size) {
-		printk(KERN_WARNING "jffs_flash_erasable_size() given length which runs off the end of device (ofs %x + len %x = %x, > %x)\n", offset,size, offset+size, mtd->size);
-		return -3;
-	}
-
-	return (size / ssize) * ssize;
-}
-
-
-/* How much dirty flash memory is possible to erase at the moment?  */
-long
-jffs_erasable_size(struct jffs_fmcontrol *fmc)
-{
-	struct jffs_fm *fm;
-	__u32 size = 0;
-	long ret;
-
-	ASSERT(if (!fmc) {
-		printk(KERN_ERR "jffs_erasable_size(): fmc = NULL\n");
-		return -1;
-	});
-
-	if (!fmc->head) {
-		/* The flash memory is totally empty. No nodes. No dirt.
-		   Just return.  */
-		return 0;
-	}
-
-	/* Calculate how much space that is dirty.  */
-	for (fm = fmc->head; fm && !fm->nodes; fm = fm->next) {
-		if (size && fm->offset == 0) {
-			/* We have reached the beginning of the flash.  */
-			break;
-		}
-		size += fm->size;
-	}
-
-	/* Someone's signature contained this:
-	   There's a fine line between fishing and just standing on
-	   the shore like an idiot...  */
-	ret = jffs_flash_erasable_size(fmc->mtd, fmc->head->offset, size);
-
-	ASSERT(if (ret < 0) {
-		printk("jffs_erasable_size: flash_erasable_size() "
-		       "returned something less than zero (%ld).\n", ret);
-		printk("jffs_erasable_size: offset = 0x%08x\n",
-		       fmc->head->offset);
-	});
-
-	/* If there is dirt on the flash (which is the reason to why
-	   this function was called in the first place) but no space is
-	   possible to erase right now, the initial part of the list of
-	   jffs_fm structs, that hold place for dirty space, could perhaps
-	   be shortened.  The list's initial "dirty" elements are merged
-	   into just one large dirty jffs_fm struct.  This operation must
-	   only be performed if nothing is possible to erase.  Otherwise,
-	   jffs_clear_end_of_node() won't work as expected.  */
-	if (ret == 0) {
-		struct jffs_fm *head = fmc->head;
-		struct jffs_fm *del;
-		/* While there are two dirty nodes beside each other.*/
-		while (head->nodes == 0
-		       && head->next
-		       && head->next->nodes == 0) {
-			del = head->next;
-			head->size += del->size;
-			head->next = del->next;
-			if (del->next) {
-				del->next->prev = head;
-			}
-			jffs_free_fm(del);
-		}
-	}
-
-	return (ret >= 0 ? ret : 0);
-}
-
-static struct jffs_fm *jffs_alloc_fm(void)
-{
-	struct jffs_fm *fm;
-
-	fm = kmem_cache_alloc(fm_cache,GFP_KERNEL);
-	DJM(if (fm) no_jffs_fm++;);
-	
-	return fm;
-}
-
-static void jffs_free_fm(struct jffs_fm *n)
-{
-	kmem_cache_free(fm_cache,n);
-	DJM(no_jffs_fm--);
-}
-
-
-
-struct jffs_node *jffs_alloc_node(void)
-{
-	struct jffs_node *n;
-
-	n = (struct jffs_node *)kmem_cache_alloc(node_cache,GFP_KERNEL);
-	if(n != NULL)
-		no_jffs_node++;
-	return n;
-}
-
-void jffs_free_node(struct jffs_node *n)
-{
-	kmem_cache_free(node_cache,n);
-	no_jffs_node--;
-}
-
-
-int jffs_get_node_inuse(void)
-{
-	return no_jffs_node;
-}
diff --git a/fs/jffs/jffs_fm.h b/fs/jffs/jffs_fm.h
deleted file mode 100644
index 9ee6ad2..0000000
--- a/fs/jffs/jffs_fm.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This 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.
- *
- * $Id: jffs_fm.h,v 1.13 2001/01/11 12:03:25 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-
-#ifndef __LINUX_JFFS_FM_H__
-#define __LINUX_JFFS_FM_H__
-
-#include <linux/types.h>
-#include <linux/jffs.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mutex.h>
-
-/* The alignment between two nodes in the flash memory.  */
-#define JFFS_ALIGN_SIZE 4
-
-/* Mark the on-flash space as obsolete when appropriate.  */
-#define JFFS_MARK_OBSOLETE 0
-
-#ifndef CONFIG_JFFS_FS_VERBOSE
-#define CONFIG_JFFS_FS_VERBOSE 1
-#endif
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-#define D(x) x
-#define D1(x) D(x)
-#else
-#define D(x)
-#define D1(x)
-#endif
-
-#if CONFIG_JFFS_FS_VERBOSE > 1
-#define D2(x) D(x)
-#else
-#define D2(x)
-#endif
-
-#if CONFIG_JFFS_FS_VERBOSE > 2
-#define D3(x) D(x)
-#else
-#define D3(x)
-#endif
-
-#define ASSERT(x) x
-
-/* How many padding bytes should be inserted between two chunks of data
-   on the flash?  */
-#define JFFS_GET_PAD_BYTES(size) ( (JFFS_ALIGN_SIZE-1) & -(__u32)(size) )
-#define JFFS_PAD(size) ( (size + (JFFS_ALIGN_SIZE-1)) & ~(JFFS_ALIGN_SIZE-1) )
-
-
-
-struct jffs_node_ref
-{
-	struct jffs_node *node;
-	struct jffs_node_ref *next;
-};
-
-
-/* The struct jffs_fm represents a chunk of data in the flash memory.  */
-struct jffs_fm
-{
-	__u32 offset;
-	__u32 size;
-	struct jffs_fm *prev;
-	struct jffs_fm *next;
-	struct jffs_node_ref *nodes; /* USED if != 0.  */
-};
-
-struct jffs_fmcontrol
-{
-	__u32 flash_size;
-	__u32 used_size;
-	__u32 dirty_size;
-	__u32 free_size;
-	__u32 sector_size;
-	__u32 min_free_size;  /* The minimum free space needed to be able
-				 to perform garbage collections.  */
-	__u32 max_chunk_size; /* The maximum size of a chunk of data.  */
-	struct mtd_info *mtd;
-	struct jffs_control *c;
-	struct jffs_fm *head;
-	struct jffs_fm *tail;
-	struct jffs_fm *head_extra;
-	struct jffs_fm *tail_extra;
-	struct mutex biglock;
-};
-
-/* Notice the two members head_extra and tail_extra in the jffs_control
-   structure above. Those are only used during the scanning of the flash
-   memory; while the file system is being built. If the data in the flash
-   memory is organized like
-
-      +----------------+------------------+----------------+
-      |  USED / DIRTY  |       FREE       |  USED / DIRTY  |
-      +----------------+------------------+----------------+
-
-   then the scan is split in two parts. The first scanned part of the
-   flash memory is organized through the members head and tail. The
-   second scanned part is organized with head_extra and tail_extra. When
-   the scan is completed, the two lists are merged together. The jffs_fm
-   struct that head_extra references is the logical beginning of the
-   flash memory so it will be referenced by the head member.  */
-
-
-
-struct jffs_fmcontrol *jffs_build_begin(struct jffs_control *c, int unit);
-void jffs_build_end(struct jffs_fmcontrol *fmc);
-void jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc);
-
-int jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size,
-		 struct jffs_node *node, struct jffs_fm **result);
-int jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
-		struct jffs_node *node);
-
-__u32 jffs_free_size1(struct jffs_fmcontrol *fmc);
-__u32 jffs_free_size2(struct jffs_fmcontrol *fmc);
-void jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size);
-struct jffs_fm *jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size);
-struct jffs_node *jffs_get_oldest_node(struct jffs_fmcontrol *fmc);
-long jffs_erasable_size(struct jffs_fmcontrol *fmc);
-struct jffs_fm *jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset,
-			       __u32 size, struct jffs_node *node);
-int jffs_add_node(struct jffs_node *node);
-void jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
-			__u32 size);
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-void jffs_print_fmcontrol(struct jffs_fmcontrol *fmc);
-#endif
-#if 0
-void jffs_print_node_ref(struct jffs_node_ref *ref);
-#endif  /*  0  */
-
-#endif /* __LINUX_JFFS_FM_H__  */
diff --git a/fs/jffs/jffs_proc.c b/fs/jffs/jffs_proc.c
deleted file mode 100644
index 9bdd99a..0000000
--- a/fs/jffs/jffs_proc.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 2000  Axis Communications AB.
- *
- * Created by Simon Kagstrom <simonk@axis.com>.
- *
- * $Id: jffs_proc.c,v 1.5 2001/06/02 14:34:55 dwmw2 Exp $
- *
- * This 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.
- *
- *  Overview:
- *   This file defines JFFS partition entries in the proc file system.
- *
- *  TODO:
- *   Create some more proc files for different kinds of info, i.e. statistics
- *   about written and read bytes, number of calls to different routines,
- *   reports about failures.
- */
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/jffs.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/time.h>
-#include <linux/types.h>
-#include "jffs_fm.h"
-#include "jffs_proc.h"
-
-/*
- * Structure for a JFFS partition in the system
- */
-struct jffs_partition_dir {
-	struct jffs_control *c;
-	struct proc_dir_entry *part_root;
-	struct proc_dir_entry *part_info;
-	struct proc_dir_entry *part_layout;
-	struct jffs_partition_dir *next;
-};
-
-/*
- * Structure for top-level entry in '/proc/fs' directory
- */
-struct proc_dir_entry *jffs_proc_root;
-
-/*
- * Linked list of 'jffs_partition_dirs' to help us track
- * the mounted JFFS partitions in the system
- */
-static struct jffs_partition_dir *jffs_part_dirs;
-
-/*
- * Read functions for entries
- */
-static int jffs_proc_info_read(char *page, char **start, off_t off,
-		int count, int *eof, void *data);
-static int jffs_proc_layout_read (char *page, char **start, off_t off,
-		int count, int *eof, void *data);
-
-
-/*
- * Register a JFFS partition directory (called upon mount)
- */
-int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c)
-{
-	struct jffs_partition_dir *part_dir;
-	struct proc_dir_entry *part_info = NULL;
-	struct proc_dir_entry *part_layout = NULL;
-	struct proc_dir_entry *part_root = NULL;
-	char name[10];
-
-	sprintf(name, "%d", mtd);
-	/* Allocate structure for local JFFS partition table */
-	part_dir = (struct jffs_partition_dir *)
-		kmalloc(sizeof (struct jffs_partition_dir), GFP_KERNEL);
-	if (!part_dir)
-		goto out;
-
-	/* Create entry for this partition */
-	part_root = proc_mkdir(name, jffs_proc_root);
-	if (!part_root)
-		goto out1;
-
-	/* Create entry for 'info' file */
-	part_info = create_proc_entry ("info", 0, part_root);
-	if (!part_info)
-		goto out2;
-	part_info->read_proc = jffs_proc_info_read;
-	part_info->data = (void *) c;
-
-	/* Create entry for 'layout' file */
-	part_layout = create_proc_entry ("layout", 0, part_root);
-	if (!part_layout)
-		goto out3;
-	part_layout->read_proc = jffs_proc_layout_read;
-	part_layout->data = (void *) c;
-
-	/* Fill in structure for table and insert in the list */
-	part_dir->c = c;
-	part_dir->part_root = part_root;
-	part_dir->part_info = part_info;
-	part_dir->part_layout = part_layout;
-	part_dir->next = jffs_part_dirs;
-	jffs_part_dirs = part_dir;
-
-	/* Return happy */
-	return 0;
-
-out3:
-	remove_proc_entry("info", part_root);
-out2:
-	remove_proc_entry(name, jffs_proc_root);
-out1:
-	kfree(part_dir);
-out:
-	return -ENOMEM;
-}
-
-
-/*
- * Unregister a JFFS partition directory (called at umount)
- */
-int jffs_unregister_jffs_proc_dir(struct jffs_control *c)
-{
-	struct jffs_partition_dir *part_dir = jffs_part_dirs;
-	struct jffs_partition_dir *prev_part_dir = NULL;
-
-	while (part_dir) {
-		if (part_dir->c == c) {
-			/* Remove entries for partition */
-			remove_proc_entry (part_dir->part_info->name,
-				part_dir->part_root);
-			remove_proc_entry (part_dir->part_layout->name,
-				part_dir->part_root);
-			remove_proc_entry (part_dir->part_root->name,
-				jffs_proc_root);
-
-			/* Remove entry from list */
-			if (prev_part_dir)
-				prev_part_dir->next = part_dir->next;
-			else
-				jffs_part_dirs = part_dir->next;
-
-			/*
-			 * Check to see if this is the last one
-			 * and remove the entry from '/proc/fs'
-			 * if it is.
-			 */
-			if (jffs_part_dirs == part_dir->next)
-				remove_proc_entry ("jffs", proc_root_fs);
-
-			/* Free memory for entry */
-			kfree(part_dir);
-
-			/* Return happy */
-			return 0;
-		}
-
-		/* Move to next entry */
-		prev_part_dir = part_dir;
-		part_dir = part_dir->next;
-	}
-
-	/* Return unhappy */
-	return -1;
-}
-
-
-/*
- * Read a JFFS partition's `info' file
- */
-static int jffs_proc_info_read (char *page, char **start, off_t off,
-		int count, int *eof, void *data)
-{
-	struct jffs_control *c = (struct jffs_control *) data;
-	int len = 0;
-
-	/* Get information on the parition */
-	len += sprintf (page,
-		"partition size:     %08lX (%u)\n"
-		"sector size:        %08lX (%u)\n"
-		"used size:          %08lX (%u)\n"
-		"dirty size:         %08lX (%u)\n"
-		"free size:          %08lX (%u)\n\n",
-		(unsigned long) c->fmc->flash_size, c->fmc->flash_size,
-		(unsigned long) c->fmc->sector_size, c->fmc->sector_size,
-		(unsigned long) c->fmc->used_size, c->fmc->used_size,
-		(unsigned long) c->fmc->dirty_size, c->fmc->dirty_size,
-		(unsigned long) (c->fmc->flash_size -
-			(c->fmc->used_size + c->fmc->dirty_size)),
-		c->fmc->flash_size - (c->fmc->used_size + c->fmc->dirty_size));
-
-	/* We're done */
-	*eof = 1;
-
-	/* Return length */
-	return len;
-}
-
-
-/*
- * Read a JFFS partition's `layout' file
- */
-static int jffs_proc_layout_read (char *page, char **start, off_t off,
-		int count, int *eof, void *data)
-{
-	struct jffs_control *c = (struct jffs_control *) data;
-	struct jffs_fm *fm = NULL;
-	struct jffs_fm *last_fm = NULL;
-	int len = 0;
-
-	/* Get the first item in the list */
- 	fm = c->fmc->head;
-
-	/* Print free space */
-	if (fm && fm->offset) {
-		len += sprintf (page, "00000000 %08lX free\n",
-			(unsigned long) fm->offset);
-	}
-
-	/* Loop through all of the flash control structures */
-	while (fm && (len < (off + count))) {
-		if (fm->nodes) {
-			len += sprintf (page + len,
-				"%08lX %08lX ino=%08lX, ver=%08lX\n",
-				(unsigned long) fm->offset,
-				(unsigned long) fm->size,
-				(unsigned long) fm->nodes->node->ino,
-				(unsigned long) fm->nodes->node->version);
-		}
-		else {
-			len += sprintf (page + len,
-				"%08lX %08lX dirty\n",
-				(unsigned long) fm->offset,
-				(unsigned long) fm->size);
-		}
-		last_fm = fm;
-		fm = fm->next;
-	}
-
-	/* Print free space */
-	if ((len < (off + count)) && last_fm
-	    && (last_fm->offset < c->fmc->flash_size)) {
-		len += sprintf (page + len,
-			       "%08lX %08lX free\n",
-			       (unsigned long) last_fm->offset + 
-				last_fm->size,
-			       (unsigned long) (c->fmc->flash_size -
-						    (last_fm->offset + last_fm->size)));
-	}
-
-	/* We're done */
-	*eof = 1;
-
-	/* Return length */
-	return len;
-}
diff --git a/fs/jffs/jffs_proc.h b/fs/jffs/jffs_proc.h
deleted file mode 100644
index 39a1c5d..0000000
--- a/fs/jffs/jffs_proc.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 2000  Axis Communications AB.
- *
- * Created by Simon Kagstrom <simonk@axis.com>.
- *
- * This 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.
- *
- * $Id: jffs_proc.h,v 1.2 2000/11/15 22:04:12 sjhill Exp $
- */
-
-/* jffs_proc.h defines a structure for inclusion in the proc-file system.  */
-#ifndef __LINUX_JFFS_PROC_H__
-#define __LINUX_JFFS_PROC_H__
-
-#include <linux/proc_fs.h>
-
-/* The proc_dir_entry for jffs (defined in jffs_proc.c).  */
-extern struct proc_dir_entry *jffs_proc_root;
-
-int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c);
-int jffs_unregister_jffs_proc_dir(struct jffs_control *c);
-
-#endif /* __LINUX_JFFS_PROC_H__ */
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index 0282696..07119c4 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -348,23 +348,27 @@
 
 	ret = jffs2_sum_init(c);
 	if (ret)
-		return ret;
+		goto out_free;
 
 	if (jffs2_build_filesystem(c)) {
 		dbg_fsbuild("build_fs failed\n");
 		jffs2_free_ino_caches(c);
 		jffs2_free_raw_node_refs(c);
-#ifndef __ECOS
-		if (jffs2_blocks_use_vmalloc(c))
-			vfree(c->blocks);
-		else
-#endif
-			kfree(c->blocks);
-
-		return -EIO;
+		ret = -EIO;
+		goto out_free;
 	}
 
 	jffs2_calc_trigger_levels(c);
 
 	return 0;
+
+ out_free:
+#ifndef __ECOS
+	if (jffs2_blocks_use_vmalloc(c))
+		vfree(c->blocks);
+	else
+#endif
+		kfree(c->blocks);
+
+	return ret;
 }
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
index 3681d07..0c1fc6e 100644
--- a/fs/jffs2/compr_zlib.c
+++ b/fs/jffs2/compr_zlib.c
@@ -16,7 +16,6 @@
 #endif
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/zlib.h>
 #include <linux/zutil.h>
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index da6034d..9fa2e27 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -13,7 +13,6 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/crc32.h>
 #include <linux/jffs2.h>
@@ -46,7 +45,7 @@
 };
 
 
-struct inode_operations jffs2_dir_inode_operations =
+const struct inode_operations jffs2_dir_inode_operations =
 {
 	.create =	jffs2_create,
 	.lookup =	jffs2_lookup,
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 242875f..e82eeaf 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -54,7 +54,7 @@
 
 /* jffs2_file_inode_operations */
 
-struct inode_operations jffs2_file_inode_operations =
+const struct inode_operations jffs2_file_inode_operations =
 {
 	.permission =	jffs2_permission,
 	.setattr =	jffs2_setattr,
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index b985949..ea88f69 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -98,20 +98,14 @@
 	uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
-	/* Write-behind buffer for NAND flash */
-	unsigned char *wbuf;
-	unsigned char *oobbuf;
+	unsigned char *wbuf; /* Write-behind buffer for NAND flash */
 	uint32_t wbuf_ofs;
 	uint32_t wbuf_len;
 	struct jffs2_inodirty *wbuf_inodes;
-
 	struct rw_semaphore wbuf_sem;	/* Protects the write buffer */
 
-	/* Information about out-of-band area usage... */
-	struct nand_ecclayout *ecclayout;
-	uint32_t badblock_pos;
-	uint32_t fsdata_pos;
-	uint32_t fsdata_len;
+	unsigned char *oobbuf;
+	int oobavail; /* How many bytes are available for JFFS2 in OOB */
 #endif
 
 	struct jffs2_summary *summary;		/* Summary information */
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 9f41fc0..e07a0ed 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -153,11 +153,11 @@
 
 /* dir.c */
 extern const struct file_operations jffs2_dir_operations;
-extern struct inode_operations jffs2_dir_inode_operations;
+extern const struct inode_operations jffs2_dir_inode_operations;
 
 /* file.c */
 extern const struct file_operations jffs2_file_operations;
-extern struct inode_operations jffs2_file_inode_operations;
+extern const struct inode_operations jffs2_file_inode_operations;
 extern const struct address_space_operations jffs2_file_address_operations;
 int jffs2_fsync(struct file *, struct dentry *, int);
 int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
@@ -166,7 +166,7 @@
 int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 
 /* symlink.c */
-extern struct inode_operations jffs2_symlink_inode_operations;
+extern const struct inode_operations jffs2_symlink_inode_operations;
 
 /* fs.c */
 int jffs2_setattr (struct dentry *, struct iattr *);
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 3af746e..31c1475 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -450,16 +450,20 @@
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 	if (jffs2_cleanmarker_oob(c)) {
-		int ret = jffs2_check_nand_cleanmarker(c, jeb);
+		int ret;
+
+		if (c->mtd->block_isbad(c->mtd, jeb->offset))
+			return BLK_STATE_BADBLOCK;
+
+		ret = jffs2_check_nand_cleanmarker(c, jeb);
 		D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d\n",ret));
+
 		/* Even if it's not found, we still scan to see
 		   if the block is empty. We use this information
 		   to decide whether to erase it or not. */
 		switch (ret) {
 		case 0:		cleanmarkerfound = 1; break;
 		case 1: 	break;
-		case 2: 	return BLK_STATE_BADBLOCK;
-		case 3:		return BLK_STATE_ALLDIRTY; /* Block has failed to erase min. once */
 		default: 	return ret;
 		}
 	}
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 2526596..30f8884 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -14,7 +14,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/pagemap.h>
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 08a0e6c..cc7e8e7 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -66,7 +66,7 @@
 	return 0;
 }
 
-static struct super_operations jffs2_super_operations =
+static const struct super_operations jffs2_super_operations =
 {
 	.alloc_inode =	jffs2_alloc_inode,
 	.destroy_inode =jffs2_destroy_inode,
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index b90d5aa..7e4882c 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -20,7 +20,7 @@
 
 static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd);
 
-struct inode_operations jffs2_symlink_inode_operations =
+const struct inode_operations jffs2_symlink_inode_operations =
 {
 	.readlink =	generic_readlink,
 	.follow_link =	jffs2_follow_link,
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 9c99859..de718e3 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -957,43 +957,48 @@
 	return ret;
 }
 
-#define NR_OOB_SCAN_PAGES	4
+#define NR_OOB_SCAN_PAGES 4
+
+/* For historical reasons we use only 12 bytes for OOB clean marker */
+#define OOB_CM_SIZE 12
+
+static const struct jffs2_unknown_node oob_cleanmarker =
+{
+	.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK),
+	.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
+	.totlen = cpu_to_je32(8)
+};
 
 /*
- * Check, if the out of band area is empty
+ * Check, if the out of band area is empty. This function knows about the clean
+ * marker and if it is present in OOB, treats the OOB as empty anyway.
  */
 int jffs2_check_oob_empty(struct jffs2_sb_info *c,
 			  struct jffs2_eraseblock *jeb, int mode)
 {
-	int i, page, ret;
-	int oobsize = c->mtd->oobsize;
+	int i, ret;
+	int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
 	struct mtd_oob_ops ops;
 
-	ops.ooblen = NR_OOB_SCAN_PAGES * oobsize;
+	ops.mode = MTD_OOB_AUTO;
+	ops.ooblen = NR_OOB_SCAN_PAGES * c->oobavail;
 	ops.oobbuf = c->oobbuf;
-	ops.ooboffs = 0;
+	ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
 	ops.datbuf = NULL;
-	ops.mode = MTD_OOB_PLACE;
 
 	ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops);
-	if (ret) {
-		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
-			  "failed %d for block at %08x\n", ret, jeb->offset));
+	if (ret || ops.oobretlen != ops.ooblen) {
+		printk(KERN_ERR "cannot read OOB for EB at %08x, requested %zd"
+				" bytes, read %zd bytes, error %d\n",
+				jeb->offset, ops.ooblen, ops.oobretlen, ret);
+		if (!ret)
+			ret = -EIO;
 		return ret;
 	}
 
-	if (ops.oobretlen < ops.ooblen) {
-		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
-			  "returned short read (%zd bytes not %d) for block "
-			  "at %08x\n", ops.oobretlen, ops.ooblen, jeb->offset));
-		return -EIO;
-	}
-
-	/* Special check for first page */
-	for(i = 0; i < oobsize ; i++) {
-		/* Yeah, we know about the cleanmarker. */
-		if (mode && i >= c->fsdata_pos &&
-		    i < c->fsdata_pos + c->fsdata_len)
+	for(i = 0; i < ops.ooblen; i++) {
+		if (mode && i < cmlen)
+			/* Yeah, we know about the cleanmarker */
 			continue;
 
 		if (ops.oobbuf[i] != 0xFF) {
@@ -1003,111 +1008,63 @@
 		}
 	}
 
-	/* we know, we are aligned :) */
-	for (page = oobsize; page < ops.ooblen; page += sizeof(long)) {
-		long dat = *(long *)(&ops.oobbuf[page]);
-		if(dat != -1)
-			return 1;
-	}
 	return 0;
 }
 
 /*
- * Scan for a valid cleanmarker and for bad blocks
+ * Check for a valid cleanmarker.
+ * Returns: 0 if a valid cleanmarker was found
+ *          1 if no cleanmarker was found
+ *          negative error code if an error occurred
  */
-int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c,
-				  struct jffs2_eraseblock *jeb)
+int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c,
+				 struct jffs2_eraseblock *jeb)
 {
-	struct jffs2_unknown_node n;
 	struct mtd_oob_ops ops;
-	int oobsize = c->mtd->oobsize;
-	unsigned char *p,*b;
-	int i, ret;
-	size_t offset = jeb->offset;
+	int ret, cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
 
-	/* Check first if the block is bad. */
-	if (c->mtd->block_isbad(c->mtd, offset)) {
-		D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker()"
-			   ": Bad block at %08x\n", jeb->offset));
-		return 2;
-	}
-
-	ops.ooblen = oobsize;
+	ops.mode = MTD_OOB_AUTO;
+	ops.ooblen = cmlen;
 	ops.oobbuf = c->oobbuf;
-	ops.ooboffs = 0;
+	ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
 	ops.datbuf = NULL;
-	ops.mode = MTD_OOB_PLACE;
 
-	ret = c->mtd->read_oob(c->mtd, offset, &ops);
-	if (ret) {
-		D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
-			   "Read OOB failed %d for block at %08x\n",
-			   ret, jeb->offset));
+	ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops);
+	if (ret || ops.oobretlen != ops.ooblen) {
+		printk(KERN_ERR "cannot read OOB for EB at %08x, requested %zd"
+				" bytes, read %zd bytes, error %d\n",
+				jeb->offset, ops.ooblen, ops.oobretlen, ret);
+		if (!ret)
+			ret = -EIO;
 		return ret;
 	}
 
-	if (ops.oobretlen < ops.ooblen) {
-		D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): "
-			    "Read OOB return short read (%zd bytes not %d) "
-			    "for block at %08x\n", ops.oobretlen, ops.ooblen,
-			    jeb->offset));
-		return -EIO;
-	}
-
-	n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
-	n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-	n.totlen = cpu_to_je32 (8);
-	p = (unsigned char *) &n;
-	b = c->oobbuf + c->fsdata_pos;
-
-	for (i = c->fsdata_len; i; i--) {
-		if (*b++ != *p++)
-			ret = 1;
-	}
-
-	D1(if (ret == 1) {
-		printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
-		       "Cleanmarker node not detected in block at %08x\n",
-		       offset);
-		printk(KERN_WARNING "OOB at %08zx was ", offset);
-		for (i=0; i < oobsize; i++)
-			printk("%02x ", c->oobbuf[i]);
-		printk("\n");
-	});
-	return ret;
+	return !!memcmp(&oob_cleanmarker, c->oobbuf, cmlen);
 }
 
 int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
 				 struct jffs2_eraseblock *jeb)
 {
-	struct jffs2_unknown_node n;
-	int	ret;
+	int ret;
 	struct mtd_oob_ops ops;
+	int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
 
-	n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
-	n.totlen = cpu_to_je32(8);
-
-	ops.ooblen = c->fsdata_len;
-	ops.oobbuf = (uint8_t *)&n;
-	ops.ooboffs = c->fsdata_pos;
+	ops.mode = MTD_OOB_AUTO;
+	ops.ooblen = cmlen;
+	ops.oobbuf = (uint8_t *)&oob_cleanmarker;
+	ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
 	ops.datbuf = NULL;
-	ops.mode = MTD_OOB_PLACE;
 
 	ret = c->mtd->write_oob(c->mtd, jeb->offset, &ops);
-
-	if (ret) {
-		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
-			  "Write failed for block at %08x: error %d\n",
-			  jeb->offset, ret));
+	if (ret || ops.oobretlen != ops.ooblen) {
+		printk(KERN_ERR "cannot write OOB for EB at %08x, requested %zd"
+				" bytes, read %zd bytes, error %d\n",
+				jeb->offset, ops.ooblen, ops.oobretlen, ret);
+		if (!ret)
+			ret = -EIO;
 		return ret;
 	}
-	if (ops.oobretlen != ops.ooblen) {
-		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
-			  "Short write for block at %08x: %zd not %d\n",
-			  jeb->offset, ops.oobretlen, ops.ooblen));
-		return -EIO;
-	}
+
 	return 0;
 }
 
@@ -1140,41 +1097,24 @@
 	return 1;
 }
 
-static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
+int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
 {
 	struct nand_ecclayout *oinfo = c->mtd->ecclayout;
 
-	/* Do this only, if we have an oob buffer */
 	if (!c->mtd->oobsize)
 		return 0;
 
 	/* Cleanmarker is out-of-band, so inline size zero */
 	c->cleanmarker_size = 0;
 
-	/* Should we use autoplacement ? */
-	if (!oinfo) {
-		D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
+	if (!oinfo || oinfo->oobavail == 0) {
+		printk(KERN_ERR "inconsistent device description\n");
 		return -EINVAL;
 	}
 
-	D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
-	/* Get the position of the free bytes */
-	if (!oinfo->oobfree[0].length) {
-		printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep."
-			" Autoplacement selected and no empty space in oob\n");
-		return -ENOSPC;
-	}
-	c->fsdata_pos = oinfo->oobfree[0].offset;
-	c->fsdata_len = oinfo->oobfree[0].length;
-	if (c->fsdata_len > 8)
-		c->fsdata_len = 8;
+	D1(printk(KERN_DEBUG "JFFS2 using OOB on NAND\n"));
 
-	return 0;
-}
-
-int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
-{
-	int res;
+	c->oobavail = oinfo->oobavail;
 
 	/* Initialise write buffer */
 	init_rwsem(&c->wbuf_sem);
@@ -1185,22 +1125,13 @@
 	if (!c->wbuf)
 		return -ENOMEM;
 
-	c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->mtd->oobsize, GFP_KERNEL);
-	if (!c->oobbuf)
-		return -ENOMEM;
-
-	res = jffs2_nand_set_oobinfo(c);
-
-#ifdef BREAKME
-	if (!brokenbuf)
-		brokenbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
-	if (!brokenbuf) {
+	c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->oobavail, GFP_KERNEL);
+	if (!c->oobbuf) {
 		kfree(c->wbuf);
 		return -ENOMEM;
 	}
-	memset(brokenbuf, 0xdb, c->wbuf_pagesize);
-#endif
-	return res;
+
+	return 0;
 }
 
 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index aa9132d..f7f8eff 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -88,7 +88,7 @@
 	return 0;
 }
 
-struct inode_operations jfs_file_inode_operations = {
+const struct inode_operations jfs_file_inode_operations = {
 	.truncate	= jfs_truncate,
 	.setxattr	= jfs_setxattr,
 	.getxattr	= jfs_getxattr,
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 0d06ccf..6802837 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -35,10 +35,10 @@
 extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern const struct address_space_operations jfs_aops;
-extern struct inode_operations jfs_dir_inode_operations;
+extern const struct inode_operations jfs_dir_inode_operations;
 extern const struct file_operations jfs_dir_operations;
-extern struct inode_operations jfs_file_inode_operations;
+extern const struct inode_operations jfs_file_inode_operations;
 extern const struct file_operations jfs_file_operations;
-extern struct inode_operations jfs_symlink_inode_operations;
+extern const struct inode_operations jfs_symlink_inode_operations;
 extern struct dentry_operations jfs_ci_dentry_operations;
 #endif				/* _H_JFS_INODE */
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 7ab4756..41c2047 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1503,7 +1503,7 @@
 	return parent;
 }
 
-struct inode_operations jfs_dir_inode_operations = {
+const struct inode_operations jfs_dir_inode_operations = {
 	.create		= jfs_create,
 	.lookup		= jfs_lookup,
 	.link		= jfs_link,
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 846ac8f..52d73d5 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -46,7 +46,7 @@
 
 static struct kmem_cache * jfs_inode_cachep;
 
-static struct super_operations jfs_super_operations;
+static const struct super_operations jfs_super_operations;
 static struct export_operations jfs_export_operations;
 static struct file_system_type jfs_fs_type;
 
@@ -716,7 +716,7 @@
 
 #endif
 
-static struct super_operations jfs_super_operations = {
+static const struct super_operations jfs_super_operations = {
 	.alloc_inode	= jfs_alloc_inode,
 	.destroy_inode	= jfs_destroy_inode,
 	.read_inode	= jfs_read_inode,
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c
index cee43f3..4af1a05 100644
--- a/fs/jfs/symlink.c
+++ b/fs/jfs/symlink.c
@@ -29,7 +29,7 @@
 	return NULL;
 }
 
-struct inode_operations jfs_symlink_inode_operations = {
+const struct inode_operations jfs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= jfs_follow_link,
 	.setxattr	= jfs_setxattr,
diff --git a/fs/libfs.c b/fs/libfs.c
index 503898d..cf79196 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -186,7 +186,7 @@
 	.fsync		= simple_sync_file,
 };
 
-struct inode_operations simple_dir_inode_operations = {
+const struct inode_operations simple_dir_inode_operations = {
 	.lookup		= simple_lookup,
 };
 
@@ -195,11 +195,11 @@
  * will never be mountable)
  */
 int get_sb_pseudo(struct file_system_type *fs_type, char *name,
-	struct super_operations *ops, unsigned long magic,
+	const struct super_operations *ops, unsigned long magic,
 	struct vfsmount *mnt)
 {
 	struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
-	static struct super_operations default_ops = {.statfs = simple_statfs};
+	static const struct super_operations default_ops = {.statfs = simple_statfs};
 	struct dentry *dentry;
 	struct inode *root;
 	struct qstr d_name = {.name = name, .len = strlen(name)};
@@ -335,17 +335,18 @@
 			flush_dcache_page(page);
 			kunmap_atomic(kaddr, KM_USER0);
 		}
-		SetPageUptodate(page);
 	}
 	return 0;
 }
 
 int simple_commit_write(struct file *file, struct page *page,
-			unsigned offset, unsigned to)
+			unsigned from, unsigned to)
 {
 	struct inode *inode = page->mapping->host;
 	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
+	if (!PageUptodate(page))
+		SetPageUptodate(page);
 	/*
 	 * No need to use i_size_read() here, the i_size
 	 * cannot change under us because we hold the i_mutex.
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 0b4acc1..a5c019e 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -361,7 +361,6 @@
 {
 	struct nlm_host	*host = req->a_host;
 	struct rpc_clnt	*clnt;
-	int status = -ENOLCK;
 
 	dprintk("lockd: call procedure %d on %s (async)\n",
 			(int)proc, host->h_name);
@@ -373,12 +372,10 @@
 	msg->rpc_proc = &clnt->cl_procinfo[proc];
 
         /* bootstrap and kick off the async RPC call */
-        status = rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req);
-	if (status == 0)
-		return 0;
+        return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req);
 out_err:
-	nlm_release_call(req);
-	return status;
+	tk_ops->rpc_release(req);
+	return -ENOLCK;
 }
 
 int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 3d4610c..ad21c07 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/sunrpc/clnt.h>
@@ -192,7 +191,7 @@
 nlmsvc_lookup_host(struct svc_rqst *rqstp,
 			const char *hostname, int hostname_len)
 {
-	return nlm_lookup_host(1, &rqstp->rq_addr,
+	return nlm_lookup_host(1, svc_addr_in(rqstp),
 			       rqstp->rq_prot, rqstp->rq_vers,
 			       hostname, hostname_len);
 }
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 8ca1808..126b1bf 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -141,6 +141,7 @@
 	 */
 	while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
 		long timeout = MAX_SCHEDULE_TIMEOUT;
+		char buf[RPC_MAX_ADDRBUFLEN];
 
 		if (signalled()) {
 			flush_signals(current);
@@ -175,11 +176,10 @@
 			break;
 		}
 
-		dprintk("lockd: request from %08x\n",
-			(unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
+		dprintk("lockd: request from %s\n",
+				svc_print_addr(rqstp, buf, sizeof(buf)));
 
 		svc_process(rqstp);
-
 	}
 
 	flush_signals(current);
@@ -223,23 +223,29 @@
 	return found;
 }
 
+/*
+ * Make any sockets that are needed but not present.
+ * If nlm_udpport or nlm_tcpport were set as module
+ * options, make those sockets unconditionally
+ */
 static int make_socks(struct svc_serv *serv, int proto)
 {
-	/* Make any sockets that are needed but not present.
-	 * If nlm_udpport or nlm_tcpport were set as module
-	 * options, make those sockets unconditionally
-	 */
-	static int		warned;
+	static int warned;
 	int err = 0;
+
 	if (proto == IPPROTO_UDP || nlm_udpport)
 		if (!find_socket(serv, IPPROTO_UDP))
-			err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport);
-	if (err == 0 && (proto == IPPROTO_TCP || nlm_tcpport))
+			err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport,
+						SVC_SOCK_DEFAULTS);
+	if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport))
 		if (!find_socket(serv, IPPROTO_TCP))
-			err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport);
-	if (!err)
+			err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport,
+						SVC_SOCK_DEFAULTS);
+
+	if (err >= 0) {
 		warned = 0;
-	else if (warned++ == 0)
+		err = 0;
+	} else if (warned++ == 0)
 		printk(KERN_WARNING
 		       "lockd_up: makesock failed, error=%d\n", err);
 	return err;
@@ -434,7 +440,7 @@
 };
 
 /*
- * Module (and driverfs) parameters.
+ * Module (and sysfs) parameters.
  */
 
 #define param_set_min_max(name, type, which_strtol, min, max)		\
@@ -506,7 +512,7 @@
 
 static int __init init_nlm(void)
 {
-	nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root, 0);
+	nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
 	return nlm_sysctl_table ? 0 : -ENOMEM;
 }
 
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index f67146a..47a66aa 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -224,7 +224,7 @@
 	resp->cookie = argp->cookie;
 
 	dprintk("lockd: GRANTED       called\n");
-	resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+	resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock);
 	dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
 	return rpc_success;
 }
@@ -421,15 +421,16 @@
 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
-	struct sockaddr_in	saddr = rqstp->rq_addr;
+	struct sockaddr_in	saddr;
+
+	memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
 
 	dprintk("lockd: SM_NOTIFY     called\n");
 	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
 	 || ntohs(saddr.sin_port) >= 1024) {
-		printk(KERN_WARNING
-			"lockd: rejected NSM callback from %08x:%d\n",
-			ntohl(rqstp->rq_addr.sin_addr.s_addr),
-			ntohs(rqstp->rq_addr.sin_port));
+		char buf[RPC_MAX_ADDRBUFLEN];
+		printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
+				svc_print_addr(rqstp, buf, sizeof(buf)));
 		return rpc_system_err;
 	}
 
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index c7db0a5..cf51f84 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -593,9 +593,7 @@
 
 	/* Call the client */
 	kref_get(&block->b_count);
-	if (nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG,
-						&nlmsvc_grant_ops) < 0)
-		nlmsvc_release_block(block);
+	nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops);
 }
 
 /*
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 3707c3a..31cb484 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -253,7 +253,7 @@
 	resp->cookie = argp->cookie;
 
 	dprintk("lockd: GRANTED       called\n");
-	resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+	resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock);
 	dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
 	return rpc_success;
 }
@@ -452,15 +452,16 @@
 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
-	struct sockaddr_in	saddr = rqstp->rq_addr;
+	struct sockaddr_in	saddr;
+
+	memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
 
 	dprintk("lockd: SM_NOTIFY     called\n");
 	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
 	 || ntohs(saddr.sin_port) >= 1024) {
-		printk(KERN_WARNING
-			"lockd: rejected NSM callback from %08x:%d\n",
-			ntohl(rqstp->rq_addr.sin_addr.s_addr),
-			ntohs(rqstp->rq_addr.sin_port));
+		char buf[RPC_MAX_ADDRBUFLEN];
+		printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
+				svc_print_addr(rqstp, buf, sizeof(buf)));
 		return rpc_system_err;
 	}
 
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index df6b107..c4a554d 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -26,14 +26,14 @@
 	for (i=0; i<numblocks-1; i++) {
 		if (!(bh=map[i])) 
 			return(0);
-		for (j=0; j<BLOCK_SIZE; j++)
+		for (j=0; j<bh->b_size; j++)
 			sum += nibblemap[bh->b_data[j] & 0xf]
 				+ nibblemap[(bh->b_data[j]>>4) & 0xf];
 	}
 
 	if (numblocks==0 || !(bh=map[numblocks-1]))
 		return(0);
-	i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2;
+	i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2;
 	for (j=0; j<i; j++) {
 		sum += nibblemap[bh->b_data[j] & 0xf]
 			+ nibblemap[(bh->b_data[j]>>4) & 0xf];
@@ -48,28 +48,29 @@
 	return(sum);
 }
 
-void minix_free_block(struct inode * inode, int block)
+void minix_free_block(struct inode *inode, unsigned long block)
 {
-	struct super_block * sb = inode->i_sb;
-	struct minix_sb_info * sbi = minix_sb(sb);
-	struct buffer_head * bh;
-	unsigned int bit,zone;
+	struct super_block *sb = inode->i_sb;
+	struct minix_sb_info *sbi = minix_sb(sb);
+	struct buffer_head *bh;
+	int k = sb->s_blocksize_bits + 3;
+	unsigned long bit, zone;
 
 	if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
 		printk("Trying to free block not in datazone\n");
 		return;
 	}
 	zone = block - sbi->s_firstdatazone + 1;
-	bit = zone & 8191;
-	zone >>= 13;
+	bit = zone & ((1<<k) - 1);
+	zone >>= k;
 	if (zone >= sbi->s_zmap_blocks) {
 		printk("minix_free_block: nonexistent bitmap buffer\n");
 		return;
 	}
 	bh = sbi->s_zmap[zone];
 	lock_kernel();
-	if (!minix_test_and_clear_bit(bit,bh->b_data))
-		printk("free_block (%s:%d): bit already cleared\n",
+	if (!minix_test_and_clear_bit(bit, bh->b_data))
+		printk("minix_free_block (%s:%lu): bit already cleared\n",
 		       sb->s_id, block);
 	unlock_kernel();
 	mark_buffer_dirty(bh);
@@ -79,6 +80,7 @@
 int minix_new_block(struct inode * inode)
 {
 	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
+	int bits_per_zone = 8 * inode->i_sb->s_blocksize;
 	int i;
 
 	for (i = 0; i < sbi->s_zmap_blocks; i++) {
@@ -86,11 +88,12 @@
 		int j;
 
 		lock_kernel();
-		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) {
-			minix_set_bit(j,bh->b_data);
+		j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
+		if (j < bits_per_zone) {
+			minix_set_bit(j, bh->b_data);
 			unlock_kernel();
 			mark_buffer_dirty(bh);
-			j += i*8192 + sbi->s_firstdatazone-1;
+			j += i * bits_per_zone + sbi->s_firstdatazone-1;
 			if (j < sbi->s_firstdatazone || j >= sbi->s_nzones)
 				break;
 			return j;
@@ -137,6 +140,7 @@
 	int block;
 	struct minix_sb_info *sbi = minix_sb(sb);
 	struct minix2_inode *p;
+	int minix2_inodes_per_block = sb->s_blocksize / sizeof(struct minix2_inode);
 
 	*bh = NULL;
 	if (!ino || ino > sbi->s_ninodes) {
@@ -146,14 +150,14 @@
 	}
 	ino--;
 	block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
-		 ino / MINIX2_INODES_PER_BLOCK;
+		 ino / minix2_inodes_per_block;
 	*bh = sb_bread(sb, block);
 	if (!*bh) {
 		printk("Unable to read inode block\n");
 		return NULL;
 	}
 	p = (void *)(*bh)->b_data;
-	return p + ino % MINIX2_INODES_PER_BLOCK;
+	return p + ino % minix2_inodes_per_block;
 }
 
 /* Clear the link count and mode of a deleted inode on disk. */
@@ -185,26 +189,30 @@
 
 void minix_free_inode(struct inode * inode)
 {
+	struct super_block *sb = inode->i_sb;
 	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
-	struct buffer_head * bh;
-	unsigned long ino;
+	struct buffer_head *bh;
+	int k = sb->s_blocksize_bits + 3;
+	unsigned long ino, bit;
 
 	ino = inode->i_ino;
 	if (ino < 1 || ino > sbi->s_ninodes) {
 		printk("minix_free_inode: inode 0 or nonexistent inode\n");
 		goto out;
 	}
-	if ((ino >> 13) >= sbi->s_imap_blocks) {
+	bit = ino & ((1<<k) - 1);
+	ino >>= k;
+	if (ino >= sbi->s_imap_blocks) {
 		printk("minix_free_inode: nonexistent imap in superblock\n");
 		goto out;
 	}
 
 	minix_clear_inode(inode);	/* clear on-disk copy */
 
-	bh = sbi->s_imap[ino >> 13];
+	bh = sbi->s_imap[ino];
 	lock_kernel();
-	if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
-		printk("minix_free_inode: bit %lu already cleared\n", ino);
+	if (!minix_test_and_clear_bit(bit, bh->b_data))
+		printk("minix_free_inode: bit %lu already cleared\n", bit);
 	unlock_kernel();
 	mark_buffer_dirty(bh);
  out:
@@ -217,35 +225,38 @@
 	struct minix_sb_info *sbi = minix_sb(sb);
 	struct inode *inode = new_inode(sb);
 	struct buffer_head * bh;
-	int i,j;
+	int bits_per_zone = 8 * sb->s_blocksize;
+	unsigned long j;
+	int i;
 
 	if (!inode) {
 		*error = -ENOMEM;
 		return NULL;
 	}
-	j = 8192;
+	j = bits_per_zone;
 	bh = NULL;
 	*error = -ENOSPC;
 	lock_kernel();
 	for (i = 0; i < sbi->s_imap_blocks; i++) {
 		bh = sbi->s_imap[i];
-		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
+		j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
+		if (j < bits_per_zone)
 			break;
 	}
-	if (!bh || j >= 8192) {
+	if (!bh || j >= bits_per_zone) {
 		unlock_kernel();
 		iput(inode);
 		return NULL;
 	}
-	if (minix_test_and_set_bit(j,bh->b_data)) {	/* shouldn't happen */
-		printk("new_inode: bit already set\n");
+	if (minix_test_and_set_bit(j, bh->b_data)) {	/* shouldn't happen */
 		unlock_kernel();
+		printk("minix_new_inode: bit already set\n");
 		iput(inode);
 		return NULL;
 	}
 	unlock_kernel();
 	mark_buffer_dirty(bh);
-	j += i*8192;
+	j += i * bits_per_zone;
 	if (!j || j > sbi->s_ninodes) {
 		iput(inode);
 		return NULL;
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index ab782c4..cb4cb57 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -4,6 +4,8 @@
  *  Copyright (C) 1991, 1992 Linus Torvalds
  *
  *  minix directory handling functions
+ *
+ *  Updated to filesystem version 3 by Daniel Aragones
  */
 
 #include "minix.h"
@@ -11,6 +13,7 @@
 #include <linux/smp_lock.h>
 
 typedef struct minix_dir_entry minix_dirent;
+typedef struct minix3_dir_entry minix3_dirent;
 
 static int minix_readdir(struct file *, void *, filldir_t);
 
@@ -89,6 +92,8 @@
 	unsigned long npages = dir_pages(inode);
 	struct minix_sb_info *sbi = minix_sb(sb);
 	unsigned chunk_size = sbi->s_dirsize;
+	char *name;
+	__u32 inumber;
 
 	lock_kernel();
 
@@ -105,16 +110,24 @@
 		kaddr = (char *)page_address(page);
 		p = kaddr+offset;
 		limit = kaddr + minix_last_byte(inode, n) - chunk_size;
-		for ( ; p <= limit ; p = minix_next_entry(p, sbi)) {
-			minix_dirent *de = (minix_dirent *)p;
-			if (de->inode) {
+		for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
+			if (sbi->s_version == MINIX_V3) {
+				minix3_dirent *de3 = (minix3_dirent *)p;
+				name = de3->name;
+				inumber = de3->inode;
+	 		} else {
+				minix_dirent *de = (minix_dirent *)p;
+				name = de->name;
+				inumber = de->inode;
+			}
+			if (inumber) {
 				int over;
-				unsigned l = strnlen(de->name,sbi->s_namelen);
 
+				unsigned l = strnlen(name, sbi->s_namelen);
 				offset = p - kaddr;
-				over = filldir(dirent, de->name, l,
-						(n<<PAGE_CACHE_SHIFT) | offset,
-						de->inode, DT_UNKNOWN);
+				over = filldir(dirent, name, l,
+					(n << PAGE_CACHE_SHIFT) | offset,
+					inumber, DT_UNKNOWN);
 				if (over) {
 					dir_put_page(page);
 					goto done;
@@ -156,23 +169,34 @@
 	unsigned long n;
 	unsigned long npages = dir_pages(dir);
 	struct page *page = NULL;
-	struct minix_dir_entry *de;
+	char *p;
 
+	char *namx;
+	__u32 inumber;
 	*res_page = NULL;
 
 	for (n = 0; n < npages; n++) {
-		char *kaddr;
+		char *kaddr, *limit;
+
 		page = dir_get_page(dir, n);
 		if (IS_ERR(page))
 			continue;
 
 		kaddr = (char*)page_address(page);
-		de = (struct minix_dir_entry *) kaddr;
-		kaddr += minix_last_byte(dir, n) - sbi->s_dirsize;
-		for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) {
-			if (!de->inode)
+		limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize;
+		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+			if (sbi->s_version == MINIX_V3) {
+				minix3_dirent *de3 = (minix3_dirent *)p;
+				namx = de3->name;
+				inumber = de3->inode;
+ 			} else {
+				minix_dirent *de = (minix_dirent *)p;
+				namx = de->name;
+				inumber = de->inode;
+			}
+			if (!inumber)
 				continue;
-			if (namecompare(namelen,sbi->s_namelen,name,de->name))
+			if (namecompare(namelen, sbi->s_namelen, name, namx))
 				goto found;
 		}
 		dir_put_page(page);
@@ -181,7 +205,7 @@
 
 found:
 	*res_page = page;
-	return de;
+	return (minix_dirent *)p;
 }
 
 int minix_add_link(struct dentry *dentry, struct inode *inode)
@@ -192,12 +216,15 @@
 	struct super_block * sb = dir->i_sb;
 	struct minix_sb_info * sbi = minix_sb(sb);
 	struct page *page = NULL;
-	struct minix_dir_entry * de;
 	unsigned long npages = dir_pages(dir);
 	unsigned long n;
-	char *kaddr;
+	char *kaddr, *p;
+	minix_dirent *de;
+	minix3_dirent *de3;
 	unsigned from, to;
 	int err;
+	char *namx = NULL;
+	__u32 inumber;
 
 	/*
 	 * We take care of directory expansion in the same loop
@@ -205,7 +232,7 @@
 	 * to protect that region.
 	 */
 	for (n = 0; n <= npages; n++) {
-		char *dir_end;
+		char *limit, *dir_end;
 
 		page = dir_get_page(dir, n);
 		err = PTR_ERR(page);
@@ -214,20 +241,30 @@
 		lock_page(page);
 		kaddr = (char*)page_address(page);
 		dir_end = kaddr + minix_last_byte(dir, n);
-		de = (minix_dirent *)kaddr;
-		kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
-		while ((char *)de <= kaddr) {
-			if ((char *)de == dir_end) {
+		limit = kaddr + PAGE_CACHE_SIZE - sbi->s_dirsize;
+		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+			de = (minix_dirent *)p;
+			de3 = (minix3_dirent *)p;
+			if (sbi->s_version == MINIX_V3) {
+				namx = de3->name;
+				inumber = de3->inode;
+		 	} else {
+  				namx = de->name;
+				inumber = de->inode;
+			}
+			if (p == dir_end) {
 				/* We hit i_size */
-				de->inode = 0;
+				if (sbi->s_version == MINIX_V3)
+					de3->inode = 0;
+		 		else
+					de->inode = 0;
 				goto got_it;
 			}
-			if (!de->inode)
+			if (!inumber)
 				goto got_it;
 			err = -EEXIST;
-			if (namecompare(namelen,sbi->s_namelen,name,de->name))
+			if (namecompare(namelen, sbi->s_namelen, name, namx))
 				goto out_unlock;
-			de = minix_next_entry(de, sbi);
 		}
 		unlock_page(page);
 		dir_put_page(page);
@@ -236,14 +273,19 @@
 	return -EINVAL;
 
 got_it:
-	from = (char*)de - (char*)page_address(page);
+	from = p - (char*)page_address(page);
 	to = from + sbi->s_dirsize;
 	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
 	if (err)
 		goto out_unlock;
-	memcpy (de->name, name, namelen);
-	memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2);
-	de->inode = inode->i_ino;
+	memcpy (namx, name, namelen);
+	if (sbi->s_version == MINIX_V3) {
+		memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4);
+		de3->inode = inode->i_ino;
+	} else {
+		memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
+		de->inode = inode->i_ino;
+	}
 	err = dir_commit_chunk(page, from, to);
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
 	mark_inode_dirty(dir);
@@ -283,8 +325,7 @@
 {
 	struct address_space *mapping = inode->i_mapping;
 	struct page *page = grab_cache_page(mapping, 0);
-	struct minix_sb_info * sbi = minix_sb(inode->i_sb);
-	struct minix_dir_entry * de;
+	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
 	char *kaddr;
 	int err;
 
@@ -299,12 +340,23 @@
 	kaddr = kmap_atomic(page, KM_USER0);
 	memset(kaddr, 0, PAGE_CACHE_SIZE);
 
-	de = (struct minix_dir_entry *)kaddr;
-	de->inode = inode->i_ino;
-	strcpy(de->name,".");
-	de = minix_next_entry(de, sbi);
-	de->inode = dir->i_ino;
-	strcpy(de->name,"..");
+	if (sbi->s_version == MINIX_V3) {
+		minix3_dirent *de3 = (minix3_dirent *)kaddr;
+
+		de3->inode = inode->i_ino;
+		strcpy(de3->name, ".");
+		de3 = minix_next_entry(de3, sbi);
+		de3->inode = dir->i_ino;
+		strcpy(de3->name, "..");
+	} else {
+		minix_dirent *de = (minix_dirent *)kaddr;
+
+		de->inode = inode->i_ino;
+		strcpy(de->name, ".");
+		de = minix_next_entry(de, sbi);
+		de->inode = dir->i_ino;
+		strcpy(de->name, "..");
+	}
 	kunmap_atomic(kaddr, KM_USER0);
 
 	err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
@@ -321,33 +373,41 @@
 	struct page *page = NULL;
 	unsigned long i, npages = dir_pages(inode);
 	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
+	char *name;
+	__u32 inumber;
 
 	for (i = 0; i < npages; i++) {
-		char *kaddr;
-		minix_dirent * de;
-		page = dir_get_page(inode, i);
+		char *p, *kaddr, *limit;
 
+		page = dir_get_page(inode, i);
 		if (IS_ERR(page))
 			continue;
 
 		kaddr = (char *)page_address(page);
-		de = (minix_dirent *)kaddr;
-		kaddr += minix_last_byte(inode, i) - sbi->s_dirsize;
+		limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize;
+		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+			if (sbi->s_version == MINIX_V3) {
+				minix3_dirent *de3 = (minix3_dirent *)p;
+				name = de3->name;
+				inumber = de3->inode;
+			} else {
+				minix_dirent *de = (minix_dirent *)p;
+				name = de->name;
+				inumber = de->inode;
+			}
 
-		while ((char *)de <= kaddr) {
-			if (de->inode != 0) {
+			if (inumber != 0) {
 				/* check for . and .. */
-				if (de->name[0] != '.')
+				if (name[0] != '.')
 					goto not_empty;
-				if (!de->name[1]) {
-					if (de->inode != inode->i_ino)
+				if (!name[1]) {
+					if (inumber != inode->i_ino)
 						goto not_empty;
-				} else if (de->name[1] != '.')
+				} else if (name[1] != '.')
 					goto not_empty;
-				else if (de->name[2])
+				else if (name[2])
 					goto not_empty;
 			}
-			de = minix_next_entry(de, sbi);
 		}
 		dir_put_page(page);
 	}
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 40eac2e..f92baa1 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -26,7 +26,7 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-struct inode_operations minix_file_inode_operations = {
+const struct inode_operations minix_file_inode_operations = {
 	.truncate	= minix_truncate,
 	.getattr	= minix_getattr,
 };
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 629e09b..92e383a 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -7,6 +7,7 @@
  *	Minix V2 fs support.
  *
  *  Modified for 680x0 by Andreas Schwab
+ *  Updated to filesystem version 3 by Daniel Aragones
  */
 
 #include <linux/module.h>
@@ -36,7 +37,8 @@
 	struct minix_sb_info *sbi = minix_sb(sb);
 
 	if (!(sb->s_flags & MS_RDONLY)) {
-		sbi->s_ms->s_state = sbi->s_mount_state;
+		if (sbi->s_version != MINIX_V3)	 /* s_state is now out from V3 sb */
+			sbi->s_ms->s_state = sbi->s_mount_state;
 		mark_buffer_dirty(sbi->s_sbh);
 	}
 	for (i = 0; i < sbi->s_imap_blocks; i++)
@@ -93,7 +95,7 @@
 	kmem_cache_destroy(minix_inode_cachep);
 }
 
-static struct super_operations minix_sops = {
+static const struct super_operations minix_sops = {
 	.alloc_inode	= minix_alloc_inode,
 	.destroy_inode	= minix_destroy_inode,
 	.read_inode	= minix_read_inode,
@@ -117,12 +119,17 @@
 		    !(sbi->s_mount_state & MINIX_VALID_FS))
 			return 0;
 		/* Mounting a rw partition read-only. */
-		ms->s_state = sbi->s_mount_state;
+		if (sbi->s_version != MINIX_V3)
+			ms->s_state = sbi->s_mount_state;
 		mark_buffer_dirty(sbi->s_sbh);
 	} else {
 	  	/* Mount a partition which is read-only, read-write. */
-		sbi->s_mount_state = ms->s_state;
-		ms->s_state &= ~MINIX_VALID_FS;
+		if (sbi->s_version != MINIX_V3) {
+			sbi->s_mount_state = ms->s_state;
+			ms->s_state &= ~MINIX_VALID_FS;
+		} else {
+			sbi->s_mount_state = MINIX_VALID_FS;
+		}
 		mark_buffer_dirty(sbi->s_sbh);
 
 		if (!(sbi->s_mount_state & MINIX_VALID_FS))
@@ -140,7 +147,8 @@
 	struct buffer_head *bh;
 	struct buffer_head **map;
 	struct minix_super_block *ms;
-	int i, block;
+	struct minix3_super_block *m3s = NULL;
+	unsigned long i, block;
 	struct inode *root_inode;
 	struct minix_sb_info *sbi;
 
@@ -192,6 +200,22 @@
 		sbi->s_dirsize = 32;
 		sbi->s_namelen = 30;
 		sbi->s_link_max = MINIX2_LINK_MAX;
+	} else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) {
+		m3s = (struct minix3_super_block *) bh->b_data;
+		s->s_magic = m3s->s_magic;
+		sbi->s_imap_blocks = m3s->s_imap_blocks;
+		sbi->s_zmap_blocks = m3s->s_zmap_blocks;
+		sbi->s_firstdatazone = m3s->s_firstdatazone;
+		sbi->s_log_zone_size = m3s->s_log_zone_size;
+		sbi->s_max_size = m3s->s_max_size;
+		sbi->s_ninodes = m3s->s_ninodes;
+		sbi->s_nzones = m3s->s_zones;
+		sbi->s_dirsize = 64;
+		sbi->s_namelen = 60;
+		sbi->s_version = MINIX_V3;
+		sbi->s_link_max = MINIX2_LINK_MAX;
+		sbi->s_mount_state = MINIX_VALID_FS;
+		sb_set_blocksize(s, m3s->s_blocksize);
 	} else
 		goto out_no_fs;
 
@@ -236,7 +260,8 @@
 		s->s_root->d_op = &minix_dentry_operations;
 
 	if (!(s->s_flags & MS_RDONLY)) {
-		ms->s_state &= ~MINIX_VALID_FS;
+		if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
+			ms->s_state &= ~MINIX_VALID_FS;
 		mark_buffer_dirty(bh);
 	}
 	if (!(sbi->s_mount_state & MINIX_VALID_FS))
@@ -278,8 +303,8 @@
 
 out_no_fs:
 	if (!silent)
-		printk("VFS: Can't find a Minix or Minix V2 filesystem "
-			"on device %s\n", s->s_id);
+		printk("VFS: Can't find a Minix filesystem V1 | V2 | V3 "
+		       "on device %s.\n", s->s_id);
 out_release:
 	brelse(bh);
 	goto out;
@@ -344,7 +369,7 @@
 	.bmap = minix_bmap
 };
 
-static struct inode_operations minix_symlink_inode_operations = {
+static const struct inode_operations minix_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -537,12 +562,14 @@
 
 int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
+	struct inode *dir = dentry->d_parent->d_inode;
+	struct super_block *sb = dir->i_sb;
 	generic_fillattr(dentry->d_inode, stat);
 	if (INODE_VERSION(dentry->d_inode) == MINIX_V1)
-		stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size);
+		stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
 	else
-		stat->blocks = (BLOCK_SIZE / 512) * V2_minix_blocks(stat->size);
-	stat->blksize = BLOCK_SIZE;
+		stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb);
+	stat->blksize = sb->s_blocksize;
 	return 0;
 }
 
diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c
index 429baf8..a731cab 100644
--- a/fs/minix/itree_common.c
+++ b/fs/minix/itree_common.c
@@ -23,7 +23,7 @@
 
 static inline block_t *block_end(struct buffer_head *bh)
 {
-	return (block_t *)((char*)bh->b_data + BLOCK_SIZE);
+	return (block_t *)((char*)bh->b_data + bh->b_size);
 }
 
 static inline Indirect *get_branch(struct inode *inode,
@@ -85,7 +85,7 @@
 		branch[n].key = cpu_to_block(nr);
 		bh = sb_getblk(inode->i_sb, parent);
 		lock_buffer(bh);
-		memset(bh->b_data, 0, BLOCK_SIZE);
+		memset(bh->b_data, 0, bh->b_size);
 		branch[n].bh = bh;
 		branch[n].p = (block_t*) bh->b_data + offsets[n];
 		*branch[n].p = branch[n].key;
@@ -292,6 +292,7 @@
 
 static inline void truncate (struct inode * inode)
 {
+	struct super_block *sb = inode->i_sb;
 	block_t *idata = i_data(inode);
 	int offsets[DEPTH];
 	Indirect chain[DEPTH];
@@ -301,7 +302,7 @@
 	int first_whole;
 	long iblock;
 
-	iblock = (inode->i_size + BLOCK_SIZE-1) >> 10;
+	iblock = (inode->i_size + sb->s_blocksize -1) >> sb->s_blocksize_bits;
 	block_truncate_page(inode->i_mapping, inode->i_size, get_block);
 
 	n = block_to_path(inode, iblock, offsets);
@@ -346,15 +347,16 @@
 	mark_inode_dirty(inode);
 }
 
-static inline unsigned nblocks(loff_t size)
+static inline unsigned nblocks(loff_t size, struct super_block *sb)
 {
+	int k = sb->s_blocksize_bits - 10;
 	unsigned blocks, res, direct = DIRECT, i = DEPTH;
-	blocks = (size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+	blocks = (size + sb->s_blocksize - 1) >> (BLOCK_SIZE_BITS + k);
 	res = blocks;
 	while (--i && blocks > direct) {
 		blocks -= direct;
-		blocks += BLOCK_SIZE/sizeof(block_t) - 1;
-		blocks /= BLOCK_SIZE/sizeof(block_t);
+		blocks += sb->s_blocksize/sizeof(block_t) - 1;
+		blocks /= sb->s_blocksize/sizeof(block_t);
 		res += blocks;
 		direct = 1;
 	}
diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c
index 656b134..1a5f3bf 100644
--- a/fs/minix/itree_v1.c
+++ b/fs/minix/itree_v1.c
@@ -55,7 +55,7 @@
 	truncate(inode);
 }
 
-unsigned V1_minix_blocks(loff_t size)
+unsigned V1_minix_blocks(loff_t size, struct super_block *sb)
 {
-	return nblocks(size);
+	return nblocks(size, sb);
 }
diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c
index 9adcdc7..ad8f0de 100644
--- a/fs/minix/itree_v2.c
+++ b/fs/minix/itree_v2.c
@@ -23,10 +23,11 @@
 static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
 {
 	int n = 0;
+	struct super_block *sb = inode->i_sb;
 
 	if (block < 0) {
 		printk("minix_bmap: block<0\n");
-	} else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) {
+	} else if (block >= (minix_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) {
 		printk("minix_bmap: block>big\n");
 	} else if (block < 7) {
 		offsets[n++] = block;
@@ -60,7 +61,7 @@
 	truncate(inode);
 }
 
-unsigned V2_minix_blocks(loff_t size)
+unsigned V2_minix_blocks(loff_t size, struct super_block *sb)
 {
-	return nblocks(size);
+	return nblocks(size, sb);
 }
diff --git a/fs/minix/minix.h b/fs/minix/minix.h
index c55b77c..73ef84f 100644
--- a/fs/minix/minix.h
+++ b/fs/minix/minix.h
@@ -7,11 +7,10 @@
  * truncated. Else they will be disallowed (ENAMETOOLONG).
  */
 #define NO_TRUNCATE 1
-
 #define INODE_VERSION(inode)	minix_sb(inode->i_sb)->s_version
-
 #define MINIX_V1		0x0001		/* original minix fs */
 #define MINIX_V2		0x0002		/* minix V2 fs */
+#define MINIX_V3		0x0003		/* minix V3 fs */
 
 /*
  * minix fs inode data in memory
@@ -52,12 +51,10 @@
 extern void minix_free_inode(struct inode * inode);
 extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi);
 extern int minix_new_block(struct inode * inode);
-extern void minix_free_block(struct inode * inode, int block);
+extern void minix_free_block(struct inode *inode, unsigned long block);
 extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi);
-
 extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 
-extern void V2_minix_truncate(struct inode *);
 extern void V1_minix_truncate(struct inode *);
 extern void V2_minix_truncate(struct inode *);
 extern void minix_truncate(struct inode *);
@@ -65,8 +62,8 @@
 extern void minix_set_inode(struct inode *, dev_t);
 extern int V1_minix_get_block(struct inode *, long, struct buffer_head *, int);
 extern int V2_minix_get_block(struct inode *, long, struct buffer_head *, int);
-extern unsigned V1_minix_blocks(loff_t);
-extern unsigned V2_minix_blocks(loff_t);
+extern unsigned V1_minix_blocks(loff_t, struct super_block *);
+extern unsigned V2_minix_blocks(loff_t, struct super_block *);
 
 extern struct minix_dir_entry *minix_find_entry(struct dentry*, struct page**);
 extern int minix_add_link(struct dentry*, struct inode*);
@@ -76,11 +73,10 @@
 extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*);
 extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**);
 extern ino_t minix_inode_by_name(struct dentry*);
-
 extern int minix_sync_file(struct file *, struct dentry *, int);
 
-extern struct inode_operations minix_file_inode_operations;
-extern struct inode_operations minix_dir_inode_operations;
+extern const struct inode_operations minix_file_inode_operations;
+extern const struct inode_operations minix_dir_inode_operations;
 extern const struct file_operations minix_file_operations;
 extern const struct file_operations minix_dir_operations;
 extern struct dentry_operations minix_dentry_operations;
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 299bb66..f4aa7a9 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -291,7 +291,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations minix_dir_inode_operations = {
+const struct inode_operations minix_dir_inode_operations = {
 	.create		= minix_create,
 	.lookup		= minix_lookup,
 	.link		= minix_link,
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 4524619..30f7d0a 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -646,7 +646,7 @@
 	return err;
 }
 
-static struct inode_operations msdos_dir_inode_operations = {
+static const struct inode_operations msdos_dir_inode_operations = {
 	.create		= msdos_create,
 	.lookup		= msdos_lookup,
 	.unlink		= msdos_unlink,
diff --git a/fs/namei.c b/fs/namei.c
index e4f108f..ee60cc4 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2688,10 +2688,11 @@
 {
 	struct address_space *mapping = inode->i_mapping;
 	struct page *page;
-	int err = -ENOMEM;
+	int err;
 	char *kaddr;
 
 retry:
+	err = -ENOMEM;
 	page = find_or_create_page(mapping, 0, gfp_mask);
 	if (!page)
 		goto fail;
@@ -2744,7 +2745,7 @@
 			mapping_gfp_mask(inode->i_mapping));
 }
 
-struct inode_operations page_symlink_inode_operations = {
+const struct inode_operations page_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
diff --git a/fs/namespace.c b/fs/namespace.c
index 5ef336c..fd999ca 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -53,9 +53,8 @@
 
 struct vfsmount *alloc_vfsmnt(const char *name)
 {
-	struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL);
+	struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
 	if (mnt) {
-		memset(mnt, 0, sizeof(struct vfsmount));
 		atomic_set(&mnt->mnt_count, 1);
 		INIT_LIST_HEAD(&mnt->mnt_hash);
 		INIT_LIST_HEAD(&mnt->mnt_child);
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 7374777..011ef0b 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -58,7 +58,7 @@
 #endif
 };
 
-struct inode_operations ncp_dir_inode_operations =
+const struct inode_operations ncp_dir_inode_operations =
 {
 	.create		= ncp_create,
 	.lookup		= ncp_lookup,
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index b91fea0..6b1f6d2 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -297,7 +297,7 @@
 	.fsync		= ncp_fsync,
 };
 
-struct inode_operations ncp_file_inode_operations =
+const struct inode_operations ncp_file_inode_operations =
 {
 	.setattr	= ncp_notify_change,
 };
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 67a90bf..14939dd 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -90,7 +90,7 @@
 	return 0;
 }
 
-static struct super_operations ncp_sops =
+static const struct super_operations ncp_sops =
 {
 	.alloc_inode	= ncp_alloc_inode,
 	.destroy_inode	= ncp_destroy_inode,
@@ -229,7 +229,7 @@
 }
 
 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
-static struct inode_operations ncp_symlink_inode_operations = {
+static const struct inode_operations ncp_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 7933e2e..75f309c 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -71,6 +71,8 @@
 	complete(&nfs_callback_info.started);
 
 	for(;;) {
+		char buf[RPC_MAX_ADDRBUFLEN];
+
 		if (signalled()) {
 			if (nfs_callback_info.users == 0)
 				break;
@@ -88,8 +90,8 @@
 					__FUNCTION__, -err);
 			break;
 		}
-		dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__,
-				NIPQUAD(rqstp->rq_addr.sin_addr.s_addr));
+		dprintk("%s: request from %s\n", __FUNCTION__,
+				svc_print_addr(rqstp, buf, sizeof(buf)));
 		svc_process(rqstp);
 	}
 
@@ -106,7 +108,6 @@
 int nfs_callback_up(void)
 {
 	struct svc_serv *serv;
-	struct svc_sock *svsk;
 	int ret = 0;
 
 	lock_kernel();
@@ -119,17 +120,14 @@
 	ret = -ENOMEM;
 	if (!serv)
 		goto out_err;
-	/* FIXME: We don't want to register this socket with the portmapper */
-	ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport);
-	if (ret < 0)
+
+	ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport,
+							SVC_SOCK_ANONYMOUS);
+	if (ret <= 0)
 		goto out_destroy;
-	if (!list_empty(&serv->sv_permsocks)) {
-		svsk = list_entry(serv->sv_permsocks.next,
-				struct svc_sock, sk_list);
-		nfs_callback_tcpport = ntohs(inet_sk(svsk->sk_sk)->sport);
-		dprintk ("Callback port = 0x%x\n", nfs_callback_tcpport);
-	} else
-		BUG();
+	nfs_callback_tcpport = ret;
+	dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
+
 	ret = svc_create_thread(nfs_callback_svc, serv);
 	if (ret < 0)
 		goto out_destroy;
@@ -140,6 +138,8 @@
 	unlock_kernel();
 	return ret;
 out_destroy:
+	dprintk("Couldn't create callback socket or server thread; err = %d\n",
+		ret);
 	svc_destroy(serv);
 out_err:
 	nfs_callback_info.users--;
@@ -166,15 +166,19 @@
 
 static int nfs_callback_authenticate(struct svc_rqst *rqstp)
 {
-	struct sockaddr_in *addr = &rqstp->rq_addr;
+	struct sockaddr_in *addr = svc_addr_in(rqstp);
 	struct nfs_client *clp;
+	char buf[RPC_MAX_ADDRBUFLEN];
 
 	/* Don't talk to strangers */
 	clp = nfs_find_client(addr, 4);
 	if (clp == NULL)
 		return SVC_DROP;
-	dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr));
+
+	dprintk("%s: %s NFSv4 callback!\n", __FUNCTION__,
+			svc_print_addr(rqstp, buf, sizeof(buf)));
 	nfs_put_client(clp);
+
 	switch (rqstp->rq_authop->flavour) {
 		case RPC_AUTH_NULL:
 			if (rqstp->rq_proc != CB_NULL)
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index f8ea1f5..849a202 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -176,7 +176,7 @@
 	status = decode_fh(xdr, &args->fh);
 	if (unlikely(status != 0))
 		goto out;
-	args->addr = &rqstp->rq_addr;
+	args->addr = svc_addr_in(rqstp);
 	status = decode_bitmap(xdr, args->bitmap);
 out:
 	dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
@@ -188,7 +188,7 @@
 	__be32 *p;
 	__be32 status;
 
-	args->addr = &rqstp->rq_addr;
+	args->addr = svc_addr_in(rqstp);
 	status = decode_stateid(xdr, &args->stateid);
 	if (unlikely(status != 0))
 		goto out;
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 23ab145..2190e6c 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -394,7 +394,8 @@
 static int nfs_create_rpc_client(struct nfs_client *clp, int proto,
 						unsigned int timeo,
 						unsigned int retrans,
-						rpc_authflavor_t flavor)
+						rpc_authflavor_t flavor,
+						int flags)
 {
 	struct rpc_timeout	timeparms;
 	struct rpc_clnt		*clnt = NULL;
@@ -407,6 +408,7 @@
 		.program	= &nfs_program,
 		.version	= clp->rpc_ops->version,
 		.authflavor	= flavor,
+		.flags		= flags,
 	};
 
 	if (!IS_ERR(clp->cl_rpcclient))
@@ -548,7 +550,7 @@
 	 * - RFC 2623, sec 2.3.2
 	 */
 	error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans,
-			RPC_AUTH_UNIX);
+					RPC_AUTH_UNIX, 0);
 	if (error < 0)
 		goto error;
 	nfs_mark_client_ready(clp, NFS_CS_READY);
@@ -868,7 +870,8 @@
 	/* Check NFS protocol revision and initialize RPC op vector */
 	clp->rpc_ops = &nfs_v4_clientops;
 
-	error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour);
+	error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour,
+					RPC_CLNT_CREATE_DISCRTRY);
 	if (error < 0)
 		goto error;
 	memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
@@ -1030,7 +1033,7 @@
  * Create an NFS4 referral server record
  */
 struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
-					       struct nfs_fh *fh)
+					       struct nfs_fh *mntfh)
 {
 	struct nfs_client *parent_client;
 	struct nfs_server *server, *parent_server;
@@ -1069,8 +1072,13 @@
 	BUG_ON(!server->nfs_client->rpc_ops);
 	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
+	/* Probe the root fh to retrieve its FSID and filehandle */
+	error = nfs4_path_walk(server, mntfh, data->mnt_path);
+	if (error < 0)
+		goto error;
+
 	/* probe the filesystem info for this server filesystem */
-	error = nfs_probe_fsinfo(server, fh, &fattr);
+	error = nfs_probe_fsinfo(server, mntfh, &fattr);
 	if (error < 0)
 		goto error;
 
@@ -1173,7 +1181,7 @@
 	.show	= nfs_server_list_show,
 };
 
-static struct file_operations nfs_server_list_fops = {
+static const struct file_operations nfs_server_list_fops = {
 	.open		= nfs_server_list_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -1193,7 +1201,7 @@
 	.show	= nfs_volume_list_show,
 };
 
-static struct file_operations nfs_volume_list_fops = {
+static const struct file_operations nfs_volume_list_fops = {
 	.open		= nfs_volume_list_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index d9ba8cb..92d8ec8 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -65,7 +65,7 @@
 	.fsync		= nfs_fsync_dir,
 };
 
-struct inode_operations nfs_dir_inode_operations = {
+const struct inode_operations nfs_dir_inode_operations = {
 	.create		= nfs_create,
 	.lookup		= nfs_lookup,
 	.link		= nfs_link,
@@ -81,7 +81,7 @@
 };
 
 #ifdef CONFIG_NFS_V3
-struct inode_operations nfs3_dir_inode_operations = {
+const struct inode_operations nfs3_dir_inode_operations = {
 	.create		= nfs_create,
 	.lookup		= nfs_lookup,
 	.link		= nfs_link,
@@ -104,7 +104,7 @@
 #ifdef CONFIG_NFS_V4
 
 static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
-struct inode_operations nfs4_dir_inode_operations = {
+const struct inode_operations nfs4_dir_inode_operations = {
 	.create		= nfs_create,
 	.lookup		= nfs_atomic_lookup,
 	.link		= nfs_link,
@@ -637,7 +637,7 @@
  * In the case it has, we assume that the dentries are untrustworthy
  * and may need to be looked up again.
  */
-static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
+static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
 {
 	if (IS_ROOT(dentry))
 		return 1;
@@ -652,6 +652,12 @@
 	dentry->d_fsdata = (void *)verf;
 }
 
+static void nfs_refresh_verifier(struct dentry * dentry, unsigned long verf)
+{
+	if (time_after(verf, (unsigned long)dentry->d_fsdata))
+		nfs_set_verifier(dentry, verf);
+}
+
 /*
  * Whenever an NFS operation succeeds, we know that the dentry
  * is valid, so we update the revalidation timestamp.
@@ -785,7 +791,7 @@
 		goto out_bad;
 
 	nfs_renew_times(dentry);
-	nfs_set_verifier(dentry, verifier);
+	nfs_refresh_verifier(dentry, verifier);
  out_valid:
 	unlock_kernel();
 	dput(parent);
@@ -1085,7 +1091,7 @@
 	verifier = nfs_save_change_attribute(dir);
 	ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
 	if (!ret)
-		nfs_set_verifier(dentry, verifier);
+		nfs_refresh_verifier(dentry, verifier);
 	unlock_kernel();
 out:
 	dput(parent);
@@ -1123,8 +1129,21 @@
 	}
 	name.hash = full_name_hash(name.name, name.len);
 	dentry = d_lookup(parent, &name);
-	if (dentry != NULL)
-		return dentry;
+	if (dentry != NULL) {
+		/* Is this a positive dentry that matches the readdir info? */
+		if (dentry->d_inode != NULL &&
+				(NFS_FILEID(dentry->d_inode) == entry->ino ||
+				d_mountpoint(dentry))) {
+			if (!desc->plus || entry->fh->size == 0)
+				return dentry;
+			if (nfs_compare_fh(NFS_FH(dentry->d_inode),
+						entry->fh) == 0)
+				goto out_renew;
+		}
+		/* No, so d_drop to allow one to be created */
+		d_drop(dentry);
+		dput(dentry);
+	}
 	if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR))
 		return NULL;
 	/* Note: caller is already holding the dir->i_mutex! */
@@ -1149,6 +1168,10 @@
 	nfs_renew_times(dentry);
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 	return dentry;
+out_renew:
+	nfs_renew_times(dentry);
+	nfs_refresh_verifier(dentry, nfs_save_change_attribute(dir));
+	return dentry;
 }
 
 /*
@@ -1443,6 +1466,8 @@
 	if (atomic_read(&dentry->d_count) > 1) {
 		spin_unlock(&dentry->d_lock);
 		spin_unlock(&dcache_lock);
+		/* Start asynchronous writeout of the inode */
+		write_inode_now(dentry->d_inode, 0);
 		error = nfs_sillyrename(dir, dentry);
 		unlock_kernel();
 		return error;
@@ -1684,7 +1709,7 @@
 	if (!error) {
 		d_move(old_dentry, new_dentry);
 		nfs_renew_times(new_dentry);
-		nfs_set_verifier(new_dentry, nfs_save_change_attribute(new_dir));
+		nfs_refresh_verifier(new_dentry, nfs_save_change_attribute(new_dir));
 	}
 
 	/* new dentry created? */
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index bd21d7f..b1c98ea 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -309,7 +309,8 @@
 
 		rpc_execute(&data->task);
 
-		dfprintk(VFS, "NFS: %5u initiated direct read call (req %s/%Ld, %zu bytes @ offset %Lu)\n",
+		dprintk("NFS: %5u initiated direct read call "
+			"(req %s/%Ld, %zu bytes @ offset %Lu)\n",
 				data->task.tk_pid,
 				inode->i_sb->s_id,
 				(long long)NFS_FILEID(inode),
@@ -639,7 +640,8 @@
 
 		rpc_execute(&data->task);
 
-		dfprintk(VFS, "NFS: %5u initiated direct write call (req %s/%Ld, %zu bytes @ offset %Lu)\n",
+		dprintk("NFS: %5u initiated direct write call "
+			"(req %s/%Ld, %zu bytes @ offset %Lu)\n",
 				data->task.tk_pid,
 				inode->i_sb->s_id,
 				(long long)NFS_FILEID(inode),
@@ -797,7 +799,7 @@
 	const char __user *buf = iov[0].iov_base;
 	size_t count = iov[0].iov_len;
 
-	dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
+	dprintk("nfs: direct write(%s/%s, %lu@%Ld)\n",
 		file->f_path.dentry->d_parent->d_name.name,
 		file->f_path.dentry->d_name.name,
 		(unsigned long) count, (long long) pos);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 9e4a2b7..8e66b5a 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -68,14 +68,14 @@
 	.check_flags	= nfs_check_flags,
 };
 
-struct inode_operations nfs_file_inode_operations = {
+const struct inode_operations nfs_file_inode_operations = {
 	.permission	= nfs_permission,
 	.getattr	= nfs_getattr,
 	.setattr	= nfs_setattr,
 };
 
 #ifdef CONFIG_NFS_V3
-struct inode_operations nfs3_file_inode_operations = {
+const struct inode_operations nfs3_file_inode_operations = {
 	.permission	= nfs_permission,
 	.getattr	= nfs_getattr,
 	.setattr	= nfs_setattr,
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 8391bd7..6ef268f 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -135,17 +135,15 @@
 	struct nfs_fh lastfh;
 	struct qstr name;
 	int ret;
-	//int referral_count = 0;
 
 	dprintk("--> nfs4_path_walk(,,%s)\n", path);
 
 	fsinfo.fattr = &fattr;
 	nfs_fattr_init(&fattr);
 
-	if (*path++ != '/') {
-		dprintk("nfs4_get_root: Path does not begin with a slash\n");
-		return -EINVAL;
-	}
+	/* Eat leading slashes */
+	while (*path == '/')
+		path++;
 
 	/* Start by getting the root filehandle from the server */
 	ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
@@ -160,6 +158,7 @@
 		return -ENOTDIR;
 	}
 
+	/* FIXME: It is quite valid for the server to return a referral here */
 	if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) {
 		printk(KERN_ERR "nfs4_get_root:"
 		       " getroot obtained referral\n");
@@ -187,6 +186,7 @@
 		goto eat_dot_dir;
 	}
 
+	/* FIXME: Why shouldn't the user be able to use ".." in the path? */
 	if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2])
 	    ) {
 		printk(KERN_ERR "nfs4_get_root:"
@@ -212,6 +212,7 @@
 		return -ENOTDIR;
 	}
 
+	/* FIXME: Referrals are quite valid here too */
 	if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) {
 		printk(KERN_ERR "nfs4_get_root:"
 		       " lookupfh obtained referral\n");
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index d834982..af53c02 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -65,13 +65,18 @@
 
 int nfs_write_inode(struct inode *inode, int sync)
 {
-	int flags = sync ? FLUSH_SYNC : 0;
 	int ret;
 
-	ret = nfs_commit_inode(inode, flags);
-	if (ret < 0)
-		return ret;
-	return 0;
+	if (sync) {
+		ret = filemap_fdatawait(inode->i_mapping);
+		if (ret == 0)
+			ret = nfs_commit_inode(inode, FLUSH_SYNC);
+	} else
+		ret = nfs_commit_inode(inode, 0);
+	if (ret >= 0)
+		return 0;
+	__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+	return ret;
 }
 
 void nfs_clear_inode(struct inode *inode)
@@ -235,6 +240,7 @@
 
 	if (inode->i_state & I_NEW) {
 		struct nfs_inode *nfsi = NFS_I(inode);
+		unsigned long now = jiffies;
 
 		/* We set i_ino for the few things that still rely on it,
 		 * such as stat(2) */
@@ -271,7 +277,8 @@
 			init_special_inode(inode, inode->i_mode, fattr->rdev);
 
 		nfsi->read_cache_jiffies = fattr->time_start;
-		nfsi->last_updated = jiffies;
+		nfsi->last_updated = now;
+		nfsi->cache_change_attribute = now;
 		inode->i_atime = fattr->atime;
 		inode->i_mtime = fattr->mtime;
 		inode->i_ctime = fattr->ctime;
@@ -290,7 +297,7 @@
 			inode->i_blocks = fattr->du.nfs2.blocks;
 		}
 		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
-		nfsi->attrtimeo_timestamp = jiffies;
+		nfsi->attrtimeo_timestamp = now;
 		memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
 		nfsi->access_cache = RB_ROOT;
 
@@ -783,20 +790,21 @@
 static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
+	unsigned long now = jiffies;
 
 	/* If we have atomic WCC data, we may update some attributes */
 	if ((fattr->valid & NFS_ATTR_WCC) != 0) {
 		if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) {
 			memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
-			nfsi->cache_change_attribute = jiffies;
+			nfsi->cache_change_attribute = now;
 		}
 		if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) {
 			memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
-			nfsi->cache_change_attribute = jiffies;
+			nfsi->cache_change_attribute = now;
 		}
 		if (inode->i_size == fattr->pre_size && nfsi->npages == 0) {
 			inode->i_size = fattr->size;
-			nfsi->cache_change_attribute = jiffies;
+			nfsi->cache_change_attribute = now;
 		}
 	}
 }
@@ -934,6 +942,7 @@
 	struct nfs_inode *nfsi = NFS_I(inode);
 	loff_t cur_isize, new_isize;
 	unsigned int	invalid = 0;
+	unsigned long now = jiffies;
 	int data_stable;
 
 	dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n",
@@ -959,7 +968,11 @@
 	 * Update the read time so we don't revalidate too often.
 	 */
 	nfsi->read_cache_jiffies = fattr->time_start;
-	nfsi->last_updated = jiffies;
+	nfsi->last_updated = now;
+
+	/* Fix a wraparound issue with nfsi->cache_change_attribute */
+	if (time_before(now, nfsi->cache_change_attribute))
+		nfsi->cache_change_attribute = now - 600*HZ;
 
 	/* Are we racing with known updates of the metadata on the server? */
 	data_stable = nfs_verify_change_attribute(inode, fattr->time_start);
@@ -985,7 +998,7 @@
 			inode->i_size = new_isize;
 			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
 		}
-		nfsi->cache_change_attribute = jiffies;
+		nfsi->cache_change_attribute = now;
 		dprintk("NFS: isize change on server for file %s/%ld\n",
 				inode->i_sb->s_id, inode->i_ino);
 	}
@@ -996,14 +1009,14 @@
 		dprintk("NFS: mtime change on server for file %s/%ld\n",
 				inode->i_sb->s_id, inode->i_ino);
 		invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
-		nfsi->cache_change_attribute = jiffies;
+		nfsi->cache_change_attribute = now;
 	}
 
 	/* If ctime has changed we should definitely clear access+acl caches */
 	if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
 		invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 		memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
-		nfsi->cache_change_attribute = jiffies;
+		nfsi->cache_change_attribute = now;
 	}
 	memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
 
@@ -1032,18 +1045,18 @@
 				inode->i_sb->s_id, inode->i_ino);
 		nfsi->change_attr = fattr->change_attr;
 		invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
-		nfsi->cache_change_attribute = jiffies;
+		nfsi->cache_change_attribute = now;
 	}
 
 	/* Update attrtimeo value if we're out of the unstable period */
 	if (invalid & NFS_INO_INVALID_ATTR) {
 		nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
 		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
-		nfsi->attrtimeo_timestamp = jiffies;
-	} else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) {
+		nfsi->attrtimeo_timestamp = now;
+	} else if (time_after(now, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) {
 		if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))
 			nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
-		nfsi->attrtimeo_timestamp = jiffies;
+		nfsi->attrtimeo_timestamp = now;
 	}
 	/* Don't invalidate the data if we were to blame */
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
@@ -1122,7 +1135,6 @@
 		return NULL;
 	nfsi->flags = 0UL;
 	nfsi->cache_validity = 0UL;
-	nfsi->cache_change_attribute = jiffies;
 #ifdef CONFIG_NFS_V3_ACL
 	nfsi->acl_access = ERR_PTR(-EAGAIN);
 	nfsi->acl_default = ERR_PTR(-EAGAIN);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index a28f6ce..6610f2b 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -107,10 +107,6 @@
 /* nfs4proc.c */
 #ifdef CONFIG_NFS_V4
 extern struct rpc_procinfo nfs4_procedures[];
-
-extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
-				  struct nfs4_fs_locations *fs_locations,
-				  struct page *page);
 #endif
 
 /* dir.c */
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 371b804..7f86e65 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -155,12 +155,12 @@
 	goto out;
 }
 
-struct inode_operations nfs_mountpoint_inode_operations = {
+const struct inode_operations nfs_mountpoint_inode_operations = {
 	.follow_link	= nfs_follow_mountpoint,
 	.getattr	= nfs_getattr,
 };
 
-struct inode_operations nfs_referral_inode_operations = {
+const struct inode_operations nfs_referral_inode_operations = {
 	.follow_link	= nfs_follow_mountpoint,
 };
 
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index acd8fe9..7d0371e 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -253,29 +253,6 @@
 	return status;
 }
 
-static int nfs3_proc_read(struct nfs_read_data *rdata)
-{
-	int			flags = rdata->flags;
-	struct inode *		inode = rdata->inode;
-	struct nfs_fattr *	fattr = rdata->res.fattr;
-	struct rpc_message	msg = {
-		.rpc_proc	= &nfs3_procedures[NFS3PROC_READ],
-		.rpc_argp	= &rdata->args,
-		.rpc_resp	= &rdata->res,
-		.rpc_cred	= rdata->cred,
-	};
-	int			status;
-
-	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
-			(long long) rdata->args.offset);
-	nfs_fattr_init(fattr);
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
-	if (status >= 0)
-		nfs_refresh_inode(inode, fattr);
-	dprintk("NFS reply read: %d\n", status);
-	return status;
-}
-
 /*
  * Create a regular file.
  * For now, we don't implement O_EXCL.
@@ -855,7 +832,6 @@
 	.lookup		= nfs3_proc_lookup,
 	.access		= nfs3_proc_access,
 	.readlink	= nfs3_proc_readlink,
-	.read		= nfs3_proc_read,
 	.create		= nfs3_proc_create,
 	.remove		= nfs3_proc_remove,
 	.unlink_setup	= nfs3_proc_unlink_setup,
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index c26cd97..cf3a17e 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -151,7 +151,7 @@
 };
 
 extern struct dentry_operations nfs4_dentry_operations;
-extern struct inode_operations nfs4_dir_inode_operations;
+extern const struct inode_operations nfs4_dir_inode_operations;
 
 /* inode.c */
 extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t);
@@ -169,7 +169,7 @@
 extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
-extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
+extern int nfs4_proc_fs_locations(struct inode *dir, struct qstr *name,
 		struct nfs4_fs_locations *fs_locations, struct page *page);
 
 extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index b872779..dd5fef2 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -16,6 +16,7 @@
 #include <linux/vfs.h>
 #include <linux/inet.h>
 #include "internal.h"
+#include "nfs4_fs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
 
@@ -130,7 +131,6 @@
 		.authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor,
 	};
 	char *page = NULL, *page2 = NULL;
-	char *devname;
 	int loc, s, error;
 
 	if (locations == NULL || locations->nlocations <= 0)
@@ -154,12 +154,6 @@
 		goto out;
 	}
 
-	devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
-	if (IS_ERR(devname)) {
-		mnt = (struct vfsmount *)devname;
-		goto out;
-	}
-
 	loc = 0;
 	while (loc < locations->nlocations && IS_ERR(mnt)) {
 		const struct nfs4_fs_location *location = &locations->locations[loc];
@@ -194,7 +188,11 @@
 			addr.sin_port = htons(NFS_PORT);
 			mountdata.addr = &addr;
 
-			mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, devname, &mountdata);
+			snprintf(page, PAGE_SIZE, "%s:%s",
+					mountdata.hostname,
+					mountdata.mnt_path);
+
+			mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, &mountdata);
 			if (!IS_ERR(mnt)) {
 				break;
 			}
@@ -242,7 +240,7 @@
 	dprintk("%s: getting locations for %s/%s\n",
 		__FUNCTION__, parent->d_name.name, dentry->d_name.name);
 
-	err = nfs4_proc_fs_locations(parent->d_inode, dentry, fs_locations, page);
+	err = nfs4_proc_fs_locations(parent->d_inode, &dentry->d_name, fs_locations, page);
 	dput(parent);
 	if (err != 0 ||
 	    fs_locations->nlocations <= 0 ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b3fd29b..f52cf5c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1140,7 +1140,6 @@
 			break;
 		case -NFS4ERR_STALE_STATEID:
 		case -NFS4ERR_EXPIRED:
-			nfs4_schedule_state_recovery(server->nfs_client);
 			break;
 		default:
 			if (nfs4_async_handle_error(task, server) == -EAGAIN) {
@@ -1424,7 +1423,6 @@
 	int status = -ENOMEM;
 	struct page *page = NULL;
 	struct nfs4_fs_locations *locations = NULL;
-	struct dentry dentry = {};
 
 	page = alloc_page(GFP_KERNEL);
 	if (page == NULL)
@@ -1433,9 +1431,7 @@
 	if (locations == NULL)
 		goto out;
 
-	dentry.d_name.name = name->name;
-	dentry.d_name.len = name->len;
-	status = nfs4_proc_fs_locations(dir, &dentry, locations, page);
+	status = nfs4_proc_fs_locations(dir, name, locations, page);
 	if (status != 0)
 		goto out;
 	/* Make sure server returned a different fsid for the referral */
@@ -1737,44 +1733,6 @@
 	return err;
 }
 
-static int _nfs4_proc_read(struct nfs_read_data *rdata)
-{
-	int flags = rdata->flags;
-	struct inode *inode = rdata->inode;
-	struct nfs_fattr *fattr = rdata->res.fattr;
-	struct nfs_server *server = NFS_SERVER(inode);
-	struct rpc_message msg = {
-		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_READ],
-		.rpc_argp	= &rdata->args,
-		.rpc_resp	= &rdata->res,
-		.rpc_cred	= rdata->cred,
-	};
-	unsigned long timestamp = jiffies;
-	int status;
-
-	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
-			(long long) rdata->args.offset);
-
-	nfs_fattr_init(fattr);
-	status = rpc_call_sync(server->client, &msg, flags);
-	if (!status)
-		renew_lease(server, timestamp);
-	dprintk("NFS reply read: %d\n", status);
-	return status;
-}
-
-static int nfs4_proc_read(struct nfs_read_data *rdata)
-{
-	struct nfs4_exception exception = { };
-	int err;
-	do {
-		err = nfs4_handle_exception(NFS_SERVER(rdata->inode),
-				_nfs4_proc_read(rdata),
-				&exception);
-	} while (exception.retry);
-	return err;
-}
-
 /*
  * Got race?
  * We will need to arrange for the VFS layer to provide an atomic open.
@@ -2753,11 +2711,15 @@
 
 	might_sleep();
 
+	rwsem_acquire(&clp->cl_sem.dep_map, 0, 0, _RET_IP_);
+
 	rpc_clnt_sigmask(clnt, &oldset);
 	res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER,
 			nfs4_wait_bit_interruptible,
 			TASK_INTERRUPTIBLE);
 	rpc_clnt_sigunmask(clnt, &oldset);
+
+	rwsem_release(&clp->cl_sem.dep_map, 1, _RET_IP_);
 	return res;
 }
 
@@ -2996,7 +2958,6 @@
 		switch (err) {
 			case -NFS4ERR_STALE_STATEID:
 			case -NFS4ERR_EXPIRED:
-				nfs4_schedule_state_recovery(server->nfs_client);
 			case 0:
 				return 0;
 		}
@@ -3150,12 +3111,10 @@
 			break;
 		case -NFS4ERR_STALE_STATEID:
 		case -NFS4ERR_EXPIRED:
-			nfs4_schedule_state_recovery(calldata->server->nfs_client);
 			break;
 		default:
-			if (nfs4_async_handle_error(task, calldata->server) == -EAGAIN) {
+			if (nfs4_async_handle_error(task, calldata->server) == -EAGAIN)
 				rpc_restart_call(task);
-			}
 	}
 }
 
@@ -3585,7 +3544,7 @@
 	return len;
 }
 
-int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
+int nfs4_proc_fs_locations(struct inode *dir, struct qstr *name,
 		struct nfs4_fs_locations *fs_locations, struct page *page)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
@@ -3595,7 +3554,7 @@
 	};
 	struct nfs4_fs_locations_arg args = {
 		.dir_fh = NFS_FH(dir),
-		.name = &dentry->d_name,
+		.name = name,
 		.page = page,
 		.bitmask = bitmask,
 	};
@@ -3607,7 +3566,7 @@
 	int status;
 
 	dprintk("%s: start\n", __FUNCTION__);
-	fs_locations->fattr.valid = 0;
+	nfs_fattr_init(&fs_locations->fattr);
 	fs_locations->server = server;
 	fs_locations->nlocations = 0;
 	status = rpc_call_sync(server->client, &msg, 0);
@@ -3625,7 +3584,7 @@
 	.recover_lock	= nfs4_lock_expired,
 };
 
-static struct inode_operations nfs4_file_inode_operations = {
+static const struct inode_operations nfs4_file_inode_operations = {
 	.permission	= nfs_permission,
 	.getattr	= nfs_getattr,
 	.setattr	= nfs_setattr,
@@ -3646,7 +3605,6 @@
 	.lookup		= nfs4_proc_lookup,
 	.access		= nfs4_proc_access,
 	.readlink	= nfs4_proc_readlink,
-	.read		= nfs4_proc_read,
 	.create		= nfs4_proc_create,
 	.remove		= nfs4_proc_remove,
 	.unlink_setup	= nfs4_proc_unlink_setup,
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 8232985..f5f4430 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -43,7 +43,6 @@
  * child task framework of the RPC layer?
  */
 
-#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 0cf3fa3..f02d522 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -387,8 +387,10 @@
 				decode_putfh_maxsz + \
 				op_decode_hdr_maxsz + 12)
 #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
+				encode_putfh_maxsz + \
 				encode_getattr_maxsz)
 #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
+				decode_putfh_maxsz + \
 				decode_getattr_maxsz)
 #define NFS4_enc_delegreturn_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 560536a..1dcf56d 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -186,35 +186,6 @@
 	return status;
 }
 
-static int nfs_proc_read(struct nfs_read_data *rdata)
-{
-	int			flags = rdata->flags;
-	struct inode *		inode = rdata->inode;
-	struct nfs_fattr *	fattr = rdata->res.fattr;
-	struct rpc_message	msg = {
-		.rpc_proc	= &nfs_procedures[NFSPROC_READ],
-		.rpc_argp	= &rdata->args,
-		.rpc_resp	= &rdata->res,
-		.rpc_cred	= rdata->cred,
-	};
-	int			status;
-
-	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
-			(long long) rdata->args.offset);
-	nfs_fattr_init(fattr);
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
-	if (status >= 0) {
-		nfs_refresh_inode(inode, fattr);
-		/* Emulate the eof flag, which isn't normally needed in NFSv2
-		 * as it is guaranteed to always return the file attributes
-		 */
-		if (rdata->args.offset + rdata->args.count >= fattr->size)
-			rdata->res.eof = 1;
-	}
-	dprintk("NFS reply read: %d\n", status);
-	return status;
-}
-
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		int flags, struct nameidata *nd)
@@ -666,7 +637,6 @@
 	.lookup		= nfs_proc_lookup,
 	.access		= NULL,		       /* access */
 	.readlink	= nfs_proc_readlink,
-	.read		= nfs_proc_read,
 	.create		= nfs_proc_create,
 	.remove		= nfs_proc_remove,
 	.unlink_setup	= nfs_proc_unlink_setup,
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index a9c2652..6ab4d5a 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -5,14 +5,6 @@
  *
  * Partial copy of Linus' read cache modifications to fs/nfs/file.c
  * modified for async RPC by okir@monad.swb.de
- *
- * We do an ugly hack here in order to return proper error codes to the
- * user program when a read request failed: since generic_file_read
- * only checks the return value of inode->i_op->readpage() which is always 0
- * for async RPC, we set the error bit of the page to 1 when an error occurs,
- * and make nfs_readpage transmit requests synchronously when encountering this.
- * This is only a small problem, though, since we now retry all operations
- * within the RPC code when root squashing is suspected.
  */
 
 #include <linux/time.h>
@@ -122,93 +114,6 @@
 	}
 }
 
-/*
- * Read a page synchronously.
- */
-static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
-		struct page *page)
-{
-	unsigned int	rsize = NFS_SERVER(inode)->rsize;
-	unsigned int	count = PAGE_CACHE_SIZE;
-	int result = -ENOMEM;
-	struct nfs_read_data *rdata;
-
-	rdata = nfs_readdata_alloc(count);
-	if (!rdata)
-		goto out_unlock;
-
-	memset(rdata, 0, sizeof(*rdata));
-	rdata->flags = (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
-	rdata->cred = ctx->cred;
-	rdata->inode = inode;
-	INIT_LIST_HEAD(&rdata->pages);
-	rdata->args.fh = NFS_FH(inode);
-	rdata->args.context = ctx;
-	rdata->args.pages = &page;
-	rdata->args.pgbase = 0UL;
-	rdata->args.count = rsize;
-	rdata->res.fattr = &rdata->fattr;
-
-	dprintk("NFS: nfs_readpage_sync(%p)\n", page);
-
-	/*
-	 * This works now because the socket layer never tries to DMA
-	 * into this buffer directly.
-	 */
-	do {
-		if (count < rsize)
-			rdata->args.count = count;
-		rdata->res.count = rdata->args.count;
-		rdata->args.offset = page_offset(page) + rdata->args.pgbase;
-
-		dprintk("NFS: nfs_proc_read(%s, (%s/%Ld), %Lu, %u)\n",
-			NFS_SERVER(inode)->nfs_client->cl_hostname,
-			inode->i_sb->s_id,
-			(long long)NFS_FILEID(inode),
-			(unsigned long long)rdata->args.pgbase,
-			rdata->args.count);
-
-		lock_kernel();
-		result = NFS_PROTO(inode)->read(rdata);
-		unlock_kernel();
-
-		/*
-		 * Even if we had a partial success we can't mark the page
-		 * cache valid.
-		 */
-		if (result < 0) {
-			if (result == -EISDIR)
-				result = -EINVAL;
-			goto io_error;
-		}
-		count -= result;
-		rdata->args.pgbase += result;
-		nfs_add_stats(inode, NFSIOS_SERVERREADBYTES, result);
-
-		/* Note: result == 0 should only happen if we're caching
-		 * a write that extends the file and punches a hole.
-		 */
-		if (rdata->res.eof != 0 || result == 0)
-			break;
-	} while (count);
-	spin_lock(&inode->i_lock);
-	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
-	spin_unlock(&inode->i_lock);
-
-	if (rdata->res.eof || rdata->res.count == rdata->args.count) {
-		SetPageUptodate(page);
-		if (rdata->res.eof && count != 0)
-			memclear_highpage_flush(page, rdata->args.pgbase, count);
-	}
-	result = 0;
-
-io_error:
-	nfs_readdata_free(rdata);
-out_unlock:
-	unlock_page(page);
-	return result;
-}
-
 static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
 		struct page *page)
 {
@@ -278,7 +183,7 @@
 
 	data->task.tk_cookie = (unsigned long)inode;
 
-	dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n",
+	dprintk("NFS: %5u initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n",
 			data->task.tk_pid,
 			inode->i_sb->s_id,
 			(long long)NFS_FILEID(inode),
@@ -452,7 +357,7 @@
 {
 	int status;
 
-	dprintk("%s: %4d, (status %d)\n", __FUNCTION__, task->tk_pid,
+	dprintk("NFS: %s: %5u, (status %d)\n", __FUNCTION__, task->tk_pid,
 			task->tk_status);
 
 	status = NFS_PROTO(data->inode)->read_done(task, data);
@@ -621,15 +526,9 @@
 	} else
 		ctx = get_nfs_open_context((struct nfs_open_context *)
 				file->private_data);
-	if (!IS_SYNC(inode)) {
-		error = nfs_readpage_async(ctx, inode, page);
-		goto out;
-	}
 
-	error = nfs_readpage_sync(ctx, inode, page);
-	if (error < 0 && IS_SWAPFILE(inode))
-		printk("Aiee.. nfs swap-in of page failed!\n");
-out:
+	error = nfs_readpage_async(ctx, inode, page);
+
 	put_nfs_open_context(ctx);
 	return error;
 
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 28108c8..bb516a2 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -44,6 +44,7 @@
 #include <linux/vfs.h>
 #include <linux/inet.h>
 #include <linux/nfs_xdr.h>
+#include <linux/magic.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -81,7 +82,7 @@
 	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
 
-static struct super_operations nfs_sops = {
+static const struct super_operations nfs_sops = {
 	.alloc_inode	= nfs_alloc_inode,
 	.destroy_inode	= nfs_destroy_inode,
 	.write_inode	= nfs_write_inode,
@@ -125,7 +126,7 @@
 	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
 
-static struct super_operations nfs4_sops = {
+static const struct super_operations nfs4_sops = {
 	.alloc_inode	= nfs_alloc_inode,
 	.destroy_inode	= nfs_destroy_inode,
 	.write_inode	= nfs_write_inode,
@@ -1044,7 +1045,7 @@
 		nfs4_fill_super(s);
 	}
 
-	mntroot = nfs4_get_root(s, data->fh);
+	mntroot = nfs4_get_root(s, &mntfh);
 	if (IS_ERR(mntroot)) {
 		error = PTR_ERR(mntroot);
 		goto error_splat_super;
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 525c136..f4a0548 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -78,7 +78,7 @@
 /*
  * symlinks can't do much...
  */
-struct inode_operations nfs_symlink_inode_operations = {
+const struct inode_operations nfs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= nfs_follow_link,
 	.put_link	= page_put_link,
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c
index 3ea50ac..fcdcafb 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/sysctl.c
@@ -75,7 +75,7 @@
 
 int nfs_register_sysctl(void)
 {
-	nfs_callback_sysctl_table = register_sysctl_table(nfs_cb_sysctl_root, 0);
+	nfs_callback_sysctl_table = register_sysctl_table(nfs_cb_sysctl_root);
 	if (nfs_callback_sysctl_table == NULL)
 		return -ENOMEM;
 	return 0;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 345492e..febdade 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1,47 +1,7 @@
 /*
  * linux/fs/nfs/write.c
  *
- * Writing file data over NFS.
- *
- * We do it like this: When a (user) process wishes to write data to an
- * NFS file, a write request is allocated that contains the RPC task data
- * plus some info on the page to be written, and added to the inode's
- * write chain. If the process writes past the end of the page, an async
- * RPC call to write the page is scheduled immediately; otherwise, the call
- * is delayed for a few seconds.
- *
- * Just like readahead, no async I/O is performed if wsize < PAGE_SIZE.
- *
- * Write requests are kept on the inode's writeback list. Each entry in
- * that list references the page (portion) to be written. When the
- * cache timeout has expired, the RPC task is woken up, and tries to
- * lock the page. As soon as it manages to do so, the request is moved
- * from the writeback list to the writelock list.
- *
- * Note: we must make sure never to confuse the inode passed in the
- * write_page request with the one in page->inode. As far as I understand
- * it, these are different when doing a swap-out.
- *
- * To understand everything that goes on here and in the NFS read code,
- * one should be aware that a page is locked in exactly one of the following
- * cases:
- *
- *  -	A write request is in progress.
- *  -	A user process is in generic_file_write/nfs_update_page
- *  -	A user process is in generic_file_read
- *
- * Also note that because of the way pages are invalidated in
- * nfs_revalidate_inode, the following assertions hold:
- *
- *  -	If a page is dirty, there will be no read requests (a page will
- *	not be re-read unless invalidated by nfs_revalidate_inode).
- *  -	If the page is not uptodate, there will be no pending write
- *	requests, and no process will be in nfs_update_page.
- *
- * FIXME: Interaction with the vmscan routines is not optimal yet.
- * Either vmscan must be made nfs-savvy, or we need a different page
- * reclaim concept that supports something like FS-independent
- * buffer_heads with a b_ops-> field.
+ * Write file data over NFS.
  *
  * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
  */
@@ -79,7 +39,6 @@
 					    unsigned int, unsigned int);
 static void nfs_mark_request_dirty(struct nfs_page *req);
 static int nfs_wait_on_write_congestion(struct address_space *, int);
-static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int);
 static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how);
 static const struct rpc_call_ops nfs_write_partial_ops;
 static const struct rpc_call_ops nfs_write_full_ops;
@@ -194,6 +153,13 @@
 	i_size_write(inode, end);
 }
 
+/* A writeback failed: mark the page as bad, and invalidate the page cache */
+static void nfs_set_pageerror(struct page *page)
+{
+	SetPageError(page);
+	nfs_zap_mapping(page->mapping->host, page->mapping);
+}
+
 /* We can set the PG_uptodate flag if we see that a write request
  * covers the full page.
  */
@@ -323,7 +289,7 @@
 		err = 0;
 out:
 	if (!wbc->for_writepages)
-		nfs_flush_mapping(page->mapping, wbc, wb_priority(wbc));
+		nfs_flush_mapping(page->mapping, wbc, FLUSH_STABLE|wb_priority(wbc));
 	return err;
 }
 
@@ -360,14 +326,7 @@
 	if (err < 0)
 		goto out;
 	nfs_add_stats(inode, NFSIOS_WRITEPAGES, err);
-	if (!wbc->nonblocking && wbc->sync_mode == WB_SYNC_ALL) {
-		err = nfs_wait_on_requests(inode, 0, 0);
-		if (err < 0)
-			goto out;
-	}
-	err = nfs_commit_inode(inode, wb_priority(wbc));
-	if (err > 0)
-		err = 0;
+	err = 0;
 out:
 	clear_bit(BDI_write_congested, &bdi->state);
 	wake_up_all(&nfs_write_congestion);
@@ -516,17 +475,6 @@
 	return res;
 }
 
-static int nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int npages)
-{
-	struct nfs_inode *nfsi = NFS_I(inode);
-	int ret;
-
-	spin_lock(&nfsi->req_lock);
-	ret = nfs_wait_on_requests_locked(inode, idx_start, npages);
-	spin_unlock(&nfsi->req_lock);
-	return ret;
-}
-
 static void nfs_cancel_dirty_list(struct list_head *head)
 {
 	struct nfs_page *req;
@@ -773,7 +721,7 @@
         dprintk("NFS:      nfs_updatepage returns %d (isize %Ld)\n",
 			status, (long long)i_size_read(inode));
 	if (status < 0)
-		ClearPageUptodate(page);
+		nfs_set_pageerror(page);
 	return status;
 }
 
@@ -852,7 +800,8 @@
 	data->task.tk_priority = flush_task_priority(how);
 	data->task.tk_cookie = (unsigned long)inode;
 
-	dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n",
+	dprintk("NFS: %5u initiated write call "
+		"(req %s/%Ld, %u bytes @ offset %Lu)\n",
 		data->task.tk_pid,
 		inode->i_sb->s_id,
 		(long long)NFS_FILEID(inode),
@@ -1034,8 +983,7 @@
 		return;
 
 	if (task->tk_status < 0) {
-		ClearPageUptodate(page);
-		SetPageError(page);
+		nfs_set_pageerror(page);
 		req->wb_context->error = task->tk_status;
 		dprintk(", error = %d\n", task->tk_status);
 	} else {
@@ -1092,8 +1040,7 @@
 			(long long)req_offset(req));
 
 		if (task->tk_status < 0) {
-			ClearPageUptodate(page);
-			SetPageError(page);
+			nfs_set_pageerror(page);
 			req->wb_context->error = task->tk_status;
 			end_page_writeback(page);
 			nfs_inode_remove_request(req);
@@ -1134,7 +1081,7 @@
 	struct nfs_writeres	*resp = &data->res;
 	int status;
 
-	dprintk("NFS: %4d nfs_writeback_done (status %d)\n",
+	dprintk("NFS: %5u nfs_writeback_done (status %d)\n",
 		task->tk_pid, task->tk_status);
 
 	/*
@@ -1250,7 +1197,7 @@
 	data->task.tk_priority = flush_task_priority(how);
 	data->task.tk_cookie = (unsigned long)inode;
 	
-	dprintk("NFS: %4d initiated commit call\n", data->task.tk_pid);
+	dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
 }
 
 /*
@@ -1291,7 +1238,7 @@
 	struct nfs_write_data	*data = calldata;
 	struct nfs_page		*req;
 
-        dprintk("NFS: %4d nfs_commit_done (status %d)\n",
+        dprintk("NFS: %5u nfs_commit_done (status %d)\n",
                                 task->tk_pid, task->tk_status);
 
 	/* Call the NFS version-specific code */
@@ -1516,6 +1463,8 @@
 		if (ret < 0)
 			goto out;
 	}
+	if (!PagePrivate(page))
+		return 0;
 	ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
 	if (ret >= 0)
 		return 0;
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 49c310b..6f24768 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -16,7 +16,6 @@
 
 #include <linux/unistd.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/in.h>
 #include <linux/seq_file.h>
@@ -190,18 +189,17 @@
 		       struct cache_head *h)
 {
 	struct svc_expkey *ek ;
+	int i;
 
 	if (h ==NULL) {
 		seq_puts(m, "#domain fsidtype fsid [path]\n");
 		return 0;
 	}
 	ek = container_of(h, struct svc_expkey, h);
-	seq_printf(m, "%s %d 0x%08x", ek->ek_client->name,
-		   ek->ek_fsidtype, ek->ek_fsid[0]);
-	if (ek->ek_fsidtype != 1)
-		seq_printf(m, "%08x", ek->ek_fsid[1]);
-	if (ek->ek_fsidtype == 2)
-		seq_printf(m, "%08x", ek->ek_fsid[2]);
+	seq_printf(m, "%s %d 0x", ek->ek_client->name,
+		   ek->ek_fsidtype);
+	for (i=0; i < key_len(ek->ek_fsidtype)/4; i++)
+		seq_printf(m, "%08x", ek->ek_fsid[i]);
 	if (test_bit(CACHE_VALID, &h->flags) && 
 	    !test_bit(CACHE_NEGATIVE, &h->flags)) {
 		seq_printf(m, " ");
@@ -232,9 +230,8 @@
 	kref_get(&item->ek_client->ref);
 	new->ek_client = item->ek_client;
 	new->ek_fsidtype = item->ek_fsidtype;
-	new->ek_fsid[0] = item->ek_fsid[0];
-	new->ek_fsid[1] = item->ek_fsid[1];
-	new->ek_fsid[2] = item->ek_fsid[2];
+
+	memcpy(new->ek_fsid, item->ek_fsid, sizeof(new->ek_fsid));
 }
 
 static inline void expkey_update(struct cache_head *cnew,
@@ -363,7 +360,7 @@
 					    struct svc_export *old);
 static struct svc_export *svc_export_lookup(struct svc_export *);
 
-static int check_export(struct inode *inode, int flags)
+static int check_export(struct inode *inode, int flags, unsigned char *uuid)
 {
 
 	/* We currently export only dirs and regular files.
@@ -376,12 +373,13 @@
 	/* There are two requirements on a filesystem to be exportable.
 	 * 1:  We must be able to identify the filesystem from a number.
 	 *       either a device number (so FS_REQUIRES_DEV needed)
-	 *       or an FSID number (so NFSEXP_FSID needed).
+	 *       or an FSID number (so NFSEXP_FSID or ->uuid is needed).
 	 * 2:  We must be able to find an inode from a filehandle.
 	 *       This means that s_export_op must be set.
 	 */
 	if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
-	    !(flags & NFSEXP_FSID)) {
+	    !(flags & NFSEXP_FSID) &&
+	    uuid == NULL) {
 		dprintk("exp_export: export of non-dev fs without fsid\n");
 		return -EINVAL;
 	}
@@ -406,10 +404,6 @@
 	int len;
 	int migrated, i, err;
 
-	len = qword_get(mesg, buf, PAGE_SIZE);
-	if (len != 5 || memcmp(buf, "fsloc", 5))
-		return 0;
-
 	/* listsize */
 	err = get_int(mesg, &fsloc->locations_count);
 	if (err)
@@ -520,6 +514,8 @@
 	exp.ex_fslocs.locations_count = 0;
 	exp.ex_fslocs.migrated = 0;
 
+	exp.ex_uuid = NULL;
+
 	/* flags */
 	err = get_int(&mesg, &an_int);
 	if (err == -ENOENT)
@@ -543,12 +539,33 @@
 		if (err) goto out;
 		exp.ex_fsid = an_int;
 
-		err = check_export(nd.dentry->d_inode, exp.ex_flags);
-		if (err) goto out;
+		while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) {
+			if (strcmp(buf, "fsloc") == 0)
+				err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
+			else if (strcmp(buf, "uuid") == 0) {
+				/* expect a 16 byte uuid encoded as \xXXXX... */
+				len = qword_get(&mesg, buf, PAGE_SIZE);
+				if (len != 16)
+					err  = -EINVAL;
+				else {
+					exp.ex_uuid =
+						kmemdup(buf, 16, GFP_KERNEL);
+					if (exp.ex_uuid == NULL)
+						err = -ENOMEM;
+				}
+			} else
+				/* quietly ignore unknown words and anything
+				 * following. Newer user-space can try to set
+				 * new values, then see what the result was.
+				 */
+				break;
+			if (err)
+				goto out;
+		}
 
-		err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
-		if (err)
-			goto out;
+		err = check_export(nd.dentry->d_inode, exp.ex_flags,
+				   exp.ex_uuid);
+		if (err) goto out;
 	}
 
 	expp = svc_export_lookup(&exp);
@@ -562,6 +579,8 @@
 	else
 		exp_put(expp);
  out:
+	nfsd4_fslocs_free(&exp.ex_fslocs);
+	kfree(exp.ex_uuid);
  	kfree(exp.ex_path);
 	if (nd.dentry)
 		path_release(&nd);
@@ -591,9 +610,19 @@
 	seq_escape(m, exp->ex_client->name, " \t\n\\");
 	seq_putc(m, '(');
 	if (test_bit(CACHE_VALID, &h->flags) && 
-	    !test_bit(CACHE_NEGATIVE, &h->flags))
+	    !test_bit(CACHE_NEGATIVE, &h->flags)) {
 		exp_flags(m, exp->ex_flags, exp->ex_fsid,
 			  exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs);
+		if (exp->ex_uuid) {
+			int i;
+			seq_puts(m, ",uuid=");
+			for (i=0; i<16; i++) {
+				if ((i&3) == 0 && i)
+					seq_putc(m, ':');
+				seq_printf(m, "%02x", exp->ex_uuid[i]);
+			}
+		}
+	}
 	seq_puts(m, ")\n");
 	return 0;
 }
@@ -630,6 +659,8 @@
 	new->ex_anon_uid = item->ex_anon_uid;
 	new->ex_anon_gid = item->ex_anon_gid;
 	new->ex_fsid = item->ex_fsid;
+	new->ex_uuid = item->ex_uuid;
+	item->ex_uuid = NULL;
 	new->ex_path = item->ex_path;
 	item->ex_path = NULL;
 	new->ex_fslocs.locations = item->ex_fslocs.locations;
@@ -752,11 +783,11 @@
 	u32 fsidv[3];
 	
 	if (old_valid_dev(dev)) {
-		mk_fsid_v0(fsidv, dev, ino);
-		return exp_find_key(clp, 0, fsidv, NULL);
+		mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL);
+		return exp_find_key(clp, FSID_DEV, fsidv, NULL);
 	}
-	mk_fsid_v3(fsidv, dev, ino);
-	return exp_find_key(clp, 3, fsidv, NULL);
+	mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL);
+	return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL);
 }
 
 /*
@@ -767,9 +798,9 @@
 {
 	u32 fsidv[2];
 
-	mk_fsid_v1(fsidv, fsid);
+	mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL);
 
-	return exp_find_key(clp, 1, fsidv, NULL);
+	return exp_find_key(clp, FSID_NUM, fsidv, NULL);
 }
 
 svc_export *
@@ -883,8 +914,8 @@
 	if ((exp->ex_flags & NFSEXP_FSID) == 0)
 		return 0;
 
-	mk_fsid_v1(fsid, exp->ex_fsid);
-	return exp_set_key(clp, 1, fsid, exp);
+	mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL);
+	return exp_set_key(clp, FSID_NUM, fsid, exp);
 }
 
 static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
@@ -894,11 +925,11 @@
 	dev_t dev = inode->i_sb->s_dev;
 
 	if (old_valid_dev(dev)) {
-		mk_fsid_v0(fsid, dev, inode->i_ino);
-		return exp_set_key(clp, 0, fsid, exp);
+		mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL);
+		return exp_set_key(clp, FSID_DEV, fsid, exp);
 	}
-	mk_fsid_v3(fsid, dev, inode->i_ino);
-	return exp_set_key(clp, 3, fsid, exp);
+	mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL);
+	return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp);
 }
 
 static void exp_unhash(struct svc_export *exp)
@@ -977,7 +1008,7 @@
 		goto finish;
 	}
 
-	err = check_export(nd.dentry->d_inode, nxp->ex_flags);
+	err = check_export(nd.dentry->d_inode, nxp->ex_flags, NULL);
 	if (err) goto finish;
 
 	err = -ENOMEM;
@@ -1170,9 +1201,9 @@
 	__be32 rv;
 	u32 fsidv[2];
 
-	mk_fsid_v1(fsidv, 0);
+	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
 
-	exp = exp_find(clp, 1, fsidv, creq);
+	exp = exp_find(clp, FSID_NUM, fsidv, creq);
 	if (IS_ERR(exp))
 		return nfserrno(PTR_ERR(exp));
 	if (exp == NULL)
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index edde5dc..b617428 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -287,13 +287,20 @@
 	return 1;
 }
 
-static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, __be32 *p,
-		struct nfsd_fhandle *resp)
+static int nfsaclsvc_release_attrstat(struct svc_rqst *rqstp, __be32 *p,
+		struct nfsd_attrstat *resp)
 {
 	fh_put(&resp->fh);
 	return 1;
 }
 
+static int nfsaclsvc_release_access(struct svc_rqst *rqstp, __be32 *p,
+               struct nfsd3_accessres *resp)
+{
+       fh_put(&resp->fh);
+       return 1;
+}
+
 #define nfsaclsvc_decode_voidargs	NULL
 #define nfsaclsvc_encode_voidres	NULL
 #define nfsaclsvc_release_void		NULL
@@ -322,9 +329,9 @@
 static struct svc_procedure		nfsd_acl_procedures2[] = {
   PROC(null,	void,		void,		void,	  RC_NOCACHE, ST),
   PROC(getacl,	getacl,		getacl,		getacl,	  RC_NOCACHE, ST+1+2*(1+ACL)),
-  PROC(setacl,	setacl,		attrstat,	fhandle,  RC_NOCACHE, ST+AT),
-  PROC(getattr, fhandle,	attrstat,	fhandle,  RC_NOCACHE, ST+AT),
-  PROC(access,	access,		access,		fhandle,  RC_NOCACHE, ST+AT+1),
+  PROC(setacl,	setacl,		attrstat,	attrstat, RC_NOCACHE, ST+AT),
+  PROC(getattr, fhandle,	attrstat,	attrstat, RC_NOCACHE, ST+AT),
+  PROC(access,	access,		access,		access,   RC_NOCACHE, ST+AT+1),
 };
 
 struct svc_version	nfsd_acl_version2 = {
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index e695660..6f67798 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -149,6 +149,27 @@
 	return p;
 }
 
+static __be32 *encode_fsid(__be32 *p, struct svc_fh *fhp)
+{
+	u64 f;
+	switch(fsid_source(fhp)) {
+	default:
+	case FSIDSOURCE_DEV:
+		p = xdr_encode_hyper(p, (u64)huge_encode_dev
+				     (fhp->fh_dentry->d_inode->i_sb->s_dev));
+		break;
+	case FSIDSOURCE_FSID:
+		p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
+		break;
+	case FSIDSOURCE_UUID:
+		f = ((u64*)fhp->fh_export->ex_uuid)[0];
+		f ^= ((u64*)fhp->fh_export->ex_uuid)[1];
+		p = xdr_encode_hyper(p, f);
+		break;
+	}
+	return p;
+}
+
 static __be32 *
 encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
 	      struct kstat *stat)
@@ -169,10 +190,7 @@
 	p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
 	*p++ = htonl((u32) MAJOR(stat->rdev));
 	*p++ = htonl((u32) MINOR(stat->rdev));
-	if (is_fsid(fhp, rqstp->rq_reffh))
-		p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
-	else
-		p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat->dev));
+	p = encode_fsid(p, fhp);
 	p = xdr_encode_hyper(p, (u64) stat->ino);
 	p = encode_time3(p, &stat->atime);
 	lease_get_mtime(dentry->d_inode, &time); 
@@ -203,10 +221,7 @@
 	p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
 	*p++ = fhp->fh_post_rdev[0];
 	*p++ = fhp->fh_post_rdev[1];
-	if (is_fsid(fhp, rqstp->rq_reffh))
-		p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
-	else
-		p = xdr_encode_hyper(p, (u64)huge_encode_dev(inode->i_sb->s_dev));
+	p = encode_fsid(p, fhp);
 	p = xdr_encode_hyper(p, (u64) inode->i_ino);
 	p = encode_time3(p, &fhp->fh_post_atime);
 	p = encode_time3(p, &fhp->fh_post_mtime);
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 5d94555..832673b 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -61,9 +61,11 @@
 
 /* flags used to simulate posix default ACLs */
 #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
-		| NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
+		| NFS4_ACE_DIRECTORY_INHERIT_ACE)
 
-#define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS | NFS4_ACE_IDENTIFIER_GROUP)
+#define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS \
+		| NFS4_ACE_INHERIT_ONLY_ACE \
+		| NFS4_ACE_IDENTIFIER_GROUP)
 
 #define MASK_EQUAL(mask1, mask2) \
 	( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) )
@@ -87,12 +89,19 @@
 }
 
 static u32
-deny_mask(u32 allow_mask, unsigned int flags)
+deny_mask_from_posix(unsigned short perm, u32 flags)
 {
-	u32 ret = ~allow_mask & ~NFS4_MASK_UNSUPP;
-	if (!(flags & NFS4_ACL_DIR))
-		ret &= ~NFS4_ACE_DELETE_CHILD;
-	return ret;
+	u32 mask = 0;
+
+	if (perm & ACL_READ)
+		mask |= NFS4_READ_MODE;
+	if (perm & ACL_WRITE)
+		mask |= NFS4_WRITE_MODE;
+	if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
+		mask |= NFS4_ACE_DELETE_CHILD;
+	if (perm & ACL_EXECUTE)
+		mask |= NFS4_EXECUTE_MODE;
+	return mask;
 }
 
 /* XXX: modify functions to return NFS errors; they're only ever
@@ -126,108 +135,151 @@
 };
 
 static short ace2type(struct nfs4_ace *);
-static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
-static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
-int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
-static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
+static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
+				unsigned int);
+void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
 
 struct nfs4_acl *
 nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
 			unsigned int flags)
 {
 	struct nfs4_acl *acl;
-	int error = -EINVAL;
+	int size = 0;
 
-	if ((pacl != NULL &&
-		(posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) ||
-	    (dpacl != NULL &&
-		(posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0)))
-		goto out_err;
-
-	acl = nfs4_acl_new();
-	if (acl == NULL) {
-		error = -ENOMEM;
-		goto out_err;
+	if (pacl) {
+		if (posix_acl_valid(pacl) < 0)
+			return ERR_PTR(-EINVAL);
+		size += 2*pacl->a_count;
+	}
+	if (dpacl) {
+		if (posix_acl_valid(dpacl) < 0)
+			return ERR_PTR(-EINVAL);
+		size += 2*dpacl->a_count;
 	}
 
-	if (pacl != NULL) {
-		error = _posix_to_nfsv4_one(pacl, acl,
-						flags & ~NFS4_ACL_TYPE_DEFAULT);
-		if (error < 0)
-			goto out_acl;
-	}
+	/* Allocate for worst case: one (deny, allow) pair each: */
+	acl = nfs4_acl_new(size);
+	if (acl == NULL)
+		return ERR_PTR(-ENOMEM);
 
-	if (dpacl != NULL) {
-		error = _posix_to_nfsv4_one(dpacl, acl,
-						flags | NFS4_ACL_TYPE_DEFAULT);
-		if (error < 0)
-			goto out_acl;
-	}
+	if (pacl)
+		_posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
 
-	return acl;
-
-out_acl:
-	nfs4_acl_free(acl);
-out_err:
-	acl = ERR_PTR(error);
+	if (dpacl)
+		_posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT);
 
 	return acl;
 }
 
-static int
-nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype,
-		uid_t owner, unsigned int flags)
-{
-	int error;
+struct posix_acl_summary {
+	unsigned short owner;
+	unsigned short users;
+	unsigned short group;
+	unsigned short groups;
+	unsigned short other;
+	unsigned short mask;
+};
 
-	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
-				 eflag, mask, whotype, owner);
-	if (error < 0)
-		return error;
-	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-				eflag, deny_mask(mask, flags), whotype, owner);
-	return error;
+static void
+summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
+{
+	struct posix_acl_entry *pa, *pe;
+	pas->users = 0;
+	pas->groups = 0;
+	pas->mask = 07;
+
+	pe = acl->a_entries + acl->a_count;
+
+	FOREACH_ACL_ENTRY(pa, acl, pe) {
+		switch (pa->e_tag) {
+			case ACL_USER_OBJ:
+				pas->owner = pa->e_perm;
+				break;
+			case ACL_GROUP_OBJ:
+				pas->group = pa->e_perm;
+				break;
+			case ACL_USER:
+				pas->users |= pa->e_perm;
+				break;
+			case ACL_GROUP:
+				pas->groups |= pa->e_perm;
+				break;
+			case ACL_OTHER:
+				pas->other = pa->e_perm;
+				break;
+			case ACL_MASK:
+				pas->mask = pa->e_perm;
+				break;
+		}
+	}
+	/* We'll only care about effective permissions: */
+	pas->users &= pas->mask;
+	pas->group &= pas->mask;
+	pas->groups &= pas->mask;
 }
 
 /* We assume the acl has been verified with posix_acl_valid. */
-static int
+static void
 _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
 						unsigned int flags)
 {
-	struct posix_acl_entry *pa, *pe, *group_owner_entry;
-	int error = -EINVAL;
-	u32 mask, mask_mask;
+	struct posix_acl_entry *pa, *group_owner_entry;
+	struct nfs4_ace *ace;
+	struct posix_acl_summary pas;
+	unsigned short deny;
 	int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
 					NFS4_INHERITANCE_FLAGS : 0);
 
 	BUG_ON(pacl->a_count < 3);
-	pe = pacl->a_entries + pacl->a_count;
-	pa = pe - 2; /* if mask entry exists, it's second from the last. */
-	if (pa->e_tag == ACL_MASK)
-		mask_mask = deny_mask(mask_from_posix(pa->e_perm, flags), flags);
-	else
-		mask_mask = 0;
+	summarize_posix_acl(pacl, &pas);
 
 	pa = pacl->a_entries;
-	BUG_ON(pa->e_tag != ACL_USER_OBJ);
-	mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
-	error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
-	if (error < 0)
-		goto out;
+	ace = acl->aces + acl->naces;
+
+	/* We could deny everything not granted by the owner: */
+	deny = ~pas.owner;
+	/*
+	 * but it is equivalent (and simpler) to deny only what is not
+	 * granted by later entries:
+	 */
+	deny &= pas.users | pas.group | pas.groups | pas.other;
+	if (deny) {
+		ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
+		ace->flag = eflag;
+		ace->access_mask = deny_mask_from_posix(deny, flags);
+		ace->whotype = NFS4_ACL_WHO_OWNER;
+		ace++;
+		acl->naces++;
+	}
+
+	ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
+	ace->flag = eflag;
+	ace->access_mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
+	ace->whotype = NFS4_ACL_WHO_OWNER;
+	ace++;
+	acl->naces++;
 	pa++;
 
 	while (pa->e_tag == ACL_USER) {
-		mask = mask_from_posix(pa->e_perm, flags);
-		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-				eflag,  mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id);
-		if (error < 0)
-			goto out;
-
-
-		error = nfs4_acl_add_pair(acl, eflag, mask,
-				NFS4_ACL_WHO_NAMED, pa->e_id, flags);
-		if (error < 0)
-			goto out;
+		deny = ~(pa->e_perm & pas.mask);
+		deny &= pas.groups | pas.group | pas.other;
+		if (deny) {
+			ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
+			ace->flag = eflag;
+			ace->access_mask = deny_mask_from_posix(deny, flags);
+			ace->whotype = NFS4_ACL_WHO_NAMED;
+			ace->who = pa->e_id;
+			ace++;
+			acl->naces++;
+		}
+		ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
+		ace->flag = eflag;
+		ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
+						   flags);
+		ace->whotype = NFS4_ACL_WHO_NAMED;
+		ace->who = pa->e_id;
+		ace++;
+		acl->naces++;
 		pa++;
 	}
 
@@ -236,67 +288,65 @@
 
 	/* allow ACEs */
 
-	if (pacl->a_count > 3) {
-		BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
-		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-				NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
-				NFS4_ACL_WHO_GROUP, 0);
-		if (error < 0)
-			goto out;
-	}
 	group_owner_entry = pa;
-	mask = mask_from_posix(pa->e_perm, flags);
-	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
-			NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
-			NFS4_ACL_WHO_GROUP, 0);
-	if (error < 0)
-		goto out;
+
+	ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
+	ace->flag = eflag;
+	ace->access_mask = mask_from_posix(pas.group, flags);
+	ace->whotype = NFS4_ACL_WHO_GROUP;
+	ace++;
+	acl->naces++;
 	pa++;
 
 	while (pa->e_tag == ACL_GROUP) {
-		mask = mask_from_posix(pa->e_perm, flags);
-		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-				NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
-				NFS4_ACL_WHO_NAMED, pa->e_id);
-		if (error < 0)
-			goto out;
-
-		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
-		    		NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
-		    		NFS4_ACL_WHO_NAMED, pa->e_id);
-		if (error < 0)
-			goto out;
+		ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
+		ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
+		ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
+						   flags);
+		ace->whotype = NFS4_ACL_WHO_NAMED;
+		ace->who = pa->e_id;
+		ace++;
+		acl->naces++;
 		pa++;
 	}
 
 	/* deny ACEs */
 
 	pa = group_owner_entry;
-	mask = mask_from_posix(pa->e_perm, flags);
-	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-			NFS4_ACE_IDENTIFIER_GROUP | eflag,
-			deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0);
-	if (error < 0)
-		goto out;
+
+	deny = ~pas.group & pas.other;
+	if (deny) {
+		ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
+		ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
+		ace->access_mask = deny_mask_from_posix(deny, flags);
+		ace->whotype = NFS4_ACL_WHO_GROUP;
+		ace++;
+		acl->naces++;
+	}
 	pa++;
+
 	while (pa->e_tag == ACL_GROUP) {
-		mask = mask_from_posix(pa->e_perm, flags);
-		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
-		    		NFS4_ACE_IDENTIFIER_GROUP | eflag,
-		    		deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id);
-		if (error < 0)
-			goto out;
+		deny = ~(pa->e_perm & pas.mask);
+		deny &= pas.other;
+		if (deny) {
+			ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
+			ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
+			ace->access_mask = mask_from_posix(deny, flags);
+			ace->whotype = NFS4_ACL_WHO_NAMED;
+			ace->who = pa->e_id;
+			ace++;
+			acl->naces++;
+		}
 		pa++;
 	}
 
 	if (pa->e_tag == ACL_MASK)
 		pa++;
-	BUG_ON(pa->e_tag != ACL_OTHER);
-	mask = mask_from_posix(pa->e_perm, flags);
-	error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
-
-out:
-	return error;
+	ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
+	ace->flag = eflag;
+	ace->access_mask = mask_from_posix(pa->e_perm, flags);
+	ace->whotype = NFS4_ACL_WHO_EVERYONE;
+	acl->naces++;
 }
 
 static void
@@ -342,46 +392,6 @@
 	return;
 }
 
-int
-nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
-		struct posix_acl **dpacl, unsigned int flags)
-{
-	struct nfs4_acl *dacl;
-	int error = -ENOMEM;
-
-	*pacl = NULL;
-	*dpacl = NULL;
-
-	dacl = nfs4_acl_new();
-	if (dacl == NULL)
-		goto out;
-
-	error = nfs4_acl_split(acl, dacl);
-	if (error)
-		goto out_acl;
-
-	*pacl = _nfsv4_to_posix_one(acl, flags);
-	if (IS_ERR(*pacl)) {
-		error = PTR_ERR(*pacl);
-		*pacl = NULL;
-		goto out_acl;
-	}
-
-	*dpacl = _nfsv4_to_posix_one(dacl, flags);
-	if (IS_ERR(*dpacl)) {
-		error = PTR_ERR(*dpacl);
-		*dpacl = NULL;
-	}
-out_acl:
-	if (error) {
-		posix_acl_release(*pacl);
-		*pacl = NULL;
-	}
-	nfs4_acl_free(dacl);
-out:
-	return error;
-}
-
 /*
  * While processing the NFSv4 ACE, this maintains bitmasks representing
  * which permission bits have been allowed and which denied to a given
@@ -406,6 +416,7 @@
  * calculated so far: */
 
 struct posix_acl_state {
+	int empty;
 	struct posix_ace_state owner;
 	struct posix_ace_state group;
 	struct posix_ace_state other;
@@ -421,6 +432,7 @@
 	int alloc;
 
 	memset(state, 0, sizeof(struct posix_acl_state));
+	state->empty = 1;
 	/*
 	 * In the worst case, each individual acl could be for a distinct
 	 * named user or group, but we don't no which, so we allocate
@@ -488,6 +500,20 @@
 	int nace;
 	int i, error = 0;
 
+	/*
+	 * ACLs with no ACEs are treated differently in the inheritable
+	 * and effective cases: when there are no inheritable ACEs, we
+	 * set a zero-length default posix acl:
+	 */
+	if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) {
+		pacl = posix_acl_alloc(0, GFP_KERNEL);
+		return pacl ? pacl : ERR_PTR(-ENOMEM);
+	}
+	/*
+	 * When there are no effective ACEs, the following will end
+	 * up setting a 3-element effective posix ACL with all
+	 * permissions zero.
+	 */
 	nace = 4 + state->users->n + state->groups->n;
 	pacl = posix_acl_alloc(nace, GFP_KERNEL);
 	if (!pacl)
@@ -603,6 +629,8 @@
 	u32 mask = ace->access_mask;
 	int i;
 
+	state->empty = 0;
+
 	switch (ace2type(ace)) {
 	case ACL_USER_OBJ:
 		if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
@@ -666,75 +694,62 @@
 	}
 }
 
-static struct posix_acl *
-_nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags)
+int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
+			    struct posix_acl **dpacl, unsigned int flags)
 {
-	struct posix_acl_state state;
-	struct posix_acl *pacl;
+	struct posix_acl_state effective_acl_state, default_acl_state;
 	struct nfs4_ace *ace;
 	int ret;
 
-	ret = init_state(&state, n4acl->naces);
+	ret = init_state(&effective_acl_state, acl->naces);
 	if (ret)
-		return ERR_PTR(ret);
-
-	list_for_each_entry(ace, &n4acl->ace_head, l_ace)
-		process_one_v4_ace(&state, ace);
-
-	pacl = posix_state_to_acl(&state, flags);
-
-	free_state(&state);
-
-	if (!IS_ERR(pacl))
-		sort_pacl(pacl);
-	return pacl;
-}
-
-static int
-nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
-{
-	struct list_head *h, *n;
-	struct nfs4_ace *ace;
-	int error = 0;
-
-	list_for_each_safe(h, n, &acl->ace_head) {
-		ace = list_entry(h, struct nfs4_ace, l_ace);
-
+		return ret;
+	ret = init_state(&default_acl_state, acl->naces);
+	if (ret)
+		goto out_estate;
+	ret = -EINVAL;
+	for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
 		if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
 		    ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
-			return -EINVAL;
-
+			goto out_dstate;
 		if (ace->flag & ~NFS4_SUPPORTED_FLAGS)
-			return -EINVAL;
-
-		switch (ace->flag & NFS4_INHERITANCE_FLAGS) {
-		case 0:
-			/* Leave this ace in the effective acl: */
+			goto out_dstate;
+		if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {
+			process_one_v4_ace(&effective_acl_state, ace);
 			continue;
-		case NFS4_INHERITANCE_FLAGS:
-			/* Add this ace to the default acl and remove it
-			 * from the effective acl: */
-			error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
-				ace->access_mask, ace->whotype, ace->who);
-			if (error)
-				return error;
-			list_del(h);
-			kfree(ace);
-			acl->naces--;
-			break;
-		case NFS4_INHERITANCE_FLAGS & ~NFS4_ACE_INHERIT_ONLY_ACE:
-			/* Add this ace to the default, but leave it in
-			 * the effective acl as well: */
-			error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
-				ace->access_mask, ace->whotype, ace->who);
-			if (error)
-				return error;
-			break;
-		default:
-			return -EINVAL;
 		}
+		if (!(flags & NFS4_ACL_DIR))
+			goto out_dstate;
+		/*
+		 * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT
+		 * is set, we're effectively turning on the other.  That's OK,
+		 * according to rfc 3530.
+		 */
+		process_one_v4_ace(&default_acl_state, ace);
+
+		if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE))
+			process_one_v4_ace(&effective_acl_state, ace);
 	}
-	return 0;
+	*pacl = posix_state_to_acl(&effective_acl_state, flags);
+	if (IS_ERR(*pacl)) {
+		ret = PTR_ERR(*pacl);
+		goto out_dstate;
+	}
+	*dpacl = posix_state_to_acl(&default_acl_state,
+						flags | NFS4_ACL_TYPE_DEFAULT);
+	if (IS_ERR(*dpacl)) {
+		ret = PTR_ERR(*dpacl);
+		posix_acl_release(*pacl);
+		goto out_dstate;
+	}
+	sort_pacl(*pacl);
+	sort_pacl(*dpacl);
+	ret = 0;
+out_dstate:
+	free_state(&default_acl_state);
+out_estate:
+	free_state(&effective_acl_state);
+	return ret;
 }
 
 static short
@@ -759,48 +774,22 @@
 EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
 
 struct nfs4_acl *
-nfs4_acl_new(void)
+nfs4_acl_new(int n)
 {
 	struct nfs4_acl *acl;
 
-	if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL)
+	acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL);
+	if (acl == NULL)
 		return NULL;
-
 	acl->naces = 0;
-	INIT_LIST_HEAD(&acl->ace_head);
-
 	return acl;
 }
 
 void
-nfs4_acl_free(struct nfs4_acl *acl)
-{
-	struct list_head *h;
-	struct nfs4_ace *ace;
-
-	if (!acl)
-		return;
-
-	while (!list_empty(&acl->ace_head)) {
-		h = acl->ace_head.next;
-		list_del(h);
-		ace = list_entry(h, struct nfs4_ace, l_ace);
-		kfree(ace);
-	}
-
-	kfree(acl);
-
-	return;
-}
-
-int
 nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
 		int whotype, uid_t who)
 {
-	struct nfs4_ace *ace;
-
-	if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
-		return -ENOMEM;
+	struct nfs4_ace *ace = acl->aces + acl->naces;
 
 	ace->type = type;
 	ace->flag = flag;
@@ -808,10 +797,7 @@
 	ace->whotype = whotype;
 	ace->who = who;
 
-	list_add_tail(&ace->l_ace, &acl->ace_head);
 	acl->naces++;
-
-	return 0;
 }
 
 static struct {
@@ -865,7 +851,6 @@
 }
 
 EXPORT_SYMBOL(nfs4_acl_new);
-EXPORT_SYMBOL(nfs4_acl_free);
 EXPORT_SYMBOL(nfs4_acl_add_ace);
 EXPORT_SYMBOL(nfs4_acl_get_whotype);
 EXPORT_SYMBOL(nfs4_acl_write_who);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index f57655a..fb14d68 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -387,7 +387,6 @@
 		.address	= (struct sockaddr *)&addr,
 		.addrsize	= sizeof(addr),
 		.timeout	= &timeparms,
-		.servername	= clp->cl_name.data,
 		.program	= program,
 		.version	= nfs_cb_version[1]->number,
 		.authflavor	= RPC_AUTH_UNIX,	/* XXX: need AUTH_GSS... */
@@ -397,6 +396,7 @@
 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
 		.rpc_argp       = clp,
 	};
+	char clientname[16];
 	int status;
 
 	if (atomic_read(&cb->cb_set))
@@ -419,6 +419,11 @@
 	memset(program->stats, 0, sizeof(cb->cb_stat));
 	program->stats->program = program;
 
+	/* Just here to make some printk's more useful: */
+	snprintf(clientname, sizeof(clientname),
+		"%u.%u.%u.%u", NIPQUAD(addr.sin_addr));
+	args.servername = clientname;
+
 	/* Create RPC client */
 	cb->cb_client = rpc_create(&args);
 	if (IS_ERR(cb->cb_client)) {
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index b1902eb..e4a83d7 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -50,7 +50,6 @@
 #include <linux/sunrpc/cache.h>
 #include <linux/nfsd_idmap.h>
 #include <linux/list.h>
-#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/seq_file.h>
 #include <linux/sunrpc/svcauth.h>
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9de89df..9e40679 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -714,7 +714,7 @@
 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		  struct nfsd4_setclientid *setclid)
 {
-	__be32 			ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	struct sockaddr_in	*sin = svc_addr_in(rqstp);
 	struct xdr_netobj 	clname = { 
 		.len = setclid->se_namelen,
 		.data = setclid->se_name,
@@ -749,7 +749,7 @@
 		 */
 		status = nfserr_clid_inuse;
 		if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
-				|| conf->cl_addr != ip_addr) {
+				|| conf->cl_addr != sin->sin_addr.s_addr) {
 			printk("NFSD: setclientid: string in use by client"
 			"(clientid %08x/%08x)\n",
 			conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
@@ -769,7 +769,7 @@
 		if (new == NULL)
 			goto out;
 		copy_verf(new, &clverifier);
-		new->cl_addr = ip_addr;
+		new->cl_addr = sin->sin_addr.s_addr;
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		gen_clid(new);
 		gen_confirm(new);
@@ -801,7 +801,7 @@
 		if (new == NULL)
 			goto out;
 		copy_verf(new,&conf->cl_verifier);
-		new->cl_addr = ip_addr;
+		new->cl_addr = sin->sin_addr.s_addr;
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		copy_clid(new, conf);
 		gen_confirm(new);
@@ -820,7 +820,7 @@
 		if (new == NULL)
 			goto out;
 		copy_verf(new,&clverifier);
-		new->cl_addr = ip_addr;
+		new->cl_addr = sin->sin_addr.s_addr;
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		gen_clid(new);
 		gen_confirm(new);
@@ -847,7 +847,7 @@
 		if (new == NULL)
 			goto out;
 		copy_verf(new,&clverifier);
-		new->cl_addr = ip_addr;
+		new->cl_addr = sin->sin_addr.s_addr;
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		gen_clid(new);
 		gen_confirm(new);
@@ -881,7 +881,7 @@
 			 struct nfsd4_compound_state *cstate,
 			 struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
-	__be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	struct sockaddr_in *sin = svc_addr_in(rqstp);
 	struct nfs4_client *conf, *unconf;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
@@ -900,9 +900,9 @@
 	unconf = find_unconfirmed_client(clid);
 
 	status = nfserr_clid_inuse;
-	if (conf && conf->cl_addr != ip_addr)
+	if (conf && conf->cl_addr != sin->sin_addr.s_addr)
 		goto out;
-	if (unconf && unconf->cl_addr != ip_addr)
+	if (unconf && unconf->cl_addr != sin->sin_addr.s_addr)
 		goto out;
 
 	if ((conf && unconf) && 
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 18aa944..5d090f1 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -199,24 +199,22 @@
 
 static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
 {
-	void *new = NULL;
 	if (p == argp->tmp) {
-		new = kmalloc(nbytes, GFP_KERNEL);
-		if (!new) return NULL;
-		p = new;
+		p = kmalloc(nbytes, GFP_KERNEL);
+		if (!p)
+			return NULL;
 		memcpy(p, argp->tmp, nbytes);
 	} else {
 		BUG_ON(p != argp->tmpp);
 		argp->tmpp = NULL;
 	}
 	if (defer_free(argp, kfree, p)) {
-		kfree(new);
+		kfree(p);
 		return NULL;
 	} else
 		return (char *)p;
 }
 
-
 static __be32
 nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
 {
@@ -255,7 +253,7 @@
 		return status;
 
 	/*
-	 * According to spec, unsupported attributes return ERR_NOTSUPP;
+	 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP;
 	 * read-only attributes return ERR_INVAL.
 	 */
 	if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
@@ -273,42 +271,42 @@
 		iattr->ia_valid |= ATTR_SIZE;
 	}
 	if (bmval[0] & FATTR4_WORD0_ACL) {
-		int nace, i;
-		struct nfs4_ace ace;
+		int nace;
+		struct nfs4_ace *ace;
 
 		READ_BUF(4); len += 4;
 		READ32(nace);
 
-		*acl = nfs4_acl_new();
+		if (nace > NFS4_ACL_MAX)
+			return nfserr_resource;
+
+		*acl = nfs4_acl_new(nace);
 		if (*acl == NULL) {
 			host_err = -ENOMEM;
 			goto out_nfserr;
 		}
-		defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl);
+		defer_free(argp, kfree, *acl);
 
-		for (i = 0; i < nace; i++) {
+		(*acl)->naces = nace;
+		for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
 			READ_BUF(16); len += 16;
-			READ32(ace.type);
-			READ32(ace.flag);
-			READ32(ace.access_mask);
+			READ32(ace->type);
+			READ32(ace->flag);
+			READ32(ace->access_mask);
 			READ32(dummy32);
 			READ_BUF(dummy32);
 			len += XDR_QUADLEN(dummy32) << 2;
 			READMEM(buf, dummy32);
-			ace.whotype = nfs4_acl_get_whotype(buf, dummy32);
+			ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
 			host_err = 0;
-			if (ace.whotype != NFS4_ACL_WHO_NAMED)
-				ace.who = 0;
-			else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP)
+			if (ace->whotype != NFS4_ACL_WHO_NAMED)
+				ace->who = 0;
+			else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
 				host_err = nfsd_map_name_to_gid(argp->rqstp,
-						buf, dummy32, &ace.who);
+						buf, dummy32, &ace->who);
 			else
 				host_err = nfsd_map_name_to_uid(argp->rqstp,
-						buf, dummy32, &ace.who);
-			if (host_err)
-				goto out_nfserr;
-			host_err = nfs4_acl_add_ace(*acl, ace.type, ace.flag,
-				 ace.access_mask, ace.whotype, ace.who);
+						buf, dummy32, &ace->who);
 			if (host_err)
 				goto out_nfserr;
 		}
@@ -1563,14 +1561,20 @@
 		if (exp->ex_fslocs.migrated) {
 			WRITE64(NFS4_REFERRAL_FSID_MAJOR);
 			WRITE64(NFS4_REFERRAL_FSID_MINOR);
-		} else if (is_fsid(fhp, rqstp->rq_reffh)) {
+		} else switch(fsid_source(fhp)) {
+		case FSIDSOURCE_FSID:
 			WRITE64((u64)exp->ex_fsid);
 			WRITE64((u64)0);
-		} else {
+			break;
+		case FSIDSOURCE_DEV:
 			WRITE32(0);
 			WRITE32(MAJOR(stat.dev));
 			WRITE32(0);
 			WRITE32(MINOR(stat.dev));
+			break;
+		case FSIDSOURCE_UUID:
+			WRITEMEM(exp->ex_uuid, 16);
+			break;
 		}
 	}
 	if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
@@ -1590,7 +1594,6 @@
 	}
 	if (bmval0 & FATTR4_WORD0_ACL) {
 		struct nfs4_ace *ace;
-		struct list_head *h;
 
 		if (acl == NULL) {
 			if ((buflen -= 4) < 0)
@@ -1603,9 +1606,7 @@
 			goto out_resource;
 		WRITE32(acl->naces);
 
-		list_for_each(h, &acl->ace_head) {
-			ace = list_entry(h, struct nfs4_ace, l_ace);
-
+		for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
 			if ((buflen -= 4*3) < 0)
 				goto out_resource;
 			WRITE32(ace->type);
@@ -1815,7 +1816,7 @@
 	status = nfs_ok;
 
 out:
-	nfs4_acl_free(acl);
+	kfree(acl);
 	if (fhp == &tempfh)
 		fh_put(&tempfh);
 	return status;
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index f90d704..578f2c9 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -185,7 +185,7 @@
 	rp->c_state = RC_INPROG;
 	rp->c_xid = xid;
 	rp->c_proc = proc;
-	rp->c_addr = rqstp->rq_addr;
+	memcpy(&rp->c_addr, svc_addr_in(rqstp), sizeof(rp->c_addr));
 	rp->c_prot = proto;
 	rp->c_vers = vers;
 	rp->c_timestamp = jiffies;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index eedf2e3..71c686d 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -123,7 +123,7 @@
 		return PTR_ERR(data);
 
 	rv =  write_op[ino](file, data, size);
-	if (rv>0) {
+	if (rv >= 0) {
 		simple_transaction_set(file, rv);
 		rv = size;
 	}
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index c59d6fb..c2660cb 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -9,7 +9,6 @@
  * ... and again Southern-Winter 2001 to support export_operations
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
@@ -20,6 +19,7 @@
 #include <linux/mount.h>
 #include <asm/pgtable.h>
 
+#include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 
@@ -118,9 +118,6 @@
 
 	dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
 
-	/* keep this filehandle for possible reference  when encoding attributes */
-	rqstp->rq_reffh = fh;
-
 	if (!fhp->fh_dentry) {
 		__u32 *datap=NULL;
 		__u32 tfh[3];		/* filehandle fragment for oldstyle filehandles */
@@ -145,10 +142,10 @@
 			}
 			len = key_len(fh->fh_fsid_type) / 4;
 			if (len == 0) goto out;
-			if  (fh->fh_fsid_type == 2) {
+			if  (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
 				/* deprecated, convert to type 3 */
-				len = 3;
-				fh->fh_fsid_type = 3;
+				len = key_len(FSID_ENCODE_DEV)/4;
+				fh->fh_fsid_type = FSID_ENCODE_DEV;
 				fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
 				fh->fh_fsid[1] = fh->fh_fsid[2];
 			}
@@ -163,8 +160,9 @@
 			/* assume old filehandle format */
 			xdev = old_decode_dev(fh->ofh_xdev);
 			xino = u32_to_ino_t(fh->ofh_xino);
-			mk_fsid_v0(tfh, xdev, xino);
-			exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle);
+			mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
+			exp = exp_find(rqstp->rq_client, FSID_DEV, tfh,
+				       &rqstp->rq_chandle);
 		}
 
 		if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
@@ -180,10 +178,10 @@
 		/* Check if the request originated from a secure port. */
 		error = nfserr_perm;
 		if (!rqstp->rq_secure && EX_SECURE(exp)) {
+			char buf[RPC_MAX_ADDRBUFLEN];
 			printk(KERN_WARNING
-			       "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n",
-			       NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
-			       ntohs(rqstp->rq_addr.sin_port));
+			       "nfsd: request from insecure port %s!\n",
+			       svc_print_addr(rqstp, buf, sizeof(buf)));
 			goto out;
 		}
 
@@ -211,7 +209,7 @@
 				fileid_type = 2;
 		} else
 			fileid_type = fh->fh_fileid_type;
-		
+
 		if (fileid_type == 0)
 			dentry = dget(exp->ex_dentry);
 		else {
@@ -291,7 +289,7 @@
 			     __u32 *datap, int *maxsize)
 {
 	struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
-	
+
 	if (dentry == exp->ex_dentry) {
 		*maxsize = 0;
 		return 0;
@@ -316,7 +314,8 @@
 }
 
 __be32
-fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh)
+fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
+	   struct svc_fh *ref_fh)
 {
 	/* ref_fh is a reference file handle.
 	 * if it is non-null and for the same filesystem, then we should compose
@@ -326,12 +325,13 @@
 	 *
 	 */
 
-	u8 ref_fh_version = 0;
-	u8 ref_fh_fsid_type = 0;
+	u8 version = 1;
+	u8 fsid_type = 0;
 	struct inode * inode = dentry->d_inode;
 	struct dentry *parent = dentry->d_parent;
 	__u32 *datap;
 	dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev;
+	int root_export = (exp->ex_dentry == exp->ex_dentry->d_sb->s_root);
 
 	dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
 		MAJOR(ex_dev), MINOR(ex_dev),
@@ -339,57 +339,64 @@
 		parent->d_name.name, dentry->d_name.name,
 		(inode ? inode->i_ino : 0));
 
+	/* Choose filehandle version and fsid type based on
+	 * the reference filehandle (if it is in the same export)
+	 * or the export options.
+	 */
 	if (ref_fh && ref_fh->fh_export == exp) {
-		ref_fh_version = ref_fh->fh_handle.fh_version;
-		if (ref_fh_version == 0xca)
-			ref_fh_fsid_type = 0;
+		version = ref_fh->fh_handle.fh_version;
+		if (version == 0xca)
+			fsid_type = FSID_DEV;
 		else
-			ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type;
-		if (ref_fh_fsid_type > 3)
-			ref_fh_fsid_type = 0;
-
-		/* make sure ref_fh type works for given export */
-		if (ref_fh_fsid_type == 1 &&
-		    !(exp->ex_flags & NFSEXP_FSID)) {
-			/* if we don't have an fsid, we cannot provide one... */
-			ref_fh_fsid_type = 0;
+			fsid_type = ref_fh->fh_handle.fh_fsid_type;
+		/* We know this version/type works for this export
+		 * so there is no need for further checks.
+		 */
+	} else if (exp->ex_uuid) {
+		if (fhp->fh_maxsize >= 64) {
+			if (root_export)
+				fsid_type = FSID_UUID16;
+			else
+				fsid_type = FSID_UUID16_INUM;
+		} else {
+			if (root_export)
+				fsid_type = FSID_UUID8;
+			else
+				fsid_type = FSID_UUID4_INUM;
 		}
 	} else if (exp->ex_flags & NFSEXP_FSID)
-		ref_fh_fsid_type = 1;
-
-	if (!old_valid_dev(ex_dev) && ref_fh_fsid_type == 0) {
+		fsid_type = FSID_NUM;
+	else if (!old_valid_dev(ex_dev))
 		/* for newer device numbers, we must use a newer fsid format */
-		ref_fh_version = 1;
-		ref_fh_fsid_type = 3;
-	}
-	if (old_valid_dev(ex_dev) &&
-	    (ref_fh_fsid_type == 2 || ref_fh_fsid_type == 3))
-		/* must use type1 for smaller device numbers */
-		ref_fh_fsid_type = 0;
+		fsid_type = FSID_ENCODE_DEV;
+	else
+		fsid_type = FSID_DEV;
 
 	if (ref_fh == fhp)
 		fh_put(ref_fh);
 
 	if (fhp->fh_locked || fhp->fh_dentry) {
 		printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
-			parent->d_name.name, dentry->d_name.name);
+		       parent->d_name.name, dentry->d_name.name);
 	}
 	if (fhp->fh_maxsize < NFS_FHSIZE)
 		printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
-		       fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name);
+		       fhp->fh_maxsize,
+		       parent->d_name.name, dentry->d_name.name);
 
 	fhp->fh_dentry = dget(dentry); /* our internal copy */
 	fhp->fh_export = exp;
 	cache_get(&exp->h);
 
-	if (ref_fh_version == 0xca) {
+	if (version == 0xca) {
 		/* old style filehandle please */
 		memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
 		fhp->fh_handle.fh_size = NFS_FHSIZE;
 		fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
 		fhp->fh_handle.ofh_dev =  old_encode_dev(ex_dev);
 		fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
-		fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino);
+		fhp->fh_handle.ofh_xino =
+			ino_t_to_u32(exp->ex_dentry->d_inode->i_ino);
 		fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry));
 		if (inode)
 			_fh_update_old(dentry, exp, &fhp->fh_handle);
@@ -398,38 +405,12 @@
 		fhp->fh_handle.fh_version = 1;
 		fhp->fh_handle.fh_auth_type = 0;
 		datap = fhp->fh_handle.fh_auth+0;
-		fhp->fh_handle.fh_fsid_type = ref_fh_fsid_type;
-		switch (ref_fh_fsid_type) {
-			case 0:
-				/*
-				 * fsid_type 0:
-				 * 2byte major, 2byte minor, 4byte inode
-				 */
-				mk_fsid_v0(datap, ex_dev,
-					exp->ex_dentry->d_inode->i_ino);
-				break;
-			case 1:
-				/* fsid_type 1 == 4 bytes filesystem id */
-				mk_fsid_v1(datap, exp->ex_fsid);
-				break;
-			case 2:
-				/*
-				 * fsid_type 2:
-				 * 4byte major, 4byte minor, 4byte inode
-				 */
-				mk_fsid_v2(datap, ex_dev,
-					exp->ex_dentry->d_inode->i_ino);
-				break;
-			case 3:
-				/*
-				 * fsid_type 3:
-				 * 4byte devicenumber, 4byte inode
-				 */
-				mk_fsid_v3(datap, ex_dev,
-					exp->ex_dentry->d_inode->i_ino);
-				break;
-		}
-		len = key_len(ref_fh_fsid_type);
+		fhp->fh_handle.fh_fsid_type = fsid_type;
+		mk_fsid(fsid_type, datap, ex_dev,
+			exp->ex_dentry->d_inode->i_ino,
+			exp->ex_fsid, exp->ex_uuid);
+
+		len = key_len(fsid_type);
 		datap += len/4;
 		fhp->fh_handle.fh_size = 4 + len;
 
@@ -456,7 +437,7 @@
 {
 	struct dentry *dentry;
 	__u32 *datap;
-	
+
 	if (!fhp->fh_dentry)
 		goto out_bad;
 
@@ -533,3 +514,22 @@
 		fh->fh_base.fh_pad[5]);
 	return buf;
 }
+
+enum fsid_source fsid_source(struct svc_fh *fhp)
+{
+	if (fhp->fh_handle.fh_version != 1)
+		return FSIDSOURCE_DEV;
+	switch(fhp->fh_handle.fh_fsid_type) {
+	case FSID_DEV:
+	case FSID_ENCODE_DEV:
+	case FSID_MAJOR_MINOR:
+		return FSIDSOURCE_DEV;
+	case FSID_NUM:
+		return FSIDSOURCE_FSID;
+	default:
+		if (fhp->fh_export->ex_flags & NFSEXP_FSID)
+			return FSIDSOURCE_FSID;
+		else
+			return FSIDSOURCE_UUID;
+	}
+}
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index ec983b7..5cc2eec 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -19,6 +19,7 @@
 #include <linux/unistd.h>
 #include <linux/slab.h>
 
+#include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/cache.h>
@@ -147,10 +148,10 @@
 	 */
 
 	if (NFSSVC_MAXBLKSIZE_V2 < argp->count) {
+		char buf[RPC_MAX_ADDRBUFLEN];
 		printk(KERN_NOTICE
-			"oversized read request from %u.%u.%u.%u:%d (%d bytes)\n",
-				NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
-				ntohs(rqstp->rq_addr.sin_port),
+			"oversized read request from %s (%d bytes)\n",
+				svc_print_addr(rqstp, buf, sizeof(buf)),
 				argp->count);
 		argp->count = NFSSVC_MAXBLKSIZE_V2;
 	}
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index fbf5d51..d7759ce 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -235,7 +235,8 @@
 
 	error = lockd_up(IPPROTO_UDP);
 	if (error >= 0) {
-		error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
+		error = svc_makesock(nfsd_serv, IPPROTO_UDP, port,
+					SVC_SOCK_DEFAULTS);
 		if (error < 0)
 			lockd_down();
 	}
@@ -245,7 +246,8 @@
 #ifdef CONFIG_NFSD_TCP
 	error = lockd_up(IPPROTO_TCP);
 	if (error >= 0) {
-		error = svc_makesock(nfsd_serv, IPPROTO_TCP, port);
+		error = svc_makesock(nfsd_serv, IPPROTO_TCP, port,
+					SVC_SOCK_DEFAULTS);
 		if (error < 0)
 			lockd_down();
 	}
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 6555c50..0c24b9e 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -153,6 +153,7 @@
 	struct dentry	*dentry = fhp->fh_dentry;
 	int type;
 	struct timespec time;
+	u32 f;
 
 	type = (stat->mode & S_IFMT);
 
@@ -173,10 +174,22 @@
 	else
 		*p++ = htonl(0xffffffff);
 	*p++ = htonl((u32) stat->blocks);
-	if (is_fsid(fhp, rqstp->rq_reffh))
-		*p++ = htonl((u32) fhp->fh_export->ex_fsid);
-	else
+	switch (fsid_source(fhp)) {
+	default:
+	case FSIDSOURCE_DEV:
 		*p++ = htonl(new_encode_dev(stat->dev));
+		break;
+	case FSIDSOURCE_FSID:
+		*p++ = htonl((u32) fhp->fh_export->ex_fsid);
+		break;
+	case FSIDSOURCE_UUID:
+		f = ((u32*)fhp->fh_export->ex_uuid)[0];
+		f ^= ((u32*)fhp->fh_export->ex_uuid)[1];
+		f ^= ((u32*)fhp->fh_export->ex_uuid)[2];
+		f ^= ((u32*)fhp->fh_export->ex_uuid)[3];
+		*p++ = htonl(f);
+		break;
+	}
 	*p++ = htonl((u32) stat->ino);
 	*p++ = htonl((u32) stat->atime.tv_sec);
 	*p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 8283236..7e6aa24 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -466,7 +466,10 @@
 	posix_acl_release(dpacl);
 	return (error);
 out_nfserr:
-	error = nfserrno(host_error);
+	if (host_error == -EOPNOTSUPP)
+		error = nfserr_attrnotsupp;
+	else
+		error = nfserrno(host_error);
 	goto out;
 }
 
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index c577d8e..7659cc1 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -1921,7 +1921,7 @@
 	u32 attr_len = 0; /* Silence stupid gcc warning. */
 	bool mp_rebuilt;
 
-#ifdef NTFS_DEBUG
+#ifdef DEBUG
 	read_lock_irqsave(&ni->size_lock, flags);
 	allocated_size = ni->allocated_size;
 	read_unlock_irqrestore(&ni->size_lock, flags);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 076c942..d69c459 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2328,7 +2328,7 @@
 						    the data source. */
 };
 
-struct inode_operations ntfs_file_inode_ops = {
+const struct inode_operations ntfs_file_inode_ops = {
 #ifdef NTFS_RW
 	.truncate	= ntfs_truncate_vfs,
 	.setattr	= ntfs_setattr,
@@ -2337,4 +2337,4 @@
 
 const struct file_operations ntfs_empty_file_ops = {};
 
-struct inode_operations ntfs_empty_inode_ops = {};
+const struct inode_operations ntfs_empty_inode_ops = {};
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index eddb224..bff01a5 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -359,7 +359,7 @@
 /**
  * Inode operations for directories.
  */
-struct inode_operations ntfs_dir_inode_ops = {
+const struct inode_operations ntfs_dir_inode_ops = {
 	.lookup	= ntfs_lookup,	/* VFS: Lookup directory. */
 };
 
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
index a12847a..d73f5a9 100644
--- a/fs/ntfs/ntfs.h
+++ b/fs/ntfs/ntfs.h
@@ -61,13 +61,13 @@
 extern const struct address_space_operations ntfs_mst_aops;
 
 extern const struct  file_operations ntfs_file_ops;
-extern struct inode_operations ntfs_file_inode_ops;
+extern const struct inode_operations ntfs_file_inode_ops;
 
 extern const struct  file_operations ntfs_dir_ops;
-extern struct inode_operations ntfs_dir_inode_ops;
+extern const struct inode_operations ntfs_dir_inode_ops;
 
 extern const struct  file_operations ntfs_empty_file_ops;
-extern struct inode_operations ntfs_empty_inode_ops;
+extern const struct inode_operations ntfs_empty_inode_ops;
 
 extern struct export_operations ntfs_export_ops;
 
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index babf94d..1594c90 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2699,7 +2699,7 @@
 /**
  * The complete super operations.
  */
-static struct super_operations ntfs_sops = {
+static const struct super_operations ntfs_sops = {
 	.alloc_inode	= ntfs_alloc_big_inode,	  /* VFS: Allocate new inode. */
 	.destroy_inode	= ntfs_destroy_big_inode, /* VFS: Deallocate inode. */
 #ifdef NTFS_RW
diff --git a/fs/ntfs/sysctl.c b/fs/ntfs/sysctl.c
index 1c23138..4847fbf 100644
--- a/fs/ntfs/sysctl.c
+++ b/fs/ntfs/sysctl.c
@@ -33,20 +33,28 @@
 #include "sysctl.h"
 #include "debug.h"
 
-#define FS_NTFS	1
-
 /* Definition of the ntfs sysctl. */
 static ctl_table ntfs_sysctls[] = {
-	{ FS_NTFS, "ntfs-debug",		/* Binary and text IDs. */
-	  &debug_msgs,sizeof(debug_msgs),	/* Data pointer and size. */
-	  0644,	NULL, &proc_dointvec },		/* Mode, child, proc handler. */
-	{ 0 }
+	{
+		.ctl_name	= CTL_UNNUMBERED,	/* Binary and text IDs. */
+		.procname	= "ntfs-debug",
+		.data		= &debug_msgs,		/* Data pointer and size. */
+		.maxlen		= sizeof(debug_msgs),
+		.mode		= 0644,			/* Mode, proc handler. */
+		.proc_handler	= &proc_dointvec
+	},
+	{}
 };
 
 /* Define the parent directory /proc/sys/fs. */
 static ctl_table sysctls_root[] = {
-	{ CTL_FS, "fs", NULL, 0, 0555, ntfs_sysctls },
-	{ 0 }
+	{
+		.ctl_name	= CTL_FS,
+		.procname	= "fs",
+		.mode		= 0555,
+		.child		= ntfs_sysctls
+	},
+	{}
 };
 
 /* Storage for the sysctls header. */
@@ -62,17 +70,9 @@
 {
 	if (add) {
 		BUG_ON(sysctls_root_table);
-		sysctls_root_table = register_sysctl_table(sysctls_root, 0);
+		sysctls_root_table = register_sysctl_table(sysctls_root);
 		if (!sysctls_root_table)
 			return -ENOMEM;
-#ifdef CONFIG_PROC_FS
-		/*
-		 * If the proc filesystem is in use and we are a module, need
-		 * to set the owner of our proc entry to our module. In the
-		 * non-modular case, THIS_MODULE is NULL, so this is ok.
-		 */
-		ntfs_sysctls[0].de->owner = THIS_MODULE;
-#endif
 	} else {
 		BUG_ON(!sysctls_root_table);
 		unregister_sysctl_table(sysctls_root_table);
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index b17333a..9f5ad0f 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -55,7 +55,7 @@
 
 static ctl_table ocfs2_mod_table[] = {
 	{
-		.ctl_name	= KERN_OCFS2_NM,
+		.ctl_name	= FS_OCFS2_NM,
 		.procname	= "nm",
 		.data		= NULL,
 		.maxlen		= 0,
@@ -67,7 +67,7 @@
 
 static ctl_table ocfs2_kern_table[] = {
 	{
-		.ctl_name	= KERN_OCFS2,
+		.ctl_name	= FS_OCFS2,
 		.procname	= "ocfs2",
 		.data		= NULL,
 		.maxlen		= 0,
@@ -922,7 +922,7 @@
 	o2hb_init();
 	o2net_init();
 
-	ocfs2_table_header = register_sysctl_table(ocfs2_root_table, 0);
+	ocfs2_table_header = register_sysctl_table(ocfs2_root_table);
 	if (!ocfs2_table_header) {
 		printk(KERN_ERR "nodemanager: unable to register sysctl\n");
 		ret = -ENOMEM; /* or something. */
diff --git a/fs/ocfs2/cluster/nodemanager.h b/fs/ocfs2/cluster/nodemanager.h
index 8fb23ca..0705221 100644
--- a/fs/ocfs2/cluster/nodemanager.h
+++ b/fs/ocfs2/cluster/nodemanager.h
@@ -33,8 +33,7 @@
 #include <linux/configfs.h>
 #include <linux/rbtree.h>
 
-#define KERN_OCFS2		988
-#define KERN_OCFS2_NM		1
+#define FS_OCFS2_NM		1
 
 const char *o2nm_get_hb_ctl_path(void);
 
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index b7f0ba9..de952eb 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -61,11 +61,11 @@
 #define MLOG_MASK_PREFIX ML_DLMFS
 #include "cluster/masklog.h"
 
-static struct super_operations dlmfs_ops;
-static struct file_operations dlmfs_file_operations;
-static struct inode_operations dlmfs_dir_inode_operations;
-static struct inode_operations dlmfs_root_inode_operations;
-static struct inode_operations dlmfs_file_inode_operations;
+static const struct super_operations dlmfs_ops;
+static const struct file_operations dlmfs_file_operations;
+static const struct inode_operations dlmfs_dir_inode_operations;
+static const struct inode_operations dlmfs_root_inode_operations;
+static const struct inode_operations dlmfs_file_inode_operations;
 static struct kmem_cache *dlmfs_inode_cache;
 
 struct workqueue_struct *user_dlm_worker;
@@ -540,27 +540,27 @@
 	return 0;
 }
 
-static struct file_operations dlmfs_file_operations = {
+static const struct file_operations dlmfs_file_operations = {
 	.open		= dlmfs_file_open,
 	.release	= dlmfs_file_release,
 	.read		= dlmfs_file_read,
 	.write		= dlmfs_file_write,
 };
 
-static struct inode_operations dlmfs_dir_inode_operations = {
+static const struct inode_operations dlmfs_dir_inode_operations = {
 	.create		= dlmfs_create,
 	.lookup		= simple_lookup,
 	.unlink		= dlmfs_unlink,
 };
 
 /* this way we can restrict mkdir to only the toplevel of the fs. */
-static struct inode_operations dlmfs_root_inode_operations = {
+static const struct inode_operations dlmfs_root_inode_operations = {
 	.lookup		= simple_lookup,
 	.mkdir		= dlmfs_mkdir,
 	.rmdir		= simple_rmdir,
 };
 
-static struct super_operations dlmfs_ops = {
+static const struct super_operations dlmfs_ops = {
 	.statfs		= simple_statfs,
 	.alloc_inode	= dlmfs_alloc_inode,
 	.destroy_inode	= dlmfs_destroy_inode,
@@ -568,7 +568,7 @@
 	.drop_inode	= generic_delete_inode,
 };
 
-static struct inode_operations dlmfs_file_inode_operations = {
+static const struct inode_operations dlmfs_file_inode_operations = {
 	.getattr	= simple_getattr,
 };
 
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 10953a5..f2cd3bf 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1365,13 +1365,13 @@
 	return ret;
 }
 
-struct inode_operations ocfs2_file_iops = {
+const struct inode_operations ocfs2_file_iops = {
 	.setattr	= ocfs2_setattr,
 	.getattr	= ocfs2_getattr,
 	.permission	= ocfs2_permission,
 };
 
-struct inode_operations ocfs2_special_file_iops = {
+const struct inode_operations ocfs2_special_file_iops = {
 	.setattr	= ocfs2_setattr,
 	.getattr	= ocfs2_getattr,
 	.permission	= ocfs2_permission,
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index 601a453..cc973f0 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -28,8 +28,8 @@
 
 extern const struct file_operations ocfs2_fops;
 extern const struct file_operations ocfs2_dops;
-extern struct inode_operations ocfs2_file_iops;
-extern struct inode_operations ocfs2_special_file_iops;
+extern const struct inode_operations ocfs2_file_iops;
+extern const struct inode_operations ocfs2_special_file_iops;
 struct ocfs2_alloc_context;
 
 enum ocfs2_alloc_restarted {
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index f3d7803..28dd757 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1098,7 +1098,7 @@
 			BUG();
 	}
 
-	/* Assume a directory heirarchy thusly:
+	/* Assume a directory hierarchy thusly:
 	 * a/b/c
 	 * a/d
 	 * a,b,c, and d are all directories.
@@ -2306,7 +2306,7 @@
 	return status;
 }
 
-struct inode_operations ocfs2_dir_iops = {
+const struct inode_operations ocfs2_dir_iops = {
 	.create		= ocfs2_create,
 	.lookup		= ocfs2_lookup,
 	.link		= ocfs2_link,
diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h
index 8425944..0975c7b 100644
--- a/fs/ocfs2/namei.h
+++ b/fs/ocfs2/namei.h
@@ -26,7 +26,7 @@
 #ifndef OCFS2_NAMEI_H
 #define OCFS2_NAMEI_H
 
-extern struct inode_operations ocfs2_dir_iops;
+extern const struct inode_operations ocfs2_dir_iops;
 
 struct dentry *ocfs2_get_parent(struct dentry *child);
 
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 6e300a8..6534f92 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -116,7 +116,7 @@
 
 static unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
 
-static struct super_operations ocfs2_sops = {
+static const struct super_operations ocfs2_sops = {
 	.statfs		= ocfs2_statfs,
 	.alloc_inode	= ocfs2_alloc_inode,
 	.destroy_inode	= ocfs2_destroy_inode,
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index 03b0191..40dc1a5 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -170,12 +170,12 @@
 	return ERR_PTR(status);
 }
 
-struct inode_operations ocfs2_symlink_inode_operations = {
+const struct inode_operations ocfs2_symlink_inode_operations = {
 	.readlink	= page_readlink,
 	.follow_link	= ocfs2_follow_link,
 	.getattr	= ocfs2_getattr,
 };
-struct inode_operations ocfs2_fast_symlink_inode_operations = {
+const struct inode_operations ocfs2_fast_symlink_inode_operations = {
 	.readlink	= ocfs2_readlink,
 	.follow_link	= ocfs2_follow_link,
 	.getattr	= ocfs2_getattr,
diff --git a/fs/ocfs2/symlink.h b/fs/ocfs2/symlink.h
index 1ea9e4d..65a6c9c 100644
--- a/fs/ocfs2/symlink.h
+++ b/fs/ocfs2/symlink.h
@@ -26,8 +26,8 @@
 #ifndef OCFS2_SYMLINK_H
 #define OCFS2_SYMLINK_H
 
-extern struct inode_operations ocfs2_symlink_inode_operations;
-extern struct inode_operations ocfs2_fast_symlink_inode_operations;
+extern const struct inode_operations ocfs2_symlink_inode_operations;
+extern const struct inode_operations ocfs2_fast_symlink_inode_operations;
 
 /*
  * Test whether an inode is a fast symlink.
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index 99c0bc3..bde1c16 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -169,7 +169,7 @@
 
 static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *);
 
-static struct inode_operations openprom_inode_operations = {
+static const struct inode_operations openprom_inode_operations = {
 	.lookup		= openpromfs_lookup,
 };
 
@@ -364,7 +364,7 @@
 	return 0;
 }
 
-static struct super_operations openprom_sops = { 
+static const struct super_operations openprom_sops = {
 	.alloc_inode	= openprom_alloc_inode,
 	.destroy_inode	= openprom_destroy_inode,
 	.read_inode	= openprom_read_inode,
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 3d73d94..22d38ff 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -358,14 +358,13 @@
 	p->ios[0] = p->ios[1] = 0;
 	p->sectors[0] = p->sectors[1] = 0;
 	sysfs_remove_link(&p->kobj, "subsystem");
-	if (p->holder_dir)
-		kobject_unregister(p->holder_dir);
+	kobject_unregister(p->holder_dir);
 	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)
+void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags)
 {
 	struct hd_struct *p;
 
@@ -390,6 +389,15 @@
 	if (!disk->part_uevent_suppress)
 		kobject_uevent(&p->kobj, KOBJ_ADD);
 	sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem");
+	if (flags & ADDPART_FLAG_WHOLEDISK) {
+		static struct attribute addpartattr = {
+			.name = "whole_disk",
+			.mode = S_IRUSR | S_IRGRP | S_IROTH,
+			.owner = THIS_MODULE,
+		};
+
+		sysfs_create_file(&p->kobj, &addpartattr);
+	}
 	partition_sysfs_add_subdir(p);
 	disk->part[part-1] = p;
 }
@@ -543,9 +551,9 @@
 			printk(" %s: p%d exceeds device capacity\n",
 				disk->disk_name, p);
 		}
-		add_partition(disk, p, from, size);
+		add_partition(disk, p, from, size, state->parts[p].flags);
 #ifdef CONFIG_BLK_DEV_MD
-		if (state->parts[p].flags)
+		if (state->parts[p].flags & ADDPART_FLAG_RAID)
 			md_autodetect_dev(bdev->bd_dev+p);
 #endif
 	}
@@ -594,10 +602,8 @@
 	disk->stamp = 0;
 
 	kobject_uevent(&disk->kobj, KOBJ_REMOVE);
-	if (disk->holder_dir)
-		kobject_unregister(disk->holder_dir);
-	if (disk->slave_dir)
-		kobject_unregister(disk->slave_dir);
+	kobject_unregister(disk->holder_dir);
+	kobject_unregister(disk->slave_dir);
 	if (disk->driverfs_dev) {
 		char *disk_name = make_block_name(disk);
 		sysfs_remove_link(&disk->kobj, "device");
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 8c7af17..4ccec4c 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -63,15 +63,25 @@
 #define AIX_LABEL_MAGIC4	0xC1
 static int aix_magic_present(unsigned char *p, struct block_device *bdev)
 {
+	struct partition *pt = (struct partition *) (p + 0x1be);
 	Sector sect;
 	unsigned char *d;
-	int ret = 0;
+	int slot, ret = 0;
 
-	if (p[0] != AIX_LABEL_MAGIC1 &&
-		p[1] != AIX_LABEL_MAGIC2 &&
-		p[2] != AIX_LABEL_MAGIC3 &&
-		p[3] != AIX_LABEL_MAGIC4)
+	if (!(p[0] == AIX_LABEL_MAGIC1 &&
+		p[1] == AIX_LABEL_MAGIC2 &&
+		p[2] == AIX_LABEL_MAGIC3 &&
+		p[3] == AIX_LABEL_MAGIC4))
 		return 0;
+	/* Assume the partition table is valid if Linux partitions exists */
+	for (slot = 1; slot <= 4; slot++, pt++) {
+		if (pt->sys_ind == LINUX_SWAP_PARTITION ||
+			pt->sys_ind == LINUX_RAID_PARTITION ||
+			pt->sys_ind == LINUX_DATA_PARTITION ||
+			pt->sys_ind == LINUX_LVM_PARTITION ||
+			is_extended_partition(pt))
+			return 0;
+	}
 	d = read_dev_sector(bdev, 7, &sect);
 	if (d) {
 		if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M')
@@ -155,7 +165,7 @@
 
 			put_partition(state, state->next, next, size);
 			if (SYS_IND(p) == LINUX_RAID_PARTITION)
-				state->parts[state->next].flags = 1;
+				state->parts[state->next].flags = ADDPART_FLAG_RAID;
 			loopct = 0;
 			if (++state->next == state->limit)
 				goto done;
diff --git a/fs/partitions/sgi.c b/fs/partitions/sgi.c
index 6fa4ff8..ed5ac83 100644
--- a/fs/partitions/sgi.c
+++ b/fs/partitions/sgi.c
@@ -72,7 +72,7 @@
 		if (blocks) {
 			put_partition(state, slot, start, blocks);
 			if (be32_to_cpu(p->type) == LINUX_RAID_PARTITION)
-				state->parts[slot].flags = 1;
+				state->parts[slot].flags = ADDPART_FLAG_RAID;
 		}
 		slot++;
 	}
diff --git a/fs/partitions/sun.c b/fs/partitions/sun.c
index 0a5927c..123f8b4 100644
--- a/fs/partitions/sun.c
+++ b/fs/partitions/sun.c
@@ -80,8 +80,11 @@
 		num_sectors = be32_to_cpu(p->num_sectors);
 		if (num_sectors) {
 			put_partition(state, slot, st_sector, num_sectors);
+			state->parts[slot].flags = 0;
 			if (label->infos[i].id == LINUX_RAID_PARTITION)
-				state->parts[slot].flags = 1;
+				state->parts[slot].flags |= ADDPART_FLAG_RAID;
+			if (label->infos[i].id == SUN_WHOLE_DISK)
+				state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK;
 		}
 		slot++;
 	}
diff --git a/fs/pipe.c b/fs/pipe.c
index 68090e8..ebafde7 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -16,6 +16,7 @@
 #include <linux/uio.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/audit.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -985,6 +986,10 @@
 		goto err_fdr;
 	fdw = error;
 
+	error = audit_fd_pair(fdr, fdw);
+	if (error < 0)
+		goto err_fdw;
+
 	fd_install(fdr, fr);
 	fd_install(fdw, fw);
 	fd[0] = fdr;
@@ -992,6 +997,8 @@
 
 	return 0;
 
+ err_fdw:
+	put_unused_fd(fdw);
  err_fdr:
 	put_unused_fd(fdr);
  err_read_pipe:
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index f6c7762..a6b3a8f 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -8,7 +8,7 @@
 proc-$(CONFIG_MMU)	:= mmu.o task_mmu.o
 
 proc-y       += inode.o root.o base.o generic.o array.o \
-		proc_tty.o proc_misc.o
+		proc_tty.o proc_misc.o proc_sysctl.o
 
 proc-$(CONFIG_PROC_KCORE)	+= kcore.o
 proc-$(CONFIG_PROC_VMCORE)	+= vmcore.o
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 70e4fab1..07c9cdb 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -351,7 +351,7 @@
 		struct signal_struct *sig = task->signal;
 
 		if (sig->tty) {
-			tty_pgrp = sig->tty->pgrp;
+			tty_pgrp = pid_nr(sig->tty->pgrp);
 			tty_nr = new_encode_dev(tty_devnum(sig->tty));
 		}
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 1a979ea..01f7769 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -93,8 +93,8 @@
 	int len;
 	char *name;
 	mode_t mode;
-	struct inode_operations *iop;
-	struct file_operations *fop;
+	const struct inode_operations *iop;
+	const struct file_operations *fop;
 	union proc_op op;
 };
 
@@ -352,7 +352,7 @@
 	return error;
 }
 
-static struct inode_operations proc_def_inode_operations = {
+static const struct inode_operations proc_def_inode_operations = {
 	.setattr	= proc_setattr,
 };
 
@@ -424,7 +424,7 @@
 	return res;
 }
 
-static struct file_operations proc_mounts_operations = {
+static const struct file_operations proc_mounts_operations = {
 	.open		= mounts_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -462,7 +462,7 @@
 	return ret;
 }
 
-static struct file_operations proc_mountstats_operations = {
+static const struct file_operations proc_mountstats_operations = {
 	.open		= mountstats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -501,7 +501,7 @@
 	return length;
 }
 
-static struct file_operations proc_info_file_operations = {
+static const struct file_operations proc_info_file_operations = {
 	.read		= proc_info_read,
 };
 
@@ -581,7 +581,7 @@
 
 #ifndef mem_write
 /* This is a security hazard */
-static ssize_t mem_write(struct file * file, const char * buf,
+static ssize_t mem_write(struct file * file, const char __user *buf,
 			 size_t count, loff_t *ppos)
 {
 	int copied;
@@ -646,7 +646,7 @@
 	return file->f_pos;
 }
 
-static struct file_operations proc_mem_operations = {
+static const struct file_operations proc_mem_operations = {
 	.llseek		= mem_lseek,
 	.read		= mem_read,
 	.write		= mem_write,
@@ -710,7 +710,7 @@
 	return end - buffer;
 }
 
-static struct file_operations proc_oom_adjust_operations = {
+static const struct file_operations proc_oom_adjust_operations = {
 	.read		= oom_adjust_read,
 	.write		= oom_adjust_write,
 };
@@ -777,7 +777,7 @@
 	return length;
 }
 
-static struct file_operations proc_loginuid_operations = {
+static const struct file_operations proc_loginuid_operations = {
 	.read		= proc_loginuid_read,
 	.write		= proc_loginuid_write,
 };
@@ -849,7 +849,7 @@
 	return result;
 }
 
-static struct file_operations proc_seccomp_operations = {
+static const struct file_operations proc_seccomp_operations = {
 	.read		= seccomp_read,
 	.write		= seccomp_write,
 };
@@ -908,7 +908,7 @@
 	return end - buffer;
 }
 
-static struct file_operations proc_fault_inject_operations = {
+static const struct file_operations proc_fault_inject_operations = {
 	.read		= proc_fault_inject_read,
 	.write		= proc_fault_inject_write,
 };
@@ -980,7 +980,7 @@
 	return error;
 }
 
-static struct inode_operations proc_pid_link_inode_operations = {
+static const struct inode_operations proc_pid_link_inode_operations = {
 	.readlink	= proc_pid_readlink,
 	.follow_link	= proc_pid_follow_link,
 	.setattr	= proc_setattr,
@@ -1408,7 +1408,7 @@
 	return retval;
 }
 
-static struct file_operations proc_fd_operations = {
+static const struct file_operations proc_fd_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_readfd,
 };
@@ -1416,7 +1416,7 @@
 /*
  * proc directories can do almost nothing..
  */
-static struct inode_operations proc_fd_inode_operations = {
+static const struct inode_operations proc_fd_inode_operations = {
 	.lookup		= proc_lookupfd,
 	.setattr	= proc_setattr,
 };
@@ -1623,7 +1623,7 @@
 	return length;
 }
 
-static struct file_operations proc_pid_attr_operations = {
+static const struct file_operations proc_pid_attr_operations = {
 	.read		= proc_pid_attr_read,
 	.write		= proc_pid_attr_write,
 };
@@ -1644,7 +1644,7 @@
 				   attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff));
 }
 
-static struct file_operations proc_attr_dir_operations = {
+static const struct file_operations proc_attr_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_attr_dir_readdir,
 };
@@ -1656,7 +1656,7 @@
 				  attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
 }
 
-static struct inode_operations proc_attr_dir_inode_operations = {
+static const struct inode_operations proc_attr_dir_inode_operations = {
 	.lookup		= proc_attr_dir_lookup,
 	.getattr	= pid_getattr,
 	.setattr	= proc_setattr,
@@ -1682,7 +1682,7 @@
 	return ERR_PTR(vfs_follow_link(nd,tmp));
 }
 
-static struct inode_operations proc_self_inode_operations = {
+static const struct inode_operations proc_self_inode_operations = {
 	.readlink	= proc_self_readlink,
 	.follow_link	= proc_self_follow_link,
 };
@@ -1810,17 +1810,21 @@
 static int proc_pid_io_accounting(struct task_struct *task, char *buffer)
 {
 	return sprintf(buffer,
+#ifdef CONFIG_TASK_XACCT
 			"rchar: %llu\n"
 			"wchar: %llu\n"
 			"syscr: %llu\n"
 			"syscw: %llu\n"
+#endif
 			"read_bytes: %llu\n"
 			"write_bytes: %llu\n"
 			"cancelled_write_bytes: %llu\n",
+#ifdef CONFIG_TASK_XACCT
 			(unsigned long long)task->rchar,
 			(unsigned long long)task->wchar,
 			(unsigned long long)task->syscr,
 			(unsigned long long)task->syscw,
+#endif
 			(unsigned long long)task->ioac.read_bytes,
 			(unsigned long long)task->ioac.write_bytes,
 			(unsigned long long)task->ioac.cancelled_write_bytes);
@@ -1830,8 +1834,8 @@
 /*
  * Thread groups
  */
-static struct file_operations proc_task_operations;
-static struct inode_operations proc_task_inode_operations;
+static const struct file_operations proc_task_operations;
+static const struct inode_operations proc_task_inode_operations;
 
 static struct pid_entry tgid_base_stuff[] = {
 	DIR("task",       S_IRUGO|S_IXUGO, task),
@@ -1890,7 +1894,7 @@
 				   tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff));
 }
 
-static struct file_operations proc_tgid_base_operations = {
+static const struct file_operations proc_tgid_base_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_tgid_base_readdir,
 };
@@ -1900,7 +1904,7 @@
 				  tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
 }
 
-static struct inode_operations proc_tgid_base_inode_operations = {
+static const struct inode_operations proc_tgid_base_inode_operations = {
 	.lookup		= proc_tgid_base_lookup,
 	.getattr	= pid_getattr,
 	.setattr	= proc_setattr,
@@ -2173,12 +2177,12 @@
 				  tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
 }
 
-static struct file_operations proc_tid_base_operations = {
+static const struct file_operations proc_tid_base_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_tid_base_readdir,
 };
 
-static struct inode_operations proc_tid_base_inode_operations = {
+static const struct inode_operations proc_tid_base_inode_operations = {
 	.lookup		= proc_tid_base_lookup,
 	.getattr	= pid_getattr,
 	.setattr	= proc_setattr,
@@ -2404,13 +2408,13 @@
 	return 0;
 }
 
-static struct inode_operations proc_task_inode_operations = {
+static const struct inode_operations proc_task_inode_operations = {
 	.lookup		= proc_task_lookup,
 	.getattr	= proc_task_getattr,
 	.setattr	= proc_setattr,
 };
 
-static struct file_operations proc_task_operations = {
+static const struct file_operations proc_task_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_task_readdir,
 };
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 853cb87..775fb21 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -32,14 +32,14 @@
 
 DEFINE_SPINLOCK(proc_subdir_lock);
 
-int proc_match(int len, const char *name, struct proc_dir_entry *de)
+static int proc_match(int len, const char *name, struct proc_dir_entry *de)
 {
 	if (de->namelen != len)
 		return 0;
 	return !memcmp(name, de->name, len);
 }
 
-static struct file_operations proc_file_operations = {
+static const struct file_operations proc_file_operations = {
 	.llseek		= proc_file_lseek,
 	.read		= proc_file_read,
 	.write		= proc_file_write,
@@ -265,7 +265,7 @@
 	return 0;
 }
 
-static struct inode_operations proc_file_inode_operations = {
+static const struct inode_operations proc_file_inode_operations = {
 	.setattr	= proc_notify_change,
 };
 
@@ -357,7 +357,7 @@
 	return NULL;
 }
 
-static struct inode_operations proc_link_inode_operations = {
+static const struct inode_operations proc_link_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= proc_follow_link,
 };
@@ -497,7 +497,7 @@
  * use the in-memory "struct proc_dir_entry" tree to parse
  * the /proc directory.
  */
-static struct file_operations proc_dir_operations = {
+static const struct file_operations proc_dir_operations = {
 	.read			= generic_read_dir,
 	.readdir		= proc_readdir,
 };
@@ -505,7 +505,7 @@
 /*
  * proc directories can do almost nothing..
  */
-static struct inode_operations proc_dir_inode_operations = {
+static const struct inode_operations proc_dir_inode_operations = {
 	.lookup		= proc_lookup,
 	.getattr	= proc_getattr,
 	.setattr	= proc_notify_change,
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index e26945b..c372eb15 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -132,7 +132,7 @@
 	return 0;
 }
 
-static struct super_operations proc_sops = { 
+static const struct super_operations proc_sops = {
 	.alloc_inode	= proc_alloc_inode,
 	.destroy_inode	= proc_destroy_inode,
 	.read_inode	= proc_read_inode,
@@ -161,6 +161,7 @@
 	if (!inode)
 		goto out_ino;
 
+	PROC_I(inode)->fd = 0;
 	PROC_I(inode)->pde = de;
 	if (de) {
 		if (de->mode) {
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 987c773..c932aa6 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -11,6 +11,8 @@
 
 #include <linux/proc_fs.h>
 
+extern int proc_sys_init(void);
+
 struct vmalloc_info {
 	unsigned long	used;
 	unsigned long	largest_chunk;
@@ -38,13 +40,13 @@
 extern int proc_pid_status(struct task_struct *, char *);
 extern int proc_pid_statm(struct task_struct *, char *);
 
-extern struct file_operations proc_maps_operations;
-extern struct file_operations proc_numa_maps_operations;
-extern struct file_operations proc_smaps_operations;
+extern const struct file_operations proc_maps_operations;
+extern const struct file_operations proc_numa_maps_operations;
+extern const struct file_operations proc_smaps_operations;
 
-extern struct file_operations proc_maps_operations;
-extern struct file_operations proc_numa_maps_operations;
-extern struct file_operations proc_smaps_operations;
+extern const struct file_operations proc_maps_operations;
+extern const struct file_operations proc_numa_maps_operations;
+extern const struct file_operations proc_smaps_operations;
 
 
 void free_proc_entry(struct proc_dir_entry *de);
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
index 5ec6725..22f789d 100644
--- a/fs/proc/nommu.c
+++ b/fs/proc/nommu.c
@@ -128,7 +128,7 @@
 	return seq_open(file, &proc_nommu_vma_list_seqop);
 }
 
-static struct file_operations proc_nommu_vma_list_operations = {
+static const struct file_operations proc_nommu_vma_list_operations = {
 	.open    = proc_nommu_vma_list_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index b37ce33..e2c4c0a5 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -121,16 +121,11 @@
 {
 	struct sysinfo i;
 	int len;
-	unsigned long inactive;
-	unsigned long active;
-	unsigned long free;
 	unsigned long committed;
 	unsigned long allowed;
 	struct vmalloc_info vmi;
 	long cached;
 
-	get_zone_counts(&active, &inactive, &free);
-
 /*
  * display in kilobytes.
  */
@@ -187,8 +182,8 @@
 		K(i.bufferram),
 		K(cached),
 		K(total_swapcache_pages),
-		K(active),
-		K(inactive),
+		K(global_page_state(NR_ACTIVE)),
+		K(global_page_state(NR_INACTIVE)),
 #ifdef CONFIG_HIGHMEM
 		K(i.totalhigh),
 		K(i.freehigh),
@@ -228,7 +223,7 @@
 	return seq_open(file, &fragmentation_op);
 }
 
-static struct file_operations fragmentation_file_operations = {
+static const struct file_operations fragmentation_file_operations = {
 	.open		= fragmentation_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -241,7 +236,7 @@
 	return seq_open(file, &zoneinfo_op);
 }
 
-static struct file_operations proc_zoneinfo_file_operations = {
+static const struct file_operations proc_zoneinfo_file_operations = {
 	.open		= zoneinfo_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -266,7 +261,7 @@
 	return seq_open(file, &cpuinfo_op);
 }
 
-static struct file_operations proc_cpuinfo_operations = {
+static const struct file_operations proc_cpuinfo_operations = {
 	.open		= cpuinfo_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -325,7 +320,7 @@
 	return seq_open(filp, &devinfo_ops);
 }
 
-static struct file_operations proc_devinfo_operations = {
+static const struct file_operations proc_devinfo_operations = {
 	.open		= devinfo_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -337,7 +332,7 @@
 {
 	return seq_open(file, &vmstat_op);
 }
-static struct file_operations proc_vmstat_file_operations = {
+static const struct file_operations proc_vmstat_file_operations = {
 	.open		= vmstat_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -368,7 +363,7 @@
 {
 	return seq_open(file, &partitions_op);
 }
-static struct file_operations proc_partitions_operations = {
+static const struct file_operations proc_partitions_operations = {
 	.open		= partitions_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -380,7 +375,7 @@
 {
 	return seq_open(file, &diskstats_op);
 }
-static struct file_operations proc_diskstats_operations = {
+static const struct file_operations proc_diskstats_operations = {
 	.open		= diskstats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -394,7 +389,7 @@
 {
 	return seq_open(file, &modules_op);
 }
-static struct file_operations proc_modules_operations = {
+static const struct file_operations proc_modules_operations = {
 	.open		= modules_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -409,7 +404,7 @@
 {
 	return seq_open(file, &slabinfo_op);
 }
-static struct file_operations proc_slabinfo_operations = {
+static const struct file_operations proc_slabinfo_operations = {
 	.open		= slabinfo_open,
 	.read		= seq_read,
 	.write		= slabinfo_write,
@@ -443,7 +438,7 @@
 	return seq_release(inode, file);
 }
 
-static struct file_operations proc_slabstats_operations = {
+static const struct file_operations proc_slabstats_operations = {
 	.open		= slabstats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -556,7 +551,7 @@
 		kfree(buf);
 	return res;
 }
-static struct file_operations proc_stat_operations = {
+static const struct file_operations proc_stat_operations = {
 	.open		= stat_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -598,7 +593,7 @@
 	return seq_open(filp, &int_seq_ops);
 }
 
-static struct file_operations proc_interrupts_operations = {
+static const struct file_operations proc_interrupts_operations = {
 	.open		= interrupts_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -655,7 +650,7 @@
 	return count;
 }
 
-static struct file_operations proc_sysrq_trigger_operations = {
+static const struct file_operations proc_sysrq_trigger_operations = {
 	.write		= write_sysrq_trigger,
 };
 #endif
@@ -672,7 +667,6 @@
 
 void __init proc_misc_init(void)
 {
-	struct proc_dir_entry *entry;
 	static struct {
 		char *name;
 		int (*read_proc)(char*,char**,off_t,int,int*,void*);
@@ -700,9 +694,12 @@
 
 	/* And now for trickier ones */
 #ifdef CONFIG_PRINTK
-	entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
-	if (entry)
-		entry->proc_fops = &proc_kmsg_operations;
+	{
+		struct proc_dir_entry *entry;
+		entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
+		if (entry)
+			entry->proc_fops = &proc_kmsg_operations;
+	}
 #endif
 	create_seq_entry("devices", 0, &proc_devinfo_operations);
 	create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
@@ -743,8 +740,11 @@
 		proc_vmcore->proc_fops = &proc_vmcore_operations;
 #endif
 #ifdef CONFIG_MAGIC_SYSRQ
-	entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
-	if (entry)
-		entry->proc_fops = &proc_sysrq_trigger_operations;
+	{
+		struct proc_dir_entry *entry;
+		entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
+		if (entry)
+			entry->proc_fops = &proc_sysrq_trigger_operations;
+	}
 #endif
 }
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
new file mode 100644
index 0000000..20e8cbb
--- /dev/null
+++ b/fs/proc/proc_sysctl.c
@@ -0,0 +1,479 @@
+/*
+ * /proc/sys support
+ */
+
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/security.h>
+#include "internal.h"
+
+static struct dentry_operations proc_sys_dentry_operations;
+static const struct file_operations proc_sys_file_operations;
+static struct inode_operations proc_sys_inode_operations;
+
+static void proc_sys_refresh_inode(struct inode *inode, struct ctl_table *table)
+{
+	/* Refresh the cached information bits in the inode */
+	if (table) {
+		inode->i_uid = 0;
+		inode->i_gid = 0;
+		inode->i_mode = table->mode;
+		if (table->proc_handler) {
+			inode->i_mode |= S_IFREG;
+			inode->i_nlink = 1;
+		} else {
+			inode->i_mode |= S_IFDIR;
+			inode->i_nlink = 0;	/* It is too hard to figure out */
+		}
+	}
+}
+
+static struct inode *proc_sys_make_inode(struct inode *dir, struct ctl_table *table)
+{
+	struct inode *inode;
+	struct proc_inode *dir_ei, *ei;
+	int depth;
+
+	inode = new_inode(dir->i_sb);
+	if (!inode)
+		goto out;
+
+	/* A directory is always one deeper than it's parent */
+	dir_ei = PROC_I(dir);
+	depth = dir_ei->fd + 1;
+
+	ei = PROC_I(inode);
+	ei->fd = depth;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	inode->i_op = &proc_sys_inode_operations;
+	inode->i_fop = &proc_sys_file_operations;
+	inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */
+	proc_sys_refresh_inode(inode, table);
+out:
+	return inode;
+}
+
+static struct dentry *proc_sys_ancestor(struct dentry *dentry, int depth)
+{
+	for (;;) {
+		struct proc_inode *ei;
+
+		ei = PROC_I(dentry->d_inode);
+		if (ei->fd == depth)
+			break; /* found */
+
+		dentry = dentry->d_parent;
+	}
+	return dentry;
+}
+
+static struct ctl_table *proc_sys_lookup_table_one(struct ctl_table *table,
+							struct qstr *name)
+{
+	int len;
+	for ( ; table->ctl_name || table->procname; table++) {
+
+		if (!table->procname)
+			continue;
+
+		len = strlen(table->procname);
+		if (len != name->len)
+			continue;
+
+		if (memcmp(table->procname, name->name, len) != 0)
+			continue;
+
+		/* I have a match */
+		return table;
+	}
+	return NULL;
+}
+
+static struct ctl_table *proc_sys_lookup_table(struct dentry *dentry,
+						struct ctl_table *table)
+{
+	struct dentry *ancestor;
+	struct proc_inode *ei;
+	int depth, i;
+
+	ei = PROC_I(dentry->d_inode);
+	depth = ei->fd;
+
+	if (depth == 0)
+		return table;
+
+	for (i = 1; table && (i <= depth); i++) {
+		ancestor = proc_sys_ancestor(dentry, i);
+		table = proc_sys_lookup_table_one(table, &ancestor->d_name);
+		if (table)
+			table = table->child;
+	}
+	return table;
+
+}
+static struct ctl_table *proc_sys_lookup_entry(struct dentry *dparent,
+						struct qstr *name,
+						struct ctl_table *table)
+{
+	table = proc_sys_lookup_table(dparent, table);
+	if (table)
+		table = proc_sys_lookup_table_one(table, name);
+	return table;
+}
+
+static struct ctl_table *do_proc_sys_lookup(struct dentry *parent,
+						struct qstr *name,
+						struct ctl_table_header **ptr)
+{
+	struct ctl_table_header *head;
+	struct ctl_table *table = NULL;
+
+	for (head = sysctl_head_next(NULL); head;
+			head = sysctl_head_next(head)) {
+		table = proc_sys_lookup_entry(parent, name, head->ctl_table);
+		if (table)
+			break;
+	}
+	*ptr = head;
+	return table;
+}
+
+static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
+					struct nameidata *nd)
+{
+	struct ctl_table_header *head;
+	struct inode *inode;
+	struct dentry *err;
+	struct ctl_table *table;
+
+	err = ERR_PTR(-ENOENT);
+	table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+	if (!table)
+		goto out;
+
+	err = ERR_PTR(-ENOMEM);
+	inode = proc_sys_make_inode(dir, table);
+	if (!inode)
+		goto out;
+
+	err = NULL;
+	dentry->d_op = &proc_sys_dentry_operations;
+	d_add(dentry, inode);
+
+out:
+	sysctl_head_finish(head);
+	return err;
+}
+
+static ssize_t proc_sys_read(struct file *filp, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct dentry *dentry = filp->f_dentry;
+	struct ctl_table_header *head;
+	struct ctl_table *table;
+	ssize_t error, res;
+
+	table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+	/* Has the sysctl entry disappeared on us? */
+	error = -ENOENT;
+	if (!table)
+		goto out;
+
+	/* Has the sysctl entry been replaced by a directory? */
+	error = -EISDIR;
+	if (!table->proc_handler)
+		goto out;
+
+	/*
+	 * At this point we know that the sysctl was not unregistered
+	 * and won't be until we finish.
+	 */
+	error = -EPERM;
+	if (sysctl_perm(table, MAY_READ))
+		goto out;
+
+	/* careful: calling conventions are nasty here */
+	res = count;
+	error = table->proc_handler(table, 0, filp, buf, &res, ppos);
+	if (!error)
+		error = res;
+out:
+	sysctl_head_finish(head);
+
+	return error;
+}
+
+static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct dentry *dentry = filp->f_dentry;
+	struct ctl_table_header *head;
+	struct ctl_table *table;
+	ssize_t error, res;
+
+	table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+	/* Has the sysctl entry disappeared on us? */
+	error = -ENOENT;
+	if (!table)
+		goto out;
+
+	/* Has the sysctl entry been replaced by a directory? */
+	error = -EISDIR;
+	if (!table->proc_handler)
+		goto out;
+
+	/*
+	 * At this point we know that the sysctl was not unregistered
+	 * and won't be until we finish.
+	 */
+	error = -EPERM;
+	if (sysctl_perm(table, MAY_WRITE))
+		goto out;
+
+	/* careful: calling conventions are nasty here */
+	res = count;
+	error = table->proc_handler(table, 1, filp, (char __user *)buf,
+				    &res, ppos);
+	if (!error)
+		error = res;
+out:
+	sysctl_head_finish(head);
+
+	return error;
+}
+
+
+static int proc_sys_fill_cache(struct file *filp, void *dirent,
+				filldir_t filldir, struct ctl_table *table)
+{
+	struct ctl_table_header *head;
+	struct ctl_table *child_table = NULL;
+	struct dentry *child, *dir = filp->f_path.dentry;
+	struct inode *inode;
+	struct qstr qname;
+	ino_t ino = 0;
+	unsigned type = DT_UNKNOWN;
+	int ret;
+
+	qname.name = table->procname;
+	qname.len  = strlen(table->procname);
+	qname.hash = full_name_hash(qname.name, qname.len);
+
+	/* Suppress duplicates.
+	 * Only fill a directory entry if it is the value that
+	 * an ordinary lookup of that name returns.  Hide all
+	 * others.
+	 *
+	 * If we ever cache this translation in the dcache
+	 * I should do a dcache lookup first.  But for now
+	 * it is just simpler not to.
+	 */
+	ret = 0;
+	child_table = do_proc_sys_lookup(dir, &qname, &head);
+	sysctl_head_finish(head);
+	if (child_table != table)
+		return 0;
+
+	child = d_lookup(dir, &qname);
+	if (!child) {
+		struct dentry *new;
+		new = d_alloc(dir, &qname);
+		if (new) {
+			inode = proc_sys_make_inode(dir->d_inode, table);
+			if (!inode)
+				child = ERR_PTR(-ENOMEM);
+			else {
+				new->d_op = &proc_sys_dentry_operations;
+				d_add(new, inode);
+			}
+			if (child)
+				dput(new);
+			else
+				child = new;
+		}
+	}
+	if (!child || IS_ERR(child) || !child->d_inode)
+		goto end_instantiate;
+	inode = child->d_inode;
+	if (inode) {
+		ino  = inode->i_ino;
+		type = inode->i_mode >> 12;
+	}
+	dput(child);
+end_instantiate:
+	if (!ino)
+		ino= find_inode_number(dir, &qname);
+	if (!ino)
+		ino = 1;
+	return filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type);
+}
+
+static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct dentry *dentry = filp->f_dentry;
+	struct inode *inode = dentry->d_inode;
+	struct ctl_table_header *head = NULL;
+	struct ctl_table *table;
+	unsigned long pos;
+	int ret;
+
+	ret = -ENOTDIR;
+	if (!S_ISDIR(inode->i_mode))
+		goto out;
+
+	ret = 0;
+	/* Avoid a switch here: arm builds fail with missing __cmpdi2 */
+	if (filp->f_pos == 0) {
+		if (filldir(dirent, ".", 1, filp->f_pos,
+				inode->i_ino, DT_DIR) < 0)
+			goto out;
+		filp->f_pos++;
+	}
+	if (filp->f_pos == 1) {
+		if (filldir(dirent, "..", 2, filp->f_pos,
+				parent_ino(dentry), DT_DIR) < 0)
+			goto out;
+		filp->f_pos++;
+	}
+	pos = 2;
+
+	/* - Find each instance of the directory
+	 * - Read all entries in each instance
+	 * - Before returning an entry to user space lookup the entry
+	 *   by name and if I find a different entry don't return
+	 *   this one because it means it is a buried dup.
+	 * For sysctl this should only happen for directory entries.
+	 */
+	for (head = sysctl_head_next(NULL); head; head = sysctl_head_next(head)) {
+		table = proc_sys_lookup_table(dentry, head->ctl_table);
+
+		if (!table)
+			continue;
+
+		for (; table->ctl_name || table->procname; table++, pos++) {
+			/* Can't do anything without a proc name */
+			if (!table->procname)
+				continue;
+
+			if (pos < filp->f_pos)
+				continue;
+
+			if (proc_sys_fill_cache(filp, dirent, filldir, table) < 0)
+				goto out;
+			filp->f_pos = pos + 1;
+		}
+	}
+	ret = 1;
+out:
+	sysctl_head_finish(head);
+	return ret;
+}
+
+static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+	/*
+	 * sysctl entries that are not writeable,
+	 * are _NOT_ writeable, capabilities or not.
+	 */
+	struct ctl_table_header *head;
+	struct ctl_table *table;
+	struct dentry *dentry;
+	int mode;
+	int depth;
+	int error;
+
+	head = NULL;
+	depth = PROC_I(inode)->fd;
+
+	/* First check the cached permissions, in case we don't have
+	 * enough information to lookup the sysctl table entry.
+	 */
+	error = -EACCES;
+	mode = inode->i_mode;
+
+	if (current->euid == 0)
+		mode >>= 6;
+	else if (in_group_p(0))
+		mode >>= 3;
+
+	if ((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)
+		error = 0;
+
+	/* If we can't get a sysctl table entry the permission
+	 * checks on the cached mode will have to be enough.
+	 */
+	if (!nd || !depth)
+		goto out;
+
+	dentry = nd->dentry;
+	table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+
+	/* If the entry does not exist deny permission */
+	error = -EACCES;
+	if (!table)
+		goto out;
+
+	/* Use the permissions on the sysctl table entry */
+	error = sysctl_perm(table, mask);
+out:
+	sysctl_head_finish(head);
+	return error;
+}
+
+static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+
+	if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
+		return -EPERM;
+
+	error = inode_change_ok(inode, attr);
+	if (!error) {
+		error = security_inode_setattr(dentry, attr);
+		if (!error)
+			error = inode_setattr(inode, attr);
+	}
+
+	return error;
+}
+
+/* I'm lazy and don't distinguish between files and directories,
+ * until access time.
+ */
+static const struct file_operations proc_sys_file_operations = {
+	.read		= proc_sys_read,
+	.write		= proc_sys_write,
+	.readdir	= proc_sys_readdir,
+};
+
+static struct inode_operations proc_sys_inode_operations = {
+	.lookup		= proc_sys_lookup,
+	.permission	= proc_sys_permission,
+	.setattr	= proc_sys_setattr,
+};
+
+static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+	struct ctl_table_header *head;
+	struct ctl_table *table;
+	table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
+	proc_sys_refresh_inode(dentry->d_inode, table);
+	sysctl_head_finish(head);
+	return !!table;
+}
+
+static struct dentry_operations proc_sys_dentry_operations = {
+	.d_revalidate	= proc_sys_revalidate,
+};
+
+static struct proc_dir_entry *proc_sys_root;
+
+int proc_sys_init(void)
+{
+	proc_sys_root = proc_mkdir("sys", NULL);
+	proc_sys_root->proc_iops = &proc_sys_inode_operations;
+	proc_sys_root->proc_fops = &proc_sys_file_operations;
+	proc_sys_root->nlink = 0;
+	return 0;
+}
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index 15c4455..c1bbfbe 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -138,7 +138,7 @@
 	return seq_open(file, &tty_drivers_op);
 }
 
-static struct file_operations proc_tty_drivers_operations = {
+static const struct file_operations proc_tty_drivers_operations = {
 	.open		= tty_drivers_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 64d242b6..5834a744 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -23,10 +23,6 @@
 
 struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
 
-#ifdef CONFIG_SYSCTL
-struct proc_dir_entry *proc_sys_root;
-#endif
-
 static int proc_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
@@ -71,13 +67,6 @@
 #ifdef CONFIG_SYSVIPC
 	proc_mkdir("sysvipc", NULL);
 #endif
-#ifdef CONFIG_SYSCTL
-	proc_sys_root = proc_mkdir("sys", NULL);
-#endif
-#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
-	proc_mkdir("sys/fs", NULL);
-	proc_mkdir("sys/fs/binfmt_misc", NULL);
-#endif
 	proc_root_fs = proc_mkdir("fs", NULL);
 	proc_root_driver = proc_mkdir("driver", NULL);
 	proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */
@@ -90,6 +79,9 @@
 	proc_device_tree_init();
 #endif
 	proc_bus = proc_mkdir("bus", NULL);
+#ifdef CONFIG_SYSCTL
+	proc_sys_init();
+#endif
 }
 
 static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
@@ -136,7 +128,7 @@
  * <pid> directories. Thus we don't use the generic
  * directory handling functions for that..
  */
-static struct file_operations proc_root_operations = {
+static const struct file_operations proc_root_operations = {
 	.read		 = generic_read_dir,
 	.readdir	 = proc_root_readdir,
 };
@@ -144,7 +136,7 @@
 /*
  * proc root can do almost nothing..
  */
-static struct inode_operations proc_root_inode_operations = {
+static const struct inode_operations proc_root_inode_operations = {
 	.lookup		= proc_root_lookup,
 	.getattr	= proc_root_getattr,
 };
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 55ade0d..7445980 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -434,7 +434,7 @@
 	return do_maps_open(inode, file, &proc_pid_maps_op);
 }
 
-struct file_operations proc_maps_operations = {
+const struct file_operations proc_maps_operations = {
 	.open		= maps_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -456,7 +456,7 @@
 	return do_maps_open(inode, file, &proc_pid_numa_maps_op);
 }
 
-struct file_operations proc_numa_maps_operations = {
+const struct file_operations proc_numa_maps_operations = {
 	.open		= numa_maps_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -469,7 +469,7 @@
 	return do_maps_open(inode, file, &proc_pid_smaps_op);
 }
 
-struct file_operations proc_smaps_operations = {
+const struct file_operations proc_smaps_operations = {
 	.open		= smaps_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index fcc5caf..7cddf6b 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -220,7 +220,7 @@
 	return ret;
 }
 
-struct file_operations proc_maps_operations = {
+const struct file_operations proc_maps_operations = {
 	.open		= maps_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index c94db1d..ea9ffef 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -87,7 +87,7 @@
 	.fsync		= file_fsync,
 };
 
-struct inode_operations qnx4_dir_inode_operations =
+const struct inode_operations qnx4_dir_inode_operations =
 {
 	.lookup		= qnx4_lookup,
 #ifdef CONFIG_QNX4FS_RW
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index 467e5ac..4464998 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -33,7 +33,7 @@
 #endif
 };
 
-struct inode_operations qnx4_file_inode_operations =
+const struct inode_operations qnx4_file_inode_operations =
 {
 #ifdef CONFIG_QNX4FS_RW
 	.truncate	= qnx4_truncate,
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index c047dc6..83bc8e7 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -30,7 +30,7 @@
 #define QNX4_VERSION  4
 #define QNX4_BMNAME   ".bitmap"
 
-static struct super_operations qnx4_sops;
+static const struct super_operations qnx4_sops;
 
 #ifdef CONFIG_QNX4FS_RW
 
@@ -129,7 +129,7 @@
 static int qnx4_remount(struct super_block *sb, int *flags, char *data);
 static int qnx4_statfs(struct dentry *, struct kstatfs *);
 
-static struct super_operations qnx4_sops =
+static const struct super_operations qnx4_sops =
 {
 	.alloc_inode	= qnx4_alloc_inode,
 	.destroy_inode	= qnx4_destroy_inode,
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 54ebbc8..2f14774 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -31,7 +31,7 @@
 	.readpage	= simple_readpage,
 	.prepare_write	= simple_prepare_write,
 	.commit_write	= simple_commit_write,
-	.set_page_dirty = __set_page_dirty_nobuffers,
+	.set_page_dirty = __set_page_dirty_no_writeback,
 };
 
 const struct file_operations ramfs_file_operations = {
@@ -45,6 +45,6 @@
 	.llseek		= generic_file_llseek,
 };
 
-struct inode_operations ramfs_file_inode_operations = {
+const struct inode_operations ramfs_file_inode_operations = {
 	.getattr	= simple_getattr,
 };
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index e9d6c47..d3fd7c6 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -32,7 +32,7 @@
 	.readpage		= simple_readpage,
 	.prepare_write		= simple_prepare_write,
 	.commit_write		= simple_commit_write,
-	.set_page_dirty = __set_page_dirty_nobuffers,
+	.set_page_dirty		= __set_page_dirty_no_writeback,
 };
 
 const struct file_operations ramfs_file_operations = {
@@ -47,7 +47,7 @@
 	.llseek			= generic_file_llseek,
 };
 
-struct inode_operations ramfs_file_inode_operations = {
+const struct inode_operations ramfs_file_inode_operations = {
 	.setattr		= ramfs_nommu_setattr,
 	.getattr		= simple_getattr,
 };
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 2faf4cd..ff1f763 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -40,8 +40,8 @@
 /* some random number */
 #define RAMFS_MAGIC	0x858458f6
 
-static struct super_operations ramfs_ops;
-static struct inode_operations ramfs_dir_inode_operations;
+static const struct super_operations ramfs_ops;
+static const struct inode_operations ramfs_dir_inode_operations;
 
 static struct backing_dev_info ramfs_backing_dev_info = {
 	.ra_pages	= 0,	/* No readahead */
@@ -143,7 +143,7 @@
 	return error;
 }
 
-static struct inode_operations ramfs_dir_inode_operations = {
+static const struct inode_operations ramfs_dir_inode_operations = {
 	.create		= ramfs_create,
 	.lookup		= simple_lookup,
 	.link		= simple_link,
@@ -155,7 +155,7 @@
 	.rename		= simple_rename,
 };
 
-static struct super_operations ramfs_ops = {
+static const struct super_operations ramfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= generic_delete_inode,
 };
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h
index c2bb58e..af7cc07 100644
--- a/fs/ramfs/internal.h
+++ b/fs/ramfs/internal.h
@@ -12,4 +12,4 @@
 
 extern const struct address_space_operations ramfs_aops;
 extern const struct file_operations ramfs_file_operations;
-extern struct inode_operations ramfs_file_inode_operations;
+extern const struct inode_operations ramfs_file_inode_operations;
diff --git a/fs/read_write.c b/fs/read_write.c
index 707ac21..1f8dc37 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -197,13 +197,13 @@
 	struct inode *inode;
 	loff_t pos;
 
+	inode = file->f_path.dentry->d_inode;
 	if (unlikely((ssize_t) count < 0))
 		goto Einval;
 	pos = *ppos;
 	if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
 		goto Einval;
 
-	inode = file->f_path.dentry->d_inode;
 	if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) {
 		int retval = locks_mandatory_area(
 			read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
@@ -274,9 +274,9 @@
 				ret = do_sync_read(file, buf, count, pos);
 			if (ret > 0) {
 				fsnotify_access(file->f_path.dentry);
-				current->rchar += ret;
+				add_rchar(current, ret);
 			}
-			current->syscr++;
+			inc_syscr(current);
 		}
 	}
 
@@ -332,9 +332,9 @@
 				ret = do_sync_write(file, buf, count, pos);
 			if (ret > 0) {
 				fsnotify_modify(file->f_path.dentry);
-				current->wchar += ret;
+				add_wchar(current, ret);
 			}
-			current->syscw++;
+			inc_syscw(current);
 		}
 	}
 
@@ -675,8 +675,8 @@
 	}
 
 	if (ret > 0)
-		current->rchar += ret;
-	current->syscr++;
+		add_rchar(current, ret);
+	inc_syscr(current);
 	return ret;
 }
 
@@ -696,8 +696,8 @@
 	}
 
 	if (ret > 0)
-		current->wchar += ret;
-	current->syscw++;
+		add_wchar(current, ret);
+	inc_syscw(current);
 	return ret;
 }
 
@@ -779,12 +779,12 @@
 	retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file);
 
 	if (retval > 0) {
-		current->rchar += retval;
-		current->wchar += retval;
+		add_rchar(current, retval);
+		add_wchar(current, retval);
 	}
-	current->syscr++;
-	current->syscw++;
 
+	inc_syscr(current);
+	inc_syscw(current);
 	if (*ppos > max)
 		retval = -EOVERFLOW;
 
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
index fba304e..f85c5cf 100644
--- a/fs/reiserfs/do_balan.c
+++ b/fs/reiserfs/do_balan.c
@@ -19,6 +19,7 @@
 #include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/buffer_head.h>
+#include <linux/kernel.h>
 
 #ifdef CONFIG_REISERFS_CHECK
 
@@ -1756,7 +1757,7 @@
 	if (buffer_dirty(bh))
 		reiserfs_warning(tb->tb_sb,
 				 "store_thrown deals with dirty buffer");
-	for (i = 0; i < sizeof(tb->thrown) / sizeof(tb->thrown[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(tb->thrown); i++)
 		if (!tb->thrown[i]) {
 			tb->thrown[i] = bh;
 			get_bh(bh);	/* free_thrown puts this */
@@ -1769,7 +1770,7 @@
 {
 	int i;
 	b_blocknr_t blocknr;
-	for (i = 0; i < sizeof(tb->thrown) / sizeof(tb->thrown[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(tb->thrown); i++) {
 		if (tb->thrown[i]) {
 			blocknr = tb->thrown[i]->b_blocknr;
 			if (buffer_dirty(tb->thrown[i]))
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 5109f1d..abfada2 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1556,7 +1556,7 @@
 	.splice_write = generic_file_splice_write,
 };
 
-struct inode_operations reiserfs_file_inode_operations = {
+const struct inode_operations reiserfs_file_inode_operations = {
 	.truncate = reiserfs_vfs_truncate_file,
 	.setattr = reiserfs_setattr,
 	.setxattr = reiserfs_setxattr,
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 23f5cd5..a216184 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -1525,7 +1525,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations reiserfs_dir_inode_operations = {
+const struct inode_operations reiserfs_dir_inode_operations = {
 	//&reiserfs_dir_operations,   /* default_file_ops */
 	.create = reiserfs_create,
 	.lookup = reiserfs_lookup,
@@ -1548,7 +1548,7 @@
  * symlink operations.. same as page_symlink_inode_operations, with xattr
  * stuff added
  */
-struct inode_operations reiserfs_symlink_inode_operations = {
+const struct inode_operations reiserfs_symlink_inode_operations = {
 	.readlink = generic_readlink,
 	.follow_link = page_follow_link_light,
 	.put_link = page_put_link,
@@ -1564,7 +1564,7 @@
 /*
  * special file operations.. just xattr/acl stuff
  */
-struct inode_operations reiserfs_special_inode_operations = {
+const struct inode_operations reiserfs_special_inode_operations = {
 	.setattr = reiserfs_setattr,
 	.setxattr = reiserfs_setxattr,
 	.getxattr = reiserfs_getxattr,
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 58ad455..f13a7f1 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -593,7 +593,7 @@
 				   loff_t);
 #endif
 
-static struct super_operations reiserfs_sops = {
+static const struct super_operations reiserfs_sops = {
 	.alloc_inode = reiserfs_alloc_inode,
 	.destroy_inode = reiserfs_destroy_inode,
 	.write_inode = reiserfs_write_inode,
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index d3e243a..fd60101 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -110,7 +110,7 @@
 	return sum;
 }
 
-static struct super_operations romfs_ops;
+static const struct super_operations romfs_ops;
 
 static int romfs_fill_super(struct super_block *s, void *data, int silent)
 {
@@ -468,7 +468,7 @@
 	.readdir	= romfs_readdir,
 };
 
-static struct inode_operations romfs_dir_inode_operations = {
+static const struct inode_operations romfs_dir_inode_operations = {
 	.lookup		= romfs_lookup,
 };
 
@@ -598,7 +598,7 @@
 	return 0;
 }
 
-static struct super_operations romfs_ops = {
+static const struct super_operations romfs_ops = {
 	.alloc_inode	= romfs_alloc_inode,
 	.destroy_inode	= romfs_destroy_inode,
 	.read_inode	= romfs_read_inode,
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index b1e58d1..50136b1 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -42,7 +42,7 @@
 	.open		= smb_dir_open,
 };
 
-struct inode_operations smb_dir_inode_operations =
+const struct inode_operations smb_dir_inode_operations =
 {
 	.create		= smb_create,
 	.lookup		= smb_lookup,
@@ -54,7 +54,7 @@
 	.setattr	= smb_notify_change,
 };
 
-struct inode_operations smb_dir_inode_operations_unix =
+const struct inode_operations smb_dir_inode_operations_unix =
 {
 	.create		= smb_create,
 	.lookup		= smb_lookup,
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index e50533a..f161797 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -418,7 +418,7 @@
 	.sendfile	= smb_file_sendfile,
 };
 
-struct inode_operations smb_file_inode_operations =
+const struct inode_operations smb_file_inode_operations =
 {
 	.permission	= smb_file_permission,
 	.getattr	= smb_getattr,
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 84dfe3f..5faba4f 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -98,7 +98,7 @@
 	return 0;
 }
 
-static struct super_operations smb_sops =
+static const struct super_operations smb_sops =
 {
 	.alloc_inode	= smb_alloc_inode,
 	.destroy_inode	= smb_destroy_inode,
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
index 34fb462..03f456c 100644
--- a/fs/smbfs/proto.h
+++ b/fs/smbfs/proto.h
@@ -36,8 +36,8 @@
 extern void smb_install_null_ops(struct smb_ops *ops);
 /* dir.c */
 extern const struct file_operations smb_dir_operations;
-extern struct inode_operations smb_dir_inode_operations;
-extern struct inode_operations smb_dir_inode_operations_unix;
+extern const struct inode_operations smb_dir_inode_operations;
+extern const struct inode_operations smb_dir_inode_operations_unix;
 extern void smb_new_dentry(struct dentry *dentry);
 extern void smb_renew_times(struct dentry *dentry);
 /* cache.c */
@@ -65,7 +65,7 @@
 /* file.c */
 extern const struct address_space_operations smb_file_aops;
 extern const struct file_operations smb_file_operations;
-extern struct inode_operations smb_file_inode_operations;
+extern const struct inode_operations smb_file_inode_operations;
 /* ioctl.c */
 extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
 /* smbiod.c */
@@ -84,4 +84,4 @@
 extern int smb_request_recv(struct smb_sb_info *server);
 /* symlink.c */
 extern int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname);
-extern struct inode_operations smb_link_inode_operations;
+extern const struct inode_operations smb_link_inode_operations;
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
index a4bcae8..42261db 100644
--- a/fs/smbfs/request.c
+++ b/fs/smbfs/request.c
@@ -61,7 +61,7 @@
 	struct smb_request *req;
 	unsigned char *buf = NULL;
 
-	req = kmem_cache_alloc(req_cachep, GFP_KERNEL);
+	req = kmem_cache_zalloc(req_cachep, GFP_KERNEL);
 	VERBOSE("allocating request: %p\n", req);
 	if (!req)
 		goto out;
@@ -74,7 +74,6 @@
 		}
 	}
 
-	memset(req, 0, sizeof(struct smb_request));
 	req->rq_buffer = buf;
 	req->rq_bufsize = bufsize;
 	req->rq_server = server;
diff --git a/fs/smbfs/symlink.c b/fs/smbfs/symlink.c
index cdc53c4..fea20ce 100644
--- a/fs/smbfs/symlink.c
+++ b/fs/smbfs/symlink.c
@@ -6,7 +6,6 @@
  *  Please add a note about your changes to smbfs in the ChangeLog file.
  */
 
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
@@ -62,7 +61,7 @@
 		__putname(s);
 }
 
-struct inode_operations smb_link_inode_operations =
+const struct inode_operations smb_link_inode_operations =
 {
 	.readlink	= generic_readlink,
 	.follow_link	= smb_follow_link,
diff --git a/fs/stack.c b/fs/stack.c
index 8ffb880d..67716f6 100644
--- a/fs/stack.c
+++ b/fs/stack.c
@@ -20,11 +20,6 @@
 void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
 				int (*get_nlinks)(struct inode *))
 {
-	if (!get_nlinks)
-		dest->i_nlink = src->i_nlink;
-	else
-		dest->i_nlink = (*get_nlinks)(dest);
-
 	dest->i_mode = src->i_mode;
 	dest->i_uid = src->i_uid;
 	dest->i_gid = src->i_gid;
@@ -34,5 +29,14 @@
 	dest->i_ctime = src->i_ctime;
 	dest->i_blkbits = src->i_blkbits;
 	dest->i_flags = src->i_flags;
+
+	/*
+	 * Update the nlinks AFTER updating the above fields, because the
+	 * get_links callback may depend on them.
+	 */
+	if (!get_nlinks)
+		dest->i_nlink = src->i_nlink;
+	else
+		dest->i_nlink = (*get_nlinks)(dest);
 }
 EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
diff --git a/fs/super.c b/fs/super.c
index 3e7458c..60b1e50 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -285,7 +285,7 @@
  */
 void generic_shutdown_super(struct super_block *sb)
 {
-	struct super_operations *sop = sb->s_op;
+	const struct super_operations *sop = sb->s_op;
 
 	if (sb->s_root) {
 		shrink_dcache_for_umount(sb);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 9dcdf55..8813990 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -37,11 +37,10 @@
 {
 	struct sysfs_dirent * sd;
 
-	sd = kmem_cache_alloc(sysfs_dir_cachep, GFP_KERNEL);
+	sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
 	if (!sd)
 		return NULL;
 
-	memset(sd, 0, sizeof(*sd));
 	atomic_set(&sd->s_count, 1);
 	atomic_set(&sd->s_event, 1);
 	INIT_LIST_HEAD(&sd->s_children);
@@ -297,7 +296,7 @@
 	return ERR_PTR(err);
 }
 
-struct inode_operations sysfs_dir_inode_operations = {
+const struct inode_operations sysfs_dir_inode_operations = {
 	.lookup		= sysfs_lookup,
 	.setattr	= sysfs_setattr,
 };
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index c0e1176..8d4d839 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -54,7 +54,7 @@
 /**
  *	add_to_collection - add buffer to a collection
  *	@buffer:	buffer to be added
- *	@node		inode of set to add to
+ *	@node:		inode of set to add to
  */
 
 static inline void
@@ -502,6 +502,30 @@
 
 
 /**
+ * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
+ * @kobj: object we're acting for.
+ * @attr: attribute descriptor.
+ * @group: group name.
+ */
+int sysfs_add_file_to_group(struct kobject *kobj,
+		const struct attribute *attr, const char *group)
+{
+	struct dentry *dir;
+	int error;
+
+	dir = lookup_one_len(group, kobj->dentry, strlen(group));
+	if (IS_ERR(dir))
+		error = PTR_ERR(dir);
+	else {
+		error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR);
+		dput(dir);
+	}
+	return error;
+}
+EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
+
+
+/**
  * sysfs_update_file - update the modified timestamp on an object attribute.
  * @kobj: object we're acting for.
  * @attr: attribute descriptor.
@@ -586,6 +610,26 @@
 }
 
 
+/**
+ * sysfs_remove_file_from_group - remove an attribute file from a group.
+ * @kobj: object we're acting for.
+ * @attr: attribute descriptor.
+ * @group: group name.
+ */
+void sysfs_remove_file_from_group(struct kobject *kobj,
+		const struct attribute *attr, const char *group)
+{
+	struct dentry *dir;
+
+	dir = lookup_one_len(group, kobj->dentry, strlen(group));
+	if (!IS_ERR(dir)) {
+		sysfs_hash_and_remove(dir, attr->name);
+		dput(dir);
+	}
+}
+EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
+
+
 EXPORT_SYMBOL_GPL(sysfs_create_file);
 EXPORT_SYMBOL_GPL(sysfs_remove_file);
 EXPORT_SYMBOL_GPL(sysfs_update_file);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 542d2bc..dd1344b 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -29,7 +29,7 @@
 	.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
 };
 
-static struct inode_operations sysfs_inode_operations ={
+static const struct inode_operations sysfs_inode_operations ={
 	.setattr	= sysfs_setattr,
 };
 
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index f6a87a8..23a48a3 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -21,7 +21,7 @@
 
 static void sysfs_clear_inode(struct inode *inode);
 
-static struct super_operations sysfs_ops = {
+static const struct super_operations sysfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= sysfs_delete_inode,
 	.clear_inode	= sysfs_clear_inode,
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 4869f61..7b9c5bf 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -181,7 +181,7 @@
 		free_page((unsigned long)page);
 }
 
-struct inode_operations sysfs_symlink_inode_operations = {
+const struct inode_operations sysfs_symlink_inode_operations = {
 	.readlink = generic_readlink,
 	.follow_link = sysfs_follow_link,
 	.put_link = sysfs_put_link,
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index fe1cbfd..a77c57e 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -1,3 +1,14 @@
+struct sysfs_dirent {
+	atomic_t		s_count;
+	struct list_head	s_sibling;
+	struct list_head	s_children;
+	void 			* s_element;
+	int			s_type;
+	umode_t			s_mode;
+	struct dentry		* s_dentry;
+	struct iattr		* s_iattr;
+	atomic_t		s_event;
+};
 
 extern struct vfsmount * sysfs_mount;
 extern struct kmem_cache *sysfs_dir_cachep;
@@ -26,8 +37,8 @@
 extern const struct file_operations sysfs_dir_operations;
 extern const struct file_operations sysfs_file_operations;
 extern const struct file_operations bin_fops;
-extern struct inode_operations sysfs_dir_inode_operations;
-extern struct inode_operations sysfs_symlink_inode_operations;
+extern const struct inode_operations sysfs_dir_inode_operations;
+extern const struct inode_operations sysfs_symlink_inode_operations;
 
 struct sysfs_symlink {
 	char * link_name;
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 47a4b72..0732ddb 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -30,7 +30,7 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-struct inode_operations sysv_file_inode_operations = {
+const struct inode_operations sysv_file_inode_operations = {
 	.truncate	= sysv_truncate,
 	.getattr	= sysv_getattr,
 };
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index ead9864..9311cac 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -142,7 +142,7 @@
 	}
 }
 
-static struct inode_operations sysv_symlink_inode_operations = {
+static const struct inode_operations sysv_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -327,7 +327,7 @@
 		inode_init_once(&si->vfs_inode);
 }
 
-struct super_operations sysv_sops = {
+const struct super_operations sysv_sops = {
 	.alloc_inode	= sysv_alloc_inode,
 	.destroy_inode	= sysv_destroy_inode,
 	.read_inode	= sysv_read_inode,
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index f7c08db..4e48abb 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -292,7 +292,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations sysv_dir_inode_operations = {
+const struct inode_operations sysv_dir_inode_operations = {
 	.create		= sysv_create,
 	.lookup		= sysv_lookup,
 	.link		= sysv_link,
diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c
index b85ce61..00d2f8a 100644
--- a/fs/sysv/symlink.c
+++ b/fs/sysv/symlink.c
@@ -14,7 +14,7 @@
 	return NULL;
 }
 
-struct inode_operations sysv_fast_symlink_inode_operations = {
+const struct inode_operations sysv_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= sysv_follow_link,
 };
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index dcb18b2..5b4fedf 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -159,13 +159,13 @@
 extern ino_t sysv_inode_by_name(struct dentry *);
 
 
-extern struct inode_operations sysv_file_inode_operations;
-extern struct inode_operations sysv_dir_inode_operations;
-extern struct inode_operations sysv_fast_symlink_inode_operations;
+extern const struct inode_operations sysv_file_inode_operations;
+extern const struct inode_operations sysv_dir_inode_operations;
+extern const struct inode_operations sysv_fast_symlink_inode_operations;
 extern const struct file_operations sysv_file_operations;
 extern const struct file_operations sysv_dir_operations;
 extern const struct address_space_operations sysv_aops;
-extern struct super_operations sysv_sops;
+extern const struct super_operations sysv_sops;
 extern struct dentry_operations sysv_dentry_operations;
 
 
diff --git a/fs/udf/file.c b/fs/udf/file.c
index d81f2db..40d5047 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -263,6 +263,6 @@
 	.sendfile		= generic_file_sendfile,
 };
 
-struct inode_operations udf_file_inode_operations = {
+const struct inode_operations udf_file_inode_operations = {
 	.truncate		= udf_truncate,
 };
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 7316332..fe361cd 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -1308,7 +1308,7 @@
 	return retval;
 }
 
-struct inode_operations udf_dir_inode_operations = {
+const struct inode_operations udf_dir_inode_operations = {
 	.lookup				= udf_lookup,
 	.create				= udf_create,
 	.link				= udf_link,
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 1dbc295..8672b88 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -160,7 +160,7 @@
 }
 
 /* Superblock operations */
-static struct super_operations udf_sb_ops = {
+static const struct super_operations udf_sb_ops = {
 	.alloc_inode		= udf_alloc_inode,
 	.destroy_inode		= udf_destroy_inode,
 	.write_inode		= udf_write_inode,
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 1033b7c..ee1dece 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -42,9 +42,9 @@
 struct buffer_head;
 struct super_block;
 
-extern struct inode_operations udf_dir_inode_operations;
+extern const struct inode_operations udf_dir_inode_operations;
 extern const struct file_operations udf_dir_operations;
-extern struct inode_operations udf_file_inode_operations;
+extern const struct inode_operations udf_file_inode_operations;
 extern const struct file_operations udf_file_operations;
 extern const struct address_space_operations udf_aops;
 extern const struct address_space_operations udf_adinicb_aops;
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 638f4c5..bcc4408 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -4,6 +4,8 @@
  * Copyright (C) 1998
  * Daniel Pirkl <daniel.pirkl@email.cz>
  * Charles University, Faculty of Mathematics and Physics
+ *
+ * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007
  */
 
 #include <linux/fs.h>
@@ -14,45 +16,48 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
-#include <linux/sched.h>
 #include <linux/bitops.h>
 #include <asm/byteorder.h>
 
 #include "swab.h"
 #include "util.h"
 
-static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
-static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
-static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
-static unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);
+#define INVBLOCK ((u64)-1L)
+
+static u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned, int *);
+static u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *);
+static u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *);
+static u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned);
 static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
 static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
 
 /*
  * Free 'count' fragments from fragment number 'fragment'
  */
-void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count)
+void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
-	unsigned cgno, bit, end_bit, bbase, blkmap, i, blkno, cylno;
+	unsigned cgno, bit, end_bit, bbase, blkmap, i;
+	u64 blkno;
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first(uspi);
 	
-	UFSD("ENTER, fragment %u, count %u\n", fragment, count);
+	UFSD("ENTER, fragment %llu, count %u\n",
+	     (unsigned long long)fragment, count);
 	
 	if (ufs_fragnum(fragment) + count > uspi->s_fpg)
 		ufs_error (sb, "ufs_free_fragments", "internal error");
 	
 	lock_super(sb);
 	
-	cgno = ufs_dtog(fragment);
-	bit = ufs_dtogd(fragment);
+	cgno = ufs_dtog(uspi, fragment);
+	bit = ufs_dtogd(uspi, fragment);
 	if (cgno >= uspi->s_ncg) {
 		ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device");
 		goto failed;
@@ -101,9 +106,13 @@
 		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
 		uspi->cs_total.cs_nbfree++;
 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
-		cylno = ufs_cbtocylno (bbase);
-		fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(bbase)), 1);
-		fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+		if (uspi->fs_magic != UFS2_MAGIC) {
+			unsigned cylno = ufs_cbtocylno (bbase);
+
+			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
+						  ufs_cbtorpos(bbase)), 1);
+			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+		}
 	}
 	
 	ubh_mark_buffer_dirty (USPI_UBH(uspi));
@@ -127,24 +136,27 @@
 /*
  * Free 'count' fragments from fragment number 'fragment' (free whole blocks)
  */
-void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count)
+void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
-	unsigned overflow, cgno, bit, end_bit, blkno, i, cylno;
+	unsigned overflow, cgno, bit, end_bit, i;
+	u64 blkno;
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first(uspi);
 
-	UFSD("ENTER, fragment %u, count %u\n", fragment, count);
+	UFSD("ENTER, fragment %llu, count %u\n",
+	     (unsigned long long)fragment, count);
 	
 	if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
 		ufs_error (sb, "ufs_free_blocks", "internal error, "
-			"fragment %u, count %u\n", fragment, count);
+			   "fragment %llu, count %u\n",
+			   (unsigned long long)fragment, count);
 		goto failed;
 	}
 
@@ -152,8 +164,8 @@
 	
 do_more:
 	overflow = 0;
-	cgno = ufs_dtog (fragment);
-	bit = ufs_dtogd (fragment);
+	cgno = ufs_dtog(uspi, fragment);
+	bit = ufs_dtogd(uspi, fragment);
 	if (cgno >= uspi->s_ncg) {
 		ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
 		goto failed_unlock;
@@ -187,9 +199,14 @@
 		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
 		uspi->cs_total.cs_nbfree++;
 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
-		cylno = ufs_cbtocylno(i);
-		fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i)), 1);
-		fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+
+		if (uspi->fs_magic != UFS2_MAGIC) {
+			unsigned cylno = ufs_cbtocylno(i);
+
+			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
+						  ufs_cbtorpos(i)), 1);
+			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+		}
 	}
 
 	ubh_mark_buffer_dirty (USPI_UBH(uspi));
@@ -308,15 +325,19 @@
 	}
 }
 
-unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
-			   unsigned goal, unsigned count, int * err, struct page *locked_page)
+u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
+			   u64 goal, unsigned count, int *err,
+			   struct page *locked_page)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
-	unsigned cgno, oldcount, newcount, tmp, request, result;
+	unsigned cgno, oldcount, newcount;
+	u64 tmp, request, result;
 	
-	UFSD("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count);
+	UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n",
+	     inode->i_ino, (unsigned long long)fragment,
+	     (unsigned long long)goal, count);
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -324,11 +345,12 @@
 	*err = -ENOSPC;
 
 	lock_super (sb);
-	
-	tmp = fs32_to_cpu(sb, *p);
+	tmp = ufs_data_ptr_to_cpu(sb, p);
+
 	if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
-		ufs_warning (sb, "ufs_new_fragments", "internal warning"
-			" fragment %u, count %u", fragment, count);
+		ufs_warning(sb, "ufs_new_fragments", "internal warning"
+			    " fragment %llu, count %u",
+			    (unsigned long long)fragment, count);
 		count = uspi->s_fpb - ufs_fragnum(fragment); 
 	}
 	oldcount = ufs_fragnum (fragment);
@@ -339,10 +361,12 @@
 	 */
 	if (oldcount) {
 		if (!tmp) {
-			ufs_error (sb, "ufs_new_fragments", "internal error, "
-				"fragment %u, tmp %u\n", fragment, tmp);
-			unlock_super (sb);
-			return (unsigned)-1;
+			ufs_error(sb, "ufs_new_fragments", "internal error, "
+				  "fragment %llu, tmp %llu\n",
+				  (unsigned long long)fragment,
+				  (unsigned long long)tmp);
+			unlock_super(sb);
+			return INVBLOCK;
 		}
 		if (fragment < UFS_I(inode)->i_lastfrag) {
 			UFSD("EXIT (ALREADY ALLOCATED)\n");
@@ -372,7 +396,7 @@
 	if (goal == 0) 
 		cgno = ufs_inotocg (inode->i_ino);
 	else
-		cgno = ufs_dtog (goal);
+		cgno = ufs_dtog(uspi, goal);
 	 
 	/*
 	 * allocate new fragment
@@ -380,14 +404,16 @@
 	if (oldcount == 0) {
 		result = ufs_alloc_fragments (inode, cgno, goal, count, err);
 		if (result) {
-			*p = cpu_to_fs32(sb, result);
+			ufs_cpu_to_data_ptr(sb, p, result);
 			*err = 0;
-			UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
-			ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
-					locked_page != NULL);
+			UFS_I(inode)->i_lastfrag =
+				max_t(u32, UFS_I(inode)->i_lastfrag,
+				      fragment + count);
+			ufs_clear_frags(inode, result + oldcount,
+					newcount - oldcount, locked_page != NULL);
 		}
 		unlock_super(sb);
-		UFSD("EXIT, result %u\n", result);
+		UFSD("EXIT, result %llu\n", (unsigned long long)result);
 		return result;
 	}
 
@@ -401,7 +427,7 @@
 		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
 				locked_page != NULL);
 		unlock_super(sb);
-		UFSD("EXIT, result %u\n", result);
+		UFSD("EXIT, result %llu\n", (unsigned long long)result);
 		return result;
 	}
 
@@ -433,15 +459,14 @@
 				locked_page != NULL);
 		ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp,
 				   result, locked_page);
-
-		*p = cpu_to_fs32(sb, result);
+		ufs_cpu_to_data_ptr(sb, p, result);
 		*err = 0;
 		UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
 		unlock_super(sb);
 		if (newcount < request)
 			ufs_free_fragments (inode, result + newcount, request - newcount);
 		ufs_free_fragments (inode, tmp, oldcount);
-		UFSD("EXIT, result %u\n", result);
+		UFSD("EXIT, result %llu\n", (unsigned long long)result);
 		return result;
 	}
 
@@ -450,9 +475,8 @@
 	return 0;
 }		
 
-static unsigned
-ufs_add_fragments (struct inode * inode, unsigned fragment,
-		   unsigned oldcount, unsigned newcount, int * err)
+static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
+			     unsigned oldcount, unsigned newcount, int *err)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
@@ -461,14 +485,15 @@
 	struct ufs_cylinder_group * ucg;
 	unsigned cgno, fragno, fragoff, count, fragsize, i;
 	
-	UFSD("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount);
+	UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n",
+	     (unsigned long long)fragment, oldcount, newcount);
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first (uspi);
 	count = newcount - oldcount;
 	
-	cgno = ufs_dtog(fragment);
+	cgno = ufs_dtog(uspi, fragment);
 	if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count)
 		return 0;
 	if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb)
@@ -483,7 +508,7 @@
 		return 0;
 	}
 
-	fragno = ufs_dtogd (fragment);
+	fragno = ufs_dtogd(uspi, fragment);
 	fragoff = ufs_fragnum (fragno);
 	for (i = oldcount; i < newcount; i++)
 		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
@@ -521,7 +546,7 @@
 	}
 	sb->s_dirt = 1;
 
-	UFSD("EXIT, fragment %u\n", fragment);
+	UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment);
 	
 	return fragment;
 }
@@ -534,17 +559,19 @@
 		if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
 			goto cg_found; 
 
-static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
-	unsigned goal, unsigned count, int * err)
+static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
+			       u64 goal, unsigned count, int *err)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
-	unsigned oldcg, i, j, k, result, allocsize;
+	unsigned oldcg, i, j, k, allocsize;
+	u64 result;
 	
-	UFSD("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count);
+	UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n",
+	     inode->i_ino, cgno, (unsigned long long)goal, count);
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -593,7 +620,7 @@
 
 	if (count == uspi->s_fpb) {
 		result = ufs_alloccg_block (inode, ucpi, goal, err);
-		if (result == (unsigned)-1)
+		if (result == INVBLOCK)
 			return 0;
 		goto succed;
 	}
@@ -604,9 +631,9 @@
 	
 	if (allocsize == uspi->s_fpb) {
 		result = ufs_alloccg_block (inode, ucpi, goal, err);
-		if (result == (unsigned)-1)
+		if (result == INVBLOCK)
 			return 0;
-		goal = ufs_dtogd (result);
+		goal = ufs_dtogd(uspi, result);
 		for (i = count; i < uspi->s_fpb; i++)
 			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
 		i = uspi->s_fpb - count;
@@ -620,7 +647,7 @@
 	}
 
 	result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
-	if (result == (unsigned)-1)
+	if (result == INVBLOCK)
 		return 0;
 	if(DQUOT_ALLOC_BLOCK(inode, count)) {
 		*err = -EDQUOT;
@@ -647,20 +674,21 @@
 	sb->s_dirt = 1;
 
 	result += cgno * uspi->s_fpg;
-	UFSD("EXIT3, result %u\n", result);
+	UFSD("EXIT3, result %llu\n", (unsigned long long)result);
 	return result;
 }
 
-static unsigned ufs_alloccg_block (struct inode * inode,
-	struct ufs_cg_private_info * ucpi, unsigned goal, int * err)
+static u64 ufs_alloccg_block(struct inode *inode,
+			     struct ufs_cg_private_info *ucpi,
+			     u64 goal, int *err)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_cylinder_group * ucg;
-	unsigned result, cylno, blkno;
+	u64 result, blkno;
 
-	UFSD("ENTER, goal %u\n", goal);
+	UFSD("ENTER, goal %llu\n", (unsigned long long)goal);
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -672,7 +700,7 @@
 		goto norot;
 	}
 	goal = ufs_blknum (goal);
-	goal = ufs_dtogd (goal);
+	goal = ufs_dtogd(uspi, goal);
 	
 	/*
 	 * If the requested block is available, use it.
@@ -684,8 +712,8 @@
 	
 norot:	
 	result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb);
-	if (result == (unsigned)-1)
-		return (unsigned)-1;
+	if (result == INVBLOCK)
+		return INVBLOCK;
 	ucpi->c_rotor = result;
 gotit:
 	blkno = ufs_fragstoblks(result);
@@ -694,17 +722,22 @@
 		ufs_clusteracct (sb, ucpi, blkno, -1);
 	if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) {
 		*err = -EDQUOT;
-		return (unsigned)-1;
+		return INVBLOCK;
 	}
 
 	fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
 	uspi->cs_total.cs_nbfree--;
 	fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
-	cylno = ufs_cbtocylno(result);
-	fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)), 1);
-	fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+
+	if (uspi->fs_magic != UFS2_MAGIC) {
+		unsigned cylno = ufs_cbtocylno((unsigned)result);
+
+		fs16_sub(sb, &ubh_cg_blks(ucpi, cylno,
+					  ufs_cbtorpos((unsigned)result)), 1);
+		fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+	}
 	
-	UFSD("EXIT, result %u\n", result);
+	UFSD("EXIT, result %llu\n", (unsigned long long)result);
 
 	return result;
 }
@@ -744,9 +777,9 @@
  * @goal: near which block we want find new one
  * @count: specified size
  */
-static unsigned ufs_bitmap_search(struct super_block *sb,
-				  struct ufs_cg_private_info *ucpi,
-				  unsigned goal, unsigned count)
+static u64 ufs_bitmap_search(struct super_block *sb,
+			     struct ufs_cg_private_info *ucpi,
+			     u64 goal, unsigned count)
 {
 	/*
 	 * Bit patterns for identifying fragments in the block map
@@ -761,16 +794,18 @@
 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	struct ufs_super_block_first *usb1;
 	struct ufs_cylinder_group *ucg;
-	unsigned start, length, loc, result;
+	unsigned start, length, loc;
 	unsigned pos, want, blockmap, mask, end;
+	u64 result;
 
-	UFSD("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count);
+	UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx,
+	     (unsigned long long)goal, count);
 
 	usb1 = ubh_get_usb_first (uspi);
 	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 
 	if (goal)
-		start = ufs_dtogd(goal) >> 3;
+		start = ufs_dtogd(uspi, goal) >> 3;
 	else
 		start = ucpi->c_frotor >> 3;
 		
@@ -790,7 +825,7 @@
 				  " length %u, count %u, freeoff %u\n",
 				  ucpi->c_cgx, start, length, count,
 				  ucpi->c_freeoff);
-			return (unsigned)-1;
+			return INVBLOCK;
 		}
 		start = 0;
 	}
@@ -808,7 +843,8 @@
 		want = want_arr[count];
 		for (pos = 0; pos <= uspi->s_fpb - count; pos++) {
 			if ((blockmap & mask) == want) {
-				UFSD("EXIT, result %u\n", result);
+				UFSD("EXIT, result %llu\n",
+				     (unsigned long long)result);
 				return result + pos;
  			}
 			mask <<= 1;
@@ -819,7 +855,7 @@
 	ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n",
 		  ucpi->c_cgx);
 	UFSD("EXIT (FAILED)\n");
-	return (unsigned)-1;
+	return INVBLOCK;
 }
 
 static void ufs_clusteracct(struct super_block * sb,
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 433b6f6..4890ddf 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -20,7 +20,6 @@
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/smp_lock.h>
-#include <linux/sched.h>
 
 #include "swab.h"
 #include "util.h"
@@ -106,12 +105,13 @@
 	char *kaddr = page_address(page);
 	unsigned offs, rec_len;
 	unsigned limit = PAGE_CACHE_SIZE;
+	const unsigned chunk_mask = UFS_SB(sb)->s_uspi->s_dirblksize - 1;
 	struct ufs_dir_entry *p;
 	char *error;
 
 	if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) {
 		limit = dir->i_size & ~PAGE_CACHE_MASK;
-		if (limit & (UFS_SECTOR_SIZE - 1))
+		if (limit & chunk_mask)
 			goto Ebadsize;
 		if (!limit)
 			goto out;
@@ -126,7 +126,7 @@
 			goto Ealign;
 		if (rec_len < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, p)))
 			goto Enamelen;
-		if (((offs + rec_len - 1) ^ offs) & ~(UFS_SECTOR_SIZE-1))
+		if (((offs + rec_len - 1) ^ offs) & ~chunk_mask)
 			goto Espan;
 		if (fs32_to_cpu(sb, p->d_ino) > (UFS_SB(sb)->s_uspi->s_ipg *
 						  UFS_SB(sb)->s_uspi->s_ncg))
@@ -310,6 +310,7 @@
 	int namelen = dentry->d_name.len;
 	struct super_block *sb = dir->i_sb;
 	unsigned reclen = UFS_DIR_REC_LEN(namelen);
+	const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize;
 	unsigned short rec_len, name_len;
 	struct page *page = NULL;
 	struct ufs_dir_entry *de;
@@ -342,8 +343,8 @@
 			if ((char *)de == dir_end) {
 				/* We hit i_size */
 				name_len = 0;
-				rec_len = UFS_SECTOR_SIZE;
-				de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE);
+				rec_len = chunk_size;
+				de->d_reclen = cpu_to_fs16(sb, chunk_size);
 				de->d_ino = 0;
 				goto got_it;
 			}
@@ -431,7 +432,7 @@
 	unsigned int offset = pos & ~PAGE_CACHE_MASK;
 	unsigned long n = pos >> PAGE_CACHE_SHIFT;
 	unsigned long npages = ufs_dir_pages(inode);
-	unsigned chunk_mask = ~(UFS_SECTOR_SIZE - 1);
+	unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);
 	int need_revalidate = filp->f_version != inode->i_version;
 	unsigned flags = UFS_SB(sb)->s_flags;
 
@@ -511,7 +512,7 @@
 	struct super_block *sb = inode->i_sb;
 	struct address_space *mapping = page->mapping;
 	char *kaddr = page_address(page);
-	unsigned from = ((char*)dir - kaddr) & ~(UFS_SECTOR_SIZE - 1);
+	unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);
 	unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen);
 	struct ufs_dir_entry *pde = NULL;
 	struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from);
@@ -556,6 +557,7 @@
 	struct super_block * sb = dir->i_sb;
 	struct address_space *mapping = inode->i_mapping;
 	struct page *page = grab_cache_page(mapping, 0);
+	const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize;
 	struct ufs_dir_entry * de;
 	char *base;
 	int err;
@@ -563,7 +565,7 @@
 	if (!page)
 		return -ENOMEM;
 	kmap(page);
-	err = mapping->a_ops->prepare_write(NULL, page, 0, UFS_SECTOR_SIZE);
+	err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size);
 	if (err) {
 		unlock_page(page);
 		goto fail;
@@ -584,11 +586,11 @@
 		((char *)de + fs16_to_cpu(sb, de->d_reclen));
 	de->d_ino = cpu_to_fs32(sb, dir->i_ino);
 	ufs_set_de_type(sb, de, dir->i_mode);
-	de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
+	de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1));
 	ufs_set_de_namlen(sb, de, 2);
 	strcpy (de->d_name, "..");
 
-	err = ufs_commit_chunk(page, 0, UFS_SECTOR_SIZE);
+	err = ufs_commit_chunk(page, 0, chunk_size);
 fail:
 	kunmap(page);
 	page_cache_release(page);
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 2ad1259..b868878 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -18,6 +18,9 @@
  *  Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
+ *
+ * UFS2 write support added by
+ * Evgeniy Dushistov <dushistov@mail.ru>, 2007
  */
 
 #include <linux/fs.h>
@@ -126,6 +129,47 @@
 }
 
 /*
+ * Nullify new chunk of inodes,
+ * BSD people also set ui_gen field of inode
+ * during nullification, but we not care about
+ * that because of linux ufs do not support NFS
+ */
+static void ufs2_init_inodes_chunk(struct super_block *sb,
+				   struct ufs_cg_private_info *ucpi,
+				   struct ufs_cylinder_group *ucg)
+{
+	struct buffer_head *bh;
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+	sector_t beg = uspi->s_sbbase +
+		ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg +
+			      fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk));
+	sector_t end = beg + uspi->s_fpb;
+
+	UFSD("ENTER cgno %d\n", ucpi->c_cgx);
+
+	for (; beg < end; ++beg) {
+		bh = sb_getblk(sb, beg);
+		lock_buffer(bh);
+		memset(bh->b_data, 0, sb->s_blocksize);
+		set_buffer_uptodate(bh);
+		mark_buffer_dirty(bh);
+		unlock_buffer(bh);
+		if (sb->s_flags & MS_SYNCHRONOUS)
+			sync_dirty_buffer(bh);
+		brelse(bh);
+	}
+
+	fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb);
+	ubh_mark_buffer_dirty(UCPI_UBH(ucpi));
+	if (sb->s_flags & MS_SYNCHRONOUS) {
+		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
+		ubh_wait_on_buffer(UCPI_UBH(ucpi));
+	}
+
+	UFSD("EXIT\n");
+}
+
+/*
  * There are two policies for allocating an inode.  If the new inode is
  * a directory, then a forward search is made for a block group with both
  * free space and a low directory-to-inode ratio; if that fails, then of
@@ -146,6 +190,7 @@
 	struct inode * inode;
 	unsigned cg, bit, i, j, start;
 	struct ufs_inode_info *ufsi;
+	int err = -ENOSPC;
 
 	UFSD("ENTER\n");
 	
@@ -198,13 +243,15 @@
 			goto cg_found;
 		}
 	}
-	
+
 	goto failed;
 
 cg_found:
 	ucpi = ufs_load_cylinder (sb, cg);
-	if (!ucpi)
+	if (!ucpi) {
+		err = -EIO;
 		goto failed;
+	}
 	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 	if (!ufs_cg_chkmagic(sb, ucg)) 
 		ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number");
@@ -216,6 +263,7 @@
 		if (!(bit < start)) {
 			ufs_error (sb, "ufs_new_inode",
 			    "cylinder group %u corrupted - error in inode bitmap\n", cg);
+			err = -EIO;
 			goto failed;
 		}
 	}
@@ -224,9 +272,18 @@
 		ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
 	else {
 		ufs_panic (sb, "ufs_new_inode", "internal error");
+		err = -EIO;
 		goto failed;
 	}
-	
+
+	if (uspi->fs_magic == UFS2_MAGIC) {
+		u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk);
+
+		if (bit + uspi->s_inopb > initediblk &&
+		    initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk))
+			ufs2_init_inodes_chunk(sb, ucpi, ucg);
+	}
+
 	fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1);
 	uspi->cs_total.cs_nifree--;
 	fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1);
@@ -236,7 +293,6 @@
 		uspi->cs_total.cs_ndir++;
 		fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1);
 	}
-
 	ubh_mark_buffer_dirty (USPI_UBH(uspi));
 	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
 	if (sb->s_flags & MS_SYNCHRONOUS) {
@@ -245,6 +301,7 @@
 	}
 	sb->s_dirt = 1;
 
+	inode->i_ino = cg * uspi->s_ipg + bit;
 	inode->i_mode = mode;
 	inode->i_uid = current->fsuid;
 	if (dir->i_mode & S_ISGID) {
@@ -254,39 +311,72 @@
 	} else
 		inode->i_gid = current->fsgid;
 
-	inode->i_ino = cg * uspi->s_ipg + bit;
 	inode->i_blocks = 0;
+	inode->i_generation = 0;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	ufsi->i_flags = UFS_I(dir)->i_flags;
 	ufsi->i_lastfrag = 0;
-	ufsi->i_gen = 0;
 	ufsi->i_shadow = 0;
 	ufsi->i_osync = 0;
 	ufsi->i_oeftflag = 0;
 	ufsi->i_dir_start_lookup = 0;
 	memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1));
-
 	insert_inode_hash(inode);
 	mark_inode_dirty(inode);
 
+	if (uspi->fs_magic == UFS2_MAGIC) {
+		struct buffer_head *bh;
+		struct ufs2_inode *ufs2_inode;
+
+		/*
+		 * setup birth date, we do it here because of there is no sense
+		 * to hold it in struct ufs_inode_info, and lose 64 bit
+		 */
+		bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
+		if (!bh) {
+			ufs_warning(sb, "ufs_read_inode",
+				    "unable to read inode %lu\n",
+				    inode->i_ino);
+			err = -EIO;
+			goto fail_remove_inode;
+		}
+		lock_buffer(bh);
+		ufs2_inode = (struct ufs2_inode *)bh->b_data;
+		ufs2_inode += ufs_inotofsbo(inode->i_ino);
+		ufs2_inode->ui_birthtime.tv_sec =
+			cpu_to_fs32(sb, CURRENT_TIME_SEC.tv_sec);
+		ufs2_inode->ui_birthtime.tv_usec = 0;
+		mark_buffer_dirty(bh);
+		unlock_buffer(bh);
+		if (sb->s_flags & MS_SYNCHRONOUS)
+			sync_dirty_buffer(bh);
+		brelse(bh);
+	}
+
 	unlock_super (sb);
 
 	if (DQUOT_ALLOC_INODE(inode)) {
 		DQUOT_DROP(inode);
-		inode->i_flags |= S_NOQUOTA;
-		inode->i_nlink = 0;
-		iput(inode);
-		return ERR_PTR(-EDQUOT);
+		err = -EDQUOT;
+		goto fail_without_unlock;
 	}
 
 	UFSD("allocating inode %lu\n", inode->i_ino);
 	UFSD("EXIT\n");
 	return inode;
 
+fail_remove_inode:
+	unlock_super(sb);
+fail_without_unlock:
+	inode->i_flags |= S_NOQUOTA;
+	inode->i_nlink = 0;
+	iput(inode);
+	UFSD("EXIT (FAILED): err %d\n", err);
+	return ERR_PTR(err);
 failed:
 	unlock_super (sb);
 	make_bad_inode(inode);
 	iput (inode);
-	UFSD("EXIT (FAILED)\n");
-	return ERR_PTR(-ENOSPC);
+	UFSD("EXIT (FAILED): err %d\n", err);
+	return ERR_PTR(err);
 }
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 4295ca9..fb34ad0 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -170,7 +170,7 @@
  * @locked_page - for ufs_new_fragments()
  */
 static struct buffer_head *
-ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
+ufs_inode_getfrag(struct inode *inode, u64 fragment,
 		  sector_t new_fragment, unsigned int required, int *err,
 		  long *phys, int *new, struct page *locked_page)
 {
@@ -178,12 +178,12 @@
 	struct super_block *sb = inode->i_sb;
 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	struct buffer_head * result;
-	unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
-	unsigned tmp, goal;
-	__fs32 * p, * p2;
+	unsigned blockoff, lastblockoff;
+	u64 tmp, goal, lastfrag, block, lastblock;
+	void *p, *p2;
 
-	UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, required %u, "
-	     "metadata %d\n", inode->i_ino, fragment,
+	UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, "
+	     "metadata %d\n", inode->i_ino, (unsigned long long)fragment,
 	     (unsigned long long)new_fragment, required, !phys);
 
         /* TODO : to be done for write support
@@ -193,17 +193,20 @@
 
 	block = ufs_fragstoblks (fragment);
 	blockoff = ufs_fragnum (fragment);
-	p = ufsi->i_u1.i_data + block;
+	p = ufs_get_direct_data_ptr(uspi, ufsi, block);
+
 	goal = 0;
 
 repeat:
-	tmp = fs32_to_cpu(sb, *p);
+	tmp = ufs_data_ptr_to_cpu(sb, p);
+
 	lastfrag = ufsi->i_lastfrag;
 	if (tmp && fragment < lastfrag) {
 		if (!phys) {
 			result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
-			if (tmp == fs32_to_cpu(sb, *p)) {
-				UFSD("EXIT, result %u\n", tmp + blockoff);
+			if (tmp == ufs_data_ptr_to_cpu(sb, p)) {
+				UFSD("EXIT, result %llu\n",
+				     (unsigned long long)tmp + blockoff);
 				return result;
 			}
 			brelse (result);
@@ -224,10 +227,11 @@
 		 * We must reallocate last allocated block
 		 */
 		if (lastblockoff) {
-			p2 = ufsi->i_u1.i_data + lastblock;
-			tmp = ufs_new_fragments (inode, p2, lastfrag, 
-						 fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff,
-						 err, locked_page);
+			p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock);
+			tmp = ufs_new_fragments(inode, p2, lastfrag,
+						ufs_data_ptr_to_cpu(sb, p2),
+						uspi->s_fpb - lastblockoff,
+						err, locked_page);
 			if (!tmp) {
 				if (lastfrag != ufsi->i_lastfrag)
 					goto repeat;
@@ -237,27 +241,31 @@
 			lastfrag = ufsi->i_lastfrag;
 			
 		}
-		tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]);
+		tmp = ufs_data_ptr_to_cpu(sb,
+					 ufs_get_direct_data_ptr(uspi, ufsi,
+								 lastblock));
 		if (tmp)
 			goal = tmp + uspi->s_fpb;
 		tmp = ufs_new_fragments (inode, p, fragment - blockoff, 
 					 goal, required + blockoff,
 					 err,
 					 phys != NULL ? locked_page : NULL);
-	}
+	} else if (lastblock == block) {
 	/*
 	 * We will extend last allocated block
 	 */
-	else if (lastblock == block) {
-		tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff),
-					fs32_to_cpu(sb, *p), required +  (blockoff - lastblockoff),
+		tmp = ufs_new_fragments(inode, p, fragment -
+					(blockoff - lastblockoff),
+					ufs_data_ptr_to_cpu(sb, p),
+					required +  (blockoff - lastblockoff),
 					err, phys != NULL ? locked_page : NULL);
 	} else /* (lastblock > block) */ {
 	/*
 	 * We will allocate new block before last allocated block
 	 */
 		if (block) {
-			tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[block-1]);
+			tmp = ufs_data_ptr_to_cpu(sb,
+						 ufs_get_direct_data_ptr(uspi, ufsi, block - 1));
 			if (tmp)
 				goal = tmp + uspi->s_fpb;
 		}
@@ -266,7 +274,7 @@
 					phys != NULL ? locked_page : NULL);
 	}
 	if (!tmp) {
-		if ((!blockoff && *p) || 
+		if ((!blockoff && ufs_data_ptr_to_cpu(sb, p)) ||
 		    (blockoff && lastfrag != ufsi->i_lastfrag))
 			goto repeat;
 		*err = -ENOSPC;
@@ -286,7 +294,7 @@
 	if (IS_SYNC(inode))
 		ufs_sync_inode (inode);
 	mark_inode_dirty(inode);
-	UFSD("EXIT, result %u\n", tmp + blockoff);
+	UFSD("EXIT, result %llu\n", (unsigned long long)tmp + blockoff);
 	return result;
 
      /* This part : To be implemented ....
@@ -320,20 +328,22 @@
  */
 static struct buffer_head *
 ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
-		  unsigned int fragment, sector_t new_fragment, int *err,
+		  u64 fragment, sector_t new_fragment, int *err,
 		  long *phys, int *new, struct page *locked_page)
 {
 	struct super_block *sb = inode->i_sb;
 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	struct buffer_head * result;
-	unsigned tmp, goal, block, blockoff;
-	__fs32 * p;
+	unsigned blockoff;
+	u64 tmp, goal, block;
+	void *p;
 
 	block = ufs_fragstoblks (fragment);
 	blockoff = ufs_fragnum (fragment);
 
-	UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, metadata %d\n",
-	     inode->i_ino, fragment, (unsigned long long)new_fragment, !phys);
+	UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, metadata %d\n",
+	     inode->i_ino, (unsigned long long)fragment,
+	     (unsigned long long)new_fragment, !phys);
 
 	result = NULL;
 	if (!bh)
@@ -344,14 +354,16 @@
 		if (!buffer_uptodate(bh))
 			goto out;
 	}
-
-	p = (__fs32 *) bh->b_data + block;
+	if (uspi->fs_magic == UFS2_MAGIC)
+		p = (__fs64 *)bh->b_data + block;
+	else
+		p = (__fs32 *)bh->b_data + block;
 repeat:
-	tmp = fs32_to_cpu(sb, *p);
+	tmp = ufs_data_ptr_to_cpu(sb, p);
 	if (tmp) {
 		if (!phys) {
 			result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
-			if (tmp == fs32_to_cpu(sb, *p))
+			if (tmp == ufs_data_ptr_to_cpu(sb, p))
 				goto out;
 			brelse (result);
 			goto repeat;
@@ -361,14 +373,16 @@
 		}
 	}
 
-	if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1])))
+	if (block && (uspi->fs_magic == UFS2_MAGIC ?
+		      (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[block-1])) :
+		      (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[block-1]))))
 		goal = tmp + uspi->s_fpb;
 	else
 		goal = bh->b_blocknr + uspi->s_fpb;
 	tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal,
 				uspi->s_fpb, err, locked_page);
 	if (!tmp) {
-		if (fs32_to_cpu(sb, *p))
+		if (ufs_data_ptr_to_cpu(sb, p))
 			goto repeat;
 		goto out;
 	}		
@@ -386,7 +400,7 @@
 		sync_dirty_buffer(bh);
 	inode->i_ctime = CURRENT_TIME_SEC;
 	mark_inode_dirty(inode);
-	UFSD("result %u\n", tmp + blockoff);
+	UFSD("result %llu\n", (unsigned long long)tmp + blockoff);
 out:
 	brelse (bh);
 	UFSD("EXIT\n");
@@ -616,8 +630,8 @@
 	inode->i_atime.tv_nsec = 0;
 	inode->i_ctime.tv_nsec = 0;
 	inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks);
+	inode->i_generation = fs32_to_cpu(sb, ufs_inode->ui_gen);
 	ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags);
-	ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen);
 	ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
 	ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
 
@@ -661,8 +675,8 @@
 	inode->i_atime.tv_nsec = 0;
 	inode->i_ctime.tv_nsec = 0;
 	inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks);
+	inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen);
 	ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags);
-	ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen);
 	/*
 	ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
 	ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
@@ -731,34 +745,11 @@
 	make_bad_inode(inode);
 }
 
-static int ufs_update_inode(struct inode * inode, int do_sync)
+static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode)
 {
-	struct ufs_inode_info *ufsi = UFS_I(inode);
-	struct super_block * sb;
-	struct ufs_sb_private_info * uspi;
-	struct buffer_head * bh;
-	struct ufs_inode * ufs_inode;
-	unsigned i;
-	unsigned flags;
-
-	UFSD("ENTER, ino %lu\n", inode->i_ino);
-
-	sb = inode->i_sb;
-	uspi = UFS_SB(sb)->s_uspi;
-	flags = UFS_SB(sb)->s_flags;
-
-	if (inode->i_ino < UFS_ROOTINO || 
-	    inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
-		ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
-		return -1;
-	}
-
-	bh = sb_bread(sb, ufs_inotofsba(inode->i_ino));
-	if (!bh) {
-		ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
-		return -1;
-	}
-	ufs_inode = (struct ufs_inode *) (bh->b_data + ufs_inotofsbo(inode->i_ino) * sizeof(struct ufs_inode));
+	struct super_block *sb = inode->i_sb;
+ 	struct ufs_inode_info *ufsi = UFS_I(inode);
+ 	unsigned i;
 
 	ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
 	ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
@@ -775,9 +766,9 @@
 	ufs_inode->ui_mtime.tv_usec = 0;
 	ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks);
 	ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
-	ufs_inode->ui_gen = cpu_to_fs32(sb, ufsi->i_gen);
+	ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);
 
-	if ((flags & UFS_UID_MASK) == UFS_UID_EFT) {
+	if ((UFS_SB(sb)->s_flags & UFS_UID_MASK) == UFS_UID_EFT) {
 		ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow);
 		ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag);
 	}
@@ -796,6 +787,78 @@
 
 	if (!inode->i_nlink)
 		memset (ufs_inode, 0, sizeof(struct ufs_inode));
+}
+
+static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode)
+{
+	struct super_block *sb = inode->i_sb;
+ 	struct ufs_inode_info *ufsi = UFS_I(inode);
+ 	unsigned i;
+
+	UFSD("ENTER\n");
+	ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
+	ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
+
+	ufs_inode->ui_uid = cpu_to_fs32(sb, inode->i_uid);
+	ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid);
+
+	ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
+	ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec);
+	ufs_inode->ui_atime.tv_usec = 0;
+	ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec);
+	ufs_inode->ui_ctime.tv_usec = 0;
+	ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec);
+	ufs_inode->ui_mtime.tv_usec = 0;
+
+	ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks);
+	ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
+	ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);
+
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+		/* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */
+		ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.u2_i_data[0];
+	} else if (inode->i_blocks) {
+		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
+			ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.u2_i_data[i];
+	} else {
+		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
+			ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i];
+ 	}
+
+	if (!inode->i_nlink)
+		memset (ufs_inode, 0, sizeof(struct ufs2_inode));
+	UFSD("EXIT\n");
+}
+
+static int ufs_update_inode(struct inode * inode, int do_sync)
+{
+	struct super_block *sb = inode->i_sb;
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+	struct buffer_head * bh;
+
+	UFSD("ENTER, ino %lu\n", inode->i_ino);
+
+	if (inode->i_ino < UFS_ROOTINO ||
+	    inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
+		ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
+		return -1;
+	}
+
+	bh = sb_bread(sb, ufs_inotofsba(inode->i_ino));
+	if (!bh) {
+		ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
+		return -1;
+	}
+	if (uspi->fs_magic == UFS2_MAGIC) {
+		struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data;
+
+		ufs2_update_inode(inode,
+				  ufs2_inode + ufs_inotofsbo(inode->i_ino));
+	} else {
+		struct ufs_inode *ufs_inode = (struct ufs_inode *) bh->b_data;
+
+		ufs1_update_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino));
+	}
 		
 	mark_buffer_dirty(bh);
 	if (do_sync)
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index e84c0ec..a059ccd 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -355,7 +355,7 @@
 	return err;
 }
 
-struct inode_operations ufs_dir_inode_operations = {
+const struct inode_operations ufs_dir_inode_operations = {
 	.create		= ufs_create,
 	.lookup		= ufs_lookup,
 	.link		= ufs_link,
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 8a8e938..b5a6461 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -61,6 +61,8 @@
  * UFS2 (of FreeBSD 5.x) support added by
  * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004
  *
+ * UFS2 write support added by
+ * Evgeniy Dushistov <dushistov@mail.ru>, 2007
  */
 
 
@@ -93,14 +95,16 @@
 /*
  * Print contents of ufs_super_block, useful for debugging
  */
-static void ufs_print_super_stuff(struct super_block *sb, unsigned flags,
+static void ufs_print_super_stuff(struct super_block *sb,
 				  struct ufs_super_block_first *usb1,
 				  struct ufs_super_block_second *usb2,
 				  struct ufs_super_block_third *usb3)
 {
+	u32 magic = fs32_to_cpu(sb, usb3->fs_magic);
+
 	printk("ufs_print_super_stuff\n");
-	printk("  magic:     0x%x\n", fs32_to_cpu(sb, usb3->fs_magic));
-	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+	printk("  magic:     0x%x\n", magic);
+	if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) {
 		printk("  fs_size:   %llu\n", (unsigned long long)
 		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size));
 		printk("  fs_dsize:  %llu\n", (unsigned long long)
@@ -117,6 +121,12 @@
 		printk("  cs_nbfree(No of free blocks):  %llu\n",
 		       (unsigned long long)
 		       fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree));
+		printk(KERN_INFO"  cs_nifree(Num of free inodes): %llu\n",
+		       (unsigned long long)
+		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree));
+		printk(KERN_INFO"  cs_nffree(Num of free frags): %llu\n",
+		       (unsigned long long)
+		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree));
 	} else {
 		printk(" sblkno:      %u\n", fs32_to_cpu(sb, usb1->fs_sblkno));
 		printk(" cblkno:      %u\n", fs32_to_cpu(sb, usb1->fs_cblkno));
@@ -199,11 +209,11 @@
 	printk("\n");
 }
 #else
-#  define ufs_print_super_stuff(sb, flags, usb1, usb2, usb3) /**/
+#  define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/
 #  define ufs_print_cylinder_stuff(sb, cg) /**/
 #endif /* CONFIG_UFS_DEBUG */
 
-static struct super_operations ufs_super_ops;
+static const struct super_operations ufs_super_ops;
 
 static char error_buf[1024];
 
@@ -422,7 +432,6 @@
 {
 	struct ufs_sb_info *sbi = UFS_SB(sb);
 	struct ufs_sb_private_info *uspi = sbi->s_uspi;
-	unsigned flags = sbi->s_flags;
 	struct ufs_buffer_head * ubh;
 	unsigned char * base, * space;
 	unsigned size, blks, i;
@@ -446,11 +455,7 @@
 		if (i + uspi->s_fpb > blks)
 			size = (blks - i) * uspi->s_fsize;
 
-		if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 
-			ubh = ubh_bread(sb,
-				fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr) + i, size);
-		else 
-			ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
+		ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
 		
 		if (!ubh)
 			goto failed;
@@ -545,6 +550,7 @@
 			cpu_to_fs32(sb, uspi->cs_total.cs_nffree);
 	}
 	ubh_mark_buffer_dirty(USPI_UBH(uspi));
+	ufs_print_super_stuff(sb, usb1, usb2, usb3);
 	UFSD("EXIT\n");
 }
 
@@ -572,7 +578,9 @@
 		size = uspi->s_bsize;
 		if (i + uspi->s_fpb > blks)
 			size = (blks - i) * uspi->s_fsize;
+
 		ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
+
 		ubh_memcpyubh (ubh, space, size);
 		space += size;
 		ubh_mark_buffer_uptodate (ubh, 1);
@@ -649,7 +657,7 @@
 		kmalloc (sizeof(struct ufs_sb_private_info), GFP_KERNEL);
 	if (!uspi)
 		goto failed;
-
+	uspi->s_dirblksize = UFS_SECTOR_SIZE;
 	super_block_offset=UFS_SBLOCK;
 
 	/* Keep 2Gig file limit. Some UFS variants need to override 
@@ -674,10 +682,6 @@
 		uspi->s_sbsize = super_block_size = 1536;
 		uspi->s_sbbase =  0;
 		flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
-		if (!(sb->s_flags & MS_RDONLY)) {
-			printk(KERN_INFO "ufstype=ufs2 is supported read-only\n");
-			sb->s_flags |= MS_RDONLY;
- 		}
 		break;
 		
 	case UFS_MOUNT_UFSTYPE_SUN:
@@ -718,6 +722,7 @@
 		break;
 	
 	case UFS_MOUNT_UFSTYPE_NEXTSTEP:
+		/*TODO: check may be we need set special dir block size?*/
 		UFSD("ufstype=nextstep\n");
 		uspi->s_fsize = block_size = 1024;
 		uspi->s_fmask = ~(1024 - 1);
@@ -733,6 +738,7 @@
 		break;
 	
 	case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD:
+		/*TODO: check may be we need set special dir block size?*/
 		UFSD("ufstype=nextstep-cd\n");
 		uspi->s_fsize = block_size = 2048;
 		uspi->s_fmask = ~(2048 - 1);
@@ -754,6 +760,7 @@
 		uspi->s_fshift = 10;
 		uspi->s_sbsize = super_block_size = 2048;
 		uspi->s_sbbase = 0;
+		uspi->s_dirblksize = 1024;
 		flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
 		if (!(sb->s_flags & MS_RDONLY)) {
 			if (!silent)
@@ -887,7 +894,7 @@
 	}
 
 
-	ufs_print_super_stuff(sb, flags, usb1, usb2, usb3);
+	ufs_print_super_stuff(sb, usb1, usb2, usb3);
 
 	/*
 	 * Check, if file system was correctly unmounted.
@@ -970,7 +977,12 @@
 	uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3);
 	uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave);
 	uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew);
-	uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr);
+
+	if (uspi->fs_magic == UFS2_MAGIC)
+		uspi->s_csaddr = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr);
+	else
+		uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr);
+
 	uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize);
 	uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize);
 	uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak);
@@ -1057,7 +1069,6 @@
 	unsigned flags;
 
 	lock_kernel();
-
 	UFSD("ENTER\n");
 	flags = UFS_SB(sb)->s_flags;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -1153,7 +1164,8 @@
 #else
 		if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 
 		    ufstype != UFS_MOUNT_UFSTYPE_44BSD &&
-		    ufstype != UFS_MOUNT_UFSTYPE_SUNx86) {
+		    ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
+		    ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
 			printk("this ufstype is read-only supported\n");
 			return -EINVAL;
 		}
@@ -1252,7 +1264,7 @@
 static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t);
 #endif
 
-static struct super_operations ufs_super_ops = {
+static const struct super_operations ufs_super_ops = {
 	.alloc_inode	= ufs_alloc_inode,
 	.destroy_inode	= ufs_destroy_inode,
 	.read_inode	= ufs_read_inode,
diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c
index 337512e..d8549f8 100644
--- a/fs/ufs/symlink.c
+++ b/fs/ufs/symlink.c
@@ -36,7 +36,7 @@
 	return NULL;
 }
 
-struct inode_operations ufs_fast_symlink_inode_operations = {
+const struct inode_operations ufs_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= ufs_follow_link,
 };
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index 0437b0a..749581f 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -30,8 +30,8 @@
  */
 
 /*
- * Modified to avoid infinite loop on 2006 by
- * Evgeniy Dushistov <dushistov@mail.ru>
+ * Adoptation to use page cache and UFS2 write support by
+ * Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007
  */
 
 #include <linux/errno.h>
@@ -63,13 +63,13 @@
 #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
 
 
-static int ufs_trunc_direct (struct inode * inode)
+static int ufs_trunc_direct(struct inode *inode)
 {
 	struct ufs_inode_info *ufsi = UFS_I(inode);
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	__fs32 * p;
-	unsigned frag1, frag2, frag3, frag4, block1, block2;
+	void *p;
+	u64 frag1, frag2, frag3, frag4, block1, block2;
 	unsigned frag_to_free, free_count;
 	unsigned i, tmp;
 	int retry;
@@ -91,13 +91,16 @@
 	if (frag2 > frag3) {
 		frag2 = frag4;
 		frag3 = frag4 = 0;
-	}
-	else if (frag2 < frag3) {
+	} else if (frag2 < frag3) {
 		block1 = ufs_fragstoblks (frag2);
 		block2 = ufs_fragstoblks (frag3);
 	}
 
-	UFSD("frag1 %u, frag2 %u, block1 %u, block2 %u, frag3 %u, frag4 %u\n", frag1, frag2, block1, block2, frag3, frag4);
+	UFSD("frag1 %llu, frag2 %llu, block1 %llu, block2 %llu, frag3 %llu,"
+	     " frag4 %llu\n",
+	     (unsigned long long)frag1, (unsigned long long)frag2,
+	     (unsigned long long)block1, (unsigned long long)block2,
+	     (unsigned long long)frag3, (unsigned long long)frag4);
 
 	if (frag1 >= frag2)
 		goto next1;		
@@ -105,8 +108,8 @@
 	/*
 	 * Free first free fragments
 	 */
-	p = ufsi->i_u1.i_data + ufs_fragstoblks (frag1);
-	tmp = fs32_to_cpu(sb, *p);
+	p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1));
+	tmp = ufs_data_ptr_to_cpu(sb, p);
 	if (!tmp )
 		ufs_panic (sb, "ufs_trunc_direct", "internal error");
 	frag2 -= frag1;
@@ -121,12 +124,11 @@
 	 * Free whole blocks
 	 */
 	for (i = block1 ; i < block2; i++) {
-		p = ufsi->i_u1.i_data + i;
-		tmp = fs32_to_cpu(sb, *p);
+		p = ufs_get_direct_data_ptr(uspi, ufsi, i);
+		tmp = ufs_data_ptr_to_cpu(sb, p);
 		if (!tmp)
 			continue;
-
-		*p = 0;
+		ufs_data_ptr_clear(uspi, p);
 
 		if (free_count == 0) {
 			frag_to_free = tmp;
@@ -150,13 +152,12 @@
 	/*
 	 * Free last free fragments
 	 */
-	p = ufsi->i_u1.i_data + ufs_fragstoblks (frag3);
-	tmp = fs32_to_cpu(sb, *p);
+	p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3));
+	tmp = ufs_data_ptr_to_cpu(sb, p);
 	if (!tmp )
 		ufs_panic(sb, "ufs_truncate_direct", "internal error");
 	frag4 = ufs_fragnum (frag4);
-
-	*p = 0;
+	ufs_data_ptr_clear(uspi, p);
 
 	ufs_free_fragments (inode, tmp, frag4);
 	mark_inode_dirty(inode);
@@ -167,17 +168,20 @@
 }
 
 
-static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
+static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * ind_ubh;
-	__fs32 * ind;
-	unsigned indirect_block, i, tmp;
-	unsigned frag_to_free, free_count;
+	void *ind;
+	u64 tmp, indirect_block, i, frag_to_free;
+	unsigned free_count;
 	int retry;
 
-	UFSD("ENTER\n");
+	UFSD("ENTER: ino %lu, offset %llu, p: %p\n",
+	     inode->i_ino, (unsigned long long)offset, p);
+
+	BUG_ON(!p);
 		
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -186,27 +190,27 @@
 	free_count = 0;
 	retry = 0;
 	
-	tmp = fs32_to_cpu(sb, *p);
+	tmp = ufs_data_ptr_to_cpu(sb, p);
 	if (!tmp)
 		return 0;
 	ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize);
-	if (tmp != fs32_to_cpu(sb, *p)) {
+	if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 		ubh_brelse (ind_ubh);
 		return 1;
 	}
 	if (!ind_ubh) {
-		*p = 0;
+		ufs_data_ptr_clear(uspi, p);
 		return 0;
 	}
 
 	indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0;
 	for (i = indirect_block; i < uspi->s_apb; i++) {
-		ind = ubh_get_addr32 (ind_ubh, i);
-		tmp = fs32_to_cpu(sb, *ind);
+		ind = ubh_get_data_ptr(uspi, ind_ubh, i);
+		tmp = ufs_data_ptr_to_cpu(sb, ind);
 		if (!tmp)
 			continue;
 
-		*ind = 0;
+		ufs_data_ptr_clear(uspi, ind);
 		ubh_mark_buffer_dirty(ind_ubh);
 		if (free_count == 0) {
 			frag_to_free = tmp;
@@ -226,11 +230,12 @@
 		ufs_free_blocks (inode, frag_to_free, free_count);
 	}
 	for (i = 0; i < uspi->s_apb; i++)
-		if (*ubh_get_addr32(ind_ubh,i))
+		if (!ufs_is_data_ptr_zero(uspi,
+					  ubh_get_data_ptr(uspi, ind_ubh, i)))
 			break;
 	if (i >= uspi->s_apb) {
-		tmp = fs32_to_cpu(sb, *p);
-		*p = 0;
+		tmp = ufs_data_ptr_to_cpu(sb, p);
+		ufs_data_ptr_clear(uspi, p);
 
 		ufs_free_blocks (inode, tmp, uspi->s_fpb);
 		mark_inode_dirty(inode);
@@ -248,13 +253,13 @@
 	return retry;
 }
 
-static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
+static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	struct ufs_buffer_head * dind_bh;
-	unsigned i, tmp, dindirect_block;
-	__fs32 * dind;
+	struct ufs_buffer_head *dind_bh;
+	u64 i, tmp, dindirect_block;
+	void *dind;
 	int retry = 0;
 	
 	UFSD("ENTER\n");
@@ -266,22 +271,22 @@
 		? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0;
 	retry = 0;
 	
-	tmp = fs32_to_cpu(sb, *p);
+	tmp = ufs_data_ptr_to_cpu(sb, p);
 	if (!tmp)
 		return 0;
 	dind_bh = ubh_bread(sb, tmp, uspi->s_bsize);
-	if (tmp != fs32_to_cpu(sb, *p)) {
+	if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 		ubh_brelse (dind_bh);
 		return 1;
 	}
 	if (!dind_bh) {
-		*p = 0;
+		ufs_data_ptr_clear(uspi, p);
 		return 0;
 	}
 
 	for (i = dindirect_block ; i < uspi->s_apb ; i++) {
-		dind = ubh_get_addr32 (dind_bh, i);
-		tmp = fs32_to_cpu(sb, *dind);
+		dind = ubh_get_data_ptr(uspi, dind_bh, i);
+		tmp = ufs_data_ptr_to_cpu(sb, dind);
 		if (!tmp)
 			continue;
 		retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind);
@@ -289,11 +294,12 @@
 	}
 
 	for (i = 0; i < uspi->s_apb; i++)
-		if (*ubh_get_addr32 (dind_bh, i))
+		if (!ufs_is_data_ptr_zero(uspi,
+					  ubh_get_data_ptr(uspi, dind_bh, i)))
 			break;
 	if (i >= uspi->s_apb) {
-		tmp = fs32_to_cpu(sb, *p);
-		*p = 0;
+		tmp = ufs_data_ptr_to_cpu(sb, p);
+		ufs_data_ptr_clear(uspi, p);
 
 		ufs_free_blocks(inode, tmp, uspi->s_fpb);
 		mark_inode_dirty(inode);
@@ -311,34 +317,33 @@
 	return retry;
 }
 
-static int ufs_trunc_tindirect (struct inode * inode)
+static int ufs_trunc_tindirect(struct inode *inode)
 {
+	struct super_block *sb = inode->i_sb;
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	struct ufs_inode_info *ufsi = UFS_I(inode);
-	struct super_block * sb;
-	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * tind_bh;
-	unsigned tindirect_block, tmp, i;
-	__fs32 * tind, * p;
+	u64 tindirect_block, tmp, i;
+	void *tind, *p;
 	int retry;
 	
 	UFSD("ENTER\n");
 
-	sb = inode->i_sb;
-	uspi = UFS_SB(sb)->s_uspi;
 	retry = 0;
 	
 	tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb))
 		? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0;
-	p = ufsi->i_u1.i_data + UFS_TIND_BLOCK;
-	if (!(tmp = fs32_to_cpu(sb, *p)))
+
+	p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK);
+	if (!(tmp = ufs_data_ptr_to_cpu(sb, p)))
 		return 0;
 	tind_bh = ubh_bread (sb, tmp, uspi->s_bsize);
-	if (tmp != fs32_to_cpu(sb, *p)) {
+	if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 		ubh_brelse (tind_bh);
 		return 1;
 	}
 	if (!tind_bh) {
-		*p = 0;
+		ufs_data_ptr_clear(uspi, p);
 		return 0;
 	}
 
@@ -349,11 +354,12 @@
 		ubh_mark_buffer_dirty(tind_bh);
 	}
 	for (i = 0; i < uspi->s_apb; i++)
-		if (*ubh_get_addr32 (tind_bh, i))
+		if (!ufs_is_data_ptr_zero(uspi,
+					  ubh_get_data_ptr(uspi, tind_bh, i)))
 			break;
 	if (i >= uspi->s_apb) {
-		tmp = fs32_to_cpu(sb, *p);
-		*p = 0;
+		tmp = ufs_data_ptr_to_cpu(sb, p);
+		ufs_data_ptr_clear(uspi, p);
 
 		ufs_free_blocks(inode, tmp, uspi->s_fpb);
 		mark_inode_dirty(inode);
@@ -375,7 +381,8 @@
 	int err = 0;
 	struct address_space *mapping = inode->i_mapping;
 	struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi;
-	unsigned lastfrag, i, end;
+	unsigned i, end;
+	sector_t lastfrag;
 	struct page *lastpage;
 	struct buffer_head *bh;
 
@@ -430,7 +437,9 @@
 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	int retry, err = 0;
 	
-	UFSD("ENTER\n");
+	UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n",
+	     inode->i_ino, (unsigned long long)i_size_read(inode),
+	     (unsigned long long)old_i_size);
 
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 	      S_ISLNK(inode->i_mode)))
@@ -450,10 +459,12 @@
 	lock_kernel();
 	while (1) {
 		retry = ufs_trunc_direct(inode);
-		retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK,
-			(__fs32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]);
-		retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb,
-			(__fs32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]);
+		retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK,
+					    ufs_get_direct_data_ptr(uspi, ufsi,
+								    UFS_IND_BLOCK));
+		retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb,
+					     ufs_get_direct_data_ptr(uspi, ufsi,
+								     UFS_DIND_BLOCK));
 		retry |= ufs_trunc_tindirect (inode);
 		if (!retry)
 			break;
@@ -502,6 +513,6 @@
 	return inode_setattr(inode, attr);
 }
 
-struct inode_operations ufs_file_inode_operations = {
+const struct inode_operations ufs_file_inode_operations = {
 	.setattr = ufs_setattr,
 };
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index 7dd12bb..06d3448 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -305,8 +305,22 @@
 	(((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
 	((begin) & ((uspi->s_fsize>>2) - 1)))
 
+#define ubh_get_addr64(ubh,begin) \
+	(((__fs64*)((ubh)->bh[(begin) >> (uspi->s_fshift-3)]->b_data)) + \
+	((begin) & ((uspi->s_fsize>>3) - 1)))
+
 #define ubh_get_addr ubh_get_addr8
 
+static inline void *ubh_get_data_ptr(struct ufs_sb_private_info *uspi,
+				     struct ufs_buffer_head *ubh,
+				     u64 blk)
+{
+	if (uspi->fs_magic == UFS2_MAGIC)
+		return ubh_get_addr64(ubh, blk);
+	else
+		return ubh_get_addr32(ubh, blk);
+}
+
 #define ubh_blkmap(ubh,begin,bit) \
 	((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb)))
 
@@ -507,3 +521,46 @@
 	if (fragsize > 0 && fragsize < uspi->s_fpb)
 		fs32_add(sb, &fraglist[fragsize], cnt);
 }
+
+static inline void *ufs_get_direct_data_ptr(struct ufs_sb_private_info *uspi,
+					    struct ufs_inode_info *ufsi,
+					    unsigned blk)
+{
+	BUG_ON(blk > UFS_TIND_BLOCK);
+	return uspi->fs_magic == UFS2_MAGIC ?
+		(void *)&ufsi->i_u1.u2_i_data[blk] :
+		(void *)&ufsi->i_u1.i_data[blk];
+}
+
+static inline u64 ufs_data_ptr_to_cpu(struct super_block *sb, void *p)
+{
+	return UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC ?
+		fs64_to_cpu(sb, *(__fs64 *)p) :
+		fs32_to_cpu(sb, *(__fs32 *)p);
+}
+
+static inline void ufs_cpu_to_data_ptr(struct super_block *sb, void *p, u64 val)
+{
+	if (UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC)
+		*(__fs64 *)p = cpu_to_fs64(sb, val);
+	else
+		*(__fs32 *)p = cpu_to_fs32(sb, val);
+}
+
+static inline void ufs_data_ptr_clear(struct ufs_sb_private_info *uspi,
+				      void *p)
+{
+	if (uspi->fs_magic == UFS2_MAGIC)
+		*(__fs64 *)p = 0;
+	else
+		*(__fs32 *)p = 0;
+}
+
+static inline int ufs_is_data_ptr_zero(struct ufs_sb_private_info *uspi,
+				       void *p)
+{
+	if (uspi->fs_magic == UFS2_MAGIC)
+		return *(__fs64 *)p == 0;
+	else
+		return *(__fs32 *)p == 0;
+}
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 0afd745..c28add2 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -996,7 +996,7 @@
 	goto out;
 }
 
-static struct inode_operations vfat_dir_inode_operations = {
+static const struct inode_operations vfat_dir_inode_operations = {
 	.create		= vfat_create,
 	.lookup		= vfat_lookup,
 	.unlink		= vfat_unlink,
diff --git a/fs/xattr_acl.c b/fs/xattr_acl.c
index 789a255..c6ad7c7 100644
--- a/fs/xattr_acl.c
+++ b/fs/xattr_acl.c
@@ -6,7 +6,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/posix_acl_xattr.h>
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c
index 004baf6..ed2b16d 100644
--- a/fs/xfs/linux-2.6/kmem.c
+++ b/fs/xfs/linux-2.6/kmem.c
@@ -15,7 +15,6 @@
  * along with this program; if not, write the Free Software Foundation,
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h
index 32e1ce0..af168a1 100644
--- a/fs/xfs/linux-2.6/mrlock.h
+++ b/fs/xfs/linux-2.6/mrlock.h
@@ -31,15 +31,13 @@
 	do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0)
 #define mrlock_init(mrp, t,n,s)	mrinit(mrp, n)
 #define mrfree(mrp)		do { } while (0)
-#define mraccess(mrp)		mraccessf(mrp, 0)
-#define mrupdate(mrp)		mrupdatef(mrp, 0)
 
-static inline void mraccessf(mrlock_t *mrp, int flags)
+static inline void mraccess(mrlock_t *mrp)
 {
 	down_read(&mrp->mr_lock);
 }
 
-static inline void mrupdatef(mrlock_t *mrp, int flags)
+static inline void mrupdate(mrlock_t *mrp)
 {
 	down_write(&mrp->mr_lock);
 	mrp->mr_writer = 1;
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 7b54461..143ffc8 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -56,8 +56,6 @@
 	do {
 		if (buffer_uptodate(bh) && !buffer_mapped(bh))
 			(*unmapped) = 1;
-		else if (buffer_unwritten(bh) && !buffer_delay(bh))
-			clear_buffer_unwritten(bh);
 		else if (buffer_unwritten(bh))
 			(*unwritten) = 1;
 		else if (buffer_delay(bh))
@@ -249,7 +247,7 @@
 	return -error;
 }
 
-STATIC inline int
+STATIC_INLINE int
 xfs_iomap_valid(
 	xfs_iomap_t		*iomapp,
 	loff_t			offset)
@@ -1272,7 +1270,6 @@
 			if (direct)
 				bh_result->b_private = inode;
 			set_buffer_unwritten(bh_result);
-			set_buffer_delay(bh_result);
 		}
 	}
 
@@ -1283,13 +1280,18 @@
 	bh_result->b_bdev = iomap.iomap_target->bt_bdev;
 
 	/*
-	 * If we previously allocated a block out beyond eof and we are
-	 * now coming back to use it then we will need to flag it as new
-	 * even if it has a disk address.
+	 * If we previously allocated a block out beyond eof and we are now
+	 * coming back to use it then we will need to flag it as new even if it
+	 * has a disk address.
+	 *
+	 * With sub-block writes into unwritten extents we also need to mark
+	 * the buffer as new so that the unwritten parts of the buffer gets
+	 * correctly zeroed.
 	 */
 	if (create &&
 	    ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) ||
-	     (offset >= i_size_read(inode)) || (iomap.iomap_flags & IOMAP_NEW)))
+	     (offset >= i_size_read(inode)) ||
+	     (iomap.iomap_flags & (IOMAP_NEW|IOMAP_UNWRITTEN))))
 		set_buffer_new(bh_result);
 
 	if (iomap.iomap_flags & IOMAP_DELAY) {
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 4fb01ff..e2bea6a 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -34,13 +34,13 @@
 #include <linux/backing-dev.h>
 #include <linux/freezer.h>
 
-STATIC kmem_zone_t *xfs_buf_zone;
-STATIC kmem_shaker_t xfs_buf_shake;
+static kmem_zone_t *xfs_buf_zone;
+static kmem_shaker_t xfs_buf_shake;
 STATIC int xfsbufd(void *);
 STATIC int xfsbufd_wakeup(int, gfp_t);
 STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
 
-STATIC struct workqueue_struct *xfslogd_workqueue;
+static struct workqueue_struct *xfslogd_workqueue;
 struct workqueue_struct *xfsdatad_workqueue;
 
 #ifdef XFS_BUF_TRACE
@@ -139,7 +139,7 @@
 	return mask;
 }
 
-STATIC inline void
+STATIC_INLINE void
 set_page_region(
 	struct page	*page,
 	size_t		offset,
@@ -151,7 +151,7 @@
 		SetPageUptodate(page);
 }
 
-STATIC inline int
+STATIC_INLINE int
 test_page_region(
 	struct page	*page,
 	size_t		offset,
@@ -171,9 +171,9 @@
 	struct a_list	*next;
 } a_list_t;
 
-STATIC a_list_t		*as_free_head;
-STATIC int		as_list_len;
-STATIC DEFINE_SPINLOCK(as_lock);
+static a_list_t		*as_free_head;
+static int		as_list_len;
+static DEFINE_SPINLOCK(as_lock);
 
 /*
  *	Try to batch vunmaps because they are costly.
@@ -1085,7 +1085,7 @@
 	return status;
 }
 
-STATIC __inline__ int
+STATIC_INLINE int
 _xfs_buf_iolocked(
 	xfs_buf_t		*bp)
 {
@@ -1095,7 +1095,7 @@
 	return 0;
 }
 
-STATIC __inline__ void
+STATIC_INLINE void
 _xfs_buf_ioend(
 	xfs_buf_t		*bp,
 	int			schedule)
@@ -1426,8 +1426,8 @@
 /*
  *	buftarg list for delwrite queue processing
  */
-STATIC LIST_HEAD(xfs_buftarg_list);
-STATIC DEFINE_SPINLOCK(xfs_buftarg_lock);
+LIST_HEAD(xfs_buftarg_list);
+static DEFINE_SPINLOCK(xfs_buftarg_lock);
 
 STATIC void
 xfs_register_buftarg(
@@ -1679,21 +1679,60 @@
 	return 0;
 }
 
+/*
+ * Move as many buffers as specified to the supplied list
+ * idicating if we skipped any buffers to prevent deadlocks.
+ */
+STATIC int
+xfs_buf_delwri_split(
+	xfs_buftarg_t	*target,
+	struct list_head *list,
+	unsigned long	age)
+{
+	xfs_buf_t	*bp, *n;
+	struct list_head *dwq = &target->bt_delwrite_queue;
+	spinlock_t	*dwlk = &target->bt_delwrite_lock;
+	int		skipped = 0;
+	int		force;
+
+	force = test_and_clear_bit(XBT_FORCE_FLUSH, &target->bt_flags);
+	INIT_LIST_HEAD(list);
+	spin_lock(dwlk);
+	list_for_each_entry_safe(bp, n, dwq, b_list) {
+		XB_TRACE(bp, "walkq1", (long)xfs_buf_ispin(bp));
+		ASSERT(bp->b_flags & XBF_DELWRI);
+
+		if (!xfs_buf_ispin(bp) && !xfs_buf_cond_lock(bp)) {
+			if (!force &&
+			    time_before(jiffies, bp->b_queuetime + age)) {
+				xfs_buf_unlock(bp);
+				break;
+			}
+
+			bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|
+					 _XBF_RUN_QUEUES);
+			bp->b_flags |= XBF_WRITE;
+			list_move_tail(&bp->b_list, list);
+		} else
+			skipped++;
+	}
+	spin_unlock(dwlk);
+
+	return skipped;
+
+}
+
 STATIC int
 xfsbufd(
-	void			*data)
+	void		*data)
 {
-	struct list_head	tmp;
-	unsigned long		age;
-	xfs_buftarg_t		*target = (xfs_buftarg_t *)data;
-	xfs_buf_t		*bp, *n;
-	struct list_head	*dwq = &target->bt_delwrite_queue;
-	spinlock_t		*dwlk = &target->bt_delwrite_lock;
-	int			count;
+	struct list_head tmp;
+	xfs_buftarg_t	*target = (xfs_buftarg_t *)data;
+	int		count;
+	xfs_buf_t	*bp;
 
 	current->flags |= PF_MEMALLOC;
 
-	INIT_LIST_HEAD(&tmp);
 	do {
 		if (unlikely(freezing(current))) {
 			set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
@@ -1705,37 +1744,17 @@
 		schedule_timeout_interruptible(
 			xfs_buf_timer_centisecs * msecs_to_jiffies(10));
 
+		xfs_buf_delwri_split(target, &tmp,
+				xfs_buf_age_centisecs * msecs_to_jiffies(10));
+
 		count = 0;
-		age = xfs_buf_age_centisecs * msecs_to_jiffies(10);
-		spin_lock(dwlk);
-		list_for_each_entry_safe(bp, n, dwq, b_list) {
-			XB_TRACE(bp, "walkq1", (long)xfs_buf_ispin(bp));
-			ASSERT(bp->b_flags & XBF_DELWRI);
-
-			if (!xfs_buf_ispin(bp) && !xfs_buf_cond_lock(bp)) {
-				if (!test_bit(XBT_FORCE_FLUSH,
-						&target->bt_flags) &&
-				    time_before(jiffies,
-						bp->b_queuetime + age)) {
-					xfs_buf_unlock(bp);
-					break;
-				}
-
-				bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|
-						 _XBF_RUN_QUEUES);
-				bp->b_flags |= XBF_WRITE;
-				list_move_tail(&bp->b_list, &tmp);
-				count++;
-			}
-		}
-		spin_unlock(dwlk);
-
 		while (!list_empty(&tmp)) {
 			bp = list_entry(tmp.next, xfs_buf_t, b_list);
 			ASSERT(target == bp->b_target);
 
 			list_del_init(&bp->b_list);
 			xfs_buf_iostrategy(bp);
+			count++;
 		}
 
 		if (as_list_len > 0)
@@ -1743,7 +1762,6 @@
 		if (count)
 			blk_run_address_space(target->bt_mapping);
 
-		clear_bit(XBT_FORCE_FLUSH, &target->bt_flags);
 	} while (!kthread_should_stop());
 
 	return 0;
@@ -1756,40 +1774,24 @@
  */
 int
 xfs_flush_buftarg(
-	xfs_buftarg_t		*target,
-	int			wait)
+	xfs_buftarg_t	*target,
+	int		wait)
 {
-	struct list_head	tmp;
-	xfs_buf_t		*bp, *n;
-	int			pincount = 0;
-	struct list_head	*dwq = &target->bt_delwrite_queue;
-	spinlock_t		*dwlk = &target->bt_delwrite_lock;
+	struct list_head tmp;
+	xfs_buf_t	*bp, *n;
+	int		pincount = 0;
 
 	xfs_buf_runall_queues(xfsdatad_workqueue);
 	xfs_buf_runall_queues(xfslogd_workqueue);
 
-	INIT_LIST_HEAD(&tmp);
-	spin_lock(dwlk);
-	list_for_each_entry_safe(bp, n, dwq, b_list) {
-		ASSERT(bp->b_target == target);
-		ASSERT(bp->b_flags & (XBF_DELWRI | _XBF_DELWRI_Q));
-		XB_TRACE(bp, "walkq2", (long)xfs_buf_ispin(bp));
-		if (xfs_buf_ispin(bp)) {
-			pincount++;
-			continue;
-		}
-
-		list_move_tail(&bp->b_list, &tmp);
-	}
-	spin_unlock(dwlk);
+	set_bit(XBT_FORCE_FLUSH, &target->bt_flags);
+	pincount = xfs_buf_delwri_split(target, &tmp, 0);
 
 	/*
 	 * Dropped the delayed write list lock, now walk the temporary list
 	 */
 	list_for_each_entry_safe(bp, n, &tmp, b_list) {
-		xfs_buf_lock(bp);
-		bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|_XBF_RUN_QUEUES);
-		bp->b_flags |= XBF_WRITE;
+		ASSERT(target == bp->b_target);
 		if (wait)
 			bp->b_flags &= ~XBF_ASYNC;
 		else
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 9dd235c..9e8ef8f 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -69,8 +69,8 @@
 } xfs_buf_flags_t;
 
 typedef enum {
-	XBT_FORCE_SLEEP = (0 << 1),
-	XBT_FORCE_FLUSH = (1 << 1),
+	XBT_FORCE_SLEEP = 0,
+	XBT_FORCE_FLUSH = 1,
 } xfs_buftarg_flags_t;
 
 typedef struct xfs_bufhash {
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index 5fb75d9..e3a5fed 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -24,7 +24,7 @@
 #include "xfs_mount.h"
 #include "xfs_export.h"
 
-STATIC struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, };
+static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, };
 
 /*
  * XFS encodes and decodes the fileid portion of NFS filehandles
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index d26f5cd..cb51dc9 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -46,7 +46,7 @@
 static struct vm_operations_struct xfs_dmapi_file_vm_ops;
 #endif
 
-STATIC inline ssize_t
+STATIC_INLINE ssize_t
 __xfs_file_read(
 	struct kiocb		*iocb,
 	const struct iovec	*iov,
@@ -84,7 +84,7 @@
 	return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
 }
 
-STATIC inline ssize_t
+STATIC_INLINE ssize_t
 __xfs_file_write(
 	struct kiocb		*iocb,
 	const struct iovec	*iov,
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index f011c9c..ff5c41f 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -41,8 +41,6 @@
 #include "xfs_error.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_bmap.h"
 #include "xfs_buf_item.h"
@@ -355,7 +353,6 @@
 xfs_readlink_by_handle(
 	xfs_mount_t		*mp,
 	void			__user *arg,
-	struct file		*parfilp,
 	struct inode		*parinode)
 {
 	int			error;
@@ -388,7 +385,7 @@
 	aiov.iov_len	= olen;
 	aiov.iov_base	= hreq.ohandle;
 
-	auio.uio_iov	= &aiov;
+	auio.uio_iov	= (struct kvec *)&aiov;
 	auio.uio_iovcnt	= 1;
 	auio.uio_offset	= 0;
 	auio.uio_segflg	= UIO_USERSPACE;
@@ -406,7 +403,6 @@
 xfs_fssetdm_by_handle(
 	xfs_mount_t		*mp,
 	void			__user *arg,
-	struct file		*parfilp,
 	struct inode		*parinode)
 {
 	int			error;
@@ -448,7 +444,6 @@
 xfs_attrlist_by_handle(
 	xfs_mount_t		*mp,
 	void			__user *arg,
-	struct file		*parfilp,
 	struct inode		*parinode)
 {
 	int			error;
@@ -569,7 +564,6 @@
 xfs_attrmulti_by_handle(
 	xfs_mount_t		*mp,
 	void			__user *arg,
-	struct file		*parfilp,
 	struct inode		*parinode)
 {
 	int			error;
@@ -689,7 +683,6 @@
 STATIC int
 xfs_ioc_getbmap(
 	bhv_desc_t		*bdp,
-	struct file		*filp,
 	int			flags,
 	unsigned int		cmd,
 	void			__user *arg);
@@ -788,7 +781,7 @@
 
 	case XFS_IOC_GETBMAP:
 	case XFS_IOC_GETBMAPA:
-		return xfs_ioc_getbmap(bdp, filp, ioflags, cmd, arg);
+		return xfs_ioc_getbmap(bdp, ioflags, cmd, arg);
 
 	case XFS_IOC_GETBMAPX:
 		return xfs_ioc_getbmapx(bdp, arg);
@@ -802,16 +795,16 @@
 		return xfs_open_by_handle(mp, arg, filp, inode);
 
 	case XFS_IOC_FSSETDM_BY_HANDLE:
-		return xfs_fssetdm_by_handle(mp, arg, filp, inode);
+		return xfs_fssetdm_by_handle(mp, arg, inode);
 
 	case XFS_IOC_READLINK_BY_HANDLE:
-		return xfs_readlink_by_handle(mp, arg, filp, inode);
+		return xfs_readlink_by_handle(mp, arg, inode);
 
 	case XFS_IOC_ATTRLIST_BY_HANDLE:
-		return xfs_attrlist_by_handle(mp, arg, filp, inode);
+		return xfs_attrlist_by_handle(mp, arg, inode);
 
 	case XFS_IOC_ATTRMULTI_BY_HANDLE:
-		return xfs_attrmulti_by_handle(mp, arg, filp, inode);
+		return xfs_attrmulti_by_handle(mp, arg, inode);
 
 	case XFS_IOC_SWAPEXT: {
 		error = xfs_swapext((struct xfs_swapext __user *)arg);
@@ -1095,11 +1088,6 @@
 /*
  * Linux extended inode flags interface.
  */
-#define LINUX_XFLAG_SYNC	0x00000008 /* Synchronous updates */
-#define LINUX_XFLAG_IMMUTABLE	0x00000010 /* Immutable file */
-#define LINUX_XFLAG_APPEND	0x00000020 /* writes to file may only append */
-#define LINUX_XFLAG_NODUMP	0x00000040 /* do not dump file */
-#define LINUX_XFLAG_NOATIME	0x00000080 /* do not update atime */
 
 STATIC unsigned int
 xfs_merge_ioc_xflags(
@@ -1108,23 +1096,23 @@
 {
 	unsigned int	xflags = start;
 
-	if (flags & LINUX_XFLAG_IMMUTABLE)
+	if (flags & FS_IMMUTABLE_FL)
 		xflags |= XFS_XFLAG_IMMUTABLE;
 	else
 		xflags &= ~XFS_XFLAG_IMMUTABLE;
-	if (flags & LINUX_XFLAG_APPEND)
+	if (flags & FS_APPEND_FL)
 		xflags |= XFS_XFLAG_APPEND;
 	else
 		xflags &= ~XFS_XFLAG_APPEND;
-	if (flags & LINUX_XFLAG_SYNC)
+	if (flags & FS_SYNC_FL)
 		xflags |= XFS_XFLAG_SYNC;
 	else
 		xflags &= ~XFS_XFLAG_SYNC;
-	if (flags & LINUX_XFLAG_NOATIME)
+	if (flags & FS_NOATIME_FL)
 		xflags |= XFS_XFLAG_NOATIME;
 	else
 		xflags &= ~XFS_XFLAG_NOATIME;
-	if (flags & LINUX_XFLAG_NODUMP)
+	if (flags & FS_NODUMP_FL)
 		xflags |= XFS_XFLAG_NODUMP;
 	else
 		xflags &= ~XFS_XFLAG_NODUMP;
@@ -1139,15 +1127,15 @@
 	unsigned int	flags = 0;
 
 	if (di_flags & XFS_DIFLAG_IMMUTABLE)
-		flags |= LINUX_XFLAG_IMMUTABLE;
+		flags |= FS_IMMUTABLE_FL;
 	if (di_flags & XFS_DIFLAG_APPEND)
-		flags |= LINUX_XFLAG_APPEND;
+		flags |= FS_APPEND_FL;
 	if (di_flags & XFS_DIFLAG_SYNC)
-		flags |= LINUX_XFLAG_SYNC;
+		flags |= FS_SYNC_FL;
 	if (di_flags & XFS_DIFLAG_NOATIME)
-		flags |= LINUX_XFLAG_NOATIME;
+		flags |= FS_NOATIME_FL;
 	if (di_flags & XFS_DIFLAG_NODUMP)
-		flags |= LINUX_XFLAG_NODUMP;
+		flags |= FS_NODUMP_FL;
 	return flags;
 }
 
@@ -1247,9 +1235,9 @@
 			break;
 		}
 
-		if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \
-			      LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \
-			      LINUX_XFLAG_SYNC)) {
+		if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
+			      FS_NOATIME_FL | FS_NODUMP_FL | \
+			      FS_SYNC_FL)) {
 			error = -EOPNOTSUPP;
 			break;
 		}
@@ -1281,7 +1269,6 @@
 STATIC int
 xfs_ioc_getbmap(
 	bhv_desc_t		*bdp,
-	struct file		*filp,
 	int			ioflags,
 	unsigned int		cmd,
 	void			__user *arg)
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 3ba814a..0b5fa12 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -43,8 +43,6 @@
 #include "xfs_itable.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_utils.h"
@@ -250,13 +248,13 @@
  *
  * XXX(hch):  nfsd is broken, better fix it instead.
  */
-STATIC inline int
+STATIC_INLINE int
 xfs_has_fs_struct(struct task_struct *task)
 {
 	return (task->fs != init_task.fs);
 }
 
-STATIC inline void
+STATIC void
 xfs_cleanup_inode(
 	bhv_vnode_t	*dvp,
 	bhv_vnode_t	*vp,
@@ -815,7 +813,7 @@
 }
 
 
-struct inode_operations xfs_inode_operations = {
+const struct inode_operations xfs_inode_operations = {
 	.permission		= xfs_vn_permission,
 	.truncate		= xfs_vn_truncate,
 	.getattr		= xfs_vn_getattr,
@@ -826,7 +824,7 @@
 	.removexattr		= xfs_vn_removexattr,
 };
 
-struct inode_operations xfs_dir_inode_operations = {
+const struct inode_operations xfs_dir_inode_operations = {
 	.create			= xfs_vn_create,
 	.lookup			= xfs_vn_lookup,
 	.link			= xfs_vn_link,
@@ -845,7 +843,7 @@
 	.removexattr		= xfs_vn_removexattr,
 };
 
-struct inode_operations xfs_symlink_inode_operations = {
+const struct inode_operations xfs_symlink_inode_operations = {
 	.readlink		= generic_readlink,
 	.follow_link		= xfs_vn_follow_link,
 	.put_link		= xfs_vn_put_link,
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
index ad6173d..95a6939 100644
--- a/fs/xfs/linux-2.6/xfs_iops.h
+++ b/fs/xfs/linux-2.6/xfs_iops.h
@@ -18,9 +18,9 @@
 #ifndef __XFS_IOPS_H__
 #define __XFS_IOPS_H__
 
-extern struct inode_operations xfs_inode_operations;
-extern struct inode_operations xfs_dir_inode_operations;
-extern struct inode_operations xfs_symlink_inode_operations;
+extern const struct inode_operations xfs_inode_operations;
+extern const struct inode_operations xfs_dir_inode_operations;
+extern const struct inode_operations xfs_symlink_inode_operations;
 
 extern const struct file_operations xfs_file_operations;
 extern const struct file_operations xfs_dir_file_operations;
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 2b0e001..715adad 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -109,16 +109,6 @@
 #undef  HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
 #endif
 
-/*
- * State flag for unwritten extent buffers.
- *
- * We need to be able to distinguish between these and delayed
- * allocate buffers within XFS.  The generic IO path code does
- * not need to distinguish - we use the BH_Delay flag for both
- * delalloc and these ondisk-uninitialised buffers.
- */
-BUFFER_FNS(PrivateStart, unwritten);
-
 #define restricted_chown	xfs_params.restrict_chown.val
 #define irix_sgid_inherit	xfs_params.sgid_inherit.val
 #define irix_symlink_mode	xfs_params.symlink_mode.val
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 65e79b4..ff8d64e 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -43,8 +43,6 @@
 #include "xfs_itable.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_inode_item.h"
 #include "xfs_buf_item.h"
@@ -134,13 +132,11 @@
 xfs_iozero(
 	struct inode		*ip,	/* inode			*/
 	loff_t			pos,	/* offset in file		*/
-	size_t			count,	/* size of data to zero		*/
-	loff_t			end_size)	/* max file size to set */
+	size_t			count)	/* size of data to zero		*/
 {
 	unsigned		bytes;
 	struct page		*page;
 	struct address_space	*mapping;
-	char			*kaddr;
 	int			status;
 
 	mapping = ip->i_mapping;
@@ -158,26 +154,21 @@
 		if (!page)
 			break;
 
-		kaddr = kmap(page);
 		status = mapping->a_ops->prepare_write(NULL, page, offset,
 							offset + bytes);
-		if (status) {
+		if (status)
 			goto unlock;
-		}
 
-		memset((void *) (kaddr + offset), 0, bytes);
-		flush_dcache_page(page);
+		memclear_highpage_flush(page, offset, bytes);
+
 		status = mapping->a_ops->commit_write(NULL, page, offset,
 							offset + bytes);
 		if (!status) {
 			pos += bytes;
 			count -= bytes;
-			if (pos > i_size_read(ip))
-				i_size_write(ip, pos < end_size ? pos : end_size);
 		}
 
 unlock:
-		kunmap(page);
 		unlock_page(page);
 		page_cache_release(page);
 		if (status)
@@ -449,8 +440,8 @@
 xfs_zero_last_block(
 	struct inode	*ip,
 	xfs_iocore_t	*io,
-	xfs_fsize_t	isize,
-	xfs_fsize_t	end_size)
+	xfs_fsize_t	offset,
+	xfs_fsize_t	isize)
 {
 	xfs_fileoff_t	last_fsb;
 	xfs_mount_t	*mp = io->io_mount;
@@ -459,7 +450,6 @@
 	int		zero_len;
 	int		error = 0;
 	xfs_bmbt_irec_t	imap;
-	loff_t		loff;
 
 	ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
 
@@ -494,9 +484,10 @@
 	 */
 	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);
+	if (isize + zero_len > offset)
+		zero_len = offset - isize;
+	error = xfs_iozero(ip, isize, zero_len);
 
 	XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
 	ASSERT(error >= 0);
@@ -519,14 +510,15 @@
 	bhv_vnode_t	*vp,
 	xfs_iocore_t	*io,
 	xfs_off_t	offset,		/* starting I/O offset */
-	xfs_fsize_t	isize,		/* current inode size */
-	xfs_fsize_t	end_size)	/* terminal inode size */
+	xfs_fsize_t	isize)		/* current inode size */
 {
 	struct inode	*ip = vn_to_inode(vp);
 	xfs_fileoff_t	start_zero_fsb;
 	xfs_fileoff_t	end_zero_fsb;
 	xfs_fileoff_t	zero_count_fsb;
 	xfs_fileoff_t	last_fsb;
+	xfs_fileoff_t	zero_off;
+	xfs_fsize_t	zero_len;
 	xfs_mount_t	*mp = io->io_mount;
 	int		nimaps;
 	int		error = 0;
@@ -540,7 +532,7 @@
 	 * First handle zeroing the block on which isize resides.
 	 * We only zero a part of that block so it is handled specially.
 	 */
-	error = xfs_zero_last_block(ip, io, isize, end_size);
+	error = xfs_zero_last_block(ip, io, offset, isize);
 	if (error) {
 		ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
 		ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
@@ -601,10 +593,13 @@
 		 */
 		XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
 
-		error = xfs_iozero(ip,
-				   XFS_FSB_TO_B(mp, start_zero_fsb),
-				   XFS_FSB_TO_B(mp, imap.br_blockcount),
-				   end_size);
+		zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
+		zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
+
+		if ((zero_off + zero_len) > offset)
+			zero_len = offset - zero_off;
+
+		error = xfs_iozero(ip, zero_off, zero_len);
 		if (error) {
 			goto out_lock;
 		}
@@ -783,8 +778,7 @@
 	 */
 
 	if (pos > isize) {
-		error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos,
-					isize, pos + count);
+		error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, isize);
 		if (error) {
 			xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
 			goto out_unlock_mutex;
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index c77e62e..7ac51b1 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -83,7 +83,7 @@
 extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
 
 extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t,
-				xfs_fsize_t, xfs_fsize_t);
+				xfs_fsize_t);
 extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
 				const struct iovec *, unsigned int,
 				loff_t *, int, struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index b93265b..2f2c40d 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -43,8 +43,6 @@
 #include "xfs_itable.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_utils.h"
@@ -58,10 +56,10 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
-STATIC struct quotactl_ops xfs_quotactl_operations;
-STATIC struct super_operations xfs_super_operations;
-STATIC kmem_zone_t *xfs_vnode_zone;
-STATIC kmem_zone_t *xfs_ioend_zone;
+static struct quotactl_ops xfs_quotactl_operations;
+static struct super_operations xfs_super_operations;
+static kmem_zone_t *xfs_vnode_zone;
+static kmem_zone_t *xfs_ioend_zone;
 mempool_t *xfs_ioend_pool;
 
 STATIC struct xfs_mount_args *
@@ -121,7 +119,7 @@
 	return (((__uint64_t)pagefactor) << bitshift) - 1;
 }
 
-STATIC __inline__ void
+STATIC_INLINE void
 xfs_set_inodeops(
 	struct inode		*inode)
 {
@@ -147,7 +145,7 @@
 	}
 }
 
-STATIC __inline__ void
+STATIC_INLINE void
 xfs_revalidate_inode(
 	xfs_mount_t		*mp,
 	bhv_vnode_t		*vp,
@@ -553,7 +551,6 @@
 		error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
 					SYNC_ATTR | SYNC_REFCACHE, NULL);
 	vfsp->vfs_sync_seq++;
-	wmb();
 	wake_up(&vfsp->vfs_wait_single_sync_task);
 }
 
@@ -659,9 +656,17 @@
 	int			error;
 	int			flags;
 
-	if (unlikely(sb->s_frozen == SB_FREEZE_WRITE))
-		flags = SYNC_QUIESCE;
-	else
+	if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
+		/*
+		 * First stage of freeze - no more writers will make progress
+		 * now we are here, so we flush delwri and delalloc buffers
+		 * here, then wait for all I/O to complete.  Data is frozen at
+		 * that point. Metadata is not frozen, transactions can still
+		 * occur here so don't bother flushing the buftarg (i.e
+		 * SYNC_QUIESCE) because it'll just get dirty again.
+		 */
+		flags = SYNC_FSDATA | SYNC_DELWRI | SYNC_WAIT | SYNC_IOWAIT;
+	} else
 		flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
 
 	error = bhv_vfs_sync(vfsp, flags, NULL);
@@ -873,7 +878,7 @@
 			   mnt);
 }
 
-STATIC struct super_operations xfs_super_operations = {
+static struct super_operations xfs_super_operations = {
 	.alloc_inode		= xfs_fs_alloc_inode,
 	.destroy_inode		= xfs_fs_destroy_inode,
 	.write_inode		= xfs_fs_write_inode,
@@ -887,7 +892,7 @@
 	.show_options		= xfs_fs_show_options,
 };
 
-STATIC struct quotactl_ops xfs_quotactl_operations = {
+static struct quotactl_ops xfs_quotactl_operations = {
 	.quota_sync		= xfs_fs_quotasync,
 	.get_xstate		= xfs_fs_getxstate,
 	.set_xstate		= xfs_fs_setxstate,
@@ -895,7 +900,7 @@
 	.set_xquota		= xfs_fs_setxquota,
 };
 
-STATIC struct file_system_type xfs_fs_type = {
+static struct file_system_type xfs_fs_type = {
 	.owner			= THIS_MODULE,
 	.name			= "xfs",
 	.get_sb			= xfs_fs_get_sb,
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index af24653..cd6eaa4 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -54,102 +54,204 @@
 }
 #endif /* CONFIG_PROC_FS */
 
-STATIC ctl_table xfs_table[] = {
-	{XFS_RESTRICT_CHOWN, "restrict_chown", &xfs_params.restrict_chown.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.restrict_chown.min, &xfs_params.restrict_chown.max},
+static ctl_table xfs_table[] = {
+	{
+		.ctl_name	= XFS_RESTRICT_CHOWN,
+		.procname	= "restrict_chown",
+		.data		= &xfs_params.restrict_chown.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.restrict_chown.min,
+		.extra2		= &xfs_params.restrict_chown.max
+	},
+	{
+		.ctl_name	= XFS_SGID_INHERIT,
+		.procname	= "irix_sgid_inherit",
+		.data		= &xfs_params.sgid_inherit.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.sgid_inherit.min,
+		.extra2		= &xfs_params.sgid_inherit.max
+	},
+	{
+		.ctl_name	= XFS_SYMLINK_MODE,
+		.procname	= "irix_symlink_mode",
+		.data		= &xfs_params.symlink_mode.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.symlink_mode.min,
+		.extra2		= &xfs_params.symlink_mode.max
+	},
+	{
+		.ctl_name	= XFS_PANIC_MASK,
+		.procname	= "panic_mask",
+		.data		= &xfs_params.panic_mask.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.panic_mask.min,
+		.extra2		= &xfs_params.panic_mask.max
+	},
 
-	{XFS_SGID_INHERIT, "irix_sgid_inherit", &xfs_params.sgid_inherit.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.sgid_inherit.min, &xfs_params.sgid_inherit.max},
-
-	{XFS_SYMLINK_MODE, "irix_symlink_mode", &xfs_params.symlink_mode.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.symlink_mode.min, &xfs_params.symlink_mode.max},
-
-	{XFS_PANIC_MASK, "panic_mask", &xfs_params.panic_mask.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.panic_mask.min, &xfs_params.panic_mask.max},
-
-	{XFS_ERRLEVEL, "error_level", &xfs_params.error_level.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.error_level.min, &xfs_params.error_level.max},
-
-	{XFS_SYNCD_TIMER, "xfssyncd_centisecs", &xfs_params.syncd_timer.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.syncd_timer.min, &xfs_params.syncd_timer.max},
-
-	{XFS_INHERIT_SYNC, "inherit_sync", &xfs_params.inherit_sync.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.inherit_sync.min, &xfs_params.inherit_sync.max},
-
-	{XFS_INHERIT_NODUMP, "inherit_nodump", &xfs_params.inherit_nodump.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.inherit_nodump.min, &xfs_params.inherit_nodump.max},
-
-	{XFS_INHERIT_NOATIME, "inherit_noatime", &xfs_params.inherit_noatim.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.inherit_noatim.min, &xfs_params.inherit_noatim.max},
-
-	{XFS_BUF_TIMER, "xfsbufd_centisecs", &xfs_params.xfs_buf_timer.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.xfs_buf_timer.min, &xfs_params.xfs_buf_timer.max},
-
-	{XFS_BUF_AGE, "age_buffer_centisecs", &xfs_params.xfs_buf_age.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.xfs_buf_age.min, &xfs_params.xfs_buf_age.max},
-
-	{XFS_INHERIT_NOSYM, "inherit_nosymlinks", &xfs_params.inherit_nosym.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.inherit_nosym.min, &xfs_params.inherit_nosym.max},
-
-	{XFS_ROTORSTEP, "rotorstep", &xfs_params.rotorstep.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.rotorstep.min, &xfs_params.rotorstep.max},
-
-	{XFS_INHERIT_NODFRG, "inherit_nodefrag", &xfs_params.inherit_nodfrg.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&xfs_params.inherit_nodfrg.min, &xfs_params.inherit_nodfrg.max},
-
+	{
+		.ctl_name	= XFS_ERRLEVEL,
+		.procname	= "error_level",
+		.data		= &xfs_params.error_level.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.error_level.min,
+		.extra2		= &xfs_params.error_level.max
+	},
+	{
+		.ctl_name	= XFS_SYNCD_TIMER,
+		.procname	= "xfssyncd_centisecs",
+		.data		= &xfs_params.syncd_timer.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.syncd_timer.min,
+		.extra2		= &xfs_params.syncd_timer.max
+	},
+	{
+		.ctl_name	= XFS_INHERIT_SYNC,
+		.procname	= "inherit_sync",
+		.data		= &xfs_params.inherit_sync.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.inherit_sync.min,
+		.extra2		= &xfs_params.inherit_sync.max
+	},
+	{
+		.ctl_name	= XFS_INHERIT_NODUMP,
+		.procname	= "inherit_nodump",
+		.data		= &xfs_params.inherit_nodump.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.inherit_nodump.min,
+		.extra2		= &xfs_params.inherit_nodump.max
+	},
+	{
+		.ctl_name	= XFS_INHERIT_NOATIME,
+		.procname	= "inherit_noatime",
+		.data		= &xfs_params.inherit_noatim.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.inherit_noatim.min,
+		.extra2		= &xfs_params.inherit_noatim.max
+	},
+	{
+		.ctl_name	= XFS_BUF_TIMER,
+		.procname	= "xfsbufd_centisecs",
+		.data		= &xfs_params.xfs_buf_timer.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.xfs_buf_timer.min,
+		.extra2		= &xfs_params.xfs_buf_timer.max
+	},
+	{
+		.ctl_name	= XFS_BUF_AGE,
+		.procname	= "age_buffer_centisecs",
+		.data		= &xfs_params.xfs_buf_age.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.xfs_buf_age.min,
+		.extra2		= &xfs_params.xfs_buf_age.max
+	},
+	{
+		.ctl_name	= XFS_INHERIT_NOSYM,
+		.procname	= "inherit_nosymlinks",
+		.data		= &xfs_params.inherit_nosym.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.inherit_nosym.min,
+		.extra2		= &xfs_params.inherit_nosym.max
+	},
+	{
+		.ctl_name	= XFS_ROTORSTEP,
+		.procname	= "rotorstep",
+		.data		= &xfs_params.rotorstep.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.rotorstep.min,
+		.extra2		= &xfs_params.rotorstep.max
+	},
+	{
+		.ctl_name	= XFS_INHERIT_NODFRG,
+		.procname	= "inherit_nodefrag",
+		.data		= &xfs_params.inherit_nodfrg.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.inherit_nodfrg.min,
+		.extra2		= &xfs_params.inherit_nodfrg.max
+	},
 	/* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
-	{XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
-	sizeof(int), 0644, NULL, &xfs_stats_clear_proc_handler,
-	&sysctl_intvec, NULL,
-	&xfs_params.stats_clear.min, &xfs_params.stats_clear.max},
+	{
+		.ctl_name	= XFS_STATS_CLEAR,
+		.procname	= "stats_clear",
+		.data		= &xfs_params.stats_clear.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &xfs_stats_clear_proc_handler,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xfs_params.stats_clear.min,
+		.extra2		= &xfs_params.stats_clear.max
+	},
 #endif /* CONFIG_PROC_FS */
 
-	{0}
+	{}
 };
 
-STATIC ctl_table xfs_dir_table[] = {
-	{FS_XFS, "xfs", NULL, 0, 0555, xfs_table},
-	{0}
+static ctl_table xfs_dir_table[] = {
+	{
+		.ctl_name	= FS_XFS,
+		.procname	= "xfs",
+		.mode		= 0555,
+		.child		= xfs_table
+	},
+	{}
 };
 
-STATIC ctl_table xfs_root_table[] = {
-	{CTL_FS, "fs",  NULL, 0, 0555, xfs_dir_table},
-	{0}
+static ctl_table xfs_root_table[] = {
+	{
+		.ctl_name	= CTL_FS,
+		.procname	= "fs",
+		.mode		= 0555,
+		.child		= xfs_dir_table
+	},
+	{}
 };
 
 void
 xfs_sysctl_register(void)
 {
-	xfs_table_header = register_sysctl_table(xfs_root_table, 1);
+	xfs_table_header = register_sysctl_table(xfs_root_table);
 }
 
 void
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index da255bd..e2c2ce9 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -91,7 +91,7 @@
 #define SYNC_FSDATA		0x0020	/* flush fs data (e.g. superblocks) */
 #define SYNC_REFCACHE		0x0040  /* prune some of the nfs ref cache */
 #define SYNC_REMOUNT		0x0080  /* remount readonly, no dummy LRs */
-#define SYNC_QUIESCE		0x0100  /* quiesce fileystem for a snapshot */
+#define SYNC_IOWAIT		0x0100  /* wait for all I/O to complete */
 
 #define SHUTDOWN_META_IO_ERROR	0x0001	/* write attempt to metadata failed */
 #define SHUTDOWN_LOG_IO_ERROR	0x0002	/* write attempt to the log failed */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index 553fa73..ada24ba 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -26,7 +26,7 @@
  */
 #define NVSYNC                  37
 #define vptosync(v)             (&vsync[((unsigned long)v) % NVSYNC])
-STATIC wait_queue_head_t vsync[NVSYNC];
+static wait_queue_head_t vsync[NVSYNC];
 
 void
 vn_init(void)
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 515f5fd..b76118c 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -489,14 +489,14 @@
 #define VN_LOCK(vp)		mutex_spinlock(&(vp)->v_lock)
 #define VN_UNLOCK(vp, s)	mutex_spinunlock(&(vp)->v_lock, s)
 
-static __inline__ void vn_flagset(struct bhv_vnode *vp, uint flag)
+STATIC_INLINE void vn_flagset(struct bhv_vnode *vp, uint flag)
 {
 	spin_lock(&vp->v_lock);
 	vp->v_flag |= flag;
 	spin_unlock(&vp->v_lock);
 }
 
-static __inline__ uint vn_flagclr(struct bhv_vnode *vp, uint flag)
+STATIC_INLINE uint vn_flagclr(struct bhv_vnode *vp, uint flag)
 {
 	uint	cleared;
 
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 3aa7715..4adaf13 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -43,8 +43,6 @@
 #include "xfs_itable.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_trans_space.h"
@@ -484,7 +482,7 @@
 
 	xfs_trans_bhold(tp, bp);
 
-	if ((error = xfs_bmap_finish(tpp, &flist, firstblock, &committed))) {
+	if ((error = xfs_bmap_finish(tpp, &flist, &committed))) {
 		goto error1;
 	}
 
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index 33ad5af..ddb61fe 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -43,8 +43,6 @@
 #include "xfs_itable.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_trans_priv.h"
@@ -399,7 +397,7 @@
 /*
  * This is the ops vector for dquots
  */
-STATIC struct xfs_item_ops xfs_dquot_item_ops = {
+static struct xfs_item_ops xfs_dquot_item_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_qm_dquot_logitem_format,
@@ -606,7 +604,7 @@
 	return;
 }
 
-STATIC struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
+static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_qm_qoff_logitem_format,
@@ -628,7 +626,7 @@
 /*
  * This is the ops vector shared by all quotaoff-start log items.
  */
-STATIC struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
+static struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_qm_qoff_logitem_format,
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 7c6a3a5..1de2acd 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -44,8 +44,6 @@
 #include "xfs_bmap.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_trans_space.h"
@@ -64,10 +62,10 @@
 
 kmem_zone_t	*qm_dqzone;
 kmem_zone_t	*qm_dqtrxzone;
-STATIC kmem_shaker_t	xfs_qm_shaker;
+static kmem_shaker_t	xfs_qm_shaker;
 
-STATIC cred_t	xfs_zerocr;
-STATIC xfs_inode_t	xfs_zeroino;
+static cred_t	xfs_zerocr;
+static xfs_inode_t	xfs_zeroino;
 
 STATIC void	xfs_qm_list_init(xfs_dqlist_t *, char *, int);
 STATIC void	xfs_qm_list_destroy(xfs_dqlist_t *);
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index db8872b..d2cdb8a 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -44,8 +44,6 @@
 #include "xfs_error.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_qm.h"
@@ -384,7 +382,7 @@
 }
 
 
-STATIC struct xfs_qmops xfs_qmcore_xfs = {
+static struct xfs_qmops xfs_qmcore_xfs = {
 	.xfs_qminit		= xfs_qm_newmount,
 	.xfs_qmdone		= xfs_qm_unmount_quotadestroy,
 	.xfs_qmmount		= xfs_qm_endmount,
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c
index 6f858fb..709f5f5 100644
--- a/fs/xfs/quota/xfs_qm_stats.c
+++ b/fs/xfs/quota/xfs_qm_stats.c
@@ -43,8 +43,6 @@
 #include "xfs_error.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_qm.h"
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index ed620c4..716f562 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -46,8 +46,6 @@
 #include "xfs_error.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_utils.h"
@@ -134,7 +132,7 @@
 		break;
 
 	case Q_XQUOTASYNC:
-		return (xfs_sync_inodes(mp, SYNC_DELWRI, 0, NULL));
+		return (xfs_sync_inodes(mp, SYNC_DELWRI, NULL));
 
 	default:
 		break;
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 0242e96..d7491e7 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -43,8 +43,6 @@
 #include "xfs_error.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_trans_priv.h"
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index 4363512..08bbd3c 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -19,7 +19,7 @@
 #include "debug.h"
 #include "spin.h"
 
-static char		message[256];	/* keep it off the stack */
+static char		message[1024];	/* keep it off the stack */
 static DEFINE_SPINLOCK(xfs_err_lock);
 
 /* Translate from CE_FOO to KERN_FOO, err_level(CE_FOO) == KERN_FOO */
@@ -44,13 +44,14 @@
 	spin_lock_irqsave(&xfs_err_lock,flags);
 	va_start(ap, fmt);
 	if (*fmt == '!') fp++;
-	len = vsprintf(message, fp, ap);
-	if (level != CE_DEBUG && message[len-1] != '\n')
-		strcat(message, "\n");
-	printk("%s%s", err_level[level], message);
+	len = vsnprintf(message, sizeof(message), fp, ap);
+	if (len >= sizeof(message))
+		len = sizeof(message) - 1;
+	if (message[len-1] == '\n')
+		message[len-1] = 0;
+	printk("%s%s\n", err_level[level], message);
 	va_end(ap);
 	spin_unlock_irqrestore(&xfs_err_lock,flags);
-
 	BUG_ON(level == CE_PANIC);
 }
 
@@ -64,11 +65,13 @@
 	if(level > XFS_MAX_ERR_LEVEL)
 		level = XFS_MAX_ERR_LEVEL;
 	spin_lock_irqsave(&xfs_err_lock,flags);
-	len = vsprintf(message, fmt, ap);
-	if (level != CE_DEBUG && message[len-1] != '\n')
-		strcat(message, "\n");
+	len = vsnprintf(message, sizeof(message), fmt, ap);
+	if (len >= sizeof(message))
+		len = sizeof(message) - 1;
+	if (message[len-1] == '\n')
+		message[len-1] = 0;
+	printk("%s%s\n", err_level[level], message);
 	spin_unlock_irqrestore(&xfs_err_lock,flags);
-	printk("%s%s", err_level[level], message);
 	BUG_ON(level == CE_PANIC);
 }
 
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
index 4f54dca..2a70cc6 100644
--- a/fs/xfs/support/debug.h
+++ b/fs/xfs/support/debug.h
@@ -38,13 +38,37 @@
 
 #ifndef DEBUG
 # define ASSERT(expr)	((void)0)
-#else
-# define ASSERT(expr)	ASSERT_ALWAYS(expr)
-extern unsigned long random(void);
-#endif
 
 #ifndef STATIC
-# define STATIC static
+# define STATIC static noinline
 #endif
 
+#ifndef STATIC_INLINE
+# define STATIC_INLINE static inline
+#endif
+
+#else /* DEBUG */
+
+# define ASSERT(expr)	ASSERT_ALWAYS(expr)
+extern unsigned long random(void);
+
+#ifndef STATIC
+# define STATIC noinline
+#endif
+
+/*
+ * We stop inlining of inline functions in debug mode.
+ * Unfortunately, this means static inline in header files
+ * get multiple definitions, so they need to remain static.
+ * This then gives tonnes of warnings about unused but defined
+ * functions, so we need to add the unused attribute to prevent
+ * these spurious warnings.
+ */
+#ifndef STATIC_INLINE
+# define STATIC_INLINE static __attribute__ ((unused)) noinline
+#endif
+
+#endif /* DEBUG */
+
+
 #endif  /* __XFS_SUPPORT_DEBUG_H__ */
diff --git a/fs/xfs/support/move.h b/fs/xfs/support/move.h
index 977879c..324e413 100644
--- a/fs/xfs/support/move.h
+++ b/fs/xfs/support/move.h
@@ -55,7 +55,7 @@
 };
 
 struct uio {
-	struct iovec	*uio_iov;   /* pointer to array of iovecs */
+	struct kvec	*uio_iov;   /* pointer to array of iovecs */
 	int		uio_iovcnt; /* number of iovecs in array */
 	xfs_off_t	uio_offset; /* offset in file this uio corresponds to */
 	int		uio_resid;  /* residual i/o count */
@@ -63,7 +63,7 @@
 };
 
 typedef struct uio uio_t;
-typedef struct iovec iovec_t;
+typedef struct kvec iovec_t;
 
 extern int	xfs_uio_read (caddr_t, size_t, uio_t *);
 
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 4b0cb47..4ca4beb 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -31,7 +31,6 @@
 #include "xfs_inode.h"
 #include "xfs_btree.h"
 #include "xfs_acl.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 
 #include <linux/capability.h>
diff --git a/fs/xfs/xfs_alloc_btree.h b/fs/xfs/xfs_alloc_btree.h
index bce81c7..5bd1a2c 100644
--- a/fs/xfs/xfs_alloc_btree.h
+++ b/fs/xfs/xfs_alloc_btree.h
@@ -58,7 +58,6 @@
 /*
  * Real block structures have a size equal to the disk block size.
  */
-#define	XFS_ALLOC_BLOCK_SIZE(lev,cur)	(1 << (cur)->bc_blocklog)
 #define	XFS_ALLOC_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_alloc_mxr[lev != 0])
 #define	XFS_ALLOC_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_alloc_mnr[lev != 0])
 
@@ -87,16 +86,13 @@
  * Record, key, and pointer address macros for btree blocks.
  */
 #define	XFS_ALLOC_REC_ADDR(bb,i,cur)	\
-	XFS_BTREE_REC_ADDR(XFS_ALLOC_BLOCK_SIZE(0,cur), xfs_alloc, \
-				bb, i, XFS_ALLOC_BLOCK_MAXRECS(0, cur))
+	XFS_BTREE_REC_ADDR(xfs_alloc, bb, i)
 
 #define	XFS_ALLOC_KEY_ADDR(bb,i,cur)	\
-	XFS_BTREE_KEY_ADDR(XFS_ALLOC_BLOCK_SIZE(1,cur), xfs_alloc, \
-				bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur))
+	XFS_BTREE_KEY_ADDR(xfs_alloc, bb, i)
 
 #define	XFS_ALLOC_PTR_ADDR(bb,i,cur)	\
-	XFS_BTREE_PTR_ADDR(XFS_ALLOC_BLOCK_SIZE(1,cur), xfs_alloc, \
-				bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur))
+	XFS_BTREE_PTR_ADDR(xfs_alloc, bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur))
 
 /*
  * Decrement cursor by one record at the level.
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 9ada7bd..9d358ff 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -57,9 +57,9 @@
  */
 
 #define ATTR_SYSCOUNT	2
-STATIC struct attrnames posix_acl_access;
-STATIC struct attrnames posix_acl_default;
-STATIC struct attrnames *attr_system_names[ATTR_SYSCOUNT];
+static struct attrnames posix_acl_access;
+static struct attrnames posix_acl_default;
+static struct attrnames *attr_system_names[ATTR_SYSCOUNT];
 
 /*========================================================================
  * Function prototypes for the kernel.
@@ -199,18 +199,14 @@
 		return (error);
 
 	/*
-	 * Determine space new attribute will use, and if it would be
-	 * "local" or "remote" (note: local != inline).
-	 */
-	size = xfs_attr_leaf_newentsize(namelen, valuelen,
-					mp->m_sb.sb_blocksize, &local);
-
-	/*
 	 * If the inode doesn't have an attribute fork, add one.
 	 * (inode must not be locked when we call this routine)
 	 */
 	if (XFS_IFORK_Q(dp) == 0) {
-		if ((error = xfs_bmap_add_attrfork(dp, size, rsvd)))
+		int sf_size = sizeof(xfs_attr_sf_hdr_t) +
+			      XFS_ATTR_SF_ENTSIZE_BYNAME(namelen, valuelen);
+
+		if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd)))
 			return(error);
 	}
 
@@ -231,6 +227,13 @@
 	args.addname = 1;
 	args.oknoent = 1;
 
+	/*
+	 * Determine space new attribute will use, and if it would be
+	 * "local" or "remote" (note: local != inline).
+	 */
+	size = xfs_attr_leaf_newentsize(namelen, valuelen,
+					mp->m_sb.sb_blocksize, &local);
+
 	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
 	if (local) {
 		if (size > (mp->m_sb.sb_blocksize >> 1)) {
@@ -346,7 +349,7 @@
 		error = xfs_attr_shortform_to_leaf(&args);
 		if (!error) {
 			error = xfs_bmap_finish(&args.trans, args.flist,
-						*args.firstblock, &committed);
+						&committed);
 		}
 		if (error) {
 			ASSERT(committed);
@@ -973,7 +976,7 @@
 		error = xfs_attr_leaf_to_node(args);
 		if (!error) {
 			error = xfs_bmap_finish(&args->trans, args->flist,
-						*args->firstblock, &committed);
+						&committed);
 		}
 		if (error) {
 			ASSERT(committed);
@@ -1074,7 +1077,6 @@
 			if (!error) {
 				error = xfs_bmap_finish(&args->trans,
 							args->flist,
-							*args->firstblock,
 							&committed);
 			}
 			if (error) {
@@ -1152,7 +1154,7 @@
 		/* bp is gone due to xfs_da_shrink_inode */
 		if (!error) {
 			error = xfs_bmap_finish(&args->trans, args->flist,
-						*args->firstblock, &committed);
+						&committed);
 		}
 		if (error) {
 			ASSERT(committed);
@@ -1307,7 +1309,6 @@
 			if (!error) {
 				error = xfs_bmap_finish(&args->trans,
 							args->flist,
-							*args->firstblock,
 							&committed);
 			}
 			if (error) {
@@ -1347,7 +1348,7 @@
 		error = xfs_da_split(state);
 		if (!error) {
 			error = xfs_bmap_finish(&args->trans, args->flist,
-						*args->firstblock, &committed);
+						&committed);
 		}
 		if (error) {
 			ASSERT(committed);
@@ -1459,7 +1460,6 @@
 			if (!error) {
 				error = xfs_bmap_finish(&args->trans,
 							args->flist,
-							*args->firstblock,
 							&committed);
 			}
 			if (error) {
@@ -1594,7 +1594,7 @@
 		error = xfs_da_join(state);
 		if (!error) {
 			error = xfs_bmap_finish(&args->trans, args->flist,
-						*args->firstblock, &committed);
+						&committed);
 		}
 		if (error) {
 			ASSERT(committed);
@@ -1646,7 +1646,6 @@
 			if (!error) {
 				error = xfs_bmap_finish(&args->trans,
 							args->flist,
-							*args->firstblock,
 							&committed);
 			}
 			if (error) {
@@ -2090,7 +2089,7 @@
 				  args->flist, NULL);
 		if (!error) {
 			error = xfs_bmap_finish(&args->trans, args->flist,
-						*args->firstblock, &committed);
+						&committed);
 		}
 		if (error) {
 			ASSERT(committed);
@@ -2246,7 +2245,7 @@
 				    NULL, &done);
 		if (!error) {
 			error = xfs_bmap_finish(&args->trans, args->flist,
-						*args->firstblock, &committed);
+						&committed);
 		}
 		if (error) {
 			ASSERT(committed);
@@ -2477,7 +2476,7 @@
 	return xfs_acl_vhasacl_default(vp);
 }
 
-STATIC struct attrnames posix_acl_access = {
+static struct attrnames posix_acl_access = {
 	.attr_name	= "posix_acl_access",
 	.attr_namelen	= sizeof("posix_acl_access") - 1,
 	.attr_get	= posix_acl_access_get,
@@ -2486,7 +2485,7 @@
 	.attr_exists	= posix_acl_access_exists,
 };
 
-STATIC struct attrnames posix_acl_default = {
+static struct attrnames posix_acl_default = {
 	.attr_name	= "posix_acl_default",
 	.attr_namelen	= sizeof("posix_acl_default") - 1,
 	.attr_get	= posix_acl_default_get,
@@ -2495,7 +2494,7 @@
 	.attr_exists	= posix_acl_default_exists,
 };
 
-STATIC struct attrnames *attr_system_names[] =
+static struct attrnames *attr_system_names[] =
 	{ &posix_acl_access, &posix_acl_default };
 
 
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 9719bbe..8eab73e 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -94,7 +94,7 @@
  * Namespace helper routines
  *========================================================================*/
 
-STATIC inline attrnames_t *
+STATIC_INLINE attrnames_t *
 xfs_attr_flags_namesp(int flags)
 {
 	return ((flags & XFS_ATTR_SECURE) ? &attr_secure:
@@ -105,7 +105,7 @@
  * If namespace bits don't match return 0.
  * If all match then return 1.
  */
-STATIC inline int
+STATIC_INLINE int
 xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
 {
 	return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags);
@@ -116,7 +116,7 @@
  * then return 0.
  * If all match or are overridable then return 1.
  */
-STATIC inline int
+STATIC_INLINE int
 xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags)
 {
 	if (((arg_flags & ATTR_SECURE) == 0) !=
@@ -150,6 +150,7 @@
 	int offset;
 	int minforkoff;	/* lower limit on valid forkoff locations */
 	int maxforkoff;	/* upper limit on valid forkoff locations */
+	int dsize;	
 	xfs_mount_t *mp = dp->i_mount;
 
 	offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
@@ -169,8 +170,43 @@
 		return 0;
 	}
 
-	/* data fork btree root can have at least this many key/ptr pairs */
-	minforkoff = MAX(dp->i_df.if_bytes, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
+	dsize = dp->i_df.if_bytes;
+	
+	switch (dp->i_d.di_format) {
+	case XFS_DINODE_FMT_EXTENTS:
+		/* 
+		 * If there is no attr fork and the data fork is extents, 
+		 * determine if creating the default attr fork will result 
+		 * in the extents form migrating to btree. If so, the 
+		 * minimum offset only needs to be the space required for 
+		 * the btree root.
+		 */ 
+		if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > mp->m_attroffset)
+			dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
+		break;
+		
+	case XFS_DINODE_FMT_BTREE:
+		/*
+		 * If have data btree then keep forkoff if we have one,
+		 * otherwise we are adding a new attr, so then we set 
+		 * minforkoff to where the btree root can finish so we have 
+		 * plenty of room for attrs
+		 */
+		if (dp->i_d.di_forkoff) {
+			if (offset < dp->i_d.di_forkoff) 
+				return 0;
+			else 
+				return dp->i_d.di_forkoff;
+		} else
+			dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot);
+		break;
+	}
+	
+	/* 
+	 * A data fork btree root must have space for at least 
+	 * MINDBTPTRS key/ptr pairs if the data fork is small or empty.
+	 */
+	minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
 	minforkoff = roundup(minforkoff, 8) >> 3;
 
 	/* attr fork btree root can have at least this many key/ptr pairs */
@@ -336,7 +372,8 @@
 	 */
 	totsize -= size;
 	if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname &&
-	    (mp->m_flags & XFS_MOUNT_ATTR2)) {
+	    (mp->m_flags & XFS_MOUNT_ATTR2) && 
+	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE)) {
 		/*
 		 * Last attribute now removed, revert to original
 		 * inode format making all literal area available
@@ -355,7 +392,8 @@
 		dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize);
 		ASSERT(dp->i_d.di_forkoff);
 		ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname ||
-			!(mp->m_flags & XFS_MOUNT_ATTR2));
+			!(mp->m_flags & XFS_MOUNT_ATTR2) ||
+			dp->i_d.di_format == XFS_DINODE_FMT_BTREE);
 		dp->i_afp->if_ext_max =
 			XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
 		dp->i_df.if_ext_max =
@@ -748,6 +786,7 @@
 				+ be16_to_cpu(name_loc->valuelen);
 	}
 	if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
+	    (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
 	    (bytes == sizeof(struct xfs_attr_sf_hdr)))
 		return(-1);
 	return(xfs_attr_shortform_bytesfit(dp, bytes));
@@ -786,6 +825,7 @@
 
 	if (forkoff == -1) {
 		ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
+		ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);
 
 		/*
 		 * Last attribute was removed, revert to original
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c
index 43be6a7..1afe07f 100644
--- a/fs/xfs/xfs_bit.c
+++ b/fs/xfs/xfs_bit.c
@@ -29,7 +29,7 @@
 /*
  * Index of high bit number in byte, -1 for none set, 0..7 otherwise.
  */
-STATIC const char xfs_highbit[256] = {
+static const char xfs_highbit[256] = {
        -1, 0, 1, 1, 2, 2, 2, 2,			/* 00 .. 07 */
 	3, 3, 3, 3, 3, 3, 3, 3,			/* 08 .. 0f */
 	4, 4, 4, 4, 4, 4, 4, 4,			/* 10 .. 17 */
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 498ad50d..8779518 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -185,16 +185,6 @@
 	int			*logflagsp, /* inode logging flags */
 	int			whichfork); /* data or attr fork */
 
-#ifdef DEBUG
-/*
- * Check that the extents list for the inode ip is in the right order.
- */
-STATIC void
-xfs_bmap_check_extents(
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	int			whichfork);	/* data or attr fork */
-#endif
-
 /*
  * Called by xfs_bmapi to update file extent records and the btree
  * after removing space (or undoing a delayed allocation).
@@ -410,7 +400,6 @@
 STATIC int
 xfs_bmap_disk_count_leaves(
 	xfs_ifork_t		*ifp,
-	xfs_mount_t		*mp,
 	xfs_extnum_t		idx,
 	xfs_bmbt_block_t	*block,
 	int			numrecs,
@@ -684,7 +673,7 @@
 		ASSERT(nblks <= da_old);
 		if (nblks < da_old)
 			xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
-				(int)(da_old - nblks), rsvd);
+				(int64_t)(da_old - nblks), rsvd);
 	}
 	/*
 	 * Clear out the allocated field, done with it now in any case.
@@ -1209,7 +1198,7 @@
 		diff = (int)(temp + temp2 - STARTBLOCKVAL(PREV.br_startblock) -
 			(cur ? cur->bc_private.b.allocated : 0));
 		if (diff > 0 &&
-		    xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -diff, rsvd)) {
+		    xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd)) {
 			/*
 			 * Ick gross gag me with a spoon.
 			 */
@@ -1220,7 +1209,7 @@
 					diff--;
 					if (!diff ||
 					    !xfs_mod_incore_sb(ip->i_mount,
-						    XFS_SBS_FDBLOCKS, -diff, rsvd))
+						    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
 						break;
 				}
 				if (temp2) {
@@ -1228,7 +1217,7 @@
 					diff--;
 					if (!diff ||
 					    !xfs_mod_incore_sb(ip->i_mount,
-						    XFS_SBS_FDBLOCKS, -diff, rsvd))
+						    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
 						break;
 				}
 			}
@@ -2015,7 +2004,7 @@
 	if (oldlen != newlen) {
 		ASSERT(oldlen > newlen);
 		xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
-			(int)(oldlen - newlen), rsvd);
+			(int64_t)(oldlen - newlen), rsvd);
 		/*
 		 * Nothing to do for disk quota accounting here.
 		 */
@@ -3359,7 +3348,7 @@
 	 */
 	ASSERT(da_old >= da_new);
 	if (da_old > da_new)
-		xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new),
+		xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int64_t)(da_old - da_new),
 			rsvd);
 	if (delta) {
 		/* DELTA: report the original extent. */
@@ -3543,6 +3532,7 @@
 	if (whichfork == XFS_ATTR_FORK &&
 	    (ip->i_d.di_format != XFS_DINODE_FMT_DEV) &&
 	    (ip->i_d.di_format != XFS_DINODE_FMT_UUID) &&
+	    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
 	    ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) {
 		ip->i_d.di_forkoff = mp->m_attroffset >> 3;
 		ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) /
@@ -4079,7 +4069,7 @@
 		} else
 			XFS_SB_UNLOCK(mp, s);
 	}
-	if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed)))
+	if ((error = xfs_bmap_finish(&tp, &flist, &committed)))
 		goto error2;
 	error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES, NULL);
 	ASSERT(ip->i_df.if_ext_max ==
@@ -4212,7 +4202,6 @@
 xfs_bmap_finish(
 	xfs_trans_t		**tp,		/* transaction pointer addr */
 	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
-	xfs_fsblock_t		firstblock,	/* controlled ag for allocs */
 	int			*committed)	/* xact committed or not */
 {
 	xfs_efd_log_item_t	*efd;		/* extent free data */
@@ -4533,8 +4522,7 @@
 			error0);
 		if (level == 0)
 			break;
-		pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
-			1, mp->m_bmap_dmxr[1]);
+		pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
 		bno = be64_to_cpu(*pp);
 		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
 		xfs_trans_brelse(tp, bp);
@@ -4577,8 +4565,7 @@
 		/*
 		 * Copy records into the extent records.
 		 */
-		frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
-			block, 1, mp->m_bmap_dmxr[0]);
+		frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
 		start = i;
 		for (j = 0; j < num_recs; j++, i++, frp++) {
 			trp = xfs_iext_get_ext(ifp, i);
@@ -4929,28 +4916,28 @@
 				if (rt) {
 					error = xfs_mod_incore_sb(mp,
 							XFS_SBS_FREXTENTS,
-							-(extsz), (flags &
+							-((int64_t)extsz), (flags &
 							XFS_BMAPI_RSVBLOCKS));
 				} else {
 					error = xfs_mod_incore_sb(mp,
 							XFS_SBS_FDBLOCKS,
-							-(alen), (flags &
+							-((int64_t)alen), (flags &
 							XFS_BMAPI_RSVBLOCKS));
 				}
 				if (!error) {
 					error = xfs_mod_incore_sb(mp,
 							XFS_SBS_FDBLOCKS,
-							-(indlen), (flags &
+							-((int64_t)indlen), (flags &
 							XFS_BMAPI_RSVBLOCKS));
 					if (error && rt)
 						xfs_mod_incore_sb(mp,
 							XFS_SBS_FREXTENTS,
-							extsz, (flags &
+							(int64_t)extsz, (flags &
 							XFS_BMAPI_RSVBLOCKS));
 					else if (error)
 						xfs_mod_incore_sb(mp,
 							XFS_SBS_FDBLOCKS,
-							alen, (flags &
+							(int64_t)alen, (flags &
 							XFS_BMAPI_RSVBLOCKS));
 				}
 
@@ -5616,13 +5603,13 @@
 				rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
 				do_div(rtexts, mp->m_sb.sb_rextsize);
 				xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
-						(int)rtexts, rsvd);
+						(int64_t)rtexts, rsvd);
 				(void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
 					NULL, ip, -((long)del.br_blockcount), 0,
 					XFS_QMOPT_RES_RTBLKS);
 			} else {
 				xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
-						(int)del.br_blockcount, rsvd);
+						(int64_t)del.br_blockcount, rsvd);
 				(void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
 					NULL, ip, -((long)del.br_blockcount), 0,
 					XFS_QMOPT_RES_REGBLKS);
@@ -6048,32 +6035,6 @@
 }
 
 #ifdef DEBUG
-/*
- * Check that the extents list for the inode ip is in the right order.
- */
-STATIC void
-xfs_bmap_check_extents(
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	int			whichfork)	/* data or attr fork */
-{
-	xfs_bmbt_rec_t		*ep;		/* current extent entry */
-	xfs_extnum_t		idx;		/* extent record index */
-	xfs_ifork_t		*ifp;		/* inode fork pointer */
-	xfs_extnum_t		nextents;	/* number of extents in list */
-	xfs_bmbt_rec_t		*nextp;		/* next extent entry */
-
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
-	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
-	ep = xfs_iext_get_ext(ifp, 0);
-	for (idx = 0; idx < nextents - 1; idx++) {
-		nextp = xfs_iext_get_ext(ifp, idx + 1);
-		xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep,
-			(void *)(nextp));
-		ep = nextp;
-	}
-}
-
 STATIC
 xfs_buf_t *
 xfs_bmap_get_bp(
@@ -6156,8 +6117,7 @@
 		if (root) {
 			keyp = XFS_BMAP_BROOT_KEY_ADDR(block, i, sz);
 		} else {
-			keyp = XFS_BTREE_KEY_ADDR(mp->m_sb.sb_blocksize,
-				xfs_bmbt, block, i, dmxr);
+			keyp = XFS_BTREE_KEY_ADDR(xfs_bmbt, block, i);
 		}
 
 		if (prevp) {
@@ -6172,15 +6132,14 @@
 		if (root) {
 			pp = XFS_BMAP_BROOT_PTR_ADDR(block, i, sz);
 		} else {
-			pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
-				xfs_bmbt, block, i, dmxr);
+			pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, i, dmxr);
 		}
 		for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) {
 			if (root) {
 				thispa = XFS_BMAP_BROOT_PTR_ADDR(block, j, sz);
 			} else {
-				thispa = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
-					xfs_bmbt, block, j, dmxr);
+				thispa = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, j,
+							    dmxr);
 			}
 			if (*thispa == *pp) {
 				cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
@@ -6267,8 +6226,7 @@
 		 */
 
 		xfs_check_block(block, mp, 0, 0);
-		pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
-			1, mp->m_bmap_dmxr[1]);
+		pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
 		bno = be64_to_cpu(*pp);
 		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
 		if (bp_release) {
@@ -6305,11 +6263,9 @@
 		 * conform with the first entry in this one.
 		 */
 
-		ep = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
-			block, 1, mp->m_bmap_dmxr[0]);
+		ep = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
 		for (j = 1; j < num_recs; j++) {
-			nextp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
-				block, j + 1, mp->m_bmap_dmxr[0]);
+			nextp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, j + 1);
 			if (lastp) {
 				xfs_btree_check_rec(XFS_BTNUM_BMAP,
 					(void *)lastp, (void *)ep);
@@ -6454,8 +6410,7 @@
 		}
 
 		/* Dive to the next level */
-		pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
-			xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
+		pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
 		bno = be64_to_cpu(*pp);
 		if (unlikely((error =
 		     xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
@@ -6470,7 +6425,7 @@
 		for (;;) {
 			nextbno = be64_to_cpu(block->bb_rightsib);
 			numrecs = be16_to_cpu(block->bb_numrecs);
-			if (unlikely(xfs_bmap_disk_count_leaves(ifp, mp,
+			if (unlikely(xfs_bmap_disk_count_leaves(ifp,
 					0, block, numrecs, count) < 0)) {
 				xfs_trans_brelse(tp, bp);
 				XFS_ERROR_REPORT("xfs_bmap_count_tree(2)",
@@ -6518,7 +6473,6 @@
 int
 xfs_bmap_disk_count_leaves(
 	xfs_ifork_t		*ifp,
-	xfs_mount_t		*mp,
 	xfs_extnum_t		idx,
 	xfs_bmbt_block_t	*block,
 	int			numrecs,
@@ -6528,8 +6482,7 @@
 	xfs_bmbt_rec_t	*frp;
 
 	for (b = 1; b <= numrecs; b++) {
-		frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize,
-			xfs_bmbt, block, idx + b, mp->m_bmap_dmxr[0]);
+		frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, idx + b);
 		*count += xfs_bmbt_disk_get_blockcount(frp);
 	}
 	return 0;
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 80e9340..4f24c7e 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -202,7 +202,6 @@
 xfs_bmap_finish(
 	struct xfs_trans	**tp,		/* transaction pointer addr */
 	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
-	xfs_fsblock_t		firstblock,	/* controlled a.g. for allocs */
 	int			*committed);	/* xact committed or not */
 
 /*
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index a7b835b..0bf192f 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -678,47 +678,6 @@
 	return error;
 }
 
-#ifdef DEBUG
-/*
- * Get the data from the pointed-to record.
- */
-int
-xfs_bmbt_get_rec(
-	xfs_btree_cur_t		*cur,
-	xfs_fileoff_t		*off,
-	xfs_fsblock_t		*bno,
-	xfs_filblks_t		*len,
-	xfs_exntst_t		*state,
-	int			*stat)
-{
-	xfs_bmbt_block_t	*block;
-	xfs_buf_t		*bp;
-#ifdef DEBUG
-	int			error;
-#endif
-	int			ptr;
-	xfs_bmbt_rec_t		*rp;
-
-	block = xfs_bmbt_get_block(cur, 0, &bp);
-	ptr = cur->bc_ptrs[0];
-#ifdef DEBUG
-	if ((error = xfs_btree_check_lblock(cur, block, 0, bp)))
-		return error;
-#endif
-	if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) {
-		*stat = 0;
-		return 0;
-	}
-	rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
-	*off = xfs_bmbt_disk_get_startoff(rp);
-	*bno = xfs_bmbt_disk_get_startblock(rp);
-	*len = xfs_bmbt_disk_get_blockcount(rp);
-	*state = xfs_bmbt_disk_get_state(rp);
-	*stat = 1;
-	return 0;
-}
-#endif
-
 /*
  * Insert one record/level.  Return information to the caller
  * allowing the next level up to proceed if necessary.
@@ -1731,9 +1690,9 @@
 	rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO);
 	rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO);
 	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
-	fkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
+	fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1);
 	tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
-	fpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
+	fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr);
 	tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
 	dmxr = be16_to_cpu(dblock->bb_numrecs);
 	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
@@ -1862,7 +1821,7 @@
  * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state.
  */
 
-STATIC __inline__ void
+STATIC_INLINE void
 __xfs_bmbt_get_all(
 		__uint64_t l0,
 		__uint64_t l1,
@@ -2016,30 +1975,6 @@
 }
 
 /*
- * Extract the startblock field from an on disk bmap extent record.
- */
-xfs_fsblock_t
-xfs_bmbt_disk_get_startblock(
-	xfs_bmbt_rec_t	*r)
-{
-#if XFS_BIG_BLKNOS
-	return (((xfs_fsblock_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
-	       (((xfs_fsblock_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
-#else
-#ifdef DEBUG
-	xfs_dfsbno_t	b;
-
-	b = (((xfs_dfsbno_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
-	    (((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
-	ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
-	return (xfs_fsblock_t)b;
-#else	/* !DEBUG */
-	return (xfs_fsblock_t)(((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
-#endif	/* DEBUG */
-#endif	/* XFS_BIG_BLKNOS */
-}
-
-/*
  * Extract the startoff field from a disk format bmap extent record.
  */
 xfs_fileoff_t
@@ -2049,17 +1984,6 @@
 	return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) &
 		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
 }
-
-xfs_exntst_t
-xfs_bmbt_disk_get_state(
-	xfs_bmbt_rec_t  *r)
-{
-	int	ext_flag;
-
-	ext_flag = (int)((INT_GET(r->l0, ARCH_CONVERT)) >> (64 - BMBT_EXNTFLAG_BITLEN));
-	return xfs_extent_state(xfs_bmbt_disk_get_blockcount(r),
-				ext_flag);
-}
 #endif /* XFS_NATIVE_HOST */
 
 
@@ -2684,9 +2608,9 @@
 	dblock->bb_numrecs = rblock->bb_numrecs;
 	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
 	fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
-	tkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
+	tkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1);
 	fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
-	tpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
+	tpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr);
 	dmxr = be16_to_cpu(dblock->bb_numrecs);
 	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
 	memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 49539de..a77b1b7 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -175,19 +175,11 @@
 
 #define XFS_BUF_TO_BMBT_BLOCK(bp)	((xfs_bmbt_block_t *)XFS_BUF_PTR(bp))
 
-#define XFS_BMAP_IBLOCK_SIZE(lev,cur)	(1 << (cur)->bc_blocklog)
 #define XFS_BMAP_RBLOCK_DSIZE(lev,cur)	((cur)->bc_private.b.forksize)
 #define XFS_BMAP_RBLOCK_ISIZE(lev,cur)	\
 	((int)XFS_IFORK_PTR((cur)->bc_private.b.ip, \
 		    (cur)->bc_private.b.whichfork)->if_broot_bytes)
 
-#define XFS_BMAP_BLOCK_DSIZE(lev,cur)	\
-	(((lev) == (cur)->bc_nlevels - 1 ? \
-		XFS_BMAP_RBLOCK_DSIZE(lev,cur) : XFS_BMAP_IBLOCK_SIZE(lev,cur)))
-#define XFS_BMAP_BLOCK_ISIZE(lev,cur)	\
-	(((lev) == (cur)->bc_nlevels - 1 ? \
-		XFS_BMAP_RBLOCK_ISIZE(lev,cur) : XFS_BMAP_IBLOCK_SIZE(lev,cur)))
-
 #define XFS_BMAP_BLOCK_DMAXRECS(lev,cur) \
 	(((lev) == (cur)->bc_nlevels - 1 ? \
 		XFS_BTREE_BLOCK_MAXRECS(XFS_BMAP_RBLOCK_DSIZE(lev,cur), \
@@ -210,37 +202,21 @@
 				xfs_bmbt, (lev) == 0) : \
 			((cur)->bc_mp->m_bmap_dmnr[(lev) != 0])))
 
-#define XFS_BMAP_REC_DADDR(bb,i,cur)	\
-	(XFS_BTREE_REC_ADDR(XFS_BMAP_BLOCK_DSIZE(			\
-			be16_to_cpu((bb)->bb_level), cur),		\
-			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS(	\
-				be16_to_cpu((bb)->bb_level), cur)))
-#define XFS_BMAP_REC_IADDR(bb,i,cur)	\
-	(XFS_BTREE_REC_ADDR(XFS_BMAP_BLOCK_ISIZE(			\
-			be16_to_cpu((bb)->bb_level), cur),		\
-			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS(	\
-				be16_to_cpu((bb)->bb_level), cur)))
+#define XFS_BMAP_REC_DADDR(bb,i,cur)	(XFS_BTREE_REC_ADDR(xfs_bmbt, bb, i))
+
+#define XFS_BMAP_REC_IADDR(bb,i,cur)	(XFS_BTREE_REC_ADDR(xfs_bmbt, bb, i))
 
 #define XFS_BMAP_KEY_DADDR(bb,i,cur)	\
-	(XFS_BTREE_KEY_ADDR(XFS_BMAP_BLOCK_DSIZE(			\
-			be16_to_cpu((bb)->bb_level), cur),		\
-			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS(	\
-				be16_to_cpu((bb)->bb_level), cur)))
+	(XFS_BTREE_KEY_ADDR(xfs_bmbt, bb, i))
+
 #define XFS_BMAP_KEY_IADDR(bb,i,cur)	\
-	(XFS_BTREE_KEY_ADDR(XFS_BMAP_BLOCK_ISIZE(			\
-			be16_to_cpu((bb)->bb_level), cur),		\
-			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS(	\
-				be16_to_cpu((bb)->bb_level), cur)))
+	(XFS_BTREE_KEY_ADDR(xfs_bmbt, bb, i))
 
 #define XFS_BMAP_PTR_DADDR(bb,i,cur)	\
-	(XFS_BTREE_PTR_ADDR(XFS_BMAP_BLOCK_DSIZE(			\
-			be16_to_cpu((bb)->bb_level), cur),		\
-			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS(	\
+	(XFS_BTREE_PTR_ADDR(xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS(	\
 				be16_to_cpu((bb)->bb_level), cur)))
 #define XFS_BMAP_PTR_IADDR(bb,i,cur)	\
-	(XFS_BTREE_PTR_ADDR(XFS_BMAP_BLOCK_ISIZE(			\
-			be16_to_cpu((bb)->bb_level), cur),		\
-			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS(	\
+	(XFS_BTREE_PTR_ADDR(xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS(	\
 				be16_to_cpu((bb)->bb_level), cur)))
 
 /*
@@ -248,11 +224,11 @@
  * we don't have a cursor.
  */
 #define XFS_BMAP_BROOT_REC_ADDR(bb,i,sz) \
-	(XFS_BTREE_REC_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
+	(XFS_BTREE_REC_ADDR(xfs_bmbt,bb,i))
 #define XFS_BMAP_BROOT_KEY_ADDR(bb,i,sz) \
-	(XFS_BTREE_KEY_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
+	(XFS_BTREE_KEY_ADDR(xfs_bmbt,bb,i))
 #define XFS_BMAP_BROOT_PTR_ADDR(bb,i,sz) \
-	(XFS_BTREE_PTR_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
+	(XFS_BTREE_PTR_ADDR(xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
 
 #define XFS_BMAP_BROOT_NUMRECS(bb)	be16_to_cpu((bb)->bb_numrecs)
 #define XFS_BMAP_BROOT_MAXRECS(sz)	XFS_BTREE_BLOCK_MAXRECS(sz,xfs_bmbt,0)
@@ -315,15 +291,11 @@
 
 #ifndef XFS_NATIVE_HOST
 extern void xfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
-extern xfs_exntst_t xfs_bmbt_disk_get_state(xfs_bmbt_rec_t *r);
 extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r);
-extern xfs_fsblock_t xfs_bmbt_disk_get_startblock(xfs_bmbt_rec_t *r);
 extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r);
 #else
 #define xfs_bmbt_disk_get_all(r, s)	xfs_bmbt_get_all(r, s)
-#define xfs_bmbt_disk_get_state(r)	xfs_bmbt_get_state(r)
 #define xfs_bmbt_disk_get_blockcount(r)	xfs_bmbt_get_blockcount(r)
-#define xfs_bmbt_disk_get_startblock(r)	xfs_bmbt_get_blockcount(r)
 #define xfs_bmbt_disk_get_startoff(r)	xfs_bmbt_get_startoff(r)
 #endif /* XFS_NATIVE_HOST */
 
@@ -364,15 +336,6 @@
 extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t,
 				xfs_fsblock_t, xfs_filblks_t, xfs_exntst_t);
 
-#ifdef DEBUG
-/*
- * Get the data from the pointed-to record.
- */
-extern int xfs_bmbt_get_rec(struct xfs_btree_cur *, xfs_fileoff_t *,
-				xfs_fsblock_t *, xfs_filblks_t *,
-				xfs_exntst_t *, int *);
-#endif
-
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_BMAP_BTREE_H__ */
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 892b06c..4e27d55 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -122,13 +122,13 @@
  * Given block size, type prefix, block pointer, and index of requested entry
  * (first entry numbered 1).
  */
-#define	XFS_BTREE_REC_ADDR(bsz,t,bb,i,mxr)	\
+#define	XFS_BTREE_REC_ADDR(t,bb,i)	\
 	((t ## _rec_t *)((char *)(bb) + sizeof(t ## _block_t) + \
 	 ((i) - 1) * sizeof(t ## _rec_t)))
-#define	XFS_BTREE_KEY_ADDR(bsz,t,bb,i,mxr)	\
+#define	XFS_BTREE_KEY_ADDR(t,bb,i)	\
 	((t ## _key_t *)((char *)(bb) + sizeof(t ## _block_t) + \
 	 ((i) - 1) * sizeof(t ## _key_t)))
-#define	XFS_BTREE_PTR_ADDR(bsz,t,bb,i,mxr)	\
+#define	XFS_BTREE_PTR_ADDR(t,bb,i,mxr)	\
 	((t ## _ptr_t *)((char *)(bb) + sizeof(t ## _block_t) + \
 	 (mxr) * sizeof(t ## _key_t) + ((i) - 1) * sizeof(t ## _ptr_t)))
 
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 7a55c24..6c1bddc 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -660,7 +660,7 @@
 /*
  * This is the ops vector shared by all buf log items.
  */
-STATIC struct xfs_item_ops xfs_buf_item_ops = {
+static struct xfs_item_ops xfs_buf_item_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_buf_item_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_buf_item_format,
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 07c708c..d7e1361 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -21,23 +21,7 @@
 /*
  * This is the structure used to lay out a buf log item in the
  * log.  The data map describes which 128 byte chunks of the buffer
- * have been logged.  This structure works only on buffers that
- * reside up to the first TB in the filesystem.  These buffers are
- * generated only by pre-6.2 systems and are known as XFS_LI_6_1_BUF.
- */
-typedef struct xfs_buf_log_format_v1 {
-	unsigned short	blf_type;	/* buf log item type indicator */
-	unsigned short	blf_size;	/* size of this item */
-	__int32_t	blf_blkno;	/* starting blkno of this buf */
-	ushort		blf_flags;	/* misc state */
-	ushort		blf_len;	/* number of blocks in this buf */
-	unsigned int	blf_map_size;	/* size of data bitmap in words */
-	unsigned int	blf_data_map[1];/* variable size bitmap of */
-					/*   regions of buffer in this item */
-} xfs_buf_log_format_v1_t;
-
-/*
- * This is a form of the above structure with a 64 bit blkno field.
+ * have been logged.
  * For 6.2 and beyond, this is XFS_LI_BUF.  We use this to log everything.
  */
 typedef struct xfs_buf_log_format_t {
diff --git a/fs/xfs/xfs_cap.h b/fs/xfs/xfs_cap.h
deleted file mode 100644
index 7a0e482..0000000
--- a/fs/xfs/xfs_cap.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_CAP_H__
-#define __XFS_CAP_H__
-
-/*
- * Capabilities
- */
-typedef __uint64_t xfs_cap_value_t;
-
-typedef struct xfs_cap_set {
-	xfs_cap_value_t	cap_effective;	/* use in capability checks */
-	xfs_cap_value_t	cap_permitted;	/* combined with file attrs */
-	xfs_cap_value_t	cap_inheritable;/* pass through exec */
-} xfs_cap_set_t;
-
-/* On-disk XFS extended attribute names */
-#define SGI_CAP_FILE	"SGI_CAP_FILE"
-#define SGI_CAP_FILE_SIZE	(sizeof(SGI_CAP_FILE)-1)
-#define SGI_CAP_LINUX	"SGI_CAP_LINUX"
-#define SGI_CAP_LINUX_SIZE	(sizeof(SGI_CAP_LINUX)-1)
-
-/*
- * For Linux, we take the bitfields directly from capability.h
- * and no longer attempt to keep this attribute ondisk compatible
- * with IRIX.  Since this attribute is only set on executables,
- * it just doesn't make much sense to try.  We do use a different
- * named attribute though, to avoid confusion.
- */
-
-#ifdef __KERNEL__
-
-#ifdef CONFIG_FS_POSIX_CAP
-
-#include <linux/posix_cap_xattr.h>
-
-struct bhv_vnode;
-
-extern int xfs_cap_vhascap(struct bhv_vnode *);
-extern int xfs_cap_vset(struct bhv_vnode *, void *, size_t);
-extern int xfs_cap_vget(struct bhv_vnode *, void *, size_t);
-extern int xfs_cap_vremove(struct bhv_vnode *);
-
-#define _CAP_EXISTS		xfs_cap_vhascap
-
-#else
-#define xfs_cap_vset(v,p,sz)	(-EOPNOTSUPP)
-#define xfs_cap_vget(v,p,sz)	(-EOPNOTSUPP)
-#define xfs_cap_vremove(v)	(-EOPNOTSUPP)
-#define _CAP_EXISTS		(NULL)
-#endif
-
-#endif	/* __KERNEL__ */
-
-#endif  /* __XFS_CAP_H__ */
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index a68bc1f1..aea37df 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -1090,8 +1090,7 @@
 		if (blk->magic == XFS_DA_NODE_MAGIC) {
 			node = blk->bp->data;
 			max = be16_to_cpu(node->hdr.count);
-			btreehashval = node->btree[max-1].hashval;
-			blk->hashval = be32_to_cpu(btreehashval);
+			blk->hashval = be32_to_cpu(node->btree[max-1].hashval);
 
 			/*
 			 * Binary search.  (note: small blocks will skip loop)
@@ -2166,21 +2165,6 @@
 		return rval;
 }
 
-/*
- * Calculate the number of bits needed to hold i different values.
- */
-uint
-xfs_da_log2_roundup(uint i)
-{
-	uint rval;
-
-	for (rval = 0; rval < NBBY * sizeof(i); rval++) {
-		if ((1 << rval) >= i)
-			break;
-	}
-	return(rval);
-}
-
 kmem_zone_t *xfs_da_state_zone;	/* anchor for state struct zone */
 kmem_zone_t *xfs_dabuf_zone;		/* dabuf zone */
 
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 4ab865e..44dabf0 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -249,7 +249,6 @@
 					  xfs_dabuf_t *dead_buf);
 
 uint xfs_da_hashname(const uchar_t *name_string, int name_length);
-uint xfs_da_log2_roundup(uint i);
 xfs_da_state_t *xfs_da_state_alloc(void);
 void xfs_da_state_free(xfs_da_state_t *state);
 
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 50d0fae..b847e6a 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -41,7 +41,6 @@
 #include "xfs_itable.h"
 #include "xfs_dfrag.h"
 #include "xfs_error.h"
-#include "xfs_mac.h"
 #include "xfs_rw.h"
 
 /*
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index b95681b..b1af544 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -132,32 +132,6 @@
 }
 
 int
-xfs_errortag_clear(int error_tag, xfs_mount_t *mp)
-{
-	int i;
-	int64_t fsid;
-
-	memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
-
-	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
-		if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
-			xfs_etest[i] = 0;
-			xfs_etest_fsid[i] = 0LL;
-			kmem_free(xfs_etest_fsname[i],
-				  strlen(xfs_etest_fsname[i]) + 1);
-			xfs_etest_fsname[i] = NULL;
-			cmn_err(CE_WARN, "Cleared XFS error tag #%d",
-				error_tag);
-			return 0;
-		}
-	}
-
-	cmn_err(CE_WARN, "XFS error tag %d not on", error_tag);
-
-	return 1;
-}
-
-int
 xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud)
 {
 	int i;
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 0893e16..5599ada 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -144,7 +144,6 @@
 #endif /* __ANSI_CPP__ */
 
 extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp);
-extern int xfs_errortag_clear(int error_tag, xfs_mount_t *mp);
 extern int xfs_errortag_clearall(xfs_mount_t *mp);
 extern int xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud);
 #else
@@ -180,6 +179,6 @@
 	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)
+	((f & XFS_MFSI_QUIET)? (void)0 : cmn_err(CE_WARN, "XFS: " fmt, ## args))
 
 #endif	/* __XFS_ERROR_H__ */
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 6dba781..3b14427 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -227,7 +227,7 @@
 /*
  * This is the ops vector shared by all efi log items.
  */
-STATIC struct xfs_item_ops xfs_efi_item_ops = {
+static struct xfs_item_ops xfs_efi_item_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_efi_item_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_efi_item_format,
@@ -525,7 +525,7 @@
 /*
  * This is the ops vector shared by all efd log items.
  */
-STATIC struct xfs_item_ops xfs_efd_item_ops = {
+static struct xfs_item_ops xfs_efd_item_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_efd_item_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_efd_item_format,
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index c064e72..32c37c1 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -250,8 +250,7 @@
 		block->bb_numrecs = cpu_to_be16(1);
 		block->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
 		block->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
-		arec = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_alloc,
-			block, 1, mp->m_alloc_mxr[0]);
+		arec = XFS_BTREE_REC_ADDR(xfs_alloc, block, 1);
 		arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
 		arec->ar_blockcount = cpu_to_be32(
 			agsize - be32_to_cpu(arec->ar_startblock));
@@ -272,8 +271,7 @@
 		block->bb_numrecs = cpu_to_be16(1);
 		block->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
 		block->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
-		arec = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_alloc,
-			block, 1, mp->m_alloc_mxr[0]);
+		arec = XFS_BTREE_REC_ADDR(xfs_alloc, block, 1);
 		arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
 		arec->ar_blockcount = cpu_to_be32(
 			agsize - be32_to_cpu(arec->ar_startblock));
@@ -460,7 +458,7 @@
 {
 	unsigned long	s;
 
-	xfs_icsb_sync_counters_lazy(mp);
+	xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
 	s = XFS_SB_LOCK(mp);
 	cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
 	cnt->freertx = mp->m_sb.sb_frextents;
@@ -491,7 +489,7 @@
 	__uint64_t              *inval,
 	xfs_fsop_resblks_t      *outval)
 {
-	__int64_t		lcounter, delta;
+	__int64_t		lcounter, delta, fdblks_delta;
 	__uint64_t		request;
 	unsigned long		s;
 
@@ -504,17 +502,35 @@
 	}
 
 	request = *inval;
+
+	/*
+	 * With per-cpu counters, this becomes an interesting
+	 * problem. we needto work out if we are freeing or allocation
+	 * blocks first, then we can do the modification as necessary.
+	 *
+	 * We do this under the XFS_SB_LOCK so that if we are near
+	 * ENOSPC, we will hold out any changes while we work out
+	 * what to do. This means that the amount of free space can
+	 * change while we do this, so we need to retry if we end up
+	 * trying to reserve more space than is available.
+	 *
+	 * We also use the xfs_mod_incore_sb() interface so that we
+	 * don't have to care about whether per cpu counter are
+	 * enabled, disabled or even compiled in....
+	 */
+retry:
 	s = XFS_SB_LOCK(mp);
+	xfs_icsb_sync_counters_flags(mp, XFS_ICSB_SB_LOCKED);
 
 	/*
 	 * If our previous reservation was larger than the current value,
 	 * then move any unused blocks back to the free pool.
 	 */
-
+	fdblks_delta = 0;
 	if (mp->m_resblks > request) {
 		lcounter = mp->m_resblks_avail - request;
 		if (lcounter  > 0) {		/* release unused blocks */
-			mp->m_sb.sb_fdblocks += lcounter;
+			fdblks_delta = lcounter;
 			mp->m_resblks_avail -= lcounter;
 		}
 		mp->m_resblks = request;
@@ -522,24 +538,50 @@
 		__int64_t	free;
 
 		free =  mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+		if (!free)
+			goto out; /* ENOSPC and fdblks_delta = 0 */
+
 		delta = request - mp->m_resblks;
 		lcounter = free - delta;
 		if (lcounter < 0) {
 			/* We can't satisfy the request, just get what we can */
 			mp->m_resblks += free;
 			mp->m_resblks_avail += free;
+			fdblks_delta = -free;
 			mp->m_sb.sb_fdblocks = XFS_ALLOC_SET_ASIDE(mp);
 		} else {
+			fdblks_delta = -delta;
 			mp->m_sb.sb_fdblocks =
 				lcounter + XFS_ALLOC_SET_ASIDE(mp);
 			mp->m_resblks = request;
 			mp->m_resblks_avail += delta;
 		}
 	}
-
+out:
 	outval->resblks = mp->m_resblks;
 	outval->resblks_avail = mp->m_resblks_avail;
 	XFS_SB_UNLOCK(mp, s);
+
+	if (fdblks_delta) {
+		/*
+		 * If we are putting blocks back here, m_resblks_avail is
+		 * already at it's max so this will put it in the free pool.
+		 *
+		 * If we need space, we'll either succeed in getting it
+		 * from the free block count or we'll get an enospc. If
+		 * we get a ENOSPC, it means things changed while we were
+		 * calculating fdblks_delta and so we should try again to
+		 * see if there is anything left to reserve.
+		 *
+		 * Don't set the reserved flag here - we don't want to reserve
+		 * the extra reserve blocks from the reserve.....
+		 */
+		int error;
+		error = xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, fdblks_delta, 0);
+		if (error == ENOSPC)
+			goto retry;
+	}
+
 	return 0;
 }
 
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index a446e5a..b5feb3e 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -342,7 +342,7 @@
 	return 0;
 }
 
-STATIC __inline xfs_agnumber_t
+STATIC_INLINE xfs_agnumber_t
 xfs_ialloc_next_ag(
 	xfs_mount_t	*mp)
 {
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index 2c0e498..bf8e9af 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -89,7 +89,6 @@
 /*
  * Real block structures have a size equal to the disk block size.
  */
-#define	XFS_INOBT_BLOCK_SIZE(lev,cur)	(1 << (cur)->bc_blocklog)
 #define	XFS_INOBT_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_inobt_mxr[lev != 0])
 #define	XFS_INOBT_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_inobt_mnr[lev != 0])
 #define	XFS_INOBT_IS_LAST_REC(cur)	\
@@ -110,14 +109,13 @@
  * Record, key, and pointer address macros for btree blocks.
  */
 #define XFS_INOBT_REC_ADDR(bb,i,cur) \
-	(XFS_BTREE_REC_ADDR(XFS_INOBT_BLOCK_SIZE(0,cur), xfs_inobt, bb, \
-				i, XFS_INOBT_BLOCK_MAXRECS(0, cur)))
+	(XFS_BTREE_REC_ADDR(xfs_inobt, bb, i))
+
 #define	XFS_INOBT_KEY_ADDR(bb,i,cur) \
-	(XFS_BTREE_KEY_ADDR(XFS_INOBT_BLOCK_SIZE(1,cur), xfs_inobt, bb, \
-				i, XFS_INOBT_BLOCK_MAXRECS(1, cur)))
+	(XFS_BTREE_KEY_ADDR(xfs_inobt, bb, i))
 
 #define	XFS_INOBT_PTR_ADDR(bb,i,cur) \
-	(XFS_BTREE_PTR_ADDR(XFS_INOBT_BLOCK_SIZE(1,cur), xfs_inobt, bb, \
+	(XFS_BTREE_PTR_ADDR(xfs_inobt, bb, \
 				i, XFS_INOBT_BLOCK_MAXRECS(1, cur)))
 
 /*
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 44dfac5..3da9829 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -47,7 +47,6 @@
 #include "xfs_utils.h"
 #include "xfs_dir2_trace.h"
 #include "xfs_quota.h"
-#include "xfs_mac.h"
 #include "xfs_acl.h"
 
 
@@ -1699,8 +1698,7 @@
 		 * Duplicate the transaction that has the permanent
 		 * reservation and commit the old transaction.
 		 */
-		error = xfs_bmap_finish(tp, &free_list, first_block,
-					&committed);
+		error = xfs_bmap_finish(tp, &free_list, &committed);
 		ntp = *tp;
 		if (error) {
 			/*
@@ -1810,7 +1808,7 @@
 	 * and any blocks between the old and new file sizes.
 	 */
 	error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size,
-			     ip->i_d.di_size, new_size);
+			     ip->i_d.di_size);
 	return error;
 }
 
@@ -2125,7 +2123,7 @@
 	return 0;
 }
 
-static __inline__ int xfs_inode_clean(xfs_inode_t *ip)
+STATIC_INLINE int xfs_inode_clean(xfs_inode_t *ip)
 {
 	return (((ip->i_itemp == NULL) ||
 		!(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL)) &&
@@ -2707,10 +2705,24 @@
 	ktrace_free(ip->i_dir_trace);
 #endif
 	if (ip->i_itemp) {
-		/* XXXdpd should be able to assert this but shutdown
-		 * is leaving the AIL behind. */
-		ASSERT(((ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL) == 0) ||
-		       XFS_FORCED_SHUTDOWN(ip->i_mount));
+		/*
+		 * Only if we are shutting down the fs will we see an
+		 * inode still in the AIL. If it is there, we should remove
+		 * it to prevent a use-after-free from occurring.
+		 */
+		xfs_mount_t	*mp = ip->i_mount;
+		xfs_log_item_t	*lip = &ip->i_itemp->ili_item;
+		int		s;
+
+		ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
+				       XFS_FORCED_SHUTDOWN(ip->i_mount));
+		if (lip->li_flags & XFS_LI_IN_AIL) {
+			AIL_LOCK(mp, s);
+			if (lip->li_flags & XFS_LI_IN_AIL)
+				xfs_trans_delete_ail(mp, lip, s);
+			else
+				AIL_UNLOCK(mp, s);
+		}
 		xfs_inode_item_destroy(ip);
 	}
 	kmem_zone_free(xfs_inode_zone, ip);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index a7a9225..565d470 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -887,7 +887,7 @@
 /*
  * This is the ops vector shared by all buf log items.
  */
-STATIC struct xfs_item_ops xfs_inode_item_ops = {
+static struct xfs_item_ops xfs_inode_item_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_inode_item_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_inode_item_format,
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 1965512..cc6a7b5 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -43,8 +43,6 @@
 #include "xfs_itable.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_trans_space.h"
@@ -542,7 +540,7 @@
 	/*
 	 * Complete the transaction
 	 */
-	error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
+	error = xfs_bmap_finish(&tp, &free_list, &committed);
 	if (error)
 		goto error0;
 	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
@@ -838,8 +836,7 @@
 			if (error)
 				goto trans_cancel;
 
-			error = xfs_bmap_finish(&tp, &free_list,
-					first_block, &committed);
+			error = xfs_bmap_finish(&tp, &free_list, &committed);
 			if (error)
 				goto trans_cancel;
 
@@ -947,8 +944,7 @@
 		if (error)
 			goto error_on_bmapi_transaction;
 
-		error = xfs_bmap_finish(&(tp), &(free_list),
-				firstfsb, &committed);
+		error = xfs_bmap_finish(&(tp), &(free_list), &committed);
 		if (error)
 			goto error_on_bmapi_transaction;
 
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 3cb678e..ca74d3f 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1514,7 +1514,6 @@
 {
 	xlog_recover_item_t	*first_item, *itemq, *itemq_next;
 	xfs_buf_log_format_t	*buf_f;
-	xfs_buf_log_format_v1_t	*obuf_f;
 	ushort			flags = 0;
 
 	first_item = itemq = trans->r_itemq;
@@ -1522,29 +1521,16 @@
 	do {
 		itemq_next = itemq->ri_next;
 		buf_f = (xfs_buf_log_format_t *)itemq->ri_buf[0].i_addr;
-		switch (ITEM_TYPE(itemq)) {
-		case XFS_LI_BUF:
-			flags = buf_f->blf_flags;
-			break;
-		case XFS_LI_6_1_BUF:
-		case XFS_LI_5_3_BUF:
-			obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-			flags = obuf_f->blf_flags;
-			break;
-		}
 
 		switch (ITEM_TYPE(itemq)) {
 		case XFS_LI_BUF:
-		case XFS_LI_6_1_BUF:
-		case XFS_LI_5_3_BUF:
+			flags = buf_f->blf_flags;
 			if (!(flags & XFS_BLI_CANCEL)) {
 				xlog_recover_insert_item_frontq(&trans->r_itemq,
 								itemq);
 				break;
 			}
 		case XFS_LI_INODE:
-		case XFS_LI_6_1_INODE:
-		case XFS_LI_5_3_INODE:
 		case XFS_LI_DQUOT:
 		case XFS_LI_QUOTAOFF:
 		case XFS_LI_EFD:
@@ -1583,7 +1569,6 @@
 	xfs_buf_cancel_t	*nextp;
 	xfs_buf_cancel_t	*prevp;
 	xfs_buf_cancel_t	**bucket;
-	xfs_buf_log_format_v1_t	*obuf_f;
 	xfs_daddr_t		blkno = 0;
 	uint			len = 0;
 	ushort			flags = 0;
@@ -1594,13 +1579,6 @@
 		len = buf_f->blf_len;
 		flags = buf_f->blf_flags;
 		break;
-	case XFS_LI_6_1_BUF:
-	case XFS_LI_5_3_BUF:
-		obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-		blkno = (xfs_daddr_t) obuf_f->blf_blkno;
-		len = obuf_f->blf_len;
-		flags = obuf_f->blf_flags;
-		break;
 	}
 
 	/*
@@ -1746,7 +1724,6 @@
 	xlog_t			*log,
 	xfs_buf_log_format_t	*buf_f)
 {
-	xfs_buf_log_format_v1_t	*obuf_f;
 	xfs_daddr_t		blkno = 0;
 	ushort			flags = 0;
 	uint			len = 0;
@@ -1757,13 +1734,6 @@
 		flags = buf_f->blf_flags;
 		len = buf_f->blf_len;
 		break;
-	case XFS_LI_6_1_BUF:
-	case XFS_LI_5_3_BUF:
-		obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-		blkno = (xfs_daddr_t) obuf_f->blf_blkno;
-		flags = obuf_f->blf_flags;
-		len = (xfs_daddr_t) obuf_f->blf_len;
-		break;
 	}
 
 	return xlog_check_buffer_cancelled(log, blkno, len, flags);
@@ -1799,7 +1769,6 @@
 	int			inodes_per_buf;
 	xfs_agino_t		*logged_nextp;
 	xfs_agino_t		*buffer_nextp;
-	xfs_buf_log_format_v1_t	*obuf_f;
 	unsigned int		*data_map = NULL;
 	unsigned int		map_size = 0;
 
@@ -1808,12 +1777,6 @@
 		data_map = buf_f->blf_data_map;
 		map_size = buf_f->blf_map_size;
 		break;
-	case XFS_LI_6_1_BUF:
-	case XFS_LI_5_3_BUF:
-		obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-		data_map = obuf_f->blf_data_map;
-		map_size = obuf_f->blf_map_size;
-		break;
 	}
 	/*
 	 * Set the variables corresponding to the current region to
@@ -1912,7 +1875,6 @@
 	int			i;
 	int			bit;
 	int			nbits;
-	xfs_buf_log_format_v1_t	*obuf_f;
 	unsigned int		*data_map = NULL;
 	unsigned int		map_size = 0;
 	int                     error;
@@ -1922,12 +1884,6 @@
 		data_map = buf_f->blf_data_map;
 		map_size = buf_f->blf_map_size;
 		break;
-	case XFS_LI_6_1_BUF:
-	case XFS_LI_5_3_BUF:
-		obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-		data_map = obuf_f->blf_data_map;
-		map_size = obuf_f->blf_map_size;
-		break;
 	}
 	bit = 0;
 	i = 1;  /* 0 is the buf format structure */
@@ -2160,7 +2116,6 @@
 	int			pass)
 {
 	xfs_buf_log_format_t	*buf_f;
-	xfs_buf_log_format_v1_t	*obuf_f;
 	xfs_mount_t		*mp;
 	xfs_buf_t		*bp;
 	int			error;
@@ -2197,13 +2152,6 @@
 		len = buf_f->blf_len;
 		flags = buf_f->blf_flags;
 		break;
-	case XFS_LI_6_1_BUF:
-	case XFS_LI_5_3_BUF:
-		obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
-		blkno = obuf_f->blf_blkno;
-		len = obuf_f->blf_len;
-		flags = obuf_f->blf_flags;
-		break;
 	default:
 		xfs_fs_cmn_err(CE_ALERT, log->l_mp,
 			"xfs_log_recover: unknown buffer type 0x%x, logdev %s",
@@ -2830,9 +2778,7 @@
 		 * where xfs_daddr_t is 32-bits but mount will warn us
 		 * off a > 1 TB filesystem before we get here.
 		 */
-		if ((ITEM_TYPE(item) == XFS_LI_BUF) ||
-		    (ITEM_TYPE(item) == XFS_LI_6_1_BUF) ||
-		    (ITEM_TYPE(item) == XFS_LI_5_3_BUF)) {
+		if ((ITEM_TYPE(item) == XFS_LI_BUF)) {
 			if  ((error = xlog_recover_do_buffer_trans(log, item,
 								 pass)))
 				break;
@@ -3902,6 +3848,9 @@
 	ASSERT(XFS_SB_GOOD_VERSION(sbp));
 	xfs_buf_relse(bp);
 
+	/* We've re-read the superblock so re-initialize per-cpu counters */
+	xfs_icsb_reinit_counters(log->l_mp);
+
 	xlog_recover_check_summary(log);
 
 	/* Normal transactions can now occur */
diff --git a/fs/xfs/xfs_mac.h b/fs/xfs/xfs_mac.h
deleted file mode 100644
index 18e0e98..0000000
--- a/fs/xfs/xfs_mac.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2001-2002,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_MAC_H__
-#define __XFS_MAC_H__
-
-/*
- * Mandatory Access Control
- *
- * Layout of a composite MAC label:
- * ml_list contains the list of categories (MSEN) followed by the list of
- * divisions (MINT). This is actually a header for the data structure which
- * will have an ml_list with more than one element.
- *
- *      -------------------------------
- *      | ml_msen_type | ml_mint_type |
- *      -------------------------------
- *      | ml_level     | ml_grade     |
- *      -------------------------------
- *      | ml_catcount                 |
- *      -------------------------------
- *      | ml_divcount                 |
- *      -------------------------------
- *      | category 1                  |
- *      | . . .                       |
- *      | category N                  | (where N = ml_catcount)
- *      -------------------------------
- *      | division 1                  |
- *      | . . .                       |
- *      | division M                  | (where M = ml_divcount)
- *      -------------------------------
- */
-#define XFS_MAC_MAX_SETS	250
-typedef struct xfs_mac_label {
-	__uint8_t	ml_msen_type;	/* MSEN label type */
-	__uint8_t	ml_mint_type;	/* MINT label type */
-	__uint8_t	ml_level;	/* Hierarchical level */
-	__uint8_t	ml_grade;	/* Hierarchical grade */
-	__uint16_t	ml_catcount;	/* Category count */
-	__uint16_t	ml_divcount;	/* Division count */
-					/* Category set, then Division set */
-	__uint16_t	ml_list[XFS_MAC_MAX_SETS];
-} xfs_mac_label_t;
-
-/* MSEN label type names. Choose an upper case ASCII character.  */
-#define XFS_MSEN_ADMIN_LABEL	'A'	/* Admin: low<admin != tcsec<high */
-#define XFS_MSEN_EQUAL_LABEL	'E'	/* Wildcard - always equal */
-#define XFS_MSEN_HIGH_LABEL	'H'	/* System High - always dominates */
-#define XFS_MSEN_MLD_HIGH_LABEL	'I'	/* System High, multi-level dir */
-#define XFS_MSEN_LOW_LABEL	'L'	/* System Low - always dominated */
-#define XFS_MSEN_MLD_LABEL	'M'	/* TCSEC label on a multi-level dir */
-#define XFS_MSEN_MLD_LOW_LABEL	'N'	/* System Low, multi-level dir */
-#define XFS_MSEN_TCSEC_LABEL	'T'	/* TCSEC label */
-#define XFS_MSEN_UNKNOWN_LABEL	'U'	/* unknown label */
-
-/* MINT label type names. Choose a lower case ASCII character.  */
-#define XFS_MINT_BIBA_LABEL	'b'	/* Dual of a TCSEC label */
-#define XFS_MINT_EQUAL_LABEL	'e'	/* Wildcard - always equal */
-#define XFS_MINT_HIGH_LABEL	'h'	/* High Grade - always dominates */
-#define XFS_MINT_LOW_LABEL	'l'	/* Low Grade - always dominated */
-
-/* On-disk XFS extended attribute names */
-#define SGI_MAC_FILE	"SGI_MAC_FILE"
-#define SGI_MAC_FILE_SIZE	(sizeof(SGI_MAC_FILE)-1)
-
-
-#ifdef __KERNEL__
-
-#ifdef CONFIG_FS_POSIX_MAC
-
-/* NOT YET IMPLEMENTED */
-
-#define MACEXEC		00100
-#define MACWRITE	00200
-#define MACREAD		00400
-
-struct xfs_inode;
-extern int  xfs_mac_iaccess(struct xfs_inode *, mode_t, cred_t *);
-
-#define _MAC_XFS_IACCESS(i,m,c) (xfs_mac_iaccess(i,m,c))
-#define _MAC_VACCESS(v,c,m)	(xfs_mac_vaccess(v,c,m))
-#define _MAC_EXISTS		xfs_mac_vhaslabel
-
-#else
-#define _MAC_XFS_IACCESS(i,m,c)	(0)
-#define _MAC_VACCESS(v,c,m)	(0)
-#define _MAC_EXISTS		(NULL)
-#endif
-
-#endif	/* __KERNEL__ */
-
-#endif	/* __XFS_MAC_H__ */
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 9dfae18..3bed0cf0 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -52,21 +52,19 @@
 
 #ifdef HAVE_PERCPU_SB
 STATIC void	xfs_icsb_destroy_counters(xfs_mount_t *);
-STATIC void	xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, int);
+STATIC void	xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
+						int, int);
 STATIC void	xfs_icsb_sync_counters(xfs_mount_t *);
 STATIC int	xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t,
-						int, int);
-STATIC int	xfs_icsb_modify_counters_locked(xfs_mount_t *, xfs_sb_field_t,
-						int, int);
+						int64_t, int);
 STATIC int	xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
 
 #else
 
 #define xfs_icsb_destroy_counters(mp)			do { } while (0)
-#define xfs_icsb_balance_counter(mp, a, b)		do { } while (0)
+#define xfs_icsb_balance_counter(mp, a, b, c)		do { } while (0)
 #define xfs_icsb_sync_counters(mp)			do { } while (0)
 #define xfs_icsb_modify_counters(mp, a, b, c)		do { } while (0)
-#define xfs_icsb_modify_counters_locked(mp, a, b, c)	do { } while (0)
 
 #endif
 
@@ -545,9 +543,8 @@
 		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
 	}
 
-	xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
-	xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
-	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
+	/* Initialize per-cpu counters */
+	xfs_icsb_reinit_counters(mp);
 
 	mp->m_sb_bp = bp;
 	xfs_buf_relse(bp);
@@ -1254,8 +1251,11 @@
  * The SB_LOCK must be held when this routine is called.
  */
 int
-xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
-			int delta, int rsvd)
+xfs_mod_incore_sb_unlocked(
+	xfs_mount_t	*mp,
+	xfs_sb_field_t	field,
+	int64_t		delta,
+	int		rsvd)
 {
 	int		scounter;	/* short counter for 32 bit fields */
 	long long	lcounter;	/* long counter for 64 bit fields */
@@ -1287,7 +1287,6 @@
 		mp->m_sb.sb_ifree = lcounter;
 		return 0;
 	case XFS_SBS_FDBLOCKS:
-
 		lcounter = (long long)
 			mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
 		res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
@@ -1418,7 +1417,11 @@
  * routine to do the work.
  */
 int
-xfs_mod_incore_sb(xfs_mount_t *mp, xfs_sb_field_t field, int delta, int rsvd)
+xfs_mod_incore_sb(
+	xfs_mount_t	*mp,
+	xfs_sb_field_t	field,
+	int64_t		delta,
+	int		rsvd)
 {
 	unsigned long	s;
 	int	status;
@@ -1485,9 +1488,11 @@
 		case XFS_SBS_IFREE:
 		case XFS_SBS_FDBLOCKS:
 			if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
-				status = xfs_icsb_modify_counters_locked(mp,
+				XFS_SB_UNLOCK(mp, s);
+				status = xfs_icsb_modify_counters(mp,
 							msbp->msb_field,
 							msbp->msb_delta, rsvd);
+				s = XFS_SB_LOCK(mp);
 				break;
 			}
 			/* FALLTHROUGH */
@@ -1521,11 +1526,12 @@
 			case XFS_SBS_IFREE:
 			case XFS_SBS_FDBLOCKS:
 				if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
-					status =
-					    xfs_icsb_modify_counters_locked(mp,
+					XFS_SB_UNLOCK(mp, s);
+					status = xfs_icsb_modify_counters(mp,
 							msbp->msb_field,
 							-(msbp->msb_delta),
 							rsvd);
+					s = XFS_SB_LOCK(mp);
 					break;
 				}
 				/* FALLTHROUGH */
@@ -1733,14 +1739,17 @@
 		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
 		break;
 	case CPU_ONLINE:
-		xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
-		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
-		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
+		xfs_icsb_lock(mp);
+		xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0);
+		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0);
+		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0, 0);
+		xfs_icsb_unlock(mp);
 		break;
 	case CPU_DEAD:
 		/* Disable all the counters, then fold the dead cpu's
 		 * count into the total on the global superblock and
 		 * re-enable the counters. */
+		xfs_icsb_lock(mp);
 		s = XFS_SB_LOCK(mp);
 		xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
 		xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
@@ -1752,10 +1761,14 @@
 
 		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
 
-		xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED);
-		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED);
-		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, XFS_ICSB_SB_LOCKED);
+		xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT,
+					 XFS_ICSB_SB_LOCKED, 0);
+		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE,
+					 XFS_ICSB_SB_LOCKED, 0);
+		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS,
+					 XFS_ICSB_SB_LOCKED, 0);
 		XFS_SB_UNLOCK(mp, s);
+		xfs_icsb_unlock(mp);
 		break;
 	}
 
@@ -1784,6 +1797,9 @@
 		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
 		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
 	}
+
+	mutex_init(&mp->m_icsb_mutex);
+
 	/*
 	 * start with all counters disabled so that the
 	 * initial balance kicks us off correctly
@@ -1792,6 +1808,22 @@
 	return 0;
 }
 
+void
+xfs_icsb_reinit_counters(
+	xfs_mount_t	*mp)
+{
+	xfs_icsb_lock(mp);
+	/*
+	 * start with all counters disabled so that the
+	 * initial balance kicks us off correctly
+	 */
+	mp->m_icsb_counters = -1;
+	xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0);
+	xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0);
+	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0, 0);
+	xfs_icsb_unlock(mp);
+}
+
 STATIC void
 xfs_icsb_destroy_counters(
 	xfs_mount_t	*mp)
@@ -1800,9 +1832,10 @@
 		unregister_hotcpu_notifier(&mp->m_icsb_notifier);
 		free_percpu(mp->m_sb_cnts);
 	}
+	mutex_destroy(&mp->m_icsb_mutex);
 }
 
-STATIC inline void
+STATIC_INLINE void
 xfs_icsb_lock_cntr(
 	xfs_icsb_cnts_t	*icsbp)
 {
@@ -1811,7 +1844,7 @@
 	}
 }
 
-STATIC inline void
+STATIC_INLINE void
 xfs_icsb_unlock_cntr(
 	xfs_icsb_cnts_t	*icsbp)
 {
@@ -1819,7 +1852,7 @@
 }
 
 
-STATIC inline void
+STATIC_INLINE void
 xfs_icsb_lock_all_counters(
 	xfs_mount_t	*mp)
 {
@@ -1832,7 +1865,7 @@
 	}
 }
 
-STATIC inline void
+STATIC_INLINE void
 xfs_icsb_unlock_all_counters(
 	xfs_mount_t	*mp)
 {
@@ -1888,6 +1921,17 @@
 
 	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
 
+	/*
+	 * If we are already disabled, then there is nothing to do
+	 * here. We check before locking all the counters to avoid
+	 * the expensive lock operation when being called in the
+	 * slow path and the counter is already disabled. This is
+	 * safe because the only time we set or clear this state is under
+	 * the m_icsb_mutex.
+	 */
+	if (xfs_icsb_counter_disabled(mp, field))
+		return 0;
+
 	xfs_icsb_lock_all_counters(mp);
 	if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
 		/* drain back to superblock */
@@ -1948,8 +1992,8 @@
 	xfs_icsb_unlock_all_counters(mp);
 }
 
-STATIC void
-xfs_icsb_sync_counters_int(
+void
+xfs_icsb_sync_counters_flags(
 	xfs_mount_t	*mp,
 	int		flags)
 {
@@ -1981,40 +2025,39 @@
 xfs_icsb_sync_counters(
 	xfs_mount_t	*mp)
 {
-	xfs_icsb_sync_counters_int(mp, 0);
-}
-
-/*
- * lazy addition used for things like df, background sb syncs, etc
- */
-void
-xfs_icsb_sync_counters_lazy(
-	xfs_mount_t	*mp)
-{
-	xfs_icsb_sync_counters_int(mp, XFS_ICSB_LAZY_COUNT);
+	xfs_icsb_sync_counters_flags(mp, 0);
 }
 
 /*
  * Balance and enable/disable counters as necessary.
  *
- * Thresholds for re-enabling counters are somewhat magic.
- * inode counts are chosen to be the same number as single
- * on disk allocation chunk per CPU, and free blocks is
- * something far enough zero that we aren't going thrash
- * when we get near ENOSPC.
+ * Thresholds for re-enabling counters are somewhat magic.  inode counts are
+ * chosen to be the same number as single on disk allocation chunk per CPU, and
+ * free blocks is something far enough zero that we aren't going thrash when we
+ * get near ENOSPC. We also need to supply a minimum we require per cpu to
+ * prevent looping endlessly when xfs_alloc_space asks for more than will
+ * be distributed to a single CPU but each CPU has enough blocks to be
+ * reenabled.
+ *
+ * Note that we can be called when counters are already disabled.
+ * xfs_icsb_disable_counter() optimises the counter locking in this case to
+ * prevent locking every per-cpu counter needlessly.
  */
-#define XFS_ICSB_INO_CNTR_REENABLE	64
+
+#define XFS_ICSB_INO_CNTR_REENABLE	(uint64_t)64
 #define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
-		(512 + XFS_ALLOC_SET_ASIDE(mp))
+		(uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
 STATIC void
 xfs_icsb_balance_counter(
 	xfs_mount_t	*mp,
 	xfs_sb_field_t  field,
-	int		flags)
+	int		flags,
+	int		min_per_cpu)
 {
 	uint64_t	count, resid;
 	int		weight = num_online_cpus();
 	int		s;
+	uint64_t	min = (uint64_t)min_per_cpu;
 
 	if (!(flags & XFS_ICSB_SB_LOCKED))
 		s = XFS_SB_LOCK(mp);
@@ -2027,19 +2070,19 @@
 	case XFS_SBS_ICOUNT:
 		count = mp->m_sb.sb_icount;
 		resid = do_div(count, weight);
-		if (count < XFS_ICSB_INO_CNTR_REENABLE)
+		if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
 			goto out;
 		break;
 	case XFS_SBS_IFREE:
 		count = mp->m_sb.sb_ifree;
 		resid = do_div(count, weight);
-		if (count < XFS_ICSB_INO_CNTR_REENABLE)
+		if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
 			goto out;
 		break;
 	case XFS_SBS_FDBLOCKS:
 		count = mp->m_sb.sb_fdblocks;
 		resid = do_div(count, weight);
-		if (count < XFS_ICSB_FDBLK_CNTR_REENABLE(mp))
+		if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
 			goto out;
 		break;
 	default:
@@ -2054,32 +2097,39 @@
 		XFS_SB_UNLOCK(mp, s);
 }
 
-STATIC int
-xfs_icsb_modify_counters_int(
+int
+xfs_icsb_modify_counters(
 	xfs_mount_t	*mp,
 	xfs_sb_field_t	field,
-	int		delta,
-	int		rsvd,
-	int		flags)
+	int64_t		delta,
+	int		rsvd)
 {
 	xfs_icsb_cnts_t	*icsbp;
 	long long	lcounter;	/* long counter for 64 bit fields */
-	int		cpu, s, locked = 0;
-	int		ret = 0, balance_done = 0;
+	int		cpu, ret = 0, s;
 
+	might_sleep();
 again:
 	cpu = get_cpu();
-	icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu),
-	xfs_icsb_lock_cntr(icsbp);
+	icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu);
+
+	/*
+	 * if the counter is disabled, go to slow path
+	 */
 	if (unlikely(xfs_icsb_counter_disabled(mp, field)))
 		goto slow_path;
+	xfs_icsb_lock_cntr(icsbp);
+	if (unlikely(xfs_icsb_counter_disabled(mp, field))) {
+		xfs_icsb_unlock_cntr(icsbp);
+		goto slow_path;
+	}
 
 	switch (field) {
 	case XFS_SBS_ICOUNT:
 		lcounter = icsbp->icsb_icount;
 		lcounter += delta;
 		if (unlikely(lcounter < 0))
-			goto slow_path;
+			goto balance_counter;
 		icsbp->icsb_icount = lcounter;
 		break;
 
@@ -2087,7 +2137,7 @@
 		lcounter = icsbp->icsb_ifree;
 		lcounter += delta;
 		if (unlikely(lcounter < 0))
-			goto slow_path;
+			goto balance_counter;
 		icsbp->icsb_ifree = lcounter;
 		break;
 
@@ -2097,7 +2147,7 @@
 		lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
 		lcounter += delta;
 		if (unlikely(lcounter < 0))
-			goto slow_path;
+			goto balance_counter;
 		icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
 		break;
 	default:
@@ -2106,72 +2156,78 @@
 	}
 	xfs_icsb_unlock_cntr(icsbp);
 	put_cpu();
-	if (locked)
-		XFS_SB_UNLOCK(mp, s);
 	return 0;
 
-	/*
-	 * The slow path needs to be run with the SBLOCK
-	 * held so that we prevent other threads from
-	 * attempting to run this path at the same time.
-	 * this provides exclusion for the balancing code,
-	 * and exclusive fallback if the balance does not
-	 * provide enough resources to continue in an unlocked
-	 * manner.
-	 */
 slow_path:
+	put_cpu();
+
+	/*
+	 * serialise with a mutex so we don't burn lots of cpu on
+	 * the superblock lock. We still need to hold the superblock
+	 * lock, however, when we modify the global structures.
+	 */
+	xfs_icsb_lock(mp);
+
+	/*
+	 * Now running atomically.
+	 *
+	 * If the counter is enabled, someone has beaten us to rebalancing.
+	 * Drop the lock and try again in the fast path....
+	 */
+	if (!(xfs_icsb_counter_disabled(mp, field))) {
+		xfs_icsb_unlock(mp);
+		goto again;
+	}
+
+	/*
+	 * The counter is currently disabled. Because we are
+	 * running atomically here, we know a rebalance cannot
+	 * be in progress. Hence we can go straight to operating
+	 * on the global superblock. We do not call xfs_mod_incore_sb()
+	 * here even though we need to get the SB_LOCK. Doing so
+	 * will cause us to re-enter this function and deadlock.
+	 * Hence we get the SB_LOCK ourselves and then call
+	 * xfs_mod_incore_sb_unlocked() as the unlocked path operates
+	 * directly on the global counters.
+	 */
+	s = XFS_SB_LOCK(mp);
+	ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
+	XFS_SB_UNLOCK(mp, s);
+
+	/*
+	 * Now that we've modified the global superblock, we
+	 * may be able to re-enable the distributed counters
+	 * (e.g. lots of space just got freed). After that
+	 * we are done.
+	 */
+	if (ret != ENOSPC)
+		xfs_icsb_balance_counter(mp, field, 0, 0);
+	xfs_icsb_unlock(mp);
+	return ret;
+
+balance_counter:
 	xfs_icsb_unlock_cntr(icsbp);
 	put_cpu();
 
-	/* need to hold superblock incase we need
-	 * to disable a counter */
-	if (!(flags & XFS_ICSB_SB_LOCKED)) {
-		s = XFS_SB_LOCK(mp);
-		locked = 1;
-		flags |= XFS_ICSB_SB_LOCKED;
-	}
-	if (!balance_done) {
-		xfs_icsb_balance_counter(mp, field, flags);
-		balance_done = 1;
-		goto again;
-	} else {
-		/*
-		 * we might not have enough on this local
-		 * cpu to allocate for a bulk request.
-		 * We need to drain this field from all CPUs
-		 * and disable the counter fastpath
-		 */
-		xfs_icsb_disable_counter(mp, field);
-	}
+	/*
+	 * We may have multiple threads here if multiple per-cpu
+	 * counters run dry at the same time. This will mean we can
+	 * do more balances than strictly necessary but it is not
+	 * the common slowpath case.
+	 */
+	xfs_icsb_lock(mp);
 
-	ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
-
-	if (locked)
-		XFS_SB_UNLOCK(mp, s);
-	return ret;
+	/*
+	 * running atomically.
+	 *
+	 * This will leave the counter in the correct state for future
+	 * accesses. After the rebalance, we simply try again and our retry
+	 * will either succeed through the fast path or slow path without
+	 * another balance operation being required.
+	 */
+	xfs_icsb_balance_counter(mp, field, 0, delta);
+	xfs_icsb_unlock(mp);
+	goto again;
 }
 
-STATIC int
-xfs_icsb_modify_counters(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t	field,
-	int		delta,
-	int		rsvd)
-{
-	return xfs_icsb_modify_counters_int(mp, field, delta, rsvd, 0);
-}
-
-/*
- * Called when superblock is already locked
- */
-STATIC int
-xfs_icsb_modify_counters_locked(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t	field,
-	int		delta,
-	int		rsvd)
-{
-	return xfs_icsb_modify_counters_int(mp, field, delta,
-						rsvd, XFS_ICSB_SB_LOCKED);
-}
 #endif
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index e5f396f..82304b9 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -18,6 +18,7 @@
 #ifndef __XFS_MOUNT_H__
 #define	__XFS_MOUNT_H__
 
+
 typedef struct xfs_trans_reservations {
 	uint	tr_write;	/* extent alloc trans */
 	uint	tr_itruncate;	/* truncate trans */
@@ -306,11 +307,13 @@
 #define XFS_ICSB_LAZY_COUNT	(1 << 1)	/* accuracy not needed */
 
 extern int	xfs_icsb_init_counters(struct xfs_mount *);
-extern void	xfs_icsb_sync_counters_lazy(struct xfs_mount *);
+extern void	xfs_icsb_reinit_counters(struct xfs_mount *);
+extern void	xfs_icsb_sync_counters_flags(struct xfs_mount *, int);
 
 #else
 #define xfs_icsb_init_counters(mp)	(0)
-#define xfs_icsb_sync_counters_lazy(mp)	do { } while (0)
+#define xfs_icsb_reinit_counters(mp)	do { } while (0)
+#define xfs_icsb_sync_counters_flags(mp, flags)	do { } while (0)
 #endif
 
 typedef struct xfs_mount {
@@ -419,6 +422,7 @@
 	xfs_icsb_cnts_t		*m_sb_cnts;	/* per-cpu superblock counters */
 	unsigned long		m_icsb_counters; /* disabled per-cpu counters */
 	struct notifier_block	m_icsb_notifier; /* hotplug cpu notifier */
+	struct mutex		m_icsb_mutex;	/* balancer sync lock */
 #endif
 } xfs_mount_t;
 
@@ -563,11 +567,32 @@
 }
 
 /*
+ * Per-cpu superblock locking functions
+ */
+#ifdef HAVE_PERCPU_SB
+STATIC_INLINE void
+xfs_icsb_lock(xfs_mount_t *mp)
+{
+	mutex_lock(&mp->m_icsb_mutex);
+}
+
+STATIC_INLINE void
+xfs_icsb_unlock(xfs_mount_t *mp)
+{
+	mutex_unlock(&mp->m_icsb_mutex);
+}
+#else
+#define xfs_icsb_lock(mp)
+#define xfs_icsb_unlock(mp)
+#endif
+
+/*
  * This structure is for use by the xfs_mod_incore_sb_batch() routine.
+ * xfs_growfs can specify a few fields which are more than int limit
  */
 typedef struct xfs_mod_sb {
 	xfs_sb_field_t	msb_field;	/* Field to modify, see below */
-	int		msb_delta;	/* Change to make to specified field */
+	int64_t		msb_delta;	/* Change to make to specified field */
 } xfs_mod_sb_t;
 
 #define	XFS_MOUNT_ILOCK(mp)	mutex_lock(&((mp)->m_ilock))
@@ -585,17 +610,17 @@
 extern void	xfs_unmountfs_close(xfs_mount_t *, struct cred *);
 extern int	xfs_unmountfs_writesb(xfs_mount_t *);
 extern int	xfs_unmount_flush(xfs_mount_t *, int);
-extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int, int);
+extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
 extern int	xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t,
-			int, int);
+			int64_t, int);
 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 *, 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 *);
-extern int	xfs_sync_inodes(xfs_mount_t *, int, int, int *);
+extern int	xfs_syncsub(xfs_mount_t *, int, int *);
+extern int	xfs_sync_inodes(xfs_mount_t *, int, int *);
 extern xfs_agnumber_t	xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *,
 						xfs_agnumber_t);
 extern void	xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index d98171d..4c6573d 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -565,7 +565,7 @@
 		IHOLD(target_ip);
 	IHOLD(src_ip);
 
-	error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+	error = xfs_bmap_finish(&tp, &free_list, &committed);
 	if (error) {
 		xfs_bmap_cancel(&free_list);
 		xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 880c732..6fff19d 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -147,7 +147,7 @@
 		/*
 		 * Free any blocks freed up in the transaction, then commit.
 		 */
-		error = xfs_bmap_finish(&tp, &flist, firstblock, &committed);
+		error = xfs_bmap_finish(&tp, &flist, &committed);
 		if (error)
 			goto error_exit;
 		xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
@@ -913,57 +913,6 @@
 }
 #endif
 
-#ifdef DEBUG
-/*
- * Check whether the given block in the bitmap has the given value.
- */
-STATIC int				/* 1 for matches, 0 for not */
-xfs_rtcheck_bit(
-	xfs_mount_t	*mp,		/* file system mount structure */
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_rtblock_t	start,		/* bit (block) to check */
-	int		val)		/* 1 for free, 0 for allocated */
-{
-	int		bit;		/* bit number in the word */
-	xfs_rtblock_t	block;		/* bitmap block number */
-	xfs_buf_t	*bp;		/* buf for the block */
-	xfs_rtword_t	*bufp;		/* pointer into the buffer */
-	/* REFERENCED */
-	int		error;		/* error value */
-	xfs_rtword_t	wdiff;		/* difference between bit & expected */
-	int		word;		/* word number in the buffer */
-	xfs_rtword_t	wval;		/* word value from buffer */
-
-	block = XFS_BITTOBLOCK(mp, start);
-	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
-	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
-	word = XFS_BITTOWORD(mp, start);
-	bit = (int)(start & (XFS_NBWORD - 1));
-	wval = bufp[word];
-	xfs_trans_brelse(tp, bp);
-	wdiff = (wval ^ -val) & ((xfs_rtword_t)1 << bit);
-	return !wdiff;
-}
-#endif	/* DEBUG */
-
-#if 0
-/*
- * Check that the given extent (block range) is free already.
- */
-STATIC int				/* error */
-xfs_rtcheck_free_range(
-	xfs_mount_t	*mp,		/* file system mount point */
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_rtblock_t	bno,		/* starting block number of extent */
-	xfs_extlen_t	len,		/* length of extent */
-	int		*stat)		/* out: 1 for free, 0 for not */
-{
-	xfs_rtblock_t	new;		/* dummy for xfs_rtcheck_range */
-
-	return xfs_rtcheck_range(mp, tp, bno, len, 1, &new, stat);
-}
-#endif
-
 /*
  * Check that the given range is either all allocated (val = 0) or
  * all free (val = 1).
@@ -2382,60 +2331,3 @@
 	*pick = b;
 	return 0;
 }
-
-#ifdef DEBUG
-/*
- * Debug code: print out the value of a range in the bitmap.
- */
-void
-xfs_rtprint_range(
-	xfs_mount_t	*mp,		/* file system mount structure */
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_rtblock_t	start,		/* starting block to print */
-	xfs_extlen_t	len)		/* length to print */
-{
-	xfs_extlen_t	i;		/* block number in the extent */
-
-	cmn_err(CE_DEBUG, "%Ld: ", (long long)start);
-	for (i = 0; i < len; i++)
-		cmn_err(CE_DEBUG, "%d", xfs_rtcheck_bit(mp, tp, start + i, 1));
-	cmn_err(CE_DEBUG, "\n");
-}
-
-/*
- * Debug code: print the summary file.
- */
-void
-xfs_rtprint_summary(
-	xfs_mount_t	*mp,		/* file system mount structure */
-	xfs_trans_t	*tp)		/* transaction pointer */
-{
-	xfs_suminfo_t	c;		/* summary data */
-	xfs_rtblock_t	i;		/* bitmap block number */
-	int		l;		/* summary information level */
-	int		p;		/* flag for printed anything */
-	xfs_fsblock_t	sb;		/* summary block number */
-	xfs_buf_t	*sumbp;		/* summary block buffer */
-
-	sumbp = NULL;
-	for (l = 0; l < mp->m_rsumlevels; l++) {
-		for (p = 0, i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
-			(void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c);
-			if (c) {
-				if (!p) {
-					cmn_err(CE_DEBUG, "%Ld-%Ld:", 1LL << l,
-						XFS_RTMIN((1LL << l) +
-							  ((1LL << l) - 1LL),
-							 mp->m_sb.sb_rextents));
-					p = 1;
-				}
-				cmn_err(CE_DEBUG, " %Ld:%d", (long long)i, c);
-			}
-		}
-		if (p)
-			cmn_err(CE_DEBUG, "\n");
-	}
-	if (sumbp)
-		xfs_trans_brelse(tp, sumbp);
-}
-#endif	/* DEBUG */
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index 0e0b4d2..799c1f8 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -134,24 +134,6 @@
 	xfs_rtblock_t		*pick);	/* result rt extent */
 
 /*
- * Debug code: print out the value of a range in the bitmap.
- */
-void
-xfs_rtprint_range(
-	struct xfs_mount	*mp,	/* file system mount structure */
-	struct xfs_trans	*tp,	/* transaction pointer */
-	xfs_rtblock_t		start,	/* starting block to print */
-	xfs_extlen_t		len);	/* length to print */
-
-/*
- * Debug code: print the summary file.
- */
-void
-xfs_rtprint_summary(
-	struct xfs_mount	*mp,	/* file system mount structure */
-	struct xfs_trans	*tp);	/* transaction pointer */
-
-/*
  * Grow the realtime area of the filesystem.
  */
 int
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c
index defb2fe..1ea7c0c 100644
--- a/fs/xfs/xfs_rw.c
+++ b/fs/xfs/xfs_rw.c
@@ -42,7 +42,6 @@
 #include "xfs_attr.h"
 #include "xfs_bmap.h"
 #include "xfs_acl.h"
-#include "xfs_mac.h"
 #include "xfs_error.h"
 #include "xfs_buf_item.h"
 #include "xfs_rw.h"
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index ee2721e..301ff94 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -339,7 +339,7 @@
 	 */
 	if (blocks > 0) {
 		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
-					  -blocks, rsvd);
+					  -((int64_t)blocks), rsvd);
 		if (error != 0) {
 			current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
 			return (XFS_ERROR(ENOSPC));
@@ -380,7 +380,7 @@
 	 */
 	if (rtextents > 0) {
 		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS,
-					  -rtextents, rsvd);
+					  -((int64_t)rtextents), rsvd);
 		if (error) {
 			error = XFS_ERROR(ENOSPC);
 			goto undo_log;
@@ -410,7 +410,7 @@
 undo_blocks:
 	if (blocks > 0) {
 		(void) xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
-					 blocks, rsvd);
+					 (int64_t)blocks, rsvd);
 		tp->t_blk_res = 0;
 	}
 
@@ -432,7 +432,7 @@
 xfs_trans_mod_sb(
 	xfs_trans_t	*tp,
 	uint		field,
-	long		delta)
+	int64_t		delta)
 {
 
 	switch (field) {
@@ -663,62 +663,62 @@
 	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
 		if (tp->t_icount_delta != 0) {
 			msbp->msb_field = XFS_SBS_ICOUNT;
-			msbp->msb_delta = (int)tp->t_icount_delta;
+			msbp->msb_delta = tp->t_icount_delta;
 			msbp++;
 		}
 		if (tp->t_ifree_delta != 0) {
 			msbp->msb_field = XFS_SBS_IFREE;
-			msbp->msb_delta = (int)tp->t_ifree_delta;
+			msbp->msb_delta = tp->t_ifree_delta;
 			msbp++;
 		}
 		if (tp->t_fdblocks_delta != 0) {
 			msbp->msb_field = XFS_SBS_FDBLOCKS;
-			msbp->msb_delta = (int)tp->t_fdblocks_delta;
+			msbp->msb_delta = tp->t_fdblocks_delta;
 			msbp++;
 		}
 		if (tp->t_frextents_delta != 0) {
 			msbp->msb_field = XFS_SBS_FREXTENTS;
-			msbp->msb_delta = (int)tp->t_frextents_delta;
+			msbp->msb_delta = tp->t_frextents_delta;
 			msbp++;
 		}
 		if (tp->t_dblocks_delta != 0) {
 			msbp->msb_field = XFS_SBS_DBLOCKS;
-			msbp->msb_delta = (int)tp->t_dblocks_delta;
+			msbp->msb_delta = tp->t_dblocks_delta;
 			msbp++;
 		}
 		if (tp->t_agcount_delta != 0) {
 			msbp->msb_field = XFS_SBS_AGCOUNT;
-			msbp->msb_delta = (int)tp->t_agcount_delta;
+			msbp->msb_delta = tp->t_agcount_delta;
 			msbp++;
 		}
 		if (tp->t_imaxpct_delta != 0) {
 			msbp->msb_field = XFS_SBS_IMAX_PCT;
-			msbp->msb_delta = (int)tp->t_imaxpct_delta;
+			msbp->msb_delta = tp->t_imaxpct_delta;
 			msbp++;
 		}
 		if (tp->t_rextsize_delta != 0) {
 			msbp->msb_field = XFS_SBS_REXTSIZE;
-			msbp->msb_delta = (int)tp->t_rextsize_delta;
+			msbp->msb_delta = tp->t_rextsize_delta;
 			msbp++;
 		}
 		if (tp->t_rbmblocks_delta != 0) {
 			msbp->msb_field = XFS_SBS_RBMBLOCKS;
-			msbp->msb_delta = (int)tp->t_rbmblocks_delta;
+			msbp->msb_delta = tp->t_rbmblocks_delta;
 			msbp++;
 		}
 		if (tp->t_rblocks_delta != 0) {
 			msbp->msb_field = XFS_SBS_RBLOCKS;
-			msbp->msb_delta = (int)tp->t_rblocks_delta;
+			msbp->msb_delta = tp->t_rblocks_delta;
 			msbp++;
 		}
 		if (tp->t_rextents_delta != 0) {
 			msbp->msb_field = XFS_SBS_REXTENTS;
-			msbp->msb_delta = (int)tp->t_rextents_delta;
+			msbp->msb_delta = tp->t_rextents_delta;
 			msbp++;
 		}
 		if (tp->t_rextslog_delta != 0) {
 			msbp->msb_field = XFS_SBS_REXTSLOG;
-			msbp->msb_delta = (int)tp->t_rextslog_delta;
+			msbp->msb_delta = tp->t_rextslog_delta;
 			msbp++;
 		}
 	}
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index c68e001..f1d7ab2 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -39,13 +39,9 @@
 /*
  * Log item types.
  */
-#define	XFS_LI_5_3_BUF		0x1234	/* v1 bufs, 1-block inode buffers */
-#define	XFS_LI_5_3_INODE	0x1235	/* 1-block inode buffers */
 #define	XFS_LI_EFI		0x1236
 #define	XFS_LI_EFD		0x1237
 #define	XFS_LI_IUNLINK		0x1238
-#define	XFS_LI_6_1_INODE	0x1239	/* 4K non-aligned inode bufs */
-#define	XFS_LI_6_1_BUF		0x123a	/* v1, 4K inode buffers */
 #define	XFS_LI_INODE		0x123b	/* aligned ino chunks, var-size ibufs */
 #define	XFS_LI_BUF		0x123c	/* v2 bufs, variable sized inode bufs */
 #define	XFS_LI_DQUOT		0x123d
@@ -354,25 +350,25 @@
 	xfs_trans_callback_t	t_callback;	/* transaction callback */
 	void			*t_callarg;	/* callback arg */
 	unsigned int		t_flags;	/* misc flags */
-	long			t_icount_delta;	/* superblock icount change */
-	long			t_ifree_delta;	/* superblock ifree change */
-	long			t_fdblocks_delta; /* superblock fdblocks chg */
-	long			t_res_fdblocks_delta; /* on-disk only chg */
-	long			t_frextents_delta;/* superblock freextents chg*/
-	long			t_res_frextents_delta; /* on-disk only chg */
+	int64_t			t_icount_delta;	/* superblock icount change */
+	int64_t			t_ifree_delta;	/* superblock ifree change */
+	int64_t			t_fdblocks_delta; /* superblock fdblocks chg */
+	int64_t			t_res_fdblocks_delta; /* on-disk only chg */
+	int64_t			t_frextents_delta;/* superblock freextents chg*/
+	int64_t			t_res_frextents_delta; /* on-disk only chg */
 #ifdef DEBUG
-	long			t_ag_freeblks_delta; /* debugging counter */
-	long			t_ag_flist_delta; /* debugging counter */
-	long			t_ag_btree_delta; /* debugging counter */
+	int64_t			t_ag_freeblks_delta; /* debugging counter */
+	int64_t			t_ag_flist_delta; /* debugging counter */
+	int64_t			t_ag_btree_delta; /* debugging counter */
 #endif
-	long			t_dblocks_delta;/* superblock dblocks change */
-	long			t_agcount_delta;/* superblock agcount change */
-	long			t_imaxpct_delta;/* superblock imaxpct change */
-	long			t_rextsize_delta;/* superblock rextsize chg */
-	long			t_rbmblocks_delta;/* superblock rbmblocks chg */
-	long			t_rblocks_delta;/* superblock rblocks change */
-	long			t_rextents_delta;/* superblocks rextents chg */
-	long			t_rextslog_delta;/* superblocks rextslog chg */
+	int64_t			t_dblocks_delta;/* superblock dblocks change */
+	int64_t			t_agcount_delta;/* superblock agcount change */
+	int64_t			t_imaxpct_delta;/* superblock imaxpct change */
+	int64_t			t_rextsize_delta;/* superblock rextsize chg */
+	int64_t			t_rbmblocks_delta;/* superblock rbmblocks chg */
+	int64_t			t_rblocks_delta;/* superblock rblocks change */
+	int64_t			t_rextents_delta;/* superblocks rextents chg */
+	int64_t			t_rextslog_delta;/* superblocks rextslog chg */
 	unsigned int		t_items_free;	/* log item descs free */
 	xfs_log_item_chunk_t	t_items;	/* first log item desc chunk */
 	xfs_trans_header_t	t_header;	/* header for in-log trans */
@@ -936,9 +932,9 @@
 #define	xfs_trans_set_sync(tp)		((tp)->t_flags |= XFS_TRANS_SYNC)
 
 #ifdef DEBUG
-#define	xfs_trans_agblocks_delta(tp, d)	((tp)->t_ag_freeblks_delta += (long)d)
-#define	xfs_trans_agflist_delta(tp, d)	((tp)->t_ag_flist_delta += (long)d)
-#define	xfs_trans_agbtree_delta(tp, d)	((tp)->t_ag_btree_delta += (long)d)
+#define	xfs_trans_agblocks_delta(tp, d)	((tp)->t_ag_freeblks_delta += (int64_t)d)
+#define	xfs_trans_agflist_delta(tp, d)	((tp)->t_ag_flist_delta += (int64_t)d)
+#define	xfs_trans_agbtree_delta(tp, d)	((tp)->t_ag_btree_delta += (int64_t)d)
 #else
 #define	xfs_trans_agblocks_delta(tp, d)
 #define	xfs_trans_agflist_delta(tp, d)
@@ -954,7 +950,7 @@
 xfs_trans_t	*xfs_trans_dup(xfs_trans_t *);
 int		xfs_trans_reserve(xfs_trans_t *, uint, uint, uint,
 				  uint, uint);
-void		xfs_trans_mod_sb(xfs_trans_t *, uint, long);
+void		xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t);
 struct xfs_buf	*xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t,
 				   int, uint);
 int		xfs_trans_read_buf(struct xfs_mount *, xfs_trans_t *,
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index fc39b16..ceb4f6e 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -90,7 +90,7 @@
 	int			flush_log;
 	SPLDECL(s);
 
-#define	XFS_TRANS_PUSH_AIL_RESTARTS	10
+#define	XFS_TRANS_PUSH_AIL_RESTARTS	1000
 
 	AIL_LOCK(mp,s);
 	lip = xfs_trans_first_ail(mp, &gen);
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 62336a4..29f72f6 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -640,7 +640,7 @@
 	 * we can write the unmount record.
 	 */
 	do {
-		xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, 0, NULL);
+		xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, NULL);
 		pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
 		if (!pincount) {
 			delay(50);
@@ -806,7 +806,7 @@
 
 	statp->f_type = XFS_SB_MAGIC;
 
-	xfs_icsb_sync_counters_lazy(mp);
+	xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
 	s = XFS_SB_LOCK(mp);
 	statp->f_bsize = sbp->sb_blocksize;
 	lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
@@ -872,6 +872,10 @@
  *		       this by simply making sure the log gets flushed
  *		       if SYNC_BDFLUSH is set, and by actually writing it
  *		       out otherwise.
+ *	SYNC_IOWAIT  - The caller wants us to wait for all data I/O to complete
+ *		       before we return (including direct I/O). Forms the drain
+ *		       side of the write barrier needed to safely quiesce the
+ *		       filesystem.
  *
  */
 /*ARGSUSED*/
@@ -883,27 +887,20 @@
 {
 	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
 
-	if (unlikely(flags == SYNC_QUIESCE))
-		return xfs_quiesce_fs(mp);
-	else
-		return xfs_syncsub(mp, flags, 0, NULL);
+	return xfs_syncsub(mp, flags, NULL);
 }
 
 /*
  * xfs sync routine for internal use
  *
  * This routine supports all of the flags defined for the generic vfs_sync
- * interface as explained above under xfs_sync.  In the interests of not
- * changing interfaces within the 6.5 family, additional internally-
- * required functions are specified within a separate xflags parameter,
- * only available by calling this routine.
+ * interface as explained above under xfs_sync.
  *
  */
 int
 xfs_sync_inodes(
 	xfs_mount_t	*mp,
 	int		flags,
-	int             xflags,
 	int             *bypassed)
 {
 	xfs_inode_t	*ip = NULL;
@@ -1176,6 +1173,13 @@
 			}
 
 		}
+		/*
+		 * When freezing, we need to wait ensure all I/O (including direct
+		 * I/O) is complete to ensure no further data modification can take
+		 * place after this point
+		 */
+		if (flags & SYNC_IOWAIT)
+			vn_iowait(vp);
 
 		if (flags & SYNC_BDFLUSH) {
 			if ((flags & SYNC_ATTR) &&
@@ -1412,17 +1416,13 @@
  * xfs sync routine for internal use
  *
  * This routine supports all of the flags defined for the generic vfs_sync
- * interface as explained above under xfs_sync.  In the interests of not
- * changing interfaces within the 6.5 family, additional internally-
- * required functions are specified within a separate xflags parameter,
- * only available by calling this routine.
+ * interface as explained above under xfs_sync.
  *
  */
 int
 xfs_syncsub(
 	xfs_mount_t	*mp,
 	int		flags,
-	int             xflags,
 	int             *bypassed)
 {
 	int		error = 0;
@@ -1444,7 +1444,7 @@
 		if (flags & SYNC_BDFLUSH)
 			xfs_finish_reclaim_all(mp, 1);
 		else
-			error = xfs_sync_inodes(mp, flags, xflags, bypassed);
+			error = xfs_sync_inodes(mp, flags, bypassed);
 	}
 
 	/*
@@ -1958,15 +1958,26 @@
 	return 0;
 }
 
+/*
+ * Second stage of a freeze. The data is already frozen, now we have to take
+ * care of the metadata. New transactions are already blocked, so we need to
+ * wait for any remaining transactions to drain out before proceding.
+ */
 STATIC void
 xfs_freeze(
 	bhv_desc_t	*bdp)
 {
 	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
 
+	/* wait for all modifications to complete */
 	while (atomic_read(&mp->m_active_trans) > 0)
 		delay(100);
 
+	/* flush inodes and push all remaining buffers out to disk */
+	xfs_quiesce_fs(mp);
+
+	ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
+
 	/* Push the superblock and write an unmount record */
 	xfs_log_unmount_write(mp);
 	xfs_unmountfs_writesb(mp);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index bda774a..52c4171 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -51,7 +51,6 @@
 #include "xfs_refcache.h"
 #include "xfs_trans_space.h"
 #include "xfs_log_priv.h"
-#include "xfs_mac.h"
 
 STATIC int
 xfs_open(
@@ -1381,7 +1380,7 @@
 	/*
 	 * Commit the first transaction.  This logs the EFI and the inode.
 	 */
-	if ((error = xfs_bmap_finish(&tp, &free_list, first_block, &committed)))
+	if ((error = xfs_bmap_finish(&tp, &free_list, &committed)))
 		goto error1;
 	/*
 	 * The transaction must have been committed, since there were
@@ -1790,8 +1789,7 @@
 		 * Just ignore errors at this point.  There is
 		 * nothing we can do except to try to keep going.
 		 */
-		(void) xfs_bmap_finish(&tp,  &free_list, first_block,
-				       &committed);
+		(void) xfs_bmap_finish(&tp,  &free_list, &committed);
 		(void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
 	}
 	/*
@@ -2022,7 +2020,7 @@
 	IHOLD(ip);
 	vp = XFS_ITOV(ip);
 
-	error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+	error = xfs_bmap_finish(&tp, &free_list, &committed);
 	if (error) {
 		xfs_bmap_cancel(&free_list);
 		goto abort_rele;
@@ -2507,7 +2505,7 @@
 		xfs_trans_set_sync(tp);
 	}
 
-	error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+	error = xfs_bmap_finish(&tp, &free_list, &committed);
 	if (error) {
 		REMOVE_DEBUG_TRACE(__LINE__);
 		goto error_rele;
@@ -2715,7 +2713,7 @@
 		xfs_trans_set_sync(tp);
 	}
 
-	error = xfs_bmap_finish (&tp, &free_list, first_block, &committed);
+	error = xfs_bmap_finish (&tp, &free_list, &committed);
 	if (error) {
 		xfs_bmap_cancel(&free_list);
 		goto abort_return;
@@ -2932,7 +2930,7 @@
 		xfs_trans_set_sync(tp);
 	}
 
-	error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+	error = xfs_bmap_finish(&tp, &free_list, &committed);
 	if (error) {
 		IRELE(cdp);
 		goto error2;
@@ -3183,7 +3181,7 @@
 		xfs_trans_set_sync(tp);
 	}
 
-	error = xfs_bmap_finish (&tp, &free_list, first_block, &committed);
+	error = xfs_bmap_finish (&tp, &free_list, &committed);
 	if (error) {
 		xfs_bmap_cancel(&free_list);
 		xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
@@ -3533,7 +3531,7 @@
 	 */
 	IHOLD(ip);
 
-	error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+	error = xfs_bmap_finish(&tp, &free_list, &committed);
 	if (error) {
 		goto error2;
 	}
@@ -4145,7 +4143,7 @@
 		/*
 		 * Complete the transaction
 		 */
-		error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
+		error = xfs_bmap_finish(&tp, &free_list, &committed);
 		if (error) {
 			goto error0;
 		}
@@ -4452,7 +4450,7 @@
 		/*
 		 * complete the transaction
 		 */
-		error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
+		error = xfs_bmap_finish(&tp, &free_list, &committed);
 		if (error) {
 			goto error0;
 		}
diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
index ce7c9d6..73967c8 100644
--- a/include/acpi/acinterp.h
+++ b/include/acpi/acinterp.h
@@ -253,7 +253,8 @@
 
 void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread);
 
-void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc);
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc,
+			  struct acpi_thread_state *thread);
 
 /*
  * exprep - ACPI AML execution - prep utilities
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index 04e9735..5206d61 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -155,7 +155,7 @@
 struct acpi_object_mutex {
 	ACPI_OBJECT_COMMON_HEADER u8 sync_level;	/* 0-15, specified in Mutex() call */
 	u16 acquisition_depth;	/* Allow multiple Acquires, same thread */
-	struct acpi_thread_state *owner_thread;	/* Current owner of the mutex */
+	acpi_thread_id owner_thread_id;	/* Current owner of the mutex */
 	acpi_mutex os_mutex;	/* Actual OS synchronization object */
 	union acpi_operand_object *prev;	/* Link for list of acquired mutexes */
 	union acpi_operand_object *next;	/* Link for list of acquired mutexes */
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 4dc8a50..f6275b0 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -105,12 +105,6 @@
 
 int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
 
-/* --------------------------------------------------------------------------
-                                    Hot Keys
-   -------------------------------------------------------------------------- */
-
-extern int acpi_specific_hotkey_enabled;
-
 /*--------------------------------------------------------------------------
                                   Dock Station
   -------------------------------------------------------------------------- */
@@ -122,10 +116,34 @@
 	acpi_notify_handler handler, void *context);
 extern void unregister_hotplug_dock_device(acpi_handle handle);
 #else
-#define is_dock_device(h)			(0)
-#define register_dock_notifier(nb) 		(-ENODEV)
-#define unregister_dock_notifier(nb)           	do { } while(0)
-#define register_hotplug_dock_device(h1, h2, c)	(-ENODEV)
-#define unregister_hotplug_dock_device(h)       do { } while(0)
+static inline int is_dock_device(acpi_handle handle)
+{
+	return 0;
+}
+static inline int register_dock_notifier(struct notifier_block *nb)
+{
+	return -ENODEV;
+}
+static inline void unregister_dock_notifier(struct notifier_block *nb)
+{
+}
+static inline int register_hotplug_dock_device(acpi_handle handle,
+				acpi_notify_handler handler, void *context)
+{
+	return -ENODEV;
+}
+static inline void unregister_hotplug_dock_device(acpi_handle handle)
+{
+}
 #endif
+
+/*--------------------------------------------------------------------------
+                                  Suspend/Resume
+  -------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_SLEEP
+extern int acpi_sleep_init(void);
+#else
+#define acpi_sleep_init() do {} while (0)
+#endif
+
 #endif /*__ACPI_DRIVERS_H__*/
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 781394b..2785058 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -240,12 +240,6 @@
 acpi_os_validate_address(u8 space_id,
 			 acpi_physical_address address, acpi_size length);
 
-u8 acpi_os_readable(void *pointer, acpi_size length);
-
-#ifdef ACPI_FUTURE_USAGE
-u8 acpi_os_writable(void *pointer, acpi_size length);
-#endif
-
 u64 acpi_os_get_timer(void);
 
 acpi_status acpi_os_signal(u32 function, void *info);
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 7798d2a..916c010 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -79,6 +79,7 @@
 	u32 bm_activity;
 	int count;
 	struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
+	int timer_broadcast_on_state;
 };
 
 /* Performance Management */
diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h
index 5d15af2..24bdcc8 100644
--- a/include/asm-alpha/io.h
+++ b/include/asm-alpha/io.h
@@ -525,15 +525,6 @@
 extern void outsl (unsigned long port, const void *src, unsigned long count);
 
 /*
- * XXX - We don't have csum_partial_copy_fromio() yet, so we cheat here and 
- * just copy it. The net code will then do the checksum later. Presently 
- * only used by some shared memory 8390 Ethernet cards anyway.
- */
-
-#define eth_io_copy_and_sum(skb,src,len,unused) \
-  memcpy_fromio((skb)->data,src,len)
-
-/*
  * The Alpha Jensen hardware for some rather strange reason puts
  * the RTC clock at 0x170 instead of 0x70. Probably due to some
  * misguided idea about using 0x70 for NMI stuff.
diff --git a/include/asm-alpha/mman.h b/include/asm-alpha/mman.h
index 5f24c75..90d7c35 100644
--- a/include/asm-alpha/mman.h
+++ b/include/asm-alpha/mman.h
@@ -49,7 +49,6 @@
 #define MADV_DOFORK	11		/* do inherit across fork */
 
 /* compatibility flags */
-#define MAP_ANON	MAP_ANONYMOUS
 #define MAP_FILE	0
 
 #endif /* __ALPHA_MMAN_H__ */
diff --git a/include/asm-alpha/percpu.h b/include/asm-alpha/percpu.h
index 48348fe..651ebb1 100644
--- a/include/asm-alpha/percpu.h
+++ b/include/asm-alpha/percpu.h
@@ -1,6 +1,20 @@
 #ifndef __ALPHA_PERCPU_H
 #define __ALPHA_PERCPU_H
 
+/*
+ * Increase the per cpu area for Alpha so that
+ * modules using percpu area can load.
+ */
+#ifdef CONFIG_MODULES
+# define PERCPU_MODULE_RESERVE 8192
+#else
+# define PERCPU_MODULE_RESERVE 0
+#endif
+
+#define PERCPU_ENOUGH_ROOM \
+	(ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \
+	 PERCPU_MODULE_RESERVE)
+
 #include <asm-generic/percpu.h>
 
 #endif /* __ALPHA_PERCPU_H */
diff --git a/include/asm-alpha/termios.h b/include/asm-alpha/termios.h
index 1cfd27f..39e492c 100644
--- a/include/asm-alpha/termios.h
+++ b/include/asm-alpha/termios.h
@@ -66,24 +66,6 @@
 #define _VEOL2	6
 #define _VSWTC	7
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 /*	eof=^D		eol=\0		eol2=\0		erase=del
 	werase=^W	kill=^U		reprint=^R	sxtc=\0
diff --git a/include/asm-arm/.gitignore b/include/asm-arm/.gitignore
new file mode 100644
index 0000000..e02c15d
--- /dev/null
+++ b/include/asm-arm/.gitignore
@@ -0,0 +1,2 @@
+arch
+mach-types.h
diff --git a/include/asm-arm/apm.h b/include/asm-arm/apm.h
deleted file mode 100644
index d09113b..0000000
--- a/include/asm-arm/apm.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- linux-c -*-
- *
- * (C) 2003 zecke@handhelds.org
- *
- * GPL version 2
- *
- * based on arch/arm/kernel/apm.c
- * factor out the information needed by architectures to provide
- * apm status
- *
- *
- */
-#ifndef ARM_ASM_SA1100_APM_H
-#define ARM_ASM_SA1100_APM_H
-
-#include <linux/apm_bios.h>
-
-/*
- * This structure gets filled in by the machine specific 'get_power_status'
- * implementation.  Any fields which are not set default to a safe value.
- */
-struct apm_power_info {
-	unsigned char	ac_line_status;
-#define APM_AC_OFFLINE			0
-#define APM_AC_ONLINE			1
-#define APM_AC_BACKUP			2
-#define APM_AC_UNKNOWN			0xff
-
-	unsigned char	battery_status;
-#define APM_BATTERY_STATUS_HIGH		0
-#define APM_BATTERY_STATUS_LOW		1
-#define APM_BATTERY_STATUS_CRITICAL	2
-#define APM_BATTERY_STATUS_CHARGING	3
-#define APM_BATTERY_STATUS_NOT_PRESENT	4
-#define APM_BATTERY_STATUS_UNKNOWN	0xff
-
-	unsigned char	battery_flag;
-#define APM_BATTERY_FLAG_HIGH		(1 << 0)
-#define APM_BATTERY_FLAG_LOW		(1 << 1)
-#define APM_BATTERY_FLAG_CRITICAL	(1 << 2)
-#define APM_BATTERY_FLAG_CHARGING	(1 << 3)
-#define APM_BATTERY_FLAG_NOT_PRESENT	(1 << 7)
-#define APM_BATTERY_FLAG_UNKNOWN	0xff
-
-	int		battery_life;
-	int		time;
-	int		units;
-#define APM_UNITS_MINS			0
-#define APM_UNITS_SECS			1
-#define APM_UNITS_UNKNOWN		-1
-
-};
-
-/*
- * This allows machines to provide their own "apm get power status" function.
- */
-extern void (*apm_get_power_status)(struct apm_power_info *);
-
-/*
- * Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND)
- */
-void apm_queue_event(apm_event_t event);
-
-#endif
diff --git a/include/asm-arm/arch-aaec2000/entry-macro.S b/include/asm-arm/arch-aaec2000/entry-macro.S
index 1eb3503..83fdf68 100644
--- a/include/asm-arm/arch-aaec2000/entry-macro.S
+++ b/include/asm-arm/arch-aaec2000/entry-macro.S
@@ -15,6 +15,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 		mov	r4, #0xf8000000
 		add	r4, r4, #0x00000500
diff --git a/include/asm-arm/arch-at91/at91_aic.h b/include/asm-arm/arch-at91/at91_aic.h
new file mode 100644
index 0000000..df44c12
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_aic.h
@@ -0,0 +1,53 @@
+/*
+ * include/asm-arm/arch-at91/at91_aic.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Advanced Interrupt Controller (AIC) - System peripherals 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 AT91_AIC_H
+#define AT91_AIC_H
+
+#define AT91_AIC_SMR(n)		(AT91_AIC + ((n) * 4))	/* Source Mode Registers 0-31 */
+#define		AT91_AIC_PRIOR		(7 << 0)		/* Priority Level */
+#define		AT91_AIC_SRCTYPE	(3 << 5)		/* Interrupt Source Type */
+#define			AT91_AIC_SRCTYPE_LOW		(0 << 5)
+#define			AT91_AIC_SRCTYPE_FALLING	(1 << 5)
+#define			AT91_AIC_SRCTYPE_HIGH		(2 << 5)
+#define			AT91_AIC_SRCTYPE_RISING		(3 << 5)
+
+#define AT91_AIC_SVR(n)		(AT91_AIC + 0x80 + ((n) * 4))	/* Source Vector Registers 0-31 */
+#define AT91_AIC_IVR		(AT91_AIC + 0x100)	/* Interrupt Vector Register */
+#define AT91_AIC_FVR		(AT91_AIC + 0x104)	/* Fast Interrupt Vector Register */
+#define AT91_AIC_ISR		(AT91_AIC + 0x108)	/* Interrupt Status Register */
+#define		AT91_AIC_IRQID		(0x1f << 0)		/* Current Interrupt Identifier */
+
+#define AT91_AIC_IPR		(AT91_AIC + 0x10c)	/* Interrupt Pending Register */
+#define AT91_AIC_IMR		(AT91_AIC + 0x110)	/* Interrupt Mask Register */
+#define AT91_AIC_CISR		(AT91_AIC + 0x114)	/* Core Interrupt Status Register */
+#define		AT91_AIC_NFIQ		(1 << 0)		/* nFIQ Status */
+#define		AT91_AIC_NIRQ		(1 << 1)		/* nIRQ Status */
+
+#define AT91_AIC_IECR		(AT91_AIC + 0x120)	/* Interrupt Enable Command Register */
+#define AT91_AIC_IDCR		(AT91_AIC + 0x124)	/* Interrupt Disable Command Register */
+#define AT91_AIC_ICCR		(AT91_AIC + 0x128)	/* Interrupt Clear Command Register */
+#define AT91_AIC_ISCR		(AT91_AIC + 0x12c)	/* Interrupt Set Command Register */
+#define AT91_AIC_EOICR		(AT91_AIC + 0x130)	/* End of Interrupt Command Register */
+#define AT91_AIC_SPU		(AT91_AIC + 0x134)	/* Spurious Interrupt Vector Register */
+#define AT91_AIC_DCR		(AT91_AIC + 0x138)	/* Debug Control Register */
+#define		AT91_AIC_DCR_PROT	(1 << 0)		/* Protection Mode */
+#define		AT91_AIC_DCR_GMSK	(1 << 1)		/* General Mask */
+
+#define AT91_AIC_FFER		(AT91_AIC + 0x140)	/* Fast Forcing Enable Register [SAM9 only] */
+#define AT91_AIC_FFDR		(AT91_AIC + 0x144)	/* Fast Forcing Disable Register [SAM9 only] */
+#define AT91_AIC_FFSR		(AT91_AIC + 0x148)	/* Fast Forcing Status Register [SAM9 only] */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_dbgu.h b/include/asm-arm/arch-at91/at91_dbgu.h
new file mode 100644
index 0000000..b0369e1
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_dbgu.h
@@ -0,0 +1,59 @@
+/*
+ * include/asm-arm/arch-at91/at91_dbgu.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Debug Unit (DBGU) - System peripherals 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 AT91_DBGU_H
+#define AT91_DBGU_H
+
+#define AT91_DBGU_CR		(AT91_DBGU + 0x00)	/* Control Register */
+#define AT91_DBGU_MR		(AT91_DBGU + 0x04)	/* Mode Register */
+#define AT91_DBGU_IER		(AT91_DBGU + 0x08)	/* Interrupt Enable Register */
+#define		AT91_DBGU_TXRDY		(1 << 1)		/* Transmitter Ready */
+#define		AT91_DBGU_TXEMPTY	(1 << 9)		/* Transmitter Empty */
+#define AT91_DBGU_IDR		(AT91_DBGU + 0x0c)	/* Interrupt Disable Register */
+#define AT91_DBGU_IMR		(AT91_DBGU + 0x10)	/* Interrupt Mask Register */
+#define AT91_DBGU_SR		(AT91_DBGU + 0x14)	/* Status Register */
+#define AT91_DBGU_RHR		(AT91_DBGU + 0x18)	/* Receiver Holding Register */
+#define AT91_DBGU_THR		(AT91_DBGU + 0x1c)	/* Transmitter Holding Register */
+#define AT91_DBGU_BRGR		(AT91_DBGU + 0x20)	/* Baud Rate Generator Register */
+
+#define AT91_DBGU_CIDR		(AT91_DBGU + 0x40)	/* Chip ID Register */
+#define AT91_DBGU_EXID		(AT91_DBGU + 0x44)	/* Chip ID Extension Register */
+#define		AT91_CIDR_VERSION	(0x1f << 0)		/* Version of the Device */
+#define		AT91_CIDR_EPROC		(7    << 5)		/* Embedded Processor */
+#define		AT91_CIDR_NVPSIZ	(0xf  << 8)		/* Nonvolatile Program Memory Size */
+#define		AT91_CIDR_NVPSIZ2	(0xf  << 12)		/* Second Nonvolatile Program Memory Size */
+#define		AT91_CIDR_SRAMSIZ	(0xf  << 16)		/* Internal SRAM Size */
+#define			AT91_CIDR_SRAMSIZ_1K	(1 << 16)
+#define			AT91_CIDR_SRAMSIZ_2K	(2 << 16)
+#define			AT91_CIDR_SRAMSIZ_112K	(4 << 16)
+#define			AT91_CIDR_SRAMSIZ_4K	(5 << 16)
+#define			AT91_CIDR_SRAMSIZ_80K	(6 << 16)
+#define			AT91_CIDR_SRAMSIZ_160K	(7 << 16)
+#define			AT91_CIDR_SRAMSIZ_8K	(8 << 16)
+#define			AT91_CIDR_SRAMSIZ_16K	(9 << 16)
+#define			AT91_CIDR_SRAMSIZ_32K	(10 << 16)
+#define			AT91_CIDR_SRAMSIZ_64K	(11 << 16)
+#define			AT91_CIDR_SRAMSIZ_128K	(12 << 16)
+#define			AT91_CIDR_SRAMSIZ_256K	(13 << 16)
+#define			AT91_CIDR_SRAMSIZ_96K	(14 << 16)
+#define			AT91_CIDR_SRAMSIZ_512K	(15 << 16)
+#define		AT91_CIDR_ARCH		(0xff << 20)		/* Architecture Identifier */
+#define		AT91_CIDR_NVPTYP	(7    << 28)		/* Nonvolatile Program Memory Type */
+#define		AT91_CIDR_EXT		(1    << 31)		/* Extension Flag */
+
+#define AT91_DBGU_FNR		(AT91_DBGU + 0x48)	/* Force NTRST Register [SAM9 only] */
+#define		AT91_DBGU_FNTRST	(1 << 0)		/* Force NTRST */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_ecc.h b/include/asm-arm/arch-at91/at91_ecc.h
new file mode 100644
index 0000000..ff93df5
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_ecc.h
@@ -0,0 +1,38 @@
+/*
+ * include/asm-arm/arch-at91/at91_ecc.h
+ *
+ * Error Corrected Code Controller (ECC) - System peripherals regsters.
+ * Based on AT91SAM9260 datasheet revision B.
+ *
+ * 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 AT91_ECC_H
+#define AT91_ECC_H
+
+#define AT91_ECC_CR		(AT91_ECC + 0x00)	/* Control register */
+#define		AT91_ECC_RST		(1 << 0)		/* Reset parity */
+
+#define AT91_ECC_MR		(AT91_ECC + 0x04)	/* Mode register */
+#define		AT91_ECC_PAGESIZE	(3 << 0)		/* Page Size */
+#define			AT91_ECC_PAGESIZE_528		(0)
+#define			AT91_ECC_PAGESIZE_1056		(1)
+#define			AT91_ECC_PAGESIZE_2112		(2)
+#define			AT91_ECC_PAGESIZE_4224		(3)
+
+#define AT91_ECC_SR		(AT91_ECC + 0x08)	/* Status register */
+#define		AT91_ECC_RECERR		(1 << 0)		/* Recoverable Error */
+#define		AT91_ECC_ECCERR		(1 << 1)		/* ECC Single Bit Error */
+#define		AT91_ECC_MULERR		(1 << 2)		/* Multiple Errors */
+
+#define AT91_ECC_PR		(AT91_ECC + 0x0c)	/* Parity register */
+#define		AT91_ECC_BITADDR	(0xf << 0)		/* Bit Error Address */
+#define		AT91_ECC_WORDADDR	(0xfff << 4)		/* Word Error Address */
+
+#define AT91_ECC_NPR		(AT91_ECC + 0x10)	/* NParity register */
+#define		AT91_ECC_NPARITY	(0xffff << 0)		/* NParity */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_lcdc.h b/include/asm-arm/arch-at91/at91_lcdc.h
new file mode 100644
index 0000000..ab040a4
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_lcdc.h
@@ -0,0 +1,148 @@
+/*
+ * include/asm-arm/arch-at91/at91_lcdc.h
+ *
+ * LCD Controller (LCDC).
+ * Based on AT91SAM9261 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 AT91_LCDC_H
+#define AT91_LCDC_H
+
+#define AT91_LCDC_DMABADDR1	0x00		/* DMA Base Address Register 1 */
+#define AT91_LCDC_DMABADDR2	0x04		/* DMA Base Address Register 2 */
+#define AT91_LCDC_DMAFRMPT1	0x08		/* DMA Frame Pointer Register 1 */
+#define AT91_LCDC_DMAFRMPT2	0x0c		/* DMA Frame Pointer Register 2 */
+#define AT91_LCDC_DMAFRMADD1	0x10		/* DMA Frame Address Register 1 */
+#define AT91_LCDC_DMAFRMADD2	0x14		/* DMA Frame Address Register 2 */
+
+#define AT91_LCDC_DMAFRMCFG	0x18		/* DMA Frame Configuration Register */
+#define		AT91_LCDC_FRSIZE	(0x7fffff <<  0)	/* Frame Size */
+#define		AT91_LCDC_BLENGTH	(0x7f     << 24)	/* Burst Length */
+
+#define AT91_LCDC_DMACON	0x1c		/* DMA Control Register */
+#define		AT91_LCDC_DMAEN		(0x1 << 0)	/* DMA Enable */
+#define		AT91_LCDC_DMARST	(0x1 << 1)	/* DMA Reset */
+#define		AT91_LCDC_DMABUSY	(0x1 << 2)	/* DMA Busy */
+
+#define AT91_LCDC_LCDCON1	0x0800		/* LCD Control Register 1 */
+#define		AT91_LCDC_BYPASS	(1     <<  0)	/* Bypass lcd_dotck divider */
+#define		AT91_LCDC_CLKVAL	(0x1ff << 12)	/* Clock Divider */
+#define		AT91_LCDC_LINCNT	(0x7ff << 21)	/* Line Counter */
+
+#define AT91_LCDC_LCDCON2	0x0804		/* LCD Control Register 2 */
+#define		AT91_LCDC_DISTYPE	(3 << 0)	/* Display Type */
+#define			AT91_LCDC_DISTYPE_STNMONO	(0 << 0)
+#define			AT91_LCDC_DISTYPE_STNCOLOR	(1 << 0)
+#define			AT91_LCDC_DISTYPE_TFT		(2 << 0)
+#define		AT91_LCDC_SCANMOD	(1 << 2)	/* Scan Mode */
+#define			AT91_LCDC_SCANMOD_SINGLE	(0 << 2)
+#define			AT91_LCDC_SCANMOD_DUAL		(1 << 2)
+#define		AT91_LCDC_IFWIDTH	(3 << 3)	/*Interface Width */
+#define			AT91_LCDC_IFWIDTH_4		(0 << 3)
+#define			AT91_LCDC_IFWIDTH_8		(1 << 3)
+#define			AT91_LCDC_IFWIDTH_16		(2 << 3)
+#define		AT91_LCDC_PIXELSIZE	(7 << 5)	/* Bits per pixel */
+#define			AT91_LCDC_PIXELSIZE_1		(0 << 5)
+#define			AT91_LCDC_PIXELSIZE_2		(1 << 5)
+#define			AT91_LCDC_PIXELSIZE_4		(2 << 5)
+#define			AT91_LCDC_PIXELSIZE_8		(3 << 5)
+#define			AT91_LCDC_PIXELSIZE_16		(4 << 5)
+#define			AT91_LCDC_PIXELSIZE_24		(5 << 5)
+#define		AT91_LCDC_INVVD		(1 << 8)	/* LCD Data polarity */
+#define			AT91_LCDC_INVVD_NORMAL		(0 << 8)
+#define			AT91_LCDC_INVVD_INVERTED	(1 << 8)
+#define		AT91_LCDC_INVFRAME	(1 << 9 )	/* LCD VSync polarity */
+#define			AT91_LCDC_INVFRAME_NORMAL	(0 << 9)
+#define			AT91_LCDC_INVFRAME_INVERTED	(1 << 9)
+#define		AT91_LCDC_INVLINE	(1 << 10)	/* LCD HSync polarity */
+#define			AT91_LCDC_INVLINE_NORMAL	(0 << 10)
+#define			AT91_LCDC_INVLINE_INVERTED	(1 << 10)
+#define		AT91_LCDC_INVCLK	(1 << 11)	/* LCD dotclk polarity */
+#define			AT91_LCDC_INVCLK_NORMAL		(0 << 11)
+#define			AT91_LCDC_INVCLK_INVERTED	(1 << 11)
+#define		AT91_LCDC_INVDVAL	(1 << 12)	/* LCD dval polarity */
+#define			AT91_LCDC_INVDVAL_NORMAL	(0 << 12)
+#define			AT91_LCDC_INVDVAL_INVERTED	(1 << 12)
+#define		AT91_LCDC_CLKMOD	(1 << 15)	/* LCD dotclk mode */
+#define			AT91_LCDC_CLKMOD_ACTIVEDISPLAY	(0 << 15)
+#define			AT91_LCDC_CLKMOD_ALWAYSACTIVE	(1 << 15)
+#define		AT91_LCDC_MEMOR		(1 << 31)	/* Memory Ordering Format */
+#define			AT91_LCDC_MEMOR_BIG		(0 << 31)
+#define			AT91_LCDC_MEMOR_LITTLE		(1 << 31)
+
+#define AT91_LCDC_TIM1		0x0808		/* LCD Timing Register 1 */
+#define		AT91_LCDC_VFP		(0xff <<  0)	/* Vertical Front Porch */
+#define		AT91_LCDC_VBP		(0xff <<  8)	/* Vertical Back Porch */
+#define		AT91_LCDC_VPW		(0x3f << 16)	/* Vertical Synchronization Pulse Width */
+#define		AT91_LCDC_VHDLY		(0xf  << 24)	/* Vertical to Horizontal Delay */
+
+#define AT91_LCDC_TIM2		0x080c		/* LCD Timing Register 2 */
+#define		AT91_LCDC_HBP		(0xff  <<  0)	/* Horizontal Back Porch */
+#define		AT91_LCDC_HPW		(0x3f  <<  8)	/* Horizontal Synchronization Pulse Width */
+#define		AT91_LCDC_HFP		(0x7ff << 21)	/* Horizontal Front Porch */
+
+#define AT91_LCDC_LCDFRMCFG	0x0810		/* LCD Frame Configuration Register */
+#define		AT91_LCDC_LINEVAL	(0x7ff <<  0)	/* Vertical Size of LCD Module */
+#define		AT91_LCDC_HOZVAL	(0x7ff << 21)	/* Horizontal Size of LCD Module */
+
+#define AT91_LCDC_FIFO		0x0814		/* LCD FIFO Register */
+#define		AT91_LCDC_FIFOTH	(0xffff)	/* FIFO Threshold */
+
+#define AT91_LCDC_DP1_2		0x081c		/* Dithering Pattern DP1_2 Register */
+#define AT91_LCDC_DP4_7		0x0820		/* Dithering Pattern DP4_7 Register */
+#define AT91_LCDC_DP3_5		0x0824		/* Dithering Pattern DP3_5 Register */
+#define AT91_LCDC_DP2_3		0x0828		/* Dithering Pattern DP2_3 Register */
+#define AT91_LCDC_DP5_7		0x082c		/* Dithering Pattern DP5_7 Register */
+#define AT91_LCDC_DP3_4		0x0830		/* Dithering Pattern DP3_4 Register */
+#define AT91_LCDC_DP4_5		0x0834		/* Dithering Pattern DP4_5 Register */
+#define AT91_LCDC_DP6_7		0x0838		/* Dithering Pattern DP6_7 Register */
+#define		AT91_LCDC_DP1_2_VAL	(0xff)
+#define		AT91_LCDC_DP4_7_VAL	(0xfffffff)
+#define		AT91_LCDC_DP3_5_VAL	(0xfffff)
+#define		AT91_LCDC_DP2_3_VAL	(0xfff)
+#define		AT91_LCDC_DP5_7_VAL	(0xfffffff)
+#define		AT91_LCDC_DP3_4_VAL	(0xffff)
+#define		AT91_LCDC_DP4_5_VAL	(0xfffff)
+#define		AT91_LCDC_DP6_7_VAL	(0xfffffff)
+
+#define AT91_LCDC_PWRCON	0x083c		/* Power Control Register */
+#define		AT91_LCDC_PWR		(1    <<  0)	/* LCD Module Power Control */
+#define		AT91_LCDC_GUARDT	(0x7f <<  1)	/* Delay in Frame Period */
+#define		AT91_LCDC_BUSY		(1    << 31)	/* LCD Busy */
+
+#define AT91_LCDC_CONTRAST_CTR	0x0840		/* Contrast Control Register */
+#define		AT91_LCDC_PS		(3 << 0)	/* Contrast Counter Prescaler */
+#define			AT91_LCDC_PS_DIV1		(0 << 0)
+#define			AT91_LCDC_PS_DIV2		(1 << 0)
+#define			AT91_LCDC_PS_DIV4		(2 << 0)
+#define			AT91_LCDC_PS_DIV8		(3 << 0)
+#define		AT91_LCDC_POL		(1 << 2)	/* Polarity of output Pulse */
+#define			AT91_LCDC_POL_NEGATIVE		(0 << 2)
+#define			AT91_LCDC_POL_POSITIVE		(1 << 2)
+#define		AT91_LCDC_ENA		(1 << 3)	/* PWM generator Control */
+#define			AT91_LCDC_ENA_PWMDISABLE	(0 << 3)
+#define			AT91_LCDC_ENA_PWMENABLE		(1 << 3)
+
+#define AT91_LCDC_CONTRAST_VAL	0x0844		/* Contrast Value Register */
+#define		AT91_LCDC_CVAL		(0xff)		/* PWM compare value */
+
+#define AT91_LCDC_IER		0x0848		/* Interrupt Enable Register */
+#define AT91_LCDC_IDR		0x084c		/* Interrupt Disable Register */
+#define AT91_LCDC_IMR		0x0850		/* Interrupt Mask Register */
+#define AT91_LCDC_ISR		0x0854		/* Interrupt Enable Register */
+#define AT91_LCDC_ICR		0x0858		/* Interrupt Clear Register */
+#define		AT91_LCDC_LNI		(1 << 0)	/* Line Interrupt */
+#define		AT91_LCDC_LSTLNI	(1 << 1)	/* Last Line Interrupt */
+#define		AT91_LCDC_EOFI		(1 << 2)	/* DMA End Of Frame Interrupt */
+#define		AT91_LCDC_UFLWI		(1 << 4)	/* FIFO Underflow Interrupt */
+#define		AT91_LCDC_OWRI		(1 << 5)	/* FIFO Overwrite Interrupt */
+#define		AT91_LCDC_MERI		(1 << 6)	/* DMA Memory Error Interrupt */
+
+#define AT91_LCDC_LUT_(n)	(0x0c00 + ((n)*4))	/* Palette Entry 0..255 */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_mci.h b/include/asm-arm/arch-at91/at91_mci.h
new file mode 100644
index 0000000..40a9876
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_mci.h
@@ -0,0 +1,106 @@
+/*
+ * include/asm-arm/arch-at91/at91_mci.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * MultiMedia Card Interface (MCI) registers.
+ * Based on AT91RM9200 datasheet revision F.
+ *
+ * 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 AT91_MCI_H
+#define AT91_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		(7     <<  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		(3 << 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_SDIOIRQA	(1 <<  8)	/* SDIO Interrupt for Slot A */
+#define		At91_MCI_SDIOIRQB	(1 <<  9)	/* SDIO Interrupt for Slot B [AT91RM9200 only] */
+#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-at91/at91_pio.h b/include/asm-arm/arch-at91/at91_pio.h
new file mode 100644
index 0000000..84c3866
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_pio.h
@@ -0,0 +1,49 @@
+/*
+ * include/asm-arm/arch-at91/at91_pio.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Parallel I/O Controller (PIO) - System peripherals 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 AT91_PIO_H
+#define AT91_PIO_H
+
+#define PIO_PER		0x00	/* Enable Register */
+#define PIO_PDR		0x04	/* Disable Register */
+#define PIO_PSR		0x08	/* Status Register */
+#define PIO_OER		0x10	/* Output Enable Register */
+#define PIO_ODR		0x14	/* Output Disable Register */
+#define PIO_OSR		0x18	/* Output Status Register */
+#define PIO_IFER	0x20	/* Glitch Input Filter Enable */
+#define PIO_IFDR	0x24	/* Glitch Input Filter Disable */
+#define PIO_IFSR	0x28	/* Glitch Input Filter Status */
+#define PIO_SODR	0x30	/* Set Output Data Register */
+#define PIO_CODR	0x34	/* Clear Output Data Register */
+#define PIO_ODSR	0x38	/* Output Data Status Register */
+#define PIO_PDSR	0x3c	/* Pin Data Status Register */
+#define PIO_IER		0x40	/* Interrupt Enable Register */
+#define PIO_IDR		0x44	/* Interrupt Disable Register */
+#define PIO_IMR		0x48	/* Interrupt Mask Register */
+#define PIO_ISR		0x4c	/* Interrupt Status Register */
+#define PIO_MDER	0x50	/* Multi-driver Enable Register */
+#define PIO_MDDR	0x54	/* Multi-driver Disable Register */
+#define PIO_MDSR	0x58	/* Multi-driver Status Register */
+#define PIO_PUDR	0x60	/* Pull-up Disable Register */
+#define PIO_PUER	0x64	/* Pull-up Enable Register */
+#define PIO_PUSR	0x68	/* Pull-up Status Register */
+#define PIO_ASR		0x70	/* Peripheral A Select Register */
+#define PIO_BSR		0x74	/* Peripheral B Select Register */
+#define PIO_ABSR	0x78	/* AB Status Register */
+#define PIO_OWER	0xa0	/* Output Write Enable Register */
+#define PIO_OWDR	0xa4	/* Output Write Disable Register */
+#define PIO_OWSR	0xa8	/* Output Write Status Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_pit.h b/include/asm-arm/arch-at91/at91_pit.h
new file mode 100644
index 0000000..5026325
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_pit.h
@@ -0,0 +1,29 @@
+/*
+ * include/asm-arm/arch-at91/at91_pit.h
+ *
+ * Periodic Interval Timer (PIT) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * 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 AT91_PIT_H
+#define AT91_PIT_H
+
+#define AT91_PIT_MR		(AT91_PIT + 0x00)	/* Mode Register */
+#define		AT91_PIT_PITIEN		(1 << 25)		/* Timer Interrupt Enable */
+#define		AT91_PIT_PITEN		(1 << 24)		/* Timer Enabled */
+#define		AT91_PIT_PIV		(0xfffff)		/* Periodic Interval Value */
+
+#define AT91_PIT_SR		(AT91_PIT + 0x04)	/* Status Register */
+#define		AT91_PIT_PITS		(1 << 0)		/* Timer Status */
+
+#define AT91_PIT_PIVR		(AT91_PIT + 0x08)	/* Periodic Interval Value Register */
+#define AT91_PIT_PIIR		(AT91_PIT + 0x0c)	/* Periodic Interval Image Register */
+#define		AT91_PIT_PICNT		(0xfff << 20)		/* Interval Counter */
+#define		AT91_PIT_CPIV		(0xfffff)		/* Inverval Value */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_pmc.h b/include/asm-arm/arch-at91/at91_pmc.h
new file mode 100644
index 0000000..33ff5b6
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_pmc.h
@@ -0,0 +1,92 @@
+/*
+ * include/asm-arm/arch-at91/at91_pmc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Power Management Controller (PMC) - System peripherals 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 AT91_PMC_H
+#define AT91_PMC_H
+
+#define	AT91_PMC_SCER		(AT91_PMC + 0x00)	/* System Clock Enable Register */
+#define	AT91_PMC_SCDR		(AT91_PMC + 0x04)	/* System Clock Disable Register */
+
+#define	AT91_PMC_SCSR		(AT91_PMC + 0x08)	/* System Clock Status Register */
+#define		AT91_PMC_PCK		(1 <<  0)		/* Processor Clock */
+#define		AT91RM9200_PMC_UDP	(1 <<  1)		/* USB Devcice Port Clock [AT91RM9200 only] */
+#define		AT91RM9200_PMC_MCKUDP	(1 <<  2)		/* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */
+#define		AT91RM9200_PMC_UHP	(1 <<  4)		/* USB Host Port Clock [AT91RM9200 only] */
+#define		AT91SAM926x_PMC_UHP	(1 <<  6)		/* USB Host Port Clock [AT91SAM926x only] */
+#define		AT91SAM926x_PMC_UDP	(1 <<  7)		/* USB Devcice Port Clock [AT91SAM926x only] */
+#define		AT91_PMC_PCK0		(1 <<  8)		/* Programmable Clock 0 */
+#define		AT91_PMC_PCK1		(1 <<  9)		/* Programmable Clock 1 */
+#define		AT91_PMC_PCK2		(1 << 10)		/* Programmable Clock 2 */
+#define		AT91_PMC_PCK3		(1 << 11)		/* Programmable Clock 3 */
+#define		AT91_PMC_HCK0		(1 << 16)		/* AHB Clock (USB host) [AT91SAM9261 only] */
+#define		AT91_PMC_HCK1		(1 << 17)		/* AHB Clock (LCD) [AT91SAM9261 only] */
+
+#define	AT91_PMC_PCER		(AT91_PMC + 0x10)	/* Peripheral Clock Enable Register */
+#define	AT91_PMC_PCDR		(AT91_PMC + 0x14)	/* Peripheral Clock Disable Register */
+#define	AT91_PMC_PCSR		(AT91_PMC + 0x18)	/* Peripheral Clock Status Register */
+
+#define	AT91_CKGR_MOR		(AT91_PMC + 0x20)	/* Main Oscillator Register */
+#define		AT91_PMC_MOSCEN		(1    << 0)		/* Main Oscillator Enable */
+#define		AT91_PMC_OSCBYPASS	(1    << 1)		/* Oscillator Bypass [AT91SAM926x only] */
+#define		AT91_PMC_OSCOUNT	(0xff << 8)		/* Main Oscillator Start-up Time */
+
+#define	AT91_CKGR_MCFR		(AT91_PMC + 0x24)	/* Main Clock Frequency Register */
+#define		AT91_PMC_MAINF		(0xffff <<  0)		/* Main Clock Frequency */
+#define		AT91_PMC_MAINRDY	(1	<< 16)		/* Main Clock Ready */
+
+#define	AT91_CKGR_PLLAR		(AT91_PMC + 0x28)	/* PLL A Register */
+#define	AT91_CKGR_PLLBR		(AT91_PMC + 0x2c)	/* PLL B Register */
+#define		AT91_PMC_DIV		(0xff  <<  0)		/* Divider */
+#define		AT91_PMC_PLLCOUNT	(0x3f  <<  8)		/* PLL Counter */
+#define		AT91_PMC_OUT		(3     << 14)		/* PLL Clock Frequency Range */
+#define		AT91_PMC_MUL		(0x7ff << 16)		/* PLL Multiplier */
+#define		AT91_PMC_USB96M		(1     << 28)		/* Divider by 2 Enable (PLLB only) */
+
+#define	AT91_PMC_MCKR		(AT91_PMC + 0x30)	/* Master Clock Register */
+#define		AT91_PMC_CSS		(3 <<  0)		/* Master Clock Selection */
+#define			AT91_PMC_CSS_SLOW		(0 << 0)
+#define			AT91_PMC_CSS_MAIN		(1 << 0)
+#define			AT91_PMC_CSS_PLLA		(2 << 0)
+#define			AT91_PMC_CSS_PLLB		(3 << 0)
+#define		AT91_PMC_PRES		(7 <<  2)		/* Master Clock Prescaler */
+#define			AT91_PMC_PRES_1			(0 << 2)
+#define			AT91_PMC_PRES_2			(1 << 2)
+#define			AT91_PMC_PRES_4			(2 << 2)
+#define			AT91_PMC_PRES_8			(3 << 2)
+#define			AT91_PMC_PRES_16		(4 << 2)
+#define			AT91_PMC_PRES_32		(5 << 2)
+#define			AT91_PMC_PRES_64		(6 << 2)
+#define		AT91_PMC_MDIV		(3 <<  8)		/* Master Clock Division */
+#define			AT91_PMC_MDIV_1			(0 << 8)
+#define			AT91_PMC_MDIV_2			(1 << 8)
+#define			AT91_PMC_MDIV_3			(2 << 8)
+#define			AT91_PMC_MDIV_4			(3 << 8)
+
+#define	AT91_PMC_PCKR(n)	(AT91_PMC + 0x40 + ((n) * 4))	/* Programmable Clock 0-3 Registers */
+
+#define	AT91_PMC_IER		(AT91_PMC + 0x60)	/* Interrupt Enable Register */
+#define	AT91_PMC_IDR		(AT91_PMC + 0x64)	/* Interrupt Disable Register */
+#define	AT91_PMC_SR		(AT91_PMC + 0x68)	/* Status Register */
+#define		AT91_PMC_MOSCS		(1 <<  0)		/* MOSCS Flag */
+#define		AT91_PMC_LOCKA		(1 <<  1)		/* PLLA Lock */
+#define		AT91_PMC_LOCKB		(1 <<  2)		/* PLLB Lock */
+#define		AT91_PMC_MCKRDY		(1 <<  3)		/* Master Clock */
+#define		AT91_PMC_PCK0RDY	(1 <<  8)		/* Programmable Clock 0 */
+#define		AT91_PMC_PCK1RDY	(1 <<  9)		/* Programmable Clock 1 */
+#define		AT91_PMC_PCK2RDY	(1 << 10)		/* Programmable Clock 2 */
+#define		AT91_PMC_PCK3RDY	(1 << 11)		/* Programmable Clock 3 */
+#define	AT91_PMC_IMR		(AT91_PMC + 0x6c)	/* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_rstc.h b/include/asm-arm/arch-at91/at91_rstc.h
new file mode 100644
index 0000000..fb8d161
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_rstc.h
@@ -0,0 +1,38 @@
+/*
+ * include/asm-arm/arch-at91/at91_rstc.h
+ *
+ * Reset Controller (RSTC) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * 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 AT91_RSTC_H
+#define AT91_RSTC_H
+
+#define AT91_RSTC_CR		(AT91_RSTC + 0x00)	/* Reset Controller Control Register */
+#define		AT91_RSTC_PROCRST	(1 << 0)		/* Processor Reset */
+#define		AT91_RSTC_PERRST	(1 << 2)		/* Peripheral Reset */
+#define		AT91_RSTC_EXTRST	(1 << 3)		/* External Reset */
+#define		AT91_RSTC_KEY		(0xa5 << 24)		/* KEY Password */
+
+#define AT91_RSTC_SR		(AT91_RSTC + 0x04)	/* Reset Controller Status Register */
+#define		AT91_RSTC_URSTS		(1 << 0)		/* User Reset Status */
+#define		AT91_RSTC_RSTTYP	(7 << 8)		/* Reset Type */
+#define			AT91_RSTC_RSTTYP_GENERAL	(0 << 8)
+#define			AT91_RSTC_RSTTYP_WAKEUP		(1 << 8)
+#define			AT91_RSTC_RSTTYP_WATCHDOG	(2 << 8)
+#define			AT91_RSTC_RSTTYP_SOFTWARE	(3 << 8)
+#define			AT91_RSTC_RSTTYP_USER	(4 << 8)
+#define		AT91_RSTC_NRSTL		(1 << 16)		/* NRST Pin Level */
+#define		AT91_RSTC_SRCMP		(1 << 17)		/* Software Reset Command in Progress */
+
+#define AT91_RSTC_MR		(AT91_RSTC + 0x08)	/* Reset Controller Mode Register */
+#define		AT91_RSTC_URSTEN	(1 << 0)		/* User Reset Enable */
+#define		AT91_RSTC_URSTIEN	(1 << 4)		/* User Reset Interrupt Enable */
+#define		AT91_RSTC_ERSTL		(0xf << 8)		/* External Reset Length */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_rtc.h b/include/asm-arm/arch-at91/at91_rtc.h
new file mode 100644
index 0000000..af9bd28
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_rtc.h
@@ -0,0 +1,75 @@
+/*
+ * include/asm-arm/arch-at91/at91_rtc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Real Time Clock (RTC) - System peripheral 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 AT91_RTC_H
+#define AT91_RTC_H
+
+#define	AT91_RTC_CR		(AT91_RTC + 0x00)	/* Control Register */
+#define		AT91_RTC_UPDTIM		(1 <<  0)		/* Update Request Time Register */
+#define		AT91_RTC_UPDCAL		(1 <<  1)		/* Update Request Calendar Register */
+#define		AT91_RTC_TIMEVSEL	(3 <<  8)		/* Time Event Selection */
+#define			AT91_RTC_TIMEVSEL_MINUTE	(0 << 8)
+#define			AT91_RTC_TIMEVSEL_HOUR		(1 << 8)
+#define			AT91_RTC_TIMEVSEL_DAY24		(2 << 8)
+#define			AT91_RTC_TIMEVSEL_DAY12		(3 << 8)
+#define		AT91_RTC_CALEVSEL	(3 << 16)		/* Calendar Event Selection */
+#define			AT91_RTC_CALEVSEL_WEEK		(0 << 16)
+#define			AT91_RTC_CALEVSEL_MONTH		(1 << 16)
+#define			AT91_RTC_CALEVSEL_YEAR		(2 << 16)
+
+#define	AT91_RTC_MR		(AT91_RTC + 0x04)	/* Mode Register */
+#define			AT91_RTC_HRMOD		(1 <<  0)		/* 12/24 Hour Mode */
+
+#define	AT91_RTC_TIMR		(AT91_RTC + 0x08)	/* Time Register */
+#define		AT91_RTC_SEC		(0x7f <<  0)		/* Current Second */
+#define		AT91_RTC_MIN		(0x7f <<  8)		/* Current Minute */
+#define		AT91_RTC_HOUR		(0x3f << 16)		/* Current Hour */
+#define		AT91_RTC_AMPM		(1    << 22)		/* Ante Meridiem Post Meridiem Indicator */
+
+#define	AT91_RTC_CALR		(AT91_RTC + 0x0c)	/* Calendar Register */
+#define		AT91_RTC_CENT		(0x7f <<  0)		/* Current Century */
+#define		AT91_RTC_YEAR		(0xff <<  8)		/* Current Year */
+#define		AT91_RTC_MONTH		(0x1f << 16)		/* Current Month */
+#define		AT91_RTC_DAY		(7    << 21)		/* Current Day */
+#define		AT91_RTC_DATE		(0x3f << 24)		/* Current Date */
+
+#define	AT91_RTC_TIMALR		(AT91_RTC + 0x10)	/* Time Alarm Register */
+#define		AT91_RTC_SECEN		(1 <<  7)		/* Second Alarm Enable */
+#define		AT91_RTC_MINEN		(1 << 15)		/* Minute Alarm Enable */
+#define		AT91_RTC_HOUREN		(1 << 23)		/* Hour Alarm Enable */
+
+#define	AT91_RTC_CALALR		(AT91_RTC + 0x14)	/* Calendar Alarm Register */
+#define		AT91_RTC_MTHEN		(1 << 23)		/* Month Alarm Enable */
+#define		AT91_RTC_DATEEN		(1 << 31)		/* Date Alarm Enable */
+
+#define	AT91_RTC_SR		(AT91_RTC + 0x18)	/* Status Register */
+#define		AT91_RTC_ACKUPD		(1 <<  0)		/* Acknowledge for Update */
+#define		AT91_RTC_ALARM		(1 <<  1)		/* Alarm Flag */
+#define		AT91_RTC_SECEV		(1 <<  2)		/* Second Event */
+#define		AT91_RTC_TIMEV		(1 <<  3)		/* Time Event */
+#define		AT91_RTC_CALEV		(1 <<  4)		/* Calendar Event */
+
+#define	AT91_RTC_SCCR		(AT91_RTC + 0x1c)	/* Status Clear Command Register */
+#define	AT91_RTC_IER		(AT91_RTC + 0x20)	/* Interrupt Enable Register */
+#define	AT91_RTC_IDR		(AT91_RTC + 0x24)	/* Interrupt Disable Register */
+#define	AT91_RTC_IMR		(AT91_RTC + 0x28)	/* Interrupt Mask Register */
+
+#define	AT91_RTC_VER		(AT91_RTC + 0x2c)	/* Valid Entry Register */
+#define		AT91_RTC_NVTIM		(1 <<  0)		/* Non valid Time */
+#define		AT91_RTC_NVCAL		(1 <<  1)		/* Non valid Calendar */
+#define		AT91_RTC_NVTIMALR	(1 <<  2)		/* Non valid Time Alarm */
+#define		AT91_RTC_NVCALALR	(1 <<  3)		/* Non valid Calendar Alarm */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_rtt.h b/include/asm-arm/arch-at91/at91_rtt.h
new file mode 100644
index 0000000..bae1103
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_rtt.h
@@ -0,0 +1,32 @@
+/*
+ * include/asm-arm/arch-at91/at91_rtt.h
+ *
+ * Real-time Timer (RTT) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * 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 AT91_RTT_H
+#define AT91_RTT_H
+
+#define AT91_RTT_MR		(AT91_RTT + 0x00)	/* Real-time Mode Register */
+#define		AT91_RTT_RTPRES		(0xffff << 0)		/* Real-time Timer Prescaler Value */
+#define		AT91_RTT_ALMIEN		(1 << 16)		/* Alarm Interrupt Enable */
+#define		AT91_RTT_RTTINCIEN	(1 << 17)		/* Real Time Timer Increment Interrupt Enable */
+#define		AT91_RTT_RTTRST		(1 << 18)		/* Real Time Timer Restart */
+
+#define AT91_RTT_AR		(AT91_RTT + 0x04)	/* Real-time Alarm Register */
+#define		AT91_RTT_ALMV		(0xffffffff)		/* Alarm Value */
+
+#define AT91_RTT_VR		(AT91_RTT + 0x08)	/* Real-time Value Register */
+#define		AT91_RTT_CRTV		(0xffffffff)		/* Current Real-time Value */
+
+#define AT91_RTT_SR		(AT91_RTT + 0x0c)	/* Real-time Status Register */
+#define		AT91_RTT_ALMS		(1 << 0)		/* Real-time Alarm Status */
+#define		AT91_RTT_RTTINC		(1 << 1)		/* Real-time Timer Increment */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_shdwc.h b/include/asm-arm/arch-at91/at91_shdwc.h
new file mode 100644
index 0000000..795fcc2
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_shdwc.h
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/arch-at91/at91_shdwc.h
+ *
+ * Shutdown Controller (SHDWC) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * 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 AT91_SHDWC_H
+#define AT91_SHDWC_H
+
+#define AT91_SHDW_CR		(AT91_SHDWC + 0x00)	/* Shut Down Control Register */
+#define		AT91_SHDW_SHDW		(1    << 0)		/* Processor Reset */
+#define		AT91_SHDW_KEY		(0xff << 24)		/* KEY Password */
+
+#define AT91_SHDW_MR		(AT91_SHDWC + 0x04)	/* Shut Down Mode Register */
+#define		AT91_SHDW_WKMODE0	(3 << 0)		/* Wake-up 0 Mode Selection */
+#define			AT91_SHDW_WKMODE0_NONE		0
+#define			AT91_SHDW_WKMODE0_HIGH		1
+#define			AT91_SHDW_WKMODE0_LOW		2
+#define			AT91_SHDW_WKMODE0_ANYLEVEL	3
+#define		AT91_SHDW_CPTWK0	(0xf << 4)		/* Counter On Wake Up 0 */
+#define		AT91_SHDW_RTTWKEN	(1   << 16)		/* Real Time Timer Wake-up Enable */
+
+#define AT91_SHDW_SR		(AT91_SHDWC + 0x08)	/* Shut Down Status Register */
+#define		AT91_SHDW_WAKEUP0	(1 <<  0)		/* Wake-up 0 Status */
+#define		AT91_SHDW_RTTWK		(1 << 16)		/* Real-time Timer Wake-up */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_spi.h b/include/asm-arm/arch-at91/at91_spi.h
new file mode 100644
index 0000000..f9b9a84
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_spi.h
@@ -0,0 +1,81 @@
+/*
+ * include/asm-arm/arch-at91/at91_spi.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Serial Peripheral Interface (SPI) 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 AT91_SPI_H
+#define AT91_SPI_H
+
+#define AT91_SPI_CR			0x00		/* Control Register */
+#define		AT91_SPI_SPIEN		(1 <<  0)		/* SPI Enable */
+#define		AT91_SPI_SPIDIS		(1 <<  1)		/* SPI Disable */
+#define		AT91_SPI_SWRST		(1 <<  7)		/* SPI Software Reset */
+#define		AT91_SPI_LASTXFER	(1 << 24)		/* Last Transfer [SAM9261 only] */
+
+#define AT91_SPI_MR			0x04		/* Mode Register */
+#define		AT91_SPI_MSTR		(1    <<  0)		/* Master/Slave Mode */
+#define		AT91_SPI_PS		(1    <<  1)		/* Peripheral Select */
+#define			AT91_SPI_PS_FIXED	(0 << 1)
+#define			AT91_SPI_PS_VARIABLE	(1 << 1)
+#define		AT91_SPI_PCSDEC		(1    <<  2)		/* Chip Select Decode */
+#define		AT91_SPI_DIV32		(1    <<  3)		/* Clock Selection [AT91RM9200 only] */
+#define		AT91_SPI_MODFDIS	(1    <<  4)		/* Mode Fault Detection */
+#define		AT91_SPI_LLB		(1    <<  7)		/* Local Loopback Enable */
+#define		AT91_SPI_PCS		(0xf  << 16)		/* Peripheral Chip Select */
+#define		AT91_SPI_DLYBCS		(0xff << 24)		/* Delay Between Chip Selects */
+
+#define AT91_SPI_RDR		0x08			/* Receive Data Register */
+#define		AT91_SPI_RD		(0xffff <<  0)		/* Receive Data */
+#define		AT91_SPI_PCS		(0xf	<< 16)		/* Peripheral Chip Select */
+
+#define AT91_SPI_TDR		0x0c			/* Transmit Data Register */
+#define		AT91_SPI_TD		(0xffff <<  0)		/* Transmit Data */
+#define		AT91_SPI_PCS		(0xf	<< 16)		/* Peripheral Chip Select */
+#define		AT91_SPI_LASTXFER	(1	<< 24)		/* Last Transfer [SAM9261 only] */
+
+#define AT91_SPI_SR		0x10			/* Status Register */
+#define		AT91_SPI_RDRF		(1 <<  0)		/* Receive Data Register Full */
+#define		AT91_SPI_TDRE		(1 <<  1)		/* Transmit Data Register Full */
+#define		AT91_SPI_MODF		(1 <<  2)		/* Mode Fault Error */
+#define		AT91_SPI_OVRES		(1 <<  3)		/* Overrun Error Status */
+#define		AT91_SPI_ENDRX		(1 <<  4)		/* End of RX buffer */
+#define		AT91_SPI_ENDTX		(1 <<  5)		/* End of TX buffer */
+#define		AT91_SPI_RXBUFF		(1 <<  6)		/* RX Buffer Full */
+#define		AT91_SPI_TXBUFE		(1 <<  7)		/* TX Buffer Empty */
+#define		AT91_SPI_NSSR		(1 <<  8)		/* NSS Rising [SAM9261 only] */
+#define		AT91_SPI_TXEMPTY	(1 <<  9)		/* Transmission Register Empty [SAM9261 only] */
+#define		AT91_SPI_SPIENS		(1 << 16)		/* SPI Enable Status */
+
+#define AT91_SPI_IER		0x14			/* Interrupt Enable Register */
+#define AT91_SPI_IDR		0x18			/* Interrupt Disable Register */
+#define AT91_SPI_IMR		0x1c			/* Interrupt Mask Register */
+
+#define AT91_SPI_CSR(n)		(0x30 + ((n) * 4))	/* Chip Select Registers 0-3 */
+#define		AT91_SPI_CPOL		(1    <<  0)		/* Clock Polarity */
+#define		AT91_SPI_NCPHA		(1    <<  1)		/* Clock Phase */
+#define		AT91_SPI_CSAAT		(1    <<  3)		/* Chip Select Active After Transfer [SAM9261 only] */
+#define		AT91_SPI_BITS		(0xf  <<  4)		/* Bits Per Transfer */
+#define			AT91_SPI_BITS_8		(0 << 4)
+#define			AT91_SPI_BITS_9		(1 << 4)
+#define			AT91_SPI_BITS_10	(2 << 4)
+#define			AT91_SPI_BITS_11	(3 << 4)
+#define			AT91_SPI_BITS_12	(4 << 4)
+#define			AT91_SPI_BITS_13	(5 << 4)
+#define			AT91_SPI_BITS_14	(6 << 4)
+#define			AT91_SPI_BITS_15	(7 << 4)
+#define			AT91_SPI_BITS_16	(8 << 4)
+#define		AT91_SPI_SCBR		(0xff <<  8)		/* Serial Clock Baud Rate */
+#define		AT91_SPI_DLYBS		(0xff << 16)		/* Delay before SPCK */
+#define		AT91_SPI_DLYBCT		(0xff << 24)		/* Delay between Consecutive Transfers */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_ssc.h b/include/asm-arm/arch-at91/at91_ssc.h
new file mode 100644
index 0000000..0ecc734
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_ssc.h
@@ -0,0 +1,106 @@
+/*
+ * include/asm-arm/arch-at91/at91_ssc.h
+ *
+ * Copyright (C) SAN People
+ *
+ * Serial Synchronous Controller (SSC) 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 AT91_SSC_H
+#define AT91_SSC_H
+
+#define AT91_SSC_CR		0x00	/* Control Register */
+#define		AT91_SSC_RXEN		(1 <<  0)	/* Receive Enable */
+#define		AT91_SSC_RXDIS		(1 <<  1)	/* Receive Disable */
+#define		AT91_SSC_TXEN		(1 <<  8)	/* Transmit Enable */
+#define		AT91_SSC_TXDIS		(1 <<  9)	/* Transmit Disable */
+#define		AT91_SSC_SWRST		(1 << 15)	/* Software Reset */
+
+#define AT91_SSC_CMR		0x04	/* Clock Mode Register */
+#define		AT91_SSC_CMR_DIV	(0xfff << 0)	/* Clock Divider */
+
+#define AT91_SSC_RCMR		0x10	/* Receive Clock Mode Register */
+#define		AT91_SSC_CKS		(3    <<  0)	/* Clock Selection */
+#define			AT91_SSC_CKS_DIV		(0 << 0)
+#define			AT91_SSC_CKS_CLOCK		(1 << 0)
+#define			AT91_SSC_CKS_PIN		(2 << 0)
+#define		AT91_SSC_CKO		(7    <<  2)	/* Clock Output Mode Selection */
+#define			AT91_SSC_CKO_NONE		(0 << 2)
+#define			AT91_SSC_CKO_CONTINUOUS		(1 << 2)
+#define		AT91_SSC_CKI		(1    <<  5)	/* Clock Inversion */
+#define			AT91_SSC_CKI_FALLING		(0 << 5)
+#define			AT91_SSC_CK_RISING		(1 << 5)
+#define		AT91_SSC_CKG		(1    <<  6)	/* Receive Clock Gating Selection [AT91SAM9261 only] */
+#define			AT91_SSC_CKG_NONE		(0 << 6)
+#define			AT91_SSC_CKG_RFLOW		(1 << 6)
+#define			AT91_SSC_CKG_RFHIGH		(2 << 6)
+#define		AT91_SSC_START		(0xf  <<  8)	/* Start Selection */
+#define			AT91_SSC_START_CONTINUOUS	(0 << 8)
+#define			AT91_SSC_START_TX_RX		(1 << 8)
+#define			AT91_SSC_START_LOW_RF		(2 << 8)
+#define			AT91_SSC_START_HIGH_RF		(3 << 8)
+#define			AT91_SSC_START_FALLING_RF	(4 << 8)
+#define			AT91_SSC_START_RISING_RF	(5 << 8)
+#define			AT91_SSC_START_LEVEL_RF		(6 << 8)
+#define			AT91_SSC_START_EDGE_RF		(7 << 8)
+#define		AT91_SSC_STOP		(1    << 12)	/* Receive Stop Selection [AT91SAM9261 only] */
+#define		AT91_SSC_STTDLY		(0xff << 16)	/* Start Delay */
+#define		AT91_SSC_PERIOD		(0xff << 24)	/* Period Divider Selection */
+
+#define AT91_SSC_RFMR		0x14	/* Receive Frame Mode Register */
+#define		AT91_SSC_DATALEN	(0x1f <<  0)	/* Data Length */
+#define		AT91_SSC_LOOP		(1    <<  5)	/* Loop Mode */
+#define		AT91_SSC_MSBF		(1    <<  7)	/* Most Significant Bit First */
+#define		AT91_SSC_DATNB		(0xf  <<  8)	/* Data Number per Frame */
+#define		AT91_SSC_FSLEN		(0xf  << 16)	/* Frame Sync Length */
+#define		AT91_SSC_FSOS		(7    << 20)	/* Frame Sync Output Selection */
+#define			AT91_SSC_FSOS_NONE		(0 << 20)
+#define			AT91_SSC_FSOS_NEGATIVE		(1 << 20)
+#define			AT91_SSC_FSOS_POSITIVE		(2 << 20)
+#define			AT91_SSC_FSOS_LOW		(3 << 20)
+#define			AT91_SSC_FSOS_HIGH		(4 << 20)
+#define			AT91_SSC_FSOS_TOGGLE		(5 << 20)
+#define		AT91_SSC_FSEDGE		(1    << 24)	/* Frame Sync Edge Detection */
+#define			AT91_SSC_FSEDGE_POSITIVE	(0 << 24)
+#define			AT91_SSC_FSEDGE_NEGATIVE	(1 << 24)
+
+#define AT91_SSC_TCMR		0x18	/* Transmit Clock Mode Register */
+#define AT91_SSC_TFMR		0x1c	/* Transmit Fram Mode Register */
+#define		AT91_SSC_DATDEF		(1 <<  5)	/* Data Default Value */
+#define		AT91_SSC_FSDEN		(1 << 23)	/* Frame Sync Data Enable */
+
+#define AT91_SSC_RHR		0x20	/* Receive Holding Register */
+#define AT91_SSC_THR		0x24	/* Transmit Holding Register */
+#define AT91_SSC_RSHR		0x30	/* Receive Sync Holding Register */
+#define AT91_SSC_TSHR		0x34	/* Transmit Sync Holding Register */
+
+#define AT91_SSC_RC0R		0x38	/* Receive Compare 0 Register [AT91SAM9261 only] */
+#define AT91_SSC_RC1R		0x3c	/* Receive Compare 1 Register [AT91SAM9261 only] */
+
+#define AT91_SSC_SR		0x40	/* Status Register */
+#define		AT91_SSC_TXRDY		(1 <<  0)	/* Transmit Ready */
+#define		AT91_SSC_TXEMPTY	(1 <<  1)	/* Transmit Empty */
+#define		AT91_SSC_ENDTX		(1 <<  2)	/* End of Transmission */
+#define		AT91_SSC_TXBUFE		(1 <<  3)	/* Transmit Buffer Empty */
+#define		AT91_SSC_RXRDY		(1 <<  4)	/* Receive Ready */
+#define		AT91_SSC_OVRUN		(1 <<  5)	/* Receive Overrun */
+#define		AT91_SSC_ENDRX		(1 <<  6)	/* End of Reception */
+#define		AT91_SSC_RXBUFF		(1 <<  7)	/* Receive Buffer Full */
+#define		AT91_SSC_CP0		(1 <<  8)	/* Compare 0 [AT91SAM9261 only] */
+#define		AT91_SSC_CP1		(1 <<  9)	/* Compare 1 [AT91SAM9261 only] */
+#define		AT91_SSC_TXSYN		(1 << 10)	/* Transmit Sync */
+#define		AT91_SSC_RXSYN		(1 << 11)	/* Receive Sync */
+#define		AT91_SSC_TXENA		(1 << 16)	/* Transmit Enable */
+#define		AT91_SSC_RXENA		(1 << 17)	/* Receive Enable */
+
+#define AT91_SSC_IER		0x44	/* Interrupt Enable Register */
+#define AT91_SSC_IDR		0x48	/* Interrupt Disable Register */
+#define AT91_SSC_IMR		0x4c	/* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_st.h b/include/asm-arm/arch-at91/at91_st.h
new file mode 100644
index 0000000..30446e2e
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_st.h
@@ -0,0 +1,49 @@
+/*
+ * include/asm-arm/arch-at91/at91_st.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * System Timer (ST) - System peripherals 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 AT91_ST_H
+#define AT91_ST_H
+
+#define	AT91_ST_CR		(AT91_ST + 0x00)	/* Control Register */
+#define 	AT91_ST_WDRST		(1 << 0)		/* Watchdog Timer Restart */
+
+#define	AT91_ST_PIMR		(AT91_ST + 0x04)	/* Period Interval Mode Register */
+#define		AT91_ST_PIV		(0xffff <<  0)		/* Period Interval Value */
+
+#define	AT91_ST_WDMR		(AT91_ST + 0x08)	/* Watchdog Mode Register */
+#define		AT91_ST_WDV		(0xffff <<  0)		/* Watchdog Counter Value */
+#define		AT91_ST_RSTEN		(1	<< 16)		/* Reset Enable */
+#define		AT91_ST_EXTEN		(1	<< 17)		/* External Signal Assertion Enable */
+
+#define	AT91_ST_RTMR		(AT91_ST + 0x0c)	/* Real-time Mode Register */
+#define		AT91_ST_RTPRES		(0xffff <<  0)		/* Real-time Prescalar Value */
+
+#define	AT91_ST_SR		(AT91_ST + 0x10)	/* Status Register */
+#define		AT91_ST_PITS		(1 << 0)		/* Period Interval Timer Status */
+#define		AT91_ST_WDOVF		(1 << 1) 		/* Watchdog Overflow */
+#define		AT91_ST_RTTINC		(1 << 2) 		/* Real-time Timer Increment */
+#define		AT91_ST_ALMS		(1 << 3) 		/* Alarm Status */
+
+#define	AT91_ST_IER		(AT91_ST + 0x14)	/* Interrupt Enable Register */
+#define	AT91_ST_IDR		(AT91_ST + 0x18)	/* Interrupt Disable Register */
+#define	AT91_ST_IMR		(AT91_ST + 0x1c)	/* Interrupt Mask Register */
+
+#define	AT91_ST_RTAR		(AT91_ST + 0x20)	/* Real-time Alarm Register */
+#define		AT91_ST_ALMV		(0xfffff << 0)		/* Alarm Value */
+
+#define	AT91_ST_CRTR		(AT91_ST + 0x24)	/* Current Real-time Register */
+#define		AT91_ST_CRTV		(0xfffff << 0)		/* Current Real-Time Value */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_tc.h b/include/asm-arm/arch-at91/at91_tc.h
new file mode 100644
index 0000000..b85d3fa
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_tc.h
@@ -0,0 +1,146 @@
+/*
+ * include/asm-arm/arch-at91/at91_tc.h
+ *
+ * Copyright (C) SAN People
+ *
+ * Timer/Counter Unit (TC) 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 AT91_TC_H
+#define AT91_TC_H
+
+#define AT91_TC_BCR		0xc0		/* TC Block Control Register */
+#define		AT91_TC_SYNC		(1 << 0)	/* Synchro Command */
+
+#define AT91_TC_BMR		0xc4		/* TC Block Mode Register */
+#define		AT91_TC_TC0XC0S		(3 << 0)	/* External Clock Signal 0 Selection */
+#define			AT91_TC_TC0XC0S_TCLK0		(0 << 0)
+#define			AT91_TC_TC0XC0S_NONE		(1 << 0)
+#define			AT91_TC_TC0XC0S_TIOA1		(2 << 0)
+#define			AT91_TC_TC0XC0S_TIOA2		(3 << 0)
+#define		AT91_TC_TC1XC1S		(3 << 2)	/* External Clock Signal 1 Selection */
+#define			AT91_TC_TC1XC1S_TCLK1		(0 << 2)
+#define			AT91_TC_TC1XC1S_NONE		(1 << 2)
+#define			AT91_TC_TC1XC1S_TIOA0		(2 << 2)
+#define			AT91_TC_TC1XC1S_TIOA2		(3 << 2)
+#define		AT91_TC_TC2XC2S		(3 << 4)	/* External Clock Signal 2 Selection */
+#define			AT91_TC_TC2XC2S_TCLK2		(0 << 4)
+#define			AT91_TC_TC2XC2S_NONE		(1 << 4)
+#define			AT91_TC_TC2XC2S_TIOA0		(2 << 4)
+#define			AT91_TC_TC2XC2S_TIOA1		(3 << 4)
+
+
+#define AT91_TC_CCR		0x00		/* Channel Control Register */
+#define		AT91_TC_CLKEN		(1 << 0)	/* Counter Clock Enable Command */
+#define		AT91_TC_CLKDIS		(1 << 1)	/* Counter CLock Disable Command */
+#define		AT91_TC_SWTRG		(1 << 2)	/* Software Trigger Command */
+
+#define AT91_TC_CMR		0x04		/* Channel Mode Register */
+#define		AT91_TC_TCCLKS		(7 << 0)	/* Capture/Waveform Mode: Clock Selection */
+#define			AT91_TC_TIMER_CLOCK1		(0 << 0)
+#define			AT91_TC_TIMER_CLOCK2		(1 << 0)
+#define			AT91_TC_TIMER_CLOCK3		(2 << 0)
+#define			AT91_TC_TIMER_CLOCK4		(3 << 0)
+#define			AT91_TC_TIMER_CLOCK5		(4 << 0)
+#define			AT91_TC_XC0			(5 << 0)
+#define			AT91_TC_XC1			(6 << 0)
+#define			AT91_TC_XC2			(7 << 0)
+#define		AT91_TC_CLKI		(1 << 3)	/* Capture/Waveform Mode: Clock Invert */
+#define		AT91_TC_BURST		(3 << 4)	/* Capture/Waveform Mode: Burst Signal Selection */
+#define		AT91_TC_LDBSTOP		(1 << 6)	/* Capture Mode: Counter Clock Stopped with TB Loading */
+#define		AT91_TC_LDBDIS		(1 << 7)	/* Capture Mode: Counter Clock Disable with RB Loading */
+#define		AT91_TC_ETRGEDG		(3 << 8)	/* Capture Mode: External Trigger Edge Selection */
+#define		AT91_TC_ABETRG		(1 << 10)	/* Capture Mode: TIOA or TIOB External Trigger Selection */
+#define		AT91_TC_CPCTRG		(1 << 14)	/* Capture Mode: RC Compare Trigger Enable */
+#define		AT91_TC_WAVE		(1 << 15)	/* Capture/Waveform mode */
+#define		AT91_TC_LDRA		(3 << 16)	/* Capture Mode: RA Loading Selection */
+#define		AT91_TC_LDRB		(3 << 18)	/* Capture Mode: RB Loading Selection */
+
+#define		AT91_TC_CPCSTOP		(1 <<  6)	/* Waveform Mode: Counter Clock Stopped with RC Compare */
+#define		AT91_TC_CPCDIS		(1 <<  7)	/* Waveform Mode: Counter Clock Disable with RC Compare */
+#define		AT91_TC_EEVTEDG		(3 <<  8)	/* Waveform Mode: External Event Edge Selection */
+#define			AT91_TC_EEVTEDG_NONE		(0 << 8)
+#define			AT91_TC_EEVTEDG_RISING		(1 << 8)
+#define			AT91_TC_EEVTEDG_FALLING		(2 << 8)
+#define			AT91_TC_EEVTEDG_BOTH		(3 << 8)
+#define		AT91_TC_EEVT		(3 << 10)	/* Waveform Mode: External Event Selection */
+#define			AT91_TC_EEVT_TIOB		(0 << 10)
+#define			AT91_TC_EEVT_XC0		(1 << 10)
+#define			AT91_TC_EEVT_XC1		(2 << 10)
+#define			AT91_TC_EEVT_XC2		(3 << 10)
+#define		AT91_TC_ENETRG		(1 << 12)	/* Waveform Mode: External Event Trigger Enable */
+#define		AT91_TC_WAVESEL		(3 << 13)	/* Waveform Mode: Waveform Selection */
+#define			AT91_TC_WAVESEL_UP		(0 << 13)
+#define			AT91_TC_WAVESEL_UP_AUTO		(2 << 13)
+#define			AT91_TC_WAVESEL_UPDOWN		(1 << 13)
+#define			AT91_TC_WAVESEL_UPDOWN_AUTO	(3 << 13)
+#define		AT91_TC_ACPA		(3 << 16)	/* Waveform Mode: RA Compare Effect on TIOA */
+#define			AT91_TC_ACPA_NONE		(0 << 16)
+#define			AT91_TC_ACPA_SET		(1 << 16)
+#define			AT91_TC_ACPA_CLEAR		(2 << 16)
+#define			AT91_TC_ACPA_TOGGLE		(3 << 16)
+#define		AT91_TC_ACPC		(3 << 18)	/* Waveform Mode: RC Compre Effect on TIOA */
+#define			AT91_TC_ACPC_NONE		(0 << 18)
+#define			AT91_TC_ACPC_SET		(1 << 18)
+#define			AT91_TC_ACPC_CLEAR		(2 << 18)
+#define			AT91_TC_ACPC_TOGGLE		(3 << 18)
+#define		AT91_TC_AEEVT		(3 << 20)	/* Waveform Mode: External Event Effect on TIOA */
+#define			AT91_TC_AEEVT_NONE		(0 << 20)
+#define			AT91_TC_AEEVT_SET		(1 << 20)
+#define			AT91_TC_AEEVT_CLEAR		(2 << 20)
+#define			AT91_TC_AEEVT_TOGGLE		(3 << 20)
+#define		AT91_TC_ASWTRG		(3 << 22)	/* Waveform Mode: Software Trigger Effect on TIOA */
+#define			AT91_TC_ASWTRG_NONE		(0 << 22)
+#define			AT91_TC_ASWTRG_SET		(1 << 22)
+#define			AT91_TC_ASWTRG_CLEAR		(2 << 22)
+#define			AT91_TC_ASWTRG_TOGGLE		(3 << 22)
+#define		AT91_TC_BCPB		(3 << 24)	/* Waveform Mode: RB Compare Effect on TIOB */
+#define			AT91_TC_BCPB_NONE		(0 << 24)
+#define			AT91_TC_BCPB_SET		(1 << 24)
+#define			AT91_TC_BCPB_CLEAR		(2 << 24)
+#define			AT91_TC_BCPB_TOGGLE		(3 << 24)
+#define		AT91_TC_BCPC		(3 << 26)	/* Waveform Mode: RC Compare Effect on TIOB */
+#define			AT91_TC_BCPC_NONE		(0 << 26)
+#define			AT91_TC_BCPC_SET		(1 << 26)
+#define			AT91_TC_BCPC_CLEAR		(2 << 26)
+#define			AT91_TC_BCPC_TOGGLE		(3 << 26)
+#define		AT91_TC_BEEVT		(3 << 28)	/* Waveform Mode: External Event Effect on TIOB */
+#define			AT91_TC_BEEVT_NONE		(0 << 28)
+#define			AT91_TC_BEEVT_SET		(1 << 28)
+#define			AT91_TC_BEEVT_CLEAR		(2 << 28)
+#define			AT91_TC_BEEVT_TOGGLE		(3 << 28)
+#define		AT91_TC_BSWTRG		(3 << 30)	/* Waveform Mode: Software Trigger Effect on TIOB */
+#define			AT91_TC_BSWTRG_NONE		(0 << 30)
+#define			AT91_TC_BSWTRG_SET		(1 << 30)
+#define			AT91_TC_BSWTRG_CLEAR		(2 << 30)
+#define			AT91_TC_BSWTRG_TOGGLE		(3 << 30)
+
+#define AT91_TC_CV		0x10		/* Counter Value */
+#define AT91_TC_RA		0x14		/* Register A */
+#define AT91_TC_RB		0x18		/* Register B */
+#define AT91_TC_RC		0x1c		/* Register C */
+
+#define AT91_TC_SR		0x20		/* Status Register */
+#define		AT91_TC_COVFS		(1 <<  0)	/* Counter Overflow Status */
+#define		AT91_TC_LOVRS		(1 <<  1)	/* Load Overrun Status */
+#define		AT91_TC_CPAS		(1 <<  2)	/* RA Compare Status */
+#define		AT91_TC_CPBS		(1 <<  3)	/* RB Compare Status */
+#define		AT91_TC_CPCS		(1 <<  4)	/* RC Compare Status */
+#define		AT91_TC_LDRAS		(1 <<  5)	/* RA Loading Status */
+#define		AT91_TC_LDRBS		(1 <<  6)	/* RB Loading Status */
+#define		AT91_TC_ETRGS		(1 <<  7)	/* External Trigger Status */
+#define		AT91_TC_CLKSTA		(1 << 16)	/* Clock Enabling Status */
+#define		AT91_TC_MTIOA		(1 << 17)	/* TIOA Mirror */
+#define		AT91_TC_MTIOB		(1 << 18)	/* TIOB Mirror */
+
+#define AT91_TC_IER		0x24		/* Interrupt Enable Register */
+#define AT91_TC_IDR		0x28		/* Interrupt Disable Register */
+#define AT91_TC_IMR		0x2c		/* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91_twi.h b/include/asm-arm/arch-at91/at91_twi.h
new file mode 100644
index 0000000..ca9a907
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_twi.h
@@ -0,0 +1,57 @@
+/*
+ * include/asm-arm/arch-at91/at91_twi.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Two-wire Interface (TWI) 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 AT91_TWI_H
+#define AT91_TWI_H
+
+#define	AT91_TWI_CR		0x00		/* Control Register */
+#define		AT91_TWI_START		(1 <<  0)	/* Send a Start Condition */
+#define		AT91_TWI_STOP		(1 <<  1)	/* Send a Stop Condition */
+#define		AT91_TWI_MSEN		(1 <<  2)	/* Master Transfer Enable */
+#define		AT91_TWI_MSDIS		(1 <<  3)	/* Master Transfer Disable */
+#define		AT91_TWI_SWRST		(1 <<  7)	/* Software Reset */
+
+#define	AT91_TWI_MMR		0x04		/* Master Mode Register */
+#define		AT91_TWI_IADRSZ		(3    <<  8)	/* Internal Device Address Size */
+#define			AT91_TWI_IADRSZ_NO		(0 << 8)
+#define			AT91_TWI_IADRSZ_1		(1 << 8)
+#define			AT91_TWI_IADRSZ_2		(2 << 8)
+#define			AT91_TWI_IADRSZ_3		(3 << 8)
+#define		AT91_TWI_MREAD		(1    << 12)	/* Master Read Direction */
+#define		AT91_TWI_DADR		(0x7f << 16)	/* Device Address */
+
+#define	AT91_TWI_IADR		0x0c		/* Internal Address Register */
+
+#define	AT91_TWI_CWGR		0x10		/* Clock Waveform Generator Register */
+#define		AT91_TWI_CLDIV		(0xff <<  0)	/* Clock Low Divisor */
+#define		AT91_TWI_CHDIV		(0xff <<  8)	/* Clock High Divisor */
+#define		AT91_TWI_CKDIV		(7    << 16)	/* Clock Divider */
+
+#define	AT91_TWI_SR		0x20		/* Status Register */
+#define		AT91_TWI_TXCOMP		(1 <<  0)	/* Transmission Complete */
+#define		AT91_TWI_RXRDY		(1 <<  1)	/* Receive Holding Register Ready */
+#define		AT91_TWI_TXRDY		(1 <<  2)	/* Transmit Holding Register Ready */
+#define		AT91_TWI_OVRE		(1 <<  6)	/* Overrun Error [AT91RM9200 only] */
+#define		AT91_TWI_UNRE		(1 <<  7)	/* Underrun Error [AT91RM9200 only] */
+#define		AT91_TWI_NACK		(1 <<  8)	/* Not Acknowledged */
+
+#define	AT91_TWI_IER		0x24		/* Interrupt Enable Register */
+#define	AT91_TWI_IDR		0x28		/* Interrupt Disable Register */
+#define	AT91_TWI_IMR		0x2c		/* Interrupt Mask Register */
+#define	AT91_TWI_RHR		0x30		/* Receive Holding Register */
+#define	AT91_TWI_THR		0x34		/* Transmit Holding Register */
+
+#endif
+
diff --git a/include/asm-arm/arch-at91/at91_wdt.h b/include/asm-arm/arch-at91/at91_wdt.h
new file mode 100644
index 0000000..7251a34
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91_wdt.h
@@ -0,0 +1,34 @@
+/*
+ * include/asm-arm/arch-at91/at91_wdt.h
+ *
+ * Watchdog Timer (WDT) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * 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 AT91_WDT_H
+#define AT91_WDT_H
+
+#define AT91_WDT_CR		(AT91_WDT + 0x00)	/* Watchdog Control Register */
+#define		AT91_WDT_WDRSTT		(1    << 0)		/* Restart */
+#define		AT91_WDT_KEY		(0xff << 24)		/* KEY Password */
+
+#define AT91_WDT_MR		(AT91_WDT + 0x04)	/* Watchdog Mode Register */
+#define		AT91_WDT_WDV		(0xfff << 0)		/* Counter Value */
+#define		AT91_WDT_WDFIEN		(1     << 12)		/* Fault Interrupt Enable */
+#define		AT91_WDT_WDRSTEN	(1     << 13)		/* Reset Processor */
+#define		AT91_WDT_WDRPROC	(1     << 14)		/* Timer Restart */
+#define		AT91_WDT_WDDIS		(1     << 15)		/* Watchdog Disable */
+#define		AT91_WDT_WDD		(0xfff << 16)		/* Delta Value */
+#define		AT91_WDT_WDDBGHLT	(1     << 28)		/* Debug Halt */
+#define		AT91_WDT_WDIDLEHLT	(1     << 29)		/* Idle Halt */
+
+#define AT91_WDT_SR		(AT91_WDT + 0x08)	/* Watchdog Status Register */
+#define		AT91_WDT_WDUNF		(1 << 0)		/* Watchdog Underflow */
+#define		AT91_WDT_WDERR		(1 << 1)		/* Watchdog Error */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91rm9200.h b/include/asm-arm/arch-at91/at91rm9200.h
new file mode 100644
index 0000000..a12ac8a
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91rm9200.h
@@ -0,0 +1,291 @@
+/*
+ * include/asm-arm/arch-at91/at91rm9200.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Common definitions.
+ * 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_H
+#define AT91RM9200_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91_ID_FIQ		0	/* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS		1	/* System Peripheral */
+#define AT91RM9200_ID_PIOA	2	/* Parallel IO Controller A */
+#define AT91RM9200_ID_PIOB	3	/* Parallel IO Controller B */
+#define AT91RM9200_ID_PIOC	4	/* Parallel IO Controller C */
+#define AT91RM9200_ID_PIOD	5	/* Parallel IO Controller D */
+#define AT91RM9200_ID_US0	6	/* USART 0 */
+#define AT91RM9200_ID_US1	7	/* USART 1 */
+#define AT91RM9200_ID_US2	8	/* USART 2 */
+#define AT91RM9200_ID_US3	9	/* USART 3 */
+#define AT91RM9200_ID_MCI	10	/* Multimedia Card Interface */
+#define AT91RM9200_ID_UDP	11	/* USB Device Port */
+#define AT91RM9200_ID_TWI	12	/* Two-Wire Interface */
+#define AT91RM9200_ID_SPI	13	/* Serial Peripheral Interface */
+#define AT91RM9200_ID_SSC0	14	/* Serial Synchronous Controller 0 */
+#define AT91RM9200_ID_SSC1	15	/* Serial Synchronous Controller 1 */
+#define AT91RM9200_ID_SSC2	16	/* Serial Synchronous Controller 2 */
+#define AT91RM9200_ID_TC0	17	/* Timer Counter 0 */
+#define AT91RM9200_ID_TC1	18	/* Timer Counter 1 */
+#define AT91RM9200_ID_TC2	19	/* Timer Counter 2 */
+#define AT91RM9200_ID_TC3	20	/* Timer Counter 3 */
+#define AT91RM9200_ID_TC4	21	/* Timer Counter 4 */
+#define AT91RM9200_ID_TC5	22	/* Timer Counter 5 */
+#define AT91RM9200_ID_UHP	23	/* USB Host port */
+#define AT91RM9200_ID_EMAC	24	/* Ethernet MAC */
+#define AT91RM9200_ID_IRQ0	25	/* Advanced Interrupt Controller (IRQ0) */
+#define AT91RM9200_ID_IRQ1	26	/* Advanced Interrupt Controller (IRQ1) */
+#define AT91RM9200_ID_IRQ2	27	/* Advanced Interrupt Controller (IRQ2) */
+#define AT91RM9200_ID_IRQ3	28	/* Advanced Interrupt Controller (IRQ3) */
+#define AT91RM9200_ID_IRQ4	29	/* Advanced Interrupt Controller (IRQ4) */
+#define AT91RM9200_ID_IRQ5	30	/* Advanced Interrupt Controller (IRQ5) */
+#define AT91RM9200_ID_IRQ6	31	/* Advanced Interrupt Controller (IRQ6) */
+
+
+/*
+ * Peripheral physical base addresses.
+ */
+#define AT91RM9200_BASE_TCB0	0xfffa0000
+#define AT91RM9200_BASE_TC0	0xfffa0000
+#define AT91RM9200_BASE_TC1	0xfffa0040
+#define AT91RM9200_BASE_TC2	0xfffa0080
+#define AT91RM9200_BASE_TCB1	0xfffa4000
+#define AT91RM9200_BASE_TC3	0xfffa4000
+#define AT91RM9200_BASE_TC4	0xfffa4040
+#define AT91RM9200_BASE_TC5	0xfffa4080
+#define AT91RM9200_BASE_UDP	0xfffb0000
+#define AT91RM9200_BASE_MCI	0xfffb4000
+#define AT91RM9200_BASE_TWI	0xfffb8000
+#define AT91RM9200_BASE_EMAC	0xfffbc000
+#define AT91RM9200_BASE_US0	0xfffc0000
+#define AT91RM9200_BASE_US1	0xfffc4000
+#define AT91RM9200_BASE_US2	0xfffc8000
+#define AT91RM9200_BASE_US3	0xfffcc000
+#define AT91RM9200_BASE_SSC0	0xfffd0000
+#define AT91RM9200_BASE_SSC1	0xfffd4000
+#define AT91RM9200_BASE_SSC2	0xfffd8000
+#define AT91RM9200_BASE_SPI	0xfffe0000
+#define AT91_BASE_SYS		0xfffff000
+
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_AIC	(0xfffff000 - AT91_BASE_SYS)	/* Advanced Interrupt Controller */
+#define AT91_DBGU	(0xfffff200 - AT91_BASE_SYS)	/* Debug Unit */
+#define AT91_PIOA	(0xfffff400 - AT91_BASE_SYS)	/* PIO Controller A */
+#define AT91_PIOB	(0xfffff600 - AT91_BASE_SYS)	/* PIO Controller B */
+#define AT91_PIOC	(0xfffff800 - AT91_BASE_SYS)	/* PIO Controller C */
+#define AT91_PIOD	(0xfffffa00 - AT91_BASE_SYS)	/* PIO Controller D */
+#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)	/* Power Management Controller */
+#define AT91_ST		(0xfffffd00 - AT91_BASE_SYS)	/* System Timer */
+#define AT91_RTC	(0xfffffe00 - AT91_BASE_SYS)	/* Real-Time Clock */
+#define AT91_MC		(0xffffff00 - AT91_BASE_SYS)	/* Memory Controllers */
+
+#define AT91_MATRIX	0	/* not supported */
+
+/*
+ * Internal Memory.
+ */
+#define AT91RM9200_ROM_BASE	0x00100000	/* Internal ROM base address */
+#define AT91RM9200_ROM_SIZE	SZ_128K		/* Internal ROM size (128Kb) */
+
+#define AT91RM9200_SRAM_BASE	0x00200000	/* Internal SRAM base address */
+#define AT91RM9200_SRAM_SIZE	SZ_16K		/* Internal SRAM size (16Kb) */
+
+#define AT91RM9200_UHP_BASE	0x00300000	/* USB Host controller */
+
+
+#if 0
+/*
+ * PIO pin definitions (peripheral A/B multiplexing).
+ */
+#define AT91_PA0_MISO		(1 <<  0)	/* A: SPI Master-In Slave-Out */
+#define AT91_PA0_PCK3		(1 <<  0)	/* B: PMC Programmable Clock Output 3 */
+#define AT91_PA1_MOSI		(1 <<  1)	/* A: SPI Master-Out Slave-In */
+#define AT91_PA1_PCK0		(1 <<  1)	/* B: PMC Programmable Clock Output 0 */
+#define AT91_PA2_SPCK		(1 <<  2)	/* A: SPI Serial Clock */
+#define AT91_PA2_IRQ4		(1 <<  2)	/* B: External Interrupt 4 */
+#define AT91_PA3_NPCS0		(1 <<  3)	/* A: SPI Peripheral Chip Select 0 */
+#define AT91_PA3_IRQ5		(1 <<  3)	/* B: External Interrupt 5 */
+#define AT91_PA4_NPCS1		(1 <<  4)	/* A: SPI Peripheral Chip Select 1 */
+#define AT91_PA4_PCK1		(1 <<  4)	/* B: PMC Programmable Clock Output 1 */
+#define AT91_PA5_NPCS2		(1 <<  5)	/* A: SPI Peripheral Chip Select 2 */
+#define AT91_PA5_TXD3		(1 <<  5)	/* B: USART Transmit Data 3 */
+#define AT91_PA6_NPCS3		(1 <<  6)	/* A: SPI Peripheral Chip Select 3 */
+#define AT91_PA6_RXD3		(1 <<  6)	/* B: USART Receive Data 3 */
+#define AT91_PA7_ETXCK_EREFCK	(1 <<  7)	/* A: Ethernet Reference Clock / Transmit Clock */
+#define AT91_PA7_PCK2		(1 <<  7)	/* B: PMC Programmable Clock Output 2 */
+#define AT91_PA8_ETXEN		(1 <<  8)	/* A: Ethernet Transmit Enable */
+#define AT91_PA8_MCCDB		(1 <<  8)	/* B: MMC Multimedia Card B Command */
+#define AT91_PA9_ETX0		(1 <<  9)	/* A: Ethernet Transmit Data 0 */
+#define AT91_PA9_MCDB0		(1 <<  9)	/* B: MMC Multimedia Card B Data 0 */
+#define AT91_PA10_ETX1		(1 << 10)	/* A: Ethernet Transmit Data 1 */
+#define AT91_PA10_MCDB1		(1 << 10)	/* B: MMC Multimedia Card B Data 1 */
+#define AT91_PA11_ECRS_ECRSDV	(1 << 11)	/* A: Ethernet Carrier Sense / Data Valid */
+#define AT91_PA11_MCDB2		(1 << 11)	/* B: MMC Multimedia Card B Data 2 */
+#define AT91_PA12_ERX0		(1 << 12)	/* A: Ethernet Receive Data 0 */
+#define AT91_PA12_MCDB3		(1 << 12)	/* B: MMC Multimedia Card B Data 3 */
+#define AT91_PA13_ERX1		(1 << 13)	/* A: Ethernet Receive Data 1 */
+#define AT91_PA13_TCLK0		(1 << 13)	/* B: TC External Clock Input 0 */
+#define AT91_PA14_ERXER		(1 << 14)	/* A: Ethernet Receive Error */
+#define AT91_PA14_TCLK1		(1 << 14)	/* B: TC External Clock Input 1 */
+#define AT91_PA15_EMDC		(1 << 15)	/* A: Ethernet Management Data Clock */
+#define AT91_PA15_TCLK2		(1 << 15)	/* B: TC External Clock Input 2 */
+#define AT91_PA16_EMDIO		(1 << 16)	/* A: Ethernet Management Data I/O */
+#define AT91_PA16_IRQ6		(1 << 16)	/* B: External Interrupt 6 */
+#define AT91_PA17_TXD0		(1 << 17)	/* A: USART Transmit Data 0 */
+#define AT91_PA17_TIOA0		(1 << 17)	/* B: TC I/O Line A 0 */
+#define AT91_PA18_RXD0		(1 << 18)	/* A: USART Receive Data 0 */
+#define AT91_PA18_TIOB0		(1 << 18)	/* B: TC I/O Line B 0 */
+#define AT91_PA19_SCK0		(1 << 19)	/* A: USART Serial Clock 0 */
+#define AT91_PA19_TIOA1		(1 << 19)	/* B: TC I/O Line A 1 */
+#define AT91_PA20_CTS0		(1 << 20)	/* A: USART Clear To Send 0 */
+#define AT91_PA20_TIOB1		(1 << 20)	/* B: TC I/O Line B 1 */
+#define AT91_PA21_RTS0		(1 << 21)	/* A: USART Ready To Send 0 */
+#define AT91_PA21_TIOA2		(1 << 21)	/* B: TC I/O Line A 2 */
+#define AT91_PA22_RXD2		(1 << 22)	/* A: USART Receive Data 2 */
+#define AT91_PA22_TIOB2		(1 << 22)	/* B: TC I/O Line B 2 */
+#define AT91_PA23_TXD2		(1 << 23)	/* A: USART Transmit Data 2 */
+#define AT91_PA23_IRQ3		(1 << 23)	/* B: External Interrupt 3 */
+#define AT91_PA24_SCK2		(1 << 24)	/* A: USART Serial Clock 2 */
+#define AT91_PA24_PCK1		(1 << 24)	/* B: PMC Programmable Clock Output 1 */
+#define AT91_PA25_TWD		(1 << 25)	/* A: TWI Two-wire Serial Data */
+#define AT91_PA25_IRQ2		(1 << 25)	/* B: External Interrupt 2 */
+#define AT91_PA26_TWCK		(1 << 26)	/* A: TWI Two-wire Serial Clock */
+#define AT91_PA26_IRQ1		(1 << 26)	/* B: External Interrupt 1 */
+#define AT91_PA27_MCCK		(1 << 27)	/* A: MMC Multimedia Card Clock */
+#define AT91_PA27_TCLK3		(1 << 27)	/* B: TC External Clock Input 3 */
+#define AT91_PA28_MCCDA		(1 << 28)	/* A: MMC Multimedia Card A Command */
+#define AT91_PA28_TCLK4		(1 << 28)	/* B: TC External Clock Input 4 */
+#define AT91_PA29_MCDA0		(1 << 29)	/* A: MMC Multimedia Card A Data 0 */
+#define AT91_PA29_TCLK5		(1 << 29)	/* B: TC External Clock Input 5 */
+#define AT91_PA30_DRXD		(1 << 30)	/* A: DBGU Receive Data */
+#define AT91_PA30_CTS2		(1 << 30)	/* B: USART Clear To Send 2 */
+#define AT91_PA31_DTXD		(1 << 31)	/* A: DBGU Transmit Data */
+#define AT91_PA31_RTS2		(1 << 31)	/* B: USART Ready To Send 2 */
+
+#define AT91_PB0_TF0		(1 <<  0)	/* A: SSC Transmit Frame Sync 0 */
+#define AT91_PB0_RTS3		(1 <<  0)	/* B: USART Ready To Send 3 */
+#define AT91_PB1_TK0		(1 <<  1)	/* A: SSC Transmit Clock 0 */
+#define AT91_PB1_CTS3		(1 <<  1)	/* B: USART Clear To Send 3 */
+#define AT91_PB2_TD0		(1 <<  2)	/* A: SSC Transmit Data 0 */
+#define AT91_PB2_SCK3		(1 <<  2)	/* B: USART Serial Clock 3 */
+#define AT91_PB3_RD0		(1 <<  3)	/* A: SSC Receive Data 0 */
+#define AT91_PB3_MCDA1		(1 <<  3)	/* B: MMC Multimedia Card A Data 1 */
+#define AT91_PB4_RK0		(1 <<  4)	/* A: SSC Receive Clock 0 */
+#define AT91_PB4_MCDA2		(1 <<  4)	/* B: MMC Multimedia Card A Data 2 */
+#define AT91_PB5_RF0		(1 <<  5)	/* A: SSC Receive Frame Sync 0 */
+#define AT91_PB5_MCDA3		(1 <<  5)	/* B: MMC Multimedia Card A Data 3 */
+#define AT91_PB6_TF1		(1 <<  6)	/* A: SSC Transmit Frame Sync 1 */
+#define AT91_PB6_TIOA3		(1 <<  6)	/* B: TC I/O Line A 3 */
+#define AT91_PB7_TK1		(1 <<  7)	/* A: SSC Transmit Clock 1 */
+#define AT91_PB7_TIOB3		(1 <<  7)	/* B: TC I/O Line B 3 */
+#define AT91_PB8_TD1		(1 <<  8)	/* A: SSC Transmit Data 1 */
+#define AT91_PB8_TIOA4		(1 <<  8)	/* B: TC I/O Line A 4 */
+#define AT91_PB9_RD1		(1 <<  9)	/* A: SSC Receive Data 1 */
+#define AT91_PB9_TIOB4		(1 <<  9)	/* B: TC I/O Line B 4 */
+#define AT91_PB10_RK1		(1 << 10)	/* A: SSC Receive Clock 1 */
+#define AT91_PB10_TIOA5		(1 << 10)	/* B: TC I/O Line A 5 */
+#define AT91_PB11_RF1		(1 << 11)	/* A: SSC Receive Frame Sync 1 */
+#define AT91_PB11_TIOB5		(1 << 11)	/* B: TC I/O Line B 5 */
+#define AT91_PB12_TF2		(1 << 12)	/* A: SSC Transmit Frame Sync 2 */
+#define AT91_PB12_ETX2		(1 << 12)	/* B: Ethernet Transmit Data 2 */
+#define AT91_PB13_TK2		(1 << 13)	/* A: SSC Transmit Clock 3 */
+#define AT91_PB13_ETX3		(1 << 13)	/* B: Ethernet Transmit Data 3 */
+#define AT91_PB14_TD2		(1 << 14)	/* A: SSC Transmit Data 2 */
+#define AT91_PB14_ETXER		(1 << 14)	/* B: Ethernet Transmit Coding Error */
+#define AT91_PB15_RD2		(1 << 15)	/* A: SSC Receive Data 2 */
+#define AT91_PB15_ERX2		(1 << 15)	/* B: Ethernet Receive Data 2 */
+#define AT91_PB16_RK2		(1 << 16)	/* A: SSC Receive Clock 2 */
+#define AT91_PB16_ERX3		(1 << 16)	/* B: Ethernet Receive Data 3 */
+#define AT91_PB17_RF2		(1 << 17)	/* A: SSC Receive Frame Sync 2 */
+#define AT91_PB17_ERXDV		(1 << 17)	/* B: Ethernet Receive Data Valid */
+#define AT91_PB18_RI1		(1 << 18)	/* A: USART Ring Indicator 1 */
+#define AT91_PB18_ECOL		(1 << 18)	/* B: Ethernet Collision Detected */
+#define AT91_PB19_DTR1		(1 << 19)	/* A: USART Data Terminal Ready 1 */
+#define AT91_PB19_ERXCK		(1 << 19)	/* B: Ethernet Receive Clock */
+#define AT91_PB20_TXD1		(1 << 20)	/* A: USART Transmit Data 1 */
+#define AT91_PB21_RXD1		(1 << 21)	/* A: USART Receive Data 1 */
+#define AT91_PB22_SCK1		(1 << 22)	/* A: USART Serial Clock 1 */
+#define AT91_PB23_DCD1		(1 << 23)	/* A: USART Data Carrier Detect 1 */
+#define AT91_PB24_CTS1		(1 << 24)	/* A: USART Clear To Send 1 */
+#define AT91_PB25_DSR1		(1 << 25)	/* A: USART Data Set Ready 1 */
+#define AT91_PB25_EF100		(1 << 25)	/* B: Ethernet Force 100 Mbit */
+#define AT91_PB26_RTS1		(1 << 26)	/* A: USART Ready To Send 1 */
+#define AT91_PB27_PCK0		(1 << 27)	/* B: PMC Programmable Clock Output 0 */
+#define AT91_PB28_FIQ		(1 << 28)	/* A: Fast Interrupt */
+#define AT91_PB29_IRQ0		(1 << 29)	/* A: External Interrupt 0 */
+
+#define AT91_PC0_BFCK		(1 <<  0)	/* A: Burst Flash Clock */
+#define AT91_PC1_BFRDY_SMOE	(1 <<  1)	/* A: Burst Flash Ready / SmartMedia Output Enable */
+#define AT91_PC2_BFAVD		(1 <<  2)	/* A: Burst Flash Address Valid */
+#define AT91_PC3_BFBAA_SMWE	(1 <<  3)	/* A: Burst Flash Address Advance / SmartMedia Write Enable */
+#define AT91_PC4_BFOE		(1 <<  4)	/* A: Burst Flash Output Enable */
+#define AT91_PC5_BFWE		(1 <<  5)	/* A: Burst Flash Write Enable */
+#define AT91_PC6_NWAIT		(1 <<  6)	/* A: SMC Wait Signal */
+#define AT91_PC7_A23		(1 <<  7)	/* A: Address Bus 23 */
+#define AT91_PC8_A24		(1 <<  8)	/* A: Address Bus 24 */
+#define AT91_PC9_A25_CFRNW	(1 <<  9)	/* A: Address Bus 25 / Compact Flash Read Not Write */
+#define AT91_PC10_NCS4_CFCS	(1 << 10)	/* A: SMC Chip Select 4 / Compact Flash Chip Select */
+#define AT91_PC11_NCS5_CFCE1	(1 << 11)	/* A: SMC Chip Select 5 / Compact Flash Chip Enable 1 */
+#define AT91_PC12_NCS6_CFCE2	(1 << 12)	/* A: SMC Chip Select 6 / Compact Flash Chip Enable 2 */
+#define AT91_PC13_NCS7		(1 << 13)	/* A: Chip Select 7 */
+
+#define AT91_PD0_ETX0		(1 <<  0)	/* A: Ethernet Transmit Data 0 */
+#define AT91_PD1_ETX1		(1 <<  1)	/* A: Ethernet Transmit Data 1 */
+#define AT91_PD2_ETX2		(1 <<  2)	/* A: Ethernet Transmit Data 2 */
+#define AT91_PD3_ETX3		(1 <<  3)	/* A: Ethernet Transmit Data 3 */
+#define AT91_PD4_ETXEN		(1 <<  4)	/* A: Ethernet Transmit Enable */
+#define AT91_PD5_ETXER		(1 <<  5)	/* A: Ethernet Transmit Coding Error */
+#define AT91_PD6_DTXD		(1 <<  6)	/* A: DBGU Transmit Data */
+#define AT91_PD7_PCK0		(1 <<  7)	/* A: PMC Programmable Clock Output 0 */
+#define AT91_PD7_TSYNC		(1 <<  7)	/* B: ETM Trace Synchronization Signal */
+#define AT91_PD8_PCK1		(1 <<  8)	/* A: PMC Programmable Clock Output 1 */
+#define AT91_PD8_TCLK		(1 <<  8)	/* B: ETM Trace Clock */
+#define AT91_PD9_PCK2		(1 <<  9)	/* A: PMC Programmable Clock Output 2 */
+#define AT91_PD9_TPS0		(1 <<  9)	/* B: ETM Trace ARM Pipeline Status 0 */
+#define AT91_PD10_PCK3		(1 << 10)	/* A: PMC Programmable Clock Output 3 */
+#define AT91_PD10_TPS1		(1 << 10)	/* B: ETM Trace ARM Pipeline Status 1 */
+#define AT91_PD11_TPS2		(1 << 11)	/* B: ETM Trace ARM Pipeline Status 2 */
+#define AT91_PD12_TPK0		(1 << 12)	/* B: ETM Trace Packet Port 0 */
+#define AT91_PD13_TPK1		(1 << 13)	/* B: ETM Trace Packet Port 1 */
+#define AT91_PD14_TPK2		(1 << 14)	/* B: ETM Trace Packet Port 2 */
+#define AT91_PD15_TD0		(1 << 15)	/* A: SSC Transmit Data 0 */
+#define AT91_PD15_TPK3		(1 << 15)	/* B: ETM Trace Packet Port 3 */
+#define AT91_PD16_TD1		(1 << 16)	/* A: SSC Transmit Data 1 */
+#define AT91_PD16_TPK4		(1 << 16)	/* B: ETM Trace Packet Port 4 */
+#define AT91_PD17_TD2		(1 << 17)	/* A: SSC Transmit Data 2 */
+#define AT91_PD17_TPK5		(1 << 17)	/* B: ETM Trace Packet Port 5 */
+#define AT91_PD18_NPCS1		(1 << 18)	/* A: SPI Peripheral Chip Select 1 */
+#define AT91_PD18_TPK6		(1 << 18)	/* B: ETM Trace Packet Port 6 */
+#define AT91_PD19_NPCS2		(1 << 19)	/* A: SPI Peripheral Chip Select 2 */
+#define AT91_PD19_TPK7		(1 << 19)	/* B: ETM Trace Packet Port 7 */
+#define AT91_PD20_NPCS3		(1 << 20)	/* A: SPI Peripheral Chip Select 3 */
+#define AT91_PD20_TPK8		(1 << 20)	/* B: ETM Trace Packet Port 8 */
+#define AT91_PD21_RTS0		(1 << 21)	/* A: USART Ready To Send 0 */
+#define AT91_PD21_TPK9		(1 << 21)	/* B: ETM Trace Packet Port 9 */
+#define AT91_PD22_RTS1		(1 << 22)	/* A: USART Ready To Send 1 */
+#define AT91_PD22_TPK10		(1 << 22)	/* B: ETM Trace Packet Port 10 */
+#define AT91_PD23_RTS2		(1 << 23)	/* A: USART Ready To Send 2 */
+#define AT91_PD23_TPK11		(1 << 23)	/* B: ETM Trace Packet Port 11 */
+#define AT91_PD24_RTS3		(1 << 24)	/* A: USART Ready To Send 3 */
+#define AT91_PD24_TPK12		(1 << 24)	/* B: ETM Trace Packet Port 12 */
+#define AT91_PD25_DTR1		(1 << 25)	/* A: USART Data Terminal Ready 1 */
+#define AT91_PD25_TPK13		(1 << 25)	/* B: ETM Trace Packet Port 13 */
+#define AT91_PD26_TPK14		(1 << 26)	/* B: ETM Trace Packet Port 14 */
+#define AT91_PD27_TPK15		(1 << 27)	/* B: ETM Trace Packet Port 15 */
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91rm9200_emac.h b/include/asm-arm/arch-at91/at91rm9200_emac.h
new file mode 100644
index 0000000..0c417af
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91rm9200_emac.h
@@ -0,0 +1,138 @@
+/*
+ * include/asm-arm/arch-at91/at91rm9200_emac.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Ethernet MAC 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_EMAC_H
+#define AT91RM9200_EMAC_H
+
+#define	AT91_EMAC_CTL		0x00	/* Control Register */
+#define		AT91_EMAC_LB		(1 <<  0)	/* Loopback */
+#define		AT91_EMAC_LBL		(1 <<  1)	/* Loopback Local */
+#define		AT91_EMAC_RE		(1 <<  2)	/* Receive Enable */
+#define		AT91_EMAC_TE		(1 <<  3)	/* Transmit Enable */
+#define		AT91_EMAC_MPE		(1 <<  4)	/* Management Port Enable */
+#define		AT91_EMAC_CSR		(1 <<  5)	/* Clear Statistics Registers */
+#define		AT91_EMAC_INCSTAT	(1 <<  6)	/* Increment Statistics Registers */
+#define		AT91_EMAC_WES		(1 <<  7)	/* Write Enable for Statistics Registers */
+#define		AT91_EMAC_BP		(1 <<  8)	/* Back Pressure */
+
+#define	AT91_EMAC_CFG		0x04	/* Configuration Register */
+#define		AT91_EMAC_SPD		(1 <<  0)	/* Speed */
+#define		AT91_EMAC_FD		(1 <<  1)	/* Full Duplex */
+#define		AT91_EMAC_BR		(1 <<  2)	/* Bit Rate */
+#define		AT91_EMAC_CAF		(1 <<  4)	/* Copy All Frames */
+#define		AT91_EMAC_NBC		(1 <<  5)	/* No Broadcast */
+#define		AT91_EMAC_MTI		(1 <<  6)	/* Multicast Hash Enable */
+#define		AT91_EMAC_UNI		(1 <<  7)	/* Unicast Hash Enable */
+#define		AT91_EMAC_BIG		(1 <<  8)	/* Receive 1522 Bytes */
+#define		AT91_EMAC_EAE		(1 <<  9)	/* External Address Match Enable */
+#define		AT91_EMAC_CLK		(3 << 10)	/* MDC Clock Divisor */
+#define		AT91_EMAC_CLK_DIV8		(0 << 10)
+#define		AT91_EMAC_CLK_DIV16		(1 << 10)
+#define		AT91_EMAC_CLK_DIV32		(2 << 10)
+#define		AT91_EMAC_CLK_DIV64		(3 << 10)
+#define		AT91_EMAC_RTY		(1 << 12)	/* Retry Test */
+#define		AT91_EMAC_RMII		(1 << 13)	/* Reduce MII (RMII) */
+
+#define	AT91_EMAC_SR		0x08	/* Status Register */
+#define		AT91_EMAC_SR_LINK	(1 <<  0)	/* Link */
+#define		AT91_EMAC_SR_MDIO	(1 <<  1)	/* MDIO pin */
+#define		AT91_EMAC_SR_IDLE	(1 <<  2)	/* PHY idle */
+
+#define	AT91_EMAC_TAR		0x0c	/* Transmit Address Register */
+
+#define	AT91_EMAC_TCR		0x10	/* Transmit Control Register */
+#define		AT91_EMAC_LEN		(0x7ff << 0)	/* Transmit Frame Length */
+#define		AT91_EMAC_NCRC		(1     << 15)	/* No CRC */
+
+#define	AT91_EMAC_TSR		0x14	/* Transmit Status Register */
+#define		AT91_EMAC_TSR_OVR	(1 <<  0)	/* Transmit Buffer Overrun */
+#define		AT91_EMAC_TSR_COL	(1 <<  1)	/* Collision Occurred */
+#define		AT91_EMAC_TSR_RLE	(1 <<  2)	/* Retry Limit Exceeded */
+#define		AT91_EMAC_TSR_IDLE	(1 <<  3)	/* Transmitter Idle */
+#define		AT91_EMAC_TSR_BNQ	(1 <<  4)	/* Transmit Buffer not Queued */
+#define		AT91_EMAC_TSR_COMP	(1 <<  5)	/* Transmit Complete */
+#define		AT91_EMAC_TSR_UND	(1 <<  6)	/* Transmit Underrun */
+
+#define	AT91_EMAC_RBQP		0x18	/* Receive Buffer Queue Pointer */
+
+#define	AT91_EMAC_RSR		0x20	/* Receive Status Register */
+#define		AT91_EMAC_RSR_BNA	(1 <<  0)	/* Buffer Not Available */
+#define		AT91_EMAC_RSR_REC	(1 <<  1)	/* Frame Received */
+#define		AT91_EMAC_RSR_OVR	(1 <<  2)	/* RX Overrun */
+
+#define	AT91_EMAC_ISR		0x24	/* Interrupt Status Register */
+#define		AT91_EMAC_DONE		(1 <<  0)	/* Management Done */
+#define		AT91_EMAC_RCOM		(1 <<  1)	/* Receive Complete */
+#define		AT91_EMAC_RBNA		(1 <<  2)	/* Receive Buffer Not Available */
+#define		AT91_EMAC_TOVR		(1 <<  3)	/* Transmit Buffer Overrun */
+#define		AT91_EMAC_TUND		(1 <<  4)	/* Transmit Buffer Underrun */
+#define		AT91_EMAC_RTRY		(1 <<  5)	/* Retry Limit */
+#define		AT91_EMAC_TBRE		(1 <<  6)	/* Transmit Buffer Register Empty */
+#define		AT91_EMAC_TCOM		(1 <<  7)	/* Transmit Complete */
+#define		AT91_EMAC_TIDLE		(1 <<  8)	/* Transmit Idle */
+#define		AT91_EMAC_LINK		(1 <<  9)	/* Link */
+#define		AT91_EMAC_ROVR		(1 << 10)	/* RX Overrun */
+#define		AT91_EMAC_ABT		(1 << 11)	/* Abort */
+
+#define	AT91_EMAC_IER		0x28	/* Interrupt Enable Register */
+#define	AT91_EMAC_IDR		0x2c	/* Interrupt Disable Register */
+#define	AT91_EMAC_IMR		0x30	/* Interrupt Mask Register */
+
+#define	AT91_EMAC_MAN		0x34	/* PHY Maintenance Register */
+#define		AT91_EMAC_DATA		(0xffff << 0)	/* MDIO Data */
+#define		AT91_EMAC_REGA		(0x1f	<< 18)	/* MDIO Register */
+#define		AT91_EMAC_PHYA		(0x1f	<< 23)	/* MDIO PHY Address */
+#define		AT91_EMAC_RW		(3	<< 28)	/* Read/Write operation */
+#define			AT91_EMAC_RW_W		(1 << 28)
+#define			AT91_EMAC_RW_R		(2 << 28)
+#define		AT91_EMAC_MAN_802_3	0x40020000	/* IEEE 802.3 value */
+
+/*
+ * Statistics Registers.
+ */
+#define AT91_EMAC_FRA		0x40	/* Frames Transmitted OK */
+#define AT91_EMAC_SCOL		0x44	/* Single Collision Frame */
+#define AT91_EMAC_MCOL		0x48	/* Multiple Collision Frame */
+#define AT91_EMAC_OK		0x4c	/* Frames Received OK */
+#define AT91_EMAC_SEQE		0x50	/* Frame Check Sequence Error */
+#define AT91_EMAC_ALE		0x54	/* Alignmemt Error */
+#define AT91_EMAC_DTE		0x58	/* Deffered Transmission Frame */
+#define AT91_EMAC_LCOL		0x5c	/* Late Collision */
+#define AT91_EMAC_ECOL		0x60	/* Excessive Collision */
+#define AT91_EMAC_TUE		0x64	/* Transmit Underrun Error */
+#define AT91_EMAC_CSE		0x68	/* Carrier Sense Error */
+#define AT91_EMAC_DRFC		0x6c	/* Discard RX Frame */
+#define AT91_EMAC_ROV		0x70	/* Receive Overrun */
+#define AT91_EMAC_CDE		0x74	/* Code Error */
+#define AT91_EMAC_ELR		0x78	/* Excessive Length Error */
+#define AT91_EMAC_RJB		0x7c	/* Receive Jabber */
+#define AT91_EMAC_USF		0x80	/* Undersize Frame */
+#define AT91_EMAC_SQEE		0x84	/* SQE Test Error */
+
+/*
+ * Address Registers.
+ */
+#define AT91_EMAC_HSL		0x90	/* Hash Address Low [31:0] */
+#define AT91_EMAC_HSH		0x94	/* Hash Address High [63:32] */
+#define AT91_EMAC_SA1L		0x98	/* Specific Address 1 Low, bytes 0-3 */
+#define AT91_EMAC_SA1H		0x9c	/* Specific Address 1 High, bytes 4-5 */
+#define AT91_EMAC_SA2L		0xa0	/* Specific Address 2 Low, bytes 0-3 */
+#define AT91_EMAC_SA2H		0xa4	/* Specific Address 2 High, bytes 4-5 */
+#define AT91_EMAC_SA3L		0xa8	/* Specific Address 3 Low, bytes 0-3 */
+#define AT91_EMAC_SA3H		0xac	/* Specific Address 3 High, bytes 4-5 */
+#define AT91_EMAC_SA4L		0xb0	/* Specific Address 4 Low, bytes 0-3 */
+#define AT91_EMAC_SA4H		0xb4	/* Specific Address 4 High, bytes 4-5 */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91rm9200_mc.h b/include/asm-arm/arch-at91/at91rm9200_mc.h
new file mode 100644
index 0000000..24d0129
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91rm9200_mc.h
@@ -0,0 +1,160 @@
+/*
+ * include/asm-arm/arch-at91/at91rm9200_mc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Memory Controllers (MC, EBI, SMC, SDRAMC, BFC) - System peripherals 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_MC_H
+#define AT91RM9200_MC_H
+
+/* Memory Controller */
+#define AT91_MC_RCR		(AT91_MC + 0x00)	/* MC Remap Control Register */
+#define		AT91_MC_RCB		(1 <<  0)		/* Remap Command Bit */
+
+#define AT91_MC_ASR		(AT91_MC + 0x04)	/* MC Abort Status Register */
+#define		AT91_MC_UNADD		(1 <<  0)		/* Undefined Address Abort Status */
+#define		AT91_MC_MISADD		(1 <<  1)		/* Misaligned Address Abort Status */
+#define		AT91_MC_ABTSZ		(3 <<  8)		/* Abort Size Status */
+#define			AT91_MC_ABTSZ_BYTE		(0 << 8)
+#define			AT91_MC_ABTSZ_HALFWORD		(1 << 8)
+#define			AT91_MC_ABTSZ_WORD		(2 << 8)
+#define		AT91_MC_ABTTYP		(3 << 10)		/* Abort Type Status */
+#define			AT91_MC_ABTTYP_DATAREAD		(0 << 10)
+#define			AT91_MC_ABTTYP_DATAWRITE	(1 << 10)
+#define			AT91_MC_ABTTYP_FETCH		(2 << 10)
+#define		AT91_MC_MST0		(1 << 16)		/* ARM920T Abort Source */
+#define		AT91_MC_MST1		(1 << 17)		/* PDC Abort Source */
+#define		AT91_MC_MST2		(1 << 18)		/* UHP Abort Source */
+#define		AT91_MC_MST3		(1 << 19)		/* EMAC Abort Source */
+#define		AT91_MC_SVMST0		(1 << 24)		/* Saved ARM920T Abort Source */
+#define		AT91_MC_SVMST1		(1 << 25)		/* Saved PDC Abort Source */
+#define		AT91_MC_SVMST2		(1 << 26)		/* Saved UHP Abort Source */
+#define		AT91_MC_SVMST3		(1 << 27)		/* Saved EMAC Abort Source */
+
+#define AT91_MC_AASR		(AT91_MC + 0x08)	/* MC Abort Address Status Register */
+
+#define AT91_MC_MPR		(AT91_MC + 0x0c)	/* MC Master Priority Register */
+#define		AT91_MPR_MSTP0		(7 <<  0)		/* ARM920T Priority */
+#define		AT91_MPR_MSTP1		(7 <<  4)		/* PDC Priority */
+#define		AT91_MPR_MSTP2		(7 <<  8)		/* UHP Priority */
+#define		AT91_MPR_MSTP3		(7 << 12)		/* EMAC Priority */
+
+/* External Bus Interface (EBI) registers */
+#define AT91_EBI_CSA		(AT91_MC + 0x60)	/* Chip Select Assignment Register */
+#define		AT91_EBI_CS0A		(1 << 0)		/* Chip Select 0 Assignment */
+#define			AT91_EBI_CS0A_SMC		(0 << 0)
+#define			AT91_EBI_CS0A_BFC		(1 << 0)
+#define		AT91_EBI_CS1A		(1 << 1)		/* Chip Select 1 Assignment */
+#define			AT91_EBI_CS1A_SMC		(0 << 1)
+#define			AT91_EBI_CS1A_SDRAMC		(1 << 1)
+#define		AT91_EBI_CS3A		(1 << 3)		/* Chip Select 2 Assignment */
+#define			AT91_EBI_CS3A_SMC		(0 << 3)
+#define			AT91_EBI_CS3A_SMC_SMARTMEDIA	(1 << 3)
+#define		AT91_EBI_CS4A		(1 << 4)		/* Chip Select 3 Assignment */
+#define			AT91_EBI_CS4A_SMC		(0 << 4)
+#define			AT91_EBI_CS4A_SMC_COMPACTFLASH	(1 << 4)
+#define AT91_EBI_CFGR		(AT91_MC + 0x64)	/* Configuration Register */
+#define		AT91_EBI_DBPUC		(1 << 0)		/* Data Bus Pull-Up Configuration */
+
+/* Static Memory Controller (SMC) registers */
+#define	AT91_SMC_CSR(n)		(AT91_MC + 0x70 + ((n) * 4))/* SMC Chip Select Register */
+#define		AT91_SMC_NWS		(0x7f <<  0)		/* Number of Wait States */
+#define			AT91_SMC_NWS_(x)	((x) << 0)
+#define		AT91_SMC_WSEN		(1    <<  7)		/* Wait State Enable */
+#define		AT91_SMC_TDF		(0xf  <<  8)		/* Data Float Time */
+#define			AT91_SMC_TDF_(x)	((x) << 8)
+#define		AT91_SMC_BAT		(1    << 12)		/* Byte Access Type */
+#define		AT91_SMC_DBW		(3    << 13)		/* Data Bus Width */
+#define			AT91_SMC_DBW_16		(1 << 13)
+#define			AT91_SMC_DBW_8		(2 << 13)
+#define		AT91_SMC_DPR		(1 << 15)		/* Data Read Protocol */
+#define		AT91_SMC_ACSS		(3 << 16)		/* Address to Chip Select Setup */
+#define			AT91_SMC_ACSS_STD	(0 << 16)
+#define			AT91_SMC_ACSS_1		(1 << 16)
+#define			AT91_SMC_ACSS_2		(2 << 16)
+#define			AT91_SMC_ACSS_3		(3 << 16)
+#define		AT91_SMC_RWSETUP	(7 << 24)		/* Read & Write Signal Time Setup */
+#define			AT91_SMC_RWSETUP_(x)	((x) << 24)
+#define		AT91_SMC_RWHOLD		(7 << 28)		/* Read & Write Signal Hold Time */
+#define			AT91_SMC_RWHOLD_(x)	((x) << 28)
+
+/* SDRAM Controller registers */
+#define AT91_SDRAMC_MR		(AT91_MC + 0x90)	/* Mode Register */
+#define		AT91_SDRAMC_MODE	(0xf << 0)		/* Command Mode */
+#define			AT91_SDRAMC_MODE_NORMAL		(0 << 0)
+#define			AT91_SDRAMC_MODE_NOP		(1 << 0)
+#define			AT91_SDRAMC_MODE_PRECHARGE	(2 << 0)
+#define			AT91_SDRAMC_MODE_LMR		(3 << 0)
+#define			AT91_SDRAMC_MODE_REFRESH	(4 << 0)
+#define		AT91_SDRAMC_DBW		(1   << 4)		/* Data Bus Width */
+#define			AT91_SDRAMC_DBW_32	(0 << 4)
+#define			AT91_SDRAMC_DBW_16	(1 << 4)
+
+#define AT91_SDRAMC_TR		(AT91_MC + 0x94)	/* Refresh Timer Register */
+#define		AT91_SDRAMC_COUNT	(0xfff << 0)		/* Refresh Timer Count */
+
+#define AT91_SDRAMC_CR		(AT91_MC + 0x98)	/* Configuration Register */
+#define		AT91_SDRAMC_NC		(3   <<  0)		/* Number of Column Bits */
+#define			AT91_SDRAMC_NC_8	(0 << 0)
+#define			AT91_SDRAMC_NC_9	(1 << 0)
+#define			AT91_SDRAMC_NC_10	(2 << 0)
+#define			AT91_SDRAMC_NC_11	(3 << 0)
+#define		AT91_SDRAMC_NR		(3   <<  2)		/* Number of Row Bits */
+#define			AT91_SDRAMC_NR_11	(0 << 2)
+#define			AT91_SDRAMC_NR_12	(1 << 2)
+#define			AT91_SDRAMC_NR_13	(2 << 2)
+#define		AT91_SDRAMC_NB		(1   <<  4)		/* Number of Banks */
+#define			AT91_SDRAMC_NB_2	(0 << 4)
+#define			AT91_SDRAMC_NB_4	(1 << 4)
+#define		AT91_SDRAMC_CAS		(3   <<  5)		/* CAS Latency */
+#define			AT91_SDRAMC_CAS_2	(2 << 5)
+#define		AT91_SDRAMC_TWR		(0xf <<  7)		/* Write Recovery Delay */
+#define		AT91_SDRAMC_TRC		(0xf << 11)		/* Row Cycle Delay */
+#define		AT91_SDRAMC_TRP		(0xf << 15)		/* Row Precharge Delay */
+#define		AT91_SDRAMC_TRCD	(0xf << 19)		/* Row to Column Delay */
+#define		AT91_SDRAMC_TRAS	(0xf << 23)		/* Active to Precharge Delay */
+#define		AT91_SDRAMC_TXSR	(0xf << 27)		/* Exit Self Refresh to Active Delay */
+
+#define AT91_SDRAMC_SRR		(AT91_MC + 0x9c)	/* Self Refresh Register */
+#define AT91_SDRAMC_LPR		(AT91_MC + 0xa0)	/* Low Power Register */
+#define AT91_SDRAMC_IER		(AT91_MC + 0xa4)	/* Interrupt Enable Register */
+#define AT91_SDRAMC_IDR		(AT91_MC + 0xa8)	/* Interrupt Disable Register */
+#define AT91_SDRAMC_IMR		(AT91_MC + 0xac)	/* Interrupt Mask Register */
+#define AT91_SDRAMC_ISR		(AT91_MC + 0xb0)	/* Interrupt Status Register */
+
+/* Burst Flash Controller register */
+#define AT91_BFC_MR		(AT91_MC + 0xc0)	/* Mode Register */
+#define		AT91_BFC_BFCOM		(3   <<  0)		/* Burst Flash Controller Operating Mode */
+#define			AT91_BFC_BFCOM_DISABLED	(0 << 0)
+#define			AT91_BFC_BFCOM_ASYNC	(1 << 0)
+#define			AT91_BFC_BFCOM_BURST	(2 << 0)
+#define		AT91_BFC_BFCC		(3   <<  2)		/* Burst Flash Controller Clock */
+#define			AT91_BFC_BFCC_MCK	(1 << 2)
+#define			AT91_BFC_BFCC_DIV2	(2 << 2)
+#define			AT91_BFC_BFCC_DIV4	(3 << 2)
+#define		AT91_BFC_AVL		(0xf <<  4)		/* Address Valid Latency */
+#define		AT91_BFC_PAGES		(7   <<  8)		/* Page Size */
+#define			AT91_BFC_PAGES_NO_PAGE	(0 << 8)
+#define			AT91_BFC_PAGES_16	(1 << 8)
+#define			AT91_BFC_PAGES_32	(2 << 8)
+#define			AT91_BFC_PAGES_64	(3 << 8)
+#define			AT91_BFC_PAGES_128	(4 << 8)
+#define			AT91_BFC_PAGES_256	(5 << 8)
+#define			AT91_BFC_PAGES_512	(6 << 8)
+#define			AT91_BFC_PAGES_1024	(7 << 8)
+#define		AT91_BFC_OEL		(3   << 12)		/* Output Enable Latency */
+#define		AT91_BFC_BAAEN		(1   << 16)		/* Burst Address Advance Enable */
+#define		AT91_BFC_BFOEH		(1   << 17)		/* Burst Flash Output Enable Handling */
+#define		AT91_BFC_MUXEN		(1   << 18)		/* Multiplexed Bus Enable */
+#define		AT91_BFC_RDYEN		(1   << 19)		/* Ready Enable Mode */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91sam9260.h b/include/asm-arm/arch-at91/at91sam9260.h
new file mode 100644
index 0000000..2cadebc
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91sam9260.h
@@ -0,0 +1,129 @@
+/*
+ * include/asm-arm/arch-at91/at91sam9260.h
+ *
+ * (C) 2006 Andrew Victor
+ *
+ * Common definitions.
+ * Based on AT91SAM9260 datasheet revision A (Preliminary).
+ *
+ * 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 AT91SAM9260_H
+#define AT91SAM9260_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91_ID_FIQ		0	/* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS		1	/* System Peripherals */
+#define AT91SAM9260_ID_PIOA	2	/* Parallel IO Controller A */
+#define AT91SAM9260_ID_PIOB	3	/* Parallel IO Controller B */
+#define AT91SAM9260_ID_PIOC	4	/* Parallel IO Controller C */
+#define AT91SAM9260_ID_ADC	5	/* Analog-to-Digital Converter */
+#define AT91SAM9260_ID_US0	6	/* USART 0 */
+#define AT91SAM9260_ID_US1	7	/* USART 1 */
+#define AT91SAM9260_ID_US2	8	/* USART 2 */
+#define AT91SAM9260_ID_MCI	9	/* Multimedia Card Interface */
+#define AT91SAM9260_ID_UDP	10	/* USB Device Port */
+#define AT91SAM9260_ID_TWI	11	/* Two-Wire Interface */
+#define AT91SAM9260_ID_SPI0	12	/* Serial Peripheral Interface 0 */
+#define AT91SAM9260_ID_SPI1	13	/* Serial Peripheral Interface 1 */
+#define AT91SAM9260_ID_SSC	14	/* Serial Synchronous Controller */
+#define AT91SAM9260_ID_TC0	17	/* Timer Counter 0 */
+#define AT91SAM9260_ID_TC1	18	/* Timer Counter 1 */
+#define AT91SAM9260_ID_TC2	19	/* Timer Counter 2 */
+#define AT91SAM9260_ID_UHP	20	/* USB Host port */
+#define AT91SAM9260_ID_EMAC	21	/* Ethernet */
+#define AT91SAM9260_ID_ISI	22	/* Image Sensor Interface */
+#define AT91SAM9260_ID_US3	23	/* USART 3 */
+#define AT91SAM9260_ID_US4	24	/* USART 4 */
+#define AT91SAM9260_ID_US5	25	/* USART 5 */
+#define AT91SAM9260_ID_TC3	26	/* Timer Counter 3 */
+#define AT91SAM9260_ID_TC4	27	/* Timer Counter 4 */
+#define AT91SAM9260_ID_TC5	28	/* Timer Counter 5 */
+#define AT91SAM9260_ID_IRQ0	29	/* Advanced Interrupt Controller (IRQ0) */
+#define AT91SAM9260_ID_IRQ1	30	/* Advanced Interrupt Controller (IRQ1) */
+#define AT91SAM9260_ID_IRQ2	31	/* Advanced Interrupt Controller (IRQ2) */
+
+
+/*
+ * User Peripheral physical base addresses.
+ */
+#define AT91SAM9260_BASE_TCB0		0xfffa0000
+#define AT91SAM9260_BASE_TC0		0xfffa0000
+#define AT91SAM9260_BASE_TC1		0xfffa0040
+#define AT91SAM9260_BASE_TC2		0xfffa0080
+#define AT91SAM9260_BASE_UDP		0xfffa4000
+#define AT91SAM9260_BASE_MCI		0xfffa8000
+#define AT91SAM9260_BASE_TWI		0xfffac000
+#define AT91SAM9260_BASE_US0		0xfffb0000
+#define AT91SAM9260_BASE_US1		0xfffb4000
+#define AT91SAM9260_BASE_US2		0xfffb8000
+#define AT91SAM9260_BASE_SSC		0xfffbc000
+#define AT91SAM9260_BASE_ISI		0xfffc0000
+#define AT91SAM9260_BASE_EMAC		0xfffc4000
+#define AT91SAM9260_BASE_SPI0		0xfffc8000
+#define AT91SAM9260_BASE_SPI1		0xfffcc000
+#define AT91SAM9260_BASE_US3		0xfffd0000
+#define AT91SAM9260_BASE_US4		0xfffd4000
+#define AT91SAM9260_BASE_US5		0xfffd8000
+#define AT91SAM9260_BASE_TCB1		0xfffdc000
+#define AT91SAM9260_BASE_TC3		0xfffdc000
+#define AT91SAM9260_BASE_TC4		0xfffdc040
+#define AT91SAM9260_BASE_TC5		0xfffdc080
+#define AT91SAM9260_BASE_ADC		0xfffe0000
+#define AT91_BASE_SYS			0xffffe800
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_ECC	(0xffffe800 - AT91_BASE_SYS)
+#define AT91_SDRAMC	(0xffffea00 - AT91_BASE_SYS)
+#define AT91_SMC	(0xffffec00 - AT91_BASE_SYS)
+#define AT91_MATRIX	(0xffffee00 - AT91_BASE_SYS)
+#define AT91_CCFG	(0xffffef10 - AT91_BASE_SYS)
+#define AT91_AIC	(0xfffff000 - AT91_BASE_SYS)
+#define AT91_DBGU	(0xfffff200 - AT91_BASE_SYS)
+#define AT91_PIOA	(0xfffff400 - AT91_BASE_SYS)
+#define AT91_PIOB	(0xfffff600 - AT91_BASE_SYS)
+#define AT91_PIOC	(0xfffff800 - AT91_BASE_SYS)
+#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
+#define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
+#define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
+#define AT91_RTT	(0xfffffd20 - AT91_BASE_SYS)
+#define AT91_PIT	(0xfffffd30 - AT91_BASE_SYS)
+#define AT91_WDT	(0xfffffd40 - AT91_BASE_SYS)
+#define AT91_GPBR	(0xfffffd50 - AT91_BASE_SYS)
+
+
+/*
+ * Internal Memory.
+ */
+#define AT91SAM9260_ROM_BASE	0x00100000	/* Internal ROM base address */
+#define AT91SAM9260_ROM_SIZE	SZ_32K		/* Internal ROM size (32Kb) */
+
+#define AT91SAM9260_SRAM0_BASE	0x00200000	/* Internal SRAM 0 base address */
+#define AT91SAM9260_SRAM0_SIZE	SZ_4K		/* Internal SRAM 0 size (4Kb) */
+#define AT91SAM9260_SRAM1_BASE	0x00300000	/* Internal SRAM 1 base address */
+#define AT91SAM9260_SRAM1_SIZE	SZ_4K		/* Internal SRAM 1 size (4Kb) */
+
+#define AT91SAM9260_UHP_BASE	0x00500000	/* USB Host controller */
+
+#define AT91SAM9XE_FLASH_BASE	0x00200000	/* Internal FLASH base address */
+#define AT91SAM9XE_SRAM_BASE	0x00300000	/* Internal SRAM base address */
+
+
+#if 0
+/*
+ * PIO pin definitions (peripheral A/B multiplexing).
+ */
+
+// TODO: Add
+
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91sam9260_matrix.h b/include/asm-arm/arch-at91/at91sam9260_matrix.h
new file mode 100644
index 0000000..aacb1e9
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91sam9260_matrix.h
@@ -0,0 +1,78 @@
+/*
+ * include/asm-arm/arch-at91/at91sam9260_matrix.h
+ *
+ * Memory Controllers (MATRIX, EBI) - System peripherals registers.
+ * Based on AT91SAM9260 datasheet revision B.
+ *
+ * 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 AT91SAM9260_MATRIX_H
+#define AT91SAM9260_MATRIX_H
+
+#define AT91_MATRIX_MCFG0	(AT91_MATRIX + 0x00)	/* Master Configuration Register 0 */
+#define AT91_MATRIX_MCFG1	(AT91_MATRIX + 0x04)	/* Master Configuration Register 1 */
+#define AT91_MATRIX_MCFG2	(AT91_MATRIX + 0x08)	/* Master Configuration Register 2 */
+#define AT91_MATRIX_MCFG3	(AT91_MATRIX + 0x0C)	/* Master Configuration Register 3 */
+#define AT91_MATRIX_MCFG4	(AT91_MATRIX + 0x10)	/* Master Configuration Register 4 */
+#define AT91_MATRIX_MCFG5	(AT91_MATRIX + 0x14)	/* Master Configuration Register 5 */
+#define		AT91_MATRIX_ULBT		(7 << 0)	/* Undefined Length Burst Type */
+#define			AT91_MATRIX_ULBT_INFINITE	(0 << 0)
+#define			AT91_MATRIX_ULBT_SINGLE		(1 << 0)
+#define			AT91_MATRIX_ULBT_FOUR		(2 << 0)
+#define			AT91_MATRIX_ULBT_EIGHT		(3 << 0)
+#define			AT91_MATRIX_ULBT_SIXTEEN	(4 << 0)
+
+#define AT91_MATRIX_SCFG0	(AT91_MATRIX + 0x40)	/* Slave Configuration Register 0 */
+#define AT91_MATRIX_SCFG1	(AT91_MATRIX + 0x44)	/* Slave Configuration Register 1 */
+#define AT91_MATRIX_SCFG2	(AT91_MATRIX + 0x48)	/* Slave Configuration Register 2 */
+#define AT91_MATRIX_SCFG3	(AT91_MATRIX + 0x4C)	/* Slave Configuration Register 3 */
+#define AT91_MATRIX_SCFG4	(AT91_MATRIX + 0x50)	/* Slave Configuration Register 4 */
+#define		AT91_MATRIX_SLOT_CYCLE		(0xff <<  0)	/* Maximum Number of Allowed Cycles for a Burst */
+#define		AT91_MATRIX_DEFMSTR_TYPE	(3    << 16)	/* Default Master Type */
+#define			AT91_MATRIX_DEFMSTR_TYPE_NONE	(0 << 16)
+#define			AT91_MATRIX_DEFMSTR_TYPE_LAST	(1 << 16)
+#define			AT91_MATRIX_DEFMSTR_TYPE_FIXED	(2 << 16)
+#define		AT91_MATRIX_FIXED_DEFMSTR	(7    << 18)	/* Fixed Index of Default Master */
+#define		AT91_MATRIX_ARBT		(3    << 24)	/* Arbitration Type */
+#define			AT91_MATRIX_ARBT_ROUND_ROBIN	(0 << 24)
+#define			AT91_MATRIX_ARBT_FIXED_PRIORITY	(1 << 24)
+
+#define AT91_MATRIX_PRAS0	(AT91_MATRIX + 0x80)	/* Priority Register A for Slave 0 */
+#define AT91_MATRIX_PRAS1	(AT91_MATRIX + 0x88)	/* Priority Register A for Slave 1 */
+#define AT91_MATRIX_PRAS2	(AT91_MATRIX + 0x90)	/* Priority Register A for Slave 2 */
+#define AT91_MATRIX_PRAS3	(AT91_MATRIX + 0x98)	/* Priority Register A for Slave 3 */
+#define AT91_MATRIX_PRAS4	(AT91_MATRIX + 0xA0)	/* Priority Register A for Slave 4 */
+#define		AT91_MATRIX_M0PR		(3 << 0)	/* Master 0 Priority */
+#define		AT91_MATRIX_M1PR		(3 << 4)	/* Master 1 Priority */
+#define		AT91_MATRIX_M2PR		(3 << 8)	/* Master 2 Priority */
+#define		AT91_MATRIX_M3PR		(3 << 12)	/* Master 3 Priority */
+#define		AT91_MATRIX_M4PR		(3 << 16)	/* Master 4 Priority */
+#define		AT91_MATRIX_M5PR		(3 << 20)	/* Master 5 Priority */
+
+#define AT91_MATRIX_MRCR	(AT91_MATRIX + 0x100)	/* Master Remap Control Register */
+#define		AT91_MATRIX_RCB0		(1 << 0)	/* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
+#define		AT91_MATRIX_RCB1		(1 << 1)	/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
+
+#define AT91_MATRIX_EBICSA	(AT91_MATRIX + 0x11C)	/* EBI Chip Select Assignment Register */
+#define		AT91_MATRIX_CS1A		(1 << 1)	/* Chip Select 1 Assignment */
+#define			AT91_MATRIX_CS1A_SMC		(0 << 1)
+#define			AT91_MATRIX_CS1A_SDRAMC		(1 << 1)
+#define		AT91_MATRIX_CS3A		(1 << 3)	/* Chip Select 3 Assignment */
+#define			AT91_MATRIX_CS3A_SMC		(0 << 3)
+#define			AT91_MATRIX_CS3A_SMC_SMARTMEDIA	(1 << 3)
+#define		AT91_MATRIX_CS4A		(1 << 4)	/* Chip Select 4 Assignment */
+#define			AT91_MATRIX_CS4A_SMC		(0 << 4)
+#define			AT91_MATRIX_CS4A_SMC_CF1	(1 << 4)
+#define		AT91_MATRIX_CS5A		(1 << 5 )	/* Chip Select 5 Assignment */
+#define			AT91_MATRIX_CS5A_SMC		(0 << 5)
+#define			AT91_MATRIX_CS5A_SMC_CF2	(1 << 5)
+#define		AT91_MATRIX_DBPUC		(1 << 8)	/* Data Bus Pull-up Configuration */
+#define		AT91_MATRIX_VDDIOMSEL		(1 << 16)	/* Memory voltage selection */
+#define			AT91_MATRIX_VDDIOMSEL_1_8V	(0 << 16)
+#define			AT91_MATRIX_VDDIOMSEL_3_3V	(1 << 16)
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91sam9261.h b/include/asm-arm/arch-at91/at91sam9261.h
new file mode 100644
index 0000000..01b58ff
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91sam9261.h
@@ -0,0 +1,292 @@
+/*
+ * include/asm-arm/arch-at91/at91sam9261.h
+ *
+ * Copyright (C) SAN People
+ *
+ * Common definitions.
+ * Based on AT91SAM9261 datasheet revision E. (Preliminary)
+ *
+ * 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 AT91SAM9261_H
+#define AT91SAM9261_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91_ID_FIQ		0	/* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS		1	/* System Peripherals */
+#define AT91SAM9261_ID_PIOA	2	/* Parallel IO Controller A */
+#define AT91SAM9261_ID_PIOB	3	/* Parallel IO Controller B */
+#define AT91SAM9261_ID_PIOC	4	/* Parallel IO Controller C */
+#define AT91SAM9261_ID_US0	6	/* USART 0 */
+#define AT91SAM9261_ID_US1	7	/* USART 1 */
+#define AT91SAM9261_ID_US2	8	/* USART 2 */
+#define AT91SAM9261_ID_MCI	9	/* Multimedia Card Interface */
+#define AT91SAM9261_ID_UDP	10	/* USB Device Port */
+#define AT91SAM9261_ID_TWI	11	/* Two-Wire Interface */
+#define AT91SAM9261_ID_SPI0	12	/* Serial Peripheral Interface 0 */
+#define AT91SAM9261_ID_SPI1	13	/* Serial Peripheral Interface 1 */
+#define AT91SAM9261_ID_SSC0	14	/* Serial Synchronous Controller 0 */
+#define AT91SAM9261_ID_SSC1	15	/* Serial Synchronous Controller 1 */
+#define AT91SAM9261_ID_SSC2	16	/* Serial Synchronous Controller 2 */
+#define AT91SAM9261_ID_TC0	17	/* Timer Counter 0 */
+#define AT91SAM9261_ID_TC1	18	/* Timer Counter 1 */
+#define AT91SAM9261_ID_TC2	19	/* Timer Counter 2 */
+#define AT91SAM9261_ID_UHP	20	/* USB Host port */
+#define AT91SAM9261_ID_LCDC	21	/* LDC Controller */
+#define AT91SAM9261_ID_IRQ0	29	/* Advanced Interrupt Controller (IRQ0) */
+#define AT91SAM9261_ID_IRQ1	30	/* Advanced Interrupt Controller (IRQ1) */
+#define AT91SAM9261_ID_IRQ2	31	/* Advanced Interrupt Controller (IRQ2) */
+
+
+/*
+ * User Peripheral physical base addresses.
+ */
+#define AT91SAM9261_BASE_TCB0		0xfffa0000
+#define AT91SAM9261_BASE_TC0		0xfffa0000
+#define AT91SAM9261_BASE_TC1		0xfffa0040
+#define AT91SAM9261_BASE_TC2		0xfffa0080
+#define AT91SAM9261_BASE_UDP		0xfffa4000
+#define AT91SAM9261_BASE_MCI		0xfffa8000
+#define AT91SAM9261_BASE_TWI		0xfffac000
+#define AT91SAM9261_BASE_US0		0xfffb0000
+#define AT91SAM9261_BASE_US1		0xfffb4000
+#define AT91SAM9261_BASE_US2		0xfffb8000
+#define AT91SAM9261_BASE_SSC0		0xfffbc000
+#define AT91SAM9261_BASE_SSC1		0xfffc0000
+#define AT91SAM9261_BASE_SSC2		0xfffc4000
+#define AT91SAM9261_BASE_SPI0		0xfffc8000
+#define AT91SAM9261_BASE_SPI1		0xfffcc000
+#define AT91_BASE_SYS			0xffffea00
+
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_SDRAMC	(0xffffea00 - AT91_BASE_SYS)
+#define AT91_SMC	(0xffffec00 - AT91_BASE_SYS)
+#define AT91_MATRIX	(0xffffee00 - AT91_BASE_SYS)
+#define AT91_AIC	(0xfffff000 - AT91_BASE_SYS)
+#define AT91_DBGU	(0xfffff200 - AT91_BASE_SYS)
+#define AT91_PIOA	(0xfffff400 - AT91_BASE_SYS)
+#define AT91_PIOB	(0xfffff600 - AT91_BASE_SYS)
+#define AT91_PIOC	(0xfffff800 - AT91_BASE_SYS)
+#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
+#define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
+#define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
+#define AT91_RTT	(0xfffffd20 - AT91_BASE_SYS)
+#define AT91_PIT	(0xfffffd30 - AT91_BASE_SYS)
+#define AT91_WDT	(0xfffffd40 - AT91_BASE_SYS)
+#define AT91_GPBR	(0xfffffd50 - AT91_BASE_SYS)
+
+
+/*
+ * Internal Memory.
+ */
+#define AT91SAM9261_SRAM_BASE	0x00300000	/* Internal SRAM base address */
+#define AT91SAM9261_SRAM_SIZE	0x00028000	/* Internal SRAM size (160Kb) */
+
+#define AT91SAM9261_ROM_BASE	0x00400000	/* Internal ROM base address */
+#define AT91SAM9261_ROM_SIZE	SZ_32K		/* Internal ROM size (32Kb) */
+
+#define AT91SAM9261_UHP_BASE	0x00500000	/* USB Host controller */
+#define AT91SAM9261_LCDC_BASE	0x00600000	/* LDC controller */
+
+
+#if 0
+/*
+ * PIO pin definitions (peripheral A/B multiplexing).
+ */
+#define AT91_PA0_SPI0_MISO	(1 <<  0)	/* A: SPI0 Master In Slave */
+#define AT91_PA0_MCDA0		(1 <<  0)	/* B: Multimedia Card A Data 0 */
+#define AT91_PA1_SPI0_MOSI	(1 <<  1)	/* A: SPI0 Master Out Slave */
+#define AT91_PA1_MCCDA		(1 <<  1)	/* B: Multimedia Card A Command */
+#define AT91_PA2_SPI0_SPCK	(1 <<  2)	/* A: SPI0 Serial Clock */
+#define AT91_PA2_MCCK		(1 <<  2)	/* B: Multimedia Card Clock */
+#define AT91_PA3_SPI0_NPCS0	(1 <<  3)	/* A: SPI0 Peripheral Chip Select 0 */
+#define AT91_PA4_SPI0_NPCS1	(1 <<  4)	/* A: SPI0 Peripheral Chip Select 1 */
+#define AT91_PA4_MCDA1		(1 <<  4)	/* B: Multimedia Card A Data 1 */
+#define AT91_PA5_SPI0_NPCS2	(1 <<  5)	/* A: SPI0 Peripheral Chip Select 2 */
+#define AT91_PA5_MCDA2		(1 <<  5)	/* B: Multimedia Card A Data 2 */
+#define AT91_PA6_SPI0_NPCS3	(1 <<  6)	/* A: SPI0 Peripheral Chip Select 3 */
+#define AT91_PA6_MCDA3		(1 <<  6)	/* B: Multimedia Card A Data 3 */
+#define AT91_PA7_TWD		(1 <<  7)	/* A: TWI Two-wire Serial Data */
+#define AT91_PA7_PCK0		(1 <<  7)	/* B: PMC Programmable clock Output 0 */
+#define AT91_PA8_TWCK		(1 <<  8)	/* A: TWI Two-wire Serial Clock */
+#define AT91_PA8_PCK1		(1 <<  8)	/* B: PMC Programmable clock Output 1 */
+#define AT91_PA9_DRXD		(1 <<  9)	/* A: DBGU Debug Receive Data */
+#define AT91_PA9_PCK2		(1 <<  9)	/* B: PMC Programmable clock Output 2 */
+#define AT91_PA10_DTXD		(1 << 10)	/* A: DBGU Debug Transmit Data */
+#define AT91_PA10_PCK3		(1 << 10)	/* B: PMC Programmable clock Output 3 */
+#define AT91_PA11_TSYNC		(1 << 11)	/* A: Trace Synchronization Signal */
+#define AT91_PA11_SCK1		(1 << 11)	/* B: USART1 Serial Clock */
+#define AT91_PA12_TCLK		(1 << 12)	/* A: Trace Clock */
+#define AT91_PA12_RTS1		(1 << 12)	/* B: USART1 Ready To Send */
+#define AT91_PA13_TPS0		(1 << 13)	/* A: Trace ARM Pipeline Status 0 */
+#define AT91_PA13_CTS1		(1 << 13)	/* B: USART1 Clear To Send */
+#define AT91_PA14_TPS1		(1 << 14)	/* A: Trace ARM Pipeline Status 1 */
+#define AT91_PA14_SCK2		(1 << 14)	/* B: USART2 Serial Clock */
+#define AT91_PA15_TPS2		(1 << 15)	/* A: Trace ARM Pipeline Status 2 */
+#define AT91_PA15_RTS2		(1 << 15)	/* B: USART2 Ready To Send */
+#define AT91_PA16_TPK0		(1 << 16)	/* A: Trace Packet Port 0 */
+#define AT91_PA16_CTS2		(1 << 16)	/* B: USART2 Clear To Send */
+#define AT91_PA17_TPK1		(1 << 17)	/* A: Trace Packet Port 1 */
+#define AT91_PA17_TF1		(1 << 17)	/* B: SSC1 Transmit Frame Sync */
+#define AT91_PA18_TPK2		(1 << 18)	/* A: Trace Packet Port 2 */
+#define AT91_PA18_TK1		(1 << 18)	/* B: SSC1 Transmit Clock */
+#define AT91_PA19_TPK3		(1 << 19)	/* A: Trace Packet Port 3 */
+#define AT91_PA19_TD1		(1 << 19)	/* B: SSC1 Transmit Data */
+#define AT91_PA20_TPK4		(1 << 20)	/* A: Trace Packet Port 4 */
+#define AT91_PA20_RD1		(1 << 20)	/* B: SSC1 Receive Data */
+#define AT91_PA21_TPK5		(1 << 21)	/* A: Trace Packet Port 5 */
+#define AT91_PA21_RK1		(1 << 21)	/* B: SSC1 Receive Clock */
+#define AT91_PA22_TPK6		(1 << 22)	/* A: Trace Packet Port 6 */
+#define AT91_PA22_RF1		(1 << 22)	/* B: SSC1 Receive Frame Sync */
+#define AT91_PA23_TPK7		(1 << 23)	/* A: Trace Packet Port 7 */
+#define AT91_PA23_RTS0		(1 << 23)	/* B: USART0 Ready To Send */
+#define AT91_PA24_TPK8		(1 << 24)	/* A: Trace Packet Port 8 */
+#define AT91_PA24_SPI1_NPCS1	(1 << 24)	/* B: SPI1 Peripheral Chip Select 1 */
+#define AT91_PA25_TPK9		(1 << 25)	/* A: Trace Packet Port 9 */
+#define AT91_PA25_SPI1_NPCS2	(1 << 25)	/* B: SPI1 Peripheral Chip Select 2 */
+#define AT91_PA26_TPK10		(1 << 26)	/* A: Trace Packet Port 10 */
+#define AT91_PA26_SPI1_NPCS3	(1 << 26)	/* B: SPI1 Peripheral Chip Select 3 */
+#define AT91_PA27_TPK11		(1 << 27)	/* A: Trace Packet Port 11 */
+#define AT91_PA27_SPI0_NPCS1	(1 << 27)	/* B: SPI0 Peripheral Chip Select 1 */
+#define AT91_PA28_TPK12		(1 << 28)	/* A: Trace Packet Port 12 */
+#define AT91_PA28_SPI0_NPCS2	(1 << 28)	/* B: SPI0 Peripheral Chip Select 2 */
+#define AT91_PA29_TPK13		(1 << 29)	/* A: Trace Packet Port 13 */
+#define AT91_PA29_SPI0_NPCS3	(1 << 29)	/* B: SPI0 Peripheral Chip Select 3 */
+#define AT91_PA30_TPK14		(1 << 30)	/* A: Trace Packet Port 14 */
+#define AT91_PA30_A23		(1 << 30)	/* B: Address Bus bit 23 */
+#define AT91_PA31_TPK15		(1 << 31)	/* A: Trace Packet Port 15 */
+#define AT91_PA31_A24		(1 << 31)	/* B: Address Bus bit 24 */
+
+#define AT91_PB0_LCDVSYNC	(1 <<  0)	/* A: LCD Vertical Synchronization */
+#define AT91_PB1_LCDHSYNC	(1 <<  1)	/* A: LCD Horizontal Synchronization */
+#define AT91_PB2_LCDDOTCK	(1 <<  2)	/* A: LCD Dot Clock */
+#define AT91_PB2_PCK0		(1 <<  2)	/* B: PMC Programmable clock Output 0 */
+#define AT91_PB3_LCDDEN		(1 <<  3)	/* A: LCD Data Enable */
+#define AT91_PB4_LCDCC		(1 <<  4)	/* A: LCD Contrast Control */
+#define AT91_PB4_LCDD2		(1 <<  4)	/* B: LCD Data Bus Bit 2 */
+#define AT91_PB5_LCDD0		(1 <<  5)	/* A: LCD Data Bus Bit 0 */
+#define AT91_PB5_LCDD3		(1 <<  5)	/* B: LCD Data Bus Bit 3 */
+#define AT91_PB6_LCDD1		(1 <<  6)	/* A: LCD Data Bus Bit 1 */
+#define AT91_PB6_LCDD4		(1 <<  6)	/* B: LCD Data Bus Bit 4 */
+#define AT91_PB7_LCDD2		(1 <<  7)	/* A: LCD Data Bus Bit 2 */
+#define AT91_PB7_LCDD5		(1 <<  7)	/* B: LCD Data Bus Bit 5 */
+#define AT91_PB8_LCDD3		(1 <<  8)	/* A: LCD Data Bus Bit 3 */
+#define AT91_PB8_LCDD6		(1 <<  8)	/* B: LCD Data Bus Bit 6 */
+#define AT91_PB9_LCDD4		(1 <<  9)	/* A: LCD Data Bus Bit 4 */
+#define AT91_PB9_LCDD7		(1 <<  9)	/* B: LCD Data Bus Bit 7 */
+#define AT91_PB10_LCDD5		(1 << 10)	/* A: LCD Data Bus Bit 5 */
+#define AT91_PB10_LCDD10	(1 << 10)	/* B: LCD Data Bus Bit 10 */
+#define AT91_PB11_LCDD6		(1 << 11)	/* A: LCD Data Bus Bit 6 */
+#define AT91_PB11_LCDD11	(1 << 11)	/* B: LCD Data Bus Bit 11 */
+#define AT91_PB12_LCDD7		(1 << 12)	/* A: LCD Data Bus Bit 7 */
+#define AT91_PB12_LCDD12	(1 << 12)	/* B: LCD Data Bus Bit 12 */
+#define AT91_PB13_LCDD8		(1 << 13)	/* A: LCD Data Bus Bit 8 */
+#define AT91_PB13_LCDD13	(1 << 13)	/* B: LCD Data Bus Bit 13 */
+#define AT91_PB14_LCDD9		(1 << 14)	/* A: LCD Data Bus Bit 9 */
+#define AT91_PB14_LCDD14	(1 << 14)	/* B: LCD Data Bus Bit 14 */
+#define AT91_PB15_LCDD10	(1 << 15)	/* A: LCD Data Bus Bit 10 */
+#define AT91_PB15_LCDD15	(1 << 15)	/* B: LCD Data Bus Bit 15 */
+#define AT91_PB16_LCDD11	(1 << 16)	/* A: LCD Data Bus Bit 11 */
+#define AT91_PB16_LCDD19	(1 << 16)	/* B: LCD Data Bus Bit 19 */
+#define AT91_PB17_LCDD12	(1 << 17)	/* A: LCD Data Bus Bit 12 */
+#define AT91_PB17_LCDD20	(1 << 17)	/* B: LCD Data Bus Bit 20 */
+#define AT91_PB18_LCDD13	(1 << 18)	/* A: LCD Data Bus Bit 13 */
+#define AT91_PB18_LCDD21	(1 << 18)	/* B: LCD Data Bus Bit 21 */
+#define AT91_PB19_LCDD14	(1 << 19)	/* A: LCD Data Bus Bit 14 */
+#define AT91_PB19_LCDD22	(1 << 19)	/* B: LCD Data Bus Bit 22 */
+#define AT91_PB20_LCDD15	(1 << 20)	/* A: LCD Data Bus Bit 15 */
+#define AT91_PB20_LCDD23	(1 << 20)	/* B: LCD Data Bus Bit 23 */
+#define AT91_PB21_TF0		(1 << 21)	/* A: SSC0 Transmit Frame Sync */
+#define AT91_PB21_LCDD16	(1 << 21)	/* B: LCD Data Bus Bit 16 */
+#define AT91_PB22_TK0		(1 << 22)	/* A: SSC0 Transmit Clock */
+#define AT91_PB22_LCDD17	(1 << 22)	/* B: LCD Data Bus Bit 17 */
+#define AT91_PB23_TD0		(1 << 23)	/* A: SSC0 Transmit Data */
+#define AT91_PB23_LCDD18	(1 << 23)	/* B: LCD Data Bus Bit 18 */
+#define AT91_PB24_RD0		(1 << 24)	/* A: SSC0 Receive Data */
+#define AT91_PB24_LCDD19	(1 << 24)	/* B: LCD Data Bus Bit 19 */
+#define AT91_PB25_RK0		(1 << 25)	/* A: SSC0 Receive Clock */
+#define AT91_PB25_LCDD20	(1 << 25)	/* B: LCD Data Bus Bit 20 */
+#define AT91_PB26_RF0		(1 << 26)	/* A: SSC0 Receive Frame Sync */
+#define AT91_PB26_LCDD21	(1 << 26)	/* B: LCD Data Bus Bit 21 */
+#define AT91_PB27_SPI1_NPCS1	(1 << 27)	/* A: SPI1 Peripheral Chip Select 1 */
+#define AT91_PB27_LCDD22	(1 << 27)	/* B: LCD Data Bus Bit 22 */
+#define AT91_PB28_SPI1_NPCS0	(1 << 28)	/* A: SPI1 Peripheral Chip Select 0 */
+#define AT91_PB28_LCDD23	(1 << 28)	/* B: LCD Data Bus Bit 23 */
+#define AT91_PB29_SPI1_SPCK	(1 << 29)	/* A: SPI1 Serial Clock */
+#define AT91_PB29_IRQ2		(1 << 29)	/* B: Interrupt input 2 */
+#define AT91_PB30_SPI1_MISO	(1 << 30)	/* A: SPI1 Master In Slave */
+#define AT91_PB30_IRQ1		(1 << 30)	/* B: Interrupt input 1 */
+#define AT91_PB31_SPI1_MOSI	(1 << 31)	/* A: SPI1 Master Out Slave */
+#define AT91_PB31_PCK2		(1 << 31)	/* B: PMC Programmable clock Output 2 */
+
+#define AT91_PC0_SMOE		(1 << 0)	/* A: SmartMedia Output Enable */
+#define AT91_PC0_NCS6		(1 << 0)	/* B: Chip Select 6 */
+#define AT91_PC1_SMWE		(1 << 1)	/* A: SmartMedia Write Enable */
+#define AT91_PC1_NCS7		(1 << 1)	/* B: Chip Select 7 */
+#define AT91_PC2_NWAIT		(1 << 2)	/* A: NWAIT */
+#define AT91_PC2_IRQ0		(1 << 2)	/* B: Interrupt input 0 */
+#define AT91_PC3_A25_CFRNW	(1 << 3)	/* A: Address Bus[25] / Compact Flash Read Not Write */
+#define AT91_PC4_NCS4_CFCS0	(1 << 4)	/* A: Chip Select 4 / CompactFlash Chip Select 0 */
+#define AT91_PC5_NCS5_CFCS1	(1 << 5)	/* A: Chip Select 5 / CompactFlash Chip Select 1 */
+#define AT91_PC6_CFCE1		(1 << 6)	/* A: CompactFlash Chip Enable 1 */
+#define AT91_PC7_CFCE2		(1 << 7)	/* A: CompactFlash Chip Enable 2 */
+#define AT91_PC8_TXD0		(1 << 8)	/* A: USART0 Transmit Data */
+#define AT91_PC8_PCK2		(1 << 8)	/* B: PMC Programmable clock Output 2 */
+#define AT91_PC9_RXD0		(1 << 9)	/* A: USART0 Receive Data */
+#define AT91_PC9_PCK3		(1 << 9)	/* B: PMC Programmable clock Output 3 */
+#define AT91_PC10_RTS0		(1 << 10)	/* A: USART0 Ready To Send */
+#define AT91_PC10_SCK0		(1 << 10)	/* B: USART0 Serial Clock */
+#define AT91_PC11_CTS0		(1 << 11)	/* A: USART0 Clear To Send */
+#define AT91_PC11_FIQ		(1 << 11)	/* B: AIC Fast Interrupt Input */
+#define AT91_PC12_TXD1		(1 << 12)	/* A: USART1 Transmit Data */
+#define AT91_PC12_NCS6		(1 << 12)	/* B: Chip Select 6 */
+#define AT91_PC13_RXD1		(1 << 13)	/* A: USART1 Receive Data */
+#define AT91_PC13_NCS7		(1 << 13)	/* B: Chip Select 7 */
+#define AT91_PC14_TXD2		(1 << 14)	/* A: USART2 Transmit Data */
+#define AT91_PC14_SPI1_NPCS2	(1 << 14)	/* B: SPI1 Peripheral Chip Select 2 */
+#define AT91_PC15_RXD2		(1 << 15)	/* A: USART2 Receive Data */
+#define AT91_PC15_SPI1_NPCS3	(1 << 15)	/* B: SPI1 Peripheral Chip Select 3 */
+#define AT91_PC16_D16		(1 << 16)	/* A: Data Bus [16] */
+#define AT91_PC16_TCLK0		(1 << 16)	/* B: Timer Counter 0 external clock input */
+#define AT91_PC17_D17		(1 << 17)	/* A: Data Bus [17] */
+#define AT91_PC17_TCLK1		(1 << 17)	/* B: Timer Counter 1 external clock input */
+#define AT91_PC18_D18		(1 << 18)	/* A: Data Bus [18] */
+#define AT91_PC18_TCLK2		(1 << 18)	/* B: Timer Counter 2 external clock input */
+#define AT91_PC19_D19		(1 << 19)	/* A: Data Bus [19] */
+#define AT91_PC19_TIOA0		(1 << 19)	/* B: Timer Counter 0 Multipurpose Timer I/O Pin A */
+#define AT91_PC20_D20		(1 << 20)	/* A: Data Bus [20] */
+#define AT91_PC20_TIOB0		(1 << 20)	/* B: Timer Counter 0 Multipurpose Timer I/O Pin B */
+#define AT91_PC21_D21		(1 << 21)	/* A: Data Bus [21] */
+#define AT91_PC21_TIOA1		(1 << 21)	/* B: Timer Counter 1 Multipurpose Timer I/O Pin A */
+#define AT91_PC22_D22		(1 << 22)	/* A: Data Bus [22] */
+#define AT91_PC22_TIOB1		(1 << 22)	/* B: Timer Counter 1 Multipurpose Timer I/O Pin B */
+#define AT91_PC23_D23		(1 << 23)	/* A: Data Bus [23] */
+#define AT91_PC23_TIOA2		(1 << 23)	/* B: Timer Counter 2 Multipurpose Timer I/O Pin A */
+#define AT91_PC24_D24		(1 << 24)	/* A: Data Bus [24] */
+#define AT91_PC24_TIOB2		(1 << 24)	/* B: Timer Counter 2 Multipurpose Timer I/O Pin B */
+#define AT91_PC25_D25		(1 << 25)	/* A: Data Bus [25] */
+#define AT91_PC25_TF2		(1 << 25)	/* B: SSC2 Transmit Frame Sync */
+#define AT91_PC26_D26		(1 << 26)	/* A: Data Bus [26] */
+#define AT91_PC26_TK2		(1 << 26)	/* B: SSC2 Transmit Clock */
+#define AT91_PC27_D27		(1 << 27)	/* A: Data Bus [27] */
+#define AT91_PC27_TD2		(1 << 27)	/* B: SSC2 Transmit Data */
+#define AT91_PC28_D28		(1 << 28)	/* A: Data Bus [28] */
+#define AT91_PC28_RD2		(1 << 28)	/* B: SSC2 Receive Data */
+#define AT91_PC29_D29		(1 << 29)	/* A: Data Bus [29] */
+#define AT91_PC29_RK2		(1 << 29)	/* B: SSC2 Receive Clock */
+#define AT91_PC30_D30		(1 << 30)	/* A: Data Bus [30] */
+#define AT91_PC30_RF2		(1 << 30)	/* B: SSC2 Receive Frame Sync */
+#define AT91_PC31_D31		(1 << 31)	/* A: Data Bus [31] */
+#define AT91_PC31_PCK1		(1 << 31)	/* B: PMC Programmable clock Output 1 */
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91sam9261_matrix.h b/include/asm-arm/arch-at91/at91sam9261_matrix.h
new file mode 100644
index 0000000..6f07242
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91sam9261_matrix.h
@@ -0,0 +1,62 @@
+/*
+ * include/asm-arm/arch-at91/at91sam9261_matrix.h
+ *
+ * Memory Controllers (MATRIX, EBI) - System peripherals registers.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * 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 AT91SAM9261_MATRIX_H
+#define AT91SAM9261_MATRIX_H
+
+#define AT91_MATRIX_MCFG	(AT91_MATRIX + 0x00)	/* Master Configuration Register */
+#define		AT91_MATRIX_RCB0	(1 << 0)		/* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
+#define		AT91_MATRIX_RCB1	(1 << 1)		/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
+
+#define AT91_MATRIX_SCFG0	(AT91_MATRIX + 0x04)	/* Slave Configuration Register 0 */
+#define AT91_MATRIX_SCFG1	(AT91_MATRIX + 0x08)	/* Slave Configuration Register 1 */
+#define AT91_MATRIX_SCFG2	(AT91_MATRIX + 0x0C)	/* Slave Configuration Register 2 */
+#define AT91_MATRIX_SCFG3	(AT91_MATRIX + 0x10)	/* Slave Configuration Register 3 */
+#define AT91_MATRIX_SCFG4	(AT91_MATRIX + 0x14)	/* Slave Configuration Register 4 */
+#define		AT91_MATRIX_SLOT_CYCLE		(0xff << 0)	/* Maximum Number of Allowed Cycles for a Burst */
+#define		AT91_MATRIX_DEFMSTR_TYPE	(3    << 16)	/* Default Master Type */
+#define			AT91_MATRIX_DEFMSTR_TYPE_NONE	(0 << 16)
+#define			AT91_MATRIX_DEFMSTR_TYPE_LAST	(1 << 16)
+#define			AT91_MATRIX_DEFMSTR_TYPE_FIXED	(2 << 16)
+#define		AT91_MATRIX_FIXED_DEFMSTR	(7    << 18)	/* Fixed Index of Default Master */
+
+#define AT91_MATRIX_TCR		(AT91_MATRIX + 0x24)	/* TCM Configuration Register */
+#define		AT91_MATRIX_ITCM_SIZE		(0xf << 0)	/* Size of ITCM enabled memory block */
+#define			AT91_MATRIX_ITCM_0		(0 << 0)
+#define			AT91_MATRIX_ITCM_16		(5 << 0)
+#define			AT91_MATRIX_ITCM_32		(6 << 0)
+#define			AT91_MATRIX_ITCM_64		(7 << 0)
+#define		AT91_MATRIX_DTCM_SIZE		(0xf << 4)	/* Size of DTCM enabled memory block */
+#define			AT91_MATRIX_DTCM_0		(0 << 4)
+#define			AT91_MATRIX_DTCM_16		(5 << 4)
+#define			AT91_MATRIX_DTCM_32		(6 << 4)
+#define			AT91_MATRIX_DTCM_64		(7 << 4)
+
+#define AT91_MATRIX_EBICSA	(AT91_MATRIX + 0x30)	/* EBI Chip Select Assignment Register */
+#define		AT91_MATRIX_CS1A		(1 << 1)	/* Chip Select 1 Assignment */
+#define			AT91_MATRIX_CS1A_SMC		(0 << 1)
+#define			AT91_MATRIX_CS1A_SDRAMC		(1 << 1)
+#define		AT91_MATRIX_CS3A		(1 << 3)	/* Chip Select 3 Assignment */
+#define			AT91_MATRIX_CS3A_SMC		(0 << 3)
+#define			AT91_MATRIX_CS3A_SMC_SMARTMEDIA	(1 << 3)
+#define		AT91_MATRIX_CS4A		(1 << 4)	/* Chip Select 4 Assignment */
+#define			AT91_MATRIX_CS4A_SMC		(0 << 4)
+#define			AT91_MATRIX_CS4A_SMC_CF1	(1 << 4)
+#define		AT91_MATRIX_CS5A		(1 << 5)	/* Chip Select 5 Assignment */
+#define			AT91_MATRIX_CS5A_SMC		(0 << 5)
+#define			AT91_MATRIX_CS5A_SMC_CF2	(1 << 5)
+#define		AT91_MATRIX_DBPUC		(1 << 8)	/* Data Bus Pull-up Configuration */
+
+#define AT91_MATRIX_USBPUCR	(AT91_MATRIX + 0x34)	/* USB Pad Pull-Up Control Register */
+#define		AT91_MATRIX_USBPUCR_PUON	(1 << 30)	/* USB Device PAD Pull-up Enable */
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91sam9263.h b/include/asm-arm/arch-at91/at91sam9263.h
new file mode 100644
index 0000000..f4af68a
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91sam9263.h
@@ -0,0 +1,131 @@
+/*
+ * include/asm-arm/arch-at91/at91sam9263.h
+ *
+ * (C) 2007 Atmel Corporation.
+ *
+ * Common definitions.
+ * Based on AT91SAM9263 datasheet revision B (Preliminary).
+ *
+ * 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 AT91SAM9263_H
+#define AT91SAM9263_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91_ID_FIQ		0	/* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS		1	/* System Peripherals */
+#define AT91SAM9263_ID_PIOA	2	/* Parallel IO Controller A */
+#define AT91SAM9263_ID_PIOB	3	/* Parallel IO Controller B */
+#define AT91SAM9263_ID_PIOCDE	4	/* Parallel IO Controller C, D and E */
+#define AT91SAM9263_ID_US0	7	/* USART 0 */
+#define AT91SAM9263_ID_US1	8	/* USART 1 */
+#define AT91SAM9263_ID_US2	9	/* USART 2 */
+#define AT91SAM9263_ID_MCI0	10	/* Multimedia Card Interface 0 */
+#define AT91SAM9263_ID_MCI1	11	/* Multimedia Card Interface 1 */
+#define AT91SAM9263_ID_CAN	12	/* CAN */
+#define AT91SAM9263_ID_TWI	13	/* Two-Wire Interface */
+#define AT91SAM9263_ID_SPI0	14	/* Serial Peripheral Interface 0 */
+#define AT91SAM9263_ID_SPI1	15	/* Serial Peripheral Interface 1 */
+#define AT91SAM9263_ID_SSC0	16	/* Serial Synchronous Controller 0 */
+#define AT91SAM9263_ID_SSC1	17	/* Serial Synchronous Controller 1 */
+#define AT91SAM9263_ID_AC97C	18	/* AC97 Controller */
+#define AT91SAM9263_ID_TCB	19	/* Timer Counter 0, 1 and 2 */
+#define AT91SAM9263_ID_PWMC	20	/* Pulse Width Modulation Controller */
+#define AT91SAM9263_ID_EMAC	21	/* Ethernet */
+#define AT91SAM9263_ID_2DGE	23	/* 2D Graphic Engine */
+#define AT91SAM9263_ID_UDP	24	/* USB Device Port */
+#define AT91SAM9263_ID_ISI	25	/* Image Sensor Interface */
+#define AT91SAM9263_ID_LCDC	26	/* LCD Controller */
+#define AT91SAM9263_ID_DMA	27	/* DMA Controller */
+#define AT91SAM9263_ID_UHP	29	/* USB Host port */
+#define AT91SAM9263_ID_IRQ0	30	/* Advanced Interrupt Controller (IRQ0) */
+#define AT91SAM9263_ID_IRQ1	31	/* Advanced Interrupt Controller (IRQ1) */
+
+
+/*
+ * User Peripheral physical base addresses.
+ */
+#define AT91SAM9263_BASE_UDP		0xfff78000
+#define AT91SAM9263_BASE_TCB0		0xfff7c000
+#define AT91SAM9263_BASE_TC0		0xfff7c000
+#define AT91SAM9263_BASE_TC1		0xfff7c040
+#define AT91SAM9263_BASE_TC2		0xfff7c080
+#define AT91SAM9263_BASE_MCI0		0xfff80000
+#define AT91SAM9263_BASE_MCI1		0xfff84000
+#define AT91SAM9263_BASE_TWI		0xfff88000
+#define AT91SAM9263_BASE_US0		0xfff8c000
+#define AT91SAM9263_BASE_US1		0xfff90000
+#define AT91SAM9263_BASE_US2		0xfff94000
+#define AT91SAM9263_BASE_SSC0		0xfff98000
+#define AT91SAM9263_BASE_SSC1		0xfff9c000
+#define AT91SAM9263_BASE_AC97C		0xfffa0000
+#define AT91SAM9263_BASE_SPI0		0xfffa4000
+#define AT91SAM9263_BASE_SPI1		0xfffa8000
+#define AT91SAM9263_BASE_CAN		0xfffac000
+#define AT91SAM9263_BASE_PWMC		0xfffb8000
+#define AT91SAM9263_BASE_EMAC		0xfffbc000
+#define AT91SAM9263_BASE_ISI		0xfffc4000
+#define AT91SAM9263_BASE_2DGE		0xfffc8000
+#define AT91_BASE_SYS			0xffffe000
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_ECC0	(0xffffe000 - AT91_BASE_SYS)
+#define AT91_SDRAMC0	(0xffffe200 - AT91_BASE_SYS)
+#define AT91_SMC0	(0xffffe400 - AT91_BASE_SYS)
+#define AT91_ECC1	(0xffffe600 - AT91_BASE_SYS)
+#define AT91_SDRAMC1	(0xffffe800 - AT91_BASE_SYS)
+#define AT91_SMC1	(0xffffea00 - AT91_BASE_SYS)
+#define AT91_MATRIX	(0xffffec00 - AT91_BASE_SYS)
+#define AT91_CCFG	(0xffffed10 - AT91_BASE_SYS)
+#define AT91_DBGU	(0xffffee00 - AT91_BASE_SYS)
+#define AT91_AIC	(0xfffff000 - AT91_BASE_SYS)
+#define AT91_PIOA	(0xfffff200 - AT91_BASE_SYS)
+#define AT91_PIOB	(0xfffff400 - AT91_BASE_SYS)
+#define AT91_PIOC	(0xfffff600 - AT91_BASE_SYS)
+#define AT91_PIOD	(0xfffff800 - AT91_BASE_SYS)
+#define AT91_PIOE	(0xfffffa00 - AT91_BASE_SYS)
+#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
+#define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
+#define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
+#define AT91_RTT0	(0xfffffd20 - AT91_BASE_SYS)
+#define AT91_PIT	(0xfffffd30 - AT91_BASE_SYS)
+#define AT91_WDT	(0xfffffd40 - AT91_BASE_SYS)
+#define AT91_RTT1	(0xfffffd50 - AT91_BASE_SYS)
+#define AT91_GPBR	(0xfffffd60 - AT91_BASE_SYS)
+
+#define AT91_SMC	AT91_SMC0
+
+/*
+ * Internal Memory.
+ */
+#define AT91SAM9263_SRAM0_BASE	0x00300000	/* Internal SRAM 0 base address */
+#define AT91SAM9263_SRAM0_SIZE	(80 * SZ_1K)	/* Internal SRAM 0 size (80Kb) */
+
+#define AT91SAM9263_ROM_BASE	0x00400000	/* Internal ROM base address */
+#define AT91SAM9263_ROM_SIZE	SZ_128K		/* Internal ROM size (128Kb) */
+
+#define AT91SAM9263_SRAM1_BASE	0x00500000	/* Internal SRAM 1 base address */
+#define AT91SAM9263_SRAM1_SIZE	SZ_16K		/* Internal SRAM 1 size (16Kb) */
+
+#define AT91SAM9263_LCDC_BASE	0x00700000	/* LCD Controller */
+#define AT91SAM9263_DMAC_BASE	0x00800000	/* DMA Controller */
+#define AT91SAM9263_UHP_BASE	0x00a00000	/* USB Host controller */
+
+#if 0
+/*
+ * PIO pin definitions (peripheral A/B multiplexing).
+ */
+
+// TODO: Add
+
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91sam9263_matrix.h b/include/asm-arm/arch-at91/at91sam9263_matrix.h
new file mode 100644
index 0000000..6fc6e4b
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91sam9263_matrix.h
@@ -0,0 +1,129 @@
+/*
+ * include/asm-arm/arch-at91/at91sam9263_matrix.h
+ *
+ *  Copyright (C) 2006 Atmel Corporation.
+ *
+ * Memory Controllers (MATRIX, EBI) - System peripherals registers.
+ * Based on AT91SAM9263 datasheet revision B (Preliminary).
+ *
+ * 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 AT91SAM9263_MATRIX_H
+#define AT91SAM9263_MATRIX_H
+
+#define AT91_MATRIX_MCFG0	(AT91_MATRIX + 0x00)	/* Master Configuration Register 0 */
+#define AT91_MATRIX_MCFG1	(AT91_MATRIX + 0x04)	/* Master Configuration Register 1 */
+#define AT91_MATRIX_MCFG2	(AT91_MATRIX + 0x08)	/* Master Configuration Register 2 */
+#define AT91_MATRIX_MCFG3	(AT91_MATRIX + 0x0C)	/* Master Configuration Register 3 */
+#define AT91_MATRIX_MCFG4	(AT91_MATRIX + 0x10)	/* Master Configuration Register 4 */
+#define AT91_MATRIX_MCFG5	(AT91_MATRIX + 0x14)	/* Master Configuration Register 5 */
+#define AT91_MATRIX_MCFG6	(AT91_MATRIX + 0x18)	/* Master Configuration Register 6 */
+#define AT91_MATRIX_MCFG7	(AT91_MATRIX + 0x1C)	/* Master Configuration Register 7 */
+#define AT91_MATRIX_MCFG8	(AT91_MATRIX + 0x20)	/* Master Configuration Register 8 */
+#define		AT91_MATRIX_ULBT	(7 << 0)	/* Undefined Length Burst Type */
+#define			AT91_MATRIX_ULBT_INFINITE	(0 << 0)
+#define			AT91_MATRIX_ULBT_SINGLE		(1 << 0)
+#define			AT91_MATRIX_ULBT_FOUR		(2 << 0)
+#define			AT91_MATRIX_ULBT_EIGHT		(3 << 0)
+#define			AT91_MATRIX_ULBT_SIXTEEN	(4 << 0)
+
+#define AT91_MATRIX_SCFG0	(AT91_MATRIX + 0x40)	/* Slave Configuration Register 0 */
+#define AT91_MATRIX_SCFG1	(AT91_MATRIX + 0x44)	/* Slave Configuration Register 1 */
+#define AT91_MATRIX_SCFG2	(AT91_MATRIX + 0x48)	/* Slave Configuration Register 2 */
+#define AT91_MATRIX_SCFG3	(AT91_MATRIX + 0x4C)	/* Slave Configuration Register 3 */
+#define AT91_MATRIX_SCFG4	(AT91_MATRIX + 0x50)	/* Slave Configuration Register 4 */
+#define AT91_MATRIX_SCFG5	(AT91_MATRIX + 0x54)	/* Slave Configuration Register 5 */
+#define AT91_MATRIX_SCFG6	(AT91_MATRIX + 0x58)	/* Slave Configuration Register 6 */
+#define AT91_MATRIX_SCFG7	(AT91_MATRIX + 0x5C)	/* Slave Configuration Register 7 */
+#define		AT91_MATRIX_SLOT_CYCLE		(0xff << 0)	/* Maximum Number of Allowed Cycles for a Burst */
+#define		AT91_MATRIX_DEFMSTR_TYPE	(3    << 16)	/* Default Master Type */
+#define			AT91_MATRIX_DEFMSTR_TYPE_NONE	(0 << 16)
+#define			AT91_MATRIX_DEFMSTR_TYPE_LAST	(1 << 16)
+#define			AT91_MATRIX_DEFMSTR_TYPE_FIXED	(2 << 16)
+#define		AT91_MATRIX_FIXED_DEFMSTR	(7    << 18)	/* Fixed Index of Default Master */
+#define		AT91_MATRIX_ARBT		(3    << 24)	/* Arbitration Type */
+#define			AT91_MATRIX_ARBT_ROUND_ROBIN	(0 << 24)
+#define			AT91_MATRIX_ARBT_FIXED_PRIORITY	(1 << 24)
+
+#define AT91_MATRIX_PRAS0	(AT91_MATRIX + 0x80)	/* Priority Register A for Slave 0 */
+#define AT91_MATRIX_PRBS0	(AT91_MATRIX + 0x84)	/* Priority Register B for Slave 0 */
+#define AT91_MATRIX_PRAS1	(AT91_MATRIX + 0x88)	/* Priority Register A for Slave 1 */
+#define AT91_MATRIX_PRBS1	(AT91_MATRIX + 0x8C)	/* Priority Register B for Slave 1 */
+#define AT91_MATRIX_PRAS2	(AT91_MATRIX + 0x90)	/* Priority Register A for Slave 2 */
+#define AT91_MATRIX_PRBS2	(AT91_MATRIX + 0x94)	/* Priority Register B for Slave 2 */
+#define AT91_MATRIX_PRAS3	(AT91_MATRIX + 0x98)	/* Priority Register A for Slave 3 */
+#define AT91_MATRIX_PRBS3	(AT91_MATRIX + 0x9C)	/* Priority Register B for Slave 3 */
+#define AT91_MATRIX_PRAS4	(AT91_MATRIX + 0xA0)	/* Priority Register A for Slave 4 */
+#define AT91_MATRIX_PRBS4	(AT91_MATRIX + 0xA4)	/* Priority Register B for Slave 4 */
+#define AT91_MATRIX_PRAS5	(AT91_MATRIX + 0xA8)	/* Priority Register A for Slave 5 */
+#define AT91_MATRIX_PRBS5	(AT91_MATRIX + 0xAC)	/* Priority Register B for Slave 5 */
+#define AT91_MATRIX_PRAS6	(AT91_MATRIX + 0xB0)	/* Priority Register A for Slave 6 */
+#define AT91_MATRIX_PRBS6	(AT91_MATRIX + 0xB4)	/* Priority Register B for Slave 6 */
+#define AT91_MATRIX_PRAS7	(AT91_MATRIX + 0xB8)	/* Priority Register A for Slave 7 */
+#define AT91_MATRIX_PRBS7	(AT91_MATRIX + 0xBC)	/* Priority Register B for Slave 7 */
+#define		AT91_MATRIX_M0PR		(3 << 0)	/* Master 0 Priority */
+#define		AT91_MATRIX_M1PR		(3 << 4)	/* Master 1 Priority */
+#define		AT91_MATRIX_M2PR		(3 << 8)	/* Master 2 Priority */
+#define		AT91_MATRIX_M3PR		(3 << 12)	/* Master 3 Priority */
+#define		AT91_MATRIX_M4PR		(3 << 16)	/* Master 4 Priority */
+#define		AT91_MATRIX_M5PR		(3 << 20)	/* Master 5 Priority */
+#define		AT91_MATRIX_M6PR		(3 << 24)	/* Master 6 Priority */
+#define		AT91_MATRIX_M7PR		(3 << 28)	/* Master 7 Priority */
+#define		AT91_MATRIX_M8PR		(3 << 0)	/* Master 8 Priority (in Register B) */
+
+#define AT91_MATRIX_MRCR	(AT91_MATRIX + 0x100)	/* Master Remap Control Register */
+#define		AT91_MATRIX_RCB0		(1 << 0)	/* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
+#define		AT91_MATRIX_RCB1		(1 << 1)	/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
+#define		AT91_MATRIX_RCB2		(1 << 2)
+#define		AT91_MATRIX_RCB3		(1 << 3)
+#define		AT91_MATRIX_RCB4		(1 << 4)
+#define		AT91_MATRIX_RCB5		(1 << 5)
+#define		AT91_MATRIX_RCB6		(1 << 6)
+#define		AT91_MATRIX_RCB7		(1 << 7)
+#define		AT91_MATRIX_RCB8		(1 << 8)
+
+#define AT91_MATRIX_TCMR	(AT91_MATRIX + 0x114)	/* TCM Configuration Register */
+#define		AT91_MATRIX_ITCM_SIZE		(0xf << 0)	/* Size of ITCM enabled memory block */
+#define			AT91_MATRIX_ITCM_0		(0 << 0)
+#define			AT91_MATRIX_ITCM_16		(5 << 0)
+#define			AT91_MATRIX_ITCM_32		(6 << 0)
+#define		AT91_MATRIX_DTCM_SIZE		(0xf << 4)	/* Size of DTCM enabled memory block */
+#define			AT91_MATRIX_DTCM_0		(0 << 4)
+#define			AT91_MATRIX_DTCM_16		(5 << 4)
+#define			AT91_MATRIX_DTCM_32		(6 << 4)
+
+#define AT91_MATRIX_EBI0CSA	(AT91_MATRIX + 0x120)	/* EBI0 Chip Select Assignment Register */
+#define		AT91_MATRIX_EBI0_CS1A		(1 << 1)	/* Chip Select 1 Assignment */
+#define			AT91_MATRIX_EBI0_CS1A_SMC		(0 << 1)
+#define			AT91_MATRIX_EBI0_CS1A_SDRAMC		(1 << 1)
+#define		AT91_MATRIX_EBI0_CS3A		(1 << 3)	/* Chip Select 3 Assignment */
+#define			AT91_MATRIX_EBI0_CS3A_SMC		(0 << 3)
+#define			AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA	(1 << 3)
+#define		AT91_MATRIX_EBI0_CS4A		(1 << 4)	/* Chip Select 4 Assignment */
+#define			AT91_MATRIX_EBI0_CS4A_SMC		(0 << 4)
+#define			AT91_MATRIX_EBI0_CS4A_SMC_CF1		(1 << 4)
+#define		AT91_MATRIX_EBI0_CS5A		(1 << 5)	/* Chip Select 5 Assignment */
+#define			AT91_MATRIX_EBI0_CS5A_SMC		(0 << 5)
+#define			AT91_MATRIX_EBI0_CS5A_SMC_CF2		(1 << 5)
+#define		AT91_MATRIX_EBI0_DBPUC		(1 << 8)	/* Data Bus Pull-up Configuration */
+#define		AT91_MATRIX_EBI0_VDDIOMSEL	(1 << 16)	/* Memory voltage selection */
+#define			AT91_MATRIX_EBI0_VDDIOMSEL_1_8V		(0 << 16)
+#define			AT91_MATRIX_EBI0_VDDIOMSEL_3_3V		(1 << 16)
+
+#define AT91_MATRIX_EBI1CSA	(AT91_MATRIX + 0x124)	/* EBI1 Chip Select Assignment Register */
+#define		AT91_MATRIX_EBI1_CS1A		(1 << 1)	/* Chip Select 1 Assignment */
+#define			AT91_MATRIX_EBI1_CS1A_SMC		(0 << 1)
+#define			AT91_MATRIX_EBI1_CS1A_SDRAMC		(1 << 1)
+#define		AT91_MATRIX_EBI1_CS2A		(1 << 3)	/* Chip Select 3 Assignment */
+#define			AT91_MATRIX_EBI1_CS2A_SMC		(0 << 3)
+#define			AT91_MATRIX_EBI1_CS2A_SMC_SMARTMEDIA	(1 << 3)
+#define		AT91_MATRIX_EBI1_DBPUC		(1 << 8)	/* Data Bus Pull-up Configuration */
+#define		AT91_MATRIX_EBI1_VDDIOMSEL	(1 << 16)	/* Memory voltage selection */
+#define			AT91_MATRIX_EBI1_VDDIOMSEL_1_8V		(0 << 16)
+#define			AT91_MATRIX_EBI1_VDDIOMSEL_3_3V		(1 << 16)
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91sam926x_mc.h b/include/asm-arm/arch-at91/at91sam926x_mc.h
new file mode 100644
index 0000000..d82631c
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91sam926x_mc.h
@@ -0,0 +1,141 @@
+/*
+ * include/asm-arm/arch-at91/at91sam926x_mc.h
+ *
+ * Memory Controllers (SMC, SDRAMC) - System peripherals registers.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * 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 AT91SAM926x_MC_H
+#define AT91SAM926x_MC_H
+
+/* SDRAM Controller (SDRAMC) registers */
+#define AT91_SDRAMC_MR		(AT91_SDRAMC + 0x00)	/* SDRAM Controller Mode Register */
+#define		AT91_SDRAMC_MODE	(0xf << 0)		/* Command Mode */
+#define			AT91_SDRAMC_MODE_NORMAL		0
+#define			AT91_SDRAMC_MODE_NOP		1
+#define			AT91_SDRAMC_MODE_PRECHARGE	2
+#define			AT91_SDRAMC_MODE_LMR		3
+#define			AT91_SDRAMC_MODE_REFRESH	4
+#define			AT91_SDRAMC_MODE_EXT_LMR	5
+#define			AT91_SDRAMC_MODE_DEEP		6
+
+#define AT91_SDRAMC_TR		(AT91_SDRAMC + 0x04)	/* SDRAM Controller Refresh Timer Register */
+#define		AT91_SDRAMC_COUNT	(0xfff << 0)		/* Refresh Timer Counter */
+
+#define AT91_SDRAMC_CR		(AT91_SDRAMC + 0x08)	/* SDRAM Controller Configuration Register */
+#define		AT91_SDRAMC_NC		(3 << 0)		/* Number of Column Bits */
+#define			AT91_SDRAMC_NC_8	(0 << 0)
+#define			AT91_SDRAMC_NC_9	(1 << 0)
+#define			AT91_SDRAMC_NC_10	(2 << 0)
+#define			AT91_SDRAMC_NC_11	(3 << 0)
+#define		AT91_SDRAMC_NR		(3 << 2)		/* Number of Row Bits */
+#define			AT91_SDRAMC_NR_11	(0 << 2)
+#define			AT91_SDRAMC_NR_12	(1 << 2)
+#define			AT91_SDRAMC_NR_13	(2 << 2)
+#define		AT91_SDRAMC_NB		(1 << 4)		/* Number of Banks */
+#define			AT91_SDRAMC_NB_2	(0 << 4)
+#define			AT91_SDRAMC_NB_4	(1 << 4)
+#define		AT91_SDRAMC_CAS		(3 << 5)		/* CAS Latency */
+#define			AT91_SDRAMC_CAS_1	(1 << 5)
+#define			AT91_SDRAMC_CAS_2	(2 << 5)
+#define			AT91_SDRAMC_CAS_3	(3 << 5)
+#define		AT91_SDRAMC_DBW		(1 << 7)		/* Data Bus Width */
+#define			AT91_SDRAMC_DBW_32	(0 << 7)
+#define			AT91_SDRAMC_DBW_16	(1 << 7)
+#define		AT91_SDRAMC_TWR		(0xf <<  8)		/* Write Recovery Delay */
+#define		AT91_SDRAMC_TRC		(0xf << 12)		/* Row Cycle Delay */
+#define		AT91_SDRAMC_TRP		(0xf << 16)		/* Row Precharge Delay */
+#define		AT91_SDRAMC_TRCD	(0xf << 20)		/* Row to Column Delay */
+#define		AT91_SDRAMC_TRAS	(0xf << 24)		/* Active to Precharge Delay */
+#define		AT91_SDRAMC_TXSR	(0xf << 28)		/* Exit Self Refresh to Active Delay */
+
+#define AT91_SDRAMC_LPR		(AT91_SDRAMC + 0x10)	/* SDRAM Controller Low Power Register */
+#define		AT91_SDRAMC_LPCB		(3 << 0)	/* Low-power Configurations */
+#define			AT91_SDRAMC_LPCB_DISABLE		0
+#define			AT91_SDRAMC_LPCB_SELF_REFRESH		1
+#define			AT91_SDRAMC_LPCB_POWER_DOWN		2
+#define			AT91_SDRAMC_LPCB_DEEP_POWER_DOWN	3
+#define		AT91_SDRAMC_PASR		(7 << 4)	/* Partial Array Self Refresh */
+#define		AT91_SDRAMC_TCSR		(3 << 8)	/* Temperature Compensated Self Refresh */
+#define		AT91_SDRAMC_DS			(3 << 10)	/* Drive Strenght */
+#define		AT91_SDRAMC_TIMEOUT		(3 << 12)	/* Time to define when Low Power Mode is enabled */
+#define			AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES	(0 << 12)
+#define			AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES	(1 << 12)
+#define			AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES	(2 << 12)
+
+#define AT91_SDRAMC_IER		(AT91_SDRAMC + 0x14)	/* SDRAM Controller Interrupt Enable Register */
+#define AT91_SDRAMC_IDR		(AT91_SDRAMC + 0x18)	/* SDRAM Controller Interrupt Disable Register */
+#define AT91_SDRAMC_IMR		(AT91_SDRAMC + 0x1C)	/* SDRAM Controller Interrupt Mask Register */
+#define AT91_SDRAMC_ISR		(AT91_SDRAMC + 0x20)	/* SDRAM Controller Interrupt Status Register */
+#define		AT91_SDRAMC_RES		(1 << 0)		/* Refresh Error Status */
+
+#define AT91_SDRAMC_MDR		(AT91_SDRAMC + 0x24)	/* SDRAM Memory Device Register */
+#define		AT91_SDRAMC_MD		(3 << 0)		/* Memory Device Type */
+#define			AT91_SDRAMC_MD_SDRAM		0
+#define			AT91_SDRAMC_MD_LOW_POWER_SDRAM	1
+
+
+/* Static Memory Controller (SMC) registers */
+#define AT91_SMC_SETUP(n)	(AT91_SMC + 0x00 + ((n)*0x10))	/* Setup Register for CS n */
+#define		AT91_SMC_NWESETUP	(0x3f << 0)			/* NWE Setup Length */
+#define			AT91_SMC_NWESETUP_(x)	((x) << 0)
+#define		AT91_SMC_NCS_WRSETUP	(0x3f << 8)			/* NCS Setup Length in Write Access */
+#define			AT91_SMC_NCS_WRSETUP_(x)	((x) << 8)
+#define		AT91_SMC_NRDSETUP	(0x3f << 16)			/* NRD Setup Length */
+#define			AT91_SMC_NRDSETUP_(x)	((x) << 16)
+#define		AT91_SMC_NCS_RDSETUP	(0x3f << 24)			/* NCS Setup Length in Read Access */
+#define			AT91_SMC_NCS_RDSETUP_(x)	((x) << 24)
+
+#define AT91_SMC_PULSE(n)	(AT91_SMC + 0x04 + ((n)*0x10))	/* Pulse Register for CS n */
+#define		AT91_SMC_NWEPULSE	(0x7f <<  0)			/* NWE Pulse Length */
+#define			AT91_SMC_NWEPULSE_(x)	((x) << 0)
+#define		AT91_SMC_NCS_WRPULSE	(0x7f <<  8)			/* NCS Pulse Length in Write Access */
+#define			AT91_SMC_NCS_WRPULSE_(x)((x) << 8)
+#define		AT91_SMC_NRDPULSE	(0x7f << 16)			/* NRD Pulse Length */
+#define			AT91_SMC_NRDPULSE_(x)	((x) << 16)
+#define		AT91_SMC_NCS_RDPULSE	(0x7f << 24)			/* NCS Pulse Length in Read Access */
+#define			AT91_SMC_NCS_RDPULSE_(x)((x) << 24)
+
+#define AT91_SMC_CYCLE(n)	(AT91_SMC + 0x08 + ((n)*0x10))	/* Cycle Register for CS n */
+#define		AT91_SMC_NWECYCLE	(0x1ff << 0 )			/* Total Write Cycle Length */
+#define			AT91_SMC_NWECYCLE_(x)	((x) << 0)
+#define		AT91_SMC_NRDCYCLE	(0x1ff << 16)			/* Total Read Cycle Length */
+#define			AT91_SMC_NRDCYCLE_(x)	((x) << 16)
+
+#define AT91_SMC_MODE(n)	(AT91_SMC + 0x0c + ((n)*0x10))	/* Mode Register for CS n */
+#define		AT91_SMC_READMODE	(1 <<  0)			/* Read Mode */
+#define		AT91_SMC_WRITEMODE	(1 <<  1)			/* Write Mode */
+#define		AT91_SMC_EXNWMODE	(3 <<  4)			/* NWAIT Mode */
+#define			AT91_SMC_EXNWMODE_DISABLE	(0 << 4)
+#define			AT91_SMC_EXNWMODE_FROZEN	(2 << 4)
+#define			AT91_SMC_EXNWMODE_READY		(3 << 4)
+#define		AT91_SMC_BAT		(1 <<  8)			/* Byte Access Type */
+#define			AT91_SMC_BAT_SELECT		(0 << 8)
+#define			AT91_SMC_BAT_WRITE		(1 << 8)
+#define		AT91_SMC_DBW		(3 << 12)			/* Data Bus Width */
+#define			AT91_SMC_DBW_8			(0 << 12)
+#define			AT91_SMC_DBW_16			(1 << 12)
+#define			AT91_SMC_DBW_32			(2 << 12)
+#define		AT91_SMC_TDF		(0xf << 16)			/* Data Float Time. */
+#define			AT91_SMC_TDF_(x)		((x) << 16)
+#define		AT91_SMC_TDFMODE	(1 << 20)			/* TDF Optimization - Enabled */
+#define		AT91_SMC_PMEN		(1 << 24)			/* Page Mode Enabled */
+#define		AT91_SMC_PS		(3 << 28)			/* Page Size */
+#define			AT91_SMC_PS_4			(0 << 28)
+#define			AT91_SMC_PS_8			(1 << 28)
+#define			AT91_SMC_PS_16			(2 << 28)
+#define			AT91_SMC_PS_32			(3 << 28)
+
+#if defined(AT91_SMC1)		/* The AT91SAM9263 has 2 Static Memory contollers */
+#define AT91_SMC1_SETUP(n)	(AT91_SMC1 + 0x00 + ((n)*0x10))	/* Setup Register for CS n */
+#define AT91_SMC1_PULSE(n)	(AT91_SMC1 + 0x04 + ((n)*0x10))	/* Pulse Register for CS n */
+#define AT91_SMC1_CYCLE(n)	(AT91_SMC1 + 0x08 + ((n)*0x10))	/* Cycle Register for CS n */
+#define AT91_SMC1_MODE(n)	(AT91_SMC1 + 0x0c + ((n)*0x10))	/* Mode Register for CS n */
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h
new file mode 100644
index 0000000..7b9903c
--- /dev/null
+++ b/include/asm-arm/arch-at91/board.h
@@ -0,0 +1,122 @@
+/*
+ * include/asm-arm/arch-at91/board.h
+ *
+ *  Copyright (C) 2005 HP Labs
+ *
+ * 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
+ */
+
+/*
+ * These are data structures found in platform_device.dev.platform_data,
+ * and describing board-specific data needed by drivers.  For example,
+ * which pin is used for a given GPIO role.
+ *
+ * In 2.6, drivers should strongly avoid board-specific knowledge so
+ * that supporting new boards normally won't require driver patches.
+ * Most board-specific knowledge should be in arch/.../board-*.c files.
+ */
+
+#ifndef __ASM_ARCH_BOARD_H
+#define __ASM_ARCH_BOARD_H
+
+#include <linux/mtd/partitions.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+ /* USB Device */
+struct at91_udc_data {
+	u8	vbus_pin;		/* high == host powering us */
+	u8	pullup_pin;		/* high == D+ pulled up */
+};
+extern void __init at91_add_device_udc(struct at91_udc_data *data);
+
+ /* Compact Flash */
+struct at91_cf_data {
+	u8	irq_pin;		/* I/O IRQ */
+	u8	det_pin;		/* Card detect */
+	u8	vcc_pin;		/* power switching */
+	u8	rst_pin;		/* card reset */
+	u8	chipselect;		/* EBI Chip Select number */
+};
+extern void __init at91_add_device_cf(struct at91_cf_data *data);
+
+ /* MMC / SD */
+struct at91_mmc_data {
+	u8		det_pin;	/* card detect IRQ */
+	unsigned	slot_b:1;	/* uses Slot B */
+	unsigned	wire4:1;	/* (SD) supports DAT0..DAT3 */
+	u8		wp_pin;		/* (SD) writeprotect detect */
+	u8		vcc_pin;	/* power switching (high == on) */
+};
+extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data);
+
+ /* Ethernet */
+struct at91_eth_data {
+	u8		phy_irq_pin;	/* PHY IRQ */
+	u8		is_rmii;	/* using RMII interface? */
+};
+extern void __init at91_add_device_eth(struct at91_eth_data *data);
+
+#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263)
+#define eth_platform_data	at91_eth_data
+#endif
+
+ /* USB Host */
+struct at91_usbh_data {
+	u8		ports;		/* number of ports on root hub */
+	u8		vbus_pin[];	/* port power-control pin */
+};
+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 */
+	u8		bus_width_16;	/* buswidth is 16 bit */
+	struct mtd_partition* (*partition_info)(int, int*);
+};
+extern void __init at91_add_device_nand(struct at91_nand_data *data);
+
+ /* I2C*/
+extern void __init at91_add_device_i2c(void);
+
+ /* SPI */
+extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices);
+
+ /* Serial */
+struct at91_uart_config {
+	unsigned short	console_tty;	/* tty number of serial console */
+	unsigned short	nr_tty;		/* number of serial tty's */
+	short		tty_map[];	/* map UART to tty number */
+};
+extern struct platform_device *atmel_default_console_device;
+extern void __init at91_init_serial(struct at91_uart_config *config);
+
+struct atmel_uart_data {
+	short		use_dma_tx;	/* use transmit DMA? */
+	short		use_dma_rx;	/* use receive DMA? */
+	void __iomem	*regs;		/* virtual base address, if any */
+};
+extern void __init at91_add_device_serial(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-at91/cpu.h b/include/asm-arm/arch-at91/cpu.h
new file mode 100644
index 0000000..d464ca5
--- /dev/null
+++ b/include/asm-arm/arch-at91/cpu.h
@@ -0,0 +1,71 @@
+/*
+ * include/asm-arm/arch-at91/cpu.h
+ *
+ *  Copyright (C) 2006 SAN People
+ *
+ * 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 __ASM_ARCH_CPU_H
+#define __ASM_ARCH_CPU_H
+
+#include <asm/hardware.h>
+#include <asm/arch/at91_dbgu.h>
+
+
+#define ARCH_ID_AT91RM9200	0x09290780
+#define ARCH_ID_AT91SAM9260	0x019803a0
+#define ARCH_ID_AT91SAM9261	0x019703a0
+#define ARCH_ID_AT91SAM9263	0x019607a0
+
+#define ARCH_ID_AT91SAM9XE128	0x329973a0
+#define ARCH_ID_AT91SAM9XE256	0x329a93a0
+#define ARCH_ID_AT91SAM9XE512	0x329aa3a0
+
+static inline unsigned long at91_cpu_identify(void)
+{
+	return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
+}
+
+
+#define ARCH_FAMILY_AT91X92	0x09200000
+#define ARCH_FAMILY_AT91SAM9	0x01900000
+#define ARCH_FAMILY_AT91SAM9XE	0x02900000
+
+static inline unsigned long at91_arch_identify(void)
+{
+	return (at91_sys_read(AT91_DBGU_CIDR) & AT91_CIDR_ARCH);
+}
+
+
+#ifdef CONFIG_ARCH_AT91RM9200
+#define cpu_is_at91rm9200()	(at91_cpu_identify() == ARCH_ID_AT91RM9200)
+#else
+#define cpu_is_at91rm9200()	(0)
+#endif
+
+#ifdef CONFIG_ARCH_AT91SAM9260
+#define cpu_is_at91sam9xe()	(at91_arch_identify() == ARCH_FAMILY_AT91SAM9XE)
+#define cpu_is_at91sam9260()	((at91_cpu_identify() == ARCH_ID_AT91SAM9260) || cpu_is_at91sam9xe())
+#else
+#define cpu_is_at91sam9xe()	(0)
+#define cpu_is_at91sam9260()	(0)
+#endif
+
+#ifdef CONFIG_ARCH_AT91SAM9261
+#define cpu_is_at91sam9261()	(at91_cpu_identify() == ARCH_ID_AT91SAM9261)
+#else
+#define cpu_is_at91sam9261()	(0)
+#endif
+
+#ifdef CONFIG_ARCH_AT91SAM9263
+#define cpu_is_at91sam9263()	(at91_cpu_identify() == ARCH_ID_AT91SAM9263)
+#else
+#define cpu_is_at91sam9263()	(0)
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91/debug-macro.S b/include/asm-arm/arch-at91/debug-macro.S
new file mode 100644
index 0000000..13e9f5e
--- /dev/null
+++ b/include/asm-arm/arch-at91/debug-macro.S
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-at91/debug-macro.S
+ *
+ *  Copyright (C) 2003-2005 SAN People
+ *
+ * Debugging macro include header
+ *
+ * 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 <asm/hardware.h>
+#include <asm/arch/at91_dbgu.h>
+
+	.macro	addruart,rx
+	mrc	p15, 0, \rx, c1, c0
+	tst	\rx, #1						@ MMU enabled?
+	ldreq	\rx, =(AT91_BASE_SYS + AT91_DBGU)		@ System peripherals (phys address)
+	ldrne	\rx, =(AT91_VA_BASE_SYS	+ AT91_DBGU)		@ System peripherals (virt address)
+	.endm
+
+	.macro	senduart,rd,rx
+	strb	\rd, [\rx, #(AT91_DBGU_THR - AT91_DBGU)]	@ Write to Transmitter Holding Register
+	.endm
+
+	.macro	waituart,rd,rx
+1001:	ldr	\rd, [\rx, #(AT91_DBGU_SR - AT91_DBGU)]		@ Read Status Register
+	tst	\rd, #AT91_DBGU_TXRDY				@ DBGU_TXRDY = 1 when ready to transmit
+	beq	1001b
+	.endm
+
+	.macro	busyuart,rd,rx
+1001:	ldr	\rd, [\rx, #(AT91_DBGU_SR - AT91_DBGU)]		@ Read Status Register
+	tst	\rd, #AT91_DBGU_TXEMPTY				@ DBGU_TXEMPTY = 1 when transmission complete
+	beq	1001b
+	.endm
+
diff --git a/include/asm-arm/arch-at91/dma.h b/include/asm-arm/arch-at91/dma.h
new file mode 100644
index 0000000..7745654
--- /dev/null
+++ b/include/asm-arm/arch-at91/dma.h
@@ -0,0 +1,19 @@
+/*
+ * include/asm-arm/arch-at91/dma.h
+ *
+ *  Copyright (C) 2003 SAN People
+ *
+ * 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
+ */
diff --git a/include/asm-arm/arch-at91/entry-macro.S b/include/asm-arm/arch-at91/entry-macro.S
new file mode 100644
index 0000000..cc1d850
--- /dev/null
+++ b/include/asm-arm/arch-at91/entry-macro.S
@@ -0,0 +1,32 @@
+/*
+ * include/asm-arm/arch-at91/entry-macro.S
+ *
+ *  Copyright (C) 2003-2005 SAN People
+ *
+ * Low-level IRQ helper macros for AT91RM9200 platforms
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/hardware.h>
+#include <asm/arch/at91_aic.h>
+
+	.macro	disable_fiq
+	.endm
+
+	.macro  get_irqnr_preamble, base, tmp
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr	\base, =(AT91_VA_BASE_SYS + AT91_AIC)		@ base virtual address of AIC peripheral
+	ldr	\irqnr, [\base, #(AT91_AIC_IVR - AT91_AIC)]	@ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
+	ldr	\irqstat, [\base, #(AT91_AIC_ISR - AT91_AIC)]	@ read interrupt source number
+	teq	\irqstat, #0					@ ISR is 0 when no current interrupt, or spurious interrupt
+	streq	\tmp, [\base, #(AT91_AIC_EOICR - AT91_AIC)]	@ not going to be handled further, then ACK it now.
+	.endm
+
diff --git a/include/asm-arm/arch-at91/gpio.h b/include/asm-arm/arch-at91/gpio.h
new file mode 100644
index 0000000..98ad211
--- /dev/null
+++ b/include/asm-arm/arch-at91/gpio.h
@@ -0,0 +1,252 @@
+/*
+ * include/asm-arm/arch-at91/gpio.h
+ *
+ *  Copyright (C) 2005 HP Labs
+ *
+ * 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 __ASM_ARCH_AT91RM9200_GPIO_H
+#define __ASM_ARCH_AT91RM9200_GPIO_H
+
+#include <asm/irq.h>
+
+#define PIN_BASE		NR_AIC_IRQS
+
+#define MAX_GPIO_BANKS		5
+
+/* these pin numbers double as IRQ numbers, like AT91xxx_ID_* values */
+
+#define	AT91_PIN_PA0	(PIN_BASE + 0x00 + 0)
+#define	AT91_PIN_PA1	(PIN_BASE + 0x00 + 1)
+#define	AT91_PIN_PA2	(PIN_BASE + 0x00 + 2)
+#define	AT91_PIN_PA3	(PIN_BASE + 0x00 + 3)
+#define	AT91_PIN_PA4	(PIN_BASE + 0x00 + 4)
+#define	AT91_PIN_PA5	(PIN_BASE + 0x00 + 5)
+#define	AT91_PIN_PA6	(PIN_BASE + 0x00 + 6)
+#define	AT91_PIN_PA7	(PIN_BASE + 0x00 + 7)
+#define	AT91_PIN_PA8	(PIN_BASE + 0x00 + 8)
+#define	AT91_PIN_PA9	(PIN_BASE + 0x00 + 9)
+#define	AT91_PIN_PA10	(PIN_BASE + 0x00 + 10)
+#define	AT91_PIN_PA11	(PIN_BASE + 0x00 + 11)
+#define	AT91_PIN_PA12	(PIN_BASE + 0x00 + 12)
+#define	AT91_PIN_PA13	(PIN_BASE + 0x00 + 13)
+#define	AT91_PIN_PA14	(PIN_BASE + 0x00 + 14)
+#define	AT91_PIN_PA15	(PIN_BASE + 0x00 + 15)
+#define	AT91_PIN_PA16	(PIN_BASE + 0x00 + 16)
+#define	AT91_PIN_PA17	(PIN_BASE + 0x00 + 17)
+#define	AT91_PIN_PA18	(PIN_BASE + 0x00 + 18)
+#define	AT91_PIN_PA19	(PIN_BASE + 0x00 + 19)
+#define	AT91_PIN_PA20	(PIN_BASE + 0x00 + 20)
+#define	AT91_PIN_PA21	(PIN_BASE + 0x00 + 21)
+#define	AT91_PIN_PA22	(PIN_BASE + 0x00 + 22)
+#define	AT91_PIN_PA23	(PIN_BASE + 0x00 + 23)
+#define	AT91_PIN_PA24	(PIN_BASE + 0x00 + 24)
+#define	AT91_PIN_PA25	(PIN_BASE + 0x00 + 25)
+#define	AT91_PIN_PA26	(PIN_BASE + 0x00 + 26)
+#define	AT91_PIN_PA27	(PIN_BASE + 0x00 + 27)
+#define	AT91_PIN_PA28	(PIN_BASE + 0x00 + 28)
+#define	AT91_PIN_PA29	(PIN_BASE + 0x00 + 29)
+#define	AT91_PIN_PA30	(PIN_BASE + 0x00 + 30)
+#define	AT91_PIN_PA31	(PIN_BASE + 0x00 + 31)
+
+#define	AT91_PIN_PB0	(PIN_BASE + 0x20 + 0)
+#define	AT91_PIN_PB1	(PIN_BASE + 0x20 + 1)
+#define	AT91_PIN_PB2	(PIN_BASE + 0x20 + 2)
+#define	AT91_PIN_PB3	(PIN_BASE + 0x20 + 3)
+#define	AT91_PIN_PB4	(PIN_BASE + 0x20 + 4)
+#define	AT91_PIN_PB5	(PIN_BASE + 0x20 + 5)
+#define	AT91_PIN_PB6	(PIN_BASE + 0x20 + 6)
+#define	AT91_PIN_PB7	(PIN_BASE + 0x20 + 7)
+#define	AT91_PIN_PB8	(PIN_BASE + 0x20 + 8)
+#define	AT91_PIN_PB9	(PIN_BASE + 0x20 + 9)
+#define	AT91_PIN_PB10	(PIN_BASE + 0x20 + 10)
+#define	AT91_PIN_PB11	(PIN_BASE + 0x20 + 11)
+#define	AT91_PIN_PB12	(PIN_BASE + 0x20 + 12)
+#define	AT91_PIN_PB13	(PIN_BASE + 0x20 + 13)
+#define	AT91_PIN_PB14	(PIN_BASE + 0x20 + 14)
+#define	AT91_PIN_PB15	(PIN_BASE + 0x20 + 15)
+#define	AT91_PIN_PB16	(PIN_BASE + 0x20 + 16)
+#define	AT91_PIN_PB17	(PIN_BASE + 0x20 + 17)
+#define	AT91_PIN_PB18	(PIN_BASE + 0x20 + 18)
+#define	AT91_PIN_PB19	(PIN_BASE + 0x20 + 19)
+#define	AT91_PIN_PB20	(PIN_BASE + 0x20 + 20)
+#define	AT91_PIN_PB21	(PIN_BASE + 0x20 + 21)
+#define	AT91_PIN_PB22	(PIN_BASE + 0x20 + 22)
+#define	AT91_PIN_PB23	(PIN_BASE + 0x20 + 23)
+#define	AT91_PIN_PB24	(PIN_BASE + 0x20 + 24)
+#define	AT91_PIN_PB25	(PIN_BASE + 0x20 + 25)
+#define	AT91_PIN_PB26	(PIN_BASE + 0x20 + 26)
+#define	AT91_PIN_PB27	(PIN_BASE + 0x20 + 27)
+#define	AT91_PIN_PB28	(PIN_BASE + 0x20 + 28)
+#define	AT91_PIN_PB29	(PIN_BASE + 0x20 + 29)
+#define	AT91_PIN_PB30	(PIN_BASE + 0x20 + 30)
+#define	AT91_PIN_PB31	(PIN_BASE + 0x20 + 31)
+
+#define	AT91_PIN_PC0	(PIN_BASE + 0x40 + 0)
+#define	AT91_PIN_PC1	(PIN_BASE + 0x40 + 1)
+#define	AT91_PIN_PC2	(PIN_BASE + 0x40 + 2)
+#define	AT91_PIN_PC3	(PIN_BASE + 0x40 + 3)
+#define	AT91_PIN_PC4	(PIN_BASE + 0x40 + 4)
+#define	AT91_PIN_PC5	(PIN_BASE + 0x40 + 5)
+#define	AT91_PIN_PC6	(PIN_BASE + 0x40 + 6)
+#define	AT91_PIN_PC7	(PIN_BASE + 0x40 + 7)
+#define	AT91_PIN_PC8	(PIN_BASE + 0x40 + 8)
+#define	AT91_PIN_PC9	(PIN_BASE + 0x40 + 9)
+#define	AT91_PIN_PC10	(PIN_BASE + 0x40 + 10)
+#define	AT91_PIN_PC11	(PIN_BASE + 0x40 + 11)
+#define	AT91_PIN_PC12	(PIN_BASE + 0x40 + 12)
+#define	AT91_PIN_PC13	(PIN_BASE + 0x40 + 13)
+#define	AT91_PIN_PC14	(PIN_BASE + 0x40 + 14)
+#define	AT91_PIN_PC15	(PIN_BASE + 0x40 + 15)
+#define	AT91_PIN_PC16	(PIN_BASE + 0x40 + 16)
+#define	AT91_PIN_PC17	(PIN_BASE + 0x40 + 17)
+#define	AT91_PIN_PC18	(PIN_BASE + 0x40 + 18)
+#define	AT91_PIN_PC19	(PIN_BASE + 0x40 + 19)
+#define	AT91_PIN_PC20	(PIN_BASE + 0x40 + 20)
+#define	AT91_PIN_PC21	(PIN_BASE + 0x40 + 21)
+#define	AT91_PIN_PC22	(PIN_BASE + 0x40 + 22)
+#define	AT91_PIN_PC23	(PIN_BASE + 0x40 + 23)
+#define	AT91_PIN_PC24	(PIN_BASE + 0x40 + 24)
+#define	AT91_PIN_PC25	(PIN_BASE + 0x40 + 25)
+#define	AT91_PIN_PC26	(PIN_BASE + 0x40 + 26)
+#define	AT91_PIN_PC27	(PIN_BASE + 0x40 + 27)
+#define	AT91_PIN_PC28	(PIN_BASE + 0x40 + 28)
+#define	AT91_PIN_PC29	(PIN_BASE + 0x40 + 29)
+#define	AT91_PIN_PC30	(PIN_BASE + 0x40 + 30)
+#define	AT91_PIN_PC31	(PIN_BASE + 0x40 + 31)
+
+#define	AT91_PIN_PD0	(PIN_BASE + 0x60 + 0)
+#define	AT91_PIN_PD1	(PIN_BASE + 0x60 + 1)
+#define	AT91_PIN_PD2	(PIN_BASE + 0x60 + 2)
+#define	AT91_PIN_PD3	(PIN_BASE + 0x60 + 3)
+#define	AT91_PIN_PD4	(PIN_BASE + 0x60 + 4)
+#define	AT91_PIN_PD5	(PIN_BASE + 0x60 + 5)
+#define	AT91_PIN_PD6	(PIN_BASE + 0x60 + 6)
+#define	AT91_PIN_PD7	(PIN_BASE + 0x60 + 7)
+#define	AT91_PIN_PD8	(PIN_BASE + 0x60 + 8)
+#define	AT91_PIN_PD9	(PIN_BASE + 0x60 + 9)
+#define	AT91_PIN_PD10	(PIN_BASE + 0x60 + 10)
+#define	AT91_PIN_PD11	(PIN_BASE + 0x60 + 11)
+#define	AT91_PIN_PD12	(PIN_BASE + 0x60 + 12)
+#define	AT91_PIN_PD13	(PIN_BASE + 0x60 + 13)
+#define	AT91_PIN_PD14	(PIN_BASE + 0x60 + 14)
+#define	AT91_PIN_PD15	(PIN_BASE + 0x60 + 15)
+#define	AT91_PIN_PD16	(PIN_BASE + 0x60 + 16)
+#define	AT91_PIN_PD17	(PIN_BASE + 0x60 + 17)
+#define	AT91_PIN_PD18	(PIN_BASE + 0x60 + 18)
+#define	AT91_PIN_PD19	(PIN_BASE + 0x60 + 19)
+#define	AT91_PIN_PD20	(PIN_BASE + 0x60 + 20)
+#define	AT91_PIN_PD21	(PIN_BASE + 0x60 + 21)
+#define	AT91_PIN_PD22	(PIN_BASE + 0x60 + 22)
+#define	AT91_PIN_PD23	(PIN_BASE + 0x60 + 23)
+#define	AT91_PIN_PD24	(PIN_BASE + 0x60 + 24)
+#define	AT91_PIN_PD25	(PIN_BASE + 0x60 + 25)
+#define	AT91_PIN_PD26	(PIN_BASE + 0x60 + 26)
+#define	AT91_PIN_PD27	(PIN_BASE + 0x60 + 27)
+#define	AT91_PIN_PD28	(PIN_BASE + 0x60 + 28)
+#define	AT91_PIN_PD29	(PIN_BASE + 0x60 + 29)
+#define	AT91_PIN_PD30	(PIN_BASE + 0x60 + 30)
+#define	AT91_PIN_PD31	(PIN_BASE + 0x60 + 31)
+
+#define	AT91_PIN_PE0	(PIN_BASE + 0x80 + 0)
+#define	AT91_PIN_PE1	(PIN_BASE + 0x80 + 1)
+#define	AT91_PIN_PE2	(PIN_BASE + 0x80 + 2)
+#define	AT91_PIN_PE3	(PIN_BASE + 0x80 + 3)
+#define	AT91_PIN_PE4	(PIN_BASE + 0x80 + 4)
+#define	AT91_PIN_PE5	(PIN_BASE + 0x80 + 5)
+#define	AT91_PIN_PE6	(PIN_BASE + 0x80 + 6)
+#define	AT91_PIN_PE7	(PIN_BASE + 0x80 + 7)
+#define	AT91_PIN_PE8	(PIN_BASE + 0x80 + 8)
+#define	AT91_PIN_PE9	(PIN_BASE + 0x80 + 9)
+#define	AT91_PIN_PE10	(PIN_BASE + 0x80 + 10)
+#define	AT91_PIN_PE11	(PIN_BASE + 0x80 + 11)
+#define	AT91_PIN_PE12	(PIN_BASE + 0x80 + 12)
+#define	AT91_PIN_PE13	(PIN_BASE + 0x80 + 13)
+#define	AT91_PIN_PE14	(PIN_BASE + 0x80 + 14)
+#define	AT91_PIN_PE15	(PIN_BASE + 0x80 + 15)
+#define	AT91_PIN_PE16	(PIN_BASE + 0x80 + 16)
+#define	AT91_PIN_PE17	(PIN_BASE + 0x80 + 17)
+#define	AT91_PIN_PE18	(PIN_BASE + 0x80 + 18)
+#define	AT91_PIN_PE19	(PIN_BASE + 0x80 + 19)
+#define	AT91_PIN_PE20	(PIN_BASE + 0x80 + 20)
+#define	AT91_PIN_PE21	(PIN_BASE + 0x80 + 21)
+#define	AT91_PIN_PE22	(PIN_BASE + 0x80 + 22)
+#define	AT91_PIN_PE23	(PIN_BASE + 0x80 + 23)
+#define	AT91_PIN_PE24	(PIN_BASE + 0x80 + 24)
+#define	AT91_PIN_PE25	(PIN_BASE + 0x80 + 25)
+#define	AT91_PIN_PE26	(PIN_BASE + 0x80 + 26)
+#define	AT91_PIN_PE27	(PIN_BASE + 0x80 + 27)
+#define	AT91_PIN_PE28	(PIN_BASE + 0x80 + 28)
+#define	AT91_PIN_PE29	(PIN_BASE + 0x80 + 29)
+#define	AT91_PIN_PE30	(PIN_BASE + 0x80 + 30)
+#define	AT91_PIN_PE31	(PIN_BASE + 0x80 + 31)
+
+#ifndef __ASSEMBLY__
+/* setup setup routines, called from board init or driver probe() */
+extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup);
+extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup);
+extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup);
+extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup);
+extern int __init_or_module at91_set_gpio_output(unsigned pin, int value);
+extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on);
+extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on);
+
+/* callable at any time */
+extern int at91_set_gpio_value(unsigned pin, int value);
+extern int at91_get_gpio_value(unsigned pin);
+
+/* callable only from core power-management code */
+extern void at91_gpio_suspend(void);
+extern void at91_gpio_resume(void);
+
+/*-------------------------------------------------------------------------*/
+
+/* wrappers for "new style" GPIO calls. the old AT91-specfic ones should
+ * eventually be removed (along with this errno.h inclusion), and the
+ * gpio request/free calls should probably be implemented.
+ */
+
+#include <asm/errno.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+}
+
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio);
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return at91_get_gpio_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	at91_set_gpio_value(gpio, value);
+}
+
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return irq;
+}
+
+#endif	/* __ASSEMBLY__ */
+
+#endif
diff --git a/include/asm-arm/arch-at91/hardware.h b/include/asm-arm/arch-at91/hardware.h
new file mode 100644
index 0000000..eaaf1c1
--- /dev/null
+++ b/include/asm-arm/arch-at91/hardware.h
@@ -0,0 +1,90 @@
+/*
+ * include/asm-arm/arch-at91/hardware.h
+ *
+ *  Copyright (C) 2003 SAN People
+ *  Copyright (C) 2003 ATMEL
+ *
+ * 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 __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+
+#if defined(CONFIG_ARCH_AT91RM9200)
+#include <asm/arch/at91rm9200.h>
+#elif defined(CONFIG_ARCH_AT91SAM9260)
+#include <asm/arch/at91sam9260.h>
+#elif defined(CONFIG_ARCH_AT91SAM9261)
+#include <asm/arch/at91sam9261.h>
+#elif defined(CONFIG_ARCH_AT91SAM9263)
+#include <asm/arch/at91sam9263.h>
+#else
+#error "Unsupported AT91 processor"
+#endif
+
+
+/*
+ * Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF
+ * to 0xFEF78000 .. 0xFF000000.  (5444Kb)
+ */
+#define AT91_IO_PHYS_BASE	0xFFF78000
+#define AT91_IO_SIZE		(0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
+#define AT91_IO_VIRT_BASE	(0xFF000000 - AT91_IO_SIZE)
+
+ /* Convert a physical IO address to virtual IO address */
+#define AT91_IO_P2V(x)		((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
+
+/*
+ * Virtual to Physical Address mapping for IO devices.
+ */
+#define AT91_VA_BASE_SYS	AT91_IO_P2V(AT91_BASE_SYS)
+#define AT91_VA_BASE_EMAC	AT91_IO_P2V(AT91RM9200_BASE_EMAC)
+
+ /* Internal SRAM is mapped below the IO devices */
+#define AT91_SRAM_MAX		SZ_1M
+#define AT91_VIRT_BASE		(AT91_IO_VIRT_BASE - AT91_SRAM_MAX)
+
+/* Serial ports */
+#define ATMEL_MAX_UART		7		/* 6 USART3's and one DBGU port (SAM9260) */
+
+/* External Memory Map */
+#define AT91_CHIPSELECT_0	0x10000000
+#define AT91_CHIPSELECT_1	0x20000000
+#define AT91_CHIPSELECT_2	0x30000000
+#define AT91_CHIPSELECT_3	0x40000000
+#define AT91_CHIPSELECT_4	0x50000000
+#define AT91_CHIPSELECT_5	0x60000000
+#define AT91_CHIPSELECT_6	0x70000000
+#define AT91_CHIPSELECT_7	0x80000000
+
+/* SDRAM */
+#define AT91_SDRAM_BASE		AT91_CHIPSELECT_1
+
+/* Clocks */
+#define AT91_SLOW_CLOCK		32768		/* slow clock */
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+static inline unsigned int at91_sys_read(unsigned int reg_offset)
+{
+	void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS;
+
+	return __raw_readl(addr + reg_offset);
+}
+
+static inline void at91_sys_write(unsigned int reg_offset, unsigned long value)
+{
+	void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS;
+
+	__raw_writel(value, addr + reg_offset);
+}
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91/io.h b/include/asm-arm/arch-at91/io.h
new file mode 100644
index 0000000..401f327
--- /dev/null
+++ b/include/asm-arm/arch-at91/io.h
@@ -0,0 +1,32 @@
+/*
+ * include/asm-arm/arch-at91/io.h
+ *
+ *  Copyright (C) 2003 SAN People
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_IO_H
+#define __ASM_ARCH_IO_H
+
+#include <asm/io.h>
+
+#define IO_SPACE_LIMIT		0xFFFFFFFF
+
+#define __io(a)			((void __iomem *)(a))
+#define __mem_pci(a)		(a)
+
+
+#endif
diff --git a/include/asm-arm/arch-at91/irqs.h b/include/asm-arm/arch-at91/irqs.h
new file mode 100644
index 0000000..1ffa3bb
--- /dev/null
+++ b/include/asm-arm/arch-at91/irqs.h
@@ -0,0 +1,44 @@
+/*
+ * include/asm-arm/arch-at91/irqs.h
+ *
+ *  Copyright (C) 2004 SAN People
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#include <asm/arch/at91_aic.h>
+
+#define NR_AIC_IRQS 32
+
+
+/*
+ * Acknowledge interrupt with AIC after interrupt has been handled.
+ *   (by kernel/irq.c)
+ */
+#define irq_finish(irq) do { at91_sys_write(AT91_AIC_EOICR, 0); } while (0)
+
+
+/*
+ * IRQ interrupt symbols are the AT91xxx_ID_* symbols
+ * for IRQs handled directly through the AIC, or else the AT91_PIN_*
+ * symbols in gpio.h for ones handled indirectly as GPIOs.
+ * We make provision for 5 banks of GPIO.
+ */
+#define	NR_IRQS		(NR_AIC_IRQS + (5 * 32))
+
+#endif
diff --git a/include/asm-arm/arch-at91/memory.h b/include/asm-arm/arch-at91/memory.h
new file mode 100644
index 0000000..4835d67
--- /dev/null
+++ b/include/asm-arm/arch-at91/memory.h
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-at91/memory.h
+ *
+ *  Copyright (C) 2004 SAN People
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#include <asm/hardware.h>
+
+#define PHYS_OFFSET	(AT91_SDRAM_BASE)
+
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *              address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *              to an address that the kernel can use.
+ */
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#endif
diff --git a/include/asm-arm/arch-at91/system.h b/include/asm-arm/arch-at91/system.h
new file mode 100644
index 0000000..6bf8460
--- /dev/null
+++ b/include/asm-arm/arch-at91/system.h
@@ -0,0 +1,53 @@
+/*
+ * include/asm-arm/arch-at91/system.h
+ *
+ *  Copyright (C) 2003 SAN People
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/hardware.h>
+#include <asm/arch/at91_st.h>
+#include <asm/arch/at91_dbgu.h>
+
+static inline void arch_idle(void)
+{
+	/*
+	 * Disable the processor clock.  The processor will be automatically
+	 * re-enabled by an interrupt or by a reset.
+	 */
+//	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+
+	/*
+	 * Set the processor (CP15) into 'Wait for Interrupt' mode.
+	 * Unlike disabling the processor clock via the PMC (above)
+	 *  this allows the processor to be woken via JTAG.
+	 */
+	cpu_do_idle();
+}
+
+void (*at91_arch_reset)(void);
+
+static inline void arch_reset(char mode)
+{
+	/* call the CPU-specific reset function */
+	if (at91_arch_reset)
+		(at91_arch_reset)();
+}
+
+#endif
diff --git a/include/asm-arm/arch-at91/timex.h b/include/asm-arm/arch-at91/timex.h
new file mode 100644
index 0000000..f41636d
--- /dev/null
+++ b/include/asm-arm/arch-at91/timex.h
@@ -0,0 +1,42 @@
+/*
+ * include/asm-arm/arch-at91/timex.h
+ *
+ *  Copyright (C) 2003 SAN People
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+#include <asm/hardware.h>
+
+#if defined(CONFIG_ARCH_AT91RM9200)
+
+#define CLOCK_TICK_RATE		(AT91_SLOW_CLOCK)
+
+#elif defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9261)
+
+#define AT91SAM9_MASTER_CLOCK	99300000
+#define CLOCK_TICK_RATE		(AT91SAM9_MASTER_CLOCK/16)
+
+#elif defined(CONFIG_ARCH_AT91SAM9263)
+
+#define AT91SAM9_MASTER_CLOCK	99959500
+#define CLOCK_TICK_RATE		(AT91SAM9_MASTER_CLOCK/16)
+
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91/uncompress.h b/include/asm-arm/arch-at91/uncompress.h
new file mode 100644
index 0000000..a193d28
--- /dev/null
+++ b/include/asm-arm/arch-at91/uncompress.h
@@ -0,0 +1,56 @@
+/*
+ * include/asm-arm/arch-at91/uncompress.h
+ *
+ *  Copyright (C) 2003 SAN People
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <asm/hardware.h>
+#include <asm/arch/at91_dbgu.h>
+
+/*
+ * The following code assumes the serial port has already been
+ * initialized by the bootloader.  If you didn't setup a port in
+ * your bootloader then nothing will appear (which might be desired).
+ *
+ * This does not append a newline
+ */
+static void putc(int c)
+{
+	void __iomem *sys = (void __iomem *) AT91_BASE_SYS;	/* physical address */
+
+	while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY))
+		barrier();
+	__raw_writel(c, sys + AT91_DBGU_THR);
+}
+
+static inline void flush(void)
+{
+	void __iomem *sys = (void __iomem *) AT91_BASE_SYS;	/* physical address */
+
+	/* wait for transmission to complete */
+	while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY))
+		barrier();
+}
+
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
+
+#endif
diff --git a/include/asm-arm/arch-at91/vmalloc.h b/include/asm-arm/arch-at91/vmalloc.h
new file mode 100644
index 0000000..bb05e70
--- /dev/null
+++ b/include/asm-arm/arch-at91/vmalloc.h
@@ -0,0 +1,26 @@
+/*
+ * include/asm-arm/arch-at91/vmalloc.h
+ *
+ *  Copyright (C) 2003 SAN People
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END		(AT91_VIRT_BASE & PGDIR_MASK)
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_aic.h b/include/asm-arm/arch-at91rm9200/at91_aic.h
deleted file mode 100644
index 267e698..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_aic.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_aic.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Advanced Interrupt Controller (AIC) - System peripherals 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 AT91_AIC_H
-#define AT91_AIC_H
-
-#define AT91_AIC_SMR(n)		(AT91_AIC + ((n) * 4))	/* Source Mode Registers 0-31 */
-#define		AT91_AIC_PRIOR		(7 << 0)		/* Priority Level */
-#define		AT91_AIC_SRCTYPE	(3 << 5)		/* Interrupt Source Type */
-#define			AT91_AIC_SRCTYPE_LOW		(0 << 5)
-#define			AT91_AIC_SRCTYPE_FALLING	(1 << 5)
-#define			AT91_AIC_SRCTYPE_HIGH		(2 << 5)
-#define			AT91_AIC_SRCTYPE_RISING		(3 << 5)
-
-#define AT91_AIC_SVR(n)		(AT91_AIC + 0x80 + ((n) * 4))	/* Source Vector Registers 0-31 */
-#define AT91_AIC_IVR		(AT91_AIC + 0x100)	/* Interrupt Vector Register */
-#define AT91_AIC_FVR		(AT91_AIC + 0x104)	/* Fast Interrupt Vector Register */
-#define AT91_AIC_ISR		(AT91_AIC + 0x108)	/* Interrupt Status Register */
-#define		AT91_AIC_IRQID		(0x1f << 0)		/* Current Interrupt Identifier */
-
-#define AT91_AIC_IPR		(AT91_AIC + 0x10c)	/* Interrupt Pending Register */
-#define AT91_AIC_IMR		(AT91_AIC + 0x110)	/* Interrupt Mask Register */
-#define AT91_AIC_CISR		(AT91_AIC + 0x114)	/* Core Interrupt Status Register */
-#define		AT91_AIC_NFIQ		(1 << 0)		/* nFIQ Status */
-#define		AT91_AIC_NIRQ		(1 << 1)		/* nIRQ Status */
-
-#define AT91_AIC_IECR		(AT91_AIC + 0x120)	/* Interrupt Enable Command Register */
-#define AT91_AIC_IDCR		(AT91_AIC + 0x124)	/* Interrupt Disable Command Register */
-#define AT91_AIC_ICCR		(AT91_AIC + 0x128)	/* Interrupt Clear Command Register */
-#define AT91_AIC_ISCR		(AT91_AIC + 0x12c)	/* Interrupt Set Command Register */
-#define AT91_AIC_EOICR		(AT91_AIC + 0x130)	/* End of Interrupt Command Register */
-#define AT91_AIC_SPU		(AT91_AIC + 0x134)	/* Spurious Interrupt Vector Register */
-#define AT91_AIC_DCR		(AT91_AIC + 0x138)	/* Debug Control Register */
-#define		AT91_AIC_DCR_PROT	(1 << 0)		/* Protection Mode */
-#define		AT91_AIC_DCR_GMSK	(1 << 1)		/* General Mask */
-
-#define AT91_AIC_FFER		(AT91_AIC + 0x140)	/* Fast Forcing Enable Register [SAM9 only] */
-#define AT91_AIC_FFDR		(AT91_AIC + 0x144)	/* Fast Forcing Disable Register [SAM9 only] */
-#define AT91_AIC_FFSR		(AT91_AIC + 0x148)	/* Fast Forcing Status Register [SAM9 only] */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_dbgu.h b/include/asm-arm/arch-at91rm9200/at91_dbgu.h
deleted file mode 100644
index e4b8b27..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_dbgu.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_dbgu.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Debug Unit (DBGU) - System peripherals 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 AT91_DBGU_H
-#define AT91_DBGU_H
-
-#define AT91_DBGU_CR		(AT91_DBGU + 0x00)	/* Control Register */
-#define AT91_DBGU_MR		(AT91_DBGU + 0x04)	/* Mode Register */
-#define AT91_DBGU_IER		(AT91_DBGU + 0x08)	/* Interrupt Enable Register */
-#define		AT91_DBGU_TXRDY		(1 << 1)		/* Transmitter Ready */
-#define		AT91_DBGU_TXEMPTY	(1 << 9)		/* Transmitter Empty */
-#define AT91_DBGU_IDR		(AT91_DBGU + 0x0c)	/* Interrupt Disable Register */
-#define AT91_DBGU_IMR		(AT91_DBGU + 0x10)	/* Interrupt Mask Register */
-#define AT91_DBGU_SR		(AT91_DBGU + 0x14)	/* Status Register */
-#define AT91_DBGU_RHR		(AT91_DBGU + 0x18)	/* Receiver Holding Register */
-#define AT91_DBGU_THR		(AT91_DBGU + 0x1c)	/* Transmitter Holding Register */
-#define AT91_DBGU_BRGR		(AT91_DBGU + 0x20)	/* Baud Rate Generator Register */
-
-#define AT91_DBGU_CIDR		(AT91_DBGU + 0x40)	/* Chip ID Register */
-#define AT91_DBGU_EXID		(AT91_DBGU + 0x44)	/* Chip ID Extension Register */
-#define		AT91_CIDR_VERSION	(0x1f << 0)		/* Version of the Device */
-#define		AT91_CIDR_EPROC		(7    << 5)		/* Embedded Processor */
-#define		AT91_CIDR_NVPSIZ	(0xf  << 8)		/* Nonvolatile Program Memory Size */
-#define		AT91_CIDR_NVPSIZ2	(0xf  << 12)		/* Second Nonvolatile Program Memory Size */
-#define		AT91_CIDR_SRAMSIZ	(0xf  << 16)		/* Internal SRAM Size */
-#define		AT91_CIDR_ARCH		(0xff << 20)		/* Architecture Identifier */
-#define		AT91_CIDR_NVPTYP	(7    << 28)		/* Nonvolatile Program Memory Type */
-#define		AT91_CIDR_EXT		(1    << 31)		/* Extension Flag */
-
-#define AT91_DBGU_FNR		(AT91_DBGU + 0x48)	/* Force NTRST Register [SAM9 only] */
-#define		AT91_DBGU_FNTRST	(1 << 0)		/* Force NTRST */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_ecc.h b/include/asm-arm/arch-at91rm9200/at91_ecc.h
deleted file mode 100644
index 5c564ed..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_ecc.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_ecc.h
- *
- * Error Corrected Code Controller (ECC) - System peripherals regsters.
- * Based on AT91SAM9260 datasheet revision B.
- *
- * 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 AT91_ECC_H
-#define AT91_ECC_H
-
-#define AT91_ECC_CR		(AT91_ECC + 0x00)	/* Control register */
-#define		AT91_ECC_RST		(1 << 0)		/* Reset parity */
-
-#define AT91_ECC_MR		(AT91_ECC + 0x04)	/* Mode register */
-#define		AT91_ECC_PAGESIZE	(3 << 0)		/* Page Size */
-#define			AT91_ECC_PAGESIZE_528		(0)
-#define			AT91_ECC_PAGESIZE_1056		(1)
-#define			AT91_ECC_PAGESIZE_2112		(2)
-#define			AT91_ECC_PAGESIZE_4224		(3)
-
-#define AT91_ECC_SR		(AT91_ECC + 0x08)	/* Status register */
-#define		AT91_ECC_RECERR		(1 << 0)		/* Recoverable Error */
-#define		AT91_ECC_ECCERR		(1 << 1)		/* ECC Single Bit Error */
-#define		AT91_ECC_MULERR		(1 << 2)		/* Multiple Errors */
-
-#define AT91_ECC_PR		(AT91_ECC + 0x0c)	/* Parity register */
-#define		AT91_ECC_BITADDR	(0xf << 0)		/* Bit Error Address */
-#define		AT91_ECC_WORDADDR	(0xfff << 4)		/* Word Error Address */
-
-#define AT91_ECC_NPR		(AT91_ECC + 0x10)	/* NParity register */
-#define		AT91_ECC_NPARITY	(0xffff << 0)		/* NParity */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_lcdc.h b/include/asm-arm/arch-at91rm9200/at91_lcdc.h
deleted file mode 100644
index 9cbfcdd..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_lcdc.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_lcdc.h
- *
- * LCD Controller (LCDC).
- * Based on AT91SAM9261 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 AT91_LCDC_H
-#define AT91_LCDC_H
-
-#define AT91_LCDC_DMABADDR1	0x00		/* DMA Base Address Register 1 */
-#define AT91_LCDC_DMABADDR2	0x04		/* DMA Base Address Register 2 */
-#define AT91_LCDC_DMAFRMPT1	0x08		/* DMA Frame Pointer Register 1 */
-#define AT91_LCDC_DMAFRMPT2	0x0c		/* DMA Frame Pointer Register 2 */
-#define AT91_LCDC_DMAFRMADD1	0x10		/* DMA Frame Address Register 1 */
-#define AT91_LCDC_DMAFRMADD2	0x14		/* DMA Frame Address Register 2 */
-
-#define AT91_LCDC_DMAFRMCFG	0x18		/* DMA Frame Configuration Register */
-#define		AT91_LCDC_FRSIZE	(0x7fffff <<  0)	/* Frame Size */
-#define		AT91_LCDC_BLENGTH	(0x7f     << 24)	/* Burst Length */
-
-#define AT91_LCDC_DMACON	0x1c		/* DMA Control Register */
-#define		AT91_LCDC_DMAEN		(0x1 << 0)	/* DMA Enable */
-#define		AT91_LCDC_DMARST	(0x1 << 1)	/* DMA Reset */
-#define		AT91_LCDC_DMABUSY	(0x1 << 2)	/* DMA Busy */
-
-#define AT91_LCDC_LCDCON1	0x0800		/* LCD Control Register 1 */
-#define		AT91_LCDC_BYPASS	(1     <<  0)	/* Bypass lcd_dotck divider */
-#define		AT91_LCDC_CLKVAL	(0x1ff << 12)	/* Clock Divider */
-#define		AT91_LCDC_LINCNT	(0x7ff << 21)	/* Line Counter */
-
-#define AT91_LCDC_LCDCON2	0x0804		/* LCD Control Register 2 */
-#define		AT91_LCDC_DISTYPE	(3 << 0)	/* Display Type */
-#define			AT91_LCDC_DISTYPE_STNMONO	(0 << 0)
-#define			AT91_LCDC_DISTYPE_STNCOLOR	(1 << 0)
-#define			AT91_LCDC_DISTYPE_TFT		(2 << 0)
-#define		AT91_LCDC_SCANMOD	(1 << 2)	/* Scan Mode */
-#define			AT91_LCDC_SCANMOD_SINGLE	(0 << 2)
-#define			AT91_LCDC_SCANMOD_DUAL		(1 << 2)
-#define		AT91_LCDC_IFWIDTH	(3 << 3)	/*Interface Width */
-#define			AT91_LCDC_IFWIDTH_4		(0 << 3)
-#define			AT91_LCDC_IFWIDTH_8		(1 << 3)
-#define			AT91_LCDC_IFWIDTH_16		(2 << 3)
-#define		AT91_LCDC_PIXELSIZE	(7 << 5)	/* Bits per pixel */
-#define			AT91_LCDC_PIXELSIZE_1		(0 << 5)
-#define			AT91_LCDC_PIXELSIZE_2		(1 << 5)
-#define			AT91_LCDC_PIXELSIZE_4		(2 << 5)
-#define			AT91_LCDC_PIXELSIZE_8		(3 << 5)
-#define			AT91_LCDC_PIXELSIZE_16		(4 << 5)
-#define			AT91_LCDC_PIXELSIZE_24		(5 << 5)
-#define		AT91_LCDC_INVVD		(1 << 8)	/* LCD Data polarity */
-#define			AT91_LCDC_INVVD_NORMAL		(0 << 8)
-#define			AT91_LCDC_INVVD_INVERTED	(1 << 8)
-#define		AT91_LCDC_INVFRAME	(1 << 9 )	/* LCD VSync polarity */
-#define			AT91_LCDC_INVFRAME_NORMAL	(0 << 9)
-#define			AT91_LCDC_INVFRAME_INVERTED	(1 << 9)
-#define		AT91_LCDC_INVLINE	(1 << 10)	/* LCD HSync polarity */
-#define			AT91_LCDC_INVLINE_NORMAL	(0 << 10)
-#define			AT91_LCDC_INVLINE_INVERTED	(1 << 10)
-#define		AT91_LCDC_INVCLK	(1 << 11)	/* LCD dotclk polarity */
-#define			AT91_LCDC_INVCLK_NORMAL		(0 << 11)
-#define			AT91_LCDC_INVCLK_INVERTED	(1 << 11)
-#define		AT91_LCDC_INVDVAL	(1 << 12)	/* LCD dval polarity */
-#define			AT91_LCDC_INVDVAL_NORMAL	(0 << 12)
-#define			AT91_LCDC_INVDVAL_INVERTED	(1 << 12)
-#define		AT91_LCDC_CLKMOD	(1 << 15)	/* LCD dotclk mode */
-#define			AT91_LCDC_CLKMOD_ACTIVEDISPLAY	(0 << 15)
-#define			AT91_LCDC_CLKMOD_ALWAYSACTIVE	(1 << 15)
-#define		AT91_LCDC_MEMOR		(1 << 31)	/* Memory Ordering Format */
-#define			AT91_LCDC_MEMOR_BIG		(0 << 31)
-#define			AT91_LCDC_MEMOR_LITTLE		(1 << 31)
-
-#define AT91_LCDC_TIM1		0x0808		/* LCD Timing Register 1 */
-#define		AT91_LCDC_VFP		(0xff <<  0)	/* Vertical Front Porch */
-#define		AT91_LCDC_VBP		(0xff <<  8)	/* Vertical Back Porch */
-#define		AT91_LCDC_VPW		(0x3f << 16)	/* Vertical Synchronization Pulse Width */
-#define		AT91_LCDC_VHDLY		(0xf  << 24)	/* Vertical to Horizontal Delay */
-
-#define AT91_LCDC_TIM2		0x080c		/* LCD Timing Register 2 */
-#define		AT91_LCDC_HBP		(0xff  <<  0)	/* Horizontal Back Porch */
-#define		AT91_LCDC_HPW		(0x3f  <<  8)	/* Horizontal Synchronization Pulse Width */
-#define		AT91_LCDC_HFP		(0x7ff << 21)	/* Horizontal Front Porch */
-
-#define AT91_LCDC_LCDFRMCFG	0x0810		/* LCD Frame Configuration Register */
-#define		AT91_LCDC_LINEVAL	(0x7ff <<  0)	/* Vertical Size of LCD Module */
-#define		AT91_LCDC_HOZVAL	(0x7ff << 21)	/* Horizontal Size of LCD Module */
-
-#define AT91_LCDC_FIFO		0x0814		/* LCD FIFO Register */
-#define		AT91_LCDC_FIFOTH	(0xffff)	/* FIFO Threshold */
-
-#define AT91_LCDC_DP1_2		0x081c		/* Dithering Pattern DP1_2 Register */
-#define AT91_LCDC_DP4_7		0x0820		/* Dithering Pattern DP4_7 Register */
-#define AT91_LCDC_DP3_5		0x0824		/* Dithering Pattern DP3_5 Register */
-#define AT91_LCDC_DP2_3		0x0828		/* Dithering Pattern DP2_3 Register */
-#define AT91_LCDC_DP5_7		0x082c		/* Dithering Pattern DP5_7 Register */
-#define AT91_LCDC_DP3_4		0x0830		/* Dithering Pattern DP3_4 Register */
-#define AT91_LCDC_DP4_5		0x0834		/* Dithering Pattern DP4_5 Register */
-#define AT91_LCDC_DP6_7		0x0838		/* Dithering Pattern DP6_7 Register */
-#define		AT91_LCDC_DP1_2_VAL	(0xff)
-#define		AT91_LCDC_DP4_7_VAL	(0xfffffff)
-#define		AT91_LCDC_DP3_5_VAL	(0xfffff)
-#define		AT91_LCDC_DP2_3_VAL	(0xfff)
-#define		AT91_LCDC_DP5_7_VAL	(0xfffffff)
-#define		AT91_LCDC_DP3_4_VAL	(0xffff)
-#define		AT91_LCDC_DP4_5_VAL	(0xfffff)
-#define		AT91_LCDC_DP6_7_VAL	(0xfffffff)
-
-#define AT91_LCDC_PWRCON	0x083c		/* Power Control Register */
-#define		AT91_LCDC_PWR		(1    <<  0)	/* LCD Module Power Control */
-#define		AT91_LCDC_GUARDT	(0x7f <<  1)	/* Delay in Frame Period */
-#define		AT91_LCDC_BUSY		(1    << 31)	/* LCD Busy */
-
-#define AT91_LCDC_CONTRAST_CTR	0x0840		/* Contrast Control Register */
-#define		AT91_LCDC_PS		(3 << 0)	/* Contrast Counter Prescaler */
-#define			AT91_LCDC_PS_DIV1		(0 << 0)
-#define			AT91_LCDC_PS_DIV2		(1 << 0)
-#define			AT91_LCDC_PS_DIV4		(2 << 0)
-#define			AT91_LCDC_PS_DIV8		(3 << 0)
-#define		AT91_LCDC_POL		(1 << 2)	/* Polarity of output Pulse */
-#define			AT91_LCDC_POL_NEGATIVE		(0 << 2)
-#define			AT91_LCDC_POL_POSITIVE		(1 << 2)
-#define		AT91_LCDC_ENA		(1 << 3)	/* PWM generator Control */
-#define			AT91_LCDC_ENA_PWMDISABLE	(0 << 3)
-#define			AT91_LCDC_ENA_PWMENABLE		(1 << 3)
-
-#define AT91_LCDC_CONTRAST_VAL	0x0844		/* Contrast Value Register */
-#define		AT91_LCDC_CVAL		(0xff)		/* PWM compare value */
-
-#define AT91_LCDC_IER		0x0848		/* Interrupt Enable Register */
-#define AT91_LCDC_IDR		0x084c		/* Interrupt Disable Register */
-#define AT91_LCDC_IMR		0x0850		/* Interrupt Mask Register */
-#define AT91_LCDC_ISR		0x0854		/* Interrupt Enable Register */
-#define AT91_LCDC_ICR		0x0858		/* Interrupt Clear Register */
-#define		AT91_LCDC_LNI		(1 << 0)	/* Line Interrupt */
-#define		AT91_LCDC_LSTLNI	(1 << 1)	/* Last Line Interrupt */
-#define		AT91_LCDC_EOFI		(1 << 2)	/* DMA End Of Frame Interrupt */
-#define		AT91_LCDC_UFLWI		(1 << 4)	/* FIFO Underflow Interrupt */
-#define		AT91_LCDC_OWRI		(1 << 5)	/* FIFO Overwrite Interrupt */
-#define		AT91_LCDC_MERI		(1 << 6)	/* DMA Memory Error Interrupt */
-
-#define AT91_LCDC_LUT_(n)	(0x0c00 + ((n)*4))	/* Palette Entry 0..255 */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_mci.h b/include/asm-arm/arch-at91rm9200/at91_mci.h
deleted file mode 100644
index 9a552cb..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_mci.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_mci.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * MultiMedia Card Interface (MCI) registers.
- * Based on AT91RM9200 datasheet revision F.
- *
- * 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 AT91_MCI_H
-#define AT91_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		(7     <<  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		(3 << 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_SDIOIRQA	(1 <<  8)	/* SDIO Interrupt for Slot A */
-#define		At91_MCI_SDIOIRQB	(1 <<  9)	/* SDIO Interrupt for Slot B [AT91RM9200 only] */
-#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/at91_pdc.h b/include/asm-arm/arch-at91rm9200/at91_pdc.h
deleted file mode 100644
index 79d6e02..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_pdc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_pdc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Peripheral Data Controller (PDC) 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 AT91_PDC_H
-#define AT91_PDC_H
-
-#define AT91_PDC_RPR		0x100	/* Receive Pointer Register */
-#define AT91_PDC_RCR		0x104	/* Receive Counter Register */
-#define AT91_PDC_TPR		0x108	/* Transmit Pointer Register */
-#define AT91_PDC_TCR		0x10c	/* Transmit Counter Register */
-#define AT91_PDC_RNPR		0x110	/* Receive Next Pointer Register */
-#define AT91_PDC_RNCR		0x114	/* Receive Next Counter Register */
-#define AT91_PDC_TNPR		0x118	/* Transmit Next Pointer Register */
-#define AT91_PDC_TNCR		0x11c	/* Transmit Next Counter Register */
-
-#define AT91_PDC_PTCR		0x120	/* Transfer Control Register */
-#define		AT91_PDC_RXTEN		(1 << 0)	/* Receiver Transfer Enable */
-#define		AT91_PDC_RXTDIS		(1 << 1)	/* Receiver Transfer Disable */
-#define		AT91_PDC_TXTEN		(1 << 8)	/* Transmitter Transfer Enable */
-#define		AT91_PDC_TXTDIS		(1 << 9)	/* Transmitter Transfer Disable */
-
-#define AT91_PDC_PTSR		0x124	/* Transfer Status Register */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_pio.h b/include/asm-arm/arch-at91rm9200/at91_pio.h
deleted file mode 100644
index 680eaa1..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_pio.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_pio.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Parallel I/O Controller (PIO) - System peripherals 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 AT91_PIO_H
-#define AT91_PIO_H
-
-#define PIO_PER		0x00	/* Enable Register */
-#define PIO_PDR		0x04	/* Disable Register */
-#define PIO_PSR		0x08	/* Status Register */
-#define PIO_OER		0x10	/* Output Enable Register */
-#define PIO_ODR		0x14	/* Output Disable Register */
-#define PIO_OSR		0x18	/* Output Status Register */
-#define PIO_IFER	0x20	/* Glitch Input Filter Enable */
-#define PIO_IFDR	0x24	/* Glitch Input Filter Disable */
-#define PIO_IFSR	0x28	/* Glitch Input Filter Status */
-#define PIO_SODR	0x30	/* Set Output Data Register */
-#define PIO_CODR	0x34	/* Clear Output Data Register */
-#define PIO_ODSR	0x38	/* Output Data Status Register */
-#define PIO_PDSR	0x3c	/* Pin Data Status Register */
-#define PIO_IER		0x40	/* Interrupt Enable Register */
-#define PIO_IDR		0x44	/* Interrupt Disable Register */
-#define PIO_IMR		0x48	/* Interrupt Mask Register */
-#define PIO_ISR		0x4c	/* Interrupt Status Register */
-#define PIO_MDER	0x50	/* Multi-driver Enable Register */
-#define PIO_MDDR	0x54	/* Multi-driver Disable Register */
-#define PIO_MDSR	0x58	/* Multi-driver Status Register */
-#define PIO_PUDR	0x60	/* Pull-up Disable Register */
-#define PIO_PUER	0x64	/* Pull-up Enable Register */
-#define PIO_PUSR	0x68	/* Pull-up Status Register */
-#define PIO_ASR		0x70	/* Peripheral A Select Register */
-#define PIO_BSR		0x74	/* Peripheral B Select Register */
-#define PIO_ABSR	0x78	/* AB Status Register */
-#define PIO_OWER	0xa0	/* Output Write Enable Register */
-#define PIO_OWDR	0xa4	/* Output Write Disable Register */
-#define PIO_OWSR	0xa8	/* Output Write Status Register */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_pit.h b/include/asm-arm/arch-at91rm9200/at91_pit.h
deleted file mode 100644
index 4a30d009..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_pit.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_pit.h
- *
- * Periodic Interval Timer (PIT) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * 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 AT91_PIT_H
-#define AT91_PIT_H
-
-#define AT91_PIT_MR		(AT91_PIT + 0x00)	/* Mode Register */
-#define		AT91_PIT_PITIEN		(1 << 25)		/* Timer Interrupt Enable */
-#define		AT91_PIT_PITEN		(1 << 24)		/* Timer Enabled */
-#define		AT91_PIT_PIV		(0xfffff)		/* Periodic Interval Value */
-
-#define AT91_PIT_SR		(AT91_PIT + 0x04)	/* Status Register */
-#define		AT91_PIT_PITS		(1 << 0)		/* Timer Status */
-
-#define AT91_PIT_PIVR		(AT91_PIT + 0x08)	/* Periodic Interval Value Register */
-#define AT91_PIT_PIIR		(AT91_PIT + 0x0c)	/* Periodic Interval Image Register */
-#define		AT91_PIT_PICNT		(0xfff << 20)		/* Interval Counter */
-#define		AT91_PIT_CPIV		(0xfffff)		/* Inverval Value */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_pmc.h b/include/asm-arm/arch-at91rm9200/at91_pmc.h
deleted file mode 100644
index c3b489d..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_pmc.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_pmc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Power Management Controller (PMC) - System peripherals 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 AT91_PMC_H
-#define AT91_PMC_H
-
-#define	AT91_PMC_SCER		(AT91_PMC + 0x00)	/* System Clock Enable Register */
-#define	AT91_PMC_SCDR		(AT91_PMC + 0x04)	/* System Clock Disable Register */
-
-#define	AT91_PMC_SCSR		(AT91_PMC + 0x08)	/* System Clock Status Register */
-#define		AT91_PMC_PCK		(1 <<  0)		/* Processor Clock */
-#define		AT91RM9200_PMC_UDP	(1 <<  1)		/* USB Devcice Port Clock [AT91RM9200 only] */
-#define		AT91RM9200_PMC_MCKUDP	(1 <<  2)		/* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */
-#define		AT91RM9200_PMC_UHP	(1 <<  4)		/* USB Host Port Clock [AT91RM9200 only] */
-#define		AT91SAM926x_PMC_UHP	(1 <<  6)		/* USB Host Port Clock [AT91SAM926x only] */
-#define		AT91SAM926x_PMC_UDP	(1 <<  7)		/* USB Devcice Port Clock [AT91SAM926x only] */
-#define		AT91_PMC_PCK0		(1 <<  8)		/* Programmable Clock 0 */
-#define		AT91_PMC_PCK1		(1 <<  9)		/* Programmable Clock 1 */
-#define		AT91_PMC_PCK2		(1 << 10)		/* Programmable Clock 2 */
-#define		AT91_PMC_PCK3		(1 << 11)		/* Programmable Clock 3 */
-#define		AT91_PMC_HCK0		(1 << 16)		/* AHB Clock (USB host) [AT91SAM9261 only] */
-#define		AT91_PMC_HCK1		(1 << 17)		/* AHB Clock (LCD) [AT91SAM9261 only] */
-
-#define	AT91_PMC_PCER		(AT91_PMC + 0x10)	/* Peripheral Clock Enable Register */
-#define	AT91_PMC_PCDR		(AT91_PMC + 0x14)	/* Peripheral Clock Disable Register */
-#define	AT91_PMC_PCSR		(AT91_PMC + 0x18)	/* Peripheral Clock Status Register */
-
-#define	AT91_CKGR_MOR		(AT91_PMC + 0x20)	/* Main Oscillator Register */
-#define		AT91_PMC_MOSCEN		(1    << 0)		/* Main Oscillator Enable */
-#define		AT91_PMC_OSCBYPASS	(1    << 1)		/* Oscillator Bypass [AT91SAM926x only] */
-#define		AT91_PMC_OSCOUNT	(0xff << 8)		/* Main Oscillator Start-up Time */
-
-#define	AT91_CKGR_MCFR		(AT91_PMC + 0x24)	/* Main Clock Frequency Register */
-#define		AT91_PMC_MAINF		(0xffff <<  0)		/* Main Clock Frequency */
-#define		AT91_PMC_MAINRDY	(1	<< 16)		/* Main Clock Ready */
-
-#define	AT91_CKGR_PLLAR		(AT91_PMC + 0x28)	/* PLL A Register */
-#define	AT91_CKGR_PLLBR		(AT91_PMC + 0x2c)	/* PLL B Register */
-#define		AT91_PMC_DIV		(0xff  <<  0)		/* Divider */
-#define		AT91_PMC_PLLCOUNT	(0x3f  <<  8)		/* PLL Counter */
-#define		AT91_PMC_OUT		(3     << 14)		/* PLL Clock Frequency Range */
-#define		AT91_PMC_MUL		(0x7ff << 16)		/* PLL Multiplier */
-#define		AT91_PMC_USB96M		(1     << 28)		/* Divider by 2 Enable (PLLB only) */
-
-#define	AT91_PMC_MCKR		(AT91_PMC + 0x30)	/* Master Clock Register */
-#define		AT91_PMC_CSS		(3 <<  0)		/* Master Clock Selection */
-#define			AT91_PMC_CSS_SLOW		(0 << 0)
-#define			AT91_PMC_CSS_MAIN		(1 << 0)
-#define			AT91_PMC_CSS_PLLA		(2 << 0)
-#define			AT91_PMC_CSS_PLLB		(3 << 0)
-#define		AT91_PMC_PRES		(7 <<  2)		/* Master Clock Prescaler */
-#define			AT91_PMC_PRES_1			(0 << 2)
-#define			AT91_PMC_PRES_2			(1 << 2)
-#define			AT91_PMC_PRES_4			(2 << 2)
-#define			AT91_PMC_PRES_8			(3 << 2)
-#define			AT91_PMC_PRES_16		(4 << 2)
-#define			AT91_PMC_PRES_32		(5 << 2)
-#define			AT91_PMC_PRES_64		(6 << 2)
-#define		AT91_PMC_MDIV		(3 <<  8)		/* Master Clock Division */
-#define			AT91_PMC_MDIV_1			(0 << 8)
-#define			AT91_PMC_MDIV_2			(1 << 8)
-#define			AT91_PMC_MDIV_3			(2 << 8)
-#define			AT91_PMC_MDIV_4			(3 << 8)
-
-#define	AT91_PMC_PCKR(n)	(AT91_PMC + 0x40 + ((n) * 4))	/* Programmable Clock 0-3 Registers */
-
-#define	AT91_PMC_IER		(AT91_PMC + 0x60)	/* Interrupt Enable Register */
-#define	AT91_PMC_IDR		(AT91_PMC + 0x64)	/* Interrupt Disable Register */
-#define	AT91_PMC_SR		(AT91_PMC + 0x68)	/* Status Register */
-#define		AT91_PMC_MOSCS		(1 <<  0)		/* MOSCS Flag */
-#define		AT91_PMC_LOCKA		(1 <<  1)		/* PLLA Lock */
-#define		AT91_PMC_LOCKB		(1 <<  2)		/* PLLB Lock */
-#define		AT91_PMC_MCKRDY		(1 <<  3)		/* Master Clock */
-#define		AT91_PMC_PCK0RDY	(1 <<  8)		/* Programmable Clock 0 */
-#define		AT91_PMC_PCK1RDY	(1 <<  9)		/* Programmable Clock 1 */
-#define		AT91_PMC_PCK2RDY	(1 << 10)		/* Programmable Clock 2 */
-#define		AT91_PMC_PCK3RDY	(1 << 11)		/* Programmable Clock 3 */
-#define	AT91_PMC_IMR		(AT91_PMC + 0x6c)	/* Interrupt Mask Register */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_rstc.h b/include/asm-arm/arch-at91rm9200/at91_rstc.h
deleted file mode 100644
index 237d3c4..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_rstc.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_rstc.h
- *
- * Reset Controller (RSTC) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * 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 AT91_RSTC_H
-#define AT91_RSTC_H
-
-#define AT91_RSTC_CR		(AT91_RSTC + 0x00)	/* Reset Controller Control Register */
-#define		AT91_RSTC_PROCRST	(1 << 0)		/* Processor Reset */
-#define		AT91_RSTC_PERRST	(1 << 2)		/* Peripheral Reset */
-#define		AT91_RSTC_EXTRST	(1 << 3)		/* External Reset */
-#define		AT91_RSTC_KEY		(0xff << 24)		/* KEY Password */
-
-#define AT91_RSTC_SR		(AT91_RSTC + 0x04)	/* Reset Controller Status Register */
-#define		AT91_RSTC_URSTS		(1 << 0)		/* User Reset Status */
-#define		AT91_RSTC_RSTTYP	(7 << 8)		/* Reset Type */
-#define			AT91_RSTC_RSTTYP_GENERAL	(0 << 8)
-#define			AT91_RSTC_RSTTYP_WAKEUP		(1 << 8)
-#define			AT91_RSTC_RSTTYP_WATCHDOG	(2 << 8)
-#define			AT91_RSTC_RSTTYP_SOFTWARE	(3 << 8)
-#define			AT91_RSTC_RSTTYP_USER	(4 << 8)
-#define		AT91_RSTC_NRSTL		(1 << 16)		/* NRST Pin Level */
-#define		AT91_RSTC_SRCMP		(1 << 17)		/* Software Reset Command in Progress */
-
-#define AT91_RSTC_MR		(AT91_RSTC + 0x08)	/* Reset Controller Mode Register */
-#define		AT91_RSTC_URSTEN	(1 << 0)		/* User Reset Enable */
-#define		AT91_RSTC_URSTIEN	(1 << 4)		/* User Reset Interrupt Enable */
-#define		AT91_RSTC_ERSTL		(0xf << 8)		/* External Reset Length */
-#define		AT91_RSTC_KEY		(0xff << 24)		/* KEY Password */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_rtc.h b/include/asm-arm/arch-at91rm9200/at91_rtc.h
deleted file mode 100644
index 095fe08..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_rtc.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_rtc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Real Time Clock (RTC) - System peripheral 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 AT91_RTC_H
-#define AT91_RTC_H
-
-#define	AT91_RTC_CR		(AT91_RTC + 0x00)	/* Control Register */
-#define		AT91_RTC_UPDTIM		(1 <<  0)		/* Update Request Time Register */
-#define		AT91_RTC_UPDCAL		(1 <<  1)		/* Update Request Calendar Register */
-#define		AT91_RTC_TIMEVSEL	(3 <<  8)		/* Time Event Selection */
-#define			AT91_RTC_TIMEVSEL_MINUTE	(0 << 8)
-#define			AT91_RTC_TIMEVSEL_HOUR		(1 << 8)
-#define			AT91_RTC_TIMEVSEL_DAY24		(2 << 8)
-#define			AT91_RTC_TIMEVSEL_DAY12		(3 << 8)
-#define		AT91_RTC_CALEVSEL	(3 << 16)		/* Calendar Event Selection */
-#define			AT91_RTC_CALEVSEL_WEEK		(0 << 16)
-#define			AT91_RTC_CALEVSEL_MONTH		(1 << 16)
-#define			AT91_RTC_CALEVSEL_YEAR		(2 << 16)
-
-#define	AT91_RTC_MR		(AT91_RTC + 0x04)	/* Mode Register */
-#define			AT91_RTC_HRMOD		(1 <<  0)		/* 12/24 Hour Mode */
-
-#define	AT91_RTC_TIMR		(AT91_RTC + 0x08)	/* Time Register */
-#define		AT91_RTC_SEC		(0x7f <<  0)		/* Current Second */
-#define		AT91_RTC_MIN		(0x7f <<  8)		/* Current Minute */
-#define		AT91_RTC_HOUR		(0x3f << 16)		/* Current Hour */
-#define		AT91_RTC_AMPM		(1    << 22)		/* Ante Meridiem Post Meridiem Indicator */
-
-#define	AT91_RTC_CALR		(AT91_RTC + 0x0c)	/* Calendar Register */
-#define		AT91_RTC_CENT		(0x7f <<  0)		/* Current Century */
-#define		AT91_RTC_YEAR		(0xff <<  8)		/* Current Year */
-#define		AT91_RTC_MONTH		(0x1f << 16)		/* Current Month */
-#define		AT91_RTC_DAY		(7    << 21)		/* Current Day */
-#define		AT91_RTC_DATE		(0x3f << 24)		/* Current Date */
-
-#define	AT91_RTC_TIMALR		(AT91_RTC + 0x10)	/* Time Alarm Register */
-#define		AT91_RTC_SECEN		(1 <<  7)		/* Second Alarm Enable */
-#define		AT91_RTC_MINEN		(1 << 15)		/* Minute Alarm Enable */
-#define		AT91_RTC_HOUREN		(1 << 23)		/* Hour Alarm Enable */
-
-#define	AT91_RTC_CALALR		(AT91_RTC + 0x14)	/* Calendar Alarm Register */
-#define		AT91_RTC_MTHEN		(1 << 23)		/* Month Alarm Enable */
-#define		AT91_RTC_DATEEN		(1 << 31)		/* Date Alarm Enable */
-
-#define	AT91_RTC_SR		(AT91_RTC + 0x18)	/* Status Register */
-#define		AT91_RTC_ACKUPD		(1 <<  0)		/* Acknowledge for Update */
-#define		AT91_RTC_ALARM		(1 <<  1)		/* Alarm Flag */
-#define		AT91_RTC_SECEV		(1 <<  2)		/* Second Event */
-#define		AT91_RTC_TIMEV		(1 <<  3)		/* Time Event */
-#define		AT91_RTC_CALEV		(1 <<  4)		/* Calendar Event */
-
-#define	AT91_RTC_SCCR		(AT91_RTC + 0x1c)	/* Status Clear Command Register */
-#define	AT91_RTC_IER		(AT91_RTC + 0x20)	/* Interrupt Enable Register */
-#define	AT91_RTC_IDR		(AT91_RTC + 0x24)	/* Interrupt Disable Register */
-#define	AT91_RTC_IMR		(AT91_RTC + 0x28)	/* Interrupt Mask Register */
-
-#define	AT91_RTC_VER		(AT91_RTC + 0x2c)	/* Valid Entry Register */
-#define		AT91_RTC_NVTIM		(1 <<  0)		/* Non valid Time */
-#define		AT91_RTC_NVCAL		(1 <<  1)		/* Non valid Calendar */
-#define		AT91_RTC_NVTIMALR	(1 <<  2)		/* Non valid Time Alarm */
-#define		AT91_RTC_NVCALALR	(1 <<  3)		/* Non valid Calendar Alarm */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_rtt.h b/include/asm-arm/arch-at91rm9200/at91_rtt.h
deleted file mode 100644
index c6751ba..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_rtt.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_rtt.h
- *
- * Real-time Timer (RTT) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * 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 AT91_RTT_H
-#define AT91_RTT_H
-
-#define AT91_RTT_MR		(AT91_RTT + 0x00)	/* Real-time Mode Register */
-#define		AT91_RTT_RTPRES		(0xffff << 0)		/* Real-time Timer Prescaler Value */
-#define		AT91_RTT_ALMIEN		(1 << 16)		/* Alarm Interrupt Enable */
-#define		AT91_RTT_RTTINCIEN	(1 << 17)		/* Real Time Timer Increment Interrupt Enable */
-#define		AT91_RTT_RTTRST		(1 << 18)		/* Real Time Timer Restart */
-
-#define AT91_RTT_AR		(AT91_RTT + 0x04)	/* Real-time Alarm Register */
-#define		AT91_RTT_ALMV		(0xffffffff)		/* Alarm Value */
-
-#define AT91_RTT_VR		(AT91_RTT + 0x08)	/* Real-time Value Register */
-#define		AT91_RTT_CRTV		(0xffffffff)		/* Current Real-time Value */
-
-#define AT91_RTT_SR		(AT91_RTT + 0x0c)	/* Real-time Status Register */
-#define		AT91_RTT_ALMS		(1 << 0)		/* Real-time Alarm Status */
-#define		AT91_RTT_RTTINC		(1 << 1)		/* Real-time Timer Increment */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_shdwc.h b/include/asm-arm/arch-at91rm9200/at91_shdwc.h
deleted file mode 100644
index 0439250..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_shdwc.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_shdwc.h
- *
- * Shutdown Controller (SHDWC) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * 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 AT91_SHDWC_H
-#define AT91_SHDWC_H
-
-#define AT91_SHDW_CR		(AT91_SHDWC + 0x00)	/* Shut Down Control Register */
-#define		AT91_SHDW_SHDW		(1    << 0)		/* Processor Reset */
-#define		AT91_SHDW_KEY		(0xff << 24)		/* KEY Password */
-
-#define AT91_SHDW_MR		(AT91_SHDWC + 0x04)	/* Shut Down Mode Register */
-#define		AT91_SHDW_WKMODE0	(3 << 0)		/* Wake-up 0 Mode Selection */
-#define			AT91_SHDW_WKMODE0_NONE		0
-#define			AT91_SHDW_WKMODE0_HIGH		1
-#define			AT91_SHDW_WKMODE0_LOW		2
-#define			AT91_SHDW_WKMODE0_ANYLEVEL	3
-#define		AT91_SHDW_CPTWK0	(0xf << 4)		/* Counter On Wake Up 0 */
-#define		AT91_SHDW_RTTWKEN	(1   << 16)		/* Real Time Timer Wake-up Enable */
-
-#define AT91_SHDW_SR		(AT91_SHDWC + 0x08)	/* Shut Down Status Register */
-#define		AT91_SHDW_WAKEUP0	(1 <<  0)		/* Wake-up 0 Status */
-#define		AT91_SHDW_RTTWK		(1 << 16)		/* Real-time Timer Wake-up */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_spi.h b/include/asm-arm/arch-at91rm9200/at91_spi.h
deleted file mode 100644
index bec48ca..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_spi.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_spi.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Serial Peripheral Interface (SPI) 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 AT91_SPI_H
-#define AT91_SPI_H
-
-#define AT91_SPI_CR			0x00		/* Control Register */
-#define		AT91_SPI_SPIEN		(1 <<  0)		/* SPI Enable */
-#define		AT91_SPI_SPIDIS		(1 <<  1)		/* SPI Disable */
-#define		AT91_SPI_SWRST		(1 <<  7)		/* SPI Software Reset */
-#define		AT91_SPI_LASTXFER	(1 << 24)		/* Last Transfer [SAM9261 only] */
-
-#define AT91_SPI_MR			0x04		/* Mode Register */
-#define		AT91_SPI_MSTR		(1    <<  0)		/* Master/Slave Mode */
-#define		AT91_SPI_PS		(1    <<  1)		/* Peripheral Select */
-#define			AT91_SPI_PS_FIXED	(0 << 1)
-#define			AT91_SPI_PS_VARIABLE	(1 << 1)
-#define		AT91_SPI_PCSDEC		(1    <<  2)		/* Chip Select Decode */
-#define		AT91_SPI_DIV32		(1    <<  3)		/* Clock Selection [AT91RM9200 only] */
-#define		AT91_SPI_MODFDIS	(1    <<  4)		/* Mode Fault Detection */
-#define		AT91_SPI_LLB		(1    <<  7)		/* Local Loopback Enable */
-#define		AT91_SPI_PCS		(0xf  << 16)		/* Peripheral Chip Select */
-#define		AT91_SPI_DLYBCS		(0xff << 24)		/* Delay Between Chip Selects */
-
-#define AT91_SPI_RDR		0x08			/* Receive Data Register */
-#define		AT91_SPI_RD		(0xffff <<  0)		/* Receive Data */
-#define		AT91_SPI_PCS		(0xf	<< 16)		/* Peripheral Chip Select */
-
-#define AT91_SPI_TDR		0x0c			/* Transmit Data Register */
-#define		AT91_SPI_TD		(0xffff <<  0)		/* Transmit Data */
-#define		AT91_SPI_PCS		(0xf	<< 16)		/* Peripheral Chip Select */
-#define		AT91_SPI_LASTXFER	(1	<< 24)		/* Last Transfer [SAM9261 only] */
-
-#define AT91_SPI_SR		0x10			/* Status Register */
-#define		AT91_SPI_RDRF		(1 <<  0)		/* Receive Data Register Full */
-#define		AT91_SPI_TDRE		(1 <<  1)		/* Transmit Data Register Full */
-#define		AT91_SPI_MODF		(1 <<  2)		/* Mode Fault Error */
-#define		AT91_SPI_OVRES		(1 <<  3)		/* Overrun Error Status */
-#define		AT91_SPI_ENDRX		(1 <<  4)		/* End of RX buffer */
-#define		AT91_SPI_ENDTX		(1 <<  5)		/* End of TX buffer */
-#define		AT91_SPI_RXBUFF		(1 <<  6)		/* RX Buffer Full */
-#define		AT91_SPI_TXBUFE		(1 <<  7)		/* TX Buffer Empty */
-#define		AT91_SPI_NSSR		(1 <<  8)		/* NSS Rising [SAM9261 only] */
-#define		AT91_SPI_TXEMPTY	(1 <<  9)		/* Transmission Register Empty [SAM9261 only] */
-#define		AT91_SPI_SPIENS		(1 << 16)		/* SPI Enable Status */
-
-#define AT91_SPI_IER		0x14			/* Interrupt Enable Register */
-#define AT91_SPI_IDR		0x18			/* Interrupt Disable Register */
-#define AT91_SPI_IMR		0x1c			/* Interrupt Mask Register */
-
-#define AT91_SPI_CSR(n)		(0x30 + ((n) * 4))	/* Chip Select Registers 0-3 */
-#define		AT91_SPI_CPOL		(1    <<  0)		/* Clock Polarity */
-#define		AT91_SPI_NCPHA		(1    <<  1)		/* Clock Phase */
-#define		AT91_SPI_CSAAT		(1    <<  3)		/* Chip Select Active After Transfer [SAM9261 only] */
-#define		AT91_SPI_BITS		(0xf  <<  4)		/* Bits Per Transfer */
-#define			AT91_SPI_BITS_8		(0 << 4)
-#define			AT91_SPI_BITS_9		(1 << 4)
-#define			AT91_SPI_BITS_10	(2 << 4)
-#define			AT91_SPI_BITS_11	(3 << 4)
-#define			AT91_SPI_BITS_12	(4 << 4)
-#define			AT91_SPI_BITS_13	(5 << 4)
-#define			AT91_SPI_BITS_14	(6 << 4)
-#define			AT91_SPI_BITS_15	(7 << 4)
-#define			AT91_SPI_BITS_16	(8 << 4)
-#define		AT91_SPI_SCBR		(0xff <<  8)		/* Serial Clock Baud Rate */
-#define		AT91_SPI_DLYBS		(0xff << 16)		/* Delay before SPCK */
-#define		AT91_SPI_DLYBCT		(0xff << 24)		/* Delay between Consecutive Transfers */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_ssc.h b/include/asm-arm/arch-at91rm9200/at91_ssc.h
deleted file mode 100644
index 694bcaa..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_ssc.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_ssc.h
- *
- * Copyright (C) SAN People
- *
- * Serial Synchronous Controller (SSC) 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 AT91_SSC_H
-#define AT91_SSC_H
-
-#define AT91_SSC_CR		0x00	/* Control Register */
-#define		AT91_SSC_RXEN		(1 <<  0)	/* Receive Enable */
-#define		AT91_SSC_RXDIS		(1 <<  1)	/* Receive Disable */
-#define		AT91_SSC_TXEN		(1 <<  8)	/* Transmit Enable */
-#define		AT91_SSC_TXDIS		(1 <<  9)	/* Transmit Disable */
-#define		AT91_SSC_SWRST		(1 << 15)	/* Software Reset */
-
-#define AT91_SSC_CMR		0x04	/* Clock Mode Register */
-#define		AT91_SSC_CMR_DIV	(0xfff << 0)	/* Clock Divider */
-
-#define AT91_SSC_RCMR		0x10	/* Receive Clock Mode Register */
-#define		AT91_SSC_CKS		(3    <<  0)	/* Clock Selection */
-#define			AT91_SSC_CKS_DIV		(0 << 0)
-#define			AT91_SSC_CKS_CLOCK		(1 << 0)
-#define			AT91_SSC_CKS_PIN		(2 << 0)
-#define		AT91_SSC_CKO		(7    <<  2)	/* Clock Output Mode Selection */
-#define			AT91_SSC_CKO_NONE		(0 << 2)
-#define			AT91_SSC_CKO_CONTINUOUS		(1 << 2)
-#define		AT91_SSC_CKI		(1    <<  5)	/* Clock Inversion */
-#define			AT91_SSC_CKI_FALLING		(0 << 5)
-#define			AT91_SSC_CK_RISING		(1 << 5)
-#define		AT91_SSC_CKG		(1    <<  6)	/* Receive Clock Gating Selection [AT91SAM9261 only] */
-#define			AT91_SSC_CKG_NONE		(0 << 6)
-#define			AT91_SSC_CKG_RFLOW		(1 << 6)
-#define			AT91_SSC_CKG_RFHIGH		(2 << 6)
-#define		AT91_SSC_START		(0xf  <<  8)	/* Start Selection */
-#define			AT91_SSC_START_CONTINUOUS	(0 << 8)
-#define			AT91_SSC_START_TX_RX		(1 << 8)
-#define			AT91_SSC_START_LOW_RF		(2 << 8)
-#define			AT91_SSC_START_HIGH_RF		(3 << 8)
-#define			AT91_SSC_START_FALLING_RF	(4 << 8)
-#define			AT91_SSC_START_RISING_RF	(5 << 8)
-#define			AT91_SSC_START_LEVEL_RF		(6 << 8)
-#define			AT91_SSC_START_EDGE_RF		(7 << 8)
-#define		AT91_SSC_STOP		(1    << 12)	/* Receive Stop Selection [AT91SAM9261 only] */
-#define		AT91_SSC_STTDLY		(0xff << 16)	/* Start Delay */
-#define		AT91_SSC_PERIOD		(0xff << 24)	/* Period Divider Selection */
-
-#define AT91_SSC_RFMR		0x14	/* Receive Frame Mode Register */
-#define		AT91_SSC_DATALEN	(0x1f <<  0)	/* Data Length */
-#define		AT91_SSC_LOOP		(1    <<  5)	/* Loop Mode */
-#define		AT91_SSC_MSBF		(1    <<  7)	/* Most Significant Bit First */
-#define		AT91_SSC_DATNB		(0xf  <<  8)	/* Data Number per Frame */
-#define		AT91_SSC_FSLEN		(0xf  << 16)	/* Frame Sync Length */
-#define		AT91_SSC_FSOS		(7    << 20)	/* Frame Sync Output Selection */
-#define			AT91_SSC_FSOS_NONE		(0 << 20)
-#define			AT91_SSC_FSOS_NEGATIVE		(1 << 20)
-#define			AT91_SSC_FSOS_POSITIVE		(2 << 20)
-#define			AT91_SSC_FSOS_LOW		(3 << 20)
-#define			AT91_SSC_FSOS_HIGH		(4 << 20)
-#define			AT91_SSC_FSOS_TOGGLE		(5 << 20)
-#define		AT91_SSC_FSEDGE		(1    << 24)	/* Frame Sync Edge Detection */
-#define			AT91_SSC_FSEDGE_POSITIVE	(0 << 24)
-#define			AT91_SSC_FSEDGE_NEGATIVE	(1 << 24)
-
-#define AT91_SSC_TCMR		0x18	/* Transmit Clock Mode Register */
-#define AT91_SSC_TFMR		0x1c	/* Transmit Fram Mode Register */
-#define		AT91_SSC_DATDEF		(1 <<  5)	/* Data Default Value */
-#define		AT91_SSC_FSDEN		(1 << 23)	/* Frame Sync Data Enable */
-
-#define AT91_SSC_RHR		0x20	/* Receive Holding Register */
-#define AT91_SSC_THR		0x24	/* Transmit Holding Register */
-#define AT91_SSC_RSHR		0x30	/* Receive Sync Holding Register */
-#define AT91_SSC_TSHR		0x34	/* Transmit Sync Holding Register */
-
-#define AT91_SSC_RC0R		0x38	/* Receive Compare 0 Register [AT91SAM9261 only] */
-#define AT91_SSC_RC1R		0x3c	/* Receive Compare 1 Register [AT91SAM9261 only] */
-
-#define AT91_SSC_SR		0x40	/* Status Register */
-#define		AT91_SSC_TXRDY		(1 <<  0)	/* Transmit Ready */
-#define		AT91_SSC_TXEMPTY	(1 <<  1)	/* Transmit Empty */
-#define		AT91_SSC_ENDTX		(1 <<  2)	/* End of Transmission */
-#define		AT91_SSC_TXBUFE		(1 <<  3)	/* Transmit Buffer Empty */
-#define		AT91_SSC_RXRDY		(1 <<  4)	/* Receive Ready */
-#define		AT91_SSC_OVRUN		(1 <<  5)	/* Receive Overrun */
-#define		AT91_SSC_ENDRX		(1 <<  6)	/* End of Reception */
-#define		AT91_SSC_RXBUFF		(1 <<  7)	/* Receive Buffer Full */
-#define		AT91_SSC_CP0		(1 <<  8)	/* Compare 0 [AT91SAM9261 only] */
-#define		AT91_SSC_CP1		(1 <<  9)	/* Compare 1 [AT91SAM9261 only] */
-#define		AT91_SSC_TXSYN		(1 << 10)	/* Transmit Sync */
-#define		AT91_SSC_RXSYN		(1 << 11)	/* Receive Sync */
-#define		AT91_SSC_TXENA		(1 << 16)	/* Transmit Enable */
-#define		AT91_SSC_RXENA		(1 << 17)	/* Receive Enable */
-
-#define AT91_SSC_IER		0x44	/* Interrupt Enable Register */
-#define AT91_SSC_IDR		0x48	/* Interrupt Disable Register */
-#define AT91_SSC_IMR		0x4c	/* Interrupt Mask Register */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_st.h b/include/asm-arm/arch-at91rm9200/at91_st.h
deleted file mode 100644
index 2432ddf..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_st.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_st.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * System Timer (ST) - System peripherals 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 AT91_ST_H
-#define AT91_ST_H
-
-#define	AT91_ST_CR		(AT91_ST + 0x00)	/* Control Register */
-#define 	AT91_ST_WDRST		(1 << 0)		/* Watchdog Timer Restart */
-
-#define	AT91_ST_PIMR		(AT91_ST + 0x04)	/* Period Interval Mode Register */
-#define		AT91_ST_PIV		(0xffff <<  0)		/* Period Interval Value */
-
-#define	AT91_ST_WDMR		(AT91_ST + 0x08)	/* Watchdog Mode Register */
-#define		AT91_ST_WDV		(0xffff <<  0)		/* Watchdog Counter Value */
-#define		AT91_ST_RSTEN		(1	<< 16)		/* Reset Enable */
-#define		AT91_ST_EXTEN		(1	<< 17)		/* External Signal Assertion Enable */
-
-#define	AT91_ST_RTMR		(AT91_ST + 0x0c)	/* Real-time Mode Register */
-#define		AT91_ST_RTPRES		(0xffff <<  0)		/* Real-time Prescalar Value */
-
-#define	AT91_ST_SR		(AT91_ST + 0x10)	/* Status Register */
-#define		AT91_ST_PITS		(1 << 0)		/* Period Interval Timer Status */
-#define		AT91_ST_WDOVF		(1 << 1) 		/* Watchdog Overflow */
-#define		AT91_ST_RTTINC		(1 << 2) 		/* Real-time Timer Increment */
-#define		AT91_ST_ALMS		(1 << 3) 		/* Alarm Status */
-
-#define	AT91_ST_IER		(AT91_ST + 0x14)	/* Interrupt Enable Register */
-#define	AT91_ST_IDR		(AT91_ST + 0x18)	/* Interrupt Disable Register */
-#define	AT91_ST_IMR		(AT91_ST + 0x1c)	/* Interrupt Mask Register */
-
-#define	AT91_ST_RTAR		(AT91_ST + 0x20)	/* Real-time Alarm Register */
-#define		AT91_ST_ALMV		(0xfffff << 0)		/* Alarm Value */
-
-#define	AT91_ST_CRTR		(AT91_ST + 0x24)	/* Current Real-time Register */
-#define		AT91_ST_CRTV		(0xfffff << 0)		/* Current Real-Time Value */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_tc.h b/include/asm-arm/arch-at91rm9200/at91_tc.h
deleted file mode 100644
index 8d06eb0..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_tc.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_tc.h
- *
- * Copyright (C) SAN People
- *
- * Timer/Counter Unit (TC) 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 AT91_TC_H
-#define AT91_TC_H
-
-#define AT91_TC_BCR		0xc0		/* TC Block Control Register */
-#define		AT91_TC_SYNC		(1 << 0)	/* Synchro Command */
-
-#define AT91_TC_BMR		0xc4		/* TC Block Mode Register */
-#define		AT91_TC_TC0XC0S		(3 << 0)	/* External Clock Signal 0 Selection */
-#define			AT91_TC_TC0XC0S_TCLK0		(0 << 0)
-#define			AT91_TC_TC0XC0S_NONE		(1 << 0)
-#define			AT91_TC_TC0XC0S_TIOA1		(2 << 0)
-#define			AT91_TC_TC0XC0S_TIOA2		(3 << 0)
-#define		AT91_TC_TC1XC1S		(3 << 2)	/* External Clock Signal 1 Selection */
-#define			AT91_TC_TC1XC1S_TCLK1		(0 << 2)
-#define			AT91_TC_TC1XC1S_NONE		(1 << 2)
-#define			AT91_TC_TC1XC1S_TIOA0		(2 << 2)
-#define			AT91_TC_TC1XC1S_TIOA2		(3 << 2)
-#define		AT91_TC_TC2XC2S		(3 << 4)	/* External Clock Signal 2 Selection */
-#define			AT91_TC_TC2XC2S_TCLK2		(0 << 4)
-#define			AT91_TC_TC2XC2S_NONE		(1 << 4)
-#define			AT91_TC_TC2XC2S_TIOA0		(2 << 4)
-#define			AT91_TC_TC2XC2S_TIOA1		(3 << 4)
-
-
-#define AT91_TC_CCR		0x00		/* Channel Control Register */
-#define		AT91_TC_CLKEN		(1 << 0)	/* Counter Clock Enable Command */
-#define		AT91_TC_CLKDIS		(1 << 1)	/* Counter CLock Disable Command */
-#define		AT91_TC_SWTRG		(1 << 2)	/* Software Trigger Command */
-
-#define AT91_TC_CMR		0x04		/* Channel Mode Register */
-#define		AT91_TC_TCCLKS		(7 << 0)	/* Capture/Waveform Mode: Clock Selection */
-#define			AT91_TC_TIMER_CLOCK1		(0 << 0)
-#define			AT91_TC_TIMER_CLOCK2		(1 << 0)
-#define			AT91_TC_TIMER_CLOCK3		(2 << 0)
-#define			AT91_TC_TIMER_CLOCK4		(3 << 0)
-#define			AT91_TC_TIMER_CLOCK5		(4 << 0)
-#define			AT91_TC_XC0			(5 << 0)
-#define			AT91_TC_XC1			(6 << 0)
-#define			AT91_TC_XC2			(7 << 0)
-#define		AT91_TC_CLKI		(1 << 3)	/* Capture/Waveform Mode: Clock Invert */
-#define		AT91_TC_BURST		(3 << 4)	/* Capture/Waveform Mode: Burst Signal Selection */
-#define		AT91_TC_LDBSTOP		(1 << 6)	/* Capture Mode: Counter Clock Stopped with TB Loading */
-#define		AT91_TC_LDBDIS		(1 << 7)	/* Capture Mode: Counter Clock Disable with RB Loading */
-#define		AT91_TC_ETRGEDG		(3 << 8)	/* Capture Mode: External Trigger Edge Selection */
-#define		AT91_TC_ABETRG		(1 << 10)	/* Capture Mode: TIOA or TIOB External Trigger Selection */
-#define		AT91_TC_CPCTRG		(1 << 14)	/* Capture Mode: RC Compare Trigger Enable */
-#define		AT91_TC_WAVE		(1 << 15)	/* Capture/Waveform mode */
-#define		AT91_TC_LDRA		(3 << 16)	/* Capture Mode: RA Loading Selection */
-#define		AT91_TC_LDRB		(3 << 18)	/* Capture Mode: RB Loading Selection */
-
-#define		AT91_TC_CPCSTOP		(1 <<  6)	/* Waveform Mode: Counter Clock Stopped with RC Compare */
-#define		AT91_TC_CPCDIS		(1 <<  7)	/* Waveform Mode: Counter Clock Disable with RC Compare */
-#define		AT91_TC_EEVTEDG		(3 <<  8)	/* Waveform Mode: External Event Edge Selection */
-#define			AT91_TC_EEVTEDG_NONE		(0 << 8)
-#define			AT91_TC_EEVTEDG_RISING		(1 << 8)
-#define			AT91_TC_EEVTEDG_FALLING		(2 << 8)
-#define			AT91_TC_EEVTEDG_BOTH		(3 << 8)
-#define		AT91_TC_EEVT		(3 << 10)	/* Waveform Mode: External Event Selection */
-#define			AT91_TC_EEVT_TIOB		(0 << 10)
-#define			AT91_TC_EEVT_XC0		(1 << 10)
-#define			AT91_TC_EEVT_XC1		(2 << 10)
-#define			AT91_TC_EEVT_XC2		(3 << 10)
-#define		AT91_TC_ENETRG		(1 << 12)	/* Waveform Mode: External Event Trigger Enable */
-#define		AT91_TC_WAVESEL		(3 << 13)	/* Waveform Mode: Waveform Selection */
-#define			AT91_TC_WAVESEL_UP		(0 << 13)
-#define			AT91_TC_WAVESEL_UP_AUTO		(2 << 13)
-#define			AT91_TC_WAVESEL_UPDOWN		(1 << 13)
-#define			AT91_TC_WAVESEL_UPDOWN_AUTO	(3 << 13)
-#define		AT91_TC_ACPA		(3 << 16)	/* Waveform Mode: RA Compare Effect on TIOA */
-#define			AT91_TC_ACPA_NONE		(0 << 16)
-#define			AT91_TC_ACPA_SET		(1 << 16)
-#define			AT91_TC_ACPA_CLEAR		(2 << 16)
-#define			AT91_TC_ACPA_TOGGLE		(3 << 16)
-#define		AT91_TC_ACPC		(3 << 18)	/* Waveform Mode: RC Compre Effect on TIOA */
-#define			AT91_TC_ACPC_NONE		(0 << 18)
-#define			AT91_TC_ACPC_SET		(1 << 18)
-#define			AT91_TC_ACPC_CLEAR		(2 << 18)
-#define			AT91_TC_ACPC_TOGGLE		(3 << 18)
-#define		AT91_TC_AEEVT		(3 << 20)	/* Waveform Mode: External Event Effect on TIOA */
-#define			AT91_TC_AEEVT_NONE		(0 << 20)
-#define			AT91_TC_AEEVT_SET		(1 << 20)
-#define			AT91_TC_AEEVT_CLEAR		(2 << 20)
-#define			AT91_TC_AEEVT_TOGGLE		(3 << 20)
-#define		AT91_TC_ASWTRG		(3 << 22)	/* Waveform Mode: Software Trigger Effect on TIOA */
-#define			AT91_TC_ASWTRG_NONE		(0 << 22)
-#define			AT91_TC_ASWTRG_SET		(1 << 22)
-#define			AT91_TC_ASWTRG_CLEAR		(2 << 22)
-#define			AT91_TC_ASWTRG_TOGGLE		(3 << 22)
-#define		AT91_TC_BCPB		(3 << 24)	/* Waveform Mode: RB Compare Effect on TIOB */
-#define			AT91_TC_BCPB_NONE		(0 << 24)
-#define			AT91_TC_BCPB_SET		(1 << 24)
-#define			AT91_TC_BCPB_CLEAR		(2 << 24)
-#define			AT91_TC_BCPB_TOGGLE		(3 << 24)
-#define		AT91_TC_BCPC		(3 << 26)	/* Waveform Mode: RC Compare Effect on TIOB */
-#define			AT91_TC_BCPC_NONE		(0 << 26)
-#define			AT91_TC_BCPC_SET		(1 << 26)
-#define			AT91_TC_BCPC_CLEAR		(2 << 26)
-#define			AT91_TC_BCPC_TOGGLE		(3 << 26)
-#define		AT91_TC_BEEVT		(3 << 28)	/* Waveform Mode: External Event Effect on TIOB */
-#define			AT91_TC_BEEVT_NONE		(0 << 28)
-#define			AT91_TC_BEEVT_SET		(1 << 28)
-#define			AT91_TC_BEEVT_CLEAR		(2 << 28)
-#define			AT91_TC_BEEVT_TOGGLE		(3 << 28)
-#define		AT91_TC_BSWTRG		(3 << 30)	/* Waveform Mode: Software Trigger Effect on TIOB */
-#define			AT91_TC_BSWTRG_NONE		(0 << 30)
-#define			AT91_TC_BSWTRG_SET		(1 << 30)
-#define			AT91_TC_BSWTRG_CLEAR		(2 << 30)
-#define			AT91_TC_BSWTRG_TOGGLE		(3 << 30)
-
-#define AT91_TC_CV		0x10		/* Counter Value */
-#define AT91_TC_RA		0x14		/* Register A */
-#define AT91_TC_RB		0x18		/* Register B */
-#define AT91_TC_RC		0x1c		/* Register C */
-
-#define AT91_TC_SR		0x20		/* Status Register */
-#define		AT91_TC_COVFS		(1 <<  0)	/* Counter Overflow Status */
-#define		AT91_TC_LOVRS		(1 <<  1)	/* Load Overrun Status */
-#define		AT91_TC_CPAS		(1 <<  2)	/* RA Compare Status */
-#define		AT91_TC_CPBS		(1 <<  3)	/* RB Compare Status */
-#define		AT91_TC_CPCS		(1 <<  4)	/* RC Compare Status */
-#define		AT91_TC_LDRAS		(1 <<  5)	/* RA Loading Status */
-#define		AT91_TC_LDRBS		(1 <<  6)	/* RB Loading Status */
-#define		AT91_TC_ETRGS		(1 <<  7)	/* External Trigger Status */
-#define		AT91_TC_CLKSTA		(1 << 16)	/* Clock Enabling Status */
-#define		AT91_TC_MTIOA		(1 << 17)	/* TIOA Mirror */
-#define		AT91_TC_MTIOB		(1 << 18)	/* TIOB Mirror */
-
-#define AT91_TC_IER		0x24		/* Interrupt Enable Register */
-#define AT91_TC_IDR		0x28		/* Interrupt Disable Register */
-#define AT91_TC_IMR		0x2c		/* Interrupt Mask Register */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_twi.h b/include/asm-arm/arch-at91rm9200/at91_twi.h
deleted file mode 100644
index cda914f..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_twi.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_twi.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Two-wire Interface (TWI) 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 AT91_TWI_H
-#define AT91_TWI_H
-
-#define	AT91_TWI_CR		0x00		/* Control Register */
-#define		AT91_TWI_START		(1 <<  0)	/* Send a Start Condition */
-#define		AT91_TWI_STOP		(1 <<  1)	/* Send a Stop Condition */
-#define		AT91_TWI_MSEN		(1 <<  2)	/* Master Transfer Enable */
-#define		AT91_TWI_MSDIS		(1 <<  3)	/* Master Transfer Disable */
-#define		AT91_TWI_SWRST		(1 <<  7)	/* Software Reset */
-
-#define	AT91_TWI_MMR		0x04		/* Master Mode Register */
-#define		AT91_TWI_IADRSZ		(3    <<  8)	/* Internal Device Address Size */
-#define			AT91_TWI_IADRSZ_NO		(0 << 8)
-#define			AT91_TWI_IADRSZ_1		(1 << 8)
-#define			AT91_TWI_IADRSZ_2		(2 << 8)
-#define			AT91_TWI_IADRSZ_3		(3 << 8)
-#define		AT91_TWI_MREAD		(1    << 12)	/* Master Read Direction */
-#define		AT91_TWI_DADR		(0x7f << 16)	/* Device Address */
-
-#define	AT91_TWI_IADR		0x0c		/* Internal Address Register */
-
-#define	AT91_TWI_CWGR		0x10		/* Clock Waveform Generator Register */
-#define		AT91_TWI_CLDIV		(0xff <<  0)	/* Clock Low Divisor */
-#define		AT91_TWI_CHDIV		(0xff <<  8)	/* Clock High Divisor */
-#define		AT91_TWI_CKDIV		(7    << 16)	/* Clock Divider */
-
-#define	AT91_TWI_SR		0x20		/* Status Register */
-#define		AT91_TWI_TXCOMP		(1 <<  0)	/* Transmission Complete */
-#define		AT91_TWI_RXRDY		(1 <<  1)	/* Receive Holding Register Ready */
-#define		AT91_TWI_TXRDY		(1 <<  2)	/* Transmit Holding Register Ready */
-#define		AT91_TWI_OVRE		(1 <<  6)	/* Overrun Error [AT91RM9200 only] */
-#define		AT91_TWI_UNRE		(1 <<  7)	/* Underrun Error [AT91RM9200 only] */
-#define		AT91_TWI_NACK		(1 <<  8)	/* Not Acknowledged */
-
-#define	AT91_TWI_IER		0x24		/* Interrupt Enable Register */
-#define	AT91_TWI_IDR		0x28		/* Interrupt Disable Register */
-#define	AT91_TWI_IMR		0x2c		/* Interrupt Mask Register */
-#define	AT91_TWI_RHR		0x30		/* Receive Holding Register */
-#define	AT91_TWI_THR		0x34		/* Transmit Holding Register */
-
-#endif
-
diff --git a/include/asm-arm/arch-at91rm9200/at91_wdt.h b/include/asm-arm/arch-at91rm9200/at91_wdt.h
deleted file mode 100644
index ac63e77..0000000
--- a/include/asm-arm/arch-at91rm9200/at91_wdt.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_wdt.h
- *
- * Watchdog Timer (WDT) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * 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 AT91_WDT_H
-#define AT91_WDT_H
-
-#define AT91_WDT_CR		(AT91_WDT + 0x00)	/* Watchdog Control Register */
-#define		AT91_WDT_WDRSTT		(1    << 0)		/* Restart */
-#define		AT91_WDT_KEY		(0xff << 24)		/* KEY Password */
-
-#define AT91_WDT_MR		(AT91_WDT + 0x04)	/* Watchdog Mode Register */
-#define		AT91_WDT_WDV		(0xfff << 0)		/* Counter Value */
-#define		AT91_WDT_WDFIEN		(1     << 12)		/* Fault Interrupt Enable */
-#define		AT91_WDT_WDRSTEN	(1     << 13)		/* Reset Processor */
-#define		AT91_WDT_WDRPROC	(1     << 14)		/* Timer Restart */
-#define		AT91_WDT_WDDIS		(1     << 15)		/* Watchdog Disable */
-#define		AT91_WDT_WDD		(0xfff << 16)		/* Delta Value */
-#define		AT91_WDT_WDDBGHLT	(1     << 28)		/* Debug Halt */
-#define		AT91_WDT_WDIDLEHLT	(1     << 29)		/* Idle Halt */
-
-#define AT91_WDT_SR		(AT91_WDT + 0x08)	/* Watchdog Status Register */
-#define		AT91_WDT_WDUNF		(1 << 0)		/* Watchdog Underflow */
-#define		AT91_WDT_WDERR		(1 << 1)		/* Watchdog Error */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200.h b/include/asm-arm/arch-at91rm9200/at91rm9200.h
deleted file mode 100644
index c569b6a..0000000
--- a/include/asm-arm/arch-at91rm9200/at91rm9200.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91rm9200.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Common definitions.
- * 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_H
-#define AT91RM9200_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91_ID_FIQ		0	/* Advanced Interrupt Controller (FIQ) */
-#define AT91_ID_SYS		1	/* System Peripheral */
-#define AT91RM9200_ID_PIOA	2	/* Parallel IO Controller A */
-#define AT91RM9200_ID_PIOB	3	/* Parallel IO Controller B */
-#define AT91RM9200_ID_PIOC	4	/* Parallel IO Controller C */
-#define AT91RM9200_ID_PIOD	5	/* Parallel IO Controller D */
-#define AT91RM9200_ID_US0	6	/* USART 0 */
-#define AT91RM9200_ID_US1	7	/* USART 1 */
-#define AT91RM9200_ID_US2	8	/* USART 2 */
-#define AT91RM9200_ID_US3	9	/* USART 3 */
-#define AT91RM9200_ID_MCI	10	/* Multimedia Card Interface */
-#define AT91RM9200_ID_UDP	11	/* USB Device Port */
-#define AT91RM9200_ID_TWI	12	/* Two-Wire Interface */
-#define AT91RM9200_ID_SPI	13	/* Serial Peripheral Interface */
-#define AT91RM9200_ID_SSC0	14	/* Serial Synchronous Controller 0 */
-#define AT91RM9200_ID_SSC1	15	/* Serial Synchronous Controller 1 */
-#define AT91RM9200_ID_SSC2	16	/* Serial Synchronous Controller 2 */
-#define AT91RM9200_ID_TC0	17	/* Timer Counter 0 */
-#define AT91RM9200_ID_TC1	18	/* Timer Counter 1 */
-#define AT91RM9200_ID_TC2	19	/* Timer Counter 2 */
-#define AT91RM9200_ID_TC3	20	/* Timer Counter 3 */
-#define AT91RM9200_ID_TC4	21	/* Timer Counter 4 */
-#define AT91RM9200_ID_TC5	22	/* Timer Counter 5 */
-#define AT91RM9200_ID_UHP	23	/* USB Host port */
-#define AT91RM9200_ID_EMAC	24	/* Ethernet MAC */
-#define AT91RM9200_ID_IRQ0	25	/* Advanced Interrupt Controller (IRQ0) */
-#define AT91RM9200_ID_IRQ1	26	/* Advanced Interrupt Controller (IRQ1) */
-#define AT91RM9200_ID_IRQ2	27	/* Advanced Interrupt Controller (IRQ2) */
-#define AT91RM9200_ID_IRQ3	28	/* Advanced Interrupt Controller (IRQ3) */
-#define AT91RM9200_ID_IRQ4	29	/* Advanced Interrupt Controller (IRQ4) */
-#define AT91RM9200_ID_IRQ5	30	/* Advanced Interrupt Controller (IRQ5) */
-#define AT91RM9200_ID_IRQ6	31	/* Advanced Interrupt Controller (IRQ6) */
-
-
-/*
- * Peripheral physical base addresses.
- */
-#define AT91RM9200_BASE_TCB0	0xfffa0000
-#define AT91RM9200_BASE_TC0	0xfffa0000
-#define AT91RM9200_BASE_TC1	0xfffa0040
-#define AT91RM9200_BASE_TC2	0xfffa0080
-#define AT91RM9200_BASE_TCB1	0xfffa4000
-#define AT91RM9200_BASE_TC3	0xfffa4000
-#define AT91RM9200_BASE_TC4	0xfffa4040
-#define AT91RM9200_BASE_TC5	0xfffa4080
-#define AT91RM9200_BASE_UDP	0xfffb0000
-#define AT91RM9200_BASE_MCI	0xfffb4000
-#define AT91RM9200_BASE_TWI	0xfffb8000
-#define AT91RM9200_BASE_EMAC	0xfffbc000
-#define AT91RM9200_BASE_US0	0xfffc0000
-#define AT91RM9200_BASE_US1	0xfffc4000
-#define AT91RM9200_BASE_US2	0xfffc8000
-#define AT91RM9200_BASE_US3	0xfffcc000
-#define AT91RM9200_BASE_SSC0	0xfffd0000
-#define AT91RM9200_BASE_SSC1	0xfffd4000
-#define AT91RM9200_BASE_SSC2	0xfffd8000
-#define AT91RM9200_BASE_SPI	0xfffe0000
-#define AT91_BASE_SYS		0xfffff000
-
-
-/*
- * System Peripherals (offset from AT91_BASE_SYS)
- */
-#define AT91_AIC	(0xfffff000 - AT91_BASE_SYS)	/* Advanced Interrupt Controller */
-#define AT91_DBGU	(0xfffff200 - AT91_BASE_SYS)	/* Debug Unit */
-#define AT91_PIOA	(0xfffff400 - AT91_BASE_SYS)	/* PIO Controller A */
-#define AT91_PIOB	(0xfffff600 - AT91_BASE_SYS)	/* PIO Controller B */
-#define AT91_PIOC	(0xfffff800 - AT91_BASE_SYS)	/* PIO Controller C */
-#define AT91_PIOD	(0xfffffa00 - AT91_BASE_SYS)	/* PIO Controller D */
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)	/* Power Management Controller */
-#define AT91_ST		(0xfffffd00 - AT91_BASE_SYS)	/* System Timer */
-#define AT91_RTC	(0xfffffe00 - AT91_BASE_SYS)	/* Real-Time Clock */
-#define AT91_MC		(0xffffff00 - AT91_BASE_SYS)	/* Memory Controllers */
-
-#define AT91_MATRIX	0	/* not supported */
-
-/*
- * Internal Memory.
- */
-#define AT91RM9200_ROM_BASE	0x00100000	/* Internal ROM base address */
-#define AT91RM9200_ROM_SIZE	SZ_128K		/* Internal ROM size (128Kb) */
-
-#define AT91RM9200_SRAM_BASE	0x00200000	/* Internal SRAM base address */
-#define AT91RM9200_SRAM_SIZE	SZ_16K		/* Internal SRAM size (16Kb) */
-
-#define AT91RM9200_UHP_BASE	0x00300000	/* USB Host controller */
-
-
-#if 0
-/*
- * PIO pin definitions (peripheral A/B multiplexing).
- */
-#define AT91_PA0_MISO		(1 <<  0)	/* A: SPI Master-In Slave-Out */
-#define AT91_PA0_PCK3		(1 <<  0)	/* B: PMC Programmable Clock Output 3 */
-#define AT91_PA1_MOSI		(1 <<  1)	/* A: SPI Master-Out Slave-In */
-#define AT91_PA1_PCK0		(1 <<  1)	/* B: PMC Programmable Clock Output 0 */
-#define AT91_PA2_SPCK		(1 <<  2)	/* A: SPI Serial Clock */
-#define AT91_PA2_IRQ4		(1 <<  2)	/* B: External Interrupt 4 */
-#define AT91_PA3_NPCS0		(1 <<  3)	/* A: SPI Peripheral Chip Select 0 */
-#define AT91_PA3_IRQ5		(1 <<  3)	/* B: External Interrupt 5 */
-#define AT91_PA4_NPCS1		(1 <<  4)	/* A: SPI Peripheral Chip Select 1 */
-#define AT91_PA4_PCK1		(1 <<  4)	/* B: PMC Programmable Clock Output 1 */
-#define AT91_PA5_NPCS2		(1 <<  5)	/* A: SPI Peripheral Chip Select 2 */
-#define AT91_PA5_TXD3		(1 <<  5)	/* B: USART Transmit Data 3 */
-#define AT91_PA6_NPCS3		(1 <<  6)	/* A: SPI Peripheral Chip Select 3 */
-#define AT91_PA6_RXD3		(1 <<  6)	/* B: USART Receive Data 3 */
-#define AT91_PA7_ETXCK_EREFCK	(1 <<  7)	/* A: Ethernet Reference Clock / Transmit Clock */
-#define AT91_PA7_PCK2		(1 <<  7)	/* B: PMC Programmable Clock Output 2 */
-#define AT91_PA8_ETXEN		(1 <<  8)	/* A: Ethernet Transmit Enable */
-#define AT91_PA8_MCCDB		(1 <<  8)	/* B: MMC Multimedia Card B Command */
-#define AT91_PA9_ETX0		(1 <<  9)	/* A: Ethernet Transmit Data 0 */
-#define AT91_PA9_MCDB0		(1 <<  9)	/* B: MMC Multimedia Card B Data 0 */
-#define AT91_PA10_ETX1		(1 << 10)	/* A: Ethernet Transmit Data 1 */
-#define AT91_PA10_MCDB1		(1 << 10)	/* B: MMC Multimedia Card B Data 1 */
-#define AT91_PA11_ECRS_ECRSDV	(1 << 11)	/* A: Ethernet Carrier Sense / Data Valid */
-#define AT91_PA11_MCDB2		(1 << 11)	/* B: MMC Multimedia Card B Data 2 */
-#define AT91_PA12_ERX0		(1 << 12)	/* A: Ethernet Receive Data 0 */
-#define AT91_PA12_MCDB3		(1 << 12)	/* B: MMC Multimedia Card B Data 3 */
-#define AT91_PA13_ERX1		(1 << 13)	/* A: Ethernet Receive Data 1 */
-#define AT91_PA13_TCLK0		(1 << 13)	/* B: TC External Clock Input 0 */
-#define AT91_PA14_ERXER		(1 << 14)	/* A: Ethernet Receive Error */
-#define AT91_PA14_TCLK1		(1 << 14)	/* B: TC External Clock Input 1 */
-#define AT91_PA15_EMDC		(1 << 15)	/* A: Ethernet Management Data Clock */
-#define AT91_PA15_TCLK2		(1 << 15)	/* B: TC External Clock Input 2 */
-#define AT91_PA16_EMDIO		(1 << 16)	/* A: Ethernet Management Data I/O */
-#define AT91_PA16_IRQ6		(1 << 16)	/* B: External Interrupt 6 */
-#define AT91_PA17_TXD0		(1 << 17)	/* A: USART Transmit Data 0 */
-#define AT91_PA17_TIOA0		(1 << 17)	/* B: TC I/O Line A 0 */
-#define AT91_PA18_RXD0		(1 << 18)	/* A: USART Receive Data 0 */
-#define AT91_PA18_TIOB0		(1 << 18)	/* B: TC I/O Line B 0 */
-#define AT91_PA19_SCK0		(1 << 19)	/* A: USART Serial Clock 0 */
-#define AT91_PA19_TIOA1		(1 << 19)	/* B: TC I/O Line A 1 */
-#define AT91_PA20_CTS0		(1 << 20)	/* A: USART Clear To Send 0 */
-#define AT91_PA20_TIOB1		(1 << 20)	/* B: TC I/O Line B 1 */
-#define AT91_PA21_RTS0		(1 << 21)	/* A: USART Ready To Send 0 */
-#define AT91_PA21_TIOA2		(1 << 21)	/* B: TC I/O Line A 2 */
-#define AT91_PA22_RXD2		(1 << 22)	/* A: USART Receive Data 2 */
-#define AT91_PA22_TIOB2		(1 << 22)	/* B: TC I/O Line B 2 */
-#define AT91_PA23_TXD2		(1 << 23)	/* A: USART Transmit Data 2 */
-#define AT91_PA23_IRQ3		(1 << 23)	/* B: External Interrupt 3 */
-#define AT91_PA24_SCK2		(1 << 24)	/* A: USART Serial Clock 2 */
-#define AT91_PA24_PCK1		(1 << 24)	/* B: PMC Programmable Clock Output 1 */
-#define AT91_PA25_TWD		(1 << 25)	/* A: TWI Two-wire Serial Data */
-#define AT91_PA25_IRQ2		(1 << 25)	/* B: External Interrupt 2 */
-#define AT91_PA26_TWCK		(1 << 26)	/* A: TWI Two-wire Serial Clock */
-#define AT91_PA26_IRQ1		(1 << 26)	/* B: External Interrupt 1 */
-#define AT91_PA27_MCCK		(1 << 27)	/* A: MMC Multimedia Card Clock */
-#define AT91_PA27_TCLK3		(1 << 27)	/* B: TC External Clock Input 3 */
-#define AT91_PA28_MCCDA		(1 << 28)	/* A: MMC Multimedia Card A Command */
-#define AT91_PA28_TCLK4		(1 << 28)	/* B: TC External Clock Input 4 */
-#define AT91_PA29_MCDA0		(1 << 29)	/* A: MMC Multimedia Card A Data 0 */
-#define AT91_PA29_TCLK5		(1 << 29)	/* B: TC External Clock Input 5 */
-#define AT91_PA30_DRXD		(1 << 30)	/* A: DBGU Receive Data */
-#define AT91_PA30_CTS2		(1 << 30)	/* B: USART Clear To Send 2 */
-#define AT91_PA31_DTXD		(1 << 31)	/* A: DBGU Transmit Data */
-#define AT91_PA31_RTS2		(1 << 31)	/* B: USART Ready To Send 2 */
-
-#define AT91_PB0_TF0		(1 <<  0)	/* A: SSC Transmit Frame Sync 0 */
-#define AT91_PB0_RTS3		(1 <<  0)	/* B: USART Ready To Send 3 */
-#define AT91_PB1_TK0		(1 <<  1)	/* A: SSC Transmit Clock 0 */
-#define AT91_PB1_CTS3		(1 <<  1)	/* B: USART Clear To Send 3 */
-#define AT91_PB2_TD0		(1 <<  2)	/* A: SSC Transmit Data 0 */
-#define AT91_PB2_SCK3		(1 <<  2)	/* B: USART Serial Clock 3 */
-#define AT91_PB3_RD0		(1 <<  3)	/* A: SSC Receive Data 0 */
-#define AT91_PB3_MCDA1		(1 <<  3)	/* B: MMC Multimedia Card A Data 1 */
-#define AT91_PB4_RK0		(1 <<  4)	/* A: SSC Receive Clock 0 */
-#define AT91_PB4_MCDA2		(1 <<  4)	/* B: MMC Multimedia Card A Data 2 */
-#define AT91_PB5_RF0		(1 <<  5)	/* A: SSC Receive Frame Sync 0 */
-#define AT91_PB5_MCDA3		(1 <<  5)	/* B: MMC Multimedia Card A Data 3 */
-#define AT91_PB6_TF1		(1 <<  6)	/* A: SSC Transmit Frame Sync 1 */
-#define AT91_PB6_TIOA3		(1 <<  6)	/* B: TC I/O Line A 3 */
-#define AT91_PB7_TK1		(1 <<  7)	/* A: SSC Transmit Clock 1 */
-#define AT91_PB7_TIOB3		(1 <<  7)	/* B: TC I/O Line B 3 */
-#define AT91_PB8_TD1		(1 <<  8)	/* A: SSC Transmit Data 1 */
-#define AT91_PB8_TIOA4		(1 <<  8)	/* B: TC I/O Line A 4 */
-#define AT91_PB9_RD1		(1 <<  9)	/* A: SSC Receive Data 1 */
-#define AT91_PB9_TIOB4		(1 <<  9)	/* B: TC I/O Line B 4 */
-#define AT91_PB10_RK1		(1 << 10)	/* A: SSC Receive Clock 1 */
-#define AT91_PB10_TIOA5		(1 << 10)	/* B: TC I/O Line A 5 */
-#define AT91_PB11_RF1		(1 << 11)	/* A: SSC Receive Frame Sync 1 */
-#define AT91_PB11_TIOB5		(1 << 11)	/* B: TC I/O Line B 5 */
-#define AT91_PB12_TF2		(1 << 12)	/* A: SSC Transmit Frame Sync 2 */
-#define AT91_PB12_ETX2		(1 << 12)	/* B: Ethernet Transmit Data 2 */
-#define AT91_PB13_TK2		(1 << 13)	/* A: SSC Transmit Clock 3 */
-#define AT91_PB13_ETX3		(1 << 13)	/* B: Ethernet Transmit Data 3 */
-#define AT91_PB14_TD2		(1 << 14)	/* A: SSC Transmit Data 2 */
-#define AT91_PB14_ETXER		(1 << 14)	/* B: Ethernet Transmit Coding Error */
-#define AT91_PB15_RD2		(1 << 15)	/* A: SSC Receive Data 2 */
-#define AT91_PB15_ERX2		(1 << 15)	/* B: Ethernet Receive Data 2 */
-#define AT91_PB16_RK2		(1 << 16)	/* A: SSC Receive Clock 2 */
-#define AT91_PB16_ERX3		(1 << 16)	/* B: Ethernet Receive Data 3 */
-#define AT91_PB17_RF2		(1 << 17)	/* A: SSC Receive Frame Sync 2 */
-#define AT91_PB17_ERXDV		(1 << 17)	/* B: Ethernet Receive Data Valid */
-#define AT91_PB18_RI1		(1 << 18)	/* A: USART Ring Indicator 1 */
-#define AT91_PB18_ECOL		(1 << 18)	/* B: Ethernet Collision Detected */
-#define AT91_PB19_DTR1		(1 << 19)	/* A: USART Data Terminal Ready 1 */
-#define AT91_PB19_ERXCK		(1 << 19)	/* B: Ethernet Receive Clock */
-#define AT91_PB20_TXD1		(1 << 20)	/* A: USART Transmit Data 1 */
-#define AT91_PB21_RXD1		(1 << 21)	/* A: USART Receive Data 1 */
-#define AT91_PB22_SCK1		(1 << 22)	/* A: USART Serial Clock 1 */
-#define AT91_PB23_DCD1		(1 << 23)	/* A: USART Data Carrier Detect 1 */
-#define AT91_PB24_CTS1		(1 << 24)	/* A: USART Clear To Send 1 */
-#define AT91_PB25_DSR1		(1 << 25)	/* A: USART Data Set Ready 1 */
-#define AT91_PB25_EF100		(1 << 25)	/* B: Ethernet Force 100 Mbit */
-#define AT91_PB26_RTS1		(1 << 26)	/* A: USART Ready To Send 1 */
-#define AT91_PB27_PCK0		(1 << 27)	/* B: PMC Programmable Clock Output 0 */
-#define AT91_PB28_FIQ		(1 << 28)	/* A: Fast Interrupt */
-#define AT91_PB29_IRQ0		(1 << 29)	/* A: External Interrupt 0 */
-
-#define AT91_PC0_BFCK		(1 <<  0)	/* A: Burst Flash Clock */
-#define AT91_PC1_BFRDY_SMOE	(1 <<  1)	/* A: Burst Flash Ready / SmartMedia Output Enable */
-#define AT91_PC2_BFAVD		(1 <<  2)	/* A: Burst Flash Address Valid */
-#define AT91_PC3_BFBAA_SMWE	(1 <<  3)	/* A: Burst Flash Address Advance / SmartMedia Write Enable */
-#define AT91_PC4_BFOE		(1 <<  4)	/* A: Burst Flash Output Enable */
-#define AT91_PC5_BFWE		(1 <<  5)	/* A: Burst Flash Write Enable */
-#define AT91_PC6_NWAIT		(1 <<  6)	/* A: SMC Wait Signal */
-#define AT91_PC7_A23		(1 <<  7)	/* A: Address Bus 23 */
-#define AT91_PC8_A24		(1 <<  8)	/* A: Address Bus 24 */
-#define AT91_PC9_A25_CFRNW	(1 <<  9)	/* A: Address Bus 25 / Compact Flash Read Not Write */
-#define AT91_PC10_NCS4_CFCS	(1 << 10)	/* A: SMC Chip Select 4 / Compact Flash Chip Select */
-#define AT91_PC11_NCS5_CFCE1	(1 << 11)	/* A: SMC Chip Select 5 / Compact Flash Chip Enable 1 */
-#define AT91_PC12_NCS6_CFCE2	(1 << 12)	/* A: SMC Chip Select 6 / Compact Flash Chip Enable 2 */
-#define AT91_PC13_NCS7		(1 << 13)	/* A: Chip Select 7 */
-
-#define AT91_PD0_ETX0		(1 <<  0)	/* A: Ethernet Transmit Data 0 */
-#define AT91_PD1_ETX1		(1 <<  1)	/* A: Ethernet Transmit Data 1 */
-#define AT91_PD2_ETX2		(1 <<  2)	/* A: Ethernet Transmit Data 2 */
-#define AT91_PD3_ETX3		(1 <<  3)	/* A: Ethernet Transmit Data 3 */
-#define AT91_PD4_ETXEN		(1 <<  4)	/* A: Ethernet Transmit Enable */
-#define AT91_PD5_ETXER		(1 <<  5)	/* A: Ethernet Transmit Coding Error */
-#define AT91_PD6_DTXD		(1 <<  6)	/* A: DBGU Transmit Data */
-#define AT91_PD7_PCK0		(1 <<  7)	/* A: PMC Programmable Clock Output 0 */
-#define AT91_PD7_TSYNC		(1 <<  7)	/* B: ETM Trace Synchronization Signal */
-#define AT91_PD8_PCK1		(1 <<  8)	/* A: PMC Programmable Clock Output 1 */
-#define AT91_PD8_TCLK		(1 <<  8)	/* B: ETM Trace Clock */
-#define AT91_PD9_PCK2		(1 <<  9)	/* A: PMC Programmable Clock Output 2 */
-#define AT91_PD9_TPS0		(1 <<  9)	/* B: ETM Trace ARM Pipeline Status 0 */
-#define AT91_PD10_PCK3		(1 << 10)	/* A: PMC Programmable Clock Output 3 */
-#define AT91_PD10_TPS1		(1 << 10)	/* B: ETM Trace ARM Pipeline Status 1 */
-#define AT91_PD11_TPS2		(1 << 11)	/* B: ETM Trace ARM Pipeline Status 2 */
-#define AT91_PD12_TPK0		(1 << 12)	/* B: ETM Trace Packet Port 0 */
-#define AT91_PD13_TPK1		(1 << 13)	/* B: ETM Trace Packet Port 1 */
-#define AT91_PD14_TPK2		(1 << 14)	/* B: ETM Trace Packet Port 2 */
-#define AT91_PD15_TD0		(1 << 15)	/* A: SSC Transmit Data 0 */
-#define AT91_PD15_TPK3		(1 << 15)	/* B: ETM Trace Packet Port 3 */
-#define AT91_PD16_TD1		(1 << 16)	/* A: SSC Transmit Data 1 */
-#define AT91_PD16_TPK4		(1 << 16)	/* B: ETM Trace Packet Port 4 */
-#define AT91_PD17_TD2		(1 << 17)	/* A: SSC Transmit Data 2 */
-#define AT91_PD17_TPK5		(1 << 17)	/* B: ETM Trace Packet Port 5 */
-#define AT91_PD18_NPCS1		(1 << 18)	/* A: SPI Peripheral Chip Select 1 */
-#define AT91_PD18_TPK6		(1 << 18)	/* B: ETM Trace Packet Port 6 */
-#define AT91_PD19_NPCS2		(1 << 19)	/* A: SPI Peripheral Chip Select 2 */
-#define AT91_PD19_TPK7		(1 << 19)	/* B: ETM Trace Packet Port 7 */
-#define AT91_PD20_NPCS3		(1 << 20)	/* A: SPI Peripheral Chip Select 3 */
-#define AT91_PD20_TPK8		(1 << 20)	/* B: ETM Trace Packet Port 8 */
-#define AT91_PD21_RTS0		(1 << 21)	/* A: USART Ready To Send 0 */
-#define AT91_PD21_TPK9		(1 << 21)	/* B: ETM Trace Packet Port 9 */
-#define AT91_PD22_RTS1		(1 << 22)	/* A: USART Ready To Send 1 */
-#define AT91_PD22_TPK10		(1 << 22)	/* B: ETM Trace Packet Port 10 */
-#define AT91_PD23_RTS2		(1 << 23)	/* A: USART Ready To Send 2 */
-#define AT91_PD23_TPK11		(1 << 23)	/* B: ETM Trace Packet Port 11 */
-#define AT91_PD24_RTS3		(1 << 24)	/* A: USART Ready To Send 3 */
-#define AT91_PD24_TPK12		(1 << 24)	/* B: ETM Trace Packet Port 12 */
-#define AT91_PD25_DTR1		(1 << 25)	/* A: USART Data Terminal Ready 1 */
-#define AT91_PD25_TPK13		(1 << 25)	/* B: ETM Trace Packet Port 13 */
-#define AT91_PD26_TPK14		(1 << 26)	/* B: ETM Trace Packet Port 14 */
-#define AT91_PD27_TPK15		(1 << 27)	/* B: ETM Trace Packet Port 15 */
-#endif
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h b/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h
deleted file mode 100644
index fbc091e..0000000
--- a/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91rm9200_emac.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Ethernet MAC 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_EMAC_H
-#define AT91RM9200_EMAC_H
-
-#define	AT91_EMAC_CTL		0x00	/* Control Register */
-#define		AT91_EMAC_LB		(1 <<  0)	/* Loopback */
-#define		AT91_EMAC_LBL		(1 <<  1)	/* Loopback Local */
-#define		AT91_EMAC_RE		(1 <<  2)	/* Receive Enable */
-#define		AT91_EMAC_TE		(1 <<  3)	/* Transmit Enable */
-#define		AT91_EMAC_MPE		(1 <<  4)	/* Management Port Enable */
-#define		AT91_EMAC_CSR		(1 <<  5)	/* Clear Statistics Registers */
-#define		AT91_EMAC_INCSTAT	(1 <<  6)	/* Increment Statistics Registers */
-#define		AT91_EMAC_WES		(1 <<  7)	/* Write Enable for Statistics Registers */
-#define		AT91_EMAC_BP		(1 <<  8)	/* Back Pressure */
-
-#define	AT91_EMAC_CFG		0x04	/* Configuration Register */
-#define		AT91_EMAC_SPD		(1 <<  0)	/* Speed */
-#define		AT91_EMAC_FD		(1 <<  1)	/* Full Duplex */
-#define		AT91_EMAC_BR		(1 <<  2)	/* Bit Rate */
-#define		AT91_EMAC_CAF		(1 <<  4)	/* Copy All Frames */
-#define		AT91_EMAC_NBC		(1 <<  5)	/* No Broadcast */
-#define		AT91_EMAC_MTI		(1 <<  6)	/* Multicast Hash Enable */
-#define		AT91_EMAC_UNI		(1 <<  7)	/* Unicast Hash Enable */
-#define		AT91_EMAC_BIG		(1 <<  8)	/* Receive 1522 Bytes */
-#define		AT91_EMAC_EAE		(1 <<  9)	/* External Address Match Enable */
-#define		AT91_EMAC_CLK		(3 << 10)	/* MDC Clock Divisor */
-#define		AT91_EMAC_CLK_DIV8		(0 << 10)
-#define		AT91_EMAC_CLK_DIV16		(1 << 10)
-#define		AT91_EMAC_CLK_DIV32		(2 << 10)
-#define		AT91_EMAC_CLK_DIV64		(3 << 10)
-#define		AT91_EMAC_RTY		(1 << 12)	/* Retry Test */
-#define		AT91_EMAC_RMII		(1 << 13)	/* Reduce MII (RMII) */
-
-#define	AT91_EMAC_SR		0x08	/* Status Register */
-#define		AT91_EMAC_SR_LINK	(1 <<  0)	/* Link */
-#define		AT91_EMAC_SR_MDIO	(1 <<  1)	/* MDIO pin */
-#define		AT91_EMAC_SR_IDLE	(1 <<  2)	/* PHY idle */
-
-#define	AT91_EMAC_TAR		0x0c	/* Transmit Address Register */
-
-#define	AT91_EMAC_TCR		0x10	/* Transmit Control Register */
-#define		AT91_EMAC_LEN		(0x7ff << 0)	/* Transmit Frame Length */
-#define		AT91_EMAC_NCRC		(1     << 15)	/* No CRC */
-
-#define	AT91_EMAC_TSR		0x14	/* Transmit Status Register */
-#define		AT91_EMAC_TSR_OVR	(1 <<  0)	/* Transmit Buffer Overrun */
-#define		AT91_EMAC_TSR_COL	(1 <<  1)	/* Collision Occurred */
-#define		AT91_EMAC_TSR_RLE	(1 <<  2)	/* Retry Limit Exceeded */
-#define		AT91_EMAC_TSR_IDLE	(1 <<  3)	/* Transmitter Idle */
-#define		AT91_EMAC_TSR_BNQ	(1 <<  4)	/* Transmit Buffer not Queued */
-#define		AT91_EMAC_TSR_COMP	(1 <<  5)	/* Transmit Complete */
-#define		AT91_EMAC_TSR_UND	(1 <<  6)	/* Transmit Underrun */
-
-#define	AT91_EMAC_RBQP		0x18	/* Receive Buffer Queue Pointer */
-
-#define	AT91_EMAC_RSR		0x20	/* Receive Status Register */
-#define		AT91_EMAC_RSR_BNA	(1 <<  0)	/* Buffer Not Available */
-#define		AT91_EMAC_RSR_REC	(1 <<  1)	/* Frame Received */
-#define		AT91_EMAC_RSR_OVR	(1 <<  2)	/* RX Overrun */
-
-#define	AT91_EMAC_ISR		0x24	/* Interrupt Status Register */
-#define		AT91_EMAC_DONE		(1 <<  0)	/* Management Done */
-#define		AT91_EMAC_RCOM		(1 <<  1)	/* Receive Complete */
-#define		AT91_EMAC_RBNA		(1 <<  2)	/* Receive Buffer Not Available */
-#define		AT91_EMAC_TOVR		(1 <<  3)	/* Transmit Buffer Overrun */
-#define		AT91_EMAC_TUND		(1 <<  4)	/* Transmit Buffer Underrun */
-#define		AT91_EMAC_RTRY		(1 <<  5)	/* Retry Limit */
-#define		AT91_EMAC_TBRE		(1 <<  6)	/* Transmit Buffer Register Empty */
-#define		AT91_EMAC_TCOM		(1 <<  7)	/* Transmit Complete */
-#define		AT91_EMAC_TIDLE		(1 <<  8)	/* Transmit Idle */
-#define		AT91_EMAC_LINK		(1 <<  9)	/* Link */
-#define		AT91_EMAC_ROVR		(1 << 10)	/* RX Overrun */
-#define		AT91_EMAC_ABT		(1 << 11)	/* Abort */
-
-#define	AT91_EMAC_IER		0x28	/* Interrupt Enable Register */
-#define	AT91_EMAC_IDR		0x2c	/* Interrupt Disable Register */
-#define	AT91_EMAC_IMR		0x30	/* Interrupt Mask Register */
-
-#define	AT91_EMAC_MAN		0x34	/* PHY Maintenance Register */
-#define		AT91_EMAC_DATA		(0xffff << 0)	/* MDIO Data */
-#define		AT91_EMAC_REGA		(0x1f	<< 18)	/* MDIO Register */
-#define		AT91_EMAC_PHYA		(0x1f	<< 23)	/* MDIO PHY Address */
-#define		AT91_EMAC_RW		(3	<< 28)	/* Read/Write operation */
-#define			AT91_EMAC_RW_W		(1 << 28)
-#define			AT91_EMAC_RW_R		(2 << 28)
-#define		AT91_EMAC_MAN_802_3	0x40020000	/* IEEE 802.3 value */
-
-/*
- * Statistics Registers.
- */
-#define AT91_EMAC_FRA		0x40	/* Frames Transmitted OK */
-#define AT91_EMAC_SCOL		0x44	/* Single Collision Frame */
-#define AT91_EMAC_MCOL		0x48	/* Multiple Collision Frame */
-#define AT91_EMAC_OK		0x4c	/* Frames Received OK */
-#define AT91_EMAC_SEQE		0x50	/* Frame Check Sequence Error */
-#define AT91_EMAC_ALE		0x54	/* Alignmemt Error */
-#define AT91_EMAC_DTE		0x58	/* Deffered Transmission Frame */
-#define AT91_EMAC_LCOL		0x5c	/* Late Collision */
-#define AT91_EMAC_ECOL		0x60	/* Excessive Collision */
-#define AT91_EMAC_TUE		0x64	/* Transmit Underrun Error */
-#define AT91_EMAC_CSE		0x68	/* Carrier Sense Error */
-#define AT91_EMAC_DRFC		0x6c	/* Discard RX Frame */
-#define AT91_EMAC_ROV		0x70	/* Receive Overrun */
-#define AT91_EMAC_CDE		0x74	/* Code Error */
-#define AT91_EMAC_ELR		0x78	/* Excessive Length Error */
-#define AT91_EMAC_RJB		0x7c	/* Receive Jabber */
-#define AT91_EMAC_USF		0x80	/* Undersize Frame */
-#define AT91_EMAC_SQEE		0x84	/* SQE Test Error */
-
-/*
- * Address Registers.
- */
-#define AT91_EMAC_HSL		0x90	/* Hash Address Low [31:0] */
-#define AT91_EMAC_HSH		0x94	/* Hash Address High [63:32] */
-#define AT91_EMAC_SA1L		0x98	/* Specific Address 1 Low, bytes 0-3 */
-#define AT91_EMAC_SA1H		0x9c	/* Specific Address 1 High, bytes 4-5 */
-#define AT91_EMAC_SA2L		0xa0	/* Specific Address 2 Low, bytes 0-3 */
-#define AT91_EMAC_SA2H		0xa4	/* Specific Address 2 High, bytes 4-5 */
-#define AT91_EMAC_SA3L		0xa8	/* Specific Address 3 Low, bytes 0-3 */
-#define AT91_EMAC_SA3H		0xac	/* Specific Address 3 High, bytes 4-5 */
-#define AT91_EMAC_SA4L		0xb0	/* Specific Address 4 Low, bytes 0-3 */
-#define AT91_EMAC_SA4H		0xb4	/* Specific Address 4 High, bytes 4-5 */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_mc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_mc.h
deleted file mode 100644
index 0c0d814..0000000
--- a/include/asm-arm/arch-at91rm9200/at91rm9200_mc.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91rm9200_mc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Memory Controllers (MC, EBI, SMC, SDRAMC, BFC) - System peripherals 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_MC_H
-#define AT91RM9200_MC_H
-
-/* Memory Controller */
-#define AT91_MC_RCR		(AT91_MC + 0x00)	/* MC Remap Control Register */
-#define		AT91_MC_RCB		(1 <<  0)		/* Remap Command Bit */
-
-#define AT91_MC_ASR		(AT91_MC + 0x04)	/* MC Abort Status Register */
-#define		AT91_MC_UNADD		(1 <<  0)		/* Undefined Address Abort Status */
-#define		AT91_MC_MISADD		(1 <<  1)		/* Misaligned Address Abort Status */
-#define		AT91_MC_ABTSZ		(3 <<  8)		/* Abort Size Status */
-#define			AT91_MC_ABTSZ_BYTE		(0 << 8)
-#define			AT91_MC_ABTSZ_HALFWORD		(1 << 8)
-#define			AT91_MC_ABTSZ_WORD		(2 << 8)
-#define		AT91_MC_ABTTYP		(3 << 10)		/* Abort Type Status */
-#define			AT91_MC_ABTTYP_DATAREAD		(0 << 10)
-#define			AT91_MC_ABTTYP_DATAWRITE	(1 << 10)
-#define			AT91_MC_ABTTYP_FETCH		(2 << 10)
-#define		AT91_MC_MST0		(1 << 16)		/* ARM920T Abort Source */
-#define		AT91_MC_MST1		(1 << 17)		/* PDC Abort Source */
-#define		AT91_MC_MST2		(1 << 18)		/* UHP Abort Source */
-#define		AT91_MC_MST3		(1 << 19)		/* EMAC Abort Source */
-#define		AT91_MC_SVMST0		(1 << 24)		/* Saved ARM920T Abort Source */
-#define		AT91_MC_SVMST1		(1 << 25)		/* Saved PDC Abort Source */
-#define		AT91_MC_SVMST2		(1 << 26)		/* Saved UHP Abort Source */
-#define		AT91_MC_SVMST3		(1 << 27)		/* Saved EMAC Abort Source */
-
-#define AT91_MC_AASR		(AT91_MC + 0x08)	/* MC Abort Address Status Register */
-
-#define AT91_MC_MPR		(AT91_MC + 0x0c)	/* MC Master Priority Register */
-#define		AT91_MPR_MSTP0		(7 <<  0)		/* ARM920T Priority */
-#define		AT91_MPR_MSTP1		(7 <<  4)		/* PDC Priority */
-#define		AT91_MPR_MSTP2		(7 <<  8)		/* UHP Priority */
-#define		AT91_MPR_MSTP3		(7 << 12)		/* EMAC Priority */
-
-/* External Bus Interface (EBI) registers */
-#define AT91_EBI_CSA		(AT91_MC + 0x60)	/* Chip Select Assignment Register */
-#define		AT91_EBI_CS0A		(1 << 0)		/* Chip Select 0 Assignment */
-#define			AT91_EBI_CS0A_SMC		(0 << 0)
-#define			AT91_EBI_CS0A_BFC		(1 << 0)
-#define		AT91_EBI_CS1A		(1 << 1)		/* Chip Select 1 Assignment */
-#define			AT91_EBI_CS1A_SMC		(0 << 1)
-#define			AT91_EBI_CS1A_SDRAMC		(1 << 1)
-#define		AT91_EBI_CS3A		(1 << 3)		/* Chip Select 2 Assignment */
-#define			AT91_EBI_CS3A_SMC		(0 << 3)
-#define			AT91_EBI_CS3A_SMC_SMARTMEDIA	(1 << 3)
-#define		AT91_EBI_CS4A		(1 << 4)		/* Chip Select 3 Assignment */
-#define			AT91_EBI_CS4A_SMC		(0 << 4)
-#define			AT91_EBI_CS4A_SMC_COMPACTFLASH	(1 << 4)
-#define AT91_EBI_CFGR		(AT91_MC + 0x64)	/* Configuration Register */
-#define		AT91_EBI_DBPUC		(1 << 0)		/* Data Bus Pull-Up Configuration */
-
-/* Static Memory Controller (SMC) registers */
-#define	AT91_SMC_CSR(n)		(AT91_MC + 0x70 + ((n) * 4))/* SMC Chip Select Register */
-#define		AT91_SMC_NWS		(0x7f <<  0)		/* Number of Wait States */
-#define			AT91_SMC_NWS_(x)	((x) << 0)
-#define		AT91_SMC_WSEN		(1    <<  7)		/* Wait State Enable */
-#define		AT91_SMC_TDF		(0xf  <<  8)		/* Data Float Time */
-#define			AT91_SMC_TDF_(x)	((x) << 8)
-#define		AT91_SMC_BAT		(1    << 12)		/* Byte Access Type */
-#define		AT91_SMC_DBW		(3    << 13)		/* Data Bus Width */
-#define			AT91_SMC_DBW_16		(1 << 13)
-#define			AT91_SMC_DBW_8		(2 << 13)
-#define		AT91_SMC_DPR		(1 << 15)		/* Data Read Protocol */
-#define		AT91_SMC_ACSS		(3 << 16)		/* Address to Chip Select Setup */
-#define			AT91_SMC_ACSS_STD	(0 << 16)
-#define			AT91_SMC_ACSS_1		(1 << 16)
-#define			AT91_SMC_ACSS_2		(2 << 16)
-#define			AT91_SMC_ACSS_3		(3 << 16)
-#define		AT91_SMC_RWSETUP	(7 << 24)		/* Read & Write Signal Time Setup */
-#define			AT91_SMC_RWSETUP_(x)	((x) << 24)
-#define		AT91_SMC_RWHOLD		(7 << 28)		/* Read & Write Signal Hold Time */
-#define			AT91_SMC_RWHOLD_(x)	((x) << 28)
-
-/* SDRAM Controller registers */
-#define AT91_SDRAMC_MR		(AT91_MC + 0x90)	/* Mode Register */
-#define		AT91_SDRAMC_MODE	(0xf << 0)		/* Command Mode */
-#define			AT91_SDRAMC_MODE_NORMAL		(0 << 0)
-#define			AT91_SDRAMC_MODE_NOP		(1 << 0)
-#define			AT91_SDRAMC_MODE_PRECHARGE	(2 << 0)
-#define			AT91_SDRAMC_MODE_LMR		(3 << 0)
-#define			AT91_SDRAMC_MODE_REFRESH	(4 << 0)
-#define		AT91_SDRAMC_DBW		(1   << 4)		/* Data Bus Width */
-#define			AT91_SDRAMC_DBW_32	(0 << 4)
-#define			AT91_SDRAMC_DBW_16	(1 << 4)
-
-#define AT91_SDRAMC_TR		(AT91_MC + 0x94)	/* Refresh Timer Register */
-#define		AT91_SDRAMC_COUNT	(0xfff << 0)		/* Refresh Timer Count */
-
-#define AT91_SDRAMC_CR		(AT91_MC + 0x98)	/* Configuration Register */
-#define		AT91_SDRAMC_NC		(3   <<  0)		/* Number of Column Bits */
-#define			AT91_SDRAMC_NC_8	(0 << 0)
-#define			AT91_SDRAMC_NC_9	(1 << 0)
-#define			AT91_SDRAMC_NC_10	(2 << 0)
-#define			AT91_SDRAMC_NC_11	(3 << 0)
-#define		AT91_SDRAMC_NR		(3   <<  2)		/* Number of Row Bits */
-#define			AT91_SDRAMC_NR_11	(0 << 2)
-#define			AT91_SDRAMC_NR_12	(1 << 2)
-#define			AT91_SDRAMC_NR_13	(2 << 2)
-#define		AT91_SDRAMC_NB		(1   <<  4)		/* Number of Banks */
-#define			AT91_SDRAMC_NB_2	(0 << 4)
-#define			AT91_SDRAMC_NB_4	(1 << 4)
-#define		AT91_SDRAMC_CAS		(3   <<  5)		/* CAS Latency */
-#define			AT91_SDRAMC_CAS_2	(2 << 5)
-#define		AT91_SDRAMC_TWR		(0xf <<  7)		/* Write Recovery Delay */
-#define		AT91_SDRAMC_TRC		(0xf << 11)		/* Row Cycle Delay */
-#define		AT91_SDRAMC_TRP		(0xf << 15)		/* Row Precharge Delay */
-#define		AT91_SDRAMC_TRCD	(0xf << 19)		/* Row to Column Delay */
-#define		AT91_SDRAMC_TRAS	(0xf << 23)		/* Active to Precharge Delay */
-#define		AT91_SDRAMC_TXSR	(0xf << 27)		/* Exit Self Refresh to Active Delay */
-
-#define AT91_SDRAMC_SRR		(AT91_MC + 0x9c)	/* Self Refresh Register */
-#define AT91_SDRAMC_LPR		(AT91_MC + 0xa0)	/* Low Power Register */
-#define AT91_SDRAMC_IER		(AT91_MC + 0xa4)	/* Interrupt Enable Register */
-#define AT91_SDRAMC_IDR		(AT91_MC + 0xa8)	/* Interrupt Disable Register */
-#define AT91_SDRAMC_IMR		(AT91_MC + 0xac)	/* Interrupt Mask Register */
-#define AT91_SDRAMC_ISR		(AT91_MC + 0xb0)	/* Interrupt Status Register */
-
-/* Burst Flash Controller register */
-#define AT91_BFC_MR		(AT91_MC + 0xc0)	/* Mode Register */
-#define		AT91_BFC_BFCOM		(3   <<  0)		/* Burst Flash Controller Operating Mode */
-#define			AT91_BFC_BFCOM_DISABLED	(0 << 0)
-#define			AT91_BFC_BFCOM_ASYNC	(1 << 0)
-#define			AT91_BFC_BFCOM_BURST	(2 << 0)
-#define		AT91_BFC_BFCC		(3   <<  2)		/* Burst Flash Controller Clock */
-#define			AT91_BFC_BFCC_MCK	(1 << 2)
-#define			AT91_BFC_BFCC_DIV2	(2 << 2)
-#define			AT91_BFC_BFCC_DIV4	(3 << 2)
-#define		AT91_BFC_AVL		(0xf <<  4)		/* Address Valid Latency */
-#define		AT91_BFC_PAGES		(7   <<  8)		/* Page Size */
-#define			AT91_BFC_PAGES_NO_PAGE	(0 << 8)
-#define			AT91_BFC_PAGES_16	(1 << 8)
-#define			AT91_BFC_PAGES_32	(2 << 8)
-#define			AT91_BFC_PAGES_64	(3 << 8)
-#define			AT91_BFC_PAGES_128	(4 << 8)
-#define			AT91_BFC_PAGES_256	(5 << 8)
-#define			AT91_BFC_PAGES_512	(6 << 8)
-#define			AT91_BFC_PAGES_1024	(7 << 8)
-#define		AT91_BFC_OEL		(3   << 12)		/* Output Enable Latency */
-#define		AT91_BFC_BAAEN		(1   << 16)		/* Burst Address Advance Enable */
-#define		AT91_BFC_BFOEH		(1   << 17)		/* Burst Flash Output Enable Handling */
-#define		AT91_BFC_MUXEN		(1   << 18)		/* Multiplexed Bus Enable */
-#define		AT91_BFC_RDYEN		(1   << 19)		/* Ready Enable Mode */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9260.h b/include/asm-arm/arch-at91rm9200/at91sam9260.h
deleted file mode 100644
index 46f4dd6..0000000
--- a/include/asm-arm/arch-at91rm9200/at91sam9260.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91sam9260.h
- *
- * (C) 2006 Andrew Victor
- *
- * Common definitions.
- * Based on AT91SAM9260 datasheet revision A (Preliminary).
- *
- * 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 AT91SAM9260_H
-#define AT91SAM9260_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91_ID_FIQ		0	/* Advanced Interrupt Controller (FIQ) */
-#define AT91_ID_SYS		1	/* System Peripherals */
-#define AT91SAM9260_ID_PIOA	2	/* Parallel IO Controller A */
-#define AT91SAM9260_ID_PIOB	3	/* Parallel IO Controller B */
-#define AT91SAM9260_ID_PIOC	4	/* Parallel IO Controller C */
-#define AT91SAM9260_ID_ADC	5	/* Analog-to-Digital Converter */
-#define AT91SAM9260_ID_US0	6	/* USART 0 */
-#define AT91SAM9260_ID_US1	7	/* USART 1 */
-#define AT91SAM9260_ID_US2	8	/* USART 2 */
-#define AT91SAM9260_ID_MCI	9	/* Multimedia Card Interface */
-#define AT91SAM9260_ID_UDP	10	/* USB Device Port */
-#define AT91SAM9260_ID_TWI	11	/* Two-Wire Interface */
-#define AT91SAM9260_ID_SPI0	12	/* Serial Peripheral Interface 0 */
-#define AT91SAM9260_ID_SPI1	13	/* Serial Peripheral Interface 1 */
-#define AT91SAM9260_ID_SSC	14	/* Serial Synchronous Controller */
-#define AT91SAM9260_ID_TC0	17	/* Timer Counter 0 */
-#define AT91SAM9260_ID_TC1	18	/* Timer Counter 1 */
-#define AT91SAM9260_ID_TC2	19	/* Timer Counter 2 */
-#define AT91SAM9260_ID_UHP	20	/* USB Host port */
-#define AT91SAM9260_ID_EMAC	21	/* Ethernet */
-#define AT91SAM9260_ID_ISI	22	/* Image Sensor Interface */
-#define AT91SAM9260_ID_US3	23	/* USART 3 */
-#define AT91SAM9260_ID_US4	24	/* USART 4 */
-#define AT91SAM9260_ID_US5	25	/* USART 5 */
-#define AT91SAM9260_ID_TC3	26	/* Timer Counter 3 */
-#define AT91SAM9260_ID_TC4	27	/* Timer Counter 4 */
-#define AT91SAM9260_ID_TC5	28	/* Timer Counter 5 */
-#define AT91SAM9260_ID_IRQ0	29	/* Advanced Interrupt Controller (IRQ0) */
-#define AT91SAM9260_ID_IRQ1	30	/* Advanced Interrupt Controller (IRQ1) */
-#define AT91SAM9260_ID_IRQ2	31	/* Advanced Interrupt Controller (IRQ2) */
-
-
-/*
- * User Peripheral physical base addresses.
- */
-#define AT91SAM9260_BASE_TCB0		0xfffa0000
-#define AT91SAM9260_BASE_TC0		0xfffa0000
-#define AT91SAM9260_BASE_TC1		0xfffa0040
-#define AT91SAM9260_BASE_TC2		0xfffa0080
-#define AT91SAM9260_BASE_UDP		0xfffa4000
-#define AT91SAM9260_BASE_MCI		0xfffa8000
-#define AT91SAM9260_BASE_TWI		0xfffac000
-#define AT91SAM9260_BASE_US0		0xfffb0000
-#define AT91SAM9260_BASE_US1		0xfffb4000
-#define AT91SAM9260_BASE_US2		0xfffb8000
-#define AT91SAM9260_BASE_SSC		0xfffbc000
-#define AT91SAM9260_BASE_ISI		0xfffc0000
-#define AT91SAM9260_BASE_EMAC		0xfffc4000
-#define AT91SAM9260_BASE_SPI0		0xfffc8000
-#define AT91SAM9260_BASE_SPI1		0xfffcc000
-#define AT91SAM9260_BASE_US3		0xfffd0000
-#define AT91SAM9260_BASE_US4		0xfffd4000
-#define AT91SAM9260_BASE_US5		0xfffd8000
-#define AT91SAM9260_BASE_TCB1		0xfffdc000
-#define AT91SAM9260_BASE_TC3		0xfffdc000
-#define AT91SAM9260_BASE_TC4		0xfffdc040
-#define AT91SAM9260_BASE_TC5		0xfffdc080
-#define AT91SAM9260_BASE_ADC		0xfffe0000
-#define AT91_BASE_SYS			0xffffe800
-
-/*
- * System Peripherals (offset from AT91_BASE_SYS)
- */
-#define AT91_ECC	(0xffffe800 - AT91_BASE_SYS)
-#define AT91_SDRAMC	(0xffffea00 - AT91_BASE_SYS)
-#define AT91_SMC	(0xffffec00 - AT91_BASE_SYS)
-#define AT91_MATRIX	(0xffffee00 - AT91_BASE_SYS)
-#define AT91_CCFG	(0xffffef10 - AT91_BASE_SYS)
-#define AT91_AIC	(0xfffff000 - AT91_BASE_SYS)
-#define AT91_DBGU	(0xfffff200 - AT91_BASE_SYS)
-#define AT91_PIOA	(0xfffff400 - AT91_BASE_SYS)
-#define AT91_PIOB	(0xfffff600 - AT91_BASE_SYS)
-#define AT91_PIOC	(0xfffff800 - AT91_BASE_SYS)
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
-#define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
-#define AT91_RTT	(0xfffffd20 - AT91_BASE_SYS)
-#define AT91_PIT	(0xfffffd30 - AT91_BASE_SYS)
-#define AT91_WDT	(0xfffffd40 - AT91_BASE_SYS)
-#define AT91_GPBR	(0xfffffd50 - AT91_BASE_SYS)
-
-
-/*
- * Internal Memory.
- */
-#define AT91SAM9260_ROM_BASE	0x00100000	/* Internal ROM base address */
-#define AT91SAM9260_ROM_SIZE	SZ_32K		/* Internal ROM size (32Kb) */
-
-#define AT91SAM9260_SRAM0_BASE	0x00200000	/* Internal SRAM 0 base address */
-#define AT91SAM9260_SRAM0_SIZE	SZ_4K		/* Internal SRAM 0 size (4Kb) */
-#define AT91SAM9260_SRAM1_BASE	0x00300000	/* Internal SRAM 1 base address */
-#define AT91SAM9260_SRAM1_SIZE	SZ_4K		/* Internal SRAM 1 size (4Kb) */
-
-#define AT91SAM9260_UHP_BASE	0x00500000	/* USB Host controller */
-
-#if 0
-/*
- * PIO pin definitions (peripheral A/B multiplexing).
- */
-
-// TODO: Add
-
-#endif
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h b/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
deleted file mode 100644
index 78f6b49..0000000
--- a/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
- *
- * Memory Controllers (MATRIX, EBI) - System peripherals registers.
- * Based on AT91SAM9260 datasheet revision B.
- *
- * 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 AT91SAM9260_MATRIX_H
-#define AT91SAM9260_MATRIX_H
-
-#define AT91_MATRIX_MCFG0	(AT91_MATRIX + 0x00)	/* Master Configuration Register 0 */
-#define AT91_MATRIX_MCFG1	(AT91_MATRIX + 0x04)	/* Master Configuration Register 1 */
-#define AT91_MATRIX_MCFG2	(AT91_MATRIX + 0x08)	/* Master Configuration Register 2 */
-#define AT91_MATRIX_MCFG3	(AT91_MATRIX + 0x0C)	/* Master Configuration Register 3 */
-#define AT91_MATRIX_MCFG4	(AT91_MATRIX + 0x10)	/* Master Configuration Register 4 */
-#define AT91_MATRIX_MCFG5	(AT91_MATRIX + 0x04)	/* Master Configuration Register 5 */
-#define		AT91_MATRIX_ULBT		(7 << 0)	/* Undefined Length Burst Type */
-#define			AT91_MATRIX_ULBT_INFINITE	(0 << 0)
-#define			AT91_MATRIX_ULBT_SINGLE		(1 << 0)
-#define			AT91_MATRIX_ULBT_FOUR		(2 << 0)
-#define			AT91_MATRIX_ULBT_EIGHT		(3 << 0)
-#define			AT91_MATRIX_ULBT_SIXTEEN	(4 << 0)
-
-#define AT91_MATRIX_SCFG0	(AT91_MATRIX + 0x40)	/* Slave Configuration Register 0 */
-#define AT91_MATRIX_SCFG1	(AT91_MATRIX + 0x44)	/* Slave Configuration Register 1 */
-#define AT91_MATRIX_SCFG2	(AT91_MATRIX + 0x48)	/* Slave Configuration Register 2 */
-#define AT91_MATRIX_SCFG3	(AT91_MATRIX + 0x4C)	/* Slave Configuration Register 3 */
-#define AT91_MATRIX_SCFG4	(AT91_MATRIX + 0x50)	/* Slave Configuration Register 4 */
-#define		AT91_MATRIX_SLOT_CYCLE		(0xff <<  0)	/* Maximum Number of Allowed Cycles for a Burst */
-#define		AT91_MATRIX_DEFMSTR_TYPE	(3    << 16)	/* Default Master Type */
-#define			AT91_MATRIX_DEFMSTR_TYPE_NONE	(0 << 16)
-#define			AT91_MATRIX_DEFMSTR_TYPE_LAST	(1 << 16)
-#define			AT91_MATRIX_DEFMSTR_TYPE_FIXED	(2 << 16)
-#define		AT91_MATRIX_FIXED_DEFMSTR	(7    << 18)	/* Fixed Index of Default Master */
-#define		AT91_MATRIX_ARBT		(3    << 24)	/* Arbitration Type */
-#define			AT91_MATRIX_ARBT_ROUND_ROBIN	(0 << 24)
-#define			AT91_MATRIX_ARBT_FIXED_PRIORITY	(1 << 24)
-
-#define AT91_MATRIX_PRAS0	(AT91_MATRIX + 0x80)	/* Priority Register A for Slave 0 */
-#define AT91_MATRIX_PRAS1	(AT91_MATRIX + 0x88)	/* Priority Register A for Slave 1 */
-#define AT91_MATRIX_PRAS2	(AT91_MATRIX + 0x90)	/* Priority Register A for Slave 2 */
-#define AT91_MATRIX_PRAS3	(AT91_MATRIX + 0x98)	/* Priority Register A for Slave 3 */
-#define AT91_MATRIX_PRAS4	(AT91_MATRIX + 0xA0)	/* Priority Register A for Slave 4 */
-#define		AT91_MATRIX_M0PR		(3 << 0)	/* Master 0 Priority */
-#define		AT91_MATRIX_M1PR		(3 << 4)	/* Master 1 Priority */
-#define		AT91_MATRIX_M2PR		(3 << 8)	/* Master 2 Priority */
-#define		AT91_MATRIX_M3PR		(3 << 12)	/* Master 3 Priority */
-#define		AT91_MATRIX_M4PR		(3 << 16)	/* Master 4 Priority */
-#define		AT91_MATRIX_M5PR		(3 << 20)	/* Master 5 Priority */
-
-#define AT91_MATRIX_MRCR	(AT91_MATRIX + 0x100)	/* Master Remap Control Register */
-#define		AT91_MATRIX_RCB0		(1 << 0)	/* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
-#define		AT91_MATRIX_RCB1		(1 << 1)	/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
-
-#define AT91_MATRIX_EBICSA	(AT91_MATRIX + 0x11C)	/* EBI Chip Select Assignment Register */
-#define		AT91_MATRIX_CS1A		(1 << 1)	/* Chip Select 1 Assignment */
-#define			AT91_MATRIX_CS1A_SMC		(0 << 1)
-#define			AT91_MATRIX_CS1A_SDRAMC		(1 << 1)
-#define		AT91_MATRIX_CS3A		(1 << 3)	/* Chip Select 3 Assignment */
-#define			AT91_MATRIX_CS3A_SMC		(0 << 3)
-#define			AT91_MATRIX_CS3A_SMC_SMARTMEDIA	(1 << 3)
-#define		AT91_MATRIX_CS4A		(1 << 4)	/* Chip Select 4 Assignment */
-#define			AT91_MATRIX_CS4A_SMC		(0 << 4)
-#define			AT91_MATRIX_CS4A_SMC_CF1	(1 << 4)
-#define		AT91_MATRIX_CS5A		(1 << 5 )	/* Chip Select 5 Assignment */
-#define			AT91_MATRIX_CS5A_SMC		(0 << 5)
-#define			AT91_MATRIX_CS5A_SMC_CF2	(1 << 5)
-#define		AT91_MATRIX_DBPUC		(1 << 8)	/* Data Bus Pull-up Configuration */
-#define		AT91_MATRIX_VDDIOMSEL		(1 << 16)	/* Memory voltage selection */
-#define			AT91_MATRIX_VDDIOMSEL_1_8V	(0 << 16)
-#define			AT91_MATRIX_VDDIOMSEL_3_3V	(1 << 16)
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9261.h b/include/asm-arm/arch-at91rm9200/at91sam9261.h
deleted file mode 100644
index 8d39672..0000000
--- a/include/asm-arm/arch-at91rm9200/at91sam9261.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91sam9261.h
- *
- * Copyright (C) SAN People
- *
- * Common definitions.
- * Based on AT91SAM9261 datasheet revision E. (Preliminary)
- *
- * 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 AT91SAM9261_H
-#define AT91SAM9261_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91_ID_FIQ		0	/* Advanced Interrupt Controller (FIQ) */
-#define AT91_ID_SYS		1	/* System Peripherals */
-#define AT91SAM9261_ID_PIOA	2	/* Parallel IO Controller A */
-#define AT91SAM9261_ID_PIOB	3	/* Parallel IO Controller B */
-#define AT91SAM9261_ID_PIOC	4	/* Parallel IO Controller C */
-#define AT91SAM9261_ID_US0	6	/* USART 0 */
-#define AT91SAM9261_ID_US1	7	/* USART 1 */
-#define AT91SAM9261_ID_US2	8	/* USART 2 */
-#define AT91SAM9261_ID_MCI	9	/* Multimedia Card Interface */
-#define AT91SAM9261_ID_UDP	10	/* USB Device Port */
-#define AT91SAM9261_ID_TWI	11	/* Two-Wire Interface */
-#define AT91SAM9261_ID_SPI0	12	/* Serial Peripheral Interface 0 */
-#define AT91SAM9261_ID_SPI1	13	/* Serial Peripheral Interface 1 */
-#define AT91SAM9261_ID_SSC0	14	/* Serial Synchronous Controller 0 */
-#define AT91SAM9261_ID_SSC1	15	/* Serial Synchronous Controller 1 */
-#define AT91SAM9261_ID_SSC2	16	/* Serial Synchronous Controller 2 */
-#define AT91SAM9261_ID_TC0	17	/* Timer Counter 0 */
-#define AT91SAM9261_ID_TC1	18	/* Timer Counter 1 */
-#define AT91SAM9261_ID_TC2	19	/* Timer Counter 2 */
-#define AT91SAM9261_ID_UHP	20	/* USB Host port */
-#define AT91SAM9261_ID_LCDC	21	/* LDC Controller */
-#define AT91SAM9261_ID_IRQ0	29	/* Advanced Interrupt Controller (IRQ0) */
-#define AT91SAM9261_ID_IRQ1	30	/* Advanced Interrupt Controller (IRQ1) */
-#define AT91SAM9261_ID_IRQ2	31	/* Advanced Interrupt Controller (IRQ2) */
-
-
-/*
- * User Peripheral physical base addresses.
- */
-#define AT91SAM9261_BASE_TCB0		0xfffa0000
-#define AT91SAM9261_BASE_TC0		0xfffa0000
-#define AT91SAM9261_BASE_TC1		0xfffa0040
-#define AT91SAM9261_BASE_TC2		0xfffa0080
-#define AT91SAM9261_BASE_UDP		0xfffa4000
-#define AT91SAM9261_BASE_MCI		0xfffa8000
-#define AT91SAM9261_BASE_TWI		0xfffac000
-#define AT91SAM9261_BASE_US0		0xfffb0000
-#define AT91SAM9261_BASE_US1		0xfffb4000
-#define AT91SAM9261_BASE_US2		0xfffb8000
-#define AT91SAM9261_BASE_SSC0		0xfffbc000
-#define AT91SAM9261_BASE_SSC1		0xfffc0000
-#define AT91SAM9261_BASE_SSC2		0xfffc4000
-#define AT91SAM9261_BASE_SPI0		0xfffc8000
-#define AT91SAM9261_BASE_SPI1		0xfffcc000
-#define AT91_BASE_SYS			0xffffea00
-
-
-/*
- * System Peripherals (offset from AT91_BASE_SYS)
- */
-#define AT91_SDRAMC	(0xffffea00 - AT91_BASE_SYS)
-#define AT91_SMC	(0xffffec00 - AT91_BASE_SYS)
-#define AT91_MATRIX	(0xffffee00 - AT91_BASE_SYS)
-#define AT91_AIC	(0xfffff000 - AT91_BASE_SYS)
-#define AT91_DBGU	(0xfffff200 - AT91_BASE_SYS)
-#define AT91_PIOA	(0xfffff400 - AT91_BASE_SYS)
-#define AT91_PIOB	(0xfffff600 - AT91_BASE_SYS)
-#define AT91_PIOC	(0xfffff800 - AT91_BASE_SYS)
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
-#define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
-#define AT91_RTT	(0xfffffd20 - AT91_BASE_SYS)
-#define AT91_PIT	(0xfffffd30 - AT91_BASE_SYS)
-#define AT91_WDT	(0xfffffd40 - AT91_BASE_SYS)
-#define AT91_GPBR	(0xfffffd50 - AT91_BASE_SYS)
-
-
-/*
- * Internal Memory.
- */
-#define AT91SAM9261_SRAM_BASE	0x00300000	/* Internal SRAM base address */
-#define AT91SAM9261_SRAM_SIZE	0x00028000	/* Internal SRAM size (160Kb) */
-
-#define AT91SAM9261_ROM_BASE	0x00400000	/* Internal ROM base address */
-#define AT91SAM9261_ROM_SIZE	SZ_32K		/* Internal ROM size (32Kb) */
-
-#define AT91SAM9261_UHP_BASE	0x00500000	/* USB Host controller */
-#define AT91SAM9261_LCDC_BASE	0x00600000	/* LDC controller */
-
-
-#if 0
-/*
- * PIO pin definitions (peripheral A/B multiplexing).
- */
-#define AT91_PA0_SPI0_MISO	(1 <<  0)	/* A: SPI0 Master In Slave */
-#define AT91_PA0_MCDA0		(1 <<  0)	/* B: Multimedia Card A Data 0 */
-#define AT91_PA1_SPI0_MOSI	(1 <<  1)	/* A: SPI0 Master Out Slave */
-#define AT91_PA1_MCCDA		(1 <<  1)	/* B: Multimedia Card A Command */
-#define AT91_PA2_SPI0_SPCK	(1 <<  2)	/* A: SPI0 Serial Clock */
-#define AT91_PA2_MCCK		(1 <<  2)	/* B: Multimedia Card Clock */
-#define AT91_PA3_SPI0_NPCS0	(1 <<  3)	/* A: SPI0 Peripheral Chip Select 0 */
-#define AT91_PA4_SPI0_NPCS1	(1 <<  4)	/* A: SPI0 Peripheral Chip Select 1 */
-#define AT91_PA4_MCDA1		(1 <<  4)	/* B: Multimedia Card A Data 1 */
-#define AT91_PA5_SPI0_NPCS2	(1 <<  5)	/* A: SPI0 Peripheral Chip Select 2 */
-#define AT91_PA5_MCDA2		(1 <<  5)	/* B: Multimedia Card A Data 2 */
-#define AT91_PA6_SPI0_NPCS3	(1 <<  6)	/* A: SPI0 Peripheral Chip Select 3 */
-#define AT91_PA6_MCDA3		(1 <<  6)	/* B: Multimedia Card A Data 3 */
-#define AT91_PA7_TWD		(1 <<  7)	/* A: TWI Two-wire Serial Data */
-#define AT91_PA7_PCK0		(1 <<  7)	/* B: PMC Programmable clock Output 0 */
-#define AT91_PA8_TWCK		(1 <<  8)	/* A: TWI Two-wire Serial Clock */
-#define AT91_PA8_PCK1		(1 <<  8)	/* B: PMC Programmable clock Output 1 */
-#define AT91_PA9_DRXD		(1 <<  9)	/* A: DBGU Debug Receive Data */
-#define AT91_PA9_PCK2		(1 <<  9)	/* B: PMC Programmable clock Output 2 */
-#define AT91_PA10_DTXD		(1 << 10)	/* A: DBGU Debug Transmit Data */
-#define AT91_PA10_PCK3		(1 << 10)	/* B: PMC Programmable clock Output 3 */
-#define AT91_PA11_TSYNC		(1 << 11)	/* A: Trace Synchronization Signal */
-#define AT91_PA11_SCK1		(1 << 11)	/* B: USART1 Serial Clock */
-#define AT91_PA12_TCLK		(1 << 12)	/* A: Trace Clock */
-#define AT91_PA12_RTS1		(1 << 12)	/* B: USART1 Ready To Send */
-#define AT91_PA13_TPS0		(1 << 13)	/* A: Trace ARM Pipeline Status 0 */
-#define AT91_PA13_CTS1		(1 << 13)	/* B: USART1 Clear To Send */
-#define AT91_PA14_TPS1		(1 << 14)	/* A: Trace ARM Pipeline Status 1 */
-#define AT91_PA14_SCK2		(1 << 14)	/* B: USART2 Serial Clock */
-#define AT91_PA15_TPS2		(1 << 15)	/* A: Trace ARM Pipeline Status 2 */
-#define AT91_PA15_RTS2		(1 << 15)	/* B: USART2 Ready To Send */
-#define AT91_PA16_TPK0		(1 << 16)	/* A: Trace Packet Port 0 */
-#define AT91_PA16_CTS2		(1 << 16)	/* B: USART2 Clear To Send */
-#define AT91_PA17_TPK1		(1 << 17)	/* A: Trace Packet Port 1 */
-#define AT91_PA17_TF1		(1 << 17)	/* B: SSC1 Transmit Frame Sync */
-#define AT91_PA18_TPK2		(1 << 18)	/* A: Trace Packet Port 2 */
-#define AT91_PA18_TK1		(1 << 18)	/* B: SSC1 Transmit Clock */
-#define AT91_PA19_TPK3		(1 << 19)	/* A: Trace Packet Port 3 */
-#define AT91_PA19_TD1		(1 << 19)	/* B: SSC1 Transmit Data */
-#define AT91_PA20_TPK4		(1 << 20)	/* A: Trace Packet Port 4 */
-#define AT91_PA20_RD1		(1 << 20)	/* B: SSC1 Receive Data */
-#define AT91_PA21_TPK5		(1 << 21)	/* A: Trace Packet Port 5 */
-#define AT91_PA21_RK1		(1 << 21)	/* B: SSC1 Receive Clock */
-#define AT91_PA22_TPK6		(1 << 22)	/* A: Trace Packet Port 6 */
-#define AT91_PA22_RF1		(1 << 22)	/* B: SSC1 Receive Frame Sync */
-#define AT91_PA23_TPK7		(1 << 23)	/* A: Trace Packet Port 7 */
-#define AT91_PA23_RTS0		(1 << 23)	/* B: USART0 Ready To Send */
-#define AT91_PA24_TPK8		(1 << 24)	/* A: Trace Packet Port 8 */
-#define AT91_PA24_SPI1_NPCS1	(1 << 24)	/* B: SPI1 Peripheral Chip Select 1 */
-#define AT91_PA25_TPK9		(1 << 25)	/* A: Trace Packet Port 9 */
-#define AT91_PA25_SPI1_NPCS2	(1 << 25)	/* B: SPI1 Peripheral Chip Select 2 */
-#define AT91_PA26_TPK10		(1 << 26)	/* A: Trace Packet Port 10 */
-#define AT91_PA26_SPI1_NPCS3	(1 << 26)	/* B: SPI1 Peripheral Chip Select 3 */
-#define AT91_PA27_TPK11		(1 << 27)	/* A: Trace Packet Port 11 */
-#define AT91_PA27_SPI0_NPCS1	(1 << 27)	/* B: SPI0 Peripheral Chip Select 1 */
-#define AT91_PA28_TPK12		(1 << 28)	/* A: Trace Packet Port 12 */
-#define AT91_PA28_SPI0_NPCS2	(1 << 28)	/* B: SPI0 Peripheral Chip Select 2 */
-#define AT91_PA29_TPK13		(1 << 29)	/* A: Trace Packet Port 13 */
-#define AT91_PA29_SPI0_NPCS3	(1 << 29)	/* B: SPI0 Peripheral Chip Select 3 */
-#define AT91_PA30_TPK14		(1 << 30)	/* A: Trace Packet Port 14 */
-#define AT91_PA30_A23		(1 << 30)	/* B: Address Bus bit 23 */
-#define AT91_PA31_TPK15		(1 << 31)	/* A: Trace Packet Port 15 */
-#define AT91_PA31_A24		(1 << 31)	/* B: Address Bus bit 24 */
-
-#define AT91_PB0_LCDVSYNC	(1 <<  0)	/* A: LCD Vertical Synchronization */
-#define AT91_PB1_LCDHSYNC	(1 <<  1)	/* A: LCD Horizontal Synchronization */
-#define AT91_PB2_LCDDOTCK	(1 <<  2)	/* A: LCD Dot Clock */
-#define AT91_PB2_PCK0		(1 <<  2)	/* B: PMC Programmable clock Output 0 */
-#define AT91_PB3_LCDDEN		(1 <<  3)	/* A: LCD Data Enable */
-#define AT91_PB4_LCDCC		(1 <<  4)	/* A: LCD Contrast Control */
-#define AT91_PB4_LCDD2		(1 <<  4)	/* B: LCD Data Bus Bit 2 */
-#define AT91_PB5_LCDD0		(1 <<  5)	/* A: LCD Data Bus Bit 0 */
-#define AT91_PB5_LCDD3		(1 <<  5)	/* B: LCD Data Bus Bit 3 */
-#define AT91_PB6_LCDD1		(1 <<  6)	/* A: LCD Data Bus Bit 1 */
-#define AT91_PB6_LCDD4		(1 <<  6)	/* B: LCD Data Bus Bit 4 */
-#define AT91_PB7_LCDD2		(1 <<  7)	/* A: LCD Data Bus Bit 2 */
-#define AT91_PB7_LCDD5		(1 <<  7)	/* B: LCD Data Bus Bit 5 */
-#define AT91_PB8_LCDD3		(1 <<  8)	/* A: LCD Data Bus Bit 3 */
-#define AT91_PB8_LCDD6		(1 <<  8)	/* B: LCD Data Bus Bit 6 */
-#define AT91_PB9_LCDD4		(1 <<  9)	/* A: LCD Data Bus Bit 4 */
-#define AT91_PB9_LCDD7		(1 <<  9)	/* B: LCD Data Bus Bit 7 */
-#define AT91_PB10_LCDD5		(1 << 10)	/* A: LCD Data Bus Bit 5 */
-#define AT91_PB10_LCDD10	(1 << 10)	/* B: LCD Data Bus Bit 10 */
-#define AT91_PB11_LCDD6		(1 << 11)	/* A: LCD Data Bus Bit 6 */
-#define AT91_PB11_LCDD11	(1 << 11)	/* B: LCD Data Bus Bit 11 */
-#define AT91_PB12_LCDD7		(1 << 12)	/* A: LCD Data Bus Bit 7 */
-#define AT91_PB12_LCDD12	(1 << 12)	/* B: LCD Data Bus Bit 12 */
-#define AT91_PB13_LCDD8		(1 << 13)	/* A: LCD Data Bus Bit 8 */
-#define AT91_PB13_LCDD13	(1 << 13)	/* B: LCD Data Bus Bit 13 */
-#define AT91_PB14_LCDD9		(1 << 14)	/* A: LCD Data Bus Bit 9 */
-#define AT91_PB14_LCDD14	(1 << 14)	/* B: LCD Data Bus Bit 14 */
-#define AT91_PB15_LCDD10	(1 << 15)	/* A: LCD Data Bus Bit 10 */
-#define AT91_PB15_LCDD15	(1 << 15)	/* B: LCD Data Bus Bit 15 */
-#define AT91_PB16_LCDD11	(1 << 16)	/* A: LCD Data Bus Bit 11 */
-#define AT91_PB16_LCDD19	(1 << 16)	/* B: LCD Data Bus Bit 19 */
-#define AT91_PB17_LCDD12	(1 << 17)	/* A: LCD Data Bus Bit 12 */
-#define AT91_PB17_LCDD20	(1 << 17)	/* B: LCD Data Bus Bit 20 */
-#define AT91_PB18_LCDD13	(1 << 18)	/* A: LCD Data Bus Bit 13 */
-#define AT91_PB18_LCDD21	(1 << 18)	/* B: LCD Data Bus Bit 21 */
-#define AT91_PB19_LCDD14	(1 << 19)	/* A: LCD Data Bus Bit 14 */
-#define AT91_PB19_LCDD22	(1 << 19)	/* B: LCD Data Bus Bit 22 */
-#define AT91_PB20_LCDD15	(1 << 20)	/* A: LCD Data Bus Bit 15 */
-#define AT91_PB20_LCDD23	(1 << 20)	/* B: LCD Data Bus Bit 23 */
-#define AT91_PB21_TF0		(1 << 21)	/* A: SSC0 Transmit Frame Sync */
-#define AT91_PB21_LCDD16	(1 << 21)	/* B: LCD Data Bus Bit 16 */
-#define AT91_PB22_TK0		(1 << 22)	/* A: SSC0 Transmit Clock */
-#define AT91_PB22_LCDD17	(1 << 22)	/* B: LCD Data Bus Bit 17 */
-#define AT91_PB23_TD0		(1 << 23)	/* A: SSC0 Transmit Data */
-#define AT91_PB23_LCDD18	(1 << 23)	/* B: LCD Data Bus Bit 18 */
-#define AT91_PB24_RD0		(1 << 24)	/* A: SSC0 Receive Data */
-#define AT91_PB24_LCDD19	(1 << 24)	/* B: LCD Data Bus Bit 19 */
-#define AT91_PB25_RK0		(1 << 25)	/* A: SSC0 Receive Clock */
-#define AT91_PB25_LCDD20	(1 << 25)	/* B: LCD Data Bus Bit 20 */
-#define AT91_PB26_RF0		(1 << 26)	/* A: SSC0 Receive Frame Sync */
-#define AT91_PB26_LCDD21	(1 << 26)	/* B: LCD Data Bus Bit 21 */
-#define AT91_PB27_SPI1_NPCS1	(1 << 27)	/* A: SPI1 Peripheral Chip Select 1 */
-#define AT91_PB27_LCDD22	(1 << 27)	/* B: LCD Data Bus Bit 22 */
-#define AT91_PB28_SPI1_NPCS0	(1 << 28)	/* A: SPI1 Peripheral Chip Select 0 */
-#define AT91_PB28_LCDD23	(1 << 28)	/* B: LCD Data Bus Bit 23 */
-#define AT91_PB29_SPI1_SPCK	(1 << 29)	/* A: SPI1 Serial Clock */
-#define AT91_PB29_IRQ2		(1 << 29)	/* B: Interrupt input 2 */
-#define AT91_PB30_SPI1_MISO	(1 << 30)	/* A: SPI1 Master In Slave */
-#define AT91_PB30_IRQ1		(1 << 30)	/* B: Interrupt input 1 */
-#define AT91_PB31_SPI1_MOSI	(1 << 31)	/* A: SPI1 Master Out Slave */
-#define AT91_PB31_PCK2		(1 << 31)	/* B: PMC Programmable clock Output 2 */
-
-#define AT91_PC0_SMOE		(1 << 0)	/* A: SmartMedia Output Enable */
-#define AT91_PC0_NCS6		(1 << 0)	/* B: Chip Select 6 */
-#define AT91_PC1_SMWE		(1 << 1)	/* A: SmartMedia Write Enable */
-#define AT91_PC1_NCS7		(1 << 1)	/* B: Chip Select 7 */
-#define AT91_PC2_NWAIT		(1 << 2)	/* A: NWAIT */
-#define AT91_PC2_IRQ0		(1 << 2)	/* B: Interrupt input 0 */
-#define AT91_PC3_A25_CFRNW	(1 << 3)	/* A: Address Bus[25] / Compact Flash Read Not Write */
-#define AT91_PC4_NCS4_CFCS0	(1 << 4)	/* A: Chip Select 4 / CompactFlash Chip Select 0 */
-#define AT91_PC5_NCS5_CFCS1	(1 << 5)	/* A: Chip Select 5 / CompactFlash Chip Select 1 */
-#define AT91_PC6_CFCE1		(1 << 6)	/* A: CompactFlash Chip Enable 1 */
-#define AT91_PC7_CFCE2		(1 << 7)	/* A: CompactFlash Chip Enable 2 */
-#define AT91_PC8_TXD0		(1 << 8)	/* A: USART0 Transmit Data */
-#define AT91_PC8_PCK2		(1 << 8)	/* B: PMC Programmable clock Output 2 */
-#define AT91_PC9_RXD0		(1 << 9)	/* A: USART0 Receive Data */
-#define AT91_PC9_PCK3		(1 << 9)	/* B: PMC Programmable clock Output 3 */
-#define AT91_PC10_RTS0		(1 << 10)	/* A: USART0 Ready To Send */
-#define AT91_PC10_SCK0		(1 << 10)	/* B: USART0 Serial Clock */
-#define AT91_PC11_CTS0		(1 << 11)	/* A: USART0 Clear To Send */
-#define AT91_PC11_FIQ		(1 << 11)	/* B: AIC Fast Interrupt Input */
-#define AT91_PC12_TXD1		(1 << 12)	/* A: USART1 Transmit Data */
-#define AT91_PC12_NCS6		(1 << 12)	/* B: Chip Select 6 */
-#define AT91_PC13_RXD1		(1 << 13)	/* A: USART1 Receive Data */
-#define AT91_PC13_NCS7		(1 << 13)	/* B: Chip Select 7 */
-#define AT91_PC14_TXD2		(1 << 14)	/* A: USART2 Transmit Data */
-#define AT91_PC14_SPI1_NPCS2	(1 << 14)	/* B: SPI1 Peripheral Chip Select 2 */
-#define AT91_PC15_RXD2		(1 << 15)	/* A: USART2 Receive Data */
-#define AT91_PC15_SPI1_NPCS3	(1 << 15)	/* B: SPI1 Peripheral Chip Select 3 */
-#define AT91_PC16_D16		(1 << 16)	/* A: Data Bus [16] */
-#define AT91_PC16_TCLK0		(1 << 16)	/* B: Timer Counter 0 external clock input */
-#define AT91_PC17_D17		(1 << 17)	/* A: Data Bus [17] */
-#define AT91_PC17_TCLK1		(1 << 17)	/* B: Timer Counter 1 external clock input */
-#define AT91_PC18_D18		(1 << 18)	/* A: Data Bus [18] */
-#define AT91_PC18_TCLK2		(1 << 18)	/* B: Timer Counter 2 external clock input */
-#define AT91_PC19_D19		(1 << 19)	/* A: Data Bus [19] */
-#define AT91_PC19_TIOA0		(1 << 19)	/* B: Timer Counter 0 Multipurpose Timer I/O Pin A */
-#define AT91_PC20_D20		(1 << 20)	/* A: Data Bus [20] */
-#define AT91_PC20_TIOB0		(1 << 20)	/* B: Timer Counter 0 Multipurpose Timer I/O Pin B */
-#define AT91_PC21_D21		(1 << 21)	/* A: Data Bus [21] */
-#define AT91_PC21_TIOA1		(1 << 21)	/* B: Timer Counter 1 Multipurpose Timer I/O Pin A */
-#define AT91_PC22_D22		(1 << 22)	/* A: Data Bus [22] */
-#define AT91_PC22_TIOB1		(1 << 22)	/* B: Timer Counter 1 Multipurpose Timer I/O Pin B */
-#define AT91_PC23_D23		(1 << 23)	/* A: Data Bus [23] */
-#define AT91_PC23_TIOA2		(1 << 23)	/* B: Timer Counter 2 Multipurpose Timer I/O Pin A */
-#define AT91_PC24_D24		(1 << 24)	/* A: Data Bus [24] */
-#define AT91_PC24_TIOB2		(1 << 24)	/* B: Timer Counter 2 Multipurpose Timer I/O Pin B */
-#define AT91_PC25_D25		(1 << 25)	/* A: Data Bus [25] */
-#define AT91_PC25_TF2		(1 << 25)	/* B: SSC2 Transmit Frame Sync */
-#define AT91_PC26_D26		(1 << 26)	/* A: Data Bus [26] */
-#define AT91_PC26_TK2		(1 << 26)	/* B: SSC2 Transmit Clock */
-#define AT91_PC27_D27		(1 << 27)	/* A: Data Bus [27] */
-#define AT91_PC27_TD2		(1 << 27)	/* B: SSC2 Transmit Data */
-#define AT91_PC28_D28		(1 << 28)	/* A: Data Bus [28] */
-#define AT91_PC28_RD2		(1 << 28)	/* B: SSC2 Receive Data */
-#define AT91_PC29_D29		(1 << 29)	/* A: Data Bus [29] */
-#define AT91_PC29_RK2		(1 << 29)	/* B: SSC2 Receive Clock */
-#define AT91_PC30_D30		(1 << 30)	/* A: Data Bus [30] */
-#define AT91_PC30_RF2		(1 << 30)	/* B: SSC2 Receive Frame Sync */
-#define AT91_PC31_D31		(1 << 31)	/* A: Data Bus [31] */
-#define AT91_PC31_PCK1		(1 << 31)	/* B: PMC Programmable clock Output 1 */
-#endif
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h b/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
deleted file mode 100644
index ec88efa..0000000
--- a/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
- *
- * Memory Controllers (MATRIX, EBI) - System peripherals registers.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * 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 AT91SAM9261_MATRIX_H
-#define AT91SAM9261_MATRIX_H
-
-#define AT91_MATRIX_MCFG	(AT91_MATRIX + 0x00)	/* Master Configuration Register */
-#define		AT91_MATRIX_RCB0	(1 << 0)		/* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
-#define		AT91_MATRIX_RCB1	(1 << 1)		/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
-
-#define AT91_MATRIX_SCFG0	(AT91_MATRIX + 0x04)	/* Slave Configuration Register 0 */
-#define AT91_MATRIX_SCFG1	(AT91_MATRIX + 0x08)	/* Slave Configuration Register 1 */
-#define AT91_MATRIX_SCFG2	(AT91_MATRIX + 0x0C)	/* Slave Configuration Register 2 */
-#define AT91_MATRIX_SCFG3	(AT91_MATRIX + 0x10)	/* Slave Configuration Register 3 */
-#define AT91_MATRIX_SCFG4	(AT91_MATRIX + 0x14)	/* Slave Configuration Register 4 */
-#define		AT91_MATRIX_SLOT_CYCLE		(0xff << 0)	/* Maximum Number of Allowed Cycles for a Burst */
-#define		AT91_MATRIX_DEFMSTR_TYPE	(3    << 16)	/* Default Master Type */
-#define			AT91_MATRIX_DEFMSTR_TYPE_NONE	(0 << 16)
-#define			AT91_MATRIX_DEFMSTR_TYPE_LAST	(1 << 16)
-#define			AT91_MATRIX_DEFMSTR_TYPE_FIXED	(2 << 16)
-#define		AT91_MATRIX_FIXED_DEFMSTR	(7    << 18)	/* Fixed Index of Default Master */
-
-#define AT91_MATRIX_TCR		(AT91_MATRIX + 0x24)	/* TCM Configuration Register */
-#define		AT91_MATRIX_ITCM_SIZE		(0xf << 0)	/* Size of ITCM enabled memory block */
-#define			AT91_MATRIX_ITCM_0		(0 << 0)
-#define			AT91_MATRIX_ITCM_16		(5 << 0)
-#define			AT91_MATRIX_ITCM_32		(6 << 0)
-#define			AT91_MATRIX_ITCM_64		(7 << 0)
-#define		AT91_MATRIX_DTCM_SIZE		(0xf << 4)	/* Size of DTCM enabled memory block */
-#define			AT91_MATRIX_DTCM_0		(0 << 4)
-#define			AT91_MATRIX_DTCM_16		(5 << 4)
-#define			AT91_MATRIX_DTCM_32		(6 << 4)
-#define			AT91_MATRIX_DTCM_64		(7 << 4)
-
-#define AT91_MATRIX_EBICSA	(AT91_MATRIX + 0x30)	/* EBI Chip Select Assignment Register */
-#define		AT91_MATRIX_CS1A		(1 << 1)	/* Chip Select 1 Assignment */
-#define			AT91_MATRIX_CS1A_SMC		(0 << 1)
-#define			AT91_MATRIX_CS1A_SDRAMC		(1 << 1)
-#define		AT91_MATRIX_CS3A		(1 << 3)	/* Chip Select 3 Assignment */
-#define			AT91_MATRIX_CS3A_SMC		(0 << 3)
-#define			AT91_MATRIX_CS3A_SMC_SMARTMEDIA	(1 << 3)
-#define		AT91_MATRIX_CS4A		(1 << 4)	/* Chip Select 4 Assignment */
-#define			AT91_MATRIX_CS4A_SMC		(0 << 4)
-#define			AT91_MATRIX_CS4A_SMC_CF1	(1 << 4)
-#define		AT91_MATRIX_CS5A		(1 << 5)	/* Chip Select 5 Assignment */
-#define			AT91_MATRIX_CS5A_SMC		(0 << 5)
-#define			AT91_MATRIX_CS5A_SMC_CF2	(1 << 5)
-#define		AT91_MATRIX_DBPUC		(1 << 8)	/* Data Bus Pull-up Configuration */
-
-#define AT91_MATRIX_USBPUCR	(AT91_MATRIX + 0x34)	/* USB Pad Pull-Up Control Register */
-#define		AT91_MATRIX_USBPUCR_PUON	(1 << 30)	/* USB Device PAD Pull-up Enable */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h b/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
deleted file mode 100644
index 972e753..0000000
--- a/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
- *
- * Memory Controllers (SMC, SDRAMC) - System peripherals registers.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * 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 AT91SAM926x_MC_H
-#define AT91SAM926x_MC_H
-
-/* SDRAM Controller (SDRAMC) registers */
-#define AT91_SDRAMC_MR		(AT91_SDRAMC + 0x00)	/* SDRAM Controller Mode Register */
-#define		AT91_SDRAMC_MODE	(0xf << 0)		/* Command Mode */
-#define			AT91_SDRAMC_MODE_NORMAL		0
-#define			AT91_SDRAMC_MODE_NOP		1
-#define			AT91_SDRAMC_MODE_PRECHARGE	2
-#define			AT91_SDRAMC_MODE_LMR		3
-#define			AT91_SDRAMC_MODE_REFRESH	4
-#define			AT91_SDRAMC_MODE_EXT_LMR	5
-#define			AT91_SDRAMC_MODE_DEEP		6
-
-#define AT91_SDRAMC_TR		(AT91_SDRAMC + 0x04)	/* SDRAM Controller Refresh Timer Register */
-#define		AT91_SDRAMC_COUNT	(0xfff << 0)		/* Refresh Timer Counter */
-
-#define AT91_SDRAMC_CR		(AT91_SDRAMC + 0x08)	/* SDRAM Controller Configuration Register */
-#define		AT91_SDRAMC_NC		(3 << 0)		/* Number of Column Bits */
-#define			AT91_SDRAMC_NC_8	(0 << 0)
-#define			AT91_SDRAMC_NC_9	(1 << 0)
-#define			AT91_SDRAMC_NC_10	(2 << 0)
-#define			AT91_SDRAMC_NC_11	(3 << 0)
-#define		AT91_SDRAMC_NR		(3 << 2)		/* Number of Row Bits */
-#define			AT91_SDRAMC_NR_11	(0 << 2)
-#define			AT91_SDRAMC_NR_12	(1 << 2)
-#define			AT91_SDRAMC_NR_13	(2 << 2)
-#define		AT91_SDRAMC_NB		(1 << 4)		/* Number of Banks */
-#define			AT91_SDRAMC_NB_2	(0 << 4)
-#define			AT91_SDRAMC_NB_4	(1 << 4)
-#define		AT91_SDRAMC_CAS		(3 << 5)		/* CAS Latency */
-#define			AT91_SDRAMC_CAS_1	(1 << 5)
-#define			AT91_SDRAMC_CAS_2	(2 << 5)
-#define			AT91_SDRAMC_CAS_3	(3 << 5)
-#define		AT91_SDRAMC_DBW		(1 << 7)		/* Data Bus Width */
-#define			AT91_SDRAMC_DBW_32	(0 << 7)
-#define			AT91_SDRAMC_DBW_16	(1 << 7)
-#define		AT91_SDRAMC_TWR		(0xf <<  8)		/* Write Recovery Delay */
-#define		AT91_SDRAMC_TRC		(0xf << 12)		/* Row Cycle Delay */
-#define		AT91_SDRAMC_TRP		(0xf << 16)		/* Row Precharge Delay */
-#define		AT91_SDRAMC_TRCD	(0xf << 20)		/* Row to Column Delay */
-#define		AT91_SDRAMC_TRAS	(0xf << 24)		/* Active to Precharge Delay */
-#define		AT91_SDRAMC_TXSR	(0xf << 28)		/* Exit Self Refresh to Active Delay */
-
-#define AT91_SDRAMC_LPR		(AT91_SDRAMC + 0x10)	/* SDRAM Controller Low Power Register */
-#define		AT91_SDRAMC_LPCB		(3 << 0)	/* Low-power Configurations */
-#define			AT91_SDRAMC_LPCB_DISABLE		0
-#define			AT91_SDRAMC_LPCB_SELF_REFRESH		1
-#define			AT91_SDRAMC_LPCB_POWER_DOWN		2
-#define			AT91_SDRAMC_LPCB_DEEP_POWER_DOWN	3
-#define		AT91_SDRAMC_PASR		(7 << 4)	/* Partial Array Self Refresh */
-#define		AT91_SDRAMC_TCSR		(3 << 8)	/* Temperature Compensated Self Refresh */
-#define		AT91_SDRAMC_DS			(3 << 10)	/* Drive Strenght */
-#define		AT91_SDRAMC_TIMEOUT		(3 << 12)	/* Time to define when Low Power Mode is enabled */
-#define			AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES	(0 << 12)
-#define			AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES	(1 << 12)
-#define			AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES	(2 << 12)
-
-#define AT91_SDRAMC_IER		(AT91_SDRAMC + 0x14)	/* SDRAM Controller Interrupt Enable Register */
-#define AT91_SDRAMC_IDR		(AT91_SDRAMC + 0x18)	/* SDRAM Controller Interrupt Disable Register */
-#define AT91_SDRAMC_IMR		(AT91_SDRAMC + 0x1C)	/* SDRAM Controller Interrupt Mask Register */
-#define AT91_SDRAMC_ISR		(AT91_SDRAMC + 0x20)	/* SDRAM Controller Interrupt Status Register */
-#define		AT91_SDRAMC_RES		(1 << 0)		/* Refresh Error Status */
-
-#define AT91_SDRAMC_MDR		(AT91_SDRAMC + 0x24)	/* SDRAM Memory Device Register */
-#define		AT91_SDRAMC_MD		(3 << 0)		/* Memory Device Type */
-#define			AT91_SDRAMC_MD_SDRAM		0
-#define			AT91_SDRAMC_MD_LOW_POWER_SDRAM	1
-
-
-/* Static Memory Controller (SMC) registers */
-#define AT91_SMC_SETUP(n)	(AT91_SMC + 0x00 + ((n)*0x10))	/* Setup Register for CS n */
-#define		AT91_SMC_NWESETUP	(0x3f << 0)			/* NWE Setup Length */
-#define			AT91_SMC_NWESETUP_(x)	((x) << 0)
-#define		AT91_SMC_NCS_WRSETUP	(0x3f << 8)			/* NCS Setup Length in Write Access */
-#define			AT91_SMC_NCS_WRSETUP_(x)	((x) << 8)
-#define		AT91_SMC_NRDSETUP	(0x3f << 16)			/* NRD Setup Length */
-#define			AT91_SMC_NRDSETUP_(x)	((x) << 16)
-#define		AT91_SMC_NCS_RDSETUP	(0x3f << 24)			/* NCS Setup Length in Read Access */
-#define			AT91_SMC_NCS_RDSETUP_(x)	((x) << 24)
-
-#define AT91_SMC_PULSE(n)	(AT91_SMC + 0x04 + ((n)*0x10))	/* Pulse Register for CS n */
-#define		AT91_SMC_NWEPULSE	(0x7f <<  0)			/* NWE Pulse Length */
-#define			AT91_SMC_NWEPULSE_(x)	((x) << 0)
-#define		AT91_SMC_NCS_WRPULSE	(0x7f <<  8)			/* NCS Pulse Length in Write Access */
-#define			AT91_SMC_NCS_WRPULSE_(x)((x) << 8)
-#define		AT91_SMC_NRDPULSE	(0x7f << 16)			/* NRD Pulse Length */
-#define			AT91_SMC_NRDPULSE_(x)	((x) << 16)
-#define		AT91_SMC_NCS_RDPULSE	(0x7f << 24)			/* NCS Pulse Length in Read Access */
-#define			AT91_SMC_NCS_RDPULSE_(x)((x) << 24)
-
-#define AT91_SMC_CYCLE(n)	(AT91_SMC + 0x08 + ((n)*0x10))	/* Cycle Register for CS n */
-#define		AT91_SMC_NWECYCLE	(0x1ff << 0 )			/* Total Write Cycle Length */
-#define			AT91_SMC_NWECYCLE_(x)	((x) << 0)
-#define		AT91_SMC_NRDCYCLE	(0x1ff << 16)			/* Total Read Cycle Length */
-#define			AT91_SMC_NRDCYCLE_(x)	((x) << 16)
-
-#define AT91_SMC_MODE(n)	(AT91_SMC + 0x0c + ((n)*0x10))	/* Mode Register for CS n */
-#define		AT91_SMC_READMODE	(1 <<  0)			/* Read Mode */
-#define		AT91_SMC_WRITEMODE	(1 <<  1)			/* Write Mode */
-#define		AT91_SMC_EXNWMODE	(3 <<  4)			/* NWAIT Mode */
-#define			AT91_SMC_EXNWMODE_DISABLE	(0 << 4)
-#define			AT91_SMC_EXNWMODE_FROZEN	(2 << 4)
-#define			AT91_SMC_EXNWMODE_READY		(3 << 4)
-#define		AT91_SMC_BAT		(1 <<  8)			/* Byte Access Type */
-#define			AT91_SMC_BAT_SELECT		(0 << 8)
-#define			AT91_SMC_BAT_WRITE		(1 << 8)
-#define		AT91_SMC_DBW		(3 << 12)			/* Data Bus Width */
-#define			AT91_SMC_DBW_8			(0 << 12)
-#define			AT91_SMC_DBW_16			(1 << 12)
-#define			AT91_SMC_DBW_32			(2 << 12)
-#define		AT91_SMC_TDF		(0xf << 16)			/* Data Float Time. */
-#define			AT91_SMC_TDF_(x)		((x) << 16)
-#define		AT91_SMC_TDFMODE	(1 << 20)			/* TDF Optimization - Enabled */
-#define		AT91_SMC_PMEN		(1 << 24)			/* Page Mode Enabled */
-#define		AT91_SMC_PS		(3 << 28)			/* Page Size */
-#define			AT91_SMC_PS_4			(0 << 28)
-#define			AT91_SMC_PS_8			(1 << 28)
-#define			AT91_SMC_PS_16			(2 << 28)
-#define			AT91_SMC_PS_32			(3 << 28)
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h
deleted file mode 100644
index 768e0fc..0000000
--- a/include/asm-arm/arch-at91rm9200/board.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/board.h
- *
- *  Copyright (C) 2005 HP Labs
- *
- * 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
- */
-
-/*
- * These are data structures found in platform_device.dev.platform_data,
- * and describing board-specific data needed by drivers.  For example,
- * which pin is used for a given GPIO role.
- *
- * In 2.6, drivers should strongly avoid board-specific knowledge so
- * that supporting new boards normally won't require driver patches.
- * Most board-specific knowledge should be in arch/.../board-*.c files.
- */
-
-#ifndef __ASM_ARCH_BOARD_H
-#define __ASM_ARCH_BOARD_H
-
-#include <linux/mtd/partitions.h>
-#include <linux/device.h>
-#include <linux/spi/spi.h>
-
- /* USB Device */
-struct at91_udc_data {
-	u8	vbus_pin;		/* high == host powering us */
-	u8	pullup_pin;		/* high == D+ pulled up */
-};
-extern void __init at91_add_device_udc(struct at91_udc_data *data);
-
- /* Compact Flash */
-struct at91_cf_data {
-	u8	irq_pin;		/* I/O IRQ */
-	u8	det_pin;		/* Card detect */
-	u8	vcc_pin;		/* power switching */
-	u8	rst_pin;		/* card reset */
-	u8	chipselect;		/* EBI Chip Select number */
-};
-extern void __init at91_add_device_cf(struct at91_cf_data *data);
-
- /* MMC / SD */
-struct at91_mmc_data {
-	u8		det_pin;	/* card detect IRQ */
-	unsigned	slot_b:1;	/* uses Slot B */
-	unsigned	wire4:1;	/* (SD) supports DAT0..DAT3 */
-	u8		wp_pin;		/* (SD) writeprotect detect */
-	u8		vcc_pin;	/* power switching (high == on) */
-};
-extern void __init at91_add_device_mmc(struct at91_mmc_data *data);
-
- /* Ethernet */
-struct at91_eth_data {
-	u8		phy_irq_pin;	/* PHY IRQ */
-	u8		is_rmii;	/* using RMII interface? */
-};
-extern void __init at91_add_device_eth(struct at91_eth_data *data);
-
- /* USB Host */
-struct at91_usbh_data {
-	u8		ports;		/* number of ports on root hub */
-};
-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 */
-	u8		bus_width_16;	/* buswidth is 16 bit */
-	struct mtd_partition* (*partition_info)(int, int*);
-};
-extern void __init at91_add_device_nand(struct at91_nand_data *data);
-
- /* I2C*/
-extern void __init at91_add_device_i2c(void);
-
- /* SPI */
-extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices);
-
- /* Serial */
-struct at91_uart_config {
-	unsigned short	console_tty;	/* tty number of serial console */
-	unsigned short	nr_tty;		/* number of serial tty's */
-	short		tty_map[];	/* map UART to tty number */
-};
-extern struct platform_device *atmel_default_console_device;
-extern void __init at91_init_serial(struct at91_uart_config *config);
-
-struct atmel_uart_data {
-	short		use_dma_tx;	/* use transmit DMA? */
-	short		use_dma_rx;	/* use receive DMA? */
-	void __iomem	*regs;		/* virtual base address, if any */
-};
-extern void __init at91_add_device_serial(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/cpu.h b/include/asm-arm/arch-at91rm9200/cpu.h
deleted file mode 100644
index 6f8d09b..0000000
--- a/include/asm-arm/arch-at91rm9200/cpu.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/cpu.h
- *
- *  Copyright (C) 2006 SAN People
- *
- * 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 __ASM_ARCH_CPU_H
-#define __ASM_ARCH_CPU_H
-
-#include <asm/hardware.h>
-#include <asm/arch/at91_dbgu.h>
-
-
-#define ARCH_ID_AT91RM9200	0x09290780
-#define ARCH_ID_AT91SAM9260	0x019803a0
-#define ARCH_ID_AT91SAM9261	0x019703a0
-
-
-static inline unsigned long at91_cpu_identify(void)
-{
-	return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
-}
-
-
-#ifdef CONFIG_ARCH_AT91RM9200
-#define cpu_is_at91rm9200()	(at91_cpu_identify() == ARCH_ID_AT91RM9200)
-#else
-#define cpu_is_at91rm9200()	(0)
-#endif
-
-#ifdef CONFIG_ARCH_AT91SAM9260
-#define cpu_is_at91sam9260()	(at91_cpu_identify() == ARCH_ID_AT91SAM9260)
-#else
-#define cpu_is_at91sam9260()	(0)
-#endif
-
-#ifdef CONFIG_ARCH_AT91SAM9261
-#define cpu_is_at91sam9261()	(at91_cpu_identify() == ARCH_ID_AT91SAM9261)
-#else
-#define cpu_is_at91sam9261()	(0)
-#endif
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/debug-macro.S b/include/asm-arm/arch-at91rm9200/debug-macro.S
deleted file mode 100644
index 85cdadf..0000000
--- a/include/asm-arm/arch-at91rm9200/debug-macro.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/debug-macro.S
- *
- *  Copyright (C) 2003-2005 SAN People
- *
- * Debugging macro include header
- *
- * 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 <asm/hardware.h>
-#include <asm/arch/at91_dbgu.h>
-
-	.macro	addruart,rx
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1				@ MMU enabled?
-	ldreq	\rx, =AT91_BASE_SYS		@ System peripherals (phys address)
-	ldrne	\rx, =AT91_VA_BASE_SYS		@ System peripherals (virt address)
-	.endm
-
-	.macro	senduart,rd,rx
-	strb	\rd, [\rx, #AT91_DBGU_THR]	@ Write to Transmitter Holding Register
-	.endm
-
-	.macro	waituart,rd,rx
-1001:	ldr	\rd, [\rx, #AT91_DBGU_SR]	@ Read Status Register
-	tst	\rd, #AT91_DBGU_TXRDY		@ DBGU_TXRDY = 1 when ready to transmit
-	beq	1001b
-	.endm
-
-	.macro	busyuart,rd,rx
-1001:	ldr	\rd, [\rx, #AT91_DBGU_SR]	@ Read Status Register
-	tst	\rd, #AT91_DBGU_TXEMPTY		@ DBGU_TXEMPTY = 1 when transmission complete
-	beq	1001b
-	.endm
-
diff --git a/include/asm-arm/arch-at91rm9200/dma.h b/include/asm-arm/arch-at91rm9200/dma.h
deleted file mode 100644
index 22c1dfd..0000000
--- a/include/asm-arm/arch-at91rm9200/dma.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/dma.h
- *
- *  Copyright (C) 2003 SAN People
- *
- * 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
- */
diff --git a/include/asm-arm/arch-at91rm9200/entry-macro.S b/include/asm-arm/arch-at91rm9200/entry-macro.S
index 57248a7..0e0aadf2 100644
--- a/include/asm-arm/arch-at91rm9200/entry-macro.S
+++ b/include/asm-arm/arch-at91rm9200/entry-macro.S
@@ -16,6 +16,12 @@
 	.macro	disable_fiq
 	.endm
 
+	.macro  get_irqnr_preamble, base, tmp
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 	ldr	\base, =(AT91_VA_BASE_SYS)		@ base virtual address of SYS peripherals
 	ldr	\irqnr, [\base, #AT91_AIC_IVR]		@ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
diff --git a/include/asm-arm/arch-at91rm9200/gpio.h b/include/asm-arm/arch-at91rm9200/gpio.h
deleted file mode 100644
index a011d27..0000000
--- a/include/asm-arm/arch-at91rm9200/gpio.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/gpio.h
- *
- *  Copyright (C) 2005 HP Labs
- *
- * 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 __ASM_ARCH_AT91RM9200_GPIO_H
-#define __ASM_ARCH_AT91RM9200_GPIO_H
-
-#include <asm/irq.h>
-
-#define PIN_BASE		NR_AIC_IRQS
-
-#define MAX_GPIO_BANKS		4
-
-/* these pin numbers double as IRQ numbers, like AT91xxx_ID_* values */
-
-#define	AT91_PIN_PA0	(PIN_BASE + 0x00 + 0)
-#define	AT91_PIN_PA1	(PIN_BASE + 0x00 + 1)
-#define	AT91_PIN_PA2	(PIN_BASE + 0x00 + 2)
-#define	AT91_PIN_PA3	(PIN_BASE + 0x00 + 3)
-#define	AT91_PIN_PA4	(PIN_BASE + 0x00 + 4)
-
-#define	AT91_PIN_PA5	(PIN_BASE + 0x00 + 5)
-#define	AT91_PIN_PA6	(PIN_BASE + 0x00 + 6)
-#define	AT91_PIN_PA7	(PIN_BASE + 0x00 + 7)
-#define	AT91_PIN_PA8	(PIN_BASE + 0x00 + 8)
-#define	AT91_PIN_PA9	(PIN_BASE + 0x00 + 9)
-
-#define	AT91_PIN_PA10	(PIN_BASE + 0x00 + 10)
-#define	AT91_PIN_PA11	(PIN_BASE + 0x00 + 11)
-#define	AT91_PIN_PA12	(PIN_BASE + 0x00 + 12)
-#define	AT91_PIN_PA13	(PIN_BASE + 0x00 + 13)
-#define	AT91_PIN_PA14	(PIN_BASE + 0x00 + 14)
-
-#define	AT91_PIN_PA15	(PIN_BASE + 0x00 + 15)
-#define	AT91_PIN_PA16	(PIN_BASE + 0x00 + 16)
-#define	AT91_PIN_PA17	(PIN_BASE + 0x00 + 17)
-#define	AT91_PIN_PA18	(PIN_BASE + 0x00 + 18)
-#define	AT91_PIN_PA19	(PIN_BASE + 0x00 + 19)
-
-#define	AT91_PIN_PA20	(PIN_BASE + 0x00 + 20)
-#define	AT91_PIN_PA21	(PIN_BASE + 0x00 + 21)
-#define	AT91_PIN_PA22	(PIN_BASE + 0x00 + 22)
-#define	AT91_PIN_PA23	(PIN_BASE + 0x00 + 23)
-#define	AT91_PIN_PA24	(PIN_BASE + 0x00 + 24)
-
-#define	AT91_PIN_PA25	(PIN_BASE + 0x00 + 25)
-#define	AT91_PIN_PA26	(PIN_BASE + 0x00 + 26)
-#define	AT91_PIN_PA27	(PIN_BASE + 0x00 + 27)
-#define	AT91_PIN_PA28	(PIN_BASE + 0x00 + 28)
-#define	AT91_PIN_PA29	(PIN_BASE + 0x00 + 29)
-
-#define	AT91_PIN_PA30	(PIN_BASE + 0x00 + 30)
-#define	AT91_PIN_PA31	(PIN_BASE + 0x00 + 31)
-
-#define	AT91_PIN_PB0	(PIN_BASE + 0x20 + 0)
-#define	AT91_PIN_PB1	(PIN_BASE + 0x20 + 1)
-#define	AT91_PIN_PB2	(PIN_BASE + 0x20 + 2)
-#define	AT91_PIN_PB3	(PIN_BASE + 0x20 + 3)
-#define	AT91_PIN_PB4	(PIN_BASE + 0x20 + 4)
-
-#define	AT91_PIN_PB5	(PIN_BASE + 0x20 + 5)
-#define	AT91_PIN_PB6	(PIN_BASE + 0x20 + 6)
-#define	AT91_PIN_PB7	(PIN_BASE + 0x20 + 7)
-#define	AT91_PIN_PB8	(PIN_BASE + 0x20 + 8)
-#define	AT91_PIN_PB9	(PIN_BASE + 0x20 + 9)
-
-#define	AT91_PIN_PB10	(PIN_BASE + 0x20 + 10)
-#define	AT91_PIN_PB11	(PIN_BASE + 0x20 + 11)
-#define	AT91_PIN_PB12	(PIN_BASE + 0x20 + 12)
-#define	AT91_PIN_PB13	(PIN_BASE + 0x20 + 13)
-#define	AT91_PIN_PB14	(PIN_BASE + 0x20 + 14)
-
-#define	AT91_PIN_PB15	(PIN_BASE + 0x20 + 15)
-#define	AT91_PIN_PB16	(PIN_BASE + 0x20 + 16)
-#define	AT91_PIN_PB17	(PIN_BASE + 0x20 + 17)
-#define	AT91_PIN_PB18	(PIN_BASE + 0x20 + 18)
-#define	AT91_PIN_PB19	(PIN_BASE + 0x20 + 19)
-
-#define	AT91_PIN_PB20	(PIN_BASE + 0x20 + 20)
-#define	AT91_PIN_PB21	(PIN_BASE + 0x20 + 21)
-#define	AT91_PIN_PB22	(PIN_BASE + 0x20 + 22)
-#define	AT91_PIN_PB23	(PIN_BASE + 0x20 + 23)
-#define	AT91_PIN_PB24	(PIN_BASE + 0x20 + 24)
-
-#define	AT91_PIN_PB25	(PIN_BASE + 0x20 + 25)
-#define	AT91_PIN_PB26	(PIN_BASE + 0x20 + 26)
-#define	AT91_PIN_PB27	(PIN_BASE + 0x20 + 27)
-#define	AT91_PIN_PB28	(PIN_BASE + 0x20 + 28)
-#define	AT91_PIN_PB29	(PIN_BASE + 0x20 + 29)
-
-#define	AT91_PIN_PB30	(PIN_BASE + 0x20 + 30)
-#define	AT91_PIN_PB31	(PIN_BASE + 0x20 + 31)
-
-#define	AT91_PIN_PC0	(PIN_BASE + 0x40 + 0)
-#define	AT91_PIN_PC1	(PIN_BASE + 0x40 + 1)
-#define	AT91_PIN_PC2	(PIN_BASE + 0x40 + 2)
-#define	AT91_PIN_PC3	(PIN_BASE + 0x40 + 3)
-#define	AT91_PIN_PC4	(PIN_BASE + 0x40 + 4)
-
-#define	AT91_PIN_PC5	(PIN_BASE + 0x40 + 5)
-#define	AT91_PIN_PC6	(PIN_BASE + 0x40 + 6)
-#define	AT91_PIN_PC7	(PIN_BASE + 0x40 + 7)
-#define	AT91_PIN_PC8	(PIN_BASE + 0x40 + 8)
-#define	AT91_PIN_PC9	(PIN_BASE + 0x40 + 9)
-
-#define	AT91_PIN_PC10	(PIN_BASE + 0x40 + 10)
-#define	AT91_PIN_PC11	(PIN_BASE + 0x40 + 11)
-#define	AT91_PIN_PC12	(PIN_BASE + 0x40 + 12)
-#define	AT91_PIN_PC13	(PIN_BASE + 0x40 + 13)
-#define	AT91_PIN_PC14	(PIN_BASE + 0x40 + 14)
-
-#define	AT91_PIN_PC15	(PIN_BASE + 0x40 + 15)
-#define	AT91_PIN_PC16	(PIN_BASE + 0x40 + 16)
-#define	AT91_PIN_PC17	(PIN_BASE + 0x40 + 17)
-#define	AT91_PIN_PC18	(PIN_BASE + 0x40 + 18)
-#define	AT91_PIN_PC19	(PIN_BASE + 0x40 + 19)
-
-#define	AT91_PIN_PC20	(PIN_BASE + 0x40 + 20)
-#define	AT91_PIN_PC21	(PIN_BASE + 0x40 + 21)
-#define	AT91_PIN_PC22	(PIN_BASE + 0x40 + 22)
-#define	AT91_PIN_PC23	(PIN_BASE + 0x40 + 23)
-#define	AT91_PIN_PC24	(PIN_BASE + 0x40 + 24)
-
-#define	AT91_PIN_PC25	(PIN_BASE + 0x40 + 25)
-#define	AT91_PIN_PC26	(PIN_BASE + 0x40 + 26)
-#define	AT91_PIN_PC27	(PIN_BASE + 0x40 + 27)
-#define	AT91_PIN_PC28	(PIN_BASE + 0x40 + 28)
-#define	AT91_PIN_PC29	(PIN_BASE + 0x40 + 29)
-
-#define	AT91_PIN_PC30	(PIN_BASE + 0x40 + 30)
-#define	AT91_PIN_PC31	(PIN_BASE + 0x40 + 31)
-
-#define	AT91_PIN_PD0	(PIN_BASE + 0x60 + 0)
-#define	AT91_PIN_PD1	(PIN_BASE + 0x60 + 1)
-#define	AT91_PIN_PD2	(PIN_BASE + 0x60 + 2)
-#define	AT91_PIN_PD3	(PIN_BASE + 0x60 + 3)
-#define	AT91_PIN_PD4	(PIN_BASE + 0x60 + 4)
-
-#define	AT91_PIN_PD5	(PIN_BASE + 0x60 + 5)
-#define	AT91_PIN_PD6	(PIN_BASE + 0x60 + 6)
-#define	AT91_PIN_PD7	(PIN_BASE + 0x60 + 7)
-#define	AT91_PIN_PD8	(PIN_BASE + 0x60 + 8)
-#define	AT91_PIN_PD9	(PIN_BASE + 0x60 + 9)
-
-#define	AT91_PIN_PD10	(PIN_BASE + 0x60 + 10)
-#define	AT91_PIN_PD11	(PIN_BASE + 0x60 + 11)
-#define	AT91_PIN_PD12	(PIN_BASE + 0x60 + 12)
-#define	AT91_PIN_PD13	(PIN_BASE + 0x60 + 13)
-#define	AT91_PIN_PD14	(PIN_BASE + 0x60 + 14)
-
-#define	AT91_PIN_PD15	(PIN_BASE + 0x60 + 15)
-#define	AT91_PIN_PD16	(PIN_BASE + 0x60 + 16)
-#define	AT91_PIN_PD17	(PIN_BASE + 0x60 + 17)
-#define	AT91_PIN_PD18	(PIN_BASE + 0x60 + 18)
-#define	AT91_PIN_PD19	(PIN_BASE + 0x60 + 19)
-
-#define	AT91_PIN_PD20	(PIN_BASE + 0x60 + 20)
-#define	AT91_PIN_PD21	(PIN_BASE + 0x60 + 21)
-#define	AT91_PIN_PD22	(PIN_BASE + 0x60 + 22)
-#define	AT91_PIN_PD23	(PIN_BASE + 0x60 + 23)
-#define	AT91_PIN_PD24	(PIN_BASE + 0x60 + 24)
-
-#define	AT91_PIN_PD25	(PIN_BASE + 0x60 + 25)
-#define	AT91_PIN_PD26	(PIN_BASE + 0x60 + 26)
-#define	AT91_PIN_PD27	(PIN_BASE + 0x60 + 27)
-#define	AT91_PIN_PD28	(PIN_BASE + 0x60 + 28)
-#define	AT91_PIN_PD29	(PIN_BASE + 0x60 + 29)
-
-#define	AT91_PIN_PD30	(PIN_BASE + 0x60 + 30)
-#define	AT91_PIN_PD31	(PIN_BASE + 0x60 + 31)
-
-#ifndef __ASSEMBLY__
-/* setup setup routines, called from board init or driver probe() */
-extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup);
-extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup);
-extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup);
-extern int __init_or_module at91_set_gpio_output(unsigned pin, int value);
-extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on);
-extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on);
-
-/* callable at any time */
-extern int at91_set_gpio_value(unsigned pin, int value);
-extern int at91_get_gpio_value(unsigned pin);
-
-/* callable only from core power-management code */
-extern void at91_gpio_suspend(void);
-extern void at91_gpio_resume(void);
-#endif
-
-#endif
-
diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h
deleted file mode 100644
index 9ea5bfe..0000000
--- a/include/asm-arm/arch-at91rm9200/hardware.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/hardware.h
- *
- *  Copyright (C) 2003 SAN People
- *  Copyright (C) 2003 ATMEL
- *
- * 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 __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>
-
-#if defined(CONFIG_ARCH_AT91RM9200)
-#include <asm/arch/at91rm9200.h>
-#elif defined(CONFIG_ARCH_AT91SAM9260)
-#include <asm/arch/at91sam9260.h>
-#elif defined(CONFIG_ARCH_AT91SAM9261)
-#include <asm/arch/at91sam9261.h>
-#else
-#error "Unsupported AT91 processor"
-#endif
-
-
-/*
- * Remap the peripherals from address 0xFFFA0000 .. 0xFFFFFFFF
- * to 0xFEFA0000 .. 0xFF000000.  (384Kb)
- */
-#define AT91_IO_PHYS_BASE	0xFFFA0000
-#define AT91_IO_SIZE		(0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
-#define AT91_IO_VIRT_BASE	(0xFF000000 - AT91_IO_SIZE)
-
- /* Convert a physical IO address to virtual IO address */
-#define AT91_IO_P2V(x)	((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
-
-/*
- * Virtual to Physical Address mapping for IO devices.
- */
-#define AT91_VA_BASE_SYS	AT91_IO_P2V(AT91_BASE_SYS)
-#define AT91_VA_BASE_EMAC	AT91_IO_P2V(AT91RM9200_BASE_EMAC)
-
- /* Internal SRAM is mapped below the IO devices */
-#define AT91_SRAM_MAX		SZ_1M
-#define AT91_VIRT_BASE		(AT91_IO_VIRT_BASE - AT91_SRAM_MAX)
-
-/* Serial ports */
-#define ATMEL_MAX_UART		7		/* 6 USART3's and one DBGU port (SAM9260) */
-
-/* External Memory Map */
-#define AT91_CHIPSELECT_0	0x10000000
-#define AT91_CHIPSELECT_1	0x20000000
-#define AT91_CHIPSELECT_2	0x30000000
-#define AT91_CHIPSELECT_3	0x40000000
-#define AT91_CHIPSELECT_4	0x50000000
-#define AT91_CHIPSELECT_5	0x60000000
-#define AT91_CHIPSELECT_6	0x70000000
-#define AT91_CHIPSELECT_7	0x80000000
-
-/* SDRAM */
-#define AT91_SDRAM_BASE		AT91_CHIPSELECT_1
-
-/* Clocks */
-#define AT91_SLOW_CLOCK		32768		/* slow clock */
-
-#ifndef __ASSEMBLY__
-#include <asm/io.h>
-
-static inline unsigned int at91_sys_read(unsigned int reg_offset)
-{
-	void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS;
-
-	return __raw_readl(addr + reg_offset);
-}
-
-static inline void at91_sys_write(unsigned int reg_offset, unsigned long value)
-{
-	void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS;
-
-	__raw_writel(value, addr + reg_offset);
-}
-#endif
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/io.h b/include/asm-arm/arch-at91rm9200/io.h
deleted file mode 100644
index 88fd1be..0000000
--- a/include/asm-arm/arch-at91rm9200/io.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/io.h
- *
- *  Copyright (C) 2003 SAN People
- *
- * 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
- */
-
-#ifndef __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#include <asm/io.h>
-
-#define IO_SPACE_LIMIT		0xFFFFFFFF
-
-#define __io(a)			((void __iomem *)(a))
-#define __mem_pci(a)		(a)
-
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/irqs.h b/include/asm-arm/arch-at91rm9200/irqs.h
deleted file mode 100644
index c0679ea..0000000
--- a/include/asm-arm/arch-at91rm9200/irqs.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/irqs.h
- *
- *  Copyright (C) 2004 SAN People
- *
- * 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
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#include <asm/arch/at91_aic.h>
-
-#define NR_AIC_IRQS 32
-
-
-/*
- * Acknowledge interrupt with AIC after interrupt has been handled.
- *   (by kernel/irq.c)
- */
-#define irq_finish(irq) do { at91_sys_write(AT91_AIC_EOICR, 0); } while (0)
-
-
-/*
- * IRQ interrupt symbols are the AT91xxx_ID_* symbols
- * for IRQs handled directly through the AIC, or else the AT91_PIN_*
- * symbols in gpio.h for ones handled indirectly as GPIOs.
- * We make provision for 4 banks of GPIO.
- */
-#define	NR_IRQS		(NR_AIC_IRQS + (4 * 32))
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/memory.h b/include/asm-arm/arch-at91rm9200/memory.h
deleted file mode 100644
index f985069..0000000
--- a/include/asm-arm/arch-at91rm9200/memory.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/memory.h
- *
- *  Copyright (C) 2004 SAN People
- *
- * 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
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <asm/hardware.h>
-
-#define PHYS_OFFSET	(AT91_SDRAM_BASE)
-
-
-/*
- * Virtual view <-> DMA view memory address translations
- * virt_to_bus: Used to translate the virtual address to an
- *              address suitable to be passed to set_dma_addr
- * bus_to_virt: Used to convert an address for DMA operations
- *              to an address that the kernel can use.
- */
-#define __virt_to_bus(x) __virt_to_phys(x)
-#define __bus_to_virt(x) __phys_to_virt(x)
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/system.h b/include/asm-arm/arch-at91rm9200/system.h
deleted file mode 100644
index 9c67130..0000000
--- a/include/asm-arm/arch-at91rm9200/system.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/system.h
- *
- *  Copyright (C) 2003 SAN People
- *
- * 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
- */
-
-#ifndef __ASM_ARCH_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H
-
-#include <asm/hardware.h>
-#include <asm/arch/at91_st.h>
-#include <asm/arch/at91_dbgu.h>
-
-static inline void arch_idle(void)
-{
-	/*
-	 * Disable the processor clock.  The processor will be automatically
-	 * re-enabled by an interrupt or by a reset.
-	 */
-//	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
-
-	/*
-	 * Set the processor (CP15) into 'Wait for Interrupt' mode.
-	 * Unlike disabling the processor clock via the PMC (above)
-	 *  this allows the processor to be woken via JTAG.
-	 */
-	cpu_do_idle();
-}
-
-void (*at91_arch_reset)(void);
-
-static inline void arch_reset(char mode)
-{
-	/* call the CPU-specific reset function */
-	if (at91_arch_reset)
-		(at91_arch_reset)();
-}
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/timex.h b/include/asm-arm/arch-at91rm9200/timex.h
deleted file mode 100644
index faeca45..0000000
--- a/include/asm-arm/arch-at91rm9200/timex.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/timex.h
- *
- *  Copyright (C) 2003 SAN People
- *
- * 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
- */
-
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#include <asm/hardware.h>
-
-#if defined(CONFIG_ARCH_AT91RM9200)
-
-#define CLOCK_TICK_RATE		(AT91_SLOW_CLOCK)
-
-#elif defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9261)
-
-#define AT91SAM9_MASTER_CLOCK	99300000
-#define CLOCK_TICK_RATE		(AT91SAM9_MASTER_CLOCK/16)
-
-#endif
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91rm9200/uncompress.h
deleted file mode 100644
index 34b4b93..0000000
--- a/include/asm-arm/arch-at91rm9200/uncompress.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/uncompress.h
- *
- *  Copyright (C) 2003 SAN People
- *
- * 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
- */
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-#include <asm/hardware.h>
-#include <asm/arch/at91_dbgu.h>
-
-/*
- * The following code assumes the serial port has already been
- * initialized by the bootloader.  If you didn't setup a port in
- * your bootloader then nothing will appear (which might be desired).
- *
- * This does not append a newline
- */
-static void putc(int c)
-{
-	void __iomem *sys = (void __iomem *) AT91_BASE_SYS;	/* physical address */
-
-	while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY))
-		barrier();
-	__raw_writel(c, sys + AT91_DBGU_THR);
-}
-
-static inline void flush(void)
-{
-	void __iomem *sys = (void __iomem *) AT91_BASE_SYS;	/* physical address */
-
-	/* wait for transmission to complete */
-	while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY))
-		barrier();
-}
-
-#define arch_decomp_setup()
-
-#define arch_decomp_wdog()
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/vmalloc.h b/include/asm-arm/arch-at91rm9200/vmalloc.h
deleted file mode 100644
index 0a23b8c..0000000
--- a/include/asm-arm/arch-at91rm9200/vmalloc.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/vmalloc.h
- *
- *  Copyright (C) 2003 SAN People
- *
- * 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
- */
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END		(AT91_VIRT_BASE & PGDIR_MASK)
-
-#endif
diff --git a/include/asm-arm/arch-cl7500/entry-macro.S b/include/asm-arm/arch-cl7500/entry-macro.S
index c9e5395..0cfb89b 100644
--- a/include/asm-arm/arch-cl7500/entry-macro.S
+++ b/include/asm-arm/arch-cl7500/entry-macro.S
@@ -1,3 +1,8 @@
 #include <asm/hardware.h>
 #include <asm/hardware/entry-macro-iomd.S>
+	.macro  get_irqnr_preamble, base, tmp
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
 
diff --git a/include/asm-arm/arch-clps711x/entry-macro.S b/include/asm-arm/arch-clps711x/entry-macro.S
index de4481d..cd8c5a0 100644
--- a/include/asm-arm/arch-clps711x/entry-macro.S
+++ b/include/asm-arm/arch-clps711x/entry-macro.S
@@ -13,6 +13,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro	get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro	arch_ret_to_user, tmp1, tmp2
+		.endm
+
 #if (INTSR2 - INTSR1) != (INTMR2 - INTMR1)
 #error INTSR stride != INTMR stride
 #endif
diff --git a/include/asm-arm/arch-ebsa110/entry-macro.S b/include/asm-arm/arch-ebsa110/entry-macro.S
index b12ca04..aa23c5d 100644
--- a/include/asm-arm/arch-ebsa110/entry-macro.S
+++ b/include/asm-arm/arch-ebsa110/entry-macro.S
@@ -15,6 +15,12 @@
 	.macro	disable_fiq
 	.endm
 
+	.macro  get_irqnr_preamble, base, tmp
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
 	.macro	get_irqnr_and_base, irqnr, stat, base, tmp
 	mov	\base, #IRQ_STAT
 	ldrb	\stat, [\base]			@ get interrupts
diff --git a/include/asm-arm/arch-ebsa285/entry-macro.S b/include/asm-arm/arch-ebsa285/entry-macro.S
index ce812d4..4203dbf 100644
--- a/include/asm-arm/arch-ebsa285/entry-macro.S
+++ b/include/asm-arm/arch-ebsa285/entry-macro.S
@@ -14,6 +14,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.equ	dc21285_high, ARMCSR_BASE & 0xff000000
 		.equ	dc21285_low, ARMCSR_BASE & 0x00ffffff
 
diff --git a/include/asm-arm/arch-ep93xx/entry-macro.S b/include/asm-arm/arch-ep93xx/entry-macro.S
index 84140a2..241ec22 100644
--- a/include/asm-arm/arch-ep93xx/entry-macro.S
+++ b/include/asm-arm/arch-ep93xx/entry-macro.S
@@ -14,6 +14,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 		ldr	\base, =(EP93XX_AHB_VIRT_BASE)
 		orr	\base, \base, #0x000b0000
diff --git a/include/asm-arm/arch-ep93xx/ep93xx-regs.h b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
index 593f562..625c6f0 100644
--- a/include/asm-arm/arch-ep93xx/ep93xx-regs.h
+++ b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
@@ -73,6 +73,11 @@
 
 #define EP93XX_GPIO_BASE		(EP93XX_APB_VIRT_BASE + 0x00040000)
 #define EP93XX_GPIO_REG(x)		(EP93XX_GPIO_BASE + (x))
+#define EP93XX_GPIO_F_INT_TYPE1		EP93XX_GPIO_REG(0x4c)
+#define EP93XX_GPIO_F_INT_TYPE2		EP93XX_GPIO_REG(0x50)
+#define EP93XX_GPIO_F_INT_ACK		EP93XX_GPIO_REG(0x54)
+#define EP93XX_GPIO_F_INT_ENABLE	EP93XX_GPIO_REG(0x58)
+#define EP93XX_GPIO_F_INT_STATUS	EP93XX_GPIO_REG(0x5c)
 #define EP93XX_GPIO_A_INT_TYPE1		EP93XX_GPIO_REG(0x90)
 #define EP93XX_GPIO_A_INT_TYPE2		EP93XX_GPIO_REG(0x94)
 #define EP93XX_GPIO_A_INT_ACK		EP93XX_GPIO_REG(0x98)
diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h
index ae532e304..2a8c636 100644
--- a/include/asm-arm/arch-ep93xx/irqs.h
+++ b/include/asm-arm/arch-ep93xx/irqs.h
@@ -67,9 +67,13 @@
 #define IRQ_EP93XX_SAI			60
 #define EP93XX_VIC2_VALID_IRQ_MASK	0x1fffffff
 
-#define IRQ_EP93XX_GPIO(x)		(64 + (x))
+/*
+ * Map GPIO A0..A7 to irq 64..71, B0..B7 to 72..79, and
+ * F0..F7 to 80..87.
+ */
+#define IRQ_EP93XX_GPIO(x)		(64 + (((x) + (((x) >> 2) & 8)) & 0x1f))
 
-#define NR_EP93XX_IRQS			IRQ_EP93XX_GPIO(16)
+#define NR_EP93XX_IRQS			(64 + 24)
 
 #define EP93XX_BOARD_IRQ(x)		(NR_EP93XX_IRQS + (x))
 #define EP93XX_BOARD_IRQS		32
diff --git a/include/asm-arm/arch-ep93xx/platform.h b/include/asm-arm/arch-ep93xx/platform.h
index b4a8deb8..44eccec 100644
--- a/include/asm-arm/arch-ep93xx/platform.h
+++ b/include/asm-arm/arch-ep93xx/platform.h
@@ -8,7 +8,6 @@
 void ep93xx_init_irq(void);
 void ep93xx_init_time(unsigned long);
 void ep93xx_init_devices(void);
-void ep93xx_clock_init(void);
 extern struct sys_timer ep93xx_timer;
 
 struct ep93xx_eth_data
diff --git a/include/asm-arm/arch-h720x/entry-macro.S b/include/asm-arm/arch-h720x/entry-macro.S
index 8f16564..38dd63a 100644
--- a/include/asm-arm/arch-h720x/entry-macro.S
+++ b/include/asm-arm/arch-h720x/entry-macro.S
@@ -11,6 +11,12 @@
 		.macro  disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 #if defined (CONFIG_CPU_H7201) || defined (CONFIG_CPU_H7202)
 		@ we could use the id register on H7202, but this is not
diff --git a/include/asm-arm/arch-imx/entry-macro.S b/include/asm-arm/arch-imx/entry-macro.S
index 3b9ef69..0b84e81 100644
--- a/include/asm-arm/arch-imx/entry-macro.S
+++ b/include/asm-arm/arch-imx/entry-macro.S
@@ -11,21 +11,22 @@
 
 		.macro	disable_fiq
 		.endm
-#define AITC_NIVECSR   0x40
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-		ldr	\irqstat, =IO_ADDRESS(IMX_AITC_BASE)
-		@ Load offset & priority of the highest priority
-		@ interrupt pending.
-		ldr	\irqnr, [\irqstat, #AITC_NIVECSR]
-		@ Shift off the priority leaving the offset or
-		@ "interrupt number"
-		mov	\irqnr, \irqnr, lsr #16
- 		ldr	\irqstat, =1	@ dummy compare
-		ldr	\base, =0xFFFF		// invalid interrupt
-		cmp	\irqnr, \base
-		bne	1001f
-		ldr	\irqstat, =0
-1001:
-		tst	\irqstat, #1	@ to make the condition code = TRUE
+
+		.macro	get_irqnr_preamble, base, tmp
 		.endm
 
+		.macro	arch_ret_to_user, tmp1, tmp2
+		.endm
+
+#define AITC_NIVECSR   0x40
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		ldr	\base, =IO_ADDRESS(IMX_AITC_BASE)
+		@ Load offset & priority of the highest priority
+		@ interrupt pending.
+		ldr	\irqstat, [\base, #AITC_NIVECSR]
+		@ Shift off the priority leaving the offset or
+		@ "interrupt number", use arithmetic shift to
+		@ transform illegal source (0xffff) as -1
+		mov	\irqnr, \irqstat, asr #16
+		adds	\tmp, \irqnr, #1
+		.endm
diff --git a/include/asm-arm/arch-imx/spi_imx.h b/include/asm-arm/arch-imx/spi_imx.h
new file mode 100644
index 0000000..2165449
--- /dev/null
+++ b/include/asm-arm/arch-imx/spi_imx.h
@@ -0,0 +1,72 @@
+/*
+ * include/asm-arm/arch-imx/spi_imx.h
+ *
+ * Copyright (C) 2006 SWAPP
+ *	Andrea Paterniani <a.paterniani@swapp-eng.it>
+ *
+ * Initial version inspired by:
+ *	linux-2.6.17-rc3-mm1/include/asm-arm/arch-pxa/pxa2xx_spi.h
+ *
+ * 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 SPI_IMX_H_
+#define SPI_IMX_H_
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ * struct spi_imx_master - device.platform_data for SPI controller devices.
+ * @num_chipselect: chipselects are used to distinguish individual
+ *	SPI slaves, and are numbered from zero to num_chipselects - 1.
+ *	each slave has a chipselect signal, but it's common that not
+ *	every chipselect is connected to a slave.
+ * @enable_dma: if true enables DMA driven transfers.
+*/
+struct spi_imx_master {
+	u8 num_chipselect;
+	u8 enable_dma:1;
+};
+/*-------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ * struct spi_imx_chip - spi_board_info.controller_data for SPI
+ * slave devices, copied to spi_device.controller_data.
+ * @enable_loopback : used for test purpouse to internally connect RX and TX
+ *	sections.
+ * @enable_dma : enables dma transfer (provided that controller driver has
+ *	dma enabled too).
+ * @ins_ss_pulse : enable /SS pulse insertion between SPI burst.
+ * @bclk_wait : number of bclk waits between each bits_per_word SPI burst.
+ * @cs_control : function pointer to board-specific function to assert/deassert
+ *	I/O port to control HW generation of devices chip-select.
+*/
+struct spi_imx_chip {
+	u8	enable_loopback:1;
+	u8	enable_dma:1;
+	u8	ins_ss_pulse:1;
+	u16	bclk_wait:15;
+	void (*cs_control)(u32 control);
+};
+
+/* Chip-select state */
+#define SPI_CS_ASSERT			(1 << 0)
+#define SPI_CS_DEASSERT			(1 << 1)
+/*-------------------------------------------------------------------------*/
+
+
+#endif /* SPI_IMX_H_*/
diff --git a/include/asm-arm/arch-integrator/entry-macro.S b/include/asm-arm/arch-integrator/entry-macro.S
index 69838d0..491af1a 100644
--- a/include/asm-arm/arch-integrator/entry-macro.S
+++ b/include/asm-arm/arch-integrator/entry-macro.S
@@ -13,6 +13,12 @@
  		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 /* FIXME: should not be using soo many LDRs here */
 		ldr	\base, =IO_ADDRESS(INTEGRATOR_IC_BASE)
diff --git a/include/asm-arm/arch-iop13xx/entry-macro.S b/include/asm-arm/arch-iop13xx/entry-macro.S
index 94c5028..a624a78 100644
--- a/include/asm-arm/arch-iop13xx/entry-macro.S
+++ b/include/asm-arm/arch-iop13xx/entry-macro.S
@@ -19,21 +19,27 @@
 	.macro  disable_fiq
 	.endm
 
+	.macro get_irqnr_preamble, base, tmp
+	mrc	p15, 0, \tmp, c15, c1, 0
+	orr	\tmp, \tmp, #(1 << 6)
+	mcr	p15, 0, \tmp, c15, c1, 0	@ Enable cp6 access
+	.endm
+
 	/*
 	 * Note: a 1-cycle window exists where iintvec will return the value
 	 * of iintbase, so we explicitly check for "bad zeros"
 	 */
 	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-	mrc	p15, 0, \tmp, c15, c1, 0
-	orr	\tmp, \tmp, #(1 << 6)
-	mcr	p15, 0, \tmp, c15, c1, 0	@ Enable cp6 access
-
 	mrc	p6, 0, \irqnr, c3, c2, 0  	@ Read IINTVEC
 	cmp	\irqnr, #0
 	mrceq	p6, 0, \irqnr, c3, c2, 0  	@ Re-read on potentially bad zero
 	adds	\irqstat, \irqnr, #1	  	@ Check for 0xffffffff
 	movne	\irqnr, \irqnr, lsr #2	  	@ Convert to irqnr
+	.endm
 
-	biceq	\tmp, \tmp, #(1 << 6)
-	mcreq	p15, 0, \tmp, c15, c1, 0	@ Disable cp6 access if no more interrupts
+	.macro arch_ret_to_user, tmp1, tmp2
+	mrc	p15, 0, \tmp1, c15, c1, 0
+	ands	\tmp2, \tmp1, #(1 << 6)
+	bicne	\tmp1, \tmp1, #(1 << 6)
+	mcrne	p15, 0, \tmp1, c15, c1, 0	@ Disable cp6 access
 	.endm
diff --git a/include/asm-arm/arch-iop13xx/iop13xx.h b/include/asm-arm/arch-iop13xx/iop13xx.h
index a88522a..d26b755 100644
--- a/include/asm-arm/arch-iop13xx/iop13xx.h
+++ b/include/asm-arm/arch-iop13xx/iop13xx.h
@@ -9,34 +9,6 @@
 void iop13xx_map_io(void);
 void iop13xx_platform_init(void);
 void iop13xx_init_irq(void);
-void iop13xx_init_time(unsigned long tickrate);
-unsigned long iop13xx_gettimeoffset(void);
-
-/* handle cp6 access
- * to do: handle access in entry-armv5.S and unify with
- * the iop3xx implementation
- * note: use iop13xx_cp6_enable_irq_save and iop13xx_cp6_irq_restore (irq.h)
- * when interrupts are enabled
- */
-static inline unsigned long iop13xx_cp6_save(void)
-{
-	u32 temp, cp_flags;
-
-	asm volatile (
-		"mrc	p15, 0, %1, c15, c1, 0\n\t"
-		"orr	%0, %1, #(1 << 6)\n\t"
-		"mcr	p15, 0, %0, c15, c1, 0\n\t"
-		: "=r" (temp), "=r"(cp_flags));
-
-	return cp_flags;
-}
-
-static inline void iop13xx_cp6_restore(unsigned long cp_flags)
-{
-	asm volatile (
-		"mcr	p15, 0, %0, c15, c1, 0\n\t"
-		: : "r" (cp_flags) );
-}
 
 /* CPUID CP6 R0 Page 0 */
 static inline int iop13xx_cpu_id(void)
@@ -479,14 +451,4 @@
 #define IOP13XX_PBI_BAR1      		IOP13XX_PBI_OFFSET(0x10)
 #define IOP13XX_PBI_LR1       		IOP13XX_PBI_OFFSET(0x14)
 
-#define IOP13XX_TMR_TC			0x01
-#define IOP13XX_TMR_EN			0x02
-#define IOP13XX_TMR_RELOAD		0x04
-#define IOP13XX_TMR_PRIVILEGED		0x08
-
-#define IOP13XX_TMR_RATIO_1_1		0x00
-#define IOP13XX_TMR_RATIO_4_1		0x10
-#define IOP13XX_TMR_RATIO_8_1		0x20
-#define IOP13XX_TMR_RATIO_16_1		0x30
-
 #endif /* _IOP13XX_HW_H_ */
diff --git a/include/asm-arm/arch-iop13xx/irqs.h b/include/asm-arm/arch-iop13xx/irqs.h
index 442e35a..5c6fac2 100644
--- a/include/asm-arm/arch-iop13xx/irqs.h
+++ b/include/asm-arm/arch-iop13xx/irqs.h
@@ -3,8 +3,6 @@
 
 #ifndef __ASSEMBLER__
 #include <linux/types.h>
-#include <asm/system.h> /* local_irq_save */
-#include <asm/arch/iop13xx.h> /* iop13xx_cp6_* */
 
 /* INTPND0 CP6 R0 Page 3
  */
@@ -41,21 +39,6 @@
 	asm volatile("mrc p6, 0, %0, c3, c3, 0":"=r" (val));
 	return val;
 }
-
-static inline void
-iop13xx_cp6_enable_irq_save(unsigned long *cp_flags, unsigned long *irq_flags)
-{
-	local_irq_save(*irq_flags);
-	*cp_flags = iop13xx_cp6_save();
-}
-
-static inline void
-iop13xx_cp6_irq_restore(unsigned long *cp_flags,
-	unsigned long *irq_flags)
-{
-	iop13xx_cp6_restore(*cp_flags);
-	local_irq_restore(*irq_flags);
-}
 #endif
 
 #define INTBASE 0
diff --git a/include/asm-arm/arch-iop13xx/system.h b/include/asm-arm/arch-iop13xx/system.h
index ee3a625..1278270 100644
--- a/include/asm-arm/arch-iop13xx/system.h
+++ b/include/asm-arm/arch-iop13xx/system.h
@@ -48,12 +48,10 @@
 	/*
 	 * Reset the internal bus (warning both cores are reset)
 	 */
-	u32 cp_flags = iop13xx_cp6_save();
 	write_wdtcr(IOP13XX_WDTCR_EN_ARM);
 	write_wdtcr(IOP13XX_WDTCR_EN);
 	write_wdtsr(IOP13XX_WDTSR_WRITE_EN | IOP13XX_WDTCR_IB_RESET);
 	write_wdtcr(0x1000);
-	iop13xx_cp6_restore(cp_flags);
 
 	for(;;);
 }
diff --git a/include/asm-arm/arch-iop13xx/time.h b/include/asm-arm/arch-iop13xx/time.h
new file mode 100644
index 0000000..77a837a
--- /dev/null
+++ b/include/asm-arm/arch-iop13xx/time.h
@@ -0,0 +1,51 @@
+#ifndef _IOP13XX_TIME_H_
+#define _IOP13XX_TIME_H_
+#define IRQ_IOP_TIMER0 IRQ_IOP13XX_TIMER0
+
+#define IOP_TMR_EN	    0x02
+#define IOP_TMR_RELOAD	    0x04
+#define IOP_TMR_PRIVILEGED 0x08
+#define IOP_TMR_RATIO_1_1  0x00
+
+void iop_init_time(unsigned long tickrate);
+unsigned long iop_gettimeoffset(void);
+
+static inline void write_tmr0(u32 val)
+{
+	asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (val));
+}
+
+static inline void write_tmr1(u32 val)
+{
+	asm volatile("mcr p6, 0, %0, c1, c9, 0" : : "r" (val));
+}
+
+static inline u32 read_tcr0(void)
+{
+	u32 val;
+	asm volatile("mrc p6, 0, %0, c2, c9, 0" : "=r" (val));
+	return val;
+}
+
+static inline u32 read_tcr1(void)
+{
+	u32 val;
+	asm volatile("mrc p6, 0, %0, c3, c9, 0" : "=r" (val));
+	return val;
+}
+
+static inline void write_trr0(u32 val)
+{
+	asm volatile("mcr p6, 0, %0, c4, c9, 0" : : "r" (val));
+}
+
+static inline void write_trr1(u32 val)
+{
+	asm volatile("mcr p6, 0, %0, c5, c9, 0" : : "r" (val));
+}
+
+static inline void write_tisr(u32 val)
+{
+	asm volatile("mcr p6, 0, %0, c6, c9, 0" : : "r" (val));
+}
+#endif
diff --git a/include/asm-arm/arch-iop32x/entry-macro.S b/include/asm-arm/arch-iop32x/entry-macro.S
index 1500cbb..207db99 100644
--- a/include/asm-arm/arch-iop32x/entry-macro.S
+++ b/include/asm-arm/arch-iop32x/entry-macro.S
@@ -9,13 +9,28 @@
  */
 #include <asm/arch/iop32x.h>
 
-		.macro	disable_fiq
-		.endm
+	.macro	disable_fiq
+	.endm
 
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-		ldr	\base, =IOP3XX_REG_ADDR(0x07D8)
-		ldr	\irqstat, [\base]		@ Read IINTSRC
-		cmp	\irqstat, #0
-		clzne	\irqnr, \irqstat
-		rsbne	\irqnr, \irqnr, #31
-		.endm
+	.macro get_irqnr_preamble, base, tmp
+	mrc	p15, 0, \tmp, c15, c1, 0
+	orr	\tmp, \tmp, #(1 << 6)
+	mcr	p15, 0, \tmp, c15, c1, 0	@ Enable cp6 access
+	mrc	p15, 0, \tmp, c15, c1, 0
+	mov	\tmp, \tmp
+	sub	pc, pc, #4			@ cp_wait
+	.endm
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+	mrc     p6, 0, \irqstat, c8, c0, 0	@ Read IINTSRC
+	cmp     \irqstat, #0
+	clzne   \irqnr, \irqstat
+	rsbne   \irqnr, \irqnr, #31
+	.endm
+
+	.macro arch_ret_to_user, tmp1, tmp2
+	mrc	p15, 0, \tmp1, c15, c1, 0
+	ands	\tmp2, \tmp1, #(1 << 6)
+	bicne	\tmp1, \tmp1, #(1 << 6)
+	mcrne	p15, 0, \tmp1, c15, c1, 0	@ Disable cp6 access
+	.endm
diff --git a/include/asm-arm/arch-iop32x/io.h b/include/asm-arm/arch-iop32x/io.h
index 12d9ee0..5f570a5 100644
--- a/include/asm-arm/arch-iop32x/io.h
+++ b/include/asm-arm/arch-iop32x/io.h
@@ -13,10 +13,16 @@
 
 #include <asm/hardware.h>
 
-#define IO_SPACE_LIMIT		0xffffffff
+extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
+extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size,
+	unsigned long flags);
+extern void __iop3xx_iounmap(void __iomem *addr);
 
-#define __io(p)			((void __iomem *)(p))
+#define IO_SPACE_LIMIT		0xffffffff
+#define __io(p)		((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)		(a)
 
+#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
+#define __arch_iounmap(a)	 __iop3xx_iounmap(a)
 
 #endif
diff --git a/include/asm-arm/arch-iop32x/time.h b/include/asm-arm/arch-iop32x/time.h
new file mode 100644
index 0000000..0f28c99
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/time.h
@@ -0,0 +1,4 @@
+#ifndef _IOP32X_TIME_H_
+#define _IOP32X_TIME_H_
+#define IRQ_IOP_TIMER0 IRQ_IOP32X_TIMER0
+#endif
diff --git a/include/asm-arm/arch-iop33x/entry-macro.S b/include/asm-arm/arch-iop33x/entry-macro.S
index 92b7917..b8e3d44 100644
--- a/include/asm-arm/arch-iop33x/entry-macro.S
+++ b/include/asm-arm/arch-iop33x/entry-macro.S
@@ -9,14 +9,29 @@
  */
 #include <asm/arch/iop33x.h>
 
-		.macro	disable_fiq
-		.endm
+	.macro	disable_fiq
+	.endm
 
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-		ldr	\base, =IOP3XX_REG_ADDR(0x07C8)
-		ldr	\irqstat, [\base]		@ Read IINTVEC
-		cmp	\irqstat, #0
-		ldreq	\irqstat, [\base]		@ erratum 63 workaround
-		adds	\irqnr, \irqstat, #1
-		movne	\irqnr, \irqstat, lsr #2
-		.endm
+	.macro get_irqnr_preamble, base, tmp
+	mrc	p15, 0, \tmp, c15, c1, 0
+	orr	\tmp, \tmp, #(1 << 6)
+	mcr	p15, 0, \tmp, c15, c1, 0	@ Enable cp6 access
+	mrc	p15, 0, \tmp, c15, c1, 0
+	mov	\tmp, \tmp
+	sub	pc, pc, #4			@ cp_wait
+	.endm
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+	mrc     p6, 0, \irqstat, c14, c0, 0     @ Read IINTVEC
+	cmp     \irqstat, #0
+	mrceq   p6, 0, \irqstat, c14, c0, 0     @ erratum 63 workaround
+	adds    \irqnr, \irqstat, #1
+	movne   \irqnr, \irqstat, lsr #2
+	.endm
+
+	.macro arch_ret_to_user, tmp1, tmp2
+	mrc	p15, 0, \tmp1, c15, c1, 0
+	ands	\tmp2, \tmp1, #(1 << 6)
+	bicne	\tmp1, \tmp1, #(1 << 6)
+	mcrne	p15, 0, \tmp1, c15, c1, 0	@ Disable cp6 access
+	.endm
diff --git a/include/asm-arm/arch-iop33x/io.h b/include/asm-arm/arch-iop33x/io.h
index c017402..1bb5071 100644
--- a/include/asm-arm/arch-iop33x/io.h
+++ b/include/asm-arm/arch-iop33x/io.h
@@ -13,9 +13,16 @@
 
 #include <asm/hardware.h>
 
+extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
+extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size,
+	unsigned long flags);
+extern void __iop3xx_iounmap(void __iomem *addr);
+
 #define IO_SPACE_LIMIT		0xffffffff
-#define __io(p)			((void __iomem *)(p))
+#define __io(p)		((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)		(a)
 
+#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
+#define __arch_iounmap(a)	 __iop3xx_iounmap(a)
 
 #endif
diff --git a/include/asm-arm/arch-iop33x/time.h b/include/asm-arm/arch-iop33x/time.h
new file mode 100644
index 0000000..4ac4d76
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/time.h
@@ -0,0 +1,4 @@
+#ifndef _IOP33X_TIME_H_
+#define _IOP33X_TIME_H_
+#define IRQ_IOP_TIMER0 IRQ_IOP33X_TIMER0
+#endif
diff --git a/include/asm-arm/arch-ixp2000/entry-macro.S b/include/asm-arm/arch-ixp2000/entry-macro.S
index 16e1e61..11d512a 100644
--- a/include/asm-arm/arch-ixp2000/entry-macro.S
+++ b/include/asm-arm/arch-ixp2000/entry-macro.S
@@ -12,6 +12,12 @@
 		.macro  disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 
 		mov	\irqnr, #0x0              @clear out irqnr as default
diff --git a/include/asm-arm/arch-ixp23xx/entry-macro.S b/include/asm-arm/arch-ixp23xx/entry-macro.S
index 8677616..ec9dd6f 100644
--- a/include/asm-arm/arch-ixp23xx/entry-macro.S
+++ b/include/asm-arm/arch-ixp23xx/entry-macro.S
@@ -5,6 +5,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 		ldr	\irqnr, =(IXP23XX_INTC_VIRT + IXP23XX_INTR_IRQ_ENC_ST_OFFSET)
 		ldr	\irqnr, [\irqnr]	@ get interrupt number
diff --git a/include/asm-arm/arch-ixp23xx/ixdp2351.h b/include/asm-arm/arch-ixp23xx/ixdp2351.h
index 4a24f8f..d5e8a43 100644
--- a/include/asm-arm/arch-ixp23xx/ixdp2351.h
+++ b/include/asm-arm/arch-ixp23xx/ixdp2351.h
@@ -46,7 +46,7 @@
 #define IXDP2351_VIRT_NVRAM_BASE	IXDP2351_BB_AREA_BASE(0x0)
 #define IXDP2351_NVRAM_SIZE		(0x20000)
 
-#define IXDP2351_VIRT_MB_IXF1104_BASE	IXDP3251_BB_AREA_BASE(0x00020000)
+#define IXDP2351_VIRT_MB_IXF1104_BASE	IXDP2351_BB_AREA_BASE(0x00020000)
 #define IXDP2351_VIRT_ADD_UART_BASE	IXDP2351_BB_AREA_BASE(0x000240C0)
 #define IXDP2351_VIRT_FIC_BASE		IXDP2351_BB_AREA_BASE(0x00200000)
 #define IXDP2351_VIRT_DB0_BASE		IXDP2351_BB_AREA_BASE(0x00400000)
diff --git a/include/asm-arm/arch-ixp4xx/avila.h b/include/asm-arm/arch-ixp4xx/avila.h
new file mode 100644
index 0000000..0dfea0c
--- /dev/null
+++ b/include/asm-arm/arch-ixp4xx/avila.h
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-ixp4xx/avila.h
+ *
+ * Gateworks Avila platform specific definitions
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp425.h
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (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.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H__
+#error "Do not include this directly, instead #include <asm/hardware.h>"
+#endif
+
+#define	AVILA_SDA_PIN		7
+#define	AVILA_SCL_PIN		6
+
+/*
+ * AVILA PCI IRQs
+ */
+#define AVILA_PCI_MAX_DEV	4
+#define LOFT_PCI_MAX_DEV    6
+#define AVILA_PCI_IRQ_LINES	4
+
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define AVILA_PCI_INTA_PIN	11
+#define AVILA_PCI_INTB_PIN	10
+#define AVILA_PCI_INTC_PIN	9
+#define AVILA_PCI_INTD_PIN	8
+
+
diff --git a/include/asm-arm/arch-ixp4xx/entry-macro.S b/include/asm-arm/arch-ixp4xx/entry-macro.S
index 27e1241..dadb568 100644
--- a/include/asm-arm/arch-ixp4xx/entry-macro.S
+++ b/include/asm-arm/arch-ixp4xx/entry-macro.S
@@ -12,6 +12,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 		ldr	\irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET)
 		ldr	\irqstat, [\irqstat]		@ get interrupts
diff --git a/include/asm-arm/arch-ixp4xx/hardware.h b/include/asm-arm/arch-ixp4xx/hardware.h
index 6acb69c..88fd087 100644
--- a/include/asm-arm/arch-ixp4xx/hardware.h
+++ b/include/asm-arm/arch-ixp4xx/hardware.h
@@ -42,6 +42,7 @@
 
 /* Platform specific details */
 #include "ixdp425.h"
+#include "avila.h"
 #include "coyote.h"
 #include "prpmc1100.h"
 #include "nslu2.h"
diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
index 0d51726..b7b5414 100644
--- a/include/asm-arm/arch-ixp4xx/io.h
+++ b/include/asm-arm/arch-ixp4xx/io.h
@@ -238,9 +238,6 @@
 #define memcpy_fromio(a,c,l)		_memcpy_fromio((a),(c),(l))
 #define memcpy_toio(c,a,l)		_memcpy_toio((c),(a),(l))
 
-#define eth_io_copy_and_sum(s,c,l,b) \
-				eth_copy_and_sum((s),__mem_pci(c),(l),(b))
-
 static inline int
 check_signature(const unsigned char __iomem *bus_addr, const unsigned char *signature,
 		int length)
diff --git a/include/asm-arm/arch-ixp4xx/irqs.h b/include/asm-arm/arch-ixp4xx/irqs.h
index f24b763..e44a563 100644
--- a/include/asm-arm/arch-ixp4xx/irqs.h
+++ b/include/asm-arm/arch-ixp4xx/irqs.h
@@ -79,6 +79,15 @@
 #define	IRQ_IXDP425_PCI_INTD	IRQ_IXP4XX_GPIO8
 
 /*
+ * Gateworks Avila board IRQs
+ */
+#define	IRQ_AVILA_PCI_INTA	IRQ_IXP4XX_GPIO11
+#define	IRQ_AVILA_PCI_INTB	IRQ_IXP4XX_GPIO10
+#define	IRQ_AVILA_PCI_INTC	IRQ_IXP4XX_GPIO9
+#define	IRQ_AVILA_PCI_INTD	IRQ_IXP4XX_GPIO8
+
+
+/*
  * PrPMC1100 Board IRQs
  */
 #define	IRQ_PRPMC1100_PCI_INTA	IRQ_IXP4XX_GPIO11
diff --git a/include/asm-arm/arch-ixp4xx/udc.h b/include/asm-arm/arch-ixp4xx/udc.h
index dbdec36f..79b850a 100644
--- a/include/asm-arm/arch-ixp4xx/udc.h
+++ b/include/asm-arm/arch-ixp4xx/udc.h
@@ -6,3 +6,25 @@
 
 extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info);
 
+static inline int udc_gpio_to_irq(unsigned gpio)
+{
+	return 0;
+}
+
+static inline void udc_gpio_init_vbus(unsigned gpio)
+{
+}
+
+static inline void udc_gpio_init_pullup(unsigned gpio)
+{
+}
+
+static inline int udc_gpio_get(unsigned gpio)
+{
+	return 0;
+}
+
+static inline void udc_gpio_set(unsigned gpio, int is_on)
+{
+}
+
diff --git a/include/asm-arm/arch-l7200/entry-macro.S b/include/asm-arm/arch-l7200/entry-macro.S
index 8b6342d..63411d3 100644
--- a/include/asm-arm/arch-l7200/entry-macro.S
+++ b/include/asm-arm/arch-l7200/entry-macro.S
@@ -14,6 +14,12 @@
 		.macro  disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 		mov     \irqstat, #irq_base_addr		@ Virt addr IRQ regs
 		add	\irqstat, \irqstat, #0x00001000		@ Status reg
diff --git a/include/asm-arm/arch-lh7a40x/entry-macro.S b/include/asm-arm/arch-lh7a40x/entry-macro.S
index 9fc7f49..5027006 100644
--- a/include/asm-arm/arch-lh7a40x/entry-macro.S
+++ b/include/asm-arm/arch-lh7a40x/entry-macro.S
@@ -26,6 +26,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 
 branch_irq_lh7a400: b 1000f
diff --git a/include/asm-arm/arch-netx/entry-macro.S b/include/asm-arm/arch-netx/entry-macro.S
index 658df4d..83ad188 100644
--- a/include/asm-arm/arch-netx/entry-macro.S
+++ b/include/asm-arm/arch-netx/entry-macro.S
@@ -23,6 +23,12 @@
 		.macro  disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 		mov	\base, #io_p2v(0x00100000)
 		add	\base, \base, #0x000ff000
diff --git a/include/asm-arm/arch-ns9xxx/board.h b/include/asm-arm/arch-ns9xxx/board.h
new file mode 100644
index 0000000..91dc8fb
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/board.h
@@ -0,0 +1,18 @@
+/*
+ * include/asm-arm/arch-ns9xxx/board.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_BOARD_H
+#define __ASM_ARCH_BOARD_H
+
+#include <asm/mach-types.h>
+
+#define board_is_a9m9750dev()	(machine_is_cc9p9360dev())
+
+#endif /* ifndef __ASM_ARCH_BOARD_H */
diff --git a/include/asm-arm/arch-ns9xxx/clock.h b/include/asm-arm/arch-ns9xxx/clock.h
new file mode 100644
index 0000000..4371a48
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/clock.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-arm/arch-ns9xxx/clock.h
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H
+
+static inline u32 ns9xxx_systemclock(void)
+{
+	/*
+	 * This should be a multiple of HZ * TIMERCLOCKSELECT (in time.c)
+	 */
+	return 353894400;
+}
+
+static inline const u32 ns9xxx_cpuclock(void)
+{
+	return ns9xxx_systemclock() / 2;
+}
+
+static inline const u32 ns9xxx_ahbclock(void)
+{
+	return ns9xxx_systemclock() / 4;
+}
+
+static inline const u32 ns9xxx_bbusclock(void)
+{
+	return ns9xxx_systemclock() / 8;
+}
+
+#endif /* ifndef __ASM_ARCH_CLOCK_H */
diff --git a/include/asm-arm/arch-ns9xxx/debug-macro.S b/include/asm-arm/arch-ns9xxx/debug-macro.S
new file mode 100644
index 0000000..b21b93e
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/debug-macro.S
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-ns9xxx/debug-macro.S
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <asm/hardware.h>
+
+#include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1
+		ldreq	\rx, =NS9XXX_CSxSTAT_PHYS(0)
+		ldrne	\rx, =io_p2v(NS9XXX_CSxSTAT_PHYS(0))
+		.endm
+
+#define UART_SHIFT	2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-ns9xxx/dma.h b/include/asm-arm/arch-ns9xxx/dma.h
new file mode 100644
index 0000000..a67cbbe
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/dma.h
@@ -0,0 +1,14 @@
+/*
+ * include/asm-arm/arch-ns9xxx/dma.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#endif /* ifndef __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-ns9xxx/entry-macro.S b/include/asm-arm/arch-ns9xxx/entry-macro.S
new file mode 100644
index 0000000..467a198
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/entry-macro.S
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-ns9xxx/entry-macro.S
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <asm/hardware.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		ldr	\base, =SYS_ISRADDR
+		ldr	\irqstat, [\base, #(SYS_ISA - SYS_ISRADDR)]
+		cmp	\irqstat, #0
+		ldrne	\irqnr, [\base]
+		.endm
+
+		.macro	disable_fiq
+		.endm
diff --git a/include/asm-arm/arch-ns9xxx/hardware.h b/include/asm-arm/arch-ns9xxx/hardware.h
new file mode 100644
index 0000000..6819da7
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/hardware.h
@@ -0,0 +1,67 @@
+/*
+ * include/asm-arm/arch-ns9xxx/hardware.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/memory.h>
+
+/*
+ * NetSilicon NS9xxx internal mapping:
+ *
+ * physical                <--> virtual
+ * 0x90000000 - 0x906fffff <--> 0xf9000000 - 0xf96fffff
+ * 0xa0100000 - 0xa0afffff <--> 0xfa100000 - 0xfaafffff
+ */
+#define io_p2v(x)	(0xf0000000 \
+			 + (((x) & 0xf0000000) >> 4) \
+			 + ((x) & 0x00ffffff))
+
+#define io_v2p(x)	((((x) & 0x0f000000) << 4) \
+			 + ((x) & 0x00ffffff))
+
+#define __REGBIT(bit)		((u32)1 << (bit))
+#define __REGBITS(hbit, lbit)	((((u32)1 << ((hbit) - (lbit) + 1)) - 1) << (lbit))
+#define __REGVAL(mask, value)	(((value) * ((mask) & (-(mask))) & (mask)))
+
+#ifndef __ASSEMBLY__
+
+#  define __REG(x)	(*((volatile u32 *)io_p2v((x))))
+#  define __REG2(x, y)	(*((volatile u32 *)io_p2v((x)) + (y)))
+
+#  define __REGB(x)	(*((volatile u8 *)io_p2v((x))))
+#  define __REGB2(x)	(*((volatile u8 *)io_p2v((x)) + (y)))
+
+#  define REGSET(var, reg, field, value)				\
+	((var) = (((var)						\
+		   & ~(reg ## _ ## field & 				\
+		       ~ reg ## _ ## field ## _ ## value))		\
+		  | (reg ## _ ## field ## _ ## value)))
+
+#  define REGSETIM(var, reg, field, value)				\
+	((var) = (((var)						\
+		   & ~(reg ## _ ## field & 				\
+		       ~(__REGVAL(reg ## _ ## field, value))))		\
+		  | (__REGVAL(reg ## _ ## field, value))))
+
+#  define REGGET(reg, field)						\
+	((reg & (reg ## _ ## field)) / (field & (-field)))
+
+#else
+
+#  define __REG(x)	io_p2v(x)
+#  define __REG2(x, y)	io_p2v((x) + (y))
+
+#  define __REGB(x)	__REG((x))
+#  define __REGB2(x, y)	__REG2((x), (y))
+
+#endif
+
+#endif /* ifndef __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-ns9xxx/io.h b/include/asm-arm/arch-ns9xxx/io.h
new file mode 100644
index 0000000..6f82d28
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/io.h
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-ns9xxx/io.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_IO_H
+#define __ASM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT  0xffffffff /* XXX */
+
+#define __io(a)         ((void __iomem *)(a))
+#define __mem_pci(a)    (a)
+#define __mem_isa(a)    (IO_BASE + (a))
+
+#endif /* ifndef __ASM_ARCH_IO_H */
diff --git a/include/asm-arm/arch-ns9xxx/irqs.h b/include/asm-arm/arch-ns9xxx/irqs.h
new file mode 100644
index 0000000..25d8d28
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/irqs.h
@@ -0,0 +1,85 @@
+/*
+ * include/asm-arm/arch-ns9xxx/irqs.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define IRQ_WATCHDOG	0
+#define IRQ_AHBBUSERR	1
+#define IRQ_BBUSAGG	2
+/* irq 3 is reserved for NS9360 */
+#define IRQ_ETHRX	4
+#define IRQ_ETHTX	5
+#define IRQ_ETHPHY	6
+#define IRQ_LCD		7
+#define IRQ_SERBRX	8
+#define IRQ_SERBTX	9
+#define IRQ_SERARX	10
+#define IRQ_SERATX	11
+#define IRQ_SERCRX	12
+#define IRQ_SERCTX	13
+#define IRQ_I2C		14
+#define IRQ_BBUSDMA	15
+#define IRQ_TIMER0	16
+#define IRQ_TIMER1	17
+#define IRQ_TIMER2	18
+#define IRQ_TIMER3	19
+#define IRQ_TIMER4	20
+#define IRQ_TIMER5	21
+#define IRQ_TIMER6	22
+#define IRQ_TIMER7	23
+#define IRQ_RTC		24
+#define IRQ_USBHOST	25
+#define IRQ_USBDEVICE	26
+#define IRQ_IEEE1284	27
+#define IRQ_EXT0	28
+#define IRQ_EXT1	29
+#define IRQ_EXT2	30
+#define IRQ_EXT3	31
+
+#define BBUS_IRQ(irq)	(32 + irq)
+
+#define IRQ_BBUS_DMA		BBUS_IRQ(0)
+#define IRQ_BBUS_SERBRX		BBUS_IRQ(2)
+#define IRQ_BBUS_SERBTX		BBUS_IRQ(3)
+#define IRQ_BBUS_SERARX		BBUS_IRQ(4)
+#define IRQ_BBUS_SERATX		BBUS_IRQ(5)
+#define IRQ_BBUS_SERCRX		BBUS_IRQ(6)
+#define IRQ_BBUS_SERCTX		BBUS_IRQ(7)
+#define IRQ_BBUS_SERDRX		BBUS_IRQ(8)
+#define IRQ_BBUS_SERDTX		BBUS_IRQ(9)
+#define IRQ_BBUS_I2C		BBUS_IRQ(10)
+#define IRQ_BBUS_1284		BBUS_IRQ(11)
+#define IRQ_BBUS_UTIL		BBUS_IRQ(12)
+#define IRQ_BBUS_RTC		BBUS_IRQ(13)
+#define IRQ_BBUS_USBHST		BBUS_IRQ(14)
+#define IRQ_BBUS_USBDEV		BBUS_IRQ(15)
+#define IRQ_BBUS_AHBDMA1	BBUS_IRQ(24)
+#define IRQ_BBUS_AHBDMA2	BBUS_IRQ(25)
+
+/*
+ * these Interrupts are specific for the a9m9750dev board.
+ * They are generated by an FPGA that interrupts the CPU on
+ * IRQ_EXT2
+ */
+#define FPGA_IRQ(irq)	(64 + irq)
+
+#define IRQ_FPGA_UARTA		FPGA_IRQ(0)
+#define IRQ_FPGA_UARTB		FPGA_IRQ(1)
+#define IRQ_FPGA_UARTC		FPGA_IRQ(2)
+#define IRQ_FPGA_UARTD		FPGA_IRQ(3)
+#define IRQ_FPGA_TOUCH		FPGA_IRQ(4)
+#define IRQ_FPGA_CF		FPGA_IRQ(5)
+#define IRQ_FPGA_CAN0		FPGA_IRQ(6)
+#define IRQ_FPGA_CAN1		FPGA_IRQ(7)
+
+#define NR_IRQS	72
+
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/include/asm-arm/arch-ns9xxx/memory.h b/include/asm-arm/arch-ns9xxx/memory.h
new file mode 100644
index 0000000..ce1343e
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/memory.h
@@ -0,0 +1,27 @@
+/*
+ * include/asm-arm/arch-ns9xxx/memory.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+*/
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/* x in [0..3] */
+#define NS9XXX_CSxSTAT_PHYS(x)	UL(((x) + 4) << 28)
+
+#define NS9XXX_CS0STAT_LENGTH	UL(0x1000)
+#define NS9XXX_CS1STAT_LENGTH	UL(0x1000)
+#define NS9XXX_CS2STAT_LENGTH	UL(0x1000)
+#define NS9XXX_CS3STAT_LENGTH	UL(0x1000)
+
+#define PHYS_OFFSET	UL(0x00000000)
+
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#endif
diff --git a/include/asm-arm/arch-ns9xxx/processor.h b/include/asm-arm/arch-ns9xxx/processor.h
new file mode 100644
index 0000000..716c106
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/processor.h
@@ -0,0 +1,18 @@
+/*
+ * include/asm-arm/arch-ns9xxx/processor.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_PROCESSOR_H
+#define __ASM_ARCH_PROCESSOR_H
+
+#include <asm/mach-types.h>
+
+#define processor_is_ns9360()	(machine_is_cc9p9360dev())
+
+#endif /* ifndef __ASM_ARCH_PROCESSOR_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-bbu.h b/include/asm-arm/arch-ns9xxx/regs-bbu.h
new file mode 100644
index 0000000..e262695
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/regs-bbu.h
@@ -0,0 +1,21 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-bbu.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSBBU_H
+#define __ASM_ARCH_REGSBBU_H
+
+#include <asm/hardware.h>
+
+/* BBus Utility */
+
+/* GPIO Configuration Register */
+#define BBU_GC(x)	__REG2(0x9060000c, (x))
+
+#endif /* ifndef __ASM_ARCH_REGSBBU_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h b/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
new file mode 100644
index 0000000..c3dc532
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
@@ -0,0 +1,24 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSBOARDA9M9750_H
+#define __ASM_ARCH_REGSBOARDA9M9750_H
+
+#include <asm/hardware.h>
+
+#define FPGA_UARTA_BASE	io_p2v(NS9XXX_CSxSTAT_PHYS(0))
+#define FPGA_UARTB_BASE	io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x08)
+#define FPGA_UARTC_BASE	io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x10)
+#define FPGA_UARTD_BASE	io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x18)
+
+#define FPGA_IER	__REGB(NS9XXX_CSxSTAT_PHYS(0) + 0x50)
+#define FPGA_ISR	__REGB(NS9XXX_CSxSTAT_PHYS(0) + 0x60)
+
+#endif /* ifndef __ASM_ARCH_REGSBOARDA9M9750_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-mem.h b/include/asm-arm/arch-ns9xxx/regs-mem.h
new file mode 100644
index 0000000..8ed8448
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/regs-mem.h
@@ -0,0 +1,135 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-mem.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSMEM_H
+#define __ASM_ARCH_REGSMEM_H
+
+#include <asm/hardware.h>
+
+/* Memory Module */
+
+/* Control register */
+#define MEM_CTRL	__REG(0xa0700000)
+
+/* Status register */
+#define MEM_STAT	__REG(0xa0700004)
+
+/* Configuration register */
+#define MEM_CONF	__REG(0xa0700008)
+
+/* Dynamic Memory Control register */
+#define MEM_DMCTRL	__REG(0xa0700020)
+
+/* Dynamic Memory Refresh Timer */
+#define MEM_DMRT	__REG(0xa0700024)
+
+/* Dynamic Memory Read Configuration register */
+#define MEM_DMRC	__REG(0xa0700028)
+
+/* Dynamic Memory Precharge Command Period (tRP) */
+#define MEM_DMPCP	__REG(0xa0700030)
+
+/* Dynamic Memory Active to Precharge Command Period (tRAS) */
+#define MEM_DMAPCP	__REG(0xa0700034)
+
+/* Dynamic Memory Self-Refresh Exit Time (tSREX) */
+#define MEM_DMSRET	__REG(0xa0700038)
+
+/* Dynamic Memory Last Data Out to Active Time (tAPR) */
+#define MEM_DMLDOAT	__REG(0xa070003c)
+
+/* Dynamic Memory Data-in to Active Command Time (tDAL or TAPW) */
+#define MEM_DMDIACT	__REG(0xa0700040)
+
+/* Dynamic Memory Write Recovery Time (tWR, tDPL, tRWL, tRDL) */
+#define MEM_DMWRT	__REG(0xa0700044)
+
+/* Dynamic Memory Active to Active Command Period (tRC) */
+#define MEM_DMAACP	__REG(0xa0700048)
+
+/* Dynamic Memory Auto Refresh Period, and Auto Refresh to Active Command Period (tRFC) */
+#define MEM_DMARP	__REG(0xa070004c)
+
+/* Dynamic Memory Exit Self-Refresh to Active Command (tXSR) */
+#define MEM_DMESRAC	__REG(0xa0700050)
+
+/* Dynamic Memory Active Bank A to Active B Time (tRRD) */
+#define MEM_DMABAABT	__REG(0xa0700054)
+
+/* Dynamic Memory Load Mode register to Active Command Time (tMRD) */
+#define MEM_DMLMACT	__REG(0xa0700058)
+
+/* Static Memory Extended Wait */
+#define MEM_SMEW	__REG(0xa0700080)
+
+/* Dynamic Memory Configuration Register x */
+#define MEM_DMCONF(x) 	__REG2(0xa0700100, (x) << 3)
+
+/* Dynamic Memory RAS and CAS Delay x */
+#define MEM_DMRCD(x)	__REG2(0xa0700104, (x) << 3)
+
+/* Static Memory Configuration Register x */
+#define MEM_SMC(x)	__REG2(0xa0700200, (x) << 3)
+
+/* Static Memory Configuration Register x: Write protect */
+#define MEM_SMC_WSMC		__REGBIT(20)
+#define MEM_SMC_WSMC_OFF		__REGVAL(MEM_SMC_WSMC, 0)
+#define MEM_SMC_WSMC_ON			__REGVAL(MEM_SMC_WSMC, 1)
+
+/* Static Memory Configuration Register x: Buffer enable */
+#define MEM_SMC_BSMC		__REGBIT(19)
+#define MEM_SMC_BSMC_OFF		__REGVAL(MEM_SMC_BSMC, 0)
+#define MEM_SMC_BSMC_ON			__REGVAL(MEM_SMC_BSMC, 1)
+
+/* Static Memory Configuration Register x: Extended Wait */
+#define MEM_SMC_EW		__REGBIT(8)
+#define MEM_SMC_EW_OFF			__REGVAL(MEM_SMC_EW, 0)
+#define MEM_SMC_EW_ON			__REGVAL(MEM_SMC_EW, 1)
+
+/* Static Memory Configuration Register x: Byte lane state */
+#define MEM_SMC_PB		__REGBIT(7)
+#define MEM_SMC_PB_0			__REGVAL(MEM_SMC_PB, 0)
+#define MEM_SMC_PB_1			__REGVAL(MEM_SMC_PB, 1)
+
+/* Static Memory Configuration Register x: Chip select polarity */
+#define MEM_SMC_PC		__REGBIT(6)
+#define MEM_SMC_PC_AL			__REGVAL(MEM_SMC_PC, 0)
+#define MEM_SMC_PC_AH			__REGVAL(MEM_SMC_PC, 1)
+
+/* static memory configuration register x: page mode*/
+#define MEM_SMC_PM		__REGBIT(3)
+#define MEM_SMC_PM_DIS			__REGVAL(MEM_SMC_PM, 0)
+#define MEM_SMC_PM_ASYNC		__REGVAL(MEM_SMC_PM, 1)
+
+/* static memory configuration register x: Memory width */
+#define MEM_SMC_MW		__REGBITS(1, 0)
+#define MEM_SMC_MW_8			__REGVAL(MEM_SMC_MW, 0)
+#define MEM_SMC_MW_16			__REGVAL(MEM_SMC_MW, 1)
+#define MEM_SMC_MW_32			__REGVAL(MEM_SMC_MW, 2)
+
+/* Static Memory Write Enable Delay x */
+#define MEM_SMWED(x)	__REG2(0xa0700204, (x) << 3)
+
+/* Static Memory Output Enable Delay x */
+#define MEM_SMOED(x)	__REG2(0xa0700208, (x) << 3)
+
+/* Static Memory Read Delay x */
+#define MEM_SMRD(x)	__REG2(0xa070020c, (x) << 3)
+
+/* Static Memory Page Mode Read Delay 0 */
+#define MEM_SMPMRD(x)	__REG2(0xa0700210, (x) << 3)
+
+/* Static Memory Write Delay */
+#define MEM_SMWD(x)	__REG2(0xa0700214, (x) << 3)
+
+/* Static Memory Turn Round Delay x */
+#define MEM_SWT(x)	__REG2(0xa0700218, (x) << 3)
+
+#endif /* ifndef __ASM_ARCH_REGSMEM_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-sys.h b/include/asm-arm/arch-ns9xxx/regs-sys.h
new file mode 100644
index 0000000..8162a50
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/regs-sys.h
@@ -0,0 +1,157 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-sys.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSSYS_H
+#define __ASM_ARCH_REGSSYS_H
+
+#include <asm/hardware.h>
+
+/* System Control Module */
+
+/* AHB Arbiter Gen Configuration */
+#define SYS_AHBAGENCONF	__REG(0xa0900000)
+
+/* BRC */
+#define SYS_BRC(x)	__REG2(0xa0900004, (x))
+
+/* Timer x Reload Count register */
+#define SYS_TRC(x)	__REG2(0xa0900044, (x))
+
+/* Timer x Read register */
+#define SYS_TR(x)	__REG2(0xa0900084, (x))
+
+/* Interrupt Vector Address Register Level x */
+#define SYS_IVA(x)	__REG2(0xa09000c4, (x))
+
+/* Interrupt Configuration registers */
+#define SYS_IC(x)	__REG2(0xa0900144, (x))
+
+/* ISRADDR */
+#define SYS_ISRADDR	__REG(0xa0900164)
+
+/* Interrupt Status Active */
+#define SYS_ISA		__REG(0xa0900168)
+
+/* Interrupt Status Raw */
+#define SYS_ISR		__REG(0xa090016c)
+
+/* Timer Interrupt Status register */
+#define SYS_TIS		__REG(0xa0900170)
+
+/* PLL Configuration register */
+#define SYS_PLL		__REG(0xa0900188)
+
+/* PLL Configuration register: PLL SW change */
+#define SYS_PLL_SWC		__REGBIT(15)
+#define SYS_PLL_SWC_NO			__REGVAL(SYS_PLL_SWC, 0)
+#define SYS_PLL_SWC_YES			__REGVAL(SYS_PLL_SWC, 1)
+
+/* Timer x Control register */
+#define SYS_TC(x)	__REG2(0xa0900190, (x))
+
+/* Timer x Control register: Timer enable */
+#define SYS_TCx_TEN		__REGBIT(15)
+#define SYS_TCx_TEN_DIS			__REGVAL(SYS_TCx_TEN, 1)
+#define SYS_TCx_TEN_EN			__REGVAL(SYS_TCx_TEN, 1)
+
+/* Timer x Control register: CPU debug mode */
+#define SYS_TCx_TDBG		__REGBIT(10)
+#define SYS_TCx_TDBG_CONT		__REGVAL(SYS_TCx_TDBG, 0)
+#define SYS_TCx_TDBG_STOP		__REGVAL(SYS_TCx_TDBG, 1)
+
+/* Timer x Control register: Interrupt clear */
+#define SYS_TCx_INTC		__REGBIT(9)
+#define SYS_TCx_INTC_UNSET		__REGVAL(SYS_TCx_INTC, 0)
+#define SYS_TCx_INTC_SET		__REGVAL(SYS_TCx_INTC, 1)
+
+/* Timer x Control register: Timer clock select */
+#define SYS_TCx_TLCS		__REGBITS(8, 6)
+#define SYS_TCx_TLCS_CPU		__REGVAL(SYS_TCx_TLCS, 0)	/* CPU clock */
+#define SYS_TCx_TLCS_DIV2		__REGVAL(SYS_TCx_TLCS, 1)	/* CPU clock / 2 */
+#define SYS_TCx_TLCS_DIV4		__REGVAL(SYS_TCx_TLCS, 2)	/* CPU clock / 4 */
+#define SYS_TCx_TLCS_DIV8		__REGVAL(SYS_TCx_TLCS, 3)	/* CPU clock / 8 */
+#define SYS_TCx_TLCS_DIV16		__REGVAL(SYS_TCx_TLCS, 4)	/* CPU clock / 16 */
+#define SYS_TCx_TLCS_DIV32		__REGVAL(SYS_TCx_TLCS, 5)	/* CPU clock / 32 */
+#define SYS_TCx_TLCS_DIV64		__REGVAL(SYS_TCx_TLCS, 6)	/* CPU clock / 64 */
+#define SYS_TCx_TLCS_EXT		__REGVAL(SYS_TCx_TLCS, 7)
+
+/* Timer x Control register: Timer mode */
+#define SYS_TCx_TM		__REGBITS(5, 4)
+#define SYS_TCx_TM_IEE			__REGVAL(SYS_TCx_TM, 0)		/* Internal timer or external event */
+#define SYS_TCx_TM_ELL			__REGVAL(SYS_TCx_TM, 1)		/* External low-level, gated timer */
+#define SYS_TCx_TM_EHL			__REGVAL(SYS_TCx_TM, 2)		/* External high-level, gated timer */
+#define SYS_TCx_TM_CONCAT		__REGVAL(SYS_TCx_TM, 3)		/* Concatenate the lower timer. */
+
+/* Timer x Control register: Interrupt select */
+#define SYS_TCx_INTS		__REGBIT(3)
+#define SYS_TCx_INTS_DIS		__REGVAL(SYS_TCx_INTS, 0)
+#define SYS_TCx_INTS_EN			__REGVAL(SYS_TCx_INTS, 1)
+
+/* Timer x Control register: Up/down select */
+#define SYS_TCx_UDS		__REGBIT(2)
+#define SYS_TCx_UDS_UP			__REGVAL(SYS_TCx_UDS, 0)
+#define SYS_TCx_UDS_DOWN		__REGVAL(SYS_TCx_UDS, 1)
+
+/* Timer x Control register: 32- or 16-bit timer */
+#define SYS_TCx_TSZ		__REGBIT(1)
+#define SYS_TCx_TSZ_16			__REGVAL(SYS_TCx_TSZ, 0)
+#define SYS_TCx_TSZ_32			__REGVAL(SYS_TCx_TSZ, 1)
+
+/* Timer x Control register: Reload enable */
+#define SYS_TCx_REN		__REGBIT(0)
+#define SYS_TCx_REN_DIS			__REGVAL(SYS_TCx_REN, 0)
+#define SYS_TCx_REN_EN			__REGVAL(SYS_TCx_REN, 1)
+
+/* System Memory Chip Select x Dynamic Memory Base */
+#define SYS_SMCSDMB(x)	__REG2(0xa09001d0, (x) << 1)
+
+/* System Memory Chip Select x Dynamic Memory Mask */
+#define SYS_SMCSDMM(x)	__REG2(0xa09001d4, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Base */
+#define SYS_SMCSSMB(x)	__REG2(0xa09001f0, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Base: Chip select x base */
+#define SYS_SMCSSMB_CSxB	__REGBITS(31, 12)
+
+/* System Memory Chip Select x Static Memory Mask */
+#define SYS_SMCSSMM(x)	__REG2(0xa09001f4, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Mask: Chip select x mask */
+#define SYS_SMCSSMM_CSxM	__REGBITS(31, 12)
+
+/* System Memory Chip Select x Static Memory Mask: Chip select x enable */
+#define SYS_SMCSSMM_CSEx	__REGBIT(0)
+#define SYS_SMCSSMM_CSEx_DIS		__REGVAL(SYS_SMCSSMM_CSEx, 0)
+#define SYS_SMCSSMM_CSEx_EN		__REGVAL(SYS_SMCSSMM_CSEx, 1)
+
+/* General purpose, user-defined ID register */
+#define SYS_GENID	__REG(0xa0900210)
+
+/* External Interrupt x Control register */
+#define SYS_EIC(x)	__REG2(0xa0900214, (x))
+
+/* External Interrupt x Control register: Status */
+#define SYS_EIC_STS		__REGBIT(3)
+
+/* External Interrupt x Control register: Clear */
+#define SYS_EIC_CLR		__REGBIT(2)
+
+/* External Interrupt x Control register: Polarity */
+#define SYS_EIC_PLTY		__REGBIT(1)
+#define SYS_EIC_PLTY_AH			__REGVAL(SYS_EIC_PLTY, 0)
+#define SYS_EIC_PLTY_AL			__REGVAL(SYS_EIC_PLTY, 1)
+
+/* External Interrupt x Control register: Level edge */
+#define SYS_EIC_LVEDG		__REGBIT(0)
+#define SYS_EIC_LVEDG_LEVEL		__REGVAL(SYS_EIC_LVEDG, 0)
+#define SYS_EIC_LVEDG_EDGE		__REGVAL(SYS_EIC_LVEDG, 1)
+
+#endif /* ifndef __ASM_ARCH_REGSSYS_H */
diff --git a/include/asm-arm/arch-ns9xxx/system.h b/include/asm-arm/arch-ns9xxx/system.h
new file mode 100644
index 0000000..e3cd4d3
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/system.h
@@ -0,0 +1,34 @@
+/*
+ * include/asm-arm/arch-ns9xxx/system.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/proc-fns.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/mach-types.h>
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	u32 reg;
+
+	reg = SYS_PLL >> 16;
+	REGSET(reg, SYS_PLL, SWC, YES);
+	SYS_PLL = reg;
+
+	BUG();
+}
+
+#endif /* ifndef __ASM_ARCH_SYSTEM_H */
diff --git a/include/asm-arm/arch-ns9xxx/timex.h b/include/asm-arm/arch-ns9xxx/timex.h
new file mode 100644
index 0000000..f776cbd
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/timex.h
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-ns9xxx/timex.h
+ *
+ * Copyright (C) 2005-2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+/*
+ * value for CLOCK_TICK_RATE stolen from include/asm-arm/arch-s3c2410/timex.h.
+ * See there for an explanation.
+ */
+#define CLOCK_TICK_RATE         12000000
+
+#endif /* ifndef __ASM_ARCH_TIMEX_H */
diff --git a/include/asm-arm/arch-ns9xxx/uncompress.h b/include/asm-arm/arch-ns9xxx/uncompress.h
new file mode 100644
index 0000000..961ca7d
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/uncompress.h
@@ -0,0 +1,35 @@
+/*
+ * include/asm-arm/arch-ns9xxx/uncompress.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+static void putc(char c)
+{
+	volatile u8 *base = (volatile u8 *)0x40000000;
+	int t = 0x10000;
+
+	do {
+		if (base[5] & 0x20) {
+			base[0] = c;
+			break;
+		}
+	} while (--t);
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+static void flush(void)
+{
+	/* nothing */
+}
+
+#endif /* ifndef __ASM_ARCH_UNCOMPRESS_H */
diff --git a/include/asm-arm/arch-ns9xxx/vmalloc.h b/include/asm-arm/arch-ns9xxx/vmalloc.h
new file mode 100644
index 0000000..2f3cb6f
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/vmalloc.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-arm/arch-ns9xxx/vmalloc.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END     (0xf0000000)
+
+#endif /* ifndef __ASM_ARCH_VMALLOC_H */
diff --git a/include/asm-arm/arch-omap/entry-macro.S b/include/asm-arm/arch-omap/entry-macro.S
index 0ffb118..c90dff4 100644
--- a/include/asm-arm/arch-omap/entry-macro.S
+++ b/include/asm-arm/arch-omap/entry-macro.S
@@ -29,6 +29,12 @@
  		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 		ldr	\base, =IO_ADDRESS(OMAP_IH1_BASE)
 		ldr	\irqnr, [\base, #IRQ_ITR_REG_OFFSET]
diff --git a/include/asm-arm/arch-omap/gpio.h b/include/asm-arm/arch-omap/gpio.h
index f486b72..3762a6a 100644
--- a/include/asm-arm/arch-omap/gpio.h
+++ b/include/asm-arm/arch-omap/gpio.h
@@ -76,4 +76,70 @@
 extern void omap_set_gpio_dataout(int gpio, int enable);
 extern int omap_get_gpio_datain(int gpio);
 
+/*-------------------------------------------------------------------------*/
+
+/* wrappers for "new style" GPIO calls. the old OMAP-specfic ones should
+ * eventually be removed (along with this errno.h inclusion), and maybe
+ * gpios should put MPUIOs last too.
+ */
+
+#include <asm/errno.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return omap_request_gpio(gpio);
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	omap_free_gpio(gpio);
+}
+
+static inline int __gpio_set_direction(unsigned gpio, int is_input)
+{
+	if (cpu_class_is_omap2()) {
+		if (gpio > OMAP_MAX_GPIO_LINES)
+			return -EINVAL;
+	} else {
+		if (gpio > (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */))
+			return -EINVAL;
+	}
+	omap_set_gpio_direction(gpio, is_input);
+	return 0;
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	return __gpio_set_direction(gpio, 1);
+}
+
+static inline int gpio_direction_output(unsigned gpio)
+{
+	return __gpio_set_direction(gpio, 0);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return omap_get_gpio_datain(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	omap_set_gpio_dataout(gpio, value);
+}
+
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return OMAP_GPIO_IRQ(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	if (cpu_class_is_omap1() && (irq < (IH_MPUIO_BASE + 16)))
+		return (irq - IH_MPUIO_BASE) + OMAP_MAX_GPIO_LINES;
+	return irq - IH_GPIO_BASE;
+}
+
 #endif
diff --git a/include/asm-arm/arch-pnx4008/entry-macro.S b/include/asm-arm/arch-pnx4008/entry-macro.S
index c1c198e..f117319 100644
--- a/include/asm-arm/arch-pnx4008/entry-macro.S
+++ b/include/asm-arm/arch-pnx4008/entry-macro.S
@@ -28,6 +28,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 /* decode the MIC interrupt numbers */
 		ldr	\base, =IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
diff --git a/include/asm-arm/arch-pxa/entry-macro.S b/include/asm-arm/arch-pxa/entry-macro.S
index 4985e33..1d5fbb9 100644
--- a/include/asm-arm/arch-pxa/entry-macro.S
+++ b/include/asm-arm/arch-pxa/entry-macro.S
@@ -13,6 +13,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 #ifdef CONFIG_PXA27x
 		mrc	p6, 0, \irqstat, c0, c0, 0		@ ICIP
diff --git a/include/asm-arm/arch-pxa/gpio.h b/include/asm-arm/arch-pxa/gpio.h
new file mode 100644
index 0000000..3d348a3
--- /dev/null
+++ b/include/asm-arm/arch-pxa/gpio.h
@@ -0,0 +1,80 @@
+/*
+ * linux/include/asm-arm/arch-pxa/gpio.h
+ *
+ * PXA GPIO wrappers for arch-neutral GPIO calls
+ *
+ * Written by Philipp Zabel <philipp.zabel@gmail.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
+ *
+ */
+
+#ifndef __ASM_ARCH_PXA_GPIO_H
+#define __ASM_ARCH_PXA_GPIO_H
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	return;
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	return pxa_gpio_mode(gpio | GPIO_IN);
+}
+
+static inline int gpio_direction_output(unsigned gpio)
+{
+	return pxa_gpio_mode(gpio | GPIO_OUT);
+}
+
+static inline int __gpio_get_value(unsigned gpio)
+{
+	return GPLR(gpio) & GPIO_bit(gpio);
+}
+
+#define gpio_get_value(gpio)			\
+	(__builtin_constant_p(gpio) ?		\
+	 __gpio_get_value(gpio) :		\
+	 pxa_gpio_get_value(gpio))
+
+static inline void __gpio_set_value(unsigned gpio, int value)
+{
+	if (value)
+		GPSR(gpio) = GPIO_bit(gpio);
+	else
+		GPCR(gpio) = GPIO_bit(gpio);
+}
+
+#define gpio_set_value(gpio,value)		\
+	(__builtin_constant_p(gpio) ?		\
+	 __gpio_set_value(gpio, value) :	\
+	 pxa_gpio_set_value(gpio, value))
+
+#include <asm-generic/gpio.h>			/* cansleep wrappers */
+
+#define gpio_to_irq(gpio)	IRQ_GPIO(gpio)
+#define irq_to_gpio(irq)	IRQ_TO_GPIO(irq)
+
+
+#endif
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
index 3e70bd9..e2bdc2f 100644
--- a/include/asm-arm/arch-pxa/hardware.h
+++ b/include/asm-arm/arch-pxa/hardware.h
@@ -65,7 +65,17 @@
 /*
  * Handy routine to set GPIO alternate functions
  */
-extern void pxa_gpio_mode( int gpio_mode );
+extern int pxa_gpio_mode( int gpio_mode );
+
+/*
+ * Return GPIO level, nonzero means high, zero is low
+ */
+extern int pxa_gpio_get_value(unsigned gpio);
+
+/*
+ * Set output GPIO level
+ */
+extern void pxa_gpio_set_value(unsigned gpio, int value);
 
 /*
  * Routine to enable or disable CKEN
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index e24f6b6..aec835b 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -463,9 +463,6 @@
  * Serial Audio Controller
  */
 
-/* FIXME: This clash with SA1111 defines */
-#ifndef _ASM_ARCH_SA1111
-
 #define SACR0		__REG(0x40400000)  /* Global Control Register */
 #define SACR1		__REG(0x40400004)  /* Serial Audio I 2 S/MSB-Justified Control Register */
 #define SASR0		__REG(0x4040000C)  /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
@@ -474,8 +471,8 @@
 #define SADIV		__REG(0x40400060)  /* Audio Clock Divider Register. */
 #define SADR		__REG(0x40400080)  /* Serial Audio Data Register (TX and RX FIFO access Register). */
 
-#define SACR0_RFTH(x)	(x << 12)	/* Rx FIFO Interrupt or DMA Trigger Threshold */
-#define SACR0_TFTH(x)	(x << 8)	/* Tx FIFO Interrupt or DMA Trigger Threshold */
+#define SACR0_RFTH(x)	((x) << 12)	/* Rx FIFO Interrupt or DMA Trigger Threshold */
+#define SACR0_TFTH(x)	((x) << 8)	/* Tx FIFO Interrupt or DMA Trigger Threshold */
 #define SACR0_STRF	(1 << 5)	/* FIFO Select for EFWR Special Function */
 #define SACR0_EFWR	(1 << 4)	/* Enable EFWR Function  */
 #define SACR0_RST	(1 << 3)	/* FIFO, i2s Register Reset */
@@ -503,8 +500,6 @@
 #define SAIMR_RFS	(1 << 4)	/* Enable Rx FIFO Service Interrupt */
 #define SAIMR_TFS	(1 << 3)	/* Enable Tx FIFO Service Interrupt */
 
-#endif
-
 /*
  * AC97 Controller registers
  */
@@ -1682,15 +1677,18 @@
 #define SSSR_PINT		(1 << 18)	/* Peripheral Trailing Byte Interrupt */
 
 #define SSPSP_FSRT		(1 << 25)	/* Frame Sync Relative Timing */
-#define SSPSP_DMYSTOP(x)	(x << 23)	/* Dummy Stop */
-#define SSPSP_SFRMWDTH(x)	(x << 16)	/* Serial Frame Width */
-#define SSPSP_SFRMDLY(x)	(x << 9)	/* Serial Frame Delay */
-#define SSPSP_DMYSTRT(x)	(x << 7)	/* Dummy Start */
-#define SSPSP_STRTDLY(x)	(x << 4)	/* Start Delay */
+#define SSPSP_DMYSTOP(x)	((x) << 23)	/* Dummy Stop */
+#define SSPSP_SFRMWDTH(x)	((x) << 16)	/* Serial Frame Width */
+#define SSPSP_SFRMDLY(x)	((x) << 9)	/* Serial Frame Delay */
+#define SSPSP_DMYSTRT(x)	((x) << 7)	/* Dummy Start */
+#define SSPSP_STRTDLY(x)	((x) << 4)	/* Start Delay */
 #define SSPSP_ETDS			(1 << 3)	/* End of Transfer data State */
 #define SSPSP_SFRMP			(1 << 2)	/* Serial Frame Polarity */
-#define SSPSP_SCMODE(x)		(x << 0)	/* Serial Bit Rate Clock Mode */
+#define SSPSP_SCMODE(x)		((x) << 0)	/* Serial Bit Rate Clock Mode */
 
+#define SSACD_SCDB		(1 << 3)	/* SSPSYSCLK Divider Bypass */
+#define SSACD_ACPS(x)		((x) << 4)	/* Audio clock PLL select */
+#define SSACD_ACDS(x)		((x) << 0)	/* Audio clock divider select */
 
 #define SSCR0_P1	__REG(0x41000000)  /* SSP Port 1 Control Register 0 */
 #define SSCR1_P1	__REG(0x41000004)  /* SSP Port 1 Control Register 1 */
diff --git a/include/asm-arm/arch-pxa/udc.h b/include/asm-arm/arch-pxa/udc.h
index 646480d..8bc6f9c 100644
--- a/include/asm-arm/arch-pxa/udc.h
+++ b/include/asm-arm/arch-pxa/udc.h
@@ -9,3 +9,33 @@
 
 extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
 
+static inline int udc_gpio_to_irq(unsigned gpio)
+{
+	return IRQ_GPIO(gpio & GPIO_MD_MASK_NR);
+}
+
+static inline void udc_gpio_init_vbus(unsigned gpio)
+{
+	pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_IN);
+}
+
+static inline void udc_gpio_init_pullup(unsigned gpio)
+{
+	pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_OUT | GPIO_DFLT_LOW);
+}
+
+static inline int udc_gpio_get(unsigned gpio)
+{
+	return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
+}
+
+static inline void udc_gpio_set(unsigned gpio, int is_on)
+{
+	int mask = GPIO_bit(gpio);
+
+	if (is_on)
+		GPSR(gpio) = mask;
+	else
+		GPCR(gpio) = mask;
+}
+
diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S
index 1a6eec8..138838d 100644
--- a/include/asm-arm/arch-realview/entry-macro.S
+++ b/include/asm-arm/arch-realview/entry-macro.S
@@ -13,6 +13,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		/*
 		 * The interrupt numbering scheme is defined in the
 		 * interrupt controller spec.  To wit:
diff --git a/include/asm-arm/arch-realview/hardware.h b/include/asm-arm/arch-realview/hardware.h
index 9ca76dc..aa78fe0 100644
--- a/include/asm-arm/arch-realview/hardware.h
+++ b/include/asm-arm/arch-realview/hardware.h
@@ -26,7 +26,7 @@
 #include <asm/arch/platform.h>
 
 /* macro to get at IO space when running virtually */
-#define IO_ADDRESS(x)		(((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
+#define IO_ADDRESS(x)		((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000)
 #define __io_address(n)		__io(IO_ADDRESS(n))
 
 #endif
diff --git a/include/asm-arm/arch-realview/irqs.h b/include/asm-arm/arch-realview/irqs.h
index c16223c..5a5db56 100644
--- a/include/asm-arm/arch-realview/irqs.h
+++ b/include/asm-arm/arch-realview/irqs.h
@@ -65,6 +65,21 @@
 #define IRQ_AACI		(IRQ_GIC_START + INT_AACI)
 #define IRQ_ETH			(IRQ_GIC_START + INT_ETH)
 #define IRQ_USB			(IRQ_GIC_START + INT_USB)
+#define IRQ_PMU_CPU0		(IRQ_GIC_START + INT_PMU_CPU0)
+#define IRQ_PMU_CPU1		(IRQ_GIC_START + INT_PMU_CPU1)
+#define IRQ_PMU_CPU2		(IRQ_GIC_START + INT_PMU_CPU2)
+#define IRQ_PMU_CPU3		(IRQ_GIC_START + INT_PMU_CPU3)
+#define IRQ_PMU_SCU0		(IRQ_GIC_START + INT_PMU_SCU0)
+#define IRQ_PMU_SCU1		(IRQ_GIC_START + INT_PMU_SCU1)
+#define IRQ_PMU_SCU2		(IRQ_GIC_START + INT_PMU_SCU2)
+#define IRQ_PMU_SCU3		(IRQ_GIC_START + INT_PMU_SCU3)
+#define IRQ_PMU_SCU4		(IRQ_GIC_START + INT_PMU_SCU4)
+#define IRQ_PMU_SCU5		(IRQ_GIC_START + INT_PMU_SCU5)
+#define IRQ_PMU_SCU6		(IRQ_GIC_START + INT_PMU_SCU6)
+#define IRQ_PMU_SCU7		(IRQ_GIC_START + INT_PMU_SCU7)
+
+#define IRQ_EB_IRQ1		(IRQ_GIC_START + INT_EB_IRQ1)
+#define IRQ_EB_IRQ2		(IRQ_GIC_START + INT_EB_IRQ2)
 
 #define IRQMASK_WDOGINT		INTMASK_WDOGINT
 #define IRQMASK_SOFTINT		INTMASK_SOFTINT
@@ -103,4 +118,4 @@
 #define IRQMASK_ETH		INTMASK_ETH
 #define IRQMASK_USB		INTMASK_USB
 
-#define NR_IRQS			(IRQ_GIC_START + 64)
+#define NR_IRQS			(IRQ_GIC_START + 96)
diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h
index 18d7c18..6e0eab9 100644
--- a/include/asm-arm/arch-realview/platform.h
+++ b/include/asm-arm/arch-realview/platform.h
@@ -207,11 +207,25 @@
 #define REALVIEW_GIC_CPU_BASE         0x10040000	/* Generic interrupt controller CPU interface */
 #define REALVIEW_GIC_DIST_BASE        0x10041000	/* Generic interrupt controller distributor */
 #else
+#ifdef CONFIG_REALVIEW_MPCORE_REVB
 #define REALVIEW_MPCORE_SCU_BASE	0x10100000	/*  SCU registers */
 #define REALVIEW_GIC_CPU_BASE		0x10100100	/* Generic interrupt controller CPU interface */
 #define REALVIEW_TWD_BASE		0x10100700
 #define REALVIEW_TWD_SIZE		0x00000100
 #define REALVIEW_GIC_DIST_BASE		0x10101000	/* Generic interrupt controller distributor */
+#define REALVIEW_MPCORE_L220_BASE	0x10102000	/* L220 registers */
+#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0xD8		/*  Register offset for MPCore sysctl */
+#else
+#define REALVIEW_MPCORE_SCU_BASE      0x1F000000	/*  SCU registers */
+#define REALVIEW_GIC_CPU_BASE         0x1F000100	/* Generic interrupt controller CPU interface */
+#define REALVIEW_TWD_BASE             0x1F000700
+#define REALVIEW_TWD_SIZE             0x00000100
+#define REALVIEW_GIC_DIST_BASE        0x1F001000	/* Generic interrupt controller distributor */
+#define REALVIEW_MPCORE_L220_BASE     0x1F002000	/* L220 registers */
+#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0x74		/*  Register offset for MPCore sysctl */
+#endif
+#define REALVIEW_GIC1_CPU_BASE        0x10040000	/* Generic interrupt controller CPU interface */
+#define REALVIEW_GIC1_DIST_BASE       0x10041000	/* Generic interrupt controller distributor */
 #endif
 #define REALVIEW_SMC_BASE             0x10080000	/* SMC */
 	/* Reserved 0x10090000 - 0x100EFFFF */
@@ -306,7 +320,11 @@
 #define INT_USB				29	/* USB controller */
 #define INT_TSPENINT			30	/* Touchscreen pen */
 #define INT_TSKPADINT			31	/* Touchscreen keypad */
+
 #else
+
+#define MAX_GIC_NR			2
+
 #define INT_AACI			0
 #define INT_TIMERINT0_1			1
 #define INT_TIMERINT2_3			2
diff --git a/include/asm-arm/arch-realview/scu.h b/include/asm-arm/arch-realview/scu.h
new file mode 100644
index 0000000..cc29364
--- /dev/null
+++ b/include/asm-arm/arch-realview/scu.h
@@ -0,0 +1,8 @@
+#ifndef __ASMARM_ARCH_SCU_H
+#define __ASMARM_ARCH_SCU_H
+
+#include <asm/arch/platform.h>
+
+#define SCU_BASE	REALVIEW_MPCORE_SCU_BASE
+
+#endif
diff --git a/include/asm-arm/arch-rpc/entry-macro.S b/include/asm-arm/arch-rpc/entry-macro.S
index c9e5395..0cfb89b 100644
--- a/include/asm-arm/arch-rpc/entry-macro.S
+++ b/include/asm-arm/arch-rpc/entry-macro.S
@@ -1,3 +1,8 @@
 #include <asm/hardware.h>
 #include <asm/hardware/entry-macro-iomd.S>
+	.macro  get_irqnr_preamble, base, tmp
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
 
diff --git a/include/asm-arm/arch-s3c2410/audio.h b/include/asm-arm/arch-s3c2410/audio.h
index 65e0acf..0a6977f 100644
--- a/include/asm-arm/arch-s3c2410/audio.h
+++ b/include/asm-arm/arch-s3c2410/audio.h
@@ -31,9 +31,9 @@
 	int	(*suspend)(struct s3c24xx_iis_ops *me);
 	int	(*resume)(struct s3c24xx_iis_ops *me);
 
-	int	(*open)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm);
-	int	(*close)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm);
-	int	(*prepare)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm, snd_pcm_runtime_t *rt);
+	int	(*open)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
+	int	(*close)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
+	int	(*prepare)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm, struct snd_pcm_runtime *rt);
 };
 
 struct s3c24xx_platdata_iis {
diff --git a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
index 58ffa7b..c6e8d8f 100644
--- a/include/asm-arm/arch-s3c2410/dma.h
+++ b/include/asm-arm/arch-s3c2410/dma.h
@@ -51,13 +51,19 @@
 	DMACH_UART0_SRC2,	/* s3c2412 second uart sources */
 	DMACH_UART1_SRC2,
 	DMACH_UART2_SRC2,
+	DMACH_UART3,		/* s3c2443 has extra uart */
+	DMACH_UART3_SRC2,
 	DMACH_MAX,		/* the end entry */
 };
 
 #define DMACH_LOW_LEVEL	(1<<28)	/* use this to specifiy hardware ch no */
 
 /* we have 4 dma channels */
-#define S3C2410_DMA_CHANNELS        (4)
+#ifndef CONFIG_CPU_S3C2443
+#define S3C2410_DMA_CHANNELS		(4)
+#else
+#define S3C2410_DMA_CHANNELS		(6)
+#endif
 
 /* types */
 
@@ -321,6 +327,7 @@
 #define S3C2410_DMA_DCDST       (0x1C)
 #define S3C2410_DMA_DMASKTRIG   (0x20)
 #define S3C2412_DMA_DMAREQSEL	(0x24)
+#define S3C2443_DMA_DMAREQSEL	(0x24)
 
 #define S3C2410_DISRCC_INC	(1<<0)
 #define S3C2410_DISRCC_APB	(1<<1)
@@ -415,4 +422,31 @@
 #define S3C2412_DMAREQSEL_UART2_1	S3C2412_DMAREQSEL_SRC(24)
 
 #endif
+
+#define S3C2443_DMAREQSEL_SRC(x)	((x)<<1)
+
+#define S3C2443_DMAREQSEL_HW		(1)
+
+#define S3C2443_DMAREQSEL_SPI0TX	S3C2443_DMAREQSEL_SRC(0)
+#define S3C2443_DMAREQSEL_SPI0RX	S3C2443_DMAREQSEL_SRC(1)
+#define S3C2443_DMAREQSEL_SPI1TX	S3C2443_DMAREQSEL_SRC(2)
+#define S3C2443_DMAREQSEL_SPI1RX	S3C2443_DMAREQSEL_SRC(3)
+#define S3C2443_DMAREQSEL_I2STX		S3C2443_DMAREQSEL_SRC(4)
+#define S3C2443_DMAREQSEL_I2SRX		S3C2443_DMAREQSEL_SRC(5)
+#define S3C2443_DMAREQSEL_TIMER		S3C2443_DMAREQSEL_SRC(9)
+#define S3C2443_DMAREQSEL_SDI		S3C2443_DMAREQSEL_SRC(10)
+#define S3C2443_DMAREQSEL_XDREQ0	S3C2443_DMAREQSEL_SRC(17)
+#define S3C2443_DMAREQSEL_XDREQ1	S3C2443_DMAREQSEL_SRC(18)
+#define S3C2443_DMAREQSEL_UART0_0	S3C2443_DMAREQSEL_SRC(19)
+#define S3C2443_DMAREQSEL_UART0_1	S3C2443_DMAREQSEL_SRC(20)
+#define S3C2443_DMAREQSEL_UART1_0	S3C2443_DMAREQSEL_SRC(21)
+#define S3C2443_DMAREQSEL_UART1_1	S3C2443_DMAREQSEL_SRC(22)
+#define S3C2443_DMAREQSEL_UART2_0	S3C2443_DMAREQSEL_SRC(23)
+#define S3C2443_DMAREQSEL_UART2_1	S3C2443_DMAREQSEL_SRC(24)
+#define S3C2443_DMAREQSEL_UART3_0	S3C2443_DMAREQSEL_SRC(25)
+#define S3C2443_DMAREQSEL_UART3_1	S3C2443_DMAREQSEL_SRC(26)
+#define S3C2443_DMAREQSEL_PCMOUT	S3C2443_DMAREQSEL_SRC(27)
+#define S3C2443_DMAREQSEL_PCMIN 	S3C2443_DMAREQSEL_SRC(28)
+#define S3C2443_DMAREQSEL_MICIN		S3C2443_DMAREQSEL_SRC(29)
+
 #endif /* __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index 1eb4e6b..bbec0a8 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -22,6 +22,12 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 
+	.macro  get_irqnr_preamble, base, tmp
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 
 		mov	\base, #S3C24XX_VA_IRQ
diff --git a/include/asm-arm/arch-s3c2410/gpio.h b/include/asm-arm/arch-s3c2410/gpio.h
new file mode 100644
index 0000000..d47ae45
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/gpio.h
@@ -0,0 +1,66 @@
+/*
+ * linux/include/asm-arm/arch-s3c2410/gpio.h
+ *
+ * S3C2410 GPIO wrappers for arch-neutral GPIO calls
+ *
+ * Written by Philipp Zabel <philipp.zabel@gmail.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
+ *
+ */
+
+#ifndef __ASM_ARCH_S3C2410_GPIO_H
+#define __ASM_ARCH_S3C2410_GPIO_H
+
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/arch/regs-gpio.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	return;
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	s3c2410_gpio_cfgpin(gpio, S3C2410_GPIO_INPUT);
+	return 0;
+}
+
+static inline int gpio_direction_output(unsigned gpio)
+{
+	s3c2410_gpio_cfgpin(gpio, S3C2410_GPIO_OUTPUT);
+	return 0;
+}
+
+#define gpio_get_value(gpio)		s3c2410_gpio_getpin(gpio)
+#define gpio_set_value(gpio,value)	s3c2410_gpio_setpin(gpio, value)
+
+#include <asm-generic/gpio.h>			/* cansleep wrappers */
+
+#ifdef CONFIG_CPU_S3C2400
+#define gpio_to_irq(gpio)		s3c2400_gpio_getirq(gpio)
+#else
+#define gpio_to_irq(gpio)		s3c2410_gpio_getirq(gpio)
+#endif
+
+/* FIXME implement irq_to_gpio() */
+
+#endif
diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
index 4b7cff4..c79cb18 100644
--- a/include/asm-arm/arch-s3c2410/irqs.h
+++ b/include/asm-arm/arch-s3c2410/irqs.h
@@ -34,10 +34,10 @@
 #define IRQ_EINT4t7    S3C2410_IRQ(4)	    /* 20 */
 #define IRQ_EINT8t23   S3C2410_IRQ(5)
 #define IRQ_RESERVED6  S3C2410_IRQ(6)	    /* for s3c2410 */
-#define IRQ_CAM        S3C2410_IRQ(6)	    /* for s3c2440 */
+#define IRQ_CAM        S3C2410_IRQ(6)	    /* for s3c2440,s3c2443 */
 #define IRQ_BATT_FLT   S3C2410_IRQ(7)
 #define IRQ_TICK       S3C2410_IRQ(8)	    /* 24 */
-#define IRQ_WDT	       S3C2410_IRQ(9)
+#define IRQ_WDT	       S3C2410_IRQ(9)	    /* WDT/AC97 for s3c2443 */
 #define IRQ_TIMER0     S3C2410_IRQ(10)
 #define IRQ_TIMER1     S3C2410_IRQ(11)
 #define IRQ_TIMER2     S3C2410_IRQ(12)
@@ -45,7 +45,7 @@
 #define IRQ_TIMER4     S3C2410_IRQ(14)
 #define IRQ_UART2      S3C2410_IRQ(15)
 #define IRQ_LCD	       S3C2410_IRQ(16)	    /* 32 */
-#define IRQ_DMA0       S3C2410_IRQ(17)
+#define IRQ_DMA0       S3C2410_IRQ(17)	    /* IRQ_DMA for s3c2443 */
 #define IRQ_DMA1       S3C2410_IRQ(18)
 #define IRQ_DMA2       S3C2410_IRQ(19)
 #define IRQ_DMA3       S3C2410_IRQ(20)
@@ -94,29 +94,63 @@
  * these need to be ordered in number of appearance in the
  * SUBSRC mask register
 */
-#define IRQ_S3CUART_RX0  S3C2410_IRQ(54)   /* 70 */
-#define IRQ_S3CUART_TX0  S3C2410_IRQ(55)   /* 71 */
-#define IRQ_S3CUART_ERR0 S3C2410_IRQ(56)
 
-#define IRQ_S3CUART_RX1  S3C2410_IRQ(57)
-#define IRQ_S3CUART_TX1  S3C2410_IRQ(58)
-#define IRQ_S3CUART_ERR1 S3C2410_IRQ(59)
+#define S3C2410_IRQSUB(x)	S3C2410_IRQ((x)+54)
 
-#define IRQ_S3CUART_RX2  S3C2410_IRQ(60)
-#define IRQ_S3CUART_TX2  S3C2410_IRQ(61)
-#define IRQ_S3CUART_ERR2 S3C2410_IRQ(62)
+#define IRQ_S3CUART_RX0		S3C2410_IRQSUB(0)	/* 70 */
+#define IRQ_S3CUART_TX0		S3C2410_IRQSUB(1)
+#define IRQ_S3CUART_ERR0	S3C2410_IRQSUB(2)
 
-#define IRQ_TC		 S3C2410_IRQ(63)
-#define IRQ_ADC		 S3C2410_IRQ(64)
+#define IRQ_S3CUART_RX1		S3C2410_IRQSUB(3)	/* 73 */
+#define IRQ_S3CUART_TX1		S3C2410_IRQSUB(4)
+#define IRQ_S3CUART_ERR1	S3C2410_IRQSUB(5)
+
+#define IRQ_S3CUART_RX2		S3C2410_IRQSUB(6)	/* 76 */
+#define IRQ_S3CUART_TX2		S3C2410_IRQSUB(7)
+#define IRQ_S3CUART_ERR2	S3C2410_IRQSUB(8)
+
+#define IRQ_TC			S3C2410_IRQSUB(9)
+#define IRQ_ADC			S3C2410_IRQSUB(10)
 
 /* extra irqs for s3c2440 */
 
-#define IRQ_S3C2440_CAM_C	S3C2410_IRQ(65)
-#define IRQ_S3C2440_CAM_P	S3C2410_IRQ(66)
-#define IRQ_S3C2440_WDT		S3C2410_IRQ(67)
-#define IRQ_S3C2440_AC97	S3C2410_IRQ(68)
+#define IRQ_S3C2440_CAM_C	S3C2410_IRQSUB(11)	/* S3C2443 too */
+#define IRQ_S3C2440_CAM_P	S3C2410_IRQSUB(12)	/* S3C2443 too */
+#define IRQ_S3C2440_WDT		S3C2410_IRQSUB(13)
+#define IRQ_S3C2440_AC97	S3C2410_IRQSUB(14)
 
+/* irqs for s3c2443 */
+
+#define IRQ_S3C2443_DMA		S3C2410_IRQ(17)		/* IRQ_DMA1 */
+#define IRQ_S3C2443_UART3	S3C2410_IRQ(18)		/* IRQ_DMA2 */
+#define IRQ_S3C2443_CFCON	S3C2410_IRQ(19)		/* IRQ_DMA3 */
+#define IRQ_S3C2443_SDI1	S3C2410_IRQ(20)		/* IRQ_SDI */
+#define IRQ_S3C2443_NAND	S3C2410_IRQ(24)		/* reserved */
+
+#define IRQ_S3C2443_LCD1	S3C2410_IRQSUB(14)
+#define IRQ_S3C2443_LCD2	S3C2410_IRQSUB(15)
+#define IRQ_S3C2443_LCD3	S3C2410_IRQSUB(16)
+#define IRQ_S3C2443_LCD4	S3C2410_IRQSUB(17)
+
+#define IRQ_S3C2443_DMA0	S3C2410_IRQSUB(18)
+#define IRQ_S3C2443_DMA1	S3C2410_IRQSUB(19)
+#define IRQ_S3C2443_DMA2	S3C2410_IRQSUB(20)
+#define IRQ_S3C2443_DMA3	S3C2410_IRQSUB(21)
+#define IRQ_S3C2443_DMA4	S3C2410_IRQSUB(22)
+#define IRQ_S3C2443_DMA5	S3C2410_IRQSUB(23)
+
+/* UART3 */
+#define IRQ_S3C2443_RX3		S3C2410_IRQSUB(24)
+#define IRQ_S3C2443_TX3		S3C2410_IRQSUB(25)
+#define IRQ_S3C2443_ERR3	S3C2410_IRQSUB(26)
+
+#define IRQ_S3C2443_WDT		S3C2410_IRQSUB(27)
+#define IRQ_S3C2443_AC97	S3C2410_IRQSUB(28)
+
+#ifdef CONFIG_CPU_S3C2443
+#define NR_IRQS (IRQ_S3C2443_AC97+1)
+#else
 #define NR_IRQS (IRQ_S3C2440_AC97+1)
-
+#endif
 
 #endif /* __ASM_ARCH_IRQ_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-adc.h b/include/asm-arm/arch-s3c2410/regs-adc.h
index 3196a28..c7f2319 100644
--- a/include/asm-arm/arch-s3c2410/regs-adc.h
+++ b/include/asm-arm/arch-s3c2410/regs-adc.h
@@ -41,7 +41,7 @@
 #define S3C2410_ADCTSC_XP_SEN		(1<<4)
 #define S3C2410_ADCTSC_PULL_UP_DISABLE	(1<<3)
 #define S3C2410_ADCTSC_AUTO_PST		(1<<2)
-#define S3C2410_ADCTSC_XY_PST		(0x3<<0)
+#define S3C2410_ADCTSC_XY_PST(x)	(((x)&0x3)<<0)
 
 /* ADCDAT0 Bits */
 #define S3C2410_ADCDAT0_UPDOWN		(1<<15)
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index eae9169..dea578b 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -201,7 +201,7 @@
 #define S3C2400_GPBDAT	   S3C2410_GPIOREG(0x0C)
 #define S3C2400_GPBUP	   S3C2410_GPIOREG(0x10)
 
-/* no i/o pin in port b can have value 3! */
+/* no i/o pin in port b can have value 3 (unless it is a s3c2443) ! */
 
 #define S3C2410_GPB0         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 0)
 #define S3C2410_GPB0_INP     (0x00 << 0)
@@ -242,6 +242,7 @@
 #define S3C2410_GPB5_INP     (0x00 << 10)
 #define S3C2410_GPB5_OUTP    (0x01 << 10)
 #define S3C2410_GPB5_nXBACK  (0x02 << 10)
+#define S3C2443_GPB5_XBACK   (0x03 << 10)
 #define S3C2400_GPB5_DATA21  (0x02 << 10)
 #define S3C2400_GPB5_nCTS1   (0x03 << 10)
 
@@ -249,6 +250,7 @@
 #define S3C2410_GPB6_INP     (0x00 << 12)
 #define S3C2410_GPB6_OUTP    (0x01 << 12)
 #define S3C2410_GPB6_nXBREQ  (0x02 << 12)
+#define S3C2443_GPB6_XBREQ   (0x03 << 12)
 #define S3C2400_GPB6_DATA22  (0x02 << 12)
 #define S3C2400_GPB6_nRTS1   (0x03 << 12)
 
@@ -256,6 +258,7 @@
 #define S3C2410_GPB7_INP     (0x00 << 14)
 #define S3C2410_GPB7_OUTP    (0x01 << 14)
 #define S3C2410_GPB7_nXDACK1 (0x02 << 14)
+#define S3C2443_GPB7_XDACK1  (0x03 << 14)
 #define S3C2400_GPB7_DATA23  (0x02 << 14)
 
 #define S3C2410_GPB8         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 8)
@@ -268,6 +271,7 @@
 #define S3C2410_GPB9_INP     (0x00 << 18)
 #define S3C2410_GPB9_OUTP    (0x01 << 18)
 #define S3C2410_GPB9_nXDACK0 (0x02 << 18)
+#define S3C2443_GPB9_XDACK0  (0x03 << 18)
 #define S3C2400_GPB9_DATA25  (0x02 << 18)
 #define S3C2400_GPB9_I2SSDI  (0x03 << 18)
 
@@ -275,6 +279,7 @@
 #define S3C2410_GPB10_INP    (0x00 << 20)
 #define S3C2410_GPB10_OUTP   (0x01 << 20)
 #define S3C2410_GPB10_nXDRE0 (0x02 << 20)
+#define S3C2443_GPB10_XDREQ0 (0x03 << 20)
 #define S3C2400_GPB10_DATA26 (0x02 << 20)
 #define S3C2400_GPB10_nSS    (0x03 << 20)
 
@@ -556,6 +561,7 @@
 #define S3C2410_GPE0_INP       (0x00 << 0)
 #define S3C2410_GPE0_OUTP      (0x01 << 0)
 #define S3C2410_GPE0_I2SLRCK   (0x02 << 0)
+#define S3C2443_GPE0_AC_nRESET (0x03 << 0)
 #define S3C2400_GPE0_EINT0     (0x02 << 0)
 #define S3C2410_GPE0_MASK      (0x03 << 0)
 
@@ -563,6 +569,7 @@
 #define S3C2410_GPE1_INP       (0x00 << 2)
 #define S3C2410_GPE1_OUTP      (0x01 << 2)
 #define S3C2410_GPE1_I2SSCLK   (0x02 << 2)
+#define S3C2443_GPE1_AC_SYNC   (0x03 << 2)
 #define S3C2400_GPE1_EINT1     (0x02 << 2)
 #define S3C2400_GPE1_nSS       (0x03 << 2)
 #define S3C2410_GPE1_MASK      (0x03 << 2)
@@ -571,6 +578,7 @@
 #define S3C2410_GPE2_INP       (0x00 << 4)
 #define S3C2410_GPE2_OUTP      (0x01 << 4)
 #define S3C2410_GPE2_CDCLK     (0x02 << 4)
+#define S3C2443_GPE2_AC_BITCLK (0x03 << 4)
 #define S3C2400_GPE2_EINT2     (0x02 << 4)
 #define S3C2400_GPE2_I2SSDI    (0x03 << 4)
 
@@ -578,6 +586,7 @@
 #define S3C2410_GPE3_INP       (0x00 << 6)
 #define S3C2410_GPE3_OUTP      (0x01 << 6)
 #define S3C2410_GPE3_I2SSDI    (0x02 << 6)
+#define S3C2443_GPE3_AC_SDI    (0x03 << 6)
 #define S3C2400_GPE3_EINT3     (0x02 << 6)
 #define S3C2400_GPE3_nCTS1     (0x03 << 6)
 #define S3C2410_GPE3_nSS0      (0x03 << 6)
@@ -587,6 +596,7 @@
 #define S3C2410_GPE4_INP       (0x00 << 8)
 #define S3C2410_GPE4_OUTP      (0x01 << 8)
 #define S3C2410_GPE4_I2SSDO    (0x02 << 8)
+#define S3C2443_GPE4_AC_SDO    (0x03 << 8)
 #define S3C2400_GPE4_EINT4     (0x02 << 8)
 #define S3C2400_GPE4_nRTS1     (0x03 << 8)
 #define S3C2410_GPE4_I2SSDI    (0x03 << 8)
@@ -596,6 +606,7 @@
 #define S3C2410_GPE5_INP       (0x00 << 10)
 #define S3C2410_GPE5_OUTP      (0x01 << 10)
 #define S3C2410_GPE5_SDCLK     (0x02 << 10)
+#define S3C2443_GPE5_SD1_CLK   (0x02 << 10)
 #define S3C2400_GPE5_EINT5     (0x02 << 10)
 #define S3C2400_GPE5_TCLK1     (0x03 << 10)
 
@@ -603,24 +614,32 @@
 #define S3C2410_GPE6_INP       (0x00 << 12)
 #define S3C2410_GPE6_OUTP      (0x01 << 12)
 #define S3C2410_GPE6_SDCMD     (0x02 << 12)
+#define S3C2443_GPE6_SD1_CMD   (0x02 << 12)
+#define S3C2443_GPE6_AC_BITCLK (0x03 << 12)
 #define S3C2400_GPE6_EINT6     (0x02 << 12)
 
 #define S3C2410_GPE7           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 7)
 #define S3C2410_GPE7_INP       (0x00 << 14)
 #define S3C2410_GPE7_OUTP      (0x01 << 14)
 #define S3C2410_GPE7_SDDAT0    (0x02 << 14)
+#define S3C2443_GPE5_SD1_DAT0  (0x02 << 14)
+#define S3C2443_GPE7_AC_SDI    (0x03 << 14)
 #define S3C2400_GPE7_EINT7     (0x02 << 14)
 
 #define S3C2410_GPE8           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 8)
 #define S3C2410_GPE8_INP       (0x00 << 16)
 #define S3C2410_GPE8_OUTP      (0x01 << 16)
 #define S3C2410_GPE8_SDDAT1    (0x02 << 16)
+#define S3C2443_GPE8_SD1_DAT1  (0x02 << 16)
+#define S3C2443_GPE8_AC_SDO    (0x03 << 16)
 #define S3C2400_GPE8_nXDACK0   (0x02 << 16)
 
 #define S3C2410_GPE9           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 9)
 #define S3C2410_GPE9_INP       (0x00 << 18)
 #define S3C2410_GPE9_OUTP      (0x01 << 18)
 #define S3C2410_GPE9_SDDAT2    (0x02 << 18)
+#define S3C2443_GPE9_SD1_DAT2  (0x02 << 18)
+#define S3C2443_GPE9_AC_SYNC   (0x03 << 18)
 #define S3C2400_GPE9_nXDACK1   (0x02 << 18)
 #define S3C2400_GPE9_nXBACK    (0x03 << 18)
 
@@ -628,6 +647,8 @@
 #define S3C2410_GPE10_INP      (0x00 << 20)
 #define S3C2410_GPE10_OUTP     (0x01 << 20)
 #define S3C2410_GPE10_SDDAT3   (0x02 << 20)
+#define S3C2443_GPE10_SD1_DAT3 (0x02 << 20)
+#define S3C2443_GPE10_AC_nRESET (0x03 << 20)
 #define S3C2400_GPE10_nXDREQ0  (0x02 << 20)
 
 #define S3C2410_GPE11          S3C2410_GPIONO(S3C2410_GPIO_BANKE, 11)
@@ -796,6 +817,7 @@
 #define S3C2400_GPG4_MMCCLK   (0x02 << 8)
 #define S3C2400_GPG4_I2SSDI   (0x03 << 8)
 #define S3C2410_GPG4_LCDPWREN (0x03 << 8)
+#define S3C2443_GPG4_LCDPWRDN (0x03 << 8)
 
 #define S3C2410_GPG5          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 5)
 #define S3C2410_GPG5_INP      (0x00 << 10)
@@ -803,7 +825,7 @@
 #define S3C2410_GPG5_EINT13   (0x02 << 10)
 #define S3C2400_GPG5_MMCCMD   (0x02 << 10)
 #define S3C2400_GPG5_IICSDA   (0x03 << 10)
-#define S3C2410_GPG5_SPIMISO1 (0x03 << 10)
+#define S3C2410_GPG5_SPIMISO1 (0x03 << 10)	/* not s3c2443 */
 
 #define S3C2410_GPG6          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 6)
 #define S3C2410_GPG6_INP      (0x00 << 12)
@@ -845,6 +867,7 @@
 #define S3C2410_GPG11_OUTP    (0x01 << 22)
 #define S3C2410_GPG11_EINT19  (0x02 << 22)
 #define S3C2410_GPG11_TCLK1   (0x03 << 22)
+#define S3C2443_GPG11_CF_nIREQ (0x03 << 22)
 
 #define S3C2410_GPG12         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 12)
 #define S3C2410_GPG12_INP     (0x00 << 24)
@@ -852,25 +875,28 @@
 #define S3C2410_GPG12_EINT20  (0x02 << 24)
 #define S3C2410_GPG12_XMON    (0x03 << 24)
 #define S3C2442_GPG12_nSPICS0 (0x03 << 24)
+#define S3C2443_GPG12_nINPACK (0x03 << 24)
 
 #define S3C2410_GPG13         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13)
 #define S3C2410_GPG13_INP     (0x00 << 26)
 #define S3C2410_GPG13_OUTP    (0x01 << 26)
 #define S3C2410_GPG13_EINT21  (0x02 << 26)
 #define S3C2410_GPG13_nXPON   (0x03 << 26)
+#define S3C2443_GPG13_CF_nREG (0x03 << 26)
 
 #define S3C2410_GPG14         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 14)
 #define S3C2410_GPG14_INP     (0x00 << 28)
 #define S3C2410_GPG14_OUTP    (0x01 << 28)
 #define S3C2410_GPG14_EINT22  (0x02 << 28)
 #define S3C2410_GPG14_YMON    (0x03 << 28)
+#define S3C2443_GPG14_CF_RESET (0x03 << 28)
 
 #define S3C2410_GPG15         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 15)
 #define S3C2410_GPG15_INP     (0x00 << 30)
 #define S3C2410_GPG15_OUTP    (0x01 << 30)
 #define S3C2410_GPG15_EINT23  (0x02 << 30)
 #define S3C2410_GPG15_nYPON   (0x03 << 30)
-
+#define S3C2443_GPG15_CF_PWR  (0x03 << 30)
 
 #define S3C2410_GPG_PUPDIS(x)  (1<<(x))
 
diff --git a/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h b/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h
new file mode 100644
index 0000000..ff0536d
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h
@@ -0,0 +1,194 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-clock.h
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * 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.
+ *
+ * S3C2443 clock register definitions
+*/
+
+#ifndef __ASM_ARM_REGS_S3C2443_CLOCK
+#define __ASM_ARM_REGS_S3C2443_CLOCK
+
+#define S3C2443_CLKREG(x)		((x) + S3C24XX_VA_CLKPWR)
+
+#define S3C2443_PLLCON_MDIVSHIFT	16
+#define S3C2443_PLLCON_PDIVSHIFT	8
+#define S3C2443_PLLCON_SDIVSHIFT	0
+#define S3C2443_PLLCON_MDIVMASK		((1<<(1+(23-16)))-1)
+#define S3C2443_PLLCON_PDIVMASK		((1<<(1+(9-8)))-1)
+#define S3C2443_PLLCON_SDIVMASK		(3)
+
+#define S3C2443_MPLLCON			S3C2443_CLKREG(0x10)
+#define S3C2443_EPLLCON			S3C2443_CLKREG(0x18)
+#define S3C2443_CLKSRC			S3C2443_CLKREG(0x20)
+#define S3C2443_CLKDIV0			S3C2443_CLKREG(0x24)
+#define S3C2443_CLKDIV1			S3C2443_CLKREG(0x28)
+#define S3C2443_HCLKCON			S3C2443_CLKREG(0x30)
+#define S3C2443_PCLKCON			S3C2443_CLKREG(0x34)
+#define S3C2443_SCLKCON			S3C2443_CLKREG(0x38)
+#define S3C2443_PWRMODE			S3C2443_CLKREG(0x40)
+#define S3C2443_SWRST			S3C2443_CLKREG(0x44)
+#define S3C2443_BUSPRI0			S3C2443_CLKREG(0x50)
+#define S3C2443_SYSID			S3C2443_CLKREG(0x5C)
+#define S3C2443_PWRCFG			S3C2443_CLKREG(0x60)
+#define S3C2443_RSTCON			S3C2443_CLKREG(0x64)
+
+#define S3C2443_SWRST_RESET		(0x533c2443)
+
+#define S3C2443_PLLCON_OFF		(1<<24)
+
+#define S3C2443_CLKSRC_I2S_EXT		(1<<14)
+#define S3C2443_CLKSRC_I2S_EPLLDIV	(0<<14)
+#define S3C2443_CLKSRC_I2S_EPLLREF	(2<<14)
+#define S3C2443_CLKSRC_I2S_EPLLREF3	(3<<14)
+#define S3C2443_CLKSRC_I2S_MASK		(3<<14)
+
+#define S3C2443_CLKSRC_EPLLREF_XTAL	(2<<8)
+#define S3C2443_CLKSRC_EPLLREF_EXTCLK	(3<<8)
+#define S3C2443_CLKSRC_EPLLREF_MPLLREF	(0<<8)
+#define S3C2443_CLKSRC_EPLLREF_MPLLREF2	(1<<8)
+#define S3C2443_CLKSRC_EPLLREF_MASK	(3<<8)
+
+#define S3C2443_CLKSRC_ESYSCLK_EPLL	(1<<6)
+#define S3C2443_CLKSRC_MSYSCLK_MPLL	(1<<4)
+#define S3C2443_CLKSRC_EXTCLK_DIV	(1<<3)
+
+#define S3C2443_CLKDIV0_DVS		(1<<13)
+#define S3C2443_CLKDIV0_HALF_HCLK	(1<<3)
+#define S3C2443_CLKDIV0_HALF_PCLK	(1<<2)
+
+#define S3C2443_CLKDIV0_HCLKDIV_MASK	(3<<0)
+
+#define S3C2443_CLKDIV0_EXTDIV_MASK	(3<<6)
+#define S3C2443_CLKDIV0_EXTDIV_SHIFT	(6)
+
+#define S3C2443_CLKDIV0_PREDIV_MASK	(3<<4)
+#define S3C2443_CLKDIV0_PREDIV_SHIFT	(4)
+
+#define S3C2443_CLKDIV0_ARMDIV_MASK	(15<<9)
+#define S3C2443_CLKDIV0_ARMDIV_SHIFT	(9)
+#define S3C2443_CLKDIV0_ARMDIV_1	(0<<9)
+#define S3C2443_CLKDIV0_ARMDIV_2	(8<<9)
+#define S3C2443_CLKDIV0_ARMDIV_3	(2<<9)
+#define S3C2443_CLKDIV0_ARMDIV_4	(9<<9)
+#define S3C2443_CLKDIV0_ARMDIV_6	(10<<9)
+#define S3C2443_CLKDIV0_ARMDIV_8	(11<<9)
+#define S3C2443_CLKDIV0_ARMDIV_12	(13<<9)
+#define S3C2443_CLKDIV0_ARMDIV_16	(15<<9)
+
+/* S3C2443_CLKDIV1 */
+
+#define S3C2443_CLKDIV1_CAMDIV_MASK	(15<<26)
+#define S3C2443_CLKDIV1_CAMDIV_SHIFT	(26)
+
+#define S3C2443_CLKDIV1_HSSPIDIV_MASK	(3<<24)
+#define S3C2443_CLKDIV1_HSSPIDIV_SHIFT	(24)
+
+#define S3C2443_CLKDIV1_DISPDIV_MASK	(0xff<<16)
+#define S3C2443_CLKDIV1_DISPDIV_SHIFT	(16)
+
+#define S3C2443_CLKDIV1_I2SDIV_MASK	(15<<12)
+#define S3C2443_CLKDIV1_I2SDIV_SHIFT	(12)
+
+#define S3C2443_CLKDIV1_UARTDIV_MASK	(15<<8)
+#define S3C2443_CLKDIV1_UARTDIV_SHIFT	(8)
+
+#define S3C2443_CLKDIV1_HSMMCDIV_MASK	(3<<6)
+#define S3C2443_CLKDIV1_HSMMCDIV_SHIFT	(6)
+
+#define S3C2443_CLKDIV1_USBHOSTDIV_MASK	(3<<4)
+#define S3C2443_CLKDIV1_USBHOSTDIV_SHIFT (4)
+
+#define S3C2443_CLKCON_NAND
+
+#define S3C2443_HCLKCON_DMA0		(1<<0)
+#define S3C2443_HCLKCON_DMA1		(1<<1)
+#define S3C2443_HCLKCON_DMA2		(1<<2)
+#define S3C2443_HCLKCON_DMA3		(1<<3)
+#define S3C2443_HCLKCON_DMA4		(1<<4)
+#define S3C2443_HCLKCON_DMA5		(1<<5)
+#define S3C2443_HCLKCON_CAMIF		(1<<8)
+#define S3C2443_HCLKCON_DISP		(1<<9)
+#define S3C2443_HCLKCON_LCDC		(1<<10)
+#define S3C2443_HCLKCON_USBH		(1<<11)
+#define S3C2443_HCLKCON_USBD		(1<<12)
+#define S3C2443_HCLKCON_HSMMC		(1<<16)
+#define S3C2443_HCLKCON_CFC		(1<<17)
+#define S3C2443_HCLKCON_SSMC		(1<<18)
+#define S3C2443_HCLKCON_DRAMC		(1<<19)
+
+#define S3C2443_PCLKCON_UART0		(1<<0)
+#define S3C2443_PCLKCON_UART1		(1<<1)
+#define S3C2443_PCLKCON_UART2		(1<<2)
+#define S3C2443_PCLKCON_UART3		(1<<3)
+#define S3C2443_PCLKCON_IIC		(1<<4)
+#define S3C2443_PCLKCON_SDI		(1<<5)
+#define S3C2443_PCLKCON_ADC		(1<<7)
+#define S3C2443_PCLKCON_IIS		(1<<9)
+#define S3C2443_PCLKCON_PWMT		(1<<10)
+#define S3C2443_PCLKCON_WDT		(1<<11)
+#define S3C2443_PCLKCON_RTC		(1<<12)
+#define S3C2443_PCLKCON_GPIO		(1<<13)
+#define S3C2443_PCLKCON_SPI0		(1<<14)
+#define S3C2443_PCLKCON_SPI1		(1<<15)
+
+#define S3C2443_SCLKCON_DDRCLK		(1<<16)
+#define S3C2443_SCLKCON_SSMCCLK		(1<<15)
+#define S3C2443_SCLKCON_HSSPICLK	(1<<14)
+#define S3C2443_SCLKCON_HSMMCCLK_EXT	(1<<13)
+#define S3C2443_SCLKCON_HSMMCCLK_EPLL	(1<<12)
+#define S3C2443_SCLKCON_CAMCLK		(1<<11)
+#define S3C2443_SCLKCON_DISPCLK		(1<<10)
+#define S3C2443_SCLKCON_I2SCLK		(1<<9)
+#define S3C2443_SCLKCON_UARTCLK		(1<<8)
+#define S3C2443_SCLKCON_USBHOST		(1<<1)
+
+#include <asm/div64.h>
+
+static inline unsigned int
+s3c2443_get_mpll(unsigned int pllval, unsigned int baseclk)
+{
+	unsigned int mdiv, pdiv, sdiv;
+	uint64_t fvco;
+
+	mdiv = pllval >> S3C2443_PLLCON_MDIVSHIFT;
+	pdiv = pllval >> S3C2443_PLLCON_PDIVSHIFT;
+	sdiv = pllval >> S3C2443_PLLCON_SDIVSHIFT;
+
+	mdiv &= S3C2443_PLLCON_MDIVMASK;
+	pdiv &= S3C2443_PLLCON_PDIVMASK;
+	sdiv &= S3C2443_PLLCON_SDIVMASK;
+
+	fvco = (uint64_t)baseclk * (2 * (mdiv + 8));
+	do_div(fvco, pdiv << sdiv);
+
+	return (unsigned int)fvco;
+}
+
+static inline unsigned int
+s3c2443_get_epll(unsigned int pllval, unsigned int baseclk)
+{
+	unsigned int mdiv, pdiv, sdiv;
+	uint64_t fvco;
+
+	mdiv = pllval >> S3C2443_PLLCON_MDIVSHIFT;
+	pdiv = pllval >> S3C2443_PLLCON_PDIVSHIFT;
+	sdiv = pllval >> S3C2443_PLLCON_SDIVSHIFT;
+
+	mdiv &= S3C2443_PLLCON_MDIVMASK;
+	pdiv &= S3C2443_PLLCON_PDIVMASK;
+	sdiv &= S3C2443_PLLCON_SDIVMASK;
+
+	fvco = (uint64_t)baseclk * (mdiv + 8);
+	do_div(fvco, (pdiv + 2) << sdiv);
+
+	return (unsigned int)fvco;
+}
+
+#endif /*  __ASM_ARM_REGS_S3C2443_CLOCK */
+
diff --git a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
index 46f5240..8946702 100644
--- a/include/asm-arm/arch-s3c2410/regs-serial.h
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h
@@ -35,10 +35,12 @@
 #define S3C24XX_VA_UART0      (S3C24XX_VA_UART)
 #define S3C24XX_VA_UART1      (S3C24XX_VA_UART + 0x4000 )
 #define S3C24XX_VA_UART2      (S3C24XX_VA_UART + 0x8000 )
+#define S3C24XX_VA_UART3      (S3C24XX_VA_UART + 0xC000 )
 
 #define S3C2410_PA_UART0      (S3C24XX_PA_UART)
 #define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
 #define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
+#define S3C2443_PA_UART3      (S3C24XX_PA_UART + 0xC000 )
 
 #define S3C2410_URXH	  (0x24)
 #define S3C2410_UTXH	  (0x20)
@@ -73,6 +75,8 @@
 #define S3C2440_UCON_UCLK	  (1<<10)
 #define S3C2440_UCON_PCLK2	  (2<<10)
 #define S3C2440_UCON_FCLK	  (3<<10)
+#define S3C2443_UCON_EPLL	  (3<<10)
+
 #define S3C2440_UCON2_FCLK_EN	  (1<<15)
 #define S3C2440_UCON0_DIVMASK	  (15 << 12)
 #define S3C2440_UCON1_DIVMASK	  (15 << 12)
@@ -93,6 +97,8 @@
 #define S3C2410_UCON_TXIRQMODE	  (1<<2)
 #define S3C2410_UCON_RXIRQMODE	  (1<<0)
 #define S3C2410_UCON_RXFIFO_TOI	  (1<<7)
+#define S3C2443_UCON_RXERR_IRQEN  (1<<6)
+#define S3C2443_UCON_LOOPBACK	  (1<<5)
 
 #define S3C2410_UCON_DEFAULT	  (S3C2410_UCON_TXILEVEL  | \
 				   S3C2410_UCON_RXILEVEL  | \
@@ -127,7 +133,7 @@
 #define	S3C2410_UMCOM_AFC	  (1<<4)
 #define	S3C2410_UMCOM_RTS_LOW	  (1<<0)
 
-#define S3C2412_UMCON_AFC_63	(0<<5)
+#define S3C2412_UMCON_AFC_63	(0<<5)		/* same as s3c2443 */
 #define S3C2412_UMCON_AFC_56	(1<<5)
 #define S3C2412_UMCON_AFC_48	(2<<5)
 #define S3C2412_UMCON_AFC_40	(3<<5)
@@ -143,6 +149,7 @@
 #define S3C2410_UFSTAT_RXMASK	  (15<<0)
 #define S3C2410_UFSTAT_RXSHIFT	  (0)
 
+/* UFSTAT S3C2443 same as S3C2440 */
 #define S3C2440_UFSTAT_TXFULL	  (1<<14)
 #define S3C2440_UFSTAT_RXFULL	  (1<<6)
 #define S3C2440_UFSTAT_TXSHIFT	  (8)
@@ -157,6 +164,8 @@
 #define S3C2410_UERSTAT_OVERRUN	  (1<<0)
 #define S3C2410_UERSTAT_FRAME	  (1<<2)
 #define S3C2410_UERSTAT_BREAK	  (1<<3)
+#define S3C2443_UERSTAT_PARITY	  (1<<1)
+
 #define S3C2410_UERSTAT_ANY	  (S3C2410_UERSTAT_OVERRUN | \
 				   S3C2410_UERSTAT_FRAME | \
 				   S3C2410_UERSTAT_BREAK)
@@ -164,6 +173,8 @@
 #define S3C2410_UMSTAT_CTS	  (1<<0)
 #define S3C2410_UMSTAT_DeltaCTS	  (1<<2)
 
+#define S3C2443_DIVSLOT		  (0x2C)
+
 #ifndef __ASSEMBLY__
 
 /* struct s3c24xx_uart_clksrc
diff --git a/include/asm-arm/arch-s3c2410/reset.h b/include/asm-arm/arch-s3c2410/reset.h
new file mode 100644
index 0000000..4f866cd
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/reset.h
@@ -0,0 +1,22 @@
+/* linux/include/asm-arm/arch-s3c2410/reset.h
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * 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.
+ *
+ * S3C2410 CPU reset controls
+*/
+
+#ifndef __ASM_ARCH_RESET_H
+#define __ASM_ARCH_RESET_H __FILE__
+
+/* This allows the over-ride of the default reset code
+*/
+
+extern void (*s3c24xx_reset_hook)(void);
+
+#endif /* __ASM_ARCH_RESET_H */
diff --git a/include/asm-arm/arch-s3c2410/system.h b/include/asm-arm/arch-s3c2410/system.h
index ecf250d..1c74ef1 100644
--- a/include/asm-arm/arch-s3c2410/system.h
+++ b/include/asm-arm/arch-s3c2410/system.h
@@ -15,15 +15,16 @@
 
 #include <asm/arch/map.h>
 #include <asm/arch/idle.h>
+#include <asm/arch/reset.h>
 
 #include <asm/arch/regs-watchdog.h>
 #include <asm/arch/regs-clock.h>
 
 void (*s3c24xx_idle)(void);
+void (*s3c24xx_reset_hook)(void);
 
 void s3c24xx_default_idle(void)
 {
-	void __iomem *reg = S3C2410_CLKCON;
 	unsigned long tmp;
 	int i;
 
@@ -33,16 +34,18 @@
 
 	/* Warning: going into idle state upsets jtag scanning */
 
-	__raw_writel(__raw_readl(reg) | (1<<2), reg);
+	__raw_writel(__raw_readl(S3C2410_CLKCON) | S3C2410_CLKCON_IDLE,
+		     S3C2410_CLKCON);
 
 	/* the samsung port seems to do a loop and then unset idle.. */
 	for (i = 0; i < 50; i++) {
-		tmp += __raw_readl(reg); /* ensure loop not optimised out */
+		tmp += __raw_readl(S3C2410_CLKCON); /* ensure loop not optimised out */
 	}
 
 	/* this bit is not cleared on re-start... */
 
-	__raw_writel(__raw_readl(reg) & ~(1<<2), reg);
+	__raw_writel(__raw_readl(S3C2410_CLKCON) & ~S3C2410_CLKCON_IDLE,
+		     S3C2410_CLKCON);
 }
 
 static void arch_idle(void)
@@ -53,7 +56,6 @@
 		s3c24xx_default_idle();
 }
 
-
 static void
 arch_reset(char mode)
 {
@@ -61,6 +63,9 @@
 		cpu_reset(0);
 	}
 
+	if (s3c24xx_reset_hook)
+		s3c24xx_reset_hook();
+
 	printk("arch_reset: attempting watchdog reset\n");
 
 	__raw_writel(0, S3C2410_WTCON);	  /* disable watchdog, to be safe  */
diff --git a/include/asm-arm/arch-s3c2410/udc.h b/include/asm-arm/arch-s3c2410/udc.h
new file mode 100644
index 0000000..e59ec33
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/udc.h
@@ -0,0 +1,36 @@
+/* linux/include/asm/arch-s3c2410/udc.h
+ *
+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.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.
+ *
+ *
+ *  Changelog:
+ *	14-Mar-2005	RTP	Created file
+ *	02-Aug-2005	RTP	File rename
+ *	07-Sep-2005	BJD	Minor cleanups, changed cmd to enum
+ *	18-Jan-2007	HMW	Add per-platform vbus_draw function
+*/
+
+#ifndef __ASM_ARM_ARCH_UDC_H
+#define __ASM_ARM_ARCH_UDC_H
+
+enum s3c2410_udc_cmd_e {
+	S3C2410_UDC_P_ENABLE	= 1,	/* Pull-up enable        */
+	S3C2410_UDC_P_DISABLE	= 2,	/* Pull-up disable       */
+	S3C2410_UDC_P_RESET	= 3,	/* UDC reset, in case of */
+};
+
+struct s3c2410_udc_mach_info {
+	void	(*udc_command)(enum s3c2410_udc_cmd_e);
+ 	void	(*vbus_draw)(unsigned int ma);
+	unsigned int vbus_pin;
+	unsigned char vbus_pin_inverted;
+};
+
+extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
+
+#endif /* __ASM_ARM_ARCH_UDC_H */
diff --git a/include/asm-arm/arch-sa1100/entry-macro.S b/include/asm-arm/arch-sa1100/entry-macro.S
index 51fb50c..0289676 100644
--- a/include/asm-arm/arch-sa1100/entry-macro.S
+++ b/include/asm-arm/arch-sa1100/entry-macro.S
@@ -11,6 +11,12 @@
  		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 		mov	r4, #0xfa000000			@ ICIP = 0xfa050000
 		add	r4, r4, #0x00050000
diff --git a/include/asm-arm/arch-sa1100/gpio.h b/include/asm-arm/arch-sa1100/gpio.h
new file mode 100644
index 0000000..da7575b
--- /dev/null
+++ b/include/asm-arm/arch-sa1100/gpio.h
@@ -0,0 +1,75 @@
+/*
+ * linux/include/asm-arm/arch-sa1100/gpio.h
+ *
+ * SA1100 GPIO wrappers for arch-neutral GPIO calls
+ *
+ * Written by Philipp Zabel <philipp.zabel@gmail.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
+ *
+ */
+
+#ifndef __ASM_ARCH_SA1100_GPIO_H
+#define __ASM_ARCH_SA1100_GPIO_H
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	return;
+}
+
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio);
+
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return GPLR & GPIO_GPIO(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	if (value)
+		GPSR = GPIO_GPIO(gpio);
+	else
+		GPCR = GPIO_GPIO(gpio);
+}
+
+#include <asm-generic/gpio.h>			/* cansleep wrappers */
+
+static inline unsigned gpio_to_irq(unsigned gpio)
+{
+	if (gpio < 11)
+		return IRQ_GPIO0 + gpio;
+	else
+		return IRQ_GPIO11 - 11 + gpio;
+}
+
+static inline unsigned irq_to_gpio(unsigned irq)
+{
+	if (irq < IRQ_GPIO11_27)
+		return irq - IRQ_GPIO0;
+	else
+		return irq - IRQ_GPIO11 + 11;
+}
+
+#endif
diff --git a/include/asm-arm/arch-shark/entry-macro.S b/include/asm-arm/arch-shark/entry-macro.S
index a924f27..82463f3 100644
--- a/include/asm-arm/arch-shark/entry-macro.S
+++ b/include/asm-arm/arch-shark/entry-macro.S
@@ -10,6 +10,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 		mov	r4, #0xe0000000
 
diff --git a/include/asm-arm/arch-versatile/entry-macro.S b/include/asm-arm/arch-versatile/entry-macro.S
index feff771..0fae002 100644
--- a/include/asm-arm/arch-versatile/entry-macro.S
+++ b/include/asm-arm/arch-versatile/entry-macro.S
@@ -13,6 +13,12 @@
 		.macro	disable_fiq
 		.endm
 
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 		ldr	\base, =IO_ADDRESS(VERSATILE_VIC_BASE)
 		ldr	\irqstat, [\base, #VIC_IRQ_STATUS]	@ get masked status
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 5f531ea..afad32c 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -185,9 +185,15 @@
 	void (*coherent_user_range)(unsigned long, unsigned long);
 	void (*flush_kern_dcache_page)(void *);
 
-	void (*dma_inv_range)(unsigned long, unsigned long);
-	void (*dma_clean_range)(unsigned long, unsigned long);
-	void (*dma_flush_range)(unsigned long, unsigned long);
+	void (*dma_inv_range)(const void *, const void *);
+	void (*dma_clean_range)(const void *, const void *);
+	void (*dma_flush_range)(const void *, const void *);
+};
+
+struct outer_cache_fns {
+	void (*inv_range)(unsigned long, unsigned long);
+	void (*clean_range)(unsigned long, unsigned long);
+	void (*flush_range)(unsigned long, unsigned long);
 };
 
 /*
@@ -240,9 +246,40 @@
 #define dmac_clean_range		__glue(_CACHE,_dma_clean_range)
 #define dmac_flush_range		__glue(_CACHE,_dma_flush_range)
 
-extern void dmac_inv_range(unsigned long, unsigned long);
-extern void dmac_clean_range(unsigned long, unsigned long);
-extern void dmac_flush_range(unsigned long, unsigned long);
+extern void dmac_inv_range(const void *, const void *);
+extern void dmac_clean_range(const void *, const void *);
+extern void dmac_flush_range(const void *, const void *);
+
+#endif
+
+#ifdef CONFIG_OUTER_CACHE
+
+extern struct outer_cache_fns outer_cache;
+
+static inline void outer_inv_range(unsigned long start, unsigned long end)
+{
+	if (outer_cache.inv_range)
+		outer_cache.inv_range(start, end);
+}
+static inline void outer_clean_range(unsigned long start, unsigned long end)
+{
+	if (outer_cache.clean_range)
+		outer_cache.clean_range(start, end);
+}
+static inline void outer_flush_range(unsigned long start, unsigned long end)
+{
+	if (outer_cache.flush_range)
+		outer_cache.flush_range(start, end);
+}
+
+#else
+
+static inline void outer_inv_range(unsigned long start, unsigned long end)
+{ }
+static inline void outer_clean_range(unsigned long start, unsigned long end)
+{ }
+static inline void outer_flush_range(unsigned long start, unsigned long end)
+{ }
 
 #endif
 
diff --git a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
index 8c0bb5b..eaa0efd 100644
--- a/include/asm-arm/checksum.h
+++ b/include/asm-arm/checksum.h
@@ -40,13 +40,27 @@
 csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr);
 
 /*
+ * 	Fold a partial checksum without adding pseudo headers
+ */
+static inline __sum16 csum_fold(__wsum sum)
+{
+	__asm__(
+	"add	%0, %1, %1, ror #16	@ csum_fold"
+	: "=r" (sum)
+	: "r" (sum)
+	: "cc");
+	return (__force __sum16)(~(__force u32)sum >> 16);
+}
+
+/*
  *	This is a version of ip_compute_csum() optimized for IP headers,
  *	which always checksum on 4 octet boundaries.
  */
 static inline __sum16
 ip_fast_csum(const void *iph, unsigned int ihl)
 {
-	unsigned int sum, tmp1;
+	unsigned int tmp1;
+	__wsum sum;
 
 	__asm__ __volatile__(
 	"ldr	%0, [%1], #4		@ ip_fast_csum		\n\
@@ -62,29 +76,11 @@
 	subne	%2, %2, #1		@ without destroying	\n\
 	bne	1b			@ the carry flag	\n\
 	adcs	%0, %0, %3					\n\
-	adc	%0, %0, #0					\n\
-	adds	%0, %0, %0, lsl #16				\n\
-	addcs	%0, %0, #0x10000				\n\
-	mvn	%0, %0						\n\
-	mov	%0, %0, lsr #16"
+	adc	%0, %0, #0"
 	: "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1)
 	: "1" (iph), "2" (ihl)
 	: "cc", "memory");
-	return (__force __sum16)sum;
-}
-
-/*
- * 	Fold a partial checksum without adding pseudo headers
- */
-static inline __sum16 csum_fold(__wsum sum)
-{
-	__asm__(
-	"adds	%0, %1, %1, lsl #16	@ csum_fold		\n\
-	addcs	%0, %0, #0x10000"
-	: "=r" (sum)
-	: "r" (sum)
-	: "cc");
-	return (__force __sum16)(~(__force u32)sum >> 16);
+	return csum_fold(sum);
 }
 
 static inline __wsum
@@ -114,23 +110,7 @@
 csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
 		  unsigned short proto, __wsum sum)
 {
-	__asm__(
-	"adds	%0, %1, %2		@ csum_tcpudp_magic	\n\
-	adcs	%0, %0, %3					\n"
-#ifdef __ARMEB__
-	"adcs	%0, %0, %4					\n"
-#else
-	"adcs	%0, %0, %4, lsl #8				\n"
-#endif
-	"adcs	%0, %0, %5					\n\
-	adc	%0, %0, #0					\n\
-	adds	%0, %0, %0, lsl #16				\n\
-	addcs	%0, %0, #0x10000				\n\
-	mvn	%0, %0"
-	: "=&r"(sum)
-	: "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto))
-	: "cc");
-	return (__force __sum16)((__force u32)sum >> 16);
+	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
 }
 
 
diff --git a/include/asm-arm/device.h b/include/asm-arm/device.h
index d8f9872..c61642b 100644
--- a/include/asm-arm/device.h
+++ b/include/asm-arm/device.h
@@ -3,5 +3,13 @@
  *
  * This file is released under the GPLv2
  */
-#include <asm-generic/device.h>
+#ifndef ASMARM_DEVICE_H
+#define ASMARM_DEVICE_H
 
+struct dev_archdata {
+#ifdef CONFIG_DMABOUNCE
+	struct dmabounce_device_info *dmabounce;
+#endif
+};
+
+#endif
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index 9bc46b4..abfb75b 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -17,7 +17,7 @@
  * platforms with CONFIG_DMABOUNCE.
  * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
  */
-extern void consistent_sync(void *kaddr, size_t size, int rw);
+extern void consistent_sync(const void *kaddr, size_t size, int rw);
 
 /*
  * Return whether the given device DMA address mask can be supported
@@ -61,6 +61,22 @@
 	return dma_addr == ~0;
 }
 
+/*
+ * Dummy noncoherent implementation.  We don't provide a dma_cache_sync
+ * function so drivers using this API are highlighted with build warnings.
+ */
+static inline void *
+dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+{
+	return NULL;
+}
+
+static inline void
+dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
+		     dma_addr_t handle)
+{
+}
+
 /**
  * dma_alloc_coherent - allocate consistent memory for DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
diff --git a/include/asm-arm/domain.h b/include/asm-arm/domain.h
index 4c2885a..3c12a76 100644
--- a/include/asm-arm/domain.h
+++ b/include/asm-arm/domain.h
@@ -57,6 +57,7 @@
 	__asm__ __volatile__(				\
 	"mcr	p15, 0, %0, c3, c0	@ set domain"	\
 	  : : "r" (x));					\
+	isb();						\
 	} while (0)
 
 #define modify_domain(dom,type)					\
diff --git a/include/asm-arm/gpio.h b/include/asm-arm/gpio.h
new file mode 100644
index 0000000..fff4f80
--- /dev/null
+++ b/include/asm-arm/gpio.h
@@ -0,0 +1,7 @@
+#ifndef _ARCH_ARM_GPIO_H
+#define _ARCH_ARM_GPIO_H
+
+/* not all ARM platforms necessarily support this API ... */
+#include <asm/arch/gpio.h>
+
+#endif /* _ARCH_ARM_GPIO_H */
diff --git a/include/asm-arm/hardware/arm_scu.h b/include/asm-arm/hardware/arm_scu.h
index 9903f60..7d28eb5 100644
--- a/include/asm-arm/hardware/arm_scu.h
+++ b/include/asm-arm/hardware/arm_scu.h
@@ -1,6 +1,8 @@
 #ifndef ASMARM_HARDWARE_ARM_SCU_H
 #define ASMARM_HARDWARE_ARM_SCU_H
 
+#include <asm/arch/scu.h>
+
 /*
  * SCU registers
  */
diff --git a/include/asm-arm/hardware/cache-l2x0.h b/include/asm-arm/hardware/cache-l2x0.h
new file mode 100644
index 0000000..54029a7
--- /dev/null
+++ b/include/asm-arm/hardware/cache-l2x0.h
@@ -0,0 +1,56 @@
+/*
+ * include/asm-arm/hardware/cache-l2x0.h
+ *
+ * Copyright (C) 2007 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_ARM_HARDWARE_L2X0_H
+#define __ASM_ARM_HARDWARE_L2X0_H
+
+#define L2X0_CACHE_ID			0x000
+#define L2X0_CACHE_TYPE			0x004
+#define L2X0_CTRL			0x100
+#define L2X0_AUX_CTRL			0x104
+#define L2X0_EVENT_CNT_CTRL		0x200
+#define L2X0_EVENT_CNT1_CFG		0x204
+#define L2X0_EVENT_CNT0_CFG		0x208
+#define L2X0_EVENT_CNT1_VAL		0x20C
+#define L2X0_EVENT_CNT0_VAL		0x210
+#define L2X0_INTR_MASK			0x214
+#define L2X0_MASKED_INTR_STAT		0x218
+#define L2X0_RAW_INTR_STAT		0x21C
+#define L2X0_INTR_CLEAR			0x220
+#define L2X0_CACHE_SYNC			0x730
+#define L2X0_INV_LINE_PA		0x770
+#define L2X0_INV_WAY			0x77C
+#define L2X0_CLEAN_LINE_PA		0x7B0
+#define L2X0_CLEAN_LINE_IDX		0x7B8
+#define L2X0_CLEAN_WAY			0x7BC
+#define L2X0_CLEAN_INV_LINE_PA		0x7F0
+#define L2X0_CLEAN_INV_LINE_IDX		0x7F8
+#define L2X0_CLEAN_INV_WAY		0x7FC
+#define L2X0_LOCKDOWN_WAY_D		0x900
+#define L2X0_LOCKDOWN_WAY_I		0x904
+#define L2X0_TEST_OPERATION		0xF00
+#define L2X0_LINE_DATA			0xF10
+#define L2X0_LINE_TAG			0xF30
+#define L2X0_DEBUG_CTRL			0xF40
+
+#ifndef __ASSEMBLY__
+extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
+#endif
+
+#endif
diff --git a/include/asm-arm/hardware/gic.h b/include/asm-arm/hardware/gic.h
index 3fa5eb7..966e428 100644
--- a/include/asm-arm/hardware/gic.h
+++ b/include/asm-arm/hardware/gic.h
@@ -33,8 +33,9 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
-void gic_dist_init(void __iomem *base);
-void gic_cpu_init(void __iomem *base);
+void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start);
+void gic_cpu_init(unsigned int gic_nr, void __iomem *base);
+void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(cpumask_t cpumask, unsigned int irq);
 #endif
 
diff --git a/include/asm-arm/hardware/gpio_keys.h b/include/asm-arm/hardware/gpio_keys.h
new file mode 100644
index 0000000..2b217c7
--- /dev/null
+++ b/include/asm-arm/hardware/gpio_keys.h
@@ -0,0 +1,17 @@
+#ifndef _GPIO_KEYS_H
+#define _GPIO_KEYS_H
+
+struct gpio_keys_button {
+	/* Configuration parameters */
+	int keycode;
+	int gpio;
+	int active_low;
+	char *desc;
+};
+
+struct gpio_keys_platform_data {
+	struct gpio_keys_button *buttons;
+	int nbuttons;
+};
+
+#endif
diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h
index 13ac8a4..15141a9 100644
--- a/include/asm-arm/hardware/iop3xx.h
+++ b/include/asm-arm/hardware/iop3xx.h
@@ -37,6 +37,13 @@
 #define IOP3XX_PERIPHERAL_PHYS_BASE	0xffffe000
 #define IOP3XX_PERIPHERAL_VIRT_BASE	0xfeffe000
 #define IOP3XX_PERIPHERAL_SIZE		0x00002000
+#define IOP3XX_PERIPHERAL_UPPER_PA (IOP3XX_PERIPHERAL_PHYS_BASE +\
+					IOP3XX_PERIPHERAL_SIZE - 1)
+#define IOP3XX_PERIPHERAL_UPPER_VA (IOP3XX_PERIPHERAL_VIRT_BASE +\
+					IOP3XX_PERIPHERAL_SIZE - 1)
+#define IOP3XX_PMMR_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
+					(IOP3XX_PERIPHERAL_PHYS_BASE\
+					- IOP3XX_PERIPHERAL_VIRT_BASE))
 #define IOP3XX_REG_ADDR(reg)		(IOP3XX_PERIPHERAL_VIRT_BASE + (reg))
 
 /* Address Translation Unit  */
@@ -181,14 +188,10 @@
 #define IOP3XX_TU_TRR1		(volatile u32 *)IOP3XX_TIMER_REG(0x0014)
 #define IOP3XX_TU_TISR		(volatile u32 *)IOP3XX_TIMER_REG(0x0018)
 #define IOP3XX_TU_WDTCR		(volatile u32 *)IOP3XX_TIMER_REG(0x001c)
-#define IOP3XX_TMR_TC		0x01
-#define IOP3XX_TMR_EN		0x02
-#define IOP3XX_TMR_RELOAD	0x04
-#define IOP3XX_TMR_PRIVILEGED	0x09
-#define IOP3XX_TMR_RATIO_1_1	0x00
-#define IOP3XX_TMR_RATIO_4_1	0x10
-#define IOP3XX_TMR_RATIO_8_1	0x20
-#define IOP3XX_TMR_RATIO_16_1	0x30
+#define IOP_TMR_EN	    0x02
+#define IOP_TMR_RELOAD	    0x04
+#define IOP_TMR_PRIVILEGED 0x08
+#define IOP_TMR_RATIO_1_1  0x00
 
 /* Application accelerator unit  */
 #define IOP3XX_AAU_ACR		(volatile u32 *)IOP3XX_REG_ADDR(0x0800)
@@ -258,43 +261,63 @@
 #define IOP3XX_PCI_LOWER_IO_PA		0x90000000
 #define IOP3XX_PCI_LOWER_IO_VA		0xfe000000
 #define IOP3XX_PCI_LOWER_IO_BA		(*IOP3XX_OIOWTVR)
+#define IOP3XX_PCI_UPPER_IO_PA		(IOP3XX_PCI_LOWER_IO_PA +\
+					IOP3XX_PCI_IO_WINDOW_SIZE - 1)
+#define IOP3XX_PCI_UPPER_IO_VA		(IOP3XX_PCI_LOWER_IO_VA +\
+					IOP3XX_PCI_IO_WINDOW_SIZE - 1)
+#define IOP3XX_PCI_IO_PHYS_TO_VIRT(addr) (((u32) addr -\
+					IOP3XX_PCI_LOWER_IO_PA) +\
+					IOP3XX_PCI_LOWER_IO_VA)
 
 
 #ifndef __ASSEMBLY__
 void iop3xx_map_io(void);
-void iop3xx_init_time(unsigned long);
-unsigned long iop3xx_gettimeoffset(void);
+void iop_init_cp6_handler(void);
+void iop_init_time(unsigned long tickrate);
+unsigned long iop_gettimeoffset(void);
+
+static inline void write_tmr0(u32 val)
+{
+	asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (val));
+}
+
+static inline void write_tmr1(u32 val)
+{
+	asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (val));
+}
+
+static inline u32 read_tcr0(void)
+{
+	u32 val;
+	asm volatile("mrc p6, 0, %0, c2, c1, 0" : "=r" (val));
+	return val;
+}
+
+static inline u32 read_tcr1(void)
+{
+	u32 val;
+	asm volatile("mrc p6, 0, %0, c3, c1, 0" : "=r" (val));
+	return val;
+}
+
+static inline void write_trr0(u32 val)
+{
+	asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (val));
+}
+
+static inline void write_trr1(u32 val)
+{
+	asm volatile("mcr p6, 0, %0, c5, c1, 0" : : "r" (val));
+}
+
+static inline void write_tisr(u32 val)
+{
+	asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (val));
+}
 
 extern struct platform_device iop3xx_i2c0_device;
 extern struct platform_device iop3xx_i2c1_device;
 
-extern inline void iop3xx_cp6_enable(void)
-{
-	u32 temp;
-
-	asm volatile (
-		"mrc	p15, 0, %0, c15, c1, 0\n\t"
-		"orr	%0, %0, #(1 << 6)\n\t"
-		"mcr	p15, 0, %0, c15, c1, 0\n\t"
-		"mrc	p15, 0, %0, c15, c1, 0\n\t"
-		"mov	%0, %0\n\t"
-		"sub	pc, pc, #4\n\t"
-		: "=r" (temp) );
-}
-
-extern inline void iop3xx_cp6_disable(void)
-{
-	u32 temp;
-
-	asm volatile (
-		"mrc	p15, 0, %0, c15, c1, 0\n\t"
-		"bic	%0, %0, #(1 << 6)\n\t"
-		"mcr	p15, 0, %0, c15, c1, 0\n\t"
-		"mrc	p15, 0, %0, c15, c1, 0\n\t"
-		"mov	%0, %0\n\t"
-		"sub	pc, pc, #4\n\t"
-		: "=r" (temp) );
-}
 #endif
 
 
diff --git a/include/asm-arm/hardware/sa1111.h b/include/asm-arm/hardware/sa1111.h
index 6aa0a5b..61b1d05 100644
--- a/include/asm-arm/hardware/sa1111.h
+++ b/include/asm-arm/hardware/sa1111.h
@@ -29,6 +29,9 @@
 #define _SA1111(x)	((x) + sa1111->resource.start)
 #endif
 
+#define sa1111_writel(val,addr)	__raw_writel(val, addr)
+#define sa1111_readl(addr)	__raw_readl(addr)
+
 /*
  * 26 bits of the SA-1110 address bus are available to the SA-1111.
  * Use these when feeding target addresses to the DMA engines.
@@ -45,14 +48,6 @@
 #define SA1111_SAC_DMA_MIN_XFER	(0x800)
 
 /*
- * SA1111 register definitions.
- */
-#define __CCREG(x)	__REGP(SA1111_VBASE + (x))
-
-#define sa1111_writel(val,addr)	__raw_writel(val, addr)
-#define sa1111_readl(addr)	__raw_readl(addr)
-
-/*
  * System Bus Interface (SBI)
  *
  * Registers
@@ -194,55 +189,37 @@
  *    SADR              Serial Audio Data Register (16 x 32-bit)
  */
 
-#define _SACR0          _SA1111( 0x0600 )
-#define _SACR1          _SA1111( 0x0604 )
-#define _SACR2          _SA1111( 0x0608 )
-#define _SASR0          _SA1111( 0x060c )
-#define _SASR1          _SA1111( 0x0610 )
-#define _SASCR          _SA1111( 0x0618 )
-#define _L3_CAR         _SA1111( 0x061c )
-#define _L3_CDR         _SA1111( 0x0620 )
-#define _ACCAR          _SA1111( 0x0624 )
-#define _ACCDR          _SA1111( 0x0628 )
-#define _ACSAR          _SA1111( 0x062c )
-#define _ACSDR          _SA1111( 0x0630 )
-#define _SADTCS         _SA1111( 0x0634 )
-#define _SADTSA         _SA1111( 0x0638 )
-#define _SADTCA         _SA1111( 0x063c )
-#define _SADTSB         _SA1111( 0x0640 )
-#define _SADTCB         _SA1111( 0x0644 )
-#define _SADRCS         _SA1111( 0x0648 )
-#define _SADRSA         _SA1111( 0x064c )
-#define _SADRCA         _SA1111( 0x0650 )
-#define _SADRSB         _SA1111( 0x0654 )
-#define _SADRCB         _SA1111( 0x0658 )
-#define _SAITR          _SA1111( 0x065c )
-#define _SADR           _SA1111( 0x0680 )
+#define SA1111_SERAUDIO		0x0600
 
-#define SACR0		__CCREG(0x0600)
-#define SACR1		__CCREG(0x0604)
-#define SACR2		__CCREG(0x0608)
-#define SASR0		__CCREG(0x060c)
-#define SASR1		__CCREG(0x0610)
-#define SASCR		__CCREG(0x0618)
-#define L3_CAR		__CCREG(0x061c)
-#define L3_CDR		__CCREG(0x0620)
-#define ACCAR		__CCREG(0x0624)
-#define ACCDR		__CCREG(0x0628)
-#define ACSAR		__CCREG(0x062c)
-#define ACSDR		__CCREG(0x0630)
-#define SADTCS		__CCREG(0x0634)
-#define SADTSA		__CCREG(0x0638)
-#define SADTCA		__CCREG(0x063c)
-#define SADTSB		__CCREG(0x0640)
-#define SADTCB		__CCREG(0x0644)
-#define SADRCS		__CCREG(0x0648)
-#define SADRSA		__CCREG(0x064c)
-#define SADRCA		__CCREG(0x0650)
-#define SADRSB		__CCREG(0x0654)
-#define SADRCB		__CCREG(0x0658)
-#define SAITR		__CCREG(0x065c)
-#define SADR		__CCREG(0x0680)
+/*
+ * These are offsets from the above base.
+ */
+#define SA1111_SACR0		0x00
+#define SA1111_SACR1		0x04
+#define SA1111_SACR2		0x08
+#define SA1111_SASR0		0x0c
+#define SA1111_SASR1		0x10
+#define SA1111_SASCR		0x18
+#define SA1111_L3_CAR		0x1c
+#define SA1111_L3_CDR		0x20
+#define SA1111_ACCAR		0x24
+#define SA1111_ACCDR		0x28
+#define SA1111_ACSAR		0x2c
+#define SA1111_ACSDR		0x30
+#define SA1111_SADTCS		0x34
+#define SA1111_SADTSA		0x38
+#define SA1111_SADTCA		0x3c
+#define SA1111_SADTSB		0x40
+#define SA1111_SADTCB		0x44
+#define SA1111_SADRCS		0x48
+#define SA1111_SADRSA		0x4c
+#define SA1111_SADRCA		0x50
+#define SA1111_SADRSB		0x54
+#define SA1111_SADRCB		0x58
+#define SA1111_SAITR		0x5c
+#define SA1111_SADR		0x80
+
+#ifndef CONFIG_ARCH_PXA
 
 #define SACR0_ENB	(1<<0)
 #define SACR0_BCKD	(1<<2)
@@ -330,6 +307,8 @@
 #define SAITR_RDBDA	(1<<10)
 #define SAITR_RDBDB	(1<<11)
 
+#endif  /* !CONFIG_ARCH_PXA */
+
 /*
  * General-Purpose I/O Interface
  *
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 288f76b16..5f60b42 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -182,9 +182,6 @@
 #define memcpy_fromio(a,c,l)	_memcpy_fromio((a),__mem_pci(c),(l))
 #define memcpy_toio(c,a,l)	_memcpy_toio(__mem_pci(c),(a),(l))
 
-#define eth_io_copy_and_sum(s,c,l,b) \
-				eth_copy_and_sum((s),__mem_pci(c),(l),(b))
-
 #elif !defined(readb)
 
 #define readb(c)			(__readwrite_bug("readb"),0)
@@ -194,8 +191,6 @@
 #define writew(v,c)			__readwrite_bug("writew")
 #define writel(v,c)			__readwrite_bug("writel")
 
-#define eth_io_copy_and_sum(s,c,l,b)	__readwrite_bug("eth_io_copy_and_sum")
-
 #define check_signature(io,sig,len)	(0)
 
 #endif	/* __mem_pci */
diff --git a/include/asm-arm/kexec.h b/include/asm-arm/kexec.h
new file mode 100644
index 0000000..8c1c616
--- /dev/null
+++ b/include/asm-arm/kexec.h
@@ -0,0 +1,30 @@
+#ifndef _ARM_KEXEC_H
+#define _ARM_KEXEC_H
+
+#ifdef CONFIG_KEXEC
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
+
+#define KEXEC_CONTROL_CODE_SIZE	4096
+
+#define KEXEC_ARCH KEXEC_ARCH_ARM
+
+#ifndef __ASSEMBLY__
+
+#define MAX_NOTE_BYTES 1024
+
+struct kimage;
+/* Provide a dummy definition to avoid build failures. */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+                                        struct pt_regs *oldregs) { }
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_KEXEC */
+
+#endif /* _ARM_KEXEC_H */
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index b8cf2d5..7b2bafc 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -175,19 +175,29 @@
 #ifndef __ASSEMBLY__
 
 /*
- * The following macros handle the cache and bufferable bits...
+ * The pgprot_* and protection_map entries will be fixed up in runtime
+ * to include the cachable and bufferable bits based on memory policy,
+ * as well as any architecture dependent bits like global/ASID and SMP
+ * shared mapping bits.
  */
 #define _L_PTE_DEFAULT	L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_CACHEABLE | L_PTE_BUFFERABLE
 #define _L_PTE_READ	L_PTE_USER | L_PTE_EXEC
 
+extern pgprot_t		pgprot_user;
 extern pgprot_t		pgprot_kernel;
 
-#define PAGE_NONE       __pgprot(_L_PTE_DEFAULT)
-#define PAGE_COPY       __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
-#define PAGE_SHARED     __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE)
-#define PAGE_READONLY   __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+#define PAGE_NONE	pgprot_user
+#define PAGE_COPY	__pgprot(pgprot_val(pgprot_user) | _L_PTE_READ)
+#define PAGE_SHARED	__pgprot(pgprot_val(pgprot_user) | _L_PTE_READ | \
+				 L_PTE_WRITE)
+#define PAGE_READONLY	__pgprot(pgprot_val(pgprot_user) | _L_PTE_READ)
 #define PAGE_KERNEL	pgprot_kernel
 
+#define __PAGE_NONE	__pgprot(_L_PTE_DEFAULT)
+#define __PAGE_COPY	__pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+#define __PAGE_SHARED	__pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE)
+#define __PAGE_READONLY	__pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+
 #endif /* __ASSEMBLY__ */
 
 /*
@@ -198,23 +208,23 @@
  *  2) If we could do execute protection, then read is implied
  *  3) write implies read permissions
  */
-#define __P000  PAGE_NONE
-#define __P001  PAGE_READONLY
-#define __P010  PAGE_COPY
-#define __P011  PAGE_COPY
-#define __P100  PAGE_READONLY
-#define __P101  PAGE_READONLY
-#define __P110  PAGE_COPY
-#define __P111  PAGE_COPY
+#define __P000  __PAGE_NONE
+#define __P001  __PAGE_READONLY
+#define __P010  __PAGE_COPY
+#define __P011  __PAGE_COPY
+#define __P100  __PAGE_READONLY
+#define __P101  __PAGE_READONLY
+#define __P110  __PAGE_COPY
+#define __P111  __PAGE_COPY
 
-#define __S000  PAGE_NONE
-#define __S001  PAGE_READONLY
-#define __S010  PAGE_SHARED
-#define __S011  PAGE_SHARED
-#define __S100  PAGE_READONLY
-#define __S101  PAGE_READONLY
-#define __S110  PAGE_SHARED
-#define __S111  PAGE_SHARED
+#define __S000  __PAGE_NONE
+#define __S001  __PAGE_READONLY
+#define __S010  __PAGE_SHARED
+#define __S011  __PAGE_SHARED
+#define __S100  __PAGE_READONLY
+#define __S101  __PAGE_READONLY
+#define __S110  __PAGE_SHARED
+#define __S111  __PAGE_SHARED
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/include/asm-arm/plat-s3c24xx/clock.h b/include/asm-arm/plat-s3c24xx/clock.h
new file mode 100644
index 0000000..f6135db
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/clock.h
@@ -0,0 +1,63 @@
+/* linux/include/asm-arm/plat-s3c24xx/clock.h
+ * linux/arch/arm/mach-s3c2410/clock.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	http://www.simtec.co.uk/products/SWLINUX/
+ *	Written by Ben Dooks, <ben@simtec.co.uk>
+ *
+ * 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.
+*/
+
+struct clk {
+	struct list_head      list;
+	struct module        *owner;
+	struct clk           *parent;
+	const char           *name;
+	int		      id;
+	int		      usage;
+	unsigned long         rate;
+	unsigned long         ctrlbit;
+
+	int		    (*enable)(struct clk *, int enable);
+	int		    (*set_rate)(struct clk *c, unsigned long rate);
+	unsigned long	    (*get_rate)(struct clk *c);
+	unsigned long	    (*round_rate)(struct clk *c, unsigned long rate);
+	int		    (*set_parent)(struct clk *c, struct clk *parent);
+};
+
+/* other clocks which may be registered by board support */
+
+extern struct clk s3c24xx_dclk0;
+extern struct clk s3c24xx_dclk1;
+extern struct clk s3c24xx_clkout0;
+extern struct clk s3c24xx_clkout1;
+extern struct clk s3c24xx_uclk;
+
+extern struct clk clk_usb_bus;
+
+/* core clock support */
+
+extern struct clk clk_f;
+extern struct clk clk_h;
+extern struct clk clk_p;
+extern struct clk clk_mpll;
+extern struct clk clk_upll;
+extern struct clk clk_xtal;
+
+/* exports for arch/arm/mach-s3c2410
+ *
+ * Please DO NOT use these outside of arch/arm/mach-s3c2410
+*/
+
+extern struct mutex clocks_mutex;
+
+extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
+
+extern int s3c24xx_register_clock(struct clk *clk);
+
+extern int s3c24xx_setup_clocks(unsigned long xtal,
+				unsigned long fclk,
+				unsigned long hclk,
+				unsigned long pclk);
diff --git a/include/asm-arm/plat-s3c24xx/common-smdk.h b/include/asm-arm/plat-s3c24xx/common-smdk.h
new file mode 100644
index 0000000..58d9094
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/common-smdk.h
@@ -0,0 +1,15 @@
+/* linux/include/asm-arm/plat-s3c24xx/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/include/asm-arm/plat-s3c24xx/cpu.h b/include/asm-arm/plat-s3c24xx/cpu.h
new file mode 100644
index 0000000..15dd188
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/cpu.h
@@ -0,0 +1,70 @@
+/* linux/include/asm-arm/plat-s3c24xx/cpu.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* todo - fix when rmk changes iodescs to use `void __iomem *` */
+
+#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
+
+/* forward declaration */
+struct s3c24xx_uart_resources;
+struct platform_device;
+struct s3c2410_uartcfg;
+struct map_desc;
+
+/* core initialisation functions */
+
+extern void s3c24xx_init_irq(void);
+
+extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
+
+extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c24xx_init_clocks(int xtal);
+
+extern void s3c24xx_init_uartdevs(char *name,
+				  struct s3c24xx_uart_resources *res,
+				  struct s3c2410_uartcfg *cfg, int no);
+
+/* the board structure is used at first initialsation time
+ * to get info such as the devices to register for this
+ * board. This is done because platfrom_add_devices() cannot
+ * be called from the map_io entry.
+*/
+
+struct s3c24xx_board {
+	struct platform_device  **devices;
+	unsigned int              devices_count;
+
+	struct clk		**clocks;
+	unsigned int		  clocks_count;
+};
+
+extern void s3c24xx_set_board(struct s3c24xx_board *board);
+
+/* timer for 2410/2440 */
+
+struct sys_timer;
+extern struct sys_timer s3c24xx_timer;
+
+/* system device classes */
+
+extern struct sysdev_class s3c2410_sysclass;
+extern struct sysdev_class s3c2412_sysclass;
+extern struct sysdev_class s3c2440_sysclass;
+extern struct sysdev_class s3c2442_sysclass;
+extern struct sysdev_class s3c2443_sysclass;
diff --git a/include/asm-arm/plat-s3c24xx/devs.h b/include/asm-arm/plat-s3c24xx/devs.h
new file mode 100644
index 0000000..dddf485
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/devs.h
@@ -0,0 +1,51 @@
+/* linux/include/asm-arm/plat-s3c24xx/devs.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 standard platform devices
+ *
+ * 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/platform_device.h>
+
+struct s3c24xx_uart_resources {
+	struct resource		*resources;
+	unsigned long		 nr_resources;
+};
+
+extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
+
+extern struct platform_device *s3c24xx_uart_devs[];
+extern struct platform_device *s3c24xx_uart_src[];
+
+extern struct platform_device s3c_device_usb;
+extern struct platform_device s3c_device_lcd;
+extern struct platform_device s3c_device_wdt;
+extern struct platform_device s3c_device_i2c;
+extern struct platform_device s3c_device_iis;
+extern struct platform_device s3c_device_rtc;
+extern struct platform_device s3c_device_adc;
+extern struct platform_device s3c_device_sdi;
+
+extern struct platform_device s3c_device_spi0;
+extern struct platform_device s3c_device_spi1;
+
+extern struct platform_device s3c_device_nand;
+
+extern struct platform_device s3c_device_timer0;
+extern struct platform_device s3c_device_timer1;
+extern struct platform_device s3c_device_timer2;
+extern struct platform_device s3c_device_timer3;
+
+extern struct platform_device s3c_device_usbgadget;
+
+/* s3c2440 specific devices */
+
+#ifdef CONFIG_CPU_S3C2440
+
+extern struct platform_device s3c_device_camif;
+
+#endif
diff --git a/include/asm-arm/plat-s3c24xx/dma.h b/include/asm-arm/plat-s3c24xx/dma.h
new file mode 100644
index 0000000..2c59406
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/dma.h
@@ -0,0 +1,77 @@
+/* linux/include/asm-arm/plat-s3c24xx/dma.h
+ *
+ * Copyright (C) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C24XX DMA support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern struct sysdev_class dma_sysclass;
+extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
+
+#define DMA_CH_VALID		(1<<31)
+#define DMA_CH_NEVER		(1<<30)
+
+struct s3c24xx_dma_addr {
+	unsigned long		from;
+	unsigned long		to;
+};
+
+/* struct s3c24xx_dma_map
+ *
+ * this holds the mapping information for the channel selected
+ * to be connected to the specified device
+*/
+
+struct s3c24xx_dma_map {
+	const char		*name;
+	struct s3c24xx_dma_addr  hw_addr;
+
+	unsigned long		 channels[S3C2410_DMA_CHANNELS];
+};
+
+struct s3c24xx_dma_selection {
+	struct s3c24xx_dma_map	*map;
+	unsigned long		 map_size;
+	unsigned long		 dcon_mask;
+
+	void	(*select)(struct s3c2410_dma_chan *chan,
+			  struct s3c24xx_dma_map *map);
+};
+
+extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
+
+/* struct s3c24xx_dma_order_ch
+ *
+ * channel map for one of the `enum dma_ch` dma channels. the list
+ * entry contains a set of low-level channel numbers, orred with
+ * DMA_CH_VALID, which are checked in the order in the array.
+*/
+
+struct s3c24xx_dma_order_ch {
+	unsigned int	list[S3C2410_DMA_CHANNELS];	/* list of channels */
+	unsigned int	flags;				/* flags */
+};
+
+/* struct s3c24xx_dma_order
+ *
+ * information provided by either the core or the board to give the
+ * dma system a hint on how to allocate channels
+*/
+
+struct s3c24xx_dma_order {
+	struct s3c24xx_dma_order_ch	channels[DMACH_MAX];
+};
+
+extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
+
+/* DMA init code, called from the cpu support code */
+
+extern int s3c2410_dma_init(void);
+
+extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
+			    unsigned int stride);
diff --git a/include/asm-arm/plat-s3c24xx/irq.h b/include/asm-arm/plat-s3c24xx/irq.h
new file mode 100644
index 0000000..8af6d95
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/irq.h
@@ -0,0 +1,107 @@
+/* linux/include/asm-arm/plat-s3c24xx/irq.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU IRQ support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define irqdbf(x...)
+#define irqdbf2(x...)
+
+#define EXTINT_OFF (IRQ_EINT4 - 4)
+
+extern struct irq_chip s3c_irq_level_chip;
+
+static inline void
+s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
+		int subcheck)
+{
+	unsigned long mask;
+	unsigned long submask;
+
+	submask = __raw_readl(S3C2410_INTSUBMSK);
+	mask = __raw_readl(S3C2410_INTMSK);
+
+	submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
+
+	/* check to see if we need to mask the parent IRQ */
+
+	if ((submask  & subcheck) == subcheck) {
+		__raw_writel(mask | parentbit, S3C2410_INTMSK);
+	}
+
+	/* write back masks */
+	__raw_writel(submask, S3C2410_INTSUBMSK);
+
+}
+
+static inline void
+s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
+{
+	unsigned long mask;
+	unsigned long submask;
+
+	submask = __raw_readl(S3C2410_INTSUBMSK);
+	mask = __raw_readl(S3C2410_INTMSK);
+
+	submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
+	mask &= ~parentbit;
+
+	/* write back masks */
+	__raw_writel(submask, S3C2410_INTSUBMSK);
+	__raw_writel(mask, S3C2410_INTMSK);
+}
+
+
+static inline void
+s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
+{
+	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+	s3c_irqsub_mask(irqno, parentmask, group);
+
+	__raw_writel(bit, S3C2410_SUBSRCPND);
+
+	/* only ack parent if we've got all the irqs (seems we must
+	 * ack, all and hope that the irq system retriggers ok when
+	 * the interrupt goes off again)
+	 */
+
+	if (1) {
+		__raw_writel(parentmask, S3C2410_SRCPND);
+		__raw_writel(parentmask, S3C2410_INTPND);
+	}
+}
+
+static inline void
+s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
+{
+	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+	__raw_writel(bit, S3C2410_SUBSRCPND);
+
+	/* only ack parent if we've got all the irqs (seems we must
+	 * ack, all and hope that the irq system retriggers ok when
+	 * the interrupt goes off again)
+	 */
+
+	if (1) {
+		__raw_writel(parentmask, S3C2410_SRCPND);
+		__raw_writel(parentmask, S3C2410_INTPND);
+	}
+}
+
+/* exported for use in arch/arm/mach-s3c2410 */
+
+#ifdef CONFIG_PM
+extern int s3c_irq_wake(unsigned int irqno, unsigned int state);
+#else
+#define s3c_irq_wake NULL
+#endif
+
+extern int s3c_irqext_type(unsigned int irq, unsigned int type);
diff --git a/include/asm-arm/plat-s3c24xx/pm.h b/include/asm-arm/plat-s3c24xx/pm.h
new file mode 100644
index 0000000..cc62366
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/pm.h
@@ -0,0 +1,73 @@
+/* linux/include/asm-arm/plat-s3c24xx/pm.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Written by Ben Dooks, <ben@simtec.co.uk>
+ *
+ * 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.
+*/
+
+/* s3c2410_pm_init
+ *
+ * called from board at initialisation time to setup the power
+ * management
+*/
+
+#ifdef CONFIG_PM
+
+extern __init int s3c2410_pm_init(void);
+
+#else
+
+static inline int s3c2410_pm_init(void)
+{
+	return 0;
+}
+#endif
+
+/* configuration for the IRQ mask over sleep */
+extern unsigned long s3c_irqwake_intmask;
+extern unsigned long s3c_irqwake_eintmask;
+
+/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
+extern unsigned long s3c_irqwake_intallow;
+extern unsigned long s3c_irqwake_eintallow;
+
+/* per-cpu sleep functions */
+
+extern void (*pm_cpu_prep)(void);
+extern void (*pm_cpu_sleep)(void);
+
+/* Flags for PM Control */
+
+extern unsigned long s3c_pm_flags;
+
+/* from sleep.S */
+
+extern int  s3c2410_cpu_save(unsigned long *saveblk);
+extern void s3c2410_cpu_suspend(void);
+extern void s3c2410_cpu_resume(void);
+
+extern unsigned long s3c2410_sleep_save_phys;
+
+/* sleep save info */
+
+struct sleep_save {
+	void __iomem	*reg;
+	unsigned long	val;
+};
+
+#define SAVE_ITEM(x) \
+	{ .reg = (x) }
+
+extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
+extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
+
+#ifdef CONFIG_PM
+extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
+extern int s3c24xx_irq_resume(struct sys_device *dev);
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2400.h b/include/asm-arm/plat-s3c24xx/s3c2400.h
new file mode 100644
index 0000000..3a5a168
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/s3c2400.h
@@ -0,0 +1,31 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2400.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2400 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Modifications:
+ *     09-Fev-2006 LCVR  First version, based on s3c2410.h
+*/
+
+#ifdef CONFIG_CPU_S3C2400
+
+extern  int s3c2400_init(void);
+
+extern void s3c2400_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2400_init_clocks(int xtal);
+
+#else
+#define s3c2400_init_clocks NULL
+#define s3c2400_init_uarts NULL
+#define s3c2400_map_io NULL
+#define s3c2400_init NULL
+#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2410.h b/include/asm-arm/plat-s3c24xx/s3c2410.h
new file mode 100644
index 0000000..36de0b8
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/s3c2410.h
@@ -0,0 +1,31 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2410.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 machine directory
+ *
+ * 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.
+ *
+*/
+
+#ifdef CONFIG_CPU_S3C2410
+
+extern  int s3c2410_init(void);
+
+extern void s3c2410_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2410_init_clocks(int xtal);
+
+extern  int s3c2410_baseclk_add(void);
+
+#else
+#define s3c2410_init_clocks NULL
+#define s3c2410_init_uarts NULL
+#define s3c2410_map_io NULL
+#define s3c2410_init NULL
+#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2412.h b/include/asm-arm/plat-s3c24xx/s3c2412.h
new file mode 100644
index 0000000..3ec9768
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/s3c2412.h
@@ -0,0 +1,29 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2412.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2412 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2412
+
+extern  int s3c2412_init(void);
+
+extern void s3c2412_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2412_init_clocks(int xtal);
+
+extern  int s3c2412_baseclk_add(void);
+#else
+#define s3c2412_init_clocks NULL
+#define s3c2412_init_uarts NULL
+#define s3c2412_map_io NULL
+#define s3c2412_init NULL
+#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2440.h b/include/asm-arm/plat-s3c24xx/s3c2440.h
new file mode 100644
index 0000000..107853b
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/s3c2440.h
@@ -0,0 +1,17 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2440.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2440 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2440
+extern  int s3c2440_init(void);
+#else
+#define s3c2440_init NULL
+#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2442.h b/include/asm-arm/plat-s3c24xx/s3c2442.h
new file mode 100644
index 0000000..451a23a
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/s3c2442.h
@@ -0,0 +1,17 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2442.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2442
+extern  int s3c2442_init(void);
+#else
+#define s3c2442_init NULL
+#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2443.h b/include/asm-arm/plat-s3c24xx/s3c2443.h
new file mode 100644
index 0000000..11d83b5
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/s3c2443.h
@@ -0,0 +1,32 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2443 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2443
+
+struct s3c2410_uartcfg;
+
+extern  int s3c2443_init(void);
+
+extern void s3c2443_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2443_init_clocks(int xtal);
+
+extern  int s3c2443_baseclk_add(void);
+
+#else
+#define s3c2443_init_clocks NULL
+#define s3c2443_init_uarts NULL
+#define s3c2443_map_io NULL
+#define s3c2443_init NULL
+#endif
diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h
index 861092f..800ba52 100644
--- a/include/asm-arm/spinlock.h
+++ b/include/asm-arm/spinlock.h
@@ -85,7 +85,6 @@
  * Write locks are easy - we just set bit 31.  When unlocking, we can
  * just write zero since the lock is exclusively held.
  */
-#define rwlock_is_locked(x)	(*((volatile unsigned int *)(x)) != 0)
 
 static inline void __raw_write_lock(raw_rwlock_t *rw)
 {
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index aa223fc..f438690 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -140,6 +140,40 @@
 #define	cpu_is_xscale()	1
 #endif
 
+#define UDBG_UNDEFINED	(1 << 0)
+#define UDBG_SYSCALL	(1 << 1)
+#define UDBG_BADABORT	(1 << 2)
+#define UDBG_SEGV	(1 << 3)
+#define UDBG_BUS	(1 << 4)
+
+extern unsigned int user_debug;
+
+#if __LINUX_ARM_ARCH__ >= 4
+#define vectors_high()	(cr_alignment & CR_V)
+#else
+#define vectors_high()	(0)
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 6
+#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
+				    : : "r" (0) : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+				    : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
+				    : : "r" (0) : "memory")
+#else
+#define isb() __asm__ __volatile__ ("" : : : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+				    : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+#endif
+#define mb() dmb()
+#define rmb() mb()
+#define wmb() mb()
+#define read_barrier_depends() do { } while(0)
+#define set_mb(var, value)  do { var = value; mb(); } while (0)
+#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
+
 extern unsigned long cr_no_alignment;	/* defined in entry-armv.S */
 extern unsigned long cr_alignment;	/* defined in entry-armv.S */
 
@@ -154,6 +188,7 @@
 {
 	asm volatile("mcr p15, 0, %0, c1, c0, 0	@ set CR"
 	  : : "r" (val) : "cc");
+	isb();
 }
 
 #ifndef CONFIG_SMP
@@ -176,34 +211,9 @@
 {
 	asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access"
 	  : : "r" (val) : "cc");
+	isb();
 }
 
-#define UDBG_UNDEFINED	(1 << 0)
-#define UDBG_SYSCALL	(1 << 1)
-#define UDBG_BADABORT	(1 << 2)
-#define UDBG_SEGV	(1 << 3)
-#define UDBG_BUS	(1 << 4)
-
-extern unsigned int user_debug;
-
-#if __LINUX_ARM_ARCH__ >= 4
-#define vectors_high()	(cr_alignment & CR_V)
-#else
-#define vectors_high()	(0)
-#endif
-
-#if __LINUX_ARM_ARCH__ >= 6
-#define mb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
-                                   : : "r" (0) : "memory")
-#else
-#define mb() __asm__ __volatile__ ("" : : : "memory")
-#endif
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value)  do { var = value; mb(); } while (0)
-#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
-
 /*
  * switch_mm() may do a full cache flush over the context switch,
  * so enable interrupts over the context switch to avoid high
diff --git a/include/asm-arm/termios.h b/include/asm-arm/termios.h
index 7b8f5e8..329c324 100644
--- a/include/asm-arm/termios.h
+++ b/include/asm-arm/termios.h
@@ -49,24 +49,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*
diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h
index cd10a0b..08c6991 100644
--- a/include/asm-arm/tlbflush.h
+++ b/include/asm-arm/tlbflush.h
@@ -247,7 +247,7 @@
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_WB))
-		asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+		dsb();
 
 	if (tlb_flag(TLB_V3_FULL))
 		asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
@@ -257,6 +257,15 @@
 		asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
 	if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
 		asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
+
+	if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+		     TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+		     TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+		/* flush the branch target cache */
+		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+		dsb();
+		isb();
+	}
 }
 
 static inline void local_flush_tlb_mm(struct mm_struct *mm)
@@ -266,7 +275,7 @@
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_WB))
-		asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+		dsb();
 
 	if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) {
 		if (tlb_flag(TLB_V3_FULL))
@@ -285,6 +294,14 @@
 		asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
 	if (tlb_flag(TLB_V6_I_ASID))
 		asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
+
+	if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+		     TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+		     TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+		/* flush the branch target cache */
+		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+		dsb();
+	}
 }
 
 static inline void
@@ -296,7 +313,7 @@
 	uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
 
 	if (tlb_flag(TLB_WB))
-		asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero));
+		dsb();
 
 	if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
 		if (tlb_flag(TLB_V3_PAGE))
@@ -317,6 +334,14 @@
 		asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
 	if (tlb_flag(TLB_V6_I_PAGE))
 		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
+
+	if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+		     TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+		     TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+		/* flush the branch target cache */
+		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+		dsb();
+	}
 }
 
 static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
@@ -327,7 +352,7 @@
 	kaddr &= PAGE_MASK;
 
 	if (tlb_flag(TLB_WB))
-		asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+		dsb();
 
 	if (tlb_flag(TLB_V3_PAGE))
 		asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc");
@@ -347,11 +372,14 @@
 	if (tlb_flag(TLB_V6_I_PAGE))
 		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
 
-	/* The ARM ARM states that the completion of a TLB maintenance
-	 * operation is only guaranteed by a DSB instruction
-	 */
-	if (tlb_flag(TLB_V6_U_PAGE | TLB_V6_D_PAGE | TLB_V6_I_PAGE))
-		asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+	if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+		     TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+		     TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+		/* flush the branch target cache */
+		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+		dsb();
+		isb();
+	}
 }
 
 /*
@@ -369,15 +397,13 @@
  */
 static inline void flush_pmd_entry(pmd_t *pmd)
 {
-	const unsigned int zero = 0;
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_DCLEAN))
 		asm("mcr	p15, 0, %0, c7, c10, 1	@ flush_pmd"
 			: : "r" (pmd) : "cc");
 	if (tlb_flag(TLB_WB))
-		asm("mcr	p15, 0, %0, c7, c10, 4	@ flush_pmd"
-			: : "r" (zero) : "cc");
+		dsb();
 }
 
 static inline void clean_pmd_entry(pmd_t *pmd)
diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h
index 5f420a0..4c1a3fa 100644
--- a/include/asm-arm/uaccess.h
+++ b/include/asm-arm/uaccess.h
@@ -76,10 +76,10 @@
 
 /* We use 33-bit arithmetic here... */
 #define __range_ok(addr,size) ({ \
-	unsigned long flag, sum; \
+	unsigned long flag, roksum; \
 	__chk_user_ptr(addr);	\
 	__asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \
-		: "=&r" (flag), "=&r" (sum) \
+		: "=&r" (flag), "=&r" (roksum) \
 		: "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \
 		: "cc"); \
 	flag; })
@@ -109,7 +109,7 @@
 
 #define get_user(x,p)							\
 	({								\
-		const register typeof(*(p)) __user *__p asm("r0") = (p);\
+		register const typeof(*(p)) __user *__p asm("r0") = (p);\
 		register unsigned long __r2 asm("r2");			\
 		register int __e asm("r0");				\
 		switch (sizeof(*(__p))) {				\
@@ -143,8 +143,8 @@
 
 #define put_user(x,p)							\
 	({								\
-		const register typeof(*(p)) __r2 asm("r2") = (x);	\
-		const register typeof(*(p)) __user *__p asm("r0") = (p);\
+		register const typeof(*(p)) __r2 asm("r2") = (x);	\
+		register const typeof(*(p)) __user *__p asm("r0") = (p);\
 		register int __e asm("r0");				\
 		switch (sizeof(*(__p))) {				\
 		case 1:							\
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 97e7060..0991b7b 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -372,6 +372,7 @@
 #define __NR_move_pages			(__NR_SYSCALL_BASE+344)
 #define __NR_getcpu			(__NR_SYSCALL_BASE+345)
 					/* 346 for epoll_pwait */
+#define __NR_sys_kexec_load		(__NR_SYSCALL_BASE+347)
 
 /*
  * The following SWIs are ARM private.
diff --git a/include/asm-arm26/termios.h b/include/asm-arm26/termios.h
index 7b8f5e8..329c324 100644
--- a/include/asm-arm26/termios.h
+++ b/include/asm-arm26/termios.h
@@ -49,24 +49,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*
diff --git a/include/asm-arm26/uaccess-asm.h b/include/asm-arm26/uaccess-asm.h
index 19f798e..ade76ec 100644
--- a/include/asm-arm26/uaccess-asm.h
+++ b/include/asm-arm26/uaccess-asm.h
@@ -34,9 +34,9 @@
 }
 
 #define __range_ok(addr,size) ({					\
-	unsigned long flag, sum;					\
+	unsigned long flag, roksum;					\
 	__asm__ __volatile__("subs %1, %0, %3; cmpcs %1, %2; movcs %0, #0" \
-		: "=&r" (flag), "=&r" (sum)				\
+		: "=&r" (flag), "=&r" (roksum)				\
 		: "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit)	\
 		: "cc");						\
 	flag; })
diff --git a/include/asm-arm26/uaccess.h b/include/asm-arm26/uaccess.h
index 3f2dd10..d64ed84 100644
--- a/include/asm-arm26/uaccess.h
+++ b/include/asm-arm26/uaccess.h
@@ -74,7 +74,7 @@
 
 #define get_user(x,p)							\
 	({								\
-		const register typeof(*(p)) *__p asm("r0") = (p);	\
+		register const typeof(*(p)) *__p asm("r0") = (p);	\
 		register typeof(*(p)) __r1 asm("r1");			\
 		register int __e asm("r0");				\
 		switch (sizeof(*(p))) {					\
@@ -139,8 +139,8 @@
 
 #define put_user(x,p)                                                   \
         ({                                                              \
-                const register typeof(*(p)) __r1 asm("r1") = (x);       \
-                const register typeof(*(p)) *__p asm("r0") = (p);       \
+                register const typeof(*(p)) __r1 asm("r1") = (x);       \
+                register const typeof(*(p)) *__p asm("r0") = (p);       \
                 register int __e asm("r0");                             \
                 switch (sizeof(*(__p))) {                               \
                 case 1:                                                 \
@@ -170,8 +170,8 @@
 
 #define put_user(x,p)							\
 	({								\
-		const register typeof(*(p)) __r1 asm("r1") = (x);	\
-		const register typeof(*(p)) *__p asm("r0") = (p);	\
+		register const typeof(*(p)) __r1 asm("r1") = (x);	\
+		register const typeof(*(p)) *__p asm("r0") = (p);	\
 		register int __e asm("r0");				\
 		switch (sizeof(*(p))) {					\
 		case 1:							\
diff --git a/include/asm-avr32/arch-at32ap/at32ap7000.h b/include/asm-avr32/arch-at32ap/at32ap7000.h
index ba85e04..3914d7b 100644
--- a/include/asm-avr32/arch-at32ap/at32ap7000.h
+++ b/include/asm-avr32/arch-at32ap/at32ap7000.h
@@ -24,10 +24,12 @@
 #define GPIO_PIOB_BASE	(GPIO_PIOA_BASE + 32)
 #define GPIO_PIOC_BASE	(GPIO_PIOB_BASE + 32)
 #define GPIO_PIOD_BASE	(GPIO_PIOC_BASE + 32)
+#define GPIO_PIOE_BASE	(GPIO_PIOD_BASE + 32)
 
 #define GPIO_PIN_PA(N)	(GPIO_PIOA_BASE + (N))
 #define GPIO_PIN_PB(N)	(GPIO_PIOB_BASE + (N))
 #define GPIO_PIN_PC(N)	(GPIO_PIOC_BASE + (N))
 #define GPIO_PIN_PD(N)	(GPIO_PIOD_BASE + (N))
+#define GPIO_PIN_PE(N)	(GPIO_PIOE_BASE + (N))
 
 #endif /* __ASM_ARCH_AT32AP7000_H__ */
diff --git a/include/asm-avr32/arch-at32ap/at91_pdc.h b/include/asm-avr32/arch-at32ap/at91_pdc.h
deleted file mode 100644
index 79d6e02..0000000
--- a/include/asm-avr32/arch-at32ap/at91_pdc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_pdc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Peripheral Data Controller (PDC) 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 AT91_PDC_H
-#define AT91_PDC_H
-
-#define AT91_PDC_RPR		0x100	/* Receive Pointer Register */
-#define AT91_PDC_RCR		0x104	/* Receive Counter Register */
-#define AT91_PDC_TPR		0x108	/* Transmit Pointer Register */
-#define AT91_PDC_TCR		0x10c	/* Transmit Counter Register */
-#define AT91_PDC_RNPR		0x110	/* Receive Next Pointer Register */
-#define AT91_PDC_RNCR		0x114	/* Receive Next Counter Register */
-#define AT91_PDC_TNPR		0x118	/* Transmit Next Pointer Register */
-#define AT91_PDC_TNCR		0x11c	/* Transmit Next Counter Register */
-
-#define AT91_PDC_PTCR		0x120	/* Transfer Control Register */
-#define		AT91_PDC_RXTEN		(1 << 0)	/* Receiver Transfer Enable */
-#define		AT91_PDC_RXTDIS		(1 << 1)	/* Receiver Transfer Disable */
-#define		AT91_PDC_TXTEN		(1 << 8)	/* Transmitter Transfer Enable */
-#define		AT91_PDC_TXTDIS		(1 << 9)	/* Transmitter Transfer Disable */
-
-#define AT91_PDC_PTSR		0x124	/* Transfer Status Register */
-
-#endif
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
index b120ee0..1a7b07d 100644
--- a/include/asm-avr32/arch-at32ap/board.h
+++ b/include/asm-avr32/arch-at32ap/board.h
@@ -26,7 +26,9 @@
 struct platform_device *
 at32_add_device_eth(unsigned int id, struct eth_platform_data *data);
 
-struct platform_device *at32_add_device_spi(unsigned int id);
+struct spi_board_info;
+struct platform_device *
+at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n);
 
 struct lcdc_platform_data {
 	unsigned long fbmem_start;
diff --git a/include/asm-avr32/arch-at32ap/gpio.h b/include/asm-avr32/arch-at32ap/gpio.h
new file mode 100644
index 0000000..fcb756b
--- /dev/null
+++ b/include/asm-avr32/arch-at32ap/gpio.h
@@ -0,0 +1,27 @@
+#ifndef __ASM_AVR32_ARCH_GPIO_H
+#define __ASM_AVR32_ARCH_GPIO_H
+
+#include <linux/compiler.h>
+#include <asm/irq.h>
+
+
+/* Arch-neutral GPIO API */
+int __must_check gpio_request(unsigned int gpio, const char *label);
+void gpio_free(unsigned int gpio);
+
+int gpio_direction_input(unsigned int gpio);
+int gpio_direction_output(unsigned int gpio);
+int gpio_get_value(unsigned int gpio);
+void gpio_set_value(unsigned int gpio, int value);
+
+static inline int gpio_to_irq(unsigned int gpio)
+{
+	return gpio + GPIO_IRQ_BASE;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+	return irq - GPIO_IRQ_BASE;
+}
+
+#endif /* __ASM_AVR32_ARCH_GPIO_H */
diff --git a/include/asm-avr32/arch-at32ap/irq.h b/include/asm-avr32/arch-at32ap/irq.h
new file mode 100644
index 0000000..5adffab
--- /dev/null
+++ b/include/asm-avr32/arch-at32ap/irq.h
@@ -0,0 +1,14 @@
+#ifndef __ASM_AVR32_ARCH_IRQ_H
+#define __ASM_AVR32_ARCH_IRQ_H
+
+#define EIM_IRQ_BASE	NR_INTERNAL_IRQS
+#define NR_EIM_IRQS	32
+
+#define AT32_EXTINT(n)	(EIM_IRQ_BASE + (n))
+
+#define GPIO_IRQ_BASE	(EIM_IRQ_BASE + NR_EIM_IRQS)
+#define NR_GPIO_IRQS	(5 * 32)
+
+#define NR_IRQS		(GPIO_IRQ_BASE + NR_GPIO_IRQS)
+
+#endif /* __ASM_AVR32_ARCH_IRQ_H */
diff --git a/include/asm-avr32/arch-at32ap/portmux.h b/include/asm-avr32/arch-at32ap/portmux.h
index 83c6905..9930871 100644
--- a/include/asm-avr32/arch-at32ap/portmux.h
+++ b/include/asm-avr32/arch-at32ap/portmux.h
@@ -15,12 +15,14 @@
  *
  * The following flags determine the initial state of the pin.
  */
-#define AT32_GPIOF_PULLUP	0x00000001	/* Enable pull-up */
-#define AT32_GPIOF_OUTPUT	0x00000002	/* Enable output driver */
-#define AT32_GPIOF_HIGH		0x00000004	/* Set output high */
+#define AT32_GPIOF_PULLUP	0x00000001	/* (not-OUT) Enable pull-up */
+#define AT32_GPIOF_OUTPUT	0x00000002	/* (OUT) Enable output driver */
+#define AT32_GPIOF_HIGH		0x00000004	/* (OUT) Set output high */
+#define AT32_GPIOF_DEGLITCH	0x00000008	/* (IN) Filter glitches */
 
 void at32_select_periph(unsigned int pin, unsigned int periph,
 			unsigned long flags);
 void at32_select_gpio(unsigned int pin, unsigned long flags);
+void at32_reserve_pin(unsigned int pin);
 
 #endif /* __ASM_ARCH_PORTMUX_H__ */
diff --git a/include/asm-avr32/checksum.h b/include/asm-avr32/checksum.h
index af9d53f..4ddbfd2 100644
--- a/include/asm-avr32/checksum.h
+++ b/include/asm-avr32/checksum.h
@@ -38,7 +38,7 @@
  *	passed in an incorrect kernel address to one of these functions.
  *
  *	If you use these functions directly please don't forget the
- *	verify_area().
+ *	access_ok().
  */
 static inline
 __wsum csum_partial_copy_nocheck(const void *src, void *dst,
diff --git a/include/asm-avr32/dma-mapping.h b/include/asm-avr32/dma-mapping.h
index 5c01e27..115813e 100644
--- a/include/asm-avr32/dma-mapping.h
+++ b/include/asm-avr32/dma-mapping.h
@@ -32,6 +32,14 @@
 	return 0;
 }
 
+/*
+ * dma_map_single can't fail as it is implemented now.
+ */
+static inline int dma_mapping_error(dma_addr_t addr)
+{
+	return 0;
+}
+
 /**
  * dma_alloc_coherent - allocate consistent memory for DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
diff --git a/include/asm-avr32/gpio.h b/include/asm-avr32/gpio.h
new file mode 100644
index 0000000..19e8ccc
--- /dev/null
+++ b/include/asm-avr32/gpio.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_AVR32_GPIO_H
+#define __ASM_AVR32_GPIO_H
+
+#include <asm/arch/gpio.h>
+
+#endif /* __ASM_AVR32_GPIO_H */
diff --git a/include/asm-avr32/io.h b/include/asm-avr32/io.h
index eec4750..c08e810 100644
--- a/include/asm-avr32/io.h
+++ b/include/asm-avr32/io.h
@@ -28,13 +28,13 @@
  * Generic IO read/write.  These perform native-endian accesses.  Note
  * that some architectures will want to re-define __raw_{read,write}w.
  */
-extern void __raw_writesb(unsigned int addr, const void *data, int bytelen);
-extern void __raw_writesw(unsigned int addr, const void *data, int wordlen);
-extern void __raw_writesl(unsigned int addr, const void *data, int longlen);
+extern void __raw_writesb(void __iomem *addr, const void *data, int bytelen);
+extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
+extern void __raw_writesl(void __iomem *addr, const void *data, int longlen);
 
-extern void __raw_readsb(unsigned int addr, void *data, int bytelen);
-extern void __raw_readsw(unsigned int addr, void *data, int wordlen);
-extern void __raw_readsl(unsigned int addr, void *data, int longlen);
+extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen);
+extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 
 static inline void writeb(unsigned char b, volatile void __iomem *addr)
 {
@@ -252,6 +252,9 @@
 #define ioremap(offset, size)			\
 	__ioremap((offset), (size), 0)
 
+#define ioremap_nocache(offset, size)		\
+	__ioremap((offset), (size), 0)
+
 #define iounmap(addr)				\
 	__iounmap(addr)
 
@@ -263,6 +266,14 @@
 #define page_to_bus page_to_phys
 #define bus_to_page phys_to_page
 
+/*
+ * Create a virtual mapping cookie for an IO port range.  There exists
+ * no such thing as port-based I/O on AVR32, so a regular ioremap()
+ * should do what we need.
+ */
+#define ioport_map(port, nr)	ioremap(port, nr)
+#define ioport_unmap(port)	iounmap(port)
+
 #define dma_cache_wback_inv(_start, _size)	\
 	flush_dcache_region(_start, _size)
 #define dma_cache_inv(_start, _size)		\
diff --git a/include/asm-avr32/irq.h b/include/asm-avr32/irq.h
index f7e7257..83e6549 100644
--- a/include/asm-avr32/irq.h
+++ b/include/asm-avr32/irq.h
@@ -2,8 +2,12 @@
 #define __ASM_AVR32_IRQ_H
 
 #define NR_INTERNAL_IRQS	64
-#define NR_EXTERNAL_IRQS	64
-#define NR_IRQS			(NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS)
+
+#include <asm/arch/irq.h>
+
+#ifndef NR_IRQS
+#define NR_IRQS			(NR_INTERNAL_IRQS)
+#endif
 
 #define irq_canonicalize(i)	(i)
 
diff --git a/include/asm-avr32/posix_types.h b/include/asm-avr32/posix_types.h
index 2831b03..9e255b9 100644
--- a/include/asm-avr32/posix_types.h
+++ b/include/asm-avr32/posix_types.h
@@ -23,7 +23,7 @@
 typedef unsigned int	__kernel_uid_t;
 typedef unsigned int	__kernel_gid_t;
 typedef unsigned long	__kernel_size_t;
-typedef int             __kernel_ssize_t;
+typedef long		__kernel_ssize_t;
 typedef int             __kernel_ptrdiff_t;
 typedef long            __kernel_time_t;
 typedef long            __kernel_suseconds_t;
diff --git a/include/asm-avr32/termios.h b/include/asm-avr32/termios.h
index 615bc06..0152aba 100644
--- a/include/asm-avr32/termios.h
+++ b/include/asm-avr32/termios.h
@@ -46,24 +46,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 /*	intr=^C		quit=^\		erase=del	kill=^U
 	eof=^D		vtime=\0	vmin=\1		sxtc=\0
diff --git a/include/asm-avr32/uaccess.h b/include/asm-avr32/uaccess.h
index 821deb5..74a679e9 100644
--- a/include/asm-avr32/uaccess.h
+++ b/include/asm-avr32/uaccess.h
@@ -68,12 +68,6 @@
 
 #define access_ok(type, addr, size) (likely(__range_ok(addr, size) == 0))
 
-static inline int
-verify_area(int type, const void __user *addr, unsigned long size)
-{
-	return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
 /* Generic arbitrary sized copy. Return the number of bytes NOT copied */
 extern __kernel_size_t __copy_user(void *to, const void *from,
 				   __kernel_size_t n);
diff --git a/include/asm-avr32/unistd.h b/include/asm-avr32/unistd.h
index 56ed1f9..8f51204 100644
--- a/include/asm-avr32/unistd.h
+++ b/include/asm-avr32/unistd.h
@@ -120,7 +120,7 @@
 #define __NR_getitimer		105
 #define __NR_swapoff		106
 #define __NR_sysinfo		107
-#define __NR_ipc		108
+/* 108 was __NR_ipc for a little while */
 #define __NR_sendfile		109
 #define __NR_setdomainname	110
 #define __NR_uname		111
@@ -282,8 +282,21 @@
 #define __NR_vmsplice		264
 #define __NR_epoll_pwait	265
 
+#define __NR_msgget		266
+#define __NR_msgsnd		267
+#define __NR_msgrcv		268
+#define __NR_msgctl		269
+#define __NR_semget		270
+#define __NR_semop		271
+#define __NR_semctl		272
+#define __NR_semtimedop		273
+#define __NR_shmat		274
+#define __NR_shmget		275
+#define __NR_shmdt		276
+#define __NR_shmctl		277
+
 #ifdef __KERNEL__
-#define NR_syscalls		266
+#define NR_syscalls		278
 
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
diff --git a/include/asm-cris/io.h b/include/asm-cris/io.h
index 716c69b..d196dd6 100644
--- a/include/asm-cris/io.h
+++ b/include/asm-cris/io.h
@@ -121,11 +121,6 @@
 #define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
 #define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
 
-/*
- * Again, CRIS does not require mem IO specific function.
- */
-
-#define eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),(void __force *)(b),(c),(d))
 
 /* The following is junk needed for the arch-independent code but which
  * we never use in the CRIS port
diff --git a/include/asm-cris/semaphore-helper.h b/include/asm-cris/semaphore-helper.h
index a8e1e6c..27bfeca1 100644
--- a/include/asm-cris/semaphore-helper.h
+++ b/include/asm-cris/semaphore-helper.h
@@ -30,8 +30,7 @@
 	unsigned long flags;
 	int ret = 0;
 
-	local_save_flags(flags);
-	local_irq_disable();
+	local_irq_save(flags);
 	if (read(&sem->waking) > 0) {
 		dec(&sem->waking);
 		ret = 1;
@@ -46,8 +45,7 @@
 	int ret = 0;
 	unsigned long flags;
 
-	local_save_flags(flags);
-	local_irq_disable();
+	local_irq_save(flags);
 	if (read(&sem->waking) > 0) {
 		dec(&sem->waking);
 		ret = 1;
@@ -64,8 +62,7 @@
         int ret = 1;
 	unsigned long flags;
 
-	local_save_flags(flags);
-	local_irq_disable();
+	local_irq_save(flags);
 	if (read(&sem->waking) <= 0)
 		inc(&sem->count);
 	else {
diff --git a/include/asm-cris/system.h b/include/asm-cris/system.h
index b869f61..fea0e8d 100644
--- a/include/asm-cris/system.h
+++ b/include/asm-cris/system.h
@@ -44,8 +44,7 @@
   /* since Etrax doesn't have any atomic xchg instructions, we need to disable
      irq's (if enabled) and do it with move.d's */
   unsigned long flags,temp;
-  local_save_flags(flags); /* save flags, including irq enable bit */
-  local_irq_disable();             /* shut off irq's */
+  local_irq_save(flags); /* save flags, including irq enable bit and shut off irqs */
   switch (size) {
   case 1:
     *((unsigned char *)&temp) = x;
diff --git a/include/asm-cris/termios.h b/include/asm-cris/termios.h
index 5ce1023..c9dbd4d 100644
--- a/include/asm-cris/termios.h
+++ b/include/asm-cris/termios.h
@@ -40,24 +40,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_BT		15	/* bluetooth */
-
 #ifdef __KERNEL__
 
 /*	intr=^C		quit=^\		erase=del	kill=^U
diff --git a/include/asm-frv/termios.h b/include/asm-frv/termios.h
index 8840cf9..a62fb58 100644
--- a/include/asm-frv/termios.h
+++ b/include/asm-frv/termios.h
@@ -51,24 +51,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 #include <asm-generic/termios.h>
 #endif
diff --git a/include/asm-generic/dma-mapping-broken.h b/include/asm-generic/dma-mapping-broken.h
index a7f1a55..29413d3 100644
--- a/include/asm-generic/dma-mapping-broken.h
+++ b/include/asm-generic/dma-mapping-broken.h
@@ -3,7 +3,6 @@
 
 /* This is used for archs that do not support DMA */
 
-
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
 		   gfp_t flag)
@@ -19,4 +18,7 @@
 	BUG();
 }
 
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
 #endif /* _ASM_GENERIC_DMA_MAPPING_H */
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
new file mode 100644
index 0000000..2d0aab1
--- /dev/null
+++ b/include/asm-generic/gpio.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_GPIO_H
+#define _ASM_GENERIC_GPIO_H
+
+/* platforms that don't directly support access to GPIOs through I2C, SPI,
+ * or other blocking infrastructure can use these wrappers.
+ */
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+	return 0;
+}
+
+static inline int gpio_get_value_cansleep(unsigned gpio)
+{
+	might_sleep();
+	return gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value_cansleep(unsigned gpio, int value)
+{
+	might_sleep();
+	gpio_set_value(gpio, value);
+}
+
+#endif /* _ASM_GENERIC_GPIO_H */
diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h
index 8078cbd..30d8d33 100644
--- a/include/asm-generic/memory_model.h
+++ b/include/asm-generic/memory_model.h
@@ -54,7 +54,7 @@
 #define __page_to_pfn(pg)					\
 ({	struct page *__pg = (pg);				\
 	int __sec = page_to_section(__pg);			\
-	__pg - __section_mem_map_addr(__nr_to_section(__sec));	\
+	(unsigned long)(__pg - __section_mem_map_addr(__nr_to_section(__sec)));	\
 })
 
 #define __pfn_to_page(pfn)				\
diff --git a/include/asm-generic/mman.h b/include/asm-generic/mman.h
index 3b41d2b..5e3dde2 100644
--- a/include/asm-generic/mman.h
+++ b/include/asm-generic/mman.h
@@ -36,7 +36,6 @@
 #define MADV_DOFORK	11		/* do inherit across fork */
 
 /* compatibility flags */
-#define MAP_ANON	MAP_ANONYMOUS
 #define MAP_FILE	0
 
 #endif
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 9d774d0..00c2343 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -183,6 +183,19 @@
 #endif
 
 /*
+ * A facility to provide batching of the reload of page tables with the
+ * actual context switch code for paravirtualized guests.  By convention,
+ * only one of the lazy modes (CPU, MMU) should be active at any given
+ * time, entry should never be nested, and entry and exits should always
+ * be paired.  This is for sanity of maintaining and reasoning about the
+ * kernel code.
+ */
+#ifndef __HAVE_ARCH_ENTER_LAZY_CPU_MODE
+#define arch_enter_lazy_cpu_mode()	do {} while (0)
+#define arch_leave_lazy_cpu_mode()	do {} while (0)
+#endif
+
+/*
  * When walking page tables, get the address of the next boundary,
  * or the end address of the range if that comes earlier.  Although no
  * vma end wraps to 0, rounded up __boundary may wrap to 0 throughout.
diff --git a/include/asm-h8300/termios.h b/include/asm-h8300/termios.h
index e2319f9..fb2925d 100644
--- a/include/asm-h8300/termios.h
+++ b/include/asm-h8300/termios.h
@@ -49,24 +49,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*
diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
index 5e657eb..449f3f2 100644
--- a/include/asm-i386/acpi.h
+++ b/include/asm-i386/acpi.h
@@ -127,6 +127,7 @@
 #define acpi_ioapic 0
 static inline void acpi_noirq_set(void) { }
 static inline void acpi_disable_pci(void) { }
+static inline void disable_acpi(void) { }
 
 #endif	/* !CONFIG_ACPI */
 
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 41a4431..cc6b165 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -43,6 +43,8 @@
 #define apic_write native_apic_write
 #define apic_write_atomic native_apic_write_atomic
 #define apic_read native_apic_read
+#define setup_boot_clock setup_boot_APIC_clock
+#define setup_secondary_clock setup_secondary_APIC_clock
 #endif
 
 static __inline fastcall void native_apic_write(unsigned long reg,
@@ -93,9 +95,7 @@
 	apic_write_around(APIC_EOI, 0);
 }
 
-extern void (*wait_timer_tick)(void);
-
-extern int get_maxlvt(void);
+extern int lapic_get_maxlvt(void);
 extern void clear_local_APIC(void);
 extern void connect_bsp_APIC (void);
 extern void disconnect_bsp_APIC (int virt_wire_setup);
@@ -111,14 +111,9 @@
 extern void setup_boot_APIC_clock (void);
 extern void setup_secondary_APIC_clock (void);
 extern int APIC_init_uniprocessor (void);
-extern void disable_APIC_timer(void);
-extern void enable_APIC_timer(void);
 
 extern void enable_NMI_through_LVT0 (void * dummy);
 
-void smp_send_timer_broadcast_ipi(void);
-void switch_APIC_timer_to_ipi(void *cpumask);
-void switch_ipi_to_APIC_timer(void *cpumask);
 #define ARCH_APICTIMER_STOPS_ON_C3	1
 
 extern int timer_over_8254;
diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h
index c57441b..4dd2723 100644
--- a/include/asm-i386/atomic.h
+++ b/include/asm-i386/atomic.h
@@ -211,12 +211,12 @@
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * atomic_add_unless - add unless the number is already a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
- * Atomically adds @a to @v, so long as it was not @u.
+ * Atomically adds @a to @v, so long as @v was not already @u.
  * Returns non-zero if @v was not @u, and zero otherwise.
  */
 #define atomic_add_unless(v, a, u)				\
diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
index 1c780fa..273b506 100644
--- a/include/asm-i386/bitops.h
+++ b/include/asm-i386/bitops.h
@@ -371,7 +371,7 @@
  *
  * This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
+ * differs in spirit from the above ffz() (man ffs).
  */
 static inline int ffs(int x)
 {
@@ -388,7 +388,7 @@
  * fls - find last bit set
  * @x: the word to search
  *
- * This is defined the same way as ffs.
+ * This is defined the same way as ffs().
  */
 static inline int fls(int x)
 {
diff --git a/include/asm-i386/bugs.h b/include/asm-i386/bugs.h
index 38f1aeb..c90c7c4 100644
--- a/include/asm-i386/bugs.h
+++ b/include/asm-i386/bugs.h
@@ -160,7 +160,7 @@
  * If we configured ourselves for a TSC, we'd better have one!
  */
 #ifdef CONFIG_X86_TSC
-	if (!cpu_has_tsc)
+	if (!cpu_has_tsc && !tsc_disable)
 		panic("Kernel compiled for Pentium+, requires TSC feature!");
 #endif
 
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index f398cc4..050831f 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -22,7 +22,7 @@
 
 extern struct Xgt_desc_struct idt_descr;
 DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
-
+extern struct Xgt_desc_struct early_gdt_descr;
 
 static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
 {
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
index 369035d..8d33c9b 100644
--- a/include/asm-i386/elf.h
+++ b/include/asm-i386/elf.h
@@ -90,8 +90,8 @@
 	pr_reg[6] = regs->eax;				\
 	pr_reg[7] = regs->xds;				\
 	pr_reg[8] = regs->xes;				\
-	savesegment(fs,pr_reg[9]);			\
-	pr_reg[10] = regs->xgs;				\
+	pr_reg[9] = regs->xfs;				\
+	savesegment(gs,pr_reg[10]);			\
 	pr_reg[11] = regs->orig_eax;			\
 	pr_reg[12] = regs->eip;				\
 	pr_reg[13] = regs->xcs;				\
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
index e47be9a..fc03cf9 100644
--- a/include/asm-i386/hpet.h
+++ b/include/asm-i386/hpet.h
@@ -90,16 +90,19 @@
 #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 */
-extern int hpet_use_timer;
+extern int is_hpet_enabled(void);
 
+#ifdef CONFIG_X86_64
+extern unsigned long hpet_tick;	/* hpet clks count per tick */
+extern int hpet_use_timer;
 extern int hpet_rtc_timer_init(void);
 extern int hpet_enable(void);
-extern int hpet_reenable(void);
-extern int is_hpet_enabled(void);
 extern int is_hpet_capable(void);
 extern int hpet_readl(unsigned long a);
+#else
+extern int hpet_enable(void);
+#endif
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
@@ -110,5 +113,10 @@
 extern int hpet_rtc_timer_init(void);
 extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
 #endif /* CONFIG_HPET_EMULATE_RTC */
+
+#else
+
+static inline int hpet_enable(void) { return 0; }
+
 #endif /* CONFIG_HPET_TIMER */
 #endif /* _I386_HPET_H */
diff --git a/include/asm-i386/i8253.h b/include/asm-i386/i8253.h
index 015d8df..6cb0dd4 100644
--- a/include/asm-i386/i8253.h
+++ b/include/asm-i386/i8253.h
@@ -1,6 +1,21 @@
 #ifndef __ASM_I8253_H__
 #define __ASM_I8253_H__
 
+#include <linux/clockchips.h>
+
 extern spinlock_t i8253_lock;
 
+extern struct clock_event_device *global_clock_event;
+
+/**
+ * pit_interrupt_hook - hook into timer tick
+ * @regs:	standard registers from interrupt
+ *
+ * Call the global clock event handler.
+ **/
+static inline void pit_interrupt_hook(void)
+{
+	global_clock_event->event_handler(global_clock_event);
+}
+
 #endif	/* __ASM_I8253_H__ */
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index 86ff5e8..59fe616 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -219,12 +219,6 @@
 #define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
 
 /*
- * Again, i386 does not require mem IO specific function.
- */
-
-#define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),(void __force *)(b),(c),(d))
-
-/*
  *	Cache management
  *
  *	This needed for two cases
diff --git a/include/asm-i386/mach-default/do_timer.h b/include/asm-i386/mach-default/do_timer.h
index 7d606e3..56e5689 100644
--- a/include/asm-i386/mach-default/do_timer.h
+++ b/include/asm-i386/mach-default/do_timer.h
@@ -1,86 +1,16 @@
 /* defines for inline arch setup functions */
+#include <linux/clockchips.h>
 
-#include <asm/apic.h>
 #include <asm/i8259.h>
+#include <asm/i8253.h>
 
 /**
  * do_timer_interrupt_hook - hook into timer tick
- * @regs:	standard registers from interrupt
  *
- * Description:
- *	This hook is called immediately after the timer interrupt is ack'd.
- *	It's primary purpose is to allow architectures that don't possess
- *	individual per CPU clocks (like the CPU APICs supply) to broadcast the
- *	timer interrupt as a means of triggering reschedules etc.
+ * Call the pit clock event handler. see asm/i8253.h
  **/
 
 static inline void do_timer_interrupt_hook(void)
 {
-	do_timer(1);
-#ifndef CONFIG_SMP
-	update_process_times(user_mode_vm(get_irq_regs()));
-#endif
-/*
- * In the SMP case we use the local APIC timer interrupt to do the
- * profiling, except when we simulate SMP mode on a uniprocessor
- * system, in that case we have to call the local interrupt handler.
- */
-#ifndef CONFIG_X86_LOCAL_APIC
-	profile_tick(CPU_PROFILING);
-#else
-	if (!using_apic_timer)
-		smp_local_timer_interrupt();
-#endif
-}
-
-
-/* you can safely undefine this if you don't have the Neptune chipset */
-
-#define BUGGY_NEPTUN_TIMER
-
-/**
- * do_timer_overflow - process a detected timer overflow condition
- * @count:	hardware timer interrupt count on overflow
- *
- * Description:
- *	This call is invoked when the jiffies count has not incremented but
- *	the hardware timer interrupt has.  It means that a timer tick interrupt
- *	came along while the previous one was pending, thus a tick was missed
- **/
-static inline int do_timer_overflow(int count)
-{
-	int i;
-
-	spin_lock(&i8259A_lock);
-	/*
-	 * This is tricky when I/O APICs are used;
-	 * see do_timer_interrupt().
-	 */
-	i = inb(0x20);
-	spin_unlock(&i8259A_lock);
-	
-	/* assumption about timer being IRQ0 */
-	if (i & 0x01) {
-		/*
-		 * We cannot detect lost timer interrupts ... 
-		 * well, that's why we call them lost, don't we? :)
-		 * [hmm, on the Pentium and Alpha we can ... sort of]
-		 */
-		count -= LATCH;
-	} else {
-#ifdef BUGGY_NEPTUN_TIMER
-		/*
-		 * for the Neptun bug we know that the 'latch'
-		 * command doesn't latch the high and low value
-		 * of the counter atomically. Thus we have to 
-		 * substract 256 from the counter 
-		 * ... funny, isnt it? :)
-		 */
-		
-		count -= 256;
-#else
-		printk("do_slow_gettimeoffset(): hardware timer problem?\n");
-#endif
-	}
-	return count;
+	pit_interrupt_hook();
 }
diff --git a/include/asm-i386/mach-voyager/do_timer.h b/include/asm-i386/mach-voyager/do_timer.h
index 04e69c1..60f9dcc 100644
--- a/include/asm-i386/mach-voyager/do_timer.h
+++ b/include/asm-i386/mach-voyager/do_timer.h
@@ -1,25 +1,18 @@
 /* defines for inline arch setup functions */
-#include <asm/voyager.h>
+#include <linux/clockchips.h>
 
+#include <asm/voyager.h>
+#include <asm/i8253.h>
+
+/**
+ * do_timer_interrupt_hook - hook into timer tick
+ * @regs:     standard registers from interrupt
+ *
+ * Call the pit clock event handler. see asm/i8253.h
+ **/
 static inline void do_timer_interrupt_hook(void)
 {
-	do_timer(1);
-#ifndef CONFIG_SMP
-	update_process_times(user_mode_vm(irq_regs));
-#endif
-
+	pit_interrupt_hook();
 	voyager_timer_interrupt();
 }
 
-static inline int do_timer_overflow(int count)
-{
-	/* can't read the ISR, just assume 1 tick
-	   overflow */
-	if(count > LATCH || count < 0) {
-		printk(KERN_ERR "VOYAGER PROBLEM: count is %d, latch is %d\n", count, LATCH);
-		count = LATCH;
-	}
-	count -= LATCH;
-
-	return count;
-}
diff --git a/include/asm-i386/mce.h b/include/asm-i386/mce.h
index 7cc1a973..b0a02ee 100644
--- a/include/asm-i386/mce.h
+++ b/include/asm-i386/mce.h
@@ -3,3 +3,5 @@
 #else
 #define mcheck_init(c) do {} while(0)
 #endif
+
+extern int mce_disabled;
diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h
index 68ff102..e6aa30f 100644
--- a/include/asm-i386/mmu_context.h
+++ b/include/asm-i386/mmu_context.h
@@ -63,7 +63,7 @@
 }
 
 #define deactivate_mm(tsk, mm)			\
-	asm("movl %0,%%fs": :"r" (0));
+	asm("movl %0,%%gs": :"r" (0));
 
 #define activate_mm(prev, next) \
 	switch_mm((prev),(next),NULL)
diff --git a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
index 770bf6d..f213493 100644
--- a/include/asm-i386/mpspec.h
+++ b/include/asm-i386/mpspec.h
@@ -23,7 +23,6 @@
 extern int mpc_default_type;
 extern unsigned long mp_lapic_addr;
 extern int pic_mode;
-extern int using_apic_timer;
 
 #ifdef CONFIG_ACPI
 extern void mp_register_lapic (u8 id, u8 enabled);
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h
index 609a389..6db40d0 100644
--- a/include/asm-i386/msr.h
+++ b/include/asm-i386/msr.h
@@ -307,4 +307,7 @@
 #define MSR_CORE_PERF_GLOBAL_CTRL	0x38f
 #define MSR_CORE_PERF_GLOBAL_OVF_CTRL	0x390
 
+/* Geode defined MSRs */
+#define MSR_GEODE_BUSCONT_CONF0         0x1900
+
 #endif /* __ASM_MSR_H */
diff --git a/include/asm-i386/paravirt.h b/include/asm-i386/paravirt.h
index 9f06265..6317e0a 100644
--- a/include/asm-i386/paravirt.h
+++ b/include/asm-i386/paravirt.h
@@ -59,90 +59,102 @@
 	   convention.  This makes it easier to implement inline
 	   assembler replacements. */
 
-	void (fastcall *cpuid)(unsigned int *eax, unsigned int *ebx,
+	void (*cpuid)(unsigned int *eax, unsigned int *ebx,
 		      unsigned int *ecx, unsigned int *edx);
 
-	unsigned long (fastcall *get_debugreg)(int regno);
-	void (fastcall *set_debugreg)(int regno, unsigned long value);
+	unsigned long (*get_debugreg)(int regno);
+	void (*set_debugreg)(int regno, unsigned long value);
 
-	void (fastcall *clts)(void);
+	void (*clts)(void);
 
-	unsigned long (fastcall *read_cr0)(void);
-	void (fastcall *write_cr0)(unsigned long);
+	unsigned long (*read_cr0)(void);
+	void (*write_cr0)(unsigned long);
 
-	unsigned long (fastcall *read_cr2)(void);
-	void (fastcall *write_cr2)(unsigned long);
+	unsigned long (*read_cr2)(void);
+	void (*write_cr2)(unsigned long);
 
-	unsigned long (fastcall *read_cr3)(void);
-	void (fastcall *write_cr3)(unsigned long);
+	unsigned long (*read_cr3)(void);
+	void (*write_cr3)(unsigned long);
 
-	unsigned long (fastcall *read_cr4_safe)(void);
-	unsigned long (fastcall *read_cr4)(void);
-	void (fastcall *write_cr4)(unsigned long);
+	unsigned long (*read_cr4_safe)(void);
+	unsigned long (*read_cr4)(void);
+	void (*write_cr4)(unsigned long);
 
-	unsigned long (fastcall *save_fl)(void);
-	void (fastcall *restore_fl)(unsigned long);
-	void (fastcall *irq_disable)(void);
-	void (fastcall *irq_enable)(void);
-	void (fastcall *safe_halt)(void);
-	void (fastcall *halt)(void);
-	void (fastcall *wbinvd)(void);
+	unsigned long (*save_fl)(void);
+	void (*restore_fl)(unsigned long);
+	void (*irq_disable)(void);
+	void (*irq_enable)(void);
+	void (*safe_halt)(void);
+	void (*halt)(void);
+	void (*wbinvd)(void);
 
 	/* err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
-	u64 (fastcall *read_msr)(unsigned int msr, int *err);
-	int (fastcall *write_msr)(unsigned int msr, u64 val);
+	u64 (*read_msr)(unsigned int msr, int *err);
+	int (*write_msr)(unsigned int msr, u64 val);
 
-	u64 (fastcall *read_tsc)(void);
-	u64 (fastcall *read_pmc)(void);
+	u64 (*read_tsc)(void);
+	u64 (*read_pmc)(void);
 
-	void (fastcall *load_tr_desc)(void);
-	void (fastcall *load_gdt)(const struct Xgt_desc_struct *);
-	void (fastcall *load_idt)(const struct Xgt_desc_struct *);
-	void (fastcall *store_gdt)(struct Xgt_desc_struct *);
-	void (fastcall *store_idt)(struct Xgt_desc_struct *);
-	void (fastcall *set_ldt)(const void *desc, unsigned entries);
-	unsigned long (fastcall *store_tr)(void);
-	void (fastcall *load_tls)(struct thread_struct *t, unsigned int cpu);
-	void (fastcall *write_ldt_entry)(void *dt, int entrynum,
+	void (*load_tr_desc)(void);
+	void (*load_gdt)(const struct Xgt_desc_struct *);
+	void (*load_idt)(const struct Xgt_desc_struct *);
+	void (*store_gdt)(struct Xgt_desc_struct *);
+	void (*store_idt)(struct Xgt_desc_struct *);
+	void (*set_ldt)(const void *desc, unsigned entries);
+	unsigned long (*store_tr)(void);
+	void (*load_tls)(struct thread_struct *t, unsigned int cpu);
+	void (*write_ldt_entry)(void *dt, int entrynum,
 					 u32 low, u32 high);
-	void (fastcall *write_gdt_entry)(void *dt, int entrynum,
+	void (*write_gdt_entry)(void *dt, int entrynum,
 					 u32 low, u32 high);
-	void (fastcall *write_idt_entry)(void *dt, int entrynum,
+	void (*write_idt_entry)(void *dt, int entrynum,
 					 u32 low, u32 high);
-	void (fastcall *load_esp0)(struct tss_struct *tss,
+	void (*load_esp0)(struct tss_struct *tss,
 				   struct thread_struct *thread);
 
-	void (fastcall *set_iopl_mask)(unsigned mask);
+	void (*set_iopl_mask)(unsigned mask);
 
-	void (fastcall *io_delay)(void);
+	void (*io_delay)(void);
 	void (*const_udelay)(unsigned long loops);
 
 #ifdef CONFIG_X86_LOCAL_APIC
-	void (fastcall *apic_write)(unsigned long reg, unsigned long v);
-	void (fastcall *apic_write_atomic)(unsigned long reg, unsigned long v);
-	unsigned long (fastcall *apic_read)(unsigned long reg);
+	void (*apic_write)(unsigned long reg, unsigned long v);
+	void (*apic_write_atomic)(unsigned long reg, unsigned long v);
+	unsigned long (*apic_read)(unsigned long reg);
+	void (*setup_boot_clock)(void);
+	void (*setup_secondary_clock)(void);
 #endif
 
-	void (fastcall *flush_tlb_user)(void);
-	void (fastcall *flush_tlb_kernel)(void);
-	void (fastcall *flush_tlb_single)(u32 addr);
+	void (*flush_tlb_user)(void);
+	void (*flush_tlb_kernel)(void);
+	void (*flush_tlb_single)(u32 addr);
 
-	void (fastcall *set_pte)(pte_t *ptep, pte_t pteval);
-	void (fastcall *set_pte_at)(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval);
-	void (fastcall *set_pmd)(pmd_t *pmdp, pmd_t pmdval);
-	void (fastcall *pte_update)(struct mm_struct *mm, u32 addr, pte_t *ptep);
-	void (fastcall *pte_update_defer)(struct mm_struct *mm, u32 addr, pte_t *ptep);
+	void (*alloc_pt)(u32 pfn);
+	void (*alloc_pd)(u32 pfn);
+	void (*alloc_pd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
+	void (*release_pt)(u32 pfn);
+	void (*release_pd)(u32 pfn);
+
+	void (*set_pte)(pte_t *ptep, pte_t pteval);
+	void (*set_pte_at)(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval);
+	void (*set_pmd)(pmd_t *pmdp, pmd_t pmdval);
+	void (*pte_update)(struct mm_struct *mm, u32 addr, pte_t *ptep);
+	void (*pte_update_defer)(struct mm_struct *mm, u32 addr, pte_t *ptep);
 #ifdef CONFIG_X86_PAE
-	void (fastcall *set_pte_atomic)(pte_t *ptep, pte_t pteval);
-	void (fastcall *set_pte_present)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
-	void (fastcall *set_pud)(pud_t *pudp, pud_t pudval);
-	void (fastcall *pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
-	void (fastcall *pmd_clear)(pmd_t *pmdp);
+	void (*set_pte_atomic)(pte_t *ptep, pte_t pteval);
+	void (*set_pte_present)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
+	void (*set_pud)(pud_t *pudp, pud_t pudval);
+	void (*pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+	void (*pmd_clear)(pmd_t *pmdp);
 #endif
 
+	void (*set_lazy_mode)(int mode);
+
 	/* These two are jmp to, not actually called. */
-	void (fastcall *irq_enable_sysexit)(void);
-	void (fastcall *iret)(void);
+	void (*irq_enable_sysexit)(void);
+	void (*iret)(void);
+
+	void (*startup_ipi_hook)(int phys_apicid, unsigned long start_eip, unsigned long start_esp);
 };
 
 /* Mark a paravirt probe function. */
@@ -313,13 +325,38 @@
 {
 	return paravirt_ops.apic_read(reg);
 }
+
+static inline void setup_boot_clock(void)
+{
+	paravirt_ops.setup_boot_clock();
+}
+
+static inline void setup_secondary_clock(void)
+{
+	paravirt_ops.setup_secondary_clock();
+}
 #endif
 
+#ifdef CONFIG_SMP
+static inline void startup_ipi_hook(int phys_apicid, unsigned long start_eip,
+				    unsigned long start_esp)
+{
+	return paravirt_ops.startup_ipi_hook(phys_apicid, start_eip, start_esp);
+}
+#endif
 
 #define __flush_tlb() paravirt_ops.flush_tlb_user()
 #define __flush_tlb_global() paravirt_ops.flush_tlb_kernel()
 #define __flush_tlb_single(addr) paravirt_ops.flush_tlb_single(addr)
 
+#define paravirt_alloc_pt(pfn) paravirt_ops.alloc_pt(pfn)
+#define paravirt_release_pt(pfn) paravirt_ops.release_pt(pfn)
+
+#define paravirt_alloc_pd(pfn) paravirt_ops.alloc_pd(pfn)
+#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) \
+	paravirt_ops.alloc_pd_clone(pfn, clonepfn, start, count)
+#define paravirt_release_pd(pfn) paravirt_ops.release_pd(pfn)
+
 static inline void set_pte(pte_t *ptep, pte_t pteval)
 {
 	paravirt_ops.set_pte(ptep, pteval);
@@ -372,6 +409,19 @@
 }
 #endif
 
+/* Lazy mode for batching updates / context switch */
+#define PARAVIRT_LAZY_NONE 0
+#define PARAVIRT_LAZY_MMU  1
+#define PARAVIRT_LAZY_CPU  2
+
+#define  __HAVE_ARCH_ENTER_LAZY_CPU_MODE
+#define arch_enter_lazy_cpu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_CPU)
+#define arch_leave_lazy_cpu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_NONE)
+
+#define  __HAVE_ARCH_ENTER_LAZY_MMU_MODE
+#define arch_enter_lazy_mmu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_MMU)
+#define arch_leave_lazy_mmu_mode() paravirt_ops.set_lazy_mode(PARAVIRT_LAZY_NONE)
+
 /* These all sit in the .parainstructions section to tell us what to patch. */
 struct paravirt_patch {
 	u8 *instr; 		/* original instructions */
diff --git a/include/asm-i386/pda.h b/include/asm-i386/pda.h
index 2ba2736..b12d59a 100644
--- a/include/asm-i386/pda.h
+++ b/include/asm-i386/pda.h
@@ -39,19 +39,19 @@
 		if (0) { T__ tmp__; tmp__ = (val); }			\
 		switch (sizeof(_proxy_pda.field)) {			\
 		case 1:							\
-			asm(op "b %1,%%gs:%c2"				\
+			asm(op "b %1,%%fs:%c2"				\
 			    : "+m" (_proxy_pda.field)			\
 			    :"ri" ((T__)val),				\
 			     "i"(pda_offset(field)));			\
 			break;						\
 		case 2:							\
-			asm(op "w %1,%%gs:%c2"				\
+			asm(op "w %1,%%fs:%c2"				\
 			    : "+m" (_proxy_pda.field)			\
 			    :"ri" ((T__)val),				\
 			     "i"(pda_offset(field)));			\
 			break;						\
 		case 4:							\
-			asm(op "l %1,%%gs:%c2"				\
+			asm(op "l %1,%%fs:%c2"				\
 			    : "+m" (_proxy_pda.field)			\
 			    :"ri" ((T__)val),				\
 			     "i"(pda_offset(field)));			\
@@ -65,19 +65,19 @@
 		typeof(_proxy_pda.field) ret__;				\
 		switch (sizeof(_proxy_pda.field)) {			\
 		case 1:							\
-			asm(op "b %%gs:%c1,%0"				\
+			asm(op "b %%fs:%c1,%0"				\
 			    : "=r" (ret__)				\
 			    : "i" (pda_offset(field)),			\
 			      "m" (_proxy_pda.field));			\
 			break;						\
 		case 2:							\
-			asm(op "w %%gs:%c1,%0"				\
+			asm(op "w %%fs:%c1,%0"				\
 			    : "=r" (ret__)				\
 			    : "i" (pda_offset(field)),			\
 			      "m" (_proxy_pda.field));			\
 			break;						\
 		case 4:							\
-			asm(op "l %%gs:%c1,%0"				\
+			asm(op "l %%fs:%c1,%0"				\
 			    : "=r" (ret__)				\
 			    : "i" (pda_offset(field)),			\
 			      "m" (_proxy_pda.field));			\
diff --git a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h
index 4b1e613..c8dc2d0 100644
--- a/include/asm-i386/pgalloc.h
+++ b/include/asm-i386/pgalloc.h
@@ -5,13 +5,31 @@
 #include <linux/threads.h>
 #include <linux/mm.h>		/* for struct page */
 
-#define pmd_populate_kernel(mm, pmd, pte) \
-		set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define paravirt_alloc_pt(pfn) do { } while (0)
+#define paravirt_alloc_pd(pfn) do { } while (0)
+#define paravirt_alloc_pd(pfn) do { } while (0)
+#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
+#define paravirt_release_pt(pfn) do { } while (0)
+#define paravirt_release_pd(pfn) do { } while (0)
+#endif
+
+#define pmd_populate_kernel(mm, pmd, pte)			\
+do {								\
+	paravirt_alloc_pt(__pa(pte) >> PAGE_SHIFT);		\
+	set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)));		\
+} while (0)
 
 #define pmd_populate(mm, pmd, pte) 				\
+do {								\
+	paravirt_alloc_pt(page_to_pfn(pte));			\
 	set_pmd(pmd, __pmd(_PAGE_TABLE +			\
 		((unsigned long long)page_to_pfn(pte) <<	\
-			(unsigned long long) PAGE_SHIFT)))
+			(unsigned long long) PAGE_SHIFT)));	\
+} while (0)
+
 /*
  * Allocate and free page tables.
  */
@@ -32,7 +50,11 @@
 }
 
 
-#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
+#define __pte_free_tlb(tlb,pte) 					\
+do {									\
+	paravirt_release_pt(page_to_pfn(pte));				\
+	tlb_remove_page((tlb),(pte));					\
+} while (0)
 
 #ifdef CONFIG_X86_PAE
 /*
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 359f10b..11bf899 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -424,7 +424,7 @@
 	.vm86_info = NULL,						\
 	.sysenter_cs = __KERNEL_CS,					\
 	.io_bitmap_ptr = NULL,						\
-	.gs = __KERNEL_PDA,						\
+	.fs = __KERNEL_PDA,						\
 }
 
 /*
@@ -442,8 +442,8 @@
 }
 
 #define start_thread(regs, new_eip, new_esp) do {		\
-	__asm__("movl %0,%%fs": :"r" (0));			\
-	regs->xgs = 0;						\
+	__asm__("movl %0,%%gs": :"r" (0));			\
+	regs->xfs = 0;						\
 	set_fs(USER_DS);					\
 	regs->xds = __USER_DS;					\
 	regs->xes = __USER_DS;					\
diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
index bdbc894..6002597 100644
--- a/include/asm-i386/ptrace.h
+++ b/include/asm-i386/ptrace.h
@@ -16,8 +16,8 @@
 	long eax;
 	int  xds;
 	int  xes;
-	/* int  xfs; */
-	int  xgs;
+	int  xfs;
+	/* int  xgs; */
 	long orig_eax;
 	long eip;
 	int  xcs;
@@ -49,6 +49,10 @@
 {
 	return ((regs->xcs & SEGMENT_RPL_MASK) | (regs->eflags & VM_MASK)) >= USER_RPL;
 }
+static inline int v8086_mode(struct pt_regs *regs)
+{
+	return (regs->eflags & VM_MASK);
+}
 
 #define instruction_pointer(regs) ((regs)->eip)
 #define regs_return_value(regs) ((regs)->eax)
diff --git a/include/asm-i386/segment.h b/include/asm-i386/segment.h
index 3c796af..065f10b 100644
--- a/include/asm-i386/segment.h
+++ b/include/asm-i386/segment.h
@@ -83,14 +83,8 @@
  * The GDT has 32 entries
  */
 #define GDT_ENTRIES 32
-
 #define GDT_SIZE (GDT_ENTRIES * 8)
 
-/* Matches __KERNEL_CS and __USER_CS (they must be 2 entries apart) */
-#define SEGMENT_IS_FLAT_CODE(x)  (((x) & 0xec) == GDT_ENTRY_KERNEL_CS * 8)
-/* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
-#define SEGMENT_IS_PNP_CODE(x)   (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
-
 /* Simple and small GDT entries for booting only */
 
 #define GDT_ENTRY_BOOT_CS		2
@@ -134,4 +128,17 @@
 #ifndef CONFIG_PARAVIRT
 #define get_kernel_rpl()  0
 #endif
+/*
+ * Matching rules for certain types of segments.
+ */
+
+/* Matches only __KERNEL_CS, ignoring PnP / USER / APM segments */
+#define SEGMENT_IS_KERNEL_CODE(x) (((x) & 0xfc) == GDT_ENTRY_KERNEL_CS * 8)
+
+/* Matches __KERNEL_CS and __USER_CS (they must be 2 entries apart) */
+#define SEGMENT_IS_FLAT_CODE(x)  (((x) & 0xec) == GDT_ENTRY_KERNEL_CS * 8)
+
+/* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
+#define SEGMENT_IS_PNP_CODE(x)   (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
+
 #endif
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
index 67659db..0e8077c 100644
--- a/include/asm-i386/setup.h
+++ b/include/asm-i386/setup.h
@@ -6,7 +6,7 @@
 #ifndef _i386_SETUP_H
 #define _i386_SETUP_H
 
-#define COMMAND_LINE_SIZE 256
+#define COMMAND_LINE_SIZE 2048
 
 #ifdef __KERNEL__
 #include <linux/pfn.h>
@@ -77,6 +77,8 @@
 void __init add_memory_region(unsigned long long start,
 			      unsigned long long size, int type);
 
+extern unsigned long init_pg_tables_end;
+
 #endif /* __ASSEMBLY__ */
 
 #endif  /*  __KERNEL__  */
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 64fe624..6bf0033 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -52,6 +52,11 @@
 extern void cpu_uninit(void);
 #endif
 
+#ifndef CONFIG_PARAVIRT
+#define startup_ipi_hook(phys_apicid, start_eip, start_esp) 		\
+do { } while (0)
+#endif
+
 /*
  * This function is needed by all SMP systems. It must _always_ be valid
  * from the initial startup. We map APIC_BASE very early in page_setup(),
diff --git a/include/asm-i386/termios.h b/include/asm-i386/termios.h
index 03f5485..7c99678 100644
--- a/include/asm-i386/termios.h
+++ b/include/asm-i386/termios.h
@@ -39,24 +39,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 #include <linux/module.h>
 
diff --git a/include/asm-i386/time.h b/include/asm-i386/time.h
index ea8065a..571b429 100644
--- a/include/asm-i386/time.h
+++ b/include/asm-i386/time.h
@@ -30,6 +30,7 @@
 
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
+extern unsigned long long native_sched_clock(void);
 #else /* !CONFIG_PARAVIRT */
 
 #define get_wallclock() native_get_wallclock()
diff --git a/include/asm-i386/timer.h b/include/asm-i386/timer.h
index d0ebd05..4752c3a 100644
--- a/include/asm-i386/timer.h
+++ b/include/asm-i386/timer.h
@@ -8,6 +8,9 @@
 /* Modifiers for buggy PIT handling */
 extern int pit_latch_buggy;
 extern int timer_ack;
+extern int no_timer_check;
+extern unsigned long long (*custom_sched_clock)(void);
+extern int no_sync_cmos_clock;
 extern int recalibrate_cpu_khz(void);
 
 #endif
diff --git a/include/asm-i386/tsc.h b/include/asm-i386/tsc.h
index c139331..e997891 100644
--- a/include/asm-i386/tsc.h
+++ b/include/asm-i386/tsc.h
@@ -1,48 +1 @@
-/*
- * linux/include/asm-i386/tsc.h
- *
- * i386 TSC related functions
- */
-#ifndef _ASM_i386_TSC_H
-#define _ASM_i386_TSC_H
-
-#include <asm/processor.h>
-
-/*
- * Standard way to access the cycle counter on i586+ CPUs.
- * Currently only used on SMP.
- *
- * If you really have a SMP machine with i486 chips or older,
- * compile for that, and this will just always return zero.
- * That's ok, it just means that the nicer scheduling heuristics
- * won't work for you.
- *
- * We only use the low 32 bits, and we'd simply better make sure
- * that we reschedule before that wraps. Scheduling at least every
- * four billion cycles just basically sounds like a good idea,
- * regardless of how fast the machine is.
- */
-typedef unsigned long long cycles_t;
-
-extern unsigned int cpu_khz;
-extern unsigned int tsc_khz;
-
-static inline cycles_t get_cycles(void)
-{
-	unsigned long long ret = 0;
-
-#ifndef CONFIG_X86_TSC
-	if (!cpu_has_tsc)
-		return 0;
-#endif
-
-#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
-	rdtscll(ret);
-#endif
-	return ret;
-}
-
-extern void tsc_init(void);
-extern void mark_tsc_unstable(void);
-
-#endif
+#include <asm-x86_64/tsc.h>
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index eef5133..70829ae 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -54,10 +54,10 @@
  * This needs 33-bit arithmetic. We have a carry...
  */
 #define __range_ok(addr,size) ({ \
-	unsigned long flag,sum; \
+	unsigned long flag,roksum; \
 	__chk_user_ptr(addr); \
 	asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
-		:"=&r" (flag), "=r" (sum) \
+		:"=&r" (flag), "=r" (roksum) \
 		:"1" (addr),"g" ((int)(size)),"rm" (current_thread_info()->addr_limit.seg)); \
 	flag; })
 
diff --git a/include/asm-i386/vmi.h b/include/asm-i386/vmi.h
new file mode 100644
index 0000000..43c8933
--- /dev/null
+++ b/include/asm-i386/vmi.h
@@ -0,0 +1,262 @@
+/*
+ * VMI interface definition
+ *
+ * Copyright (C) 2005, VMware, 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Maintained by: Zachary Amsden zach@vmware.com
+ *
+ */
+#include <linux/types.h>
+
+/*
+ *---------------------------------------------------------------------
+ *
+ *  VMI Option ROM API
+ *
+ *---------------------------------------------------------------------
+ */
+#define VMI_SIGNATURE 0x696d5663   /* "cVmi" */
+
+#define PCI_VENDOR_ID_VMWARE            0x15AD
+#define PCI_DEVICE_ID_VMWARE_VMI        0x0801
+
+/*
+ * We use two version numbers for compatibility, with the major
+ * number signifying interface breakages, and the minor number
+ * interface extensions.
+ */
+#define VMI_API_REV_MAJOR       3
+#define VMI_API_REV_MINOR       0
+
+#define VMI_CALL_CPUID			0
+#define VMI_CALL_WRMSR			1
+#define VMI_CALL_RDMSR			2
+#define VMI_CALL_SetGDT			3
+#define VMI_CALL_SetLDT			4
+#define VMI_CALL_SetIDT			5
+#define VMI_CALL_SetTR			6
+#define VMI_CALL_GetGDT			7
+#define VMI_CALL_GetLDT			8
+#define VMI_CALL_GetIDT			9
+#define VMI_CALL_GetTR			10
+#define VMI_CALL_WriteGDTEntry		11
+#define VMI_CALL_WriteLDTEntry		12
+#define VMI_CALL_WriteIDTEntry		13
+#define VMI_CALL_UpdateKernelStack	14
+#define VMI_CALL_SetCR0			15
+#define VMI_CALL_SetCR2			16
+#define VMI_CALL_SetCR3			17
+#define VMI_CALL_SetCR4			18
+#define VMI_CALL_GetCR0			19
+#define VMI_CALL_GetCR2			20
+#define VMI_CALL_GetCR3			21
+#define VMI_CALL_GetCR4			22
+#define VMI_CALL_WBINVD			23
+#define VMI_CALL_SetDR			24
+#define VMI_CALL_GetDR			25
+#define VMI_CALL_RDPMC			26
+#define VMI_CALL_RDTSC			27
+#define VMI_CALL_CLTS			28
+#define VMI_CALL_EnableInterrupts	29
+#define VMI_CALL_DisableInterrupts	30
+#define VMI_CALL_GetInterruptMask	31
+#define VMI_CALL_SetInterruptMask	32
+#define VMI_CALL_IRET			33
+#define VMI_CALL_SYSEXIT		34
+#define VMI_CALL_Halt			35
+#define VMI_CALL_Reboot			36
+#define VMI_CALL_Shutdown		37
+#define VMI_CALL_SetPxE			38
+#define VMI_CALL_SetPxELong		39
+#define VMI_CALL_UpdatePxE		40
+#define VMI_CALL_UpdatePxELong		41
+#define VMI_CALL_MachineToPhysical	42
+#define VMI_CALL_PhysicalToMachine	43
+#define VMI_CALL_AllocatePage		44
+#define VMI_CALL_ReleasePage		45
+#define VMI_CALL_InvalPage		46
+#define VMI_CALL_FlushTLB		47
+#define VMI_CALL_SetLinearMapping	48
+
+#define VMI_CALL_SetIOPLMask		61
+#define VMI_CALL_SetInitialAPState	62
+#define VMI_CALL_APICWrite		63
+#define VMI_CALL_APICRead		64
+#define VMI_CALL_SetLazyMode		73
+
+/*
+ *---------------------------------------------------------------------
+ *
+ * MMU operation flags
+ *
+ *---------------------------------------------------------------------
+ */
+
+/* Flags used by VMI_{Allocate|Release}Page call */
+#define VMI_PAGE_PAE             0x10  /* Allocate PAE shadow */
+#define VMI_PAGE_CLONE           0x20  /* Clone from another shadow */
+#define VMI_PAGE_ZEROED          0x40  /* Page is pre-zeroed */
+
+
+/* Flags shared by Allocate|Release Page and PTE updates */
+#define VMI_PAGE_PT              0x01
+#define VMI_PAGE_PD              0x02
+#define VMI_PAGE_PDP             0x04
+#define VMI_PAGE_PML4            0x08
+
+#define VMI_PAGE_NORMAL          0x00 /* for debugging */
+
+/* Flags used by PTE updates */
+#define VMI_PAGE_CURRENT_AS      0x10 /* implies VMI_PAGE_VA_MASK is valid */
+#define VMI_PAGE_DEFER           0x20 /* may queue update until TLB inval */
+#define VMI_PAGE_VA_MASK         0xfffff000
+
+#ifdef CONFIG_X86_PAE
+#define VMI_PAGE_L1		(VMI_PAGE_PT | VMI_PAGE_PAE | VMI_PAGE_ZEROED)
+#define VMI_PAGE_L2		(VMI_PAGE_PD | VMI_PAGE_PAE | VMI_PAGE_ZEROED)
+#else
+#define VMI_PAGE_L1		(VMI_PAGE_PT | VMI_PAGE_ZEROED)
+#define VMI_PAGE_L2		(VMI_PAGE_PD | VMI_PAGE_ZEROED)
+#endif
+
+/* Flags used by VMI_FlushTLB call */
+#define VMI_FLUSH_TLB            0x01
+#define VMI_FLUSH_GLOBAL         0x02
+
+/*
+ *---------------------------------------------------------------------
+ *
+ *  VMI relocation definitions for ROM call get_reloc
+ *
+ *---------------------------------------------------------------------
+ */
+
+/* VMI Relocation types */
+#define VMI_RELOCATION_NONE     0
+#define VMI_RELOCATION_CALL_REL 1
+#define VMI_RELOCATION_JUMP_REL 2
+#define VMI_RELOCATION_NOP	3
+
+#ifndef __ASSEMBLY__
+struct vmi_relocation_info {
+        unsigned char           *eip;
+        unsigned char           type;
+        unsigned char           reserved[3];
+};
+#endif
+
+
+/*
+ *---------------------------------------------------------------------
+ *
+ *  Generic ROM structures and definitions
+ *
+ *---------------------------------------------------------------------
+ */
+
+#ifndef __ASSEMBLY__
+
+struct vrom_header {
+	u16     rom_signature;  // option ROM signature
+	u8      rom_length;     // ROM length in 512 byte chunks
+	u8      rom_entry[4];   // 16-bit code entry point
+	u8      rom_pad0;       // 4-byte align pad
+	u32     vrom_signature; // VROM identification signature
+	u8      api_version_min;// Minor version of API
+	u8      api_version_maj;// Major version of API
+	u8      jump_slots;     // Number of jump slots
+	u8      reserved1;      // Reserved for expansion
+	u32     virtual_top;    // Hypervisor virtual address start
+	u16     reserved2;      // Reserved for expansion
+	u16	license_offs;	// Offset to License string
+	u16     pci_header_offs;// Offset to PCI OPROM header
+	u16     pnp_header_offs;// Offset to PnP OPROM header
+	u32     rom_pad3;       // PnP reserverd / VMI reserved
+	u8      reserved[96];   // Reserved for headers
+	char    vmi_init[8];    // VMI_Init jump point
+	char    get_reloc[8];   // VMI_GetRelocationInfo jump point
+} __attribute__((packed));
+
+struct pnp_header {
+        char sig[4];
+        char rev;
+        char size;
+        short next;
+        short res;
+        long devID;
+        unsigned short manufacturer_offset;
+        unsigned short product_offset;
+} __attribute__((packed));
+
+struct pci_header {
+        char sig[4];
+        short vendorID;
+        short deviceID;
+        short vpdData;
+        short size;
+        char rev;
+        char class;
+        char subclass;
+        char interface;
+        short chunks;
+        char rom_version_min;
+        char rom_version_maj;
+        char codetype;
+        char lastRom;
+        short reserved;
+} __attribute__((packed));
+
+/* Function prototypes for bootstrapping */
+extern void vmi_init(void);
+extern void vmi_bringup(void);
+extern void vmi_apply_boot_page_allocations(void);
+
+/* State needed to start an application processor in an SMP system. */
+struct vmi_ap_state {
+	u32 cr0;
+	u32 cr2;
+	u32 cr3;
+	u32 cr4;
+
+	u64 efer;
+
+	u32 eip;
+	u32 eflags;
+	u32 eax;
+	u32 ebx;
+	u32 ecx;
+	u32 edx;
+	u32 esp;
+	u32 ebp;
+	u32 esi;
+	u32 edi;
+	u16 cs;
+	u16 ss;
+	u16 ds;
+	u16 es;
+	u16 fs;
+	u16 gs;
+	u16 ldtr;
+
+	u16 gdtr_limit;
+	u32 gdtr_base;
+	u32 idtr_base;
+	u16 idtr_limit;
+};
+
+#endif
diff --git a/include/asm-i386/vmi_time.h b/include/asm-i386/vmi_time.h
new file mode 100644
index 0000000..c129312
--- /dev/null
+++ b/include/asm-i386/vmi_time.h
@@ -0,0 +1,103 @@
+/*
+ * VMI Time wrappers
+ *
+ * Copyright (C) 2006, VMware, 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to dhecht@vmware.com
+ *
+ */
+
+#ifndef __VMI_TIME_H
+#define __VMI_TIME_H
+
+/*
+ * Raw VMI call indices for timer functions
+ */
+#define VMI_CALL_GetCycleFrequency	66
+#define VMI_CALL_GetCycleCounter	67
+#define VMI_CALL_SetAlarm		68
+#define VMI_CALL_CancelAlarm		69
+#define VMI_CALL_GetWallclockTime	70
+#define VMI_CALL_WallclockUpdated	71
+
+/* Cached VMI timer operations */
+extern struct vmi_timer_ops {
+	u64 (*get_cycle_frequency)(void);
+	u64 (*get_cycle_counter)(int);
+	u64 (*get_wallclock)(void);
+	int (*wallclock_updated)(void);
+	void (*set_alarm)(u32 flags, u64 expiry, u64 period);
+	void (*cancel_alarm)(u32 flags);
+} vmi_timer_ops;
+
+/* Prototypes */
+extern void __init vmi_time_init(void);
+extern unsigned long vmi_get_wallclock(void);
+extern int vmi_set_wallclock(unsigned long now);
+extern unsigned long long vmi_sched_clock(void);
+
+#ifdef CONFIG_X86_LOCAL_APIC
+extern void __init vmi_timer_setup_boot_alarm(void);
+extern void __init vmi_timer_setup_secondary_alarm(void);
+extern void apic_vmi_timer_interrupt(void);
+#endif
+
+#ifdef CONFIG_NO_IDLE_HZ
+extern int vmi_stop_hz_timer(void);
+extern void vmi_account_time_restart_hz_timer(void);
+#endif
+
+/*
+ * When run under a hypervisor, a vcpu is always in one of three states:
+ * running, halted, or ready.  The vcpu is in the 'running' state if it
+ * is executing.  When the vcpu executes the halt interface, the vcpu
+ * enters the 'halted' state and remains halted until there is some work
+ * pending for the vcpu (e.g. an alarm expires, host I/O completes on
+ * behalf of virtual I/O).  At this point, the vcpu enters the 'ready'
+ * state (waiting for the hypervisor to reschedule it).  Finally, at any
+ * time when the vcpu is not in the 'running' state nor the 'halted'
+ * state, it is in the 'ready' state.
+ *
+ * Real time is advances while the vcpu is 'running', 'ready', or
+ * 'halted'.  Stolen time is the time in which the vcpu is in the
+ * 'ready' state.  Available time is the remaining time -- the vcpu is
+ * either 'running' or 'halted'.
+ *
+ * All three views of time are accessible through the VMI cycle
+ * counters.
+ */
+
+/* The cycle counters. */
+#define VMI_CYCLES_REAL         0
+#define VMI_CYCLES_AVAILABLE    1
+#define VMI_CYCLES_STOLEN       2
+
+/* The alarm interface 'flags' bits */
+#define VMI_ALARM_COUNTERS      2
+
+#define VMI_ALARM_COUNTER_MASK  0x000000ff
+
+#define VMI_ALARM_WIRED_IRQ0    0x00000000
+#define VMI_ALARM_WIRED_LVTT    0x00010000
+
+#define VMI_ALARM_IS_ONESHOT    0x00000000
+#define VMI_ALARM_IS_PERIODIC   0x00000100
+
+#define CONFIG_VMI_ALARM_HZ	100
+
+#endif
diff --git a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h
index ebd5887..6299b51 100644
--- a/include/asm-ia64/dma-mapping.h
+++ b/include/asm-ia64/dma-mapping.h
@@ -8,9 +8,20 @@
 #include <asm/machvec.h>
 
 #define dma_alloc_coherent	platform_dma_alloc_coherent
-#define dma_alloc_noncoherent	platform_dma_alloc_coherent	/* coherent mem. is cheap */
+/* coherent mem. is cheap */
+static inline void *
+dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+		      gfp_t flag)
+{
+	return dma_alloc_coherent(dev, size, dma_handle, flag);
+}
 #define dma_free_coherent	platform_dma_free_coherent
-#define dma_free_noncoherent	platform_dma_free_coherent
+static inline void
+dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
+		     dma_addr_t dma_handle)
+{
+	dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
 #define dma_map_single		platform_dma_map_single
 #define dma_map_sg		platform_dma_map_sg
 #define dma_unmap_single	platform_dma_unmap_single
diff --git a/include/asm-ia64/kexec.h b/include/asm-ia64/kexec.h
index 01c36b0..f2ad469 100644
--- a/include/asm-ia64/kexec.h
+++ b/include/asm-ia64/kexec.h
@@ -23,7 +23,7 @@
 
 extern struct kimage *ia64_kimage;
 DECLARE_PER_CPU(u64, ia64_mca_pal_base);
-const extern unsigned int relocate_new_kernel_size;
+extern const unsigned int relocate_new_kernel_size;
 extern void relocate_new_kernel(unsigned long, unsigned long,
 		struct ia64_boot_param *, unsigned long);
 static inline void
diff --git a/include/asm-ia64/libata-portmap.h b/include/asm-ia64/libata-portmap.h
new file mode 100644
index 0000000..0e00c9a
--- /dev/null
+++ b/include/asm-ia64/libata-portmap.h
@@ -0,0 +1,12 @@
+#ifndef __ASM_IA64_LIBATA_PORTMAP_H
+#define __ASM_IA64_LIBATA_PORTMAP_H
+
+#define ATA_PRIMARY_CMD		0x1F0
+#define ATA_PRIMARY_CTL		0x3F6
+#define ATA_PRIMARY_IRQ(dev)	isa_irq_to_vector(14)
+
+#define ATA_SECONDARY_CMD	0x170
+#define ATA_SECONDARY_CTL	0x376
+#define ATA_SECONDARY_IRQ(dev)	isa_irq_to_vector(15)
+
+#endif
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index bc76815..e43021a 100644
--- a/include/asm-ia64/pal.h
+++ b/include/asm-ia64/pal.h
@@ -32,7 +32,7 @@
 #define PAL_CACHE_FLUSH		1	/* flush i/d cache */
 #define PAL_CACHE_INFO		2	/* get detailed i/d cache info */
 #define PAL_CACHE_INIT		3	/* initialize i/d cache */
-#define PAL_CACHE_SUMMARY	4	/* get summary of cache heirarchy */
+#define PAL_CACHE_SUMMARY	4	/* get summary of cache hierarchy */
 #define PAL_MEM_ATTRIB		5	/* list supported memory attributes */
 #define PAL_PTCE_INFO		6	/* purge TLB info */
 #define PAL_VM_INFO		7	/* return supported virtual memory features */
@@ -113,14 +113,14 @@
 						 */
 #define PAL_STATUS_REQUIRES_MEMORY	(-9)	/* Call requires PAL memory buffer */
 
-/* Processor cache level in the heirarchy */
+/* Processor cache level in the hierarchy */
 typedef u64				pal_cache_level_t;
 #define PAL_CACHE_LEVEL_L0		0	/* L0 */
 #define PAL_CACHE_LEVEL_L1		1	/* L1 */
 #define PAL_CACHE_LEVEL_L2		2	/* L2 */
 
 
-/* Processor cache type at a particular level in the heirarchy */
+/* Processor cache type at a particular level in the hierarchy */
 
 typedef u64				pal_cache_type_t;
 #define PAL_CACHE_TYPE_INSTRUCTION	1	/* Instruction cache */
@@ -272,14 +272,14 @@
 #define PAL_CACHE_PROT_METHOD_ECC		3	/* ECC protection */
 
 
-/* Processor cache line identification in the heirarchy */
+/* Processor cache line identification in the hierarchy */
 typedef union pal_cache_line_id_u {
 	u64			pclid_data;
 	struct {
 		u64		cache_type	: 8,	/* 7-0 cache type */
 				level		: 8,	/* 15-8 level of the
 							 * cache in the
-							 * heirarchy.
+							 * hierarchy.
 							 */
 				way		: 8,	/* 23-16 way in the set
 							 */
@@ -292,7 +292,7 @@
 		u64		cache_type	: 8,	/* 7-0 cache type */
 				level		: 8,	/* 15-8 level of the
 							 * cache in the
-							 * heirarchy.
+							 * hierarchy.
 							 */
 				way		: 8,	/* 23-16 way in the set
 							 */
@@ -978,7 +978,7 @@
 	return iprv.status;
 }
 
-/* Return summary information about the heirarchy of caches controlled by the processor */
+/* Return summary information about the hierarchy of caches controlled by the processor */
 static inline s64
 ia64_pal_cache_summary (u64 *cache_levels, u64 *unique_caches)
 {
diff --git a/include/asm-ia64/setup.h b/include/asm-ia64/setup.h
index ea29b57..4399a44 100644
--- a/include/asm-ia64/setup.h
+++ b/include/asm-ia64/setup.h
@@ -1,6 +1,6 @@
 #ifndef __IA64_SETUP_H
 #define __IA64_SETUP_H
 
-#define COMMAND_LINE_SIZE	512
+#define COMMAND_LINE_SIZE	2048
 
 #endif
diff --git a/include/asm-ia64/termios.h b/include/asm-ia64/termios.h
index 42c9569..08750c2 100644
--- a/include/asm-ia64/termios.h
+++ b/include/asm-ia64/termios.h
@@ -46,24 +46,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS msgs */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 # ifdef __KERNEL__
 
 /*	intr=^C		quit=^\		erase=del	kill=^U
diff --git a/include/asm-m32r/a.out.h b/include/asm-m32r/a.out.h
index 4619ba5..9a4a5d2 100644
--- a/include/asm-m32r/a.out.h
+++ b/include/asm-m32r/a.out.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_A_OUT_H
 #define _ASM_M32R_A_OUT_H
 
-/* orig : i386 2.4.18 */
-
 struct exec
 {
   unsigned long a_info;		/* Use macros N_MAGIC, etc for access */
diff --git a/include/asm-m32r/addrspace.h b/include/asm-m32r/addrspace.h
index 06a83dc..81782c1 100644
--- a/include/asm-m32r/addrspace.h
+++ b/include/asm-m32r/addrspace.h
@@ -1,4 +1,3 @@
-/* $Id$ */
 /*
  * 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
diff --git a/include/asm-m32r/bugs.h b/include/asm-m32r/bugs.h
index 9a56f66..f77214e 100644
--- a/include/asm-m32r/bugs.h
+++ b/include/asm-m32r/bugs.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_BUGS_H
 #define _ASM_M32R_BUGS_H
 
-/* $Id$ */
-
 /*
  * This is included by init/main.c to check for architecture-dependent bugs.
  *
diff --git a/include/asm-m32r/byteorder.h b/include/asm-m32r/byteorder.h
index 3c0b9a2..10b2c1d 100644
--- a/include/asm-m32r/byteorder.h
+++ b/include/asm-m32r/byteorder.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_BYTEORDER_H
 #define _ASM_M32R_BYTEORDER_H
 
-/* $Id$ */
-
 #include <asm/types.h>
 
 #if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
diff --git a/include/asm-m32r/cache.h b/include/asm-m32r/cache.h
index 9c2b2d9..40b3ee98 100644
--- a/include/asm-m32r/cache.h
+++ b/include/asm-m32r/cache.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_CACHE_H
 #define _ASM_M32R_CACHE_H
 
-/* $Id$ */
-
 /* L1 cache line size */
 #define L1_CACHE_SHIFT		4
 #define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
diff --git a/include/asm-m32r/cacheflush.h b/include/asm-m32r/cacheflush.h
index 56961a9..78587c9 100644
--- a/include/asm-m32r/cacheflush.h
+++ b/include/asm-m32r/cacheflush.h
@@ -67,4 +67,3 @@
 	memcpy(dst, src, len)
 
 #endif /* _ASM_M32R_CACHEFLUSH_H */
-
diff --git a/include/asm-m32r/current.h b/include/asm-m32r/current.h
index c19d927f..7859d86 100644
--- a/include/asm-m32r/current.h
+++ b/include/asm-m32r/current.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_CURRENT_H
 #define _ASM_M32R_CURRENT_H
 
-/* $Id$ */
-
 #include <linux/thread_info.h>
 
 struct task_struct;
@@ -15,4 +13,3 @@
 #define current	(get_current())
 
 #endif	/* _ASM_M32R_CURRENT_H */
-
diff --git a/include/asm-m32r/delay.h b/include/asm-m32r/delay.h
index f285eae..164448d 100644
--- a/include/asm-m32r/delay.h
+++ b/include/asm-m32r/delay.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_DELAY_H
 #define _ASM_M32R_DELAY_H
 
-/* $Id$ */
-
 /*
  * Copyright (C) 1993 Linus Torvalds
  *
diff --git a/include/asm-m32r/dma.h b/include/asm-m32r/dma.h
index 7263b01..52f6a22 100644
--- a/include/asm-m32r/dma.h
+++ b/include/asm-m32r/dma.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_DMA_H
 #define _ASM_M32R_DMA_H
 
-/* $Id$ */
-
 #include <asm/io.h>
 
 /*
diff --git a/include/asm-m32r/errno.h b/include/asm-m32r/errno.h
index 7a98520..7771492 100644
--- a/include/asm-m32r/errno.h
+++ b/include/asm-m32r/errno.h
@@ -1,9 +1,6 @@
 #ifndef _ASM_M32R_ERRNO_H
 #define _ASM_M32R_ERRNO_H
 
-/* $Id$ */
-
 #include <asm-generic/errno.h>
 
 #endif /* _ASM_M32R_ERRNO_H */
-
diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
index c82ebe8..4672a49 100644
--- a/include/asm-m32r/ide.h
+++ b/include/asm-m32r/ide.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_IDE_H
 #define _ASM_M32R_IDE_H
 
-/* $Id$ */
-
 /*
  *  linux/include/asm-m32r/ide.h
  *
@@ -15,6 +13,7 @@
 
 #ifdef __KERNEL__
 
+#include <asm/m32r.h>
 
 #ifndef MAX_HWIFS
 # ifdef CONFIG_BLK_DEV_IDEPCI
@@ -24,9 +23,6 @@
 # endif
 #endif
 
-#include <asm/m32r.h>
-
-
 #define IDE_ARCH_OBSOLETE_DEFAULTS
 
 static __inline__ int ide_default_irq(unsigned long base)
diff --git a/include/asm-m32r/ioctls.h b/include/asm-m32r/ioctls.h
index b350829..d23cfc4 100644
--- a/include/asm-m32r/ioctls.h
+++ b/include/asm-m32r/ioctls.h
@@ -1,10 +1,6 @@
 #ifndef __ARCH_M32R_IOCTLS_H__
 #define __ARCH_M32R_IOCTLS_H__
 
-/* $Id$ */
-
-/* orig : i386 2.5.67 */
-
 #include <asm/ioctl.h>
 
 /* 0x54 is just a magic number to make these relatively unique ('T') */
@@ -85,4 +81,3 @@
 #define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
 
 #endif /* __ARCH_M32R_IOCTLS_H__ */
-
diff --git a/include/asm-m32r/ipcbuf.h b/include/asm-m32r/ipcbuf.h
index 7c77fb0..8d2d7c8 100644
--- a/include/asm-m32r/ipcbuf.h
+++ b/include/asm-m32r/ipcbuf.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_IPCBUF_H
 #define _ASM_M32R_IPCBUF_H
 
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
 /*
  * The ipc64_perm structure for m32r architecture.
  * Note extra padding because this structure is passed back and forth
diff --git a/include/asm-m32r/kmap_types.h b/include/asm-m32r/kmap_types.h
index 0524d89..fa94dc6 100644
--- a/include/asm-m32r/kmap_types.h
+++ b/include/asm-m32r/kmap_types.h
@@ -1,9 +1,6 @@
 #ifndef __M32R_KMAP_TYPES_H
 #define __M32R_KMAP_TYPES_H
 
-/* Dummy header just to define km_type. */
-
-
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
 #else
@@ -30,4 +27,3 @@
 #undef D
 
 #endif /* __M32R_KMAP_TYPES_H */
-
diff --git a/include/asm-m32r/m32104ut/m32104ut_pld.h b/include/asm-m32r/m32104ut/m32104ut_pld.h
index cbdbc58..2dc89d6 100644
--- a/include/asm-m32r/m32104ut/m32104ut_pld.h
+++ b/include/asm-m32r/m32104ut/m32104ut_pld.h
@@ -1,3 +1,6 @@
+#ifndef _M32104UT_M32104UT_PLD_H
+#define _M32104UT_M32104UT_PLD_H
+
 /*
  * include/asm-m32r/m32104ut/m32104ut_pld.h
  *
@@ -12,10 +15,6 @@
  * this archive for more details.
  */
 
-#ifndef _M32104UT_M32104UT_PLD_H
-#define _M32104UT_M32104UT_PLD_H
-
-
 #if defined(CONFIG_PLAT_M32104UT)
 #define PLD_PLAT_BASE		0x02c00000
 #else
@@ -35,7 +34,7 @@
 #define __reg8
 #define __reg16
 #define __reg32
-#endif	/* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
 
 /* CFC */
 #define	PLD_CFRSTCR		__reg16(PLD_BASE + 0x0000)
@@ -159,4 +158,4 @@
 #define PLD_SCTXB		__reg16(PLD_BASE + 0x3800c)
 #define PLD_SCRXB		__reg16(PLD_BASE + 0x3800e)
 
-#endif	/* _M32104UT_M32104UT_PLD_H */
+#endif /* _M32104UT_M32104UT_PLD_H */
diff --git a/include/asm-m32r/m32700ut/m32700ut_lan.h b/include/asm-m32r/m32700ut/m32700ut_lan.h
index f1e47ae..aae810a 100644
--- a/include/asm-m32r/m32700ut/m32700ut_lan.h
+++ b/include/asm-m32r/m32700ut/m32700ut_lan.h
@@ -1,3 +1,6 @@
+#ifndef _M32700UT_M32700UT_LAN_H
+#define _M32700UT_M32700UT_LAN_H
+
 /*
  * include/asm-m32r/m32700ut/m32700ut_lan.h
  *
@@ -8,14 +11,8 @@
  * 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.
- *
- * $Id$
  */
 
-#ifndef _M32700UT_M32700UT_LAN_H
-#define _M32700UT_M32700UT_LAN_H
-
-
 #ifndef __ASSEMBLY__
 /*
  * C functions use non-cache address.
@@ -23,7 +20,7 @@
 #define M32700UT_LAN_BASE	(0x10000000 /* + NONCACHE_OFFSET */)
 #else
 #define M32700UT_LAN_BASE	(0x10000000 + NONCACHE_OFFSET)
-#endif	/* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
 
 /* ICU
  *  ICUISTS:	status register
@@ -103,4 +100,4 @@
 #define PLDI2CSTS_BB		0x00000010
 #define PLDI2CSTS_NOACK		0x00000001	/* 0:ack, 1:noack */
 
-#endif	/* _M32700UT_M32700UT_LAN_H */
+#endif /* _M32700UT_M32700UT_LAN_H */
diff --git a/include/asm-m32r/m32700ut/m32700ut_lcd.h b/include/asm-m32r/m32700ut/m32700ut_lcd.h
index e41c4aa..4c24890 100644
--- a/include/asm-m32r/m32700ut/m32700ut_lcd.h
+++ b/include/asm-m32r/m32700ut/m32700ut_lcd.h
@@ -1,3 +1,6 @@
+#ifndef _M32700UT_M32700UT_LCD_H
+#define _M32700UT_M32700UT_LCD_H
+
 /*
  * include/asm-m32r/m32700ut/m32700ut_lcd.h
  *
@@ -8,14 +11,8 @@
  * 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.
- *
- * $Id$
  */
 
-#ifndef _M32700UT_M32700UT_LCD_H
-#define _M32700UT_M32700UT_LCD_H
-
-
 #ifndef __ASSEMBLY__
 /*
  * C functions use non-cache address.
@@ -23,7 +20,7 @@
 #define M32700UT_LCD_BASE	(0x10000000 /* + NONCACHE_OFFSET */)
 #else
 #define M32700UT_LCD_BASE	(0x10000000 + NONCACHE_OFFSET)
-#endif	/* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
 
 /*
  * ICU
@@ -55,4 +52,4 @@
 #define M32700UT_LCD_ICUCR19	__reg16(M32700UT_LCD_BASE + 0x300036)
 #define M32700UT_LCD_ICUCR21	__reg16(M32700UT_LCD_BASE + 0x30003a)
 
-#endif	/* _M32700UT_M32700UT_LCD_H */
+#endif /* _M32700UT_M32700UT_LCD_H */
diff --git a/include/asm-m32r/m32700ut/m32700ut_pld.h b/include/asm-m32r/m32700ut/m32700ut_pld.h
index a48c22c..d391212 100644
--- a/include/asm-m32r/m32700ut/m32700ut_pld.h
+++ b/include/asm-m32r/m32700ut/m32700ut_pld.h
@@ -1,3 +1,6 @@
+#ifndef _M32700UT_M32700UT_PLD_H
+#define _M32700UT_M32700UT_PLD_H
+
 /*
  * include/asm-m32r/m32700ut/m32700ut_pld.h
  *
@@ -8,14 +11,8 @@
  * 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.
- *
- * $Id$
  */
 
-#ifndef _M32700UT_M32700UT_PLD_H
-#define _M32700UT_M32700UT_PLD_H
-
-
 #if defined(CONFIG_PLAT_M32700UT_Alpha)
 #define PLD_PLAT_BASE		0x08c00000
 #elif defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV)
@@ -37,7 +34,7 @@
 #define __reg8
 #define __reg16
 #define __reg32
-#endif	/* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
 
 /* CFC */
 #define	PLD_CFRSTCR		__reg16(PLD_BASE + 0x0000)
@@ -261,4 +258,4 @@
 #define PLD_SCTXB		__reg16(PLD_BASE + 0x3800c)
 #define PLD_SCRXB		__reg16(PLD_BASE + 0x3800e)
 
-#endif	/* _M32700UT_M32700UT_PLD.H */
+#endif /* _M32700UT_M32700UT_PLD.H */
diff --git a/include/asm-m32r/mappi2/mappi2_pld.h b/include/asm-m32r/mappi2/mappi2_pld.h
index 56a2b12..2624c9d 100644
--- a/include/asm-m32r/mappi2/mappi2_pld.h
+++ b/include/asm-m32r/mappi2/mappi2_pld.h
@@ -1,18 +1,17 @@
+#ifndef _MAPPI2_PLD_H
+#define _MAPPI2_PLD_H
+
 /*
  * include/asm-m32r/mappi2/mappi2_pld.h
  *
  * Definitions for Extended IO Logic on MAPPI2 board.
- *  based on m32700ut_pld.h by
+ *  based on m32700ut_pld.h
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file "COPYING" in the main directory of
  * this archive for more details.
- *
  */
 
-#ifndef _MAPPI2_PLD_H
-#define _MAPPI2_PLD_H
-
 #ifndef __ASSEMBLY__
 /* FIXME:
  * Some C functions use non-cache address, so can't define non-cache address.
@@ -26,7 +25,7 @@
 #define __reg8
 #define __reg16
 #define __reg32
-#endif	/* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
 
 /* CFC */
 #define	PLD_CFRSTCR		__reg16(PLD_BASE + 0x0000)
@@ -148,4 +147,4 @@
 
 #endif
 
-#endif	/* _MAPPI2_PLD.H */
+#endif /* _MAPPI2_PLD.H */
diff --git a/include/asm-m32r/mappi3/mappi3_pld.h b/include/asm-m32r/mappi3/mappi3_pld.h
index 92f10de..451c40e 100644
--- a/include/asm-m32r/mappi3/mappi3_pld.h
+++ b/include/asm-m32r/mappi3/mappi3_pld.h
@@ -1,3 +1,6 @@
+#ifndef _MAPPI3_PLD_H
+#define _MAPPI3_PLD_H
+
 /*
  * include/asm-m32r/mappi3/mappi3_pld.h
  *
@@ -7,12 +10,8 @@
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file "COPYING" in the main directory of
  * this archive for more details.
- *
  */
 
-#ifndef _MAPPI3_PLD_H
-#define _MAPPI3_PLD_H
-
 #ifndef __ASSEMBLY__
 /* FIXME:
  * Some C functions use non-cache address, so can't define non-cache address.
@@ -26,7 +25,7 @@
 #define __reg8
 #define __reg16
 #define __reg32
-#endif	/* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
 
 /* CFC */
 #define	PLD_CFRSTCR		__reg16(PLD_BASE + 0x0000)
@@ -140,4 +139,4 @@
 /* Reset Control */
 #define PLD_REBOOT		__reg16(PLD_BASE + 0x38000)
 
-#endif	/* _MAPPI3_PLD.H */
+#endif /* _MAPPI3_PLD.H */
diff --git a/include/asm-m32r/mc146818rtc.h b/include/asm-m32r/mc146818rtc.h
index 755601d..aa1b7bf 100644
--- a/include/asm-m32r/mc146818rtc.h
+++ b/include/asm-m32r/mc146818rtc.h
@@ -7,7 +7,6 @@
 #include <asm/io.h>
 
 #ifndef RTC_PORT
-// #define RTC_PORT(x)	(0x70 + (x))
 #define RTC_PORT(x)	((x))
 #define RTC_ALWAYS_BCD	1	/* RTC operates in binary mode */
 #endif
@@ -26,7 +25,5 @@
 })
 
 #define RTC_IRQ 8
-#if 0
-#endif
 
 #endif /* _ASM_MC146818RTC_H */
diff --git a/include/asm-m32r/mman.h b/include/asm-m32r/mman.h
index 695a860..516a897 100644
--- a/include/asm-m32r/mman.h
+++ b/include/asm-m32r/mman.h
@@ -3,8 +3,6 @@
 
 #include <asm-generic/mman.h>
 
-/* orig : i386 2.6.0-test6 */
-
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
 #define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
diff --git a/include/asm-m32r/mmu.h b/include/asm-m32r/mmu.h
index cf3f6d7..d9bd724 100644
--- a/include/asm-m32r/mmu.h
+++ b/include/asm-m32r/mmu.h
@@ -1,13 +1,14 @@
 #ifndef _ASM_M32R_MMU_H
 #define _ASM_M32R_MMU_H
 
-
 #if !defined(CONFIG_MMU)
+
 typedef struct {
 	struct vm_list_struct	*vmlist;
 	unsigned long		end_brk;
 } mm_context_t;
-#else
+
+#else /* CONFIG_MMU */
 
 /* Default "unsigned long" context */
 #ifndef CONFIG_SMP
@@ -16,5 +17,6 @@
 typedef unsigned long mm_context_t[NR_CPUS];
 #endif
 
-#endif  /* CONFIG_MMU */
-#endif  /* _ASM_M32R_MMU_H */
+#endif /* CONFIG_MMU */
+
+#endif /* _ASM_M32R_MMU_H */
diff --git a/include/asm-m32r/mmu_context.h b/include/asm-m32r/mmu_context.h
index 542302e..1f40d4a 100644
--- a/include/asm-m32r/mmu_context.h
+++ b/include/asm-m32r/mmu_context.h
@@ -1,9 +1,7 @@
 #ifndef _ASM_M32R_MMU_CONTEXT_H
 #define _ASM_M32R_MMU_CONTEXT_H
-
 #ifdef __KERNEL__
 
-
 #include <asm/m32r.h>
 
 #define MMU_CONTEXT_ASID_MASK      (0x000000FF)
@@ -11,7 +9,6 @@
 #define MMU_CONTEXT_FIRST_VERSION  (0x00000100)
 #define NO_CONTEXT                 (0x00000000)
 
-
 #ifndef __ASSEMBLY__
 
 #include <asm/atomic.h>
@@ -147,7 +144,7 @@
 #define activate_mm(prev, next)	\
 	switch_mm((prev), (next), NULL)
 
-#else
+#else /* not CONFIG_MMU */
 #define get_mmu_context(mm)             do { } while (0)
 #define init_new_context(tsk,mm)        (0)
 #define destroy_context(mm)             do { } while (0)
@@ -158,11 +155,9 @@
 #define deactivate_mm(mm,tsk)           do { } while (0)
 #define activate_mm(prev,next)          do { } while (0)
 #define enter_lazy_tlb(mm,tsk)          do { } while (0)
-#endif /* CONFIG_MMU */
-
+#endif /* not CONFIG_MMU */
 
 #endif /* not __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
-
 #endif /* _ASM_M32R_MMU_CONTEXT_H */
diff --git a/include/asm-m32r/module.h b/include/asm-m32r/module.h
index 3f2541c..eb73ee0 100644
--- a/include/asm-m32r/module.h
+++ b/include/asm-m32r/module.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_MODULE_H
 #define _ASM_M32R_MODULE_H
 
-/* $Id$ */
-
 struct mod_arch_specific { };
 
 #define Elf_Shdr	Elf32_Shdr
@@ -10,4 +8,3 @@
 #define Elf_Ehdr	Elf32_Ehdr
 
 #endif /* _ASM_M32R_MODULE_H */
-
diff --git a/include/asm-m32r/msgbuf.h b/include/asm-m32r/msgbuf.h
index 852ff52..0d5a877 100644
--- a/include/asm-m32r/msgbuf.h
+++ b/include/asm-m32r/msgbuf.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_MSGBUF_H
 #define _ASM_M32R_MSGBUF_H
 
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
 /*
  * The msqid64_ds structure for m32r architecture.
  * Note extra padding because this structure is passed back and forth
diff --git a/include/asm-m32r/namei.h b/include/asm-m32r/namei.h
index 7172d3d..210f805 100644
--- a/include/asm-m32r/namei.h
+++ b/include/asm-m32r/namei.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_NAMEI_H
 #define _ASM_M32R_NAMEI_H
 
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
 /*
  * linux/include/asm-m32r/namei.h
  *
diff --git a/include/asm-m32r/opsput/opsput_lan.h b/include/asm-m32r/opsput/opsput_lan.h
index f53e101..a5f18dd 100644
--- a/include/asm-m32r/opsput/opsput_lan.h
+++ b/include/asm-m32r/opsput/opsput_lan.h
@@ -1,3 +1,6 @@
+#ifndef _OPSPUT_OPSPUT_LAN_H
+#define _OPSPUT_OPSPUT_LAN_H
+
 /*
  * include/asm-m32r/opsput/opsput_lan.h
  *
@@ -8,14 +11,8 @@
  * 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.
- *
- * $Id: opsput_lan.h,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
  */
 
-#ifndef _OPSPUT_OPSPUT_LAN_H
-#define _OPSPUT_OPSPUT_LAN_H
-
-
 #ifndef __ASSEMBLY__
 /*
  * C functions use non-cache address.
@@ -23,7 +20,7 @@
 #define OPSPUT_LAN_BASE	(0x10000000 /* + NONCACHE_OFFSET */)
 #else
 #define OPSPUT_LAN_BASE	(0x10000000 + NONCACHE_OFFSET)
-#endif	/* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
 
 /* ICU
  *  ICUISTS:	status register
@@ -52,4 +49,4 @@
 #define OPSPUT_LAN_ICUCR1	__reg16(OPSPUT_LAN_BASE + 0xc0010)
 #define OPSPUT_LAN_ICUCR3	__reg16(OPSPUT_LAN_BASE + 0xc0014)
 
-#endif	/* _OPSPUT_OPSPUT_LAN_H */
+#endif /* _OPSPUT_OPSPUT_LAN_H */
diff --git a/include/asm-m32r/opsput/opsput_lcd.h b/include/asm-m32r/opsput/opsput_lcd.h
index 99f296e..369c9f0 100644
--- a/include/asm-m32r/opsput/opsput_lcd.h
+++ b/include/asm-m32r/opsput/opsput_lcd.h
@@ -1,3 +1,6 @@
+#ifndef _OPSPUT_OPSPUT_LCD_H
+#define _OPSPUT_OPSPUT_LCD_H
+
 /*
  * include/asm-m32r/opsput/opsput_lcd.h
  *
@@ -8,14 +11,8 @@
  * 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.
- *
- * $Id: opsput_lcd.h,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
  */
 
-#ifndef _OPSPUT_OPSPUT_LCD_H
-#define _OPSPUT_OPSPUT_LCD_H
-
-
 #ifndef __ASSEMBLY__
 /*
  * C functions use non-cache address.
@@ -23,7 +20,7 @@
 #define OPSPUT_LCD_BASE	(0x10000000 /* + NONCACHE_OFFSET */)
 #else
 #define OPSPUT_LCD_BASE	(0x10000000 + NONCACHE_OFFSET)
-#endif	/* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
 
 /*
  * ICU
@@ -55,4 +52,4 @@
 #define OPSPUT_LCD_ICUCR19	__reg16(OPSPUT_LCD_BASE + 0x300036)
 #define OPSPUT_LCD_ICUCR21	__reg16(OPSPUT_LCD_BASE + 0x30003a)
 
-#endif	/* _OPSPUT_OPSPUT_LCD_H */
+#endif /* _OPSPUT_OPSPUT_LCD_H */
diff --git a/include/asm-m32r/opsput/opsput_pld.h b/include/asm-m32r/opsput/opsput_pld.h
index a8d6452..3f11ea1 100644
--- a/include/asm-m32r/opsput/opsput_pld.h
+++ b/include/asm-m32r/opsput/opsput_pld.h
@@ -1,3 +1,6 @@
+#ifndef _OPSPUT_OPSPUT_PLD_H
+#define _OPSPUT_OPSPUT_PLD_H
+
 /*
  * include/asm-m32r/opsput/opsput_pld.h
  *
@@ -8,14 +11,8 @@
  * 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.
- *
- * $Id: opsput_pld.h,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
  */
 
-#ifndef _OPSPUT_OPSPUT_PLD_H
-#define _OPSPUT_OPSPUT_PLD_H
-
-
 #define PLD_PLAT_BASE		0x1cc00000
 
 #ifndef __ASSEMBLY__
@@ -31,7 +28,7 @@
 #define __reg8
 #define __reg16
 #define __reg32
-#endif	/* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
 
 /* CFC */
 #define	PLD_CFRSTCR		__reg16(PLD_BASE + 0x0000)
@@ -255,4 +252,4 @@
 #define PLD_SCTXB		__reg16(PLD_BASE + 0x3800c)
 #define PLD_SCRXB		__reg16(PLD_BASE + 0x3800e)
 
-#endif	/* _OPSPUT_OPSPUT_PLD.H */
+#endif /* _OPSPUT_OPSPUT_PLD.H */
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
index 404a4c2..6f6ecf7 100644
--- a/include/asm-m32r/page.h
+++ b/include/asm-m32r/page.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_M32R_PAGE_H
 #define _ASM_M32R_PAGE_H
 
-
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
@@ -57,9 +56,6 @@
  * and CONFIG_HIGHMEM64G options in the kernel configuration.
  */
 
-
-/* This handles the memory map.. */
-
 #define __MEMORY_START  CONFIG_MEMORY_START
 #define __MEMORY_SIZE   CONFIG_MEMORY_SIZE
 
@@ -92,4 +88,3 @@
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_M32R_PAGE_H */
-
diff --git a/include/asm-m32r/param.h b/include/asm-m32r/param.h
index 750b938..3e14026 100644
--- a/include/asm-m32r/param.h
+++ b/include/asm-m32r/param.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_PARAM_H
 #define _ASM_M32R_PARAM_H
 
-/* $Id$ */
-
-/* orig : i386 2.5.67 */
-
 #ifdef __KERNEL__
 # define HZ		100		/* Internal kernel timer frequency */
 # define USER_HZ	100		/* .. some user interfaces are in "ticks" */
diff --git a/include/asm-m32r/pci.h b/include/asm-m32r/pci.h
index 00d7b6f..fe785d1 100644
--- a/include/asm-m32r/pci.h
+++ b/include/asm-m32r/pci.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_PCI_H
 #define _ASM_M32R_PCI_H
 
-/* $Id$ */
-
 #include <asm-generic/pci.h>
 
 #define PCI_DMA_BUS_IS_PHYS	(1)
diff --git a/include/asm-m32r/pgalloc.h b/include/asm-m32r/pgalloc.h
index e09a86c..943ba63 100644
--- a/include/asm-m32r/pgalloc.h
+++ b/include/asm-m32r/pgalloc.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_PGALLOC_H
 #define _ASM_M32R_PGALLOC_H
 
-/* $Id$ */
-
 #include <linux/mm.h>
 
 #include <asm/io.h>
@@ -74,4 +72,3 @@
 #define check_pgt_cache()	do { } while (0)
 
 #endif /* _ASM_M32R_PGALLOC_H */
-
diff --git a/include/asm-m32r/pgtable-2level.h b/include/asm-m32r/pgtable-2level.h
index 8415276..7509257 100644
--- a/include/asm-m32r/pgtable-2level.h
+++ b/include/asm-m32r/pgtable-2level.h
@@ -1,9 +1,7 @@
 #ifndef _ASM_M32R_PGTABLE_2LEVEL_H
 #define _ASM_M32R_PGTABLE_2LEVEL_H
-
 #ifdef __KERNEL__
 
-
 /*
  * traditional M32R two-level paging structure:
  */
@@ -77,5 +75,4 @@
 #define pgoff_to_pte(off)	((pte_t) { (((off) & 0xef) << 2) | (((off) >> 7) << 10) | _PAGE_FILE })
 
 #endif /* __KERNEL__ */
-
 #endif /* _ASM_M32R_PGTABLE_2LEVEL_H */
diff --git a/include/asm-m32r/posix_types.h b/include/asm-m32r/posix_types.h
index 47e7e85..1caac65 100644
--- a/include/asm-m32r/posix_types.h
+++ b/include/asm-m32r/posix_types.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_POSIX_TYPES_H
 #define _ASM_M32R_POSIX_TYPES_H
 
-/* $Id$ */
-
-/* orig : i386, sh 2.4.18 */
-
 /*
  * This file is generally used by user-level software, so you need to
  * be a little careful about namespace pollution etc.  Also, we cannot
diff --git a/include/asm-m32r/rtc.h b/include/asm-m32r/rtc.h
index 6b2b837..0340633 100644
--- a/include/asm-m32r/rtc.h
+++ b/include/asm-m32r/rtc.h
@@ -1,10 +1,6 @@
-/* $Id: rtc.h,v 1.1.1.1 2004/03/25 04:29:22 hitoshiy Exp $ */
-
 #ifndef __RTC_H__
 #define __RTC_H__
 
-
-
    /* Dallas DS1302 clock/calendar register numbers. */
 #  define RTC_SECONDS      0
 #  define RTC_MINUTES      1
diff --git a/include/asm-m32r/scatterlist.h b/include/asm-m32r/scatterlist.h
index 09a10e4..c2de96c 100644
--- a/include/asm-m32r/scatterlist.h
+++ b/include/asm-m32r/scatterlist.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_SCATTERLIST_H
 #define _ASM_M32R_SCATTERLIST_H
 
-/* $Id$ */
-
 struct scatterlist {
     char *  address;    /* Location data is to be transferred to, NULL for
                          * highmem page */
diff --git a/include/asm-m32r/sections.h b/include/asm-m32r/sections.h
index 6b969e5..5e5d21c 100644
--- a/include/asm-m32r/sections.h
+++ b/include/asm-m32r/sections.h
@@ -5,4 +5,3 @@
 #include <asm-generic/sections.h>
 
 #endif	/* _M32R_SECTIONS_H */
-
diff --git a/include/asm-m32r/segment.h b/include/asm-m32r/segment.h
index e45db68..42b11ae 100644
--- a/include/asm-m32r/segment.h
+++ b/include/asm-m32r/segment.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_SEGMENT_H
 #define _ASM_M32R_SEGMENT_H
 
-/* $Id$ */
-
-/* orig : i386 (2.4.18) */
-
 #define __KERNEL_CS	0x10
 #define __KERNEL_DS	0x18
 
diff --git a/include/asm-m32r/sembuf.h b/include/asm-m32r/sembuf.h
index e69018e..c9873d6 100644
--- a/include/asm-m32r/sembuf.h
+++ b/include/asm-m32r/sembuf.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_SEMBUF_H
 #define _ASM_M32R_SEMBUF_H
 
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
 /*
  * The semid64_ds structure for m32r architecture.
  * Note extra padding because this structure is passed back and forth
diff --git a/include/asm-m32r/setup.h b/include/asm-m32r/setup.h
index 6a0b322..c637ab9 100644
--- a/include/asm-m32r/setup.h
+++ b/include/asm-m32r/setup.h
@@ -1,3 +1,6 @@
+#ifndef _ASM_M32R_SETUP_H
+#define _ASM_M32R_SETUP_H
+
 /*
  * This is set up by the setup-routine at boot-time
  */
@@ -32,3 +35,4 @@
 
 #endif  /*  __KERNEL__  */
 
+#endif /* _ASM_M32R_SETUP_H */
diff --git a/include/asm-m32r/shmbuf.h b/include/asm-m32r/shmbuf.h
index b84e897..b0cdf0a 100644
--- a/include/asm-m32r/shmbuf.h
+++ b/include/asm-m32r/shmbuf.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_SHMBUF_H
 #define _ASM_M32R_SHMBUF_H
 
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
 /*
  * The shmid64_ds structure for M32R architecture.
  * Note extra padding because this structure is passed back and forth
diff --git a/include/asm-m32r/shmparam.h b/include/asm-m32r/shmparam.h
index db0019b..35986d8 100644
--- a/include/asm-m32r/shmparam.h
+++ b/include/asm-m32r/shmparam.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_SHMPARAM_H
 #define _ASM_M32R_SHMPARAM_H
 
-/* $Id$ */
-
 #define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
 
 #endif /* _ASM_M32R_SHMPARAM_H */
diff --git a/include/asm-m32r/sigcontext.h b/include/asm-m32r/sigcontext.h
index 62537dc..da4a9c3 100644
--- a/include/asm-m32r/sigcontext.h
+++ b/include/asm-m32r/sigcontext.h
@@ -1,9 +1,6 @@
 #ifndef _ASM_M32R_SIGCONTEXT_H
 #define _ASM_M32R_SIGCONTEXT_H
 
-/* $Id$ */
-
-
 struct sigcontext {
 	/* CPU registers */
 	/* Saved main processor registers. */
diff --git a/include/asm-m32r/siginfo.h b/include/asm-m32r/siginfo.h
index 482202f..7d9cd9e 100644
--- a/include/asm-m32r/siginfo.h
+++ b/include/asm-m32r/siginfo.h
@@ -1,8 +1,6 @@
 #ifndef _M32R_SIGINFO_H
 #define _M32R_SIGINFO_H
 
-/* $Id$ */
-
 #include <asm-generic/siginfo.h>
 
 #endif /* _M32R_SIGINFO_H */
diff --git a/include/asm-m32r/signal.h b/include/asm-m32r/signal.h
index 65423be..9372586 100644
--- a/include/asm-m32r/signal.h
+++ b/include/asm-m32r/signal.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_SIGNAL_H
 #define _ASM_M32R_SIGNAL_H
 
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
 #include <linux/types.h>
 #include <linux/time.h>
 #include <linux/compiler.h>
diff --git a/include/asm-m32r/smp.h b/include/asm-m32r/smp.h
index 650d255..abd937a 100644
--- a/include/asm-m32r/smp.h
+++ b/include/asm-m32r/smp.h
@@ -1,9 +1,6 @@
 #ifndef _ASM_M32R_SMP_H
 #define _ASM_M32R_SMP_H
 
-/* $Id$ */
-
-
 #ifdef CONFIG_SMP
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-m32r/sockios.h b/include/asm-m32r/sockios.h
index 147a118..f89962e 100644
--- a/include/asm-m32r/sockios.h
+++ b/include/asm-m32r/sockios.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_SOCKIOS_H
 #define _ASM_M32R_SOCKIOS_H
 
-/* $Id$ */
-
 /* Socket-level I/O control calls. */
 #define FIOSETOWN 	0x8901
 #define SIOCSPGRP	0x8902
diff --git a/include/asm-m32r/spinlock_types.h b/include/asm-m32r/spinlock_types.h
index 7e9941c..83f5210 100644
--- a/include/asm-m32r/spinlock_types.h
+++ b/include/asm-m32r/spinlock_types.h
@@ -20,4 +20,4 @@
 
 #define __RAW_RW_LOCK_UNLOCKED		{ RW_LOCK_BIAS }
 
-#endif
+#endif /* _ASM_M32R_SPINLOCK_TYPES_H */
diff --git a/include/asm-m32r/stat.h b/include/asm-m32r/stat.h
index 05748fe..da4518f 100644
--- a/include/asm-m32r/stat.h
+++ b/include/asm-m32r/stat.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_STAT_H
 #define _ASM_M32R_STAT_H
 
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
 #include <asm/byteorder.h>
 
 struct __old_kernel_stat {
diff --git a/include/asm-m32r/string.h b/include/asm-m32r/string.h
index cb54bcc..e61e2b0 100644
--- a/include/asm-m32r/string.h
+++ b/include/asm-m32r/string.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_STRING_H
 #define _ASM_M32R_STRING_H
 
-/* $Id$ */
-
 #define  __HAVE_ARCH_STRLEN
 extern size_t strlen(const char * s);
 
diff --git a/include/asm-m32r/syscall.h b/include/asm-m32r/syscall.h
index d8d4b2c..25f316f 100644
--- a/include/asm-m32r/syscall.h
+++ b/include/asm-m32r/syscall.h
@@ -1,11 +1,8 @@
 #ifndef _ASM_M32R_SYSCALL_H
 #define _ASM_M32R_SYSCALL_H
 
-/* $Id$ */
-
 /* Definitions for the system call vector.  */
 #define SYSCALL_VECTOR          "2"
 #define SYSCALL_VECTOR_ADDRESS  "0xa0"
 
 #endif /* _ASM_M32R_SYSCALL_H */
-
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index 4ce0619..99ee098 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -339,4 +339,4 @@
 
 #define arch_align_stack(x) (x)
 
-#endif  /* _ASM_M32R_SYSTEM_H */
+#endif /* _ASM_M32R_SYSTEM_H */
diff --git a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h
index faf2bd0..e402641df 100644
--- a/include/asm-m32r/termbits.h
+++ b/include/asm-m32r/termbits.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_TERMBITS_H
 #define _ASM_M32R_TERMBITS_H
 
-/* $Id$ */
-
 #include <linux/posix_types.h>
 
 typedef unsigned char	cc_t;
@@ -184,4 +182,4 @@
 #define	TCSADRAIN	1
 #define	TCSAFLUSH	2
 
-#endif  /* _ASM_M32R_TERMBITS_H */
+#endif /* _ASM_M32R_TERMBITS_H */
diff --git a/include/asm-m32r/termios.h b/include/asm-m32r/termios.h
index fc99d2e..4943dd8 100644
--- a/include/asm-m32r/termios.h
+++ b/include/asm-m32r/termios.h
@@ -1,8 +1,6 @@
 #ifndef _M32R_TERMIOS_H
 #define _M32R_TERMIOS_H
 
-/* orig : i386 2.6.0-test5 */
-
 #include <asm/termbits.h>
 #include <asm/ioctls.h>
 
@@ -41,24 +39,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 #include <linux/module.h>
 
diff --git a/include/asm-m32r/timex.h b/include/asm-m32r/timex.h
index 019441c..bb9fe4f 100644
--- a/include/asm-m32r/timex.h
+++ b/include/asm-m32r/timex.h
@@ -1,15 +1,12 @@
 #ifndef _ASM_M32R_TIMEX_H
 #define _ASM_M32R_TIMEX_H
 
-/* $Id$ */
-
 /*
  * linux/include/asm-m32r/timex.h
  *
  * m32r architecture timex specifications
  */
 
-
 #define CLOCK_TICK_RATE	(CONFIG_BUS_CLOCK / CONFIG_TIMER_DIVIDE)
 #define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
 
diff --git a/include/asm-m32r/tlbflush.h b/include/asm-m32r/tlbflush.h
index ae44949..3d37ac0 100644
--- a/include/asm-m32r/tlbflush.h
+++ b/include/asm-m32r/tlbflush.h
@@ -98,4 +98,3 @@
 extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
 
 #endif	/* _ASM_M32R_TLBFLUSH_H */
-
diff --git a/include/asm-m32r/types.h b/include/asm-m32r/types.h
index fcf24c6..27d3eb5 100644
--- a/include/asm-m32r/types.h
+++ b/include/asm-m32r/types.h
@@ -3,10 +3,6 @@
 
 #ifndef __ASSEMBLY__
 
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
 typedef unsigned short umode_t;
 
 /*
@@ -59,4 +55,4 @@
 
 #endif /* __KERNEL__ */
 
-#endif  /* _ASM_M32R_TYPES_H */
+#endif /* _ASM_M32R_TYPES_H */
diff --git a/include/asm-m32r/uaccess.h b/include/asm-m32r/uaccess.h
index 26e978c..bd8c837 100644
--- a/include/asm-m32r/uaccess.h
+++ b/include/asm-m32r/uaccess.h
@@ -68,7 +68,7 @@
  * This needs 33-bit arithmetic. We have a carry...
  */
 #define __range_ok(addr,size) ({					\
-	unsigned long flag, sum; 					\
+	unsigned long flag, roksum; 					\
 	__chk_user_ptr(addr);						\
 	asm ( 								\
 		"	cmpu	%1, %1    ; clear cbit\n"		\
@@ -76,7 +76,7 @@
 		"	subx	%0, %0\n"				\
 		"	cmpu	%4, %1\n"				\
 		"	subx	%0, %5\n"				\
-		: "=&r" (flag), "=r" (sum)				\
+		: "=&r" (flag), "=r" (roksum)				\
 		: "1" (addr), "r" ((int)(size)), 			\
 		  "r" (current_thread_info()->addr_limit.seg), "r" (0)	\
 		: "cbit" );						\
diff --git a/include/asm-m32r/ucontext.h b/include/asm-m32r/ucontext.h
index 2de709a..0932474 100644
--- a/include/asm-m32r/ucontext.h
+++ b/include/asm-m32r/ucontext.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_UCONTEXT_H
 #define _ASM_M32R_UCONTEXT_H
 
-/* orig : i386 2.4.18 */
-
 struct ucontext {
 	unsigned long	  uc_flags;
 	struct ucontext  *uc_link;
diff --git a/include/asm-m32r/unaligned.h b/include/asm-m32r/unaligned.h
index 3aef9ac..fccc180 100644
--- a/include/asm-m32r/unaligned.h
+++ b/include/asm-m32r/unaligned.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_M32R_UNALIGNED_H
 #define _ASM_M32R_UNALIGNED_H
 
-/* $Id$ */
-
-/* orig : generic 2.4.18 */
-
 /*
  * For the benefit of those who are trying to port Linux to another
  * architecture, here are some C-language equivalents.
@@ -12,7 +8,6 @@
 
 #include <asm/string.h>
 
-
 #define get_unaligned(ptr) \
   ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
 
@@ -21,5 +16,4 @@
      memmove((ptr), &__tmp, sizeof(*(ptr)));		\
      (void)0; })
 
-
-#endif  /* _ASM_M32R_UNALIGNED_H */
+#endif /* _ASM_M32R_UNALIGNED_H */
diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
index 5b66bd3..cbbd537 100644
--- a/include/asm-m32r/unistd.h
+++ b/include/asm-m32r/unistd.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_UNISTD_H
 #define _ASM_M32R_UNISTD_H
 
-/* $Id$ */
-
 /*
  * This file contains the system call numbers.
  */
diff --git a/include/asm-m32r/user.h b/include/asm-m32r/user.h
index 1ad4ded..035258d 100644
--- a/include/asm-m32r/user.h
+++ b/include/asm-m32r/user.h
@@ -1,12 +1,6 @@
 #ifndef _ASM_M32R_USER_H
 #define _ASM_M32R_USER_H
 
-/* $Id$ */
-
-/* orig : sh 2.4.18
- * mod  : remove fpu registers
- */
-
 #include <linux/types.h>
 #include <asm/ptrace.h>
 #include <asm/page.h>
diff --git a/include/asm-m32r/vga.h b/include/asm-m32r/vga.h
index 5331634..a1b6306 100644
--- a/include/asm-m32r/vga.h
+++ b/include/asm-m32r/vga.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_VGA_H
 #define _ASM_M32R_VGA_H
 
-/* $Id$ */
-
 /*
  *	Access to VGA videoram
  *
@@ -19,4 +17,4 @@
 #define vga_readb(x) (*(x))
 #define vga_writeb(x,y) (*(y) = (x))
 
-#endif  /* _ASM_M32R_VGA_H */
+#endif /* _ASM_M32R_VGA_H */
diff --git a/include/asm-m32r/xor.h b/include/asm-m32r/xor.h
index fd960dc..6d52525 100644
--- a/include/asm-m32r/xor.h
+++ b/include/asm-m32r/xor.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_M32R_XOR_H
 #define _ASM_M32R_XOR_H
 
-/* $Id$ */
-
 #include <asm-generic/xor.h>
 
 #endif  /* _ASM_M32R_XOR_H */
diff --git a/include/asm-m68k/math-emu.h b/include/asm-m68k/math-emu.h
index 7ac6259..ddfab96 100644
--- a/include/asm-m68k/math-emu.h
+++ b/include/asm-m68k/math-emu.h
@@ -226,6 +226,21 @@
 	.previous
 .endm
 
+/* work around binutils idiocy */
+old_gas=-1
+.irp    gas_ident.x .x
+old_gas=old_gas+1
+.endr
+.if !old_gas
+.irp	m b,w,l
+.macro	getuser.\m src,dest,label,addr
+	getuser .\m,\src,\dest,\label,\addr
+.endm
+.macro	putuser.\m src,dest,label,addr
+	putuser .\m,\src,\dest,\label,\addr
+.endm
+.endr
+.endif
 
 .macro	movestack	nr,arg1,arg2,arg3,arg4,arg5
 	.if	\nr
diff --git a/include/asm-m68k/termios.h b/include/asm-m68k/termios.h
index 857f0c9..00edabd 100644
--- a/include/asm-m68k/termios.h
+++ b/include/asm-m68k/termios.h
@@ -49,24 +49,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*
diff --git a/include/asm-m68k/user.h b/include/asm-m68k/user.h
index d7c0b10..8c56cca 100644
--- a/include/asm-m68k/user.h
+++ b/include/asm-m68k/user.h
@@ -1,8 +1,6 @@
 #ifndef _M68K_USER_H
 #define _M68K_USER_H
 
-#include <asm/page.h>
-
 /* Core file format: The core file is written in such a way that gdb
    can understand it and provide useful information to the user (under
    linux we use the 'trad-core' bfd).  There are quite a number of
diff --git a/include/asm-m68knommu/bitops.h b/include/asm-m68knommu/bitops.h
index d7fa7d9..7d6075d 100644
--- a/include/asm-m68knommu/bitops.h
+++ b/include/asm-m68knommu/bitops.h
@@ -7,7 +7,6 @@
 
 #include <linux/compiler.h>
 #include <asm/byteorder.h>	/* swab32 */
-#include <asm/system.h>		/* save_flags */
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-mips/abi.h b/include/asm-mips/abi.h
index 1ce0518..1dd74fb 100644
--- a/include/asm-mips/abi.h
+++ b/include/asm-mips/abi.h
@@ -13,13 +13,13 @@
 #include <asm/siginfo.h>
 
 struct mips_abi {
-	void (* const do_signal)(struct pt_regs *regs);
 	int (* const setup_frame)(struct k_sigaction * ka,
 	                          struct pt_regs *regs, int signr,
 	                          sigset_t *set);
 	int (* const setup_rt_frame)(struct k_sigaction * ka,
 	                       struct pt_regs *regs, int signr,
 	                       sigset_t *set, siginfo_t *info);
+	const unsigned long	restart;
 };
 
 #endif /* _ASM_ABI_H */
diff --git a/include/asm-mips/apm.h b/include/asm-mips/apm.h
deleted file mode 100644
index 4b99ffc..0000000
--- a/include/asm-mips/apm.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- linux-c -*-
- *
- * (C) 2003 zecke@handhelds.org
- *
- * GPL version 2
- *
- * based on arch/arm/kernel/apm.c
- * factor out the information needed by architectures to provide
- * apm status
- *
- *
- */
-#ifndef MIPS_ASM_SA1100_APM_H
-#define MIPS_ASM_SA1100_APM_H
-
-#include <linux/apm_bios.h>
-
-/*
- * This structure gets filled in by the machine specific 'get_power_status'
- * implementation.  Any fields which are not set default to a safe value.
- */
-struct apm_power_info {
-	unsigned char	ac_line_status;
-#define APM_AC_OFFLINE			0
-#define APM_AC_ONLINE			1
-#define APM_AC_BACKUP			2
-#define APM_AC_UNKNOWN			0xff
-
-	unsigned char	battery_status;
-#define APM_BATTERY_STATUS_HIGH		0
-#define APM_BATTERY_STATUS_LOW		1
-#define APM_BATTERY_STATUS_CRITICAL	2
-#define APM_BATTERY_STATUS_CHARGING	3
-#define APM_BATTERY_STATUS_NOT_PRESENT	4
-#define APM_BATTERY_STATUS_UNKNOWN	0xff
-
-	unsigned char	battery_flag;
-#define APM_BATTERY_FLAG_HIGH		(1 << 0)
-#define APM_BATTERY_FLAG_LOW		(1 << 1)
-#define APM_BATTERY_FLAG_CRITICAL	(1 << 2)
-#define APM_BATTERY_FLAG_CHARGING	(1 << 3)
-#define APM_BATTERY_FLAG_NOT_PRESENT	(1 << 7)
-#define APM_BATTERY_FLAG_UNKNOWN	0xff
-
-	int		battery_life;
-	int		time;
-	int		units;
-#define APM_UNITS_MINS			0
-#define APM_UNITS_SECS			1
-#define APM_UNITS_UNKNOWN		-1
-
-};
-
-/*
- * This allows machines to provide their own "apm get power status" function.
- */
-extern void (*apm_get_power_status)(struct apm_power_info *);
-
-/*
- * Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND)
- */
-void apm_queue_event(apm_event_t event);
-
-#endif
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h
index c1a2409..8578869 100644
--- a/include/asm-mips/atomic.h
+++ b/include/asm-mips/atomic.h
@@ -69,7 +69,10 @@
 		"1:	ll	%0, %1		# atomic_add		\n"
 		"	addu	%0, %2					\n"
 		"	sc	%0, %1					\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
@@ -111,7 +114,10 @@
 		"1:	ll	%0, %1		# atomic_sub		\n"
 		"	subu	%0, %2					\n"
 		"	sc	%0, %1					\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
@@ -155,8 +161,11 @@
 		"1:	ll	%1, %2		# atomic_add_return	\n"
 		"	addu	%0, %1, %3				\n"
 		"	sc	%0, %2					\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
 		"	addu	%0, %1, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -204,8 +213,11 @@
 		"1:	ll	%1, %2		# atomic_sub_return	\n"
 		"	subu	%0, %1, %3				\n"
 		"	sc	%0, %2					\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
 		"	subu	%0, %1, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -267,10 +279,13 @@
 		"	bltz	%0, 1f					\n"
 		"	sc	%0, %2					\n"
 		"	.set	noreorder				\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
 		"	 subu	%0, %1, %3				\n"
 		"	.set	reorder					\n"
 		"1:							\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -429,7 +444,10 @@
 		"1:	lld	%0, %1		# atomic64_add		\n"
 		"	addu	%0, %2					\n"
 		"	scd	%0, %1					\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
@@ -471,7 +489,10 @@
 		"1:	lld	%0, %1		# atomic64_sub		\n"
 		"	subu	%0, %2					\n"
 		"	scd	%0, %1					\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
@@ -515,8 +536,11 @@
 		"1:	lld	%1, %2		# atomic64_add_return	\n"
 		"	addu	%0, %1, %3				\n"
 		"	scd	%0, %2					\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
 		"	addu	%0, %1, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -564,8 +588,11 @@
 		"1:	lld	%1, %2		# atomic64_sub_return	\n"
 		"	subu	%0, %1, %3				\n"
 		"	scd	%0, %2					\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
 		"	subu	%0, %1, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -627,10 +654,13 @@
 		"	bltz	%0, 1f					\n"
 		"	scd	%0, %2					\n"
 		"	.set	noreorder				\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
 		"	 dsubu	%0, %1, %3				\n"
 		"	.set	reorder					\n"
 		"1:							\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index 06445de..89436b9 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 1994 - 1997, 1999, 2000, 06  Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (c) 1994 - 1997, 99, 2000, 06, 07  Ralf Baechle (ralf@linux-mips.org)
  * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
  */
 #ifndef _ASM_BITOPS_H
@@ -24,11 +24,15 @@
 #define SZLONG_MASK 31UL
 #define __LL		"ll	"
 #define __SC		"sc	"
+#define __INS		"ins    "
+#define __EXT		"ext    "
 #elif (_MIPS_SZLONG == 64)
 #define SZLONG_LOG 6
 #define SZLONG_MASK 63UL
 #define __LL		"lld	"
 #define __SC		"scd	"
+#define __INS		"dins    "
+#define __EXT		"dext    "
 #endif
 
 /*
@@ -62,13 +66,29 @@
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
+#ifdef CONFIG_CPU_MIPSR2
+	} else if (__builtin_constant_p(nr)) {
+		__asm__ __volatile__(
+		"1:	" __LL "%0, %1			# set_bit	\n"
+		"	" __INS "%0, %4, %2, 1				\n"
+		"	" __SC "%0, %1					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		: "=&r" (temp), "=m" (*m)
+		: "ir" (nr & SZLONG_MASK), "m" (*m), "r" (~0));
+#endif /* CONFIG_CPU_MIPSR2 */
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
 		"1:	" __LL "%0, %1			# set_bit	\n"
 		"	or	%0, %2					\n"
 		"	" __SC	"%0, %1					\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
@@ -110,13 +130,29 @@
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
+#ifdef CONFIG_CPU_MIPSR2
+	} else if (__builtin_constant_p(nr)) {
+		__asm__ __volatile__(
+		"1:	" __LL "%0, %1			# clear_bit	\n"
+		"	" __INS "%0, $0, %2, 1				\n"
+		"	" __SC "%0, %1					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		: "=&r" (temp), "=m" (*m)
+		: "ir" (nr & SZLONG_MASK), "m" (*m));
+#endif /* CONFIG_CPU_MIPSR2 */
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
 		"1:	" __LL "%0, %1			# clear_bit	\n"
 		"	and	%0, %2					\n"
 		"	" __SC "%0, %1					\n"
-		"	beqz	%0, 1b					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
@@ -166,7 +202,10 @@
 		"1:	" __LL "%0, %1		# change_bit	\n"
 		"	xor	%0, %2				\n"
 		"	" __SC	"%0, %1				\n"
-		"	beqz	%0, 1b				\n"
+		"	beqz	%0, 2f				\n"
+		"	.subsection 2				\n"
+		"2:	b	1b				\n"
+		"	.previous				\n"
 		"	.set	mips0				\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
@@ -222,8 +261,12 @@
 		"1:	" __LL "%0, %1		# test_and_set_bit	\n"
 		"	or	%2, %0, %3				\n"
 		"	" __SC	"%2, %1					\n"
-		"	beqz	%2, 1b					\n"
+		"	beqz	%2, 2f					\n"
 		"	 and	%2, %0, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	 nop						\n"
+		"	.previous					\n"
 		"	.set	pop					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -278,6 +321,26 @@
 		: "memory");
 
 		return res != 0;
+#ifdef CONFIG_CPU_MIPSR2
+	} else if (__builtin_constant_p(nr)) {
+		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
+		unsigned long temp, res;
+
+		__asm__ __volatile__(
+		"1:	" __LL	"%0, %1		# test_and_clear_bit	\n"
+		"	" __EXT "%2, %0, %3, 1				\n"
+		"	" __INS	"%0, $0, %3, 1				\n"
+		"	" __SC 	"%0, %1					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		: "=&r" (temp), "=m" (*m), "=&r" (res)
+		: "ri" (nr & SZLONG_MASK), "m" (*m)
+		: "memory");
+
+		return res;
+#endif
 	} else if (cpu_has_llsc) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
 		unsigned long temp, res;
@@ -290,8 +353,12 @@
 		"	or	%2, %0, %3				\n"
 		"	xor	%2, %3					\n"
 		"	" __SC 	"%2, %1					\n"
-		"	beqz	%2, 1b					\n"
+		"	beqz	%2, 2f					\n"
 		"	 and	%2, %0, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	 nop						\n"
+		"	.previous					\n"
 		"	.set	pop					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -356,8 +423,12 @@
 		"1:	" __LL	"%0, %1		# test_and_change_bit	\n"
 		"	xor	%2, %0, %3				\n"
 		"	" __SC	"\t%2, %1				\n"
-		"	beqz	%2, 1b					\n"
+		"	beqz	%2, 2f					\n"
 		"	 and	%2, %0, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	 nop						\n"
+		"	.previous					\n"
 		"	.set	pop					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
diff --git a/include/asm-mips/compat-signal.h b/include/asm-mips/compat-signal.h
new file mode 100644
index 0000000..6599a90
--- /dev/null
+++ b/include/asm-mips/compat-signal.h
@@ -0,0 +1,57 @@
+#ifndef __ASM_COMPAT_SIGNAL_H
+#define __ASM_COMPAT_SIGNAL_H
+
+#include <linux/bug.h>
+#include <linux/compat.h>
+#include <linux/compiler.h>
+
+#include <asm/signal.h>
+#include <asm/siginfo.h>
+
+#include <asm/uaccess.h>
+
+static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d,
+	const sigset_t *s)
+{
+	int err;
+
+	BUG_ON(sizeof(*d) != sizeof(*s));
+	BUG_ON(_NSIG_WORDS != 2);
+
+	err  = __put_user(s->sig[0],       &d->sig[0]);
+	err |= __put_user(s->sig[0] >> 32, &d->sig[1]);
+	err |= __put_user(s->sig[1],       &d->sig[2]);
+	err |= __put_user(s->sig[1] >> 32, &d->sig[3]);
+
+	return err;
+}
+
+static inline int __copy_conv_sigset_from_user(sigset_t *d,
+	const compat_sigset_t __user *s)
+{
+	int err;
+	union sigset_u {
+		sigset_t	s;
+		compat_sigset_t c;
+	} *u = (union sigset_u *) d;
+
+	BUG_ON(sizeof(*d) != sizeof(*s));
+	BUG_ON(_NSIG_WORDS != 2);
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	err  = __get_user(u->c.sig[1], &s->sig[0]);
+	err |= __get_user(u->c.sig[0], &s->sig[1]);
+	err |= __get_user(u->c.sig[3], &s->sig[2]);
+	err |= __get_user(u->c.sig[2], &s->sig[3]);
+#endif
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+	err  = __get_user(u->c.sig[0], &s->sig[0]);
+	err |= __get_user(u->c.sig[1], &s->sig[1]);
+	err |= __get_user(u->c.sig[2], &s->sig[2]);
+	err |= __get_user(u->c.sig[3], &s->sig[3]);
+#endif
+
+	return err;
+}
+
+#endif /* __ASM_COMPAT_SIGNAL_H */
diff --git a/include/asm-mips/dec/system.h b/include/asm-mips/dec/system.h
index 78af51f..b2afacc 100644
--- a/include/asm-mips/dec/system.h
+++ b/include/asm-mips/dec/system.h
@@ -3,7 +3,7 @@
  *
  *	Generic DECstation/DECsystem bits.
  *
- *	Copyright (C) 2005  Maciej W. Rozycki
+ *	Copyright (C) 2005, 2006  Maciej W. Rozycki
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -14,5 +14,6 @@
 #define __ASM_DEC_SYSTEM_H
 
 extern unsigned long dec_kn_slot_base, dec_kn_slot_size;
+extern int dec_tc_bus;
 
 #endif /* __ASM_DEC_SYSTEM_H */
diff --git a/include/asm-mips/dec/tc.h b/include/asm-mips/dec/tc.h
deleted file mode 100644
index 9cb51f2..0000000
--- a/include/asm-mips/dec/tc.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Interface to the TURBOchannel related routines
- *
- * 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) 1998 Harald Koerfgen
- */
-#ifndef __ASM_DEC_TC_H
-#define __ASM_DEC_TC_H
-
-/*
- * Search for a TURBOchannel Option Module
- * with a certain name. Returns slot number
- * of the first card not in use or -ENODEV
- * if none found.
- */
-extern int search_tc_card(const char *);
-/*
- * Marks the card in slot as used
- */
-extern void claim_tc_card(int);
-/*
- * Marks the card in slot as free
- */
-extern void release_tc_card(int);
-/*
- * Return base address of card in slot
- */
-extern unsigned long get_tc_base_addr(int);
-/*
- * Return interrupt number of slot
- */
-extern unsigned long get_tc_irq_nr(int);
-/*
- * Return TURBOchannel clock frequency in Hz
- */
-extern unsigned long get_tc_speed(void);
-
-#endif /* __ASM_DEC_TC_H */
diff --git a/include/asm-mips/dec/tcinfo.h b/include/asm-mips/dec/tcinfo.h
deleted file mode 100644
index cc23509..0000000
--- a/include/asm-mips/dec/tcinfo.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Various TURBOchannel related stuff
- *
- * 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.
- *
- * Information obtained through the get_tcinfo prom call
- * created from:
- *
- * TURBOchannel Firmware Specification
- *
- * EK-TCAAD-FS-004
- * from Digital Equipment Corporation
- *
- * Copyright (c) 1998 Harald Koerfgen
- */
-
-typedef struct {
-	int revision;
-	int clk_period;
-	int slot_size;
-	int io_timeout;
-	int dma_range;
-	int max_dma_burst;
-	int parity;
-	int reserved[4];
-} tcinfo;
-
-#define MAX_SLOT 7
-
-typedef struct {
-	unsigned long base_addr;
-	unsigned char name[9];
-	unsigned char vendor[9];
-	unsigned char firmware[9];
-	int interrupt;
-	int flags;
-} slot_info;
-
-/*
- * Values for flags
- */
-#define FREE 	1<<0
-#define IN_USE	1<<1
-
-
diff --git a/include/asm-mips/dec/tcmodule.h b/include/asm-mips/dec/tcmodule.h
deleted file mode 100644
index 6268e89..0000000
--- a/include/asm-mips/dec/tcmodule.h
+++ /dev/null
@@ -1,39 +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.
- *
- * Offsets for the ROM header locations for
- * TURBOchannel cards
- *
- * created from:
- *
- * TURBOchannel Firmware Specification
- *
- * EK-TCAAD-FS-004
- * from Digital Equipment Corporation
- *
- * Jan.1998 Harald Koerfgen
- */
-#ifndef __ASM_DEC_TCMODULE_H
-#define __ASM_DEC_TCMODULE_H
-
-#define OLDCARD 0x3c0000
-#define NEWCARD 0x000000
-
-#define TC_ROM_WIDTH	0x3e0
-#define TC_ROM_STRIDE	0x3e4
-#define TC_ROM_SIZE	0x3e8
-#define TC_SLOT_SIZE	0x3ec
-#define TC_PATTERN0	0x3f0
-#define TC_PATTERN1	0x3f4
-#define TC_PATTERN2	0x3f8
-#define TC_PATTERN3	0x3fc
-#define TC_FIRM_VER	0x400
-#define TC_VENDOR	0x420
-#define TC_MODULE	0x440
-#define TC_FIRM_TYPE	0x460
-#define TC_FLAGS	0x470
-#define TC_ROM_OBJECTS	0x480
-
-#endif /* __ASM_DEC_TCMODULE_H */
diff --git a/include/asm-mips/dma-mapping.h b/include/asm-mips/dma-mapping.h
index 236d1a4..230b3f1 100644
--- a/include/asm-mips/dma-mapping.h
+++ b/include/asm-mips/dma-mapping.h
@@ -68,6 +68,7 @@
 extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 	       enum dma_data_direction direction);
 
+#if 0
 #define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
 
 extern int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
@@ -75,5 +76,6 @@
 extern void dma_release_declared_memory(struct device *dev);
 extern void * dma_mark_declared_memory_occupied(struct device *dev,
 	dma_addr_t device_addr, size_t size);
+#endif
 
 #endif /* _ASM_DMA_MAPPING_H */
diff --git a/include/asm-mips/ds1216.h b/include/asm-mips/ds1216.h
new file mode 100644
index 0000000..1ff8b73
--- /dev/null
+++ b/include/asm-mips/ds1216.h
@@ -0,0 +1,31 @@
+#ifndef _DS1216_H
+#define _DS1216_H
+
+extern volatile unsigned char *ds1216_base;
+unsigned long ds1216_get_cmos_time(void);
+int ds1216_set_rtc_mmss(unsigned long nowtime);
+
+#define DS1216_SEC_BYTE		1
+#define DS1216_MIN_BYTE		2
+#define DS1216_HOUR_BYTE	3
+#define DS1216_HOUR_MASK	(0x1f)
+#define DS1216_AMPM_MASK	(1<<5)
+#define DS1216_1224_MASK	(1<<7)
+#define DS1216_DAY_BYTE		4
+#define DS1216_DAY_MASK		(0x7)
+#define DS1216_DATE_BYTE	5
+#define DS1216_DATE_MASK	(0x3f)
+#define DS1216_MONTH_BYTE	6
+#define DS1216_MONTH_MASK	(0x1f)
+#define DS1216_YEAR_BYTE	7
+
+#define DS1216_SEC(buf)		(buf[DS1216_SEC_BYTE])
+#define DS1216_MIN(buf)		(buf[DS1216_MIN_BYTE])
+#define DS1216_HOUR(buf)	(buf[DS1216_HOUR_BYTE] & DS1216_HOUR_MASK)
+#define DS1216_AMPM(buf)	(buf[DS1216_HOUR_BYTE] & DS1216_AMPM_MASK)
+#define DS1216_1224(buf)	(buf[DS1216_HOUR_BYTE] & DS1216_1224_MASK)
+#define DS1216_DATE(buf)	(buf[DS1216_DATE_BYTE] & DS1216_DATE_MASK)
+#define DS1216_MONTH(buf)	(buf[DS1216_MONTH_BYTE] & DS1216_MONTH_MASK)
+#define DS1216_YEAR(buf)	(buf[DS1216_YEAR_BYTE])
+
+#endif
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index 67f0810..92ec261 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -20,6 +20,7 @@
 #include <asm/byteorder.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
+#include <asm-generic/iomap.h>
 #include <asm/page.h>
 #include <asm/pgtable-bits.h>
 #include <asm/processor.h>
@@ -518,34 +519,6 @@
 }
 
 /*
- * Memory Mapped I/O
- */
-#define ioread8(addr)		readb(addr)
-#define ioread16(addr)		readw(addr)
-#define ioread32(addr)		readl(addr)
-
-#define iowrite8(b,addr)	writeb(b,addr)
-#define iowrite16(w,addr)	writew(w,addr)
-#define iowrite32(l,addr)	writel(l,addr)
-
-#define ioread8_rep(a,b,c)	readsb(a,b,c)
-#define ioread16_rep(a,b,c)	readsw(a,b,c)
-#define ioread32_rep(a,b,c)	readsl(a,b,c)
-
-#define iowrite8_rep(a,b,c)	writesb(a,b,c)
-#define iowrite16_rep(a,b,c)	writesw(a,b,c)
-#define iowrite32_rep(a,b,c)	writesl(a,b,c)
-
-/* Create a virtual mapping cookie for an IO port range */
-extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
-extern void ioport_unmap(void __iomem *);
-
-/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
-struct pci_dev;
-extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
-extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
-
-/*
  * ISA space is 'always mapped' on currently supported MIPS systems, no need
  * to explicitly ioremap() it. The fact that the ISA IO space is mapped
  * to PAGE_OFFSET is pure coincidence - it does not mean ISA values
@@ -556,12 +529,6 @@
 #define __ISA_IO_base ((char *)(isa_slot_offset))
 
 /*
- * We don't have csum_partial_copy_fromio() yet, so we cheat here and
- * just copy it. The net code will then do the checksum later.
- */
-#define eth_io_copy_and_sum(skb,src,len,unused) memcpy_fromio((skb)->data,(src),(len))
-
-/*
  * The caches on some architectures aren't dma-coherent and have need to
  * handle this in software.  There are three types of operations that
  * can be applied to dma buffers.
diff --git a/include/asm-mips/mach-generic/dma-coherence.h b/include/asm-mips/mach-generic/dma-coherence.h
new file mode 100644
index 0000000..df71822
--- /dev/null
+++ b/include/asm-mips/mach-generic/dma-coherence.h
@@ -0,0 +1,43 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
+ *
+ */
+#ifndef __ASM_MACH_GENERIC_DMA_COHERENCE_H
+#define __ASM_MACH_GENERIC_DMA_COHERENCE_H
+
+struct device;
+
+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+	return virt_to_phys(addr);
+}
+
+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+	return page_to_phys(page);
+}
+
+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+	return dma_addr;
+}
+
+static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+#ifdef CONFIG_DMA_COHERENT
+	return 1;
+#endif
+#ifdef CONFIG_DMA_NONCOHERENT
+	return 0;
+#endif
+}
+
+#endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-generic/kmalloc.h b/include/asm-mips/mach-generic/kmalloc.h
index 410ab5f..b8e6deb 100644
--- a/include/asm-mips/mach-generic/kmalloc.h
+++ b/include/asm-mips/mach-generic/kmalloc.h
@@ -5,6 +5,7 @@
 #ifndef CONFIG_DMA_COHERENT
 /*
  * Total overkill for most systems but need as a safe default.
+ * Set this one if any device in the system might do non-coherent DMA.
  */
 #define ARCH_KMALLOC_MINALIGN	128
 #endif
diff --git a/include/asm-mips/mach-ip27/dma-coherence.h b/include/asm-mips/mach-ip27/dma-coherence.h
new file mode 100644
index 0000000..659816e
--- /dev/null
+++ b/include/asm-mips/mach-ip27/dma-coherence.h
@@ -0,0 +1,49 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
+ *
+ */
+#ifndef __ASM_MACH_IP27_DMA_COHERENCE_H
+#define __ASM_MACH_IP27_DMA_COHERENCE_H
+
+#include <asm/pci/bridge.h>
+
+#define pdev_to_baddr(pdev, addr) \
+	(BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr))
+#define dev_to_baddr(dev, addr) \
+	pdev_to_baddr(to_pci_dev(dev), (addr))
+
+struct device;
+
+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+	dma_addr_t pa = dev_to_baddr(dev, virt_to_phys(addr));
+
+	return pa;
+}
+
+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+	dma_addr_t pa = dev_to_baddr(dev, page_to_phys(page));
+
+	return pa;
+}
+
+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+	return dma_addr & (0xffUL << 56);
+}
+
+static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+	return 1;		/* IP27 non-cohernet mode is unsupported */
+}
+
+#endif /* __ASM_MACH_IP27_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-ip32/dma-coherence.h b/include/asm-mips/mach-ip32/dma-coherence.h
new file mode 100644
index 0000000..950be17
--- /dev/null
+++ b/include/asm-mips/mach-ip32/dma-coherence.h
@@ -0,0 +1,71 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
+ *
+ */
+#ifndef __ASM_MACH_IP35_DMA_COHERENCE_H
+#define __ASM_MACH_IP35_DMA_COHERENCE_H
+
+#include <asm/ip32/crime.h>
+
+struct device;
+
+/*
+ * Few notes.
+ * 1. CPU sees memory as two chunks: 0-256M@0x0, and the rest @0x40000000+256M
+ * 2. PCI sees memory as one big chunk @0x0 (or we could use 0x40000000 for
+ *    native-endian)
+ * 3. All other devices see memory as one big chunk at 0x40000000
+ * 4. Non-PCI devices will pass NULL as struct device*
+ *
+ * Thus we translate differently, depending on device.
+ */
+
+#define RAM_OFFSET_MASK 0x3fffffffUL
+
+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+	dma_addr_t pa = virt_to_phys(addr) & RAM_OFFSET_MASK;
+
+	if (dev == NULL)
+		pa += CRIME_HI_MEM_BASE;
+
+	return pa;
+}
+
+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+	dma_addr_t pa;
+
+	pa = page_to_phys(page) & RAM_OFFSET_MASK;
+
+	if (dev == NULL)
+		pa += CRIME_HI_MEM_BASE;
+
+	return pa;
+}
+
+/* This is almost certainly wrong but it's what dma-ip32.c used to use  */
+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+	unsigned long addr = dma_addr & RAM_OFFSET_MASK;
+
+	if (dma_addr >= 256*1024*1024)
+		addr += CRIME_HI_MEM_BASE;
+
+	return addr;
+}
+
+static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+	return 0;		/* IP32 is non-cohernet */
+}
+
+#endif /* __ASM_MACH_IP35_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-jazz/dma-coherence.h b/include/asm-mips/mach-jazz/dma-coherence.h
new file mode 100644
index 0000000..d66979a
--- /dev/null
+++ b/include/asm-mips/mach-jazz/dma-coherence.h
@@ -0,0 +1,40 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MACH_JAZZ_DMA_COHERENCE_H
+#define __ASM_MACH_JAZZ_DMA_COHERENCE_H
+
+#include <asm/jazzdma.h>
+
+struct device;
+
+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+	return vdma_alloc(virt_to_phys(addr), size);
+}
+
+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+	return vdma_alloc(page_to_phys(page), PAGE_SIZE);
+}
+
+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+	return vdma_log2phys(dma_addr);
+}
+
+static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+	vdma_free(dma_addr);
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+	return 0;
+}
+
+#endif /* __ASM_MACH_JAZZ_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-rm/cpu-feature-overrides.h b/include/asm-mips/mach-rm/cpu-feature-overrides.h
index 11410ae..7e07283 100644
--- a/include/asm-mips/mach-rm/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-rm/cpu-feature-overrides.h
@@ -21,9 +21,7 @@
 #define cpu_has_watch		0
 #define cpu_has_mips16		0
 #define cpu_has_divec		0
-#define cpu_has_vce		0
 #define cpu_has_cache_cdex_p	1
-#define cpu_has_cache_cdex_s	0
 #define cpu_has_prefetch	0
 #define cpu_has_mcheck		0
 #define cpu_has_ejtag		0
@@ -35,9 +33,6 @@
 #define cpu_has_nofpuex		0
 #define cpu_has_64bits		1
 
-#define cpu_dcache_line_size()	32
-#define cpu_icache_line_size()	32
-
 #define cpu_has_mips32r1	0
 #define cpu_has_mips32r2	0
 #define cpu_has_mips64r1	0
diff --git a/include/asm-mips/mips_mt.h b/include/asm-mips/mips_mt.h
index c31a312..fdfff0b 100644
--- a/include/asm-mips/mips_mt.h
+++ b/include/asm-mips/mips_mt.h
@@ -12,4 +12,7 @@
 extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
 extern void mips_mt_set_cpuoptions(void);
 
+struct class;
+extern struct class *mt_class;
+
 #endif /* __ASM_MIPS_MT_H */
diff --git a/include/asm-mips/mman.h b/include/asm-mips/mman.h
index 046cf68..e4d6f1f 100644
--- a/include/asm-mips/mman.h
+++ b/include/asm-mips/mman.h
@@ -72,7 +72,6 @@
 #define MADV_DOFORK	11		/* do inherit across fork */
 
 /* compatibility flags */
-#define MAP_ANON	MAP_ANONYMOUS
 #define MAP_FILE	0
 
 #endif /* _ASM_MMAN_H */
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index 7f0f120..3eea3ba 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -32,6 +32,7 @@
 	unsigned long mem_offset;
 	struct resource *io_resource;
 	unsigned long io_offset;
+	unsigned long io_map_base;
 
 	unsigned int index;
 	/* For compatibility with current (as of July 2003) pciutils
diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h
index af121c6..5685d4f 100644
--- a/include/asm-mips/pgalloc.h
+++ b/include/asm-mips/pgalloc.h
@@ -130,4 +130,6 @@
 
 #define check_pgt_cache()	do { } while (0)
 
+extern void pagetable_init(void);
+
 #endif /* _ASM_PGALLOC_H */
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 8a1f2b6..1906938 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -21,6 +21,7 @@
 #define FPC_EIR		70
 #define DSP_BASE	71		/* 3 more hi / lo register pairs */
 #define DSP_CONTROL	77
+#define ACX		78
 
 /*
  * This struct defines the way the registers are stored on the stack during a
@@ -39,6 +40,9 @@
 	unsigned long cp0_status;
 	unsigned long hi;
 	unsigned long lo;
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+	unsigned long acx;
+#endif
 	unsigned long cp0_badvaddr;
 	unsigned long cp0_cause;
 	unsigned long cp0_epc;
diff --git a/include/asm-mips/sigcontext.h b/include/asm-mips/sigcontext.h
index cefa657..9ce0607 100644
--- a/include/asm-mips/sigcontext.h
+++ b/include/asm-mips/sigcontext.h
@@ -19,11 +19,11 @@
  */
 struct sigcontext {
 	unsigned int		sc_regmask;	/* Unused */
-	unsigned int		sc_status;
+	unsigned int		sc_status;	/* Unused */
 	unsigned long long	sc_pc;
 	unsigned long long	sc_regs[32];
 	unsigned long long	sc_fpregs[32];
-	unsigned int		sc_ownedfp;	/* Unused */
+	unsigned int		sc_acx;		/* Was sc_ownedfp */
 	unsigned int		sc_fpc_csr;
 	unsigned int		sc_fpc_eir;	/* Unused */
 	unsigned int		sc_used_math;
@@ -42,6 +42,7 @@
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
 
+#include <linux/posix_types.h>
 /*
  * Keep this struct definition in sync with the sigcontext fragment
  * in arch/mips/tools/offset.c
@@ -53,34 +54,32 @@
  * entries, add sc_dsp and sc_reserved for padding.  No prisoners.
  */
 struct sigcontext {
-	unsigned long	sc_regs[32];
-	unsigned long	sc_fpregs[32];
-	unsigned long	sc_mdhi;
-	unsigned long	sc_hi1;
-	unsigned long	sc_hi2;
-	unsigned long	sc_hi3;
-	unsigned long	sc_mdlo;
-	unsigned long	sc_lo1;
-	unsigned long	sc_lo2;
-	unsigned long	sc_lo3;
-	unsigned long	sc_pc;
-	unsigned int	sc_fpc_csr;
-	unsigned int	sc_used_math;
-	unsigned int	sc_dsp;
-	unsigned int	sc_reserved;
+	__u64	sc_regs[32];
+	__u64	sc_fpregs[32];
+	__u64	sc_mdhi;
+	__u64	sc_hi1;
+	__u64	sc_hi2;
+	__u64	sc_hi3;
+	__u64	sc_mdlo;
+	__u64	sc_lo1;
+	__u64	sc_lo2;
+	__u64	sc_lo3;
+	__u64	sc_pc;
+	__u32	sc_fpc_csr;
+	__u32	sc_used_math;
+	__u32	sc_dsp;
+	__u32	sc_reserved;
 };
 
 #ifdef __KERNEL__
 
-#include <linux/posix_types.h>
-
 struct sigcontext32 {
 	__u32		sc_regmask;	/* Unused */
-	__u32		sc_status;
+	__u32		sc_status;	/* Unused */
 	__u64		sc_pc;
 	__u64		sc_regs[32];
 	__u64		sc_fpregs[32];
-	__u32		sc_ownedfp;	/* Unused */
+	__u32		sc_acx;		/* Only MIPS32; was sc_ownedfp */
 	__u32		sc_fpc_csr;
 	__u32		sc_fpc_eir;	/* Unused */
 	__u32		sc_used_math;
diff --git a/include/asm-mips/signal.h b/include/asm-mips/signal.h
index 8b391a2..7a28989 100644
--- a/include/asm-mips/signal.h
+++ b/include/asm-mips/signal.h
@@ -137,23 +137,6 @@
 
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
-struct pt_regs;
-extern void do_signal(struct pt_regs *regs);
-extern void do_signal32(struct pt_regs *regs);
-
-extern int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
-        int signr, sigset_t *set);
-extern int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
-        int signr, sigset_t *set, siginfo_t *info);
-
-extern int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
-        int signr, sigset_t *set);
-extern int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
-        int signr, sigset_t *set, siginfo_t *info);
-
-extern int setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs,
-        int signr, sigset_t *set, siginfo_t *info);
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_SIGNAL_H */
diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h
index b9ba54d..62f9be6 100644
--- a/include/asm-mips/sni.h
+++ b/include/asm-mips/sni.h
@@ -6,12 +6,72 @@
  * for more details.
  *
  * Copyright (C) 1997, 1998 by Ralf Baechle
+ * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  */
 #ifndef __ASM_SNI_H
 #define __ASM_SNI_H
 
+extern unsigned int sni_brd_type;
+
+#define SNI_BRD_10                 2
+#define SNI_BRD_10NEW              3
+#define SNI_BRD_TOWER_OASIC        4
+#define SNI_BRD_MINITOWER          5
+#define SNI_BRD_PCI_TOWER          6
+#define SNI_BRD_RM200              7
+#define SNI_BRD_PCI_MTOWER         8
+#define SNI_BRD_PCI_DESKTOP        9
+#define SNI_BRD_PCI_TOWER_CPLUS   10
+#define SNI_BRD_PCI_MTOWER_CPLUS  11
+
+/* RM400 cpu types */
+#define SNI_CPU_M8021           0x01
+#define SNI_CPU_M8030           0x04
+#define SNI_CPU_M8031           0x06
+#define SNI_CPU_M8034           0x0f
+#define SNI_CPU_M8037           0x07
+#define SNI_CPU_M8040           0x05
+#define SNI_CPU_M8043           0x09
+#define SNI_CPU_M8050           0x0b
+#define SNI_CPU_M8053           0x0d
+
 #define SNI_PORT_BASE		0xb4000000
 
+#ifndef __MIPSEL__
+/*
+ * ASIC PCI registers for big endian configuration.
+ */
+#define PCIMT_UCONF		0xbfff0004
+#define PCIMT_IOADTIMEOUT2	0xbfff000c
+#define PCIMT_IOMEMCONF		0xbfff0014
+#define PCIMT_IOMMU		0xbfff001c
+#define PCIMT_IOADTIMEOUT1	0xbfff0024
+#define PCIMT_DMAACCESS		0xbfff002c
+#define PCIMT_DMAHIT		0xbfff0034
+#define PCIMT_ERRSTATUS		0xbfff003c
+#define PCIMT_ERRADDR		0xbfff0044
+#define PCIMT_SYNDROME		0xbfff004c
+#define PCIMT_ITPEND		0xbfff0054
+#define  IT_INT2		0x01
+#define  IT_INTD		0x02
+#define  IT_INTC		0x04
+#define  IT_INTB		0x08
+#define  IT_INTA		0x10
+#define  IT_EISA		0x20
+#define  IT_SCSI		0x40
+#define  IT_ETH			0x80
+#define PCIMT_IRQSEL		0xbfff005c
+#define PCIMT_TESTMEM		0xbfff0064
+#define PCIMT_ECCREG		0xbfff006c
+#define PCIMT_CONFIG_ADDRESS	0xbfff0074
+#define PCIMT_ASIC_ID		0xbfff007c	/* read */
+#define PCIMT_SOFT_RESET	0xbfff007c	/* write */
+#define PCIMT_PIA_OE		0xbfff0084
+#define PCIMT_PIA_DATAOUT	0xbfff008c
+#define PCIMT_PIA_DATAIN	0xbfff0094
+#define PCIMT_CACHECONF		0xbfff009c
+#define PCIMT_INVSPACE		0xbfff00a4
+#else
 /*
  * ASIC PCI registers for little endian configuration.
  */
@@ -45,6 +105,8 @@
 #define PCIMT_PIA_DATAIN	0xbfff0090
 #define PCIMT_CACHECONF		0xbfff0098
 #define PCIMT_INVSPACE		0xbfff00a0
+#endif
+
 #define PCIMT_PCI_CONF		0xbfff0100
 
 /*
@@ -73,6 +135,36 @@
 #define PCIMT_PWDN		0xbfdf0000
 
 /*
+ * A20R based boards
+ */
+#define A20R_PT_CLOCK_BASE      0xbc040000
+#define A20R_PT_TIM0_ACK        0xbc050000
+#define A20R_PT_TIM1_ACK        0xbc060000
+
+#define SNI_MIPS_IRQ_CPU_BASE   16
+#define SNI_MIPS_IRQ_CPU_TIMER  (SNI_MIPS_IRQ_CPU_BASE+7)
+
+#define SNI_A20R_IRQ_BASE       SNI_MIPS_IRQ_CPU_BASE
+#define SNI_A20R_IRQ_TIMER      (SNI_A20R_IRQ_BASE+5)
+
+#define SNI_DS1216_A20R_BASE    0xbc081ffc
+#define SNI_DS1216_RM200_BASE   0xbcd41ffc
+
+#define SNI_PCIT_INT_REG        0xbfff000c
+
+#define SNI_PCIT_INT_START      24
+#define SNI_PCIT_INT_END        30
+
+#define PCIT_IRQ_ETHERNET       (SNI_MIPS_IRQ_CPU_BASE + 5)
+#define PCIT_IRQ_INTA           (SNI_PCIT_INT_START + 0)
+#define PCIT_IRQ_INTB           (SNI_PCIT_INT_START + 1)
+#define PCIT_IRQ_INTC           (SNI_PCIT_INT_START + 2)
+#define PCIT_IRQ_INTD           (SNI_PCIT_INT_START + 3)
+#define PCIT_IRQ_SCSI0          (SNI_PCIT_INT_START + 4)
+#define PCIT_IRQ_SCSI1          (SNI_PCIT_INT_START + 5)
+
+
+/*
  * Interrupt 0-16 are EISA interrupts.  Interrupts from 16 on are assigned
  * to the other interrupts generated by ASIC PCI.
  *
@@ -80,18 +172,22 @@
  * ASIC PCI interrupt.
  */
 #define PCIMT_KEYBOARD_IRQ	 1
-#define PCIMT_IRQ_INT2		16
-#define PCIMT_IRQ_INTD		17
-#define PCIMT_IRQ_INTC		18
-#define PCIMT_IRQ_INTB		19
-#define PCIMT_IRQ_INTA		20
-#define PCIMT_IRQ_EISA		21
-#define PCIMT_IRQ_SCSI		22
-#define PCIMT_IRQ_ETHERNET	23
+#define PCIMT_IRQ_INT2		24
+#define PCIMT_IRQ_INTD		25
+#define PCIMT_IRQ_INTC		26
+#define PCIMT_IRQ_INTB		27
+#define PCIMT_IRQ_INTA		28
+#define PCIMT_IRQ_EISA		29
+#define PCIMT_IRQ_SCSI		30
+
+#define PCIMT_IRQ_ETHERNET	(SNI_MIPS_IRQ_CPU_BASE+6)
+
+#if 0
 #define PCIMT_IRQ_TEMPERATURE	24
 #define PCIMT_IRQ_EISA_NMI	25
 #define PCIMT_IRQ_POWER_OFF	26
 #define PCIMT_IRQ_BUTTON	27
+#endif
 
 /*
  * Base address for the mapped 16mb EISA bus segment.
@@ -101,4 +197,24 @@
 /* PCI EISA Interrupt acknowledge  */
 #define PCIMT_INT_ACKNOWLEDGE	0xba000000
 
+/* board specific init functions */
+extern void sni_a20r_init (void);
+extern void sni_pcit_init (void);
+extern void sni_rm200_init (void);
+extern void sni_pcimt_init (void);
+
+/* board specific irq init functions */
+extern void sni_a20r_irq_init (void);
+extern void sni_pcit_irq_init (void);
+extern void sni_pcit_cplus_irq_init (void);
+extern void sni_rm200_irq_init (void);
+extern void sni_pcimt_irq_init (void);
+
+/* timer inits */
+extern void sni_cpu_time_init(void);
+
+/* common irq stuff */
+extern void (*sni_hwint)(void);
+extern struct irqaction sni_isa_irq;
+
 #endif /* __ASM_SNI_H */
diff --git a/include/asm-mips/spinlock.h b/include/asm-mips/spinlock.h
index fc3217f..f1755d2 100644
--- a/include/asm-mips/spinlock.h
+++ b/include/asm-mips/spinlock.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999, 2000, 06 by Ralf Baechle
+ * Copyright (C) 1999, 2000, 06 Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_SPINLOCK_H
@@ -49,11 +49,18 @@
 		__asm__ __volatile__(
 		"	.set	noreorder	# __raw_spin_lock	\n"
 		"1:	ll	%1, %2					\n"
-		"	bnez	%1, 1b					\n"
+		"	bnez	%1, 2f					\n"
 		"	 li	%1, 1					\n"
 		"	sc	%1, %0					\n"
-		"	beqz	%1, 1b					\n"
+		"	beqz	%1, 2f					\n"
 		"	 nop						\n"
+		"	.subsection 2					\n"
+		"2:	ll	%1, %2					\n"
+		"	bnez	%1, 2b					\n"
+		"	 li	%1, 1					\n"
+		"	b	1b					\n"
+		"	 nop						\n"
+		"	.previous					\n"
 		"	.set	reorder					\n"
 		: "=m" (lock->lock), "=&r" (tmp)
 		: "m" (lock->lock)
@@ -99,8 +106,12 @@
 		"1:	ll	%0, %3					\n"
 		"	ori	%2, %0, 1				\n"
 		"	sc	%2, %1					\n"
-		"	beqz	%2, 1b					\n"
+		"	beqz	%2, 2f					\n"
 		"	 andi	%2, %0, 1				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	 nop						\n"
+		"	.previous					\n"
 		"	.set	reorder"
 		: "=&r" (temp), "=m" (lock->lock), "=&r" (res)
 		: "m" (lock->lock)
@@ -154,11 +165,18 @@
 		__asm__ __volatile__(
 		"	.set	noreorder	# __raw_read_lock	\n"
 		"1:	ll	%1, %2					\n"
-		"	bltz	%1, 1b					\n"
+		"	bltz	%1, 2f					\n"
 		"	 addu	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	beqz	%1, 1b					\n"
 		"	 nop						\n"
+		"	.subsection 2					\n"
+		"2:	ll	%1, %2					\n"
+		"	bltz	%1, 2b					\n"
+		"	 addu	%1, 1					\n"
+		"	b	1b					\n"
+		"	 nop						\n"
+		"	.previous					\n"
 		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
@@ -192,8 +210,12 @@
 		"1:	ll	%1, %2					\n"
 		"	sub	%1, 1					\n"
 		"	sc	%1, %0					\n"
-		"	beqz	%1, 1b					\n"
+		"	beqz	%1, 2f					\n"
 		"	 nop						\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	 nop						\n"
+		"	.previous					\n"
 		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
@@ -222,11 +244,18 @@
 		__asm__ __volatile__(
 		"	.set	noreorder	# __raw_write_lock	\n"
 		"1:	ll	%1, %2					\n"
-		"	bnez	%1, 1b					\n"
+		"	bnez	%1, 2f					\n"
 		"	 lui	%1, 0x8000				\n"
 		"	sc	%1, %0					\n"
-		"	beqz	%1, 1b					\n"
+		"	beqz	%1, 2f					\n"
 		"	 nop						\n"
+		"	.subsection 2					\n"
+		"2:	ll	%1, %2					\n"
+		"	bnez	%1, 2b					\n"
+		"	 lui	%1, 0x8000				\n"
+		"	b	1b					\n"
+		"	 nop						\n"
+		"	.previous					\n"
 		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
@@ -322,12 +351,15 @@
 		"	bnez	%1, 2f					\n"
 		"	lui	%1, 0x8000				\n"
 		"	sc	%1, %0					\n"
-		"	beqz	%1, 1b					\n"
-		"	 nop						\n"
-		__WEAK_ORDERING_MB
-		"	li	%2, 1					\n"
-		"	.set	reorder					\n"
+		"	beqz	%1, 3f					\n"
+		"	 li	%2, 1					\n"
 		"2:							\n"
+		__WEAK_ORDERING_MB
+		"	.subsection 2					\n"
+		"3:	b	1b					\n"
+		"	 li	%2, 0					\n"
+		"	.previous					\n"
+		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
 		: "m" (rw->lock)
 		: "memory");
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 1fae5dc..7afa1fd 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -29,16 +29,25 @@
 		.endm
 
 		.macro	SAVE_TEMP
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+		mflhxu	v1
+		LONG_S	v1, PT_LO(sp)
+		mflhxu	v1
+		LONG_S	v1, PT_HI(sp)
+		mflhxu	v1
+		LONG_S	v1, PT_ACX(sp)
+#else
 		mfhi	v1
+		LONG_S	v1, PT_HI(sp)
+		mflo	v1
+		LONG_S	v1, PT_LO(sp)
+#endif
 #ifdef CONFIG_32BIT
 		LONG_S	$8, PT_R8(sp)
 		LONG_S	$9, PT_R9(sp)
 #endif
-		LONG_S	v1, PT_HI(sp)
-		mflo	v1
 		LONG_S	$10, PT_R10(sp)
 		LONG_S	$11, PT_R11(sp)
-		LONG_S	v1,  PT_LO(sp)
 		LONG_S	$12, PT_R12(sp)
 		LONG_S	$13, PT_R13(sp)
 		LONG_S	$14, PT_R14(sp)
@@ -182,16 +191,25 @@
 		.endm
 
 		.macro	RESTORE_TEMP
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+		LONG_L	$24, PT_ACX(sp)
+		mtlhx	$24
+		LONG_L	$24, PT_HI(sp)
+		mtlhx	$24
 		LONG_L	$24, PT_LO(sp)
+		mtlhx	$24
+#else
+		LONG_L	$24, PT_LO(sp)
+		mtlo	$24
+		LONG_L	$24, PT_HI(sp)
+		mthi	$24
+#endif
 #ifdef CONFIG_32BIT
 		LONG_L	$8, PT_R8(sp)
 		LONG_L	$9, PT_R9(sp)
 #endif
-		mtlo	$24
-		LONG_L	$24, PT_HI(sp)
 		LONG_L	$10, PT_R10(sp)
 		LONG_L	$11, PT_R11(sp)
-		mthi	$24
 		LONG_L	$12, PT_R12(sp)
 		LONG_L	$13, PT_R13(sp)
 		LONG_L	$14, PT_R14(sp)
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 5e1289c..597a374 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -110,7 +110,10 @@
 		"	move	%2, %z4					\n"
 		"	.set	mips3					\n"
 		"	sc	%2, %1					\n"
-		"	beqz	%2, 1b					\n"
+		"	beqz	%2, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
@@ -155,7 +158,10 @@
 		"1:	lld	%0, %3			# xchg_u64	\n"
 		"	move	%2, %z4					\n"
 		"	scd	%2, %1					\n"
-		"	beqz	%2, 1b					\n"
+		"	beqz	%2, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	mips0					\n"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
@@ -232,8 +238,11 @@
 		"	move	$1, %z4					\n"
 		"	.set	mips3					\n"
 		"	sc	$1, %1					\n"
-		"	beqz	$1, 1b					\n"
+		"	beqz	$1, 3f					\n"
 		"2:							\n"
+		"	.subsection 2					\n"
+		"3:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	pop					\n"
 		: "=&r" (retval), "=R" (*m)
 		: "R" (*m), "Jr" (old), "Jr" (new)
@@ -283,8 +292,11 @@
 		"	bne	%0, %z3, 2f				\n"
 		"	move	$1, %z4					\n"
 		"	scd	$1, %1					\n"
-		"	beqz	$1, 1b					\n"
+		"	beqz	$1, 3f					\n"
 		"2:							\n"
+		"	.subsection 2					\n"
+		"3:	b	1b					\n"
+		"	.previous					\n"
 		"	.set	pop					\n"
 		: "=&r" (retval), "=R" (*m)
 		: "R" (*m), "Jr" (old), "Jr" (new)
diff --git a/include/asm-mips/termios.h b/include/asm-mips/termios.h
index 4906204..2ce07f4 100644
--- a/include/asm-mips/termios.h
+++ b/include/asm-mips/termios.h
@@ -87,24 +87,6 @@
 #define TIOCM_OUT2	0x4000
 #define TIOCM_LOOP	0x8000
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6		/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved fo Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_HCI		15	/* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 #include <linux/string.h>
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index c12ebc5..c62c20e 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -265,12 +265,14 @@
  */
 #define __get_user_asm_ll32(val, addr)					\
 {									\
-        unsigned long long __gu_tmp;					\
+	union {								\
+		unsigned long long	l;				\
+		__typeof__(*(addr))	t;				\
+	} __gu_tmp;							\
 									\
 	__asm__ __volatile__(						\
 	"1:	lw	%1, (%3)				\n"	\
 	"2:	lw	%D1, 4(%3)				\n"	\
-	"	move	%0, $0					\n"	\
 	"3:	.section	.fixup,\"ax\"			\n"	\
 	"4:	li	%0, %4					\n"	\
 	"	move	%1, $0					\n"	\
@@ -281,9 +283,10 @@
 	"	" __UA_ADDR "	1b, 4b				\n"	\
 	"	" __UA_ADDR "	2b, 4b				\n"	\
 	"	.previous					\n"	\
-	: "=r" (__gu_err), "=&r" (__gu_tmp)				\
+	: "=r" (__gu_err), "=&r" (__gu_tmp.l)				\
 	: "0" (0), "r" (addr), "i" (-EFAULT));				\
-	(val) = (__typeof__(*(addr))) __gu_tmp;				\
+									\
+	(val) = __gu_tmp.t;						\
 }
 
 /*
@@ -432,8 +435,32 @@
 	__cu_len;							\
 })
 
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
+#define __copy_to_user_inatomic(to,from,n)				\
+({									\
+	void __user *__cu_to;						\
+	const void *__cu_from;						\
+	long __cu_len;							\
+									\
+	__cu_to = (to);							\
+	__cu_from = (from);						\
+	__cu_len = (n);							\
+	__cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len);	\
+	__cu_len;							\
+})
+
+#define __copy_from_user_inatomic(to,from,n)				\
+({									\
+	void *__cu_to;							\
+	const void __user *__cu_from;					\
+	long __cu_len;							\
+									\
+	__cu_to = (to);							\
+	__cu_from = (from);						\
+	__cu_len = (n);							\
+	__cu_len = __invoke_copy_from_user_inatomic(__cu_to, __cu_from,	\
+	                                            __cu_len);		\
+	__cu_len;							\
+})
 
 /*
  * copy_to_user: - Copy a block of data into user space.
@@ -487,6 +514,29 @@
 	__cu_len_r;							\
 })
 
+#define __invoke_copy_from_user_inatomic(to,from,n)			\
+({									\
+	register void *__cu_to_r __asm__ ("$4");			\
+	register const void __user *__cu_from_r __asm__ ("$5");		\
+	register long __cu_len_r __asm__ ("$6");			\
+									\
+	__cu_to_r = (to);						\
+	__cu_from_r = (from);						\
+	__cu_len_r = (n);						\
+	__asm__ __volatile__(						\
+	".set\tnoreorder\n\t"						\
+	__MODULE_JAL(__copy_user_inatomic)				\
+	".set\tnoat\n\t"						\
+	__UA_ADDU "\t$1, %1, %2\n\t"					\
+	".set\tat\n\t"							\
+	".set\treorder"							\
+	: "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)	\
+	:								\
+	: "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31",		\
+	  "memory");							\
+	__cu_len_r;							\
+})
+
 /*
  * __copy_from_user: - Copy a block of data from user space, with less checking.
  * @to:   Destination address, in kernel space.
diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h
index c1963ce..ca46e7c 100644
--- a/include/asm-parisc/io.h
+++ b/include/asm-parisc/io.h
@@ -191,15 +191,6 @@
 void memcpy_fromio(void *dst, const volatile void __iomem *src, int count);
 void memcpy_toio(volatile void __iomem *dst, const void *src, int count);
 
-/*
- * XXX - We don't have csum_partial_copy_fromio() yet, so we cheat here and 
- * just copy it. The net code will then do the checksum later. Presently 
- * only used by some shared memory 8390 Ethernet cards anyway.
- */
-
-#define eth_io_copy_and_sum(skb,src,len,unused) \
-  memcpy_fromio((skb)->data,(src),(len))
-
 /* Port-space IO */
 
 #define inb_p inb
diff --git a/include/asm-parisc/mman.h b/include/asm-parisc/mman.h
index 0ef15ee..defe752 100644
--- a/include/asm-parisc/mman.h
+++ b/include/asm-parisc/mman.h
@@ -55,7 +55,6 @@
 #define MADV_64M_PAGES  26              /* Use 64 Megabyte pages */
 
 /* compatibility flags */
-#define MAP_ANON	MAP_ANONYMOUS
 #define MAP_FILE	0
 #define MAP_VARIABLE	0
 
diff --git a/include/asm-parisc/termios.h b/include/asm-parisc/termios.h
index 6965e8f..5345b34 100644
--- a/include/asm-parisc/termios.h
+++ b/include/asm-parisc/termios.h
@@ -39,24 +39,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*	intr=^C		quit=^\		erase=del	kill=^U
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
index 703970f..4869513 100644
--- a/include/asm-powerpc/Kbuild
+++ b/include/asm-powerpc/Kbuild
@@ -23,6 +23,7 @@
 header-y += resource.h
 header-y += sigcontext.h
 header-y += statfs.h
+header-y += ps3fb.h
 
 unifdef-y += a.out.h
 unifdef-y += asm-compat.h
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h
index f038e33..2ce4b6b 100644
--- a/include/asm-powerpc/atomic.h
+++ b/include/asm-powerpc/atomic.h
@@ -165,7 +165,8 @@
 	return t;
 }
 
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_cmpxchg(v, o, n) \
+	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
@@ -413,6 +414,43 @@
 	return t;
 }
 
+#define atomic64_cmpxchg(v, o, n) \
+	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+/**
+ * atomic64_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic64_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+	long t;
+
+	__asm__ __volatile__ (
+	LWSYNC_ON_SMP
+"1:	ldarx	%0,0,%1		# atomic_add_unless\n\
+	cmpd	0,%0,%3 \n\
+	beq-	2f \n\
+	add	%0,%2,%0 \n"
+"	stdcx.	%0,0,%1 \n\
+	bne-	1b \n"
+	ISYNC_ON_SMP
+"	subf	%0,%2,%0 \n\
+2:"
+	: "=&r" (t)
+	: "r" (&v->counter), "r" (a), "r" (u)
+	: "cc", "memory");
+
+	return t != u;
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
 #endif /* __powerpc64__ */
 
 #include <asm-generic/atomic.h>
diff --git a/include/asm-powerpc/cell-pmu.h b/include/asm-powerpc/cell-pmu.h
index e8c2ebd..35b9577 100644
--- a/include/asm-powerpc/cell-pmu.h
+++ b/include/asm-powerpc/cell-pmu.h
@@ -53,6 +53,11 @@
 #define CBE_PM_CTR_POLARITY                0x01000000
 #define CBE_PM_CTR_COUNT_CYCLES            0x00800000
 #define CBE_PM_CTR_ENABLE                  0x00400000
+#define PM07_CTR_INPUT_MUX(x)              (((x) & 0x3F) << 26)
+#define PM07_CTR_INPUT_CONTROL(x)          (((x) & 1) << 25)
+#define PM07_CTR_POLARITY(x)               (((x) & 1) << 24)
+#define PM07_CTR_COUNT_CYCLES(x)           (((x) & 1) << 23)
+#define PM07_CTR_ENABLE(x)                 (((x) & 1) << 22)
 
 /* Macros for the pm_status register. */
 #define CBE_PM_CTR_OVERFLOW_INTR(ctr)      (1 << (31 - ((ctr) & 7)))
@@ -89,8 +94,7 @@
 
 extern void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask);
 extern void cbe_disable_pm_interrupts(u32 cpu);
-extern u32  cbe_query_pm_interrupts(u32 cpu);
-extern u32  cbe_clear_pm_interrupts(u32 cpu);
+extern u32  cbe_get_and_clear_pm_interrupts(u32 cpu);
 extern void cbe_sync_irq(int node);
 
 /* Utility functions, macros */
@@ -103,11 +107,4 @@
 #define CBE_COUNT_PROBLEM_MODE          2
 #define CBE_COUNT_ALL_MODES             3
 
-/* Macros for the pm07_control registers. */
-#define PM07_CTR_INPUT_MUX(x)                    (((x) & 0x3F) << 26)
-#define PM07_CTR_INPUT_CONTROL(x)                (((x) & 1) << 25)
-#define PM07_CTR_POLARITY(x)                     (((x) & 1) << 24)
-#define PM07_CTR_COUNT_CYCLES(x)                 (((x) & 1) << 23)
-#define PM07_CTR_ENABLE(x)                       (((x) & 1) << 22)
-
 #endif /* __ASM_CELL_PMU_H__ */
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
index d7a1bc1..05af081 100644
--- a/include/asm-powerpc/dcr-native.h
+++ b/include/asm-powerpc/dcr-native.h
@@ -26,8 +26,8 @@
 
 #define DCR_MAP_OK(host)	(1)
 
-#define dcr_map(dev, dcr_n, dcr_c)	{}
-#define dcr_unmap(host, dcr_n, dcr_c)	{}
+#define dcr_map(dev, dcr_n, dcr_c)	((dcr_host_t){})
+#define dcr_unmap(host, dcr_n, dcr_c)	do {} while (0)
 #define dcr_read(host, dcr_n)		mfdcr(dcr_n)
 #define dcr_write(host, dcr_n, value)	mtdcr(dcr_n, value)
 
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index fd242a2..a0f14ee 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -17,28 +17,115 @@
 #define fd_outb(value,port)	outb_p(value,port)
 
 #define fd_enable_dma()         enable_dma(FLOPPY_DMA)
-#define fd_disable_dma()        disable_dma(FLOPPY_DMA)
-#define fd_request_dma()        request_dma(FLOPPY_DMA, "floppy")
-#define fd_free_dma()           free_dma(FLOPPY_DMA)
+#define fd_disable_dma()	 fd_ops->_disable_dma(FLOPPY_DMA)
+#define fd_free_dma()           fd_ops->_free_dma(FLOPPY_DMA)
 #define fd_clear_dma_ff()       clear_dma_ff(FLOPPY_DMA)
 #define fd_set_dma_mode(mode)   set_dma_mode(FLOPPY_DMA, mode)
 #define fd_set_dma_count(count) set_dma_count(FLOPPY_DMA, count)
+#define fd_get_dma_residue()    fd_ops->_get_dma_residue(FLOPPY_DMA)
 #define fd_enable_irq()         enable_irq(FLOPPY_IRQ)
 #define fd_disable_irq()        disable_irq(FLOPPY_IRQ)
 #define fd_cacheflush(addr,size) /* nothing */
-#define fd_request_irq()        request_irq(FLOPPY_IRQ, floppy_interrupt, \
-					    IRQF_DISABLED, "floppy", NULL)
 #define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
 
-#ifdef CONFIG_PCI
-
 #include <linux/pci.h>
 #include <asm/ppc-pci.h>	/* for ppc64_isabridge_dev */
 
-#define fd_dma_setup(addr,size,mode,io) powerpc_fd_dma_setup(addr,size,mode,io)
+#define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io)
 
-static __inline__ int powerpc_fd_dma_setup(char *addr, unsigned long size,
-					   int mode, int io)
+static int fd_request_dma(void);
+
+struct fd_dma_ops {
+	void (*_disable_dma)(unsigned int dmanr);
+	void (*_free_dma)(unsigned int dmanr);
+	int (*_get_dma_residue)(unsigned int dummy);
+	int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
+};
+
+static int virtual_dma_count;
+static int virtual_dma_residue;
+static char *virtual_dma_addr;
+static int virtual_dma_mode;
+static int doing_vdma;
+static struct fd_dma_ops *fd_ops;
+
+static irqreturn_t floppy_hardint(int irq, void *dev_id)
+{
+	unsigned char st;
+	int lcount;
+	char *lptr;
+
+	if (!doing_vdma)
+		return floppy_interrupt(irq, dev_id);
+
+
+	st = 1;
+	for (lcount=virtual_dma_count, lptr=virtual_dma_addr;
+	     lcount; lcount--, lptr++) {
+		st=inb(virtual_dma_port+4) & 0xa0 ;
+		if (st != 0xa0)
+			break;
+		if (virtual_dma_mode)
+			outb_p(*lptr, virtual_dma_port+5);
+		else
+			*lptr = inb_p(virtual_dma_port+5);
+	}
+	virtual_dma_count = lcount;
+	virtual_dma_addr = lptr;
+	st = inb(virtual_dma_port+4);
+
+	if (st == 0x20)
+		return IRQ_HANDLED;
+	if (!(st & 0x20)) {
+		virtual_dma_residue += virtual_dma_count;
+		virtual_dma_count=0;
+		doing_vdma = 0;
+		floppy_interrupt(irq, dev_id);
+		return IRQ_HANDLED;
+	}
+	return IRQ_HANDLED;
+}
+
+static void vdma_disable_dma(unsigned int dummy)
+{
+	doing_vdma = 0;
+	virtual_dma_residue += virtual_dma_count;
+	virtual_dma_count=0;
+}
+
+static void vdma_nop(unsigned int dummy)
+{
+}
+
+
+static int vdma_get_dma_residue(unsigned int dummy)
+{
+	return virtual_dma_count + virtual_dma_residue;
+}
+
+
+static int fd_request_irq(void)
+{
+	if (can_use_virtual_dma)
+		return request_irq(FLOPPY_IRQ, floppy_hardint,
+				   IRQF_DISABLED, "floppy", NULL);
+	else
+		return request_irq(FLOPPY_IRQ, floppy_interrupt,
+				   IRQF_DISABLED, "floppy", NULL);
+}
+
+static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
+{
+	doing_vdma = 1;
+	virtual_dma_port = io;
+	virtual_dma_mode = (mode  == DMA_MODE_WRITE);
+	virtual_dma_addr = addr;
+	virtual_dma_count = size;
+	virtual_dma_residue = 0;
+	return 0;
+}
+
+static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
 {
 	static unsigned long prev_size;
 	static dma_addr_t bus_addr = 0;
@@ -46,6 +133,7 @@
 	static int prev_dir;
 	int dir;
 
+	doing_vdma = 0;
 	dir = (mode == DMA_MODE_READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE;
 
 	if (bus_addr 
@@ -74,11 +162,32 @@
 	return 0;
 }
 
-#endif /* CONFIG_PCI */
-
-__inline__ void virtual_dma_init(void)
+static struct fd_dma_ops real_dma_ops =
 {
-	/* Nothing to do on PowerPC */
+	._disable_dma = disable_dma,
+	._free_dma = free_dma,
+	._get_dma_residue = get_dma_residue,
+	._dma_setup = hard_dma_setup
+};
+
+static struct fd_dma_ops virt_dma_ops =
+{
+	._disable_dma = vdma_disable_dma,
+	._free_dma = vdma_nop,
+	._get_dma_residue = vdma_get_dma_residue,
+	._dma_setup = vdma_dma_setup
+};
+
+static int fd_request_dma()
+{
+	if (can_use_virtual_dma & 1) {
+		fd_ops = &virt_dma_ops;
+		return 0;
+	}
+	else {
+		fd_ops = &real_dma_ops;
+		return request_dma(FLOPPY_DMA, "floppy");
+	}
 }
 
 static int FDC1 = 0x3f0;
diff --git a/include/asm-powerpc/pmi.h b/include/asm-powerpc/pmi.h
new file mode 100644
index 0000000..cb0f8aa
--- /dev/null
+++ b/include/asm-powerpc/pmi.h
@@ -0,0 +1,67 @@
+#ifndef _POWERPC_PMI_H
+#define _POWERPC_PMI_H
+
+/*
+ * Definitions for talking with PMI device on PowerPC
+ *
+ * PMI (Platform Management Interrupt) is a way to communicate
+ * with the BMC (Baseboard Management Controller) via interrupts.
+ * Unlike IPMI it is bidirectional and has a low latency.
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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.
+ */
+
+#ifdef __KERNEL__
+
+#include <asm/of_device.h>
+
+#define PMI_TYPE_FREQ_CHANGE	0x01
+#define PMI_READ_TYPE		0
+#define PMI_READ_DATA0		1
+#define PMI_READ_DATA1		2
+#define PMI_READ_DATA2		3
+#define PMI_WRITE_TYPE		4
+#define PMI_WRITE_DATA0		5
+#define PMI_WRITE_DATA1		6
+#define PMI_WRITE_DATA2		7
+
+#define PMI_ACK			0x80
+
+#define PMI_TIMEOUT		100
+
+typedef struct {
+	u8	type;
+	u8	data0;
+	u8	data1;
+	u8	data2;
+} pmi_message_t;
+
+struct pmi_handler {
+	struct list_head node;
+	u8 type;
+	void (*handle_pmi_message) (struct of_device *, pmi_message_t);
+};
+
+void pmi_register_handler(struct of_device *, struct pmi_handler *);
+void pmi_unregister_handler(struct of_device *, struct pmi_handler *);
+
+void pmi_send_message(struct of_device *, pmi_message_t);
+
+#endif /* __KERNEL__ */
+#endif /* _POWERPC_PMI_H */
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 0afee17..020ed01 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -255,6 +255,8 @@
 /* CPU OF node matching */
 struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
 
+/* Get the MAC address */
+extern const void *of_get_mac_address(struct device_node *np);
 
 /*
  * OF interrupt mapping
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index 4f5a1e0..821581a 100644
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -355,13 +355,7 @@
 
 /* vuart routines */
 
-struct ps3_vuart_stats {
-	unsigned long bytes_written;
-	unsigned long bytes_read;
-	unsigned long tx_interrupts;
-	unsigned long rx_interrupts;
-	unsigned long disconnect_interrupts;
-};
+struct ps3_vuart_port_priv;
 
 /**
  * struct ps3_vuart_port_device - a device on a vuart port
@@ -370,22 +364,24 @@
 struct ps3_vuart_port_device {
 	enum ps3_match_id match_id;
 	struct device core;
+	struct ps3_vuart_port_priv* priv; /* private driver variables */
 
-	/* private driver variables */
-	unsigned int port_number;
-	u64 interrupt_mask;
-	struct {
-		spinlock_t lock;
-		struct list_head head;
-	} tx_list;
-	struct {
-		unsigned long bytes_held;
-		spinlock_t lock;
-		struct list_head head;
-	} rx_list;
-	struct ps3_vuart_stats stats;
 };
 
 int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
 
+/* system manager */
+
+void ps3_sys_manager_restart(void);
+void ps3_sys_manager_power_off(void);
+
+struct ps3_prealloc {
+    const char *name;
+    void *address;
+    unsigned long size;
+    unsigned long align;
+};
+
+extern struct ps3_prealloc ps3fb_videomemory;
+
 #endif
diff --git a/include/asm-powerpc/ps3av.h b/include/asm-powerpc/ps3av.h
new file mode 100644
index 0000000..43e90ea
--- /dev/null
+++ b/include/asm-powerpc/ps3av.h
@@ -0,0 +1,738 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony 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; version 2 of the License.
+ *
+ * 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 _ASM_POWERPC_PS3AV_H_
+#define _ASM_POWERPC_PS3AV_H_
+
+#include <linux/mutex.h>
+
+/** command for ioctl() **/
+#define PS3AV_VERSION 0x205	/* version of ps3av command */
+
+#define PS3AV_CID_AV_INIT              0x00000001
+#define PS3AV_CID_AV_FIN               0x00000002
+#define PS3AV_CID_AV_GET_HW_CONF       0x00000003
+#define PS3AV_CID_AV_GET_MONITOR_INFO  0x00000004
+#define PS3AV_CID_AV_ENABLE_EVENT      0x00000006
+#define PS3AV_CID_AV_DISABLE_EVENT     0x00000007
+#define PS3AV_CID_AV_TV_MUTE           0x0000000a
+
+#define PS3AV_CID_AV_VIDEO_CS          0x00010001
+#define PS3AV_CID_AV_VIDEO_MUTE        0x00010002
+#define PS3AV_CID_AV_VIDEO_DISABLE_SIG 0x00010003
+#define PS3AV_CID_AV_AUDIO_PARAM       0x00020001
+#define PS3AV_CID_AV_AUDIO_MUTE        0x00020002
+#define PS3AV_CID_AV_HDMI_MODE         0x00040001
+
+#define PS3AV_CID_VIDEO_INIT           0x01000001
+#define PS3AV_CID_VIDEO_MODE           0x01000002
+#define PS3AV_CID_VIDEO_FORMAT         0x01000004
+#define PS3AV_CID_VIDEO_PITCH          0x01000005
+
+#define PS3AV_CID_AUDIO_INIT           0x02000001
+#define PS3AV_CID_AUDIO_MODE           0x02000002
+#define PS3AV_CID_AUDIO_MUTE           0x02000003
+#define PS3AV_CID_AUDIO_ACTIVE         0x02000004
+#define PS3AV_CID_AUDIO_INACTIVE       0x02000005
+#define PS3AV_CID_AUDIO_SPDIF_BIT      0x02000006
+#define PS3AV_CID_AUDIO_CTRL           0x02000007
+
+#define PS3AV_CID_EVENT_UNPLUGGED      0x10000001
+#define PS3AV_CID_EVENT_PLUGGED        0x10000002
+#define PS3AV_CID_EVENT_HDCP_DONE      0x10000003
+#define PS3AV_CID_EVENT_HDCP_FAIL      0x10000004
+#define PS3AV_CID_EVENT_HDCP_AUTH      0x10000005
+#define PS3AV_CID_EVENT_HDCP_ERROR     0x10000006
+
+#define PS3AV_CID_AVB_PARAM            0x04000001
+
+/* max backend ports */
+#define PS3AV_HDMI_MAX                 2	/* HDMI_0 HDMI_1 */
+#define PS3AV_AVMULTI_MAX              1	/* AVMULTI_0 */
+#define PS3AV_AV_PORT_MAX              (PS3AV_HDMI_MAX + PS3AV_AVMULTI_MAX)
+#define PS3AV_OPT_PORT_MAX             1	/* SPDIF0 */
+#define PS3AV_HEAD_MAX                 2	/* HEAD_A HEAD_B */
+
+/* num of pkt for PS3AV_CID_AVB_PARAM */
+#define PS3AV_AVB_NUM_VIDEO            PS3AV_HEAD_MAX
+#define PS3AV_AVB_NUM_AUDIO            0	/* not supported */
+#define PS3AV_AVB_NUM_AV_VIDEO         PS3AV_AV_PORT_MAX
+#define PS3AV_AVB_NUM_AV_AUDIO         PS3AV_HDMI_MAX
+
+#define PS3AV_MUTE_PORT_MAX            1	/* num of ports in mute pkt */
+
+/* event_bit */
+#define PS3AV_CMD_EVENT_BIT_UNPLUGGED			(1 << 0)
+#define PS3AV_CMD_EVENT_BIT_PLUGGED			(1 << 1)
+#define PS3AV_CMD_EVENT_BIT_HDCP_DONE			(1 << 2)
+#define PS3AV_CMD_EVENT_BIT_HDCP_FAIL			(1 << 3)
+#define PS3AV_CMD_EVENT_BIT_HDCP_REAUTH			(1 << 4)
+#define PS3AV_CMD_EVENT_BIT_HDCP_TOPOLOGY		(1 << 5)
+
+/* common params */
+/* mute */
+#define PS3AV_CMD_MUTE_OFF				0x0000
+#define PS3AV_CMD_MUTE_ON				0x0001
+/* avport */
+#define PS3AV_CMD_AVPORT_HDMI_0				0x0000
+#define PS3AV_CMD_AVPORT_HDMI_1				0x0001
+#define PS3AV_CMD_AVPORT_AVMULTI_0			0x0010
+#define PS3AV_CMD_AVPORT_SPDIF_0			0x0020
+#define PS3AV_CMD_AVPORT_SPDIF_1			0x0021
+
+/* for av backend */
+/* av_mclk */
+#define PS3AV_CMD_AV_MCLK_128				0x0000
+#define PS3AV_CMD_AV_MCLK_256				0x0001
+#define PS3AV_CMD_AV_MCLK_512				0x0003
+/* av_inputlen */
+#define PS3AV_CMD_AV_INPUTLEN_16			0x02
+#define PS3AV_CMD_AV_INPUTLEN_20			0x0a
+#define PS3AV_CMD_AV_INPUTLEN_24			0x0b
+/* alayout */
+#define PS3AV_CMD_AV_LAYOUT_32				(1 << 0)
+#define PS3AV_CMD_AV_LAYOUT_44				(1 << 1)
+#define PS3AV_CMD_AV_LAYOUT_48				(1 << 2)
+#define PS3AV_CMD_AV_LAYOUT_88				(1 << 3)
+#define PS3AV_CMD_AV_LAYOUT_96				(1 << 4)
+#define PS3AV_CMD_AV_LAYOUT_176				(1 << 5)
+#define PS3AV_CMD_AV_LAYOUT_192				(1 << 6)
+/* hdmi_mode */
+#define PS3AV_CMD_AV_HDMI_MODE_NORMAL			0xff
+#define PS3AV_CMD_AV_HDMI_HDCP_OFF			0x01
+#define PS3AV_CMD_AV_HDMI_EDID_PASS			0x80
+#define PS3AV_CMD_AV_HDMI_DVI				0x40
+
+/* for video module */
+/* video_head */
+#define PS3AV_CMD_VIDEO_HEAD_A				0x0000
+#define PS3AV_CMD_VIDEO_HEAD_B				0x0001
+/* video_cs_out video_cs_in */
+#define PS3AV_CMD_VIDEO_CS_NONE				0x0000
+#define PS3AV_CMD_VIDEO_CS_RGB_8			0x0001
+#define PS3AV_CMD_VIDEO_CS_YUV444_8			0x0002
+#define PS3AV_CMD_VIDEO_CS_YUV422_8			0x0003
+#define PS3AV_CMD_VIDEO_CS_XVYCC_8			0x0004
+#define PS3AV_CMD_VIDEO_CS_RGB_10			0x0005
+#define PS3AV_CMD_VIDEO_CS_YUV444_10			0x0006
+#define PS3AV_CMD_VIDEO_CS_YUV422_10			0x0007
+#define PS3AV_CMD_VIDEO_CS_XVYCC_10			0x0008
+#define PS3AV_CMD_VIDEO_CS_RGB_12			0x0009
+#define PS3AV_CMD_VIDEO_CS_YUV444_12			0x000a
+#define PS3AV_CMD_VIDEO_CS_YUV422_12			0x000b
+#define PS3AV_CMD_VIDEO_CS_XVYCC_12			0x000c
+/* video_vid */
+#define PS3AV_CMD_VIDEO_VID_NONE			0x0000
+#define PS3AV_CMD_VIDEO_VID_480I			0x0001
+#define PS3AV_CMD_VIDEO_VID_576I			0x0003
+#define PS3AV_CMD_VIDEO_VID_480P			0x0005
+#define PS3AV_CMD_VIDEO_VID_576P			0x0006
+#define PS3AV_CMD_VIDEO_VID_1080I_60HZ			0x0007
+#define PS3AV_CMD_VIDEO_VID_1080I_50HZ			0x0008
+#define PS3AV_CMD_VIDEO_VID_720P_60HZ			0x0009
+#define PS3AV_CMD_VIDEO_VID_720P_50HZ			0x000a
+#define PS3AV_CMD_VIDEO_VID_1080P_60HZ			0x000b
+#define PS3AV_CMD_VIDEO_VID_1080P_50HZ			0x000c
+#define PS3AV_CMD_VIDEO_VID_WXGA			0x000d
+#define PS3AV_CMD_VIDEO_VID_SXGA			0x000e
+#define PS3AV_CMD_VIDEO_VID_WUXGA			0x000f
+#define PS3AV_CMD_VIDEO_VID_480I_A			0x0010
+/* video_format */
+#define PS3AV_CMD_VIDEO_FORMAT_BLACK			0x0000
+#define PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT		0x0007
+/* video_order */
+#define PS3AV_CMD_VIDEO_ORDER_RGB			0x0000
+#define PS3AV_CMD_VIDEO_ORDER_BGR			0x0001
+/* video_fmt */
+#define PS3AV_CMD_VIDEO_FMT_X8R8G8B8			0x0000
+/* video_out_format */
+#define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT		0x0000
+/* video_sync */
+#define PS3AV_CMD_VIDEO_SYNC_VSYNC			0x0001
+#define PS3AV_CMD_VIDEO_SYNC_CSYNC			0x0004
+#define PS3AV_CMD_VIDEO_SYNC_HSYNC			0x0010
+
+/* for audio module */
+/* num_of_ch */
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_2			0x0000
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_3			0x0001
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_4			0x0002
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_5			0x0003
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_6			0x0004
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_7			0x0005
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_8			0x0006
+/* audio_fs */
+#define PS3AV_CMD_AUDIO_FS_32K				0x0001
+#define PS3AV_CMD_AUDIO_FS_44K				0x0002
+#define PS3AV_CMD_AUDIO_FS_48K				0x0003
+#define PS3AV_CMD_AUDIO_FS_88K				0x0004
+#define PS3AV_CMD_AUDIO_FS_96K				0x0005
+#define PS3AV_CMD_AUDIO_FS_176K				0x0006
+#define PS3AV_CMD_AUDIO_FS_192K				0x0007
+/* audio_word_bits */
+#define PS3AV_CMD_AUDIO_WORD_BITS_16			0x0001
+#define PS3AV_CMD_AUDIO_WORD_BITS_20			0x0002
+#define PS3AV_CMD_AUDIO_WORD_BITS_24			0x0003
+/* audio_format */
+#define PS3AV_CMD_AUDIO_FORMAT_PCM			0x0001
+#define PS3AV_CMD_AUDIO_FORMAT_BITSTREAM		0x00ff
+/* audio_source */
+#define PS3AV_CMD_AUDIO_SOURCE_SERIAL			0x0000
+#define PS3AV_CMD_AUDIO_SOURCE_SPDIF			0x0001
+/* audio_swap */
+#define PS3AV_CMD_AUDIO_SWAP_0				0x0000
+#define PS3AV_CMD_AUDIO_SWAP_1				0x0000
+/* audio_map */
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_0			0x0000
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_1			0x0001
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_2			0x0002
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_3			0x0003
+/* audio_layout */
+#define PS3AV_CMD_AUDIO_LAYOUT_2CH			0x0000
+#define PS3AV_CMD_AUDIO_LAYOUT_6CH			0x000b	/* LREClr */
+#define PS3AV_CMD_AUDIO_LAYOUT_8CH			0x001f	/* LREClrXY */
+/* audio_downmix */
+#define PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED		0x0000
+#define PS3AV_CMD_AUDIO_DOWNMIX_PROHIBITED		0x0001
+
+/* audio_port */
+#define PS3AV_CMD_AUDIO_PORT_HDMI_0			( 1 << 0 )
+#define PS3AV_CMD_AUDIO_PORT_HDMI_1			( 1 << 1 )
+#define PS3AV_CMD_AUDIO_PORT_AVMULTI_0			( 1 << 10 )
+#define PS3AV_CMD_AUDIO_PORT_SPDIF_0			( 1 << 20 )
+#define PS3AV_CMD_AUDIO_PORT_SPDIF_1			( 1 << 21 )
+
+/* audio_ctrl_id */
+#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_RESET		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_DE_EMPHASIS		0x0001
+#define PS3AV_CMD_AUDIO_CTRL_ID_AVCLK			0x0002
+/* audio_ctrl_data[0] reset */
+#define PS3AV_CMD_AUDIO_CTRL_RESET_NEGATE		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_RESET_ASSERT		0x0001
+/* audio_ctrl_data[0] de-emphasis */
+#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_OFF		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_ON		0x0001
+/* audio_ctrl_data[0] avclk */
+#define PS3AV_CMD_AUDIO_CTRL_AVCLK_22			0x0000
+#define PS3AV_CMD_AUDIO_CTRL_AVCLK_18			0x0001
+
+/* av_vid */
+/* do not use these params directly, use vid_video2av */
+#define PS3AV_CMD_AV_VID_480I				0x0000
+#define PS3AV_CMD_AV_VID_480P				0x0001
+#define PS3AV_CMD_AV_VID_720P_60HZ			0x0002
+#define PS3AV_CMD_AV_VID_1080I_60HZ			0x0003
+#define PS3AV_CMD_AV_VID_1080P_60HZ			0x0004
+#define PS3AV_CMD_AV_VID_576I				0x0005
+#define PS3AV_CMD_AV_VID_576P				0x0006
+#define PS3AV_CMD_AV_VID_720P_50HZ			0x0007
+#define PS3AV_CMD_AV_VID_1080I_50HZ			0x0008
+#define PS3AV_CMD_AV_VID_1080P_50HZ			0x0009
+#define PS3AV_CMD_AV_VID_WXGA				0x000a
+#define PS3AV_CMD_AV_VID_SXGA				0x000b
+#define PS3AV_CMD_AV_VID_WUXGA				0x000c
+/* av_cs_out av_cs_in */
+/* use cs_video2av() */
+#define PS3AV_CMD_AV_CS_RGB_8				0x0000
+#define PS3AV_CMD_AV_CS_YUV444_8			0x0001
+#define PS3AV_CMD_AV_CS_YUV422_8			0x0002
+#define PS3AV_CMD_AV_CS_XVYCC_8				0x0003
+#define PS3AV_CMD_AV_CS_RGB_10				0x0004
+#define PS3AV_CMD_AV_CS_YUV444_10			0x0005
+#define PS3AV_CMD_AV_CS_YUV422_10			0x0006
+#define PS3AV_CMD_AV_CS_XVYCC_10			0x0007
+#define PS3AV_CMD_AV_CS_RGB_12				0x0008
+#define PS3AV_CMD_AV_CS_YUV444_12			0x0009
+#define PS3AV_CMD_AV_CS_YUV422_12			0x000a
+#define PS3AV_CMD_AV_CS_XVYCC_12			0x000b
+#define PS3AV_CMD_AV_CS_8				0x0000
+#define PS3AV_CMD_AV_CS_10				0x0001
+#define PS3AV_CMD_AV_CS_12				0x0002
+/* dither */
+#define PS3AV_CMD_AV_DITHER_OFF				0x0000
+#define PS3AV_CMD_AV_DITHER_ON				0x0001
+#define PS3AV_CMD_AV_DITHER_8BIT			0x0000
+#define PS3AV_CMD_AV_DITHER_10BIT			0x0002
+#define PS3AV_CMD_AV_DITHER_12BIT			0x0004
+/* super_white */
+#define PS3AV_CMD_AV_SUPER_WHITE_OFF			0x0000
+#define PS3AV_CMD_AV_SUPER_WHITE_ON			0x0001
+/* aspect */
+#define PS3AV_CMD_AV_ASPECT_16_9			0x0000
+#define PS3AV_CMD_AV_ASPECT_4_3				0x0001
+/* video_cs_cnv() */
+#define PS3AV_CMD_VIDEO_CS_RGB				0x0001
+#define PS3AV_CMD_VIDEO_CS_YUV422			0x0002
+#define PS3AV_CMD_VIDEO_CS_YUV444			0x0003
+
+/* for automode */
+#define PS3AV_RESBIT_720x480P			0x0003	/* 0x0001 | 0x0002 */
+#define PS3AV_RESBIT_720x576P			0x0003	/* 0x0001 | 0x0002 */
+#define PS3AV_RESBIT_1280x720P			0x0004
+#define PS3AV_RESBIT_1920x1080I			0x0008
+#define PS3AV_RESBIT_1920x1080P			0x4000
+#define PS3AV_RES_MASK_60			(PS3AV_RESBIT_720x480P \
+						| PS3AV_RESBIT_1280x720P \
+						| PS3AV_RESBIT_1920x1080I \
+						| PS3AV_RESBIT_1920x1080P)
+#define PS3AV_RES_MASK_50			(PS3AV_RESBIT_720x576P \
+						| PS3AV_RESBIT_1280x720P \
+						| PS3AV_RESBIT_1920x1080I \
+						| PS3AV_RESBIT_1920x1080P)
+
+#define PS3AV_MONITOR_TYPE_HDMI			1	/* HDMI */
+#define PS3AV_MONITOR_TYPE_DVI			2	/* DVI */
+#define PS3AV_DEFAULT_HDMI_VID_REG_60		PS3AV_CMD_VIDEO_VID_480P
+#define PS3AV_DEFAULT_AVMULTI_VID_REG_60	PS3AV_CMD_VIDEO_VID_480I
+#define PS3AV_DEFAULT_HDMI_VID_REG_50		PS3AV_CMD_VIDEO_VID_576P
+#define PS3AV_DEFAULT_AVMULTI_VID_REG_50	PS3AV_CMD_VIDEO_VID_576I
+#define PS3AV_DEFAULT_DVI_VID			PS3AV_CMD_VIDEO_VID_480P
+
+#define PS3AV_REGION_60				0x01
+#define PS3AV_REGION_50				0x02
+#define PS3AV_REGION_RGB			0x10
+
+#define get_status(buf)				(((__u32 *)buf)[2])
+#define PS3AV_HDR_SIZE				4	/* version + size */
+
+/* for video mode */
+#define PS3AV_MODE_MASK				0x000F
+#define PS3AV_MODE_HDCP_OFF			0x1000	/* Retail PS3 product doesn't support this */
+#define PS3AV_MODE_DITHER			0x0800
+#define PS3AV_MODE_FULL				0x0080
+#define PS3AV_MODE_DVI				0x0040
+#define PS3AV_MODE_RGB				0x0020
+
+
+/** command packet structure **/
+struct ps3av_send_hdr {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+};
+
+struct ps3av_reply_hdr {
+	u16 version;
+	u16 size;
+	u32 cid;
+	u32 status;
+};
+
+/* backend: initialization */
+struct ps3av_pkt_av_init {
+	struct ps3av_send_hdr send_hdr;
+	u32 event_bit;
+};
+
+/* backend: finalize */
+struct ps3av_pkt_av_fin {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* backend: get port */
+struct ps3av_pkt_av_get_hw_conf {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 status;
+	u16 num_of_hdmi;	/* out: number of hdmi */
+	u16 num_of_avmulti;	/* out: number of avmulti */
+	u16 num_of_spdif;	/* out: number of hdmi */
+	u16 reserved;
+};
+
+/* backend: get monitor info */
+struct ps3av_info_resolution {
+	u32 res_bits;
+	u32 native;
+};
+
+struct ps3av_info_cs {
+	u8 rgb;
+	u8 yuv444;
+	u8 yuv422;
+	u8 reserved;
+};
+
+struct ps3av_info_color {
+	u16 red_x;
+	u16 red_y;
+	u16 green_x;
+	u16 green_y;
+	u16 blue_x;
+	u16 blue_y;
+	u16 white_x;
+	u16 white_y;
+	u32 gamma;
+};
+
+struct ps3av_info_audio {
+	u8 type;
+	u8 max_num_of_ch;
+	u8 fs;
+	u8 sbit;
+};
+
+struct ps3av_info_monitor {
+	u8 avport;
+	u8 monitor_id[10];
+	u8 monitor_type;
+	u8 monitor_name[16];
+	struct ps3av_info_resolution res_60;
+	struct ps3av_info_resolution res_50;
+	struct ps3av_info_resolution res_other;
+	struct ps3av_info_resolution res_vesa;
+	struct ps3av_info_cs cs;
+	struct ps3av_info_color color;
+	u8 supported_ai;
+	u8 speaker_info;
+	u8 num_of_audio_block;
+	struct ps3av_info_audio audio[0];	/* 0 or more audio blocks */
+	u8 reserved[169];
+} __attribute__ ((packed));
+
+struct ps3av_pkt_av_get_monitor_info {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+	/* recv */
+	struct ps3av_info_monitor info;	/* out: monitor info */
+};
+
+/* backend: enable/disable event */
+struct ps3av_pkt_av_event {
+	struct ps3av_send_hdr send_hdr;
+	u32 event_bit;		/* in */
+};
+
+/* backend: video cs param */
+struct ps3av_pkt_av_video_cs {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 av_vid;		/* in: video resolution */
+	u16 av_cs_out;		/* in: output color space */
+	u16 av_cs_in;		/* in: input color space */
+	u8 dither;		/* in: dither bit length */
+	u8 bitlen_out;		/* in: bit length */
+	u8 super_white;		/* in: super white */
+	u8 aspect;		/* in: aspect ratio */
+};
+
+/* backend: video mute */
+struct ps3av_av_mute {
+	u16 avport;		/* in: avport */
+	u16 mute;		/* in: mute on/off */
+};
+
+struct ps3av_pkt_av_video_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX];
+};
+
+/* backend: video disable signal */
+struct ps3av_pkt_av_video_disable_sig {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+};
+
+/* backend: audio param */
+struct ps3av_audio_info_frame {
+	struct pb1_bit {
+		u8 ct:4;
+		u8 rsv:1;
+		u8 cc:3;
+	} pb1;
+	struct pb2_bit {
+		u8 rsv:3;
+		u8 sf:3;
+		u8 ss:2;
+	} pb2;
+	u8 pb3;
+	u8 pb4;
+	struct pb5_bit {
+		u8 dm:1;
+		u8 lsv:4;
+		u8 rsv:3;
+	} pb5;
+};
+
+struct ps3av_pkt_av_audio_param {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+	u8 mclk;		/* in: audio mclk */
+	u8 ns[3];		/* in: audio ns val */
+	u8 enable;		/* in: audio enable */
+	u8 swaplr;		/* in: audio swap */
+	u8 fifomap;		/* in: audio fifomap */
+	u8 inputctrl;		/* in: audio input ctrl */
+	u8 inputlen;		/* in: sample bit size */
+	u8 layout;		/* in: speaker layout param */
+	struct ps3av_audio_info_frame info;	/* in: info */
+	u8 chstat[5];		/* in: ch stat */
+};
+
+/* backend: audio_mute */
+struct ps3av_pkt_av_audio_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX];
+};
+
+/* backend: hdmi_mode */
+struct ps3av_pkt_av_hdmi_mode {
+	struct ps3av_send_hdr send_hdr;
+	u8 mode;		/* in: hdmi_mode */
+	u8 reserved0;
+	u8 reserved1;
+	u8 reserved2;
+};
+
+/* backend: tv_mute */
+struct ps3av_pkt_av_tv_mute {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport HDMI only */
+	u16 mute;		/* in: mute */
+};
+
+/* video: initialize */
+struct ps3av_pkt_video_init {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* video: mode setting */
+struct ps3av_pkt_video_mode {
+	struct ps3av_send_hdr send_hdr;
+	u32 video_head;		/* in: head */
+	u32 reserved;
+	u32 video_vid;		/* in: video resolution */
+	u16 reserved1;
+	u16 width;		/* in: width in pixel */
+	u16 reserved2;
+	u16 height;		/* in: height in pixel */
+	u32 pitch;		/* in: line size in byte */
+	u32 video_out_format;	/* in: out format */
+	u32 video_format;	/* in: input frame buffer format */
+	u8 reserved3;
+	u8 reserved4;
+	u16 video_order;	/* in: input RGB order */
+	u32 reserved5;
+};
+
+/* video: format */
+struct ps3av_pkt_video_format {
+	struct ps3av_send_hdr send_hdr;
+	u32 video_head;		/* in: head */
+	u32 video_format;	/* in: frame buffer format */
+	u16 reserved;
+	u16 video_order;	/* in: input RGB order */
+};
+
+/* video: pitch */
+struct ps3av_pkt_video_pitch {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u32 video_head;		/* in: head */
+	u32 pitch;		/* in: line size in byte */
+};
+
+/* audio: initialize */
+struct ps3av_pkt_audio_init {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* audio: mode setting */
+struct ps3av_pkt_audio_mode {
+	struct ps3av_send_hdr send_hdr;
+	u8 avport;		/* in: avport */
+	u8 reserved0[3];
+	u32 mask;		/* in: mask */
+	u32 audio_num_of_ch;	/* in: number of ch */
+	u32 audio_fs;		/* in: sampling freq */
+	u32 audio_word_bits;	/* in: sample bit size */
+	u32 audio_format;	/* in: audio output format */
+	u32 audio_source;	/* in: audio source */
+	u8 audio_enable[4];	/* in: audio enable */
+	u8 audio_swap[4];	/* in: audio swap */
+	u8 audio_map[4];	/* in: audio map */
+	u32 audio_layout;	/* in: speaker layout */
+	u32 audio_downmix;	/* in: audio downmix permission */
+	u32 audio_downmix_level;
+	u8 audio_cs_info[8];	/* in: IEC channel status */
+};
+
+/* audio: mute */
+struct ps3av_audio_mute {
+	u8 avport;		/* in: opt_port optical */
+	u8 reserved[3];
+	u32 mute;		/* in: mute */
+};
+
+struct ps3av_pkt_audio_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_audio_mute mute[PS3AV_OPT_PORT_MAX];
+};
+
+/* audio: active/inactive */
+struct ps3av_pkt_audio_active {
+	struct ps3av_send_hdr send_hdr;
+	u32 audio_port;		/* in: audio active/inactive port */
+};
+
+/* audio: SPDIF user bit */
+struct ps3av_pkt_audio_spdif_bit {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u8 avport;		/* in: avport SPDIF only */
+	u8 reserved[3];
+	u32 audio_port;		/* in: SPDIF only */
+	u32 spdif_bit_data[12];	/* in: user bit data */
+};
+
+/* audio: audio control */
+struct ps3av_pkt_audio_ctrl {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u32 audio_ctrl_id;	/* in: control id */
+	u32 audio_ctrl_data[4];	/* in: control data */
+};
+
+/* avb:param */
+#define PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE	\
+	(PS3AV_AVB_NUM_VIDEO*sizeof(struct ps3av_pkt_video_mode) + \
+	 PS3AV_AVB_NUM_AUDIO*sizeof(struct ps3av_pkt_audio_mode) + \
+	 PS3AV_AVB_NUM_AV_VIDEO*sizeof(struct ps3av_pkt_av_video_cs) + \
+	 PS3AV_AVB_NUM_AV_AUDIO*sizeof(struct ps3av_pkt_av_audio_param))
+
+struct ps3av_pkt_avb_param {
+	struct ps3av_send_hdr send_hdr;
+	u16 num_of_video_pkt;
+	u16 num_of_audio_pkt;
+	u16 num_of_av_video_pkt;
+	u16 num_of_av_audio_pkt;
+	/*
+	 * The actual buffer layout depends on the fields above:
+	 *
+	 * struct ps3av_pkt_video_mode video[num_of_video_pkt];
+	 * struct ps3av_pkt_audio_mode audio[num_of_audio_pkt];
+	 * struct ps3av_pkt_av_video_cs av_video[num_of_av_video_pkt];
+	 * struct ps3av_pkt_av_audio_param av_audio[num_of_av_audio_pkt];
+	 */
+	u8 buf[PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE];
+};
+
+struct ps3av {
+	int available;
+	struct semaphore sem;
+	struct semaphore ping;
+	struct semaphore pong;
+	struct mutex mutex;
+	int open_count;
+	struct ps3_vuart_port_device *dev;
+
+	int region;
+	struct ps3av_pkt_av_get_hw_conf av_hw_conf;
+	u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX];
+	u32 opt_port[PS3AV_OPT_PORT_MAX];
+	u32 head[PS3AV_HEAD_MAX];
+	u32 audio_port;
+	int ps3av_mode;
+	int ps3av_mode_old;
+};
+
+/** command status **/
+#define PS3AV_STATUS_SUCCESS			0x0000	/* success */
+#define PS3AV_STATUS_RECEIVE_VUART_ERROR	0x0001	/* receive vuart error */
+#define PS3AV_STATUS_SYSCON_COMMUNICATE_FAIL	0x0002	/* syscon communication error */
+#define PS3AV_STATUS_INVALID_COMMAND		0x0003	/* obsolete invalid CID */
+#define PS3AV_STATUS_INVALID_PORT		0x0004	/* invalid port number */
+#define PS3AV_STATUS_INVALID_VID		0x0005	/* invalid video format */
+#define PS3AV_STATUS_INVALID_COLOR_SPACE	0x0006	/* invalid video colose space */
+#define PS3AV_STATUS_INVALID_FS			0x0007	/* invalid audio sampling freq */
+#define PS3AV_STATUS_INVALID_AUDIO_CH		0x0008	/* invalid audio channel number */
+#define PS3AV_STATUS_UNSUPPORTED_VERSION	0x0009	/* version mismatch  */
+#define PS3AV_STATUS_INVALID_SAMPLE_SIZE	0x000a	/* invalid audio sample bit size */
+#define PS3AV_STATUS_FAILURE			0x000b	/* other failures */
+#define PS3AV_STATUS_UNSUPPORTED_COMMAND	0x000c	/* unsupported cid */
+#define PS3AV_STATUS_BUFFER_OVERFLOW		0x000d	/* write buffer overflow */
+#define PS3AV_STATUS_INVALID_VIDEO_PARAM	0x000e	/* invalid video param */
+#define PS3AV_STATUS_NO_SEL			0x000f	/* not exist selector */
+#define PS3AV_STATUS_INVALID_AV_PARAM		0x0010	/* invalid backend param */
+#define PS3AV_STATUS_INVALID_AUDIO_PARAM	0x0011	/* invalid audio param */
+#define PS3AV_STATUS_UNSUPPORTED_HDMI_MODE	0x0012	/* unsupported hdmi mode */
+#define PS3AV_STATUS_NO_SYNC_HEAD		0x0013	/* sync head failed */
+
+extern void ps3av_set_hdr(u32, u16, struct ps3av_send_hdr *);
+extern int ps3av_do_pkt(u32, u16, size_t, struct ps3av_send_hdr *);
+
+extern int ps3av_cmd_init(void);
+extern int ps3av_cmd_fin(void);
+extern int ps3av_cmd_av_video_mute(int, u32 *, u32);
+extern int ps3av_cmd_av_video_disable_sig(u32);
+extern int ps3av_cmd_av_tv_mute(u32, u32);
+extern int ps3av_cmd_enable_event(void);
+extern int ps3av_cmd_av_hdmi_mode(u8);
+extern u32 ps3av_cmd_set_av_video_cs(void *, u32, int, int, int, u32);
+extern u32 ps3av_cmd_set_video_mode(void *, u32, int, int, u32);
+extern int ps3av_cmd_video_format_black(u32, u32, u32);
+extern int ps3av_cmd_av_audio_mute(int, u32 *, u32);
+extern u32 ps3av_cmd_set_av_audio_param(void *, u32,
+					const struct ps3av_pkt_audio_mode *,
+					u32);
+extern void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *, u32, u32,
+				     u32, u32, u32, u32);
+extern int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *);
+extern int ps3av_cmd_audio_mute(int, u32 *, u32);
+extern int ps3av_cmd_audio_active(int, u32);
+extern int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *, u32);
+extern int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *);
+#ifdef PS3AV_DEBUG
+extern void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *);
+extern void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *);
+#else
+static inline void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf) {}
+static inline void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) {}
+#endif
+extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
+					    u32);
+
+extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
+			     const void *buf, unsigned long size);
+extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
+			    unsigned long size, int timeout);
+
+extern int ps3av_set_video_mode(u32, int);
+extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
+extern int ps3av_set_mode(u32, int);
+extern int ps3av_get_mode(void);
+extern int ps3av_get_scanmode(int);
+extern int ps3av_get_refresh_rate(int);
+extern int ps3av_video_mode2res(u32, u32 *, u32 *);
+extern int ps3av_video_mute(int);
+extern int ps3av_audio_mute(int);
+extern int ps3av_dev_open(void);
+extern int ps3av_dev_close(void);
+
+#endif	/* _ASM_POWERPC_PS3AV_H_ */
diff --git a/include/asm-powerpc/ps3fb.h b/include/asm-powerpc/ps3fb.h
new file mode 100644
index 0000000..ad81cf4
--- /dev/null
+++ b/include/asm-powerpc/ps3fb.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony 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; version 2 of the License.
+ *
+ * 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 _ASM_POWERPC_PS3FB_H_
+#define _ASM_POWERPC_PS3FB_H_
+
+#include <linux/ioctl.h>
+
+/* ioctl */
+#define PS3FB_IOCTL_SETMODE       _IOW('r',  1, int) /* set video mode */
+#define PS3FB_IOCTL_GETMODE       _IOR('r',  2, int) /* get video mode */
+#define PS3FB_IOCTL_SCREENINFO    _IOR('r',  3, int) /* get screen info */
+#define PS3FB_IOCTL_ON            _IO('r', 4)        /* use IOCTL_FSEL */
+#define PS3FB_IOCTL_OFF           _IO('r', 5)        /* return to normal-flip */
+#define PS3FB_IOCTL_FSEL          _IOW('r', 6, int)  /* blit and flip request */
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC         _IOW('F', 0x20, __u32) /* wait for vsync */
+#endif
+
+struct ps3fb_ioctl_res {
+	__u32 xres; /* frame buffer x_size */
+	__u32 yres; /* frame buffer y_size */
+	__u32 xoff; /* margine x  */
+	__u32 yoff; /* margine y */
+	__u32 num_frames; /* num of frame buffers */
+};
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_FB_PS3
+extern void ps3fb_flip_ctl(int on);
+extern void ps3fb_cleanup(void);
+#else
+static inline void ps3fb_flip_ctl(int on) {}
+static inline void ps3fb_cleanup(void) {}
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_POWERPC_PS3FB_H_ */
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index b634e16..0f9f2dd2 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -129,7 +129,6 @@
 	struct spu_runqueue *rq;
 	unsigned long long timestamp;
 	pid_t pid;
-	int prio;
 	int class_0_pending;
 	spinlock_t register_lock;
 
diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h
index 97b4354..418e5c7 100644
--- a/include/asm-powerpc/systbl.h
+++ b/include/asm-powerpc/systbl.h
@@ -305,3 +305,4 @@
 COMPAT_SYS_SPU(get_robust_list)
 COMPAT_SYS_SPU(set_robust_list)
 COMPAT_SYS(move_pages)
+SYSCALL_SPU(getcpu)
diff --git a/include/asm-powerpc/termios.h b/include/asm-powerpc/termios.h
index 7f80a01..2c14fea 100644
--- a/include/asm-powerpc/termios.h
+++ b/include/asm-powerpc/termios.h
@@ -71,24 +71,6 @@
 #define _VEOL2	8
 #define _VSWTC	9
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 /*                   ^C  ^\ del  ^U  ^D   1   0   0   0   0  ^W  ^R  ^Z  ^Q  ^S  ^V  ^U  */
 #define INIT_C_CC "\003\034\177\025\004\001\000\000\000\000\027\022\032\021\023\026\025" 
diff --git a/include/asm-powerpc/ucc_slow.h b/include/asm-powerpc/ucc_slow.h
index ca93bc9..fdaac9d7 100644
--- a/include/asm-powerpc/ucc_slow.h
+++ b/include/asm-powerpc/ucc_slow.h
@@ -150,7 +150,7 @@
 	int ucc_num;
 	enum qe_clock rx_clock;
 	enum qe_clock tx_clock;
-	struct ucc_slow *us_regs;
+	u32 regs;
 	int irq;
 	u16 uccm_mask;
 	int data_mem_part;
@@ -199,9 +199,9 @@
 				   and length for first BD in a frame */
 	u32 tx_base_offset;	/* first BD in Tx BD table offset (In MURAM) */
 	u32 rx_base_offset;	/* first BD in Rx BD table offset (In MURAM) */
-	u8 *confBd;		/* next BD for confirm after Tx */
-	u8 *tx_bd;		/* next BD for new Tx request */
-	u8 *rx_bd;		/* next BD to collect after Rx */
+	struct qe_bd *confBd;	/* next BD for confirm after Tx */
+	struct qe_bd *tx_bd;	/* next BD for new Tx request */
+	struct qe_bd *rx_bd;	/* next BD to collect after Rx */
 	void *p_rx_frame;	/* accumulating receive frame */
 	u16 *p_ucce;		/* a pointer to the event register in memory.
 				 */
diff --git a/include/asm-powerpc/udbg.h b/include/asm-powerpc/udbg.h
index 4cbc313..d03d855 100644
--- a/include/asm-powerpc/udbg.h
+++ b/include/asm-powerpc/udbg.h
@@ -46,6 +46,7 @@
 extern void __init udbg_init_rtas_panel(void);
 extern void __init udbg_init_rtas_console(void);
 extern void __init udbg_init_debug_beat(void);
+extern void __init udbg_init_btext(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UDBG_H */
diff --git a/include/asm-powerpc/vdso.h b/include/asm-powerpc/vdso.h
index b9f9118..26fc449 100644
--- a/include/asm-powerpc/vdso.h
+++ b/include/asm-powerpc/vdso.h
@@ -18,16 +18,11 @@
 
 #ifndef __ASSEMBLY__
 
-extern unsigned int vdso64_pages;
-extern unsigned int vdso32_pages;
-
 /* Offsets relative to thread->vdso_base */
 extern unsigned long vdso64_rt_sigtramp;
 extern unsigned long vdso32_sigtramp;
 extern unsigned long vdso32_rt_sigtramp;
 
-extern void vdso_init(void);
-
 #else /* __ASSEMBLY__ */
 
 #ifdef __VDSO64__
diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h
index 7a64ede..92fd02d 100644
--- a/include/asm-ppc/ibm4xx.h
+++ b/include/asm-ppc/ibm4xx.h
@@ -109,6 +109,10 @@
 #include <platforms/4xx/ocotea.h>
 #endif
 
+#if defined(CONFIG_TAISHAN)
+#include <platforms/4xx/taishan.h>
+#endif
+
 #ifndef __ASSEMBLY__
 #ifdef CONFIG_40x
 /*
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index ccf1a9b..95d5904 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -358,8 +358,6 @@
 }
 #endif
 
-#define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),(void __force *)(void __iomem *)(b),(c),(d))
-
 /*
  * Map in an area of physical address space, for accessing
  * I/O devices etc.
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index af20c74..c17bdbf 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -215,6 +215,8 @@
 	       __CSG_LOOP(v, mask, "ogr");
 }
 
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
 static __inline__ long long atomic64_cmpxchg(atomic64_t *v,
 					     long long old, long long new)
 {
diff --git a/include/asm-s390/ccwdev.h b/include/asm-s390/ccwdev.h
index 58c70ac..cfc8153 100644
--- a/include/asm-s390/ccwdev.h
+++ b/include/asm-s390/ccwdev.h
@@ -110,7 +110,9 @@
 
 struct ccw1;
 
+extern int ccw_device_set_options_mask(struct ccw_device *, unsigned long);
 extern int ccw_device_set_options(struct ccw_device *, unsigned long);
+extern void ccw_device_clear_options(struct ccw_device *, unsigned long);
 
 /* Allow for i/o completion notification after primary interrupt status. */
 #define CCWDEV_EARLY_NOTIFICATION	0x0001
diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h
index a4c2d55..b7ff6af 100644
--- a/include/asm-s390/io.h
+++ b/include/asm-s390/io.h
@@ -13,13 +13,10 @@
 
 #ifdef __KERNEL__
 
-#include <linux/vmalloc.h>
 #include <asm/page.h>
 
 #define IO_SPACE_LIMIT 0xffffffff
 
-#define __io_virt(x)            ((void *)(PAGE_OFFSET | (unsigned long)(x)))
-
 /*
  * Change virtual addresses to physical addresses and vv.
  * These are pretty trivial
@@ -38,75 +35,9 @@
 
 static inline void * phys_to_virt(unsigned long address)
 {
-        return __io_virt(address);
+	return (void *) address;
 }
 
-extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
-
-static inline void * ioremap (unsigned long offset, unsigned long size)
-{
-        return __ioremap(offset, size, 0);
-}
-
-/*
- * 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:
- */
-static inline void * ioremap_nocache (unsigned long offset, unsigned long size)
-{
-        return __ioremap(offset, size, 0);
-}
-
-extern void iounmap(void *addr);
-
-/*
- * IO bus memory addresses are also 1:1 with the physical address
- */
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently.
- */
-
-#define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
-#define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
-#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
-#define readq(addr) (*(volatile unsigned long long *) __io_virt(addr))
-
-#define readb_relaxed(addr) readb(addr)
-#define readw_relaxed(addr) readw(addr)
-#define readl_relaxed(addr) readl(addr)
-#define readq_relaxed(addr) readq(addr)
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
-#define __raw_readq readq
-
-#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
-#define writeq(b,addr) (*(volatile unsigned long long *) __io_virt(addr) = (b))
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-#define __raw_writeq writeq
-
-#define memset_io(a,b,c)        memset(__io_virt(a),(b),(c))
-#define memcpy_fromio(a,b,c)    memcpy((a),__io_virt(b),(c))
-#define memcpy_toio(a,b,c)      memcpy(__io_virt(a),(b),(c))
-
-#define inb_p(addr) readb(addr)
-#define inb(addr) readb(addr)
-
-#define outb(x,addr) ((void) writeb(x,addr))
-#define outb_p(x,addr) outb(x,addr)
-
-#define mmiowb()	do { } while (0)
-
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access
diff --git a/include/asm-s390/ipl.h b/include/asm-s390/ipl.h
new file mode 100644
index 0000000..5650d3d
--- /dev/null
+++ b/include/asm-s390/ipl.h
@@ -0,0 +1,113 @@
+/*
+ * s390 (re)ipl support
+ *
+ * Copyright IBM Corp. 2007
+ */
+
+#ifndef _ASM_S390_IPL_H
+#define _ASM_S390_IPL_H
+
+#include <asm/types.h>
+
+#define IPL_PARMBLOCK_ORIGIN	0x2000
+
+#define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
+			      sizeof(struct ipl_block_fcp))
+
+#define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
+			      sizeof(struct ipl_block_ccw))
+
+#define IPL_MAX_SUPPORTED_VERSION (0)
+
+#define IPL_PARMBLOCK_START	((struct ipl_parameter_block *) \
+				 IPL_PARMBLOCK_ORIGIN)
+#define IPL_PARMBLOCK_SIZE	(IPL_PARMBLOCK_START->hdr.len)
+
+struct ipl_list_hdr {
+	u32 len;
+	u8  reserved1[3];
+	u8  version;
+	u32 blk0_len;
+	u8  pbt;
+	u8  flags;
+	u16 reserved2;
+} __attribute__((packed));
+
+struct ipl_block_fcp {
+	u8  reserved1[313-1];
+	u8  opt;
+	u8  reserved2[3];
+	u16 reserved3;
+	u16 devno;
+	u8  reserved4[4];
+	u64 wwpn;
+	u64 lun;
+	u32 bootprog;
+	u8  reserved5[12];
+	u64 br_lba;
+	u32 scp_data_len;
+	u8  reserved6[260];
+	u8  scp_data[];
+} __attribute__((packed));
+
+struct ipl_block_ccw {
+	u8  load_param[8];
+	u8  reserved1[84];
+	u8  reserved2[2];
+	u16 devno;
+	u8  vm_flags;
+	u8  reserved3[3];
+	u32 vm_parm_len;
+} __attribute__((packed));
+
+struct ipl_parameter_block {
+	struct ipl_list_hdr hdr;
+	union {
+		struct ipl_block_fcp fcp;
+		struct ipl_block_ccw ccw;
+	} ipl_info;
+} __attribute__((packed));
+
+/*
+ * IPL validity flags and parameters as detected in head.S
+ */
+extern u32 ipl_flags;
+extern u16 ipl_devno;
+
+extern void do_reipl(void);
+extern void ipl_save_parameters(void);
+
+enum {
+	IPL_DEVNO_VALID		= 1,
+	IPL_PARMBLOCK_VALID	= 2,
+	IPL_NSS_VALID		= 4,
+};
+
+/*
+ * DIAG 308 support
+ */
+enum diag308_subcode  {
+	DIAG308_REL_HSA	= 2,
+	DIAG308_IPL	= 3,
+	DIAG308_DUMP	= 4,
+	DIAG308_SET	= 5,
+	DIAG308_STORE	= 6,
+};
+
+enum diag308_ipl_type {
+	DIAG308_IPL_TYPE_FCP	= 0,
+	DIAG308_IPL_TYPE_CCW	= 2,
+};
+
+enum diag308_opt {
+	DIAG308_IPL_OPT_IPL	= 0x10,
+	DIAG308_IPL_OPT_DUMP	= 0x20,
+};
+
+enum diag308_rc {
+	DIAG308_RC_OK	= 1,
+};
+
+extern int diag308(unsigned long subcode, void *addr);
+
+#endif /* _ASM_S390_IPL_H */
diff --git a/include/asm-s390/local.h b/include/asm-s390/local.h
index 86745a1..c11c530 100644
--- a/include/asm-s390/local.h
+++ b/include/asm-s390/local.h
@@ -1,58 +1 @@
-#ifndef _ASM_LOCAL_H
-#define _ASM_LOCAL_H
-
-#include <linux/percpu.h>
-#include <asm/atomic.h>
-
-#ifndef __s390x__
-
-typedef atomic_t local_t;
-
-#define LOCAL_INIT(i)	ATOMIC_INIT(i)
-#define local_read(v)	atomic_read(v)
-#define local_set(v,i)	atomic_set(v,i)
-
-#define local_inc(v)	atomic_inc(v)
-#define local_dec(v)	atomic_dec(v)
-#define local_add(i, v)	atomic_add(i, v)
-#define local_sub(i, v)	atomic_sub(i, v)
-
-#else
-
-typedef atomic64_t local_t;
-
-#define LOCAL_INIT(i)	ATOMIC64_INIT(i)
-#define local_read(v)	atomic64_read(v)
-#define local_set(v,i)	atomic64_set(v,i)
-
-#define local_inc(v)	atomic64_inc(v)
-#define local_dec(v)	atomic64_dec(v)
-#define local_add(i, v)	atomic64_add(i, v)
-#define local_sub(i, v)	atomic64_sub(i, v)
-
-#endif
-
-#define __local_inc(v)		((v)->counter++)
-#define __local_dec(v)		((v)->counter--)
-#define __local_add(i,v)	((v)->counter+=(i))
-#define __local_sub(i,v)	((v)->counter-=(i))
-
-/*
- * Use these for per-cpu local_t variables: on some archs they are
- * much more efficient than these naive implementations.  Note they take
- * a variable, not an address.
- */
-#define cpu_local_read(v)	local_read(&__get_cpu_var(v))
-#define cpu_local_set(v, i)	local_set(&__get_cpu_var(v), (i))
-
-#define cpu_local_inc(v)	local_inc(&__get_cpu_var(v))
-#define cpu_local_dec(v)	local_dec(&__get_cpu_var(v))
-#define cpu_local_add(i, v)	local_add((i), &__get_cpu_var(v))
-#define cpu_local_sub(i, v)	local_sub((i), &__get_cpu_var(v))
-
-#define __cpu_local_inc(v)	__local_inc(&__get_cpu_var(v))
-#define __cpu_local_dec(v)	__local_dec(&__get_cpu_var(v))
-#define __cpu_local_add(i, v)	__local_add((i), &__get_cpu_var(v))
-#define __cpu_local_sub(i, v)	__local_sub((i), &__get_cpu_var(v))
-
-#endif /* _ASM_LOCAL_H */
+#include <asm-generic/local.h>
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 4c1b739..33b80ce 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -36,6 +36,11 @@
         unsigned int unused  : 16;
 } __attribute__ ((packed)) cpuid_t;
 
+static inline void get_cpu_id(cpuid_t *ptr)
+{
+	asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr));
+}
+
 struct cpuinfo_S390
 {
         cpuid_t  cpu_id;
diff --git a/include/asm-s390/sections.h b/include/asm-s390/sections.h
index 1c5a2c4..fbd9116 100644
--- a/include/asm-s390/sections.h
+++ b/include/asm-s390/sections.h
@@ -3,6 +3,6 @@
 
 #include <asm-generic/sections.h>
 
-extern char _eshared[];
+extern char _eshared[], _ehead[];
 
 #endif
diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h
index 3388bb5..44c7aee 100644
--- a/include/asm-s390/setup.h
+++ b/include/asm-s390/setup.h
@@ -16,7 +16,6 @@
 
 #define PARMAREA		0x10400
 #define MEMORY_CHUNKS		16	/* max 0x7fff */
-#define IPL_PARMBLOCK_ORIGIN	0x2000
 
 #ifndef __ASSEMBLY__
 
@@ -97,82 +96,9 @@
 #define SET_CONSOLE_3215	do { console_mode = 2; } while (0)
 #define SET_CONSOLE_3270	do { console_mode = 3; } while (0)
 
-struct ipl_list_hdr {
-	u32 len;
-	u8  reserved1[3];
-	u8  version;
-	u32 blk0_len;
-	u8  pbt;
-	u8  flags;
-	u16 reserved2;
-} __attribute__((packed));
-
-struct ipl_block_fcp {
-	u8  reserved1[313-1];
-	u8  opt;
-	u8  reserved2[3];
-	u16 reserved3;
-	u16 devno;
-	u8  reserved4[4];
-	u64 wwpn;
-	u64 lun;
-	u32 bootprog;
-	u8  reserved5[12];
-	u64 br_lba;
-	u32 scp_data_len;
-	u8  reserved6[260];
-	u8  scp_data[];
-} __attribute__((packed));
-
-struct ipl_block_ccw {
-	u8  load_param[8];
-	u8  reserved1[84];
-	u8  reserved2[2];
-	u16 devno;
-	u8  vm_flags;
-	u8  reserved3[3];
-	u32 vm_parm_len;
-} __attribute__((packed));
-
-struct ipl_parameter_block {
-	struct ipl_list_hdr hdr;
-	union {
-		struct ipl_block_fcp fcp;
-		struct ipl_block_ccw ccw;
-	} ipl_info;
-} __attribute__((packed));
-
-#define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
-			      sizeof(struct ipl_block_fcp))
-
-#define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
-			      sizeof(struct ipl_block_ccw))
-
-#define IPL_MAX_SUPPORTED_VERSION (0)
-
-/*
- * IPL validity flags and parameters as detected in head.S
- */
-extern u32 ipl_flags;
-extern u16 ipl_devno;
-
-extern void do_reipl(void);
-extern void ipl_save_parameters(void);
-
-enum {
-	IPL_DEVNO_VALID	= 1,
-	IPL_PARMBLOCK_VALID = 2,
-	IPL_NSS_VALID = 4,
-};
-
 #define NSS_NAME_SIZE	8
-
 extern char kernel_nss_name[];
 
-#define IPL_PARMBLOCK_START	((struct ipl_parameter_block *) \
-				 IPL_PARMBLOCK_ORIGIN)
-#define IPL_PARMBLOCK_SIZE	(IPL_PARMBLOCK_START->hdr.len)
-
 #else /* __ASSEMBLY__ */
 
 #ifndef __s390x__
diff --git a/include/asm-s390/termios.h b/include/asm-s390/termios.h
index 62b23ca..a3480e2 100644
--- a/include/asm-s390/termios.h
+++ b/include/asm-s390/termios.h
@@ -47,24 +47,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*	intr=^C		quit=^\		erase=del	kill=^U
diff --git a/include/asm-sh/Kbuild b/include/asm-sh/Kbuild
index c68e168..76a8ccf 100644
--- a/include/asm-sh/Kbuild
+++ b/include/asm-sh/Kbuild
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+header-y += cpu-features.h
diff --git a/include/asm-sh/apm.h b/include/asm-sh/apm.h
deleted file mode 100644
index 8b091e9..0000000
--- a/include/asm-sh/apm.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2006 (c) Andriy Skulysh <askulysh@gmail.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-
-#ifndef __ASM_SH_APM_H
-#define __ASM_SH_APM_H
-
-#define APM_AC_OFFLINE			0
-#define APM_AC_ONLINE			1
-#define APM_AC_BACKUP			2
-#define APM_AC_UNKNOWN			0xff
-
-#define APM_BATTERY_STATUS_HIGH		0
-#define APM_BATTERY_STATUS_LOW		1
-#define APM_BATTERY_STATUS_CRITICAL	2
-#define APM_BATTERY_STATUS_CHARGING	3
-#define APM_BATTERY_STATUS_NOT_PRESENT	4
-#define APM_BATTERY_STATUS_UNKNOWN	0xff
-
-#define APM_BATTERY_LIFE_UNKNOWN	0xFFFF
-#define APM_BATTERY_LIFE_MINUTES	0x8000
-#define APM_BATTERY_LIFE_VALUE_MASK	0x7FFF
-
-#define APM_BATTERY_FLAG_HIGH		(1 << 0)
-#define APM_BATTERY_FLAG_LOW		(1 << 1)
-#define APM_BATTERY_FLAG_CRITICAL	(1 << 2)
-#define APM_BATTERY_FLAG_CHARGING	(1 << 3)
-#define APM_BATTERY_FLAG_NOT_PRESENT	(1 << 7)
-#define APM_BATTERY_FLAG_UNKNOWN	0xff
-
-#define APM_UNITS_MINS			0
-#define APM_UNITS_SECS			1
-#define APM_UNITS_UNKNOWN		-1
-
-
-extern int (*apm_get_info)(char *buf, char **start, off_t fpos, int length);
-extern int apm_suspended;
-
-void apm_queue_event(apm_event_t event);
-
-#endif
diff --git a/include/asm-sh/bigsur/bigsur.h b/include/asm-sh/bigsur/bigsur.h
deleted file mode 100644
index 427245f..0000000
--- a/include/asm-sh/bigsur/bigsur.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *
- * Hitachi Big Sur Eval Board support
- *
- * Dustin McIntire (dustin@sensoria.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Derived from Hitachi SH7751 reference manual
- * 
- */
-
-#ifndef _ASM_BIGSUR_H_
-#define _ASM_BIGSUR_H_
-
-#include <asm/irq.h>
-#include <asm/hd64465/hd64465.h>
-
-/* 7751 Internal IRQ's used by external CPLD controller */
-#define BIGSUR_IRQ_LOW	0
-#define BIGSUR_IRQ_NUM  14         /* External CPLD level 1 IRQs */
-#define BIGSUR_IRQ_HIGH (BIGSUR_IRQ_LOW + BIGSUR_IRQ_NUM)
-#define BIGSUR_2NDLVL_IRQ_LOW   (HD64465_IRQ_BASE+HD64465_IRQ_NUM)  
-#define BIGSUR_2NDLVL_IRQ_NUM   32 /* Level 2 IRQs = 4 regs * 8 bits */
-#define BIGSUR_2NDLVL_IRQ_HIGH  (BIGSUR_2NDLVL_IRQ_LOW + \
-                                 BIGSUR_2NDLVL_IRQ_NUM)
-
-/* PCI interrupt base number (A_INTA-A_INTD) */
-#define BIGSUR_SH7751_PCI_IRQ_BASE  (BIGSUR_2NDLVL_IRQ_LOW+10)  
-
-/* CPLD registers and external chip addresses */
-#define BIGSUR_HD64464_ADDR	0xB2000000
-#define BIGSUR_DGDR	0xB1FFFE00
-#define BIGSUR_BIDR	0xB1FFFD00
-#define BIGSUR_CSLR	0xB1FFFC00
-#define BIGSUR_SW1R	0xB1FFFB00
-#define BIGSUR_DBGR	0xB1FFFA00
-#define BIGSUR_BDTR	0xB1FFF900
-#define BIGSUR_BDRR	0xB1FFF800
-#define BIGSUR_PPR1	0xB1FFF700
-#define BIGSUR_PPR2	0xB1FFF600
-#define BIGSUR_IDE2	0xB1FFF500
-#define BIGSUR_IDE3	0xB1FFF400
-#define BIGSUR_SPCR	0xB1FFF300
-#define BIGSUR_ETHR	0xB1FE0000
-#define BIGSUR_PPDR	0xB1FDFF00
-#define BIGSUR_ICTL	0xB1FDFE00
-#define BIGSUR_ICMD	0xB1FDFD00
-#define BIGSUR_DMA0	0xB1FDFC00
-#define BIGSUR_DMA1	0xB1FDFB00
-#define BIGSUR_IRQ0	0xB1FDFA00
-#define BIGSUR_IRQ1	0xB1FDF900
-#define BIGSUR_IRQ2	0xB1FDF800
-#define BIGSUR_IRQ3	0xB1FDF700
-#define BIGSUR_IMR0	0xB1FDF600
-#define BIGSUR_IMR1	0xB1FDF500
-#define BIGSUR_IMR2	0xB1FDF400
-#define BIGSUR_IMR3	0xB1FDF300
-#define BIGSUR_IRLMR0	0xB1FDF200
-#define BIGSUR_IRLMR1	0xB1FDF100
-#define BIGSUR_V320USC_ADDR  0xB1000000
-#define BIGSUR_HD64465_ADDR  0xB0000000
-#define BIGSUR_INTERNAL_BASE 0xB0000000
-
-/* SMC ethernet card parameters */
-#define BIGSUR_ETHER_IOPORT		0x220
-
-/* IDE register paramters */
-#define BIGSUR_IDECMD_IOPORT	0x1f0
-#define BIGSUR_IDECTL_IOPORT	0x1f8
-
-/* LED bit position in BIGSUR_CSLR */
-#define BIGSUR_LED  (1<<4)
-
-/* PCI: default LOCAL memory window sizes (seen from PCI bus) */
-#define BIGSUR_LSR0_SIZE    (64*(1<<20)) //64MB
-#define BIGSUR_LSR1_SIZE    (64*(1<<20)) //64MB
-
-#endif /* _ASM_BIGSUR_H_ */
diff --git a/include/asm-sh/bigsur/io.h b/include/asm-sh/bigsur/io.h
deleted file mode 100644
index 1470ac8..0000000
--- a/include/asm-sh/bigsur/io.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * include/asm-sh/bigsur/io.h
- *
- * By Dustin McIntire (dustin@sensoria.com) (c)2001
- * Derived from io_hd64465.h, which bore the message:
- * By Greg Banks <gbanks@pocketpenguins.com>
- * (c) 2000 PocketPenguins Inc. 
- * and from io_hd64461.h, which bore the message:
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for a Hitachi Big Sur Evaluation Board.
- */
-
-#ifndef _ASM_SH_IO_BIGSUR_H
-#define _ASM_SH_IO_BIGSUR_H
-
-#include <linux/types.h>
-
-extern unsigned long bigsur_isa_port2addr(unsigned long offset);
-extern int bigsur_irq_demux(int irq);
-/* Provision for generic secondary demux step -- used by PCMCIA code */
-extern void bigsur_register_irq_demux(int irq,
-		int (*demux)(int irq, void *dev), void *dev);
-extern void bigsur_unregister_irq_demux(int irq);
-/* Set this variable to 1 to see port traffic */
-extern int bigsur_io_debug;
-/* Map a range of ports to a range of kernel virtual memory. */
-extern void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift);
-extern void bigsur_port_unmap(u32 baseport, u32 nports);
-
-#endif /* _ASM_SH_IO_BIGSUR_H */
-
diff --git a/include/asm-sh/bigsur/serial.h b/include/asm-sh/bigsur/serial.h
deleted file mode 100644
index a08fa82..0000000
--- a/include/asm-sh/bigsur/serial.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * include/asm-sh/bigsur/serial.h
- *
- * Configuration details for Big Sur 16550 based serial ports 
- * i.e. HD64465, PCMCIA, etc.
- */
-
-#ifndef _ASM_SERIAL_BIGSUR_H
-#define _ASM_SERIAL_BIGSUR_H
-#include <asm/hd64465.h>
-
-#define BASE_BAUD (3379200 / 16)
-
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
-
-#define SERIAL_PORT_DFNS                   \
-        /* UART CLK   PORT IRQ     FLAGS        */                      \
-        { 0, BASE_BAUD, 0x3F8, HD64465_IRQ_UART, STD_COM_FLAGS } /* ttyS0 */ 
-
-/* XXX: This should be moved ino irq.h */
-#define irq_cannonicalize(x) (x)
-
-#endif /* _ASM_SERIAL_BIGSUR_H */
diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h
index a294997..5a117ec 100644
--- a/include/asm-sh/bugs.h
+++ b/include/asm-sh/bugs.h
@@ -19,9 +19,9 @@
 	extern unsigned long loops_per_jiffy;
 	char *p = &init_utsname()->machine[2]; /* "sh" */
 
-	cpu_data->loops_per_jiffy = loops_per_jiffy;
+	current_cpu_data.loops_per_jiffy = loops_per_jiffy;
 
-	switch (cpu_data->type) {
+	switch (current_cpu_data.type) {
 	case CPU_SH7604 ... CPU_SH7619:
 		*p++ = '2';
 		break;
@@ -54,7 +54,7 @@
 		break;
 	}
 
-	printk("CPU: %s\n", get_cpu_subtype());
+	printk("CPU: %s\n", get_cpu_subtype(&current_cpu_data));
 
 #ifndef __LITTLE_ENDIAN__
 	/* 'eb' means 'Endian Big' */
diff --git a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h
index 07f62ec..22f1263 100644
--- a/include/asm-sh/cacheflush.h
+++ b/include/asm-sh/cacheflush.h
@@ -30,5 +30,8 @@
 
 #define HAVE_ARCH_UNMAPPED_AREA
 
+/* Page flag for lazy dcache write-back for the aliasing UP caches */
+#define PG_dcache_dirty	PG_arch_1
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHEFLUSH_H */
diff --git a/include/asm-sh/cpu-sh3/cacheflush.h b/include/asm-sh/cpu-sh3/cacheflush.h
index f70d8ef7..6fabbba 100644
--- a/include/asm-sh/cpu-sh3/cacheflush.h
+++ b/include/asm-sh/cpu-sh3/cacheflush.h
@@ -36,8 +36,6 @@
  /* 32KB cache, 4kb PAGE sizes need to check bit 12 */
 #define CACHE_ALIAS 0x00001000
 
-#define PG_mapped	PG_arch_1
-
 void flush_cache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
 #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
diff --git a/include/asm-sh/cpu-sh4/cacheflush.h b/include/asm-sh/cpu-sh4/cacheflush.h
index b01a10f..b3746a9 100644
--- a/include/asm-sh/cpu-sh4/cacheflush.h
+++ b/include/asm-sh/cpu-sh4/cacheflush.h
@@ -17,6 +17,7 @@
  *  so we need them.
  */
 void flush_cache_all(void);
+void flush_dcache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
 #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
 void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
@@ -38,16 +39,4 @@
 /* Initialization of P3 area for copy_user_page */
 void p3_cache_init(void);
 
-#define PG_mapped	PG_arch_1
-
-#ifdef CONFIG_MMU
-extern int remap_area_pages(unsigned long addr, unsigned long phys_addr,
-			    unsigned long size, unsigned long flags);
-#else /* CONFIG_MMU */
-static inline int remap_area_pages(unsigned long addr, unsigned long phys_addr,
-				   unsigned long size, unsigned long flags)
-{
-	return 0;
-}
-#endif /* CONFIG_MMU */
 #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
diff --git a/include/asm-sh/cpu-sh4/dma.h b/include/asm-sh/cpu-sh4/dma.h
index 3e4b3e6..c135e9c 100644
--- a/include/asm-sh/cpu-sh4/dma.h
+++ b/include/asm-sh/cpu-sh4/dma.h
@@ -3,6 +3,17 @@
 
 #define DMAOR_INIT	( 0x8000 | DMAOR_DME )
 
+/* SH7751/7760/7780 DMA IRQ sources */
+#define DMTE0_IRQ	34
+#define DMTE1_IRQ	35
+#define DMTE2_IRQ	36
+#define DMTE3_IRQ	37
+#define DMTE4_IRQ	44
+#define DMTE5_IRQ	45
+#define DMTE6_IRQ	46
+#define DMTE7_IRQ	47
+#define DMAE_IRQ	38
+
 #ifdef CONFIG_CPU_SH4A
 #define SH_DMAC_BASE	0xfc808020
 
diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
index 8d0867b..d3bc781 100644
--- a/include/asm-sh/dma-mapping.h
+++ b/include/asm-sh/dma-mapping.h
@@ -53,6 +53,10 @@
 	consistent_free(vaddr, size);
 }
 
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(d, h) (1)
+
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 				  enum dma_data_direction dir)
 {
diff --git a/include/asm-sh/ec3104/ec3104.h b/include/asm-sh/ec3104/ec3104.h
deleted file mode 100644
index 639cfa4..0000000
--- a/include/asm-sh/ec3104/ec3104.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef __ASM_EC3104_H
-#define __ASM_EC3104_H
-
-
-/*
- * Most of the register set is at 0xb0ec0000 - 0xb0ecffff.
- *
- * as far as I've figured it out the register map is:
- * 0xb0ec0000 - id string
- * 0xb0ec0XXX - power management
- * 0xb0ec1XXX - interrupt control
- * 0xb0ec3XXX - ps2 port (touch pad on aero 8000)
- * 0xb0ec6XXX - i2c
- * 0xb0ec7000 - first serial port (proprietary connector on aero 8000)
- * 0xb0ec8000 - second serial port
- * 0xb0ec9000 - third serial port
- * 0xb0eca000 - fourth serial port (keyboard controller on aero 8000)
- * 0xb0eccXXX - GPIO
- * 0xb0ecdXXX - GPIO
- */
-
-#define EC3104_BASE	0xb0ec0000
-
-#define EC3104_SER4_DATA	(EC3104_BASE+0xa000)
-#define EC3104_SER4_IIR		(EC3104_BASE+0xa008)
-#define EC3104_SER4_MCR		(EC3104_BASE+0xa010)
-#define EC3104_SER4_LSR		(EC3104_BASE+0xa014)
-#define EC3104_SER4_MSR		(EC3104_BASE+0xa018)
-
-/*
- * our ISA bus.  this seems to be real ISA.
- */
-#define EC3104_ISA_BASE	0xa5000000
-
-#define EC3104_IRQ	11
-#define EC3104_IRQBASE	64
-
-#define EC3104_IRQ_SER1	EC3104_IRQBASE + 7
-#define EC3104_IRQ_SER2	EC3104_IRQBASE + 8
-#define EC3104_IRQ_SER3	EC3104_IRQBASE + 9
-#define EC3104_IRQ_SER4	EC3104_IRQBASE + 10
-
-#endif /* __ASM_EC3104_H */
diff --git a/include/asm-sh/ec3104/io.h b/include/asm-sh/ec3104/io.h
deleted file mode 100644
index ea5c8e6..0000000
--- a/include/asm-sh/ec3104/io.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _ASM_SH_IO_EC3104_H
-#define _ASM_SH_IO_EC3104_H
-
-#include <linux/types.h>
-
-extern unsigned char ec3104_inb(unsigned long port);
-extern unsigned short ec3104_inw(unsigned long port);
-extern unsigned long ec3104_inl(unsigned long port);
-
-extern void ec3104_outb(unsigned char value, unsigned long port);
-extern void ec3104_outw(unsigned short value, unsigned long port);
-extern void ec3104_outl(unsigned long value, unsigned long port);
-
-extern int ec3104_irq_demux(int irq);
-
-#endif /* _ASM_SH_IO_EC3104_H */
diff --git a/include/asm-sh/ec3104/keyboard.h b/include/asm-sh/ec3104/keyboard.h
deleted file mode 100644
index c1253a6..0000000
--- a/include/asm-sh/ec3104/keyboard.h
+++ /dev/null
@@ -1,15 +0,0 @@
-extern unsigned char ec3104_kbd_sysrq_xlate[];
-extern int ec3104_kbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int ec3104_kbd_getkeycode(unsigned int scancode);
-extern int ec3104_kbd_translate(unsigned char, unsigned char *, char);
-extern char ec3104_kbd_unexpected_up(unsigned char);
-extern void ec3104_kbd_leds(unsigned char);
-extern void ec3104_kbd_init_hw(void);
-
-#define kbd_sysrq_xlate ec3104_kbd_sysrq_xlate
-#define kbd_setkeycode ec3104_kbd_setkeycode
-#define kbd_getkeycode ec3104_kbd_getkeycode
-#define kbd_translate ec3104_kbd_translate
-#define kbd_unexpected_up ec3104_kbd_unexpected_up
-#define kbd_leds ec3104_kbd_leds
-#define kbd_init_hw ec3104_kbd_init_hw
diff --git a/include/asm-sh/ec3104/serial.h b/include/asm-sh/ec3104/serial.h
deleted file mode 100644
index cfe4d78..0000000
--- a/include/asm-sh/ec3104/serial.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <asm/ec3104.h>
-/* Naturally we don't know the exact value but 115200 baud has a divisor
- * of 9 and 19200 baud has a divisor of 52, so this seems like a good
- * guess.  */
-#define BASE_BAUD (16800000 / 16)
-
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
-/* there is a fourth serial port with the expected values as well, but
- * it's got the keyboard controller behind it so we can't really use it
- * (without moving the keyboard driver to userspace, which doesn't sound
- * like a very good idea) */
-#define SERIAL_PORT_DFNS			\
-	/* UART CLK   PORT IRQ     FLAGS        */			\
-	{ 0, BASE_BAUD, 0x11C00, EC3104_IRQBASE+7, STD_COM_FLAGS }, /* ttyS0 */	\
-	{ 0, BASE_BAUD, 0x12000, EC3104_IRQBASE+8, STD_COM_FLAGS }, /* ttyS1 */	\
-	{ 0, BASE_BAUD, 0x12400, EC3104_IRQBASE+9, STD_COM_FLAGS }, /* ttyS2 */
-
-/* XXX: This should be moved ino irq.h */
-#define irq_cannonicalize(x) (x)
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index bff965e..8ccf7ae 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -66,12 +66,8 @@
 /* 3. OFFCHIP_NR_IRQS */
 #if defined(CONFIG_HD64461)
 # define OFFCHIP_NR_IRQS 18
-#elif defined (CONFIG_SH_BIGSUR) /* must be before CONFIG_HD64465 */
-# define OFFCHIP_NR_IRQS 48
 #elif defined(CONFIG_HD64465)
 # define OFFCHIP_NR_IRQS 16
-#elif defined (CONFIG_SH_EC3104)
-# define OFFCHIP_NR_IRQS 16
 #elif defined (CONFIG_SH_DREAMCAST)
 # define OFFCHIP_NR_IRQS 96
 #elif defined (CONFIG_SH_TITAN)
diff --git a/include/asm-sh/kgdb.h b/include/asm-sh/kgdb.h
index 7b26f53..0095c66 100644
--- a/include/asm-sh/kgdb.h
+++ b/include/asm-sh/kgdb.h
@@ -85,10 +85,10 @@
 #define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__)
 
 /* Forced breakpoint */
-#define BREAKPOINT() do {                                     \
-  if (kgdb_enabled) {                                         \
-    asm volatile("trapa   #0xff");                            \
-  }                                                           \
+#define BREAKPOINT()					\
+do {							\
+	if (kgdb_enabled)				\
+		__asm__ __volatile__("trapa   #0x3c");	\
 } while (0)
 
 /* KGDB should be able to flush all kernel text space */
diff --git a/include/asm-sh/mmu.h b/include/asm-sh/mmu.h
index cf47df7..eb0358c 100644
--- a/include/asm-sh/mmu.h
+++ b/include/asm-sh/mmu.h
@@ -1,25 +1,19 @@
 #ifndef __MMU_H
 #define __MMU_H
 
-#if !defined(CONFIG_MMU)
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_id_t[NR_CPUS];
 
 typedef struct {
+#ifdef CONFIG_MMU
+	mm_context_id_t		id;
+	void			*vdso;
+#else
 	struct vm_list_struct	*vmlist;
 	unsigned long		end_brk;
+#endif
 } mm_context_t;
 
-#else
-
-/* Default "unsigned long" context */
-typedef unsigned long mm_context_id_t;
-
-typedef struct {
-	mm_context_id_t id;
-	void *vdso;
-} mm_context_t;
-
-#endif /* CONFIG_MMU */
-
 /*
  * Privileged Space Mapping Buffer (PMB) definitions
  */
diff --git a/include/asm-sh/mmu_context.h b/include/asm-sh/mmu_context.h
index 46f04e2..3420244 100644
--- a/include/asm-sh/mmu_context.h
+++ b/include/asm-sh/mmu_context.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2003 Paul Mundt
+ * Copyright (C) 2003 - 2006 Paul Mundt
  *
  * ASID handling idea taken from MIPS implementation.
  */
@@ -19,11 +19,6 @@
  *    (b) ASID (Address Space IDentifier)
  */
 
-/*
- * Cache of MMU context last used.
- */
-extern unsigned long mmu_context_cache;
-
 #define MMU_CONTEXT_ASID_MASK		0x000000ff
 #define MMU_CONTEXT_VERSION_MASK	0xffffff00
 #define MMU_CONTEXT_FIRST_VERSION	0x00000100
@@ -32,6 +27,11 @@
 /* ASID is 8-bit value, so it can't be 0x100 */
 #define MMU_NO_ASID			0x100
 
+#define cpu_context(cpu, mm)	((mm)->context.id[cpu])
+#define cpu_asid(cpu, mm)	(cpu_context((cpu), (mm)) & \
+				 MMU_CONTEXT_ASID_MASK)
+#define asid_cache(cpu)		(cpu_data[cpu].asid_cache)
+
 /*
  * Virtual Page Number mask
  */
@@ -41,18 +41,17 @@
 /*
  * Get MMU context if needed.
  */
-static inline void get_mmu_context(struct mm_struct *mm)
+static inline void get_mmu_context(struct mm_struct *mm, unsigned int cpu)
 {
-	unsigned long mc = mmu_context_cache;
+	unsigned long asid = asid_cache(cpu);
 
 	/* Check if we have old version of context. */
-	if (((mm->context.id ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
+	if (((cpu_context(cpu, mm) ^ asid) & MMU_CONTEXT_VERSION_MASK) == 0)
 		/* It's up to date, do nothing */
 		return;
 
 	/* It's old, we need to get new context with new version. */
-	mc = ++mmu_context_cache;
-	if (!(mc & MMU_CONTEXT_ASID_MASK)) {
+	if (!(++asid & MMU_CONTEXT_ASID_MASK)) {
 		/*
 		 * We exhaust ASID of this version.
 		 * Flush all TLB and start new cycle.
@@ -63,10 +62,11 @@
 		 * Fix version; Note that we avoid version #0
 		 * to distingush NO_CONTEXT.
 		 */
-		if (!mc)
-			mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
+		if (!asid)
+			asid = MMU_CONTEXT_FIRST_VERSION;
 	}
-	mm->context.id = mc;
+
+	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
 }
 
 /*
@@ -74,9 +74,13 @@
  * instance.
  */
 static inline int init_new_context(struct task_struct *tsk,
-				       struct mm_struct *mm)
+				   struct mm_struct *mm)
 {
-	mm->context.id = NO_CONTEXT;
+	int i;
+
+	for (i = 0; i < num_online_cpus(); i++)
+		cpu_context(i, mm) = NO_CONTEXT;
+
 	return 0;
 }
 
@@ -117,10 +121,10 @@
  * After we have set current->mm to a new value, this activates
  * the context for the new mm so we see the new mappings.
  */
-static inline void activate_context(struct mm_struct *mm)
+static inline void activate_context(struct mm_struct *mm, unsigned int cpu)
 {
-	get_mmu_context(mm);
-	set_asid(mm->context.id & MMU_CONTEXT_ASID_MASK);
+	get_mmu_context(mm, cpu);
+	set_asid(cpu_asid(cpu, mm));
 }
 
 /* MMU_TTB is used for optimizing the fault handling. */
@@ -138,10 +142,15 @@
 			     struct mm_struct *next,
 			     struct task_struct *tsk)
 {
+	unsigned int cpu = smp_processor_id();
+
 	if (likely(prev != next)) {
+		cpu_set(cpu, next->cpu_vm_mask);
 		set_TTB(next->pgd);
-		activate_context(next);
-	}
+		activate_context(next, cpu);
+	} else
+		if (!cpu_test_and_set(cpu, next->cpu_vm_mask))
+			activate_context(next, cpu);
 }
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
@@ -159,7 +168,7 @@
 #define destroy_context(mm)		do { } while (0)
 #define set_asid(asid)			do { } while (0)
 #define get_asid()			(0)
-#define activate_context(mm)		do { } while (0)
+#define activate_context(mm,cpu)	do { } while (0)
 #define switch_mm(prev,next,tsk)	do { } while (0)
 #define deactivate_mm(tsk,mm)		do { } while (0)
 #define activate_mm(prev,next)		do { } while (0)
@@ -174,14 +183,16 @@
  */
 static inline void enable_mmu(void)
 {
+	unsigned int cpu = smp_processor_id();
+
 	/* Enable MMU */
 	ctrl_outl(MMU_CONTROL_INIT, MMUCR);
 	ctrl_barrier();
 
-	if (mmu_context_cache == NO_CONTEXT)
-		mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
+	if (asid_cache(cpu) == NO_CONTEXT)
+		asid_cache(cpu) = MMU_CONTEXT_FIRST_VERSION;
 
-	set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);
+	set_asid(asid_cache(cpu) & MMU_CONTEXT_ASID_MASK);
 }
 
 static inline void disable_mmu(void)
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 380fd62..ac4b467 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -13,6 +13,8 @@
    [ P4 control   ]		0xE0000000
  */
 
+#ifdef __KERNEL__
+
 /* PAGE_SHIFT determines the page size */
 #if defined(CONFIG_PAGE_SIZE_4KB)
 # define PAGE_SHIFT	12
@@ -51,7 +53,6 @@
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT-PAGE_SHIFT)
 #endif
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 extern void (*clear_page)(void *to);
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index 036ca28..9214c01 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -43,17 +43,17 @@
 /* PGD bits */
 #define PGDIR_SHIFT	(PTE_SHIFT + PTE_BITS)
 #define PGDIR_BITS	(32 - PGDIR_SHIFT)
-#define PGDIR_SIZE	(1 << PGDIR_SHIFT)
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
 /* Entries per level */
-#define PTRS_PER_PTE	(PAGE_SIZE / 4)
+#define PTRS_PER_PTE	(PAGE_SIZE / (1 << PTE_MAGNITUDE))
 #define PTRS_PER_PGD	(PAGE_SIZE / 4)
 
 #define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
 #define FIRST_USER_ADDRESS	0
 
-#define PTE_PHYS_MASK	0x1ffff000
+#define PTE_PHYS_MASK		(0x20000000 - PAGE_SIZE)
 
 /*
  * First 1MB map is used by fixed purpose.
@@ -583,11 +583,6 @@
 extern unsigned int kobjsize(const void *objp);
 #endif /* !CONFIG_MMU */
 
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
-#endif
-
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern void paging_init(void);
 
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index e29f2ab..3e46a7a 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -27,8 +27,6 @@
 #define CCN_CVR		0xff000040
 #define CCN_PRR		0xff000044
 
-const char *get_cpu_subtype(void);
-
 /*
  *  CPU type and hardware bug flags. Kept separately for each CPU.
  *
@@ -66,6 +64,7 @@
 struct sh_cpuinfo {
 	unsigned int type;
 	unsigned long loops_per_jiffy;
+	unsigned long asid_cache;
 
 	struct cache_info icache;	/* Primary I-cache */
 	struct cache_info dcache;	/* Primary D-cache */
@@ -288,5 +287,8 @@
 #define vsyscall_init() do { } while (0)
 #endif
 
+/* arch/sh/kernel/setup.c */
+const char *get_cpu_subtype(struct sh_cpuinfo *c);
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_PROCESSOR_H */
diff --git a/include/asm-sh/rts7751r2d.h b/include/asm-sh/rts7751r2d.h
index 796b8fc..10565ac 100644
--- a/include/asm-sh/rts7751r2d.h
+++ b/include/asm-sh/rts7751r2d.h
@@ -68,6 +68,10 @@
 #define IRQ_PCISLOT2	10		/* PCI Slot #2 IRQ */
 #define	IRQ_EXTENTION	11		/* EXTn IRQ */
 
+/* arch/sh/boards/renesas/rts7751r2d/irq.c */
+void init_rts7751r2d_IRQ(void);
+int rts7751r2d_irq_demux(int);
+
 #define __IO_PREFIX rts7751r2d
 #include <asm/io_generic.h>
 
diff --git a/include/asm-sh/serial.h b/include/asm-sh/serial.h
index 8734590..21f6d33 100644
--- a/include/asm-sh/serial.h
+++ b/include/asm-sh/serial.h
@@ -9,11 +9,6 @@
 
 #include <linux/kernel.h>
 
-#ifdef CONFIG_SH_EC3104
-#include <asm/serial-ec3104.h>
-#elif defined (CONFIG_SH_BIGSUR)
-#include <asm/serial-bigsur.h>
-#else
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
  *
@@ -34,12 +29,8 @@
 
 #else
 
-#define SERIAL_PORT_DFNS			\
-	/* UART CLK   PORT IRQ     FLAGS        */			\
-	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
-	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }	/* ttyS1 */
+#define SERIAL_PORT_DFNS
 
 #endif
 
-#endif
 #endif /* _ASM_SERIAL_H */
diff --git a/include/asm-sh/termios.h b/include/asm-sh/termios.h
index 44edfd4..e7c8f86 100644
--- a/include/asm-sh/termios.h
+++ b/include/asm-sh/termios.h
@@ -39,24 +39,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*	intr=^C		quit=^\		erase=del	kill=^U
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h
index 879f741..279e70a 100644
--- a/include/asm-sh/thread_info.h
+++ b/include/asm-sh/thread_info.h
@@ -32,12 +32,20 @@
 
 #define PREEMPT_ACTIVE		0x10000000
 
-#ifdef CONFIG_4KSTACKS
-#define THREAD_SIZE		(PAGE_SIZE)
+#if defined(CONFIG_4KSTACKS)
+#define THREAD_SIZE_ORDER	(0)
+#elif defined(CONFIG_PAGE_SIZE_4KB)
+#define THREAD_SIZE_ORDER	(1)
+#elif defined(CONFIG_PAGE_SIZE_8KB)
+#define THREAD_SIZE_ORDER	(1)
+#elif defined(CONFIG_PAGE_SIZE_64KB)
+#define THREAD_SIZE_ORDER	(0)
 #else
-#define THREAD_SIZE		(PAGE_SIZE * 2)
+#error "Unknown thread size"
 #endif
-#define STACK_WARN		(THREAD_SIZE / 8)
+
+#define THREAD_SIZE	(PAGE_SIZE << THREAD_SIZE_ORDER)
+#define STACK_WARN	(THREAD_SIZE >> 3)
 
 /*
  * macros/functions for gaining access to the thread information structure
diff --git a/include/asm-sh/tlbflush.h b/include/asm-sh/tlbflush.h
index 28c073b..455fb8d 100644
--- a/include/asm-sh/tlbflush.h
+++ b/include/asm-sh/tlbflush.h
@@ -4,7 +4,6 @@
 /*
  * TLB flushing:
  *
- *  - flush_tlb() flushes the current mm struct TLBs
  *  - flush_tlb_all() flushes all processes TLBs
  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
  *  - flush_tlb_page(vma, vmaddr) flushes one page
@@ -12,20 +11,45 @@
  *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
  *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
  */
+extern void local_flush_tlb_all(void);
+extern void local_flush_tlb_mm(struct mm_struct *mm);
+extern void local_flush_tlb_range(struct vm_area_struct *vma,
+				  unsigned long start,
+				  unsigned long end);
+extern void local_flush_tlb_page(struct vm_area_struct *vma,
+				 unsigned long page);
+extern void local_flush_tlb_kernel_range(unsigned long start,
+					 unsigned long end);
+extern void local_flush_tlb_one(unsigned long asid, unsigned long page);
 
-extern void flush_tlb(void);
+#ifdef CONFIG_SMP
+
 extern void flush_tlb_all(void);
 extern void flush_tlb_mm(struct mm_struct *mm);
 extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 			    unsigned long end);
 extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
-extern void __flush_tlb_page(unsigned long asid, unsigned long page);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tlb_one(unsigned long asid, unsigned long page);
+
+#else
+
+#define flush_tlb_all()			local_flush_tlb_all()
+#define flush_tlb_mm(mm)		local_flush_tlb_mm(mm)
+#define flush_tlb_page(vma, page)	local_flush_tlb_page(vma, page)
+#define flush_tlb_one(asid, page)	local_flush_tlb_one(asid, page)
+
+#define flush_tlb_range(vma, start, end)	\
+	local_flush_tlb_range(vma, start, end)
+
+#define flush_tlb_kernel_range(start, end)	\
+	local_flush_tlb_kernel_range(start, end)
+
+#endif /* CONFIG_SMP */
 
 static inline void flush_tlb_pgtables(struct mm_struct *mm,
 				      unsigned long start, unsigned long end)
-{ /* Nothing to do */
+{
+	/* Nothing to do */
 }
-
-extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
-
 #endif /* __ASM_SH_TLBFLUSH_H */
diff --git a/include/asm-sh/ubc.h b/include/asm-sh/ubc.h
index 694f51f..ae9bbde 100644
--- a/include/asm-sh/ubc.h
+++ b/include/asm-sh/ubc.h
@@ -17,7 +17,7 @@
 /* User Break Controller */
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
     defined(CONFIG_CPU_SUBTYPE_SH7300)
-#define UBC_TYPE_SH7729	(cpu_data->type == CPU_SH7729)
+#define UBC_TYPE_SH7729	(current_cpu_data.type == CPU_SH7729)
 #else
 #define UBC_TYPE_SH7729	0
 #endif
diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
index f982073..17f527b 100644
--- a/include/asm-sh/unistd.h
+++ b/include/asm-sh/unistd.h
@@ -292,22 +292,22 @@
 #define __NR_mq_getsetattr      (__NR_mq_open+5)
 #define __NR_kexec_load		283
 #define __NR_waitid		284
-/* #define __NR_sys_setaltroot	285 */
-#define __NR_add_key		286
-#define __NR_request_key	287
-#define __NR_keyctl		288
-#define __NR_ioprio_set		289
-#define __NR_ioprio_get		290
-#define __NR_inotify_init	291
-#define __NR_inotify_add_watch	292
-#define __NR_inotify_rm_watch	293
+#define __NR_add_key		285
+#define __NR_request_key	286
+#define __NR_keyctl		287
+#define __NR_ioprio_set		288
+#define __NR_ioprio_get		289
+#define __NR_inotify_init	290
+#define __NR_inotify_add_watch	291
+#define __NR_inotify_rm_watch	292
+/* 293 is unused */
 #define __NR_migrate_pages	294
 #define __NR_openat		295
 #define __NR_mkdirat		296
 #define __NR_mknodat		297
 #define __NR_fchownat		298
 #define __NR_futimesat		299
-#define __NR_newfstatat		300
+#define __NR_fstatat64		300
 #define __NR_unlinkat		301
 #define __NR_renameat		302
 #define __NR_linkat		303
diff --git a/include/asm-sh/voyagergx.h b/include/asm-sh/voyagergx.h
index 99b0807..64c936b 100644
--- a/include/asm-sh/voyagergx.h
+++ b/include/asm-sh/voyagergx.h
@@ -308,6 +308,9 @@
 #define AC97C_READ			(1 << 19)
 #define AC97C_WD_BIT			(1 << 2)
 #define AC97C_INDEX_MASK		0x7f
-/* -------------------------------------------------------------------- */
+
+/* arch/sh/cchips/voyagergx/consistent.c */
+void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
+int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
 
 #endif /* _VOYAGER_GX_REG_H */
diff --git a/include/asm-sh64/termios.h b/include/asm-sh64/termios.h
index 4a9c7fb..dc44e6e 100644
--- a/include/asm-sh64/termios.h
+++ b/include/asm-sh64/termios.h
@@ -50,24 +50,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15	/* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*	intr=^C		quit=^\		erase=del	kill=^U
diff --git a/include/asm-sparc/io.h b/include/asm-sparc/io.h
index cab0b85..c23e74a 100644
--- a/include/asm-sparc/io.h
+++ b/include/asm-sparc/io.h
@@ -256,6 +256,35 @@
 #define iowrite16(val,X)		writew(val,X)
 #define iowrite32(val,X)		writel(val,X)
 
+static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insb((unsigned long __force)port, buf, count);
+}
+static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insw((unsigned long __force)port, buf, count);
+}
+
+static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insl((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+	outsb((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+	outsw((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+	outsl((unsigned long __force)port, buf, count);
+}
+
 /* Create a virtual mapping cookie for an IO port range */
 extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
 extern void ioport_unmap(void __iomem *);
diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h
index d05f83c..d767f20 100644
--- a/include/asm-sparc/termios.h
+++ b/include/asm-sparc/termios.h
@@ -45,24 +45,6 @@
 	unsigned short ws_ypixel;
 };
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 #include <linux/module.h>
 
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
index 905e59b..5d233b4 100644
--- a/include/asm-sparc64/irq.h
+++ b/include/asm-sparc64/irq.h
@@ -46,6 +46,10 @@
 #define irq_canonicalize(irq)	(irq)
 extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
 extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
+extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
+				    unsigned int msi_devino_start,
+				    unsigned int msi_devino_end);
+extern void sun4v_destroy_msi(unsigned int virt_irq);
 extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
 
 static __inline__ void set_softint(unsigned long bits)
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h
index dcfa762..7a246d8 100644
--- a/include/asm-sparc64/pbm.h
+++ b/include/asm-sparc64/pbm.h
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
+#include <linux/msi.h>
 
 #include <asm/io.h>
 #include <asm/page.h>
@@ -177,6 +178,24 @@
 	int				is_66mhz_capable;
 	int				all_devs_66mhz;
 
+#ifdef CONFIG_PCI_MSI
+	/* MSI info.  */
+	u32				msiq_num;
+	u32				msiq_ent_count;
+	u32				msiq_first;
+	u32				msiq_first_devino;
+	u32				msi_num;
+	u32				msi_first;
+	u32				msi_data_mask;
+	u32				msix_data_width;
+	u64				msi32_start;
+	u64				msi64_start;
+	u32				msi32_len;
+	u32				msi64_len;
+	void				*msi_queues;
+	unsigned long			*msi_bitmap;
+#endif /* !(CONFIG_PCI_MSI) */
+
 	/* This PBM's streaming buffer. */
 	struct pci_strbuf		stc;
 
@@ -213,6 +232,12 @@
 	void (*base_address_update)(struct pci_dev *, int);
 	void (*resource_adjust)(struct pci_dev *, struct resource *, struct resource *);
 
+#ifdef CONFIG_PCI_MSI
+	int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev,
+			     struct msi_desc *entry);
+	void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev);
+#endif
+
 	/* Now things for the actual PCI bus probes. */
 	struct pci_ops			*pci_ops;
 	unsigned int			pci_first_busno;
@@ -231,6 +256,9 @@
 	int num_prom_regs;
 	struct linux_prom_pci_registers prom_assignments[PROMREG_MAX];
 	int num_prom_assignments;
+#ifdef CONFIG_PCI_MSI
+	unsigned int			msi_num;
+#endif
 };
 
 /* Currently these are the same across all PCI controllers
diff --git a/include/asm-sparc64/setup.h b/include/asm-sparc64/setup.h
index b356ee2..5053df3 100644
--- a/include/asm-sparc64/setup.h
+++ b/include/asm-sparc64/setup.h
@@ -5,6 +5,6 @@
 #ifndef _SPARC64_SETUP_H
 #define _SPARC64_SETUP_H
 
-#define COMMAND_LINE_SIZE	256
+#define COMMAND_LINE_SIZE	2048
 
 #endif /* _SPARC64_SETUP_H */
diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
index ee26a07..f05d390 100644
--- a/include/asm-sparc64/termios.h
+++ b/include/asm-sparc64/termios.h
@@ -45,24 +45,6 @@
 	unsigned short ws_ypixel;
 };
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 #include <linux/module.h>
 
diff --git a/include/asm-um/elf-ppc.h b/include/asm-um/elf-ppc.h
index 9971113..d3b90b7 100644
--- a/include/asm-um/elf-ppc.h
+++ b/include/asm-um/elf-ppc.h
@@ -11,7 +11,7 @@
 
 #define elf_check_arch(x) (1)
 
-#ifdef CONFIG_64_BIT
+#ifdef CONFIG_64BIT
 #define ELF_CLASS ELFCLASS64
 #else
 #define ELF_CLASS ELFCLASS32
diff --git a/include/asm-um/processor-x86_64.h b/include/asm-um/processor-x86_64.h
index 10609af..31c2d4d 100644
--- a/include/asm-um/processor-x86_64.h
+++ b/include/asm-um/processor-x86_64.h
@@ -13,6 +13,7 @@
 struct arch_thread {
         unsigned long debugregs[8];
         int debugregs_seq;
+        unsigned long fs;
         struct faultinfo faultinfo;
 };
 
@@ -25,8 +26,9 @@
 #define cpu_relax()   rep_nop()
 
 #define INIT_ARCH_THREAD { .debugregs  		= { [ 0 ... 7 ] = 0 }, \
-                           .debugregs_seq	= 0, \
-                           .faultinfo		= { 0, 0, 0 } }
+                           .debugregs_seq	= 0,			       \
+			   .fs			= 0, \
+			   .faultinfo		= { 0, 0, 0 } }
 
 static inline void arch_flush_thread(struct arch_thread *thread)
 {
diff --git a/include/asm-um/ptrace-x86_64.h b/include/asm-um/ptrace-x86_64.h
index 03b4af4..bf61d17 100644
--- a/include/asm-um/ptrace-x86_64.h
+++ b/include/asm-um/ptrace-x86_64.h
@@ -81,9 +81,10 @@
 {
 }
 
-static inline void arch_switch_to_skas(struct task_struct *from,
-                                       struct task_struct *to)
-{
-}
+extern void arch_switch_to_skas(struct task_struct *from,
+				struct task_struct *to);
+
+extern long arch_prctl_skas(struct task_struct *task, int code,
+			    unsigned long __user *addr);
 
 #endif
diff --git a/include/asm-v850/termios.h b/include/asm-v850/termios.h
index 79e97b5..c2c2b1d 100644
--- a/include/asm-v850/termios.h
+++ b/include/asm-v850/termios.h
@@ -39,24 +39,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*	intr=^C		quit=^\		erase=del	kill=^U
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index 8da9609..d4dbbe5 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -7,7 +7,7 @@
 
 #include <asm/alternative.h>
 
-#if __GNUC__ < 4 || __GNUC_MINOR__ < 1
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
 /* Technically wrong, but this avoids compilation errors on some gcc
    versions. */
 #define ADDR "=m" (*(volatile long *) addr)
diff --git a/include/asm-x86_64/bootsetup.h b/include/asm-x86_64/bootsetup.h
index b829f7b..7b1c3ad 100644
--- a/include/asm-x86_64/bootsetup.h
+++ b/include/asm-x86_64/bootsetup.h
@@ -31,7 +31,7 @@
 #define EDD_MBR_SIG_NR (*(unsigned char *) (PARAM+EDD_MBR_SIG_NR_BUF))
 #define EDD_MBR_SIGNATURE ((unsigned int *) (PARAM+EDD_MBR_SIG_BUF))
 #define EDD_BUF     ((struct edd_info *) (PARAM+EDDBUF))
-#define COMMAND_LINE saved_command_line
+#define COMMAND_LINE boot_command_line
 
 #define RAMDISK_IMAGE_START_MASK  	0x07FF
 #define RAMDISK_PROMPT_FLAG		0x8000
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
index 49dbab0..d2af227 100644
--- a/include/asm-x86_64/dma-mapping.h
+++ b/include/asm-x86_64/dma-mapping.h
@@ -66,6 +66,9 @@
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
 extern void *dma_alloc_coherent(struct device *dev, size_t size,
 				dma_addr_t *dma_handle, gfp_t gfp);
 extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h
index fa20867..6216fa3 100644
--- a/include/asm-x86_64/e820.h
+++ b/include/asm-x86_64/e820.h
@@ -46,6 +46,7 @@
 extern void e820_print_map(char *who);
 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 unsigned long e820_hole_size(unsigned long start, unsigned long end);
 
 extern void e820_setup_gap(void);
 extern void e820_register_active_regions(int nid,
@@ -56,6 +57,7 @@
 extern struct e820map e820;
 
 extern unsigned ebda_addr, ebda_size;
+extern unsigned long nodemap_addr, nodemap_size;
 #endif/*!__ASSEMBLY__*/
 
 #endif/*__E820_HEADER*/
diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h
index b390984..59a66f0 100644
--- a/include/asm-x86_64/hpet.h
+++ b/include/asm-x86_64/hpet.h
@@ -56,8 +56,15 @@
 extern int is_hpet_enabled(void);
 extern int hpet_rtc_timer_init(void);
 extern int apic_is_clustered_box(void);
+extern int hpet_arch_init(void);
+extern int hpet_timer_stop_set_go(unsigned long tick);
+extern int hpet_reenable(void);
+extern unsigned int hpet_calibrate_tsc(void);
 
 extern int hpet_use_timer;
+extern unsigned long hpet_address;
+extern unsigned long hpet_period;
+extern unsigned long hpet_tick;
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
index 179cce7..2e4b7a5 100644
--- a/include/asm-x86_64/hw_irq.h
+++ b/include/asm-x86_64/hw_irq.h
@@ -32,9 +32,30 @@
 #define IA32_SYSCALL_VECTOR	0x80
 
 
+/* Reserve the lowest usable priority level 0x20 - 0x2f for triggering
+ * cleanup after irq migration.
+ */
+#define IRQ_MOVE_CLEANUP_VECTOR	FIRST_EXTERNAL_VECTOR
+ 
 /*
  * Vectors 0x20-0x2f are used for ISA interrupts.
  */
+#define IRQ0_VECTOR		FIRST_EXTERNAL_VECTOR + 0x10
+#define IRQ1_VECTOR		IRQ0_VECTOR + 1
+#define IRQ2_VECTOR		IRQ0_VECTOR + 2
+#define IRQ3_VECTOR		IRQ0_VECTOR + 3
+#define IRQ4_VECTOR		IRQ0_VECTOR + 4
+#define IRQ5_VECTOR		IRQ0_VECTOR + 5 
+#define IRQ6_VECTOR		IRQ0_VECTOR + 6
+#define IRQ7_VECTOR		IRQ0_VECTOR + 7
+#define IRQ8_VECTOR		IRQ0_VECTOR + 8
+#define IRQ9_VECTOR		IRQ0_VECTOR + 9
+#define IRQ10_VECTOR		IRQ0_VECTOR + 10
+#define IRQ11_VECTOR		IRQ0_VECTOR + 11
+#define IRQ12_VECTOR		IRQ0_VECTOR + 12
+#define IRQ13_VECTOR		IRQ0_VECTOR + 13
+#define IRQ14_VECTOR		IRQ0_VECTOR + 14
+#define IRQ15_VECTOR		IRQ0_VECTOR + 15
 
 /*
  * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
@@ -66,10 +87,10 @@
 
 /*
  * First APIC vector available to drivers: (vectors 0x30-0xee)
- * we start at 0x31 to spread out vectors evenly between priority
+ * we start at 0x41 to spread out vectors evenly between priority
  * levels. (0x80 is the syscall vector)
  */
-#define FIRST_DEVICE_VECTOR	0x31
+#define FIRST_DEVICE_VECTOR	(IRQ15_VECTOR + 2)
 #define FIRST_SYSTEM_VECTOR	0xef   /* duplicated in irq.h */
 
 
@@ -91,7 +112,7 @@
 extern int i8259A_irq_pending(unsigned int irq);
 extern void make_8259A_irq(unsigned int irq);
 extern void init_8259A(int aeoi);
-extern void FASTCALL(send_IPI_self(int vector));
+extern void send_IPI_self(int vector);
 extern void init_VISWS_APIC_irqs(void);
 extern void setup_IO_APIC(void);
 extern void disable_IO_APIC(void);
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index 6ee9fad..de2cd9a 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -100,7 +100,7 @@
 
 #define IO_SPACE_LIMIT 0xffff
 
-#if defined(__KERNEL__) && __x86_64__
+#if defined(__KERNEL__) && defined(__x86_64__)
 
 #include <linux/vmalloc.h>
 
@@ -248,12 +248,6 @@
  */
 #define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
 
-/*
- * Again, x86-64 does not require mem IO specific function.
- */
-
-#define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),(void *)(b),(c),(d))
-
 /* Nothing to do */
 
 #define dma_cache_inv(_start,_size)		do { } while (0)
diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h
index 561ecbf..f4fb238 100644
--- a/include/asm-x86_64/io_apic.h
+++ b/include/asm-x86_64/io_apic.h
@@ -85,18 +85,8 @@
 		mask		:  1,	/* 0: enabled, 1: disabled */
 		__reserved_2	: 15;
 
-	union {		struct { __u32
-					__reserved_1	: 24,
-					physical_dest	:  4,
-					__reserved_2	:  4;
-			} physical;
-
-			struct { __u32
-					__reserved_1	: 24,
-					logical_dest	:  8;
-			} logical;
-	} dest;
-
+	__u32	__reserved_3	: 24,
+		dest		:  8;
 } __attribute__ ((packed));
 
 /*
diff --git a/include/asm-x86_64/mce.h b/include/asm-x86_64/mce.h
index 5a11146..177e92b 100644
--- a/include/asm-x86_64/mce.h
+++ b/include/asm-x86_64/mce.h
@@ -103,6 +103,8 @@
 
 extern atomic_t mce_entry;
 
+extern void do_machine_check(struct pt_regs *, long);
+
 #endif
 
 #endif
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index c38ebdf..fb558fb 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -11,24 +11,25 @@
 
 #include <asm/smp.h>
 
-/* Should really switch to dynamic allocation at some point */
-#define NODEMAPSIZE 0x4fff
-
 /* Simple perfect hash to map physical addresses to node numbers */
 struct memnode {
 	int shift;
-	u8 map[NODEMAPSIZE];
-} ____cacheline_aligned;
+	unsigned int mapsize;
+	u8 *map;
+	u8 embedded_map[64-16];
+} ____cacheline_aligned; /* total size = 64 bytes */
 extern struct memnode memnode;
 #define memnode_shift memnode.shift
 #define memnodemap memnode.map
+#define memnodemapsize memnode.mapsize
 
 extern struct pglist_data *node_data[];
 
 static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) 
 { 
 	unsigned nid; 
-	VIRTUAL_BUG_ON((addr >> memnode_shift) >= NODEMAPSIZE);
+	VIRTUAL_BUG_ON(!memnodemap);
+	VIRTUAL_BUG_ON((addr >> memnode_shift) >= memnodemapsize);
 	nid = memnodemap[addr >> memnode_shift]; 
 	VIRTUAL_BUG_ON(nid >= MAX_NUMNODES || !node_data[nid]); 
 	return nid; 
@@ -46,5 +47,10 @@
 extern int pfn_valid(unsigned long pfn);
 #endif
 
+#ifdef CONFIG_NUMA_EMU
+#define FAKE_NODE_MIN_SIZE	(64*1024*1024)
+#define FAKE_NODE_MIN_HASH_MASK	(~(FAKE_NODE_MIN_SIZE - 1ul))
+#endif
+
 #endif
 #endif
diff --git a/include/asm-x86_64/mutex.h b/include/asm-x86_64/mutex.h
index 16396b1..6c2949a 100644
--- a/include/asm-x86_64/mutex.h
+++ b/include/asm-x86_64/mutex.h
@@ -21,7 +21,7 @@
 	unsigned long dummy;						\
 									\
 	typecheck(atomic_t *, v);					\
-	typecheck_fn(fastcall void (*)(atomic_t *), fail_fn);		\
+	typecheck_fn(void (*)(atomic_t *), fail_fn);			\
 									\
 	__asm__ __volatile__(						\
 		LOCK_PREFIX "   decl (%%rdi)	\n"			\
@@ -47,7 +47,7 @@
  */
 static inline int
 __mutex_fastpath_lock_retval(atomic_t *count,
-			     int fastcall (*fail_fn)(atomic_t *))
+			     int (*fail_fn)(atomic_t *))
 {
 	if (unlikely(atomic_dec_return(count) < 0))
 		return fail_fn(count);
@@ -67,7 +67,7 @@
 	unsigned long dummy;						\
 									\
 	typecheck(atomic_t *, v);					\
-	typecheck_fn(fastcall void (*)(atomic_t *), fail_fn);		\
+	typecheck_fn(void (*)(atomic_t *), fail_fn);			\
 									\
 	__asm__ __volatile__(						\
 		LOCK_PREFIX "   incl (%%rdi)	\n"			\
diff --git a/include/asm-x86_64/pgalloc.h b/include/asm-x86_64/pgalloc.h
index 43d4c33..4e28b60 100644
--- a/include/asm-x86_64/pgalloc.h
+++ b/include/asm-x86_64/pgalloc.h
@@ -18,11 +18,6 @@
 	set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
 }
 
-static inline pmd_t *get_pmd(void)
-{
-	return (pmd_t *)get_zeroed_page(GFP_KERNEL);
-}
-
 static inline void pmd_free(pmd_t *pmd)
 {
 	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 59901c6..730bd60 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -359,15 +359,6 @@
 #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
 #define mk_pte_huge(entry) (pte_val(entry) |= _PAGE_PRESENT | _PAGE_PSE)
  
-/* physical address -> PTE */
-static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{ 
-	pte_t pte;
-	pte_val(pte) = physpage | pgprot_val(pgprot); 
-	pte_val(pte) &= __supported_pte_mask;
-	return pte; 
-}
- 
 /* Change flags of a PTE */
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { 
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index 6d324b8..f54f3ab 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -45,11 +45,7 @@
 #else
 #define pmtmr_ioport 0
 #endif
-extern unsigned long long monotonic_base;
-extern int sysctl_vsyscall;
 extern int nohpet;
-extern unsigned long vxtime_hz;
-extern void time_init_gtod(void);
 
 extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2)));
 
@@ -81,7 +77,6 @@
 extern void __show_regs(struct pt_regs * regs);
 extern void show_regs(struct pt_regs * regs);
 
-extern char *syscall32_page;
 extern void syscall32_cpu_init(void);
 
 extern void setup_node_bootmem(int nodeid, unsigned long start, unsigned long end);
@@ -92,8 +87,6 @@
 
 extern int unhandled_signal(struct task_struct *tsk, int sig);
 
-extern int unsynchronized_tsc(void);
-
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 
 extern unsigned long table_start, table_end;
diff --git a/include/asm-x86_64/setup.h b/include/asm-x86_64/setup.h
index 985d4e3..eaeff73 100644
--- a/include/asm-x86_64/setup.h
+++ b/include/asm-x86_64/setup.h
@@ -1,6 +1,6 @@
 #ifndef _x8664_SETUP_H
 #define _x8664_SETUP_H
 
-#define COMMAND_LINE_SIZE	256
+#define COMMAND_LINE_SIZE	2048
 
 #endif
diff --git a/include/asm-x86_64/termios.h b/include/asm-x86_64/termios.h
index 443b225..35ee59b 100644
--- a/include/asm-x86_64/termios.h
+++ b/include/asm-x86_64/termios.h
@@ -39,24 +39,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* line disciplines */
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14	/* synchronous PPP */
-#define N_HCI		15  /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*	intr=^C		quit=^\		erase=del	kill=^U
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index b9e5320..8c6808a 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -12,38 +12,21 @@
 #include <asm/hpet.h>
 #include <asm/system.h>
 #include <asm/processor.h>
+#include <asm/tsc.h>
 #include <linux/compiler.h>
 
 #define CLOCK_TICK_RATE	PIT_TICK_RATE	/* Underlying HZ */
 
-typedef unsigned long long cycles_t;
-
-static inline cycles_t get_cycles (void)
-{
-	unsigned long long ret;
-
-	rdtscll(ret);
-	return ret;
-}
-
-/* Like get_cycles, but make sure the CPU is synchronized. */
-static __always_inline cycles_t get_cycles_sync(void)
-{
-	unsigned long long ret;
-	unsigned eax;
-	/* Don't do an additional sync on CPUs where we know
-	   RDTSC is already synchronous. */
-	alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC,
-			  "=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
-	rdtscll(ret);
-	return ret;
-}
-
-extern unsigned int cpu_khz;
-
 extern int read_current_timer(unsigned long *timer_value);
 #define ARCH_HAS_READ_CURRENT_TIMER	1
 
-extern struct vxtime_data vxtime;
+#define USEC_PER_TICK (USEC_PER_SEC / HZ)
+#define NSEC_PER_TICK (NSEC_PER_SEC / HZ)
+#define FSEC_PER_TICK (FSEC_PER_SEC / HZ)
 
+#define NS_SCALE        10 /* 2^10, carefully chosen */
+#define US_SCALE        32 /* 2^32, arbitralrily chosen */
+
+extern void mark_tsc_unstable(void);
+extern void set_cyc2ns_scale(unsigned long khz);
 #endif
diff --git a/include/asm-x86_64/tsc.h b/include/asm-x86_64/tsc.h
new file mode 100644
index 0000000..9a0a368
--- /dev/null
+++ b/include/asm-x86_64/tsc.h
@@ -0,0 +1,66 @@
+/*
+ * linux/include/asm-x86_64/tsc.h
+ *
+ * x86_64 TSC related functions
+ */
+#ifndef _ASM_x86_64_TSC_H
+#define _ASM_x86_64_TSC_H
+
+#include <asm/processor.h>
+
+/*
+ * Standard way to access the cycle counter.
+ */
+typedef unsigned long long cycles_t;
+
+extern unsigned int cpu_khz;
+extern unsigned int tsc_khz;
+
+static inline cycles_t get_cycles(void)
+{
+	unsigned long long ret = 0;
+
+#ifndef CONFIG_X86_TSC
+	if (!cpu_has_tsc)
+		return 0;
+#endif
+
+#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
+	rdtscll(ret);
+#endif
+	return ret;
+}
+
+/* Like get_cycles, but make sure the CPU is synchronized. */
+static __always_inline cycles_t get_cycles_sync(void)
+{
+	unsigned long long ret;
+#ifdef X86_FEATURE_SYNC_RDTSC
+	unsigned eax;
+
+	/*
+	 * Don't do an additional sync on CPUs where we know
+	 * RDTSC is already synchronous:
+	 */
+	alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC,
+			  "=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
+#else
+	sync_core();
+#endif
+	rdtscll(ret);
+
+	return ret;
+}
+
+extern void tsc_init(void);
+extern void mark_tsc_unstable(void);
+extern int unsynchronized_tsc(void);
+
+/*
+ * Boot-time check whether the TSCs are synchronized across
+ * all CPUs/cores:
+ */
+extern void check_tsc_sync_source(int cpu);
+extern void check_tsc_sync_target(void);
+
+#endif
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index c0eac51..1981f70 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -37,11 +37,11 @@
  * Uhhuh, this needs 65-bit arithmetic. We have a carry..
  */
 #define __range_not_ok(addr,size) ({ \
-	unsigned long flag,sum; \
+	unsigned long flag,roksum; \
 	__chk_user_ptr(addr); \
 	asm("# range_ok\n\r" \
 		"addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0"  \
-		:"=&r" (flag), "=r" (sum) \
+		:"=&r" (flag), "=r" (roksum) \
 		:"1" (addr),"g" ((long)(size)),"g" (current_thread_info()->addr_limit.seg)); \
 	flag; })
 
@@ -367,4 +367,18 @@
 	return copy_user_generic((__force void *)dst, src, size);
 }
 
+#define ARCH_HAS_NOCACHE_UACCESS 1
+extern long __copy_user_nocache(void *dst, const void __user *src, unsigned size, int zerorest);
+
+static inline int __copy_from_user_nocache(void *dst, const void __user *src, unsigned size)
+{
+	might_sleep();
+	return __copy_user_nocache(dst, (__force void *)src, size, 1);
+}
+
+static inline int __copy_from_user_inatomic_nocache(void *dst, const void __user *src, unsigned size)
+{
+	return __copy_user_nocache(dst, (__force void *)src, size, 0);
+}
+
 #endif /* __X86_64_UACCESS_H */
diff --git a/include/asm-x86_64/vsyscall.h b/include/asm-x86_64/vsyscall.h
index 05cb8dd..82b4afe 100644
--- a/include/asm-x86_64/vsyscall.h
+++ b/include/asm-x86_64/vsyscall.h
@@ -16,51 +16,27 @@
 #ifdef __KERNEL__
 #include <linux/seqlock.h>
 
-#define __section_vxtime __attribute__ ((unused, __section__ (".vxtime"), aligned(16)))
 #define __section_vgetcpu_mode __attribute__ ((unused, __section__ (".vgetcpu_mode"), aligned(16)))
 #define __section_jiffies __attribute__ ((unused, __section__ (".jiffies"), aligned(16)))
-#define __section_sys_tz __attribute__ ((unused, __section__ (".sys_tz"), aligned(16)))
-#define __section_sysctl_vsyscall __attribute__ ((unused, __section__ (".sysctl_vsyscall"), aligned(16)))
-#define __section_xtime __attribute__ ((unused, __section__ (".xtime"), aligned(16)))
-#define __section_xtime_lock __attribute__ ((unused, __section__ (".xtime_lock"), aligned(16)))
 
-#define VXTIME_TSC	1
-#define VXTIME_HPET	2
-#define VXTIME_PMTMR	3
+/* Definitions for CONFIG_GENERIC_TIME definitions */
+#define __section_vsyscall_gtod_data __attribute__ \
+	((unused, __section__ (".vsyscall_gtod_data"),aligned(16)))
+#define __vsyscall_fn __attribute__ ((unused,__section__(".vsyscall_fn")))
 
 #define VGETCPU_RDTSCP	1
 #define VGETCPU_LSL	2
 
-struct vxtime_data {
-	long hpet_address;	/* HPET base address */
-	int last;
-	unsigned long last_tsc;
-	long quot;
-	long tsc_quot;
-	int mode;
-};
-
 #define hpet_readl(a)           readl((const void __iomem *)fix_to_virt(FIX_HPET_BASE) + a)
 #define hpet_writel(d,a)        writel(d, (void __iomem *)fix_to_virt(FIX_HPET_BASE) + a)
 
-/* vsyscall space (readonly) */
-extern struct vxtime_data __vxtime;
 extern int __vgetcpu_mode;
-extern struct timespec __xtime;
 extern volatile unsigned long __jiffies;
-extern struct timezone __sys_tz;
-extern seqlock_t __xtime_lock;
 
 /* kernel space (writeable) */
-extern struct vxtime_data vxtime;
 extern int vgetcpu_mode;
 extern struct timezone sys_tz;
-extern int sysctl_vsyscall;
-extern seqlock_t xtime_lock;
-
-extern int sysctl_vsyscall;
-
-#define ARCH_HAVE_XTIME_LOCK 1
+extern struct vsyscall_gtod_data_t vsyscall_gtod_data;
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-xtensa/mman.h b/include/asm-xtensa/mman.h
index ba394cb..9b92620 100644
--- a/include/asm-xtensa/mman.h
+++ b/include/asm-xtensa/mman.h
@@ -79,7 +79,6 @@
 #define MADV_DOFORK	11		/* do inherit across fork */
 
 /* compatibility flags */
-#define MAP_ANON	MAP_ANONYMOUS
 #define MAP_FILE	0
 
 #endif /* _XTENSA_MMAN_H */
diff --git a/include/asm-xtensa/termios.h b/include/asm-xtensa/termios.h
index 83c6aed..f14b42c 100644
--- a/include/asm-xtensa/termios.h
+++ b/include/asm-xtensa/termios.h
@@ -52,25 +52,6 @@
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
-/* Line disciplines */
-
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6	/* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9	/* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
-#define N_HDLC		13	/* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15      /* Bluetooth HCI UART */
-
 #ifdef __KERNEL__
 
 /*	intr=^C		quit=^\		erase=del	kill=^U
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 5748aec..4e05e93 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -18,8 +18,8 @@
 struct seq_file;
 
 struct crypto_type {
-	unsigned int (*ctxsize)(struct crypto_alg *alg);
-	int (*init)(struct crypto_tfm *tfm);
+	unsigned int (*ctxsize)(struct crypto_alg *alg, u32 type, u32 mask);
+	int (*init)(struct crypto_tfm *tfm, u32 type, u32 mask);
 	void (*exit)(struct crypto_tfm *tfm);
 	void (*show)(struct seq_file *m, struct crypto_alg *alg);
 };
@@ -93,7 +93,8 @@
 int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
 		      struct crypto_instance *inst);
 void crypto_drop_spawn(struct crypto_spawn *spawn);
-struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn);
+struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
+				    u32 mask);
 
 struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
 				       u32 type, u32 mask);
@@ -132,11 +133,28 @@
 	return crypto_tfm_ctx_aligned(&tfm->base);
 }
 
+static inline struct crypto_cipher *crypto_spawn_cipher(
+	struct crypto_spawn *spawn)
+{
+	u32 type = CRYPTO_ALG_TYPE_CIPHER;
+	u32 mask = CRYPTO_ALG_TYPE_MASK;
+
+	return __crypto_cipher_cast(crypto_spawn_tfm(spawn, type, mask));
+}
+
 static inline struct cipher_alg *crypto_cipher_alg(struct crypto_cipher *tfm)
 {
 	return &crypto_cipher_tfm(tfm)->__crt_alg->cra_cipher;
 }
 
+static inline struct crypto_hash *crypto_spawn_hash(struct crypto_spawn *spawn)
+{
+	u32 type = CRYPTO_ALG_TYPE_HASH;
+	u32 mask = CRYPTO_ALG_TYPE_HASH_MASK;
+
+	return __crypto_hash_cast(crypto_spawn_tfm(spawn, type, mask));
+}
+
 static inline void *crypto_hash_ctx_aligned(struct crypto_hash *tfm)
 {
 	return crypto_tfm_ctx_aligned(&tfm->base);
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 683513e..e81e301 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -156,7 +156,6 @@
 header-y += videotext.h
 header-y += vt.h
 header-y += wireless.h
-header-y += xattr.h
 header-y += x25.h
 
 unifdef-y += acct.h
@@ -324,6 +323,7 @@
 unifdef-y += types.h
 unifdef-y += udf_fs_i.h
 unifdef-y += udp.h
+unifdef-y += ufs_fs.h
 unifdef-y += uinput.h
 unifdef-y += uio.h
 unifdef-y += unistd.h
@@ -336,6 +336,7 @@
 unifdef-y += wanrouter.h
 unifdef-y += watchdog.h
 unifdef-y += wireless.h
+unifdef-y += xattr.h
 unifdef-y += xfrm.h
 
 objhdr-y += version.h
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 815f1fb..8bcfaa4 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -75,7 +75,7 @@
 
 typedef int (*acpi_table_handler) (struct acpi_table_header *table);
 
-typedef int (*acpi_madt_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
+typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
 
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 unsigned long acpi_find_rsdp (void);
@@ -85,8 +85,10 @@
 
 int acpi_table_init (void);
 int acpi_table_parse (char *id, acpi_table_handler handler);
-int acpi_table_parse_madt (enum acpi_madt_type id, acpi_madt_entry_handler handler, unsigned int max_entries);
-int acpi_table_parse_srat (enum acpi_srat_type id, acpi_madt_entry_handler handler, unsigned int max_entries);
+int __init acpi_table_parse_entries(char *id, unsigned long table_size,
+	int entry_id, acpi_table_entry_handler handler, unsigned int max_entries);
+int acpi_table_parse_madt (enum acpi_madt_type id, acpi_table_entry_handler handler, unsigned int max_entries);
+int acpi_table_parse_srat (enum acpi_srat_type id, acpi_table_entry_handler handler, unsigned int max_entries);
 int acpi_parse_mcfg (struct acpi_table_header *header);
 void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);
 void acpi_table_print_srat_entry (struct acpi_subtable_header *srat);
diff --git a/include/linux/acpi_pmtmr.h b/include/linux/acpi_pmtmr.h
new file mode 100644
index 0000000..1d0ef1a
--- /dev/null
+++ b/include/linux/acpi_pmtmr.h
@@ -0,0 +1,38 @@
+#ifndef _ACPI_PMTMR_H_
+#define _ACPI_PMTMR_H_
+
+#include <linux/clocksource.h>
+
+/* Number of PMTMR ticks expected during calibration run */
+#define PMTMR_TICKS_PER_SEC 3579545
+
+/* limit it to 24 bits */
+#define ACPI_PM_MASK CLOCKSOURCE_MASK(24)
+
+/* Overrun value */
+#define ACPI_PM_OVRRUN	(1<<24)
+
+#ifdef CONFIG_X86_PM_TIMER
+
+extern u32 acpi_pm_read_verified(void);
+extern u32 pmtmr_ioport;
+
+static inline u32 acpi_pm_read_early(void)
+{
+	if (!pmtmr_ioport)
+		return 0;
+	/* mask the output to 24 bits */
+	return acpi_pm_read_verified() & ACPI_PM_MASK;
+}
+
+#else
+
+static inline u32 acpi_pm_read_early(void)
+{
+	return 0;
+}
+
+#endif
+
+#endif
+
diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h
index a5c8bb5..abc521c 100644
--- a/include/linux/agp_backend.h
+++ b/include/linux/agp_backend.h
@@ -87,10 +87,15 @@
 	u32 physical;
 	u8 is_bound;
 	u8 is_flushed;
+        u8 vmalloc_flag;
 };
 
 #define AGP_NORMAL_MEMORY 0
 
+#define AGP_USER_TYPES (1 << 16)
+#define AGP_USER_MEMORY (AGP_USER_TYPES)
+#define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1)
+
 extern struct agp_bridge_data *agp_bridge;
 extern struct list_head agp_bridges;
 
diff --git a/include/linux/apm-emulation.h b/include/linux/apm-emulation.h
new file mode 100644
index 0000000..e6d8003
--- /dev/null
+++ b/include/linux/apm-emulation.h
@@ -0,0 +1,62 @@
+/* -*- linux-c -*-
+ *
+ * (C) 2003 zecke@handhelds.org
+ *
+ * GPL version 2
+ *
+ * based on arch/arm/kernel/apm.c
+ * factor out the information needed by architectures to provide
+ * apm status
+ */
+#ifndef __LINUX_APM_EMULATION_H
+#define __LINUX_APM_EMULATION_H
+
+#include <linux/apm_bios.h>
+
+/*
+ * This structure gets filled in by the machine specific 'get_power_status'
+ * implementation.  Any fields which are not set default to a safe value.
+ */
+struct apm_power_info {
+	unsigned char	ac_line_status;
+#define APM_AC_OFFLINE			0
+#define APM_AC_ONLINE			1
+#define APM_AC_BACKUP			2
+#define APM_AC_UNKNOWN			0xff
+
+	unsigned char	battery_status;
+#define APM_BATTERY_STATUS_HIGH		0
+#define APM_BATTERY_STATUS_LOW		1
+#define APM_BATTERY_STATUS_CRITICAL	2
+#define APM_BATTERY_STATUS_CHARGING	3
+#define APM_BATTERY_STATUS_NOT_PRESENT	4
+#define APM_BATTERY_STATUS_UNKNOWN	0xff
+
+	unsigned char	battery_flag;
+#define APM_BATTERY_FLAG_HIGH		(1 << 0)
+#define APM_BATTERY_FLAG_LOW		(1 << 1)
+#define APM_BATTERY_FLAG_CRITICAL	(1 << 2)
+#define APM_BATTERY_FLAG_CHARGING	(1 << 3)
+#define APM_BATTERY_FLAG_NOT_PRESENT	(1 << 7)
+#define APM_BATTERY_FLAG_UNKNOWN	0xff
+
+	int		battery_life;
+	int		time;
+	int		units;
+#define APM_UNITS_MINS			0
+#define APM_UNITS_SECS			1
+#define APM_UNITS_UNKNOWN		-1
+
+};
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+extern void (*apm_get_power_status)(struct apm_power_info *);
+
+/*
+ * Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND)
+ */
+void apm_queue_event(apm_event_t event);
+
+#endif /* __LINUX_APM_EMULATION_H */
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 1df9416..272736e 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -44,9 +44,9 @@
 	ATA_MAX_SECTORS_LBA48	= 65535,/* TODO: 65536? */
 
 	ATA_ID_WORDS		= 256,
-	ATA_ID_SERNO_OFS	= 10,
-	ATA_ID_FW_REV_OFS	= 23,
-	ATA_ID_PROD_OFS		= 27,
+	ATA_ID_SERNO		= 10,
+	ATA_ID_FW_REV		= 23,
+	ATA_ID_PROD		= 27,
 	ATA_ID_OLD_PIO_MODES	= 51,
 	ATA_ID_FIELD_VALID	= 53,
 	ATA_ID_MWDMA_MODES	= 63,
@@ -58,8 +58,11 @@
 	ATA_ID_MAJOR_VER	= 80,
 	ATA_ID_PIO4		= (1 << 1),
 
+	ATA_ID_SERNO_LEN	= 20,
+	ATA_ID_FW_REV_LEN	= 8,
+	ATA_ID_PROD_LEN		= 40,
+
 	ATA_PCI_CTL_OFS		= 2,
-	ATA_SERNO_LEN		= 20,
 	ATA_UDMA0		= (1 << 0),
 	ATA_UDMA1		= ATA_UDMA0 | (1 << 1),
 	ATA_UDMA2		= ATA_UDMA1 | (1 << 2),
@@ -296,6 +299,8 @@
 #define ata_id_queue_depth(id)	(((id)[75] & 0x1f) + 1)
 #define ata_id_removeable(id)	((id)[0] & (1 << 7))
 #define ata_id_has_dword_io(id)	((id)[50] & (1 << 0))
+#define ata_id_iordy_disable(id) ((id)[49] & (1 << 10))
+#define ata_id_has_iordy(id) ((id)[49] & (1 << 9))
 #define ata_id_u32(id,n)	\
 	(((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)]))
 #define ata_id_u64(id,n)	\
@@ -347,7 +352,7 @@
 {
 	if (ata_id_major_version(dev_id) >= 5 && ata_id_is_sata(dev_id))
 		return 0;	/* SATA */
-	if (dev_id[93] & 0x4000)
+	if ((dev_id[93] & 0xE000) == 0x6000)
 		return 0;	/* 80 wire */
 	return 1;
 }
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index 75b8bac..d12984d 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -182,7 +182,7 @@
 
 extern struct atalk_route atrtr_default;
 
-extern struct file_operations atalk_seq_arp_fops;
+extern const struct file_operations atalk_seq_arp_fops;
 
 extern int sysctl_aarp_expiry_time;
 extern int sysctl_aarp_tick_time;
diff --git a/include/linux/atmarp.h b/include/linux/atmarp.h
index ee108f9..231f4bd 100644
--- a/include/linux/atmarp.h
+++ b/include/linux/atmarp.h
@@ -6,9 +6,7 @@
 #ifndef _LINUX_ATMARP_H
 #define _LINUX_ATMARP_H
 
-#ifdef __KERNEL__
 #include <linux/types.h>
-#endif
 #include <linux/atmapi.h>
 #include <linux/atmioc.h>
 
diff --git a/include/linux/atmel_pdc.h b/include/linux/atmel_pdc.h
new file mode 100644
index 0000000..5058a31
--- /dev/null
+++ b/include/linux/atmel_pdc.h
@@ -0,0 +1,36 @@
+/*
+ * include/linux/atmel_pdc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Peripheral Data Controller (PDC) 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 ATMEL_PDC_H
+#define ATMEL_PDC_H
+
+#define ATMEL_PDC_RPR		0x100	/* Receive Pointer Register */
+#define ATMEL_PDC_RCR		0x104	/* Receive Counter Register */
+#define ATMEL_PDC_TPR		0x108	/* Transmit Pointer Register */
+#define ATMEL_PDC_TCR		0x10c	/* Transmit Counter Register */
+#define ATMEL_PDC_RNPR		0x110	/* Receive Next Pointer Register */
+#define ATMEL_PDC_RNCR		0x114	/* Receive Next Counter Register */
+#define ATMEL_PDC_TNPR		0x118	/* Transmit Next Pointer Register */
+#define ATMEL_PDC_TNCR		0x11c	/* Transmit Next Counter Register */
+
+#define ATMEL_PDC_PTCR		0x120	/* Transfer Control Register */
+#define		ATMEL_PDC_RXTEN		(1 << 0)	/* Receiver Transfer Enable */
+#define		ATMEL_PDC_RXTDIS	(1 << 1)	/* Receiver Transfer Disable */
+#define		ATMEL_PDC_TXTEN		(1 << 8)	/* Transmitter Transfer Enable */
+#define		ATMEL_PDC_TXTDIS	(1 << 9)	/* Transmitter Transfer Disable */
+
+#define ATMEL_PDC_PTSR		0x124	/* Transfer Status Register */
+
+#endif
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 0e07db6..229fa01 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -89,6 +89,7 @@
 #define AUDIT_MQ_NOTIFY		1314	/* POSIX MQ notify record type */
 #define AUDIT_MQ_GETSETATTR	1315	/* POSIX MQ get/set attribute record type */
 #define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
+#define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -387,6 +388,7 @@
 extern int audit_bprm(struct linux_binprm *bprm);
 extern int audit_socketcall(int nargs, unsigned long *args);
 extern int audit_sockaddr(int len, void *addr);
+extern int __audit_fd_pair(int fd1, int fd2);
 extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
 extern int audit_set_macxattr(const char *name);
 extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr);
@@ -401,6 +403,12 @@
 		return __audit_ipc_obj(ipcp);
 	return 0;
 }
+static inline int audit_fd_pair(int fd1, int fd2)
+{
+	if (unlikely(!audit_dummy_context()))
+		return __audit_fd_pair(fd1, fd2);
+	return 0;
+}
 static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
 {
 	if (unlikely(!audit_dummy_context()))
@@ -459,6 +467,7 @@
 #define audit_ipc_set_perm(q,u,g,m) ({ 0; })
 #define audit_bprm(p) ({ 0; })
 #define audit_socketcall(n,a) ({ 0; })
+#define audit_fd_pair(n,a) ({ 0; })
 #define audit_sockaddr(len, addr) ({ 0; })
 #define audit_avc_path(dentry, mnt) ({ 0; })
 #define audit_set_macxattr(n) do { ; } while (0)
diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h
index 0a6bc52..31a2954 100644
--- a/include/linux/auto_fs4.h
+++ b/include/linux/auto_fs4.h
@@ -59,6 +59,13 @@
 	char name[NAME_MAX+1];
 };
 
+union autofs_packet_union {
+	struct autofs_packet_hdr hdr;
+	struct autofs_packet_missing missing;
+	struct autofs_packet_expire expire;
+	struct autofs_packet_expire_multi expire_multi;
+};
+
 /* autofs v5 common packet struct */
 struct autofs_v5_packet {
 	struct autofs_packet_hdr hdr;
@@ -78,12 +85,13 @@
 typedef struct autofs_v5_packet autofs_packet_missing_direct_t;
 typedef struct autofs_v5_packet autofs_packet_expire_direct_t;
 
-union autofs_packet_union {
+union autofs_v5_packet_union {
 	struct autofs_packet_hdr hdr;
-	struct autofs_packet_missing missing;
-	struct autofs_packet_expire expire;
-	struct autofs_packet_expire_multi expire_multi;
 	struct autofs_v5_packet v5_packet;
+	autofs_packet_missing_indirect_t missing_indirect;
+	autofs_packet_expire_indirect_t expire_indirect;
+	autofs_packet_missing_direct_t missing_direct;
+	autofs_packet_expire_direct_t expire_direct;
 };
 
 #define AUTOFS_IOC_EXPIRE_MULTI		_IOW(0x93,0x66,int)
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index a5cf1be..1023ba0 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -9,17 +9,28 @@
 #define _LINUX_BACKLIGHT_H
 
 #include <linux/device.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 
+/* Notes on locking:
+ *
+ * backlight_device->ops_lock is an internal backlight lock protecting the
+ * ops pointer and no code outside the core should need to touch it.
+ *
+ * Access to update_status() is serialised by the update_lock mutex since
+ * most drivers seem to need this and historically get it wrong.
+ *
+ * Most drivers don't need locking on their get_brightness() method.
+ * If yours does, you need to implement it in the driver. You can use the
+ * update_lock mutex if appropriate.
+ *
+ * Any other use of the locks below is probably wrong.
+ */
+
 struct backlight_device;
 struct fb_info;
 
-/* This structure defines all the properties of a backlight
-   (usually attached to a LCD). */
-struct backlight_properties {
-	/* Owner module */
-	struct module *owner;
-
+struct backlight_ops {
 	/* Notify the backlight driver some property has changed */
 	int (*update_status)(struct backlight_device *);
 	/* Return the current backlight brightness (accounting for power,
@@ -28,7 +39,10 @@
 	/* Check if given framebuffer device is the one bound to this backlight;
 	   return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */
 	int (*check_fb)(struct fb_info *);
+};
 
+/* This structure defines all the properties of a backlight */
+struct backlight_properties {
 	/* Current User requested brightness (0 - max_brightness) */
 	int brightness;
 	/* Maximal value for brightness (read-only) */
@@ -41,20 +55,34 @@
 };
 
 struct backlight_device {
-	/* This protects the 'props' field. If 'props' is NULL, the driver that
+	/* Backlight properties */
+	struct backlight_properties props;
+
+	/* Serialise access to update_status method */
+	struct mutex update_lock;
+
+	/* This protects the 'ops' field. If 'ops' is NULL, the driver that
 	   registered this device has been unloaded, and if class_get_devdata()
 	   points to something in the body of that driver, it is also invalid. */
-	struct semaphore sem;
-	/* If this is NULL, the backing module is unloaded */
-	struct backlight_properties *props;
+	struct mutex ops_lock;
+	struct backlight_ops *ops;
+
 	/* The framebuffer notifier block */
 	struct notifier_block fb_notif;
 	/* The class device structure */
 	struct class_device class_dev;
 };
 
+static inline void backlight_update_status(struct backlight_device *bd)
+{
+	mutex_lock(&bd->update_lock);
+	if (bd->ops && bd->ops->update_status)
+		bd->ops->update_status(bd);
+	mutex_unlock(&bd->update_lock);
+}
+
 extern struct backlight_device *backlight_device_register(const char *name,
-	struct device *dev,void *devdata,struct backlight_properties *bp);
+	struct device *dev, void *devdata, struct backlight_ops *ops);
 extern void backlight_device_unregister(struct backlight_device *bd);
 
 #define to_backlight_device(obj) container_of(obj, struct backlight_device, class_dev)
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index c1e82c5..2d956cd 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -59,6 +59,7 @@
 	int (*load_shlib)(struct file *);
 	int (*core_dump)(long signr, struct pt_regs * regs, struct file * file);
 	unsigned long min_coredump;	/* minimal dump size */
+	int hasvdso;
 };
 
 extern int register_binfmt(struct linux_binfmt *);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 36a6eac..83dcd8c 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -82,7 +82,6 @@
 
 	unsigned long last_end_request;
 	sector_t last_request_pos;
- 	unsigned long last_queue;
 
 	unsigned long ttime_total;
 	unsigned long ttime_samples;
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 5d9fb0e..dd27b1c 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -34,6 +34,7 @@
 	BH_Write_EIO,	/* I/O error on write */
 	BH_Ordered,	/* ordered write */
 	BH_Eopnotsupp,	/* operation not supported (barrier) */
+	BH_Unwritten,	/* Buffer is allocated on disk but not written */
 
 	BH_PrivateStart,/* not a state bit, but the first bit available
 			 * for private allocation by other entities
@@ -126,6 +127,7 @@
 BUFFER_FNS(Write_EIO, write_io_error)
 BUFFER_FNS(Ordered, ordered)
 BUFFER_FNS(Eopnotsupp, eopnotsupp)
+BUFFER_FNS(Unwritten, unwritten)
 
 #define bh_offset(bh)		((unsigned long)(bh)->b_data & ~PAGE_MASK)
 #define touch_buffer(bh)	mark_page_accessed(bh->b_page)
@@ -172,12 +174,14 @@
 void thaw_bdev(struct block_device *, struct super_block *);
 int fsync_super(struct super_block *);
 int fsync_no_super(struct block_device *);
-struct buffer_head *__find_get_block(struct block_device *, sector_t, int);
-struct buffer_head * __getblk(struct block_device *, sector_t, int);
+struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block,
+			unsigned size);
+struct buffer_head *__getblk(struct block_device *bdev, sector_t block,
+			unsigned size);
 void __brelse(struct buffer_head *);
 void __bforget(struct buffer_head *);
-void __breadahead(struct block_device *, sector_t block, int size);
-struct buffer_head *__bread(struct block_device *, sector_t block, int size);
+void __breadahead(struct block_device *, sector_t block, unsigned int size);
+struct buffer_head *__bread(struct block_device *, sector_t block, unsigned size);
 struct buffer_head *alloc_buffer_head(gfp_t gfp_flags);
 void free_buffer_head(struct buffer_head * bh);
 void FASTCALL(unlock_buffer(struct buffer_head *bh));
diff --git a/include/linux/byteorder/Kbuild b/include/linux/byteorder/Kbuild
index 56499ab..79beddd 100644
--- a/include/linux/byteorder/Kbuild
+++ b/include/linux/byteorder/Kbuild
@@ -1,7 +1,5 @@
 header-y += big_endian.h
 header-y += little_endian.h
-header-y += pdp_endian.h
 
 unifdef-y += generic.h
-unifdef-y += swabb.h
 unifdef-y += swab.h
diff --git a/include/linux/byteorder/pdp_endian.h b/include/linux/byteorder/pdp_endian.h
deleted file mode 100644
index 618631c..0000000
--- a/include/linux/byteorder/pdp_endian.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef _LINUX_BYTEORDER_PDP_ENDIAN_H
-#define _LINUX_BYTEORDER_PDP_ENDIAN_H
-
-/*
- * Could have been named NUXI-endian, but we use the same name as in glibc.
- * hopefully only the PDP and its evolutions (old VAXen in compatibility mode)
- * should ever use this braindead byteorder.
- * This file *should* work, but has not been tested.
- *
- * little-endian is 1234; big-endian is 4321; nuxi/pdp-endian is 3412
- *
- * I thought vaxen were NUXI-endian, but was told they were correct-endian
- * (little-endian), though indeed there existed NUXI-endian machines
- * (DEC PDP-11 and old VAXen in compatibility mode).
- * This makes this file a bit useless, but as a proof-of-concept.
- *
- * But what does a __u64 look like: is it 34127856 or 78563412 ???
- * I don't dare imagine! Hence, no 64-bit byteorder support yet.
- * Hopefully, there 64-bit pdp-endian support shouldn't ever be required.
- *
- */
-
-#ifndef __PDP_ENDIAN
-#define __PDP_ENDIAN 3412
-#endif
-#ifndef __PDP_ENDIAN_BITFIELD
-#define __PDP_ENDIAN_BITFIELD
-#endif
-
-#include <linux/byteorder/swab.h>
-#include <linux/byteorder/swabb.h>
-
-#define __constant_htonl(x) ___constant_swahb32((x))
-#define __constant_ntohl(x) ___constant_swahb32((x))
-#define __constant_htons(x) ___constant_swab16((x))
-#define __constant_ntohs(x) ___constant_swab16((x))
-#define __constant_cpu_to_le64(x) I DON'T KNOW
-#define __constant_le64_to_cpu(x) I DON'T KNOW
-#define __constant_cpu_to_le32(x) ___constant_swahw32((x))
-#define __constant_le32_to_cpu(x) ___constant_swahw32((x))
-#define __constant_cpu_to_le16(x) ((__u16)(x)
-#define __constant_le16_to_cpu(x) ((__u16)(x)
-#define __constant_cpu_to_be64(x) I DON'T KNOW
-#define __constant_be64_to_cpu(x) I DON'T KNOW
-#define __constant_cpu_to_be32(x) ___constant_swahb32((x))
-#define __constant_be32_to_cpu(x) ___constant_swahb32((x))
-#define __constant_cpu_to_be16(x) ___constant_swab16((x))
-#define __constant_be16_to_cpu(x) ___constant_swab16((x))
-#define __cpu_to_le64(x) I DON'T KNOW
-#define __le64_to_cpu(x) I DON'T KNOW
-#define __cpu_to_le32(x) ___swahw32((x))
-#define __le32_to_cpu(x) ___swahw32((x))
-#define __cpu_to_le16(x) ((__u16)(x)
-#define __le16_to_cpu(x) ((__u16)(x)
-#define __cpu_to_be64(x) I DON'T KNOW
-#define __be64_to_cpu(x) I DON'T KNOW
-#define __cpu_to_be32(x) __swahb32((x))
-#define __be32_to_cpu(x) __swahb32((x))
-#define __cpu_to_be16(x) __swab16((x))
-#define __be16_to_cpu(x) __swab16((x))
-#define __cpu_to_le64p(x) I DON'T KNOW
-#define __le64_to_cpup(x) I DON'T KNOW
-#define __cpu_to_le32p(x) ___swahw32p((x))
-#define __le32_to_cpup(x) ___swahw32p((x))
-#define __cpu_to_le16p(x) (*(__u16*)(x))
-#define __le16_to_cpup(x) (*(__u16*)(x))
-#define __cpu_to_be64p(x) I DON'T KNOW
-#define __be64_to_cpup(x) I DON'T KNOW
-#define __cpu_to_be32p(x) __swahb32p((x))
-#define __be32_to_cpup(x) __swahb32p((x))
-#define __cpu_to_be16p(x) __swab16p((x))
-#define __be16_to_cpup(x) __swab16p((x))
-#define __cpu_to_le64s(x) I DON'T KNOW
-#define __le64_to_cpus(x) I DON'T KNOW
-#define __cpu_to_le32s(x) ___swahw32s((x))
-#define __le32_to_cpus(x) ___swahw32s((x))
-#define __cpu_to_le16s(x) do {} while (0)
-#define __le16_to_cpus(x) do {} while (0)
-#define __cpu_to_be64s(x) I DON'T KNOW
-#define __be64_to_cpus(x) I DON'T KNOW
-#define __cpu_to_be32s(x) __swahb32s((x))
-#define __be32_to_cpus(x) __swahb32s((x))
-#define __cpu_to_be16s(x) __swab16s((x))
-#define __be16_to_cpus(x) __swab16s((x))
-
-#include <linux/byteorder/generic.h>
-
-#endif /* _LINUX_BYTEORDER_PDP_ENDIAN_H */
diff --git a/include/linux/byteorder/swabb.h b/include/linux/byteorder/swabb.h
index ae5e5f9..8c780c7 100644
--- a/include/linux/byteorder/swabb.h
+++ b/include/linux/byteorder/swabb.h
@@ -25,6 +25,8 @@
  *
  */
 
+#include <linux/types.h>
+
 #define ___swahw32(x) \
 ({ \
 	__u32 __x = (x); \
@@ -77,19 +79,14 @@
 /*
  * Allow constant folding
  */
-#if defined(__GNUC__) && defined(__OPTIMIZE__)
-#  define __swahw32(x) \
+#define __swahw32(x) \
 (__builtin_constant_p((__u32)(x)) ? \
  ___swahw32((x)) : \
  __fswahw32((x)))
-#  define __swahb32(x) \
+#define __swahb32(x) \
 (__builtin_constant_p((__u32)(x)) ? \
  ___swahb32((x)) : \
  __fswahb32((x)))
-#else
-#  define __swahw32(x) __fswahw32(x)
-#  define __swahb32(x) __fswahb32(x)
-#endif /* OPTIMIZE */
 
 
 static inline __u32 __fswahw32(__u32 x)
@@ -128,13 +125,11 @@
  */
 #endif /* __BYTEORDER_HAS_U64__ */
 
-#if defined(__KERNEL__)
 #define swahw32 __swahw32
 #define swahb32 __swahb32
 #define swahw32p __swahw32p
 #define swahb32p __swahb32p
 #define swahw32s __swahw32s
 #define swahb32s __swahb32s
-#endif
 
 #endif /* _LINUX_BYTEORDER_SWABB_H */
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index bbbe7b4..f50f04b 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -939,7 +939,7 @@
 	int speed;			/* maximum speed for reading data */
 	int capacity;			/* number of discs in jukebox */
 /* device-related storage */
-	int options		: 30;	/* options flags */
+	unsigned int options	: 30;	/* options flags */
 	unsigned mc_flags	: 2;	/* media change buffer flags */
     	int use_count;                  /* number of times device opened */
     	char name[20];                  /* name of the device type */
diff --git a/include/linux/cfag12864b.h b/include/linux/cfag12864b.h
new file mode 100644
index 0000000..1605dd8
--- /dev/null
+++ b/include/linux/cfag12864b.h
@@ -0,0 +1,82 @@
+/*
+ *    Filename: cfag12864b.h
+ *     Version: 0.1.0
+ * Description: cfag12864b LCD driver header
+ *     License: GPLv2
+ *
+ *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *        Date: 2006-10-12
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _CFAG12864B_H_
+#define _CFAG12864B_H_
+
+#define CFAG12864B_WIDTH	(128)
+#define CFAG12864B_HEIGHT	(64)
+#define CFAG12864B_CONTROLLERS	(2)
+#define CFAG12864B_PAGES	(8)
+#define CFAG12864B_ADDRESSES	(64)
+#define CFAG12864B_SIZE		((CFAG12864B_CONTROLLERS) * \
+				(CFAG12864B_PAGES) * \
+				(CFAG12864B_ADDRESSES))
+
+/*
+ * The driver will blit this buffer to the LCD
+ *
+ * Its size is CFAG12864B_SIZE.
+ */
+extern unsigned char * cfag12864b_buffer;
+
+/*
+ * Get the refresh rate of the LCD
+ *
+ * Returns the refresh rate (hertzs).
+ */
+extern unsigned int cfag12864b_getrate(void);
+
+/*
+ * Enable refreshing
+ *
+ * Returns 0 if successful (anyone was using it),
+ * or != 0 if failed (someone is using it).
+ */
+extern unsigned char cfag12864b_enable(void);
+
+/*
+ * Disable refreshing
+ *
+ * You should call this only when you finish using the LCD.
+ */
+extern void cfag12864b_disable(void);
+
+/*
+ * Is enabled refreshing? (is anyone using the module?)
+ *
+ * Returns 0 if refreshing is not enabled (anyone is using it),
+ * or != 0 if refreshing is enabled (someone is using it).
+ *
+ * Useful for buffer read-only modules.
+ */
+extern unsigned char cfag12864b_isenabled(void);
+
+/*
+ * Is the module inited?
+ */
+extern unsigned char cfag12864b_isinited(void);
+
+#endif /* _CFAG12864B_H_ */
+
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
new file mode 100644
index 0000000..4ea7e7b
--- /dev/null
+++ b/include/linux/clockchips.h
@@ -0,0 +1,142 @@
+/*  linux/include/linux/clockchips.h
+ *
+ *  This file contains the structure definitions for clockchips.
+ *
+ *  If you are not a clockchip, or the time of day code, you should
+ *  not be including this file!
+ */
+#ifndef _LINUX_CLOCKCHIPS_H
+#define _LINUX_CLOCKCHIPS_H
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+
+#include <linux/clocksource.h>
+#include <linux/cpumask.h>
+#include <linux/ktime.h>
+#include <linux/notifier.h>
+
+struct clock_event_device;
+
+/* Clock event mode commands */
+enum clock_event_mode {
+	CLOCK_EVT_MODE_UNUSED = 0,
+	CLOCK_EVT_MODE_SHUTDOWN,
+	CLOCK_EVT_MODE_PERIODIC,
+	CLOCK_EVT_MODE_ONESHOT,
+};
+
+/* Clock event notification values */
+enum clock_event_nofitiers {
+	CLOCK_EVT_NOTIFY_ADD,
+	CLOCK_EVT_NOTIFY_BROADCAST_ON,
+	CLOCK_EVT_NOTIFY_BROADCAST_OFF,
+	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
+	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
+	CLOCK_EVT_NOTIFY_SUSPEND,
+	CLOCK_EVT_NOTIFY_RESUME,
+	CLOCK_EVT_NOTIFY_CPU_DEAD,
+};
+
+/*
+ * Clock event features
+ */
+#define CLOCK_EVT_FEAT_PERIODIC		0x000001
+#define CLOCK_EVT_FEAT_ONESHOT		0x000002
+/*
+ * x86(64) specific misfeatures:
+ *
+ * - Clockevent source stops in C3 State and needs broadcast support.
+ * - Local APIC timer is used as a dummy device.
+ */
+#define CLOCK_EVT_FEAT_C3STOP		0x000004
+#define CLOCK_EVT_FEAT_DUMMY		0x000008
+
+/**
+ * struct clock_event_device - clock event device descriptor
+ * @name:		ptr to clock event name
+ * @hints:		usage hints
+ * @max_delta_ns:	maximum delta value in ns
+ * @min_delta_ns:	minimum delta value in ns
+ * @mult:		nanosecond to cycles multiplier
+ * @shift:		nanoseconds to cycles divisor (power of two)
+ * @rating:		variable to rate clock event devices
+ * @irq:		irq number (only for non cpu local devices)
+ * @cpumask:		cpumask to indicate for which cpus this device works
+ * @set_next_event:	set next event
+ * @set_mode:		set mode function
+ * @evthandler:		Assigned by the framework to be called by the low
+ *			level handler of the event source
+ * @broadcast:		function to broadcast events
+ * @list:		list head for the management code
+ * @mode:		operating mode assigned by the management code
+ * @next_event:		local storage for the next event in oneshot mode
+ */
+struct clock_event_device {
+	const char		*name;
+	unsigned int		features;
+	unsigned long		max_delta_ns;
+	unsigned long		min_delta_ns;
+	unsigned long		mult;
+	int			shift;
+	int			rating;
+	int			irq;
+	cpumask_t		cpumask;
+	int			(*set_next_event)(unsigned long evt,
+						  struct clock_event_device *);
+	void			(*set_mode)(enum clock_event_mode mode,
+					    struct clock_event_device *);
+	void			(*event_handler)(struct clock_event_device *);
+	void			(*broadcast)(cpumask_t mask);
+	struct list_head	list;
+	enum clock_event_mode	mode;
+	ktime_t			next_event;
+};
+
+/*
+ * Calculate a multiplication factor for scaled math, which is used to convert
+ * nanoseconds based values to clock ticks:
+ *
+ * clock_ticks = (nanoseconds * factor) >> shift.
+ *
+ * div_sc is the rearranged equation to calculate a factor from a given clock
+ * ticks / nanoseconds ratio:
+ *
+ * factor = (clock_ticks << shift) / nanoseconds
+ */
+static inline unsigned long div_sc(unsigned long ticks, unsigned long nsec,
+				   int shift)
+{
+	uint64_t tmp = ((uint64_t)ticks) << shift;
+
+	do_div(tmp, nsec);
+	return (unsigned long) tmp;
+}
+
+/* Clock event layer functions */
+extern unsigned long clockevent_delta2ns(unsigned long latch,
+					 struct clock_event_device *evt);
+extern void clockevents_register_device(struct clock_event_device *dev);
+
+extern void clockevents_exchange_device(struct clock_event_device *old,
+					struct clock_event_device *new);
+extern
+struct clock_event_device *clockevents_request_device(unsigned int features,
+						      cpumask_t cpumask);
+extern void clockevents_release_device(struct clock_event_device *dev);
+extern void clockevents_set_mode(struct clock_event_device *dev,
+				 enum clock_event_mode mode);
+extern int clockevents_register_notifier(struct notifier_block *nb);
+extern void clockevents_unregister_notifier(struct notifier_block *nb);
+extern int clockevents_program_event(struct clock_event_device *dev,
+				     ktime_t expires, ktime_t now);
+
+extern void clockevents_notify(unsigned long reason, void *arg);
+
+#else
+
+static inline void clockevents_resume_events(void) { }
+#define clockevents_notify(reason, arg) do { } while (0)
+
+#endif
+
+#endif
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 1622d23..daa4940 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -12,11 +12,13 @@
 #include <linux/timex.h>
 #include <linux/time.h>
 #include <linux/list.h>
+#include <linux/timer.h>
 #include <asm/div64.h>
 #include <asm/io.h>
 
 /* clocksource cycle base type */
 typedef u64 cycle_t;
+struct clocksource;
 
 /**
  * struct clocksource - hardware abstraction for a free running counter
@@ -44,8 +46,8 @@
  *			subtraction of non 64 bit counters
  * @mult:		cycle to nanosecond multiplier
  * @shift:		cycle to nanosecond divisor (power of two)
- * @update_callback:	called when safe to alter clocksource values
- * @is_continuous:	defines if clocksource is free-running.
+ * @flags:		flags describing special properties
+ * @vread:		vsyscall based read
  * @cycle_interval:	Used internally by timekeeping core, please ignore.
  * @xtime_interval:	Used internally by timekeeping core, please ignore.
  */
@@ -57,15 +59,30 @@
 	cycle_t mask;
 	u32 mult;
 	u32 shift;
-	int (*update_callback)(void);
-	int is_continuous;
+	unsigned long flags;
+	cycle_t (*vread)(void);
 
 	/* timekeeping specific data, ignore */
 	cycle_t cycle_last, cycle_interval;
 	u64 xtime_nsec, xtime_interval;
 	s64 error;
+
+#ifdef CONFIG_CLOCKSOURCE_WATCHDOG
+	/* Watchdog related data, used by the framework */
+	struct list_head wd_list;
+	cycle_t wd_last;
+#endif
 };
 
+/*
+ * Clock source flags bits::
+ */
+#define CLOCK_SOURCE_IS_CONTINUOUS		0x01
+#define CLOCK_SOURCE_MUST_VERIFY		0x02
+
+#define CLOCK_SOURCE_WATCHDOG			0x10
+#define CLOCK_SOURCE_VALID_FOR_HRES		0x20
+
 /* simplify initialization of mask field */
 #define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL<<bits)-1) : -1)
 
@@ -178,8 +195,16 @@
 
 
 /* used to install a new clocksource */
-int clocksource_register(struct clocksource*);
-void clocksource_reselect(void);
-struct clocksource* clocksource_get_next(void);
+extern int clocksource_register(struct clocksource*);
+extern struct clocksource* clocksource_get_next(void);
+extern void clocksource_change_rating(struct clocksource *cs, int rating);
+
+#ifdef CONFIG_GENERIC_TIME_VSYSCALL
+extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
+#else
+static inline void update_vsyscall(struct timespec *ts, struct clocksource *c)
+{
+}
+#endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
index 4c2632a..e4ac016 100644
--- a/include/linux/coda_linux.h
+++ b/include/linux/coda_linux.h
@@ -23,9 +23,9 @@
 #include <linux/coda_fs_i.h>
 
 /* operations */
-extern struct inode_operations coda_dir_inode_operations;
-extern struct inode_operations coda_file_inode_operations;
-extern struct inode_operations coda_ioctl_inode_operations;
+extern const struct inode_operations coda_dir_inode_operations;
+extern const struct inode_operations coda_file_inode_operations;
+extern const struct inode_operations coda_ioctl_inode_operations;
 
 extern const struct address_space_operations coda_file_aops;
 extern const struct address_space_operations coda_symlink_aops;
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 6e1c44a..9008eab 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -27,6 +27,13 @@
 #define __inline__	__inline__	__attribute__((always_inline))
 #define __inline	__inline	__attribute__((always_inline))
 #define __deprecated			__attribute__((deprecated))
+#define __packed			__attribute__((packed))
+#define __weak				__attribute__((weak))
+#define __naked				__attribute__((naked))
+#define __noreturn			__attribute__((noreturn))
+#define __pure				__attribute__((pure))
+#define __aligned(x)			__attribute__((aligned(x)))
+#define __printf(a,b)			__attribute__((format(printf,a,b)))
 #define  noinline			__attribute__((noinline))
 #define __attribute_pure__		__attribute__((pure))
 #define __attribute_const__		__attribute__((__const__))
diff --git a/include/linux/console.h b/include/linux/console.h
index 7d04202..de25ee3 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -21,6 +21,7 @@
 struct console_font_op;
 struct console_font;
 struct module;
+struct tty_struct;
 
 /*
  * this is what the terminal answers to a ESC-Z or csi0c query.
@@ -132,6 +133,9 @@
 int mda_console_init(void);
 void prom_con_init(void);
 
+void vcs_make_sysfs(struct tty_struct *tty);
+void vcs_remove_sysfs(struct tty_struct *tty);
+
 /* Some debug stub to catch some of the obvious races in the VT code */
 #if 1
 #define WARN_CONSOLE_UNLOCKED()	WARN_ON(!is_console_locked() && !oops_in_progress)
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index ed6c0fe..a86162b 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -11,6 +11,7 @@
 
 #include <linux/wait.h>
 #include <linux/vt.h>
+#include <linux/workqueue.h>
 
 struct vt_struct;
 
@@ -103,6 +104,7 @@
 
 struct vc {
 	struct vc_data *d;
+	struct work_struct SAK_work;
 
 	/* might add  scrmem, vt_struct, kbd  at some time,
 	   to have everything in one place - the disadvantage
@@ -110,6 +112,7 @@
 };
 
 extern struct vc vc_cons [MAX_NR_CONSOLES];
+extern void vc_SAK(struct work_struct *work);
 
 #define CUR_DEF		0
 #define CUR_NONE	1
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index bfb5202..769ddc6 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -49,10 +49,20 @@
 
 #ifdef CONFIG_SMP
 /* Need to know about CPUs going up/down? */
-extern int register_cpu_notifier(struct notifier_block *nb);
 #ifdef CONFIG_HOTPLUG_CPU
+extern int register_cpu_notifier(struct notifier_block *nb);
 extern void unregister_cpu_notifier(struct notifier_block *nb);
 #else
+
+#ifndef MODULE
+extern int register_cpu_notifier(struct notifier_block *nb);
+#else
+static inline int register_cpu_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+#endif
+
 static inline void unregister_cpu_notifier(struct notifier_block *nb)
 {
 }
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 7f008f6..0899e2c 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -84,9 +84,6 @@
         unsigned int		policy; /* see above */
 	struct cpufreq_governor	*governor; /* see below */
 
- 	struct mutex		lock;   /* CPU ->setpolicy or ->target may
-					   only be called once a time */
-
 	struct work_struct	update; /* if update_policy() needs to be
 					 * called, but you're in IRQ context */
 
@@ -172,11 +169,16 @@
 				   unsigned int relation);
 
 
-extern int cpufreq_driver_getavg(struct cpufreq_policy *policy);
+extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy);
 
 int cpufreq_register_governor(struct cpufreq_governor *governor);
 void cpufreq_unregister_governor(struct cpufreq_governor *governor);
 
+int lock_policy_rwsem_read(int cpu);
+int lock_policy_rwsem_write(int cpu);
+void unlock_policy_rwsem_read(int cpu);
+void unlock_policy_rwsem_write(int cpu);
+
 
 /*********************************************************************
  *                      CPUFREQ DRIVER INTERFACE                     *
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index d0e8c8b..23f5514 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -398,11 +398,11 @@
 #endif
 
 #ifdef CONFIG_SMP
-int highest_possible_processor_id(void);
+extern int nr_cpu_ids;
 #define any_online_cpu(mask) __any_online_cpu(&(mask))
 int __any_online_cpu(const cpumask_t *mask);
 #else
-#define highest_possible_processor_id()	0
+#define nr_cpu_ids			1
 #define any_online_cpu(mask)		0
 #endif
 
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index fd40441..826b15e 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -55,7 +55,7 @@
 extern int cpuset_memory_pressure_enabled;
 extern void __cpuset_memory_pressure_bump(void);
 
-extern struct file_operations proc_cpuset_operations;
+extern const struct file_operations proc_cpuset_operations;
 extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
 
 extern void cpuset_lock(void);
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 4aa9046..779aa78 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -51,15 +51,9 @@
 /*
  * Transform masks and values (for crt_flags).
  */
-#define CRYPTO_TFM_MODE_MASK		0x000000ff
 #define CRYPTO_TFM_REQ_MASK		0x000fff00
 #define CRYPTO_TFM_RES_MASK		0xfff00000
 
-#define CRYPTO_TFM_MODE_ECB		0x00000001
-#define CRYPTO_TFM_MODE_CBC		0x00000002
-#define CRYPTO_TFM_MODE_CFB		0x00000004
-#define CRYPTO_TFM_MODE_CTR		0x00000008
-
 #define CRYPTO_TFM_REQ_WEAK_KEY		0x00000100
 #define CRYPTO_TFM_REQ_MAY_SLEEP	0x00000200
 #define CRYPTO_TFM_RES_WEAK_KEY		0x00100000
@@ -71,12 +65,8 @@
 /*
  * Miscellaneous stuff.
  */
-#define CRYPTO_UNSPEC			0
 #define CRYPTO_MAX_ALG_NAME		64
 
-#define CRYPTO_DIR_ENCRYPT		1
-#define CRYPTO_DIR_DECRYPT		0
-
 /*
  * The macro CRYPTO_MINALIGN_ATTR (along with the void * type in the actual
  * declaration) is used to ensure that the crypto_tfm context structure is
@@ -148,19 +138,6 @@
 	                  unsigned int keylen);
 	void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 	void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-
-	unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes) __deprecated;
-	unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes) __deprecated;
-	unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes) __deprecated;
-	unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes) __deprecated;
 };
 
 struct digest_alg {
@@ -243,11 +220,6 @@
 #ifdef CONFIG_CRYPTO
 int crypto_has_alg(const char *name, u32 type, u32 mask);
 #else
-static inline int crypto_alg_available(const char *name, u32 flags)
-{
-	return 0;
-}
-
 static inline int crypto_has_alg(const char *name, u32 type, u32 mask)
 {
 	return 0;
@@ -339,13 +311,18 @@
 	void *__crt_ctx[] CRYPTO_MINALIGN_ATTR;
 };
 
-#define crypto_cipher crypto_tfm
-#define crypto_comp crypto_tfm
-
 struct crypto_blkcipher {
 	struct crypto_tfm base;
 };
 
+struct crypto_cipher {
+	struct crypto_tfm base;
+};
+
+struct crypto_comp {
+	struct crypto_tfm base;
+};
+
 struct crypto_hash {
 	struct crypto_tfm base;
 };
@@ -395,40 +372,11 @@
 	return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK;
 }
 
-static unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm)
-	__deprecated;
-static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->__crt_alg->cra_cipher.cia_min_keysize;
-}
-
-static unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm)
-	__deprecated;
-static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->__crt_alg->cra_cipher.cia_max_keysize;
-}
-
-static unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) __deprecated;
-static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_ivsize;
-}
-
 static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm)
 {
 	return tfm->__crt_alg->cra_blocksize;
 }
 
-static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
-	return tfm->__crt_alg->cra_digest.dia_digestsize;
-}
-
 static inline unsigned int crypto_tfm_alg_alignmask(struct crypto_tfm *tfm)
 {
 	return tfm->__crt_alg->cra_alignmask;
@@ -633,7 +581,7 @@
 
 static inline struct crypto_tfm *crypto_cipher_tfm(struct crypto_cipher *tfm)
 {
-	return tfm;
+	return &tfm->base;
 }
 
 static inline void crypto_free_cipher(struct crypto_cipher *tfm)
@@ -809,76 +757,6 @@
 	return crypto_hash_crt(hash)->setkey(hash, key, keylen);
 }
 
-static int crypto_cipher_encrypt(struct crypto_tfm *tfm,
-				 struct scatterlist *dst,
-				 struct scatterlist *src,
-				 unsigned int nbytes) __deprecated;
-static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
-                                        struct scatterlist *dst,
-                                        struct scatterlist *src,
-                                        unsigned int nbytes)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
-}                                        
-
-static int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
-				    struct scatterlist *dst,
-				    struct scatterlist *src,
-				    unsigned int nbytes, u8 *iv) __deprecated;
-static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
-                                           struct scatterlist *dst,
-                                           struct scatterlist *src,
-                                           unsigned int nbytes, u8 *iv)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv);
-}                                        
-
-static int crypto_cipher_decrypt(struct crypto_tfm *tfm,
-				 struct scatterlist *dst,
-				 struct scatterlist *src,
-				 unsigned int nbytes) __deprecated;
-static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
-                                        struct scatterlist *dst,
-                                        struct scatterlist *src,
-                                        unsigned int nbytes)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
-}
-
-static int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
-				    struct scatterlist *dst,
-				    struct scatterlist *src,
-				    unsigned int nbytes, u8 *iv) __deprecated;
-static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
-                                           struct scatterlist *dst,
-                                           struct scatterlist *src,
-                                           unsigned int nbytes, u8 *iv)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv);
-}
-
-static void crypto_cipher_set_iv(struct crypto_tfm *tfm,
-				 const u8 *src, unsigned int len) __deprecated;
-static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
-                                        const u8 *src, unsigned int len)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	memcpy(tfm->crt_cipher.cit_iv, src, len);
-}
-
-static void crypto_cipher_get_iv(struct crypto_tfm *tfm,
-				 u8 *dst, unsigned int len) __deprecated;
-static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
-                                        u8 *dst, unsigned int len)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	memcpy(dst, tfm->crt_cipher.cit_iv, len);
-}
-
 static inline struct crypto_comp *__crypto_comp_cast(struct crypto_tfm *tfm)
 {
 	return (struct crypto_comp *)tfm;
@@ -903,7 +781,7 @@
 
 static inline struct crypto_tfm *crypto_comp_tfm(struct crypto_comp *tfm)
 {
-	return tfm;
+	return &tfm->base;
 }
 
 static inline void crypto_free_comp(struct crypto_comp *tfm)
@@ -934,14 +812,16 @@
                                        const u8 *src, unsigned int slen,
                                        u8 *dst, unsigned int *dlen)
 {
-	return crypto_comp_crt(tfm)->cot_compress(tfm, src, slen, dst, dlen);
+	return crypto_comp_crt(tfm)->cot_compress(crypto_comp_tfm(tfm),
+						  src, slen, dst, dlen);
 }
 
 static inline int crypto_comp_decompress(struct crypto_comp *tfm,
                                          const u8 *src, unsigned int slen,
                                          u8 *dst, unsigned int *dlen)
 {
-	return crypto_comp_crt(tfm)->cot_decompress(tfm, src, slen, dst, dlen);
+	return crypto_comp_crt(tfm)->cot_decompress(crypto_comp_tfm(tfm),
+						    src, slen, dst, dlen);
 }
 
 #endif	/* _LINUX_CRYPTO_H */
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 047567d..9fa0983 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -33,6 +33,9 @@
 
 struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
 
+struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
+				      const char *dest);
+
 void debugfs_remove(struct dentry *dentry);
 
 struct dentry *debugfs_create_u8(const char *name, mode_t mode,
@@ -70,6 +73,13 @@
 	return ERR_PTR(-ENODEV);
 }
 
+static inline struct dentry *debugfs_create_symlink(const char *name,
+						    struct dentry *parent,
+						    const char *dest)
+{
+	return ERR_PTR(-ENODEV);
+}
+
 static inline void debugfs_remove(struct dentry *dentry)
 { }
 
diff --git a/include/linux/device.h b/include/linux/device.h
index 5ca1cdb..39a3199 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -2,6 +2,7 @@
  * device.h - generic, centralized driver model
  *
  * Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
+ * Copyright (c) 2004-2007 Greg Kroah-Hartman <gregkh@suse.de>
  *
  * This file is released under the GPLv2
  *
@@ -101,7 +102,7 @@
 #define BUS_NOTIFY_UNBIND_DRIVER	0x00000004 /* driver about to be
 						      unbound */
 
-/* driverfs interface for exporting bus attributes */
+/* sysfs interface for exporting bus attributes */
 
 struct bus_attribute {
 	struct attribute	attr;
@@ -146,7 +147,7 @@
 extern struct device_driver *driver_find(const char *name, struct bus_type *bus);
 extern int driver_probe_done(void);
 
-/* driverfs interface for exporting driver attributes */
+/* sysfs interface for exporting driver attributes */
 
 struct driver_attribute {
 	struct attribute	attr;
@@ -293,8 +294,6 @@
 extern int __must_check class_device_add(struct class_device *);
 extern void class_device_del(struct class_device *);
 
-extern int class_device_rename(struct class_device *, char *);
-
 extern struct class_device * class_device_get(struct class_device *);
 extern void class_device_put(struct class_device *);
 
@@ -354,6 +353,41 @@
 					       struct bin_attribute *attr);
 extern void device_remove_bin_file(struct device *dev,
 				   struct bin_attribute *attr);
+
+/* device resource management */
+typedef void (*dr_release_t)(struct device *dev, void *res);
+typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data);
+
+#ifdef CONFIG_DEBUG_DEVRES
+extern void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
+			     const char *name);
+#define devres_alloc(release, size, gfp) \
+	__devres_alloc(release, size, gfp, #release)
+#else
+extern void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp);
+#endif
+extern void devres_free(void *res);
+extern void devres_add(struct device *dev, void *res);
+extern void * devres_find(struct device *dev, dr_release_t release,
+			  dr_match_t match, void *match_data);
+extern void * devres_get(struct device *dev, void *new_res,
+			 dr_match_t match, void *match_data);
+extern void * devres_remove(struct device *dev, dr_release_t release,
+			    dr_match_t match, void *match_data);
+extern int devres_destroy(struct device *dev, dr_release_t release,
+			  dr_match_t match, void *match_data);
+
+/* devres group */
+extern void * __must_check devres_open_group(struct device *dev, void *id,
+					     gfp_t gfp);
+extern void devres_close_group(struct device *dev, void *id);
+extern void devres_remove_group(struct device *dev, void *id);
+extern int devres_release_group(struct device *dev, void *id);
+
+/* managed kzalloc/kfree for device drivers, no kmalloc, always use kzalloc */
+extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
+extern void devm_kfree(struct device *dev, void *p);
+
 struct device {
 	struct klist		klist_children;
 	struct klist_node	knode_parent;		/* node in sibling list */
@@ -397,6 +431,9 @@
 	/* arch specific additions */
 	struct dev_archdata	archdata;
 
+	spinlock_t		devres_lock;
+	struct list_head	devres_head;
+
 	/* class_device migration path */
 	struct list_head	node;
 	struct class		*class;
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index ff203c4..9a663c6 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -66,6 +66,33 @@
 }
 #endif
 
+/*
+ * Managed DMA API
+ */
+extern void *dmam_alloc_coherent(struct device *dev, size_t size,
+				 dma_addr_t *dma_handle, gfp_t gfp);
+extern void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
+			       dma_addr_t dma_handle);
+extern void *dmam_alloc_noncoherent(struct device *dev, size_t size,
+				    dma_addr_t *dma_handle, gfp_t gfp);
+extern void dmam_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+				  dma_addr_t dma_handle);
+#ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
+extern int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+					dma_addr_t device_addr, size_t size,
+					int flags);
+extern void dmam_release_declared_memory(struct device *dev);
+#else /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
+static inline int dmam_declare_coherent_memory(struct device *dev,
+				dma_addr_t bus_addr, dma_addr_t device_addr,
+				size_t size, gfp_t gfp)
+{
+	return 0;
+}
+
+static inline void dmam_release_declared_memory(struct device *dev)
+{
+}
+#endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
+
 #endif
-
-
diff --git a/include/linux/dmapool.h b/include/linux/dmapool.h
index 76f12f4..022e34f 100644
--- a/include/linux/dmapool.h
+++ b/include/linux/dmapool.h
@@ -24,5 +24,12 @@
 
 void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t addr);
 
+/*
+ * Managed DMA pool
+ */
+struct dma_pool *dmam_pool_create(const char *name, struct device *dev,
+				  size_t size, size_t align, size_t allocation);
+void dmam_pool_destroy(struct dma_pool *pool);
+
 #endif
 
diff --git a/include/linux/dn.h b/include/linux/dn.h
index 10b6a6f..02bba04 100644
--- a/include/linux/dn.h
+++ b/include/linux/dn.h
@@ -113,7 +113,7 @@
  * DECnet logical link information structure
  */
 struct linkinfo_dn {
-        __le16  idn_segsize;    /* Segment size for link */
+        __u16  idn_segsize;    /* Segment size for link */
         __u8   idn_linkstate;  /* Logical link state    */
 };
 
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index 278ef44..dfed800 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -36,7 +36,7 @@
 
 struct statfs;
 
-extern struct inode_operations efs_dir_inode_operations;
+extern const struct inode_operations efs_dir_inode_operations;
 extern const struct file_operations efs_dir_operations;
 extern const struct address_space_operations efs_symlink_aops;
 
diff --git a/include/linux/eisa.h b/include/linux/eisa.h
index 1ff7c13..fe806b6 100644
--- a/include/linux/eisa.h
+++ b/include/linux/eisa.h
@@ -61,10 +61,20 @@
 
 #define to_eisa_driver(drv) container_of(drv,struct eisa_driver, driver)
 
+/* These external functions are only available when EISA support is enabled. */
+#ifdef CONFIG_EISA
+
 extern struct bus_type eisa_bus_type;
 int eisa_driver_register (struct eisa_driver *edrv);
 void eisa_driver_unregister (struct eisa_driver *edrv);
 
+#else /* !CONFIG_EISA */
+
+static inline int eisa_driver_register (struct eisa_driver *edrv) { return 0; }
+static inline void eisa_driver_unregister (struct eisa_driver *edrv) { }
+
+#endif /* !CONFIG_EISA */
+
 /* Mimics pci.h... */
 static inline void *eisa_get_drvdata (struct eisa_device *edev)
 {
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 11cca1b..4eb18ac 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -868,16 +868,16 @@
 extern const struct file_operations ext3_dir_operations;
 
 /* file.c */
-extern struct inode_operations ext3_file_inode_operations;
+extern const struct inode_operations ext3_file_inode_operations;
 extern const struct file_operations ext3_file_operations;
 
 /* namei.c */
-extern struct inode_operations ext3_dir_inode_operations;
-extern struct inode_operations ext3_special_inode_operations;
+extern const struct inode_operations ext3_dir_inode_operations;
+extern const struct inode_operations ext3_special_inode_operations;
 
 /* symlink.c */
-extern struct inode_operations ext3_symlink_inode_operations;
-extern struct inode_operations ext3_fast_symlink_inode_operations;
+extern const struct inode_operations ext3_symlink_inode_operations;
+extern const struct inode_operations ext3_fast_symlink_inode_operations;
 
 
 #endif	/* __KERNEL__ */
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
index 498503e..54c576d 100644
--- a/include/linux/ext4_fs.h
+++ b/include/linux/ext4_fs.h
@@ -955,16 +955,16 @@
 extern const struct file_operations ext4_dir_operations;
 
 /* file.c */
-extern struct inode_operations ext4_file_inode_operations;
+extern const struct inode_operations ext4_file_inode_operations;
 extern const struct file_operations ext4_file_operations;
 
 /* namei.c */
-extern struct inode_operations ext4_dir_inode_operations;
-extern struct inode_operations ext4_special_inode_operations;
+extern const struct inode_operations ext4_dir_inode_operations;
+extern const struct inode_operations ext4_special_inode_operations;
 
 /* symlink.c */
-extern struct inode_operations ext4_symlink_inode_operations;
-extern struct inode_operations ext4_fast_symlink_inode_operations;
+extern const struct inode_operations ext4_symlink_inode_operations;
+extern const struct inode_operations ext4_fast_symlink_inode_operations;
 
 /* extents.c */
 extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h
index a41cc24..7eb1d73 100644
--- a/include/linux/ext4_fs_extents.h
+++ b/include/linux/ext4_fs_extents.h
@@ -22,12 +22,12 @@
 #include <linux/ext4_fs.h>
 
 /*
- * With AGRESSIVE_TEST defined, the capacity of index/leaf blocks
+ * With AGGRESSIVE_TEST defined, the capacity of index/leaf blocks
  * becomes very small, so index split, in-depth growing and
  * other hard changes happen much more often.
  * This is for debug purposes only.
  */
-#define AGRESSIVE_TEST_
+#define AGGRESSIVE_TEST_
 
 /*
  * With EXTENTS_STATS defined, the number of blocks and extents
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 64177ec..be913ec 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -49,6 +49,13 @@
 #define FB_AUX_TEXT_S3_MMIO	2	/* S3 MMIO fasttext */
 #define FB_AUX_TEXT_MGA_STEP16	3	/* MGA Millenium I: text, attr, 14 reserved bytes */
 #define FB_AUX_TEXT_MGA_STEP8	4	/* other MGAs:      text, attr,  6 reserved bytes */
+#define FB_AUX_TEXT_SVGA_GROUP	8	/* 8-15: SVGA tileblit compatible modes */
+#define FB_AUX_TEXT_SVGA_MASK	7	/* lower three bits says step */
+#define FB_AUX_TEXT_SVGA_STEP2	8	/* SVGA text mode:  text, attr */
+#define FB_AUX_TEXT_SVGA_STEP4	9	/* SVGA text mode:  text, attr,  2 reserved bytes */
+#define FB_AUX_TEXT_SVGA_STEP8	10	/* SVGA text mode:  text, attr,  6 reserved bytes */
+#define FB_AUX_TEXT_SVGA_STEP16	11	/* SVGA text mode:  text, attr, 14 reserved bytes */
+#define FB_AUX_TEXT_SVGA_LAST	15	/* reserved up to 15 */
 
 #define FB_AUX_VGA_PLANES_VGA4		0	/* 16 color planes (EGA/VGA) */
 #define FB_AUX_VGA_PLANES_CFB4		1	/* CFB4 in planes (VGA) */
@@ -509,13 +516,15 @@
 #define FB_EVENT_GET_CONSOLE_MAP        0x07
 /*      CONSOLE-SPECIFIC: set console to framebuffer mapping */
 #define FB_EVENT_SET_CONSOLE_MAP        0x08
-/*      A display blank is requested       */
+/*      A hardware display blank change occured */
 #define FB_EVENT_BLANK                  0x09
 /*      Private modelist is to be replaced */
 #define FB_EVENT_NEW_MODELIST           0x0A
 /*	The resolution of the passed in fb_info about to change and
         all vc's should be changed         */
 #define FB_EVENT_MODE_CHANGE_ALL	0x0B
+/*	A software display blank change occured */
+#define FB_EVENT_CONBLANK               0x0C
 
 struct fb_event {
 	struct fb_info *info;
@@ -760,16 +769,13 @@
 	struct fb_videomode *mode;	/* current mode */
 
 #ifdef CONFIG_FB_BACKLIGHT
-	/* Lock ordering:
-	 * bl_mutex (protects bl_dev and bl_curve)
-	 *   bl_dev->sem (backlight class)
-	 */
-	struct mutex bl_mutex;
-
 	/* assigned backlight device */
+	/* set before framebuffer registration, 
+	   remove after unregister */
 	struct backlight_device *bl_dev;
 
 	/* Backlight level curve */
+	struct mutex bl_curve_mutex;	
 	u8 bl_curve[FB_BACKLIGHT_LEVELS];
 #endif
 
@@ -945,25 +951,26 @@
 /* drivers/video/modedb.c */
 #define VESA_MODEDB_SIZE 34
 extern void fb_var_to_videomode(struct fb_videomode *mode,
-				struct fb_var_screeninfo *var);
+				const struct fb_var_screeninfo *var);
 extern void fb_videomode_to_var(struct fb_var_screeninfo *var,
-				struct fb_videomode *mode);
-extern int fb_mode_is_equal(struct fb_videomode *mode1,
-			    struct fb_videomode *mode2);
-extern int fb_add_videomode(struct fb_videomode *mode, struct list_head *head);
-extern void fb_delete_videomode(struct fb_videomode *mode,
+				const struct fb_videomode *mode);
+extern int fb_mode_is_equal(const struct fb_videomode *mode1,
+			    const struct fb_videomode *mode2);
+extern int fb_add_videomode(const struct fb_videomode *mode,
+			    struct list_head *head);
+extern void fb_delete_videomode(const struct fb_videomode *mode,
 				struct list_head *head);
-extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
-					  struct list_head *head);
-extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
-					      struct list_head *head);
-extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
-						 struct list_head *head);
+extern const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
+						struct list_head *head);
+extern const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
+						    struct list_head *head);
+extern const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
+						       struct list_head *head);
 extern void fb_destroy_modelist(struct list_head *head);
-extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+extern void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
 				     struct list_head *head);
-extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
-						 struct list_head *head);
+extern const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
+						       struct list_head *head);
 
 /* drivers/video/fbcmap.c */
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 1410e53..86ec3f4 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -169,6 +169,7 @@
 #define IS_DIRSYNC(inode)	(__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \
 					((inode)->i_flags & (S_SYNC|S_DIRSYNC)))
 #define IS_MANDLOCK(inode)	__IS_FLG(inode, MS_MANDLOCK)
+#define IS_NOATIME(inode)   __IS_FLG(inode, MS_RDONLY|MS_NOATIME)
 
 #define IS_NOQUOTA(inode)	((inode)->i_flags & S_NOQUOTA)
 #define IS_APPEND(inode)	((inode)->i_flags & S_APPEND)
@@ -550,7 +551,7 @@
 	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
 	struct mutex		i_mutex;
 	struct rw_semaphore	i_alloc_sem;
-	struct inode_operations	*i_op;
+	const struct inode_operations	*i_op;
 	const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
 	struct super_block	*i_sb;
 	struct file_lock	*i_flock;
@@ -906,7 +907,7 @@
 	unsigned char		s_dirt;
 	unsigned long long	s_maxbytes;	/* Max file size */
 	struct file_system_type	*s_type;
-	struct super_operations	*s_op;
+	const struct super_operations	*s_op;
 	struct dquot_operations	*dq_op;
  	struct quotactl_ops	*s_qcop;
 	struct export_operations *s_export_op;
@@ -1382,7 +1383,7 @@
 			int (*set)(struct super_block *,void *),
 			void *data);
 extern int get_sb_pseudo(struct file_system_type *, char *,
-	struct super_operations *ops, unsigned long,
+	const struct super_operations *ops, unsigned long,
 	struct vfsmount *mnt);
 extern int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);
 int __put_super(struct super_block *sb);
@@ -1572,12 +1573,18 @@
 extern int invalidate_inodes(struct super_block *);
 unsigned long invalidate_mapping_pages(struct address_space *mapping,
 					pgoff_t start, pgoff_t end);
-unsigned long invalidate_inode_pages(struct address_space *mapping);
+
+static inline unsigned long __deprecated
+invalidate_inode_pages(struct address_space *mapping)
+{
+	return invalidate_mapping_pages(mapping, 0, ~0UL);
+}
+
 static inline void invalidate_remote_inode(struct inode *inode)
 {
 	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 	    S_ISLNK(inode->i_mode))
-		invalidate_inode_pages(inode->i_mapping);
+		invalidate_mapping_pages(inode->i_mapping, 0, -1);
 }
 extern int invalidate_inode_pages2(struct address_space *mapping);
 extern int invalidate_inode_pages2_range(struct address_space *mapping,
@@ -1681,7 +1688,6 @@
 extern int __remove_suid(struct dentry *, int);
 extern int should_remove_suid(struct dentry *);
 extern int remove_suid(struct dentry *);
-extern void remove_dquot_ref(struct super_block *, int, struct list_head *);
 
 extern void __insert_inode_hash(struct inode *, unsigned long hashval);
 extern void remove_inode_hash(struct inode *);
@@ -1822,7 +1828,7 @@
 extern int __page_symlink(struct inode *inode, const char *symname, int len,
 		gfp_t gfp_mask);
 extern int page_symlink(struct inode *inode, const char *symname, int len);
-extern struct inode_operations page_symlink_inode_operations;
+extern const struct inode_operations page_symlink_inode_operations;
 extern int generic_readlink(struct dentry *, char __user *, int);
 extern void generic_fillattr(struct inode *, struct kstat *);
 extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
@@ -1867,7 +1873,7 @@
 extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
 extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
 extern const struct file_operations simple_dir_operations;
-extern struct inode_operations simple_dir_inode_operations;
+extern const struct inode_operations simple_dir_inode_operations;
 struct tree_descr { char *name; const struct file_operations *ops; int mode; };
 struct dentry *d_alloc_name(struct dentry *, const char *);
 extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 0a022b2..2c65da7 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -20,7 +20,11 @@
 	LINUX_EXTENDED_PARTITION = 0x85,
 	WIN98_EXTENDED_PARTITION = 0x0f,
 
+	SUN_WHOLE_DISK = DOS_EXTENDED_PARTITION,
+
 	LINUX_SWAP_PARTITION = 0x82,
+	LINUX_DATA_PARTITION = 0x83,
+	LINUX_LVM_PARTITION = 0x8e,
 	LINUX_RAID_PARTITION = 0xfd,	/* autodetect RAID partition */
 
 	SOLARIS_X86_PARTITION =	LINUX_SWAP_PARTITION,
@@ -400,10 +404,14 @@
 
 #ifdef __KERNEL__
 
+#define ADDPART_FLAG_NONE	0
+#define ADDPART_FLAG_RAID	1
+#define ADDPART_FLAG_WHOLEDISK	2
+
 char *disk_name (struct gendisk *hd, int part, char *buf);
 
 extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
-extern void add_partition(struct gendisk *, int, sector_t, sector_t);
+extern void add_partition(struct gendisk *, int, sector_t, sector_t, int);
 extern void delete_partition(struct gendisk *, int);
 
 extern struct gendisk *alloc_disk_node(int minors, int node_id);
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 00c314a..2a7d15b 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -70,7 +70,7 @@
 #ifdef CONFIG_NUMA
 #define GFP_THISNODE	(__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
 #else
-#define GFP_THISNODE	0
+#define GFP_THISNODE	((__force gfp_t)0)
 #endif
 
 
@@ -85,8 +85,10 @@
 
 static inline enum zone_type gfp_zone(gfp_t flags)
 {
+#ifdef CONFIG_ZONE_DMA
 	if (flags & __GFP_DMA)
 		return ZONE_DMA;
+#endif
 #ifdef CONFIG_ZONE_DMA32
 	if (flags & __GFP_DMA32)
 		return ZONE_DMA32;
diff --git a/include/linux/gigaset_dev.h b/include/linux/gigaset_dev.h
index 70ad09c..5dc4a31 100644
--- a/include/linux/gigaset_dev.h
+++ b/include/linux/gigaset_dev.h
@@ -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: gigaset_dev.h,v 1.4.4.4 2005/11/21 22:28:09 hjlipp Exp $
- * =====================================================================
  */
 
 #ifndef GIGASET_INTERFACE_H
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 612472a..7803014 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -106,7 +106,7 @@
  * always balanced, so the interrupted value of ->hardirq_context
  * will always be restored.
  */
-#define irq_enter()					\
+#define __irq_enter()					\
 	do {						\
 		account_system_vtime(current);		\
 		add_preempt_count(HARDIRQ_OFFSET);	\
@@ -114,6 +114,11 @@
 	} while (0)
 
 /*
+ * Enter irq context (on NO_HZ, update jiffies):
+ */
+extern void irq_enter(void);
+
+/*
  * Exit irq context without processing softirqs:
  */
 #define __irq_exit()					\
@@ -128,7 +133,7 @@
  */
 extern void irq_exit(void);
 
-#define nmi_enter()		do { lockdep_off(); irq_enter(); } while (0)
+#define nmi_enter()		do { lockdep_off(); __irq_enter(); } while (0)
 #define nmi_exit()		do { __irq_exit(); lockdep_on(); } while (0)
 
 #endif /* LINUX_HARDIRQ_H */
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index fca9302..37f9279 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -21,22 +21,72 @@
 #include <linux/list.h>
 #include <linux/wait.h>
 
+struct hrtimer_clock_base;
+struct hrtimer_cpu_base;
+
 /*
  * Mode arguments of xxx_hrtimer functions:
  */
 enum hrtimer_mode {
-	HRTIMER_ABS,	/* Time value is absolute */
-	HRTIMER_REL,	/* Time value is relative to now */
+	HRTIMER_MODE_ABS,	/* Time value is absolute */
+	HRTIMER_MODE_REL,	/* Time value is relative to now */
 };
 
+/*
+ * Return values for the callback function
+ */
 enum hrtimer_restart {
-	HRTIMER_NORESTART,
-	HRTIMER_RESTART,
+	HRTIMER_NORESTART,	/* Timer is not restarted */
+	HRTIMER_RESTART,	/* Timer must be restarted */
 };
 
-#define HRTIMER_INACTIVE	((void *)1UL)
+/*
+ * hrtimer callback modes:
+ *
+ *	HRTIMER_CB_SOFTIRQ:		Callback must run in softirq context
+ *	HRTIMER_CB_IRQSAFE:		Callback may run in hardirq context
+ *	HRTIMER_CB_IRQSAFE_NO_RESTART:	Callback may run in hardirq context and
+ *					does not restart the timer
+ *	HRTIMER_CB_IRQSAFE_NO_SOFTIRQ:	Callback must run in softirq context
+ *					Special mode for tick emultation
+ */
+enum hrtimer_cb_mode {
+	HRTIMER_CB_SOFTIRQ,
+	HRTIMER_CB_IRQSAFE,
+	HRTIMER_CB_IRQSAFE_NO_RESTART,
+	HRTIMER_CB_IRQSAFE_NO_SOFTIRQ,
+};
 
-struct hrtimer_base;
+/*
+ * Values to track state of the timer
+ *
+ * Possible states:
+ *
+ * 0x00		inactive
+ * 0x01		enqueued into rbtree
+ * 0x02		callback function running
+ * 0x04		callback pending (high resolution mode)
+ *
+ * Special case:
+ * 0x03		callback function running and enqueued
+ *		(was requeued on another CPU)
+ * The "callback function running and enqueued" status is only possible on
+ * SMP. It happens for example when a posix timer expired and the callback
+ * queued a signal. Between dropping the lock which protects the posix timer
+ * and reacquiring the base lock of the hrtimer, another CPU can deliver the
+ * signal and rearm the timer. We have to preserve the callback running state,
+ * as otherwise the timer could be removed before the softirq code finishes the
+ * the handling of the timer.
+ *
+ * The HRTIMER_STATE_ENQUEUE bit is always or'ed to the current state to
+ * preserve the HRTIMER_STATE_CALLBACK bit in the above scenario.
+ *
+ * All state transitions are protected by cpu_base->lock.
+ */
+#define HRTIMER_STATE_INACTIVE	0x00
+#define HRTIMER_STATE_ENQUEUED	0x01
+#define HRTIMER_STATE_CALLBACK	0x02
+#define HRTIMER_STATE_PENDING	0x04
 
 /**
  * struct hrtimer - the basic hrtimer structure
@@ -46,14 +96,34 @@
  *		which the timer is based.
  * @function:	timer expiry callback function
  * @base:	pointer to the timer base (per cpu and per clock)
+ * @state:	state information (See bit values above)
+ * @cb_mode:	high resolution timer feature to select the callback execution
+ *		 mode
+ * @cb_entry:	list head to enqueue an expired timer into the callback list
+ * @start_site:	timer statistics field to store the site where the timer
+ *		was started
+ * @start_comm: timer statistics field to store the name of the process which
+ *		started the timer
+ * @start_pid: timer statistics field to store the pid of the task which
+ *		started the timer
  *
- * The hrtimer structure must be initialized by init_hrtimer_#CLOCKTYPE()
+ * The hrtimer structure must be initialized by hrtimer_init()
  */
 struct hrtimer {
-	struct rb_node		node;
-	ktime_t			expires;
-	int			(*function)(struct hrtimer *);
-	struct hrtimer_base	*base;
+	struct rb_node			node;
+	ktime_t				expires;
+	enum hrtimer_restart		(*function)(struct hrtimer *);
+	struct hrtimer_clock_base	*base;
+	unsigned long			state;
+#ifdef CONFIG_HIGH_RES_TIMERS
+	enum hrtimer_cb_mode		cb_mode;
+	struct list_head		cb_entry;
+#endif
+#ifdef CONFIG_TIMER_STATS
+	void				*start_site;
+	char				start_comm[16];
+	int				start_pid;
+#endif
 };
 
 /**
@@ -70,37 +140,114 @@
 
 /**
  * struct hrtimer_base - the timer base for a specific clock
- * @index:		clock type index for per_cpu support when moving a timer
- *			to a base on another cpu.
- * @lock:		lock protecting the base and associated timers
+ * @index:		clock type index for per_cpu support when moving a
+ *			timer to a base on another cpu.
  * @active:		red black tree root node for the active timers
  * @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_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
- * @lock_key:		the lock_class_key for use with lockdep
+ * @cb_pending:		list of timers where the callback is pending
+ * @offset:		offset of this clock to the monotonic base
+ * @reprogram:		function to reprogram the timer event
  */
-struct hrtimer_base {
+struct hrtimer_clock_base {
+	struct hrtimer_cpu_base	*cpu_base;
 	clockid_t		index;
-	spinlock_t		lock;
 	struct rb_root		active;
 	struct rb_node		*first;
 	ktime_t			resolution;
 	ktime_t			(*get_time)(void);
 	ktime_t			(*get_softirq_time)(void);
-	struct hrtimer		*curr_timer;
 	ktime_t			softirq_time;
-	struct lock_class_key lock_key;
+#ifdef CONFIG_HIGH_RES_TIMERS
+	ktime_t			offset;
+	int			(*reprogram)(struct hrtimer *t,
+					     struct hrtimer_clock_base *b,
+					     ktime_t n);
+#endif
 };
 
+#define HRTIMER_MAX_CLOCK_BASES 2
+
+/*
+ * struct hrtimer_cpu_base - the per cpu clock bases
+ * @lock:		lock protecting the base and associated clock bases
+ *			and timers
+ * @lock_key:		the lock_class_key for use with lockdep
+ * @clock_base:		array of clock bases for this cpu
+ * @curr_timer:		the timer which is executing a callback right now
+ * @expires_next:	absolute time of the next event which was scheduled
+ *			via clock_set_next_event()
+ * @hres_active:	State of high resolution mode
+ * @check_clocks:	Indictator, when set evaluate time source and clock
+ *			event devices whether high resolution mode can be
+ *			activated.
+ * @cb_pending:		Expired timers are moved from the rbtree to this
+ *			list in the timer interrupt. The list is processed
+ *			in the softirq.
+ * @nr_events:		Total number of timer interrupt events
+ */
+struct hrtimer_cpu_base {
+	spinlock_t			lock;
+	struct lock_class_key		lock_key;
+	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];
+#ifdef CONFIG_HIGH_RES_TIMERS
+	ktime_t				expires_next;
+	int				hres_active;
+	struct list_head		cb_pending;
+	unsigned long			nr_events;
+#endif
+};
+
+#ifdef CONFIG_HIGH_RES_TIMERS
+struct clock_event_device;
+
+extern void clock_was_set(void);
+extern void hrtimer_interrupt(struct clock_event_device *dev);
+
+/*
+ * In high resolution mode the time reference must be read accurate
+ */
+static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer)
+{
+	return timer->base->get_time();
+}
+
+/*
+ * The resolution of the clocks. The resolution value is returned in
+ * the clock_getres() system call to give application programmers an
+ * idea of the (in)accuracy of timers. Timer values are rounded up to
+ * this resolution values.
+ */
+# define KTIME_HIGH_RES		(ktime_t) { .tv64 = 1 }
+# define KTIME_MONOTONIC_RES	KTIME_HIGH_RES
+
+#else
+
+# define KTIME_MONOTONIC_RES	KTIME_LOW_RES
+
 /*
  * clock_was_set() is a NOP for non- high-resolution systems. The
  * time-sorted order guarantees that a timer does not expire early and
  * is expired in the next softirq when the clock was advanced.
  */
-#define clock_was_set()		do { } while (0)
+static inline void clock_was_set(void) { }
+
+/*
+ * In non high resolution mode the time reference is taken from
+ * the base softirq time variable.
+ */
+static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer)
+{
+	return timer->base->softirq_time;
+}
+
+#endif
+
+extern ktime_t ktime_get(void);
+extern ktime_t ktime_get_real(void);
 
 /* Exported timer functions: */
 
@@ -114,19 +261,33 @@
 extern int hrtimer_cancel(struct hrtimer *timer);
 extern int hrtimer_try_to_cancel(struct hrtimer *timer);
 
-#define hrtimer_restart(timer) hrtimer_start((timer), (timer)->expires, HRTIMER_ABS)
+static inline int hrtimer_restart(struct hrtimer *timer)
+{
+	return hrtimer_start(timer, timer->expires, HRTIMER_MODE_ABS);
+}
 
 /* Query timers: */
 extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
 extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp);
 
-#ifdef CONFIG_NO_IDLE_HZ
 extern ktime_t hrtimer_get_next_event(void);
-#endif
 
+/*
+ * A timer is active, when it is enqueued into the rbtree or the callback
+ * function is running.
+ */
 static inline int hrtimer_active(const struct hrtimer *timer)
 {
-	return rb_parent(&timer->node) != &timer->node;
+	return timer->state != HRTIMER_STATE_INACTIVE;
+}
+
+/*
+ * Helper function to check, whether the timer is on one of the queues
+ */
+static inline int hrtimer_is_queued(struct hrtimer *timer)
+{
+	return timer->state &
+		(HRTIMER_STATE_ENQUEUED | HRTIMER_STATE_PENDING);
 }
 
 /* Forward a hrtimer so it expires after now: */
@@ -149,4 +310,53 @@
 /* Bootup initialization: */
 extern void __init hrtimers_init(void);
 
+#if BITS_PER_LONG < 64
+extern unsigned long ktime_divns(const ktime_t kt, s64 div);
+#else /* BITS_PER_LONG < 64 */
+# define ktime_divns(kt, div)		(unsigned long)((kt).tv64 / (div))
+#endif
+
+/* Show pending timers: */
+extern void sysrq_timer_list_show(void);
+
+/*
+ * Timer-statistics info:
+ */
+#ifdef CONFIG_TIMER_STATS
+
+extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
+				     void *timerf, char * comm);
+
+static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
+{
+	timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
+				 timer->function, timer->start_comm);
+}
+
+extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer,
+						 void *addr);
+
+static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)
+{
+	__timer_stats_hrtimer_set_start_info(timer, __builtin_return_address(0));
+}
+
+static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer)
+{
+	timer->start_site = NULL;
+}
+#else
+static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
+{
+}
+
+static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)
+{
+}
+
+static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer)
+{
+}
+#endif
+
 #endif
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index d38778f..9c21dc7 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -115,6 +115,8 @@
 #define I2C_DRIVERID_KS0127	86	/* Samsung ks0127 video decoder */
 #define I2C_DRIVERID_TLV320AIC23B 87	/* TI TLV320AIC23B audio codec  */
 #define I2C_DRIVERID_ISL1208	88	/* Intersil ISL1208 RTC		*/
+#define I2C_DRIVERID_WM8731		89	/* Wolfson WM8731 audio codec */
+#define I2C_DRIVERID_WM8750		90	/* Wolfson WM8750 audio codec */
 
 #define I2C_DRIVERID_I2CDEV	900
 #define I2C_DRIVERID_ARP        902    /* SMBus ARP Client              */
@@ -230,7 +232,6 @@
 #define I2C_HW_SMBUS_PIIX4	0x040000
 #define I2C_HW_SMBUS_ALI15X3	0x040001
 #define I2C_HW_SMBUS_VIA2	0x040002
-#define I2C_HW_SMBUS_VOODOO3	0x040003
 #define I2C_HW_SMBUS_I801	0x040004
 #define I2C_HW_SMBUS_AMD756	0x040005
 #define I2C_HW_SMBUS_SIS5595	0x040006
@@ -246,13 +247,11 @@
 #define I2C_HW_SMBUS_OV519	0x040010 /* OV519 USB 1.1 webcam IC */
 #define I2C_HW_SMBUS_OVFX2	0x040011 /* Cypress/OmniVision FX2 webcam */
 #define I2C_HW_SMBUS_CAFE	0x040012 /* Marvell 88ALP01 "CAFE" cam  */
+#define I2C_HW_SMBUS_ALI1563	0x040013
 
 /* --- ISA pseudo-adapter						*/
 #define I2C_HW_ISA		0x050000
 
-/* --- IPMI pseudo-adapter						*/
-#define I2C_HW_IPMI		0x0b0000
-
 /* --- IPMB adapter						*/
 #define I2C_HW_IPMB		0x0c0000
 
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 71e50d3..9428092 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -125,7 +125,12 @@
 	 * it must be freed here.
 	 */
 	int (*detach_client)(struct i2c_client *);
-	
+
+	/* driver model interfaces that don't relate to enumeration  */
+	void (*shutdown)(struct i2c_client *);
+	int (*suspend)(struct i2c_client *, pm_message_t mesg);
+	int (*resume)(struct i2c_client *);
+
 	/* a ioctl like command that can be used to perform specific functions
 	 * with the device.
 	 */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 04e0fa9..79c0282 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -636,7 +636,6 @@
 	unsigned int	bios_cyl;	/* BIOS/fdisk/LILO number of cyls */
 	unsigned int	cyl;		/* "real" number of cyls */
 	unsigned int	drive_data;	/* use by tuneproc/selectproc */
-	unsigned int	usage;		/* current "open()" count for drive */
 	unsigned int	failures;	/* current failure count */
 	unsigned int	max_failures;	/* maximum allowed failure count */
 	u64		probed_capacity;/* initial reported media capacity (ide-cd only currently) */
@@ -736,23 +735,22 @@
 	int (*ide_dma_end)(ide_drive_t *drive);
 	int (*ide_dma_check)(ide_drive_t *drive);
 	int (*ide_dma_on)(ide_drive_t *drive);
-	int (*ide_dma_off_quietly)(ide_drive_t *drive);
+	void (*dma_off_quietly)(ide_drive_t *drive);
 	int (*ide_dma_test_irq)(ide_drive_t *drive);
-	int (*ide_dma_host_on)(ide_drive_t *drive);
-	int (*ide_dma_host_off)(ide_drive_t *drive);
+	void (*ide_dma_clear_irq)(ide_drive_t *drive);
+	void (*dma_host_on)(ide_drive_t *drive);
+	void (*dma_host_off)(ide_drive_t *drive);
 	int (*ide_dma_lostirq)(ide_drive_t *drive);
 	int (*ide_dma_timeout)(ide_drive_t *drive);
 
 	void (*OUTB)(u8 addr, unsigned long port);
 	void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
 	void (*OUTW)(u16 addr, unsigned long port);
-	void (*OUTL)(u32 addr, unsigned long port);
 	void (*OUTSW)(unsigned long port, void *addr, u32 count);
 	void (*OUTSL)(unsigned long port, void *addr, u32 count);
 
 	u8  (*INB)(unsigned long port);
 	u16 (*INW)(unsigned long port);
-	u32 (*INL)(unsigned long port);
 	void (*INSW)(unsigned long port, void *addr, u32 count);
 	void (*INSL)(unsigned long port, void *addr, u32 count);
 
@@ -774,7 +772,6 @@
 	unsigned int cursg;
 	unsigned int cursg_ofs;
 
-	int		mmio;		/* hosts iomio (0) or custom (2) select */
 	int		rqsize;		/* max sectors per request */
 	int		irq;		/* our irq number */
 
@@ -802,12 +799,11 @@
 	unsigned	udma_four  : 1;	/* 1=ATA-66 capable, 0=default */
 	unsigned	no_lba48   : 1; /* 1 = cannot do LBA48 */
 	unsigned	no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
-	unsigned	no_dsc     : 1;	/* 0 default, 1 dsc_overlap disabled */
 	unsigned	auto_poll  : 1; /* supports nop auto-poll */
 	unsigned	sg_mapped  : 1;	/* sg_table and sg_nents are ready */
 	unsigned	no_io_32bit : 1; /* 1 = can not do 32-bit IO ops */
 	unsigned	err_stops_fifo : 1; /* 1=data FIFO is cleared by an error */
-	unsigned	atapi_irq_bogon : 1; /* Generates spurious DMA interrupts in PIO mode */
+	unsigned	mmio       : 1; /* host uses MMIO */
 
 	struct device	gendev;
 	struct completion gendev_rel_comp; /* To deal with device release() */
@@ -1280,8 +1276,9 @@
 int __ide_dma_bad_drive(ide_drive_t *);
 int __ide_dma_good_drive(ide_drive_t *);
 int ide_use_dma(ide_drive_t *);
-int __ide_dma_off(ide_drive_t *);
+void ide_dma_off(ide_drive_t *);
 void ide_dma_verbose(ide_drive_t *);
+int ide_set_dma(ide_drive_t *);
 ide_startstop_t ide_dma_intr(ide_drive_t *);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -1291,9 +1288,9 @@
 extern int ide_release_dma(ide_hwif_t *);
 extern void ide_setup_dma(ide_hwif_t *, unsigned long, unsigned int);
 
-extern int __ide_dma_host_off(ide_drive_t *);
-extern int __ide_dma_off_quietly(ide_drive_t *);
-extern int __ide_dma_host_on(ide_drive_t *);
+void ide_dma_host_off(ide_drive_t *);
+void ide_dma_off_quietly(ide_drive_t *);
+void ide_dma_host_on(ide_drive_t *);
 extern int __ide_dma_on(ide_drive_t *);
 extern int __ide_dma_check(ide_drive_t *);
 extern int ide_dma_setup(ide_drive_t *);
@@ -1305,8 +1302,9 @@
 
 #else
 static inline int ide_use_dma(ide_drive_t *drive) { return 0; }
-static inline int __ide_dma_off(ide_drive_t *drive) { return 0; }
+static inline void ide_dma_off(ide_drive_t *drive) { ; }
 static inline void ide_dma_verbose(ide_drive_t *drive) { ; }
+static inline int ide_set_dma(ide_drive_t *drive) { return 1; }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 #ifndef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -1354,6 +1352,7 @@
 extern char *ide_xfer_verbose(u8 xfer_rate);
 extern void ide_toggle_bounce(ide_drive_t *drive, int on);
 extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
+int ide_use_fast_pio(ide_drive_t *);
 
 u8 ide_dump_status(ide_drive_t *, const char *, u8);
 
@@ -1367,7 +1366,6 @@
 	u8 pio_mode;
 	u8 use_iordy;
 	u8 overridden;
-	u8 blacklisted;
 	unsigned int cycle_time;
 } ide_pio_data_t;
 
diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
index 99393ef..f3de05c 100644
--- a/include/linux/if_packet.h
+++ b/include/linux/if_packet.h
@@ -41,6 +41,7 @@
 #define PACKET_RX_RING			5
 #define PACKET_STATISTICS		6
 #define PACKET_COPY_THRESH		7
+#define PACKET_AUXDATA			8
 
 struct tpacket_stats
 {
@@ -48,6 +49,15 @@
 	unsigned int	tp_drops;
 };
 
+struct tpacket_auxdata
+{
+	__u32		tp_status;
+	__u32		tp_len;
+	__u32		tp_snaplen;
+	__u16		tp_mac;
+	__u16		tp_net;
+};
+
 struct tpacket_hdr
 {
 	unsigned long	tp_status;
diff --git a/include/linux/init.h b/include/linux/init.h
index 5a593a1..e290a01 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -67,7 +67,8 @@
 extern initcall_t __security_initcall_start[], __security_initcall_end[];
 
 /* Defined in init/main.c */
-extern char saved_command_line[];
+extern char __initdata boot_command_line[];
+extern char *saved_command_line;
 extern unsigned int reset_devices;
 
 /* used by init/main.c */
@@ -164,7 +165,7 @@
 #define early_param(str, fn)					\
 	__setup_param(str, fn, fn, 1)
 
-/* Relies on saved_command_line being set */
+/* Relies on boot_command_line being set */
 void __init parse_early_param(void);
 #endif /* __ASSEMBLY__ */
 
@@ -172,7 +173,7 @@
  * module_init() - driver initialization entry point
  * @x: function to be run at kernel boot time or module insertion
  * 
- * module_init() will either be called during do_initcalls (if
+ * module_init() will either be called during do_initcalls() (if
  * builtin) or at module insertion time (if a module).  There can only
  * be one per module.
  */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 6383d2d..a2d95ff 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -66,7 +66,7 @@
 	.cpu_timers	= INIT_CPU_TIMERS(sig.cpu_timers),		\
 	.rlim		= INIT_RLIMITS,					\
 	.pgrp		= 1,						\
-	.tty_old_pgrp   = 0,						\
+	.tty_old_pgrp   = NULL,						\
 	{ .__session      = 1},						\
 }
 
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index e36e86c..838cf5a 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -12,6 +12,7 @@
 #include <linux/sched.h>
 #include <linux/irqflags.h>
 #include <linux/bottom_half.h>
+#include <linux/device.h>
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -41,6 +42,8 @@
  * IRQF_SHARED - allow sharing the irq among several devices
  * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
  * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
+ * IRQF_PERCPU - Interrupt is per cpu
+ * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
  */
 #define IRQF_DISABLED		0x00000020
 #define IRQF_SAMPLE_RANDOM	0x00000040
@@ -48,6 +51,7 @@
 #define IRQF_PROBE_SHARED	0x00000100
 #define IRQF_TIMER		0x00000200
 #define IRQF_PERCPU		0x00000400
+#define IRQF_NOBALANCING	0x00000800
 
 /*
  * Migration helpers. Scheduled for removal in 1/2007
@@ -83,6 +87,11 @@
 		       unsigned long, const char *, void *);
 extern void free_irq(unsigned int, void *);
 
+extern int devm_request_irq(struct device *dev, unsigned int irq,
+			    irq_handler_t handler, unsigned long irqflags,
+			    const char *devname, void *dev_id);
+extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
+
 /*
  * On lockdep we dont want to enable hardirqs in hardirq
  * context. Use local_irq_enable_in_hardirq() to annotate
@@ -233,6 +242,9 @@
 	BLOCK_SOFTIRQ,
 	TASKLET_SOFTIRQ,
 	SCHED_SOFTIRQ,
+#ifdef CONFIG_HIGH_RES_TIMERS
+	HRTIMER_SOFTIRQ,
+#endif
 };
 
 /* softirq mask and active fields moved to irq_cpustat_t in
@@ -411,4 +423,13 @@
 extern unsigned int probe_irq_mask(unsigned long);	/* returns mask of ISA interrupts */
 #endif
 
+#ifdef CONFIG_PROC_FS
+/* Initialize /proc/irq/ */
+extern void init_irq_proc(void);
+#else
+static inline void init_irq_proc(void)
+{
+}
+#endif
+
 #endif
diff --git a/include/linux/io.h b/include/linux/io.h
index 81877ea..c244a0c 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -22,12 +22,27 @@
 #include <asm/io.h>
 #include <asm/page.h>
 
+struct device;
+
 void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
 void __iowrite64_copy(void __iomem *to, const void *from, size_t count);
 
 int ioremap_page_range(unsigned long addr, unsigned long end,
 		       unsigned long phys_addr, pgprot_t prot);
 
+/*
+ * Managed iomap interface
+ */
+void __iomem * devm_ioport_map(struct device *dev, unsigned long port,
+			       unsigned int nr);
+void devm_ioport_unmap(struct device *dev, void __iomem *addr);
+
+void __iomem * devm_ioremap(struct device *dev, unsigned long offset,
+			    unsigned long size);
+void __iomem * devm_ioremap_nocache(struct device *dev, unsigned long offset,
+				    unsigned long size);
+void devm_iounmap(struct device *dev, void __iomem *addr);
+
 /**
  *	check_signature		-	find BIOS signatures
  *	@io_addr: mmio address to check
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 15228d7..6859a3b 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -137,4 +137,24 @@
 {
 	return __check_region(&ioport_resource, s, n);
 }
+
+/* Wrappers for managed devices */
+struct device;
+#define devm_request_region(dev,start,n,name) \
+	__devm_request_region(dev, &ioport_resource, (start), (n), (name))
+#define devm_request_mem_region(dev,start,n,name) \
+	__devm_request_region(dev, &iomem_resource, (start), (n), (name))
+
+extern struct resource * __devm_request_region(struct device *dev,
+				struct resource *parent, resource_size_t start,
+				resource_size_t n, const char *name);
+
+#define devm_release_region(start,n) \
+	__devm_release_region(dev, &ioport_resource, (start), (n))
+#define devm_release_mem_region(start,n) \
+	__devm_release_region(dev, &iomem_resource, (start), (n))
+
+extern void __devm_release_region(struct device *dev, struct resource *parent,
+				  resource_size_t start, resource_size_t n);
+
 #endif	/* _LINUX_IOPORT_H */
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 5504b67..b0a44b8 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -31,7 +31,7 @@
 /*
  * IRQ line status.
  *
- * Bits 0-16 are reserved for the IRQF_* bits in linux/interrupt.h
+ * Bits 0-7 are reserved for the IRQF_* bits in linux/interrupt.h
  *
  * IRQ types
  */
@@ -45,28 +45,30 @@
 #define IRQ_TYPE_PROBE		0x00000010	/* Probing in progress */
 
 /* Internal flags */
-#define IRQ_INPROGRESS		0x00010000	/* IRQ handler active - do not enter! */
-#define IRQ_DISABLED		0x00020000	/* IRQ disabled - do not enter! */
-#define IRQ_PENDING		0x00040000	/* IRQ pending - replay on enable */
-#define IRQ_REPLAY		0x00080000	/* IRQ has been replayed but not acked yet */
-#define IRQ_AUTODETECT		0x00100000	/* IRQ is being autodetected */
-#define IRQ_WAITING		0x00200000	/* IRQ not yet seen - for autodetection */
-#define IRQ_LEVEL		0x00400000	/* IRQ level triggered */
-#define IRQ_MASKED		0x00800000	/* IRQ masked - shouldn't be seen again */
-#define IRQ_PER_CPU		0x01000000	/* IRQ is per CPU */
+#define IRQ_INPROGRESS		0x00000100	/* IRQ handler active - do not enter! */
+#define IRQ_DISABLED		0x00000200	/* IRQ disabled - do not enter! */
+#define IRQ_PENDING		0x00000400	/* IRQ pending - replay on enable */
+#define IRQ_REPLAY		0x00000800	/* IRQ has been replayed but not acked yet */
+#define IRQ_AUTODETECT		0x00001000	/* IRQ is being autodetected */
+#define IRQ_WAITING		0x00002000	/* IRQ not yet seen - for autodetection */
+#define IRQ_LEVEL		0x00004000	/* IRQ level triggered */
+#define IRQ_MASKED		0x00008000	/* IRQ masked - shouldn't be seen again */
+#define IRQ_PER_CPU		0x00010000	/* IRQ is per CPU */
+#define IRQ_NOPROBE		0x00020000	/* IRQ is not valid for probing */
+#define IRQ_NOREQUEST		0x00040000	/* IRQ cannot be requested */
+#define IRQ_NOAUTOEN		0x00080000	/* IRQ will not be enabled on request irq */
+#define IRQ_WAKEUP		0x00100000	/* IRQ triggers system wakeup */
+#define IRQ_MOVE_PENDING	0x00200000	/* need to re-target IRQ destination */
+#define IRQ_NO_BALANCING	0x00400000	/* IRQ is excluded from balancing */
+
 #ifdef CONFIG_IRQ_PER_CPU
 # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
+# define IRQ_NO_BALANCING_MASK	(IRQ_PER_CPU | IRQ_NO_BALANCING)
 #else
 # define CHECK_IRQ_PER_CPU(var) 0
+# define IRQ_NO_BALANCING_MASK	IRQ_NO_BALANCING
 #endif
 
-#define IRQ_NOPROBE		0x02000000	/* IRQ is not valid for probing */
-#define IRQ_NOREQUEST		0x04000000	/* IRQ cannot be requested */
-#define IRQ_NOAUTOEN		0x08000000	/* IRQ will not be enabled on request irq */
-#define IRQ_DELAYED_DISABLE	0x10000000	/* IRQ disable (masking) happens delayed. */
-#define IRQ_WAKEUP		0x20000000	/* IRQ triggers system wakeup */
-#define IRQ_MOVE_PENDING	0x40000000	/* need to re-target IRQ destination */
-
 struct proc_dir_entry;
 struct msi_desc;
 
@@ -127,6 +129,7 @@
  *
  * @handle_irq:		highlevel irq-events handler [if NULL, __do_IRQ()]
  * @chip:		low level interrupt hardware access
+ * @msi_desc:		MSI descriptor
  * @handler_data:	per-IRQ data for the irq_chip methods
  * @chip_data:		platform-specific per-chip private data for the chip
  *			methods, to allow shared chip implementations
@@ -197,17 +200,6 @@
 #endif
 
 #ifdef CONFIG_SMP
-static inline void set_native_irq_info(int irq, cpumask_t mask)
-{
-	irq_desc[irq].affinity = mask;
-}
-#else
-static inline void set_native_irq_info(int irq, cpumask_t mask)
-{
-}
-#endif
-
-#ifdef CONFIG_SMP
 
 #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
 
@@ -235,11 +227,21 @@
 
 #endif /* CONFIG_GENERIC_PENDING_IRQ */
 
+extern int irq_set_affinity(unsigned int irq, cpumask_t cpumask);
+extern int irq_can_set_affinity(unsigned int irq);
+
 #else /* CONFIG_SMP */
 
 #define move_native_irq(x)
 #define move_masked_irq(x)
 
+static inline int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
+{
+	return -EINVAL;
+}
+
+static inline int irq_can_set_affinity(unsigned int irq) { return 0; }
+
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_IRQBALANCE
@@ -261,6 +263,11 @@
 
 extern int no_irq_affinity;
 
+static inline int irq_balancing_disabled(unsigned int irq)
+{
+	return irq_desc[irq].status & IRQ_NO_BALANCING_MASK;
+}
+
 /* Handle irq action chains: */
 extern int handle_IRQ_event(unsigned int irq, struct irqaction *action);
 
@@ -310,9 +317,6 @@
 /* Resending of interrupts :*/
 void check_irq_resend(struct irq_desc *desc, unsigned int irq);
 
-/* Initialize /proc/irq/ */
-extern void init_irq_proc(void);
-
 /* Enable/disable irq debugging output: */
 extern int noirqdebug_setup(char *str);
 
diff --git a/include/linux/jffs.h b/include/linux/jffs.h
deleted file mode 100644
index 9221321..0000000
--- a/include/linux/jffs.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * JFFS -- Journalling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000  Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * This 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.
- *
- * $Id: jffs.h,v 1.20 2001/09/18 21:33:37 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-
-#ifndef __LINUX_JFFS_H__
-#define __LINUX_JFFS_H__
-
-#include <linux/types.h>
-#include <linux/completion.h>
-
-#define JFFS_VERSION_STRING "1.0"
-
-/* This is a magic number that is used as an identification number for
-   this file system.  It is written to the super_block structure.  */
-#define JFFS_MAGIC_SB_BITMASK 0x07c0  /* 1984 */
-
-/* This is a magic number that every on-flash raw inode begins with.  */
-#define JFFS_MAGIC_BITMASK 0x34383931 /* "1984" */
-
-/* These two bitmasks are the valid ones for the flash memories we have
-   for the moment.  */
-#define JFFS_EMPTY_BITMASK 0xffffffff
-#define JFFS_DIRTY_BITMASK 0x00000000
-
-/* This is the inode number of the root node.  */
-#define JFFS_MIN_INO 1
-
-/* How many slots in the file hash table should we have?  */
-#define JFFS_HASH_SIZE 40
-
-/* Don't use more than 254 bytes as the maximum allowed length of a file's
-   name due to errors that could occur during the scanning of the flash
-   memory. In fact, a name length of 255 or 0xff, could be the result of
-   an uncompleted write.  For instance, if a raw inode is written to the
-   flash memory and there is a power lossage just before the length of
-   the name is written, the length 255 would be interpreted as an illegal
-   value.  */
-#define JFFS_MAX_NAME_LEN 254
-
-/* Commands for ioctl().  */
-#define JFFS_IOCTL_MAGIC 't'
-#define JFFS_PRINT_HASH _IO(JFFS_IOCTL_MAGIC, 90)
-#define JFFS_PRINT_TREE _IO(JFFS_IOCTL_MAGIC, 91)
-#define JFFS_GET_STATUS _IO(JFFS_IOCTL_MAGIC, 92)
-
-/* XXX: This is something that we should try to get rid of in the future.  */
-#define JFFS_MODIFY_INODE 0x01
-#define JFFS_MODIFY_NAME  0x02
-#define JFFS_MODIFY_DATA  0x04
-#define JFFS_MODIFY_EXIST 0x08
-
-struct jffs_control;
-
-/* The JFFS raw inode structure: Used for storage on physical media.  */
-/* Perhaps the uid, gid, atime, mtime and ctime members should have
-   more space due to future changes in the Linux kernel. Anyhow, since
-   a user of this filesystem probably have to fix a large number of
-   other things, we have decided to not be forward compatible.  */
-struct jffs_raw_inode
-{
-	__u32 magic;      /* A constant magic number.  */
-	__u32 ino;        /* Inode number.  */
-	__u32 pino;       /* Parent's inode number.  */
-	__u32 version;    /* Version number.  */
-	__u32 mode;       /* The file's type or mode.  */
-	__u16 uid;        /* The file's owner.  */
-	__u16 gid;        /* The file's group.  */
-	__u32 atime;      /* Last access time.  */
-	__u32 mtime;      /* Last modification time.  */
-	__u32 ctime;      /* Creation time.  */
-	__u32 offset;     /* Where to begin to write.  */
-	__u32 dsize;      /* Size of the node's data.  */
-	__u32 rsize;      /* How much are going to be replaced?  */
-	__u8 nsize;       /* Name length.  */
-	__u8 nlink;       /* Number of links.  */
-	__u8 spare : 6;   /* For future use.  */
-	__u8 rename : 1;  /* Rename to a name of an already existing file?  */
-	__u8 deleted : 1; /* Has this file been deleted?  */
-	__u8 accurate;    /* The inode is obsolete if accurate == 0.  */
-	__u32 dchksum;    /* Checksum for the data.  */
-	__u16 nchksum;    /* Checksum for the name.  */
-	__u16 chksum;     /* Checksum for the raw inode.  */
-};
-
-/* Define the offset of the accurate byte in struct jffs_raw_inode.  */
-#define JFFS_RAW_INODE_ACCURATE_OFFSET (sizeof(struct jffs_raw_inode) \
-					- 2 * sizeof(__u32) - sizeof(__u8))
-
-/* Define the offset of the chksum member in struct jffs_raw_inode.  */
-#define JFFS_RAW_INODE_CHKSUM_OFFSET (sizeof(struct jffs_raw_inode) \
-				      - sizeof(__u16))
-
-/* Define the offset of the dchksum member in struct jffs_raw_inode.  */
-#define JFFS_RAW_INODE_DCHKSUM_OFFSET (sizeof(struct jffs_raw_inode)   \
-				       - sizeof(__u16) - sizeof(__u16) \
-				       - sizeof(__u32))
-
-
-/* The RAM representation of the node.  The names of pointers to
-   jffs_nodes are very often just called `n' in the source code.  */
-struct jffs_node
-{
-	__u32 ino;          /* Inode number.  */
-	__u32 version;      /* Version number.  */
-	__u32 data_offset;  /* Logic location of the data to insert.  */
-	__u32 data_size;    /* The amount of data this node inserts.  */
-	__u32 removed_size; /* The amount of data that this node removes.  */
-	__u32 fm_offset;    /* Physical location of the data in the actual
-			       flash memory data chunk.  */
-	__u8 name_size;     /* Size of the name.  */
-	struct jffs_fm *fm; /* Physical memory information.  */
-	struct jffs_node *version_prev;
-	struct jffs_node *version_next;
-	struct jffs_node *range_prev;
-	struct jffs_node *range_next;
-};
-
-
-/* The RAM representation of a file (plain files, directories,
-   links, etc.).  Pointers to jffs_files are normally named `f'
-   in the JFFS source code.  */
-struct jffs_file
-{
-	__u32 ino;    /* Inode number.  */
-	__u32 pino;   /* Parent's inode number.  */
-	__u32 mode;   /* file_type, mode  */
-	__u16 uid;    /* owner  */
-	__u16 gid;    /* group  */
-	__u32 atime;  /* Last access time.  */
-	__u32 mtime;  /* Last modification time.  */
-	__u32 ctime;  /* Creation time.  */
-	__u8 nsize;   /* Name length.  */
-	__u8 nlink;   /* Number of links.  */
-	__u8 deleted; /* Has this file been deleted?  */
-	char *name;   /* The name of this file; NULL-terminated.  */
-	__u32 size;   /* The total size of the file's data.  */
-	__u32 highest_version; /* The highest version number of this file.  */
-	struct jffs_control *c;
-	struct jffs_file *parent;   /* Reference to the parent directory.  */
-	struct jffs_file *children; /* Always NULL for plain files.  */
-	struct jffs_file *sibling_prev; /* Siblings in the same directory.  */
-	struct jffs_file *sibling_next;
-	struct list_head hash;    /* hash list.  */
-	struct jffs_node *range_head;   /* The final data.  */
-	struct jffs_node *range_tail;   /* The first data.  */
-	struct jffs_node *version_head; /* The youngest node.  */
-	struct jffs_node *version_tail; /* The oldest node.  */
-};
-
-
-/* This is just a definition of a simple list used for keeping track of
-   files deleted due to a rename.  This list is only used during the
-   mounting of the file system and only if there have been rename operations
-   earlier.  */
-struct jffs_delete_list
-{
-	__u32 ino;
-	struct jffs_delete_list *next;
-};
-
-
-/* A struct for the overall file system control.  Pointers to
-   jffs_control structs are named `c' in the source code.  */
-struct jffs_control
-{
-	struct super_block *sb;		/* Reference to the VFS super block.  */
-	struct jffs_file *root;		/* The root directory file.  */
-	struct list_head *hash;		/* Hash table for finding files by ino.  */
-	struct jffs_fmcontrol *fmc;	/* Flash memory control structure.  */
-	__u32 hash_len;			/* The size of the hash table.  */
-	__u32 next_ino;			/* Next inode number to use for new files.  */
-	__u16 building_fs;		/* Is the file system being built right now?  */
-	struct jffs_delete_list *delete_list; /* Track deleted files.  */
-	pid_t thread_pid;		/* GC thread's PID */
-	struct task_struct *gc_task;	/* GC task struct */
-	struct completion gc_thread_comp; /* GC thread exit mutex */
-	__u32 gc_minfree_threshold;	/* GC trigger thresholds */
-	__u32 gc_maxdirty_threshold;
-};
-
-
-/* Used to inform about flash status.  */
-struct jffs_flash_status
-{
-	__u32 size;
-	__u32 used;
-	__u32 dirty;
-	__u32 begin;
-	__u32 end;
-};
-
-/* This stuff could be used for finding memory leaks.  */
-#define JFFS_MEMORY_DEBUG 0
-
-extern long no_jffs_node;
-#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
-extern long no_jffs_control;
-extern long no_jffs_raw_inode;
-extern long no_jffs_node_ref;
-extern long no_jffs_fm;
-extern long no_jffs_fmcontrol;
-extern long no_hash;
-extern long no_name;
-#define DJM(x) x
-#else
-#define DJM(x)
-#endif
-
-#endif /* __LINUX_JFFS_H__ */
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 0ec6e28..c080f61 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -142,13 +142,13 @@
  *
  * And some not so obvious.
  *
- * Note that we don't want to return MAX_LONG, because
+ * Note that we don't want to return LONG_MAX, because
  * for various timeout reasons we often end up having
  * to wait "jiffies+1" in order to guarantee that we wait
  * at _least_ "jiffies" - so "jiffies+1" had better still
  * be positive.
  */
-#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
+#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1)-1)
 
 /*
  * We want to do realistic conversions of time so we need to use the same
@@ -259,207 +259,23 @@
 #endif
 
 /*
- * Convert jiffies to milliseconds and back.
- *
- * Avoid unnecessary multiplications/divisions in the
- * two most common HZ cases:
+ * Convert various time units to each other:
  */
-static inline unsigned int jiffies_to_msecs(const unsigned long j)
-{
-#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
-	return (MSEC_PER_SEC / HZ) * j;
-#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
-	return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
-#else
-	return (j * MSEC_PER_SEC) / HZ;
-#endif
-}
+extern unsigned int jiffies_to_msecs(const unsigned long j);
+extern unsigned int jiffies_to_usecs(const unsigned long j);
+extern unsigned long msecs_to_jiffies(const unsigned int m);
+extern unsigned long usecs_to_jiffies(const unsigned int u);
+extern unsigned long timespec_to_jiffies(const struct timespec *value);
+extern void jiffies_to_timespec(const unsigned long jiffies,
+				struct timespec *value);
+extern unsigned long timeval_to_jiffies(const struct timeval *value);
+extern void jiffies_to_timeval(const unsigned long jiffies,
+			       struct timeval *value);
+extern clock_t jiffies_to_clock_t(long x);
+extern unsigned long clock_t_to_jiffies(unsigned long x);
+extern u64 jiffies_64_to_clock_t(u64 x);
+extern u64 nsec_to_clock_t(u64 x);
 
-static inline unsigned int jiffies_to_usecs(const unsigned long j)
-{
-#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
-	return (USEC_PER_SEC / HZ) * j;
-#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
-	return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC);
-#else
-	return (j * USEC_PER_SEC) / HZ;
-#endif
-}
-
-static inline unsigned long msecs_to_jiffies(const unsigned int m)
-{
-	if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
-		return MAX_JIFFY_OFFSET;
-#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
-	return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ);
-#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
-	return m * (HZ / MSEC_PER_SEC);
-#else
-	return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC;
-#endif
-}
-
-static inline unsigned long usecs_to_jiffies(const unsigned int u)
-{
-	if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
-		return MAX_JIFFY_OFFSET;
-#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
-	return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ);
-#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
-	return u * (HZ / USEC_PER_SEC);
-#else
-	return (u * HZ + USEC_PER_SEC - 1) / USEC_PER_SEC;
-#endif
-}
-
-/*
- * The TICK_NSEC - 1 rounds up the value to the next resolution.  Note
- * that a remainder subtract here would not do the right thing as the
- * resolution values don't fall on second boundries.  I.e. the line:
- * nsec -= nsec % TICK_NSEC; is NOT a correct resolution rounding.
- *
- * Rather, we just shift the bits off the right.
- *
- * The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec
- * value to a scaled second value.
- */
-static __inline__ unsigned long
-timespec_to_jiffies(const struct timespec *value)
-{
-	unsigned long sec = value->tv_sec;
-	long nsec = value->tv_nsec + TICK_NSEC - 1;
-
-	if (sec >= MAX_SEC_IN_JIFFIES){
-		sec = MAX_SEC_IN_JIFFIES;
-		nsec = 0;
-	}
-	return (((u64)sec * SEC_CONVERSION) +
-		(((u64)nsec * NSEC_CONVERSION) >>
-		 (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
-
-}
-
-static __inline__ void
-jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)
-{
-	/*
-	 * Convert jiffies to nanoseconds and separate with
-	 * one divide.
-	 */
-	u64 nsec = (u64)jiffies * TICK_NSEC;
-	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_nsec);
-}
-
-/* Same for "timeval"
- *
- * Well, almost.  The problem here is that the real system resolution is
- * in nanoseconds and the value being converted is in micro seconds.
- * Also for some machines (those that use HZ = 1024, in-particular),
- * there is a LARGE error in the tick size in microseconds.
-
- * The solution we use is to do the rounding AFTER we convert the
- * microsecond part.  Thus the USEC_ROUND, the bits to be shifted off.
- * Instruction wise, this should cost only an additional add with carry
- * instruction above the way it was done above.
- */
-static __inline__ unsigned long
-timeval_to_jiffies(const struct timeval *value)
-{
-	unsigned long sec = value->tv_sec;
-	long usec = value->tv_usec;
-
-	if (sec >= MAX_SEC_IN_JIFFIES){
-		sec = MAX_SEC_IN_JIFFIES;
-		usec = 0;
-	}
-	return (((u64)sec * SEC_CONVERSION) +
-		(((u64)usec * USEC_CONVERSION + USEC_ROUND) >>
-		 (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
-}
-
-static __inline__ void
-jiffies_to_timeval(const unsigned long jiffies, struct timeval *value)
-{
-	/*
-	 * Convert jiffies to nanoseconds and separate with
-	 * one divide.
-	 */
-	u64 nsec = (u64)jiffies * TICK_NSEC;
-	long tv_usec;
-
-	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tv_usec);
-	tv_usec /= NSEC_PER_USEC;
-	value->tv_usec = tv_usec;
-}
-
-/*
- * Convert jiffies/jiffies_64 to clock_t and back.
- */
-static inline clock_t jiffies_to_clock_t(long x)
-{
-#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
-	return x / (HZ / USER_HZ);
-#else
-	u64 tmp = (u64)x * TICK_NSEC;
-	do_div(tmp, (NSEC_PER_SEC / USER_HZ));
-	return (long)tmp;
-#endif
-}
-
-static inline unsigned long clock_t_to_jiffies(unsigned long x)
-{
-#if (HZ % USER_HZ)==0
-	if (x >= ~0UL / (HZ / USER_HZ))
-		return ~0UL;
-	return x * (HZ / USER_HZ);
-#else
-	u64 jif;
-
-	/* Don't worry about loss of precision here .. */
-	if (x >= ~0UL / HZ * USER_HZ)
-		return ~0UL;
-
-	/* .. but do try to contain it here */
-	jif = x * (u64) HZ;
-	do_div(jif, USER_HZ);
-	return jif;
-#endif
-}
-
-static inline u64 jiffies_64_to_clock_t(u64 x)
-{
-#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
-	do_div(x, HZ / USER_HZ);
-#else
-	/*
-	 * There are better ways that don't overflow early,
-	 * but even this doesn't overflow in hundreds of years
-	 * in 64 bits, so..
-	 */
-	x *= TICK_NSEC;
-	do_div(x, (NSEC_PER_SEC / USER_HZ));
-#endif
-	return x;
-}
-
-static inline u64 nsec_to_clock_t(u64 x)
-{
-#if (NSEC_PER_SEC % USER_HZ) == 0
-	do_div(x, (NSEC_PER_SEC / USER_HZ));
-#elif (USER_HZ % 512) == 0
-	x *= USER_HZ/512;
-	do_div(x, (NSEC_PER_SEC / 512));
-#else
-	/*
-         * max relative error 5.7e-8 (1.8s per year) for USER_HZ <= 1024,
-         * overflow after 64.99 years.
-         * exact for HZ=60, 72, 90, 120, 144, 180, 300, 600, 900, ...
-         */
-	x *= 9;
-	do_div(x, (unsigned long)((9ull * NSEC_PER_SEC + (USER_HZ/2))
-	                          / USER_HZ));
-#endif
-	return x;
-}
+#define TIMESTAMP_SIZE	30
 
 #endif
diff --git a/include/linux/kdev_t.h b/include/linux/kdev_t.h
index bceea52..4c2c373 100644
--- a/include/linux/kdev_t.h
+++ b/include/linux/kdev_t.h
@@ -87,6 +87,7 @@
 	return dev & 0x3ffff;
 }
 
+bool is_lanana_major(unsigned int major);
 
 #else /* __KERNEL__ */
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 63fb18dc..9ddf25c 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -92,11 +92,6 @@
 		(__x < 0) ? -__x : __x;		\
 	})
 
-#define labs(x) ({				\
-		long __x = (x);			\
-		(__x < 0) ? -__x : __x;		\
-	})
-
 extern struct atomic_notifier_head panic_notifier_list;
 extern long (*panic_blink)(long time);
 NORET_TYPE void panic(const char * fmt, ...)
@@ -139,7 +134,8 @@
 extern int core_kernel_text(unsigned long addr);
 extern int __kernel_text_address(unsigned long addr);
 extern int kernel_text_address(unsigned long addr);
-extern int session_of_pgrp(int pgrp);
+struct pid;
+extern struct pid *session_of_pgrp(struct pid *pgrp);
 
 extern void dump_thread(struct pt_regs *regs, struct user *dump);
 
@@ -176,6 +172,7 @@
 }
 
 extern void bust_spinlocks(int yes);
+extern void wake_up_klogd(void);
 extern int oops_in_progress;		/* If set, an oops, panic(), BUG() or die() is in progress */
 extern int panic_timeout;
 extern int panic_on_oops;
@@ -200,6 +197,7 @@
 #define TAINT_FORCED_RMMOD		(1<<3)
 #define TAINT_MACHINE_CHECK		(1<<4)
 #define TAINT_BAD_PAGE			(1<<5)
+#define TAINT_USER			(1<<6)
 
 extern void dump_stack(void);
 
@@ -312,6 +310,9 @@
 	(void)__tmp; \
 })
 
+struct sysinfo;
+extern int do_sysinfo(struct sysinfo *info);
+
 #endif /* __KERNEL__ */
 
 #define SI_LOAD_SHIFT	16
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index d02425c..696e5ec 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -125,6 +125,7 @@
 #define KEXEC_ARCH_PPC     (20 << 16)
 #define KEXEC_ARCH_PPC64   (21 << 16)
 #define KEXEC_ARCH_IA_64   (50 << 16)
+#define KEXEC_ARCH_ARM     (40 << 16)
 #define KEXEC_ARCH_S390    (22 << 16)
 #define KEXEC_ARCH_SH      (42 << 16)
 #define KEXEC_ARCH_MIPS_LE (10 << 16)
diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
index 48eccd8..404f446 100644
--- a/include/linux/kfifo.h
+++ b/include/linux/kfifo.h
@@ -74,7 +74,7 @@
  * @buffer: the data to be added.
  * @len: the length of the data to be added.
  *
- * This function copies at most 'len' bytes from the 'buffer' into
+ * This function copies at most @len bytes from the @buffer into
  * the FIFO depending on the free space, and returns the number of
  * bytes copied.
  */
@@ -99,8 +99,8 @@
  * @buffer: where the data must be copied.
  * @len: the size of the destination buffer.
  *
- * This function copies at most 'len' bytes from the FIFO into the
- * 'buffer' and returns the number of copied bytes.
+ * This function copies at most @len bytes from the FIFO into the
+ * @buffer and returns the number of copied bytes.
  */
 static inline unsigned int kfifo_get(struct kfifo *fifo,
 				     unsigned char *buffer, unsigned int len)
diff --git a/include/linux/ks0108.h b/include/linux/ks0108.h
new file mode 100644
index 0000000..a2c54ac
--- /dev/null
+++ b/include/linux/ks0108.h
@@ -0,0 +1,49 @@
+/*
+ *    Filename: ks0108.h
+ *     Version: 0.1.0
+ * Description: ks0108 LCD Controller driver header
+ *     License: GPLv2
+ *
+ *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *        Date: 2006-10-31
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _KS0108_H_
+#define _KS0108_H_
+
+/* Write a byte to the data port */
+extern void ks0108_writedata(unsigned char byte);
+
+/* Write a byte to the control port */
+extern void ks0108_writecontrol(unsigned char byte);
+
+/* Set the controller's current display state (0..1) */
+extern void ks0108_displaystate(unsigned char state);
+
+/* Set the controller's current startline (0..63) */
+extern void ks0108_startline(unsigned char startline);
+
+/* Set the controller's current address (0..63) */
+extern void ks0108_address(unsigned char address);
+
+/* Set the controller's current page (0..7) */
+extern void ks0108_page(unsigned char page);
+
+/* Is the module inited? */
+extern unsigned char ks0108_isinited(void);
+
+#endif /* _KS0108_H_ */
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 611f17f..c68c7ac 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -163,7 +163,7 @@
  * @add1:	addend1
  * @add2:	addend2
  *
- * Returns the sum of addend1 and addend2
+ * Returns the sum of @add1 and @add2.
  */
 static inline ktime_t ktime_add(const ktime_t add1, const ktime_t add2)
 {
@@ -189,7 +189,7 @@
  * @kt:		addend
  * @nsec:	the scalar nsec value to add
  *
- * Returns the sum of kt and nsec in ktime_t format
+ * Returns the sum of @kt and @nsec in ktime_t format
  */
 extern ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);
 
@@ -246,7 +246,7 @@
  * ktime_to_ns - convert a ktime_t variable to scalar nanoseconds
  * @kt:		the ktime_t variable to convert
  *
- * Returns the scalar nanoseconds representation of kt
+ * Returns the scalar nanoseconds representation of @kt
  */
 static inline s64 ktime_to_ns(const ktime_t kt)
 {
@@ -261,8 +261,7 @@
  * idea of the (in)accuracy of timers. Timer values are rounded up to
  * this resolution values.
  */
-#define KTIME_REALTIME_RES	(ktime_t){ .tv64 = TICK_NSEC }
-#define KTIME_MONOTONIC_RES	(ktime_t){ .tv64 = TICK_NSEC }
+#define KTIME_LOW_RES		(ktime_t){ .tv64 = TICK_NSEC }
 
 /* Get the monotonic time in timespec format: */
 extern void ktime_get_ts(struct timespec *ts);
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 1be148f..f360459 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -11,7 +11,7 @@
 #include <asm/types.h>
 #include <linux/ioctl.h>
 
-#define KVM_API_VERSION 2
+#define KVM_API_VERSION 3
 
 /*
  * Architectural interrupt line count, and the size of the bitmap needed
@@ -65,6 +65,8 @@
 	__u8 ready_for_interrupt_injection;
 	__u8 if_flag;
 	__u16 padding2;
+
+	/* in (pre_kvm_run), out (post_kvm_run) */
 	__u64 cr8;
 	__u64 apic_base;
 
@@ -185,6 +187,7 @@
 	__u8  valid;
 	__u8  writeable;
 	__u8  usermode;
+	__u8  pad[5];
 };
 
 /* for KVM_INTERRUPT */
diff --git a/include/linux/lcd.h b/include/linux/lcd.h
index d739b2e..598793c 100644
--- a/include/linux/lcd.h
+++ b/include/linux/lcd.h
@@ -9,22 +9,38 @@
 #define _LINUX_LCD_H
 
 #include <linux/device.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 
+/* Notes on locking:
+ *
+ * lcd_device->ops_lock is an internal backlight lock protecting the ops
+ * field and no code outside the core should need to touch it.
+ *
+ * Access to set_power() is serialised by the update_lock mutex since
+ * most drivers seem to need this and historically get it wrong.
+ *
+ * Most drivers don't need locking on their get_power() method.
+ * If yours does, you need to implement it in the driver. You can use the
+ * update_lock mutex if appropriate.
+ *
+ * Any other use of the locks below is probably wrong.
+ */
+
 struct lcd_device;
 struct fb_info;
 
-/* This structure defines all the properties of a LCD flat panel. */
 struct lcd_properties {
-	/* Owner module */
-	struct module *owner;
+	/* The maximum value for contrast (read-only) */
+	int max_contrast;
+};
+
+struct lcd_ops {
 	/* Get the LCD panel power status (0: full on, 1..3: controller
 	   power on, flat panel power off, 4: full off), see FB_BLANK_XXX */
 	int (*get_power)(struct lcd_device *);
 	/* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */
 	int (*set_power)(struct lcd_device *, int power);
-	/* The maximum value for contrast (read-only) */
-	int max_contrast;
 	/* Get the current contrast setting (0-max_contrast) */
 	int (*get_contrast)(struct lcd_device *);
 	/* Set LCD panel contrast */
@@ -35,20 +51,31 @@
 };
 
 struct lcd_device {
-	/* This protects the 'props' field. If 'props' is NULL, the driver that
+	struct lcd_properties props;
+	/* This protects the 'ops' field. If 'ops' is NULL, the driver that
 	   registered this device has been unloaded, and if class_get_devdata()
 	   points to something in the body of that driver, it is also invalid. */
-	struct semaphore sem;
+	struct mutex ops_lock;
 	/* If this is NULL, the backing module is unloaded */
-	struct lcd_properties *props;
+	struct lcd_ops *ops;
+	/* Serialise access to set_power method */
+	struct mutex update_lock;
 	/* The framebuffer notifier block */
 	struct notifier_block fb_notif;
 	/* The class device structure */
 	struct class_device class_dev;
 };
 
+static inline void lcd_set_power(struct lcd_device *ld, int power)
+{
+	mutex_lock(&ld->update_lock);
+	if (ld->ops && ld->ops->set_power)
+		ld->ops->set_power(ld, power);
+	mutex_unlock(&ld->update_lock);
+}
+
 extern struct lcd_device *lcd_device_register(const char *name,
-	void *devdata, struct lcd_properties *lp);
+	void *devdata, struct lcd_ops *ops);
 extern void lcd_device_unregister(struct lcd_device *ld);
 
 #define to_lcd_device(obj) container_of(obj, struct lcd_device, class_dev)
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 91bb8ce..86762a9 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -31,10 +31,11 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <asm/scatterlist.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/ata.h>
 #include <linux/workqueue.h>
 #include <scsi/scsi_host.h>
+#include <linux/acpi.h>
 
 /*
  * Define if arch has non-standard setup.  This is a _PCI_ standard
@@ -54,8 +55,6 @@
 #undef ATA_VERBOSE_DEBUG	/* yet more debugging output */
 #undef ATA_IRQ_TRAP		/* define to ack screaming irqs */
 #undef ATA_NDEBUG		/* define to disable quick runtime checks */
-#define ATA_ENABLE_PATA		/* define to enable PATA support in some
-				 * low-level drivers */
 
 
 /* note: prints function name for you */
@@ -109,10 +108,6 @@
 #define ATA_TAG_POISON		0xfafbfcfdU
 
 /* move to PCI layer? */
-#define PCI_VDEVICE(vendor, device)		\
-	PCI_VENDOR_ID_##vendor, (device),	\
-	PCI_ANY_ID, PCI_ANY_ID, 0, 0
-
 static inline struct device *pci_dev_to_dev(struct pci_dev *pdev)
 {
 	return &pdev->dev;
@@ -178,6 +173,7 @@
 	ATA_FLAG_DEBUGMSG	= (1 << 13),
 	ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */
 	ATA_FLAG_IGN_SIMPLEX	= (1 << 15), /* ignore SIMPLEX */
+	ATA_FLAG_NO_IORDY	= (1 << 16), /* controller lacks iordy */
 
 	/* The following flag belongs to ap->pflags but is kept in
 	 * ap->flags because it's referenced in many LLDs and will be
@@ -308,7 +304,7 @@
 	 * most devices.
 	 */
 	ATA_SPINUP_WAIT		= 8000,
-	
+
 	/* Horkage types. May be set by libata or controller on drives
 	   (some horkage may be drive/controller pair dependant */
 
@@ -352,21 +348,21 @@
 typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *classes);
 
 struct ata_ioports {
-	unsigned long		cmd_addr;
-	unsigned long		data_addr;
-	unsigned long		error_addr;
-	unsigned long		feature_addr;
-	unsigned long		nsect_addr;
-	unsigned long		lbal_addr;
-	unsigned long		lbam_addr;
-	unsigned long		lbah_addr;
-	unsigned long		device_addr;
-	unsigned long		status_addr;
-	unsigned long		command_addr;
-	unsigned long		altstatus_addr;
-	unsigned long		ctl_addr;
-	unsigned long		bmdma_addr;
-	unsigned long		scr_addr;
+	void __iomem		*cmd_addr;
+	void __iomem		*data_addr;
+	void __iomem		*error_addr;
+	void __iomem		*feature_addr;
+	void __iomem		*nsect_addr;
+	void __iomem		*lbal_addr;
+	void __iomem		*lbam_addr;
+	void __iomem		*lbah_addr;
+	void __iomem		*device_addr;
+	void __iomem		*status_addr;
+	void __iomem		*command_addr;
+	void __iomem		*altstatus_addr;
+	void __iomem		*ctl_addr;
+	void __iomem		*bmdma_addr;
+	void __iomem		*scr_addr;
 };
 
 struct ata_probe_ent {
@@ -385,7 +381,7 @@
 	unsigned int		irq_flags;
 	unsigned long		port_flags;
 	unsigned long		_host_flags;
-	void __iomem		*mmio_base;
+	void __iomem * const	*iomap;
 	void			*private_data;
 
 	/* port_info for the secondary port.  Together with irq2, it's
@@ -402,7 +398,7 @@
 	struct device 		*dev;
 	unsigned long		irq;
 	unsigned long		irq2;
-	void __iomem		*mmio_base;
+	void __iomem * const	*iomap;
 	unsigned int		n_ports;
 	void			*private_data;
 	const struct ata_port_operations *ops;
@@ -431,9 +427,6 @@
 
 	unsigned int		pad_len;
 
-	unsigned int		nsect;
-	unsigned int		cursect;
-
 	unsigned int		nbytes;
 	unsigned int		curbytes;
 
@@ -503,6 +496,10 @@
 	/* error history */
 	struct ata_ering	ering;
 	unsigned int		horkage;	/* List of broken features */
+#ifdef CONFIG_SATA_ACPI
+	/* ACPI objects info */
+	acpi_handle obj_handle;
+#endif
 };
 
 /* Offset into struct ata_device.  Fields above it are maintained
@@ -639,6 +636,8 @@
 
 	irq_handler_t irq_handler;
 	void (*irq_clear) (struct ata_port *);
+	u8 (*irq_on) (struct ata_port *);
+	u8 (*irq_ack) (struct ata_port *ap, unsigned int chk_drq);
 
 	u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
 	void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
@@ -720,20 +719,18 @@
 			     unsigned int n_ports);
 extern void ata_pci_remove_one (struct pci_dev *pdev);
 extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg);
-extern void ata_pci_device_do_resume(struct pci_dev *pdev);
+extern int __must_check ata_pci_device_do_resume(struct pci_dev *pdev);
 extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 extern int ata_pci_device_resume(struct pci_dev *pdev);
 extern int ata_pci_clear_simplex(struct pci_dev *pdev);
 #endif /* CONFIG_PCI */
 extern int ata_device_add(const struct ata_probe_ent *ent);
-extern void ata_port_detach(struct ata_port *ap);
+extern void ata_host_detach(struct ata_host *host);
 extern void ata_host_init(struct ata_host *, struct device *,
 			  unsigned long, const struct ata_port_operations *);
-extern void ata_host_remove(struct ata_host *host);
 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_release(struct Scsi_Host *host);
 extern void ata_sas_port_destroy(struct ata_port *);
 extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
 					   struct ata_port_info *, struct Scsi_Host *);
@@ -776,15 +773,11 @@
 extern u8 ata_altstatus(struct ata_port *ap);
 extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
 extern int ata_port_start (struct ata_port *ap);
-extern void ata_port_stop (struct ata_port *ap);
-extern void ata_host_stop (struct ata_host *host);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance);
-extern void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
-			       unsigned int buflen, int write_data);
-extern void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf,
-			      unsigned int buflen, int write_data);
-extern void ata_pio_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
-			      unsigned int buflen, int write_data);
+extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
+			  unsigned int buflen, int write_data);
+extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
+				unsigned int buflen, int write_data);
 extern void ata_qc_prep(struct ata_queued_cmd *qc);
 extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
 extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -826,6 +819,10 @@
 extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
 				       int queue_depth);
 extern struct ata_device *ata_dev_pair(struct ata_device *adev);
+extern u8 ata_irq_on(struct ata_port *ap);
+extern u8 ata_dummy_irq_on(struct ata_port *ap);
+extern u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq);
+extern u8 ata_dummy_irq_ack(struct ata_port *ap, unsigned int chk_drq);
 
 /*
  * Timing helpers
@@ -864,7 +861,6 @@
 	unsigned long		val;
 };
 
-extern void ata_pci_host_stop (struct ata_host *host);
 extern struct ata_probe_ent *
 ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask);
 extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
@@ -1096,10 +1092,9 @@
 	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
 
 	if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ))) {
-		unsigned long l = ap->ioaddr.status_addr;
 		if (ata_msg_warn(ap))
-			printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n",
-				status, l);
+			printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%p\n",
+				status, ap->ioaddr.status_addr);
 	}
 
 	return status;
@@ -1149,8 +1144,7 @@
 	qc->dma_dir = DMA_NONE;
 	qc->__sg = NULL;
 	qc->flags = 0;
-	qc->cursect = qc->cursg = qc->cursg_ofs = 0;
-	qc->nsect = 0;
+	qc->cursg = qc->cursg_ofs = 0;
 	qc->nbytes = qc->curbytes = 0;
 	qc->n_elem = 0;
 	qc->err_mask = 0;
@@ -1163,51 +1157,6 @@
 	qc->result_tf.feature = 0;
 }
 
-/**
- *	ata_irq_ack - Acknowledge a device interrupt.
- *	@ap: Port on which interrupts are enabled.
- *
- *	Wait up to 10 ms for legacy IDE device to become idle (BUSY
- *	or BUSY+DRQ clear).  Obtain dma status and port status from
- *	device.  Clear the interrupt.  Return port status.
- *
- *	LOCKING:
- */
-
-static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
-{
-	unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
-	u8 host_stat, post_stat, status;
-
-	status = ata_busy_wait(ap, bits, 1000);
-	if (status & bits)
-		if (ata_msg_err(ap))
-			printk(KERN_ERR "abnormal status 0x%X\n", status);
-
-	/* get controller status; clear intr, err bits */
-	if (ap->flags & ATA_FLAG_MMIO) {
-		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-		host_stat = readb(mmio + ATA_DMA_STATUS);
-		writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
-		       mmio + ATA_DMA_STATUS);
-
-		post_stat = readb(mmio + ATA_DMA_STATUS);
-	} else {
-		host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-		outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
-		     ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-
-		post_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-	}
-
-	if (ata_msg_intr(ap))
-		printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
-			__FUNCTION__,
-			host_stat, post_stat, status);
-
-	return status;
-}
-
 static inline int ata_try_flush_cache(const struct ata_device *dev)
 {
 	return ata_id_wcache_enabled(dev->id) ||
@@ -1235,14 +1184,14 @@
 static inline int ata_pad_alloc(struct ata_port *ap, struct device *dev)
 {
 	ap->pad_dma = 0;
-	ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ,
-				     &ap->pad_dma, GFP_KERNEL);
+	ap->pad = dmam_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ,
+				      &ap->pad_dma, GFP_KERNEL);
 	return (ap->pad == NULL) ? -ENOMEM : 0;
 }
 
 static inline void ata_pad_free(struct ata_port *ap, struct device *dev)
 {
-	dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
+	dmam_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
 }
 
 static inline struct ata_port *ata_shost_to_port(struct Scsi_Host *host)
diff --git a/include/linux/list.h b/include/linux/list.h
index 611059d..f9d71ea 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -161,7 +161,7 @@
 /**
  * list_del - deletes entry from list.
  * @entry: the element to delete from the list.
- * Note: list_empty on entry does not return true after this, the entry is
+ * Note: list_empty() on entry does not return true after this, the entry is
  * in an undefined state.
  */
 #ifndef CONFIG_DEBUG_LIST
@@ -179,7 +179,7 @@
  * list_del_rcu - deletes entry from list without re-initialization
  * @entry: the element to delete from the list.
  *
- * Note: list_empty on entry does not return true after this,
+ * Note: list_empty() on entry does not return true after this,
  * the entry is in an undefined state. It is useful for RCU based
  * lockfree traversal.
  *
@@ -209,7 +209,8 @@
  * list_replace - replace old entry by new one
  * @old : the element to be replaced
  * @new : the new element to insert
- * Note: if 'old' was empty, it will be overwritten.
+ *
+ * If @old was empty, it will be overwritten.
  */
 static inline void list_replace(struct list_head *old,
 				struct list_head *new)
@@ -360,6 +361,62 @@
 }
 
 /**
+ * list_splice_init_rcu - splice an RCU-protected list into an existing list.
+ * @list:	the RCU-protected list to splice
+ * @head:	the place in the list to splice the first list into
+ * @sync:	function to sync: synchronize_rcu(), synchronize_sched(), ...
+ *
+ * @head can be RCU-read traversed concurrently with this function.
+ *
+ * Note that this function blocks.
+ *
+ * Important note: the caller must take whatever action is necessary to
+ *	prevent any other updates to @head.  In principle, it is possible
+ *	to modify the list as soon as sync() begins execution.
+ *	If this sort of thing becomes necessary, an alternative version
+ *	based on call_rcu() could be created.  But only if -really-
+ *	needed -- there is no shortage of RCU API members.
+ */
+static inline void list_splice_init_rcu(struct list_head *list,
+					struct list_head *head,
+					void (*sync)(void))
+{
+	struct list_head *first = list->next;
+	struct list_head *last = list->prev;
+	struct list_head *at = head->next;
+
+	if (list_empty(head))
+		return;
+
+	/* "first" and "last" tracking list, so initialize it. */
+
+	INIT_LIST_HEAD(list);
+
+	/*
+	 * At this point, the list body still points to the source list.
+	 * Wait for any readers to finish using the list before splicing
+	 * the list body into the new list.  Any new readers will see
+	 * an empty list.
+	 */
+
+	sync();
+
+	/*
+	 * Readers are finished with the source list, so perform splice.
+	 * The order is important if the new list is global and accessible
+	 * to concurrent RCU readers.  Note that RCU readers are not
+	 * permitted to traverse the prev pointers without excluding
+	 * this function.
+	 */
+
+	last->next = at;
+	smp_wmb();
+	head->next = first;
+	first->prev = head;
+	at->prev = last;
+}
+
+/**
  * list_entry - get the struct for this entry
  * @ptr:	the &struct list_head pointer.
  * @type:	the type of the struct this is embedded in.
@@ -432,12 +489,12 @@
 	     pos = list_entry(pos->member.prev, typeof(*pos), member))
 
 /**
- * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
  * @pos:	the type * to use as a start point
  * @head:	the head of the list
  * @member:	the name of the list_struct within the struct.
  *
- * Prepares a pos entry for use as a start point in list_for_each_entry_continue.
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
  */
 #define list_prepare_entry(pos, head, member) \
 	((pos) ? : list_entry(head, typeof(*pos), member))
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index ea097dd..06fe93a 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -8,6 +8,8 @@
 #ifndef __LINUX_LOCKDEP_H
 #define __LINUX_LOCKDEP_H
 
+struct task_struct;
+
 #ifdef CONFIG_LOCKDEP
 
 #include <linux/linkage.h>
@@ -132,6 +134,7 @@
 	struct list_head		entry;
 	struct lock_class		*class;
 	struct stack_trace		trace;
+	int				distance;
 };
 
 /*
diff --git a/include/linux/log2.h b/include/linux/log2.h
index 99922be..57e641e 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -152,7 +152,7 @@
  * roundup_pow_of_two - round the given value up to nearest power of two
  * @n - parameter
  *
- * round the given balue up to the nearest power of two
+ * round the given value up to the nearest power of two
  * - the result is undefined when n == 0
  * - this can be used to initialise global variables from constant data
  */
diff --git a/include/linux/magic.h b/include/linux/magic.h
index b78bbf4..b32c8a9 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -18,6 +18,7 @@
 #define MINIX_SUPER_MAGIC2	0x138F		/* minix fs, 30 char names */
 #define MINIX2_SUPER_MAGIC	0x2468		/* minix V2 fs */
 #define MINIX2_SUPER_MAGIC2	0x2478		/* minix V2 fs, 30 char names */
+#define MINIX3_SUPER_MAGIC	0x4d5a		/* minix V3 fs */
 
 #define MSDOS_SUPER_MAGIC	0x4d44		/* MD */
 #define NCP_SUPER_MAGIC		0x564c		/* Guess, what 0x564c is :-) */
diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h
index 432b2fa..bdc0112 100644
--- a/include/linux/mc146818rtc.h
+++ b/include/linux/mc146818rtc.h
@@ -18,6 +18,16 @@
 #ifdef __KERNEL__
 #include <linux/spinlock.h>		/* spinlock_t */
 extern spinlock_t rtc_lock;		/* serialize CMOS RAM access */
+
+/* Some RTCs extend the mc146818 register set to support alarms of more
+ * than 24 hours in the future; or dates that include a century code.
+ * This platform_data structure can pass this information to the driver.
+ */
+struct cmos_rtc_board_info {
+	u8	rtc_day_alarm;		/* zero, or register index */
+	u8	rtc_mon_alarm;		/* zero, or register index */
+	u8	rtc_century;		/* zero, or register index */
+};
 #endif
 
 /**********************************************************************
diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h
index 916e8f7..0e39745 100644
--- a/include/linux/minix_fs.h
+++ b/include/linux/minix_fs.h
@@ -25,7 +25,6 @@
 #define MINIX_ERROR_FS		0x0002		/* fs has errors. */
 
 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
-#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
 
 /*
  * This is the original minix inode layout on disk.
@@ -75,9 +74,32 @@
 	__u32 s_zones;
 };
 
+/*
+ * V3 minix super-block data on disk
+ */
+struct minix3_super_block {
+	__u32 s_ninodes;
+	__u16 s_pad0;
+	__u16 s_imap_blocks;
+	__u16 s_zmap_blocks;
+	__u16 s_firstdatazone;
+	__u16 s_log_zone_size;
+	__u16 s_pad1;
+	__u32 s_max_size;
+	__u32 s_zones;
+	__u16 s_magic;
+	__u16 s_pad2;
+	__u16 s_blocksize;
+	__u8  s_disk_version;
+};
+
 struct minix_dir_entry {
 	__u16 inode;
 	char name[0];
 };
 
+struct minix3_dir_entry {
+	__u32 inode;
+	char name[0];
+};
 #endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2d2c08d..a0eec16 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -437,15 +437,15 @@
 /* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allcator */
 #ifdef NODE_NOT_IN_PAGEFLAGS
 #define ZONEID_SHIFT		(SECTIONS_SHIFT + ZONES_SHIFT)
+#define ZONEID_PGOFF		((SECTIONS_PGOFF < ZONES_PGOFF)? \
+						SECTIONS_PGOFF : ZONES_PGOFF)
 #else
 #define ZONEID_SHIFT		(NODES_SHIFT + ZONES_SHIFT)
+#define ZONEID_PGOFF		((NODES_PGOFF < ZONES_PGOFF)? \
+						NODES_PGOFF : ZONES_PGOFF)
 #endif
 
-#if ZONES_WIDTH > 0
-#define ZONEID_PGSHIFT		ZONES_PGSHIFT
-#else
-#define ZONEID_PGSHIFT		NODES_PGOFF
-#endif
+#define ZONEID_PGSHIFT		(ZONEID_PGOFF * (ZONEID_SHIFT != 0))
 
 #if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
 #error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
@@ -471,7 +471,6 @@
  */
 static inline int page_zone_id(struct page *page)
 {
-	BUILD_BUG_ON(ZONEID_PGSHIFT == 0 && ZONEID_MASK);
 	return (page->flags >> ZONEID_PGSHIFT) & ZONEID_MASK;
 }
 
@@ -638,6 +637,7 @@
  */
 #define NOPFN_SIGBUS	((unsigned long) -1)
 #define NOPFN_OOM	((unsigned long) -2)
+#define NOPFN_REFAULT	((unsigned long) -3)
 
 /*
  * Different kinds of faults, as returned by handle_mm_fault().
@@ -786,6 +786,7 @@
 extern void do_invalidatepage(struct page *page, unsigned long offset);
 
 int __set_page_dirty_nobuffers(struct page *page);
+int __set_page_dirty_no_writeback(struct page *page);
 int redirty_page_for_writepage(struct writeback_control *wbc,
 				struct page *page);
 int FASTCALL(set_page_dirty(struct page *page));
@@ -1030,6 +1031,9 @@
 	unsigned long addr, unsigned long len, pgoff_t pgoff);
 extern void exit_mmap(struct mm_struct *);
 extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
+extern int install_special_mapping(struct mm_struct *mm,
+				   unsigned long addr, unsigned long len,
+				   unsigned long flags, struct page **pages);
 
 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 
@@ -1121,6 +1125,8 @@
 int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
 			unsigned long pfn, unsigned long size, pgprot_t);
 int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
+int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
+			unsigned long pfn);
 
 struct page *follow_page(struct vm_area_struct *, unsigned long address,
 			unsigned int foll_flags);
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index 3b6723d..895bc4e 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -1,30 +1,29 @@
-
 static inline void
 add_page_to_active_list(struct zone *zone, struct page *page)
 {
 	list_add(&page->lru, &zone->active_list);
-	zone->nr_active++;
+	__inc_zone_state(zone, NR_ACTIVE);
 }
 
 static inline void
 add_page_to_inactive_list(struct zone *zone, struct page *page)
 {
 	list_add(&page->lru, &zone->inactive_list);
-	zone->nr_inactive++;
+	__inc_zone_state(zone, NR_INACTIVE);
 }
 
 static inline void
 del_page_from_active_list(struct zone *zone, struct page *page)
 {
 	list_del(&page->lru);
-	zone->nr_active--;
+	__dec_zone_state(zone, NR_ACTIVE);
 }
 
 static inline void
 del_page_from_inactive_list(struct zone *zone, struct page *page)
 {
 	list_del(&page->lru);
-	zone->nr_inactive--;
+	__dec_zone_state(zone, NR_INACTIVE);
 }
 
 static inline void
@@ -33,9 +32,9 @@
 	list_del(&page->lru);
 	if (PageActive(page)) {
 		__ClearPageActive(page);
-		zone->nr_active--;
+		__dec_zone_state(zone, NR_ACTIVE);
 	} else {
-		zone->nr_inactive--;
+		__dec_zone_state(zone, NR_INACTIVE);
 	}
 }
 
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index b262f47..ee9e314 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -47,15 +47,20 @@
 #endif
 
 enum zone_stat_item {
+	/* First 128 byte cacheline (assuming 64 bit words) */
+	NR_FREE_PAGES,
+	NR_INACTIVE,
+	NR_ACTIVE,
 	NR_ANON_PAGES,	/* Mapped anonymous pages */
 	NR_FILE_MAPPED,	/* pagecache pages mapped into pagetables.
 			   only modified from process context */
 	NR_FILE_PAGES,
-	NR_SLAB_RECLAIMABLE,
-	NR_SLAB_UNRECLAIMABLE,
-	NR_PAGETABLE,	/* used for pagetables */
 	NR_FILE_DIRTY,
 	NR_WRITEBACK,
+	/* Second 128 byte cacheline */
+	NR_SLAB_RECLAIMABLE,
+	NR_SLAB_UNRECLAIMABLE,
+	NR_PAGETABLE,		/* used for pagetables */
 	NR_UNSTABLE_NFS,	/* NFS unstable pages */
 	NR_BOUNCE,
 	NR_VMSCAN_WRITE,
@@ -91,6 +96,7 @@
 #endif
 
 enum zone_type {
+#ifdef CONFIG_ZONE_DMA
 	/*
 	 * ZONE_DMA is used when there are devices that are not able
 	 * to do DMA to all of addressable memory (ZONE_NORMAL). Then we
@@ -111,6 +117,7 @@
 	 * 			<16M.
 	 */
 	ZONE_DMA,
+#endif
 #ifdef CONFIG_ZONE_DMA32
 	/*
 	 * x86_64 needs two ZONE_DMAs because it supports devices that are
@@ -147,15 +154,30 @@
  * match the requested limits. See gfp_zone() in include/linux/gfp.h
  */
 
-#if !defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_HIGHMEM)
+/*
+ * Count the active zones.  Note that the use of defined(X) outside
+ * #if and family is not necessarily defined so ensure we cannot use
+ * it later.  Use __ZONE_COUNT to work out how many shift bits we need.
+ */
+#define __ZONE_COUNT (			\
+	  defined(CONFIG_ZONE_DMA)	\
+	+ defined(CONFIG_ZONE_DMA32)	\
+	+ 1				\
+	+ defined(CONFIG_HIGHMEM)	\
+)
+#if __ZONE_COUNT < 2
+#define ZONES_SHIFT 0
+#elif __ZONE_COUNT <= 2
 #define ZONES_SHIFT 1
-#else
+#elif __ZONE_COUNT <= 4
 #define ZONES_SHIFT 2
+#else
+#error ZONES_SHIFT -- too many zones configured adjust calculation
 #endif
+#undef __ZONE_COUNT
 
 struct zone {
 	/* Fields commonly accessed by the page allocator */
-	unsigned long		free_pages;
 	unsigned long		pages_min, pages_low, pages_high;
 	/*
 	 * We don't know if the memory that we're going to allocate will be freeable
@@ -197,8 +219,6 @@
 	struct list_head	inactive_list;
 	unsigned long		nr_scan_active;
 	unsigned long		nr_scan_inactive;
-	unsigned long		nr_active;
-	unsigned long		nr_inactive;
 	unsigned long		pages_scanned;	   /* since last reclaim */
 	int			all_unreclaimable; /* All pages pinned */
 
@@ -442,8 +462,6 @@
 
 #include <linux/memory_hotplug.h>
 
-void __get_zone_counts(unsigned long *active, unsigned long *inactive,
-			unsigned long *free, struct pglist_data *pgdat);
 void get_zone_counts(unsigned long *active, unsigned long *inactive,
 			unsigned long *free);
 void build_all_zonelists(void);
@@ -523,7 +541,11 @@
 
 static inline int is_dma(struct zone *zone)
 {
+#ifdef CONFIG_ZONE_DMA
 	return zone == zone->zone_pgdat->node_zones + ZONE_DMA;
+#else
+	return 0;
+#endif
 }
 
 /* These two functions are used to setup the per zone pages min values */
diff --git a/include/linux/module.h b/include/linux/module.h
index 419d3ef..95679eb 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -76,8 +76,6 @@
 		  struct exception_table_entry *finish);
 void sort_main_extable(void);
 
-extern struct subsystem module_subsys;
-
 #ifdef MODULE
 #define MODULE_GENERIC_TABLE(gtype,name)			\
 extern const struct gtype##_id __mod_##gtype##_table		\
@@ -467,10 +465,6 @@
 
 extern void print_modules(void);
 
-struct device_driver;
-void module_add_driver(struct module *, struct device_driver *);
-void module_remove_driver(struct device_driver *);
-
 #else /* !CONFIG_MODULES... */
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
@@ -568,18 +562,59 @@
 {
 }
 
+#endif /* CONFIG_MODULES */
+
 struct device_driver;
+#ifdef CONFIG_SYSFS
 struct module;
 
-static inline void module_add_driver(struct module *module, struct device_driver *driver)
+extern struct subsystem module_subsys;
+
+int mod_sysfs_init(struct module *mod);
+int mod_sysfs_setup(struct module *mod,
+			   struct kernel_param *kparam,
+			   unsigned int num_params);
+int module_add_modinfo_attrs(struct module *mod);
+void module_remove_modinfo_attrs(struct module *mod);
+
+#else /* !CONFIG_SYSFS */
+
+static inline int mod_sysfs_init(struct module *mod)
 {
+	return 0;
 }
 
-static inline void module_remove_driver(struct device_driver *driver)
+static inline int mod_sysfs_setup(struct module *mod,
+			   struct kernel_param *kparam,
+			   unsigned int num_params)
 {
+	return 0;
 }
 
-#endif /* CONFIG_MODULES */
+static inline int module_add_modinfo_attrs(struct module *mod)
+{
+	return 0;
+}
+
+static inline void module_remove_modinfo_attrs(struct module *mod)
+{ }
+
+#endif /* CONFIG_SYSFS */
+
+#if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES)
+
+void module_add_driver(struct module *mod, struct device_driver *drv);
+void module_remove_driver(struct device_driver *drv);
+
+#else /* not both CONFIG_SYSFS && CONFIG_MODULES */
+
+static inline void module_add_driver(struct module *mod, struct device_driver *drv)
+{ }
+
+static inline void module_remove_driver(struct device_driver *drv)
+{ }
+
+#endif
 
 #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
 
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 4a189da..c83588c 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -59,7 +59,7 @@
 };
 
 /* This is the fundamental function for registering boot/module
-   parameters.  perm sets the visibility in driverfs: 000 means it's
+   parameters.  perm sets the visibility in sysfs: 000 means it's
    not there, read bits mean it's readable, write bits mean it's
    writable. */
 #define __module_param_call(prefix, name, set, get, arg, perm)		\
@@ -169,10 +169,22 @@
 
 struct module;
 
+#if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES)
 extern int module_param_sysfs_setup(struct module *mod,
 				    struct kernel_param *kparam,
 				    unsigned int num_params);
 
 extern void module_param_sysfs_remove(struct module *mod);
+#else
+static inline int module_param_sysfs_setup(struct module *mod,
+			     struct kernel_param *kparam,
+			     unsigned int num_params)
+{
+	return 0;
+}
+
+static inline void module_param_sysfs_remove(struct module *mod)
+{ }
+#endif
 
 #endif /* _LINUX_MODULE_PARAMS_H */
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 1b7e178..dab69af 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -43,9 +43,8 @@
 	struct super_block *mnt_sb;	/* pointer to superblock */
 	struct list_head mnt_mounts;	/* list of children, anchored here */
 	struct list_head mnt_child;	/* and going through their mnt_child */
-	atomic_t mnt_count;
 	int mnt_flags;
-	int mnt_expiry_mark;		/* true if marked for expiry */
+	/* 4 bytes hole on 64bits arches */
 	char *mnt_devname;		/* Name of device e.g. /dev/dsk/hda1 */
 	struct list_head mnt_list;
 	struct list_head mnt_expire;	/* link in fs-specific expiry list */
@@ -54,6 +53,13 @@
 	struct list_head mnt_slave;	/* slave list entry */
 	struct vfsmount *mnt_master;	/* slave is on master->mnt_slave_list */
 	struct mnt_namespace *mnt_ns;	/* containing namespace */
+	/*
+	 * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
+	 * to let these frequently modified fields in a separate cache line
+	 * (so that reads of mnt_flags wont ping-pong on SMP machines)
+	 */
+	atomic_t mnt_count;
+	int mnt_expiry_mark;		/* true if marked for expiry */
 	int mnt_pinned;
 };
 
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 24a9ef1..fa253fa 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -234,7 +234,7 @@
 	struct fat_mount_options options;
 	struct nls_table *nls_disk;  /* Codepage used on disk */
 	struct nls_table *nls_io;    /* Charset used for input and display */
-	void *dir_ops;		     /* Opaque; default directory operations */
+	const void *dir_ops;		     /* Opaque; default directory operations */
 	int dir_per_block;	     /* dir entries per block */
 	int dir_per_block_bits;	     /* log2(dir_per_block) */
 
@@ -399,7 +399,7 @@
 extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
 			     unsigned int cmd, unsigned long arg);
 extern const struct file_operations fat_file_operations;
-extern struct inode_operations fat_file_inode_operations;
+extern const struct inode_operations fat_file_inode_operations;
 extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
 extern void fat_truncate(struct inode *inode);
 extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
@@ -413,7 +413,7 @@
 			struct msdos_dir_entry *de, loff_t i_pos);
 extern int fat_sync_inode(struct inode *inode);
 extern int fat_fill_super(struct super_block *sb, void *data, int silent,
-			struct inode_operations *fs_dir_inode_ops, int isvfat);
+			const struct inode_operations *fs_dir_inode_ops, int isvfat);
 
 extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
 		            struct inode *i2);
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 1221b7c..fff8c53 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -92,6 +92,13 @@
  */
 #define ONENAND_BADBLOCK_POS	0
 
+/*
+ * Bad block scanning errors
+ */
+#define ONENAND_BBT_READ_ERROR		1
+#define ONENAND_BBT_READ_ECC_ERROR	2
+#define ONENAND_BBT_READ_FATAL_ERROR	4
+
 /**
  * struct bbm_info - [GENERIC] Bad Block Table data structure
  * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index 28d461d..81f3a31 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -183,7 +183,7 @@
 struct map_info {
 	char *name;
 	unsigned long size;
-	unsigned long phys;
+	resource_size_t phys;
 #define NO_XIP (-1UL)
 
 	void __iomem *virt;
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index d644e57..6a8570b 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -85,6 +85,10 @@
  *		mode = MTD_OOB_PLACE)
  * @datbuf:	data buffer - if NULL only oob data are read/written
  * @oobbuf:	oob data buffer
+ *
+ * Note, it is allowed to read more then one OOB area at one go, but not write.
+ * The interface assumes that the OOB write requests program only one page's
+ * OOB area.
  */
 struct mtd_oob_ops {
 	mtd_oob_mode_t	mode;
@@ -117,18 +121,6 @@
 	u_int32_t writesize;
 
 	u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
-	u_int32_t ecctype;
-	u_int32_t eccsize;
-
-	/*
-	 * Reuse some of the above unused fields in the case of NOR flash
-	 * with configurable programming regions to avoid modifying the
-	 * user visible structure layout/size.  Only valid when the
-	 * MTD_PROGRAM_REGIONS flag is set.
-	 * (Maybe we should have an union for those?)
-	 */
-#define MTD_PROGREGION_CTRLMODE_VALID(mtd)  (mtd)->oobsize
-#define MTD_PROGREGION_CTRLMODE_INVALID(mtd)  (mtd)->ecctype
 
 	// Kernel-only stuff starts here.
 	char *name;
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 2071b02..9752388 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -343,6 +343,7 @@
  * @options:		[BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
  *			special functionality. See the defines for further explanation
  * @badblockpos:	[INTERN] position of the bad block marker in the oob area
+ * @cellinfo:		[INTERN] MLC/multichip data from chip ident
  * @numchips:		[INTERN] number of physical chips
  * @chipsize:		[INTERN] the size of one chip for multichip arrays
  * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index f775a7a..d8af8a9 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -1,7 +1,7 @@
 /*
  *  linux/include/linux/mtd/onenand.h
  *
- *  Copyright (C) 2005-2006 Samsung Electronics
+ *  Copyright (C) 2005-2007 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -42,14 +42,10 @@
 
 /**
  * struct onenand_bufferram - OneNAND BufferRAM Data
- * @block:		block address in BufferRAM
- * @page:		page address in BufferRAM
- * @valid:		valid flag
+ * @blockpage:		block & page address in BufferRAM
  */
 struct onenand_bufferram {
-	int block;
-	int page;
-	int valid;
+	int	blockpage;
 };
 
 /**
@@ -63,7 +59,6 @@
  *			partly be set to inform onenand_scan about
  * @erase_shift:	[INTERN] number of address bits in a block
  * @page_shift:		[INTERN] number of address bits in a page
- * @ppb_shift:		[INTERN] number of address bits in a pages per block
  * @page_mask:		[INTERN] a page per block mask
  * @bufferram_index:	[INTERN] BufferRAM index
  * @bufferram:		[INTERN] BufferRAM info
@@ -103,7 +98,6 @@
 
 	unsigned int		erase_shift;
 	unsigned int		page_shift;
-	unsigned int		ppb_shift;	/* Pages per block shift */
 	unsigned int		page_mask;
 
 	unsigned int		bufferram_index;
@@ -150,6 +144,9 @@
 #define ONENAND_SET_SYS_CFG1(v, this)					\
 	(this->write_word(v, this->base + ONENAND_REG_SYS_CFG1))
 
+#define ONENAND_IS_DDP(this)						\
+	(this->device_id & ONENAND_DEVICE_IS_DDP)
+
 /* Check byte access in OneNAND */
 #define ONENAND_CHECK_BYTE_ACCESS(addr)		(addr & 0x1)
 
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index e31c8f5..af94719 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -3,7 +3,8 @@
  *
  *  OneNAND Register header file
  *
- *  Copyright (C) 2005-2006 Samsung Electronics
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  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 version 2 as
@@ -80,9 +81,11 @@
 #define ONENAND_VERSION_PROCESS_SHIFT	(8)
 
 /*
- * Start Address 1 F100h (R/W)
+ * Start Address 1 F100h (R/W) & Start Address 2 F101h (R/W)
  */
 #define ONENAND_DDP_SHIFT		(15)
+#define ONENAND_DDP_CHIP0		(0)
+#define ONENAND_DDP_CHIP1		(1 << ONENAND_DDP_SHIFT)
 
 /*
  * Start Address 8 F107h (R/W)
diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
index 86831e3..0dc07d5 100644
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -18,9 +18,10 @@
 #define __LINUX_MTD_PHYSMAP__
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 
+struct map_info;
+
 struct physmap_flash_data {
 	unsigned int		width;
 	void			(*set_vpp)(struct map_info *, int);
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 0ea7f89..83e39eb 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -204,7 +204,7 @@
 void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
 
 /* linux/fs/ncpfs/dir.c */
-extern struct inode_operations ncp_dir_inode_operations;
+extern const struct inode_operations ncp_dir_inode_operations;
 extern const struct file_operations ncp_dir_operations;
 int ncp_conn_logged_in(struct super_block *);
 int ncp_date_dos2unix(__le16 time, __le16 date);
@@ -226,7 +226,7 @@
 void ncp_unlock_server(struct ncp_server *server);
 
 /* linux/fs/ncpfs/file.c */
-extern struct inode_operations ncp_file_inode_operations;
+extern const struct inode_operations ncp_file_inode_operations;
 extern const struct file_operations ncp_file_operations;
 int ncp_make_open(struct inode *, int);
 
diff --git a/include/linux/net.h b/include/linux/net.h
index f28d8a2..4db21e6 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -24,7 +24,7 @@
 struct poll_table_struct;
 struct inode;
 
-#define NPROTO		32		/* should be enough for now..	*/
+#define NPROTO		33		/* should be enough for now..	*/
 
 #define SYS_SOCKET	1		/* sys_socket(2)		*/
 #define SYS_BIND	2		/* sys_bind(2)			*/
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2e37f50..1a52854 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -589,7 +589,7 @@
 extern int		dev_close(struct net_device *dev);
 extern int		dev_queue_xmit(struct sk_buff *skb);
 extern int		register_netdevice(struct net_device *dev);
-extern int		unregister_netdevice(struct net_device *dev);
+extern void		unregister_netdevice(struct net_device *dev);
 extern void		free_netdev(struct net_device *dev);
 extern void		synchronize_net(void);
 extern int 		register_netdevice_notifier(struct notifier_block *nb);
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index d4c4c51..70d3b4f 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -172,8 +172,8 @@
 
 /* Function to register/unregister log function. */
 int nf_log_register(int pf, struct nf_logger *logger);
-int nf_log_unregister_pf(int pf);
-void nf_log_unregister_logger(struct nf_logger *logger);
+void nf_log_unregister(struct nf_logger *logger);
+void nf_log_unregister_pf(int pf);
 
 /* Calls the registered backend logging function */
 void nf_log_packet(int pf,
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index 6328175..43397a4 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -33,6 +33,7 @@
 header-y += xt_tcpudp.h
 header-y += xt_SECMARK.h
 header-y += xt_CONNSECMARK.h
+header-y += xt_TCPMSS.h
 
 unifdef-y += nf_conntrack_common.h
 unifdef-y += nf_conntrack_ftp.h
diff --git a/include/linux/netfilter/nf_conntrack_sane.h b/include/linux/netfilter/nf_conntrack_sane.h
new file mode 100644
index 0000000..4767d6e
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_sane.h
@@ -0,0 +1,21 @@
+#ifndef _NF_CONNTRACK_SANE_H
+#define _NF_CONNTRACK_SANE_H
+/* SANE tracking. */
+
+#ifdef __KERNEL__
+
+#define SANE_PORT	6566
+
+enum sane_state {
+	SANE_STATE_NORMAL,
+	SANE_STATE_START_REQUESTED,
+};
+
+/* This structure exists only once per master */
+struct nf_ct_sane_master {
+	enum sane_state state;
+};
+
+#endif /* __KERNEL__ */
+
+#endif /* _NF_CONNTRACK_SANE_H */
diff --git a/include/linux/netfilter/nf_conntrack_tcp.h b/include/linux/netfilter/nf_conntrack_tcp.h
index 2f4e98b..007af4c 100644
--- a/include/linux/netfilter/nf_conntrack_tcp.h
+++ b/include/linux/netfilter/nf_conntrack_tcp.h
@@ -27,6 +27,9 @@
 /* This sender sent FIN first */
 #define IP_CT_TCP_FLAG_CLOSE_INIT		0x04
 
+/* Be liberal in window checking */
+#define IP_CT_TCP_FLAG_BE_LIBERAL		0x08
+
 #ifdef __KERNEL__
 
 struct ip_ct_tcp_state {
@@ -34,7 +37,6 @@
 	u_int32_t	td_maxend;	/* max of ack + max(win, 1) */
 	u_int32_t	td_maxwin;	/* max(win) */
 	u_int8_t	td_scale;	/* window scale factor */
-	u_int8_t	loose;		/* used when connection picked up from the middle */
 	u_int8_t	flags;		/* per direction options */
 };
 
diff --git a/include/linux/netfilter/xt_TCPMSS.h b/include/linux/netfilter/xt_TCPMSS.h
new file mode 100644
index 0000000..53a292c
--- /dev/null
+++ b/include/linux/netfilter/xt_TCPMSS.h
@@ -0,0 +1,10 @@
+#ifndef _XT_TCPMSS_H
+#define _XT_TCPMSS_H
+
+struct xt_tcpmss_info {
+	u_int16_t mss;
+};
+
+#define XT_TCPMSS_CLAMP_PMTU 0xffff
+
+#endif /* _XT_TCPMSS_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 33581c1..da9274e 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -301,6 +301,12 @@
 extern int ip_conntrack_checksum;
  
 #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
+#define CONNTRACK_STAT_INC_ATOMIC(count)		\
+do {							\
+	local_bh_disable();				\
+	__get_cpu_var(ip_conntrack_stat).count++;	\
+	local_bh_enable();				\
+} while (0)
 
 #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
 #include <linux/notifier.h>
diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h
index bdf5536..bbca89a 100644
--- a/include/linux/netfilter_ipv4/ip_nat.h
+++ b/include/linux/netfilter_ipv4/ip_nat.h
@@ -16,6 +16,7 @@
 
 #define IP_NAT_RANGE_MAP_IPS 1
 #define IP_NAT_RANGE_PROTO_SPECIFIED 2
+#define IP_NAT_RANGE_PROTO_RANDOM 4 /* add randomness to "port" selection */
 
 /* NAT sequence number modifications */
 struct ip_nat_seq {
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 98d566c..9527296 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -272,25 +272,9 @@
 #include <linux/init.h>
 extern void ipt_init(void) __init;
 
-#define ipt_register_target(tgt) 	\
-({	(tgt)->family = AF_INET;	\
- 	xt_register_target(tgt); })
-#define ipt_unregister_target(tgt) xt_unregister_target(tgt)
-
-#define ipt_register_match(mtch) 	\
-({	(mtch)->family = AF_INET;	\
-	xt_register_match(mtch); })
-#define ipt_unregister_match(mtch) xt_unregister_match(mtch)
-
-//#define ipt_register_table(tbl, repl) xt_register_table(AF_INET, tbl, repl)
-//#define ipt_unregister_table(tbl) xt_unregister_table(AF_INET, tbl)
-
-extern int ipt_register_table(struct ipt_table *table,
+extern int ipt_register_table(struct xt_table *table,
 			      const struct ipt_replace *repl);
-extern void ipt_unregister_table(struct ipt_table *table);
-
-/* net/sched/ipt.c: Gimme access to your targets!  Gets target->me. */
-extern struct ipt_target *ipt_find_target(const char *name, u8 revision);
+extern void ipt_unregister_table(struct xt_table *table);
 
 /* Standard entry. */
 struct ipt_standard
@@ -315,7 +299,7 @@
 				 unsigned int hook,
 				 const struct net_device *in,
 				 const struct net_device *out,
-				 struct ipt_table *table);
+				 struct xt_table *table);
 
 #define IPT_ALIGN(s) XT_ALIGN(s)
 
diff --git a/include/linux/netfilter_ipv4/ipt_TCPMSS.h b/include/linux/netfilter_ipv4/ipt_TCPMSS.h
index aadb395..7a850f9 100644
--- a/include/linux/netfilter_ipv4/ipt_TCPMSS.h
+++ b/include/linux/netfilter_ipv4/ipt_TCPMSS.h
@@ -1,10 +1,9 @@
 #ifndef _IPT_TCPMSS_H
 #define _IPT_TCPMSS_H
 
-struct ipt_tcpmss_info {
-	u_int16_t mss;
-};
+#include <linux/netfilter/xt_TCPMSS.h>
 
-#define IPT_TCPMSS_CLAMP_PMTU 0xffff
+#define ipt_tcpmss_info		xt_tcpmss_info
+#define IPT_TCPMSS_CLAMP_PMTU	XT_TCPMSS_CLAMP_PMTU
 
 #endif /*_IPT_TCPMSS_H*/
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 4aed340..61aa104 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -104,6 +104,25 @@
 	unsigned char elems[0];
 };
 
+/* Standard entry */
+struct ip6t_standard
+{
+	struct ip6t_entry entry;
+	struct ip6t_standard_target target;
+};
+
+struct ip6t_error_target
+{
+	struct ip6t_entry_target target;
+	char errorname[IP6T_FUNCTION_MAXNAMELEN];
+};
+
+struct ip6t_error
+{
+	struct ip6t_entry entry;
+	struct ip6t_error_target target;
+};
+
 /*
  * New IP firewall options for [gs]etsockopt at the RAW IP level.
  * Unlike BSD Linux inherits IP options so you don't have to use
@@ -286,24 +305,14 @@
 #include <linux/init.h>
 extern void ip6t_init(void) __init;
 
-#define ip6t_register_target(tgt) 		\
-({	(tgt)->family = AF_INET6;		\
- 	xt_register_target(tgt); })
-#define ip6t_unregister_target(tgt) xt_unregister_target(tgt)
-
-#define ip6t_register_match(match)		\
-({	(match)->family = AF_INET6;		\
-	xt_register_match(match); })
-#define ip6t_unregister_match(match) xt_unregister_match(match)
-
-extern int ip6t_register_table(struct ip6t_table *table,
+extern int ip6t_register_table(struct xt_table *table,
 			       const struct ip6t_replace *repl);
-extern void ip6t_unregister_table(struct ip6t_table *table);
+extern void ip6t_unregister_table(struct xt_table *table);
 extern unsigned int ip6t_do_table(struct sk_buff **pskb,
 				  unsigned int hook,
 				  const struct net_device *in,
 				  const struct net_device *out,
-				  struct ip6t_table *table);
+				  struct xt_table *table);
 
 /* Check for an extension */
 extern int ip6t_ext_hdr(u8 nexthdr);
diff --git a/include/linux/netfilter_ipv6/ip6t_mh.h b/include/linux/netfilter_ipv6/ip6t_mh.h
new file mode 100644
index 0000000..b9ca9a5
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_mh.h
@@ -0,0 +1,15 @@
+#ifndef _IP6T_MH_H
+#define _IP6T_MH_H
+
+/* MH matching stuff */
+struct ip6t_mh
+{
+	u_int8_t types[2];	/* MH type range */
+	u_int8_t invflags;	/* Inverse flags */
+};
+
+/* Values for "invflags" field in struct ip6t_mh. */
+#define IP6T_MH_INV_TYPE	0x01	/* Invert the sense of type. */
+#define IP6T_MH_INV_MASK	0x01	/* All possible flags. */
+
+#endif /*_IP6T_MH_H*/
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index b3b9b60..2a20f48 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -23,6 +23,7 @@
 #define NETLINK_GENERIC		16
 /* leave room for NETLINK_DM (DM Events) */
 #define NETLINK_SCSITRANSPORT	18	/* SCSI Transports */
+#define NETLINK_ECRYPTFS	19
 
 #define MAX_LINKS 32		
 
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index db05182..1be5be8 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -105,12 +105,11 @@
 	uint32_t	access_mask;
 	int		whotype;
 	uid_t		who;
-	struct list_head l_ace;
 };
 
 struct nfs4_acl {
 	uint32_t	naces;
-	struct list_head ace_head;
+	struct nfs4_ace	aces[0];
 };
 
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
diff --git a/include/linux/nfs4_acl.h b/include/linux/nfs4_acl.h
index 22aff4d..409b6e0 100644
--- a/include/linux/nfs4_acl.h
+++ b/include/linux/nfs4_acl.h
@@ -39,9 +39,12 @@
 
 #include <linux/posix_acl.h>
 
-struct nfs4_acl *nfs4_acl_new(void);
-void nfs4_acl_free(struct nfs4_acl *);
-int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+/* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to
+ * fit in a page: */
+#define NFS4_ACL_MAX 170
+
+struct nfs4_acl *nfs4_acl_new(int);
+void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
 int nfs4_acl_get_whotype(char *, u32);
 int nfs4_acl_write_who(int who, char *p);
 int nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index c5d4084..47aaa2c 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -11,14 +11,6 @@
 
 #include <linux/magic.h>
 
-/*
- * Enable debugging support for nfs client.
- * Requires RPC_DEBUG.
- */
-#ifdef RPC_DEBUG
-# define NFS_DEBUG
-#endif
-
 /* Default timeout values */
 #define NFS_MAX_UDP_TIMEOUT	(60*HZ)
 #define NFS_MAX_TCP_TIMEOUT	(600*HZ)
@@ -331,9 +323,9 @@
 /*
  * linux/fs/nfs/file.c
  */
-extern struct inode_operations nfs_file_inode_operations;
+extern const struct inode_operations nfs_file_inode_operations;
 #ifdef CONFIG_NFS_V3
-extern struct inode_operations nfs3_file_inode_operations;
+extern const struct inode_operations nfs3_file_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_file_operations;
 extern const struct address_space_operations nfs_file_aops;
@@ -380,9 +372,9 @@
 /*
  * linux/fs/nfs/dir.c
  */
-extern struct inode_operations nfs_dir_inode_operations;
+extern const struct inode_operations nfs_dir_inode_operations;
 #ifdef CONFIG_NFS_V3
-extern struct inode_operations nfs3_dir_inode_operations;
+extern const struct inode_operations nfs3_dir_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_dir_operations;
 extern struct dentry_operations nfs_dentry_operations;
@@ -392,7 +384,7 @@
 /*
  * linux/fs/nfs/symlink.c
  */
-extern struct inode_operations nfs_symlink_inode_operations;
+extern const struct inode_operations nfs_symlink_inode_operations;
 
 /*
  * linux/fs/nfs/sysctl.c
@@ -409,8 +401,8 @@
  * linux/fs/nfs/namespace.c
  */
 extern struct list_head nfs_automount_list;
-extern struct inode_operations nfs_mountpoint_inode_operations;
-extern struct inode_operations nfs_referral_inode_operations;
+extern const struct inode_operations nfs_mountpoint_inode_operations;
+extern const struct inode_operations nfs_referral_inode_operations;
 extern int nfs_mountpoint_expiry_timeout;
 extern void nfs_release_automount_timer(void);
 
@@ -567,6 +559,15 @@
 #define NFSDBG_ALL		0xFFFF
 
 #ifdef __KERNEL__
+
+/*
+ * Enable debugging support for nfs client.
+ * Requires RPC_DEBUG.
+ */
+#ifdef RPC_DEBUG
+# define NFS_DEBUG
+#endif
+
 # undef ifdebug
 # ifdef NFS_DEBUG
 #  define ifdebug(fac)		if (unlikely(nfs_debug & NFSDBG_##fac))
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9ee9da5..10c26ed 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -767,8 +767,8 @@
 struct nfs_rpc_ops {
 	int	version;		/* Protocol version */
 	struct dentry_operations *dentry_ops;
-	struct inode_operations *dir_inode_ops;
-	struct inode_operations *file_inode_ops;
+	const struct inode_operations *dir_inode_ops;
+	const struct inode_operations *file_inode_ops;
 
 	int	(*getroot) (struct nfs_server *, struct nfs_fh *,
 			    struct nfs_fsinfo *);
@@ -784,7 +784,6 @@
 	int	(*access)  (struct inode *, struct nfs_access_entry *);
 	int	(*readlink)(struct inode *, struct page *, unsigned int,
 			    unsigned int);
-	int	(*read)    (struct nfs_read_data *);
 	int	(*create)  (struct inode *, struct dentry *,
 			    struct iattr *, int, struct nameidata *);
 	int	(*remove)  (struct inode *, struct qstr *);
diff --git a/include/linux/nfsd/const.h b/include/linux/nfsd/const.h
index f0cc777..323f8cf 100644
--- a/include/linux/nfsd/const.h
+++ b/include/linux/nfsd/const.h
@@ -30,10 +30,6 @@
 
 #include <linux/sunrpc/msg_prot.h>
 
-#ifndef NFS_SUPER_MAGIC
-# define NFS_SUPER_MAGIC	0x6969
-#endif
-
 /*
  * Largest number of bytes we need to allocate for an NFS
  * call or reply.  Used to control buffer sizes.  We use
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 045e38c..9f62d61 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -74,19 +74,20 @@
 	uid_t			ex_anon_uid;
 	gid_t			ex_anon_gid;
 	int			ex_fsid;
+	unsigned char *		ex_uuid; /* 16 byte fsid */
 	struct nfsd4_fs_locations ex_fslocs;
 };
 
 /* an "export key" (expkey) maps a filehandlefragement to an
- * svc_export for a given client.  There can be two per export, one
- * for type 0 (dev/ino), one for type 1 (fsid)
+ * svc_export for a given client.  There can be several per export,
+ * for the different fsid types.
  */
 struct svc_expkey {
 	struct cache_head	h;
 
 	struct auth_domain *	ek_client;
 	int			ek_fsidtype;
-	u32			ek_fsid[3];
+	u32			ek_fsid[6];
 
 	struct vfsmount *	ek_mnt;
 	struct dentry *		ek_dentry;
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 4b7c4b5..72feac5 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -254,18 +254,6 @@
  */
 extern struct timeval	nfssvc_boot;
 
-static inline int is_fsid(struct svc_fh *fh, struct knfsd_fh *reffh)
-{
-	if (fh->fh_export->ex_flags & NFSEXP_FSID) {
-		struct vfsmount *mnt = fh->fh_export->ex_mnt;
-		if (!old_valid_dev(mnt->mnt_sb->s_dev) ||
-		    (reffh->fh_version == 1 && reffh->fh_fsid_type == 1))
-			return 1;
-	}
-	return 0;
-}
-
-
 #ifdef CONFIG_NFSD_V4
 
 /* before processing a COMPOUND operation, we have to check that there
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index d9c6c38..11e568e 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -165,38 +165,91 @@
 
 } svc_fh;
 
-static inline void mk_fsid_v0(u32 *fsidv, dev_t dev, ino_t ino)
-{
-	fsidv[0] = htonl((MAJOR(dev)<<16) |
-			MINOR(dev));
-	fsidv[1] = ino_t_to_u32(ino);
-}
+enum nfsd_fsid {
+	FSID_DEV = 0,
+	FSID_NUM,
+	FSID_MAJOR_MINOR,
+	FSID_ENCODE_DEV,
+	FSID_UUID4_INUM,
+	FSID_UUID8,
+	FSID_UUID16,
+	FSID_UUID16_INUM,
+};
 
-static inline void mk_fsid_v1(u32 *fsidv, u32 fsid)
-{
-	fsidv[0] = fsid;
-}
+enum fsid_source {
+	FSIDSOURCE_DEV,
+	FSIDSOURCE_FSID,
+	FSIDSOURCE_UUID,
+};
+extern enum fsid_source fsid_source(struct svc_fh *fhp);
 
-static inline void mk_fsid_v2(u32 *fsidv, dev_t dev, ino_t ino)
-{
-	fsidv[0] = htonl(MAJOR(dev));
-	fsidv[1] = htonl(MINOR(dev));
-	fsidv[2] = ino_t_to_u32(ino);
-}
 
-static inline void mk_fsid_v3(u32 *fsidv, dev_t dev, ino_t ino)
+/* This might look a little large to "inline" but in all calls except
+ * one, 'vers' is constant so moste of the function disappears.
+ */
+static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
+			   u32 fsid, unsigned char *uuid)
 {
-	fsidv[0] = new_encode_dev(dev);
-	fsidv[1] = ino_t_to_u32(ino);
+	u32 *up;
+	switch(vers) {
+	case FSID_DEV:
+		fsidv[0] = htonl((MAJOR(dev)<<16) |
+				 MINOR(dev));
+		fsidv[1] = ino_t_to_u32(ino);
+		break;
+	case FSID_NUM:
+		fsidv[0] = fsid;
+		break;
+	case FSID_MAJOR_MINOR:
+		fsidv[0] = htonl(MAJOR(dev));
+		fsidv[1] = htonl(MINOR(dev));
+		fsidv[2] = ino_t_to_u32(ino);
+		break;
+
+	case FSID_ENCODE_DEV:
+		fsidv[0] = new_encode_dev(dev);
+		fsidv[1] = ino_t_to_u32(ino);
+		break;
+
+	case FSID_UUID4_INUM:
+		/* 4 byte fsid and inode number */
+		up = (u32*)uuid;
+		fsidv[0] = ino_t_to_u32(ino);
+		fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
+		break;
+
+	case FSID_UUID8:
+		/* 8 byte fsid  */
+		up = (u32*)uuid;
+		fsidv[0] = up[0] ^ up[2];
+		fsidv[1] = up[1] ^ up[3];
+		break;
+
+	case FSID_UUID16:
+		/* 16 byte fsid - NFSv3+ only */
+		memcpy(fsidv, uuid, 16);
+		break;
+
+	case FSID_UUID16_INUM:
+		/* 8 byte inode and 16 byte fsid */
+		*(u64*)fsidv = (u64)ino;
+		memcpy(fsidv+2, uuid, 16);
+		break;
+	default: BUG();
+	}
 }
 
 static inline int key_len(int type)
 {
 	switch(type) {
-	case 0: return 8;
-	case 1: return 4;
-	case 2: return 12;
-	case 3: return 8;
+	case FSID_DEV:		return 8;
+	case FSID_NUM: 		return 4;
+	case FSID_MAJOR_MINOR:	return 12;
+	case FSID_ENCODE_DEV:	return 8;
+	case FSID_UUID4_INUM:	return 8;
+	case FSID_UUID8:	return 8;
+	case FSID_UUID16:	return 16;
+	case FSID_UUID16_INUM:	return 24;
 	default: return 0;
 	}
 }
diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index acb4ed1..29af2d5 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -17,8 +17,15 @@
 #ifdef ARCH_HAS_NMI_WATCHDOG
 #include <asm/nmi.h>
 extern void touch_nmi_watchdog(void);
+extern void acpi_nmi_disable(void);
+extern void acpi_nmi_enable(void);
 #else
-# define touch_nmi_watchdog() touch_softlockup_watchdog()
+static inline void touch_nmi_watchdog(void)
+{
+	touch_softlockup_watchdog();
+}
+static inline void acpi_nmi_disable(void) { }
+static inline void acpi_nmi_enable(void) { }
 #endif
 
 #ifndef trigger_all_cpu_backtrace
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index b1063e9..52c54a5 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -352,7 +352,7 @@
 #define node_possible(node)	node_isset((node), node_possible_map)
 #define first_online_node	first_node(node_online_map)
 #define next_online_node(nid)	next_node((nid), node_online_map)
-int highest_possible_node_id(void);
+extern int nr_node_ids;
 #else
 #define num_online_nodes()	1
 #define num_possible_nodes()	1
@@ -360,7 +360,7 @@
 #define node_possible(node)	((node) == 0)
 #define first_online_node	0
 #define next_online_node(nid)	(MAX_NUMNODES)
-#define highest_possible_node_id()	0
+#define nr_node_ids		1
 #endif
 
 #define any_online_node(mask)			\
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index c3e255b..7a8dcb8 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -76,8 +76,6 @@
 				unsigned long index);
 extern struct page * find_lock_page(struct address_space *mapping,
 				unsigned long index);
-extern __deprecated_for_modules struct page * find_trylock_page(
-			struct address_space *mapping, unsigned long index);
 extern struct page * find_or_create_page(struct address_space *mapping,
 				unsigned long index, gfp_t gfp_mask);
 unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 805412c..2c4b684 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -167,6 +167,7 @@
 	unsigned int	broken_parity_status:1;	/* Device generates false positive parity */
 	unsigned int 	msi_enabled:1;
 	unsigned int	msix_enabled:1;
+	unsigned int	is_managed:1;
 	atomic_t	enable_cnt;	/* pci_enable_device has been called */
 
 	u32		saved_config_space[16]; /* config space saved at suspend time */
@@ -528,6 +529,14 @@
 
 int __must_check pci_enable_device(struct pci_dev *dev);
 int __must_check pci_enable_device_bars(struct pci_dev *dev, int mask);
+int __must_check pcim_enable_device(struct pci_dev *pdev);
+void pcim_pin_device(struct pci_dev *pdev);
+
+static inline int pci_is_managed(struct pci_dev *pdev)
+{
+	return pdev->is_managed;
+}
+
 void pci_disable_device(struct pci_dev *dev);
 void pci_set_master(struct pci_dev *dev);
 #define HAVE_PCI_SET_MWI
@@ -831,6 +840,11 @@
 
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
 
+void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
+void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
+void __iomem * const * pcim_iomap_table(struct pci_dev *pdev);
+int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name);
+
 extern int pci_pci_problems;
 #define PCIPCI_FAIL		1	/* No PCI PCI DMA */
 #define PCIPCI_TRITON		2
@@ -840,5 +854,8 @@
 #define PCIPCI_ALIMAGIK		32	/* Need low latency setting */
 #define PCIAGP_FAIL		64	/* No PCI to AGP DMA */
 
+extern unsigned long pci_cardbus_io_size;
+extern unsigned long pci_cardbus_mem_size;
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index defdeed..600308f 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -15,6 +15,8 @@
 #define PCI_CLASS_STORAGE_FLOPPY	0x0102
 #define PCI_CLASS_STORAGE_IPI		0x0103
 #define PCI_CLASS_STORAGE_RAID		0x0104
+#define PCI_CLASS_STORAGE_SATA		0x0106
+#define PCI_CLASS_STORAGE_SATA_AHCI	0x010601
 #define PCI_CLASS_STORAGE_SAS		0x0107
 #define PCI_CLASS_STORAGE_OTHER		0x0180
 
@@ -95,6 +97,7 @@
 
 #define PCI_BASE_CLASS_SERIAL		0x0c
 #define PCI_CLASS_SERIAL_FIREWIRE	0x0c00
+#define PCI_CLASS_SERIAL_FIREWIRE_OHCI	0x0c0010
 #define PCI_CLASS_SERIAL_ACCESS		0x0c01
 #define PCI_CLASS_SERIAL_SSA		0x0c02
 #define PCI_CLASS_SERIAL_USB		0x0c03
@@ -366,6 +369,7 @@
 #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_SMBUS	0x4385
 #define PCI_DEVICE_ID_ATI_IXP600_IDE	0x438c
 
 #define PCI_VENDOR_ID_VLSI		0x1004
@@ -956,6 +960,7 @@
 #define PCI_DEVICE_ID_PLX_R753		0x1152
 #define PCI_DEVICE_ID_PLX_OLITEC	0x1187
 #define PCI_DEVICE_ID_PLX_PCI200SYN	0x3196
+#define PCI_DEVICE_ID_PLX_9030          0x9030
 #define PCI_DEVICE_ID_PLX_9050		0x9050
 #define PCI_DEVICE_ID_PLX_9080		0x9080
 #define PCI_DEVICE_ID_PLX_GTEK_SERIAL2	0xa001
@@ -1632,6 +1637,7 @@
 #define PCI_VENDOR_ID_ITE		0x1283
 #define PCI_DEVICE_ID_ITE_8211		0x8211
 #define PCI_DEVICE_ID_ITE_8212		0x8212
+#define PCI_DEVICE_ID_ITE_8213		0x8213
 #define PCI_DEVICE_ID_ITE_8872		0x8872
 #define PCI_DEVICE_ID_ITE_IT8330G_0	0xe886
 
@@ -1692,6 +1698,8 @@
 #define PCI_VENDOR_ID_ELECTRONICDESIGNGMBH 0x12f8
 #define PCI_DEVICE_ID_LML_33R10		0x8a02
 
+#define PCI_VENDOR_ID_ESDGMBH		0x12fe
+#define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111
 
 #define PCI_VENDOR_ID_SIIG		0x131f
 #define PCI_SUBVENDOR_ID_SIIG		0x131f
@@ -1807,6 +1815,9 @@
 #define PCI_DEVICE_ID_MOXA_C168		0x1680
 #define PCI_DEVICE_ID_MOXA_CP168U	0x1681
 #define PCI_DEVICE_ID_MOXA_CP168EL	0x1682
+#define PCI_DEVICE_ID_MOXA_CP204J	0x2040
+#define PCI_DEVICE_ID_MOXA_C218		0x2180
+#define PCI_DEVICE_ID_MOXA_C320		0x3200
 
 #define PCI_VENDOR_ID_CCD		0x1397
 #define PCI_DEVICE_ID_CCD_2BD0		0x2bd0
@@ -1987,6 +1998,10 @@
 
 #define PCI_VENDOR_ID_CHELSIO		0x1425
 
+#define PCI_SUBVENDOR_ID_PERLE          0x155f
+#define PCI_SUBDEVICE_ID_PCI_RAS4       0xf001
+#define PCI_SUBDEVICE_ID_PCI_RAS8       0xf010
+
 
 #define PCI_VENDOR_ID_SYBA		0x1592
 #define PCI_DEVICE_ID_SYBA_2P_EPP	0x0782
@@ -2073,6 +2088,9 @@
 
 #define PCI_VENDOR_ID_PASEMI		0x1959
 
+#define PCI_VENDOR_ID_ATTANSIC		0x1969
+#define PCI_DEVICE_ID_ATTANSIC_L1	0x1048
+
 #define PCI_VENDOR_ID_JMICRON		0x197B
 #define PCI_DEVICE_ID_JMICRON_JMB360	0x2360
 #define PCI_DEVICE_ID_JMICRON_JMB361	0x2361
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
index 265bafa..d9db5f6 100644
--- a/include/linux/pfkeyv2.h
+++ b/include/linux/pfkeyv2.h
@@ -251,7 +251,8 @@
 #define SADB_X_SPDEXPIRE	21
 #define SADB_X_SPDDELETE2	22
 #define SADB_X_NAT_T_NEW_MAPPING	23
-#define SADB_MAX		23
+#define SADB_X_MIGRATE		24
+#define SADB_MAX		24
 
 /* Security Association flags */
 #define SADB_SAFLAGS_PFS	1
@@ -297,6 +298,7 @@
 #define SADB_X_EALG_BLOWFISHCBC		7
 #define SADB_EALG_NULL			11
 #define SADB_X_EALG_AESCBC		12
+#define SADB_X_EALG_CAMELLIACBC		22
 #define SADB_EALG_MAX                   253 /* last EALG */
 /* private allocations should use 249-255 (RFC2407) */
 #define SADB_X_EALG_SERPENTCBC  252     /* draft-ietf-ipsec-ciph-aes-cbc-00 */
diff --git a/include/linux/phonedev.h b/include/linux/phonedev.h
index a0e31ad..4269de9 100644
--- a/include/linux/phonedev.h
+++ b/include/linux/phonedev.h
@@ -9,7 +9,7 @@
 
 struct phone_device {
 	struct phone_device *next;
-	struct file_operations *f_op;
+	const struct file_operations *f_op;
 	int (*open) (struct phone_device *, struct file *);
 	int board;		/* Device private index */
 	int minor;
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 4dec047..2ac27f9 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -105,20 +105,6 @@
 	return nr;
 }
 
-
-#define do_each_task_pid(who, type, task)				\
-	do {								\
-		struct hlist_node *pos___;				\
-		struct pid *pid___ = find_pid(who);			\
-		if (pid___ != NULL)					\
-			hlist_for_each_entry_rcu((task), pos___,	\
-				&pid___->tasks[type], pids[type].node) {
-
-#define while_each_task_pid(who, type, task)				\
-			}						\
-	} while (0)
-
-
 #define do_each_pid_task(pid, type, task)				\
 	do {								\
 		struct hlist_node *pos___;				\
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 070394e..21db05a 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -120,15 +120,48 @@
 #define	PM_DISK_TESTPROC	((__force suspend_disk_method_t) 6)
 #define	PM_DISK_MAX		((__force suspend_disk_method_t) 7)
 
+/**
+ * struct pm_ops - Callbacks for managing platform dependent suspend states.
+ * @valid: Callback to determine whether the given state can be entered.
+ * 	If %CONFIG_SOFTWARE_SUSPEND is set then %PM_SUSPEND_DISK is
+ *	always valid and never passed to this call.
+ *	If not assigned, all suspend states are advertised as valid
+ *	in /sys/power/state (but can still be rejected by prepare or enter.)
+ *
+ * @prepare: Prepare the platform for the given suspend state. Can return a
+ *	negative error code if necessary.
+ *
+ * @enter: Enter the given suspend state, must be assigned. Can return a
+ *	negative error code if necessary.
+ *
+ * @finish: Called when the system has left the given state and all devices
+ *	are resumed. The return value is ignored.
+ *
+ * @pm_disk_mode: Set to the disk method that the user should be able to
+ *	configure for suspend-to-disk. Since %PM_DISK_SHUTDOWN,
+ *	%PM_DISK_REBOOT, %PM_DISK_TEST and %PM_DISK_TESTPROC
+ *	are always allowed, currently only %PM_DISK_PLATFORM
+ *	makes sense. If the user then choses %PM_DISK_PLATFORM,
+ *	the @prepare call will be called before suspending to disk
+ *	(if present), the @enter call should be present and will
+ *	be called after all state has been saved and the machine
+ *	is ready to be shut down/suspended/..., and the @finish
+ *	callback is called after state has been restored. All
+ *	these calls are called with %PM_SUSPEND_DISK as the state.
+ */
 struct pm_ops {
-	suspend_disk_method_t pm_disk_mode;
 	int (*valid)(suspend_state_t state);
 	int (*prepare)(suspend_state_t state);
 	int (*enter)(suspend_state_t state);
 	int (*finish)(suspend_state_t state);
+	suspend_disk_method_t pm_disk_mode;
 };
 
-extern void pm_set_ops(struct pm_ops *);
+/**
+ * pm_set_ops - set platform dependent power management ops
+ * @pm_ops: The new power management operations to set.
+ */
+extern void pm_set_ops(struct pm_ops *pm_ops);
 extern struct pm_ops *pm_ops;
 extern int pm_suspend(suspend_state_t state);
 
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index ab8a8dd..9a5226f 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -352,6 +352,8 @@
 	(dev) = protocol_to_pnp_dev((dev)->protocol_list.next))
 
 
+extern struct bus_type pnp_bus_type;
+
 #if defined(CONFIG_PNP)
 
 /* device management */
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 87dec8f..be4652a 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -55,8 +55,8 @@
 	uid_t uid;
 	gid_t gid;
 	loff_t size;
-	struct inode_operations * proc_iops;
-	const struct file_operations * proc_fops;
+	const struct inode_operations *proc_iops;
+	const struct file_operations *proc_fops;
 	get_info_t *get_info;
 	struct module *owner;
 	struct proc_dir_entry *next, *parent, *subdir;
@@ -113,8 +113,6 @@
 extern int proc_fill_super(struct super_block *,void *,int);
 extern struct inode *proc_get_inode(struct super_block *, unsigned int, struct proc_dir_entry *);
 
-extern int proc_match(int, const char *,struct proc_dir_entry *);
-
 /*
  * These are generic /proc routines that use the internal
  * "struct proc_dir_entry" tree to traverse the filesystem.
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h
index 0c7ac44..19bc9b8 100644
--- a/include/linux/qnx4_fs.h
+++ b/include/linux/qnx4_fs.h
@@ -116,8 +116,8 @@
 
 extern struct buffer_head *qnx4_bread(struct inode *, int, int);
 
-extern struct inode_operations qnx4_file_inode_operations;
-extern struct inode_operations qnx4_dir_inode_operations;
+extern const struct inode_operations qnx4_file_inode_operations;
+extern const struct inode_operations qnx4_dir_inode_operations;
 extern const struct file_operations qnx4_file_operations;
 extern const struct file_operations qnx4_dir_operations;
 extern int qnx4_is_free(struct super_block *sb, long block);
diff --git a/include/linux/quota.h b/include/linux/quota.h
index b8fbf26..77db80a 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -132,6 +132,7 @@
 
 #ifdef __KERNEL__
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 #include <linux/mutex.h>
 
 #include <linux/dqblk_xfs.h>
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index ebd42a3..6db9a4c 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -247,6 +247,7 @@
 
 	atomic_t pending_writes; /* pending writes to the bitmap file */
 	wait_queue_head_t write_wait;
+	wait_queue_head_t overflow_wait;
 
 };
 
diff --git a/include/linux/random.h b/include/linux/random.h
index 01ad710..36f125c 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -63,7 +63,7 @@
 				       __be16 sport, __be16 dport);
 
 #ifndef MODULE
-extern struct file_operations random_fops, urandom_fops;
+extern const struct file_operations random_fops, urandom_fops;
 #endif
 
 unsigned int get_random_int(void);
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index c3fc6ca..965d5b3 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1949,9 +1949,9 @@
 #endif
 
 /* dir.c */
-extern struct inode_operations reiserfs_dir_inode_operations;
-extern struct inode_operations reiserfs_symlink_inode_operations;
-extern struct inode_operations reiserfs_special_inode_operations;
+extern const struct inode_operations reiserfs_dir_inode_operations;
+extern const struct inode_operations reiserfs_symlink_inode_operations;
+extern const struct inode_operations reiserfs_special_inode_operations;
 extern const struct file_operations reiserfs_dir_operations;
 
 /* tail_conversion.c */
@@ -1963,7 +1963,7 @@
 void reiserfs_unmap_buffer(struct buffer_head *);
 
 /* file.c */
-extern struct inode_operations reiserfs_file_inode_operations;
+extern const struct inode_operations reiserfs_file_inode_operations;
 extern const struct file_operations reiserfs_file_operations;
 extern const struct address_space_operations reiserfs_address_space_operations;
 
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index 966c358..66a9681 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -2,7 +2,10 @@
   File: linux/reiserfs_xattr.h
 */
 
-#include <linux/xattr.h>
+#ifndef _LINUX_REISERFS_XATTR_H
+#define _LINUX_REISERFS_XATTR_H
+
+#include <linux/types.h>
 
 /* Magic value in header */
 #define REISERFS_XATTR_MAGIC 0x52465841	/* "RFXA" */
@@ -13,7 +16,18 @@
 };
 
 #ifdef __KERNEL__
+
 #include <linux/init.h>
+#include <linux/list.h>
+#include <linux/rwsem.h>
+#include <linux/reiserfs_fs_i.h>
+#include <linux/reiserfs_fs.h>
+
+struct inode;
+struct dentry;
+struct iattr;
+struct super_block;
+struct nameidata;
 
 struct reiserfs_xattr_handler {
 	char *prefix;
@@ -49,9 +63,7 @@
 
 extern struct reiserfs_xattr_handler user_handler;
 extern struct reiserfs_xattr_handler trusted_handler;
-#ifdef CONFIG_REISERFS_FS_SECURITY
 extern struct reiserfs_xattr_handler security_handler;
-#endif
 
 int reiserfs_xattr_register_handlers(void) __init;
 void reiserfs_xattr_unregister_handlers(void);
@@ -137,6 +149,8 @@
 static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
 {
 }
-#endif
+#endif  /*  CONFIG_REISERFS_FS_XATTR  */
 
-#endif				/* __KERNEL__ */
+#endif  /*  __KERNEL__  */
+
+#endif  /*  _LINUX_REISERFS_XATTR_H  */
diff --git a/include/linux/relay.h b/include/linux/relay.h
index c6a48bf..759a0f9 100644
--- a/include/linux/relay.h
+++ b/include/linux/relay.h
@@ -24,7 +24,7 @@
 /*
  * Tracks changes to rchan/rchan_buf structs
  */
-#define RELAYFS_CHANNEL_VERSION		6
+#define RELAYFS_CHANNEL_VERSION		7
 
 /*
  * Per-cpu relay channel buffer
@@ -64,6 +64,10 @@
 	void *private_data;		/* for user-defined data */
 	size_t last_toobig;		/* tried to log event > subbuf size */
 	struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
+	int is_global;			/* One global buffer ? */
+	struct list_head list;		/* for channel list */
+	struct dentry *parent;		/* parent dentry passed to open */
+	char base_filename[NAME_MAX];	/* saved base filename */
 };
 
 /*
@@ -162,7 +166,8 @@
 			 struct dentry *parent,
 			 size_t subbuf_size,
 			 size_t n_subbufs,
-			 struct rchan_callbacks *cb);
+			 struct rchan_callbacks *cb,
+			 void *private_data);
 extern void relay_close(struct rchan *chan);
 extern void relay_flush(struct rchan *chan);
 extern void relay_subbufs_consumed(struct rchan *chan,
diff --git a/include/linux/rio.h b/include/linux/rio.h
index d938570..68e3f68 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -25,6 +25,7 @@
 
 #define RIO_ANY_DESTID		0xff
 #define RIO_NO_HOPCOUNT		-1
+#define RIO_INVALID_DESTID	0xffff
 
 #define RIO_MAX_MPORT_RESOURCES	16
 #define RIO_MAX_DEV_RESOURCES	16
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4463735..5053dc0 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -436,7 +436,7 @@
 
 	/* job control IDs */
 	pid_t pgrp;
-	pid_t tty_old_pgrp;
+	struct pid *tty_old_pgrp;
 
 	union {
 		pid_t session __deprecated;
@@ -1013,8 +1013,10 @@
  * to a stack based synchronous wait) if its doing sync IO.
  */
 	wait_queue_t *io_wait;
+#ifdef CONFIG_TASK_XACCT
 /* i/o counters(bytes read/written, #syscalls */
 	u64 rchar, wchar, syscr, syscw;
+#endif
 	struct task_io_accounting ioac;
 #if defined(CONFIG_TASK_XACCT)
 	u64 acct_rss_mem1;	/* accumulated rss usage */
@@ -1327,14 +1329,11 @@
 extern int kill_pid_info_as_uid(int, struct siginfo *, struct pid *, uid_t, uid_t, u32);
 extern int kill_pgrp(struct pid *pid, int sig, int priv);
 extern int kill_pid(struct pid *pid, int sig, int priv);
-extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp);
-extern int kill_pg_info(int, struct siginfo *, pid_t);
 extern void do_notify_parent(struct task_struct *, int);
 extern void force_sig(int, struct task_struct *);
 extern void force_sig_specific(int, struct task_struct *);
 extern int send_sig(int, struct task_struct *, int);
 extern void zap_other_threads(struct task_struct *p);
-extern int kill_pg(pid_t, int, int);
 extern int kill_proc(pid_t, int, int);
 extern struct sigqueue *sigqueue_alloc(void);
 extern void sigqueue_free(struct sigqueue *);
@@ -1649,6 +1648,44 @@
 
 extern void normalize_rt_tasks(void);
 
+#ifdef CONFIG_TASK_XACCT
+static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
+{
+	tsk->rchar += amt;
+}
+
+static inline void add_wchar(struct task_struct *tsk, ssize_t amt)
+{
+	tsk->wchar += amt;
+}
+
+static inline void inc_syscr(struct task_struct *tsk)
+{
+	tsk->syscr++;
+}
+
+static inline void inc_syscw(struct task_struct *tsk)
+{
+	tsk->syscw++;
+}
+#else
+static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
+{
+}
+
+static inline void add_wchar(struct task_struct *tsk, ssize_t amt)
+{
+}
+
+static inline void inc_syscr(struct task_struct *tsk)
+{
+}
+
+static inline void inc_syscw(struct task_struct *tsk)
+{
+}
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif
diff --git a/include/linux/security.h b/include/linux/security.h
index 83cdefa..7f88d97 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -492,7 +492,7 @@
  *	Note that the fown_struct, @fown, is never outside the context of a
  *	struct file, so the file structure (and associated security information)
  *	can always be obtained:
- *		(struct file *)((long)fown - offsetof(struct file,f_owner));
+ *		container_of(fown, struct file, f_owner)
  * 	@tsk contains the structure of task receiving signal.
  *	@fown contains the file owner information.
  *	@sig is the signal that will be sent.  When 0, kernel sends SIGIO.
@@ -2130,7 +2130,7 @@
 extern int mod_unreg_security	(const char *name, struct security_operations *ops);
 extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
 					     struct dentry *parent, void *data,
-					     struct file_operations *fops);
+					     const struct file_operations *fops);
 extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent);
 extern void securityfs_remove(struct dentry *dentry);
 
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 6b0648c..52c9eb9 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -2,7 +2,7 @@
 #define __LINUX_SEQLOCK_H
 /*
  * Reader/writer consistent mechanism without starving writers. This type of
- * lock for data where the reader wants a consitent set of information
+ * lock for data where the reader wants a consistent set of information
  * and is willing to retry if the information changes.  Readers never
  * block but they may have to retry if a writer is in
  * progress. Writers do not wait for readers. 
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index cf23813..586aaba 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -122,7 +122,7 @@
 /*Digi jsm */
 #define PORT_JSM        69
 
-#define PORT_IP3106	70
+#define PORT_PNX8XXX	70
 
 /* Hilscher netx */
 #define PORT_NETX	71
diff --git a/include/linux/serial_ip3106.h b/include/linux/serial_ip3106.h
deleted file mode 100644
index f500ac6..0000000
--- a/include/linux/serial_ip3106.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Embedded Alley Solutions, source@embeddedalley.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
- */
-
-#ifndef _LINUX_SERIAL_IP3106_H
-#define _LINUX_SERIAL_IP3106_H
-
-#include <linux/serial_core.h>
-#include <linux/device.h>
-
-#define IP3106_NR_PORTS		2
-
-struct ip3106_port {
-	struct uart_port	port;
-	struct timer_list	timer;
-	unsigned int		old_status;
-};
-
-/* register offsets */
-#define IP3106_LCR		0
-#define IP3106_MCR		0x004
-#define IP3106_BAUD		0x008
-#define IP3106_CFG		0x00c
-#define IP3106_FIFO		0x028
-#define IP3106_ISTAT		0xfe0
-#define IP3106_IEN		0xfe4
-#define IP3106_ICLR		0xfe8
-#define IP3106_ISET		0xfec
-#define IP3106_PD		0xff4
-#define IP3106_MID		0xffc
-
-#define IP3106_UART_LCR_TXBREAK		(1<<30)
-#define IP3106_UART_LCR_PAREVN		0x10000000
-#define IP3106_UART_LCR_PAREN		0x08000000
-#define IP3106_UART_LCR_2STOPB		0x04000000
-#define IP3106_UART_LCR_8BIT		0x01000000
-#define IP3106_UART_LCR_TX_RST		0x00040000
-#define IP3106_UART_LCR_RX_RST		0x00020000
-#define IP3106_UART_LCR_RX_NEXT		0x00010000
-
-#define IP3106_UART_MCR_SCR		0xFF000000
-#define IP3106_UART_MCR_DCD		0x00800000
-#define IP3106_UART_MCR_CTS		0x00100000
-#define IP3106_UART_MCR_LOOP		0x00000010
-#define IP3106_UART_MCR_RTS		0x00000002
-#define IP3106_UART_MCR_DTR		0x00000001
-
-#define IP3106_UART_INT_TX		0x00000080
-#define IP3106_UART_INT_EMPTY		0x00000040
-#define IP3106_UART_INT_RCVTO		0x00000020
-#define IP3106_UART_INT_RX		0x00000010
-#define IP3106_UART_INT_RXOVRN		0x00000008
-#define IP3106_UART_INT_FRERR		0x00000004
-#define IP3106_UART_INT_BREAK		0x00000002
-#define IP3106_UART_INT_PARITY		0x00000001
-#define IP3106_UART_INT_ALLRX		0x0000003F
-#define IP3106_UART_INT_ALLTX		0x000000C0
-
-#define IP3106_UART_FIFO_TXFIFO		0x001F0000
-#define IP3106_UART_FIFO_TXFIFO_STA	(0x1f<<16)
-#define IP3106_UART_FIFO_RXBRK		0x00008000
-#define IP3106_UART_FIFO_RXFE		0x00004000
-#define IP3106_UART_FIFO_RXPAR		0x00002000
-#define IP3106_UART_FIFO_RXFIFO		0x00001F00
-#define IP3106_UART_FIFO_RBRTHR		0x000000FF
-
-#endif
diff --git a/include/linux/serial_pnx8xxx.h b/include/linux/serial_pnx8xxx.h
new file mode 100644
index 0000000..de6c19c
--- /dev/null
+++ b/include/linux/serial_pnx8xxx.h
@@ -0,0 +1,81 @@
+/*
+ * Embedded Alley Solutions, source@embeddedalley.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
+ */
+
+#ifndef _LINUX_SERIAL_PNX8XXX_H
+#define _LINUX_SERIAL_PNX8XXX_H
+
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+#define PNX8XXX_NR_PORTS	2
+
+struct pnx8xxx_port {
+	struct uart_port	port;
+	struct timer_list	timer;
+	unsigned int		old_status;
+};
+
+/* register offsets */
+#define PNX8XXX_LCR		0
+#define PNX8XXX_MCR		0x004
+#define PNX8XXX_BAUD		0x008
+#define PNX8XXX_CFG		0x00c
+#define PNX8XXX_FIFO		0x028
+#define PNX8XXX_ISTAT		0xfe0
+#define PNX8XXX_IEN		0xfe4
+#define PNX8XXX_ICLR		0xfe8
+#define PNX8XXX_ISET		0xfec
+#define PNX8XXX_PD		0xff4
+#define PNX8XXX_MID		0xffc
+
+#define PNX8XXX_UART_LCR_TXBREAK	(1<<30)
+#define PNX8XXX_UART_LCR_PAREVN		0x10000000
+#define PNX8XXX_UART_LCR_PAREN		0x08000000
+#define PNX8XXX_UART_LCR_2STOPB		0x04000000
+#define PNX8XXX_UART_LCR_8BIT		0x01000000
+#define PNX8XXX_UART_LCR_TX_RST		0x00040000
+#define PNX8XXX_UART_LCR_RX_RST		0x00020000
+#define PNX8XXX_UART_LCR_RX_NEXT	0x00010000
+
+#define PNX8XXX_UART_MCR_SCR		0xFF000000
+#define PNX8XXX_UART_MCR_DCD		0x00800000
+#define PNX8XXX_UART_MCR_CTS		0x00100000
+#define PNX8XXX_UART_MCR_LOOP		0x00000010
+#define PNX8XXX_UART_MCR_RTS		0x00000002
+#define PNX8XXX_UART_MCR_DTR		0x00000001
+
+#define PNX8XXX_UART_INT_TX		0x00000080
+#define PNX8XXX_UART_INT_EMPTY		0x00000040
+#define PNX8XXX_UART_INT_RCVTO		0x00000020
+#define PNX8XXX_UART_INT_RX		0x00000010
+#define PNX8XXX_UART_INT_RXOVRN		0x00000008
+#define PNX8XXX_UART_INT_FRERR		0x00000004
+#define PNX8XXX_UART_INT_BREAK		0x00000002
+#define PNX8XXX_UART_INT_PARITY		0x00000001
+#define PNX8XXX_UART_INT_ALLRX		0x0000003F
+#define PNX8XXX_UART_INT_ALLTX		0x000000C0
+
+#define PNX8XXX_UART_FIFO_TXFIFO	0x001F0000
+#define PNX8XXX_UART_FIFO_TXFIFO_STA	(0x1f<<16)
+#define PNX8XXX_UART_FIFO_RXBRK		0x00008000
+#define PNX8XXX_UART_FIFO_RXFE		0x00004000
+#define PNX8XXX_UART_FIFO_RXPAR		0x00002000
+#define PNX8XXX_UART_FIFO_RXFIFO	0x00001F00
+#define PNX8XXX_UART_FIFO_RBRTHR	0x000000FF
+
+#endif
diff --git a/include/linux/serio.h b/include/linux/serio.h
index ac2c70e..1ebf045 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -108,12 +108,6 @@
 		serio->drv->write_wakeup(serio);
 }
 
-static inline void serio_cleanup(struct serio *serio)
-{
-	if (serio->drv && serio->drv->cleanup)
-		serio->drv->cleanup(serio);
-}
-
 /*
  * Use the following functions to manipulate serio's per-port
  * driver-specific data.
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 4b463e6..5e43646 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -19,7 +19,9 @@
 struct cache_sizes {
 	size_t		 	cs_size;
 	struct kmem_cache	*cs_cachep;
+#ifdef CONFIG_ZONE_DMA
 	struct kmem_cache	*cs_dmacachep;
+#endif
 };
 extern struct cache_sizes malloc_sizes[];
 
@@ -39,9 +41,12 @@
 			__you_cannot_kmalloc_that_much();
 		}
 found:
-		return kmem_cache_alloc((flags & GFP_DMA) ?
-			malloc_sizes[i].cs_dmacachep :
-			malloc_sizes[i].cs_cachep, flags);
+#ifdef CONFIG_ZONE_DMA
+		if (flags & GFP_DMA)
+			return kmem_cache_alloc(malloc_sizes[i].cs_dmacachep,
+						flags);
+#endif
+		return kmem_cache_alloc(malloc_sizes[i].cs_cachep, flags);
 	}
 	return __kmalloc(size, flags);
 }
@@ -62,9 +67,12 @@
 			__you_cannot_kzalloc_that_much();
 		}
 found:
-		return kmem_cache_zalloc((flags & GFP_DMA) ?
-			malloc_sizes[i].cs_dmacachep :
-			malloc_sizes[i].cs_cachep, flags);
+#ifdef CONFIG_ZONE_DMA
+		if (flags & GFP_DMA)
+			return kmem_cache_zalloc(malloc_sizes[i].cs_dmacachep,
+						flags);
+#endif
+		return kmem_cache_zalloc(malloc_sizes[i].cs_cachep, flags);
 	}
 	return __kzalloc(size, flags);
 }
@@ -88,9 +96,13 @@
 			__you_cannot_kmalloc_that_much();
 		}
 found:
-		return kmem_cache_alloc_node((flags & GFP_DMA) ?
-			malloc_sizes[i].cs_dmacachep :
-			malloc_sizes[i].cs_cachep, flags, node);
+#ifdef CONFIG_ZONE_DMA
+		if (flags & GFP_DMA)
+			return kmem_cache_alloc_node(malloc_sizes[i].cs_dmacachep,
+						flags, node);
+#endif
+		return kmem_cache_alloc_node(malloc_sizes[i].cs_cachep,
+						flags, node);
 	}
 	return __kmalloc_node(size, flags, node);
 }
diff --git a/include/linux/sm501-regs.h b/include/linux/sm501-regs.h
new file mode 100644
index 0000000..cc9be4a
--- /dev/null
+++ b/include/linux/sm501-regs.h
@@ -0,0 +1,357 @@
+/* sm501-regs.h
+ *
+ * Copyright 2006 Simtec Electronics
+ *
+ * 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.
+ *
+ * Silicon Motion SM501 register definitions
+*/
+
+/* System Configuration area */
+/* System config base */
+#define SM501_SYS_CONFIG		(0x000000)
+
+/* config 1 */
+#define SM501_SYSTEM_CONTROL 		(0x000000)
+#define SM501_MISC_CONTROL		(0x000004)
+
+#define SM501_MISC_BUS_SH		(0x0)
+#define SM501_MISC_BUS_PCI		(0x1)
+#define SM501_MISC_BUS_XSCALE		(0x2)
+#define SM501_MISC_BUS_NEC		(0x6)
+#define SM501_MISC_BUS_MASK		(0x7)
+
+#define SM501_MISC_VR_62MB		(1<<3)
+#define SM501_MISC_CDR_RESET		(1<<7)
+#define SM501_MISC_USB_LB		(1<<8)
+#define SM501_MISC_USB_SLAVE		(1<<9)
+#define SM501_MISC_BL_1			(1<<10)
+#define SM501_MISC_MC			(1<<11)
+#define SM501_MISC_DAC_POWER		(1<<12)
+#define SM501_MISC_IRQ_INVERT		(1<<16)
+#define SM501_MISC_SH			(1<<17)
+
+#define SM501_MISC_HOLD_EMPTY		(0<<18)
+#define SM501_MISC_HOLD_8		(1<<18)
+#define SM501_MISC_HOLD_16		(2<<18)
+#define SM501_MISC_HOLD_24		(3<<18)
+#define SM501_MISC_HOLD_32		(4<<18)
+#define SM501_MISC_HOLD_MASK		(7<<18)
+
+#define SM501_MISC_FREQ_12		(1<<24)
+#define SM501_MISC_PNL_24BIT		(1<<25)
+#define SM501_MISC_8051_LE		(1<<26)
+
+
+
+#define SM501_GPIO31_0_CONTROL		(0x000008)
+#define SM501_GPIO63_32_CONTROL		(0x00000C)
+#define SM501_DRAM_CONTROL		(0x000010)
+
+/* command list */
+#define SM501_ARBTRTN_CONTROL		(0x000014)
+
+/* command list */
+#define SM501_COMMAND_LIST_STATUS	(0x000024)
+
+/* interrupt debug */
+#define SM501_RAW_IRQ_STATUS		(0x000028)
+#define SM501_RAW_IRQ_CLEAR		(0x000028)
+#define SM501_IRQ_STATUS		(0x00002C)
+#define SM501_IRQ_MASK			(0x000030)
+#define SM501_DEBUG_CONTROL		(0x000034)
+
+/* power management */
+#define SM501_CURRENT_GATE		(0x000038)
+#define SM501_CURRENT_CLOCK		(0x00003C)
+#define SM501_POWER_MODE_0_GATE		(0x000040)
+#define SM501_POWER_MODE_0_CLOCK	(0x000044)
+#define SM501_POWER_MODE_1_GATE		(0x000048)
+#define SM501_POWER_MODE_1_CLOCK	(0x00004C)
+#define SM501_SLEEP_MODE_GATE		(0x000050)
+#define SM501_POWER_MODE_CONTROL	(0x000054)
+
+/* power gates for units within the 501 */
+#define SM501_GATE_HOST			(0)
+#define SM501_GATE_MEMORY		(1)
+#define SM501_GATE_DISPLAY		(2)
+#define SM501_GATE_2D_ENGINE		(3)
+#define SM501_GATE_CSC			(4)
+#define SM501_GATE_ZVPORT		(5)
+#define SM501_GATE_GPIO			(6)
+#define SM501_GATE_UART0		(7)
+#define SM501_GATE_UART1		(8)
+#define SM501_GATE_SSP			(10)
+#define SM501_GATE_USB_HOST		(11)
+#define SM501_GATE_USB_GADGET		(12)
+#define SM501_GATE_UCONTROLLER		(17)
+#define SM501_GATE_AC97			(18)
+
+/* panel clock */
+#define SM501_CLOCK_P2XCLK		(24)
+/* crt clock */
+#define SM501_CLOCK_V2XCLK		(16)
+/* main clock */
+#define SM501_CLOCK_MCLK		(8)
+/* SDRAM controller clock */
+#define SM501_CLOCK_M1XCLK		(0)
+
+/* config 2 */
+#define SM501_PCI_MASTER_BASE		(0x000058)
+#define SM501_ENDIAN_CONTROL		(0x00005C)
+#define SM501_DEVICEID			(0x000060)
+/* 0x050100A0 */
+
+#define SM501_PLLCLOCK_COUNT		(0x000064)
+#define SM501_MISC_TIMING		(0x000068)
+#define SM501_CURRENT_SDRAM_CLOCK	(0x00006C)
+
+/* GPIO base */
+#define SM501_GPIO			(0x010000)
+#define SM501_GPIO_DATA_LOW		(0x00)
+#define SM501_GPIO_DATA_HIGH		(0x04)
+#define SM501_GPIO_DDR_LOW		(0x08)
+#define SM501_GPIO_DDR_HIGH		(0x0C)
+#define SM501_GPIO_IRQ_SETUP		(0x10)
+#define SM501_GPIO_IRQ_STATUS		(0x14)
+#define SM501_GPIO_IRQ_RESET		(0x14)
+
+/* I2C controller base */
+#define SM501_I2C			(0x010040)
+#define SM501_I2C_BYTE_COUNT		(0x00)
+#define SM501_I2C_CONTROL		(0x01)
+#define SM501_I2C_STATUS		(0x02)
+#define SM501_I2C_RESET			(0x02)
+#define SM501_I2C_SLAVE_ADDRESS		(0x03)
+#define SM501_I2C_DATA			(0x04)
+
+/* SSP base */
+#define SM501_SSP			(0x020000)
+
+/* Uart 0 base */
+#define SM501_UART0			(0x030000)
+
+/* Uart 1 base */
+#define SM501_UART1			(0x030020)
+
+/* USB host port base */
+#define SM501_USB_HOST			(0x040000)
+
+/* USB slave/gadget base */
+#define SM501_USB_GADGET		(0x060000)
+
+/* USB slave/gadget data port base */
+#define SM501_USB_GADGET_DATA		(0x070000)
+
+/* Display contoller/video engine base */
+#define SM501_DC			(0x080000)
+
+/* common defines for the SM501 address registers */
+#define SM501_ADDR_FLIP			(1<<31)
+#define SM501_ADDR_EXT			(1<<27)
+#define SM501_ADDR_CS1			(1<<26)
+#define SM501_ADDR_MASK			(0x3f << 26)
+
+#define SM501_FIFO_MASK			(0x3 << 16)
+#define SM501_FIFO_1			(0x0 << 16)
+#define SM501_FIFO_3			(0x1 << 16)
+#define SM501_FIFO_7			(0x2 << 16)
+#define SM501_FIFO_11			(0x3 << 16)
+
+/* common registers for panel and the crt */
+#define SM501_OFF_DC_H_TOT		(0x000)
+#define SM501_OFF_DC_V_TOT		(0x008)
+#define SM501_OFF_DC_H_SYNC		(0x004)
+#define SM501_OFF_DC_V_SYNC		(0x00C)
+
+#define SM501_DC_PANEL_CONTROL		(0x000)
+
+#define SM501_DC_PANEL_CONTROL_FPEN	(1<<27)
+#define SM501_DC_PANEL_CONTROL_BIAS	(1<<26)
+#define SM501_DC_PANEL_CONTROL_DATA	(1<<25)
+#define SM501_DC_PANEL_CONTROL_VDD	(1<<24)
+#define SM501_DC_PANEL_CONTROL_DP	(1<<23)
+
+#define SM501_DC_PANEL_CONTROL_TFT_888	(0<<21)
+#define SM501_DC_PANEL_CONTROL_TFT_333	(1<<21)
+#define SM501_DC_PANEL_CONTROL_TFT_444	(2<<21)
+
+#define SM501_DC_PANEL_CONTROL_DE	(1<<20)
+
+#define SM501_DC_PANEL_CONTROL_LCD_TFT	(0<<18)
+#define SM501_DC_PANEL_CONTROL_LCD_STN8	(1<<18)
+#define SM501_DC_PANEL_CONTROL_LCD_STN12 (2<<18)
+
+#define SM501_DC_PANEL_CONTROL_CP	(1<<14)
+#define SM501_DC_PANEL_CONTROL_VSP	(1<<13)
+#define SM501_DC_PANEL_CONTROL_HSP	(1<<12)
+#define SM501_DC_PANEL_CONTROL_CK	(1<<9)
+#define SM501_DC_PANEL_CONTROL_TE	(1<<8)
+#define SM501_DC_PANEL_CONTROL_VPD	(1<<7)
+#define SM501_DC_PANEL_CONTROL_VP	(1<<6)
+#define SM501_DC_PANEL_CONTROL_HPD	(1<<5)
+#define SM501_DC_PANEL_CONTROL_HP	(1<<4)
+#define SM501_DC_PANEL_CONTROL_GAMMA	(1<<3)
+#define SM501_DC_PANEL_CONTROL_EN	(1<<2)
+
+#define SM501_DC_PANEL_CONTROL_8BPP	(0<<0)
+#define SM501_DC_PANEL_CONTROL_16BPP	(1<<0)
+#define SM501_DC_PANEL_CONTROL_32BPP	(2<<0)
+
+
+#define SM501_DC_PANEL_PANNING_CONTROL	(0x004)
+#define SM501_DC_PANEL_COLOR_KEY	(0x008)
+#define SM501_DC_PANEL_FB_ADDR		(0x00C)
+#define SM501_DC_PANEL_FB_OFFSET	(0x010)
+#define SM501_DC_PANEL_FB_WIDTH		(0x014)
+#define SM501_DC_PANEL_FB_HEIGHT	(0x018)
+#define SM501_DC_PANEL_TL_LOC		(0x01C)
+#define SM501_DC_PANEL_BR_LOC		(0x020)
+#define SM501_DC_PANEL_H_TOT		(0x024)
+#define SM501_DC_PANEL_H_SYNC		(0x028)
+#define SM501_DC_PANEL_V_TOT		(0x02C)
+#define SM501_DC_PANEL_V_SYNC		(0x030)
+#define SM501_DC_PANEL_CUR_LINE		(0x034)
+
+#define SM501_DC_VIDEO_CONTROL		(0x040)
+#define SM501_DC_VIDEO_FB0_ADDR		(0x044)
+#define SM501_DC_VIDEO_FB_WIDTH		(0x048)
+#define SM501_DC_VIDEO_FB0_LAST_ADDR	(0x04C)
+#define SM501_DC_VIDEO_TL_LOC		(0x050)
+#define SM501_DC_VIDEO_BR_LOC		(0x054)
+#define SM501_DC_VIDEO_SCALE		(0x058)
+#define SM501_DC_VIDEO_INIT_SCALE	(0x05C)
+#define SM501_DC_VIDEO_YUV_CONSTANTS	(0x060)
+#define SM501_DC_VIDEO_FB1_ADDR		(0x064)
+#define SM501_DC_VIDEO_FB1_LAST_ADDR	(0x068)
+
+#define SM501_DC_VIDEO_ALPHA_CONTROL	(0x080)
+#define SM501_DC_VIDEO_ALPHA_FB_ADDR	(0x084)
+#define SM501_DC_VIDEO_ALPHA_FB_OFFSET	(0x088)
+#define SM501_DC_VIDEO_ALPHA_FB_LAST_ADDR	(0x08C)
+#define SM501_DC_VIDEO_ALPHA_TL_LOC	(0x090)
+#define SM501_DC_VIDEO_ALPHA_BR_LOC	(0x094)
+#define SM501_DC_VIDEO_ALPHA_SCALE	(0x098)
+#define SM501_DC_VIDEO_ALPHA_INIT_SCALE	(0x09C)
+#define SM501_DC_VIDEO_ALPHA_CHROMA_KEY	(0x0A0)
+#define SM501_DC_VIDEO_ALPHA_COLOR_LOOKUP	(0x0A4)
+
+#define SM501_DC_PANEL_HWC_BASE		(0x0F0)
+#define SM501_DC_PANEL_HWC_ADDR		(0x0F0)
+#define SM501_DC_PANEL_HWC_LOC		(0x0F4)
+#define SM501_DC_PANEL_HWC_COLOR_1_2	(0x0F8)
+#define SM501_DC_PANEL_HWC_COLOR_3	(0x0FC)
+
+#define SM501_HWC_EN			(1<<31)
+
+#define SM501_OFF_HWC_ADDR		(0x00)
+#define SM501_OFF_HWC_LOC		(0x04)
+#define SM501_OFF_HWC_COLOR_1_2		(0x08)
+#define SM501_OFF_HWC_COLOR_3		(0x0C)
+
+#define SM501_DC_ALPHA_CONTROL		(0x100)
+#define SM501_DC_ALPHA_FB_ADDR		(0x104)
+#define SM501_DC_ALPHA_FB_OFFSET	(0x108)
+#define SM501_DC_ALPHA_TL_LOC		(0x10C)
+#define SM501_DC_ALPHA_BR_LOC		(0x110)
+#define SM501_DC_ALPHA_CHROMA_KEY	(0x114)
+#define SM501_DC_ALPHA_COLOR_LOOKUP	(0x118)
+
+#define SM501_DC_CRT_CONTROL		(0x200)
+
+#define SM501_DC_CRT_CONTROL_TVP	(1<<15)
+#define SM501_DC_CRT_CONTROL_CP		(1<<14)
+#define SM501_DC_CRT_CONTROL_VSP	(1<<13)
+#define SM501_DC_CRT_CONTROL_HSP	(1<<12)
+#define SM501_DC_CRT_CONTROL_VS		(1<<11)
+#define SM501_DC_CRT_CONTROL_BLANK	(1<<10)
+#define SM501_DC_CRT_CONTROL_SEL	(1<<9)
+#define SM501_DC_CRT_CONTROL_TE		(1<<8)
+#define SM501_DC_CRT_CONTROL_PIXEL_MASK (0xF << 4)
+#define SM501_DC_CRT_CONTROL_GAMMA	(1<<3)
+#define SM501_DC_CRT_CONTROL_ENABLE	(1<<2)
+
+#define SM501_DC_CRT_CONTROL_8BPP	(0<<0)
+#define SM501_DC_CRT_CONTROL_16BPP	(1<<0)
+#define SM501_DC_CRT_CONTROL_32BPP	(2<<0)
+
+#define SM501_DC_CRT_FB_ADDR		(0x204)
+#define SM501_DC_CRT_FB_OFFSET		(0x208)
+#define SM501_DC_CRT_H_TOT		(0x20C)
+#define SM501_DC_CRT_H_SYNC		(0x210)
+#define SM501_DC_CRT_V_TOT		(0x214)
+#define SM501_DC_CRT_V_SYNC		(0x218)
+#define SM501_DC_CRT_SIGNATURE_ANALYZER	(0x21C)
+#define SM501_DC_CRT_CUR_LINE		(0x220)
+#define SM501_DC_CRT_MONITOR_DETECT	(0x224)
+
+#define SM501_DC_CRT_HWC_BASE		(0x230)
+#define SM501_DC_CRT_HWC_ADDR		(0x230)
+#define SM501_DC_CRT_HWC_LOC		(0x234)
+#define SM501_DC_CRT_HWC_COLOR_1_2	(0x238)
+#define SM501_DC_CRT_HWC_COLOR_3	(0x23C)
+
+#define SM501_DC_PANEL_PALETTE		(0x400)
+
+#define SM501_DC_VIDEO_PALETTE		(0x800)
+
+#define SM501_DC_CRT_PALETTE		(0xC00)
+
+/* Zoom Video port base */
+#define SM501_ZVPORT			(0x090000)
+
+/* AC97/I2S base */
+#define SM501_AC97			(0x0A0000)
+
+/* 8051 micro controller base */
+#define SM501_UCONTROLLER		(0x0B0000)
+
+/* 8051 micro controller SRAM base */
+#define SM501_UCONTROLLER_SRAM		(0x0C0000)
+
+/* DMA base */
+#define SM501_DMA			(0x0D0000)
+
+/* 2d engine base */
+#define SM501_2D_ENGINE			(0x100000)
+#define SM501_2D_SOURCE			(0x00)
+#define SM501_2D_DESTINATION		(0x04)
+#define SM501_2D_DIMENSION		(0x08)
+#define SM501_2D_CONTROL		(0x0C)
+#define SM501_2D_PITCH			(0x10)
+#define SM501_2D_FOREGROUND		(0x14)
+#define SM501_2D_BACKGROUND		(0x18)
+#define SM501_2D_STRETCH		(0x1C)
+#define SM501_2D_COLOR_COMPARE		(0x20)
+#define SM501_2D_COLOR_COMPARE_MASK 	(0x24)
+#define SM501_2D_MASK			(0x28)
+#define SM501_2D_CLIP_TL		(0x2C)
+#define SM501_2D_CLIP_BR		(0x30)
+#define SM501_2D_MONO_PATTERN_LOW	(0x34)
+#define SM501_2D_MONO_PATTERN_HIGH	(0x38)
+#define SM501_2D_WINDOW_WIDTH		(0x3C)
+#define SM501_2D_SOURCE_BASE		(0x40)
+#define SM501_2D_DESTINATION_BASE	(0x44)
+#define SM501_2D_ALPHA			(0x48)
+#define SM501_2D_WRAP			(0x4C)
+#define SM501_2D_STATUS			(0x50)
+
+#define SM501_CSC_Y_SOURCE_BASE		(0xC8)
+#define SM501_CSC_CONSTANTS		(0xCC)
+#define SM501_CSC_Y_SOURCE_X		(0xD0)
+#define SM501_CSC_Y_SOURCE_Y		(0xD4)
+#define SM501_CSC_U_SOURCE_BASE		(0xD8)
+#define SM501_CSC_V_SOURCE_BASE		(0xDC)
+#define SM501_CSC_SOURCE_DIMENSION	(0xE0)
+#define SM501_CSC_SOURCE_PITCH		(0xE4)
+#define SM501_CSC_DESTINATION		(0xE8)
+#define SM501_CSC_DESTINATION_DIMENSION	(0xEC)
+#define SM501_CSC_DESTINATION_PITCH	(0xF0)
+#define SM501_CSC_SCALE_FACTOR		(0xF4)
+#define SM501_CSC_DESTINATION_BASE	(0xF8)
+#define SM501_CSC_CONTROL		(0xFC)
+
+/* 2d engine data port base */
+#define SM501_2D_ENGINE_DATA		(0x110000)
diff --git a/include/linux/sm501.h b/include/linux/sm501.h
new file mode 100644
index 0000000..9e3aaad
--- /dev/null
+++ b/include/linux/sm501.h
@@ -0,0 +1,170 @@
+/* include/linux/sm501.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	Vincent Sanders <vince@simtec.co.uk>
+ *
+ * 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
+ *
+ * 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
+*/
+
+extern int sm501_unit_power(struct device *dev,
+			    unsigned int unit, unsigned int to);
+
+extern unsigned long sm501_set_clock(struct device *dev,
+				     int clksrc, unsigned long freq);
+
+extern unsigned long sm501_find_clock(int clksrc, unsigned long req_freq);
+
+/* sm501_misc_control
+ *
+ * Modify the SM501's MISC_CONTROL register
+*/
+
+extern int sm501_misc_control(struct device *dev,
+			      unsigned long set, unsigned long clear);
+
+/* sm501_modify_reg
+ *
+ * Modify a register in the SM501 which may be shared with other
+ * drivers.
+*/
+
+extern unsigned long sm501_modify_reg(struct device *dev,
+				      unsigned long reg,
+				      unsigned long set,
+				      unsigned long clear);
+
+/* sm501_gpio_set
+ *
+ * set the state of the given GPIO line
+*/
+
+extern void sm501_gpio_set(struct device *dev,
+			   unsigned long gpio,
+			   unsigned int to,
+			   unsigned int dir);
+
+/* sm501_gpio_get
+ *
+ * get the state of the given GPIO line
+*/
+
+extern unsigned long sm501_gpio_get(struct device *dev,
+				    unsigned long gpio);
+
+
+/* Platform data definitions */
+
+#define SM501FB_FLAG_USE_INIT_MODE	(1<<0)
+#define SM501FB_FLAG_DISABLE_AT_EXIT	(1<<1)
+#define SM501FB_FLAG_USE_HWCURSOR	(1<<2)
+#define SM501FB_FLAG_USE_HWACCEL	(1<<3)
+
+struct sm501_platdata_fbsub {
+	struct fb_videomode	*def_mode;
+	unsigned int		 def_bpp;
+	unsigned long		 max_mem;
+	unsigned int		 flags;
+};
+
+enum sm501_fb_routing {
+	SM501_FB_OWN		= 0,	/* CRT=>CRT, Panel=>Panel */
+	SM501_FB_CRT_PANEL	= 1,	/* Panel=>CRT, Panel=>Panel */
+};
+
+/* sm501_platdata_fb flag field bit definitions */
+
+#define SM501_FBPD_SWAP_FB_ENDIAN	(1<<0)	/* need to endian swap */
+
+/* sm501_platdata_fb
+ *
+ * configuration data for the framebuffer driver
+*/
+
+struct sm501_platdata_fb {
+	enum sm501_fb_routing		 fb_route;
+	unsigned int			 flags;
+	struct sm501_platdata_fbsub	*fb_crt;
+	struct sm501_platdata_fbsub	*fb_pnl;
+};
+
+/* gpio i2c */
+
+struct sm501_platdata_gpio_i2c {
+	unsigned int		pin_sda;
+	unsigned int		pin_scl;
+};
+
+/* sm501_initdata
+ *
+ * use for initialising values that may not have been setup
+ * before the driver is loaded.
+*/
+
+struct sm501_reg_init {
+	unsigned long		set;
+	unsigned long		mask;
+};
+
+#define SM501_USE_USB_HOST	(1<<0)
+#define SM501_USE_USB_SLAVE	(1<<1)
+#define SM501_USE_SSP0		(1<<2)
+#define SM501_USE_SSP1		(1<<3)
+#define SM501_USE_UART0		(1<<4)
+#define SM501_USE_UART1		(1<<5)
+#define SM501_USE_FBACCEL	(1<<6)
+#define SM501_USE_AC97		(1<<7)
+#define SM501_USE_I2S		(1<<8)
+
+#define SM501_USE_ALL		(0xffffffff)
+
+struct sm501_initdata {
+	struct sm501_reg_init	gpio_low;
+	struct sm501_reg_init	gpio_high;
+	struct sm501_reg_init	misc_timing;
+	struct sm501_reg_init	misc_control;
+
+	unsigned long		devices;
+	unsigned long		mclk;		/* non-zero to modify */
+	unsigned long		m1xclk;		/* non-zero to modify */
+};
+
+/* sm501_init_gpio
+ *
+ * default gpio settings
+*/
+
+struct sm501_init_gpio {
+	struct sm501_reg_init	gpio_data_low;
+	struct sm501_reg_init	gpio_data_high;
+	struct sm501_reg_init	gpio_ddr_low;
+	struct sm501_reg_init	gpio_ddr_high;
+};
+
+/* sm501_platdata
+ *
+ * This is passed with the platform device to allow the board
+ * to control the behaviour of the SM501 driver(s) which attach
+ * to the device.
+ *
+*/
+
+struct sm501_platdata {
+	struct sm501_initdata		*init;
+	struct sm501_init_gpio		*init_gpiop;
+	struct sm501_platdata_fb	*fb;
+
+	struct sm501_platdata_gpio_i2c	*gpio_i2c;
+	unsigned int			 gpio_i2c_nr;
+};
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 92cd38e..28157a3 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -16,7 +16,7 @@
 				/* _SS_MAXSIZE value minus size of ss_family */
 } __attribute__ ((aligned(_K_SS_ALIGNSIZE)));	/* force desired alignment */
 
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+#ifdef __KERNEL__
 
 #include <asm/socket.h>			/* arch-dependent defines	*/
 #include <linux/sockios.h>		/* the SIOCxxx I/O controls	*/
@@ -187,7 +187,8 @@
 #define AF_LLC		26	/* Linux LLC			*/
 #define AF_TIPC		30	/* TIPC sockets			*/
 #define AF_BLUETOOTH	31	/* Bluetooth sockets 		*/
-#define AF_MAX		32	/* For now.. */
+#define AF_IUCV		32	/* IUCV sockets			*/
+#define AF_MAX		33	/* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC	AF_UNSPEC
@@ -220,6 +221,7 @@
 #define PF_LLC		AF_LLC
 #define PF_TIPC		AF_TIPC
 #define PF_BLUETOOTH	AF_BLUETOOTH
+#define PF_IUCV		AF_IUCV
 #define PF_MAX		AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h
index adb3dafd..3387e44 100644
--- a/include/linux/spi/ads7846.h
+++ b/include/linux/spi/ads7846.h
@@ -5,9 +5,17 @@
  *
  * It's OK if the min/max values are zero.
  */
+enum ads7846_filter {
+	ADS7846_FILTER_OK,
+	ADS7846_FILTER_REPEAT,
+	ADS7846_FILTER_IGNORE,
+};
+
 struct ads7846_platform_data {
 	u16	model;			/* 7843, 7845, 7846. */
 	u16	vref_delay_usecs;	/* 0 for external vref; etc */
+	int	keep_vref_on:1;		/* set to keep vref on for differential
+					 * measurements as well */
 	u16	x_plate_ohms;
 	u16	y_plate_ohms;
 
@@ -21,5 +29,9 @@
 	u16	debounce_rep;		/* additional consecutive good readings
 					 * required after the first two */
 	int	(*get_pendown_state)(void);
+	int	(*filter_init)	(struct ads7846_platform_data *pdata,
+				 void **filter_data);
+	int	(*filter)	(void *filter_data, int data_idx, int *val);
+	void	(*filter_cleanup)(void *filter_data);
 };
 
diff --git a/include/linux/spi/eeprom.h b/include/linux/spi/eeprom.h
new file mode 100644
index 0000000..1085212
--- /dev/null
+++ b/include/linux/spi/eeprom.h
@@ -0,0 +1,22 @@
+#ifndef __LINUX_SPI_EEPROM_H
+#define __LINUX_SPI_EEPROM_H
+
+/*
+ * Put one of these structures in platform_data for SPI EEPROMS handled
+ * by the "at25" driver.  On SPI, most EEPROMS understand the same core
+ * command set.  If you need to support EEPROMs that don't yet fit, add
+ * flags to support those protocol options.  These values all come from
+ * the chip datasheets.
+ */
+struct spi_eeprom {
+	u32		byte_len;
+	char		name[10];
+	u16		page_size;		/* for writes */
+	u16		flags;
+#define	EE_ADDR1	0x0001			/*  8 bit addrs */
+#define	EE_ADDR2	0x0002			/* 16 bit addrs */
+#define	EE_ADDR3	0x0004			/* 24 bit addrs */
+#define	EE_READONLY	0x0008			/* disallow writes */
+};
+
+#endif /* __LINUX_SPI_EEPROM_H */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 176f6e3..4f0f8c2 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -114,6 +114,17 @@
 	spi->controller_state = state;
 }
 
+/* device driver data */
+
+static inline void spi_set_drvdata(struct spi_device *spi, void *data)
+{
+	dev_set_drvdata(&spi->dev, data);
+}
+
+static inline void *spi_get_drvdata(struct spi_device *spi)
+{
+	return dev_get_drvdata(&spi->dev);
+}
 
 struct spi_message;
 
@@ -137,13 +148,11 @@
 
 static inline void spi_unregister_driver(struct spi_driver *sdrv)
 {
-	if (!sdrv)
-		return;
-	driver_unregister(&sdrv->driver);
+	if (sdrv)
+		driver_unregister(&sdrv->driver);
 }
 
 
-
 /**
  * struct spi_master - interface to SPI master controller
  * @cdev: class interface to this driver
@@ -154,7 +163,8 @@
  *	each slave has a chipselect signal, but it's common that not
  *	every chipselect is connected to a slave.
  * @setup: updates the device mode and clocking records used by a
- *	device's SPI controller; protocol code may call this.
+ *	device's SPI controller; protocol code may call this.  This
+ *	must fail if an unrecognized or unsupported mode is requested.
  * @transfer: adds a message to the controller's transfer queue.
  * @cleanup: frees controller-specific state
  *
@@ -211,7 +221,7 @@
 						struct spi_message *mesg);
 
 	/* called on release() to free memory provided by spi_master */
-	void			(*cleanup)(const struct spi_device *spi);
+	void			(*cleanup)(struct spi_device *spi);
 };
 
 static inline void *spi_master_get_devdata(struct spi_master *master)
@@ -296,6 +306,16 @@
  * shifting out three bytes with word size of sixteen or twenty bits;
  * the former uses two bytes per word, the latter uses four bytes.)
  *
+ * In-memory data values are always in native CPU byte order, translated
+ * from the wire byte order (big-endian except with SPI_LSB_FIRST).  So
+ * for example when bits_per_word is sixteen, buffers are 2N bytes long
+ * and hold N sixteen bit words in CPU byte order.
+ *
+ * When the word size of the SPI transfer is not a power-of-two multiple
+ * of eight bits, those in-memory words include extra bits.  In-memory
+ * words are always seen by protocol drivers as right-justified, so the
+ * undefined (rx) or unused (tx) bits are always the most significant bits.
+ *
  * All SPI transfers start with the relevant chipselect active.  Normally
  * it stays selected until after the last transfer in a message.  Drivers
  * can affect the chipselect signal using cs_change:
@@ -453,6 +473,11 @@
  * changes those settings, and must be called from a context that can sleep.
  * The changes take effect the next time the device is selected and data
  * is transferred to or from it.
+ *
+ * Note that this call wil fail if the protocol driver specifies an option
+ * that the underlying controller or its driver does not support.  For
+ * example, not all hardware supports wire transfers using nine bit words,
+ * LSB-first wire encoding, or active-high chipselects.
  */
 static inline int
 spi_setup(struct spi_device *spi)
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index 16ce178..2e8c048 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -55,7 +55,7 @@
  * methods, if you like.
  */
 extern int spi_bitbang_setup(struct spi_device *spi);
-extern void spi_bitbang_cleanup(const struct spi_device *spi);
+extern void spi_bitbang_cleanup(struct spi_device *spi);
 extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
 extern int spi_bitbang_setup_transfer(struct spi_device *spi,
 				      struct spi_transfer *t);
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 94b767d..61fef37 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -228,15 +228,30 @@
 # define read_unlock_irq(lock)		_read_unlock_irq(lock)
 # define write_unlock_irq(lock)		_write_unlock_irq(lock)
 #else
-# define spin_unlock(lock)		__raw_spin_unlock(&(lock)->raw_lock)
-# define read_unlock(lock)		__raw_read_unlock(&(lock)->raw_lock)
-# define write_unlock(lock)		__raw_write_unlock(&(lock)->raw_lock)
-# define spin_unlock_irq(lock) \
-    do { __raw_spin_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0)
-# define read_unlock_irq(lock) \
-    do { __raw_read_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0)
-# define write_unlock_irq(lock) \
-    do { __raw_write_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0)
+# define spin_unlock(lock) \
+    do {__raw_spin_unlock(&(lock)->raw_lock); __release(lock); } while (0)
+# define read_unlock(lock) \
+    do {__raw_read_unlock(&(lock)->raw_lock); __release(lock); } while (0)
+# define write_unlock(lock) \
+    do {__raw_write_unlock(&(lock)->raw_lock); __release(lock); } while (0)
+# define spin_unlock_irq(lock)			\
+do {						\
+	__raw_spin_unlock(&(lock)->raw_lock);	\
+	__release(lock);			\
+	local_irq_enable();			\
+} while (0)
+# define read_unlock_irq(lock)			\
+do {						\
+	__raw_read_unlock(&(lock)->raw_lock);	\
+	__release(lock);			\
+	local_irq_enable();			\
+} while (0)
+# define write_unlock_irq(lock)			\
+do {						\
+	__raw_write_unlock(&(lock)->raw_lock);	\
+	__release(lock);			\
+	local_irq_enable();			\
+} while (0)
 #endif
 
 #define spin_unlock_irqrestore(lock, flags) \
diff --git a/include/linux/stat.h b/include/linux/stat.h
index 679ef0d..4f8539c 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -7,7 +7,7 @@
 
 #endif
 
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+#ifdef __KERNEL__
 
 #define S_IFMT  00170000
 #define S_IFSOCK 0140000
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index a1be89d..c7a78eef2 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -40,6 +40,7 @@
 
 	unsigned int		cl_softrtry : 1,/* soft timeouts */
 				cl_intr     : 1,/* interruptible */
+				cl_discrtry : 1,/* disconnect before retry */
 				cl_autobind : 1,/* use getport() */
 				cl_oneshot  : 1,/* dispose after use */
 				cl_dead     : 1;/* abandoned */
@@ -111,6 +112,7 @@
 #define RPC_CLNT_CREATE_ONESHOT		(1UL << 3)
 #define RPC_CLNT_CREATE_NONPRIVPORT	(1UL << 4)
 #define RPC_CLNT_CREATE_NOPING		(1UL << 5)
+#define RPC_CLNT_CREATE_DISCRTRY	(1UL << 6)
 
 struct rpc_clnt *rpc_create(struct rpc_create_args *args);
 struct rpc_clnt	*rpc_bind_new_program(struct rpc_clnt *,
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 60fce3c..b7c7307 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -78,7 +78,6 @@
  * module currently registers its sysctl table dynamically, the sysctl path
  * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
  */
-#define CTL_SUNRPC	7249	/* arbitrary and hopefully unused */
 
 enum {
 	CTL_RPCDEBUG = 1,
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 8b6ce60..3069ecc 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -150,10 +150,10 @@
 #define RPC_TASK_HAS_TIMER	3
 #define RPC_TASK_ACTIVE		4
 
-#define RPC_IS_RUNNING(t)	(test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
-#define rpc_set_running(t)	(set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
+#define RPC_IS_RUNNING(t)	test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
+#define rpc_set_running(t)	set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
 #define rpc_test_and_set_running(t) \
-				(test_and_set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
+				test_and_set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
 #define rpc_clear_running(t)	\
 	do { \
 		smp_mb__before_clear_bit(); \
@@ -161,8 +161,8 @@
 		smp_mb__after_clear_bit(); \
 	} while (0)
 
-#define RPC_IS_QUEUED(t)	(test_bit(RPC_TASK_QUEUED, &(t)->tk_runstate))
-#define rpc_set_queued(t)	(set_bit(RPC_TASK_QUEUED, &(t)->tk_runstate))
+#define RPC_IS_QUEUED(t)	test_bit(RPC_TASK_QUEUED, &(t)->tk_runstate)
+#define rpc_set_queued(t)	set_bit(RPC_TASK_QUEUED, &(t)->tk_runstate)
 #define rpc_clear_queued(t)	\
 	do { \
 		smp_mb__before_clear_bit(); \
@@ -179,7 +179,7 @@
 		smp_mb__after_clear_bit(); \
 	} while (0)
 
-#define RPC_IS_ACTIVATED(t)	(test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate))
+#define RPC_IS_ACTIVATED(t)	test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)
 
 /*
  * Task priorities.
@@ -253,7 +253,7 @@
 void		rpc_exit_task(struct rpc_task *);
 void		rpc_release_calldata(const struct rpc_call_ops *, void *);
 void		rpc_killall_tasks(struct rpc_clnt *);
-int		rpc_execute(struct rpc_task *);
+void		rpc_execute(struct rpc_task *);
 void		rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
 void		rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
 void		rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 64f3d60..83b3c7b 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -11,6 +11,7 @@
 #define SUNRPC_SVC_H
 
 #include <linux/in.h>
+#include <linux/in6.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/auth.h>
@@ -191,7 +192,13 @@
 	iov->iov_len += sizeof(__be32);
 }
 
-	
+union svc_addr_u {
+    struct in_addr	addr;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+    struct in6_addr	addr6;
+#endif
+};
+
 /*
  * The context of a single thread, including the request currently being
  * processed.
@@ -200,8 +207,8 @@
 	struct list_head	rq_list;	/* idle list */
 	struct list_head	rq_all;		/* all threads list */
 	struct svc_sock *	rq_sock;	/* socket */
-	struct sockaddr_in	rq_addr;	/* peer address */
-	int			rq_addrlen;
+	struct sockaddr_storage	rq_addr;	/* peer address */
+	size_t			rq_addrlen;
 
 	struct svc_serv *	rq_server;	/* RPC service definition */
 	struct svc_pool *	rq_pool;	/* thread pool */
@@ -227,8 +234,8 @@
 	unsigned short
 				rq_secure  : 1;	/* secure port */
 
-
-	__be32			rq_daddr;	/* dest addr of request - reply from here */
+	union svc_addr_u	rq_daddr;	/* dest addr of request
+						 *  - reply from here */
 
 	void *			rq_argp;	/* decoded arguments */
 	void *			rq_resp;	/* xdr'd results */
@@ -256,6 +263,24 @@
 };
 
 /*
+ * Rigorous type checking on sockaddr type conversions
+ */
+static inline struct sockaddr_in *svc_addr_in(struct svc_rqst *rqst)
+{
+	return (struct sockaddr_in *) &rqst->rq_addr;
+}
+
+static inline struct sockaddr_in6 *svc_addr_in6(struct svc_rqst *rqst)
+{
+	return (struct sockaddr_in6 *) &rqst->rq_addr;
+}
+
+static inline struct sockaddr *svc_addr(struct svc_rqst *rqst)
+{
+	return (struct sockaddr *) &rqst->rq_addr;
+}
+
+/*
  * Check buffer bounds after decoding arguments
  */
 static inline int
@@ -292,9 +317,10 @@
 
 struct svc_deferred_req {
 	u32			prot;	/* protocol (UDP or TCP) */
-	struct sockaddr_in	addr;
-	struct svc_sock		*svsk;	/* where reply must go */
-	__be32			daddr;	/* where reply must come from */
+	struct svc_sock		*svsk;
+	struct sockaddr_storage	addr;	/* where reply must go */
+	size_t			addrlen;
+	union svc_addr_u	daddr;	/* where reply must come from */
 	struct cache_deferred_req handle;
 	int			argslen;
 	__be32			args[0];
@@ -368,5 +394,8 @@
 void		   svc_wake_up(struct svc_serv *);
 void		   svc_reserve(struct svc_rqst *rqstp, int space);
 struct svc_pool *  svc_pool_for_cpu(struct svc_serv *serv, int cpu);
+char *		   svc_print_addr(struct svc_rqst *, char *, size_t);
+
+#define	RPC_MAX_ADDRBUFLEN	(63U)
 
 #endif /* SUNRPC_SVC_H */
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 98b21ad..cccea0a 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -57,13 +57,16 @@
 
 	/* cache of various info for TCP sockets */
 	void			*sk_info_authunix;
+
+	struct sockaddr_storage	sk_remote;	/* remote peer's address */
+	int			sk_remotelen;	/* length of address */
 };
 
 /*
  * Function prototypes.
  */
-int		svc_makesock(struct svc_serv *, int, unsigned short);
-void		svc_delete_socket(struct svc_sock *);
+int		svc_makesock(struct svc_serv *, int, unsigned short, int flags);
+void		svc_close_socket(struct svc_sock *);
 int		svc_recv(struct svc_rqst *, long);
 int		svc_send(struct svc_rqst *);
 void		svc_drop(struct svc_rqst *);
@@ -74,4 +77,11 @@
 			    char *name_return,
 			    int *proto);
 
+/*
+ * svc_makesock socket characteristics
+ */
+#define SVC_SOCK_DEFAULTS	(0U)
+#define SVC_SOCK_ANONYMOUS	(1U << 0)	/* don't register with pmap */
+#define SVC_SOCK_TEMPORARY	(1U << 1)	/* flag socket as temporary */
+
 #endif /* SUNRPC_SVCSOCK_H */
diff --git a/include/linux/svga.h b/include/linux/svga.h
new file mode 100644
index 0000000..eadb981
--- /dev/null
+++ b/include/linux/svga.h
@@ -0,0 +1,124 @@
+#ifndef _LINUX_SVGA_H
+#define _LINUX_SVGA_H
+
+#ifdef __KERNEL__
+
+#include <linux/pci.h>
+#include <video/vga.h>
+
+/* Terminator for register set */
+
+#define VGA_REGSET_END_VAL	0xFF
+#define VGA_REGSET_END		{VGA_REGSET_END_VAL, 0, 0}
+
+struct vga_regset {
+	u8 regnum;
+	u8 lowbit;
+	u8 highbit;
+};
+
+/* ------------------------------------------------------------------------- */
+
+#define SVGA_FORMAT_END_VAL	0xFFFF
+#define SVGA_FORMAT_END		{SVGA_FORMAT_END_VAL, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, 0, 0, 0, 0, 0, 0}
+
+struct svga_fb_format {
+	/* var part */
+	u32 bits_per_pixel;
+	struct fb_bitfield red;
+	struct fb_bitfield green;
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;
+	u32 nonstd;
+	/* fix part */
+	u32 type;
+	u32 type_aux;
+	u32 visual;
+	u32 xpanstep;
+	u32 xresstep;
+};
+
+struct svga_timing_regs {
+	const struct vga_regset *h_total_regs;
+	const struct vga_regset *h_display_regs;
+	const struct vga_regset *h_blank_start_regs;
+	const struct vga_regset *h_blank_end_regs;
+	const struct vga_regset *h_sync_start_regs;
+	const struct vga_regset *h_sync_end_regs;
+
+	const struct vga_regset *v_total_regs;
+	const struct vga_regset *v_display_regs;
+	const struct vga_regset *v_blank_start_regs;
+	const struct vga_regset *v_blank_end_regs;
+	const struct vga_regset *v_sync_start_regs;
+	const struct vga_regset *v_sync_end_regs;
+};
+
+struct svga_pll {
+	u16 m_min;
+	u16 m_max;
+	u16 n_min;
+	u16 n_max;
+	u16 r_min;
+	u16 r_max;  /* r_max < 32 */
+	u32 f_vco_min;
+	u32 f_vco_max;
+	u32 f_base;
+};
+
+
+/* Write a value to the attribute register */
+
+static inline void svga_wattr(u8 index, u8 data)
+{
+	inb(0x3DA);
+	outb(index, 0x3C0);
+	outb(data, 0x3C0);
+}
+
+/* Write a value to a sequence register with a mask */
+
+static inline void svga_wseq_mask(u8 index, u8 data, u8 mask)
+{
+	vga_wseq(NULL, index, (data & mask) | (vga_rseq(NULL, index) & ~mask));
+}
+
+/* Write a value to a CRT register with a mask */
+
+static inline void svga_wcrt_mask(u8 index, u8 data, u8 mask)
+{
+	vga_wcrt(NULL, index, (data & mask) | (vga_rcrt(NULL, index) & ~mask));
+}
+
+static inline int svga_primary_device(struct pci_dev *dev)
+{
+	u16 flags;
+	pci_read_config_word(dev, PCI_COMMAND, &flags);
+	return (flags & PCI_COMMAND_IO);
+}
+
+
+void svga_wcrt_multi(const struct vga_regset *regset, u32 value);
+void svga_wseq_multi(const struct vga_regset *regset, u32 value);
+
+void svga_set_default_gfx_regs(void);
+void svga_set_default_atc_regs(void);
+void svga_set_default_seq_regs(void);
+void svga_set_default_crt_regs(void);
+void svga_set_textmode_vga_regs(void);
+
+void svga_settile(struct fb_info *info, struct fb_tilemap *map);
+void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area);
+void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect);
+void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit);
+void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor);
+
+int svga_compute_pll(const struct svga_pll *pll, u32 f_wanted, u16 *m, u16 *n, u16 *r, int node);
+int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, int node);
+void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node);
+
+int svga_match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix);
+
+#endif /* __KERNEL__  */
+#endif /* _LINUX_SVGA_H */
+
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 5423559..0068688 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -170,11 +170,13 @@
 extern unsigned long totalram_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);
 extern unsigned int nr_free_buffer_pages(void);
 extern unsigned int nr_free_pagecache_pages(void);
 
+/* Definition of global_page_state not available yet */
+#define nr_free_pages() global_page_state(NR_FREE_PAGES)
+
+
 /* linux/mm/swap.c */
 extern void FASTCALL(lru_cache_add(struct page *));
 extern void FASTCALL(lru_cache_add_active(struct page *));
diff --git a/include/linux/swapops.h b/include/linux/swapops.h
index ec639aa..ceb6cc5 100644
--- a/include/linux/swapops.h
+++ b/include/linux/swapops.h
@@ -108,7 +108,10 @@
 #else
 
 #define make_migration_entry(page, write) swp_entry(0, 0)
-#define is_migration_entry(swp) 0
+static inline int is_migration_entry(swp_entry_t swp)
+{
+	return 0;
+}
 #define migration_entry_to_page(swp) NULL
 static inline void make_migration_entry_read(swp_entry_t *entryp) { }
 static inline void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 81480e6..2c5fb38 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -53,7 +53,6 @@
 
 /* For internal pattern-matching use only: */
 #ifdef __KERNEL__
-#define CTL_ANY		-1	/* Matches any name */
 #define CTL_NONE	0
 #define CTL_UNNUMBERED	CTL_NONE	/* sysctl without a binary number */
 #endif
@@ -69,7 +68,13 @@
 	CTL_DEV=7,		/* Devices */
 	CTL_BUS=8,		/* Busses */
 	CTL_ABI=9,		/* Binary emulation */
-	CTL_CPU=10		/* CPU stuff (speed scaling, etc) */
+	CTL_CPU=10,		/* CPU stuff (speed scaling, etc) */
+	CTL_ARLAN=254,		/* arlan wireless driver */
+	CTL_APPLDATA=2120,	/* s390 appldata */
+	CTL_S390DBF=5677,	/* s390 debug */
+	CTL_SUNRPC=7249,	/* sunrpc debug */
+	CTL_PM=9899,		/* frv power management */
+	CTL_FRV=9898,		/* frv specific sysctls */
 };
 
 /* CTL_BUS names: */
@@ -202,6 +207,11 @@
 	VM_PANIC_ON_OOM=33,	/* panic at out-of-memory */
 	VM_VDSO_ENABLED=34,	/* map VDSO into new processes? */
 	VM_MIN_SLAB=35,		 /* Percent pages ignored by zone reclaim */
+
+	/* s390 vm cmm sysctls */
+	VM_CMM_PAGES=1111,
+	VM_CMM_TIMED_PAGES=1112,
+	VM_CMM_TIMEOUT=1113,
 };
 
 
@@ -699,7 +709,8 @@
 	NET_X25_CALL_REQUEST_TIMEOUT=2,
 	NET_X25_RESET_REQUEST_TIMEOUT=3,
 	NET_X25_CLEAR_REQUEST_TIMEOUT=4,
-	NET_X25_ACK_HOLD_BACK_TIMEOUT=5
+	NET_X25_ACK_HOLD_BACK_TIMEOUT=5,
+	NET_X25_FORWARD=6
 };
 
 /* /proc/sys/net/token-ring */
@@ -802,6 +813,7 @@
 	FS_AIO_NR=18,	/* current system-wide number of aio requests */
 	FS_AIO_MAX_NR=19,	/* system-wide maximum number of aio requests */
 	FS_INOTIFY=20,	/* inotify submenu */
+	FS_OCFS2=988,	/* ocfs2 */
 };
 
 /* /proc/sys/fs/quota/ */
@@ -912,7 +924,11 @@
 #ifdef __KERNEL__
 #include <linux/list.h>
 
-extern void sysctl_init(void);
+/* For the /proc/sys support */
+struct ctl_table;
+extern struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev);
+extern void sysctl_head_finish(struct ctl_table_header *prev);
+extern int sysctl_perm(struct ctl_table *table, int op);
 
 typedef struct ctl_table ctl_table;
 
@@ -1006,9 +1022,9 @@
 	int maxlen;
 	mode_t mode;
 	ctl_table *child;
+	ctl_table *parent;		/* Automatically set */
 	proc_handler *proc_handler;	/* Callback for text formatting */
 	ctl_handler *strategy;		/* Callback function for all r/w */
-	struct proc_dir_entry *de;	/* /proc control block */
 	void *extra1;
 	void *extra2;
 };
@@ -1023,8 +1039,8 @@
 	struct completion *unregistering;
 };
 
-struct ctl_table_header * register_sysctl_table(ctl_table * table, 
-						int insert_at_head);
+struct ctl_table_header * register_sysctl_table(ctl_table * table);
+
 void unregister_sysctl_table(struct ctl_table_header * table);
 
 #else /* __KERNEL__ */
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 192de3a..21805b5 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -17,6 +17,7 @@
 struct kobject;
 struct module;
 struct nameidata;
+struct dentry;
 
 struct attribute {
 	const char		* name;
@@ -68,18 +69,6 @@
 	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
 };
 
-struct sysfs_dirent {
-	atomic_t		s_count;
-	struct list_head	s_sibling;
-	struct list_head	s_children;
-	void 			* s_element;
-	int			s_type;
-	umode_t			s_mode;
-	struct dentry		* s_dentry;
-	struct iattr		* s_iattr;
-	atomic_t		s_event;
-};
-
 #define SYSFS_ROOT		0x0001
 #define SYSFS_DIR		0x0002
 #define SYSFS_KOBJ_ATTR 	0x0004
@@ -126,6 +115,11 @@
 int __must_check sysfs_create_group(struct kobject *,
 					const struct attribute_group *);
 void sysfs_remove_group(struct kobject *, const struct attribute_group *);
+int sysfs_add_file_to_group(struct kobject *kobj,
+		const struct attribute *attr, const char *group);
+void sysfs_remove_file_from_group(struct kobject *kobj,
+		const struct attribute *attr, const char *group);
+
 void sysfs_notify(struct kobject * k, char *dir, char *attr);
 
 
@@ -210,6 +204,18 @@
 	;
 }
 
+static inline int sysfs_add_file_to_group(struct kobject *kobj,
+		const struct attribute *attr, const char *group)
+{
+	return 0;
+}
+
+static inline void sysfs_remove_file_from_group(struct kobject *kobj,
+		const struct attribute *attr, const char *group);
+{
+	;
+}
+
 static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
 {
 }
diff --git a/include/linux/tc.h b/include/linux/tc.h
new file mode 100644
index 0000000..f92511e
--- /dev/null
+++ b/include/linux/tc.h
@@ -0,0 +1,141 @@
+/*
+ *	Interface to the TURBOchannel related routines.
+ *
+ *	Copyright (c) 1998  Harald Koerfgen
+ *	Copyright (c) 2005  James Simmons
+ *	Copyright (c) 2006  Maciej W. Rozycki
+ *
+ *	Based on:
+ *
+ *	"TURBOchannel Firmware Specification", EK-TCAAD-FS-004
+ *
+ *	from Digital Equipment Corporation.
+ *
+ *	This file is subject to the terms and conditions of the GNU
+ *	General Public License.  See the file "COPYING" in the main
+ *	directory of this archive for more details.
+ */
+#ifndef _LINUX_TC_H
+#define _LINUX_TC_H
+
+#include <linux/compiler.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+
+/*
+ * Offsets for the ROM header locations for TURBOchannel cards.
+ */
+#define TC_OLDCARD	0x3c0000
+#define TC_NEWCARD	0x000000
+
+#define TC_ROM_WIDTH	0x3e0
+#define TC_ROM_STRIDE	0x3e4
+#define TC_ROM_SIZE	0x3e8
+#define TC_SLOT_SIZE	0x3ec
+#define TC_PATTERN0	0x3f0
+#define TC_PATTERN1	0x3f4
+#define TC_PATTERN2	0x3f8
+#define TC_PATTERN3	0x3fc
+#define TC_FIRM_VER	0x400
+#define TC_VENDOR	0x420
+#define TC_MODULE	0x440
+#define TC_FIRM_TYPE	0x460
+#define TC_FLAGS	0x470
+#define TC_ROM_OBJECTS	0x480
+
+/*
+ * Information obtained through the get_tcinfo() PROM call.
+ */
+struct tcinfo {
+	s32		revision;	/* Hardware revision level. */
+	s32		clk_period;	/* Clock period in nanoseconds. */
+	s32		slot_size;	/* Slot size in megabytes. */
+	s32		io_timeout;	/* I/O timeout in cycles. */
+	s32		dma_range;	/* DMA address range in megabytes. */
+	s32		max_dma_burst;	/* Maximum DMA burst length. */
+	s32		parity;		/* System module supports TC parity. */
+	s32		reserved[4];
+};
+
+/*
+ * TURBOchannel bus.
+ */
+struct tc_bus {
+	struct list_head devices;	/* List of devices on this bus. */
+	struct resource	resource[2];	/* Address space routed to this bus. */
+
+	struct device	dev;
+	char		name[13];
+	resource_size_t	slot_base;
+	resource_size_t	ext_slot_base;
+	resource_size_t	ext_slot_size;
+	int		num_tcslots;
+	struct tcinfo	info;
+};
+
+/*
+ * TURBOchannel device.
+ */
+struct tc_dev {
+	struct list_head node;		/* Node in list of all TC devices. */
+	struct tc_bus	*bus;		/* Bus this device is on. */
+	struct tc_driver *driver;	/* Which driver has allocated this
+					   device. */
+	struct device	dev;		/* Generic device interface. */
+	struct resource	resource;	/* Address space of this device. */
+	char		vendor[9];
+	char		name[9];
+	char		firmware[9];
+	int		interrupt;
+	int		slot;
+};
+
+#define to_tc_dev(n) container_of(n, struct tc_dev, dev)
+
+struct tc_device_id {
+	char		vendor[9];
+	char		name[9];
+};
+
+/*
+ * TURBOchannel driver.
+ */
+struct tc_driver {
+	struct list_head node;
+	const struct tc_device_id *id_table;
+	struct device_driver driver;
+};
+
+#define to_tc_driver(drv) container_of(drv, struct tc_driver, driver)
+
+/*
+ * Return TURBOchannel clock frequency in Hz.
+ */
+static inline unsigned long tc_get_speed(struct tc_bus *tbus)
+{
+	return 100000 * (10000 / (unsigned long)tbus->info.clk_period);
+}
+
+#ifdef CONFIG_TC
+
+extern struct bus_type tc_bus_type;
+
+extern int tc_register_driver(struct tc_driver *tdrv);
+extern void tc_unregister_driver(struct tc_driver *tdrv);
+
+#else /* !CONFIG_TC */
+
+static inline int tc_register_driver(struct tc_driver *tdrv) { return 0; }
+static inline void tc_unregister_driver(struct tc_driver *tdrv) { }
+
+#endif /* CONFIG_TC */
+
+/*
+ * These have to be provided by the architecture.
+ */
+extern int tc_preadb(u8 *valp, void __iomem *addr);
+extern int tc_bus_get_info(struct tc_bus *tbus);
+extern void tc_device_get_irq(struct tc_dev *tdev);
+
+#endif /* _LINUX_TC_H */
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 3cc70d1..29d3089 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -316,7 +316,7 @@
 	struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
 	struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
 
-	struct tcp_sack_block recv_sack_cache[4];
+	struct tcp_sack_block_wire recv_sack_cache[4];
 
 	/* from STCP, retrans queue hinting */
 	struct sk_buff* lost_skb_hint;
diff --git a/include/linux/tick.h b/include/linux/tick.h
new file mode 100644
index 0000000..9a7252e
--- /dev/null
+++ b/include/linux/tick.h
@@ -0,0 +1,109 @@
+/*  linux/include/linux/tick.h
+ *
+ *  This file contains the structure definitions for tick related functions
+ *
+ */
+#ifndef _LINUX_TICK_H
+#define _LINUX_TICK_H
+
+#include <linux/clockchips.h>
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+
+enum tick_device_mode {
+	TICKDEV_MODE_PERIODIC,
+	TICKDEV_MODE_ONESHOT,
+};
+
+struct tick_device {
+	struct clock_event_device *evtdev;
+	enum tick_device_mode mode;
+};
+
+enum tick_nohz_mode {
+	NOHZ_MODE_INACTIVE,
+	NOHZ_MODE_LOWRES,
+	NOHZ_MODE_HIGHRES,
+};
+
+/**
+ * struct tick_sched - sched tick emulation and no idle tick control/stats
+ * @sched_timer:	hrtimer to schedule the periodic tick in high
+ *			resolution mode
+ * @idle_tick:		Store the last idle tick expiry time when the tick
+ *			timer is modified for idle sleeps. This is necessary
+ *			to resume the tick timer operation in the timeline
+ *			when the CPU returns from idle
+ * @tick_stopped:	Indicator that the idle tick has been stopped
+ * @idle_jiffies:	jiffies at the entry to idle for idle time accounting
+ * @idle_calls:		Total number of idle calls
+ * @idle_sleeps:	Number of idle calls, where the sched tick was stopped
+ * @idle_entrytime:	Time when the idle call was entered
+ * @idle_sleeptime:	Sum of the time slept in idle with sched tick stopped
+ */
+struct tick_sched {
+	struct hrtimer			sched_timer;
+	unsigned long			check_clocks;
+	enum tick_nohz_mode		nohz_mode;
+	ktime_t				idle_tick;
+	int				tick_stopped;
+	unsigned long			idle_jiffies;
+	unsigned long			idle_calls;
+	unsigned long			idle_sleeps;
+	ktime_t				idle_entrytime;
+	ktime_t				idle_sleeptime;
+	unsigned long			last_jiffies;
+	unsigned long			next_jiffies;
+	ktime_t				idle_expires;
+};
+
+extern void __init tick_init(void);
+extern int tick_is_oneshot_available(void);
+extern struct tick_device *tick_get_device(int cpu);
+
+# ifdef CONFIG_HIGH_RES_TIMERS
+extern int tick_init_highres(void);
+extern int tick_program_event(ktime_t expires, int force);
+extern void tick_setup_sched_timer(void);
+extern void tick_cancel_sched_timer(int cpu);
+# else
+static inline void tick_cancel_sched_timer(int cpu) { }
+# endif /* HIGHRES */
+
+# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+extern struct tick_device *tick_get_broadcast_device(void);
+extern cpumask_t *tick_get_broadcast_mask(void);
+
+#  ifdef CONFIG_TICK_ONESHOT
+extern cpumask_t *tick_get_broadcast_oneshot_mask(void);
+#  endif
+
+# endif /* BROADCAST */
+
+# ifdef CONFIG_TICK_ONESHOT
+extern void tick_clock_notify(void);
+extern int tick_check_oneshot_change(int allow_nohz);
+extern struct tick_sched *tick_get_tick_sched(int cpu);
+# else
+static inline void tick_clock_notify(void) { }
+static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
+# endif
+
+#else /* CONFIG_GENERIC_CLOCKEVENTS */
+static inline void tick_init(void) { }
+static inline void tick_cancel_sched_timer(int cpu) { }
+static inline void tick_clock_notify(void) { }
+static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
+
+# ifdef CONFIG_NO_HZ
+extern void tick_nohz_stop_sched_tick(void);
+extern void tick_nohz_restart_sched_tick(void);
+extern void tick_nohz_update_jiffies(void);
+# else
+static inline void tick_nohz_stop_sched_tick(void) { }
+static inline void tick_nohz_restart_sched_tick(void) { }
+static inline void tick_nohz_update_jiffies(void) { }
+# endif /* !NO_HZ */
+
+#endif
diff --git a/include/linux/time.h b/include/linux/time.h
index a5b7399..8ea8dea 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -46,7 +46,7 @@
  * lhs == rhs: return 0
  * lhs > rhs:  return >0
  */
-static inline int timespec_compare(struct timespec *lhs, struct timespec *rhs)
+static inline int timespec_compare(const struct timespec *lhs, const struct timespec *rhs)
 {
 	if (lhs->tv_sec < rhs->tv_sec)
 		return -1;
@@ -55,7 +55,7 @@
 	return lhs->tv_nsec - rhs->tv_nsec;
 }
 
-static inline int timeval_compare(struct timeval *lhs, struct timeval *rhs)
+static inline int timeval_compare(const struct timeval *lhs, const struct timeval *rhs)
 {
 	if (lhs->tv_sec < rhs->tv_sec)
 		return -1;
@@ -90,8 +90,9 @@
 
 extern struct timespec xtime;
 extern struct timespec wall_to_monotonic;
-extern seqlock_t xtime_lock;
+extern seqlock_t xtime_lock __attribute__((weak));
 
+extern unsigned long read_persistent_clock(void);
 void timekeeping_init(void);
 
 static inline unsigned long get_seconds(void)
diff --git a/include/linux/timer.h b/include/linux/timer.h
index fb5edaa..719113b 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -2,6 +2,7 @@
 #define _LINUX_TIMER_H
 
 #include <linux/list.h>
+#include <linux/ktime.h>
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
 
@@ -15,6 +16,11 @@
 	unsigned long data;
 
 	struct tvec_t_base_s *base;
+#ifdef CONFIG_TIMER_STATS
+	void *start_site;
+	char start_comm[16];
+	int start_pid;
+#endif
 };
 
 extern struct tvec_t_base_s boot_tvec_bases;
@@ -61,7 +67,65 @@
 extern int __mod_timer(struct timer_list *timer, unsigned long expires);
 extern int mod_timer(struct timer_list *timer, unsigned long expires);
 
+/*
+ * Return when the next timer-wheel timeout occurs (in absolute jiffies),
+ * locks the timer base:
+ */
 extern unsigned long next_timer_interrupt(void);
+/*
+ * Return when the next timer-wheel timeout occurs (in absolute jiffies),
+ * locks the timer base and does the comparison against the given
+ * jiffie.
+ */
+extern unsigned long get_next_timer_interrupt(unsigned long now);
+
+/*
+ * Timer-statistics info:
+ */
+#ifdef CONFIG_TIMER_STATS
+
+extern void init_timer_stats(void);
+
+extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
+				     void *timerf, char * comm);
+
+static inline void timer_stats_account_timer(struct timer_list *timer)
+{
+	timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
+				 timer->function, timer->start_comm);
+}
+
+extern void __timer_stats_timer_set_start_info(struct timer_list *timer,
+					       void *addr);
+
+static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
+{
+	__timer_stats_timer_set_start_info(timer, __builtin_return_address(0));
+}
+
+static inline void timer_stats_timer_clear_start_info(struct timer_list *timer)
+{
+	timer->start_site = NULL;
+}
+#else
+static inline void init_timer_stats(void)
+{
+}
+
+static inline void timer_stats_account_timer(struct timer_list *timer)
+{
+}
+
+static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
+{
+}
+
+static inline void timer_stats_timer_clear_start_info(struct timer_list *timer)
+{
+}
+#endif
+
+extern void delayed_work_timer_fn(unsigned long __data);
 
 /**
  * add_timer - start a timer
@@ -96,7 +160,7 @@
 extern void init_timers(void);
 extern void run_local_timers(void);
 struct hrtimer;
-extern int it_real_fn(struct hrtimer *);
+extern enum hrtimer_restart it_real_fn(struct hrtimer *);
 
 unsigned long __round_jiffies(unsigned long j, int cpu);
 unsigned long __round_jiffies_relative(unsigned long j, int cpu);
diff --git a/include/linux/timex.h b/include/linux/timex.h
index db501dc..da929db 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -255,10 +255,10 @@
 	u8 jitter;			/* if set compensate for fluctuations */
 	u32 nsec_per_cyc;		/* set by register_time_interpolator() */
 	void *addr;			/* address of counter or function */
-	u64 mask;			/* mask the valid bits of the counter */
+	cycles_t mask;			/* mask the valid bits of the counter */
 	unsigned long offset;		/* nsec offset at last update of interpolator */
 	u64 last_counter;		/* counter value in units of the counter at last update */
-	u64 last_cycle;			/* Last timer value if TIME_SOURCE_JITTER is set */
+	cycles_t last_cycle;		/* Last timer value if TIME_SOURCE_JITTER is set */
 	u64 frequency;			/* frequency in counts/second */
 	long drift;			/* drift in parts-per-million (or -1) */
 	unsigned long skips;		/* skips forward */
@@ -286,6 +286,13 @@
 
 #define TICK_LENGTH_SHIFT	32
 
+#ifdef CONFIG_NO_HZ
+#define NTP_INTERVAL_FREQ  (2)
+#else
+#define NTP_INTERVAL_FREQ  (HZ)
+#endif
+#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
+
 /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
 extern u64 current_tick_length(void);
 
diff --git a/include/linux/toshiba.h b/include/linux/toshiba.h
index 916e5e3..6a7c4ed 100644
--- a/include/linux/toshiba.h
+++ b/include/linux/toshiba.h
@@ -33,4 +33,6 @@
 	unsigned int edi __attribute__ ((packed));
 } SMMRegisters;
 
+int tosh_smm(SMMRegisters *regs);
+
 #endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 65cbcf2..dee72b9 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -24,7 +24,27 @@
 #define NR_PTYS	CONFIG_LEGACY_PTY_COUNT   /* Number of legacy ptys */
 #define NR_UNIX98_PTY_DEFAULT	4096      /* Default maximum for Unix98 ptys */
 #define NR_UNIX98_PTY_MAX	(1 << MINORBITS) /* Absolute limit */
-#define NR_LDISCS		16
+#define NR_LDISCS		17
+
+/* line disciplines */
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+#define N_STRIP		4
+#define N_AX25		5
+#define N_X25		6	/* X.25 async */
+#define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data */
+				/* cards about SMS messages */
+#define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14	/* synchronous PPP */
+#define N_HCI		15	/* Bluetooth HCI UART */
+#define N_GIGASET_M101	16	/* Siemens Gigaset M101 serial DECT adapter */
 
 /*
  * This character is the same as _POSIX_VDISABLE: it cannot be used as
@@ -177,8 +197,8 @@
 	struct mutex termios_mutex;
 	struct ktermios *termios, *termios_locked;
 	char name[64];
-	int pgrp;
-	int session;
+	struct pid *pgrp;
+	struct pid *session;
 	unsigned long flags;
 	int count;
 	struct winsize winsize;
@@ -283,7 +303,7 @@
 			     int buflen);
 extern void tty_write_message(struct tty_struct *tty, char *msg);
 
-extern int is_orphaned_pgrp(int pgrp);
+extern int is_current_pgrp_orphaned(void);
 extern int is_ignored(int sig);
 extern int tty_signal(int sig, struct tty_struct *tty);
 extern void tty_hangup(struct tty_struct * tty);
@@ -291,6 +311,7 @@
 extern void tty_unhangup(struct file *filp);
 extern int tty_hung_up_p(struct file * filp);
 extern void do_SAK(struct tty_struct *tty);
+extern void __do_SAK(struct tty_struct *tty);
 extern void disassociate_ctty(int priv);
 extern void tty_flip_buffer_push(struct tty_struct *tty);
 extern speed_t tty_get_baud_rate(struct tty_struct *tty);
@@ -312,7 +333,6 @@
 
 extern dev_t tty_devnum(struct tty_struct *tty);
 extern void proc_clear_tty(struct task_struct *p);
-extern void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 extern void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 extern struct tty_struct *get_current_tty(void);
 
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
index 28967ed..dc2e9fe6 100644
--- a/include/linux/ufs_fs.h
+++ b/include/linux/ufs_fs.h
@@ -40,13 +40,16 @@
 typedef __u32 __fs32;
 typedef __u16 __fs16;
 #else
+#include <asm/div64.h>
 typedef __u64 __bitwise __fs64;
 typedef __u32 __bitwise __fs32;
 typedef __u16 __bitwise __fs16;
 #endif
 
+#ifdef __KERNEL__
 #include <linux/ufs_fs_i.h>
 #include <linux/ufs_fs_sb.h>
+#endif
 
 #define UFS_BBLOCK 0
 #define UFS_BBSIZE 8192
@@ -261,17 +264,10 @@
  */
 #define	ufs_inotocg(x)		((x) / uspi->s_ipg)
 #define	ufs_inotocgoff(x)	((x) % uspi->s_ipg)
-#define	ufs_inotofsba(x)	(ufs_cgimin(ufs_inotocg(x)) + ufs_inotocgoff(x) / uspi->s_inopf)
+#define	ufs_inotofsba(x)	(((u64)ufs_cgimin(ufs_inotocg(x))) + ufs_inotocgoff(x) / uspi->s_inopf)
 #define	ufs_inotofsbo(x)	((x) % uspi->s_inopf)
 
 /*
- * Give cylinder group number for a file system block.
- * Give cylinder group block number for a file system block.
- */
-#define	ufs_dtog(d)	((d) / uspi->s_fpg)
-#define	ufs_dtogd(d)	((d) % uspi->s_fpg)
-
-/*
  * Compute the cylinder and rotational position of a cyl block addr.
  */
 #define ufs_cbtocylno(bno) \
@@ -303,7 +299,7 @@
 #define UFS_MAXMNTLEN 512
 #define UFS2_MAXMNTLEN 468
 #define UFS2_MAXVOLLEN 32
-/* #define UFS_MAXCSBUFS 31 */
+#define UFS_MAXCSBUFS 31
 #define UFS_LINK_MAX 32000
 /*
 #define	UFS2_NOCSPTRS	((128 / sizeof(void *)) - 4)
@@ -721,6 +717,7 @@
 	__u32	c_nclusterblks;	/* number of clusters this cg */
 };	
 
+
 struct ufs_sb_private_info {
 	struct ufs_buffer_head s_ubh; /* buffer containing super block */
 	struct ufs_csum_core cs_total;
@@ -754,7 +751,7 @@
 	__u32	s_npsect;	/* # sectors/track including spares */
 	__u32	s_interleave;	/* hardware sector interleave */
 	__u32	s_trackskew;	/* sector 0 skew, per track */
-	__u32	s_csaddr;	/* blk addr of cyl grp summary area */
+	__u64	s_csaddr;	/* blk addr of cyl grp summary area */
 	__u32	s_cssize;	/* size of cyl grp summary area */
 	__u32	s_cgsize;	/* cylinder group size */
 	__u32	s_ntrak;	/* tracks per cylinder */
@@ -789,6 +786,7 @@
 
 	__u32	s_maxsymlinklen;/* upper limit on fast symlinks' size */
 	__s32	fs_magic;       /* filesystem magic */
+	unsigned int s_dirblksize;
 };
 
 /*
@@ -949,17 +947,17 @@
 #ifdef __KERNEL__
 
 /* balloc.c */
-extern void ufs_free_fragments (struct inode *, unsigned, unsigned);
-extern void ufs_free_blocks (struct inode *, unsigned, unsigned);
-extern unsigned ufs_new_fragments(struct inode *, __fs32 *, unsigned, unsigned,
-				  unsigned, int *, struct page *);
+extern void ufs_free_fragments (struct inode *, u64, unsigned);
+extern void ufs_free_blocks (struct inode *, u64, unsigned);
+extern u64 ufs_new_fragments(struct inode *, void *, u64, u64,
+			     unsigned, int *, struct page *);
 
 /* cylinder.c */
 extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned);
 extern void ufs_put_cylinder (struct super_block *, unsigned);
 
 /* dir.c */
-extern struct inode_operations ufs_dir_inode_operations;
+extern const struct inode_operations ufs_dir_inode_operations;
 extern int ufs_add_link (struct dentry *, struct inode *);
 extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
 extern int ufs_make_empty(struct inode *, struct inode *);
@@ -971,7 +969,7 @@
 			 struct page *page, struct inode *inode);
 
 /* file.c */
-extern struct inode_operations ufs_file_inode_operations;
+extern const struct inode_operations ufs_file_inode_operations;
 extern const struct file_operations ufs_file_operations;
 
 extern const struct address_space_operations ufs_aops;
@@ -998,7 +996,7 @@
 extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 
 /* symlink.c */
-extern struct inode_operations ufs_fast_symlink_inode_operations;
+extern const struct inode_operations ufs_fast_symlink_inode_operations;
 
 /* truncate.c */
 extern int ufs_truncate (struct inode *, loff_t);
@@ -1013,6 +1011,22 @@
 	return container_of(inode, struct ufs_inode_info, vfs_inode);
 }
 
+/*
+ * Give cylinder group number for a file system block.
+ * Give cylinder group block number for a file system block.
+ */
+/* #define	ufs_dtog(d)	((d) / uspi->s_fpg) */
+static inline u64 ufs_dtog(struct ufs_sb_private_info * uspi, u64 b)
+{
+	do_div(b, uspi->s_fpg);
+	return b;
+}
+/* #define	ufs_dtogd(d)	((d) % uspi->s_fpg) */
+static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b)
+{
+	return do_div(b, uspi->s_fpg);
+}
+
 #endif	/* __KERNEL__ */
 
 #endif /* __LINUX_UFS_FS_H */
diff --git a/include/linux/ufs_fs_i.h b/include/linux/ufs_fs_i.h
index f50ce3b..6496caa 100644
--- a/include/linux/ufs_fs_i.h
+++ b/include/linux/ufs_fs_i.h
@@ -20,13 +20,12 @@
 		__fs64	u2_i_data[15];
 	} i_u1;
 	__u32	i_flags;
-	__u32	i_gen;
 	__u32	i_shadow;
 	__u32	i_unused1;
 	__u32	i_unused2;
 	__u32	i_oeftflag;
 	__u16	i_osync;
-	__u32	i_lastfrag;
+	__u64	i_lastfrag;
 	__u32   i_dir_start_lookup;
 	struct inode vfs_inode;
 };
diff --git a/include/linux/ufs_fs_sb.h b/include/linux/ufs_fs_sb.h
index 8ff13c1..e114c93 100644
--- a/include/linux/ufs_fs_sb.h
+++ b/include/linux/ufs_fs_sb.h
@@ -21,7 +21,6 @@
 struct ufs_sb_private_info;
 struct ufs_cg_private_info;
 struct ufs_csum;
-#define UFS_MAXCSBUFS 31
 
 struct ufs_sb_info {
 	struct ufs_sb_private_info * s_uspi;	
diff --git a/include/linux/usb.h b/include/linux/usb.h
index b5c226a..87dc75a 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -388,10 +388,14 @@
 	struct usb_device *children[USB_MAXCHILDREN];
 
 	int pm_usage_cnt;		/* usage counter for autosuspend */
+	u32 quirks;			/* quirks of the whole device */
+
 #ifdef CONFIG_PM
 	struct delayed_work autosuspend; /* for delayed autosuspends */
 	struct mutex pm_mutex;		/* protects PM operations */
 
+	unsigned autosuspend_delay;	/* in jiffies */
+
 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
 #endif
@@ -935,7 +939,7 @@
 	unsigned int offset;
 	unsigned int length;		/* expected length */
 	unsigned int actual_length;
-	unsigned int status;
+	int status;
 };
 
 struct urb;
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
index ba617c3..956edf3 100644
--- a/include/linux/usb/cdc.h
+++ b/include/linux/usb/cdc.h
@@ -73,6 +73,13 @@
 	__u8	bmCapabilities;
 } __attribute__ ((packed));
 
+/* capabilities from 5.2.3.3 */
+
+#define USB_CDC_COMM_FEATURE	0x01
+#define USB_CDC_CAP_LINE	0x02
+#define USB_CDC_CAP_BRK	0x04
+#define USB_CDC_CAP_NOTIFY	0x08
+
 /* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
 struct usb_cdc_union_desc {
 	__u8	bLength;
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index ae78337..1122a6c 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -1,8 +1,9 @@
 /*
- * This file holds USB constants and structures that are needed for USB
- * device APIs.  These are used by the USB device model, which is defined
- * in chapter 9 of the USB 2.0 specification.  Linux has several APIs in C
- * that need these:
+ * This file holds USB constants and structures that are needed for
+ * USB device APIs.  These are used by the USB device model, which is
+ * defined in chapter 9 of the USB 2.0 specification and in the
+ * Wireless USB 1.0 (spread around).  Linux has several APIs in C that
+ * need these:
  *
  * - the master/host side Linux-USB kernel driver API;
  * - the "usbfs" user space API; and
@@ -14,6 +15,19 @@
  *
  * There's also "Wireless USB", using low power short range radios for
  * peripheral interconnection but otherwise building on the USB framework.
+ *
+ * Note all descriptors are declared '__attribute__((packed))' so that:
+ *
+ * [a] they never get padded, either internally (USB spec writers
+ *     probably handled that) or externally;
+ *
+ * [b] so that accessing bigger-than-a-bytes fields will never
+ *     generate bus errors on any platform, even when the location of
+ *     its descriptor inside a bundle isn't "naturally aligned", and
+ *
+ * [c] for consistency, removing all doubt even when it appears to
+ *     someone that the two other points are non-issues for that
+ *     particular descriptor type.
  */
 
 #ifndef __LINUX_USB_CH9_H
@@ -367,7 +381,7 @@
 	/* bulk endpoints with 8 byte maxpacket */
 	__u8  bDebugInEndpoint;
 	__u8  bDebugOutEndpoint;
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -396,7 +410,7 @@
 
 	__le16 wTotalLength;
 	__u8  bNumEncryptionTypes;
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -410,7 +424,7 @@
 	__u8  tTKID[3];
 	__u8  bReserved;
 	__u8  bKeyData[0];
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -426,7 +440,7 @@
 #define	USB_ENC_TYPE_RSA_1		3	/* rsa3072/sha1 auth */
 	__u8  bEncryptionValue;		/* use in SET_ENCRYPTION */
 	__u8  bAuthKeyIndex;
-};
+} __attribute__((packed));
 
 
 /*-------------------------------------------------------------------------*/
@@ -438,7 +452,7 @@
 
 	__le16 wTotalLength;
 	__u8  bNumDeviceCaps;
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -447,7 +461,7 @@
 	__u8  bLength;
 	__u8  bDescriptorType;
 	__u8  bDevCapabilityType;
-};
+} __attribute__((packed));
 
 #define	USB_CAP_TYPE_WIRELESS_USB	1
 
@@ -475,7 +489,7 @@
 	__u8  bmFFITXPowerInfo;	/* FFI power levels */
 	__le16 bmBandGroup;
 	__u8  bReserved;
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -496,7 +510,7 @@
 #define USB_ENDPOINT_SWITCH_NO		0
 #define USB_ENDPOINT_SWITCH_SWITCH	1
 #define USB_ENDPOINT_SWITCH_SCALE	2
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -512,7 +526,7 @@
 	__u8 CDID[16];
 	__u8 nonce[16];
 	__u8 MIC[8];
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
@@ -524,7 +538,7 @@
 	__u8 CHID[16];		/* persistent host id */
 	__u8 CDID[16];		/* device id (unique w/in host context) */
 	__u8 CK[16];		/* connection key */
-};
+} __attribute__((packed));
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/include/linux/usb/iowarrior.h b/include/linux/usb/iowarrior.h
new file mode 100644
index 0000000..cbbe020
--- /dev/null
+++ b/include/linux/usb/iowarrior.h
@@ -0,0 +1,33 @@
+#ifndef _IOWARRIOR_H_
+#define _IOWARRIOR_H_
+
+#define CODEMERCS_MAGIC_NUMBER	0xC0	/* like COde Mercenaries */
+
+/* Define the ioctl commands for reading and writing data */
+#define IOW_WRITE	_IOW(CODEMERCS_MAGIC_NUMBER, 1, __u8 *)
+#define IOW_READ	_IOW(CODEMERCS_MAGIC_NUMBER, 2, __u8 *)
+
+/*
+   A struct for available device info which is read
+   with the ioctl IOW_GETINFO.
+   To be compatible with 2.4 userspace which didn't have an easy way to get
+   this information.
+*/
+struct iowarrior_info {
+	__u32 vendor;		/* vendor id : supposed to be USB_VENDOR_ID_CODEMERCS in all cases */
+	__u32 product;		/* product id : depends on type of chip (USB_DEVICE_ID_CODEMERCS_XXXXX) */
+	__u8 serial[9];		/* the serial number of our chip (if a serial-number is not available this is empty string) */
+	__u32 revision;		/* revision number of the chip */
+	__u32 speed;		/* USB-speed of the device (0=UNKNOWN, 1=LOW, 2=FULL 3=HIGH) */
+	__u32 power;		/* power consumption of the device in mA */
+	__u32 if_num;		/* the number of the endpoint */
+	__u32 report_size;	/* size of the data-packets on this interface */
+};
+
+/*
+  Get some device-information (product-id , serial-number etc.)
+  in order to identify a chip.
+*/
+#define IOW_GETINFO _IOR(CODEMERCS_MAGIC_NUMBER, 3, struct iowarrior_info)
+
+#endif  /* _IOWARRIOR_H_ */
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
new file mode 100644
index 0000000..6bac8fa
--- /dev/null
+++ b/include/linux/usb/quirks.h
@@ -0,0 +1,11 @@
+/*
+ * This file holds the definitions of quirks found in USB devices.
+ * Only quirks that affect the whole device, not an interface,
+ * belong here.
+ */
+
+/* device must not be autosuspended */
+#define USB_QUIRK_NO_AUTOSUSPEND	0x00000001
+
+/* string descriptors must not be fetched using a 255-byte read */
+#define USB_QUIRK_STRING_FETCH_255	0x00000002
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 33dcd85..32acbae 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -54,6 +54,8 @@
  * @write_wait: a wait_queue_head_t used by the port.
  * @work: work queue entry for the line discipline waking up.
  * @open_count: number of times this port has been opened.
+ * @throttled: nonzero if the read urb is inactive to throttle the device
+ * @throttle_req: nonzero if the tty wants to throttle us
  *
  * This structure is used by the usb-serial core and drivers for the specific
  * ports of a device.
@@ -88,6 +90,8 @@
 	wait_queue_head_t	write_wait;
 	struct work_struct	work;
 	int			open_count;
+	char			throttled;
+	char			throttle_req;
 	struct device		dev;
 };
 #define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
@@ -269,6 +273,8 @@
 extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
 extern void usb_serial_generic_read_bulk_callback (struct urb *urb);
 extern void usb_serial_generic_write_bulk_callback (struct urb *urb);
+extern void usb_serial_generic_throttle (struct usb_serial_port *port);
+extern void usb_serial_generic_unthrottle (struct usb_serial_port *port);
 extern void usb_serial_generic_shutdown (struct usb_serial *serial);
 extern int usb_serial_generic_register (int debug);
 extern void usb_serial_generic_deregister (void);
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index 2ae76fe..1b792b9 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -46,7 +46,9 @@
 	US_FLAG(MAX_SECTORS_64,	0x00000400)			\
 		/* Sets max_sectors to 64    */			\
 	US_FLAG(IGNORE_DEVICE,	0x00000800)			\
-		/* Don't claim device */
+		/* Don't claim device */			\
+	US_FLAG(CAPACITY_HEURISTICS,	0x00001000)		\
+		/* sometimes sizes is too big */
 
 #define US_FLAG(name, value)	US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index 617d8a1..342dd5a 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -159,9 +159,9 @@
 #define USBDEVFS_SUBMITURB32       _IOR('U', 10, struct usbdevfs_urb32)
 #define USBDEVFS_DISCARDURB        _IO('U', 11)
 #define USBDEVFS_REAPURB           _IOW('U', 12, void *)
-#define USBDEVFS_REAPURB32         _IOW('U', 12, u32)
+#define USBDEVFS_REAPURB32         _IOW('U', 12, __u32)
 #define USBDEVFS_REAPURBNDELAY     _IOW('U', 13, void *)
-#define USBDEVFS_REAPURBNDELAY32   _IOW('U', 13, u32)
+#define USBDEVFS_REAPURBNDELAY32   _IOW('U', 13, __u32)
 #define USBDEVFS_DISCSIGNAL        _IOR('U', 14, struct usbdevfs_disconnectsignal)
 #define USBDEVFS_CLAIMINTERFACE    _IOR('U', 15, unsigned int)
 #define USBDEVFS_RELEASEINTERFACE  _IOR('U', 16, unsigned int)
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index d94e268..65a165f 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1,5 +1,45 @@
 /*
- *	Video for Linux Two
+ *  Video for Linux Two header file
+ *
+ *  Copyright (C) 1999-2007 the contributors
+ *
+ *  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.
+ *
+ *  Alternatively you can redistribute this file under the terms of the
+ *  BSD license as stated below:
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *  3. The names of its contributors may not be used to endorse or promote
+ *     products derived from this software without specific prior written
+ *     permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS 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.
  *
  *	Header file for v4l or V4L2 drivers and applications
  * with public API.
@@ -8,8 +48,9 @@
  *
  *	See http://linuxtv.org for more info
  *
- *	Author: Bill Dirks <bdirks@pacbell.net>
+ *	Author: Bill Dirks <bill@thedirks.org>
  *		Justin Schoeman
+ *              Hans Verkuil <hverkuil@xs4all.nl>
  *		et al.
  */
 #ifndef __LINUX_VIDEODEV2_H
@@ -90,11 +131,8 @@
 	V4L2_BUF_TYPE_VIDEO_OVERLAY      = 3,
 	V4L2_BUF_TYPE_VBI_CAPTURE        = 4,
 	V4L2_BUF_TYPE_VBI_OUTPUT         = 5,
-#if 1
-	/* Experimental Sliced VBI */
 	V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6,
 	V4L2_BUF_TYPE_SLICED_VBI_OUTPUT  = 7,
-#endif
 	V4L2_BUF_TYPE_PRIVATE            = 0x80,
 };
 
@@ -186,10 +224,8 @@
 #define V4L2_CAP_VIDEO_OVERLAY		0x00000004  /* Can do video overlay */
 #define V4L2_CAP_VBI_CAPTURE		0x00000010  /* Is a raw VBI capture device */
 #define V4L2_CAP_VBI_OUTPUT		0x00000020  /* Is a raw VBI output device */
-#if 1
 #define V4L2_CAP_SLICED_VBI_CAPTURE	0x00000040  /* Is a sliced VBI capture device */
 #define V4L2_CAP_SLICED_VBI_OUTPUT	0x00000080  /* Is a sliced VBI output device */
-#endif
 #define V4L2_CAP_RDS_CAPTURE		0x00000100  /* RDS data capture */
 
 #define V4L2_CAP_TUNER			0x00010000  /* has a tuner */
@@ -1179,7 +1215,6 @@
 #define V4L2_VBI_UNSYNC		(1<< 0)
 #define V4L2_VBI_INTERLACED	(1<< 1)
 
-#if 1
 /* Sliced VBI
  *
  *    This implements is a proposal V4L2 API to allow SLICED VBI
@@ -1212,7 +1247,6 @@
 #define V4L2_SLICED_VBI_525             (V4L2_SLICED_CAPTION_525)
 #define V4L2_SLICED_VBI_625             (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625)
 
-
 struct v4l2_sliced_vbi_cap
 {
 	__u16   service_set;
@@ -1233,7 +1267,6 @@
 	__u32   reserved;       /* must be 0 */
 	__u8    data[48];
 };
-#endif
 
 /*
  *	A G G R E G A T E   S T R U C T U R E S
@@ -1249,9 +1282,7 @@
 		struct v4l2_pix_format		pix;     // V4L2_BUF_TYPE_VIDEO_CAPTURE
 		struct v4l2_window		win;     // V4L2_BUF_TYPE_VIDEO_OVERLAY
 		struct v4l2_vbi_format		vbi;     // V4L2_BUF_TYPE_VBI_CAPTURE
-#if 1
 		struct v4l2_sliced_vbi_format	sliced;  // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
-#endif
 		__u8	raw_data[200];                   // user-defined
 	} fmt;
 };
@@ -1271,6 +1302,17 @@
 };
 
 /*
+ *	A D V A N C E D   D E B U G G I N G
+ */
+
+/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */
+struct v4l2_register {
+	__u64 reg;
+	__u32 i2c_id; /* I2C driver ID of the I2C chip, or 0 for the host */
+	__u32 val;
+};
+
+/*
  *	I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
  */
@@ -1328,9 +1370,7 @@
 #define VIDIOC_ENUMAUDOUT	_IOWR ('V', 66, struct v4l2_audioout)
 #define VIDIOC_G_PRIORITY       _IOR  ('V', 67, enum v4l2_priority)
 #define VIDIOC_S_PRIORITY       _IOW  ('V', 68, enum v4l2_priority)
-#if 1
 #define VIDIOC_G_SLICED_VBI_CAP _IOWR ('V', 69, struct v4l2_sliced_vbi_cap)
-#endif
 #define VIDIOC_LOG_STATUS       _IO   ('V', 70)
 #define VIDIOC_G_EXT_CTRLS	_IOWR ('V', 71, struct v4l2_ext_controls)
 #define VIDIOC_S_EXT_CTRLS	_IOWR ('V', 72, struct v4l2_ext_controls)
@@ -1339,6 +1379,9 @@
 #define VIDIOC_ENUM_FRAMESIZES	_IOWR ('V', 74, struct v4l2_frmsizeenum)
 #define VIDIOC_ENUM_FRAMEINTERVALS	_IOWR ('V', 75, struct v4l2_frmivalenum)
 #endif
+/* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
+#define	VIDIOC_DBG_S_REGISTER 	_IOW ('d', 100, struct v4l2_register)
+#define	VIDIOC_DBG_G_REGISTER 	_IOWR('d', 101, struct v4l2_register)
 
 #ifdef __OLD_VIDIOC_
 /* for compatibility, will go away some day */
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 5e9803e..acb1f10 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -3,20 +3,15 @@
 
 #include <linux/types.h>
 #include <linux/percpu.h>
+#include <linux/mm.h>
 #include <linux/mmzone.h>
 #include <asm/atomic.h>
 
-#ifdef CONFIG_VM_EVENT_COUNTERS
-/*
- * Light weight per cpu counter implementation.
- *
- * Counters should only be incremented.  You need to set EMBEDDED
- * to disable VM_EVENT_COUNTERS.  Things like procps (vmstat,
- * top, etc) use /proc/vmstat and depend on these counters.
- *
- * Counters are handled completely inline. On many platforms the code
- * generated will simply be the increment of a global address.
- */
+#ifdef CONFIG_ZONE_DMA
+#define DMA_ZONE(xx) xx##_DMA,
+#else
+#define DMA_ZONE(xx)
+#endif
 
 #ifdef CONFIG_ZONE_DMA32
 #define DMA32_ZONE(xx) xx##_DMA32,
@@ -30,7 +25,7 @@
 #define HIGHMEM_ZONE(xx)
 #endif
 
-#define FOR_ALL_ZONES(xx) xx##_DMA, DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx)
+#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx)
 
 enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
 		FOR_ALL_ZONES(PGALLOC),
@@ -45,6 +40,17 @@
 		NR_VM_EVENT_ITEMS
 };
 
+#ifdef CONFIG_VM_EVENT_COUNTERS
+/*
+ * Light weight per cpu counter implementation.
+ *
+ * Counters should only be incremented and no critical kernel component
+ * should rely on the counter values.
+ *
+ * Counters are handled completely inline. On many platforms the code
+ * generated will simply be the increment of a global address.
+ */
+
 struct vm_event_state {
 	unsigned long event[NR_VM_EVENT_ITEMS];
 };
@@ -85,17 +91,30 @@
 #else
 
 /* Disable counters */
-#define get_cpu_vm_events(e)	0L
-#define count_vm_event(e)	do { } while (0)
-#define count_vm_events(e,d)	do { } while (0)
-#define __count_vm_event(e)	do { } while (0)
-#define __count_vm_events(e,d)	do { } while (0)
-#define vm_events_fold_cpu(x)	do { } while (0)
+static inline void count_vm_event(enum vm_event_item item)
+{
+}
+static inline void count_vm_events(enum vm_event_item item, long delta)
+{
+}
+static inline void __count_vm_event(enum vm_event_item item)
+{
+}
+static inline void __count_vm_events(enum vm_event_item item, long delta)
+{
+}
+static inline void all_vm_events(unsigned long *ret)
+{
+}
+static inline void vm_events_fold_cpu(int cpu)
+{
+}
 
 #endif /* CONFIG_VM_EVENT_COUNTERS */
 
 #define __count_zone_vm_events(item, zone, delta) \
-			__count_vm_events(item##_DMA + zone_idx(zone), delta)
+		__count_vm_events(item##_NORMAL - ZONE_NORMAL + \
+		zone_idx(zone), delta)
 
 /*
  * Zone based page accounting with per cpu differentials.
@@ -142,14 +161,16 @@
 	struct zone *zones = NODE_DATA(node)->node_zones;
 
 	return
+#ifdef CONFIG_ZONE_DMA
+		zone_page_state(&zones[ZONE_DMA], item) +
+#endif
 #ifdef CONFIG_ZONE_DMA32
 		zone_page_state(&zones[ZONE_DMA32], item) +
 #endif
-		zone_page_state(&zones[ZONE_NORMAL], item) +
 #ifdef CONFIG_HIGHMEM
 		zone_page_state(&zones[ZONE_HIGHMEM], item) +
 #endif
-		zone_page_state(&zones[ZONE_DMA], item);
+		zone_page_state(&zones[ZONE_NORMAL], item);
 }
 
 extern void zone_statistics(struct zonelist *, struct zone *);
@@ -186,6 +207,9 @@
 void dec_zone_page_state(struct page *, enum zone_stat_item);
 
 extern void inc_zone_state(struct zone *, enum zone_stat_item);
+extern void __inc_zone_state(struct zone *, enum zone_stat_item);
+extern void dec_zone_state(struct zone *, enum zone_stat_item);
+extern void __dec_zone_state(struct zone *, enum zone_stat_item);
 
 void refresh_cpu_vm_stats(int);
 void refresh_vm_stats(void);
@@ -214,6 +238,12 @@
 	__inc_zone_state(page_zone(page), item);
 }
 
+static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item)
+{
+	atomic_long_dec(&zone->vm_stat[item]);
+	atomic_long_dec(&vm_stat[item]);
+}
+
 static inline void __dec_zone_page_state(struct page *page,
 			enum zone_stat_item item)
 {
diff --git a/include/linux/wanrouter.h b/include/linux/wanrouter.h
index 2cd0501..3add874 100644
--- a/include/linux/wanrouter.h
+++ b/include/linux/wanrouter.h
@@ -516,9 +516,6 @@
 /* Public functions available for device drivers */
 extern int register_wan_device(struct wan_device *wandev);
 extern int unregister_wan_device(char *name);
-__be16 wanrouter_type_trans(struct sk_buff *skb, struct net_device *dev);
-int wanrouter_encapsulate(struct sk_buff *skb, struct net_device *dev,
-			  unsigned short type);
 
 /* Proc interface functions. These must not be called by the drivers! */
 extern int wanrouter_proc_init(void);
@@ -527,11 +524,6 @@
 extern int wanrouter_proc_delete(struct wan_device *wandev);
 extern int wanrouter_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
 
-extern void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
-extern void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
-
-
-
 /* Public Data */
 /* list of registered devices */
 extern struct wan_device *wanrouter_router_devlist;
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index 7c269f49..447c52b 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -334,7 +334,7 @@
  * separate range because of collisions with other tools such as
  * 'mii-tool'.
  * We now have 32 commands, so a bit more space ;-).
- * Also, all 'odd' commands are only usable by root and don't return the
+ * Also, all 'even' commands are only usable by root and don't return the
  * content of ifr/iwr to user (but you are not obliged to use the set/get
  * convention, just use every other two command). More details in iwpriv.c.
  * And I repeat : you are not forced to use them with iwpriv, but you
@@ -348,7 +348,7 @@
 #define SIOCIWLAST	SIOCIWLASTPRIV		/* 0x8BFF */
 #define IW_IOCTL_IDX(cmd)	((cmd) - SIOCIWFIRST)
 
-/* Even : get (world access), odd : set (root access) */
+/* Odd : get (world access), even : set (root access) */
 #define IW_IS_SET(cmd)	(!((cmd) & 0x1))
 #define IW_IS_GET(cmd)	((cmd) & 0x1)
 
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 0e7f1e2..def131a 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -13,6 +13,10 @@
 #define XATTR_CREATE	0x1	/* set value, fail if attr already exists */
 #define XATTR_REPLACE	0x2	/* set value, fail if attr does not exist */
 
+#ifdef  __KERNEL__
+
+#include <linux/types.h>
+
 /* Namespaces */
 #define XATTR_OS2_PREFIX "os2."
 #define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1)
@@ -29,6 +33,8 @@
 #define XATTR_USER_PREFIX "user."
 #define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
 
+struct inode;
+struct dentry;
 
 struct xattr_handler {
 	char *prefix;
@@ -50,4 +56,6 @@
 int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
 int generic_removexattr(struct dentry *dentry, const char *name);
 
+#endif  /*  __KERNEL__  */
+
 #endif	/* _LINUX_XATTR_H */
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 9529ea1..15ca89e 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -178,6 +178,9 @@
 	XFRM_MSG_REPORT,
 #define XFRM_MSG_REPORT XFRM_MSG_REPORT
 
+	XFRM_MSG_MIGRATE,
+#define XFRM_MSG_MIGRATE XFRM_MSG_MIGRATE
+
 	__XFRM_MSG_MAX
 };
 #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@@ -256,6 +259,7 @@
 	XFRMA_COADDR,		/* xfrm_address_t */
 	XFRMA_LASTUSED,
 	XFRMA_POLICY_TYPE,	/* struct xfrm_userpolicy_type */
+	XFRMA_MIGRATE,
 	__XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -351,6 +355,19 @@
 	struct xfrm_selector		sel;
 };
 
+struct xfrm_user_migrate {
+	xfrm_address_t			old_daddr;
+	xfrm_address_t			old_saddr;
+	xfrm_address_t			new_daddr;
+	xfrm_address_t			new_saddr;
+	__u8				proto;
+	__u8				mode;
+	__u16				reserved;
+	__u32				reqid;
+	__u16				old_family;
+	__u16				new_family;
+};
+
 #ifndef __KERNEL__
 /* backwards compatibility for userspace */
 #define XFRMGRP_ACQUIRE		1
@@ -375,6 +392,8 @@
 #define XFRMNLGRP_AEVENTS	XFRMNLGRP_AEVENTS
 	XFRMNLGRP_REPORT,
 #define XFRMNLGRP_REPORT	XFRMNLGRP_REPORT
+	XFRMNLGRP_MIGRATE,
+#define XFRMNLGRP_MIGRATE	XFRMNLGRP_MIGRATE
 	__XFRMNLGRP_MAX
 };
 #define XFRMNLGRP_MAX	(__XFRMNLGRP_MAX - 1)
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h
index ecad55b..d758a52c 100644
--- a/include/media/cx2341x.h
+++ b/include/media/cx2341x.h
@@ -57,7 +57,6 @@
 	u16 video_b_frames;
 	u16 video_gop_size;
 	u16 video_gop_closure;
-	u16 video_pulldown;
 	enum v4l2_mpeg_video_bitrate_mode video_bitrate_mode;
 	u32 video_bitrate;
 	u32 video_bitrate_peak;
@@ -121,8 +120,6 @@
 #define CX2341X_DEC_SET_DISPLAY_BUFFERS		0x18
 #define CX2341X_DEC_EXTRACT_VBI 		0x19
 #define CX2341X_DEC_SET_DECODER_SOURCE 		0x1a
-#define CX2341X_DEC_SET_AUDIO_OUTPUT 		0x1b
-#define CX2341X_DEC_SET_AV_DELAY 		0x1c
 #define CX2341X_DEC_SET_PREBUFFERING		0x1e
 
 /* MPEG encoder API */
@@ -141,7 +138,6 @@
 #define CX2341X_ENC_SET_DNR_FILTER_PROPS 	0x9d
 #define CX2341X_ENC_SET_CORING_LEVELS 		0x9f
 #define CX2341X_ENC_SET_SPATIAL_FILTER_TYPE 	0xa1
-#define CX2341X_ENC_SET_3_2_PULLDOWN 		0xb1
 #define CX2341X_ENC_SET_VBI_LINE 		0xb7
 #define CX2341X_ENC_SET_STREAM_TYPE 		0xb9
 #define CX2341X_ENC_SET_OUTPUT_PORT 		0xbb
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
index 4bb0ad8..9807a7c 100644
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -36,6 +36,11 @@
 #define IR_KEYCODE(tab,code)	(((unsigned)code < IR_KEYTAB_SIZE) \
 				 ? tab[code] : KEY_RESERVED)
 
+#define RC5_START(x)	(((x)>>12)&3)
+#define RC5_TOGGLE(x)	(((x)>>11)&1)
+#define RC5_ADDR(x)	(((x)>>6)&31)
+#define RC5_INSTR(x)	((x)&63)
+
 struct ir_input_state {
 	/* configuration */
 	int                ir_type;
@@ -48,6 +53,40 @@
 	int                keypressed;  /* current state */
 };
 
+/* this was saa7134_ir and bttv_ir, moved here for
+ * rc5 decoding. */
+struct card_ir {
+	struct input_dev        *dev;
+	struct ir_input_state   ir;
+	char                    name[32];
+	char                    phys[32];
+
+	/* Usual gpio signalling */
+
+	u32                     mask_keycode;
+	u32                     mask_keydown;
+	u32                     mask_keyup;
+	u32                     polling;
+	u32                     last_gpio;
+	int			shift_by;
+	int			start; // What should RC5_START() be
+	int			addr; // What RC5_ADDR() should be.
+	int			rc5_key_timeout;
+	int			rc5_remote_gap;
+	struct work_struct      work;
+	struct timer_list       timer;
+
+	/* RC5 gpio */
+	u32 rc5_gpio;
+	struct timer_list timer_end;	/* timer_end for code completion */
+	struct timer_list timer_keyup;	/* timer_end for key release */
+	u32 last_rc5;			/* last good rc5 code */
+	u32 last_bit;			/* last raw bit seen */
+	u32 code;			/* raw code under construction */
+	struct timeval base_time;	/* time of last seen code */
+	int active;			/* building raw code */
+};
+
 void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
 		   int ir_type, IR_KEYTAB_TYPE *ir_codes);
 void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir);
@@ -58,6 +97,10 @@
 int  ir_decode_biphase(u32 *samples, int count, int low, int high);
 int  ir_decode_pulsedistance(u32 *samples, int count, int low, int high);
 
+u32 ir_rc5_decode(unsigned int code);
+void ir_rc5_timer_end(unsigned long data);
+void ir_rc5_timer_keyup(unsigned long data);
+
 /* Keymaps to be used by other modules */
 
 extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE];
@@ -94,6 +137,9 @@
 extern IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE];
 
 #endif
 
diff --git a/include/media/saa7115.h b/include/media/saa7115.h
index 9f0e228..f677dfb 100644
--- a/include/media/saa7115.h
+++ b/include/media/saa7115.h
@@ -42,5 +42,8 @@
 #define SAA7115_FREQ_FL_CGCDIV (1 << 1)	   /* SA 3A[6], CGCDIV, SAA7115 only */
 #define SAA7115_FREQ_FL_APLL   (1 << 2)	   /* SA 3A[3], APLL, SAA7114/5 only */
 
+#define SAA7115_IPORT_ON    1
+#define SAA7115_IPORT_OFF   0
+
 #endif
 
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 91b1992..244e440 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -64,9 +64,6 @@
 /* Prints the ioctl in a human-readable format */
 extern void v4l_printk_ioctl(unsigned int cmd);
 
-/* Prints the ioctl and arg in a human-readable format */
-extern void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg);
-
 /* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */
 #define v4l_print_ioctl(name, cmd)  		 \
 	do {  					 \
@@ -99,13 +96,6 @@
 
 /* Internal ioctls */
 
-/* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */
-struct v4l2_register {
-	u32 i2c_id; 		/* I2C driver ID of the I2C chip. 0 for the I2C adapter. */
-	unsigned long reg;
-	u32 val;
-};
-
 /* VIDIOC_INT_DECODE_VBI_LINE */
 struct v4l2_decode_vbi_line {
 	u32 is_second_field;	/* Set to 0 for the first (odd) field,
@@ -175,9 +165,7 @@
    Replacement of TUNER_SET_STANDBY. */
 #define VIDIOC_INT_S_STANDBY 	     _IOW('d', 94, u32)
 
-/* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
-#define	VIDIOC_INT_S_REGISTER 		_IOW ('d', 100, struct v4l2_register)
-#define	VIDIOC_INT_G_REGISTER 		_IOWR('d', 101, struct v4l2_register)
+/* 100, 101 used by  VIDIOC_DBG_[SG]_REGISTER */
 
 /* Generic reset command. The argument selects which subsystems to reset.
    Passing 0 will always reset the whole chip. */
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index fb96472..aeec569 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -296,6 +296,15 @@
 	int (*vidioc_log_status)       (struct file *file, void *fh);
 
 
+	/* Debugging ioctls */
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	int (*vidioc_g_register)       (struct file *file, void *fh,
+					struct v4l2_register *reg);
+	int (*vidioc_s_register)       (struct file *file, void *fh,
+					struct v4l2_register *reg);
+#endif
+
+
 #ifdef OBSOLETE_OWNER /* to be removed soon */
 /* obsolete -- fops->owner is used instead */
 struct module *owner;
diff --git a/include/media/video-buf.h b/include/media/video-buf.h
index 1115a25..d6f0794 100644
--- a/include/media/video-buf.h
+++ b/include/media/video-buf.h
@@ -78,6 +78,9 @@
 	/* for kernel buffers */
 	void                *vmalloc;
 
+	/* Stores the userspace pointer to vmalloc area */
+	void                *varea;
+
 	/* for overlay buffers (pci-pci dma) */
 	dma_addr_t          bus_addr;
 
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index f913c30..8e501a7 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -36,12 +36,6 @@
 #define MTD_CAP_NORFLASH	(MTD_WRITEABLE | MTD_BIT_WRITEABLE)
 #define MTD_CAP_NANDFLASH	(MTD_WRITEABLE)
 
-
-// Types of automatic ECC/Checksum available
-#define MTD_ECC_NONE		0 	// No automatic ECC available
-#define MTD_ECC_RS_DiskOnChip	1	// Automatic ECC on DiskOnChip
-#define MTD_ECC_SW		2	// SW ECC for Toshiba & Samsung devices
-
 /* ECC byte placement */
 #define MTD_NANDECC_OFF		0	// Switch off ECC (Not recommended)
 #define MTD_NANDECC_PLACE	1	// Use the given placement in the structure (YAFFS1 legacy mode)
@@ -61,6 +55,8 @@
 	uint32_t erasesize;
 	uint32_t writesize;
 	uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
+	/* The below two fields are obsolete and broken, do not use them
+	 * (TODO: remove at some point) */
 	uint32_t ecctype;
 	uint32_t eccsize;
 };
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 5ae10dd..47ff2f4 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -377,7 +377,7 @@
 /* ax25_route.c */
 extern void ax25_rt_device_down(struct net_device *);
 extern int  ax25_rt_ioctl(unsigned int, void __user *);
-extern struct file_operations ax25_route_fops;
+extern const struct file_operations ax25_route_fops;
 extern ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev);
 extern int  ax25_rt_autobind(ax25_cb *, ax25_address *);
 extern struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *, ax25_address *, ax25_digi *);
@@ -430,7 +430,7 @@
 extern int  ax25_uid_policy;
 extern ax25_uid_assoc *ax25_findbyuid(uid_t);
 extern int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *);
-extern struct file_operations ax25_uid_fops;
+extern const struct file_operations ax25_uid_fops;
 extern void ax25_uid_free(void);
 
 /* sysctl_net_ax25.c */
diff --git a/include/net/dn_route.h b/include/net/dn_route.h
index 76f957e..a566944 100644
--- a/include/net/dn_route.h
+++ b/include/net/dn_route.h
@@ -68,9 +68,10 @@
 struct dn_route {
 	union {
 		struct dst_entry dst;
-		struct dn_route *rt_next;
 	} u;
 
+	struct flowi fl;
+
 	__le16 rt_saddr;
 	__le16 rt_daddr;
 	__le16 rt_gateway;
@@ -80,8 +81,6 @@
 
 	unsigned rt_flags;
 	unsigned rt_type;
-
-	struct flowi fl;
 };
 
 extern void dn_route_init(void);
diff --git a/include/net/dst.h b/include/net/dst.h
index 62b7e75..e12a8ce 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -37,9 +37,7 @@
 
 struct dst_entry
 {
-	struct dst_entry        *next;
-	atomic_t		__refcnt;	/* client references	*/
-	int			__use;
+	struct rcu_head		rcu_head;
 	struct dst_entry	*child;
 	struct net_device       *dev;
 	short			error;
@@ -50,7 +48,6 @@
 #define DST_NOPOLICY		4
 #define DST_NOHASH		8
 #define DST_BALANCED            0x10
-	unsigned long		lastuse;
 	unsigned long		expires;
 
 	unsigned short		header_len;	/* more space at head required */
@@ -75,8 +72,16 @@
 #endif
 
 	struct  dst_ops	        *ops;
-	struct rcu_head		rcu_head;
 		
+	unsigned long		lastuse;
+	atomic_t		__refcnt;	/* client references	*/
+	int			__use;
+	union {
+		struct dst_entry *next;
+		struct rtable    *rt_next;
+		struct rt6_info   *rt6_next;
+		struct dn_route  *dn_next;
+	};
 	char			info[0];
 };
 
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 34cc76e..d27ee8c 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -34,12 +34,13 @@
 #include <asm/byteorder.h>
 
 /* This is for all connections with a full identity, no wildcards.
- * New scheme, half the table is for TIME_WAIT, the other half is
- * for the rest.  I'll experiment with dynamic table growth later.
+ * One chain is dedicated to TIME_WAIT sockets.
+ * I'll experiment with dynamic table growth later.
  */
 struct inet_ehash_bucket {
 	rwlock_t	  lock;
 	struct hlist_head chain;
+	struct hlist_head twchain;
 };
 
 /* There are a few simple rules, which allow for local port reuse by
@@ -97,8 +98,7 @@
 	 *
 	 *          TCP_ESTABLISHED <= sk->sk_state < TCP_CLOSE
 	 *
-	 * First half of the table is for sockets not in TIME_WAIT, second half
-	 * is for TIME_WAIT sockets only.
+	 * TIME_WAIT sockets use a separate chain (twchain).
 	 */
 	struct inet_ehash_bucket	*ehash;
 
@@ -369,7 +369,7 @@
 	}
 
 	/* Must check for a TIME_WAIT'er before going to listener hash. */
-	sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
+	sk_for_each(sk, node, &head->twchain) {
 		if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
 			goto hit;
 	}
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 7be4f4e..9eda572 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -83,7 +83,6 @@
 {
 	union {
 		struct dst_entry	dst;
-		struct rt6_info		*next;
 	} u;
 
 	struct inet6_dev		*rt6i_idev;
diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h
new file mode 100644
index 0000000..04d1abb
--- /dev/null
+++ b/include/net/iucv/af_iucv.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2006 IBM Corporation
+ * IUCV protocol stack for Linux on zSeries
+ * Version 1.0
+ * Author(s): Jennifer Hunt <jenhunt@us.ibm.com>
+ *
+ */
+
+#ifndef __AFIUCV_H
+#define __AFIUCV_H
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <linux/socket.h>
+
+#ifndef AF_IUCV
+#define AF_IUCV		32
+#define PF_IUCV		AF_IUCV
+#endif
+
+/* Connection and socket states */
+enum {
+	IUCV_CONNECTED = 1,
+	IUCV_OPEN,
+	IUCV_BOUND,
+	IUCV_LISTEN,
+	IUCV_SEVERED,
+	IUCV_DISCONN,
+	IUCV_CLOSED
+};
+
+#define IUCV_QUEUELEN_DEFAULT	65535
+#define IUCV_CONN_TIMEOUT	(HZ * 40)
+#define IUCV_DISCONN_TIMEOUT	(HZ * 2)
+#define IUCV_CONN_IDLE_TIMEOUT	(HZ * 60)
+#define IUCV_BUFSIZE_DEFAULT	32768
+
+/* IUCV socket address */
+struct sockaddr_iucv {
+	sa_family_t	siucv_family;
+	unsigned short	siucv_port;		/* Reserved */
+	unsigned int	siucv_addr;		/* Reserved */
+	char		siucv_nodeid[8];	/* Reserved */
+	char		siucv_user_id[8];	/* Guest User Id */
+	char		siucv_name[8];		/* Application Name */
+};
+
+
+/* Common socket structures and functions */
+
+#define iucv_sk(__sk) ((struct iucv_sock *) __sk)
+
+struct iucv_sock {
+	struct sock		sk;
+	char			src_user_id[8];
+	char			src_name[8];
+	char			dst_user_id[8];
+	char			dst_name[8];
+	struct list_head	accept_q;
+	struct sock		*parent;
+	struct iucv_path	*path;
+	struct sk_buff_head	send_skb_q;
+	unsigned int		send_tag;
+};
+
+struct iucv_sock_list {
+	struct hlist_head head;
+	rwlock_t	  lock;
+	atomic_t	  autobind_name;
+};
+
+static void iucv_sock_destruct(struct sock *sk);
+static void iucv_sock_cleanup_listen(struct sock *parent);
+static void iucv_sock_kill(struct sock *sk);
+static void iucv_sock_close(struct sock *sk);
+static int  iucv_sock_create(struct socket *sock, int proto);
+static int  iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
+			int addr_len);
+static int  iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
+			      int alen, int flags);
+static int  iucv_sock_listen(struct socket *sock, int backlog);
+static int  iucv_sock_accept(struct socket *sock, struct socket *newsock,
+			     int flags);
+static int  iucv_sock_getname(struct socket *sock, struct sockaddr *addr,
+			      int *len, int peer);
+static int  iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
+			      struct msghdr *msg, size_t len);
+static int  iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+			      struct msghdr *msg, size_t len, int flags);
+unsigned int iucv_sock_poll(struct file *file, struct socket *sock,
+			    poll_table *wait);
+static int iucv_sock_release(struct socket *sock);
+static int iucv_sock_shutdown(struct socket *sock, int how);
+
+void iucv_sock_link(struct iucv_sock_list *l, struct sock *s);
+void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *s);
+int  iucv_sock_wait_state(struct sock *sk, int state, int state2,
+			  unsigned long timeo);
+int  iucv_sock_wait_cnt(struct sock *sk, unsigned long timeo);
+void iucv_accept_enqueue(struct sock *parent, struct sock *sk);
+void iucv_accept_unlink(struct sock *sk);
+struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock);
+
+#endif /* __IUCV_H */
diff --git a/include/net/iucv/iucv.h b/include/net/iucv/iucv.h
new file mode 100644
index 0000000..746e741
--- /dev/null
+++ b/include/net/iucv/iucv.h
@@ -0,0 +1,415 @@
+/*
+ *  drivers/s390/net/iucv.h
+ *    IUCV base support.
+ *
+ *  S390 version
+ *    Copyright 2000, 2006 IBM Corporation
+ *    Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
+ *		Xenia Tkatschow (xenia@us.ibm.com)
+ *    Rewritten for af_iucv:
+ *	Martin Schwidefsky <schwidefsky@de.ibm.com>
+ *
+ *
+ * Functionality:
+ * To explore any of the IUCV functions, one must first register their
+ * program using iucv_register(). Once your program has successfully
+ * completed a register, it can exploit the other functions.
+ * For furthur reference on all IUCV functionality, refer to the
+ * CP Programming Services book, also available on the web thru
+ * www.ibm.com/s390/vm/pubs, manual # SC24-5760
+ *
+ * Definition of Return Codes
+ * - All positive return codes including zero are reflected back
+ *   from CP. The definition of each return code can be found in
+ *   CP Programming Services book.
+ * - Return Code of:
+ *   -EINVAL: Invalid value
+ *   -ENOMEM: storage allocation failed
+ */
+
+#include <linux/types.h>
+#include <asm/debug.h>
+
+/*
+ * IUCV option flags usable by device drivers:
+ *
+ * IUCV_IPRMDATA  Indicates that your program can handle a message in the
+ *		  parameter list / a message is sent in the parameter list.
+ *		  Used for iucv_path_accept, iucv_path_connect,
+ *		  iucv_message_reply, iucv_message_send, iucv_message_send2way.
+ * IUCV_IPQUSCE	  Indicates that you do not want to receive messages on this
+ *		  path until an iucv_path_resume is issued.
+ *		  Used for iucv_path_accept, iucv_path_connect.
+ * IUCV_IPBUFLST  Indicates that an address list is used for the message data.
+ *		  Used for iucv_message_receive, iucv_message_send,
+ *		  iucv_message_send2way.
+ * IUCV_IPPRTY	  Specifies that you want to send priority messages.
+ *		  Used for iucv_path_accept, iucv_path_connect,
+ *		  iucv_message_reply, iucv_message_send, iucv_message_send2way.
+ * IUCV_IPSYNC	  Indicates a synchronous send request.
+ *		  Used for iucv_message_send, iucv_message_send2way.
+ * IUCV_IPANSLST  Indicates that an address list is used for the reply data.
+ *		  Used for iucv_message_reply, iucv_message_send2way.
+ * IUCV_IPLOCAL	  Specifies that the communication partner has to be on the
+ *		  local system. If local is specified no target class can be
+ *		  specified.
+ *		  Used for iucv_path_connect.
+ *
+ * All flags are defined in the input field IPFLAGS1 of each function
+ * and can be found in CP Programming Services.
+ */
+#define IUCV_IPRMDATA	0x80
+#define IUCV_IPQUSCE	0x40
+#define IUCV_IPBUFLST	0x40
+#define IUCV_IPPRTY	0x20
+#define IUCV_IPANSLST	0x08
+#define IUCV_IPSYNC	0x04
+#define IUCV_IPLOCAL	0x01
+
+/*
+ * iucv_array : Defines buffer array.
+ * Inside the array may be 31- bit addresses and 31-bit lengths.
+ * Use a pointer to an iucv_array as the buffer, reply or answer
+ * parameter on iucv_message_send, iucv_message_send2way, iucv_message_receive
+ * and iucv_message_reply if IUCV_IPBUFLST or IUCV_IPANSLST are used.
+ */
+struct iucv_array {
+	u32 address;
+	u32 length;
+} __attribute__ ((aligned (8)));
+
+extern struct bus_type iucv_bus;
+extern struct device *iucv_root;
+
+/*
+ * struct iucv_path
+ * pathid: 16 bit path identification
+ * msglim: 16 bit message limit
+ * flags: properties of the path: IPRMDATA, IPQUSCE, IPPRTY
+ * handler:  address of iucv handler structure
+ * private: private information of the handler associated with the path
+ * list: list_head for the iucv_handler path list.
+ */
+struct iucv_path {
+	u16 pathid;
+	u16 msglim;
+	u8  flags;
+	void *private;
+	struct iucv_handler *handler;
+	struct list_head list;
+};
+
+/*
+ * struct iucv_message
+ * id: 32 bit message id
+ * audit: 32 bit error information of purged or replied messages
+ * class: 32 bit target class of a message (source class for replies)
+ * tag: 32 bit tag to be associated with the message
+ * length: 32 bit length of the message / reply
+ * reply_size: 32 bit maximum allowed length of the reply
+ * rmmsg: 8 byte inline message
+ * flags: message properties (IUCV_IPPRTY)
+ */
+struct iucv_message {
+	u32 id;
+	u32 audit;
+	u32 class;
+	u32 tag;
+	u32 length;
+	u32 reply_size;
+	u8  rmmsg[8];
+	u8  flags;
+};
+
+/*
+ * struct iucv_handler
+ *
+ * A vector of functions that handle IUCV interrupts. Each functions gets
+ * a parameter area as defined by the CP Programming Services and private
+ * pointer that is provided by the user of the interface.
+ */
+struct iucv_handler {
+	 /*
+	  * The path_pending function is called after an iucv interrupt
+	  * type 0x01 has been received. The base code allocates a path
+	  * structure and "asks" the handler if this path belongs to the
+	  * handler. To accept the path the path_pending function needs
+	  * to call iucv_path_accept and return 0. If the callback returns
+	  * a value != 0 the iucv base code will continue with the next
+	  * handler. The order in which the path_pending functions are
+	  * called is the order of the registration of the iucv handlers
+	  * to the base code.
+	  */
+	int  (*path_pending)(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+	/*
+	 * The path_complete function is called after an iucv interrupt
+	 * type 0x02 has been received for a path that has been established
+	 * for this handler with iucv_path_connect and got accepted by the
+	 * peer with iucv_path_accept.
+	 */
+	void (*path_complete)(struct iucv_path *, u8 ipuser[16]);
+	 /*
+	  * The path_severed function is called after an iucv interrupt
+	  * type 0x03 has been received. The communication peer shutdown
+	  * his end of the communication path. The path still exists and
+	  * remaining messages can be received until a iucv_path_sever
+	  * shuts down the other end of the path as well.
+	  */
+	void (*path_severed)(struct iucv_path *, u8 ipuser[16]);
+	/*
+	 * The path_quiesced function is called after an icuv interrupt
+	 * type 0x04 has been received. The communication peer has quiesced
+	 * the path. Delivery of messages is stopped until iucv_path_resume
+	 * has been called.
+	 */
+	void (*path_quiesced)(struct iucv_path *, u8 ipuser[16]);
+	/*
+	 * The path_resumed function is called after an icuv interrupt
+	 * type 0x05 has been received. The communication peer has resumed
+	 * the path.
+	 */
+	void (*path_resumed)(struct iucv_path *, u8 ipuser[16]);
+	/*
+	 * The message_pending function is called after an icuv interrupt
+	 * type 0x06 or type 0x07 has been received. A new message is
+	 * availabe and can be received with iucv_message_receive.
+	 */
+	void (*message_pending)(struct iucv_path *, struct iucv_message *);
+	/*
+	 * The message_complete function is called after an icuv interrupt
+	 * type 0x08 or type 0x09 has been received. A message send with
+	 * iucv_message_send2way has been replied to. The reply can be
+	 * received with iucv_message_receive.
+	 */
+	void (*message_complete)(struct iucv_path *, struct iucv_message *);
+
+	struct list_head list;
+	struct list_head paths;
+};
+
+/**
+ * iucv_register:
+ * @handler: address of iucv handler structure
+ * @smp: != 0 indicates that the handler can deal with out of order messages
+ *
+ * Registers a driver with IUCV.
+ *
+ * Returns 0 on success, -ENOMEM if the memory allocation for the pathid
+ * table failed, or -EIO if IUCV_DECLARE_BUFFER failed on all cpus.
+ */
+int iucv_register(struct iucv_handler *handler, int smp);
+
+/**
+ * iucv_unregister
+ * @handler:  address of iucv handler structure
+ * @smp: != 0 indicates that the handler can deal with out of order messages
+ *
+ * Unregister driver from IUCV.
+ */
+void iucv_unregister(struct iucv_handler *handle, int smp);
+
+/**
+ * iucv_path_alloc
+ * @msglim: initial message limit
+ * @flags: initial flags
+ * @gfp: kmalloc allocation flag
+ *
+ * Allocate a new path structure for use with iucv_connect.
+ *
+ * Returns NULL if the memory allocation failed or a pointer to the
+ * path structure.
+ */
+static inline struct iucv_path *iucv_path_alloc(u16 msglim, u8 flags, gfp_t gfp)
+{
+	struct iucv_path *path;
+
+	path = kzalloc(sizeof(struct iucv_path), gfp);
+	if (path) {
+		path->msglim = msglim;
+		path->flags = flags;
+	}
+	return path;
+}
+
+/**
+ * iucv_path_free
+ * @path: address of iucv path structure
+ *
+ * Frees a path structure.
+ */
+static inline void iucv_path_free(struct iucv_path *path)
+{
+	kfree(path);
+}
+
+/**
+ * iucv_path_accept
+ * @path: address of iucv path structure
+ * @handler: address of iucv handler structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ * @private: private data passed to interrupt handlers for this path
+ *
+ * This function is issued after the user received a connection pending
+ * external interrupt and now wishes to complete the IUCV communication path.
+ *
+ * Returns the result of the CP IUCV call.
+ */
+int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
+		     u8 userdata[16], void *private);
+
+/**
+ * iucv_path_connect
+ * @path: address of iucv path structure
+ * @handler: address of iucv handler structure
+ * @userid: 8-byte user identification
+ * @system: 8-byte target system identification
+ * @userdata: 16 bytes of data reflected to the communication partner
+ * @private: private data passed to interrupt handlers for this path
+ *
+ * This function establishes an IUCV path. Although the connect may complete
+ * successfully, you are not able to use the path until you receive an IUCV
+ * Connection Complete external interrupt.
+ *
+ * Returns the result of the CP IUCV call.
+ */
+int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
+		      u8 userid[8], u8 system[8], u8 userdata[16],
+		      void *private);
+
+/**
+ * iucv_path_quiesce:
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function temporarily suspends incoming messages on an IUCV path.
+ * You can later reactivate the path by invoking the iucv_resume function.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]);
+
+/**
+ * iucv_path_resume:
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function resumes incoming messages on an IUCV path that has
+ * been stopped with iucv_path_quiesce.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_resume(struct iucv_path *path, u8 userdata[16]);
+
+/**
+ * iucv_path_sever
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function terminates an IUCV path.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_sever(struct iucv_path *path, u8 userdata[16]);
+
+/**
+ * iucv_message_purge
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @srccls: source class of message
+ *
+ * Cancels a message you have sent.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
+		       u32 srccls);
+
+/**
+ * iucv_message_receive
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: flags that affect how the message is received (IUCV_IPBUFLST)
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of data buffer
+ * @residual:
+ *
+ * This function receives messages that are being sent to you over
+ * established paths. This function will deal with RMDATA messages
+ * embedded in struct iucv_message as well.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
+			 u8 flags, void *buffer, size_t size, size_t *residual);
+
+/**
+ * iucv_message_reject
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ *
+ * The reject function refuses a specified message. Between the time you
+ * are notified of a message and the time that you complete the message,
+ * the message may be rejected.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg);
+
+/**
+ * iucv_message_reply
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the reply is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
+ * @reply: address of data buffer or address of struct iucv_array
+ * @size: length of reply data buffer
+ *
+ * This function responds to the two-way messages that you receive. You
+ * must identify completely the message to which you wish to reply. ie,
+ * pathid, msgid, and trgcls. Prmmsg signifies the data is moved into
+ * the parameter list.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
+		       u8 flags, void *reply, size_t size);
+
+/**
+ * iucv_message_send
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the message is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
+ * @srccls: source class of message
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of send buffer
+ *
+ * This function transmits data to another application. Data to be
+ * transmitted is in a buffer and this is a one-way message and the
+ * receiver will not reply to the message.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
+		      u8 flags, u32 srccls, void *buffer, size_t size);
+
+/**
+ * iucv_message_send2way
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the message is sent and the reply is received
+ *	   (IUCV_IPRMDATA, IUCV_IPBUFLST, IUCV_IPPRTY, IUCV_ANSLST)
+ * @srccls: source class of message
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of send buffer
+ * @ansbuf: address of answer buffer or address of struct iucv_array
+ * @asize: size of reply buffer
+ *
+ * This function transmits data to another application. Data to be
+ * transmitted is in a buffer. The receiver of the send is expected to
+ * reply to the message and a buffer is provided into which IUCV moves
+ * the reply to this message.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
+			  u8 flags, u32 srccls, void *buffer, size_t size,
+			  void *answer, size_t asize, size_t *residual);
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index bd01b46..0e690e3 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -45,6 +45,7 @@
 #include <linux/netfilter/nf_conntrack_ftp.h>
 #include <linux/netfilter/nf_conntrack_pptp.h>
 #include <linux/netfilter/nf_conntrack_h323.h>
+#include <linux/netfilter/nf_conntrack_sane.h>
 
 /* per conntrack: application helper private data */
 union nf_conntrack_help {
@@ -52,6 +53,7 @@
 	struct nf_ct_ftp_master ct_ftp_info;
 	struct nf_ct_pptp_master ct_pptp_info;
 	struct nf_ct_h323_master ct_h323_info;
+	struct nf_ct_sane_master ct_sane_info;
 };
 
 #include <linux/types.h>
@@ -255,6 +257,12 @@
 
 DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
 #define NF_CT_STAT_INC(count) (__get_cpu_var(nf_conntrack_stat).count++)
+#define NF_CT_STAT_INC_ATOMIC(count)			\
+do {							\
+	local_bh_disable();				\
+	__get_cpu_var(nf_conntrack_stat).count++;	\
+	local_bh_enable();				\
+} while (0)
 
 /* no helper, no nat */
 #define	NF_CT_F_BASIC	0
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 41bcc9e..173c7c1 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -8,7 +8,7 @@
 
 extern struct list_head nf_conntrack_expect_list;
 extern struct kmem_cache *nf_conntrack_expect_cachep;
-extern struct file_operations exp_file_ops;
+extern const struct file_operations exp_file_ops;
 
 struct nf_conntrack_expect
 {
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 664ddcf..eb575cb 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -89,7 +89,7 @@
 
 /* Protocol registration. */
 extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
-extern int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
+extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
 
 extern struct nf_conntrack_l3proto *
 nf_ct_l3proto_find_get(u_int16_t l3proto);
@@ -106,7 +106,7 @@
 {
 	if (unlikely(l3proto >= AF_MAX))
 		return &nf_conntrack_l3proto_generic;
-	return nf_ct_l3protos[l3proto];
+	return rcu_dereference(nf_ct_l3protos[l3proto]);
 }
 
 #endif /*_NF_CONNTRACK_L3PROTO_H*/
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index fc8af08..8415182 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -109,7 +109,7 @@
 
 /* Protocol registration. */
 extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto);
-extern int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
+extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
 
 /* Generic netlink helpers */
 extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index 61c6206..bc57dd7 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -16,6 +16,7 @@
 
 #define IP_NAT_RANGE_MAP_IPS 1
 #define IP_NAT_RANGE_PROTO_SPECIFIED 2
+#define IP_NAT_RANGE_PROTO_RANDOM 4
 
 /* NAT sequence number modifications */
 struct nf_nat_seq {
diff --git a/include/net/netrom.h b/include/net/netrom.h
index e0ca112..f06852b 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -215,8 +215,8 @@
 extern int  nr_rt_ioctl(unsigned int, void __user *);
 extern void nr_link_failed(ax25_cb *, int);
 extern int  nr_route_frame(struct sk_buff *, ax25_cb *);
-extern struct file_operations nr_nodes_fops;
-extern struct file_operations nr_neigh_fops;
+extern const struct file_operations nr_nodes_fops;
+extern const struct file_operations nr_neigh_fops;
 extern void nr_rt_free(void);
 
 /* nr_subr.c */
diff --git a/include/net/rose.h b/include/net/rose.h
index 4c05a88..a4047d3 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -189,9 +189,9 @@
 
 /* rose_route.c */
 extern struct rose_neigh rose_loopback_neigh;
-extern struct file_operations rose_neigh_fops;
-extern struct file_operations rose_nodes_fops;
-extern struct file_operations rose_routes_fops;
+extern const struct file_operations rose_neigh_fops;
+extern const struct file_operations rose_nodes_fops;
+extern const struct file_operations rose_routes_fops;
 
 extern void rose_add_loopback_neigh(void);
 extern int __must_check rose_add_loopback_node(rose_address *);
diff --git a/include/net/route.h b/include/net/route.h
index 486e37a..749e4df 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -53,9 +53,11 @@
 	union
 	{
 		struct dst_entry	dst;
-		struct rtable		*rt_next;
 	} u;
 
+	/* Cache lookup keys */
+	struct flowi		fl;
+
 	struct in_device	*idev;
 	
 	unsigned		rt_flags;
@@ -69,9 +71,6 @@
 	/* Info on neighbour */
 	__be32			rt_gateway;
 
-	/* Cache lookup keys */
-	struct flowi		fl;
-
 	/* Miscellaneous cached information */
 	__be32			rt_spec_dst; /* RFC1122 specific destination */
 	struct inet_peer	*peer; /* long-living peer info */
@@ -146,7 +145,8 @@
 
 static inline int ip_route_connect(struct rtable **rp, __be32 dst,
 				   __be32 src, u32 tos, int oif, u8 protocol,
-				   __be16 sport, __be16 dport, struct sock *sk)
+				   __be16 sport, __be16 dport, struct sock *sk,
+				   int flags)
 {
 	struct flowi fl = { .oif = oif,
 			    .nl_u = { .ip4_u = { .daddr = dst,
@@ -168,7 +168,7 @@
 		*rp = NULL;
 	}
 	security_sk_classify_flow(sk, &fl);
-	return ip_route_output_flow(rp, &fl, sk, 0);
+	return ip_route_output_flow(rp, &fl, sk, flags);
 }
 
 static inline int ip_route_newports(struct rtable **rp, u8 protocol,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index cd8fa0c..5c472f2 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -802,9 +802,8 @@
 /*
  * Calculate(/check) TCP checksum
  */
-static inline __sum16 tcp_v4_check(struct tcphdr *th, int len,
-			       __be32 saddr, __be32 daddr,
-			       __wsum base)
+static inline __sum16 tcp_v4_check(int len, __be32 saddr,
+				   __be32 daddr, __wsum base)
 {
 	return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
 }
diff --git a/include/net/x25.h b/include/net/x25.h
index e47fe44..fc3f03d 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -161,6 +161,14 @@
 	unsigned long 		vc_facil_mask;	/* inc_call facilities mask */
 };
 
+struct x25_forward {
+	struct list_head	node;
+	unsigned int		lci;
+	struct net_device	*dev1;
+	struct net_device	*dev2;
+	atomic_t		refcnt;
+};
+
 static inline struct x25_sock *x25_sk(const struct sock *sk)
 {
 	return (struct x25_sock *)sk;
@@ -172,6 +180,7 @@
 extern int  sysctl_x25_reset_request_timeout;
 extern int  sysctl_x25_clear_request_timeout;
 extern int  sysctl_x25_ack_holdback_timeout;
+extern int  sysctl_x25_forward;
 
 extern int  x25_addr_ntoa(unsigned char *, struct x25_address *,
 			  struct x25_address *);
@@ -198,6 +207,13 @@
 				struct x25_dte_facilities *);
 extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
 
+/* x25_forward.c */
+extern void x25_clear_forward_by_lci(unsigned int lci);
+extern void x25_clear_forward_by_dev(struct net_device *);
+extern int x25_forward_data(int, struct x25_neigh *, struct sk_buff *);
+extern int x25_forward_call(struct x25_address *, struct x25_neigh *,
+				struct sk_buff *, int);
+
 /* x25_in.c */
 extern int  x25_process_rx_frame(struct sock *, struct sk_buff *);
 extern int  x25_backlog_rcv(struct sock *, struct sk_buff *);
@@ -282,6 +298,8 @@
 extern rwlock_t x25_list_lock;
 extern struct list_head x25_route_list;
 extern rwlock_t x25_route_list_lock;
+extern struct list_head x25_forward_list;
+extern rwlock_t x25_forward_list_lock;
 
 extern int x25_proc_init(void);
 extern void x25_proc_exit(void);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index e476541..92a1fc4 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -252,10 +252,13 @@
 						xfrm_address_t *daddr, xfrm_address_t *saddr);
 	int			(*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
 	int			(*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
+	int			(*output)(struct sk_buff *skb);
 };
 
 extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
 extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
+extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
+extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
 
 extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
@@ -359,6 +362,19 @@
 	struct xfrm_tmpl       	xfrm_vec[XFRM_MAX_DEPTH];
 };
 
+struct xfrm_migrate {
+	xfrm_address_t		old_daddr;
+	xfrm_address_t		old_saddr;
+	xfrm_address_t		new_daddr;
+	xfrm_address_t		new_saddr;
+	u8			proto;
+	u8			mode;
+	u16			reserved;
+	u32			reqid;
+	u16			old_family;
+	u16			new_family;
+};
+
 #define XFRM_KM_TIMEOUT                30
 /* which seqno */
 #define XFRM_REPLAY_SEQ		1
@@ -385,6 +401,7 @@
 	int			(*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
 	int			(*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
 	int			(*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
+	int			(*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles);
 };
 
 extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -929,14 +946,14 @@
 extern int xfrm_init_state(struct xfrm_state *x);
 extern int xfrm4_rcv(struct sk_buff *skb);
 extern int xfrm4_output(struct sk_buff *skb);
-extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
-extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
+extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
+extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
 extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
 extern int xfrm6_rcv(struct sk_buff **pskb);
 extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
 			    xfrm_address_t *saddr, u8 proto);
-extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
-extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
+extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
+extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
 extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
 extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
 extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
@@ -985,6 +1002,16 @@
 			  struct flowi *fl, int family, int strict);
 extern void xfrm_init_pmtu(struct dst_entry *dst);
 
+#ifdef CONFIG_XFRM_MIGRATE
+extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+		      struct xfrm_migrate *m, int num_bundles);
+extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m);
+extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
+					      struct xfrm_migrate *m);
+extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+			struct xfrm_migrate *m, int num_bundles);
+#endif
+
 extern wait_queue_head_t km_waitq;
 extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
 extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
@@ -1050,5 +1077,25 @@
 		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
 }
 
+#ifdef CONFIG_XFRM_MIGRATE
+static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
+{
+	return (struct xfrm_algo *)kmemdup(orig, sizeof(*orig) + orig->alg_key_len, GFP_KERNEL);
+}
+
+static inline void xfrm_states_put(struct xfrm_state **states, int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		xfrm_state_put(*(states + i));
+}
+
+static inline void xfrm_states_delete(struct xfrm_state **states, int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		xfrm_state_delete(*(states + i));
+}
+#endif
 
 #endif	/* _NET_XFRM_H */
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index c1da855..eae7e2e 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -95,6 +95,7 @@
 #define PRODID_QUATECH_DUAL_RS232	0x0012
 #define PRODID_QUATECH_DUAL_RS232_D1	0x0007
 #define PRODID_QUATECH_DUAL_RS232_D2	0x0052
+#define PRODID_QUATECH_DUAL_RS232_G	0x004d
 #define PRODID_QUATECH_QUAD_RS232	0x001b
 #define PRODID_QUATECH_DUAL_RS422	0x000e
 #define PRODID_QUATECH_QUAD_RS422	0x0045
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h
index c094e50..c36750f 100644
--- a/include/rdma/ib_addr.h
+++ b/include/rdma/ib_addr.h
@@ -110,6 +110,12 @@
 	dev_addr->broadcast[9] = (unsigned char) pkey;
 }
 
+static inline void ib_addr_get_mgid(struct rdma_dev_addr *dev_addr,
+				    union ib_gid *gid)
+{
+	memcpy(gid, dev_addr->broadcast + 4, sizeof *gid);
+}
+
 static inline void ib_addr_get_sgid(struct rdma_dev_addr *dev_addr,
 				    union ib_gid *gid)
 {
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index 97715b0..5e26b2f 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -285,18 +285,6 @@
 		       void *context,
 		       struct ib_sa_query **query);
 
-int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
-			     struct ib_device *device, u8 port_num,
-			     u8 method,
-			     struct ib_sa_mcmember_rec *rec,
-			     ib_sa_comp_mask comp_mask,
-			     int timeout_ms, gfp_t gfp_mask,
-			     void (*callback)(int status,
-					      struct ib_sa_mcmember_rec *resp,
-					      void *context),
-			     void *context,
-			     struct ib_sa_query **query);
-
 int ib_sa_service_rec_query(struct ib_sa_client *client,
 			 struct ib_device *device, u8 port_num,
 			 u8 method,
@@ -309,93 +297,82 @@
 			 void *context,
 			 struct ib_sa_query **sa_query);
 
-/**
- * ib_sa_mcmember_rec_set - Start an MCMember set query
- * @client:SA client
- * @device:device to send query on
- * @port_num: port number to send query on
- * @rec:MCMember Record to send in query
- * @comp_mask:component mask to send in query
- * @timeout_ms:time to wait for response
- * @gfp_mask:GFP mask to use for internal allocations
- * @callback:function called when query completes, times out or is
- * canceled
- * @context:opaque user context passed to callback
- * @sa_query:query context, used to cancel query
- *
- * Send an MCMember Set query to the SA (eg to join a multicast
- * group).  The callback function will be called when the query
- * completes (or fails); status is 0 for a successful response, -EINTR
- * if the query is canceled, -ETIMEDOUT is the query timed out, or
- * -EIO if an error occurred sending the query.  The resp parameter of
- * the callback is only valid if status is 0.
- *
- * If the return value of ib_sa_mcmember_rec_set() is negative, it is
- * an error code.  Otherwise it is a query ID that can be used to
- * cancel the query.
- */
-static inline int
-ib_sa_mcmember_rec_set(struct ib_sa_client *client,
-		       struct ib_device *device, u8 port_num,
-		       struct ib_sa_mcmember_rec *rec,
-		       ib_sa_comp_mask comp_mask,
-		       int timeout_ms, gfp_t gfp_mask,
-		       void (*callback)(int status,
-					struct ib_sa_mcmember_rec *resp,
-					void *context),
-		       void *context,
-		       struct ib_sa_query **query)
-{
-	return ib_sa_mcmember_rec_query(client, device, port_num,
-					IB_MGMT_METHOD_SET,
-					rec, comp_mask,
-					timeout_ms, gfp_mask, callback,
-					context, query);
-}
+struct ib_sa_multicast {
+	struct ib_sa_mcmember_rec rec;
+	ib_sa_comp_mask		comp_mask;
+	int			(*callback)(int status,
+					    struct ib_sa_multicast *multicast);
+	void			*context;
+};
 
 /**
- * ib_sa_mcmember_rec_delete - Start an MCMember delete query
- * @client:SA client
- * @device:device to send query on
- * @port_num: port number to send query on
- * @rec:MCMember Record to send in query
- * @comp_mask:component mask to send in query
- * @timeout_ms:time to wait for response
- * @gfp_mask:GFP mask to use for internal allocations
- * @callback:function called when query completes, times out or is
- * canceled
- * @context:opaque user context passed to callback
- * @sa_query:query context, used to cancel query
+ * ib_sa_join_multicast - Initiates a join request to the specified multicast
+ *   group.
+ * @client: SA client
+ * @device: Device associated with the multicast group.
+ * @port_num: Port on the specified device to associate with the multicast
+ *   group.
+ * @rec: SA multicast member record specifying group attributes.
+ * @comp_mask: Component mask indicating which group attributes of %rec are
+ *   valid.
+ * @gfp_mask: GFP mask for memory allocations.
+ * @callback: User callback invoked once the join operation completes.
+ * @context: User specified context stored with the ib_sa_multicast structure.
  *
- * Send an MCMember Delete query to the SA (eg to leave a multicast
- * group).  The callback function will be called when the query
- * completes (or fails); status is 0 for a successful response, -EINTR
- * if the query is canceled, -ETIMEDOUT is the query timed out, or
- * -EIO if an error occurred sending the query.  The resp parameter of
- * the callback is only valid if status is 0.
+ * This call initiates a multicast join request with the SA for the specified
+ * multicast group.  If the join operation is started successfully, it returns
+ * an ib_sa_multicast structure that is used to track the multicast operation.
+ * Users must free this structure by calling ib_free_multicast, even if the
+ * join operation later fails.  (The callback status is non-zero.)
  *
- * If the return value of ib_sa_mcmember_rec_delete() is negative, it
- * is an error code.  Otherwise it is a query ID that can be used to
- * cancel the query.
+ * If the join operation fails; status will be non-zero, with the following
+ * failures possible:
+ * -ETIMEDOUT: The request timed out.
+ * -EIO: An error occurred sending the query.
+ * -EINVAL: The MCMemberRecord values differed from the existing group's.
+ * -ENETRESET: Indicates that an fatal error has occurred on the multicast
+ *   group, and the user must rejoin the group to continue using it.
  */
-static inline int
-ib_sa_mcmember_rec_delete(struct ib_sa_client *client,
-			  struct ib_device *device, u8 port_num,
-			  struct ib_sa_mcmember_rec *rec,
-			  ib_sa_comp_mask comp_mask,
-			  int timeout_ms, gfp_t gfp_mask,
-			  void (*callback)(int status,
-					   struct ib_sa_mcmember_rec *resp,
-					   void *context),
-			  void *context,
-			  struct ib_sa_query **query)
-{
-	return ib_sa_mcmember_rec_query(client, device, port_num,
-					IB_SA_METHOD_DELETE,
-					rec, comp_mask,
-					timeout_ms, gfp_mask, callback,
-					context, query);
-}
+struct ib_sa_multicast *ib_sa_join_multicast(struct ib_sa_client *client,
+					     struct ib_device *device, u8 port_num,
+					     struct ib_sa_mcmember_rec *rec,
+					     ib_sa_comp_mask comp_mask, gfp_t gfp_mask,
+					     int (*callback)(int status,
+							     struct ib_sa_multicast
+								    *multicast),
+					     void *context);
+
+/**
+ * ib_free_multicast - Frees the multicast tracking structure, and releases
+ *    any reference on the multicast group.
+ * @multicast: Multicast tracking structure allocated by ib_join_multicast.
+ *
+ * This call blocks until the multicast identifier is destroyed.  It may
+ * not be called from within the multicast callback; however, returning a non-
+ * zero value from the callback will result in destroying the multicast
+ * tracking structure.
+ */
+void ib_sa_free_multicast(struct ib_sa_multicast *multicast);
+
+/**
+ * ib_get_mcmember_rec - Looks up a multicast member record by its MGID and
+ *   returns it if found.
+ * @device: Device associated with the multicast group.
+ * @port_num: Port on the specified device to associate with the multicast
+ *   group.
+ * @mgid: MGID of multicast group.
+ * @rec: Location to copy SA multicast member record.
+ */
+int ib_sa_get_mcmember_rec(struct ib_device *device, u8 port_num,
+			   union ib_gid *mgid, struct ib_sa_mcmember_rec *rec);
+
+/**
+ * ib_init_ah_from_mcmember - Initialize address handle attributes based on
+ * an SA multicast member record.
+ */
+int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
+			     struct ib_sa_mcmember_rec *rec,
+			     struct ib_ah_attr *ah_attr);
 
 /**
  * ib_init_ah_from_path - Initialize address handle attributes based on an SA
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index 36cd8a8..2d6a770 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -52,10 +52,13 @@
 	RDMA_CM_EVENT_ESTABLISHED,
 	RDMA_CM_EVENT_DISCONNECTED,
 	RDMA_CM_EVENT_DEVICE_REMOVAL,
+	RDMA_CM_EVENT_MULTICAST_JOIN,
+	RDMA_CM_EVENT_MULTICAST_ERROR
 };
 
 enum rdma_port_space {
 	RDMA_PS_SDP  = 0x0001,
+	RDMA_PS_IPOIB= 0x0002,
 	RDMA_PS_TCP  = 0x0106,
 	RDMA_PS_UDP  = 0x0111,
 	RDMA_PS_SCTP = 0x0183
@@ -294,5 +297,21 @@
  */
 int rdma_disconnect(struct rdma_cm_id *id);
 
-#endif /* RDMA_CM_H */
+/**
+ * rdma_join_multicast - Join the multicast group specified by the given
+ *   address.
+ * @id: Communication identifier associated with the request.
+ * @addr: Multicast address identifying the group to join.
+ * @context: User-defined context associated with the join request, returned
+ * to the user through the private_data pointer in multicast events.
+ */
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
+			void *context);
 
+/**
+ * rdma_leave_multicast - Leave the multicast group specified by the given
+ *   address.
+ */
+void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr);
+
+#endif /* RDMA_CM_H */
diff --git a/include/rdma/rdma_cm_ib.h b/include/rdma/rdma_cm_ib.h
index 9b176df..950424b 100644
--- a/include/rdma/rdma_cm_ib.h
+++ b/include/rdma/rdma_cm_ib.h
@@ -44,7 +44,7 @@
 int rdma_set_ib_paths(struct rdma_cm_id *id,
 		      struct ib_sa_path_rec *path_rec, int num_paths);
 
-/* Global qkey for UD QPs and multicast groups. */
-#define RDMA_UD_QKEY 0x01234567
+/* Global qkey for UDP QPs and multicast groups. */
+#define RDMA_UDP_QKEY 0x01234567
 
 #endif /* RDMA_CM_IB_H */
diff --git a/include/rdma/rdma_user_cm.h b/include/rdma/rdma_user_cm.h
index 9572ab8..f632b0c 100644
--- a/include/rdma/rdma_user_cm.h
+++ b/include/rdma/rdma_user_cm.h
@@ -38,7 +38,7 @@
 #include <rdma/ib_user_verbs.h>
 #include <rdma/ib_user_sa.h>
 
-#define RDMA_USER_CM_ABI_VERSION	3
+#define RDMA_USER_CM_ABI_VERSION	4
 
 #define RDMA_MAX_PRIVATE_DATA		256
 
@@ -58,7 +58,9 @@
 	RDMA_USER_CM_CMD_GET_EVENT,
 	RDMA_USER_CM_CMD_GET_OPTION,
 	RDMA_USER_CM_CMD_SET_OPTION,
-	RDMA_USER_CM_CMD_NOTIFY
+	RDMA_USER_CM_CMD_NOTIFY,
+	RDMA_USER_CM_CMD_JOIN_MCAST,
+	RDMA_USER_CM_CMD_LEAVE_MCAST
 };
 
 /*
@@ -188,6 +190,13 @@
 	__u32 event;
 };
 
+struct rdma_ucm_join_mcast {
+	__u64 response;		/* rdma_ucm_create_id_resp */
+	__u64 uid;
+	struct sockaddr_in6 addr;
+	__u32 id;
+};
+
 struct rdma_ucm_get_event {
 	__u64 response;
 };
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index 02f6e4b..4a44278 100644
--- a/include/scsi/iscsi_proto.h
+++ b/include/scsi/iscsi_proto.h
@@ -40,6 +40,14 @@
 }
 #define zero_data(p) {p[0]=0;p[1]=0;p[2]=0;}
 
+/* initiator tags; opaque for target */
+typedef uint32_t __bitwise__ itt_t;
+/* below makes sense only for initiator that created this tag */
+#define build_itt(itt, id, age) ((__force itt_t)\
+	((itt) | ((id) << ISCSI_CID_SHIFT) | ((age) << ISCSI_AGE_SHIFT)))
+#define get_itt(itt) ((__force uint32_t)(itt_t)(itt) & ISCSI_ITT_MASK)
+#define RESERVED_ITT ((__force itt_t)0xffffffff)
+
 /*
  * iSCSI Template Message Header
  */
@@ -50,7 +58,7 @@
 	uint8_t		hlength;	/* AHSs total length */
 	uint8_t		dlength[3];	/* Data length */
 	uint8_t		lun[8];
-	__be32		itt;		/* Initiator Task Tag */
+	itt_t		itt;		/* Initiator Task Tag, opaque for target */
 	__be32		ttt;		/* Target Task Tag */
 	__be32		statsn;
 	__be32		exp_statsn;
@@ -111,7 +119,7 @@
 	uint8_t hlength;
 	uint8_t dlength[3];
 	uint8_t lun[8];
-	__be32 itt;	/* Initiator Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
 	__be32 data_length;
 	__be32 cmdsn;
 	__be32 exp_statsn;
@@ -148,7 +156,7 @@
 	uint8_t hlength;
 	uint8_t dlength[3];
 	uint8_t rsvd[8];
-	__be32	itt;	/* Initiator Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
 	__be32	rsvd1;
 	__be32	statsn;
 	__be32	exp_cmdsn;
@@ -206,7 +214,7 @@
 	uint8_t rsvd3;
 	uint8_t dlength[3];
 	uint8_t lun[8];
-	__be32	itt;	/* Initiator Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
 	__be32	ttt;	/* Target Transfer Tag */
 	__be32	cmdsn;
 	__be32	exp_statsn;
@@ -221,7 +229,7 @@
 	uint8_t rsvd3;
 	uint8_t dlength[3];
 	uint8_t lun[8];
-	__be32	itt;	/* Initiator Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
 	__be32	ttt;	/* Target Transfer Tag */
 	__be32	statsn;
 	__be32	exp_cmdsn;
@@ -237,8 +245,8 @@
 	uint8_t hlength;
 	uint8_t dlength[3];
 	uint8_t lun[8];
-	__be32	itt;	/* Initiator Task Tag */
-	__be32	rtt;	/* Reference Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
+	itt_t	 rtt;	/* Reference Task Tag */
 	__be32	cmdsn;
 	__be32	exp_statsn;
 	__be32	refcmdsn;
@@ -267,8 +275,8 @@
 	uint8_t hlength;
 	uint8_t dlength[3];
 	uint8_t rsvd2[8];
-	__be32	itt;	/* Initiator Task Tag */
-	__be32	rtt;	/* Reference Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
+	itt_t	 rtt;	/* Reference Task Tag */
 	__be32	statsn;
 	__be32	exp_cmdsn;
 	__be32	max_cmdsn;
@@ -293,7 +301,7 @@
 	uint8_t	hlength;
 	uint8_t	dlength[3];
 	uint8_t lun[8];
-	__be32	itt;	/* Initiator Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
 	__be32	ttt;	/* Target Transfer Tag */
 	__be32	statsn;
 	__be32	exp_cmdsn;
@@ -311,7 +319,7 @@
 	uint8_t rsvd3;
 	uint8_t dlength[3];
 	uint8_t lun[8];
-	__be32	itt;
+	itt_t	 itt;
 	__be32	ttt;
 	__be32	rsvd4;
 	__be32	exp_statsn;
@@ -331,7 +339,7 @@
 	uint8_t hlength;
 	uint8_t dlength[3];
 	uint8_t lun[8];
-	__be32	itt;
+	itt_t	 itt;
 	__be32	ttt;
 	__be32	statsn;
 	__be32	exp_cmdsn;
@@ -355,7 +363,7 @@
 	uint8_t hlength;
 	uint8_t dlength[3];
 	uint8_t rsvd4[8];
-	__be32	itt;
+	itt_t	 itt;
 	__be32	ttt;
 	__be32	cmdsn;
 	__be32	exp_statsn;
@@ -373,7 +381,7 @@
 	uint8_t hlength;
 	uint8_t dlength[3];
 	uint8_t rsvd4[8];
-	__be32	itt;
+	itt_t	 itt;
 	__be32	ttt;
 	__be32	statsn;
 	__be32	exp_cmdsn;
@@ -392,7 +400,7 @@
 	uint8_t dlength[3];
 	uint8_t isid[6];	/* Initiator Session ID */
 	__be16	tsih;	/* Target Session Handle */
-	__be32	itt;	/* Initiator Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
 	__be16	cid;
 	__be16	rsvd3;
 	__be32	cmdsn;
@@ -421,7 +429,7 @@
 	uint8_t dlength[3];
 	uint8_t isid[6];	/* Initiator Session ID */
 	__be16	tsih;	/* Target Session Handle */
-	__be32	itt;	/* Initiator Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
 	__be32	rsvd3;
 	__be32	statsn;
 	__be32	exp_cmdsn;
@@ -478,7 +486,7 @@
 	uint8_t hlength;
 	uint8_t dlength[3];
 	uint8_t rsvd2[8];
-	__be32	itt;	/* Initiator Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
 	__be16	cid;
 	uint8_t rsvd3[2];
 	__be32	cmdsn;
@@ -505,7 +513,7 @@
 	uint8_t hlength;
 	uint8_t dlength[3];
 	uint8_t rsvd3[8];
-	__be32	itt;	/* Initiator Task Tag */
+	itt_t	 itt;	/* Initiator Task Tag */
 	__be32	rsvd4;
 	__be32	statsn;
 	__be32	exp_cmdsn;
@@ -528,7 +536,7 @@
 	uint8_t opcode;
 	uint8_t flags;
 	uint8_t rsvd2[14];
-	__be32	itt;
+	itt_t	 itt;
 	__be32	begrun;
 	__be32	runlength;
 	__be32	exp_statsn;
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 0c775fc..ad0182e 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -323,12 +323,20 @@
 	struct sas_ha_struct *ha;
 };
 
+enum sas_ha_state {
+	SAS_HA_REGISTERED,
+	SAS_HA_UNREGISTERED
+};
+
 struct sas_ha_struct {
 /* private: */
 	spinlock_t       event_lock;
 	struct sas_ha_event ha_events[HA_NUM_EVENTS];
 	unsigned long	 pending;
 
+	enum sas_ha_state state;
+	spinlock_t 	  state_lock;
+
 	struct scsi_core core;
 
 /* public: */
@@ -553,15 +561,15 @@
 #define SAS_TASK_STATE_PENDING      1
 #define SAS_TASK_STATE_DONE         2
 #define SAS_TASK_STATE_ABORTED      4
-#define SAS_TASK_INITIATOR_ABORTED  8
+#define SAS_TASK_NEED_DEV_RESET     8
+#define SAS_TASK_AT_INITIATOR       16
 
 static inline struct sas_task *sas_alloc_task(gfp_t flags)
 {
 	extern struct kmem_cache *sas_task_cache;
-	struct sas_task *task = kmem_cache_alloc(sas_task_cache, flags);
+	struct sas_task *task = kmem_cache_zalloc(sas_task_cache, flags);
 
 	if (task) {
-		memset(task, 0, sizeof(*task));
 		INIT_LIST_HEAD(&task->list);
 		spin_lock_init(&task->task_state_lock);
 		task->task_state_flags = SAS_TASK_STATE_PENDING;
@@ -613,6 +621,9 @@
 extern int sas_register_ha(struct sas_ha_struct *);
 extern int sas_unregister_ha(struct sas_ha_struct *);
 
+int sas_set_phy_speed(struct sas_phy *phy,
+		      struct sas_phy_linkrates *rates);
+int sas_phy_enable(struct sas_phy *phy, int enabled);
 int sas_phy_reset(struct sas_phy *phy, int hard_reset);
 extern int sas_queuecommand(struct scsi_cmnd *,
 		     void (*scsi_done)(struct scsi_cmnd *));
@@ -646,6 +657,9 @@
 
 void sas_init_dev(struct domain_device *);
 
-void sas_task_abort(struct work_struct *);
+void sas_task_abort(struct sas_task *);
+int __sas_task_abort(struct sas_task *);
+int sas_eh_device_reset_handler(struct scsi_cmnd *cmd);
+int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd);
 
 #endif /* _SASLIB_H_ */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index ebf31b1..9dd37e2 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -122,6 +122,7 @@
 	unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
 	unsigned select_no_atn:1;
 	unsigned fix_capacity:1;	/* READ_CAPACITY is too high by 1 */
+	unsigned guess_capacity:1;	/* READ_CAPACITY might be too high by 1 */
 	unsigned retry_hwerror:1;	/* Retry HARDWARE_ERROR */
 
 	unsigned int device_blocked;	/* Device returned QUEUE_FULL. */
diff --git a/include/scsi/scsi_tgt_if.h b/include/scsi/scsi_tgt_if.h
index 46d5e70..07d6e77 100644
--- a/include/scsi/scsi_tgt_if.h
+++ b/include/scsi/scsi_tgt_if.h
@@ -83,8 +83,5 @@
 } __attribute__ ((aligned (sizeof(uint64_t))));
 
 #define TGT_RING_SIZE (1UL << 16)
-#define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT)
-#define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event))
-#define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES)
 
 #endif
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index cca1d49..3c18baa 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -22,6 +22,7 @@
 
 #include <linux/transport_class.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
 
 struct scsi_transport_template {
 	/* the attribute containers */
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index 59633a82d..9aedc19 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -54,6 +54,7 @@
 struct sas_phy {
 	struct device		dev;
 	int			number;
+	int			enabled;
 
 	/* phy identification */
 	struct sas_identify	identify;
@@ -163,6 +164,7 @@
 	int (*get_enclosure_identifier)(struct sas_rphy *, u64 *);
 	int (*get_bay_identifier)(struct sas_rphy *);
 	int (*phy_reset)(struct sas_phy *, int);
+	int (*phy_enable)(struct sas_phy *, int);
 	int (*set_phy_speed)(struct sas_phy *, struct sas_phy_linkrates *);
 };
 
@@ -180,6 +182,7 @@
 extern struct sas_rphy *sas_expander_alloc(struct sas_port *, enum sas_device_type);
 void sas_rphy_free(struct sas_rphy *);
 extern int sas_rphy_add(struct sas_rphy *);
+extern void sas_rphy_remove(struct sas_rphy *);
 extern void sas_rphy_delete(struct sas_rphy *);
 extern int scsi_is_sas_rphy(const struct device *);
 
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index da180f7..286e962 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -85,6 +85,7 @@
 #define spi_pcomp_en(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en)
 #define spi_hold_mcs(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->hold_mcs)
 #define spi_initial_dv(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv)
+#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
 
 #define spi_support_sync(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_sync)
 #define spi_support_wide(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_wide)
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 3372039..246ac23 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -375,6 +375,7 @@
 #define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */
 #define AC97_SCAP_NO_SPDIF	(1<<9)	/* don't build SPDIF controls */
 #define AC97_SCAP_EAPD_LED	(1<<10)	/* EAPD as mute LED */
+#define AC97_SCAP_POWER_SAVE	(1<<11)	/* capable for aggresive power-saving */
 
 /* ac97->flags */
 #define AC97_HAS_PC_BEEP	(1<<0)	/* force PC Speaker usage */
@@ -425,6 +426,7 @@
 
 struct snd_ac97_bus_ops {
 	void (*reset) (struct snd_ac97 *ac97);
+	void (*warm_reset)(struct snd_ac97 *ac97);
 	void (*write) (struct snd_ac97 *ac97, unsigned short reg, unsigned short val);
 	unsigned short (*read) (struct snd_ac97 *ac97, unsigned short reg);
 	void (*wait) (struct snd_ac97 *ac97);
@@ -501,6 +503,7 @@
 			unsigned short id[3];		// codec IDs (lower 16-bit word)
 			unsigned short pcmreg[3];	// PCM registers
 			unsigned short codec_cfg[3];	// CODEC_CFG bits
+			unsigned char swap_mic_linein;	// AD1986/AD1986A only
 		} ad18xx;
 		unsigned int dev_flags;		/* device specific */
 	} spec;
@@ -510,7 +513,6 @@
 
 #ifdef CONFIG_SND_AC97_POWER_SAVE
 	unsigned int power_up;	/* power states */
-	struct workqueue_struct *power_workq;
 	struct delayed_work power_work;
 #endif
 	struct device dev;
diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h
index c8de6f8..b2c3f00 100644
--- a/include/sound/ad1848.h
+++ b/include/sound/ad1848.h
@@ -185,7 +185,7 @@
 	int index;
 	int type;
 	unsigned long private_value;
-	unsigned int *tlv;
+	const unsigned int *tlv;
 };
 
 #define AD1848_SINGLE(xname, xindex, reg, shift, mask, invert) \
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index 2ee0616..c149d3b25 100644
--- a/include/sound/ak4114.h
+++ b/include/sound/ak4114.h
@@ -181,7 +181,6 @@
 	unsigned long ccrc_errors;
 	unsigned char rcs0;
 	unsigned char rcs1;
-	struct workqueue_struct *workqueue;
 	struct delayed_work work;
 	void *change_callback_private;
 	void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1);
@@ -189,7 +188,7 @@
 
 int snd_ak4114_create(struct snd_card *card,
 		      ak4114_read_t *read, ak4114_write_t *write,
-		      unsigned char pgm[7], unsigned char txcsb[5],
+		      const unsigned char pgm[7], const unsigned char txcsb[5],
 		      void *private_data, struct ak4114 **r_ak4114);
 void snd_ak4114_reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char mask, unsigned char val);
 void snd_ak4114_reinit(struct ak4114 *ak4114);
diff --git a/include/sound/ak4117.h b/include/sound/ak4117.h
index 2b96c32..d650d52 100644
--- a/include/sound/ak4117.h
+++ b/include/sound/ak4117.h
@@ -178,7 +178,7 @@
 };
 
 int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write,
-		      unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117);
+		      const unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117);
 void snd_ak4117_reg_write(struct ak4117 *ak4117, unsigned char reg, unsigned char mask, unsigned char val);
 void snd_ak4117_reinit(struct ak4117 *ak4117);
 int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *capture_substream);
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
index d0deca6..aa49dda 100644
--- a/include/sound/ak4xxx-adda.h
+++ b/include/sound/ak4xxx-adda.h
@@ -50,6 +50,8 @@
 	char *name;		/* capture gain volume label */
 	char *switch_name;	/* capture switch */
 	unsigned int num_channels;
+	char *selector_name;	/* capture source select label */
+	const char **input_names; /* capture source names (NULL terminated) */
 };
 
 struct snd_akm4xxx {
@@ -69,8 +71,8 @@
 	} type;
 
 	/* (array) information of combined codecs */
-	struct snd_akm4xxx_dac_channel *dac_info;
-	struct snd_akm4xxx_adc_channel *adc_info;
+	const struct snd_akm4xxx_dac_channel *dac_info;
+	const struct snd_akm4xxx_adc_channel *adc_info;
 
 	struct snd_ak4xxx_ops ops;
 };
diff --git a/include/sound/control.h b/include/sound/control.h
index 1de148b..72e759f 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -49,7 +49,7 @@
 	snd_kcontrol_put_t *put;
 	union {
 		snd_kcontrol_tlv_rw_t *c;
-		unsigned int *p;
+		const unsigned int *p;
 	} tlv;
 	unsigned long private_value;
 };
@@ -69,7 +69,7 @@
 	snd_kcontrol_put_t *put;
 	union {
 		snd_kcontrol_tlv_rw_t *c;
-		unsigned int *p;
+		const unsigned int *p;
 	} tlv;
 	unsigned long private_value;
 	void *private_data;
@@ -108,7 +108,6 @@
 
 void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id);
 
-struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol * kcontrol, unsigned int access);
 struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data);
 void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
 int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
diff --git a/include/sound/core.h b/include/sound/core.h
index 521f036..4b9e609 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -211,9 +211,40 @@
 
 void snd_request_card(int card);
 
-int snd_register_device(int type, struct snd_card *card, int dev,
-			const struct file_operations *f_ops, void *private_data,
-			const char *name);
+int snd_register_device_for_dev(int type, struct snd_card *card,
+				int dev,
+				const struct file_operations *f_ops,
+				void *private_data,
+				const char *name,
+				struct device *device);
+
+/**
+ * snd_register_device - Register the ALSA device file for the card
+ * @type: the device type, SNDRV_DEVICE_TYPE_XXX
+ * @card: the card instance
+ * @dev: the device index
+ * @f_ops: the file operations
+ * @private_data: user pointer for f_ops->open()
+ * @name: the device file name
+ *
+ * Registers an ALSA device file for the given card.
+ * The operators have to be set in reg parameter.
+ *
+ * This function uses the card's device pointer to link to the
+ * correct &struct device.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+static inline int snd_register_device(int type, struct snd_card *card, int dev,
+				      const struct file_operations *f_ops,
+				      void *private_data,
+				      const char *name)
+{
+	return snd_register_device_for_dev(type, card, dev, f_ops,
+					   private_data, name,
+					   snd_card_get_device_link(card));
+}
+
 int snd_unregister_device(int type, struct snd_card *card, int dev);
 void *snd_lookup_minor_data(unsigned int minor, int type);
 int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
@@ -396,6 +427,29 @@
 #endif
 #endif
 
-#include "typedefs.h"
+/* PCI quirk list helper */
+struct snd_pci_quirk {
+	unsigned short subvendor;	/* PCI subvendor ID */
+	unsigned short subdevice;	/* PCI subdevice ID */
+	int value;			/* value */
+#ifdef CONFIG_SND_DEBUG_DETECT
+	const char *name;		/* name of the device (optional) */
+#endif
+};
+
+#define _SND_PCI_QUIRK_ID(vend,dev) \
+	.subvendor = (vend), .subdevice = (dev)
+#define SND_PCI_QUIRK_ID(vend,dev) {_SND_PCI_QUIRK_ID(vend, dev)}
+#ifdef CONFIG_SND_DEBUG_DETECT
+#define SND_PCI_QUIRK(vend,dev,xname,val) \
+	{_SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname)}
+#else
+#define SND_PCI_QUIRK(vend,dev,xname,val) \
+	{_SND_PCI_QUIRK_ID(vend, dev), .value = (val)}
+#endif
+
+const struct snd_pci_quirk *
+snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list);
+
 
 #endif /* __SOUND_CORE_H */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 3d3c151..23e45a4 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -188,7 +188,35 @@
 #define HCFG_LEGACYINT		0x00200000	/* 1 = legacy event captured. Write 1 to clear.	*/
 						/* NOTE: The rest of the bits in this register	*/
 						/* _are_ relevant under Linux.			*/
-#define HCFG_CODECFORMAT_MASK	0x00070000	/* CODEC format					*/
+#define HCFG_PUSH_BUTTON_ENABLE 0x00100000	/* Enables Volume Inc/Dec and Mute functions    */
+#define HCFG_BAUD_RATE		0x00080000	/* 0 = 48kHz, 1 = 44.1kHz			*/
+#define HCFG_EXPANDED_MEM	0x00040000	/* 1 = any 16M of 4G addr, 0 = 32M of 2G addr	*/
+#define HCFG_CODECFORMAT_MASK	0x00030000	/* CODEC format					*/
+
+/* Specific to Alice2, CA0102 */
+#define HCFG_CODECFORMAT_AC97_1	0x00000000	/* AC97 CODEC format -- Ver 1.03		*/
+#define HCFG_CODECFORMAT_AC97_2	0x00010000	/* AC97 CODEC format -- Ver 2.1			*/
+#define HCFG_AUTOMUTE_ASYNC	0x00008000	/* When set, the async sample rate convertors	*/
+						/* will automatically mute their output when	*/
+						/* they are not rate-locked to the external	*/
+						/* async audio source  				*/
+#define HCFG_AUTOMUTE_SPDIF	0x00004000	/* When set, the async sample rate convertors	*/
+						/* will automatically mute their output when	*/
+						/* the SPDIF V-bit indicates invalid audio	*/
+#define HCFG_EMU32_SLAVE	0x00002000	/* 0 = Master, 1 = Slave. Slave for EMU1010	*/
+#define HCFG_SLOW_RAMP		0x00001000	/* Increases Send Smoothing time constant	*/
+/* 0x00000800 not used on Alice2 */
+#define HCFG_PHASE_TRACK_MASK	0x00000700	/* When set, forces corresponding input to	*/
+						/* phase track the previous input.		*/
+						/* I2S0 can phase track the last S/PDIF input	*/
+#define HCFG_I2S_ASRC_ENABLE	0x00000070	/* When set, enables asynchronous sample rate   */
+						/* conversion for the corresponding		*/
+ 						/* I2S format input				*/
+/* Rest of HCFG 0x0000000f same as below. LOCKSOUNDCACHE etc.  */
+
+
+
+/* Older chips */
 #define HCFG_CODECFORMAT_AC97	0x00000000	/* AC97 CODEC format -- Primary Output		*/
 #define HCFG_CODECFORMAT_I2S	0x00010000	/* I2S CODEC format -- Secondary (Rear) Output	*/
 #define HCFG_GPINPUT0		0x00004000	/* External pin112				*/
@@ -432,6 +460,7 @@
 #define FXRT_CHANNELC		0x0f000000	/* Effects send bus number for channel's effects send C	*/
 #define FXRT_CHANNELD		0xf0000000	/* Effects send bus number for channel's effects send D	*/
 
+#define A_HR			0x0b	/* High Resolution. 24bit playback from host to DSP. */
 #define MAPA			0x0c		/* Cache map A						*/
 
 #define MAPB			0x0d		/* Cache map B						*/
@@ -439,6 +468,8 @@
 #define MAP_PTE_MASK		0xffffe000	/* The 19 MSBs of the PTE indexed by the PTI		*/
 #define MAP_PTI_MASK		0x00001fff	/* The 13 bit index to one of the 8192 PTE dwords      	*/
 
+/* 0x0e, 0x0f: Not used */
+
 #define ENVVOL			0x10		/* Volume envelope register				*/
 #define ENVVOL_MASK		0x0000ffff	/* Current value of volume envelope state variable	*/  
 						/* 0x8000-n == 666*n usec delay	       			*/
@@ -527,7 +558,7 @@
 						/* NOTE: All channels contain internal variables; do	*/
 						/* not write to these locations.			*/
 
-/* 1f something */
+/* 0x1f: not used */
 
 #define CD0			0x20		/* Cache data 0 register				*/
 #define CD1			0x21		/* Cache data 1 register				*/
@@ -597,6 +628,8 @@
 #define FXWC_SPDIFLEFT          (1<<22)		/* 0x00400000 */
 #define FXWC_SPDIFRIGHT         (1<<23)		/* 0x00800000 */
 
+#define A_TBLSZ			0x43	/* Effects Tank Internal Table Size. Only low byte or register used */
+
 #define TCBS			0x44		/* Tank cache buffer size register			*/
 #define TCBS_MASK		0x00000007	/* Tank cache buffer size field				*/
 #define TCBS_BUFFSIZE_16K	0x00000000
@@ -617,7 +650,7 @@
 #define FXBA			0x47		/* FX Buffer Address */
 #define FXBA_MASK		0xfffff000	/* 20 bit base address					*/
 
-/* 0x48 something - word access, defaults to 3f */
+#define A_HWM			0x48	/* High PCI Water Mark - word access, defaults to 3f */
 
 #define MICBS			0x49		/* Microphone buffer size register			*/
 
@@ -661,6 +694,18 @@
 #define ADCBS_BUFSIZE_57344	0x0000001e
 #define ADCBS_BUFSIZE_65536	0x0000001f
 
+/* Current Send B, A Amounts */
+#define A_CSBA			0x4c
+
+/* Current Send D, C Amounts */
+#define A_CSDC			0x4d
+
+/* Current Send F, E Amounts */
+#define A_CSFE			0x4e
+
+/* Current Send H, G Amounts */
+#define A_CSHG			0x4f
+
 
 #define CDCS			0x50		/* CD-ROM digital channel status register	*/
 
@@ -668,6 +713,9 @@
 
 #define DBG			0x52		/* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
 
+/* S/PDIF Input C Channel Status */
+#define A_SPSC			0x52
+
 #define REG53			0x53		/* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
 
 #define A_DBG			 0x53
@@ -708,6 +756,8 @@
 #define SPCS_NOTAUDIODATA	0x00000002	/* 0 = Digital audio, 1 = not audio		*/
 #define SPCS_PROFESSIONAL	0x00000001	/* 0 = Consumer (IEC-958), 1 = pro (AES3-1992)	*/
 
+/* 0x57: Not used */
+
 /* The 32-bit CLIx and SOLx registers all have one bit per channel control/status      		*/
 #define CLIEL			0x58		/* Channel loop interrupt enable low register	*/
 
@@ -733,6 +783,9 @@
 #define AC97SLOT_CNTR		0x10            /* Center enable */
 #define AC97SLOT_LFE		0x20            /* LFE enable */
 
+/* PCB Revision */
+#define A_PCB			0x5f
+
 // NOTE: 0x60,61,62: 64-bit
 #define CDSRCS			0x60		/* CD-ROM Sample Rate Converter status register	*/
 
@@ -780,9 +833,18 @@
 
 #define HLIPH			0x69		/* Channel half loop interrupt pending high register	*/
 
-// 0x6a,6b,6c used for some recording
-// 0x6d unused
-// 0x6e,6f - tanktable base / offset
+/* S/PDIF Host Record Index (bypasses SRC) */
+#define A_SPRI			0x6a
+/* S/PDIF Host Record Address */
+#define A_SPRA			0x6b
+/* S/PDIF Host Record Control */
+#define A_SPRC			0x6c
+/* Delayed Interrupt Counter & Enable */
+#define A_DICE			0x6d
+/* Tank Table Base */
+#define A_TTB			0x6e
+/* Tank Delay Offset */
+#define A_TDOF			0x6f
 
 /* This is the MPU port on the card (via the game port)						*/
 #define A_MUDATA1		0x70
@@ -800,6 +862,7 @@
 #define A_FXWC1			0x74            /* Selects 0x7f-0x60 for FX recording           */
 #define A_FXWC2			0x75		/* Selects 0x9f-0x80 for FX recording           */
 
+/* Extended Hardware Control */
 #define A_SPDIF_SAMPLERATE	0x76		/* Set the sample rate of SPDIF output		*/
 #define A_SAMPLE_RATE		0x76		/* Various sample rate settings. */
 #define A_SAMPLE_RATE_NOT_USED  0x0ffc111e	/* Bits that are not used and cannot be set. 	*/
@@ -822,8 +885,20 @@
 #define A_PCM_96000		0x00004000
 #define A_PCM_44100		0x00008000
 
-/* 0x77,0x78,0x79 "something i2s-related" - default to 0x01080000 on my audigy 2 ZS --rlrevell	*/
-/* 0x7a, 0x7b - lookup tables */
+/* I2S0 Sample Rate Tracker Status */
+#define A_SRT3			0x77
+
+/* I2S1 Sample Rate Tracker Status */
+#define A_SRT4			0x78
+
+/* I2S2 Sample Rate Tracker Status */
+#define A_SRT5			0x79
+/* - default to 0x01080000 on my audigy 2 ZS --rlrevell	*/
+
+/* Tank Table DMA Address */
+#define A_TTDA			0x7a
+/* Tank Table DMA Data */
+#define A_TTDD			0x7b
 
 #define A_FXRT2			0x7c
 #define A_FXRT_CHANNELE		0x0000003f	/* Effects send bus number for channel's effects send E	*/
@@ -845,7 +920,7 @@
 #define A_FXRT_CHANNELC		0x003f0000
 #define A_FXRT_CHANNELD		0x3f000000
 
-
+/* 0x7f: Not used */
 /* Each FX general purpose register is 32 bits in length, all bits are used			*/
 #define FXGPREGBASE		0x100		/* FX general purpose registers base       	*/
 #define A_FXGPREGBASE		0x400		/* Audigy GPRs, 0x400 to 0x5ff			*/
@@ -886,6 +961,293 @@
 #define A_HIWORD_RESULT_MASK	0x007ff000
 #define A_HIWORD_OPA_MASK	0x000007ff
 
+/************************************************************************************************/
+/* EMU1010m HANA FPGA registers									*/
+/************************************************************************************************/
+#define EMU_HANA_DESTHI		0x00	/* 0000xxx  3 bits Link Destination */
+#define EMU_HANA_DESTLO		0x01	/* 00xxxxx  5 bits */
+#define EMU_HANA_SRCHI		0x02	/* 0000xxx  3 bits Link Source */
+#define EMU_HANA_SRCLO		0x03	/* 00xxxxx  5 bits */
+#define EMU_HANA_DOCK_PWR	0x04	/* 000000x  1 bits Audio Dock power */
+#define EMU_HANA_DOCK_PWR_ON		0x01 /* Audio Dock power on */
+#define EMU_HANA_WCLOCK		0x05	/* 0000xxx  3 bits Word Clock source select  */
+					/* Must be written after power on to reset DLL */
+					/* One is unable to detect the Audio dock without this */
+#define EMU_HANA_WCLOCK_SRC_MASK	0x07
+#define EMU_HANA_WCLOCK_INT_48K		0x00
+#define EMU_HANA_WCLOCK_INT_44_1K	0x01
+#define EMU_HANA_WCLOCK_HANA_SPDIF_IN	0x02
+#define EMU_HANA_WCLOCK_HANA_ADAT_IN	0x03
+#define EMU_HANA_WCLOCK_SYNC_BNCN	0x04
+#define EMU_HANA_WCLOCK_2ND_HANA	0x05
+#define EMU_HANA_WCLOCK_SRC_RESERVED	0x06
+#define EMU_HANA_WCLOCK_OFF		0x07 /* For testing, forces fallback to DEFCLOCK */
+#define EMU_HANA_WCLOCK_MULT_MASK	0x18
+#define EMU_HANA_WCLOCK_1X		0x00
+#define EMU_HANA_WCLOCK_2X		0x08
+#define EMU_HANA_WCLOCK_4X		0x10
+#define EMU_HANA_WCLOCK_MULT_RESERVED	0x18
+
+#define EMU_HANA_DEFCLOCK	0x06	/* 000000x  1 bits Default Word Clock  */
+#define EMU_HANA_DEFCLOCK_48K		0x00
+#define EMU_HANA_DEFCLOCK_44_1K		0x01
+
+#define EMU_HANA_UNMUTE		0x07	/* 000000x  1 bits Mute all audio outputs  */
+#define EMU_MUTE			0x00
+#define EMU_UNMUTE			0x01
+
+#define EMU_HANA_FPGA_CONFIG	0x08	/* 00000xx  2 bits Config control of FPGAs  */
+#define EMU_HANA_FPGA_CONFIG_AUDIODOCK	0x01 /* Set in order to program FPGA on Audio Dock */
+#define EMU_HANA_FPGA_CONFIG_HANA	0x02 /* Set in order to program FPGA on Hana */
+
+#define EMU_HANA_IRQ_ENABLE	0x09	/* 000xxxx  4 bits IRQ Enable  */
+#define EMU_HANA_IRQ_WCLK_CHANGED	0x01
+#define EMU_HANA_IRQ_ADAT		0x02
+#define EMU_HANA_IRQ_DOCK		0x04
+#define EMU_HANA_IRQ_DOCK_LOST		0x08
+
+#define EMU_HANA_SPDIF_MODE	0x0a	/* 00xxxxx  5 bits SPDIF MODE  */
+#define EMU_HANA_SPDIF_MODE_TX_COMSUMER	0x00
+#define EMU_HANA_SPDIF_MODE_TX_PRO	0x01
+#define EMU_HANA_SPDIF_MODE_TX_NOCOPY	0x02
+#define EMU_HANA_SPDIF_MODE_RX_COMSUMER	0x00
+#define EMU_HANA_SPDIF_MODE_RX_PRO	0x04
+#define EMU_HANA_SPDIF_MODE_RX_NOCOPY	0x08
+#define EMU_HANA_SPDIF_MODE_RX_INVALID	0x10
+
+#define EMU_HANA_OPTICAL_TYPE	0x0b	/* 00000xx  2 bits ADAT or SPDIF in/out  */
+#define EMU_HANA_OPTICAL_IN_SPDIF	0x00
+#define EMU_HANA_OPTICAL_IN_ADAT	0x01
+#define EMU_HANA_OPTICAL_OUT_SPDIF	0x00
+#define EMU_HANA_OPTICAL_OUT_ADAT	0x02
+
+#define EMU_HANA_MIDI_IN		0x0c	/* 000000x  1 bit  Control MIDI  */
+#define EMU_HANA_MIDI_IN_FROM_HAMOA	0x00 /* HAMOA MIDI in to Alice 2 MIDI B */
+#define EMU_HANA_MIDI_IN_FROM_DOCK	0x01 /* Audio Dock MIDI in to Alice 2 MIDI B */
+
+#define EMU_HANA_DOCK_LEDS_1	0x0d	/* 000xxxx  4 bit  Audio Dock LEDs  */
+#define EMU_HANA_DOCK_LEDS_1_MIDI1	0x01	/* MIDI 1 LED on */
+#define EMU_HANA_DOCK_LEDS_1_MIDI2	0x02	/* MIDI 2 LED on */
+#define EMU_HANA_DOCK_LEDS_1_SMPTE_IN	0x04	/* SMPTE IN LED on */
+#define EMU_HANA_DOCK_LEDS_1_SMPTE_OUT	0x08	/* SMPTE OUT LED on */
+
+#define EMU_HANA_DOCK_LEDS_2	0x0e	/* 0xxxxxx  6 bit  Audio Dock LEDs  */
+#define EMU_HANA_DOCK_LEDS_2_44K	0x01	/* 44.1 kHz LED on */
+#define EMU_HANA_DOCK_LEDS_2_48K	0x02	/* 48 kHz LED on */
+#define EMU_HANA_DOCK_LEDS_2_96K	0x04	/* 96 kHz LED on */
+#define EMU_HANA_DOCK_LEDS_2_192K	0x08	/* 192 kHz LED on */
+#define EMU_HANA_DOCK_LEDS_2_LOCK	0x10	/* LOCK LED on */
+#define EMU_HANA_DOCK_LEDS_2_EXT	0x20	/* EXT LED on */
+
+#define EMU_HANA_DOCK_LEDS_3	0x0f	/* 0xxxxxx  6 bit  Audio Dock LEDs  */
+#define EMU_HANA_DOCK_LEDS_3_CLIP_A	0x01	/* Mic A Clip LED on */
+#define EMU_HANA_DOCK_LEDS_3_CLIP_B	0x02	/* Mic B Clip LED on */
+#define EMU_HANA_DOCK_LEDS_3_SIGNAL_A	0x04	/* Signal A Clip LED on */
+#define EMU_HANA_DOCK_LEDS_3_SIGNAL_B	0x08	/* Signal B Clip LED on */
+#define EMU_HANA_DOCK_LEDS_3_MANUAL_CLIP	0x10	/* Manual Clip detection */
+#define EMU_HANA_DOCK_LEDS_3_MANUAL_SIGNAL	0x20	/* Manual Signal detection */
+
+#define EMU_HANA_ADC_PADS	0x10	/* 0000xxx  3 bit  Audio Dock ADC 14dB pads */
+#define EMU_HANA_DOCK_ADC_PAD1	0x01	/* 14dB Attenuation on Audio Dock ADC 1 */
+#define EMU_HANA_DOCK_ADC_PAD2	0x02	/* 14dB Attenuation on Audio Dock ADC 2 */
+#define EMU_HANA_DOCK_ADC_PAD3	0x04	/* 14dB Attenuation on Audio Dock ADC 3 */
+#define EMU_HANA_0202_ADC_PAD1	0x08	/* 14dB Attenuation on 0202 ADC 1 */
+
+#define EMU_HANA_DOCK_MISC	0x11	/* 0xxxxxx  6 bit  Audio Dock misc bits */
+#define EMU_HANA_DOCK_DAC1_MUTE	0x01	/* DAC 1 Mute */
+#define EMU_HANA_DOCK_DAC2_MUTE	0x02	/* DAC 2 Mute */
+#define EMU_HANA_DOCK_DAC3_MUTE	0x04	/* DAC 3 Mute */
+#define EMU_HANA_DOCK_DAC4_MUTE	0x08	/* DAC 4 Mute */
+#define EMU_HANA_DOCK_PHONES_192_DAC1	0x00	/* DAC 1 Headphones source at 192kHz */
+#define EMU_HANA_DOCK_PHONES_192_DAC2	0x10	/* DAC 2 Headphones source at 192kHz */
+#define EMU_HANA_DOCK_PHONES_192_DAC3	0x20	/* DAC 3 Headphones source at 192kHz */
+#define EMU_HANA_DOCK_PHONES_192_DAC4	0x30	/* DAC 4 Headphones source at 192kHz */
+
+#define EMU_HANA_MIDI_OUT	0x12	/* 00xxxxx  5 bit  Source for each MIDI out port */
+#define EMU_HANA_MIDI_OUT_0202	0x01 /* 0202 MIDI from Alice 2. 0 = A, 1 = B */
+#define EMU_HANA_MIDI_OUT_DOCK1	0x02 /* Audio Dock MIDI1 front, from Alice 2. 0 = A, 1 = B */
+#define EMU_HANA_MIDI_OUT_DOCK2	0x04 /* Audio Dock MIDI2 rear, from Alice 2. 0 = A, 1 = B */
+#define EMU_HANA_MIDI_OUT_SYNC2	0x08 /* Sync card. Not the actual MIDI out jack. 0 = A, 1 = B */
+#define EMU_HANA_MIDI_OUT_LOOP	0x10 /* 0 = bits (3:0) normal. 1 = MIDI loopback enabled. */
+
+#define EMU_HANA_DAC_PADS	0x13	/* 00xxxxx  5 bit  DAC 14dB attenuation pads */
+#define EMU_HANA_DOCK_DAC_PAD1	0x01	/* 14dB Attenuation on AudioDock DAC 1. Left and Right */
+#define EMU_HANA_DOCK_DAC_PAD2	0x02	/* 14dB Attenuation on AudioDock DAC 2. Left and Right */
+#define EMU_HANA_DOCK_DAC_PAD3	0x04	/* 14dB Attenuation on AudioDock DAC 3. Left and Right */
+#define EMU_HANA_DOCK_DAC_PAD4	0x08	/* 14dB Attenuation on AudioDock DAC 4. Left and Right */
+#define EMU_HANA_0202_DAC_PAD1	0x10	/* 14dB Attenuation on 0202 DAC 1. Left and Right */
+
+/* 0x14 - 0x1f Unused R/W registers */
+#define EMU_HANA_IRQ_STATUS	0x20	/* 000xxxx  4 bits IRQ Status  */
+#if 0  /* Already defined for reg 0x09 IRQ_ENABLE */
+#define EMU_HANA_IRQ_WCLK_CHANGED	0x01
+#define EMU_HANA_IRQ_ADAT		0x02
+#define EMU_HANA_IRQ_DOCK		0x04
+#define EMU_HANA_IRQ_DOCK_LOST		0x08
+#endif
+
+#define EMU_HANA_OPTION_CARDS	0x21	/* 000xxxx  4 bits Presence of option cards */
+#define EMU_HANA_OPTION_HAMOA	0x01	/* HAMOA card present */
+#define EMU_HANA_OPTION_SYNC	0x02	/* Sync card present */
+#define EMU_HANA_OPTION_DOCK_ONLINE	0x04	/* Audio Dock online and FPGA configured */
+#define EMU_HANA_OPTION_DOCK_OFFLINE	0x08	/* Audio Dock online and FPGA not configured */
+
+#define EMU_HANA_ID		0x22	/* 1010101  7 bits ID byte & 0x7f = 0x55 */
+
+#define EMU_HANA_MAJOR_REV	0x23	/* 0000xxx  3 bit  Hana FPGA Major rev */
+#define EMU_HANA_MINOR_REV	0x24	/* 0000xxx  3 bit  Hana FPGA Minor rev */
+
+#define EMU_DOCK_MAJOR_REV	0x25	/* 0000xxx  3 bit  Audio Dock FPGA Major rev */
+#define EMU_DOCK_MINOR_REV	0x26	/* 0000xxx  3 bit  Audio Dock FPGA Minor rev */
+
+#define EMU_DOCK_BOARD_ID	0x27	/* 00000xx  2 bits Audio Dock ID pins */
+#define EMU_DOCK_BOARD_ID0	0x00	/* ID bit 0 */
+#define EMU_DOCK_BOARD_ID1	0x03	/* ID bit 1 */
+
+#define EMU_HANA_WC_SPDIF_HI	0x28	/* 0xxxxxx  6 bit  SPDIF IN Word clock, upper 6 bits */
+#define EMU_HANA_WC_SPDIF_LO	0x29	/* 0xxxxxx  6 bit  SPDIF IN Word clock, lower 6 bits */
+
+#define EMU_HANA_WC_ADAT_HI	0x2a	/* 0xxxxxx  6 bit  ADAT IN Word clock, upper 6 bits */
+#define EMU_HANA_WC_ADAT_LO	0x2b	/* 0xxxxxx  6 bit  ADAT IN Word clock, lower 6 bits */
+
+#define EMU_HANA_WC_BNC_LO	0x2c	/* 0xxxxxx  6 bit  BNC IN Word clock, lower 6 bits */
+#define EMU_HANA_WC_BNC_HI	0x2d	/* 0xxxxxx  6 bit  BNC IN Word clock, upper 6 bits */
+
+#define EMU_HANA2_WC_SPDIF_HI	0x2e	/* 0xxxxxx  6 bit  HANA2 SPDIF IN Word clock, upper 6 bits */
+#define EMU_HANA2_WC_SPDIF_LO	0x2f	/* 0xxxxxx  6 bit  HANA2 SPDIF IN Word clock, lower 6 bits */
+/* 0x30 - 0x3f Unused Read only registers */
+
+/************************************************************************************************/
+/* EMU1010m HANA Destinations									*/
+/************************************************************************************************/
+#define EMU_DST_ALICE2_EMU32_0	0x000f	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_1	0x0000	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_2	0x0001	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_3	0x0002	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_4	0x0003	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_5	0x0004	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_6	0x0005	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_7	0x0006	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_8	0x0007	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_9	0x0008	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_A	0x0009	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_B	0x000a	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_C	0x000b	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_D	0x000c	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_E	0x000d	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_ALICE2_EMU32_F	0x000e	/* 16 EMU32 channels to Alice2 +0 to +0xf */
+#define EMU_DST_DOCK_DAC1_LEFT1	0x0100	/* Audio Dock DAC1 Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC1_LEFT2	0x0101	/* Audio Dock DAC1 Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC1_LEFT3	0x0102	/* Audio Dock DAC1 Left, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC1_LEFT4	0x0103	/* Audio Dock DAC1 Left, 4th or 192kHz */
+#define EMU_DST_DOCK_DAC1_RIGHT1	0x0104	/* Audio Dock DAC1 Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC1_RIGHT2	0x0105	/* Audio Dock DAC1 Right, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC1_RIGHT3	0x0106	/* Audio Dock DAC1 Right, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC1_RIGHT4	0x0107	/* Audio Dock DAC1 Right, 4th or 192kHz */
+#define EMU_DST_DOCK_DAC2_LEFT1	0x0108	/* Audio Dock DAC2 Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC2_LEFT2	0x0109	/* Audio Dock DAC2 Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC2_LEFT3	0x010a	/* Audio Dock DAC2 Left, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC2_LEFT4	0x010b	/* Audio Dock DAC2 Left, 4th or 192kHz */
+#define EMU_DST_DOCK_DAC2_RIGHT1	0x010c	/* Audio Dock DAC2 Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC2_RIGHT2	0x010d	/* Audio Dock DAC2 Right, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC2_RIGHT3	0x010e	/* Audio Dock DAC2 Right, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC2_RIGHT4	0x010f	/* Audio Dock DAC2 Right, 4th or 192kHz */
+#define EMU_DST_DOCK_DAC3_LEFT1	0x0110	/* Audio Dock DAC1 Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC3_LEFT2	0x0111	/* Audio Dock DAC1 Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC3_LEFT3	0x0112	/* Audio Dock DAC1 Left, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC3_LEFT4	0x0113	/* Audio Dock DAC1 Left, 4th or 192kHz */
+#define EMU_DST_DOCK_PHONES_LEFT1	0x0112	/* Audio Dock PHONES Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_PHONES_LEFT2	0x0113	/* Audio Dock PHONES Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC3_RIGHT1	0x0114	/* Audio Dock DAC1 Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC3_RIGHT2	0x0115	/* Audio Dock DAC1 Right, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC3_RIGHT3	0x0116	/* Audio Dock DAC1 Right, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC3_RIGHT4	0x0117	/* Audio Dock DAC1 Right, 4th or 192kHz */
+#define EMU_DST_DOCK_PHONES_RIGHT1	0x0116	/* Audio Dock PHONES Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_PHONES_RIGHT2	0x0117	/* Audio Dock PHONES Right, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC4_LEFT1	0x0118	/* Audio Dock DAC2 Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC4_LEFT2	0x0119	/* Audio Dock DAC2 Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC4_LEFT3	0x011a	/* Audio Dock DAC2 Left, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC4_LEFT4	0x011b	/* Audio Dock DAC2 Left, 4th or 192kHz */
+#define EMU_DST_DOCK_SPDIF_LEFT1	0x011a	/* Audio Dock SPDIF Left, 1st or 48kHz only */
+#define EMU_DST_DOCK_SPDIF_LEFT2	0x011b	/* Audio Dock SPDIF Left, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC4_RIGHT1	0x011c	/* Audio Dock DAC2 Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_DAC4_RIGHT2	0x011d	/* Audio Dock DAC2 Right, 2nd or 96kHz */
+#define EMU_DST_DOCK_DAC4_RIGHT3	0x011e	/* Audio Dock DAC2 Right, 3rd or 192kHz */
+#define EMU_DST_DOCK_DAC4_RIGHT4	0x011f	/* Audio Dock DAC2 Right, 4th or 192kHz */
+#define EMU_DST_DOCK_SPDIF_RIGHT1	0x011e	/* Audio Dock SPDIF Right, 1st or 48kHz only */
+#define EMU_DST_DOCK_SPDIF_RIGHT2	0x011f	/* Audio Dock SPDIF Right, 2nd or 96kHz */
+#define EMU_DST_HANA_SPDIF_LEFT1	0x0200	/* Hana SPDIF Left, 1st or 48kHz only */
+#define EMU_DST_HANA_SPDIF_LEFT2	0x0202	/* Hana SPDIF Left, 2nd or 96kHz */
+#define EMU_DST_HANA_SPDIF_RIGHT1	0x0201	/* Hana SPDIF Right, 1st or 48kHz only */
+#define EMU_DST_HANA_SPDIF_RIGHT2	0x0203	/* Hana SPDIF Right, 2nd or 96kHz */
+#define EMU_DST_HAMOA_DAC_LEFT1	0x0300	/* Hamoa DAC Left, 1st or 48kHz only */
+#define EMU_DST_HAMOA_DAC_LEFT2	0x0302	/* Hamoa DAC Left, 2nd or 96kHz */
+#define EMU_DST_HAMOA_DAC_LEFT3	0x0304	/* Hamoa DAC Left, 3rd or 192kHz */
+#define EMU_DST_HAMOA_DAC_LEFT4	0x0306	/* Hamoa DAC Left, 4th or 192kHz */
+#define EMU_DST_HAMOA_DAC_RIGHT1	0x0301	/* Hamoa DAC Right, 1st or 48kHz only */
+#define EMU_DST_HAMOA_DAC_RIGHT2	0x0303	/* Hamoa DAC Right, 2nd or 96kHz */
+#define EMU_DST_HAMOA_DAC_RIGHT3	0x0305	/* Hamoa DAC Right, 3rd or 192kHz */
+#define EMU_DST_HAMOA_DAC_RIGHT4	0x0307	/* Hamoa DAC Right, 4th or 192kHz */
+#define EMU_DST_HANA_ADAT	0x0400	/* Hana ADAT 8 channel out +0 to +7 */
+#define EMU_DST_ALICE_I2S0_LEFT		0x0500	/* Alice2 I2S0 Left */
+#define EMU_DST_ALICE_I2S0_RIGHT	0x0501	/* Alice2 I2S0 Right */
+#define EMU_DST_ALICE_I2S1_LEFT		0x0600	/* Alice2 I2S1 Left */
+#define EMU_DST_ALICE_I2S1_RIGHT	0x0601	/* Alice2 I2S1 Right */
+#define EMU_DST_ALICE_I2S2_LEFT		0x0700	/* Alice2 I2S2 Left */
+#define EMU_DST_ALICE_I2S2_RIGHT	0x0701	/* Alice2 I2S2 Right */
+
+/************************************************************************************************/
+/* EMU1010m HANA Sources									*/
+/************************************************************************************************/
+#define EMU_SRC_SILENCE		0x0000	/* Silence */
+#define EMU_SRC_DOCK_MIC_A1	0x0100	/* Audio Dock Mic A, 1st or 48kHz only */
+#define EMU_SRC_DOCK_MIC_A2	0x0101	/* Audio Dock Mic A, 2nd or 96kHz */
+#define EMU_SRC_DOCK_MIC_A3	0x0102	/* Audio Dock Mic A, 3rd or 192kHz */
+#define EMU_SRC_DOCK_MIC_A4	0x0103	/* Audio Dock Mic A, 4th or 192kHz */
+#define EMU_SRC_DOCK_MIC_B1	0x0104	/* Audio Dock Mic B, 1st or 48kHz only */
+#define EMU_SRC_DOCK_MIC_B2	0x0105	/* Audio Dock Mic B, 2nd or 96kHz */
+#define EMU_SRC_DOCK_MIC_B3	0x0106	/* Audio Dock Mic B, 3rd or 192kHz */
+#define EMU_SRC_DOCK_MIC_B4	0x0107	/* Audio Dock Mic B, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC1_LEFT1	0x0108	/* Audio Dock ADC1 Left, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC1_LEFT2	0x0109	/* Audio Dock ADC1 Left, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC1_LEFT3	0x010a	/* Audio Dock ADC1 Left, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC1_LEFT4	0x010b	/* Audio Dock ADC1 Left, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC1_RIGHT1	0x010c	/* Audio Dock ADC1 Right, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC1_RIGHT2	0x010d	/* Audio Dock ADC1 Right, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC1_RIGHT3	0x010e	/* Audio Dock ADC1 Right, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC1_RIGHT4	0x010f	/* Audio Dock ADC1 Right, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC2_LEFT1	0x0110	/* Audio Dock ADC2 Left, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC2_LEFT2	0x0111	/* Audio Dock ADC2 Left, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC2_LEFT3	0x0112	/* Audio Dock ADC2 Left, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC2_LEFT4	0x0113	/* Audio Dock ADC2 Left, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC2_RIGHT1	0x0114	/* Audio Dock ADC2 Right, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC2_RIGHT2	0x0115	/* Audio Dock ADC2 Right, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC2_RIGHT3	0x0116	/* Audio Dock ADC2 Right, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC2_RIGHT4	0x0117	/* Audio Dock ADC2 Right, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC3_LEFT1	0x0118	/* Audio Dock ADC3 Left, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC3_LEFT2	0x0119	/* Audio Dock ADC3 Left, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC3_LEFT3	0x011a	/* Audio Dock ADC3 Left, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC3_LEFT4	0x011b	/* Audio Dock ADC3 Left, 4th or 192kHz */
+#define EMU_SRC_DOCK_ADC3_RIGHT1	0x011c	/* Audio Dock ADC3 Right, 1st or 48kHz only */
+#define EMU_SRC_DOCK_ADC3_RIGHT2	0x011d	/* Audio Dock ADC3 Right, 2nd or 96kHz */
+#define EMU_SRC_DOCK_ADC3_RIGHT3	0x011e	/* Audio Dock ADC3 Right, 3rd or 192kHz */
+#define EMU_SRC_DOCK_ADC3_RIGHT4	0x011f	/* Audio Dock ADC3 Right, 4th or 192kHz */
+#define EMU_SRC_HAMOA_ADC_LEFT1	0x0200	/* Hamoa ADC Left, 1st or 48kHz only */
+#define EMU_SRC_HAMOA_ADC_LEFT2	0x0202	/* Hamoa ADC Left, 2nd or 96kHz */
+#define EMU_SRC_HAMOA_ADC_LEFT3	0x0204	/* Hamoa ADC Left, 3rd or 192kHz */
+#define EMU_SRC_HAMOA_ADC_LEFT4	0x0206	/* Hamoa ADC Left, 4th or 192kHz */
+#define EMU_SRC_HAMOA_ADC_RIGHT1	0x0201	/* Hamoa ADC Right, 1st or 48kHz only */
+#define EMU_SRC_HAMOA_ADC_RIGHT2	0x0203	/* Hamoa ADC Right, 2nd or 96kHz */
+#define EMU_SRC_HAMOA_ADC_RIGHT3	0x0205	/* Hamoa ADC Right, 3rd or 192kHz */
+#define EMU_SRC_HAMOA_ADC_RIGHT4	0x0207	/* Hamoa ADC Right, 4th or 192kHz */
+#define EMU_SRC_ALICE_EMU32A		0x0300	/* Alice2 EMU32a 16 outputs. +0 to +0xf */
+#define EMU_SRC_ALICE_EMU32B		0x0310	/* Alice2 EMU32b 16 outputs. +0 to +0xf */
+#define EMU_SRC_HANA_ADAT	0x0400	/* Hana ADAT 8 channel in +0 to +7 */
+#define EMU_SRC_HANA_SPDIF_LEFT1	0x0500	/* Hana SPDIF Left, 1st or 48kHz only */
+#define EMU_SRC_HANA_SPDIF_LEFT2	0x0502	/* Hana SPDIF Left, 2nd or 96kHz */
+#define EMU_SRC_HANA_SPDIF_RIGHT1	0x0501	/* Hana SPDIF Right, 1st or 48kHz only */
+#define EMU_SRC_HANA_SPDIF_RIGHT2	0x0503	/* Hana SPDIF Right, 2nd or 96kHz */
+/* 0x600 and 0x700 no used */
 
 /* ------------------- STRUCTURES -------------------- */
 
@@ -1063,7 +1425,7 @@
 	unsigned char spdif_bug;    /* Has Spdif phasing bug */
 	unsigned char ac97_chip;    /* Has an AC97 chip: 1 = mandatory, 2 = optional */
 	unsigned char ecard;        /* APS EEPROM */
-	unsigned char emu1212m;     /* EMU 1212m card */
+	unsigned char emu1010;     /* EMU 1010m card */
 	unsigned char spi_dac;      /* SPI interface for DAC */
 	unsigned char i2c_adc;      /* I2C interface for ADC */
 	unsigned char adc_1361t;    /* Use Philips 1361T ADC */
@@ -1072,6 +1434,14 @@
 	const char *id;		/* for backward compatibility - can be NULL if not needed */
 };
 
+struct snd_emu1010 {
+	unsigned int output_source[64];
+	unsigned int input_source[64];
+	unsigned int adc_pads; /* bit mask */
+	unsigned int dac_pads; /* bit mask */
+	unsigned int internal_clock; /* 44100 or 48000 */
+};
+
 struct snd_emu10k1 {
 	int irq;
 
@@ -1079,6 +1449,7 @@
 	unsigned int tos_link: 1,		/* tos link detected */
 		rear_ac97: 1,			/* rear channels are on AC'97 */
 		enable_ir: 1;
+	unsigned int support_tlv :1;
 	/* Contains profile of card capabilities */
 	const struct snd_emu_chip_details *card_capabilities;
 	unsigned int audigy;			/* is Audigy? */
@@ -1104,6 +1475,8 @@
 	spinlock_t memblk_lock;
 
 	unsigned int spdif_bits[3];		/* s/pdif out setup */
+	unsigned int i2c_capture_source;
+	u8 i2c_capture_volume[4][2];
 
 	struct snd_emu10k1_fx8010 fx8010;		/* FX8010 info */
 	int gpr_base;
@@ -1132,6 +1505,7 @@
 	int p16v_device_offset;
 	u32 p16v_capture_source;
 	u32 p16v_capture_channel;
+        struct snd_emu1010 emu1010;
 	struct snd_emu10k1_pcm_mixer pcm_mixer[32];
 	struct snd_emu10k1_pcm_mixer efx_pcm_mixer[NUM_EFX_PLAYBACK];
 	struct snd_kcontrol *ctl_send_routing;
@@ -1208,6 +1582,10 @@
 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn);
 void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
 int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
+int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
+int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value);
+int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value);
+int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src);
 unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc);
 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb);
 void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb);
@@ -1524,11 +1902,20 @@
 	unsigned int value[32];		/* initial values */
 	unsigned int min;		/* minimum range */
 	unsigned int max;		/* maximum range */
-	union {
-		snd_kcontrol_tlv_rw_t *c;
-		unsigned int *p;
-	} tlv;
 	unsigned int translation;	/* translation type (EMU10K1_GPR_TRANSLATION*) */
+	const unsigned int *tlv;
+};
+
+/* old ABI without TLV support */
+struct snd_emu10k1_fx8010_control_old_gpr {
+	struct snd_ctl_elem_id id;
+	unsigned int vcount;
+	unsigned int count;
+	unsigned short gpr[32];
+	unsigned int value[32];
+	unsigned int min;
+	unsigned int max;
+	unsigned int translation;
 };
 
 struct snd_emu10k1_fx8010_code {
@@ -1579,6 +1966,8 @@
 	unsigned int res2;		/* reserved */
 };
 
+#define SNDRV_EMU10K1_VERSION		SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
 #define SNDRV_EMU10K1_IOCTL_INFO	_IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
 #define SNDRV_EMU10K1_IOCTL_CODE_POKE	_IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
 #define SNDRV_EMU10K1_IOCTL_CODE_PEEK	_IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
@@ -1587,6 +1976,7 @@
 #define SNDRV_EMU10K1_IOCTL_TRAM_PEEK	_IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
 #define SNDRV_EMU10K1_IOCTL_PCM_POKE	_IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
 #define SNDRV_EMU10K1_IOCTL_PCM_PEEK	_IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PVERSION	_IOR ('H', 0x40, int)
 #define SNDRV_EMU10K1_IOCTL_STOP	_IO  ('H', 0x80)
 #define SNDRV_EMU10K1_IOCTL_CONTINUE	_IO  ('H', 0x81)
 #define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 2f645df..deff5a9 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -56,6 +56,8 @@
 	size_t fifo_size;		/* fifo size in bytes */
 };
 
+struct snd_pcm_substream;
+
 struct snd_pcm_ops {
 	int (*open)(struct snd_pcm_substream *substream);
 	int (*close)(struct snd_pcm_substream *substream);
@@ -384,6 +386,7 @@
 	struct snd_info_entry *proc_sw_params_entry;
 	struct snd_info_entry *proc_status_entry;
 	struct snd_info_entry *proc_prealloc_entry;
+	struct snd_info_entry *proc_prealloc_max_entry;
 #endif
 	/* misc flags */
 	unsigned int hw_opened: 1;
@@ -427,6 +430,7 @@
 	wait_queue_head_t open_wait;
 	void *private_data;
 	void (*private_free) (struct snd_pcm *pcm);
+	struct device *dev; /* actual hw device this belongs to */
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	struct snd_pcm_oss oss;
 #endif
@@ -443,7 +447,7 @@
  *  Registering
  */
 
-extern struct file_operations snd_pcm_f_ops[2];
+extern const struct file_operations snd_pcm_f_ops[2];
 
 int snd_pcm_new(struct snd_card *card, char *id, int device,
 		int playback_count, int capture_count,
diff --git a/include/sound/pt2258.h b/include/sound/pt2258.h
new file mode 100644
index 0000000..160f812
--- /dev/null
+++ b/include/sound/pt2258.h
@@ -0,0 +1,37 @@
+/*
+ *   ALSA Driver for the PT2258 volume controller.
+ *
+ *	Copyright (c) 2006  Jochen Voss <voss@seehuhn.de>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */      
+
+#ifndef __SOUND_PT2258_H
+#define __SOUND_PT2258_H
+
+struct snd_pt2258 {
+	struct snd_card *card;
+	struct snd_i2c_bus *i2c_bus;
+	struct snd_i2c_device *i2c_dev;
+
+	unsigned char volume[6];
+	int mute;
+};
+
+extern int snd_pt2258_reset(struct snd_pt2258 *pt);
+extern int snd_pt2258_build_controls(struct snd_pt2258 *pt);
+
+#endif /* __SOUND_PT2258_H */
diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h
index caf6fe2..736eac7 100644
--- a/include/sound/sb16_csp.h
+++ b/include/sound/sb16_csp.h
@@ -114,9 +114,21 @@
 #ifdef __KERNEL__
 #include "sb.h"
 #include "hwdep.h"
+#include <linux/firmware.h>
 
 struct snd_sb_csp;
 
+/* indices for the known CSP programs */
+enum {
+	CSP_PROGRAM_MULAW,
+	CSP_PROGRAM_ALAW,
+	CSP_PROGRAM_ADPCM_INIT,
+	CSP_PROGRAM_ADPCM_PLAYBACK,
+	CSP_PROGRAM_ADPCM_CAPTURE,
+
+	CSP_PROGRAM_COUNT
+};
+
 /*
  * CSP operators
  */
@@ -159,6 +171,8 @@
 	struct snd_kcontrol *qsound_space;
 
 	struct mutex access_mutex;	/* locking */
+
+	const struct firmware *csp_programs[CSP_PROGRAM_COUNT];
 };
 
 int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep);
diff --git a/include/sound/snd_wavefront.h b/include/sound/snd_wavefront.h
index 0b9e5de..9688d4b 100644
--- a/include/sound/snd_wavefront.h
+++ b/include/sound/snd_wavefront.h
@@ -85,6 +85,7 @@
 	char hw_version[2];                /* major = [0], minor = [1] */
 	char israw;                        /* needs Motorola microcode */
 	char has_fx;                       /* has FX processor (Tropez+) */
+	char fx_initialized;               /* FX's register pages initialized */
 	char prog_status[WF_MAX_PROGRAM];  /* WF_SLOT_* */
 	char patch_status[WF_MAX_PATCH];   /* WF_SLOT_* */
 	char sample_status[WF_MAX_SAMPLE]; /* WF_ST_* | WF_SLOT_* */
@@ -94,6 +95,7 @@
 	spinlock_t irq_lock;
 	wait_queue_head_t interrupt_sleeper; 
 	snd_wavefront_midi_t midi;         /* ICS2115 MIDI interface */
+	struct snd_card *card;
 };
 
 struct _snd_wavefront_card {
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
new file mode 100644
index 0000000..2b1ae8e
--- /dev/null
+++ b/include/sound/soc-dapm.h
@@ -0,0 +1,286 @@
+/*
+ * linux/sound/soc-dapm.h -- ALSA SoC Dynamic Audio Power Management
+ *
+ * Author:		Liam Girdwood
+ * Created:		Aug 11th 2005
+ * Copyright:	Wolfson Microelectronics. PLC.
+ *
+ * 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 __LINUX_SND_SOC_DAPM_H
+#define __LINUX_SND_SOC_DAPM_H
+
+#include <linux/device.h>
+#include <linux/types.h>
+#include <sound/control.h>
+#include <sound/soc.h>
+
+/* widget has no PM register bit */
+#define SND_SOC_NOPM	-1
+
+/*
+ * SoC dynamic audio power managment
+ *
+ * We can have upto 4 power domains
+ * 	1. Codec domain - VREF, VMID
+ *     Usually controlled at codec probe/remove, although can be set
+ *     at stream time if power is not needed for sidetone, etc.
+ *  2. Platform/Machine domain - physically connected inputs and outputs
+ *     Is platform/machine and user action specific, is set in the machine
+ *     driver and by userspace e.g when HP are inserted
+ *  3. Path domain - Internal codec path mixers
+ *     Are automatically set when mixer and mux settings are
+ *     changed by the user.
+ *  4. Stream domain - DAC's and ADC's.
+ *     Enabled when stream playback/capture is started.
+ */
+
+/* codec domain */
+#define SND_SOC_DAPM_VMID(wname) \
+{	.id = snd_soc_dapm_vmid, .name = wname, .kcontrols = NULL, \
+	.num_kcontrols = 0}
+
+/* platform domain */
+#define SND_SOC_DAPM_INPUT(wname) \
+{	.id = snd_soc_dapm_input, .name = wname, .kcontrols = NULL, \
+	.num_kcontrols = 0}
+#define SND_SOC_DAPM_OUTPUT(wname) \
+{	.id = snd_soc_dapm_output, .name = wname, .kcontrols = NULL, \
+	.num_kcontrols = 0}
+#define SND_SOC_DAPM_MIC(wname, wevent) \
+{	.id = snd_soc_dapm_mic, .name = wname, .kcontrols = NULL, \
+	.num_kcontrols = 0, .event = wevent, \
+	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
+#define SND_SOC_DAPM_HP(wname, wevent) \
+{	.id = snd_soc_dapm_hp, .name = wname, .kcontrols = NULL, \
+	.num_kcontrols = 0, .event = wevent, \
+	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
+#define SND_SOC_DAPM_SPK(wname, wevent) \
+{	.id = snd_soc_dapm_spk, .name = wname, .kcontrols = NULL, \
+	.num_kcontrols = 0, .event = wevent, \
+	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
+#define SND_SOC_DAPM_LINE(wname, wevent) \
+{	.id = snd_soc_dapm_line, .name = wname, .kcontrols = NULL, \
+	.num_kcontrols = 0, .event = wevent, \
+	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
+
+/* path domain */
+#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
+	 wcontrols, wncontrols) \
+{	.id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
+#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
+	 wcontrols, wncontrols)\
+{	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
+#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
+{	.id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = NULL, .num_kcontrols = 0}
+#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \
+{	.id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1}
+#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
+{	.id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1}
+
+/* path domain with event - event handler must return 0 for success */
+#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
+	wncontrols, wevent, wflags) \
+{	.id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
+	.event = wevent, .event_flags = wflags}
+#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
+	wncontrols, wevent, wflags) \
+{	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
+	.event = wevent, .event_flags = wflags}
+#define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \
+{	.id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = NULL, .num_kcontrols = 0, \
+	.event = wevent, .event_flags = wflags}
+#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
+	wevent, wflags) \
+{	.id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1 \
+	.event = wevent, .event_flags = wflags}
+#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
+	wevent, wflags) \
+{	.id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1, \
+	.event = wevent, .event_flags = wflags}
+
+/* events that are pre and post DAPM */
+#define SND_SOC_DAPM_PRE(wname, wevent) \
+{	.id = snd_soc_dapm_pre, .name = wname, .kcontrols = NULL, \
+	.num_kcontrols = 0, .event = wevent, \
+	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD}
+#define SND_SOC_DAPM_POST(wname, wevent) \
+{	.id = snd_soc_dapm_post, .name = wname, .kcontrols = NULL, \
+	.num_kcontrols = 0, .event = wevent, \
+	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
+
+/* stream domain */
+#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
+{	.id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
+	.shift = wshift, .invert = winvert}
+#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
+{	.id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
+	.shift = wshift, .invert = winvert}
+
+/* dapm kcontrol types */
+#define SOC_DAPM_SINGLE(xname, reg, shift, mask, invert) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_volsw, \
+	.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
+	.private_value =  SOC_SINGLE_VALUE(reg, shift, mask, invert) }
+#define SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, mask, invert, \
+	power) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+	.info = snd_soc_info_volsw, \
+ 	.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
+ 	.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\
+ 		 ((mask) << 16) | ((invert) << 24) }
+#define SOC_DAPM_ENUM(xname, xenum) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_enum_double, \
+ 	.get = snd_soc_dapm_get_enum_double, \
+ 	.put = snd_soc_dapm_put_enum_double, \
+  	.private_value = (unsigned long)&xenum }
+
+/* dapm stream operations */
+#define SND_SOC_DAPM_STREAM_NOP			0x0
+#define SND_SOC_DAPM_STREAM_START		0x1
+#define SND_SOC_DAPM_STREAM_STOP		0x2
+#define SND_SOC_DAPM_STREAM_SUSPEND		0x4
+#define SND_SOC_DAPM_STREAM_RESUME		0x8
+#define SND_SOC_DAPM_STREAM_PAUSE_PUSH	0x10
+#define SND_SOC_DAPM_STREAM_PAUSE_RELEASE	0x20
+
+/* dapm event types */
+#define SND_SOC_DAPM_PRE_PMU	0x1 	/* before widget power up */
+#define SND_SOC_DAPM_POST_PMU	0x2		/* after widget power up */
+#define SND_SOC_DAPM_PRE_PMD	0x4 	/* before widget power down */
+#define SND_SOC_DAPM_POST_PMD	0x8		/* after widget power down */
+#define SND_SOC_DAPM_PRE_REG	0x10	/* before audio path setup */
+#define SND_SOC_DAPM_POST_REG	0x20	/* after audio path setup */
+
+/* convenience event type detection */
+#define SND_SOC_DAPM_EVENT_ON(e)	\
+	(e & (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU))
+#define SND_SOC_DAPM_EVENT_OFF(e)	\
+	(e & (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD))
+
+struct snd_soc_dapm_widget;
+enum snd_soc_dapm_type;
+struct snd_soc_dapm_path;
+struct snd_soc_dapm_pin;
+
+/* dapm controls */
+int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
+	const struct snd_soc_dapm_widget *widget);
+
+/* dapm path setup */
+int snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
+	const char *sink_name, const char *control_name, const char *src_name);
+int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
+void snd_soc_dapm_free(struct snd_soc_device *socdev);
+
+/* dapm events */
+int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream,
+	int event);
+
+/* dapm sys fs - used by the core */
+int snd_soc_dapm_sys_add(struct device *dev);
+
+/* dapm audio endpoint control */
+int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
+	char *pin, int status);
+int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec);
+
+/* dapm widget types */
+enum snd_soc_dapm_type {
+	snd_soc_dapm_input = 0,		/* input pin */
+	snd_soc_dapm_output,		/* output pin */
+	snd_soc_dapm_mux,			/* selects 1 analog signal from many inputs */
+	snd_soc_dapm_mixer,			/* mixes several analog signals together */
+	snd_soc_dapm_pga,			/* programmable gain/attenuation (volume) */
+	snd_soc_dapm_adc,			/* analog to digital converter */
+	snd_soc_dapm_dac,			/* digital to analog converter */
+	snd_soc_dapm_micbias,		/* microphone bias (power) */
+	snd_soc_dapm_mic,			/* microphone */
+	snd_soc_dapm_hp,			/* headphones */
+	snd_soc_dapm_spk,			/* speaker */
+	snd_soc_dapm_line,			/* line input/output */
+	snd_soc_dapm_switch,		/* analog switch */
+	snd_soc_dapm_vmid,			/* codec bias/vmid - to minimise pops */
+	snd_soc_dapm_pre,			/* machine specific pre widget - exec first */
+	snd_soc_dapm_post,			/* machine specific post widget - exec last */
+};
+
+/* dapm audio path between two widgets */
+struct snd_soc_dapm_path {
+	char *name;
+	char *long_name;
+
+	/* source (input) and sink (output) widgets */
+	struct snd_soc_dapm_widget *source;
+	struct snd_soc_dapm_widget *sink;
+	struct snd_kcontrol *kcontrol;
+
+	/* status */
+	u32 connect:1;	/* source and sink widgets are connected */
+	u32 walked:1;	/* path has been walked */
+
+	struct list_head list_source;
+	struct list_head list_sink;
+	struct list_head list;
+};
+
+/* dapm widget */
+struct snd_soc_dapm_widget {
+	enum snd_soc_dapm_type id;
+	char *name;		/* widget name */
+	char *sname;	/* stream name */
+	struct snd_soc_codec *codec;
+	struct list_head list;
+
+	/* dapm control */
+	short reg;						/* negative reg = no direct dapm */
+	unsigned char shift;			/* bits to shift */
+	unsigned int saved_value;		/* widget saved value */
+	unsigned int value;				/* widget current value */
+	unsigned char power:1;			/* block power status */
+	unsigned char invert:1;			/* invert the power bit */
+	unsigned char active:1;			/* active stream on DAC, ADC's */
+	unsigned char connected:1;		/* connected codec pin */
+	unsigned char new:1;			/* cnew complete */
+	unsigned char ext:1;			/* has external widgets */
+	unsigned char muted:1;			/* muted for pop reduction */
+	unsigned char suspend:1;		/* was active before suspend */
+	unsigned char pmdown:1;			/* waiting for timeout */
+
+	/* external events */
+	unsigned short event_flags;		/* flags to specify event types */
+	int (*event)(struct snd_soc_dapm_widget*, int);
+
+	/* kcontrols that relate to this widget */
+	int num_kcontrols;
+	const struct snd_kcontrol_new *kcontrols;
+
+	/* widget input and outputs */
+	struct list_head sources;
+	struct list_head sinks;
+};
+
+#endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
new file mode 100644
index 0000000..b1dc364
--- /dev/null
+++ b/include/sound/soc.h
@@ -0,0 +1,461 @@
+/*
+ * linux/sound/soc.h -- ALSA SoC Layer
+ *
+ * Author:		Liam Girdwood
+ * Created:		Aug 11th 2005
+ * Copyright:	Wolfson Microelectronics. PLC.
+ *
+ * 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 __LINUX_SND_SOC_H
+#define __LINUX_SND_SOC_H
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/control.h>
+#include <sound/ac97_codec.h>
+
+#define SND_SOC_VERSION "0.13.0"
+
+/*
+ * Convenience kcontrol builders
+ */
+#define SOC_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) |\
+	((shift) << 12) | ((mask) << 16) | ((invert) << 24))
+#define SOC_SINGLE_VALUE_EXT(reg,mask,invert) ((reg) | ((mask) << 16) |\
+	((invert) << 31))
+#define SOC_SINGLE(xname, reg, shift, mask, invert) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
+	.put = snd_soc_put_volsw, \
+	.private_value =  SOC_SINGLE_VALUE(reg, shift, mask, invert) }
+#define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
+	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
+	.put = snd_soc_put_volsw, \
+	.private_value = (reg) | ((shift_left) << 8) | \
+		((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
+#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+	.info = snd_soc_info_volsw_2r, \
+	.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
+	.private_value = (reg_left) | ((shift) << 8)  | \
+		((mask) << 12) | ((invert) << 20) | ((reg_right) << 24) }
+#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
+{	.reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
+	.mask = xmask, .texts = xtexts }
+#define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \
+	SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts)
+#define SOC_ENUM_SINGLE_EXT(xmask, xtexts) \
+{	.mask = xmask, .texts = xtexts }
+#define SOC_ENUM(xname, xenum) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
+	.info = snd_soc_info_enum_double, \
+	.get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
+	.private_value = (unsigned long)&xenum }
+#define SOC_SINGLE_EXT(xname, xreg, xshift, xmask, xinvert,\
+	 xhandler_get, xhandler_put) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_volsw, \
+	.get = xhandler_get, .put = xhandler_put, \
+	.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmask, xinvert) }
+#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_bool_ext, \
+	.get = xhandler_get, .put = xhandler_put, \
+	.private_value = xdata }
+#define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_enum_ext, \
+	.get = xhandler_get, .put = xhandler_put, \
+	.private_value = (unsigned long)&xenum }
+
+/*
+ * Digital Audio Interface (DAI) types
+ */
+#define SND_SOC_DAI_AC97	0x1
+#define SND_SOC_DAI_I2S		0x2
+#define SND_SOC_DAI_PCM		0x4
+
+/*
+ * DAI hardware audio formats
+ */
+#define SND_SOC_DAIFMT_I2S		0	/* I2S mode */
+#define SND_SOC_DAIFMT_RIGHT_J	1	/* Right justified mode */
+#define SND_SOC_DAIFMT_LEFT_J	2	/* Left Justified mode */
+#define SND_SOC_DAIFMT_DSP_A	3	/* L data msb after FRM or LRC */
+#define SND_SOC_DAIFMT_DSP_B	4	/* L data msb during FRM or LRC */
+#define SND_SOC_DAIFMT_AC97		5	/* AC97 */
+
+#define SND_SOC_DAIFMT_MSB 	SND_SOC_DAIFMT_LEFT_J
+#define SND_SOC_DAIFMT_LSB	SND_SOC_DAIFMT_RIGHT_J
+
+/*
+ * DAI Gating
+ */
+#define SND_SOC_DAIFMT_CONT			(0 << 4)	/* continuous clock */
+#define SND_SOC_DAIFMT_GATED		(1 << 4)	/* clock is gated when not Tx/Rx */
+
+/*
+ * DAI hardware signal inversions
+ */
+#define SND_SOC_DAIFMT_NB_NF		(0 << 8)	/* normal bit clock + frame */
+#define SND_SOC_DAIFMT_NB_IF		(1 << 8)	/* normal bclk + inv frm */
+#define SND_SOC_DAIFMT_IB_NF		(2 << 8)	/* invert bclk + nor frm */
+#define SND_SOC_DAIFMT_IB_IF		(3 << 8)	/* invert bclk + frm */
+
+/*
+ * DAI hardware clock masters
+ * This is wrt the codec, the inverse is true for the interface
+ * i.e. if the codec is clk and frm master then the interface is
+ * clk and frame slave.
+ */
+#define SND_SOC_DAIFMT_CBM_CFM	(0 << 12) /* codec clk & frm master */
+#define SND_SOC_DAIFMT_CBS_CFM	(1 << 12) /* codec clk slave & frm master */
+#define SND_SOC_DAIFMT_CBM_CFS	(2 << 12) /* codec clk master & frame slave */
+#define SND_SOC_DAIFMT_CBS_CFS	(3 << 12) /* codec clk & frm slave */
+
+#define SND_SOC_DAIFMT_FORMAT_MASK		0x000f
+#define SND_SOC_DAIFMT_CLOCK_MASK		0x00f0
+#define SND_SOC_DAIFMT_INV_MASK			0x0f00
+#define SND_SOC_DAIFMT_MASTER_MASK		0xf000
+
+
+/*
+ * Master Clock Directions
+ */
+#define SND_SOC_CLOCK_IN	0
+#define SND_SOC_CLOCK_OUT	1
+
+/*
+ * AC97 codec ID's bitmask
+ */
+#define SND_SOC_DAI_AC97_ID0	(1 << 0)
+#define SND_SOC_DAI_AC97_ID1	(1 << 1)
+#define SND_SOC_DAI_AC97_ID2	(1 << 2)
+#define SND_SOC_DAI_AC97_ID3	(1 << 3)
+
+struct snd_soc_device;
+struct snd_soc_pcm_stream;
+struct snd_soc_ops;
+struct snd_soc_dai_mode;
+struct snd_soc_pcm_runtime;
+struct snd_soc_codec_dai;
+struct snd_soc_cpu_dai;
+struct snd_soc_codec;
+struct snd_soc_machine_config;
+struct soc_enum;
+struct snd_soc_ac97_ops;
+struct snd_soc_clock_info;
+
+typedef int (*hw_write_t)(void *,const char* ,int);
+typedef int (*hw_read_t)(void *,char* ,int);
+
+extern struct snd_ac97_bus_ops soc_ac97_ops;
+
+/* pcm <-> DAI connect */
+void snd_soc_free_pcms(struct snd_soc_device *socdev);
+int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
+int snd_soc_register_card(struct snd_soc_device *socdev);
+
+/* set runtime hw params */
+int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
+	const struct snd_pcm_hardware *hw);
+
+/* codec IO */
+#define snd_soc_read(codec, reg) codec->read(codec, reg)
+#define snd_soc_write(codec, reg, value) codec->write(codec, reg, value)
+
+/* codec register bit access */
+int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
+				unsigned short mask, unsigned short value);
+int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
+				unsigned short mask, unsigned short value);
+
+int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
+	struct snd_ac97_bus_ops *ops, int num);
+void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
+
+/*
+ *Controls
+ */
+struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
+	void *data, char *long_name);
+int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo);
+int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo);
+int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo);
+int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo);
+int snd_soc_info_bool_ext(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo);
+int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo);
+int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+
+/* SoC PCM stream information */
+struct snd_soc_pcm_stream {
+	char *stream_name;
+	u64 formats;			/* SNDRV_PCM_FMTBIT_* */
+	unsigned int rates;		/* SNDRV_PCM_RATE_* */
+	unsigned int rate_min;		/* min rate */
+	unsigned int rate_max;		/* max rate */
+	unsigned int channels_min;	/* min channels */
+	unsigned int channels_max;	/* max channels */
+	unsigned int active:1;		/* stream is in use */
+};
+
+/* SoC audio ops */
+struct snd_soc_ops {
+	int (*startup)(struct snd_pcm_substream *);
+	void (*shutdown)(struct snd_pcm_substream *);
+	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
+	int (*hw_free)(struct snd_pcm_substream *);
+	int (*prepare)(struct snd_pcm_substream *);
+	int (*trigger)(struct snd_pcm_substream *, int);
+};
+
+/* ASoC codec DAI ops */
+struct snd_soc_codec_ops {
+	/* codec DAI clocking configuration */
+	int (*set_sysclk)(struct snd_soc_codec_dai *codec_dai,
+		int clk_id, unsigned int freq, int dir);
+	int (*set_pll)(struct snd_soc_codec_dai *codec_dai,
+		int pll_id, unsigned int freq_in, unsigned int freq_out);
+	int (*set_clkdiv)(struct snd_soc_codec_dai *codec_dai,
+		int div_id, int div);
+
+	/* CPU DAI format configuration */
+	int (*set_fmt)(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt);
+	int (*set_tdm_slot)(struct snd_soc_codec_dai *codec_dai,
+		unsigned int mask, int slots);
+	int (*set_tristate)(struct snd_soc_codec_dai *, int tristate);
+
+	/* digital mute */
+	int (*digital_mute)(struct snd_soc_codec_dai *, int mute);
+};
+
+/* ASoC cpu DAI ops */
+struct snd_soc_cpu_ops {
+	/* CPU DAI clocking configuration */
+	int (*set_sysclk)(struct snd_soc_cpu_dai *cpu_dai,
+		int clk_id, unsigned int freq, int dir);
+	int (*set_clkdiv)(struct snd_soc_cpu_dai *cpu_dai,
+		int div_id, int div);
+	int (*set_pll)(struct snd_soc_cpu_dai *cpu_dai,
+		int pll_id, unsigned int freq_in, unsigned int freq_out);
+
+	/* CPU DAI format configuration */
+	int (*set_fmt)(struct snd_soc_cpu_dai *cpu_dai,
+		unsigned int fmt);
+	int (*set_tdm_slot)(struct snd_soc_cpu_dai *cpu_dai,
+		unsigned int mask, int slots);
+	int (*set_tristate)(struct snd_soc_cpu_dai *, int tristate);
+};
+
+/* SoC Codec DAI */
+struct snd_soc_codec_dai {
+	char *name;
+	int id;
+
+	/* DAI capabilities */
+	struct snd_soc_pcm_stream playback;
+	struct snd_soc_pcm_stream capture;
+
+	/* DAI runtime info */
+	struct snd_soc_codec *codec;
+	unsigned int active;
+	unsigned char pop_wait:1;
+
+	/* ops */
+	struct snd_soc_ops ops;
+	struct snd_soc_codec_ops dai_ops;
+
+	/* DAI private data */
+	void *private_data;
+};
+
+/* SoC CPU DAI */
+struct snd_soc_cpu_dai {
+
+	/* DAI description */
+	char *name;
+	unsigned int id;
+	unsigned char type;
+
+	/* DAI callbacks */
+	int (*probe)(struct platform_device *pdev);
+	void (*remove)(struct platform_device *pdev);
+	int (*suspend)(struct platform_device *pdev,
+		struct snd_soc_cpu_dai *cpu_dai);
+	int (*resume)(struct platform_device *pdev,
+		struct snd_soc_cpu_dai *cpu_dai);
+
+	/* ops */
+	struct snd_soc_ops ops;
+	struct snd_soc_cpu_ops dai_ops;
+
+	/* DAI capabilities */
+	struct snd_soc_pcm_stream capture;
+	struct snd_soc_pcm_stream playback;
+
+	/* DAI runtime info */
+	struct snd_pcm_runtime *runtime;
+	unsigned char active:1;
+	void *dma_data;
+
+	/* DAI private data */
+	void *private_data;
+};
+
+/* SoC Audio Codec */
+struct snd_soc_codec {
+	char *name;
+	struct module *owner;
+	struct mutex mutex;
+
+	/* callbacks */
+	int (*dapm_event)(struct snd_soc_codec *codec, int event);
+
+	/* runtime */
+	struct snd_card *card;
+	struct snd_ac97 *ac97;  /* for ad-hoc ac97 devices */
+	unsigned int active;
+	unsigned int pcm_devs;
+	void *private_data;
+
+	/* codec IO */
+	void *control_data; /* codec control (i2c/3wire) data */
+	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
+	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
+	hw_write_t hw_write;
+	hw_read_t hw_read;
+	void *reg_cache;
+	short reg_cache_size;
+	short reg_cache_step;
+
+	/* dapm */
+	struct list_head dapm_widgets;
+	struct list_head dapm_paths;
+	unsigned int dapm_state;
+	unsigned int suspend_dapm_state;
+	struct delayed_work delayed_work;
+
+	/* codec DAI's */
+	struct snd_soc_codec_dai *dai;
+	unsigned int num_dai;
+};
+
+/* codec device */
+struct snd_soc_codec_device {
+	int (*probe)(struct platform_device *pdev);
+	int (*remove)(struct platform_device *pdev);
+	int (*suspend)(struct platform_device *pdev, pm_message_t state);
+	int (*resume)(struct platform_device *pdev);
+};
+
+/* SoC platform interface */
+struct snd_soc_platform {
+	char *name;
+
+	int (*probe)(struct platform_device *pdev);
+	int (*remove)(struct platform_device *pdev);
+	int (*suspend)(struct platform_device *pdev,
+		struct snd_soc_cpu_dai *cpu_dai);
+	int (*resume)(struct platform_device *pdev,
+		struct snd_soc_cpu_dai *cpu_dai);
+
+	/* pcm creation and destruction */
+	int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *,
+		struct snd_pcm *);
+	void (*pcm_free)(struct snd_pcm *);
+
+	/* platform stream ops */
+	struct snd_pcm_ops *pcm_ops;
+};
+
+/* SoC machine DAI configuration, glues a codec and cpu DAI together */
+struct snd_soc_dai_link  {
+	char *name;			/* Codec name */
+	char *stream_name;		/* Stream name */
+
+	/* DAI */
+	struct snd_soc_codec_dai *codec_dai;
+	struct snd_soc_cpu_dai *cpu_dai;
+
+	/* machine stream operations */
+	struct snd_soc_ops *ops;
+
+	/* codec/machine specific init - e.g. add machine controls */
+	int (*init)(struct snd_soc_codec *codec);
+};
+
+/* SoC machine */
+struct snd_soc_machine {
+	char *name;
+
+	int (*probe)(struct platform_device *pdev);
+	int (*remove)(struct platform_device *pdev);
+
+	/* the pre and post PM functions are used to do any PM work before and
+	 * after the codec and DAI's do any PM work. */
+	int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
+	int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
+	int (*resume_pre)(struct platform_device *pdev);
+	int (*resume_post)(struct platform_device *pdev);
+
+	/* CPU <--> Codec DAI links  */
+	struct snd_soc_dai_link *dai_link;
+	int num_links;
+};
+
+/* SoC Device - the audio subsystem */
+struct snd_soc_device {
+	struct device *dev;
+	struct snd_soc_machine *machine;
+	struct snd_soc_platform *platform;
+	struct snd_soc_codec *codec;
+	struct snd_soc_codec_device *codec_dev;
+	struct delayed_work delayed_work;
+	void *codec_data;
+};
+
+/* runtime channel data */
+struct snd_soc_pcm_runtime {
+	struct snd_soc_dai_link *dai;
+	struct snd_soc_device *socdev;
+};
+
+/* enumerated kcontrol */
+struct soc_enum {
+	unsigned short reg;
+	unsigned short reg2;
+	unsigned char shift_l;
+	unsigned char shift_r;
+	unsigned int mask;
+	const char **texts;
+	void *dapm;
+};
+
+#endif
diff --git a/include/sound/typedefs.h b/include/sound/typedefs.h
deleted file mode 100644
index f454b02..0000000
--- a/include/sound/typedefs.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Typedef's for backward compatibility (for out-of-kernel drivers)
- *
- * This file will be removed soon in future
- */
-
-/* core stuff */
-typedef struct snd_card snd_card_t;
-typedef struct snd_device snd_device_t;
-typedef struct snd_device_ops snd_device_ops_t;
-typedef enum snd_card_type snd_card_type_t;
-typedef struct snd_minor snd_minor_t;
-
-/* info */
-typedef struct snd_info_entry snd_info_entry_t;
-typedef struct snd_info_buffer snd_info_buffer_t;
-
-/* control */
-typedef struct snd_ctl_file snd_ctl_file_t;
-typedef struct snd_kcontrol snd_kcontrol_t;
-typedef struct snd_kcontrol_new snd_kcontrol_new_t;
-typedef struct snd_kcontrol_volatile snd_kcontrol_volatile_t;
-typedef struct snd_kctl_event snd_kctl_event_t;
-typedef struct snd_aes_iec958 snd_aes_iec958_t;
-typedef struct snd_ctl_card_info snd_ctl_card_info_t;
-typedef struct snd_ctl_elem_id snd_ctl_elem_id_t;
-typedef struct snd_ctl_elem_list snd_ctl_elem_list_t;
-typedef struct snd_ctl_elem_info snd_ctl_elem_info_t;
-typedef struct snd_ctl_elem_value snd_ctl_elem_value_t;
-typedef struct snd_ctl_event snd_ctl_event_t;
-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
-typedef struct snd_mixer_oss snd_mixer_oss_t;
-#endif
-
-/* timer */
-typedef struct snd_timer snd_timer_t;
-typedef struct snd_timer_instance snd_timer_instance_t;
-typedef struct snd_timer_id snd_timer_id_t;
-typedef struct snd_timer_ginfo snd_timer_ginfo_t;
-typedef struct snd_timer_gparams snd_timer_gparams_t;
-typedef struct snd_timer_gstatus snd_timer_gstatus_t;
-typedef struct snd_timer_select snd_timer_select_t;
-typedef struct snd_timer_info snd_timer_info_t;
-typedef struct snd_timer_params snd_timer_params_t;
-typedef struct snd_timer_status snd_timer_status_t;
-typedef struct snd_timer_read snd_timer_read_t;
-typedef struct snd_timer_tread snd_timer_tread_t;
-
-/* PCM */
-typedef struct snd_pcm snd_pcm_t;
-typedef struct snd_pcm_str snd_pcm_str_t;
-typedef struct snd_pcm_substream snd_pcm_substream_t;
-typedef struct snd_pcm_info snd_pcm_info_t;
-typedef struct snd_pcm_hw_params snd_pcm_hw_params_t;
-typedef struct snd_pcm_sw_params snd_pcm_sw_params_t;
-typedef struct snd_pcm_channel_info snd_pcm_channel_info_t;
-typedef struct snd_pcm_status snd_pcm_status_t;
-typedef struct snd_pcm_mmap_status snd_pcm_mmap_status_t;
-typedef struct snd_pcm_mmap_control snd_pcm_mmap_control_t;
-typedef struct snd_mask snd_mask_t;
-typedef struct snd_sg_buf snd_pcm_sgbuf_t;
-
-typedef struct snd_interval snd_interval_t;
-typedef struct snd_xferi snd_xferi_t;
-typedef struct snd_xfern snd_xfern_t;
-typedef struct snd_xferv snd_xferv_t;
-
-typedef struct snd_pcm_file snd_pcm_file_t;
-typedef struct snd_pcm_runtime snd_pcm_runtime_t;
-typedef struct snd_pcm_hardware snd_pcm_hardware_t;
-typedef struct snd_pcm_ops snd_pcm_ops_t;
-typedef struct snd_pcm_hw_rule snd_pcm_hw_rule_t;
-typedef struct snd_pcm_hw_constraints snd_pcm_hw_constraints_t;
-typedef struct snd_ratnum ratnum_t;
-typedef struct snd_ratden ratden_t;
-typedef struct snd_pcm_hw_constraint_ratnums snd_pcm_hw_constraint_ratnums_t;
-typedef struct snd_pcm_hw_constraint_ratdens snd_pcm_hw_constraint_ratdens_t;
-typedef struct snd_pcm_hw_constraint_list snd_pcm_hw_constraint_list_t;
-typedef struct snd_pcm_group snd_pcm_group_t;
-typedef struct snd_pcm_notify snd_pcm_notify_t;
-
-/* rawmidi */
-typedef struct snd_rawmidi snd_rawmidi_t;
-typedef struct snd_rawmidi_info snd_rawmidi_info_t;
-typedef struct snd_rawmidi_params snd_rawmidi_params_t;
-typedef struct snd_rawmidi_status snd_rawmidi_status_t;
-typedef struct snd_rawmidi_runtime snd_rawmidi_runtime_t;
-typedef struct snd_rawmidi_substream snd_rawmidi_substream_t;
-typedef struct snd_rawmidi_str snd_rawmidi_str_t;
-typedef struct snd_rawmidi_ops snd_rawmidi_ops_t;
-typedef struct snd_rawmidi_global_ops snd_rawmidi_global_ops_t;
-typedef struct snd_rawmidi_file snd_rawmidi_file_t;
-
-/* hwdep */
-typedef struct snd_hwdep snd_hwdep_t;
-typedef struct snd_hwdep_info snd_hwdep_info_t;
-typedef struct snd_hwdep_dsp_status snd_hwdep_dsp_status_t;
-typedef struct snd_hwdep_dsp_image snd_hwdep_dsp_image_t;
-typedef struct snd_hwdep_ops snd_hwdep_ops_t;
-
-/* sequencer */
-typedef struct snd_seq_port_info snd_seq_port_info_t;
-typedef struct snd_seq_port_subscribe snd_seq_port_subscribe_t;
-typedef struct snd_seq_event snd_seq_event_t;
-typedef struct snd_seq_addr snd_seq_addr_t;
-typedef struct snd_seq_ev_volume snd_seq_ev_volume_t;
-typedef struct snd_seq_ev_loop snd_seq_ev_loop_t;
-typedef struct snd_seq_remove_events snd_seq_remove_events_t;
-typedef struct snd_seq_query_subs snd_seq_query_subs_t;
-typedef struct snd_seq_system_info snd_seq_system_info_t;
-typedef struct snd_seq_client_info snd_seq_client_info_t;
-typedef struct snd_seq_queue_info snd_seq_queue_info_t;
-typedef struct snd_seq_queue_status snd_seq_queue_status_t;
-typedef struct snd_seq_queue_tempo snd_seq_queue_tempo_t;
-typedef struct snd_seq_queue_owner snd_seq_queue_owner_t;
-typedef struct snd_seq_queue_timer snd_seq_queue_timer_t;
-typedef struct snd_seq_queue_client snd_seq_queue_client_t;
-typedef struct snd_seq_client_pool snd_seq_client_pool_t;
-typedef struct snd_seq_instr snd_seq_instr_t;
-typedef struct snd_seq_instr_data snd_seq_instr_data_t;
-typedef struct snd_seq_instr_header snd_seq_instr_header_t;
-
-typedef struct snd_seq_user_client user_client_t;
-typedef struct snd_seq_kernel_client kernel_client_t;
-typedef struct snd_seq_client client_t;
-typedef struct snd_seq_queue queue_t;
-
-/* seq_device */
-typedef struct snd_seq_device snd_seq_device_t;
-typedef struct snd_seq_dev_ops snd_seq_dev_ops_t;
-
-/* seq_midi */
-typedef struct snd_midi_event snd_midi_event_t;
-
-/* seq_midi_emul */
-typedef struct snd_midi_channel snd_midi_channel_t;
-typedef struct snd_midi_channel_set snd_midi_channel_set_t;
-typedef struct snd_midi_op snd_midi_op_t;
-
-/* seq_oss */
-typedef struct snd_seq_oss_arg snd_seq_oss_arg_t;
-typedef struct snd_seq_oss_callback snd_seq_oss_callback_t;
-typedef struct snd_seq_oss_reg snd_seq_oss_reg_t;
-
-/* virmidi */
-typedef struct snd_virmidi_dev snd_virmidi_dev_t;
-typedef struct snd_virmidi snd_virmidi_t;
-
-/* seq_instr */
-typedef struct snd_seq_kcluster snd_seq_kcluster_t;
-typedef struct snd_seq_kinstr_ops snd_seq_kinstr_ops_t;
-typedef struct snd_seq_kinstr snd_seq_kinstr_t;
-typedef struct snd_seq_kinstr_list snd_seq_kinstr_list_t;
-
-/* ac97 */
-typedef struct snd_ac97_bus ac97_bus_t;
-typedef struct snd_ac97_bus_ops ac97_bus_ops_t;
-typedef struct snd_ac97_template ac97_template_t;
-typedef struct snd_ac97 ac97_t;
-
-/* opl3/4 */
-typedef struct snd_opl3 opl3_t;
-typedef struct snd_opl4 opl4_t;
-
-/* mpu401 */
-typedef struct snd_mpu401 mpu401_t;
-
-/* i2c */
-typedef struct snd_i2c_device snd_i2c_device_t;
-typedef struct snd_i2c_bus snd_i2c_bus_t;
-
-typedef struct snd_ak4531 ak4531_t;
-
diff --git a/include/sound/version.h b/include/sound/version.h
index 20f7bab..a9ba7ee 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by alsa/ksync script.  */
-#define CONFIG_SND_VERSION "1.0.14rc1"
-#define CONFIG_SND_DATE " (Tue Jan 09 09:56:17 2007 UTC)"
+#define CONFIG_SND_VERSION "1.0.14rc2"
+#define CONFIG_SND_DATE " (Wed Feb 14 07:42:13 2007 UTC)"
diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h
index 2173946..4830651 100644
--- a/include/sound/vx_core.h
+++ b/include/sound/vx_core.h
@@ -128,7 +128,7 @@
 	unsigned int num_ins;
 	unsigned int num_outs;
 	unsigned int output_level_max;
-	unsigned int *output_level_db_scale;
+	const unsigned int *output_level_db_scale;
 };
 
 /* hwdep id string */
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index f3514ee..203d2b4 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -270,6 +270,7 @@
 	struct snd_pcm_substream *substream;
 	struct snd_ymfpci_voice *voices[2];	/* playback only */
 	unsigned int running: 1,
+		     use_441_slot: 1,
 	             output_front: 1,
 	             output_rear: 1,
 	             swap_rear: 1;
@@ -324,6 +325,7 @@
 
 	u32 active_bank;
 	struct snd_ymfpci_voice voices[64];
+	int src441_used;
 
 	struct snd_ac97_bus *ac97_bus;
 	struct snd_ac97 *ac97;
@@ -346,7 +348,7 @@
 	int mode_dup4ch;
 	int rear_opened;
 	int spdif_opened;
-	struct {
+	struct snd_ymfpci_pcm_mixer {
 		u16 left;
 		u16 right;
 		struct snd_kcontrol *ctl;
@@ -357,6 +359,8 @@
 	wait_queue_head_t interrupt_sleep;
 	atomic_t interrupt_sleep_count;
 	struct snd_info_entry *proc_entry;
+	const struct firmware *dsp_microcode;
+	const struct firmware *controller_microcode;
 
 #ifdef CONFIG_PM
 	u32 *saved_regs;
diff --git a/include/video/neomagic.h b/include/video/neomagic.h
index 78b1f15..a9e118a 100644
--- a/include/video/neomagic.h
+++ b/include/video/neomagic.h
@@ -140,7 +140,8 @@
 
 struct neofb_par {
 	struct vgastate state;
-	atomic_t ref_count;
+	struct mutex open_lock;
+	unsigned int ref_count;
 
 	unsigned char MiscOutReg;	/* Misc */
 	unsigned char CRTC[25];		/* Crtc Controller */
diff --git a/include/video/s3blit.h b/include/video/s3blit.h
deleted file mode 100644
index b1db631..0000000
--- a/include/video/s3blit.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef _VIDEO_S3BLIT_H
-#define _VIDEO_S3BLIT_H
-
-/* s3 commands */
-#define S3_BITBLT       0xc011
-#define S3_TWOPOINTLINE 0x2811
-#define S3_FILLEDRECT   0x40b1
-
-#define S3_FIFO_EMPTY 0x0400
-#define S3_HDW_BUSY   0x0200
-
-/* Enhanced register mapping (MMIO mode) */
-
-#define S3_READ_SEL      0xbee8 /* offset f */
-#define S3_MULT_MISC     0xbee8 /* offset e */
-#define S3_ERR_TERM      0x92e8
-#define S3_FRGD_COLOR    0xa6e8
-#define S3_BKGD_COLOR    0xa2e8
-#define S3_PIXEL_CNTL    0xbee8 /* offset a */
-#define S3_FRGD_MIX      0xbae8
-#define S3_BKGD_MIX      0xb6e8
-#define S3_CUR_Y         0x82e8
-#define S3_CUR_X         0x86e8
-#define S3_DESTY_AXSTP   0x8ae8
-#define S3_DESTX_DIASTP  0x8ee8
-#define S3_MIN_AXIS_PCNT 0xbee8 /* offset 0 */
-#define S3_MAJ_AXIS_PCNT 0x96e8
-#define S3_CMD           0x9ae8
-#define S3_GP_STAT       0x9ae8
-#define S3_ADVFUNC_CNTL  0x4ae8
-#define S3_WRT_MASK      0xaae8
-#define S3_RD_MASK       0xaee8
-
-/* Enhanced register mapping (Packed MMIO mode, write only) */
-#define S3_ALT_CURXY     0x8100
-#define S3_ALT_CURXY2    0x8104
-#define S3_ALT_STEP      0x8108
-#define S3_ALT_STEP2     0x810c
-#define S3_ALT_ERR       0x8110
-#define S3_ALT_CMD       0x8118
-#define S3_ALT_MIX       0x8134
-#define S3_ALT_PCNT      0x8148
-#define S3_ALT_PAT       0x8168
-
-/* Drawing modes */
-#define S3_NOTCUR          0x0000
-#define S3_LOGICALZERO     0x0001
-#define S3_LOGICALONE      0x0002
-#define S3_LEAVEASIS       0x0003
-#define S3_NOTNEW          0x0004
-#define S3_CURXORNEW       0x0005
-#define S3_NOT_CURXORNEW   0x0006
-#define S3_NEW             0x0007
-#define S3_NOTCURORNOTNEW  0x0008
-#define S3_CURORNOTNEW     0x0009
-#define S3_NOTCURORNEW     0x000a
-#define S3_CURORNEW        0x000b
-#define S3_CURANDNEW       0x000c
-#define S3_NOTCURANDNEW    0x000d
-#define S3_CURANDNOTNEW    0x000e
-#define S3_NOTCURANDNOTNEW 0x000f
-
-#define S3_CRTC_ADR    0x03d4
-#define S3_CRTC_DATA   0x03d5
-
-#define S3_REG_LOCK2 0x39
-#define S3_HGC_MODE  0x45
-
-#define S3_HWGC_ORGX_H 0x46
-#define S3_HWGC_ORGX_L 0x47
-#define S3_HWGC_ORGY_H 0x48
-#define S3_HWGC_ORGY_L 0x49
-#define S3_HWGC_DX     0x4e
-#define S3_HWGC_DY     0x4f
-
-
-#define S3_LAW_CTL 0x58
-
-#endif /* _VIDEO_S3BLIT_H */
diff --git a/init/Kconfig b/init/Kconfig
index a3f83e2..f977086 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -125,6 +125,12 @@
 	  environments, to use ipc namespaces to provide different ipc
 	  objects for different servers.  If unsure, say N.
 
+config SYSVIPC_SYSCTL
+	bool
+	depends on SYSVIPC
+	depends on SYSCTL
+	default y
+
 config POSIX_MQUEUE
 	bool "POSIX Message Queues"
 	depends on NET && EXPERIMENTAL
@@ -192,6 +198,24 @@
 
 	  Say N if unsure.
 
+config TASK_XACCT
+	bool "Enable extended accounting over taskstats (EXPERIMENTAL)"
+	depends on TASKSTATS
+	help
+	  Collect extended task accounting data and send the data
+	  to userland for processing over the taskstats interface.
+
+	  Say N if unsure.
+
+config TASK_IO_ACCOUNTING
+	bool "Enable per-task storage I/O accounting (EXPERIMENTAL)"
+	depends on TASK_XACCT
+	help
+	  Collect information on the number of bytes of storage I/O which this
+	  task has caused.
+
+	  Say N if unsure.
+
 config UTS_NS
 	bool "UTS Namespaces"
 	default n
@@ -280,8 +304,12 @@
 
 	  If unsure, say N.
 
+if BLK_DEV_INITRD
+
 source "usr/Kconfig"
 
+endif
+
 config CC_OPTIMIZE_FOR_SIZE
 	bool "Optimize for size (Look out for broken compilers!)"
 	default y
@@ -295,24 +323,6 @@
 
 	  If unsure, say N.
 
-config TASK_XACCT
-	bool "Enable extended accounting over taskstats (EXPERIMENTAL)"
-	depends on TASKSTATS
-	help
-	  Collect extended task accounting data and send the data
-	  to userland for processing over the taskstats interface.
-
-	  Say N if unsure.
-
-config TASK_IO_ACCOUNTING
-	bool "Enable per-task storage I/O accounting (EXPERIMENTAL)"
-	depends on TASK_XACCT
-	help
-	  Collect information on the number of bytes of storage I/O which this
-	  task has caused.
-
-	  Say N if unsure.
-
 config SYSCTL
 	bool
 
diff --git a/init/Makefile b/init/Makefile
index 633a268..0154aea 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -2,7 +2,12 @@
 # Makefile for the linux kernel.
 #
 
-obj-y				:= main.o version.o mounts.o initramfs.o
+obj-y                          := main.o version.o mounts.o
+ifneq ($(CONFIG_BLK_DEV_INITRD),y)
+obj-y                          += noinitramfs.o
+else
+obj-$(CONFIG_BLK_DEV_INITRD)   += initramfs.o
+endif
 obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o
 
 mounts-y			:= do_mounts.o
diff --git a/init/calibrate.c b/init/calibrate.c
index d206c75..40ff3b4 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -4,7 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <linux/sched.h>
+#include <linux/jiffies.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 
diff --git a/init/initramfs.c b/init/initramfs.c
index 4fa0f79..00eff7a 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -491,6 +491,17 @@
 	return message;
 }
 
+static int __initdata do_retain_initrd;
+
+static int __init retain_initrd_param(char *str)
+{
+	if (*str)
+		return 0;
+	do_retain_initrd = 1;
+	return 1;
+}
+__setup("retain_initrd", retain_initrd_param);
+
 extern char __initramfs_start[], __initramfs_end[];
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/initrd.h>
@@ -501,7 +512,11 @@
 #ifdef CONFIG_KEXEC
 	unsigned long crashk_start = (unsigned long)__va(crashk_res.start);
 	unsigned long crashk_end   = (unsigned long)__va(crashk_res.end);
+#endif
+	if (do_retain_initrd)
+		goto skip;
 
+#ifdef CONFIG_KEXEC
 	/*
 	 * If the initrd region is overlapped with crashkernel reserved region,
 	 * free only memory that is not part of crashkernel region.
@@ -519,7 +534,7 @@
 	} else
 #endif
 		free_initrd_mem(initrd_start, initrd_end);
-
+skip:
 	initrd_start = 0;
 	initrd_end = 0;
 }
diff --git a/init/main.c b/init/main.c
index 8b4a7d7..a92989e 100644
--- a/init/main.c
+++ b/init/main.c
@@ -40,6 +40,8 @@
 #include <linux/cpu.h>
 #include <linux/cpuset.h>
 #include <linux/efi.h>
+#include <linux/tick.h>
+#include <linux/interrupt.h>
 #include <linux/taskstats_kern.h>
 #include <linux/delayacct.h>
 #include <linux/unistd.h>
@@ -86,7 +88,6 @@
 extern void fork_init(unsigned long);
 extern void mca_init(void);
 extern void sbus_init(void);
-extern void sysctl_init(void);
 extern void signals_init(void);
 extern void pidhash_init(void);
 extern void pidmap_init(void);
@@ -121,8 +122,12 @@
 void (*late_time_init)(void);
 extern void softirq_init(void);
 
-/* Untouched command line (eg. for /proc) saved by arch-specific code. */
-char saved_command_line[COMMAND_LINE_SIZE];
+/* Untouched command line saved by arch-specific code. */
+char __initdata boot_command_line[COMMAND_LINE_SIZE];
+/* Untouched saved command line (eg. for /proc) */
+char *saved_command_line;
+/* Command line for parameter parsing */
+static char *static_command_line;
 
 static char *execute_command;
 static char *ramdisk_execute_command;
@@ -382,29 +387,43 @@
 /* Called by boot processor to activate the rest. */
 static void __init smp_init(void)
 {
-	unsigned int i;
+	unsigned int cpu;
+	unsigned highest = 0;
+
+	for_each_cpu_mask(cpu, cpu_possible_map)
+		highest = cpu;
+	nr_cpu_ids = highest + 1;
 
 	/* FIXME: This should be done in userspace --RR */
-	for_each_present_cpu(i) {
+	for_each_present_cpu(cpu) {
 		if (num_online_cpus() >= max_cpus)
 			break;
-		if (!cpu_online(i))
-			cpu_up(i);
+		if (!cpu_online(cpu))
+			cpu_up(cpu);
 	}
 
 	/* Any cleanup work */
 	printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus());
 	smp_cpus_done(max_cpus);
-#if 0
-	/* Get other processors into their bootup holding patterns. */
-
-	smp_commence();
-#endif
 }
 
 #endif
 
 /*
+ * We need to store the untouched command line for future reference.
+ * We also need to store the touched command line since the parameter
+ * parsing is performed in place, and we should allow a component to
+ * store reference of name/value for future reference.
+ */
+static void __init setup_command_line(char *command_line)
+{
+	saved_command_line = alloc_bootmem(strlen (boot_command_line)+1);
+	static_command_line = alloc_bootmem(strlen (command_line)+1);
+	strcpy (saved_command_line, boot_command_line);
+	strcpy (static_command_line, command_line);
+}
+
+/*
  * We need to finalize in a non-__init function or else race conditions
  * between the root thread and the init thread may cause start_kernel to
  * be reaped by free_initmem before the root thread has proceeded to
@@ -458,7 +477,7 @@
 		return;
 
 	/* All fall through to do_early_param. */
-	strlcpy(tmp_cmdline, saved_command_line, COMMAND_LINE_SIZE);
+	strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 	parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);
 	done = 1;
 }
@@ -503,11 +522,13 @@
  * enable them
  */
 	lock_kernel();
+	tick_init();
 	boot_cpu_init();
 	page_address_init();
 	printk(KERN_NOTICE);
 	printk(linux_banner);
 	setup_arch(&command_line);
+	setup_command_line(command_line);
 	unwind_setup();
 	setup_per_cpu_areas();
 	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */
@@ -525,9 +546,9 @@
 	preempt_disable();
 	build_all_zonelists();
 	page_alloc_init();
-	printk(KERN_NOTICE "Kernel command line: %s\n", saved_command_line);
+	printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
 	parse_early_param();
-	parse_args("Booting kernel", command_line, __start___param,
+	parse_args("Booting kernel", static_command_line, __start___param,
 		   __stop___param - __start___param,
 		   &unknown_bootoption);
 	if (!irqs_disabled()) {
@@ -687,11 +708,7 @@
 	init_workqueues();
 	usermodehelper_init();
 	driver_init();
-
-#ifdef CONFIG_SYSCTL
-	sysctl_init();
-#endif
-
+	init_irq_proc();
 	do_initcalls();
 }
 
@@ -713,7 +730,49 @@
 	kernel_execve(init_filename, argv_init, envp_init);
 }
 
-static int init(void * unused)
+/* This is a non __init function. Force it to be noinline otherwise gcc
+ * makes it inline to init() and it becomes part of init.text section
+ */
+static int noinline init_post(void)
+{
+	free_initmem();
+	unlock_kernel();
+	mark_rodata_ro();
+	system_state = SYSTEM_RUNNING;
+	numa_default_policy();
+
+	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
+		printk(KERN_WARNING "Warning: unable to open an initial console.\n");
+
+	(void) sys_dup(0);
+	(void) sys_dup(0);
+
+	if (ramdisk_execute_command) {
+		run_init_process(ramdisk_execute_command);
+		printk(KERN_WARNING "Failed to execute %s\n",
+				ramdisk_execute_command);
+	}
+
+	/*
+	 * We try each of these until one succeeds.
+	 *
+	 * The Bourne shell can be used instead of init if we are
+	 * trying to recover a really broken machine.
+	 */
+	if (execute_command) {
+		run_init_process(execute_command);
+		printk(KERN_WARNING "Failed to execute %s.  Attempting "
+					"defaults...\n", execute_command);
+	}
+	run_init_process("/sbin/init");
+	run_init_process("/etc/init");
+	run_init_process("/bin/init");
+	run_init_process("/bin/sh");
+
+	panic("No init found.  Try passing init= option to kernel.");
+}
+
+static int __init init(void * unused)
 {
 	lock_kernel();
 	/*
@@ -761,39 +820,6 @@
 	 * we're essentially up and running. Get rid of the
 	 * initmem segments and start the user-mode stuff..
 	 */
-	free_initmem();
-	unlock_kernel();
-	mark_rodata_ro();
-	system_state = SYSTEM_RUNNING;
-	numa_default_policy();
-
-	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
-		printk(KERN_WARNING "Warning: unable to open an initial console.\n");
-
-	(void) sys_dup(0);
-	(void) sys_dup(0);
-
-	if (ramdisk_execute_command) {
-		run_init_process(ramdisk_execute_command);
-		printk(KERN_WARNING "Failed to execute %s\n",
-				ramdisk_execute_command);
-	}
-
-	/*
-	 * We try each of these until one succeeds.
-	 *
-	 * The Bourne shell can be used instead of init if we are 
-	 * trying to recover a really broken machine.
-	 */
-	if (execute_command) {
-		run_init_process(execute_command);
-		printk(KERN_WARNING "Failed to execute %s.  Attempting "
-					"defaults...\n", execute_command);
-	}
-	run_init_process("/sbin/init");
-	run_init_process("/etc/init");
-	run_init_process("/bin/init");
-	run_init_process("/bin/sh");
-
-	panic("No init found.  Try passing init= option to kernel.");
+	init_post();
+	return 0;
 }
diff --git a/init/noinitramfs.c b/init/noinitramfs.c
new file mode 100644
index 0000000..f4c1a3a
--- /dev/null
+++ b/init/noinitramfs.c
@@ -0,0 +1,52 @@
+/*
+ * init/noinitramfs.c
+ *
+ * Copyright (C) 2006, NXP Semiconductors, All Rights Reserved
+ * Author: Jean-Paul Saman <jean-paul.saman@nxp.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; version 2 of the License.
+ *
+ * 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/init.h>
+#include <linux/stat.h>
+#include <linux/kdev_t.h>
+#include <linux/syscalls.h>
+
+/*
+ * Create a simple rootfs that is similar to the default initramfs
+ */
+static int __init default_rootfs(void)
+{
+	int err;
+
+	err = sys_mkdir("/dev", 0755);
+	if (err < 0)
+		goto out;
+
+	err = sys_mknod((const char __user *) "/dev/console",
+			S_IFCHR | S_IRUSR | S_IWUSR,
+			new_encode_dev(MKDEV(5, 1)));
+	if (err < 0)
+		goto out;
+
+	err = sys_mkdir("/root", 0700);
+	if (err < 0)
+		goto out;
+
+	return 0;
+
+out:
+	printk(KERN_WARNING "Failed to create a rootfs\n");
+	return err;
+}
+rootfs_initcall(default_rootfs);
diff --git a/init/version.c b/init/version.c
index 6c01ec1..9d17d70 100644
--- a/init/version.c
+++ b/init/version.c
@@ -12,7 +12,6 @@
 #include <linux/utsname.h>
 #include <linux/utsrelease.h>
 #include <linux/version.h>
-#include <linux/sched.h>
 
 #define version(a) Version_ ## a
 #define version_string(a) version(a)
diff --git a/ipc/Makefile b/ipc/Makefile
index 0a6d626..b93bba6 100644
--- a/ipc/Makefile
+++ b/ipc/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o
 obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o
+obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o
 obj_mq-$(CONFIG_COMPAT) += compat_mq.o
 obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
 
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
new file mode 100644
index 0000000..a88934a
--- /dev/null
+++ b/ipc/ipc_sysctl.c
@@ -0,0 +1,183 @@
+/*
+ *  Copyright (C) 2007
+ *
+ *  Author: Eric Biederman <ebiederm@xmision.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, version 2 of the
+ *  License.
+ */
+
+#include <linux/module.h>
+#include <linux/ipc.h>
+#include <linux/nsproxy.h>
+#include <linux/sysctl.h>
+#include <linux/uaccess.h>
+
+#ifdef CONFIG_IPC_NS
+static void *get_ipc(ctl_table *table)
+{
+	char *which = table->data;
+	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
+	which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
+	return which;
+}
+#else
+#define get_ipc(T) ((T)->data)
+#endif
+
+#ifdef CONFIG_PROC_FS
+static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+	void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table ipc_table;
+	memcpy(&ipc_table, table, sizeof(ipc_table));
+	ipc_table.data = get_ipc(table);
+
+	return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
+}
+
+static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
+	struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table ipc_table;
+	memcpy(&ipc_table, table, sizeof(ipc_table));
+	ipc_table.data = get_ipc(table);
+
+	return proc_doulongvec_minmax(&ipc_table, write, filp, buffer,
+					lenp, ppos);
+}
+
+#else
+#define proc_ipc_doulongvec_minmax NULL
+#define proc_ipc_dointvec	   NULL
+#endif
+
+#ifdef CONFIG_SYSCTL_SYSCALL
+/* The generic sysctl ipc data routine. */
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+		void __user *oldval, size_t __user *oldlenp,
+		void __user *newval, size_t newlen)
+{
+	size_t len;
+	void *data;
+
+	/* Get out of I don't have a variable */
+	if (!table->data || !table->maxlen)
+		return -ENOTDIR;
+
+	data = get_ipc(table);
+	if (!data)
+		return -ENOTDIR;
+
+	if (oldval && oldlenp) {
+		if (get_user(len, oldlenp))
+			return -EFAULT;
+		if (len) {
+			if (len > table->maxlen)
+				len = table->maxlen;
+			if (copy_to_user(oldval, data, len))
+				return -EFAULT;
+			if (put_user(len, oldlenp))
+				return -EFAULT;
+		}
+	}
+
+	if (newval && newlen) {
+		if (newlen > table->maxlen)
+			newlen = table->maxlen;
+
+		if (copy_from_user(data, newval, newlen))
+			return -EFAULT;
+	}
+	return 1;
+}
+#else
+#define sysctl_ipc_data NULL
+#endif
+
+static struct ctl_table ipc_kern_table[] = {
+	{
+		.ctl_name	= KERN_SHMMAX,
+		.procname	= "shmmax",
+		.data		= &init_ipc_ns.shm_ctlmax,
+		.maxlen		= sizeof (init_ipc_ns.shm_ctlmax),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_doulongvec_minmax,
+		.strategy	= sysctl_ipc_data,
+	},
+	{
+		.ctl_name	= KERN_SHMALL,
+		.procname	= "shmall",
+		.data		= &init_ipc_ns.shm_ctlall,
+		.maxlen		= sizeof (init_ipc_ns.shm_ctlall),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_doulongvec_minmax,
+		.strategy	= sysctl_ipc_data,
+	},
+	{
+		.ctl_name	= KERN_SHMMNI,
+		.procname	= "shmmni",
+		.data		= &init_ipc_ns.shm_ctlmni,
+		.maxlen		= sizeof (init_ipc_ns.shm_ctlmni),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_dointvec,
+		.strategy	= sysctl_ipc_data,
+	},
+	{
+		.ctl_name	= KERN_MSGMAX,
+		.procname	= "msgmax",
+		.data		= &init_ipc_ns.msg_ctlmax,
+		.maxlen		= sizeof (init_ipc_ns.msg_ctlmax),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_dointvec,
+		.strategy	= sysctl_ipc_data,
+	},
+	{
+		.ctl_name	= KERN_MSGMNI,
+		.procname	= "msgmni",
+		.data		= &init_ipc_ns.msg_ctlmni,
+		.maxlen		= sizeof (init_ipc_ns.msg_ctlmni),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_dointvec,
+		.strategy	= sysctl_ipc_data,
+	},
+	{
+		.ctl_name	= KERN_MSGMNB,
+		.procname	=  "msgmnb",
+		.data		= &init_ipc_ns.msg_ctlmnb,
+		.maxlen		= sizeof (init_ipc_ns.msg_ctlmnb),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_dointvec,
+		.strategy	= sysctl_ipc_data,
+	},
+	{
+		.ctl_name	= KERN_SEM,
+		.procname	= "sem",
+		.data		= &init_ipc_ns.sem_ctls,
+		.maxlen		= 4*sizeof (int),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_dointvec,
+		.strategy	= sysctl_ipc_data,
+	},
+	{}
+};
+
+static struct ctl_table ipc_root_table[] = {
+	{
+		.ctl_name	= CTL_KERN,
+		.procname	= "kernel",
+		.mode		= 0555,
+		.child		= ipc_kern_table,
+	},
+	{}
+};
+
+static int __init ipc_sysctl_init(void)
+{
+	register_sysctl_table(ipc_root_table);
+	return 0;
+}
+
+__initcall(ipc_sysctl_init);
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 02717f7..0b5ecbe 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -84,8 +84,8 @@
 	unsigned long qsize; /* size of queue in memory (sum of all msgs) */
 };
 
-static struct inode_operations mqueue_dir_inode_operations;
-static struct file_operations mqueue_file_operations;
+static const struct inode_operations mqueue_dir_inode_operations;
+static const struct file_operations mqueue_file_operations;
 static struct super_operations mqueue_super_ops;
 static void remove_notification(struct mqueue_inode_info *info);
 
@@ -1160,13 +1160,13 @@
 	return ret;
 }
 
-static struct inode_operations mqueue_dir_inode_operations = {
+static const struct inode_operations mqueue_dir_inode_operations = {
 	.lookup = simple_lookup,
 	.create = mqueue_create,
 	.unlink = mqueue_unlink,
 };
 
-static struct file_operations mqueue_file_operations = {
+static const struct file_operations mqueue_file_operations = {
 	.flush = mqueue_flush_file,
 	.poll = mqueue_poll_file,
 	.read = mqueue_read_file,
@@ -1255,7 +1255,7 @@
 		return -ENOMEM;
 
 	/* ignore failues - they are not fatal */
-	mq_sysctl_table = register_sysctl_table(mq_sysctl_root, 0);
+	mq_sysctl_table = register_sysctl_table(mq_sysctl_root);
 
 	error = register_filesystem(&mqueue_fs_type);
 	if (error)
diff --git a/ipc/shm.c b/ipc/shm.c
index f8e10a2..eb57e22 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -37,12 +37,22 @@
 #include <linux/seq_file.h>
 #include <linux/mutex.h>
 #include <linux/nsproxy.h>
+#include <linux/mount.h>
 
 #include <asm/uaccess.h>
 
 #include "util.h"
 
-static struct file_operations shm_file_operations;
+struct shm_file_data {
+	int id;
+	struct ipc_namespace *ns;
+	struct file *file;
+	const struct vm_operations_struct *vm_ops;
+};
+
+#define shm_file_data(file) (*((struct shm_file_data **)&(file)->private_data))
+
+static const struct file_operations shm_file_operations;
 static struct vm_operations_struct shm_vm_ops;
 
 static struct ipc_ids init_shm_ids;
@@ -60,8 +70,8 @@
 
 static int newseg (struct ipc_namespace *ns, key_t key,
 		int shmflg, size_t size);
-static void shm_open (struct vm_area_struct *shmd);
-static void shm_close (struct vm_area_struct *shmd);
+static void shm_open(struct vm_area_struct *vma);
+static void shm_close(struct vm_area_struct *vma);
 static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
 #ifdef CONFIG_PROC_FS
 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
@@ -150,11 +160,14 @@
 
 
 
-static inline void shm_inc(struct ipc_namespace *ns, int id)
+/* This is called by fork, once for every shm attach. */
+static void shm_open(struct vm_area_struct *vma)
 {
+	struct file *file = vma->vm_file;
+	struct shm_file_data *sfd = shm_file_data(file);
 	struct shmid_kernel *shp;
 
-	shp = shm_lock(ns, id);
+	shp = shm_lock(sfd->ns, sfd->id);
 	BUG_ON(!shp);
 	shp->shm_atim = get_seconds();
 	shp->shm_lprid = current->tgid;
@@ -162,15 +175,6 @@
 	shm_unlock(shp);
 }
 
-#define shm_file_ns(file) (*((struct ipc_namespace **)&(file)->private_data))
-
-/* This is called by fork, once for every shm attach. */
-static void shm_open(struct vm_area_struct *shmd)
-{
-	shm_inc(shm_file_ns(shmd->vm_file),
-			shmd->vm_file->f_path.dentry->d_inode->i_ino);
-}
-
 /*
  * shm_destroy - free the struct shmid_kernel
  *
@@ -195,23 +199,21 @@
 }
 
 /*
- * remove the attach descriptor shmd.
+ * remove the attach descriptor vma.
  * free memory for segment if it is marked destroyed.
  * The descriptor has already been removed from the current->mm->mmap list
  * and will later be kfree()d.
  */
-static void shm_close (struct vm_area_struct *shmd)
+static void shm_close(struct vm_area_struct *vma)
 {
-	struct file * file = shmd->vm_file;
-	int id = file->f_path.dentry->d_inode->i_ino;
+	struct file * file = vma->vm_file;
+	struct shm_file_data *sfd = shm_file_data(file);
 	struct shmid_kernel *shp;
-	struct ipc_namespace *ns;
-
-	ns = shm_file_ns(file);
+	struct ipc_namespace *ns = sfd->ns;
 
 	mutex_lock(&shm_ids(ns).mutex);
 	/* remove from the list of attaches of the shm segment */
-	shp = shm_lock(ns, id);
+	shp = shm_lock(ns, sfd->id);
 	BUG_ON(!shp);
 	shp->shm_lprid = current->tgid;
 	shp->shm_dtim = get_seconds();
@@ -224,46 +226,91 @@
 	mutex_unlock(&shm_ids(ns).mutex);
 }
 
+struct page *shm_nopage(struct vm_area_struct *vma, unsigned long address,
+			int *type)
+{
+	struct file *file = vma->vm_file;
+	struct shm_file_data *sfd = shm_file_data(file);
+
+	return sfd->vm_ops->nopage(vma, address, type);
+}
+
+#ifdef CONFIG_NUMA
+int shm_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
+{
+	struct file *file = vma->vm_file;
+	struct shm_file_data *sfd = shm_file_data(file);
+	int err = 0;
+	if (sfd->vm_ops->set_policy)
+		err = sfd->vm_ops->set_policy(vma, new);
+	return err;
+}
+
+struct mempolicy *shm_get_policy(struct vm_area_struct *vma, unsigned long addr)
+{
+	struct file *file = vma->vm_file;
+	struct shm_file_data *sfd = shm_file_data(file);
+	struct mempolicy *pol = NULL;
+
+	if (sfd->vm_ops->get_policy)
+		pol = sfd->vm_ops->get_policy(vma, addr);
+	else
+		pol = vma->vm_policy;
+	return pol;
+}
+#endif
+
 static int shm_mmap(struct file * file, struct vm_area_struct * vma)
 {
+	struct shm_file_data *sfd = shm_file_data(file);
 	int ret;
 
-	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(shm_file_ns(file), file->f_path.dentry->d_inode->i_ino);
-	}
+	ret = sfd->file->f_op->mmap(sfd->file, vma);
+	if (ret != 0)
+		return ret;
+	sfd->vm_ops = vma->vm_ops;
+	vma->vm_ops = &shm_vm_ops;
+	shm_open(vma);
 
 	return ret;
 }
 
 static int shm_release(struct inode *ino, struct file *file)
 {
-	struct ipc_namespace *ns;
+	struct shm_file_data *sfd = shm_file_data(file);
 
-	ns = shm_file_ns(file);
-	put_ipc_ns(ns);
-	shm_file_ns(file) = NULL;
+	put_ipc_ns(sfd->ns);
+	shm_file_data(file) = NULL;
+	kfree(sfd);
 	return 0;
 }
 
-static struct file_operations shm_file_operations = {
+#ifndef CONFIG_MMU
+static unsigned long shm_get_unmapped_area(struct file *file,
+	unsigned long addr, unsigned long len, unsigned long pgoff,
+	unsigned long flags)
+{
+	struct shm_file_data *sfd = shm_file_data(file);
+	return sfd->file->f_op->get_unmapped_area(sfd->file, addr, len, pgoff,
+							flags);
+}
+#else
+#define shm_get_unmapped_area NULL
+#endif
+
+static const struct file_operations shm_file_operations = {
 	.mmap		= shm_mmap,
 	.release	= shm_release,
-#ifndef CONFIG_MMU
-	.get_unmapped_area = shmem_get_unmapped_area,
-#endif
+	.get_unmapped_area	= shm_get_unmapped_area,
 };
 
 static struct vm_operations_struct shm_vm_ops = {
 	.open	= shm_open,	/* callback for a new vm-area open */
 	.close	= shm_close,	/* callback for when the vm-area is released */
-	.nopage	= shmem_nopage,
-#if defined(CONFIG_NUMA) && defined(CONFIG_SHMEM)
-	.set_policy = shmem_set_policy,
-	.get_policy = shmem_get_policy,
+	.nopage	= shm_nopage,
+#if defined(CONFIG_NUMA)
+	.set_policy = shm_set_policy,
+	.get_policy = shm_get_policy,
 #endif
 };
 
@@ -330,13 +377,6 @@
 	shp->shm_nattch = 0;
 	shp->id = shm_buildid(ns, id, shp->shm_perm.seq);
 	shp->shm_file = file;
-	file->f_path.dentry->d_inode->i_ino = shp->id;
-
-	shm_file_ns(file) = get_ipc_ns(ns);
-
-	/* Hugetlb ops would have already been assigned. */
-	if (!(shmflg & SHM_HUGETLB))
-		file->f_op = &shm_file_operations;
 
 	ns->shm_tot += numpages;
 	shm_unlock(shp);
@@ -607,10 +647,7 @@
 		tbuf.shm_ctime	= shp->shm_ctim;
 		tbuf.shm_cpid	= shp->shm_cprid;
 		tbuf.shm_lpid	= shp->shm_lprid;
-		if (!is_file_hugepages(shp->shm_file))
-			tbuf.shm_nattch	= shp->shm_nattch;
-		else
-			tbuf.shm_nattch = file_count(shp->shm_file) - 1;
+		tbuf.shm_nattch	= shp->shm_nattch;
 		shm_unlock(shp);
 		if(copy_shmid_to_user (buf, &tbuf, version))
 			err = -EFAULT;
@@ -779,13 +816,16 @@
 	unsigned long flags;
 	unsigned long prot;
 	int acc_mode;
-	void *user_addr;
+	unsigned long user_addr;
 	struct ipc_namespace *ns;
+	struct shm_file_data *sfd;
+	struct path path;
+	mode_t f_mode;
 
-	if (shmid < 0) {
-		err = -EINVAL;
+	err = -EINVAL;
+	if (shmid < 0)
 		goto out;
-	} else if ((addr = (ulong)shmaddr)) {
+	else if ((addr = (ulong)shmaddr)) {
 		if (addr & (SHMLBA-1)) {
 			if (shmflg & SHM_RND)
 				addr &= ~(SHMLBA-1);	   /* round down */
@@ -793,12 +833,12 @@
 #ifndef __ARCH_FORCE_SHMLBA
 				if (addr & ~PAGE_MASK)
 #endif
-					return -EINVAL;
+					goto out;
 		}
 		flags = MAP_SHARED | MAP_FIXED;
 	} else {
 		if ((shmflg & SHM_REMAP))
-			return -EINVAL;
+			goto out;
 
 		flags = MAP_SHARED;
 	}
@@ -806,9 +846,11 @@
 	if (shmflg & SHM_RDONLY) {
 		prot = PROT_READ;
 		acc_mode = S_IRUGO;
+		f_mode = FMODE_READ;
 	} else {
 		prot = PROT_READ | PROT_WRITE;
 		acc_mode = S_IRUGO | S_IWUGO;
+		f_mode = FMODE_READ | FMODE_WRITE;
 	}
 	if (shmflg & SHM_EXEC) {
 		prot |= PROT_EXEC;
@@ -821,35 +863,50 @@
 	 */
 	ns = current->nsproxy->ipc_ns;
 	shp = shm_lock(ns, shmid);
-	if(shp == NULL) {
-		err = -EINVAL;
+	if(shp == NULL)
 		goto out;
-	}
+
 	err = shm_checkid(ns, shp,shmid);
-	if (err) {
-		shm_unlock(shp);
-		goto out;
-	}
-	if (ipcperms(&shp->shm_perm, acc_mode)) {
-		shm_unlock(shp);
-		err = -EACCES;
-		goto out;
-	}
+	if (err)
+		goto out_unlock;
+
+	err = -EACCES;
+	if (ipcperms(&shp->shm_perm, acc_mode))
+		goto out_unlock;
 
 	err = security_shm_shmat(shp, shmaddr, shmflg);
-	if (err) {
-		shm_unlock(shp);
-		return err;
-	}
-		
-	file = shp->shm_file;
-	size = i_size_read(file->f_path.dentry->d_inode);
+	if (err)
+		goto out_unlock;
+
+	path.dentry = dget(shp->shm_file->f_path.dentry);
+	path.mnt    = mntget(shp->shm_file->f_path.mnt);
 	shp->shm_nattch++;
+	size = i_size_read(path.dentry->d_inode);
 	shm_unlock(shp);
 
+	err = -ENOMEM;
+	sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
+	if (!sfd)
+		goto out_put_path;
+
+	err = -ENOMEM;
+	file = get_empty_filp();
+	if (!file)
+		goto out_free;
+
+	file->f_op = &shm_file_operations;
+	file->private_data = sfd;
+	file->f_path = path;
+	file->f_mapping = shp->shm_file->f_mapping;
+	file->f_mode = f_mode;
+	sfd->id = shp->id;
+	sfd->ns = get_ipc_ns(ns);
+	sfd->file = shp->shm_file;
+	sfd->vm_ops = NULL;
+
 	down_write(&current->mm->mmap_sem);
 	if (addr && !(shmflg & SHM_REMAP)) {
-		user_addr = ERR_PTR(-EINVAL);
+		err = -EINVAL;
 		if (find_vma_intersection(current->mm, addr, addr + size))
 			goto invalid;
 		/*
@@ -861,11 +918,17 @@
 			goto invalid;
 	}
 		
-	user_addr = (void*) do_mmap (file, addr, size, prot, flags, 0);
-
+	user_addr = do_mmap (file, addr, size, prot, flags, 0);
+	*raddr = user_addr;
+	err = 0;
+	if (IS_ERR_VALUE(user_addr))
+		err = (long)user_addr;
 invalid:
 	up_write(&current->mm->mmap_sem);
 
+	fput(file);
+
+out_nattch:
 	mutex_lock(&shm_ids(ns).mutex);
 	shp = shm_lock(ns, shmid);
 	BUG_ON(!shp);
@@ -877,12 +940,19 @@
 		shm_unlock(shp);
 	mutex_unlock(&shm_ids(ns).mutex);
 
-	*raddr = (unsigned long) user_addr;
-	err = 0;
-	if (IS_ERR(user_addr))
-		err = PTR_ERR(user_addr);
 out:
 	return err;
+
+out_unlock:
+	shm_unlock(shp);
+	goto out;
+
+out_free:
+	kfree(sfd);
+out_put_path:
+	dput(path.dentry);
+	mntput(path.mnt);
+	goto out_nattch;
 }
 
 asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg)
@@ -944,7 +1014,7 @@
 		 * a fragment created by mprotect() and/or munmap(), or it
 		 * otherwise it starts at this address with no hassles.
 		 */
-		if ((vma->vm_ops == &shm_vm_ops || is_vm_hugetlb_page(vma)) &&
+		if ((vma->vm_ops == &shm_vm_ops) &&
 			(vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) {
 
 
@@ -973,7 +1043,7 @@
 		next = vma->vm_next;
 
 		/* finding a matching vma now does not alter retval */
-		if ((vma->vm_ops == &shm_vm_ops || is_vm_hugetlb_page(vma)) &&
+		if ((vma->vm_ops == &shm_vm_ops) &&
 			(vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff)
 
 			do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
@@ -1004,7 +1074,7 @@
 			  shp->shm_segsz,
 			  shp->shm_cprid,
 			  shp->shm_lprid,
-			  is_file_hugepages(shp->shm_file) ? (file_count(shp->shm_file) - 1) : shp->shm_nattch,
+			  shp->shm_nattch,
 			  shp->shm_perm.uid,
 			  shp->shm_perm.gid,
 			  shp->shm_perm.cuid,
diff --git a/ipc/util.c b/ipc/util.c
index a9b7a22..08a6479 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -150,7 +150,7 @@
  *	ipc_init	-	initialise IPC subsystem
  *
  *	The various system5 IPC resources (semaphores, messages and shared
- *	memory are initialised
+ *	memory) are initialised
  */
  
 static int __init ipc_init(void)
@@ -205,10 +205,9 @@
 }
 
 #ifdef CONFIG_PROC_FS
-static struct file_operations sysvipc_proc_fops;
+static const struct file_operations sysvipc_proc_fops;
 /**
- *	ipc_init_proc_interface	-  Create a proc interface for sysipc types
- *				   using a seq_file interface.
+ *	ipc_init_proc_interface	-  Create a proc interface for sysipc types using a seq_file interface.
  *	@path: Path in procfs
  *	@header: Banner to be printed at the beginning of the file.
  *	@ids: ipc id table to iterate.
@@ -417,7 +416,7 @@
  *	@ptr: pointer returned by ipc_alloc
  *	@size: size of block
  *
- *	Free a block created with ipc_alloc. The caller must know the size
+ *	Free a block created with ipc_alloc(). The caller must know the size
  *	used in the allocation call.
  */
 
@@ -524,7 +523,7 @@
  * @head: RCU callback structure for queued work
  * 
  * Since RCU callback function is called in bh,
- * we need to defer the vfree to schedule_work
+ * we need to defer the vfree to schedule_work().
  */
 static void ipc_schedule_free(struct rcu_head *head)
 {
@@ -541,7 +540,7 @@
  * ipc_immediate_free - free ipc + rcu space
  * @head: RCU callback structure that contains pointer to be freed
  *
- * Free from the RCU callback context
+ * Free from the RCU callback context.
  */
 static void ipc_immediate_free(struct rcu_head *head)
 {
@@ -603,8 +602,8 @@
  *	@in: kernel permissions
  *	@out: new style IPC permissions
  *
- *	Turn the kernel object 'in' into a set of permissions descriptions
- *	for returning to userspace (out).
+ *	Turn the kernel object @in into a set of permissions descriptions
+ *	for returning to userspace (@out).
  */
  
 
@@ -624,8 +623,8 @@
  *	@in: new style IPC permissions
  *	@out: old style IPC permissions
  *
- *	Turn the new style permissions object in into a compatibility
- *	object and store it into the 'out' pointer.
+ *	Turn the new style permissions object @in into a compatibility
+ *	object and store it into the @out pointer.
  */
  
 void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)
@@ -722,7 +721,7 @@
  *	@cmd: pointer to command
  *
  *	Return IPC_64 for new style IPC and IPC_OLD for old style IPC. 
- *	The cmd value is turned from an encoding command and version into
+ *	The @cmd value is turned from an encoding command and version into
  *	just the command code.
  */
  
@@ -739,14 +738,20 @@
 #endif /* __ARCH_WANT_IPC_PARSE_VERSION */
 
 #ifdef CONFIG_PROC_FS
+struct ipc_proc_iter {
+	struct ipc_namespace *ns;
+	struct ipc_proc_iface *iface;
+};
+
 static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
 {
-	struct ipc_proc_iface *iface = s->private;
+	struct ipc_proc_iter *iter = s->private;
+	struct ipc_proc_iface *iface = iter->iface;
 	struct kern_ipc_perm *ipc = it;
 	loff_t p;
 	struct ipc_ids *ids;
 
-	ids = current->nsproxy->ipc_ns->ids[iface->ids];
+	ids = iter->ns->ids[iface->ids];
 
 	/* If we had an ipc id locked before, unlock it */
 	if (ipc && ipc != SEQ_START_TOKEN)
@@ -773,12 +778,13 @@
  */
 static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
 {
-	struct ipc_proc_iface *iface = s->private;
+	struct ipc_proc_iter *iter = s->private;
+	struct ipc_proc_iface *iface = iter->iface;
 	struct kern_ipc_perm *ipc;
 	loff_t p;
 	struct ipc_ids *ids;
 
-	ids = current->nsproxy->ipc_ns->ids[iface->ids];
+	ids = iter->ns->ids[iface->ids];
 
 	/*
 	 * Take the lock - this will be released by the corresponding
@@ -807,21 +813,23 @@
 static void sysvipc_proc_stop(struct seq_file *s, void *it)
 {
 	struct kern_ipc_perm *ipc = it;
-	struct ipc_proc_iface *iface = s->private;
+	struct ipc_proc_iter *iter = s->private;
+	struct ipc_proc_iface *iface = iter->iface;
 	struct ipc_ids *ids;
 
 	/* If we had a locked segment, release it */
 	if (ipc && ipc != SEQ_START_TOKEN)
 		ipc_unlock(ipc);
 
-	ids = current->nsproxy->ipc_ns->ids[iface->ids];
+	ids = iter->ns->ids[iface->ids];
 	/* Release the lock we took in start() */
 	mutex_unlock(&ids->mutex);
 }
 
 static int sysvipc_proc_show(struct seq_file *s, void *it)
 {
-	struct ipc_proc_iface *iface = s->private;
+	struct ipc_proc_iter *iter = s->private;
+	struct ipc_proc_iface *iface = iter->iface;
 
 	if (it == SEQ_START_TOKEN)
 		return seq_puts(s, iface->header);
@@ -836,22 +844,45 @@
 	.show  = sysvipc_proc_show,
 };
 
-static int sysvipc_proc_open(struct inode *inode, struct file *file) {
+static int sysvipc_proc_open(struct inode *inode, struct file *file)
+{
 	int ret;
 	struct seq_file *seq;
+	struct ipc_proc_iter *iter;
+
+	ret = -ENOMEM;
+	iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+	if (!iter)
+		goto out;
 
 	ret = seq_open(file, &sysvipc_proc_seqops);
-	if (!ret) {
-		seq = file->private_data;
-		seq->private = PDE(inode)->data;
-	}
+	if (ret)
+		goto out_kfree;
+
+	seq = file->private_data;
+	seq->private = iter;
+
+	iter->iface = PDE(inode)->data;
+	iter->ns    = get_ipc_ns(current->nsproxy->ipc_ns);
+out:
 	return ret;
+out_kfree:
+	kfree(iter);
+	goto out;
 }
 
-static struct file_operations sysvipc_proc_fops = {
+static int sysvipc_proc_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq = file->private_data;
+	struct ipc_proc_iter *iter = seq->private;
+	put_ipc_ns(iter->ns);
+	return seq_release_private(inode, file);
+}
+
+static const struct file_operations sysvipc_proc_fops = {
 	.open    = sysvipc_proc_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release,
+	.release = sysvipc_proc_release,
 };
 #endif /* CONFIG_PROC_FS */
diff --git a/kernel/Makefile b/kernel/Makefile
index 14f4d45..ac6b27a 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -47,6 +47,7 @@
 obj-$(CONFIG_SECCOMP) += seccomp.o
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_RELAY) += relay.o
+obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
 obj-$(CONFIG_UTS_NS) += utsname.o
 obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
 obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
diff --git a/kernel/audit.c b/kernel/audit.c
index d9b690a..76c9a11 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2,7 +2,7 @@
  * Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
  * System-call specific features have moved to auditsc.c
  *
- * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -65,7 +65,9 @@
  * (Initialization happens after skb_init is called.) */
 static int	audit_initialized;
 
-/* No syscall auditing will take place unless audit_enabled != 0. */
+/* 0 - no auditing
+ * 1 - auditing enabled
+ * 2 - auditing enabled and configuration is locked/unchangeable. */
 int		audit_enabled;
 
 /* Default state when kernel boots without any parameters. */
@@ -239,102 +241,150 @@
 
 static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
 {
-	int old	= audit_rate_limit;
+	int res, rc = 0, old = audit_rate_limit;
+
+	/* check if we are locked */
+	if (audit_enabled == 2)
+		res = 0;
+	else
+		res = 1;
 
 	if (sid) {
 		char *ctx = NULL;
 		u32 len;
-		int rc;
-		if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
-			return rc;
-		else
+		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
 			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				"audit_rate_limit=%d old=%d by auid=%u subj=%s",
-				limit, old, loginuid, ctx);
-		kfree(ctx);
-	} else
-		audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-			"audit_rate_limit=%d old=%d by auid=%u",
-			limit, old, loginuid);
-	audit_rate_limit = limit;
-	return 0;
+				"audit_rate_limit=%d old=%d by auid=%u"
+				" subj=%s res=%d",
+				limit, old, loginuid, ctx, res);
+			kfree(ctx);
+		} else
+			res = 0; /* Something weird, deny request */
+	}
+	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+		"audit_rate_limit=%d old=%d by auid=%u res=%d",
+		limit, old, loginuid, res);
+
+	/* If we are allowed, make the change */
+	if (res == 1)
+		audit_rate_limit = limit;
+	/* Not allowed, update reason */
+	else if (rc == 0)
+		rc = -EPERM;
+	return rc;
 }
 
 static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
 {
-	int old	= audit_backlog_limit;
+	int res, rc = 0, old = audit_backlog_limit;
+
+	/* check if we are locked */
+	if (audit_enabled == 2)
+		res = 0;
+	else
+		res = 1;
 
 	if (sid) {
 		char *ctx = NULL;
 		u32 len;
-		int rc;
-		if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
-			return rc;
-		else
+		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
 			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-			    "audit_backlog_limit=%d old=%d by auid=%u subj=%s",
-				limit, old, loginuid, ctx);
-		kfree(ctx);
-	} else
-		audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-			"audit_backlog_limit=%d old=%d by auid=%u",
-			limit, old, loginuid);
-	audit_backlog_limit = limit;
-	return 0;
+				"audit_backlog_limit=%d old=%d by auid=%u"
+				" subj=%s res=%d",
+				limit, old, loginuid, ctx, res);
+			kfree(ctx);
+		} else
+			res = 0; /* Something weird, deny request */
+	}
+	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+		"audit_backlog_limit=%d old=%d by auid=%u res=%d",
+		limit, old, loginuid, res);
+
+	/* If we are allowed, make the change */
+	if (res == 1)
+		audit_backlog_limit = limit;
+	/* Not allowed, update reason */
+	else if (rc == 0)
+		rc = -EPERM;
+	return rc;
 }
 
 static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
 {
-	int old = audit_enabled;
+	int res, rc = 0, old = audit_enabled;
 
-	if (state != 0 && state != 1)
+	if (state < 0 || state > 2)
 		return -EINVAL;
 
+	/* check if we are locked */
+	if (audit_enabled == 2)
+		res = 0;
+	else
+		res = 1;
+
 	if (sid) {
 		char *ctx = NULL;
 		u32 len;
-		int rc;
-		if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
-			return rc;
-		else
+		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
 			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				"audit_enabled=%d old=%d by auid=%u subj=%s",
-				state, old, loginuid, ctx);
-		kfree(ctx);
-	} else
-		audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-			"audit_enabled=%d old=%d by auid=%u",
-			state, old, loginuid);
-	audit_enabled = state;
-	return 0;
+				"audit_enabled=%d old=%d by auid=%u"
+				" subj=%s res=%d",
+				state, old, loginuid, ctx, res);
+			kfree(ctx);
+		} else
+			res = 0; /* Something weird, deny request */
+	}
+	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+		"audit_enabled=%d old=%d by auid=%u res=%d",
+		state, old, loginuid, res);
+
+	/* If we are allowed, make the change */
+	if (res == 1)
+		audit_enabled = state;
+	/* Not allowed, update reason */
+	else if (rc == 0)
+		rc = -EPERM;
+	return rc;
 }
 
 static int audit_set_failure(int state, uid_t loginuid, u32 sid)
 {
-	int old = audit_failure;
+	int res, rc = 0, old = audit_failure;
 
 	if (state != AUDIT_FAIL_SILENT
 	    && state != AUDIT_FAIL_PRINTK
 	    && state != AUDIT_FAIL_PANIC)
 		return -EINVAL;
 
+	/* check if we are locked */
+	if (audit_enabled == 2)
+		res = 0;
+	else
+		res = 1;
+
 	if (sid) {
 		char *ctx = NULL;
 		u32 len;
-		int rc;
-		if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
-			return rc;
-		else
+		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
 			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				"audit_failure=%d old=%d by auid=%u subj=%s",
-				state, old, loginuid, ctx);
-		kfree(ctx);
-	} else
-		audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-			"audit_failure=%d old=%d by auid=%u",
-			state, old, loginuid);
-	audit_failure = state;
-	return 0;
+				"audit_failure=%d old=%d by auid=%u"
+				" subj=%s res=%d",
+				state, old, loginuid, ctx, res);
+			kfree(ctx);
+		} else
+			res = 0; /* Something weird, deny request */
+	}
+	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+		"audit_failure=%d old=%d by auid=%u res=%d",
+		state, old, loginuid, res);
+
+	/* If we are allowed, make the change */
+	if (res == 1)
+		audit_failure = state;
+	/* Not allowed, update reason */
+	else if (rc == 0)
+		rc = -EPERM;
+	return rc;
 }
 
 static int kauditd_thread(void *dummy)
@@ -599,6 +649,30 @@
 	case AUDIT_DEL:
 		if (nlmsg_len(nlh) < sizeof(struct audit_rule))
 			return -EINVAL;
+		if (audit_enabled == 2) {
+			ab = audit_log_start(NULL, GFP_KERNEL,
+					AUDIT_CONFIG_CHANGE);
+			if (ab) {
+				audit_log_format(ab,
+						 "pid=%d uid=%u auid=%u",
+						 pid, uid, loginuid);
+				if (sid) {
+					if (selinux_sid_to_string(
+							sid, &ctx, &len)) {
+						audit_log_format(ab,
+							" ssid=%u", sid);
+						/* Maybe call audit_panic? */
+					} else
+						audit_log_format(ab,
+							" subj=%s", ctx);
+					kfree(ctx);
+				}
+				audit_log_format(ab, " audit_enabled=%d res=0",
+					audit_enabled);
+				audit_log_end(ab);
+			}
+			return -EPERM;
+		}
 		/* fallthrough */
 	case AUDIT_LIST:
 		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
@@ -609,6 +683,30 @@
 	case AUDIT_DEL_RULE:
 		if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
 			return -EINVAL;
+		if (audit_enabled == 2) {
+			ab = audit_log_start(NULL, GFP_KERNEL,
+					AUDIT_CONFIG_CHANGE);
+			if (ab) {
+				audit_log_format(ab,
+						 "pid=%d uid=%u auid=%u",
+						 pid, uid, loginuid);
+				if (sid) {
+					if (selinux_sid_to_string(
+							sid, &ctx, &len)) {
+						audit_log_format(ab,
+							" ssid=%u", sid);
+						/* Maybe call audit_panic? */
+					} else
+						audit_log_format(ab,
+							" subj=%s", ctx);
+					kfree(ctx);
+				}
+				audit_log_format(ab, " audit_enabled=%d res=0",
+					audit_enabled);
+				audit_log_end(ab);
+			}
+			return -EPERM;
+		}
 		/* fallthrough */
 	case AUDIT_LIST_RULES:
 		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 9c8c232..3749193 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -937,9 +937,10 @@
 		}
 
 		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-		audit_log_format(ab, "audit updated rules specifying path=");
+		audit_log_format(ab, "op=updated rules specifying path=");
 		audit_log_untrustedstring(ab, owatch->path);
 		audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
+		audit_log_format(ab, " list=%d res=1", r->listnr);
 		audit_log_end(ab);
 
 		audit_remove_watch(owatch);
@@ -969,14 +970,14 @@
 			e = container_of(r, struct audit_entry, rule);
 
 			ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-			audit_log_format(ab, "audit implicitly removed rule path=");
+			audit_log_format(ab, "op=remove rule path=");
 			audit_log_untrustedstring(ab, w->path);
 			if (r->filterkey) {
 				audit_log_format(ab, " key=");
 				audit_log_untrustedstring(ab, r->filterkey);
 			} else
 				audit_log_format(ab, " key=(null)");
-			audit_log_format(ab, " list=%d", r->listnr);
+			audit_log_format(ab, " list=%d res=1", r->listnr);
 			audit_log_end(ab);
 
 			list_del(&r->rlist);
@@ -1410,7 +1411,7 @@
 			audit_log_format(ab, " subj=%s", ctx);
 		kfree(ctx);
 	}
-	audit_log_format(ab, " %s rule key=", action);
+	audit_log_format(ab, " op=%s rule key=", action);
 	if (rule->filterkey)
 		audit_log_untrustedstring(ab, rule->filterkey);
 	else
@@ -1601,8 +1602,8 @@
 
 int audit_filter_user(struct netlink_skb_parms *cb, int type)
 {
+	enum audit_state state = AUDIT_DISABLED;
 	struct audit_entry *e;
-	enum audit_state   state;
 	int ret = 1;
 
 	rcu_read_lock();
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 2988975..3599558 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -170,6 +170,11 @@
 	char			a[0];
 };
 
+struct audit_aux_data_fd_pair {
+	struct	audit_aux_data d;
+	int	fd[2];
+};
+
 struct audit_aux_data_path {
 	struct audit_aux_data	d;
 	struct dentry		*dentry;
@@ -961,6 +966,11 @@
 			audit_log_d_path(ab, "path=", axi->dentry, axi->mnt);
 			break; }
 
+		case AUDIT_FD_PAIR: {
+			struct audit_aux_data_fd_pair *axs = (void *)aux;
+			audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]);
+			break; }
+
 		}
 		audit_log_end(ab);
 	}
@@ -1815,6 +1825,36 @@
 }
 
 /**
+ * __audit_fd_pair - record audit data for pipe and socketpair
+ * @fd1: the first file descriptor
+ * @fd2: the second file descriptor
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_fd_pair(int fd1, int fd2)
+{
+	struct audit_context *context = current->audit_context;
+	struct audit_aux_data_fd_pair *ax;
+
+	if (likely(!context)) {
+		return 0;
+	}
+
+	ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+	if (!ax) {
+		return -ENOMEM;
+	}
+
+	ax->fd[0] = fd1;
+	ax->fd[1] = fd2;
+
+	ax->d.type = AUDIT_FD_PAIR;
+	ax->d.next = context->aux;
+	context->aux = (void *)ax;
+	return 0;
+}
+
+/**
  * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
  * @len: data length in user space
  * @a: data address in kernel space
diff --git a/kernel/capability.c b/kernel/capability.c
index edb845a..c8d3c77 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -92,15 +92,17 @@
  * cap_set_pg - set capabilities for all processes in a given process
  * group.  We call this holding task_capability_lock and tasklist_lock.
  */
-static inline int cap_set_pg(int pgrp, kernel_cap_t *effective,
+static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective,
 			      kernel_cap_t *inheritable,
 			      kernel_cap_t *permitted)
 {
 	struct task_struct *g, *target;
 	int ret = -EPERM;
 	int found = 0;
+	struct pid *pgrp;
 
-	do_each_task_pid(pgrp, PIDTYPE_PGID, g) {
+	pgrp = find_pid(pgrp_nr);
+	do_each_pid_task(pgrp, PIDTYPE_PGID, g) {
 		target = g;
 		while_each_thread(g, target) {
 			if (!security_capset_check(target, effective,
@@ -113,7 +115,7 @@
 			}
 			found = 1;
 		}
-	} while_each_task_pid(pgrp, PIDTYPE_PGID, g);
+	} while_each_pid_task(pgrp, PIDTYPE_PGID, g);
 
 	if (!found)
 	     ret = 0;
diff --git a/kernel/compat.c b/kernel/compat.c
index 6952dd0..cebb4c2 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -1016,3 +1016,69 @@
 	return sys_migrate_pages(pid, nr_bits + 1, old, new);
 }
 #endif
+
+struct compat_sysinfo {
+	s32 uptime;
+	u32 loads[3];
+	u32 totalram;
+	u32 freeram;
+	u32 sharedram;
+	u32 bufferram;
+	u32 totalswap;
+	u32 freeswap;
+	u16 procs;
+	u16 pad;
+	u32 totalhigh;
+	u32 freehigh;
+	u32 mem_unit;
+	char _f[20-2*sizeof(u32)-sizeof(int)];
+};
+
+asmlinkage long
+compat_sys_sysinfo(struct compat_sysinfo __user *info)
+{
+	struct sysinfo s;
+
+	do_sysinfo(&s);
+
+	/* Check to see if any memory value is too large for 32-bit and scale
+	 *  down if needed
+	 */
+	if ((s.totalram >> 32) || (s.totalswap >> 32)) {
+		int bitcount = 0;
+
+		while (s.mem_unit < PAGE_SIZE) {
+			s.mem_unit <<= 1;
+			bitcount++;
+		}
+
+		s.totalram >>= bitcount;
+		s.freeram >>= bitcount;
+		s.sharedram >>= bitcount;
+		s.bufferram >>= bitcount;
+		s.totalswap >>= bitcount;
+		s.freeswap >>= bitcount;
+		s.totalhigh >>= bitcount;
+		s.freehigh >>= bitcount;
+	}
+
+	if (!access_ok(VERIFY_WRITE, info, sizeof(struct compat_sysinfo)) ||
+	    __put_user (s.uptime, &info->uptime) ||
+	    __put_user (s.loads[0], &info->loads[0]) ||
+	    __put_user (s.loads[1], &info->loads[1]) ||
+	    __put_user (s.loads[2], &info->loads[2]) ||
+	    __put_user (s.totalram, &info->totalram) ||
+	    __put_user (s.freeram, &info->freeram) ||
+	    __put_user (s.sharedram, &info->sharedram) ||
+	    __put_user (s.bufferram, &info->bufferram) ||
+	    __put_user (s.totalswap, &info->totalswap) ||
+	    __put_user (s.freeswap, &info->freeswap) ||
+	    __put_user (s.procs, &info->procs) ||
+	    __put_user (s.totalhigh, &info->totalhigh) ||
+	    __put_user (s.freehigh, &info->freehigh) ||
+	    __put_user (s.mem_unit, &info->mem_unit))
+		return -EFAULT;
+
+	return 0;
+}
+
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 7406fe6..3d4206a 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -309,6 +309,8 @@
 	mutex_lock(&cpu_add_remove_lock);
 	cpu_hotplug_disabled = 0;
 	mutex_unlock(&cpu_add_remove_lock);
+	if (cpus_empty(frozen_cpus))
+		return;
 
 	printk("Enabling non-boot CPUs ...\n");
 	for_each_cpu_mask(cpu, frozen_cpus) {
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 6b05dc6..f382b0f 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1540,7 +1540,7 @@
 	.release = cpuset_file_release,
 };
 
-static struct inode_operations cpuset_dir_inode_operations = {
+static const struct inode_operations cpuset_dir_inode_operations = {
 	.lookup = simple_lookup,
 	.mkdir = cpuset_mkdir,
 	.rmdir = cpuset_rmdir,
@@ -2656,7 +2656,7 @@
 	return single_open(file, proc_cpuset_show, pid);
 }
 
-struct file_operations proc_cpuset_operations = {
+const struct file_operations proc_cpuset_operations = {
 	.open		= cpuset_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/kernel/exit.c b/kernel/exit.c
index fec12eb..f132349 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -185,21 +185,19 @@
  * This checks not only the pgrp, but falls back on the pid if no
  * satisfactory pgrp is found. I dunno - gdb doesn't work correctly
  * without this...
+ *
+ * The caller must hold rcu lock or the tasklist lock.
  */
-int session_of_pgrp(int pgrp)
+struct pid *session_of_pgrp(struct pid *pgrp)
 {
 	struct task_struct *p;
-	int sid = 0;
+	struct pid *sid = NULL;
 
-	read_lock(&tasklist_lock);
-
-	p = find_task_by_pid_type(PIDTYPE_PGID, pgrp);
+	p = pid_task(pgrp, PIDTYPE_PGID);
 	if (p == NULL)
-		p = find_task_by_pid(pgrp);
+		p = pid_task(pgrp, PIDTYPE_PID);
 	if (p != NULL)
-		sid = process_session(p);
-
-	read_unlock(&tasklist_lock);
+		sid = task_session(p);
 
 	return sid;
 }
@@ -212,53 +210,52 @@
  *
  * "I ask you, have you ever known what it is to be an orphan?"
  */
-static int will_become_orphaned_pgrp(int pgrp, struct task_struct *ignored_task)
+static int will_become_orphaned_pgrp(struct pid *pgrp, struct task_struct *ignored_task)
 {
 	struct task_struct *p;
 	int ret = 1;
 
-	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
+	do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 		if (p == ignored_task
 				|| p->exit_state
 				|| is_init(p->real_parent))
 			continue;
-		if (process_group(p->real_parent) != pgrp &&
-		    process_session(p->real_parent) == process_session(p)) {
+		if (task_pgrp(p->real_parent) != pgrp &&
+		    task_session(p->real_parent) == task_session(p)) {
 			ret = 0;
 			break;
 		}
-	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
+	} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 	return ret;	/* (sighing) "Often!" */
 }
 
-int is_orphaned_pgrp(int pgrp)
+int is_current_pgrp_orphaned(void)
 {
 	int retval;
 
 	read_lock(&tasklist_lock);
-	retval = will_become_orphaned_pgrp(pgrp, NULL);
+	retval = will_become_orphaned_pgrp(task_pgrp(current), NULL);
 	read_unlock(&tasklist_lock);
 
 	return retval;
 }
 
-static int has_stopped_jobs(int pgrp)
+static int has_stopped_jobs(struct pid *pgrp)
 {
 	int retval = 0;
 	struct task_struct *p;
 
-	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
+	do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 		if (p->state != TASK_STOPPED)
 			continue;
 		retval = 1;
 		break;
-	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
+	} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 	return retval;
 }
 
 /**
- * reparent_to_init - Reparent the calling kernel thread to the init task
- * of the pid space that the thread belongs to.
+ * reparent_to_init - Reparent the calling kernel thread to the init task of the pid space that the thread belongs to.
  *
  * If a kernel thread is launched as a result of a system call, or if
  * it ever exits, it should generally reparent itself to init so that
@@ -431,8 +428,10 @@
 		while (set) {
 			if (set & 1) {
 				struct file * file = xchg(&fdt->fd[i], NULL);
-				if (file)
+				if (file) {
 					filp_close(file, files);
+					cond_resched();
+				}
 			}
 			i++;
 			set >>= 1;
@@ -649,14 +648,14 @@
 	 * than we are, and it was the only connection
 	 * outside, so the child pgrp is now orphaned.
 	 */
-	if ((process_group(p) != process_group(father)) &&
-	    (process_session(p) == process_session(father))) {
-		int pgrp = process_group(p);
+	if ((task_pgrp(p) != task_pgrp(father)) &&
+	    (task_session(p) == task_session(father))) {
+		struct pid *pgrp = task_pgrp(p);
 
 		if (will_become_orphaned_pgrp(pgrp, NULL) &&
 		    has_stopped_jobs(pgrp)) {
-			__kill_pg_info(SIGHUP, SEND_SIG_PRIV, pgrp);
-			__kill_pg_info(SIGCONT, SEND_SIG_PRIV, pgrp);
+			__kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
+			__kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
 		}
 	}
 }
@@ -736,6 +735,7 @@
 	int state;
 	struct task_struct *t;
 	struct list_head ptrace_dead, *_p, *_n;
+	struct pid *pgrp;
 
 	if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
 	    && !thread_group_empty(tsk)) {
@@ -788,12 +788,13 @@
 	 
 	t = tsk->real_parent;
 	
-	if ((process_group(t) != process_group(tsk)) &&
-	    (process_session(t) == process_session(tsk)) &&
-	    will_become_orphaned_pgrp(process_group(tsk), tsk) &&
-	    has_stopped_jobs(process_group(tsk))) {
-		__kill_pg_info(SIGHUP, SEND_SIG_PRIV, process_group(tsk));
-		__kill_pg_info(SIGCONT, SEND_SIG_PRIV, process_group(tsk));
+	pgrp = task_pgrp(tsk);
+	if ((task_pgrp(t) != pgrp) &&
+	    (task_session(t) != task_session(tsk)) &&
+	    will_become_orphaned_pgrp(pgrp, tsk) &&
+	    has_stopped_jobs(pgrp)) {
+		__kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
+		__kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
 	}
 
 	/* Let father know we died 
diff --git a/kernel/fork.c b/kernel/fork.c
index d57118d..d154cc7 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -858,7 +858,7 @@
 	init_sigpending(&sig->shared_pending);
 	INIT_LIST_HEAD(&sig->posix_timers);
 
-	hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_REL);
+	hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	sig->it_real_incr.tv64 = 0;
 	sig->real_timer.function = it_real_fn;
 	sig->tsk = tsk;
@@ -869,7 +869,7 @@
 	sig->it_prof_incr = cputime_zero;
 
 	sig->leader = 0;	/* session leadership doesn't inherit */
-	sig->tty_old_pgrp = 0;
+	sig->tty_old_pgrp = NULL;
 
 	sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
 	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
@@ -1038,10 +1038,12 @@
 	p->utime = cputime_zero;
 	p->stime = cputime_zero;
  	p->sched_time = 0;
+#ifdef CONFIG_TASK_XACCT
 	p->rchar = 0;		/* I/O counter: bytes read */
 	p->wchar = 0;		/* I/O counter: bytes written */
 	p->syscr = 0;		/* I/O counter: read syscalls */
 	p->syscw = 0;		/* I/O counter: write syscalls */
+#endif
 	task_io_accounting_init(p);
 	acct_clear_integrals(p);
 
diff --git a/kernel/futex.c b/kernel/futex.c
index 5a737de..e749e7d 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1134,7 +1134,7 @@
 
 	if (sec != MAX_SCHEDULE_TIMEOUT) {
 		to = &timeout;
-		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
+		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 		hrtimer_init_sleeper(to, current);
 		to->timer.expires = ktime_set(sec, nsec);
 	}
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index d0ba190..476cb0c 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1,8 +1,9 @@
 /*
  *  linux/kernel/hrtimer.c
  *
- *  Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
- *  Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *  Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ *  Copyright(C) 2006-2007  Timesys Corp., Thomas Gleixner
  *
  *  High-resolution kernel timers
  *
@@ -31,12 +32,17 @@
  */
 
 #include <linux/cpu.h>
+#include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/percpu.h>
 #include <linux/hrtimer.h>
 #include <linux/notifier.h>
 #include <linux/syscalls.h>
+#include <linux/kallsyms.h>
 #include <linux/interrupt.h>
+#include <linux/tick.h>
+#include <linux/seq_file.h>
+#include <linux/err.h>
 
 #include <asm/uaccess.h>
 
@@ -45,7 +51,7 @@
  *
  * returns the time in ktime_t format
  */
-static ktime_t ktime_get(void)
+ktime_t ktime_get(void)
 {
 	struct timespec now;
 
@@ -59,7 +65,7 @@
  *
  * returns the time in ktime_t format
  */
-static ktime_t ktime_get_real(void)
+ktime_t ktime_get_real(void)
 {
 	struct timespec now;
 
@@ -79,21 +85,22 @@
  * This ensures that we capture erroneous accesses to these clock ids
  * rather than moving them into the range of valid clock id's.
  */
-
-#define MAX_HRTIMER_BASES 2
-
-static DEFINE_PER_CPU(struct hrtimer_base, hrtimer_bases[MAX_HRTIMER_BASES]) =
+DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
 {
+
+	.clock_base =
 	{
-		.index = CLOCK_REALTIME,
-		.get_time = &ktime_get_real,
-		.resolution = KTIME_REALTIME_RES,
-	},
-	{
-		.index = CLOCK_MONOTONIC,
-		.get_time = &ktime_get,
-		.resolution = KTIME_MONOTONIC_RES,
-	},
+		{
+			.index = CLOCK_REALTIME,
+			.get_time = &ktime_get_real,
+			.resolution = KTIME_LOW_RES,
+		},
+		{
+			.index = CLOCK_MONOTONIC,
+			.get_time = &ktime_get,
+			.resolution = KTIME_LOW_RES,
+		},
+	}
 };
 
 /**
@@ -102,7 +109,7 @@
  *
  * The function calculates the monotonic clock from the realtime
  * clock and the wall_to_monotonic offset and stores the result
- * in normalized timespec format in the variable pointed to by ts.
+ * in normalized timespec format in the variable pointed to by @ts.
  */
 void ktime_get_ts(struct timespec *ts)
 {
@@ -125,20 +132,35 @@
  * Get the coarse grained time at the softirq based on xtime and
  * wall_to_monotonic.
  */
-static void hrtimer_get_softirq_time(struct hrtimer_base *base)
+static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
 {
 	ktime_t xtim, tomono;
+	struct timespec xts;
 	unsigned long seq;
 
 	do {
 		seq = read_seqbegin(&xtime_lock);
-		xtim = timespec_to_ktime(xtime);
-		tomono = timespec_to_ktime(wall_to_monotonic);
-
+#ifdef CONFIG_NO_HZ
+		getnstimeofday(&xts);
+#else
+		xts = xtime;
+#endif
 	} while (read_seqretry(&xtime_lock, seq));
 
-	base[CLOCK_REALTIME].softirq_time = xtim;
-	base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono);
+	xtim = timespec_to_ktime(xts);
+	tomono = timespec_to_ktime(wall_to_monotonic);
+	base->clock_base[CLOCK_REALTIME].softirq_time = xtim;
+	base->clock_base[CLOCK_MONOTONIC].softirq_time =
+		ktime_add(xtim, tomono);
+}
+
+/*
+ * Helper function to check, whether the timer is running the callback
+ * function
+ */
+static inline int hrtimer_callback_running(struct hrtimer *timer)
+{
+	return timer->state & HRTIMER_STATE_CALLBACK;
 }
 
 /*
@@ -147,8 +169,6 @@
  */
 #ifdef CONFIG_SMP
 
-#define set_curr_timer(b, t)		do { (b)->curr_timer = (t); } while (0)
-
 /*
  * We are using hashed locking: holding per_cpu(hrtimer_bases)[n].lock
  * means that all timers which are tied to this base via timer->base are
@@ -161,19 +181,20 @@
  * possible to set timer->base = NULL and drop the lock: the timer remains
  * locked.
  */
-static struct hrtimer_base *lock_hrtimer_base(const struct hrtimer *timer,
-					      unsigned long *flags)
+static
+struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer,
+					     unsigned long *flags)
 {
-	struct hrtimer_base *base;
+	struct hrtimer_clock_base *base;
 
 	for (;;) {
 		base = timer->base;
 		if (likely(base != NULL)) {
-			spin_lock_irqsave(&base->lock, *flags);
+			spin_lock_irqsave(&base->cpu_base->lock, *flags);
 			if (likely(base == timer->base))
 				return base;
 			/* The timer has migrated to another CPU: */
-			spin_unlock_irqrestore(&base->lock, *flags);
+			spin_unlock_irqrestore(&base->cpu_base->lock, *flags);
 		}
 		cpu_relax();
 	}
@@ -182,12 +203,14 @@
 /*
  * Switch the timer base to the current CPU when possible.
  */
-static inline struct hrtimer_base *
-switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_base *base)
+static inline struct hrtimer_clock_base *
+switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base)
 {
-	struct hrtimer_base *new_base;
+	struct hrtimer_clock_base *new_base;
+	struct hrtimer_cpu_base *new_cpu_base;
 
-	new_base = &__get_cpu_var(hrtimer_bases)[base->index];
+	new_cpu_base = &__get_cpu_var(hrtimer_bases);
+	new_base = &new_cpu_base->clock_base[base->index];
 
 	if (base != new_base) {
 		/*
@@ -199,13 +222,13 @@
 		 * completed. There is no conflict as we hold the lock until
 		 * the timer is enqueued.
 		 */
-		if (unlikely(base->curr_timer == timer))
+		if (unlikely(hrtimer_callback_running(timer)))
 			return base;
 
 		/* See the comment in lock_timer_base() */
 		timer->base = NULL;
-		spin_unlock(&base->lock);
-		spin_lock(&new_base->lock);
+		spin_unlock(&base->cpu_base->lock);
+		spin_lock(&new_base->cpu_base->lock);
 		timer->base = new_base;
 	}
 	return new_base;
@@ -213,19 +236,17 @@
 
 #else /* CONFIG_SMP */
 
-#define set_curr_timer(b, t)		do { } while (0)
-
-static inline struct hrtimer_base *
+static inline struct hrtimer_clock_base *
 lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
 {
-	struct hrtimer_base *base = timer->base;
+	struct hrtimer_clock_base *base = timer->base;
 
-	spin_lock_irqsave(&base->lock, *flags);
+	spin_lock_irqsave(&base->cpu_base->lock, *flags);
 
 	return base;
 }
 
-#define switch_hrtimer_base(t, b)	(b)
+# define switch_hrtimer_base(t, b)	(b)
 
 #endif	/* !CONFIG_SMP */
 
@@ -256,15 +277,12 @@
 
 	return ktime_add(kt, tmp);
 }
-
-#else /* CONFIG_KTIME_SCALAR */
-
 # endif /* !CONFIG_KTIME_SCALAR */
 
 /*
  * Divide a ktime value by a nanosecond value
  */
-static unsigned long ktime_divns(const ktime_t kt, s64 div)
+unsigned long ktime_divns(const ktime_t kt, s64 div)
 {
 	u64 dclc, inc, dns;
 	int sft = 0;
@@ -281,18 +299,311 @@
 
 	return (unsigned long) dclc;
 }
-
-#else /* BITS_PER_LONG < 64 */
-# define ktime_divns(kt, div)		(unsigned long)((kt).tv64 / (div))
 #endif /* BITS_PER_LONG >= 64 */
 
+/* High resolution timer related functions */
+#ifdef CONFIG_HIGH_RES_TIMERS
+
+/*
+ * High resolution timer enabled ?
+ */
+static int hrtimer_hres_enabled __read_mostly  = 1;
+
+/*
+ * Enable / Disable high resolution mode
+ */
+static int __init setup_hrtimer_hres(char *str)
+{
+	if (!strcmp(str, "off"))
+		hrtimer_hres_enabled = 0;
+	else if (!strcmp(str, "on"))
+		hrtimer_hres_enabled = 1;
+	else
+		return 0;
+	return 1;
+}
+
+__setup("highres=", setup_hrtimer_hres);
+
+/*
+ * hrtimer_high_res_enabled - query, if the highres mode is enabled
+ */
+static inline int hrtimer_is_hres_enabled(void)
+{
+	return hrtimer_hres_enabled;
+}
+
+/*
+ * Is the high resolution mode active ?
+ */
+static inline int hrtimer_hres_active(void)
+{
+	return __get_cpu_var(hrtimer_bases).hres_active;
+}
+
+/*
+ * Reprogram the event source with checking both queues for the
+ * next event
+ * Called with interrupts disabled and base->lock held
+ */
+static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base)
+{
+	int i;
+	struct hrtimer_clock_base *base = cpu_base->clock_base;
+	ktime_t expires;
+
+	cpu_base->expires_next.tv64 = KTIME_MAX;
+
+	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
+		struct hrtimer *timer;
+
+		if (!base->first)
+			continue;
+		timer = rb_entry(base->first, struct hrtimer, node);
+		expires = ktime_sub(timer->expires, base->offset);
+		if (expires.tv64 < cpu_base->expires_next.tv64)
+			cpu_base->expires_next = expires;
+	}
+
+	if (cpu_base->expires_next.tv64 != KTIME_MAX)
+		tick_program_event(cpu_base->expires_next, 1);
+}
+
+/*
+ * Shared reprogramming for clock_realtime and clock_monotonic
+ *
+ * When a timer is enqueued and expires earlier than the already enqueued
+ * timers, we have to check, whether it expires earlier than the timer for
+ * which the clock event device was armed.
+ *
+ * Called with interrupts disabled and base->cpu_base.lock held
+ */
+static int hrtimer_reprogram(struct hrtimer *timer,
+			     struct hrtimer_clock_base *base)
+{
+	ktime_t *expires_next = &__get_cpu_var(hrtimer_bases).expires_next;
+	ktime_t expires = ktime_sub(timer->expires, base->offset);
+	int res;
+
+	/*
+	 * When the callback is running, we do not reprogram the clock event
+	 * device. The timer callback is either running on a different CPU or
+	 * the callback is executed in the hrtimer_interupt context. The
+	 * reprogramming is handled either by the softirq, which called the
+	 * callback or at the end of the hrtimer_interrupt.
+	 */
+	if (hrtimer_callback_running(timer))
+		return 0;
+
+	if (expires.tv64 >= expires_next->tv64)
+		return 0;
+
+	/*
+	 * Clockevents returns -ETIME, when the event was in the past.
+	 */
+	res = tick_program_event(expires, 0);
+	if (!IS_ERR_VALUE(res))
+		*expires_next = expires;
+	return res;
+}
+
+
+/*
+ * Retrigger next event is called after clock was set
+ *
+ * Called with interrupts disabled via on_each_cpu()
+ */
+static void retrigger_next_event(void *arg)
+{
+	struct hrtimer_cpu_base *base;
+	struct timespec realtime_offset;
+	unsigned long seq;
+
+	if (!hrtimer_hres_active())
+		return;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		set_normalized_timespec(&realtime_offset,
+					-wall_to_monotonic.tv_sec,
+					-wall_to_monotonic.tv_nsec);
+	} while (read_seqretry(&xtime_lock, seq));
+
+	base = &__get_cpu_var(hrtimer_bases);
+
+	/* Adjust CLOCK_REALTIME offset */
+	spin_lock(&base->lock);
+	base->clock_base[CLOCK_REALTIME].offset =
+		timespec_to_ktime(realtime_offset);
+
+	hrtimer_force_reprogram(base);
+	spin_unlock(&base->lock);
+}
+
+/*
+ * Clock realtime was set
+ *
+ * Change the offset of the realtime clock vs. the monotonic
+ * clock.
+ *
+ * We might have to reprogram the high resolution timer interrupt. On
+ * SMP we call the architecture specific code to retrigger _all_ high
+ * resolution timer interrupts. On UP we just disable interrupts and
+ * call the high resolution interrupt code.
+ */
+void clock_was_set(void)
+{
+	/* Retrigger the CPU local events everywhere */
+	on_each_cpu(retrigger_next_event, NULL, 0, 1);
+}
+
+/*
+ * Check, whether the timer is on the callback pending list
+ */
+static inline int hrtimer_cb_pending(const struct hrtimer *timer)
+{
+	return timer->state & HRTIMER_STATE_PENDING;
+}
+
+/*
+ * Remove a timer from the callback pending list
+ */
+static inline void hrtimer_remove_cb_pending(struct hrtimer *timer)
+{
+	list_del_init(&timer->cb_entry);
+}
+
+/*
+ * Initialize the high resolution related parts of cpu_base
+ */
+static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base)
+{
+	base->expires_next.tv64 = KTIME_MAX;
+	base->hres_active = 0;
+	INIT_LIST_HEAD(&base->cb_pending);
+}
+
+/*
+ * Initialize the high resolution related parts of a hrtimer
+ */
+static inline void hrtimer_init_timer_hres(struct hrtimer *timer)
+{
+	INIT_LIST_HEAD(&timer->cb_entry);
+}
+
+/*
+ * When High resolution timers are active, try to reprogram. Note, that in case
+ * the state has HRTIMER_STATE_CALLBACK set, no reprogramming and no expiry
+ * check happens. The timer gets enqueued into the rbtree. The reprogramming
+ * and expiry check is done in the hrtimer_interrupt or in the softirq.
+ */
+static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
+					    struct hrtimer_clock_base *base)
+{
+	if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) {
+
+		/* Timer is expired, act upon the callback mode */
+		switch(timer->cb_mode) {
+		case HRTIMER_CB_IRQSAFE_NO_RESTART:
+			/*
+			 * We can call the callback from here. No restart
+			 * happens, so no danger of recursion
+			 */
+			BUG_ON(timer->function(timer) != HRTIMER_NORESTART);
+			return 1;
+		case HRTIMER_CB_IRQSAFE_NO_SOFTIRQ:
+			/*
+			 * This is solely for the sched tick emulation with
+			 * dynamic tick support to ensure that we do not
+			 * restart the tick right on the edge and end up with
+			 * the tick timer in the softirq ! The calling site
+			 * takes care of this.
+			 */
+			return 1;
+		case HRTIMER_CB_IRQSAFE:
+		case HRTIMER_CB_SOFTIRQ:
+			/*
+			 * Move everything else into the softirq pending list !
+			 */
+			list_add_tail(&timer->cb_entry,
+				      &base->cpu_base->cb_pending);
+			timer->state = HRTIMER_STATE_PENDING;
+			raise_softirq(HRTIMER_SOFTIRQ);
+			return 1;
+		default:
+			BUG();
+		}
+	}
+	return 0;
+}
+
+/*
+ * Switch to high resolution mode
+ */
+static void hrtimer_switch_to_hres(void)
+{
+	struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases);
+	unsigned long flags;
+
+	if (base->hres_active)
+		return;
+
+	local_irq_save(flags);
+
+	if (tick_init_highres()) {
+		local_irq_restore(flags);
+		return;
+	}
+	base->hres_active = 1;
+	base->clock_base[CLOCK_REALTIME].resolution = KTIME_HIGH_RES;
+	base->clock_base[CLOCK_MONOTONIC].resolution = KTIME_HIGH_RES;
+
+	tick_setup_sched_timer();
+
+	/* "Retrigger" the interrupt to get things going */
+	retrigger_next_event(NULL);
+	local_irq_restore(flags);
+	printk(KERN_INFO "Switched to high resolution mode on CPU %d\n",
+	       smp_processor_id());
+}
+
+#else
+
+static inline int hrtimer_hres_active(void) { return 0; }
+static inline int hrtimer_is_hres_enabled(void) { return 0; }
+static inline void hrtimer_switch_to_hres(void) { }
+static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { }
+static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
+					    struct hrtimer_clock_base *base)
+{
+	return 0;
+}
+static inline int hrtimer_cb_pending(struct hrtimer *timer) { return 0; }
+static inline void hrtimer_remove_cb_pending(struct hrtimer *timer) { }
+static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { }
+static inline void hrtimer_init_timer_hres(struct hrtimer *timer) { }
+
+#endif /* CONFIG_HIGH_RES_TIMERS */
+
+#ifdef CONFIG_TIMER_STATS
+void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer, void *addr)
+{
+	if (timer->start_site)
+		return;
+
+	timer->start_site = addr;
+	memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
+	timer->start_pid = current->pid;
+}
+#endif
+
 /*
  * Counterpart to lock_timer_base above:
  */
 static inline
 void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
 {
-	spin_unlock_irqrestore(&timer->base->lock, *flags);
+	spin_unlock_irqrestore(&timer->base->cpu_base->lock, *flags);
 }
 
 /**
@@ -342,7 +653,8 @@
  * The timer is inserted in expiry order. Insertion into the
  * red black tree is O(log(n)). Must hold the base lock.
  */
-static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+static void enqueue_hrtimer(struct hrtimer *timer,
+			    struct hrtimer_clock_base *base, int reprogram)
 {
 	struct rb_node **link = &base->active.rb_node;
 	struct rb_node *parent = NULL;
@@ -368,39 +680,85 @@
 	 * Insert the timer to the rbtree and check whether it
 	 * replaces the first pending timer
 	 */
+	if (!base->first || timer->expires.tv64 <
+	    rb_entry(base->first, struct hrtimer, node)->expires.tv64) {
+		/*
+		 * Reprogram the clock event device. When the timer is already
+		 * expired hrtimer_enqueue_reprogram has either called the
+		 * callback or added it to the pending list and raised the
+		 * softirq.
+		 *
+		 * This is a NOP for !HIGHRES
+		 */
+		if (reprogram && hrtimer_enqueue_reprogram(timer, base))
+			return;
+
+		base->first = &timer->node;
+	}
+
 	rb_link_node(&timer->node, parent, link);
 	rb_insert_color(&timer->node, &base->active);
-
-	if (!base->first || timer->expires.tv64 <
-	    rb_entry(base->first, struct hrtimer, node)->expires.tv64)
-		base->first = &timer->node;
+	/*
+	 * HRTIMER_STATE_ENQUEUED is or'ed to the current state to preserve the
+	 * state of a possibly running callback.
+	 */
+	timer->state |= HRTIMER_STATE_ENQUEUED;
 }
 
 /*
  * __remove_hrtimer - internal function to remove a timer
  *
  * Caller must hold the base lock.
+ *
+ * High resolution timer mode reprograms the clock event device when the
+ * timer is the one which expires next. The caller can disable this by setting
+ * reprogram to zero. This is useful, when the context does a reprogramming
+ * anyway (e.g. timer interrupt)
  */
-static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+static void __remove_hrtimer(struct hrtimer *timer,
+			     struct hrtimer_clock_base *base,
+			     unsigned long newstate, int reprogram)
 {
-	/*
-	 * Remove the timer from the rbtree and replace the
-	 * first entry pointer if necessary.
-	 */
-	if (base->first == &timer->node)
-		base->first = rb_next(&timer->node);
-	rb_erase(&timer->node, &base->active);
-	rb_set_parent(&timer->node, &timer->node);
+	/* High res. callback list. NOP for !HIGHRES */
+	if (hrtimer_cb_pending(timer))
+		hrtimer_remove_cb_pending(timer);
+	else {
+		/*
+		 * Remove the timer from the rbtree and replace the
+		 * first entry pointer if necessary.
+		 */
+		if (base->first == &timer->node) {
+			base->first = rb_next(&timer->node);
+			/* Reprogram the clock event device. if enabled */
+			if (reprogram && hrtimer_hres_active())
+				hrtimer_force_reprogram(base->cpu_base);
+		}
+		rb_erase(&timer->node, &base->active);
+	}
+	timer->state = newstate;
 }
 
 /*
  * remove hrtimer, called with base lock held
  */
 static inline int
-remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
 {
-	if (hrtimer_active(timer)) {
-		__remove_hrtimer(timer, base);
+	if (hrtimer_is_queued(timer)) {
+		int reprogram;
+
+		/*
+		 * Remove the timer and force reprogramming when high
+		 * resolution mode is active and the timer is on the current
+		 * CPU. If we remove a timer on another CPU, reprogramming is
+		 * skipped. The interrupt event on this CPU is fired and
+		 * reprogramming happens in the interrupt handler. This is a
+		 * rare case and less expensive than a smp call.
+		 */
+		timer_stats_hrtimer_clear_start_info(timer);
+		reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
+		__remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
+				 reprogram);
 		return 1;
 	}
 	return 0;
@@ -419,7 +777,7 @@
 int
 hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
 {
-	struct hrtimer_base *base, *new_base;
+	struct hrtimer_clock_base *base, *new_base;
 	unsigned long flags;
 	int ret;
 
@@ -431,7 +789,7 @@
 	/* Switch the timer base, if necessary: */
 	new_base = switch_hrtimer_base(timer, base);
 
-	if (mode == HRTIMER_REL) {
+	if (mode == HRTIMER_MODE_REL) {
 		tim = ktime_add(tim, new_base->get_time());
 		/*
 		 * CONFIG_TIME_LOW_RES is a temporary way for architectures
@@ -446,7 +804,9 @@
 	}
 	timer->expires = tim;
 
-	enqueue_hrtimer(timer, new_base);
+	timer_stats_hrtimer_set_start_info(timer);
+
+	enqueue_hrtimer(timer, new_base, base == new_base);
 
 	unlock_hrtimer_base(timer, &flags);
 
@@ -466,13 +826,13 @@
  */
 int hrtimer_try_to_cancel(struct hrtimer *timer)
 {
-	struct hrtimer_base *base;
+	struct hrtimer_clock_base *base;
 	unsigned long flags;
 	int ret = -1;
 
 	base = lock_hrtimer_base(timer, &flags);
 
-	if (base->curr_timer != timer)
+	if (!hrtimer_callback_running(timer))
 		ret = remove_hrtimer(timer, base);
 
 	unlock_hrtimer_base(timer, &flags);
@@ -508,19 +868,19 @@
  */
 ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
 {
-	struct hrtimer_base *base;
+	struct hrtimer_clock_base *base;
 	unsigned long flags;
 	ktime_t rem;
 
 	base = lock_hrtimer_base(timer, &flags);
-	rem = ktime_sub(timer->expires, timer->base->get_time());
+	rem = ktime_sub(timer->expires, base->get_time());
 	unlock_hrtimer_base(timer, &flags);
 
 	return rem;
 }
 EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
 
-#ifdef CONFIG_NO_IDLE_HZ
+#if defined(CONFIG_NO_IDLE_HZ) || defined(CONFIG_NO_HZ)
 /**
  * hrtimer_get_next_event - get the time until next expiry event
  *
@@ -529,26 +889,31 @@
  */
 ktime_t hrtimer_get_next_event(void)
 {
-	struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
+	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+	struct hrtimer_clock_base *base = cpu_base->clock_base;
 	ktime_t delta, mindelta = { .tv64 = KTIME_MAX };
 	unsigned long flags;
 	int i;
 
-	for (i = 0; i < MAX_HRTIMER_BASES; i++, base++) {
-		struct hrtimer *timer;
+	spin_lock_irqsave(&cpu_base->lock, flags);
 
-		spin_lock_irqsave(&base->lock, flags);
-		if (!base->first) {
-			spin_unlock_irqrestore(&base->lock, flags);
-			continue;
+	if (!hrtimer_hres_active()) {
+		for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
+			struct hrtimer *timer;
+
+			if (!base->first)
+				continue;
+
+			timer = rb_entry(base->first, struct hrtimer, node);
+			delta.tv64 = timer->expires.tv64;
+			delta = ktime_sub(delta, base->get_time());
+			if (delta.tv64 < mindelta.tv64)
+				mindelta.tv64 = delta.tv64;
 		}
-		timer = rb_entry(base->first, struct hrtimer, node);
-		delta.tv64 = timer->expires.tv64;
-		spin_unlock_irqrestore(&base->lock, flags);
-		delta = ktime_sub(delta, base->get_time());
-		if (delta.tv64 < mindelta.tv64)
-			mindelta.tv64 = delta.tv64;
 	}
+
+	spin_unlock_irqrestore(&cpu_base->lock, flags);
+
 	if (mindelta.tv64 < 0)
 		mindelta.tv64 = 0;
 	return mindelta;
@@ -564,17 +929,23 @@
 void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
 		  enum hrtimer_mode mode)
 {
-	struct hrtimer_base *bases;
+	struct hrtimer_cpu_base *cpu_base;
 
 	memset(timer, 0, sizeof(struct hrtimer));
 
-	bases = __raw_get_cpu_var(hrtimer_bases);
+	cpu_base = &__raw_get_cpu_var(hrtimer_bases);
 
-	if (clock_id == CLOCK_REALTIME && mode != HRTIMER_ABS)
+	if (clock_id == CLOCK_REALTIME && mode != HRTIMER_MODE_ABS)
 		clock_id = CLOCK_MONOTONIC;
 
-	timer->base = &bases[clock_id];
-	rb_set_parent(&timer->node, &timer->node);
+	timer->base = &cpu_base->clock_base[clock_id];
+	hrtimer_init_timer_hres(timer);
+
+#ifdef CONFIG_TIMER_STATS
+	timer->start_site = NULL;
+	timer->start_pid = -1;
+	memset(timer->start_comm, 0, TASK_COMM_LEN);
+#endif
 }
 EXPORT_SYMBOL_GPL(hrtimer_init);
 
@@ -583,26 +954,164 @@
  * @which_clock: which clock to query
  * @tp:		 pointer to timespec variable to store the resolution
  *
- * Store the resolution of the clock selected by which_clock in the
- * variable pointed to by tp.
+ * Store the resolution of the clock selected by @which_clock in the
+ * variable pointed to by @tp.
  */
 int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
 {
-	struct hrtimer_base *bases;
+	struct hrtimer_cpu_base *cpu_base;
 
-	bases = __raw_get_cpu_var(hrtimer_bases);
-	*tp = ktime_to_timespec(bases[which_clock].resolution);
+	cpu_base = &__raw_get_cpu_var(hrtimer_bases);
+	*tp = ktime_to_timespec(cpu_base->clock_base[which_clock].resolution);
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(hrtimer_get_res);
 
+#ifdef CONFIG_HIGH_RES_TIMERS
+
+/*
+ * High resolution timer interrupt
+ * Called with interrupts disabled
+ */
+void hrtimer_interrupt(struct clock_event_device *dev)
+{
+	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+	struct hrtimer_clock_base *base;
+	ktime_t expires_next, now;
+	int i, raise = 0;
+
+	BUG_ON(!cpu_base->hres_active);
+	cpu_base->nr_events++;
+	dev->next_event.tv64 = KTIME_MAX;
+
+ retry:
+	now = ktime_get();
+
+	expires_next.tv64 = KTIME_MAX;
+
+	base = cpu_base->clock_base;
+
+	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
+		ktime_t basenow;
+		struct rb_node *node;
+
+		spin_lock(&cpu_base->lock);
+
+		basenow = ktime_add(now, base->offset);
+
+		while ((node = base->first)) {
+			struct hrtimer *timer;
+
+			timer = rb_entry(node, struct hrtimer, node);
+
+			if (basenow.tv64 < timer->expires.tv64) {
+				ktime_t expires;
+
+				expires = ktime_sub(timer->expires,
+						    base->offset);
+				if (expires.tv64 < expires_next.tv64)
+					expires_next = expires;
+				break;
+			}
+
+			/* Move softirq callbacks to the pending list */
+			if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
+				__remove_hrtimer(timer, base,
+						 HRTIMER_STATE_PENDING, 0);
+				list_add_tail(&timer->cb_entry,
+					      &base->cpu_base->cb_pending);
+				raise = 1;
+				continue;
+			}
+
+			__remove_hrtimer(timer, base,
+					 HRTIMER_STATE_CALLBACK, 0);
+			timer_stats_account_hrtimer(timer);
+
+			/*
+			 * Note: We clear the CALLBACK bit after
+			 * enqueue_hrtimer to avoid reprogramming of
+			 * the event hardware. This happens at the end
+			 * of this function anyway.
+			 */
+			if (timer->function(timer) != HRTIMER_NORESTART) {
+				BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
+				enqueue_hrtimer(timer, base, 0);
+			}
+			timer->state &= ~HRTIMER_STATE_CALLBACK;
+		}
+		spin_unlock(&cpu_base->lock);
+		base++;
+	}
+
+	cpu_base->expires_next = expires_next;
+
+	/* Reprogramming necessary ? */
+	if (expires_next.tv64 != KTIME_MAX) {
+		if (tick_program_event(expires_next, 0))
+			goto retry;
+	}
+
+	/* Raise softirq ? */
+	if (raise)
+		raise_softirq(HRTIMER_SOFTIRQ);
+}
+
+static void run_hrtimer_softirq(struct softirq_action *h)
+{
+	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+
+	spin_lock_irq(&cpu_base->lock);
+
+	while (!list_empty(&cpu_base->cb_pending)) {
+		enum hrtimer_restart (*fn)(struct hrtimer *);
+		struct hrtimer *timer;
+		int restart;
+
+		timer = list_entry(cpu_base->cb_pending.next,
+				   struct hrtimer, cb_entry);
+
+		timer_stats_account_hrtimer(timer);
+
+		fn = timer->function;
+		__remove_hrtimer(timer, timer->base, HRTIMER_STATE_CALLBACK, 0);
+		spin_unlock_irq(&cpu_base->lock);
+
+		restart = fn(timer);
+
+		spin_lock_irq(&cpu_base->lock);
+
+		timer->state &= ~HRTIMER_STATE_CALLBACK;
+		if (restart == HRTIMER_RESTART) {
+			BUG_ON(hrtimer_active(timer));
+			/*
+			 * Enqueue the timer, allow reprogramming of the event
+			 * device
+			 */
+			enqueue_hrtimer(timer, timer->base, 1);
+		} else if (hrtimer_active(timer)) {
+			/*
+			 * If the timer was rearmed on another CPU, reprogram
+			 * the event device.
+			 */
+			if (timer->base->first == &timer->node)
+				hrtimer_reprogram(timer, timer->base);
+		}
+	}
+	spin_unlock_irq(&cpu_base->lock);
+}
+
+#endif	/* CONFIG_HIGH_RES_TIMERS */
+
 /*
  * Expire the per base hrtimer-queue:
  */
-static inline void run_hrtimer_queue(struct hrtimer_base *base)
+static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
+				     int index)
 {
 	struct rb_node *node;
+	struct hrtimer_clock_base *base = &cpu_base->clock_base[index];
 
 	if (!base->first)
 		return;
@@ -610,53 +1119,72 @@
 	if (base->get_softirq_time)
 		base->softirq_time = base->get_softirq_time();
 
-	spin_lock_irq(&base->lock);
+	spin_lock_irq(&cpu_base->lock);
 
 	while ((node = base->first)) {
 		struct hrtimer *timer;
-		int (*fn)(struct hrtimer *);
+		enum hrtimer_restart (*fn)(struct hrtimer *);
 		int restart;
 
 		timer = rb_entry(node, struct hrtimer, node);
 		if (base->softirq_time.tv64 <= timer->expires.tv64)
 			break;
 
+		timer_stats_account_hrtimer(timer);
+
 		fn = timer->function;
-		set_curr_timer(base, timer);
-		__remove_hrtimer(timer, base);
-		spin_unlock_irq(&base->lock);
+		__remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
+		spin_unlock_irq(&cpu_base->lock);
 
 		restart = fn(timer);
 
-		spin_lock_irq(&base->lock);
+		spin_lock_irq(&cpu_base->lock);
 
+		timer->state &= ~HRTIMER_STATE_CALLBACK;
 		if (restart != HRTIMER_NORESTART) {
 			BUG_ON(hrtimer_active(timer));
-			enqueue_hrtimer(timer, base);
+			enqueue_hrtimer(timer, base, 0);
 		}
 	}
-	set_curr_timer(base, NULL);
-	spin_unlock_irq(&base->lock);
+	spin_unlock_irq(&cpu_base->lock);
 }
 
 /*
  * Called from timer softirq every jiffy, expire hrtimers:
+ *
+ * For HRT its the fall back code to run the softirq in the timer
+ * softirq context in case the hrtimer initialization failed or has
+ * not been done yet.
  */
 void hrtimer_run_queues(void)
 {
-	struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
+	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
 	int i;
 
-	hrtimer_get_softirq_time(base);
+	if (hrtimer_hres_active())
+		return;
 
-	for (i = 0; i < MAX_HRTIMER_BASES; i++)
-		run_hrtimer_queue(&base[i]);
+	/*
+	 * This _is_ ugly: We have to check in the softirq context,
+	 * whether we can switch to highres and / or nohz mode. The
+	 * clocksource switch happens in the timer interrupt with
+	 * xtime_lock held. Notification from there only sets the
+	 * check bit in the tick_oneshot code, otherwise we might
+	 * deadlock vs. xtime_lock.
+	 */
+	if (tick_check_oneshot_change(!hrtimer_is_hres_enabled()))
+		hrtimer_switch_to_hres();
+
+	hrtimer_get_softirq_time(cpu_base);
+
+	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
+		run_hrtimer_queue(cpu_base, i);
 }
 
 /*
  * Sleep related functions:
  */
-static int hrtimer_wakeup(struct hrtimer *timer)
+static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer)
 {
 	struct hrtimer_sleeper *t =
 		container_of(timer, struct hrtimer_sleeper, timer);
@@ -673,6 +1201,9 @@
 {
 	sl->timer.function = hrtimer_wakeup;
 	sl->task = task;
+#ifdef CONFIG_HIGH_RES_TIMERS
+	sl->timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_RESTART;
+#endif
 }
 
 static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
@@ -683,10 +1214,11 @@
 		set_current_state(TASK_INTERRUPTIBLE);
 		hrtimer_start(&t->timer, t->timer.expires, mode);
 
-		schedule();
+		if (likely(t->task))
+			schedule();
 
 		hrtimer_cancel(&t->timer);
-		mode = HRTIMER_ABS;
+		mode = HRTIMER_MODE_ABS;
 
 	} while (t->task && !signal_pending(current));
 
@@ -702,10 +1234,10 @@
 
 	restart->fn = do_no_restart_syscall;
 
-	hrtimer_init(&t.timer, restart->arg0, HRTIMER_ABS);
+	hrtimer_init(&t.timer, restart->arg0, HRTIMER_MODE_ABS);
 	t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2;
 
-	if (do_nanosleep(&t, HRTIMER_ABS))
+	if (do_nanosleep(&t, HRTIMER_MODE_ABS))
 		return 0;
 
 	rmtp = (struct timespec __user *) restart->arg1;
@@ -738,7 +1270,7 @@
 		return 0;
 
 	/* Absolute timers do not update the rmtp value and restart: */
-	if (mode == HRTIMER_ABS)
+	if (mode == HRTIMER_MODE_ABS)
 		return -ERESTARTNOHAND;
 
 	if (rmtp) {
@@ -771,7 +1303,7 @@
 	if (!timespec_valid(&tu))
 		return -EINVAL;
 
-	return hrtimer_nanosleep(&tu, rmtp, HRTIMER_REL, CLOCK_MONOTONIC);
+	return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 }
 
 /*
@@ -779,56 +1311,60 @@
  */
 static void __devinit init_hrtimers_cpu(int cpu)
 {
-	struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu);
+	struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
 	int i;
 
-	for (i = 0; i < MAX_HRTIMER_BASES; i++, base++) {
-		spin_lock_init(&base->lock);
-		lockdep_set_class(&base->lock, &base->lock_key);
-	}
+	spin_lock_init(&cpu_base->lock);
+	lockdep_set_class(&cpu_base->lock, &cpu_base->lock_key);
+
+	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
+		cpu_base->clock_base[i].cpu_base = cpu_base;
+
+	hrtimer_init_hres(cpu_base);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
 
-static void migrate_hrtimer_list(struct hrtimer_base *old_base,
-				struct hrtimer_base *new_base)
+static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
+				struct hrtimer_clock_base *new_base)
 {
 	struct hrtimer *timer;
 	struct rb_node *node;
 
 	while ((node = rb_first(&old_base->active))) {
 		timer = rb_entry(node, struct hrtimer, node);
-		__remove_hrtimer(timer, old_base);
+		BUG_ON(hrtimer_callback_running(timer));
+		__remove_hrtimer(timer, old_base, HRTIMER_STATE_INACTIVE, 0);
 		timer->base = new_base;
-		enqueue_hrtimer(timer, new_base);
+		/*
+		 * Enqueue the timer. Allow reprogramming of the event device
+		 */
+		enqueue_hrtimer(timer, new_base, 1);
 	}
 }
 
 static void migrate_hrtimers(int cpu)
 {
-	struct hrtimer_base *old_base, *new_base;
+	struct hrtimer_cpu_base *old_base, *new_base;
 	int i;
 
 	BUG_ON(cpu_online(cpu));
-	old_base = per_cpu(hrtimer_bases, cpu);
-	new_base = get_cpu_var(hrtimer_bases);
+	old_base = &per_cpu(hrtimer_bases, cpu);
+	new_base = &get_cpu_var(hrtimer_bases);
+
+	tick_cancel_sched_timer(cpu);
 
 	local_irq_disable();
 
-	for (i = 0; i < MAX_HRTIMER_BASES; i++) {
+	spin_lock(&new_base->lock);
+	spin_lock(&old_base->lock);
 
-		spin_lock(&new_base->lock);
-		spin_lock(&old_base->lock);
-
-		BUG_ON(old_base->curr_timer);
-
-		migrate_hrtimer_list(old_base, new_base);
-
-		spin_unlock(&old_base->lock);
-		spin_unlock(&new_base->lock);
-		old_base++;
-		new_base++;
+	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
+		migrate_hrtimer_list(&old_base->clock_base[i],
+				     &new_base->clock_base[i]);
 	}
+	spin_unlock(&old_base->lock);
+	spin_unlock(&new_base->lock);
 
 	local_irq_enable();
 	put_cpu_var(hrtimer_bases);
@@ -848,6 +1384,7 @@
 
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
+		clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &cpu);
 		migrate_hrtimers(cpu);
 		break;
 #endif
@@ -868,5 +1405,8 @@
 	hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
 			  (void *)(long)smp_processor_id());
 	register_cpu_notifier(&hrtimers_nb);
+#ifdef CONFIG_HIGH_RES_TIMERS
+	open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq, NULL);
+#endif
 }
 
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 1dab0ac..681c52d 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -1,5 +1,5 @@
 
-obj-y := handle.o manage.o spurious.o resend.o chip.o
+obj-y := handle.o manage.o spurious.o resend.o chip.o devres.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/chip.c b/kernel/irq/chip.c
index 475e8a7..0133f4f 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -168,7 +168,7 @@
 /**
  *	set_irq_data - set irq type data for an irq
  *	@irq:	Interrupt number
- *	@data:	Pointer to interrupt specific data
+ *	@entry:	Pointer to MSI descriptor data
  *
  *	Set the hardware irq controller data for an irq
  */
@@ -230,10 +230,6 @@
  */
 static void default_disable(unsigned int irq)
 {
-	struct irq_desc *desc = irq_desc + irq;
-
-	if (!(desc->status & IRQ_DELAYED_DISABLE))
-		desc->chip->mask(irq);
 }
 
 /*
@@ -298,13 +294,18 @@
 
 	if (unlikely(desc->status & IRQ_INPROGRESS))
 		goto out_unlock;
-	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
 	kstat_cpu(cpu).irqs[irq]++;
 
 	action = desc->action;
-	if (unlikely(!action || (desc->status & IRQ_DISABLED)))
+	if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
+		if (desc->chip->mask)
+			desc->chip->mask(irq);
+		desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+		desc->status |= IRQ_PENDING;
 		goto out_unlock;
+	}
 
+	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING | IRQ_PENDING);
 	desc->status |= IRQ_INPROGRESS;
 	spin_unlock(&desc->lock);
 
@@ -396,11 +397,13 @@
 
 	/*
 	 * If its disabled or no action available
-	 * keep it masked and get out of here
+	 * then mask it and get out of here:
 	 */
 	action = desc->action;
 	if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
 		desc->status |= IRQ_PENDING;
+		if (desc->chip->mask)
+			desc->chip->mask(irq);
 		goto out;
 	}
 
@@ -562,10 +565,8 @@
 
 	/* Uninstall? */
 	if (handle == handle_bad_irq) {
-		if (desc->chip != &no_irq_chip) {
-			desc->chip->mask(irq);
-			desc->chip->ack(irq);
-		}
+		if (desc->chip != &no_irq_chip)
+			mask_ack_irq(desc, irq);
 		desc->status |= IRQ_DISABLED;
 		desc->depth = 1;
 	}
diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c
new file mode 100644
index 0000000..85a430d
--- /dev/null
+++ b/kernel/irq/devres.c
@@ -0,0 +1,88 @@
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+/*
+ * Device resource management aware IRQ request/free implementation.
+ */
+struct irq_devres {
+	unsigned int irq;
+	void *dev_id;
+};
+
+static void devm_irq_release(struct device *dev, void *res)
+{
+	struct irq_devres *this = res;
+
+	free_irq(this->irq, this->dev_id);
+}
+
+static int devm_irq_match(struct device *dev, void *res, void *data)
+{
+	struct irq_devres *this = res, *match = data;
+
+	return this->irq == match->irq && this->dev_id == match->dev_id;
+}
+
+/**
+ *	devm_request_irq - allocate an interrupt line for a managed device
+ *	@dev: device to request interrupt for
+ *	@irq: Interrupt line to allocate
+ *	@handler: Function to be called when the IRQ occurs
+ *	@irqflags: Interrupt type flags
+ *	@devname: An ascii name for the claiming device
+ *	@dev_id: A cookie passed back to the handler function
+ *
+ *	Except for the extra @dev argument, this function takes the
+ *	same arguments and performs the same function as
+ *	request_irq().  IRQs requested with this function will be
+ *	automatically freed on driver detach.
+ *
+ *	If an IRQ allocated with this function needs to be freed
+ *	separately, dev_free_irq() must be used.
+ */
+int devm_request_irq(struct device *dev, unsigned int irq,
+		     irq_handler_t handler, unsigned long irqflags,
+		     const char *devname, void *dev_id)
+{
+	struct irq_devres *dr;
+	int rc;
+
+	dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
+			  GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	rc = request_irq(irq, handler, irqflags, devname, dev_id);
+	if (rc) {
+		kfree(dr);
+		return rc;
+	}
+
+	dr->irq = irq;
+	dr->dev_id = dev_id;
+	devres_add(dev, dr);
+
+	return 0;
+}
+EXPORT_SYMBOL(devm_request_irq);
+
+/**
+ *	devm_free_irq - free an interrupt
+ *	@dev: device to free interrupt for
+ *	@irq: Interrupt line to free
+ *	@dev_id: Device identity to free
+ *
+ *	Except for the extra @dev argument, this function takes the
+ *	same arguments and performs the same function as free_irq().
+ *	This function instead of free_irq() should be used to manually
+ *	free IRQs allocated with dev_request_irq().
+ */
+void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
+{
+	struct irq_devres match_data = { irq, dev_id };
+
+	free_irq(irq, dev_id);
+	WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match,
+			       &match_data));
+}
+EXPORT_SYMBOL(devm_free_irq);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 8b961ad..5597c15 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -38,6 +38,46 @@
 }
 EXPORT_SYMBOL(synchronize_irq);
 
+/**
+ *	irq_can_set_affinity - Check if the affinity of a given irq can be set
+ *	@irq:		Interrupt to check
+ *
+ */
+int irq_can_set_affinity(unsigned int irq)
+{
+	struct irq_desc *desc = irq_desc + irq;
+
+	if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip ||
+	    !desc->chip->set_affinity)
+		return 0;
+
+	return 1;
+}
+
+/**
+ *	irq_set_affinity - Set the irq affinity of a given irq
+ *	@irq:		Interrupt to set affinity
+ *	@cpumask:	cpumask
+ *
+ */
+int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
+{
+	struct irq_desc *desc = irq_desc + irq;
+
+	if (!desc->chip->set_affinity)
+		return -EINVAL;
+
+	set_balance_irq_affinity(irq, cpumask);
+
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+	set_pending_irq(irq, cpumask);
+#else
+	desc->affinity = cpumask;
+	desc->chip->set_affinity(irq, cpumask);
+#endif
+	return 0;
+}
+
 #endif
 
 /**
@@ -281,6 +321,10 @@
 	if (new->flags & IRQF_PERCPU)
 		desc->status |= IRQ_PER_CPU;
 #endif
+	/* Exclude IRQ from balancing */
+	if (new->flags & IRQF_NOBALANCING)
+		desc->status |= IRQ_NO_BALANCING;
+
 	if (!shared) {
 		irq_chip_set_defaults(desc->chip);
 
@@ -328,12 +372,14 @@
 	return 0;
 
 mismatch:
+#ifdef CONFIG_DEBUG_SHIRQ
 	if (!(new->flags & IRQF_PROBE_SHARED)) {
 		printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
 		if (old_name)
 			printk(KERN_ERR "current handler: %s\n", old_name);
 		dump_stack();
 	}
+#endif
 	spin_unlock_irqrestore(&desc->lock, flags);
 	return -EBUSY;
 }
@@ -357,6 +403,7 @@
 	struct irq_desc *desc;
 	struct irqaction **p;
 	unsigned long flags;
+	irqreturn_t (*handler)(int, void *) = NULL;
 
 	WARN_ON(in_interrupt());
 	if (irq >= NR_IRQS)
@@ -396,6 +443,8 @@
 
 			/* Make sure it's not being used on another CPU */
 			synchronize_irq(irq);
+			if (action->flags & IRQF_SHARED)
+				handler = action->handler;
 			kfree(action);
 			return;
 		}
@@ -403,6 +452,17 @@
 		spin_unlock_irqrestore(&desc->lock, flags);
 		return;
 	}
+#ifdef CONFIG_DEBUG_SHIRQ
+	if (handler) {
+		/*
+		 * It's a shared IRQ -- the driver ought to be prepared for it
+		 * to happen even now it's being freed, so let's make sure....
+		 * We do this after actually deregistering it, to make sure that
+		 * a 'real' IRQ doesn't run in parallel with our fake
+		 */
+		handler(irq, dev_id);
+	}
+#endif
 }
 EXPORT_SYMBOL(free_irq);
 
@@ -445,7 +505,7 @@
 	/*
 	 * Lockdep wants atomic interrupt handlers:
 	 */
-	irqflags |= SA_INTERRUPT;
+	irqflags |= IRQF_DISABLED;
 #endif
 	/*
 	 * Sanity-check: shared interrupts must pass in a real dev-ID,
@@ -475,6 +535,25 @@
 
 	select_smp_affinity(irq);
 
+#ifdef CONFIG_DEBUG_SHIRQ
+	if (irqflags & IRQF_SHARED) {
+		/*
+		 * It's a shared IRQ -- the driver ought to be prepared for it
+		 * to happen immediately, so let's make sure....
+		 * We do this before actually registering it, to make sure that
+		 * a 'real' IRQ doesn't run in parallel with our fake
+		 */
+		if (irqflags & IRQF_DISABLED) {
+			unsigned long flags;
+
+			local_irq_save(flags);
+			handler(irq, dev_id);
+			local_irq_restore(flags);
+		} else
+			handler(irq, dev_id);
+	}
+#endif
+
 	retval = setup_irq(irq, action);
 	if (retval)
 		kfree(action);
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 4baa3bb..77b7acc 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -65,12 +65,11 @@
 	if (likely(!(desc->status & IRQ_MOVE_PENDING)))
 		return;
 
-	if (likely(!(desc->status & IRQ_DISABLED)))
-		desc->chip->disable(irq);
+	if (unlikely(desc->status & IRQ_DISABLED))
+		return;
 
+	desc->chip->mask(irq);
 	move_masked_irq(irq);
-
-	if (likely(!(desc->status & IRQ_DISABLED)))
-		desc->chip->enable(irq);
+	desc->chip->unmask(irq);
 }
 
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 61f5c71..2db91eb 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -16,26 +16,6 @@
 
 #ifdef CONFIG_SMP
 
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
-{
-	set_balance_irq_affinity(irq, mask_val);
-
-	/*
-	 * Save these away for later use. Re-progam when the
-	 * interrupt is pending
-	 */
-	set_pending_irq(irq, mask_val);
-}
-#else
-void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
-{
-	set_balance_irq_affinity(irq, mask_val);
-	irq_desc[irq].affinity = mask_val;
-	irq_desc[irq].chip->set_affinity(irq, mask_val);
-}
-#endif
-
 static int irq_affinity_read_proc(char *page, char **start, off_t off,
 				  int count, int *eof, void *data)
 {
@@ -55,7 +35,7 @@
 	cpumask_t new_value, tmp;
 
 	if (!irq_desc[irq].chip->set_affinity || no_irq_affinity ||
-				CHECK_IRQ_PER_CPU(irq_desc[irq].status))
+	    irq_balancing_disabled(irq))
 		return -EIO;
 
 	err = cpumask_parse_user(buffer, count, new_value);
@@ -73,7 +53,7 @@
 		   code to set default SMP affinity. */
 		return select_smp_affinity(irq) ? -EINVAL : full_count;
 
-	proc_set_irq_affinity(irq, new_value);
+	irq_set_affinity(irq, new_value);
 
 	return full_count;
 }
@@ -136,7 +116,6 @@
 		entry = create_proc_entry("smp_affinity", 0600, irq_desc[irq].dir);
 
 		if (entry) {
-			entry->nlink = 1;
 			entry->data = (void *)(long)irq;
 			entry->read_proc = irq_affinity_read_proc;
 			entry->write_proc = irq_affinity_write_proc;
diff --git a/kernel/itimer.c b/kernel/itimer.c
index 204ed79..307c6a6 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -128,18 +128,13 @@
 /*
  * The timer is automagically restarted, when interval != 0
  */
-int it_real_fn(struct hrtimer *timer)
+enum hrtimer_restart it_real_fn(struct hrtimer *timer)
 {
 	struct signal_struct *sig =
 	    container_of(timer, struct signal_struct, real_timer);
 
 	send_group_sig_info(SIGALRM, SEND_SIG_PRIV, sig->tsk);
 
-	if (sig->it_real_incr.tv64 != 0) {
-		hrtimer_forward(timer, timer->base->softirq_time,
-				sig->it_real_incr);
-		return HRTIMER_RESTART;
-	}
 	return HRTIMER_NORESTART;
 }
 
@@ -231,11 +226,14 @@
 			spin_unlock_irq(&tsk->sighand->siglock);
 			goto again;
 		}
-		tsk->signal->it_real_incr =
-			timeval_to_ktime(value->it_interval);
 		expires = timeval_to_ktime(value->it_value);
-		if (expires.tv64 != 0)
-			hrtimer_start(timer, expires, HRTIMER_REL);
+		if (expires.tv64 != 0) {
+			tsk->signal->it_real_incr =
+				timeval_to_ktime(value->it_interval);
+			hrtimer_start(timer, expires, HRTIMER_MODE_REL);
+		} else
+			tsk->signal->it_real_incr.tv64 = 0;
+
 		spin_unlock_irq(&tsk->sighand->siglock);
 		break;
 	case ITIMER_VIRTUAL:
diff --git a/kernel/kfifo.c b/kernel/kfifo.c
index 5d1d9073..cee4191 100644
--- a/kernel/kfifo.c
+++ b/kernel/kfifo.c
@@ -32,8 +32,8 @@
  * @gfp_mask: get_free_pages mask, passed to kmalloc()
  * @lock: the lock to be used to protect the fifo buffer
  *
- * Do NOT pass the kfifo to kfifo_free() after use ! Simply free the
- * struct kfifo with kfree().
+ * Do NOT pass the kfifo to kfifo_free() after use! Simply free the
+ * &struct kfifo with kfree().
  */
 struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
 			 gfp_t gfp_mask, spinlock_t *lock)
@@ -108,7 +108,7 @@
  * @buffer: the data to be added.
  * @len: the length of the data to be added.
  *
- * This function copies at most 'len' bytes from the 'buffer' into
+ * This function copies at most @len bytes from the @buffer into
  * the FIFO depending on the free space, and returns the number of
  * bytes copied.
  *
@@ -155,8 +155,8 @@
  * @buffer: where the data must be copied.
  * @len: the size of the destination buffer.
  *
- * This function copies at most 'len' bytes from the FIFO into the
- * 'buffer' and returns the number of copied bytes.
+ * This function copies at most @len bytes from the FIFO into the
+ * @buffer and returns the number of copied bytes.
  *
  * Note that with only one concurrent reader and one concurrent
  * writer, you don't need extra locking to use these functions.
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 3a7379a..7962761 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -217,7 +217,10 @@
 			sub_info->retval = ret;
 	}
 
-	complete(sub_info->complete);
+	if (sub_info->wait < 0)
+		kfree(sub_info);
+	else
+		complete(sub_info->complete);
 	return 0;
 }
 
@@ -239,6 +242,9 @@
 		pid = kernel_thread(____call_usermodehelper, sub_info,
 				    CLONE_VFORK | SIGCHLD);
 
+	if (wait < 0)
+		return;
+
 	if (pid < 0) {
 		sub_info->retval = pid;
 		complete(sub_info->complete);
@@ -253,6 +259,9 @@
  * @envp: null-terminated environment list
  * @session_keyring: session keyring for process (NULL for an empty keyring)
  * @wait: wait for the application to finish and return status.
+ *        when -1 don't wait at all, but you get no useful error back when
+ *        the program couldn't be exec'ed. This makes it safe to call
+ *        from interrupt context.
  *
  * Runs a user-space application.  The application is started
  * asynchronously if wait is not set, and runs as a child of keventd.
@@ -265,17 +274,8 @@
 			     struct key *session_keyring, int wait)
 {
 	DECLARE_COMPLETION_ONSTACK(done);
-	struct subprocess_info sub_info = {
-		.work		= __WORK_INITIALIZER(sub_info.work,
-						     __call_usermodehelper),
-		.complete	= &done,
-		.path		= path,
-		.argv		= argv,
-		.envp		= envp,
-		.ring		= session_keyring,
-		.wait		= wait,
-		.retval		= 0,
-	};
+	struct subprocess_info *sub_info;
+	int retval;
 
 	if (!khelper_wq)
 		return -EBUSY;
@@ -283,9 +283,25 @@
 	if (path[0] == '\0')
 		return 0;
 
-	queue_work(khelper_wq, &sub_info.work);
+	sub_info = kzalloc(sizeof(struct subprocess_info),  GFP_ATOMIC);
+	if (!sub_info)
+		return -ENOMEM;
+
+	INIT_WORK(&sub_info->work, __call_usermodehelper);
+	sub_info->complete = &done;
+	sub_info->path = path;
+	sub_info->argv = argv;
+	sub_info->envp = envp;
+	sub_info->ring = session_keyring;
+	sub_info->wait = wait;
+
+	queue_work(khelper_wq, &sub_info->work);
+	if (wait < 0) /* task has freed sub_info */
+		return 0;
 	wait_for_completion(&done);
-	return sub_info.retval;
+	retval = sub_info->retval;
+	kfree(sub_info);
+	return retval;
 }
 EXPORT_SYMBOL(call_usermodehelper_keys);
 
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 6fcf8dd..d25a9ad 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -39,6 +39,8 @@
 #include <linux/moduleloader.h>
 #include <linux/kallsyms.h>
 #include <linux/freezer.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
 #include <asm-generic/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/errno.h>
@@ -778,6 +780,12 @@
 	return -ENOSYS;
 }
 
+static int __kprobes pre_handler_kretprobe(struct kprobe *p,
+					   struct pt_regs *regs)
+{
+	return 0;
+}
+
 #endif /* ARCH_SUPPORTS_KRETPROBES */
 
 void __kprobes unregister_kretprobe(struct kretprobe *rp)
@@ -815,7 +823,109 @@
 	return err;
 }
 
-__initcall(init_kprobes);
+#ifdef CONFIG_DEBUG_FS
+static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p,
+               const char *sym, int offset,char *modname)
+{
+	char *kprobe_type;
+
+	if (p->pre_handler == pre_handler_kretprobe)
+		kprobe_type = "r";
+	else if (p->pre_handler == setjmp_pre_handler)
+		kprobe_type = "j";
+	else
+		kprobe_type = "k";
+	if (sym)
+		seq_printf(pi, "%p  %s  %s+0x%x  %s\n", p->addr, kprobe_type,
+			sym, offset, (modname ? modname : " "));
+	else
+		seq_printf(pi, "%p  %s  %p\n", p->addr, kprobe_type, p->addr);
+}
+
+static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos)
+{
+	return (*pos < KPROBE_TABLE_SIZE) ? pos : NULL;
+}
+
+static void __kprobes *kprobe_seq_next(struct seq_file *f, void *v, loff_t *pos)
+{
+	(*pos)++;
+	if (*pos >= KPROBE_TABLE_SIZE)
+		return NULL;
+	return pos;
+}
+
+static void __kprobes kprobe_seq_stop(struct seq_file *f, void *v)
+{
+	/* Nothing to do */
+}
+
+static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct kprobe *p, *kp;
+	const char *sym = NULL;
+	unsigned int i = *(loff_t *) v;
+	unsigned long size, offset = 0;
+	char *modname, namebuf[128];
+
+	head = &kprobe_table[i];
+	preempt_disable();
+	hlist_for_each_entry_rcu(p, node, head, hlist) {
+		sym = kallsyms_lookup((unsigned long)p->addr, &size,
+					&offset, &modname, namebuf);
+		if (p->pre_handler == aggr_pre_handler) {
+			list_for_each_entry_rcu(kp, &p->list, list)
+				report_probe(pi, kp, sym, offset, modname);
+		} else
+			report_probe(pi, p, sym, offset, modname);
+	}
+	preempt_enable();
+	return 0;
+}
+
+static struct seq_operations kprobes_seq_ops = {
+	.start = kprobe_seq_start,
+	.next  = kprobe_seq_next,
+	.stop  = kprobe_seq_stop,
+	.show  = show_kprobe_addr
+};
+
+static int __kprobes kprobes_open(struct inode *inode, struct file *filp)
+{
+	return seq_open(filp, &kprobes_seq_ops);
+}
+
+static struct file_operations debugfs_kprobes_operations = {
+	.open           = kprobes_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = seq_release,
+};
+
+static int __kprobes debugfs_kprobe_init(void)
+{
+	struct dentry *dir, *file;
+
+	dir = debugfs_create_dir("kprobes", NULL);
+	if (!dir)
+		return -ENOMEM;
+
+	file = debugfs_create_file("list", 0444, dir , 0 ,
+				&debugfs_kprobes_operations);
+	if (!file) {
+		debugfs_remove(dir);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+late_initcall(debugfs_kprobe_init);
+#endif /* CONFIG_DEBUG_FS */
+
+module_init(init_kprobes);
 
 EXPORT_SYMBOL_GPL(register_kprobe);
 EXPORT_SYMBOL_GPL(unregister_kprobe);
@@ -824,4 +934,3 @@
 EXPORT_SYMBOL_GPL(jprobe_return);
 EXPORT_SYMBOL_GPL(register_kretprobe);
 EXPORT_SYMBOL_GPL(unregister_kretprobe);
-
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 1db8c72..87c50cc 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -50,7 +50,7 @@
 /**
  * kthread_should_stop - should this kthread return now?
  *
- * When someone calls kthread_stop on your kthread, it will be woken
+ * When someone calls kthread_stop() on your kthread, it will be woken
  * and this will return true.  You should then return, and your return
  * value will be passed through to kthread_stop().
  */
@@ -143,7 +143,7 @@
  * it.  See also kthread_run(), kthread_create_on_cpu().
  *
  * When woken, the thread will run @threadfn() with @data as its
- * argument. @threadfn can either call do_exit() directly if it is a
+ * argument. @threadfn() can either call do_exit() directly if it is a
  * standalone thread for which noone will call kthread_stop(), or
  * return when 'kthread_should_stop()' is true (which means
  * kthread_stop() has been called).  The return value should be zero
@@ -192,7 +192,7 @@
  *
  * Description: This function is equivalent to set_cpus_allowed(),
  * except that @cpu doesn't need to be online, and the thread must be
- * stopped (i.e., just returned from kthread_create().
+ * stopped (i.e., just returned from kthread_create()).
  */
 void kthread_bind(struct task_struct *k, unsigned int cpu)
 {
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 509efd4..a08a172 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -70,6 +70,9 @@
 
 static inline int graph_unlock(void)
 {
+	if (debug_locks && !__raw_spin_is_locked(&lockdep_lock))
+		return DEBUG_LOCKS_WARN_ON(1);
+
 	__raw_spin_unlock(&lockdep_lock);
 	return 0;
 }
@@ -487,7 +490,7 @@
  * Add a new dependency to the head of the list:
  */
 static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
-			    struct list_head *head, unsigned long ip)
+			    struct list_head *head, unsigned long ip, int distance)
 {
 	struct lock_list *entry;
 	/*
@@ -499,6 +502,7 @@
 		return 0;
 
 	entry->class = this;
+	entry->distance = distance;
 	if (!save_trace(&entry->trace))
 		return 0;
 
@@ -712,6 +716,9 @@
 	struct lock_list *entry;
 	int ret;
 
+	if (!__raw_spin_is_locked(&lockdep_lock))
+		return DEBUG_LOCKS_WARN_ON(1);
+
 	if (depth > max_recursion_depth)
 		max_recursion_depth = depth;
 	if (depth >= RECURSION_LIMIT)
@@ -900,7 +907,7 @@
  */
 static int
 check_prev_add(struct task_struct *curr, struct held_lock *prev,
-	       struct held_lock *next)
+	       struct held_lock *next, int distance)
 {
 	struct lock_list *entry;
 	int ret;
@@ -978,8 +985,11 @@
 	 *  L2 added to its dependency list, due to the first chain.)
 	 */
 	list_for_each_entry(entry, &prev->class->locks_after, entry) {
-		if (entry->class == next->class)
+		if (entry->class == next->class) {
+			if (distance == 1)
+				entry->distance = 1;
 			return 2;
+		}
 	}
 
 	/*
@@ -987,12 +997,13 @@
 	 * to the previous lock's dependency list:
 	 */
 	ret = add_lock_to_list(prev->class, next->class,
-			       &prev->class->locks_after, next->acquire_ip);
+			       &prev->class->locks_after, next->acquire_ip, distance);
+
 	if (!ret)
 		return 0;
 
 	ret = add_lock_to_list(next->class, prev->class,
-			       &next->class->locks_before, next->acquire_ip);
+			       &next->class->locks_before, next->acquire_ip, distance);
 	if (!ret)
 		return 0;
 
@@ -1040,13 +1051,14 @@
 		goto out_bug;
 
 	for (;;) {
+		int distance = curr->lockdep_depth - depth + 1;
 		hlock = curr->held_locks + depth-1;
 		/*
 		 * Only non-recursive-read entries get new dependencies
 		 * added:
 		 */
 		if (hlock->read != 2) {
-			if (!check_prev_add(curr, hlock, next))
+			if (!check_prev_add(curr, hlock, next, distance))
 				return 0;
 			/*
 			 * Stop after the first non-trylock entry,
@@ -1293,7 +1305,8 @@
 	if (!subclass || force)
 		lock->class_cache = class;
 
-	DEBUG_LOCKS_WARN_ON(class->subclass != subclass);
+	if (DEBUG_LOCKS_WARN_ON(class->subclass != subclass))
+		return NULL;
 
 	return class;
 }
@@ -1308,7 +1321,8 @@
 	struct list_head *hash_head = chainhashentry(chain_key);
 	struct lock_chain *chain;
 
-	DEBUG_LOCKS_WARN_ON(!irqs_disabled());
+	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
+		return 0;
 	/*
 	 * We can walk it lock-free, because entries only get added
 	 * to the hash:
@@ -1394,7 +1408,9 @@
 			return;
 		}
 		id = hlock->class - lock_classes;
-		DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS);
+		if (DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS))
+			return;
+
 		if (prev_hlock && (prev_hlock->irq_context !=
 							hlock->irq_context))
 			chain_key = 0;
@@ -2205,15 +2221,24 @@
 			if (!check_prevs_add(curr, hlock))
 				return 0;
 		graph_unlock();
-	}
+	} else
+		/* after lookup_chain_cache(): */
+		if (unlikely(!debug_locks))
+			return 0;
+
 	curr->lockdep_depth++;
 	check_chain_key(curr);
+#ifdef CONFIG_DEBUG_LOCKDEP
+	if (unlikely(!debug_locks))
+		return 0;
+#endif
 	if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) {
 		debug_locks_off();
 		printk("BUG: MAX_LOCK_DEPTH too low!\n");
 		printk("turning off the locking correctness validator.\n");
 		return 0;
 	}
+
 	if (unlikely(curr->lockdep_depth > max_lockdep_depth))
 		max_lockdep_depth = curr->lockdep_depth;
 
@@ -2764,4 +2789,3 @@
 }
 
 EXPORT_SYMBOL_GPL(debug_show_held_locks);
-
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
index b554b40..58f35e5 100644
--- a/kernel/lockdep_proc.c
+++ b/kernel/lockdep_proc.c
@@ -10,7 +10,6 @@
  * Code for /proc/lockdep and /proc/lockdep_stats:
  *
  */
-#include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -77,12 +76,29 @@
 	return ret;
 }
 
+static void print_name(struct seq_file *m, struct lock_class *class)
+{
+	char str[128];
+	const char *name = class->name;
+
+	if (!name) {
+		name = __get_key_name(class->key, str);
+		seq_printf(m, "%s", name);
+	} else{
+		seq_printf(m, "%s", name);
+		if (class->name_version > 1)
+			seq_printf(m, "#%d", class->name_version);
+		if (class->subclass)
+			seq_printf(m, "/%d", class->subclass);
+	}
+}
+
 static int l_show(struct seq_file *m, void *v)
 {
 	unsigned long nr_forward_deps, nr_backward_deps;
 	struct lock_class *class = m->private;
-	char str[128], c1, c2, c3, c4;
-	const char *name;
+	struct lock_list *entry;
+	char c1, c2, c3, c4;
 
 	seq_printf(m, "%p", class->key);
 #ifdef CONFIG_DEBUG_LOCKDEP
@@ -97,16 +113,16 @@
 	get_usage_chars(class, &c1, &c2, &c3, &c4);
 	seq_printf(m, " %c%c%c%c", c1, c2, c3, c4);
 
-	name = class->name;
-	if (!name) {
-		name = __get_key_name(class->key, str);
-		seq_printf(m, ": %s", name);
-	} else{
-		seq_printf(m, ": %s", name);
-		if (class->name_version > 1)
-			seq_printf(m, "#%d", class->name_version);
-		if (class->subclass)
-			seq_printf(m, "/%d", class->subclass);
+	seq_printf(m, ": ");
+	print_name(m, class);
+	seq_puts(m, "\n");
+
+	list_for_each_entry(entry, &class->locks_after, entry) {
+		if (entry->distance == 1) {
+			seq_printf(m, " -> [%p] ", entry->class);
+			print_name(m, entry->class);
+			seq_puts(m, "\n");
+		}
 	}
 	seq_puts(m, "\n");
 
@@ -227,7 +243,7 @@
 
 		sum_forward_deps += count_forward_deps(class);
 	}
-#ifdef CONFIG_LOCKDEP_DEBUG
+#ifdef CONFIG_DEBUG_LOCKDEP
 	DEBUG_LOCKS_WARN_ON(debug_atomic_read(&nr_unused_locks) != nr_unused);
 #endif
 	seq_printf(m, " lock-classes:                  %11lu [max: %lu]\n",
diff --git a/kernel/module.c b/kernel/module.c
index 8a94e05..f77e893 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1068,7 +1068,8 @@
 }
 #endif /* CONFIG_KALLSYMS */
 
-static int module_add_modinfo_attrs(struct module *mod)
+#ifdef CONFIG_SYSFS
+int module_add_modinfo_attrs(struct module *mod)
 {
 	struct module_attribute *attr;
 	struct module_attribute *temp_attr;
@@ -1094,7 +1095,7 @@
 	return error;
 }
 
-static void module_remove_modinfo_attrs(struct module *mod)
+void module_remove_modinfo_attrs(struct module *mod)
 {
 	struct module_attribute *attr;
 	int i;
@@ -1109,8 +1110,10 @@
 	}
 	kfree(mod->modinfo_attrs);
 }
+#endif
 
-static int mod_sysfs_init(struct module *mod)
+#ifdef CONFIG_SYSFS
+int mod_sysfs_init(struct module *mod)
 {
 	int err;
 
@@ -1133,7 +1136,7 @@
 	return err;
 }
 
-static int mod_sysfs_setup(struct module *mod,
+int mod_sysfs_setup(struct module *mod,
 			   struct kernel_param *kparam,
 			   unsigned int num_params)
 {
@@ -1169,16 +1172,14 @@
 out:
 	return err;
 }
+#endif
 
 static void mod_kobject_remove(struct module *mod)
 {
 	module_remove_modinfo_attrs(mod);
 	module_param_sysfs_remove(mod);
-	if (mod->mkobj.drivers_dir)
-		kobject_unregister(mod->mkobj.drivers_dir);
-	if (mod->holders_dir)
-		kobject_unregister(mod->holders_dir);
-
+	kobject_unregister(mod->mkobj.drivers_dir);
+	kobject_unregister(mod->holders_dir);
 	kobject_unregister(&mod->mkobj.kobj);
 }
 
@@ -2345,6 +2346,7 @@
 	printk("\n");
 }
 
+#ifdef CONFIG_SYSFS
 static char *make_driver_name(struct device_driver *drv)
 {
 	char *driver_name;
@@ -2417,8 +2419,15 @@
 			kfree(driver_name);
 		}
 	}
+	/*
+	 * Undo the additional reference we added in module_add_driver()
+	 * via kset_find_obj()
+	 */
+	if (drv->mod_name)
+		kobject_put(&drv->kobj);
 }
 EXPORT_SYMBOL(module_remove_driver);
+#endif
 
 #ifdef CONFIG_MODVERSIONS
 /* Generate the signature for struct module here, too, for modversions. */
diff --git a/kernel/mutex-debug.c b/kernel/mutex-debug.c
index 841539d..d17436c 100644
--- a/kernel/mutex-debug.c
+++ b/kernel/mutex-debug.c
@@ -13,7 +13,6 @@
  *  Released under the General Public License (GPL).
  */
 #include <linux/mutex.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/poison.h>
diff --git a/kernel/panic.c b/kernel/panic.c
index 525e365..623d182 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -150,6 +150,7 @@
  *  'R' - User forced a module unload.
  *  'M' - Machine had a machine check experience.
  *  'B' - System has hit bad_page.
+ *  'U' - Userspace-defined naughtiness.
  *
  *	The string is overwritten by the next call to print_taint().
  */
@@ -158,13 +159,14 @@
 {
 	static char buf[20];
 	if (tainted) {
-		snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c",
+		snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c",
 			tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
 			tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
 			tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
 			tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
  			tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
-			tainted & TAINT_BAD_PAGE ? 'B' : ' ');
+			tainted & TAINT_BAD_PAGE ? 'B' : ' ',
+			tainted & TAINT_USER ? 'U' : ' ');
 	}
 	else
 		snprintf(buf, sizeof(buf), "Not tainted");
diff --git a/kernel/params.c b/kernel/params.c
index 553cf7d..e265b13 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -30,8 +30,6 @@
 #define DEBUGP(fmt, a...)
 #endif
 
-static struct kobj_type module_ktype;
-
 static inline char dash2underscore(char c)
 {
 	if (c == '-')
@@ -391,6 +389,7 @@
 	struct param_attribute attrs[0];
 };
 
+#ifdef CONFIG_SYSFS
 #define to_param_attr(n) container_of(n, struct param_attribute, mattr);
 
 static ssize_t param_attr_show(struct module_attribute *mattr,
@@ -426,6 +425,7 @@
 		return len;
 	return err;
 }
+#endif
 
 #ifdef CONFIG_MODULES
 #define __modinit
@@ -433,6 +433,7 @@
 #define __modinit __init
 #endif
 
+#ifdef CONFIG_SYSFS
 /*
  * param_sysfs_setup - setup sysfs support for one module or KBUILD_MODNAME
  * @mk: struct module_kobject (contains parent kobject)
@@ -500,9 +501,7 @@
 	return mp;
 }
 
-
 #ifdef CONFIG_MODULES
-
 /*
  * module_param_sysfs_setup - setup sysfs support for one module
  * @mod: module
@@ -625,7 +624,6 @@
 
 
 /* module-related sysfs stuff */
-#ifdef CONFIG_SYSFS
 
 #define to_module_attr(n) container_of(n, struct module_attribute, attr);
 #define to_module_kobject(n) container_of(n, struct module_kobject, kobj);
@@ -673,6 +671,8 @@
 	.store = module_attr_store,
 };
 
+static struct kobj_type module_ktype;
+
 static int uevent_filter(struct kset *kset, struct kobject *kobj)
 {
 	struct kobj_type *ktype = get_ktype(kobj);
@@ -686,19 +686,12 @@
 	.filter = uevent_filter,
 };
 
-#else
-static struct sysfs_ops module_sysfs_ops = {
-	.show = NULL,
-	.store = NULL,
-};
-#endif
+decl_subsys(module, &module_ktype, &module_uevent_ops);
 
 static struct kobj_type module_ktype = {
 	.sysfs_ops =	&module_sysfs_ops,
 };
 
-decl_subsys(module, &module_ktype, &module_uevent_ops);
-
 /*
  * param_sysfs_init - wrapper for built-in params support
  */
@@ -719,6 +712,15 @@
 }
 subsys_initcall(param_sysfs_init);
 
+#else
+#if 0
+static struct sysfs_ops module_sysfs_ops = {
+	.show = NULL,
+	.store = NULL,
+};
+#endif
+#endif
+
 EXPORT_SYMBOL(param_set_byte);
 EXPORT_SYMBOL(param_get_byte);
 EXPORT_SYMBOL(param_set_short);
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 7c3e1e6..657f776 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -304,7 +304,7 @@
 		 * should be able to see it.
 		 */
 		struct task_struct *p;
-		read_lock(&tasklist_lock);
+		rcu_read_lock();
 		p = find_task_by_pid(pid);
 		if (p) {
 			if (CPUCLOCK_PERTHREAD(which_clock)) {
@@ -312,12 +312,17 @@
 					error = cpu_clock_sample(which_clock,
 								 p, &rtn);
 				}
-			} else if (p->tgid == pid && p->signal) {
-				error = cpu_clock_sample_group(which_clock,
-							       p, &rtn);
+			} else {
+				read_lock(&tasklist_lock);
+				if (p->tgid == pid && p->signal) {
+					error =
+					    cpu_clock_sample_group(which_clock,
+							           p, &rtn);
+				}
+				read_unlock(&tasklist_lock);
 			}
 		}
-		read_unlock(&tasklist_lock);
+		rcu_read_unlock();
 	}
 
 	if (error)
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 5fe87de..44318ca 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -145,7 +145,7 @@
 			    struct itimerspec *, struct itimerspec *);
 static int common_timer_del(struct k_itimer *timer);
 
-static int posix_timer_fn(struct hrtimer *data);
+static enum hrtimer_restart posix_timer_fn(struct hrtimer *data);
 
 static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
 
@@ -334,12 +334,12 @@
 
  * This code is for CLOCK_REALTIME* and CLOCK_MONOTONIC* timers.
  */
-static int posix_timer_fn(struct hrtimer *timer)
+static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
 {
 	struct k_itimer *timr;
 	unsigned long flags;
 	int si_private = 0;
-	int ret = HRTIMER_NORESTART;
+	enum hrtimer_restart ret = HRTIMER_NORESTART;
 
 	timr = container_of(timer, struct k_itimer, it.real.timer);
 	spin_lock_irqsave(&timr->it_lock, flags);
@@ -356,7 +356,7 @@
 		if (timr->it.real.interval.tv64 != 0) {
 			timr->it_overrun +=
 				hrtimer_forward(timer,
-						timer->base->softirq_time,
+						hrtimer_cb_get_time(timer),
 						timr->it.real.interval);
 			ret = HRTIMER_RESTART;
 			++timr->it_requeue_pending;
@@ -399,10 +399,9 @@
 static struct k_itimer * alloc_posix_timer(void)
 {
 	struct k_itimer *tmr;
-	tmr = kmem_cache_alloc(posix_timers_cache, GFP_KERNEL);
+	tmr = kmem_cache_zalloc(posix_timers_cache, GFP_KERNEL);
 	if (!tmr)
 		return tmr;
-	memset(tmr, 0, sizeof (struct k_itimer));
 	if (unlikely(!(tmr->sigq = sigqueue_alloc()))) {
 		kmem_cache_free(posix_timers_cache, tmr);
 		tmr = NULL;
@@ -723,7 +722,7 @@
 	if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec)
 		return 0;
 
-	mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
+	mode = flags & TIMER_ABSTIME ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL;
 	hrtimer_init(&timr->it.real.timer, timr->it_clock, mode);
 	timr->it.real.timer.function = posix_timer_fn;
 
@@ -735,7 +734,7 @@
 	/* SIGEV_NONE timers are not queued ! See common_timer_get */
 	if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
 		/* Setup correct expiry time for relative timers */
-		if (mode == HRTIMER_REL)
+		if (mode == HRTIMER_MODE_REL)
 			timer->expires = ktime_add(timer->expires,
 						   timer->base->get_time());
 		return 0;
@@ -951,7 +950,8 @@
 			 struct timespec *tsave, struct timespec __user *rmtp)
 {
 	return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
-				 HRTIMER_ABS : HRTIMER_REL, which_clock);
+				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
+				 which_clock);
 }
 
 asmlinkage long
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index ed29622..95f6657 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -131,3 +131,29 @@
 	bool
 	depends on HOTPLUG_CPU && X86 && PM
 	default y
+
+config APM_EMULATION
+	tristate "Advanced Power Management Emulation"
+	depends on PM && SYS_SUPPORTS_APM_EMULATION
+	help
+	  APM is a BIOS specification for saving power using several different
+	  techniques. This is mostly useful for battery powered laptops with
+	  APM compliant BIOSes. If you say Y here, the system time will be
+	  reset after a RESUME operation, the /proc/apm device will provide
+	  battery status information, and user-space programs will receive
+	  notification of APM "events" (e.g. battery status change).
+
+	  In order to use APM, you will need supporting software. For location
+	  and more information, read <file:Documentation/pm.txt> and the
+	  Battery Powered Linux mini-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  This driver does not spin down disk drives (see the hdparm(8)
+	  manpage ("man 8 hdparm") for that), and it doesn't turn off
+	  VESA-compliant "green" monitors.
+
+	  Generally, if you don't have a battery in your machine, there isn't
+	  much point in using this driver and you should say N. If you get
+	  random kernel OOPSes or reboots that don't seem to be related to
+	  anything, try disabling/enabling this option (or disabling/enabling
+	  APM in your BIOS).
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 88fc5d7..406b20a 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -87,52 +87,24 @@
 	}
 }
 
+static void unprepare_processes(void)
+{
+	thaw_processes();
+	pm_restore_console();
+}
+
 static int prepare_processes(void)
 {
 	int error = 0;
 
 	pm_prepare_console();
-
-	error = disable_nonboot_cpus();
-	if (error)
-		goto enable_cpus;
-
 	if (freeze_processes()) {
 		error = -EBUSY;
-		goto thaw;
+		unprepare_processes();
 	}
-
-	if (pm_disk_mode == PM_DISK_TESTPROC) {
-		printk("swsusp debug: Waiting for 5 seconds.\n");
-		mdelay(5000);
-		goto thaw;
-	}
-
-	error = platform_prepare();
-	if (error)
-		goto thaw;
-
-	/* Free memory before shutting down devices. */
-	if (!(error = swsusp_shrink_memory()))
-		return 0;
-
-	platform_finish();
- thaw:
-	thaw_processes();
- enable_cpus:
-	enable_nonboot_cpus();
-	pm_restore_console();
 	return error;
 }
 
-static void unprepare_processes(void)
-{
-	platform_finish();
-	thaw_processes();
-	enable_nonboot_cpus();
-	pm_restore_console();
-}
-
 /**
  *	pm_suspend_disk - The granpappy of hibernation power management.
  *
@@ -150,29 +122,45 @@
 	if (error)
 		return error;
 
-	if (pm_disk_mode == PM_DISK_TESTPROC)
-		return 0;
+	if (pm_disk_mode == PM_DISK_TESTPROC) {
+		printk("swsusp debug: Waiting for 5 seconds.\n");
+		mdelay(5000);
+		goto Thaw;
+	}
+	/* Free memory before shutting down devices. */
+	error = swsusp_shrink_memory();
+	if (error)
+		goto Thaw;
+
+	error = platform_prepare();
+	if (error)
+		goto Thaw;
 
 	suspend_console();
 	error = device_suspend(PMSG_FREEZE);
 	if (error) {
-		resume_console();
-		printk("Some devices failed to suspend\n");
-		goto Thaw;
+		printk(KERN_ERR "PM: Some devices failed to suspend\n");
+		goto Resume_devices;
 	}
+	error = disable_nonboot_cpus();
+	if (error)
+		goto Enable_cpus;
 
 	if (pm_disk_mode == PM_DISK_TEST) {
 		printk("swsusp debug: Waiting for 5 seconds.\n");
 		mdelay(5000);
-		goto Done;
+		goto Enable_cpus;
 	}
 
 	pr_debug("PM: snapshotting memory.\n");
 	in_suspend = 1;
-	if ((error = swsusp_suspend()))
-		goto Done;
+	error = swsusp_suspend();
+	if (error)
+		goto Enable_cpus;
 
 	if (in_suspend) {
+		enable_nonboot_cpus();
+		platform_finish();
 		device_resume();
 		resume_console();
 		pr_debug("PM: writing image.\n");
@@ -188,7 +176,10 @@
 	}
 
 	swsusp_free();
- Done:
+ Enable_cpus:
+	enable_nonboot_cpus();
+ Resume_devices:
+	platform_finish();
 	device_resume();
 	resume_console();
  Thaw:
@@ -237,19 +228,28 @@
 
 	pr_debug("PM: Checking swsusp image.\n");
 
-	if ((error = swsusp_check()))
+	error = swsusp_check();
+	if (error)
 		goto Done;
 
 	pr_debug("PM: Preparing processes for restore.\n");
 
-	if ((error = prepare_processes())) {
+	error = prepare_processes();
+	if (error) {
 		swsusp_close();
 		goto Done;
 	}
 
+	error = platform_prepare();
+	if (error) {
+		swsusp_free();
+		goto Thaw;
+	}
+
 	pr_debug("PM: Reading swsusp image.\n");
 
-	if ((error = swsusp_read())) {
+	error = swsusp_read();
+	if (error) {
 		swsusp_free();
 		goto Thaw;
 	}
@@ -257,21 +257,22 @@
 	pr_debug("PM: Preparing devices for restore.\n");
 
 	suspend_console();
-	if ((error = device_suspend(PMSG_PRETHAW))) {
-		resume_console();
-		printk("Some devices failed to suspend\n");
-		swsusp_free();
-		goto Thaw;
-	}
+	error = device_suspend(PMSG_PRETHAW);
+	if (error)
+		goto Free;
 
-	mb();
+	error = disable_nonboot_cpus();
+	if (!error)
+		swsusp_resume();
 
-	pr_debug("PM: Restoring saved image.\n");
-	swsusp_resume();
-	pr_debug("PM: Restore failed, recovering.n");
+	enable_nonboot_cpus();
+ Free:
+	swsusp_free();
+	platform_finish();
 	device_resume();
 	resume_console();
  Thaw:
+	printk(KERN_ERR "PM: Restore failed, recovering.\n");
 	unprepare_processes();
  Done:
 	/* For success case, the suspend path will release the lock */
diff --git a/kernel/power/main.c b/kernel/power/main.c
index ff3a618..a064dfd 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -20,6 +20,7 @@
 #include <linux/cpu.h>
 #include <linux/resume-trace.h>
 #include <linux/freezer.h>
+#include <linux/vmstat.h>
 
 #include "power.h"
 
@@ -43,6 +44,11 @@
 	mutex_unlock(&pm_mutex);
 }
 
+static inline void pm_finish(suspend_state_t state)
+{
+	if (pm_ops->finish)
+		pm_ops->finish(state);
+}
 
 /**
  *	suspend_prepare - Do prep work before entering low-power state.
@@ -63,16 +69,13 @@
 
 	pm_prepare_console();
 
-	error = disable_nonboot_cpus();
-	if (error)
-		goto Enable_cpu;
-
 	if (freeze_processes()) {
 		error = -EAGAIN;
 		goto Thaw;
 	}
 
-	if ((free_pages = nr_free_pages()) < FREE_PAGE_NUMBER) {
+	if ((free_pages = global_page_state(NR_FREE_PAGES))
+			< FREE_PAGE_NUMBER) {
 		pr_debug("PM: free some memory\n");
 		shrink_all_memory(FREE_PAGE_NUMBER - free_pages);
 		if (nr_free_pages() < FREE_PAGE_NUMBER) {
@@ -88,18 +91,22 @@
 	}
 
 	suspend_console();
-	if ((error = device_suspend(PMSG_SUSPEND))) {
+	error = device_suspend(PMSG_SUSPEND);
+	if (error) {
 		printk(KERN_ERR "Some devices failed to suspend\n");
-		goto Finish;
+		goto Resume_devices;
 	}
-	return 0;
- Finish:
-	if (pm_ops->finish)
-		pm_ops->finish(state);
+	error = disable_nonboot_cpus();
+	if (!error)
+		return 0;
+
+	enable_nonboot_cpus();
+ Resume_devices:
+	pm_finish(state);
+	device_resume();
+	resume_console();
  Thaw:
 	thaw_processes();
- Enable_cpu:
-	enable_nonboot_cpus();
 	pm_restore_console();
 	return error;
 }
@@ -134,12 +141,11 @@
 
 static void suspend_finish(suspend_state_t state)
 {
+	enable_nonboot_cpus();
+	pm_finish(state);
 	device_resume();
 	resume_console();
 	thaw_processes();
-	enable_nonboot_cpus();
-	if (pm_ops && pm_ops->finish)
-		pm_ops->finish(state);
 	pm_restore_console();
 }
 
@@ -161,7 +167,10 @@
 	if (state == PM_SUSPEND_DISK)
 		return 1;
 
-	if (pm_ops && pm_ops->valid && !pm_ops->valid(state))
+	/* all other states need lowlevel support and need to be
+	 * valid to the lowlevel implementation, no valid callback
+	 * implies that all are valid. */
+	if (!pm_ops || (pm_ops->valid && !pm_ops->valid(state)))
 		return 0;
 	return 1;
 }
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index c024606..fc53ad0 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -591,7 +591,7 @@
 
 	for_each_zone(zone)
 		if (populated_zone(zone) && is_highmem(zone))
-			cnt += zone->free_pages;
+			cnt += zone_page_state(zone, NR_FREE_PAGES);
 
 	return cnt;
 }
@@ -869,7 +869,7 @@
 	for_each_zone(zone) {
 		meta += snapshot_additional_pages(zone);
 		if (!is_highmem(zone))
-			free += zone->free_pages;
+			free += zone_page_state(zone, NR_FREE_PAGES);
 	}
 
 	nr_pages += count_pages_for_highmem(nr_highmem);
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 31aa039..7fb8343 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -230,9 +230,10 @@
 		for_each_zone (zone)
 			if (populated_zone(zone)) {
 				if (is_highmem(zone)) {
-					highmem_size -= zone->free_pages;
+					highmem_size -=
+					zone_page_state(zone, NR_FREE_PAGES);
 				} else {
-					tmp -= zone->free_pages;
+					tmp -= zone_page_state(zone, NR_FREE_PAGES);
 					tmp += zone->lowmem_reserve[ZONE_NORMAL];
 					tmp += snapshot_additional_pages(zone);
 				}
diff --git a/kernel/power/user.c b/kernel/power/user.c
index f7b7a78..dd09efe 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -37,6 +37,7 @@
 	int mode;
 	char frozen;
 	char ready;
+	char platform_suspend;
 } snapshot_state;
 
 static atomic_t device_available = ATOMIC_INIT(1);
@@ -66,6 +67,7 @@
 	data->bitmap = NULL;
 	data->frozen = 0;
 	data->ready = 0;
+	data->platform_suspend = 0;
 
 	return 0;
 }
@@ -122,6 +124,92 @@
 	return res;
 }
 
+static inline int platform_prepare(void)
+{
+	int error = 0;
+
+	if (pm_ops && pm_ops->prepare)
+		error = pm_ops->prepare(PM_SUSPEND_DISK);
+
+	return error;
+}
+
+static inline void platform_finish(void)
+{
+	if (pm_ops && pm_ops->finish)
+		pm_ops->finish(PM_SUSPEND_DISK);
+}
+
+static inline int snapshot_suspend(int platform_suspend)
+{
+	int error;
+
+	mutex_lock(&pm_mutex);
+	/* Free memory before shutting down devices. */
+	error = swsusp_shrink_memory();
+	if (error)
+		goto Finish;
+
+	if (platform_suspend) {
+		error = platform_prepare();
+		if (error)
+			goto Finish;
+	}
+	suspend_console();
+	error = device_suspend(PMSG_FREEZE);
+	if (error)
+		goto Resume_devices;
+
+	error = disable_nonboot_cpus();
+	if (!error) {
+		in_suspend = 1;
+		error = swsusp_suspend();
+	}
+	enable_nonboot_cpus();
+ Resume_devices:
+	if (platform_suspend)
+		platform_finish();
+
+	device_resume();
+	resume_console();
+ Finish:
+	mutex_unlock(&pm_mutex);
+	return error;
+}
+
+static inline int snapshot_restore(int platform_suspend)
+{
+	int error;
+
+	mutex_lock(&pm_mutex);
+	pm_prepare_console();
+	if (platform_suspend) {
+		error = platform_prepare();
+		if (error)
+			goto Finish;
+	}
+	suspend_console();
+	error = device_suspend(PMSG_PRETHAW);
+	if (error)
+		goto Resume_devices;
+
+	error = disable_nonboot_cpus();
+	if (!error)
+		error = swsusp_resume();
+
+	enable_nonboot_cpus();
+ Resume_devices:
+	if (platform_suspend)
+		platform_finish();
+
+	device_resume();
+	resume_console();
+ Finish:
+	pm_restore_console();
+	mutex_unlock(&pm_mutex);
+	return error;
+}
+
 static int snapshot_ioctl(struct inode *inode, struct file *filp,
                           unsigned int cmd, unsigned long arg)
 {
@@ -145,14 +233,9 @@
 		if (data->frozen)
 			break;
 		mutex_lock(&pm_mutex);
-		error = disable_nonboot_cpus();
-		if (!error) {
-			error = freeze_processes();
-			if (error) {
-				thaw_processes();
-				enable_nonboot_cpus();
-				error = -EBUSY;
-			}
+		if (freeze_processes()) {
+			thaw_processes();
+			error = -EBUSY;
 		}
 		mutex_unlock(&pm_mutex);
 		if (!error)
@@ -164,7 +247,6 @@
 			break;
 		mutex_lock(&pm_mutex);
 		thaw_processes();
-		enable_nonboot_cpus();
 		mutex_unlock(&pm_mutex);
 		data->frozen = 0;
 		break;
@@ -174,20 +256,7 @@
 			error = -EPERM;
 			break;
 		}
-		mutex_lock(&pm_mutex);
-		/* Free memory before shutting down devices. */
-		error = swsusp_shrink_memory();
-		if (!error) {
-			suspend_console();
-			error = device_suspend(PMSG_FREEZE);
-			if (!error) {
-				in_suspend = 1;
-				error = swsusp_suspend();
-				device_resume();
-			}
-			resume_console();
-		}
-		mutex_unlock(&pm_mutex);
+		error = snapshot_suspend(data->platform_suspend);
 		if (!error)
 			error = put_user(in_suspend, (unsigned int __user *)arg);
 		if (!error)
@@ -201,17 +270,7 @@
 			error = -EPERM;
 			break;
 		}
-		mutex_lock(&pm_mutex);
-		pm_prepare_console();
-		suspend_console();
-		error = device_suspend(PMSG_PRETHAW);
-		if (!error) {
-			error = swsusp_resume();
-			device_resume();
-		}
-		resume_console();
-		pm_restore_console();
-		mutex_unlock(&pm_mutex);
+		error = snapshot_restore(data->platform_suspend);
 		break;
 
 	case SNAPSHOT_FREE:
@@ -282,6 +341,11 @@
 		break;
 
 	case SNAPSHOT_S2RAM:
+		if (!pm_ops) {
+			error = -ENOSYS;
+			break;
+		}
+
 		if (!data->frozen) {
 			error = -EPERM;
 			break;
@@ -319,28 +383,35 @@
 		break;
 
 	case SNAPSHOT_PMOPS:
+		error = -EINVAL;
+
 		switch (arg) {
 
 		case PMOPS_PREPARE:
-			if (pm_ops->prepare) {
-				error = pm_ops->prepare(PM_SUSPEND_DISK);
+			if (pm_ops && pm_ops->enter) {
+				data->platform_suspend = 1;
+				error = 0;
+			} else {
+				error = -ENOSYS;
 			}
 			break;
 
 		case PMOPS_ENTER:
-			kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
-			error = pm_ops->enter(PM_SUSPEND_DISK);
+			if (data->platform_suspend) {
+				kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
+				error = pm_ops->enter(PM_SUSPEND_DISK);
+				error = 0;
+			}
 			break;
 
 		case PMOPS_FINISH:
-			if (pm_ops && pm_ops->finish) {
-				pm_ops->finish(PM_SUSPEND_DISK);
-			}
+			if (data->platform_suspend)
+				error = 0;
+
 			break;
 
 		default:
 			printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg);
-			error = -EINVAL;
 
 		}
 		break;
diff --git a/kernel/printk.c b/kernel/printk.c
index c770e1a..4b47e59 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -54,7 +54,7 @@
 };
 
 /*
- * Low lever drivers may need that to know if they can schedule in
+ * Low level drivers may need that to know if they can schedule in
  * their unblank() callback or not. So let's export it.
  */
 int oops_in_progress;
@@ -483,7 +483,7 @@
  * printk - print a kernel message
  * @fmt: format string
  *
- * This is printk.  It can be called from any context.  We want it to work.
+ * This is printk().  It can be called from any context.  We want it to work.
  *
  * We try to grab the console_sem.  If we succeed, it's easy - we log the output and
  * call the console drivers.  If we fail to get the semaphore we place the output
@@ -529,7 +529,7 @@
 		zap_locks();
 
 	/* This stops the holder of console_sem just where we want him */
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	lockdep_off();
 	spin_lock(&logbuf_lock);
 	printk_cpu = smp_processor_id();
@@ -618,7 +618,7 @@
 			up(&console_sem);
 		}
 		lockdep_on();
-		local_irq_restore(flags);
+		raw_local_irq_restore(flags);
 	} else {
 		/*
 		 * Someone else owns the drivers.  We drop the spinlock, which
@@ -628,7 +628,7 @@
 		printk_cpu = UINT_MAX;
 		spin_unlock(&logbuf_lock);
 		lockdep_on();
-		local_irq_restore(flags);
+		raw_local_irq_restore(flags);
 	}
 
 	preempt_enable();
@@ -783,6 +783,12 @@
 	return console_locked;
 }
 
+void wake_up_klogd(void)
+{
+	if (!oops_in_progress && waitqueue_active(&log_wait))
+		wake_up_interruptible(&log_wait);
+}
+
 /**
  * release_console_sem - unlock the console system
  *
@@ -825,8 +831,8 @@
 	console_locked = 0;
 	up(&console_sem);
 	spin_unlock_irqrestore(&logbuf_lock, flags);
-	if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait))
-		wake_up_interruptible(&log_wait);
+	if (wake_klogd)
+		wake_up_klogd();
 }
 EXPORT_SYMBOL(release_console_sem);
 
diff --git a/kernel/profile.c b/kernel/profile.c
index d6579d5..9bfadb2 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -449,7 +449,6 @@
 	/* create /proc/irq/prof_cpu_mask */
 	if (!(entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir)))
 		return;
-	entry->nlink = 1;
 	entry->data = (void *)&prof_cpu_mask;
 	entry->read_proc = prof_cpu_mask_read_proc;
 	entry->write_proc = prof_cpu_mask_write_proc;
diff --git a/kernel/relay.c b/kernel/relay.c
index 284e2e8..ef8a935 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -7,6 +7,8 @@
  * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
  *
  * Moved to kernel/relay.c by Paul Mundt, 2006.
+ * November 2006 - CPU hotplug support by Mathieu Desnoyers
+ * 	(mathieu.desnoyers@polymtl.ca)
  *
  * This file is released under the GPL.
  */
@@ -18,6 +20,11 @@
 #include <linux/relay.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
+#include <linux/cpu.h>
+
+/* list of open channels, for cpu hotplug */
+static DEFINE_MUTEX(relay_channels_mutex);
+static LIST_HEAD(relay_channels);
 
 /*
  * close() vm_op implementation for relay file mapping.
@@ -187,6 +194,7 @@
 			__free_page(buf->page_array[i]);
 		kfree(buf->page_array);
 	}
+	chan->buf[buf->cpu] = NULL;
 	kfree(buf->padding);
 	kfree(buf);
 	kref_put(&chan->kref, relay_destroy_channel);
@@ -320,7 +328,7 @@
  *	@buf: the channel buffer
  *	@init: 1 if this is a first-time initialization
  *
- *	See relay_reset for description of effect.
+ *	See relay_reset() for description of effect.
  */
 static void __relay_reset(struct rchan_buf *buf, unsigned int init)
 {
@@ -356,57 +364,75 @@
  *	and restarting the channel in its initial state.  The buffers
  *	are not freed, so any mappings are still in effect.
  *
- *	NOTE: Care should be taken that the channel isn't actually
+ *	NOTE. Care should be taken that the channel isn't actually
  *	being used by anything when this call is made.
  */
 void relay_reset(struct rchan *chan)
 {
 	unsigned int i;
-	struct rchan_buf *prev = NULL;
 
 	if (!chan)
 		return;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!chan->buf[i] || chan->buf[i] == prev)
-			break;
-		__relay_reset(chan->buf[i], 0);
-		prev = chan->buf[i];
+ 	if (chan->is_global && chan->buf[0]) {
+		__relay_reset(chan->buf[0], 0);
+		return;
 	}
+
+	mutex_lock(&relay_channels_mutex);
+	for_each_online_cpu(i)
+		if (chan->buf[i])
+			__relay_reset(chan->buf[i], 0);
+	mutex_unlock(&relay_channels_mutex);
 }
 EXPORT_SYMBOL_GPL(relay_reset);
 
 /*
  *	relay_open_buf - create a new relay channel buffer
  *
- *	Internal - used by relay_open().
+ *	used by relay_open() and CPU hotplug.
  */
-static struct rchan_buf *relay_open_buf(struct rchan *chan,
-					const char *filename,
-					struct dentry *parent,
-					int *is_global)
+static struct rchan_buf *relay_open_buf(struct rchan *chan, unsigned int cpu)
 {
-	struct rchan_buf *buf;
+ 	struct rchan_buf *buf = NULL;
 	struct dentry *dentry;
+ 	char *tmpname;
 
-	if (*is_global)
+ 	if (chan->is_global)
 		return chan->buf[0];
 
+	tmpname = kzalloc(NAME_MAX + 1, GFP_KERNEL);
+ 	if (!tmpname)
+ 		goto end;
+ 	snprintf(tmpname, NAME_MAX, "%s%d", chan->base_filename, cpu);
+
 	buf = relay_create_buf(chan);
 	if (!buf)
-		return NULL;
+ 		goto free_name;
+
+ 	buf->cpu = cpu;
+ 	__relay_reset(buf, 1);
 
 	/* Create file in fs */
-	dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR,
-					   buf, is_global);
-	if (!dentry) {
-		relay_destroy_buf(buf);
-		return NULL;
-	}
+ 	dentry = chan->cb->create_buf_file(tmpname, chan->parent, S_IRUSR,
+ 					   buf, &chan->is_global);
+ 	if (!dentry)
+ 		goto free_buf;
 
 	buf->dentry = dentry;
-	__relay_reset(buf, 1);
 
+ 	if(chan->is_global) {
+ 		chan->buf[0] = buf;
+ 		buf->cpu = 0;
+  	}
+
+ 	goto free_name;
+
+free_buf:
+ 	relay_destroy_buf(buf);
+free_name:
+ 	kfree(tmpname);
+end:
 	return buf;
 }
 
@@ -448,31 +474,71 @@
 }
 
 /**
+ *
+ * 	relay_hotcpu_callback - CPU hotplug callback
+ * 	@nb: notifier block
+ * 	@action: hotplug action to take
+ * 	@hcpu: CPU number
+ *
+ * 	Returns the success/failure of the operation. (NOTIFY_OK, NOTIFY_BAD)
+ */
+static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb,
+				unsigned long action,
+				void *hcpu)
+{
+	unsigned int hotcpu = (unsigned long)hcpu;
+	struct rchan *chan;
+
+	switch(action) {
+	case CPU_UP_PREPARE:
+		mutex_lock(&relay_channels_mutex);
+		list_for_each_entry(chan, &relay_channels, list) {
+			if (chan->buf[hotcpu])
+				continue;
+			chan->buf[hotcpu] = relay_open_buf(chan, hotcpu);
+			if(!chan->buf[hotcpu]) {
+				printk(KERN_ERR
+					"relay_hotcpu_callback: cpu %d buffer "
+					"creation failed\n", hotcpu);
+				mutex_unlock(&relay_channels_mutex);
+				return NOTIFY_BAD;
+			}
+		}
+		mutex_unlock(&relay_channels_mutex);
+		break;
+	case CPU_DEAD:
+		/* No need to flush the cpu : will be flushed upon
+		 * final relay_flush() call. */
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+/**
  *	relay_open - create a new relay channel
  *	@base_filename: base name of files to create
  *	@parent: dentry of parent directory, %NULL for root directory
  *	@subbuf_size: size of sub-buffers
  *	@n_subbufs: number of sub-buffers
  *	@cb: client callback functions
+ *	@private_data: user-defined data
  *
  *	Returns channel pointer if successful, %NULL otherwise.
  *
  *	Creates a channel buffer for each cpu using the sizes and
  *	attributes specified.  The created channel buffer files
  *	will be named base_filename0...base_filenameN-1.  File
- *	permissions will be S_IRUSR.
+ *	permissions will be %S_IRUSR.
  */
 struct rchan *relay_open(const char *base_filename,
 			 struct dentry *parent,
 			 size_t subbuf_size,
 			 size_t n_subbufs,
-			 struct rchan_callbacks *cb)
+			 struct rchan_callbacks *cb,
+			 void *private_data)
 {
 	unsigned int i;
 	struct rchan *chan;
-	char *tmpname;
-	int is_global = 0;
-
 	if (!base_filename)
 		return NULL;
 
@@ -487,38 +553,32 @@
 	chan->n_subbufs = n_subbufs;
 	chan->subbuf_size = subbuf_size;
 	chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs);
+	chan->parent = parent;
+	chan->private_data = private_data;
+	strlcpy(chan->base_filename, base_filename, NAME_MAX);
 	setup_callbacks(chan, cb);
 	kref_init(&chan->kref);
 
-	tmpname = kmalloc(NAME_MAX + 1, GFP_KERNEL);
-	if (!tmpname)
-		goto free_chan;
-
+	mutex_lock(&relay_channels_mutex);
 	for_each_online_cpu(i) {
-		sprintf(tmpname, "%s%d", base_filename, i);
-		chan->buf[i] = relay_open_buf(chan, tmpname, parent,
-					      &is_global);
+		chan->buf[i] = relay_open_buf(chan, i);
 		if (!chan->buf[i])
 			goto free_bufs;
-
-		chan->buf[i]->cpu = i;
 	}
+	list_add(&chan->list, &relay_channels);
+	mutex_unlock(&relay_channels_mutex);
 
-	kfree(tmpname);
 	return chan;
 
 free_bufs:
-	for (i = 0; i < NR_CPUS; i++) {
+	for_each_online_cpu(i) {
 		if (!chan->buf[i])
 			break;
 		relay_close_buf(chan->buf[i]);
-		if (is_global)
-			break;
 	}
-	kfree(tmpname);
 
-free_chan:
 	kref_put(&chan->kref, relay_destroy_channel);
+	mutex_unlock(&relay_channels_mutex);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(relay_open);
@@ -588,7 +648,7 @@
  *	subbufs_consumed should be the number of sub-buffers newly consumed,
  *	not the total consumed.
  *
- *	NOTE: Kernel clients don't need to call this function if the channel
+ *	NOTE. Kernel clients don't need to call this function if the channel
  *	mode is 'overwrite'.
  */
 void relay_subbufs_consumed(struct rchan *chan,
@@ -619,24 +679,26 @@
 void relay_close(struct rchan *chan)
 {
 	unsigned int i;
-	struct rchan_buf *prev = NULL;
 
 	if (!chan)
 		return;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!chan->buf[i] || chan->buf[i] == prev)
-			break;
-		relay_close_buf(chan->buf[i]);
-		prev = chan->buf[i];
-	}
+	mutex_lock(&relay_channels_mutex);
+	if (chan->is_global && chan->buf[0])
+		relay_close_buf(chan->buf[0]);
+	else
+		for_each_possible_cpu(i)
+			if (chan->buf[i])
+				relay_close_buf(chan->buf[i]);
 
 	if (chan->last_toobig)
 		printk(KERN_WARNING "relay: one or more items not logged "
 		       "[item size (%Zd) > sub-buffer size (%Zd)]\n",
 		       chan->last_toobig, chan->subbuf_size);
 
+	list_del(&chan->list);
 	kref_put(&chan->kref, relay_destroy_channel);
+	mutex_unlock(&relay_channels_mutex);
 }
 EXPORT_SYMBOL_GPL(relay_close);
 
@@ -649,17 +711,20 @@
 void relay_flush(struct rchan *chan)
 {
 	unsigned int i;
-	struct rchan_buf *prev = NULL;
 
 	if (!chan)
 		return;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!chan->buf[i] || chan->buf[i] == prev)
-			break;
-		relay_switch_subbuf(chan->buf[i], 0);
-		prev = chan->buf[i];
+	if (chan->is_global && chan->buf[0]) {
+		relay_switch_subbuf(chan->buf[0], 0);
+		return;
 	}
+
+	mutex_lock(&relay_channels_mutex);
+	for_each_possible_cpu(i)
+		if (chan->buf[i])
+			relay_switch_subbuf(chan->buf[i], 0);
+	mutex_unlock(&relay_channels_mutex);
 }
 EXPORT_SYMBOL_GPL(relay_flush);
 
@@ -684,7 +749,7 @@
  *	@filp: the file
  *	@vma: the vma describing what to map
  *
- *	Calls upon relay_mmap_buf to map the file into user space.
+ *	Calls upon relay_mmap_buf() to map the file into user space.
  */
 static int relay_file_mmap(struct file *filp, struct vm_area_struct *vma)
 {
@@ -826,7 +891,7 @@
  *	@read_pos: file read position
  *	@buf: relay channel buffer
  *
- *	If the read_pos is in the middle of padding, return the
+ *	If the @read_pos is in the middle of padding, return the
  *	position of the first actually available byte, otherwise
  *	return the original value.
  */
@@ -1022,3 +1087,12 @@
 	.sendfile       = relay_file_sendfile,
 };
 EXPORT_SYMBOL_GPL(relay_file_operations);
+
+static __init int relay_init(void)
+{
+
+	hotcpu_notifier(relay_hotcpu_callback, 0);
+	return 0;
+}
+
+module_init(relay_init);
diff --git a/kernel/resource.c b/kernel/resource.c
index 7b9a497..bdb55a3 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -8,7 +8,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
@@ -17,6 +16,7 @@
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/device.h>
 #include <asm/io.h>
 
 
@@ -618,6 +618,67 @@
 EXPORT_SYMBOL(__release_region);
 
 /*
+ * Managed region resource
+ */
+struct region_devres {
+	struct resource *parent;
+	resource_size_t start;
+	resource_size_t n;
+};
+
+static void devm_region_release(struct device *dev, void *res)
+{
+	struct region_devres *this = res;
+
+	__release_region(this->parent, this->start, this->n);
+}
+
+static int devm_region_match(struct device *dev, void *res, void *match_data)
+{
+	struct region_devres *this = res, *match = match_data;
+
+	return this->parent == match->parent &&
+		this->start == match->start && this->n == match->n;
+}
+
+struct resource * __devm_request_region(struct device *dev,
+				struct resource *parent, resource_size_t start,
+				resource_size_t n, const char *name)
+{
+	struct region_devres *dr = NULL;
+	struct resource *res;
+
+	dr = devres_alloc(devm_region_release, sizeof(struct region_devres),
+			  GFP_KERNEL);
+	if (!dr)
+		return NULL;
+
+	dr->parent = parent;
+	dr->start = start;
+	dr->n = n;
+
+	res = __request_region(parent, start, n, name);
+	if (res)
+		devres_add(dev, dr);
+	else
+		devres_free(dr);
+
+	return res;
+}
+EXPORT_SYMBOL(__devm_request_region);
+
+void __devm_release_region(struct device *dev, struct resource *parent,
+			   resource_size_t start, resource_size_t n)
+{
+	struct region_devres match_data = { parent, start, n };
+
+	__release_region(parent, start, n);
+	WARN_ON(devres_destroy(dev, devm_region_release, devm_region_match,
+			       &match_data));
+}
+EXPORT_SYMBOL(__devm_release_region);
+
+/*
  * Called from init/main.c to reserve IO ports.
  */
 #define MAXRESERVE 4
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 4ab17da..180978c 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -625,7 +625,7 @@
 	/* Setup the timer, when timeout != NULL */
 	if (unlikely(timeout))
 		hrtimer_start(&timeout->timer, timeout->timer.expires,
-			      HRTIMER_ABS);
+			      HRTIMER_MODE_ABS);
 
 	for (;;) {
 		/* Try to acquire the lock: */
diff --git a/kernel/sched.c b/kernel/sched.c
index cca93cc..0dc7572 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -57,6 +57,16 @@
 #include <asm/unistd.h>
 
 /*
+ * Scheduler clock - returns current time in nanosec units.
+ * This is default implementation.
+ * Architectures and sub-architectures can override this.
+ */
+unsigned long long __attribute__((weak)) sched_clock(void)
+{
+	return (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
+/*
  * Convert user-nice values [ -20 ... 0 ... 19 ]
  * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
  * and back.
@@ -1843,6 +1853,13 @@
 	struct mm_struct *mm = next->mm;
 	struct mm_struct *oldmm = prev->active_mm;
 
+	/*
+	 * For paravirt, this is coupled with an exit in switch_to to
+	 * combine the page table reload and the switch backend into
+	 * one hypercall.
+	 */
+	arch_enter_lazy_cpu_mode();
+
 	if (!mm) {
 		next->active_mm = oldmm;
 		atomic_inc(&oldmm->mm_count);
@@ -2887,14 +2904,16 @@
 static void update_load(struct rq *this_rq)
 {
 	unsigned long this_load;
-	int i, scale;
+	unsigned int i, scale;
 
 	this_load = this_rq->raw_weighted_load;
 
 	/* Update our load: */
-	for (i = 0, scale = 1; i < 3; i++, scale <<= 1) {
+	for (i = 0, scale = 1; i < 3; i++, scale += scale) {
 		unsigned long old_load, new_load;
 
+		/* scale is effectively 1 << i now, and >> i divides by scale */
+
 		old_load = this_rq->cpu_load[i];
 		new_load = this_load;
 		/*
@@ -2904,7 +2923,7 @@
 		 */
 		if (new_load > old_load)
 			new_load += scale-1;
-		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) / scale;
+		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
 	}
 }
 
@@ -4193,13 +4212,12 @@
 }
 
 /**
- * sched_setscheduler - change the scheduling policy and/or RT priority of
- * a thread.
+ * sched_setscheduler - change the scheduling policy and/or RT priority of a thread.
  * @p: the task in question.
  * @policy: new policy.
  * @param: structure containing the new RT priority.
  *
- * NOTE: the task may be already dead
+ * NOTE that the task may be already dead.
  */
 int sched_setscheduler(struct task_struct *p, int policy,
 		       struct sched_param *param)
@@ -4567,7 +4585,7 @@
 /**
  * sys_sched_yield - yield the current processor to other threads.
  *
- * this function yields the current CPU by moving the calling thread
+ * This function yields the current CPU by moving the calling thread
  * to the expired array. If there are no other threads running on this
  * CPU then this function will return.
  */
@@ -4694,7 +4712,7 @@
 /**
  * yield - yield the current processor to other threads.
  *
- * this is a shortcut for kernel-space yielding - it marks the
+ * This is a shortcut for kernel-space yielding - it marks the
  * thread runnable and calls sys_sched_yield().
  */
 void __sched yield(void)
diff --git a/kernel/signal.c b/kernel/signal.c
index 5630255..e2a7d4b 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -456,26 +456,50 @@
 int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
 {
 	int signr = __dequeue_signal(&tsk->pending, mask, info);
-	if (!signr)
+	if (!signr) {
 		signr = __dequeue_signal(&tsk->signal->shared_pending,
 					 mask, info);
+		/*
+		 * itimer signal ?
+		 *
+		 * itimers are process shared and we restart periodic
+		 * itimers in the signal delivery path to prevent DoS
+		 * attacks in the high resolution timer case. This is
+		 * compliant with the old way of self restarting
+		 * itimers, as the SIGALRM is a legacy signal and only
+		 * queued once. Changing the restart behaviour to
+		 * restart the timer in the signal dequeue path is
+		 * reducing the timer noise on heavy loaded !highres
+		 * systems too.
+		 */
+		if (unlikely(signr == SIGALRM)) {
+			struct hrtimer *tmr = &tsk->signal->real_timer;
+
+			if (!hrtimer_is_queued(tmr) &&
+			    tsk->signal->it_real_incr.tv64 != 0) {
+				hrtimer_forward(tmr, tmr->base->get_time(),
+						tsk->signal->it_real_incr);
+				hrtimer_restart(tmr);
+			}
+		}
+	}
 	recalc_sigpending_tsk(tsk);
- 	if (signr && unlikely(sig_kernel_stop(signr))) {
- 		/*
- 		 * Set a marker that we have dequeued a stop signal.  Our
- 		 * caller might release the siglock and then the pending
- 		 * stop signal it is about to process is no longer in the
- 		 * pending bitmasks, but must still be cleared by a SIGCONT
- 		 * (and overruled by a SIGKILL).  So those cases clear this
- 		 * shared flag after we've set it.  Note that this flag may
- 		 * remain set after the signal we return is ignored or
- 		 * handled.  That doesn't matter because its only purpose
- 		 * is to alert stop-signal processing code when another
- 		 * processor has come along and cleared the flag.
- 		 */
- 		if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
- 			tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
- 	}
+	if (signr && unlikely(sig_kernel_stop(signr))) {
+		/*
+		 * Set a marker that we have dequeued a stop signal.  Our
+		 * caller might release the siglock and then the pending
+		 * stop signal it is about to process is no longer in the
+		 * pending bitmasks, but must still be cleared by a SIGCONT
+		 * (and overruled by a SIGKILL).  So those cases clear this
+		 * shared flag after we've set it.  Note that this flag may
+		 * remain set after the signal we return is ignored or
+		 * handled.  That doesn't matter because its only purpose
+		 * is to alert stop-signal processing code when another
+		 * processor has come along and cleared the flag.
+		 */
+		if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
+			tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
+	}
 	if ( signr &&
 	     ((info->si_code & __SI_MASK) == __SI_TIMER) &&
 	     info->si_sys_private){
@@ -1096,42 +1120,21 @@
 	return retval;
 }
 
-int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
-{
-	if (pgrp <= 0)
-		return -EINVAL;
-
-	return __kill_pgrp_info(sig, info, find_pid(pgrp));
-}
-
-int
-kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
-{
-	int retval;
-
-	read_lock(&tasklist_lock);
-	retval = __kill_pg_info(sig, info, pgrp);
-	read_unlock(&tasklist_lock);
-
-	return retval;
-}
-
 int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
 {
 	int error;
-	int acquired_tasklist_lock = 0;
 	struct task_struct *p;
 
 	rcu_read_lock();
-	if (unlikely(sig_needs_tasklist(sig))) {
+	if (unlikely(sig_needs_tasklist(sig)))
 		read_lock(&tasklist_lock);
-		acquired_tasklist_lock = 1;
-	}
+
 	p = pid_task(pid, PIDTYPE_PID);
 	error = -ESRCH;
 	if (p)
 		error = group_send_sig_info(sig, info, p);
-	if (unlikely(acquired_tasklist_lock))
+
+	if (unlikely(sig_needs_tasklist(sig)))
 		read_unlock(&tasklist_lock);
 	rcu_read_unlock();
 	return error;
@@ -1192,8 +1195,10 @@
 
 static int kill_something_info(int sig, struct siginfo *info, int pid)
 {
+	int ret;
+	rcu_read_lock();
 	if (!pid) {
-		return kill_pg_info(sig, info, process_group(current));
+		ret = kill_pgrp_info(sig, info, task_pgrp(current));
 	} else if (pid == -1) {
 		int retval = 0, count = 0;
 		struct task_struct * p;
@@ -1208,12 +1213,14 @@
 			}
 		}
 		read_unlock(&tasklist_lock);
-		return count ? retval : -ESRCH;
+		ret = count ? retval : -ESRCH;
 	} else if (pid < 0) {
-		return kill_pg_info(sig, info, -pid);
+		ret = kill_pgrp_info(sig, info, find_pid(-pid));
 	} else {
-		return kill_proc_info(sig, info, pid);
+		ret = kill_pid_info(sig, info, find_pid(pid));
 	}
+	rcu_read_unlock();
+	return ret;
 }
 
 /*
@@ -1312,12 +1319,6 @@
 EXPORT_SYMBOL(kill_pid);
 
 int
-kill_pg(pid_t pgrp, int sig, int priv)
-{
-	return kill_pg_info(sig, __si_special(priv), pgrp);
-}
-
-int
 kill_proc(pid_t pid, int sig, int priv)
 {
 	return kill_proc_info(sig, __si_special(priv), pid);
@@ -1906,7 +1907,7 @@
 
 				/* signals can be posted during this window */
 
-				if (is_orphaned_pgrp(process_group(current)))
+				if (is_current_pgrp_orphaned())
 					goto relock;
 
 				spin_lock_irq(&current->sighand->siglock);
@@ -1956,7 +1957,6 @@
 EXPORT_SYMBOL_GPL(dequeue_signal);
 EXPORT_SYMBOL(flush_signals);
 EXPORT_SYMBOL(force_sig);
-EXPORT_SYMBOL(kill_pg);
 EXPORT_SYMBOL(kill_proc);
 EXPORT_SYMBOL(ptrace_notify);
 EXPORT_SYMBOL(send_sig);
@@ -2283,7 +2283,7 @@
  *  @pid: the PID of the thread
  *  @sig: signal to be sent
  *
- *  This syscall also checks the tgid and returns -ESRCH even if the PID
+ *  This syscall also checks the @tgid and returns -ESRCH even if the PID
  *  exists but it's not belonging to the target process anymore. This
  *  method solves the problem of threads exiting and PIDs getting reused.
  */
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 918e52d..8b75008 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -17,6 +17,7 @@
 #include <linux/kthread.h>
 #include <linux/rcupdate.h>
 #include <linux/smp.h>
+#include <linux/tick.h>
 
 #include <asm/irq.h>
 /*
@@ -273,6 +274,18 @@
 
 #endif
 
+/*
+ * Enter an interrupt context.
+ */
+void irq_enter(void)
+{
+	__irq_enter();
+#ifdef CONFIG_NO_HZ
+	if (idle_cpu(smp_processor_id()))
+		tick_nohz_update_jiffies();
+#endif
+}
+
 #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
 # define invoke_softirq()	__do_softirq()
 #else
@@ -289,6 +302,12 @@
 	sub_preempt_count(IRQ_EXIT_OFFSET);
 	if (!in_interrupt() && local_softirq_pending())
 		invoke_softirq();
+
+#ifdef CONFIG_NO_HZ
+	/* Make sure that timer wheel updates are propagated */
+	if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
+		tick_nohz_stop_sched_tick();
+#endif
 	preempt_enable_no_resched();
 }
 
diff --git a/kernel/sys.c b/kernel/sys.c
index 6e2101d..123b165 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -215,7 +215,7 @@
  *	This routine uses RCU to synchronize with changes to the chain.
  *
  *	If the return value of the notifier can be and'ed
- *	with %NOTIFY_STOP_MASK then atomic_notifier_call_chain
+ *	with %NOTIFY_STOP_MASK then atomic_notifier_call_chain()
  *	will return immediately, with the return value of
  *	the notifier function which halted execution.
  *	Otherwise the return value is the return value
@@ -313,7 +313,7 @@
  *	run in a process context, so they are allowed to block.
  *
  *	If the return value of the notifier can be and'ed
- *	with %NOTIFY_STOP_MASK then blocking_notifier_call_chain
+ *	with %NOTIFY_STOP_MASK then blocking_notifier_call_chain()
  *	will return immediately, with the return value of
  *	the notifier function which halted execution.
  *	Otherwise the return value is the return value
@@ -393,7 +393,7 @@
  *	All locking must be provided by the caller.
  *
  *	If the return value of the notifier can be and'ed
- *	with %NOTIFY_STOP_MASK then raw_notifier_call_chain
+ *	with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
  *	will return immediately, with the return value of
  *	the notifier function which halted execution.
  *	Otherwise the return value is the return value
@@ -487,7 +487,7 @@
  *	run in a process context, so they are allowed to block.
  *
  *	If the return value of the notifier can be and'ed
- *	with %NOTIFY_STOP_MASK then srcu_notifier_call_chain
+ *	with %NOTIFY_STOP_MASK then srcu_notifier_call_chain()
  *	will return immediately, with the return value of
  *	the notifier function which halted execution.
  *	Otherwise the return value is the return value
@@ -538,7 +538,7 @@
  *	Registers a function with the list of functions
  *	to be called at reboot time.
  *
- *	Currently always returns zero, as blocking_notifier_chain_register
+ *	Currently always returns zero, as blocking_notifier_chain_register()
  *	always returns zero.
  */
  
@@ -596,6 +596,7 @@
 	struct task_struct *g, *p;
 	struct user_struct *user;
 	int error = -EINVAL;
+	struct pid *pgrp;
 
 	if (which > 2 || which < 0)
 		goto out;
@@ -610,18 +611,21 @@
 	read_lock(&tasklist_lock);
 	switch (which) {
 		case PRIO_PROCESS:
-			if (!who)
-				who = current->pid;
-			p = find_task_by_pid(who);
+			if (who)
+				p = find_task_by_pid(who);
+			else
+				p = current;
 			if (p)
 				error = set_one_prio(p, niceval, error);
 			break;
 		case PRIO_PGRP:
-			if (!who)
-				who = process_group(current);
-			do_each_task_pid(who, PIDTYPE_PGID, p) {
+			if (who)
+				pgrp = find_pid(who);
+			else
+				pgrp = task_pgrp(current);
+			do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 				error = set_one_prio(p, niceval, error);
-			} while_each_task_pid(who, PIDTYPE_PGID, p);
+			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 			break;
 		case PRIO_USER:
 			user = current->user;
@@ -656,6 +660,7 @@
 	struct task_struct *g, *p;
 	struct user_struct *user;
 	long niceval, retval = -ESRCH;
+	struct pid *pgrp;
 
 	if (which > 2 || which < 0)
 		return -EINVAL;
@@ -663,9 +668,10 @@
 	read_lock(&tasklist_lock);
 	switch (which) {
 		case PRIO_PROCESS:
-			if (!who)
-				who = current->pid;
-			p = find_task_by_pid(who);
+			if (who)
+				p = find_task_by_pid(who);
+			else
+				p = current;
 			if (p) {
 				niceval = 20 - task_nice(p);
 				if (niceval > retval)
@@ -673,13 +679,15 @@
 			}
 			break;
 		case PRIO_PGRP:
-			if (!who)
-				who = process_group(current);
-			do_each_task_pid(who, PIDTYPE_PGID, p) {
+			if (who)
+				pgrp = find_pid(who);
+			else
+				pgrp = task_pgrp(current);
+			do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 				niceval = 20 - task_nice(p);
 				if (niceval > retval)
 					retval = niceval;
-			} while_each_task_pid(who, PIDTYPE_PGID, p);
+			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 			break;
 		case PRIO_USER:
 			user = current->user;
@@ -1388,7 +1396,7 @@
 
 	if (p->real_parent == group_leader) {
 		err = -EPERM;
-		if (process_session(p) != process_session(group_leader))
+		if (task_session(p) != task_session(group_leader))
 			goto out;
 		err = -EACCES;
 		if (p->did_exec)
@@ -1407,7 +1415,7 @@
 		struct task_struct *g =
 			find_task_by_pid_type(PIDTYPE_PGID, pgid);
 
-		if (!g || process_session(g) != process_session(group_leader))
+		if (!g || task_session(g) != task_session(group_leader))
 			goto out;
 	}
 
@@ -1510,7 +1518,6 @@
 
 	spin_lock(&group_leader->sighand->siglock);
 	group_leader->signal->tty = NULL;
-	group_leader->signal->tty_old_pgrp = 0;
 	spin_unlock(&group_leader->sighand->siglock);
 
 	err = process_group(group_leader);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 600b333..3ca1d5f 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -90,12 +90,6 @@
 #ifdef CONFIG_CHR_DEV_SG
 extern int sg_big_buff;
 #endif
-#ifdef CONFIG_SYSVIPC
-static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
-		void __user *buffer, size_t *lenp, loff_t *ppos);
-static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
-		void __user *buffer, size_t *lenp, loff_t *ppos);
-#endif
 
 #ifdef __sparc__
 extern char reboot_command [];
@@ -135,22 +129,12 @@
 		void __user *, size_t, ctl_table *);
 #endif
 
-static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
-		  void __user *buffer, size_t *lenp, loff_t *ppos);
-
-static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
-		  void __user *oldval, size_t __user *oldlenp,
-		  void __user *newval, size_t newlen);
-
-#ifdef CONFIG_SYSVIPC
-static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
-		  void __user *oldval, size_t __user *oldlenp,
-		  void __user *newval, size_t newlen);
-#endif
 
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
 		  void __user *buffer, size_t *lenp, loff_t *ppos);
+static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
+			       void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
 static ctl_table root_table[];
@@ -174,59 +158,6 @@
 int sysctl_legacy_va_layout;
 #endif
 
-static void *get_uts(ctl_table *table, int write)
-{
-	char *which = table->data;
-#ifdef CONFIG_UTS_NS
-	struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
-	which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
-#endif
-	if (!write)
-		down_read(&uts_sem);
-	else
-		down_write(&uts_sem);
-	return which;
-}
-
-static void put_uts(ctl_table *table, int write, void *which)
-{
-	if (!write)
-		up_read(&uts_sem);
-	else
-		up_write(&uts_sem);
-}
-
-#ifdef CONFIG_SYSVIPC
-static void *get_ipc(ctl_table *table, int write)
-{
-	char *which = table->data;
-	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
-	which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
-	return which;
-}
-#else
-#define get_ipc(T,W) ((T)->data)
-#endif
-
-/* /proc declarations: */
-
-#ifdef CONFIG_PROC_SYSCTL
-
-static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
-static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
-static int proc_opensys(struct inode *, struct file *);
-
-const struct file_operations proc_sys_file_operations = {
-	.open		= proc_opensys,
-	.read		= proc_readsys,
-	.write		= proc_writesys,
-};
-
-extern struct proc_dir_entry *proc_sys_root;
-
-static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *);
-static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
-#endif
 
 /* The default sysctl tables: */
 
@@ -275,51 +206,6 @@
 
 static ctl_table kern_table[] = {
 	{
-		.ctl_name	= KERN_OSTYPE,
-		.procname	= "ostype",
-		.data		= init_uts_ns.name.sysname,
-		.maxlen		= sizeof(init_uts_ns.name.sysname),
-		.mode		= 0444,
-		.proc_handler	= &proc_do_uts_string,
-		.strategy	= &sysctl_uts_string,
-	},
-	{
-		.ctl_name	= KERN_OSRELEASE,
-		.procname	= "osrelease",
-		.data		= init_uts_ns.name.release,
-		.maxlen		= sizeof(init_uts_ns.name.release),
-		.mode		= 0444,
-		.proc_handler	= &proc_do_uts_string,
-		.strategy	= &sysctl_uts_string,
-	},
-	{
-		.ctl_name	= KERN_VERSION,
-		.procname	= "version",
-		.data		= init_uts_ns.name.version,
-		.maxlen		= sizeof(init_uts_ns.name.version),
-		.mode		= 0444,
-		.proc_handler	= &proc_do_uts_string,
-		.strategy	= &sysctl_uts_string,
-	},
-	{
-		.ctl_name	= KERN_NODENAME,
-		.procname	= "hostname",
-		.data		= init_uts_ns.name.nodename,
-		.maxlen		= sizeof(init_uts_ns.name.nodename),
-		.mode		= 0644,
-		.proc_handler	= &proc_do_uts_string,
-		.strategy	= &sysctl_uts_string,
-	},
-	{
-		.ctl_name	= KERN_DOMAINNAME,
-		.procname	= "domainname",
-		.data		= init_uts_ns.name.domainname,
-		.maxlen		= sizeof(init_uts_ns.name.domainname),
-		.mode		= 0644,
-		.proc_handler	= &proc_do_uts_string,
-		.strategy	= &sysctl_uts_string,
-	},
-	{
 		.ctl_name	= KERN_PANIC,
 		.procname	= "panic",
 		.data		= &panic_timeout,
@@ -344,14 +230,16 @@
 		.proc_handler	= &proc_dostring,
 		.strategy	= &sysctl_string,
 	},
+#ifdef CONFIG_PROC_SYSCTL
 	{
 		.ctl_name	= KERN_TAINTED,
 		.procname	= "tainted",
 		.data		= &tainted,
 		.maxlen		= sizeof(int),
-		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_taint,
 	},
+#endif
 	{
 		.ctl_name	= KERN_CAP_BSET,
 		.procname	= "cap-bound",
@@ -473,71 +361,6 @@
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
-#ifdef CONFIG_SYSVIPC
-	{
-		.ctl_name	= KERN_SHMMAX,
-		.procname	= "shmmax",
-		.data		= &init_ipc_ns.shm_ctlmax,
-		.maxlen		= sizeof (init_ipc_ns.shm_ctlmax),
-		.mode		= 0644,
-		.proc_handler	= &proc_ipc_doulongvec_minmax,
-		.strategy	= sysctl_ipc_data,
-	},
-	{
-		.ctl_name	= KERN_SHMALL,
-		.procname	= "shmall",
-		.data		= &init_ipc_ns.shm_ctlall,
-		.maxlen		= sizeof (init_ipc_ns.shm_ctlall),
-		.mode		= 0644,
-		.proc_handler	= &proc_ipc_doulongvec_minmax,
-		.strategy	= sysctl_ipc_data,
-	},
-	{
-		.ctl_name	= KERN_SHMMNI,
-		.procname	= "shmmni",
-		.data		= &init_ipc_ns.shm_ctlmni,
-		.maxlen		= sizeof (init_ipc_ns.shm_ctlmni),
-		.mode		= 0644,
-		.proc_handler	= &proc_ipc_dointvec,
-		.strategy	= sysctl_ipc_data,
-	},
-	{
-		.ctl_name	= KERN_MSGMAX,
-		.procname	= "msgmax",
-		.data		= &init_ipc_ns.msg_ctlmax,
-		.maxlen		= sizeof (init_ipc_ns.msg_ctlmax),
-		.mode		= 0644,
-		.proc_handler	= &proc_ipc_dointvec,
-		.strategy	= sysctl_ipc_data,
-	},
-	{
-		.ctl_name	= KERN_MSGMNI,
-		.procname	= "msgmni",
-		.data		= &init_ipc_ns.msg_ctlmni,
-		.maxlen		= sizeof (init_ipc_ns.msg_ctlmni),
-		.mode		= 0644,
-		.proc_handler	= &proc_ipc_dointvec,
-		.strategy	= sysctl_ipc_data,
-	},
-	{
-		.ctl_name	= KERN_MSGMNB,
-		.procname	=  "msgmnb",
-		.data		= &init_ipc_ns.msg_ctlmnb,
-		.maxlen		= sizeof (init_ipc_ns.msg_ctlmnb),
-		.mode		= 0644,
-		.proc_handler	= &proc_ipc_dointvec,
-		.strategy	= sysctl_ipc_data,
-	},
-	{
-		.ctl_name	= KERN_SEM,
-		.procname	= "sem",
-		.data		= &init_ipc_ns.sem_ctls,
-		.maxlen		= 4*sizeof (int),
-		.mode		= 0644,
-		.proc_handler	= &proc_ipc_dointvec,
-		.strategy	= sysctl_ipc_data,
-	},
-#endif
 #ifdef CONFIG_MAGIC_SYSRQ
 	{
 		.ctl_name	= KERN_SYSRQ,
@@ -1038,6 +861,12 @@
 	{ .ctl_name = 0 }
 };
 
+#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
+static ctl_table binfmt_misc_table[] = {
+	{ .ctl_name = 0 }
+};
+#endif
+
 static ctl_table fs_table[] = {
 	{
 		.ctl_name	= FS_NRINODE,
@@ -1161,6 +990,14 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
+#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "binfmt_misc",
+		.mode		= 0555,
+		.child		= binfmt_misc_table,
+	},
+#endif
 	{ .ctl_name = 0 }
 };
 
@@ -1172,8 +1009,6 @@
 	{ .ctl_name = 0 }
 };
 
-extern void init_irq_proc (void);
-
 static DEFINE_SPINLOCK(sysctl_lock);
 
 /* called under sysctl_lock */
@@ -1215,19 +1050,47 @@
 	list_del_init(&p->ctl_entry);
 }
 
-void __init sysctl_init(void)
+void sysctl_head_finish(struct ctl_table_header *head)
 {
-#ifdef CONFIG_PROC_SYSCTL
-	register_proc_table(root_table, proc_sys_root, &root_table_header);
-	init_irq_proc();
-#endif
+	if (!head)
+		return;
+	spin_lock(&sysctl_lock);
+	unuse_table(head);
+	spin_unlock(&sysctl_lock);
+}
+
+struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
+{
+	struct ctl_table_header *head;
+	struct list_head *tmp;
+	spin_lock(&sysctl_lock);
+	if (prev) {
+		tmp = &prev->ctl_entry;
+		unuse_table(prev);
+		goto next;
+	}
+	tmp = &root_table_header.ctl_entry;
+	for (;;) {
+		head = list_entry(tmp, struct ctl_table_header, ctl_entry);
+
+		if (!use_table(head))
+			goto next;
+		spin_unlock(&sysctl_lock);
+		return head;
+	next:
+		tmp = tmp->next;
+		if (tmp == &root_table_header.ctl_entry)
+			break;
+	}
+	spin_unlock(&sysctl_lock);
+	return NULL;
 }
 
 #ifdef CONFIG_SYSCTL_SYSCALL
 int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
 	       void __user *newval, size_t newlen)
 {
-	struct list_head *tmp;
+	struct ctl_table_header *head;
 	int error = -ENOTDIR;
 
 	if (nlen <= 0 || nlen >= CTL_MAXNAME)
@@ -1237,26 +1100,16 @@
 		if (!oldlenp || get_user(old_len, oldlenp))
 			return -EFAULT;
 	}
-	spin_lock(&sysctl_lock);
-	tmp = &root_table_header.ctl_entry;
-	do {
-		struct ctl_table_header *head =
-			list_entry(tmp, struct ctl_table_header, ctl_entry);
 
-		if (!use_table(head))
-			continue;
-
-		spin_unlock(&sysctl_lock);
-
+	for (head = sysctl_head_next(NULL); head;
+			head = sysctl_head_next(head)) {
 		error = parse_table(name, nlen, oldval, oldlenp, 
 					newval, newlen, head->ctl_table);
-
-		spin_lock(&sysctl_lock);
-		unuse_table(head);
-		if (error != -ENOTDIR)
+		if (error != -ENOTDIR) {
+			sysctl_head_finish(head);
 			break;
-	} while ((tmp = tmp->next) != &root_table_header.ctl_entry);
-	spin_unlock(&sysctl_lock);
+		}
+	}
 	return error;
 }
 
@@ -1277,7 +1130,7 @@
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
- * ctl_perm does NOT grant the superuser all rights automatically, because
+ * sysctl_perm does NOT grant the superuser all rights automatically, because
  * some sysctl variables are readonly even to root.
  */
 
@@ -1292,7 +1145,7 @@
 	return -EACCES;
 }
 
-static inline int ctl_perm(ctl_table *table, int op)
+int sysctl_perm(ctl_table *table, int op)
 {
 	int error;
 	error = security_sysctl(table, op);
@@ -1316,19 +1169,11 @@
 	for ( ; table->ctl_name || table->procname; table++) {
 		if (!table->ctl_name)
 			continue;
-		if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
+		if (n == table->ctl_name) {
 			int error;
 			if (table->child) {
-				if (ctl_perm(table, 001))
+				if (sysctl_perm(table, 001))
 					return -EPERM;
-				if (table->strategy) {
-					error = table->strategy(
-						table, name, nlen,
-						oldval, oldlenp,
-						newval, newlen);
-					if (error)
-						return error;
-				}
 				name++;
 				nlen--;
 				table = table->child;
@@ -1356,7 +1201,7 @@
 		op |= 004;
 	if (newval) 
 		op |= 002;
-	if (ctl_perm(table, op))
+	if (sysctl_perm(table, op))
 		return -EPERM;
 
 	if (table->strategy) {
@@ -1395,10 +1240,26 @@
 }
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
+static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
+{
+	for (; table->ctl_name || table->procname; table++) {
+		table->parent = parent;
+		if (table->child)
+			sysctl_set_parent(table, table->child);
+	}
+}
+
+static __init int sysctl_init(void)
+{
+	sysctl_set_parent(NULL, root_table);
+	return 0;
+}
+
+core_initcall(sysctl_init);
+
 /**
  * register_sysctl_table - register a sysctl hierarchy
  * @table: the top-level table structure
- * @insert_at_head: whether the entry should be inserted in front or at the end
  *
  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
  * array. An entry with a ctl_name of 0 terminates the table. 
@@ -1464,8 +1325,7 @@
  * This routine returns %NULL on a failure to register, and a pointer
  * to the table header on success.
  */
-struct ctl_table_header *register_sysctl_table(ctl_table * table, 
-					       int insert_at_head)
+struct ctl_table_header *register_sysctl_table(ctl_table * table)
 {
 	struct ctl_table_header *tmp;
 	tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
@@ -1475,15 +1335,10 @@
 	INIT_LIST_HEAD(&tmp->ctl_entry);
 	tmp->used = 0;
 	tmp->unregistering = NULL;
+	sysctl_set_parent(NULL, table);
 	spin_lock(&sysctl_lock);
-	if (insert_at_head)
-		list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
-	else
-		list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
+	list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
 	spin_unlock(&sysctl_lock);
-#ifdef CONFIG_PROC_SYSCTL
-	register_proc_table(table, proc_sys_root, tmp);
-#endif
 	return tmp;
 }
 
@@ -1499,9 +1354,6 @@
 	might_sleep();
 	spin_lock(&sysctl_lock);
 	start_unregistering(header);
-#ifdef CONFIG_PROC_SYSCTL
-	unregister_proc_table(header->ctl_table, proc_sys_root);
-#endif
 	spin_unlock(&sysctl_lock);
 	kfree(header);
 }
@@ -1525,155 +1377,6 @@
 
 #ifdef CONFIG_PROC_SYSCTL
 
-/* Scan the sysctl entries in table and add them all into /proc */
-static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set)
-{
-	struct proc_dir_entry *de;
-	int len;
-	mode_t mode;
-	
-	for (; table->ctl_name || table->procname; table++) {
-		/* Can't do anything without a proc name. */
-		if (!table->procname)
-			continue;
-		/* Maybe we can't do anything with it... */
-		if (!table->proc_handler && !table->child) {
-			printk(KERN_WARNING "SYSCTL: Can't register %s\n",
-				table->procname);
-			continue;
-		}
-
-		len = strlen(table->procname);
-		mode = table->mode;
-
-		de = NULL;
-		if (table->proc_handler)
-			mode |= S_IFREG;
-		else {
-			mode |= S_IFDIR;
-			for (de = root->subdir; de; de = de->next) {
-				if (proc_match(len, table->procname, de))
-					break;
-			}
-			/* If the subdir exists already, de is non-NULL */
-		}
-
-		if (!de) {
-			de = create_proc_entry(table->procname, mode, root);
-			if (!de)
-				continue;
-			de->set = set;
-			de->data = (void *) table;
-			if (table->proc_handler)
-				de->proc_fops = &proc_sys_file_operations;
-		}
-		table->de = de;
-		if (de->mode & S_IFDIR)
-			register_proc_table(table->child, de, set);
-	}
-}
-
-/*
- * Unregister a /proc sysctl table and any subdirectories.
- */
-static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
-{
-	struct proc_dir_entry *de;
-	for (; table->ctl_name || table->procname; table++) {
-		if (!(de = table->de))
-			continue;
-		if (de->mode & S_IFDIR) {
-			if (!table->child) {
-				printk (KERN_ALERT "Help - malformed sysctl tree on free\n");
-				continue;
-			}
-			unregister_proc_table(table->child, de);
-
-			/* Don't unregister directories which still have entries.. */
-			if (de->subdir)
-				continue;
-		}
-
-		/*
-		 * In any case, mark the entry as goner; we'll keep it
-		 * around if it's busy, but we'll know to do nothing with
-		 * its fields.  We are under sysctl_lock here.
-		 */
-		de->data = NULL;
-
-		/* Don't unregister proc entries that are still being used.. */
-		if (atomic_read(&de->count))
-			continue;
-
-		table->de = NULL;
-		remove_proc_entry(table->procname, root);
-	}
-}
-
-static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
-			  size_t count, loff_t *ppos)
-{
-	int op;
-	struct proc_dir_entry *de = PDE(file->f_path.dentry->d_inode);
-	struct ctl_table *table;
-	size_t res;
-	ssize_t error = -ENOTDIR;
-	
-	spin_lock(&sysctl_lock);
-	if (de && de->data && use_table(de->set)) {
-		/*
-		 * at that point we know that sysctl was not unregistered
-		 * and won't be until we finish
-		 */
-		spin_unlock(&sysctl_lock);
-		table = (struct ctl_table *) de->data;
-		if (!table || !table->proc_handler)
-			goto out;
-		error = -EPERM;
-		op = (write ? 002 : 004);
-		if (ctl_perm(table, op))
-			goto out;
-		
-		/* careful: calling conventions are nasty here */
-		res = count;
-		error = (*table->proc_handler)(table, write, file,
-						buf, &res, ppos);
-		if (!error)
-			error = res;
-	out:
-		spin_lock(&sysctl_lock);
-		unuse_table(de->set);
-	}
-	spin_unlock(&sysctl_lock);
-	return error;
-}
-
-static int proc_opensys(struct inode *inode, struct file *file)
-{
-	if (file->f_mode & FMODE_WRITE) {
-		/*
-		 * sysctl entries that are not writable,
-		 * are _NOT_ writable, capabilities or not.
-		 */
-		if (!(inode->i_mode & S_IWUSR))
-			return -EPERM;
-	}
-
-	return 0;
-}
-
-static ssize_t proc_readsys(struct file * file, char __user * buf,
-			    size_t count, loff_t *ppos)
-{
-	return do_rw_proc(0, file, buf, count, ppos);
-}
-
-static ssize_t proc_writesys(struct file * file, const char __user * buf,
-			     size_t count, loff_t *ppos)
-{
-	return do_rw_proc(1, file, (char __user *) buf, count, ppos);
-}
-
 static int _proc_do_string(void* data, int maxlen, int write,
 			   struct file *filp, void __user *buffer,
 			   size_t *lenp, loff_t *ppos)
@@ -1681,13 +1384,12 @@
 	size_t len;
 	char __user *p;
 	char c;
-	
-	if (!data || !maxlen || !*lenp ||
-	    (*ppos && !write)) {
+
+	if (!data || !maxlen || !*lenp) {
 		*lenp = 0;
 		return 0;
 	}
-	
+
 	if (write) {
 		len = 0;
 		p = buffer;
@@ -1708,6 +1410,15 @@
 		len = strlen(data);
 		if (len > maxlen)
 			len = maxlen;
+
+		if (*ppos > len) {
+			*lenp = 0;
+			return 0;
+		}
+
+		data += *ppos;
+		len  -= *ppos;
+
 		if (len > *lenp)
 			len = *lenp;
 		if (len)
@@ -1749,21 +1460,6 @@
 			       buffer, lenp, ppos);
 }
 
-/*
- *	Special case of dostring for the UTS structure. This has locks
- *	to observe. Should this be in kernel/sys.c ????
- */
-
-static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
-		  void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-	int r;
-	void *which;
-	which = get_uts(table, write);
-	r = _proc_do_string(which, table->maxlen,write,filp,buffer,lenp, ppos);
-	put_uts(table, write, which);
-	return r;
-}
 
 static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
 				 int *valp,
@@ -1927,6 +1623,7 @@
 
 #define OP_SET	0
 #define OP_AND	1
+#define OP_OR	2
 
 static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
 				      int *valp,
@@ -1938,6 +1635,7 @@
 		switch(op) {
 		case OP_SET:	*valp = val; break;
 		case OP_AND:	*valp &= val; break;
+		case OP_OR:	*valp |= val; break;
 		}
 	} else {
 		int val = *valp;
@@ -1961,7 +1659,7 @@
 {
 	int op;
 
-	if (!capable(CAP_SYS_MODULE)) {
+	if (write && !capable(CAP_SYS_MODULE)) {
 		return -EPERM;
 	}
 
@@ -1970,6 +1668,22 @@
 				do_proc_dointvec_bset_conv,&op);
 }
 
+/*
+ *	Taint values can only be increased
+ */
+static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
+			       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	int op;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	op = OP_OR;
+	return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
+				do_proc_dointvec_bset_conv,&op);
+}
+
 struct do_proc_dointvec_minmax_conv_param {
 	int *min;
 	int *max;
@@ -2331,27 +2045,6 @@
 				do_proc_dointvec_ms_jiffies_conv, NULL);
 }
 
-#ifdef CONFIG_SYSVIPC
-static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
-	void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-	void *which;
-	which = get_ipc(table, write);
-	return __do_proc_dointvec(which, table, write, filp, buffer,
-			lenp, ppos, NULL, NULL);
-}
-
-static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
-	struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-	void *which;
-	which = get_ipc(table, write);
-	return __do_proc_doulongvec_minmax(which, table, write, filp, buffer,
-			lenp, ppos, 1l, 1l);
-}
-
-#endif
-
 static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
 			   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -2382,31 +2075,6 @@
 	return -ENOSYS;
 }
 
-static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
-		void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-	return -ENOSYS;
-}
-
-#ifdef CONFIG_SYSVIPC
-static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
-		void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-	return -ENOSYS;
-}
-static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
-		void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-	return -ENOSYS;
-}
-static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
-		struct file *filp, void __user *buffer,
-		size_t *lenp, loff_t *ppos)
-{
-	return -ENOSYS;
-}
-#endif
-
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
 		  void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -2553,17 +2221,23 @@
 		void __user *oldval, size_t __user *oldlenp,
 		void __user *newval, size_t newlen)
 {
-	if (oldval) {
+	if (oldval && oldlenp) {
 		size_t olen;
-		if (oldlenp) { 
-			if (get_user(olen, oldlenp))
-				return -EFAULT;
-			if (olen!=sizeof(int))
-				return -EINVAL; 
-		}
-		if (put_user(*(int *)(table->data)/HZ, (int __user *)oldval) ||
-		    (oldlenp && put_user(sizeof(int),oldlenp)))
+
+		if (get_user(olen, oldlenp))
 			return -EFAULT;
+		if (olen) {
+			int val;
+
+			if (olen < sizeof(int))
+				return -EINVAL;
+
+			val = *(int *)(table->data) / HZ;
+			if (put_user(val, (int __user *)oldval))
+				return -EFAULT;
+			if (put_user(sizeof(int), oldlenp))
+				return -EFAULT;
+		}
 	}
 	if (newval && newlen) { 
 		int new;
@@ -2581,17 +2255,23 @@
 		void __user *oldval, size_t __user *oldlenp,
 		void __user *newval, size_t newlen)
 {
-	if (oldval) {
+	if (oldval && oldlenp) {
 		size_t olen;
-		if (oldlenp) { 
-			if (get_user(olen, oldlenp))
-				return -EFAULT;
-			if (olen!=sizeof(int))
-				return -EINVAL; 
-		}
-		if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) ||
-		    (oldlenp && put_user(sizeof(int),oldlenp)))
+
+		if (get_user(olen, oldlenp))
 			return -EFAULT;
+		if (olen) {
+			int val;
+
+			if (olen < sizeof(int))
+				return -EINVAL;
+
+			val = jiffies_to_msecs(*(int *)(table->data));
+			if (put_user(val, (int __user *)oldval))
+				return -EFAULT;
+			if (put_user(sizeof(int), oldlenp))
+				return -EFAULT;
+		}
 	}
 	if (newval && newlen) { 
 		int new;
@@ -2605,62 +2285,6 @@
 }
 
 
-/* The generic string strategy routine: */
-static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
-		  void __user *oldval, size_t __user *oldlenp,
-		  void __user *newval, size_t newlen)
-{
-	struct ctl_table uts_table;
-	int r, write;
-	write = newval && newlen;
-	memcpy(&uts_table, table, sizeof(uts_table));
-	uts_table.data = get_uts(table, write);
-	r = sysctl_string(&uts_table, name, nlen,
-		oldval, oldlenp, newval, newlen);
-	put_uts(table, write, uts_table.data);
-	return r;
-}
-
-#ifdef CONFIG_SYSVIPC
-/* The generic sysctl ipc data routine. */
-static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
-		void __user *oldval, size_t __user *oldlenp,
-		void __user *newval, size_t newlen)
-{
-	size_t len;
-	void *data;
-
-	/* Get out of I don't have a variable */
-	if (!table->data || !table->maxlen)
-		return -ENOTDIR;
-
-	data = get_ipc(table, 1);
-	if (!data)
-		return -ENOTDIR;
-
-	if (oldval && oldlenp) {
-		if (get_user(len, oldlenp))
-			return -EFAULT;
-		if (len) {
-			if (len > table->maxlen)
-				len = table->maxlen;
-			if (copy_to_user(oldval, data, len))
-				return -EFAULT;
-			if (put_user(len, oldlenp))
-				return -EFAULT;
-		}
-	}
-
-	if (newval && newlen) {
-		if (newlen > table->maxlen)
-			newlen = table->maxlen;
-
-		if (copy_from_user(data, newval, newlen))
-			return -EFAULT;
-	}
-	return 1;
-}
-#endif
 
 #else /* CONFIG_SYSCTL_SYSCALL */
 
@@ -2726,18 +2350,6 @@
 	return -ENOSYS;
 }
 
-static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
-		  void __user *oldval, size_t __user *oldlenp,
-		  void __user *newval, size_t newlen)
-{
-	return -ENOSYS;
-}
-static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
-		void __user *oldval, size_t __user *oldlenp,
-		void __user *newval, size_t newlen)
-{
-	return -ENOSYS;
-}
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
diff --git a/kernel/time.c b/kernel/time.c
index 0e017bff..c6c80ea5 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -470,6 +470,260 @@
 	return tv;
 }
 
+/*
+ * Convert jiffies to milliseconds and back.
+ *
+ * Avoid unnecessary multiplications/divisions in the
+ * two most common HZ cases:
+ */
+unsigned int jiffies_to_msecs(const unsigned long j)
+{
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+	return (MSEC_PER_SEC / HZ) * j;
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+	return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
+#else
+	return (j * MSEC_PER_SEC) / HZ;
+#endif
+}
+EXPORT_SYMBOL(jiffies_to_msecs);
+
+unsigned int jiffies_to_usecs(const unsigned long j)
+{
+#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
+	return (USEC_PER_SEC / HZ) * j;
+#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
+	return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC);
+#else
+	return (j * USEC_PER_SEC) / HZ;
+#endif
+}
+EXPORT_SYMBOL(jiffies_to_usecs);
+
+/*
+ * When we convert to jiffies then we interpret incoming values
+ * the following way:
+ *
+ * - negative values mean 'infinite timeout' (MAX_JIFFY_OFFSET)
+ *
+ * - 'too large' values [that would result in larger than
+ *   MAX_JIFFY_OFFSET values] mean 'infinite timeout' too.
+ *
+ * - all other values are converted to jiffies by either multiplying
+ *   the input value by a factor or dividing it with a factor
+ *
+ * We must also be careful about 32-bit overflows.
+ */
+unsigned long msecs_to_jiffies(const unsigned int m)
+{
+	/*
+	 * Negative value, means infinite timeout:
+	 */
+	if ((int)m < 0)
+		return MAX_JIFFY_OFFSET;
+
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+	/*
+	 * HZ is equal to or smaller than 1000, and 1000 is a nice
+	 * round multiple of HZ, divide with the factor between them,
+	 * but round upwards:
+	 */
+	return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ);
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+	/*
+	 * HZ is larger than 1000, and HZ is a nice round multiple of
+	 * 1000 - simply multiply with the factor between them.
+	 *
+	 * But first make sure the multiplication result cannot
+	 * overflow:
+	 */
+	if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
+		return MAX_JIFFY_OFFSET;
+
+	return m * (HZ / MSEC_PER_SEC);
+#else
+	/*
+	 * Generic case - multiply, round and divide. But first
+	 * check that if we are doing a net multiplication, that
+	 * we wouldnt overflow:
+	 */
+	if (HZ > MSEC_PER_SEC && m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
+		return MAX_JIFFY_OFFSET;
+
+	return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC;
+#endif
+}
+EXPORT_SYMBOL(msecs_to_jiffies);
+
+unsigned long usecs_to_jiffies(const unsigned int u)
+{
+	if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
+		return MAX_JIFFY_OFFSET;
+#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
+	return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ);
+#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
+	return u * (HZ / USEC_PER_SEC);
+#else
+	return (u * HZ + USEC_PER_SEC - 1) / USEC_PER_SEC;
+#endif
+}
+EXPORT_SYMBOL(usecs_to_jiffies);
+
+/*
+ * The TICK_NSEC - 1 rounds up the value to the next resolution.  Note
+ * that a remainder subtract here would not do the right thing as the
+ * resolution values don't fall on second boundries.  I.e. the line:
+ * nsec -= nsec % TICK_NSEC; is NOT a correct resolution rounding.
+ *
+ * Rather, we just shift the bits off the right.
+ *
+ * The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec
+ * value to a scaled second value.
+ */
+unsigned long
+timespec_to_jiffies(const struct timespec *value)
+{
+	unsigned long sec = value->tv_sec;
+	long nsec = value->tv_nsec + TICK_NSEC - 1;
+
+	if (sec >= MAX_SEC_IN_JIFFIES){
+		sec = MAX_SEC_IN_JIFFIES;
+		nsec = 0;
+	}
+	return (((u64)sec * SEC_CONVERSION) +
+		(((u64)nsec * NSEC_CONVERSION) >>
+		 (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
+
+}
+EXPORT_SYMBOL(timespec_to_jiffies);
+
+void
+jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)
+{
+	/*
+	 * Convert jiffies to nanoseconds and separate with
+	 * one divide.
+	 */
+	u64 nsec = (u64)jiffies * TICK_NSEC;
+	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_nsec);
+}
+EXPORT_SYMBOL(jiffies_to_timespec);
+
+/* Same for "timeval"
+ *
+ * Well, almost.  The problem here is that the real system resolution is
+ * in nanoseconds and the value being converted is in micro seconds.
+ * Also for some machines (those that use HZ = 1024, in-particular),
+ * there is a LARGE error in the tick size in microseconds.
+
+ * The solution we use is to do the rounding AFTER we convert the
+ * microsecond part.  Thus the USEC_ROUND, the bits to be shifted off.
+ * Instruction wise, this should cost only an additional add with carry
+ * instruction above the way it was done above.
+ */
+unsigned long
+timeval_to_jiffies(const struct timeval *value)
+{
+	unsigned long sec = value->tv_sec;
+	long usec = value->tv_usec;
+
+	if (sec >= MAX_SEC_IN_JIFFIES){
+		sec = MAX_SEC_IN_JIFFIES;
+		usec = 0;
+	}
+	return (((u64)sec * SEC_CONVERSION) +
+		(((u64)usec * USEC_CONVERSION + USEC_ROUND) >>
+		 (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
+}
+
+void jiffies_to_timeval(const unsigned long jiffies, struct timeval *value)
+{
+	/*
+	 * Convert jiffies to nanoseconds and separate with
+	 * one divide.
+	 */
+	u64 nsec = (u64)jiffies * TICK_NSEC;
+	long tv_usec;
+
+	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tv_usec);
+	tv_usec /= NSEC_PER_USEC;
+	value->tv_usec = tv_usec;
+}
+
+/*
+ * Convert jiffies/jiffies_64 to clock_t and back.
+ */
+clock_t jiffies_to_clock_t(long x)
+{
+#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
+	return x / (HZ / USER_HZ);
+#else
+	u64 tmp = (u64)x * TICK_NSEC;
+	do_div(tmp, (NSEC_PER_SEC / USER_HZ));
+	return (long)tmp;
+#endif
+}
+EXPORT_SYMBOL(jiffies_to_clock_t);
+
+unsigned long clock_t_to_jiffies(unsigned long x)
+{
+#if (HZ % USER_HZ)==0
+	if (x >= ~0UL / (HZ / USER_HZ))
+		return ~0UL;
+	return x * (HZ / USER_HZ);
+#else
+	u64 jif;
+
+	/* Don't worry about loss of precision here .. */
+	if (x >= ~0UL / HZ * USER_HZ)
+		return ~0UL;
+
+	/* .. but do try to contain it here */
+	jif = x * (u64) HZ;
+	do_div(jif, USER_HZ);
+	return jif;
+#endif
+}
+EXPORT_SYMBOL(clock_t_to_jiffies);
+
+u64 jiffies_64_to_clock_t(u64 x)
+{
+#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
+	do_div(x, HZ / USER_HZ);
+#else
+	/*
+	 * There are better ways that don't overflow early,
+	 * but even this doesn't overflow in hundreds of years
+	 * in 64 bits, so..
+	 */
+	x *= TICK_NSEC;
+	do_div(x, (NSEC_PER_SEC / USER_HZ));
+#endif
+	return x;
+}
+
+EXPORT_SYMBOL(jiffies_64_to_clock_t);
+
+u64 nsec_to_clock_t(u64 x)
+{
+#if (NSEC_PER_SEC % USER_HZ) == 0
+	do_div(x, (NSEC_PER_SEC / USER_HZ));
+#elif (USER_HZ % 512) == 0
+	x *= USER_HZ/512;
+	do_div(x, (NSEC_PER_SEC / 512));
+#else
+	/*
+         * max relative error 5.7e-8 (1.8s per year) for USER_HZ <= 1024,
+         * overflow after 64.99 years.
+         * exact for HZ=60, 72, 90, 120, 144, 180, 300, 600, 900, ...
+         */
+	x *= 9;
+	do_div(x, (unsigned long)((9ull * NSEC_PER_SEC + (USER_HZ/2)) /
+				  USER_HZ));
+#endif
+	return x;
+}
+
 #if (BITS_PER_LONG < 64)
 u64 get_jiffies_64(void)
 {
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
new file mode 100644
index 0000000..f663511
--- /dev/null
+++ b/kernel/time/Kconfig
@@ -0,0 +1,25 @@
+#
+# Timer subsystem related configuration options
+#
+config TICK_ONESHOT
+	bool
+	default n
+
+config NO_HZ
+	bool "Tickless System (Dynamic Ticks)"
+	depends on GENERIC_TIME && GENERIC_CLOCKEVENTS
+	select TICK_ONESHOT
+	help
+	  This option enables a tickless system: timer interrupts will
+	  only trigger on an as-needed basis both when the system is
+	  busy and when the system is idle.
+
+config HIGH_RES_TIMERS
+	bool "High Resolution Timer Support"
+	depends on GENERIC_TIME && GENERIC_CLOCKEVENTS
+	select TICK_ONESHOT
+	help
+	  This option enables high resolution timer support. If your
+	  hardware is not capable then this option only increases
+	  the size of the kernel image.
+
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index 61a3907..93bccba 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -1 +1,8 @@
-obj-y += ntp.o clocksource.o jiffies.o
+obj-y += ntp.o clocksource.o jiffies.o timer_list.o
+
+obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= clockevents.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= tick-common.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= tick-broadcast.o
+obj-$(CONFIG_TICK_ONESHOT)			+= tick-oneshot.o
+obj-$(CONFIG_TICK_ONESHOT)			+= tick-sched.o
+obj-$(CONFIG_TIMER_STATS)			+= timer_stats.o
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
new file mode 100644
index 0000000..67932ea
--- /dev/null
+++ b/kernel/time/clockevents.c
@@ -0,0 +1,345 @@
+/*
+ * linux/kernel/time/clockevents.c
+ *
+ * This file contains functions which manage clock event devices.
+ *
+ * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
+ *
+ * This code is licenced under the GPL version 2. For details see
+ * kernel-base/COPYING.
+ */
+
+#include <linux/clockchips.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/smp.h>
+#include <linux/sysdev.h>
+
+/* The registered clock event devices */
+static LIST_HEAD(clockevent_devices);
+static LIST_HEAD(clockevents_released);
+
+/* Notification for clock events */
+static RAW_NOTIFIER_HEAD(clockevents_chain);
+
+/* Protection for the above */
+static DEFINE_SPINLOCK(clockevents_lock);
+
+/**
+ * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds
+ * @latch:	value to convert
+ * @evt:	pointer to clock event device descriptor
+ *
+ * Math helper, returns latch value converted to nanoseconds (bound checked)
+ */
+unsigned long clockevent_delta2ns(unsigned long latch,
+				  struct clock_event_device *evt)
+{
+	u64 clc = ((u64) latch << evt->shift);
+
+	do_div(clc, evt->mult);
+	if (clc < 1000)
+		clc = 1000;
+	if (clc > LONG_MAX)
+		clc = LONG_MAX;
+
+	return (unsigned long) clc;
+}
+
+/**
+ * clockevents_set_mode - set the operating mode of a clock event device
+ * @dev:	device to modify
+ * @mode:	new mode
+ *
+ * Must be called with interrupts disabled !
+ */
+void clockevents_set_mode(struct clock_event_device *dev,
+				 enum clock_event_mode mode)
+{
+	if (dev->mode != mode) {
+		dev->set_mode(mode, dev);
+		dev->mode = mode;
+	}
+}
+
+/**
+ * clockevents_program_event - Reprogram the clock event device.
+ * @expires:	absolute expiry time (monotonic clock)
+ *
+ * Returns 0 on success, -ETIME when the event is in the past.
+ */
+int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
+			      ktime_t now)
+{
+	unsigned long long clc;
+	int64_t delta;
+
+	delta = ktime_to_ns(ktime_sub(expires, now));
+
+	if (delta <= 0)
+		return -ETIME;
+
+	dev->next_event = expires;
+
+	if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN)
+		return 0;
+
+	if (delta > dev->max_delta_ns)
+		delta = dev->max_delta_ns;
+	if (delta < dev->min_delta_ns)
+		delta = dev->min_delta_ns;
+
+	clc = delta * dev->mult;
+	clc >>= dev->shift;
+
+	return dev->set_next_event((unsigned long) clc, dev);
+}
+
+/**
+ * clockevents_register_notifier - register a clock events change listener
+ */
+int clockevents_register_notifier(struct notifier_block *nb)
+{
+	int ret;
+
+	spin_lock(&clockevents_lock);
+	ret = raw_notifier_chain_register(&clockevents_chain, nb);
+	spin_unlock(&clockevents_lock);
+
+	return ret;
+}
+
+/**
+ * clockevents_unregister_notifier - unregister a clock events change listener
+ */
+void clockevents_unregister_notifier(struct notifier_block *nb)
+{
+	spin_lock(&clockevents_lock);
+	raw_notifier_chain_unregister(&clockevents_chain, nb);
+	spin_unlock(&clockevents_lock);
+}
+
+/*
+ * Notify about a clock event change. Called with clockevents_lock
+ * held.
+ */
+static void clockevents_do_notify(unsigned long reason, void *dev)
+{
+	raw_notifier_call_chain(&clockevents_chain, reason, dev);
+}
+
+/*
+ * Called after a notify add to make devices availble which were
+ * released from the notifier call.
+ */
+static void clockevents_notify_released(void)
+{
+	struct clock_event_device *dev;
+
+	while (!list_empty(&clockevents_released)) {
+		dev = list_entry(clockevents_released.next,
+				 struct clock_event_device, list);
+		list_del(&dev->list);
+		list_add(&dev->list, &clockevent_devices);
+		clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
+	}
+}
+
+/**
+ * clockevents_register_device - register a clock event device
+ * @dev:	device to register
+ */
+void clockevents_register_device(struct clock_event_device *dev)
+{
+	BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
+
+	spin_lock(&clockevents_lock);
+
+	list_add(&dev->list, &clockevent_devices);
+	clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
+	clockevents_notify_released();
+
+	spin_unlock(&clockevents_lock);
+}
+
+/*
+ * Noop handler when we shut down an event device
+ */
+static void clockevents_handle_noop(struct clock_event_device *dev)
+{
+}
+
+/**
+ * clockevents_exchange_device - release and request clock devices
+ * @old:	device to release (can be NULL)
+ * @new:	device to request (can be NULL)
+ *
+ * Called from the notifier chain. clockevents_lock is held already
+ */
+void clockevents_exchange_device(struct clock_event_device *old,
+				 struct clock_event_device *new)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	/*
+	 * Caller releases a clock event device. We queue it into the
+	 * released list and do a notify add later.
+	 */
+	if (old) {
+		old->event_handler = clockevents_handle_noop;
+		clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
+		list_del(&old->list);
+		list_add(&old->list, &clockevents_released);
+	}
+
+	if (new) {
+		BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED);
+		clockevents_set_mode(new, CLOCK_EVT_MODE_SHUTDOWN);
+	}
+	local_irq_restore(flags);
+}
+
+/**
+ * clockevents_request_device
+ */
+struct clock_event_device *clockevents_request_device(unsigned int features,
+						      cpumask_t cpumask)
+{
+	struct clock_event_device *cur, *dev = NULL;
+	struct list_head *tmp;
+
+	spin_lock(&clockevents_lock);
+
+	list_for_each(tmp, &clockevent_devices) {
+		cur = list_entry(tmp, struct clock_event_device, list);
+
+		if ((cur->features & features) == features &&
+		    cpus_equal(cpumask, cur->cpumask)) {
+			if (!dev || dev->rating < cur->rating)
+				dev = cur;
+		}
+	}
+
+	clockevents_exchange_device(NULL, dev);
+
+	spin_unlock(&clockevents_lock);
+
+	return dev;
+}
+
+/**
+ * clockevents_release_device
+ */
+void clockevents_release_device(struct clock_event_device *dev)
+{
+	spin_lock(&clockevents_lock);
+
+	clockevents_exchange_device(dev, NULL);
+	clockevents_notify_released();
+
+	spin_unlock(&clockevents_lock);
+}
+
+/**
+ * clockevents_notify - notification about relevant events
+ */
+void clockevents_notify(unsigned long reason, void *arg)
+{
+	spin_lock(&clockevents_lock);
+	clockevents_do_notify(reason, arg);
+
+	switch (reason) {
+	case CLOCK_EVT_NOTIFY_CPU_DEAD:
+		/*
+		 * Unregister the clock event devices which were
+		 * released from the users in the notify chain.
+		 */
+		while (!list_empty(&clockevents_released)) {
+			struct clock_event_device *dev;
+
+			dev = list_entry(clockevents_released.next,
+					 struct clock_event_device, list);
+			list_del(&dev->list);
+		}
+		break;
+	default:
+		break;
+	}
+	spin_unlock(&clockevents_lock);
+}
+EXPORT_SYMBOL_GPL(clockevents_notify);
+
+#ifdef CONFIG_SYSFS
+
+/**
+ * clockevents_show_registered - sysfs interface for listing clockevents
+ * @dev:	unused
+ * @buf:	char buffer to be filled with clock events list
+ *
+ * Provides sysfs interface for listing registered clock event devices
+ */
+static ssize_t clockevents_show_registered(struct sys_device *dev, char *buf)
+{
+	struct list_head *tmp;
+	char *p = buf;
+	int cpu;
+
+	spin_lock(&clockevents_lock);
+
+	list_for_each(tmp, &clockevent_devices) {
+		struct clock_event_device *ce;
+
+		ce = list_entry(tmp, struct clock_event_device, list);
+		p += sprintf(p, "%-20s F:%04x M:%d", ce->name,
+			     ce->features, ce->mode);
+		p += sprintf(p, " C:");
+		if (!cpus_equal(ce->cpumask, cpu_possible_map)) {
+			for_each_cpu_mask(cpu, ce->cpumask)
+				p += sprintf(p, " %d", cpu);
+		} else {
+			/*
+			 * FIXME: Add the cpu which is handling this sucker
+			 */
+		}
+		p += sprintf(p, "\n");
+	}
+
+	spin_unlock(&clockevents_lock);
+
+	return p - buf;
+}
+
+/*
+ * Sysfs setup bits:
+ */
+static SYSDEV_ATTR(registered, 0600,
+		   clockevents_show_registered, NULL);
+
+static struct sysdev_class clockevents_sysclass = {
+	set_kset_name("clockevents"),
+};
+
+static struct sys_device clockevents_sys_device = {
+	.id	= 0,
+	.cls	= &clockevents_sysclass,
+};
+
+static int __init clockevents_sysfs_init(void)
+{
+	int error = sysdev_class_register(&clockevents_sysclass);
+
+	if (!error)
+		error = sysdev_register(&clockevents_sys_device);
+	if (!error)
+		error = sysdev_create_file(
+				&clockevents_sys_device,
+				&attr_registered);
+	return error;
+}
+device_initcall(clockevents_sysfs_init);
+#endif
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 22504af..193a079 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -28,6 +28,8 @@
 #include <linux/sysdev.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/sched.h> /* for spin_unlock_irq() using preempt_count() m68k */
+#include <linux/tick.h>
 
 /* XXX - Would like a better way for initializing curr_clocksource */
 extern struct clocksource clocksource_jiffies;
@@ -47,6 +49,7 @@
  */
 static struct clocksource *curr_clocksource = &clocksource_jiffies;
 static struct clocksource *next_clocksource;
+static struct clocksource *clocksource_override;
 static LIST_HEAD(clocksource_list);
 static DEFINE_SPINLOCK(clocksource_lock);
 static char override_name[32];
@@ -61,9 +64,123 @@
 	finished_booting = 1;
 	return 0;
 }
-
 late_initcall(clocksource_done_booting);
 
+#ifdef CONFIG_CLOCKSOURCE_WATCHDOG
+static LIST_HEAD(watchdog_list);
+static struct clocksource *watchdog;
+static struct timer_list watchdog_timer;
+static DEFINE_SPINLOCK(watchdog_lock);
+static cycle_t watchdog_last;
+/*
+ * Interval: 0.5sec Treshold: 0.0625s
+ */
+#define WATCHDOG_INTERVAL (HZ >> 1)
+#define WATCHDOG_TRESHOLD (NSEC_PER_SEC >> 4)
+
+static void clocksource_ratewd(struct clocksource *cs, int64_t delta)
+{
+	if (delta > -WATCHDOG_TRESHOLD && delta < WATCHDOG_TRESHOLD)
+		return;
+
+	printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
+	       cs->name, delta);
+	cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
+	clocksource_change_rating(cs, 0);
+	cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
+	list_del(&cs->wd_list);
+}
+
+static void clocksource_watchdog(unsigned long data)
+{
+	struct clocksource *cs, *tmp;
+	cycle_t csnow, wdnow;
+	int64_t wd_nsec, cs_nsec;
+
+	spin_lock(&watchdog_lock);
+
+	wdnow = watchdog->read();
+	wd_nsec = cyc2ns(watchdog, (wdnow - watchdog_last) & watchdog->mask);
+	watchdog_last = wdnow;
+
+	list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) {
+		csnow = cs->read();
+		/* Initialized ? */
+		if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
+			if ((cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&
+			    (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) {
+				cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
+				/*
+				 * We just marked the clocksource as
+				 * highres-capable, notify the rest of the
+				 * system as well so that we transition
+				 * into high-res mode:
+				 */
+				tick_clock_notify();
+			}
+			cs->flags |= CLOCK_SOURCE_WATCHDOG;
+			cs->wd_last = csnow;
+		} else {
+			cs_nsec = cyc2ns(cs, (csnow - cs->wd_last) & cs->mask);
+			cs->wd_last = csnow;
+			/* Check the delta. Might remove from the list ! */
+			clocksource_ratewd(cs, cs_nsec - wd_nsec);
+		}
+	}
+
+	if (!list_empty(&watchdog_list)) {
+		__mod_timer(&watchdog_timer,
+			    watchdog_timer.expires + WATCHDOG_INTERVAL);
+	}
+	spin_unlock(&watchdog_lock);
+}
+static void clocksource_check_watchdog(struct clocksource *cs)
+{
+	struct clocksource *cse;
+	unsigned long flags;
+
+	spin_lock_irqsave(&watchdog_lock, flags);
+	if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) {
+		int started = !list_empty(&watchdog_list);
+
+		list_add(&cs->wd_list, &watchdog_list);
+		if (!started && watchdog) {
+			watchdog_last = watchdog->read();
+			watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
+			add_timer(&watchdog_timer);
+		}
+	} else if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) {
+			cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
+
+		if (!watchdog || cs->rating > watchdog->rating) {
+			if (watchdog)
+				del_timer(&watchdog_timer);
+			watchdog = cs;
+			init_timer(&watchdog_timer);
+			watchdog_timer.function = clocksource_watchdog;
+
+			/* Reset watchdog cycles */
+			list_for_each_entry(cse, &watchdog_list, wd_list)
+				cse->flags &= ~CLOCK_SOURCE_WATCHDOG;
+			/* Start if list is not empty */
+			if (!list_empty(&watchdog_list)) {
+				watchdog_last = watchdog->read();
+				watchdog_timer.expires =
+					jiffies + WATCHDOG_INTERVAL;
+				add_timer(&watchdog_timer);
+			}
+		}
+	}
+	spin_unlock_irqrestore(&watchdog_lock, flags);
+}
+#else
+static void clocksource_check_watchdog(struct clocksource *cs)
+{
+	if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
+		cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
+}
+#endif
+
 /**
  * clocksource_get_next - Returns the selected clocksource
  *
@@ -83,60 +200,54 @@
 }
 
 /**
- * select_clocksource - Finds the best registered clocksource.
+ * select_clocksource - Selects the best registered clocksource.
  *
  * Private function. Must hold clocksource_lock when called.
  *
- * Looks through the list of registered clocksources, returning
- * the one with the highest rating value. If there is a clocksource
- * name that matches the override string, it returns that clocksource.
+ * Select the clocksource with the best rating, or the clocksource,
+ * which is selected by userspace override.
  */
 static struct clocksource *select_clocksource(void)
 {
-	struct clocksource *best = NULL;
-	struct list_head *tmp;
+	struct clocksource *next;
 
-	list_for_each(tmp, &clocksource_list) {
-		struct clocksource *src;
+	if (list_empty(&clocksource_list))
+		return NULL;
 
-		src = list_entry(tmp, struct clocksource, list);
-		if (!best)
-			best = src;
+	if (clocksource_override)
+		next = clocksource_override;
+	else
+		next = list_entry(clocksource_list.next, struct clocksource,
+				  list);
 
-		/* check for override: */
-		if (strlen(src->name) == strlen(override_name) &&
-		    !strcmp(src->name, override_name)) {
-			best = src;
-			break;
-		}
-		/* pick the highest rating: */
-		if (src->rating > best->rating)
-		 	best = src;
-	}
+	if (next == curr_clocksource)
+		return NULL;
 
-	return best;
+	return next;
 }
 
-/**
- * is_registered_source - Checks if clocksource is registered
- * @c:		pointer to a clocksource
- *
- * Private helper function. Must hold clocksource_lock when called.
- *
- * Returns one if the clocksource is already registered, zero otherwise.
+/*
+ * Enqueue the clocksource sorted by rating
  */
-static int is_registered_source(struct clocksource *c)
+static int clocksource_enqueue(struct clocksource *c)
 {
-	int len = strlen(c->name);
-	struct list_head *tmp;
+	struct list_head *tmp, *entry = &clocksource_list;
 
 	list_for_each(tmp, &clocksource_list) {
-		struct clocksource *src;
+		struct clocksource *cs;
 
-		src = list_entry(tmp, struct clocksource, list);
-		if (strlen(src->name) == len &&	!strcmp(src->name, c->name))
-			return 1;
+		cs = list_entry(tmp, struct clocksource, list);
+		if (cs == c)
+			return -EBUSY;
+		/* Keep track of the place, where to insert */
+		if (cs->rating >= c->rating)
+			entry = tmp;
 	}
+	list_add(&c->list, entry);
+
+	if (strlen(c->name) == strlen(override_name) &&
+	    !strcmp(c->name, override_name))
+		clocksource_override = c;
 
 	return 0;
 }
@@ -149,42 +260,35 @@
  */
 int clocksource_register(struct clocksource *c)
 {
-	int ret = 0;
 	unsigned long flags;
+	int ret;
 
 	spin_lock_irqsave(&clocksource_lock, flags);
-	/* check if clocksource is already registered */
-	if (is_registered_source(c)) {
-		printk("register_clocksource: Cannot register %s. "
-		       "Already registered!", c->name);
-		ret = -EBUSY;
-	} else {
-		/* register it */
- 		list_add(&c->list, &clocksource_list);
-		/* scan the registered clocksources, and pick the best one */
+	ret = clocksource_enqueue(c);
+	if (!ret)
 		next_clocksource = select_clocksource();
-	}
 	spin_unlock_irqrestore(&clocksource_lock, flags);
+	if (!ret)
+		clocksource_check_watchdog(c);
 	return ret;
 }
 EXPORT_SYMBOL(clocksource_register);
 
 /**
- * clocksource_reselect - Rescan list for next clocksource
+ * clocksource_change_rating - Change the rating of a registered clocksource
  *
- * A quick helper function to be used if a clocksource changes its
- * rating. Forces the clocksource list to be re-scanned for the best
- * clocksource.
  */
-void clocksource_reselect(void)
+void clocksource_change_rating(struct clocksource *cs, int rating)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&clocksource_lock, flags);
+	list_del(&cs->list);
+	cs->rating = rating;
+	clocksource_enqueue(cs);
 	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
 }
-EXPORT_SYMBOL(clocksource_reselect);
 
 #ifdef CONFIG_SYSFS
 /**
@@ -220,7 +324,11 @@
 static ssize_t sysfs_override_clocksource(struct sys_device *dev,
 					  const char *buf, size_t count)
 {
+	struct clocksource *ovr = NULL;
+	struct list_head *tmp;
 	size_t ret = count;
+	int len;
+
 	/* strings from sysfs write are not 0 terminated! */
 	if (count >= sizeof(override_name))
 		return -EINVAL;
@@ -228,17 +336,32 @@
 	/* strip of \n: */
 	if (buf[count-1] == '\n')
 		count--;
-	if (count < 1)
-		return -EINVAL;
 
 	spin_lock_irq(&clocksource_lock);
 
-	/* copy the name given: */
-	memcpy(override_name, buf, count);
+	if (count > 0)
+		memcpy(override_name, buf, count);
 	override_name[count] = 0;
 
-	/* try to select it: */
-	next_clocksource = select_clocksource();
+	len = strlen(override_name);
+	if (len) {
+		ovr = clocksource_override;
+		/* try to select it: */
+		list_for_each(tmp, &clocksource_list) {
+			struct clocksource *cs;
+
+			cs = list_entry(tmp, struct clocksource, list);
+			if (strlen(cs->name) == len &&
+			    !strcmp(cs->name, override_name))
+				ovr = cs;
+		}
+	}
+
+	/* Reselect, when the override name has changed */
+	if (ovr != clocksource_override) {
+		clocksource_override = ovr;
+		next_clocksource = select_clocksource();
+	}
 
 	spin_unlock_irq(&clocksource_lock);
 
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
index a99b2a6..3be8da8 100644
--- a/kernel/time/jiffies.c
+++ b/kernel/time/jiffies.c
@@ -62,7 +62,6 @@
 	.mask		= 0xffffffff, /*32bits*/
 	.mult		= NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */
 	.shift		= JIFFIES_SHIFT,
-	.is_continuous	= 0, /* tick based, not free running */
 };
 
 static int __init init_jiffies_clocksource(void)
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 3afeaa3..eb12509 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -24,7 +24,7 @@
 
 #define MAX_TICKADJ		500		/* microsecs */
 #define MAX_TICKADJ_SCALED	(((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \
-				  TICK_LENGTH_SHIFT) / HZ)
+				  TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ)
 
 /*
  * phase-lock loop variables
@@ -46,13 +46,17 @@
 
 static void ntp_update_frequency(void)
 {
-	tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT;
-	tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
-	tick_length_base += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
+	u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
+				<< TICK_LENGTH_SHIFT;
+	second_length += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
+	second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
 
-	do_div(tick_length_base, HZ);
+	tick_length_base = second_length;
 
-	tick_nsec = tick_length_base >> TICK_LENGTH_SHIFT;
+	do_div(second_length, HZ);
+	tick_nsec = second_length >> TICK_LENGTH_SHIFT;
+
+	do_div(tick_length_base, NTP_INTERVAL_FREQ);
 }
 
 /**
@@ -162,7 +166,7 @@
 			tick_length -= MAX_TICKADJ_SCALED;
 		} else {
 			tick_length += (s64)(time_adjust * NSEC_PER_USEC /
-					     HZ) << TICK_LENGTH_SHIFT;
+					NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT;
 			time_adjust = 0;
 		}
 	}
@@ -239,7 +243,8 @@
 		    result = -EINVAL;
 		    goto leave;
 		}
-		time_freq = ((s64)txc->freq * NSEC_PER_USEC) >> (SHIFT_USEC - SHIFT_NSEC);
+		time_freq = ((s64)txc->freq * NSEC_PER_USEC)
+				>> (SHIFT_USEC - SHIFT_NSEC);
 	    }
 
 	    if (txc->modes & ADJ_MAXERROR) {
@@ -309,7 +314,8 @@
 		    freq_adj += time_freq;
 		    freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
 		    time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
-		    time_offset = (time_offset / HZ) << SHIFT_UPDATE;
+		    time_offset = (time_offset / NTP_INTERVAL_FREQ)
+		    			<< SHIFT_UPDATE;
 		} /* STA_PLL */
 	    } /* txc->modes & ADJ_OFFSET */
 	    if (txc->modes & ADJ_TICK)
@@ -324,8 +330,10 @@
 	if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
 	    txc->offset	   = save_adjust;
 	else
-	    txc->offset    = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000;
-	txc->freq	   = (time_freq / NSEC_PER_USEC) << (SHIFT_USEC - SHIFT_NSEC);
+	    txc->offset    = shift_right(time_offset, SHIFT_UPDATE)
+	    			* NTP_INTERVAL_FREQ / 1000;
+	txc->freq	   = (time_freq / NSEC_PER_USEC)
+				<< (SHIFT_USEC - SHIFT_NSEC);
 	txc->maxerror	   = time_maxerror;
 	txc->esterror	   = time_esterror;
 	txc->status	   = time_status;
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
new file mode 100644
index 0000000..12b3efe
--- /dev/null
+++ b/kernel/time/tick-broadcast.c
@@ -0,0 +1,480 @@
+/*
+ * linux/kernel/time/tick-broadcast.c
+ *
+ * This file contains functions which emulate a local clock-event
+ * device via a broadcast event source.
+ *
+ * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
+ *
+ * This code is licenced under the GPL version 2. For details see
+ * kernel-base/COPYING.
+ */
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
+#include <linux/profile.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+
+#include "tick-internal.h"
+
+/*
+ * Broadcast support for broken x86 hardware, where the local apic
+ * timer stops in C3 state.
+ */
+
+struct tick_device tick_broadcast_device;
+static cpumask_t tick_broadcast_mask;
+static DEFINE_SPINLOCK(tick_broadcast_lock);
+
+/*
+ * Debugging: see timer_list.c
+ */
+struct tick_device *tick_get_broadcast_device(void)
+{
+	return &tick_broadcast_device;
+}
+
+cpumask_t *tick_get_broadcast_mask(void)
+{
+	return &tick_broadcast_mask;
+}
+
+/*
+ * Start the device in periodic mode
+ */
+static void tick_broadcast_start_periodic(struct clock_event_device *bc)
+{
+	if (bc && bc->mode == CLOCK_EVT_MODE_SHUTDOWN)
+		tick_setup_periodic(bc, 1);
+}
+
+/*
+ * Check, if the device can be utilized as broadcast device:
+ */
+int tick_check_broadcast_device(struct clock_event_device *dev)
+{
+	if (tick_broadcast_device.evtdev ||
+	    (dev->features & CLOCK_EVT_FEAT_C3STOP))
+		return 0;
+
+	clockevents_exchange_device(NULL, dev);
+	tick_broadcast_device.evtdev = dev;
+	if (!cpus_empty(tick_broadcast_mask))
+		tick_broadcast_start_periodic(dev);
+	return 1;
+}
+
+/*
+ * Check, if the device is the broadcast device
+ */
+int tick_is_broadcast_device(struct clock_event_device *dev)
+{
+	return (dev && tick_broadcast_device.evtdev == dev);
+}
+
+/*
+ * Check, if the device is disfunctional and a place holder, which
+ * needs to be handled by the broadcast device.
+ */
+int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+	/*
+	 * Devices might be registered with both periodic and oneshot
+	 * mode disabled. This signals, that the device needs to be
+	 * operated from the broadcast device and is a placeholder for
+	 * the cpu local device.
+	 */
+	if (!tick_device_is_functional(dev)) {
+		dev->event_handler = tick_handle_periodic;
+		cpu_set(cpu, tick_broadcast_mask);
+		tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
+		ret = 1;
+	}
+
+	spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+	return ret;
+}
+
+/*
+ * Broadcast the event to the cpus, which are set in the mask
+ */
+int tick_do_broadcast(cpumask_t mask)
+{
+	int ret = 0, cpu = smp_processor_id();
+	struct tick_device *td;
+
+	/*
+	 * Check, if the current cpu is in the mask
+	 */
+	if (cpu_isset(cpu, mask)) {
+		cpu_clear(cpu, mask);
+		td = &per_cpu(tick_cpu_device, cpu);
+		td->evtdev->event_handler(td->evtdev);
+		ret = 1;
+	}
+
+	if (!cpus_empty(mask)) {
+		/*
+		 * It might be necessary to actually check whether the devices
+		 * have different broadcast functions. For now, just use the
+		 * one of the first device. This works as long as we have this
+		 * misfeature only on x86 (lapic)
+		 */
+		cpu = first_cpu(mask);
+		td = &per_cpu(tick_cpu_device, cpu);
+		td->evtdev->broadcast(mask);
+		ret = 1;
+	}
+	return ret;
+}
+
+/*
+ * Periodic broadcast:
+ * - invoke the broadcast handlers
+ */
+static void tick_do_periodic_broadcast(void)
+{
+	cpumask_t mask;
+
+	spin_lock(&tick_broadcast_lock);
+
+	cpus_and(mask, cpu_online_map, tick_broadcast_mask);
+	tick_do_broadcast(mask);
+
+	spin_unlock(&tick_broadcast_lock);
+}
+
+/*
+ * Event handler for periodic broadcast ticks
+ */
+static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
+{
+	dev->next_event.tv64 = KTIME_MAX;
+
+	tick_do_periodic_broadcast();
+
+	/*
+	 * The device is in periodic mode. No reprogramming necessary:
+	 */
+	if (dev->mode == CLOCK_EVT_MODE_PERIODIC)
+		return;
+
+	/*
+	 * Setup the next period for devices, which do not have
+	 * periodic mode:
+	 */
+	for (;;) {
+		ktime_t next = ktime_add(dev->next_event, tick_period);
+
+		if (!clockevents_program_event(dev, next, ktime_get()))
+			return;
+		tick_do_periodic_broadcast();
+	}
+}
+
+/*
+ * Powerstate information: The system enters/leaves a state, where
+ * affected devices might stop
+ */
+static void tick_do_broadcast_on_off(void *why)
+{
+	struct clock_event_device *bc, *dev;
+	struct tick_device *td;
+	unsigned long flags, *reason = why;
+	int cpu;
+
+	spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+	cpu = smp_processor_id();
+	td = &per_cpu(tick_cpu_device, cpu);
+	dev = td->evtdev;
+	bc = tick_broadcast_device.evtdev;
+
+	/*
+	 * Is the device in broadcast mode forever or is it not
+	 * affected by the powerstate ?
+	 */
+	if (!dev || !tick_device_is_functional(dev) ||
+	    !(dev->features & CLOCK_EVT_FEAT_C3STOP))
+		goto out;
+
+	if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_ON) {
+		if (!cpu_isset(cpu, tick_broadcast_mask)) {
+			cpu_set(cpu, tick_broadcast_mask);
+			if (td->mode == TICKDEV_MODE_PERIODIC)
+				clockevents_set_mode(dev,
+						     CLOCK_EVT_MODE_SHUTDOWN);
+		}
+	} else {
+		if (cpu_isset(cpu, tick_broadcast_mask)) {
+			cpu_clear(cpu, tick_broadcast_mask);
+			if (td->mode == TICKDEV_MODE_PERIODIC)
+				tick_setup_periodic(dev, 0);
+		}
+	}
+
+	if (cpus_empty(tick_broadcast_mask))
+		clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+	else {
+		if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
+			tick_broadcast_start_periodic(bc);
+		else
+			tick_broadcast_setup_oneshot(bc);
+	}
+out:
+	spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+/*
+ * Powerstate information: The system enters/leaves a state, where
+ * affected devices might stop.
+ */
+void tick_broadcast_on_off(unsigned long reason, int *oncpu)
+{
+	int cpu = get_cpu();
+
+	if (cpu == *oncpu)
+		tick_do_broadcast_on_off(&reason);
+	else
+		smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
+					 &reason, 1, 1);
+	put_cpu();
+}
+
+/*
+ * Set the periodic handler depending on broadcast on/off
+ */
+void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast)
+{
+	if (!broadcast)
+		dev->event_handler = tick_handle_periodic;
+	else
+		dev->event_handler = tick_handle_periodic_broadcast;
+}
+
+/*
+ * Remove a CPU from broadcasting
+ */
+void tick_shutdown_broadcast(unsigned int *cpup)
+{
+	struct clock_event_device *bc;
+	unsigned long flags;
+	unsigned int cpu = *cpup;
+
+	spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+	bc = tick_broadcast_device.evtdev;
+	cpu_clear(cpu, tick_broadcast_mask);
+
+	if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) {
+		if (bc && cpus_empty(tick_broadcast_mask))
+			clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+	}
+
+	spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+#ifdef CONFIG_TICK_ONESHOT
+
+static cpumask_t tick_broadcast_oneshot_mask;
+
+/*
+ * Debugging: see timer_list.c
+ */
+cpumask_t *tick_get_broadcast_oneshot_mask(void)
+{
+	return &tick_broadcast_oneshot_mask;
+}
+
+static int tick_broadcast_set_event(ktime_t expires, int force)
+{
+	struct clock_event_device *bc = tick_broadcast_device.evtdev;
+	ktime_t now = ktime_get();
+	int res;
+
+	for(;;) {
+		res = clockevents_program_event(bc, expires, now);
+		if (!res || !force)
+			return res;
+		now = ktime_get();
+		expires = ktime_add(now, ktime_set(0, bc->min_delta_ns));
+	}
+}
+
+/*
+ * Reprogram the broadcast device:
+ *
+ * Called with tick_broadcast_lock held and interrupts disabled.
+ */
+static int tick_broadcast_reprogram(void)
+{
+	ktime_t expires = { .tv64 = KTIME_MAX };
+	struct tick_device *td;
+	int cpu;
+
+	/*
+	 * Find the event which expires next:
+	 */
+	for (cpu = first_cpu(tick_broadcast_oneshot_mask); cpu != NR_CPUS;
+	     cpu = next_cpu(cpu, tick_broadcast_oneshot_mask)) {
+		td = &per_cpu(tick_cpu_device, cpu);
+		if (td->evtdev->next_event.tv64 < expires.tv64)
+			expires = td->evtdev->next_event;
+	}
+
+	if (expires.tv64 == KTIME_MAX)
+		return 0;
+
+	return tick_broadcast_set_event(expires, 0);
+}
+
+/*
+ * Handle oneshot mode broadcasting
+ */
+static void tick_handle_oneshot_broadcast(struct clock_event_device *dev)
+{
+	struct tick_device *td;
+	cpumask_t mask;
+	ktime_t now;
+	int cpu;
+
+	spin_lock(&tick_broadcast_lock);
+again:
+	dev->next_event.tv64 = KTIME_MAX;
+	mask = CPU_MASK_NONE;
+	now = ktime_get();
+	/* Find all expired events */
+	for (cpu = first_cpu(tick_broadcast_oneshot_mask); cpu != NR_CPUS;
+	     cpu = next_cpu(cpu, tick_broadcast_oneshot_mask)) {
+		td = &per_cpu(tick_cpu_device, cpu);
+		if (td->evtdev->next_event.tv64 <= now.tv64)
+			cpu_set(cpu, mask);
+	}
+
+	/*
+	 * Wakeup the cpus which have an expired event. The broadcast
+	 * device is reprogrammed in the return from idle code.
+	 */
+	if (!tick_do_broadcast(mask)) {
+		/*
+		 * The global event did not expire any CPU local
+		 * events. This happens in dyntick mode, as the
+		 * maximum PIT delta is quite small.
+		 */
+		if (tick_broadcast_reprogram())
+			goto again;
+	}
+	spin_unlock(&tick_broadcast_lock);
+}
+
+/*
+ * Powerstate information: The system enters/leaves a state, where
+ * affected devices might stop
+ */
+void tick_broadcast_oneshot_control(unsigned long reason)
+{
+	struct clock_event_device *bc, *dev;
+	struct tick_device *td;
+	unsigned long flags;
+	int cpu;
+
+	spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+	/*
+	 * Periodic mode does not care about the enter/exit of power
+	 * states
+	 */
+	if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
+		goto out;
+
+	bc = tick_broadcast_device.evtdev;
+	cpu = smp_processor_id();
+	td = &per_cpu(tick_cpu_device, cpu);
+	dev = td->evtdev;
+
+	if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
+		goto out;
+
+	if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
+		if (!cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
+			cpu_set(cpu, tick_broadcast_oneshot_mask);
+			clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
+			if (dev->next_event.tv64 < bc->next_event.tv64)
+				tick_broadcast_set_event(dev->next_event, 1);
+		}
+	} else {
+		if (cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
+			cpu_clear(cpu, tick_broadcast_oneshot_mask);
+			clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
+			if (dev->next_event.tv64 != KTIME_MAX)
+				tick_program_event(dev->next_event, 1);
+		}
+	}
+
+out:
+	spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+/**
+ * tick_broadcast_setup_highres - setup the broadcast device for highres
+ */
+void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
+{
+	if (bc->mode != CLOCK_EVT_MODE_ONESHOT) {
+		bc->event_handler = tick_handle_oneshot_broadcast;
+		clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+		bc->next_event.tv64 = KTIME_MAX;
+	}
+}
+
+/*
+ * Select oneshot operating mode for the broadcast device
+ */
+void tick_broadcast_switch_to_oneshot(void)
+{
+	struct clock_event_device *bc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+	tick_broadcast_device.mode = TICKDEV_MODE_ONESHOT;
+	bc = tick_broadcast_device.evtdev;
+	if (bc)
+		tick_broadcast_setup_oneshot(bc);
+	spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+
+/*
+ * Remove a dead CPU from broadcasting
+ */
+void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
+{
+	struct clock_event_device *bc;
+	unsigned long flags;
+	unsigned int cpu = *cpup;
+
+	spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+	bc = tick_broadcast_device.evtdev;
+	cpu_clear(cpu, tick_broadcast_oneshot_mask);
+
+	if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT) {
+		if (bc && cpus_empty(tick_broadcast_oneshot_mask))
+			clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+	}
+
+	spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
+
+#endif
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
new file mode 100644
index 0000000..0986a2b
--- /dev/null
+++ b/kernel/time/tick-common.c
@@ -0,0 +1,347 @@
+/*
+ * linux/kernel/time/tick-common.c
+ *
+ * This file contains the base functions to manage periodic tick
+ * related events.
+ *
+ * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
+ *
+ * This code is licenced under the GPL version 2. For details see
+ * kernel-base/COPYING.
+ */
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
+#include <linux/profile.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+
+#include "tick-internal.h"
+
+/*
+ * Tick devices
+ */
+DEFINE_PER_CPU(struct tick_device, tick_cpu_device);
+/*
+ * Tick next event: keeps track of the tick time
+ */
+ktime_t tick_next_period;
+ktime_t tick_period;
+static int tick_do_timer_cpu = -1;
+DEFINE_SPINLOCK(tick_device_lock);
+
+/*
+ * Debugging: see timer_list.c
+ */
+struct tick_device *tick_get_device(int cpu)
+{
+	return &per_cpu(tick_cpu_device, cpu);
+}
+
+/**
+ * tick_is_oneshot_available - check for a oneshot capable event device
+ */
+int tick_is_oneshot_available(void)
+{
+	struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+
+	return dev && (dev->features & CLOCK_EVT_FEAT_ONESHOT);
+}
+
+/*
+ * Periodic tick
+ */
+static void tick_periodic(int cpu)
+{
+	if (tick_do_timer_cpu == cpu) {
+		write_seqlock(&xtime_lock);
+
+		/* Keep track of the next tick event */
+		tick_next_period = ktime_add(tick_next_period, tick_period);
+
+		do_timer(1);
+		write_sequnlock(&xtime_lock);
+	}
+
+	update_process_times(user_mode(get_irq_regs()));
+	profile_tick(CPU_PROFILING);
+}
+
+/*
+ * Event handler for periodic ticks
+ */
+void tick_handle_periodic(struct clock_event_device *dev)
+{
+	int cpu = smp_processor_id();
+	ktime_t next;
+
+	tick_periodic(cpu);
+
+	if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
+		return;
+	/*
+	 * Setup the next period for devices, which do not have
+	 * periodic mode:
+	 */
+	next = ktime_add(dev->next_event, tick_period);
+	for (;;) {
+		if (!clockevents_program_event(dev, next, ktime_get()))
+			return;
+		tick_periodic(cpu);
+		next = ktime_add(next, tick_period);
+	}
+}
+
+/*
+ * Setup the device for a periodic tick
+ */
+void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
+{
+	tick_set_periodic_handler(dev, broadcast);
+
+	/* Broadcast setup ? */
+	if (!tick_device_is_functional(dev))
+		return;
+
+	if (dev->features & CLOCK_EVT_FEAT_PERIODIC) {
+		clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC);
+	} else {
+		unsigned long seq;
+		ktime_t next;
+
+		do {
+			seq = read_seqbegin(&xtime_lock);
+			next = tick_next_period;
+		} while (read_seqretry(&xtime_lock, seq));
+
+		clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
+
+		for (;;) {
+			if (!clockevents_program_event(dev, next, ktime_get()))
+				return;
+			next = ktime_add(next, tick_period);
+		}
+	}
+}
+
+/*
+ * Setup the tick device
+ */
+static void tick_setup_device(struct tick_device *td,
+			      struct clock_event_device *newdev, int cpu,
+			      cpumask_t cpumask)
+{
+	ktime_t next_event;
+	void (*handler)(struct clock_event_device *) = NULL;
+
+	/*
+	 * First device setup ?
+	 */
+	if (!td->evtdev) {
+		/*
+		 * If no cpu took the do_timer update, assign it to
+		 * this cpu:
+		 */
+		if (tick_do_timer_cpu == -1) {
+			tick_do_timer_cpu = cpu;
+			tick_next_period = ktime_get();
+			tick_period = ktime_set(0, NSEC_PER_SEC / HZ);
+		}
+
+		/*
+		 * Startup in periodic mode first.
+		 */
+		td->mode = TICKDEV_MODE_PERIODIC;
+	} else {
+		handler = td->evtdev->event_handler;
+		next_event = td->evtdev->next_event;
+	}
+
+	td->evtdev = newdev;
+
+	/*
+	 * When the device is not per cpu, pin the interrupt to the
+	 * current cpu:
+	 */
+	if (!cpus_equal(newdev->cpumask, cpumask))
+		irq_set_affinity(newdev->irq, cpumask);
+
+	/*
+	 * When global broadcasting is active, check if the current
+	 * device is registered as a placeholder for broadcast mode.
+	 * This allows us to handle this x86 misfeature in a generic
+	 * way.
+	 */
+	if (tick_device_uses_broadcast(newdev, cpu))
+		return;
+
+	if (td->mode == TICKDEV_MODE_PERIODIC)
+		tick_setup_periodic(newdev, 0);
+	else
+		tick_setup_oneshot(newdev, handler, next_event);
+}
+
+/*
+ * Check, if the new registered device should be used.
+ */
+static int tick_check_new_device(struct clock_event_device *newdev)
+{
+	struct clock_event_device *curdev;
+	struct tick_device *td;
+	int cpu, ret = NOTIFY_OK;
+	unsigned long flags;
+	cpumask_t cpumask;
+
+	spin_lock_irqsave(&tick_device_lock, flags);
+
+	cpu = smp_processor_id();
+	if (!cpu_isset(cpu, newdev->cpumask))
+		goto out;
+
+	td = &per_cpu(tick_cpu_device, cpu);
+	curdev = td->evtdev;
+	cpumask = cpumask_of_cpu(cpu);
+
+	/* cpu local device ? */
+	if (!cpus_equal(newdev->cpumask, cpumask)) {
+
+		/*
+		 * If the cpu affinity of the device interrupt can not
+		 * be set, ignore it.
+		 */
+		if (!irq_can_set_affinity(newdev->irq))
+			goto out_bc;
+
+		/*
+		 * If we have a cpu local device already, do not replace it
+		 * by a non cpu local device
+		 */
+		if (curdev && cpus_equal(curdev->cpumask, cpumask))
+			goto out_bc;
+	}
+
+	/*
+	 * If we have an active device, then check the rating and the oneshot
+	 * feature.
+	 */
+	if (curdev) {
+		/*
+		 * Prefer one shot capable devices !
+		 */
+		if ((curdev->features & CLOCK_EVT_FEAT_ONESHOT) &&
+		    !(newdev->features & CLOCK_EVT_FEAT_ONESHOT))
+			goto out_bc;
+		/*
+		 * Check the rating
+		 */
+		if (curdev->rating >= newdev->rating)
+			goto out_bc;
+	}
+
+	/*
+	 * Replace the eventually existing device by the new
+	 * device. If the current device is the broadcast device, do
+	 * not give it back to the clockevents layer !
+	 */
+	if (tick_is_broadcast_device(curdev)) {
+		clockevents_set_mode(curdev, CLOCK_EVT_MODE_SHUTDOWN);
+		curdev = NULL;
+	}
+	clockevents_exchange_device(curdev, newdev);
+	tick_setup_device(td, newdev, cpu, cpumask);
+	if (newdev->features & CLOCK_EVT_FEAT_ONESHOT)
+		tick_oneshot_notify();
+
+	spin_unlock_irqrestore(&tick_device_lock, flags);
+	return NOTIFY_STOP;
+
+out_bc:
+	/*
+	 * Can the new device be used as a broadcast device ?
+	 */
+	if (tick_check_broadcast_device(newdev))
+		ret = NOTIFY_STOP;
+out:
+	spin_unlock_irqrestore(&tick_device_lock, flags);
+
+	return ret;
+}
+
+/*
+ * Shutdown an event device on a given cpu:
+ *
+ * This is called on a life CPU, when a CPU is dead. So we cannot
+ * access the hardware device itself.
+ * We just set the mode and remove it from the lists.
+ */
+static void tick_shutdown(unsigned int *cpup)
+{
+	struct tick_device *td = &per_cpu(tick_cpu_device, *cpup);
+	struct clock_event_device *dev = td->evtdev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tick_device_lock, flags);
+	td->mode = TICKDEV_MODE_PERIODIC;
+	if (dev) {
+		/*
+		 * Prevent that the clock events layer tries to call
+		 * the set mode function!
+		 */
+		dev->mode = CLOCK_EVT_MODE_UNUSED;
+		clockevents_exchange_device(dev, NULL);
+		td->evtdev = NULL;
+	}
+	spin_unlock_irqrestore(&tick_device_lock, flags);
+}
+
+/*
+ * Notification about clock event devices
+ */
+static int tick_notify(struct notifier_block *nb, unsigned long reason,
+			       void *dev)
+{
+	switch (reason) {
+
+	case CLOCK_EVT_NOTIFY_ADD:
+		return tick_check_new_device(dev);
+
+	case CLOCK_EVT_NOTIFY_BROADCAST_ON:
+	case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
+		tick_broadcast_on_off(reason, dev);
+		break;
+
+	case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
+	case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
+		tick_broadcast_oneshot_control(reason);
+		break;
+
+	case CLOCK_EVT_NOTIFY_CPU_DEAD:
+		tick_shutdown_broadcast_oneshot(dev);
+		tick_shutdown_broadcast(dev);
+		tick_shutdown(dev);
+		break;
+
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block tick_notifier = {
+	.notifier_call = tick_notify,
+};
+
+/**
+ * tick_init - initialize the tick control
+ *
+ * Register the notifier with the clockevents framework
+ */
+void __init tick_init(void)
+{
+	clockevents_register_notifier(&tick_notifier);
+}
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
new file mode 100644
index 0000000..54861a0
--- /dev/null
+++ b/kernel/time/tick-internal.h
@@ -0,0 +1,110 @@
+/*
+ * tick internal variable and functions used by low/high res code
+ */
+DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
+extern spinlock_t tick_device_lock;
+extern ktime_t tick_next_period;
+extern ktime_t tick_period;
+
+extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
+extern void tick_handle_periodic(struct clock_event_device *dev);
+
+/*
+ * NO_HZ / high resolution timer shared code
+ */
+#ifdef CONFIG_TICK_ONESHOT
+extern void tick_setup_oneshot(struct clock_event_device *newdev,
+			       void (*handler)(struct clock_event_device *),
+			       ktime_t nextevt);
+extern int tick_program_event(ktime_t expires, int force);
+extern void tick_oneshot_notify(void);
+extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
+
+# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
+extern void tick_broadcast_oneshot_control(unsigned long reason);
+extern void tick_broadcast_switch_to_oneshot(void);
+extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
+# else /* BROADCAST */
+static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
+{
+	BUG();
+}
+static inline void tick_broadcast_oneshot_control(unsigned long reason) { }
+static inline void tick_broadcast_switch_to_oneshot(void) { }
+static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
+# endif /* !BROADCAST */
+
+#else /* !ONESHOT */
+static inline
+void tick_setup_oneshot(struct clock_event_device *newdev,
+			void (*handler)(struct clock_event_device *),
+			ktime_t nextevt)
+{
+	BUG();
+}
+static inline int tick_program_event(ktime_t expires, int force)
+{
+	return 0;
+}
+static inline void tick_oneshot_notify(void) { }
+static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
+{
+	BUG();
+}
+static inline void tick_broadcast_oneshot_control(unsigned long reason) { }
+static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
+#endif /* !TICK_ONESHOT */
+
+/*
+ * Broadcasting support
+ */
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+extern int tick_do_broadcast(cpumask_t mask);
+
+extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu);
+extern int tick_check_broadcast_device(struct clock_event_device *dev);
+extern int tick_is_broadcast_device(struct clock_event_device *dev);
+extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
+extern void tick_shutdown_broadcast(unsigned int *cpup);
+
+extern void
+tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
+
+#else /* !BROADCAST */
+
+static inline int tick_check_broadcast_device(struct clock_event_device *dev)
+{
+	return 0;
+}
+
+static inline int tick_is_broadcast_device(struct clock_event_device *dev)
+{
+	return 0;
+}
+static inline int tick_device_uses_broadcast(struct clock_event_device *dev,
+					     int cpu)
+{
+	return 0;
+}
+static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
+static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
+static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
+
+/*
+ * Set the periodic handler in non broadcast mode
+ */
+static inline void tick_set_periodic_handler(struct clock_event_device *dev,
+					     int broadcast)
+{
+	dev->event_handler = tick_handle_periodic;
+}
+#endif /* !BROADCAST */
+
+/*
+ * Check, if the device is functional or a dummy for broadcast
+ */
+static inline int tick_device_is_functional(struct clock_event_device *dev)
+{
+	return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
+}
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c
new file mode 100644
index 0000000..2e8b7ff
--- /dev/null
+++ b/kernel/time/tick-oneshot.c
@@ -0,0 +1,84 @@
+/*
+ * linux/kernel/time/tick-oneshot.c
+ *
+ * This file contains functions which manage high resolution tick
+ * related events.
+ *
+ * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
+ *
+ * This code is licenced under the GPL version 2. For details see
+ * kernel-base/COPYING.
+ */
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
+#include <linux/profile.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+
+#include "tick-internal.h"
+
+/**
+ * tick_program_event
+ */
+int tick_program_event(ktime_t expires, int force)
+{
+	struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+	ktime_t now = ktime_get();
+
+	while (1) {
+		int ret = clockevents_program_event(dev, expires, now);
+
+		if (!ret || !force)
+			return ret;
+		now = ktime_get();
+		expires = ktime_add(now, ktime_set(0, dev->min_delta_ns));
+	}
+}
+
+/**
+ * tick_setup_oneshot - setup the event device for oneshot mode (hres or nohz)
+ */
+void tick_setup_oneshot(struct clock_event_device *newdev,
+			void (*handler)(struct clock_event_device *),
+			ktime_t next_event)
+{
+	newdev->event_handler = handler;
+	clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
+	clockevents_program_event(newdev, next_event, ktime_get());
+}
+
+/**
+ * tick_switch_to_oneshot - switch to oneshot mode
+ */
+int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
+{
+	struct tick_device *td = &__get_cpu_var(tick_cpu_device);
+	struct clock_event_device *dev = td->evtdev;
+
+	if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT) ||
+	    !tick_device_is_functional(dev))
+		return -EINVAL;
+
+	td->mode = TICKDEV_MODE_ONESHOT;
+	dev->event_handler = handler;
+	clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
+	tick_broadcast_switch_to_oneshot();
+	return 0;
+}
+
+#ifdef CONFIG_HIGH_RES_TIMERS
+/**
+ * tick_init_highres - switch to high resolution mode
+ *
+ * Called with interrupts disabled.
+ */
+int tick_init_highres(void)
+{
+	return tick_switch_to_oneshot(hrtimer_interrupt);
+}
+#endif
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
new file mode 100644
index 0000000..51556b9
--- /dev/null
+++ b/kernel/time/tick-sched.c
@@ -0,0 +1,567 @@
+/*
+ *  linux/kernel/time/tick-sched.c
+ *
+ *  Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
+ *  Copyright(C) 2006-2007  Timesys Corp., Thomas Gleixner
+ *
+ *  No idle tick implementation for low and high resolution timers
+ *
+ *  Started by: Thomas Gleixner and Ingo Molnar
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/percpu.h>
+#include <linux/profile.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+
+#include <asm/irq_regs.h>
+
+#include "tick-internal.h"
+
+/*
+ * Per cpu nohz control structure
+ */
+static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
+
+/*
+ * The time, when the last jiffy update happened. Protected by xtime_lock.
+ */
+static ktime_t last_jiffies_update;
+
+struct tick_sched *tick_get_tick_sched(int cpu)
+{
+	return &per_cpu(tick_cpu_sched, cpu);
+}
+
+/*
+ * Must be called with interrupts disabled !
+ */
+static void tick_do_update_jiffies64(ktime_t now)
+{
+	unsigned long ticks = 0;
+	ktime_t delta;
+
+	/* Reevalute with xtime_lock held */
+	write_seqlock(&xtime_lock);
+
+	delta = ktime_sub(now, last_jiffies_update);
+	if (delta.tv64 >= tick_period.tv64) {
+
+		delta = ktime_sub(delta, tick_period);
+		last_jiffies_update = ktime_add(last_jiffies_update,
+						tick_period);
+
+		/* Slow path for long timeouts */
+		if (unlikely(delta.tv64 >= tick_period.tv64)) {
+			s64 incr = ktime_to_ns(tick_period);
+
+			ticks = ktime_divns(delta, incr);
+
+			last_jiffies_update = ktime_add_ns(last_jiffies_update,
+							   incr * ticks);
+		}
+		do_timer(++ticks);
+	}
+	write_sequnlock(&xtime_lock);
+}
+
+/*
+ * Initialize and return retrieve the jiffies update.
+ */
+static ktime_t tick_init_jiffy_update(void)
+{
+	ktime_t period;
+
+	write_seqlock(&xtime_lock);
+	/* Did we start the jiffies update yet ? */
+	if (last_jiffies_update.tv64 == 0)
+		last_jiffies_update = tick_next_period;
+	period = last_jiffies_update;
+	write_sequnlock(&xtime_lock);
+	return period;
+}
+
+/*
+ * NOHZ - aka dynamic tick functionality
+ */
+#ifdef CONFIG_NO_HZ
+/*
+ * NO HZ enabled ?
+ */
+static int tick_nohz_enabled __read_mostly  = 1;
+
+/*
+ * Enable / Disable tickless mode
+ */
+static int __init setup_tick_nohz(char *str)
+{
+	if (!strcmp(str, "off"))
+		tick_nohz_enabled = 0;
+	else if (!strcmp(str, "on"))
+		tick_nohz_enabled = 1;
+	else
+		return 0;
+	return 1;
+}
+
+__setup("nohz=", setup_tick_nohz);
+
+/**
+ * tick_nohz_update_jiffies - update jiffies when idle was interrupted
+ *
+ * Called from interrupt entry when the CPU was idle
+ *
+ * In case the sched_tick was stopped on this CPU, we have to check if jiffies
+ * must be updated. Otherwise an interrupt handler could use a stale jiffy
+ * value. We do this unconditionally on any cpu, as we don't know whether the
+ * cpu, which has the update task assigned is in a long sleep.
+ */
+void tick_nohz_update_jiffies(void)
+{
+	int cpu = smp_processor_id();
+	struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+	unsigned long flags;
+	ktime_t now;
+
+	if (!ts->tick_stopped)
+		return;
+
+	cpu_clear(cpu, nohz_cpu_mask);
+	now = ktime_get();
+
+	local_irq_save(flags);
+	tick_do_update_jiffies64(now);
+	local_irq_restore(flags);
+}
+
+/**
+ * tick_nohz_stop_sched_tick - stop the idle tick from the idle task
+ *
+ * When the next event is more than a tick into the future, stop the idle tick
+ * Called either from the idle loop or from irq_exit() when an idle period was
+ * just interrupted by an interrupt which did not cause a reschedule.
+ */
+void tick_nohz_stop_sched_tick(void)
+{
+	unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
+	struct tick_sched *ts;
+	ktime_t last_update, expires, now, delta;
+	int cpu;
+
+	local_irq_save(flags);
+
+	cpu = smp_processor_id();
+	ts = &per_cpu(tick_cpu_sched, cpu);
+
+	if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
+		goto end;
+
+	if (need_resched())
+		goto end;
+
+	cpu = smp_processor_id();
+	if (unlikely(local_softirq_pending()))
+		printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
+		       local_softirq_pending());
+
+	now = ktime_get();
+	/*
+	 * When called from irq_exit we need to account the idle sleep time
+	 * correctly.
+	 */
+	if (ts->tick_stopped) {
+		delta = ktime_sub(now, ts->idle_entrytime);
+		ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
+	}
+
+	ts->idle_entrytime = now;
+	ts->idle_calls++;
+
+	/* Read jiffies and the time when jiffies were updated last */
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		last_update = last_jiffies_update;
+		last_jiffies = jiffies;
+	} while (read_seqretry(&xtime_lock, seq));
+
+	/* Get the next timer wheel timer */
+	next_jiffies = get_next_timer_interrupt(last_jiffies);
+	delta_jiffies = next_jiffies - last_jiffies;
+
+	if (rcu_needs_cpu(cpu))
+		delta_jiffies = 1;
+	/*
+	 * Do not stop the tick, if we are only one off
+	 * or if the cpu is required for rcu
+	 */
+	if (!ts->tick_stopped && delta_jiffies == 1)
+		goto out;
+
+	/* Schedule the tick, if we are at least one jiffie off */
+	if ((long)delta_jiffies >= 1) {
+
+		if (delta_jiffies > 1)
+			cpu_set(cpu, nohz_cpu_mask);
+		/*
+		 * nohz_stop_sched_tick can be called several times before
+		 * the nohz_restart_sched_tick is called. This happens when
+		 * interrupts arrive which do not cause a reschedule. In the
+		 * first call we save the current tick time, so we can restart
+		 * the scheduler tick in nohz_restart_sched_tick.
+		 */
+		if (!ts->tick_stopped) {
+			ts->idle_tick = ts->sched_timer.expires;
+			ts->tick_stopped = 1;
+			ts->idle_jiffies = last_jiffies;
+		}
+		/*
+		 * calculate the expiry time for the next timer wheel
+		 * timer
+		 */
+		expires = ktime_add_ns(last_update, tick_period.tv64 *
+				       delta_jiffies);
+		ts->idle_expires = expires;
+		ts->idle_sleeps++;
+
+		if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
+			hrtimer_start(&ts->sched_timer, expires,
+				      HRTIMER_MODE_ABS);
+			/* Check, if the timer was already in the past */
+			if (hrtimer_active(&ts->sched_timer))
+				goto out;
+		} else if(!tick_program_event(expires, 0))
+				goto out;
+		/*
+		 * We are past the event already. So we crossed a
+		 * jiffie boundary. Update jiffies and raise the
+		 * softirq.
+		 */
+		tick_do_update_jiffies64(ktime_get());
+		cpu_clear(cpu, nohz_cpu_mask);
+	}
+	raise_softirq_irqoff(TIMER_SOFTIRQ);
+out:
+	ts->next_jiffies = next_jiffies;
+	ts->last_jiffies = last_jiffies;
+end:
+	local_irq_restore(flags);
+}
+
+/**
+ * nohz_restart_sched_tick - restart the idle tick from the idle task
+ *
+ * Restart the idle tick when the CPU is woken up from idle
+ */
+void tick_nohz_restart_sched_tick(void)
+{
+	int cpu = smp_processor_id();
+	struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+	unsigned long ticks;
+	ktime_t now, delta;
+
+	if (!ts->tick_stopped)
+		return;
+
+	/* Update jiffies first */
+	now = ktime_get();
+
+	local_irq_disable();
+	tick_do_update_jiffies64(now);
+	cpu_clear(cpu, nohz_cpu_mask);
+
+	/* Account the idle time */
+	delta = ktime_sub(now, ts->idle_entrytime);
+	ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
+
+	/*
+	 * We stopped the tick in idle. Update process times would miss the
+	 * time we slept as update_process_times does only a 1 tick
+	 * accounting. Enforce that this is accounted to idle !
+	 */
+	ticks = jiffies - ts->idle_jiffies;
+	/*
+	 * We might be one off. Do not randomly account a huge number of ticks!
+	 */
+	if (ticks && ticks < LONG_MAX) {
+		add_preempt_count(HARDIRQ_OFFSET);
+		account_system_time(current, HARDIRQ_OFFSET,
+				    jiffies_to_cputime(ticks));
+		sub_preempt_count(HARDIRQ_OFFSET);
+	}
+
+	/*
+	 * Cancel the scheduled timer and restore the tick
+	 */
+	ts->tick_stopped  = 0;
+	hrtimer_cancel(&ts->sched_timer);
+	ts->sched_timer.expires = ts->idle_tick;
+
+	while (1) {
+		/* Forward the time to expire in the future */
+		hrtimer_forward(&ts->sched_timer, now, tick_period);
+
+		if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
+			hrtimer_start(&ts->sched_timer,
+				      ts->sched_timer.expires,
+				      HRTIMER_MODE_ABS);
+			/* Check, if the timer was already in the past */
+			if (hrtimer_active(&ts->sched_timer))
+				break;
+		} else {
+			if (!tick_program_event(ts->sched_timer.expires, 0))
+				break;
+		}
+		/* Update jiffies and reread time */
+		tick_do_update_jiffies64(now);
+		now = ktime_get();
+	}
+	local_irq_enable();
+}
+
+static int tick_nohz_reprogram(struct tick_sched *ts, ktime_t now)
+{
+	hrtimer_forward(&ts->sched_timer, now, tick_period);
+	return tick_program_event(ts->sched_timer.expires, 0);
+}
+
+/*
+ * The nohz low res interrupt handler
+ */
+static void tick_nohz_handler(struct clock_event_device *dev)
+{
+	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+	struct pt_regs *regs = get_irq_regs();
+	ktime_t now = ktime_get();
+
+	dev->next_event.tv64 = KTIME_MAX;
+
+	/* Check, if the jiffies need an update */
+	tick_do_update_jiffies64(now);
+
+	/*
+	 * When we are idle and the tick is stopped, we have to touch
+	 * the watchdog as we might not schedule for a really long
+	 * time. This happens on complete idle SMP systems while
+	 * waiting on the login prompt. We also increment the "start
+	 * of idle" jiffy stamp so the idle accounting adjustment we
+	 * do when we go busy again does not account too much ticks.
+	 */
+	if (ts->tick_stopped) {
+		touch_softlockup_watchdog();
+		ts->idle_jiffies++;
+	}
+
+	update_process_times(user_mode(regs));
+	profile_tick(CPU_PROFILING);
+
+	/* Do not restart, when we are in the idle loop */
+	if (ts->tick_stopped)
+		return;
+
+	while (tick_nohz_reprogram(ts, now)) {
+		now = ktime_get();
+		tick_do_update_jiffies64(now);
+	}
+}
+
+/**
+ * tick_nohz_switch_to_nohz - switch to nohz mode
+ */
+static void tick_nohz_switch_to_nohz(void)
+{
+	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+	ktime_t next;
+
+	if (!tick_nohz_enabled)
+		return;
+
+	local_irq_disable();
+	if (tick_switch_to_oneshot(tick_nohz_handler)) {
+		local_irq_enable();
+		return;
+	}
+
+	ts->nohz_mode = NOHZ_MODE_LOWRES;
+
+	/*
+	 * Recycle the hrtimer in ts, so we can share the
+	 * hrtimer_forward with the highres code.
+	 */
+	hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+	/* Get the next period */
+	next = tick_init_jiffy_update();
+
+	for (;;) {
+		ts->sched_timer.expires = next;
+		if (!tick_program_event(next, 0))
+			break;
+		next = ktime_add(next, tick_period);
+	}
+	local_irq_enable();
+
+	printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n",
+	       smp_processor_id());
+}
+
+#else
+
+static inline void tick_nohz_switch_to_nohz(void) { }
+
+#endif /* NO_HZ */
+
+/*
+ * High resolution timer specific code
+ */
+#ifdef CONFIG_HIGH_RES_TIMERS
+/*
+ * We rearm the timer until we get disabled by the idle code
+ * Called with interrupts disabled and timer->base->cpu_base->lock held.
+ */
+static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
+{
+	struct tick_sched *ts =
+		container_of(timer, struct tick_sched, sched_timer);
+	struct hrtimer_cpu_base *base = timer->base->cpu_base;
+	struct pt_regs *regs = get_irq_regs();
+	ktime_t now = ktime_get();
+
+	/* Check, if the jiffies need an update */
+	tick_do_update_jiffies64(now);
+
+	/*
+	 * Do not call, when we are not in irq context and have
+	 * no valid regs pointer
+	 */
+	if (regs) {
+		/*
+		 * When we are idle and the tick is stopped, we have to touch
+		 * the watchdog as we might not schedule for a really long
+		 * time. This happens on complete idle SMP systems while
+		 * waiting on the login prompt. We also increment the "start of
+		 * idle" jiffy stamp so the idle accounting adjustment we do
+		 * when we go busy again does not account too much ticks.
+		 */
+		if (ts->tick_stopped) {
+			touch_softlockup_watchdog();
+			ts->idle_jiffies++;
+		}
+		/*
+		 * update_process_times() might take tasklist_lock, hence
+		 * drop the base lock. sched-tick hrtimers are per-CPU and
+		 * never accessible by userspace APIs, so this is safe to do.
+		 */
+		spin_unlock(&base->lock);
+		update_process_times(user_mode(regs));
+		profile_tick(CPU_PROFILING);
+		spin_lock(&base->lock);
+	}
+
+	/* Do not restart, when we are in the idle loop */
+	if (ts->tick_stopped)
+		return HRTIMER_NORESTART;
+
+	hrtimer_forward(timer, now, tick_period);
+
+	return HRTIMER_RESTART;
+}
+
+/**
+ * tick_setup_sched_timer - setup the tick emulation timer
+ */
+void tick_setup_sched_timer(void)
+{
+	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+	ktime_t now = ktime_get();
+
+	/*
+	 * Emulate tick processing via per-CPU hrtimers:
+	 */
+	hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+	ts->sched_timer.function = tick_sched_timer;
+	ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
+
+	/* Get the next period */
+	ts->sched_timer.expires = tick_init_jiffy_update();
+
+	for (;;) {
+		hrtimer_forward(&ts->sched_timer, now, tick_period);
+		hrtimer_start(&ts->sched_timer, ts->sched_timer.expires,
+			      HRTIMER_MODE_ABS);
+		/* Check, if the timer was already in the past */
+		if (hrtimer_active(&ts->sched_timer))
+			break;
+		now = ktime_get();
+	}
+
+#ifdef CONFIG_NO_HZ
+	if (tick_nohz_enabled)
+		ts->nohz_mode = NOHZ_MODE_HIGHRES;
+#endif
+}
+
+void tick_cancel_sched_timer(int cpu)
+{
+	struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+
+	if (ts->sched_timer.base)
+		hrtimer_cancel(&ts->sched_timer);
+	ts->tick_stopped = 0;
+	ts->nohz_mode = NOHZ_MODE_INACTIVE;
+}
+#endif /* HIGH_RES_TIMERS */
+
+/**
+ * Async notification about clocksource changes
+ */
+void tick_clock_notify(void)
+{
+	int cpu;
+
+	for_each_possible_cpu(cpu)
+		set_bit(0, &per_cpu(tick_cpu_sched, cpu).check_clocks);
+}
+
+/*
+ * Async notification about clock event changes
+ */
+void tick_oneshot_notify(void)
+{
+	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+
+	set_bit(0, &ts->check_clocks);
+}
+
+/**
+ * Check, if a change happened, which makes oneshot possible.
+ *
+ * Called cyclic from the hrtimer softirq (driven by the timer
+ * softirq) allow_nohz signals, that we can switch into low-res nohz
+ * mode, because high resolution timers are disabled (either compile
+ * or runtime).
+ */
+int tick_check_oneshot_change(int allow_nohz)
+{
+	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+
+	if (!test_and_clear_bit(0, &ts->check_clocks))
+		return 0;
+
+	if (ts->nohz_mode != NOHZ_MODE_INACTIVE)
+		return 0;
+
+	if (!timekeeping_is_continuous() || !tick_is_oneshot_available())
+		return 0;
+
+	if (!allow_nohz)
+		return 1;
+
+	tick_nohz_switch_to_nohz();
+	return 0;
+}
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
new file mode 100644
index 0000000..f82c635
--- /dev/null
+++ b/kernel/time/timer_list.c
@@ -0,0 +1,287 @@
+/*
+ * kernel/time/timer_list.c
+ *
+ * List pending timers
+ *
+ * Copyright(C) 2006, Red Hat, Inc., Ingo Molnar
+ *
+ * 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/proc_fs.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/tick.h>
+
+#include <asm/uaccess.h>
+
+typedef void (*print_fn_t)(struct seq_file *m, unsigned int *classes);
+
+DECLARE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases);
+
+/*
+ * This allows printing both to /proc/timer_list and
+ * to the console (on SysRq-Q):
+ */
+#define SEQ_printf(m, x...)			\
+ do {						\
+	if (m)					\
+		seq_printf(m, x);		\
+	else					\
+		printk(x);			\
+ } while (0)
+
+static void print_name_offset(struct seq_file *m, void *sym)
+{
+	unsigned long addr = (unsigned long)sym;
+	char namebuf[KSYM_NAME_LEN+1];
+	unsigned long size, offset;
+	const char *sym_name;
+	char *modname;
+
+	sym_name = kallsyms_lookup(addr, &size, &offset, &modname, namebuf);
+	if (sym_name)
+		SEQ_printf(m, "%s", sym_name);
+	else
+		SEQ_printf(m, "<%p>", sym);
+}
+
+static void
+print_timer(struct seq_file *m, struct hrtimer *timer, int idx, u64 now)
+{
+#ifdef CONFIG_TIMER_STATS
+	char tmp[TASK_COMM_LEN + 1];
+#endif
+	SEQ_printf(m, " #%d: ", idx);
+	print_name_offset(m, timer);
+	SEQ_printf(m, ", ");
+	print_name_offset(m, timer->function);
+	SEQ_printf(m, ", S:%02lx", timer->state);
+#ifdef CONFIG_TIMER_STATS
+	SEQ_printf(m, ", ");
+	print_name_offset(m, timer->start_site);
+	memcpy(tmp, timer->start_comm, TASK_COMM_LEN);
+	tmp[TASK_COMM_LEN] = 0;
+	SEQ_printf(m, ", %s/%d", tmp, timer->start_pid);
+#endif
+	SEQ_printf(m, "\n");
+	SEQ_printf(m, " # expires at %Ld nsecs [in %Ld nsecs]\n",
+		(unsigned long long)ktime_to_ns(timer->expires),
+		(unsigned long long)(ktime_to_ns(timer->expires) - now));
+}
+
+static void
+print_active_timers(struct seq_file *m, struct hrtimer_clock_base *base,
+		    u64 now)
+{
+	struct hrtimer *timer, tmp;
+	unsigned long next = 0, i;
+	struct rb_node *curr;
+	unsigned long flags;
+
+next_one:
+	i = 0;
+	spin_lock_irqsave(&base->cpu_base->lock, flags);
+
+	curr = base->first;
+	/*
+	 * Crude but we have to do this O(N*N) thing, because
+	 * we have to unlock the base when printing:
+	 */
+	while (curr && i < next) {
+		curr = rb_next(curr);
+		i++;
+	}
+
+	if (curr) {
+
+		timer = rb_entry(curr, struct hrtimer, node);
+		tmp = *timer;
+		spin_unlock_irqrestore(&base->cpu_base->lock, flags);
+
+		print_timer(m, &tmp, i, now);
+		next++;
+		goto next_one;
+	}
+	spin_unlock_irqrestore(&base->cpu_base->lock, flags);
+}
+
+static void
+print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now)
+{
+	SEQ_printf(m, "  .index:      %d\n",
+			base->index);
+	SEQ_printf(m, "  .resolution: %Ld nsecs\n",
+			(unsigned long long)ktime_to_ns(base->resolution));
+	SEQ_printf(m,   "  .get_time:   ");
+	print_name_offset(m, base->get_time);
+	SEQ_printf(m,   "\n");
+#ifdef CONFIG_HIGH_RES_TIMERS
+	SEQ_printf(m, "  .offset:     %Ld nsecs\n",
+			ktime_to_ns(base->offset));
+#endif
+	SEQ_printf(m,   "active timers:\n");
+	print_active_timers(m, base, now);
+}
+
+static void print_cpu(struct seq_file *m, int cpu, u64 now)
+{
+	struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
+	int i;
+
+	SEQ_printf(m, "\ncpu: %d\n", cpu);
+	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
+		SEQ_printf(m, " clock %d:\n", i);
+		print_base(m, cpu_base->clock_base + i, now);
+	}
+#define P(x) \
+	SEQ_printf(m, "  .%-15s: %Ld\n", #x, (u64)(cpu_base->x))
+#define P_ns(x) \
+	SEQ_printf(m, "  .%-15s: %Ld nsecs\n", #x, \
+		(u64)(ktime_to_ns(cpu_base->x)))
+
+#ifdef CONFIG_HIGH_RES_TIMERS
+	P_ns(expires_next);
+	P(hres_active);
+	P(nr_events);
+#endif
+#undef P
+#undef P_ns
+
+#ifdef CONFIG_TICK_ONESHOT
+# define P(x) \
+	SEQ_printf(m, "  .%-15s: %Ld\n", #x, (u64)(ts->x))
+# define P_ns(x) \
+	SEQ_printf(m, "  .%-15s: %Ld nsecs\n", #x, \
+		(u64)(ktime_to_ns(ts->x)))
+	{
+		struct tick_sched *ts = tick_get_tick_sched(cpu);
+		P(nohz_mode);
+		P_ns(idle_tick);
+		P(tick_stopped);
+		P(idle_jiffies);
+		P(idle_calls);
+		P(idle_sleeps);
+		P_ns(idle_entrytime);
+		P_ns(idle_sleeptime);
+		P(last_jiffies);
+		P(next_jiffies);
+		P_ns(idle_expires);
+		SEQ_printf(m, "jiffies: %Ld\n", (u64)jiffies);
+	}
+#endif
+
+#undef P
+#undef P_ns
+}
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+static void
+print_tickdevice(struct seq_file *m, struct tick_device *td)
+{
+	struct clock_event_device *dev = td->evtdev;
+
+	SEQ_printf(m, "\nTick Device: mode:     %d\n", td->mode);
+
+	SEQ_printf(m, "Clock Event Device: ");
+	if (!dev) {
+		SEQ_printf(m, "<NULL>\n");
+		return;
+	}
+	SEQ_printf(m, "%s\n", dev->name);
+	SEQ_printf(m, " max_delta_ns:   %ld\n", dev->max_delta_ns);
+	SEQ_printf(m, " min_delta_ns:   %ld\n", dev->min_delta_ns);
+	SEQ_printf(m, " mult:           %ld\n", dev->mult);
+	SEQ_printf(m, " shift:          %d\n", dev->shift);
+	SEQ_printf(m, " mode:           %d\n", dev->mode);
+	SEQ_printf(m, " next_event:     %Ld nsecs\n",
+		   (unsigned long long) ktime_to_ns(dev->next_event));
+
+	SEQ_printf(m, " set_next_event: ");
+	print_name_offset(m, dev->set_next_event);
+	SEQ_printf(m, "\n");
+
+	SEQ_printf(m, " set_mode:       ");
+	print_name_offset(m, dev->set_mode);
+	SEQ_printf(m, "\n");
+
+	SEQ_printf(m, " event_handler:  ");
+	print_name_offset(m, dev->event_handler);
+	SEQ_printf(m, "\n");
+}
+
+static void timer_list_show_tickdevices(struct seq_file *m)
+{
+	int cpu;
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+	print_tickdevice(m, tick_get_broadcast_device());
+	SEQ_printf(m, "tick_broadcast_mask: %08lx\n",
+		   tick_get_broadcast_mask()->bits[0]);
+#ifdef CONFIG_TICK_ONESHOT
+	SEQ_printf(m, "tick_broadcast_oneshot_mask: %08lx\n",
+		   tick_get_broadcast_oneshot_mask()->bits[0]);
+#endif
+	SEQ_printf(m, "\n");
+#endif
+	for_each_online_cpu(cpu)
+		   print_tickdevice(m, tick_get_device(cpu));
+	SEQ_printf(m, "\n");
+}
+#else
+static void timer_list_show_tickdevices(struct seq_file *m) { }
+#endif
+
+static int timer_list_show(struct seq_file *m, void *v)
+{
+	u64 now = ktime_to_ns(ktime_get());
+	int cpu;
+
+	SEQ_printf(m, "Timer List Version: v0.3\n");
+	SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES);
+	SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now);
+
+	for_each_online_cpu(cpu)
+		print_cpu(m, cpu, now);
+
+	SEQ_printf(m, "\n");
+	timer_list_show_tickdevices(m);
+
+	return 0;
+}
+
+void sysrq_timer_list_show(void)
+{
+	timer_list_show(NULL, NULL);
+}
+
+static int timer_list_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, timer_list_show, NULL);
+}
+
+static struct file_operations timer_list_fops = {
+	.open		= timer_list_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int __init init_timer_list_procfs(void)
+{
+	struct proc_dir_entry *pe;
+
+	pe = create_proc_entry("timer_list", 0644, NULL);
+	if (!pe)
+		return -ENOMEM;
+
+	pe->proc_fops = &timer_list_fops;
+
+	return 0;
+}
+__initcall(init_timer_list_procfs);
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
new file mode 100644
index 0000000..1bc4882
--- /dev/null
+++ b/kernel/time/timer_stats.c
@@ -0,0 +1,411 @@
+/*
+ * kernel/time/timer_stats.c
+ *
+ * Collect timer usage statistics.
+ *
+ * Copyright(C) 2006, Red Hat, Inc., Ingo Molnar
+ * Copyright(C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * timer_stats is based on timer_top, a similar functionality which was part of
+ * Con Kolivas dyntick patch set. It was developed by Daniel Petrini at the
+ * Instituto Nokia de Tecnologia - INdT - Manaus. timer_top's design was based
+ * on dynamic allocation of the statistics entries and linear search based
+ * lookup combined with a global lock, rather than the static array, hash
+ * and per-CPU locking which is used by timer_stats. It was written for the
+ * pre hrtimer kernel code and therefore did not take hrtimers into account.
+ * Nevertheless it provided the base for the timer_stats implementation and
+ * was a helpful source of inspiration. Kudos to Daniel and the Nokia folks
+ * for this effort.
+ *
+ * timer_top.c is
+ *	Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus
+ *	Written by Daniel Petrini <d.pensator@gmail.com>
+ *	timer_top.c was released under the GNU General Public License version 2
+ *
+ * We export the addresses and counting of timer functions being called,
+ * the pid and cmdline from the owner process if applicable.
+ *
+ * Start/stop data collection:
+ * # echo 1[0] >/proc/timer_stats
+ *
+ * Display the information collected so far:
+ * # cat /proc/timer_stats
+ *
+ * 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/proc_fs.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+
+#include <asm/uaccess.h>
+
+/*
+ * This is our basic unit of interest: a timer expiry event identified
+ * by the timer, its start/expire functions and the PID of the task that
+ * started the timer. We count the number of times an event happens:
+ */
+struct entry {
+	/*
+	 * Hash list:
+	 */
+	struct entry		*next;
+
+	/*
+	 * Hash keys:
+	 */
+	void			*timer;
+	void			*start_func;
+	void			*expire_func;
+	pid_t			pid;
+
+	/*
+	 * Number of timeout events:
+	 */
+	unsigned long		count;
+
+	/*
+	 * We save the command-line string to preserve
+	 * this information past task exit:
+	 */
+	char			comm[TASK_COMM_LEN + 1];
+
+} ____cacheline_aligned_in_smp;
+
+/*
+ * Spinlock protecting the tables - not taken during lookup:
+ */
+static DEFINE_SPINLOCK(table_lock);
+
+/*
+ * Per-CPU lookup locks for fast hash lookup:
+ */
+static DEFINE_PER_CPU(spinlock_t, lookup_lock);
+
+/*
+ * Mutex to serialize state changes with show-stats activities:
+ */
+static DEFINE_MUTEX(show_mutex);
+
+/*
+ * Collection status, active/inactive:
+ */
+static int __read_mostly active;
+
+/*
+ * Beginning/end timestamps of measurement:
+ */
+static ktime_t time_start, time_stop;
+
+/*
+ * tstat entry structs only get allocated while collection is
+ * active and never freed during that time - this simplifies
+ * things quite a bit.
+ *
+ * They get freed when a new collection period is started.
+ */
+#define MAX_ENTRIES_BITS	10
+#define MAX_ENTRIES		(1UL << MAX_ENTRIES_BITS)
+
+static unsigned long nr_entries;
+static struct entry entries[MAX_ENTRIES];
+
+static atomic_t overflow_count;
+
+static void reset_entries(void)
+{
+	nr_entries = 0;
+	memset(entries, 0, sizeof(entries));
+	atomic_set(&overflow_count, 0);
+}
+
+static struct entry *alloc_entry(void)
+{
+	if (nr_entries >= MAX_ENTRIES)
+		return NULL;
+
+	return entries + nr_entries++;
+}
+
+/*
+ * The entries are in a hash-table, for fast lookup:
+ */
+#define TSTAT_HASH_BITS		(MAX_ENTRIES_BITS - 1)
+#define TSTAT_HASH_SIZE		(1UL << TSTAT_HASH_BITS)
+#define TSTAT_HASH_MASK		(TSTAT_HASH_SIZE - 1)
+
+#define __tstat_hashfn(entry)						\
+	(((unsigned long)(entry)->timer       ^				\
+	  (unsigned long)(entry)->start_func  ^				\
+	  (unsigned long)(entry)->expire_func ^				\
+	  (unsigned long)(entry)->pid		) & TSTAT_HASH_MASK)
+
+#define tstat_hashentry(entry)	(tstat_hash_table + __tstat_hashfn(entry))
+
+static struct entry *tstat_hash_table[TSTAT_HASH_SIZE] __read_mostly;
+
+static int match_entries(struct entry *entry1, struct entry *entry2)
+{
+	return entry1->timer       == entry2->timer	  &&
+	       entry1->start_func  == entry2->start_func  &&
+	       entry1->expire_func == entry2->expire_func &&
+	       entry1->pid	   == entry2->pid;
+}
+
+/*
+ * Look up whether an entry matching this item is present
+ * in the hash already. Must be called with irqs off and the
+ * lookup lock held:
+ */
+static struct entry *tstat_lookup(struct entry *entry, char *comm)
+{
+	struct entry **head, *curr, *prev;
+
+	head = tstat_hashentry(entry);
+	curr = *head;
+
+	/*
+	 * The fastpath is when the entry is already hashed,
+	 * we do this with the lookup lock held, but with the
+	 * table lock not held:
+	 */
+	while (curr) {
+		if (match_entries(curr, entry))
+			return curr;
+
+		curr = curr->next;
+	}
+	/*
+	 * Slowpath: allocate, set up and link a new hash entry:
+	 */
+	prev = NULL;
+	curr = *head;
+
+	spin_lock(&table_lock);
+	/*
+	 * Make sure we have not raced with another CPU:
+	 */
+	while (curr) {
+		if (match_entries(curr, entry))
+			goto out_unlock;
+
+		prev = curr;
+		curr = curr->next;
+	}
+
+	curr = alloc_entry();
+	if (curr) {
+		*curr = *entry;
+		curr->count = 0;
+		memcpy(curr->comm, comm, TASK_COMM_LEN);
+		if (prev)
+			prev->next = curr;
+		else
+			*head = curr;
+		curr->next = NULL;
+	}
+ out_unlock:
+	spin_unlock(&table_lock);
+
+	return curr;
+}
+
+/**
+ * timer_stats_update_stats - Update the statistics for a timer.
+ * @timer:	pointer to either a timer_list or a hrtimer
+ * @pid:	the pid of the task which set up the timer
+ * @startf:	pointer to the function which did the timer setup
+ * @timerf:	pointer to the timer callback function of the timer
+ * @comm:	name of the process which set up the timer
+ *
+ * When the timer is already registered, then the event counter is
+ * incremented. Otherwise the timer is registered in a free slot.
+ */
+void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
+			      void *timerf, char * comm)
+{
+	/*
+	 * It doesnt matter which lock we take:
+	 */
+	spinlock_t *lock = &per_cpu(lookup_lock, raw_smp_processor_id());
+	struct entry *entry, input;
+	unsigned long flags;
+
+	input.timer = timer;
+	input.start_func = startf;
+	input.expire_func = timerf;
+	input.pid = pid;
+
+	spin_lock_irqsave(lock, flags);
+	if (!active)
+		goto out_unlock;
+
+	entry = tstat_lookup(&input, comm);
+	if (likely(entry))
+		entry->count++;
+	else
+		atomic_inc(&overflow_count);
+
+ out_unlock:
+	spin_unlock_irqrestore(lock, flags);
+}
+
+static void print_name_offset(struct seq_file *m, unsigned long addr)
+{
+	char namebuf[KSYM_NAME_LEN+1];
+	unsigned long size, offset;
+	const char *sym_name;
+	char *modname;
+
+	sym_name = kallsyms_lookup(addr, &size, &offset, &modname, namebuf);
+	if (sym_name)
+		seq_printf(m, "%s", sym_name);
+	else
+		seq_printf(m, "<%p>", (void *)addr);
+}
+
+static int tstats_show(struct seq_file *m, void *v)
+{
+	struct timespec period;
+	struct entry *entry;
+	unsigned long ms;
+	long events = 0;
+	ktime_t time;
+	int i;
+
+	mutex_lock(&show_mutex);
+	/*
+	 * If still active then calculate up to now:
+	 */
+	if (active)
+		time_stop = ktime_get();
+
+	time = ktime_sub(time_stop, time_start);
+
+	period = ktime_to_timespec(time);
+	ms = period.tv_nsec / 1000000;
+
+	seq_puts(m, "Timer Stats Version: v0.1\n");
+	seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms);
+	if (atomic_read(&overflow_count))
+		seq_printf(m, "Overflow: %d entries\n",
+			atomic_read(&overflow_count));
+
+	for (i = 0; i < nr_entries; i++) {
+		entry = entries + i;
+		seq_printf(m, "%4lu, %5d %-16s ",
+				entry->count, entry->pid, entry->comm);
+
+		print_name_offset(m, (unsigned long)entry->start_func);
+		seq_puts(m, " (");
+		print_name_offset(m, (unsigned long)entry->expire_func);
+		seq_puts(m, ")\n");
+
+		events += entry->count;
+	}
+
+	ms += period.tv_sec * 1000;
+	if (!ms)
+		ms = 1;
+
+	if (events && period.tv_sec)
+		seq_printf(m, "%ld total events, %ld.%ld events/sec\n", events,
+			   events / period.tv_sec, events * 1000 / ms);
+	else
+		seq_printf(m, "%ld total events\n", events);
+
+	mutex_unlock(&show_mutex);
+
+	return 0;
+}
+
+/*
+ * After a state change, make sure all concurrent lookup/update
+ * activities have stopped:
+ */
+static void sync_access(void)
+{
+	unsigned long flags;
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		spin_lock_irqsave(&per_cpu(lookup_lock, cpu), flags);
+		/* nothing */
+		spin_unlock_irqrestore(&per_cpu(lookup_lock, cpu), flags);
+	}
+}
+
+static ssize_t tstats_write(struct file *file, const char __user *buf,
+			    size_t count, loff_t *offs)
+{
+	char ctl[2];
+
+	if (count != 2 || *offs)
+		return -EINVAL;
+
+	if (copy_from_user(ctl, buf, count))
+		return -EFAULT;
+
+	mutex_lock(&show_mutex);
+	switch (ctl[0]) {
+	case '0':
+		if (active) {
+			active = 0;
+			time_stop = ktime_get();
+			sync_access();
+		}
+		break;
+	case '1':
+		if (!active) {
+			reset_entries();
+			time_start = ktime_get();
+			active = 1;
+		}
+		break;
+	default:
+		count = -EINVAL;
+	}
+	mutex_unlock(&show_mutex);
+
+	return count;
+}
+
+static int tstats_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, tstats_show, NULL);
+}
+
+static struct file_operations tstats_fops = {
+	.open		= tstats_open,
+	.read		= seq_read,
+	.write		= tstats_write,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+void __init init_timer_stats(void)
+{
+	int cpu;
+
+	for_each_possible_cpu(cpu)
+		spin_lock_init(&per_cpu(lookup_lock, cpu));
+}
+
+static int __init init_tstats_procfs(void)
+{
+	struct proc_dir_entry *pe;
+
+	pe = create_proc_entry("timer_stats", 0644, NULL);
+	if (!pe)
+		return -ENOMEM;
+
+	pe->proc_fops = &tstats_fops;
+
+	return 0;
+}
+__initcall(init_tstats_procfs);
diff --git a/kernel/timer.c b/kernel/timer.c
index c2a8ccf..cb1b86a 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -34,6 +34,8 @@
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
 #include <linux/delay.h>
+#include <linux/tick.h>
+#include <linux/kallsyms.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -85,7 +87,7 @@
  * @j: the time in (absolute) jiffies that should be rounded
  * @cpu: the processor number on which the timeout will happen
  *
- * __round_jiffies rounds an absolute time in the future (in jiffies)
+ * __round_jiffies() rounds an absolute time in the future (in jiffies)
  * up or down to (approximately) full seconds. This is useful for timers
  * for which the exact time they fire does not matter too much, as long as
  * they fire approximately every X seconds.
@@ -98,7 +100,7 @@
  * processors firing at the exact same time, which could lead
  * to lock contention or spurious cache line bouncing.
  *
- * The return value is the rounded version of the "j" parameter.
+ * The return value is the rounded version of the @j parameter.
  */
 unsigned long __round_jiffies(unsigned long j, int cpu)
 {
@@ -142,7 +144,7 @@
  * @j: the time in (relative) jiffies that should be rounded
  * @cpu: the processor number on which the timeout will happen
  *
- * __round_jiffies_relative rounds a time delta  in the future (in jiffies)
+ * __round_jiffies_relative() rounds a time delta  in the future (in jiffies)
  * up or down to (approximately) full seconds. This is useful for timers
  * for which the exact time they fire does not matter too much, as long as
  * they fire approximately every X seconds.
@@ -155,7 +157,7 @@
  * processors firing at the exact same time, which could lead
  * to lock contention or spurious cache line bouncing.
  *
- * The return value is the rounded version of the "j" parameter.
+ * The return value is the rounded version of the @j parameter.
  */
 unsigned long __round_jiffies_relative(unsigned long j, int cpu)
 {
@@ -173,7 +175,7 @@
  * round_jiffies - function to round jiffies to a full second
  * @j: the time in (absolute) jiffies that should be rounded
  *
- * round_jiffies rounds an absolute time in the future (in jiffies)
+ * round_jiffies() rounds an absolute time in the future (in jiffies)
  * up or down to (approximately) full seconds. This is useful for timers
  * for which the exact time they fire does not matter too much, as long as
  * they fire approximately every X seconds.
@@ -182,7 +184,7 @@
  * at the same time, rather than at various times spread out. The goal
  * of this is to have the CPU wake up less, which saves power.
  *
- * The return value is the rounded version of the "j" parameter.
+ * The return value is the rounded version of the @j parameter.
  */
 unsigned long round_jiffies(unsigned long j)
 {
@@ -194,7 +196,7 @@
  * round_jiffies_relative - function to round jiffies to a full second
  * @j: the time in (relative) jiffies that should be rounded
  *
- * round_jiffies_relative rounds a time delta  in the future (in jiffies)
+ * round_jiffies_relative() rounds a time delta  in the future (in jiffies)
  * up or down to (approximately) full seconds. This is useful for timers
  * for which the exact time they fire does not matter too much, as long as
  * they fire approximately every X seconds.
@@ -203,7 +205,7 @@
  * at the same time, rather than at various times spread out. The goal
  * of this is to have the CPU wake up less, which saves power.
  *
- * The return value is the rounded version of the "j" parameter.
+ * The return value is the rounded version of the @j parameter.
  */
 unsigned long round_jiffies_relative(unsigned long j)
 {
@@ -262,6 +264,18 @@
 	list_add_tail(&timer->entry, vec);
 }
 
+#ifdef CONFIG_TIMER_STATS
+void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
+{
+	if (timer->start_site)
+		return;
+
+	timer->start_site = addr;
+	memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
+	timer->start_pid = current->pid;
+}
+#endif
+
 /**
  * init_timer - initialize a timer.
  * @timer: the timer to be initialized
@@ -273,11 +287,16 @@
 {
 	timer->entry.next = NULL;
 	timer->base = __raw_get_cpu_var(tvec_bases);
+#ifdef CONFIG_TIMER_STATS
+	timer->start_site = NULL;
+	timer->start_pid = -1;
+	memset(timer->start_comm, 0, TASK_COMM_LEN);
+#endif
 }
 EXPORT_SYMBOL(init_timer);
 
 static inline void detach_timer(struct timer_list *timer,
-					int clear_pending)
+				int clear_pending)
 {
 	struct list_head *entry = &timer->entry;
 
@@ -324,6 +343,7 @@
 	unsigned long flags;
 	int ret = 0;
 
+	timer_stats_timer_set_start_info(timer);
 	BUG_ON(!timer->function);
 
 	base = lock_timer_base(timer, &flags);
@@ -374,6 +394,7 @@
 	tvec_base_t *base = per_cpu(tvec_bases, cpu);
   	unsigned long flags;
 
+	timer_stats_timer_set_start_info(timer);
   	BUG_ON(timer_pending(timer) || !timer->function);
 	spin_lock_irqsave(&base->lock, flags);
 	timer->base = base;
@@ -387,7 +408,7 @@
  * @timer: the timer to be modified
  * @expires: new timeout in jiffies
  *
- * mod_timer is a more efficient way to update the expire field of an
+ * mod_timer() is a more efficient way to update the expire field of an
  * active timer (if the timer is inactive it will be activated)
  *
  * mod_timer(timer, expires) is equivalent to:
@@ -406,6 +427,7 @@
 {
 	BUG_ON(!timer->function);
 
+	timer_stats_timer_set_start_info(timer);
 	/*
 	 * This is a common optimization triggered by the
 	 * networking code - if the timer is re-modified
@@ -436,6 +458,7 @@
 	unsigned long flags;
 	int ret = 0;
 
+	timer_stats_timer_clear_start_info(timer);
 	if (timer_pending(timer)) {
 		base = lock_timer_base(timer, &flags);
 		if (timer_pending(timer)) {
@@ -490,7 +513,7 @@
  * the timer it also makes sure the handler has finished executing on other
  * CPUs.
  *
- * Synchronization rules: callers must prevent restarting of the timer,
+ * Synchronization rules: Callers must prevent restarting of the timer,
  * otherwise this function is meaningless. It must not be called from
  * interrupt contexts. The caller must not hold locks which would prevent
  * completion of the timer's handler. The timer's handler must not call
@@ -569,6 +592,8 @@
  			fn = timer->function;
  			data = timer->data;
 
+			timer_stats_account_timer(timer);
+
 			set_running_timer(base, timer);
 			detach_timer(timer, 1);
 			spin_unlock_irq(&base->lock);
@@ -591,105 +616,124 @@
 	spin_unlock_irq(&base->lock);
 }
 
-#ifdef CONFIG_NO_IDLE_HZ
+#if defined(CONFIG_NO_IDLE_HZ) || defined(CONFIG_NO_HZ)
 /*
  * Find out when the next timer event is due to happen. This
  * is used on S/390 to stop all activity when a cpus is idle.
  * This functions needs to be called disabled.
  */
-unsigned long next_timer_interrupt(void)
+static unsigned long __next_timer_interrupt(tvec_base_t *base)
 {
-	tvec_base_t *base;
-	struct list_head *list;
+	unsigned long timer_jiffies = base->timer_jiffies;
+	unsigned long expires = timer_jiffies + (LONG_MAX >> 1);
+	int index, slot, array, found = 0;
 	struct timer_list *nte;
-	unsigned long expires;
-	unsigned long hr_expires = MAX_JIFFY_OFFSET;
-	ktime_t hr_delta;
 	tvec_t *varray[4];
-	int i, j;
-
-	hr_delta = hrtimer_get_next_event();
-	if (hr_delta.tv64 != KTIME_MAX) {
-		struct timespec tsdelta;
-		tsdelta = ktime_to_timespec(hr_delta);
-		hr_expires = timespec_to_jiffies(&tsdelta);
-		if (hr_expires < 3)
-			return hr_expires + jiffies;
-	}
-	hr_expires += jiffies;
-
-	base = __get_cpu_var(tvec_bases);
-	spin_lock(&base->lock);
-	expires = base->timer_jiffies + (LONG_MAX >> 1);
-	list = NULL;
 
 	/* Look for timer events in tv1. */
-	j = base->timer_jiffies & TVR_MASK;
+	index = slot = timer_jiffies & TVR_MASK;
 	do {
-		list_for_each_entry(nte, base->tv1.vec + j, entry) {
+		list_for_each_entry(nte, base->tv1.vec + slot, entry) {
+			found = 1;
 			expires = nte->expires;
-			if (j < (base->timer_jiffies & TVR_MASK))
-				list = base->tv2.vec + (INDEX(0));
-			goto found;
+			/* Look at the cascade bucket(s)? */
+			if (!index || slot < index)
+				goto cascade;
+			return expires;
 		}
-		j = (j + 1) & TVR_MASK;
-	} while (j != (base->timer_jiffies & TVR_MASK));
+		slot = (slot + 1) & TVR_MASK;
+	} while (slot != index);
+
+cascade:
+	/* Calculate the next cascade event */
+	if (index)
+		timer_jiffies += TVR_SIZE - index;
+	timer_jiffies >>= TVR_BITS;
 
 	/* Check tv2-tv5. */
 	varray[0] = &base->tv2;
 	varray[1] = &base->tv3;
 	varray[2] = &base->tv4;
 	varray[3] = &base->tv5;
-	for (i = 0; i < 4; i++) {
-		j = INDEX(i);
+
+	for (array = 0; array < 4; array++) {
+		tvec_t *varp = varray[array];
+
+		index = slot = timer_jiffies & TVN_MASK;
 		do {
-			if (list_empty(varray[i]->vec + j)) {
-				j = (j + 1) & TVN_MASK;
-				continue;
-			}
-			list_for_each_entry(nte, varray[i]->vec + j, entry)
+			list_for_each_entry(nte, varp->vec + slot, entry) {
+				found = 1;
 				if (time_before(nte->expires, expires))
 					expires = nte->expires;
-			if (j < (INDEX(i)) && i < 3)
-				list = varray[i + 1]->vec + (INDEX(i + 1));
-			goto found;
-		} while (j != (INDEX(i)));
+			}
+			/*
+			 * Do we still search for the first timer or are
+			 * we looking up the cascade buckets ?
+			 */
+			if (found) {
+				/* Look at the cascade bucket(s)? */
+				if (!index || slot < index)
+					break;
+				return expires;
+			}
+			slot = (slot + 1) & TVN_MASK;
+		} while (slot != index);
+
+		if (index)
+			timer_jiffies += TVN_SIZE - index;
+		timer_jiffies >>= TVN_BITS;
 	}
-found:
-	if (list) {
-		/*
-		 * The search wrapped. We need to look at the next list
-		 * from next tv element that would cascade into tv element
-		 * where we found the timer element.
-		 */
-		list_for_each_entry(nte, list, entry) {
-			if (time_before(nte->expires, expires))
-				expires = nte->expires;
-		}
-	}
-	spin_unlock(&base->lock);
-
-	/*
-	 * It can happen that other CPUs service timer IRQs and increment
-	 * jiffies, but we have not yet got a local timer tick to process
-	 * the timer wheels.  In that case, the expiry time can be before
-	 * jiffies, but since the high-resolution timer here is relative to
-	 * jiffies, the default expression when high-resolution timers are
-	 * not active,
-	 *
-	 *   time_before(MAX_JIFFY_OFFSET + jiffies, expires)
-	 *
-	 * would falsely evaluate to true.  If that is the case, just
-	 * return jiffies so that we can immediately fire the local timer
-	 */
-	if (time_before(expires, jiffies))
-		return jiffies;
-
-	if (time_before(hr_expires, expires))
-		return hr_expires;
-
 	return expires;
 }
+
+/*
+ * Check, if the next hrtimer event is before the next timer wheel
+ * event:
+ */
+static unsigned long cmp_next_hrtimer_event(unsigned long now,
+					    unsigned long expires)
+{
+	ktime_t hr_delta = hrtimer_get_next_event();
+	struct timespec tsdelta;
+
+	if (hr_delta.tv64 == KTIME_MAX)
+		return expires;
+
+	if (hr_delta.tv64 <= TICK_NSEC)
+		return now;
+
+	tsdelta = ktime_to_timespec(hr_delta);
+	now += timespec_to_jiffies(&tsdelta);
+	if (time_before(now, expires))
+		return now;
+	return expires;
+}
+
+/**
+ * next_timer_interrupt - return the jiffy of the next pending timer
+ */
+unsigned long get_next_timer_interrupt(unsigned long now)
+{
+	tvec_base_t *base = __get_cpu_var(tvec_bases);
+	unsigned long expires;
+
+	spin_lock(&base->lock);
+	expires = __next_timer_interrupt(base);
+	spin_unlock(&base->lock);
+
+	if (time_before_eq(expires, now))
+		return now;
+
+	return cmp_next_hrtimer_event(now, expires);
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+unsigned long next_timer_interrupt(void)
+{
+	return get_next_timer_interrupt(jiffies);
+}
+#endif
+
 #endif
 
 /******************************************************************/
@@ -832,32 +876,35 @@
  *
  * Accumulates current time interval and initializes new clocksource
  */
-static int change_clocksource(void)
+static void change_clocksource(void)
 {
 	struct clocksource *new;
 	cycle_t now;
 	u64 nsec;
-	new = clocksource_get_next();
-	if (clock != new) {
-		now = clocksource_read(new);
-		nsec =  __get_nsec_offset();
-		timespec_add_ns(&xtime, nsec);
 
-		clock = new;
-		clock->cycle_last = now;
-		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
-		       clock->name);
-		return 1;
-	} else if (clock->update_callback) {
-		return clock->update_callback();
-	}
-	return 0;
+	new = clocksource_get_next();
+
+	if (clock == new)
+		return;
+
+	now = clocksource_read(new);
+	nsec =  __get_nsec_offset();
+	timespec_add_ns(&xtime, nsec);
+
+	clock = new;
+	clock->cycle_last = now;
+
+	clock->error = 0;
+	clock->xtime_nsec = 0;
+	clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+
+	tick_clock_notify();
+
+	printk(KERN_INFO "Time: %s clocksource has been installed.\n",
+	       clock->name);
 }
 #else
-static inline int change_clocksource(void)
-{
-	return 0;
-}
+static inline void change_clocksource(void) { }
 #endif
 
 /**
@@ -871,33 +918,56 @@
 	do {
 		seq = read_seqbegin(&xtime_lock);
 
-		ret = clock->is_continuous;
+		ret = clock->flags & CLOCK_SOURCE_VALID_FOR_HRES;
 
 	} while (read_seqretry(&xtime_lock, seq));
 
 	return ret;
 }
 
+/**
+ * read_persistent_clock -  Return time in seconds from the persistent clock.
+ *
+ * Weak dummy function for arches that do not yet support it.
+ * Returns seconds from epoch using the battery backed persistent clock.
+ * Returns zero if unsupported.
+ *
+ *  XXX - Do be sure to remove it once all arches implement it.
+ */
+unsigned long __attribute__((weak)) read_persistent_clock(void)
+{
+	return 0;
+}
+
 /*
  * timekeeping_init - Initializes the clocksource and common timekeeping values
  */
 void __init timekeeping_init(void)
 {
 	unsigned long flags;
+	unsigned long sec = read_persistent_clock();
 
 	write_seqlock_irqsave(&xtime_lock, flags);
 
 	ntp_clear();
 
 	clock = clocksource_get_next();
-	clocksource_calculate_interval(clock, tick_nsec);
+	clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
 	clock->cycle_last = clocksource_read(clock);
 
+	xtime.tv_sec = sec;
+	xtime.tv_nsec = 0;
+	set_normalized_timespec(&wall_to_monotonic,
+		-xtime.tv_sec, -xtime.tv_nsec);
+
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 }
 
-
+/* flag for if timekeeping is suspended */
 static int timekeeping_suspended;
+/* time in seconds when suspend began */
+static unsigned long timekeeping_suspend_time;
+
 /**
  * timekeeping_resume - Resumes the generic timekeeping subsystem.
  * @dev:	unused
@@ -909,13 +979,26 @@
 static int timekeeping_resume(struct sys_device *dev)
 {
 	unsigned long flags;
+	unsigned long now = read_persistent_clock();
 
 	write_seqlock_irqsave(&xtime_lock, flags);
-	/* restart the last cycle value */
+
+	if (now && (now > timekeeping_suspend_time)) {
+		unsigned long sleep_length = now - timekeeping_suspend_time;
+
+		xtime.tv_sec += sleep_length;
+		wall_to_monotonic.tv_sec -= sleep_length;
+	}
+	/* re-base the last cycle value */
 	clock->cycle_last = clocksource_read(clock);
 	clock->error = 0;
 	timekeeping_suspended = 0;
 	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	touch_softlockup_watchdog();
+	/* Resume hrtimers */
+	clock_was_set();
+
 	return 0;
 }
 
@@ -925,6 +1008,7 @@
 
 	write_seqlock_irqsave(&xtime_lock, flags);
 	timekeeping_suspended = 1;
+	timekeeping_suspend_time = read_persistent_clock();
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 	return 0;
 }
@@ -1089,11 +1173,8 @@
 	clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
 
 	/* check to see if there is a new clocksource to use */
-	if (change_clocksource()) {
-		clock->error = 0;
-		clock->xtime_nsec = 0;
-		clocksource_calculate_interval(clock, tick_nsec);
-	}
+	change_clocksource();
+	update_vsyscall(&xtime, clock);
 }
 
 /*
@@ -1162,11 +1243,9 @@
  * This read-write spinlock protects us from races in SMP while
  * playing with xtime and avenrun.
  */
-#ifndef ARCH_HAVE_XTIME_LOCK
-__cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
+__attribute__((weak)) __cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
 
 EXPORT_SYMBOL(xtime_lock);
-#endif
 
 /*
  * This function runs timers and the timer-tq in bottom half context.
@@ -1175,7 +1254,8 @@
 {
 	tvec_base_t *base = __get_cpu_var(tvec_bases);
 
- 	hrtimer_run_queues();
+	hrtimer_run_queues();
+
 	if (time_after_eq(jiffies, base->timer_jiffies))
 		__run_timers(base);
 }
@@ -1392,17 +1472,16 @@
 }
 
 /**
- * sys_sysinfo - fill in sysinfo struct
+ * do_sysinfo - fill in sysinfo struct
  * @info: pointer to buffer to fill
  */ 
-asmlinkage long sys_sysinfo(struct sysinfo __user *info)
+int do_sysinfo(struct sysinfo *info)
 {
-	struct sysinfo val;
 	unsigned long mem_total, sav_total;
 	unsigned int mem_unit, bitcount;
 	unsigned long seq;
 
-	memset((char *)&val, 0, sizeof(struct sysinfo));
+	memset(info, 0, sizeof(struct sysinfo));
 
 	do {
 		struct timespec tp;
@@ -1422,17 +1501,17 @@
 			tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC;
 			tp.tv_sec++;
 		}
-		val.uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0);
+		info->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0);
 
-		val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
-		val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
-		val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
+		info->loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
+		info->loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
+		info->loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
 
-		val.procs = nr_threads;
+		info->procs = nr_threads;
 	} while (read_seqretry(&xtime_lock, seq));
 
-	si_meminfo(&val);
-	si_swapinfo(&val);
+	si_meminfo(info);
+	si_swapinfo(info);
 
 	/*
 	 * If the sum of all the available memory (i.e. ram + swap)
@@ -1443,11 +1522,11 @@
 	 *  -Erik Andersen <andersee@debian.org>
 	 */
 
-	mem_total = val.totalram + val.totalswap;
-	if (mem_total < val.totalram || mem_total < val.totalswap)
+	mem_total = info->totalram + info->totalswap;
+	if (mem_total < info->totalram || mem_total < info->totalswap)
 		goto out;
 	bitcount = 0;
-	mem_unit = val.mem_unit;
+	mem_unit = info->mem_unit;
 	while (mem_unit > 1) {
 		bitcount++;
 		mem_unit >>= 1;
@@ -1459,22 +1538,31 @@
 
 	/*
 	 * If mem_total did not overflow, multiply all memory values by
-	 * val.mem_unit and set it to 1.  This leaves things compatible
+	 * info->mem_unit and set it to 1.  This leaves things compatible
 	 * with 2.2.x, and also retains compatibility with earlier 2.4.x
 	 * kernels...
 	 */
 
-	val.mem_unit = 1;
-	val.totalram <<= bitcount;
-	val.freeram <<= bitcount;
-	val.sharedram <<= bitcount;
-	val.bufferram <<= bitcount;
-	val.totalswap <<= bitcount;
-	val.freeswap <<= bitcount;
-	val.totalhigh <<= bitcount;
-	val.freehigh <<= bitcount;
+	info->mem_unit = 1;
+	info->totalram <<= bitcount;
+	info->freeram <<= bitcount;
+	info->sharedram <<= bitcount;
+	info->bufferram <<= bitcount;
+	info->totalswap <<= bitcount;
+	info->freeswap <<= bitcount;
+	info->totalhigh <<= bitcount;
+	info->freehigh <<= bitcount;
 
- out:
+out:
+	return 0;
+}
+
+asmlinkage long sys_sysinfo(struct sysinfo __user *info)
+{
+	struct sysinfo val;
+
+	do_sysinfo(&val);
+
 	if (copy_to_user(info, &val, sizeof(struct sysinfo)))
 		return -EFAULT;
 
@@ -1613,6 +1701,8 @@
 	int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
 				(void *)(long)smp_processor_id());
 
+	init_timer_stats();
+
 	BUG_ON(err == NOTIFY_BAD);
 	register_cpu_notifier(&timers_nb);
 	open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
@@ -1624,7 +1714,7 @@
 static struct time_interpolator *time_interpolator_list __read_mostly;
 static DEFINE_SPINLOCK(time_interpolator_lock);
 
-static inline u64 time_interpolator_get_cycles(unsigned int src)
+static inline cycles_t time_interpolator_get_cycles(unsigned int src)
 {
 	unsigned long (*x)(void);
 
@@ -1650,8 +1740,8 @@
 
 	if (time_interpolator->jitter)
 	{
-		u64 lcycle;
-		u64 now;
+		cycles_t lcycle;
+		cycles_t now;
 
 		do {
 			lcycle = time_interpolator->last_cycle;
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index baacc36..658f638 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -22,8 +22,6 @@
 #include <linux/acct.h>
 #include <linux/jiffies.h>
 
-
-#define USEC_PER_TICK	(USEC_PER_SEC/HZ)
 /*
  * fill in basic accounting fields
  */
diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c
new file mode 100644
index 0000000..f22b9db
--- /dev/null
+++ b/kernel/utsname_sysctl.c
@@ -0,0 +1,146 @@
+/*
+ *  Copyright (C) 2007
+ *
+ *  Author: Eric Biederman <ebiederm@xmision.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, version 2 of the
+ *  License.
+ */
+
+#include <linux/module.h>
+#include <linux/uts.h>
+#include <linux/utsname.h>
+#include <linux/version.h>
+#include <linux/sysctl.h>
+
+static void *get_uts(ctl_table *table, int write)
+{
+	char *which = table->data;
+#ifdef CONFIG_UTS_NS
+	struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
+	which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
+#endif
+	if (!write)
+		down_read(&uts_sem);
+	else
+		down_write(&uts_sem);
+	return which;
+}
+
+static void put_uts(ctl_table *table, int write, void *which)
+{
+	if (!write)
+		up_read(&uts_sem);
+	else
+		up_write(&uts_sem);
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ *	Special case of dostring for the UTS structure. This has locks
+ *	to observe. Should this be in kernel/sys.c ????
+ */
+static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
+		  void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table uts_table;
+	int r;
+	memcpy(&uts_table, table, sizeof(uts_table));
+	uts_table.data = get_uts(table, write);
+	r = proc_dostring(&uts_table,write,filp,buffer,lenp, ppos);
+	put_uts(table, write, uts_table.data);
+	return r;
+}
+#else
+#define proc_do_uts_string NULL
+#endif
+
+
+#ifdef CONFIG_SYSCTL_SYSCALL
+/* The generic string strategy routine: */
+static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
+		  void __user *oldval, size_t __user *oldlenp,
+		  void __user *newval, size_t newlen)
+{
+	struct ctl_table uts_table;
+	int r, write;
+	write = newval && newlen;
+	memcpy(&uts_table, table, sizeof(uts_table));
+	uts_table.data = get_uts(table, write);
+	r = sysctl_string(&uts_table, name, nlen,
+		oldval, oldlenp, newval, newlen);
+	put_uts(table, write, uts_table.data);
+	return r;
+}
+#else
+#define sysctl_uts_string NULL
+#endif
+
+static struct ctl_table uts_kern_table[] = {
+	{
+		.ctl_name	= KERN_OSTYPE,
+		.procname	= "ostype",
+		.data		= init_uts_ns.name.sysname,
+		.maxlen		= sizeof(init_uts_ns.name.sysname),
+		.mode		= 0444,
+		.proc_handler	= proc_do_uts_string,
+		.strategy	= sysctl_uts_string,
+	},
+	{
+		.ctl_name	= KERN_OSRELEASE,
+		.procname	= "osrelease",
+		.data		= init_uts_ns.name.release,
+		.maxlen		= sizeof(init_uts_ns.name.release),
+		.mode		= 0444,
+		.proc_handler	= proc_do_uts_string,
+		.strategy	= sysctl_uts_string,
+	},
+	{
+		.ctl_name	= KERN_VERSION,
+		.procname	= "version",
+		.data		= init_uts_ns.name.version,
+		.maxlen		= sizeof(init_uts_ns.name.version),
+		.mode		= 0444,
+		.proc_handler	= proc_do_uts_string,
+		.strategy	= sysctl_uts_string,
+	},
+	{
+		.ctl_name	= KERN_NODENAME,
+		.procname	= "hostname",
+		.data		= init_uts_ns.name.nodename,
+		.maxlen		= sizeof(init_uts_ns.name.nodename),
+		.mode		= 0644,
+		.proc_handler	= proc_do_uts_string,
+		.strategy	= sysctl_uts_string,
+	},
+	{
+		.ctl_name	= KERN_DOMAINNAME,
+		.procname	= "domainname",
+		.data		= init_uts_ns.name.domainname,
+		.maxlen		= sizeof(init_uts_ns.name.domainname),
+		.mode		= 0644,
+		.proc_handler	= proc_do_uts_string,
+		.strategy	= sysctl_uts_string,
+	},
+	{}
+};
+
+static struct ctl_table uts_root_table[] = {
+	{
+		.ctl_name	= CTL_KERN,
+		.procname	= "kernel",
+		.mode		= 0555,
+		.child		= uts_kern_table,
+	},
+	{}
+};
+
+static int __init utsname_sysctl_init(void)
+{
+	register_sysctl_table(uts_root_table);
+	return 0;
+}
+
+__initcall(utsname_sysctl_init);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index a3da07c..b6fa5e6 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -218,7 +218,7 @@
 }
 EXPORT_SYMBOL_GPL(queue_work);
 
-static void delayed_work_timer_fn(unsigned long __data)
+void delayed_work_timer_fn(unsigned long __data)
 {
 	struct delayed_work *dwork = (struct delayed_work *)__data;
 	struct workqueue_struct *wq = get_wq_data(&dwork->work);
@@ -245,6 +245,7 @@
 	struct timer_list *timer = &dwork->timer;
 	struct work_struct *work = &dwork->work;
 
+	timer_stats_timer_set_start_info(timer);
 	if (delay == 0)
 		return queue_work(wq, work);
 
@@ -593,8 +594,10 @@
  * After waiting for a given time this puts a job in the kernel-global
  * workqueue.
  */
-int fastcall schedule_delayed_work(struct delayed_work *dwork, unsigned long delay)
+int fastcall schedule_delayed_work(struct delayed_work *dwork,
+					unsigned long delay)
 {
+	timer_stats_timer_set_start_info(&dwork->timer);
 	return queue_delayed_work(keventd_wq, dwork, delay);
 }
 EXPORT_SYMBOL(schedule_delayed_work);
@@ -656,8 +659,7 @@
 EXPORT_SYMBOL(flush_scheduled_work);
 
 /**
- * cancel_rearming_delayed_workqueue - reliably kill off a delayed
- *			work whose handler rearms the delayed work.
+ * cancel_rearming_delayed_workqueue - reliably kill off a delayed work whose handler rearms the delayed work.
  * @wq:   the controlling workqueue structure
  * @dwork: the delayed work struct
  */
@@ -670,8 +672,7 @@
 EXPORT_SYMBOL(cancel_rearming_delayed_workqueue);
 
 /**
- * cancel_rearming_delayed_work - reliably kill off a delayed keventd
- *			work whose handler rearms the delayed work.
+ * cancel_rearming_delayed_work - reliably kill off a delayed keventd work whose handler rearms the delayed work.
  * @dwork: the delayed work struct
  */
 void cancel_rearming_delayed_work(struct delayed_work *dwork)
diff --git a/lib/Kconfig b/lib/Kconfig
index 9b03581..3842499 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -101,9 +101,14 @@
 config PLIST
 	boolean
 
-config IOMAP_COPY
+config HAS_IOMEM
 	boolean
-	depends on !UML
+	depends on !NO_IOMEM
+	default y
+
+config HAS_IOPORT
+	boolean
+	depends on HAS_IOMEM && !NO_IOPORT
 	default y
 
 endmenu
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 5c268187..3f3e740 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -77,6 +77,15 @@
 	  Say Y here if you are developing drivers or trying to debug and
 	  identify kernel problems.
 
+config DEBUG_SHIRQ
+	bool "Debug shared IRQ handlers"
+	depends on DEBUG_KERNEL && GENERIC_HARDIRQS
+	help
+	  Enable this to generate a spurious interrupt as soon as a shared
+	  interrupt handler is registered, and just before one is deregistered.
+	  Drivers ought to be able to handle interrupts coming in at those
+	  points; some don't and need to be caught.
+
 config LOG_BUF_SHIFT
 	int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
 	range 12 21
@@ -125,6 +134,17 @@
 	  application, you can say N to avoid the very slight overhead
 	  this adds.
 
+config TIMER_STATS
+	bool "Collect kernel timers statistics"
+	depends on DEBUG_KERNEL && PROC_FS
+	help
+	  If you say Y here, additional code will be inserted into the
+	  timer routines to collect statistics about kernel timers being
+	  reprogrammed. The statistics can be read from /proc/timer_stats.
+	  The statistics collection is started by writing 1 to /proc/timer_stats,
+	  writing 0 stops it. This feature is useful to collect information
+	  about timer usage patterns in kernel and userspace.
+
 config DEBUG_SLAB
 	bool "Debug slab memory allocations"
 	depends on DEBUG_KERNEL && SLAB
@@ -181,19 +201,11 @@
 	 This feature allows mutex semantics violations to be detected and
 	 reported.
 
-config DEBUG_RWSEMS
-	bool "RW-sem debugging: basic checks"
-	depends on DEBUG_KERNEL
-	help
-	 This feature allows read-write semaphore semantics violations to
-	 be detected and reported.
-
 config DEBUG_LOCK_ALLOC
 	bool "Lock debugging: detect incorrect freeing of live locks"
 	depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
 	select DEBUG_SPINLOCK
 	select DEBUG_MUTEXES
-	select DEBUG_RWSEMS
 	select LOCKDEP
 	help
 	 This feature will check whether any held lock (spinlock, rwlock,
@@ -209,7 +221,6 @@
 	select LOCKDEP
 	select DEBUG_SPINLOCK
 	select DEBUG_MUTEXES
-	select DEBUG_RWSEMS
 	select DEBUG_LOCK_ALLOC
 	default n
 	help
@@ -400,8 +411,6 @@
 config FAULT_INJECTION
 	bool "Fault-injection framework"
 	depends on DEBUG_KERNEL
-	depends on STACKTRACE
-	select FRAME_POINTER
 	help
 	  Provide fault-injection framework.
 	  For more details, see Documentation/fault-injection/.
@@ -429,3 +438,11 @@
 	depends on FAULT_INJECTION && SYSFS && DEBUG_FS
 	help
 	  Enable configuration of fault-injection capabilities via debugfs.
+
+config FAULT_INJECTION_STACKTRACE_FILTER
+	bool "stacktrace filter for fault-injection capabilities"
+	depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT
+	select STACKTRACE
+	select FRAME_POINTER
+	help
+	  Provide stacktrace filter for fault-injection capabilities
diff --git a/lib/Makefile b/lib/Makefile
index 77b4bad..992a39e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -3,7 +3,7 @@
 #
 
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
-	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
+	 rbtree.o radix-tree.o dump_stack.o \
 	 idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
 	 sha1.o irq_regs.o reciprocal_div.o
 
@@ -12,14 +12,15 @@
 
 lib-y	+= kobject.o kref.o kobject_uevent.o klist.o
 
-obj-y += sort.o parser.o halfmd4.o debug_locks.o random32.o
+obj-y += sort.o parser.o halfmd4.o debug_locks.o random32.o bust_spinlocks.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
 CFLAGS_kobject_uevent.o += -DDEBUG
 endif
 
-obj-$(CONFIG_IOMAP_COPY) += iomap_copy.o
+obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
+obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
@@ -41,7 +42,6 @@
 obj-$(CONFIG_CRC16)	+= crc16.o
 obj-$(CONFIG_CRC32)	+= crc32.o
 obj-$(CONFIG_LIBCRC32C)	+= libcrc32c.o
-obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
 obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 037fa9a..ee6e58f 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -95,7 +95,7 @@
 }
 EXPORT_SYMBOL(__bitmap_complement);
 
-/*
+/**
  * __bitmap_shift_right - logical right shift of the bits in a bitmap
  *   @dst - destination bitmap
  *   @src - source bitmap
@@ -139,7 +139,7 @@
 EXPORT_SYMBOL(__bitmap_shift_right);
 
 
-/*
+/**
  * __bitmap_shift_left - logical left shift of the bits in a bitmap
  *   @dst - destination bitmap
  *   @src - source bitmap
@@ -529,7 +529,7 @@
 }
 EXPORT_SYMBOL(bitmap_parselist);
 
-/*
+/**
  * bitmap_pos_to_ord(buf, pos, bits)
  *	@buf: pointer to a bitmap
  *	@pos: a bit position in @buf (0 <= @pos < @bits)
@@ -804,7 +804,7 @@
  *	@pos: beginning of bit region to release
  *	@order: region size (log base 2 of number of bits) to release
  *
- * This is the complement to __bitmap_find_free_region and releases
+ * This is the complement to __bitmap_find_free_region() and releases
  * the found region (by clearing it in the bitmap).
  *
  * No return value.
diff --git a/lib/bust_spinlocks.c b/lib/bust_spinlocks.c
index a2055bc..accb356 100644
--- a/lib/bust_spinlocks.c
+++ b/lib/bust_spinlocks.c
@@ -14,24 +14,16 @@
 #include <linux/vt_kern.h>
 
 
-void bust_spinlocks(int yes)
+void __attribute__((weak)) bust_spinlocks(int yes)
 {
 	if (yes) {
 		oops_in_progress = 1;
 	} else {
-		int loglevel_save = console_loglevel;
 #ifdef CONFIG_VT
 		unblank_screen();
 #endif
 		oops_in_progress = 0;
-		/*
-		 * OK, the message is on the console.  Now we call printk()
-		 * without oops_in_progress set so that printk() will give klogd
-		 * and the blanked console a poke.  Hold onto your hats...
-		 */
-		console_loglevel = 15;		/* NMI oopser may have shut the console up */
-		printk(" ");
-		console_loglevel = loglevel_save;
+		wake_up_klogd();
 	}
 }
 
diff --git a/lib/cmdline.c b/lib/cmdline.c
index 8a5b530..f596c08d 100644
--- a/lib/cmdline.c
+++ b/lib/cmdline.c
@@ -43,10 +43,10 @@
  *	comma as well.
  *
  *	Return values:
- *	0 : no int in string
- *	1 : int found, no subsequent comma
- *	2 : int found including a subsequent comma
- *	3 : hyphen found to denote a range
+ *	0 - no int in string
+ *	1 - int found, no subsequent comma
+ *	2 - int found including a subsequent comma
+ *	3 - hyphen found to denote a range
  */
 
 int get_option (char **str, int *pint)
diff --git a/lib/cpumask.c b/lib/cpumask.c
index 3a67dc5..1ea2c18 100644
--- a/lib/cpumask.c
+++ b/lib/cpumask.c
@@ -15,22 +15,8 @@
 }
 EXPORT_SYMBOL(__next_cpu);
 
-/*
- * Find the highest possible smp_processor_id()
- *
- * Note: if we're prepared to assume that cpu_possible_map never changes
- * (reasonable) then this function should cache its return value.
- */
-int highest_possible_processor_id(void)
-{
-	unsigned int cpu;
-	unsigned highest = 0;
-
-	for_each_cpu_mask(cpu, cpu_possible_map)
-		highest = cpu;
-	return highest;
-}
-EXPORT_SYMBOL(highest_possible_processor_id);
+int nr_cpu_ids;
+EXPORT_SYMBOL(nr_cpu_ids);
 
 int __any_online_cpu(const cpumask_t *mask)
 {
diff --git a/lib/devres.c b/lib/devres.c
new file mode 100644
index 0000000..eb38849
--- /dev/null
+++ b/lib/devres.c
@@ -0,0 +1,300 @@
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+static void devm_ioremap_release(struct device *dev, void *res)
+{
+	iounmap(*(void __iomem **)res);
+}
+
+static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
+{
+	return *(void **)res == match_data;
+}
+
+/**
+ * devm_ioremap - Managed ioremap()
+ * @dev: Generic device to remap IO address for
+ * @offset: BUS offset to map
+ * @size: Size of map
+ *
+ * Managed ioremap().  Map is automatically unmapped on driver detach.
+ */
+void __iomem *devm_ioremap(struct device *dev, unsigned long offset,
+			   unsigned long size)
+{
+	void __iomem **ptr, *addr;
+
+	ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	addr = ioremap(offset, size);
+	if (addr) {
+		*ptr = addr;
+		devres_add(dev, ptr);
+	} else
+		devres_free(ptr);
+
+	return addr;
+}
+EXPORT_SYMBOL(devm_ioremap);
+
+/**
+ * devm_ioremap_nocache - Managed ioremap_nocache()
+ * @dev: Generic device to remap IO address for
+ * @offset: BUS offset to map
+ * @size: Size of map
+ *
+ * Managed ioremap_nocache().  Map is automatically unmapped on driver
+ * detach.
+ */
+void __iomem *devm_ioremap_nocache(struct device *dev, unsigned long offset,
+				   unsigned long size)
+{
+	void __iomem **ptr, *addr;
+
+	ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	addr = ioremap_nocache(offset, size);
+	if (addr) {
+		*ptr = addr;
+		devres_add(dev, ptr);
+	} else
+		devres_free(ptr);
+
+	return addr;
+}
+EXPORT_SYMBOL(devm_ioremap_nocache);
+
+/**
+ * devm_iounmap - Managed iounmap()
+ * @dev: Generic device to unmap for
+ * @addr: Address to unmap
+ *
+ * Managed iounmap().  @addr must have been mapped using devm_ioremap*().
+ */
+void devm_iounmap(struct device *dev, void __iomem *addr)
+{
+	iounmap(addr);
+	WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match,
+			       (void *)addr));
+}
+EXPORT_SYMBOL(devm_iounmap);
+
+#ifdef CONFIG_HAS_IOPORT
+/*
+ * Generic iomap devres
+ */
+static void devm_ioport_map_release(struct device *dev, void *res)
+{
+	ioport_unmap(*(void __iomem **)res);
+}
+
+static int devm_ioport_map_match(struct device *dev, void *res,
+				 void *match_data)
+{
+	return *(void **)res == match_data;
+}
+
+/**
+ * devm_ioport_map - Managed ioport_map()
+ * @dev: Generic device to map ioport for
+ * @port: Port to map
+ * @nr: Number of ports to map
+ *
+ * Managed ioport_map().  Map is automatically unmapped on driver
+ * detach.
+ */
+void __iomem * devm_ioport_map(struct device *dev, unsigned long port,
+			       unsigned int nr)
+{
+	void __iomem **ptr, *addr;
+
+	ptr = devres_alloc(devm_ioport_map_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	addr = ioport_map(port, nr);
+	if (addr) {
+		*ptr = addr;
+		devres_add(dev, ptr);
+	} else
+		devres_free(ptr);
+
+	return addr;
+}
+EXPORT_SYMBOL(devm_ioport_map);
+
+/**
+ * devm_ioport_unmap - Managed ioport_unmap()
+ * @dev: Generic device to unmap for
+ * @addr: Address to unmap
+ *
+ * Managed ioport_unmap().  @addr must have been mapped using
+ * devm_ioport_map().
+ */
+void devm_ioport_unmap(struct device *dev, void __iomem *addr)
+{
+	ioport_unmap(addr);
+	WARN_ON(devres_destroy(dev, devm_ioport_map_release,
+			       devm_ioport_map_match, (void *)addr));
+}
+EXPORT_SYMBOL(devm_ioport_unmap);
+
+#ifdef CONFIG_PCI
+/*
+ * PCI iomap devres
+ */
+#define PCIM_IOMAP_MAX	PCI_ROM_RESOURCE
+
+struct pcim_iomap_devres {
+	void __iomem *table[PCIM_IOMAP_MAX];
+};
+
+static void pcim_iomap_release(struct device *gendev, void *res)
+{
+	struct pci_dev *dev = container_of(gendev, struct pci_dev, dev);
+	struct pcim_iomap_devres *this = res;
+	int i;
+
+	for (i = 0; i < PCIM_IOMAP_MAX; i++)
+		if (this->table[i])
+			pci_iounmap(dev, this->table[i]);
+}
+
+/**
+ * pcim_iomap_table - access iomap allocation table
+ * @pdev: PCI device to access iomap table for
+ *
+ * Access iomap allocation table for @dev.  If iomap table doesn't
+ * exist and @pdev is managed, it will be allocated.  All iomaps
+ * recorded in the iomap table are automatically unmapped on driver
+ * detach.
+ *
+ * This function might sleep when the table is first allocated but can
+ * be safely called without context and guaranteed to succed once
+ * allocated.
+ */
+void __iomem * const * pcim_iomap_table(struct pci_dev *pdev)
+{
+	struct pcim_iomap_devres *dr, *new_dr;
+
+	dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL);
+	if (dr)
+		return dr->table;
+
+	new_dr = devres_alloc(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL);
+	if (!new_dr)
+		return NULL;
+	dr = devres_get(&pdev->dev, new_dr, NULL, NULL);
+	return dr->table;
+}
+EXPORT_SYMBOL(pcim_iomap_table);
+
+/**
+ * pcim_iomap - Managed pcim_iomap()
+ * @pdev: PCI device to iomap for
+ * @bar: BAR to iomap
+ * @maxlen: Maximum length of iomap
+ *
+ * Managed pci_iomap().  Map is automatically unmapped on driver
+ * detach.
+ */
+void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
+{
+	void __iomem **tbl;
+
+	BUG_ON(bar >= PCIM_IOMAP_MAX);
+
+	tbl = (void __iomem **)pcim_iomap_table(pdev);
+	if (!tbl || tbl[bar])	/* duplicate mappings not allowed */
+		return NULL;
+
+	tbl[bar] = pci_iomap(pdev, bar, maxlen);
+	return tbl[bar];
+}
+EXPORT_SYMBOL(pcim_iomap);
+
+/**
+ * pcim_iounmap - Managed pci_iounmap()
+ * @pdev: PCI device to iounmap for
+ * @addr: Address to unmap
+ *
+ * Managed pci_iounmap().  @addr must have been mapped using pcim_iomap().
+ */
+void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
+{
+	void __iomem **tbl;
+	int i;
+
+	pci_iounmap(pdev, addr);
+
+	tbl = (void __iomem **)pcim_iomap_table(pdev);
+	BUG_ON(!tbl);
+
+	for (i = 0; i < PCIM_IOMAP_MAX; i++)
+		if (tbl[i] == addr) {
+			tbl[i] = NULL;
+			return;
+		}
+	WARN_ON(1);
+}
+EXPORT_SYMBOL(pcim_iounmap);
+
+/**
+ * pcim_iomap_regions - Request and iomap PCI BARs
+ * @pdev: PCI device to map IO resources for
+ * @mask: Mask of BARs to request and iomap
+ * @name: Name used when requesting regions
+ *
+ * Request and iomap regions specified by @mask.
+ */
+int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name)
+{
+	void __iomem * const *iomap;
+	int i, rc;
+
+	iomap = pcim_iomap_table(pdev);
+	if (!iomap)
+		return -ENOMEM;
+
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		unsigned long len;
+
+		if (!(mask & (1 << i)))
+			continue;
+
+		rc = -EINVAL;
+		len = pci_resource_len(pdev, i);
+		if (!len)
+			goto err_inval;
+
+		rc = pci_request_region(pdev, i, name);
+		if (rc)
+			goto err_inval;
+
+		rc = -ENOMEM;
+		if (!pcim_iomap(pdev, i, 0))
+			goto err_region;
+	}
+
+	return 0;
+
+ err_region:
+	pci_release_region(pdev, i);
+ err_inval:
+	while (--i >= 0) {
+		if (!(mask & (1 << i)))
+			continue;
+		pcim_iounmap(pdev, iomap[i]);
+		pci_release_region(pdev, i);
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(pcim_iomap_regions);
+#endif
+#endif
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
index b5a90fc..0fabd12 100644
--- a/lib/fault-inject.c
+++ b/lib/fault-inject.c
@@ -55,7 +55,7 @@
 
 #define MAX_STACK_TRACE_DEPTH 32
 
-#if defined(CONFIG_STACKTRACE)
+#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
 
 static bool fail_stacktrace(struct fault_attr *attr)
 {
@@ -90,17 +90,10 @@
 
 static inline bool fail_stacktrace(struct fault_attr *attr)
 {
-	static bool firsttime = true;
-
-	if (firsttime) {
-		printk(KERN_WARNING
-		"This architecture does not implement save_stack_trace()\n");
-		firsttime = false;
-	}
-	return false;
+	return true;
 }
 
-#endif
+#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
 
 /*
  * This code is stolen from failmalloc-1.0
@@ -217,6 +210,8 @@
 	debugfs_remove(attr->dentries.task_filter_file);
 	attr->dentries.task_filter_file = NULL;
 
+#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
+
 	debugfs_remove(attr->dentries.stacktrace_depth_file);
 	attr->dentries.stacktrace_depth_file = NULL;
 
@@ -232,6 +227,8 @@
 	debugfs_remove(attr->dentries.reject_end_file);
 	attr->dentries.reject_end_file = NULL;
 
+#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
+
 	if (attr->dentries.dir)
 		WARN_ON(!simple_empty(attr->dentries.dir));
 
@@ -269,6 +266,13 @@
 	attr->dentries.task_filter_file = debugfs_create_bool("task-filter",
 						mode, dir, &attr->task_filter);
 
+	if (!attr->dentries.probability_file || !attr->dentries.interval_file ||
+	    !attr->dentries.times_file || !attr->dentries.space_file ||
+	    !attr->dentries.verbose_file || !attr->dentries.task_filter_file)
+		goto fail;
+
+#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
+
 	attr->dentries.stacktrace_depth_file =
 		debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
 			"stacktrace-depth", mode, dir, &attr->stacktrace_depth);
@@ -285,18 +289,15 @@
 	attr->dentries.reject_end_file =
 		debugfs_create_ul("reject-end", mode, dir, &attr->reject_end);
 
-
-	if (!attr->dentries.probability_file || !attr->dentries.interval_file
-	    || !attr->dentries.times_file || !attr->dentries.space_file
-	    || !attr->dentries.verbose_file || !attr->dentries.task_filter_file
-	    || !attr->dentries.stacktrace_depth_file
-	    || !attr->dentries.require_start_file
-	    || !attr->dentries.require_end_file
-	    || !attr->dentries.reject_start_file
-	    || !attr->dentries.reject_end_file
-	    )
+	if (!attr->dentries.stacktrace_depth_file ||
+	    !attr->dentries.require_start_file ||
+	    !attr->dentries.require_end_file ||
+	    !attr->dentries.reject_start_file ||
+	    !attr->dentries.reject_end_file)
 		goto fail;
 
+#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
+
 	return 0;
 fail:
 	cleanup_fault_attr_dentries(attr);
diff --git a/lib/genalloc.c b/lib/genalloc.c
index 75ae68c..eb7c2ba 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -148,7 +148,7 @@
 			addr = chunk->start_addr +
 					    ((unsigned long)start_bit << order);
 			while (nbits--)
-				__set_bit(start_bit++, &chunk->bits);
+				__set_bit(start_bit++, chunk->bits);
 			spin_unlock_irqrestore(&chunk->lock, flags);
 			read_unlock(&pool->lock);
 			return addr;
@@ -187,7 +187,7 @@
 			spin_lock_irqsave(&chunk->lock, flags);
 			bit = (addr - chunk->start_addr) >> order;
 			while (nbits--)
-				__clear_bit(bit++, &chunk->bits);
+				__clear_bit(bit++, chunk->bits);
 			spin_unlock_irqrestore(&chunk->lock, flags);
 			break;
 		}
diff --git a/lib/idr.c b/lib/idr.c
index 7185353..305117c 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -329,8 +329,8 @@
 
 /**
  * idr_remove - remove the given id and free it's slot
- * idp: idr handle
- * id: uniqueue key
+ * @idp: idr handle
+ * @id: unique key
  */
 void idr_remove(struct idr *idp, int id)
 {
diff --git a/lib/iomap.c b/lib/iomap.c
index d6ccdd8..4d43f37 100644
--- a/lib/iomap.c
+++ b/lib/iomap.c
@@ -4,8 +4,9 @@
  * (C) Copyright 2004 Linus Torvalds
  */
 #include <linux/pci.h>
+#include <linux/io.h>
+
 #include <linux/module.h>
-#include <asm/io.h>
 
 /*
  * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
diff --git a/lib/kobject.c b/lib/kobject.c
index c2917ffe..f4f6176 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -97,11 +97,12 @@
 }
 
 /**
- * kobject_get_path - generate and return the path associated with a given kobj
- * and kset pair.  The result must be freed by the caller with kfree().
+ * kobject_get_path - generate and return the path associated with a given kobj and kset pair.
  *
  * @kobj:	kobject in question, with which to build the path
  * @gfp_mask:	the allocation type used to allocate the path
+ *
+ * The result must be freed by the caller with kfree().
  */
 char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask)
 {
@@ -170,7 +171,7 @@
 		return -ENOENT;
 	if (!kobj->k_name)
 		kobj->k_name = kobj->name;
-	if (!kobj->k_name) {
+	if (!*kobj->k_name) {
 		pr_debug("kobject attempted to be registered with no name!\n");
 		WARN_ON(1);
 		return -EINVAL;
@@ -325,6 +326,7 @@
 /**
  *	kobject_rename - change the name of an object
  *	@kobj:	object in question.
+ *	@new_parent: object's new parent
  *	@new_name: object's new name
  */
 
diff --git a/lib/sha1.c b/lib/sha1.c
index 1cdabe3..4c45fd5 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -20,8 +20,8 @@
 #define K3  0x8F1BBCDCL			/* Rounds 40-59: sqrt(5) * 2^30 */
 #define K4  0xCA62C1D6L			/* Rounds 60-79: sqrt(10) * 2^30 */
 
-/*
- * sha_transform: single block SHA1 transform
+/**
+ * sha_transform - single block SHA1 transform
  *
  * @digest: 160 bit digest to update
  * @data:   512 bits of data to hash
@@ -80,9 +80,8 @@
 }
 EXPORT_SYMBOL(sha_transform);
 
-/*
- * sha_init: initialize the vectors for a SHA1 digest
- *
+/**
+ * sha_init - initialize the vectors for a SHA1 digest
  * @buf: vector to initialize
  */
 void sha_init(__u32 *buf)
diff --git a/lib/sort.c b/lib/sort.c
index 488788b..9615678 100644
--- a/lib/sort.c
+++ b/lib/sort.c
@@ -27,7 +27,7 @@
 	} while (--size > 0);
 }
 
-/*
+/**
  * sort - sort an array of elements
  * @base: pointer to data to sort
  * @num: number of elements
diff --git a/lib/string.c b/lib/string.c
index a485d75..bab440f 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -160,7 +160,7 @@
  * @src: The string to append to it
  * @count: The maximum numbers of bytes to copy
  *
- * Note that in contrast to strncpy, strncat ensures the result is
+ * Note that in contrast to strncpy(), strncat() ensures the result is
  * terminated.
  */
 char *strncat(char *dest, const char *src, size_t count)
@@ -366,8 +366,7 @@
 
 #ifndef __HAVE_ARCH_STRSPN
 /**
- * strspn - Calculate the length of the initial substring of @s which only
- * 	contain letters in @accept
+ * strspn - Calculate the length of the initial substring of @s which only contain letters in @accept
  * @s: The string to be searched
  * @accept: The string to search for
  */
@@ -394,8 +393,7 @@
 
 #ifndef __HAVE_ARCH_STRCSPN
 /**
- * strcspn - Calculate the length of the initial substring of @s which does
- * 	not contain letters in @reject
+ * strcspn - Calculate the length of the initial substring of @s which does not contain letters in @reject
  * @s: The string to be searched
  * @reject: The string to avoid
  */
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 50a4380..623a68a 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -313,7 +313,7 @@
 #endif
 
 #ifndef SWIOTLB_ARCH_HAS_NEEDS_MAPPING
-static inline int
+static int
 address_needs_mapping(struct device *hwdev, dma_addr_t addr)
 {
 	dma_addr_t mask = 0xffffffff;
@@ -672,7 +672,7 @@
  * address back to the card, you must first perform a
  * swiotlb_dma_sync_for_device, and then the device again owns the buffer
  */
-static inline void
+static void
 swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
 		    size_t size, int dir, int target)
 {
@@ -702,7 +702,7 @@
 /*
  * Same as above, but for a sub-range of the mapping.
  */
-static inline void
+static void
 swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr,
 			  unsigned long offset, size_t size,
 			  int dir, int target)
@@ -805,7 +805,7 @@
  * The same as swiotlb_sync_single_* but for a scatter-gather list, same rules
  * and usage.
  */
-static inline void
+static void
 swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg,
 		int nelems, int dir, int target)
 {
diff --git a/lib/textsearch.c b/lib/textsearch.c
index 98bcadc..88c98a2 100644
--- a/lib/textsearch.c
+++ b/lib/textsearch.c
@@ -40,7 +40,7 @@
  *       configuration according to the specified parameters.
  *   (3) User starts the search(es) by calling _find() or _next() to
  *       fetch subsequent occurrences. A state variable is provided
- *       to the algorihtm to store persistent variables.
+ *       to the algorithm to store persistent variables.
  *   (4) Core eventually resets the search offset and forwards the find()
  *       request to the algorithm.
  *   (5) Algorithm calls get_next_block() provided by the user continously
@@ -218,7 +218,7 @@
  * Call textsearch_next() to retrieve subsequent matches.
  *
  * Returns the position of first occurrence of the pattern or
- * UINT_MAX if no occurrence was found.
+ * %UINT_MAX if no occurrence was found.
  */ 
 unsigned int textsearch_find_continuous(struct ts_config *conf,
 					struct ts_state *state,
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index bed7229..b025864 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -247,12 +247,12 @@
  * be generated for the given input, excluding the trailing
  * '\0', as per ISO C99. If you want to have the exact
  * number of characters written into @buf as return value
- * (not including the trailing '\0'), use vscnprintf. If the
+ * (not including the trailing '\0'), use vscnprintf(). If the
  * return is greater than or equal to @size, the resulting
  * string is truncated.
  *
  * Call this function if you are already dealing with a va_list.
- * You probably want snprintf instead.
+ * You probably want snprintf() instead.
  */
 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 {
@@ -509,7 +509,7 @@
  * returns 0.
  *
  * Call this function if you are already dealing with a va_list.
- * You probably want scnprintf instead.
+ * You probably want scnprintf() instead.
  */
 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
 {
@@ -554,8 +554,7 @@
  * @...: Arguments for the format string
  *
  * The return value is the number of characters written into @buf not including
- * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
- * greater than or equal to @size, the resulting string is truncated.
+ * the trailing '\0'. If @size is <= 0 the function returns 0.
  */
 
 int scnprintf(char * buf, size_t size, const char *fmt, ...)
@@ -577,11 +576,11 @@
  * @args: Arguments for the format string
  *
  * The function returns the number of characters written
- * into @buf. Use vsnprintf or vscnprintf in order to avoid
+ * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
  * buffer overflows.
  *
  * Call this function if you are already dealing with a va_list.
- * You probably want sprintf instead.
+ * You probably want sprintf() instead.
  */
 int vsprintf(char *buf, const char *fmt, va_list args)
 {
@@ -597,7 +596,7 @@
  * @...: Arguments for the format string
  *
  * The function returns the number of characters written
- * into @buf. Use snprintf or scnprintf in order to avoid
+ * into @buf. Use snprintf() or scnprintf() in order to avoid
  * buffer overflows.
  */
 int sprintf(char * buf, const char *fmt, ...)
diff --git a/mm/Kconfig b/mm/Kconfig
index db7c55d..7942b33 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -157,3 +157,9 @@
 	default 64BIT
 	help
 	  This option allows memory and IO resources to be 64 bit.
+
+config ZONE_DMA_FLAG
+	int
+	default "0" if !ZONE_DMA
+	default "1"
+
diff --git a/mm/filemap.c b/mm/filemap.c
index 8332c77..d1060b8 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -327,7 +327,7 @@
  * @pos:	beginning offset in pages to write
  * @count:	number of bytes to write
  *
- * Note: Holding i_mutex across sync_page_range_nolock is not a good idea
+ * Note: Holding i_mutex across sync_page_range_nolock() is not a good idea
  * as it forces O_SYNC writers to different parts of the same file
  * to be serialised right until io completion.
  */
@@ -606,26 +606,6 @@
 EXPORT_SYMBOL(find_get_page);
 
 /**
- * find_trylock_page - find and lock a page
- * @mapping: the address_space to search
- * @offset: the page index
- *
- * Same as find_get_page(), but trylock it instead of incrementing the count.
- */
-struct page *find_trylock_page(struct address_space *mapping, unsigned long offset)
-{
-	struct page *page;
-
-	read_lock_irq(&mapping->tree_lock);
-	page = radix_tree_lookup(&mapping->page_tree, offset);
-	if (page && TestSetPageLocked(page))
-		page = NULL;
-	read_unlock_irq(&mapping->tree_lock);
-	return page;
-}
-EXPORT_SYMBOL(find_trylock_page);
-
-/**
  * find_lock_page - locate, pin and lock a pagecache page
  * @mapping: the address_space to search
  * @offset: the page index
@@ -804,7 +784,7 @@
  * @mapping: target address_space
  * @index: the page index
  *
- * Same as grab_cache_page, but do not wait if the page is unavailable.
+ * Same as grab_cache_page(), but do not wait if the page is unavailable.
  * This is intended for speculative data generators, where the data can
  * be regenerated if the page couldn't be grabbed.  This routine should
  * be safe to call while holding the lock for another page.
@@ -2099,21 +2079,27 @@
 		/* Limit the size of the copy to the caller's write size */
 		bytes = min(bytes, count);
 
-		/*
-		 * Limit the size of the copy to that of the current segment,
-		 * because fault_in_pages_readable() doesn't know how to walk
-		 * segments.
+		/* We only need to worry about prefaulting when writes are from
+		 * user-space.  NFSd uses vfs_writev with several non-aligned
+		 * segments in the vector, and limiting to one segment a time is
+		 * a noticeable performance for re-write
 		 */
-		bytes = min(bytes, cur_iov->iov_len - iov_base);
+		if (!segment_eq(get_fs(), KERNEL_DS)) {
+			/*
+			 * Limit the size of the copy to that of the current
+			 * segment, because fault_in_pages_readable() doesn't
+			 * know how to walk segments.
+			 */
+			bytes = min(bytes, cur_iov->iov_len - iov_base);
 
-		/*
-		 * Bring in the user page that we will copy from _first_.
-		 * Otherwise there's a nasty deadlock on copying from the
-		 * same page as we're writing to, without it being marked
-		 * up-to-date.
-		 */
-		fault_in_pages_readable(buf, bytes);
-
+			/*
+			 * Bring in the user page that we will copy from
+			 * _first_.  Otherwise there's a nasty deadlock on
+			 * copying from the same page as we're writing to,
+			 * without it being marked up-to-date.
+			 */
+			fault_in_pages_readable(buf, bytes);
+		}
 		page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec);
 		if (!page) {
 			status = -ENOMEM;
diff --git a/mm/highmem.c b/mm/highmem.c
index 0206e7e..51e1c19 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -47,7 +47,8 @@
 	unsigned int pages = 0;
 
 	for_each_online_pgdat(pgdat)
-		pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages;
+		pages += zone_page_state(&pgdat->node_zones[ZONE_HIGHMEM],
+			NR_FREE_PAGES);
 
 	return pages;
 }
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index cb362f7..36db012 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -389,6 +389,8 @@
 			continue;
 
 		page = pte_page(pte);
+		if (pte_dirty(pte))
+			set_page_dirty(page);
 		list_add(&page->lru, &page_list);
 	}
 	spin_unlock(&mm->page_table_lock);
diff --git a/mm/memory.c b/mm/memory.c
index ef09f0ac..e7066e7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -678,7 +678,7 @@
 				if (pte_dirty(ptent))
 					set_page_dirty(page);
 				if (pte_young(ptent))
-					mark_page_accessed(page);
+					SetPageReferenced(page);
 				file_rss--;
 			}
 			page_remove_rmap(page, vma);
@@ -1277,6 +1277,51 @@
 }
 EXPORT_SYMBOL(vm_insert_page);
 
+/**
+ * vm_insert_pfn - insert single pfn into user vma
+ * @vma: user vma to map to
+ * @addr: target user address of this page
+ * @pfn: source kernel pfn
+ *
+ * Similar to vm_inert_page, this allows drivers to insert individual pages
+ * they've allocated into a user vma. Same comments apply.
+ *
+ * This function should only be called from a vm_ops->fault handler, and
+ * in that case the handler should return NULL.
+ */
+int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
+		unsigned long pfn)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	int retval;
+	pte_t *pte, entry;
+	spinlock_t *ptl;
+
+	BUG_ON(!(vma->vm_flags & VM_PFNMAP));
+	BUG_ON(is_cow_mapping(vma->vm_flags));
+
+	retval = -ENOMEM;
+	pte = get_locked_pte(mm, addr, &ptl);
+	if (!pte)
+		goto out;
+	retval = -EBUSY;
+	if (!pte_none(*pte))
+		goto out_unlock;
+
+	/* Ok, finally just insert the thing.. */
+	entry = pfn_pte(pfn, vma->vm_page_prot);
+	set_pte_at(mm, addr, pte, entry);
+	update_mmu_cache(vma, addr, entry);
+
+	retval = 0;
+out_unlock:
+	pte_unmap_unlock(pte, ptl);
+
+out:
+	return retval;
+}
+EXPORT_SYMBOL(vm_insert_pfn);
+
 /*
  * maps a range of physical memory into the requested pages. the old
  * mappings are removed. any references to nonexistent pages results
@@ -1531,8 +1576,6 @@
 			if (vma->vm_ops->page_mkwrite(vma, old_page) < 0)
 				goto unwritable_page;
 
-			page_cache_release(old_page);
-
 			/*
 			 * Since we dropped the lock we need to revalidate
 			 * the PTE as someone else may have changed it.  If
@@ -1541,6 +1584,7 @@
 			 */
 			page_table = pte_offset_map_lock(mm, pmd, address,
 							 &ptl);
+			page_cache_release(old_page);
 			if (!pte_same(*page_table, orig_pte))
 				goto unlock;
 		}
@@ -1776,9 +1820,7 @@
 }
 
 /**
- * unmap_mapping_range - unmap the portion of all mmaps
- * in the specified address_space corresponding to the specified
- * page range in the underlying file.
+ * unmap_mapping_range - unmap the portion of all mmaps in the specified address_space corresponding to the specified page range in the underlying file.
  * @mapping: the address space containing mmaps to be unmapped.
  * @holebegin: byte in first page to unmap, relative to the start of
  * the underlying file.  This will be rounded down to a PAGE_SIZE
@@ -2313,10 +2355,12 @@
 	BUG_ON(is_cow_mapping(vma->vm_flags));
 
 	pfn = vma->vm_ops->nopfn(vma, address & PAGE_MASK);
-	if (pfn == NOPFN_OOM)
+	if (unlikely(pfn == NOPFN_OOM))
 		return VM_FAULT_OOM;
-	if (pfn == NOPFN_SIGBUS)
+	else if (unlikely(pfn == NOPFN_SIGBUS))
 		return VM_FAULT_SIGBUS;
+	else if (unlikely(pfn == NOPFN_REFAULT))
+		return VM_FAULT_MINOR;
 
 	page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
 
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index c2aec0e..cf2a538 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -105,7 +105,7 @@
 
 /* Highest zone. An specific allocation for a zone below that is not
    policied. */
-enum zone_type policy_zone = ZONE_DMA;
+enum zone_type policy_zone = 0;
 
 struct mempolicy default_policy = {
 	.refcnt = ATOMIC_INIT(1), /* never free it */
@@ -144,7 +144,7 @@
 	max++;			/* space for zlcache_ptr (see mmzone.h) */
 	zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL);
 	if (!zl)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	zl->zlcache_ptr = NULL;
 	num = 0;
 	/* First put in the highest zones from all nodes, then all the next 
@@ -162,6 +162,10 @@
 			break;
 		k--;
 	}
+	if (num == 0) {
+		kfree(zl);
+		return ERR_PTR(-EINVAL);
+	}
 	zl->zones[num] = NULL;
 	return zl;
 }
@@ -193,9 +197,10 @@
 		break;
 	case MPOL_BIND:
 		policy->v.zonelist = bind_zonelist(nodes);
-		if (policy->v.zonelist == NULL) {
+		if (IS_ERR(policy->v.zonelist)) {
+			void *error_code = policy->v.zonelist;
 			kmem_cache_free(policy_cache, policy);
-			return ERR_PTR(-ENOMEM);
+			return error_code;
 		}
 		break;
 	}
@@ -1667,7 +1672,7 @@
 		 * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT.
 		 */
 
-		if (zonelist) {
+		if (!IS_ERR(zonelist)) {
 			/* Good - got mem - substitute new zonelist */
 			kfree(pol->v.zonelist);
 			pol->v.zonelist = zonelist;
diff --git a/mm/mempool.c b/mm/mempool.c
index ccd8cb8..cc1ca86 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -46,9 +46,9 @@
  * @pool_data: optional private data available to the user-defined functions.
  *
  * this function creates and allocates a guaranteed size, preallocated
- * memory pool. The pool can be used from the mempool_alloc and mempool_free
+ * memory pool. The pool can be used from the mempool_alloc() and mempool_free()
  * functions. This function might sleep. Both the alloc_fn() and the free_fn()
- * functions might sleep - as long as the mempool_alloc function is not called
+ * functions might sleep - as long as the mempool_alloc() function is not called
  * from IRQ contexts.
  */
 mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
@@ -195,7 +195,7 @@
  *             mempool_create().
  * @gfp_mask:  the usual allocation bitmask.
  *
- * this function only sleeps if the alloc_fn function sleeps or
+ * this function only sleeps if the alloc_fn() function sleeps or
  * returns NULL. Note that due to preallocation, this function
  * *never* fails when called from process contexts. (it might
  * fail if called from an IRQ context.)
diff --git a/mm/mincore.c b/mm/mincore.c
index 8aca6f7..5efe0de 100644
--- a/mm/mincore.c
+++ b/mm/mincore.c
@@ -12,6 +12,8 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/syscalls.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -22,14 +24,22 @@
  * and is up to date; i.e. that no page-in operation would be required
  * at this time if an application were to map and access this page.
  */
-static unsigned char mincore_page(struct vm_area_struct * vma,
-	unsigned long pgoff)
+static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
 {
 	unsigned char present = 0;
-	struct address_space * as = vma->vm_file->f_mapping;
-	struct page * page;
+	struct page *page;
 
-	page = find_get_page(as, pgoff);
+	/*
+	 * When tmpfs swaps out a page from a file, any process mapping that
+	 * file will not get a swp_entry_t in its pte, but rather it is like
+	 * any other file mapping (ie. marked !present and faulted in with
+	 * tmpfs's .nopage). So swapped out tmpfs mappings are tested here.
+	 *
+	 * However when tmpfs moves the page from pagecache and into swapcache,
+	 * it is still in core, but the find_get_page below won't find it.
+	 * No big deal, but make a note of it.
+	 */
+	page = find_get_page(mapping, pgoff);
 	if (page) {
 		present = PageUptodate(page);
 		page_cache_release(page);
@@ -45,7 +55,14 @@
  */
 static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pages)
 {
-	unsigned long i, nr, pgoff;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *ptep;
+	spinlock_t *ptl;
+	unsigned long nr;
+	int i;
+	pgoff_t pgoff;
 	struct vm_area_struct *vma = find_vma(current->mm, addr);
 
 	/*
@@ -56,31 +73,82 @@
 		return -ENOMEM;
 
 	/*
-	 * Ok, got it. But check whether it's a segment we support
-	 * mincore() on. Right now, we don't do any anonymous mappings.
-	 *
-	 * FIXME: This is just stupid. And returning ENOMEM is 
-	 * stupid too. We should just look at the page tables. But
-	 * this is what we've traditionally done, so we'll just
-	 * continue doing it.
+	 * Calculate how many pages there are left in the last level of the
+	 * PTE array for our address.
 	 */
-	if (!vma->vm_file)
-		return -ENOMEM;
+	nr = PTRS_PER_PTE - ((addr >> PAGE_SHIFT) & (PTRS_PER_PTE-1));
 
 	/*
-	 * Calculate how many pages there are left in the vma, and
-	 * what the pgoff is for our address.
+	 * Don't overrun this vma
 	 */
-	nr = (vma->vm_end - addr) >> PAGE_SHIFT;
-	if (nr > pages)
-		nr = pages;
+	nr = min(nr, (vma->vm_end - addr) >> PAGE_SHIFT);
 
-	pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
-	pgoff += vma->vm_pgoff;
+	/*
+	 * Don't return more than the caller asked for
+	 */
+	nr = min(nr, pages);
 
-	/* And then we just fill the sucker in.. */
-	for (i = 0 ; i < nr; i++, pgoff++)
-		vec[i] = mincore_page(vma, pgoff);
+	pgd = pgd_offset(vma->vm_mm, addr);
+	if (pgd_none_or_clear_bad(pgd))
+		goto none_mapped;
+	pud = pud_offset(pgd, addr);
+	if (pud_none_or_clear_bad(pud))
+		goto none_mapped;
+	pmd = pmd_offset(pud, addr);
+	if (pmd_none_or_clear_bad(pmd))
+		goto none_mapped;
+
+	ptep = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+	for (i = 0; i < nr; i++, ptep++, addr += PAGE_SIZE) {
+		unsigned char present;
+		pte_t pte = *ptep;
+
+		if (pte_present(pte)) {
+			present = 1;
+
+		} else if (pte_none(pte)) {
+			if (vma->vm_file) {
+				pgoff = linear_page_index(vma, addr);
+				present = mincore_page(vma->vm_file->f_mapping,
+							pgoff);
+			} else
+				present = 0;
+
+		} else if (pte_file(pte)) {
+			pgoff = pte_to_pgoff(pte);
+			present = mincore_page(vma->vm_file->f_mapping, pgoff);
+
+		} else { /* pte is a swap entry */
+			swp_entry_t entry = pte_to_swp_entry(pte);
+			if (is_migration_entry(entry)) {
+				/* migration entries are always uptodate */
+				present = 1;
+			} else {
+#ifdef CONFIG_SWAP
+				pgoff = entry.val;
+				present = mincore_page(&swapper_space, pgoff);
+#else
+				WARN_ON(1);
+				present = 1;
+#endif
+			}
+		}
+
+		vec[i] = present;
+	}
+	pte_unmap_unlock(ptep-1, ptl);
+
+	return nr;
+
+none_mapped:
+	if (vma->vm_file) {
+		pgoff = linear_page_index(vma, addr);
+		for (i = 0; i < nr; i++, pgoff++)
+			vec[i] = mincore_page(vma->vm_file->f_mapping, pgoff);
+	} else {
+		for (i = 0; i < nr; i++)
+			vec[i] = 0;
+	}
 
 	return nr;
 }
diff --git a/mm/mmap.c b/mm/mmap.c
index cc3a208..eb509ae 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2101,3 +2101,75 @@
 		return 0;
 	return 1;
 }
+
+
+static struct page *special_mapping_nopage(struct vm_area_struct *vma,
+					   unsigned long address, int *type)
+{
+	struct page **pages;
+
+	BUG_ON(address < vma->vm_start || address >= vma->vm_end);
+
+	address -= vma->vm_start;
+	for (pages = vma->vm_private_data; address > 0 && *pages; ++pages)
+		address -= PAGE_SIZE;
+
+	if (*pages) {
+		struct page *page = *pages;
+		get_page(page);
+		return page;
+	}
+
+	return NOPAGE_SIGBUS;
+}
+
+/*
+ * Having a close hook prevents vma merging regardless of flags.
+ */
+static void special_mapping_close(struct vm_area_struct *vma)
+{
+}
+
+static struct vm_operations_struct special_mapping_vmops = {
+	.close = special_mapping_close,
+	.nopage	= special_mapping_nopage,
+};
+
+/*
+ * Called with mm->mmap_sem held for writing.
+ * Insert a new vma covering the given region, with the given flags.
+ * Its pages are supplied by the given array of struct page *.
+ * The array can be shorter than len >> PAGE_SHIFT if it's null-terminated.
+ * The region past the last page supplied will always produce SIGBUS.
+ * The array pointer and the pages it points to are assumed to stay alive
+ * for as long as this mapping might exist.
+ */
+int install_special_mapping(struct mm_struct *mm,
+			    unsigned long addr, unsigned long len,
+			    unsigned long vm_flags, struct page **pages)
+{
+	struct vm_area_struct *vma;
+
+	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
+	if (unlikely(vma == NULL))
+		return -ENOMEM;
+
+	vma->vm_mm = mm;
+	vma->vm_start = addr;
+	vma->vm_end = addr + len;
+
+	vma->vm_flags = vm_flags | mm->def_flags;
+	vma->vm_page_prot = protection_map[vma->vm_flags & 7];
+
+	vma->vm_ops = &special_mapping_vmops;
+	vma->vm_private_data = pages;
+
+	if (unlikely(insert_vm_struct(mm, vma))) {
+		kmem_cache_free(vm_area_cachep, vma);
+		return -ENOMEM;
+	}
+
+	mm->total_vm += len >> PAGE_SHIFT;
+
+	return 0;
+}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index be0efbd..f7e088f 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -515,7 +515,7 @@
 ratelimit_handler(struct notifier_block *self, unsigned long u, void *v)
 {
 	writeback_set_ratelimit();
-	return 0;
+	return NOTIFY_DONE;
 }
 
 static struct notifier_block __cpuinitdata ratelimit_nb = {
@@ -549,9 +549,7 @@
 }
 
 /**
- * generic_writepages - walk the list of dirty pages of the given
- *                      address space and writepage() all of them.
- *
+ * generic_writepages - walk the list of dirty pages of the given address space and writepage() all of them.
  * @mapping: address space structure to write
  * @wbc: subtract the number of written pages from *@wbc->nr_to_write
  *
@@ -698,7 +696,6 @@
 
 /**
  * write_one_page - write out a single page and optionally wait on I/O
- *
  * @page: the page to write
  * @wait: if true, wait on writeout
  *
@@ -737,6 +734,16 @@
 EXPORT_SYMBOL(write_one_page);
 
 /*
+ * For address_spaces which do not use buffers nor write back.
+ */
+int __set_page_dirty_no_writeback(struct page *page)
+{
+	if (!PageDirty(page))
+		SetPageDirty(page);
+	return 0;
+}
+
+/*
  * For address_spaces which do not use buffers.  Just tag the page as dirty in
  * its radix tree.
  *
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 2c606cc..4173739 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -73,7 +73,9 @@
  * don't need any ZONE_NORMAL reservation
  */
 int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1] = {
+#ifdef CONFIG_ZONE_DMA
 	 256,
+#endif
 #ifdef CONFIG_ZONE_DMA32
 	 256,
 #endif
@@ -85,7 +87,9 @@
 EXPORT_SYMBOL(totalram_pages);
 
 static char * const zone_names[MAX_NR_ZONES] = {
+#ifdef CONFIG_ZONE_DMA
 	 "DMA",
+#endif
 #ifdef CONFIG_ZONE_DMA32
 	 "DMA32",
 #endif
@@ -395,7 +399,7 @@
 	VM_BUG_ON(page_idx & (order_size - 1));
 	VM_BUG_ON(bad_range(zone, page));
 
-	zone->free_pages += order_size;
+	__mod_zone_page_state(zone, NR_FREE_PAGES, order_size);
 	while (order < MAX_ORDER-1) {
 		unsigned long combined_idx;
 		struct free_area *area;
@@ -631,7 +635,7 @@
 		list_del(&page->lru);
 		rmv_page_order(page);
 		area->nr_free--;
-		zone->free_pages -= 1UL << order;
+		__mod_zone_page_state(zone, NR_FREE_PAGES, - (1UL << order));
 		expand(zone, page, order, current_order, area);
 		return page;
 	}
@@ -660,6 +664,26 @@
 	return i;
 }
 
+#if MAX_NUMNODES > 1
+int nr_node_ids __read_mostly;
+EXPORT_SYMBOL(nr_node_ids);
+
+/*
+ * Figure out the number of possible node ids.
+ */
+static void __init setup_nr_node_ids(void)
+{
+	unsigned int node;
+	unsigned int highest = 0;
+
+	for_each_node_mask(node, node_possible_map)
+		highest = node;
+	nr_node_ids = highest + 1;
+}
+#else
+static void __init setup_nr_node_ids(void) {}
+#endif
+
 #ifdef CONFIG_NUMA
 /*
  * Called from the slab reaper to drain pagesets on a particular node that
@@ -989,7 +1013,8 @@
 		      int classzone_idx, int alloc_flags)
 {
 	/* free_pages my go negative - that's OK */
-	long min = mark, free_pages = z->free_pages - (1 << order) + 1;
+	long min = mark;
+	long free_pages = zone_page_state(z, NR_FREE_PAGES) - (1 << order) + 1;
 	int o;
 
 	if (alloc_flags & ALLOC_HIGH)
@@ -1439,35 +1464,6 @@
 
 EXPORT_SYMBOL(free_pages);
 
-/*
- * Total amount of free (allocatable) RAM:
- */
-unsigned int nr_free_pages(void)
-{
-	unsigned int sum = 0;
-	struct zone *zone;
-
-	for_each_zone(zone)
-		sum += zone->free_pages;
-
-	return sum;
-}
-
-EXPORT_SYMBOL(nr_free_pages);
-
-#ifdef CONFIG_NUMA
-unsigned int nr_free_pages_pgdat(pg_data_t *pgdat)
-{
-	unsigned int sum = 0;
-	enum zone_type i;
-
-	for (i = 0; i < MAX_NR_ZONES; i++)
-		sum += pgdat->node_zones[i].free_pages;
-
-	return sum;
-}
-#endif
-
 static unsigned int nr_free_zone_pages(int offset)
 {
 	/* Just pick one node, since fallback list is circular */
@@ -1514,7 +1510,7 @@
 {
 	val->totalram = totalram_pages;
 	val->sharedram = 0;
-	val->freeram = nr_free_pages();
+	val->freeram = global_page_state(NR_FREE_PAGES);
 	val->bufferram = nr_blockdev_pages();
 	val->totalhigh = totalhigh_pages;
 	val->freehigh = nr_free_highpages();
@@ -1529,10 +1525,11 @@
 	pg_data_t *pgdat = NODE_DATA(nid);
 
 	val->totalram = pgdat->node_present_pages;
-	val->freeram = nr_free_pages_pgdat(pgdat);
+	val->freeram = node_page_state(nid, NR_FREE_PAGES);
 #ifdef CONFIG_HIGHMEM
 	val->totalhigh = pgdat->node_zones[ZONE_HIGHMEM].present_pages;
-	val->freehigh = pgdat->node_zones[ZONE_HIGHMEM].free_pages;
+	val->freehigh = zone_page_state(&pgdat->node_zones[ZONE_HIGHMEM],
+			NR_FREE_PAGES);
 #else
 	val->totalhigh = 0;
 	val->freehigh = 0;
@@ -1551,9 +1548,6 @@
 void show_free_areas(void)
 {
 	int cpu;
-	unsigned long active;
-	unsigned long inactive;
-	unsigned long free;
 	struct zone *zone;
 
 	for_each_zone(zone) {
@@ -1577,20 +1571,19 @@
 		}
 	}
 
-	get_zone_counts(&active, &inactive, &free);
-
-	printk("Active:%lu inactive:%lu dirty:%lu writeback:%lu "
-		"unstable:%lu free:%u slab:%lu mapped:%lu pagetables:%lu\n",
-		active,
-		inactive,
+	printk("Active:%lu inactive:%lu dirty:%lu writeback:%lu unstable:%lu\n"
+		" free:%lu slab:%lu mapped:%lu pagetables:%lu bounce:%lu\n",
+		global_page_state(NR_ACTIVE),
+		global_page_state(NR_INACTIVE),
 		global_page_state(NR_FILE_DIRTY),
 		global_page_state(NR_WRITEBACK),
 		global_page_state(NR_UNSTABLE_NFS),
-		nr_free_pages(),
+		global_page_state(NR_FREE_PAGES),
 		global_page_state(NR_SLAB_RECLAIMABLE) +
 			global_page_state(NR_SLAB_UNRECLAIMABLE),
 		global_page_state(NR_FILE_MAPPED),
-		global_page_state(NR_PAGETABLE));
+		global_page_state(NR_PAGETABLE),
+		global_page_state(NR_BOUNCE));
 
 	for_each_zone(zone) {
 		int i;
@@ -1611,12 +1604,12 @@
 			" all_unreclaimable? %s"
 			"\n",
 			zone->name,
-			K(zone->free_pages),
+			K(zone_page_state(zone, NR_FREE_PAGES)),
 			K(zone->pages_min),
 			K(zone->pages_low),
 			K(zone->pages_high),
-			K(zone->nr_active),
-			K(zone->nr_inactive),
+			K(zone_page_state(zone, NR_ACTIVE)),
+			K(zone_page_state(zone, NR_INACTIVE)),
 			K(zone->present_pages),
 			zone->pages_scanned,
 			(zone->all_unreclaimable ? "yes" : "no")
@@ -2650,11 +2643,11 @@
 				"  %s zone: %lu pages exceeds realsize %lu\n",
 				zone_names[j], memmap_pages, realsize);
 
-		/* Account for reserved DMA pages */
-		if (j == ZONE_DMA && realsize > dma_reserve) {
+		/* Account for reserved pages */
+		if (j == 0 && realsize > dma_reserve) {
 			realsize -= dma_reserve;
-			printk(KERN_DEBUG "  DMA zone: %lu pages reserved\n",
-								dma_reserve);
+			printk(KERN_DEBUG "  %s zone: %lu pages reserved\n",
+					zone_names[0], dma_reserve);
 		}
 
 		if (!is_highmem_idx(j))
@@ -2674,7 +2667,6 @@
 		spin_lock_init(&zone->lru_lock);
 		zone_seqlock_init(zone);
 		zone->zone_pgdat = pgdat;
-		zone->free_pages = 0;
 
 		zone->prev_priority = DEF_PRIORITY;
 
@@ -2683,8 +2675,6 @@
 		INIT_LIST_HEAD(&zone->inactive_list);
 		zone->nr_scan_active = 0;
 		zone->nr_scan_inactive = 0;
-		zone->nr_active = 0;
-		zone->nr_inactive = 0;
 		zap_zone_vm_stats(zone);
 		atomic_set(&zone->reclaim_in_progress, 0);
 		if (!size)
@@ -2876,20 +2866,23 @@
 			cmp_node_active_region, NULL);
 }
 
-/* Find the lowest pfn for a node. This depends on a sorted early_node_map */
+/* Find the lowest pfn for a node */
 unsigned long __init find_min_pfn_for_node(unsigned long nid)
 {
 	int i;
-
-	/* Regions in the early_node_map can be in any order */
-	sort_node_map();
+	unsigned long min_pfn = ULONG_MAX;
 
 	/* Assuming a sorted map, the first range found has the starting pfn */
 	for_each_active_range_index_in_nid(i, nid)
-		return early_node_map[i].start_pfn;
+		min_pfn = min(min_pfn, early_node_map[i].start_pfn);
 
-	printk(KERN_WARNING "Could not find start_pfn for node %lu\n", nid);
-	return 0;
+	if (min_pfn == ULONG_MAX) {
+		printk(KERN_WARNING
+			"Could not find start_pfn for node %lu\n", nid);
+		return 0;
+	}
+
+	return min_pfn;
 }
 
 /**
@@ -2938,6 +2931,9 @@
 	unsigned long nid;
 	enum zone_type i;
 
+	/* Sort early_node_map as initialisation assumes it is sorted */
+	sort_node_map();
+
 	/* Record where the zone boundaries are */
 	memset(arch_zone_lowest_possible_pfn, 0,
 				sizeof(arch_zone_lowest_possible_pfn));
@@ -2968,6 +2964,7 @@
 						early_node_map[i].end_pfn);
 
 	/* Initialise every node */
+	setup_nr_node_ids();
 	for_each_online_node(nid) {
 		pg_data_t *pgdat = NODE_DATA(nid);
 		free_area_init_node(nid, pgdat, NULL,
@@ -3394,18 +3391,4 @@
 EXPORT_SYMBOL(page_to_pfn);
 #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
 
-#if MAX_NUMNODES > 1
-/*
- * Find the highest possible node id.
- */
-int highest_possible_node_id(void)
-{
-	unsigned int node;
-	unsigned int highest = 0;
 
-	for_each_node_mask(node, node_possible_map)
-		highest = node;
-	return highest;
-}
-EXPORT_SYMBOL(highest_possible_node_id);
-#endif
diff --git a/mm/readahead.c b/mm/readahead.c
index 0f539e8..93d9ee6 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -575,10 +575,6 @@
  */
 unsigned long max_sane_readahead(unsigned long nr)
 {
-	unsigned long active;
-	unsigned long inactive;
-	unsigned long free;
-
-	__get_zone_counts(&active, &inactive, &free, NODE_DATA(numa_node_id()));
-	return min(nr, (inactive + free) / 2);
+	return min(nr, (node_page_state(numa_node_id(), NR_INACTIVE)
+		+ node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2);
 }
diff --git a/mm/shmem.c b/mm/shmem.c
index 70da7a0..8820530 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -178,9 +178,9 @@
 static struct super_operations shmem_ops;
 static const struct address_space_operations shmem_aops;
 static const struct file_operations shmem_file_operations;
-static struct inode_operations shmem_inode_operations;
-static struct inode_operations shmem_dir_inode_operations;
-static struct inode_operations shmem_special_inode_operations;
+static const struct inode_operations shmem_inode_operations;
+static const struct inode_operations shmem_dir_inode_operations;
+static const struct inode_operations shmem_special_inode_operations;
 static struct vm_operations_struct shmem_vm_ops;
 
 static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
@@ -1410,8 +1410,8 @@
 }
 
 #ifdef CONFIG_TMPFS
-static struct inode_operations shmem_symlink_inode_operations;
-static struct inode_operations shmem_symlink_inline_operations;
+static const struct inode_operations shmem_symlink_inode_operations;
+static const struct inode_operations shmem_symlink_inline_operations;
 
 /*
  * Normally tmpfs makes no use of shmem_prepare_write, but it
@@ -1904,12 +1904,12 @@
 	}
 }
 
-static struct inode_operations shmem_symlink_inline_operations = {
+static const struct inode_operations shmem_symlink_inline_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= shmem_follow_link_inline,
 };
 
-static struct inode_operations shmem_symlink_inode_operations = {
+static const struct inode_operations shmem_symlink_inode_operations = {
 	.truncate	= shmem_truncate,
 	.readlink	= generic_readlink,
 	.follow_link	= shmem_follow_link,
@@ -2316,7 +2316,7 @@
 
 static const struct address_space_operations shmem_aops = {
 	.writepage	= shmem_writepage,
-	.set_page_dirty	= __set_page_dirty_nobuffers,
+	.set_page_dirty	= __set_page_dirty_no_writeback,
 #ifdef CONFIG_TMPFS
 	.prepare_write	= shmem_prepare_write,
 	.commit_write	= simple_commit_write,
@@ -2335,7 +2335,7 @@
 #endif
 };
 
-static struct inode_operations shmem_inode_operations = {
+static const struct inode_operations shmem_inode_operations = {
 	.truncate	= shmem_truncate,
 	.setattr	= shmem_notify_change,
 	.truncate_range	= shmem_truncate_range,
@@ -2349,7 +2349,7 @@
 
 };
 
-static struct inode_operations shmem_dir_inode_operations = {
+static const struct inode_operations shmem_dir_inode_operations = {
 #ifdef CONFIG_TMPFS
 	.create		= shmem_create,
 	.lookup		= simple_lookup,
@@ -2371,7 +2371,7 @@
 #endif
 };
 
-static struct inode_operations shmem_special_inode_operations = {
+static const struct inode_operations shmem_special_inode_operations = {
 #ifdef CONFIG_TMPFS_POSIX_ACL
 	.setattr	= shmem_notify_change,
 	.setxattr	= generic_setxattr,
diff --git a/mm/slab.c b/mm/slab.c
index c610062..8fdaffa 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -793,8 +793,10 @@
 	 * has cs_{dma,}cachep==NULL. Thus no special case
 	 * for large kmalloc calls required.
 	 */
+#ifdef CONFIG_ZONE_DMA
 	if (unlikely(gfpflags & GFP_DMA))
 		return csizep->cs_dmacachep;
+#endif
 	return csizep->cs_cachep;
 }
 
@@ -1040,7 +1042,7 @@
 static struct array_cache **alloc_alien_cache(int node, int limit)
 {
 	struct array_cache **ac_ptr;
-	int memsize = sizeof(void *) * MAX_NUMNODES;
+	int memsize = sizeof(void *) * nr_node_ids;
 	int i;
 
 	if (limit > 1)
@@ -1493,13 +1495,15 @@
 					ARCH_KMALLOC_FLAGS|SLAB_PANIC,
 					NULL, NULL);
 		}
-
-		sizes->cs_dmacachep = kmem_cache_create(names->name_dma,
+#ifdef CONFIG_ZONE_DMA
+		sizes->cs_dmacachep = kmem_cache_create(
+					names->name_dma,
 					sizes->cs_size,
 					ARCH_KMALLOC_MINALIGN,
 					ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA|
 						SLAB_PANIC,
 					NULL, NULL);
+#endif
 		sizes++;
 		names++;
 	}
@@ -2321,7 +2325,7 @@
 	cachep->slab_size = slab_size;
 	cachep->flags = flags;
 	cachep->gfpflags = 0;
-	if (flags & SLAB_CACHE_DMA)
+	if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA))
 		cachep->gfpflags |= GFP_DMA;
 	cachep->buffer_size = size;
 	cachep->reciprocal_buffer_size = reciprocal_value(size);
@@ -2516,7 +2520,7 @@
  * kmem_cache_destroy - delete a cache
  * @cachep: the cache to destroy
  *
- * Remove a struct kmem_cache object from the slab cache.
+ * Remove a &struct kmem_cache object from the slab cache.
  *
  * It is expected this function will be called by a module when it is
  * unloaded.  This will remove the cache completely, and avoid a duplicate
@@ -2643,10 +2647,12 @@
 
 static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags)
 {
-	if (flags & GFP_DMA)
-		BUG_ON(!(cachep->gfpflags & GFP_DMA));
-	else
-		BUG_ON(cachep->gfpflags & GFP_DMA);
+	if (CONFIG_ZONE_DMA_FLAG) {
+		if (flags & GFP_DMA)
+			BUG_ON(!(cachep->gfpflags & GFP_DMA));
+		else
+			BUG_ON(cachep->gfpflags & GFP_DMA);
+	}
 }
 
 static void *slab_get_obj(struct kmem_cache *cachep, struct slab *slabp,
@@ -2814,19 +2820,11 @@
  */
 static void kfree_debugcheck(const void *objp)
 {
-	struct page *page;
-
 	if (!virt_addr_valid(objp)) {
 		printk(KERN_ERR "kfree_debugcheck: out of range ptr %lxh.\n",
 		       (unsigned long)objp);
 		BUG();
 	}
-	page = virt_to_page(objp);
-	if (!PageSlab(page)) {
-		printk(KERN_ERR "kfree_debugcheck: bad ptr %lxh.\n",
-		       (unsigned long)objp);
-		BUG();
-	}
 }
 
 static inline void verify_redzone_free(struct kmem_cache *cache, void *obj)
@@ -3197,35 +3195,6 @@
 	return objp;
 }
 
-static __always_inline void *__cache_alloc(struct kmem_cache *cachep,
-						gfp_t flags, void *caller)
-{
-	unsigned long save_flags;
-	void *objp = NULL;
-
-	cache_alloc_debugcheck_before(cachep, flags);
-
-	local_irq_save(save_flags);
-
-	if (unlikely(NUMA_BUILD &&
-			current->flags & (PF_SPREAD_SLAB | PF_MEMPOLICY)))
-		objp = alternate_node_alloc(cachep, flags);
-
-	if (!objp)
-		objp = ____cache_alloc(cachep, flags);
-	/*
-	 * We may just have run out of memory on the local node.
-	 * ____cache_alloc_node() knows how to locate memory on other nodes
-	 */
- 	if (NUMA_BUILD && !objp)
- 		objp = ____cache_alloc_node(cachep, flags, numa_node_id());
-	local_irq_restore(save_flags);
-	objp = cache_alloc_debugcheck_after(cachep, flags, objp,
-					    caller);
-	prefetchw(objp);
-	return objp;
-}
-
 #ifdef CONFIG_NUMA
 /*
  * Try allocating on another node if PF_SPREAD_SLAB|PF_MEMPOLICY.
@@ -3257,14 +3226,20 @@
  * allocator to do its reclaim / fallback magic. We then insert the
  * slab into the proper nodelist and then allocate from it.
  */
-void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
+static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
 {
-	struct zonelist *zonelist = &NODE_DATA(slab_node(current->mempolicy))
-					->node_zonelists[gfp_zone(flags)];
+	struct zonelist *zonelist;
+	gfp_t local_flags;
 	struct zone **z;
 	void *obj = NULL;
 	int nid;
-	gfp_t local_flags = (flags & GFP_LEVEL_MASK);
+
+	if (flags & __GFP_THISNODE)
+		return NULL;
+
+	zonelist = &NODE_DATA(slab_node(current->mempolicy))
+			->node_zonelists[gfp_zone(flags)];
+	local_flags = (flags & GFP_LEVEL_MASK);
 
 retry:
 	/*
@@ -3374,16 +3349,110 @@
 	if (x)
 		goto retry;
 
-	if (!(flags & __GFP_THISNODE))
-		/* Unable to grow the cache. Fall back to other nodes. */
-		return fallback_alloc(cachep, flags);
-
-	return NULL;
+	return fallback_alloc(cachep, flags);
 
 done:
 	return obj;
 }
-#endif
+
+/**
+ * kmem_cache_alloc_node - Allocate an object on the specified node
+ * @cachep: The cache to allocate from.
+ * @flags: See kmalloc().
+ * @nodeid: node number of the target node.
+ * @caller: return address of caller, used for debug information
+ *
+ * Identical to kmem_cache_alloc but it will allocate memory on the given
+ * node, which can improve the performance for cpu bound structures.
+ *
+ * Fallback to other node is possible if __GFP_THISNODE is not set.
+ */
+static __always_inline void *
+__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
+		   void *caller)
+{
+	unsigned long save_flags;
+	void *ptr;
+
+	cache_alloc_debugcheck_before(cachep, flags);
+	local_irq_save(save_flags);
+
+	if (unlikely(nodeid == -1))
+		nodeid = numa_node_id();
+
+	if (unlikely(!cachep->nodelists[nodeid])) {
+		/* Node not bootstrapped yet */
+		ptr = fallback_alloc(cachep, flags);
+		goto out;
+	}
+
+	if (nodeid == numa_node_id()) {
+		/*
+		 * Use the locally cached objects if possible.
+		 * However ____cache_alloc does not allow fallback
+		 * to other nodes. It may fail while we still have
+		 * objects on other nodes available.
+		 */
+		ptr = ____cache_alloc(cachep, flags);
+		if (ptr)
+			goto out;
+	}
+	/* ___cache_alloc_node can fall back to other nodes */
+	ptr = ____cache_alloc_node(cachep, flags, nodeid);
+  out:
+	local_irq_restore(save_flags);
+	ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
+
+	return ptr;
+}
+
+static __always_inline void *
+__do_cache_alloc(struct kmem_cache *cache, gfp_t flags)
+{
+	void *objp;
+
+	if (unlikely(current->flags & (PF_SPREAD_SLAB | PF_MEMPOLICY))) {
+		objp = alternate_node_alloc(cache, flags);
+		if (objp)
+			goto out;
+	}
+	objp = ____cache_alloc(cache, flags);
+
+	/*
+	 * We may just have run out of memory on the local node.
+	 * ____cache_alloc_node() knows how to locate memory on other nodes
+	 */
+ 	if (!objp)
+ 		objp = ____cache_alloc_node(cache, flags, numa_node_id());
+
+  out:
+	return objp;
+}
+#else
+
+static __always_inline void *
+__do_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
+{
+	return ____cache_alloc(cachep, flags);
+}
+
+#endif /* CONFIG_NUMA */
+
+static __always_inline void *
+__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
+{
+	unsigned long save_flags;
+	void *objp;
+
+	cache_alloc_debugcheck_before(cachep, flags);
+	local_irq_save(save_flags);
+	objp = __do_cache_alloc(cachep, flags);
+	local_irq_restore(save_flags);
+	objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
+	prefetchw(objp);
+
+	return objp;
+}
 
 /*
  * Caller needs to acquire correct kmem_list's list_lock
@@ -3582,57 +3651,6 @@
 }
 
 #ifdef CONFIG_NUMA
-/**
- * kmem_cache_alloc_node - Allocate an object on the specified node
- * @cachep: The cache to allocate from.
- * @flags: See kmalloc().
- * @nodeid: node number of the target node.
- * @caller: return address of caller, used for debug information
- *
- * Identical to kmem_cache_alloc but it will allocate memory on the given
- * node, which can improve the performance for cpu bound structures.
- *
- * Fallback to other node is possible if __GFP_THISNODE is not set.
- */
-static __always_inline void *
-__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
-		int nodeid, void *caller)
-{
-	unsigned long save_flags;
-	void *ptr = NULL;
-
-	cache_alloc_debugcheck_before(cachep, flags);
-	local_irq_save(save_flags);
-
-	if (unlikely(nodeid == -1))
-		nodeid = numa_node_id();
-
-	if (likely(cachep->nodelists[nodeid])) {
-		if (nodeid == numa_node_id()) {
-			/*
-			 * Use the locally cached objects if possible.
-			 * However ____cache_alloc does not allow fallback
-			 * to other nodes. It may fail while we still have
-			 * objects on other nodes available.
-			 */
-			ptr = ____cache_alloc(cachep, flags);
-		}
-		if (!ptr) {
-			/* ___cache_alloc_node can fall back to other nodes */
-			ptr = ____cache_alloc_node(cachep, flags, nodeid);
-		}
-	} else {
-		/* Node not bootstrapped yet */
-		if (!(flags & __GFP_THISNODE))
-			ptr = fallback_alloc(cachep, flags);
-	}
-
-	local_irq_restore(save_flags);
-	ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
-
-	return ptr;
-}
-
 void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
 	return __cache_alloc_node(cachep, flags, nodeid,
@@ -3733,6 +3751,7 @@
 	BUG_ON(virt_to_cache(objp) != cachep);
 
 	local_irq_save(flags);
+	debug_check_no_locks_freed(objp, obj_size(cachep));
 	__cache_free(cachep, objp);
 	local_irq_restore(flags);
 }
@@ -4017,18 +4036,17 @@
  * If we cannot acquire the cache chain mutex then just give up - we'll try
  * again on the next iteration.
  */
-static void cache_reap(struct work_struct *unused)
+static void cache_reap(struct work_struct *w)
 {
 	struct kmem_cache *searchp;
 	struct kmem_list3 *l3;
 	int node = numa_node_id();
+	struct delayed_work *work =
+		container_of(w, struct delayed_work, work);
 
-	if (!mutex_trylock(&cache_chain_mutex)) {
+	if (!mutex_trylock(&cache_chain_mutex))
 		/* Give up. Setup the next iteration. */
-		schedule_delayed_work(&__get_cpu_var(reap_work),
-				      round_jiffies_relative(REAPTIMEOUT_CPUC));
-		return;
-	}
+		goto out;
 
 	list_for_each_entry(searchp, &cache_chain, next) {
 		check_irq_on();
@@ -4071,9 +4089,9 @@
 	mutex_unlock(&cache_chain_mutex);
 	next_reap_node();
 	refresh_cpu_vm_stats(smp_processor_id());
+out:
 	/* Set up the next iteration */
-	schedule_delayed_work(&__get_cpu_var(reap_work),
-		round_jiffies_relative(REAPTIMEOUT_CPUC));
+	schedule_delayed_work(work, round_jiffies_relative(REAPTIMEOUT_CPUC));
 }
 
 #ifdef CONFIG_PROC_FS
diff --git a/mm/truncate.c b/mm/truncate.c
index 5df947d..ebf3fcb 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -85,7 +85,7 @@
  *
  * We need to bale out if page->mapping is no longer equal to the original
  * mapping.  This happens a) when the VM reclaimed the page while we waited on
- * its lock, b) when a concurrent invalidate_inode_pages got there first and
+ * its lock, b) when a concurrent invalidate_mapping_pages got there first and
  * c) when tmpfs swizzles a page between a tmpfs inode and swapper_space.
  */
 static void
@@ -106,7 +106,7 @@
 }
 
 /*
- * This is for invalidate_inode_pages().  That function can be called at
+ * This is for invalidate_mapping_pages().  That function can be called at
  * any time, and is not supposed to throw away dirty pages.  But pages can
  * be marked dirty at any time too, so use remove_mapping which safely
  * discards clean, unused pages.
@@ -310,12 +310,7 @@
 	}
 	return ret;
 }
-
-unsigned long invalidate_inode_pages(struct address_space *mapping)
-{
-	return invalidate_mapping_pages(mapping, 0, ~0UL);
-}
-EXPORT_SYMBOL(invalidate_inode_pages);
+EXPORT_SYMBOL(invalidate_mapping_pages);
 
 /*
  * This is like invalidate_complete_page(), except it ignores the page's
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 86897ee..9eef486 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -699,7 +699,7 @@
  *	that it is big enough to cover the vma. Will return failure if
  *	that criteria isn't met.
  *
- *	Similar to remap_pfn_range (see mm/memory.c)
+ *	Similar to remap_pfn_range() (see mm/memory.c)
  */
 int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
 						unsigned long pgoff)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 7430df6..0655d5f 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -679,7 +679,7 @@
 		nr_taken = isolate_lru_pages(sc->swap_cluster_max,
 					     &zone->inactive_list,
 					     &page_list, &nr_scan);
-		zone->nr_inactive -= nr_taken;
+		__mod_zone_page_state(zone, NR_INACTIVE, -nr_taken);
 		zone->pages_scanned += nr_scan;
 		spin_unlock_irq(&zone->lru_lock);
 
@@ -740,7 +740,8 @@
 
 static inline int zone_is_near_oom(struct zone *zone)
 {
-	return zone->pages_scanned >= (zone->nr_active + zone->nr_inactive)*3;
+	return zone->pages_scanned >= (zone_page_state(zone, NR_ACTIVE)
+				+ zone_page_state(zone, NR_INACTIVE))*3;
 }
 
 /*
@@ -825,7 +826,7 @@
 	pgmoved = isolate_lru_pages(nr_pages, &zone->active_list,
 				    &l_hold, &pgscanned);
 	zone->pages_scanned += pgscanned;
-	zone->nr_active -= pgmoved;
+	__mod_zone_page_state(zone, NR_ACTIVE, -pgmoved);
 	spin_unlock_irq(&zone->lru_lock);
 
 	while (!list_empty(&l_hold)) {
@@ -857,7 +858,7 @@
 		list_move(&page->lru, &zone->inactive_list);
 		pgmoved++;
 		if (!pagevec_add(&pvec, page)) {
-			zone->nr_inactive += pgmoved;
+			__mod_zone_page_state(zone, NR_INACTIVE, pgmoved);
 			spin_unlock_irq(&zone->lru_lock);
 			pgdeactivate += pgmoved;
 			pgmoved = 0;
@@ -867,7 +868,7 @@
 			spin_lock_irq(&zone->lru_lock);
 		}
 	}
-	zone->nr_inactive += pgmoved;
+	__mod_zone_page_state(zone, NR_INACTIVE, pgmoved);
 	pgdeactivate += pgmoved;
 	if (buffer_heads_over_limit) {
 		spin_unlock_irq(&zone->lru_lock);
@@ -885,14 +886,14 @@
 		list_move(&page->lru, &zone->active_list);
 		pgmoved++;
 		if (!pagevec_add(&pvec, page)) {
-			zone->nr_active += pgmoved;
+			__mod_zone_page_state(zone, NR_ACTIVE, pgmoved);
 			pgmoved = 0;
 			spin_unlock_irq(&zone->lru_lock);
 			__pagevec_release(&pvec);
 			spin_lock_irq(&zone->lru_lock);
 		}
 	}
-	zone->nr_active += pgmoved;
+	__mod_zone_page_state(zone, NR_ACTIVE, pgmoved);
 
 	__count_zone_vm_events(PGREFILL, zone, pgscanned);
 	__count_vm_events(PGDEACTIVATE, pgdeactivate);
@@ -918,14 +919,16 @@
 	 * Add one to `nr_to_scan' just to make sure that the kernel will
 	 * slowly sift through the active list.
 	 */
-	zone->nr_scan_active += (zone->nr_active >> priority) + 1;
+	zone->nr_scan_active +=
+		(zone_page_state(zone, NR_ACTIVE) >> priority) + 1;
 	nr_active = zone->nr_scan_active;
 	if (nr_active >= sc->swap_cluster_max)
 		zone->nr_scan_active = 0;
 	else
 		nr_active = 0;
 
-	zone->nr_scan_inactive += (zone->nr_inactive >> priority) + 1;
+	zone->nr_scan_inactive +=
+		(zone_page_state(zone, NR_INACTIVE) >> priority) + 1;
 	nr_inactive = zone->nr_scan_inactive;
 	if (nr_inactive >= sc->swap_cluster_max)
 		zone->nr_scan_inactive = 0;
@@ -1037,7 +1040,8 @@
 		if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
 			continue;
 
-		lru_pages += zone->nr_active + zone->nr_inactive;
+		lru_pages += zone_page_state(zone, NR_ACTIVE)
+				+ zone_page_state(zone, NR_INACTIVE);
 	}
 
 	for (priority = DEF_PRIORITY; priority >= 0; priority--) {
@@ -1182,7 +1186,8 @@
 		for (i = 0; i <= end_zone; i++) {
 			struct zone *zone = pgdat->node_zones + i;
 
-			lru_pages += zone->nr_active + zone->nr_inactive;
+			lru_pages += zone_page_state(zone, NR_ACTIVE)
+					+ zone_page_state(zone, NR_INACTIVE);
 		}
 
 		/*
@@ -1219,8 +1224,9 @@
 			if (zone->all_unreclaimable)
 				continue;
 			if (nr_slab == 0 && zone->pages_scanned >=
-				    (zone->nr_active + zone->nr_inactive) * 6)
-				zone->all_unreclaimable = 1;
+				(zone_page_state(zone, NR_ACTIVE)
+				+ zone_page_state(zone, NR_INACTIVE)) * 6)
+					zone->all_unreclaimable = 1;
 			/*
 			 * If we've done a decent amount of scanning and
 			 * the reclaim ratio is low, start doing writepage
@@ -1385,18 +1391,22 @@
 
 		/* For pass = 0 we don't shrink the active list */
 		if (pass > 0) {
-			zone->nr_scan_active += (zone->nr_active >> prio) + 1;
+			zone->nr_scan_active +=
+				(zone_page_state(zone, NR_ACTIVE) >> prio) + 1;
 			if (zone->nr_scan_active >= nr_pages || pass > 3) {
 				zone->nr_scan_active = 0;
-				nr_to_scan = min(nr_pages, zone->nr_active);
+				nr_to_scan = min(nr_pages,
+					zone_page_state(zone, NR_ACTIVE));
 				shrink_active_list(nr_to_scan, zone, sc, prio);
 			}
 		}
 
-		zone->nr_scan_inactive += (zone->nr_inactive >> prio) + 1;
+		zone->nr_scan_inactive +=
+			(zone_page_state(zone, NR_INACTIVE) >> prio) + 1;
 		if (zone->nr_scan_inactive >= nr_pages || pass > 3) {
 			zone->nr_scan_inactive = 0;
-			nr_to_scan = min(nr_pages, zone->nr_inactive);
+			nr_to_scan = min(nr_pages,
+				zone_page_state(zone, NR_INACTIVE));
 			ret += shrink_inactive_list(nr_to_scan, zone, sc);
 			if (ret >= nr_pages)
 				return ret;
@@ -1408,12 +1418,7 @@
 
 static unsigned long count_lru_pages(void)
 {
-	struct zone *zone;
-	unsigned long ret = 0;
-
-	for_each_zone(zone)
-		ret += zone->nr_active + zone->nr_inactive;
-	return ret;
+	return global_page_state(NR_ACTIVE) + global_page_state(NR_INACTIVE);
 }
 
 /*
diff --git a/mm/vmstat.c b/mm/vmstat.c
index dc005a0..6c488d6 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -13,39 +13,6 @@
 #include <linux/module.h>
 #include <linux/cpu.h>
 
-void __get_zone_counts(unsigned long *active, unsigned long *inactive,
-			unsigned long *free, struct pglist_data *pgdat)
-{
-	struct zone *zones = pgdat->node_zones;
-	int i;
-
-	*active = 0;
-	*inactive = 0;
-	*free = 0;
-	for (i = 0; i < MAX_NR_ZONES; i++) {
-		*active += zones[i].nr_active;
-		*inactive += zones[i].nr_inactive;
-		*free += zones[i].free_pages;
-	}
-}
-
-void get_zone_counts(unsigned long *active,
-		unsigned long *inactive, unsigned long *free)
-{
-	struct pglist_data *pgdat;
-
-	*active = 0;
-	*inactive = 0;
-	*free = 0;
-	for_each_online_pgdat(pgdat) {
-		unsigned long l, m, n;
-		__get_zone_counts(&l, &m, &n, pgdat);
-		*active += l;
-		*inactive += m;
-		*free += n;
-	}
-}
-
 #ifdef CONFIG_VM_EVENT_COUNTERS
 DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
 EXPORT_PER_CPU_SYMBOL(vm_event_states);
@@ -239,7 +206,7 @@
  * in between and therefore the atomicity vs. interrupt cannot be exploited
  * in a useful way here.
  */
-static void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
+void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
 {
 	struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
 	s8 *p = pcp->vm_stat_diff + item;
@@ -260,9 +227,8 @@
 }
 EXPORT_SYMBOL(__inc_zone_page_state);
 
-void __dec_zone_page_state(struct page *page, enum zone_stat_item item)
+void __dec_zone_state(struct zone *zone, enum zone_stat_item item)
 {
-	struct zone *zone = page_zone(page);
 	struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
 	s8 *p = pcp->vm_stat_diff + item;
 
@@ -275,6 +241,11 @@
 		*p = overstep;
 	}
 }
+
+void __dec_zone_page_state(struct page *page, enum zone_stat_item item)
+{
+	__dec_zone_state(page_zone(page), item);
+}
 EXPORT_SYMBOL(__dec_zone_page_state);
 
 void inc_zone_state(struct zone *zone, enum zone_stat_item item)
@@ -437,6 +408,12 @@
 	.show	= frag_show,
 };
 
+#ifdef CONFIG_ZONE_DMA
+#define TEXT_FOR_DMA(xx) xx "_dma",
+#else
+#define TEXT_FOR_DMA(xx)
+#endif
+
 #ifdef CONFIG_ZONE_DMA32
 #define TEXT_FOR_DMA32(xx) xx "_dma32",
 #else
@@ -449,19 +426,22 @@
 #define TEXT_FOR_HIGHMEM(xx)
 #endif
 
-#define TEXTS_FOR_ZONES(xx) xx "_dma", TEXT_FOR_DMA32(xx) xx "_normal", \
+#define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx "_normal", \
 					TEXT_FOR_HIGHMEM(xx)
 
 static const char * const vmstat_text[] = {
 	/* Zoned VM counters */
+	"nr_free_pages",
+	"nr_active",
+	"nr_inactive",
 	"nr_anon_pages",
 	"nr_mapped",
 	"nr_file_pages",
+	"nr_dirty",
+	"nr_writeback",
 	"nr_slab_reclaimable",
 	"nr_slab_unreclaimable",
 	"nr_page_table_pages",
-	"nr_dirty",
-	"nr_writeback",
 	"nr_unstable",
 	"nr_bounce",
 	"nr_vmscan_write",
@@ -529,17 +509,13 @@
 			   "\n        min      %lu"
 			   "\n        low      %lu"
 			   "\n        high     %lu"
-			   "\n        active   %lu"
-			   "\n        inactive %lu"
 			   "\n        scanned  %lu (a: %lu i: %lu)"
 			   "\n        spanned  %lu"
 			   "\n        present  %lu",
-			   zone->free_pages,
+			   zone_page_state(zone, NR_FREE_PAGES),
 			   zone->pages_min,
 			   zone->pages_low,
 			   zone->pages_high,
-			   zone->nr_active,
-			   zone->nr_inactive,
 			   zone->pages_scanned,
 			   zone->nr_scan_active, zone->nr_scan_inactive,
 			   zone->spanned_pages,
@@ -563,12 +539,6 @@
 
 			pageset = zone_pcp(zone, i);
 			for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
-				if (pageset->pcp[j].count)
-					break;
-			}
-			if (j == ARRAY_SIZE(pageset->pcp))
-				continue;
-			for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
 				seq_printf(m,
 					   "\n    cpu: %i pcp: %i"
 					   "\n              count: %i"
diff --git a/net/802/fc.c b/net/802/fc.c
index 2a27e37..675d9ba 100644
--- a/net/802/fc.c
+++ b/net/802/fc.c
@@ -1,6 +1,6 @@
 /*
  * NET3:	Fibre Channel device handling subroutines
- * 
+ *
  *		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
@@ -14,7 +14,6 @@
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -31,18 +30,18 @@
 #include <net/arp.h>
 
 /*
- *	Put the headers on a Fibre Channel packet. 
+ *	Put the headers on a Fibre Channel packet.
  */
- 
+
 static int fc_header(struct sk_buff *skb, struct net_device *dev,
 		     unsigned short type,
-		     void *daddr, void *saddr, unsigned len) 
+		     void *daddr, void *saddr, unsigned len)
 {
 	struct fch_hdr *fch;
 	int hdr_len;
 
-	/* 
-	 * Add the 802.2 SNAP header if IP as the IPv4 code calls  
+	/*
+	 * Add the 802.2 SNAP header if IP as the IPv4 code calls
 	 * dev->hard_header directly.
 	 */
 	if (type == ETH_P_IP || type == ETH_P_ARP)
@@ -60,7 +59,7 @@
 	else
 	{
 		hdr_len = sizeof(struct fch_hdr);
-		fch = (struct fch_hdr *)skb_push(skb, hdr_len);	
+		fch = (struct fch_hdr *)skb_push(skb, hdr_len);
 	}
 
 	if(saddr)
@@ -68,20 +67,20 @@
 	else
 		memcpy(fch->saddr,dev->dev_addr,dev->addr_len);
 
-	if(daddr) 
+	if(daddr)
 	{
 		memcpy(fch->daddr,daddr,dev->addr_len);
 		return(hdr_len);
 	}
 	return -hdr_len;
 }
-	
+
 /*
  *	A neighbour discovery of some species (eg arp) has completed. We
  *	can now send the packet.
  */
- 
-static int fc_rebuild_header(struct sk_buff *skb) 
+
+static int fc_rebuild_header(struct sk_buff *skb)
 {
 	struct fch_hdr *fch=(struct fch_hdr *)skb->data;
 	struct fcllc *fcllc=(struct fcllc *)(skb->data+sizeof(struct fch_hdr));
@@ -100,7 +99,7 @@
 {
 	dev->hard_header	= fc_header;
 	dev->rebuild_header	= fc_rebuild_header;
-                
+
 	dev->type		= ARPHRD_IEEE802;
 	dev->hard_header_len	= FC_HLEN;
 	dev->mtu		= 2024;
diff --git a/net/802/fddi.c b/net/802/fddi.c
index 797c6d9..ace6386 100644
--- a/net/802/fddi.c
+++ b/net/802/fddi.c
@@ -15,7 +15,7 @@
  *			Mark Evans, <evansmp@uhura.aston.ac.uk>
  *			Florian La Roche, <rzsfl@rz.uni-sb.de>
  *			Alan Cox, <gw4pts@gw4pts.ampr.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
@@ -25,12 +25,11 @@
  *		Alan Cox		:	New arp/rebuild header
  *		Maciej W. Rozycki	:	IPv6 support
  */
- 
+
 #include <linux/module.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -57,7 +56,7 @@
 {
 	int hl = FDDI_K_SNAP_HLEN;
 	struct fddihdr *fddi;
-	
+
 	if(type != ETH_P_IP && type != ETH_P_IPV6 && type != ETH_P_ARP)
 		hl=FDDI_K_8022_HLEN-3;
 	fddi = (struct fddihdr *)skb_push(skb, hl);
@@ -74,7 +73,7 @@
 	}
 
 	/* Set the source and destination hardware addresses */
-	 
+
 	if (saddr != NULL)
 		memcpy(fddi->saddr, saddr, dev->addr_len);
 	else
@@ -95,7 +94,7 @@
  * (or in future other address resolution) has completed on
  * this sk_buff.  We now let ARP fill in the other fields.
  */
- 
+
 static int fddi_rebuild_header(struct sk_buff	*skb)
 {
 	struct fddihdr *fddi = (struct fddihdr *)skb->data;
@@ -105,7 +104,7 @@
 		/* Try to get ARP to resolve the header and fill destination address */
 		return arp_find(fddi->daddr, skb);
 	else
-#endif	
+#endif
 	{
 		printk("%s: Don't know how to resolve type %04X addresses.\n",
 		       skb->dev->name, ntohs(fddi->hdr.llc_snap.ethertype));
@@ -120,19 +119,19 @@
  * up.  It's used to fill in specific skb fields and to set
  * the proper pointer to the start of packet data (skb->data).
  */
- 
+
 __be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct fddihdr *fddi = (struct fddihdr *)skb->data;
 	__be16 type;
-	
+
 	/*
 	 * Set mac.raw field to point to FC byte, set data field to point
 	 * to start of packet data.  Assume 802.2 SNAP frames for now.
 	 */
 
 	skb->mac.raw = skb->data;	/* point to frame control (FC) */
-	
+
 	if(fddi->hdr.llc_8022_1.dsap==0xe0)
 	{
 		skb_pull(skb, FDDI_K_8022_HLEN-3);
@@ -143,9 +142,9 @@
 		skb_pull(skb, FDDI_K_SNAP_HLEN);		/* adjust for 21 byte header */
 		type=fddi->hdr.llc_snap.ethertype;
 	}
-	
+
 	/* Set packet type based on destination address and flag settings */
-			
+
 	if (*fddi->daddr & 0x01)
 	{
 		if (memcmp(fddi->daddr, dev->broadcast, FDDI_K_ALEN) == 0)
@@ -153,7 +152,7 @@
 		else
 			skb->pkt_type = PACKET_MULTICAST;
 	}
-	
+
 	else if (dev->flags & IFF_PROMISC)
 	{
 		if (memcmp(fddi->daddr, dev->dev_addr, FDDI_K_ALEN))
@@ -187,7 +186,7 @@
 	dev->addr_len		= FDDI_K_ALEN;
 	dev->tx_queue_len	= 100;			/* Long queues on FDDI */
 	dev->flags		= IFF_BROADCAST | IFF_MULTICAST;
-	
+
 	memset(dev->broadcast, 0xFF, FDDI_K_ALEN);
 }
 
diff --git a/net/802/hippi.c b/net/802/hippi.c
index 579e2dd..578f2a3 100644
--- a/net/802/hippi.c
+++ b/net/802/hippi.c
@@ -23,7 +23,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -39,7 +38,7 @@
 #include <asm/system.h>
 
 /*
- * Create the HIPPI MAC header for an arbitrary protocol layer 
+ * Create the HIPPI MAC header for an arbitrary protocol layer
  *
  * saddr=NULL	means use device source address
  * daddr=NULL	means leave destination address (eg unresolved arp)
@@ -104,8 +103,8 @@
 	/*
 	 * Only IP is currently supported
 	 */
-	 
-	if(hip->snap.ethertype != __constant_htons(ETH_P_IP)) 
+
+	if(hip->snap.ethertype != __constant_htons(ETH_P_IP))
 	{
 		printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n",skb->dev->name,ntohs(hip->snap.ethertype));
 		return 0;
@@ -122,11 +121,11 @@
 /*
  *	Determine the packet's protocol ID.
  */
- 
+
 __be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct hippi_hdr *hip;
-	
+
 	hip = (struct hippi_hdr *) skb->data;
 
 	/*
@@ -173,10 +172,10 @@
 {
 	/* Never send broadcast/multicast ARP messages */
 	p->mcast_probes = 0;
- 
+
 	/* In IPv6 unicast probes are valid even on NBMA,
 	* because they are encapsulated in normal IPv6 protocol.
-	* Should be a generic flag. 
+	* Should be a generic flag.
 	*/
 	if (p->tbl->family != AF_INET6)
 		p->ucast_probes = 0;
@@ -193,7 +192,7 @@
 	dev->hard_header_parse		= NULL;
 	dev->hard_header_cache		= NULL;
 	dev->header_cache_update	= NULL;
-	dev->neigh_setup 		= hippi_neigh_setup_dev; 
+	dev->neigh_setup 		= hippi_neigh_setup_dev;
 
 	/*
 	 * We don't support HIPPI `ARP' for the time being, and probably
@@ -210,9 +209,9 @@
 
 	/*
 	 * HIPPI doesn't support broadcast+multicast and we only use
-	 * static ARP tables. ARP is disabled by hippi_neigh_setup_dev. 
+	 * static ARP tables. ARP is disabled by hippi_neigh_setup_dev.
 	 */
-	dev->flags = 0; 
+	dev->flags = 0;
 }
 
 /**
diff --git a/net/802/psnap.c b/net/802/psnap.c
index 270b9d2..6e7c212 100644
--- a/net/802/psnap.c
+++ b/net/802/psnap.c
@@ -117,7 +117,7 @@
  */
 struct datalink_proto *register_snap_client(unsigned char *desc,
 					    int (*rcvfunc)(struct sk_buff *,
-						    	   struct net_device *,
+							   struct net_device *,
 							   struct packet_type *,
 							   struct net_device *))
 {
diff --git a/net/802/tr.c b/net/802/tr.c
index 829deb4..96bd144 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -1,6 +1,6 @@
 /*
  * NET3:	Token ring device handling subroutines
- * 
+ *
  *		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
@@ -12,7 +12,7 @@
  *              22 Jun 98 Paul Norton <p.norton@computer.org> Rearranged
  *              tr_header and tr_type_trans to handle passing IPX SNAP and
  *              802.2 through the correct layers. Eliminated tr_reformat.
- *        
+ *
  */
 
 #include <asm/uaccess.h>
@@ -45,7 +45,7 @@
 /*
  *	Each RIF entry we learn is kept this way
  */
- 
+
 struct rif_cache {
 	unsigned char addr[TR_ALEN];
 	int iface;
@@ -62,7 +62,7 @@
  *	We hash the RIF cache 32 ways. We do after all have to look it
  *	up a lot.
  */
- 
+
 static struct rif_cache *rif_table[RIF_TABLE_SIZE];
 
 static DEFINE_SPINLOCK(rif_lock);
@@ -71,7 +71,7 @@
 /*
  *	Garbage disposal timer.
  */
- 
+
 static struct timer_list rif_timer;
 
 int sysctl_tr_rif_timeout = 60*10*HZ;
@@ -96,16 +96,16 @@
  *	Put the headers on a token ring packet. Token ring source routing
  *	makes this a little more exciting than on ethernet.
  */
- 
+
 static int tr_header(struct sk_buff *skb, struct net_device *dev,
 		     unsigned short type,
-		     void *daddr, void *saddr, unsigned len) 
+		     void *daddr, void *saddr, unsigned len)
 {
 	struct trh_hdr *trh;
 	int hdr_len;
 
-	/* 
-	 * Add the 802.2 SNAP header if IP as the IPv4/IPv6 code calls  
+	/*
+	 * Add the 802.2 SNAP header if IP as the IPv4/IPv6 code calls
 	 * dev->hard_header directly.
 	 */
 	if (type == ETH_P_IP || type == ETH_P_IPV6 || type == ETH_P_ARP)
@@ -123,7 +123,7 @@
 	else
 	{
 		hdr_len = sizeof(struct trh_hdr);
-		trh = (struct trh_hdr *)skb_push(skb, hdr_len);	
+		trh = (struct trh_hdr *)skb_push(skb, hdr_len);
 	}
 
 	trh->ac=AC;
@@ -137,8 +137,8 @@
 	/*
 	 *	Build the destination and then source route the frame
 	 */
-	 
-	if(daddr) 
+
+	if(daddr)
 	{
 		memcpy(trh->daddr,daddr,dev->addr_len);
 		tr_source_route(skb,trh,dev);
@@ -147,13 +147,13 @@
 
 	return -hdr_len;
 }
-	
+
 /*
  *	A neighbour discovery of some species (eg arp) has completed. We
  *	can now send the packet.
  */
- 
-static int tr_rebuild_header(struct sk_buff *skb) 
+
+static int tr_rebuild_header(struct sk_buff *skb)
 {
 	struct trh_hdr *trh=(struct trh_hdr *)skb->data;
 	struct trllc *trllc=(struct trllc *)(skb->data+sizeof(struct trh_hdr));
@@ -162,7 +162,7 @@
 	/*
 	 *	FIXME: We don't yet support IPv6 over token rings
 	 */
-	 
+
 	if(trllc->ethertype != htons(ETH_P_IP)) {
 		printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n", ntohs(trllc->ethertype));
 		return 0;
@@ -172,39 +172,39 @@
 	if(arp_find(trh->daddr, skb)) {
 			return 1;
 	}
-	else 
-#endif	
-	{	
-		tr_source_route(skb,trh,dev); 
+	else
+#endif
+	{
+		tr_source_route(skb,trh,dev);
 		return 0;
 	}
 }
-	
+
 /*
  *	Some of this is a bit hackish. We intercept RIF information
  *	used for source routing. We also grab IP directly and don't feed
  *	it via SNAP.
  */
- 
+
 __be16 tr_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 
 	struct trh_hdr *trh=(struct trh_hdr *)skb->data;
 	struct trllc *trllc;
 	unsigned riflen=0;
-	
+
 	skb->mac.raw = skb->data;
-	
-       	if(trh->saddr[0] & TR_RII)
+
+	if(trh->saddr[0] & TR_RII)
 		riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
 
 	trllc = (struct trllc *)(skb->data+sizeof(struct trh_hdr)-TR_MAXRIFLEN+riflen);
 
 	skb_pull(skb,sizeof(struct trh_hdr)-TR_MAXRIFLEN+riflen);
 
-	if(*trh->daddr & 0x80) 
+	if(*trh->daddr & 0x80)
 	{
-		if(!memcmp(trh->daddr,dev->broadcast,TR_ALEN)) 	
+		if(!memcmp(trh->daddr,dev->broadcast,TR_ALEN))
 			skb->pkt_type=PACKET_BROADCAST;
 		else
 			skb->pkt_type=PACKET_MULTICAST;
@@ -213,7 +213,7 @@
 	{
 		skb->pkt_type=PACKET_MULTICAST;
 	}
-	else if(dev->flags & IFF_PROMISC) 
+	else if(dev->flags & IFF_PROMISC)
 	{
 		if(memcmp(trh->daddr, dev->dev_addr, TR_ALEN))
 			skb->pkt_type=PACKET_OTHERHOST;
@@ -221,10 +221,10 @@
 
 	if ((skb->pkt_type != PACKET_BROADCAST) &&
 	    (skb->pkt_type != PACKET_MULTICAST))
-		tr_add_rif_info(trh,dev) ; 
+		tr_add_rif_info(trh,dev) ;
 
 	/*
-	 * Strip the SNAP header from ARP packets since we don't 
+	 * Strip the SNAP header from ARP packets since we don't
 	 * pass them through to the 802.2/SNAP layers.
 	 */
 
@@ -241,32 +241,32 @@
 }
 
 /*
- *	We try to do source routing... 
+ *	We try to do source routing...
  */
 
-void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device *dev) 
+void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device *dev)
 {
 	int slack;
 	unsigned int hash;
 	struct rif_cache *entry;
 	unsigned char *olddata;
 	unsigned long flags;
-	static const unsigned char mcast_func_addr[] 
+	static const unsigned char mcast_func_addr[]
 		= {0xC0,0x00,0x00,0x04,0x00,0x00};
-	
+
 	spin_lock_irqsave(&rif_lock, flags);
 
 	/*
-	 *	Broadcasts are single route as stated in RFC 1042 
+	 *	Broadcasts are single route as stated in RFC 1042
 	 */
 	if( (!memcmp(&(trh->daddr[0]),&(dev->broadcast[0]),TR_ALEN)) ||
 	    (!memcmp(&(trh->daddr[0]),&(mcast_func_addr[0]), TR_ALEN))  )
 	{
-		trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)  
+		trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)
 			       | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
 		trh->saddr[0]|=TR_RII;
 	}
-	else 
+	else
 	{
 		hash = rif_hash(trh->daddr);
 		/*
@@ -277,7 +277,7 @@
 		/*
 		 *	If we found an entry we can route the frame.
 		 */
-		if(entry) 
+		if(entry)
 		{
 #if TR_SR_DEBUG
 printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0],
@@ -287,7 +287,7 @@
 			{
 				trh->rcf=entry->rcf;
 				memcpy(&trh->rseg[0],&entry->rseg[0],8*sizeof(unsigned short));
-				trh->rcf^=htons(TR_RCF_DIR_BIT);	
+				trh->rcf^=htons(TR_RCF_DIR_BIT);
 				trh->rcf&=htons(0x1fff);	/* Issam Chehab <ichehab@madge1.demon.co.uk> */
 
 				trh->saddr[0]|=TR_RII;
@@ -301,14 +301,14 @@
 			}
 			entry->last_used=jiffies;
 		}
-		else 
+		else
 		{
 			/*
 			 *	Without the information we simply have to shout
 			 *	on the wire. The replies should rapidly clean this
 			 *	situation up.
 			 */
-			trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)  
+			trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)
 				       | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
 			trh->saddr[0]|=TR_RII;
 #if TR_SR_DEBUG
@@ -320,7 +320,7 @@
 	/* Compress the RIF here so we don't have to do it in the driver(s) */
 	if (!(trh->saddr[0] & 0x80))
 		slack = 18;
-	else 
+	else
 		slack = 18 - ((ntohs(trh->rcf) & TR_RCF_LEN_MASK)>>8);
 	olddata = skb->data;
 	spin_unlock_irqrestore(&rif_lock, flags);
@@ -333,7 +333,7 @@
  *	We have learned some new RIF information for our source
  *	routing.
  */
- 
+
 static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev)
 {
 	unsigned int hash, rii_p = 0;
@@ -343,29 +343,29 @@
 
 	spin_lock_irqsave(&rif_lock, flags);
 	saddr0 = trh->saddr[0];
-	
+
 	/*
 	 *	Firstly see if the entry exists
 	 */
 
-       	if(trh->saddr[0] & TR_RII)
+	if(trh->saddr[0] & TR_RII)
 	{
 		trh->saddr[0]&=0x7f;
 		if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2)
 		{
 			rii_p = 1;
-	        }
+		}
 	}
 
 	hash = rif_hash(trh->saddr);
 	for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);entry=entry->next);
 
-	if(entry==NULL) 
+	if(entry==NULL)
 	{
 #if TR_SR_DEBUG
 printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
 		trh->saddr[0],trh->saddr[1],trh->saddr[2],
-       		trh->saddr[3],trh->saddr[4],trh->saddr[5],
+		trh->saddr[3],trh->saddr[4],trh->saddr[5],
 		ntohs(trh->rcf));
 #endif
 		/*
@@ -377,7 +377,7 @@
 		 */
 		entry=kmalloc(sizeof(struct rif_cache),GFP_ATOMIC);
 
-		if(!entry) 
+		if(!entry)
 		{
 			printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry !\n");
 			spin_unlock_irqrestore(&rif_lock, flags);
@@ -400,13 +400,13 @@
 		{
 			entry->local_ring = 1;
 		}
-	} 	
+	}
 	else	/* Y. Tahara added */
-	{ 
+	{
 		/*
 		 *	Update existing entries
 		 */
-		if (!entry->local_ring) 
+		if (!entry->local_ring)
 		    if (entry->rcf != (trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK)) &&
 			 !(trh->rcf & htons(TR_RCF_BROADCAST_MASK)))
 		    {
@@ -417,9 +417,9 @@
 		ntohs(trh->rcf));
 #endif
 			    entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK);
-        		    memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
-		    }                                         
-           	entry->last_used=jiffies;               
+			    memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
+		    }
+		entry->last_used=jiffies;
 	}
 	trh->saddr[0]=saddr0; /* put the routing indicator back for tcpdump */
 	spin_unlock_irqrestore(&rif_lock, flags);
@@ -429,16 +429,16 @@
  *	Scan the cache with a timer and see what we need to throw out.
  */
 
-static void rif_check_expire(unsigned long dummy) 
+static void rif_check_expire(unsigned long dummy)
 {
 	int i;
 	unsigned long flags, next_interval = jiffies + sysctl_tr_rif_timeout/2;
 
 	spin_lock_irqsave(&rif_lock, flags);
-	
+
 	for(i =0; i < RIF_TABLE_SIZE; i++) {
 		struct rif_cache *entry, **pentry;
-		
+
 		pentry = rif_table+i;
 		while((entry=*pentry) != NULL) {
 			unsigned long expires
@@ -455,7 +455,7 @@
 			}
 		}
 	}
-	
+
 	spin_unlock_irqrestore(&rif_lock, flags);
 
 	mod_timer(&rif_timer, next_interval);
@@ -466,7 +466,7 @@
  *	Generate the /proc/net information for the token ring RIF
  *	routing.
  */
- 
+
 #ifdef CONFIG_PROC_FS
 
 static struct rif_cache *rif_get_idx(loff_t pos)
@@ -475,7 +475,7 @@
 	struct rif_cache *entry;
 	loff_t off = 0;
 
-	for(i = 0; i < RIF_TABLE_SIZE; i++) 
+	for(i = 0; i < RIF_TABLE_SIZE; i++)
 		for(entry = rif_table[i]; entry; entry = entry->next) {
 			if (off == pos)
 				return entry;
@@ -504,7 +504,7 @@
 		goto scan;
 	}
 
-	if (ent->next) 
+	if (ent->next)
 		return ent->next;
 
 	i = rif_hash(ent->addr);
@@ -541,13 +541,13 @@
 			   ttl/HZ);
 
 			if (entry->local_ring)
-			        seq_puts(seq, "local\n");
+				seq_puts(seq, "local\n");
 			else {
 
 				seq_printf(seq, "%04X", ntohs(entry->rcf));
-				rcf_len = ((ntohs(entry->rcf) & TR_RCF_LEN_MASK)>>8)-2; 
+				rcf_len = ((ntohs(entry->rcf) & TR_RCF_LEN_MASK)>>8)-2;
 				if (rcf_len)
-				        rcf_len >>= 1;
+					rcf_len >>= 1;
 				for(j = 1; j < rcf_len; j++) {
 					if(j==1) {
 						segment=ntohs(entry->rseg[j-1])>>4;
@@ -559,7 +559,7 @@
 				}
 				seq_putc(seq, '\n');
 			}
-	   	}
+		}
 	return 0;
 }
 
@@ -576,7 +576,7 @@
 	return seq_open(file, &rif_seq_ops);
 }
 
-static struct file_operations rif_seq_fops = {
+static const struct file_operations rif_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = rif_seq_open,
 	.read    = seq_read,
@@ -591,7 +591,7 @@
 	/*
 	 *	Configure and register
 	 */
-	
+
 	dev->hard_header	= tr_header;
 	dev->rebuild_header	= tr_rebuild_header;
 
@@ -600,7 +600,7 @@
 	dev->mtu		= 2000;
 	dev->addr_len		= TR_ALEN;
 	dev->tx_queue_len	= 100;	/* Long queues on tr */
-	
+
 	memset(dev->broadcast,0xFF, TR_ALEN);
 
 	/* New-style flags. */
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 18fcb9f..c1c205f 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -5,7 +5,7 @@
  * Authors:	Ben Greear <greearb@candelatech.com>
  *              Please send support related email to: vlan@scry.wanfear.com
  *              VLAN Home Page: http://www.candelatech.com/~greear/vlan.html
- * 
+ *
  * Fixes:
  *              Fix for packet capture - Nick Eggleston <nick@dccinc.com>;
  *		Add HW acceleration hooks - David S. Miller <davem@redhat.com>;
@@ -72,7 +72,7 @@
 /*
  * Function vlan_proto_init (pro)
  *
- *    Initialize VLAN protocol layer, 
+ *    Initialize VLAN protocol layer,
  *
  */
 static int __init vlan_proto_init(void)
@@ -87,7 +87,7 @@
 	/* proc file system initialization */
 	err = vlan_proc_init();
 	if (err < 0) {
-		printk(KERN_ERR 
+		printk(KERN_ERR
 		       "%s %s: can't create entry in proc filesystem!\n",
 		       __FUNCTION__, VLAN_NAME);
 		return err;
@@ -108,7 +108,7 @@
 	return 0;
 }
 
-/* Cleanup all vlan devices 
+/* Cleanup all vlan devices
  * Note: devices that have been registered that but not
  * brought up will exist but have no module ref count.
  */
@@ -132,7 +132,7 @@
 /*
  *     Module 'remove' entry point.
  *     o delete /proc/net/router directory and static entries.
- */ 
+ */
 static void __exit vlan_cleanup_module(void)
 {
 	int i;
@@ -184,7 +184,7 @@
 	struct vlan_group *grp = __vlan_find_group(real_dev->ifindex);
 
 	if (grp)
-                return grp->vlan_devices[VID];
+		return grp->vlan_devices[VID];
 
 	return NULL;
 }
@@ -269,7 +269,7 @@
 		}
 	}
 
-        return ret;
+	return ret;
 }
 
 static int unregister_vlan_device(const char *vlan_IF_name)
@@ -295,7 +295,7 @@
 			if (ret == 1)
 				ret = 0;
 		} else {
-			printk(VLAN_ERR 
+			printk(VLAN_ERR
 			       "%s: ERROR:	Tried to remove a non-vlan device "
 			       "with VLAN code, name: %s  priv_flags: %hX\n",
 			       __FUNCTION__, dev->name, dev->priv_flags);
@@ -315,7 +315,7 @@
 static void vlan_setup(struct net_device *new_dev)
 {
 	SET_MODULE_OWNER(new_dev);
-	    
+
 	/* new_dev->ifindex = 0;  it will be set when added to
 	 * the global list.
 	 * iflink is set as well.
@@ -324,7 +324,7 @@
 
 	/* Make this thing known as a VLAN device */
 	new_dev->priv_flags |= IFF_802_1Q_VLAN;
-				
+
 	/* Set us up to have no queue, as the underlying Hardware device
 	 * can do all the queueing we could want.
 	 */
@@ -461,7 +461,7 @@
 	default:
 		snprintf(name, IFNAMSIZ, "vlan%.4i", VLAN_ID);
 	};
-		    
+
 	new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name,
 			       vlan_setup);
 
@@ -477,7 +477,7 @@
 
 	new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
 					     (1<<__LINK_STATE_DORMANT))) |
-			 (1<<__LINK_STATE_PRESENT); 
+			 (1<<__LINK_STATE_PRESENT);
 
 	/* need 4 bytes for extra VLAN header info,
 	 * hope the underlying device can handle it.
@@ -496,7 +496,7 @@
 	VLAN_MEM_DBG("new_dev->priv malloc, addr: %p  size: %i\n",
 		     new_dev->priv,
 		     sizeof(struct vlan_dev_info));
-	    
+
 	memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len);
 	memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
 	new_dev->addr_len = real_dev->addr_len;
@@ -521,7 +521,7 @@
 	printk(VLAN_DBG "About to go find the group for idx: %i\n",
 	       real_dev->ifindex);
 #endif
-	    
+
 	if (register_netdevice(new_dev))
 		goto out_free_newdev;
 
@@ -543,22 +543,22 @@
 		grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
 		if (!grp)
 			goto out_free_unregister;
-					
+
 		/* printk(KERN_ALERT "VLAN REGISTER:  Allocated new group.\n"); */
 		grp->real_dev_ifindex = real_dev->ifindex;
 
-		hlist_add_head_rcu(&grp->hlist, 
+		hlist_add_head_rcu(&grp->hlist,
 				   &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
 
 		if (real_dev->features & NETIF_F_HW_VLAN_RX)
 			real_dev->vlan_rx_register(real_dev, grp);
 	}
-	    
+
 	grp->vlan_devices[VLAN_ID] = new_dev;
 
 	if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */
-            	printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
-					                 new_dev->name);
+		printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
+							 new_dev->name);
 
 	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
 		real_dev->vlan_rx_add_vid(real_dev, VLAN_ID);
@@ -635,7 +635,7 @@
 			vlandev = grp->vlan_devices[i];
 			if (!vlandev)
 				continue;
-				
+
 			flgs = vlandev->flags;
 			if (flgs & IFF_UP)
 				continue;
@@ -643,7 +643,7 @@
 			dev_change_flags(vlandev, flgs | IFF_UP);
 		}
 		break;
-		
+
 	case NETDEV_UNREGISTER:
 		/* Delete all VLANs for this dev. */
 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
@@ -755,8 +755,8 @@
 		/* TODO:  Implement
 		   err = vlan_dev_get_ingress_priority(args);
 		   if (copy_to_user((void*)arg, &args,
-		        sizeof(struct vlan_ioctl_args))) {
-		        err = -EFAULT;
+			sizeof(struct vlan_ioctl_args))) {
+			err = -EFAULT;
 		   }
 		*/
 		err = -EINVAL;
@@ -765,8 +765,8 @@
 		/* TODO:  Implement
 		   err = vlan_dev_get_egress_priority(args.device1, &(args.args);
 		   if (copy_to_user((void*)arg, &args,
-		        sizeof(struct vlan_ioctl_args))) {
-		        err = -EFAULT;
+			sizeof(struct vlan_ioctl_args))) {
+			err = -EFAULT;
 		   }
 		*/
 		err = -EINVAL;
@@ -788,7 +788,7 @@
 		args.u.VID = vid;
 		if (copy_to_user(arg, &args,
 				 sizeof(struct vlan_ioctl_args))) {
-                      err = -EFAULT;
+		      err = -EFAULT;
 		}
 		break;
 
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 9ae3a14..1976cdb 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -9,8 +9,8 @@
 #define VLAN_ERR KERN_ERR
 #define VLAN_INF KERN_INFO
 #define VLAN_DBG KERN_ALERT /* change these... to debug, having a hard time
-                             * changing the log level at run-time..for some reason.
-                             */
+			     * changing the log level at run-time..for some reason.
+			     */
 
 /*
 
@@ -24,7 +24,7 @@
 */
 
 /* This way they don't do anything! */
-#define VLAN_MEM_DBG(x, y, z) 
+#define VLAN_MEM_DBG(x, y, z)
 #define VLAN_FMEM_DBG(x, y)
 
 
@@ -51,10 +51,10 @@
 /* found in vlan_dev.c */
 int vlan_dev_rebuild_header(struct sk_buff *skb);
 int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
-                  struct packet_type *ptype, struct net_device *orig_dev);
+		  struct packet_type *ptype, struct net_device *orig_dev);
 int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
-                         unsigned short type, void *daddr, void *saddr,
-                         unsigned len);
+			 unsigned short type, void *daddr, void *saddr,
+			 unsigned len);
 int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
 int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
 int vlan_dev_change_mtu(struct net_device *dev, int new_mtu);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 60a508e..2fc8fe2 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -5,14 +5,14 @@
  * Authors:	Ben Greear <greearb@candelatech.com>
  *              Please send support related email to: vlan@scry.wanfear.com
  *              VLAN Home Page: http://www.candelatech.com/~greear/vlan.html
- * 
+ *
  * Fixes:       Mar 22 2001: Martin Bokaemper <mbokaemper@unispherenetworks.com>
  *                - reset skb->pkt_type on incoming packets when MAC was changed
  *                - see that changed MAC is saddr for outgoing packets
  *              Oct 20, 2001:  Ard van Breeman:
  *                - Fix MC-list, finally.
  *                - Flush MC-list on VLAN destroy.
- *                
+ *
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -58,12 +58,12 @@
 
 		/* TODO:  Confirm this will work with VLAN headers... */
 		return arp_find(veth->h_dest, skb);
-#endif	
+#endif
 	default:
 		printk(VLAN_DBG
-		       "%s: unable to resolve type %X addresses.\n", 
+		       "%s: unable to resolve type %X addresses.\n",
 		       dev->name, ntohs(veth->h_vlan_encapsulated_proto));
-	 
+
 		memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
 		break;
 	};
@@ -91,7 +91,7 @@
 }
 
 /*
- *	Determine the packet's protocol ID. The rule here is that we 
+ *	Determine the packet's protocol ID. The rule here is that we
  *	assume 802.3 if the type field is short enough to be a length.
  *	This is normal practice and works for any 'now in use' protocol.
  *
@@ -113,7 +113,7 @@
  *
  */
 int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
-                  struct packet_type* ptype, struct net_device *orig_dev)
+		  struct packet_type* ptype, struct net_device *orig_dev)
 {
 	unsigned char *rawp = NULL;
 	struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data);
@@ -175,8 +175,8 @@
 
 #ifdef VLAN_DEBUG
 		printk(VLAN_DBG "%s: dropping skb: %p because came in on wrong device, dev: %s  real_dev: %s, skb_dev: %s\n",
-			__FUNCTION__, skb, dev->name, 
-			VLAN_DEV_INFO(skb->dev)->real_dev->name, 
+			__FUNCTION__, skb, dev->name,
+			VLAN_DEV_INFO(skb->dev)->real_dev->name,
 			skb->dev->name);
 #endif
 		kfree_skb(skb);
@@ -191,7 +191,7 @@
 
 #ifdef VLAN_DEBUG
 	printk(VLAN_DBG "%s: priority: %lu  for TCI: %hu (hbo)\n",
-		__FUNCTION__, (unsigned long)(skb->priority), 
+		__FUNCTION__, (unsigned long)(skb->priority),
 		ntohs(vhdr->h_vlan_TCI));
 #endif
 
@@ -207,7 +207,7 @@
 		stats->multicast++;
 		break;
 
-	case PACKET_OTHERHOST: 
+	case PACKET_OTHERHOST:
 		/* Our lower layer thinks this is not local, let's make sure.
 		 * This allows the VLAN to have a different MAC than the underlying
 		 * device, and still route correctly.
@@ -319,7 +319,7 @@
 }
 
 /*
- *	Create the VLAN header for an arbitrary protocol layer 
+ *	Create the VLAN header for an arbitrary protocol layer
  *
  *	saddr=NULL	means use device source address
  *	daddr=NULL	means leave destination address (eg unresolved arp)
@@ -328,8 +328,8 @@
  *  physical devices.
  */
 int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
-                         unsigned short type, void *daddr, void *saddr,
-                         unsigned len)
+			 unsigned short type, void *daddr, void *saddr,
+			 unsigned len)
 {
 	struct vlan_hdr *vhdr;
 	unsigned short veth_TCI = 0;
@@ -346,7 +346,7 @@
 	 * fixes some programs that get confused when they see a VLAN device
 	 * sending a frame that is VLAN encoded (the consensus is that the VLAN
 	 * device should look completely like an Ethernet device when the
-	 * REORDER_HEADER flag is set)	The drawback to this is some extra 
+	 * REORDER_HEADER flag is set)	The drawback to this is some extra
 	 * header shuffling in the hard_start_xmit.  Users can turn off this
 	 * REORDER behaviour with the vconfig tool.
 	 */
@@ -553,7 +553,7 @@
 	struct net_device *dev = dev_get_by_name(dev_name);
 	struct vlan_priority_tci_mapping *mp = NULL;
 	struct vlan_priority_tci_mapping *np;
-   
+
 	if (dev) {
 		if (dev->priv_flags & IFF_802_1Q_VLAN) {
 			/* See if a priority mapping exists.. */
@@ -610,13 +610,13 @@
 				return -EINVAL;
 			}
 		} else {
-			printk(KERN_ERR 
+			printk(KERN_ERR
 			       "%s: %s is not a vlan device, priv_flags: %hX.\n",
 			       __FUNCTION__, dev->name, dev->priv_flags);
 			dev_put(dev);
 		}
 	} else {
-		printk(KERN_ERR  "%s: Could not find device: %s\n", 
+		printk(KERN_ERR  "%s: Could not find device: %s\n",
 			__FUNCTION__, dev_name);
 	}
 
@@ -700,7 +700,7 @@
 }
 
 static inline int vlan_dmi_equals(struct dev_mc_list *dmi1,
-                                  struct dev_mc_list *dmi2)
+				  struct dev_mc_list *dmi2)
 {
 	return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) &&
 		(memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0));
@@ -810,7 +810,7 @@
 	case SIOCGMIIPHY:
 	case SIOCGMIIREG:
 	case SIOCSMIIREG:
-		if (real_dev->do_ioctl && netif_device_present(real_dev)) 
+		if (real_dev->do_ioctl && netif_device_present(real_dev))
 			err = real_dev->do_ioctl(real_dev, &ifrr, cmd);
 		break;
 
@@ -818,7 +818,7 @@
 		err = dev_ethtool(&ifrr);
 	}
 
-	if (!err) 
+	if (!err)
 		ifr->ifr_ifru = ifrr.ifr_ifru;
 
 	return err;
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index a8fc0de..5e24f72 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -51,7 +51,7 @@
 
 
 /*
- *	Names of the proc directory entries 
+ *	Names of the proc directory entries
  */
 
 static const char name_root[]	 = "vlan";
@@ -66,7 +66,7 @@
  */
 
 /*
- *	Generic /proc/net/vlan/<file> file and inode operations 
+ *	Generic /proc/net/vlan/<file> file and inode operations
  */
 
 static struct seq_operations vlan_seq_ops = {
@@ -81,7 +81,7 @@
 	return seq_open(file, &vlan_seq_ops);
 }
 
-static struct file_operations vlan_fops = {
+static const struct file_operations vlan_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = vlan_seq_open,
 	.read    = seq_read,
@@ -98,7 +98,7 @@
 	return single_open(file, vlandev_seq_show, PDE(inode)->data);
 }
 
-static struct file_operations vlandev_fops = {
+static const struct file_operations vlandev_fops = {
 	.owner = THIS_MODULE,
 	.open    = vlandev_seq_open,
 	.read    = seq_read,
@@ -111,13 +111,13 @@
  */
 
 /*
- *	/proc/net/vlan 
+ *	/proc/net/vlan
  */
 
 static struct proc_dir_entry *proc_vlan_dir;
 
 /*
- *	/proc/net/vlan/config 
+ *	/proc/net/vlan/config
  */
 
 static struct proc_dir_entry *proc_vlan_conf;
@@ -238,15 +238,15 @@
  */
 
 /* starting at dev, find a VLAN device */
-static struct net_device *vlan_skip(struct net_device *dev) 
+static struct net_device *vlan_skip(struct net_device *dev)
 {
-	while (dev && !(dev->priv_flags & IFF_802_1Q_VLAN)) 
+	while (dev && !(dev->priv_flags & IFF_802_1Q_VLAN))
 		dev = dev->next;
 
 	return dev;
 }
 
-/* start read of /proc/net/vlan/config */ 
+/* start read of /proc/net/vlan/config */
 static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	struct net_device *dev;
@@ -256,19 +256,19 @@
 
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
-	
-	for (dev = vlan_skip(dev_base); dev && i < *pos; 
+
+	for (dev = vlan_skip(dev_base); dev && i < *pos;
 	     dev = vlan_skip(dev->next), ++i);
-		
+
 	return  (i == *pos) ? dev : NULL;
-} 
+}
 
 static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	++*pos;
 
-	return vlan_skip((v == SEQ_START_TOKEN)  
-			    ? dev_base 
+	return vlan_skip((v == SEQ_START_TOKEN)
+			    ? dev_base
 			    : ((struct net_device *)v)->next);
 }
 
@@ -287,13 +287,13 @@
 		if (vlan_name_type < ARRAY_SIZE(vlan_name_type_str))
 		    nmtype =  vlan_name_type_str[vlan_name_type];
 
-		seq_printf(seq, "Name-Type: %s\n", 
+		seq_printf(seq, "Name-Type: %s\n",
 			   nmtype ? nmtype :  "UNKNOWN" );
 	} else {
 		const struct net_device *vlandev = v;
 		const struct vlan_dev_info *dev_info = VLAN_DEV_INFO(vlandev);
 
-		seq_printf(seq, "%-15s| %d  | %s\n",  vlandev->name,  
+		seq_printf(seq, "%-15s| %d  | %s\n",  vlandev->name,
 			   dev_info->vlan_id,    dev_info->real_dev->name);
 	}
 	return 0;
@@ -323,13 +323,13 @@
 	seq_puts(seq, "\n");
 	seq_printf(seq, fmt, "total frames transmitted", stats->tx_packets);
 	seq_printf(seq, fmt, "total bytes transmitted", stats->tx_bytes);
-	seq_printf(seq, fmt, "total headroom inc", 
+	seq_printf(seq, fmt, "total headroom inc",
 		   dev_info->cnt_inc_headroom_on_tx);
-	seq_printf(seq, fmt, "total encap on xmit", 
+	seq_printf(seq, fmt, "total encap on xmit",
 		   dev_info->cnt_encap_on_xmit);
 	seq_printf(seq, "Device: %s", dev_info->real_dev->name);
 	/* now show all PRIORITY mappings relating to this VLAN */
-	seq_printf(seq, 
+	seq_printf(seq,
 		       "\nINGRESS priority mappings: 0:%lu  1:%lu  2:%lu  3:%lu  4:%lu  5:%lu  6:%lu 7:%lu\n",
 		       dev_info->ingress_priority_map[0],
 		       dev_info->ingress_priority_map[1],
diff --git a/net/Kconfig b/net/Kconfig
index 7dfc949..9156578 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -37,6 +37,7 @@
 source "net/packet/Kconfig"
 source "net/unix/Kconfig"
 source "net/xfrm/Kconfig"
+source "net/iucv/Kconfig"
 
 config INET
 	bool "TCP/IP networking"
diff --git a/net/Makefile b/net/Makefile
index ad4d14f..4854ac5 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -47,6 +47,7 @@
 obj-$(CONFIG_IEEE80211)		+= ieee80211/
 obj-$(CONFIG_TIPC)		+= tipc/
 obj-$(CONFIG_NETLABEL)		+= netlabel/
+obj-$(CONFIG_IUCV)		+= iucv/
 
 ifeq ($(CONFIG_NET),y)
 obj-$(CONFIG_SYSCTL)		+= sysctl_net.o
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index f3777ec..d89d62f 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -895,7 +895,7 @@
 
 /*
  * Get the aarp entry that is in the chain described
- * by the iterator. 
+ * by the iterator.
  * If pos is set then skip till that index.
  * pos = 1 is the first entry
  */
@@ -905,7 +905,7 @@
 	struct aarp_entry **table = iter->table;
 	loff_t off = 0;
 	struct aarp_entry *entry;
-	
+
  rescan:
 	while(ct < AARP_HASH_SIZE) {
 		for (entry = table[ct]; entry; entry = entry->next) {
@@ -950,9 +950,9 @@
 	++*pos;
 
 	/* first line after header */
-	if (v == SEQ_START_TOKEN) 
+	if (v == SEQ_START_TOKEN)
 		entry = iter_next(iter, NULL);
-		
+
 	/* next entry in current bucket */
 	else if (entry->next)
 		entry = entry->next;
@@ -986,7 +986,7 @@
 	unsigned long now = jiffies;
 
 	if (v == SEQ_START_TOKEN)
-		seq_puts(seq, 
+		seq_puts(seq,
 			 "Address  Interface   Hardware Address"
 			 "   Expires LastSend  Retry Status\n");
 	else {
@@ -1014,7 +1014,7 @@
 			   : (iter->table == unresolved) ? "unresolved"
 			   : (iter->table == proxies) ? "proxies"
 			   : "unknown");
-	}				 
+	}
 	return 0;
 }
 
@@ -1030,7 +1030,7 @@
 	struct seq_file *seq;
 	int rc = -ENOMEM;
 	struct aarp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
-       
+
 	if (!s)
 		goto out;
 
@@ -1048,7 +1048,7 @@
 	goto out;
 }
 
-struct file_operations atalk_seq_arp_fops = {
+const struct file_operations atalk_seq_arp_fops = {
 	.owner		= THIS_MODULE,
 	.open           = aarp_seq_open,
 	.read           = seq_read,
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
index 7ae4916..57ff812 100644
--- a/net/appletalk/atalk_proc.c
+++ b/net/appletalk/atalk_proc.c
@@ -240,7 +240,7 @@
 	return seq_open(file, &atalk_seq_socket_ops);
 }
 
-static struct file_operations atalk_seq_interface_fops = {
+static const struct file_operations atalk_seq_interface_fops = {
 	.owner		= THIS_MODULE,
 	.open		= atalk_seq_interface_open,
 	.read		= seq_read,
@@ -248,7 +248,7 @@
 	.release	= seq_release,
 };
 
-static struct file_operations atalk_seq_route_fops = {
+static const struct file_operations atalk_seq_route_fops = {
 	.owner		= THIS_MODULE,
 	.open		= atalk_seq_route_open,
 	.read		= seq_read,
@@ -256,7 +256,7 @@
 	.release	= seq_release,
 };
 
-static struct file_operations atalk_seq_socket_fops = {
+static const struct file_operations atalk_seq_socket_fops = {
 	.owner		= THIS_MODULE,
 	.open		= atalk_seq_socket_open,
 	.read		= seq_read,
@@ -292,7 +292,7 @@
 	p->proc_fops = &atalk_seq_socket_fops;
 
 	p = create_proc_entry("arp", S_IRUGO, atalk_proc_dir);
-	if (!p) 
+	if (!p)
 		goto out_arp;
 	p->proc_fops = &atalk_seq_arp_fops;
 
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 3a70522..113c175 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -28,16 +28,16 @@
  *		Bradford Johnson	:	IP-over-DDP (experimental)
  *		Jay Schulist		:	Moved IP-over-DDP to its own
  *						driver file. (ipddp.c & ipddp.h)
- *		Jay Schulist		:	Made work as module with 
+ *		Jay Schulist		:	Made work as module with
  *						AppleTalk drivers, cleaned it.
  *		Rob Newberry		:	Added proxy AARP and AARP
  *						procfs, moved probing to AARP
  *						module.
- *              Adrian Sun/ 
- *              Michael Zuelsdorff      :       fix for net.0 packets. don't 
+ *              Adrian Sun/
+ *              Michael Zuelsdorff      :       fix for net.0 packets. don't
  *                                              allow illegal ether/tokentalk
- *                                              port assignment. we lose a 
- *                                              valid localtalk port as a 
+ *                                              port assignment. we lose a
+ *                                              valid localtalk port as a
  *                                              result.
  *		Arnaldo C. de Melo	:	Cleanup, in preparation for
  *						shared skb support 8)
@@ -48,7 +48,7 @@
  *		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/capability.h>
@@ -100,17 +100,17 @@
 		if (to->sat_port != at->src_port)
 			continue;
 
-	    	if (to->sat_addr.s_net == ATADDR_ANYNET &&
+		if (to->sat_addr.s_net == ATADDR_ANYNET &&
 		    to->sat_addr.s_node == ATADDR_BCAST)
 			goto found;
 
-	    	if (to->sat_addr.s_net == at->src_net &&
+		if (to->sat_addr.s_net == at->src_net &&
 		    (to->sat_addr.s_node == at->src_node ||
 		     to->sat_addr.s_node == ATADDR_BCAST ||
 		     to->sat_addr.s_node == ATADDR_ANYNODE))
 			goto found;
 
-	    	/* XXXX.0 -- we got a request for this router. make sure
+		/* XXXX.0 -- we got a request for this router. make sure
 		 * that the node is appropriately set. */
 		if (to->sat_addr.s_node == ATADDR_ANYNODE &&
 		    to->sat_addr.s_net != ATADDR_ANYNET &&
@@ -314,7 +314,7 @@
 
 	if (probe_node == ATADDR_ANYNODE)
 		probe_node = jiffies & 0xFF;
-		
+
 	/* Scan the networks */
 	for (netct = 0; netct <= netrange; netct++) {
 		/* Sweep the available nodes from a given start */
@@ -417,7 +417,7 @@
 		if (node == ATADDR_ANYNODE && net != ATADDR_ANYNET &&
 		    ntohs(iface->nets.nr_firstnet) <= ntohs(net) &&
 		    ntohs(net) <= ntohs(iface->nets.nr_lastnet))
-		        break;
+			break;
 	}
 	read_unlock_bh(&atalk_interfaces_lock);
 	return iface;
@@ -432,13 +432,13 @@
 static struct atalk_route *atrtr_find(struct atalk_addr *target)
 {
 	/*
-	 * we must search through all routes unless we find a 
+	 * we must search through all routes unless we find a
 	 * host route, because some host routes might overlap
 	 * network routes
 	 */
 	struct atalk_route *net_route = NULL;
 	struct atalk_route *r;
-	
+
 	read_lock_bh(&atalk_routes_lock);
 	for (r = atalk_routes; r; r = r->next) {
 		if (!(r->flags & RTF_UP))
@@ -460,8 +460,8 @@
 				net_route = r;
 		}
 	}
-	
-	/* 
+
+	/*
 	 * if we found a network route but not a direct host
 	 * route, then return it
 	 */
@@ -540,15 +540,15 @@
 		for (iface = atalk_interfaces; iface; iface = iface->next) {
 			if (!riface &&
 			    ntohs(ga->sat_addr.s_net) >=
-			    		ntohs(iface->nets.nr_firstnet) &&
+					ntohs(iface->nets.nr_firstnet) &&
 			    ntohs(ga->sat_addr.s_net) <=
-			    		ntohs(iface->nets.nr_lastnet))
+					ntohs(iface->nets.nr_lastnet))
 				riface = iface;
 
 			if (ga->sat_addr.s_net == iface->address.s_net &&
 			    ga->sat_addr.s_node == iface->address.s_node)
 				riface = iface;
-		}		
+		}
 		read_unlock_bh(&atalk_interfaces_lock);
 
 		retval = -ENETUNREACH;
@@ -649,7 +649,7 @@
 {
 	if (event == NETDEV_DOWN)
 		/* Discard any use of this */
-	        atalk_dev_down(ptr);
+		atalk_dev_down(ptr);
 
 	return NOTIFY_DONE;
 }
@@ -701,13 +701,13 @@
 			 */
 			if ((dev->flags & IFF_POINTOPOINT) &&
 			    atalk_find_interface(sa->sat_addr.s_net,
-				    		 sa->sat_addr.s_node)) {
+						 sa->sat_addr.s_node)) {
 				printk(KERN_DEBUG "AppleTalk: point-to-point "
 						  "interface added with "
 						  "existing address\n");
 				add_route = 0;
 			}
-			
+
 			/*
 			 * Phase 1 is fine on LocalTalk but we don't do
 			 * EtherTalk phase 1. Anyone wanting to add it go ahead.
@@ -797,78 +797,78 @@
 			sa->sat_addr.s_node = ATADDR_BCAST;
 			break;
 
-	        case SIOCATALKDIFADDR:
-	        case SIOCDIFADDR:
+		case SIOCATALKDIFADDR:
+		case SIOCDIFADDR:
 			if (!capable(CAP_NET_ADMIN))
 				return -EPERM;
 			if (sa->sat_family != AF_APPLETALK)
 				return -EINVAL;
 			atalk_dev_down(dev);
-			break;			
+			break;
 
 		case SIOCSARP:
 			if (!capable(CAP_NET_ADMIN))
-                                return -EPERM;
-                        if (sa->sat_family != AF_APPLETALK)
-                                return -EINVAL;
-                        if (!atif)
-                                return -EADDRNOTAVAIL;
+				return -EPERM;
+			if (sa->sat_family != AF_APPLETALK)
+				return -EINVAL;
+			if (!atif)
+				return -EADDRNOTAVAIL;
 
-                        /*
-                         * for now, we only support proxy AARP on ELAP;
-                         * we should be able to do it for LocalTalk, too.
-                         */
-                        if (dev->type != ARPHRD_ETHER)
-                                return -EPROTONOSUPPORT;
+			/*
+			 * for now, we only support proxy AARP on ELAP;
+			 * we should be able to do it for LocalTalk, too.
+			 */
+			if (dev->type != ARPHRD_ETHER)
+				return -EPROTONOSUPPORT;
 
-                        /*
-                         * atif points to the current interface on this network;
-                         * we aren't concerned about its current status (at
+			/*
+			 * atif points to the current interface on this network;
+			 * we aren't concerned about its current status (at
 			 * least for now), but it has all the settings about
 			 * the network we're going to probe. Consequently, it
 			 * must exist.
-                         */
-                        if (!atif)
-                                return -EADDRNOTAVAIL;
+			 */
+			if (!atif)
+				return -EADDRNOTAVAIL;
 
-                        nr = (struct atalk_netrange *)&(atif->nets);
-                        /*
-                         * Phase 1 is fine on Localtalk but we don't do
-                         * Ethertalk phase 1. Anyone wanting to add it go ahead.
-                         */
-                        if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
-                                return -EPROTONOSUPPORT;
-
-                        if (sa->sat_addr.s_node == ATADDR_BCAST ||
-			    sa->sat_addr.s_node == 254)
-                                return -EINVAL;
-
-                        /*
-                         * Check if the chosen address is used. If so we
-                         * error and ATCP will try another.
-                         */
-                      	if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0)
-                      		return -EADDRINUSE;
-                      	
+			nr = (struct atalk_netrange *)&(atif->nets);
 			/*
-                         * We now have an address on the local network, and
+			 * Phase 1 is fine on Localtalk but we don't do
+			 * Ethertalk phase 1. Anyone wanting to add it go ahead.
+			 */
+			if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
+				return -EPROTONOSUPPORT;
+
+			if (sa->sat_addr.s_node == ATADDR_BCAST ||
+			    sa->sat_addr.s_node == 254)
+				return -EINVAL;
+
+			/*
+			 * Check if the chosen address is used. If so we
+			 * error and ATCP will try another.
+			 */
+			if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0)
+				return -EADDRINUSE;
+
+			/*
+			 * We now have an address on the local network, and
 			 * the AARP code will defend it for us until we take it
 			 * down. We don't set up any routes right now, because
 			 * ATCP will install them manually via SIOCADDRT.
-                         */
-                        break;
+			 */
+			break;
 
-                case SIOCDARP:
-                        if (!capable(CAP_NET_ADMIN))
-                                return -EPERM;
-                        if (sa->sat_family != AF_APPLETALK)
-                                return -EINVAL;
-                        if (!atif)
-                                return -EADDRNOTAVAIL;
+		case SIOCDARP:
+			if (!capable(CAP_NET_ADMIN))
+				return -EPERM;
+			if (sa->sat_family != AF_APPLETALK)
+				return -EINVAL;
+			if (!atif)
+				return -EADDRNOTAVAIL;
 
-                        /* give to aarp module to remove proxy entry */
-                        aarp_proxy_remove(atif->dev, &(sa->sat_addr));
-                        return 0;
+			/* give to aarp module to remove proxy entry */
+			aarp_proxy_remove(atif->dev, &(sa->sat_addr));
+			return 0;
 	}
 
 	return copy_to_user(arg, &atreq, sizeof(atreq)) ? -EFAULT : 0;
@@ -899,7 +899,7 @@
 				dev = __dev_get_by_name(name);
 				if (!dev)
 					return -ENODEV;
-			}			
+			}
 			return atrtr_create(&rt, dev);
 		}
 	}
@@ -917,7 +917,7 @@
  * Checksum: This is 'optional'. It's quite likely also a good
  * candidate for assembler hackery 8)
  */
-static unsigned long atalk_sum_partial(const unsigned char *data, 
+static unsigned long atalk_sum_partial(const unsigned char *data,
 				       int len, unsigned long sum)
 {
 	/* This ought to be unwrapped neatly. I'll trust gcc for now */
@@ -945,7 +945,7 @@
 		if (copy > len)
 			copy = len;
 		sum = atalk_sum_partial(skb->data + offset, copy, sum);
-		if ( (len -= copy) == 0) 
+		if ( (len -= copy) == 0)
 			return sum;
 
 		offset += copy;
@@ -1031,7 +1031,7 @@
 
 	/*
 	 * We permit SOCK_DGRAM and RAW is an extension. It is trivial to do
-	 * and gives you the full ELAP frame. Should be handy for CAP 8) 
+	 * and gives you the full ELAP frame. Should be handy for CAP 8)
 	 */
 	if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
 		goto out;
@@ -1196,14 +1196,14 @@
 
 	if (addr->sat_addr.s_node == ATADDR_BCAST &&
 	    !sock_flag(sk, SOCK_BROADCAST)) {
-#if 1	
+#if 1
 		printk(KERN_WARNING "%s is broken and did not set "
 				    "SO_BROADCAST. It will break when 2.2 is "
 				    "released.\n",
 			current->comm);
 #else
 		return -EACCES;
-#endif			
+#endif
 	}
 
 	if (sock_flag(sk, SOCK_ZAPPED))
@@ -1260,27 +1260,27 @@
 #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE)
 static __inline__ int is_ip_over_ddp(struct sk_buff *skb)
 {
-        return skb->data[12] == 22;
+	return skb->data[12] == 22;
 }
 
 static int handle_ip_over_ddp(struct sk_buff *skb)
 {
-        struct net_device *dev = __dev_get_by_name("ipddp0");
+	struct net_device *dev = __dev_get_by_name("ipddp0");
 	struct net_device_stats *stats;
 
 	/* This needs to be able to handle ipddp"N" devices */
-        if (!dev)
-                return -ENODEV;
+	if (!dev)
+		return -ENODEV;
 
-        skb->protocol = htons(ETH_P_IP);
-        skb_pull(skb, 13);
-        skb->dev   = dev;
-        skb->h.raw = skb->data;
+	skb->protocol = htons(ETH_P_IP);
+	skb_pull(skb, 13);
+	skb->dev   = dev;
+	skb->h.raw = skb->data;
 
 	stats = dev->priv;
-        stats->rx_packets++;
-        stats->rx_bytes += skb->len + 13;
-        netif_rx(skb);  /* Send the SKB up to a higher place. */
+	stats->rx_packets++;
+	stats->rx_bytes += skb->len + 13;
+	netif_rx(skb);  /* Send the SKB up to a higher place. */
 	return 0;
 }
 #else
@@ -1298,7 +1298,7 @@
 
 	/*
 	 * Don't route multicast, etc., packets, or packets sent to "this
-	 * network" 
+	 * network"
 	 */
 	if (skb->pkt_type != PACKET_HOST || !ddp->deh_dnet) {
 		/*
@@ -1335,8 +1335,8 @@
 		ta.s_node = rt->gateway.s_node;
 	}
 
-        /* Fix up skb->len field */
-        skb_trim(skb, min_t(unsigned int, origlen,
+	/* Fix up skb->len field */
+	skb_trim(skb, min_t(unsigned int, origlen,
 			    (rt->dev->hard_header_len +
 			     ddp_dl->header_length + (len_hops & 1023))));
 
@@ -1358,12 +1358,12 @@
 		/* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */
 		struct sk_buff *nskb = skb_realloc_headroom(skb, 32);
 		kfree_skb(skb);
-		if (!nskb) 
+		if (!nskb)
 			goto out;
 		skb = nskb;
 	} else
 		skb = skb_unshare(skb, GFP_ATOMIC);
-	
+
 	/*
 	 * If the buffer didn't vanish into the lack of space bitbucket we can
 	 * send it.
@@ -1395,13 +1395,13 @@
 	struct sock *sock;
 	struct atalk_iface *atif;
 	struct sockaddr_at tosat;
-        int origlen;
+	int origlen;
 	__u16 len_hops;
 
 	/* Don't mangle buffer if shared */
-	if (!(skb = skb_share_check(skb, GFP_ATOMIC))) 
+	if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
 		goto out;
-		
+
 	/* Size check and make sure header is contiguous */
 	if (!pskb_may_pull(skb, sizeof(*ddp)))
 		goto freeit;
@@ -1490,7 +1490,7 @@
 			goto freeit;
 
 		/* Don't mangle buffer if shared */
-		if (!(skb = skb_share_check(skb, GFP_ATOMIC))) 
+		if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
 			return 0;
 
 		/*
@@ -1501,11 +1501,11 @@
 
 		/* Now fill in the long header */
 
-	 	/*
-	 	 * These two first. The mac overlays the new source/dest
-	 	 * network information so we MUST copy these before
-	 	 * we write the network numbers !
-	 	 */
+		/*
+		 * These two first. The mac overlays the new source/dest
+		 * network information so we MUST copy these before
+		 * we write the network numbers !
+		 */
 
 		ddp->deh_dnode = skb->mac.raw[0];     /* From physical header */
 		ddp->deh_snode = skb->mac.raw[1];     /* From physical header */
@@ -1605,7 +1605,7 @@
 	skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err);
 	if (!skb)
 		return err;
-	
+
 	skb->sk = sk;
 	skb_reserve(skb, ddp_dl->header_length);
 	skb_reserve(skb, dev->hard_header_len);
diff --git a/net/appletalk/dev.c b/net/appletalk/dev.c
index 1237e20..9e4dffc 100644
--- a/net/appletalk/dev.c
+++ b/net/appletalk/dev.c
@@ -15,14 +15,14 @@
 }
 
 static int ltalk_mac_addr(struct net_device *dev, void *addr)
-{	
+{
 	return -EINVAL;
 }
 
 static void ltalk_setup(struct net_device *dev)
 {
 	/* Fill in the fields of the device structure with localtalk-generic values. */
-	
+
 	dev->change_mtu		= ltalk_change_mtu;
 	dev->hard_header	= NULL;
 	dev->rebuild_header 	= NULL;
@@ -34,8 +34,8 @@
 	dev->hard_header_len 	= LTALK_HLEN;
 	dev->mtu		= LTALK_MTU;
 	dev->addr_len		= LTALK_ALEN;
-	dev->tx_queue_len	= 10;	
-	
+	dev->tx_queue_len	= 10;
+
 	dev->broadcast[0]	= 0xFF;
 
 	dev->flags		= IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP;
diff --git a/net/appletalk/sysctl_net_atalk.c b/net/appletalk/sysctl_net_atalk.c
index 40b0af7..7df1778 100644
--- a/net/appletalk/sysctl_net_atalk.c
+++ b/net/appletalk/sysctl_net_atalk.c
@@ -73,7 +73,7 @@
 
 void atalk_register_sysctl(void)
 {
-	atalk_table_header = register_sysctl_table(atalk_root_table, 1);
+	atalk_table_header = register_sysctl_table(atalk_root_table);
 }
 
 void atalk_unregister_sysctl(void)
diff --git a/net/atm/addr.c b/net/atm/addr.c
index 3060fd0..6afa77d 100644
--- a/net/atm/addr.c
+++ b/net/atm/addr.c
@@ -4,7 +4,6 @@
 
 #include <linux/atm.h>
 #include <linux/atmdev.h>
-#include <linux/sched.h>
 #include <asm/uaccess.h>
 
 #include "signaling.h"
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c
index 62f6ed1..f094a08 100644
--- a/net/atm/atm_sysfs.c
+++ b/net/atm/atm_sysfs.c
@@ -30,15 +30,15 @@
 
 static ssize_t show_atmaddress(struct class_device *cdev, char *buf)
 {
-        unsigned long flags;
+	unsigned long flags;
 	char *pos = buf;
 	struct atm_dev *adev = to_atm_dev(cdev);
-        struct atm_dev_addr *aaddr;
+	struct atm_dev_addr *aaddr;
 	int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin;
 	int i, j;
 
-        spin_lock_irqsave(&adev->lock, flags);
-        list_for_each_entry(aaddr, &adev->local, entry) {
+	spin_lock_irqsave(&adev->lock, flags);
+	list_for_each_entry(aaddr, &adev->local, entry) {
 		for(i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) {
 			if (j == *fmt) {
 				pos += sprintf(pos, ".");
@@ -49,7 +49,7 @@
 		}
 		pos += sprintf(pos, "\n");
 	}
-        spin_unlock_irqrestore(&adev->lock, flags);
+	spin_unlock_irqrestore(&adev->lock, flags);
 
 	return pos - buf;
 }
@@ -61,7 +61,7 @@
 
 	pos += sprintf(pos, "%d\n",
 		       adev->signal == ATM_PHY_SIG_LOST ? 0 : 1);
-		
+
 	return pos - buf;
 }
 
@@ -86,7 +86,7 @@
 			link_rate = adev->link_rate * 8 * 53;
 	}
 	pos += sprintf(pos, "%d\n", link_rate);
-		
+
 	return pos - buf;
 }
 
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 83a1c1b..ec4ebd3 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -182,7 +182,7 @@
 	ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
 	DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
 	if (!atm_may_send(atmvcc, skb->truesize)) {
-		/* we free this here for now, because we cannot know in a higher 
+		/* we free this here for now, because we cannot know in a higher
 			layer whether the skb point it supplied wasn't freed yet.
 			now, it always is.
 		*/
@@ -718,7 +718,7 @@
 
 	++*pos;
 
-	brd = list_entry(brd->br2684_devs.next, 
+	brd = list_entry(brd->br2684_devs.next,
 			 struct br2684_dev, br2684_devs);
 	return (&brd->br2684_devs != &br2684_devs) ? brd : NULL;
 }
@@ -784,7 +784,7 @@
 	return seq_open(file, &br2684_seq_ops);
 }
 
-static struct file_operations br2684_proc_ops = {
+static const struct file_operations br2684_proc_ops = {
 	.owner   = THIS_MODULE,
 	.open    = br2684_proc_open,
 	.read    = seq_read,
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 5f8a1d2..ebb5d0c 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -971,7 +971,7 @@
 	goto out;
 }
 
-static struct file_operations arp_seq_fops = {
+static const struct file_operations arp_seq_fops = {
 	.open		= arp_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/net/atm/common.c b/net/atm/common.c
index fbabff4..282d761 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -109,11 +109,11 @@
 	struct atm_vcc *vcc = atm_sk(sk);
 
 	return (vcc->qos.txtp.max_sdu +
-	        atomic_read(&sk->sk_wmem_alloc)) <= sk->sk_sndbuf;
+		atomic_read(&sk->sk_wmem_alloc)) <= sk->sk_sndbuf;
 }
 
 static void vcc_write_space(struct sock *sk)
-{       
+{
 	read_lock(&sk->sk_callback_lock);
 
 	if (vcc_writable(sk)) {
@@ -131,7 +131,7 @@
 	.owner	  = THIS_MODULE,
 	.obj_size = sizeof(struct atm_vcc),
 };
- 
+
 int vcc_create(struct socket *sock, int protocol, int family)
 {
 	struct sock *sk;
@@ -359,7 +359,7 @@
 		return error;
 	vcc->dev = dev;
 	write_lock_irq(&vcc_sklist_lock);
-	if (test_bit(ATM_DF_REMOVED, &dev->flags) || 
+	if (test_bit(ATM_DF_REMOVED, &dev->flags) ||
 	    (error = find_ci(vcc, &vpi, &vci))) {
 		write_unlock_irq(&vcc_sklist_lock);
 		goto fail_module_put;
@@ -494,20 +494,20 @@
 	if (!skb)
 		return error;
 
-	copied = skb->len; 
+	copied = skb->len;
 	if (copied > size) {
-		copied = size; 
+		copied = size;
 		msg->msg_flags |= MSG_TRUNC;
 	}
 
-        error = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-        if (error)
-                return error;
-        sock_recv_timestamp(msg, sk, skb);
-        DPRINTK("RcvM %d -= %d\n", atomic_read(&sk->rmem_alloc), skb->truesize);
-        atm_return(vcc, skb->truesize);
-        skb_free_datagram(sk, skb);
-        return copied;
+	error = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	if (error)
+		return error;
+	sock_recv_timestamp(msg, sk, skb);
+	DPRINTK("RcvM %d -= %d\n", atomic_read(&sk->rmem_alloc), skb->truesize);
+	atm_return(vcc, skb->truesize);
+	skb_free_datagram(sk, skb);
+	return copied;
 }
 
 
@@ -675,7 +675,7 @@
 	int error;
 
 	if (!qos->txtp.traffic_class && !qos->rxtp.traffic_class)
-                return -EINVAL;
+		return -EINVAL;
 	if (qos->txtp.traffic_class != qos->rxtp.traffic_class &&
 	    qos->txtp.traffic_class && qos->rxtp.traffic_class &&
 	    qos->txtp.traffic_class != ATM_ANYCLASS &&
@@ -786,11 +786,11 @@
 		printk(KERN_ERR "atmsvc_init() failed with %d\n", error);
 		goto out_atmpvc_exit;
 	}
-        if ((error = atm_proc_init()) < 0) {
+	if ((error = atm_proc_init()) < 0) {
 		printk(KERN_ERR "atm_proc_init() failed with %d\n",error);
 		goto out_atmsvc_exit;
 	}
-        if ((error = atm_sysfs_init()) < 0) {
+	if ((error = atm_sysfs_init()) < 0) {
 		printk(KERN_ERR "atm_sysfs_init() failed with %d\n",error);
 		goto out_atmproc_exit;
 	}
@@ -816,7 +816,8 @@
 	proto_unregister(&vcc_proto);
 }
 
-module_init(atm_init);
+subsys_initcall(atm_init);
+
 module_exit(atm_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/net/atm/common.h b/net/atm/common.h
index a422da7..ad78c9e 100644
--- a/net/atm/common.h
+++ b/net/atm/common.h
@@ -1,5 +1,5 @@
 /* net/atm/common.h - ATM sockets (common part for PVC and SVC) */
- 
+
 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index 8c2022c..8ccee45 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -76,7 +76,7 @@
 				}
 				skb = skb_peek(&sk->sk_receive_queue);
 				error = put_user(skb ? skb->len : 0,
-					 	 (int __user *)argp) ? -EFAULT : 0;
+						 (int __user *)argp) ? -EFAULT : 0;
 				goto done;
 			}
 		case SIOCGSTAMP: /* borrowed from IP */
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 3fc0abe..3d804d6 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1,5 +1,5 @@
 /*
- * lec.c: Lan Emulation driver 
+ * lec.c: Lan Emulation driver
  *
  * Marko Kiiskila <mkiiskila@yahoo.com>
  */
@@ -1212,7 +1212,7 @@
 	return seq_release_private(inode, file);
 }
 
-static struct file_operations lec_seq_fops = {
+static const struct file_operations lec_seq_fops = {
 	.owner = THIS_MODULE,
 	.open = lec_seq_open,
 	.read = seq_read,
@@ -1437,7 +1437,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <asm/param.h>
 #include <asm/atomic.h>
@@ -1457,7 +1456,7 @@
 static void lec_arp_check_expire(struct work_struct *work);
 static void lec_arp_expire_arp(unsigned long data);
 
-/* 
+/*
  * Arp table funcs
  */
 
@@ -1473,9 +1472,9 @@
 	for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
 		INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
 	}
-        INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
-        INIT_HLIST_HEAD(&priv->lec_no_forward);
-        INIT_HLIST_HEAD(&priv->mcast_fwds);
+	INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
+	INIT_HLIST_HEAD(&priv->lec_no_forward);
+	INIT_HLIST_HEAD(&priv->mcast_fwds);
 	spin_lock_init(&priv->lec_arp_lock);
 	INIT_DELAYED_WORK(&priv->lec_arp_work, lec_arp_check_expire);
 	schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
@@ -1770,7 +1769,7 @@
 	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 }
 
-/* 
+/*
  * Find entry by mac_address
  */
 static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
@@ -1949,7 +1948,7 @@
 
 /*
  * Try to find vcc where mac_address is attached.
- * 
+ *
  */
 static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
 				       unsigned char *mac_to_find, int is_rdesc,
@@ -2075,7 +2074,7 @@
 }
 
 /*
- * Notifies:  Response to arp_request (atm_addr != NULL) 
+ * Notifies:  Response to arp_request (atm_addr != NULL)
  */
 static void
 lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
@@ -2176,7 +2175,7 @@
 }
 
 /*
- * Notifies: Vcc setup ready 
+ * Notifies: Vcc setup ready
  */
 static void
 lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
@@ -2380,7 +2379,7 @@
 			if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
 				entry->flush_tran_id = tran_id;
 				DPRINTK("Set flush transaction id to %lx for %p\n",
-				        tran_id, entry);
+					tran_id, entry);
 			}
 		}
 	spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
diff --git a/net/atm/lec.h b/net/atm/lec.h
index 99136ba..b41cda7 100644
--- a/net/atm/lec.h
+++ b/net/atm/lec.h
@@ -52,12 +52,12 @@
 
 /*
  * ATM LAN Emulation supports both LLC & Dix Ethernet EtherType
- * frames. 
+ * frames.
  *
  * 1. Dix Ethernet EtherType frames encoded by placing EtherType
  *    field in h_type field. Data follows immediatelly after header.
  * 2. LLC Data frames whose total length, including LLC field and data,
- *    but not padding required to meet the minimum data frame length, 
+ *    but not padding required to meet the minimum data frame length,
  *    is less than 1536(0x0600) MUST be encoded by placing that length
  *    in the h_type field. The LLC field follows header immediatelly.
  * 3. LLC data frames longer than this maximum MUST be encoded by placing
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index c18f737..cb3c004 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -32,7 +32,7 @@
 #include "resources.h"
 
 /*
- * mpc.c: Implementation of MPOA client kernel part 
+ * mpc.c: Implementation of MPOA client kernel part
  */
 
 #if 0
@@ -80,17 +80,17 @@
 	0xaa, 0xaa, 0x03,
 	{0x00, 0x00, 0x5e},
 	{0x00, 0x03}         /* For MPOA control PDUs */
-};        
+};
 static struct llc_snap_hdr llc_snap_mpoa_data = {
 	0xaa, 0xaa, 0x03,
 	{0x00, 0x00, 0x00},
 	{0x08, 0x00}         /* This is for IP PDUs only */
-};        
+};
 static struct llc_snap_hdr llc_snap_mpoa_data_tagged = {
 	0xaa, 0xaa, 0x03,
 	{0x00, 0x00, 0x00},
 	{0x88, 0x4c}         /* This is for tagged data PDUs */
-};        
+};
 
 static struct notifier_block mpoa_notifier = {
 	mpoa_event_listener,
@@ -106,12 +106,12 @@
 static struct mpoa_client *find_mpc_by_itfnum(int itf)
 {
 	struct mpoa_client *mpc;
-	
+
 	mpc = mpcs;  /* our global linked list */
 	while (mpc != NULL) {
 		if (mpc->dev_num == itf)
 			return mpc;
-		mpc = mpc->next;    
+		mpc = mpc->next;
 	}
 
 	return NULL;   /* not found */
@@ -120,7 +120,7 @@
 static struct mpoa_client *find_mpc_by_vcc(struct atm_vcc *vcc)
 {
 	struct mpoa_client *mpc;
-	
+
 	mpc = mpcs;  /* our global linked list */
 	while (mpc != NULL) {
 		if (mpc->mpoad_vcc == vcc)
@@ -134,7 +134,7 @@
 static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
 {
 	struct mpoa_client *mpc;
-	
+
 	mpc = mpcs;  /* our global linked list */
 	while (mpc != NULL) {
 		if (mpc->dev == dev)
@@ -190,7 +190,7 @@
 	}
 
 	return qos;
-}        
+}
 
 /*
  * Returns 0 for failure
@@ -245,7 +245,7 @@
 
 	sprintf(name, "lec%d", itf);
 	dev = dev_get_by_name(name);
-	
+
 	return dev;
 }
 
@@ -265,25 +265,25 @@
 	mpc->parameters.mpc_p2 = MPC_P2;
 	memset(mpc->parameters.mpc_p3,0,sizeof(mpc->parameters.mpc_p3));
 	mpc->parameters.mpc_p4 = MPC_P4;
-	mpc->parameters.mpc_p5 = MPC_P5; 
+	mpc->parameters.mpc_p5 = MPC_P5;
 	mpc->parameters.mpc_p6 = MPC_P6;
-	
+
 	mpcs = mpc;
-	
+
 	return mpc;
 }
 
 /*
  *
  * start_mpc() puts the MPC on line. All the packets destined
- * to the lec underneath us are now being monitored and 
+ * to the lec underneath us are now being monitored and
  * shortcuts will be established.
  *
  */
 static void start_mpc(struct mpoa_client *mpc, struct net_device *dev)
 {
-	
-	dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name); 
+
+	dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name);
 	if (dev->hard_start_xmit == NULL) {
 		printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n",
 		       dev->name);
@@ -297,8 +297,8 @@
 
 static void stop_mpc(struct mpoa_client *mpc)
 {
-	
-	dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name); 
+
+	dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name);
 
 	/* Lets not nullify lec device's dev->hard_start_xmit */
 	if (mpc->dev->hard_start_xmit != mpc_send_packet) {
@@ -309,7 +309,7 @@
 	mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit;
 	mpc->old_hard_start_xmit = NULL;
 	/* close_shortcuts(mpc);    ??? FIXME */
-	
+
 	return;
 }
 
@@ -358,7 +358,7 @@
 	uint8_t length, mpoa_device_type, number_of_mps_macs;
 	uint8_t *end_of_tlvs;
 	struct mpoa_client *mpc;
-	
+
 	mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
 	dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name);
 	dprintk("total length of all TLVs %d\n", sizeoftlvs);
@@ -377,7 +377,7 @@
 			printk("TLV value extends past its buffer, aborting parse\n");
 			return;
 		}
-		
+
 		if (type == 0) {
 			printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name);
 			return;
@@ -412,10 +412,10 @@
 			continue;  /* someone should read the spec */
 		}
 		dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs);
-		
+
 		/* ok, now we can go and tell our daemon the control address of MPS */
 		send_set_mps_ctrl_addr(tlvs, mpc);
-		
+
 		tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type);
 		if (tlvs == NULL) return;
 	}
@@ -474,7 +474,7 @@
 	iph = (struct iphdr *)buff;
 	ipaddr = iph->daddr;
 
-	ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr);        
+	ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr);
 
 	entry = mpc->in_ops->get(ipaddr, mpc);
 	if (entry == NULL) {
@@ -483,15 +483,15 @@
 		return 1;
 	}
 	if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){   /* threshold not exceeded or VCC not ready */
-		ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name);        
+		ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name);
 		mpc->in_ops->put(entry);
 		return 1;
 	}
 
-	ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name);        
+	ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name);
 	/* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
 	if (iph->ttl <= 1) {
-		ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl);        
+		ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl);
 		mpc->in_ops->put(entry);
 		return 1;
 	}
@@ -529,7 +529,7 @@
 	struct mpoa_client *mpc;
 	struct ethhdr *eth;
 	int i = 0;
-	
+
 	mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
 	if(mpc == NULL) {
 		printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name);
@@ -549,7 +549,7 @@
 
  non_ip:
 	retval = mpc->old_hard_start_xmit(skb,dev);
-	
+
 	return retval;
 }
 
@@ -569,11 +569,11 @@
 	ipaddr = ioc_data.ipaddr;
 	if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
 		return -EINVAL;
-	
+
 	mpc = find_mpc_by_itfnum(ioc_data.dev_num);
 	if (mpc == NULL)
 		return -EINVAL;
-	
+
 	if (ioc_data.type == MPC_SOCKET_INGRESS) {
 		in_entry = mpc->in_ops->get(ipaddr, mpc);
 		if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) {
@@ -604,7 +604,7 @@
 	struct mpoa_client *mpc;
 	in_cache_entry *in_entry;
 	eg_cache_entry *eg_entry;
-	
+
 	mpc = find_mpc_by_lec(dev);
 	if (mpc == NULL) {
 		printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name);
@@ -640,14 +640,14 @@
 	struct mpoa_client *mpc;
 	__be32 tag;
 	char *tmp;
-	
+
 	ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
 	if (skb == NULL) {
 		dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name);
 		mpc_vcc_close(vcc, dev);
 		return;
 	}
-	
+
 	skb->dev = dev;
 	if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
 		struct sock *sk = sk_atm(vcc);
@@ -693,11 +693,11 @@
 		dev_kfree_skb_any(skb);
 		return;
 	}
-	
+
 	/*
 	 * See if ingress MPC is using shortcut we opened as a return channel.
 	 * This means we have a bi-directional vcc opened by us.
-	 */ 
+	 */
 	if (eg->shortcut == NULL) {
 		eg->shortcut = vcc;
 		printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name);
@@ -743,7 +743,7 @@
 	struct mpoa_client *mpc;
 	struct lec_priv *priv;
 	int err;
-	
+
 	if (mpcs == NULL) {
 		init_timer(&mpc_timer);
 		mpc_timer_refresh();
@@ -755,7 +755,7 @@
 			return err;
 		}
 	}
-	
+
 	mpc = find_mpc_by_itfnum(arg);
 	if (mpc == NULL) {
 		dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg);
@@ -776,7 +776,7 @@
 			dev_put(mpc->dev);
 			mpc->dev = NULL;
 		} else
-			priv->lane2_ops->associate_indicator = lane2_assoc_ind;  
+			priv->lane2_ops->associate_indicator = lane2_assoc_ind;
 	}
 
 	mpc->mpoad_vcc = vcc;
@@ -788,7 +788,7 @@
 	if (mpc->dev) {
 		char empty[ATM_ESA_LEN];
 		memset(empty, 0, ATM_ESA_LEN);
-		
+
 		start_mpc(mpc, mpc->dev);
 		/* set address if mpcd e.g. gets killed and restarted.
 		 * If we do not do it now we have to wait for the next LE_ARP
@@ -806,7 +806,7 @@
 	struct k_message mesg;
 
 	memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);
-	
+
 	mesg.type = SET_MPS_CTRL_ADDR;
 	memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
 	msg_to_mpoad(&mesg, mpc);
@@ -828,7 +828,7 @@
 		printk("mpoa: mpoad_close: close for non-present mpoad\n");
 		return;
 	}
-	
+
 	mpc->mpoad_vcc = NULL;
 	if (mpc->dev) {
 		struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
@@ -844,7 +844,7 @@
 		atm_return(vcc, skb->truesize);
 		kfree_skb(skb);
 	}
-	
+
 	printk("mpoa: (%s) going down\n",
 		(mpc->dev) ? mpc->dev->name : "<unknown>");
 	module_put(THIS_MODULE);
@@ -857,11 +857,11 @@
  */
 static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
 {
-	
+
 	struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
 	struct k_message *mesg = (struct k_message*)skb->data;
 	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
-	
+
 	if (mpc == NULL) {
 		printk("mpoa: msg_from_mpoad: no mpc found\n");
 		return 0;
@@ -938,7 +938,7 @@
 	skb_put(skb, sizeof(struct k_message));
 	memcpy(skb->data, mesg, sizeof(struct k_message));
 	atm_force_charge(mpc->mpoad_vcc, skb->truesize);
-	
+
 	sk = sk_atm(mpc->mpoad_vcc);
 	skb_queue_tail(&sk->sk_receive_queue, skb);
 	sk->sk_data_ready(sk, skb->len);
@@ -955,7 +955,7 @@
 	dev = (struct net_device *)dev_ptr;
 	if (dev->name == NULL || strncmp(dev->name, "lec", 3))
 		return NOTIFY_DONE; /* we are only interested in lec:s */
-	
+
 	switch (event) {
 	case NETDEV_REGISTER:       /* a new lec device was allocated */
 		priv = (struct lec_priv *)dev->priv;
@@ -1043,7 +1043,7 @@
 		mpc->in_ops->put(entry);
 		return;
 	}
-	
+
 	if(entry->entry_state == INGRESS_INVALID){
 		entry->entry_state = INGRESS_RESOLVING;
 		msg->type = SND_MPOA_RES_RQST;
@@ -1053,7 +1053,7 @@
 		mpc->in_ops->put(entry);
 		return;
 	}
-	
+
 	printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n",
 		(mpc->dev) ? mpc->dev->name : "<unknown>");
 	mpc->in_ops->put(entry);
@@ -1062,7 +1062,7 @@
 
 /*
  * Things get complicated because we have to check if there's an egress
- * shortcut with suitable traffic parameters we could use. 
+ * shortcut with suitable traffic parameters we could use.
  */
 static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry)
 {
@@ -1079,7 +1079,7 @@
 			    else if(eg_entry->shortcut->qos.txtp.max_pcr > 0)
 				    entry->shortcut = eg_entry->shortcut;
 		}
-	 	if(entry->shortcut){
+		if(entry->shortcut){
 			dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(dst_ip));
 			client->eg_ops->put(eg_entry);
 			return;
@@ -1094,7 +1094,7 @@
 	{
 		msg->qos = qos->qos;
 		printk("mpoa: (%s) trying to get a CBR shortcut\n",client->dev->name);
-    	}
+	}
 	else memset(&msg->qos,0,sizeof(struct atm_qos));
 	msg_to_mpoad(msg, client);
 	return;
@@ -1111,7 +1111,7 @@
 		printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name);
 		return;
 	}
-	ddprintk(" entry_state = %d ", entry->entry_state);	
+	ddprintk(" entry_state = %d ", entry->entry_state);
 
 	if (entry->entry_state == INGRESS_RESOLVED) {
 		printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", mpc->dev->name);
@@ -1126,7 +1126,7 @@
 	ddprintk("entry->shortcut = %p\n", entry->shortcut);
 
 	if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL){
-		entry->entry_state = INGRESS_RESOLVED; 
+		entry->entry_state = INGRESS_RESOLVED;
 		mpc->in_ops->put(entry);
 		return; /* Shortcut already open... */
 	}
@@ -1137,7 +1137,7 @@
 		mpc->in_ops->put(entry);
 		return;
 	}
-	
+
 	check_qos_and_open_shortcut(msg, mpc, entry);
 	entry->entry_state = INGRESS_RESOLVED;
 	mpc->in_ops->put(entry);
@@ -1169,13 +1169,13 @@
 	} while (entry != NULL);
 
 	return;
-} 
+}
 
 static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 {
 	__be32 cache_id = msg->content.eg_info.cache_id;
 	eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc);
-	
+
 	if (entry == NULL) {
 		dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", mpc->dev->name);
 		return;
@@ -1188,7 +1188,7 @@
 	mpc->eg_ops->put(entry);
 
 	return;
-} 
+}
 
 static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
 {
@@ -1259,7 +1259,7 @@
 {
 	uint16_t holding_time;
 	eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc);
-	
+
 	holding_time = msg->content.eg_info.holding_time;
 	dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n",
 	       mpc->dev->name, entry, holding_time);
@@ -1272,13 +1272,13 @@
 		mpc->eg_ops->update(entry, holding_time);
 		return;
 	}
-	
+
 	write_lock_irq(&mpc->egress_lock);
 	mpc->eg_ops->remove_entry(entry, mpc);
 	write_unlock_irq(&mpc->egress_lock);
 
 	mpc->eg_ops->put(entry);
-	
+
 	return;
 }
 
@@ -1328,7 +1328,7 @@
 		return;
 	}
 	client->number_of_mps_macs = 1;
-	
+
 	return;
 }
 
@@ -1364,7 +1364,7 @@
 	mpc_timer.data = mpc_timer.expires;
 	mpc_timer.function = mpc_cache_check;
 	add_timer(&mpc_timer);
-	
+
 	return;
 }
 
@@ -1373,7 +1373,7 @@
 	struct mpoa_client *mpc = mpcs;
 	static unsigned long previous_resolving_check_time;
 	static unsigned long previous_refresh_time;
-	
+
 	while( mpc != NULL ){
 		mpc->in_ops->clear_count(mpc);
 		mpc->eg_ops->clear_expired(mpc);
@@ -1388,7 +1388,7 @@
 		mpc = mpc->next;
 	}
 	mpc_timer_refresh();
-	
+
 	return;
 }
 
diff --git a/net/atm/mpc.h b/net/atm/mpc.h
index 51f460d..24c386c 100644
--- a/net/atm/mpc.h
+++ b/net/atm/mpc.h
@@ -12,32 +12,32 @@
 int msg_to_mpoad(struct k_message *msg, struct mpoa_client *mpc);
 
 struct mpoa_client {
-        struct mpoa_client *next;
-        struct net_device *dev;      /* lec in question                     */
-        int dev_num;                 /* e.g. 2 for lec2                     */
-        int (*old_hard_start_xmit)(struct sk_buff *skb, struct net_device *dev);
-        struct atm_vcc *mpoad_vcc;   /* control channel to mpoad            */
-        uint8_t mps_ctrl_addr[ATM_ESA_LEN];  /* MPS control ATM address     */
-        uint8_t our_ctrl_addr[ATM_ESA_LEN];  /* MPC's control ATM address   */
+	struct mpoa_client *next;
+	struct net_device *dev;      /* lec in question                     */
+	int dev_num;                 /* e.g. 2 for lec2                     */
+	int (*old_hard_start_xmit)(struct sk_buff *skb, struct net_device *dev);
+	struct atm_vcc *mpoad_vcc;   /* control channel to mpoad            */
+	uint8_t mps_ctrl_addr[ATM_ESA_LEN];  /* MPS control ATM address     */
+	uint8_t our_ctrl_addr[ATM_ESA_LEN];  /* MPC's control ATM address   */
 
-        rwlock_t ingress_lock;
-        struct in_cache_ops *in_ops; /* ingress cache operations            */
-        in_cache_entry *in_cache;    /* the ingress cache of this MPC       */
+	rwlock_t ingress_lock;
+	struct in_cache_ops *in_ops; /* ingress cache operations            */
+	in_cache_entry *in_cache;    /* the ingress cache of this MPC       */
 
-        rwlock_t egress_lock;
-        struct eg_cache_ops *eg_ops; /* egress cache operations             */
-        eg_cache_entry *eg_cache;    /* the egress  cache of this MPC       */
+	rwlock_t egress_lock;
+	struct eg_cache_ops *eg_ops; /* egress cache operations             */
+	eg_cache_entry *eg_cache;    /* the egress  cache of this MPC       */
 
-        uint8_t *mps_macs;           /* array of MPS MAC addresses, >=1     */
-        int number_of_mps_macs;      /* number of the above MAC addresses   */
-        struct mpc_parameters parameters;  /* parameters for this client    */
+	uint8_t *mps_macs;           /* array of MPS MAC addresses, >=1     */
+	int number_of_mps_macs;      /* number of the above MAC addresses   */
+	struct mpc_parameters parameters;  /* parameters for this client    */
 };
 
 
 struct atm_mpoa_qos {
-        struct atm_mpoa_qos *next;
-        __be32 ipaddr;
-        struct atm_qos qos;
+	struct atm_mpoa_qos *next;
+	__be32 ipaddr;
+	struct atm_qos qos;
 };
 
 
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
index 697a081..24799e3 100644
--- a/net/atm/mpoa_caches.c
+++ b/net/atm/mpoa_caches.c
@@ -369,7 +369,7 @@
 	while (entry != NULL){
 		if (entry->shortcut == vcc) {
 			atomic_inc(&entry->use);
-	       		read_unlock_irqrestore(&mpc->egress_lock, flags);
+			read_unlock_irqrestore(&mpc->egress_lock, flags);
 			return entry;
 		}
 		entry = entry->next;
@@ -388,7 +388,7 @@
 	while(entry != NULL){
 		if(entry->latest_ip_addr == ipaddr) {
 			atomic_inc(&entry->use);
-	       		read_unlock_irq(&mpc->egress_lock);
+			read_unlock_irq(&mpc->egress_lock);
 			return entry;
 		}
 		entry = entry->next;
diff --git a/net/atm/mpoa_caches.h b/net/atm/mpoa_caches.h
index 84de977..8e5f78c 100644
--- a/net/atm/mpoa_caches.h
+++ b/net/atm/mpoa_caches.h
@@ -12,66 +12,66 @@
 void atm_mpoa_init_cache(struct mpoa_client *mpc);
 
 typedef struct in_cache_entry {
-        struct in_cache_entry *next;
-        struct in_cache_entry *prev;
-        struct timeval  tv;
-        struct timeval  reply_wait;
-        struct timeval  hold_down;
-        uint32_t  packets_fwded;
-        uint16_t  entry_state; 
-        uint32_t retry_time;
-        uint32_t refresh_time;
-        uint32_t count;
-        struct   atm_vcc *shortcut;
-        uint8_t  MPS_ctrl_ATM_addr[ATM_ESA_LEN];
-        struct   in_ctrl_info ctrl_info;
-        atomic_t use;
+	struct in_cache_entry *next;
+	struct in_cache_entry *prev;
+	struct timeval  tv;
+	struct timeval  reply_wait;
+	struct timeval  hold_down;
+	uint32_t  packets_fwded;
+	uint16_t  entry_state;
+	uint32_t retry_time;
+	uint32_t refresh_time;
+	uint32_t count;
+	struct   atm_vcc *shortcut;
+	uint8_t  MPS_ctrl_ATM_addr[ATM_ESA_LEN];
+	struct   in_ctrl_info ctrl_info;
+	atomic_t use;
 } in_cache_entry;
 
 struct in_cache_ops{
-        in_cache_entry *(*add_entry)(__be32 dst_ip,
-                                      struct mpoa_client *client);
-        in_cache_entry *(*get)(__be32 dst_ip, struct mpoa_client *client);
-        in_cache_entry *(*get_with_mask)(__be32 dst_ip,
+	in_cache_entry *(*add_entry)(__be32 dst_ip,
+				      struct mpoa_client *client);
+	in_cache_entry *(*get)(__be32 dst_ip, struct mpoa_client *client);
+	in_cache_entry *(*get_with_mask)(__be32 dst_ip,
 					 struct mpoa_client *client,
 					 __be32 mask);
-        in_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, 
-                                      struct mpoa_client *client);
-        void            (*put)(in_cache_entry *entry);
-        void            (*remove_entry)(in_cache_entry *delEntry,
+	in_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc,
+				      struct mpoa_client *client);
+	void            (*put)(in_cache_entry *entry);
+	void            (*remove_entry)(in_cache_entry *delEntry,
 					struct mpoa_client *client );
-        int             (*cache_hit)(in_cache_entry *entry,
-                                     struct mpoa_client *client);
-        void            (*clear_count)(struct mpoa_client *client);
-        void            (*check_resolving)(struct mpoa_client *client);
-        void            (*refresh)(struct mpoa_client *client);
-        void            (*destroy_cache)(struct mpoa_client *mpc);
+	int             (*cache_hit)(in_cache_entry *entry,
+				     struct mpoa_client *client);
+	void            (*clear_count)(struct mpoa_client *client);
+	void            (*check_resolving)(struct mpoa_client *client);
+	void            (*refresh)(struct mpoa_client *client);
+	void            (*destroy_cache)(struct mpoa_client *mpc);
 };
 
 typedef struct eg_cache_entry{
-        struct               eg_cache_entry *next;
-        struct               eg_cache_entry *prev;
-        struct               timeval  tv;
-        uint8_t              MPS_ctrl_ATM_addr[ATM_ESA_LEN];
-        struct atm_vcc       *shortcut;
-        uint32_t             packets_rcvd;
-        uint16_t             entry_state;
-        __be32             latest_ip_addr;    /* The src IP address of the last packet */
-        struct eg_ctrl_info  ctrl_info;
-        atomic_t             use;
+	struct               eg_cache_entry *next;
+	struct               eg_cache_entry *prev;
+	struct               timeval  tv;
+	uint8_t              MPS_ctrl_ATM_addr[ATM_ESA_LEN];
+	struct atm_vcc       *shortcut;
+	uint32_t             packets_rcvd;
+	uint16_t             entry_state;
+	__be32             latest_ip_addr;    /* The src IP address of the last packet */
+	struct eg_ctrl_info  ctrl_info;
+	atomic_t             use;
 } eg_cache_entry;
 
 struct eg_cache_ops{
-        eg_cache_entry *(*add_entry)(struct k_message *msg, struct mpoa_client *client);
-        eg_cache_entry *(*get_by_cache_id)(__be32 cache_id, struct mpoa_client *client);
-        eg_cache_entry *(*get_by_tag)(__be32 cache_id, struct mpoa_client *client);
-        eg_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
-        eg_cache_entry *(*get_by_src_ip)(__be32 ipaddr, struct mpoa_client *client);
-        void            (*put)(eg_cache_entry *entry);
-        void            (*remove_entry)(eg_cache_entry *entry, struct mpoa_client *client);
-        void            (*update)(eg_cache_entry *entry, uint16_t holding_time);
-        void            (*clear_expired)(struct mpoa_client *client);
-        void            (*destroy_cache)(struct mpoa_client *mpc);
+	eg_cache_entry *(*add_entry)(struct k_message *msg, struct mpoa_client *client);
+	eg_cache_entry *(*get_by_cache_id)(__be32 cache_id, struct mpoa_client *client);
+	eg_cache_entry *(*get_by_tag)(__be32 cache_id, struct mpoa_client *client);
+	eg_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
+	eg_cache_entry *(*get_by_src_ip)(__be32 ipaddr, struct mpoa_client *client);
+	void            (*put)(eg_cache_entry *entry);
+	void            (*remove_entry)(eg_cache_entry *entry, struct mpoa_client *client);
+	void            (*update)(eg_cache_entry *entry, uint16_t holding_time);
+	void            (*clear_expired)(struct mpoa_client *client);
+	void            (*destroy_cache)(struct mpoa_client *mpc);
 };
 
 
@@ -85,7 +85,7 @@
 /* VCC states */
 
 #define OPEN   1
-#define CLOSED 0 
+#define CLOSED 0
 
 /* Egress cache entry states */
 
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
index 3844c85..4b05cbe 100644
--- a/net/atm/mpoa_proc.c
+++ b/net/atm/mpoa_proc.c
@@ -2,7 +2,7 @@
 #ifdef CONFIG_PROC_FS
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/string.h> 
+#include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
@@ -16,7 +16,7 @@
 
 /*
  * mpoa_proc.c: Implementation MPOA client's proc
- * file system statistics 
+ * file system statistics
  */
 
 #if 1
@@ -32,14 +32,14 @@
 
 static int proc_mpc_open(struct inode *inode, struct file *file);
 static ssize_t proc_mpc_write(struct file *file, const char __user *buff,
-                              size_t nbytes, loff_t *ppos);
+			      size_t nbytes, loff_t *ppos);
 
 static int parse_qos(const char *buff);
 
 /*
  *   Define allowed FILE OPERATIONS
  */
-static struct file_operations mpc_file_operations = {
+static const struct file_operations mpc_file_operations = {
 	.owner =	THIS_MODULE,
 	.open =		proc_mpc_open,
 	.read =		seq_read,
@@ -52,18 +52,18 @@
  * Returns the state of an ingress cache entry as a string
  */
 static const char *ingress_state_string(int state){
-        switch(state) {
+	switch(state) {
 	case INGRESS_RESOLVING:
-	        return "resolving  ";
+		return "resolving  ";
 		break;
 	case INGRESS_RESOLVED:
-                return "resolved   ";
+		return "resolved   ";
 		break;
 	case INGRESS_INVALID:
-	        return "invalid    ";
+		return "invalid    ";
 		break;
 	case INGRESS_REFRESHING:
-	        return "refreshing ";
+		return "refreshing ";
 		break;
 	default:
 	       return "";
@@ -74,15 +74,15 @@
  * Returns the state of an egress cache entry as a string
  */
 static const char *egress_state_string(int state){
-        switch(state) {
+	switch(state) {
 	case EGRESS_RESOLVED:
-	        return "resolved   ";
+		return "resolved   ";
 		break;
 	case EGRESS_PURGE:
-                return "purge      ";
+		return "purge      ";
 		break;
 	case EGRESS_INVALID:
-	        return "invalid    ";
+		return "invalid    ";
 		break;
 	default:
 	       return "";
@@ -135,7 +135,7 @@
 		return 0;
 	}
 
-	seq_printf(m, "\nInterface %d:\n\n", mpc->dev_num);  
+	seq_printf(m, "\nInterface %d:\n\n", mpc->dev_num);
 	seq_printf(m, "Ingress Entries:\nIP address      State      Holding time  Packets fwded  VPI  VCI\n");
 	do_gettimeofday(&now);
 
@@ -163,7 +163,7 @@
 			   egress_state_string(eg_entry->entry_state),
 			   (eg_entry->ctrl_info.holding_time-(now.tv_sec-eg_entry->tv.tv_sec)),
 			   eg_entry->packets_rcvd);
-		
+
 		/* latest IP address */
 		temp = (unsigned char *)&eg_entry->latest_ip_addr;
 		sprintf(ip_string, "%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]);
@@ -190,51 +190,51 @@
 }
 
 static ssize_t proc_mpc_write(struct file *file, const char __user *buff,
-                              size_t nbytes, loff_t *ppos)
+			      size_t nbytes, loff_t *ppos)
 {
-        char *page, *p;
+	char *page, *p;
 	unsigned len;
 
-        if (nbytes == 0)
+	if (nbytes == 0)
 		return 0;
 
-        if (nbytes >= PAGE_SIZE)
+	if (nbytes >= PAGE_SIZE)
 		nbytes = PAGE_SIZE-1;
 
-        page = (char *)__get_free_page(GFP_KERNEL);
-        if (!page)
+	page = (char *)__get_free_page(GFP_KERNEL);
+	if (!page)
 		return -ENOMEM;
 
-        for (p = page, len = 0; len < nbytes; p++, len++) {
-                if (get_user(*p, buff++)) {
+	for (p = page, len = 0; len < nbytes; p++, len++) {
+		if (get_user(*p, buff++)) {
 			free_page((unsigned long)page);
 			return -EFAULT;
 		}
-                if (*p == '\0' || *p == '\n')
-                        break;
-        }
+		if (*p == '\0' || *p == '\n')
+			break;
+	}
 
-        *p = '\0';
+	*p = '\0';
 
 	if (!parse_qos(page))
-                printk("mpoa: proc_mpc_write: could not parse '%s'\n", page);
+		printk("mpoa: proc_mpc_write: could not parse '%s'\n", page);
 
-        free_page((unsigned long)page);
-        
-        return len;
+	free_page((unsigned long)page);
+
+	return len;
 }
 
 static int parse_qos(const char *buff)
 {
-        /* possible lines look like this
-         * add 130.230.54.142 tx=max_pcr,max_sdu rx=max_pcr,max_sdu
-         */
-        unsigned char ip[4]; 
+	/* possible lines look like this
+	 * add 130.230.54.142 tx=max_pcr,max_sdu rx=max_pcr,max_sdu
+	 */
+	unsigned char ip[4];
 	int tx_pcr, tx_sdu, rx_pcr, rx_sdu;
-        __be32 ipaddr;
-	struct atm_qos qos; 
-        
-        memset(&qos, 0, sizeof(struct atm_qos));
+	__be32 ipaddr;
+	struct atm_qos qos;
+
+	memset(&qos, 0, sizeof(struct atm_qos));
 
 	if (sscanf(buff, "del %hhu.%hhu.%hhu.%hhu",
 			ip, ip+1, ip+2, ip+3) == 4) {
@@ -250,14 +250,14 @@
 		ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu, &rx_pcr, &rx_sdu) != 8)
 		return 0;
 
-        ipaddr = *(__be32 *)ip;
+	ipaddr = *(__be32 *)ip;
 	qos.txtp.traffic_class = ATM_CBR;
 	qos.txtp.max_pcr = tx_pcr;
 	qos.txtp.max_sdu = tx_sdu;
 	qos.rxtp.traffic_class = ATM_CBR;
 	qos.rxtp.max_pcr = rx_pcr;
 	qos.rxtp.max_sdu = rx_sdu;
-        qos.aal = ATM_AAL5;
+	qos.aal = ATM_AAL5;
 	dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n",
 		qos.txtp.max_pcr,
 		qos.txtp.max_sdu,
@@ -276,11 +276,11 @@
 {
 	struct proc_dir_entry *p;
 
-        p = create_proc_entry(STAT_FILE_NAME, 0, atm_proc_root);
+	p = create_proc_entry(STAT_FILE_NAME, 0, atm_proc_root);
 	if (!p) {
-                printk(KERN_ERR "Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME);
-                return -ENOMEM;
-        }
+		printk(KERN_ERR "Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME);
+		return -ENOMEM;
+	}
 	p->proc_fops = &mpc_file_operations;
 	p->owner = THIS_MODULE;
 	return 0;
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 739866b..9e61e51 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -33,7 +33,7 @@
 static ssize_t proc_dev_atm_read(struct file *file,char __user *buf,size_t count,
     loff_t *pos);
 
-static struct file_operations proc_atm_dev_ops = {
+static const struct file_operations proc_atm_dev_ops = {
 	.owner =	THIS_MODULE,
 	.read =		proc_dev_atm_read,
 };
@@ -86,7 +86,7 @@
 				break;
 		}
 		l--;
-	} 
+	}
 try_again:
 	for (; sk; sk = sk_next(sk)) {
 		l -= compare_family(sk, family);
@@ -205,7 +205,7 @@
 	seq_printf(seq, "%p ", vcc);
 	if (!vcc->dev)
 		seq_printf(seq, "Unassigned    ");
-	else 
+	else
 		seq_printf(seq, "%3d %3d %5d ", vcc->dev->number, vcc->vpi,
 			vcc->vci);
 	switch (sk->sk_family) {
@@ -249,7 +249,7 @@
 	static char atm_dev_banner[] =
 		"Itf Type    ESI/\"MAC\"addr "
 		"AAL(TX,err,RX,err,drop) ...               [refcnt]\n";
- 
+
 	if (v == (void *)1)
 		seq_puts(seq, atm_dev_banner);
 	else {
@@ -257,22 +257,22 @@
 
 		atm_dev_info(seq, dev);
 	}
- 	return 0;
+	return 0;
 }
- 
+
 static struct seq_operations atm_dev_seq_ops = {
 	.start	= atm_dev_seq_start,
 	.next	= atm_dev_seq_next,
 	.stop	= atm_dev_seq_stop,
 	.show	= atm_dev_seq_show,
 };
- 
+
 static int atm_dev_seq_open(struct inode *inode, struct file *file)
 {
 	return seq_open(file, &atm_dev_seq_ops);
 }
- 
-static struct file_operations devices_seq_fops = {
+
+static const struct file_operations devices_seq_fops = {
 	.open		= atm_dev_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -281,7 +281,7 @@
 
 static int pvc_seq_show(struct seq_file *seq, void *v)
 {
-	static char atm_pvc_banner[] = 
+	static char atm_pvc_banner[] =
 		"Itf VPI VCI   AAL RX(PCR,Class) TX(PCR,Class)\n";
 
 	if (v == (void *)1)
@@ -307,7 +307,7 @@
 	return __vcc_seq_open(inode, file, PF_ATMPVC, &pvc_seq_ops);
 }
 
-static struct file_operations pvc_seq_fops = {
+static const struct file_operations pvc_seq_fops = {
 	.open		= pvc_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -316,32 +316,32 @@
 
 static int vcc_seq_show(struct seq_file *seq, void *v)
 {
- 	if (v == (void *)1) {
- 		seq_printf(seq, sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
- 			"Address ", "Itf VPI VCI   Fam Flags Reply "
- 			"Send buffer     Recv buffer      [refcnt]\n");
- 	} else {
- 		struct vcc_state *state = seq->private;
- 		struct atm_vcc *vcc = atm_sk(state->sk);
-  
- 		vcc_info(seq, vcc);
- 	}
-  	return 0;
+	if (v == (void *)1) {
+		seq_printf(seq, sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
+			"Address ", "Itf VPI VCI   Fam Flags Reply "
+			"Send buffer     Recv buffer      [refcnt]\n");
+	} else {
+		struct vcc_state *state = seq->private;
+		struct atm_vcc *vcc = atm_sk(state->sk);
+
+		vcc_info(seq, vcc);
+	}
+	return 0;
 }
-  
+
 static struct seq_operations vcc_seq_ops = {
- 	.start	= vcc_seq_start,
- 	.next	= vcc_seq_next,
- 	.stop	= vcc_seq_stop,
- 	.show	= vcc_seq_show,
+	.start	= vcc_seq_start,
+	.next	= vcc_seq_next,
+	.stop	= vcc_seq_stop,
+	.show	= vcc_seq_show,
 };
- 
+
 static int vcc_seq_open(struct inode *inode, struct file *file)
 {
- 	return __vcc_seq_open(inode, file, 0, &vcc_seq_ops);
+	return __vcc_seq_open(inode, file, 0, &vcc_seq_ops);
 }
- 
-static struct file_operations vcc_seq_fops = {
+
+static const struct file_operations vcc_seq_fops = {
 	.open		= vcc_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -350,7 +350,7 @@
 
 static int svc_seq_show(struct seq_file *seq, void *v)
 {
-	static char atm_svc_banner[] = 
+	static char atm_svc_banner[] =
 		"Itf VPI VCI           State      Remote\n";
 
 	if (v == (void *)1)
@@ -376,7 +376,7 @@
 	return __vcc_seq_open(inode, file, PF_ATMSVC, &svc_seq_ops);
 }
 
-static struct file_operations svc_seq_fops = {
+static const struct file_operations svc_seq_fops = {
 	.open		= svc_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -457,7 +457,7 @@
 
 static struct atm_proc_entry {
 	char *name;
-	struct file_operations *proc_fops;
+	const struct file_operations *proc_fops;
 	struct proc_dir_entry *dirent;
 } atm_proc_ents[] = {
 	{ .name = "devices",	.proc_fops = &devices_seq_fops },
@@ -472,7 +472,7 @@
 	static struct atm_proc_entry *e;
 
 	for (e = atm_proc_ents; e->name; e++) {
-		if (e->dirent) 
+		if (e->dirent)
 			remove_proc_entry(e->name, atm_proc_root);
 	}
 	remove_proc_entry("net/atm", NULL);
diff --git a/net/atm/pvc.c b/net/atm/pvc.c
index b2148b4..848e6e1 100644
--- a/net/atm/pvc.c
+++ b/net/atm/pvc.c
@@ -72,7 +72,7 @@
 
 
 static int pvc_getsockopt(struct socket *sock, int level, int optname,
-		          char __user *optval, int __user *optlen)
+			  char __user *optval, int __user *optlen)
 {
 	struct sock *sk = sock->sk;
 	int error;
@@ -91,7 +91,7 @@
 	struct atm_vcc *vcc = ATM_SD(sock);
 
 	if (!vcc->dev || !test_bit(ATM_VF_ADDR,&vcc->flags)) return -ENOTCONN;
-        *sockaddr_len = sizeof(struct sockaddr_atmpvc);
+	*sockaddr_len = sizeof(struct sockaddr_atmpvc);
 	addr = (struct sockaddr_atmpvc *) sockaddr;
 	addr->sap_family = AF_ATMPVC;
 	addr->sap_addr.itf = vcc->dev->number;
diff --git a/net/atm/raw.c b/net/atm/raw.c
index 3e57b17..1378f61 100644
--- a/net/atm/raw.c
+++ b/net/atm/raw.c
@@ -4,7 +4,6 @@
 
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/atmdev.h>
 #include <linux/capability.h>
 #include <linux/kernel.h>
@@ -56,12 +55,12 @@
 	 * still work
 	 */
 	if (!capable(CAP_NET_ADMIN) &&
-            (((u32 *) skb->data)[0] & (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK)) !=
-            ((vcc->vpi << ATM_HDR_VPI_SHIFT) | (vcc->vci << ATM_HDR_VCI_SHIFT)))
+	    (((u32 *) skb->data)[0] & (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK)) !=
+	    ((vcc->vpi << ATM_HDR_VPI_SHIFT) | (vcc->vci << ATM_HDR_VCI_SHIFT)))
 	    {
 		kfree_skb(skb);
 		return -EADDRNOTAVAIL;
-        }
+	}
 	return vcc->dev->ops->send(vcc,skb);
 }
 
diff --git a/net/atm/resources.c b/net/atm/resources.c
index 529f7e6..1bcf6dc 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -142,8 +142,8 @@
 	set_bit(ATM_DF_REMOVED, &dev->flags);
 
 	/*
-	 * if we remove current device from atm_devs list, new device 
-	 * with same number can appear, such we need deregister proc, 
+	 * if we remove current device from atm_devs list, new device
+	 * with same number can appear, such we need deregister proc,
 	 * release async all vccs and remove them from vccs list too
 	 */
 	mutex_lock(&atm_dev_mutex);
@@ -228,7 +228,7 @@
 				*tmp_p++ = dev->number;
 			}
 			mutex_unlock(&atm_dev_mutex);
-		        error = ((copy_to_user(buf, tmp_buf, size)) ||
+			error = ((copy_to_user(buf, tmp_buf, size)) ||
 					put_user(size, &iobuf->length))
 						? -EFAULT : 0;
 			kfree(tmp_buf);
@@ -247,7 +247,7 @@
 	if (!(dev = try_then_request_module(atm_dev_lookup(number),
 					    "atm-device-%d", number)))
 		return -ENODEV;
-	
+
 	switch (cmd) {
 		case ATM_GETTYPE:
 			size = strlen(dev->type) + 1;
@@ -390,7 +390,7 @@
 				goto done;
 			}
 	}
-	
+
 	if (size)
 		error = put_user(size, &sioc->length)
 			? -EFAULT : 0;
@@ -414,15 +414,15 @@
 
 void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos)
 {
- 	mutex_lock(&atm_dev_mutex);
+	mutex_lock(&atm_dev_mutex);
 	return *pos ? dev_get_idx(*pos) : (void *) 1;
 }
 
 void atm_dev_seq_stop(struct seq_file *seq, void *v)
 {
- 	mutex_unlock(&atm_dev_mutex);
+	mutex_unlock(&atm_dev_mutex);
 }
- 
+
 void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	++*pos;
diff --git a/net/atm/signaling.h b/net/atm/signaling.h
index 434ead4..08b2a69 100644
--- a/net/atm/signaling.h
+++ b/net/atm/signaling.h
@@ -1,7 +1,7 @@
 /* net/atm/signaling.h - ATM signaling */
- 
+
 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
- 
+
 
 #ifndef NET_ATM_SIGNALING_H
 #define NET_ATM_SIGNALING_H
diff --git a/net/atm/svc.c b/net/atm/svc.c
index 3a180cf..876ec7b 100644
--- a/net/atm/svc.c
+++ b/net/atm/svc.c
@@ -89,7 +89,7 @@
 		clear_bit(ATM_VF_READY, &vcc->flags);
 		/* VCC pointer is used as a reference, so we must not free it
 		   (thereby subjecting it to re-use) before all pending connections
-	           are closed */
+		   are closed */
 		svc_disconnect(vcc);
 		vcc_release(sock);
 	}
@@ -144,7 +144,7 @@
 		error = -EUNATCH;
 		goto out;
 	}
-        if (!sk->sk_err)
+	if (!sk->sk_err)
 		set_bit(ATM_VF_BOUND,&vcc->flags);
 	error = -sk->sk_err;
 out:
@@ -229,7 +229,7 @@
 			 * This is tricky:
 			 *   Kernel ---close--> Demon
 			 *   Kernel <--close--- Demon
-		         * or
+			 * or
 			 *   Kernel ---close--> Demon
 			 *   Kernel <--error--- Demon
 			 * or
@@ -470,13 +470,13 @@
 			}
 			set_bit(ATM_VF_HASSAP, &vcc->flags);
 			break;
- 		case SO_MULTIPOINT:
+		case SO_MULTIPOINT:
 			if (level != SOL_ATM || optlen != sizeof(int)) {
 				error = -EINVAL;
 				goto out;
 			}
- 			if (get_user(value, (int __user *) optval)) {
- 				error = -EFAULT;
+			if (get_user(value, (int __user *) optval)) {
+				error = -EFAULT;
 				goto out;
 			}
 			if (value == 1) {
@@ -486,7 +486,7 @@
 			} else {
 				error = -EINVAL;
 			}
-  			break;
+			break;
 		default:
 			error = vcc_setsockopt(sock, level, optname,
 					       optval, optlen);
@@ -539,7 +539,7 @@
 	set_bit(ATM_VF_WAITING, &vcc->flags);
 	prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 	sigd_enq(vcc, as_addparty, NULL, NULL,
-	         (struct sockaddr_atmsvc *) sockaddr);
+		 (struct sockaddr_atmsvc *) sockaddr);
 	if (flags & O_NONBLOCK) {
 		finish_wait(sk->sk_sleep, &wait);
 		error = -EINPROGRESS;
@@ -587,26 +587,26 @@
 
 static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
- 	int error, ep_ref;
- 	struct sockaddr_atmsvc sa;
+	int error, ep_ref;
+	struct sockaddr_atmsvc sa;
 	struct atm_vcc *vcc = ATM_SD(sock);
-  
+
 	switch (cmd) {
- 		case ATM_ADDPARTY:
- 			if (!test_bit(ATM_VF_SESSION, &vcc->flags))
- 				return -EINVAL;
- 			if (copy_from_user(&sa, (void __user *) arg, sizeof(sa)))
+		case ATM_ADDPARTY:
+			if (!test_bit(ATM_VF_SESSION, &vcc->flags))
+				return -EINVAL;
+			if (copy_from_user(&sa, (void __user *) arg, sizeof(sa)))
 				return -EFAULT;
- 			error = svc_addparty(sock, (struct sockaddr *) &sa, sizeof(sa), 0);
- 			break;
- 		case ATM_DROPPARTY:
- 			if (!test_bit(ATM_VF_SESSION, &vcc->flags))
- 				return -EINVAL;
- 			if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int)))
+			error = svc_addparty(sock, (struct sockaddr *) &sa, sizeof(sa), 0);
+			break;
+		case ATM_DROPPARTY:
+			if (!test_bit(ATM_VF_SESSION, &vcc->flags))
+				return -EINVAL;
+			if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int)))
 				return -EFAULT;
- 			error = svc_dropparty(sock, ep_ref);
- 			break;
-  		default:
+			error = svc_dropparty(sock, ep_ref);
+			break;
+		default:
 			error = vcc_ioctl(sock, cmd, arg);
 	}
 
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 42233df..1c07c6a 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -263,9 +263,9 @@
 {
 	ax25_cb *ax25=(ax25_cb *)data;
 	struct sock *sk;
-	
+
 	sk=ax25->sk;
-	
+
 	bh_lock_sock(sk);
 	sock_hold(sk);
 	ax25_destroy_socket(ax25);
@@ -369,57 +369,57 @@
 		ax25_disconnect(ax25, ENETRESET);
 		break;
 
-  	case AX25_WINDOW:
-  		if (ax25->modulus == AX25_MODULUS) {
-  			if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7)
-  				return -EINVAL;
-  		} else {
-  			if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63)
-  				return -EINVAL;
-  		}
-  		ax25->window = ax25_ctl.arg;
-  		break;
+	case AX25_WINDOW:
+		if (ax25->modulus == AX25_MODULUS) {
+			if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7)
+				return -EINVAL;
+		} else {
+			if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63)
+				return -EINVAL;
+		}
+		ax25->window = ax25_ctl.arg;
+		break;
 
-  	case AX25_T1:
+	case AX25_T1:
 		if (ax25_ctl.arg < 1)
-  			return -EINVAL;
-  		ax25->rtt = (ax25_ctl.arg * HZ) / 2;
-  		ax25->t1  = ax25_ctl.arg * HZ;
-  		break;
-
-  	case AX25_T2:
-  		if (ax25_ctl.arg < 1)
-  			return -EINVAL;
-  		ax25->t2 = ax25_ctl.arg * HZ;
-  		break;
-
-  	case AX25_N2:
-  		if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31)
 			return -EINVAL;
-  		ax25->n2count = 0;
-  		ax25->n2 = ax25_ctl.arg;
-  		break;
+		ax25->rtt = (ax25_ctl.arg * HZ) / 2;
+		ax25->t1  = ax25_ctl.arg * HZ;
+		break;
 
-  	case AX25_T3:
-  		if (ax25_ctl.arg < 0)
-  			return -EINVAL;
-  		ax25->t3 = ax25_ctl.arg * HZ;
-  		break;
+	case AX25_T2:
+		if (ax25_ctl.arg < 1)
+			return -EINVAL;
+		ax25->t2 = ax25_ctl.arg * HZ;
+		break;
 
-  	case AX25_IDLE:
-  		if (ax25_ctl.arg < 0)
-  			return -EINVAL;
-  		ax25->idle = ax25_ctl.arg * 60 * HZ;
-  		break;
+	case AX25_N2:
+		if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31)
+			return -EINVAL;
+		ax25->n2count = 0;
+		ax25->n2 = ax25_ctl.arg;
+		break;
 
-  	case AX25_PACLEN:
-  		if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535)
-  			return -EINVAL;
-  		ax25->paclen = ax25_ctl.arg;
-  		break;
+	case AX25_T3:
+		if (ax25_ctl.arg < 0)
+			return -EINVAL;
+		ax25->t3 = ax25_ctl.arg * HZ;
+		break;
 
-  	default:
-  		return -EINVAL;
+	case AX25_IDLE:
+		if (ax25_ctl.arg < 0)
+			return -EINVAL;
+		ax25->idle = ax25_ctl.arg * 60 * HZ;
+		break;
+
+	case AX25_PACLEN:
+		if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535)
+			return -EINVAL;
+		ax25->paclen = ax25_ctl.arg;
+		break;
+
+	default:
+		return -EINVAL;
 	  }
 
 	return 0;
@@ -1209,7 +1209,7 @@
 
 	if (sk->sk_type == SOCK_SEQPACKET &&
 	    (ax25t=ax25_find_cb(&ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi,
-		    	 ax25->ax25_dev->dev))) {
+			 ax25->ax25_dev->dev))) {
 		kfree(digi);
 		err = -EADDRINUSE;		/* Already such a connection */
 		ax25_cb_put(ax25t);
@@ -1456,7 +1456,7 @@
 		err = -EMSGSIZE;
 		goto out;
 	}
-		
+
 	if (usax != NULL) {
 		if (usax->sax25_family != AF_AX25) {
 			err = -EINVAL;
@@ -1470,8 +1470,8 @@
 		else if (addr_len != sizeof(struct full_sockaddr_ax25)) {
 			/* support for old structure may go away some time */
 			if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||
-		    	    (addr_len > sizeof(struct full_sockaddr_ax25))) {
-		    		err = -EINVAL;
+			    (addr_len > sizeof(struct full_sockaddr_ax25))) {
+				err = -EINVAL;
 				goto out;
 			}
 
@@ -1624,7 +1624,7 @@
 
 	/* Now we can treat all alike */
 	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
-	                        flags & MSG_DONTWAIT, &err);
+				flags & MSG_DONTWAIT, &err);
 	if (skb == NULL)
 		goto out;
 
@@ -1869,7 +1869,7 @@
 	return hlist_entry( ((struct ax25_cb *)v)->ax25_node.next,
 			    struct ax25_cb, ax25_node);
 }
-	
+
 static void ax25_info_stop(struct seq_file *seq, void *v)
 {
 	spin_unlock_bh(&ax25_list_lock);
@@ -1938,7 +1938,7 @@
 	return seq_open(file, &ax25_info_seqops);
 }
 
-static struct file_operations ax25_info_fops = {
+static const struct file_operations ax25_info_fops = {
 	.owner = THIS_MODULE,
 	.open = ax25_info_open,
 	.read = seq_read,
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
index 97a49c7..7e7964d 100644
--- a/net/ax25/ax25_addr.c
+++ b/net/ax25/ax25_addr.c
@@ -12,7 +12,6 @@
 #include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -126,10 +125,10 @@
 		ct++;
 	}
 
- 	if ((a->ax25_call[ct] & 0x1E) == (b->ax25_call[ct] & 0x1E))	/* SSID without control bit */
- 		return 0;
+	if ((a->ax25_call[ct] & 0x1E) == (b->ax25_call[ct] & 0x1E))	/* SSID without control bit */
+		return 0;
 
- 	return 2;			/* Partial match */
+	return 2;			/* Partial match */
 }
 
 EXPORT_SYMBOL(ax25cmp);
diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
index b7876782..528c874 100644
--- a/net/ax25/ax25_dev.c
+++ b/net/ax25/ax25_dev.c
@@ -11,7 +11,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c
index edcaa89..e37d217 100644
--- a/net/ax25/ax25_ds_in.c
+++ b/net/ax25/ax25_ds_in.c
@@ -12,7 +12,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c
index 4d22d44..9569dd3 100644
--- a/net/ax25/ax25_ds_subr.c
+++ b/net/ax25/ax25_ds_subr.c
@@ -12,7 +12,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c
index aff3e65..16be0c1 100644
--- a/net/ax25/ax25_iface.c
+++ b/net/ax25/ax25_iface.c
@@ -12,7 +12,6 @@
 #include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/string.h>
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index e9d9429..4a6b26b 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -14,7 +14,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index 136c3ae..7f818bb 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -12,7 +12,6 @@
 #include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -55,46 +54,46 @@
 	if (type == ETH_P_AX25)
 		return 0;
 
-  	/* header is an AX.25 UI frame from us to them */
- 	buff = skb_push(skb, AX25_HEADER_LEN);
-  	*buff++ = 0x00;	/* KISS DATA */
+	/* header is an AX.25 UI frame from us to them */
+	buff = skb_push(skb, AX25_HEADER_LEN);
+	*buff++ = 0x00;	/* KISS DATA */
 
 	if (daddr != NULL)
 		memcpy(buff, daddr, dev->addr_len);	/* Address specified */
 
-  	buff[6] &= ~AX25_CBIT;
-  	buff[6] &= ~AX25_EBIT;
-  	buff[6] |= AX25_SSSID_SPARE;
-  	buff    += AX25_ADDR_LEN;
+	buff[6] &= ~AX25_CBIT;
+	buff[6] &= ~AX25_EBIT;
+	buff[6] |= AX25_SSSID_SPARE;
+	buff    += AX25_ADDR_LEN;
 
-  	if (saddr != NULL)
-  		memcpy(buff, saddr, dev->addr_len);
-  	else
-  		memcpy(buff, dev->dev_addr, dev->addr_len);
+	if (saddr != NULL)
+		memcpy(buff, saddr, dev->addr_len);
+	else
+		memcpy(buff, dev->dev_addr, dev->addr_len);
 
-  	buff[6] &= ~AX25_CBIT;
-  	buff[6] |= AX25_EBIT;
-  	buff[6] |= AX25_SSSID_SPARE;
-  	buff    += AX25_ADDR_LEN;
+	buff[6] &= ~AX25_CBIT;
+	buff[6] |= AX25_EBIT;
+	buff[6] |= AX25_SSSID_SPARE;
+	buff    += AX25_ADDR_LEN;
 
-  	*buff++  = AX25_UI;	/* UI */
+	*buff++  = AX25_UI;	/* UI */
 
-  	/* Append a suitable AX.25 PID */
-  	switch (type) {
-  	case ETH_P_IP:
-  		*buff++ = AX25_P_IP;
- 		break;
-  	case ETH_P_ARP:
-  		*buff++ = AX25_P_ARP;
-  		break;
-  	default:
-  		printk(KERN_ERR "AX.25: ax25_hard_header - wrong protocol type 0x%2.2x\n", type);
-  		*buff++ = 0;
-  		break;
- 	}
+	/* Append a suitable AX.25 PID */
+	switch (type) {
+	case ETH_P_IP:
+		*buff++ = AX25_P_IP;
+		break;
+	case ETH_P_ARP:
+		*buff++ = AX25_P_ARP;
+		break;
+	default:
+		printk(KERN_ERR "AX.25: ax25_hard_header - wrong protocol type 0x%2.2x\n", type);
+		*buff++ = 0;
+		break;
+	}
 
 	if (daddr != NULL)
-	  	return AX25_HEADER_LEN;
+		return AX25_HEADER_LEN;
 
 	return -AX25_HEADER_LEN;	/* Unfinished header */
 }
@@ -114,8 +113,8 @@
 	dst = (ax25_address *)(bp + 1);
 	src = (ax25_address *)(bp + 8);
 
-  	if (arp_find(bp + 1, skb))
-  		return 1;
+	if (arp_find(bp + 1, skb))
+		return 1;
 
 	route = ax25_get_route(dst, NULL);
 	if (route) {
@@ -127,8 +126,8 @@
 	if (dev == NULL)
 		dev = skb->dev;
 
-        if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
-                goto put;
+	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
+		goto put;
 	}
 
 	if (bp[16] == AX25_P_IP) {
@@ -175,8 +174,8 @@
 			ourskb->nh.raw = ourskb->data;
 
 			ax25=ax25_send_frame(
-			    ourskb, 
-			    ax25_dev->values[AX25_VALUES_PACLEN], 
+			    ourskb,
+			    ax25_dev->values[AX25_VALUES_PACLEN],
 			    &src_c,
 			    &dst_c, digipeat, dev);
 			if (ax25) {
@@ -186,13 +185,13 @@
 		}
 	}
 
-  	bp[7]  &= ~AX25_CBIT;
-  	bp[7]  &= ~AX25_EBIT;
-  	bp[7]  |= AX25_SSSID_SPARE;
+	bp[7]  &= ~AX25_CBIT;
+	bp[7]  &= ~AX25_EBIT;
+	bp[7]  |= AX25_SSSID_SPARE;
 
-  	bp[14] &= ~AX25_CBIT;
-  	bp[14] |= AX25_EBIT;
-  	bp[14] |= AX25_SSSID_SPARE;
+	bp[14] &= ~AX25_CBIT;
+	bp[14] |= AX25_EBIT;
+	bp[14] |= AX25_SSSID_SPARE;
 
 	skb_pull(skb, AX25_KISS_HEADER_LEN);
 
@@ -211,7 +210,7 @@
 	if (route)
 		ax25_put_route(route);
 
-  	return 1;
+	return 1;
 }
 
 #else	/* INET */
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index f84047d..2238350 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -14,7 +14,6 @@
 #include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 0a03816..d65b8e2 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -87,7 +87,7 @@
 	ax25_rt = ax25_route_list;
 	while (ax25_rt != NULL) {
 		if (ax25cmp(&ax25_rt->callsign, &route->dest_addr) == 0 &&
-		            ax25_rt->dev == ax25_dev->dev) {
+			    ax25_rt->dev == ax25_dev->dev) {
 			kfree(ax25_rt->digipeat);
 			ax25_rt->digipeat = NULL;
 			if (route->digi_count != 0) {
@@ -252,8 +252,8 @@
 {
 	struct ax25_route *ax25_rt;
 	int i = 1;
- 
- 	read_lock(&ax25_route_lock);
+
+	read_lock(&ax25_route_lock);
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
@@ -269,7 +269,7 @@
 static void *ax25_rt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	++*pos;
-	return (v == SEQ_START_TOKEN) ? ax25_route_list : 
+	return (v == SEQ_START_TOKEN) ? ax25_route_list :
 		((struct ax25_route *) v)->next;
 }
 
@@ -332,7 +332,7 @@
 	return seq_open(file, &ax25_rt_seqops);
 }
 
-struct file_operations ax25_route_fops = {
+const struct file_operations ax25_route_fops = {
 	.owner = THIS_MODULE,
 	.open = ax25_rt_info_open,
 	.read = seq_read,
diff --git a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c
index f6ed283..a8eef88 100644
--- a/net/ax25/ax25_std_in.c
+++ b/net/ax25/ax25_std_in.c
@@ -19,7 +19,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/ax25/ax25_std_subr.c b/net/ax25/ax25_std_subr.c
index 2b3c801..277f81b 100644
--- a/net/ax25/ax25_std_subr.c
+++ b/net/ax25/ax25_std_subr.c
@@ -11,7 +11,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
index a29c480..f2f6918 100644
--- a/net/ax25/ax25_std_timer.c
+++ b/net/ax25/ax25_std_timer.c
@@ -14,7 +14,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -34,7 +33,7 @@
 void ax25_std_heartbeat_expiry(ax25_cb *ax25)
 {
 	struct sock *sk=ax25->sk;
-	
+
 	if (sk)
 		bh_lock_sock(sk);
 
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index c41dbe5..b6c577e 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -14,7 +14,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -56,7 +55,7 @@
 	 */
 	if (ax25->va != nr) {
 		while (skb_peek(&ax25->ack_queue) != NULL && ax25->va != nr) {
-		        skb = skb_dequeue(&ax25->ack_queue);
+			skb = skb_dequeue(&ax25->ack_queue);
 			kfree_skb(skb);
 			ax25->va = (ax25->va + 1) % ax25->modulus;
 		}
@@ -65,7 +64,7 @@
 
 void ax25_requeue_frames(ax25_cb *ax25)
 {
-        struct sk_buff *skb, *skb_prev = NULL;
+	struct sk_buff *skb, *skb_prev = NULL;
 
 	/*
 	 * Requeue all the un-ack-ed frames on the output queue to be picked
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index 5e9a81e..75c7664 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -13,7 +13,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -164,7 +163,7 @@
 	++*pos;
 
 	return hlist_entry(((ax25_uid_assoc *)v)->uid_node.next,
-	                   ax25_uid_assoc, uid_node);
+			   ax25_uid_assoc, uid_node);
 }
 
 static void ax25_uid_seq_stop(struct seq_file *seq, void *v)
@@ -198,7 +197,7 @@
 	return seq_open(file, &ax25_uid_seqops);
 }
 
-struct file_operations ax25_uid_fops = {
+const struct file_operations ax25_uid_fops = {
 	.owner = THIS_MODULE,
 	.open = ax25_uid_info_open,
 	.read = seq_read,
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index d23a27f..443a836 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -245,7 +245,7 @@
 
 	ax25_dir_table[0].child = ax25_table;
 
-	ax25_table_header = register_sysctl_table(ax25_root_table, 1);
+	ax25_table_header = register_sysctl_table(ax25_root_table);
 }
 
 void ax25_unregister_sysctl(void)
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 67df99e..c7228cf 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
@@ -12,13 +12,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -119,7 +119,7 @@
 
 	read_unlock(&bt_proto_lock);
 
-	return err; 
+	return err;
 }
 
 void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
@@ -265,7 +265,7 @@
 	if (sk->sk_shutdown == SHUTDOWN_MASK)
 		mask |= POLLHUP;
 
-	if (!skb_queue_empty(&sk->sk_receive_queue) || 
+	if (!skb_queue_empty(&sk->sk_receive_queue) ||
 			(sk->sk_shutdown & RCV_SHUTDOWN))
 		mask |= POLLIN | POLLRDNORM;
 
diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h
index 0b6cd0e..a299228 100644
--- a/net/bluetooth/bnep/bnep.h
+++ b/net/bluetooth/bnep/bnep.h
@@ -1,7 +1,7 @@
 /*
   BNEP protocol definition for Linux Bluetooth stack (BlueZ).
   Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.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.
@@ -60,7 +60,7 @@
 // Extension types
 #define BNEP_EXT_CONTROL           0x00
 
-// Response messages 
+// Response messages
 #define BNEP_SUCCESS               0x00
 
 #define BNEP_CONN_INVALID_DST      0x01
@@ -81,7 +81,7 @@
 #define BNEP_CONNECT_TO  15
 #define BNEP_FILTER_TO   15
 
-// Headers 
+// Headers
 #define BNEP_TYPE_MASK	 0x7f
 #define BNEP_EXT_HEADER	 0x80
 
@@ -132,7 +132,7 @@
 struct bnep_conninfo {
 	__u32 flags;
 	__u16 role;
-	__u16 state;	
+	__u16 state;
 	__u8  dst[ETH_ALEN];
 	char  device[16];
 };
@@ -155,10 +155,10 @@
 // BNEP sessions
 struct bnep_session {
 	struct list_head list;
-	
+
 	unsigned int  role;
-        unsigned long state;
-        unsigned long flags;
+	unsigned long state;
+	unsigned long flags;
 	atomic_t      killed;
 
 	struct ethhdr eh;
@@ -166,7 +166,7 @@
 
 	struct bnep_proto_filter proto_filter[BNEP_MAX_PROTO_FILTERS];
 	u64    mc_filter;
-	
+
 	struct socket    *sock;
 	struct net_device *dev;
 	struct net_device_stats stats;
@@ -178,7 +178,7 @@
 
 static inline int bnep_mc_hash(__u8 *addr)
 {
-        return (crc32_be(~0, addr, ETH_ALEN) >> 26);
+	return (crc32_be(~0, addr, ETH_ALEN) >> 26);
 }
 
 #endif
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 7ba6470..b85d149 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BNEP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2001-2002 Inventel Systemes
    Written 2001-2002 by
@@ -15,19 +15,19 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
 /*
  * $Id: core.c,v 1.20 2002/08/04 21:23:58 maxk Exp $
- */ 
+ */
 
 #include <linux/module.h>
 
@@ -74,7 +74,7 @@
 	BT_DBG("");
 
 	list_for_each(p, &bnep_session_list) {
-		s = list_entry(p, struct bnep_session, list);	
+		s = list_entry(p, struct bnep_session, list);
 		if (!compare_ether_addr(dst, s->eh.h_source))
 			return s;
 	}
@@ -87,7 +87,7 @@
 	   by the socket layer which has to hold the refference to this module.
 	 */
 	__module_get(THIS_MODULE);
-	list_add(&s->list, &bnep_session_list);	
+	list_add(&s->list, &bnep_session_list);
 }
 
 static void __bnep_unlink_session(struct bnep_session *s)
@@ -203,7 +203,7 @@
 
 			memcpy(a1, data, ETH_ALEN); data += ETH_ALEN;
 			a2 = data; data += ETH_ALEN;
-	
+
 			BT_DBG("mc filter %s -> %s",
 				batostr((void *) a1), batostr((void *) a2));
 
@@ -277,7 +277,7 @@
 		}
 
 		BT_DBG("type 0x%x len %d", h->type, h->len);
-	
+
 		switch (h->type & BNEP_TYPE_MASK) {
 		case BNEP_EXT_CONTROL:
 			bnep_rx_control(s, skb->data, skb->len);
@@ -293,7 +293,7 @@
 			break;
 		}
 	} while (!err && (h->type & BNEP_EXT_HEADER));
-	
+
 	return err;
 }
 
@@ -319,7 +319,7 @@
 
 	if ((type & BNEP_TYPE_MASK) > BNEP_RX_TYPES)
 		goto badframe;
-	
+
 	if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
 		bnep_rx_control(s, skb->data, skb->len);
 		kfree_skb(skb);
@@ -345,7 +345,7 @@
 			goto badframe;
 		s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
 	}
-	
+
 	/* We have to alloc new skb and copy data here :(. Because original skb
 	 * may not be modified and because of the alignment requirements. */
 	nskb = alloc_skb(2 + ETH_HLEN + skb->len, GFP_KERNEL);
@@ -361,7 +361,7 @@
 	case BNEP_COMPRESSED:
 		memcpy(__skb_put(nskb, ETH_HLEN), &s->eh, ETH_HLEN);
 		break;
-	
+
 	case BNEP_COMPRESSED_SRC_ONLY:
 		memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN);
 		memcpy(__skb_put(nskb, ETH_ALEN), skb->mac.raw, ETH_ALEN);
@@ -381,7 +381,7 @@
 
 	memcpy(__skb_put(nskb, skb->len), skb->data, skb->len);
 	kfree_skb(skb);
-	
+
 	s->stats.rx_packets++;
 	nskb->dev       = dev;
 	nskb->ip_summed = CHECKSUM_NONE;
@@ -435,7 +435,7 @@
 		iv[il++] = (struct kvec) { eh->h_source, ETH_ALEN };
 		len += ETH_ALEN;
 		break;
-		
+
 	case BNEP_COMPRESSED_DST_ONLY:
 		iv[il++] = (struct kvec) { eh->h_dest, ETH_ALEN };
 		len += ETH_ALEN;
@@ -445,7 +445,7 @@
 send:
 	iv[il++] = (struct kvec) { skb->data, skb->len };
 	len += skb->len;
-	
+
 	/* FIXME: linearize skb */
 	{
 		len = kernel_sendmsg(sock, &s->msg, iv, il, len);
@@ -471,7 +471,7 @@
 
 	BT_DBG("");
 
-        daemonize("kbnepd %s", dev->name);
+	daemonize("kbnepd %s", dev->name);
 	set_user_nice(current, -15);
 	current->flags |= PF_NOFREEZE;
 
@@ -488,13 +488,13 @@
 
 		if (sk->sk_state != BT_CONNECTED)
 			break;
-	
+
 		// TX
 		while ((skb = skb_dequeue(&sk->sk_write_queue)))
 			if (bnep_tx_frame(s, skb))
 				break;
 		netif_wake_queue(dev);
-	
+
 		schedule();
 	}
 	set_current_state(TASK_RUNNING);
@@ -573,7 +573,7 @@
 	s->sock  = sock;
 	s->role  = req->role;
 	s->state = BT_CONNECTED;
-	
+
 	s->msg.msg_flags = MSG_NOSIGNAL;
 
 #ifdef CONFIG_BT_BNEP_MC_FILTER
@@ -594,7 +594,7 @@
 	}
 
 	__bnep_link_session(s);
-	
+
 	err = kernel_thread(bnep_session, s, CLONE_KERNEL);
 	if (err < 0) {
 		/* Session thread start failed, gotta cleanup. */
@@ -627,7 +627,7 @@
 		/* Wakeup user-space which is polling for socket errors.
 		 * This is temporary hack untill we have shutdown in L2CAP */
 		s->sock->sk->sk_err = EUNATCH;
-		
+
 		/* Kill session thread */
 		atomic_inc(&s->killed);
 		wake_up_interruptible(s->sock->sk->sk_sleep);
@@ -661,7 +661,7 @@
 		s = list_entry(p, struct bnep_session, list);
 
 		__bnep_copy_ci(&ci, s);
-		
+
 		if (copy_to_user(req->ci, &ci, sizeof(ci))) {
 			err = -EFAULT;
 			break;
@@ -696,7 +696,7 @@
 }
 
 static int __init bnep_init(void)
-{	
+{
 	char flt[50] = "";
 
 	l2cap_load();
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index 67a002a..9092816 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BNEP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2001-2002 Inventel Systemes
    Written 2001-2002 by
@@ -15,19 +15,19 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
 /*
  * $Id: netdev.c,v 1.8 2002/08/04 21:23:58 maxk Exp $
- */ 
+ */
 
 #include <linux/module.h>
 
@@ -94,7 +94,7 @@
 	r->type = BNEP_CONTROL;
 	r->ctrl = BNEP_FILTER_MULTI_ADDR_SET;
 
-        if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
+	if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
 		u8 start[ETH_ALEN] = { 0x01 };
 
 		/* Request all addresses */
@@ -102,14 +102,14 @@
 		memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN);
 		r->len = htons(ETH_ALEN * 2);
 	} else {
-                struct dev_mc_list *dmi = dev->mc_list;
+		struct dev_mc_list *dmi = dev->mc_list;
 		int i, len = skb->len;
 
 		if (dev->flags & IFF_BROADCAST) {
 			memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN);
 			memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN);
-		}	
-		
+		}
+
 		/* FIXME: We should group addresses here. */
 
 		for (i = 0; i < dev->mc_count && i < BNEP_MAX_MULTICAST_FILTERS; i++) {
@@ -159,13 +159,13 @@
 {
 	struct ethhdr *eh = (void *) skb->data;
 	u16 proto = ntohs(eh->h_proto);
-	
+
 	if (proto >= 1536)
 		return proto;
-		
+
 	if (get_unaligned((__be16 *) skb->data) == htons(0xFFFF))
 		return ETH_P_802_3;
-		
+
 	return ETH_P_802_2;
 }
 
@@ -174,7 +174,7 @@
 	u16 proto = bnep_net_eth_proto(skb);
 	struct bnep_proto_filter *f = s->proto_filter;
 	int i;
-	
+
 	for (i = 0; i < BNEP_MAX_PROTO_FILTERS && f[i].end; i++) {
 		if (proto >= f[i].start && proto <= f[i].end)
 			return 0;
@@ -198,14 +198,14 @@
 		return 0;
 	}
 #endif
-	
+
 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
 	if (bnep_net_proto_filter(skb, s)) {
 		kfree_skb(skb);
 		return 0;
 	}
 #endif
-	
+
 	/*
 	 * We cannot send L2CAP packets from here as we are potentially in a bh.
 	 * So we have to queue them and wake up session thread which is sleeping
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 5563db1..10292e7 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BNEP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2001-2002 Inventel Systemes
    Written 2001-2002 by
@@ -14,19 +14,19 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
 /*
  * $Id: sock.c,v 1.4 2002/08/04 21:23:58 maxk Exp $
- */ 
+ */
 
 #include <linux/module.h>
 
@@ -34,7 +34,6 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
@@ -89,7 +88,7 @@
 
 		if (copy_from_user(&ca, argp, sizeof(ca)))
 			return -EFAULT;
-	
+
 		nsock = sockfd_lookup(ca.sock, &err);
 		if (!nsock)
 			return err;
@@ -101,20 +100,20 @@
 
 		err = bnep_add_connection(&ca, nsock);
 		if (!err) {
-    			if (copy_to_user(argp, &ca, sizeof(ca)))
+			if (copy_to_user(argp, &ca, sizeof(ca)))
 				err = -EFAULT;
 		} else
 			fput(nsock->file);
 
 		return err;
-	
+
 	case BNEPCONNDEL:
 		if (!capable(CAP_NET_ADMIN))
 			return -EACCES;
 
 		if (copy_from_user(&cd, argp, sizeof(cd)))
 			return -EFAULT;
-	
+
 		return bnep_del_connection(&cd);
 
 	case BNEPGETCONNLIST:
@@ -123,7 +122,7 @@
 
 		if (cl.cnum <= 0)
 			return -EINVAL;
-	
+
 		err = bnep_get_connlist(&cl);
 		if (!err && copy_to_user(argp, &cl, sizeof(cl)))
 			return -EFAULT;
@@ -163,7 +162,7 @@
 
 		if (cl.cnum <= 0)
 			return -EINVAL;
-	
+
 		err = bnep_get_connlist(&cl);
 
 		if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index ab166b4..3e9d5bb 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -1,4 +1,4 @@
-/* 
+/*
    CMTP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
 
@@ -10,13 +10,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -563,7 +563,7 @@
 
 	ret = wait_event_interruptible_timeout(session->wait,
 			session->ncontroller, CMTP_INTEROP_TIMEOUT);
-	
+
 	BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
 
 	if (!ret)
diff --git a/net/bluetooth/cmtp/cmtp.h b/net/bluetooth/cmtp/cmtp.h
index 40e3dfe..e4663aa 100644
--- a/net/bluetooth/cmtp/cmtp.h
+++ b/net/bluetooth/cmtp/cmtp.h
@@ -1,4 +1,4 @@
-/* 
+/*
    CMTP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
 
@@ -10,13 +10,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index b81a01c..3933608 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -1,4 +1,4 @@
-/* 
+/*
    CMTP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
 
@@ -10,13 +10,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -336,7 +336,7 @@
 	baswap(&dst, &bt_sk(sock->sk)->dst);
 
 	session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL);
-	if (!session) 
+	if (!session)
 		return -ENOMEM;
 
 	down_write(&cmtp_session_sem);
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index 53295d3..19be786 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -1,4 +1,4 @@
-/* 
+/*
    CMTP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
 
@@ -10,13 +10,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -26,7 +26,6 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
@@ -154,7 +153,7 @@
 
 		if (cl.cnum <= 0)
 			return -EINVAL;
-	
+
 		err = cmtp_get_connlist(&cl);
 
 		if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 6cd5711..f3403fd 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
@@ -12,13 +12,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -29,7 +29,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
@@ -146,7 +145,7 @@
 	case BT_CONNECT:
 		hci_acl_connect_cancel(conn);
 		break;
- 	case BT_CONNECTED:
+	case BT_CONNECTED:
 		hci_acl_disconn(conn, 0x13);
 		break;
 	default:
@@ -272,7 +271,7 @@
 		if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
 			continue;
 
-		/* Simple routing: 
+		/* Simple routing:
 		 *   No source address - find interface with bdaddr != dst
 		 *   Source address    - find interface with bdaddr == src
 		 */
@@ -328,7 +327,7 @@
 
 		hci_conn_hold(sco);
 
-		if (acl->state == BT_CONNECTED && 
+		if (acl->state == BT_CONNECTED &&
 				(sco->state == BT_OPEN || sco->state == BT_CLOSED))
 			hci_add_sco(sco, acl->handle);
 
@@ -370,7 +369,7 @@
 	if (hci_conn_auth(conn)) {
 		struct hci_cp_set_conn_encrypt cp;
 		cp.handle  = __cpu_to_le16(conn->handle);
-		cp.encrypt = 1; 
+		cp.encrypt = 1;
 		hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT, sizeof(cp), &cp);
 	}
 	return 0;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 338ae97..4917919 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
@@ -12,13 +12,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -116,7 +116,7 @@
 }
 
 /* Execute request and wait for completion. */
-static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt), 
+static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt),
 				unsigned long opt, __u32 timeout)
 {
 	DECLARE_WAITQUEUE(wait, current);
@@ -278,7 +278,7 @@
 	hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_ENCRYPT_MODE, 1, &encrypt);
 }
 
-/* Get HCI device by index. 
+/* Get HCI device by index.
  * Device is held on return. */
 struct hci_dev *hci_dev_get(int index)
 {
@@ -405,7 +405,7 @@
 		return -ENODEV;
 
 	hci_dev_lock_bh(hdev);
-	if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || 
+	if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
 					inquiry_cache_empty(hdev) ||
 					ir.flags & IREQ_CACHE_FLUSH) {
 		inquiry_cache_flush(hdev);
@@ -439,7 +439,7 @@
 		if (copy_to_user(ptr, buf, sizeof(struct inquiry_info) *
 					ir.num_rsp))
 			err = -EFAULT;
-	} else 
+	} else
 		err = -EFAULT;
 
 	kfree(buf);
@@ -491,7 +491,7 @@
 		hci_dev_hold(hdev);
 		set_bit(HCI_UP, &hdev->flags);
 		hci_notify(hdev, HCI_DEV_UP);
-	} else {	
+	} else {
 		/* Init failed, cleanup */
 		tasklet_kill(&hdev->rx_task);
 		tasklet_kill(&hdev->tx_task);
@@ -619,7 +619,7 @@
 	if (hdev->flush)
 		hdev->flush(hdev);
 
-	atomic_set(&hdev->cmd_cnt, 1); 
+	atomic_set(&hdev->cmd_cnt, 1);
 	hdev->acl_cnt = 0; hdev->sco_cnt = 0;
 
 	if (!test_bit(HCI_RAW, &hdev->flags))
@@ -841,7 +841,7 @@
 			break;
 		head = p; id++;
 	}
-	
+
 	sprintf(hdev->name, "hci%d", id);
 	hdev->id = id;
 	list_add(&hdev->list, head);
@@ -1109,7 +1109,7 @@
 		__skb_queue_tail(&conn->data_q, skb);
 		do {
 			skb = list; list = list->next;
-			
+
 			skb->dev = (void *) hdev;
 			bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
 			hci_add_acl_hdr(skb, conn->handle, flags | ACL_CONT);
@@ -1164,7 +1164,7 @@
 	int num = 0, min = ~0;
 	struct list_head *p;
 
-	/* We don't have to lock device here. Connections are always 
+	/* We don't have to lock device here. Connections are always
 	 * added and removed with TX task disabled. */
 	list_for_each(p, &h->list) {
 		struct hci_conn *c;
@@ -1306,7 +1306,7 @@
 	hci_dev_lock(hdev);
 	conn = hci_conn_hash_lookup_handle(hdev, handle);
 	hci_dev_unlock(hdev);
-	
+
 	if (conn) {
 		register struct hci_proto *hp;
 
@@ -1318,7 +1318,7 @@
 			return;
 		}
 	} else {
-		BT_ERR("%s ACL packet for unknown connection handle %d", 
+		BT_ERR("%s ACL packet for unknown connection handle %d",
 			hdev->name, handle);
 	}
 
@@ -1353,7 +1353,7 @@
 			return;
 		}
 	} else {
-		BT_ERR("%s SCO packet for unknown connection handle %d", 
+		BT_ERR("%s SCO packet for unknown connection handle %d",
 			hdev->name, handle);
 	}
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index bb94e6d..936d3fc 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
@@ -12,13 +12,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -29,7 +29,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
@@ -100,7 +99,7 @@
 	BT_DBG("%s ocf 0x%x", hdev->name, ocf);
 
 	switch (ocf) {
-	case OCF_ROLE_DISCOVERY: 
+	case OCF_ROLE_DISCOVERY:
 		rd = (void *) skb->data;
 
 		if (rd->status)
@@ -141,7 +140,7 @@
 		break;
 
 	default:
-		BT_DBG("%s: Command complete: ogf LINK_POLICY ocf %x", 
+		BT_DBG("%s: Command complete: ogf LINK_POLICY ocf %x",
 				hdev->name, ocf);
 		break;
 	}
@@ -237,10 +236,10 @@
 		if (!status) {
 			clear_bit(HCI_PSCAN, &hdev->flags);
 			clear_bit(HCI_ISCAN, &hdev->flags);
-			if (param & SCAN_INQUIRY) 
+			if (param & SCAN_INQUIRY)
 				set_bit(HCI_ISCAN, &hdev->flags);
 
-			if (param & SCAN_PAGE) 
+			if (param & SCAN_PAGE)
 				set_bit(HCI_PSCAN, &hdev->flags);
 		}
 		hci_req_complete(hdev, status);
@@ -343,7 +342,7 @@
 
 		memcpy(hdev->features, lf->features, sizeof(hdev->features));
 
-		/* Adjust default settings according to features 
+		/* Adjust default settings according to features
 		 * supported by device. */
 		if (hdev->features[0] & LMP_3SLOT)
 			hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
@@ -491,7 +490,7 @@
 		break;
 
 	default:
-		BT_DBG("%s Command status: ogf LINK_CTL ocf %x status %d", 
+		BT_DBG("%s Command status: ogf LINK_CTL ocf %x status %d",
 			hdev->name, ocf, status);
 		break;
 	}
@@ -793,7 +792,7 @@
 		if (!conn->out) {
 			struct hci_cp_change_conn_ptype cp;
 			cp.handle = ev->handle;
-			cp.pkt_type = (conn->type == ACL_LINK) ? 
+			cp.pkt_type = (conn->type == ACL_LINK) ?
 				__cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK):
 				__cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
 
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index dbf98c4..f928d2b 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
@@ -12,13 +12,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -30,7 +30,6 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
@@ -170,7 +169,7 @@
 	return 0;
 }
 
-/* Ioctls that require bound socket */ 
+/* Ioctls that require bound socket */
 static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
 {
 	struct hci_dev *hdev = hci_pi(sk)->hdev;
@@ -348,8 +347,8 @@
 		put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, sizeof(tv), &tv);
 	}
 }
- 
-static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, 
+
+static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 				struct msghdr *msg, size_t len, int flags)
 {
 	int noblock = flags & MSG_DONTWAIT;
@@ -386,7 +385,7 @@
 	return err ? : copied;
 }
 
-static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, 
+static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 			    struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
@@ -520,7 +519,7 @@
 			*((u32 *) f->event_mask + 0) = uf.event_mask[0];
 			*((u32 *) f->event_mask + 1) = uf.event_mask[1];
 		}
-		break; 
+		break;
 
 	default:
 		err = -ENOPROTOOPT;
@@ -535,7 +534,7 @@
 {
 	struct hci_ufilter uf;
 	struct sock *sk = sock->sk;
-	int len, opt; 
+	int len, opt;
 
 	if (get_user(len, optlen))
 		return -EFAULT;
@@ -544,7 +543,7 @@
 	case HCI_DATA_DIR:
 		if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
 			opt = 1;
-		else 
+		else
 			opt = 0;
 
 		if (put_user(opt, optval))
@@ -554,7 +553,7 @@
 	case HCI_TIME_STAMP:
 		if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
 			opt = 1;
-		else 
+		else
 			opt = 0;
 
 		if (put_user(opt, optval))
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 6678201..4b99c5e 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -1,4 +1,4 @@
-/* 
+/*
    HIDP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
 
@@ -10,13 +10,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -293,7 +293,7 @@
 
 	case HIDP_HSHK_ERR_FATAL:
 		/* Device requests a reboot, as this is the only way this error
- 		 * can be recovered. */
+		 * can be recovered. */
 		__hidp_send_ctrl_message(session,
 			HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
 		break;
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index c2775f5..a326601 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -1,4 +1,4 @@
-/* 
+/*
    HIDP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
 
@@ -10,13 +10,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -86,7 +86,7 @@
 	int   intr_sock;	// Connteted interrupt socket
 	__u16 parser;
 	__u16 rd_size;
-	__u8 *rd_data;
+	__u8 __user *rd_data;
 	__u8  country;
 	__u8  subclass;
 	__u16 vendor;
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 407fba4..8b8a6c1 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -1,4 +1,4 @@
-/* 
+/*
    HIDP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
 
@@ -10,13 +10,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -26,7 +26,6 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
@@ -189,7 +188,7 @@
 
 		uca = compat_alloc_user_space(sizeof(*uca));
 
-		if (copy_from_user(&ca, (void *) arg, sizeof(ca)))
+		if (copy_from_user(&ca, (void __user *) arg, sizeof(ca)))
 			return -EFAULT;
 
 		if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
@@ -206,7 +205,7 @@
 				put_user(ca.idle_to, &uca->idle_to) ||
 				copy_to_user(&uca->name[0], &ca.name[0], 128))
 			return -EFAULT;
-		
+
 		arg = (unsigned long) uca;
 
 		/* Fall through. We don't actually write back any _changes_
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index f8c25d5..e83ee82 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
@@ -12,13 +12,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -227,7 +227,7 @@
 		bt_accept_enqueue(parent, sk);
 }
 
-/* Delete channel. 
+/* Delete channel.
  * Must be called on the locked socket. */
 static void l2cap_chan_del(struct sock *sk, int err)
 {
@@ -238,7 +238,7 @@
 
 	BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
 
-	if (conn) { 
+	if (conn) {
 		/* Unlink from channel list */
 		l2cap_chan_unlink(&conn->chan_list, sk);
 		l2cap_pi(sk)->conn = NULL;
@@ -590,7 +590,7 @@
 		err = -EACCES;
 		goto done;
 	}
-		
+
 	write_lock_bh(&l2cap_sk_list.lock);
 
 	if (la->l2_psm && __l2cap_get_sock_by_addr(la->l2_psm, &la->l2_bdaddr)) {
@@ -890,7 +890,7 @@
 		*frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
 		if (!*frag)
 			goto fail;
-		
+
 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) {
 			err = -EFAULT;
 			goto fail;
@@ -1267,7 +1267,7 @@
 
 static inline void l2cap_parse_conf_req(struct sock *sk, void *data, int len)
 {
-	int type, hint, olen; 
+	int type, hint, olen;
 	unsigned long val;
 	void *ptr = data;
 
@@ -1414,7 +1414,7 @@
 
 	/* Check for backlog size */
 	if (sk_acceptq_is_full(parent)) {
-		BT_DBG("backlog full %d", parent->sk_ack_backlog); 
+		BT_DBG("backlog full %d", parent->sk_ack_backlog);
 		goto response;
 	}
 
@@ -1607,7 +1607,7 @@
 			goto done;
 		}
 
-	default: 
+	default:
 		sk->sk_state = BT_DISCONN;
 		sk->sk_err   = ECONNRESET;
 		l2cap_sock_set_timer(sk, HZ * 5);
diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c
index e5fd0cb..ad2af58 100644
--- a/net/bluetooth/lib.c
+++ b/net/bluetooth/lib.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
@@ -12,13 +12,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 278c867..94f4573 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -1,4 +1,4 @@
-/* 
+/*
    RFCOMM implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
    Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
@@ -11,13 +11,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -134,7 +134,7 @@
 /* ---- RFCOMM FCS computation ---- */
 
 /* reversed, 8-bit, poly=0x07 */
-static unsigned char rfcomm_crc_table[256] = { 
+static unsigned char rfcomm_crc_table[256] = {
 	0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
 	0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
 	0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
@@ -179,13 +179,13 @@
 /* CRC on 2 bytes */
 #define __crc(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]])
 
-/* FCS on 2 bytes */ 
+/* FCS on 2 bytes */
 static inline u8 __fcs(u8 *data)
 {
 	return (0xff - __crc(data));
 }
 
-/* FCS on 3 bytes */ 
+/* FCS on 3 bytes */
 static inline u8 __fcs2(u8 *data)
 {
 	return (0xff - rfcomm_crc_table[__crc(data) ^ data[2]]);
@@ -288,7 +288,7 @@
 	atomic_set(&d->refcnt, 1);
 
 	rfcomm_dlc_clear_state(d);
-	
+
 	BT_DBG("%p", d);
 
 	return d;
@@ -345,7 +345,7 @@
 	int err = 0;
 	u8 dlci;
 
-	BT_DBG("dlc %p state %ld %s %s channel %d", 
+	BT_DBG("dlc %p state %ld %s %s channel %d",
 			d, d->state, batostr(src), batostr(dst), channel);
 
 	if (channel < 1 || channel > 30)
@@ -489,21 +489,21 @@
 	rfcomm_schedule(RFCOMM_SCHED_TX);
 }
 
-/* 
+/*
    Set/get modem status functions use _local_ status i.e. what we report
    to the other side.
    Remote status is provided by dlc->modem_status() callback.
  */
 int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig)
 {
-	BT_DBG("dlc %p state %ld v24_sig 0x%x", 
+	BT_DBG("dlc %p state %ld v24_sig 0x%x",
 			d, d->state, v24_sig);
 
 	if (test_bit(RFCOMM_RX_THROTTLED, &d->flags))
 		v24_sig |= RFCOMM_V24_FC;
 	else
 		v24_sig &= ~RFCOMM_V24_FC;
-	
+
 	d->v24_sig = v24_sig;
 
 	if (!test_and_set_bit(RFCOMM_MSC_PENDING, &d->flags))
@@ -514,7 +514,7 @@
 
 int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig)
 {
-	BT_DBG("dlc %p state %ld v24_sig 0x%x", 
+	BT_DBG("dlc %p state %ld v24_sig 0x%x",
 			d, d->state, d->v24_sig);
 
 	*v24_sig = d->v24_sig;
@@ -576,7 +576,7 @@
 	struct bt_sock *sk;
 	list_for_each_safe(p, n, &session_list) {
 		s = list_entry(p, struct rfcomm_session, list);
-		sk = bt_sk(s->sock->sk); 
+		sk = bt_sk(s->sock->sk);
 
 		if ((!bacmp(src, BDADDR_ANY) || !bacmp(&sk->src, src)) &&
 				!bacmp(&sk->dst, dst))
@@ -825,7 +825,7 @@
 
 int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
 			u8 bit_rate, u8 data_bits, u8 stop_bits,
-			u8 parity, u8 flow_ctrl_settings, 
+			u8 parity, u8 flow_ctrl_settings,
 			u8 xon_char, u8 xoff_char, u16 param_mask)
 {
 	struct rfcomm_hdr *hdr;
@@ -834,8 +834,8 @@
 	u8 buf[16], *ptr = buf;
 
 	BT_DBG("%p cr %d dlci %d bit_r 0x%x data_b 0x%x stop_b 0x%x parity 0x%x"
-			" flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x", 
-		s, cr, dlci, bit_rate, data_bits, stop_bits, parity, 
+			" flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x",
+		s, cr, dlci, bit_rate, data_bits, stop_bits, parity,
 		flow_ctrl_settings, xon_char, xoff_char, param_mask);
 
 	hdr = (void *) ptr; ptr += sizeof(*hdr);
@@ -1120,9 +1120,9 @@
 
 			d->state = BT_CLOSED;
 			__rfcomm_dlc_close(d, err);
-		} else 
+		} else
 			rfcomm_send_dm(s, dlci);
-			
+
 	} else {
 		rfcomm_send_ua(s, 0);
 
@@ -1230,7 +1230,7 @@
 {
 	struct rfcomm_session *s = d->session;
 
-	BT_DBG("dlc %p state %ld dlci %d mtu %d fc 0x%x credits %d", 
+	BT_DBG("dlc %p state %ld dlci %d mtu %d fc 0x%x credits %d",
 			d, d->state, d->dlci, pn->mtu, pn->flow_ctrl, pn->credits);
 
 	if ((pn->flow_ctrl == 0xf0 && s->cfc != RFCOMM_CFC_DISABLED) ||
@@ -1454,7 +1454,7 @@
 		if (d->modem_status)
 			d->modem_status(d, msc->v24_sig);
 		rfcomm_dlc_unlock(d);
-		
+
 		rfcomm_send_msc(s, 0, dlci, msc->v24_sig);
 
 		d->mscex |= RFCOMM_MSCEX_RX;
@@ -1641,18 +1641,18 @@
 	struct sk_buff *skb;
 	int err;
 
-	BT_DBG("dlc %p state %ld cfc %d rx_credits %d tx_credits %d", 
+	BT_DBG("dlc %p state %ld cfc %d rx_credits %d tx_credits %d",
 			d, d->state, d->cfc, d->rx_credits, d->tx_credits);
 
 	/* Send pending MSC */
 	if (test_and_clear_bit(RFCOMM_MSC_PENDING, &d->flags))
-		rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig); 
+		rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
 
 	if (d->cfc) {
-		/* CFC enabled. 
+		/* CFC enabled.
 		 * Give them some credits */
 		if (!test_bit(RFCOMM_RX_THROTTLED, &d->flags) &&
-			       	d->rx_credits <= (d->cfc >> 2)) {
+				d->rx_credits <= (d->cfc >> 2)) {
 			rfcomm_send_credits(d->session, d->addr, d->cfc - d->rx_credits);
 			d->rx_credits = d->cfc;
 		}
@@ -1876,7 +1876,7 @@
 
 	/* Create socket */
 	err = rfcomm_l2sock_create(&sock);
-	if (err < 0) { 
+	if (err < 0) {
 		BT_ERR("Create socket failed %d", err);
 		return err;
 	}
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index cb7e855..30586ab 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -1,4 +1,4 @@
-/* 
+/*
    RFCOMM implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
    Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
@@ -11,13 +11,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -130,7 +130,7 @@
 	struct hlist_node *node;
 
 	sk_for_each(sk, node, &rfcomm_sk_list.head) {
-		if (rfcomm_pi(sk)->channel == channel && 
+		if (rfcomm_pi(sk)->channel == channel &&
 				!bacmp(&bt_sk(sk)->src, src))
 			break;
 	}
@@ -572,7 +572,7 @@
 	while (len) {
 		size_t size = min_t(size_t, len, d->mtu);
 		int err;
-		
+
 		skb = sock_alloc_send_skb(sk, size + RFCOMM_SKB_RESERVE,
 				msg->msg_flags & MSG_DONTWAIT, &err);
 		if (!skb)
@@ -843,7 +843,7 @@
 	return err;
 }
 
-/* ---- RFCOMM core layer callbacks ---- 
+/* ---- RFCOMM core layer callbacks ----
  *
  * called under rfcomm_lock()
  */
@@ -864,7 +864,7 @@
 
 	/* Check for backlog size */
 	if (sk_acceptq_is_full(parent)) {
-		BT_DBG("backlog full %d", parent->sk_ack_backlog); 
+		BT_DBG("backlog full %d", parent->sk_ack_backlog);
 		goto done;
 	}
 
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index eb2b524..8cd82dc 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -1,4 +1,4 @@
-/* 
+/*
    RFCOMM implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
    Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
@@ -11,13 +11,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -110,7 +110,7 @@
 
 	kfree(dev);
 
-	/* It's safe to call module_put() here because socket still 
+	/* It's safe to call module_put() here because socket still
 	   holds reference to this module. */
 	module_put(THIS_MODULE);
 }
@@ -185,7 +185,7 @@
 	int err = 0;
 
 	BT_DBG("id %d channel %d", req->dev_id, req->channel);
-	
+
 	dev = kzalloc(sizeof(struct rfcomm_dev), GFP_KERNEL);
 	if (!dev)
 		return -ENOMEM;
@@ -234,7 +234,7 @@
 	bacpy(&dev->dst, &req->dst);
 	dev->channel = req->channel;
 
-	dev->flags = req->flags & 
+	dev->flags = req->flags &
 		((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
 
 	init_waitqueue_head(&dev->wait);
@@ -249,7 +249,7 @@
 	dev->dlc   = dlc;
 	rfcomm_dlc_unlock(dlc);
 
-	/* It's safe to call __module_get() here because socket already 
+	/* It's safe to call __module_get() here because socket already
 	   holds reference to this module. */
 	__module_get(THIS_MODULE);
 
@@ -487,7 +487,7 @@
 {
 	struct rfcomm_dev *dev = dlc->owner;
 	struct tty_struct *tty;
-       
+
 	if (!dev || !(tty = dev->tty)) {
 		kfree_skb(skb);
 		return;
@@ -506,7 +506,7 @@
 	struct rfcomm_dev *dev = dlc->owner;
 	if (!dev)
 		return;
-	
+
 	BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
 
 	dev->err = err;
@@ -525,7 +525,7 @@
 				rfcomm_dev_put(dev);
 				rfcomm_dlc_lock(dlc);
 			}
-		} else 
+		} else
 			tty_hangup(dev->tty);
 	}
 }
@@ -543,7 +543,7 @@
 			tty_hangup(dev->tty);
 	}
 
-	dev->modem_status = 
+	dev->modem_status =
 		((v24_sig & RFCOMM_V24_RTC) ? (TIOCM_DSR | TIOCM_DTR) : 0) |
 		((v24_sig & RFCOMM_V24_RTR) ? (TIOCM_RTS | TIOCM_CTS) : 0) |
 		((v24_sig & RFCOMM_V24_IC)  ? TIOCM_RI : 0) |
@@ -561,7 +561,7 @@
 	BT_DBG("dev %p tty %p", dev, tty);
 
 	if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && tty->ldisc.write_wakeup)
-                (tty->ldisc.write_wakeup)(tty);
+		(tty->ldisc.write_wakeup)(tty);
 
 	wake_up_interruptible(&tty->write_wait);
 #ifdef SERIAL_HAVE_POLL_WAIT
@@ -576,7 +576,7 @@
 	struct rfcomm_dlc *dlc;
 	int err, id;
 
-        id = tty->index;
+	id = tty->index;
 
 	BT_DBG("tty %p id %d", tty, id);
 
@@ -670,7 +670,7 @@
 		size = min_t(uint, count, dlc->mtu);
 
 		skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC);
-		
+
 		if (!skb)
 			break;
 
@@ -773,7 +773,7 @@
 		return;
 
 	/* Handle turning off CRTSCTS */
-	if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS)) 
+	if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS))
 		BT_DBG("Turning off CRTSCTS unsupported");
 
 	/* Parity on/off and when on, odd/even */
@@ -830,7 +830,7 @@
 	}
 
 	/* Handle number of data bits [5-8] */
-	if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE)) 
+	if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE))
 		changes |= RFCOMM_RPN_PM_DATA;
 
 	switch (new->c_cflag & CSIZE) {
@@ -868,7 +868,7 @@
 	case 9600:
 		baud = RFCOMM_RPN_BR_9600;
 		break;
-	case 19200: 
+	case 19200:
 		baud = RFCOMM_RPN_BR_19200;
 		break;
 	case 38400:
@@ -887,7 +887,7 @@
 		/* 9600 is standard accordinag to the RFCOMM specification */
 		baud = RFCOMM_RPN_BR_9600;
 		break;
-	
+
 	}
 
 	if (changes)
@@ -978,11 +978,11 @@
 
 static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp)
 {
- 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
+	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
 
 	BT_DBG("tty %p dev %p", tty, dev);
 
- 	return dev->modem_status;
+	return dev->modem_status;
 }
 
 static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 5d13d4f..ae43914 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -1,4 +1,4 @@
-/* 
+/*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
@@ -12,13 +12,13 @@
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -149,7 +149,7 @@
 	struct sco_conn *conn;
 	struct sock *sk;
 
-	if (!(conn = hcon->sco_data)) 
+	if (!(conn = hcon->sco_data))
 		return 0;
 
 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
@@ -404,7 +404,7 @@
 {
 	BT_DBG("sk %p", sk);
 
-	if (parent) 
+	if (parent)
 		sk->sk_type = parent->sk_type;
 }
 
@@ -522,7 +522,7 @@
 	if ((err = sco_connect(sk)))
 		goto done;
 
-	err = bt_sock_wait_state(sk, BT_CONNECTED, 
+	err = bt_sock_wait_state(sk, BT_CONNECTED,
 			sock_sndtimeo(sk, flags & O_NONBLOCK));
 
 done:
@@ -627,7 +627,7 @@
 	return 0;
 }
 
-static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, 
+static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 			    struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
@@ -677,7 +677,7 @@
 	struct sock *sk = sock->sk;
 	struct sco_options opts;
 	struct sco_conninfo cinfo;
-	int len, err = 0; 
+	int len, err = 0;
 
 	BT_DBG("sk %p", sk);
 
@@ -761,7 +761,7 @@
 		bt_accept_enqueue(parent, sk);
 }
 
-/* Delete channel. 
+/* Delete channel.
  * Must be called on the locked socket. */
 static void sco_chan_del(struct sock *sk, int err)
 {
@@ -771,7 +771,7 @@
 
 	BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
 
-	if (conn) { 
+	if (conn) {
 		sco_conn_lock(conn);
 		conn->sk = NULL;
 		sco_pi(sk)->conn = NULL;
@@ -855,7 +855,7 @@
 		conn = sco_conn_add(hcon, status);
 		if (conn)
 			sco_conn_ready(conn);
-	} else 
+	} else
 		sco_conn_del(hcon, bt_err(status));
 
 	return 0;
@@ -887,7 +887,7 @@
 	}
 
 drop:
-	kfree_skb(skb);	
+	kfree_skb(skb);
 	return 0;
 }
 
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index f8dbcee..905a39c 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -40,7 +40,7 @@
 	skb->mac.raw = skb->data;
 	skb_pull(skb, ETH_HLEN);
 
-	if (dest[0] & 1) 
+	if (dest[0] & 1)
 		br_flood_deliver(br, skb, 0);
 	else if ((dst = __br_fdb_get(br, dest)) != NULL)
 		br_deliver(dst->dst, skb);
@@ -178,12 +178,12 @@
 	dev->change_mtu = br_change_mtu;
 	dev->destructor = free_netdev;
 	SET_MODULE_OWNER(dev);
- 	SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
+	SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
 	dev->stop = br_dev_stop;
 	dev->tx_queue_len = 0;
 	dev->set_mac_address = br_set_mac_address;
 	dev->priv_flags = IFF_EBRIDGE;
 
- 	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
- 			NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST;
+	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
+			NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST;
 }
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 8ca448d..def2e40 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -52,7 +52,7 @@
 static __inline__ int has_expired(const struct net_bridge *br,
 				  const struct net_bridge_fdb_entry *fdb)
 {
-	return !fdb->is_static 
+	return !fdb->is_static
 		&& time_before_eq(fdb->ageing_timer + hold_time(br), jiffies);
 }
 
@@ -71,7 +71,7 @@
 {
 	struct net_bridge *br = p->br;
 	int i;
-	
+
 	spin_lock_bh(&br->hash_lock);
 
 	/* Search all chains since old address/hash is unknown */
@@ -85,7 +85,7 @@
 				/* maybe another port has same hw addr? */
 				struct net_bridge_port *op;
 				list_for_each_entry(op, &br->port_list, list) {
-					if (op != p && 
+					if (op != p &&
 					    !compare_ether_addr(op->dev->dev_addr,
 								f->addr.addr)) {
 						f->dst = op;
@@ -118,8 +118,8 @@
 		struct hlist_node *h, *n;
 
 		hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) {
-			if (!f->is_static && 
-			    time_before_eq(f->ageing_timer + delay, jiffies)) 
+			if (!f->is_static &&
+			    time_before_eq(f->ageing_timer + delay, jiffies))
 				fdb_delete(f);
 		}
 	}
@@ -138,11 +138,11 @@
 	spin_lock_bh(&br->hash_lock);
 	for (i = 0; i < BR_HASH_SIZE; i++) {
 		struct hlist_node *h, *g;
-		
+
 		hlist_for_each_safe(h, g, &br->hash[i]) {
 			struct net_bridge_fdb_entry *f
 				= hlist_entry(h, struct net_bridge_fdb_entry, hlist);
-			if (f->dst != p) 
+			if (f->dst != p)
 				continue;
 
 			if (f->is_static && !do_all)
@@ -155,7 +155,7 @@
 			if (f->is_local) {
 				struct net_bridge_port *op;
 				list_for_each_entry(op, &br->port_list, list) {
-					if (op != p && 
+					if (op != p &&
 					    !compare_ether_addr(op->dev->dev_addr,
 								f->addr.addr)) {
 						f->dst = op;
@@ -190,14 +190,14 @@
 }
 
 /* Interface used by ATM hook that keeps a ref count */
-struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, 
+struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
 					unsigned char *addr)
 {
 	struct net_bridge_fdb_entry *fdb;
 
 	rcu_read_lock();
 	fdb = __br_fdb_get(br, addr);
-	if (fdb) 
+	if (fdb)
 		atomic_inc(&fdb->use_count);
 	rcu_read_unlock();
 	return fdb;
@@ -218,7 +218,7 @@
 }
 
 /*
- * Fill buffer with forwarding table records in 
+ * Fill buffer with forwarding table records in
  * the API format.
  */
 int br_fdb_fillbuf(struct net_bridge *br, void *buf,
@@ -237,7 +237,7 @@
 			if (num >= maxnum)
 				goto out;
 
-			if (has_expired(br, f)) 
+			if (has_expired(br, f))
 				continue;
 
 			if (skip) {
@@ -277,7 +277,7 @@
 
 static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
 					       struct net_bridge_port *source,
-					       const unsigned char *addr, 
+					       const unsigned char *addr,
 					       int is_local)
 {
 	struct net_bridge_fdb_entry *fdb;
@@ -307,17 +307,17 @@
 
 	fdb = fdb_find(head, addr);
 	if (fdb) {
-		/* it is okay to have multiple ports with same 
+		/* it is okay to have multiple ports with same
 		 * address, just use the first one.
 		 */
-		if (fdb->is_local) 
+		if (fdb->is_local)
 			return 0;
 
 		printk(KERN_WARNING "%s adding interface with same address "
 		       "as a received packet\n",
 		       source->dev->name);
 		fdb_delete(fdb);
- 	}
+	}
 
 	if (!fdb_create(head, source, addr, 1))
 		return -ENOMEM;
@@ -350,7 +350,7 @@
 	if (likely(fdb)) {
 		/* attempt to update an entry for a local interface */
 		if (unlikely(fdb->is_local)) {
-			if (net_ratelimit()) 
+			if (net_ratelimit())
 				printk(KERN_WARNING "%s: received packet with "
 				       " own address as source address\n",
 				       source->dev->name);
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 191b861..3e45c1a 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -21,7 +21,7 @@
 #include "br_private.h"
 
 /* Don't forward packets to originating port or forwarding diasabled */
-static inline int should_deliver(const struct net_bridge_port *p, 
+static inline int should_deliver(const struct net_bridge_port *p,
 				 const struct sk_buff *skb)
 {
 	return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING);
@@ -101,7 +101,7 @@
 
 /* called under bridge lock */
 static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
-	void (*__packet_hook)(const struct net_bridge_port *p, 
+	void (*__packet_hook)(const struct net_bridge_port *p,
 			      struct sk_buff *skb))
 {
 	struct net_bridge_port *p;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 2b7c2c7..aff6a77 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -47,7 +47,7 @@
 	set_fs(KERNEL_DS);
 	err = dev_ethtool(&ifr);
 	set_fs(old_fs);
-	
+
 	if (!err) {
 		switch(ecmd.speed) {
 		case SPEED_100:
@@ -108,6 +108,7 @@
 		spin_unlock_bh(&br->lock);
 	}
 done:
+	dev_put(dev);
 	rtnl_unlock();
 }
 
@@ -161,7 +162,8 @@
 
 	dev_set_promiscuity(dev, -1);
 
-	cancel_delayed_work(&p->carrier_check);
+	if (cancel_delayed_work(&p->carrier_check))
+		dev_put(dev);
 
 	spin_lock_bh(&br->lock);
 	br_stp_disable_port(p);
@@ -191,7 +193,7 @@
 	del_timer_sync(&br->gc_timer);
 
 	br_sysfs_delbr(br->dev);
- 	unregister_netdevice(br->dev);
+	unregister_netdevice(br->dev);
 }
 
 static struct net_device *new_bridge_dev(const char *name)
@@ -201,7 +203,7 @@
 
 	dev = alloc_netdev(sizeof(struct net_bridge), name,
 			   br_dev_setup);
-	
+
 	if (!dev)
 		return NULL;
 
@@ -258,12 +260,12 @@
 }
 
 /* called with RTNL but without bridge lock */
-static struct net_bridge_port *new_nbp(struct net_bridge *br, 
+static struct net_bridge_port *new_nbp(struct net_bridge *br,
 				       struct net_device *dev)
 {
 	int index;
 	struct net_bridge_port *p;
-	
+
 	index = find_portno(br);
 	if (index < 0)
 		return ERR_PTR(index);
@@ -276,7 +278,7 @@
 	dev_hold(dev);
 	p->dev = dev;
 	p->path_cost = port_cost(dev);
- 	p->priority = 0x8000 >> BR_PORT_BITS;
+	p->priority = 0x8000 >> BR_PORT_BITS;
 	p->port_no = index;
 	br_init_port(p);
 	p->state = BR_STATE_DISABLED;
@@ -298,7 +300,7 @@
 	int ret;
 
 	dev = new_bridge_dev(name);
-	if (!dev) 
+	if (!dev)
 		return -ENOMEM;
 
 	rtnl_lock();
@@ -329,7 +331,7 @@
 
 	rtnl_lock();
 	dev = __dev_get_by_name(name);
-	if (dev == NULL) 
+	if (dev == NULL)
 		ret =  -ENXIO; 	/* Could not find device */
 
 	else if (!(dev->priv_flags & IFF_EBRIDGE)) {
@@ -340,9 +342,9 @@
 	else if (dev->flags & IFF_UP) {
 		/* Not shutdown yet. */
 		ret = -EBUSY;
-	} 
+	}
 
-	else 
+	else
 		del_br(netdev_priv(dev));
 
 	rtnl_unlock();
@@ -428,7 +430,7 @@
 	if (err)
 		goto err0;
 
- 	err = br_fdb_insert(br, p, dev->dev_addr);
+	err = br_fdb_insert(br, p, dev->dev_addr);
 	if (err)
 		goto err1;
 
@@ -444,7 +446,9 @@
 	spin_lock_bh(&br->lock);
 	br_stp_recalculate_bridge_id(br);
 	br_features_recompute(br);
-	schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
+	if (schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE))
+		dev_hold(dev);
+
 	spin_unlock_bh(&br->lock);
 
 	dev_set_mtu(br->dev, br_min_mtu(br));
@@ -464,8 +468,8 @@
 int br_del_if(struct net_bridge *br, struct net_device *dev)
 {
 	struct net_bridge_port *p = dev->br_port;
-	
-	if (!p || p->br != br) 
+
+	if (!p || p->br != br)
 		return -EINVAL;
 
 	del_nbp(p);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index bfa4d8c..35b94f9 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -119,7 +119,7 @@
  * Called via br_handle_frame_hook.
  * Return 0 if *pskb should be processed furthur
  *	  1 if *pskb is handled
- * note: already called with rcu_read_lock (preempt_disabled) 
+ * note: already called with rcu_read_lock (preempt_disabled)
  */
 int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
 {
@@ -137,7 +137,7 @@
 
 	if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) {
 		if (br_should_route_hook) {
-			if (br_should_route_hook(pskb)) 
+			if (br_should_route_hook(pskb))
 				return 0;
 			skb = *pskb;
 			dest = eth_hdr(skb)->h_dest;
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 4c61a7e..3ab153d 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -28,7 +28,7 @@
 	int i = 0;
 
 	for (dev = dev_base; dev && i < num; dev = dev->next) {
-		if (dev->priv_flags & IFF_EBRIDGE) 
+		if (dev->priv_flags & IFF_EBRIDGE)
 			indices[i++] = dev->ifindex;
 	}
 
@@ -53,7 +53,7 @@
  *            (limited to a page for sanity)
  * offset  -- number of records to skip
  */
-static int get_fdb_entries(struct net_bridge *br, void __user *userbuf, 
+static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,
 			   unsigned long maxnum, unsigned long offset)
 {
 	int num;
@@ -69,7 +69,7 @@
 	buf = kmalloc(size, GFP_USER);
 	if (!buf)
 		return -ENOMEM;
-	
+
 	num = br_fdb_fillbuf(br, buf, maxnum, offset);
 	if (num > 0) {
 		if (copy_to_user(userbuf, buf, num*sizeof(struct __fdb_entry)))
@@ -91,7 +91,7 @@
 	dev = dev_get_by_index(ifindex);
 	if (dev == NULL)
 		return -EINVAL;
-	
+
 	if (isadd)
 		ret = br_add_if(br, dev);
 	else
@@ -110,7 +110,7 @@
 {
 	struct net_bridge *br = netdev_priv(dev);
 	unsigned long args[4];
-	
+
 	if (copy_from_user(args, rq->ifr_data, sizeof(args)))
 		return -EFAULT;
 
@@ -143,7 +143,7 @@
 		b.tcn_timer_value = br_timer_value(&br->tcn_timer);
 		b.topology_change_timer_value = br_timer_value(&br->topology_change_timer);
 		b.gc_timer_value = br_timer_value(&br->gc_timer);
-	        rcu_read_unlock();
+		rcu_read_unlock();
 
 		if (copy_to_user((void __user *)args[1], &b, sizeof(b)))
 			return -EFAULT;
@@ -275,7 +275,7 @@
 			return -ERANGE;
 
 		spin_lock_bh(&br->lock);
-		if ((p = br_get_port(br, args[1])) == NULL) 
+		if ((p = br_get_port(br, args[1])) == NULL)
 			ret = -EINVAL;
 		else
 			br_stp_set_port_priority(p, args[2]);
@@ -301,7 +301,7 @@
 	}
 
 	case BRCTL_GET_FDB_ENTRIES:
-		return get_fdb_entries(br, (void __user *)args[1], 
+		return get_fdb_entries(br, (void __user *)args[1],
 				       args[2], args[3]);
 	}
 
@@ -368,7 +368,7 @@
 	case SIOCGIFBR:
 	case SIOCSIFBR:
 		return old_deviceless(uarg);
-		
+
 	case SIOCBRADDBR:
 	case SIOCBRDELBR:
 	{
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index ea3337a..7712d76 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -68,7 +68,7 @@
 
 #define IS_VLAN_IP(skb) \
 	(skb->protocol == htons(ETH_P_8021Q) && \
- 	 vlan_proto(skb) == htons(ETH_P_IP) && 	\
+	 vlan_proto(skb) == htons(ETH_P_IP) && 	\
 	 brnf_filter_vlan_tagged)
 
 #define IS_VLAN_IPV6(skb) \
@@ -124,7 +124,7 @@
 
 static inline void nf_bridge_save_header(struct sk_buff *skb)
 {
-        int header_size = ETH_HLEN;
+	int header_size = ETH_HLEN;
 
 	if (skb->protocol == htons(ETH_P_8021Q))
 		header_size += VLAN_HLEN;
@@ -139,7 +139,7 @@
 int nf_bridge_copy_header(struct sk_buff *skb)
 {
 	int err;
-        int header_size = ETH_HLEN;
+	int header_size = ETH_HLEN;
 
 	if (skb->protocol == htons(ETH_P_8021Q))
 		header_size += VLAN_HLEN;
@@ -836,10 +836,10 @@
  * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
  * ip_refrag() can return NF_STOLEN. */
 static struct nf_hook_ops br_nf_ops[] = {
-	{ .hook = br_nf_pre_routing, 
-	  .owner = THIS_MODULE, 
-	  .pf = PF_BRIDGE, 
-	  .hooknum = NF_BR_PRE_ROUTING, 
+	{ .hook = br_nf_pre_routing,
+	  .owner = THIS_MODULE,
+	  .pf = PF_BRIDGE,
+	  .hooknum = NF_BR_PRE_ROUTING,
 	  .priority = NF_BR_PRI_BRNF, },
 	{ .hook = br_nf_local_in,
 	  .owner = THIS_MODULE,
@@ -949,44 +949,29 @@
 };
 #endif
 
-int br_netfilter_init(void)
+int __init br_netfilter_init(void)
 {
-	int i;
+	int ret;
 
-	for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) {
-		int ret;
-
-		if ((ret = nf_register_hook(&br_nf_ops[i])) >= 0)
-			continue;
-
-		while (i--)
-			nf_unregister_hook(&br_nf_ops[i]);
-
+	ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
+	if (ret < 0)
 		return ret;
-	}
-
 #ifdef CONFIG_SYSCTL
-	brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0);
+	brnf_sysctl_header = register_sysctl_table(brnf_net_table);
 	if (brnf_sysctl_header == NULL) {
 		printk(KERN_WARNING
 		       "br_netfilter: can't register to sysctl.\n");
-		for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++)
-			nf_unregister_hook(&br_nf_ops[i]);
-		return -EFAULT;
+		nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
+		return -ENOMEM;
 	}
 #endif
-
 	printk(KERN_NOTICE "Bridge firewalling registered\n");
-
 	return 0;
 }
 
 void br_netfilter_fini(void)
 {
-	int i;
-
-	for (i = ARRAY_SIZE(br_nf_ops) - 1; i >= 0; i--)
-		nf_unregister_hook(&br_nf_ops[i]);
+	nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
 #ifdef CONFIG_SYSCTL
 	unregister_sysctl_table(brnf_sysctl_header);
 #endif
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index a913968..7d68b24 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -45,7 +45,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	hdr = nlmsg_data(nlh);
 	hdr->ifi_family = AF_BRIDGE;
@@ -72,7 +72,8 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 /*
@@ -89,9 +90,12 @@
 		goto errout;
 
 	err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
-	/* failure implies BUG in br_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in br_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
 errout:
 	if (err < 0)
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index 2027849..3311c4e3 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -26,7 +26,7 @@
 
 /*
  * Handle changes in state of network devices enslaved to a bridge.
- * 
+ *
  * Note: don't care about up/down if bridge itself is down, because
  *     port state is checked when bridge is brought up.
  */
@@ -56,15 +56,17 @@
 
 	case NETDEV_CHANGE:
 		if (br->dev->flags & IFF_UP)
-			schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
+			if (schedule_delayed_work(&p->carrier_check,
+						BR_PORT_DEBOUNCE))
+				dev_hold(dev);
 		break;
 
 	case NETDEV_FEAT_CHANGE:
-		if (br->dev->flags & IFF_UP) 
+		if (br->dev->flags & IFF_UP)
 			br_features_recompute(br);
 
 		/* could do recursive feature change notification
-		 * but who would care?? 
+		 * but who would care??
 		 */
 		break;
 
@@ -74,7 +76,7 @@
 		break;
 
 	case NETDEV_UP:
-		if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) 
+		if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP))
 			br_stp_enable_port(p);
 		break;
 
@@ -82,7 +84,7 @@
 		spin_unlock_bh(&br->lock);
 		br_del_if(br, dev);
 		goto done;
-	} 
+	}
 	spin_unlock_bh(&br->lock);
 
  done:
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 3a534e9..6a0540e0 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -149,7 +149,7 @@
 extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
 					       unsigned char *addr);
 extern void br_fdb_put(struct net_bridge_fdb_entry *ent);
-extern int br_fdb_fillbuf(struct net_bridge *br, void *buf, 
+extern int br_fdb_fillbuf(struct net_bridge *br, void *buf,
 			  unsigned long count, unsigned long off);
 extern int br_fdb_insert(struct net_bridge *br,
 			 struct net_bridge_port *source,
@@ -203,7 +203,7 @@
 /* br_stp.c */
 extern void br_log_state(const struct net_bridge_port *p);
 extern struct net_bridge_port *br_get_port(struct net_bridge *br,
-				    	   u16 port_no);
+					   u16 port_no);
 extern void br_init_port(struct net_bridge_port *p);
 extern void br_become_designated_port(struct net_bridge_port *p);
 
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 04ca0639..f9ff4d5 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -24,17 +24,17 @@
 #define MESSAGE_AGE_INCR	((HZ < 256) ? 1 : (HZ/256))
 
 static const char *br_port_state_names[] = {
-	[BR_STATE_DISABLED] = "disabled", 
+	[BR_STATE_DISABLED] = "disabled",
 	[BR_STATE_LISTENING] = "listening",
-	[BR_STATE_LEARNING] = "learning", 
-	[BR_STATE_FORWARDING] = "forwarding", 
+	[BR_STATE_LEARNING] = "learning",
+	[BR_STATE_FORWARDING] = "forwarding",
 	[BR_STATE_BLOCKING] = "blocking",
 };
 
 void br_log_state(const struct net_bridge_port *p)
 {
 	pr_info("%s: port %d(%s) entering %s state\n",
-		p->br->dev->name, p->port_no, p->dev->name, 
+		p->br->dev->name, p->port_no, p->dev->name,
 		br_port_state_names[p->state]);
 
 }
@@ -53,7 +53,7 @@
 }
 
 /* called under bridge lock */
-static int br_should_become_root_port(const struct net_bridge_port *p, 
+static int br_should_become_root_port(const struct net_bridge_port *p,
 				      u16 root_port)
 {
 	struct net_bridge *br;
@@ -184,7 +184,7 @@
 }
 
 /* called under bridge lock */
-static inline void br_record_config_information(struct net_bridge_port *p, 
+static inline void br_record_config_information(struct net_bridge_port *p,
 						const struct br_config_bpdu *bpdu)
 {
 	p->designated_root = bpdu->root;
@@ -192,12 +192,12 @@
 	p->designated_bridge = bpdu->bridge_id;
 	p->designated_port = bpdu->port_id;
 
-	mod_timer(&p->message_age_timer, jiffies 
+	mod_timer(&p->message_age_timer, jiffies
 		  + (p->br->max_age - bpdu->message_age));
 }
 
 /* called under bridge lock */
-static inline void br_record_config_timeout_values(struct net_bridge *br, 
+static inline void br_record_config_timeout_values(struct net_bridge *br,
 					    const struct br_config_bpdu *bpdu)
 {
 	br->max_age = bpdu->max_age;
@@ -415,7 +415,7 @@
 {
 	struct net_bridge *br;
 	int was_root;
- 
+
 	br = p->br;
 	was_root = br_is_root_bridge(br);
 
@@ -430,7 +430,7 @@
 				del_timer(&br->topology_change_timer);
 				br_transmit_tcn(br);
 
-				mod_timer(&br->tcn_timer, 
+				mod_timer(&br->tcn_timer,
 					  jiffies + br->bridge_hello_time);
 			}
 		}
@@ -441,8 +441,8 @@
 			if (bpdu->topology_change_ack)
 				br_topology_change_acknowledged(br);
 		}
-	} else if (br_is_designated_port(p)) {		
-		br_reply(p);		
+	} else if (br_is_designated_port(p)) {
+		br_reply(p);
 	}
 }
 
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index 068d8af..b9fb0dc 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -29,7 +29,7 @@
 #define LLC_RESERVE sizeof(struct llc_pdu_un)
 
 static void br_send_bpdu(struct net_bridge_port *p,
- 			 const unsigned char *data, int length)
+			 const unsigned char *data, int length)
 {
 	struct sk_buff *skb;
 
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index d294224..58d13f2 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -28,7 +28,7 @@
  */
 static inline port_id br_make_port_id(__u8 priority, __u16 port_no)
 {
-	return ((u16)priority << BR_PORT_BITS) 
+	return ((u16)priority << BR_PORT_BITS)
 		| (port_no & ((1<<BR_PORT_BITS)-1));
 }
 
@@ -50,7 +50,7 @@
 	spin_lock_bh(&br->lock);
 	mod_timer(&br->hello_timer, jiffies + br->hello_time);
 	mod_timer(&br->gc_timer, jiffies + HZ/10);
-	
+
 	br_config_bpdu_generation(br);
 
 	list_for_each_entry(p, &br->port_list, list) {
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index d0fcde8..030aa79 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -27,7 +27,7 @@
 
 	list_for_each_entry(p, &br->port_list, list) {
 		if (p->state != BR_STATE_DISABLED &&
-		    !memcmp(&p->designated_bridge, &br->bridge_id, 8)) 
+		    !memcmp(&p->designated_bridge, &br->bridge_id, 8))
 			return 1;
 	}
 
@@ -37,7 +37,7 @@
 static void br_hello_timer_expired(unsigned long arg)
 {
 	struct net_bridge *br = (struct net_bridge *)arg;
-	
+
 	pr_debug("%s: hello timer expired\n", br->dev->name);
 	spin_lock(&br->lock);
 	if (br->dev->flags & IFF_UP) {
@@ -58,11 +58,11 @@
 	if (p->state == BR_STATE_DISABLED)
 		return;
 
-	
+
 	pr_info("%s: neighbor %.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x lost on port %d(%s)\n",
-		br->dev->name, 
-		id->prio[0], id->prio[1], 
-		id->addr[0], id->addr[1], id->addr[2], 
+		br->dev->name,
+		id->prio[0], id->prio[1],
+		id->addr[0], id->addr[1], id->addr[2],
 		id->addr[3], id->addr[4], id->addr[5],
 		p->port_no, p->dev->name);
 
@@ -114,7 +114,7 @@
 	spin_lock(&br->lock);
 	if (br->dev->flags & IFF_UP) {
 		br_transmit_tcn(br);
-	
+
 		mod_timer(&br->tcn_timer,jiffies + br->bridge_hello_time);
 	}
 	spin_unlock(&br->lock);
@@ -135,7 +135,7 @@
 {
 	struct net_bridge_port *p = (struct net_bridge_port *) arg;
 
-	pr_debug("%s: %d(%s) hold timer expired\n", 
+	pr_debug("%s: %d(%s) hold timer expired\n",
 		 p->br->dev->name,  p->port_no, p->dev->name);
 
 	spin_lock(&p->br->lock);
@@ -166,10 +166,10 @@
 
 	setup_timer(&p->forward_delay_timer, br_forward_delay_timer_expired,
 		      (unsigned long) p);
-		      
+
 	setup_timer(&p->hold_timer, br_hold_timer_expired,
 		      (unsigned long) p);
-}	
+}
 
 /* Report ticks left (in USER_HZ) used for API */
 unsigned long br_timer_value(const struct timer_list *timer)
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index ce10464..01a22ad 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -353,19 +353,19 @@
 	if (off % sizeof(struct __fdb_entry) != 0)
 		return -EINVAL;
 
-	n =  br_fdb_fillbuf(br, buf, 
+	n =  br_fdb_fillbuf(br, buf,
 			    count / sizeof(struct __fdb_entry),
 			    off / sizeof(struct __fdb_entry));
 
 	if (n > 0)
 		n *= sizeof(struct __fdb_entry);
-	
+
 	return n;
 }
 
 static struct bin_attribute bridge_forward = {
 	.attr = { .name = SYSFS_BRIDGE_FDB,
-		  .mode = S_IRUGO, 
+		  .mode = S_IRUGO,
 		  .owner = THIS_MODULE, },
 	.read = brforward_read,
 };
@@ -401,7 +401,7 @@
 		goto out2;
 	}
 
-	
+
 	kobject_set_name(&br->ifobj, SYSFS_BRIDGE_PORT_SUBDIR);
 	br->ifobj.ktype = NULL;
 	br->ifobj.kset = NULL;
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
index 9abbc09..41a7807 100644
--- a/net/bridge/netfilter/ebt_802_3.c
+++ b/net/bridge/netfilter/ebt_802_3.c
@@ -5,7 +5,7 @@
  * Chris Vitale csv@bluetail.com
  *
  * May 2003
- * 
+ *
  */
 
 #include <linux/netfilter_bridge/ebtables.h>
@@ -20,7 +20,7 @@
 	__be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
 
 	if (info->bitmask & EBT_802_3_SAP) {
-		if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP)) 
+		if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP))
 				return EBT_NOMATCH;
 		if (FWINV(info->sap != hdr->llc.ui.dsap, EBT_802_3_SAP))
 				return EBT_NOMATCH;
@@ -29,7 +29,7 @@
 	if (info->bitmask & EBT_802_3_TYPE) {
 		if (!(hdr->llc.ui.dsap == CHECK_TYPE && hdr->llc.ui.ssap == CHECK_TYPE))
 			return EBT_NOMATCH;
-		if (FWINV(info->type != type, EBT_802_3_TYPE)) 
+		if (FWINV(info->type != type, EBT_802_3_TYPE))
 			return EBT_NOMATCH;
 	}
 
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c
index ce97c42..392d877 100644
--- a/net/bridge/netfilter/ebt_among.c
+++ b/net/bridge/netfilter/ebt_among.c
@@ -18,7 +18,7 @@
 				     const char *mac, __be32 ip)
 {
 	/* You may be puzzled as to how this code works.
-	 * Some tricks were used, refer to 
+	 * Some tricks were used, refer to
 	 * 	include/linux/netfilter_bridge/ebt_among.h
 	 * as there you can find a solution of this mystery.
 	 */
@@ -207,8 +207,8 @@
 }
 
 static struct ebt_match filter_among = {
-	.name		= EBT_AMONG_MATCH, 
-	.match		= ebt_filter_among, 
+	.name		= EBT_AMONG_MATCH,
+	.match		= ebt_filter_among,
 	.check		= ebt_among_check,
 	.me		= THIS_MODULE,
 };
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index 0aa7b99..ffe468a 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -51,7 +51,7 @@
 		return EBT_DROP;
 
 	arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)in,
-	         *diptr, shp, info->mac, shp);
+		 *diptr, shp, info->mac, shp);
 
 	return info->target;
 }
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
index e4c6424..69f7f0a 100644
--- a/net/bridge/netfilter/ebt_ip.c
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -61,15 +61,15 @@
 		if (info->bitmask & EBT_IP_DPORT) {
 			u32 dst = ntohs(pptr->dst);
 			if (FWINV(dst < info->dport[0] ||
-			          dst > info->dport[1],
-			          EBT_IP_DPORT))
+				  dst > info->dport[1],
+				  EBT_IP_DPORT))
 			return EBT_NOMATCH;
 		}
 		if (info->bitmask & EBT_IP_SPORT) {
 			u32 src = ntohs(pptr->src);
 			if (FWINV(src < info->sport[0] ||
-			          src > info->sport[1],
-			          EBT_IP_SPORT))
+				  src > info->sport[1],
+				  EBT_IP_SPORT))
 			return EBT_NOMATCH;
 		}
 	}
@@ -93,6 +93,7 @@
 			return -EINVAL;
 		if (info->protocol != IPPROTO_TCP &&
 		    info->protocol != IPPROTO_UDP &&
+		    info->protocol != IPPROTO_UDPLITE &&
 		    info->protocol != IPPROTO_SCTP &&
 		    info->protocol != IPPROTO_DCCP)
 			 return -EINVAL;
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index a184f87..45712ae 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -96,6 +96,7 @@
 		       NIPQUAD(ih->daddr), ih->tos, ih->protocol);
 		if (ih->protocol == IPPROTO_TCP ||
 		    ih->protocol == IPPROTO_UDP ||
+		    ih->protocol == IPPROTO_UDPLITE ||
 		    ih->protocol == IPPROTO_SCTP ||
 		    ih->protocol == IPPROTO_DCCP) {
 			struct tcpudphdr _ports, *pptr;
@@ -168,10 +169,10 @@
 
 	if (info->bitmask & EBT_LOG_NFLOG)
 		nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
-		              "%s", info->prefix);
+			      "%s", info->prefix);
 	else
 		ebt_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
-		               info->prefix);
+			       info->prefix);
 }
 
 static struct ebt_watcher log =
@@ -198,7 +199,7 @@
 	if (nf_log_register(PF_BRIDGE, &ebt_log_logger) < 0) {
 		printk(KERN_WARNING "ebt_log: not logging via system console "
 		       "since somebody else already registered for PF_INET\n");
-		/* we cannot make module load fail here, since otherwise 
+		/* we cannot make module load fail here, since otherwise
 		 * ebtables userspace would abort */
 	}
 
@@ -207,7 +208,7 @@
 
 static void __exit ebt_log_fini(void)
 {
-	nf_log_unregister_logger(&ebt_log_logger);
+	nf_log_unregister(&ebt_log_logger);
 	ebt_unregister_watcher(&log);
 }
 
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
index 025869ee0..6b0d216 100644
--- a/net/bridge/netfilter/ebt_mark_m.c
+++ b/net/bridge/netfilter/ebt_mark_m.c
@@ -26,7 +26,7 @@
 static int ebt_mark_check(const char *tablename, unsigned int hookmask,
    const struct ebt_entry *e, void *data, unsigned int datalen)
 {
-        struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data;
+	struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data;
 
 	if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_m_info)))
 		return -EINVAL;
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
index a0bed82..31b7736 100644
--- a/net/bridge/netfilter/ebt_stp.c
+++ b/net/bridge/netfilter/ebt_stp.c
@@ -62,7 +62,7 @@
 		verdict = 0;
 		for (i = 0; i < 6; i++)
 			verdict |= (stpc->root[2+i] ^ c->root_addr[i]) &
-			           c->root_addrmsk[i];
+				   c->root_addrmsk[i];
 		if (FWINV(verdict != 0, EBT_STP_ROOTADDR))
 			return EBT_NOMATCH;
 	}
@@ -82,7 +82,7 @@
 		verdict = 0;
 		for (i = 0; i < 6; i++)
 			verdict |= (stpc->sender[2+i] ^ c->sender_addr[i]) &
-			           c->sender_addrmsk[i];
+				   c->sender_addrmsk[i];
 		if (FWINV(verdict != 0, EBT_STP_SENDERADDR))
 			return EBT_NOMATCH;
 	}
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index c1af68b..8e15cc4 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -10,8 +10,8 @@
  * Based on ipt_ULOG.c, which is
  * (C) 2000-2002 by Harald Welte <laforge@netfilter.org>
  *
- * This module accepts two parameters: 
- * 
+ * This module accepts two parameters:
+ *
  * nlbufsiz:
  *   The parameter specifies how big the buffer for each netlink multicast
  * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will
@@ -43,17 +43,17 @@
 #include "../br_private.h"
 
 #define PRINTR(format, args...) do { if (net_ratelimit()) \
-                                printk(format , ## args); } while (0)
+				printk(format , ## args); } while (0)
 
 static unsigned int nlbufsiz = NLMSG_GOODSIZE;
 module_param(nlbufsiz, uint, 0600);
 MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) "
-                           "(defaults to 4096)");
+			   "(defaults to 4096)");
 
 static unsigned int flushtimeout = 10;
 module_param(flushtimeout, uint, 0600);
 MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths ofa second) "
-                               "(defaults to 10)");
+			       "(defaults to 10)");
 
 typedef struct {
 	unsigned int qlen;		/* number of nlmsgs' in the skb */
@@ -157,7 +157,7 @@
 	}
 
 	nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0,
-	                size - NLMSG_ALIGN(sizeof(*nlh)));
+			size - NLMSG_ALIGN(sizeof(*nlh)));
 	ub->qlen++;
 
 	pm = NLMSG_DATA(nlh);
@@ -302,7 +302,7 @@
 	}
 
 	ebtulognl = netlink_kernel_create(NETLINK_NFLOG, EBT_ULOG_MAXNLGROUPS,
-	                                  NULL, THIS_MODULE);
+					  NULL, THIS_MODULE);
 	if (!ebtulognl)
 		ret = -ENOMEM;
 	else if ((ret = ebt_register_watcher(&ulog)))
@@ -323,7 +323,7 @@
 	ebt_ulog_buff_t *ub;
 	int i;
 
-	nf_log_unregister_logger(&ebt_ulog_logger);
+	nf_log_unregister(&ebt_ulog_logger);
 	ebt_unregister_watcher(&ulog);
 	for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
 		ub = &ulog_buffers[i];
@@ -344,4 +344,4 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
 MODULE_DESCRIPTION("ebtables userspace logging module for bridged Ethernet"
-                   " frames");
+		   " frames");
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index 7ee3776..a43c697 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -128,9 +128,9 @@
 
 	/* Reserved VLAN ID (VID) values
 	 * -----------------------------
-	 * 0 - The null VLAN ID. 
+	 * 0 - The null VLAN ID.
 	 * 1 - The default Port VID (PVID)
-	 * 0x0FFF - Reserved for implementation use. 
+	 * 0x0FFF - Reserved for implementation use.
 	 * if_vlan.h: VLAN_GROUP_ARRAY_LEN 4096. */
 	if (GET_BITMASK(EBT_VLAN_ID)) {
 		if (!!info->id) { /* if id!=0 => check vid range */
@@ -141,7 +141,7 @@
 				return -EINVAL;
 			}
 			/* Note: This is valid VLAN-tagged frame point.
-			 * Any value of user_priority are acceptable, 
+			 * Any value of user_priority are acceptable,
 			 * but should be ignored according to 802.1Q Std.
 			 * So we just drop the prio flag. */
 			info->bitmask &= ~EBT_VLAN_PRIO;
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 127135e..81d8414 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -51,10 +51,10 @@
 }
 
 static struct ebt_table frame_filter =
-{ 
+{
 	.name		= "filter",
 	.table		= &initial_table,
-	.valid_hooks	= FILTER_VALID_HOOKS, 
+	.valid_hooks	= FILTER_VALID_HOOKS,
 	.lock		= RW_LOCK_UNLOCKED,
 	.check		= check,
 	.me		= THIS_MODULE,
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 6c84ccb..ac9984f 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -16,7 +16,6 @@
  */
 
 /* used for print_string */
-#include <linux/sched.h>
 #include <linux/tty.h>
 
 #include <linux/kmod.h>
@@ -33,10 +32,10 @@
 #include "../br_private.h"
 
 #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
-                                         "report to author: "format, ## args)
+					 "report to author: "format, ## args)
 /* #define BUGPRINT(format, args...) */
 #define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
-                                         ": out of memory: "format, ## args)
+					 ": out of memory: "format, ## args)
 /* #define MEMPRINT(format, args...) */
 
 
@@ -482,7 +481,7 @@
 		   as it said it has */
 		if (*n != *cnt) {
 			BUGPRINT("nentries does not equal the nr of entries "
-		                 "in the chain\n");
+				 "in the chain\n");
 			return -EINVAL;
 		}
 		if (((struct ebt_entries *)e)->policy != EBT_DROP &&
@@ -809,7 +808,7 @@
 	i = 0; /* holds the expected nr. of entries for the chain */
 	j = 0; /* holds the up to now counted entries for the chain */
 	k = 0; /* holds the total nr. of entries, should equal
-	          newinfo->nentries afterwards */
+		  newinfo->nentries afterwards */
 	udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
 	ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
 	   ebt_check_entry_size_and_hooks, newinfo,
@@ -820,7 +819,7 @@
 
 	if (i != j) {
 		BUGPRINT("nentries does not equal the nr of entries in the "
-		         "(last) chain\n");
+			 "(last) chain\n");
 		return -EINVAL;
 	}
 	if (k != newinfo->nentries) {
@@ -834,8 +833,7 @@
 		/* this will get free'd in do_replace()/ebt_register_table()
 		   if an error occurs */
 		newinfo->chainstack =
-			vmalloc((highest_possible_processor_id()+1)
-				   	* sizeof(*(newinfo->chainstack)));
+			vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
 		if (!newinfo->chainstack)
 			return -ENOMEM;
 		for_each_possible_cpu(i) {
@@ -948,8 +946,7 @@
 	if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
 		return -ENOMEM;
 
-	countersize = COUNTER_OFFSET(tmp.nentries) * 
-					(highest_possible_processor_id()+1);
+	countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
 	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	if (!newinfo)
 		return -ENOMEM;
@@ -1169,8 +1166,7 @@
 		return -EINVAL;
 	}
 
-	countersize = COUNTER_OFFSET(repl->nentries) *
-					(highest_possible_processor_id()+1);
+	countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
 	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	ret = -ENOMEM;
 	if (!newinfo)
@@ -1350,7 +1346,7 @@
 
 	hlp = ubase + (((char *)e + e->target_offset) - base);
 	t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
-	
+
 	ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
 	if (ret != 0)
 		return ret;
diff --git a/net/compat.c b/net/compat.c
index 52d32f1..1f32866 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c.
  *
  * Copyright (C) 2000		VA Linux Co
@@ -8,12 +8,11 @@
  * Copyright (C) 1997 		David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 2000		Hewlett-Packard Co.
  * Copyright (C) 2000		David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2000,2001	Andi Kleen, SuSE Labs 
+ * Copyright (C) 2000,2001	Andi Kleen, SuSE Labs
  */
 
 #include <linux/kernel.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/file.h>
 #include <linux/icmpv6.h>
@@ -225,14 +224,14 @@
 		return 0; /* XXX: return error? check spec. */
 	}
 
-	if (level == SOL_SOCKET && type == SO_TIMESTAMP) { 
+	if (level == SOL_SOCKET && type == SO_TIMESTAMP) {
 		struct timeval *tv = (struct timeval *)data;
 		ctv.tv_sec = tv->tv_sec;
 		ctv.tv_usec = tv->tv_usec;
 		data = &ctv;
 		len = sizeof(struct compat_timeval);
-	} 
-	
+	}
+
 	cmlen = CMSG_COMPAT_LEN(len);
 	if(kmsg->msg_controllen < cmlen) {
 		kmsg->msg_flags |= MSG_CTRUNC;
@@ -419,7 +418,7 @@
 				char __user *optval, int optlen)
 {
 	struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval;
-	struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog)); 
+	struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog));
 	compat_uptr_t ptr;
 	u16 len;
 
@@ -610,14 +609,14 @@
 	int ret;
 	u32 a[6];
 	u32 a0, a1;
-				 
+
 	if (call < SYS_SOCKET || call > SYS_RECVMSG)
 		return -EINVAL;
 	if (copy_from_user(a, args, nas[call]))
 		return -EFAULT;
 	a0 = a[0];
 	a1 = a[1];
-	
+
 	switch(call) {
 	case SYS_SOCKET:
 		ret = sys_socket(a0, a1, a[2]);
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 797fdd4..186212b 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -430,7 +430,7 @@
  *	@skb: skbuff
  *	@hlen: hardware length
  *	@iov: io vector
- * 
+ *
  *	Caller _must_ check that skb will fit to this iovec.
  *
  *	Returns: 0       - success.
diff --git a/net/core/dev.c b/net/core/dev.c
index 455d589..cf71614 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -255,7 +255,7 @@
  *	is linked into kernel lists and may not be freed until it has been
  *	removed from the kernel lists.
  *
- *	This call does not sleep therefore it can not 
+ *	This call does not sleep therefore it can not
  *	guarantee all CPU's that are in middle of receiving packets
  *	will see the new packet type (until the next received packet).
  */
@@ -282,7 +282,7 @@
  *	Remove a protocol handler that was previously added to the kernel
  *	protocol handlers by dev_add_pack(). The passed &packet_type is removed
  *	from the kernel lists and can be freed or reused once this function
- *	returns. 
+ *	returns.
  *
  *      The packet type might still be in use by receivers
  *	and must not be freed until after all the CPU's have gone
@@ -327,7 +327,7 @@
 void dev_remove_pack(struct packet_type *pt)
 {
 	__dev_remove_pack(pt);
-	
+
 	synchronize_net();
 }
 
@@ -607,7 +607,7 @@
  *	@mask: bitmask of bits in if_flags to check
  *
  *	Search for any interface with the given flags. Returns NULL if a device
- *	is not found or a pointer to the device. The device returned has 
+ *	is not found or a pointer to the device. The device returned has
  *	had a reference added and the pointer is safe until the user calls
  *	dev_put to indicate they have finished with it.
  */
@@ -802,7 +802,7 @@
 
 void dev_load(const char *name)
 {
-	struct net_device *dev;  
+	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
 	dev = __dev_get_by_name(name);
@@ -860,7 +860,7 @@
 			clear_bit(__LINK_STATE_START, &dev->state);
 	}
 
- 	/*
+	/*
 	 *	If it went open OK then:
 	 */
 
@@ -964,7 +964,7 @@
  *	is returned on a failure.
  *
  * 	When registered all registration and up events are replayed
- *	to the new notifier to allow device to have a race free 
+ *	to the new notifier to allow device to have a race free
  *	view of the network device list.
  */
 
@@ -979,7 +979,7 @@
 		for (dev = dev_base; dev; dev = dev->next) {
 			nb->notifier_call(nb, NETDEV_REGISTER, dev);
 
-			if (dev->flags & IFF_UP) 
+			if (dev->flags & IFF_UP)
 				nb->notifier_call(nb, NETDEV_UP, dev);
 		}
 	}
@@ -1157,7 +1157,7 @@
 	if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) &&
 	    netif_running(dev)) {
 		netif_wake_queue(dev);
- 		__netdev_watchdog_up(dev);
+		__netdev_watchdog_up(dev);
 	}
 }
 EXPORT_SYMBOL(netif_device_attach);
@@ -1197,7 +1197,7 @@
 
 out_set_summed:
 	skb->ip_summed = CHECKSUM_NONE;
-out:	
+out:
 	return ret;
 }
 
@@ -1258,7 +1258,7 @@
 void netdev_rx_csum_fault(struct net_device *dev)
 {
 	if (net_ratelimit()) {
-		printk(KERN_ERR "%s: hw csum failure.\n", 
+		printk(KERN_ERR "%s: hw csum failure.\n",
 			dev ? dev->name : "<unknown>");
 		dump_stack();
 	}
@@ -1372,7 +1372,7 @@
 		if (unlikely(netif_queue_stopped(dev) && skb->next))
 			return NETDEV_TX_BUSY;
 	} while (skb->next);
-	
+
 	skb->destructor = DEV_GSO_CB(skb)->destructor;
 
 out_kfree_skb:
@@ -1449,25 +1449,25 @@
 	    (!(dev->features & NETIF_F_GEN_CSUM) &&
 	     (!(dev->features & NETIF_F_IP_CSUM) ||
 	      skb->protocol != htons(ETH_P_IP))))
-	      	if (skb_checksum_help(skb))
-	      		goto out_kfree_skb;
+		if (skb_checksum_help(skb))
+			goto out_kfree_skb;
 
 gso:
 	spin_lock_prefetch(&dev->queue_lock);
 
-	/* Disable soft irqs for various locks below. Also 
-	 * stops preemption for RCU. 
+	/* Disable soft irqs for various locks below. Also
+	 * stops preemption for RCU.
 	 */
-	rcu_read_lock_bh(); 
+	rcu_read_lock_bh();
 
-	/* Updates of qdisc are serialized by queue_lock. 
-	 * The struct Qdisc which is pointed to by qdisc is now a 
-	 * rcu structure - it may be accessed without acquiring 
+	/* Updates of qdisc are serialized by queue_lock.
+	 * The struct Qdisc which is pointed to by qdisc is now a
+	 * rcu structure - it may be accessed without acquiring
 	 * a lock (but the structure may be stale.) The freeing of the
-	 * qdisc will be deferred until it's known that there are no 
+	 * qdisc will be deferred until it's known that there are no
 	 * more references to it.
-	 * 
-	 * If the qdisc has an enqueue function, we still need to 
+	 *
+	 * If the qdisc has an enqueue function, we still need to
 	 * hold the queue_lock before calling it, since queue_lock
 	 * also serializes access to the device queue.
 	 */
@@ -1715,8 +1715,8 @@
 	if (*pt_prev) {
 		*ret = deliver_skb(*pskb, *pt_prev, orig_dev);
 		*pt_prev = NULL;
-	} 
-	
+	}
+
 	return br_handle_frame_hook(port, pskb);
 }
 #else
@@ -1728,16 +1728,16 @@
  * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
  * a compare and 2 stores extra right now if we dont have it on
  * but have CONFIG_NET_CLS_ACT
- * NOTE: This doesnt stop any functionality; if you dont have 
+ * NOTE: This doesnt stop any functionality; if you dont have
  * the ingress scheduler, you just cant add policies on ingress.
  *
  */
-static int ing_filter(struct sk_buff *skb) 
+static int ing_filter(struct sk_buff *skb)
 {
 	struct Qdisc *q;
 	struct net_device *dev = skb->dev;
 	int result = TC_ACT_OK;
-	
+
 	if (dev->qdisc_ingress) {
 		__u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
 		if (MAX_RED_LOOP < ttl++) {
@@ -1801,7 +1801,7 @@
 
 	list_for_each_entry_rcu(ptype, &ptype_all, list) {
 		if (!ptype->dev || ptype->dev == skb->dev) {
-			if (pt_prev) 
+			if (pt_prev)
 				ret = deliver_skb(skb, pt_prev, orig_dev);
 			pt_prev = ptype;
 		}
@@ -1833,7 +1833,7 @@
 	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
 		if (ptype->type == type &&
 		    (!ptype->dev || ptype->dev == skb->dev)) {
-			if (pt_prev) 
+			if (pt_prev)
 				ret = deliver_skb(skb, pt_prev, orig_dev);
 			pt_prev = ptype;
 		}
@@ -2061,7 +2061,7 @@
 				total += done;
 			}
 		}
-  	}
+	}
 
 	/*
 	 *	All done.  Write the updated control block back to the caller.
@@ -2154,7 +2154,7 @@
 	struct netif_rx_stats *rc = NULL;
 
 	while (*pos < NR_CPUS)
-	       	if (cpu_online(*pos)) {
+		if (cpu_online(*pos)) {
 			rc = &per_cpu(netdev_rx_stat, *pos);
 			break;
 		} else
@@ -2200,7 +2200,7 @@
 	return seq_open(file, &dev_seq_ops);
 }
 
-static struct file_operations dev_seq_fops = {
+static const struct file_operations dev_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = dev_seq_open,
 	.read    = seq_read,
@@ -2220,7 +2220,7 @@
 	return seq_open(file, &softnet_seq_ops);
 }
 
-static struct file_operations softnet_seq_fops = {
+static const struct file_operations softnet_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = softnet_seq_open,
 	.read    = seq_read,
@@ -2282,7 +2282,7 @@
 	}
 
 	slave->master = master;
-	
+
 	synchronize_net();
 
 	if (old)
@@ -2319,13 +2319,13 @@
 		dev_mc_upload(dev);
 		printk(KERN_INFO "device %s %s promiscuous mode\n",
 		       dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
-		       					       "left");
+							       "left");
 		audit_log(current->audit_context, GFP_ATOMIC,
 			AUDIT_ANOM_PROMISCUOUS,
 			"dev=%s prom=%d old_prom=%d auid=%u",
 			dev->name, (dev->flags & IFF_PROMISC),
 			(old_flags & IFF_PROMISC),
-			audit_get_loginuid(current->audit_context)); 
+			audit_get_loginuid(current->audit_context));
 	}
 }
 
@@ -2816,7 +2816,7 @@
 				rtnl_unlock();
 				if (IW_IS_GET(cmd) &&
 				    copy_to_user(arg, &ifr,
-					    	 sizeof(struct ifreq)))
+						 sizeof(struct ifreq)))
 					ret = -EFAULT;
 				return ret;
 			}
@@ -2906,7 +2906,7 @@
 			goto out;
 		}
 	}
- 
+
 	if (!dev_valid_name(dev->name)) {
 		ret = -EINVAL;
 		goto out;
@@ -2923,9 +2923,9 @@
 			= hlist_entry(p, struct net_device, name_hlist);
 		if (!strncmp(d->name, dev->name, IFNAMSIZ)) {
 			ret = -EEXIST;
- 			goto out;
+			goto out;
 		}
- 	}
+	}
 
 	/* Fix illegal SG+CSUM combinations. */
 	if ((dev->features & NETIF_F_SG) &&
@@ -3024,7 +3024,7 @@
 		if (err < 0)
 			goto out;
 	}
-	
+
 	err = register_netdevice(dev);
 out:
 	rtnl_unlock();
@@ -3041,7 +3041,7 @@
  * for netdevice notification, and cleanup and put back the
  * reference if they receive an UNREGISTER event.
  * We can get stuck here if buggy protocols don't correctly
- * call dev_put. 
+ * call dev_put.
  */
 static void netdev_wait_allrefs(struct net_device *dev)
 {
@@ -3205,8 +3205,8 @@
  *	free_netdev - free network device
  *	@dev: device
  *
- *	This function does the last stage of destroying an allocated device 
- * 	interface. The reference to the device object is released.  
+ *	This function does the last stage of destroying an allocated device
+ * 	interface. The reference to the device object is released.
  *	If this is the last reference then it will be freed.
  */
 void free_netdev(struct net_device *dev)
@@ -3227,9 +3227,9 @@
 	kfree((char *)dev - dev->padded);
 #endif
 }
- 
+
 /* Synchronize with packet receive processing. */
-void synchronize_net(void) 
+void synchronize_net(void)
 {
 	might_sleep();
 	synchronize_rcu();
@@ -3247,7 +3247,7 @@
  *	unregister_netdev() instead of this.
  */
 
-int unregister_netdevice(struct net_device *dev)
+void unregister_netdevice(struct net_device *dev)
 {
 	struct net_device *d, **dp;
 
@@ -3258,7 +3258,9 @@
 	if (dev->reg_state == NETREG_UNINITIALIZED) {
 		printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
 				  "was registered\n", dev->name, dev);
-		return -ENODEV;
+
+		WARN_ON(1);
+		return;
 	}
 
 	BUG_ON(dev->reg_state != NETREG_REGISTERED);
@@ -3280,11 +3282,7 @@
 			break;
 		}
 	}
-	if (!d) {
-		printk(KERN_ERR "unregister net_device: '%s' not found\n",
-		       dev->name);
-		return -ENODEV;
-	}
+	BUG_ON(!d);
 
 	dev->reg_state = NETREG_UNREGISTERING;
 
@@ -3293,12 +3291,12 @@
 	/* Shutdown queueing discipline. */
 	dev_shutdown(dev);
 
-	
+
 	/* Notify protocols, that we are about to destroy
 	   this device. They should clean all the things.
 	*/
 	raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
-	
+
 	/*
 	 *	Flush the multicast chain
 	 */
@@ -3316,7 +3314,6 @@
 	synchronize_net();
 
 	dev_put(dev);
-	return 0;
 }
 
 /**
@@ -3486,7 +3483,7 @@
 		goto out;
 
 	INIT_LIST_HEAD(&ptype_all);
-	for (i = 0; i < 16; i++) 
+	for (i = 0; i < 16; i++)
 		INIT_LIST_HEAD(&ptype_base[i]);
 
 	for (i = 0; i < ARRAY_SIZE(dev_name_head); i++)
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index b22648d..56b310c 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -1,12 +1,12 @@
 /*
- *	Linux NET3:	Multicast List maintenance. 
+ *	Linux NET3:	Multicast List maintenance.
  *
  *	Authors:
- *		Tim Kordas <tjk@nostromo.eeap.cwru.edu> 
+ *		Tim Kordas <tjk@nostromo.eeap.cwru.edu>
  *		Richard Underwood <richard@wuzz.demon.co.uk>
  *
  *	Stir fried together from the IP multicast and CAP patches above
- *		Alan Cox <Alan.Cox@linux.org>	
+ *		Alan Cox <Alan.Cox@linux.org>
  *
  *	Fixes:
  *		Alan Cox	:	Update the device on a real delete
@@ -27,7 +27,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -50,11 +49,11 @@
 
 
 /*
- *	Device multicast list maintenance. 
+ *	Device multicast list maintenance.
  *
- *	This is used both by IP and by the user level maintenance functions. 
- *	Unlike BSD we maintain a usage count on a given multicast address so 
- *	that a casual user application can add/delete multicasts used by 
+ *	This is used both by IP and by the user level maintenance functions.
+ *	Unlike BSD we maintain a usage count on a given multicast address so
+ *	that a casual user application can add/delete multicasts used by
  *	protocols without doing damage to the protocols when it deletes the
  *	entries. It also helps IP as it tracks overlapping maps.
  *
@@ -67,7 +66,7 @@
 /*
  *	Update the multicast list into the physical NIC controller.
  */
- 
+
 static void __dev_mc_upload(struct net_device *dev)
 {
 	/* Don't do anything till we up the interface
@@ -100,7 +99,7 @@
 /*
  *	Delete a device level multicast
  */
- 
+
 int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
 {
 	int err = 0;
@@ -137,7 +136,7 @@
 			 *	loaded filter is now wrong. Fix it
 			 */
 			__dev_mc_upload(dev);
-			
+
 			netif_tx_unlock_bh(dev);
 			return 0;
 		}
@@ -151,7 +150,7 @@
 /*
  *	Add a device level multicast
  */
- 
+
 int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
 {
 	int err = 0;
@@ -187,7 +186,7 @@
 	dev->mc_count++;
 
 	__dev_mc_upload(dev);
-	
+
 	netif_tx_unlock_bh(dev);
 	return 0;
 
@@ -204,7 +203,7 @@
 void dev_mc_discard(struct net_device *dev)
 {
 	netif_tx_lock_bh(dev);
-	
+
 	while (dev->mc_list != NULL) {
 		struct dev_mc_list *tmp = dev->mc_list;
 		dev->mc_list = tmp->next;
@@ -225,7 +224,7 @@
 
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev; dev = dev->next) {
-		if (off++ == *pos) 
+		if (off++ == *pos)
 			return dev;
 	}
 	return NULL;
@@ -277,7 +276,7 @@
 	return seq_open(file, &dev_mc_seq_ops);
 }
 
-static struct file_operations dev_mc_seq_fops = {
+static const struct file_operations dev_mc_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = dev_mc_seq_open,
 	.read    = seq_read,
diff --git a/net/core/dst.c b/net/core/dst.c
index 836ec66..764bccb 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -12,7 +12,6 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/string.h>
 #include <linux/types.h>
@@ -29,7 +28,7 @@
  * 4) All operations modify state, so a spinlock is used.
  */
 static struct dst_entry 	*dst_garbage_list;
-#if RT_CACHE_DEBUG >= 2 
+#if RT_CACHE_DEBUG >= 2
 static atomic_t			 dst_total = ATOMIC_INIT(0);
 #endif
 static DEFINE_SPINLOCK(dst_lock);
@@ -99,7 +98,14 @@
 	printk("dst_total: %d/%d %ld\n",
 	       atomic_read(&dst_total), delayed,  dst_gc_timer_expires);
 #endif
-	mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires);
+	/* if the next desired timer is more than 4 seconds in the future
+	 * then round the timer to whole seconds
+	 */
+	if (dst_gc_timer_expires > 4*HZ)
+		mod_timer(&dst_gc_timer,
+			round_jiffies(jiffies + dst_gc_timer_expires));
+	else
+		mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires);
 
 out:
 	spin_unlock(&dst_lock);
@@ -125,17 +131,16 @@
 		if (ops->gc())
 			return NULL;
 	}
-	dst = kmem_cache_alloc(ops->kmem_cachep, GFP_ATOMIC);
+	dst = kmem_cache_zalloc(ops->kmem_cachep, GFP_ATOMIC);
 	if (!dst)
 		return NULL;
-	memset(dst, 0, ops->entry_size);
 	atomic_set(&dst->__refcnt, 0);
 	dst->ops = ops;
 	dst->lastuse = jiffies;
 	dst->path = dst;
 	dst->input = dst_discard_in;
 	dst->output = dst_discard_out;
-#if RT_CACHE_DEBUG >= 2 
+#if RT_CACHE_DEBUG >= 2
 	atomic_inc(&dst_total);
 #endif
 	atomic_inc(&ops->entries);
@@ -196,7 +201,7 @@
 		dst->ops->destroy(dst);
 	if (dst->dev)
 		dev_put(dst->dev);
-#if RT_CACHE_DEBUG >= 2 
+#if RT_CACHE_DEBUG >= 2
 	atomic_dec(&dst_total);
 #endif
 	kmem_cache_free(dst->ops->kmem_cachep, dst);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 87dc556..6168edd 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -17,7 +17,7 @@
 #include <linux/netdevice.h>
 #include <asm/uaccess.h>
 
-/* 
+/*
  * Some useful ethtool_ops methods that're device independent.
  * If we find that all drivers want to do the same thing here,
  * we can turn these into dev_() function calls.
@@ -87,12 +87,12 @@
 	unsigned char len = dev->addr_len;
 	if ( addr->size < len )
 		return -ETOOSMALL;
-	
+
 	addr->size = len;
 	memcpy(data, dev->perm_addr, len);
 	return 0;
 }
- 
+
 
 u32 ethtool_op_get_ufo(struct net_device *dev)
 {
@@ -550,7 +550,7 @@
 	if (copy_from_user(&edata, useraddr, sizeof(edata)))
 		return -EFAULT;
 
-	if (edata.data && 
+	if (edata.data &&
 	    !(dev->features & NETIF_F_ALL_CSUM))
 		return -EINVAL;
 
@@ -951,7 +951,7 @@
 	default:
 		rc =  -EOPNOTSUPP;
 	}
-	
+
 	if(dev->ethtool_ops->complete)
 		dev->ethtool_ops->complete(dev);
 
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 1df6cd45..215f1bff 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -331,7 +331,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags);
 	if (nlh == NULL)
-		return -1;
+		return -EMSGSIZE;
 
 	frh = nlmsg_data(nlh);
 	frh->table = rule->table;
@@ -359,7 +359,8 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family)
@@ -405,9 +406,12 @@
 		goto errout;
 
 	err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
-	/* failure implies BUG in fib_rule_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in fib_rule_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
 errout:
 	if (err < 0)
diff --git a/net/core/filter.c b/net/core/filter.c
index 0df843b..8d185a08 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -18,7 +18,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/fcntl.h>
 #include <linux/socket.h>
@@ -53,7 +52,7 @@
 }
 
 static inline void *load_pointer(struct sk_buff *skb, int k,
-                                 unsigned int size, void *buffer)
+				 unsigned int size, void *buffer)
 {
 	if (k >= 0)
 		return skb_header_pointer(skb, k, size, buffer);
@@ -91,7 +90,7 @@
 	 */
 	for (pc = 0; pc < flen; pc++) {
 		fentry = &filter[pc];
-			
+
 		switch (fentry->code) {
 		case BPF_ALU|BPF_ADD|BPF_X:
 			A += X;
@@ -399,7 +398,7 @@
  */
 int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
 {
-	struct sk_filter *fp; 
+	struct sk_filter *fp;
 	unsigned int fsize = sizeof(struct sock_filter) * fprog->len;
 	int err;
 
@@ -411,7 +410,7 @@
 	if (!fp)
 		return -ENOMEM;
 	if (copy_from_user(fp->insns, fprog->filter, fsize)) {
-		sock_kfree_s(sk, fp, fsize+sizeof(*fp)); 
+		sock_kfree_s(sk, fp, fsize+sizeof(*fp));
 		return -EFAULT;
 	}
 
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index 3cad026..17daf4c 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -144,7 +144,7 @@
  * configuration TLV is created. Upon each interval, the latest statistics
  * will be read from &bstats and the estimated rate will be stored in
  * &rate_est with the statistics lock grabed during this period.
- * 
+ *
  * Returns 0 on success or a negative error code.
  */
 int gen_new_estimator(struct gnet_stats_basic *bstats,
@@ -231,7 +231,7 @@
  *
  * Replaces the configuration of a rate estimator by calling
  * gen_kill_estimator() and gen_new_estimator().
- * 
+ *
  * Returns 0 on success or a negative error code.
  */
 int
@@ -242,7 +242,7 @@
     gen_kill_estimator(bstats, rate_est);
     return gen_new_estimator(bstats, rate_est, stats_lock, opt);
 }
-    
+
 
 EXPORT_SYMBOL(gen_kill_estimator);
 EXPORT_SYMBOL(gen_new_estimator);
diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c
index 8f214903..259473d 100644
--- a/net/core/gen_stats.c
+++ b/net/core/gen_stats.c
@@ -57,7 +57,7 @@
 	int xstats_type, spinlock_t *lock, struct gnet_dump *d)
 {
 	memset(d, 0, sizeof(*d));
-	
+
 	spin_lock_bh(lock);
 	d->lock = lock;
 	if (type)
diff --git a/net/core/iovec.c b/net/core/iovec.c
index 04b249c..755c37f 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -18,7 +18,6 @@
 
 #include <linux/errno.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
@@ -40,7 +39,7 @@
 int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
 {
 	int size, err, ct;
-	
+
 	if (m->msg_namelen) {
 		if (mode == VERIFY_READ) {
 			err = move_addr_to_kernel(m->msg_name, m->msg_namelen,
@@ -79,7 +78,7 @@
  *
  *	Note: this modifies the original iovec.
  */
- 
+
 int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
 {
 	while (len > 0) {
@@ -103,7 +102,7 @@
  *
  *	Note: this modifies the original iovec.
  */
- 
+
 int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
 {
 	while (len > 0) {
@@ -209,7 +208,7 @@
 			if (partial_cnt) {
 				copy -= partial_cnt;
 				if (copy_from_user(kdata + copy, base + copy,
-				 		partial_cnt))
+						partial_cnt))
 					goto out_fault;
 			}
 		}
@@ -224,7 +223,7 @@
 		kdata += copy + partial_cnt;
 		iov++;
 	}
-        *csump = csum;
+	*csump = csum;
 out:
 	return err;
 
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index 549a2ce..8b45c9d 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -124,7 +124,7 @@
 
 		dev_put(dev);
 	}
-}       
+}
 
 
 static void linkwatch_event(struct work_struct *dummy)
@@ -133,7 +133,7 @@
 	 * per second so that a runaway driver does not
 	 * cause a storm of messages on the netlink
 	 * socket
-	 */	
+	 */
 	linkwatch_nextevent = jiffies + HZ;
 	clear_bit(LW_RUNNING, &linkwatch_flags);
 
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index e7300b6..3183142 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/socket.h>
-#include <linux/sched.h>
 #include <linux/netdevice.h>
 #include <linux/proc_fs.h>
 #ifdef CONFIG_SYSCTL
@@ -63,7 +62,7 @@
 
 static struct neigh_table *neigh_tables;
 #ifdef CONFIG_PROC_FS
-static struct file_operations neigh_stat_seq_fops;
+static const struct file_operations neigh_stat_seq_fops;
 #endif
 
 /*
@@ -251,12 +250,10 @@
 			goto out_entries;
 	}
 
-	n = kmem_cache_alloc(tbl->kmem_cachep, GFP_ATOMIC);
+	n = kmem_cache_zalloc(tbl->kmem_cachep, GFP_ATOMIC);
 	if (!n)
 		goto out_entries;
 
-	memset(n, 0, tbl->entry_size);
-
 	skb_queue_head_init(&n->arp_queue);
 	rwlock_init(&n->lock);
 	n->updated	  = n->used = now;
@@ -345,7 +342,7 @@
 	struct neighbour *n;
 	int key_len = tbl->key_len;
 	u32 hash_val = tbl->hash(pkey, dev);
-	
+
 	NEIGH_CACHE_STAT_INC(tbl, lookups);
 
 	read_lock_bh(&tbl->lock);
@@ -687,16 +684,19 @@
 		np = &n->next;
 	}
 
- 	/* Cycle through all hash buckets every base_reachable_time/2 ticks.
- 	 * ARP entry timeouts range from 1/2 base_reachable_time to 3/2
- 	 * base_reachable_time.
+	/* Cycle through all hash buckets every base_reachable_time/2 ticks.
+	 * ARP entry timeouts range from 1/2 base_reachable_time to 3/2
+	 * base_reachable_time.
 	 */
 	expire = tbl->parms.base_reachable_time >> 1;
 	expire /= (tbl->hash_mask + 1);
 	if (!expire)
 		expire = 1;
 
- 	mod_timer(&tbl->gc_timer, now + expire);
+	if (expire>HZ)
+		mod_timer(&tbl->gc_timer, round_jiffies(now + expire));
+	else
+		mod_timer(&tbl->gc_timer, now + expire);
 
 	write_unlock(&tbl->lock);
 }
@@ -741,7 +741,7 @@
 	}
 
 	if (state & NUD_REACHABLE) {
-		if (time_before_eq(now, 
+		if (time_before_eq(now,
 				   neigh->confirmed + neigh->parms->reachable_time)) {
 			NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
 			next = neigh->confirmed + neigh->parms->reachable_time;
@@ -760,7 +760,7 @@
 			notify = 1;
 		}
 	} else if (state & NUD_DELAY) {
-		if (time_before_eq(now, 
+		if (time_before_eq(now,
 				   neigh->confirmed + neigh->parms->delay_probe_time)) {
 			NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh);
 			neigh->nud_state = NUD_REACHABLE;
@@ -846,7 +846,7 @@
 		goto out_unlock_bh;
 
 	now = jiffies;
-	
+
 	if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
 		if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
 			atomic_set(&neigh->probes, neigh->parms->ucast_probes);
@@ -914,13 +914,13 @@
 	NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
 				if it is different.
 	NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
-				lladdr instead of overriding it 
+				lladdr instead of overriding it
 				if it is different.
 				It also allows to retain current state
 				if lladdr is unchanged.
 	NEIGH_UPDATE_F_ADMIN	means that the change is administrative.
 
-	NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing 
+	NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
 				NTF_ROUTER flag.
 	NEIGH_UPDATE_F_ISROUTER	indicates if the neighbour is known as
 				a router.
@@ -943,7 +943,7 @@
 	old    = neigh->nud_state;
 	err    = -EPERM;
 
-	if (!(flags & NEIGH_UPDATE_F_ADMIN) && 
+	if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
 	    (old & (NUD_NOARP | NUD_PERMANENT)))
 		goto out;
 
@@ -967,7 +967,7 @@
 		   - compare new & old
 		   - if they are different, check override flag
 		 */
-		if ((old & NUD_VALID) && 
+		if ((old & NUD_VALID) &&
 		    !memcmp(lladdr, neigh->ha, dev->addr_len))
 			lladdr = neigh->ha;
 	} else {
@@ -1011,8 +1011,8 @@
 		neigh_del_timer(neigh);
 		if (new & NUD_IN_TIMER) {
 			neigh_hold(neigh);
-			neigh_add_timer(neigh, (jiffies + 
-						((new & NUD_REACHABLE) ? 
+			neigh_add_timer(neigh, (jiffies +
+						((new & NUD_REACHABLE) ?
 						 neigh->parms->reachable_time :
 						 0)));
 		}
@@ -1074,7 +1074,7 @@
 	struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
 						 lladdr || !dev->addr_len);
 	if (neigh)
-		neigh_update(neigh, lladdr, NUD_STALE, 
+		neigh_update(neigh, lladdr, NUD_STALE,
 			     NEIGH_UPDATE_F_OVERRIDE);
 	return neigh;
 }
@@ -1126,7 +1126,7 @@
 
 	if (dev->hard_header &&
 	    dev->hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
-		    	     skb->len) < 0 &&
+			     skb->len) < 0 &&
 	    dev->rebuild_header(skb))
 		return 0;
 
@@ -1346,10 +1346,10 @@
 	tbl->stats = alloc_percpu(struct neigh_statistics);
 	if (!tbl->stats)
 		panic("cannot create neighbour cache statistics");
-	
+
 #ifdef CONFIG_PROC_FS
 	tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat);
-	if (!tbl->pde) 
+	if (!tbl->pde)
 		panic("cannot create neighbour proc dir entry");
 	tbl->pde->proc_fops = &neigh_stat_seq_fops;
 	tbl->pde->data = tbl;
@@ -1564,7 +1564,7 @@
 				err = -ENOENT;
 				goto out_dev_put;
 			}
-	
+
 			neigh = __neigh_lookup_errno(tbl, dst, dev);
 			if (IS_ERR(neigh)) {
 				err = PTR_ERR(neigh);
@@ -1637,7 +1637,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ndtmsg = nlmsg_data(nlh);
 
@@ -1706,7 +1706,8 @@
 
 nla_put_failure:
 	read_unlock_bh(&tbl->lock);
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static int neightbl_fill_param_info(struct sk_buff *skb,
@@ -1720,7 +1721,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ndtmsg = nlmsg_data(nlh);
 
@@ -1737,14 +1738,15 @@
 	return nlmsg_end(skb, nlh);
 errout:
 	read_unlock_bh(&tbl->lock);
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
- 
+
 static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
 						      int ifindex)
 {
 	struct neigh_parms *p;
-	
+
 	for (p = &tbl->parms; p; p = p->next)
 		if ((p->dev && p->dev->ifindex == ifindex) ||
 		    (!p->dev && !ifindex))
@@ -1810,7 +1812,7 @@
 		goto errout_locked;
 	}
 
-	/* 
+	/*
 	 * We acquire tbl->lock to be nice to the periodic timers and
 	 * make sure they always see a consistent set of values.
 	 */
@@ -1955,7 +1957,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ndm = nlmsg_data(nlh);
 	ndm->ndm_family	 = neigh->ops->family;
@@ -1987,7 +1989,8 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 
@@ -2317,7 +2320,7 @@
 
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
-	
+
 	for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
 		if (!cpu_possible(cpu))
 			continue;
@@ -2399,7 +2402,7 @@
 	return ret;
 };
 
-static struct file_operations neigh_stat_seq_fops = {
+static const struct file_operations neigh_stat_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open 	 = neigh_stat_seq_open,
 	.read	 = seq_read,
@@ -2429,9 +2432,12 @@
 		goto errout;
 
 	err = neigh_fill_info(skb, n, 0, 0, type, flags);
-	/* failure implies BUG in neigh_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
 errout:
 	if (err < 0)
@@ -2622,7 +2628,7 @@
 };
 
 int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
-			  int p_id, int pdev_id, char *p_name, 
+			  int p_id, int pdev_id, char *p_name,
 			  proc_handler *handler, ctl_handler *strategy)
 {
 	struct neigh_sysctl_table *t = kmemdup(&neigh_sysctl_template,
@@ -2654,7 +2660,7 @@
 		t->neigh_vars[14].procname = NULL;
 		t->neigh_vars[15].procname = NULL;
 	} else {
- 		dev_name_source = t->neigh_dev[0].procname;
+		dev_name_source = t->neigh_dev[0].procname;
 		t->neigh_vars[12].data = (int *)(p + 1);
 		t->neigh_vars[13].data = (int *)(p + 1) + 1;
 		t->neigh_vars[14].data = (int *)(p + 1) + 2;
@@ -2689,7 +2695,7 @@
 		goto free;
 	}
 
- 	t->neigh_dev[0].procname = dev_name;
+	t->neigh_dev[0].procname = dev_name;
 
 	t->neigh_neigh_dir[0].ctl_name = pdev_id;
 
@@ -2701,7 +2707,7 @@
 	t->neigh_proto_dir[0].child    = t->neigh_neigh_dir;
 	t->neigh_root_dir[0].child     = t->neigh_proto_dir;
 
-	t->sysctl_header = register_sysctl_table(t->neigh_root_dir, 0);
+	t->sysctl_header = register_sysctl_table(t->neigh_root_dir);
 	if (!t->sysctl_header) {
 		err = -ENOBUFS;
 		goto free_procname;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 44db095..4cbb129 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -2,7 +2,7 @@
  * net-sysfs.c - network device class and attributes
  *
  * Copyright (c) 2003 Stephen Hemminger <shemminger@osdl.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
@@ -23,7 +23,7 @@
 static const char fmt_dec[] = "%d\n";
 static const char fmt_ulong[] = "%lu\n";
 
-static inline int dev_isalive(const struct net_device *dev) 
+static inline int dev_isalive(const struct net_device *dev)
 {
 	return dev->reg_state <= NETREG_REGISTERED;
 }
@@ -265,7 +265,7 @@
 
 	read_lock(&dev_base_lock);
 	if (dev_isalive(dev) && dev->get_stats &&
-	    (stats = (*dev->get_stats)(dev))) 
+	    (stats = (*dev->get_stats)(dev)))
 		ret = sprintf(buf, fmt_ulong,
 			      *(unsigned long *)(((u8 *) stats) + offset));
 
@@ -340,7 +340,7 @@
 	.attrs  = netstat_attrs,
 };
 
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
 /* helper function that does all the locking etc for wireless stats */
 static ssize_t wireless_show(struct device *d, char *buf,
 			     ssize_t (*format)(const struct iw_statistics *,
@@ -349,7 +349,7 @@
 	struct net_device *dev = to_net_dev(d);
 	const struct iw_statistics *iw = NULL;
 	ssize_t ret = -EINVAL;
-	
+
 	read_lock(&dev_base_lock);
 	if (dev_isalive(dev)) {
 		if(dev->wireless_handlers &&
@@ -430,7 +430,7 @@
 #endif
 
 /*
- *	netdev_release -- destroy and free a dead device. 
+ *	netdev_release -- destroy and free a dead device.
  *	Called when last reference to device kobject is gone.
  */
 static void netdev_release(struct device *d)
@@ -473,7 +473,7 @@
 	if (net->get_stats)
 		*groups++ = &netstat_group;
 
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
 	if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
 		*groups++ = &wireless_group;
 #endif
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 823215d..da10194 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -237,13 +237,13 @@
 {
 	int status = NETDEV_TX_BUSY;
 	unsigned long tries;
- 	struct net_device *dev = np->dev;
- 	struct netpoll_info *npinfo = np->dev->npinfo;
+	struct net_device *dev = np->dev;
+	struct netpoll_info *npinfo = np->dev->npinfo;
 
- 	if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) {
- 		__kfree_skb(skb);
- 		return;
- 	}
+	if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) {
+		__kfree_skb(skb);
+		return;
+	}
 
 	/* don't get messages out of order, and no recursion */
 	if (skb_queue_len(&npinfo->txq) == 0 &&
@@ -676,7 +676,7 @@
 		}
 
 		atleast = jiffies + HZ/10;
- 		atmost = jiffies + 4*HZ;
+		atmost = jiffies + 4*HZ;
 		while (!netif_carrier_ok(ndev)) {
 			if (time_after(jiffies, atmost)) {
 				printk(KERN_NOTICE
@@ -772,9 +772,9 @@
 			np->dev->npinfo = NULL;
 			if (atomic_dec_and_test(&npinfo->refcnt)) {
 				skb_queue_purge(&npinfo->arp_tx);
- 				skb_queue_purge(&npinfo->txq);
+				skb_queue_purge(&npinfo->txq);
 				cancel_rearming_delayed_work(&npinfo->tx_work);
- 				flush_scheduled_work();
+				flush_scheduled_work();
 
 				kfree(npinfo);
 			}
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 04d4b93..74a9a32 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -15,7 +15,7 @@
  *
  *
  * A tool for loading the network with preconfigurated packets.
- * The tool is implemented as a linux module.  Parameters are output 
+ * The tool is implemented as a linux module.  Parameters are output
  * device, delay (to hard_xmit), number of packets, and whether
  * to use multiple SKBs or just the same one.
  * pktgen uses the installed interface's output routine.
@@ -44,14 +44,14 @@
  *   *  Add IOCTL interface to easily get counters & configuration.
  *   --Ben Greear <greearb@candelatech.com>
  *
- * Renamed multiskb to clone_skb and cleaned up sending core for two distinct 
- * skb modes. A clone_skb=0 mode for Ben "ranges" work and a clone_skb != 0 
+ * Renamed multiskb to clone_skb and cleaned up sending core for two distinct
+ * skb modes. A clone_skb=0 mode for Ben "ranges" work and a clone_skb != 0
  * as a "fastpath" with a configurable number of clones after alloc's.
- * clone_skb=0 means all packets are allocated this also means ranges time 
- * stamps etc can be used. clone_skb=100 means 1 malloc is followed by 100 
+ * clone_skb=0 means all packets are allocated this also means ranges time
+ * stamps etc can be used. clone_skb=100 means 1 malloc is followed by 100
  * clones.
  *
- * Also moved to /proc/net/pktgen/ 
+ * Also moved to /proc/net/pktgen/
  * --ro
  *
  * Sept 10:  Fixed threading/locking.  Lots of bone-headed and more clever
@@ -60,28 +60,28 @@
  *
  * Integrated to 2.5.x 021029 --Lucio Maciel (luciomaciel@zipmail.com.br)
  *
- * 
+ *
  * 021124 Finished major redesign and rewrite for new functionality.
  * See Documentation/networking/pktgen.txt for how to use this.
  *
  * The new operation:
- * For each CPU one thread/process is created at start. This process checks 
- * for running devices in the if_list and sends packets until count is 0 it 
- * also the thread checks the thread->control which is used for inter-process 
- * communication. controlling process "posts" operations to the threads this 
+ * For each CPU one thread/process is created at start. This process checks
+ * for running devices in the if_list and sends packets until count is 0 it
+ * also the thread checks the thread->control which is used for inter-process
+ * communication. controlling process "posts" operations to the threads this
  * way. The if_lock should be possible to remove when add/rem_device is merged
  * into this too.
  *
- * By design there should only be *one* "controlling" process. In practice 
- * multiple write accesses gives unpredictable result. Understood by "write" 
+ * By design there should only be *one* "controlling" process. In practice
+ * multiple write accesses gives unpredictable result. Understood by "write"
  * to /proc gives result code thats should be read be the "writer".
  * For practical use this should be no problem.
  *
- * Note when adding devices to a specific CPU there good idea to also assign 
- * /proc/irq/XX/smp_affinity so TX-interrupts gets bound to the same CPU. 
+ * Note when adding devices to a specific CPU there good idea to also assign
+ * /proc/irq/XX/smp_affinity so TX-interrupts gets bound to the same CPU.
  * --ro
  *
- * Fix refcount off by one if first packet fails, potential null deref, 
+ * Fix refcount off by one if first packet fails, potential null deref,
  * memleak 030710- KJP
  *
  * First "ranges" functionality for ipv6 030726 --ro
@@ -89,22 +89,22 @@
  * Included flow support. 030802 ANK.
  *
  * Fixed unaligned access on IA-64 Grant Grundler <grundler@parisc-linux.org>
- * 
+ *
  * Remove if fix from added Harald Welte <laforge@netfilter.org> 040419
  * ia64 compilation fix from  Aron Griffis <aron@hp.com> 040604
  *
- * New xmit() return, do_div and misc clean up by Stephen Hemminger 
+ * New xmit() return, do_div and misc clean up by Stephen Hemminger
  * <shemminger@osdl.org> 040923
  *
- * Randy Dunlap fixed u64 printk compiler waring 
+ * Randy Dunlap fixed u64 printk compiler waring
  *
  * Remove FCS from BW calculation.  Lennert Buytenhek <buytenh@wantstofly.org>
  * New time handling. Lennert Buytenhek <buytenh@wantstofly.org> 041213
  *
- * Corrections from Nikolai Malykh (nmalykh@bilim.com) 
+ * Corrections from Nikolai Malykh (nmalykh@bilim.com)
  * Removed unused flags F_SET_SRCMAC & F_SET_SRCIP 041230
  *
- * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com> 
+ * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com>
  * 050103
  *
  * MPLS support by Steven Whitehouse <steve@chygwyn.com>
@@ -456,7 +456,7 @@
 /*
  * How do we know if the architecture we are running on
  * supports division with 64 bit base?
- * 
+ *
  */
 #if defined(__sparc_v9__) || defined(__powerpc64__) || defined(__alpha__) || defined(__x86_64__) || defined(__ia64__)
 
@@ -529,7 +529,7 @@
 };
 
 /*
- * /proc handling functions 
+ * /proc handling functions
  *
  */
 
@@ -579,7 +579,7 @@
 	return single_open(file, pgctrl_show, PDE(inode)->data);
 }
 
-static struct file_operations pktgen_fops = {
+static const struct file_operations pktgen_fops = {
 	.owner   = THIS_MODULE,
 	.open    = pgctrl_open,
 	.read    = seq_read,
@@ -1672,7 +1672,7 @@
 	return single_open(file, pktgen_if_show, PDE(inode)->data);
 }
 
-static struct file_operations pktgen_if_fops = {
+static const struct file_operations pktgen_if_fops = {
 	.owner   = THIS_MODULE,
 	.open    = pktgen_if_open,
 	.read    = seq_read,
@@ -1815,7 +1815,7 @@
 	return single_open(file, pktgen_thread_show, PDE(inode)->data);
 }
 
-static struct file_operations pktgen_thread_fops = {
+static const struct file_operations pktgen_thread_fops = {
 	.owner   = THIS_MODULE,
 	.open    = pktgen_thread_open,
 	.read    = seq_read,
@@ -1979,7 +1979,7 @@
 
 	if (pkt_dev->flags & F_IPV6) {
 		/*
-		 * Skip this automatic address setting until locks or functions 
+		 * Skip this automatic address setting until locks or functions
 		 * gets exported
 		 */
 
@@ -2477,10 +2477,10 @@
 }
 
 /*
- * scan_ip6, fmt_ip taken from dietlibc-0.21 
+ * scan_ip6, fmt_ip taken from dietlibc-0.21
  * Author Felix von Leitner <felix-dietlibc@fefe.de>
  *
- * Slightly modified for kernel. 
+ * Slightly modified for kernel.
  * Should be candidate for net/ipv4/utils.c
  * --ro
  */
@@ -3256,7 +3256,7 @@
 out:;
 }
 
-/* 
+/*
  * Main loop of the thread goes here
  */
 
@@ -3365,8 +3365,8 @@
 	return pkt_dev;
 }
 
-/* 
- * Adds a dev at front of if_list. 
+/*
+ * Adds a dev at front of if_list.
  */
 
 static int add_dev_to_thread(struct pktgen_thread *t,
@@ -3510,8 +3510,8 @@
 	return 0;
 }
 
-/* 
- * Removes a device from the thread if_list. 
+/*
+ * Removes a device from the thread if_list.
  */
 static void _rem_dev_from_if_list(struct pktgen_thread *t,
 				  struct pktgen_dev *pkt_dev)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index e76539a..6055074 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -21,7 +21,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -320,7 +319,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ifm = nlmsg_data(nlh);
 	ifm->ifi_family = AF_UNSPEC;
@@ -384,7 +383,8 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
@@ -633,9 +633,12 @@
 
 	err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
 			       NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
-	/* failure impilies BUG in if_nlmsg_size or wireless_rtnetlink_get */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in if_nlmsg_size */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(nskb);
+		goto errout;
+	}
 	err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
 errout:
 	kfree(iw_buf);
@@ -678,9 +681,12 @@
 		goto errout;
 
 	err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
-	/* failure implies BUG in if_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in if_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
 errout:
 	if (err < 0)
@@ -867,7 +873,7 @@
 		panic("rtnetlink_init: cannot allocate rta_buf\n");
 
 	rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv,
-	                             THIS_MODULE);
+				     THIS_MODULE);
 	if (rtnl == NULL)
 		panic("rtnetlink_init: cannot initialize rtnetlink\n");
 	netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
diff --git a/net/core/scm.c b/net/core/scm.c
index 271cf06..292ad8d 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -36,7 +36,7 @@
 
 
 /*
- *	Only allow a user to send credentials, that they could set with 
+ *	Only allow a user to send credentials, that they could set with
  *	setu(g)id.
  */
 
@@ -79,11 +79,11 @@
 
 	if (fpl->count + num > SCM_MAX_FD)
 		return -EINVAL;
-	
+
 	/*
 	 *	Verify the descriptors and increment the usage count.
 	 */
-	 
+
 	for (i=0; i< num; i++)
 	{
 		int fd = fdp[i];
@@ -123,7 +123,7 @@
 		/* The first check was omitted in <= 2.2.5. The reasoning was
 		   that parser checks cmsg_len in any case, so that
 		   additional check would be work duplication.
-		   But if cmsg_level is not SOL_SOCKET, we do not check 
+		   But if cmsg_level is not SOL_SOCKET, we do not check
 		   for too short ancillary data object at all! Oops.
 		   OK, let's add it...
 		 */
@@ -159,7 +159,7 @@
 		p->fp = NULL;
 	}
 	return 0;
-	
+
 error:
 	scm_destroy(p);
 	return err;
@@ -189,7 +189,7 @@
 
 	err = -EFAULT;
 	if (copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		goto out; 
+		goto out;
 	if (copy_to_user(CMSG_DATA(cm), data, cmlen - sizeof(struct cmsghdr)))
 		goto out;
 	cmlen = CMSG_SPACE(len);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f3404ae..f89ff15 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -41,7 +41,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
@@ -88,7 +87,7 @@
 void skb_over_panic(struct sk_buff *skb, int sz, void *here)
 {
 	printk(KERN_EMERG "skb_over_panic: text:%p len:%d put:%d head:%p "
-	                  "data:%p tail:%p end:%p dev:%s\n",
+			  "data:%p tail:%p end:%p dev:%s\n",
 	       here, skb->len, sz, skb->head, skb->data, skb->tail, skb->end,
 	       skb->dev ? skb->dev->name : "<NULL>");
 	BUG();
@@ -106,7 +105,7 @@
 void skb_under_panic(struct sk_buff *skb, int sz, void *here)
 {
 	printk(KERN_EMERG "skb_under_panic: text:%p len:%d put:%d head:%p "
-	                  "data:%p tail:%p end:%p dev:%s\n",
+			  "data:%p tail:%p end:%p dev:%s\n",
 	       here, skb->len, sz, skb->head, skb->data, skb->tail, skb->end,
 	       skb->dev ? skb->dev->name : "<NULL>");
 	BUG();
@@ -271,7 +270,7 @@
 	int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
 	struct sk_buff *skb;
 
- 	skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node);
+	skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node);
 	if (likely(skb)) {
 		skb_reserve(skb, NET_SKB_PAD);
 		skb->dev = dev;
@@ -819,12 +818,12 @@
  *
  *	May return error in out of memory cases. The skb is freed on error.
  */
- 
+
 int skb_pad(struct sk_buff *skb, int pad)
 {
 	int err;
 	int ntail;
-	
+
 	/* If the skbuff is non linear tailroom is always zero.. */
 	if (!skb_cloned(skb) && skb_tailroom(skb) >= pad) {
 		memset(skb->data+skb->len, 0, pad);
@@ -851,8 +850,8 @@
 free_skb:
 	kfree_skb(skb);
 	return err;
-}	
- 
+}
+
 /* Trims skb to length len. It can change skb pointers.
  */
 
diff --git a/net/core/sock.c b/net/core/sock.c
index 0ed5b4f..e9986ac 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -34,7 +34,7 @@
  *		Alan Cox	:	TCP ack handling is buggy, the DESTROY timer
  *					was buggy. Put a remove_sock() in the handler
  *					for memory when we hit 0. Also altered the timer
- *					code. The ACK stuff can wait and needs major 
+ *					code. The ACK stuff can wait and needs major
  *					TCP layer surgery.
  *		Alan Cox	:	Fixed TCP ack bug, removed remove sock
  *					and fixed timer/inet_bh race.
@@ -217,8 +217,8 @@
 {
 	static int warned;
 	static char warncomm[TASK_COMM_LEN];
-	if (strcmp(warncomm, current->comm) && warned < 5) { 
-		strcpy(warncomm,  current->comm); 
+	if (strcmp(warncomm, current->comm) && warned < 5) {
+		strcpy(warncomm,  current->comm);
 		printk(KERN_WARNING "process `%s' is using obsolete "
 		       "%s SO_BSDCOMPAT\n", warncomm, name);
 		warned++;
@@ -226,8 +226,8 @@
 }
 
 static void sock_disable_timestamp(struct sock *sk)
-{	
-	if (sock_flag(sk, SOCK_TIMESTAMP)) { 
+{
+	if (sock_flag(sk, SOCK_TIMESTAMP)) {
 		sock_reset_flag(sk, SOCK_TIMESTAMP);
 		net_disable_timestamp();
 	}
@@ -347,7 +347,7 @@
 	int valbool;
 	struct linger ling;
 	int ret = 0;
-	
+
 	/*
 	 *	Options without arguments
 	 */
@@ -360,20 +360,20 @@
 		return 0;
 	}
 #endif
-	
-  	if(optlen<sizeof(int))
-  		return(-EINVAL);
-  	
+
+	if(optlen<sizeof(int))
+		return(-EINVAL);
+
 	if (get_user(val, (int __user *)optval))
 		return -EFAULT;
-	
-  	valbool = val?1:0;
+
+	valbool = val?1:0;
 
 	lock_sock(sk);
 
-  	switch(optname) 
-  	{
-		case SO_DEBUG:	
+	switch(optname)
+	{
+		case SO_DEBUG:
 			if(val && !capable(CAP_NET_ADMIN))
 			{
 				ret = -EACCES;
@@ -389,7 +389,7 @@
 		case SO_TYPE:
 		case SO_ERROR:
 			ret = -ENOPROTOOPT;
-		  	break;
+			break;
 		case SO_DONTROUTE:
 			if (valbool)
 				sock_set_flag(sk, SOCK_LOCALROUTE);
@@ -404,7 +404,7 @@
 			   about it this is right. Otherwise apps have to
 			   play 'guess the biggest size' games. RCVBUF/SNDBUF
 			   are treated in BSD as hints */
-			   
+
 			if (val > sysctl_wmem_max)
 				val = sysctl_wmem_max;
 set_sndbuf:
@@ -433,7 +433,7 @@
 			   about it this is right. Otherwise apps have to
 			   play 'guess the biggest size' games. RCVBUF/SNDBUF
 			   are treated in BSD as hints */
-			  
+
 			if (val > sysctl_rmem_max)
 				val = sysctl_rmem_max;
 set_rcvbuf:
@@ -474,16 +474,16 @@
 			sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
 			break;
 
-	 	case SO_OOBINLINE:
+		case SO_OOBINLINE:
 			sock_valbool_flag(sk, SOCK_URGINLINE, valbool);
 			break;
 
-	 	case SO_NO_CHECK:
+		case SO_NO_CHECK:
 			sk->sk_no_check = valbool;
 			break;
 
 		case SO_PRIORITY:
-			if ((val >= 0 && val <= 6) || capable(CAP_NET_ADMIN)) 
+			if ((val >= 0 && val <= 6) || capable(CAP_NET_ADMIN))
 				sk->sk_priority = val;
 			else
 				ret = -EPERM;
@@ -547,9 +547,9 @@
 #ifdef CONFIG_NETDEVICES
 		case SO_BINDTODEVICE:
 		{
-			char devname[IFNAMSIZ]; 
+			char devname[IFNAMSIZ];
 
-			/* Sorry... */ 
+			/* Sorry... */
 			if (!capable(CAP_NET_RAW)) {
 				ret = -EPERM;
 				break;
@@ -557,9 +557,9 @@
 
 			/* Bind this socket to a particular device like "eth0",
 			 * as specified in the passed interface name. If the
-			 * name is "" or the option length is zero the socket 
-			 * is not bound. 
-			 */ 
+			 * name is "" or the option length is zero the socket
+			 * is not bound.
+			 */
 
 			if (!valbool) {
 				sk->sk_bound_dev_if = 0;
@@ -608,7 +608,7 @@
 		case SO_DETACH_FILTER:
 			rcu_read_lock_bh();
 			filter = rcu_dereference(sk->sk_filter);
-                        if (filter) {
+			if (filter) {
 				rcu_assign_pointer(sk->sk_filter, NULL);
 				sk_filter_release(sk, filter);
 				rcu_read_unlock_bh();
@@ -628,9 +628,9 @@
 		/* We implement the SO_SNDLOWAT etc to
 		   not be settable (1003.1g 5.3) */
 		default:
-		  	ret = -ENOPROTOOPT;
+			ret = -ENOPROTOOPT;
 			break;
-  	}
+	}
 	release_sock(sk);
 	return ret;
 }
@@ -640,32 +640,32 @@
 		    char __user *optval, int __user *optlen)
 {
 	struct sock *sk = sock->sk;
-	
+
 	union
 	{
-  		int val;
-  		struct linger ling;
+		int val;
+		struct linger ling;
 		struct timeval tm;
 	} v;
-	
+
 	unsigned int lv = sizeof(int);
 	int len;
-  	
-  	if(get_user(len,optlen))
-  		return -EFAULT;
+
+	if(get_user(len,optlen))
+		return -EFAULT;
 	if(len < 0)
 		return -EINVAL;
-		
-  	switch(optname) 
-  	{
-		case SO_DEBUG:		
+
+	switch(optname)
+	{
+		case SO_DEBUG:
 			v.val = sock_flag(sk, SOCK_DBG);
 			break;
-		
+
 		case SO_DONTROUTE:
 			v.val = sock_flag(sk, SOCK_LOCALROUTE);
 			break;
-		
+
 		case SO_BROADCAST:
 			v.val = !!sock_flag(sk, SOCK_BROADCAST);
 			break;
@@ -673,7 +673,7 @@
 		case SO_SNDBUF:
 			v.val = sk->sk_sndbuf;
 			break;
-		
+
 		case SO_RCVBUF:
 			v.val = sk->sk_rcvbuf;
 			break;
@@ -687,7 +687,7 @@
 			break;
 
 		case SO_TYPE:
-			v.val = sk->sk_type;		  		
+			v.val = sk->sk_type;
 			break;
 
 		case SO_ERROR:
@@ -699,7 +699,7 @@
 		case SO_OOBINLINE:
 			v.val = !!sock_flag(sk, SOCK_URGINLINE);
 			break;
-	
+
 		case SO_NO_CHECK:
 			v.val = sk->sk_no_check;
 			break;
@@ -707,13 +707,13 @@
 		case SO_PRIORITY:
 			v.val = sk->sk_priority;
 			break;
-		
-		case SO_LINGER:	
+
+		case SO_LINGER:
 			lv		= sizeof(v.ling);
 			v.ling.l_onoff	= !!sock_flag(sk, SOCK_LINGER);
- 			v.ling.l_linger	= sk->sk_lingertime / HZ;
+			v.ling.l_linger	= sk->sk_lingertime / HZ;
 			break;
-					
+
 		case SO_BSDCOMPAT:
 			sock_warn_obsolete_bsdism("getsockopt");
 			break;
@@ -750,7 +750,7 @@
 
 		case SO_SNDLOWAT:
 			v.val=1;
-			break; 
+			break;
 
 		case SO_PASSCRED:
 			v.val = test_bit(SOCK_PASSCRED, &sock->flags) ? 1 : 0;
@@ -798,9 +798,9 @@
 	if (copy_to_user(optval, &v, len))
 		return -EFAULT;
 lenout:
-  	if (put_user(len, optlen))
-  		return -EFAULT;
-  	return 0;
+	if (put_user(len, optlen))
+		return -EFAULT;
+	return 0;
 }
 
 /*
@@ -846,7 +846,7 @@
 			sk->sk_prot = sk->sk_prot_creator = prot;
 			sock_lock_init(sk);
 		}
-		
+
 		if (security_sk_alloc(sk, family, priority))
 			goto out_free;
 
@@ -988,8 +988,8 @@
  */
 
 
-/* 
- * Write buffer destructor automatically called from kfree_skb. 
+/*
+ * Write buffer destructor automatically called from kfree_skb.
  */
 void sock_wfree(struct sk_buff *skb)
 {
@@ -1002,8 +1002,8 @@
 	sock_put(sk);
 }
 
-/* 
- * Read buffer destructor automatically called from kfree_skb. 
+/*
+ * Read buffer destructor automatically called from kfree_skb.
  */
 void sock_rfree(struct sk_buff *skb)
 {
@@ -1051,7 +1051,7 @@
 
 /*
  * Allocate a skb from the socket's receive buffer.
- */ 
+ */
 struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force,
 			     gfp_t priority)
 {
@@ -1065,16 +1065,16 @@
 	return NULL;
 }
 
-/* 
+/*
  * Allocate a memory block from the socket's option memory buffer.
- */ 
+ */
 void *sock_kmalloc(struct sock *sk, int size, gfp_t priority)
 {
 	if ((unsigned)size <= sysctl_optmem_max &&
 	    atomic_read(&sk->sk_omem_alloc) + size < sysctl_optmem_max) {
 		void *mem;
 		/* First do the add, to avoid the race if kmalloc
- 		 * might sleep.
+		 * might sleep.
 		 */
 		atomic_add(size, &sk->sk_omem_alloc);
 		mem = kmalloc(size, priority);
@@ -1210,7 +1210,7 @@
 	return NULL;
 }
 
-struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, 
+struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
 				    int noblock, int *errcode)
 {
 	return sock_alloc_send_pskb(sk, size, 0, noblock, errcode);
@@ -1298,7 +1298,7 @@
 	return -EOPNOTSUPP;
 }
 
-int sock_no_connect(struct socket *sock, struct sockaddr *saddr, 
+int sock_no_connect(struct socket *sock, struct sockaddr *saddr,
 		    int len, int flags)
 {
 	return -EOPNOTSUPP;
@@ -1314,7 +1314,7 @@
 	return -EOPNOTSUPP;
 }
 
-int sock_no_getname(struct socket *sock, struct sockaddr *saddr, 
+int sock_no_getname(struct socket *sock, struct sockaddr *saddr,
 		    int *len, int peer)
 {
 	return -EOPNOTSUPP;
@@ -1400,7 +1400,7 @@
 	read_lock(&sk->sk_callback_lock);
 	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
 		wake_up_interruptible(sk->sk_sleep);
-	sk_wake_async(sk,0,POLL_ERR); 
+	sk_wake_async(sk,0,POLL_ERR);
 	read_unlock(&sk->sk_callback_lock);
 }
 
@@ -1473,7 +1473,7 @@
 	sk->sk_send_head	=	NULL;
 
 	init_timer(&sk->sk_timer);
-	
+
 	sk->sk_allocation	=	GFP_KERNEL;
 	sk->sk_rcvbuf		=	sysctl_rmem_default;
 	sk->sk_sndbuf		=	sysctl_wmem_default;
@@ -1553,26 +1553,26 @@
 EXPORT_SYMBOL(release_sock);
 
 int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp)
-{ 
+{
 	if (!sock_flag(sk, SOCK_TIMESTAMP))
 		sock_enable_timestamp(sk);
-	if (sk->sk_stamp.tv_sec == -1) 
+	if (sk->sk_stamp.tv_sec == -1)
 		return -ENOENT;
 	if (sk->sk_stamp.tv_sec == 0)
 		do_gettimeofday(&sk->sk_stamp);
 	return copy_to_user(userstamp, &sk->sk_stamp, sizeof(struct timeval)) ?
-		-EFAULT : 0; 
-} 
+		-EFAULT : 0;
+}
 EXPORT_SYMBOL(sock_get_timestamp);
 
 void sock_enable_timestamp(struct sock *sk)
-{	
-	if (!sock_flag(sk, SOCK_TIMESTAMP)) { 
+{
+	if (!sock_flag(sk, SOCK_TIMESTAMP)) {
 		sock_set_flag(sk, SOCK_TIMESTAMP);
 		net_enable_timestamp();
 	}
 }
-EXPORT_SYMBOL(sock_enable_timestamp); 
+EXPORT_SYMBOL(sock_enable_timestamp);
 
 /*
  *	Get a socket option on an socket.
@@ -1911,7 +1911,7 @@
 	return seq_open(file, &proto_seq_ops);
 }
 
-static struct file_operations proto_seq_fops = {
+static const struct file_operations proto_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= proto_seq_open,
 	.read		= seq_read,
diff --git a/net/core/stream.c b/net/core/stream.c
index d1d7dec..755bacb 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -69,7 +69,7 @@
 		sk->sk_write_pending++;
 		done = sk_wait_event(sk, timeo_p,
 				     !sk->sk_err &&
-				     !((1 << sk->sk_state) & 
+				     !((1 << sk->sk_state) &
 				       ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)));
 		finish_wait(sk->sk_sleep, &wait);
 		sk->sk_write_pending--;
@@ -139,7 +139,7 @@
 
 		set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 		sk->sk_write_pending++;
-		sk_wait_event(sk, &current_timeo, !sk->sk_err && 
+		sk_wait_event(sk, &current_timeo, !sk->sk_err &&
 						  !(sk->sk_shutdown & SEND_SHUTDOWN) &&
 						  sk_stream_memory_free(sk) &&
 						  vm_wait);
diff --git a/net/core/user_dma.c b/net/core/user_dma.c
index 248a6b6..0ad1cd5 100644
--- a/net/core/user_dma.c
+++ b/net/core/user_dma.c
@@ -58,7 +58,7 @@
 		if (copy > len)
 			copy = len;
 		cookie = dma_memcpy_to_iovec(chan, to, pinned_list,
-		                            skb->data + offset, copy);
+					    skb->data + offset, copy);
 		if (cookie < 0)
 			goto fault;
 		len -= copy;
@@ -108,8 +108,8 @@
 				if (copy > len)
 					copy = len;
 				cookie = dma_skb_copy_datagram_iovec(chan, list,
-				                offset - start, to, copy,
-				                pinned_list);
+						offset - start, to, copy,
+						pinned_list);
 				if (cookie < 0)
 					goto fault;
 				len -= copy;
@@ -128,5 +128,5 @@
 	}
 
 fault:
- 	return -EFAULT;
+	return -EFAULT;
 }
diff --git a/net/core/utils.c b/net/core/utils.c
index 6155606..07236c1 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -33,9 +33,9 @@
 int net_msg_cost = 5*HZ;
 int net_msg_burst = 10;
 
-/* 
+/*
  * All net warning printk()s should be guarded by this function.
- */ 
+ */
 int net_ratelimit(void)
 {
 	return __printk_ratelimit(net_msg_cost, net_msg_burst);
diff --git a/net/core/wireless.c b/net/core/wireless.c
index f69ab7b..9936ab1 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -369,7 +369,7 @@
 		.header_type	= IW_HEADER_TYPE_ADDR,
 	},
 	[IWEVEXPIRED	- IWEVFIRST] = {
-		.header_type	= IW_HEADER_TYPE_ADDR, 
+		.header_type	= IW_HEADER_TYPE_ADDR,
 	},
 	[IWEVGENIE	- IWEVFIRST] = {
 		.header_type	= IW_HEADER_TYPE_POINT,
@@ -377,7 +377,7 @@
 		.max_tokens	= IW_GENERIC_IE_MAX,
 	},
 	[IWEVMICHAELMICFAILURE	- IWEVFIRST] = {
-		.header_type	= IW_HEADER_TYPE_POINT, 
+		.header_type	= IW_HEADER_TYPE_POINT,
 		.token_size	= 1,
 		.max_tokens	= sizeof(struct iw_michaelmicfailure),
 	},
@@ -630,11 +630,11 @@
 			   dev->name, stats->status, stats->qual.qual,
 			   stats->qual.updated & IW_QUAL_QUAL_UPDATED
 			   ? '.' : ' ',
-			   ((__s32) stats->qual.level) - 
+			   ((__s32) stats->qual.level) -
 			   ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
 			   stats->qual.updated & IW_QUAL_LEVEL_UPDATED
 			   ? '.' : ' ',
-			   ((__s32) stats->qual.noise) - 
+			   ((__s32) stats->qual.noise) -
 			   ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
 			   stats->qual.updated & IW_QUAL_NOISE_UPDATED
 			   ? '.' : ' ',
@@ -674,7 +674,7 @@
 	return seq_open(file, &wireless_seq_ops);
 }
 
-static struct file_operations wireless_seq_fops = {
+static const struct file_operations wireless_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = wireless_seq_open,
 	.read    = seq_read,
@@ -862,7 +862,7 @@
 					   iwr->u.data.length *
 					   descr->token_size);
 			if (err)
-				ret =  -EFAULT;				   
+				ret =  -EFAULT;
 #ifdef WE_IOCTL_DEBUG
 			printk(KERN_DEBUG "%s (WE) : Wrote %d bytes\n",
 			       dev->name,
@@ -1040,7 +1040,7 @@
 			err = copy_to_user(iwr->u.data.pointer, extra,
 					   extra_size);
 			if (err)
-				ret =  -EFAULT;				   
+				ret =  -EFAULT;
 #ifdef WE_IOCTL_DEBUG
 			printk(KERN_DEBUG "%s (WE) : Wrote %d elem\n",
 			       dev->name, iwr->u.data.length);
@@ -1080,7 +1080,7 @@
 	/* A bunch of special cases, then the generic case...
 	 * Note that 'cmd' is already filtered in dev_ioctl() with
 	 * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
-	switch(cmd) 
+	switch(cmd)
 	{
 		case SIOCGIWSTATS:
 			/* Get Wireless Stats */
@@ -2015,7 +2015,7 @@
 		 * The best the driver could do is to log an error message.
 		 * We will do it ourselves instead...
 		 */
-	  	printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
+		printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
 		       dev->name, cmd);
 		return;
 	}
@@ -2029,11 +2029,11 @@
 	if(descr->header_type == IW_HEADER_TYPE_POINT) {
 		/* Check if number of token fits within bounds */
 		if(wrqu->data.length > descr->max_tokens) {
-		  	printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length);
+			printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length);
 			return;
 		}
 		if(wrqu->data.length < descr->min_tokens) {
-		  	printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length);
+			printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length);
 			return;
 		}
 		/* Calculate extra_len - extra is NULL for restricted events */
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index fd38b05..248d20f 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -139,7 +139,7 @@
 		return 0;
 	}
 
-        hctx = ccid2_hc_tx_sk(sk);
+	hctx = ccid2_hc_tx_sk(sk);
 
 	ccid2_pr_debug("pipe=%d cwnd=%d\n", hctx->ccid2hctx_pipe,
 		       hctx->ccid2hctx_cwnd);
@@ -368,13 +368,13 @@
 static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset,
 			   unsigned char **vec, unsigned char *veclen)
 {
-        const struct dccp_hdr *dh = dccp_hdr(skb);
-        unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
-        unsigned char *opt_ptr;
-        const unsigned char *opt_end = (unsigned char *)dh +
-                                        (dh->dccph_doff * 4);
-        unsigned char opt, len;
-        unsigned char *value;
+	const struct dccp_hdr *dh = dccp_hdr(skb);
+	unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
+	unsigned char *opt_ptr;
+	const unsigned char *opt_end = (unsigned char *)dh +
+					(dh->dccph_doff * 4);
+	unsigned char opt, len;
+	unsigned char *value;
 
 	BUG_ON(offset < 0);
 	options += offset;
@@ -383,29 +383,29 @@
 		return -1;
 
 	while (opt_ptr != opt_end) {
-                opt   = *opt_ptr++;
-                len   = 0;
-                value = NULL;
+		opt   = *opt_ptr++;
+		len   = 0;
+		value = NULL;
 
-                /* Check if this isn't a single byte option */
-                if (opt > DCCPO_MAX_RESERVED) {
-                        if (opt_ptr == opt_end)
-                                goto out_invalid_option;
+		/* Check if this isn't a single byte option */
+		if (opt > DCCPO_MAX_RESERVED) {
+			if (opt_ptr == opt_end)
+				goto out_invalid_option;
 
-                        len = *opt_ptr++;
-                        if (len < 3)
-                                goto out_invalid_option;
-                        /*
-                         * Remove the type and len fields, leaving
-                         * just the value size
-                         */
-                        len     -= 2;
-                        value   = opt_ptr;
-                        opt_ptr += len;
+			len = *opt_ptr++;
+			if (len < 3)
+				goto out_invalid_option;
+			/*
+			 * Remove the type and len fields, leaving
+			 * just the value size
+			 */
+			len     -= 2;
+			value   = opt_ptr;
+			opt_ptr += len;
 
-                        if (opt_ptr > opt_end)
-                                goto out_invalid_option;
-                }
+			if (opt_ptr > opt_end)
+				goto out_invalid_option;
+		}
 
 		switch (opt) {
 		case DCCPO_ACK_VECTOR_0:
@@ -432,7 +432,7 @@
 }
 
 static inline void ccid2_new_ack(struct sock *sk,
-			         struct ccid2_seq *seqp,
+				 struct ccid2_seq *seqp,
 				 unsigned int *maxincr)
 {
 	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
@@ -759,7 +759,7 @@
 
 static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
 {
-        struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);
+	struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);
 
 	ccid2_change_cwnd(hctx, 1);
 	/* Initialize ssthresh to infinity.  This means that we will exit the
@@ -793,7 +793,7 @@
 
 static void ccid2_hc_tx_exit(struct sock *sk)
 {
-        struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
+	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
 	int i;
 
 	ccid2_hc_tx_kill_rto_timer(sk);
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 40402c5..5361a4d 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -284,7 +284,7 @@
 
 restart_timer:
 	sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
-		           jiffies + usecs_to_jiffies(t_nfb));
+			   jiffies + usecs_to_jiffies(t_nfb));
 out:
 	bh_unlock_sock(sk);
 	sock_put(sk);
@@ -319,7 +319,7 @@
 	case TFRC_SSTATE_NO_SENT:
 		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
 			       (jiffies +
-			        usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
+				usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
 		hctx->ccid3hctx_last_win_count	 = 0;
 		hctx->ccid3hctx_t_last_win_count = now;
 		ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
@@ -479,14 +479,15 @@
 
 			ccid3_pr_debug("%s(%p), s=%u, w_init=%llu, "
 				       "R_sample=%dus, X=%u\n", dccp_role(sk),
-				       sk, hctx->ccid3hctx_s, w_init,
+				       sk, hctx->ccid3hctx_s,
+				       (unsigned long long)w_init,
 				       (int)r_sample,
 				       (unsigned)(hctx->ccid3hctx_x >> 6));
 
 			ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
 		} else {
 			hctx->ccid3hctx_rtt = (9 * hctx->ccid3hctx_rtt +
-					           (u32)r_sample) / 10;
+						   (u32)r_sample) / 10;
 
 			/* Update sending rate (step 4 of [RFC 3448, 4.3]) */
 			if (hctx->ccid3hctx_p > 0)
@@ -923,7 +924,7 @@
 }
 
 static int ccid3_hc_rx_detect_loss(struct sock *sk,
-                                    struct dccp_rx_hist_entry *packet)
+				    struct dccp_rx_hist_entry *packet)
 {
 	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 	struct dccp_rx_hist_entry *rx_hist =
@@ -1005,7 +1006,7 @@
 		DCCP_BUG_ON(r_sample < 0);
 		if (unlikely(r_sample <= t_elapsed))
 			DCCP_WARN("r_sample=%ldus, t_elapsed=%ldus\n",
-				  r_sample, t_elapsed);
+				  (long)r_sample, (long)t_elapsed);
 		else
 			r_sample -= t_elapsed;
 		CCID3_RTT_SANITY_CHECK(r_sample);
@@ -1073,7 +1074,7 @@
 		       dccp_role(sk), sk, dccp_state_name(sk->sk_state));
 
 	p_prev = hcrx->ccid3hcrx_p;
-	
+
 	/* Calculate loss event rate */
 	if (!list_empty(&hcrx->ccid3hcrx_li_hist)) {
 		u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);
@@ -1155,7 +1156,7 @@
 {
 	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 	const void *val;
-	
+
 	/* Listen socks doesn't have a private CCID block */
 	if (sk->sk_state == DCCP_LISTEN)
 		return -EINVAL;
@@ -1182,7 +1183,7 @@
 {
 	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 	const void *val;
-	
+
 	/* Listen socks doesn't have a private CCID block */
 	if (sk->sk_state == DCCP_LISTEN)
 		return -EINVAL;
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 1f960c1..60d00f0 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -137,7 +137,7 @@
 static inline struct dccp_rx_hist_entry *
 			dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
 					       const struct sock *sk,
-				     	       const u32 ndp,
+					       const u32 ndp,
 					       const struct sk_buff *skb,
 					       const gfp_t prio)
 {
@@ -169,7 +169,7 @@
 }
 
 extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
-   				   u8 *ccval);
+				   u8 *ccval);
 extern struct dccp_rx_hist_entry *
 		dccp_rx_hist_find_data_packet(const struct list_head *list);
 
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index 90009fd..e4e64b7 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -26,7 +26,7 @@
   The following two-column lookup table implements a part of the TCP throughput
   equation from [RFC 3448, sec. 3.1]:
 
-	 			     s
+				     s
   X_calc  =  --------------------------------------------------------------
 	     R * sqrt(2*b*p/3) + (3 * t_RTO * sqrt(3*b*p/8) * (p + 32*p^3))
 
@@ -35,7 +35,7 @@
 	s      is the packet size in bytes
 	R      is the round trip time in seconds
 	p      is the loss event rate, between 0 and 1.0, of the number of loss
-	              events as a fraction of the number of packets transmitted
+		      events as a fraction of the number of packets transmitted
 	t_RTO  is the TCP retransmission timeout value in seconds
 	b      is the number of packets acknowledged by a single TCP ACK
 
@@ -47,9 +47,9 @@
 
   which we can break down into:
 
-                      s
+		      s
 	X_calc  =  ---------
-	            R * f(p)
+		    R * f(p)
 
   where f(p) is given for 0 < p <= 1 by:
 
@@ -62,7 +62,7 @@
     * the return result f(p)
   The lookup table therefore actually tabulates the following function g(q):
 
-  	g(q)  =  1000000 * f(q/1000000)
+	g(q)  =  1000000 * f(q/1000000)
 
   Hence, when p <= 1, q must be less than or equal to 1000000. To achieve finer
   granularity for the practically more relevant case of small values of p (up to
@@ -628,7 +628,7 @@
 	if (R == 0) {			/* possible  divide by zero */
 		DCCP_CRIT("WARNING: RTT is 0, returning maximum X_calc.");
 		return ~0U;
- 	}
+	}
 
 	if (p <= TFRC_CALC_X_SPLIT) 		{     /* 0.0000 < p <= 0.05   */
 		if (p < TFRC_SMALLEST_P) {	      /* 0.0000 < p <  0.0001 */
@@ -638,7 +638,7 @@
 		} else 				      /* 0.0001 <= p <= 0.05  */
 			index =  p/TFRC_SMALLEST_P - 1;
 
- 		f = tfrc_calc_x_lookup[index][1];
+		f = tfrc_calc_x_lookup[index][1];
 
 	} else {	 			      /* 0.05   <  p <= 1.00  */
 		index = p/(1000000/TFRC_CALC_X_ARRSIZE) - 1;
@@ -687,8 +687,8 @@
 	if (fvalue <= tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE - 1][1]) {
 		index = tfrc_binsearch(fvalue, 1);
 		return (index + 1) * TFRC_CALC_X_SPLIT / TFRC_CALC_X_ARRSIZE;
- 	}
- 
+	}
+
 	/* else ... it must be in the coarse-grained column */
 	index = tfrc_binsearch(fvalue, 0);
 	return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE;
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index a0900bf..e33a9ed 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -22,7 +22,7 @@
  * 	DCCP - specific warning and debugging macros.
  */
 #define DCCP_WARN(fmt, a...) LIMIT_NETDEBUG(KERN_WARNING "%s: " fmt,       \
-						        __FUNCTION__, ##a)
+							__FUNCTION__, ##a)
 #define DCCP_CRIT(fmt, a...) printk(KERN_CRIT fmt " at %s:%d/%s()\n", ##a, \
 					 __FILE__, __LINE__, __FUNCTION__)
 #define DCCP_BUG(a...)       do { DCCP_CRIT("BUG: " a); dump_stack(); } while(0)
@@ -34,7 +34,7 @@
 #ifdef MODULE
 #define DCCP_PRINTK(enable, fmt, args...)	do { if (enable)	     \
 							printk(fmt, ##args); \
-					 	} while(0)
+						} while(0)
 #else
 #define DCCP_PRINTK(enable, fmt, args...)	printk(fmt, ##args)
 #endif
@@ -128,7 +128,7 @@
 	DCCP_MIB_ACTIVEOPENS,			/* ActiveOpens */
 	DCCP_MIB_ESTABRESETS,			/* EstabResets */
 	DCCP_MIB_CURRESTAB,			/* CurrEstab */
-	DCCP_MIB_OUTSEGS,			/* OutSegs */ 
+	DCCP_MIB_OUTSEGS,			/* OutSegs */
 	DCCP_MIB_OUTRSTS,
 	DCCP_MIB_ABORTONTIMEOUT,
 	DCCP_MIB_TIMEOUTS,
@@ -372,7 +372,7 @@
 		       (dp->dccps_gss -
 			dccp_msk(sk)->dccpms_sequence_window + 1));
 }
-				
+
 static inline int dccp_ack_pending(const struct sock *sk)
 {
 	const struct dccp_sock *dp = dccp_sk(sk);
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 95b6927..cd845df 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -480,8 +480,8 @@
 
 	list_for_each_entry_safe(opt, next, &dmsk->dccpms_pending,
 				 dccpop_node) {
-                BUG_ON(opt->dccpop_val == NULL);
-                kfree(opt->dccpop_val);
+		BUG_ON(opt->dccpop_val == NULL);
+		kfree(opt->dccpop_val);
 
 		if (opt->dccpop_sc != NULL) {
 			BUG_ON(opt->dccpop_sc->dccpoc_val == NULL);
@@ -489,8 +489,8 @@
 			kfree(opt->dccpop_sc);
 		}
 
-                kfree(opt);
-        }
+		kfree(opt);
+	}
 	INIT_LIST_HEAD(&dmsk->dccpms_pending);
 
 	list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {
diff --git a/net/dccp/feat.h b/net/dccp/feat.h
index 2c373ad..177f7de 100644
--- a/net/dccp/feat.h
+++ b/net/dccp/feat.h
@@ -30,7 +30,7 @@
 {
 	return (feat > DCCPF_DATA_CHECKSUM &&
 		feat < DCCPF_MIN_CCID_SPECIFIC) ||
-	        feat == DCCPF_RESERVED;
+		feat == DCCPF_RESERVED;
 }
 
 /* feature negotiation knows only these four option types (RFC 4340, sec. 6) */
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 565bc80..4dee462 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -91,7 +91,7 @@
 		else
 			return -1;
 	}
-	
+
 	/*
 	 *   Step 6: Check sequence numbers
 	 *      Let LSWL = S.SWL and LAWL = S.AWL
@@ -136,7 +136,7 @@
 			  (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq,
 			  (unsigned long long) dp->dccps_swh,
 			  (DCCP_SKB_CB(skb)->dccpd_ack_seq ==
-			        DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" : "exists",
+				DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" : "exists",
 			  (unsigned long long) lawl,
 			  (unsigned long long) DCCP_SKB_CB(skb)->dccpd_ack_seq,
 			  (unsigned long long) dp->dccps_awh);
@@ -308,11 +308,11 @@
 		if (dccp_parse_options(sk, skb))
 			goto out_invalid_packet;
 
-                if (dccp_msk(sk)->dccpms_send_ack_vector &&
-                    dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
-                                    DCCP_SKB_CB(skb)->dccpd_seq,
-                                    DCCP_ACKVEC_STATE_RECEIVED))
-                        goto out_invalid_packet; /* FIXME: change error code */
+		if (dccp_msk(sk)->dccpms_send_ack_vector &&
+		    dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
+				    DCCP_SKB_CB(skb)->dccpd_seq,
+				    DCCP_ACKVEC_STATE_RECEIVED))
+			goto out_invalid_packet; /* FIXME: change error code */
 
 		dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq;
 		dccp_update_gsr(sk, dp->dccps_isr);
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 90c74b4..4a83978 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -72,7 +72,7 @@
 	tmp = ip_route_connect(&rt, nexthop, inet->saddr,
 			       RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
 			       IPPROTO_DCCP,
-			       inet->sport, usin->sin_port, sk);
+			       inet->sport, usin->sin_port, sk, 1);
 	if (tmp < 0)
 		return tmp;
 
@@ -106,7 +106,7 @@
 		goto failure;
 
 	err = ip_route_newports(&rt, IPPROTO_DCCP, inet->sport, inet->dport,
-	                        sk);
+				sk);
 	if (err != 0)
 		goto failure;
 
@@ -157,7 +157,7 @@
 	/* We don't check in the destentry if pmtu discovery is forbidden
 	 * on this route. We just assume that no packet_to_big packets
 	 * are send back when pmtu discovery is not active.
- 	 * There is a small race when the user changes this flag in the
+	 * There is a small race when the user changes this flag in the
 	 * route, but I think that's acceptable.
 	 */
 	if ((dst = __sk_dst_check(sk, 0)) == NULL)
@@ -486,7 +486,7 @@
 	struct sk_buff *skb;
 
 	/* First, grab a route. */
-	
+
 	if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL)
 		goto out;
 
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 6b91a9d..7f51e8d 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -734,7 +734,7 @@
 	   looks not very well thought. For now we latch
 	   options, received in the last packet, enqueued
 	   by tcp. Feel free to propose better solution.
-	                                       --ANK (980728)
+					       --ANK (980728)
 	 */
 	if (np->rxopt.all)
 	/*
@@ -1041,7 +1041,7 @@
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	err = xfrm_lookup(&dst, &fl, sk, 0);
+	err = xfrm_lookup(&dst, &fl, sk, 1);
 	if (err < 0)
 		goto failure;
 
diff --git a/net/dccp/options.c b/net/dccp/options.c
index c03ba61..ca13f77 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -242,7 +242,7 @@
 			DCCP_CRIT("DCCP(%p): option %d(len=%d) not "
 				  "implemented, ignoring", sk, opt, len);
 			break;
-	        }
+		}
 
 		if (opt != DCCPO_MANDATORY)
 			mandatory = 0;
@@ -442,7 +442,7 @@
 }
 
 static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
-			        u8 *val, u8 len)
+				u8 *val, u8 len)
 {
 	u8 *to;
 
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 3435542..f5c6aca 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -87,7 +87,7 @@
 			kfree_skb(skb);
 			return -EPROTO;
 		}
-		
+
 
 		/* Build DCCP header and checksum it. */
 		dh = dccp_zeroed_hdr(skb, dccp_header_size);
@@ -415,7 +415,7 @@
 
 	sk->sk_err = 0;
 	sock_reset_flag(sk, SOCK_DONE);
-	
+
 	dccp_sync_mss(sk, dst_mtu(dst));
 
 	/*
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
index f81e37d..3b1f509 100644
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -149,7 +149,7 @@
 	return error ? error : cnt;
 }
 
-static struct file_operations dccpprobe_fops = {
+static const struct file_operations dccpprobe_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = dccpprobe_open,
 	.read    = dccpprobe_read,
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 63b3fa2..cf28c53 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -478,7 +478,7 @@
 			err = -EINVAL;
 		else
 			err = dccp_setsockopt_change(sk, DCCPO_CHANGE_L,
-					             (struct dccp_so_feat __user *)
+						     (struct dccp_so_feat __user *)
 						     optval);
 		break;
 	case DCCP_SOCKOPT_CHANGE_R:
@@ -1024,7 +1024,6 @@
 	do {
 		dccp_hashinfo.ehash_size = (1UL << ehash_order) * PAGE_SIZE /
 					sizeof(struct inet_ehash_bucket);
-		dccp_hashinfo.ehash_size >>= 1;
 		while (dccp_hashinfo.ehash_size &
 		       (dccp_hashinfo.ehash_size - 1))
 			dccp_hashinfo.ehash_size--;
@@ -1037,9 +1036,10 @@
 		goto out_free_bind_bucket_cachep;
 	}
 
-	for (i = 0; i < (dccp_hashinfo.ehash_size << 1); i++) {
+	for (i = 0; i < dccp_hashinfo.ehash_size; i++) {
 		rwlock_init(&dccp_hashinfo.ehash[i].lock);
 		INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].chain);
+		INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].twchain);
 	}
 
 	bhash_order = ehash_order;
diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c
index fdcfca3..1260aab 100644
--- a/net/dccp/sysctl.c
+++ b/net/dccp/sysctl.c
@@ -127,7 +127,7 @@
 
 int __init dccp_sysctl_init(void)
 {
-	dccp_table_header = register_sysctl_table(dccp_root_table, 1);
+	dccp_table_header = register_sysctl_table(dccp_root_table);
 
 	return dccp_table_header != NULL ? 0 : -ENOMEM;
 }
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index e5348f3..41ea0f6 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -60,7 +60,7 @@
    be far nicer to have all of the black holes fixed rather than fixing
    all of the TCP implementations."
 
-                           Golden words :-).
+			   Golden words :-).
 		   */
 
 			dst_negative_advice(&sk->sk_dst_cache);
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 21f20f2..c6568d6 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -45,7 +45,7 @@
 
 /******************************************************************************
     (c) 1995-1998 E.M. Serrat		emserrat@geocities.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
@@ -63,7 +63,7 @@
 Version 0.0.1     2.0.30    01-dic-97	Eduardo Marcelo Serrat
 					(emserrat@geocities.com)
 
-                                        First Development of DECnet Socket La-
+					First Development of DECnet Socket La-
 					yer for Linux. Only supports outgoing
 					connections.
 
@@ -75,28 +75,28 @@
 Version 0.0.3     2.1.106   25-jun-98   Eduardo Marcelo Serrat
 					(emserrat@geocities.com)
 					_
-                                        Added support for incoming connections
-                                        so we can start developing server apps
-                                        on Linux.
+					Added support for incoming connections
+					so we can start developing server apps
+					on Linux.
 					-
 					Module Support
 Version 0.0.4     2.1.109   21-jul-98   Eduardo Marcelo Serrat
-                                       (emserrat@geocities.com)
-                                       _
-                                        Added support for X11R6.4. Now we can 
-                                        use DECnet transport for X on Linux!!!
-                                       -
+				       (emserrat@geocities.com)
+				       _
+					Added support for X11R6.4. Now we can
+					use DECnet transport for X on Linux!!!
+				       -
 Version 0.0.5    2.1.110   01-aug-98   Eduardo Marcelo Serrat
-                                       (emserrat@geocities.com)
-                                       Removed bugs on flow control
-                                       Removed bugs on incoming accessdata
-                                       order
-                                       -
+				       (emserrat@geocities.com)
+				       Removed bugs on flow control
+				       Removed bugs on incoming accessdata
+				       order
+				       -
 Version 0.0.6    2.1.110   07-aug-98   Eduardo Marcelo Serrat
-                                       dn_recvmsg fixes
+				       dn_recvmsg fixes
 
-                                        Patrick J. Caulfield
-                                       dn_bind fixes
+					Patrick J. Caulfield
+				       dn_bind fixes
 *******************************************************************************/
 
 #include <linux/module.h>
@@ -169,7 +169,7 @@
 	return &dn_sk_hash[dn_ntohs(scp->addrloc) & DN_SK_HASH_MASK];
 }
 
-/* 
+/*
  * Valid ports are those greater than zero and not already in use.
  */
 static int check_port(__le16 port)
@@ -218,7 +218,7 @@
 	BUG_ON(sk_hashed(sk));
 
 	write_lock_bh(&dn_hash_lock);
-	
+
 	if (!scp->addrloc && !port_alloc(sk))
 		goto out;
 
@@ -400,7 +400,7 @@
 
 	sk = sk_head(&dn_wild_sk);
 	if (sk) {
-	       	if (sk->sk_state == TCP_LISTEN)
+		if (sk->sk_state == TCP_LISTEN)
 			sock_hold(sk);
 		else
 			sk = NULL;
@@ -500,7 +500,7 @@
 	scp->ackxmt_oth = 0;		/* Last oth data ack'ed */
 	scp->ackrcv_dat = 0;		/* Highest data ack recv*/
 	scp->ackrcv_oth = 0;		/* Last oth data ack rec*/
-        scp->flowrem_sw = DN_SEND;
+	scp->flowrem_sw = DN_SEND;
 	scp->flowloc_sw = DN_SEND;
 	scp->flowrem_dat = 0;
 	scp->flowrem_oth = 1;
@@ -690,7 +690,7 @@
 	}
 
 
-	if ((sk = dn_alloc_sock(sock, GFP_KERNEL)) == NULL) 
+	if ((sk = dn_alloc_sock(sock, GFP_KERNEL)) == NULL)
 		return -ENOBUFS;
 
 	sk->sk_protocol = protocol;
@@ -713,7 +713,7 @@
 		sock_put(sk);
 	}
 
-        return 0;
+	return 0;
 }
 
 static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
@@ -770,7 +770,7 @@
 	}
 	release_sock(sk);
 
-        return rv;
+	return rv;
 }
 
 
@@ -791,7 +791,7 @@
 	 */
 	if ((scp->accessdata.acc_accl != 0) &&
 		(scp->accessdata.acc_accl <= 12)) {
-	
+
 		scp->addr.sdn_objnamel = dn_htons(scp->accessdata.acc_accl);
 		memcpy(scp->addr.sdn_objname, scp->accessdata.acc_acc, dn_ntohs(scp->addr.sdn_objnamel));
 
@@ -997,20 +997,20 @@
 
 static void dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc)
 {
-        unsigned char *ptr = skb->data;
+	unsigned char *ptr = skb->data;
 
-        acc->acc_userl = *ptr++;
-        memcpy(&acc->acc_user, ptr, acc->acc_userl);
-        ptr += acc->acc_userl;
+	acc->acc_userl = *ptr++;
+	memcpy(&acc->acc_user, ptr, acc->acc_userl);
+	ptr += acc->acc_userl;
 
-        acc->acc_passl = *ptr++;
-        memcpy(&acc->acc_pass, ptr, acc->acc_passl);
-        ptr += acc->acc_passl;
+	acc->acc_passl = *ptr++;
+	memcpy(&acc->acc_pass, ptr, acc->acc_passl);
+	ptr += acc->acc_passl;
 
-        acc->acc_accl = *ptr++;
-        memcpy(&acc->acc_acc, ptr, acc->acc_accl);
+	acc->acc_accl = *ptr++;
+	memcpy(&acc->acc_acc, ptr, acc->acc_accl);
 
-        skb_pull(skb, acc->acc_accl + acc->acc_passl + acc->acc_userl + 3);
+	skb_pull(skb, acc->acc_accl + acc->acc_passl + acc->acc_userl + 3);
 
 }
 
@@ -1071,7 +1071,7 @@
 
 	lock_sock(sk);
 
-        if (sk->sk_state != TCP_LISTEN || DN_SK(sk)->state != DN_O) {
+	if (sk->sk_state != TCP_LISTEN || DN_SK(sk)->state != DN_O) {
 		release_sock(sk);
 		return -EINVAL;
 	}
@@ -1098,13 +1098,13 @@
 	dst_release(xchg(&newsk->sk_dst_cache, skb->dst));
 	skb->dst = NULL;
 
-        DN_SK(newsk)->state        = DN_CR;
+	DN_SK(newsk)->state        = DN_CR;
 	DN_SK(newsk)->addrrem      = cb->src_port;
 	DN_SK(newsk)->services_rem = cb->services;
 	DN_SK(newsk)->info_rem     = cb->info;
 	DN_SK(newsk)->segsize_rem  = cb->segsize;
 	DN_SK(newsk)->accept_mode  = DN_SK(sk)->accept_mode;
-	
+
 	if (DN_SK(newsk)->segsize_rem < 230)
 		DN_SK(newsk)->segsize_rem = 230;
 
@@ -1154,15 +1154,15 @@
 		dn_send_conn_ack(newsk);
 
 		/*
-	 	 * Here we use sk->sk_allocation since although the conn conf is
-	 	 * for the newsk, the context is the old socket.
-	 	 */
+		 * Here we use sk->sk_allocation since although the conn conf is
+		 * for the newsk, the context is the old socket.
+		 */
 		if (DN_SK(newsk)->accept_mode == ACC_IMMED)
 			err = dn_confirm_accept(newsk, &timeo,
 						sk->sk_allocation);
 	}
 	release_sock(newsk);
-        return err;
+	return err;
 }
 
 
@@ -1177,10 +1177,10 @@
 	lock_sock(sk);
 
 	if (peer) {
-		if ((sock->state != SS_CONNECTED && 
-		     sock->state != SS_CONNECTING) && 
+		if ((sock->state != SS_CONNECTED &&
+		     sock->state != SS_CONNECTING) &&
 		    scp->accept_mode == ACC_IMMED) {
-		    	release_sock(sk);
+			release_sock(sk);
 			return -ENOTCONN;
 		}
 
@@ -1191,7 +1191,7 @@
 
 	release_sock(sk);
 
-        return 0;
+	return 0;
 }
 
 
@@ -1285,7 +1285,7 @@
 out:
 	release_sock(sk);
 
-        return err;
+	return err;
 }
 
 
@@ -1333,7 +1333,7 @@
 	return err;
 }
 
-static int __dn_setsockopt(struct socket *sock, int level,int optname, char __user *optval, int optlen, int flags) 
+static int __dn_setsockopt(struct socket *sock, int level,int optname, char __user *optval, int optlen, int flags)
 {
 	struct	sock *sk = sock->sk;
 	struct dn_scp *scp = DN_SK(sk);
@@ -1360,7 +1360,7 @@
 
 	switch(optname) {
 		case DSO_CONDATA:
-			if (sock->state == SS_CONNECTED) 
+			if (sock->state == SS_CONNECTED)
 				return -EISCONN;
 			if ((scp->state != DN_O) && (scp->state != DN_CR))
 				return -EINVAL;
@@ -1375,7 +1375,7 @@
 			break;
 
 		case DSO_DISDATA:
-	   	        if (sock->state != SS_CONNECTED && scp->accept_mode == ACC_IMMED)
+			if (sock->state != SS_CONNECTED && scp->accept_mode == ACC_IMMED)
 				return -ENOTCONN;
 
 			if (optlen != sizeof(struct optdata_dn))
@@ -1388,7 +1388,7 @@
 			break;
 
 		case DSO_CONACCESS:
-			if (sock->state == SS_CONNECTED) 
+			if (sock->state == SS_CONNECTED)
 				return -EISCONN;
 			if (scp->state != DN_O)
 				return -EINVAL;
@@ -1521,7 +1521,7 @@
 
 	if(get_user(r_len , optlen))
 		return -EFAULT;
-		
+
 	switch(optname) {
 		case DSO_CONDATA:
 			if (r_len > sizeof(struct optdata_dn))
@@ -1573,11 +1573,11 @@
 #ifdef CONFIG_NETFILTER
 		{
 			int val, len;
-			
+
 			if(get_user(len, optlen))
 				return -EFAULT;
-			
-			val = nf_getsockopt(sk, PF_DECnet, optname, 
+
+			val = nf_getsockopt(sk, PF_DECnet, optname,
 							optval, &len);
 			if (val >= 0)
 				val = put_user(len, optlen);
@@ -1588,7 +1588,7 @@
 		case DSO_SEQPACKET:
 		case DSO_CONACCEPT:
 		case DSO_CONREJECT:
-        		return -ENOPROTOOPT;
+			return -ENOPROTOOPT;
 
 		case DSO_MAXWINDOW:
 			if (r_len > sizeof(unsigned long))
@@ -1724,7 +1724,7 @@
 				}
 			}
 		}
-		
+
 		if (scp->state != DN_RUN)
 			goto out;
 
@@ -1773,7 +1773,7 @@
 		if (skb->len == 0) {
 			skb_unlink(skb, queue);
 			kfree_skb(skb);
-			/* 
+			/*
 			 * N.B. Don't refer to skb or cb after this point
 			 * in loop.
 			 */
@@ -1783,7 +1783,7 @@
 			}
 		}
 
-		if (eor) { 
+		if (eor) {
 			if (sk->sk_type == SOCK_SEQPACKET)
 				break;
 			if (!(flags & MSG_WAITALL))
@@ -1884,7 +1884,7 @@
 	return mss_now;
 }
 
-/* 
+/*
  * N.B. We get the timeout wrong here, but then we always did get it
  * wrong before and this is another step along the road to correcting
  * it. It ought to get updated each time we pass through the routine,
@@ -2044,7 +2044,7 @@
 				cb->nsp_flags |= 0x20;
 
 			scp->seg_total += len;
-		
+
 			if (((sent + len) == size) && (flags & MSG_EOR)) {
 				cb->nsp_flags |= 0x40;
 				scp->seg_total = 0;
@@ -2202,7 +2202,7 @@
 static void dn_printable_object(struct sockaddr_dn *dn, unsigned char *buf)
 {
 	int i;
-    
+
 	switch (dn_ntohs(dn->sdn_objnamel)) {
 		case 0:
 			sprintf(buf, "%d", dn->sdn_objnum);
@@ -2214,7 +2214,7 @@
 					buf[i] = '.';
 			}
 			buf[i] = 0;
-    	}
+	}
 }
 
 static char *dn_state2asc(unsigned char state)
@@ -2331,7 +2331,7 @@
 	goto out;
 }
 
-static struct file_operations dn_socket_seq_fops = {
+static const struct file_operations dn_socket_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= dn_socket_seq_open,
 	.read		= seq_read,
@@ -2381,7 +2381,7 @@
 {
 	int rc;
 
-        printk(banner);
+	printk(banner);
 
 	rc = proto_register(&dn_proto, 1);
 	if (rc != 0)
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index ed083ab..060d725 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -224,27 +224,27 @@
 	{0}
 	},
 	{{
-		.ctl_name = 0, 
-		.procname = "", 
-		.mode = 0555, 
+		.ctl_name = 0,
+		.procname = "",
+		.mode = 0555,
 		.child = dn_dev_sysctl.dn_dev_vars
 	}, {0}},
 	{{
 		.ctl_name = NET_DECNET_CONF,
-		.procname = "conf", 
-		.mode = 0555, 
+		.procname = "conf",
+		.mode = 0555,
 		.child = dn_dev_sysctl.dn_dev_dev
 	}, {0}},
 	{{
-		.ctl_name = NET_DECNET, 
-		.procname = "decnet", 
-		.mode = 0555, 
+		.ctl_name = NET_DECNET,
+		.procname = "decnet",
+		.mode = 0555,
 		.child = dn_dev_sysctl.dn_dev_conf_dir
 	}, {0}},
 	{{
-		.ctl_name = CTL_NET, 
-		.procname = "net", 
-		.mode = 0555, 
+		.ctl_name = CTL_NET,
+		.procname = "net",
+		.mode = 0555,
 		.child = dn_dev_sysctl.dn_dev_proto_dir
 	}, {0}}
 };
@@ -261,7 +261,6 @@
 	for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) {
 		long offset = (long)t->dn_dev_vars[i].data;
 		t->dn_dev_vars[i].data = ((char *)parms) + offset;
-		t->dn_dev_vars[i].de = NULL;
 	}
 
 	if (dev) {
@@ -273,16 +272,12 @@
 	}
 
 	t->dn_dev_dev[0].child = t->dn_dev_vars;
-	t->dn_dev_dev[0].de = NULL;
 	t->dn_dev_conf_dir[0].child = t->dn_dev_dev;
-	t->dn_dev_conf_dir[0].de = NULL;
 	t->dn_dev_proto_dir[0].child = t->dn_dev_conf_dir;
-	t->dn_dev_proto_dir[0].de = NULL;
 	t->dn_dev_root_dir[0].child = t->dn_dev_proto_dir;
-	t->dn_dev_root_dir[0].de = NULL;
 	t->dn_dev_vars[0].extra1 = (void *)dev;
 
-	t->sysctl_header = register_sysctl_table(t->dn_dev_root_dir, 0);
+	t->sysctl_header = register_sysctl_table(t->dn_dev_root_dir);
 	if (t->sysctl_header == NULL)
 		kfree(t);
 	else
@@ -299,7 +294,7 @@
 	}
 }
 
-static int dn_forwarding_proc(ctl_table *table, int write, 
+static int dn_forwarding_proc(ctl_table *table, int write,
 				struct file *filep,
 				void __user *buffer,
 				size_t *lenp, loff_t *ppos)
@@ -456,7 +451,7 @@
 
 	ASSERT_RTNL();
 
-	/* Check for duplicates */	
+	/* Check for duplicates */
 	for(ifa1 = dn_db->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
 		if (ifa1->ifa_local == ifa->ifa_local)
 			return -EEXIST;
@@ -708,7 +703,7 @@
 		if (!dn_db)
 			return err;
 	}
-	
+
 	if ((ifa = dn_dev_alloc_ifa()) == NULL)
 		return -ENOBUFS;
 
@@ -749,7 +744,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ifm = nlmsg_data(nlh);
 	ifm->ifa_family = AF_DECnet;
@@ -768,7 +763,8 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
@@ -781,9 +777,12 @@
 		goto errout;
 
 	err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0);
-	/* failure implies BUG in dn_ifaddr_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in dn_ifaddr_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
 errout:
 	if (err < 0)
@@ -849,7 +848,7 @@
 	return rv;
 }
 
-/* 
+/*
  * Find a default address to bind to.
  *
  * This is one of those areas where the initial VMS concepts don't really
@@ -880,39 +879,39 @@
 
 static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa)
 {
-        struct endnode_hello_message *msg;
-        struct sk_buff *skb = NULL;
-        __le16 *pktlen;
+	struct endnode_hello_message *msg;
+	struct sk_buff *skb = NULL;
+	__le16 *pktlen;
 	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
 
-        if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL)
+	if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL)
 		return;
 
-        skb->dev = dev;
+	skb->dev = dev;
 
-        msg = (struct endnode_hello_message *)skb_put(skb,sizeof(*msg));
+	msg = (struct endnode_hello_message *)skb_put(skb,sizeof(*msg));
 
-        msg->msgflg  = 0x0D;
-        memcpy(msg->tiver, dn_eco_version, 3);
+	msg->msgflg  = 0x0D;
+	memcpy(msg->tiver, dn_eco_version, 3);
 	dn_dn2eth(msg->id, ifa->ifa_local);
-        msg->iinfo   = DN_RT_INFO_ENDN;
-        msg->blksize = dn_htons(mtu2blksize(dev));
-        msg->area    = 0x00;
-        memset(msg->seed, 0, 8);
-        memcpy(msg->neighbor, dn_hiord, ETH_ALEN);
+	msg->iinfo   = DN_RT_INFO_ENDN;
+	msg->blksize = dn_htons(mtu2blksize(dev));
+	msg->area    = 0x00;
+	memset(msg->seed, 0, 8);
+	memcpy(msg->neighbor, dn_hiord, ETH_ALEN);
 
 	if (dn_db->router) {
 		struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
 		dn_dn2eth(msg->neighbor, dn->addr);
 	}
 
-        msg->timer   = dn_htons((unsigned short)dn_db->parms.t3);
-        msg->mpd     = 0x00;
-        msg->datalen = 0x02;
-        memset(msg->data, 0xAA, 2);
-        
-        pktlen = (__le16 *)skb_push(skb,2);
-        *pktlen = dn_htons(skb->len - 2);
+	msg->timer   = dn_htons((unsigned short)dn_db->parms.t3);
+	msg->mpd     = 0x00;
+	msg->datalen = 0x02;
+	memset(msg->data, 0xAA, 2);
+
+	pktlen = (__le16 *)skb_push(skb,2);
+	*pktlen = dn_htons(skb->len - 2);
 
 	skb->nh.raw = skb->data;
 
@@ -982,11 +981,11 @@
 	dn_dn2eth(ptr, ifa->ifa_local);
 	src = ptr;
 	ptr += ETH_ALEN;
-	*ptr++ = dn_db->parms.forwarding == 1 ? 
+	*ptr++ = dn_db->parms.forwarding == 1 ?
 			DN_RT_INFO_L1RT : DN_RT_INFO_L2RT;
 	*((__le16 *)ptr) = dn_htons(mtu2blksize(dev));
 	ptr += 2;
-	*ptr++ = dn_db->parms.priority; /* Priority */ 
+	*ptr++ = dn_db->parms.priority; /* Priority */
 	*ptr++ = 0; /* Area: Reserved */
 	*((__le16 *)ptr) = dn_htons((unsigned short)dn_db->parms.t3);
 	ptr += 2;
@@ -1404,18 +1403,18 @@
 static int dn_dev_seq_show(struct seq_file *seq, void *v)
 {
 	if (v == SEQ_START_TOKEN)
-        	seq_puts(seq, "Name     Flags T1   Timer1 T3   Timer3 BlkSize Pri State DevType    Router Peer\n");
+		seq_puts(seq, "Name     Flags T1   Timer1 T3   Timer3 BlkSize Pri State DevType    Router Peer\n");
 	else {
 		struct net_device *dev = v;
 		char peer_buf[DN_ASCBUF_LEN];
 		char router_buf[DN_ASCBUF_LEN];
 		struct dn_dev *dn_db = dev->dn_ptr;
 
-                seq_printf(seq, "%-8s %1s     %04u %04u   %04lu %04lu"
+		seq_printf(seq, "%-8s %1s     %04u %04u   %04lu %04lu"
 				"   %04hu    %03d %02x    %-10s %-7s %-7s\n",
-                             	dev->name ? dev->name : "???",
-                             	dn_type2asc(dn_db->parms.mode),
-                             	0, 0,
+				dev->name ? dev->name : "???",
+				dn_type2asc(dn_db->parms.mode),
+				0, 0,
 				dn_db->t3, dn_db->parms.t3,
 				mtu2blksize(dev),
 				dn_db->parms.priority,
@@ -1438,7 +1437,7 @@
 	return seq_open(file, &dn_dev_seq_ops);
 }
 
-static struct file_operations dn_dev_seq_fops = {
+static const struct file_operations dn_dev_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = dn_dev_seq_open,
 	.read	 = seq_read,
@@ -1472,17 +1471,17 @@
 
 void __init dn_dev_init(void)
 {
-        if (addr[0] > 63 || addr[0] < 0) {
-                printk(KERN_ERR "DECnet: Area must be between 0 and 63");
-                return;
-        }
+	if (addr[0] > 63 || addr[0] < 0) {
+		printk(KERN_ERR "DECnet: Area must be between 0 and 63");
+		return;
+	}
 
-        if (addr[1] > 1023 || addr[1] < 0) {
-                printk(KERN_ERR "DECnet: Node must be between 0 and 1023");
-                return;
-        }
+	if (addr[1] > 1023 || addr[1] < 0) {
+		printk(KERN_ERR "DECnet: Node must be between 0 and 1023");
+		return;
+	}
 
-        decnet_address = dn_htons((addr[0] << 10) | addr[1]);
+	decnet_address = dn_htons((addr[0] << 10) | addr[1]);
 
 	dn_dev_devices_on();
 
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 1cf0101..3cbfddc 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -527,7 +527,7 @@
 		return -EINVAL;
 
 	tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 1);
-	if (tb) 
+	if (tb)
 		return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
 
 	return -ENOBUFS;
@@ -654,80 +654,80 @@
 
 static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force)
 {
-        int ret = 0;
-        int scope = RT_SCOPE_NOWHERE;
+	int ret = 0;
+	int scope = RT_SCOPE_NOWHERE;
 
-        if (force)
-                scope = -1;
+	if (force)
+		scope = -1;
 
-        for_fib_info() {
-                /* 
-                 * This makes no sense for DECnet.... we will almost
-                 * certainly have more than one local address the same
-                 * over all our interfaces. It needs thinking about
-                 * some more.
-                 */
-                if (local && fi->fib_prefsrc == local) {
-                        fi->fib_flags |= RTNH_F_DEAD;
-                        ret++;
-                } else if (dev && fi->fib_nhs) {
-                        int dead = 0;
+	for_fib_info() {
+		/*
+		 * This makes no sense for DECnet.... we will almost
+		 * certainly have more than one local address the same
+		 * over all our interfaces. It needs thinking about
+		 * some more.
+		 */
+		if (local && fi->fib_prefsrc == local) {
+			fi->fib_flags |= RTNH_F_DEAD;
+			ret++;
+		} else if (dev && fi->fib_nhs) {
+			int dead = 0;
 
-                        change_nexthops(fi) {
-                                if (nh->nh_flags&RTNH_F_DEAD)
-                                        dead++;
-                                else if (nh->nh_dev == dev &&
-                                                nh->nh_scope != scope) {
+			change_nexthops(fi) {
+				if (nh->nh_flags&RTNH_F_DEAD)
+					dead++;
+				else if (nh->nh_dev == dev &&
+						nh->nh_scope != scope) {
 					spin_lock_bh(&dn_fib_multipath_lock);
-                                        nh->nh_flags |= RTNH_F_DEAD;
-                                        fi->fib_power -= nh->nh_power;
-                                        nh->nh_power = 0;
+					nh->nh_flags |= RTNH_F_DEAD;
+					fi->fib_power -= nh->nh_power;
+					nh->nh_power = 0;
 					spin_unlock_bh(&dn_fib_multipath_lock);
-                                        dead++;
-                                }
-                        } endfor_nexthops(fi)
-                        if (dead == fi->fib_nhs) {
-                                fi->fib_flags |= RTNH_F_DEAD;
-                                ret++;
-                        }
-                }
-        } endfor_fib_info();
-        return ret;
+					dead++;
+				}
+			} endfor_nexthops(fi)
+			if (dead == fi->fib_nhs) {
+				fi->fib_flags |= RTNH_F_DEAD;
+				ret++;
+			}
+		}
+	} endfor_fib_info();
+	return ret;
 }
 
 
 static int dn_fib_sync_up(struct net_device *dev)
 {
-        int ret = 0;
+	int ret = 0;
 
-        if (!(dev->flags&IFF_UP))
-                return 0;
+	if (!(dev->flags&IFF_UP))
+		return 0;
 
-        for_fib_info() {
-                int alive = 0;
+	for_fib_info() {
+		int alive = 0;
 
-                change_nexthops(fi) {
-                        if (!(nh->nh_flags&RTNH_F_DEAD)) {
-                                alive++;
-                                continue;
-                        }
-                        if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
-                                continue;
-                        if (nh->nh_dev != dev || dev->dn_ptr == NULL)
-                                continue;
-                        alive++;
+		change_nexthops(fi) {
+			if (!(nh->nh_flags&RTNH_F_DEAD)) {
+				alive++;
+				continue;
+			}
+			if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
+				continue;
+			if (nh->nh_dev != dev || dev->dn_ptr == NULL)
+				continue;
+			alive++;
 			spin_lock_bh(&dn_fib_multipath_lock);
-                        nh->nh_power = 0;
-                        nh->nh_flags &= ~RTNH_F_DEAD;
+			nh->nh_power = 0;
+			nh->nh_flags &= ~RTNH_F_DEAD;
 			spin_unlock_bh(&dn_fib_multipath_lock);
-                } endfor_nexthops(fi);
+		} endfor_nexthops(fi);
 
-                if (alive > 0) {
-                        fi->fib_flags &= ~RTNH_F_DEAD;
-                        ret++;
-                }
-        } endfor_fib_info();
-        return ret;
+		if (alive > 0) {
+			fi->fib_flags &= ~RTNH_F_DEAD;
+			ret++;
+		}
+	} endfor_fib_info();
+	return ret;
 }
 
 static struct notifier_block dn_fib_dnaddr_notifier = {
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 7322bb3..bf701cf 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -3,7 +3,7 @@
  *              operating system.  DECnet is implemented using the  BSD Socket
  *              interface as the means of communication with the user level.
  *
- *              DECnet Neighbour Functions (Adjacency Database and 
+ *              DECnet Neighbour Functions (Adjacency Database and
  *                                                        On-Ethernet Cache)
  *
  * Author:      Steve Whitehouse <SteveW@ACM.org>
@@ -277,19 +277,19 @@
 	struct dn_skb_cb *cb = DN_SKB_CB(skb);
 
 
-        if (skb_headroom(skb) < headroom) {
-                struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
-                if (skb2 == NULL) {
+	if (skb_headroom(skb) < headroom) {
+		struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
+		if (skb2 == NULL) {
 			if (net_ratelimit())
-                        	printk(KERN_CRIT "dn_short_output: no memory\n");
-                        kfree_skb(skb);
-                        return -ENOBUFS;
-                }
-                kfree_skb(skb);
-                skb = skb2;
+				printk(KERN_CRIT "dn_short_output: no memory\n");
+			kfree_skb(skb);
+			return -ENOBUFS;
+		}
+		kfree_skb(skb);
+		skb = skb2;
 		if (net_ratelimit())
-                	printk(KERN_INFO "dn_short_output: Increasing headroom\n");
-        }
+			printk(KERN_INFO "dn_short_output: Increasing headroom\n");
+	}
 
 	data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
 	*((__le16 *)data) = dn_htons(skb->len - 2);
@@ -598,7 +598,7 @@
 	goto out;
 }
 
-static struct file_operations dn_neigh_seq_fops = {
+static const struct file_operations dn_neigh_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= dn_neigh_seq_open,
 	.read		= seq_read,
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 39a6cf7..9d20904 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -33,7 +33,7 @@
 
 /******************************************************************************
     (c) 1995-1998 E.M. Serrat		emserrat@geocities.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
@@ -50,7 +50,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -63,7 +62,7 @@
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
-#include <linux/termios.h>      
+#include <linux/termios.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
@@ -139,7 +138,7 @@
 		ptr++;
 		len += 2;
 		if ((ack & 0x4000) == 0) {
-			if (oth) 
+			if (oth)
 				ack ^= 0x2000;
 			dn_ack(sk, skb, ack);
 		}
@@ -152,7 +151,7 @@
 		skb_pull(skb, 2);
 		len += 2;
 		if ((ack & 0x4000) == 0) {
-			if (oth) 
+			if (oth)
 				ack ^= 0x2000;
 			dn_ack(sk, skb, ack);
 		}
@@ -349,9 +348,9 @@
 
 	if ((scp->state == DN_CI) || (scp->state == DN_CD)) {
 		scp->persist = 0;
-                scp->addrrem = cb->src_port;
-                sk->sk_state = TCP_ESTABLISHED;
-                scp->state = DN_RUN;
+		scp->addrrem = cb->src_port;
+		sk->sk_state = TCP_ESTABLISHED;
+		scp->state = DN_RUN;
 		scp->services_rem = cb->services;
 		scp->info_rem = cb->info;
 		scp->segsize_rem = cb->segsize;
@@ -366,13 +365,13 @@
 				memcpy(scp->conndata_in.opt_data, skb->data + 1, dlen);
 			}
 		}
-                dn_nsp_send_link(sk, DN_NOCHANGE, 0);
-                if (!sock_flag(sk, SOCK_DEAD))
-                	sk->sk_state_change(sk);
-        }
+		dn_nsp_send_link(sk, DN_NOCHANGE, 0);
+		if (!sock_flag(sk, SOCK_DEAD))
+			sk->sk_state_change(sk);
+	}
 
 out:
-        kfree_skb(skb);
+	kfree_skb(skb);
 }
 
 static void dn_nsp_conn_ack(struct sock *sk, struct sk_buff *skb)
@@ -435,7 +434,7 @@
 		sk->sk_state_change(sk);
 	}
 
-	/* 
+	/*
 	 * It appears that its possible for remote machines to send disc
 	 * init messages with no port identifier if we are in the CI and
 	 * possibly also the CD state. Obviously we shouldn't reply with
@@ -519,7 +518,7 @@
 
 	/*
 	 * Here we ignore erronous packets which should really
-	 * should cause a connection abort. It is not critical 
+	 * should cause a connection abort. It is not critical
 	 * for now though.
 	 */
 	if (lsflags & 0xf8)
@@ -530,7 +529,7 @@
 		switch(lsflags & 0x04) { /* FCVAL INT */
 		case 0x00: /* Normal Request */
 			switch(lsflags & 0x03) { /* FCVAL MOD */
-       	         	case 0x00: /* Request count */
+			case 0x00: /* Request count */
 				if (fcval < 0) {
 					unsigned char p_fcval = -fcval;
 					if ((scp->flowrem_dat > p_fcval) &&
@@ -541,7 +540,7 @@
 					scp->flowrem_dat += fcval;
 					wake_up = 1;
 				}
-               	       	 	break;
+				break;
 			case 0x01: /* Stop outgoing data */
 				scp->flowrem_sw = DN_DONTSEND;
 				break;
@@ -557,10 +556,10 @@
 				wake_up = 1;
 			}
 			break;
-                }
+		}
 		if (wake_up && !sock_flag(sk, SOCK_DEAD))
 			sk->sk_state_change(sk);
-        }
+	}
 
 	dn_nsp_send_oth_ack(sk);
 
@@ -576,38 +575,38 @@
 static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig, struct sk_buff_head *queue)
 {
 	int err;
-	
-        /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
-           number of warnings when compiling with -W --ANK
-         */
-        if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
+
+	/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
+	   number of warnings when compiling with -W --ANK
+	 */
+	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
 	    (unsigned)sk->sk_rcvbuf) {
-        	err = -ENOMEM;
-        	goto out;
-        }
+		err = -ENOMEM;
+		goto out;
+	}
 
 	err = sk_filter(sk, skb);
 	if (err)
 		goto out;
 
-        skb_set_owner_r(skb, sk);
-        skb_queue_tail(queue, skb);
+	skb_set_owner_r(skb, sk);
+	skb_queue_tail(queue, skb);
 
 	/* This code only runs from BH or BH protected context.
 	 * Therefore the plain read_lock is ok here. -DaveM
 	 */
 	read_lock(&sk->sk_callback_lock);
-        if (!sock_flag(sk, SOCK_DEAD)) {
+	if (!sock_flag(sk, SOCK_DEAD)) {
 		struct socket *sock = sk->sk_socket;
 		wake_up_interruptible(sk->sk_sleep);
 		if (sock && sock->fasync_list &&
 		    !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
-			__kill_fasync(sock->fasync_list, sig, 
+			__kill_fasync(sock->fasync_list, sig,
 				    (sig == SIGURG) ? POLL_PRI : POLL_IN);
 	}
 	read_unlock(&sk->sk_callback_lock);
 out:
-        return err;
+	return err;
 }
 
 static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb)
@@ -652,16 +651,16 @@
 	skb_pull(skb, 2);
 
 	if (seq_next(scp->numdat_rcv, segnum)) {
-                if (dn_queue_skb(sk, skb, SIGIO, &sk->sk_receive_queue) == 0) {
+		if (dn_queue_skb(sk, skb, SIGIO, &sk->sk_receive_queue) == 0) {
 			seq_add(&scp->numdat_rcv, 1);
-                	queued = 1;
-                }
+			queued = 1;
+		}
 
 		if ((scp->flowloc_sw == DN_SEND) && dn_congested(sk)) {
 			scp->flowloc_sw = DN_DONTSEND;
 			dn_nsp_send_link(sk, DN_DONTSEND, 0);
 		}
-        }
+	}
 
 	dn_nsp_send_data_ack(sk);
 out:
@@ -732,7 +731,7 @@
 	if (decnet_debug_level & 2)
 		printk(KERN_DEBUG "dn_nsp_rx: Message type 0x%02x\n", (int)cb->nsp_flags);
 
-	if (cb->nsp_flags & 0x83) 
+	if (cb->nsp_flags & 0x83)
 		goto free_out;
 
 	/*
@@ -852,7 +851,7 @@
 			case 0x30:
 				dn_nsp_disc_init(sk, skb);
 				break;
-			case 0x40:      
+			case 0x40:
 				dn_nsp_disc_conf(sk, skb);
 				break;
 		}
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
index b342e4e..2d2cda8 100644
--- a/net/decnet/dn_nsp_out.c
+++ b/net/decnet/dn_nsp_out.c
@@ -26,7 +26,7 @@
 
 /******************************************************************************
     (c) 1995-1998 E.M. Serrat		emserrat@geocities.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
@@ -43,7 +43,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -55,7 +54,7 @@
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
-#include <linux/termios.h>      
+#include <linux/termios.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
@@ -176,14 +175,14 @@
 	 * gathering this value might turn out negative, so we make sure
 	 * that is it always positive here.
 	 */
-	if (rtt < 0) 
+	if (rtt < 0)
 		rtt = -rtt;
 	/*
 	 * Add new rtt to smoothed average
 	 */
 	delta = ((rtt << 3) - srtt);
 	srtt += (delta >> 3);
-	if (srtt >= 1) 
+	if (srtt >= 1)
 		scp->nsp_srtt = (unsigned long)srtt;
 	else
 		scp->nsp_srtt = 1;
@@ -193,7 +192,7 @@
 	 */
 	delta >>= 1;
 	rttvar += ((((delta>0)?(delta):(-delta)) - rttvar) >> 2);
-	if (rttvar >= 1) 
+	if (rttvar >= 1)
 		scp->nsp_rttvar = (unsigned long)rttvar;
 	else
 		scp->nsp_rttvar = 1;
@@ -434,7 +433,7 @@
 		 * further.
 		 */
 		if (xmit_count == 1) {
-			if (dn_equal(segnum, acknum)) 
+			if (dn_equal(segnum, acknum))
 				dn_nsp_rtt(sk, (long)(pkttime - reftime));
 
 			if (scp->snd_window < scp->max_window)
@@ -486,16 +485,16 @@
 {
 	struct dn_scp *scp = DN_SK(sk);
 	struct sk_buff *skb = NULL;
-        struct nsp_conn_ack_msg *msg;
+	struct nsp_conn_ack_msg *msg;
 
 	if ((skb = dn_alloc_skb(sk, 3, sk->sk_allocation)) == NULL)
 		return;
 
-        msg = (struct nsp_conn_ack_msg *)skb_put(skb, 3);
-        msg->msgflg = 0x24;                   
+	msg = (struct nsp_conn_ack_msg *)skb_put(skb, 3);
+	msg->msgflg = 0x24;
 	msg->dstaddr = scp->addrrem;
 
-	dn_nsp_send(skb);	
+	dn_nsp_send(skb);
 }
 
 void dn_nsp_delayed_ack(struct sock *sk)
@@ -523,25 +522,25 @@
 {
 	struct dn_scp *scp = DN_SK(sk);
 	struct sk_buff *skb = NULL;
-        struct nsp_conn_init_msg *msg;
+	struct nsp_conn_init_msg *msg;
 	__u8 len = (__u8)dn_ntohs(scp->conndata_out.opt_optl);
 
 	if ((skb = dn_alloc_skb(sk, 50 + len, gfp)) == NULL)
 		return;
 
-        msg = (struct nsp_conn_init_msg *)skb_put(skb, sizeof(*msg));
-        msg->msgflg = 0x28;                   
+	msg = (struct nsp_conn_init_msg *)skb_put(skb, sizeof(*msg));
+	msg->msgflg = 0x28;
 	msg->dstaddr = scp->addrrem;
-        msg->srcaddr = scp->addrloc;
-        msg->services = scp->services_loc;
-        msg->info = scp->info_loc;
-        msg->segsize = dn_htons(scp->segsize_loc);
+	msg->srcaddr = scp->addrloc;
+	msg->services = scp->services_loc;
+	msg->info = scp->info_loc;
+	msg->segsize = dn_htons(scp->segsize_loc);
 
 	*skb_put(skb,1) = len;
 
-	if (len > 0) 
+	if (len > 0)
 		memcpy(skb_put(skb, len), scp->conndata_out.opt_data, len);
-	
+
 
 	dn_nsp_send(skb);
 
@@ -550,7 +549,7 @@
 }
 
 
-static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, 
+static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg,
 			unsigned short reason, gfp_t gfp,
 			struct dst_entry *dst,
 			int ddl, unsigned char *dd, __le16 rem, __le16 loc)
@@ -593,7 +592,7 @@
 }
 
 
-void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg, 
+void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg,
 			unsigned short reason, gfp_t gfp)
 {
 	struct dn_scp *scp = DN_SK(sk);
@@ -605,19 +604,19 @@
 	if (reason == 0)
 		reason = dn_ntohs(scp->discdata_out.opt_status);
 
-	dn_nsp_do_disc(sk, msgflg, reason, gfp, sk->sk_dst_cache, ddl, 
+	dn_nsp_do_disc(sk, msgflg, reason, gfp, sk->sk_dst_cache, ddl,
 		scp->discdata_out.opt_data, scp->addrrem, scp->addrloc);
 }
 
 
-void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg, 
+void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg,
 			unsigned short reason)
 {
 	struct dn_skb_cb *cb = DN_SKB_CB(skb);
 	int ddl = 0;
 	gfp_t gfp = GFP_ATOMIC;
 
-	dn_nsp_do_disc(NULL, msgflg, reason, gfp, skb->dst, ddl, 
+	dn_nsp_do_disc(NULL, msgflg, reason, gfp, skb->dst, ddl,
 			NULL, cb->src_port, cb->dst_port);
 }
 
@@ -676,8 +675,8 @@
 
 	msg->srcaddr	= scp->addrloc;
 	msg->services	= scp->services_loc;	/* Requested flow control    */
-	msg->info	= scp->info_loc;	/* Version Number            */	
-	msg->segsize	= dn_htons(scp->segsize_loc);	/* Max segment size  */	
+	msg->info	= scp->info_loc;	/* Version Number            */
+	msg->segsize	= dn_htons(scp->segsize_loc);	/* Max segment size  */
 
 	if (scp->peer.sdn_objnum)
 		type = 0;
@@ -692,7 +691,7 @@
 		menuver |= DN_MENUVER_UIC;
 
 	*skb_put(skb, 1) = menuver;	/* Menu Version		*/
-	
+
 	aux = scp->accessdata.acc_userl;
 	*skb_put(skb, 1) = aux;
 	if (aux > 0)
@@ -718,6 +717,6 @@
 
 	cb->rt_flags = DN_RT_F_RQR;
 
-	dn_nsp_send(skb);	
+	dn_nsp_send(skb);
 }
 
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 9881933..c1b5502 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -43,7 +43,7 @@
 
 /******************************************************************************
     (c) 1995-1998 E.M. Serrat		emserrat@geocities.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
@@ -167,11 +167,11 @@
 		while((rt=*rtp) != NULL) {
 			if (atomic_read(&rt->u.dst.__refcnt) ||
 					(now - rt->u.dst.lastuse) < expire) {
-				rtp = &rt->u.rt_next;
+				rtp = &rt->u.dst.dn_next;
 				continue;
 			}
-			*rtp = rt->u.rt_next;
-			rt->u.rt_next = NULL;
+			*rtp = rt->u.dst.dn_next;
+			rt->u.dst.dn_next = NULL;
 			dnrt_free(rt);
 		}
 		spin_unlock(&dn_rt_hash_table[i].lock);
@@ -198,11 +198,11 @@
 		while((rt=*rtp) != NULL) {
 			if (atomic_read(&rt->u.dst.__refcnt) ||
 					(now - rt->u.dst.lastuse) < expire) {
-				rtp = &rt->u.rt_next;
+				rtp = &rt->u.dst.dn_next;
 				continue;
 			}
-			*rtp = rt->u.rt_next;
-			rt->u.rt_next = NULL;
+			*rtp = rt->u.dst.dn_next;
+			rt->u.dst.dn_next = NULL;
 			dnrt_drop(rt);
 			break;
 		}
@@ -246,7 +246,7 @@
 	}
 }
 
-/* 
+/*
  * When a route has been marked obsolete. (e.g. routing cache flush)
  */
 static struct dst_entry *dn_dst_check(struct dst_entry *dst, __u32 cookie)
@@ -286,8 +286,8 @@
 	while((rth = *rthp) != NULL) {
 		if (compare_keys(&rth->fl, &rt->fl)) {
 			/* Put it first */
-			*rthp = rth->u.rt_next;
-			rcu_assign_pointer(rth->u.rt_next,
+			*rthp = rth->u.dst.dn_next;
+			rcu_assign_pointer(rth->u.dst.dn_next,
 					   dn_rt_hash_table[hash].chain);
 			rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth);
 
@@ -300,12 +300,12 @@
 			*rp = rth;
 			return 0;
 		}
-		rthp = &rth->u.rt_next;
+		rthp = &rth->u.dst.dn_next;
 	}
 
-	rcu_assign_pointer(rt->u.rt_next, dn_rt_hash_table[hash].chain);
+	rcu_assign_pointer(rt->u.dst.dn_next, dn_rt_hash_table[hash].chain);
 	rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt);
-	
+
 	dst_hold(&rt->u.dst);
 	rt->u.dst.__use++;
 	rt->u.dst.lastuse = now;
@@ -326,8 +326,8 @@
 			goto nothing_to_declare;
 
 		for(; rt; rt=next) {
-			next = rt->u.rt_next;
-			rt->u.rt_next = NULL;
+			next = rt->u.dst.dn_next;
+			rt->u.dst.dn_next = NULL;
 			dst_free((struct dst_entry *)rt);
 		}
 
@@ -506,23 +506,23 @@
 	skb_pull(skb, 20);
 	skb->h.raw = skb->data;
 
-        /* Destination info */
-        ptr += 2;
+	/* Destination info */
+	ptr += 2;
 	cb->dst = dn_eth2dn(ptr);
-        if (memcmp(ptr, dn_hiord_addr, 4) != 0)
-                goto drop_it;
-        ptr += 6;
+	if (memcmp(ptr, dn_hiord_addr, 4) != 0)
+		goto drop_it;
+	ptr += 6;
 
 
-        /* Source info */
-        ptr += 2;
+	/* Source info */
+	ptr += 2;
 	cb->src = dn_eth2dn(ptr);
-        if (memcmp(ptr, dn_hiord_addr, 4) != 0)
-                goto drop_it;
-        ptr += 6;
-        /* Other junk */
-        ptr++;
-        cb->hops = *ptr++; /* Visit Count */
+	if (memcmp(ptr, dn_hiord_addr, 4) != 0)
+		goto drop_it;
+	ptr += 6;
+	/* Other junk */
+	ptr++;
+	cb->hops = *ptr++; /* Visit Count */
 
 	return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, dn_route_rx_packet);
 
@@ -545,16 +545,16 @@
 	skb->h.raw = skb->data;
 
 	cb->dst = *(__le16 *)ptr;
-        ptr += 2;
-        cb->src = *(__le16 *)ptr;
-        ptr += 2;
-        cb->hops = *ptr & 0x3f;
+	ptr += 2;
+	cb->src = *(__le16 *)ptr;
+	ptr += 2;
+	cb->hops = *ptr & 0x3f;
 
 	return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, dn_route_rx_packet);
 
 drop_it:
-        kfree_skb(skb);
-        return NET_RX_DROP;
+	kfree_skb(skb);
+	return NET_RX_DROP;
 }
 
 static int dn_route_discard(struct sk_buff *skb)
@@ -626,20 +626,20 @@
 	cb->rt_flags = flags;
 
 	if (decnet_debug_level & 1)
-		printk(KERN_DEBUG 
+		printk(KERN_DEBUG
 			"dn_route_rcv: got 0x%02x from %s [%d %d %d]\n",
-			(int)flags, (dev) ? dev->name : "???", len, skb->len, 
+			(int)flags, (dev) ? dev->name : "???", len, skb->len,
 			padlen);
 
-        if (flags & DN_RT_PKT_CNTL) {
+	if (flags & DN_RT_PKT_CNTL) {
 		if (unlikely(skb_linearize(skb)))
 			goto dump_it;
 
-                switch(flags & DN_RT_CNTL_MSK) {
-        	        case DN_RT_PKT_INIT:
+		switch(flags & DN_RT_CNTL_MSK) {
+			case DN_RT_PKT_INIT:
 				dn_dev_init_pkt(skb);
 				break;
-                	case DN_RT_PKT_VERI:
+			case DN_RT_PKT_VERI:
 				dn_dev_veri_pkt(skb);
 				break;
 		}
@@ -648,31 +648,31 @@
 			goto dump_it;
 
 		switch(flags & DN_RT_CNTL_MSK) {
-                	case DN_RT_PKT_HELO:
+			case DN_RT_PKT_HELO:
 				return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_route_ptp_hello);
 
-                	case DN_RT_PKT_L1RT:
-                	case DN_RT_PKT_L2RT:
-                                return NF_HOOK(PF_DECnet, NF_DN_ROUTE, skb, skb->dev, NULL, dn_route_discard);
-                	case DN_RT_PKT_ERTH:
+			case DN_RT_PKT_L1RT:
+			case DN_RT_PKT_L2RT:
+				return NF_HOOK(PF_DECnet, NF_DN_ROUTE, skb, skb->dev, NULL, dn_route_discard);
+			case DN_RT_PKT_ERTH:
 				return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_router_hello);
 
-                	case DN_RT_PKT_EEDH:
+			case DN_RT_PKT_EEDH:
 				return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_endnode_hello);
-                }
-        } else {
+		}
+	} else {
 		if (dn->parms.state != DN_DEV_S_RU)
 			goto dump_it;
 
 		skb_pull(skb, 1); /* Pull flags */
 
-                switch(flags & DN_RT_PKT_MSK) {
-                	case DN_RT_PKT_LONG:
-                        	return dn_route_rx_long(skb);
-                	case DN_RT_PKT_SHORT:
-                        	return dn_route_rx_short(skb);
+		switch(flags & DN_RT_PKT_MSK) {
+			case DN_RT_PKT_LONG:
+				return dn_route_rx_long(skb);
+			case DN_RT_PKT_SHORT:
+				return dn_route_rx_short(skb);
 		}
-        }
+	}
 
 dump_it:
 	kfree_skb(skb);
@@ -815,8 +815,8 @@
 		rt->u.dst.neighbour = n;
 	}
 
-	if (rt->u.dst.metrics[RTAX_MTU-1] == 0 || 
-            rt->u.dst.metrics[RTAX_MTU-1] > rt->u.dst.dev->mtu)
+	if (rt->u.dst.metrics[RTAX_MTU-1] == 0 ||
+	    rt->u.dst.metrics[RTAX_MTU-1] > rt->u.dst.dev->mtu)
 		rt->u.dst.metrics[RTAX_MTU-1] = rt->u.dst.dev->mtu;
 	mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->u.dst));
 	if (rt->u.dst.metrics[RTAX_ADVMSS-1] == 0 ||
@@ -876,7 +876,7 @@
 
 static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *oldflp, int try_hard)
 {
-	struct flowi fl = { .nl_u = { .dn_u = 
+	struct flowi fl = { .nl_u = { .dn_u =
 				      { .daddr = oldflp->fld_dst,
 					.saddr = oldflp->fld_src,
 					.scope = RT_SCOPE_UNIVERSE,
@@ -899,7 +899,7 @@
 		       "dn_route_output_slow: dst=%04x src=%04x mark=%d"
 		       " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst),
 		       dn_ntohs(oldflp->fld_src),
-                       oldflp->mark, loopback_dev.ifindex, oldflp->oif);
+		       oldflp->mark, loopback_dev.ifindex, oldflp->oif);
 
 	/* If we have an output interface, verify its a DECnet device */
 	if (oldflp->oif) {
@@ -982,19 +982,19 @@
 		if (err != -ESRCH)
 			goto out;
 		/*
-	 	 * Here the fallback is basically the standard algorithm for 
+		 * Here the fallback is basically the standard algorithm for
 		 * routing in endnodes which is described in the DECnet routing
 		 * docs
 		 *
 		 * If we are not trying hard, look in neighbour cache.
 		 * The result is tested to ensure that if a specific output
-		 * device/source address was requested, then we honour that 
+		 * device/source address was requested, then we honour that
 		 * here
 		 */
 		if (!try_hard) {
 			neigh = neigh_lookup_nodev(&dn_neigh_table, &fl.fld_dst);
 			if (neigh) {
-				if ((oldflp->oif && 
+				if ((oldflp->oif &&
 				    (neigh->dev->ifindex != oldflp->oif)) ||
 				    (oldflp->fld_src &&
 				    (!dn_dev_islocal(neigh->dev,
@@ -1044,7 +1044,7 @@
 		if (fl.fld_src == 0) {
 			fl.fld_src = dnet_select_source(dev_out, gateway,
 							 res.type == RTN_LOCAL ?
-							 RT_SCOPE_HOST : 
+							 RT_SCOPE_HOST :
 							 RT_SCOPE_LINK);
 			if (fl.fld_src == 0 && res.type != RTN_LOCAL)
 				goto e_addr;
@@ -1074,14 +1074,14 @@
 	if (res.fi->fib_nhs > 1 && fl.oif == 0)
 		dn_fib_select_multipath(&fl, &res);
 
-	/* 
+	/*
 	 * We could add some logic to deal with default routes here and
 	 * get rid of some of the special casing above.
 	 */
 
 	if (!fl.fld_src)
 		fl.fld_src = DN_FIB_RES_PREFSRC(res);
-	
+
 	if (dev_out)
 		dev_put(dev_out);
 	dev_out = DN_FIB_RES_DEV(res);
@@ -1144,8 +1144,8 @@
 	return err;
 
 e_addr:
-        err = -EADDRNOTAVAIL;
-        goto done;
+	err = -EADDRNOTAVAIL;
+	goto done;
 e_inval:
 	err = -EINVAL;
 	goto done;
@@ -1169,7 +1169,7 @@
 	if (!(flags & MSG_TRYHARD)) {
 		rcu_read_lock_bh();
 		for(rt = rcu_dereference(dn_rt_hash_table[hash].chain); rt;
-			rt = rcu_dereference(rt->u.rt_next)) {
+			rt = rcu_dereference(rt->u.dst.dn_next)) {
 			if ((flp->fld_dst == rt->fl.fld_dst) &&
 			    (flp->fld_src == rt->fl.fld_src) &&
 			    (flp->mark == rt->fl.mark) &&
@@ -1223,7 +1223,7 @@
 	int flags = 0;
 	__le16 gateway = 0;
 	__le16 local_src = 0;
-	struct flowi fl = { .nl_u = { .dn_u = 
+	struct flowi fl = { .nl_u = { .dn_u =
 				     { .daddr = cb->dst,
 				       .saddr = cb->src,
 				       .scope = RT_SCOPE_UNIVERSE,
@@ -1311,7 +1311,7 @@
 		if (res.fi->fib_nhs > 1 && fl.oif == 0)
 			dn_fib_select_multipath(&fl, &res);
 
-		/* 
+		/*
 		 * Check for out_dev == in_dev. We use the RTCF_DOREDIRECT
 		 * flag as a hint to set the intra-ethernet bit when
 		 * forwarding. If we've got NAT in operation, we don't do
@@ -1443,9 +1443,9 @@
 
 	rcu_read_lock();
 	for(rt = rcu_dereference(dn_rt_hash_table[hash].chain); rt != NULL;
-	    rt = rcu_dereference(rt->u.rt_next)) {
+	    rt = rcu_dereference(rt->u.dst.dn_next)) {
 		if ((rt->fl.fld_src == cb->src) &&
-	 	    (rt->fl.fld_dst == cb->dst) &&
+		    (rt->fl.fld_dst == cb->dst) &&
 		    (rt->fl.oif == 0) &&
 		    (rt->fl.mark == skb->mark) &&
 		    (rt->fl.iif == cb->iif)) {
@@ -1514,8 +1514,8 @@
 
 nlmsg_failure:
 rtattr_failure:
-        skb_trim(skb, b - skb->data);
-        return -1;
+	skb_trim(skb, b - skb->data);
+	return -1;
 }
 
 /*
@@ -1627,12 +1627,12 @@
 		rcu_read_lock_bh();
 		for(rt = rcu_dereference(dn_rt_hash_table[h].chain), idx = 0;
 			rt;
-			rt = rcu_dereference(rt->u.rt_next), idx++) {
+			rt = rcu_dereference(rt->u.dst.dn_next), idx++) {
 			if (idx < s_idx)
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
 			if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
-					cb->nlh->nlmsg_seq, RTM_NEWROUTE, 
+					cb->nlh->nlmsg_seq, RTM_NEWROUTE,
 					1, NLM_F_MULTI) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
 				rcu_read_unlock_bh();
@@ -1673,7 +1673,7 @@
 {
 	struct dn_rt_cache_iter_state *s = rcu_dereference(seq->private);
 
-	rt = rt->u.rt_next;
+	rt = rt->u.dst.dn_next;
 	while(!rt) {
 		rcu_read_unlock_bh();
 		if (--s->bucket < 0)
@@ -1721,7 +1721,7 @@
 			rt->u.dst.__use,
 			(int) dst_metric(&rt->u.dst, RTAX_RTT));
 	return 0;
-} 
+}
 
 static struct seq_operations dn_rt_cache_seq_ops = {
 	.start	= dn_rt_cache_seq_start,
@@ -1751,7 +1751,7 @@
 	goto out;
 }
 
-static struct file_operations dn_rt_cache_seq_fops = {
+static const struct file_operations dn_rt_cache_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = dn_rt_cache_seq_open,
 	.read	 = seq_read,
@@ -1778,38 +1778,38 @@
 	for(order = 0; (1UL << order) < goal; order++)
 		/* NOTHING */;
 
-        /*
-         * Only want 1024 entries max, since the table is very, very unlikely
-         * to be larger than that.
-         */
-        while(order && ((((1UL << order) * PAGE_SIZE) / 
-                                sizeof(struct dn_rt_hash_bucket)) >= 2048))
-                order--;
+	/*
+	 * Only want 1024 entries max, since the table is very, very unlikely
+	 * to be larger than that.
+	 */
+	while(order && ((((1UL << order) * PAGE_SIZE) /
+				sizeof(struct dn_rt_hash_bucket)) >= 2048))
+		order--;
 
-        do {
-                dn_rt_hash_mask = (1UL << order) * PAGE_SIZE /
-                        sizeof(struct dn_rt_hash_bucket);
-                while(dn_rt_hash_mask & (dn_rt_hash_mask - 1))
-                        dn_rt_hash_mask--;
-                dn_rt_hash_table = (struct dn_rt_hash_bucket *)
-                        __get_free_pages(GFP_ATOMIC, order);
-        } while (dn_rt_hash_table == NULL && --order > 0);
+	do {
+		dn_rt_hash_mask = (1UL << order) * PAGE_SIZE /
+			sizeof(struct dn_rt_hash_bucket);
+		while(dn_rt_hash_mask & (dn_rt_hash_mask - 1))
+			dn_rt_hash_mask--;
+		dn_rt_hash_table = (struct dn_rt_hash_bucket *)
+			__get_free_pages(GFP_ATOMIC, order);
+	} while (dn_rt_hash_table == NULL && --order > 0);
 
 	if (!dn_rt_hash_table)
-                panic("Failed to allocate DECnet route cache hash table\n");
+		panic("Failed to allocate DECnet route cache hash table\n");
 
-	printk(KERN_INFO 
-		"DECnet: Routing cache hash table of %u buckets, %ldKbytes\n", 
-		dn_rt_hash_mask, 
+	printk(KERN_INFO
+		"DECnet: Routing cache hash table of %u buckets, %ldKbytes\n",
+		dn_rt_hash_mask,
 		(long)(dn_rt_hash_mask*sizeof(struct dn_rt_hash_bucket))/1024);
 
 	dn_rt_hash_mask--;
-        for(i = 0; i <= dn_rt_hash_mask; i++) {
-                spin_lock_init(&dn_rt_hash_table[i].lock);
-                dn_rt_hash_table[i].chain = NULL;
-        }
+	for(i = 0; i <= dn_rt_hash_mask; i++) {
+		spin_lock_init(&dn_rt_hash_table[i].lock);
+		dn_rt_hash_table[i].chain = NULL;
+	}
 
-        dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
+	dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
 
 	proc_net_fops_create("decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
 }
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index e32d0c3..b6c98ac 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -151,10 +151,10 @@
 	}
 
 	if (tb[FRA_SRC])
-		r->src = nla_get_u16(tb[FRA_SRC]);
+		r->src = nla_get_le16(tb[FRA_SRC]);
 
 	if (tb[FRA_DST])
-		r->dst = nla_get_u16(tb[FRA_DST]);
+		r->dst = nla_get_le16(tb[FRA_DST]);
 
 	r->src_len = frh->src_len;
 	r->srcmask = dnet_make_mask(r->src_len);
@@ -176,10 +176,10 @@
 	if (frh->dst_len && (r->dst_len != frh->dst_len))
 		return 0;
 
-	if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC])))
+	if (tb[FRA_SRC] && (r->src != nla_get_le16(tb[FRA_SRC])))
 		return 0;
 
-	if (tb[FRA_DST] && (r->dst != nla_get_u16(tb[FRA_DST])))
+	if (tb[FRA_DST] && (r->dst != nla_get_le16(tb[FRA_DST])))
 		return 0;
 
 	return 1;
@@ -214,9 +214,9 @@
 	frh->tos = 0;
 
 	if (r->dst_len)
-		NLA_PUT_U16(skb, FRA_DST, r->dst);
+		NLA_PUT_LE16(skb, FRA_DST, r->dst);
 	if (r->src_len)
-		NLA_PUT_U16(skb, FRA_SRC, r->src);
+		NLA_PUT_LE16(skb, FRA_SRC, r->src);
 
 	return 0;
 
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 13b2421..780a141 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -60,7 +60,7 @@
 #define dz_prefix(key,dz)	((key).datum)
 
 #define for_nexthops(fi) { int nhsel; const struct dn_fib_nh *nh;\
-        for(nhsel = 0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
+	for(nhsel = 0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
 
 #define endfor_nexthops(fi) }
 
@@ -290,94 +290,97 @@
 }
 
 static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-                        u32 tb_id, u8 type, u8 scope, void *dst, int dst_len,
-                        struct dn_fib_info *fi, unsigned int flags)
+			u32 tb_id, u8 type, u8 scope, void *dst, int dst_len,
+			struct dn_fib_info *fi, unsigned int flags)
 {
-        struct rtmsg *rtm;
-        struct nlmsghdr *nlh;
-        unsigned char *b = skb->tail;
+	struct rtmsg *rtm;
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
 
-        nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
-        rtm = NLMSG_DATA(nlh);
-        rtm->rtm_family = AF_DECnet;
-        rtm->rtm_dst_len = dst_len;
-        rtm->rtm_src_len = 0;
-        rtm->rtm_tos = 0;
-        rtm->rtm_table = tb_id;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
+	rtm = NLMSG_DATA(nlh);
+	rtm->rtm_family = AF_DECnet;
+	rtm->rtm_dst_len = dst_len;
+	rtm->rtm_src_len = 0;
+	rtm->rtm_tos = 0;
+	rtm->rtm_table = tb_id;
 	RTA_PUT_U32(skb, RTA_TABLE, tb_id);
-        rtm->rtm_flags = fi->fib_flags;
-        rtm->rtm_scope = scope;
+	rtm->rtm_flags = fi->fib_flags;
+	rtm->rtm_scope = scope;
 	rtm->rtm_type  = type;
-        if (rtm->rtm_dst_len)
-                RTA_PUT(skb, RTA_DST, 2, dst);
-        rtm->rtm_protocol = fi->fib_protocol;
-        if (fi->fib_priority)
-                RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority);
+	if (rtm->rtm_dst_len)
+		RTA_PUT(skb, RTA_DST, 2, dst);
+	rtm->rtm_protocol = fi->fib_protocol;
+	if (fi->fib_priority)
+		RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority);
 	if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0)
 		goto rtattr_failure;
-        if (fi->fib_nhs == 1) {
-                if (fi->fib_nh->nh_gw)
-                        RTA_PUT(skb, RTA_GATEWAY, 2, &fi->fib_nh->nh_gw);
-                if (fi->fib_nh->nh_oif)
-                        RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif);
-        }
-        if (fi->fib_nhs > 1) {
-                struct rtnexthop *nhp;
-                struct rtattr *mp_head;
-                if (skb_tailroom(skb) <= RTA_SPACE(0))
-                        goto rtattr_failure;
-                mp_head = (struct rtattr *)skb_put(skb, RTA_SPACE(0));
+	if (fi->fib_nhs == 1) {
+		if (fi->fib_nh->nh_gw)
+			RTA_PUT(skb, RTA_GATEWAY, 2, &fi->fib_nh->nh_gw);
+		if (fi->fib_nh->nh_oif)
+			RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif);
+	}
+	if (fi->fib_nhs > 1) {
+		struct rtnexthop *nhp;
+		struct rtattr *mp_head;
+		if (skb_tailroom(skb) <= RTA_SPACE(0))
+			goto rtattr_failure;
+		mp_head = (struct rtattr *)skb_put(skb, RTA_SPACE(0));
 
-                for_nexthops(fi) {
-                        if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
-                                goto rtattr_failure;
-                        nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
-                        nhp->rtnh_flags = nh->nh_flags & 0xFF;
-                        nhp->rtnh_hops = nh->nh_weight - 1;
-                        nhp->rtnh_ifindex = nh->nh_oif;
-                        if (nh->nh_gw)
-                                RTA_PUT(skb, RTA_GATEWAY, 2, &nh->nh_gw);
-                        nhp->rtnh_len = skb->tail - (unsigned char *)nhp;
-                } endfor_nexthops(fi);
-                mp_head->rta_type = RTA_MULTIPATH;
-                mp_head->rta_len = skb->tail - (u8*)mp_head;
-        }
+		for_nexthops(fi) {
+			if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
+				goto rtattr_failure;
+			nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
+			nhp->rtnh_flags = nh->nh_flags & 0xFF;
+			nhp->rtnh_hops = nh->nh_weight - 1;
+			nhp->rtnh_ifindex = nh->nh_oif;
+			if (nh->nh_gw)
+				RTA_PUT(skb, RTA_GATEWAY, 2, &nh->nh_gw);
+			nhp->rtnh_len = skb->tail - (unsigned char *)nhp;
+		} endfor_nexthops(fi);
+		mp_head->rta_type = RTA_MULTIPATH;
+		mp_head->rta_len = skb->tail - (u8*)mp_head;
+	}
 
-        nlh->nlmsg_len = skb->tail - b;
-        return skb->len;
+	nlh->nlmsg_len = skb->tail - b;
+	return skb->len;
 
 
 nlmsg_failure:
 rtattr_failure:
-        skb_trim(skb, b - skb->data);
-        return -1;
+	skb_trim(skb, b - skb->data);
+	return -EMSGSIZE;
 }
 
 
 static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id,
-                        struct nlmsghdr *nlh, struct netlink_skb_parms *req)
+			struct nlmsghdr *nlh, struct netlink_skb_parms *req)
 {
-        struct sk_buff *skb;
-        u32 pid = req ? req->pid : 0;
+	struct sk_buff *skb;
+	u32 pid = req ? req->pid : 0;
 	int err = -ENOBUFS;
 
-        skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f)), GFP_KERNEL);
-        if (skb == NULL)
+	skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f)), GFP_KERNEL);
+	if (skb == NULL)
 		goto errout;
 
-        err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
+	err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
 			       f->fn_type, f->fn_scope, &f->fn_key, z,
 			       DN_FIB_INFO(f), 0);
-	/* failure implies BUG in dn_fib_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in dn_fib_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
 errout:
 	if (err < 0)
 		rtnl_set_sk_err(RTNLGRP_DECnet_ROUTE, err);
 }
 
-static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb, 
+static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
 				struct netlink_callback *cb,
 				struct dn_fib_table *tb,
 				struct dn_zone *dz,
@@ -391,12 +394,12 @@
 			continue;
 		if (f->fn_state & DN_S_ZOMBIE)
 			continue;
-		if (dn_fib_dump_info(skb, NETLINK_CB(cb->skb).pid, 
+		if (dn_fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
 				cb->nlh->nlmsg_seq,
 				RTM_NEWROUTE,
-				tb->n, 
+				tb->n,
 				(f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type,
-				f->fn_scope, &f->fn_key, dz->dz_order, 
+				f->fn_scope, &f->fn_key, dz->dz_order,
 				f->fn_info, NLM_F_MULTI) < 0) {
 			cb->args[4] = i;
 			return -1;
@@ -406,7 +409,7 @@
 	return skb->len;
 }
 
-static __inline__ int dn_hash_dump_zone(struct sk_buff *skb, 
+static __inline__ int dn_hash_dump_zone(struct sk_buff *skb,
 				struct netlink_callback *cb,
 				struct dn_fib_table *tb,
 				struct dn_zone *dz)
@@ -430,10 +433,10 @@
 	return skb->len;
 }
 
-static int dn_fib_table_dump(struct dn_fib_table *tb, struct sk_buff *skb, 
-                                struct netlink_callback *cb)
+static int dn_fib_table_dump(struct dn_fib_table *tb, struct sk_buff *skb,
+				struct netlink_callback *cb)
 {
-        int m, s_m;
+	int m, s_m;
 	struct dn_zone *dz;
 	struct dn_hash *table = (struct dn_hash *)tb->data;
 
@@ -454,7 +457,7 @@
 	read_unlock(&dn_fib_tables_lock);
 	cb->args[2] = m;
 
-        return skb->len;
+	return skb->len;
 }
 
 int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
@@ -479,7 +482,7 @@
 				goto next;
 			if (dumped)
 				memset(&cb->args[2], 0, sizeof(cb->args) -
-				                 2 * sizeof(cb->args[0]));
+						 2 * sizeof(cb->args[0]));
 			if (tb->dump(tb, skb, cb) < 0)
 				goto out;
 			dumped = 1;
@@ -500,13 +503,13 @@
 	struct dn_fib_node *new_f, *f, **fp, **del_fp;
 	struct dn_zone *dz;
 	struct dn_fib_info *fi;
-        int z = r->rtm_dst_len;
+	int z = r->rtm_dst_len;
 	int type = r->rtm_type;
 	dn_fib_key_t key;
-        int err;
+	int err;
 
-        if (z > 16)
-                return -EINVAL;
+	if (z > 16)
+		return -EINVAL;
 
 	dz = table->dh_zones[z];
 	if (!dz && !(dz = dn_new_zone(table, z)))
@@ -521,8 +524,8 @@
 		key = dz_key(dst, dz);
 	}
 
-        if ((fi = dn_fib_create_info(r, rta, n, &err)) == NULL)
-                return err;
+	if ((fi = dn_fib_create_info(r, rta, n, &err)) == NULL)
+		return err;
 
 	if (dz->dz_nent > (dz->dz_divisor << 2) &&
 			dz->dz_divisor > DN_MAX_DIVISOR &&
@@ -590,12 +593,10 @@
 
 replace:
 	err = -ENOBUFS;
-	new_f = kmem_cache_alloc(dn_hash_kmem, GFP_KERNEL);
+	new_f = kmem_cache_zalloc(dn_hash_kmem, GFP_KERNEL);
 	if (new_f == NULL)
 		goto out;
 
-	memset(new_f, 0, sizeof(struct dn_fib_node));
-
 	new_f->fn_key = key;
 	new_f->fn_type = type;
 	new_f->fn_scope = r->rtm_scope;
@@ -623,9 +624,9 @@
 		dn_rt_cache_flush(-1);
 	}
 
-        dn_rtmsg_fib(RTM_NEWROUTE, new_f, z, tb->n, n, req);
+	dn_rtmsg_fib(RTM_NEWROUTE, new_f, z, tb->n, n, req);
 
-        return 0;
+	return 0;
 out:
 	dn_fib_release_info(fi);
 	return err;
@@ -636,14 +637,14 @@
 {
 	struct dn_hash *table = (struct dn_hash*)tb->data;
 	struct dn_fib_node **fp, **del_fp, *f;
-        int z = r->rtm_dst_len;
+	int z = r->rtm_dst_len;
 	struct dn_zone *dz;
 	dn_fib_key_t key;
 	int matched;
 
 
-        if (z > 16)
-                return -EINVAL;
+	if (z > 16)
+		return -EINVAL;
 
 	if ((dz = table->dh_zones[z]) == NULL)
 		return -ESRCH;
@@ -679,7 +680,7 @@
 		if (del_fp == NULL &&
 				(!r->rtm_type || f->fn_type == r->rtm_type) &&
 				(r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
-				(!r->rtm_protocol || 
+				(!r->rtm_protocol ||
 					fi->fib_protocol == r->rtm_protocol) &&
 				dn_fib_nh_match(r, n, rta, fi) == 0)
 			del_fp = fp;
@@ -687,7 +688,7 @@
 
 	if (del_fp) {
 		f = *del_fp;
-        	dn_rtmsg_fib(RTM_DELROUTE, f, z, tb->n, n, req);
+		dn_rtmsg_fib(RTM_DELROUTE, f, z, tb->n, n, req);
 
 		if (matched != 1) {
 			write_lock_bh(&dn_fib_tables_lock);
@@ -711,7 +712,7 @@
 		return 0;
 	}
 
-        return -ESRCH;
+	return -ESRCH;
 }
 
 static inline int dn_flush_list(struct dn_fib_node **fp, int z, struct dn_hash *table)
@@ -758,7 +759,7 @@
 
 static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct flowi *flp, struct dn_fib_res *res)
 {
-        int err;
+	int err;
 	struct dn_zone *dz;
 	struct dn_hash *t = (struct dn_hash *)tb->data;
 
@@ -787,7 +788,7 @@
 
 			if (err == 0) {
 				res->type = f->fn_type;
-				res->scope = f->fn_scope; 
+				res->scope = f->fn_scope;
 				res->prefixlen = dz->dz_order;
 				goto out;
 			}
@@ -798,21 +799,21 @@
 	err = 1;
 out:
 	read_unlock(&dn_fib_tables_lock);
-        return err;
+	return err;
 }
 
 
 struct dn_fib_table *dn_fib_get_table(u32 n, int create)
 {
-        struct dn_fib_table *t;
+	struct dn_fib_table *t;
 	struct hlist_node *node;
 	unsigned int h;
 
-        if (n < RT_TABLE_MIN)
-                return NULL;
+	if (n < RT_TABLE_MIN)
+		return NULL;
 
-        if (n > RT_TABLE_MAX)
-                return NULL;
+	if (n > RT_TABLE_MAX)
+		return NULL;
 
 	h = n & (DN_FIB_TABLE_HASHSZ - 1);
 	rcu_read_lock();
@@ -824,54 +825,54 @@
 	}
 	rcu_read_unlock();
 
-        if (!create)
-                return NULL;
+	if (!create)
+		return NULL;
 
-        if (in_interrupt() && net_ratelimit()) {
-                printk(KERN_DEBUG "DECnet: BUG! Attempt to create routing table from interrupt\n"); 
-                return NULL;
-        }
+	if (in_interrupt() && net_ratelimit()) {
+		printk(KERN_DEBUG "DECnet: BUG! Attempt to create routing table from interrupt\n");
+		return NULL;
+	}
 
-        t = kzalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash),
+	t = kzalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash),
 		    GFP_KERNEL);
-        if (t == NULL)
-                return NULL;
+	if (t == NULL)
+		return NULL;
 
-        t->n = n;
-        t->insert = dn_fib_table_insert;
-        t->delete = dn_fib_table_delete;
-        t->lookup = dn_fib_table_lookup;
-        t->flush  = dn_fib_table_flush;
-        t->dump = dn_fib_table_dump;
+	t->n = n;
+	t->insert = dn_fib_table_insert;
+	t->delete = dn_fib_table_delete;
+	t->lookup = dn_fib_table_lookup;
+	t->flush  = dn_fib_table_flush;
+	t->dump = dn_fib_table_dump;
 	hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]);
 
-        return t;
+	return t;
 }
 
 struct dn_fib_table *dn_fib_empty_table(void)
 {
-        u32 id;
+	u32 id;
 
-        for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++)
+	for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++)
 		if (dn_fib_get_table(id, 0) == NULL)
-                        return dn_fib_get_table(id, 1);
-        return NULL;
+			return dn_fib_get_table(id, 1);
+	return NULL;
 }
 
 void dn_fib_flush(void)
 {
-        int flushed = 0;
-        struct dn_fib_table *tb;
+	int flushed = 0;
+	struct dn_fib_table *tb;
 	struct hlist_node *node;
 	unsigned int h;
 
 	for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
 		hlist_for_each_entry(tb, node, &dn_fib_table_hash[h], hlist)
-	                flushed += tb->flush(tb);
-        }
+			flushed += tb->flush(tb);
+	}
 
-        if (flushed)
-                dn_rt_cache_flush(-1);
+	if (flushed)
+		dn_rt_cache_flush(-1);
 }
 
 void __init dn_fib_table_init(void)
@@ -891,7 +892,7 @@
 	write_lock(&dn_fib_tables_lock);
 	for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
 		hlist_for_each_entry_safe(t, node, next, &dn_fib_table_hash[h],
-		                          hlist) {
+					  hlist) {
 			hlist_del(&t->hlist);
 			kfree(t);
 		}
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 8b99bd3..0e62def 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -138,7 +138,7 @@
 	int rv = 0;
 
 	dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, DNRNG_NLGRP_MAX,
-	                              dnrmg_receive_user_sk, THIS_MODULE);
+				      dnrmg_receive_user_sk, THIS_MODULE);
 	if (dnrmg == NULL) {
 		printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
 		return -ENOMEM;
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c
index a4065eb..52e40d7 100644
--- a/net/decnet/sysctl_net_decnet.c
+++ b/net/decnet/sysctl_net_decnet.c
@@ -164,7 +164,7 @@
 	return 0;
 }
 
-static int dn_node_address_handler(ctl_table *table, int write, 
+static int dn_node_address_handler(ctl_table *table, int write,
 				struct file *filp,
 				void __user *buffer,
 				size_t *lenp, loff_t *ppos)
@@ -240,7 +240,7 @@
 			}
 
 			namel = strlen(devname) + 1;
-			if (len > namel) len = namel;	
+			if (len > namel) len = namel;
 
 			if (copy_to_user(oldval, devname, len))
 				return -EFAULT;
@@ -275,7 +275,7 @@
 }
 
 
-static int dn_def_dev_handler(ctl_table *table, int write, 
+static int dn_def_dev_handler(ctl_table *table, int write,
 				struct file * filp,
 				void __user *buffer,
 				size_t *lenp, loff_t *ppos)
@@ -341,17 +341,17 @@
 
 static ctl_table dn_table[] = {
 	{
-		.ctl_name = NET_DECNET_NODE_ADDRESS, 
-		.procname = "node_address", 
-		.maxlen = 7, 
-		.mode = 0644, 
+		.ctl_name = NET_DECNET_NODE_ADDRESS,
+		.procname = "node_address",
+		.maxlen = 7,
+		.mode = 0644,
 		.proc_handler = dn_node_address_handler,
 		.strategy = dn_node_address_strategy,
 	},
 	{
 		.ctl_name = NET_DECNET_NODE_NAME,
 		.procname = "node_name",
-		.data = node_name, 
+		.data = node_name,
 		.maxlen = 7,
 		.mode = 0644,
 		.proc_handler = &proc_dostring,
@@ -359,8 +359,8 @@
 	},
 	{
 		.ctl_name = NET_DECNET_DEFAULT_DEVICE,
-		.procname = "default_device", 
-		.maxlen = 16, 
+		.procname = "default_device",
+		.maxlen = 16,
 		.mode = 0644,
 		.proc_handler = dn_def_dev_handler,
 		.strategy = dn_def_dev_strategy,
@@ -432,32 +432,32 @@
 		.extra2 = &max_decnet_no_fc_max_cwnd
 	},
        {
-                .ctl_name = NET_DECNET_MEM,
-                .procname = "decnet_mem",
-                .data = &sysctl_decnet_mem,
-                .maxlen = sizeof(sysctl_decnet_mem),
-                .mode = 0644,
-                .proc_handler = &proc_dointvec,
-                .strategy = &sysctl_intvec,
-        },
-        {
-                .ctl_name = NET_DECNET_RMEM,
-                .procname = "decnet_rmem",
-                .data = &sysctl_decnet_rmem,
-                .maxlen = sizeof(sysctl_decnet_rmem),
-                .mode = 0644,
-                .proc_handler = &proc_dointvec,
-                .strategy = &sysctl_intvec,
-        },
-        {
-                .ctl_name = NET_DECNET_WMEM,
-                .procname = "decnet_wmem",
-                .data = &sysctl_decnet_wmem,
-                .maxlen = sizeof(sysctl_decnet_wmem),
-                .mode = 0644,
-                .proc_handler = &proc_dointvec,
-                .strategy = &sysctl_intvec,
-        },
+		.ctl_name = NET_DECNET_MEM,
+		.procname = "decnet_mem",
+		.data = &sysctl_decnet_mem,
+		.maxlen = sizeof(sysctl_decnet_mem),
+		.mode = 0644,
+		.proc_handler = &proc_dointvec,
+		.strategy = &sysctl_intvec,
+	},
+	{
+		.ctl_name = NET_DECNET_RMEM,
+		.procname = "decnet_rmem",
+		.data = &sysctl_decnet_rmem,
+		.maxlen = sizeof(sysctl_decnet_rmem),
+		.mode = 0644,
+		.proc_handler = &proc_dointvec,
+		.strategy = &sysctl_intvec,
+	},
+	{
+		.ctl_name = NET_DECNET_WMEM,
+		.procname = "decnet_wmem",
+		.data = &sysctl_decnet_wmem,
+		.maxlen = sizeof(sysctl_decnet_wmem),
+		.mode = 0644,
+		.proc_handler = &proc_dointvec,
+		.strategy = &sysctl_intvec,
+	},
 	{
 		.ctl_name = NET_DECNET_DEBUG_LEVEL,
 		.procname = "debug",
@@ -472,18 +472,18 @@
 
 static ctl_table dn_dir_table[] = {
 	{
-		.ctl_name = NET_DECNET, 
-		.procname = "decnet", 
-		.mode = 0555, 
+		.ctl_name = NET_DECNET,
+		.procname = "decnet",
+		.mode = 0555,
 		.child = dn_table},
 	{0}
 };
 
 static ctl_table dn_root_table[] = {
 	{
-		.ctl_name = CTL_NET, 
-		.procname = "net", 
-		.mode = 0555, 
+		.ctl_name = CTL_NET,
+		.procname = "net",
+		.mode = 0555,
 		.child = dn_dir_table
 	},
 	{0}
@@ -491,7 +491,7 @@
 
 void dn_register_sysctl(void)
 {
-	dn_table_header = register_sysctl_table(dn_root_table, 1);
+	dn_table_header = register_sysctl_table(dn_root_table);
 }
 
 void dn_unregister_sysctl(void)
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 4d66aac..bc12e36 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -13,7 +13,6 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -139,7 +138,7 @@
 	skb=skb_recv_datagram(sk,flags,flags&MSG_DONTWAIT,&err);
 
 	/*
-	 *	An error occurred so return it. Because skb_recv_datagram() 
+	 *	An error occurred so return it. Because skb_recv_datagram()
 	 *	handles the blocking we don't see and worry about blocking
 	 *	retries.
 	 */
@@ -190,15 +189,15 @@
 	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
 	struct sock *sk;
 	struct econet_sock *eo;
-	
+
 	/*
 	 *	Check legality
 	 */
-	 
+
 	if (addr_len < sizeof(struct sockaddr_ec) ||
 	    sec->sec_family != AF_ECONET)
 		return -EINVAL;
-	
+
 	mutex_lock(&econet_mutex);
 
 	sk = sock->sk;
@@ -283,18 +282,18 @@
 	int i;
 	mm_segment_t oldfs;
 #endif
-		
+
 	/*
-	 *	Check the flags. 
+	 *	Check the flags.
 	 */
 
-	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) 
+	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
 		return -EINVAL;
 
 	/*
-	 *	Get and verify the address. 
+	 *	Get and verify the address.
 	 */
-	 
+
 	mutex_lock(&econet_mutex);
 
 	if (saddr == NULL) {
@@ -339,17 +338,17 @@
 		unsigned short proto = 0;
 
 		dev_hold(dev);
-		
-		skb = sock_alloc_send_skb(sk, len+LL_RESERVED_SPACE(dev), 
+
+		skb = sock_alloc_send_skb(sk, len+LL_RESERVED_SPACE(dev),
 					  msg->msg_flags & MSG_DONTWAIT, &err);
 		if (skb==NULL)
 			goto out_unlock;
-		
+
 		skb_reserve(skb, LL_RESERVED_SPACE(dev));
 		skb->nh.raw = skb->data;
-		
+
 		eb = (struct ec_cb *)&skb->cb;
-		
+
 		/* BUG: saddr may be NULL */
 		eb->cookie = saddr->cookie;
 		eb->sec = *saddr;
@@ -359,7 +358,7 @@
 			int res;
 			struct ec_framehdr *fh;
 			err = -EINVAL;
-			res = dev->hard_header(skb, dev, ntohs(proto), 
+			res = dev->hard_header(skb, dev, ntohs(proto),
 					       &addr, NULL, len);
 			/* Poke in our control byte and
 			   port number.  Hack, hack.  */
@@ -372,7 +371,7 @@
 			} else if (res < 0)
 				goto out_free;
 		}
-		
+
 		/* Copy the data. Returns -EFAULT on error */
 		err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
 		skb->protocol = proto;
@@ -380,15 +379,15 @@
 		skb->priority = sk->sk_priority;
 		if (err)
 			goto out_free;
-		
+
 		err = -ENETDOWN;
 		if (!(dev->flags & IFF_UP))
 			goto out_free;
-		
+
 		/*
 		 *	Now send it
 		 */
-		
+
 		dev_queue_xmit(skb);
 		dev_put(dev);
 		mutex_unlock(&econet_mutex);
@@ -414,7 +413,7 @@
 		mutex_unlock(&econet_mutex);
 		return -ENETDOWN;		/* No socket - can't send */
 	}
-	
+
 	/* Make up a UDP datagram and hand it off to some higher intellect. */
 
 	memset(&udpdest, 0, sizeof(udpdest));
@@ -432,7 +431,7 @@
 		idev = __in_dev_get_rcu(dev);
 		if (idev) {
 			if (idev->ifa_list)
-				network = ntohl(idev->ifa_list->ifa_address) & 
+				network = ntohl(idev->ifa_list->ifa_address) &
 					0xffffff00;		/* !!! */
 		}
 		rcu_read_unlock();
@@ -470,7 +469,7 @@
 	}
 
 	/* Get a skbuff (no data, just holds our cb information) */
-	if ((skb = sock_alloc_send_skb(sk, 0, 
+	if ((skb = sock_alloc_send_skb(sk, 0,
 				       msg->msg_flags & MSG_DONTWAIT,
 				       &err)) == NULL) {
 		mutex_unlock(&econet_mutex);
@@ -660,7 +659,7 @@
 	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
 		return -EFAULT;
 
-	if ((dev = dev_get_by_name(ifr.ifr_name)) == NULL) 
+	if ((dev = dev_get_by_name(ifr.ifr_name)) == NULL)
 		return -ENODEV;
 
 	sec = (struct sockaddr_ec *)&ifr.ifr_addr;
@@ -754,7 +753,7 @@
 	.connect =	sock_no_connect,
 	.socketpair =	sock_no_socketpair,
 	.accept =	sock_no_accept,
-	.getname =	econet_getname, 
+	.getname =	econet_getname,
 	.poll =		datagram_poll,
 	.ioctl =	econet_ioctl,
 	.listen =	sock_no_listen,
@@ -780,7 +779,7 @@
 
 	sk_for_each(sk, node, &econet_sklist) {
 		struct econet_sock *opt = ec_sk(sk);
-		if ((opt->port == port || opt->port == 0) && 
+		if ((opt->port == port || opt->port == 0) &&
 		    (opt->station == station || opt->station == 0) &&
 		    (opt->net == net || opt->net == 0))
 			goto found;
@@ -815,7 +814,7 @@
 
 #ifdef CONFIG_ECONET_AUNUDP
 /*
- *	Send an AUN protocol response. 
+ *	Send an AUN protocol response.
  */
 
 static void aun_send_response(__u32 addr, unsigned long seq, int code, int cb)
@@ -828,7 +827,7 @@
 	struct aunhdr ah = {.code = code, .cb = cb, .handle = seq};
 	struct kvec iov = {.iov_base = (void *)&ah, .iov_len = sizeof(ah)};
 	struct msghdr udpmsg;
-	
+
 	udpmsg.msg_name = (void *)&sin;
 	udpmsg.msg_namelen = sizeof(sin);
 	udpmsg.msg_control = NULL;
@@ -858,7 +857,7 @@
 	if ((sk = ec_listening_socket(ah->port, stn, edev->net)) == NULL)
 		goto bad;		/* Nobody wants it */
 
-	newskb = alloc_skb((len - sizeof(struct aunhdr) + 15) & ~15, 
+	newskb = alloc_skb((len - sizeof(struct aunhdr) + 15) & ~15,
 			   GFP_ATOMIC);
 	if (newskb == NULL)
 	{
@@ -867,7 +866,7 @@
 		goto bad;
 	}
 
-	memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah+1), 
+	memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah+1),
 	       len - sizeof(struct aunhdr));
 
 	if (ec_queue_packet(sk, newskb, stn, edev->net, ah->cb, ah->port))
@@ -990,7 +989,7 @@
 		struct ec_cb *eb = (struct ec_cb *)&skb->cb;
 		if ((jiffies - eb->start) > eb->timeout)
 		{
-			tx_result(skb->sk, eb->cookie, 
+			tx_result(skb->sk, eb->cookie,
 				  ECTYPE_TRANSMIT_NOT_PRESENT);
 			skb_unlink(skb, &aun_queue);
 			kfree_skb(skb);
@@ -1024,11 +1023,11 @@
 		printk("AUN: socket error %d\n", -error);
 		return error;
 	}
-	
+
 	udpsock->sk->sk_reuse = 1;
 	udpsock->sk->sk_allocation = GFP_ATOMIC; /* we're going to call it
 						    from interrupts */
-	
+
 	error = udpsock->ops->bind(udpsock, (struct sockaddr *)&sin,
 				sizeof(sin));
 	if (error < 0)
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 2d31bf3..7391f55 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -12,14 +12,14 @@
  *		Mark Evans, <evansmp@uhura.aston.ac.uk>
  *		Florian  La Roche, <rzsfl@rz.uni-sb.de>
  *		Alan Cox, <gw4pts@gw4pts.ampr.org>
- * 
+ *
  * Fixes:
  *		Mr Linux	: Arp problems
  *		Alan Cox	: Generic queue tidyup (very tiny here)
  *		Alan Cox	: eth_header ntohs should be htons
  *		Alan Cox	: eth_rebuild_header missing an htons and
  *				  minor other things.
- *		Tegge		: Arp bug fixes. 
+ *		Tegge		: Arp bug fixes.
  *		Florian		: Removed many unnecessary functions, code cleanup
  *				  and changes for new arp and skbuff.
  *		Alan Cox	: Redid header building to reflect new format.
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -307,9 +306,9 @@
 	dev->hard_header_len 	= ETH_HLEN;
 	dev->mtu		= ETH_DATA_LEN;
 	dev->addr_len		= ETH_ALEN;
-	dev->tx_queue_len	= 1000;	/* Ethernet wants good queues */	
+	dev->tx_queue_len	= 1000;	/* Ethernet wants good queues */
 	dev->flags		= IFF_BROADCAST|IFF_MULTICAST;
-	
+
 	memset(dev->broadcast, 0xFF, ETH_ALEN);
 
 }
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index 7a95c3d..ec6d885 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -97,7 +97,7 @@
 	struct prism2_wep_data *wep = priv;
 	u32 klen, len;
 	u8 *pos;
-	
+
 	if (skb_headroom(skb) < 4 || skb->len < hdr_len)
 		return -1;
 
@@ -146,17 +146,17 @@
 	/* other checks are in prism2_wep_build_iv */
 	if (skb_tailroom(skb) < 4)
 		return -1;
-	
+
 	/* add the IV to the frame */
 	if (prism2_wep_build_iv(skb, hdr_len, NULL, 0, priv))
 		return -1;
-	
+
 	/* Copy the IV into the first 3 bytes of the key */
 	memcpy(key, skb->data + hdr_len, 3);
 
 	/* Copy rest of the WEP key (the secret part) */
 	memcpy(key + 3, wep->key, wep->key_len);
-	
+
 	len = skb->len - hdr_len - 4;
 	pos = skb->data + hdr_len + 4;
 	klen = 3 + wep->key_len;
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index d97e541..4084909 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -663,7 +663,7 @@
 	 * any security data (IV, ICV, etc) that was left behind */
 	if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) &&
 	    ieee->host_strip_iv_icv) {
-	    	int trimlen = 0;
+		int trimlen = 0;
 
 		/* Top two-bits of byte 3 are the key index */
 		if (skb->len >= hdrlen + 3)
@@ -852,7 +852,7 @@
 
 	if ((fc & IEEE80211_FCTL_VERS) != 0)
 		goto drop_free;
-		
+
 	switch (fc & IEEE80211_FCTL_FTYPE) {
 	case IEEE80211_FTYPE_MGMT:
 		if (skb->len < sizeof(struct ieee80211_hdr_3addr))
@@ -1489,7 +1489,7 @@
 
 	/* We only update the statistics if they were created by receiving
 	 * the network information on the actual channel the network is on.
-	 * 
+	 *
 	 * This keeps beacons received on neighbor channels from bringing
 	 * down the signal level of an AP. */
 	if (dst->channel == src->stats.received_channel)
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 854fc13..0292d63 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -54,7 +54,7 @@
       |      | tion | (BSSID) |         |         | ence |  data   |      |
       `--------------------------------------------------|         |------'
 Total: 28 non-data bytes                                 `----.----'
-                                                              |
+							      |
        .- 'Frame data' expands, if WEP enabled, to <----------'
        |
        V
@@ -64,8 +64,8 @@
 Desc. | IV  | Encrypted | ICV |
       |     | Packet    |     |
       `-----|           |-----'
-            `-----.-----'
-                  |
+	    `-----.-----'
+		  |
        .- 'Encrypted Packet' expands to
        |
        V
@@ -502,9 +502,6 @@
 		if (host_encrypt)
 			ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
 		else if (host_build_iv) {
-			struct ieee80211_crypt_data *crypt;
-
-			crypt = ieee->crypt[ieee->tx_keyidx];
 			atomic_inc(&crypt->refcnt);
 			if (crypt->ops->build_iv)
 				crypt->ops->build_iv(skb_frag, hdr_len,
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 5cb9cfd..40d7a55 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -754,7 +754,7 @@
 	int err = 0;
 
 	spin_lock_irqsave(&ieee->lock, flags);
-	
+
 	switch (wrqu->param.flags & IW_AUTH_INDEX) {
 	case IW_AUTH_WPA_VERSION:
 	case IW_AUTH_CIPHER_PAIRWISE:
@@ -799,7 +799,7 @@
 	int err = 0;
 
 	spin_lock_irqsave(&ieee->lock, flags);
-	
+
 	switch (wrqu->param.flags & IW_AUTH_INDEX) {
 	case IW_AUTH_WPA_VERSION:
 	case IW_AUTH_CIPHER_PAIRWISE:
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index a824852..cc8110b 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -30,7 +30,7 @@
  * Overview
  *
  * Before you can associate, you have to authenticate.
- * 
+ *
  */
 
 /* Sends out an association request to the desired AP */
@@ -41,10 +41,10 @@
 
 	/* Switch to correct channel for this network */
 	mac->set_channel(mac->dev, net->channel);
-	
+
 	/* Send association request */
 	ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_ASSOC_REQ, 0);
-	
+
 	dprintk(KERN_INFO PFX "sent association request!\n");
 
 	spin_lock_irqsave(&mac->lock, flags);
@@ -153,7 +153,7 @@
 	}
 
 	/* if 'ANY' network requested, take any that doesn't have privacy enabled */
-	if (mac->associnfo.req_essid.len == 0 
+	if (mac->associnfo.req_essid.len == 0
 	    && !(net->capability & WLAN_CAPABILITY_PRIVACY))
 		return 1;
 	if (net->ssid_len != mac->associnfo.req_essid.len)
@@ -212,8 +212,8 @@
 
 	/* try to find the requested network in our list, if we found one already */
 	if (bssvalid || mac->associnfo.bssfixed)
-		found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);	
-	
+		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,
 	 * but only if we've scanned at least once (to get a better list of networks to
 	 * select from). If we have not scanned before, the !found logic below will be
@@ -265,7 +265,7 @@
 		if (mac->associnfo.scan_retry > 0) {
 			mac->associnfo.scan_retry--;
 
-			/* We know of no such network. Let's scan. 
+			/* We know of no such network. Let's scan.
 			 * NB: this also happens if we had no memory to copy the network info...
 			 * Maybe we can hope to have more memory after scanning finishes ;)
 			 */
@@ -353,7 +353,7 @@
 		mac->set_bssid_filter(mac->dev, net->bssid);
 	memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN);
 	netif_carrier_on(mac->dev);
-	
+
 	mac->association_id = le16_to_cpup(&resp->aid);
 }
 
@@ -374,7 +374,7 @@
 
 	if (unlikely(!mac->running))
 		return -ENODEV;
-	
+
 	spin_lock_irqsave(&mac->lock, flags);
 
 	if (!mac->associnfo.associating) {
@@ -426,7 +426,7 @@
 			mac->associnfo.associated = 0;
 			ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network);
 	}
-	
+
 	spin_unlock_irqrestore(&mac->lock, flags);
 	return 0;
 }
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index 8ed3e59..826c32d 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -30,12 +30,12 @@
 
 /* Queues an auth request to the desired AP */
 int
-ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, 
+ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
 	struct ieee80211softmac_network *net)
 {
 	struct ieee80211softmac_auth_queue_item *auth;
 	unsigned long flags;
-	
+
 	if (net->authenticating || net->authenticated)
 		return 0;
 	net->authenticating = 1;
@@ -55,7 +55,7 @@
 	auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT;
 	auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST;
 	INIT_DELAYED_WORK(&auth->work, ieee80211softmac_auth_queue);
-	
+
 	/* Lock (for list) */
 	spin_lock_irqsave(&mac->lock, flags);
 
@@ -63,7 +63,7 @@
 	list_add_tail(&auth->list, &mac->auth_queue);
 	schedule_delayed_work(&auth->work, 0);
 	spin_unlock_irqrestore(&mac->lock, flags);
-	
+
 	return 0;
 }
 
@@ -85,7 +85,7 @@
 	if(auth->retry > 0) {
 		/* Switch to correct channel for this network */
 		mac->set_channel(mac->dev, net->channel);
-		
+
 		/* Lock and set flags */
 		spin_lock_irqsave(&mac->lock, flags);
 		if (unlikely(!mac->running)) {
@@ -130,11 +130,11 @@
 }
 
 /* Handle the auth response from the AP
- * This should be registered with ieee80211 as handle_auth 
+ * This should be registered with ieee80211 as handle_auth
  */
-int 
+int
 ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
-{	
+{
 
 	struct list_head *list_ptr;
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
@@ -142,7 +142,7 @@
 	struct ieee80211softmac_network *net = NULL;
 	unsigned long flags;
 	u8 * data;
-	
+
 	if (unlikely(!mac->running))
 		return -ENODEV;
 
@@ -157,15 +157,15 @@
 			aq = NULL;
 	}
 	spin_unlock_irqrestore(&mac->lock, flags);
-	
+
 	/* Make sure that we've got an auth queue item for this request */
 	if(aq == NULL)
 	{
 		dprintkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2));
 		/* Error #? */
 		return -1;
-	}			
-	
+	}
+
 	/* Check for out of order authentication */
 	if(!net->authenticating)
 	{
@@ -182,10 +182,10 @@
 		case WLAN_STATUS_SUCCESS:
 			/* Update the status to Authenticated */
 			spin_lock_irqsave(&mac->lock, flags);
-		        net->authenticating = 0;
+			net->authenticating = 0;
 			net->authenticated = 1;
 			spin_unlock_irqrestore(&mac->lock, flags);
-			
+
 			/* Send event */
 			printkl(KERN_NOTICE PFX "Open Authentication completed with "MAC_FMT"\n", MAC_ARG(net->bssid));
 			ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
@@ -196,8 +196,8 @@
 			net->authenticated = 0;
 			net->authenticating = 0;
 			spin_unlock_irqrestore(&mac->lock, flags);
-			
-			printkl(KERN_NOTICE PFX "Open Authentication with "MAC_FMT" failed, error code: %i\n", 
+
+			printkl(KERN_NOTICE PFX "Open Authentication with "MAC_FMT" failed, error code: %i\n",
 				MAC_ARG(net->bssid), le16_to_cpup(&auth->status));
 			/* Count the error? */
 			break;
@@ -212,11 +212,11 @@
 			data = (u8 *)auth->info_element;
 			if (*data++ != MFIE_TYPE_CHALLENGE) {
 				printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n");
-				break;	
+				break;
 			}
 			/* Save the challenge */
 			spin_lock_irqsave(&mac->lock, flags);
-			net->challenge_len = *data++; 	
+			net->challenge_len = *data++;
 			if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
 				net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
 			kfree(net->challenge);
@@ -229,7 +229,7 @@
 				spin_unlock_irqrestore(&mac->lock, flags);
 				break;
 			}
-			aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; 
+			aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
 
 			/* We reuse the work struct from the auth request here.
 			 * It is safe to do so as each one is per-request, and
@@ -248,22 +248,22 @@
 			/* Check the status code of the response */
 			switch(auth->status) {
 			case WLAN_STATUS_SUCCESS:
-				/* Update the status to Authenticated */	
+				/* Update the status to Authenticated */
 				spin_lock_irqsave(&mac->lock, flags);
 				net->authenticating = 0;
 				net->authenticated = 1;
 				spin_unlock_irqrestore(&mac->lock, flags);
-				printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n", 
+				printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n",
 					MAC_ARG(net->bssid));
 				ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
 				break;
 			default:
-				printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n", 
+				printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n",
 					MAC_ARG(net->bssid), le16_to_cpup(&auth->status));
 				/* Lock and reset flags */
 				spin_lock_irqsave(&mac->lock, flags);
- 				net->authenticating = 0;
- 				net->authenticated = 0;
+				net->authenticating = 0;
+				net->authenticated = 0;
 				spin_unlock_irqrestore(&mac->lock, flags);
 				/* Count the error? */
 				break;
@@ -277,7 +277,7 @@
 		goto free_aq;
 		break;
 	default:
-		/* ERROR */	
+		/* ERROR */
 		goto free_aq;
 		break;
 	}
@@ -313,7 +313,7 @@
 	spin_lock_irqsave(&mac->lock, flags);
 	net->authenticating = 0;
 	net->authenticated = 0;
-	
+
 	/* Find correct auth queue item, if it exists */
 	list_for_each(list_ptr, &mac->auth_queue) {
 		aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
@@ -322,7 +322,7 @@
 		else
 			aq = NULL;
 	}
-	
+
 	/* Cancel pending work */
 	if(aq != NULL)
 		/* Not entirely safe?  What about running work? */
@@ -333,7 +333,7 @@
 	if(net->challenge != NULL)
 		kfree(net->challenge);
 	kfree(net);
-	
+
 	/* can't transmit data right now... */
 	netif_carrier_off(mac->dev);
 	spin_unlock_irqrestore(&mac->lock, flags);
@@ -341,15 +341,15 @@
 	ieee80211softmac_try_reassoc(mac);
 }
 
-/* 
+/*
  * Sends a deauth request to the desired AP
  */
-int 
-ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, 
+int
+ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
 	struct ieee80211softmac_network *net, int reason)
 {
 	int ret;
-	
+
 	/* Make sure the network is authenticated */
 	if (!net->authenticated)
 	{
@@ -357,25 +357,25 @@
 		/* Error okay? */
 		return -EPERM;
 	}
-	
+
 	/* Send the de-auth packet */
 	if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason)))
 		return ret;
-	
+
 	ieee80211softmac_deauth_from_net(mac, net);
 	return 0;
 }
- 
+
 /*
  * This should be registered with ieee80211 as handle_deauth
  */
-int 
+int
 ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth)
 {
-	
+
 	struct ieee80211softmac_network *net = NULL;
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-	
+
 	if (unlikely(!mac->running))
 		return -ENODEV;
 
@@ -385,7 +385,7 @@
 	}
 
 	net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2);
-	
+
 	if (net == NULL) {
 		dprintkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n",
 			MAC_ARG(deauth->header.addr2));
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index b901565..b3e33a4 100644
--- a/net/ieee80211/softmac/ieee80211softmac_event.c
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -79,7 +79,7 @@
 		container_of(work, struct ieee80211softmac_event, work.work);
 	struct ieee80211softmac_event event = *pevent;
 	kfree(pevent);
-	
+
 	event.fun(event.mac->dev, event.event_type, event.context);
 }
 
@@ -92,14 +92,14 @@
 
 	if (event < -1 || event > IEEE80211SOFTMAC_EVENT_LAST)
 		return -ENOSYS;
-	
+
 	if (!fun)
 		return -EINVAL;
-	
+
 	eventptr = kmalloc(sizeof(struct ieee80211softmac_event), gfp_mask);
 	if (!eventptr)
 		return -ENOMEM;
-	
+
 	eventptr->event_type = event;
 	INIT_DELAYED_WORK(&eventptr->work, ieee80211softmac_notify_callback);
 	eventptr->fun = fun;
@@ -122,7 +122,7 @@
 
 	if (event < 0 || event > IEEE80211SOFTMAC_EVENT_LAST)
 		return -ENOSYS;
-	
+
 	return ieee80211softmac_notify_internal(mac, event, NULL, fun, context, gfp_mask);
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_notify_gfp);
@@ -133,7 +133,7 @@
 {
 	struct ieee80211softmac_event *eventptr, *tmp;
 	struct ieee80211softmac_network *network;
-	
+
 	if (event >= 0) {
 		union iwreq_data wrqu;
 		int we_event;
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index b969310..26c3525 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Some parts based on code from net80211
  * Copyright (c) 2001 Atsushi Onoe
  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
@@ -29,14 +29,14 @@
  * 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.
- * 
+ *
  */
 
 #include "ieee80211softmac_priv.h"
 
 /* Helper functions for inserting data into the frames */
 
-/* 
+/*
  * Adds an ESSID element to the frame
  *
  */
@@ -53,7 +53,7 @@
 		*dst++ = 0;
 		return dst;
 	}
-}     
+}
 
 /* Adds Supported Rates and if required Extended Rates Information Element
  * to the frame, ASSUMES WE HAVE A SORTED LIST OF RATES */
@@ -81,18 +81,18 @@
 			memcpy(dst, r->rates + cck_len, ofdm_len);
 			dst += ofdm_len;
 		}
-	}	
+	}
 	return dst;
 }
 
 /* Allocate a management frame */
-static u8 * 
+static u8 *
 ieee80211softmac_alloc_mgt(u32 size)
 {
 	u8 * data;
-	
+
 	/* Add the header and FCS to the size */
-	size = size + IEEE80211_3ADDR_LEN;	
+	size = size + IEEE80211_3ADDR_LEN;
 	if(size > IEEE80211_DATA_LEN)
 		return NULL;
 	/* Allocate the frame */
@@ -103,13 +103,13 @@
 /*
  * Add a 2 Address Header
  */
-static void 
+static void
 ieee80211softmac_hdr_2addr(struct ieee80211softmac_device *mac,
 	struct ieee80211_hdr_2addr *header, u32 type, u8 *dest)
 {
 	/* Fill in the frame control flags */
 	header->frame_ctl = cpu_to_le16(type);
-	/* Control packets always have WEP turned off */	
+	/* Control packets always have WEP turned off */
 	if(type > IEEE80211_STYPE_CFENDACK && type < IEEE80211_STYPE_PSPOLL)
 		header->frame_ctl |= mac->ieee->sec.level ? cpu_to_le16(IEEE80211_FCTL_PROTECTED) : 0;
 
@@ -130,13 +130,13 @@
 
 
 /* Add a 3 Address Header */
-static void 
+static void
 ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
 	struct ieee80211_hdr_3addr *header, u32 type, u8 *dest, u8 *bssid)
 {
 	/* This is common with 2addr, so use that instead */
-	ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest);	
-	
+	ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest);
+
 	/* Fill in the BSS ID */
 	if(bssid == NULL)
 		memset(header->addr3, 0xFF, ETH_ALEN);
@@ -201,11 +201,11 @@
 
 /*****************************************************************************
  * Create Management packets
- *****************************************************************************/ 
+ *****************************************************************************/
 
 /* Creates an association request packet */
 static u32
-ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt, 
+ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
 	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
 {
 	u8 *data;
@@ -233,7 +233,7 @@
 
 	/* Fill in Listen Interval (?) */
 	(*pkt)->listen_interval = cpu_to_le16(10);
-	
+
 	data = (u8 *)(*pkt)->info_element;
 	/* Add SSID */
 	data = ieee80211softmac_add_essid(data, &net->essid);
@@ -250,7 +250,7 @@
 
 /* Create a reassociation request packet */
 static u32
-ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt, 
+ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
 	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
 {
 	u8 *data;
@@ -263,9 +263,9 @@
 		/* Rates IE */
 		1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
 		/* Extended Rates IE */
-		1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN 
+		1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN
 		/* Other IE's? */
-	);				
+	);
 	if (unlikely((*pkt) == NULL))
 		return 0;
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
@@ -277,10 +277,10 @@
 	(*pkt)->listen_interval = cpu_to_le16(10);
 	/* Fill in the current AP MAC */
 	memcpy((*pkt)->current_ap, mac->ieee->bssid, ETH_ALEN);
-	
+
 	data = (u8 *)(*pkt)->info_element;
 	/* Add SSID */
-	data = ieee80211softmac_add_essid(data, &net->essid); 
+	data = ieee80211softmac_add_essid(data, &net->essid);
 	/* Add Rates */
 	data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
 	/* Return packet size */
@@ -289,7 +289,7 @@
 
 /* Create an authentication packet */
 static u32
-ieee80211softmac_auth(struct ieee80211_auth **pkt, 
+ieee80211softmac_auth(struct ieee80211_auth **pkt,
 	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
 	u16 transaction, u16 status, int *encrypt_mpdu)
 {
@@ -309,20 +309,20 @@
 	if (unlikely((*pkt) == NULL))
 		return 0;
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
-		
+
 	/* Algorithm */
 	(*pkt)->algorithm = cpu_to_le16(auth_mode);
 	/* Transaction */
 	(*pkt)->transaction = cpu_to_le16(transaction);
 	/* Status */
 	(*pkt)->status = cpu_to_le16(status);
-	
+
 	data = (u8 *)(*pkt)->info_element;
 	/* Challenge Text */
 	if (is_shared_response) {
 		*data = MFIE_TYPE_CHALLENGE;
 		data++;
-		
+
 		/* Copy the challenge in */
 		*data = net->challenge_len;
 		data++;
@@ -360,7 +360,7 @@
 ieee80211softmac_probe_req(struct ieee80211_probe_request **pkt,
 	struct ieee80211softmac_device *mac, struct ieee80211softmac_essid *essid)
 {
-	u8 *data;	
+	u8 *data;
 	/* Allocate Packet */
 	(*pkt) = (struct ieee80211_probe_request *)ieee80211softmac_alloc_mgt(
 		/* SSID of requested network */
@@ -368,12 +368,12 @@
 		/* Rates IE */
 		1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
 		/* Extended Rates IE */
-		1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN 
+		1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN
 	);
 	if (unlikely((*pkt) == NULL))
 		return 0;
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_REQ, NULL, NULL);
-		
+
 	data = (u8 *)(*pkt)->info_element;
 	/* Add ESSID (can be NULL) */
 	data = ieee80211softmac_add_essid(data, essid);
@@ -401,7 +401,7 @@
 		2 +		/* DS Parameter Set */
 		8 +		/* CF Parameter Set */
 		4 		/* IBSS Parameter Set */
-	);	
+	);
 	if (unlikely((*pkt) == NULL))
 		return 0;
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_RESP, net->bssid, net->bssid);
@@ -445,15 +445,15 @@
 		pkt_size = ieee80211softmac_probe_resp((struct ieee80211_probe_response **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
 		break;
 	default:
-                printkl(KERN_DEBUG PFX "Unsupported Management Frame type: %i\n", type);
-                return -EINVAL;
+		printkl(KERN_DEBUG PFX "Unsupported Management Frame type: %i\n", type);
+		return -EINVAL;
 	};
 
 	if(pkt_size == 0 || pkt == NULL) {
 		printkl(KERN_DEBUG PFX "Error, packet is nonexistant or 0 length\n");
 		return -ENOMEM;
 	}
-	
+
 	/* Send the packet to the ieee80211 layer for tx */
 	/* we defined softmac->mgmt_xmit for this. Should we keep it
 	 * as it is (that means we'd need to wrap this into a txb),
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 256207b..e9cdc66 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -32,19 +32,19 @@
 {
 	struct ieee80211softmac_device *softmac;
 	struct net_device *dev;
-	
+
 	dev = alloc_ieee80211(sizeof(struct ieee80211softmac_device) + sizeof_priv);
 	softmac = ieee80211_priv(dev);
 	softmac->dev = dev;
 	softmac->ieee = netdev_priv(dev);
 	spin_lock_init(&softmac->lock);
-	
+
 	softmac->ieee->handle_auth = ieee80211softmac_auth_resp;
 	softmac->ieee->handle_deauth = ieee80211softmac_deauth_resp;
 	softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response;
 	softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req;
 	softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
- 	softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon;
+	softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon;
 	softmac->scaninfo = NULL;
 
 	softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
@@ -66,37 +66,37 @@
 
 	/* to start with, we can't send anything ... */
 	netif_carrier_off(dev);
-	
+
 	return dev;
 }
 EXPORT_SYMBOL_GPL(alloc_ieee80211softmac);
 
 /* Clears the pending work queue items, stops all scans, etc. */
-void 
+void
 ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
 {
 	unsigned long flags;
 	struct ieee80211softmac_event *eventptr, *eventtmp;
 	struct ieee80211softmac_auth_queue_item *authptr, *authtmp;
 	struct ieee80211softmac_network *netptr, *nettmp;
-	
+
 	ieee80211softmac_stop_scan(sm);
 	ieee80211softmac_wait_for_scan(sm);
-	
+
 	spin_lock_irqsave(&sm->lock, flags);
 	sm->running = 0;
 
 	/* Free all pending assoc work items */
 	cancel_delayed_work(&sm->associnfo.work);
-	
+
 	/* Free all pending scan work items */
 	if(sm->scaninfo != NULL)
-		cancel_delayed_work(&sm->scaninfo->softmac_scan);	
-	
+		cancel_delayed_work(&sm->scaninfo->softmac_scan);
+
 	/* Free all pending auth work items */
 	list_for_each_entry(authptr, &sm->auth_queue, list)
 		cancel_delayed_work(&authptr->work);
-	
+
 	/* delete all pending event calls and work items */
 	list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list)
 		cancel_delayed_work(&eventptr->work);
@@ -111,13 +111,13 @@
 		list_del(&authptr->list);
 		kfree(authptr);
 	}
-	
+
 	/* delete all pending event calls and work items */
 	list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) {
 		list_del(&eventptr->list);
 		kfree(eventptr);
 	}
-		
+
 	/* Free all networks */
 	list_for_each_entry_safe(netptr, nettmp, &sm->network_list, list) {
 		ieee80211softmac_del_network_locked(sm, netptr);
@@ -133,7 +133,7 @@
 void free_ieee80211softmac(struct net_device *dev)
 {
 	struct ieee80211softmac_device *sm = ieee80211_priv(dev);
-	ieee80211softmac_clear_pending_work(sm);	
+	ieee80211softmac_clear_pending_work(sm);
 	kfree(sm->scaninfo);
 	kfree(sm->wpa.IE);
 	free_ieee80211(dev);
@@ -208,9 +208,9 @@
 void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
 	u8 erp_value)
 {
- 	int use_protection;
+	int use_protection;
 	int short_preamble;
- 	u32 changes = 0;
+	u32 changes = 0;
 
 	/* Barker preamble mode */
 	short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0
@@ -265,17 +265,10 @@
 	/* Change the default txrate to the highest possible value.
 	 * The txrate machine will lower it, if it is too high.
 	 */
-	/* FIXME: We don't correctly handle backing down to lower
-	   rates, so 801.11g devices start off at 11M for now. People
-	   can manually change it if they really need to, but 11M is
-	   more reliable. Note similar logic in
-	   ieee80211softmac_wx_set_rate() */	 
-	if (ieee->modulation & IEEE80211_CCK_MODULATION) {
+	if (ieee->modulation & IEEE80211_OFDM_MODULATION)
+		txrates->user_rate = IEEE80211_OFDM_RATE_24MB;
+	else
 		txrates->user_rate = IEEE80211_CCK_RATE_11MB;
-	} else if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
-		txrates->user_rate = IEEE80211_OFDM_RATE_54MB;
-	} else
-		assert(0);
 
 	txrates->default_rate = IEEE80211_CCK_RATE_1MB;
 	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
@@ -332,7 +325,7 @@
 {
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 	unsigned long flags;
-	
+
 	spin_lock_irqsave(&mac->lock, flags);
 	memcpy(mac->ratesinfo.rates, rates, count);
 	mac->ratesinfo.count = count;
@@ -344,7 +337,7 @@
 {
 	int i;
 	struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
-	
+
 	for (i=0; i<ri->count-1; i++) {
 		if (ri->rates[i] == rate)
 			return ri->rates[i+1];
@@ -357,7 +350,7 @@
 {
 	int i;
 	struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
-	
+
 	for (i=delta; i<ri->count; i++) {
 		if (ri->rates[i] == rate)
 			return ri->rates[i-delta];
@@ -438,7 +431,7 @@
 	softnet->channel = net->channel;
 	softnet->essid.len = net->ssid_len;
 	memcpy(softnet->essid.data, net->ssid, softnet->essid.len);
-	
+
 	/* copy rates over */
 	softnet->supported_rates.count = net->rates_len;
 	memcpy(&softnet->supported_rates.rates[0], net->rates, net->rates_len);
@@ -529,7 +522,7 @@
 {
 	unsigned long flags;
 	struct ieee80211softmac_network *softmac_net;
-	
+
 	spin_lock_irqsave(&mac->lock, flags);
 	softmac_net = ieee80211softmac_get_network_by_bssid_locked(mac, bssid);
 	spin_unlock_irqrestore(&mac->lock, flags);
@@ -556,13 +549,13 @@
 /* Get a network from the list by ESSID with locking */
 struct ieee80211softmac_network *
 ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
-	struct ieee80211softmac_essid *essid)	
+	struct ieee80211softmac_essid *essid)
 {
 	unsigned long flags;
 	struct ieee80211softmac_network *softmac_net = NULL;
 
 	spin_lock_irqsave(&mac->lock, flags);
-	softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid);	
+	softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid);
 	spin_unlock_irqrestore(&mac->lock, flags);
 	return softmac_net;
 }
diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h
index 4c2bba3..c43b189 100644
--- a/net/ieee80211/softmac/ieee80211softmac_priv.h
+++ b/net/ieee80211/softmac/ieee80211softmac_priv.h
@@ -130,7 +130,7 @@
 {
 	return ieee80211softmac_lower_rate_delta(mac, rate, 2);
 }
-                
+
 
 /*** prototypes from _io.c */
 int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
@@ -156,7 +156,7 @@
 int ieee80211softmac_handle_disassoc(struct net_device * dev,
 				     struct ieee80211_disassoc * disassoc);
 int ieee80211softmac_handle_reassoc_req(struct net_device * dev,
-				        struct ieee80211_reassoc_request * reassoc);
+					struct ieee80211_reassoc_request * reassoc);
 void ieee80211softmac_assoc_timeout(struct work_struct *work);
 void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason);
 void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac);
@@ -164,15 +164,15 @@
 /* some helper functions */
 static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm)
 {
-	return (sm->start_scan == ieee80211softmac_start_scan_implementation) && 
-		(sm->stop_scan == ieee80211softmac_stop_scan_implementation) && 
+	return (sm->start_scan == ieee80211softmac_start_scan_implementation) &&
+		(sm->stop_scan == ieee80211softmac_stop_scan_implementation) &&
 		(sm->wait_for_scan == ieee80211softmac_wait_for_scan_implementation);
 }
 
 static inline int ieee80211softmac_scan_sanity_check(struct ieee80211softmac_device *sm)
 {
-	return ((sm->start_scan != ieee80211softmac_start_scan_implementation) && 
-		(sm->stop_scan != ieee80211softmac_stop_scan_implementation) && 
+	return ((sm->start_scan != ieee80211softmac_start_scan_implementation) &&
+		(sm->stop_scan != ieee80211softmac_stop_scan_implementation) &&
 		(sm->wait_for_scan != ieee80211softmac_wait_for_scan_implementation)
 		) || ieee80211softmac_scan_handlers_check_self(sm);
 }
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
index 0c85d6c..abea364 100644
--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
+++ b/net/ieee80211/softmac/ieee80211softmac_scan.c
@@ -62,12 +62,12 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&sm->lock, flags);
-	
+
 	if (!sm->scanning) {
 		spin_unlock_irqrestore(&sm->lock, flags);
 		return;
 	}
-	
+
 	spin_unlock_irqrestore(&sm->lock, flags);
 	sm->stop_scan(sm->dev);
 }
@@ -78,12 +78,12 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&sm->lock, flags);
-	
+
 	if (!sm->scanning) {
 		spin_unlock_irqrestore(&sm->lock, flags);
 		return;
 	}
-	
+
 	spin_unlock_irqrestore(&sm->lock, flags);
 	sm->wait_for_scan(sm->dev);
 }
@@ -158,14 +158,14 @@
 {
 	struct ieee80211softmac_device *sm = ieee80211_priv(dev);
 	unsigned long flags;
-	
+
 	if (!(dev->flags & IFF_UP))
 		return -ENODEV;
 
 	assert(ieee80211softmac_scan_handlers_check_self(sm));
 	if (!ieee80211softmac_scan_handlers_check_self(sm))
 		return -EINVAL;
-		
+
 	spin_lock_irqsave(&sm->lock, flags);
 	/* it looks like we need to hold the lock here
 	 * to make sure we don't allocate two of these... */
@@ -241,7 +241,7 @@
 	spin_lock_irqsave(&sm->lock, flags);
 	sm->scanning = 0;
 	spin_unlock_irqrestore(&sm->lock, flags);
-	
+
 	if (sm->associnfo.bssvalid) {
 		struct ieee80211softmac_network *net;
 
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index fb58e03..f13937b 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -142,14 +142,14 @@
 	/* If all fails, return ANY (empty) */
 	data->essid.length = 0;
 	data->essid.flags = 0;  /* active */
-	
+
 	/* If we have a statically configured ESSID then return it */
 	if (sm->associnfo.static_essid) {
 		data->essid.length = sm->associnfo.req_essid.len;
 		data->essid.flags = 1;  /* active */
 		memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
 	}
-	
+
 	/* If we're associating/associated, return that */
 	if (sm->associnfo.associated || sm->associnfo.associating) {
 		data->essid.length = sm->associnfo.associate_essid.len;
@@ -177,15 +177,10 @@
 	int err = -EINVAL;
 
 	if (in_rate == -1) {
-		/* FIXME: We don't correctly handle backing down to lower
-		   rates, so 801.11g devices start off at 11M for now. People
-		   can manually change it if they really need to, but 11M is
-		   more reliable. Note similar logic in
-		   ieee80211softmac_wx_set_rate() */	 
-		if (ieee->modulation & IEEE80211_CCK_MODULATION)
-			in_rate = 11000000;
+		if (ieee->modulation & IEEE80211_OFDM_MODULATION)
+			in_rate = 24000000;
 		else
-			in_rate = 54000000;
+			in_rate = 11000000;
 	}
 
 	switch (in_rate) {
@@ -247,7 +242,7 @@
 	ieee80211softmac_recalc_txrates(mac);
 	err = 0;
 
-out_unlock:	
+out_unlock:
 	spin_unlock_irqrestore(&mac->lock, flags);
 out:
 	return err;
@@ -366,7 +361,7 @@
 	} else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
 		/* the bssid we have is no longer fixed */
 		mac->associnfo.bssfixed = 0;
-        } else {
+	} else {
 		if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
 			if (mac->associnfo.associating || mac->associnfo.associated) {
 			/* bssid unchanged and associated or associating - just return */
@@ -380,7 +375,7 @@
 		mac->associnfo.bssfixed = 1;
 		/* queue associate if new bssid or (old one again and not associated) */
 		schedule_delayed_work(&mac->associnfo.work, 0);
-        }
+	}
 
  out:
 	mutex_unlock(&mac->associnfo.mutex);
@@ -437,7 +432,7 @@
 		mac->wpa.IEbuflen = 0;
 	}
 
- out:	
+ out:
 	spin_unlock_irqrestore(&mac->lock, flags);
 	mutex_unlock(&mac->associnfo.mutex);
 
@@ -458,9 +453,9 @@
 
 	mutex_lock(&mac->associnfo.mutex);
 	spin_lock_irqsave(&mac->lock, flags);
-	
+
 	wrqu->data.length = 0;
-	
+
 	if (mac->wpa.IE && mac->wpa.IElen) {
 		wrqu->data.length = mac->wpa.IElen;
 		if (mac->wpa.IElen <= space)
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 503e705..91f3a5c 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -9,7 +9,7 @@
 	  intend to participate in the MBONE, a high bandwidth network on top
 	  of the Internet which carries audio and video broadcasts. More
 	  information about the MBONE is on the WWW at
-	  <http://www-itg.lbl.gov/mbone/>. Information about the multicast
+	  <http://www.savetz.com/mbone/>. Information about the multicast
 	  capabilities of the various network cards is contained in
 	  <file:Documentation/networking/multicast.txt>. For most people, it's
 	  safe to say N.
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 8640096..cf358c8 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -550,7 +550,7 @@
 		if (err < 0)
 			goto out;
 
-  		sock->state = SS_CONNECTING;
+		sock->state = SS_CONNECTING;
 
 		/* Just entered SS_CONNECTING state; the only
 		 * difference is that return value in non-blocking
@@ -878,36 +878,36 @@
  */
 static struct inet_protosw inetsw_array[] =
 {
-        {
-                .type =       SOCK_STREAM,
-                .protocol =   IPPROTO_TCP,
-                .prot =       &tcp_prot,
-                .ops =        &inet_stream_ops,
-                .capability = -1,
-                .no_check =   0,
-                .flags =      INET_PROTOSW_PERMANENT |
+	{
+		.type =       SOCK_STREAM,
+		.protocol =   IPPROTO_TCP,
+		.prot =       &tcp_prot,
+		.ops =        &inet_stream_ops,
+		.capability = -1,
+		.no_check =   0,
+		.flags =      INET_PROTOSW_PERMANENT |
 			      INET_PROTOSW_ICSK,
-        },
+	},
 
-        {
-                .type =       SOCK_DGRAM,
-                .protocol =   IPPROTO_UDP,
-                .prot =       &udp_prot,
-                .ops =        &inet_dgram_ops,
-                .capability = -1,
-                .no_check =   UDP_CSUM_DEFAULT,
-                .flags =      INET_PROTOSW_PERMANENT,
+	{
+		.type =       SOCK_DGRAM,
+		.protocol =   IPPROTO_UDP,
+		.prot =       &udp_prot,
+		.ops =        &inet_dgram_ops,
+		.capability = -1,
+		.no_check =   UDP_CSUM_DEFAULT,
+		.flags =      INET_PROTOSW_PERMANENT,
        },
-        
+
 
        {
-               .type =       SOCK_RAW,
-               .protocol =   IPPROTO_IP,	/* wild card */
-               .prot =       &raw_prot,
-               .ops =        &inet_sockraw_ops,
-               .capability = CAP_NET_RAW,
-               .no_check =   UDP_CSUM_DEFAULT,
-               .flags =      INET_PROTOSW_REUSE,
+	       .type =       SOCK_RAW,
+	       .protocol =   IPPROTO_IP,	/* wild card */
+	       .prot =       &raw_prot,
+	       .ops =        &inet_sockraw_ops,
+	       .capability = CAP_NET_RAW,
+	       .no_check =   UDP_CSUM_DEFAULT,
+	       .flags =      INET_PROTOSW_REUSE,
        }
 };
 
@@ -946,7 +946,7 @@
 	/* Add the new entry after the last permanent entry if any, so that
 	 * the new entry does not override a permanent entry when matched with
 	 * a wild-card protocol. But it is allowed to override any existing
-	 * non-permanent entry.  This means that when we remove this entry, the 
+	 * non-permanent entry.  This means that when we remove this entry, the
 	 * system automatically returns to the old behavior.
 	 */
 	list_add_rcu(&p->list, last_perm);
@@ -1007,7 +1007,7 @@
 			       RT_CONN_FLAGS(sk),
 			       sk->sk_bound_dev_if,
 			       sk->sk_protocol,
-			       inet->sport, inet->dport, sk);
+			       inet->sport, inet->dport, sk, 0);
 	if (err)
 		return err;
 
@@ -1073,7 +1073,7 @@
 			},
 		},
 	};
-						
+
 	security_sk_classify_flow(sk, &fl);
 	err = ip_route_output_flow(&rt, &fl, sk, 0);
 }
@@ -1273,10 +1273,10 @@
 		goto out_unregister_udp_proto;
 
 	/*
-	 *	Tell SOCKET that we are alive... 
+	 *	Tell SOCKET that we are alive...
 	 */
 
-  	(void)sock_register(&inet_family_ops);
+	(void)sock_register(&inet_family_ops);
 
 	/*
 	 *	Add all the base protocols.
@@ -1306,9 +1306,9 @@
 
 	arp_init();
 
-  	/*
-  	 *	Set the IP module up
-  	 */
+	/*
+	 *	Set the IP module up
+	 */
 
 	ip_init();
 
@@ -1334,11 +1334,11 @@
 #endif
 	/*
 	 *	Initialise per-cpu ipv4 mibs
-	 */ 
+	 */
 
 	if(init_ipv4_mibs())
 		printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ;
-	
+
 	ipv4_proc_init();
 
 	ipfrag_init();
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 67a5509..7194eb4 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -91,7 +91,7 @@
 	top_iph->check = 0;
 
 	ahp = x->data;
-	ah->hdrlen  = (XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + 
+	ah->hdrlen  = (XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
 				   ahp->icv_trunc_len) >> 2) - 2;
 
 	ah->reserved = 0;
@@ -135,9 +135,9 @@
 	ah = (struct ip_auth_hdr*)skb->data;
 	ahp = x->data;
 	ah_hlen = (ah->hdrlen + 2) << 2;
-	
+
 	if (ah_hlen != XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_full_len) &&
-	    ah_hlen != XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_trunc_len)) 
+	    ah_hlen != XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_trunc_len))
 		goto out;
 
 	if (!pskb_may_pull(skb, ah_hlen))
@@ -166,9 +166,9 @@
 		if (ip_clear_mutable_options(iph, &dummy))
 			goto out;
 	}
-        {
+	{
 		u8 auth_data[MAX_AH_AUTH_LEN];
-		
+
 		memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
 		skb_push(skb, ihl);
 		err = ah_mac_digest(ahp, skb, ah->auth_data);
@@ -237,7 +237,7 @@
 	ahp->tfm = tfm;
 	if (crypto_hash_setkey(tfm, ahp->key, ahp->key_len))
 		goto error;
-	
+
 	/*
 	 * Lookup the algorithm description maintained by xfrm_algo,
 	 * verify crypto transform properties, and store information
@@ -254,16 +254,16 @@
 		       aalg_desc->uinfo.auth.icv_fullbits/8);
 		goto error;
 	}
-	
+
 	ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
 	ahp->icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
-	
+
 	BUG_ON(ahp->icv_trunc_len > MAX_AH_AUTH_LEN);
-	
+
 	ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL);
 	if (!ahp->work_icv)
 		goto error;
-	
+
 	x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_trunc_len);
 	if (x->props.mode == XFRM_MODE_TUNNEL)
 		x->props.header_len += sizeof(struct iphdr);
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 3981e8b..1a3488a 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -15,9 +15,9 @@
  * 2 of the License, or (at your option) any later version.
  *
  * Fixes:
- *		Alan Cox	:	Removed the Ethernet assumptions in 
+ *		Alan Cox	:	Removed the Ethernet assumptions in
  *					Florian's code
- *		Alan Cox	:	Fixed some small errors in the ARP 
+ *		Alan Cox	:	Fixed some small errors in the ARP
  *					logic
  *		Alan Cox	:	Allow >4K in /proc
  *		Alan Cox	:	Make ARP add its own protocol entry
@@ -39,18 +39,18 @@
  *		Jonathan Naylor :	Only lookup the hardware address for
  *					the correct hardware type.
  *		Germano Caronni	:	Assorted subtle races.
- *		Craig Schlenter :	Don't modify permanent entry 
+ *		Craig Schlenter :	Don't modify permanent entry
  *					during arp_rcv.
  *		Russ Nelson	:	Tidied up a few bits.
  *		Alexey Kuznetsov:	Major changes to caching and behaviour,
- *					eg intelligent arp probing and 
+ *					eg intelligent arp probing and
  *					generation
  *					of host down events.
  *		Alan Cox	:	Missing unlock in device events.
  *		Eckes		:	ARP ioctl control errors.
  *		Alexey Kuznetsov:	Arp free fix.
  *		Manuel Rodriguez:	Gratuitous ARP.
- *              Jonathan Layes  :       Added arpd support through kerneld 
+ *              Jonathan Layes  :       Added arpd support through kerneld
  *                                      message queue (960314)
  *		Mike Shaver	:	/proc/sys/net/ipv4/arp_* support
  *		Mike McLagan    :	Routing by source
@@ -78,7 +78,6 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/capability.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
@@ -210,7 +209,7 @@
 	case ARPHRD_FDDI:
 	case ARPHRD_IEEE802:
 		ip_eth_mc_map(addr, haddr);
-		return 0; 
+		return 0;
 	case ARPHRD_IEEE802_TR:
 		ip_tr_mc_map(addr, haddr);
 		return 0;
@@ -288,7 +287,7 @@
 		switch (dev->type) {
 		default:
 			break;
-		case ARPHRD_ROSE:	
+		case ARPHRD_ROSE:
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 		case ARPHRD_AX25:
 #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
@@ -425,18 +424,18 @@
 	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip,
 						 .saddr = tip } } };
 	struct rtable *rt;
-	int flag = 0; 
+	int flag = 0;
 	/*unsigned long now; */
 
-	if (ip_route_output_key(&rt, &fl) < 0) 
+	if (ip_route_output_key(&rt, &fl) < 0)
 		return 1;
-	if (rt->u.dst.dev != dev) { 
+	if (rt->u.dst.dev != dev) {
 		NET_INC_STATS_BH(LINUX_MIB_ARPFILTER);
 		flag = 1;
-	} 
-	ip_rt_put(rt); 
-	return flag; 
-} 
+	}
+	ip_rt_put(rt);
+	return flag;
+}
 
 /* OBSOLETE FUNCTIONS */
 
@@ -490,7 +489,7 @@
 		n->used = jiffies;
 		if (n->nud_state&NUD_VALID || neigh_event_send(n, skb) == 0) {
 			read_lock_bh(&n->lock);
- 			memcpy(haddr, n->ha, dev->addr_len);
+			memcpy(haddr, n->ha, dev->addr_len);
 			read_unlock_bh(&n->lock);
 			neigh_release(n);
 			return 0;
@@ -572,7 +571,7 @@
 	/*
 	 *	Allocate a buffer
 	 */
-	
+
 	skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
 				+ LL_RESERVED_SPACE(dev), GFP_ATOMIC);
 	if (skb == NULL)
@@ -685,7 +684,7 @@
 	/*
 	 *	No arp on this interface.
 	 */
-	
+
 	if (dev->flags&IFF_NOARP)
 		return;
 
@@ -725,7 +724,7 @@
 	arp = skb->nh.arph;
 
 	switch (dev_type) {
-	default:	
+	default:
 		if (arp->ar_pro != htons(ETH_P_IP) ||
 		    htons(dev_type) != arp->ar_hrd)
 			goto out;
@@ -792,7 +791,7 @@
 	tha	= arp_ptr;
 	arp_ptr += dev->addr_len;
 	memcpy(&tip, arp_ptr, 4);
-/* 
+/*
  *	Check for bad requests for 127.x.x.x and requests for multicast
  *	addresses.  If this is one such, delete it.
  */
@@ -809,16 +808,16 @@
  *  Process entry.  The idea here is we want to send a reply if it is a
  *  request for us or if it is a request for someone else that we hold
  *  a proxy for.  We want to add an entry to our cache if it is a reply
- *  to us or if it is a request for our address.  
- *  (The assumption for this last is that if someone is requesting our 
- *  address, they are probably intending to talk to us, so it saves time 
- *  if we cache their address.  Their address is also probably not in 
+ *  to us or if it is a request for our address.
+ *  (The assumption for this last is that if someone is requesting our
+ *  address, they are probably intending to talk to us, so it saves time
+ *  if we cache their address.  Their address is also probably not in
  *  our cache, since ours is not in their cache.)
- * 
+ *
  *  Putting this another way, we only care about replies if they are to
  *  us, in which case we add them to the cache.  For requests, we care
  *  about those for us and those for our proxies.  We reply to both,
- *  and in the case of requests for us we add the requester to the arp 
+ *  and in the case of requests for us we add the requester to the arp
  *  cache.
  */
 
@@ -845,7 +844,7 @@
 				if (!dont_send)
 					dont_send |= arp_ignore(in_dev,dev,sip,tip);
 				if (!dont_send && IN_DEV_ARPFILTER(in_dev))
-					dont_send |= arp_filter(sip,tip,dev); 
+					dont_send |= arp_filter(sip,tip,dev);
 				if (!dont_send)
 					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
 
@@ -860,7 +859,7 @@
 				if (n)
 					neigh_release(n);
 
-				if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED || 
+				if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED ||
 				    skb->pkt_type == PACKET_HOST ||
 				    in_dev->arp_parms->proxy_delay == 0) {
 					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
@@ -1039,7 +1038,7 @@
 		if (r->arp_flags & ATF_PERM)
 			state = NUD_PERMANENT;
 		err = neigh_update(neigh, (r->arp_flags&ATF_COM) ?
-				   r->arp_ha.sa_data : NULL, state, 
+				   r->arp_ha.sa_data : NULL, state,
 				   NEIGH_UPDATE_F_OVERRIDE|
 				   NEIGH_UPDATE_F_ADMIN);
 		neigh_release(neigh);
@@ -1121,7 +1120,7 @@
 	neigh = neigh_lookup(&arp_tbl, &ip, dev);
 	if (neigh) {
 		if (neigh->nud_state&~NUD_NOARP)
-			err = neigh_update(neigh, NULL, NUD_FAILED, 
+			err = neigh_update(neigh, NULL, NUD_FAILED,
 					   NEIGH_UPDATE_F_OVERRIDE|
 					   NEIGH_UPDATE_F_ADMIN);
 		neigh_release(neigh);
@@ -1181,7 +1180,7 @@
 
 	switch(cmd) {
 	case SIOCDARP:
-	        err = arp_req_delete(&r, dev);
+		err = arp_req_delete(&r, dev);
 		break;
 	case SIOCSARP:
 		err = arp_req_set(&r, dev);
@@ -1268,14 +1267,14 @@
 
 		if (c != ' ') *s++ = c;
 	}
-	
+
 	*s++ = '-';
 
 	if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
 		*s++ = '1';
 		n -= 10;
 	}
-	
+
 	*s++ = n + '0';
 	*s++ = '\0';
 
@@ -1373,7 +1372,7 @@
 	struct seq_file *seq;
 	int rc = -ENOMEM;
 	struct neigh_seq_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
-       
+
 	if (!s)
 		goto out;
 
@@ -1390,7 +1389,7 @@
 	goto out;
 }
 
-static struct file_operations arp_seq_fops = {
+static const struct file_operations arp_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = arp_seq_open,
 	.read           = seq_read,
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index 7b068a8..dd02a45 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -29,12 +29,12 @@
 	int oif;
 	int err;
 
-	
-	if (addr_len < sizeof(*usin)) 
-	  	return -EINVAL;
 
-	if (usin->sin_family != AF_INET) 
-	  	return -EAFNOSUPPORT;
+	if (addr_len < sizeof(*usin))
+		return -EINVAL;
+
+	if (usin->sin_family != AF_INET)
+		return -EAFNOSUPPORT;
 
 	sk_dst_reset(sk);
 
@@ -49,15 +49,15 @@
 	err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
 			       RT_CONN_FLAGS(sk), oif,
 			       sk->sk_protocol,
-			       inet->sport, usin->sin_port, sk);
+			       inet->sport, usin->sin_port, sk, 1);
 	if (err)
 		return err;
 	if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
 		ip_rt_put(rt);
 		return -EACCES;
 	}
-  	if (!inet->saddr)
-	  	inet->saddr = rt->rt_src;	/* Update source address */
+	if (!inet->saddr)
+		inet->saddr = rt->rt_src;	/* Update source address */
 	if (!inet->rcv_saddr)
 		inet->rcv_saddr = rt->rt_src;
 	inet->daddr = rt->rt_dst;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 480ace9..8a0ec10 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -35,7 +35,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -252,7 +251,7 @@
 
 	ASSERT_RTNL();
 
-	/* 1. Deleting primary ifaddr forces deletion all secondaries 
+	/* 1. Deleting primary ifaddr forces deletion all secondaries
 	 * unless alias promotion is set
 	 **/
 
@@ -260,7 +259,7 @@
 		struct in_ifaddr **ifap1 = &ifa1->ifa_next;
 
 		while ((ifa = *ifap1) != NULL) {
-			if (!(ifa->ifa_flags & IFA_F_SECONDARY) && 
+			if (!(ifa->ifa_flags & IFA_F_SECONDARY) &&
 			    ifa1->ifa_scope <= ifa->ifa_scope)
 				last_prim = ifa;
 
@@ -583,8 +582,8 @@
 {
 	int rc = -1;	/* Something else, probably a multicast. */
 
-  	if (ZERONET(addr))
-  		rc = 0;
+	if (ZERONET(addr))
+		rc = 0;
 	else {
 		__u32 haddr = ntohl(addr);
 
@@ -596,7 +595,7 @@
 			rc = 24;
 	}
 
-  	return rc;
+	return rc;
 }
 
 
@@ -1020,29 +1019,29 @@
  * alias numbering and to create unique labels if possible.
 */
 static void inetdev_changename(struct net_device *dev, struct in_device *in_dev)
-{ 
+{
 	struct in_ifaddr *ifa;
 	int named = 0;
 
-	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { 
-		char old[IFNAMSIZ], *dot; 
+	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
+		char old[IFNAMSIZ], *dot;
 
 		memcpy(old, ifa->ifa_label, IFNAMSIZ);
-		memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); 
+		memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
 		if (named++ == 0)
 			continue;
 		dot = strchr(ifa->ifa_label, ':');
-		if (dot == NULL) { 
-			sprintf(old, ":%d", named); 
+		if (dot == NULL) {
+			sprintf(old, ":%d", named);
 			dot = old;
 		}
-		if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) { 
-			strcat(ifa->ifa_label, dot); 
-		} else { 
-			strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); 
-		} 
-	}	
-} 
+		if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) {
+			strcat(ifa->ifa_label, dot);
+		} else {
+			strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot);
+		}
+	}
+}
 
 /* Called only under RTNL semaphore */
 
@@ -1140,7 +1139,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ifm = nlmsg_data(nlh);
 	ifm->ifa_family = AF_INET;
@@ -1167,7 +1166,8 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
@@ -1225,9 +1225,12 @@
 		goto errout;
 
 	err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
-	/* failure implies BUG in inet_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in inet_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
 errout:
 	if (err < 0)
@@ -1535,7 +1538,7 @@
 		},
 	},
 	.devinet_conf_dir = {
-	        {
+		{
 			.ctl_name	= NET_IPV4_CONF,
 			.procname	= "conf",
 			.mode		= 0555,
@@ -1573,37 +1576,32 @@
 		return;
 	for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
 		t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
-		t->devinet_vars[i].de = NULL;
 	}
 
 	if (dev) {
-		dev_name = dev->name; 
+		dev_name = dev->name;
 		t->devinet_dev[0].ctl_name = dev->ifindex;
 	} else {
 		dev_name = "default";
 		t->devinet_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;
 	}
 
-	/* 
-	 * Make a copy of dev_name, because '.procname' is regarded as const 
+	/*
+	 * Make a copy of dev_name, because '.procname' is regarded as const
 	 * by sysctl and we wouldn't want anyone to change it under our feet
 	 * (see SIOCSIFNAME).
-	 */	
+	 */
 	dev_name = kstrdup(dev_name, GFP_KERNEL);
 	if (!dev_name)
 	    goto free;
 
 	t->devinet_dev[0].procname    = dev_name;
 	t->devinet_dev[0].child	      = t->devinet_vars;
-	t->devinet_dev[0].de	      = NULL;
 	t->devinet_conf_dir[0].child  = t->devinet_dev;
-	t->devinet_conf_dir[0].de     = NULL;
 	t->devinet_proto_dir[0].child = t->devinet_conf_dir;
-	t->devinet_proto_dir[0].de    = NULL;
 	t->devinet_root_dir[0].child  = t->devinet_proto_dir;
-	t->devinet_root_dir[0].de     = NULL;
 
-	t->sysctl_header = register_sysctl_table(t->devinet_root_dir, 0);
+	t->sysctl_header = register_sysctl_table(t->devinet_root_dir);
 	if (!t->sysctl_header)
 	    goto free_procname;
 
@@ -1637,7 +1635,7 @@
 	rtnetlink_links[PF_INET] = inet_rtnetlink_table;
 #ifdef CONFIG_SYSCTL
 	devinet_sysctl.sysctl_header =
-		register_sysctl_table(devinet_sysctl.devinet_root_dir, 0);
+		register_sysctl_table(devinet_sysctl.devinet_root_dir);
 	devinet_sysctl_register(NULL, &ipv4_devconf_dflt);
 #endif
 }
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index f2c6776..3104112 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -215,7 +215,7 @@
 	if (padlen+2 >= elen)
 		goto out;
 
-	/* ... check padding bits here. Silly. :-) */ 
+	/* ... check padding bits here. Silly. :-) */
 
 	iph = skb->nh.iph;
 	ihl = iph->ihl * 4;
@@ -236,7 +236,7 @@
 
 			ipaddr.a4 = iph->saddr;
 			km_new_mapping(x, &ipaddr, uh->source);
-				
+
 			/* XXX: perhaps add an extra
 			 * policy check here, to see
 			 * if we should allow or
@@ -245,7 +245,7 @@
 			 * address/port.
 			 */
 		}
-	
+
 		/*
 		 * 2) ignore UDP/TCP checksums in case
 		 *    of NAT-T in Transport Mode, or
@@ -284,7 +284,7 @@
 		mtu = ALIGN(mtu + 2, 4) + blksize - 4;
 		break;
 	case XFRM_MODE_BEET:
- 		/* The worst case. */
+		/* The worst case. */
 		enclen = IPV4_BEET_PHMAXLEN;
 		mtu = ALIGN(mtu + enclen + 2, blksize);
 		break;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index d47b72a..1fba643 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -22,7 +22,6 @@
 #include <linux/capability.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/socket.h>
@@ -160,7 +159,7 @@
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	res.r = NULL;
 #endif
-	
+
 	if (ip_fib_local_table) {
 		ret = RTN_UNICAST;
 		if (!ip_fib_local_table->tb_lookup(ip_fib_local_table,
@@ -378,7 +377,7 @@
 		int len = 0;
 
 		mx = kzalloc(3 * nla_total_size(4), GFP_KERNEL);
- 		if (mx == NULL)
+		if (mx == NULL)
 			return -ENOMEM;
 
 		if (rt->rt_flags & RTF_MTU)
@@ -400,7 +399,7 @@
 /*
  *	Handle IP routing ioctl calls. These are used to manipulate the routing tables
  */
- 
+
 int ip_rt_ioctl(unsigned int cmd, void __user *arg)
 {
 	struct fib_config cfg;
@@ -600,7 +599,7 @@
 				goto next;
 			if (dumped)
 				memset(&cb->args[2], 0, sizeof(cb->args) -
-				                 2 * sizeof(cb->args[0]));
+						 2 * sizeof(cb->args[0]));
 			if (tb->tb_dump(tb, skb, cb) < 0)
 				goto out;
 			dumped = 1;
@@ -766,7 +765,7 @@
 
 static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
 {
-	
+
 	struct fib_result       res;
 	struct flowi            fl = { .mark = frn->fl_mark,
 				       .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
@@ -791,11 +790,11 @@
 static void nl_fib_input(struct sock *sk, int len)
 {
 	struct sk_buff *skb = NULL;
-        struct nlmsghdr *nlh = NULL;
+	struct nlmsghdr *nlh = NULL;
 	struct fib_result_nl *frn;
-	u32 pid;     
+	u32 pid;
 	struct fib_table *tb;
-	
+
 	skb = skb_dequeue(&sk->sk_receive_queue);
 	nlh = (struct nlmsghdr *)skb->data;
 	if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len ||
@@ -803,17 +802,17 @@
 		kfree_skb(skb);
 		return;
 	}
-	
+
 	frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
 	tb = fib_get_table(frn->tb_id_in);
 
 	nl_fib_lookup(frn, tb);
-	
+
 	pid = nlh->nlmsg_pid;           /*pid of sending process */
 	NETLINK_CB(skb).pid = 0;         /* from kernel */
 	NETLINK_CB(skb).dst_group = 0;  /* unicast */
 	netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
-}    
+}
 
 static void nl_fib_lookup_init(void)
 {
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 648f47c..a4949f9 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -20,7 +20,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/socket.h>
@@ -146,7 +145,7 @@
 	struct hlist_head *ht, *old_ht;
 	int old_divisor, new_divisor;
 	u32 new_hashmask;
-		
+
 	old_divisor = fz->fz_divisor;
 
 	switch (old_divisor) {
@@ -911,7 +910,7 @@
 
 		if (!iter->zone)
 			goto out;
-		
+
 		iter->bucket = 0;
 		iter->hash_head = iter->zone->fz_hash;
 
@@ -932,7 +931,7 @@
 {
 	struct fib_iter_state *iter = seq->private;
 	struct fib_alias *fa;
-	
+
 	if (iter->valid && pos >= iter->pos && iter->genid == fib_hash_genid) {
 		fa   = iter->fa;
 		pos -= iter->pos;
@@ -981,7 +980,7 @@
 	return flags;
 }
 
-/* 
+/*
  *	This outputs /proc/net/route.
  *
  *	It always works in backward compatibility mode.
@@ -1040,7 +1039,7 @@
 	struct seq_file *seq;
 	int rc = -ENOMEM;
 	struct fib_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
-       
+
 	if (!s)
 		goto out;
 
@@ -1057,7 +1056,7 @@
 	goto out;
 }
 
-static struct file_operations fib_seq_fops = {
+static const struct file_operations fib_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = fib_seq_open,
 	.read           = seq_read,
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index e63b8a9..2f1fdae 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -85,12 +85,12 @@
 #define endfor_nexthops(fi) }
 
 
-static const struct 
+static const struct
 {
 	int	error;
 	u8	scope;
 } fib_props[RTA_MAX + 1] = {
-        {
+	{
 		.error	= 0,
 		.scope	= RT_SCOPE_NOWHERE,
 	},	/* RTN_UNSPEC */
@@ -314,9 +314,12 @@
 	err = fib_dump_info(skb, info->pid, seq, event, tb_id,
 			    fa->fa_type, fa->fa_scope, key, dst_len,
 			    fa->fa_tos, fa->fa_info, 0);
-	/* failure implies BUG in fib_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in fib_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
 			  info->nlh, GFP_KERNEL);
 errout:
@@ -436,7 +439,7 @@
 
 	rtnh = cfg->fc_mp;
 	remaining = cfg->fc_mp_len;
-	
+
 	for_nexthops(fi) {
 		int attrlen;
 
@@ -505,9 +508,9 @@
    Normally it looks as following.
 
    {universe prefix}  -> (gw, oif) [scope link]
-                          |
+			  |
 			  |-> {link prefix} -> (gw, oif) [scope local]
-			                        |
+						|
 						|-> {local prefix} (terminal node)
  */
 
@@ -861,7 +864,7 @@
 	err = -EINVAL;
 
 failure:
-        if (fi) {
+	if (fi) {
 		fi->fib_dead = 1;
 		free_fib_info(fi);
 	}
@@ -960,7 +963,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	rtm = nlmsg_data(nlh);
 	rtm->rtm_family = AF_INET;
@@ -1031,7 +1034,8 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 /*
@@ -1045,7 +1049,7 @@
 {
 	int ret = 0;
 	int scope = RT_SCOPE_NOWHERE;
-	
+
 	if (force)
 		scope = -1;
 
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 1e589b9..72b3036 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -7,13 +7,13 @@
  *   Robert Olsson <robert.olsson@its.uu.se> Uppsala Universitet
  *     & Swedish University of Agricultural Sciences.
  *
- *   Jens Laas <jens.laas@data.slu.se> Swedish University of 
+ *   Jens Laas <jens.laas@data.slu.se> Swedish University of
  *     Agricultural Sciences.
- * 
+ *
  *   Hans Liss <hans.liss@its.uu.se>  Uppsala Universitet
  *
  * This work is based on the LPC-trie which is originally descibed in:
- * 
+ *
  * An experimental study of compression methods for dynamic tries
  * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002.
  * http://www.nada.kth.se/~snilsson/public/papers/dyntrie2/
@@ -57,7 +57,6 @@
 #include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/socket.h>
@@ -224,34 +223,34 @@
 }
 
 /*
-  To understand this stuff, an understanding of keys and all their bits is 
-  necessary. Every node in the trie has a key associated with it, but not 
+  To understand this stuff, an understanding of keys and all their bits is
+  necessary. Every node in the trie has a key associated with it, but not
   all of the bits in that key are significant.
 
   Consider a node 'n' and its parent 'tp'.
 
-  If n is a leaf, every bit in its key is significant. Its presence is 
-  necessitated by path compression, since during a tree traversal (when 
-  searching for a leaf - unless we are doing an insertion) we will completely 
-  ignore all skipped bits we encounter. Thus we need to verify, at the end of 
-  a potentially successful search, that we have indeed been walking the 
+  If n is a leaf, every bit in its key is significant. Its presence is
+  necessitated by path compression, since during a tree traversal (when
+  searching for a leaf - unless we are doing an insertion) we will completely
+  ignore all skipped bits we encounter. Thus we need to verify, at the end of
+  a potentially successful search, that we have indeed been walking the
   correct key path.
 
-  Note that we can never "miss" the correct key in the tree if present by 
-  following the wrong path. Path compression ensures that segments of the key 
-  that are the same for all keys with a given prefix are skipped, but the 
-  skipped part *is* identical for each node in the subtrie below the skipped 
-  bit! trie_insert() in this implementation takes care of that - note the 
+  Note that we can never "miss" the correct key in the tree if present by
+  following the wrong path. Path compression ensures that segments of the key
+  that are the same for all keys with a given prefix are skipped, but the
+  skipped part *is* identical for each node in the subtrie below the skipped
+  bit! trie_insert() in this implementation takes care of that - note the
   call to tkey_sub_equals() in trie_insert().
 
-  if n is an internal node - a 'tnode' here, the various parts of its key 
+  if n is an internal node - a 'tnode' here, the various parts of its key
   have many different meanings.
 
-  Example:  
+  Example:
   _________________________________________________________________
   | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
   -----------------------------------------------------------------
-    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15 
+    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
 
   _________________________________________________________________
   | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
@@ -263,23 +262,23 @@
   n->pos = 15
   n->bits = 4
 
-  First, let's just ignore the bits that come before the parent tp, that is 
-  the bits from 0 to (tp->pos-1). They are *known* but at this point we do 
+  First, let's just ignore the bits that come before the parent tp, that is
+  the bits from 0 to (tp->pos-1). They are *known* but at this point we do
   not use them for anything.
 
   The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the
-  index into the parent's child array. That is, they will be used to find 
+  index into the parent's child array. That is, they will be used to find
   'n' among tp's children.
 
   The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits
   for the node n.
 
-  All the bits we have seen so far are significant to the node n. The rest 
+  All the bits we have seen so far are significant to the node n. The rest
   of the bits are really not needed or indeed known in n->key.
 
-  The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into 
+  The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into
   n's child array, and will of course be different for each child.
-  
+
 
   The rest of the bits, from (n->pos + n->bits) onward, are completely unknown
   at this point.
@@ -294,7 +293,7 @@
 static int halve_threshold = 25;
 static int inflate_threshold = 50;
 static int halve_threshold_root = 15;
-static int inflate_threshold_root = 25; 
+static int inflate_threshold_root = 25;
 
 
 static void __alias_free_mem(struct rcu_head *head)
@@ -355,7 +354,7 @@
 		struct leaf *l = (struct leaf *) tn;
 		call_rcu_bh(&l->rcu, __leaf_free_rcu);
 	}
-        else
+	else
 		call_rcu(&tn->rcu, __tnode_free_rcu);
 }
 
@@ -461,7 +460,7 @@
 	int inflate_threshold_use;
 	int halve_threshold_use;
 
- 	if (!tn)
+	if (!tn)
 		return NULL;
 
 	pr_debug("In tnode_resize %p inflate_threshold=%d threshold=%d\n",
@@ -556,7 +555,7 @@
 
 	if(!tn->parent)
 		inflate_threshold_use = inflate_threshold_root;
-	else 
+	else
 		inflate_threshold_use = inflate_threshold;
 
 	err = 0;
@@ -587,7 +586,7 @@
 
 	if(!tn->parent)
 		halve_threshold_use = halve_threshold_root;
-	else 
+	else
 		halve_threshold_use = halve_threshold;
 
 	err = 0;
@@ -665,10 +664,10 @@
 			right = tnode_new(inode->key|m, inode->pos + 1,
 					  inode->bits - 1);
 
-                        if (!right) {
+			if (!right) {
 				tnode_free(left);
 				goto nomem;
-                        }
+			}
 
 			put_child(t, tn, 2*i, (struct node *) left);
 			put_child(t, tn, 2*i+1, (struct node *) right);
@@ -890,23 +889,23 @@
 
 static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
 {
-        struct leaf_info *li = NULL, *last = NULL;
-        struct hlist_node *node;
+	struct leaf_info *li = NULL, *last = NULL;
+	struct hlist_node *node;
 
-        if (hlist_empty(head)) {
-                hlist_add_head_rcu(&new->hlist, head);
-        } else {
-                hlist_for_each_entry(li, node, head, hlist) {
-                        if (new->plen > li->plen)
-                                break;
+	if (hlist_empty(head)) {
+		hlist_add_head_rcu(&new->hlist, head);
+	} else {
+		hlist_for_each_entry(li, node, head, hlist) {
+			if (new->plen > li->plen)
+				break;
 
-                        last = li;
-                }
-                if (last)
-                        hlist_add_after_rcu(&last->hlist, &new->hlist);
-                else
-                        hlist_add_before_rcu(&new->hlist, &li->hlist);
-        }
+			last = li;
+		}
+		if (last)
+			hlist_add_after_rcu(&last->hlist, &new->hlist);
+		else
+			hlist_add_before_rcu(&new->hlist, &li->hlist);
+	}
 }
 
 /* rcu_read_lock needs to be hold by caller from readside */
@@ -1700,7 +1699,7 @@
 			/* Decend if tnode */
 			while (IS_TNODE(c)) {
 				p = (struct tnode *) c;
-  				idx = 0;
+				idx = 0;
 
 				/* Rightmost non-NULL branch */
 				if (p && IS_TNODE(p))
@@ -2173,7 +2172,7 @@
 	return single_open(file, fib_triestat_seq_show, NULL);
 }
 
-static struct file_operations fib_triestat_fops = {
+static const struct file_operations fib_triestat_fops = {
 	.owner	= THIS_MODULE,
 	.open	= fib_triestat_seq_open,
 	.read	= seq_read,
@@ -2303,9 +2302,9 @@
 
 		seq_indent(seq, iter->depth-1);
 		seq_printf(seq, "  +-- %d.%d.%d.%d/%d %d %d %d\n",
-			   NIPQUAD(prf), tn->pos, tn->bits, tn->full_children, 
+			   NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,
 			   tn->empty_children);
-		
+
 	} else {
 		struct leaf *l = (struct leaf *) n;
 		int i;
@@ -2364,7 +2363,7 @@
 	goto out;
 }
 
-static struct file_operations fib_trie_fops = {
+static const struct file_operations fib_trie_fops = {
 	.owner  = THIS_MODULE,
 	.open   = fib_trie_seq_open,
 	.read   = seq_read,
@@ -2485,7 +2484,7 @@
 	goto out;
 }
 
-static struct file_operations fib_route_fops = {
+static const struct file_operations fib_route_fops = {
 	.owner  = THIS_MODULE,
 	.open   = fib_route_seq_open,
 	.read   = seq_read,
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 40cf0d0..4b7a0d9 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -304,7 +304,7 @@
 
 	/* No rate limit on loopback */
 	if (dst->dev && (dst->dev->flags&IFF_LOOPBACK))
- 		goto out;
+		goto out;
 
 	/* Limit if icmp type is enabled in ratemask. */
 	if ((1 << type) & sysctl_icmp_ratemask)
@@ -350,9 +350,9 @@
 	struct sk_buff *skb;
 
 	if (ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param,
-		           icmp_param->data_len+icmp_param->head_len,
-		           icmp_param->head_len,
-		           ipc, rt, MSG_DONTWAIT) < 0)
+			   icmp_param->data_len+icmp_param->head_len,
+			   icmp_param->head_len,
+			   ipc, rt, MSG_DONTWAIT) < 0)
 		ip_flush_pending_frames(icmp_socket->sk);
 	else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) {
 		struct icmphdr *icmph = skb->h.icmph;
@@ -755,7 +755,7 @@
 			       skb->h.icmph->un.gateway,
 			       iph->saddr, skb->dev);
 		break;
-  	}
+	}
 out:
 	return;
 out_err:
@@ -959,7 +959,7 @@
 	 *	Parse the ICMP message
 	 */
 
- 	if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
+	if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
 		/*
 		 *	RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be
 		 *	  silently ignored (we let user decide with a sysctl).
@@ -976,7 +976,7 @@
 		    icmph->type != ICMP_ADDRESS &&
 		    icmph->type != ICMP_ADDRESSREPLY) {
 			goto error;
-  		}
+		}
 	}
 
 	ICMP_INC_STATS_BH(icmp_pointers[icmph->type].input_entry);
@@ -1085,7 +1085,7 @@
 		.input_entry = ICMP_MIB_DUMMY,
 		.handler = icmp_discard,
 	},
- 	[ICMP_INFO_REPLY] = {
+	[ICMP_INFO_REPLY] = {
 		.output_entry = ICMP_MIB_DUMMY,
 		.input_entry = ICMP_MIB_DUMMY,
 		.handler = icmp_discard,
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 0017ccb..0637213 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -35,7 +35,7 @@
  *
  *		Chih-Jen Chang	:	Tried to revise IGMP to Version 2
  *		Tsu-Sheng Tsao		E-mail: chihjenc@scf.usc.edu and tsusheng@scf.usc.edu
- *					The enhancements are mainly based on Steve Deering's 
+ *					The enhancements are mainly based on Steve Deering's
  * 					ipmulti-3.5 source code.
  *		Chih-Jen Chang	:	Added the igmp_get_mrouter_info and
  *		Tsu-Sheng Tsao		igmp_set_mrouter_info to keep track of
@@ -49,11 +49,11 @@
  *		Alan Cox	:	Stop IGMP from 0.0.0.0 being accepted.
  *		Alan Cox	:	Use GFP_ATOMIC in the right places.
  *		Christian Daudt :	igmp timer wasn't set for local group
- *					memberships but was being deleted, 
- *					which caused a "del_timer() called 
+ *					memberships but was being deleted,
+ *					which caused a "del_timer() called
  *					from %p with timer not initialized\n"
  *					message (960131).
- *		Christian Daudt :	removed del_timer from 
+ *		Christian Daudt :	removed del_timer from
  *					igmp_timer_expire function (960205).
  *             Christian Daudt :       igmp_heard_report now only calls
  *                                     igmp_timer_expire if tm->running is
@@ -455,6 +455,8 @@
 			skb = add_grhead(skb, pmc, type, &pgr);
 			first = 0;
 		}
+		if (!skb)
+			return NULL;
 		psrc = (__be32 *)skb_put(skb, sizeof(__be32));
 		*psrc = psf->sf_inaddr;
 		scount++; stotal++;
@@ -716,7 +718,7 @@
 {
 	if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev))
 		return;
-	in_dev->mr_ifc_count = in_dev->mr_qrv ? in_dev->mr_qrv : 
+	in_dev->mr_ifc_count = in_dev->mr_qrv ? in_dev->mr_qrv :
 		IGMP_Unsolicited_Report_Count;
 	igmp_ifc_start_timer(in_dev, 1);
 }
@@ -836,7 +838,7 @@
 	if (len == 8) {
 		if (ih->code == 0) {
 			/* Alas, old v1 router presents here. */
-	
+
 			max_delay = IGMP_Query_Response_Interval;
 			in_dev->mr_v1_seen = jiffies +
 				IGMP_V1_Router_Present_Timeout;
@@ -858,10 +860,10 @@
 	} else { /* v3 */
 		if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
 			return;
-		
+
 		ih3 = (struct igmpv3_query *) skb->h.raw;
 		if (ih3->nsrcs) {
-			if (!pskb_may_pull(skb, sizeof(struct igmpv3_query) 
+			if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)
 					   + ntohs(ih3->nsrcs)*sizeof(__be32)))
 				return;
 			ih3 = (struct igmpv3_query *) skb->h.raw;
@@ -907,7 +909,7 @@
 		else
 			im->gsquery = mark;
 		changed = !im->gsquery ||
-		    	igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
+			igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
 		spin_unlock_bh(&im->lock);
 		if (changed)
 			igmp_mod_timer(im, max_delay);
@@ -1255,9 +1257,9 @@
 void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
 {
 	struct ip_mc_list *i, **ip;
-	
+
 	ASSERT_RTNL();
-	
+
 	for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
 		if (i->multiaddr==addr) {
 			if (--i->users == 0) {
@@ -1434,7 +1436,7 @@
 #ifdef CONFIG_IP_MULTICAST
 		if (psf->sf_oldin &&
 		    !IGMP_V1_SEEN(in_dev) && !IGMP_V2_SEEN(in_dev)) {
-			psf->sf_crcount = in_dev->mr_qrv ? in_dev->mr_qrv : 
+			psf->sf_crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
 				IGMP_Unsolicited_Report_Count;
 			psf->sf_next = pmc->tomb;
 			pmc->tomb = psf;
@@ -1498,7 +1500,7 @@
 		/* filter mode change */
 		pmc->sfmode = MCAST_INCLUDE;
 #ifdef CONFIG_IP_MULTICAST
-		pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv : 
+		pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
 			IGMP_Unsolicited_Report_Count;
 		in_dev->mr_ifc_count = pmc->crcount;
 		for (psf=pmc->sources; psf; psf = psf->sf_next)
@@ -1677,7 +1679,7 @@
 #ifdef CONFIG_IP_MULTICAST
 		/* else no filters; keep old mode for reports */
 
-		pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv : 
+		pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
 			IGMP_Unsolicited_Report_Count;
 		in_dev->mr_ifc_count = pmc->crcount;
 		for (psf=pmc->sources; psf; psf = psf->sf_next)
@@ -1871,7 +1873,7 @@
 	} else if (pmc->sfmode != omode) {
 		/* allow mode switches for empty-set filters */
 		ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 0, NULL, 0);
-		ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, pmc->sfmode, 0, 
+		ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, pmc->sfmode, 0,
 			NULL, 0);
 		pmc->sfmode = omode;
 	}
@@ -1897,7 +1899,7 @@
 		}
 
 		/* update the interface filter */
-		ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1, 
+		ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
 			&mreqs->imr_sourceaddr, 1);
 
 		for (j=i+1; j<psl->sl_count; j++)
@@ -1947,7 +1949,7 @@
 	psl->sl_count++;
 	err = 0;
 	/* update the interface list */
-	ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1, 
+	ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
 		&mreqs->imr_sourceaddr, 1);
 done:
 	rtnl_unlock();
@@ -2262,7 +2264,7 @@
 	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
 
 	for (state->dev = dev_base, state->in_dev = NULL;
-	     state->dev; 
+	     state->dev;
 	     state->dev = state->dev->next) {
 		struct in_device *in_dev;
 		in_dev = in_dev_get(state->dev);
@@ -2344,7 +2346,7 @@
 static int igmp_mc_seq_show(struct seq_file *seq, void *v)
 {
 	if (v == SEQ_START_TOKEN)
-		seq_puts(seq, 
+		seq_puts(seq,
 			 "Idx\tDevice    : Count Querier\tGroup    Users Timer\tReporter\n");
 	else {
 		struct ip_mc_list *im = (struct ip_mc_list *)v;
@@ -2401,7 +2403,7 @@
 	goto out;
 }
 
-static struct file_operations igmp_mc_seq_fops = {
+static const struct file_operations igmp_mc_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	igmp_mc_seq_open,
 	.read		=	seq_read,
@@ -2424,7 +2426,7 @@
 	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
 
 	for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
-	     state->dev; 
+	     state->dev;
 	     state->dev = state->dev->next) {
 		struct in_device *idev;
 		idev = in_dev_get(state->dev);
@@ -2529,7 +2531,7 @@
 	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
 
 	if (v == SEQ_START_TOKEN) {
-		seq_printf(seq, 
+		seq_printf(seq,
 			   "%3s %6s "
 			   "%10s %10s %6s %6s\n", "Idx",
 			   "Device", "MCA",
@@ -2537,8 +2539,8 @@
 	} else {
 		seq_printf(seq,
 			   "%3d %6.6s 0x%08x "
-			   "0x%08x %6lu %6lu\n", 
-			   state->dev->ifindex, state->dev->name, 
+			   "0x%08x %6lu %6lu\n",
+			   state->dev->ifindex, state->dev->name,
 			   ntohl(state->im->multiaddr),
 			   ntohl(psf->sf_inaddr),
 			   psf->sf_count[MCAST_INCLUDE],
@@ -2575,7 +2577,7 @@
 	goto out;
 }
 
-static struct file_operations igmp_mcf_seq_fops = {
+static const struct file_operations igmp_mcf_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	igmp_mcf_seq_open,
 	.read		=	seq_read,
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 9d68837..43fb160 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -149,7 +149,7 @@
 	if (!inet_csk(sk)->icsk_bind_hash)
 		inet_bind_hash(sk, tb, snum);
 	BUG_TRAP(inet_csk(sk)->icsk_bind_hash == tb);
- 	ret = 0;
+	ret = 0;
 
 fail_unlock:
 	spin_unlock(&head->lock);
@@ -255,7 +255,7 @@
 
 /*
  * Using different timers for retransmit, delayed acks and probes
- * We may wish use just one timer maintaining a list of expire jiffies 
+ * We may wish use just one timer maintaining a list of expire jiffies
  * to optimize.
  */
 void inet_csk_init_xmit_timers(struct sock *sk,
@@ -273,7 +273,7 @@
 	icsk->icsk_delack_timer.function     = delack_handler;
 	sk->sk_timer.function		     = keepalive_handler;
 
-	icsk->icsk_retransmit_timer.data = 
+	icsk->icsk_retransmit_timer.data =
 		icsk->icsk_delack_timer.data =
 			sk->sk_timer.data  = (unsigned long)sk;
 
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 77761ac..5df71cd 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -153,7 +153,7 @@
 rtattr_failure:
 nlmsg_failure:
 	skb_trim(skb, b - skb->data);
-	return -1;
+	return -EMSGSIZE;
 }
 
 static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
@@ -209,7 +209,7 @@
 	return skb->len;
 nlmsg_failure:
 	skb_trim(skb, previous_tail - skb->data);
-	return -1;
+	return -EMSGSIZE;
 }
 
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
@@ -274,11 +274,14 @@
 	if (!rep)
 		goto out;
 
-	if (sk_diag_fill(sk, rep, req->idiag_ext,
-			 NETLINK_CB(in_skb).pid,
-			 nlh->nlmsg_seq, 0, nlh) <= 0)
-		BUG();
-
+	err = sk_diag_fill(sk, rep, req->idiag_ext,
+			   NETLINK_CB(in_skb).pid,
+			   nlh->nlmsg_seq, 0, nlh);
+	if (err < 0) {
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(rep);
+		goto out;
+	}
 	err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid,
 			      MSG_DONTWAIT);
 	if (err > 0)
@@ -378,7 +381,7 @@
 				if (addr[0] == 0 && addr[1] == 0 &&
 				    addr[2] == htonl(0xffff) &&
 				    bitstring_match(addr + 3, cond->addr,
-					    	    cond->prefix_len))
+						    cond->prefix_len))
 					break;
 			}
 			yes = 0;
@@ -515,7 +518,7 @@
 		}
 		entry.sport = tw->tw_num;
 		entry.dport = ntohs(tw->tw_dport);
-		entry.userlocks = 0; 
+		entry.userlocks = 0;
 
 		if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry))
 			return 0;
@@ -775,7 +778,7 @@
 			struct inet_timewait_sock *tw;
 
 			inet_twsk_for_each(tw, node,
-				    &hashinfo->ehash[i + hashinfo->ehash_size].chain) {
+				    &head->twchain) {
 
 				if (num < s_num)
 					goto next_dying;
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 8c79c8a..fb66262 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -212,7 +212,7 @@
 	write_lock(&head->lock);
 
 	/* Check TIME-WAIT sockets first. */
-	sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) {
+	sk_for_each(sk2, node, &head->twchain) {
 		tw = inet_twsk(sk2);
 
 		if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {
@@ -262,7 +262,7 @@
 static inline u32 inet_sk_port_offset(const struct sock *sk)
 {
 	const struct inet_sock *inet = inet_sk(sk);
-	return secure_ipv4_port_ephemeral(inet->rcv_saddr, inet->daddr, 
+	return secure_ipv4_port_ephemeral(inet->rcv_saddr, inet->daddr,
 					  inet->dport);
 }
 
@@ -274,81 +274,81 @@
 {
 	struct inet_hashinfo *hinfo = death_row->hashinfo;
 	const unsigned short snum = inet_sk(sk)->num;
- 	struct inet_bind_hashbucket *head;
- 	struct inet_bind_bucket *tb;
+	struct inet_bind_hashbucket *head;
+	struct inet_bind_bucket *tb;
 	int ret;
 
- 	if (!snum) {
- 		int low = sysctl_local_port_range[0];
- 		int high = sysctl_local_port_range[1];
+	if (!snum) {
+		int low = sysctl_local_port_range[0];
+		int high = sysctl_local_port_range[1];
 		int range = high - low;
- 		int i;
+		int i;
 		int port;
 		static u32 hint;
 		u32 offset = hint + inet_sk_port_offset(sk);
 		struct hlist_node *node;
- 		struct inet_timewait_sock *tw = NULL;
+		struct inet_timewait_sock *tw = NULL;
 
- 		local_bh_disable();
+		local_bh_disable();
 		for (i = 1; i <= range; i++) {
 			port = low + (i + offset) % range;
- 			head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)];
- 			spin_lock(&head->lock);
+			head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)];
+			spin_lock(&head->lock);
 
- 			/* Does not bother with rcv_saddr checks,
- 			 * because the established check is already
- 			 * unique enough.
- 			 */
+			/* Does not bother with rcv_saddr checks,
+			 * because the established check is already
+			 * unique enough.
+			 */
 			inet_bind_bucket_for_each(tb, node, &head->chain) {
- 				if (tb->port == port) {
- 					BUG_TRAP(!hlist_empty(&tb->owners));
- 					if (tb->fastreuse >= 0)
- 						goto next_port;
- 					if (!__inet_check_established(death_row,
+				if (tb->port == port) {
+					BUG_TRAP(!hlist_empty(&tb->owners));
+					if (tb->fastreuse >= 0)
+						goto next_port;
+					if (!__inet_check_established(death_row,
 								      sk, port,
 								      &tw))
- 						goto ok;
- 					goto next_port;
- 				}
- 			}
+						goto ok;
+					goto next_port;
+				}
+			}
 
- 			tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, head, port);
- 			if (!tb) {
- 				spin_unlock(&head->lock);
- 				break;
- 			}
- 			tb->fastreuse = -1;
- 			goto ok;
+			tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, head, port);
+			if (!tb) {
+				spin_unlock(&head->lock);
+				break;
+			}
+			tb->fastreuse = -1;
+			goto ok;
 
- 		next_port:
- 			spin_unlock(&head->lock);
- 		}
- 		local_bh_enable();
+		next_port:
+			spin_unlock(&head->lock);
+		}
+		local_bh_enable();
 
- 		return -EADDRNOTAVAIL;
+		return -EADDRNOTAVAIL;
 
 ok:
 		hint += i;
 
- 		/* Head lock still held and bh's disabled */
- 		inet_bind_hash(sk, tb, port);
+		/* Head lock still held and bh's disabled */
+		inet_bind_hash(sk, tb, port);
 		if (sk_unhashed(sk)) {
- 			inet_sk(sk)->sport = htons(port);
- 			__inet_hash(hinfo, sk, 0);
- 		}
- 		spin_unlock(&head->lock);
+			inet_sk(sk)->sport = htons(port);
+			__inet_hash(hinfo, sk, 0);
+		}
+		spin_unlock(&head->lock);
 
- 		if (tw) {
- 			inet_twsk_deschedule(tw, death_row);
- 			inet_twsk_put(tw);
- 		}
+		if (tw) {
+			inet_twsk_deschedule(tw, death_row);
+			inet_twsk_put(tw);
+		}
 
 		ret = 0;
 		goto out;
- 	}
+	}
 
- 	head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
- 	tb  = inet_csk(sk)->icsk_bind_hash;
+	head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
+	tb  = inet_csk(sk)->icsk_bind_hash;
 	spin_lock_bh(&head->lock);
 	if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
 		__inet_hash(hinfo, sk, 0);
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index 9f414e3..a73cf93 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -78,8 +78,8 @@
 	if (__sk_del_node_init(sk))
 		sock_prot_dec_use(sk->sk_prot);
 
-	/* Step 3: Hash TW into TIMEWAIT half of established hash table. */
-	inet_twsk_add_node(tw, &(ehead + hashinfo->ehash_size)->chain);
+	/* Step 3: Hash TW into TIMEWAIT chain. */
+	inet_twsk_add_node(tw, &ehead->twchain);
 	atomic_inc(&tw->tw_refcnt);
 
 	write_unlock(&ehead->lock);
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 711eb6d..db3ef96 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -14,7 +14,6 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/random.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/time.h>
 #include <linux/kernel.h>
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index a22d11d..369e721 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -4,15 +4,15 @@
  *		interface as the means of communication with the user level.
  *
  *		The IP forwarding functionality.
- *		
+ *
  * Version:	$Id: ip_forward.c,v 1.48 2000/12/13 18:31:48 davem Exp $
  *
  * Authors:	see ip.c
  *
  * Fixes:
- *		Many		:	Split from ip.c , see ip_input.c for 
+ *		Many		:	Split from ip.c , see ip_input.c for
  *					history.
- *		Dave Gregorich	:	NULL ip_rt_put fix for multicast 
+ *		Dave Gregorich	:	NULL ip_rt_put fix for multicast
  *					routing.
  *		Jos Vos		:	Add call_out_firewall before sending,
  *					use output device for accounting.
@@ -23,7 +23,6 @@
 
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/icmp.h>
@@ -69,14 +68,14 @@
 		goto drop;
 
 	skb->ip_summed = CHECKSUM_NONE;
-	
+
 	/*
 	 *	According to the RFC, we must first decrease the TTL field. If
 	 *	that reaches zero, we must reply an ICMP control message telling
 	 *	that the packet's lifetime expired.
 	 */
 	if (skb->nh.iph->ttl <= 1)
-                goto too_many_hops;
+		goto too_many_hops;
 
 	if (!xfrm4_route_forward(skb))
 		goto drop;
@@ -107,16 +106,16 @@
 		       ip_forward_finish);
 
 sr_failed:
-        /*
+	/*
 	 *	Strict routing permits no gatewaying
 	 */
-         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
-         goto drop;
+	 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
+	 goto drop;
 
 too_many_hops:
-        /* Tell the sender its packet died... */
-        IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
-        icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
+	/* Tell the sender its packet died... */
+	IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+	icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
 drop:
 	kfree_skb(skb);
 	return NET_RX_DROP;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 8ce00d3..b6f0553 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -4,7 +4,7 @@
  *		interface as the means of communication with the user level.
  *
  *		The IP fragmentation functionality.
- *		
+ *
  * Version:	$Id: ip_fragment.c,v 1.59 2002/01/12 07:54:56 davem Exp $
  *
  * Authors:	Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
@@ -238,7 +238,7 @@
 	}
 }
 
-/* Memory limiting on fragments.  Evictor trashes the oldest 
+/* Memory limiting on fragments.  Evictor trashes the oldest
  * fragment queue until we are back under the threshold.
  */
 static void ip_evictor(void)
@@ -479,14 +479,14 @@
 		goto err;
 	}
 
- 	offset = ntohs(skb->nh.iph->frag_off);
+	offset = ntohs(skb->nh.iph->frag_off);
 	flags = offset & ~IP_OFFSET;
 	offset &= IP_OFFSET;
 	offset <<= 3;		/* offset is in 8-byte chunks */
- 	ihl = skb->nh.iph->ihl * 4;
+	ihl = skb->nh.iph->ihl * 4;
 
 	/* Determine the position of this fragment. */
- 	end = offset + skb->len - ihl;
+	end = offset + skb->len - ihl;
 
 	/* Is this the final fragment? */
 	if ((flags & IP_MF) == 0) {
@@ -589,8 +589,8 @@
 	else
 		qp->fragments = skb;
 
- 	if (skb->dev)
- 		qp->iif = skb->dev->ifindex;
+	if (skb->dev)
+		qp->iif = skb->dev->ifindex;
 	skb->dev = NULL;
 	skb_get_timestamp(skb, &qp->stamp);
 	qp->meat += skb->len;
@@ -684,7 +684,7 @@
 	return head;
 
 out_nomem:
- 	LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing "
+	LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing "
 			      "queue %p\n", qp);
 	goto out_fail;
 out_oversize:
@@ -703,7 +703,7 @@
 	struct iphdr *iph = skb->nh.iph;
 	struct ipq *qp;
 	struct net_device *dev;
-	
+
 	IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
 
 	/* Start by cleaning up the memory. */
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 476cb60..9151da6 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1,5 +1,5 @@
 /*
- *	Linux NET3:	GRE over IP protocol decoder. 
+ *	Linux NET3:	GRE over IP protocol decoder.
  *
  *	Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
  *
@@ -13,7 +13,6 @@
 #include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
 #include <linux/skbuff.h>
@@ -63,7 +62,7 @@
    solution, but it supposes maintaing new variable in ALL
    skb, even if no tunneling is used.
 
-   Current solution: t->recursion lock breaks dead loops. It looks 
+   Current solution: t->recursion lock breaks dead loops. It looks
    like dev->tbusy flag, but I preferred new variable, because
    the semantics is different. One day, when hard_start_xmit
    will be multithreaded we will have to use skb->encapsulation.
@@ -613,7 +612,7 @@
 		if (flags == 0 &&
 		    skb->protocol == htons(ETH_P_WCCP)) {
 			skb->protocol = htons(ETH_P_IP);
-			if ((*(h + offset) & 0xF0) != 0x40) 
+			if ((*(h + offset) & 0xF0) != 0x40)
 				offset += 4;
 		}
 
@@ -816,7 +815,7 @@
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
-  			stats->tx_dropped++;
+			stats->tx_dropped++;
 			dev_kfree_skb(skb);
 			tunnel->recursion--;
 			return 0;
@@ -1008,7 +1007,8 @@
 				goto done;
 			dev = t->dev;
 		}
-		err = unregister_netdevice(dev);
+		unregister_netdevice(dev);
+		err = 0;
 		break;
 
 	default:
@@ -1043,7 +1043,7 @@
    so that I had to set ARPHRD_IPGRE to a random value.
    I have an impression, that Cisco could make something similar,
    but this feature is apparently missing in IOS<=11.2(8).
-   
+
    I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
    with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
 
@@ -1075,9 +1075,9 @@
 	p[1]		= htons(type);
 
 	/*
-	 *	Set the source hardware address. 
+	 *	Set the source hardware address.
 	 */
-	 
+
 	if (saddr)
 		memcpy(&iph->saddr, saddr, 4);
 
@@ -1087,7 +1087,7 @@
 	}
 	if (iph->daddr && !MULTICAST(iph->daddr))
 		return t->hlen;
-	
+
 	return -t->hlen;
 }
 
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 212734c..f38e976 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -15,7 +15,7 @@
  *		Stefan Becker, <stefanb@yello.ping.de>
  *		Jorge Cwik, <jorge@laser.satlink.net>
  *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
- *		
+ *
  *
  * Fixes:
  *		Alan Cox	:	Commented a couple of minor bits of surplus code
@@ -98,13 +98,13 @@
  *		Jos Vos		:	Do accounting *before* call_in_firewall
  *	Willy Konynenberg	:	Transparent proxying support
  *
- *  
+ *
  *
  * To Fix:
  *		IP fragmentation wants rewriting cleanly. The RFC815 algorithm is much more efficient
  *		and could be made very efficient with the addition of some virtual memory hacks to permit
  *		the allocation of a buffer that can then be 'grown' by twiddling page tables.
- *		Output fragmentation wants updating along with the buffer management to use a single 
+ *		Output fragmentation wants updating along with the buffer management to use a single
  *		interleaved copy algorithm so that fragmenting has a one copy overhead. Actual packet
  *		output should probably do its own fragmentation at the UDP/RAW layer. TCP shouldn't cause
  *		fragmentation anyway.
@@ -154,7 +154,7 @@
 
 /*
  *	Process Router Attention IP option
- */ 
+ */
 int ip_call_ra_chain(struct sk_buff *skb)
 {
 	struct ip_ra_chain *ra;
@@ -202,8 +202,8 @@
 
 	__skb_pull(skb, ihl);
 
-        /* Point into the IP datagram, just past the header. */
-        skb->h.raw = skb->data;
+	/* Point into the IP datagram, just past the header. */
+	skb->h.raw = skb->data;
 
 	rcu_read_lock();
 	{
@@ -259,7 +259,7 @@
 
 /*
  * 	Deliver IP Packets to the higher protocol layers.
- */ 
+ */
 int ip_local_deliver(struct sk_buff *skb)
 {
 	/*
@@ -335,14 +335,14 @@
 	/*
 	 *	Initialise the virtual path cache for the packet. It describes
 	 *	how the packet travels inside Linux networking.
-	 */ 
+	 */
 	if (skb->dst == NULL) {
 		int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
 					 skb->dev);
 		if (unlikely(err)) {
 			if (err == -EHOSTUNREACH)
 				IP_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
-			goto drop; 
+			goto drop;
 		}
 	}
 
@@ -363,13 +363,13 @@
 	return dst_input(skb);
 
 drop:
-        kfree_skb(skb);
-        return NET_RX_DROP;
+	kfree_skb(skb);
+	return NET_RX_DROP;
 }
 
 /*
  * 	Main IP Receive routine.
- */ 
+ */
 int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
 {
 	struct iphdr *iph;
@@ -437,9 +437,9 @@
 inhdr_error:
 	IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
 drop:
-        kfree_skb(skb);
+	kfree_skb(skb);
 out:
-        return NET_RX_DROP;
+	return NET_RX_DROP;
 }
 
 EXPORT_SYMBOL(ip_statistics);
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 9f02917..f906a80 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -8,7 +8,7 @@
  * Version:	$Id: ip_options.c,v 1.21 2001/09/01 00:31:50 davem Exp $
  *
  * Authors:	A.N.Kuznetsov
- *		
+ *
  */
 
 #include <linux/capability.h>
@@ -26,7 +26,7 @@
 #include <net/route.h>
 #include <net/cipso_ipv4.h>
 
-/* 
+/*
  * Write options to IP header, record destination address to
  * source route option, address of outgoing interface
  * (we should already know it, so that this  function is allowed be
@@ -76,7 +76,7 @@
 	}
 }
 
-/* 
+/*
  * Provided (sopt, skb) points to received options,
  * build in dopt compiled option set appropriate for answering.
  * i.e. invert SRR option, copy anothers,
@@ -85,7 +85,7 @@
  * NOTE: dopt cannot point to skb.
  */
 
-int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) 
+int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
 {
 	struct ip_options *sopt;
 	unsigned char *sptr, *dptr;
@@ -215,7 +215,7 @@
  *	Simple and stupid 8), but the most efficient way.
  */
 
-void ip_options_fragment(struct sk_buff * skb) 
+void ip_options_fragment(struct sk_buff * skb)
 {
 	unsigned char * optptr = skb->nh.raw + sizeof(struct iphdr);
 	struct ip_options * opt = &(IPCB(skb)->opt);
@@ -370,7 +370,7 @@
 				switch (optptr[3]&0xF) {
 				      case IPOPT_TS_TSONLY:
 					opt->ts = optptr - iph;
-					if (skb) 
+					if (skb)
 						timeptr = (__be32*)&optptr[optptr[2]-1];
 					opt->ts_needtime = 1;
 					optptr[2] += 4;
@@ -448,7 +448,7 @@
 				goto error;
 			}
 			opt->cipso = optptr - iph;
-		        if (cipso_v4_validate(&optptr)) {
+			if (cipso_v4_validate(&optptr)) {
 				pp_ptr = optptr;
 				goto error;
 			}
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index a0f2008..d096332 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -22,7 +22,7 @@
  *	Fixes:
  *		Alan Cox	:	Missing nonblock feature in ip_build_xmit.
  *		Mike Kilburn	:	htons() missing in ip_build_xmit.
- *		Bradford Johnson:	Fix faulty handling of some frames when 
+ *		Bradford Johnson:	Fix faulty handling of some frames when
  *					no route is found.
  *		Alexander Demenshin:	Missing sk/skb free in ip_queue_xmit
  *					(in case if packet not accepted by
@@ -33,9 +33,9 @@
  *					some redundant tests.
  *	Vitaly E. Lavrov	:	Transparent proxy revived after year coma.
  *		Andi Kleen	: 	Replace ip_reply with ip_send_reply.
- *		Andi Kleen	:	Split fast and slow ip_build_xmit path 
- *					for decreased register pressure on x86 
- *					and more readibility. 
+ *		Andi Kleen	:	Split fast and slow ip_build_xmit path
+ *					for decreased register pressure on x86
+ *					and more readibility.
  *		Marc Boucher	:	When call_out_firewall returns FW_QUEUE,
  *					silently drop skb instead of failing with -EPERM.
  *		Detlev Wengorz	:	Copy protocol for fragments.
@@ -49,7 +49,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -114,7 +113,7 @@
 	return ttl;
 }
 
-/* 
+/*
  *		Add an ip header to a skbuff and send it out.
  *
  */
@@ -243,7 +242,7 @@
 			struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
 			if (newskb)
 				NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL,
-					newskb->dev, 
+					newskb->dev,
 					ip_dev_loopback_xmit);
 		}
 
@@ -277,7 +276,7 @@
 	skb->protocol = htons(ETH_P_IP);
 
 	return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
-		            ip_finish_output,
+			    ip_finish_output,
 			    !(IPCB(skb)->flags & IPSKB_REROUTED));
 }
 
@@ -660,7 +659,7 @@
 	return err;
 
 fail:
-	kfree_skb(skb); 
+	kfree_skb(skb);
 	IP_INC_STATS(IPSTATS_MIB_FRAGFAILS);
 	return err;
 }
@@ -755,7 +754,7 @@
  *	from many pieces of data. Each pieces will be holded on the socket
  *	until ip_push_pending_frames() is called. Each piece can be a page
  *	or non-page data.
- *	
+ *
  *	Not only UDP, other transport protocols - e.g. raw sockets - can use
  *	this interface potentially.
  *
@@ -888,7 +887,7 @@
 				datalen = maxfraglen - fragheaderlen;
 			fraglen = datalen + fragheaderlen;
 
-			if ((flags & MSG_MORE) && 
+			if ((flags & MSG_MORE) &&
 			    !(rt->u.dst.dev->features&NETIF_F_SG))
 				alloclen = mtu;
 			else
@@ -903,14 +902,14 @@
 				alloclen += rt->u.dst.trailer_len;
 
 			if (transhdrlen) {
-				skb = sock_alloc_send_skb(sk, 
+				skb = sock_alloc_send_skb(sk,
 						alloclen + hh_len + 15,
 						(flags & MSG_DONTWAIT), &err);
 			} else {
 				skb = NULL;
 				if (atomic_read(&sk->sk_wmem_alloc) <=
 				    2 * sk->sk_sndbuf)
-					skb = sock_wmalloc(sk, 
+					skb = sock_wmalloc(sk,
 							   alloclen + hh_len + 15, 1,
 							   sk->sk_allocation);
 				if (unlikely(skb == NULL))
@@ -971,7 +970,7 @@
 			unsigned int off;
 
 			off = skb->len;
-			if (getfrag(from, skb_put(skb, copy), 
+			if (getfrag(from, skb_put(skb, copy),
 					offset, copy, off, skb) < 0) {
 				__skb_trim(skb, off);
 				err = -EFAULT;
@@ -993,7 +992,7 @@
 						goto error;
 					}
 					get_page(page);
-	 				skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
+					skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
 					frag = &skb_shinfo(skb)->frags[i];
 				}
 			} else if (i < MAX_SKB_FRAGS) {
@@ -1033,7 +1032,7 @@
 error:
 	inet->cork.length -= length;
 	IP_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
-	return err; 
+	return err;
 }
 
 ssize_t	ip_append_page(struct sock *sk, struct page *page,
@@ -1257,7 +1256,7 @@
 	skb->dst = dst_clone(&rt->u.dst);
 
 	/* Netfilter gets whole the not fragmented skb. */
-	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
+	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
 		      skb->dst->dev, dst_output);
 	if (err) {
 		if (err > 0)
@@ -1305,21 +1304,21 @@
 /*
  *	Fetch data from kernel space and fill in checksum if needed.
  */
-static int ip_reply_glue_bits(void *dptr, char *to, int offset, 
+static int ip_reply_glue_bits(void *dptr, char *to, int offset,
 			      int len, int odd, struct sk_buff *skb)
 {
 	__wsum csum;
 
 	csum = csum_partial_copy_nocheck(dptr+offset, to, len, 0);
 	skb->csum = csum_block_add(skb->csum, csum, odd);
-	return 0;  
+	return 0;
 }
 
-/* 
+/*
  *	Generic function to send a packet as reply to another packet.
  *	Used to send TCP resets so far. ICMP should use this function too.
  *
- *	Should run single threaded per socket because it uses the sock 
+ *	Should run single threaded per socket because it uses the sock
  *     	structure to pass arguments.
  *
  *	LATER: switch from ip_build_xmit to ip_append_*
@@ -1357,7 +1356,7 @@
 				    /* Not quite clean, but right. */
 				    .uli_u = { .ports =
 					       { .sport = skb->h.th->dest,
-					         .dport = skb->h.th->source } },
+						 .dport = skb->h.th->source } },
 				    .proto = sk->sk_protocol };
 		security_skb_classify_flow(skb, &fl);
 		if (ip_route_output_key(&rt, &fl))
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 57d4bae..23048d9 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -4,7 +4,7 @@
  *		interface as the means of communication with the user level.
  *
  *		The IP to API glue.
- *		
+ *
  * Version:	$Id: ip_sockglue.c,v 1.62 2002/02/01 22:01:04 davem Exp $
  *
  * Authors:	see ip.c
@@ -12,7 +12,7 @@
  * Fixes:
  *		Many		:	Split from ip.c , see ip.c for history.
  *		Martin Mares	:	TOS setting fixed.
- *		Alan Cox	:	Fixed a couple of oopses in Martin's 
+ *		Alan Cox	:	Fixed a couple of oopses in Martin's
  *					TOS tweaks.
  *		Mike McLagan	:	Routing by source
  */
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/icmp.h>
@@ -253,7 +252,7 @@
 	return 0;
 }
 
-void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
+void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
 		   __be16 port, u32 info, u8 *payload)
 {
 	struct inet_sock *inet = inet_sk(sk);
@@ -266,10 +265,10 @@
 	if (!skb)
 		return;
 
-	serr = SKB_EXT_ERR(skb);  
+	serr = SKB_EXT_ERR(skb);
 	serr->ee.ee_errno = err;
 	serr->ee.ee_origin = SO_EE_ORIGIN_ICMP;
-	serr->ee.ee_type = skb->h.icmph->type; 
+	serr->ee.ee_type = skb->h.icmph->type;
 	serr->ee.ee_code = skb->h.icmph->code;
 	serr->ee.ee_pad = 0;
 	serr->ee.ee_info = info;
@@ -301,10 +300,10 @@
 	skb->nh.iph = iph;
 	iph->daddr = daddr;
 
-	serr = SKB_EXT_ERR(skb);  
+	serr = SKB_EXT_ERR(skb);
 	serr->ee.ee_errno = err;
 	serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
-	serr->ee.ee_type = 0; 
+	serr->ee.ee_type = 0;
 	serr->ee.ee_code = 0;
 	serr->ee.ee_pad = 0;
 	serr->ee.ee_info = info;
@@ -319,7 +318,7 @@
 		kfree_skb(skb);
 }
 
-/* 
+/*
  *	Handle MSG_ERRQUEUE
  */
 int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
@@ -391,7 +390,7 @@
 	} else
 		spin_unlock_bh(&sk->sk_error_queue.lock);
 
-out_free_skb:	
+out_free_skb:
 	kfree_skb(skb);
 out:
 	return err;
@@ -409,15 +408,15 @@
 	struct inet_sock *inet = inet_sk(sk);
 	int val=0,err;
 
-	if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | 
-			    (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | 
-			    (1<<IP_RETOPTS) | (1<<IP_TOS) | 
-			    (1<<IP_TTL) | (1<<IP_HDRINCL) | 
-			    (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | 
+	if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
+			    (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
+			    (1<<IP_RETOPTS) | (1<<IP_TOS) |
+			    (1<<IP_TTL) | (1<<IP_HDRINCL) |
+			    (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
 			    (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
 			    (1<<IP_PASSSEC))) ||
-				optname == IP_MULTICAST_TTL || 
-				optname == IP_MULTICAST_LOOP) { 
+				optname == IP_MULTICAST_TTL ||
+				optname == IP_MULTICAST_LOOP) {
 		if (optlen >= sizeof(int)) {
 			if (get_user(val, (int __user *) optval))
 				return -EFAULT;
@@ -511,7 +510,7 @@
 				val &= ~3;
 				val |= inet->tos & 3;
 			}
-			if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && 
+			if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP &&
 			    !capable(CAP_NET_ADMIN)) {
 				err = -EPERM;
 				break;
@@ -519,7 +518,7 @@
 			if (inet->tos != val) {
 				inet->tos = val;
 				sk->sk_priority = rt_tos2priority(val);
-				sk_dst_reset(sk); 
+				sk_dst_reset(sk);
 			}
 			break;
 		case IP_TTL:
@@ -556,13 +555,13 @@
 			if (val < 0 || val > 255)
 				goto e_inval;
 			inet->mc_ttl = val;
-	                break;
-		case IP_MULTICAST_LOOP: 
+			break;
+		case IP_MULTICAST_LOOP:
 			if (optlen<1)
 				goto e_inval;
 			inet->mc_loop = !!val;
-	                break;
-		case IP_MULTICAST_IF: 
+			break;
+		case IP_MULTICAST_IF:
 		{
 			struct ip_mreqn mreq;
 			struct net_device *dev = NULL;
@@ -616,7 +615,7 @@
 		}
 
 		case IP_ADD_MEMBERSHIP:
-		case IP_DROP_MEMBERSHIP: 
+		case IP_DROP_MEMBERSHIP:
 		{
 			struct ip_mreqn mreq;
 
@@ -629,7 +628,7 @@
 			} else {
 				memset(&mreq, 0, sizeof(mreq));
 				if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq)))
-					break; 
+					break;
 			}
 
 			if (optname == IP_ADD_MEMBERSHIP)
@@ -714,7 +713,7 @@
 			break;
 		}
 		case MCAST_JOIN_GROUP:
-		case MCAST_LEAVE_GROUP: 
+		case MCAST_LEAVE_GROUP:
 		{
 			struct group_req greq;
 			struct sockaddr_in *psin;
@@ -858,16 +857,16 @@
 			kfree(gsf);
 			break;
 		}
-		case IP_ROUTER_ALERT:	
+		case IP_ROUTER_ALERT:
 			err = ip_ra_control(sk, val ? 1 : 0, NULL);
 			break;
 
 		case IP_FREEBIND:
 			if (optlen<1)
 				goto e_inval;
-			inet->freebind = !!val; 
-	                break;			
- 
+			inet->freebind = !!val;
+			break;
+
 		case IP_IPSEC_POLICY:
 		case IP_XFRM_POLICY:
 			err = -EPERM;
@@ -954,7 +953,7 @@
 	struct inet_sock *inet = inet_sk(sk);
 	int val;
 	int len;
-	
+
 	if(level!=SOL_IP)
 		return -EOPNOTSUPP;
 
@@ -969,7 +968,7 @@
 		return -EFAULT;
 	if(len < 0)
 		return -EINVAL;
-		
+
 	lock_sock(sk);
 
 	switch(optname)	{
@@ -984,7 +983,7 @@
 					       inet->opt->optlen);
 				release_sock(sk);
 
-				if (opt->optlen == 0) 
+				if (opt->optlen == 0)
 					return put_user(0, optlen);
 
 				ip_options_undo(opt);
@@ -1059,8 +1058,8 @@
 			addr.s_addr = inet->mc_addr;
 			release_sock(sk);
 
-  			if(put_user(len, optlen))
-  				return -EFAULT;
+			if(put_user(len, optlen))
+				return -EFAULT;
 			if(copy_to_user(optval, &addr, len))
 				return -EFAULT;
 			return 0;
@@ -1101,7 +1100,7 @@
 			release_sock(sk);
 			return err;
 		}
-		case IP_PKTOPTIONS:		
+		case IP_PKTOPTIONS:
 		{
 			struct msghdr msg;
 
@@ -1129,15 +1128,15 @@
 			len -= msg.msg_controllen;
 			return put_user(len, optlen);
 		}
-		case IP_FREEBIND: 
-			val = inet->freebind; 
-			break; 
+		case IP_FREEBIND:
+			val = inet->freebind;
+			break;
 		default:
 			release_sock(sk);
 			return -ENOPROTOOPT;
 	}
 	release_sock(sk);
-	
+
 	if (len < sizeof(int) && len > 0 && val>=0 && val<255) {
 		unsigned char ucval = (unsigned char)val;
 		len = 1;
@@ -1168,7 +1167,7 @@
 		&& (optname < MRT_BASE || optname > MRT_BASE+10)
 #endif
 	   ) {
-	   	int len;
+		int len;
 
 		if(get_user(len,optlen))
 			return -EFAULT;
@@ -1197,7 +1196,7 @@
 	    && (optname < MRT_BASE || optname > MRT_BASE+10)
 #endif
 	   ) {
-	   	int len;
+		int len;
 
 		if (get_user(len, optlen))
 			return -EFAULT;
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 3839b70..aa704b8 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -5,7 +5,7 @@
  *
  * 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) 
+ * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
  * Todo:
@@ -48,7 +48,7 @@
 	u8 *start, *scratch;
 	struct crypto_comp *tfm;
 	int cpu;
-	
+
 	plen = skb->len;
 	dlen = IPCOMP_SCRATCH_SIZE;
 	start = skb->data;
@@ -69,11 +69,11 @@
 	err = pskb_expand_head(skb, 0, dlen - plen, GFP_ATOMIC);
 	if (err)
 		goto out;
-		
+
 	skb->truesize += dlen - plen;
 	__skb_put(skb, dlen - plen);
 	memcpy(skb->data, scratch, dlen);
-out:	
+out:
 	put_cpu();
 	return err;
 }
@@ -85,11 +85,11 @@
 	struct ip_comp_hdr *ipch;
 
 	if (skb_linearize_cow(skb))
-	    	goto out;
+		goto out;
 
 	skb->ip_summed = CHECKSUM_NONE;
 
-	/* Remove ipcomp header and decompress original payload */	
+	/* Remove ipcomp header and decompress original payload */
 	iph = skb->nh.iph;
 	ipch = (void *)skb->data;
 	iph->protocol = ipch->nexthdr;
@@ -97,7 +97,7 @@
 	__skb_pull(skb, sizeof(*ipch));
 	err = ipcomp_decompress(x, skb);
 
-out:	
+out:
 	return err;
 }
 
@@ -109,7 +109,7 @@
 	u8 *start, *scratch;
 	struct crypto_comp *tfm;
 	int cpu;
-	
+
 	ihlen = iph->ihl * 4;
 	plen = skb->len - ihlen;
 	dlen = IPCOMP_SCRATCH_SIZE;
@@ -127,14 +127,14 @@
 		err = -EMSGSIZE;
 		goto out;
 	}
-	
+
 	memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
 	put_cpu();
 
 	pskb_trim(skb, ihlen + dlen + sizeof(struct ip_comp_hdr));
 	return 0;
-	
-out:	
+
+out:
 	put_cpu();
 	return err;
 }
@@ -157,7 +157,7 @@
 
 	if (skb_linearize_cow(skb))
 		goto out_ok;
-	
+
 	err = ipcomp_compress(x, skb);
 	iph = skb->nh.iph;
 
@@ -194,7 +194,7 @@
 
 	spi = htonl(ntohs(ipch->cpi));
 	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr,
-	                      spi, IPPROTO_COMP, AF_INET);
+			      spi, IPPROTO_COMP, AF_INET);
 	if (!x)
 		return;
 	NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%u.%u.%u.%u\n",
@@ -202,12 +202,12 @@
 	xfrm_state_put(x);
 }
 
-/* We always hold one tunnel user reference to indicate a tunnel */ 
+/* We always hold one tunnel user reference to indicate a tunnel */
 static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
 {
 	struct xfrm_state *t;
 	u8 mode = XFRM_MODE_TUNNEL;
-	
+
 	t = xfrm_state_alloc();
 	if (t == NULL)
 		goto out;
@@ -247,7 +247,7 @@
 	struct xfrm_state *t;
 
 	t = xfrm_state_lookup((xfrm_address_t *)&x->id.daddr.a4,
-	                      x->props.saddr.a4, IPPROTO_IPIP, AF_INET);
+			      x->props.saddr.a4, IPPROTO_IPIP, AF_INET);
 	if (!t) {
 		t = ipcomp_tunnel_create(x);
 		if (!t) {
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index afa60b9..cf49de1 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -12,7 +12,7 @@
  *  BOOTP rewritten to construct and analyse packets itself instead
  *  of misusing the IP layer. num_bugs_causing_wrong_arp_replies--;
  *					     -- MJ, December 1998
- *  
+ *
  *  Fixed ip_auto_config_setup calling at startup in the new "Linker Magic"
  *  initialization scheme.
  *	- Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 08/11/1999
@@ -98,8 +98,8 @@
 #define CONF_TIMEOUT_RANDOM	(HZ)	/* Maximum amount of randomization */
 #define CONF_TIMEOUT_MULT	*7/4	/* Rate of timeout growth */
 #define CONF_TIMEOUT_MAX	(HZ*30)	/* Maximum allowed timeout */
-#define CONF_NAMESERVERS_MAX   3       /* Maximum number of nameservers  
-                                           - '3' from resolv.h */
+#define CONF_NAMESERVERS_MAX   3       /* Maximum number of nameservers
+					   - '3' from resolv.h */
 
 #define NONE __constant_htonl(INADDR_NONE)
 
@@ -365,7 +365,7 @@
 	 *	At this point we have no userspace running so need not
 	 *	claim locks on system_utsname
 	 */
-	 
+
 	if (!ic_host_name_set)
 		sprintf(init_utsname()->nodename, "%u.%u.%u.%u", NIPQUAD(ic_myaddr));
 
@@ -650,9 +650,9 @@
 	*e++ = 40;
 	e += 40;
 
-	*e++ = 57;		/* set extension buffer size for reply */ 
+	*e++ = 57;		/* set extension buffer size for reply */
 	*e++ = 2;
-	*e++ = 1;		/* 128+236+8+20+14, see dhcpd sources */ 
+	*e++ = 1;		/* 128+236+8+20+14, see dhcpd sources */
 	*e++ = 150;
 
 	*e++ = 255;		/* End of the list */
@@ -913,7 +913,7 @@
 	/* Parse extensions */
 	if (ext_len >= 4 &&
 	    !memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */
-                u8 *end = (u8 *) b + ntohs(b->iph.tot_len);
+		u8 *end = (u8 *) b + ntohs(b->iph.tot_len);
 		u8 *ext;
 
 #ifdef IPCONFIG_DHCP
@@ -1020,7 +1020,7 @@
 	kfree_skb(skb);
 
 	return 0;
-}	
+}
 
 
 #endif
@@ -1080,7 +1080,7 @@
 	 * seems to be a terrible waste of CPU time, but actually there is
 	 * only one process running at all, so we don't need to use any
 	 * scheduler functions.
-	 * [Actually we could now, but the nothing else running note still 
+	 * [Actually we could now, but the nothing else running note still
 	 *  applies.. - AC]
 	 */
 	printk(KERN_NOTICE "Sending %s%s%s requests .",
@@ -1156,7 +1156,7 @@
 	}
 
 	printk("IP-Config: Got %s answer from %u.%u.%u.%u, ",
-		((ic_got_reply & IC_RARP) ? "RARP" 
+		((ic_got_reply & IC_RARP) ? "RARP"
 		 : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"),
 		NIPQUAD(ic_servaddr));
 	printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr));
@@ -1200,7 +1200,7 @@
 	return single_open(file, pnp_seq_show, NULL);
 }
 
-static struct file_operations pnp_seq_fops = {
+static const struct file_operations pnp_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= pnp_seq_open,
 	.read		= seq_read,
@@ -1286,7 +1286,7 @@
 #endif
 	    ic_first_dev->next) {
 #ifdef IPCONFIG_DYNAMIC
-	
+
 		int retries = CONF_OPEN_RETRIES;
 
 		if (ic_dynamic() < 0) {
@@ -1308,14 +1308,14 @@
 			 */
 #ifdef CONFIG_ROOT_NFS
 			if (ROOT_DEV ==  Root_NFS) {
-				printk(KERN_ERR 
+				printk(KERN_ERR
 					"IP-Config: Retrying forever (NFS root)...\n");
 				goto try_try_again;
 			}
 #endif
 
 			if (--retries) {
-				printk(KERN_ERR 
+				printk(KERN_ERR
 				       "IP-Config: Reopening network devices...\n");
 				goto try_try_again;
 			}
@@ -1443,8 +1443,8 @@
 
 	ic_set_manually = 1;
 
-	ic_enable = (*addrs && 
-		(strcmp(addrs, "off") != 0) && 
+	ic_enable = (*addrs &&
+		(strcmp(addrs, "off") != 0) &&
 		(strcmp(addrs, "none") != 0));
 	if (!ic_enable)
 		return 1;
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 9d719d6..3ec5ce0 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -1,5 +1,5 @@
 /*
- *	Linux NET3:	IP/IP protocol decoder. 
+ *	Linux NET3:	IP/IP protocol decoder.
  *
  *	Version: $Id: ipip.c,v 1.50 2001/10/02 02:22:36 davem Exp $
  *
@@ -35,14 +35,14 @@
 	Thanks for the great code!
 
 		-Sam Lantinga	(slouken@cs.ucdavis.edu)  02/01/95
-		
+
 	Minor tweaks:
 		Cleaned up the code a little and added some pre-1.3.0 tweaks.
 		dev->hard_header/hard_header_len changed to use no headers.
 		Comments/bracketing tweaked.
 		Made the tunnels use dev->name not tunnel: when error reporting.
 		Added tx_dropped stat
-		
+
 		-Alan Cox	(Alan.Cox@linux.org) 21 March 95
 
 	Reworked:
@@ -52,7 +52,7 @@
 		Note:  There is currently no firewall or ICMP handling done.
 
 		-Sam Lantinga	(slouken@cs.ucdavis.edu) 02/13/96
-		
+
 */
 
 /* Things I wish I had known when writing the tunnel driver:
@@ -75,7 +75,7 @@
 	"allocated" with skb_put().  You can then write up to skb->len
 	bytes to that buffer.  If you need more, you can call skb_put()
 	again with the additional amount of space you need.  You can
-	find out how much more space you can allocate by calling 
+	find out how much more space you can allocate by calling
 	"skb_tailroom(skb)".
 	Now, to add header space, call "skb_push(skb, header_len)".
 	This creates space at the beginning of the buffer and returns
@@ -92,11 +92,10 @@
    For comments look at net/ipv4/ip_gre.c --ANK
  */
 
- 
+
 #include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
 #include <linux/skbuff.h>
@@ -607,7 +606,7 @@
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
-  			stats->tx_dropped++;
+			stats->tx_dropped++;
 			dev_kfree_skb(skb);
 			tunnel->recursion--;
 			return 0;
@@ -754,7 +753,8 @@
 				goto done;
 			dev = t->dev;
 		}
-		err = unregister_netdevice(dev);
+		unregister_netdevice(dev);
+		err = 0;
 		break;
 
 	default:
@@ -870,7 +870,7 @@
 
 	printk(banner);
 
-	if (xfrm4_tunnel_register(&ipip_handler)) {
+	if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
 		printk(KERN_INFO "ipip init: can't register tunnel\n");
 		return -EAGAIN;
 	}
@@ -892,7 +892,7 @@
  err2:
 	free_netdev(ipip_fb_tunnel_dev);
  err1:
-	xfrm4_tunnel_deregister(&ipip_handler);
+	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
 	goto out;
 }
 
@@ -912,7 +912,7 @@
 
 static void __exit ipip_fini(void)
 {
-	if (xfrm4_tunnel_deregister(&ipip_handler))
+	if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
 		printk(KERN_INFO "ipip close: can't deregister tunnel\n");
 
 	rtnl_lock();
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index ecb5422..601e3df 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -31,7 +31,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
@@ -241,7 +240,7 @@
 /*
  *	Delete a VIF entry
  */
- 
+
 static int vif_delete(int vifi)
 {
 	struct vif_device *v;
@@ -409,7 +408,7 @@
 			return -ENOBUFS;
 		break;
 #endif
-	case VIFF_TUNNEL:	
+	case VIFF_TUNNEL:
 		dev = ipmr_new_tunnel(vifc);
 		if (!dev)
 			return -ENOBUFS;
@@ -479,20 +478,18 @@
  */
 static struct mfc_cache *ipmr_cache_alloc(void)
 {
-	struct mfc_cache *c=kmem_cache_alloc(mrt_cachep, GFP_KERNEL);
+	struct mfc_cache *c=kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
 	if(c==NULL)
 		return NULL;
-	memset(c, 0, sizeof(*c));
 	c->mfc_un.res.minvif = MAXVIFS;
 	return c;
 }
 
 static struct mfc_cache *ipmr_cache_alloc_unres(void)
 {
-	struct mfc_cache *c=kmem_cache_alloc(mrt_cachep, GFP_ATOMIC);
+	struct mfc_cache *c=kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
 	if(c==NULL)
 		return NULL;
-	memset(c, 0, sizeof(*c));
 	skb_queue_head_init(&c->mfc_un.unres.unresolved);
 	c->mfc_un.unres.expires = jiffies + 10*HZ;
 	return c;
@@ -501,7 +498,7 @@
 /*
  *	A cache entry has gone into a resolved state from queued
  */
- 
+
 static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c)
 {
 	struct sk_buff *skb;
@@ -538,7 +535,7 @@
  *
  *	Called under mrt_lock.
  */
- 
+
 static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert)
 {
 	struct sk_buff *skb;
@@ -569,13 +566,13 @@
 		memcpy(msg, pkt->nh.raw, sizeof(struct iphdr));
 		msg->im_msgtype = IGMPMSG_WHOLEPKT;
 		msg->im_mbz = 0;
- 		msg->im_vif = reg_vif_num;
+		msg->im_vif = reg_vif_num;
 		skb->nh.iph->ihl = sizeof(struct iphdr) >> 2;
 		skb->nh.iph->tot_len = htons(ntohs(pkt->nh.iph->tot_len) + sizeof(struct iphdr));
-	} else 
+	} else
 #endif
-	{	
-		
+	{
+
 	/*
 	 *	Copy the IP header
 	 */
@@ -597,7 +594,7 @@
 	igmp->code 	=	0;
 	skb->nh.iph->tot_len=htons(skb->len);			/* Fix the length */
 	skb->h.raw = skb->nh.raw;
-        }
+	}
 
 	if (mroute_socket == NULL) {
 		kfree_skb(skb);
@@ -619,7 +616,7 @@
 /*
  *	Queue a packet for resolution. It gets locked cache entry!
  */
- 
+
 static int
 ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb)
 {
@@ -657,7 +654,7 @@
 		 *	Reflect first query at mrouted.
 		 */
 		if ((err = ipmr_cache_report(skb, vifi, IGMPMSG_NOCACHE))<0) {
-			/* If the report failed throw the cache entry 
+			/* If the report failed throw the cache entry
 			   out - Brad Parker
 			 */
 			spin_unlock_bh(&mfc_unres_lock);
@@ -783,11 +780,11 @@
 /*
  *	Close the multicast socket, and clear the vif tables etc
  */
- 
+
 static void mroute_clean_tables(struct sock *sk)
 {
 	int i;
-		
+
 	/*
 	 *	Shut down all active vif entries
 	 */
@@ -854,13 +851,13 @@
  *	that's how BSD mrouted happens to think. Maybe one day with a proper
  *	MOSPF/PIM router set up we can clean this up.
  */
- 
+
 int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int optlen)
 {
 	int ret;
 	struct vifctl vif;
 	struct mfcctl mfc;
-	
+
 	if(optname!=MRT_INIT)
 	{
 		if(sk!=mroute_socket && !capable(CAP_NET_ADMIN))
@@ -901,7 +898,7 @@
 			if(optlen!=sizeof(vif))
 				return -EINVAL;
 			if (copy_from_user(&vif,optval,sizeof(vif)))
-				return -EFAULT; 
+				return -EFAULT;
 			if(vif.vifc_vifi >= MAXVIFS)
 				return -ENFILE;
 			rtnl_lock();
@@ -980,13 +977,13 @@
 /*
  *	Getsock opt support for the multicast routing system.
  */
- 
+
 int ip_mroute_getsockopt(struct sock *sk,int optname,char __user *optval,int __user *optlen)
 {
 	int olr;
 	int val;
 
-	if(optname!=MRT_VERSION && 
+	if(optname!=MRT_VERSION &&
 #ifdef CONFIG_IP_PIMSM
 	   optname!=MRT_PIM &&
 #endif
@@ -999,7 +996,7 @@
 	olr = min_t(unsigned int, olr, sizeof(int));
 	if (olr < 0)
 		return -EINVAL;
-		
+
 	if(put_user(olr,optlen))
 		return -EFAULT;
 	if(optname==MRT_VERSION)
@@ -1018,19 +1015,19 @@
 /*
  *	The IP multicast ioctl support routines.
  */
- 
+
 int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
 {
 	struct sioc_sg_req sr;
 	struct sioc_vif_req vr;
 	struct vif_device *vif;
 	struct mfc_cache *c;
-	
+
 	switch(cmd)
 	{
 		case SIOCGETVIFCNT:
 			if (copy_from_user(&vr,arg,sizeof(vr)))
-				return -EFAULT; 
+				return -EFAULT;
 			if(vr.vifi>=maxvif)
 				return -EINVAL;
 			read_lock(&mrt_lock);
@@ -1096,7 +1093,7 @@
  *	This avoids tunnel drivers and other mess and gives us the speed so
  *	important for multicast video.
  */
- 
+
 static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr)
 {
 	struct iphdr *iph = (struct iphdr *)skb_push(skb,sizeof(struct iphdr));
@@ -1194,7 +1191,7 @@
 	encap += LL_RESERVED_SPACE(dev) + rt->u.dst.header_len;
 
 	if (skb_cow(skb, encap)) {
- 		ip_rt_put(rt);
+		ip_rt_put(rt);
 		goto out_free;
 	}
 
@@ -1228,7 +1225,7 @@
 	 * not mrouter) cannot join to more than one interface - it will
 	 * result in receiving multiple packets.
 	 */
-	NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev, 
+	NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev,
 		ipmr_forward_finish);
 	return;
 
@@ -1289,7 +1286,7 @@
 		       large chunk of pimd to kernel. Ough... --ANK
 		     */
 		    (mroute_do_pim || cache->mfc_un.res.ttls[true_vifi] < 255) &&
-		    time_after(jiffies, 
+		    time_after(jiffies,
 			       cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
 			cache->mfc_un.res.last_assert = jiffies;
 			ipmr_cache_report(skb, true_vifi, IGMPMSG_WRONGVIF);
@@ -1426,14 +1423,14 @@
 	struct iphdr   *encap;
 	struct net_device  *reg_dev = NULL;
 
-	if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) 
+	if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
 		goto drop;
 
 	pim = (struct igmphdr*)skb->h.raw;
 
-        if (!mroute_do_pim ||
+	if (!mroute_do_pim ||
 	    skb->len < sizeof(*pim) + sizeof(*encap) ||
-	    pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) 
+	    pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER)
 		goto drop;
 
 	encap = (struct iphdr*)(skb->h.raw + sizeof(struct igmphdr));
@@ -1445,7 +1442,7 @@
 	 */
 	if (!MULTICAST(encap->daddr) ||
 	    encap->tot_len == 0 ||
-	    ntohs(encap->tot_len) + sizeof(*pim) > skb->len) 
+	    ntohs(encap->tot_len) + sizeof(*pim) > skb->len)
 		goto drop;
 
 	read_lock(&mrt_lock);
@@ -1455,7 +1452,7 @@
 		dev_hold(reg_dev);
 	read_unlock(&mrt_lock);
 
-	if (reg_dev == NULL) 
+	if (reg_dev == NULL)
 		goto drop;
 
 	skb->mac.raw = skb->nh.raw;
@@ -1486,13 +1483,13 @@
 	struct iphdr   *encap;
 	struct net_device  *reg_dev = NULL;
 
-	if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) 
+	if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
 		goto drop;
 
 	pim = (struct pimreghdr*)skb->h.raw;
-        if (pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) ||
+	if (pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) ||
 	    (pim->flags&PIM_NULL_REGISTER) ||
-	    (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 && 
+	    (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 &&
 	     csum_fold(skb_checksum(skb, 0, skb->len, 0))))
 		goto drop;
 
@@ -1500,7 +1497,7 @@
 	encap = (struct iphdr*)(skb->h.raw + sizeof(struct pimreghdr));
 	if (!MULTICAST(encap->daddr) ||
 	    encap->tot_len == 0 ||
-	    ntohs(encap->tot_len) + sizeof(*pim) > skb->len) 
+	    ntohs(encap->tot_len) + sizeof(*pim) > skb->len)
 		goto drop;
 
 	read_lock(&mrt_lock);
@@ -1510,7 +1507,7 @@
 		dev_hold(reg_dev);
 	read_unlock(&mrt_lock);
 
-	if (reg_dev == NULL) 
+	if (reg_dev == NULL)
 		goto drop;
 
 	skb->mac.raw = skb->nh.raw;
@@ -1616,7 +1613,7 @@
 	return err;
 }
 
-#ifdef CONFIG_PROC_FS	
+#ifdef CONFIG_PROC_FS
 /*
  *	The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif
  */
@@ -1630,7 +1627,7 @@
 	for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) {
 		if(!VIF_EXISTS(iter->ct))
 			continue;
-		if (pos-- == 0) 
+		if (pos-- == 0)
 			return &vif_table[iter->ct];
 	}
 	return NULL;
@@ -1639,7 +1636,7 @@
 static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	read_lock(&mrt_lock);
-	return *pos ? ipmr_vif_seq_idx(seq->private, *pos - 1) 
+	return *pos ? ipmr_vif_seq_idx(seq->private, *pos - 1)
 		: SEQ_START_TOKEN;
 }
 
@@ -1650,7 +1647,7 @@
 	++*pos;
 	if (v == SEQ_START_TOKEN)
 		return ipmr_vif_seq_idx(iter, 0);
-	
+
 	while (++iter->ct < maxvif) {
 		if(!VIF_EXISTS(iter->ct))
 			continue;
@@ -1667,7 +1664,7 @@
 static int ipmr_vif_seq_show(struct seq_file *seq, void *v)
 {
 	if (v == SEQ_START_TOKEN) {
-		seq_puts(seq, 
+		seq_puts(seq,
 			 "Interface      BytesIn  PktsIn  BytesOut PktsOut Flags Local    Remote\n");
 	} else {
 		const struct vif_device *vif = v;
@@ -1676,7 +1673,7 @@
 		seq_printf(seq,
 			   "%2Zd %-10s %8ld %7ld  %8ld %7ld %05X %08X %08X\n",
 			   vif - vif_table,
-			   name, vif->bytes_in, vif->pkt_in, 
+			   name, vif->bytes_in, vif->pkt_in,
 			   vif->bytes_out, vif->pkt_out,
 			   vif->flags, vif->local, vif->remote);
 	}
@@ -1695,7 +1692,7 @@
 	struct seq_file *seq;
 	int rc = -ENOMEM;
 	struct ipmr_vif_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
-       
+
 	if (!s)
 		goto out;
 
@@ -1714,7 +1711,7 @@
 
 }
 
-static struct file_operations ipmr_vif_fops = {
+static const struct file_operations ipmr_vif_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = ipmr_vif_open,
 	.read    = seq_read,
@@ -1734,15 +1731,15 @@
 
 	it->cache = mfc_cache_array;
 	read_lock(&mrt_lock);
-	for (it->ct = 0; it->ct < MFC_LINES; it->ct++) 
-		for(mfc = mfc_cache_array[it->ct]; mfc; mfc = mfc->next) 
-			if (pos-- == 0) 
+	for (it->ct = 0; it->ct < MFC_LINES; it->ct++)
+		for(mfc = mfc_cache_array[it->ct]; mfc; mfc = mfc->next)
+			if (pos-- == 0)
 				return mfc;
 	read_unlock(&mrt_lock);
 
 	it->cache = &mfc_unres_queue;
 	spin_lock_bh(&mfc_unres_lock);
-	for(mfc = mfc_unres_queue; mfc; mfc = mfc->next) 
+	for(mfc = mfc_unres_queue; mfc; mfc = mfc->next)
 		if (pos-- == 0)
 			return mfc;
 	spin_unlock_bh(&mfc_unres_lock);
@@ -1757,7 +1754,7 @@
 	struct ipmr_mfc_iter *it = seq->private;
 	it->cache = NULL;
 	it->ct = 0;
-	return *pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1) 
+	return *pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1)
 		: SEQ_START_TOKEN;
 }
 
@@ -1773,8 +1770,8 @@
 
 	if (mfc->next)
 		return mfc->next;
-	
-	if (it->cache == &mfc_unres_queue) 
+
+	if (it->cache == &mfc_unres_queue)
 		goto end_of_list;
 
 	BUG_ON(it->cache != mfc_cache_array);
@@ -1789,10 +1786,10 @@
 	read_unlock(&mrt_lock);
 	it->cache = &mfc_unres_queue;
 	it->ct = 0;
-		
+
 	spin_lock_bh(&mfc_unres_lock);
 	mfc = mfc_unres_queue;
-	if (mfc) 
+	if (mfc)
 		return mfc;
 
  end_of_list:
@@ -1817,12 +1814,12 @@
 	int n;
 
 	if (v == SEQ_START_TOKEN) {
-		seq_puts(seq, 
+		seq_puts(seq,
 		 "Group    Origin   Iif     Pkts    Bytes    Wrong Oifs\n");
 	} else {
 		const struct mfc_cache *mfc = v;
 		const struct ipmr_mfc_iter *it = seq->private;
-		
+
 		seq_printf(seq, "%08lX %08lX %-3d %8ld %8ld %8ld",
 			   (unsigned long) mfc->mfc_mcastgrp,
 			   (unsigned long) mfc->mfc_origin,
@@ -1832,12 +1829,12 @@
 			   mfc->mfc_un.res.wrong_if);
 
 		if (it->cache != &mfc_unres_queue) {
-			for(n = mfc->mfc_un.res.minvif; 
+			for(n = mfc->mfc_un.res.minvif;
 			    n < mfc->mfc_un.res.maxvif; n++ ) {
-				if(VIF_EXISTS(n) 
+				if(VIF_EXISTS(n)
 				   && mfc->mfc_un.res.ttls[n] < 255)
-				seq_printf(seq, 
-					   " %2d:%-3d", 
+				seq_printf(seq,
+					   " %2d:%-3d",
 					   n, mfc->mfc_un.res.ttls[n]);
 			}
 		}
@@ -1858,7 +1855,7 @@
 	struct seq_file *seq;
 	int rc = -ENOMEM;
 	struct ipmr_mfc_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
-       
+
 	if (!s)
 		goto out;
 
@@ -1876,14 +1873,14 @@
 
 }
 
-static struct file_operations ipmr_mfc_fops = {
+static const struct file_operations ipmr_mfc_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = ipmr_mfc_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
 	.release = seq_release_private,
 };
-#endif	
+#endif
 
 #ifdef CONFIG_IP_PIMSM_V2
 static struct net_protocol pim_protocol = {
@@ -1895,7 +1892,7 @@
 /*
  *	Setup for IP multicast routing
  */
- 
+
 void __init ip_mr_init(void)
 {
 	mrt_cachep = kmem_cache_create("ip_mrt_cache",
@@ -1905,8 +1902,8 @@
 	init_timer(&ipmr_expire_timer);
 	ipmr_expire_timer.function=ipmr_expire_process;
 	register_netdevice_notifier(&ip_mr_notifier);
-#ifdef CONFIG_PROC_FS	
+#ifdef CONFIG_PROC_FS
 	proc_net_fops_create("ip_mr_vif", 0, &ipmr_vif_fops);
 	proc_net_fops_create("ip_mr_cache", 0, &ipmr_mfc_fops);
-#endif	
+#endif
 }
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index 6c40899..22e104c 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -561,7 +561,7 @@
 	return seq_open(file, &ip_vs_app_seq_ops);
 }
 
-static struct file_operations ip_vs_app_fops = {
+static const struct file_operations ip_vs_app_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = ip_vs_app_open,
 	.read	 = seq_read,
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 8086787..7018f97 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -494,8 +494,8 @@
 	 * Checking the dest server status.
 	 */
 	if ((dest == NULL) ||
-	    !(dest->flags & IP_VS_DEST_F_AVAILABLE) || 
-	    (sysctl_ip_vs_expire_quiescent_template && 
+	    !(dest->flags & IP_VS_DEST_F_AVAILABLE) ||
+	    (sysctl_ip_vs_expire_quiescent_template &&
 	     (atomic_read(&dest->weight) == 0))) {
 		IP_VS_DBG(9, "check_template: dest not available for "
 			  "protocol %s s:%u.%u.%u.%u:%d v:%u.%u.%u.%u:%d "
@@ -603,13 +603,12 @@
 	struct ip_vs_conn *cp;
 	struct ip_vs_protocol *pp = ip_vs_proto_get(proto);
 
-	cp = kmem_cache_alloc(ip_vs_conn_cachep, GFP_ATOMIC);
+	cp = kmem_cache_zalloc(ip_vs_conn_cachep, GFP_ATOMIC);
 	if (cp == NULL) {
 		IP_VS_ERR_RL("ip_vs_conn_new: no memory available.\n");
 		return NULL;
 	}
 
-	memset(cp, 0, sizeof(*cp));
 	INIT_LIST_HEAD(&cp->c_list);
 	init_timer(&cp->timer);
 	cp->timer.data     = (unsigned long)cp;
@@ -667,7 +666,7 @@
 {
 	int idx;
 	struct ip_vs_conn *cp;
-	
+
 	for(idx = 0; idx < IP_VS_CONN_TAB_SIZE; idx++) {
 		ct_read_lock_bh(idx);
 		list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
@@ -695,7 +694,7 @@
 	int idx;
 
 	++*pos;
-	if (v == SEQ_START_TOKEN) 
+	if (v == SEQ_START_TOKEN)
 		return ip_vs_conn_array(seq, 0);
 
 	/* more on same hash chain? */
@@ -710,7 +709,7 @@
 		list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
 			seq->private = &ip_vs_conn_tab[idx];
 			return cp;
-		}	
+		}
 		ct_read_unlock_bh(idx);
 	}
 	seq->private = NULL;
@@ -758,7 +757,7 @@
 	return seq_open(file, &ip_vs_conn_seq_ops);
 }
 
-static struct file_operations ip_vs_conn_fops = {
+static const struct file_operations ip_vs_conn_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = ip_vs_conn_open,
 	.read    = seq_read,
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 3425752..24d7b66 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -813,14 +813,14 @@
 	skb->nh.iph->saddr = cp->vaddr;
 	ip_send_check(skb->nh.iph);
 
- 	/* For policy routing, packets originating from this
- 	 * machine itself may be routed differently to packets
- 	 * passing through.  We want this packet to be routed as
- 	 * if it came from this machine itself.  So re-compute
- 	 * the routing information.
- 	 */
- 	if (ip_route_me_harder(pskb, RTN_LOCAL) != 0)
- 		goto drop;
+	/* For policy routing, packets originating from this
+	 * machine itself may be routed differently to packets
+	 * passing through.  We want this packet to be routed as
+	 * if it came from this machine itself.  So re-compute
+	 * the routing information.
+	 */
+	if (ip_route_me_harder(pskb, RTN_LOCAL) != 0)
+		goto drop;
 	skb = *pskb;
 
 	IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");
@@ -847,7 +847,7 @@
  *	forward to the right destination host if relevant.
  *	Currently handles error types - unreachable, quench, ttl exceeded.
  */
-static int 
+static int
 ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
 {
 	struct sk_buff *skb = *pskb;
@@ -863,7 +863,7 @@
 	/* reassemble IP fragments */
 	if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
 		skb = ip_vs_gather_frags(skb,
-		                         hooknum == NF_IP_LOCAL_IN ?
+					 hooknum == NF_IP_LOCAL_IN ?
 					 IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD);
 		if (!skb)
 			return NF_STOLEN;
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 9b93338..b3050a6 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -1812,7 +1812,7 @@
 	goto out;
 }
 
-static struct file_operations ip_vs_info_fops = {
+static const struct file_operations ip_vs_info_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = ip_vs_info_open,
 	.read    = seq_read,
@@ -1859,7 +1859,7 @@
 	return single_open(file, ip_vs_stats_show, NULL);
 }
 
-static struct file_operations ip_vs_stats_fops = {
+static const struct file_operations ip_vs_stats_fops = {
 	.owner = THIS_MODULE,
 	.open = ip_vs_stats_seq_open,
 	.read = seq_read,
@@ -2359,7 +2359,7 @@
 	proc_net_fops_create("ip_vs", 0, &ip_vs_info_fops);
 	proc_net_fops_create("ip_vs_stats",0, &ip_vs_stats_fops);
 
-	sysctl_header = register_sysctl_table(vs_root_table, 0);
+	sysctl_header = register_sysctl_table(vs_root_table);
 
 	/* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */
 	for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++)  {
diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c
index 687c1de..847c47a 100644
--- a/net/ipv4/ipvs/ip_vs_ftp.c
+++ b/net/ipv4/ipvs/ip_vs_ftp.c
@@ -370,7 +370,7 @@
 		if (ret)
 			break;
 		IP_VS_INFO("%s: loaded support on port[%d] = %d\n",
-		 	   app->name, i, ports[i]);
+			   app->name, i, ports[i]);
 	}
 
 	if (ret)
diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c
index a4385a2..c801273 100644
--- a/net/ipv4/ipvs/ip_vs_lblc.c
+++ b/net/ipv4/ipvs/ip_vs_lblc.c
@@ -118,7 +118,7 @@
 		.procname	= "lblc_expiration",
 		.data		= &sysctl_ip_vs_lblc_expiration,
 		.maxlen		= sizeof(int),
-		.mode		= 0644, 
+		.mode		= 0644,
 		.proc_handler	= &proc_dointvec_jiffies,
 	},
 	{ .ctl_name = 0 }
@@ -128,7 +128,7 @@
 	{
 		.ctl_name	= NET_IPV4_VS,
 		.procname	= "vs",
-		.mode		= 0555, 
+		.mode		= 0555,
 		.child		= vs_vars_table
 	},
 	{ .ctl_name = 0 }
@@ -137,7 +137,7 @@
 static ctl_table ipvs_ipv4_table[] = {
 	{
 		.ctl_name	= NET_IPV4,
-		.procname	= "ipv4", 
+		.procname	= "ipv4",
 		.mode		= 0555,
 		.child		= vs_table
 	},
@@ -147,8 +147,8 @@
 static ctl_table lblc_root_table[] = {
 	{
 		.ctl_name	= CTL_NET,
-		.procname	= "net", 
-		.mode		= 0555, 
+		.procname	= "net",
+		.mode		= 0555,
 		.child		= ipvs_ipv4_table
 	},
 	{ .ctl_name = 0 }
@@ -288,7 +288,7 @@
 
 		write_lock(&tbl->lock);
 		list_for_each_entry_safe(en, nxt, &tbl->bucket[j], list) {
-			if (time_before(now, 
+			if (time_before(now,
 					en->lastuse + sysctl_ip_vs_lblc_expiration))
 				continue;
 
@@ -583,7 +583,7 @@
 static int __init ip_vs_lblc_init(void)
 {
 	INIT_LIST_HEAD(&ip_vs_lblc_scheduler.n_list);
-	sysctl_header = register_sysctl_table(lblc_root_table, 0);
+	sysctl_header = register_sysctl_table(lblc_root_table);
 	return register_ip_vs_scheduler(&ip_vs_lblc_scheduler);
 }
 
diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c
index fe1af5d..23f9b9e 100644
--- a/net/ipv4/ipvs/ip_vs_lblcr.c
+++ b/net/ipv4/ipvs/ip_vs_lblcr.c
@@ -307,7 +307,7 @@
 		.procname	= "lblcr_expiration",
 		.data		= &sysctl_ip_vs_lblcr_expiration,
 		.maxlen		= sizeof(int),
-		.mode		= 0644, 
+		.mode		= 0644,
 		.proc_handler	= &proc_dointvec_jiffies,
 	},
 	{ .ctl_name = 0 }
@@ -326,7 +326,7 @@
 static ctl_table ipvs_ipv4_table[] = {
 	{
 		.ctl_name	= NET_IPV4,
-		.procname	= "ipv4", 
+		.procname	= "ipv4",
 		.mode		= 0555,
 		.child		= vs_table
 	},
@@ -336,8 +336,8 @@
 static ctl_table lblcr_root_table[] = {
 	{
 		.ctl_name	= CTL_NET,
-		.procname	= "net", 
-		.mode		= 0555, 
+		.procname	= "net",
+		.mode		= 0555,
 		.child		= ipvs_ipv4_table
 	},
 	{ .ctl_name = 0 }
@@ -841,7 +841,7 @@
 static int __init ip_vs_lblcr_init(void)
 {
 	INIT_LIST_HEAD(&ip_vs_lblcr_scheduler.n_list);
-	sysctl_header = register_sysctl_table(lblcr_root_table, 0);
+	sysctl_header = register_sysctl_table(lblcr_root_table);
 #ifdef CONFIG_IP_VS_LBLCR_DEBUG
 	proc_net_create("ip_vs_lblcr", 0, ip_vs_lblcr_getinfo);
 #endif
diff --git a/net/ipv4/ipvs/ip_vs_rr.c b/net/ipv4/ipvs/ip_vs_rr.c
index b23bab2..433f8a9 100644
--- a/net/ipv4/ipvs/ip_vs_rr.c
+++ b/net/ipv4/ipvs/ip_vs_rr.c
@@ -68,7 +68,7 @@
 			q = q->next;
 			continue;
 		}
-		
+
 		dest = list_entry(q, struct ip_vs_dest, n_list);
 		if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
 		    atomic_read(&dest->weight) > 0)
diff --git a/net/ipv4/ipvs/ip_vs_sched.c b/net/ipv4/ipvs/ip_vs_sched.c
index 8bc42b7..1602304 100644
--- a/net/ipv4/ipvs/ip_vs_sched.c
+++ b/net/ipv4/ipvs/ip_vs_sched.c
@@ -20,7 +20,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <asm/string.h>
diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c
index 252e837..574c735 100644
--- a/net/ipv4/multipath_drr.c
+++ b/net/ipv4/multipath_drr.c
@@ -15,7 +15,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
@@ -134,7 +133,7 @@
 			     struct rtable *first, struct rtable **rp)
 {
 	struct rtable *nh, *result, *cur_min;
-	int min_usecount = -1; 
+	int min_usecount = -1;
 	int devidx = -1;
 	int cur_min_devidx = -1;
 
@@ -143,7 +142,7 @@
 	result = NULL;
 	cur_min = NULL;
 	for (nh = rcu_dereference(first); nh;
-	     nh = rcu_dereference(nh->u.rt_next)) {
+	     nh = rcu_dereference(nh->u.dst.rt_next)) {
 		if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
 		    multipath_comparekeys(&nh->fl, flp)) {
 			int nh_ifidx = nh->u.dst.dev->ifindex;
@@ -161,7 +160,7 @@
 			 */
 			devidx = __multipath_finddev(nh_ifidx);
 			if (devidx == -1) {
-				/* add the interface to the array 
+				/* add the interface to the array
 				 * SMP safe
 				 */
 				spin_lock_bh(&state_lock);
diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c
index b8c289f..57f481498 100644
--- a/net/ipv4/multipath_random.c
+++ b/net/ipv4/multipath_random.c
@@ -15,7 +15,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
@@ -74,7 +73,7 @@
 
 	/* count all candidate */
 	for (rt = rcu_dereference(first); rt;
-	     rt = rcu_dereference(rt->u.rt_next)) {
+	     rt = rcu_dereference(rt->u.dst.rt_next)) {
 		if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
 		    multipath_comparekeys(&rt->fl, flp))
 			++candidate_count;
@@ -90,7 +89,7 @@
 		/* find chosen candidate and adjust GC data for all candidates
 		 * to ensure they stay in cache
 		 */
-		for (rt = first; rt; rt = rt->u.rt_next) {
+		for (rt = first; rt; rt = rt->u.dst.rt_next) {
 			if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
 			    multipath_comparekeys(&rt->fl, flp)) {
 				rt->u.dst.lastuse = jiffies;
diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c
index bba5abe..0ad2252 100644
--- a/net/ipv4/multipath_rr.c
+++ b/net/ipv4/multipath_rr.c
@@ -15,7 +15,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
@@ -58,7 +57,7 @@
 	 */
 	result = NULL;
 	for (nh = rcu_dereference(first); nh;
- 	     nh = rcu_dereference(nh->u.rt_next)) {
+	     nh = rcu_dereference(nh->u.dst.rt_next)) {
 		if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
 		    multipath_comparekeys(&nh->fl, flp)) {
 			nh->u.dst.lastuse = jiffies;
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
index 92b0482..2bdbb92 100644
--- a/net/ipv4/multipath_wrandom.c
+++ b/net/ipv4/multipath_wrandom.c
@@ -15,7 +15,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
@@ -142,7 +141,7 @@
 	return weight;
 }
 
-static void wrandom_init_state(void) 
+static void wrandom_init_state(void)
 {
 	int i;
 
@@ -167,7 +166,7 @@
 
 	/* collect all candidates and identify their weights */
 	for (rt = rcu_dereference(first); rt;
-	     rt = rcu_dereference(rt->u.rt_next)) {
+	     rt = rcu_dereference(rt->u.dst.rt_next)) {
 		if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
 		    multipath_comparekeys(&rt->fl, flp)) {
 			struct multipath_candidate* mpc =
@@ -287,7 +286,7 @@
 
 static void __multipath_free_dst(struct rcu_head *head)
 {
-  	struct multipath_dest *dst = container_of(head,
+	struct multipath_dest *dst = container_of(head,
 						  struct multipath_dest,
 						  rcu);
 	kfree(dst);
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index c47ce707..6069a11 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -53,7 +53,7 @@
 		dst_release(&rt->u.dst);
 		dst_release(odst);
 	}
-	
+
 	if ((*pskb)->dst->error)
 		return -1;
 
@@ -70,7 +70,7 @@
 		struct sk_buff *nskb;
 
 		nskb = skb_realloc_headroom(*pskb, hh_len);
-		if (!nskb) 
+		if (!nskb)
 			return -1;
 		if ((*pskb)->sk)
 			skb_set_owner_w(nskb, (*pskb)->sk);
@@ -177,7 +177,7 @@
 			break;
 		if ((protocol == 0 && !csum_fold(skb->csum)) ||
 		    !csum_tcpudp_magic(iph->saddr, iph->daddr,
-			    	       skb->len - dataoff, protocol,
+				       skb->len - dataoff, protocol,
 				       skb->csum)) {
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			break;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 47bd3ad1..601808c 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -226,7 +226,7 @@
 
 config IP_NF_IPTABLES
 	tristate "IP tables support (required for filtering/masq/NAT)"
-	depends on NETFILTER_XTABLES
+	select NETFILTER_XTABLES
 	help
 	  iptables is a general, extensible packet identification framework.
 	  The packet filtering and full NAT (masquerading, port forwarding,
@@ -361,32 +361,6 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP_NF_TARGET_TCPMSS
-	tristate "TCPMSS target support"
-	depends on IP_NF_IPTABLES
-	---help---
-	  This option adds a `TCPMSS' target, which allows you to alter the
-	  MSS value of TCP SYN packets, to control the maximum size for that
-	  connection (usually limiting it to your outgoing interface's MTU
-	  minus 40).
-
-	  This is used to overcome criminally braindead ISPs or servers which
-	  block ICMP Fragmentation Needed packets.  The symptoms of this
-	  problem are that everything works fine from your Linux
-	  firewall/router, but machines behind it can never exchange large
-	  packets:
-	  	1) Web browsers connect, then hang with no data received.
-	  	2) Small mail works fine, but large emails hang.
-	  	3) ssh works fine, but scp hangs after initial handshaking.
-
-	  Workaround: activate this option and add a rule to your firewall
-	  configuration like:
-
-	  iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-	  		 -j TCPMSS --clamp-mss-to-pmtu
-
-	  To compile it as a module, choose M here.  If unsure, say N.
-
 # NAT + specific targets: ip_conntrack
 config IP_NF_NAT
 	tristate "Full NAT"
@@ -632,7 +606,9 @@
 config IP_NF_TARGET_CLUSTERIP
 	tristate "CLUSTERIP target support (EXPERIMENTAL)"
 	depends on IP_NF_MANGLE && EXPERIMENTAL
-	depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
+	depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
+	select IP_NF_CONNTRACK_MARK if IP_NF_CONNTRACK
+	select NF_CONNTRACK_MARK if NF_CONNTRACK_IPV4
 	help
 	  The CLUSTERIP target allows you to build load-balancing clusters of
 	  network servers without having a dedicated load-balancing
@@ -655,7 +631,7 @@
 # ARP tables
 config IP_NF_ARPTABLES
 	tristate "ARP tables support"
-	depends on NETFILTER_XTABLES
+	select NETFILTER_XTABLES
 	help
 	  arptables is a general, extensible packet identification framework.
 	  The ARP packet filtering and mangling (manipulation)subsystems
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 16d177b..6625ec6 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -103,7 +103,6 @@
 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
-obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
 obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
 
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 9aa2239..5170f5c 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -544,7 +544,7 @@
 	}
 
 	/* FIXME: underflows must be unconditional, standard verdicts
-           < 0 (not ARPT_RETURN). --RR */
+	   < 0 (not ARPT_RETURN). --RR */
 
 	/* Clear counters and comefrom */
 	e->counters = ((struct xt_counters) { 0, 0 });
@@ -869,8 +869,8 @@
 	/* 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)) 
+	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))
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index d12b1df..709db4d 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -67,7 +67,7 @@
 
 static int
 checkentry(const char *tablename, const void *e, const struct xt_target *target,
-           void *targinfo, unsigned int hook_mask)
+	   void *targinfo, unsigned int hook_mask)
 {
 	const struct arpt_mangle *mangle = targinfo;
 
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index ad246ba..4f561f5 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -9,7 +9,7 @@
  *
  *	Module load syntax:
  * 	insmod ip_conntrack_amanda.o [master_timeout=n]
- *	
+ *
  *	Where master_timeout is the timeout (in seconds) of the master
  *	connection (port 10080).  This defaults to 5 minutes but if
  *	your clients take longer than 5 minutes to do their work
@@ -84,7 +84,7 @@
 };
 
 static int help(struct sk_buff **pskb,
-                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
 	struct ts_state ts;
 	struct ip_conntrack_expect *exp;
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 8556a4f..07ba1dd 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -2,7 +2,7 @@
    but required by, the NAT layer; it can also be used by an iptables
    extension. */
 
-/* (C) 1999-2001 Paul `Rusty' Russell  
+/* (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
@@ -99,7 +99,7 @@
 void ip_ct_deliver_cached_events(const struct ip_conntrack *ct)
 {
 	struct ip_conntrack_ecache *ecache;
-	
+
 	local_bh_disable();
 	ecache = &__get_cpu_var(ip_conntrack_ecache);
 	if (ecache->ct == ct)
@@ -147,9 +147,9 @@
 			    unsigned int size, unsigned int rnd)
 {
 	return (jhash_3words((__force u32)tuple->src.ip,
-	                     ((__force u32)tuple->dst.ip ^ tuple->dst.protonum),
-	                     (tuple->src.u.all | (tuple->dst.u.all << 16)),
-	                     rnd) % size);
+			     ((__force u32)tuple->dst.ip ^ tuple->dst.protonum),
+			     (tuple->src.u.all | (tuple->dst.u.all << 16)),
+			     rnd) % size);
 }
 
 static u_int32_t
@@ -219,7 +219,7 @@
 __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
 {
 	struct ip_conntrack_expect *i;
-	
+
 	list_for_each_entry(i, &ip_conntrack_expect_list, list) {
 		if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
 			return i;
@@ -232,7 +232,7 @@
 ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
 {
 	struct ip_conntrack_expect *i;
-	
+
 	read_lock_bh(&ip_conntrack_lock);
 	i = __ip_conntrack_expect_find(tuple);
 	if (i)
@@ -303,6 +303,7 @@
 	struct ip_conntrack *ct = (struct ip_conntrack *)nfct;
 	struct ip_conntrack_protocol *proto;
 	struct ip_conntrack_helper *helper;
+	typeof(ip_conntrack_destroyed) destroyed;
 
 	DEBUGP("destroy_conntrack(%p)\n", ct);
 	IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
@@ -318,12 +319,16 @@
 	/* To make sure we don't get any weird locking issues here:
 	 * destroy_conntrack() MUST NOT be called with a write lock
 	 * to ip_conntrack_lock!!! -HW */
+	rcu_read_lock();
 	proto = __ip_conntrack_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
 	if (proto && proto->destroy)
 		proto->destroy(ct);
 
-	if (ip_conntrack_destroyed)
-		ip_conntrack_destroyed(ct);
+	destroyed = rcu_dereference(ip_conntrack_destroyed);
+	if (destroyed)
+		destroyed(ct);
+
+	rcu_read_unlock();
 
 	write_lock_bh(&ip_conntrack_lock);
 	/* Expectations will have been removed in clean_from_lists,
@@ -398,7 +403,7 @@
 
 static void __ip_conntrack_hash_insert(struct ip_conntrack *ct,
 					unsigned int hash,
-					unsigned int repl_hash) 
+					unsigned int repl_hash)
 {
 	ct->id = ++ip_conntrack_next_id;
 	list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list,
@@ -446,15 +451,15 @@
 	/* IP_NF_ASSERT(atomic_read(&ct->ct_general.use) == 1); */
 
 	/* No external references means noone else could have
-           confirmed us. */
+	   confirmed us. */
 	IP_NF_ASSERT(!is_confirmed(ct));
 	DEBUGP("Confirming conntrack %p\n", ct);
 
 	write_lock_bh(&ip_conntrack_lock);
 
 	/* See if there's one in the list already, including reverse:
-           NAT could have grabbed it without realizing, since we're
-           not in the hash.  If there is, we lost race. */
+	   NAT could have grabbed it without realizing, since we're
+	   not in the hash.  If there is, we lost race. */
 	list_for_each_entry(h, &ip_conntrack_hash[hash], list)
 		if (ip_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
 				      &h->tuple))
@@ -536,7 +541,7 @@
 	if (del_timer(&ct->timeout)) {
 		death_by_timeout((unsigned long)ct);
 		dropped = 1;
-		CONNTRACK_STAT_INC(early_drop);
+		CONNTRACK_STAT_INC_ATOMIC(early_drop);
 	}
 	ip_conntrack_put(ct);
 	return dropped;
@@ -595,14 +600,14 @@
 {
 	struct ip_conntrack_protocol *p;
 
-	preempt_disable();
+	rcu_read_lock();
 	p = __ip_conntrack_proto_find(protocol);
 	if (p) {
 		if (!try_module_get(p->me))
 			p = &ip_conntrack_generic_protocol;
 	}
-	preempt_enable();
-	
+	rcu_read_unlock();
+
 	return p;
 }
 
@@ -638,14 +643,13 @@
 		}
 	}
 
-	conntrack = kmem_cache_alloc(ip_conntrack_cachep, GFP_ATOMIC);
+	conntrack = kmem_cache_zalloc(ip_conntrack_cachep, GFP_ATOMIC);
 	if (!conntrack) {
 		DEBUGP("Can't allocate conntrack.\n");
 		atomic_dec(&ip_conntrack_count);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	memset(conntrack, 0, sizeof(*conntrack));
 	atomic_set(&conntrack->ct_general.use, 1);
 	conntrack->ct_general.destroy = destroy_conntrack;
 	conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
@@ -746,7 +750,7 @@
 
 	IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
 
-	if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, 
+	if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4,
 				&tuple,proto))
 		return NULL;
 
@@ -771,7 +775,7 @@
 		if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
 			DEBUGP("ip_conntrack_in: normal packet for %p\n",
 			       ct);
-		        *ctinfo = IP_CT_ESTABLISHED;
+			*ctinfo = IP_CT_ESTABLISHED;
 		} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
 			DEBUGP("ip_conntrack_in: related packet for %p\n",
 			       ct);
@@ -803,7 +807,7 @@
 
 	/* Previously seen (loopback or untracked)?  Ignore. */
 	if ((*pskb)->nfct) {
-		CONNTRACK_STAT_INC(ignore);
+		CONNTRACK_STAT_INC_ATOMIC(ignore);
 		return NF_ACCEPT;
 	}
 
@@ -822,7 +826,7 @@
 	if ((*pskb)->pkt_type == PACKET_BROADCAST) {
 		printk("Broadcast packet!\n");
 		return NF_ACCEPT;
-	} else if (((*pskb)->nh.iph->daddr & htonl(0x000000FF)) 
+	} else if (((*pskb)->nh.iph->daddr & htonl(0x000000FF))
 		   == htonl(0x000000FF)) {
 		printk("Should bcast: %u.%u.%u.%u->%u.%u.%u.%u (sk=%p, ptype=%u)\n",
 		       NIPQUAD((*pskb)->nh.iph->saddr),
@@ -831,27 +835,28 @@
 	}
 #endif
 
+	/* rcu_read_lock()ed by nf_hook_slow */
 	proto = __ip_conntrack_proto_find((*pskb)->nh.iph->protocol);
 
 	/* It may be an special packet, error, unclean...
 	 * inverse of the return code tells to the netfilter
 	 * core what to do with the packet. */
-	if (proto->error != NULL 
+	if (proto->error != NULL
 	    && (ret = proto->error(*pskb, &ctinfo, hooknum)) <= 0) {
-		CONNTRACK_STAT_INC(error);
-		CONNTRACK_STAT_INC(invalid);
+		CONNTRACK_STAT_INC_ATOMIC(error);
+		CONNTRACK_STAT_INC_ATOMIC(invalid);
 		return -ret;
 	}
 
 	if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) {
 		/* Not valid part of a connection */
-		CONNTRACK_STAT_INC(invalid);
+		CONNTRACK_STAT_INC_ATOMIC(invalid);
 		return NF_ACCEPT;
 	}
 
 	if (IS_ERR(ct)) {
 		/* Too stressed to deal. */
-		CONNTRACK_STAT_INC(drop);
+		CONNTRACK_STAT_INC_ATOMIC(drop);
 		return NF_DROP;
 	}
 
@@ -863,7 +868,7 @@
 		 * the netfilter core what to do*/
 		nf_conntrack_put((*pskb)->nfct);
 		(*pskb)->nfct = NULL;
-		CONNTRACK_STAT_INC(invalid);
+		CONNTRACK_STAT_INC_ATOMIC(invalid);
 		return -ret;
 	}
 
@@ -876,8 +881,15 @@
 int invert_tuplepr(struct ip_conntrack_tuple *inverse,
 		   const struct ip_conntrack_tuple *orig)
 {
-	return ip_ct_invert_tuple(inverse, orig, 
-				  __ip_conntrack_proto_find(orig->dst.protonum));
+	struct ip_conntrack_protocol *proto;
+	int ret;
+
+	rcu_read_lock();
+	proto = __ip_conntrack_proto_find(orig->dst.protonum);
+	ret = ip_ct_invert_tuple(inverse, orig, proto);
+	rcu_read_unlock();
+
+	return ret;
 }
 
 /* Would two expected things clash? */
@@ -885,7 +897,7 @@
 			       const struct ip_conntrack_expect *b)
 {
 	/* Part covered by intersection of masks must be unequal,
-           otherwise they clash */
+	   otherwise they clash */
 	struct ip_conntrack_tuple intersect_mask
 		= { { a->mask.src.ip & b->mask.src.ip,
 		      { a->mask.src.u.all & b->mask.src.u.all } },
@@ -923,7 +935,7 @@
 }
 
 /* We don't increase the master conntrack refcount for non-fulfilled
- * conntracks. During the conntrack destruction, the expectations are 
+ * conntracks. During the conntrack destruction, the expectations are
  * always killed before the conntrack itself */
 struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me)
 {
@@ -1012,7 +1024,7 @@
 	}
 
 	/* Will be over limit? */
-	if (expect->master->helper->max_expected && 
+	if (expect->master->helper->max_expected &&
 	    expect->master->expecting >= expect->master->helper->max_expected)
 		evict_oldest_expect(expect->master);
 
@@ -1021,7 +1033,7 @@
 	ret = 0;
 out:
 	write_unlock_bh(&ip_conntrack_lock);
- 	return ret;
+	return ret;
 }
 
 /* Alter reply tuple (maybe alter helper).  This is for NAT, and is
@@ -1069,7 +1081,7 @@
 			  const struct ip_conntrack_helper *me)
 {
 	if (tuplehash_to_ctrack(i)->helper == me) {
- 		ip_conntrack_event(IPCT_HELPER, tuplehash_to_ctrack(i));
+		ip_conntrack_event(IPCT_HELPER, tuplehash_to_ctrack(i));
 		tuplehash_to_ctrack(i)->helper = NULL;
 	}
 }
@@ -1105,8 +1117,8 @@
 }
 
 /* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */
-void __ip_ct_refresh_acct(struct ip_conntrack *ct, 
-		        enum ip_conntrack_info ctinfo,
+void __ip_ct_refresh_acct(struct ip_conntrack *ct,
+			enum ip_conntrack_info ctinfo,
 			const struct sk_buff *skb,
 			unsigned long extra_jiffies,
 			int do_acct)
@@ -1140,7 +1152,7 @@
 #ifdef CONFIG_IP_NF_CT_ACCT
 	if (do_acct) {
 		ct->counters[CTINFO2DIR(ctinfo)].packets++;
-		ct->counters[CTINFO2DIR(ctinfo)].bytes += 
+		ct->counters[CTINFO2DIR(ctinfo)].bytes +=
 						ntohs(skb->nh.iph->tot_len);
 		if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
 		    || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
@@ -1194,7 +1206,7 @@
 {
 	skb_orphan(skb);
 
-	local_bh_disable(); 
+	local_bh_disable();
 	skb = ip_defrag(skb, user);
 	local_bh_enable();
 
@@ -1211,7 +1223,7 @@
 
 	/* This ICMP is in reverse direction to the packet which caused it */
 	ct = ip_conntrack_get(skb, &ctinfo);
-	
+
 	if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
 		ctinfo = IP_CT_RELATED + IP_CT_IS_REPLY;
 	else
@@ -1279,7 +1291,7 @@
 	struct inet_sock *inet = inet_sk(sk);
 	struct ip_conntrack_tuple_hash *h;
 	struct ip_conntrack_tuple tuple;
-	
+
 	IP_CT_TUPLE_U_BLANK(&tuple);
 	tuple.src.ip = inet->rcv_saddr;
 	tuple.src.u.tcp.port = inet->sport;
@@ -1347,7 +1359,7 @@
 	if (vmalloced)
 		vfree(hash);
 	else
-		free_pages((unsigned long)hash, 
+		free_pages((unsigned long)hash,
 			   get_order(sizeof(struct list_head) * size));
 }
 
@@ -1355,11 +1367,11 @@
    supposed to kill the mall. */
 void ip_conntrack_cleanup(void)
 {
-	ip_ct_attach = NULL;
+	rcu_assign_pointer(ip_ct_attach, NULL);
 
 	/* This makes sure all current packets have passed through
-           netfilter framework.  Roll on, two-stage module
-           delete... */
+	   netfilter framework.  Roll on, two-stage module
+	   delete... */
 	synchronize_net();
 
 	ip_ct_event_cache_flush();
@@ -1385,11 +1397,11 @@
 	struct list_head *hash;
 	unsigned int i;
 
-	*vmalloced = 0; 
-	hash = (void*)__get_free_pages(GFP_KERNEL, 
+	*vmalloced = 0;
+	hash = (void*)__get_free_pages(GFP_KERNEL,
 				       get_order(sizeof(struct list_head)
 						 * size));
-	if (!hash) { 
+	if (!hash) {
 		*vmalloced = 1;
 		printk(KERN_WARNING"ip_conntrack: falling back to vmalloc.\n");
 		hash = vmalloc(sizeof(struct list_head) * size);
@@ -1422,7 +1434,7 @@
 	if (!hash)
 		return -ENOMEM;
 
-	/* We have to rehash for the new table anyway, so we also can 
+	/* We have to rehash for the new table anyway, so we also can
 	 * use a new random seed */
 	get_random_bytes(&rnd, 4);
 
@@ -1460,7 +1472,7 @@
 
 	/* Idea from tcp.c: use 1/16384 of memory.  On i386: 32MB
 	 * machine has 256 buckets.  >= 1GB machines have 8192 buckets. */
- 	if (!ip_conntrack_htable_size) {
+	if (!ip_conntrack_htable_size) {
 		ip_conntrack_htable_size
 			= (((num_physpages << PAGE_SHIFT) / 16384)
 			   / sizeof(struct list_head));
@@ -1490,8 +1502,8 @@
 	}
 
 	ip_conntrack_cachep = kmem_cache_create("ip_conntrack",
-	                                        sizeof(struct ip_conntrack), 0,
-	                                        0, NULL, NULL);
+						sizeof(struct ip_conntrack), 0,
+						0, NULL, NULL);
 	if (!ip_conntrack_cachep) {
 		printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
 		goto err_free_hash;
@@ -1508,15 +1520,15 @@
 	/* Don't NEED lock here, but good form anyway. */
 	write_lock_bh(&ip_conntrack_lock);
 	for (i = 0; i < MAX_IP_CT_PROTO; i++)
-		ip_ct_protos[i] = &ip_conntrack_generic_protocol;
+		rcu_assign_pointer(ip_ct_protos[i], &ip_conntrack_generic_protocol);
 	/* Sew in builtin protocols. */
-	ip_ct_protos[IPPROTO_TCP] = &ip_conntrack_protocol_tcp;
-	ip_ct_protos[IPPROTO_UDP] = &ip_conntrack_protocol_udp;
-	ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;
+	rcu_assign_pointer(ip_ct_protos[IPPROTO_TCP], &ip_conntrack_protocol_tcp);
+	rcu_assign_pointer(ip_ct_protos[IPPROTO_UDP], &ip_conntrack_protocol_udp);
+	rcu_assign_pointer(ip_ct_protos[IPPROTO_ICMP], &ip_conntrack_protocol_icmp);
 	write_unlock_bh(&ip_conntrack_lock);
 
 	/* For use by ipt_REJECT */
-	ip_ct_attach = ip_conntrack_attach;
+	rcu_assign_pointer(ip_ct_attach, ip_conntrack_attach);
 
 	/* Set up fake conntrack:
 	    - to never be deleted, not in any hashes */
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 0410c99..1faa68a 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -1,6 +1,6 @@
 /* FTP extension for IP connection tracking. */
 
-/* (C) 1999-2001 Paul `Rusty' Russell  
+/* (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
@@ -169,7 +169,7 @@
 	int length;
 
 	/* First character is delimiter, then "1" for IPv4, then
-           delimiter again. */
+	   delimiter again. */
 	if (dlen <= 3) return 0;
 	delim = data[0];
 	if (isdigit(delim) || delim < 33 || delim > 126
@@ -344,14 +344,14 @@
 	if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) {
 		/* Now if this ends in \n, update ftp info. */
 		DEBUGP("ip_conntrack_ftp_help: wrong seq pos %s(%u) or %s(%u)\n",
-		       ct_ftp_info->seq_aft_nl[0][dir] 
+		       ct_ftp_info->seq_aft_nl[0][dir]
 		       old_seq_aft_nl_set ? "":"(UNSET) ", old_seq_aft_nl);
 		ret = NF_ACCEPT;
 		goto out_update_nl;
 	}
 
 	/* Initialize IP array to expected address (it's not mentioned
-           in EPSV responses) */
+	   in EPSV responses) */
 	array[0] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 24) & 0xFF;
 	array[1] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 16) & 0xFF;
 	array[2] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 8) & 0xFF;
@@ -386,7 +386,7 @@
 
 	DEBUGP("conntrack_ftp: match `%s' (%u bytes at %u)\n",
 	       fb_ptr + matchoff, matchlen, ntohl(th->seq) + matchoff);
-			 
+
 	/* Allocate expectation which will be inserted */
 	exp = ip_conntrack_expect_alloc(ct);
 	if (exp == NULL) {
@@ -504,7 +504,7 @@
 			sprintf(tmpname, "ftp-%d", ports[i]);
 		ftp[i].name = tmpname;
 
-		DEBUGP("ip_ct_ftp: registering helper for port %d\n", 
+		DEBUGP("ip_ct_ftp: registering helper for port %d\n",
 				ports[i]);
 		ret = ip_conntrack_helper_register(&ftp[i]);
 
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index aabfe1c..53eb365 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -42,7 +42,7 @@
 static int callforward_filter = 1;
 module_param(callforward_filter, bool, 0600);
 MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
-		                     "if both endpoints are on different sides "
+				     "if both endpoints are on different sides "
 				     "(determined by routing information)");
 
 /* Hooks for NAT */
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index 4d19373..2b760c5 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -560,7 +560,7 @@
 	tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph);
 	BUG_ON(!tcph);
 	nexthdr_off += tcph->doff * 4;
- 	datalen = tcplen - tcph->doff * 4;
+	datalen = tcplen - tcph->doff * 4;
 
 	pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
 	if (!pptph) {
@@ -624,7 +624,7 @@
 	.max_expected = 2,
 	.timeout = 5 * 60,
 	.tuple = { .src = { .ip = 0,
-		 	    .u = { .tcp = { .port =
+			    .u = { .tcp = { .port =
 				    __constant_htons(PPTP_CONTROL_PORT) } }
 			  },
 		   .dst = { .ip = 0,
@@ -638,7 +638,7 @@
 		  .dst = { .ip = 0,
 			   .u = { .all = 0 },
 			   .protonum = 0xff
-		 	 }
+			 }
 		},
 	.help = conntrack_pptp_help,
 	.destroy = pptp_destroy_siblings,
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index 91832ec..053e591 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -1,6 +1,6 @@
 /* IRC extension for IP connection tracking, Version 1.21
  * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
- * based on RR's ip_conntrack_ftp.c	
+ * based on RR's ip_conntrack_ftp.c
  *
  * ip_conntrack_irc.c,v 1.21 2002/02/05 14:49:26 laforge Exp
  *
@@ -12,12 +12,12 @@
  *	Module load syntax:
  * 	insmod ip_conntrack_irc.o ports=port1,port2,...port<MAX_PORTS>
  *			    max_dcc_channels=n dcc_timeout=secs
- *	
+ *
  * 	please give the ports of all IRC servers You wish to connect to.
  *	If You don't specify ports, the default will be port 6667.
  *	With max_dcc_channels you can define the maximum number of not
  *	yet answered DCC channels per IRC session (default 8).
- *	With dcc_timeout you can specify how long the system waits for 
+ *	With dcc_timeout you can specify how long the system waits for
  *	an expected DCC channel (default 300 seconds).
  *
  */
@@ -63,7 +63,7 @@
 
 #if 0
 #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s:" format, \
-                                       __FILE__, __FUNCTION__ , ## args)
+				       __FILE__, __FUNCTION__ , ## args)
 #else
 #define DEBUGP(format, args...)
 #endif
@@ -71,7 +71,7 @@
 static int parse_dcc(char *data, char *data_end, u_int32_t *ip,
 		     u_int16_t *port, char **ad_beg_p, char **ad_end_p)
 /* tries to get the ip_addr and port out of a dcc command
-   return value: -1 on failure, 0 on success 
+   return value: -1 on failure, 0 on success
 	data		pointer to first byte of DCC command data
 	data_end	pointer to last byte of dcc command data
 	ip		returns parsed ip of dcc command
@@ -90,7 +90,7 @@
 
 	/* skip blanks between ip and port */
 	while (*data == ' ') {
-		if (data >= data_end) 
+		if (data >= data_end)
 			return -1;
 		data++;
 	}
@@ -171,7 +171,7 @@
 
 			DEBUGP("DCC %s detected\n", dccprotos[i]);
 			data += strlen(dccprotos[i]);
-			/* we have at least 
+			/* we have at least
 			 * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
 			 * data left (== 14/13 bytes) */
 			if (parse_dcc((char *)data, data_limit, &dcc_ip,
@@ -260,7 +260,7 @@
 	irc_buffer = kmalloc(65536, GFP_KERNEL);
 	if (!irc_buffer)
 		return -ENOMEM;
-	
+
 	/* If no port given, default to standard irc port */
 	if (ports_c == 0)
 		ports[ports_c++] = IRC_PORT;
@@ -297,7 +297,7 @@
 	return 0;
 }
 
-/* This function is intentionally _NOT_ defined as __exit, because 
+/* This function is intentionally _NOT_ defined as __exit, because
  * it is needed by the init function */
 static void ip_conntrack_irc_fini(void)
 {
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
index a1d6a89..cc6dd49 100644
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -42,7 +42,7 @@
 MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
 
 static int help(struct sk_buff **pskb,
-                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
 	struct ip_conntrack_expect *exp;
 	struct iphdr *iph = (*pskb)->nh.iph;
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 7f70b08..9228b76c 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -6,10 +6,10 @@
  * (C) 2003 by Patrick Mchardy <kaber@trash.net>
  * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
  *
- * I've reworked this stuff to use attributes instead of conntrack 
+ * I've reworked this stuff to use attributes instead of conntrack
  * structures. 5.44 am. I need more tea. --pablo 05/07/11.
  *
- * Initial connection tracking via netlink development funded and 
+ * Initial connection tracking via netlink development funded and
  * generally made possible by Network Robots, Inc. (www.networkrobots.com)
  *
  * Further development of this code funded by Astaro AG (http://www.astaro.com)
@@ -45,7 +45,7 @@
 static char __initdata version[] = "0.90";
 
 static inline int
-ctnetlink_dump_tuples_proto(struct sk_buff *skb, 
+ctnetlink_dump_tuples_proto(struct sk_buff *skb,
 			    const struct ip_conntrack_tuple *tuple,
 			    struct ip_conntrack_protocol *proto)
 {
@@ -56,7 +56,7 @@
 
 	if (likely(proto->tuple_to_nfattr))
 		ret = proto->tuple_to_nfattr(skb, tuple);
-	
+
 	NFA_NEST_END(skb, nest_parms);
 
 	return ret;
@@ -70,7 +70,7 @@
 			 const struct ip_conntrack_tuple *tuple)
 {
 	struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
-	
+
 	NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(__be32), &tuple->src.ip);
 	NFA_PUT(skb, CTA_IP_V4_DST, sizeof(__be32), &tuple->dst.ip);
 
@@ -121,7 +121,7 @@
 		timeout = 0;
 	else
 		timeout = htonl(timeout_l / HZ);
-	
+
 	NFA_PUT(skb, CTA_TIMEOUT, sizeof(timeout), &timeout);
 	return 0;
 
@@ -141,7 +141,7 @@
 		ip_conntrack_proto_put(proto);
 		return 0;
 	}
-	
+
 	nest_proto = NFA_NEST(skb, CTA_PROTOINFO);
 
 	ret = proto->to_nfattr(skb, nest_proto, ct);
@@ -164,7 +164,7 @@
 
 	if (!ct->helper)
 		return 0;
-		
+
 	nest_helper = NFA_NEST(skb, CTA_HELP);
 	NFA_PUT(skb, CTA_HELP_NAME, strlen(ct->helper->name), ct->helper->name);
 
@@ -236,7 +236,7 @@
 ctnetlink_dump_use(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
 	__be32 use = htonl(atomic_read(&ct->ct_general.use));
-	
+
 	NFA_PUT(skb, CTA_USE, sizeof(__be32), &use);
 	return 0;
 
@@ -248,7 +248,7 @@
 
 static int
 ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
-		    int event, int nowait, 
+		    int event, int nowait,
 		    const struct ip_conntrack *ct)
 {
 	struct nlmsghdr *nlh;
@@ -271,7 +271,7 @@
 	if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
 		goto nfattr_failure;
 	NFA_NEST_END(skb, nest_parms);
-	
+
 	nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
 	if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
 		goto nfattr_failure;
@@ -299,7 +299,7 @@
 
 #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
 static int ctnetlink_conntrack_event(struct notifier_block *this,
-                                     unsigned long events, void *ptr)
+				     unsigned long events, void *ptr)
 {
 	struct nlmsghdr *nlh;
 	struct nfgenmsg *nfmsg;
@@ -324,7 +324,7 @@
 	} else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
 		type = IPCTNL_MSG_CT_NEW;
 		group = NFNLGRP_CONNTRACK_UPDATE;
-	} else 
+	} else
 		return NOTIFY_DONE;
 
 	if (!nfnetlink_has_listeners(group))
@@ -349,7 +349,7 @@
 	if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
 		goto nfattr_failure;
 	NFA_NEST_END(skb, nest_parms);
-	
+
 	nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
 	if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
 		goto nfattr_failure;
@@ -368,16 +368,16 @@
 
 		if (events & IPCT_PROTOINFO
 		    && ctnetlink_dump_protoinfo(skb, ct) < 0)
-		    	goto nfattr_failure;
+			goto nfattr_failure;
 
 		if ((events & IPCT_HELPER || ct->helper)
 		    && ctnetlink_dump_helpinfo(skb, ct) < 0)
-		    	goto nfattr_failure;
+			goto nfattr_failure;
 
 #ifdef CONFIG_IP_NF_CONNTRACK_MARK
 		if ((events & IPCT_MARK || ct->mark)
 		    && ctnetlink_dump_mark(skb, ct) < 0)
-		    	goto nfattr_failure;
+			goto nfattr_failure;
 #endif
 
 		if (events & IPCT_COUNTER_FILLING &&
@@ -426,7 +426,7 @@
 				cb->args[1] = 0;
 			}
 			if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
-		                        	cb->nlh->nlmsg_seq,
+						cb->nlh->nlmsg_seq,
 						IPCTNL_MSG_CT_NEW,
 						1, ct) < 0) {
 				nf_conntrack_get(&ct->ct_general);
@@ -488,7 +488,7 @@
 };
 
 static inline int
-ctnetlink_parse_tuple_proto(struct nfattr *attr, 
+ctnetlink_parse_tuple_proto(struct nfattr *attr,
 			    struct ip_conntrack_tuple *tuple)
 {
 	struct nfattr *tb[CTA_PROTO_MAX];
@@ -508,9 +508,9 @@
 
 	if (likely(proto->nfattr_to_tuple))
 		ret = proto->nfattr_to_tuple(tb, tuple);
-	
+
 	ip_conntrack_proto_put(proto);
-	
+
 	return ret;
 }
 
@@ -595,7 +595,7 @@
 	int err;
 
 	memset(range, 0, sizeof(*range));
-	
+
 	nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
 
 	if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
@@ -647,7 +647,7 @@
 };
 
 static int
-ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, 
+ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
 			struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
 {
 	struct ip_conntrack_tuple_hash *h;
@@ -676,14 +676,14 @@
 		return -ENOENT;
 
 	ct = tuplehash_to_ctrack(h);
-	
+
 	if (cda[CTA_ID-1]) {
 		u_int32_t id = ntohl(*(__be32 *)NFA_DATA(cda[CTA_ID-1]));
 		if (ct->id != id) {
 			ip_conntrack_put(ct);
 			return -ENOENT;
 		}
-	}	
+	}
 	if (del_timer(&ct->timeout))
 		ct->timeout.function((unsigned long)ct);
 
@@ -693,7 +693,7 @@
 }
 
 static int
-ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, 
+ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 			struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
 {
 	struct ip_conntrack_tuple_hash *h;
@@ -714,8 +714,8 @@
 			return -ENOTSUPP;
 #endif
 		if ((*errp = netlink_dump_start(ctnl, skb, nlh,
-	      		                        ctnetlink_dump_table,
-	                                	ctnetlink_done)) != 0)
+						ctnetlink_dump_table,
+						ctnetlink_done)) != 0)
 			return -EINVAL;
 
 		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
@@ -751,7 +751,7 @@
 		return -ENOMEM;
 	}
 
-	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 
+	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
 				  IPCTNL_MSG_CT_NEW, 1, ct);
 	ip_conntrack_put(ct);
 	if (err <= 0)
@@ -779,12 +779,12 @@
 	if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
 		/* unchangeable */
 		return -EINVAL;
-	
+
 	if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
 		/* SEEN_REPLY bit can only be set */
 		return -EINVAL;
 
-	
+
 	if (d & IPS_ASSURED && !(status & IPS_ASSURED))
 		/* ASSURED bit can only be set */
 		return -EINVAL;
@@ -857,7 +857,7 @@
 			memset(&ct->help, 0, sizeof(ct->help));
 		}
 	}
-	
+
 	ct->helper = helper;
 
 	return 0;
@@ -867,7 +867,7 @@
 ctnetlink_change_timeout(struct ip_conntrack *ct, struct nfattr *cda[])
 {
 	u_int32_t timeout = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
-	
+
 	if (!del_timer(&ct->timeout))
 		return -ETIME;
 
@@ -891,7 +891,7 @@
 
 	if (proto->from_nfattr)
 		err = proto->from_nfattr(tb, ct);
-	ip_conntrack_proto_put(proto); 
+	ip_conntrack_proto_put(proto);
 
 	return err;
 }
@@ -934,7 +934,7 @@
 }
 
 static int
-ctnetlink_create_conntrack(struct nfattr *cda[], 
+ctnetlink_create_conntrack(struct nfattr *cda[],
 			   struct ip_conntrack_tuple *otuple,
 			   struct ip_conntrack_tuple *rtuple)
 {
@@ -943,7 +943,7 @@
 
 	ct = ip_conntrack_alloc(otuple, rtuple);
 	if (ct == NULL || IS_ERR(ct))
-		return -ENOMEM;	
+		return -ENOMEM;
 
 	if (!cda[CTA_TIMEOUT-1])
 		goto err;
@@ -979,13 +979,13 @@
 
 	return 0;
 
-err:	
+err:
 	ip_conntrack_free(ct);
 	return err;
 }
 
-static int 
-ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, 
+static int
+ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
 			struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
 {
 	struct ip_conntrack_tuple otuple, rtuple;
@@ -1039,9 +1039,9 @@
 	return err;
 }
 
-/*********************************************************************** 
- * EXPECT 
- ***********************************************************************/ 
+/***********************************************************************
+ * EXPECT
+ ***********************************************************************/
 
 static inline int
 ctnetlink_exp_dump_tuple(struct sk_buff *skb,
@@ -1049,7 +1049,7 @@
 			 enum ctattr_expect type)
 {
 	struct nfattr *nest_parms = NFA_NEST(skb, type);
-	
+
 	if (ctnetlink_dump_tuples(skb, tuple) < 0)
 		goto nfattr_failure;
 
@@ -1059,7 +1059,7 @@
 
 nfattr_failure:
 	return -1;
-}			
+}
 
 static inline int
 ctnetlink_exp_dump_mask(struct sk_buff *skb,
@@ -1090,7 +1090,7 @@
 
 static inline int
 ctnetlink_exp_dump_expect(struct sk_buff *skb,
-                          const struct ip_conntrack_expect *exp)
+			  const struct ip_conntrack_expect *exp)
 {
 	struct ip_conntrack *master = exp->master;
 	__be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ);
@@ -1104,20 +1104,20 @@
 				 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
 				 CTA_EXPECT_MASTER) < 0)
 		goto nfattr_failure;
-	
+
 	NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(__be32), &timeout);
 	NFA_PUT(skb, CTA_EXPECT_ID, sizeof(__be32), &id);
 
 	return 0;
-	
+
 nfattr_failure:
 	return -1;
 }
 
 static int
 ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
-		    int event, 
-		    int nowait, 
+		    int event,
+		    int nowait,
 		    const struct ip_conntrack_expect *exp)
 {
 	struct nlmsghdr *nlh;
@@ -1216,7 +1216,7 @@
 			goto out;
 		*id = exp->id;
 	}
-out:	
+out:
 	read_unlock_bh(&ip_conntrack_lock);
 
 	return skb->len;
@@ -1228,7 +1228,7 @@
 };
 
 static int
-ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, 
+ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
 		     struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
 {
 	struct ip_conntrack_tuple tuple;
@@ -1247,7 +1247,7 @@
 			return -EAFNOSUPPORT;
 
 		if ((*errp = netlink_dump_start(ctnl, skb, nlh,
-		    				ctnetlink_exp_dump_table,
+						ctnetlink_exp_dump_table,
 						ctnetlink_done)) != 0)
 			return -EINVAL;
 		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
@@ -1275,14 +1275,14 @@
 			ip_conntrack_expect_put(exp);
 			return -ENOENT;
 		}
-	}	
+	}
 
 	err = -ENOMEM;
 	skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
 	if (!skb2)
 		goto out;
 
-	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, 
+	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
 				      nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
 				      1, exp);
 	if (err <= 0)
@@ -1300,7 +1300,7 @@
 }
 
 static int
-ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, 
+ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
 		     struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
 {
 	struct ip_conntrack_expect *exp, *tmp;
@@ -1333,7 +1333,7 @@
 
 		/* after list removal, usage count == 1 */
 		ip_conntrack_unexpect_related(exp);
-		/* have to put what we 'get' above. 
+		/* have to put what we 'get' above.
 		 * after this line usage count == 0 */
 		ip_conntrack_expect_put(exp);
 	} else if (cda[CTA_EXPECT_HELP_NAME-1]) {
@@ -1348,7 +1348,7 @@
 		}
 		list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list,
 					 list) {
-			if (exp->master->helper == h 
+			if (exp->master->helper == h
 			    && del_timer(&exp->timeout)) {
 				ip_ct_unlink_expect(exp);
 				ip_conntrack_expect_put(exp);
@@ -1413,7 +1413,7 @@
 		err = -ENOMEM;
 		goto out;
 	}
-	
+
 	exp->expectfn = NULL;
 	exp->flags = 0;
 	exp->master = ct;
@@ -1423,7 +1423,7 @@
 	err = ip_conntrack_expect_related(exp);
 	ip_conntrack_expect_put(exp);
 
-out:	
+out:
 	ip_conntrack_put(tuplehash_to_ctrack(h));
 	return err;
 }
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
index 36f2b5e..88af82e 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
@@ -7,7 +7,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 295b6fa..ad70c81 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -7,7 +7,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/in.h>
@@ -94,9 +93,9 @@
 		       enum ip_conntrack_info ctinfo)
 {
 	/* Try to delete connection immediately after all replies:
-           won't actually vanish as we still have skb, and del_timer
-           means this will only run once even if count hits zero twice
-           (theoretically possible with SMP) */
+	   won't actually vanish as we still have skb, and del_timer
+	   means this will only run once even if count hits zero twice
+	   (theoretically possible with SMP) */
 	if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) {
 		if (atomic_dec_and_test(&ct->proto.icmp.count)
 		    && del_timer(&ct->timeout))
@@ -114,11 +113,11 @@
 static int icmp_new(struct ip_conntrack *conntrack,
 		    const struct sk_buff *skb)
 {
-	static const u_int8_t valid_new[] = { 
+	static const u_int8_t valid_new[] = {
 		[ICMP_ECHO] = 1,
 		[ICMP_TIMESTAMP] = 1,
 		[ICMP_INFO_REQUEST] = 1,
-		[ICMP_ADDRESS] = 1 
+		[ICMP_ADDRESS] = 1
 	};
 
 	if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
@@ -282,7 +281,7 @@
 	    || !tb[CTA_PROTO_ICMP_ID-1])
 		return -EINVAL;
 
-	tuple->dst.u.icmp.type = 
+	tuple->dst.u.icmp.type =
 			*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
 	tuple->dst.u.icmp.code =
 			*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index 2443322..e694299 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -1,9 +1,9 @@
 /*
  * Connection tracking protocol helper module for SCTP.
- * 
- * SCTP is defined in RFC 2960. References to various sections in this code 
+ *
+ * SCTP is defined in RFC 2960. References to various sections in this code
  * are to this RFC.
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -14,7 +14,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/netfilter.h>
@@ -38,7 +37,7 @@
 static DEFINE_RWLOCK(sctp_lock);
 
 /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
-   closely.  They're more complex. --RR 
+   closely.  They're more complex. --RR
 
    And so for me for SCTP :D -Kiran */
 
@@ -87,32 +86,32 @@
 #define	sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
 #define	sIV SCTP_CONNTRACK_MAX
 
-/* 
+/*
 	These are the descriptions of the states:
 
-NOTE: These state names are tantalizingly similar to the states of an 
+NOTE: These state names are tantalizingly similar to the states of an
 SCTP endpoint. But the interpretation of the states is a little different,
-considering that these are the states of the connection and not of an end 
+considering that these are the states of the connection and not of an end
 point. Please note the subtleties. -Kiran
 
 NONE              - Nothing so far.
-COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also 
-                    an INIT_ACK chunk in the reply direction.
+COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also
+		    an INIT_ACK chunk in the reply direction.
 COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.
 ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.
 SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.
 SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.
 SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
-                    to that of the SHUTDOWN chunk.
-CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 
-                    the SHUTDOWN chunk. Connection is closed.
+		    to that of the SHUTDOWN chunk.
+CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
+		    the SHUTDOWN chunk. Connection is closed.
 */
 
 /* TODO
- - I have assumed that the first INIT is in the original direction. 
+ - I have assumed that the first INIT is in the original direction.
  This messes things when an INIT comes in the reply direction in CLOSED
  state.
- - Check the error type in the reply dir before transitioning from 
+ - Check the error type in the reply dir before transitioning from
 cookie echoed to closed.
  - Sec 5.2.4 of RFC 2960
  - Multi Homing support.
@@ -229,7 +228,7 @@
 	for_each_sctp_chunk (skb, sch, _sch, offset, count) {
 		DEBUGP("Chunk Num: %d  Type: %d\n", count, sch->type);
 
-		if (sch->type == SCTP_CID_INIT 
+		if (sch->type == SCTP_CID_INIT
 			|| sch->type == SCTP_CID_INIT_ACK
 			|| sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
 			flag = 1;
@@ -269,42 +268,42 @@
 	DEBUGP("Chunk type: %d\n", chunk_type);
 
 	switch (chunk_type) {
-		case SCTP_CID_INIT: 
+		case SCTP_CID_INIT:
 			DEBUGP("SCTP_CID_INIT\n");
 			i = 0; break;
-		case SCTP_CID_INIT_ACK: 
+		case SCTP_CID_INIT_ACK:
 			DEBUGP("SCTP_CID_INIT_ACK\n");
 			i = 1; break;
-		case SCTP_CID_ABORT: 
+		case SCTP_CID_ABORT:
 			DEBUGP("SCTP_CID_ABORT\n");
 			i = 2; break;
-		case SCTP_CID_SHUTDOWN: 
+		case SCTP_CID_SHUTDOWN:
 			DEBUGP("SCTP_CID_SHUTDOWN\n");
 			i = 3; break;
-		case SCTP_CID_SHUTDOWN_ACK: 
+		case SCTP_CID_SHUTDOWN_ACK:
 			DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
 			i = 4; break;
-		case SCTP_CID_ERROR: 
+		case SCTP_CID_ERROR:
 			DEBUGP("SCTP_CID_ERROR\n");
 			i = 5; break;
-		case SCTP_CID_COOKIE_ECHO: 
+		case SCTP_CID_COOKIE_ECHO:
 			DEBUGP("SCTP_CID_COOKIE_ECHO\n");
 			i = 6; break;
-		case SCTP_CID_COOKIE_ACK: 
+		case SCTP_CID_COOKIE_ACK:
 			DEBUGP("SCTP_CID_COOKIE_ACK\n");
 			i = 7; break;
-		case SCTP_CID_SHUTDOWN_COMPLETE: 
+		case SCTP_CID_SHUTDOWN_COMPLETE:
 			DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
 			i = 8; break;
 		default:
 			/* Other chunks like DATA, SACK, HEARTBEAT and
 			its ACK do not cause a change in state */
-			DEBUGP("Unknown chunk type, Will stay in %s\n", 
+			DEBUGP("Unknown chunk type, Will stay in %s\n",
 						sctp_conntrack_names[cur_state]);
 			return cur_state;
 	}
 
-	DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 
+	DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n",
 			dir, sctp_conntrack_names[cur_state], chunk_type,
 			sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
 
@@ -367,7 +366,7 @@
 			/* Sec 8.5.1 (C) */
 			if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
 				&& !(sh->vtag == conntrack->proto.sctp.vtag
-							[1 - CTINFO2DIR(ctinfo)] 
+							[1 - CTINFO2DIR(ctinfo)]
 					&& (sch->flags & 1))) {
 				write_unlock_bh(&sctp_lock);
 				return -1;
@@ -392,17 +391,17 @@
 		}
 
 		/* If it is an INIT or an INIT ACK note down the vtag */
-		if (sch->type == SCTP_CID_INIT 
+		if (sch->type == SCTP_CID_INIT
 			|| sch->type == SCTP_CID_INIT_ACK) {
 			sctp_inithdr_t _inithdr, *ih;
 
 			ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
-			                        sizeof(_inithdr), &_inithdr);
+						sizeof(_inithdr), &_inithdr);
 			if (ih == NULL) {
 					write_unlock_bh(&sctp_lock);
 					return -1;
 			}
-			DEBUGP("Setting vtag %x for dir %d\n", 
+			DEBUGP("Setting vtag %x for dir %d\n",
 					ih->init_tag, !CTINFO2DIR(ctinfo));
 			conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag;
 		}
@@ -427,7 +426,7 @@
 }
 
 /* Called when a new connection for this protocol found. */
-static int sctp_new(struct ip_conntrack *conntrack, 
+static int sctp_new(struct ip_conntrack *conntrack,
 		    const struct sk_buff *skb)
 {
 	enum sctp_conntrack newconntrack;
@@ -457,7 +456,7 @@
 	newconntrack = SCTP_CONNTRACK_MAX;
 	for_each_sctp_chunk (skb, sch, _sch, offset, count) {
 		/* Don't need lock here: this conntrack not in circulation yet */
-		newconntrack = new_state (IP_CT_DIR_ORIGINAL, 
+		newconntrack = new_state (IP_CT_DIR_ORIGINAL,
 						SCTP_CONNTRACK_NONE, sch->type);
 
 		/* Invalid: delete conntrack */
@@ -472,14 +471,14 @@
 				sctp_inithdr_t _inithdr, *ih;
 
 				ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
-				                        sizeof(_inithdr), &_inithdr);
+							sizeof(_inithdr), &_inithdr);
 				if (ih == NULL)
 					return 0;
 
-				DEBUGP("Setting vtag %x for new conn\n", 
+				DEBUGP("Setting vtag %x for new conn\n",
 					ih->init_tag);
 
-				conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = 
+				conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
 								ih->init_tag;
 			} else {
 				/* Sec 8.5.1 (A) */
@@ -489,7 +488,7 @@
 		/* If it is a shutdown ack OOTB packet, we expect a return
 		   shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
 		else {
-			DEBUGP("Setting vtag %x for new conn OOTB\n", 
+			DEBUGP("Setting vtag %x for new conn OOTB\n",
 				sh->vtag);
 			conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
 		}
@@ -500,16 +499,16 @@
 	return 1;
 }
 
-static struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { 
-	.proto 		 = IPPROTO_SCTP, 
+static struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
+	.proto 		 = IPPROTO_SCTP,
 	.name 		 = "sctp",
-	.pkt_to_tuple 	 = sctp_pkt_to_tuple, 
-	.invert_tuple 	 = sctp_invert_tuple, 
-	.print_tuple 	 = sctp_print_tuple, 
+	.pkt_to_tuple 	 = sctp_pkt_to_tuple,
+	.invert_tuple 	 = sctp_invert_tuple,
+	.print_tuple 	 = sctp_print_tuple,
 	.print_conntrack = sctp_print_conntrack,
-	.packet 	 = sctp_packet, 
-	.new 		 = sctp_new, 
-	.destroy 	 = NULL, 
+	.packet 	 = sctp_packet,
+	.new 		 = sctp_new,
+	.destroy 	 = NULL,
 	.me 		 = THIS_MODULE,
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
     defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
@@ -603,7 +602,7 @@
 	{
 		.ctl_name	= CTL_NET,
 		.procname	= "net",
-		.mode		= 0555, 
+		.mode		= 0555,
 		.child		= ip_ct_ipv4_table,
 	},
 	{ .ctl_name = 0 }
@@ -623,7 +622,7 @@
 	}
 
 #ifdef CONFIG_SYSCTL
-	ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
+	ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table);
 	if (ip_ct_sysctl_header == NULL) {
 		ret = -ENOMEM;
 		printk("ip_conntrack_proto_sctp: can't register to sysctl.\n");
@@ -638,7 +637,7 @@
 	ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
 #endif
  out:
-	DEBUGP("SCTP conntrack module loading %s\n", 
+	DEBUGP("SCTP conntrack module loading %s\n",
 					ret ? "failed": "succeeded");
 	return ret;
 }
@@ -647,7 +646,7 @@
 {
 	ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
 #ifdef CONFIG_SYSCTL
- 	unregister_sysctl_table(ip_ct_sysctl_header);
+	unregister_sysctl_table(ip_ct_sysctl_header);
 #endif
 	DEBUGP("SCTP conntrack module unloaded\n");
 }
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 06e4e8a..170d625 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -20,7 +20,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/module.h>
@@ -45,20 +44,17 @@
 /* Protects conntrack->proto.tcp */
 static DEFINE_RWLOCK(tcp_lock);
 
-/* "Be conservative in what you do, 
-    be liberal in what you accept from others." 
+/* "Be conservative in what you do,
+    be liberal in what you accept from others."
     If it's non-zero, we mark only out of window RST segments as INVALID. */
 int ip_ct_tcp_be_liberal __read_mostly = 0;
 
-/* When connection is picked up from the middle, how many packets are required
-   to pass in each direction when we assume we are in sync - if any side uses
-   window scaling, we lost the game. 
-   If it is set to zero, we disable picking up already established 
+/* If it is set to zero, we disable picking up already established
    connections. */
-int ip_ct_tcp_loose __read_mostly = 3;
+int ip_ct_tcp_loose __read_mostly = 1;
 
-/* Max number of the retransmitted packets without receiving an (acceptable) 
-   ACK from the destination. If this number is reached, a shorter timer 
+/* Max number of the retransmitted packets without receiving an (acceptable)
+   ACK from the destination. If this number is reached, a shorter timer
    will be started. */
 int ip_ct_tcp_max_retrans __read_mostly = 3;
 
@@ -77,7 +73,7 @@
 	"CLOSE",
 	"LISTEN"
 };
-  
+
 #define SECS * HZ
 #define MINS * 60 SECS
 #define HOURS * 60 MINS
@@ -93,10 +89,10 @@
 unsigned int ip_ct_tcp_timeout_close __read_mostly =        10 SECS;
 
 /* RFC1122 says the R2 limit should be at least 100 seconds.
-   Linux uses 15 packets as limit, which corresponds 
+   Linux uses 15 packets as limit, which corresponds
    to ~13-30min depending on RTO. */
 unsigned int ip_ct_tcp_timeout_max_retrans __read_mostly =   5 MINS;
- 
+
 static const unsigned int * tcp_timeouts[]
 = { NULL,                              /*      TCP_CONNTRACK_NONE */
     &ip_ct_tcp_timeout_syn_sent,       /*      TCP_CONNTRACK_SYN_SENT, */
@@ -109,7 +105,7 @@
     &ip_ct_tcp_timeout_close,          /*      TCP_CONNTRACK_CLOSE,    */
     NULL,                              /*      TCP_CONNTRACK_LISTEN */
  };
- 
+
 #define sNO TCP_CONNTRACK_NONE
 #define sSS TCP_CONNTRACK_SYN_SENT
 #define sSR TCP_CONNTRACK_SYN_RECV
@@ -132,13 +128,13 @@
 	TCP_RST_SET,
 	TCP_NONE_SET,
 };
-  
+
 /*
  * The TCP state transition table needs a few words...
  *
  * We are the man in the middle. All the packets go through us
  * but might get lost in transit to the destination.
- * It is assumed that the destinations can't receive segments 
+ * It is assumed that the destinations can't receive segments
  * we haven't seen.
  *
  * The checked segment is in window, but our windows are *not*
@@ -148,11 +144,11 @@
  * The meaning of the states are:
  *
  * NONE:	initial state
- * SYN_SENT:	SYN-only packet seen 
+ * SYN_SENT:	SYN-only packet seen
  * SYN_RECV:	SYN-ACK packet seen
  * ESTABLISHED:	ACK packet seen
  * FIN_WAIT:	FIN packet seen
- * CLOSE_WAIT:	ACK seen (after FIN) 
+ * CLOSE_WAIT:	ACK seen (after FIN)
  * LAST_ACK:	FIN seen (after FIN)
  * TIME_WAIT:	last ACK seen
  * CLOSE:	closed connection
@@ -160,8 +156,8 @@
  * LISTEN state is not used.
  *
  * Packets marked as IGNORED (sIG):
- *	if they may be either invalid or valid 
- *	and the receiver may send back a connection 
+ *	if they may be either invalid or valid
+ *	and the receiver may send back a connection
  *	closing RST or a SYN/ACK.
  *
  * Packets marked as INVALID (sIV):
@@ -178,7 +174,7 @@
  *	sSS -> sSS	Retransmitted SYN
  *	sSR -> sIG	Late retransmitted SYN?
  *	sES -> sIG	Error: SYNs in window outside the SYN_SENT state
- *			are errors. Receiver will reply with RST 
+ *			are errors. Receiver will reply with RST
  *			and close the connection.
  *			Or we are not in sync and hold a dead connection.
  *	sFW -> sIG
@@ -191,10 +187,10 @@
 /*synack*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },
 /*
  * A SYN/ACK from the client is always invalid:
- *	- either it tries to set up a simultaneous open, which is 
+ *	- either it tries to set up a simultaneous open, which is
  *	  not supported;
  *	- or the firewall has just been inserted between the two hosts
- *	  during the session set-up. The SYN will be retransmitted 
+ *	  during the session set-up. The SYN will be retransmitted
  *	  by the true client (or it'll time out).
  */
 /* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
@@ -204,9 +200,9 @@
  *	sSS -> sIV	Client migth not send FIN in this state:
  *			we enforce waiting for a SYN/ACK reply first.
  *	sSR -> sFW	Close started.
- *	sES -> sFW	
+ *	sES -> sFW
  *	sFW -> sLA	FIN seen in both directions, waiting for
- *			the last ACK. 
+ *			the last ACK.
  *			Migth be a retransmitted FIN as well...
  *	sCW -> sLA
  *	sLA -> sLA	Retransmitted FIN. Remain in the same state.
@@ -284,7 +280,7 @@
 /* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
 /*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },
 /*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
-  	}
+	}
 };
 
 static int tcp_pkt_to_tuple(const struct sk_buff *skb,
@@ -340,7 +336,7 @@
 			 const struct ip_conntrack *ct)
 {
 	struct nfattr *nest_parms;
-	
+
 	read_lock_bh(&tcp_lock);
 	nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
 	NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
@@ -370,7 +366,7 @@
 	if (!attr)
 		return 0;
 
-        nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);
+	nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);
 
 	if (nfattr_bad_size(tb, CTA_PROTOINFO_TCP_MAX, cta_min_tcp))
 		return -EINVAL;
@@ -379,7 +375,7 @@
 		return -EINVAL;
 
 	write_lock_bh(&tcp_lock);
-	ct->proto.tcp.state = 
+	ct->proto.tcp.state =
 		*(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
 	write_unlock_bh(&tcp_lock);
 
@@ -398,30 +394,30 @@
 
 /* TCP connection tracking based on 'Real Stateful TCP Packet Filtering
    in IP Filter' by Guido van Rooij.
-   
+
    http://www.nluug.nl/events/sane2000/papers.html
    http://www.iae.nl/users/guido/papers/tcp_filtering.ps.gz
-   
+
    The boundaries and the conditions are changed according to RFC793:
    the packet must intersect the window (i.e. segments may be
    after the right or before the left edge) and thus receivers may ACK
    segments after the right edge of the window.
 
-   	td_maxend = max(sack + max(win,1)) seen in reply packets
+	td_maxend = max(sack + max(win,1)) seen in reply packets
 	td_maxwin = max(max(win, 1)) + (sack - ack) seen in sent packets
 	td_maxwin += seq + len - sender.td_maxend
 			if seq + len > sender.td_maxend
 	td_end    = max(seq + len) seen in sent packets
-   
+
    I.   Upper bound for valid data:	seq <= sender.td_maxend
    II.  Lower bound for valid data:	seq + len >= sender.td_end - receiver.td_maxwin
    III.	Upper bound for valid ack:      sack <= receiver.td_end
    IV.	Lower bound for valid ack:	ack >= receiver.td_end - MAXACKWINDOW
-   	
+
    where sack is the highest right edge of sack block found in the packet.
-   	
-   The upper bound limit for a valid ack is not ignored - 
-   we doesn't have to deal with fragments. 
+
+   The upper bound limit for a valid ack is not ignored -
+   we doesn't have to deal with fragments.
 */
 
 static inline __u32 segment_seq_plus_len(__u32 seq,
@@ -432,25 +428,25 @@
 	return (seq + len - (iph->ihl + tcph->doff)*4
 		+ (tcph->syn ? 1 : 0) + (tcph->fin ? 1 : 0));
 }
-  
+
 /* Fixme: what about big packets? */
 #define MAXACKWINCONST			66000
 #define MAXACKWINDOW(sender)						\
 	((sender)->td_maxwin > MAXACKWINCONST ? (sender)->td_maxwin	\
 					      : MAXACKWINCONST)
-  
+
 /*
  * Simplified tcp_parse_options routine from tcp_input.c
  */
 static void tcp_options(const struct sk_buff *skb,
 			struct iphdr *iph,
-			struct tcphdr *tcph, 
+			struct tcphdr *tcph,
 			struct ip_ct_tcp_state *state)
 {
 	unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
 	unsigned char *ptr;
 	int length = (tcph->doff*4) - sizeof(struct tcphdr);
-	
+
 	if (!length)
 		return;
 
@@ -459,13 +455,13 @@
 				 length, buff);
 	BUG_ON(ptr == NULL);
 
-	state->td_scale = 
+	state->td_scale =
 	state->flags = 0;
-	
+
 	while (length > 0) {
 		int opcode=*ptr++;
 		int opsize;
-		
+
 		switch (opcode) {
 		case TCPOPT_EOL:
 			return;
@@ -479,13 +475,13 @@
 			if (opsize > length)
 				break;	/* don't parse partial options */
 
-			if (opcode == TCPOPT_SACK_PERM 
+			if (opcode == TCPOPT_SACK_PERM
 			    && opsize == TCPOLEN_SACK_PERM)
 				state->flags |= IP_CT_TCP_FLAG_SACK_PERM;
 			else if (opcode == TCPOPT_WINDOW
 				 && opsize == TCPOLEN_WINDOW) {
 				state->td_scale = *(u_int8_t *)ptr;
-				
+
 				if (state->td_scale > 14) {
 					/* See RFC1323 */
 					state->td_scale = 14;
@@ -520,16 +516,16 @@
 	/* Fast path for timestamp-only option */
 	if (length == TCPOLEN_TSTAMP_ALIGNED*4
 	    && *(__be32 *)ptr ==
-	        __constant_htonl((TCPOPT_NOP << 24)
-	        		 | (TCPOPT_NOP << 16)
-	        		 | (TCPOPT_TIMESTAMP << 8)
-	        		 | TCPOLEN_TIMESTAMP))
+		__constant_htonl((TCPOPT_NOP << 24)
+				 | (TCPOPT_NOP << 16)
+				 | (TCPOPT_TIMESTAMP << 8)
+				 | TCPOLEN_TIMESTAMP))
 		return;
-		
+
 	while (length > 0) {
 		int opcode=*ptr++;
 		int opsize, i;
-		
+
 		switch (opcode) {
 		case TCPOPT_EOL:
 			return;
@@ -543,16 +539,16 @@
 			if (opsize > length)
 				break;	/* don't parse partial options */
 
-			if (opcode == TCPOPT_SACK 
-			    && opsize >= (TCPOLEN_SACK_BASE 
-			    		  + TCPOLEN_SACK_PERBLOCK)
-			    && !((opsize - TCPOLEN_SACK_BASE) 
-			    	 % TCPOLEN_SACK_PERBLOCK)) {
-			    	for (i = 0;
-			    	     i < (opsize - TCPOLEN_SACK_BASE);
-			    	     i += TCPOLEN_SACK_PERBLOCK) {
+			if (opcode == TCPOPT_SACK
+			    && opsize >= (TCPOLEN_SACK_BASE
+					  + TCPOLEN_SACK_PERBLOCK)
+			    && !((opsize - TCPOLEN_SACK_BASE)
+				 % TCPOLEN_SACK_PERBLOCK)) {
+				for (i = 0;
+				     i < (opsize - TCPOLEN_SACK_BASE);
+				     i += TCPOLEN_SACK_PERBLOCK) {
 					tmp = ntohl(*((__be32 *)(ptr+i)+1));
-					
+
 					if (after(tmp, *sack))
 						*sack = tmp;
 				}
@@ -564,18 +560,18 @@
 	}
 }
 
-static int tcp_in_window(struct ip_ct_tcp *state, 
-                         enum ip_conntrack_dir dir,
-                         unsigned int index,
-                         const struct sk_buff *skb,
-                         struct iphdr *iph,
-                         struct tcphdr *tcph)
+static int tcp_in_window(struct ip_ct_tcp *state,
+			 enum ip_conntrack_dir dir,
+			 unsigned int index,
+			 const struct sk_buff *skb,
+			 struct iphdr *iph,
+			 struct tcphdr *tcph)
 {
 	struct ip_ct_tcp_state *sender = &state->seen[dir];
 	struct ip_ct_tcp_state *receiver = &state->seen[!dir];
 	__u32 seq, ack, sack, end, win, swin;
 	int res;
-	
+
 	/*
 	 * Get the required data from the packet.
 	 */
@@ -583,23 +579,23 @@
 	ack = sack = ntohl(tcph->ack_seq);
 	win = ntohs(tcph->window);
 	end = segment_seq_plus_len(seq, skb->len, iph, tcph);
-	
+
 	if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
 		tcp_sack(skb, iph, tcph, &sack);
-		
+
 	DEBUGP("tcp_in_window: START\n");
 	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
 	       "seq=%u ack=%u sack=%u win=%u end=%u\n",
-		NIPQUAD(iph->saddr), ntohs(tcph->source), 
+		NIPQUAD(iph->saddr), ntohs(tcph->source),
 		NIPQUAD(iph->daddr), ntohs(tcph->dest),
 		seq, ack, sack, win, end);
 	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
 	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
 		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale, 
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin, 
+		sender->td_scale,
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
 		receiver->td_scale);
-		
+
 	if (sender->td_end == 0) {
 		/*
 		 * Initialize sender data.
@@ -608,26 +604,26 @@
 			/*
 			 * Outgoing SYN-ACK in reply to a SYN.
 			 */
-			sender->td_end = 
+			sender->td_end =
 			sender->td_maxend = end;
 			sender->td_maxwin = (win == 0 ? 1 : win);
 
 			tcp_options(skb, iph, tcph, sender);
-			/* 
+			/*
 			 * RFC 1323:
 			 * Both sides must send the Window Scale option
 			 * to enable window scaling in either direction.
 			 */
 			if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE
 			      && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE))
-				sender->td_scale = 
+				sender->td_scale =
 				receiver->td_scale = 0;
 		} else {
 			/*
 			 * We are in the middle of a connection,
 			 * its history is lost for us.
 			 * Let's try to use the data from the packet.
-		 	 */
+			 */
 			sender->td_end = end;
 			sender->td_maxwin = (win == 0 ? 1 : win);
 			sender->td_maxend = end + sender->td_maxwin;
@@ -635,11 +631,11 @@
 	} else if (((state->state == TCP_CONNTRACK_SYN_SENT
 		     && dir == IP_CT_DIR_ORIGINAL)
 		    || (state->state == TCP_CONNTRACK_SYN_RECV
-		        && dir == IP_CT_DIR_REPLY))
+			&& dir == IP_CT_DIR_REPLY))
 		    && after(end, sender->td_end)) {
 		/*
 		 * RFC 793: "if a TCP is reinitialized ... then it need
-		 * not wait at all; it must only be sure to use sequence 
+		 * not wait at all; it must only be sure to use sequence
 		 * numbers larger than those recently used."
 		 */
 		sender->td_end =
@@ -648,14 +644,14 @@
 
 		tcp_options(skb, iph, tcph, sender);
 	}
-	
+
 	if (!(tcph->ack)) {
 		/*
 		 * If there is no ACK, just pretend it was set and OK.
 		 */
 		ack = sack = receiver->td_end;
-	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) == 
-		    (TCP_FLAG_ACK|TCP_FLAG_RST)) 
+	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) ==
+		    (TCP_FLAG_ACK|TCP_FLAG_RST))
 		   && (ack == 0)) {
 		/*
 		 * Broken TCP stacks, that set ACK in RST packets as well
@@ -665,8 +661,8 @@
 	}
 
 	if (seq == end
-	    && (!tcph->rst 
-	        || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
+	    && (!tcph->rst
+		|| (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
 		/*
 		 * Packets contains no data: we assume it is valid
 		 * and check the ack value only.
@@ -675,7 +671,7 @@
 		 * SYN.
 		 */
 		seq = end = sender->td_end;
-		
+
 	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
 	       "seq=%u ack=%u sack =%u win=%u end=%u\n",
 		NIPQUAD(iph->saddr), ntohs(tcph->source),
@@ -684,27 +680,26 @@
 	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
 	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
 		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale, 
+		sender->td_scale,
 		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
 		receiver->td_scale);
-	
+
 	DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
 		before(seq, sender->td_maxend + 1),
-	    	after(end, sender->td_end - receiver->td_maxwin - 1),
-	    	before(sack, receiver->td_end + 1),
-	    	after(ack, receiver->td_end - MAXACKWINDOW(sender)));
-	
-	if (sender->loose || receiver->loose ||
-	    (before(seq, sender->td_maxend + 1) &&
-	     after(end, sender->td_end - receiver->td_maxwin - 1) &&
-	     before(sack, receiver->td_end + 1) &&
-	     after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
-	    	/*
+		after(end, sender->td_end - receiver->td_maxwin - 1),
+		before(sack, receiver->td_end + 1),
+		after(ack, receiver->td_end - MAXACKWINDOW(sender)));
+
+	if (before(seq, sender->td_maxend + 1) &&
+	    after(end, sender->td_end - receiver->td_maxwin - 1) &&
+	    before(sack, receiver->td_end + 1) &&
+	    after(ack, receiver->td_end - MAXACKWINDOW(sender))) {
+		/*
 		 * Take into account window scaling (RFC 1323).
 		 */
 		if (!tcph->syn)
 			win <<= sender->td_scale;
-		
+
 		/*
 		 * Update sender data.
 		 */
@@ -724,7 +719,7 @@
 				receiver->td_maxend++;
 		}
 
-		/* 
+		/*
 		 * Check retransmissions.
 		 */
 		if (index == TCP_ACK_SET) {
@@ -743,15 +738,13 @@
 				state->retrans = 0;
 			}
 		}
-		/*
-		 * Close the window of disabled window tracking :-)
-		 */
-		if (sender->loose)
-			sender->loose--;
-		
 		res = 1;
 	} else {
-		if (LOG_INVALID(IPPROTO_TCP))
+		res = 0;
+		if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
+		    ip_ct_tcp_be_liberal)
+			res = 1;
+		if (!res && LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
 			"ip_ct_tcp: %s ",
 			before(seq, sender->td_maxend + 1) ?
@@ -762,13 +755,11 @@
 			: "ACK is over the upper bound (ACKed data not seen yet)"
 			: "SEQ is under the lower bound (already ACKed data retransmitted)"
 			: "SEQ is over the upper bound (over the window of the receiver)");
+	}
 
-		res = ip_ct_tcp_be_liberal;
-  	}
-  
 	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
 	       "receiver end=%u maxend=%u maxwin=%u\n",
-		res, sender->td_end, sender->td_maxend, sender->td_maxwin, 
+		res, sender->td_end, sender->td_maxend, sender->td_maxwin,
 		receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
 
 	return res;
@@ -777,7 +768,7 @@
 #ifdef CONFIG_IP_NF_NAT_NEEDED
 /* Update sender->td_end after NAT successfully mangled the packet */
 void ip_conntrack_tcp_update(struct sk_buff *skb,
-			     struct ip_conntrack *conntrack, 
+			     struct ip_conntrack *conntrack,
 			     enum ip_conntrack_dir dir)
 {
 	struct iphdr *iph = skb->nh.iph;
@@ -789,7 +780,7 @@
 #endif
 
 	end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, iph, tcph);
-	
+
 	write_lock_bh(&tcp_lock);
 	/*
 	 * We have to worry for the ack in the reply packet only...
@@ -801,11 +792,11 @@
 	DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
 	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
 		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale, 
+		sender->td_scale,
 		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
 		receiver->td_scale);
 }
- 
+
 #endif
 
 #define	TH_FIN	0x01
@@ -855,8 +846,8 @@
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
 				"ip_ct_tcp: short packet ");
 		return -NF_ACCEPT;
-  	}
-  
+	}
+
 	/* Not whole TCP header or malformed packet */
 	if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
 		if (LOG_INVALID(IPPROTO_TCP))
@@ -864,7 +855,7 @@
 				"ip_ct_tcp: truncated/malformed packet ");
 		return -NF_ACCEPT;
 	}
-  
+
 	/* Checksum invalid? Ignore.
 	 * We skip checking packets on the outgoing path
 	 * because it is assumed to be correct.
@@ -901,11 +892,11 @@
 	struct tcphdr *th, _tcph;
 	unsigned long timeout;
 	unsigned int index;
-	
+
 	th = skb_header_pointer(skb, iph->ihl * 4,
 				sizeof(_tcph), &_tcph);
 	BUG_ON(th == NULL);
-	
+
 	write_lock_bh(&tcp_lock);
 	old_state = conntrack->proto.tcp.state;
 	dir = CTINFO2DIR(ctinfo);
@@ -915,7 +906,7 @@
 	switch (new_state) {
 	case TCP_CONNTRACK_IGNORE:
 		/* Ignored packets:
-		 * 
+		 *
 		 * a) SYN in ORIGINAL
 		 * b) SYN/ACK in REPLY
 		 * c) ACK in reply direction after initial SYN in original.
@@ -924,30 +915,30 @@
 		    && conntrack->proto.tcp.last_index == TCP_SYN_SET
 		    && conntrack->proto.tcp.last_dir != dir
 		    && ntohl(th->ack_seq) ==
-		    	     conntrack->proto.tcp.last_end) {
-			/* This SYN/ACK acknowledges a SYN that we earlier 
+			     conntrack->proto.tcp.last_end) {
+			/* This SYN/ACK acknowledges a SYN that we earlier
 			 * ignored as invalid. This means that the client and
 			 * the server are both in sync, while the firewall is
 			 * not. We kill this session and block the SYN/ACK so
-			 * that the client cannot but retransmit its SYN and 
+			 * that the client cannot but retransmit its SYN and
 			 * thus initiate a clean new session.
 			 */
-		    	write_unlock_bh(&tcp_lock);
+			write_unlock_bh(&tcp_lock);
 			if (LOG_INVALID(IPPROTO_TCP))
 				nf_log_packet(PF_INET, 0, skb, NULL, NULL,
 					      NULL, "ip_ct_tcp: "
 					      "killing out of sync session ");
-		    	if (del_timer(&conntrack->timeout))
-		    		conntrack->timeout.function((unsigned long)
-		    					    conntrack);
-		    	return -NF_DROP;
+			if (del_timer(&conntrack->timeout))
+				conntrack->timeout.function((unsigned long)
+							    conntrack);
+			return -NF_DROP;
 		}
 		conntrack->proto.tcp.last_index = index;
 		conntrack->proto.tcp.last_dir = dir;
 		conntrack->proto.tcp.last_seq = ntohl(th->seq);
-		conntrack->proto.tcp.last_end = 
+		conntrack->proto.tcp.last_end =
 		    segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th);
-		
+
 		write_unlock_bh(&tcp_lock);
 		if (LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
@@ -967,16 +958,16 @@
 		if (old_state < TCP_CONNTRACK_TIME_WAIT)
 			break;
 		if ((conntrack->proto.tcp.seen[dir].flags &
-		         IP_CT_TCP_FLAG_CLOSE_INIT)
+			 IP_CT_TCP_FLAG_CLOSE_INIT)
 		    || after(ntohl(th->seq),
-		    	     conntrack->proto.tcp.seen[dir].td_end)) {	
-		    	/* Attempt to reopen a closed connection.
-		    	* Delete this connection and look up again. */
-		    	write_unlock_bh(&tcp_lock);
-		    	if (del_timer(&conntrack->timeout))
-		    		conntrack->timeout.function((unsigned long)
-		    					    conntrack);
-		    	return -NF_REPEAT;
+			     conntrack->proto.tcp.seen[dir].td_end)) {
+			/* Attempt to reopen a closed connection.
+			* Delete this connection and look up again. */
+			write_unlock_bh(&tcp_lock);
+			if (del_timer(&conntrack->timeout))
+				conntrack->timeout.function((unsigned long)
+							    conntrack);
+			return -NF_REPEAT;
 		} else {
 			write_unlock_bh(&tcp_lock);
 			if (LOG_INVALID(IPPROTO_TCP))
@@ -987,9 +978,9 @@
 	case TCP_CONNTRACK_CLOSE:
 		if (index == TCP_RST_SET
 		    && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
-		         && conntrack->proto.tcp.last_index == TCP_SYN_SET)
-		        || (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
-		            && conntrack->proto.tcp.last_index == TCP_ACK_SET))
+			 && conntrack->proto.tcp.last_index == TCP_SYN_SET)
+			|| (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
+			    && conntrack->proto.tcp.last_index == TCP_ACK_SET))
 		    && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
 			/* RST sent to invalid SYN or ACK we had let through
 			 * at a) and c) above:
@@ -1008,13 +999,13 @@
 		break;
 	}
 
-	if (!tcp_in_window(&conntrack->proto.tcp, dir, index, 
+	if (!tcp_in_window(&conntrack->proto.tcp, dir, index,
 			   skb, iph, th)) {
 		write_unlock_bh(&tcp_lock);
 		return -NF_ACCEPT;
 	}
     in_window:
-	/* From now on we have got in-window packets */	
+	/* From now on we have got in-window packets */
 	conntrack->proto.tcp.last_index = index;
 
 	DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
@@ -1026,9 +1017,9 @@
 		old_state, new_state);
 
 	conntrack->proto.tcp.state = new_state;
-	if (old_state != new_state 
+	if (old_state != new_state
 	    && (new_state == TCP_CONNTRACK_FIN_WAIT
-	    	|| new_state == TCP_CONNTRACK_CLOSE))
+		|| new_state == TCP_CONNTRACK_CLOSE))
 		conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
 	timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
 		  && *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
@@ -1054,8 +1045,8 @@
 		   && (old_state == TCP_CONNTRACK_SYN_RECV
 		       || old_state == TCP_CONNTRACK_ESTABLISHED)
 		   && new_state == TCP_CONNTRACK_ESTABLISHED) {
-		/* Set ASSURED if we see see valid ack in ESTABLISHED 
-		   after SYN_RECV or a valid answer for a picked up 
+		/* Set ASSURED if we see see valid ack in ESTABLISHED
+		   after SYN_RECV or a valid answer for a picked up
 		   connection. */
 		set_bit(IPS_ASSURED_BIT, &conntrack->status);
 		ip_conntrack_event_cache(IPCT_STATUS, skb);
@@ -1064,7 +1055,7 @@
 
 	return NF_ACCEPT;
 }
- 
+
 /* Called when a new connection for this protocol found. */
 static int tcp_new(struct ip_conntrack *conntrack,
 		   const struct sk_buff *skb)
@@ -1080,7 +1071,7 @@
 	th = skb_header_pointer(skb, iph->ihl * 4,
 				sizeof(_tcph), &_tcph);
 	BUG_ON(th == NULL);
-	
+
 	/* Don't need lock here: this conntrack not in circulation yet */
 	new_state
 		= tcp_conntracks[0][get_conntrack_index(th)]
@@ -1105,8 +1096,6 @@
 
 		tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]);
 		conntrack->proto.tcp.seen[1].flags = 0;
-		conntrack->proto.tcp.seen[0].loose = 
-		conntrack->proto.tcp.seen[1].loose = 0;
 	} else if (ip_ct_tcp_loose == 0) {
 		/* Don't try to pick up connections. */
 		return 0;
@@ -1123,35 +1112,35 @@
 		if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
 			conntrack->proto.tcp.seen[0].td_maxwin = 1;
 		conntrack->proto.tcp.seen[0].td_maxend =
-			conntrack->proto.tcp.seen[0].td_end + 
+			conntrack->proto.tcp.seen[0].td_end +
 			conntrack->proto.tcp.seen[0].td_maxwin;
 		conntrack->proto.tcp.seen[0].td_scale = 0;
 
-		/* We assume SACK. Should we assume window scaling too? */
+		/* We assume SACK and liberal window checking to handle
+		 * window scaling */
 		conntrack->proto.tcp.seen[0].flags =
-		conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
-		conntrack->proto.tcp.seen[0].loose = 
-		conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose;
+		conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM |
+						     IP_CT_TCP_FLAG_BE_LIBERAL;
 	}
-    
+
 	conntrack->proto.tcp.seen[1].td_end = 0;
 	conntrack->proto.tcp.seen[1].td_maxend = 0;
 	conntrack->proto.tcp.seen[1].td_maxwin = 1;
-	conntrack->proto.tcp.seen[1].td_scale = 0;      
+	conntrack->proto.tcp.seen[1].td_scale = 0;
 
 	/* tcp_packet will set them */
 	conntrack->proto.tcp.state = TCP_CONNTRACK_NONE;
 	conntrack->proto.tcp.last_index = TCP_NONE_SET;
-	 
+
 	DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
 	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
 		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale, 
+		sender->td_scale,
 		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
 		receiver->td_scale);
 	return 1;
 }
-  
+
 struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
 {
 	.proto 			= IPPROTO_TCP,
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index d0e8a16..14c30c6 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -7,7 +7,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/in.h>
@@ -70,7 +69,7 @@
 	/* If we've seen traffic both ways, this is some kind of UDP
 	   stream.  Extend timeout. */
 	if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
-		ip_ct_refresh_acct(conntrack, ctinfo, skb, 
+		ip_ct_refresh_acct(conntrack, ctinfo, skb,
 				   ip_ct_udp_timeout_stream);
 		/* Also, more likely to be important, and not a probe */
 		if (!test_and_set_bit(IPS_ASSURED_BIT, &conntrack->status))
@@ -102,7 +101,7 @@
 				  "ip_ct_udp: short packet ");
 		return -NF_ACCEPT;
 	}
-	
+
 	/* Truncated/malformed packets */
 	if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
 		if (LOG_INVALID(IPPROTO_UDP))
@@ -110,7 +109,7 @@
 				  "ip_ct_udp: truncated/malformed packet ");
 		return -NF_ACCEPT;
 	}
-	
+
 	/* Packet with no checksum */
 	if (!hdr->check)
 		return NF_ACCEPT;
@@ -126,7 +125,7 @@
 				  "ip_ct_udp: bad UDP checksum ");
 		return -NF_ACCEPT;
 	}
-	
+
 	return NF_ACCEPT;
 }
 
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index 11c588a..c59a962 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -321,7 +321,7 @@
 			continue;
 		}
 		aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
-		                    ct_sip_lnlen(dptr, limit),
+				    ct_sip_lnlen(dptr, limit),
 				    hnfo->case_sensitive);
 		if (!aux) {
 			DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
@@ -406,7 +406,7 @@
 	if (dataoff >= (*pskb)->len) {
 		DEBUGP("skb->len = %u\n", (*pskb)->len);
 		return NF_ACCEPT;
-        }
+	}
 
 	ip_ct_refresh(ct, *pskb, sip_timeout * HZ);
 
@@ -439,16 +439,16 @@
 	}
 	/* Get ip and port address from SDP packet. */
 	if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
-	                    POS_CONNECTION) > 0) {
+			    POS_CONNECTION) > 0) {
 
 		/* We'll drop only if there are parse problems. */
 		if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
-		                 dptr + datalen) < 0) {
+				 dptr + datalen) < 0) {
 			ret = NF_DROP;
 			goto out;
 		}
 		if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
-		                    POS_MEDIA) > 0) {
+				    POS_MEDIA) > 0) {
 
 			port = simple_strtoul(dptr + matchoff, NULL, 10);
 			if (port < 1024) {
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 86efb54..56b2f75 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -46,7 +46,7 @@
 
 static int kill_proto(struct ip_conntrack *i, void *data)
 {
-	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == 
+	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
 			*((u_int8_t *) data));
 }
 
@@ -124,12 +124,12 @@
 	(*pos)++;
 	return ct_get_next(s, v);
 }
-  
+
 static void ct_seq_stop(struct seq_file *s, void *v)
 {
 	read_unlock_bh(&ip_conntrack_lock);
 }
- 
+
 static int ct_seq_show(struct seq_file *s, void *v)
 {
 	const struct ip_conntrack_tuple_hash *hash = v;
@@ -155,12 +155,12 @@
 
 	if (proto->print_conntrack(s, conntrack))
 		return -ENOSPC;
-  
+
 	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
 			proto))
 		return -ENOSPC;
 
- 	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
+	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
 		return -ENOSPC;
 
 	if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
@@ -171,7 +171,7 @@
 			proto))
 		return -ENOSPC;
 
- 	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
+	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
 		return -ENOSPC;
 
 	if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
@@ -200,7 +200,7 @@
 	.stop  = ct_seq_stop,
 	.show  = ct_seq_show
 };
-  
+
 static int ct_open(struct inode *inode, struct file *file)
 {
 	struct seq_file *seq;
@@ -222,14 +222,14 @@
 	return ret;
 }
 
-static struct file_operations ct_file_ops = {
+static const struct file_operations ct_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
 	.release = seq_release_private,
 };
-  
+
 /* expects */
 static void *exp_seq_start(struct seq_file *s, loff_t *pos)
 {
@@ -253,7 +253,7 @@
 
 static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
- 	struct list_head *e = v;
+	struct list_head *e = v;
 
 	++*pos;
 	e = e->next;
@@ -297,8 +297,8 @@
 {
 	return seq_open(file, &exp_seq_ops);
 }
-  
-static struct file_operations exp_file_ops = {
+
+static const struct file_operations exp_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = exp_open,
 	.read    = seq_read,
@@ -386,7 +386,7 @@
 	return seq_open(file, &ct_cpu_seq_ops);
 }
 
-static struct file_operations ct_cpu_seq_fops = {
+static const struct file_operations ct_cpu_seq_fops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_cpu_seq_open,
 	.read    = seq_read,
@@ -426,14 +426,14 @@
 }
 
 static unsigned int ip_conntrack_defrag(unsigned int hooknum,
-				        struct sk_buff **pskb,
-				        const struct net_device *in,
-				        const struct net_device *out,
-				        int (*okfn)(struct sk_buff *))
+					struct sk_buff **pskb,
+					const struct net_device *in,
+					const struct net_device *out,
+					int (*okfn)(struct sk_buff *))
 {
 #if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
 	/* Previously seen (loopback)?  Ignore.  Do this before
-           fragment check. */
+	   fragment check. */
 	if ((*pskb)->nfct)
 		return NF_ACCEPT;
 #endif
@@ -441,7 +441,7 @@
 	/* Gather fragments. */
 	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
 		*pskb = ip_ct_gather_frags(*pskb,
-		                           hooknum == NF_IP_PRE_ROUTING ? 
+					   hooknum == NF_IP_PRE_ROUTING ?
 					   IP_DEFRAG_CONNTRACK_IN :
 					   IP_DEFRAG_CONNTRACK_OUT);
 		if (!*pskb)
@@ -776,7 +776,7 @@
 	{
 		.ctl_name	= CTL_NET,
 		.procname	= "net",
-		.mode		= 0555, 
+		.mode		= 0555,
 		.child		= ip_ct_ipv4_table,
 	},
 	{ .ctl_name = 0 }
@@ -796,7 +796,7 @@
 		ret = -EBUSY;
 		goto out;
 	}
-	ip_ct_protos[proto->proto] = proto;
+	rcu_assign_pointer(ip_ct_protos[proto->proto], proto);
  out:
 	write_unlock_bh(&ip_conntrack_lock);
 	return ret;
@@ -805,11 +805,10 @@
 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
 {
 	write_lock_bh(&ip_conntrack_lock);
-	ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
+	rcu_assign_pointer(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();
+	synchronize_rcu();
 
 	/* Remove all contrack entries for this protocol */
 	ip_ct_iterate_cleanup(kill_proto, &proto->proto);
@@ -849,7 +848,7 @@
 		goto cleanup_proc_stat;
 	}
 #ifdef CONFIG_SYSCTL
-	ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
+	ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table);
 	if (ip_ct_sysctl_header == NULL) {
 		printk("ip_conntrack: can't register to sysctl.\n");
 		ret = -ENOMEM;
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index ef56de2..76e175e 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -33,7 +33,7 @@
 
 #if 0
 #define DEBUGP(format, args...) printk("%s:%s:" format, \
-                                       __FILE__, __FUNCTION__ , ## args)
+				       __FILE__, __FUNCTION__ , ## args)
 #else
 #define DEBUGP(format, args...)
 #endif
@@ -113,7 +113,7 @@
 		DEBUGP("unregistering helper for port %d\n",
 			ports[i]);
 		ip_conntrack_helper_unregister(&tftp[i]);
-	} 
+	}
 }
 
 static int __init ip_conntrack_tftp_init(void)
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 9d1a517..40737fd 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -50,7 +50,7 @@
 static inline struct ip_nat_protocol *
 __ip_nat_proto_find(u_int8_t protonum)
 {
-	return ip_nat_protos[protonum];
+	return rcu_dereference(ip_nat_protos[protonum]);
 }
 
 struct ip_nat_protocol *
@@ -58,13 +58,11 @@
 {
 	struct ip_nat_protocol *p;
 
-	/* we need to disable preemption to make sure 'p' doesn't get
-	 * removed until we've grabbed the reference */
-	preempt_disable();
+	rcu_read_lock();
 	p = __ip_nat_proto_find(protonum);
 	if (!try_module_get(p->me))
 		p = &ip_nat_unknown_protocol;
-	preempt_enable();
+	rcu_read_unlock();
 
 	return p;
 }
@@ -120,8 +118,8 @@
 in_range(const struct ip_conntrack_tuple *tuple,
 	 const struct ip_nat_range *range)
 {
-	struct ip_nat_protocol *proto = 
-				__ip_nat_proto_find(tuple->dst.protonum);
+	struct ip_nat_protocol *proto;
+	int ret = 0;
 
 	/* If we are supposed to map IPs, then we must be in the
 	   range specified, otherwise let this drag us onto a new src IP. */
@@ -131,12 +129,15 @@
 			return 0;
 	}
 
+	rcu_read_lock();
+	proto = __ip_nat_proto_find(tuple->dst.protonum);
 	if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
 	    || proto->in_range(tuple, IP_NAT_MANIP_SRC,
 			       &range->min, &range->max))
-		return 1;
+		ret = 1;
+	rcu_read_unlock();
 
-	return 0;
+	return ret;
 }
 
 static inline int
@@ -246,8 +247,9 @@
 	if (maniptype == IP_NAT_MANIP_SRC) {
 		if (find_appropriate_src(orig_tuple, tuple, range)) {
 			DEBUGP("get_unique_tuple: Found current src map\n");
-			if (!ip_nat_used_tuple(tuple, conntrack))
-				return;
+			if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
+				if (!ip_nat_used_tuple(tuple, conntrack))
+					return;
 		}
 	}
 
@@ -259,20 +261,25 @@
 	/* 3) The per-protocol part of the manip is made to map into
 	   the range to make a unique tuple. */
 
-	proto = ip_nat_proto_find_get(orig_tuple->dst.protonum);
+	rcu_read_lock();
+	proto = __ip_nat_proto_find(orig_tuple->dst.protonum);
+
+	/* Change protocol info to have some randomization */
+	if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) {
+		proto->unique_tuple(tuple, range, maniptype, conntrack);
+		goto out;
+	}
 
 	/* Only bother mapping if it's not already in range and unique */
 	if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
 	     || proto->in_range(tuple, maniptype, &range->min, &range->max))
-	    && !ip_nat_used_tuple(tuple, conntrack)) {
-		ip_nat_proto_put(proto);
-		return;
-	}
+	    && !ip_nat_used_tuple(tuple, conntrack))
+		goto out;
 
 	/* Last change: get protocol to try to obtain unique tuple. */
 	proto->unique_tuple(tuple, range, maniptype, conntrack);
-
-	ip_nat_proto_put(proto);
+out:
+	rcu_read_unlock();
 }
 
 unsigned int
@@ -352,12 +359,11 @@
 	iph = (void *)(*pskb)->data + iphdroff;
 
 	/* Manipulate protcol part. */
-	p = ip_nat_proto_find_get(proto);
-	if (!p->manip_pkt(pskb, iphdroff, target, maniptype)) {
-		ip_nat_proto_put(p);
+
+	/* rcu_read_lock()ed by nf_hook_slow */
+	p = __ip_nat_proto_find(proto);
+	if (!p->manip_pkt(pskb, iphdroff, target, maniptype))
 		return 0;
-	}
-	ip_nat_proto_put(p);
 
 	iph = (void *)(*pskb)->data + iphdroff;
 
@@ -414,6 +420,7 @@
 		struct icmphdr icmp;
 		struct iphdr ip;
 	} *inside;
+	struct ip_conntrack_protocol *proto;
 	struct ip_conntrack_tuple inner, target;
 	int hdrlen = (*pskb)->nh.iph->ihl * 4;
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
@@ -435,8 +442,8 @@
 		     (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
 
 	/* Redirects on non-null nats must be dropped, else they'll
-           start talking to each other without our translation, and be
-           confused... --RR */
+	   start talking to each other without our translation, and be
+	   confused... --RR */
 	if (inside->icmp.type == ICMP_REDIRECT) {
 		/* If NAT isn't finished, assume it and drop. */
 		if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
@@ -449,10 +456,11 @@
 	DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n",
 	       *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
 
+	/* rcu_read_lock()ed by nf_hook_slow */
+	proto = __ip_conntrack_proto_find(inside->ip.protocol);
 	if (!ip_ct_get_tuple(&inside->ip, *pskb, (*pskb)->nh.iph->ihl*4 +
-	                     sizeof(struct icmphdr) + inside->ip.ihl*4,
-	                     &inner,
-			     __ip_conntrack_proto_find(inside->ip.protocol)))
+			     sizeof(struct icmphdr) + inside->ip.ihl*4,
+			     &inner, proto))
 		return 0;
 
 	/* Change inner back to look like incoming packet.  We do the
@@ -507,7 +515,7 @@
 		ret = -EBUSY;
 		goto out;
 	}
-	ip_nat_protos[proto->protonum] = proto;
+	rcu_assign_pointer(ip_nat_protos[proto->protonum], proto);
  out:
 	write_unlock_bh(&ip_nat_lock);
 	return ret;
@@ -518,18 +526,17 @@
 void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
 {
 	write_lock_bh(&ip_nat_lock);
-	ip_nat_protos[proto->protonum] = &ip_nat_unknown_protocol;
+	rcu_assign_pointer(ip_nat_protos[proto->protonum],
+			   &ip_nat_unknown_protocol);
 	write_unlock_bh(&ip_nat_lock);
-
-	/* Someone could be still looking at the proto in a bh. */
-	synchronize_net();
+	synchronize_rcu();
 }
 EXPORT_SYMBOL(ip_nat_protocol_unregister);
 
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
     defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
 int
-ip_nat_port_range_to_nfattr(struct sk_buff *skb, 
+ip_nat_port_range_to_nfattr(struct sk_buff *skb,
 			    const struct ip_nat_range *range)
 {
 	NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(__be16),
@@ -547,21 +554,21 @@
 ip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range)
 {
 	int ret = 0;
-	
+
 	/* we have to return whether we actually parsed something or not */
 
 	if (tb[CTA_PROTONAT_PORT_MIN-1]) {
 		ret = 1;
-		range->min.tcp.port = 
+		range->min.tcp.port =
 			*(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]);
 	}
-	
+
 	if (!tb[CTA_PROTONAT_PORT_MAX-1]) {
-		if (ret) 
+		if (ret)
 			range->max.tcp.port = range->min.tcp.port;
 	} else {
 		ret = 1;
-		range->max.tcp.port = 
+		range->max.tcp.port =
 			*(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]);
 	}
 
@@ -586,10 +593,10 @@
 	/* Sew in builtin protocols. */
 	write_lock_bh(&ip_nat_lock);
 	for (i = 0; i < MAX_IP_NAT_PROTO; i++)
-		ip_nat_protos[i] = &ip_nat_unknown_protocol;
-	ip_nat_protos[IPPROTO_TCP] = &ip_nat_protocol_tcp;
-	ip_nat_protos[IPPROTO_UDP] = &ip_nat_protocol_udp;
-	ip_nat_protos[IPPROTO_ICMP] = &ip_nat_protocol_icmp;
+		rcu_assign_pointer(ip_nat_protos[i], &ip_nat_unknown_protocol);
+	rcu_assign_pointer(ip_nat_protos[IPPROTO_TCP], &ip_nat_protocol_tcp);
+	rcu_assign_pointer(ip_nat_protos[IPPROTO_UDP], &ip_nat_protocol_udp);
+	rcu_assign_pointer(ip_nat_protos[IPPROTO_ICMP], &ip_nat_protocol_icmp);
 	write_unlock_bh(&ip_nat_lock);
 
 	for (i = 0; i < ip_nat_htable_size; i++) {
@@ -597,8 +604,8 @@
 	}
 
 	/* FIXME: Man, this is a hack.  <SIGH> */
-	IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
-	ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
+	IP_NF_ASSERT(rcu_dereference(ip_conntrack_destroyed) == NULL);
+	rcu_assign_pointer(ip_conntrack_destroyed, ip_nat_cleanup_conntrack);
 
 	/* Initialize fake conntrack so that NAT will skip it */
 	ip_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
@@ -616,7 +623,8 @@
 static void __exit ip_nat_cleanup(void)
 {
 	ip_ct_iterate_cleanup(&clean_nat, NULL);
-	ip_conntrack_destroyed = NULL;
+	rcu_assign_pointer(ip_conntrack_destroyed, NULL);
+	synchronize_rcu();
 	vfree(bysource);
 }
 
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index 913960e..32e01d8 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -50,7 +50,7 @@
 	DEBUGP("calling ip_nat_mangle_tcp_packet\n");
 
 	*seq += strlen(buffer) - matchlen;
-	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, 
+	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
 					matchlen, buffer, strlen(buffer));
 }
 
@@ -72,7 +72,7 @@
 	DEBUGP("calling ip_nat_mangle_tcp_packet\n");
 
 	*seq += strlen(buffer) - matchlen;
-	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, 
+	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
 					matchlen, buffer, strlen(buffer));
 }
 
@@ -94,7 +94,7 @@
 	DEBUGP("calling ip_nat_mangle_tcp_packet\n");
 
 	*seq += strlen(buffer) - matchlen;
-	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, 
+	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
 					matchlen, buffer, strlen(buffer));
 }
 
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index ee80feb..dc778cf 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -1,4 +1,4 @@
-/* ip_nat_helper.c - generic support functions for NAT helpers 
+/* ip_nat_helper.c - generic support functions for NAT helpers
  *
  * (C) 2000-2002 Harald Welte <laforge@netfilter.org>
  * (C) 2003-2004 Netfilter Core Team <coreteam@netfilter.org>
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  *
  * 	14 Jan 2002 Harald Welte <laforge@gnumonks.org>:
- *		- add support for SACK adjustment 
+ *		- add support for SACK adjustment
  *	14 Mar 2002 Harald Welte <laforge@gnumonks.org>:
  *		- merge SACK support into newnat API
  *	16 Aug 2002 Brian J. Murrell <netfilter@interlinx.bc.ca>:
@@ -45,10 +45,10 @@
 static DEFINE_SPINLOCK(ip_nat_seqofs_lock);
 
 /* Setup TCP sequence correction given this change at this sequence */
-static inline void 
+static inline void
 adjust_tcp_sequence(u32 seq,
 		    int sizediff,
-		    struct ip_conntrack *ct, 
+		    struct ip_conntrack *ct,
 		    enum ip_conntrack_info ctinfo)
 {
 	int dir;
@@ -150,7 +150,7 @@
  * skb enlargement, ...
  *
  * */
-int 
+int
 ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
 			 struct ip_conntrack *ct,
 			 enum ip_conntrack_info ctinfo,
@@ -183,10 +183,10 @@
 	datalen = (*pskb)->len - iph->ihl*4;
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 		tcph->check = 0;
-		tcph->check = tcp_v4_check(tcph, datalen,
+		tcph->check = tcp_v4_check(datalen,
 					   iph->saddr, iph->daddr,
 					   csum_partial((char *)tcph,
-					   		datalen, 0));
+							datalen, 0));
 	} else
 		nf_proto_csum_replace2(&tcph->check, *pskb,
 					htons(oldlen), htons(datalen), 1);
@@ -202,7 +202,7 @@
 	return 1;
 }
 EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
-			
+
 /* Generic function for mangling variable-length address changes inside
  * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
  * command in the Amanda protocol)
@@ -213,7 +213,7 @@
  * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
  *       should be fairly easy to do.
  */
-int 
+int
 ip_nat_mangle_udp_packet(struct sk_buff **pskb,
 			 struct ip_conntrack *ct,
 			 enum ip_conntrack_info ctinfo,
@@ -228,8 +228,8 @@
 
 	/* UDP helpers might accidentally mangle the wrong packet */
 	iph = (*pskb)->nh.iph;
-	if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) + 
-	                       match_offset + match_len)
+	if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) +
+			       match_offset + match_len)
 		return 0;
 
 	if (!skb_make_writable(pskb, (*pskb)->len))
@@ -258,9 +258,9 @@
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 		udph->check = 0;
 		udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
-		                                datalen, IPPROTO_UDP,
-		                                csum_partial((char *)udph,
-		                                             datalen, 0));
+						datalen, IPPROTO_UDP,
+						csum_partial((char *)udph,
+							     datalen, 0));
 		if (!udph->check)
 			udph->check = CSUM_MANGLED_0;
 	} else
@@ -273,7 +273,7 @@
 /* Adjust one found SACK option including checksum correction */
 static void
 sack_adjust(struct sk_buff *skb,
-	    struct tcphdr *tcph, 
+	    struct tcphdr *tcph,
 	    unsigned int sackoff,
 	    unsigned int sackend,
 	    struct ip_nat_seq *natseq)
@@ -360,14 +360,14 @@
 
 /* TCP sequence number adjustment.  Returns 1 on success, 0 on failure */
 int
-ip_nat_seq_adjust(struct sk_buff **pskb, 
-		  struct ip_conntrack *ct, 
+ip_nat_seq_adjust(struct sk_buff **pskb,
+		  struct ip_conntrack *ct,
 		  enum ip_conntrack_info ctinfo)
 {
 	struct tcphdr *tcph;
 	int dir;
 	__be32 newseq, newack;
-	struct ip_nat_seq *this_way, *other_way;	
+	struct ip_nat_seq *this_way, *other_way;
 
 	dir = CTINFO2DIR(ctinfo);
 
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index ec957bb..24ce4a5 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -202,10 +202,10 @@
 
 	/* mangle packet */
 	if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
-	                             cid_off + sizeof(struct pptp_pkt_hdr) +
-	                             sizeof(struct PptpControlHeader),
-	                             sizeof(new_callid), (char *)&new_callid,
-	                             sizeof(new_callid)) == 0)
+				     cid_off + sizeof(struct pptp_pkt_hdr) +
+				     sizeof(struct PptpControlHeader),
+				     sizeof(new_callid), (char *)&new_callid,
+				     sizeof(new_callid)) == 0)
 		return NF_DROP;
 
 	return NF_ACCEPT;
@@ -293,7 +293,7 @@
 		ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
 
 	if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
-	                             pcid_off + sizeof(struct pptp_pkt_hdr) +
+				     pcid_off + sizeof(struct pptp_pkt_hdr) +
 				     sizeof(struct PptpControlHeader),
 				     sizeof(new_pcid), (char *)&new_pcid,
 				     sizeof(new_pcid)) == 0)
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index feb26b4..cfaeea3 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -88,8 +88,8 @@
 	DEBUGP("ip_nat_irc: Inserting '%s' == %u.%u.%u.%u, port %u\n",
 	       buffer, NIPQUAD(exp->tuple.src.ip), port);
 
-	ret = ip_nat_mangle_tcp_packet(pskb, exp->master, ctinfo, 
-				       matchoff, matchlen, buffer, 
+	ret = ip_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
+				       matchoff, matchlen, buffer,
 				       strlen(buffer));
 	if (ret != NF_ACCEPT)
 		ip_conntrack_unexpect_related(exp);
diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
index fb716ed..22a528a 100644
--- a/net/ipv4/netfilter/ip_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c
@@ -45,7 +45,7 @@
 
 	for (i = 0; i < range_size; i++, id++) {
 		tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +
-		                             (id % range_size));
+					     (id % range_size));
 		if (!ip_nat_used_tuple(tuple, conntrack))
 			return 1;
 	}
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
index b586d18..14ff24f 100644
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/random.h>
 #include <linux/netfilter.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
@@ -75,6 +76,10 @@
 		range_size = ntohs(range->max.tcp.port) - min + 1;
 	}
 
+	/* Start from random port to avoid prediction */
+	if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
+		port =  net_random();
+
 	for (i = 0; i < range_size; i++, port++) {
 		*portptr = htons(min + port % range_size);
 		if (!ip_nat_used_tuple(tuple, conntrack)) {
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
index 5ced087..dfd5216 100644
--- a/net/ipv4/netfilter/ip_nat_proto_udp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/random.h>
 #include <linux/netfilter.h>
 #include <linux/ip.h>
 #include <linux/udp.h>
@@ -74,6 +75,10 @@
 		range_size = ntohs(range->max.udp.port) - min + 1;
 	}
 
+	/* Start from random port to avoid prediction */
+	if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
+		port = net_random();
+
 	for (i = 0; i < range_size; i++, port++) {
 		*portptr = htons(min + port % range_size);
 		if (!ip_nat_used_tuple(tuple, conntrack))
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index a176aa3..080eb1d 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -86,7 +86,7 @@
     }
 };
 
-static struct ipt_table nat_table = {
+static struct xt_table nat_table = {
 	.name		= "nat",
 	.valid_hooks	= NAT_VALID_HOOKS,
 	.lock		= RW_LOCK_UNLOCKED,
@@ -99,7 +99,7 @@
 				    const struct net_device *in,
 				    const struct net_device *out,
 				    unsigned int hooknum,
-				    const struct ipt_target *target,
+				    const struct xt_target *target,
 				    const void *targinfo)
 {
 	struct ip_conntrack *ct;
@@ -112,7 +112,7 @@
 
 	/* Connection must be valid and new. */
 	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
-	                    || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
+			    || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
 	IP_NF_ASSERT(out);
 
 	return ip_nat_setup_info(ct, &mr->range[0], hooknum);
@@ -141,7 +141,7 @@
 				    const struct net_device *in,
 				    const struct net_device *out,
 				    unsigned int hooknum,
-				    const struct ipt_target *target,
+				    const struct xt_target *target,
 				    const void *targinfo)
 {
 	struct ip_conntrack *ct;
@@ -166,7 +166,7 @@
 
 static int ipt_snat_checkentry(const char *tablename,
 			       const void *entry,
-			       const struct ipt_target *target,
+			       const struct xt_target *target,
 			       void *targinfo,
 			       unsigned int hook_mask)
 {
@@ -182,7 +182,7 @@
 
 static int ipt_dnat_checkentry(const char *tablename,
 			       const void *entry,
-			       const struct ipt_target *target,
+			       const struct xt_target *target,
 			       void *targinfo,
 			       unsigned int hook_mask)
 {
@@ -193,6 +193,10 @@
 		printk("DNAT: multiple ranges no longer supported\n");
 		return 0;
 	}
+	if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) {
+		printk("DNAT: port randomization not supported\n");
+		return 0;
+	}
 	return 1;
 }
 
@@ -219,8 +223,8 @@
 
 unsigned int
 alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
-                             struct ip_nat_info *info,
-                             unsigned int hooknum)
+			     struct ip_nat_info *info,
+			     unsigned int hooknum)
 {
 	__be32 ip
 		= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
@@ -257,8 +261,9 @@
 	return ret;
 }
 
-static struct ipt_target ipt_snat_reg = {
+static struct xt_target ipt_snat_reg = {
 	.name		= "SNAT",
+	.family		= AF_INET,
 	.target		= ipt_snat_target,
 	.targetsize	= sizeof(struct ip_nat_multi_range_compat),
 	.table		= "nat",
@@ -266,8 +271,9 @@
 	.checkentry	= ipt_snat_checkentry,
 };
 
-static struct ipt_target ipt_dnat_reg = {
+static struct xt_target ipt_dnat_reg = {
 	.name		= "DNAT",
+	.family		= AF_INET,
 	.target		= ipt_dnat_target,
 	.targetsize	= sizeof(struct ip_nat_multi_range_compat),
 	.table		= "nat",
@@ -282,27 +288,27 @@
 	ret = ipt_register_table(&nat_table, &nat_initial_table.repl);
 	if (ret != 0)
 		return ret;
-	ret = ipt_register_target(&ipt_snat_reg);
+	ret = xt_register_target(&ipt_snat_reg);
 	if (ret != 0)
 		goto unregister_table;
 
-	ret = ipt_register_target(&ipt_dnat_reg);
+	ret = xt_register_target(&ipt_dnat_reg);
 	if (ret != 0)
 		goto unregister_snat;
 
 	return ret;
 
  unregister_snat:
-	ipt_unregister_target(&ipt_snat_reg);
+	xt_unregister_target(&ipt_snat_reg);
  unregister_table:
-	ipt_unregister_table(&nat_table);
+	xt_unregister_table(&nat_table);
 
 	return ret;
 }
 
 void ip_nat_rule_cleanup(void)
 {
-	ipt_unregister_target(&ipt_dnat_reg);
-	ipt_unregister_target(&ipt_snat_reg);
+	xt_unregister_target(&ipt_dnat_reg);
+	xt_unregister_target(&ipt_snat_reg);
 	ipt_unregister_table(&nat_table);
 }
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
index 6223abc..325c5a9 100644
--- a/net/ipv4/netfilter/ip_nat_sip.c
+++ b/net/ipv4/netfilter/ip_nat_sip.c
@@ -88,7 +88,7 @@
 		return 1;
 
 	if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
-	                              matchoff, matchlen, addr, addrlen))
+				      matchoff, matchlen, addr, addrlen))
 		return 0;
 	*dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
 	return 1;
@@ -149,7 +149,7 @@
 		return 0;
 
 	if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
-	                              matchoff, matchlen, buffer, bufflen))
+				      matchoff, matchlen, buffer, bufflen))
 		return 0;
 
 	/* We need to reload this. Thanks Patrick. */
@@ -170,7 +170,7 @@
 
 	/* Get actual SDP lenght */
 	if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
-	                    &matchlen, POS_SDP_HEADER) > 0) {
+			    &matchlen, POS_SDP_HEADER) > 0) {
 
 		/* since ct_sip_get_info() give us a pointer passing 'v='
 		   we need to add 2 bytes in this count. */
@@ -178,7 +178,7 @@
 
 		/* Now, update SDP lenght */
 		if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
-		                    &matchlen, POS_CONTENT) > 0) {
+				    &matchlen, POS_CONTENT) > 0) {
 
 			bufflen = sprintf(buffer, "%u", c_len);
 
@@ -204,17 +204,17 @@
 	/* Mangle owner and contact info. */
 	bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
 	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-	                       buffer, bufflen, POS_OWNER))
+			       buffer, bufflen, POS_OWNER))
 		return 0;
 
 	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-	                       buffer, bufflen, POS_CONNECTION))
+			       buffer, bufflen, POS_CONNECTION))
 		return 0;
 
 	/* Mangle media port. */
 	bufflen = sprintf(buffer, "%u", port);
 	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-	                       buffer, bufflen, POS_MEDIA))
+			       buffer, bufflen, POS_MEDIA))
 		return 0;
 
 	return mangle_content_len(pskb, ctinfo, ct, dptr);
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index c3d9f3b..e41d0ef 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -3,11 +3,11 @@
  *
  * Basic SNMP Application Layer Gateway
  *
- * This IP NAT module is intended for use with SNMP network 
- * discovery and monitoring applications where target networks use 
+ * This IP NAT module is intended for use with SNMP network
+ * discovery and monitoring applications where target networks use
  * conflicting private address realms.
  *
- * Static NAT is used to remap the networks from the view of the network 
+ * Static NAT is used to remap the networks from the view of the network
  * management system at the IP layer, and this module remaps some application
  * layer addresses to match.
  *
@@ -20,7 +20,7 @@
  * More information on ALG and associated issues can be found in
  * RFC 2962
  *
- * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory 
+ * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory
  * McLean & Jochen Friedrich, stripped down for use in the kernel.
  *
  * Copyright (c) 2000 RP Internet (www.rpi.net.au).
@@ -69,8 +69,8 @@
 static int debug;
 static DEFINE_SPINLOCK(snmp_lock);
 
-/* 
- * Application layer address mapping mimics the NAT mapping, but 
+/*
+ * Application layer address mapping mimics the NAT mapping, but
  * only for the first octet in this case (a more flexible system
  * can be implemented if needed).
  */
@@ -80,7 +80,7 @@
 	u_int8_t to;
 };
 
-                                  
+
 /*****************************************************************************
  *
  * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
@@ -129,7 +129,7 @@
 #define ASN1_ERR_DEC_LENGTH_MISMATCH	4
 #define ASN1_ERR_DEC_BADVALUE		5
 
-/* 
+/*
  * ASN.1 context.
  */
 struct asn1_ctx
@@ -148,10 +148,10 @@
 	unsigned char *data;
 	unsigned int len;
 };
-	
+
 static void asn1_open(struct asn1_ctx *ctx,
-                      unsigned char *buf,
-                      unsigned int len)
+		      unsigned char *buf,
+		      unsigned int len)
 {
 	ctx->begin = buf;
 	ctx->end = buf + len;
@@ -172,9 +172,9 @@
 static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
 {
 	unsigned char ch;
-	
+
 	*tag = 0;
-	
+
 	do
 	{
 		if (!asn1_octet_decode(ctx, &ch))
@@ -185,20 +185,20 @@
 	return 1;
 }
 
-static unsigned char asn1_id_decode(struct asn1_ctx *ctx, 
-                                    unsigned int *cls,
-                                    unsigned int *con,
-                                    unsigned int *tag)
+static unsigned char asn1_id_decode(struct asn1_ctx *ctx,
+				    unsigned int *cls,
+				    unsigned int *con,
+				    unsigned int *tag)
 {
 	unsigned char ch;
-	
+
 	if (!asn1_octet_decode(ctx, &ch))
 		return 0;
-		
+
 	*cls = (ch & 0xC0) >> 6;
 	*con = (ch & 0x20) >> 5;
 	*tag = (ch & 0x1F);
-	
+
 	if (*tag == 0x1F) {
 		if (!asn1_tag_decode(ctx, tag))
 			return 0;
@@ -207,25 +207,25 @@
 }
 
 static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
-                                        unsigned int *def,
-                                        unsigned int *len)
+					unsigned int *def,
+					unsigned int *len)
 {
 	unsigned char ch, cnt;
-	
+
 	if (!asn1_octet_decode(ctx, &ch))
 		return 0;
-		
+
 	if (ch == 0x80)
 		*def = 0;
 	else {
 		*def = 1;
-		
+
 		if (ch < 0x80)
 			*len = ch;
 		else {
 			cnt = (unsigned char) (ch & 0x7F);
 			*len = 0;
-			
+
 			while (cnt > 0) {
 				if (!asn1_octet_decode(ctx, &ch))
 					return 0;
@@ -239,20 +239,20 @@
 }
 
 static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
-                                        unsigned char **eoc,
-                                        unsigned int *cls,
-                                        unsigned int *con,
-                                        unsigned int *tag)
+					unsigned char **eoc,
+					unsigned int *cls,
+					unsigned int *con,
+					unsigned int *tag)
 {
 	unsigned int def, len;
-	
+
 	if (!asn1_id_decode(ctx, cls, con, tag))
 		return 0;
-		
+
 	def = len = 0;
 	if (!asn1_length_decode(ctx, &def, &len))
 		return 0;
-		
+
 	if (def)
 		*eoc = ctx->pointer + len;
 	else
@@ -263,19 +263,19 @@
 static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
 {
 	unsigned char ch;
-	
+
 	if (eoc == 0) {
 		if (!asn1_octet_decode(ctx, &ch))
 			return 0;
-			
+
 		if (ch != 0x00) {
 			ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
 			return 0;
 		}
-		
+
 		if (!asn1_octet_decode(ctx, &ch))
 			return 0;
-			
+
 		if (ch != 0x00) {
 			ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
 			return 0;
@@ -297,27 +297,27 @@
 }
 
 static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
-                                      unsigned char *eoc,
-                                      long *integer)
+				      unsigned char *eoc,
+				      long *integer)
 {
 	unsigned char ch;
 	unsigned int  len;
-	
+
 	if (!asn1_octet_decode(ctx, &ch))
 		return 0;
-		
+
 	*integer = (signed char) ch;
 	len = 1;
-	
+
 	while (ctx->pointer < eoc) {
 		if (++len > sizeof (long)) {
 			ctx->error = ASN1_ERR_DEC_BADVALUE;
 			return 0;
 		}
-		
+
 		if (!asn1_octet_decode(ctx, &ch))
 			return 0;
-			
+
 		*integer <<= 8;
 		*integer |= ch;
 	}
@@ -325,28 +325,28 @@
 }
 
 static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
-                                      unsigned char *eoc,
-                                      unsigned int *integer)
+				      unsigned char *eoc,
+				      unsigned int *integer)
 {
 	unsigned char ch;
 	unsigned int  len;
-	
+
 	if (!asn1_octet_decode(ctx, &ch))
 		return 0;
-		
+
 	*integer = ch;
 	if (ch == 0) len = 0;
 	else len = 1;
-	
+
 	while (ctx->pointer < eoc) {
 		if (++len > sizeof (unsigned int)) {
 			ctx->error = ASN1_ERR_DEC_BADVALUE;
 			return 0;
 		}
-		
+
 		if (!asn1_octet_decode(ctx, &ch))
 			return 0;
-			
+
 		*integer <<= 8;
 		*integer |= ch;
 	}
@@ -354,28 +354,28 @@
 }
 
 static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
-                                       unsigned char *eoc,
-                                       unsigned long *integer)
+				       unsigned char *eoc,
+				       unsigned long *integer)
 {
 	unsigned char ch;
 	unsigned int  len;
-	
+
 	if (!asn1_octet_decode(ctx, &ch))
 		return 0;
-		
+
 	*integer = ch;
 	if (ch == 0) len = 0;
 	else len = 1;
-	
+
 	while (ctx->pointer < eoc) {
 		if (++len > sizeof (unsigned long)) {
 			ctx->error = ASN1_ERR_DEC_BADVALUE;
 			return 0;
 		}
-		
+
 		if (!asn1_octet_decode(ctx, &ch))
 			return 0;
-			
+
 		*integer <<= 8;
 		*integer |= ch;
 	}
@@ -383,21 +383,21 @@
 }
 
 static unsigned char asn1_octets_decode(struct asn1_ctx *ctx,
-                                        unsigned char *eoc,
-                                        unsigned char **octets,
-                                        unsigned int *len)
+					unsigned char *eoc,
+					unsigned char **octets,
+					unsigned int *len)
 {
 	unsigned char *ptr;
-	
+
 	*len = 0;
-	
+
 	*octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
 	if (*octets == NULL) {
 		if (net_ratelimit())
 			printk("OOM in bsalg (%d)\n", __LINE__);
 		return 0;
 	}
-	
+
 	ptr = *octets;
 	while (ctx->pointer < eoc) {
 		if (!asn1_octet_decode(ctx, (unsigned char *)ptr++)) {
@@ -411,16 +411,16 @@
 }
 
 static unsigned char asn1_subid_decode(struct asn1_ctx *ctx,
-                                       unsigned long *subid)
+				       unsigned long *subid)
 {
 	unsigned char ch;
-	
+
 	*subid = 0;
-	
+
 	do {
 		if (!asn1_octet_decode(ctx, &ch))
 			return 0;
-		
+
 		*subid <<= 7;
 		*subid |= ch & 0x7F;
 	} while ((ch & 0x80) == 0x80);
@@ -428,14 +428,14 @@
 }
 
 static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
-                                     unsigned char *eoc,
-                                     unsigned long **oid,
-                                     unsigned int *len)
+				     unsigned char *eoc,
+				     unsigned long **oid,
+				     unsigned int *len)
 {
 	unsigned long subid;
 	unsigned int  size;
 	unsigned long *optr;
-	
+
 	size = eoc - ctx->pointer + 1;
 	*oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
 	if (*oid == NULL) {
@@ -443,15 +443,15 @@
 			printk("OOM in bsalg (%d)\n", __LINE__);
 		return 0;
 	}
-	
+
 	optr = *oid;
-	
+
 	if (!asn1_subid_decode(ctx, &subid)) {
 		kfree(*oid);
 		*oid = NULL;
 		return 0;
 	}
-	
+
 	if (subid < 40) {
 		optr [0] = 0;
 		optr [1] = subid;
@@ -462,10 +462,10 @@
 		optr [0] = 2;
 		optr [1] = subid - 80;
 	}
-	
+
 	*len = 2;
 	optr += 2;
-	
+
 	while (ctx->pointer < eoc) {
 		if (++(*len) > size) {
 			ctx->error = ASN1_ERR_DEC_BADVALUE;
@@ -473,7 +473,7 @@
 			*oid = NULL;
 			return 0;
 		}
-		
+
 		if (!asn1_subid_decode(ctx, optr++)) {
 			kfree(*oid);
 			*oid = NULL;
@@ -611,9 +611,9 @@
 #define SERR_EOM    2
 
 static inline void mangle_address(unsigned char *begin,
-                                  unsigned char *addr,
-                                  const struct oct1_map *map,
-                                  __sum16 *check);
+				  unsigned char *addr,
+				  const struct oct1_map *map,
+				  __sum16 *check);
 struct snmp_cnv
 {
 	unsigned int class;
@@ -633,7 +633,7 @@
 	{ASN1_APL, SNMP_GGE, SNMP_GAUGE},	/* Gauge32 == Unsigned32  */
 	{ASN1_APL, SNMP_TIT, SNMP_TIMETICKS},
 	{ASN1_APL, SNMP_OPQ, SNMP_OPAQUE},
-	
+
 	/* SNMPv2 data types and errors */
 	{ASN1_UNI, ASN1_BTS, SNMP_BITSTR},
 	{ASN1_APL, SNMP_C64, SNMP_COUNTER64},
@@ -644,13 +644,13 @@
 };
 
 static unsigned char snmp_tag_cls2syntax(unsigned int tag,
-                                         unsigned int cls,
-                                         unsigned short *syntax)
+					 unsigned int cls,
+					 unsigned short *syntax)
 {
 	struct snmp_cnv *cnv;
-	
+
 	cnv = snmp_conv;
-	
+
 	while (cnv->syntax != -1) {
 		if (cnv->tag == tag && cnv->class == cls) {
 			*syntax = cnv->syntax;
@@ -662,7 +662,7 @@
 }
 
 static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
-                                        struct snmp_object **obj)
+					struct snmp_object **obj)
 {
 	unsigned int cls, con, tag, len, idlen;
 	unsigned short type;
@@ -670,41 +670,41 @@
 	unsigned long *lp, *id;
 	unsigned long ul;
 	long l;
-	
+
 	*obj = NULL;
 	id = NULL;
-	
+
 	if (!asn1_header_decode(ctx, &eoc, &cls, &con, &tag))
 		return 0;
-		
+
 	if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
 		return 0;
-	
+
 	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
 		return 0;
-	
+
 	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
 		return 0;
-	
+
 	if (!asn1_oid_decode(ctx, end, &id, &idlen))
 		return 0;
-		
+
 	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) {
 		kfree(id);
 		return 0;
 	}
-	
+
 	if (con != ASN1_PRI) {
 		kfree(id);
 		return 0;
 	}
-	
+
 	type = 0;
 	if (!snmp_tag_cls2syntax(tag, cls, &type)) {
 		kfree(id);
 		return 0;
 	}
-	
+
 	l = 0;
 	switch (type) {
 		case SNMP_INTEGER:
@@ -714,7 +714,7 @@
 				return 0;
 			}
 			*obj = kmalloc(sizeof(struct snmp_object) + len,
-			               GFP_ATOMIC);
+				       GFP_ATOMIC);
 			if (*obj == NULL) {
 				kfree(id);
 				if (net_ratelimit())
@@ -730,7 +730,7 @@
 				return 0;
 			}
 			*obj = kmalloc(sizeof(struct snmp_object) + len,
-			               GFP_ATOMIC);
+				       GFP_ATOMIC);
 			if (*obj == NULL) {
 				kfree(id);
 				if (net_ratelimit())
@@ -818,12 +818,12 @@
 			kfree(id);
 			return 0;
 	}
-	
+
 	(*obj)->syntax_len = len;
 	(*obj)->type = type;
 	(*obj)->id = id;
 	(*obj)->id_len = idlen;
-	
+
 	if (!asn1_eoc_decode(ctx, eoc)) {
 		kfree(id);
 		kfree(*obj);
@@ -834,49 +834,49 @@
 }
 
 static unsigned char snmp_request_decode(struct asn1_ctx *ctx,
-                                         struct snmp_request *request)
+					 struct snmp_request *request)
 {
 	unsigned int cls, con, tag;
 	unsigned char *end;
-	
+
 	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
 		return 0;
-		
+
 	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
 		return 0;
-		
+
 	if (!asn1_ulong_decode(ctx, end, &request->id))
 		return 0;
-		
+
 	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
 		return 0;
-		
+
 	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
 		return 0;
-		
+
 	if (!asn1_uint_decode(ctx, end, &request->error_status))
 		return 0;
-		
+
 	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
 		return 0;
-		
+
 	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
 		return 0;
-		
+
 	if (!asn1_uint_decode(ctx, end, &request->error_index))
 		return 0;
-	
+
 	return 1;
 }
 
-/* 
+/*
  * Fast checksum update for possibly oddly-aligned UDP byte, from the
  * code example in the draft.
  */
 static void fast_csum(__sum16 *csum,
-                      const unsigned char *optr,
-                      const unsigned char *nptr,
-                      int offset)
+		      const unsigned char *optr,
+		      const unsigned char *nptr,
+		      int offset)
 {
 	unsigned char s[4];
 
@@ -893,30 +893,30 @@
 	*csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
 }
 
-/* 
+/*
  * Mangle IP address.
  * 	- begin points to the start of the snmp messgae
  *      - addr points to the start of the address
  */
 static inline void mangle_address(unsigned char *begin,
-                                  unsigned char *addr,
-                                  const struct oct1_map *map,
-                                  __sum16 *check)
+				  unsigned char *addr,
+				  const struct oct1_map *map,
+				  __sum16 *check)
 {
 	if (map->from == NOCT1(addr)) {
 		u_int32_t old;
-		
+
 		if (debug)
 			memcpy(&old, (unsigned char *)addr, sizeof(old));
-			
+
 		*addr = map->to;
-		
+
 		/* Update UDP checksum if being used */
 		if (*check) {
 			fast_csum(check,
-			          &map->from, &map->to, addr - begin);
+				  &map->from, &map->to, addr - begin);
 		}
-		
+
 		if (debug)
 			printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "
 			       "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));
@@ -924,66 +924,66 @@
 }
 
 static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
-                                      struct snmp_v1_trap *trap,
-                                      const struct oct1_map *map,
-                                      __sum16 *check)
+				      struct snmp_v1_trap *trap,
+				      const struct oct1_map *map,
+				      __sum16 *check)
 {
 	unsigned int cls, con, tag, len;
 	unsigned char *end;
 
 	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
 		return 0;
-		
+
 	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
 		return 0;
-	
+
 	if (!asn1_oid_decode(ctx, end, &trap->id, &trap->id_len))
 		return 0;
-		
+
 	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
 		goto err_id_free;
 
 	if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
 	      (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)))
 		goto err_id_free;
-	
+
 	if (!asn1_octets_decode(ctx, end, (unsigned char **)&trap->ip_address, &len))
 		goto err_id_free;
-	
+
 	/* IPv4 only */
 	if (len != 4)
 		goto err_addr_free;
-	
+
 	mangle_address(ctx->begin, ctx->pointer - 4, map, check);
-	
+
 	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
 		goto err_addr_free;
-		
+
 	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
 		goto err_addr_free;
-		
+
 	if (!asn1_uint_decode(ctx, end, &trap->general))
 		goto err_addr_free;
-		
+
 	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
 		goto err_addr_free;
-	
+
 	if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
 		goto err_addr_free;
-		
+
 	if (!asn1_uint_decode(ctx, end, &trap->specific))
 		goto err_addr_free;
-		
+
 	if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
 		goto err_addr_free;
-		
+
 	if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
 	      (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT)))
 		goto err_addr_free;
-		
+
 	if (!asn1_ulong_decode(ctx, end, &trap->time))
 		goto err_addr_free;
-		
+
 	return 1;
 
 err_addr_free:
@@ -1004,7 +1004,7 @@
 static void hex_dump(unsigned char *buf, size_t len)
 {
 	size_t i;
-	
+
 	for (i = 0; i < len; i++) {
 		if (i && !(i % 16))
 			printk("\n");
@@ -1018,30 +1018,30 @@
  * (And this is the fucking 'basic' method).
  */
 static int snmp_parse_mangle(unsigned char *msg,
-                             u_int16_t len,
-                             const struct oct1_map *map,
-                             __sum16 *check)
+			     u_int16_t len,
+			     const struct oct1_map *map,
+			     __sum16 *check)
 {
 	unsigned char *eoc, *end;
 	unsigned int cls, con, tag, vers, pdutype;
 	struct asn1_ctx ctx;
 	struct asn1_octstr comm;
 	struct snmp_object **obj;
-	
+
 	if (debug > 1)
 		hex_dump(msg, len);
 
 	asn1_open(&ctx, msg, len);
-	
-	/* 
+
+	/*
 	 * Start of SNMP message.
 	 */
 	if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
 		return 0;
 	if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
 		return 0;
-	
-	/* 
+
+	/*
 	 * Version 1 or 2 handled.
 	 */
 	if (!asn1_header_decode(&ctx, &end, &cls, &con, &tag))
@@ -1054,7 +1054,7 @@
 		printk(KERN_DEBUG "bsalg: snmp version: %u\n", vers + 1);
 	if (vers > 1)
 		return 1;
-	
+
 	/*
 	 * Community.
 	 */
@@ -1066,14 +1066,14 @@
 		return 0;
 	if (debug > 1) {
 		unsigned int i;
-		
+
 		printk(KERN_DEBUG "bsalg: community: ");
 		for (i = 0; i < comm.len; i++)
 			printk("%c", comm.data[i]);
 		printk("\n");
 	}
 	kfree(comm.data);
-	
+
 	/*
 	 * PDU type
 	 */
@@ -1092,7 +1092,7 @@
 			[SNMP_PDU_INFORM] = "inform",
 			[SNMP_PDU_TRAP2] = "trapv2"
 		};
-		
+
 		if (pdutype > SNMP_PDU_TRAP2)
 			printk(KERN_DEBUG "bsalg: bad pdu type %u\n", pdutype);
 		else
@@ -1101,56 +1101,56 @@
 	if (pdutype != SNMP_PDU_RESPONSE &&
 	    pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2)
 		return 1;
-	
+
 	/*
 	 * Request header or v1 trap
 	 */
 	if (pdutype == SNMP_PDU_TRAP1) {
 		struct snmp_v1_trap trap;
 		unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check);
-		
+
 		if (ret) {
 			kfree(trap.id);
 			kfree((unsigned long *)trap.ip_address);
-		} else 
+		} else
 			return ret;
-		
+
 	} else {
 		struct snmp_request req;
-		
+
 		if (!snmp_request_decode(&ctx, &req))
 			return 0;
-			
+
 		if (debug > 1)
 			printk(KERN_DEBUG "bsalg: request: id=0x%lx error_status=%u "
 			"error_index=%u\n", req.id, req.error_status,
 			req.error_index);
 	}
-	
+
 	/*
 	 * Loop through objects, look for IP addresses to mangle.
 	 */
 	if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
 		return 0;
-		
+
 	if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
 		return 0;
-	
+
 	obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
 	if (obj == NULL) {
 		if (net_ratelimit())
 			printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__);
-		return 0;	
+		return 0;
 	}
 
 	while (!asn1_eoc_decode(&ctx, eoc)) {
 		unsigned int i;
-		
+
 		if (!snmp_object_decode(&ctx, obj)) {
 			if (*obj) {
 				kfree((*obj)->id);
 				kfree(*obj);
-			}	
+			}
 			kfree(obj);
 			return 0;
 		}
@@ -1163,20 +1163,20 @@
 				printk("%lu", (*obj)->id[i]);
 			}
 			printk(": type=%u\n", (*obj)->type);
-			
+
 		}
 
 		if ((*obj)->type == SNMP_IPADDR)
 			mangle_address(ctx.begin, ctx.pointer - 4 , map, check);
-		
+
 		kfree((*obj)->id);
 		kfree(*obj);
 	}
 	kfree(obj);
-	
+
 	if (!asn1_eoc_decode(&ctx, eoc))
 		return 0;
-		
+
 	return 1;
 }
 
@@ -1186,12 +1186,12 @@
  *
  *****************************************************************************/
 
-/* 
+/*
  * SNMP translation routine.
  */
 static int snmp_translate(struct ip_conntrack *ct,
-                          enum ip_conntrack_info ctinfo,
-                          struct sk_buff **pskb)
+			  enum ip_conntrack_info ctinfo,
+			  struct sk_buff **pskb)
 {
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
@@ -1213,12 +1213,12 @@
 		map.from = NOCT1(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
 		map.to = NOCT1(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip);
 	}
-	
+
 	if (map.from == map.to)
 		return NF_ACCEPT;
-	
+
 	if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),
-	                       paylen, &map, &udph->check)) {
+			       paylen, &map, &udph->check)) {
 		if (net_ratelimit())
 			printk(KERN_WARNING "bsalg: parser failed\n");
 		return NF_DROP;
@@ -1247,7 +1247,7 @@
 	if (!(ct->status & IPS_NAT_MASK))
 		return NF_ACCEPT;
 
-	/* 
+	/*
 	 * Make sure the packet length is ok.  So far, we were only guaranteed
 	 * to have a valid length IP header plus 8 bytes, which means we have
 	 * enough room for a UDP header.  Just verify the UDP length field so we
@@ -1305,7 +1305,7 @@
  * Module stuff.
  *
  *****************************************************************************/
- 
+
 static int __init ip_nat_snmp_basic_init(void)
 {
 	int ret = 0;
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index ad66328..adf25f9 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -81,7 +81,7 @@
 	}
 }
 #endif
-		
+
 static unsigned int
 ip_nat_fn(unsigned int hooknum,
 	  struct sk_buff **pskb,
@@ -107,8 +107,8 @@
 	   protocol. 8) --RR */
 	if (!ct) {
 		/* Exception: ICMP redirect to new connection (not in
-                   hash table yet).  We must not let this through, in
-                   case we're doing NAT to the same network. */
+		   hash table yet).  We must not let this through, in
+		   case we're doing NAT to the same network. */
 		if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
 			struct icmphdr _hdr, *hp;
 
@@ -148,7 +148,7 @@
 			if (unlikely(is_confirmed(ct)))
 				/* NAT module was loaded late */
 				ret = alloc_null_binding_confirmed(ct, info,
-				                                   hooknum);
+								   hooknum);
 			else if (hooknum == NF_IP_LOCAL_IN)
 				/* LOCAL_IN hook doesn't have a chain!  */
 				ret = alloc_null_binding(ct, info, hooknum);
@@ -179,10 +179,10 @@
 
 static unsigned int
 ip_nat_in(unsigned int hooknum,
-          struct sk_buff **pskb,
-          const struct net_device *in,
-          const struct net_device *out,
-          int (*okfn)(struct sk_buff *))
+	  struct sk_buff **pskb,
+	  const struct net_device *in,
+	  const struct net_device *out,
+	  int (*okfn)(struct sk_buff *))
 {
 	unsigned int ret;
 	__be32 daddr = (*pskb)->nh.iph->daddr;
@@ -277,9 +277,9 @@
 
 	ct = ip_conntrack_get(*pskb, &ctinfo);
 	if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
-	        DEBUGP("ip_nat_standalone: adjusting sequence number\n");
-	        if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
-	                return NF_DROP;
+		DEBUGP("ip_nat_standalone: adjusting sequence number\n");
+		if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
+			return NF_DROP;
 	}
 	return NF_ACCEPT;
 }
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index cd520df..a14798a 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -11,13 +11,13 @@
  *
  * 2000-03-27: Simplified code (thanks to Andi Kleen for clues).
  * 2000-05-20: Fixed notifier problems (following Miguel Freitas' report).
- * 2000-06-19: Fixed so nfmark is copied to metadata (reported by Sebastian 
+ * 2000-06-19: Fixed so nfmark is copied to metadata (reported by Sebastian
  *             Zander).
  * 2000-08-01: Added Nick Williams' MAC support.
  * 2002-06-25: Code cleanup.
  * 2005-01-10: Added /proc counter for dropped packets; fixed so
- *             packets aren't delivered to user space if they're going 
- *             to be dropped. 
+ *             packets aren't delivered to user space if they're going
+ *             to be dropped.
  * 2005-05-26: local_bh_{disable,enable} around nf_reinject (Harald Welte)
  *
  */
@@ -97,7 +97,7 @@
 
 	list_for_each_prev(p, &queue_list) {
 		struct ipq_queue_entry *entry = (struct ipq_queue_entry *)p;
-		
+
 		if (!cmpfn || cmpfn(entry, data))
 			return entry;
 	}
@@ -129,7 +129,7 @@
 __ipq_flush(int verdict)
 {
 	struct ipq_queue_entry *entry;
-	
+
 	while ((entry = __ipq_find_dequeue_entry(NULL, 0)))
 		ipq_issue_verdict(entry, verdict);
 }
@@ -138,21 +138,21 @@
 __ipq_set_mode(unsigned char mode, unsigned int range)
 {
 	int status = 0;
-	
+
 	switch(mode) {
 	case IPQ_COPY_NONE:
 	case IPQ_COPY_META:
 		copy_mode = mode;
 		copy_range = 0;
 		break;
-		
+
 	case IPQ_COPY_PACKET:
 		copy_mode = mode;
 		copy_range = range;
 		if (copy_range > 0xFFFF)
 			copy_range = 0xFFFF;
 		break;
-		
+
 	default:
 		status = -EINVAL;
 
@@ -173,7 +173,7 @@
 ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data)
 {
 	struct ipq_queue_entry *entry;
-	
+
 	write_lock_bh(&queue_lock);
 	entry = __ipq_find_dequeue_entry(cmpfn, data);
 	write_unlock_bh(&queue_lock);
@@ -199,14 +199,14 @@
 	struct nlmsghdr *nlh;
 
 	read_lock_bh(&queue_lock);
-	
+
 	switch (copy_mode) {
 	case IPQ_COPY_META:
 	case IPQ_COPY_NONE:
 		size = NLMSG_SPACE(sizeof(*pmsg));
 		data_len = 0;
 		break;
-	
+
 	case IPQ_COPY_PACKET:
 		if ((entry->skb->ip_summed == CHECKSUM_PARTIAL ||
 		     entry->skb->ip_summed == CHECKSUM_COMPLETE) &&
@@ -218,10 +218,10 @@
 			data_len = entry->skb->len;
 		else
 			data_len = copy_range;
-		
+
 		size = NLMSG_SPACE(sizeof(*pmsg) + data_len);
 		break;
-	
+
 	default:
 		*errp = -EINVAL;
 		read_unlock_bh(&queue_lock);
@@ -233,7 +233,7 @@
 	skb = alloc_skb(size, GFP_ATOMIC);
 	if (!skb)
 		goto nlmsg_failure;
-		
+
 	old_tail= skb->tail;
 	nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh));
 	pmsg = NLMSG_DATA(nlh);
@@ -246,29 +246,29 @@
 	pmsg->mark            = entry->skb->mark;
 	pmsg->hook            = entry->info->hook;
 	pmsg->hw_protocol     = entry->skb->protocol;
-	
+
 	if (entry->info->indev)
 		strcpy(pmsg->indev_name, entry->info->indev->name);
 	else
 		pmsg->indev_name[0] = '\0';
-	
+
 	if (entry->info->outdev)
 		strcpy(pmsg->outdev_name, entry->info->outdev->name);
 	else
 		pmsg->outdev_name[0] = '\0';
-	
+
 	if (entry->info->indev && entry->skb->dev) {
 		pmsg->hw_type = entry->skb->dev->type;
 		if (entry->skb->dev->hard_header_parse)
 			pmsg->hw_addrlen =
 				entry->skb->dev->hard_header_parse(entry->skb,
-				                                   pmsg->hw_addr);
+								   pmsg->hw_addr);
 	}
-	
+
 	if (data_len)
 		if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len))
 			BUG();
-		
+
 	nlh->nlmsg_len = skb->tail - old_tail;
 	return skb;
 
@@ -303,26 +303,26 @@
 	nskb = ipq_build_packet_message(entry, &status);
 	if (nskb == NULL)
 		goto err_out_free;
-		
+
 	write_lock_bh(&queue_lock);
-	
+
 	if (!peer_pid)
-		goto err_out_free_nskb; 
+		goto err_out_free_nskb;
 
 	if (queue_total >= queue_maxlen) {
-                queue_dropped++;
+		queue_dropped++;
 		status = -ENOSPC;
 		if (net_ratelimit())
-		          printk (KERN_WARNING "ip_queue: full at %d entries, "
+			  printk (KERN_WARNING "ip_queue: full at %d entries, "
 				  "dropping packets(s). Dropped: %d\n", queue_total,
 				  queue_dropped);
 		goto err_out_free_nskb;
 	}
 
- 	/* netlink_unicast will either free the nskb or attach it to a socket */ 
+	/* netlink_unicast will either free the nskb or attach it to a socket */
 	status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
 	if (status < 0) {
-	        queue_user_dropped++;
+		queue_user_dropped++;
 		goto err_out_unlock;
 	}
 
@@ -332,8 +332,8 @@
 	return status;
 
 err_out_free_nskb:
-	kfree_skb(nskb); 
-	
+	kfree_skb(nskb);
+
 err_out_unlock:
 	write_unlock_bh(&queue_lock);
 
@@ -359,11 +359,11 @@
 			return -EINVAL;
 		if (diff > skb_tailroom(e->skb)) {
 			struct sk_buff *newskb;
-			
+
 			newskb = skb_copy_expand(e->skb,
-			                         skb_headroom(e->skb),
-			                         diff,
-			                         GFP_ATOMIC);
+						 skb_headroom(e->skb),
+						 diff,
+						 GFP_ATOMIC);
 			if (newskb == NULL) {
 				printk(KERN_WARNING "ip_queue: OOM "
 				      "in mangle, dropping packet\n");
@@ -403,11 +403,11 @@
 		return -ENOENT;
 	else {
 		int verdict = vmsg->value;
-		
+
 		if (vmsg->data_len && vmsg->data_len == len)
 			if (ipq_mangle_ipv4(vmsg, entry) < 0)
 				verdict = NF_DROP;
-		
+
 		ipq_issue_verdict(entry, verdict);
 		return 0;
 	}
@@ -426,7 +426,7 @@
 
 static int
 ipq_receive_peer(struct ipq_peer_msg *pmsg,
-                 unsigned char type, unsigned int len)
+		 unsigned char type, unsigned int len)
 {
 	int status = 0;
 
@@ -436,15 +436,15 @@
 	switch (type) {
 	case IPQM_MODE:
 		status = ipq_set_mode(pmsg->msg.mode.value,
-		                      pmsg->msg.mode.range);
+				      pmsg->msg.mode.range);
 		break;
-		
+
 	case IPQM_VERDICT:
 		if (pmsg->msg.verdict.value > NF_MAX_VERDICT)
 			status = -EINVAL;
 		else
 			status = ipq_set_verdict(&pmsg->msg.verdict,
-			                         len - sizeof(*pmsg));
+						 len - sizeof(*pmsg));
 			break;
 	default:
 		status = -EINVAL;
@@ -468,7 +468,7 @@
 			return 1;
 		if (entry->skb->nf_bridge->physoutdev &&
 		    entry->skb->nf_bridge->physoutdev->ifindex == ifindex)
-		    	return 1;
+			return 1;
 	}
 #endif
 	return 0;
@@ -478,7 +478,7 @@
 ipq_dev_drop(int ifindex)
 {
 	struct ipq_queue_entry *entry;
-	
+
 	while ((entry = ipq_find_dequeue_entry(dev_cmp, ifindex)) != NULL)
 		ipq_issue_verdict(entry, NF_DROP);
 }
@@ -502,25 +502,25 @@
 
 	pid = nlh->nlmsg_pid;
 	flags = nlh->nlmsg_flags;
-	
+
 	if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI)
 		RCV_SKB_FAIL(-EINVAL);
-		
+
 	if (flags & MSG_TRUNC)
 		RCV_SKB_FAIL(-ECOMM);
-		
+
 	type = nlh->nlmsg_type;
 	if (type < NLMSG_NOOP || type >= IPQM_MAX)
 		RCV_SKB_FAIL(-EINVAL);
-		
+
 	if (type <= IPQM_BASE)
 		return;
-		
+
 	if (security_netlink_recv(skb, CAP_NET_ADMIN))
 		RCV_SKB_FAIL(-EPERM);
-	
+
 	write_lock_bh(&queue_lock);
-	
+
 	if (peer_pid) {
 		if (peer_pid != pid) {
 			write_unlock_bh(&queue_lock);
@@ -530,17 +530,17 @@
 		net_enable_timestamp();
 		peer_pid = pid;
 	}
-		
+
 	write_unlock_bh(&queue_lock);
-	
+
 	status = ipq_receive_peer(NLMSG_DATA(nlh), type,
-	                          nlmsglen - NLMSG_LENGTH(0));
+				  nlmsglen - NLMSG_LENGTH(0));
 	if (status < 0)
 		RCV_SKB_FAIL(status);
-		
+
 	if (flags & NLM_F_ACK)
 		netlink_ack(skb, nlh, 0);
-        return;
+	return;
 }
 
 static void
@@ -550,19 +550,19 @@
 	unsigned int qlen;
 
 	mutex_lock(&ipqnl_mutex);
-			
+
 	for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
 		skb = skb_dequeue(&sk->sk_receive_queue);
 		ipq_rcv_skb(skb);
 		kfree_skb(skb);
 	}
-		
+
 	mutex_unlock(&ipqnl_mutex);
 }
 
 static int
 ipq_rcv_dev_event(struct notifier_block *this,
-                  unsigned long event, void *ptr)
+		  unsigned long event, void *ptr)
 {
 	struct net_device *dev = ptr;
 
@@ -578,7 +578,7 @@
 
 static int
 ipq_rcv_nl_event(struct notifier_block *this,
-                 unsigned long event, void *ptr)
+		 unsigned long event, void *ptr)
 {
 	struct netlink_notify *n = ptr;
 
@@ -607,7 +607,7 @@
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
- 	{ .ctl_name = 0 }
+	{ .ctl_name = 0 }
 };
 
 static ctl_table ipq_dir_table[] = {
@@ -637,25 +637,25 @@
 	int len;
 
 	read_lock_bh(&queue_lock);
-	
+
 	len = sprintf(buffer,
-	              "Peer PID          : %d\n"
-	              "Copy mode         : %hu\n"
-	              "Copy range        : %u\n"
-	              "Queue length      : %u\n"
-	              "Queue max. length : %u\n"
+		      "Peer PID          : %d\n"
+		      "Copy mode         : %hu\n"
+		      "Copy range        : %u\n"
+		      "Queue length      : %u\n"
+		      "Queue max. length : %u\n"
 		      "Queue dropped     : %u\n"
 		      "Netlink dropped   : %u\n",
-	              peer_pid,
-	              copy_mode,
-	              copy_range,
-	              queue_total,
-	              queue_maxlen,
+		      peer_pid,
+		      copy_mode,
+		      copy_range,
+		      queue_total,
+		      queue_maxlen,
 		      queue_dropped,
 		      queue_user_dropped);
 
 	read_unlock_bh(&queue_lock);
-	
+
 	*start = buffer + offset;
 	len -= offset;
 	if (len > length)
@@ -675,7 +675,7 @@
 {
 	int status = -ENOMEM;
 	struct proc_dir_entry *proc;
-	
+
 	netlink_register_notifier(&ipq_nl_notifier);
 	ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
 				      THIS_MODULE);
@@ -691,10 +691,10 @@
 		printk(KERN_ERR "ip_queue: failed to create proc entry\n");
 		goto cleanup_ipqnl;
 	}
-	
+
 	register_netdevice_notifier(&ipq_dev_notifier);
-	ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
-	
+	ipq_sysctl_header = register_sysctl_table(ipq_root_table);
+
 	status = nf_register_queue_handler(PF_INET, &nfqh);
 	if (status < 0) {
 		printk(KERN_ERR "ip_queue: failed to register queue handler\n");
@@ -706,12 +706,12 @@
 	unregister_sysctl_table(ipq_sysctl_header);
 	unregister_netdevice_notifier(&ipq_dev_notifier);
 	proc_net_remove(IPQ_PROC_FS_NAME);
-	
+
 cleanup_ipqnl:
 	sock_release(ipqnl->sk_socket);
 	mutex_lock(&ipqnl_mutex);
 	mutex_unlock(&ipqnl_mutex);
-	
+
 cleanup_netlink_notifier:
 	netlink_unregister_notifier(&ipq_nl_notifier);
 	return status;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index fc1f153..50cc4b9 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -216,7 +216,7 @@
 	     unsigned int hook,
 	     const struct net_device *in,
 	     const struct net_device *out,
-	     struct ipt_table *table)
+	     struct xt_table *table)
 {
 	static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
 	u_int16_t offset;
@@ -297,7 +297,7 @@
 				e = get_entry(table_base, v);
 			} else {
 				/* Targets which reenter must return
-                                   abs. verdicts */
+				   abs. verdicts */
 #ifdef CONFIG_NETFILTER_DEBUG
 				((struct ipt_entry *)table_base)->comefrom
 					= 0xeeeeeeec;
@@ -507,7 +507,7 @@
 static inline int check_match(struct ipt_entry_match *m, const char *name,
 				const struct ipt_ip *ip, unsigned int hookmask)
 {
-	struct ipt_match *match;
+	struct xt_match *match;
 	int ret;
 
 	match = m->u.kernel.match;
@@ -531,7 +531,7 @@
 	    unsigned int hookmask,
 	    unsigned int *i)
 {
-	struct ipt_match *match;
+	struct xt_match *match;
 	int ret;
 
 	match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
@@ -556,9 +556,9 @@
 
 static inline int check_target(struct ipt_entry *e, const char *name)
 {
- 	struct ipt_entry_target *t;
- 	struct ipt_target *target;
- 	int ret;
+	struct ipt_entry_target *t;
+	struct xt_target *target;
+	int ret;
 
 	t = ipt_get_target(e);
 	target = t->u.kernel.target;
@@ -580,7 +580,7 @@
 	    unsigned int *i)
 {
 	struct ipt_entry_target *t;
-	struct ipt_target *target;
+	struct xt_target *target;
 	int ret;
 	unsigned int j;
 
@@ -652,7 +652,7 @@
 	}
 
 	/* FIXME: underflows must be unconditional, standard verdicts
-           < 0 (not IPT_RETURN). --RR */
+	   < 0 (not IPT_RETURN). --RR */
 
 	/* Clear counters and comefrom */
 	e->counters = ((struct xt_counters) { 0, 0 });
@@ -818,7 +818,7 @@
 	}
 }
 
-static inline struct xt_counters * alloc_counters(struct ipt_table *table)
+static inline struct xt_counters * alloc_counters(struct xt_table *table)
 {
 	unsigned int countersize;
 	struct xt_counters *counters;
@@ -843,7 +843,7 @@
 
 static int
 copy_entries_to_user(unsigned int total_size,
-		     struct ipt_table *table,
+		     struct xt_table *table,
 		     void __user *userptr)
 {
 	unsigned int off, num;
@@ -1046,7 +1046,7 @@
 static int get_info(void __user *user, int *len, int compat)
 {
 	char name[IPT_TABLE_MAXNAMELEN];
-	struct ipt_table *t;
+	struct xt_table *t;
 	int ret;
 
 	if (*len != sizeof(struct ipt_getinfo)) {
@@ -1107,7 +1107,7 @@
 {
 	int ret;
 	struct ipt_get_entries get;
-	struct ipt_table *t;
+	struct xt_table *t;
 
 	if (*len < sizeof(get)) {
 		duprintf("get_entries: %u < %d\n", *len,
@@ -1151,7 +1151,7 @@
 		void __user *counters_ptr)
 {
 	int ret;
-	struct ipt_table *t;
+	struct xt_table *t;
 	struct xt_table_info *oldinfo;
 	struct xt_counters *counters;
 	void *loc_cpu_old_entry;
@@ -1302,7 +1302,7 @@
 	char *name;
 	int size;
 	void *ptmp;
-	struct ipt_table *t;
+	struct xt_table *t;
 	struct xt_table_info *private;
 	int ret = 0;
 	void *loc_cpu_entry;
@@ -1437,7 +1437,7 @@
 	    unsigned int hookmask,
 	    int *size, int *i)
 {
-	struct ipt_match *match;
+	struct xt_match *match;
 
 	match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
 						   m->u.user.revision),
@@ -1466,7 +1466,7 @@
 			   const char *name)
 {
 	struct ipt_entry_target *t;
-	struct ipt_target *target;
+	struct xt_target *target;
 	unsigned int entry_offset;
 	int ret, off, h, j;
 
@@ -1550,7 +1550,7 @@
 	struct xt_table_info *newinfo, unsigned char *base)
 {
 	struct ipt_entry_target *t;
-	struct ipt_target *target;
+	struct xt_target *target;
 	struct ipt_entry *de;
 	unsigned int origsize;
 	int ret, h;
@@ -1795,7 +1795,7 @@
 };
 
 static int compat_copy_entries_to_user(unsigned int total_size,
-		     struct ipt_table *table, void __user *userptr)
+		     struct xt_table *table, void __user *userptr)
 {
 	unsigned int off, num;
 	struct compat_ipt_entry e;
@@ -1869,7 +1869,7 @@
 {
 	int ret;
 	struct compat_ipt_get_entries get;
-	struct ipt_table *t;
+	struct xt_table *t;
 
 
 	if (*len < sizeof(get)) {
@@ -2052,12 +2052,12 @@
 	return 0;
 }
 
-void ipt_unregister_table(struct ipt_table *table)
+void ipt_unregister_table(struct xt_table *table)
 {
 	struct xt_table_info *private;
 	void *loc_cpu_entry;
 
- 	private = xt_unregister_table(table);
+	private = xt_unregister_table(table);
 
 	/* Decrease module usage counts and free resources */
 	loc_cpu_entry = private->entries[raw_smp_processor_id()];
@@ -2124,7 +2124,7 @@
 }
 
 /* The built-in targets: standard (NULL) and error. */
-static struct ipt_target ipt_standard_target = {
+static struct xt_target ipt_standard_target = {
 	.name		= IPT_STANDARD_TARGET,
 	.targetsize	= sizeof(int),
 	.family		= AF_INET,
@@ -2135,7 +2135,7 @@
 #endif
 };
 
-static struct ipt_target ipt_error_target = {
+static struct xt_target ipt_error_target = {
 	.name		= IPT_ERROR_TARGET,
 	.target		= ipt_error,
 	.targetsize	= IPT_FUNCTION_MAXNAMELEN,
@@ -2158,7 +2158,7 @@
 #endif
 };
 
-static struct ipt_match icmp_matchstruct = {
+static struct xt_match icmp_matchstruct = {
 	.name		= "icmp",
 	.match		= icmp_match,
 	.matchsize	= sizeof(struct ipt_icmp),
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index b1c1116..e965b33 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -1,4 +1,4 @@
-/* Cluster IP hashmark target 
+/* Cluster IP hashmark target
  * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
  * based on ideas of Fabio Olive Leite <olive@unixforge.org>
  *
@@ -26,6 +26,7 @@
 
 #include <linux/netfilter_arp.h>
 
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
 #include <net/netfilter/nf_conntrack_compat.h>
@@ -69,7 +70,7 @@
 static DEFINE_RWLOCK(clusterip_lock);
 
 #ifdef CONFIG_PROC_FS
-static struct file_operations clusterip_proc_fops;
+static const struct file_operations clusterip_proc_fops;
 static struct proc_dir_entry *clusterip_procdir;
 #endif
 
@@ -122,7 +123,7 @@
 	struct list_head *pos;
 
 	list_for_each(pos, &clusterip_configs) {
-		struct clusterip_config *c = list_entry(pos, 
+		struct clusterip_config *c = list_entry(pos,
 					struct clusterip_config, list);
 		if (c->clusterip == clusterip) {
 			return c;
@@ -228,7 +229,7 @@
 	if (nodenum == 0 ||
 	    nodenum > c->num_total_nodes)
 		return 1;
-		
+
 	if (test_and_clear_bit(nodenum - 1, &c->local_nodes))
 		return 0;
 
@@ -247,6 +248,7 @@
 	switch (iph->protocol) {
 	case IPPROTO_TCP:
 	case IPPROTO_UDP:
+	case IPPROTO_UDPLITE:
 	case IPPROTO_SCTP:
 	case IPPROTO_DCCP:
 	case IPPROTO_ICMP:
@@ -268,7 +270,7 @@
 				      config->hash_initval);
 		break;
 	case CLUSTERIP_HASHMODE_SIP_SPT:
-		hashval = jhash_2words(ntohl(iph->saddr), sport, 
+		hashval = jhash_2words(ntohl(iph->saddr), sport,
 				       config->hash_initval);
 		break;
 	case CLUSTERIP_HASHMODE_SIP_SPT_DPT:
@@ -295,8 +297,8 @@
 	return test_bit(hash - 1, &config->local_nodes);
 }
 
-/*********************************************************************** 
- * IPTABLES TARGET 
+/***********************************************************************
+ * IPTABLES TARGET
  ***********************************************************************/
 
 static unsigned int
@@ -319,7 +321,7 @@
 	if (mark == NULL) {
 		printk(KERN_ERR "CLUSTERIP: no conntrack!\n");
 			/* FIXME: need to drop invalid ones, since replies
-			 * to outgoing connections of other nodes will be 
+			 * to outgoing connections of other nodes will be
 			 * marked as INVALID */
 		return NF_DROP;
 	}
@@ -327,11 +329,11 @@
 	/* special case: ICMP error handling. conntrack distinguishes between
 	 * error messages (RELATED) and information requests (see below) */
 	if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
-	    && (ctinfo == IP_CT_RELATED 
+	    && (ctinfo == IP_CT_RELATED
 		|| ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
-		return IPT_CONTINUE;
+		return XT_CONTINUE;
 
-	/* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, 
+	/* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO,
 	 * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here
 	 * on, which all have an ID field [relevant for hashing]. */
 
@@ -367,15 +369,15 @@
 	 * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
 	(*pskb)->pkt_type = PACKET_HOST;
 
-	return IPT_CONTINUE;
+	return XT_CONTINUE;
 }
 
 static int
 checkentry(const char *tablename,
 	   const void *e_void,
 	   const struct xt_target *target,
-           void *targinfo,
-           unsigned int hook_mask)
+	   void *targinfo,
+	   unsigned int hook_mask)
 {
 	struct ipt_clusterip_tgt_info *cipinfo = targinfo;
 	const struct ipt_entry *e = e_void;
@@ -435,7 +437,7 @@
 				return 0;
 			}
 
-			config = clusterip_config_init(cipinfo, 
+			config = clusterip_config_init(cipinfo,
 							e->ip.dst.s_addr, dev);
 			if (!config) {
 				printk(KERN_WARNING "CLUSTERIP: cannot allocate config\n");
@@ -470,8 +472,9 @@
 	nf_ct_l3proto_module_put(target->family);
 }
 
-static struct ipt_target clusterip_tgt = {
+static struct xt_target clusterip_tgt = {
 	.name		= "CLUSTERIP",
+	.family		= AF_INET,
 	.target		= target,
 	.targetsize	= sizeof(struct ipt_clusterip_tgt_info),
 	.checkentry	= checkentry,
@@ -480,8 +483,8 @@
 };
 
 
-/*********************************************************************** 
- * ARP MANGLING CODE 
+/***********************************************************************
+ * ARP MANGLING CODE
  ***********************************************************************/
 
 /* hardcoded for 48bit ethernet and 32bit ipv4 addresses */
@@ -493,7 +496,7 @@
 } __attribute__ ((packed));
 
 #ifdef CLUSTERIP_DEBUG
-static void arp_print(struct arp_payload *payload) 
+static void arp_print(struct arp_payload *payload)
 {
 #define HBUFFERLEN 30
 	char hbuffer[HBUFFERLEN];
@@ -507,7 +510,7 @@
 	}
 	hbuffer[--k]='\0';
 
-	printk("src %u.%u.%u.%u@%s, dst %u.%u.%u.%u\n", 
+	printk("src %u.%u.%u.%u@%s, dst %u.%u.%u.%u\n",
 		NIPQUAD(payload->src_ip), hbuffer,
 		NIPQUAD(payload->dst_ip));
 }
@@ -537,13 +540,13 @@
 
 	payload = (void *)(arp+1);
 
-	/* if there is no clusterip configuration for the arp reply's 
+	/* if there is no clusterip configuration for the arp reply's
 	 * source ip, we don't want to mangle it */
 	c = clusterip_config_find_get(payload->src_ip, 0);
 	if (!c)
 		return NF_ACCEPT;
 
-	/* normally the linux kernel always replies to arp queries of 
+	/* normally the linux kernel always replies to arp queries of
 	 * addresses on different interfacs.  However, in the CLUSTERIP case
 	 * this wouldn't work, since we didn't subscribe the mcast group on
 	 * other interfaces */
@@ -574,8 +577,8 @@
 	.priority = -1
 };
 
-/*********************************************************************** 
- * PROC DIR HANDLING 
+/***********************************************************************
+ * PROC DIR HANDLING
  ***********************************************************************/
 
 #ifdef CONFIG_PROC_FS
@@ -637,7 +640,7 @@
 {
 	struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
 
-	if (idx->pos != 0) 
+	if (idx->pos != 0)
 		seq_putc(s, ',');
 
 	seq_printf(s, "%u", idx->bit);
@@ -712,7 +715,7 @@
 	return size;
 }
 
-static struct file_operations clusterip_proc_fops = {
+static const struct file_operations clusterip_proc_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = clusterip_proc_open,
 	.read	 = seq_read,
@@ -727,7 +730,7 @@
 {
 	int ret;
 
-	ret = ipt_register_target(&clusterip_tgt);
+	ret = xt_register_target(&clusterip_tgt);
 	if (ret < 0)
 		return ret;
 
@@ -753,7 +756,7 @@
 	nf_unregister_hook(&cip_arp_ops);
 #endif /* CONFIG_PROC_FS */
 cleanup_target:
-	ipt_unregister_target(&clusterip_tgt);
+	xt_unregister_target(&clusterip_tgt);
 	return ret;
 }
 
@@ -765,7 +768,7 @@
 	remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
 #endif
 	nf_unregister_hook(&cip_arp_ops);
-	ipt_unregister_target(&clusterip_tgt);
+	xt_unregister_target(&clusterip_tgt);
 }
 
 module_init(ipt_clusterip_init);
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index b55d670..4f56563 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -1,20 +1,22 @@
 /* iptables module for the IPv4 and TCP ECN bits, Version 1.5
  *
  * (C) 2002 by Harald Welte <laforge@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 
+ * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
  * ipt_ECN.c,v 1.5 2002/08/18 19:36:51 laforge Exp
 */
 
+#include <linux/in.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <net/checksum.h>
 
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_ECN.h>
 
@@ -38,7 +40,7 @@
 		iph->tos &= ~IPT_ECN_IP_MASK;
 		iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
 		nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
-	} 
+	}
 	return 1;
 }
 
@@ -95,15 +97,15 @@
 		if (!set_ect_tcp(pskb, einfo))
 			return NF_DROP;
 
-	return IPT_CONTINUE;
+	return XT_CONTINUE;
 }
 
 static int
 checkentry(const char *tablename,
 	   const void *e_void,
 	   const struct xt_target *target,
-           void *targinfo,
-           unsigned int hook_mask)
+	   void *targinfo,
+	   unsigned int hook_mask)
 {
 	const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo;
 	const struct ipt_entry *e = e_void;
@@ -119,7 +121,7 @@
 		return 0;
 	}
 	if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR))
-	    && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO))) {
+	    && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) {
 		printk(KERN_WARNING "ECN: cannot use TCP operations on a "
 		       "non-tcp rule\n");
 		return 0;
@@ -127,8 +129,9 @@
 	return 1;
 }
 
-static struct ipt_target ipt_ecn_reg = {
+static struct xt_target ipt_ecn_reg = {
 	.name		= "ECN",
+	.family		= AF_INET,
 	.target		= target,
 	.targetsize	= sizeof(struct ipt_ECN_info),
 	.table		= "mangle",
@@ -138,12 +141,12 @@
 
 static int __init ipt_ecn_init(void)
 {
-	return ipt_register_target(&ipt_ecn_reg);
+	return xt_register_target(&ipt_ecn_reg);
 }
 
 static void __exit ipt_ecn_fini(void)
 {
-	ipt_unregister_target(&ipt_ecn_reg);
+	xt_unregister_target(&ipt_ecn_reg);
 }
 
 module_init(ipt_ecn_init);
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index c96de16..d9c37fd 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -20,7 +20,7 @@
 #include <net/route.h>
 
 #include <linux/netfilter.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ipt_LOG.h>
 
 MODULE_LICENSE("GPL");
@@ -289,7 +289,7 @@
 
 		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
-		
+
 		/* Max length: 9 "PROTO=AH " */
 		printk("PROTO=AH ");
 
@@ -334,10 +334,10 @@
 	}
 
 	/* Max length: 15 "UID=4294967295 " */
- 	if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
+	if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
 		read_lock_bh(&skb->sk->sk_callback_lock);
 		if (skb->sk->sk_socket && skb->sk->sk_socket->file)
- 			printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
+			printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
 		read_unlock_bh(&skb->sk->sk_callback_lock);
 	}
 
@@ -431,8 +431,8 @@
 	li.u.log.logflags = loginfo->logflags;
 
 	ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
-	               loginfo->prefix);
-	return IPT_CONTINUE;
+		       loginfo->prefix);
+	return XT_CONTINUE;
 }
 
 static int ipt_log_checkentry(const char *tablename,
@@ -455,8 +455,9 @@
 	return 1;
 }
 
-static struct ipt_target ipt_log_reg = {
+static struct xt_target ipt_log_reg = {
 	.name		= "LOG",
+	.family		= AF_INET,
 	.target		= ipt_log_target,
 	.targetsize	= sizeof(struct ipt_log_info),
 	.checkentry	= ipt_log_checkentry,
@@ -471,22 +472,25 @@
 
 static int __init ipt_log_init(void)
 {
-	if (ipt_register_target(&ipt_log_reg))
-		return -EINVAL;
+	int ret;
+
+	ret = xt_register_target(&ipt_log_reg);
+	if (ret < 0)
+		return ret;
 	if (nf_log_register(PF_INET, &ipt_log_logger) < 0) {
 		printk(KERN_WARNING "ipt_LOG: not logging via system console "
 		       "since somebody else already registered for PF_INET\n");
 		/* we cannot make module load fail here, since otherwise
 		 * iptables userspace would abort */
 	}
-	
+
 	return 0;
 }
 
 static void __exit ipt_log_fini(void)
 {
-	nf_log_unregister_logger(&ipt_log_logger);
-	ipt_unregister_target(&ipt_log_reg);
+	nf_log_unregister(&ipt_log_logger);
+	xt_unregister_target(&ipt_log_reg);
 }
 
 module_init(ipt_log_init);
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index d669685..b5955f3 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -25,7 +25,7 @@
 #else
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
 #endif
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -86,7 +86,7 @@
 	nat = nfct_nat(ct);
 #endif
 	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
-	                    || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
+			    || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
 
 	/* Source address is 0.0.0.0 - locally generated packet that is
 	 * probably not supposed to be masqueraded.
@@ -190,8 +190,9 @@
 	.notifier_call	= masq_inet_event,
 };
 
-static struct ipt_target masquerade = {
+static struct xt_target masquerade = {
 	.name		= "MASQUERADE",
+	.family		= AF_INET,
 	.target		= masquerade_target,
 	.targetsize	= sizeof(struct ip_nat_multi_range_compat),
 	.table		= "nat",
@@ -204,7 +205,7 @@
 {
 	int ret;
 
-	ret = ipt_register_target(&masquerade);
+	ret = xt_register_target(&masquerade);
 
 	if (ret == 0) {
 		/* Register for device down reports */
@@ -218,9 +219,9 @@
 
 static void __exit ipt_masquerade_fini(void)
 {
-	ipt_unregister_target(&masquerade);
+	xt_unregister_target(&masquerade);
 	unregister_netdevice_notifier(&masq_dev_notifier);
-	unregister_inetaddr_notifier(&masq_inet_notifier);	
+	unregister_inetaddr_notifier(&masq_inet_notifier);
 }
 
 module_init(ipt_masquerade_init);
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 9390e90..fd7aaa3 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -15,6 +15,7 @@
 #include <linux/netdevice.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/x_tables.h>
 #ifdef CONFIG_NF_NAT_NEEDED
 #include <net/netfilter/nf_nat_rule.h>
 #else
@@ -88,25 +89,26 @@
 	return ip_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static struct ipt_target target_module = { 
+static struct xt_target target_module = {
 	.name 		= MODULENAME,
-	.target 	= target, 
+	.family		= AF_INET,
+	.target 	= target,
 	.targetsize	= sizeof(struct ip_nat_multi_range_compat),
 	.table		= "nat",
 	.hooks		= (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING) |
 			  (1 << NF_IP_LOCAL_OUT),
 	.checkentry 	= check,
-    	.me 		= THIS_MODULE 
+	.me 		= THIS_MODULE
 };
 
 static int __init ipt_netmap_init(void)
 {
-	return ipt_register_target(&target_module);
+	return xt_register_target(&target_module);
 }
 
 static void __exit ipt_netmap_fini(void)
 {
-	ipt_unregister_target(&target_module);
+	xt_unregister_target(&target_module);
 }
 
 module_init(ipt_netmap_init);
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 462eceb..c2b6b80 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -18,6 +18,7 @@
 #include <net/protocol.h>
 #include <net/checksum.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/x_tables.h>
 #ifdef CONFIG_NF_NAT_NEEDED
 #include <net/netfilter/nf_nat_rule.h>
 #else
@@ -83,7 +84,7 @@
 		struct in_ifaddr *ifa;
 
 		newdst = 0;
-		
+
 		rcu_read_lock();
 		indev = __in_dev_get_rcu((*pskb)->dev);
 		if (indev && (ifa = indev->ifa_list))
@@ -104,8 +105,9 @@
 	return ip_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static struct ipt_target redirect_reg = {
+static struct xt_target redirect_reg = {
 	.name		= "REDIRECT",
+	.family		= AF_INET,
 	.target		= redirect_target,
 	.targetsize	= sizeof(struct ip_nat_multi_range_compat),
 	.table		= "nat",
@@ -116,12 +118,12 @@
 
 static int __init ipt_redirect_init(void)
 {
-	return ipt_register_target(&redirect_reg);
+	return xt_register_target(&redirect_reg);
 }
 
 static void __exit ipt_redirect_fini(void)
 {
-	ipt_unregister_target(&redirect_reg);
+	xt_unregister_target(&redirect_reg);
 }
 
 module_init(ipt_redirect_init);
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index f0319e5..80f739e 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -22,6 +22,7 @@
 #include <net/tcp.h>
 #include <net/route.h>
 #include <net/dst.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_REJECT.h>
 #ifdef CONFIG_BRIDGE_NETFILTER
@@ -56,7 +57,7 @@
 	oth = skb_header_pointer(oldskb, oldskb->nh.iph->ihl * 4,
 				 sizeof(_otcph), &_otcph);
 	if (oth == NULL)
- 		return;
+		return;
 
 	/* No RST for RST. */
 	if (oth->rst)
@@ -79,6 +80,10 @@
 	nskb->mark = 0;
 	skb_init_secmark(nskb);
 
+	skb_shinfo(nskb)->gso_size = 0;
+	skb_shinfo(nskb)->gso_segs = 0;
+	skb_shinfo(nskb)->gso_type = 0;
+
 	tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
 
 	/* Swap source and dest */
@@ -116,7 +121,7 @@
 
 	/* Adjust TCP checksum */
 	tcph->check = 0;
-	tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
+	tcph->check = tcp_v4_check(sizeof(struct tcphdr),
 				   nskb->nh.iph->saddr,
 				   nskb->nh.iph->daddr,
 				   csum_partial((char *)tcph,
@@ -144,7 +149,7 @@
 
 	/* Adjust IP checksum */
 	nskb->nh.iph->check = 0;
-	nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
+	nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
 					   nskb->nh.iph->ihl);
 
 	/* "Never happens" */
@@ -164,7 +169,7 @@
 static inline void send_unreach(struct sk_buff *skb_in, int code)
 {
 	icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
-}	
+}
 
 static unsigned int reject(struct sk_buff **pskb,
 			   const struct net_device *in,
@@ -176,33 +181,33 @@
 	const struct ipt_reject_info *reject = targinfo;
 
 	/* Our naive response construction doesn't deal with IP
-           options, and probably shouldn't try. */
+	   options, and probably shouldn't try. */
 	if ((*pskb)->nh.iph->ihl<<2 != sizeof(struct iphdr))
 		return NF_DROP;
 
 	/* WARNING: This code causes reentry within iptables.
 	   This means that the iptables jump stack is now crap.  We
 	   must return an absolute verdict. --RR */
-    	switch (reject->with) {
-    	case IPT_ICMP_NET_UNREACHABLE:
-    		send_unreach(*pskb, ICMP_NET_UNREACH);
-    		break;
-    	case IPT_ICMP_HOST_UNREACHABLE:
-    		send_unreach(*pskb, ICMP_HOST_UNREACH);
-    		break;
-    	case IPT_ICMP_PROT_UNREACHABLE:
-    		send_unreach(*pskb, ICMP_PROT_UNREACH);
-    		break;
-    	case IPT_ICMP_PORT_UNREACHABLE:
-    		send_unreach(*pskb, ICMP_PORT_UNREACH);
-    		break;
-    	case IPT_ICMP_NET_PROHIBITED:
-    		send_unreach(*pskb, ICMP_NET_ANO);
-    		break;
+	switch (reject->with) {
+	case IPT_ICMP_NET_UNREACHABLE:
+		send_unreach(*pskb, ICMP_NET_UNREACH);
+		break;
+	case IPT_ICMP_HOST_UNREACHABLE:
+		send_unreach(*pskb, ICMP_HOST_UNREACH);
+		break;
+	case IPT_ICMP_PROT_UNREACHABLE:
+		send_unreach(*pskb, ICMP_PROT_UNREACH);
+		break;
+	case IPT_ICMP_PORT_UNREACHABLE:
+		send_unreach(*pskb, ICMP_PORT_UNREACH);
+		break;
+	case IPT_ICMP_NET_PROHIBITED:
+		send_unreach(*pskb, ICMP_NET_ANO);
+		break;
 	case IPT_ICMP_HOST_PROHIBITED:
-    		send_unreach(*pskb, ICMP_HOST_ANO);
-    		break;
-    	case IPT_ICMP_ADMIN_PROHIBITED:
+		send_unreach(*pskb, ICMP_HOST_ANO);
+		break;
+	case IPT_ICMP_ADMIN_PROHIBITED:
 		send_unreach(*pskb, ICMP_PKT_FILTERED);
 		break;
 	case IPT_TCP_RESET:
@@ -221,7 +226,7 @@
 		 void *targinfo,
 		 unsigned int hook_mask)
 {
- 	const struct ipt_reject_info *rejinfo = targinfo;
+	const struct ipt_reject_info *rejinfo = targinfo;
 	const struct ipt_entry *e = e_void;
 
 	if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
@@ -230,7 +235,7 @@
 	} else if (rejinfo->with == IPT_TCP_RESET) {
 		/* Must specify that it's a TCP packet */
 		if (e->ip.proto != IPPROTO_TCP
-		    || (e->ip.invflags & IPT_INV_PROTO)) {
+		    || (e->ip.invflags & XT_INV_PROTO)) {
 			DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n");
 			return 0;
 		}
@@ -238,8 +243,9 @@
 	return 1;
 }
 
-static struct ipt_target ipt_reject_reg = {
+static struct xt_target ipt_reject_reg = {
 	.name		= "REJECT",
+	.family		= AF_INET,
 	.target		= reject,
 	.targetsize	= sizeof(struct ipt_reject_info),
 	.table		= "filter",
@@ -251,12 +257,12 @@
 
 static int __init ipt_reject_init(void)
 {
-	return ipt_register_target(&ipt_reject_reg);
+	return xt_register_target(&ipt_reject_reg);
 }
 
 static void __exit ipt_reject_fini(void)
 {
-	ipt_unregister_target(&ipt_reject_reg);
+	xt_unregister_target(&ipt_reject_reg);
 }
 
 module_init(ipt_reject_init);
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 3dcf294..bd4404e 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -34,6 +34,7 @@
 #include <net/protocol.h>
 #include <net/checksum.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/x_tables.h>
 #ifdef CONFIG_NF_NAT_NEEDED
 #include <net/netfilter/nf_nat_rule.h>
 #else
@@ -86,24 +87,24 @@
 			DEBUGP("same_check: bad MAP_IPS.\n");
 			return 0;
 		}
-		rangeip = (ntohl(mr->range[count].max_ip) - 
+		rangeip = (ntohl(mr->range[count].max_ip) -
 					ntohl(mr->range[count].min_ip) + 1);
 		mr->ipnum += rangeip;
-		
+
 		DEBUGP("same_check: range %u, ipnum = %u\n", count, rangeip);
 	}
 	DEBUGP("same_check: total ipaddresses = %u\n", mr->ipnum);
-	
+
 	mr->iparray = kmalloc((sizeof(u_int32_t) * mr->ipnum), GFP_KERNEL);
 	if (!mr->iparray) {
 		DEBUGP("same_check: Couldn't allocate %u bytes "
-			"for %u ipaddresses!\n", 
+			"for %u ipaddresses!\n",
 			(sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
 		return 0;
 	}
 	DEBUGP("same_check: Allocated %u bytes for %u ipaddresses.\n",
 			(sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
-	
+
 	for (count = 0; count < mr->rangesize; count++) {
 		for (countess = ntohl(mr->range[count].min_ip);
 				countess <= ntohl(mr->range[count].max_ip);
@@ -118,13 +119,13 @@
 	return 1;
 }
 
-static void 
+static void
 same_destroy(const struct xt_target *target, void *targinfo)
 {
 	struct ipt_same_info *mr = targinfo;
 
 	kfree(mr->iparray);
-	
+
 	DEBUGP("same_destroy: Deallocated %u bytes for %u ipaddresses.\n",
 			(sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
 }
@@ -155,7 +156,7 @@
 	   giving some hope for consistency across reboots.
 	   Here we calculate the index in same->iparray which
 	   holds the ipaddress we should use */
-	
+
 #ifdef CONFIG_NF_NAT_NEEDED
 	tmpip = ntohl(t->src.u3.ip);
 
@@ -186,8 +187,9 @@
 	return ip_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static struct ipt_target same_reg = { 
+static struct xt_target same_reg = {
 	.name		= "SAME",
+	.family		= AF_INET,
 	.target		= same_target,
 	.targetsize	= sizeof(struct ipt_same_info),
 	.table		= "nat",
@@ -199,12 +201,12 @@
 
 static int __init ipt_same_init(void)
 {
-	return ipt_register_target(&same_reg);
+	return xt_register_target(&same_reg);
 }
 
 static void __exit ipt_same_fini(void)
 {
-	ipt_unregister_target(&same_reg);
+	xt_unregister_target(&same_reg);
 }
 
 module_init(ipt_same_init);
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
deleted file mode 100644
index 93eb5c3..0000000
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * This is a module which is used for setting the MSS option in TCP packets.
- *
- * Copyright (C) 2000 Marc Boucher <marc@mbsi.ca>
- *
- * 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 <net/tcp.h>
-
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_TCPMSS.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
-MODULE_DESCRIPTION("iptables TCP MSS modification module");
-
-static inline unsigned int
-optlen(const u_int8_t *opt, unsigned int offset)
-{
-	/* Beware zero-length options: make finite progress */
-	if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0)
-		return 1;
-	else
-		return opt[offset+1];
-}
-
-static unsigned int
-ipt_tcpmss_target(struct sk_buff **pskb,
-		  const struct net_device *in,
-		  const struct net_device *out,
-		  unsigned int hooknum,
-		  const struct xt_target *target,
-		  const void *targinfo)
-{
-	const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
-	struct tcphdr *tcph;
-	struct iphdr *iph;
-	u_int16_t tcplen, newmss;
-	__be16 newtotlen, oldval;
-	unsigned int i;
-	u_int8_t *opt;
-
-	if (!skb_make_writable(pskb, (*pskb)->len))
-		return NF_DROP;
-
-	iph = (*pskb)->nh.iph;
-	tcplen = (*pskb)->len - iph->ihl*4;
-	tcph = (void *)iph + iph->ihl*4;
-
-	/* Since it passed flags test in tcp match, we know it is is
-	   not a fragment, and has data >= tcp header length.  SYN
-	   packets should not contain data: if they did, then we risk
-	   running over MTU, sending Frag Needed and breaking things
-	   badly. --RR */
-	if (tcplen != tcph->doff*4) {
-		if (net_ratelimit())
-			printk(KERN_ERR
-			       "ipt_tcpmss_target: bad length (%d bytes)\n",
-			       (*pskb)->len);
-		return NF_DROP;
-	}
-
-	if (tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) {
-		if (dst_mtu((*pskb)->dst) <= sizeof(struct iphdr) +
-					     sizeof(struct tcphdr)) {
-			if (net_ratelimit())
-				printk(KERN_ERR "ipt_tcpmss_target: "
-				       "unknown or invalid path-MTU (%d)\n",
-				       dst_mtu((*pskb)->dst));
-			return NF_DROP; /* or IPT_CONTINUE ?? */
-		}
-
-		newmss = dst_mtu((*pskb)->dst) - sizeof(struct iphdr) -
-						 sizeof(struct tcphdr);
-	} else
-		newmss = tcpmssinfo->mss;
-
- 	opt = (u_int8_t *)tcph;
-	for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) {
-		if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS &&
-		    opt[i+1] == TCPOLEN_MSS) {
-			u_int16_t oldmss;
-
-			oldmss = (opt[i+2] << 8) | opt[i+3];
-
-			if (tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU &&
-			    oldmss <= newmss)
-				return IPT_CONTINUE;
-
-			opt[i+2] = (newmss & 0xff00) >> 8;
-			opt[i+3] = (newmss & 0x00ff);
-
-			nf_proto_csum_replace2(&tcph->check, *pskb,
-						htons(oldmss), htons(newmss), 0);
-			return IPT_CONTINUE;
-		}
-	}
-
-	/*
-	 * MSS Option not found ?! add it..
-	 */
-	if (skb_tailroom((*pskb)) < TCPOLEN_MSS) {
-		struct sk_buff *newskb;
-
-		newskb = skb_copy_expand(*pskb, skb_headroom(*pskb),
-					 TCPOLEN_MSS, GFP_ATOMIC);
-		if (!newskb)
-			return NF_DROP;
-		kfree_skb(*pskb);
-		*pskb = newskb;
-		iph = (*pskb)->nh.iph;
-		tcph = (void *)iph + iph->ihl*4;
-	}
-
-	skb_put((*pskb), TCPOLEN_MSS);
-
- 	opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
-	memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
-
-	nf_proto_csum_replace2(&tcph->check, *pskb,
-				htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
-	opt[0] = TCPOPT_MSS;
-	opt[1] = TCPOLEN_MSS;
-	opt[2] = (newmss & 0xff00) >> 8;
-	opt[3] = (newmss & 0x00ff);
-
-	nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
-
-	oldval = ((__be16 *)tcph)[6];
-	tcph->doff += TCPOLEN_MSS/4;
-	nf_proto_csum_replace2(&tcph->check, *pskb,
-				oldval, ((__be16 *)tcph)[6], 0);
-
-	newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS);
-	nf_csum_replace2(&iph->check, iph->tot_len, newtotlen);
-	iph->tot_len = newtotlen;
-	return IPT_CONTINUE;
-}
-
-#define TH_SYN 0x02
-
-static inline int find_syn_match(const struct ipt_entry_match *m)
-{
-	const struct ipt_tcp *tcpinfo = (const struct ipt_tcp *)m->data;
-
-	if (strcmp(m->u.kernel.match->name, "tcp") == 0 &&
-	    tcpinfo->flg_cmp & TH_SYN &&
-	    !(tcpinfo->invflags & IPT_TCP_INV_FLAGS))
-		return 1;
-
-	return 0;
-}
-
-/* Must specify -p tcp --syn/--tcp-flags SYN */
-static int
-ipt_tcpmss_checkentry(const char *tablename,
-		      const void *e_void,
-		      const struct xt_target *target,
-		      void *targinfo,
-		      unsigned int hook_mask)
-{
-	const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
-	const struct ipt_entry *e = e_void;
-
-	if (tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU &&
-	    (hook_mask & ~((1 << NF_IP_FORWARD) |
-			   (1 << NF_IP_LOCAL_OUT) |
-			   (1 << NF_IP_POST_ROUTING))) != 0) {
-		printk("TCPMSS: path-MTU clamping only supported in "
-		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
-		return 0;
-	}
-
-	if (IPT_MATCH_ITERATE(e, find_syn_match))
-		return 1;
-	printk("TCPMSS: Only works on TCP SYN packets\n");
-	return 0;
-}
-
-static struct ipt_target ipt_tcpmss_reg = {
-	.name		= "TCPMSS",
-	.target		= ipt_tcpmss_target,
-	.targetsize	= sizeof(struct ipt_tcpmss_info),
-	.proto		= IPPROTO_TCP,
-	.checkentry	= ipt_tcpmss_checkentry,
-	.me		= THIS_MODULE,
-};
-
-static int __init ipt_tcpmss_init(void)
-{
-	return ipt_register_target(&ipt_tcpmss_reg);
-}
-
-static void __exit ipt_tcpmss_fini(void)
-{
-	ipt_unregister_target(&ipt_tcpmss_reg);
-}
-
-module_init(ipt_tcpmss_init);
-module_exit(ipt_tcpmss_fini);
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 18e74ac..cedf9f7 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -13,7 +13,7 @@
 #include <linux/ip.h>
 #include <net/checksum.h>
 
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ipt_TOS.h>
 
 MODULE_LICENSE("GPL");
@@ -40,15 +40,15 @@
 		iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
 		nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
 	}
-	return IPT_CONTINUE;
+	return XT_CONTINUE;
 }
 
 static int
 checkentry(const char *tablename,
 	   const void *e_void,
 	   const struct xt_target *target,
-           void *targinfo,
-           unsigned int hook_mask)
+	   void *targinfo,
+	   unsigned int hook_mask)
 {
 	const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos;
 
@@ -63,8 +63,9 @@
 	return 1;
 }
 
-static struct ipt_target ipt_tos_reg = {
+static struct xt_target ipt_tos_reg = {
 	.name		= "TOS",
+	.family		= AF_INET,
 	.target		= target,
 	.targetsize	= sizeof(struct ipt_tos_target_info),
 	.table		= "mangle",
@@ -74,12 +75,12 @@
 
 static int __init ipt_tos_init(void)
 {
-	return ipt_register_target(&ipt_tos_reg);
+	return xt_register_target(&ipt_tos_reg);
 }
 
 static void __exit ipt_tos_fini(void)
 {
-	ipt_unregister_target(&ipt_tos_reg);
+	xt_unregister_target(&ipt_tos_reg);
 }
 
 module_init(ipt_tos_init);
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index fffe5ca..64be31c 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -12,14 +12,14 @@
 #include <linux/ip.h>
 #include <net/checksum.h>
 
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ipt_TTL.h>
 
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("IP tables TTL modification module");
 MODULE_LICENSE("GPL");
 
-static unsigned int 
+static unsigned int
 ipt_ttl_target(struct sk_buff **pskb,
 	       const struct net_device *in, const struct net_device *out,
 	       unsigned int hooknum, const struct xt_target *target,
@@ -59,7 +59,7 @@
 		iph->ttl = new_ttl;
 	}
 
-	return IPT_CONTINUE;
+	return XT_CONTINUE;
 }
 
 static int ipt_ttl_checkentry(const char *tablename,
@@ -71,7 +71,7 @@
 	struct ipt_TTL_info *info = targinfo;
 
 	if (info->mode > IPT_TTL_MAXMODE) {
-		printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n", 
+		printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
 			info->mode);
 		return 0;
 	}
@@ -80,23 +80,24 @@
 	return 1;
 }
 
-static struct ipt_target ipt_TTL = { 
+static struct xt_target ipt_TTL = {
 	.name 		= "TTL",
-	.target 	= ipt_ttl_target, 
+	.family		= AF_INET,
+	.target 	= ipt_ttl_target,
 	.targetsize	= sizeof(struct ipt_TTL_info),
 	.table		= "mangle",
-	.checkentry 	= ipt_ttl_checkentry, 
+	.checkentry 	= ipt_ttl_checkentry,
 	.me 		= THIS_MODULE,
 };
 
 static int __init ipt_ttl_init(void)
 {
-	return ipt_register_target(&ipt_TTL);
+	return xt_register_target(&ipt_TTL);
 }
 
 static void __exit ipt_ttl_fini(void)
 {
-	ipt_unregister_target(&ipt_TTL);
+	xt_unregister_target(&ipt_TTL);
 }
 
 module_init(ipt_ttl_init);
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index dbd3478..a26404d 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -4,9 +4,9 @@
  * (C) 2000-2004 by Harald Welte <laforge@netfilter.org>
  *
  * 2000/09/22 ulog-cprange feature added
- * 2001/01/04 in-kernel queue as proposed by Sebastian Zander 
+ * 2001/01/04 in-kernel queue as proposed by Sebastian Zander
  * 						<zander@fokus.gmd.de>
- * 2001/01/30 per-rule nlgroup conflicts with global queue. 
+ * 2001/01/30 per-rule nlgroup conflicts with global queue.
  *            nlgroup now global (sysctl)
  * 2001/04/19 ulog-queue reworked, now fixed buffer size specified at
  * 	      module loadtime -HW
@@ -23,8 +23,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * This module accepts two parameters: 
- * 
+ * This module accepts two parameters:
+ *
  * nlbufsiz:
  *   The parameter specifies how big the buffer for each netlink multicast
  * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will
@@ -57,7 +57,7 @@
 #include <linux/mm.h>
 #include <linux/moduleparam.h>
 #include <linux/netfilter.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ipt_ULOG.h>
 #include <net/sock.h>
 #include <linux/bitops.h>
@@ -72,7 +72,7 @@
 
 #if 0
 #define DEBUGP(format, args...) printk("%s:%s:" format, \
-                                       __FILE__, __FUNCTION__ , ## args)
+				       __FILE__, __FUNCTION__ , ## args)
 #else
 #define DEBUGP(format, args...)
 #endif
@@ -132,7 +132,6 @@
 	ub->qlen = 0;
 	ub->skb = NULL;
 	ub->lastnlh = NULL;
-
 }
 
 
@@ -163,7 +162,7 @@
 		PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", n);
 
 		if (n > size) {
-			/* try to allocate only as much as we need for 
+			/* try to allocate only as much as we need for
 			 * current packet */
 
 			skb = alloc_skb(size, GFP_ATOMIC);
@@ -204,7 +203,7 @@
 	size = NLMSG_SPACE(sizeof(*pm) + copy_len);
 
 	ub = &ulog_buffers[groupnum];
-	
+
 	spin_lock_bh(&ulog_lock);
 
 	if (!ub->skb) {
@@ -212,7 +211,7 @@
 			goto alloc_failure;
 	} else if (ub->qlen >= loginfo->qthreshold ||
 		   size > skb_tailroom(ub->skb)) {
-		/* either the queue len is too high or we don't have 
+		/* either the queue len is too high or we don't have
 		 * enough room in nlskb left. send it to userspace. */
 
 		ulog_send(groupnum);
@@ -221,11 +220,11 @@
 			goto alloc_failure;
 	}
 
-	DEBUGP("ipt_ULOG: qlen %d, qthreshold %d\n", ub->qlen, 
+	DEBUGP("ipt_ULOG: qlen %d, qthreshold %d\n", ub->qlen,
 		loginfo->qthreshold);
 
 	/* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */
-	nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT, 
+	nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT,
 			sizeof(*pm)+copy_len);
 	ub->qlen++;
 
@@ -269,7 +268,7 @@
 	/* copy_len <= skb->len, so can't fail. */
 	if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
 		BUG();
-	
+
 	/* check if we are building multi-part messages */
 	if (ub->qlen > 1) {
 		ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
@@ -313,10 +312,10 @@
 	struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
 
 	ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
- 
- 	return IPT_CONTINUE;
+
+	return XT_CONTINUE;
 }
- 
+
 static void ipt_logfn(unsigned int pf,
 		      unsigned int hooknum,
 		      const struct sk_buff *skb,
@@ -363,8 +362,9 @@
 	return 1;
 }
 
-static struct ipt_target ipt_ulog_reg = {
+static struct xt_target ipt_ulog_reg = {
 	.name		= "ULOG",
+	.family		= AF_INET,
 	.target		= ipt_ulog_target,
 	.targetsize	= sizeof(struct ipt_ulog_info),
 	.checkentry	= ipt_ulog_checkentry,
@@ -379,7 +379,7 @@
 
 static int __init ipt_ulog_init(void)
 {
-	int i;
+	int ret, i;
 
 	DEBUGP("ipt_ULOG: init module\n");
 
@@ -396,17 +396,18 @@
 	}
 
 	nflognl = netlink_kernel_create(NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL,
-	                                THIS_MODULE);
+					THIS_MODULE);
 	if (!nflognl)
 		return -ENOMEM;
 
-	if (ipt_register_target(&ipt_ulog_reg) != 0) {
+	ret = xt_register_target(&ipt_ulog_reg);
+	if (ret < 0) {
 		sock_release(nflognl->sk_socket);
-		return -EINVAL;
+		return ret;
 	}
 	if (nflog)
 		nf_log_register(PF_INET, &ipt_ulog_logger);
-	
+
 	return 0;
 }
 
@@ -418,8 +419,8 @@
 	DEBUGP("ipt_ULOG: cleanup_module\n");
 
 	if (nflog)
-		nf_log_unregister_logger(&ipt_ulog_logger);
-	ipt_unregister_target(&ipt_ulog_reg);
+		nf_log_unregister(&ipt_ulog_logger);
+	xt_unregister_target(&ipt_ulog_reg);
 	sock_release(nflognl->sk_socket);
 
 	/* remove pending timers and free allocated skb's */
@@ -435,7 +436,6 @@
 			ub->skb = NULL;
 		}
 	}
-
 }
 
 module_init(ipt_ulog_init);
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index 7b60eb7..cfa0472 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -16,7 +16,7 @@
 #include <net/route.h>
 
 #include <linux/netfilter_ipv4/ipt_addrtype.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
@@ -40,12 +40,13 @@
 		ret &= match_type(iph->saddr, info->source)^info->invert_source;
 	if (info->dest)
 		ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
-	
+
 	return ret;
 }
 
-static struct ipt_match addrtype_match = {
+static struct xt_match addrtype_match = {
 	.name		= "addrtype",
+	.family		= AF_INET,
 	.match		= match,
 	.matchsize	= sizeof(struct ipt_addrtype_info),
 	.me		= THIS_MODULE
@@ -53,12 +54,12 @@
 
 static int __init ipt_addrtype_init(void)
 {
-	return ipt_register_match(&addrtype_match);
+	return xt_register_match(&addrtype_match);
 }
 
 static void __exit ipt_addrtype_fini(void)
 {
-	ipt_unregister_match(&addrtype_match);
+	xt_unregister_match(&addrtype_match);
 }
 
 module_init(ipt_addrtype_init);
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 1798f86..18a1678 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -6,12 +6,13 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/in.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 
 #include <linux/netfilter_ipv4/ipt_ah.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
@@ -28,8 +29,8 @@
 spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
 {
 	int r=0;
-        duprintf("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
-        	min,spi,max);
+	duprintf("ah 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;
@@ -86,8 +87,9 @@
 	return 1;
 }
 
-static struct ipt_match ah_match = {
+static struct xt_match ah_match = {
 	.name		= "ah",
+	.family		= AF_INET,
 	.match		= match,
 	.matchsize	= sizeof(struct ipt_ah),
 	.proto		= IPPROTO_AH,
@@ -97,12 +99,12 @@
 
 static int __init ipt_ah_init(void)
 {
-	return ipt_register_match(&ah_match);
+	return xt_register_match(&ah_match);
 }
 
 static void __exit ipt_ah_fini(void)
 {
-	ipt_unregister_match(&ah_match);
+	xt_unregister_match(&ah_match);
 }
 
 module_init(ipt_ah_init);
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index dafbdec..37508b2 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -9,10 +9,13 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/in.h>
+#include <linux/ip.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/tcp.h>
 
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_ecn.h>
 
@@ -109,8 +112,9 @@
 	return 1;
 }
 
-static struct ipt_match ecn_match = {
+static struct xt_match ecn_match = {
 	.name		= "ecn",
+	.family		= AF_INET,
 	.match		= match,
 	.matchsize	= sizeof(struct ipt_ecn_info),
 	.checkentry	= checkentry,
@@ -119,12 +123,12 @@
 
 static int __init ipt_ecn_init(void)
 {
-	return ipt_register_match(&ecn_match);
+	return xt_register_match(&ecn_match);
 }
 
 static void __exit ipt_ecn_fini(void)
 {
-	ipt_unregister_match(&ecn_match);
+	xt_unregister_match(&ecn_match);
 }
 
 module_init(ipt_ecn_init);
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index 5202edd..bc5d5e6 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -10,7 +10,7 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ipt_iprange.h>
 
 MODULE_LICENSE("GPL");
@@ -41,7 +41,7 @@
 			DEBUGP("src IP %u.%u.%u.%u NOT in range %s"
 			       "%u.%u.%u.%u-%u.%u.%u.%u\n",
 				NIPQUAD(iph->saddr),
-			        info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
+				info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
 				NIPQUAD(info->src.min_ip),
 				NIPQUAD(info->src.max_ip));
 			return 0;
@@ -54,7 +54,7 @@
 			DEBUGP("dst IP %u.%u.%u.%u NOT in range %s"
 			       "%u.%u.%u.%u-%u.%u.%u.%u\n",
 				NIPQUAD(iph->daddr),
-			        info->flags & IPRANGE_DST_INV ? "(INV) " : "",
+				info->flags & IPRANGE_DST_INV ? "(INV) " : "",
 				NIPQUAD(info->dst.min_ip),
 				NIPQUAD(info->dst.max_ip));
 			return 0;
@@ -63,22 +63,22 @@
 	return 1;
 }
 
-static struct ipt_match iprange_match = {
+static struct xt_match iprange_match = {
 	.name		= "iprange",
+	.family		= AF_INET,
 	.match		= match,
 	.matchsize	= sizeof(struct ipt_iprange_info),
-	.destroy	= NULL,
 	.me		= THIS_MODULE
 };
 
 static int __init ipt_iprange_init(void)
 {
-	return ipt_register_match(&iprange_match);
+	return xt_register_match(&iprange_match);
 }
 
 static void __exit ipt_iprange_fini(void)
 {
-	ipt_unregister_match(&iprange_match);
+	xt_unregister_match(&iprange_match);
 }
 
 module_init(ipt_iprange_init);
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 78c336f1..7fae9aa 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -15,7 +15,7 @@
 #include <net/sock.h>
 
 #include <linux/netfilter_ipv4/ipt_owner.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
@@ -53,10 +53,10 @@
 
 static int
 checkentry(const char *tablename,
-           const void *ip,
+	   const void *ip,
 	   const struct xt_match *match,
-           void *matchinfo,
-           unsigned int hook_mask)
+	   void *matchinfo,
+	   unsigned int hook_mask)
 {
 	const struct ipt_owner_info *info = matchinfo;
 
@@ -68,8 +68,9 @@
 	return 1;
 }
 
-static struct ipt_match owner_match = {
+static struct xt_match owner_match = {
 	.name		= "owner",
+	.family		= AF_INET,
 	.match		= match,
 	.matchsize	= sizeof(struct ipt_owner_info),
 	.hooks		= (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING),
@@ -79,12 +80,12 @@
 
 static int __init ipt_owner_init(void)
 {
-	return ipt_register_match(&owner_match);
+	return xt_register_match(&owner_match);
 }
 
 static void __exit ipt_owner_fini(void)
 {
-	ipt_unregister_match(&owner_match);
+	xt_unregister_match(&owner_match);
 }
 
 module_init(ipt_owner_init);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 4db0e73..aecb9c4 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -12,6 +12,7 @@
  * Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org
  */
 #include <linux/init.h>
+#include <linux/ip.h>
 #include <linux/moduleparam.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -24,7 +25,7 @@
 #include <linux/skbuff.h>
 #include <linux/inet.h>
 
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ipt_recent.h>
 
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
@@ -78,7 +79,7 @@
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry	*proc_dir;
-static struct file_operations	recent_fops;
+static const struct file_operations	recent_fops;
 #endif
 
 static u_int32_t hash_rnd;
@@ -453,7 +454,7 @@
 	return size;
 }
 
-static struct file_operations recent_fops = {
+static const struct file_operations recent_fops = {
 	.open		= recent_seq_open,
 	.read		= seq_read,
 	.write		= recent_proc_write,
@@ -462,8 +463,9 @@
 };
 #endif /* CONFIG_PROC_FS */
 
-static struct ipt_match recent_match = {
+static struct xt_match recent_match = {
 	.name		= "recent",
+	.family		= AF_INET,
 	.match		= ipt_recent_match,
 	.matchsize	= sizeof(struct ipt_recent_info),
 	.checkentry	= ipt_recent_checkentry,
@@ -479,13 +481,13 @@
 		return -EINVAL;
 	ip_list_hash_size = 1 << fls(ip_list_tot);
 
-	err = ipt_register_match(&recent_match);
+	err = xt_register_match(&recent_match);
 #ifdef CONFIG_PROC_FS
 	if (err)
 		return err;
 	proc_dir = proc_mkdir("ipt_recent", proc_net);
 	if (proc_dir == NULL) {
-		ipt_unregister_match(&recent_match);
+		xt_unregister_match(&recent_match);
 		err = -ENOMEM;
 	}
 #endif
@@ -495,7 +497,7 @@
 static void __exit ipt_recent_exit(void)
 {
 	BUG_ON(!list_empty(&tables));
-	ipt_unregister_match(&recent_match);
+	xt_unregister_match(&recent_match);
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("ipt_recent", proc_net);
 #endif
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index 5549c39..5d33b51 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -8,11 +8,12 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/ip.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 
 #include <linux/netfilter_ipv4/ipt_tos.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("iptables TOS match module");
@@ -32,8 +33,9 @@
 	return (skb->nh.iph->tos == info->tos) ^ info->invert;
 }
 
-static struct ipt_match tos_match = {
+static struct xt_match tos_match = {
 	.name		= "tos",
+	.family		= AF_INET,
 	.match		= match,
 	.matchsize	= sizeof(struct ipt_tos_info),
 	.me		= THIS_MODULE,
@@ -41,12 +43,12 @@
 
 static int __init ipt_multiport_init(void)
 {
-	return ipt_register_match(&tos_match);
+	return xt_register_match(&tos_match);
 }
 
 static void __exit ipt_multiport_fini(void)
 {
-	ipt_unregister_match(&tos_match);
+	xt_unregister_match(&tos_match);
 }
 
 module_init(ipt_multiport_init);
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index a5243bd..1eca9f4 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -1,4 +1,4 @@
-/* IP tables module for matching the value of the TTL 
+/* IP tables module for matching the value of the TTL
  *
  * ipt_ttl.c,v 1.5 2000/11/13 11:16:08 laforge Exp
  *
@@ -9,11 +9,12 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/ip.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 
 #include <linux/netfilter_ipv4/ipt_ttl.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("IP tables TTL matching module");
@@ -40,7 +41,7 @@
 			return (skb->nh.iph->ttl > info->ttl);
 			break;
 		default:
-			printk(KERN_WARNING "ipt_ttl: unknown mode %d\n", 
+			printk(KERN_WARNING "ipt_ttl: unknown mode %d\n",
 				info->mode);
 			return 0;
 	}
@@ -48,8 +49,9 @@
 	return 0;
 }
 
-static struct ipt_match ttl_match = {
+static struct xt_match ttl_match = {
 	.name		= "ttl",
+	.family		= AF_INET,
 	.match		= match,
 	.matchsize	= sizeof(struct ipt_ttl_info),
 	.me		= THIS_MODULE,
@@ -57,13 +59,12 @@
 
 static int __init ipt_ttl_init(void)
 {
-	return ipt_register_match(&ttl_match);
+	return xt_register_match(&ttl_match);
 }
 
 static void __exit ipt_ttl_fini(void)
 {
-	ipt_unregister_match(&ttl_match);
-
+	xt_unregister_match(&ttl_match);
 }
 
 module_init(ipt_ttl_init);
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index e2e7dd8..d1d61e9 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -25,7 +25,7 @@
 	struct ipt_replace repl;
 	struct ipt_standard entries[3];
 	struct ipt_error term;
-} initial_table __initdata 
+} initial_table __initdata
 = { { "filter", FILTER_VALID_HOOKS, 4,
       sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
       { [NF_IP_LOCAL_IN] = 0,
@@ -74,7 +74,7 @@
     }
 };
 
-static struct ipt_table packet_filter = {
+static struct xt_table packet_filter = {
 	.name		= "filter",
 	.valid_hooks	= FILTER_VALID_HOOKS,
 	.lock		= RW_LOCK_UNLOCKED,
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index af29398..98b66ef 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -58,7 +58,7 @@
 	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
 		-NF_ACCEPT - 1 } },
 	    /* LOCAL_IN */
- 	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
+	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
 		0,
 		sizeof(struct ipt_entry),
 		sizeof(struct ipt_standard),
@@ -66,7 +66,7 @@
 	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
 		-NF_ACCEPT - 1 } },
 	    /* FORWARD */
- 	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
+	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
 		0,
 		sizeof(struct ipt_entry),
 		sizeof(struct ipt_standard),
@@ -103,7 +103,7 @@
     }
 };
 
-static struct ipt_table packet_mangler = {
+static struct xt_table packet_mangler = {
 	.name		= "mangle",
 	.valid_hooks	= MANGLE_VALID_HOOKS,
 	.lock		= RW_LOCK_UNLOCKED,
@@ -166,7 +166,7 @@
 		.hook		= ipt_route_hook,
 		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
-		.hooknum	= NF_IP_PRE_ROUTING, 
+		.hooknum	= NF_IP_PRE_ROUTING,
 		.priority	= NF_IP_PRI_MANGLE,
 	},
 	{
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index bcbeb4a..18c3d4c 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
  *
  * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
@@ -15,26 +15,26 @@
 	struct ipt_error term;
 } initial_table __initdata = {
 	.repl = {
-		.name = "raw", 
-		.valid_hooks = RAW_VALID_HOOKS, 
+		.name = "raw",
+		.valid_hooks = RAW_VALID_HOOKS,
 		.num_entries = 3,
 		.size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
-		.hook_entry = { 
+		.hook_entry = {
 			[NF_IP_PRE_ROUTING] = 0,
 			[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) },
-		.underflow = { 
+		.underflow = {
 			[NF_IP_PRE_ROUTING] = 0,
 			[NF_IP_LOCAL_OUT]  = sizeof(struct ipt_standard) },
 	},
 	.entries = {
 	     /* PRE_ROUTING */
-	     { 
-		     .entry = { 
+	     {
+		     .entry = {
 			     .target_offset = sizeof(struct ipt_entry),
 			     .next_offset = sizeof(struct ipt_standard),
 		     },
-		     .target = { 
-			  .target = { 
+		     .target = {
+			  .target = {
 				  .u = {
 					  .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
 				  },
@@ -69,7 +69,7 @@
 			.target = {
 				.u = {
 					.user = {
-						.target_size = IPT_ALIGN(sizeof(struct ipt_error_target)), 
+						.target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
 						.name = IPT_ERROR_TARGET,
 					},
 				},
@@ -79,10 +79,10 @@
 	}
 };
 
-static struct ipt_table packet_raw = { 
-	.name = "raw", 
-	.valid_hooks =  RAW_VALID_HOOKS, 
-	.lock = RW_LOCK_UNLOCKED, 
+static struct xt_table packet_raw = {
+	.name = "raw",
+	.valid_hooks =  RAW_VALID_HOOKS,
+	.lock = RW_LOCK_UNLOCKED,
 	.me = THIS_MODULE,
 	.af = AF_INET,
 };
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 471b638..b984db7 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -66,7 +66,7 @@
 			    const struct nf_conntrack_tuple *tuple)
 {
 	return seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
-		          NIPQUAD(tuple->src.u3.ip),
+			  NIPQUAD(tuple->src.u3.ip),
 			  NIPQUAD(tuple->dst.u3.ip));
 }
 
@@ -82,14 +82,14 @@
 {
 	skb_orphan(skb);
 
-        local_bh_disable();
-        skb = ip_defrag(skb, user);
-        local_bh_enable();
+	local_bh_disable();
+	skb = ip_defrag(skb, user);
+	local_bh_enable();
 
-        if (skb)
+	if (skb)
 		ip_send_check(skb->nh.iph);
 
-        return skb;
+	return skb;
 }
 
 static int
@@ -192,10 +192,10 @@
 }
 
 static unsigned int ipv4_conntrack_local(unsigned int hooknum,
-				         struct sk_buff **pskb,
-				         const struct net_device *in,
-				         const struct net_device *out,
-				         int (*okfn)(struct sk_buff *))
+					 struct sk_buff **pskb,
+					 const struct net_device *in,
+					 const struct net_device *out,
+					 int (*okfn)(struct sk_buff *))
 {
 	/* root is playing with raw sockets. */
 	if ((*pskb)->len < sizeof(struct iphdr)
@@ -332,7 +332,7 @@
 	struct inet_sock *inet = inet_sk(sk);
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conntrack_tuple tuple;
-	
+
 	NF_CT_TUPLE_U_BLANK(&tuple);
 	tuple.src.u3.ip = inet->rcv_saddr;
 	tuple.src.u.tcp.port = inet->sport;
@@ -501,7 +501,7 @@
 	return ret;
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
  cleanup_hooks:
- 	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
+	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
 #endif
  cleanup_ipv4:
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 3b31bc6..89f933e 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -135,7 +135,7 @@
 			l3proto, l4proto))
 		return -ENOSPC;
 
- 	if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL]))
+	if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL]))
 		return -ENOSPC;
 
 	if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
@@ -146,7 +146,7 @@
 			l3proto, l4proto))
 		return -ENOSPC;
 
- 	if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY]))
+	if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY]))
 		return -ENOSPC;
 
 	if (test_bit(IPS_ASSURED_BIT, &ct->status))
@@ -197,7 +197,7 @@
 	return ret;
 }
 
-static struct file_operations ct_file_ops = {
+static const struct file_operations ct_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_open,
 	.read    = seq_read,
@@ -228,7 +228,7 @@
 
 static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
- 	struct list_head *e = v;
+	struct list_head *e = v;
 
 	++*pos;
 	e = e->next;
@@ -262,7 +262,7 @@
 	print_tuple(s, &exp->tuple,
 		    __nf_ct_l3proto_find(exp->tuple.src.l3num),
 		    __nf_ct_l4proto_find(exp->tuple.src.l3num,
-		    			 exp->tuple.dst.protonum));
+					 exp->tuple.dst.protonum));
 	return seq_putc(s, '\n');
 }
 
@@ -278,7 +278,7 @@
 	return seq_open(file, &exp_seq_ops);
 }
 
-static struct file_operations ip_exp_file_ops = {
+static const struct file_operations ip_exp_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = exp_open,
 	.read    = seq_read,
@@ -366,7 +366,7 @@
 	return seq_open(file, &ct_cpu_seq_ops);
 }
 
-static struct file_operations ct_cpu_seq_fops = {
+static const struct file_operations ct_cpu_seq_fops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_cpu_seq_open,
 	.read    = seq_read,
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index db9e7c4..88cfa6a 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/in.h>
@@ -101,9 +100,9 @@
 		       unsigned int hooknum)
 {
 	/* Try to delete connection immediately after all replies:
-           won't actually vanish as we still have skb, and del_timer
-           means this will only run once even if count hits zero twice
-           (theoretically possible with SMP) */
+	   won't actually vanish as we still have skb, and del_timer
+	   means this will only run once even if count hits zero twice
+	   (theoretically possible with SMP) */
 	if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) {
 		if (atomic_dec_and_test(&ct->proto.icmp.count)
 		    && del_timer(&ct->timeout))
@@ -144,8 +143,8 @@
 /* Returns conntrack if it dealt with ICMP, and filled in skb fields */
 static int
 icmp_error_message(struct sk_buff *skb,
-                 enum ip_conntrack_info *ctinfo,
-                 unsigned int hooknum)
+		 enum ip_conntrack_info *ctinfo,
+		 unsigned int hooknum)
 {
 	struct nf_conntrack_tuple innertuple, origtuple;
 	struct {
@@ -170,7 +169,9 @@
 		return -NF_ACCEPT;
 	}
 
+	/* rcu_read_lock()ed by nf_hook_slow */
 	innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
+
 	dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp);
 	/* Are they talking about one of our connections? */
 	if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
@@ -181,9 +182,9 @@
 		return -NF_ACCEPT;
 	}
 
-        /* Ordinarily, we'd expect the inverted tupleproto, but it's
-           been preserved inside the ICMP. */
-        if (!nf_ct_invert_tuple(&innertuple, &origtuple,
+	/* Ordinarily, we'd expect the inverted tupleproto, but it's
+	   been preserved inside the ICMP. */
+	if (!nf_ct_invert_tuple(&innertuple, &origtuple,
 				&nf_conntrack_l3proto_ipv4, innerproto)) {
 		DEBUGP("icmp_error_message: no match\n");
 		return -NF_ACCEPT;
@@ -212,10 +213,10 @@
 			*ctinfo += IP_CT_IS_REPLY;
 	}
 
-        /* Update skb to refer to this connection */
-        skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general;
-        skb->nfctinfo = *ctinfo;
-        return -NF_ACCEPT;
+	/* Update skb to refer to this connection */
+	skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general;
+	skb->nfctinfo = *ctinfo;
+	return -NF_ACCEPT;
 }
 
 /* Small and modified version of icmp_rcv */
@@ -306,7 +307,7 @@
 	if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
 		return -EINVAL;
 
-	tuple->dst.u.icmp.type = 
+	tuple->dst.u.icmp.type =
 			*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
 	tuple->dst.u.icmp.code =
 			*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
@@ -332,7 +333,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec_jiffies,
 	},
-        {
+	{
 		.ctl_name = 0
 	}
 };
@@ -346,7 +347,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec_jiffies,
 	},
-        {
+	{
 		.ctl_name = 0
 	}
 };
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 86a9227..2c01378 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -53,7 +53,7 @@
 static inline struct nf_nat_protocol *
 __nf_nat_proto_find(u_int8_t protonum)
 {
-	return nf_nat_protos[protonum];
+	return rcu_dereference(nf_nat_protos[protonum]);
 }
 
 struct nf_nat_protocol *
@@ -61,13 +61,11 @@
 {
 	struct nf_nat_protocol *p;
 
-	/* we need to disable preemption to make sure 'p' doesn't get
-	 * removed until we've grabbed the reference */
-	preempt_disable();
+	rcu_read_lock();
 	p = __nf_nat_proto_find(protonum);
 	if (!try_module_get(p->me))
 		p = &nf_nat_unknown_protocol;
-	preempt_enable();
+	rcu_read_unlock();
 
 	return p;
 }
@@ -126,8 +124,8 @@
 	 const struct nf_nat_range *range)
 {
 	struct nf_nat_protocol *proto;
+	int ret = 0;
 
-	proto = __nf_nat_proto_find(tuple->dst.protonum);
 	/* If we are supposed to map IPs, then we must be in the
 	   range specified, otherwise let this drag us onto a new src IP. */
 	if (range->flags & IP_NAT_RANGE_MAP_IPS) {
@@ -136,12 +134,15 @@
 			return 0;
 	}
 
+	rcu_read_lock();
+	proto = __nf_nat_proto_find(tuple->dst.protonum);
 	if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
 	    proto->in_range(tuple, IP_NAT_MANIP_SRC,
 			    &range->min, &range->max))
-		return 1;
+		ret = 1;
+	rcu_read_unlock();
 
-	return 0;
+	return ret;
 }
 
 static inline int
@@ -254,8 +255,9 @@
 	if (maniptype == IP_NAT_MANIP_SRC) {
 		if (find_appropriate_src(orig_tuple, tuple, range)) {
 			DEBUGP("get_unique_tuple: Found current src map\n");
-			if (!nf_nat_used_tuple(tuple, ct))
-				return;
+			if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
+				if (!nf_nat_used_tuple(tuple, ct))
+					return;
 		}
 	}
 
@@ -267,20 +269,25 @@
 	/* 3) The per-protocol part of the manip is made to map into
 	   the range to make a unique tuple. */
 
-	proto = nf_nat_proto_find_get(orig_tuple->dst.protonum);
+	rcu_read_lock();
+	proto = __nf_nat_proto_find(orig_tuple->dst.protonum);
+
+	/* Change protocol info to have some randomization */
+	if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) {
+		proto->unique_tuple(tuple, range, maniptype, ct);
+		goto out;
+	}
 
 	/* Only bother mapping if it's not already in range and unique */
 	if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
 	     proto->in_range(tuple, maniptype, &range->min, &range->max)) &&
-	    !nf_nat_used_tuple(tuple, ct)) {
-		nf_nat_proto_put(proto);
-		return;
-	}
+	    !nf_nat_used_tuple(tuple, ct))
+		goto out;
 
 	/* Last change: get protocol to try to obtain unique tuple. */
 	proto->unique_tuple(tuple, range, maniptype, ct);
-
-	nf_nat_proto_put(proto);
+out:
+	rcu_read_unlock();
 }
 
 unsigned int
@@ -361,12 +368,11 @@
 	iph = (void *)(*pskb)->data + iphdroff;
 
 	/* Manipulate protcol part. */
-	p = nf_nat_proto_find_get(proto);
-	if (!p->manip_pkt(pskb, iphdroff, target, maniptype)) {
-		nf_nat_proto_put(p);
+
+	/* rcu_read_lock()ed by nf_hook_slow */
+	p = __nf_nat_proto_find(proto);
+	if (!p->manip_pkt(pskb, iphdroff, target, maniptype))
 		return 0;
-	}
-	nf_nat_proto_put(p);
 
 	iph = (void *)(*pskb)->data + iphdroff;
 
@@ -423,6 +429,7 @@
 		struct icmphdr icmp;
 		struct iphdr ip;
 	} *inside;
+	struct nf_conntrack_l4proto *l4proto;
 	struct nf_conntrack_tuple inner, target;
 	int hdrlen = (*pskb)->nh.iph->ihl * 4;
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
@@ -444,8 +451,8 @@
 		     (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
 
 	/* Redirects on non-null nats must be dropped, else they'll
-           start talking to each other without our translation, and be
-           confused... --RR */
+	   start talking to each other without our translation, and be
+	   confused... --RR */
 	if (inside->icmp.type == ICMP_REDIRECT) {
 		/* If NAT isn't finished, assume it and drop. */
 		if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
@@ -458,16 +465,16 @@
 	DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n",
 	       *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
 
+	/* rcu_read_lock()ed by nf_hook_slow */
+	l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
+
 	if (!nf_ct_get_tuple(*pskb,
 			     (*pskb)->nh.iph->ihl*4 + sizeof(struct icmphdr),
 			     (*pskb)->nh.iph->ihl*4 +
-	                     sizeof(struct icmphdr) + inside->ip.ihl*4,
-	                     (u_int16_t)AF_INET,
-	                     inside->ip.protocol,
-	                     &inner,
-	                     l3proto,
-			     __nf_ct_l4proto_find((u_int16_t)PF_INET,
-			     			  inside->ip.protocol)))
+			     sizeof(struct icmphdr) + inside->ip.ihl*4,
+			     (u_int16_t)AF_INET,
+			     inside->ip.protocol,
+			     &inner, l3proto, l4proto))
 		return 0;
 
 	/* Change inner back to look like incoming packet.  We do the
@@ -521,7 +528,7 @@
 		ret = -EBUSY;
 		goto out;
 	}
-	nf_nat_protos[proto->protonum] = proto;
+	rcu_assign_pointer(nf_nat_protos[proto->protonum], proto);
  out:
 	write_unlock_bh(&nf_nat_lock);
 	return ret;
@@ -532,11 +539,10 @@
 void nf_nat_protocol_unregister(struct nf_nat_protocol *proto)
 {
 	write_lock_bh(&nf_nat_lock);
-	nf_nat_protos[proto->protonum] = &nf_nat_unknown_protocol;
+	rcu_assign_pointer(nf_nat_protos[proto->protonum],
+			   &nf_nat_unknown_protocol);
 	write_unlock_bh(&nf_nat_lock);
-
-	/* Someone could be still looking at the proto in a bh. */
-	synchronize_net();
+	synchronize_rcu();
 }
 EXPORT_SYMBOL(nf_nat_protocol_unregister);
 
@@ -600,10 +606,10 @@
 	/* Sew in builtin protocols. */
 	write_lock_bh(&nf_nat_lock);
 	for (i = 0; i < MAX_IP_NAT_PROTO; i++)
-		nf_nat_protos[i] = &nf_nat_unknown_protocol;
-	nf_nat_protos[IPPROTO_TCP] = &nf_nat_protocol_tcp;
-	nf_nat_protos[IPPROTO_UDP] = &nf_nat_protocol_udp;
-	nf_nat_protos[IPPROTO_ICMP] = &nf_nat_protocol_icmp;
+		rcu_assign_pointer(nf_nat_protos[i], &nf_nat_unknown_protocol);
+	rcu_assign_pointer(nf_nat_protos[IPPROTO_TCP], &nf_nat_protocol_tcp);
+	rcu_assign_pointer(nf_nat_protos[IPPROTO_UDP], &nf_nat_protocol_udp);
+	rcu_assign_pointer(nf_nat_protos[IPPROTO_ICMP], &nf_nat_protocol_icmp);
 	write_unlock_bh(&nf_nat_lock);
 
 	for (i = 0; i < nf_nat_htable_size; i++) {
@@ -611,8 +617,8 @@
 	}
 
 	/* FIXME: Man, this is a hack.  <SIGH> */
-	NF_CT_ASSERT(nf_conntrack_destroyed == NULL);
-	nf_conntrack_destroyed = &nf_nat_cleanup_conntrack;
+	NF_CT_ASSERT(rcu_dereference(nf_conntrack_destroyed) == NULL);
+	rcu_assign_pointer(nf_conntrack_destroyed, nf_nat_cleanup_conntrack);
 
 	/* Initialize fake conntrack so that NAT will skip it */
 	nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
@@ -636,7 +642,8 @@
 static void __exit nf_nat_cleanup(void)
 {
 	nf_ct_iterate_cleanup(&clean_nat, NULL);
-	nf_conntrack_destroyed = NULL;
+	rcu_assign_pointer(nf_conntrack_destroyed, NULL);
+	synchronize_rcu();
 	vfree(bysource);
 	nf_ct_l3proto_put(l3proto);
 }
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index fb9ab01..9cbf3f9 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -256,7 +256,7 @@
 	if (set_h245_addr(pskb, data, dataoff, taddr,
 			  &ct->tuplehash[!dir].tuple.dst.u3,
 			  htons((port & htons(1)) ? nated_port + 1 :
-			  			    nated_port)) == 0) {
+						    nated_port)) == 0) {
 		/* Save ports */
 		info->rtp_port[i][dir] = rtp_port;
 		info->rtp_port[i][!dir] = htons(nated_port);
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 98fbfc84..49a90c3 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -176,10 +176,10 @@
 	datalen = (*pskb)->len - iph->ihl*4;
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 		tcph->check = 0;
-		tcph->check = tcp_v4_check(tcph, datalen,
+		tcph->check = tcp_v4_check(datalen,
 					   iph->saddr, iph->daddr,
 					   csum_partial((char *)tcph,
-					   		datalen, 0));
+							datalen, 0));
 	} else
 		nf_proto_csum_replace2(&tcph->check, *pskb,
 				       htons(oldlen), htons(datalen), 1);
@@ -223,7 +223,7 @@
 	/* UDP helpers might accidentally mangle the wrong packet */
 	iph = (*pskb)->nh.iph;
 	if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) +
-	                       match_offset + match_len)
+			       match_offset + match_len)
 		return 0;
 
 	if (!skb_make_writable(pskb, (*pskb)->len))
@@ -252,9 +252,9 @@
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 		udph->check = 0;
 		udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
-		                                datalen, IPPROTO_UDP,
-		                                csum_partial((char *)udph,
-		                                             datalen, 0));
+						datalen, IPPROTO_UDP,
+						csum_partial((char *)udph,
+							     datalen, 0));
 		if (!udph->check)
 			udph->check = CSUM_MANGLED_0;
 	} else
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index 5df4fca..7ba341c 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -184,10 +184,10 @@
 
 	/* mangle packet */
 	if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
-	                             cid_off + sizeof(struct pptp_pkt_hdr) +
-	                             sizeof(struct PptpControlHeader),
-	                             sizeof(new_callid), (char *)&new_callid,
-	                             sizeof(new_callid)) == 0)
+				     cid_off + sizeof(struct pptp_pkt_hdr) +
+				     sizeof(struct PptpControlHeader),
+				     sizeof(new_callid), (char *)&new_callid,
+				     sizeof(new_callid)) == 0)
 		return NF_DROP;
 	return NF_ACCEPT;
 }
@@ -276,7 +276,7 @@
 		ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
 
 	if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
-	                             pcid_off + sizeof(struct pptp_pkt_hdr) +
+				     pcid_off + sizeof(struct pptp_pkt_hdr) +
 				     sizeof(struct PptpControlHeader),
 				     sizeof(new_pcid), (char *)&new_pcid,
 				     sizeof(new_pcid)) == 0)
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c
index dcfd772..6bc2f06 100644
--- a/net/ipv4/netfilter/nf_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c
@@ -44,7 +44,7 @@
 
 	for (i = 0; i < range_size; i++, id++) {
 		tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +
-		                             (id % range_size));
+					     (id % range_size));
 		if (!nf_nat_used_tuple(tuple, ct))
 			return 1;
 	}
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c
index 7e26a7e..439164c 100644
--- a/net/ipv4/netfilter/nf_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/random.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
 
@@ -75,6 +76,9 @@
 		range_size = ntohs(range->max.tcp.port) - min + 1;
 	}
 
+	if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
+		port =  net_random();
+
 	for (i = 0; i < range_size; i++, port++) {
 		*portptr = htons(min + port % range_size);
 		if (!nf_nat_used_tuple(tuple, ct))
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c
index ab0ce4c..8cae6e0 100644
--- a/net/ipv4/netfilter/nf_nat_proto_udp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_udp.c
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/random.h>
 #include <linux/ip.h>
 #include <linux/udp.h>
 
@@ -73,6 +74,9 @@
 		range_size = ntohs(range->max.udp.port) - min + 1;
 	}
 
+	if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
+		port = net_random();
+
 	for (i = 0; i < range_size; i++, port++) {
 		*portptr = htons(min + port % range_size);
 		if (!nf_nat_used_tuple(tuple, ct))
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index b868ee0..147a437 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -56,8 +56,8 @@
 		/* PRE_ROUTING */
 		{
 			.entry = {
-	    			.target_offset = sizeof(struct ipt_entry),
-	    			.next_offset = sizeof(struct ipt_standard),
+				.target_offset = sizeof(struct ipt_entry),
+				.next_offset = sizeof(struct ipt_standard),
 			},
 			.target = {
 				.target = {
@@ -71,8 +71,8 @@
 		/* POST_ROUTING */
 		{
 			.entry = {
-	    			.target_offset = sizeof(struct ipt_entry),
-	    			.next_offset = sizeof(struct ipt_standard),
+				.target_offset = sizeof(struct ipt_entry),
+				.next_offset = sizeof(struct ipt_standard),
 			},
 			.target = {
 				.target = {
@@ -86,8 +86,8 @@
 		/* LOCAL_OUT */
 		{
 			.entry = {
-	    			.target_offset = sizeof(struct ipt_entry),
-	    			.next_offset = sizeof(struct ipt_standard),
+				.target_offset = sizeof(struct ipt_entry),
+				.next_offset = sizeof(struct ipt_standard),
 			},
 			.target = {
 				.target = {
@@ -119,7 +119,7 @@
 	}
 };
 
-static struct ipt_table nat_table = {
+static struct xt_table nat_table = {
 	.name		= "nat",
 	.valid_hooks	= NAT_VALID_HOOKS,
 	.lock		= RW_LOCK_UNLOCKED,
@@ -145,7 +145,7 @@
 
 	/* Connection must be valid and new. */
 	NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
-	                    ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
+			    ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
 	NF_CT_ASSERT(out);
 
 	return nf_nat_setup_info(ct, &mr->range[0], hooknum);
@@ -226,6 +226,10 @@
 		printk("DNAT: multiple ranges no longer supported\n");
 		return 0;
 	}
+	if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) {
+		printk("DNAT: port randomization not supported\n");
+		return 0;
+	}
 	return 1;
 }
 
@@ -252,8 +256,8 @@
 
 unsigned int
 alloc_null_binding_confirmed(struct nf_conn *ct,
-                             struct nf_nat_info *info,
-                             unsigned int hooknum)
+			     struct nf_nat_info *info,
+			     unsigned int hooknum)
 {
 	__be32 ip
 		= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
@@ -290,7 +294,7 @@
 	return ret;
 }
 
-static struct ipt_target ipt_snat_reg = {
+static struct xt_target ipt_snat_reg = {
 	.name		= "SNAT",
 	.target		= ipt_snat_target,
 	.targetsize	= sizeof(struct nf_nat_multi_range_compat),
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 3d524b9..b12cd7c 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -90,7 +90,7 @@
 		return 1;
 
 	if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
-	                              matchoff, matchlen, addr, addrlen))
+				      matchoff, matchlen, addr, addrlen))
 		return 0;
 	*dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
 	return 1;
@@ -151,7 +151,7 @@
 		return 0;
 
 	if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
-	                              matchoff, matchlen, buffer, bufflen))
+				      matchoff, matchlen, buffer, bufflen))
 		return 0;
 
 	/* We need to reload this. Thanks Patrick. */
@@ -172,7 +172,7 @@
 
 	/* Get actual SDP lenght */
 	if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff,
-	                    &matchlen, POS_SDP_HEADER) > 0) {
+			    &matchlen, POS_SDP_HEADER) > 0) {
 
 		/* since ct_sip_get_info() give us a pointer passing 'v='
 		   we need to add 2 bytes in this count. */
@@ -180,7 +180,7 @@
 
 		/* Now, update SDP length */
 		if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff,
-		                    &matchlen, POS_CONTENT) > 0) {
+				    &matchlen, POS_CONTENT) > 0) {
 
 			bufflen = sprintf(buffer, "%u", c_len);
 			return nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
@@ -205,17 +205,17 @@
 	/* Mangle owner and contact info. */
 	bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
 	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-	                       buffer, bufflen, POS_OWNER_IP4))
+			       buffer, bufflen, POS_OWNER_IP4))
 		return 0;
 
 	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-	                       buffer, bufflen, POS_CONNECTION_IP4))
+			       buffer, bufflen, POS_CONNECTION_IP4))
 		return 0;
 
 	/* Mangle media port. */
 	bufflen = sprintf(buffer, "%u", port);
 	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
-	                       buffer, bufflen, POS_MEDIA))
+			       buffer, bufflen, POS_MEDIA))
 		return 0;
 
 	return mangle_content_len(pskb, ctinfo, ct, dptr);
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index f12528f..ce5c493 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -150,8 +150,8 @@
 };
 
 static void asn1_open(struct asn1_ctx *ctx,
-                      unsigned char *buf,
-                      unsigned int len)
+		      unsigned char *buf,
+		      unsigned int len)
 {
 	ctx->begin = buf;
 	ctx->end = buf + len;
@@ -186,9 +186,9 @@
 }
 
 static unsigned char asn1_id_decode(struct asn1_ctx *ctx,
-                                    unsigned int *cls,
-                                    unsigned int *con,
-                                    unsigned int *tag)
+				    unsigned int *cls,
+				    unsigned int *con,
+				    unsigned int *tag)
 {
 	unsigned char ch;
 
@@ -207,8 +207,8 @@
 }
 
 static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
-                                        unsigned int *def,
-                                        unsigned int *len)
+					unsigned int *def,
+					unsigned int *len)
 {
 	unsigned char ch, cnt;
 
@@ -239,10 +239,10 @@
 }
 
 static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
-                                        unsigned char **eoc,
-                                        unsigned int *cls,
-                                        unsigned int *con,
-                                        unsigned int *tag)
+					unsigned char **eoc,
+					unsigned int *cls,
+					unsigned int *con,
+					unsigned int *tag)
 {
 	unsigned int def, len;
 
@@ -297,8 +297,8 @@
 }
 
 static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
-                                      unsigned char *eoc,
-                                      long *integer)
+				      unsigned char *eoc,
+				      long *integer)
 {
 	unsigned char ch;
 	unsigned int  len;
@@ -325,8 +325,8 @@
 }
 
 static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
-                                      unsigned char *eoc,
-                                      unsigned int *integer)
+				      unsigned char *eoc,
+				      unsigned int *integer)
 {
 	unsigned char ch;
 	unsigned int  len;
@@ -354,8 +354,8 @@
 }
 
 static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
-                                       unsigned char *eoc,
-                                       unsigned long *integer)
+				       unsigned char *eoc,
+				       unsigned long *integer)
 {
 	unsigned char ch;
 	unsigned int  len;
@@ -383,9 +383,9 @@
 }
 
 static unsigned char asn1_octets_decode(struct asn1_ctx *ctx,
-                                        unsigned char *eoc,
-                                        unsigned char **octets,
-                                        unsigned int *len)
+					unsigned char *eoc,
+					unsigned char **octets,
+					unsigned int *len)
 {
 	unsigned char *ptr;
 
@@ -411,7 +411,7 @@
 }
 
 static unsigned char asn1_subid_decode(struct asn1_ctx *ctx,
-                                       unsigned long *subid)
+				       unsigned long *subid)
 {
 	unsigned char ch;
 
@@ -428,9 +428,9 @@
 }
 
 static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
-                                     unsigned char *eoc,
-                                     unsigned long **oid,
-                                     unsigned int *len)
+				     unsigned char *eoc,
+				     unsigned long **oid,
+				     unsigned int *len)
 {
 	unsigned long subid;
 	unsigned int  size;
@@ -611,9 +611,9 @@
 #define SERR_EOM    2
 
 static inline void mangle_address(unsigned char *begin,
-                                  unsigned char *addr,
-                                  const struct oct1_map *map,
-                                  __sum16 *check);
+				  unsigned char *addr,
+				  const struct oct1_map *map,
+				  __sum16 *check);
 struct snmp_cnv
 {
 	unsigned int class;
@@ -644,8 +644,8 @@
 };
 
 static unsigned char snmp_tag_cls2syntax(unsigned int tag,
-                                         unsigned int cls,
-                                         unsigned short *syntax)
+					 unsigned int cls,
+					 unsigned short *syntax)
 {
 	struct snmp_cnv *cnv;
 
@@ -662,7 +662,7 @@
 }
 
 static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
-                                        struct snmp_object **obj)
+					struct snmp_object **obj)
 {
 	unsigned int cls, con, tag, len, idlen;
 	unsigned short type;
@@ -714,7 +714,7 @@
 				return 0;
 			}
 			*obj = kmalloc(sizeof(struct snmp_object) + len,
-			               GFP_ATOMIC);
+				       GFP_ATOMIC);
 			if (*obj == NULL) {
 				kfree(id);
 				if (net_ratelimit())
@@ -730,7 +730,7 @@
 				return 0;
 			}
 			*obj = kmalloc(sizeof(struct snmp_object) + len,
-			               GFP_ATOMIC);
+				       GFP_ATOMIC);
 			if (*obj == NULL) {
 				kfree(id);
 				if (net_ratelimit())
@@ -834,7 +834,7 @@
 }
 
 static unsigned char snmp_request_decode(struct asn1_ctx *ctx,
-                                         struct snmp_request *request)
+					 struct snmp_request *request)
 {
 	unsigned int cls, con, tag;
 	unsigned char *end;
@@ -874,9 +874,9 @@
  * code example in the draft.
  */
 static void fast_csum(__sum16 *csum,
-                      const unsigned char *optr,
-                      const unsigned char *nptr,
-                      int offset)
+		      const unsigned char *optr,
+		      const unsigned char *nptr,
+		      int offset)
 {
 	unsigned char s[4];
 
@@ -899,9 +899,9 @@
  *      - addr points to the start of the address
  */
 static inline void mangle_address(unsigned char *begin,
-                                  unsigned char *addr,
-                                  const struct oct1_map *map,
-                                  __sum16 *check)
+				  unsigned char *addr,
+				  const struct oct1_map *map,
+				  __sum16 *check)
 {
 	if (map->from == NOCT1(addr)) {
 		u_int32_t old;
@@ -914,7 +914,7 @@
 		/* Update UDP checksum if being used */
 		if (*check) {
 			fast_csum(check,
-			          &map->from, &map->to, addr - begin);
+				  &map->from, &map->to, addr - begin);
 
 		}
 
@@ -925,9 +925,9 @@
 }
 
 static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
-                                      struct snmp_v1_trap *trap,
-                                      const struct oct1_map *map,
-                                      __sum16 *check)
+				      struct snmp_v1_trap *trap,
+				      const struct oct1_map *map,
+				      __sum16 *check)
 {
 	unsigned int cls, con, tag, len;
 	unsigned char *end;
@@ -1019,9 +1019,9 @@
  * (And this is the fucking 'basic' method).
  */
 static int snmp_parse_mangle(unsigned char *msg,
-                             u_int16_t len,
-                             const struct oct1_map *map,
-                             __sum16 *check)
+			     u_int16_t len,
+			     const struct oct1_map *map,
+			     __sum16 *check)
 {
 	unsigned char *eoc, *end;
 	unsigned int cls, con, tag, vers, pdutype;
@@ -1191,8 +1191,8 @@
  * SNMP translation routine.
  */
 static int snmp_translate(struct nf_conn *ct,
-                          enum ip_conntrack_info ctinfo,
-                          struct sk_buff **pskb)
+			  enum ip_conntrack_info ctinfo,
+			  struct sk_buff **pskb)
 {
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
@@ -1219,7 +1219,7 @@
 		return NF_ACCEPT;
 
 	if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),
-	                       paylen, &map, &udph->check)) {
+			       paylen, &map, &udph->check)) {
 		if (net_ratelimit())
 			printk(KERN_WARNING "bsalg: parser failed\n");
 		return NF_DROP;
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 00d6dea..e4d3ef1 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -32,12 +32,6 @@
 #define DEBUGP(format, args...)
 #endif
 
-#define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING"  \
-			   : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \
-			      : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT"  \
-			         : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN"  \
-				    : "*ERROR*")))
-
 #ifdef CONFIG_XFRM
 static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
 {
@@ -102,8 +96,8 @@
 	   protocol. 8) --RR */
 	if (!ct) {
 		/* Exception: ICMP redirect to new connection (not in
-                   hash table yet).  We must not let this through, in
-                   case we're doing NAT to the same network. */
+		   hash table yet).  We must not let this through, in
+		   case we're doing NAT to the same network. */
 		if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
 			struct icmphdr _hdr, *hp;
 
@@ -147,7 +141,7 @@
 			if (unlikely(nf_ct_is_confirmed(ct)))
 				/* NAT module was loaded late */
 				ret = alloc_null_binding_confirmed(ct, info,
-				                                   hooknum);
+								   hooknum);
 			else if (hooknum == NF_IP_LOCAL_IN)
 				/* LOCAL_IN hook doesn't have a chain!  */
 				ret = alloc_null_binding(ct, info, hooknum);
@@ -177,10 +171,10 @@
 
 static unsigned int
 nf_nat_in(unsigned int hooknum,
-          struct sk_buff **pskb,
-          const struct net_device *in,
-          const struct net_device *out,
-          int (*okfn)(struct sk_buff *))
+	  struct sk_buff **pskb,
+	  const struct net_device *in,
+	  const struct net_device *out,
+	  int (*okfn)(struct sk_buff *))
 {
 	unsigned int ret;
 	__be32 daddr = (*pskb)->nh.iph->daddr;
@@ -275,9 +269,9 @@
 
 	ct = nf_ct_get(*pskb, &ctinfo);
 	if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
-	        DEBUGP("nf_nat_standalone: adjusting sequence number\n");
-	        if (!nf_nat_seq_adjust(pskb, ct, ctinfo))
-	                return NF_DROP;
+		DEBUGP("nf_nat_standalone: adjusting sequence number\n");
+		if (!nf_nat_seq_adjust(pskb, ct, ctinfo))
+			return NF_DROP;
 	}
 	return NF_ACCEPT;
 }
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cd873da..ae68a69 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -79,7 +79,7 @@
 	return single_open(file, sockstat_seq_show, NULL);
 }
 
-static struct file_operations sockstat_seq_fops = {
+static const struct file_operations sockstat_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = sockstat_seq_open,
 	.read	 = seq_read,
@@ -266,7 +266,7 @@
 
 	for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
 		seq_printf(seq, " %lu",
-			   fold_field((void **) ip_statistics, 
+			   fold_field((void **) ip_statistics,
 				      snmp4_ipstats_list[i].entry));
 
 	seq_puts(seq, "\nIcmp:");
@@ -276,7 +276,7 @@
 	seq_puts(seq, "\nIcmp:");
 	for (i = 0; snmp4_icmp_list[i].name != NULL; i++)
 		seq_printf(seq, " %lu",
-			   fold_field((void **) icmp_statistics, 
+			   fold_field((void **) icmp_statistics,
 				      snmp4_icmp_list[i].entry));
 
 	seq_puts(seq, "\nTcp:");
@@ -288,7 +288,7 @@
 		/* MaxConn field is signed, RFC 2012 */
 		if (snmp4_tcp_list[i].entry == TCP_MIB_MAXCONN)
 			seq_printf(seq, " %ld",
-				   fold_field((void **) tcp_statistics, 
+				   fold_field((void **) tcp_statistics,
 					      snmp4_tcp_list[i].entry));
 		else
 			seq_printf(seq, " %lu",
@@ -303,7 +303,7 @@
 	seq_puts(seq, "\nUdp:");
 	for (i = 0; snmp4_udp_list[i].name != NULL; i++)
 		seq_printf(seq, " %lu",
-			   fold_field((void **) udp_statistics, 
+			   fold_field((void **) udp_statistics,
 				      snmp4_udp_list[i].entry));
 
 	/* the UDP and UDP-Lite MIBs are the same */
@@ -326,7 +326,7 @@
 	return single_open(file, snmp_seq_show, NULL);
 }
 
-static struct file_operations snmp_seq_fops = {
+static const struct file_operations snmp_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = snmp_seq_open,
 	.read	 = seq_read,
@@ -348,7 +348,7 @@
 	seq_puts(seq, "\nTcpExt:");
 	for (i = 0; snmp4_net_list[i].name != NULL; i++)
 		seq_printf(seq, " %lu",
-			   fold_field((void **) net_statistics, 
+			   fold_field((void **) net_statistics,
 				      snmp4_net_list[i].entry));
 
 	seq_putc(seq, '\n');
@@ -360,7 +360,7 @@
 	return single_open(file, netstat_seq_show, NULL);
 }
 
-static struct file_operations netstat_seq_fops = {
+static const struct file_operations netstat_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = netstat_seq_open,
 	.read	 = seq_read,
diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c
index 05f5114..da70fef 100644
--- a/net/ipv4/protocol.c
+++ b/net/ipv4/protocol.c
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/socket.h>
 #include <linux/in.h>
@@ -74,7 +73,7 @@
 /*
  *	Remove a protocol from the hash tables.
  */
- 
+
 int inet_del_protocol(struct net_protocol *prot, unsigned char protocol)
 {
 	int hash, ret;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index a6c63bb..87e9c16 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -95,7 +95,7 @@
 
 static void raw_v4_unhash(struct sock *sk)
 {
- 	write_lock_bh(&raw_v4_lock);
+	write_lock_bh(&raw_v4_lock);
 	if (sk_del_node_init(sk))
 		sock_prot_dec_use(sk->sk_prot);
 	write_unlock_bh(&raw_v4_lock);
@@ -238,7 +238,7 @@
 static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb)
 {
 	/* Charge it to the socket. */
-	
+
 	if (sock_queue_rcv_skb(sk, skb) < 0) {
 		/* FIXME: increment a raw drops counter here */
 		kfree_skb(skb);
@@ -263,7 +263,7 @@
 }
 
 static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
-			struct rtable *rt, 
+			struct rtable *rt,
 			unsigned int flags)
 {
 	struct inet_sock *inet = inet_sk(sk);
@@ -285,7 +285,7 @@
 	skb = sock_alloc_send_skb(sk, length+hh_len+15,
 				  flags&MSG_DONTWAIT, &err);
 	if (skb == NULL)
-		goto error; 
+		goto error;
 	skb_reserve(skb, hh_len);
 
 	skb->priority = sk->sk_priority;
@@ -326,7 +326,7 @@
 	kfree_skb(skb);
 error:
 	IP_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
-	return err; 
+	return err;
 }
 
 static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
@@ -399,9 +399,9 @@
 	err = -EOPNOTSUPP;
 	if (msg->msg_flags & MSG_OOB)	/* Mirror BSD error message */
 		goto out;               /* compatibility */
-			 
+
 	/*
-	 *	Get and verify the address. 
+	 *	Get and verify the address.
 	 */
 
 	if (msg->msg_namelen) {
@@ -426,7 +426,7 @@
 		 */
 	} else {
 		err = -EDESTADDRREQ;
-		if (sk->sk_state != TCP_ESTABLISHED) 
+		if (sk->sk_state != TCP_ESTABLISHED)
 			goto out;
 		daddr = inet->daddr;
 	}
@@ -480,7 +480,7 @@
 						.saddr = saddr,
 						.tos = tos } },
 				    .proto = inet->hdrincl ? IPPROTO_RAW :
-					    		     sk->sk_protocol,
+							     sk->sk_protocol,
 				  };
 		if (!inet->hdrincl) {
 			err = raw_probe_proto_opt(&fl, msg);
@@ -489,7 +489,7 @@
 		}
 
 		security_sk_classify_flow(sk, &fl);
-		err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
+		err = ip_route_output_flow(&rt, &fl, sk, 1);
 	}
 	if (err)
 		goto done;
@@ -503,9 +503,9 @@
 back_from_confirm:
 
 	if (inet->hdrincl)
-		err = raw_send_hdrinc(sk, msg->msg_iov, len, 
+		err = raw_send_hdrinc(sk, msg->msg_iov, len,
 					rt, msg->msg_flags);
-	
+
 	 else {
 		if (!ipc.addr)
 			ipc.addr = rt->rt_dst;
@@ -538,7 +538,7 @@
 
 static void raw_close(struct sock *sk, long timeout)
 {
-        /*
+	/*
 	 * Raw sockets may have direct kernel refereneces. Kill them.
 	 */
 	ip_ra_control(sk, 0, NULL);
@@ -861,7 +861,7 @@
 
 	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
 		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
-		i, src, srcp, dest, destp, sp->sk_state, 
+		i, src, srcp, dest, destp, sp->sk_state,
 		atomic_read(&sp->sk_wmem_alloc),
 		atomic_read(&sp->sk_rmem_alloc),
 		0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
@@ -916,7 +916,7 @@
 	goto out;
 }
 
-static struct file_operations raw_seq_fops = {
+static const struct file_operations raw_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = raw_seq_open,
 	.read	 = seq_read,
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 2daa0dc..37e0d4d 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -20,7 +20,7 @@
  *		(rco@di.uminho.pt)	Routing table insertion and update
  *		Linus Torvalds	:	Rewrote bits to be sensible
  *		Alan Cox	:	Added BSD route gw semantics
- *		Alan Cox	:	Super /proc >4K 
+ *		Alan Cox	:	Super /proc >4K
  *		Alan Cox	:	MTU in route table
  *		Alan Cox	: 	MSS actually. Also added the window
  *					clamper.
@@ -38,7 +38,7 @@
  *		Alan Cox	:	Faster /proc handling
  *	Alexey Kuznetsov	:	Massive rework to support tree based routing,
  *					routing caches and better behaviour.
- *		
+ *
  *		Olaf Erb	:	irtt wasn't being copied right.
  *		Bjorn Ekwall	:	Kerneld route support.
  *		Alan Cox	:	Multicast fixed (I hope)
@@ -70,7 +70,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
 #include <linux/string.h>
@@ -289,7 +288,7 @@
 {
 	struct rt_cache_iter_state *st = rcu_dereference(seq->private);
 
-	r = r->u.rt_next;
+	r = r->u.dst.rt_next;
 	while (!r) {
 		rcu_read_unlock_bh();
 		if (--st->bucket < 0)
@@ -361,8 +360,8 @@
 				       dev_queue_xmit) : 0,
 			r->rt_spec_dst);
 		seq_printf(seq, "%-127s\n", temp);
-        }
-  	return 0;
+	}
+	return 0;
 }
 
 static struct seq_operations rt_cache_seq_ops = {
@@ -393,7 +392,7 @@
 	goto out;
 }
 
-static struct file_operations rt_cache_seq_fops = {
+static const struct file_operations rt_cache_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = rt_cache_seq_open,
 	.read	 = seq_read,
@@ -429,7 +428,7 @@
 		return &per_cpu(rt_cache_stat, cpu);
 	}
 	return NULL;
-	
+
 }
 
 static void rt_cpu_seq_stop(struct seq_file *seq, void *v)
@@ -445,7 +444,7 @@
 		seq_printf(seq, "entries  in_hit in_slow_tot in_slow_mc in_no_route in_brd in_martian_dst in_martian_src  out_hit out_slow_tot out_slow_mc  gc_total gc_ignored gc_goal_miss gc_dst_overflow in_hlist_search out_hlist_search\n");
 		return 0;
 	}
-	
+
 	seq_printf(seq,"%08x  %08x %08x %08x %08x %08x %08x %08x "
 		   " %08x %08x %08x %08x %08x %08x %08x %08x %08x \n",
 		   atomic_read(&ipv4_dst_ops.entries),
@@ -459,7 +458,7 @@
 
 		   st->out_hit,
 		   st->out_slow_tot,
-		   st->out_slow_mc, 
+		   st->out_slow_mc,
 
 		   st->gc_total,
 		   st->gc_ignored,
@@ -484,7 +483,7 @@
 	return seq_open(file, &rt_cpu_seq_ops);
 }
 
-static struct file_operations rt_cpu_seq_fops = {
+static const struct file_operations rt_cpu_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = rt_cpu_seq_open,
 	.read	 = seq_read,
@@ -493,7 +492,7 @@
 };
 
 #endif /* CONFIG_PROC_FS */
-  
+
 static __inline__ void rt_free(struct rtable *rt)
 {
 	multipath_remove(rt);
@@ -512,7 +511,7 @@
 	/* Kill broadcast/multicast entries very aggresively, if they
 	   collide in hash table with more useful entries */
 	return (rth->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) &&
-		rth->fl.iif && rth->u.rt_next;
+		rth->fl.iif && rth->u.dst.rt_next;
 }
 
 static __inline__ int rt_valuable(struct rtable *rth)
@@ -595,10 +594,10 @@
 		if (((*rthp)->u.dst.flags & DST_BALANCED) != 0  &&
 		    compare_keys(&(*rthp)->fl, &expentry->fl)) {
 			if (*rthp == expentry) {
-				*rthp = rth->u.rt_next;
+				*rthp = rth->u.dst.rt_next;
 				continue;
 			} else {
-				*rthp = rth->u.rt_next;
+				*rthp = rth->u.dst.rt_next;
 				rt_free(rth);
 				if (removed_count)
 					++(*removed_count);
@@ -606,9 +605,9 @@
 		} else {
 			if (!((*rthp)->u.dst.flags & DST_BALANCED) &&
 			    passedexpired && !nextstep)
-				nextstep = &rth->u.rt_next;
+				nextstep = &rth->u.dst.rt_next;
 
-			rthp = &rth->u.rt_next;
+			rthp = &rth->u.dst.rt_next;
 		}
 	}
 
@@ -649,12 +648,12 @@
 				/* Entry is expired even if it is in use */
 				if (time_before_eq(now, rth->u.dst.expires)) {
 					tmo >>= 1;
-					rthp = &rth->u.rt_next;
+					rthp = &rth->u.dst.rt_next;
 					continue;
 				}
 			} else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) {
 				tmo >>= 1;
-				rthp = &rth->u.rt_next;
+				rthp = &rth->u.dst.rt_next;
 				continue;
 			}
 
@@ -668,12 +667,12 @@
 				if (!rthp)
 					break;
 			} else {
-				*rthp = rth->u.rt_next;
+				*rthp = rth->u.dst.rt_next;
 				rt_free(rth);
 			}
 #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
- 			*rthp = rth->u.rt_next;
- 			rt_free(rth);
+			*rthp = rth->u.dst.rt_next;
+			rt_free(rth);
 #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
 		}
 		spin_unlock(rt_hash_lock_addr(i));
@@ -706,7 +705,7 @@
 		spin_unlock_bh(rt_hash_lock_addr(i));
 
 		for (; rth; rth = next) {
-			next = rth->u.rt_next;
+			next = rth->u.dst.rt_next;
 			rt_free(rth);
 		}
 	}
@@ -739,7 +738,7 @@
 
 		if (user_mode && tmo < ip_rt_max_delay-ip_rt_min_delay)
 			tmo = 0;
-		
+
 		if (delay > tmo)
 			delay = tmo;
 	}
@@ -840,7 +839,7 @@
 			while ((rth = *rthp) != NULL) {
 				if (!rt_may_expire(rth, tmo, expire)) {
 					tmo >>= 1;
-					rthp = &rth->u.rt_next;
+					rthp = &rth->u.dst.rt_next;
 					continue;
 				}
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
@@ -858,12 +857,12 @@
 					if (!rthp)
 						break;
 				} else {
-					*rthp = rth->u.rt_next;
+					*rthp = rth->u.dst.rt_next;
 					rt_free(rth);
 					goal--;
 				}
 #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
-				*rthp = rth->u.rt_next;
+				*rthp = rth->u.dst.rt_next;
 				rt_free(rth);
 				goal--;
 #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
@@ -947,13 +946,13 @@
 		if (compare_keys(&rth->fl, &rt->fl)) {
 #endif
 			/* Put it first */
-			*rthp = rth->u.rt_next;
+			*rthp = rth->u.dst.rt_next;
 			/*
 			 * Since lookup is lockfree, the deletion
 			 * must be visible to another weakly ordered CPU before
 			 * the insertion at the start of the hash chain.
 			 */
-			rcu_assign_pointer(rth->u.rt_next,
+			rcu_assign_pointer(rth->u.dst.rt_next,
 					   rt_hash_table[hash].chain);
 			/*
 			 * Since lookup is lockfree, the update writes
@@ -983,7 +982,7 @@
 
 		chain_length++;
 
-		rthp = &rth->u.rt_next;
+		rthp = &rth->u.dst.rt_next;
 	}
 
 	if (cand) {
@@ -994,7 +993,7 @@
 		 * only 2 entries per bucket. We will see.
 		 */
 		if (chain_length > ip_rt_gc_elasticity) {
-			*candp = cand->u.rt_next;
+			*candp = cand->u.dst.rt_next;
 			rt_free(cand);
 		}
 	}
@@ -1034,13 +1033,13 @@
 		}
 	}
 
-	rt->u.rt_next = rt_hash_table[hash].chain;
+	rt->u.dst.rt_next = rt_hash_table[hash].chain;
 #if RT_CACHE_DEBUG >= 2
-	if (rt->u.rt_next) {
+	if (rt->u.dst.rt_next) {
 		struct rtable *trt;
 		printk(KERN_DEBUG "rt_cache @%02x: %u.%u.%u.%u", hash,
 		       NIPQUAD(rt->rt_dst));
-		for (trt = rt->u.rt_next; trt; trt = trt->u.rt_next)
+		for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next)
 			printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst));
 		printk("\n");
 	}
@@ -1104,7 +1103,7 @@
 			return;
 		}
 	} else
-		printk(KERN_DEBUG "rt_bind_peer(0) @%p\n", 
+		printk(KERN_DEBUG "rt_bind_peer(0) @%p\n",
 		       __builtin_return_address(0));
 
 	ip_select_fb_ident(iph);
@@ -1117,9 +1116,9 @@
 	spin_lock_bh(rt_hash_lock_addr(hash));
 	ip_rt_put(rt);
 	for (rthp = &rt_hash_table[hash].chain; *rthp;
-	     rthp = &(*rthp)->u.rt_next)
+	     rthp = &(*rthp)->u.dst.rt_next)
 		if (*rthp == rt) {
-			*rthp = rt->u.rt_next;
+			*rthp = rt->u.dst.rt_next;
 			rt_free(rt);
 			break;
 		}
@@ -1167,7 +1166,7 @@
 				    rth->fl.fl4_src != skeys[i] ||
 				    rth->fl.oif != ikeys[k] ||
 				    rth->fl.iif != 0) {
-					rthp = &rth->u.rt_next;
+					rthp = &rth->u.dst.rt_next;
 					continue;
 				}
 
@@ -1190,7 +1189,7 @@
 
 				/* Copy all the information. */
 				*rt = *rth;
- 				INIT_RCU_HEAD(&rt->u.dst.rcu_head);
+				INIT_RCU_HEAD(&rt->u.dst.rcu_head);
 				rt->u.dst.__use		= 1;
 				atomic_set(&rt->u.dst.__refcnt, 1);
 				rt->u.dst.child		= NULL;
@@ -1225,11 +1224,11 @@
 					rt_drop(rt);
 					goto do_next;
 				}
-				
+
 				netevent.old = &rth->u.dst;
 				netevent.new = &rt->u.dst;
-				call_netevent_notifiers(NETEVENT_REDIRECT, 
-						        &netevent);
+				call_netevent_notifiers(NETEVENT_REDIRECT,
+							&netevent);
 
 				rt_del(hash, rth);
 				if (!rt_intern_hash(hash, rt, &rt))
@@ -1343,7 +1342,7 @@
 #endif
 	}
 out:
-        in_dev_put(in_dev);
+	in_dev_put(in_dev);
 }
 
 static int ip_error(struct sk_buff *skb)
@@ -1379,7 +1378,7 @@
 
 out:	kfree_skb(skb);
 	return 0;
-} 
+}
 
 /*
  *	The last two values are not from the RFC but
@@ -1392,7 +1391,7 @@
 static __inline__ unsigned short guess_mtu(unsigned short old_mtu)
 {
 	int i;
-	
+
 	for (i = 0; i < ARRAY_SIZE(mtu_plateau); i++)
 		if (old_mtu > mtu_plateau[i])
 			return mtu_plateau[i];
@@ -1416,7 +1415,7 @@
 
 		rcu_read_lock();
 		for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
-		     rth = rcu_dereference(rth->u.rt_next)) {
+		     rth = rcu_dereference(rth->u.dst.rt_next)) {
 			if (rth->fl.fl4_dst == daddr &&
 			    rth->fl.fl4_src == skeys[i] &&
 			    rth->rt_dst  == daddr &&
@@ -1436,7 +1435,7 @@
 					mtu = guess_mtu(old_mtu);
 				}
 				if (mtu <= rth->u.dst.metrics[RTAX_MTU-1]) {
-					if (mtu < rth->u.dst.metrics[RTAX_MTU-1]) { 
+					if (mtu < rth->u.dst.metrics[RTAX_MTU-1]) {
 						dst_confirm(&rth->u.dst);
 						if (mtu < ip_rt_min_pmtu) {
 							mtu = ip_rt_min_pmtu;
@@ -1600,7 +1599,7 @@
 #endif
 	set_class_tag(rt, itag);
 #endif
-        rt->rt_type = res->type;
+	rt->rt_type = res->type;
 }
 
 static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
@@ -1714,11 +1713,11 @@
 #endif
 }
 
-static inline int __mkroute_input(struct sk_buff *skb, 
-				  struct fib_result* res, 
-				  struct in_device *in_dev, 
+static inline int __mkroute_input(struct sk_buff *skb,
+				  struct fib_result* res,
+				  struct in_device *in_dev,
 				  __be32 daddr, __be32 saddr, u32 tos,
-				  struct rtable **result) 
+				  struct rtable **result)
 {
 
 	struct rtable *rth;
@@ -1738,12 +1737,12 @@
 	}
 
 
-	err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), 
+	err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res),
 				  in_dev->dev, &spec_dst, &itag);
 	if (err < 0) {
-		ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, 
+		ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr,
 					 saddr);
-		
+
 		err = -EINVAL;
 		goto cleanup;
 	}
@@ -1811,10 +1810,10 @@
 	/* release the working reference to the output device */
 	in_dev_put(out_dev);
 	return err;
-}						
+}
 
-static inline int ip_mkroute_input_def(struct sk_buff *skb, 
-				       struct fib_result* res, 
+static inline int ip_mkroute_input_def(struct sk_buff *skb,
+				       struct fib_result* res,
 				       const struct flowi *fl,
 				       struct in_device *in_dev,
 				       __be32 daddr, __be32 saddr, u32 tos)
@@ -1835,11 +1834,11 @@
 
 	/* put it into the cache */
 	hash = rt_hash(daddr, saddr, fl->iif);
-	return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);	
+	return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
 }
 
-static inline int ip_mkroute_input(struct sk_buff *skb, 
-				   struct fib_result* res, 
+static inline int ip_mkroute_input(struct sk_buff *skb,
+				   struct fib_result* res,
 				   const struct flowi *fl,
 				   struct in_device *in_dev,
 				   __be32 daddr, __be32 saddr, u32 tos)
@@ -1859,7 +1858,7 @@
 	if (hopcount < 2)
 		return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
 					    saddr, tos);
-	
+
 	/* add all alternatives to the routing cache */
 	for (hop = 0; hop < hopcount; hop++) {
 		res->nh_sel = hop;
@@ -1988,7 +1987,7 @@
 		goto e_nobufs;
 	if (err == -EINVAL)
 		goto e_inval;
-	
+
 done:
 	in_dev_put(in_dev);
 	if (free_res)
@@ -2071,8 +2070,8 @@
 #endif
 
 e_hostunreach:
-        err = -EHOSTUNREACH;
-        goto done;
+	err = -EHOSTUNREACH;
+	goto done;
 
 e_inval:
 	err = -EINVAL;
@@ -2099,7 +2098,7 @@
 
 	rcu_read_lock();
 	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
-	     rth = rcu_dereference(rth->u.rt_next)) {
+	     rth = rcu_dereference(rth->u.dst.rt_next)) {
 		if (rth->fl.fl4_dst == daddr &&
 		    rth->fl.fl4_src == saddr &&
 		    rth->fl.iif == iif &&
@@ -2153,11 +2152,11 @@
 }
 
 static inline int __mkroute_output(struct rtable **result,
-				   struct fib_result* res, 
+				   struct fib_result* res,
 				   const struct flowi *fl,
-				   const struct flowi *oldflp, 
-				   struct net_device *dev_out, 
-				   unsigned flags) 
+				   const struct flowi *oldflp,
+				   struct net_device *dev_out,
+				   unsigned flags)
 {
 	struct rtable *rth;
 	struct in_device *in_dev;
@@ -2190,7 +2189,7 @@
 		}
 	} else if (res->type == RTN_MULTICAST) {
 		flags |= RTCF_MULTICAST|RTCF_LOCAL;
-		if (!ip_check_mc(in_dev, oldflp->fl4_dst, oldflp->fl4_src, 
+		if (!ip_check_mc(in_dev, oldflp->fl4_dst, oldflp->fl4_src,
 				 oldflp->proto))
 			flags &= ~RTCF_LOCAL;
 		/* If multicast route do not exist use
@@ -2208,7 +2207,7 @@
 	if (!rth) {
 		err = -ENOBUFS;
 		goto cleanup;
-	}		
+	}
 
 	atomic_set(&rth->u.dst.__refcnt, 1);
 	rth->u.dst.flags= DST_HOST;
@@ -2232,7 +2231,7 @@
 	rth->rt_dst	= fl->fl4_dst;
 	rth->rt_src	= fl->fl4_src;
 	rth->rt_iif	= oldflp->oif ? : dev_out->ifindex;
-	/* get references to the devices that are to be hold by the routing 
+	/* get references to the devices that are to be hold by the routing
 	   cache entry */
 	rth->u.dst.dev	= dev_out;
 	dev_hold(dev_out);
@@ -2250,7 +2249,7 @@
 	}
 	if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
 		rth->rt_spec_dst = fl->fl4_src;
-		if (flags & RTCF_LOCAL && 
+		if (flags & RTCF_LOCAL &&
 		    !(dev_out->flags & IFF_LOOPBACK)) {
 			rth->u.dst.output = ip_mc_output;
 			RT_CACHE_STAT_INC(out_slow_mc);
@@ -2292,7 +2291,7 @@
 		hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif);
 		err = rt_intern_hash(hash, rth, rp);
 	}
-	
+
 	return err;
 }
 
@@ -2563,7 +2562,7 @@
 
 	rcu_read_lock_bh();
 	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
-		rth = rcu_dereference(rth->u.rt_next)) {
+		rth = rcu_dereference(rth->u.dst.rt_next)) {
 		if (rth->fl.fl4_dst == flp->fl4_dst &&
 		    rth->fl.fl4_src == flp->fl4_src &&
 		    rth->fl.iif == 0 &&
@@ -2635,7 +2634,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	r = nlmsg_data(nlh);
 	r->rtm_family	 = AF_INET;
@@ -2718,7 +2717,8 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
@@ -2824,12 +2824,12 @@
 			s_idx = 0;
 		rcu_read_lock_bh();
 		for (rt = rcu_dereference(rt_hash_table[h].chain), idx = 0; rt;
-		     rt = rcu_dereference(rt->u.rt_next), idx++) {
+		     rt = rcu_dereference(rt->u.dst.rt_next), idx++) {
 			if (idx < s_idx)
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
 			if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
-					 cb->nlh->nlmsg_seq, RTM_NEWROUTE, 
+					 cb->nlh->nlmsg_seq, RTM_NEWROUTE,
 					 1, NLM_F_MULTI) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
 				rcu_read_unlock_bh();
@@ -2862,7 +2862,7 @@
 		proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
 		rt_cache_flush(flush_delay);
 		return 0;
-	} 
+	}
 
 	return -EINVAL;
 }
@@ -2879,13 +2879,13 @@
 	if (newlen != sizeof(int))
 		return -EINVAL;
 	if (get_user(delay, (int __user *)newval))
-		return -EFAULT; 
-	rt_cache_flush(delay); 
+		return -EFAULT;
+	rt_cache_flush(delay);
 	return 0;
 }
 
 ctl_table ipv4_route_table[] = {
-        {
+	{
 		.ctl_name 	= NET_IPV4_ROUTE_FLUSH,
 		.procname	= "flush",
 		.data		= &flush_delay,
@@ -2930,7 +2930,7 @@
 	},
 	{
 		/*  Deprecated. Use gc_min_interval_ms */
- 
+
 		.ctl_name	= NET_IPV4_ROUTE_GC_MIN_INTERVAL,
 		.procname	= "gc_min_interval",
 		.data		= &ip_rt_gc_min_interval,
@@ -3179,8 +3179,8 @@
 	{
 	struct proc_dir_entry *rtstat_pde = NULL; /* keep gcc happy */
 	if (!proc_net_fops_create("rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
-	    !(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO, 
-			    		     proc_net_stat))) {
+	    !(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO,
+					     proc_net_stat))) {
 		return -ENOMEM;
 	}
 	rtstat_pde->proc_fops = &rt_cpu_seq_fops;
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 6b19530..33016cc 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -2,16 +2,16 @@
  *  Syncookies implementation for the Linux kernel
  *
  *  Copyright (C) 1997 Andi Kleen
- *  Based on ideas by D.J.Bernstein and Eric Schenk. 
+ *  Based on ideas by D.J.Bernstein and Eric Schenk.
  *
  *	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.
- * 
+ *
  *  $Id: syncookies.c,v 1.18 2002/02/01 22:01:04 davem Exp $
  *
- *  Missing: IPv6 support. 
+ *  Missing: IPv6 support.
  */
 
 #include <linux/tcp.h>
@@ -57,7 +57,7 @@
 	/*
 	 * Compute the secure sequence number.
 	 * The output should be:
-   	 *   HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24)
+	 *   HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24)
 	 *      + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
 	 * Where sseq is their sequence number and count increases every
 	 * minute by 1.
@@ -99,17 +99,17 @@
 		& COOKIEMASK;	/* Leaving the data behind */
 }
 
-/* 
+/*
  * This table has to be sorted and terminated with (__u16)-1.
  * XXX generate a better table.
  * Unresolved Issues: HIPPI with a 64k MSS is not well supported.
  */
 static __u16 const msstab[] = {
 	64 - 1,
-	256 - 1,	
+	256 - 1,
 	512 - 1,
 	536 - 1,
-	1024 - 1,	
+	1024 - 1,
 	1440 - 1,
 	1460 - 1,
 	4312 - 1,
@@ -128,7 +128,7 @@
 	int mssind;
 	const __u16 mss = *mssp;
 
-	
+
 	tp->last_synq_overflow = jiffies;
 
 	/* XXX sort msstab[] by probability?  Binary search? */
@@ -144,23 +144,23 @@
 				     jiffies / (HZ * 60), mssind);
 }
 
-/* 
+/*
  * This (misnamed) value is the age of syncookie which is permitted.
  * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
  * sysctl_tcp_retries1. It's a rather complicated formula (exponential
  * backoff) to compute at runtime so it's currently hardcoded here.
  */
 #define COUNTER_TRIES 4
-/*  
- * Check if a ack sequence number is a valid syncookie. 
+/*
+ * Check if a ack sequence number is a valid syncookie.
  * Return the decoded mss if it is, or 0 if not.
  */
 static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
 {
-	__u32 seq; 
+	__u32 seq;
 	__u32 mssind;
 
-	seq = ntohl(skb->h.th->seq)-1; 
+	seq = ntohl(skb->h.th->seq)-1;
 	mssind = check_tcp_syn_cookie(cookie,
 				      skb->nh.iph->saddr, skb->nh.iph->daddr,
 				      skb->h.th->source, skb->h.th->dest,
@@ -191,19 +191,19 @@
 	struct inet_request_sock *ireq;
 	struct tcp_request_sock *treq;
 	struct tcp_sock *tp = tcp_sk(sk);
-	__u32 cookie = ntohl(skb->h.th->ack_seq) - 1; 
+	__u32 cookie = ntohl(skb->h.th->ack_seq) - 1;
 	struct sock *ret = sk;
-	struct request_sock *req; 
-	int mss; 
-	struct rtable *rt; 
+	struct request_sock *req;
+	int mss;
+	struct rtable *rt;
 	__u8 rcv_wscale;
 
 	if (!sysctl_tcp_syncookies || !skb->h.th->ack)
 		goto out;
 
-  	if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) ||
+	if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) ||
 	    (mss = cookie_check(skb, cookie)) == 0) {
-	 	NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESFAILED);
+		NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESFAILED);
 		goto out;
 	}
 
@@ -221,9 +221,9 @@
 	ireq = inet_rsk(req);
 	treq = tcp_rsk(req);
 	treq->rcv_isn		= ntohl(skb->h.th->seq) - 1;
-	treq->snt_isn		= cookie; 
+	treq->snt_isn		= cookie;
 	req->mss		= mss;
- 	ireq->rmt_port		= skb->h.th->source;
+	ireq->rmt_port		= skb->h.th->source;
 	ireq->loc_addr		= skb->nh.iph->daddr;
 	ireq->rmt_addr		= skb->nh.iph->saddr;
 	ireq->opt		= NULL;
@@ -242,15 +242,15 @@
 	}
 
 	ireq->snd_wscale = ireq->rcv_wscale = ireq->tstamp_ok = 0;
-	ireq->wscale_ok	 = ireq->sack_ok = 0; 
-	req->expires	= 0UL; 
-	req->retrans	= 0; 
-	
+	ireq->wscale_ok	 = ireq->sack_ok = 0;
+	req->expires	= 0UL;
+	req->retrans	= 0;
+
 	/*
 	 * We need to lookup the route here to get at the correct
 	 * window size. We should better make sure that the window size
 	 * hasn't changed since we received the original syn, but I see
-	 * no easy way to do this. 
+	 * no easy way to do this.
 	 */
 	{
 		struct flowi fl = { .nl_u = { .ip4_u =
@@ -266,17 +266,17 @@
 		security_req_classify_flow(req, &fl);
 		if (ip_route_output_key(&rt, &fl)) {
 			reqsk_free(req);
-			goto out; 
+			goto out;
 		}
 	}
 
 	/* Try to redo what tcp_v4_send_synack did. */
 	req->window_clamp = dst_metric(&rt->u.dst, RTAX_WINDOW);
 	tcp_select_initial_window(tcp_full_space(sk), req->mss,
-				  &req->rcv_wnd, &req->window_clamp, 
+				  &req->rcv_wnd, &req->window_clamp,
 				  0, &rcv_wscale);
 	/* BTW win scale with syncookies is 0 by definition */
-	ireq->rcv_wscale  = rcv_wscale; 
+	ireq->rcv_wscale  = rcv_wscale;
 
 	ret = get_cookie_sock(sk, skb, req, &rt->u.dst);
 out:	return ret;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index fabf69a..0aa3047 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -24,7 +24,7 @@
 
 #ifdef CONFIG_SYSCTL
 static int zero;
-static int tcp_retr1_max = 255; 
+static int tcp_retr1_max = 255;
 static int ip_local_port_range_min[] = { 1, 1 };
 static int ip_local_port_range_max[] = { 65535, 65535 };
 #endif
@@ -187,7 +187,7 @@
 }
 
 ctl_table ipv4_table[] = {
-        {
+	{
 		.ctl_name	= NET_IPV4_TCP_TIMESTAMPS,
 		.procname	= "tcp_timestamps",
 		.data		= &sysctl_tcp_timestamps,
@@ -195,7 +195,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
-        {
+	{
 		.ctl_name	= NET_IPV4_TCP_WINDOW_SCALING,
 		.procname	= "tcp_window_scaling",
 		.data		= &sysctl_tcp_window_scaling,
@@ -203,7 +203,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
-        {
+	{
 		.ctl_name	= NET_IPV4_TCP_SACK,
 		.procname	= "tcp_sack",
 		.data		= &sysctl_tcp_sack,
@@ -211,7 +211,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
-        {
+	{
 		.ctl_name	= NET_IPV4_TCP_RETRANS_COLLAPSE,
 		.procname	= "tcp_retrans_collapse",
 		.data		= &sysctl_tcp_retrans_collapse,
@@ -219,7 +219,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
-        {
+	{
 		.ctl_name	= NET_IPV4_FORWARD,
 		.procname	= "ip_forward",
 		.data		= &ipv4_devconf.forwarding,
@@ -228,16 +228,16 @@
 		.proc_handler	= &ipv4_sysctl_forward,
 		.strategy	= &ipv4_sysctl_forward_strategy
 	},
-        {
+	{
 		.ctl_name	= NET_IPV4_DEFAULT_TTL,
 		.procname	= "ip_default_ttl",
- 		.data		= &sysctl_ip_default_ttl,
+		.data		= &sysctl_ip_default_ttl,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &ipv4_doint_and_flush,
 		.strategy	= &ipv4_doint_and_flush_strategy,
 	},
-        {
+	{
 		.ctl_name	= NET_IPV4_NO_PMTU_DISC,
 		.procname	= "ip_no_pmtu_disc",
 		.data		= &ipv4_config.no_pmtu_disc,
@@ -728,7 +728,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
-        {
+	{
 		.ctl_name	= NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS,
 		.procname	= "tcp_workaround_signed_windows",
 		.data		= &sysctl_tcp_workaround_signed_windows,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index b67e0dd..ac6516c 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -475,7 +475,7 @@
 	if (!sk->sk_send_head)
 		sk->sk_send_head = skb;
 	if (tp->nonagle & TCP_NAGLE_PUSH)
-		tp->nonagle &= ~TCP_NAGLE_PUSH; 
+		tp->nonagle &= ~TCP_NAGLE_PUSH;
 }
 
 static inline void tcp_mark_urg(struct tcp_sock *tp, int flags,
@@ -557,7 +557,7 @@
 		}
 		if (!sk_stream_wmem_schedule(sk, copy))
 			goto wait_for_memory;
-		
+
 		if (can_coalesce) {
 			skb_shinfo(skb)->frags[i - 1].size += copy;
 		} else {
@@ -1439,12 +1439,12 @@
 		dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
 
 		while (dma_async_memcpy_complete(tp->ucopy.dma_chan,
-		                                 tp->ucopy.dma_cookie, &done,
-		                                 &used) == DMA_IN_PROGRESS) {
+						 tp->ucopy.dma_cookie, &done,
+						 &used) == DMA_IN_PROGRESS) {
 			/* do partial cleanup of sk_async_wait_queue */
 			while ((skb = skb_peek(&sk->sk_async_wait_queue)) &&
 			       (dma_async_is_complete(skb->dma_cookie, done,
-			                              used) == DMA_SUCCESS)) {
+						      used) == DMA_SUCCESS)) {
 				__skb_dequeue(&sk->sk_async_wait_queue);
 				kfree_skb(skb);
 			}
@@ -2006,7 +2006,7 @@
 		info->tcpi_options |= TCPI_OPT_WSCALE;
 		info->tcpi_snd_wscale = tp->rx_opt.snd_wscale;
 		info->tcpi_rcv_wscale = tp->rx_opt.rcv_wscale;
-	} 
+	}
 
 	if (tp->ecn_flags&TCP_ECN_OK)
 		info->tcpi_options |= TCPI_OPT_ECN;
@@ -2415,10 +2415,11 @@
 					&tcp_hashinfo.ehash_size,
 					NULL,
 					0);
-	tcp_hashinfo.ehash_size = (1 << tcp_hashinfo.ehash_size) >> 1;
-	for (i = 0; i < (tcp_hashinfo.ehash_size << 1); i++) {
+	tcp_hashinfo.ehash_size = 1 << tcp_hashinfo.ehash_size;
+	for (i = 0; i < tcp_hashinfo.ehash_size; i++) {
 		rwlock_init(&tcp_hashinfo.ehash[i].lock);
 		INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].chain);
+		INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].twchain);
 	}
 
 	tcp_hashinfo.bhash =
@@ -2475,7 +2476,7 @@
 
 	printk(KERN_INFO "TCP: Hash tables configured "
 	       "(established %d bind %d)\n",
-	       tcp_hashinfo.ehash_size << 1, tcp_hashinfo.bhash_size);
+	       tcp_hashinfo.ehash_size, tcp_hashinfo.bhash_size);
 
 	tcp_register_congestion_control(&tcp_reno);
 }
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 5ca7723..5c8caf4 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -29,7 +29,7 @@
 }
 
 /*
- * Attach new congestion control algorthim to the list
+ * Attach new congestion control algorithm to the list
  * of available options.
  */
 int tcp_register_congestion_control(struct tcp_congestion_ops *ca)
@@ -313,28 +313,28 @@
 		return;
 
 	/* In "safe" area, increase. */
-        if (tp->snd_cwnd <= tp->snd_ssthresh)
+	if (tp->snd_cwnd <= tp->snd_ssthresh)
 		tcp_slow_start(tp);
 
- 	/* In dangerous area, increase slowly. */
+	/* In dangerous area, increase slowly. */
 	else if (sysctl_tcp_abc) {
- 		/* RFC3465: Appropriate Byte Count
- 		 * increase once for each full cwnd acked
- 		 */
- 		if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) {
- 			tp->bytes_acked -= tp->snd_cwnd*tp->mss_cache;
- 			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
- 				tp->snd_cwnd++;
- 		}
- 	} else {
- 		/* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd */
- 		if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
- 			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
- 				tp->snd_cwnd++;
- 			tp->snd_cwnd_cnt = 0;
- 		} else
- 			tp->snd_cwnd_cnt++;
- 	}
+		/* RFC3465: Appropriate Byte Count
+		 * increase once for each full cwnd acked
+		 */
+		if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) {
+			tp->bytes_acked -= tp->snd_cwnd*tp->mss_cache;
+			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+				tp->snd_cwnd++;
+		}
+	} else {
+		/* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd */
+		if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+				tp->snd_cwnd++;
+			tp->snd_cwnd_cnt = 0;
+		} else
+			tp->snd_cwnd_cnt++;
+	}
 }
 EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid);
 
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index 6ad1848..9a582fb 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -26,16 +26,16 @@
 					  */
 #define	BICTCP_HZ		10	/* BIC HZ 2^10 = 1024 */
 
-static int fast_convergence = 1;
-static int max_increment = 16;
-static int beta = 819;		/* = 819/1024 (BICTCP_BETA_SCALE) */
-static int initial_ssthresh = 100;
-static int bic_scale = 41;
-static int tcp_friendliness = 1;
+static int fast_convergence __read_mostly = 1;
+static int max_increment __read_mostly = 16;
+static int beta __read_mostly = 819;	/* = 819/1024 (BICTCP_BETA_SCALE) */
+static int initial_ssthresh __read_mostly = 100;
+static int bic_scale __read_mostly = 41;
+static int tcp_friendliness __read_mostly = 1;
 
-static u32 cube_rtt_scale;
-static u32 beta_scale;
-static u64 cube_factor;
+static u32 cube_rtt_scale __read_mostly;
+static u32 beta_scale __read_mostly;
+static u64 cube_factor __read_mostly;
 
 /* Note parameters that are used for precomputing scale factors are read-only */
 module_param(fast_convergence, int, 0644);
@@ -175,42 +175,42 @@
 		}
 	}
 
-        /* cubic function - calc*/
-        /* calculate c * time^3 / rtt,
-         *  while considering overflow in calculation of time^3
+	/* cubic function - calc*/
+	/* calculate c * time^3 / rtt,
+	 *  while considering overflow in calculation of time^3
 	 * (so time^3 is done by using 64 bit)
 	 * and without the support of division of 64bit numbers
 	 * (so all divisions are done by using 32 bit)
-         *  also NOTE the unit of those veriables
-         *	  time  = (t - K) / 2^bictcp_HZ
-         *	  c = bic_scale >> 10
+	 *  also NOTE the unit of those veriables
+	 *	  time  = (t - K) / 2^bictcp_HZ
+	 *	  c = bic_scale >> 10
 	 * rtt  = (srtt >> 3) / HZ
 	 * !!! The following code does not have overflow problems,
 	 * if the cwnd < 1 million packets !!!
-         */
+	 */
 
 	/* change the unit from HZ to bictcp_HZ */
-        t = ((tcp_time_stamp + (ca->delay_min>>3) - ca->epoch_start)
+	t = ((tcp_time_stamp + (ca->delay_min>>3) - ca->epoch_start)
 	     << BICTCP_HZ) / HZ;
 
-        if (t < ca->bic_K)		/* t - K */
+	if (t < ca->bic_K)		/* t - K */
 		offs = ca->bic_K - t;
-        else
-                offs = t - ca->bic_K;
+	else
+		offs = t - ca->bic_K;
 
 	/* c/rtt * (t-K)^3 */
 	delta = (cube_rtt_scale * offs * offs * offs) >> (10+3*BICTCP_HZ);
-        if (t < ca->bic_K)                                	/* below origin*/
-                bic_target = ca->bic_origin_point - delta;
-        else                                                	/* above origin*/
-                bic_target = ca->bic_origin_point + delta;
+	if (t < ca->bic_K)                                	/* below origin*/
+		bic_target = ca->bic_origin_point - delta;
+	else                                                	/* above origin*/
+		bic_target = ca->bic_origin_point + delta;
 
-        /* cubic function - calc bictcp_cnt*/
-        if (bic_target > cwnd) {
+	/* cubic function - calc bictcp_cnt*/
+	if (bic_target > cwnd) {
 		ca->cnt = cwnd / (bic_target - cwnd);
-        } else {
-                ca->cnt = 100 * cwnd;              /* very small increment*/
-        }
+	} else {
+		ca->cnt = 100 * cwnd;              /* very small increment*/
+	}
 
 	if (ca->delay_min > 0) {
 		/* max increment = Smax * rtt / 0.1  */
@@ -219,7 +219,7 @@
 			ca->cnt = min_cnt;
 	}
 
-        /* slow start and low utilization  */
+	/* slow start and low utilization  */
 	if (ca->loss_cwnd == 0)		/* could be aggressive in slow start */
 		ca->cnt = 50;
 
@@ -227,9 +227,9 @@
 	if (tcp_friendliness) {
 		u32 scale = beta_scale;
 		delta = (cwnd * scale) >> 3;
-	        while (ca->ack_cnt > delta) {		/* update tcp cwnd */
-	                ca->ack_cnt -= delta;
-        	        ca->tcp_cwnd++;
+		while (ca->ack_cnt > delta) {		/* update tcp cwnd */
+			ca->ack_cnt -= delta;
+			ca->tcp_cwnd++;
 		}
 
 		if (ca->tcp_cwnd > cwnd){	/* if bic is slower than tcp */
@@ -238,7 +238,7 @@
 			if (ca->cnt > max_cnt)
 				ca->cnt = max_cnt;
 		}
-        }
+	}
 
 	ca->cnt = (ca->cnt << ACK_RATIO_SHIFT) / ca->delayed_ack;
 	if (ca->cnt == 0)			/* cannot be zero */
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index c4fc811b..a291097 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -14,8 +14,8 @@
  * with fixed-point MD scaled <<8.
  */
 static const struct hstcp_aimd_val {
-        unsigned int cwnd;
-        unsigned int md;
+	unsigned int cwnd;
+	unsigned int md;
 } hstcp_aimd_vals[] = {
  {     38,  128, /*  0.50 */ },
  {    118,  112, /*  0.44 */ },
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 753987a..1020eb4 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -10,22 +10,23 @@
 #include <linux/module.h>
 #include <net/tcp.h>
 
-#define ALPHA_BASE	(1<<7)  /* 1.0 with shift << 7 */
-#define BETA_MIN	(1<<6)  /* 0.5 with shift << 7 */
+#define ALPHA_BASE	(1<<7)	/* 1.0 with shift << 7 */
+#define BETA_MIN	(1<<6)	/* 0.5 with shift << 7 */
 #define BETA_MAX	102	/* 0.8 with shift << 7 */
 
-static int use_rtt_scaling = 1;
+static int use_rtt_scaling __read_mostly = 1;
 module_param(use_rtt_scaling, int, 0644);
 MODULE_PARM_DESC(use_rtt_scaling, "turn on/off RTT scaling");
 
-static int use_bandwidth_switch = 1;
+static int use_bandwidth_switch __read_mostly = 1;
 module_param(use_bandwidth_switch, int, 0644);
 MODULE_PARM_DESC(use_bandwidth_switch, "turn on/off bandwidth switcher");
 
 struct htcp {
 	u32	alpha;		/* Fixed point arith, << 7 */
 	u8	beta;           /* Fixed point arith, << 7 */
-	u8	modeswitch;     /* Delay modeswitch until we had at least one congestion event */
+	u8	modeswitch;	/* Delay modeswitch
+				   until we had at least one congestion event */
 	u16	pkts_acked;
 	u32	packetcount;
 	u32	minRTT;
@@ -44,14 +45,14 @@
 	u32	lasttime;
 };
 
-static inline u32 htcp_cong_time(struct htcp *ca)
+static inline u32 htcp_cong_time(const struct htcp *ca)
 {
 	return jiffies - ca->last_cong;
 }
 
-static inline u32 htcp_ccount(struct htcp *ca)
+static inline u32 htcp_ccount(const struct htcp *ca)
 {
-	return htcp_cong_time(ca)/ca->minRTT;
+	return htcp_cong_time(ca) / ca->minRTT;
 }
 
 static inline void htcp_reset(struct htcp *ca)
@@ -67,10 +68,12 @@
 {
 	const struct tcp_sock *tp = tcp_sk(sk);
 	struct htcp *ca = inet_csk_ca(sk);
+
 	ca->last_cong = ca->undo_last_cong;
 	ca->maxRTT = ca->undo_maxRTT;
 	ca->old_maxB = ca->undo_old_maxB;
-	return max(tp->snd_cwnd, (tp->snd_ssthresh<<7)/ca->beta);
+
+	return max(tp->snd_cwnd, (tp->snd_ssthresh << 7) / ca->beta);
 }
 
 static inline void measure_rtt(struct sock *sk)
@@ -78,17 +81,19 @@
 	const struct inet_connection_sock *icsk = inet_csk(sk);
 	const struct tcp_sock *tp = tcp_sk(sk);
 	struct htcp *ca = inet_csk_ca(sk);
-	u32 srtt = tp->srtt>>3;
+	u32 srtt = tp->srtt >> 3;
 
 	/* keep track of minimum RTT seen so far, minRTT is zero at first */
 	if (ca->minRTT > srtt || !ca->minRTT)
 		ca->minRTT = srtt;
 
 	/* max RTT */
-	if (icsk->icsk_ca_state == TCP_CA_Open && tp->snd_ssthresh < 0xFFFF && htcp_ccount(ca) > 3) {
+	if (icsk->icsk_ca_state == TCP_CA_Open
+	    && tp->snd_ssthresh < 0xFFFF && htcp_ccount(ca) > 3) {
 		if (ca->maxRTT < ca->minRTT)
 			ca->maxRTT = ca->minRTT;
-		if (ca->maxRTT < srtt && srtt <= ca->maxRTT+msecs_to_jiffies(20))
+		if (ca->maxRTT < srtt
+		    && srtt <= ca->maxRTT + msecs_to_jiffies(20))
 			ca->maxRTT = srtt;
 	}
 }
@@ -116,15 +121,16 @@
 
 	ca->packetcount += pkts_acked;
 
-	if (ca->packetcount >= tp->snd_cwnd - (ca->alpha>>7? : 1)
-			&& now - ca->lasttime >= ca->minRTT
-			&& ca->minRTT > 0) {
-		__u32 cur_Bi = ca->packetcount*HZ/(now - ca->lasttime);
+	if (ca->packetcount >= tp->snd_cwnd - (ca->alpha >> 7 ? : 1)
+	    && now - ca->lasttime >= ca->minRTT
+	    && ca->minRTT > 0) {
+		__u32 cur_Bi = ca->packetcount * HZ / (now - ca->lasttime);
+
 		if (htcp_ccount(ca) <= 3) {
 			/* just after backoff */
 			ca->minB = ca->maxB = ca->Bi = cur_Bi;
 		} else {
-			ca->Bi = (3*ca->Bi + cur_Bi)/4;
+			ca->Bi = (3 * ca->Bi + cur_Bi) / 4;
 			if (ca->Bi > ca->maxB)
 				ca->maxB = ca->Bi;
 			if (ca->minB > ca->maxB)
@@ -142,7 +148,7 @@
 		u32 old_maxB = ca->old_maxB;
 		ca->old_maxB = ca->maxB;
 
-		if (!between(5*maxB, 4*old_maxB, 6*old_maxB)) {
+		if (!between(5 * maxB, 4 * old_maxB, 6 * old_maxB)) {
 			ca->beta = BETA_MIN;
 			ca->modeswitch = 0;
 			return;
@@ -150,7 +156,7 @@
 	}
 
 	if (ca->modeswitch && minRTT > msecs_to_jiffies(10) && maxRTT) {
-		ca->beta = (minRTT<<7)/maxRTT;
+		ca->beta = (minRTT << 7) / maxRTT;
 		if (ca->beta < BETA_MIN)
 			ca->beta = BETA_MIN;
 		else if (ca->beta > BETA_MAX)
@@ -169,23 +175,26 @@
 
 	if (diff > HZ) {
 		diff -= HZ;
-		factor = 1+ ( 10*diff + ((diff/2)*(diff/2)/HZ) )/HZ;
+		factor = 1 + (10 * diff + ((diff / 2) * (diff / 2) / HZ)) / HZ;
 	}
 
 	if (use_rtt_scaling && minRTT) {
-		u32 scale = (HZ<<3)/(10*minRTT);
-		scale = min(max(scale, 1U<<2), 10U<<3); /* clamping ratio to interval [0.5,10]<<3 */
-		factor = (factor<<3)/scale;
+		u32 scale = (HZ << 3) / (10 * minRTT);
+
+		/* clamping ratio to interval [0.5,10]<<3 */
+		scale = min(max(scale, 1U << 2), 10U << 3);
+		factor = (factor << 3) / scale;
 		if (!factor)
 			factor = 1;
 	}
 
-	ca->alpha = 2*factor*((1<<7)-ca->beta);
+	ca->alpha = 2 * factor * ((1 << 7) - ca->beta);
 	if (!ca->alpha)
 		ca->alpha = ALPHA_BASE;
 }
 
-/* After we have the rtt data to calculate beta, we'd still prefer to wait one
+/*
+ * After we have the rtt data to calculate beta, we'd still prefer to wait one
  * rtt before we adjust our beta to ensure we are working from a consistent
  * data.
  *
@@ -202,15 +211,16 @@
 	htcp_beta_update(ca, minRTT, maxRTT);
 	htcp_alpha_update(ca);
 
-	/* add slowly fading memory for maxRTT to accommodate routing changes etc */
+	/* add slowly fading memory for maxRTT to accommodate routing changes */
 	if (minRTT > 0 && maxRTT > minRTT)
-		ca->maxRTT = minRTT + ((maxRTT-minRTT)*95)/100;
+		ca->maxRTT = minRTT + ((maxRTT - minRTT) * 95) / 100;
 }
 
 static u32 htcp_recalc_ssthresh(struct sock *sk)
 {
 	const struct tcp_sock *tp = tcp_sk(sk);
 	const struct htcp *ca = inet_csk_ca(sk);
+
 	htcp_param_update(sk);
 	return max((tp->snd_cwnd * ca->beta) >> 7, 2U);
 }
@@ -224,10 +234,9 @@
 	if (!tcp_is_cwnd_limited(sk, in_flight))
 		return;
 
-        if (tp->snd_cwnd <= tp->snd_ssthresh)
+	if (tp->snd_cwnd <= tp->snd_ssthresh)
 		tcp_slow_start(tp);
 	else {
-
 		measure_rtt(sk);
 
 		/* In dangerous area, increase slowly.
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c26076f..1a14191 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -50,9 +50,9 @@
  *		Andi Kleen:		Make sure we never ack data there is not
  *					enough room for. Also make this condition
  *					a fatal error if it might still happen.
- *		Andi Kleen:		Add tcp_measure_rcv_mss to make 
+ *		Andi Kleen:		Add tcp_measure_rcv_mss to make
  *					connections with MSS<min(MTU,ann. MSS)
- *					work without delayed acks. 
+ *					work without delayed acks.
  *		Andi Kleen:		Process packets with PSH set in the
  *					fast path.
  *		J Hadi Salim:		ECN support
@@ -112,17 +112,17 @@
 
 #define TCP_REMNANT (TCP_FLAG_FIN|TCP_FLAG_URG|TCP_FLAG_SYN|TCP_FLAG_PSH)
 
-/* Adapt the MSS value used to make delayed ack decision to the 
+/* Adapt the MSS value used to make delayed ack decision to the
  * real world.
- */ 
+ */
 static void tcp_measure_rcv_mss(struct sock *sk,
 				const struct sk_buff *skb)
 {
 	struct inet_connection_sock *icsk = inet_csk(sk);
-	const unsigned int lss = icsk->icsk_ack.last_seg_size; 
+	const unsigned int lss = icsk->icsk_ack.last_seg_size;
 	unsigned int len;
 
-	icsk->icsk_ack.last_seg_size = 0; 
+	icsk->icsk_ack.last_seg_size = 0;
 
 	/* skb->len may jitter because of SACKs, even if peer
 	 * sends good full-sized frames.
@@ -440,15 +440,15 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 	int time;
 	int space;
-	
+
 	if (tp->rcvq_space.time == 0)
 		goto new_measure;
-	
+
 	time = tcp_time_stamp - tp->rcvq_space.time;
 	if (time < (tp->rcv_rtt_est.rtt >> 3) ||
 	    tp->rcv_rtt_est.rtt == 0)
 		return;
-	
+
 	space = 2 * (tp->copied_seq - tp->rcvq_space.seq);
 
 	space = max(tp->rcvq_space.space, space);
@@ -483,7 +483,7 @@
 			}
 		}
 	}
-	
+
 new_measure:
 	tp->rcvq_space.seq = tp->copied_seq;
 	tp->rcvq_space.time = tcp_time_stamp;
@@ -509,7 +509,7 @@
 	tcp_measure_rcv_mss(sk, skb);
 
 	tcp_rcv_rtt_measure(tp);
-	
+
 	now = tcp_time_stamp;
 
 	if (!icsk->icsk_ack.ato) {
@@ -561,7 +561,7 @@
 	/*	The following amusing code comes from Jacobson's
 	 *	article in SIGCOMM '88.  Note that rtt and mdev
 	 *	are scaled versions of rtt and mean deviation.
-	 *	This is designed to be as fast as possible 
+	 *	This is designed to be as fast as possible
 	 *	m stands for "measurement".
 	 *
 	 *	On a 1990 paper the rto value is changed to:
@@ -936,28 +936,58 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 	unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked;
 	struct tcp_sack_block_wire *sp = (struct tcp_sack_block_wire *)(ptr+2);
+	struct sk_buff *cached_skb;
 	int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
 	int reord = tp->packets_out;
 	int prior_fackets;
 	u32 lost_retrans = 0;
 	int flag = 0;
 	int dup_sack = 0;
+	int cached_fack_count;
 	int i;
+	int first_sack_index;
 
 	if (!tp->sacked_out)
 		tp->fackets_out = 0;
 	prior_fackets = tp->fackets_out;
 
+	/* Check for D-SACK. */
+	if (before(ntohl(sp[0].start_seq), TCP_SKB_CB(ack_skb)->ack_seq)) {
+		dup_sack = 1;
+		tp->rx_opt.sack_ok |= 4;
+		NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV);
+	} else if (num_sacks > 1 &&
+			!after(ntohl(sp[0].end_seq), ntohl(sp[1].end_seq)) &&
+			!before(ntohl(sp[0].start_seq), ntohl(sp[1].start_seq))) {
+		dup_sack = 1;
+		tp->rx_opt.sack_ok |= 4;
+		NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV);
+	}
+
+	/* D-SACK for already forgotten data...
+	 * Do dumb counting. */
+	if (dup_sack &&
+			!after(ntohl(sp[0].end_seq), prior_snd_una) &&
+			after(ntohl(sp[0].end_seq), tp->undo_marker))
+		tp->undo_retrans--;
+
+	/* Eliminate too old ACKs, but take into
+	 * account more or less fresh ones, they can
+	 * contain valid SACK info.
+	 */
+	if (before(TCP_SKB_CB(ack_skb)->ack_seq, prior_snd_una - tp->max_window))
+		return 0;
+
 	/* SACK fastpath:
 	 * if the only SACK change is the increase of the end_seq of
 	 * the first block then only apply that SACK block
 	 * and use retrans queue hinting otherwise slowpath */
 	flag = 1;
-	for (i = 0; i< num_sacks; i++) {
-		__u32 start_seq = ntohl(sp[i].start_seq);
-		__u32 end_seq =	 ntohl(sp[i].end_seq);
+	for (i = 0; i < num_sacks; i++) {
+		__be32 start_seq = sp[i].start_seq;
+		__be32 end_seq = sp[i].end_seq;
 
-		if (i == 0){
+		if (i == 0) {
 			if (tp->recv_sack_cache[i].start_seq != start_seq)
 				flag = 0;
 		} else {
@@ -967,39 +997,14 @@
 		}
 		tp->recv_sack_cache[i].start_seq = start_seq;
 		tp->recv_sack_cache[i].end_seq = end_seq;
-
-		/* Check for D-SACK. */
-		if (i == 0) {
-			u32 ack = TCP_SKB_CB(ack_skb)->ack_seq;
-
-			if (before(start_seq, ack)) {
-				dup_sack = 1;
-				tp->rx_opt.sack_ok |= 4;
-				NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV);
-			} else if (num_sacks > 1 &&
-				   !after(end_seq, ntohl(sp[1].end_seq)) &&
-				   !before(start_seq, ntohl(sp[1].start_seq))) {
-				dup_sack = 1;
-				tp->rx_opt.sack_ok |= 4;
-				NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV);
-			}
-
-			/* D-SACK for already forgotten data...
-			 * Do dumb counting. */
-			if (dup_sack &&
-			    !after(end_seq, prior_snd_una) &&
-			    after(end_seq, tp->undo_marker))
-				tp->undo_retrans--;
-
-			/* Eliminate too old ACKs, but take into
-			 * account more or less fresh ones, they can
-			 * contain valid SACK info.
-			 */
-			if (before(ack, prior_snd_una - tp->max_window))
-				return 0;
-		}
+	}
+	/* Clear the rest of the cache sack blocks so they won't match mistakenly. */
+	for (; i < ARRAY_SIZE(tp->recv_sack_cache); i++) {
+		tp->recv_sack_cache[i].start_seq = 0;
+		tp->recv_sack_cache[i].end_seq = 0;
 	}
 
+	first_sack_index = 0;
 	if (flag)
 		num_sacks = 1;
 	else {
@@ -1016,6 +1021,10 @@
 					tmp = sp[j];
 					sp[j] = sp[j+1];
 					sp[j+1] = tmp;
+
+					/* Track where the first SACK block goes to */
+					if (j == first_sack_index)
+						first_sack_index = j+1;
 				}
 
 			}
@@ -1025,20 +1034,22 @@
 	/* clear flag as used for different purpose in following code */
 	flag = 0;
 
+	/* Use SACK fastpath hint if valid */
+	cached_skb = tp->fastpath_skb_hint;
+	cached_fack_count = tp->fastpath_cnt_hint;
+	if (!cached_skb) {
+		cached_skb = sk->sk_write_queue.next;
+		cached_fack_count = 0;
+	}
+
 	for (i=0; i<num_sacks; i++, sp++) {
 		struct sk_buff *skb;
 		__u32 start_seq = ntohl(sp->start_seq);
 		__u32 end_seq = ntohl(sp->end_seq);
 		int fack_count;
 
-		/* Use SACK fastpath hint if valid */
-		if (tp->fastpath_skb_hint) {
-			skb = tp->fastpath_skb_hint;
-			fack_count = tp->fastpath_cnt_hint;
-		} else {
-			skb = sk->sk_write_queue.next;
-			fack_count = 0;
-		}
+		skb = cached_skb;
+		fack_count = cached_fack_count;
 
 		/* Event "B" in the comment above. */
 		if (after(end_seq, tp->high_seq))
@@ -1048,8 +1059,12 @@
 			int in_sack, pcount;
 			u8 sacked;
 
-			tp->fastpath_skb_hint = skb;
-			tp->fastpath_cnt_hint = fack_count;
+			cached_skb = skb;
+			cached_fack_count = fack_count;
+			if (i == first_sack_index) {
+				tp->fastpath_skb_hint = skb;
+				tp->fastpath_cnt_hint = fack_count;
+			}
 
 			/* The retransmission queue is always in order, so
 			 * we can short-circuit the walk early.
@@ -1234,8 +1249,8 @@
 	tp->frto_counter = 1;
 
 	if (icsk->icsk_ca_state <= TCP_CA_Disorder ||
-            tp->snd_una == tp->high_seq ||
-            (icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) {
+	    tp->snd_una == tp->high_seq ||
+	    (icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) {
 		tp->prior_ssthresh = tcp_current_ssthresh(sk);
 		tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
 		tcp_ca_event(sk, CA_EVENT_FRTO);
@@ -1954,11 +1969,11 @@
 	 * 1. Reno does not count dupacks (sacked_out) automatically. */
 	if (!tp->packets_out)
 		tp->sacked_out = 0;
-        /* 2. SACK counts snd_fack in packets inaccurately. */
+	/* 2. SACK counts snd_fack in packets inaccurately. */
 	if (tp->sacked_out == 0)
 		tp->fackets_out = 0;
 
-        /* Now state machine starts.
+	/* Now state machine starts.
 	 * A. ECE, hence prohibit cwnd undoing, the reduction is required. */
 	if (flag&FLAG_ECE)
 		tp->prior_ssthresh = 0;
@@ -2188,7 +2203,7 @@
 			 __u32 now, __s32 *seq_rtt)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 
+	struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
 	__u32 seq = tp->snd_una;
 	__u32 packets_acked;
 	int acked = 0;
@@ -2264,7 +2279,7 @@
 
 	while ((skb = skb_peek(&sk->sk_write_queue)) &&
 	       skb != sk->sk_send_head) {
-		struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 
+		struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
 		__u8 sacked = scb->sacked;
 
 		/* If our packet is before the ack sequence we can
@@ -2455,9 +2470,9 @@
 static void tcp_process_frto(struct sock *sk, u32 prior_snd_una)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	
+
 	tcp_sync_left_out(tp);
-	
+
 	if (tp->snd_una == prior_snd_una ||
 	    !before(tp->snd_una, tp->frto_highmark)) {
 		/* RTO was caused by loss, start retransmitting in
@@ -2612,7 +2627,7 @@
 	opt_rx->saw_tstamp = 0;
 
 	while(length>0) {
-	  	int opcode=*ptr++;
+		int opcode=*ptr++;
 		int opsize;
 
 		switch (opcode) {
@@ -2627,7 +2642,7 @@
 					return;
 				if (opsize > length)
 					return;	/* don't parse partial options */
-	  			switch(opcode) {
+				switch(opcode) {
 				case TCPOPT_MSS:
 					if(opsize==TCPOLEN_MSS && th->syn && !estab) {
 						u16 in_mss = ntohs(get_unaligned((__be16 *)ptr));
@@ -2686,10 +2701,10 @@
 					 */
 					break;
 #endif
-	  			};
-	  			ptr+=opsize-2;
-	  			length-=opsize;
-	  	};
+				};
+				ptr+=opsize-2;
+				length-=opsize;
+		};
 	}
 }
 
@@ -3248,7 +3263,7 @@
 			   TCP_SKB_CB(skb)->end_seq);
 
 		tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, tp->rcv_nxt);
-		
+
 		/* If window is closed, drop tail of packet. But after
 		 * remembering D-SACK for its head made in previous line.
 		 */
@@ -3327,7 +3342,7 @@
 			}
 		}
 		__skb_insert(skb, skb1, skb1->next, &tp->out_of_order_queue);
-		
+
 		/* And clean segments covered by new one as whole. */
 		while ((skb1 = skb->next) !=
 		       (struct sk_buff*)&tp->out_of_order_queue &&
@@ -3492,7 +3507,7 @@
  */
 static int tcp_prune_queue(struct sock *sk)
 {
-	struct tcp_sock *tp = tcp_sk(sk); 
+	struct tcp_sock *tp = tcp_sk(sk);
 
 	SOCK_DEBUG(sk, "prune_queue: c=%x\n", tp->copied_seq);
 
@@ -3602,7 +3617,7 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 
 	if (tcp_should_expand_sndbuf(sk, tp)) {
- 		int sndmem = max_t(u32, tp->rx_opt.mss_clamp, tp->mss_cache) +
+		int sndmem = max_t(u32, tp->rx_opt.mss_clamp, tp->mss_cache) +
 			MAX_TCP_HEADER + 16 + sizeof(struct sk_buff),
 		    demanded = max_t(unsigned int, tp->snd_cwnd,
 						   tp->reordering + 1);
@@ -3675,7 +3690,7 @@
  *	For 1003.1g we should support a new option TCP_STDURG to permit
  *	either form (or just set the sysctl tcp_stdurg).
  */
- 
+
 static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -3756,7 +3771,7 @@
 		u32 ptr = tp->urg_seq - ntohl(th->seq) + (th->doff * 4) -
 			  th->syn;
 
-		/* Is the urgent pointer pointing into this packet? */	 
+		/* Is the urgent pointer pointing into this packet? */
 		if (ptr < skb->len) {
 			u8 tmp;
 			if (skb_copy_bits(skb, ptr, &tmp, 1))
@@ -3820,7 +3835,7 @@
 	int copied_early = 0;
 
 	if (tp->ucopy.wakeup)
-          	return 0;
+		return 0;
 
 	if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
 		tp->ucopy.dma_chan = get_softnet_dma();
@@ -3856,26 +3871,26 @@
 #endif /* CONFIG_NET_DMA */
 
 /*
- *	TCP receive function for the ESTABLISHED state. 
+ *	TCP receive function for the ESTABLISHED state.
  *
- *	It is split into a fast path and a slow path. The fast path is 
+ *	It is split into a fast path and a slow path. The fast path is
  * 	disabled when:
  *	- A zero window was announced from us - zero window probing
- *        is only handled properly in the slow path. 
+ *        is only handled properly in the slow path.
  *	- Out of order segments arrived.
  *	- Urgent data is expected.
  *	- There is no buffer space left
  *	- Unexpected TCP flags/window values/header lengths are received
- *	  (detected by checking the TCP header against pred_flags) 
+ *	  (detected by checking the TCP header against pred_flags)
  *	- Data is sent in both directions. Fast path only supports pure senders
  *	  or pure receivers (this means either the sequence number or the ack
  *	  value must stay constant)
  *	- Unexpected TCP option.
  *
- *	When these conditions are not satisfied it drops into a standard 
+ *	When these conditions are not satisfied it drops into a standard
  *	receive procedure patterned after RFC793 to handle all cases.
  *	The first three cases are guaranteed by proper pred_flags setting,
- *	the rest is checked inline. Fast processing is turned on in 
+ *	the rest is checked inline. Fast processing is turned on in
  *	tcp_data_queue when everything is OK.
  */
 int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
@@ -3885,15 +3900,15 @@
 
 	/*
 	 *	Header prediction.
-	 *	The code loosely follows the one in the famous 
+	 *	The code loosely follows the one in the famous
 	 *	"30 instruction TCP receive" Van Jacobson mail.
-	 *	
-	 *	Van's trick is to deposit buffers into socket queue 
+	 *
+	 *	Van's trick is to deposit buffers into socket queue
 	 *	on a device interrupt, to call tcp_recv function
 	 *	on the receive process context and checksum and copy
 	 *	the buffer to user space. smart...
 	 *
-	 *	Our current scheme is not silly either but we take the 
+	 *	Our current scheme is not silly either but we take the
 	 *	extra cost of the net_bh soft interrupt processing...
 	 *	We do checksum and copy also but from device to kernel.
 	 */
@@ -3904,7 +3919,7 @@
 	 *	if header_prediction is to be made
 	 *	'S' will always be tp->tcp_header_len >> 2
 	 *	'?' will be 0 for the fast path, otherwise pred_flags is 0 to
-	 *  turn it off	(when there are holes in the receive 
+	 *  turn it off	(when there are holes in the receive
 	 *	 space for instance)
 	 *	PSH flag is ignored.
 	 */
@@ -3928,7 +3943,7 @@
 				goto slow_path;
 
 			tp->rx_opt.saw_tstamp = 1;
-			++ptr; 
+			++ptr;
 			tp->rx_opt.rcv_tsval = ntohl(*ptr);
 			++ptr;
 			tp->rx_opt.rcv_tsecr = ntohl(*ptr);
@@ -3960,7 +3975,7 @@
 				 * on entry.
 				 */
 				tcp_ack(sk, skb, 0);
-				__kfree_skb(skb); 
+				__kfree_skb(skb);
 				tcp_data_snd_check(sk, tp);
 				return 0;
 			} else { /* Header too small */
@@ -4378,11 +4393,11 @@
 
 /*
  *	This function implements the receiving procedure of RFC 793 for
- *	all states except ESTABLISHED and TIME_WAIT. 
+ *	all states except ESTABLISHED and TIME_WAIT.
  *	It's called from both tcp_v4_rcv and tcp_v6_rcv and should be
  *	address independent.
  */
-	
+
 int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 			  struct tcphdr *th, unsigned len)
 {
@@ -4407,19 +4422,19 @@
 			if (icsk->icsk_af_ops->conn_request(sk, skb) < 0)
 				return 1;
 
-			/* Now we have several options: In theory there is 
-			 * nothing else in the frame. KA9Q has an option to 
+			/* Now we have several options: In theory there is
+			 * nothing else in the frame. KA9Q has an option to
 			 * send data with the syn, BSD accepts data with the
-			 * syn up to the [to be] advertised window and 
-			 * Solaris 2.1 gives you a protocol error. For now 
-			 * we just ignore it, that fits the spec precisely 
+			 * syn up to the [to be] advertised window and
+			 * Solaris 2.1 gives you a protocol error. For now
+			 * we just ignore it, that fits the spec precisely
 			 * and avoids incompatibilities. It would be nice in
 			 * future to drop through and process the data.
 			 *
-			 * Now that TTCP is starting to be used we ought to 
+			 * Now that TTCP is starting to be used we ought to
 			 * queue this data.
 			 * But, this leaves one open to an easy denial of
-		 	 * service attack, and SYN cookies can't defend
+			 * service attack, and SYN cookies can't defend
 			 * against this problem. So, we drop the data
 			 * in the interest of security over speed unless
 			 * it's still in use.
@@ -4609,7 +4624,7 @@
 	case TCP_FIN_WAIT1:
 	case TCP_FIN_WAIT2:
 		/* RFC 793 says to queue data in these states,
-		 * RFC 1122 says we MUST send a reset. 
+		 * RFC 1122 says we MUST send a reset.
 		 * BSD 4.4 also does reset.
 		 */
 		if (sk->sk_shutdown & RCV_SHUTDOWN) {
@@ -4621,7 +4636,7 @@
 			}
 		}
 		/* Fall through */
-	case TCP_ESTABLISHED: 
+	case TCP_ESTABLISHED:
 		tcp_data_queue(sk, skb);
 		queued = 1;
 		break;
@@ -4633,7 +4648,7 @@
 		tcp_ack_snd_check(sk);
 	}
 
-	if (!queued) { 
+	if (!queued) {
 discard:
 		__kfree_skb(skb);
 	}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 12de90a..0ba74bb 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -191,7 +191,7 @@
 	tmp = ip_route_connect(&rt, nexthop, inet->saddr,
 			       RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
 			       IPPROTO_TCP,
-			       inet->sport, usin->sin_port, sk);
+			       inet->sport, usin->sin_port, sk, 1);
 	if (tmp < 0)
 		return tmp;
 
@@ -303,7 +303,7 @@
 	/* We don't check in the destentry if pmtu discovery is forbidden
 	 * on this route. We just assume that no packet_to_big packets
 	 * are send back when pmtu discovery is not active.
-     	 * There is a small race when the user changes this flag in the
+	 * There is a small race when the user changes this flag in the
 	 * route, but I think that's acceptable.
 	 */
 	if ((dst = __sk_dst_check(sk, 0)) == NULL)
@@ -502,11 +502,11 @@
 	struct tcphdr *th = skb->h.th;
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		th->check = ~tcp_v4_check(th, len,
-					  inet->saddr, inet->daddr, 0);
+		th->check = ~tcp_v4_check(len, inet->saddr,
+					  inet->daddr, 0);
 		skb->csum_offset = offsetof(struct tcphdr, check);
 	} else {
-		th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr,
+		th->check = tcp_v4_check(len, inet->saddr, inet->daddr,
 					 csum_partial((char *)th,
 						      th->doff << 2,
 						      skb->csum));
@@ -525,7 +525,7 @@
 	th = skb->h.th;
 
 	th->check = 0;
-	th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
+	th->check = ~tcp_v4_check(skb->len, iph->saddr, iph->daddr, 0);
 	skb->csum_offset = offsetof(struct tcphdr, check);
 	skb->ip_summed = CHECKSUM_PARTIAL;
 	return 0;
@@ -747,7 +747,7 @@
 	if (skb) {
 		struct tcphdr *th = skb->h.th;
 
-		th->check = tcp_v4_check(th, skb->len,
+		th->check = tcp_v4_check(skb->len,
 					 ireq->loc_addr,
 					 ireq->rmt_addr,
 					 csum_partial((char *)th, skb->len,
@@ -880,7 +880,7 @@
 
 		if (md5sig->alloced4 == md5sig->entries4) {
 			keys = kmalloc((sizeof(*keys) *
-				        (md5sig->entries4 + 1)), GFP_ATOMIC);
+					(md5sig->entries4 + 1)), GFP_ATOMIC);
 			if (!keys) {
 				kfree(newkey);
 				tcp_free_md5sig_pool();
@@ -934,7 +934,7 @@
 				memcpy(&tp->md5sig_info->keys4[i],
 				       &tp->md5sig_info->keys4[i+1],
 				       (tp->md5sig_info->entries4 - i) *
-				        sizeof(struct tcp4_md5sig_key));
+					sizeof(struct tcp4_md5sig_key));
 			}
 			tcp_free_md5sig_pool();
 			return 0;
@@ -1388,7 +1388,7 @@
 		goto drop_and_free;
 
 	if (want_cookie) {
-	   	reqsk_free(req);
+		reqsk_free(req);
 	} else {
 		inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
 	}
@@ -1514,7 +1514,7 @@
 static __sum16 tcp_v4_checksum_init(struct sk_buff *skb)
 {
 	if (skb->ip_summed == CHECKSUM_COMPLETE) {
-		if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr,
+		if (!tcp_v4_check(skb->len, skb->nh.iph->saddr,
 				  skb->nh.iph->daddr, skb->csum)) {
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			return 0;
@@ -1704,7 +1704,7 @@
 discard_it:
 	/* Discard frame. */
 	kfree_skb(skb);
-  	return 0;
+	return 0;
 
 discard_and_relse:
 	sock_put(sk);
@@ -1890,10 +1890,10 @@
 	tcp_cleanup_congestion_control(sk);
 
 	/* Cleanup up the write buffer. */
-  	sk_stream_writequeue_purge(sk);
+	sk_stream_writequeue_purge(sk);
 
 	/* Cleans up our, hopefully empty, out_of_order_queue. */
-  	__skb_queue_purge(&tp->out_of_order_queue);
+	__skb_queue_purge(&tp->out_of_order_queue);
 
 #ifdef CONFIG_TCP_MD5SIG
 	/* Clean up the MD5 key list, if any */
@@ -1906,7 +1906,7 @@
 
 #ifdef CONFIG_NET_DMA
 	/* Cleans up our sk_async_wait_queue */
-  	__skb_queue_purge(&sk->sk_async_wait_queue);
+	__skb_queue_purge(&sk->sk_async_wait_queue);
 #endif
 
 	/* Clean prequeue, it must be empty really */
@@ -1983,7 +1983,7 @@
 		st->state = TCP_SEQ_STATE_LISTENING;
 		read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
 	} else {
-	       	icsk = inet_csk(sk);
+		icsk = inet_csk(sk);
 		read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
 		if (reqsk_queue_len(&icsk->icsk_accept_queue))
 			goto start_req;
@@ -1996,7 +1996,7 @@
 			cur = sk;
 			goto out;
 		}
-	       	icsk = inet_csk(sk);
+		icsk = inet_csk(sk);
 		read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
 		if (reqsk_queue_len(&icsk->icsk_accept_queue)) {
 start_req:
@@ -2051,7 +2051,7 @@
 		}
 		st->state = TCP_SEQ_STATE_TIME_WAIT;
 		inet_twsk_for_each(tw, node,
-				   &tcp_hashinfo.ehash[st->bucket + tcp_hashinfo.ehash_size].chain) {
+				   &tcp_hashinfo.ehash[st->bucket].twchain) {
 			if (tw->tw_family != st->family) {
 				continue;
 			}
@@ -2107,7 +2107,7 @@
 	}
 
 	st->state = TCP_SEQ_STATE_TIME_WAIT;
-	tw = tw_head(&tcp_hashinfo.ehash[st->bucket + tcp_hashinfo.ehash_size].chain);
+	tw = tw_head(&tcp_hashinfo.ehash[st->bucket].twchain);
 	goto get_tw;
 found:
 	cur = sk;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 4a3889d..30b1e52 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -64,7 +64,7 @@
 	return (seq == e_win && seq == end_seq);
 }
 
-/* 
+/*
  * * Main purpose of TIME-WAIT state is to close connection gracefully,
  *   when one of ends sits in LAST-ACK or CLOSING retransmitting FIN
  *   (and, probably, tail of data) and one or more our ACKs are lost.
@@ -176,13 +176,13 @@
 	 *	"When a connection is [...] on TIME-WAIT state [...]
 	 *	[a TCP] MAY accept a new SYN from the remote TCP to
 	 *	reopen the connection directly, if it:
-	 *	
+	 *
 	 *	(1)  assigns its initial sequence number for the new
 	 *	connection to be larger than the largest sequence
 	 *	number it used on the previous connection incarnation,
 	 *	and
 	 *
-	 *	(2)  returns to TIME-WAIT state if the SYN turns out 
+	 *	(2)  returns to TIME-WAIT state if the SYN turns out
 	 *	to be an old duplicate".
 	 */
 
@@ -266,9 +266,9 @@
 	return TCP_TW_SUCCESS;
 }
 
-/* 
+/*
  * Move a socket to time-wait or dead fin-wait-2 state.
- */ 
+ */
 void tcp_time_wait(struct sock *sk, int state, int timeo)
 {
 	struct inet_timewait_sock *tw = NULL;
@@ -481,7 +481,7 @@
 	return newsk;
 }
 
-/* 
+/*
  *	Process an incoming packet for SYN_RECV sockets represented
  *	as a request_sock.
  */
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 975f447..dc15113 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -198,7 +198,7 @@
 	(*rcv_wscale) = 0;
 	if (wscale_ok) {
 		/* Set window scaling on max possible window
-		 * See RFC1323 for an explanation of the limit to 14 
+		 * See RFC1323 for an explanation of the limit to 14
 		 */
 		space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max);
 		space = min_t(u32, space, *window_clamp);
@@ -451,7 +451,7 @@
 				    (tp->rx_opt.eff_sacks *
 				     TCPOLEN_SACK_PERBLOCK));
 	}
-		
+
 	if (tcp_packets_in_flight(tp) == 0)
 		tcp_ca_event(sk, CA_EVENT_TX_START);
 
@@ -481,7 +481,7 @@
 		/* RFC1323: The window in SYN & SYN/ACK segments
 		 * is never scaled.
 		 */
-		th->window	= htons(tp->rcv_wnd);
+		th->window	= htons(min(tp->rcv_wnd, 65535U));
 	} else {
 		th->window	= htons(tcp_select_window(sk));
 	}
@@ -555,7 +555,7 @@
 }
 
 
-/* This routine just queue's the buffer 
+/* This routine just queue's the buffer
  *
  * NOTE: probe0 timer is not checked, do not forget tcp_push_pending_frames,
  * otherwise socket can stall.
@@ -597,7 +597,7 @@
 
 /* Function to create two new TCP segments.  Shrinks the given segment
  * to the specified size and appends a new segment with the rest of the
- * packet to the list.  This won't be called frequently, I hope. 
+ * packet to the list.  This won't be called frequently, I hope.
  * Remember, these are still headerless SKBs at this point.
  */
 int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss_now)
@@ -610,7 +610,7 @@
 
 	BUG_ON(len > skb->len);
 
- 	clear_all_retrans_hints(tp);
+	clear_all_retrans_hints(tp);
 	nsize = skb_headlen(skb) - len;
 	if (nsize < 0)
 		nsize = 0;
@@ -821,7 +821,7 @@
 
 	icsk->icsk_mtup.enabled = sysctl_tcp_mtu_probing > 1;
 	icsk->icsk_mtup.search_high = tp->rx_opt.mss_clamp + sizeof(struct tcphdr) +
-	                       icsk->icsk_af_ops->net_header_len;
+			       icsk->icsk_af_ops->net_header_len;
 	icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, sysctl_tcp_base_mss);
 	icsk->icsk_mtup.probe_size = 0;
 }
@@ -965,7 +965,8 @@
 	u32 in_flight, cwnd;
 
 	/* Don't be strict about the congestion window for the final FIN.  */
-	if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)
+	if ((TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+	    tcp_skb_pcount(skb) == 1)
 		return 1;
 
 	in_flight = tcp_packets_in_flight(tp);
@@ -1007,7 +1008,7 @@
  */
 
 static inline int tcp_nagle_check(const struct tcp_sock *tp,
-				  const struct sk_buff *skb, 
+				  const struct sk_buff *skb,
 				  unsigned mss_now, int nonagle)
 {
 	return (skb->len < mss_now &&
@@ -1077,7 +1078,7 @@
 	return cwnd_quota;
 }
 
-static inline int tcp_skb_is_last(const struct sock *sk, 
+static inline int tcp_skb_is_last(const struct sock *sk,
 				  const struct sk_buff *skb)
 {
 	return skb->next == (struct sk_buff *)&sk->sk_write_queue;
@@ -1297,7 +1298,7 @@
 			skb_copy_bits(skb, 0, skb_put(nskb, copy), copy);
 		else
 			nskb->csum = skb_copy_and_csum_bits(skb, 0,
-			                 skb_put(nskb, copy), copy, nskb->csum);
+					 skb_put(nskb, copy), copy, nskb->csum);
 
 		if (skb->len <= copy) {
 			/* We've eaten all the data from this skb.
@@ -1307,7 +1308,7 @@
 			sk_stream_free_skb(sk, skb);
 		} else {
 			TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags &
-			                           ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
+						   ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
 			if (!skb_shinfo(skb)->nr_frags) {
 				skb_pull(skb, copy);
 				if (skb->ip_summed != CHECKSUM_PARTIAL)
@@ -1500,7 +1501,7 @@
 
 /* This function returns the amount that we can raise the
  * usable window based on the following constraints
- *  
+ *
  * 1. The window can never be shrunk once it is offered (RFC 793)
  * 2. We limit memory per socket
  *
@@ -1519,12 +1520,12 @@
  * side SWS prevention criteria. The problem is that under this rule
  * a stream of single byte packets will cause the right side of the
  * window to always advance by a single byte.
- * 
+ *
  * Of course, if the sender implements sender side SWS prevention
  * then this will not be a problem.
- * 
+ *
  * BSD seems to make the following compromise:
- * 
+ *
  *	If the free space is less than the 1/4 of the maximum
  *	space available and the free space is less than 1/2 mss,
  *	then set the window to 0.
@@ -1566,7 +1567,7 @@
 	int window;
 
 	if (mss > full_space)
-		mss = full_space; 
+		mss = full_space;
 
 	if (free_space < full_space/2) {
 		icsk->icsk_ack.quick = 0;
@@ -1690,9 +1691,9 @@
 }
 
 /* Do a simple retransmit without using the backoff mechanisms in
- * tcp_timer. This is used for path mtu discovery. 
+ * tcp_timer. This is used for path mtu discovery.
  * The socket is already locked here.
- */ 
+ */
 void tcp_simple_retransmit(struct sock *sk)
 {
 	const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -1702,7 +1703,7 @@
 	int lost = 0;
 
 	sk_stream_for_retrans_queue(skb, sk) {
-		if (skb->len > mss && 
+		if (skb->len > mss &&
 		    !(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) {
 			if (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) {
 				TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
@@ -1723,7 +1724,7 @@
 
 	tcp_sync_left_out(tp);
 
- 	/* Don't muck with the congestion window here.
+	/* Don't muck with the congestion window here.
 	 * Reason is that we do not increase amount of _data_
 	 * in network, but units changed and effective
 	 * cwnd/ssthresh really reduced now.
@@ -1746,7 +1747,7 @@
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct inet_connection_sock *icsk = inet_csk(sk);
- 	unsigned int cur_mss = tcp_current_mss(sk, 0);
+	unsigned int cur_mss = tcp_current_mss(sk, 0);
 	int err;
 
 	/* Inconslusive MTU probe */
@@ -1983,10 +1984,10 @@
  */
 void tcp_send_fin(struct sock *sk)
 {
-	struct tcp_sock *tp = tcp_sk(sk);	
+	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *skb = skb_peek_tail(&sk->sk_write_queue);
 	int mss_now;
-	
+
 	/* Optimization, tack on the FIN if we have a queue of
 	 * unsent frames.  But be careful about outgoing SACKS
 	 * and IP options.
@@ -2145,21 +2146,21 @@
 	th->seq = htonl(TCP_SKB_CB(skb)->seq);
 	th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
 	if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
-		__u8 rcv_wscale; 
+		__u8 rcv_wscale;
 		/* Set this up on the first call only */
 		req->window_clamp = tp->window_clamp ? : dst_metric(dst, RTAX_WINDOW);
 		/* tcp_full_space because it is guaranteed to be the first packet */
-		tcp_select_initial_window(tcp_full_space(sk), 
+		tcp_select_initial_window(tcp_full_space(sk),
 			dst_metric(dst, RTAX_ADVMSS) - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
 			&req->rcv_wnd,
 			&req->window_clamp,
 			ireq->wscale_ok,
 			&rcv_wscale);
-		ireq->rcv_wscale = rcv_wscale; 
+		ireq->rcv_wscale = rcv_wscale;
 	}
 
 	/* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
-	th->window = htons(req->rcv_wnd);
+	th->window = htons(min(req->rcv_wnd, 65535U));
 
 	TCP_SKB_CB(skb)->when = tcp_time_stamp;
 	tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
@@ -2191,9 +2192,9 @@
 	return skb;
 }
 
-/* 
+/*
  * Do all connect socket setups that can be done AF independent.
- */ 
+ */
 static void tcp_connect_init(struct sock *sk)
 {
 	struct dst_entry *dst = __sk_dst_get(sk);
@@ -2250,7 +2251,7 @@
 
 /*
  * Build a SYN and send it off.
- */ 
+ */
 int tcp_connect(struct sock *sk)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -2408,7 +2409,7 @@
 
 	/* We don't queue it, tcp_transmit_skb() sets ownership. */
 	skb = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
-	if (skb == NULL) 
+	if (skb == NULL)
 		return -1;
 
 	/* Reserve space for headers and set control bits. */
@@ -2497,7 +2498,7 @@
 		if (icsk->icsk_backoff < sysctl_tcp_retries2)
 			icsk->icsk_backoff++;
 		icsk->icsk_probes_out++;
-		inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0, 
+		inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
 					  min(icsk->icsk_rto << icsk->icsk_backoff, TCP_RTO_MAX),
 					  TCP_RTO_MAX);
 	} else {
@@ -2509,7 +2510,7 @@
 		 */
 		if (!icsk->icsk_probes_out)
 			icsk->icsk_probes_out = 1;
-		inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0, 
+		inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
 					  min(icsk->icsk_rto << icsk->icsk_backoff,
 					      TCP_RESOURCE_PROBE_INTERVAL),
 					  TCP_RTO_MAX);
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index 41c1578..61f406f2 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -143,7 +143,7 @@
 	return error ? error : cnt;
 }
 
-static struct file_operations tcpprobe_fops = {
+static const struct file_operations tcpprobe_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = tcpprobe_open,
 	.read    = tcpprobe_read,
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 3355c276..a9243cf 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -69,7 +69,7 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 	int orphans = atomic_read(&tcp_orphan_count);
 
-	/* If peer does not open window for long time, or did not transmit 
+	/* If peer does not open window for long time, or did not transmit
 	 * anything for long time, penalize it. */
 	if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset)
 		orphans <<= 1;
@@ -137,7 +137,7 @@
 					tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
 				} else {
 					mss = min(sysctl_tcp_base_mss,
-					          tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low)/2);
+						  tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low)/2);
 					mss = max(mss, 68 - tp->tcp_header_len);
 					icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss);
 					tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
@@ -150,7 +150,7 @@
 		retry_until = sysctl_tcp_retries2;
 		if (sock_flag(sk, SOCK_DEAD)) {
 			const int alive = (icsk->icsk_rto < TCP_RTO_MAX);
- 
+
 			retry_until = tcp_orphan_retries(sk, alive);
 
 			if (tcp_out_of_resources(sk, alive || icsk->icsk_retransmits < retry_until))
@@ -257,7 +257,7 @@
 
 	if (sock_flag(sk, SOCK_DEAD)) {
 		const int alive = ((icsk->icsk_rto << icsk->icsk_backoff) < TCP_RTO_MAX);
- 
+
 		max_probes = tcp_orphan_retries(sk, alive);
 
 		if (tcp_out_of_resources(sk, alive || icsk->icsk_probes_out <= max_probes))
@@ -453,7 +453,7 @@
 	/* Only process if socket is not in use. */
 	bh_lock_sock(sk);
 	if (sock_owned_by_user(sk)) {
-		/* Try again later. */ 
+		/* Try again later. */
 		inet_csk_reset_keepalive_timer (sk, HZ/20);
 		goto out;
 	}
@@ -515,7 +515,7 @@
 	inet_csk_reset_keepalive_timer (sk, elapsed);
 	goto out;
 
-death:	
+death:
 	tcp_done(sk);
 
 out:
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index ddc4bcc..5c484dc 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -330,9 +330,9 @@
 		vegas->minRTT = 0x7fffffff;
 	}
 	/* Use normal slow start */
-	else if (tp->snd_cwnd <= tp->snd_ssthresh) 
+	else if (tp->snd_cwnd <= tp->snd_ssthresh)
 		tcp_slow_start(tp);
-	
+
 }
 
 /* Extract info for Tcp socket info provided via netlink. */
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
index 4f42a86..4e1b610 100644
--- a/net/ipv4/tcp_westwood.c
+++ b/net/ipv4/tcp_westwood.c
@@ -63,10 +63,10 @@
 	struct westwood *w = inet_csk_ca(sk);
 
 	w->bk = 0;
-        w->bw_ns_est = 0;
-        w->bw_est = 0;
-        w->accounted = 0;
-        w->cumul_ack = 0;
+	w->bw_ns_est = 0;
+	w->bw_est = 0;
+	w->accounted = 0;
+	w->cumul_ack = 0;
 	w->reset_rtt_min = 1;
 	w->rtt_min = w->rtt = TCP_WESTWOOD_INIT_RTT;
 	w->rtt_win_sx = tcp_time_stamp;
@@ -121,7 +121,7 @@
 	 * to fix mismatch between tp->snd_una and w->snd_una for the first
 	 * bandwidth sample
 	 */
-        if (w->first_ack) {
+	if (w->first_ack) {
 		w->snd_una = tcp_sk(sk)->snd_una;
 		w->first_ack = 0;
 	}
@@ -147,7 +147,7 @@
 {
 	if (w->reset_rtt_min) {
 		w->rtt_min = w->rtt;
-		w->reset_rtt_min = 0;	
+		w->reset_rtt_min = 0;
 	} else
 		w->rtt_min = min(w->rtt, w->rtt_min);
 }
@@ -183,15 +183,15 @@
 
 	w->cumul_ack = tp->snd_una - w->snd_una;
 
-        /* If cumul_ack is 0 this is a dupack since it's not moving
-         * tp->snd_una.
-         */
-        if (!w->cumul_ack) {
+	/* If cumul_ack is 0 this is a dupack since it's not moving
+	 * tp->snd_una.
+	 */
+	if (!w->cumul_ack) {
 		w->accounted += tp->mss_cache;
 		w->cumul_ack = tp->mss_cache;
 	}
 
-        if (w->cumul_ack > tp->mss_cache) {
+	if (w->cumul_ack > tp->mss_cache) {
 		/* Partial or delayed ack */
 		if (w->accounted >= w->cumul_ack) {
 			w->accounted -= w->cumul_ack;
@@ -237,7 +237,7 @@
 
 	case CA_EVENT_FRTO:
 		tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
- 		/* Update RTT_min when next ack arrives */
+		/* Update RTT_min when next ack arrives */
 		w->reset_rtt_min = 1;
 		break;
 
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index 8d30c48..a794a8c 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -14,9 +14,10 @@
 #include <net/xfrm.h>
 
 static struct xfrm_tunnel *tunnel4_handlers;
+static struct xfrm_tunnel *tunnel64_handlers;
 static DEFINE_MUTEX(tunnel4_mutex);
 
-int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
+int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
 {
 	struct xfrm_tunnel **pprev;
 	int ret = -EEXIST;
@@ -24,7 +25,8 @@
 
 	mutex_lock(&tunnel4_mutex);
 
-	for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
+	for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
+	     *pprev; pprev = &(*pprev)->next) {
 		if ((*pprev)->priority > priority)
 			break;
 		if ((*pprev)->priority == priority)
@@ -44,14 +46,15 @@
 
 EXPORT_SYMBOL(xfrm4_tunnel_register);
 
-int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
+int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family)
 {
 	struct xfrm_tunnel **pprev;
 	int ret = -ENOENT;
 
 	mutex_lock(&tunnel4_mutex);
 
-	for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
+	for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
+	     *pprev; pprev = &(*pprev)->next) {
 		if (*pprev == handler) {
 			*pprev = handler->next;
 			ret = 0;
@@ -86,6 +89,26 @@
 	return 0;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static int tunnel64_rcv(struct sk_buff *skb)
+{
+	struct xfrm_tunnel *handler;
+
+	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+		goto drop;
+
+	for (handler = tunnel64_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;
+}
+#endif
+
 static void tunnel4_err(struct sk_buff *skb, u32 info)
 {
 	struct xfrm_tunnel *handler;
@@ -101,17 +124,36 @@
 	.no_policy	=	1,
 };
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static struct net_protocol tunnel64_protocol = {
+	.handler	=	tunnel64_rcv,
+	.err_handler	=	tunnel4_err,
+	.no_policy	=	1,
+};
+#endif
+
 static int __init tunnel4_init(void)
 {
 	if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
 		printk(KERN_ERR "tunnel4 init: can't add protocol\n");
 		return -EAGAIN;
 	}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
+		printk(KERN_ERR "tunnel64 init: can't add protocol\n");
+		inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
+		return -EAGAIN;
+	}
+#endif
 	return 0;
 }
 
 static void __exit tunnel4_fini(void)
 {
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
+		printk(KERN_ERR "tunnel64 close: can't remove protocol\n");
+#endif
 	if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
 		printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
 }
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index cfff930..ce6c460 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -20,8 +20,8 @@
  *					for udp at least is 'valid'.
  *		Alan Cox	:	Fixed icmp handling properly
  *		Alan Cox	: 	Correct error for oversized datagrams
- *		Alan Cox	:	Tidied select() semantics. 
- *		Alan Cox	:	udp_err() fixed properly, also now 
+ *		Alan Cox	:	Tidied select() semantics.
+ *		Alan Cox	:	udp_err() fixed properly, also now
  *					select and read wake correctly on errors
  *		Alan Cox	:	udp_send verify_area moved to avoid mem leak
  *		Alan Cox	:	UDP can count its memory
@@ -56,7 +56,7 @@
  *					does have a high hit rate.
  *		Olaf Kirch	:	Don't linearise iovec on sendmsg.
  *		Andi Kleen	:	Some cleanups, cache destination entry
- *					for connect. 
+ *					for connect.
  *	Vitaly E. Lavrov	:	Transparent proxy revived after year coma.
  *		Melvin Smith	:	Check msg_name not msg_namelen in sendto(),
  *					return ENOTCONN for unconnected sockets (POSIX)
@@ -77,7 +77,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  */
- 
+
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -120,7 +120,7 @@
 	struct hlist_node *node;
 
 	sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
-		if (inet_sk(sk)->num == num)
+		if (sk->sk_hash == num)
 			return 1;
 	return 0;
 }
@@ -191,7 +191,7 @@
 		head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
 
 		sk_for_each(sk2, node, head)
-			if (inet_sk(sk2)->num == snum                        &&
+			if (sk2->sk_hash == snum                             &&
 			    sk2 != sk                                        &&
 			    (!sk2->sk_reuse        || !sk->sk_reuse)         &&
 			    (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
@@ -200,6 +200,7 @@
 				goto fail;
 	}
 	inet_sk(sk)->num = snum;
+	sk->sk_hash = snum;
 	if (sk_unhashed(sk)) {
 		head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
 		sk_add_node(sk, head);
@@ -247,7 +248,7 @@
 	sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
 		struct inet_sock *inet = inet_sk(sk);
 
-		if (inet->num == hnum && !ipv6_only_sock(sk)) {
+		if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) {
 			int score = (sk->sk_family == PF_INET ? 1 : 0);
 			if (inet->rcv_saddr) {
 				if (inet->rcv_saddr != daddr)
@@ -296,7 +297,7 @@
 	sk_for_each_from(s, node) {
 		struct inet_sock *inet = inet_sk(s);
 
-		if (inet->num != hnum					||
+		if (s->sk_hash != hnum					||
 		    (inet->daddr && inet->daddr != rmt_addr)		||
 		    (inet->dport != rmt_port && inet->dport)		||
 		    (inet->rcv_saddr && inet->rcv_saddr != loc_addr)	||
@@ -306,17 +307,17 @@
 		if (!ip_mc_sf_allow(s, loc_addr, rmt_addr, dif))
 			continue;
 		goto found;
-  	}
+	}
 	s = NULL;
 found:
-  	return s;
+	return s;
 }
 
 /*
  * This routine is called by the ICMP module when it gets some
  * sort of error condition.  If err < 0 then the socket should
  * be closed and the error returned to the user.  If err > 0
- * it's just the icmp type << 8 | icmp code.  
+ * it's just the icmp type << 8 | icmp code.
  * Header points to the ip header of the error packet. We move
  * on past this. Then (as it used to claim before adjustment)
  * header points to the first 8 bytes of the udp header.  We need
@@ -338,7 +339,7 @@
 			       skb->dev->ifindex, udptable		    );
 	if (sk == NULL) {
 		ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
-    	  	return;	/* No socket for error */
+		return;	/* No socket for error */
 	}
 
 	err = 0;
@@ -374,7 +375,7 @@
 	}
 
 	/*
-	 *      RFC1122: OK.  Passes ICMP errors back to application, as per 
+	 *      RFC1122: OK.  Passes ICMP errors back to application, as per
 	 *	4.1.3.3.
 	 */
 	if (!inet->recverr) {
@@ -524,7 +525,7 @@
 	if (len > 0xFFFF)
 		return -EMSGSIZE;
 
-	/* 
+	/*
 	 *	Check the flags.
 	 */
 
@@ -536,7 +537,7 @@
 	if (up->pending) {
 		/*
 		 * There are pending frames.
-	 	 * The socket lock must be held while it's corked.
+		 * The socket lock must be held while it's corked.
 		 */
 		lock_sock(sk);
 		if (likely(up->pending)) {
@@ -544,14 +545,14 @@
 				release_sock(sk);
 				return -EINVAL;
 			}
- 			goto do_append_data;
+			goto do_append_data;
 		}
 		release_sock(sk);
 	}
 	ulen += sizeof(struct udphdr);
 
 	/*
-	 *	Get and verify the address. 
+	 *	Get and verify the address.
 	 */
 	if (msg->msg_name) {
 		struct sockaddr_in * usin = (struct sockaddr_in*)msg->msg_name;
@@ -575,7 +576,7 @@
 		   Route will not be used, if at least one option is set.
 		 */
 		connected = 1;
-  	}
+	}
 	ipc.addr = inet->saddr;
 
 	ipc.oif = sk->sk_bound_dev_if;
@@ -601,7 +602,7 @@
 	}
 	tos = RT_TOS(inet->tos);
 	if (sock_flag(sk, SOCK_LOCALROUTE) ||
-	    (msg->msg_flags & MSG_DONTROUTE) || 
+	    (msg->msg_flags & MSG_DONTROUTE) ||
 	    (ipc.opt && ipc.opt->is_strictroute)) {
 		tos |= RTO_ONLINK;
 		connected = 0;
@@ -629,7 +630,7 @@
 					       { .sport = inet->sport,
 						 .dport = dport } } };
 		security_sk_classify_flow(sk, &fl);
-		err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
+		err = ip_route_output_flow(&rt, &fl, sk, 1);
 		if (err)
 			goto out;
 
@@ -761,10 +762,10 @@
 /*
  *	IOCTL requests applicable to the UDP protocol
  */
- 
+
 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-	switch(cmd) 
+	switch(cmd)
 	{
 		case SIOCOUTQ:
 		{
@@ -804,11 +805,11 @@
  */
 
 int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
-	        size_t len, int noblock, int flags, int *addr_len)
+		size_t len, int noblock, int flags, int *addr_len)
 {
 	struct inet_sock *inet = inet_sk(sk);
-  	struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
-  	struct sk_buff *skb;
+	struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
+	struct sk_buff *skb;
 	int copied, err, copy_only, is_udplite = IS_UDPLITE(sk);
 
 	/*
@@ -824,8 +825,8 @@
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
-  
-  	copied = skb->len - sizeof(struct udphdr);
+
+	copied = skb->len - sizeof(struct udphdr);
 	if (copied > len) {
 		copied = len;
 		msg->msg_flags |= MSG_TRUNC;
@@ -868,18 +869,18 @@
 		sin->sin_port = skb->h.uh->source;
 		sin->sin_addr.s_addr = skb->nh.iph->saddr;
 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
-  	}
+	}
 	if (inet->cmsg_flags)
 		ip_cmsg_recv(msg, skb);
 
 	err = copied;
 	if (flags & MSG_TRUNC)
 		err = skb->len - sizeof(struct udphdr);
-  
+
 out_free:
-  	skb_free_datagram(sk, skb);
+	skb_free_datagram(sk, skb);
 out:
-  	return err;
+	return err;
 
 csum_copy_err:
 	UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
@@ -887,7 +888,7 @@
 	skb_kill_datagram(sk, skb, flags);
 
 	if (noblock)
-		return -EAGAIN;	
+		return -EAGAIN;
 	goto try_again;
 }
 
@@ -898,7 +899,7 @@
 	/*
 	 *	1003.1g - break association.
 	 */
-	 
+
 	sk->sk_state = TCP_CLOSE;
 	inet->daddr = 0;
 	inet->dport = 0;
@@ -922,13 +923,13 @@
 static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
 {
 #ifndef CONFIG_XFRM
-	return 1; 
+	return 1;
 #else
 	struct udp_sock *up = udp_sk(sk);
-  	struct udphdr *uh;
+	struct udphdr *uh;
 	struct iphdr *iph;
 	int iphlen, len;
-  
+
 	__u8 *udpdata;
 	__be32 *udpdata32;
 	__u16 encap_type = up->encap_type;
@@ -971,7 +972,7 @@
 			return 0;
 		} else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
 			   udpdata32[0] == 0 && udpdata32[1] == 0) {
-			
+
 			/* ESP Packet with Non-IKE marker */
 			len = sizeof(struct udphdr) + 2 * sizeof(u32);
 		} else
@@ -1187,14 +1188,14 @@
 }
 
 /*
- *	All we need to do is get the socket, and then do a checksum. 
+ *	All we need to do is get the socket, and then do a checksum.
  */
- 
+
 int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
 		   int is_udplite)
 {
-  	struct sock *sk;
-  	struct udphdr *uh = skb->h.uh;
+	struct sock *sk;
+	struct udphdr *uh = skb->h.uh;
 	unsigned short ulen;
 	struct rtable *rt = (struct rtable*)skb->dst;
 	__be32 saddr = skb->nh.iph->saddr;
@@ -1270,9 +1271,9 @@
 	goto drop;
 
 csum_error:
-	/* 
-	 * RFC1122: OK.  Discards the bad packet silently (as far as 
-	 * the network is concerned, anyway) as per 4.1.3.4 (MUST). 
+	/*
+	 * RFC1122: OK.  Discards the bad packet silently (as far as
+	 * the network is concerned, anyway) as per 4.1.3.4 (MUST).
 	 */
 	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
 		       is_udplite? "-Lite" : "",
@@ -1328,7 +1329,7 @@
 			release_sock(sk);
 		}
 		break;
-		
+
 	case UDP_ENCAP:
 		switch (val) {
 		case 0:
@@ -1356,8 +1357,8 @@
 		up->pcflag |= UDPLITE_SEND_CC;
 		break;
 
-        /* The receiver specifies a minimum checksum coverage value. To make
-         * sense, this should be set to at least 8 (as done below). If zero is
+	/* The receiver specifies a minimum checksum coverage value. To make
+	 * sense, this should be set to at least 8 (as done below). If zero is
 	 * used, this again means full checksum coverage.                     */
 	case UDPLITE_RECV_CSCOV:
 		if (!up->pcflag)         /* Disable the option on UDP sockets */
@@ -1406,7 +1407,7 @@
 		return -EFAULT;
 
 	len = min_t(unsigned int, len, sizeof(int));
-	
+
 	if(len < 0)
 		return -EINVAL;
 
@@ -1433,11 +1434,11 @@
 		return -ENOPROTOOPT;
 	};
 
-  	if(put_user(len, optlen))
-  		return -EFAULT;
+	if(put_user(len, optlen))
+		return -EFAULT;
 	if(copy_to_user(optval, &val,len))
 		return -EFAULT;
-  	return 0;
+	return 0;
 }
 
 int udp_getsockopt(struct sock *sk, int level, int optname,
@@ -1463,7 +1464,7 @@
  *	@sock - socket
  *	@wait - poll table
  *
- *	This is same as datagram poll, except for the special case of 
+ *	This is same as datagram poll, except for the special case of
  *	blocking sockets. If application is using a blocking fd
  *	and a packet with checksum error is in the queue;
  *	then it could get return from select indicating data available
@@ -1502,11 +1503,11 @@
 	}
 
 	return mask;
-	
+
 }
 
 struct proto udp_prot = {
- 	.name		   = "UDP",
+	.name		   = "UDP",
 	.owner		   = THIS_MODULE,
 	.close		   = udp_lib_close,
 	.connect	   = ip4_datagram_connect,
@@ -1670,7 +1671,7 @@
 
 	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
 		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
-		bucket, src, srcp, dest, destp, sp->sk_state, 
+		bucket, src, srcp, dest, destp, sp->sk_state,
 		atomic_read(&sp->sk_wmem_alloc),
 		atomic_read(&sp->sk_rmem_alloc),
 		0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
index f6f4277..820a477 100644
--- a/net/ipv4/udp_impl.h
+++ b/net/ipv4/udp_impl.h
@@ -10,7 +10,7 @@
 
 extern int	__udp_lib_get_port(struct sock *sk, unsigned short snum,
 				   struct hlist_head udptable[], int *port_rover,
-		       	       	   int (*)(const struct sock*,const struct sock*));
+				   int (*)(const struct sock*,const struct sock*));
 extern int	ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
 
 
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 8655d03..78e80de 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -6,7 +6,7 @@
  *		Split up af-specific portion
  *	Derek Atkins <derek@ihtfp.com>
  *		Add Encapsulation support
- * 	
+ *
  */
 
 #include <linux/module.h>
@@ -27,6 +27,7 @@
 {
 	switch (nexthdr) {
 	case IPPROTO_IPIP:
+	case IPPROTO_IPV6:
 		*spi = skb->nh.iph->saddr;
 		*seq = 0;
 		return 0;
@@ -42,7 +43,7 @@
 
 	if (skb->dst == NULL) {
 		if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
-		                   skb->dev))
+				   skb->dev))
 			goto drop;
 	}
 	return dst_input(skb);
@@ -70,7 +71,8 @@
 		if (xfrm_nr == XFRM_MAX_DEPTH)
 			goto drop;
 
-		x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, iph->protocol, AF_INET);
+		x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
+				iph->protocol != IPPROTO_IPV6 ? iph->protocol : IPPROTO_IPIP, AF_INET);
 		if (x == NULL)
 			goto drop;
 
@@ -149,7 +151,7 @@
 		ip_send_check(skb->nh.iph);
 
 		NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
-		        xfrm4_rcv_encap_finish);
+			xfrm4_rcv_encap_finish);
 		return 0;
 #else
 		return -skb->nh.iph->protocol;
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index e23c21d..e1cab33 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -23,6 +23,12 @@
 		IP_ECN_set_ce(inner_iph);
 }
 
+static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+{
+	if (INET_ECN_is_ce(iph->tos))
+		IP6_ECN_set_ce(skb->nh.ipv6h);
+}
+
 /* Add encapsulation header.
  *
  * The top IP header will be constructed per RFC 2401.  The following fields
@@ -36,6 +42,7 @@
 static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb->dst;
+	struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
 	struct iphdr *iph, *top_iph;
 	int flags;
 
@@ -48,15 +55,27 @@
 	top_iph->ihl = 5;
 	top_iph->version = 4;
 
-	/* DS disclosed */
-	top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
-
 	flags = x->props.flags;
+
+	/* DS disclosed */
+	if (xdst->route->ops->family == AF_INET) {
+		top_iph->protocol = IPPROTO_IPIP;
+		top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
+		top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
+			0 : (iph->frag_off & htons(IP_DF));
+	}
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	else {
+		struct ipv6hdr *ipv6h = (struct ipv6hdr*)iph;
+		top_iph->protocol = IPPROTO_IPV6;
+		top_iph->tos = INET_ECN_encapsulate(iph->tos, ipv6_get_dsfield(ipv6h));
+		top_iph->frag_off = 0;
+	}
+#endif
+
 	if (flags & XFRM_STATE_NOECN)
 		IP_ECN_clear(top_iph);
 
-	top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
-		0 : (iph->frag_off & htons(IP_DF));
 	if (!top_iph->frag_off)
 		__ip_select_ident(top_iph, dst->child, 0);
 
@@ -64,7 +83,6 @@
 
 	top_iph->saddr = x->props.saddr.a4;
 	top_iph->daddr = x->id.daddr.a4;
-	top_iph->protocol = IPPROTO_IPIP;
 
 	memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 	return 0;
@@ -75,8 +93,17 @@
 	struct iphdr *iph = skb->nh.iph;
 	int err = -EINVAL;
 
-	if (iph->protocol != IPPROTO_IPIP)
-		goto out;
+	switch(iph->protocol){
+		case IPPROTO_IPIP:
+			break;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		case IPPROTO_IPV6:
+			break;
+#endif
+		default:
+			goto out;
+	}
+
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 		goto out;
 
@@ -84,10 +111,19 @@
 	    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
 		goto out;
 
-	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
-		ipv4_copy_dscp(iph, skb->h.ipiph);
-	if (!(x->props.flags & XFRM_STATE_NOECN))
-		ipip_ecn_decapsulate(skb);
+	if (iph->protocol == IPPROTO_IPIP) {
+		if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+			ipv4_copy_dscp(iph, skb->h.ipiph);
+		if (!(x->props.flags & XFRM_STATE_NOECN))
+			ipip_ecn_decapsulate(skb);
+	}
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	else {
+		if (!(x->props.flags & XFRM_STATE_NOECN))
+			ipip6_ecn_decapsulate(iph, skb);
+		skb->protocol = htons(ETH_P_IPV6);
+	}
+#endif
 	skb->mac.raw = memmove(skb->data - skb->mac_len,
 			       skb->mac.raw, skb->mac_len);
 	skb->nh.raw = skb->data;
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 04403fb0..038ca16 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -1,7 +1,7 @@
 /*
  * xfrm4_output.c - Common IPsec encapsulation code for IPv4.
  * Copyright (c) 2004 Herbert Xu <herbert@gondor.apana.org.au>
- * 
+ *
  * 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
@@ -28,7 +28,7 @@
 		goto out;
 
 	IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
-	
+
 	if (!(iph->frag_off & htons(IP_DF)) || skb->local_df)
 		goto out;
 
@@ -47,7 +47,7 @@
 	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	int err;
-	
+
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		err = skb_checksum_help(skb);
 		if (err)
@@ -78,7 +78,7 @@
 		x->curlft.packets++;
 
 		spin_unlock_bh(&x->lock);
-	
+
 		if (!(skb->dst = dst_pop(dst))) {
 			err = -EHOSTUNREACH;
 			goto error_nolock;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index fb9f69c..fef19c6 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -1,11 +1,11 @@
-/* 
+/*
  * xfrm4_policy.c
  *
  * Changes:
  *	Kazunori MIYAZAWA @USAGI
  * 	YOSHIFUJI Hideaki @USAGI
  *		Split up af-specific portion
- * 	
+ *
  */
 
 #include <linux/compiler.h>
@@ -50,8 +50,8 @@
 		struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
 		if (xdst->u.rt.fl.oif == fl->oif &&	/*XXX*/
 		    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
-	    	    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
-	    	    xdst->u.rt.fl.fl4_tos == fl->fl4_tos &&
+		    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
+		    xdst->u.rt.fl.fl4_tos == fl->fl4_tos &&
 		    xfrm_bundle_ok(policy, xdst, fl, AF_INET, 0)) {
 			dst_clone(dst);
 			break;
@@ -72,13 +72,11 @@
 	struct dst_entry *dst, *dst_prev;
 	struct rtable *rt0 = (struct rtable*)(*dst_p);
 	struct rtable *rt = rt0;
-	__be32 remote = fl->fl4_dst;
-	__be32 local  = fl->fl4_src;
 	struct flowi fl_tunnel = {
 		.nl_u = {
 			.ip4_u = {
-				.saddr = local,
-				.daddr = remote,
+				.saddr = fl->fl4_src,
+				.daddr = fl->fl4_dst,
 				.tos = fl->fl4_tos
 			}
 		}
@@ -94,7 +92,6 @@
 	for (i = 0; i < nx; i++) {
 		struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops);
 		struct xfrm_dst *xdst;
-		int tunnel = 0;
 
 		if (unlikely(dst1 == NULL)) {
 			err = -ENOBUFS;
@@ -116,19 +113,28 @@
 
 		dst1->next = dst_prev;
 		dst_prev = dst1;
-		if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
-			remote = xfrm[i]->id.daddr.a4;
-			local  = xfrm[i]->props.saddr.a4;
-			tunnel = 1;
-		}
+
 		header_len += xfrm[i]->props.header_len;
 		trailer_len += xfrm[i]->props.trailer_len;
 
-		if (tunnel) {
-			fl_tunnel.fl4_src = local;
-			fl_tunnel.fl4_dst = remote;
+		if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) {
+			unsigned short encap_family = xfrm[i]->props.family;
+			switch(encap_family) {
+			case AF_INET:
+				fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4;
+				fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4;
+				break;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+			case AF_INET6:
+				ipv6_addr_copy(&fl_tunnel.fl6_dst, (struct in6_addr*)&xfrm[i]->id.daddr.a6);
+				ipv6_addr_copy(&fl_tunnel.fl6_src, (struct in6_addr*)&xfrm[i]->props.saddr.a6);
+				break;
+#endif
+			default:
+				BUG_ON(1);
+			}
 			err = xfrm_dst_lookup((struct xfrm_dst **)&rt,
-					      &fl_tunnel, AF_INET);
+					      &fl_tunnel, encap_family);
 			if (err)
 				goto error;
 		} else
@@ -145,6 +151,7 @@
 	i = 0;
 	for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
 		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
+		struct xfrm_state_afinfo *afinfo;
 		x->u.rt.fl = *fl;
 
 		dst_prev->xfrm = xfrm[i++];
@@ -162,8 +169,18 @@
 		/* Copy neighbout for reachability confirmation */
 		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
 		dst_prev->input		= rt->u.dst.input;
-		dst_prev->output	= xfrm4_output;
-		if (rt->peer)
+		/* XXX: When IPv6 module can be unloaded, we should manage reference
+		 * to xfrm6_output in afinfo->output. Miyazawa
+		 * */
+		afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family);
+		if (!afinfo) {
+			dst = *dst_p;
+			err = -EAFNOSUPPORT;
+			goto error;
+		}
+		dst_prev->output = afinfo->output;
+		xfrm_state_put_afinfo(afinfo);
+		if (dst_prev->xfrm->props.family == AF_INET && rt->peer)
 			atomic_inc(&rt->peer->refcnt);
 		x->u.rt.peer = rt->peer;
 		/* Sheit... I remember I did this right. Apparently,
@@ -274,7 +291,7 @@
 
 	if (likely(xdst->u.rt.idev))
 		in_dev_put(xdst->u.rt.idev);
-	if (likely(xdst->u.rt.peer))
+	if (dst->xfrm->props.family == AF_INET && likely(xdst->u.rt.peer))
 		inet_putpeer(xdst->u.rt.peer);
 	xfrm_dst_destroy(xdst);
 }
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 3cc3df0..93e2c06 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -51,6 +51,7 @@
 	.family			= AF_INET,
 	.init_flags		= xfrm4_init_flags,
 	.init_tempsel		= __xfrm4_init_tempsel,
+	.output			= xfrm4_output,
 };
 
 void __init xfrm4_state_init(void)
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index f110af5..3eef064 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -13,7 +13,7 @@
 static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct iphdr *iph;
-	
+
 	iph = skb->nh.iph;
 	iph->tot_len = htons(skb->len);
 	ip_send_check(iph);
@@ -64,24 +64,45 @@
 	.priority	=	2,
 };
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static struct xfrm_tunnel xfrm64_tunnel_handler = {
+	.handler	=	xfrm4_rcv,
+	.err_handler	=	xfrm_tunnel_err,
+	.priority	=	2,
+};
+#endif
+
 static int __init ipip_init(void)
 {
 	if (xfrm_register_type(&ipip_type, AF_INET) < 0) {
 		printk(KERN_INFO "ipip init: can't add xfrm type\n");
 		return -EAGAIN;
 	}
-	if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) {
-		printk(KERN_INFO "ipip init: can't add xfrm handler\n");
+
+	if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) {
+		printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET\n");
 		xfrm_unregister_type(&ipip_type, AF_INET);
 		return -EAGAIN;
 	}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) {
+		printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET6\n");
+		xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET);
+		xfrm_unregister_type(&ipip_type, AF_INET);
+		return -EAGAIN;
+	}
+#endif
 	return 0;
 }
 
 static void __exit ipip_fini(void)
 {
-	if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler))
-		printk(KERN_INFO "ipip close: can't remove xfrm handler\n");
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6))
+		printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET6\n");
+#endif
+	if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET))
+		printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET\n");
 	if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
 		printk(KERN_INFO "ipip close: can't remove xfrm type\n");
 }
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index deb4101..79682ef 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -156,6 +156,7 @@
 config IPV6_SIT
 	tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
 	depends on IPV6
+	select INET_TUNNEL
 	default y
 	---help---
 	  Tunneling means encapsulating data of one protocol type within
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e385469..569a37d 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
  *	$Id: addrconf.c,v 1.69 2001/10/31 21:55:54 davem Exp $
@@ -44,7 +44,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -105,7 +104,7 @@
 
 #ifdef CONFIG_IPV6_PRIVACY
 static int __ipv6_regen_rndid(struct inet6_dev *idev);
-static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); 
+static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
 static void ipv6_regen_rndid(unsigned long data);
 
 static int desync_factor = MAX_DESYNC_FACTOR * HZ;
@@ -137,7 +136,7 @@
 static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
 static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
 
-static void inet6_prefix_notify(int event, struct inet6_dev *idev, 
+static void inet6_prefix_notify(int event, struct inet6_dev *idev,
 				struct prefix_info *pinfo);
 static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev);
 
@@ -241,7 +240,7 @@
 	 */
 	if ((st & htonl(0xE0000000)) != htonl(0x00000000) &&
 	    (st & htonl(0xE0000000)) != htonl(0xE0000000))
-		return (IPV6_ADDR_UNICAST | 
+		return (IPV6_ADDR_UNICAST |
 			IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
 
 	if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) {
@@ -252,7 +251,7 @@
 	}
 
 	if ((st & htonl(0xFFC00000)) == htonl(0xFE800000))
-		return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST | 
+		return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
 			IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));		/* addr-select 3.1 */
 	if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000))
 		return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
@@ -272,11 +271,11 @@
 		}
 
 		if (addr->s6_addr32[2] == htonl(0x0000ffff))
-			return (IPV6_ADDR_MAPPED | 
+			return (IPV6_ADDR_MAPPED |
 				IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));	/* addr-select 3.3 */
 	}
 
-	return (IPV6_ADDR_RESERVED | 
+	return (IPV6_ADDR_RESERVED |
 		IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));	/* addr-select 3.4 */
 }
 
@@ -348,10 +347,10 @@
 	if (dev->mtu < IPV6_MIN_MTU)
 		return NULL;
 
- 	ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL);
+	ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL);
 
- 	if (ndev == NULL)
- 		return NULL;
+	if (ndev == NULL)
+		return NULL;
 
 	rwlock_init(&ndev->lock);
 	ndev->dev = dev;
@@ -462,7 +461,7 @@
 	dev = idev->dev;
 	if (dev && (dev->flags & IFF_MULTICAST)) {
 		ipv6_addr_all_routers(&addr);
-	
+
 		if (idev->cnf.forwarding)
 			ipv6_dev_mc_inc(dev, &addr);
 		else
@@ -817,8 +816,8 @@
 	tmp_valid_lft = min_t(__u32,
 			      ifp->valid_lft,
 			      idev->cnf.temp_valid_lft);
-	tmp_prefered_lft = min_t(__u32, 
-				 ifp->prefered_lft, 
+	tmp_prefered_lft = min_t(__u32,
+				 ifp->prefered_lft,
 				 idev->cnf.temp_prefered_lft - desync_factor / HZ);
 	tmp_plen = ifp->prefix_len;
 	max_addresses = idev->cnf.max_addresses;
@@ -828,7 +827,7 @@
 
 	write_unlock(&idev->lock);
 	ift = !max_addresses ||
-	      ipv6_count_addresses(idev) < max_addresses ? 
+	      ipv6_count_addresses(idev) < max_addresses ?
 		ipv6_add_addr(idev, &addr, tmp_plen,
 			      ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, IFA_F_TEMPORARY) : NULL;
 	if (!ift || IS_ERR(ift)) {
@@ -1160,7 +1159,7 @@
 
 	if (!ifa_result)
 		return -EADDRNOTAVAIL;
-	
+
 	ipv6_addr_copy(saddr, &ifa_result->addr);
 	in6_ifa_put(ifa_result);
 	return 0;
@@ -1475,7 +1474,7 @@
 	 *  - value 0
 	 *  - XXX: already assigned to an address on the device
 	 */
-	if (idev->rndid[0] == 0xfd && 
+	if (idev->rndid[0] == 0xfd &&
 	    (idev->rndid[1]&idev->rndid[2]&idev->rndid[3]&idev->rndid[4]&idev->rndid[5]&idev->rndid[6]) == 0xff &&
 	    (idev->rndid[7]&0x80))
 		goto regen;
@@ -1502,9 +1501,9 @@
 
 	if (__ipv6_regen_rndid(idev) < 0)
 		goto out;
-	
+
 	expires = jiffies +
-		idev->cnf.temp_prefered_lft * HZ - 
+		idev->cnf.temp_prefered_lft * HZ -
 		idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor;
 	if (time_before(expires, jiffies)) {
 		printk(KERN_WARNING
@@ -1630,12 +1629,12 @@
 	struct inet6_dev *in6_dev;
 
 	pinfo = (struct prefix_info *) opt;
-	
+
 	if (len < sizeof(struct prefix_info)) {
 		ADBG(("addrconf: prefix option too short\n"));
 		return;
 	}
-	
+
 	/*
 	 *	Validation checks ([ADDRCONF], page 19)
 	 */
@@ -1827,7 +1826,7 @@
 				 * When a new public address is created as described in [ADDRCONF],
 				 * also create a new temporary address.
 				 */
-				read_unlock_bh(&in6_dev->lock); 
+				read_unlock_bh(&in6_dev->lock);
 				ipv6_create_tempaddr(ifp, NULL);
 			} else {
 				read_unlock_bh(&in6_dev->lock);
@@ -1913,14 +1912,14 @@
 	int scope;
 
 	ASSERT_RTNL();
-	
+
 	/* check the lifetime */
 	if (!valid_lft || prefered_lft > valid_lft)
 		return -EINVAL;
 
 	if ((dev = __dev_get_by_index(ifindex)) == NULL)
 		return -ENODEV;
-	
+
 	if ((idev = addrconf_add_dev(dev)) == NULL)
 		return -ENOBUFS;
 
@@ -1960,7 +1959,7 @@
 	struct inet6_ifaddr *ifp;
 	struct inet6_dev *idev;
 	struct net_device *dev;
-	
+
 	if ((dev = __dev_get_by_index(ifindex)) == NULL)
 		return -ENODEV;
 
@@ -1973,7 +1972,7 @@
 		    ipv6_addr_equal(pfx, &ifp->addr)) {
 			in6_ifa_hold(ifp);
 			read_unlock_bh(&idev->lock);
-			
+
 			ipv6_del_addr(ifp);
 
 			/* If the last address is deleted administratively,
@@ -1993,10 +1992,10 @@
 {
 	struct in6_ifreq ireq;
 	int err;
-	
+
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
-	
+
 	if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
 		return -EFAULT;
 
@@ -2011,7 +2010,7 @@
 {
 	struct in6_ifreq ireq;
 	int err;
-	
+
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
@@ -2056,7 +2055,7 @@
 		return;
 	}
 
-        for (dev = dev_base; dev != NULL; dev = dev->next) {
+	for (dev = dev_base; dev != NULL; dev = dev->next) {
 		struct in_device * in_dev = __in_dev_get_rtnl(dev);
 		if (in_dev && (dev->flags & IFF_UP)) {
 			struct in_ifaddr * ifa;
@@ -2091,7 +2090,7 @@
 				}
 			}
 		}
-        }
+	}
 }
 #endif
 
@@ -2137,7 +2136,7 @@
 
 	ASSERT_RTNL();
 
-	if ((dev->type != ARPHRD_ETHER) && 
+	if ((dev->type != ARPHRD_ETHER) &&
 	    (dev->type != ARPHRD_FDDI) &&
 	    (dev->type != ARPHRD_IEEE802_TR) &&
 	    (dev->type != ARPHRD_ARCNET) &&
@@ -2164,9 +2163,9 @@
 
 	ASSERT_RTNL();
 
-	/* 
-	 * Configure the tunnel with one of our IPv4 
-	 * addresses... we should configure all of 
+	/*
+	 * Configure the tunnel with one of our IPv4
+	 * addresses... we should configure all of
 	 * our v4 addrs in the tunnel
 	 */
 
@@ -2233,7 +2232,7 @@
 	ip6_tnl_add_linklocal(idev);
 }
 
-static int addrconf_notify(struct notifier_block *this, unsigned long event, 
+static int addrconf_notify(struct notifier_block *this, unsigned long event,
 			   void * data)
 {
 	struct net_device *dev = (struct net_device *) data;
@@ -2378,7 +2377,7 @@
 		return -ENODEV;
 
 	/* Step 1: remove reference to ipv6 device from parent device.
-	           Do not dev_put!
+		   Do not dev_put!
 	 */
 	if (how == 1) {
 		idev->dead = 1;
@@ -2461,7 +2460,7 @@
 	/* Step 5: netlink notification of this interface */
 	idev->tstamp = jiffies;
 	inet6_ifinfo_notify(RTM_DELLINK, idev);
-	
+
 	/* Shot the device (if unregistered) */
 
 	if (how == 1) {
@@ -2776,7 +2775,7 @@
 	goto out;
 }
 
-static struct file_operations if6_fops = {
+static const struct file_operations if6_fops = {
 	.owner		= THIS_MODULE,
 	.open		= if6_seq_open,
 	.read		= seq_read,
@@ -2850,8 +2849,8 @@
 			age = (now - ifp->tstamp) / HZ;
 
 #ifdef CONFIG_IPV6_PRIVACY
-			regen_advance = ifp->idev->cnf.regen_max_retry * 
-					ifp->idev->cnf.dad_transmits * 
+			regen_advance = ifp->idev->cnf.regen_max_retry *
+					ifp->idev->cnf.dad_transmits *
 					ifp->idev->nd_parms->retrans_time / HZ;
 #endif
 
@@ -3117,7 +3116,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
 		      ifa->idev->dev->ifindex);
@@ -3137,8 +3136,10 @@
 	}
 
 	if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 ||
-	    put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
-		return nlmsg_cancel(skb, nlh);
+	    put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) {
+		nlmsg_cancel(skb, nlh);
+		return -EMSGSIZE;
+	}
 
 	return nlmsg_end(skb, nlh);
 }
@@ -3155,13 +3156,15 @@
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
 	if (nla_put(skb, IFA_MULTICAST, 16, &ifmca->mca_addr) < 0 ||
 	    put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp,
-			  INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0)
-		return nlmsg_cancel(skb, nlh);
+			  INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
+		nlmsg_cancel(skb, nlh);
+		return -EMSGSIZE;
+	}
 
 	return nlmsg_end(skb, nlh);
 }
@@ -3178,13 +3181,15 @@
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
 	if (nla_put(skb, IFA_ANYCAST, 16, &ifaca->aca_addr) < 0 ||
 	    put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp,
-			  INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0)
-		return nlmsg_cancel(skb, nlh);
+			  INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
+		nlmsg_cancel(skb, nlh);
+		return -EMSGSIZE;
+	}
 
 	return nlmsg_end(skb, nlh);
 }
@@ -3211,7 +3216,7 @@
 	s_idx = cb->args[0];
 	s_ip_idx = ip_idx = cb->args[1];
 	read_lock(&dev_base_lock);
-	
+
 	for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
 		if (idx < s_idx)
 			continue;
@@ -3228,8 +3233,8 @@
 			     ifa = ifa->if_next, ip_idx++) {
 				if (ip_idx < s_ip_idx)
 					continue;
-				if ((err = inet6_fill_ifaddr(skb, ifa, 
-				    NETLINK_CB(cb->skb).pid, 
+				if ((err = inet6_fill_ifaddr(skb, ifa,
+				    NETLINK_CB(cb->skb).pid,
 				    cb->nlh->nlmsg_seq, RTM_NEWADDR,
 				    NLM_F_MULTI)) <= 0)
 					goto done;
@@ -3237,12 +3242,12 @@
 			break;
 		case MULTICAST_ADDR:
 			/* multicast address */
-			for (ifmca = idev->mc_list; ifmca; 
+			for (ifmca = idev->mc_list; ifmca;
 			     ifmca = ifmca->next, ip_idx++) {
 				if (ip_idx < s_ip_idx)
 					continue;
-				if ((err = inet6_fill_ifmcaddr(skb, ifmca, 
-				    NETLINK_CB(cb->skb).pid, 
+				if ((err = inet6_fill_ifmcaddr(skb, ifmca,
+				    NETLINK_CB(cb->skb).pid,
 				    cb->nlh->nlmsg_seq, RTM_GETMULTICAST,
 				    NLM_F_MULTI)) <= 0)
 					goto done;
@@ -3254,10 +3259,10 @@
 			     ifaca = ifaca->aca_next, ip_idx++) {
 				if (ip_idx < s_ip_idx)
 					continue;
-				if ((err = inet6_fill_ifacaddr(skb, ifaca, 
-				    NETLINK_CB(cb->skb).pid, 
+				if ((err = inet6_fill_ifacaddr(skb, ifaca,
+				    NETLINK_CB(cb->skb).pid,
 				    cb->nlh->nlmsg_seq, RTM_GETANYCAST,
-				    NLM_F_MULTI)) <= 0) 
+				    NLM_F_MULTI)) <= 0)
 					goto done;
 			}
 			break;
@@ -3334,9 +3339,12 @@
 
 	err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
 				nlh->nlmsg_seq, RTM_NEWADDR, 0);
-	/* failure implies BUG in inet6_ifaddr_msgsize() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout_ifa;
+	}
 	err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
 errout_ifa:
 	in6_ifa_put(ifa);
@@ -3354,9 +3362,12 @@
 		goto errout;
 
 	err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
-	/* failure implies BUG in inet6_ifaddr_msgsize() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
 errout:
 	if (err < 0)
@@ -3414,7 +3425,7 @@
 		 );
 }
 
-static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 
+static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
 			     u32 pid, u32 seq, int event, unsigned int flags)
 {
 	struct net_device *dev = idev->dev;
@@ -3426,7 +3437,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	hdr = nlmsg_data(nlh);
 	hdr->ifi_family = AF_INET6;
@@ -3469,7 +3480,8 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
@@ -3485,7 +3497,7 @@
 			continue;
 		if ((idev = in6_dev_get(dev)) == NULL)
 			continue;
-		err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid, 
+		err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid,
 				cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
 		in6_dev_put(idev);
 		if (err <= 0)
@@ -3501,15 +3513,18 @@
 {
 	struct sk_buff *skb;
 	int err = -ENOBUFS;
-	
+
 	skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
 	if (skb == NULL)
 		goto errout;
 
 	err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
-	/* failure implies BUG in inet6_if_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in inet6_if_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
 errout:
 	if (err < 0)
@@ -3533,7 +3548,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	pmsg = nlmsg_data(nlh);
 	pmsg->prefix_family = AF_INET6;
@@ -3558,10 +3573,11 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
-static void inet6_prefix_notify(int event, struct inet6_dev *idev, 
+static void inet6_prefix_notify(int event, struct inet6_dev *idev,
 			 struct prefix_info *pinfo)
 {
 	struct sk_buff *skb;
@@ -3572,9 +3588,12 @@
 		goto errout;
 
 	err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
-	/* failure implies BUG in inet6_prefix_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in inet6_prefix_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
 errout:
 	if (err < 0)
@@ -3655,10 +3674,10 @@
 			rt6_purge_dflt_routers();
 	}
 
-        return ret;
+	return ret;
 }
 
-static int addrconf_sysctl_forward_strategy(ctl_table *table, 
+static int addrconf_sysctl_forward_strategy(ctl_table *table,
 					    int __user *name, int nlen,
 					    void __user *oldval,
 					    size_t __user *oldlenp,
@@ -3723,19 +3742,19 @@
 } addrconf_sysctl __read_mostly = {
 	.sysctl_header = NULL,
 	.addrconf_vars = {
-        	{
+		{
 			.ctl_name	=	NET_IPV6_FORWARDING,
 			.procname	=	"forwarding",
-         		.data		=	&ipv6_devconf.forwarding,
+			.data		=	&ipv6_devconf.forwarding,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&addrconf_sysctl_forward,
+			.proc_handler	=	&addrconf_sysctl_forward,
 			.strategy	=	&addrconf_sysctl_forward_strategy,
 		},
 		{
 			.ctl_name	=	NET_IPV6_HOP_LIMIT,
 			.procname	=	"hop_limit",
-         		.data		=	&ipv6_devconf.hop_limit,
+			.data		=	&ipv6_devconf.hop_limit,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
 			.proc_handler	=	proc_dointvec,
@@ -3744,116 +3763,116 @@
 			.ctl_name	=	NET_IPV6_MTU,
 			.procname	=	"mtu",
 			.data		=	&ipv6_devconf.mtu6,
-         		.maxlen		=	sizeof(int),
+			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_ACCEPT_RA,
 			.procname	=	"accept_ra",
-         		.data		=	&ipv6_devconf.accept_ra,
+			.data		=	&ipv6_devconf.accept_ra,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_ACCEPT_REDIRECTS,
 			.procname	=	"accept_redirects",
-         		.data		=	&ipv6_devconf.accept_redirects,
+			.data		=	&ipv6_devconf.accept_redirects,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_AUTOCONF,
 			.procname	=	"autoconf",
-         		.data		=	&ipv6_devconf.autoconf,
+			.data		=	&ipv6_devconf.autoconf,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_DAD_TRANSMITS,
 			.procname	=	"dad_transmits",
-         		.data		=	&ipv6_devconf.dad_transmits,
+			.data		=	&ipv6_devconf.dad_transmits,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_RTR_SOLICITS,
 			.procname	=	"router_solicitations",
-         		.data		=	&ipv6_devconf.rtr_solicits,
+			.data		=	&ipv6_devconf.rtr_solicits,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_RTR_SOLICIT_INTERVAL,
 			.procname	=	"router_solicitation_interval",
-         		.data		=	&ipv6_devconf.rtr_solicit_interval,
+			.data		=	&ipv6_devconf.rtr_solicit_interval,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec_jiffies,
+			.proc_handler	=	&proc_dointvec_jiffies,
 			.strategy	=	&sysctl_jiffies,
 		},
 		{
 			.ctl_name	=	NET_IPV6_RTR_SOLICIT_DELAY,
 			.procname	=	"router_solicitation_delay",
-         		.data		=	&ipv6_devconf.rtr_solicit_delay,
+			.data		=	&ipv6_devconf.rtr_solicit_delay,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec_jiffies,
+			.proc_handler	=	&proc_dointvec_jiffies,
 			.strategy	=	&sysctl_jiffies,
 		},
 		{
 			.ctl_name	=	NET_IPV6_FORCE_MLD_VERSION,
 			.procname	=	"force_mld_version",
-         		.data		=	&ipv6_devconf.force_mld_version,
+			.data		=	&ipv6_devconf.force_mld_version,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 #ifdef CONFIG_IPV6_PRIVACY
 		{
 			.ctl_name	=	NET_IPV6_USE_TEMPADDR,
 			.procname	=	"use_tempaddr",
-	 		.data		=	&ipv6_devconf.use_tempaddr,
+			.data		=	&ipv6_devconf.use_tempaddr,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-	 		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_TEMP_VALID_LFT,
 			.procname	=	"temp_valid_lft",
-	 		.data		=	&ipv6_devconf.temp_valid_lft,
+			.data		=	&ipv6_devconf.temp_valid_lft,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-	 		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_TEMP_PREFERED_LFT,
 			.procname	=	"temp_prefered_lft",
-	 		.data		=	&ipv6_devconf.temp_prefered_lft,
+			.data		=	&ipv6_devconf.temp_prefered_lft,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-	 		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_REGEN_MAX_RETRY,
 			.procname	=	"regen_max_retry",
-	 		.data		=	&ipv6_devconf.regen_max_retry,
+			.data		=	&ipv6_devconf.regen_max_retry,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-	 		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_MAX_DESYNC_FACTOR,
 			.procname	=	"max_desync_factor",
-	 		.data		=	&ipv6_devconf.max_desync_factor,
+			.data		=	&ipv6_devconf.max_desync_factor,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-	 		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 #endif
 		{
@@ -3867,18 +3886,18 @@
 		{
 			.ctl_name	=	NET_IPV6_ACCEPT_RA_DEFRTR,
 			.procname	=	"accept_ra_defrtr",
-         		.data		=	&ipv6_devconf.accept_ra_defrtr,
+			.data		=	&ipv6_devconf.accept_ra_defrtr,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 		{
 			.ctl_name	=	NET_IPV6_ACCEPT_RA_PINFO,
 			.procname	=	"accept_ra_pinfo",
-         		.data		=	&ipv6_devconf.accept_ra_pinfo,
+			.data		=	&ipv6_devconf.accept_ra_pinfo,
 			.maxlen		=	sizeof(int),
 			.mode		=	0644,
-         		.proc_handler	=	&proc_dointvec,
+			.proc_handler	=	&proc_dointvec,
 		},
 #ifdef CONFIG_IPV6_ROUTER_PREF
 		{
@@ -3979,22 +3998,21 @@
 		return;
 	for (i=0; t->addrconf_vars[i].data; i++) {
 		t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf;
-		t->addrconf_vars[i].de = NULL;
 		t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */
 	}
 	if (dev) {
-		dev_name = dev->name; 
+		dev_name = dev->name;
 		t->addrconf_dev[0].ctl_name = dev->ifindex;
 	} else {
 		dev_name = "default";
 		t->addrconf_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;
 	}
 
-	/* 
-	 * Make a copy of dev_name, because '.procname' is regarded as const 
+	/*
+	 * Make a copy of dev_name, because '.procname' is regarded as const
 	 * by sysctl and we wouldn't want anyone to change it under our feet
 	 * (see SIOCSIFNAME).
-	 */	
+	 */
 	dev_name = kstrdup(dev_name, GFP_KERNEL);
 	if (!dev_name)
 	    goto free;
@@ -4002,15 +4020,11 @@
 	t->addrconf_dev[0].procname = dev_name;
 
 	t->addrconf_dev[0].child = t->addrconf_vars;
-	t->addrconf_dev[0].de = NULL;
 	t->addrconf_conf_dir[0].child = t->addrconf_dev;
-	t->addrconf_conf_dir[0].de = NULL;
 	t->addrconf_proto_dir[0].child = t->addrconf_conf_dir;
-	t->addrconf_proto_dir[0].de = NULL;
 	t->addrconf_root_dir[0].child = t->addrconf_proto_dir;
-	t->addrconf_root_dir[0].de = NULL;
 
-	t->sysctl_header = register_sysctl_table(t->addrconf_root_dir, 0);
+	t->sysctl_header = register_sysctl_table(t->addrconf_root_dir);
 	if (t->sysctl_header == NULL)
 		goto free_procname;
 	else
@@ -4046,12 +4060,12 @@
 
 int register_inet6addr_notifier(struct notifier_block *nb)
 {
-        return atomic_notifier_chain_register(&inet6addr_chain, nb);
+	return atomic_notifier_chain_register(&inet6addr_chain, nb);
 }
 
 int unregister_inet6addr_notifier(struct notifier_block *nb)
 {
-        return atomic_notifier_chain_unregister(&inet6addr_chain,nb);
+	return atomic_notifier_chain_unregister(&inet6addr_chain,nb);
 }
 
 /*
@@ -4095,7 +4109,7 @@
 	rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
 #ifdef CONFIG_SYSCTL
 	addrconf_sysctl.sysctl_header =
-		register_sysctl_table(addrconf_sysctl.addrconf_root_dir, 0);
+		register_sysctl_table(addrconf_sysctl.addrconf_root_dir);
 	addrconf_sysctl_register(NULL, &ipv6_devconf_dflt);
 #endif
 
@@ -4104,9 +4118,9 @@
 
 void __exit addrconf_cleanup(void)
 {
- 	struct net_device *dev;
- 	struct inet6_dev *idev;
- 	struct inet6_ifaddr *ifa;
+	struct net_device *dev;
+	struct inet6_dev *idev;
+	struct inet6_ifaddr *ifa;
 	int i;
 
 	unregister_netdevice_notifier(&ipv6_dev_notf);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 0e0e426..3585d8f 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -1,9 +1,9 @@
 /*
  *	PF_INET6 socket protocol family
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
@@ -28,7 +28,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -191,7 +190,7 @@
 	np->mc_loop	= 1;
 	np->pmtudisc	= IPV6_PMTUDISC_WANT;
 	np->ipv6only	= sysctl_ipv6_bindv6only;
-	
+
 	/* Init the ipv4 part of the socket since we can have sockets
 	 * using v6 API for ipv4.
 	 */
@@ -206,7 +205,7 @@
 		inet->pmtudisc = IP_PMTUDISC_DONT;
 	else
 		inet->pmtudisc = IP_PMTUDISC_WANT;
-	/* 
+	/*
 	 * Increment only the relevant sk_prot->socks debug field, this changes
 	 * the previous behaviour of incrementing both the equivalent to
 	 * answer->prot->socks (inet6_sock_nr) and inet_sock_nr.
@@ -293,7 +292,7 @@
 					 */
 					sk->sk_bound_dev_if = addr->sin6_scope_id;
 				}
-				
+
 				/* Binding to link-local address requires an interface */
 				if (!sk->sk_bound_dev_if) {
 					err = -EINVAL;
@@ -327,7 +326,7 @@
 	inet->saddr = v4addr;
 
 	ipv6_addr_copy(&np->rcv_saddr, &addr->sin6_addr);
-		
+
 	if (!(addr_type & IPV6_ADDR_MULTICAST))
 		ipv6_addr_copy(&np->saddr, &addr->sin6_addr);
 
@@ -393,7 +392,7 @@
 /*
  *	This does both peername and sockname.
  */
- 
+
 int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
 		 int *uaddr_len, int peer)
 {
@@ -401,7 +400,7 @@
 	struct sock *sk = sock->sk;
 	struct inet_sock *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
-  
+
 	sin->sin6_family = AF_INET6;
 	sin->sin6_flowinfo = 0;
 	sin->sin6_scope_id = 0;
@@ -433,14 +432,14 @@
 {
 	struct sock *sk = sock->sk;
 
-	switch(cmd) 
+	switch(cmd)
 	{
 	case SIOCGSTAMP:
 		return sock_get_timestamp(sk, (struct timeval __user *)arg);
 
 	case SIOCADDRT:
 	case SIOCDELRT:
-	  
+
 		return(ipv6_route_ioctl(cmd,(void __user *)arg));
 
 	case SIOCSIFADDR:
@@ -584,7 +583,7 @@
 	/* Add the new entry after the last permanent entry if any, so that
 	 * the new entry does not override a permanent entry when matched with
 	 * a wild-card protocol. But it is allowed to override any existing
-	 * non-permanent entry.  This means that when we remove this entry, the 
+	 * non-permanent entry.  This means that when we remove this entry, the
 	 * system automatically returns to the old behavior.
 	 */
 	list_add_rcu(&p->list, last_perm);
@@ -749,7 +748,7 @@
 	snmp6_mib_free((void **)ipv6_statistics);
 err_ip_mib:
 	return -ENOMEM;
-	
+
 }
 
 static void cleanup_ipv6_mibs(void)
@@ -763,7 +762,7 @@
 static int __init inet6_init(void)
 {
 	struct sk_buff *dummy_skb;
-        struct list_head *r;
+	struct list_head *r;
 	int err;
 
 	BUILD_BUG_ON(sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb));
@@ -814,7 +813,7 @@
 	err = init_ipv6_mibs();
 	if (err)
 		goto out_unregister_sock;
-	
+
 	/*
 	 *	ipngwg API draft makes clear that the correct semantics
 	 *	for TCP and UDP is to consider one TCP and UDP instance
@@ -933,11 +932,11 @@
 #ifdef CONFIG_PROC_FS
 	if6_proc_exit();
 	ac6_proc_exit();
- 	ipv6_misc_proc_exit();
- 	udp6_proc_exit();
- 	udplite6_proc_exit();
- 	tcp6_proc_exit();
- 	raw6_proc_exit();
+	ipv6_misc_proc_exit();
+	udp6_proc_exit();
+	udplite6_proc_exit();
+	tcp6_proc_exit();
+	raw6_proc_exit();
 #endif
 #ifdef CONFIG_IPV6_MIP6
 	mip6_fini();
@@ -952,7 +951,7 @@
 	ndisc_cleanup();
 	icmpv6_cleanup();
 #ifdef CONFIG_SYSCTL
-	ipv6_sysctl_unregister();	
+	ipv6_sysctl_unregister();
 #endif
 	cleanup_ipv6_mibs();
 	proto_unregister(&rawv6_prot);
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 12c5a4d..dc68b72 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -1,26 +1,26 @@
 /*
  * Copyright (C)2002 USAGI/WIDE Project
- * 
+ *
  * 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
  *
  * Authors
  *
- *	Mitsuru KANDA @USAGI       : IPv6 Support 
+ *	Mitsuru KANDA @USAGI       : IPv6 Support
  * 	Kazunori MIYAZAWA @USAGI   :
  * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
- * 	
+ *
  * 	This file is derived from net/ipv4/ah.c.
  */
 
@@ -54,7 +54,7 @@
 			optlen = 1;
 			break;
 		default:
-			if (len < 2) 
+			if (len < 2)
 				goto bad;
 			optlen = opt[off+1]+2;
 			if (len < optlen)
@@ -152,7 +152,7 @@
 	segments_left = rthdr->segments_left;
 	if (segments_left == 0)
 		return;
-	rthdr->segments_left = 0; 
+	rthdr->segments_left = 0;
 
 	/* The value of rthdr->hdrlen has been verified either by the system
 	 * call if it is locally generated, or by ipv6_rthdr_rcv() for incoming
@@ -278,7 +278,7 @@
 	top_iph->hop_limit   = 0;
 
 	ahp = x->data;
-	ah->hdrlen  = (XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + 
+	ah->hdrlen  = (XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) +
 				   ahp->icv_trunc_len) >> 2) - 2;
 
 	ah->reserved = 0;
@@ -319,7 +319,7 @@
 	 * Moving the pointer of skb->nh.raw by using skb_pull as long as AH
 	 * header length. Then copy back the copy as long as hdr_len
 	 * If destination header following AH exists, copy it into after [Ext2].
-	 * 
+	 *
 	 * |<>|[IPv6][Ext1][Ext2][Dest][Payload]
 	 * There is offset of AH before IPv6 header after the process.
 	 */
@@ -347,9 +347,9 @@
 	nexthdr = ah->nexthdr;
 	ah_hlen = (ah->hdrlen + 2) << 2;
 
-        if (ah_hlen != XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_full_len) &&
-            ah_hlen != XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_trunc_len))
-                goto out;
+	if (ah_hlen != XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_full_len) &&
+	    ah_hlen != XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_trunc_len))
+		goto out;
 
 	if (!pskb_may_pull(skb, ah_hlen))
 		goto out;
@@ -365,7 +365,7 @@
 	skb->nh.ipv6h->flow_lbl[2] = 0;
 	skb->nh.ipv6h->hop_limit   = 0;
 
-        {
+	{
 		u8 auth_data[MAX_AH_AUTH_LEN];
 
 		memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
@@ -395,8 +395,8 @@
 	return err;
 }
 
-static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 
-                    int type, int code, int offset, __be32 info)
+static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+		    int type, int code, int offset, __be32 info)
 {
 	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
 	struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset);
@@ -445,7 +445,7 @@
 	ahp->tfm = tfm;
 	if (crypto_hash_setkey(tfm, ahp->key, ahp->key_len))
 		goto error;
-	
+
 	/*
 	 * Lookup the algorithm description maintained by xfrm_algo,
 	 * verify crypto transform properties, and store information
@@ -462,16 +462,16 @@
 		       aalg_desc->uinfo.auth.icv_fullbits/8);
 		goto error;
 	}
-	
+
 	ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
 	ahp->icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
-	
+
 	BUG_ON(ahp->icv_trunc_len > MAX_AH_AUTH_LEN);
-	
+
 	ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL);
 	if (!ahp->work_icv)
 		goto error;
-	
+
 	x->props.header_len = XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_trunc_len);
 	if (x->props.mode == XFRM_MODE_TUNNEL)
 		x->props.header_len += sizeof(struct ipv6hdr);
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index a960476..e5ef5979 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -1,6 +1,6 @@
 /*
  *	Anycast support for IPv6
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
  *	David L Stevens (dlstevens@us.ibm.com)
@@ -21,7 +21,6 @@
 #include <linux/string.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -397,7 +396,7 @@
 	in6_dev_put(idev);
 	return ret;
 }
-	
+
 /*
  *	check if the interface has this anycast address
  */
@@ -565,7 +564,7 @@
 	goto out;
 }
 
-static struct file_operations ac6_seq_fops = {
+static const struct file_operations ac6_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	ac6_seq_open,
 	.read		=	seq_read,
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 5c94fea..3b4e8dc 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -1,9 +1,9 @@
 /*
  *	common UDP/RAW code
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	$Id: datagram.c,v 1.24 2002/02/01 22:01:04 davem Exp $
  *
@@ -17,7 +17,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
@@ -55,10 +54,10 @@
 	}
 
 	if (addr_len < SIN6_LEN_RFC2133)
-	  	return -EINVAL;
+		return -EINVAL;
 
-	if (usin->sin6_family != AF_INET6) 
-	  	return -EAFNOSUPPORT;
+	if (usin->sin6_family != AF_INET6)
+		return -EAFNOSUPPORT;
 
 	memset(&fl, 0, sizeof(fl));
 	if (np->sndflow) {
@@ -93,14 +92,14 @@
 		sin.sin_addr.s_addr = daddr->s6_addr32[3];
 		sin.sin_port = usin->sin6_port;
 
-		err = ip4_datagram_connect(sk, 
-					   (struct sockaddr*) &sin, 
+		err = ip4_datagram_connect(sk,
+					   (struct sockaddr*) &sin,
 					   sizeof(sin));
 
 ipv4_connected:
 		if (err)
 			goto out;
-		
+
 		ipv6_addr_set(&np->daddr, 0, 0, htonl(0x0000ffff), inet->daddr);
 
 		if (ipv6_addr_any(&np->saddr)) {
@@ -178,7 +177,7 @@
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+	if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
 		goto out;
 
 	/* source address lookup done in ip6_dst_lookup */
@@ -206,7 +205,7 @@
 	return err;
 }
 
-void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
+void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
 		     __be16 port, u32 info, u8 *payload)
 {
 	struct ipv6_pinfo *np  = inet6_sk(sk);
@@ -223,7 +222,7 @@
 	serr = SKB_EXT_ERR(skb);
 	serr->ee.ee_errno = err;
 	serr->ee.ee_origin = SO_EE_ORIGIN_ICMP6;
-	serr->ee.ee_type = icmph->icmp6_type; 
+	serr->ee.ee_type = icmph->icmp6_type;
 	serr->ee.ee_code = icmph->icmp6_code;
 	serr->ee.ee_pad = 0;
 	serr->ee.ee_info = info;
@@ -259,7 +258,7 @@
 	serr = SKB_EXT_ERR(skb);
 	serr->ee.ee_errno = err;
 	serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
-	serr->ee.ee_type = 0; 
+	serr->ee.ee_type = 0;
 	serr->ee.ee_code = 0;
 	serr->ee.ee_pad = 0;
 	serr->ee.ee_info = info;
@@ -274,7 +273,7 @@
 		kfree_skb(skb);
 }
 
-/* 
+/*
  *	Handle MSG_ERRQUEUE
  */
 int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
@@ -312,7 +311,7 @@
 	if (sin) {
 		sin->sin6_family = AF_INET6;
 		sin->sin6_flowinfo = 0;
-		sin->sin6_port = serr->port; 
+		sin->sin6_port = serr->port;
 		sin->sin6_scope_id = 0;
 		if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) {
 			ipv6_addr_copy(&sin->sin6_addr,
@@ -370,7 +369,7 @@
 		spin_unlock_bh(&sk->sk_error_queue.lock);
 	}
 
-out_free_skb:	
+out_free_skb:
 	kfree_skb(skb);
 out:
 	return err;
@@ -419,7 +418,7 @@
 		 * report extension headers (except for HbH)
 		 * in order.
 		 *
-		 * Also note that IPV6_RECVRTHDRDSTOPTS is NOT 
+		 * Also note that IPV6_RECVRTHDRDSTOPTS is NOT
 		 * (and WILL NOT be) defined because
 		 * IPV6_RECVDSTOPTS is more generic. --yoshfuji
 		 */
@@ -512,15 +511,15 @@
 			continue;
 
 		switch (cmsg->cmsg_type) {
- 		case IPV6_PKTINFO:
- 		case IPV6_2292PKTINFO:
- 			if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) {
+		case IPV6_PKTINFO:
+		case IPV6_2292PKTINFO:
+			if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) {
 				err = -EINVAL;
 				goto exit_f;
 			}
 
 			src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
-			
+
 			if (src_info->ipi6_ifindex) {
 				if (fl->oif && src_info->ipi6_ifindex != fl->oif)
 					return -EINVAL;
@@ -531,7 +530,7 @@
 
 			if (addr_type == IPV6_ADDR_ANY)
 				break;
-			
+
 			if (addr_type & IPV6_ADDR_LINKLOCAL) {
 				if (!src_info->ipi6_ifindex)
 					return -EINVAL;
@@ -554,7 +553,7 @@
 			break;
 
 		case IPV6_FLOWINFO:
-                        if (cmsg->cmsg_len < CMSG_LEN(4)) {
+			if (cmsg->cmsg_len < CMSG_LEN(4)) {
 				err = -EINVAL;
 				goto exit_f;
 			}
@@ -570,7 +569,7 @@
 
 		case IPV6_2292HOPOPTS:
 		case IPV6_HOPOPTS:
-                        if (opt->hopopt || cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) {
+			if (opt->hopopt || cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) {
 				err = -EINVAL;
 				goto exit_f;
 			}
@@ -590,7 +589,7 @@
 			break;
 
 		case IPV6_2292DSTOPTS:
-                        if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) {
+			if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) {
 				err = -EINVAL;
 				goto exit_f;
 			}
@@ -641,7 +640,7 @@
 
 		case IPV6_2292RTHDR:
 		case IPV6_RTHDR:
-                        if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_rt_hdr))) {
+			if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_rt_hdr))) {
 				err = -EINVAL;
 				goto exit_f;
 			}
@@ -661,7 +660,7 @@
 
 			len = ((rthdr->hdrlen + 1) << 3);
 
-                        if (cmsg->cmsg_len < CMSG_LEN(len)) {
+			if (cmsg->cmsg_len < CMSG_LEN(len)) {
 				err = -EINVAL;
 				goto exit_f;
 			}
@@ -716,7 +715,7 @@
 		    }
 		default:
 			LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n",
-			               cmsg->cmsg_type);
+				       cmsg->cmsg_type);
 			err = -EINVAL;
 			break;
 		};
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 25dcf69..363e63f 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -1,26 +1,26 @@
 /*
  * Copyright (C)2002 USAGI/WIDE Project
- * 
+ *
  * 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
  *
  * Authors
  *
- *	Mitsuru KANDA @USAGI       : IPv6 Support 
+ *	Mitsuru KANDA @USAGI       : IPv6 Support
  * 	Kazunori MIYAZAWA @USAGI   :
  * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
- * 	
+ *
  * 	This file is derived from net/ipv4/esp.c
  */
 
@@ -166,7 +166,7 @@
 	}
 
 	/* If integrity check is required, do this. */
-        if (esp->auth.icv_full_len) {
+	if (esp->auth.icv_full_len) {
 		u8 sum[alen];
 
 		ret = esp_mac_digest(esp, skb, 0, skb->len - alen);
@@ -197,7 +197,7 @@
 	if (esp->conf.ivlen)
 		crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen);
 
-        {
+	{
 		u8 nexthdr[2];
 		struct scatterlist *sg = &esp->sgbuf[0];
 		u8 padlen;
@@ -225,7 +225,7 @@
 			ret = -EINVAL;
 			goto out;
 		}
-		/* ... check padding bits here. Silly. :-) */ 
+		/* ... check padding bits here. Silly. :-) */
 
 		pskb_trim(skb, skb->len - alen - padlen - 2);
 		ret = nexthdr[1];
@@ -256,20 +256,20 @@
 }
 
 static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-                     int type, int code, int offset, __be32 info)
+		     int type, int code, int offset, __be32 info)
 {
 	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
 	struct ipv6_esp_hdr *esph = (struct ipv6_esp_hdr*)(skb->data+offset);
 	struct xfrm_state *x;
 
-	if (type != ICMPV6_DEST_UNREACH && 
+	if (type != ICMPV6_DEST_UNREACH &&
 	    type != ICMPV6_PKT_TOOBIG)
 		return;
 
 	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6);
 	if (!x)
 		return;
-	printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" NIP6_FMT "\n", 
+	printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" NIP6_FMT "\n",
 			ntohl(esph->spi), NIP6(iph->daddr));
 	xfrm_state_put(x);
 }
@@ -326,10 +326,10 @@
 		esp->auth.tfm = hash;
 		if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len))
 			goto error;
- 
+
 		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
 		BUG_ON(!aalg_desc);
- 
+
 		if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
 		    crypto_hash_digestsize(hash)) {
 			NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
@@ -338,10 +338,10 @@
 				 aalg_desc->uinfo.auth.icv_fullbits/8);
 			goto error;
 		}
- 
+
 		esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
 		esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
- 
+
 		esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
 		if (!esp->auth.work_icv)
 			goto error;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 0711f92..28e0c65 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -16,7 +16,7 @@
  */
 
 /* Changes:
- *	yoshfuji		: ensure not to overrun while parsing 
+ *	yoshfuji		: ensure not to overrun while parsing
  *				  tlv options.
  *	Mitsuru KANDA @USAGI and: Remove ipv6_parse_exthdrs().
  *	YOSHIFUJI Hideaki @USAGI  Register inbound extension header
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/netdevice.h>
 #include <linux/in6.h>
@@ -167,8 +166,8 @@
 				goto bad;
 			for (curr=procs; curr->type >= 0; curr++) {
 				if (curr->type == skb->nh.raw[off]) {
-					/* type specific length/alignment 
-					   checks will be performed in the 
+					/* type specific length/alignment
+					   checks will be performed in the
 					   func(). */
 					if (curr->func(skbp, off) == 0)
 						return 0;
@@ -572,7 +571,7 @@
    For now we need to test the engine, so that I created
    temporary (or permanent) backdoor.
    If listening socket set IPV6_RTHDR to 2, then we invert header.
-                                                   --ANK (980729)
+						   --ANK (980729)
  */
 
 struct ipv6_txoptions *
@@ -635,7 +634,7 @@
 		return 1;
 	}
 	LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
-	               skb->nh.raw[optoff+1]);
+		       skb->nh.raw[optoff+1]);
 	kfree_skb(skb);
 	return 0;
 }
@@ -649,7 +648,7 @@
 
 	if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
 		LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
-		               skb->nh.raw[optoff+1]);
+			       skb->nh.raw[optoff+1]);
 		IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
 				 IPSTATS_MIB_INHDRERRORS);
 		goto drop;
@@ -740,7 +739,7 @@
 	int hops;
 
 	ihdr = (struct rt0_hdr *) opt;
-	
+
 	phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
 	memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
 
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index 21cbbbd..e1caa5d 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -4,13 +4,13 @@
  */
 #include <net/ipv6.h>
 
-/* 
+/*
  * find out if nexthdr is a well-known extension header or a protocol
  */
 
 int ipv6_ext_hdr(u8 nexthdr)
 {
-	/* 
+	/*
 	 * find out if nexthdr is an extension header or a protocol
 	 */
 	return ( (nexthdr == NEXTHDR_HOP)	||
@@ -25,18 +25,18 @@
  * Skip any extension headers. This is used by the ICMP module.
  *
  * Note that strictly speaking this conflicts with RFC 2460 4.0:
- * ...The contents and semantics of each extension header determine whether 
+ * ...The contents and semantics of each extension header determine whether
  * or not to proceed to the next header.  Therefore, extension headers must
  * be processed strictly in the order they appear in the packet; a
  * receiver must not, for example, scan through a packet looking for a
  * particular kind of extension header and process that header prior to
  * processing all preceding ones.
- * 
+ *
  * We do exactly this. This is a protocol bug. We can't decide after a
- * seeing an unknown discard-with-error flavour TLV option if it's a 
+ * seeing an unknown discard-with-error flavour TLV option if it's a
  * ICMP error message or not (errors should never be send in reply to
  * ICMP error messages).
- * 
+ *
  * But I see no other way to do this. This might need to be reexamined
  * when Linux implements ESP (and maybe AUTH) headers.
  * --AK
@@ -90,9 +90,9 @@
 				break;
 			hdrlen = 8;
 		} else if (nexthdr == NEXTHDR_AUTH)
-			hdrlen = (hp->hdrlen+2)<<2; 
+			hdrlen = (hp->hdrlen+2)<<2;
 		else
-			hdrlen = ipv6_optlen(hp); 
+			hdrlen = ipv6_optlen(hp);
 
 		nexthdr = hp->nexthdr;
 		start += hdrlen;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 3dcc4b7..edfe98b 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -37,7 +37,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
 #include <linux/skbuff.h>
@@ -107,7 +106,7 @@
 	spin_unlock_bh(&icmpv6_socket->sk->sk_lock.slock);
 }
 
-/* 
+/*
  * Slightly more convenient version of icmpv6_send.
  */
 void icmpv6_param_prob(struct sk_buff *skb, int code, int pos)
@@ -153,8 +152,8 @@
 
 static int sysctl_icmpv6_time __read_mostly = 1*HZ;
 
-/* 
- * Check the ICMP output rate limit 
+/*
+ * Check the ICMP output rate limit
  */
 static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
 				     struct flowi *fl)
@@ -170,7 +169,7 @@
 	if (type == ICMPV6_PKT_TOOBIG)
 		return 1;
 
-	/* 
+	/*
 	 * Look up the output route.
 	 * XXX: perhaps the expire for routing entries cloned by
 	 * this lookup should be more aggressive (not longer than timeout).
@@ -198,7 +197,7 @@
 /*
  *	an inline helper for the "simple" if statement below
  *	checks if parameter problem report is caused by an
- *	unrecognized IPv6 option that has the Option Type 
+ *	unrecognized IPv6 option that has the Option Type
  *	highest-order two bits set to 10
  */
 
@@ -298,7 +297,7 @@
 /*
  *	Send an ICMP message in response to a packet in error
  */
-void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, 
+void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
 		 struct net_device *dev)
 {
 	struct inet6_dev *idev = NULL;
@@ -320,7 +319,7 @@
 		return;
 
 	/*
-	 *	Make sure we respect the rules 
+	 *	Make sure we respect the rules
 	 *	i.e. RFC 1885 2.4(e)
 	 *	Rule (e.1) is enforced by not using icmpv6_send
 	 *	in any code that processes icmp errors.
@@ -336,8 +335,8 @@
 
 	if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST)) {
 		if (type != ICMPV6_PKT_TOOBIG &&
-		    !(type == ICMPV6_PARAMPROB && 
-		      code == ICMPV6_UNK_OPTION && 
+		    !(type == ICMPV6_PARAMPROB &&
+		      code == ICMPV6_UNK_OPTION &&
 		      (opt_unrec(skb, info))))
 			return;
 
@@ -364,7 +363,7 @@
 		return;
 	}
 
-	/* 
+	/*
 	 *	Never answer to a ICMP packet.
 	 */
 	if (is_ineligible(skb)) {
@@ -543,14 +542,14 @@
 	}
 	err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr));
 
-        ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTECHOREPLIES);
-        ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
+	ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTECHOREPLIES);
+	ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
 
-out_put: 
+out_put:
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
 	dst_release(dst);
-out: 
+out:
 	icmpv6_xmit_unlock();
 }
 
@@ -608,7 +607,7 @@
 	}
 	read_unlock(&raw_v6_lock);
 }
-  
+
 /*
  *	Handle icmp messages
  */
@@ -722,9 +721,9 @@
 		if (type & ICMPV6_INFOMSG_MASK)
 			break;
 
-		/* 
-		 * error of unknown type. 
-		 * must pass to upper level 
+		/*
+		 * error of unknown type.
+		 * must pass to upper level
 		 */
 
 		icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
@@ -852,7 +851,7 @@
 	case ICMPV6_PKT_TOOBIG:
 		*err = EMSGSIZE;
 		break;
-		
+
 	case ICMPV6_PARAMPROB:
 		*err = EPROTO;
 		fatal = 1;
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index b7e5bae..ae6b0e7 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -79,7 +79,7 @@
 			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) {
+	sk_for_each(sk, node, &head->twchain) {
 		const struct inet_timewait_sock *tw = inet_twsk(sk);
 
 		if(*((__portpair *)&(tw->tw_dport))	== ports	&&
@@ -115,7 +115,7 @@
 	sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) {
 		if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) {
 			const struct ipv6_pinfo *np = inet6_sk(sk);
-			
+
 			score = 1;
 			if (!ipv6_addr_any(&np->rcv_saddr)) {
 				if (!ipv6_addr_equal(&np->rcv_saddr, daddr))
@@ -172,7 +172,7 @@
 	const struct in6_addr *saddr = &np->daddr;
 	const int dif = sk->sk_bound_dev_if;
 	const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
-	const unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr,
+	const unsigned int hash = inet6_ehashfn(daddr, lport, saddr,
 						inet->dport);
 	struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
 	struct sock *sk2;
@@ -183,7 +183,7 @@
 	write_lock(&head->lock);
 
 	/* Check TIME-WAIT sockets first. */
-	sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) {
+	sk_for_each(sk2, node, &head->twchain) {
 		const struct inet6_timewait_sock *tw6 = inet6_twsk(sk2);
 
 		tw = inet_twsk(sk2);
@@ -249,81 +249,81 @@
 {
 	struct inet_hashinfo *hinfo = death_row->hashinfo;
 	const unsigned short snum = inet_sk(sk)->num;
- 	struct inet_bind_hashbucket *head;
- 	struct inet_bind_bucket *tb;
+	struct inet_bind_hashbucket *head;
+	struct inet_bind_bucket *tb;
 	int ret;
 
- 	if (snum == 0) {
- 		const int low = sysctl_local_port_range[0];
- 		const int high = sysctl_local_port_range[1];
+	if (snum == 0) {
+		const int low = sysctl_local_port_range[0];
+		const int high = sysctl_local_port_range[1];
 		const int range = high - low;
- 		int i, port;
+		int i, port;
 		static u32 hint;
 		const u32 offset = hint + inet6_sk_port_offset(sk);
 		struct hlist_node *node;
- 		struct inet_timewait_sock *tw = NULL;
+		struct inet_timewait_sock *tw = NULL;
 
- 		local_bh_disable();
+		local_bh_disable();
 		for (i = 1; i <= range; i++) {
 			port = low + (i + offset) % range;
- 			head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)];
- 			spin_lock(&head->lock);
+			head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)];
+			spin_lock(&head->lock);
 
- 			/* Does not bother with rcv_saddr checks,
- 			 * because the established check is already
- 			 * unique enough.
- 			 */
+			/* Does not bother with rcv_saddr checks,
+			 * because the established check is already
+			 * unique enough.
+			 */
 			inet_bind_bucket_for_each(tb, node, &head->chain) {
- 				if (tb->port == port) {
- 					BUG_TRAP(!hlist_empty(&tb->owners));
- 					if (tb->fastreuse >= 0)
- 						goto next_port;
- 					if (!__inet6_check_established(death_row,
+				if (tb->port == port) {
+					BUG_TRAP(!hlist_empty(&tb->owners));
+					if (tb->fastreuse >= 0)
+						goto next_port;
+					if (!__inet6_check_established(death_row,
 								       sk, port,
 								       &tw))
- 						goto ok;
- 					goto next_port;
- 				}
- 			}
+						goto ok;
+					goto next_port;
+				}
+			}
 
- 			tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
+			tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
 						     head, port);
- 			if (!tb) {
- 				spin_unlock(&head->lock);
- 				break;
- 			}
- 			tb->fastreuse = -1;
- 			goto ok;
+			if (!tb) {
+				spin_unlock(&head->lock);
+				break;
+			}
+			tb->fastreuse = -1;
+			goto ok;
 
- 		next_port:
- 			spin_unlock(&head->lock);
- 		}
- 		local_bh_enable();
+		next_port:
+			spin_unlock(&head->lock);
+		}
+		local_bh_enable();
 
- 		return -EADDRNOTAVAIL;
+		return -EADDRNOTAVAIL;
 
 ok:
 		hint += i;
 
- 		/* Head lock still held and bh's disabled */
- 		inet_bind_hash(sk, tb, port);
+		/* Head lock still held and bh's disabled */
+		inet_bind_hash(sk, tb, port);
 		if (sk_unhashed(sk)) {
- 			inet_sk(sk)->sport = htons(port);
- 			__inet6_hash(hinfo, sk);
- 		}
- 		spin_unlock(&head->lock);
+			inet_sk(sk)->sport = htons(port);
+			__inet6_hash(hinfo, sk);
+		}
+		spin_unlock(&head->lock);
 
- 		if (tw) {
- 			inet_twsk_deschedule(tw, death_row);
- 			inet_twsk_put(tw);
- 		}
+		if (tw) {
+			inet_twsk_deschedule(tw, death_row);
+			inet_twsk_put(tw);
+		}
 
 		ret = 0;
 		goto out;
- 	}
+	}
 
- 	head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
- 	tb   = inet_csk(sk)->icsk_bind_hash;
+	head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
+	tb   = inet_csk(sk)->icsk_bind_hash;
 	spin_lock_bh(&head->lock);
 
 	if (sk_head(&tb->owners) == sk && sk->sk_bind_node.next == NULL) {
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 96d8310..f4d7be7 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1,9 +1,9 @@
 /*
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *	Forwarding Information Database
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	$Id: ip6_fib.c,v 1.25 2001/10/31 21:55:55 davem Exp $
  *
@@ -97,7 +97,7 @@
 
 static struct fib6_walker_t fib6_walker_list = {
 	.prev	= &fib6_walker_list,
-	.next	= &fib6_walker_list, 
+	.next	= &fib6_walker_list,
 };
 
 #define FOR_WALKERS(w) for ((w)=fib6_walker_list.next; (w) != &fib6_walker_list; (w)=(w)->next)
@@ -131,7 +131,7 @@
 /*
  *	Auxiliary address test functions for the radix tree.
  *
- *	These assume a 32bit processor (although it will work on 
+ *	These assume a 32bit processor (although it will work on
  *	64bit processors)
  */
 
@@ -150,8 +150,7 @@
 {
 	struct fib6_node *fn;
 
-	if ((fn = kmem_cache_alloc(fib6_node_kmem, GFP_ATOMIC)) != NULL)
-		memset(fn, 0, sizeof(struct fib6_node));
+	fn = kmem_cache_zalloc(fib6_node_kmem, GFP_ATOMIC);
 
 	return fn;
 }
@@ -298,7 +297,7 @@
 	int res;
 	struct rt6_info *rt;
 
-	for (rt = w->leaf; rt; rt = rt->u.next) {
+	for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) {
 		res = rt6_dump_route(rt, w->args);
 		if (res < 0) {
 			/* Frame is full, suspend walking */
@@ -434,7 +433,7 @@
 	struct fib6_node *pn = NULL;
 	struct rt6key *key;
 	int	bit;
-       	__be32	dir = 0;
+	__be32	dir = 0;
 	__u32	sernum = fib6_new_sernum();
 
 	RT6_TRACE("fib6_add_1\n");
@@ -452,27 +451,27 @@
 		if (plen < fn->fn_bit ||
 		    !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
 			goto insert_above;
-		
+
 		/*
 		 *	Exact match ?
 		 */
-			 
+
 		if (plen == fn->fn_bit) {
 			/* clean up an intermediate node */
 			if ((fn->fn_flags & RTN_RTINFO) == 0) {
 				rt6_release(fn->leaf);
 				fn->leaf = NULL;
 			}
-			
+
 			fn->fn_sernum = sernum;
-				
+
 			return fn;
 		}
 
 		/*
 		 *	We have more bits to go
 		 */
-			 
+
 		/* Try to walk down on tree. */
 		fn->fn_sernum = sernum;
 		dir = addr_bit_set(addr, fn->fn_bit);
@@ -490,7 +489,7 @@
 	if (ln == NULL)
 		return NULL;
 	ln->fn_bit = plen;
-			
+
 	ln->parent = pn;
 	ln->fn_sernum = sernum;
 
@@ -504,7 +503,7 @@
 
 insert_above:
 	/*
-	 * split since we don't have a common prefix anymore or 
+	 * split since we don't have a common prefix anymore or
 	 * we have a less significant route.
 	 * we've to insert an intermediate node on the list
 	 * this new node will point to the one we need to create
@@ -518,18 +517,18 @@
 	   See comment in __ipv6_addr_diff: bit may be an invalid value,
 	   but if it is >= plen, the value is ignored in any case.
 	 */
-	
+
 	bit = __ipv6_addr_diff(addr, &key->addr, addrlen);
 
-	/* 
-	 *		(intermediate)[in]	
+	/*
+	 *		(intermediate)[in]
 	 *	          /	   \
 	 *	(new leaf node)[ln] (old node)[fn]
 	 */
 	if (plen > bit) {
 		in = node_alloc();
 		ln = node_alloc();
-		
+
 		if (in == NULL || ln == NULL) {
 			if (in)
 				node_free(in);
@@ -538,8 +537,8 @@
 			return NULL;
 		}
 
-		/* 
-		 * new intermediate node. 
+		/*
+		 * new intermediate node.
 		 * RTN_RTINFO will
 		 * be off since that an address that chooses one of
 		 * the branches would not match less specific routes
@@ -576,7 +575,7 @@
 		}
 	} else { /* plen <= bit */
 
-		/* 
+		/*
 		 *		(new leaf node)[ln]
 		 *	          /	   \
 		 *	     (old node)[fn] NULL
@@ -592,7 +591,7 @@
 		ln->parent = pn;
 
 		ln->fn_sernum = sernum;
-		
+
 		if (dir)
 			pn->right = ln;
 		else
@@ -624,11 +623,11 @@
 	    fn->leaf == &ip6_null_entry &&
 	    !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ){
 		fn->leaf = rt;
-		rt->u.next = NULL;
+		rt->u.dst.rt6_next = NULL;
 		goto out;
 	}
 
-	for (iter = fn->leaf; iter; iter=iter->u.next) {
+	for (iter = fn->leaf; iter; iter=iter->u.dst.rt6_next) {
 		/*
 		 *	Search for duplicates
 		 */
@@ -656,7 +655,7 @@
 		if (iter->rt6i_metric > rt->rt6i_metric)
 			break;
 
-		ins = &iter->u.next;
+		ins = &iter->u.dst.rt6_next;
 	}
 
 	/*
@@ -664,7 +663,7 @@
 	 */
 
 out:
-	rt->u.next = iter;
+	rt->u.dst.rt6_next = iter;
 	*ins = rt;
 	rt->rt6i_node = fn;
 	atomic_inc(&rt->rt6i_ref);
@@ -1105,7 +1104,7 @@
 	RT6_TRACE("fib6_del_route\n");
 
 	/* Unlink it */
-	*rtp = rt->u.next;
+	*rtp = rt->u.dst.rt6_next;
 	rt->rt6i_node = NULL;
 	rt6_stats.fib_rt_entries--;
 	rt6_stats.fib_discarded_routes++;
@@ -1115,14 +1114,14 @@
 	FOR_WALKERS(w) {
 		if (w->state == FWS_C && w->leaf == rt) {
 			RT6_TRACE("walker %p adjusted by delroute\n", w);
-			w->leaf = rt->u.next;
+			w->leaf = rt->u.dst.rt6_next;
 			if (w->leaf == NULL)
 				w->state = FWS_U;
 		}
 	}
 	read_unlock(&fib6_walker_lock);
 
-	rt->u.next = NULL;
+	rt->u.dst.rt6_next = NULL;
 
 	if (fn->leaf == NULL && fn->fn_flags&RTN_TL_ROOT)
 		fn->leaf = &ip6_null_entry;
@@ -1190,7 +1189,7 @@
 	 *	Walk the leaf entries looking for ourself
 	 */
 
-	for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
+	for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.dst.rt6_next) {
 		if (*rtp == rt) {
 			fib6_del_route(fn, rtp, info);
 			return 0;
@@ -1206,7 +1205,7 @@
  *	However, it is internally reenterable wrt itself and fib6_add/fib6_del.
  *	It means, that we can modify tree during walking
  *	and use this function for garbage collection, clone pruning,
- *	cleaning tree when a device goes down etc. etc.	
+ *	cleaning tree when a device goes down etc. etc.
  *
  *	It guarantees that every node will be traversed,
  *	and that it will be traversed only once.
@@ -1245,7 +1244,7 @@
 				continue;
 			}
 			w->state = FWS_L;
-#endif	
+#endif
 		case FWS_L:
 			if (fn->left) {
 				w->node = fn->left;
@@ -1317,7 +1316,7 @@
 	struct rt6_info *rt;
 	struct fib6_cleaner_t *c = (struct fib6_cleaner_t*)w;
 
-	for (rt = w->leaf; rt; rt = rt->u.next) {
+	for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) {
 		res = c->func(rt, c->arg);
 		if (res < 0) {
 			w->leaf = rt;
@@ -1338,7 +1337,7 @@
 
 /*
  *	Convenient frontend to tree walker.
- *	
+ *
  *	func is called on each route.
  *		It may return -1 -> delete this route.
  *		              0  -> continue walking
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 624fae2..c206a15 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -228,10 +228,10 @@
 					 struct ipv6_txoptions * fopt)
 {
 	struct ipv6_txoptions * fl_opt = fl->opt;
-	
+
 	if (fopt == NULL || fopt->opt_flen == 0)
 		return fl_opt;
-	
+
 	if (fl_opt != NULL) {
 		opt_space->hopopt = fl_opt->hopopt;
 		opt_space->dst0opt = fl_opt->dst0opt;
@@ -677,7 +677,7 @@
 	goto out;
 }
 
-static struct file_operations ip6fl_seq_fops = {
+static const struct file_operations ip6fl_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	ip6fl_seq_open,
 	.read		=	seq_read,
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index ad0b8ab..11bfc7c 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -1,6 +1,6 @@
 /*
  *	IPv6 input
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>
@@ -25,7 +25,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/netdevice.h>
 #include <linux/in6.h>
@@ -48,7 +47,7 @@
 
 
 
-inline int ip6_rcv_finish( struct sk_buff *skb) 
+inline int ip6_rcv_finish( struct sk_buff *skb)
 {
 	if (skb->dst == NULL)
 		ip6_route_input(skb);
@@ -173,9 +172,9 @@
 	hash = nexthdr & (MAX_INET_PROTOS - 1);
 	if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) {
 		int ret;
-		
+
 		if (ipprot->flags & INET6_PROTO_FINAL) {
-			struct ipv6hdr *hdr;	
+			struct ipv6hdr *hdr;
 
 			/* Free reference early: we don't need it any more,
 			   and it may hold ip_conntrack module loaded
@@ -192,9 +191,9 @@
 				goto discard;
 		}
 		if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
-		    !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) 
+		    !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
 			goto discard;
-		
+
 		ret = ipprot->handler(&skb);
 		if (ret > 0)
 			goto resubmit;
@@ -205,8 +204,8 @@
 			if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
 				IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS);
 				icmpv6_send(skb, ICMPV6_PARAMPROB,
-				            ICMPV6_UNK_NEXTHDR, nhoff,
-				            skb->dev);
+					    ICMPV6_UNK_NEXTHDR, nhoff,
+					    skb->dev);
 			}
 		} else
 			IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS);
@@ -253,7 +252,7 @@
 			struct dst_entry *dst;
 
 			dst = skb->dst;
-			
+
 			if (deliver) {
 				skb2 = skb_clone(skb, GFP_ATOMIC);
 				dst_output(skb2);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 7b7bd44..3055169 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1,9 +1,9 @@
 /*
  *	IPv6 output functions
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	$Id: ip6_output.c,v 1.34 2002/02/01 22:01:04 davem Exp $
  *
@@ -363,7 +363,7 @@
 	struct dst_entry *dst = skb->dst;
 	struct ipv6hdr *hdr = skb->nh.ipv6h;
 	struct inet6_skb_parm *opt = IP6CB(skb);
-	
+
 	if (ipv6_devconf.forwarding == 0)
 		goto error;
 
@@ -473,7 +473,7 @@
 	hdr = skb->nh.ipv6h;
 
 	/* Mangling hops number delayed to point after skb COW */
- 
+
 	hdr->hop_limit--;
 
 	IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
@@ -659,7 +659,7 @@
 				frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr));
 				ip6_copy_metadata(frag, skb);
 			}
-			
+
 			err = output(skb);
 			if(!err)
 				IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGCREATES);
@@ -792,7 +792,7 @@
 fail:
 	IP6_INC_STATS(ip6_dst_idev(skb->dst),
 		      IPSTATS_MIB_FRAGFAILS);
-	kfree_skb(skb); 
+	kfree_skb(skb);
 	return err;
 }
 
@@ -955,7 +955,7 @@
 		struct frag_hdr fhdr;
 
 		/* specify the length of each IP datagram fragment*/
-		skb_shinfo(skb)->gso_size = mtu - fragheaderlen - 
+		skb_shinfo(skb)->gso_size = mtu - fragheaderlen -
 					    sizeof(struct frag_hdr);
 		skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
 		ipv6_select_ident(skb, &fhdr);
@@ -1058,13 +1058,13 @@
 	 * fragment alignment (= 8-15 octects, in total).
 	 *
 	 * Note that we may need to "move" the data from the tail of
-	 * of the buffer to the new fragment when we split 
+	 * of the buffer to the new fragment when we split
 	 * the message.
 	 *
-	 * FIXME: It may be fragmented into multiple chunks 
+	 * FIXME: It may be fragmented into multiple chunks
 	 *        at once if non-fragmentable extension headers
 	 *        are too large.
-	 * --yoshfuji 
+	 * --yoshfuji
 	 */
 
 	inet->cork.length += length;
@@ -1129,7 +1129,7 @@
 
 			/*
 			 * We just reserve space for fragment header.
-			 * Note: this may be overallocation if the message 
+			 * Note: this may be overallocation if the message
 			 * (without MSG_MORE) fits into the MTU.
 			 */
 			alloclen += sizeof(struct frag_hdr);
@@ -1310,7 +1310,7 @@
 		ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst);
 
 	skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr));
-	
+
 	*(__be32*)hdr = fl->fl6_flowlabel |
 		     htonl(0x60000000 | ((int)np->cork.tclass << 20));
 
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 8d91834..662edb8 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation
  *
  *	Authors:
- *	Ville Nuorvala		<vnuorval@tcs.hut.fi>	
+ *	Ville Nuorvala		<vnuorval@tcs.hut.fi>
  *
  *	$Id$
  *
@@ -67,8 +67,8 @@
 #define HASH_SIZE  32
 
 #define HASH(addr) ((__force u32)((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \
-	             (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \
-                    (HASH_SIZE - 1))
+		     (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \
+		    (HASH_SIZE - 1))
 
 static int ip6ip6_fb_tnl_dev_init(struct net_device *dev);
 static int ip6ip6_tnl_dev_init(struct net_device *dev);
@@ -90,7 +90,7 @@
 {
 	struct dst_entry *dst = t->dst_cache;
 
-	if (dst && dst->obsolete && 
+	if (dst && dst->obsolete &&
 	    dst->ops->check(dst, t->dst_cookie) == NULL) {
 		t->dst_cache = NULL;
 		dst_release(dst);
@@ -116,12 +116,12 @@
 
 /**
  * ip6ip6_tnl_lookup - fetch tunnel matching the end-point addresses
- *   @remote: the address of the tunnel exit-point 
- *   @local: the address of the tunnel entry-point 
+ *   @remote: the address of the tunnel exit-point
+ *   @local: the address of the tunnel entry-point
  *
- * Return:  
+ * Return:
  *   tunnel matching given end-points if found,
- *   else fallback tunnel if its device is up, 
+ *   else fallback tunnel if its device is up,
  *   else %NULL
  **/
 
@@ -146,13 +146,13 @@
 
 /**
  * ip6ip6_bucket - get head of list matching given tunnel parameters
- *   @p: parameters containing tunnel end-points 
+ *   @p: parameters containing tunnel end-points
  *
  * Description:
- *   ip6ip6_bucket() returns the head of the list matching the 
+ *   ip6ip6_bucket() returns the head of the list matching the
  *   &struct in6_addr entries laddr and raddr in @p.
  *
- * Return: head of IPv6 tunnel list 
+ * Return: head of IPv6 tunnel list
  **/
 
 static struct ip6_tnl **
@@ -213,8 +213,8 @@
  *
  * Description:
  *   Create tunnel matching given parameters.
- * 
- * Return: 
+ *
+ * Return:
  *   created tunnel or NULL
  **/
 
@@ -234,7 +234,7 @@
 			if (__dev_get_by_name(name) == NULL)
 				break;
 		}
-		if (i == IP6_TNL_MAX) 
+		if (i == IP6_TNL_MAX)
 			goto failed;
 	}
 	dev = alloc_netdev(sizeof (*t), name, ip6ip6_tnl_dev_setup);
@@ -258,7 +258,7 @@
 
 /**
  * ip6ip6_tnl_locate - find or create tunnel matching given parameters
- *   @p: tunnel parameters 
+ *   @p: tunnel parameters
  *   @create: != 0 if allowed to create new tunnel if no match found
  *
  * Description:
@@ -289,7 +289,7 @@
 /**
  * ip6ip6_tnl_dev_uninit - tunnel device uninitializer
  *   @dev: the device to be destroyed
- *   
+ *
  * Description:
  *   ip6ip6_tnl_dev_uninit() removes tunnel from its list
  **/
@@ -314,8 +314,8 @@
  * parse_tvl_tnl_enc_lim - handle encapsulation limit option
  *   @skb: received socket buffer
  *
- * Return: 
- *   0 if none was found, 
+ * Return:
+ *   0 if none was found,
  *   else index to encapsulation limit
  **/
 
@@ -392,8 +392,8 @@
 	__u16 len;
 	int err = -ENOENT;
 
-	/* If the packet doesn't contain the original IPv6 header we are 
-	   in trouble since we might need the source address for further 
+	/* If the packet doesn't contain the original IPv6 header we are
+	   in trouble since we might need the source address for further
 	   processing of the error. */
 
 	read_lock(&ip6ip6_lock);
@@ -418,7 +418,7 @@
 			if (net_ratelimit())
 				printk(KERN_WARNING
 				       "%s: Too small hop limit or "
-				       "routing loop in tunnel!\n", 
+				       "routing loop in tunnel!\n",
 				       t->parms.name);
 			rel_msg = 1;
 		}
@@ -502,7 +502,7 @@
 	int ret = 0;
 
 	if (p->flags & IP6_TNL_F_CAP_RCV) {
-    		struct net_device *ldev = NULL;
+		struct net_device *ldev = NULL;
 
 		if (p->link)
 			ldev = dev_get_by_index(p->link);
@@ -525,7 +525,7 @@
  * Return: 0
  **/
 
-static int 
+static int
 ip6ip6_rcv(struct sk_buff *skb)
 {
 	struct ipv6hdr *ipv6h;
@@ -595,13 +595,13 @@
 /**
  * ip6ip6_tnl_addr_conflict - compare packet addresses to tunnel's own
  *   @t: the outgoing tunnel device
- *   @hdr: IPv6 header from the incoming packet 
+ *   @hdr: IPv6 header from the incoming packet
  *
  * Description:
- *   Avoid trivial tunneling loop by checking that tunnel exit-point 
+ *   Avoid trivial tunneling loop by checking that tunnel exit-point
  *   doesn't match source of incoming packet.
  *
- * Return: 
+ * Return:
  *   1 if conflict,
  *   0 else
  **/
@@ -617,7 +617,7 @@
 	struct ip6_tnl_parm *p = &t->parms;
 	int ret = 0;
 
- 	if (p->flags & IP6_TNL_F_CAP_XMIT) {
+	if (p->flags & IP6_TNL_F_CAP_XMIT) {
 		struct net_device *ldev = NULL;
 
 		if (p->link)
@@ -641,19 +641,19 @@
 	return ret;
 }
 /**
- * ip6ip6_tnl_xmit - encapsulate packet and send 
+ * ip6ip6_tnl_xmit - encapsulate packet and send
  *   @skb: the outgoing socket buffer
- *   @dev: the outgoing tunnel device 
+ *   @dev: the outgoing tunnel device
  *
  * Description:
  *   Build new header and do some sanity checks on the packet before sending
  *   it.
  *
- * Return: 
+ * Return:
  *   0
  **/
 
-static int 
+static int
 ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
@@ -715,7 +715,7 @@
 	if (tdev == dev) {
 		stats->collisions++;
 		if (net_ratelimit())
-			printk(KERN_WARNING 
+			printk(KERN_WARNING
 			       "%s: Local routing loop detected!\n",
 			       t->parms.name);
 		goto tx_err_dst_release;
@@ -741,11 +741,11 @@
 	 * Okay, now see if we can stuff it in the buffer as-is.
 	 */
 	max_headroom += LL_RESERVED_SPACE(tdev);
-	
-	if (skb_headroom(skb) < max_headroom || 
+
+	if (skb_headroom(skb) < max_headroom ||
 	    skb_cloned(skb) || skb_shared(skb)) {
 		struct sk_buff *new_skb;
-		
+
 		if (!(new_skb = skb_realloc_headroom(skb, max_headroom)))
 			goto tx_err_dst_release;
 
@@ -775,7 +775,7 @@
 	ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst);
 	nf_reset(skb);
 	pkt_len = skb->len;
-	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, 
+	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL,
 		      skb->dst->dev, dst_output);
 
 	if (net_xmit_eval(err) == 0) {
@@ -898,14 +898,14 @@
 }
 
 /**
- * ip6ip6_tnl_ioctl - configure ipv6 tunnels from userspace 
+ * ip6ip6_tnl_ioctl - configure ipv6 tunnels from userspace
  *   @dev: virtual device associated with tunnel
  *   @ifr: parameters passed from userspace
  *   @cmd: command to be performed
  *
  * Description:
- *   ip6ip6_tnl_ioctl() is used for managing IPv6 tunnels 
- *   from userspace. 
+ *   ip6ip6_tnl_ioctl() is used for managing IPv6 tunnels
+ *   from userspace.
  *
  *   The possible commands are the following:
  *     %SIOCGETTUNNEL: get tunnel parameters for device
@@ -913,7 +913,7 @@
  *     %SIOCCHGTUNNEL: change tunnel parameters to those given
  *     %SIOCDELTUNNEL: delete tunnel
  *
- *   The fallback device "ip6tnl0", created during module 
+ *   The fallback device "ip6tnl0", created during module
  *   initialization, can be used for creating other tunnel devices.
  *
  * Return:
@@ -999,7 +999,8 @@
 				break;
 			dev = t->dev;
 		}
-		err = unregister_netdevice(dev);
+		err = 0;
+		unregister_netdevice(dev);
 		break;
 	default:
 		err = -EINVAL;
@@ -1008,7 +1009,7 @@
 }
 
 /**
- * ip6ip6_tnl_get_stats - return the stats for tunnel device 
+ * ip6ip6_tnl_get_stats - return the stats for tunnel device
  *   @dev: virtual device associated with tunnel
  *
  * Return: stats for device
@@ -1101,7 +1102,7 @@
  * Return: 0
  **/
 
-static int 
+static int
 ip6ip6_fb_tnl_dev_init(struct net_device *dev)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
@@ -1127,7 +1128,7 @@
 {
 	int  err;
 
-	if (xfrm6_tunnel_register(&ip6ip6_handler)) {
+	if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) {
 		printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
 		return -EAGAIN;
 	}
@@ -1146,7 +1147,7 @@
 	}
 	return 0;
 fail:
-	xfrm6_tunnel_deregister(&ip6ip6_handler);
+	xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
 	return err;
 }
 
@@ -1170,7 +1171,7 @@
 
 static void __exit ip6_tunnel_cleanup(void)
 {
-	if (xfrm6_tunnel_deregister(&ip6ip6_handler))
+	if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6))
 		printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
 
 	rtnl_lock();
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 511730b..5724ba9 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -9,25 +9,25 @@
  * 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
  */
-/* 
+/*
  * [Memo]
  *
  * Outbound:
- *  The compression of IP datagram MUST be done before AH/ESP processing, 
- *  fragmentation, and the addition of Hop-by-Hop/Routing header. 
+ *  The compression of IP datagram MUST be done before AH/ESP processing,
+ *  fragmentation, and the addition of Hop-by-Hop/Routing header.
  *
  * Inbound:
- *  The decompression of IP datagram MUST be done after the reassembly, 
+ *  The decompression of IP datagram MUST be done after the reassembly,
  *  AH/ESP processing.
  */
 #include <linux/module.h>
@@ -176,7 +176,7 @@
 }
 
 static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-		                int type, int code, int offset, __be32 info)
+				int type, int code, int offset, __be32 info)
 {
 	__be32 spi;
 	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
@@ -422,7 +422,7 @@
 	x->props.header_len = 0;
 	if (x->props.mode == XFRM_MODE_TUNNEL)
 		x->props.header_len += sizeof(struct ipv6hdr);
-	
+
 	mutex_lock(&ipcomp6_resource_mutex);
 	if (!ipcomp6_alloc_scratches())
 		goto error;
@@ -455,7 +455,7 @@
 	goto out;
 }
 
-static struct xfrm_type ipcomp6_type = 
+static struct xfrm_type ipcomp6_type =
 {
 	.description	= "IPCOMP6",
 	.owner		= THIS_MODULE,
@@ -467,7 +467,7 @@
 	.hdr_offset	= xfrm6_find_1stfragopt,
 };
 
-static struct inet6_protocol ipcomp6_protocol = 
+static struct inet6_protocol ipcomp6_protocol =
 {
 	.handler	= xfrm6_rcv,
 	.err_handler	= ipcomp6_err,
@@ -490,7 +490,7 @@
 
 static void __exit ipcomp6_fini(void)
 {
-	if (inet6_del_protocol(&ipcomp6_protocol, IPPROTO_COMP) < 0) 
+	if (inet6_del_protocol(&ipcomp6_protocol, IPPROTO_COMP) < 0)
 		printk(KERN_INFO "ipv6 ipcomp close: can't remove protocol\n");
 	if (xfrm_unregister_type(&ipcomp6_type, AF_INET6) < 0)
 		printk(KERN_INFO "ipv6 ipcomp close: can't remove xfrm type\n");
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 352690e..286c867 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -1,9 +1,9 @@
 /*
  *	IPv6 BSD socket options interface
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	Based on linux/net/ipv4/ip_sockglue.c
  *
@@ -31,7 +31,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -164,7 +163,7 @@
 }
 
 static struct packet_type ipv6_packet_type = {
-	.type = __constant_htons(ETH_P_IPV6), 
+	.type = __constant_htons(ETH_P_IPV6),
 	.func = ipv6_rcv,
 	.gso_send_check = ipv6_gso_send_check,
 	.gso_segment = ipv6_gso_segment,
@@ -320,7 +319,7 @@
 		np->rxopt.bits.rxinfo = valbool;
 		retv = 0;
 		break;
-		
+
 	case IPV6_2292PKTINFO:
 		np->rxopt.bits.rxoinfo = valbool;
 		retv = 0;
@@ -376,7 +375,7 @@
 		np->tclass = val;
 		retv = 0;
 		break;
-		
+
 	case IPV6_RECVTCLASS:
 		np->rxopt.bits.rxtclass = valbool;
 		retv = 0;
@@ -893,7 +892,7 @@
 	case IPV6_MTU:
 	{
 		struct dst_entry *dst;
-		val = 0;	
+		val = 0;
 		lock_sock(sk);
 		dst = sk_dst_get(sk);
 		if (dst) {
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 882cde4..a8d6625 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1,13 +1,13 @@
 /*
  *	Multicast support for IPv6
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	$Id: mcast.c,v 1.40 2002/02/08 03:57:19 davem Exp $
  *
- *	Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c 
+ *	Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -644,7 +644,7 @@
 		memset(&ss, 0, sizeof(ss));
 		psin6->sin6_family = AF_INET6;
 		psin6->sin6_addr = psl->sl_addr[i];
-	    	if (copy_to_user(&optval->gf_slist[i], &ss, sizeof(ss)))
+		if (copy_to_user(&optval->gf_slist[i], &ss, sizeof(ss)))
 			return -EFAULT;
 	}
 	return 0;
@@ -1168,7 +1168,7 @@
 
 	/* compute payload length excluding extension headers */
 	len = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr);
-	len -= (char *)skb->h.raw - (char *)skb->nh.ipv6h; 
+	len -= (char *)skb->h.raw - (char *)skb->nh.ipv6h;
 
 	/* Drop queries with not link local source */
 	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr)&IPV6_ADDR_LINKLOCAL))
@@ -1206,7 +1206,7 @@
 		/* clear deleted report items */
 		mld_clear_delrec(idev);
 	} else if (len >= 28) {
-		int srcs_offset = sizeof(struct mld2_query) - 
+		int srcs_offset = sizeof(struct mld2_query) -
 				  sizeof(struct icmp6hdr);
 		if (!pskb_may_pull(skb, srcs_offset)) {
 			in6_dev_put(idev);
@@ -1230,7 +1230,7 @@
 		}
 		/* mark sources to include, if group & source-specific */
 		if (mlh2->nsrcs != 0) {
-			if (!pskb_may_pull(skb, srcs_offset + 
+			if (!pskb_may_pull(skb, srcs_offset +
 			    ntohs(mlh2->nsrcs) * sizeof(struct in6_addr))) {
 				in6_dev_put(idev);
 				return -EINVAL;
@@ -1304,7 +1304,7 @@
 
 	/* Drop reports with not link local source */
 	addr_type = ipv6_addr_type(&skb->nh.ipv6h->saddr);
-	if (addr_type != IPV6_ADDR_ANY && 
+	if (addr_type != IPV6_ADDR_ANY &&
 	    !(addr_type&IPV6_ADDR_LINKLOCAL))
 		return -EINVAL;
 
@@ -1413,7 +1413,7 @@
 
 	if (ipv6_get_lladdr(dev, &addr_buf)) {
 		/* <draft-ietf-magma-mld-source-05.txt>:
-		 * use unspecified address as the source address 
+		 * use unspecified address as the source address
 		 * when a valid link-local address is not available.
 		 */
 		memset(&addr_buf, 0, sizeof(addr_buf));
@@ -1454,7 +1454,7 @@
 static inline int mld_dev_queue_xmit(struct sk_buff *skb)
 {
 	return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dev,
-	               mld_dev_queue_xmit2);
+		       mld_dev_queue_xmit2);
 }
 
 static void mld_sendpack(struct sk_buff *skb)
@@ -1582,6 +1582,8 @@
 			skb = add_grhead(skb, pmc, type, &pgr);
 			first = 0;
 		}
+		if (!skb)
+			return NULL;
 		psrc = (struct in6_addr *)skb_put(skb, sizeof(*psrc));
 		*psrc = psf->sf_addr;
 		scount++; stotal++;
@@ -1752,8 +1754,8 @@
 {
 	struct sock *sk = igmp6_socket->sk;
 	struct inet6_dev *idev;
-        struct sk_buff *skb;
-        struct icmp6hdr *hdr;
+	struct sk_buff *skb;
+	struct icmp6hdr *hdr;
 	struct in6_addr *snd_addr;
 	struct in6_addr *addrp;
 	struct in6_addr addr_buf;
@@ -1791,7 +1793,7 @@
 
 	if (ipv6_get_lladdr(dev, &addr_buf)) {
 		/* <draft-ietf-magma-mld-source-05.txt>:
-		 * use unspecified address as the source address 
+		 * use unspecified address as the source address
 		 * when a valid link-local address is not available.
 		 */
 		memset(&addr_buf, 0, sizeof(addr_buf));
@@ -2328,7 +2330,7 @@
 	struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
 
 	for (state->dev = dev_base, state->idev = NULL;
-	     state->dev; 
+	     state->dev;
 	     state->dev = state->dev->next) {
 		struct inet6_dev *idev;
 		idev = in6_dev_get(state->dev);
@@ -2411,7 +2413,7 @@
 	struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
 
 	seq_printf(seq,
-		   "%-4d %-15s " NIP6_SEQFMT " %5d %08X %ld\n", 
+		   "%-4d %-15s " NIP6_SEQFMT " %5d %08X %ld\n",
 		   state->dev->ifindex, state->dev->name,
 		   NIP6(im->mca_addr),
 		   im->mca_users, im->mca_flags,
@@ -2449,7 +2451,7 @@
 	goto out;
 }
 
-static struct file_operations igmp6_mc_seq_fops = {
+static const struct file_operations igmp6_mc_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	igmp6_mc_seq_open,
 	.read		=	seq_read,
@@ -2472,7 +2474,7 @@
 	struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
 
 	for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
-	     state->dev; 
+	     state->dev;
 	     state->dev = state->dev->next) {
 		struct inet6_dev *idev;
 		idev = in6_dev_get(state->dev);
@@ -2577,7 +2579,7 @@
 	struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
 
 	if (v == SEQ_START_TOKEN) {
-		seq_printf(seq, 
+		seq_printf(seq,
 			   "%3s %6s "
 			   "%32s %32s %6s %6s\n", "Idx",
 			   "Device", "Multicast Address",
@@ -2606,7 +2608,7 @@
 	struct seq_file *seq;
 	int rc = -ENOMEM;
 	struct igmp6_mcf_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
-	
+
 	if (!s)
 		goto out;
 
@@ -2623,7 +2625,7 @@
 	goto out;
 }
 
-static struct file_operations igmp6_mcf_seq_fops = {
+static const struct file_operations igmp6_mcf_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	igmp6_mcf_seq_open,
 	.read		=	seq_read,
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index be7dd7d..0afcabd 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -89,7 +89,6 @@
 int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
 {
 	struct ip6_mh *mh;
-	int mhlen;
 
 	if (!pskb_may_pull(skb, (skb->h.raw - skb->data) + 8) ||
 	    !pskb_may_pull(skb, (skb->h.raw - skb->data) + ((skb->h.raw[1] + 1) << 3)))
@@ -103,31 +102,6 @@
 		mip6_param_prob(skb, 0, (&mh->ip6mh_hdrlen) - skb->nh.raw);
 		return -1;
 	}
-	mhlen = (mh->ip6mh_hdrlen + 1) << 3;
-
-	if (skb->ip_summed == CHECKSUM_COMPLETE) {
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
-				    &skb->nh.ipv6h->daddr,
-				    mhlen, IPPROTO_MH,
-				    skb->csum)) {
-			LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH hw checksum failed\n");
-			skb->ip_summed = CHECKSUM_NONE;
-		}
-	}
-	if (skb->ip_summed == CHECKSUM_NONE) {
-		if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
-				    &skb->nh.ipv6h->daddr,
-				    mhlen, IPPROTO_MH,
-				    skb_checksum(skb, 0, mhlen, 0))) {
-			LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH checksum failed "
-				       "[" NIP6_FMT " > " NIP6_FMT "]\n",
-				       NIP6(skb->nh.ipv6h->saddr),
-				       NIP6(skb->nh.ipv6h->daddr));
-			return -1;
-		}
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	}
 
 	if (mh->ip6mh_proto != IPPROTO_NONE) {
 		LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
@@ -359,7 +333,7 @@
 	.destructor	= mip6_destopt_destroy,
 	.input		= mip6_destopt_input,
 	.output		= mip6_destopt_output,
- 	.reject		= mip6_destopt_reject,
+	.reject		= mip6_destopt_reject,
 	.hdr_offset	= mip6_destopt_offset,
 	.local_addr	= mip6_xfrm_addr,
 };
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 39bb658..121f31c 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1,9 +1,9 @@
 /*
  *	Neighbour Discovery for IPv6
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *	Mike Shaver		<shaver@ingenia.com>
  *
  *	This program is free software; you can redistribute it and/or
@@ -427,25 +427,25 @@
 
 static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
 		   struct in6_addr *daddr, struct in6_addr *solicited_addr,
-	 	   int router, int solicited, int override, int inc_opt) 
+		   int router, int solicited, int override, int inc_opt)
 {
 	struct in6_addr tmpaddr;
 	struct inet6_ifaddr *ifp;
 	struct inet6_dev *idev;
 	struct flowi fl;
 	struct dst_entry* dst;
-        struct sock *sk = ndisc_socket->sk;
+	struct sock *sk = ndisc_socket->sk;
 	struct in6_addr *src_addr;
-        struct nd_msg *msg;
-        int len;
-        struct sk_buff *skb;
+	struct nd_msg *msg;
+	int len;
+	struct sk_buff *skb;
 	int err;
 
 	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
 
 	/* for anycast or proxy, solicited_addr != src_addr */
 	ifp = ipv6_get_ifaddr(solicited_addr, dev, 1);
- 	if (ifp) {
+	if (ifp) {
 		src_addr = solicited_addr;
 		in6_ifa_put(ifp);
 	} else {
@@ -479,7 +479,7 @@
 
 	if (skb == NULL) {
 		ND_PRINTK0(KERN_ERR
-			   "ICMPv6 NA: %s() failed to allocate an skb.\n", 
+			   "ICMPv6 NA: %s() failed to allocate an skb.\n",
 			   __FUNCTION__);
 		dst_release(dst);
 		return;
@@ -491,16 +491,16 @@
 	msg = (struct nd_msg *)skb_put(skb, len);
 	skb->h.raw = (unsigned char*)msg;
 
-        msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
-        msg->icmph.icmp6_code = 0;
-        msg->icmph.icmp6_cksum = 0;
+	msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
+	msg->icmph.icmp6_code = 0;
+	msg->icmph.icmp6_cksum = 0;
 
-        msg->icmph.icmp6_unused = 0;
-        msg->icmph.icmp6_router    = router;
-        msg->icmph.icmp6_solicited = solicited;
-        msg->icmph.icmp6_override  = override;
+	msg->icmph.icmp6_unused = 0;
+	msg->icmph.icmp6_router    = router;
+	msg->icmph.icmp6_solicited = solicited;
+	msg->icmph.icmp6_override  = override;
 
-        /* Set the target address. */
+	/* Set the target address. */
 	ipv6_addr_copy(&msg->target, solicited_addr);
 
 	if (inc_opt)
@@ -508,9 +508,9 @@
 				       dev->addr_len, dev->type);
 
 	/* checksum */
-	msg->icmph.icmp6_cksum = csum_ipv6_magic(src_addr, daddr, len, 
+	msg->icmph.icmp6_cksum = csum_ipv6_magic(src_addr, daddr, len,
 						 IPPROTO_ICMPV6,
-						 csum_partial((__u8 *) msg, 
+						 csum_partial((__u8 *) msg,
 							      len, 0));
 
 	skb->dst = dst;
@@ -524,20 +524,20 @@
 
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
-}        
+}
 
 void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
 		   struct in6_addr *solicit,
-		   struct in6_addr *daddr, struct in6_addr *saddr) 
+		   struct in6_addr *daddr, struct in6_addr *saddr)
 {
 	struct flowi fl;
 	struct dst_entry* dst;
 	struct inet6_dev *idev;
-        struct sock *sk = ndisc_socket->sk;
-        struct sk_buff *skb;
-        struct nd_msg *msg;
+	struct sock *sk = ndisc_socket->sk;
+	struct sk_buff *skb;
+	struct nd_msg *msg;
 	struct in6_addr addr_buf;
-        int len;
+	int len;
 	int err;
 	int send_llinfo;
 
@@ -569,7 +569,7 @@
 				  1, &err);
 	if (skb == NULL) {
 		ND_PRINTK0(KERN_ERR
-			   "ICMPv6 NA: %s() failed to allocate an skb.\n", 
+			   "ICMPv6 NA: %s() failed to allocate an skb.\n",
 			   __FUNCTION__);
 		dst_release(dst);
 		return;
@@ -594,9 +594,9 @@
 
 	/* checksum */
 	msg->icmph.icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr,
-						 daddr, len, 
+						 daddr, len,
 						 IPPROTO_ICMPV6,
-						 csum_partial((__u8 *) msg, 
+						 csum_partial((__u8 *) msg,
 							      len, 0));
 	/* send it! */
 	skb->dst = dst;
@@ -619,10 +619,10 @@
 	struct dst_entry* dst;
 	struct inet6_dev *idev;
 	struct sock *sk = ndisc_socket->sk;
-        struct sk_buff *skb;
-        struct icmp6hdr *hdr;
+	struct sk_buff *skb;
+	struct icmp6hdr *hdr;
 	__u8 * opt;
-        int len;
+	int len;
 	int err;
 
 	ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr,
@@ -640,13 +640,13 @@
 	if (dev->addr_len)
 		len += ndisc_opt_addr_space(dev);
 
-        skb = sock_alloc_send_skb(sk,
+	skb = sock_alloc_send_skb(sk,
 				  (MAX_HEADER + sizeof(struct ipv6hdr) +
 				   len + LL_RESERVED_SPACE(dev)),
 				  1, &err);
 	if (skb == NULL) {
 		ND_PRINTK0(KERN_ERR
-			   "ICMPv6 RS: %s() failed to allocate an skb.\n", 
+			   "ICMPv6 RS: %s() failed to allocate an skb.\n",
 			   __FUNCTION__);
 		dst_release(dst);
 		return;
@@ -655,12 +655,12 @@
 	skb_reserve(skb, LL_RESERVED_SPACE(dev));
 	ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
 
-        hdr = (struct icmp6hdr *)skb_put(skb, len);
-        skb->h.raw = (unsigned char*)hdr;
-        hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
-        hdr->icmp6_code = 0;
-        hdr->icmp6_cksum = 0;
-        hdr->icmp6_unused = 0;
+	hdr = (struct icmp6hdr *)skb_put(skb, len);
+	skb->h.raw = (unsigned char*)hdr;
+	hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
+	hdr->icmp6_code = 0;
+	hdr->icmp6_cksum = 0;
+	hdr->icmp6_unused = 0;
 
 	opt = (u8*) (hdr + 1);
 
@@ -686,7 +686,7 @@
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
 }
-		   
+
 
 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
 {
@@ -748,7 +748,7 @@
 	int is_router;
 
 	if (ipv6_addr_is_multicast(&msg->target)) {
-		ND_PRINTK2(KERN_WARNING 
+		ND_PRINTK2(KERN_WARNING
 			   "ICMPv6 NS: multicast target address");
 		return;
 	}
@@ -768,7 +768,7 @@
 	}
 
 	if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
-		ND_PRINTK2(KERN_WARNING 
+		ND_PRINTK2(KERN_WARNING
 			   "ICMPv6 NS: invalid ND options\n");
 		return;
 	}
@@ -782,12 +782,12 @@
 		}
 
 		/* RFC2461 7.1.1:
-	 	 *	If the IP source address is the unspecified address, 
-		 *	there MUST NOT be source link-layer address option 
+		 *	If the IP source address is the unspecified address,
+		 *	there MUST NOT be source link-layer address option
 		 *	in the message.
 		 */
 		if (dad) {
-			ND_PRINTK2(KERN_WARNING 
+			ND_PRINTK2(KERN_WARNING
 				   "ICMPv6 NS: bad DAD packet (link-layer address option)\n");
 			return;
 		}
@@ -816,7 +816,7 @@
 					goto out;
 				}
 			}
-			addrconf_dad_failure(ifp); 
+			addrconf_dad_failure(ifp);
 			return;
 		}
 
@@ -829,7 +829,7 @@
 		}
 
 		if (ipv6_chk_acast_addr(dev, &msg->target) ||
-		    (idev->cnf.forwarding && 
+		    (idev->cnf.forwarding &&
 		     (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) &&
 		     (pneigh = pneigh_lookup(&nd_tbl,
 					     &msg->target, dev, 0)) != NULL)) {
@@ -839,8 +839,8 @@
 			    idev->nd_parms->proxy_delay != 0) {
 				/*
 				 * for anycast or proxy,
-				 * sender should delay its response 
-				 * by a random time between 0 and 
+				 * sender should delay its response
+				 * by a random time between 0 and
 				 * MAX_ANYCAST_DELAY_TIME seconds.
 				 * (RFC2461) -- yoshfuji
 				 */
@@ -869,14 +869,14 @@
 	else
 		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);
 
-	/* 
+	/*
 	 *	update / create cache entry
 	 *	for the source address
 	 */
 	neigh = __neigh_lookup(&nd_tbl, saddr, dev,
 			       !inc || lladdr || !dev->addr_len);
 	if (neigh)
-		neigh_update(neigh, lladdr, NUD_STALE, 
+		neigh_update(neigh, lladdr, NUD_STALE,
 			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
 			     NEIGH_UPDATE_F_OVERRIDE);
 	if (neigh || !dev->hard_header) {
@@ -926,7 +926,7 @@
 			   "ICMPv6 NA: solicited NA is multicasted.\n");
 		return;
 	}
-		
+
 	if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
 		ND_PRINTK2(KERN_WARNING
 			   "ICMPv6 NS: invalid ND option\n");
@@ -1057,7 +1057,7 @@
 
 static void ndisc_router_discovery(struct sk_buff *skb)
 {
-        struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
+	struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
 	struct neighbour *neigh = NULL;
 	struct inet6_dev *in6_dev;
 	struct rt6_info *rt = NULL;
@@ -1076,7 +1076,7 @@
 		return;
 	}
 	if (optlen < 0) {
-		ND_PRINTK2(KERN_WARNING 
+		ND_PRINTK2(KERN_WARNING
 			   "ICMPv6 RA: packet too short\n");
 		return;
 	}
@@ -1286,7 +1286,7 @@
 			rt6_mtu_change(skb->dev, mtu);
 		}
 	}
-			
+
 	if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) {
 		ND_PRINTK2(KERN_WARNING
 			   "ICMPv6 RA: invalid RA options");
@@ -1339,7 +1339,7 @@
 	if (ipv6_addr_equal(dest, target)) {
 		on_link = 1;
 	} else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
-		ND_PRINTK2(KERN_WARNING 
+		ND_PRINTK2(KERN_WARNING
 			   "ICMPv6 Redirect: target address is not link-local.\n");
 		return;
 	}
@@ -1352,11 +1352,11 @@
 		return;
 	}
 
-	/* RFC2461 8.1: 
+	/* RFC2461 8.1:
 	 *	The IP source address of the Redirect MUST be the same as the current
 	 *	first-hop router for the specified ICMP Destination Address.
 	 */
-		
+
 	if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
 		ND_PRINTK2(KERN_WARNING
 			   "ICMPv6 Redirect: invalid ND options\n");
@@ -1410,8 +1410,8 @@
 		ND_PRINTK2(KERN_WARNING
 			   "ICMPv6 Redirect: no link-local address on %s\n",
 			   dev->name);
- 		return;
- 	}
+		return;
+	}
 
 	if (!ipv6_addr_equal(&skb->nh.ipv6h->daddr, target) &&
 	    !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
@@ -1507,7 +1507,7 @@
 	 *	build redirect option and copy skb over to the new packet.
 	 */
 
-	memset(opt, 0, 8);	
+	memset(opt, 0, 8);
 	*(opt++) = ND_OPT_REDIRECT_HDR;
 	*(opt++) = (rd_len >> 3);
 	opt += 6;
@@ -1556,7 +1556,7 @@
 	}
 
 	if (msg->icmph.icmp6_code != 0) {
-		ND_PRINTK2(KERN_WARNING 
+		ND_PRINTK2(KERN_WARNING
 			   "ICMPv6 NDISC: invalid ICMPv6 code: %d\n",
 			   msg->icmph.icmp6_code);
 		return 0;
@@ -1717,12 +1717,12 @@
 {
 	struct ipv6_pinfo *np;
 	struct sock *sk;
-        int err;
+	int err;
 
 	err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
 	if (err < 0) {
 		ND_PRINTK0(KERN_ERR
-			   "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n", 
+			   "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n",
 			   err);
 		ndisc_socket = NULL; /* For safety. */
 		return err;
@@ -1736,14 +1736,14 @@
 	np->mc_loop = 0;
 	sk->sk_prot->unhash(sk);
 
-        /*
-         * Initialize the neighbour table
-         */
-	
+	/*
+	 * Initialize the neighbour table
+	 */
+
 	neigh_table_init(&nd_tbl);
 
 #ifdef CONFIG_SYSCTL
-	neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH, 
+	neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH,
 			      "ipv6",
 			      &ndisc_ifinfo_sysctl_change,
 			      &ndisc_ifinfo_sysctl_strategy);
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index f6294e5..0b2d265 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -91,7 +91,7 @@
 		if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN)
 			break;
 		if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
-			    	     skb->len - dataoff, protocol,
+				     skb->len - dataoff, protocol,
 				     csum_sub(skb->csum,
 					      skb_checksum(skb, 0,
 							   dataoff, 0)))) {
@@ -106,7 +106,7 @@
 					     protocol,
 					     csum_sub(0,
 						      skb_checksum(skb, 0,
-							           dataoff, 0))));
+								   dataoff, 0))));
 		csum = __skb_checksum_complete(skb);
 	}
 	return csum;
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index adcd613..da07e9a 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -42,7 +42,8 @@
 
 config IP6_NF_IPTABLES
 	tristate "IP6 tables support (required for filtering)"
-	depends on INET && IPV6 && EXPERIMENTAL && NETFILTER_XTABLES
+	depends on INET && IPV6 && EXPERIMENTAL
+	select NETFILTER_XTABLES
 	help
 	  ip6tables is a general, extensible packet identification framework.
 	  Currently only the packet filtering and packet mangling subsystem
@@ -114,6 +115,14 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP6_NF_MATCH_MH
+	tristate "MH match support"
+	depends on IP6_NF_IPTABLES
+	help
+	  This module allows one to match MH packets.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP6_NF_MATCH_EUI64
 	tristate "EUI64 address check"
 	depends on IP6_NF_IPTABLES
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index ac1dfeb..4513eab 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -19,6 +19,7 @@
 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
+obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
 
 # objects for l3 independent conntrack
 nf_conntrack_ipv6-objs  :=  nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index d4d9f18..fdb30a5 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -95,7 +95,7 @@
 
 	list_for_each_prev(p, &queue_list) {
 		struct ipq_queue_entry *entry = (struct ipq_queue_entry *)p;
-		
+
 		if (!cmpfn || cmpfn(entry, data))
 			return entry;
 	}
@@ -127,7 +127,7 @@
 __ipq_flush(int verdict)
 {
 	struct ipq_queue_entry *entry;
-	
+
 	while ((entry = __ipq_find_dequeue_entry(NULL, 0)))
 		ipq_issue_verdict(entry, verdict);
 }
@@ -136,21 +136,21 @@
 __ipq_set_mode(unsigned char mode, unsigned int range)
 {
 	int status = 0;
-	
+
 	switch(mode) {
 	case IPQ_COPY_NONE:
 	case IPQ_COPY_META:
 		copy_mode = mode;
 		copy_range = 0;
 		break;
-		
+
 	case IPQ_COPY_PACKET:
 		copy_mode = mode;
 		copy_range = range;
 		if (copy_range > 0xFFFF)
 			copy_range = 0xFFFF;
 		break;
-		
+
 	default:
 		status = -EINVAL;
 
@@ -171,7 +171,7 @@
 ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data)
 {
 	struct ipq_queue_entry *entry;
-	
+
 	write_lock_bh(&queue_lock);
 	entry = __ipq_find_dequeue_entry(cmpfn, data);
 	write_unlock_bh(&queue_lock);
@@ -197,14 +197,14 @@
 	struct nlmsghdr *nlh;
 
 	read_lock_bh(&queue_lock);
-	
+
 	switch (copy_mode) {
 	case IPQ_COPY_META:
 	case IPQ_COPY_NONE:
 		size = NLMSG_SPACE(sizeof(*pmsg));
 		data_len = 0;
 		break;
-	
+
 	case IPQ_COPY_PACKET:
 		if ((entry->skb->ip_summed == CHECKSUM_PARTIAL ||
 		     entry->skb->ip_summed == CHECKSUM_COMPLETE) &&
@@ -216,10 +216,10 @@
 			data_len = entry->skb->len;
 		else
 			data_len = copy_range;
-		
+
 		size = NLMSG_SPACE(sizeof(*pmsg) + data_len);
 		break;
-	
+
 	default:
 		*errp = -EINVAL;
 		read_unlock_bh(&queue_lock);
@@ -231,7 +231,7 @@
 	skb = alloc_skb(size, GFP_ATOMIC);
 	if (!skb)
 		goto nlmsg_failure;
-		
+
 	old_tail= skb->tail;
 	nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh));
 	pmsg = NLMSG_DATA(nlh);
@@ -244,29 +244,29 @@
 	pmsg->mark            = entry->skb->mark;
 	pmsg->hook            = entry->info->hook;
 	pmsg->hw_protocol     = entry->skb->protocol;
-	
+
 	if (entry->info->indev)
 		strcpy(pmsg->indev_name, entry->info->indev->name);
 	else
 		pmsg->indev_name[0] = '\0';
-	
+
 	if (entry->info->outdev)
 		strcpy(pmsg->outdev_name, entry->info->outdev->name);
 	else
 		pmsg->outdev_name[0] = '\0';
-	
+
 	if (entry->info->indev && entry->skb->dev) {
 		pmsg->hw_type = entry->skb->dev->type;
 		if (entry->skb->dev->hard_header_parse)
 			pmsg->hw_addrlen =
 				entry->skb->dev->hard_header_parse(entry->skb,
-				                                   pmsg->hw_addr);
+								   pmsg->hw_addr);
 	}
-	
+
 	if (data_len)
 		if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len))
 			BUG();
-		
+
 	nlh->nlmsg_len = skb->tail - old_tail;
 	return skb;
 
@@ -279,7 +279,7 @@
 }
 
 static int
-ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, 
+ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
 		   unsigned int queuenum, void *data)
 {
 	int status = -EINVAL;
@@ -301,37 +301,37 @@
 	nskb = ipq_build_packet_message(entry, &status);
 	if (nskb == NULL)
 		goto err_out_free;
-		
+
 	write_lock_bh(&queue_lock);
-	
+
 	if (!peer_pid)
-		goto err_out_free_nskb; 
+		goto err_out_free_nskb;
 
 	if (queue_total >= queue_maxlen) {
-                queue_dropped++;
+		queue_dropped++;
 		status = -ENOSPC;
 		if (net_ratelimit())
-		        printk (KERN_WARNING "ip6_queue: fill at %d entries, "
+			printk (KERN_WARNING "ip6_queue: fill at %d entries, "
 				"dropping packet(s).  Dropped: %d\n", queue_total,
 				queue_dropped);
 		goto err_out_free_nskb;
 	}
 
- 	/* netlink_unicast will either free the nskb or attach it to a socket */ 
+	/* netlink_unicast will either free the nskb or attach it to a socket */
 	status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
 	if (status < 0) {
- 	        queue_user_dropped++;
+		queue_user_dropped++;
 		goto err_out_unlock;
 	}
-	
+
 	__ipq_enqueue_entry(entry);
 
 	write_unlock_bh(&queue_lock);
 	return status;
-	
+
 err_out_free_nskb:
-	kfree_skb(nskb); 
-	
+	kfree_skb(nskb);
+
 err_out_unlock:
 	write_unlock_bh(&queue_lock);
 
@@ -357,11 +357,11 @@
 			return -EINVAL;
 		if (diff > skb_tailroom(e->skb)) {
 			struct sk_buff *newskb;
-			
+
 			newskb = skb_copy_expand(e->skb,
-			                         skb_headroom(e->skb),
-			                         diff,
-			                         GFP_ATOMIC);
+						 skb_headroom(e->skb),
+						 diff,
+						 GFP_ATOMIC);
 			if (newskb == NULL) {
 				printk(KERN_WARNING "ip6_queue: OOM "
 				      "in mangle, dropping packet\n");
@@ -401,11 +401,11 @@
 		return -ENOENT;
 	else {
 		int verdict = vmsg->value;
-		
+
 		if (vmsg->data_len && vmsg->data_len == len)
 			if (ipq_mangle_ipv6(vmsg, entry) < 0)
 				verdict = NF_DROP;
-		
+
 		ipq_issue_verdict(entry, verdict);
 		return 0;
 	}
@@ -424,7 +424,7 @@
 
 static int
 ipq_receive_peer(struct ipq_peer_msg *pmsg,
-                 unsigned char type, unsigned int len)
+		 unsigned char type, unsigned int len)
 {
 	int status = 0;
 
@@ -434,15 +434,15 @@
 	switch (type) {
 	case IPQM_MODE:
 		status = ipq_set_mode(pmsg->msg.mode.value,
-		                      pmsg->msg.mode.range);
+				      pmsg->msg.mode.range);
 		break;
-		
+
 	case IPQM_VERDICT:
 		if (pmsg->msg.verdict.value > NF_MAX_VERDICT)
 			status = -EINVAL;
 		else
 			status = ipq_set_verdict(&pmsg->msg.verdict,
-			                         len - sizeof(*pmsg));
+						 len - sizeof(*pmsg));
 			break;
 	default:
 		status = -EINVAL;
@@ -456,7 +456,7 @@
 	if (entry->info->indev)
 		if (entry->info->indev->ifindex == ifindex)
 			return 1;
-			
+
 	if (entry->info->outdev)
 		if (entry->info->outdev->ifindex == ifindex)
 			return 1;
@@ -468,7 +468,7 @@
 ipq_dev_drop(int ifindex)
 {
 	struct ipq_queue_entry *entry;
-	
+
 	while ((entry = ipq_find_dequeue_entry(dev_cmp, ifindex)) != NULL)
 		ipq_issue_verdict(entry, NF_DROP);
 }
@@ -492,25 +492,25 @@
 
 	pid = nlh->nlmsg_pid;
 	flags = nlh->nlmsg_flags;
-	
+
 	if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI)
 		RCV_SKB_FAIL(-EINVAL);
-		
+
 	if (flags & MSG_TRUNC)
 		RCV_SKB_FAIL(-ECOMM);
-		
+
 	type = nlh->nlmsg_type;
 	if (type < NLMSG_NOOP || type >= IPQM_MAX)
 		RCV_SKB_FAIL(-EINVAL);
-		
+
 	if (type <= IPQM_BASE)
 		return;
-	
+
 	if (security_netlink_recv(skb, CAP_NET_ADMIN))
-		RCV_SKB_FAIL(-EPERM);	
+		RCV_SKB_FAIL(-EPERM);
 
 	write_lock_bh(&queue_lock);
-	
+
 	if (peer_pid) {
 		if (peer_pid != pid) {
 			write_unlock_bh(&queue_lock);
@@ -520,17 +520,17 @@
 		net_enable_timestamp();
 		peer_pid = pid;
 	}
-		
+
 	write_unlock_bh(&queue_lock);
-	
+
 	status = ipq_receive_peer(NLMSG_DATA(nlh), type,
-	                          nlmsglen - NLMSG_LENGTH(0));
+				  nlmsglen - NLMSG_LENGTH(0));
 	if (status < 0)
 		RCV_SKB_FAIL(status);
-		
+
 	if (flags & NLM_F_ACK)
 		netlink_ack(skb, nlh, 0);
-        return;
+	return;
 }
 
 static void
@@ -540,19 +540,19 @@
 	unsigned int qlen;
 
 	mutex_lock(&ipqnl_mutex);
-			
+
 	for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
 		skb = skb_dequeue(&sk->sk_receive_queue);
 		ipq_rcv_skb(skb);
 		kfree_skb(skb);
 	}
-		
+
 	mutex_unlock(&ipqnl_mutex);
 }
 
 static int
 ipq_rcv_dev_event(struct notifier_block *this,
-                  unsigned long event, void *ptr)
+		  unsigned long event, void *ptr)
 {
 	struct net_device *dev = ptr;
 
@@ -568,7 +568,7 @@
 
 static int
 ipq_rcv_nl_event(struct notifier_block *this,
-                 unsigned long event, void *ptr)
+		 unsigned long event, void *ptr)
 {
 	struct netlink_notify *n = ptr;
 
@@ -597,7 +597,7 @@
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
- 	{ .ctl_name = 0 }
+	{ .ctl_name = 0 }
 };
 
 static ctl_table ipq_dir_table[] = {
@@ -627,25 +627,25 @@
 	int len;
 
 	read_lock_bh(&queue_lock);
-	
+
 	len = sprintf(buffer,
-	              "Peer PID          : %d\n"
-	              "Copy mode         : %hu\n"
-	              "Copy range        : %u\n"
-	              "Queue length      : %u\n"
-	              "Queue max. length : %u\n"
+		      "Peer PID          : %d\n"
+		      "Copy mode         : %hu\n"
+		      "Copy range        : %u\n"
+		      "Queue length      : %u\n"
+		      "Queue max. length : %u\n"
 		      "Queue dropped     : %u\n"
 		      "Netfilter dropped : %u\n",
-	              peer_pid,
-	              copy_mode,
-	              copy_range,
-	              queue_total,
-	              queue_maxlen,
+		      peer_pid,
+		      copy_mode,
+		      copy_range,
+		      queue_total,
+		      queue_maxlen,
 		      queue_dropped,
 		      queue_user_dropped);
 
 	read_unlock_bh(&queue_lock);
-	
+
 	*start = buffer + offset;
 	len -= offset;
 	if (len > length)
@@ -665,10 +665,10 @@
 {
 	int status = -ENOMEM;
 	struct proc_dir_entry *proc;
-	
+
 	netlink_register_notifier(&ipq_nl_notifier);
 	ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
-	                              THIS_MODULE);
+				      THIS_MODULE);
 	if (ipqnl == NULL) {
 		printk(KERN_ERR "ip6_queue: failed to create netlink socket\n");
 		goto cleanup_netlink_notifier;
@@ -681,10 +681,10 @@
 		printk(KERN_ERR "ip6_queue: failed to create proc entry\n");
 		goto cleanup_ipqnl;
 	}
-	
+
 	register_netdevice_notifier(&ipq_dev_notifier);
-	ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
-	
+	ipq_sysctl_header = register_sysctl_table(ipq_root_table);
+
 	status = nf_register_queue_handler(PF_INET6, &nfqh);
 	if (status < 0) {
 		printk(KERN_ERR "ip6_queue: failed to register queue handler\n");
@@ -696,12 +696,12 @@
 	unregister_sysctl_table(ipq_sysctl_header);
 	unregister_netdevice_notifier(&ipq_dev_notifier);
 	proc_net_remove(IPQ_PROC_FS_NAME);
-	
+
 cleanup_ipqnl:
 	sock_release(ipqnl->sk_socket);
 	mutex_lock(&ipqnl_mutex);
 	mutex_unlock(&ipqnl_mutex);
-	
+
 cleanup_netlink_notifier:
 	netlink_unregister_notifier(&ipq_nl_notifier);
 	return status;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 99502c5..7c512e1 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -92,16 +92,16 @@
 #endif
 
 /* Check for an extension */
-int 
+int
 ip6t_ext_hdr(u8 nexthdr)
 {
-        return ( (nexthdr == IPPROTO_HOPOPTS)   ||
-                 (nexthdr == IPPROTO_ROUTING)   ||
-                 (nexthdr == IPPROTO_FRAGMENT)  ||
-                 (nexthdr == IPPROTO_ESP)       ||
-                 (nexthdr == IPPROTO_AH)        ||
-                 (nexthdr == IPPROTO_NONE)      ||
-                 (nexthdr == IPPROTO_DSTOPTS) );
+	return ( (nexthdr == IPPROTO_HOPOPTS)   ||
+		 (nexthdr == IPPROTO_ROUTING)   ||
+		 (nexthdr == IPPROTO_FRAGMENT)  ||
+		 (nexthdr == IPPROTO_ESP)       ||
+		 (nexthdr == IPPROTO_AH)        ||
+		 (nexthdr == IPPROTO_NONE)      ||
+		 (nexthdr == IPPROTO_DSTOPTS) );
 }
 
 /* Returns whether matches rule or not. */
@@ -120,9 +120,9 @@
 #define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg))
 
 	if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk,
-	                               &ip6info->src), IP6T_INV_SRCIP)
+				       &ip6info->src), IP6T_INV_SRCIP)
 	    || FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk,
-	                                  &ip6info->dst), IP6T_INV_DSTIP)) {
+					  &ip6info->dst), IP6T_INV_DSTIP)) {
 		dprintf("Source or dest mismatch.\n");
 /*
 		dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
@@ -177,7 +177,7 @@
 		*fragoff = _frag_off;
 
 		dprintf("Packet protocol %hi ?= %s%hi.\n",
-				protohdr, 
+				protohdr,
 				ip6info->invflags & IP6T_INV_PROTO ? "!":"",
 				ip6info->proto);
 
@@ -197,7 +197,7 @@
 }
 
 /* should be ip6 safe */
-static inline int 
+static inline int
 ip6_checkentry(const struct ip6t_ip6 *ipv6)
 {
 	if (ipv6->flags & ~IP6T_F_MASK) {
@@ -337,7 +337,7 @@
 				e = get_entry(table_base, v);
 			} else {
 				/* Targets which reenter must return
-                                   abs. verdicts */
+				   abs. verdicts */
 #ifdef CONFIG_NETFILTER_DEBUG
 				((struct ip6t_entry *)table_base)->comefrom
 					= 0xeeeeeeec;
@@ -530,14 +530,14 @@
 	    unsigned int hookmask,
 	    unsigned int *i)
 {
-	struct ip6t_match *match;
+	struct xt_match *match;
 	int ret;
 
 	match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
-			      		m->u.user.revision),
+					m->u.user.revision),
 					"ip6t_%s", m->u.user.name);
 	if (IS_ERR(match) || !match) {
-	  	duprintf("check_match: `%s' not found\n", m->u.user.name);
+		duprintf("check_match: `%s' not found\n", m->u.user.name);
 		return match ? PTR_ERR(match) : -ENOENT;
 	}
 	m->u.kernel.match = match;
@@ -564,14 +564,14 @@
 	return ret;
 }
 
-static struct ip6t_target ip6t_standard_target;
+static struct xt_target ip6t_standard_target;
 
 static inline int
 check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
 	    unsigned int *i)
 {
 	struct ip6t_entry_target *t;
-	struct ip6t_target *target;
+	struct xt_target *target;
 	int ret;
 	unsigned int j;
 
@@ -661,7 +661,7 @@
 	}
 
 	/* FIXME: underflows must be unconditional, standard verdicts
-           < 0 (not IP6T_RETURN). --RR */
+	   < 0 (not IP6T_RETURN). --RR */
 
 	/* Clear counters and comefrom */
 	e->counters = ((struct xt_counters) { 0, 0 });
@@ -1003,8 +1003,8 @@
 	/* 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)) 
+	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))
@@ -1348,13 +1348,13 @@
 }
 
 /* The built-in targets: standard (NULL) and error. */
-static struct ip6t_target ip6t_standard_target = {
+static struct xt_target ip6t_standard_target = {
 	.name		= IP6T_STANDARD_TARGET,
 	.targetsize	= sizeof(int),
 	.family		= AF_INET6,
 };
 
-static struct ip6t_target ip6t_error_target = {
+static struct xt_target ip6t_error_target = {
 	.name		= IP6T_ERROR_TARGET,
 	.target		= ip6t_error,
 	.targetsize	= IP6T_FUNCTION_MAXNAMELEN,
@@ -1371,7 +1371,7 @@
 	.get		= do_ip6t_get_ctl,
 };
 
-static struct ip6t_match icmp6_matchstruct = {
+static struct xt_match icmp6_matchstruct = {
 	.name		= "icmp6",
 	.match		= &icmp6_match,
 	.matchsize	= sizeof(struct ip6t_icmp),
@@ -1492,9 +1492,9 @@
 			}
 			hdrlen = 8;
 		} else if (nexthdr == NEXTHDR_AUTH)
-			hdrlen = (hp->hdrlen + 2) << 2; 
+			hdrlen = (hp->hdrlen + 2) << 2;
 		else
-			hdrlen = ipv6_optlen(hp); 
+			hdrlen = ipv6_optlen(hp);
 
 		nexthdr = hp->nexthdr;
 		len -= hdrlen;
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index 435750f..ccbab66 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Hop Limit modification target for ip6tables
  * Maciej Soltysiak <solt@dns.toxicfilms.tv>
  * Based on HW's TTL module
@@ -9,15 +9,16 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
+#include <linux/ipv6.h>
 
-#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6t_HL.h>
 
 MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
-MODULE_DESCRIPTION("IP tables Hop Limit modification module");
+MODULE_DESCRIPTION("IP6 tables Hop Limit modification module");
 MODULE_LICENSE("GPL");
 
-static unsigned int ip6t_hl_target(struct sk_buff **pskb, 
+static unsigned int ip6t_hl_target(struct sk_buff **pskb,
 				   const struct net_device *in,
 				   const struct net_device *out,
 				   unsigned int hooknum,
@@ -52,10 +53,9 @@
 			break;
 	}
 
-	if (new_hl != ip6h->hop_limit)
-		ip6h->hop_limit = new_hl;
+	ip6h->hop_limit = new_hl;
 
-	return IP6T_CONTINUE;
+	return XT_CONTINUE;
 }
 
 static int ip6t_hl_checkentry(const char *tablename,
@@ -67,7 +67,7 @@
 	struct ip6t_HL_info *info = targinfo;
 
 	if (info->mode > IP6T_HL_MAXMODE) {
-		printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", 
+		printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
 			info->mode);
 		return 0;
 	}
@@ -79,23 +79,24 @@
 	return 1;
 }
 
-static struct ip6t_target ip6t_HL = { 
-	.name 		= "HL", 
-	.target		= ip6t_hl_target, 
+static struct xt_target ip6t_HL = {
+	.name 		= "HL",
+	.family		= AF_INET6,
+	.target		= ip6t_hl_target,
 	.targetsize	= sizeof(struct ip6t_HL_info),
 	.table		= "mangle",
-	.checkentry	= ip6t_hl_checkentry, 
+	.checkentry	= ip6t_hl_checkentry,
 	.me		= THIS_MODULE
 };
 
 static int __init ip6t_hl_init(void)
 {
-	return ip6t_register_target(&ip6t_HL);
+	return xt_register_target(&ip6t_HL);
 }
 
 static void __exit ip6t_hl_fini(void)
 {
-	ip6t_unregister_target(&ip6t_HL);
+	xt_unregister_target(&ip6t_HL);
 }
 
 module_init(ip6t_hl_init);
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 33b1faa..afaa039 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -21,6 +21,7 @@
 #include <net/tcp.h>
 #include <net/ipv6.h>
 #include <linux/netfilter.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 
 MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
@@ -144,7 +145,7 @@
 							&_ahdr);
 				if (ah == NULL) {
 					/*
-					 * Max length: 26 "INCOMPLETE [65535 	
+					 * Max length: 26 "INCOMPLETE [65535
 					 *  bytes] )"
 					 */
 					printk("INCOMPLETE [%u bytes] )",
@@ -386,7 +387,7 @@
 		loginfo = &default_loginfo;
 
 	spin_lock_bh(&log_lock);
-	printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, 
+	printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
 		prefix,
 		in ? in->name : "",
 		out ? out->name : "");
@@ -441,8 +442,8 @@
 	li.u.log.logflags = loginfo->logflags;
 
 	ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
-	                loginfo->prefix);
-	return IP6T_CONTINUE;
+			loginfo->prefix);
+	return XT_CONTINUE;
 }
 
 
@@ -466,11 +467,12 @@
 	return 1;
 }
 
-static struct ip6t_target ip6t_log_reg = {
+static struct xt_target ip6t_log_reg = {
 	.name 		= "LOG",
-	.target 	= ip6t_log_target, 
+	.family		= AF_INET6,
+	.target 	= ip6t_log_target,
 	.targetsize	= sizeof(struct ip6t_log_info),
-	.checkentry	= ip6t_log_checkentry, 
+	.checkentry	= ip6t_log_checkentry,
 	.me 		= THIS_MODULE,
 };
 
@@ -482,8 +484,11 @@
 
 static int __init ip6t_log_init(void)
 {
-	if (ip6t_register_target(&ip6t_log_reg))
-		return -EINVAL;
+	int ret;
+
+	ret = xt_register_target(&ip6t_log_reg);
+	if (ret < 0)
+		return ret;
 	if (nf_log_register(PF_INET6, &ip6t_logger) < 0) {
 		printk(KERN_WARNING "ip6t_LOG: not logging via system console "
 		       "since somebody else already registered for PF_INET6\n");
@@ -496,8 +501,8 @@
 
 static void __exit ip6t_log_fini(void)
 {
-	nf_log_unregister_logger(&ip6t_logger);
-	ip6t_unregister_target(&ip6t_log_reg);
+	nf_log_unregister(&ip6t_logger);
+	xt_unregister_target(&ip6t_log_reg);
 }
 
 module_init(ip6t_log_init);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 311eae8..6abee94 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -26,6 +26,7 @@
 #include <net/ip6_fib.h>
 #include <net/ip6_route.h>
 #include <net/flow.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_REJECT.h>
 
@@ -188,23 +189,23 @@
 	/* WARNING: This code causes reentry within ip6tables.
 	   This means that the ip6tables jump stack is now crap.  We
 	   must return an absolute verdict. --RR */
-    	switch (reject->with) {
-    	case IP6T_ICMP6_NO_ROUTE:
-    		send_unreach(*pskb, ICMPV6_NOROUTE, hooknum);
-    		break;
-    	case IP6T_ICMP6_ADM_PROHIBITED:
-    		send_unreach(*pskb, ICMPV6_ADM_PROHIBITED, hooknum);
-    		break;
-    	case IP6T_ICMP6_NOT_NEIGHBOUR:
-    		send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR, hooknum);
-    		break;
-    	case IP6T_ICMP6_ADDR_UNREACH:
-    		send_unreach(*pskb, ICMPV6_ADDR_UNREACH, hooknum);
-    		break;
-    	case IP6T_ICMP6_PORT_UNREACH:
-    		send_unreach(*pskb, ICMPV6_PORT_UNREACH, hooknum);
-    		break;
-    	case IP6T_ICMP6_ECHOREPLY:
+	switch (reject->with) {
+	case IP6T_ICMP6_NO_ROUTE:
+		send_unreach(*pskb, ICMPV6_NOROUTE, hooknum);
+		break;
+	case IP6T_ICMP6_ADM_PROHIBITED:
+		send_unreach(*pskb, ICMPV6_ADM_PROHIBITED, hooknum);
+		break;
+	case IP6T_ICMP6_NOT_NEIGHBOUR:
+		send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR, hooknum);
+		break;
+	case IP6T_ICMP6_ADDR_UNREACH:
+		send_unreach(*pskb, ICMPV6_ADDR_UNREACH, hooknum);
+		break;
+	case IP6T_ICMP6_PORT_UNREACH:
+		send_unreach(*pskb, ICMPV6_PORT_UNREACH, hooknum);
+		break;
+	case IP6T_ICMP6_ECHOREPLY:
 		/* Do nothing */
 		break;
 	case IP6T_TCP_RESET:
@@ -225,7 +226,7 @@
 		 void *targinfo,
 		 unsigned int hook_mask)
 {
- 	const struct ip6t_reject_info *rejinfo = targinfo;
+	const struct ip6t_reject_info *rejinfo = targinfo;
 	const struct ip6t_entry *e = entry;
 
 	if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
@@ -234,7 +235,7 @@
 	} else if (rejinfo->with == IP6T_TCP_RESET) {
 		/* Must specify that it's a TCP packet */
 		if (e->ipv6.proto != IPPROTO_TCP
-		    || (e->ipv6.invflags & IP6T_INV_PROTO)) {
+		    || (e->ipv6.invflags & XT_INV_PROTO)) {
 			DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
 			return 0;
 		}
@@ -242,8 +243,9 @@
 	return 1;
 }
 
-static struct ip6t_target ip6t_reject_reg = {
+static struct xt_target ip6t_reject_reg = {
 	.name		= "REJECT",
+	.family		= AF_INET6,
 	.target		= reject6_target,
 	.targetsize	= sizeof(struct ip6t_reject_info),
 	.table		= "filter",
@@ -255,12 +257,12 @@
 
 static int __init ip6t_reject_init(void)
 {
-	return ip6t_register_target(&ip6t_reject_reg);
+	return xt_register_target(&ip6t_reject_reg);
 }
 
 static void __exit ip6t_reject_fini(void)
 {
-	ip6t_unregister_target(&ip6t_reject_reg);
+	xt_unregister_target(&ip6t_reject_reg);
 }
 
 module_init(ip6t_reject_init);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index 4648664..d3c1543 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -15,6 +15,7 @@
 #include <net/checksum.h>
 #include <net/ipv6.h>
 
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_ah.h>
 
@@ -77,13 +78,13 @@
 
 	DEBUGP("IPv6 AH spi %02X ",
 	       (spi_match(ahinfo->spis[0], ahinfo->spis[1],
-	                  ntohl(ah->spi),
-	                  !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
+			  ntohl(ah->spi),
+			  !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
 	DEBUGP("len %02X %04X %02X ",
 	       ahinfo->hdrlen, hdrlen,
 	       (!ahinfo->hdrlen ||
-	        (ahinfo->hdrlen == hdrlen) ^
-	        !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
+		(ahinfo->hdrlen == hdrlen) ^
+		!!(ahinfo->invflags & IP6T_AH_INV_LEN)));
 	DEBUGP("res %02X %04X %02X\n",
 	       ahinfo->hdrres, ah->reserved,
 	       !(ahinfo->hdrres && ah->reserved));
@@ -91,12 +92,12 @@
 	return (ah != NULL)
 	       &&
 	       (spi_match(ahinfo->spis[0], ahinfo->spis[1],
-	                  ntohl(ah->spi),
-	                  !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
+			  ntohl(ah->spi),
+			  !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
 	       &&
 	       (!ahinfo->hdrlen ||
-	        (ahinfo->hdrlen == hdrlen) ^
-	        !!(ahinfo->invflags & IP6T_AH_INV_LEN))
+		(ahinfo->hdrlen == hdrlen) ^
+		!!(ahinfo->invflags & IP6T_AH_INV_LEN))
 	       &&
 	       !(ahinfo->hdrres && ah->reserved);
 }
@@ -104,10 +105,10 @@
 /* Called when user tries to insert an entry of this type. */
 static int
 checkentry(const char *tablename,
-          const void *entry,
+	  const void *entry,
 	  const struct xt_match *match,
-          void *matchinfo,
-          unsigned int hook_mask)
+	  void *matchinfo,
+	  unsigned int hook_mask)
 {
 	const struct ip6t_ah *ahinfo = matchinfo;
 
@@ -118,8 +119,9 @@
 	return 1;
 }
 
-static struct ip6t_match ah_match = {
+static struct xt_match ah_match = {
 	.name		= "ah",
+	.family		= AF_INET6,
 	.match		= match,
 	.matchsize	= sizeof(struct ip6t_ah),
 	.checkentry	= checkentry,
@@ -128,12 +130,12 @@
 
 static int __init ip6t_ah_init(void)
 {
-	return ip6t_register_match(&ah_match);
+	return xt_register_match(&ah_match);
 }
 
 static void __exit ip6t_ah_fini(void)
 {
-	ip6t_unregister_match(&ah_match);
+	xt_unregister_match(&ah_match);
 }
 
 module_init(ip6t_ah_init);
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 4f6b84c..967bed7 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -12,6 +12,7 @@
 #include <linux/ipv6.h>
 #include <linux/if_ether.h>
 
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 
 MODULE_DESCRIPTION("IPv6 EUI64 address checking match");
@@ -61,8 +62,9 @@
 	return 0;
 }
 
-static struct ip6t_match eui64_match = {
+static struct xt_match eui64_match = {
 	.name		= "eui64",
+	.family		= AF_INET6,
 	.match		= match,
 	.matchsize	= sizeof(int),
 	.hooks		= (1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) |
@@ -72,12 +74,12 @@
 
 static int __init ip6t_eui64_init(void)
 {
-	return ip6t_register_match(&eui64_match);
+	return xt_register_match(&eui64_match);
 }
 
 static void __exit ip6t_eui64_fini(void)
 {
-	ip6t_unregister_match(&eui64_match);
+	xt_unregister_match(&eui64_match);
 }
 
 module_init(ip6t_eui64_init);
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index cd22eaa..5a5da71 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -14,6 +14,7 @@
 #include <net/checksum.h>
 #include <net/ipv6.h>
 
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_frag.h>
 
@@ -135,8 +136,9 @@
 	return 1;
 }
 
-static struct ip6t_match frag_match = {
+static struct xt_match frag_match = {
 	.name		= "frag",
+	.family		= AF_INET6,
 	.match		= match,
 	.matchsize	= sizeof(struct ip6t_frag),
 	.checkentry	= checkentry,
@@ -145,12 +147,12 @@
 
 static int __init ip6t_frag_init(void)
 {
-	return ip6t_register_match(&frag_match);
+	return xt_register_match(&frag_match);
 }
 
 static void __exit ip6t_frag_fini(void)
 {
-	ip6t_unregister_match(&frag_match);
+	xt_unregister_match(&frag_match);
 }
 
 module_init(ip6t_frag_init);
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 3f25bab..d2373c7 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -16,6 +16,7 @@
 
 #include <asm/byteorder.h>
 
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_opts.h>
 
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index 44a729e..37c8a4d 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -8,11 +8,12 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/ipv6.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 
 #include <linux/netfilter_ipv6/ip6t_hl.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/x_tables.h>
 
 MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
 MODULE_DESCRIPTION("IP tables Hop Limit matching module");
@@ -40,7 +41,7 @@
 			return (ip6h->hop_limit > info->hop_limit);
 			break;
 		default:
-			printk(KERN_WARNING "ip6t_hl: unknown mode %d\n", 
+			printk(KERN_WARNING "ip6t_hl: unknown mode %d\n",
 				info->mode);
 			return 0;
 	}
@@ -48,8 +49,9 @@
 	return 0;
 }
 
-static struct ip6t_match hl_match = {
+static struct xt_match hl_match = {
 	.name		= "hl",
+	.family		= AF_INET6,
 	.match		= match,
 	.matchsize	= sizeof(struct ip6t_hl_info),
 	.me		= THIS_MODULE,
@@ -57,13 +59,12 @@
 
 static int __init ip6t_hl_init(void)
 {
-	return ip6t_register_match(&hl_match);
+	return xt_register_match(&hl_match);
 }
 
 static void __exit ip6t_hl_fini(void)
 {
-	ip6t_unregister_match(&hl_match);
-
+	xt_unregister_match(&hl_match);
 }
 
 module_init(ip6t_hl_init);
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index 3093c39..700a11d 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -1,7 +1,7 @@
 /* ipv6header match - matches IPv6 packets based
    on whether they contain certain headers */
 
-/* Original idea: Brad Chapman 
+/* Original idea: Brad Chapman
  * Rewritten by: Andras Kis-Szabo <kisza@sch.bme.hu> */
 
 /* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu>
@@ -18,6 +18,7 @@
 #include <net/checksum.h>
 #include <net/ipv6.h>
 
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_ipv6header.h>
 
@@ -140,8 +141,9 @@
 	return 1;
 }
 
-static struct ip6t_match ip6t_ipv6header_match = {
+static struct xt_match ip6t_ipv6header_match = {
 	.name		= "ipv6header",
+	.family		= AF_INET6,
 	.match		= &ipv6header_match,
 	.matchsize	= sizeof(struct ip6t_ipv6header_info),
 	.checkentry	= &ipv6header_checkentry,
@@ -151,12 +153,12 @@
 
 static int __init ipv6header_init(void)
 {
-	return ip6t_register_match(&ip6t_ipv6header_match);
+	return xt_register_match(&ip6t_ipv6header_match);
 }
 
 static void __exit ipv6header_exit(void)
 {
-	ip6t_unregister_match(&ip6t_ipv6header_match);
+	xt_unregister_match(&ip6t_ipv6header_match);
 }
 
 module_init(ipv6header_init);
diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c
new file mode 100644
index 0000000..c2a9098
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_mh.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C)2006 USAGI/WIDE Project
+ *
+ * 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.
+ *
+ * Author:
+ *	Masahide NAKAMURA @USAGI <masahide.nakamura.cz@hitachi.com>
+ *
+ * Based on net/netfilter/xt_tcpudp.c
+ *
+ */
+#include <linux/types.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
+#include <net/mip6.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv6/ip6t_mh.h>
+
+MODULE_DESCRIPTION("ip6t_tables match for MH");
+MODULE_LICENSE("GPL");
+
+#ifdef DEBUG_IP_FIREWALL_USER
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+/* Returns 1 if the type is matched by the range, 0 otherwise */
+static inline int
+type_match(u_int8_t min, u_int8_t max, u_int8_t type, int invert)
+{
+	int ret;
+
+	ret = (type >= min && type <= max) ^ invert;
+	return ret;
+}
+
+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 ip6_mh _mh, *mh;
+	const struct ip6t_mh *mhinfo = matchinfo;
+
+	/* Must not be a fragment. */
+	if (offset)
+		return 0;
+
+	mh = skb_header_pointer(skb, protoff, sizeof(_mh), &_mh);
+	if (mh == NULL) {
+		/* We've been asked to examine this packet, and we
+		   can't.  Hence, no choice but to drop. */
+		duprintf("Dropping evil MH tinygram.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	if (mh->ip6mh_proto != IPPROTO_NONE) {
+		duprintf("Dropping invalid MH Payload Proto: %u\n",
+			 mh->ip6mh_proto);
+		*hotdrop = 1;
+		return 0;
+	}
+
+	return type_match(mhinfo->types[0], mhinfo->types[1], mh->ip6mh_type,
+			  !!(mhinfo->invflags & IP6T_MH_INV_TYPE));
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+mh_checkentry(const char *tablename,
+	      const void *entry,
+	      const struct xt_match *match,
+	      void *matchinfo,
+	      unsigned int hook_mask)
+{
+	const struct ip6t_mh *mhinfo = matchinfo;
+
+	/* Must specify no unknown invflags */
+	return !(mhinfo->invflags & ~IP6T_MH_INV_MASK);
+}
+
+static struct xt_match mh_match = {
+	.name		= "mh",
+	.family		= AF_INET6,
+	.checkentry	= mh_checkentry,
+	.match		= match,
+	.matchsize	= sizeof(struct ip6t_mh),
+	.proto		= IPPROTO_MH,
+	.me		= THIS_MODULE,
+};
+
+static int __init ip6t_mh_init(void)
+{
+	return xt_register_match(&mh_match);
+}
+
+static void __exit ip6t_mh_fini(void)
+{
+	xt_unregister_match(&mh_match);
+}
+
+module_init(ip6t_mh_init);
+module_exit(ip6t_mh_fini);
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 4eb9bbc..43738bb 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -16,6 +16,7 @@
 
 #include <linux/netfilter_ipv6/ip6t_owner.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/x_tables.h>
 
 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
 MODULE_DESCRIPTION("IP6 tables owner matching module");
@@ -69,8 +70,9 @@
 	return 1;
 }
 
-static struct ip6t_match owner_match = {
+static struct xt_match owner_match = {
 	.name		= "owner",
+	.family		= AF_INET6,
 	.match		= match,
 	.matchsize	= sizeof(struct ip6t_owner_info),
 	.hooks		= (1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING),
@@ -80,12 +82,12 @@
 
 static int __init ip6t_owner_init(void)
 {
-	return ip6t_register_match(&owner_match);
+	return xt_register_match(&owner_match);
 }
 
 static void __exit ip6t_owner_fini(void)
 {
-	ip6t_unregister_match(&owner_match);
+	xt_unregister_match(&owner_match);
 }
 
 module_init(ip6t_owner_init);
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 54d7d14..81ab00d 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -16,6 +16,7 @@
 
 #include <asm/byteorder.h>
 
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_rt.h>
 
@@ -221,8 +222,9 @@
 	return 1;
 }
 
-static struct ip6t_match rt_match = {
+static struct xt_match rt_match = {
 	.name		= "rt",
+	.family		= AF_INET6,
 	.match		= match,
 	.matchsize	= sizeof(struct ip6t_rt),
 	.checkentry	= checkentry,
@@ -231,12 +233,12 @@
 
 static int __init ip6t_rt_init(void)
 {
-	return ip6t_register_match(&rt_match);
+	return xt_register_match(&rt_match);
 }
 
 static void __exit ip6t_rt_fini(void)
 {
-	ip6t_unregister_match(&rt_match);
+	xt_unregister_match(&rt_match);
 }
 
 module_init(ip6t_rt_init);
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 2fc07c7..112a21d 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -19,25 +19,6 @@
 
 #define FILTER_VALID_HOOKS ((1 << NF_IP6_LOCAL_IN) | (1 << NF_IP6_FORWARD) | (1 << NF_IP6_LOCAL_OUT))
 
-/* Standard entry. */
-struct ip6t_standard
-{
-	struct ip6t_entry entry;
-	struct ip6t_standard_target target;
-};
-
-struct ip6t_error_target
-{
-	struct ip6t_entry_target target;
-	char errorname[IP6T_FUNCTION_MAXNAMELEN];
-};
-
-struct ip6t_error
-{
-	struct ip6t_entry entry;
-	struct ip6t_error_target target;
-};
-
 static struct
 {
 	struct ip6t_replace repl;
@@ -92,7 +73,7 @@
     }
 };
 
-static struct ip6t_table packet_filter = {
+static struct xt_table packet_filter = {
 	.name		= "filter",
 	.valid_hooks	= FILTER_VALID_HOOKS,
 	.lock		= RW_LOCK_UNLOCKED,
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 6250e86..0c468d3 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -29,25 +29,6 @@
 #define DEBUGP(x, args...)
 #endif
 
-/* Standard entry. */
-struct ip6t_standard
-{
-	struct ip6t_entry entry;
-	struct ip6t_standard_target target;
-};
-
-struct ip6t_error_target
-{
-	struct ip6t_entry_target target;
-	char errorname[IP6T_FUNCTION_MAXNAMELEN];
-};
-
-struct ip6t_error
-{
-	struct ip6t_entry entry;
-	struct ip6t_error_target target;
-};
-
 static struct
 {
 	struct ip6t_replace repl;
@@ -69,7 +50,7 @@
       0, NULL, { } },
     {
 	    /* PRE_ROUTING */
-            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
+	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
 		0,
 		sizeof(struct ip6t_entry),
 		sizeof(struct ip6t_standard),
@@ -77,7 +58,7 @@
 	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
 		-NF_ACCEPT - 1 } },
 	    /* LOCAL_IN */
-            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
+	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
 		0,
 		sizeof(struct ip6t_entry),
 		sizeof(struct ip6t_standard),
@@ -85,7 +66,7 @@
 	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
 		-NF_ACCEPT - 1 } },
 	    /* FORWARD */
-            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
+	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
 		0,
 		sizeof(struct ip6t_entry),
 		sizeof(struct ip6t_standard),
@@ -93,7 +74,7 @@
 	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
 		-NF_ACCEPT - 1 } },
 	    /* LOCAL_OUT */
-            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
+	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
 		0,
 		sizeof(struct ip6t_entry),
 		sizeof(struct ip6t_standard),
@@ -122,7 +103,7 @@
     }
 };
 
-static struct ip6t_table packet_mangler = {
+static struct xt_table packet_mangler = {
 	.name		= "mangle",
 	.valid_hooks	= MANGLE_VALID_HOOKS,
 	.lock		= RW_LOCK_UNLOCKED,
@@ -175,7 +156,7 @@
 
 	ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler);
 
-	if (ret != NF_DROP && ret != NF_STOLEN 
+	if (ret != NF_DROP && ret != NF_STOLEN
 		&& (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr))
 		    || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr))
 		    || (*pskb)->mark != mark
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index b4154da..a3eb5b8 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -14,25 +14,6 @@
 #define DEBUGP(x, args...)
 #endif
 
-/* Standard entry. */
-struct ip6t_standard
-{
-	struct ip6t_entry entry;
-	struct ip6t_standard_target target;
-};
-
-struct ip6t_error_target
-{
-	struct ip6t_entry_target target;
-	char errorname[IP6T_FUNCTION_MAXNAMELEN];
-};
-
-struct ip6t_error
-{
-	struct ip6t_entry entry;
-	struct ip6t_error_target target;
-};
-
 static struct
 {
 	struct ip6t_replace repl;
@@ -106,10 +87,10 @@
 	}
 };
 
-static struct xt_table packet_raw = { 
-	.name = "raw", 
-	.valid_hooks = RAW_VALID_HOOKS, 
-	.lock = RW_LOCK_UNLOCKED, 
+static struct xt_table packet_raw = {
+	.name = "raw",
+	.valid_hooks = RAW_VALID_HOOKS,
+	.lock = RW_LOCK_UNLOCKED,
 	.me = THIS_MODULE,
 	.af = AF_INET6,
 };
@@ -125,17 +106,17 @@
 	return ip6t_do_table(pskb, hook, in, out, &packet_raw);
 }
 
-static struct nf_hook_ops ip6t_ops[] = { 
+static struct nf_hook_ops ip6t_ops[] = {
 	{
-	  .hook = ip6t_hook, 
+	  .hook = ip6t_hook,
 	  .pf = PF_INET6,
 	  .hooknum = NF_IP6_PRE_ROUTING,
 	  .priority = NF_IP6_PRI_FIRST,
 	  .owner = THIS_MODULE,
 	},
 	{
-	  .hook = ip6t_hook, 
-	  .pf = PF_INET6, 
+	  .hook = ip6t_hook,
+	  .pf = PF_INET6,
 	  .hooknum = NF_IP6_LOCAL_OUT,
 	  .priority = NF_IP6_PRI_FIRST,
 	  .owner = THIS_MODULE,
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index a20615f..4b7be4b 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -154,8 +154,8 @@
 	 */
 	if ((protoff < 0) || (protoff > (*pskb)->len)) {
 		DEBUGP("ip6_conntrack_core: can't find proto in pkt\n");
-		NF_CT_STAT_INC(error);
-		NF_CT_STAT_INC(invalid);
+		NF_CT_STAT_INC_ATOMIC(error);
+		NF_CT_STAT_INC_ATOMIC(invalid);
 		return -NF_ACCEPT;
 	}
 
@@ -349,7 +349,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
-        { .ctl_name = 0 }
+	{ .ctl_name = 0 }
 };
 #endif
 
@@ -386,7 +386,7 @@
 	if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
 		return -EINVAL;
 
-	memcpy(&t->src.u3.ip6, NFA_DATA(tb[CTA_IP_V6_SRC-1]), 
+	memcpy(&t->src.u3.ip6, NFA_DATA(tb[CTA_IP_V6_SRC-1]),
 	       sizeof(u_int32_t) * 4);
 	memcpy(&t->dst.u3.ip6, NFA_DATA(tb[CTA_IP_V6_DST-1]),
 	       sizeof(u_int32_t) * 4);
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 3905cac..21f19cc 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -17,7 +17,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/module.h>
 #include <linux/netfilter.h>
@@ -104,9 +103,9 @@
 		       unsigned int hooknum)
 {
 	/* Try to delete connection immediately after all replies:
-           won't actually vanish as we still have skb, and del_timer
-           means this will only run once even if count hits zero twice
-           (theoretically possible with SMP) */
+	   won't actually vanish as we still have skb, and del_timer
+	   means this will only run once even if count hits zero twice
+	   (theoretically possible with SMP) */
 	if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) {
 		if (atomic_dec_and_test(&ct->proto.icmp.count)
 		    && del_timer(&ct->timeout))
@@ -182,6 +181,7 @@
 		return -NF_ACCEPT;
 	}
 
+	/* rcu_read_lock()ed by nf_hook_slow */
 	inproto = __nf_ct_l4proto_find(PF_INET6, inprotonum);
 
 	/* Are they talking about one of our connections? */
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index d9c1540..15ab1e3 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -311,7 +311,7 @@
 	write_lock(&nf_ct_frag6_lock);
 #ifdef CONFIG_SMP
 	hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
-		if (fq->id == fq_in->id && 
+		if (fq->id == fq_in->id &&
 		    ipv6_addr_equal(&fq_in->saddr, &fq->saddr) &&
 		    ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) {
 			atomic_inc(&fq->refcnt);
@@ -374,7 +374,7 @@
 
 	read_lock(&nf_ct_frag6_lock);
 	hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
-		if (fq->id == id && 
+		if (fq->id == id &&
 		    ipv6_addr_equal(src, &fq->saddr) &&
 		    ipv6_addr_equal(dst, &fq->daddr)) {
 			atomic_inc(&fq->refcnt);
@@ -388,7 +388,7 @@
 }
 
 
-static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, 
+static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
 			     struct frag_hdr *fhdr, int nhoff)
 {
 	struct sk_buff *prev, *next;
@@ -405,12 +405,12 @@
 
 	if ((unsigned int)end > IPV6_MAXPLEN) {
 		DEBUGP("offset is too large.\n");
- 		return -1;
+		return -1;
 	}
 
- 	if (skb->ip_summed == CHECKSUM_COMPLETE)
- 		skb->csum = csum_sub(skb->csum,
- 				     csum_partial(skb->nh.raw,
+	if (skb->ip_summed == CHECKSUM_COMPLETE)
+		skb->csum = csum_sub(skb->csum,
+				     csum_partial(skb->nh.raw,
 						  (u8*)(fhdr + 1) - skb->nh.raw,
 						  0));
 
@@ -625,7 +625,7 @@
 	/* We have to remove fragment header from datagram and to relocate
 	 * header in order to calculate ICV correctly. */
 	head->nh.raw[fq->nhoffset] = head->h.raw[0];
-	memmove(head->head + sizeof(struct frag_hdr), head->head, 
+	memmove(head->head + sizeof(struct frag_hdr), head->head,
 		(head->data - head->head) - sizeof(struct frag_hdr));
 	head->mac.raw += sizeof(struct frag_hdr);
 	head->nh.raw += sizeof(struct frag_hdr);
@@ -701,41 +701,41 @@
 static int
 find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff)
 {
-        u8 nexthdr = skb->nh.ipv6h->nexthdr;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
 	u8 prev_nhoff = (u8 *)&skb->nh.ipv6h->nexthdr - skb->data;
 	int start = (u8 *)(skb->nh.ipv6h+1) - skb->data;
 	int len = skb->len - start;
 	u8 prevhdr = NEXTHDR_IPV6;
 
-        while (nexthdr != NEXTHDR_FRAGMENT) {
-                struct ipv6_opt_hdr hdr;
-                int hdrlen;
+	while (nexthdr != NEXTHDR_FRAGMENT) {
+		struct ipv6_opt_hdr hdr;
+		int hdrlen;
 
 		if (!ipv6_ext_hdr(nexthdr)) {
 			return -1;
 		}
-                if (len < (int)sizeof(struct ipv6_opt_hdr)) {
+		if (len < (int)sizeof(struct ipv6_opt_hdr)) {
 			DEBUGP("too short\n");
 			return -1;
 		}
-                if (nexthdr == NEXTHDR_NONE) {
+		if (nexthdr == NEXTHDR_NONE) {
 			DEBUGP("next header is none\n");
 			return -1;
 		}
-                if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
-                        BUG();
-                if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hdr.hdrlen+2)<<2;
-                else
-                        hdrlen = ipv6_optlen(&hdr);
+		if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
+			BUG();
+		if (nexthdr == NEXTHDR_AUTH)
+			hdrlen = (hdr.hdrlen+2)<<2;
+		else
+			hdrlen = ipv6_optlen(&hdr);
 
 		prevhdr = nexthdr;
 		prev_nhoff = start;
 
-                nexthdr = hdr.nexthdr;
-                len -= hdrlen;
-                start += hdrlen;
-        }
+		nexthdr = hdr.nexthdr;
+		len -= hdrlen;
+		start += hdrlen;
+	}
 
 	if (len < 0)
 		return -1;
@@ -749,7 +749,7 @@
 
 struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
 {
-	struct sk_buff *clone; 
+	struct sk_buff *clone;
 	struct net_device *dev = skb->dev;
 	struct frag_hdr *fhdr;
 	struct nf_ct_frag6_queue *fq;
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 35249d8..fa3fb50 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -17,7 +17,6 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  */
-#include <linux/sched.h>
 #include <linux/socket.h>
 #include <linux/net.h>
 #include <linux/ipv6.h>
@@ -50,7 +49,7 @@
 	seq_printf(seq, "UDP6: inuse %d\n",
 		       fold_prot_inuse(&udpv6_prot));
 	seq_printf(seq, "UDPLITE6: inuse %d\n",
-		        fold_prot_inuse(&udplitev6_prot));
+			fold_prot_inuse(&udplitev6_prot));
 	seq_printf(seq, "RAW6: inuse %d\n",
 		       fold_prot_inuse(&rawv6_prot));
 	seq_printf(seq, "FRAG6: inuse %d memory %d\n",
@@ -89,7 +88,7 @@
 /* icmpv6 mib according to RFC 2466
 
    Exceptions:  {In|Out}AdminProhibs are removed, because I see
-                no good reasons to account them separately
+		no good reasons to account them separately
 		of another dest.unreachs.
 		OutErrs is zero identically.
 		OutEchos too.
@@ -146,14 +145,14 @@
 static unsigned long
 fold_field(void *mib[], int offt)
 {
-        unsigned long res = 0;
-        int 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);
-        }
-        return res;
+	unsigned long res = 0;
+	int 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);
+	}
+	return res;
 }
 
 static inline void
@@ -161,7 +160,7 @@
 {
 	int i;
 	for (i=0; itemlist[i].name; i++)
-		seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, 
+		seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name,
 				fold_field(mib, itemlist[i].entry));
 }
 
@@ -187,7 +186,7 @@
 	return single_open(file, sockstat6_seq_show, NULL);
 }
 
-static struct file_operations sockstat6_seq_fops = {
+static const struct file_operations sockstat6_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = sockstat6_seq_open,
 	.read	 = seq_read,
@@ -200,7 +199,7 @@
 	return single_open(file, snmp6_seq_show, PDE(inode)->data);
 }
 
-static struct file_operations snmp6_seq_fops = {
+static const struct file_operations snmp6_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = snmp6_seq_open,
 	.read	 = seq_read,
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c
index 52c1d58..ef43bd5 100644
--- a/net/ipv6/protocol.c
+++ b/net/ipv6/protocol.c
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -64,7 +63,7 @@
 /*
  *	Remove a protocol from the hash tables.
  */
- 
+
 int inet6_del_protocol(struct inet6_protocol *prot, unsigned char protocol)
 {
 	int ret, hash = protocol & (MAX_INET_PROTOS - 1);
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 4ae1b19a..306d5d8 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1,9 +1,9 @@
 /*
  *	RAW sockets for IPv6
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	Adapted from linux/net/ipv4/raw.c
  *
@@ -11,7 +11,7 @@
  *
  *	Fixes:
  *	Hideaki YOSHIFUJI	:	sin6_scope_id support
- *	YOSHIFUJI,H.@USAGI	:	raw checksum (RFC2292(bis) compliance) 
+ *	YOSHIFUJI,H.@USAGI	:	raw checksum (RFC2292(bis) compliance)
  *	Kazunori MIYAZAWA @USAGI:	change process style to use ip6_append_data
  *
  *	This program is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -71,12 +70,12 @@
 	write_lock_bh(&raw_v6_lock);
 	sk_add_node(sk, list);
 	sock_prot_inc_use(sk->sk_prot);
- 	write_unlock_bh(&raw_v6_lock);
+	write_unlock_bh(&raw_v6_lock);
 }
 
 static void raw_v6_unhash(struct sock *sk)
 {
- 	write_lock_bh(&raw_v6_lock);
+	write_lock_bh(&raw_v6_lock);
 	if (sk_del_node_init(sk))
 		sock_prot_dec_use(sk->sk_prot);
 	write_unlock_bh(&raw_v6_lock);
@@ -250,7 +249,7 @@
 				 */
 				sk->sk_bound_dev_if = addr->sin6_scope_id;
 			}
-			
+
 			/* Binding to link-local address requires an interface */
 			if (!sk->sk_bound_dev_if)
 				goto out;
@@ -261,7 +260,7 @@
 				goto out;
 			}
 		}
-		
+
 		/* ipv4 addr of the socket is invalid.  Only the
 		 * unspecified and mapped address have a v4 equivalent.
 		 */
@@ -324,7 +323,7 @@
 
 static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
 {
-	if ((raw6_sk(sk)->checksum || sk->sk_filter) && 
+	if ((raw6_sk(sk)->checksum || sk->sk_filter) &&
 	    skb_checksum_complete(skb)) {
 		/* FIXME: increment a raw6 drops counter here */
 		kfree_skb(skb);
@@ -342,10 +341,10 @@
 }
 
 /*
- *	This is next to useless... 
+ *	This is next to useless...
  *	if we demultiplex in network layer we don't need the extra call
- *	just to queue the skb... 
- *	maybe we could have the network decide upon a hint if it 
+ *	just to queue the skb...
+ *	maybe we could have the network decide upon a hint if it
  *	should call raw_rcv for demultiplexing
  */
 int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
@@ -353,17 +352,17 @@
 	struct inet_sock *inet = inet_sk(sk);
 	struct raw6_sock *rp = raw6_sk(sk);
 
-        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
-                kfree_skb(skb);
-                return NET_RX_DROP;
-        }
+	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
+		kfree_skb(skb);
+		return NET_RX_DROP;
+	}
 
 	if (!rp->checksum)
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 	if (skb->ip_summed == CHECKSUM_COMPLETE) {
 		skb_postpull_rcsum(skb, skb->nh.raw,
-		                   skb->h.raw - skb->nh.raw);
+				   skb->h.raw - skb->nh.raw);
 		if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr,
 				     &skb->nh.ipv6h->daddr,
 				     skb->len, inet->num, skb->csum))
@@ -404,8 +403,8 @@
 
 	if (flags & MSG_OOB)
 		return -EOPNOTSUPP;
-		
-	if (addr_len) 
+
+	if (addr_len)
 		*addr_len=sizeof(*sin6);
 
 	if (flags & MSG_ERRQUEUE)
@@ -416,10 +415,10 @@
 		goto out;
 
 	copied = skb->len;
-  	if (copied > len) {
-  		copied = len;
-  		msg->msg_flags |= MSG_TRUNC;
-  	}
+	if (copied > len) {
+		copied = len;
+		msg->msg_flags |= MSG_TRUNC;
+	}
 
 	if (skb->ip_summed==CHECKSUM_UNNECESSARY) {
 		err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
@@ -549,7 +548,7 @@
 }
 
 static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
-			struct flowi *fl, struct rt6_info *rt, 
+			struct flowi *fl, struct rt6_info *rt,
 			unsigned int flags)
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
@@ -570,7 +569,7 @@
 	skb = sock_alloc_send_skb(sk, length+hh_len+15,
 				  flags&MSG_DONTWAIT, &err);
 	if (skb == NULL)
-		goto error; 
+		goto error;
 	skb_reserve(skb, hh_len);
 
 	skb->priority = sk->sk_priority;
@@ -600,7 +599,7 @@
 	kfree_skb(skb);
 error:
 	IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
-	return err; 
+	return err;
 }
 
 static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
@@ -694,19 +693,19 @@
 		return -EMSGSIZE;
 
 	/* Mirror BSD error message compatibility */
-	if (msg->msg_flags & MSG_OOB)		
+	if (msg->msg_flags & MSG_OOB)
 		return -EOPNOTSUPP;
 
 	/*
-	 *	Get and verify the address. 
+	 *	Get and verify the address.
 	 */
 	memset(&fl, 0, sizeof(fl));
 
 	if (sin6) {
-		if (addr_len < SIN6_LEN_RFC2133) 
+		if (addr_len < SIN6_LEN_RFC2133)
 			return -EINVAL;
 
-		if (sin6->sin6_family && sin6->sin6_family != AF_INET6) 
+		if (sin6->sin6_family && sin6->sin6_family != AF_INET6)
 			return(-EAFNOSUPPORT);
 
 		/* port is the proto value [0..255] carried in nexthdr */
@@ -744,17 +743,17 @@
 		    ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)
 			fl.oif = sin6->sin6_scope_id;
 	} else {
-		if (sk->sk_state != TCP_ESTABLISHED) 
+		if (sk->sk_state != TCP_ESTABLISHED)
 			return -EDESTADDRREQ;
-		
+
 		proto = inet->num;
 		daddr = &np->daddr;
 		fl.fl6_flowlabel = np->flow_label;
 	}
 
 	if (ipv6_addr_any(daddr)) {
-		/* 
-		 * unspecified destination address 
+		/*
+		 * unspecified destination address
 		 * treated as error... is this correct ?
 		 */
 		fl6_sock_release(flowlabel);
@@ -792,7 +791,7 @@
 	err = rawv6_probe_proto_opt(&fl, msg);
 	if (err)
 		goto out;
- 
+
 	ipv6_addr_copy(&fl.fl6_dst, daddr);
 	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
@@ -815,7 +814,7 @@
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+	if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
 		goto out;
 
 	if (hlimit < 0) {
@@ -856,7 +855,7 @@
 	dst_release(dst);
 	if (!inet->hdrincl)
 		release_sock(sk);
-out:	
+out:
 	fl6_sock_release(flowlabel);
 	return err<0?err:len;
 do_confirm:
@@ -867,7 +866,7 @@
 	goto done;
 }
 
-static int rawv6_seticmpfilter(struct sock *sk, int level, int optname, 
+static int rawv6_seticmpfilter(struct sock *sk, int level, int optname,
 			       char __user *optval, int optlen)
 {
 	switch (optname) {
@@ -884,7 +883,7 @@
 	return 0;
 }
 
-static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, 
+static int rawv6_geticmpfilter(struct sock *sk, int level, int optname,
 			       char __user *optval, int __user *optlen)
 {
 	int len;
@@ -916,7 +915,7 @@
 	struct raw6_sock *rp = raw6_sk(sk);
 	int val;
 
-  	if (get_user(val, (int __user *)optval))
+	if (get_user(val, (int __user *)optval))
 		return -EFAULT;
 
 	switch (optname) {
@@ -1094,10 +1093,19 @@
 
 static int rawv6_init_sk(struct sock *sk)
 {
-	if (inet_sk(sk)->num == IPPROTO_ICMPV6) {
-		struct raw6_sock *rp = raw6_sk(sk);
+	struct raw6_sock *rp = raw6_sk(sk);
+
+	switch (inet_sk(sk)->num) {
+	case IPPROTO_ICMPV6:
 		rp->checksum = 1;
 		rp->offset   = 2;
+		break;
+	case IPPROTO_MH:
+		rp->checksum = 1;
+		rp->offset   = 4;
+		break;
+	default:
+		break;
 	}
 	return(0);
 }
@@ -1215,7 +1223,7 @@
 		   src->s6_addr32[2], src->s6_addr32[3], srcp,
 		   dest->s6_addr32[0], dest->s6_addr32[1],
 		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
-		   sp->sk_state, 
+		   sp->sk_state,
 		   atomic_read(&sp->sk_wmem_alloc),
 		   atomic_read(&sp->sk_rmem_alloc),
 		   0, 0L, 0,
@@ -1264,7 +1272,7 @@
 	goto out;
 }
 
-static struct file_operations raw6_seq_fops = {
+static const struct file_operations raw6_seq_fops = {
 	.owner =	THIS_MODULE,
 	.open =		raw6_seq_open,
 	.read =		seq_read,
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 6f9a904..7034c54 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -1,9 +1,9 @@
 /*
  *	IPv6 fragment reassembly
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	$Id: reassembly.c,v 1.26 2001/03/07 22:00:57 davem Exp $
  *
@@ -15,8 +15,8 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-/* 
- *	Fixes:	
+/*
+ *	Fixes:
  *	Andi Kleen	Make it work with multiple hosts.
  *			More RFC compliance.
  *
@@ -343,7 +343,7 @@
 	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 && 
+		if (fq->id == fq_in->id &&
 		    ipv6_addr_equal(&fq_in->saddr, &fq->saddr) &&
 		    ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) {
 			atomic_inc(&fq->refcnt);
@@ -406,7 +406,7 @@
 	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 && 
+		if (fq->id == id &&
 		    ipv6_addr_equal(src, &fq->saddr) &&
 		    ipv6_addr_equal(dst, &fq->daddr)) {
 			atomic_inc(&fq->refcnt);
@@ -420,7 +420,7 @@
 }
 
 
-static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, 
+static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
 			   struct frag_hdr *fhdr, int nhoff)
 {
 	struct sk_buff *prev, *next;
@@ -436,13 +436,13 @@
 	if ((unsigned int)end > IPV6_MAXPLEN) {
 		IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
 				 IPSTATS_MIB_INHDRERRORS);
- 		icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw);
- 		return;
+		icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw);
+		return;
 	}
 
- 	if (skb->ip_summed == CHECKSUM_COMPLETE)
- 		skb->csum = csum_sub(skb->csum,
- 				     csum_partial(skb->nh.raw, (u8*)(fhdr+1)-skb->nh.raw, 0));
+	if (skb->ip_summed == CHECKSUM_COMPLETE)
+		skb->csum = csum_sub(skb->csum,
+				     csum_partial(skb->nh.raw, (u8*)(fhdr+1)-skb->nh.raw, 0));
 
 	/* Is this the final fragment? */
 	if (!(fhdr->frag_off & htons(IP6_MF))) {
@@ -464,7 +464,7 @@
 			 */
 			IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
 					 IPSTATS_MIB_INHDRERRORS);
-			icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 
+			icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
 					  offsetof(struct ipv6hdr, payload_len));
 			return;
 		}
@@ -482,7 +482,7 @@
 	/* Point into the IP datagram 'data' part. */
 	if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data))
 		goto err;
-	
+
 	if (pskb_trim_rcsum(skb, end - offset))
 		goto err;
 
@@ -640,7 +640,7 @@
 	 * header in order to calculate ICV correctly. */
 	nhoff = fq->nhoffset;
 	head->nh.raw[nhoff] = head->h.raw[0];
-	memmove(head->head + sizeof(struct frag_hdr), head->head, 
+	memmove(head->head + sizeof(struct frag_hdr), head->head,
 		(head->data - head->head) - sizeof(struct frag_hdr));
 	head->mac.raw += sizeof(struct frag_hdr);
 	head->nh.raw += sizeof(struct frag_hdr);
@@ -695,7 +695,7 @@
 
 static int ipv6_frag_rcv(struct sk_buff **skbp)
 {
-	struct sk_buff *skb = *skbp; 
+	struct sk_buff *skb = *skbp;
 	struct net_device *dev = skb->dev;
 	struct frag_hdr *fhdr;
 	struct frag_queue *fq;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 5f0043c..0e1f4b2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -3,7 +3,7 @@
  *	FIB front-end.
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	$Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $
  *
@@ -201,7 +201,7 @@
 	if (idev != NULL) {
 		rt->rt6i_idev = NULL;
 		in6_dev_put(idev);
-	}	
+	}
 }
 
 static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
@@ -243,7 +243,7 @@
 	struct rt6_info *sprt;
 
 	if (oif) {
-		for (sprt = rt; sprt; sprt = sprt->u.next) {
+		for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
 			struct net_device *dev = sprt->rt6i_dev;
 			if (dev->ifindex == oif)
 				return sprt;
@@ -252,7 +252,7 @@
 				    sprt->rt6i_idev->dev->ifindex != oif) {
 					if (strict && oif)
 						continue;
-					if (local && (!oif || 
+					if (local && (!oif ||
 						      local->rt6i_idev->dev->ifindex == oif))
 						continue;
 				}
@@ -311,12 +311,21 @@
 static int inline rt6_check_dev(struct rt6_info *rt, int oif)
 {
 	struct net_device *dev = rt->rt6i_dev;
-	if (!oif || dev->ifindex == oif)
+	int ret = 0;
+
+	if (!oif)
 		return 2;
-	if ((dev->flags & IFF_LOOPBACK) &&
-	    rt->rt6i_idev && rt->rt6i_idev->dev->ifindex == oif)
-		return 1;
-	return 0;
+	if (dev->flags & IFF_LOOPBACK) {
+		if (!WARN_ON(rt->rt6i_idev == NULL) &&
+		    rt->rt6i_idev->dev->ifindex == oif)
+			ret = 1;
+		else
+			return 0;
+	}
+	if (dev->ifindex == oif)
+		return 2;
+
+	return ret;
 }
 
 static int inline rt6_check_neigh(struct rt6_info *rt)
@@ -341,7 +350,7 @@
 			   int strict)
 {
 	int m, n;
-		
+
 	m = rt6_check_dev(rt, oif);
 	if (!m && (strict & RT6_LOOKUP_F_IFACE))
 		return -1;
@@ -367,7 +376,7 @@
 
 	for (rt = rt0, metric = rt0->rt6i_metric;
 	     rt && rt->rt6i_metric == metric && (!last || rt != rt0);
-	     rt = rt->u.next) {
+	     rt = rt->u.dst.rt6_next) {
 		int m;
 
 		if (rt6_check_expired(rt))
@@ -395,9 +404,9 @@
 		/* no entries matched; do round-robin */
 		static DEFINE_SPINLOCK(lock);
 		spin_lock(&lock);
-		*head = rt0->u.next;
-		rt0->u.next = last->u.next;
-		last->u.next = rt0;
+		*head = rt0->u.dst.rt6_next;
+		rt0->u.dst.rt6_next = last->u.dst.rt6_next;
+		last->u.dst.rt6_next = rt0;
 		spin_unlock(&lock);
 	}
 
@@ -714,7 +723,7 @@
 				.flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK,
 			},
 		},
- 		.mark = skb->mark,
+		.mark = skb->mark,
 		.proto = iph->nexthdr,
 	};
 
@@ -879,9 +888,9 @@
 		mtu = ip6_rt_min_advmss;
 
 	/*
-	 * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and 
-	 * corresponding MSS is IPV6_MAXPLEN - tcp_header_size. 
-	 * IPV6_MAXPLEN is also valid and means: "any MSS, 
+	 * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and
+	 * corresponding MSS is IPV6_MAXPLEN - tcp_header_size.
+	 * IPV6_MAXPLEN is also valid and means: "any MSS,
 	 * rely only on pmtu discovery"
 	 */
 	if (mtu > IPV6_MAXPLEN - sizeof(struct tcphdr))
@@ -892,7 +901,7 @@
 static struct dst_entry *ndisc_dst_gc_list;
 static DEFINE_SPINLOCK(ndisc_lock);
 
-struct dst_entry *ndisc_dst_alloc(struct net_device *dev, 
+struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
 				  struct neighbour *neigh,
 				  struct in6_addr *addr,
 				  int (*output)(struct sk_buff *))
@@ -925,8 +934,8 @@
 	rt->u.dst.output  = output;
 
 #if 0	/* there's no chance to use these for ndisc */
-	rt->u.dst.flags   = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST 
-				? DST_HOST 
+	rt->u.dst.flags   = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST
+				? DST_HOST
 				: 0;
 	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
 	rt->rt6i_dst.plen = 128;
@@ -949,7 +958,7 @@
 	int freed;
 
 	next = NULL;
- 	freed = 0;
+	freed = 0;
 
 	spin_lock_bh(&ndisc_lock);
 	pprev = &ndisc_dst_gc_list;
@@ -1267,9 +1276,9 @@
 	fn = fib6_locate(&table->tb6_root,
 			 &cfg->fc_dst, cfg->fc_dst_len,
 			 &cfg->fc_src, cfg->fc_src_len);
-	
+
 	if (fn) {
-		for (rt = fn->leaf; rt; rt = rt->u.next) {
+		for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) {
 			if (cfg->fc_ifindex &&
 			    (rt->rt6i_dev == NULL ||
 			     rt->rt6i_dev->ifindex != cfg->fc_ifindex))
@@ -1320,7 +1329,7 @@
 	read_lock_bh(&table->tb6_lock);
 	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
 restart:
-	for (rt = fn->leaf; rt; rt = rt->u.next) {
+	for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) {
 		/*
 		 * Current route is on-link; redirect is always invalid.
 		 *
@@ -1396,7 +1405,7 @@
 	 *	We have finally decided to accept it.
 	 */
 
-	neigh_update(neigh, lladdr, NUD_STALE, 
+	neigh_update(neigh, lladdr, NUD_STALE,
 		     NEIGH_UPDATE_F_WEAK_OVERRIDE|
 		     NEIGH_UPDATE_F_OVERRIDE|
 		     (on_link ? 0 : (NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
@@ -1445,7 +1454,7 @@
 	}
 
 out:
-        dst_release(&rt->u.dst);
+	dst_release(&rt->u.dst);
 	return;
 }
 
@@ -1469,7 +1478,7 @@
 
 	if (pmtu < IPV6_MIN_MTU) {
 		/*
-		 * According to RFC2460, PMTU is set to the IPv6 Minimum Link 
+		 * According to RFC2460, PMTU is set to the IPv6 Minimum Link
 		 * MTU (1280) and a fragment header should always be included
 		 * after a node receiving Too Big message reporting PMTU is
 		 * less than the IPv6 Minimum Link MTU.
@@ -1581,7 +1590,7 @@
 	if (!fn)
 		goto out;
 
-	for (rt = fn->leaf; rt; rt = rt->u.next) {
+	for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) {
 		if (rt->rt6i_dev->ifindex != ifindex)
 			continue;
 		if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))
@@ -1623,7 +1632,7 @@
 #endif
 
 struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev)
-{	
+{
 	struct rt6_info *rt;
 	struct fib6_table *table;
 
@@ -1632,7 +1641,7 @@
 		return NULL;
 
 	write_lock_bh(&table->tb6_lock);
-	for (rt = table->tb6_root.leaf; rt; rt=rt->u.next) {
+	for (rt = table->tb6_root.leaf; rt; rt=rt->u.dst.rt6_next) {
 		if (dev == rt->rt6i_dev &&
 		    ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
 		    ipv6_addr_equal(&rt->rt6i_gateway, addr))
@@ -1675,7 +1684,7 @@
 
 restart:
 	read_lock_bh(&table->tb6_lock);
-	for (rt = table->tb6_root.leaf; rt; rt = rt->u.next) {
+	for (rt = table->tb6_root.leaf; rt; rt = rt->u.dst.rt6_next) {
 		if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
 			dst_hold(&rt->u.dst);
 			read_unlock_bh(&table->tb6_lock);
@@ -1887,8 +1896,8 @@
 	 */
 	if (rt->rt6i_dev == arg->dev &&
 	    !dst_metric_locked(&rt->u.dst, RTAX_MTU) &&
-            (dst_mtu(&rt->u.dst) > arg->mtu ||
-             (dst_mtu(&rt->u.dst) < arg->mtu &&
+	    (dst_mtu(&rt->u.dst) > arg->mtu ||
+	     (dst_mtu(&rt->u.dst) < arg->mtu &&
 	      dst_mtu(&rt->u.dst) == idev->cnf.mtu6)))
 		rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu;
 	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu);
@@ -2040,7 +2049,7 @@
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	rtm = nlmsg_data(nlh);
 	rtm->rtm_family = AF_INET6;
@@ -2074,13 +2083,13 @@
 
 	if (dst) {
 		NLA_PUT(skb, RTA_DST, 16, dst);
-	        rtm->rtm_dst_len = 128;
+		rtm->rtm_dst_len = 128;
 	} else if (rtm->rtm_dst_len)
 		NLA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr);
 #ifdef CONFIG_IPV6_SUBTREES
 	if (src) {
 		NLA_PUT(skb, RTA_SRC, 16, src);
-	        rtm->rtm_src_len = 128;
+		rtm->rtm_src_len = 128;
 	} else if (rtm->rtm_src_len)
 		NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr);
 #endif
@@ -2111,7 +2120,8 @@
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 int rt6_dump_route(struct rt6_info *rt, void *p_arg)
@@ -2222,9 +2232,12 @@
 		goto errout;
 
 	err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
-	/* failure implies BUG in rt6_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
 errout:
 	if (err < 0)
@@ -2286,7 +2299,7 @@
 	arg->len += sprintf(arg->buffer + arg->len,
 			    " %08x %08x %08x %08x %8s\n",
 			    rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt),
-			    rt->u.dst.__use, rt->rt6i_flags, 
+			    rt->u.dst.__use, rt->rt6i_flags,
 			    rt->rt6i_dev ? rt->rt6i_dev->name : "");
 	return 0;
 }
@@ -2332,7 +2345,7 @@
 	return single_open(file, rt6_stats_seq_show, NULL);
 }
 
-static struct file_operations rt6_stats_seq_fops = {
+static const struct file_operations rt6_stats_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = rt6_stats_seq_open,
 	.read	 = seq_read,
@@ -2358,91 +2371,91 @@
 }
 
 ctl_table ipv6_route_table[] = {
-        {
-		.ctl_name	=	NET_IPV6_ROUTE_FLUSH, 
+	{
+		.ctl_name	=	NET_IPV6_ROUTE_FLUSH,
 		.procname	=	"flush",
-         	.data		=	&flush_delay,
+		.data		=	&flush_delay,
 		.maxlen		=	sizeof(int),
 		.mode		=	0200,
-         	.proc_handler	=	&ipv6_sysctl_rtcache_flush
+		.proc_handler	=	&ipv6_sysctl_rtcache_flush
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_THRESH,
 		.procname	=	"gc_thresh",
-         	.data		=	&ip6_dst_ops.gc_thresh,
+		.data		=	&ip6_dst_ops.gc_thresh,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-         	.proc_handler	=	&proc_dointvec,
+		.proc_handler	=	&proc_dointvec,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_MAX_SIZE,
 		.procname	=	"max_size",
-         	.data		=	&ip6_rt_max_size,
+		.data		=	&ip6_rt_max_size,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-         	.proc_handler	=	&proc_dointvec,
+		.proc_handler	=	&proc_dointvec,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_MIN_INTERVAL,
 		.procname	=	"gc_min_interval",
-         	.data		=	&ip6_rt_gc_min_interval,
+		.data		=	&ip6_rt_gc_min_interval,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-         	.proc_handler	=	&proc_dointvec_jiffies,
+		.proc_handler	=	&proc_dointvec_jiffies,
 		.strategy	=	&sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_TIMEOUT,
 		.procname	=	"gc_timeout",
-         	.data		=	&ip6_rt_gc_timeout,
+		.data		=	&ip6_rt_gc_timeout,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-         	.proc_handler	=	&proc_dointvec_jiffies,
+		.proc_handler	=	&proc_dointvec_jiffies,
 		.strategy	=	&sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_INTERVAL,
 		.procname	=	"gc_interval",
-         	.data		=	&ip6_rt_gc_interval,
+		.data		=	&ip6_rt_gc_interval,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-         	.proc_handler	=	&proc_dointvec_jiffies,
+		.proc_handler	=	&proc_dointvec_jiffies,
 		.strategy	=	&sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_ELASTICITY,
 		.procname	=	"gc_elasticity",
-         	.data		=	&ip6_rt_gc_elasticity,
+		.data		=	&ip6_rt_gc_elasticity,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-         	.proc_handler	=	&proc_dointvec_jiffies,
+		.proc_handler	=	&proc_dointvec_jiffies,
 		.strategy	=	&sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_MTU_EXPIRES,
 		.procname	=	"mtu_expires",
-         	.data		=	&ip6_rt_mtu_expires,
+		.data		=	&ip6_rt_mtu_expires,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-         	.proc_handler	=	&proc_dointvec_jiffies,
+		.proc_handler	=	&proc_dointvec_jiffies,
 		.strategy	=	&sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_MIN_ADVMSS,
 		.procname	=	"min_adv_mss",
-         	.data		=	&ip6_rt_min_advmss,
+		.data		=	&ip6_rt_min_advmss,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-         	.proc_handler	=	&proc_dointvec_jiffies,
+		.proc_handler	=	&proc_dointvec_jiffies,
 		.strategy	=	&sysctl_jiffies,
 	},
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS,
 		.procname	=	"gc_min_interval_ms",
-         	.data		=	&ip6_rt_gc_min_interval,
+		.data		=	&ip6_rt_gc_min_interval,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-         	.proc_handler	=	&proc_dointvec_ms_jiffies,
+		.proc_handler	=	&proc_dointvec_ms_jiffies,
 		.strategy	=	&sysctl_ms_jiffies,
 	},
 	{ .ctl_name = 0 }
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 77b7b09..08d6ed3 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
  *	$Id: sit.c,v 1.53 2001/09/25 05:09:53 davem Exp $
@@ -24,7 +24,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -216,7 +215,7 @@
 }
 
 
-static void ipip6_err(struct sk_buff *skb, u32 info)
+static int ipip6_err(struct sk_buff *skb, u32 info)
 {
 #ifndef I_WISH_WORLD_WERE_PERFECT
 
@@ -228,21 +227,22 @@
 	int type = skb->h.icmph->type;
 	int code = skb->h.icmph->code;
 	struct ip_tunnel *t;
+	int err;
 
 	switch (type) {
 	default:
 	case ICMP_PARAMETERPROB:
-		return;
+		return 0;
 
 	case ICMP_DEST_UNREACH:
 		switch (code) {
 		case ICMP_SR_FAILED:
 		case ICMP_PORT_UNREACH:
 			/* Impossible event. */
-			return;
+			return 0;
 		case ICMP_FRAG_NEEDED:
 			/* Soft state for pmtu is maintained by IP core. */
-			return;
+			return 0;
 		default:
 			/* All others are translated to HOST_UNREACH.
 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
@@ -253,14 +253,18 @@
 		break;
 	case ICMP_TIME_EXCEEDED:
 		if (code != ICMP_EXC_TTL)
-			return;
+			return 0;
 		break;
 	}
 
+	err = -ENOENT;
+
 	read_lock(&ipip6_lock);
 	t = ipip6_tunnel_lookup(iph->daddr, iph->saddr);
 	if (t == NULL || t->parms.iph.daddr == 0)
 		goto out;
+
+	err = 0;
 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
 		goto out;
 
@@ -271,7 +275,7 @@
 	t->err_time = jiffies;
 out:
 	read_unlock(&ipip6_lock);
-	return;
+	return err;
 #else
 	struct iphdr *iph = (struct iphdr*)dp;
 	int hlen = iph->ihl<<2;
@@ -332,7 +336,7 @@
 	/* Prepare fake skb to feed it to icmpv6_send */
 	skb2 = skb_clone(skb, GFP_ATOMIC);
 	if (skb2 == NULL)
-		return;
+		return 0;
 	dst_release(skb2->dst);
 	skb2->dst = NULL;
 	skb_pull(skb2, skb->data - (u8*)iph6);
@@ -355,7 +359,7 @@
 		}
 	}
 	kfree_skb(skb2);
-	return;
+	return 0;
 #endif
 }
 
@@ -410,7 +414,7 @@
 	__be32 dst = 0;
 
 	if (v6dst->s6_addr16[0] == htons(0x2002)) {
-	        /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */
+		/* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */
 		memcpy(&dst, &v6dst->s6_addr16[1], 4);
 	}
 	return dst;
@@ -434,7 +438,7 @@
 	int    max_headroom;			/* The extra header space needed */
 	__be32 dst = tiph->daddr;
 	int    mtu;
-	struct in6_addr *addr6;	
+	struct in6_addr *addr6;
 	int addr_type;
 
 	if (tunnel->recursion++) {
@@ -537,7 +541,7 @@
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
-  			stats->tx_dropped++;
+			stats->tx_dropped++;
 			dev_kfree_skb(skb);
 			tunnel->recursion--;
 			return 0;
@@ -686,7 +690,8 @@
 				goto done;
 			dev = t->dev;
 		}
-		err = unregister_netdevice(dev);
+		unregister_netdevice(dev);
+		err = 0;
 		break;
 
 	default:
@@ -790,9 +795,10 @@
 	return 0;
 }
 
-static struct net_protocol sit_protocol = {
+static struct xfrm_tunnel sit_handler = {
 	.handler	=	ipip6_rcv,
 	.err_handler	=	ipip6_err,
+	.priority	=	1,
 };
 
 static void __exit sit_destroy_tunnels(void)
@@ -811,7 +817,7 @@
 
 static void __exit sit_cleanup(void)
 {
-	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
+	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
 
 	rtnl_lock();
 	sit_destroy_tunnels();
@@ -825,12 +831,12 @@
 
 	printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n");
 
-	if (inet_add_protocol(&sit_protocol, IPPROTO_IPV6) < 0) {
+	if (xfrm4_tunnel_register(&sit_handler, AF_INET6) < 0) {
 		printk(KERN_INFO "sit init: Can't add protocol\n");
 		return -EAGAIN;
 	}
 
-	ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", 
+	ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0",
 					   ipip6_tunnel_setup);
 	if (!ipip6_fb_tunnel_dev) {
 		err = -ENOMEM;
@@ -847,7 +853,7 @@
  err2:
 	free_netdev(ipip6_fb_tunnel_dev);
  err1:
-	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
+	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
 	goto out;
 }
 
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 7a4639d..3fb4427 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -92,7 +92,7 @@
 		.mode		= 0555,
 		.child		= ipv6_table
 	},
-        { .ctl_name = 0 }
+	{ .ctl_name = 0 }
 };
 
 static ctl_table ipv6_root_table[] = {
@@ -102,12 +102,12 @@
 		.mode		= 0555,
 		.child		= ipv6_net_table
 	},
-        { .ctl_name = 0 }
+	{ .ctl_name = 0 }
 };
 
 void ipv6_sysctl_register(void)
 {
-	ipv6_sysctl_header = register_sysctl_table(ipv6_root_table, 0);
+	ipv6_sysctl_header = register_sysctl_table(ipv6_root_table);
 }
 
 void ipv6_sysctl_unregister(void)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index c25e930..f57a9ba 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1,13 +1,13 @@
 /*
  *	TCP over IPv6
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	$Id: tcp_ipv6.c,v 1.144 2002/02/01 22:01:04 davem Exp $
  *
- *	Based on: 
+ *	Based on:
  *	linux/net/ipv4/tcp.c
  *	linux/net/ipv4/tcp_input.c
  *	linux/net/ipv4/tcp_output.c
@@ -74,7 +74,7 @@
 
 static void	tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
 static void	tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
-static void	tcp_v6_send_check(struct sock *sk, int len, 
+static void	tcp_v6_send_check(struct sock *sk, int len,
 				  struct sk_buff *skb);
 
 static int	tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
@@ -106,8 +106,8 @@
 }
 
 static __inline__ __sum16 tcp_v6_check(struct tcphdr *th, int len,
-				   struct in6_addr *saddr, 
-				   struct in6_addr *daddr, 
+				   struct in6_addr *saddr,
+				   struct in6_addr *daddr,
 				   __wsum base)
 {
 	return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
@@ -121,11 +121,11 @@
 					    skb->h.th->source);
 }
 
-static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, 
+static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 			  int addr_len)
 {
 	struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
- 	struct inet_sock *inet = inet_sk(sk);
+	struct inet_sock *inet = inet_sk(sk);
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -135,10 +135,10 @@
 	int addr_type;
 	int err;
 
-	if (addr_len < SIN6_LEN_RFC2133) 
+	if (addr_len < SIN6_LEN_RFC2133)
 		return -EINVAL;
 
-	if (usin->sin6_family != AF_INET6) 
+	if (usin->sin6_family != AF_INET6)
 		return(-EAFNOSUPPORT);
 
 	memset(&fl, 0, sizeof(fl));
@@ -157,11 +157,11 @@
 	}
 
 	/*
-  	 *	connect() to INADDR_ANY means loopback (BSD'ism).
-  	 */
-  	
-  	if(ipv6_addr_any(&usin->sin6_addr))
-		usin->sin6_addr.s6_addr[15] = 0x1; 
+	 *	connect() to INADDR_ANY means loopback (BSD'ism).
+	 */
+
+	if(ipv6_addr_any(&usin->sin6_addr))
+		usin->sin6_addr.s6_addr[15] = 0x1;
 
 	addr_type = ipv6_addr_type(&usin->sin6_addr);
 
@@ -265,7 +265,7 @@
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+	if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
 		goto failure;
 
 	if (saddr == NULL) {
@@ -323,7 +323,7 @@
 	struct ipv6_pinfo *np;
 	struct sock *sk;
 	int err;
-	struct tcp_sock *tp; 
+	struct tcp_sock *tp;
 	__u32 seq;
 
 	sk = inet6_lookup(&tcp_hashinfo, &hdr->daddr, th->dest, &hdr->saddr,
@@ -347,7 +347,7 @@
 		goto out;
 
 	tp = tcp_sk(sk);
-	seq = ntohl(th->seq); 
+	seq = ntohl(th->seq);
 	if (sk->sk_state != TCP_LISTEN &&
 	    !between(seq, tp->snd_una, tp->snd_nxt)) {
 		NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
@@ -434,7 +434,7 @@
 
 	case TCP_SYN_SENT:
 	case TCP_SYN_RECV:  /* Cannot happen.
-			       It can, it SYNs are crossed. --ANK */ 
+			       It can, it SYNs are crossed. --ANK */
 		if (!sock_owned_by_user(sk)) {
 			sk->sk_err = err;
 			sk->sk_error_report(sk);		/* Wake people up to see the error (see connect in sock.c) */
@@ -519,7 +519,7 @@
 	}
 
 done:
-        if (opt && opt != np->opt)
+	if (opt && opt != np->opt)
 		sock_kfree_s(sk, opt, opt->tot_len);
 	dst_release(dst);
 	return err;
@@ -950,8 +950,8 @@
 		th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP,  0);
 		skb->csum_offset = offsetof(struct tcphdr, check);
 	} else {
-		th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 
-					    csum_partial((char *)th, th->doff<<2, 
+		th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP,
+					    csum_partial((char *)th, th->doff<<2,
 							 skb->csum));
 	}
 }
@@ -977,7 +977,7 @@
 
 static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
 {
-	struct tcphdr *th = skb->h.th, *t1; 
+	struct tcphdr *th = skb->h.th, *t1;
 	struct sk_buff *buff;
 	struct flowi fl;
 	int tot_len = sizeof(*th);
@@ -989,7 +989,7 @@
 		return;
 
 	if (!ipv6_unicast_destination(skb))
-		return; 
+		return;
 
 #ifdef CONFIG_TCP_MD5SIG
 	if (sk)
@@ -1008,8 +1008,8 @@
 
 	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
 			 GFP_ATOMIC);
-	if (buff == NULL) 
-	  	return;
+	if (buff == NULL)
+		return;
 
 	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
 
@@ -1021,9 +1021,9 @@
 	t1->source = th->dest;
 	t1->doff = tot_len / 4;
 	t1->rst = 1;
-  
+
 	if(th->ack) {
-	  	t1->seq = th->ack_seq;
+		t1->seq = th->ack_seq;
 	} else {
 		t1->ack = 1;
 		t1->ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin
@@ -1128,7 +1128,7 @@
 	t1->window = htons(win);
 
 	topt = (__be32 *)(t1 + 1);
-	
+
 	if (ts) {
 		*topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
 				(TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
@@ -1243,15 +1243,15 @@
 		return tcp_v4_conn_request(sk, skb);
 
 	if (!ipv6_unicast_destination(skb))
-		goto drop; 
+		goto drop;
 
 	/*
-	 *	There are no SYN attacks on IPv6, yet...	
+	 *	There are no SYN attacks on IPv6, yet...
 	 */
 	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
 		if (net_ratelimit())
 			printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n");
-		goto drop;		
+		goto drop;
 	}
 
 	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
@@ -1292,7 +1292,7 @@
 	    ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
 		treq->iif = inet6_iif(skb);
 
-	if (isn == 0) 
+	if (isn == 0)
 		isn = tcp_v6_init_sequence(skb);
 
 	tcp_rsk(req)->snt_isn = isn;
@@ -1334,7 +1334,7 @@
 
 		newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst);
 
-		if (newsk == NULL) 
+		if (newsk == NULL)
 			return NULL;
 
 		newtcp6sk = (struct tcp6_sock *)newsk;
@@ -1419,7 +1419,7 @@
 
 		if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
 			goto out;
-	} 
+	}
 
 	newsk = tcp_create_openreq_child(sk, req, skb);
 	if (newsk == NULL)
@@ -1448,7 +1448,7 @@
 	ipv6_addr_copy(&newnp->rcv_saddr, &treq->loc_addr);
 	newsk->sk_bound_dev_if = treq->iif;
 
-	/* Now IPv6 options... 
+	/* Now IPv6 options...
 
 	   First: no IPv4 options.
 	 */
@@ -1592,7 +1592,7 @@
 	   looks not very well thought. For now we latch
 	   options, received in the last packet, enqueued
 	   by tcp. Feel free to propose better solution.
-	                                       --ANK (980728)
+					       --ANK (980728)
 	 */
 	if (np->rxopt.all)
 		opt_skb = skb_clone(skb, GFP_ATOMIC);
@@ -1610,7 +1610,7 @@
 	if (skb->len < (skb->h.th->doff<<2) || tcp_checksum_complete(skb))
 		goto csum_err;
 
-	if (sk->sk_state == TCP_LISTEN) { 
+	if (sk->sk_state == TCP_LISTEN) {
 		struct sock *nsk = tcp_v6_hnd_req(sk, skb);
 		if (!nsk)
 			goto discard;
@@ -1620,7 +1620,7 @@
 		 * otherwise we just shortcircuit this and continue with
 		 * the new socket..
 		 */
- 		if(nsk != sk) {
+		if(nsk != sk) {
 			if (tcp_child_process(sk, nsk, skb))
 				goto reset;
 			if (opt_skb)
@@ -1681,7 +1681,7 @@
 static int tcp_v6_rcv(struct sk_buff **pskb)
 {
 	struct sk_buff *skb = *pskb;
-	struct tcphdr *th;	
+	struct tcphdr *th;
 	struct sock *sk;
 	int ret;
 
@@ -1739,10 +1739,10 @@
 	ret = 0;
 	if (!sock_owned_by_user(sk)) {
 #ifdef CONFIG_NET_DMA
-                struct tcp_sock *tp = tcp_sk(sk);
-                if (tp->ucopy.dma_chan)
-                        ret = tcp_v6_do_rcv(sk, skb);
-                else
+		struct tcp_sock *tp = tcp_sk(sk);
+		if (tp->ucopy.dma_chan)
+			ret = tcp_v6_do_rcv(sk, skb);
+		else
 #endif
 		{
 			if (!tcp_prequeue(sk, skb))
@@ -1945,7 +1945,7 @@
 }
 
 /* Proc filesystem TCPv6 sock list dumping. */
-static void get_openreq6(struct seq_file *seq, 
+static void get_openreq6(struct seq_file *seq,
 			 struct sock *sk, struct request_sock *req, int i, int uid)
 {
 	int ttd = req->expires - jiffies;
@@ -1967,11 +1967,11 @@
 		   ntohs(inet_rsk(req)->rmt_port),
 		   TCP_SYN_RECV,
 		   0,0, /* could print option size, but that is af dependent. */
-		   1,   /* timers active (only the expire timer) */  
-		   jiffies_to_clock_t(ttd), 
+		   1,   /* timers active (only the expire timer) */
+		   jiffies_to_clock_t(ttd),
 		   req->retrans,
 		   uid,
-		   0,  /* non standard timer */  
+		   0,  /* non standard timer */
 		   0, /* open_requests have no inode */
 		   0, req);
 }
@@ -2014,7 +2014,7 @@
 		   src->s6_addr32[2], src->s6_addr32[3], srcp,
 		   dest->s6_addr32[0], dest->s6_addr32[1],
 		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
-		   sp->sk_state, 
+		   sp->sk_state,
 		   tp->write_seq-tp->snd_una,
 		   (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq),
 		   timer_active,
@@ -2031,7 +2031,7 @@
 		   );
 }
 
-static void get_timewait6_sock(struct seq_file *seq, 
+static void get_timewait6_sock(struct seq_file *seq,
 			       struct inet_timewait_sock *tw, int i)
 {
 	struct in6_addr *dest, *src;
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index 918d07d..23e2809 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -30,9 +30,10 @@
 #include <net/xfrm.h>
 
 static struct xfrm6_tunnel *tunnel6_handlers;
+static struct xfrm6_tunnel *tunnel46_handlers;
 static DEFINE_MUTEX(tunnel6_mutex);
 
-int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
+int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family)
 {
 	struct xfrm6_tunnel **pprev;
 	int ret = -EEXIST;
@@ -40,7 +41,8 @@
 
 	mutex_lock(&tunnel6_mutex);
 
-	for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
+	for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
+	     *pprev; pprev = &(*pprev)->next) {
 		if ((*pprev)->priority > priority)
 			break;
 		if ((*pprev)->priority == priority)
@@ -60,14 +62,15 @@
 
 EXPORT_SYMBOL(xfrm6_tunnel_register);
 
-int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
+int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family)
 {
 	struct xfrm6_tunnel **pprev;
 	int ret = -ENOENT;
 
 	mutex_lock(&tunnel6_mutex);
 
-	for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
+	for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
+	     *pprev; pprev = &(*pprev)->next) {
 		if (*pprev == handler) {
 			*pprev = handler->next;
 			ret = 0;
@@ -103,6 +106,25 @@
 	return 0;
 }
 
+static int tunnel46_rcv(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	struct xfrm6_tunnel *handler;
+
+	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+		goto drop;
+
+	for (handler = tunnel46_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;
+}
+
 static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 			int type, int code, int offset, __be32 info)
 {
@@ -119,17 +141,30 @@
 	.flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
+static struct inet6_protocol tunnel46_protocol = {
+	.handler	= tunnel46_rcv,
+	.err_handler	= tunnel6_err,
+	.flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+};
+
 static int __init tunnel6_init(void)
 {
 	if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) {
 		printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
 		return -EAGAIN;
 	}
+	if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) {
+		printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
+		inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6);
+		return -EAGAIN;
+	}
 	return 0;
 }
 
 static void __exit tunnel6_fini(void)
 {
+	if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP))
+		printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
 	if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
 		printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
 }
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index f52a5c3..0ad4719 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1,9 +1,9 @@
 /*
  *	UDP over IPv6
- *	Linux INET6 implementation 
+ *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<roque@di.fc.ul.pt>
  *
  *	Based on linux/ipv4/udp.c
  *
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
-#include <linux/sched.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -67,11 +66,11 @@
 	unsigned short hnum = ntohs(dport);
 	int badness = -1;
 
- 	read_lock(&udp_hash_lock);
+	read_lock(&udp_hash_lock);
 	sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
 		struct inet_sock *inet = inet_sk(sk);
 
-		if (inet->num == hnum && sk->sk_family == PF_INET6) {
+		if (sk->sk_hash == hnum && sk->sk_family == PF_INET6) {
 			struct ipv6_pinfo *np = inet6_sk(sk);
 			int score = 0;
 			if (inet->dport) {
@@ -105,7 +104,7 @@
 	}
 	if (result)
 		sock_hold(result);
- 	read_unlock(&udp_hash_lock);
+	read_unlock(&udp_hash_lock);
 	return result;
 }
 
@@ -120,13 +119,13 @@
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct inet_sock *inet = inet_sk(sk);
-  	struct sk_buff *skb;
+	struct sk_buff *skb;
 	size_t copied;
 	int err, copy_only, is_udplite = IS_UDPLITE(sk);
 
-  	if (addr_len)
-  		*addr_len=sizeof(struct sockaddr_in6);
-  
+	if (addr_len)
+		*addr_len=sizeof(struct sockaddr_in6);
+
 	if (flags & MSG_ERRQUEUE)
 		return ipv6_recv_error(sk, msg, len);
 
@@ -135,11 +134,11 @@
 	if (!skb)
 		goto out;
 
- 	copied = skb->len - sizeof(struct udphdr);
-  	if (copied > len) {
-  		copied = len;
-  		msg->msg_flags |= MSG_TRUNC;
-  	}
+	copied = skb->len - sizeof(struct udphdr);
+	if (copied > len) {
+		copied = len;
+		msg->msg_flags |= MSG_TRUNC;
+	}
 
 	/*
 	 * 	Decide whether to checksum and/or copy data.
@@ -168,7 +167,7 @@
 	/* Copy the address. */
 	if (msg->msg_name) {
 		struct sockaddr_in6 *sin6;
-	  
+
 		sin6 = (struct sockaddr_in6 *) msg->msg_name;
 		sin6->sin6_family = AF_INET6;
 		sin6->sin6_port = skb->h.uh->source;
@@ -191,7 +190,7 @@
 	} else {
 		if (np->rxopt.all)
 			datagram_recv_ctl(sk, msg, skb);
-  	}
+	}
 
 	err = copied;
 	if (flags & MSG_TRUNC)
@@ -309,7 +308,7 @@
 	sk_for_each_from(s, node) {
 		struct inet_sock *inet = inet_sk(s);
 
-		if (inet->num == num && s->sk_family == PF_INET6) {
+		if (s->sk_hash == num && s->sk_family == PF_INET6) {
 			struct ipv6_pinfo *np = inet6_sk(s);
 			if (inet->dport) {
 				if (inet->dport != rmt_port)
@@ -339,7 +338,7 @@
  * so we don't need to lock the hashes.
  */
 static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr,
-		           struct in6_addr *daddr, struct hlist_head udptable[])
+			   struct in6_addr *daddr, struct hlist_head udptable[])
 {
 	struct sock *sk, *sk2;
 	const struct udphdr *uh = skb->h.uh;
@@ -379,7 +378,7 @@
 	}
 	if (skb->ip_summed == CHECKSUM_COMPLETE &&
 	    !csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
-		    	     skb->len, IPPROTO_UDP, skb->csum             ))
+			     skb->len, IPPROTO_UDP, skb->csum             ))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 	if (skb->ip_summed != CHECKSUM_UNNECESSARY)
@@ -396,7 +395,7 @@
 {
 	struct sk_buff *skb = *pskb;
 	struct sock *sk;
-  	struct udphdr *uh;
+	struct udphdr *uh;
 	struct net_device *dev = skb->dev;
 	struct in6_addr *saddr, *daddr;
 	u32 ulen = 0;
@@ -437,15 +436,15 @@
 			goto discard;
 	}
 
-	/* 
-	 *	Multicast receive code 
+	/*
+	 *	Multicast receive code
 	 */
 	if (ipv6_addr_is_multicast(daddr))
 		return __udp6_lib_mcast_deliver(skb, saddr, daddr, udptable);
 
 	/* Unicast */
 
-	/* 
+	/*
 	 * check socket cache ... must talk to Alan about his plans
 	 * for sock caches... i'll skip this for now.
 	 */
@@ -465,21 +464,21 @@
 		kfree_skb(skb);
 		return(0);
 	}
-	
+
 	/* deliver */
-	
+
 	udpv6_queue_rcv_skb(sk, skb);
 	sock_put(sk);
 	return(0);
 
-short_packet:	
+short_packet:
 	LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n",
 		       is_udplite? "-Lite" : "",  ulen, skb->len);
 
 discard:
 	UDP6_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
 	kfree_skb(skb);
-	return(0);	
+	return(0);
 }
 
 static __inline__ int udpv6_rcv(struct sk_buff **pskb)
@@ -498,7 +497,7 @@
 		up->len = 0;
 		up->pending = 0;
 		ip6_flush_pending_frames(sk);
-        }
+	}
 }
 
 /*
@@ -594,7 +593,7 @@
 		if (sk->sk_state != TCP_ESTABLISHED)
 			return -EDESTADDRREQ;
 		daddr = &np->daddr;
-	} else 
+	} else
 		daddr = NULL;
 
 	if (daddr) {
@@ -620,7 +619,7 @@
 	   */
 	if (len > INT_MAX - sizeof(struct udphdr))
 		return -EMSGSIZE;
-	
+
 	if (up->pending) {
 		/*
 		 * There are pending frames.
@@ -713,7 +712,7 @@
 	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
 	fl.fl_ip_sport = inet->sport;
-	
+
 	/* merge ip6_build_xmit from ip6_output */
 	if (opt && opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
@@ -736,7 +735,7 @@
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+	if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
 		goto out;
 
 	if (hlimit < 0) {
@@ -911,7 +910,7 @@
 		   src->s6_addr32[2], src->s6_addr32[3], srcp,
 		   dest->s6_addr32[0], dest->s6_addr32[1],
 		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
-		   sp->sk_state, 
+		   sp->sk_state,
 		   atomic_read(&sp->sk_wmem_alloc),
 		   atomic_read(&sp->sk_rmem_alloc),
 		   0, 0L, 0,
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index ec98788..6e252f3 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -11,9 +11,9 @@
 			       int , int , int , __be32 , struct hlist_head []);
 
 extern int	udpv6_getsockopt(struct sock *sk, int level, int optname,
-		     		 char __user *optval, int __user *optlen);
+				 char __user *optval, int __user *optlen);
 extern int	udpv6_setsockopt(struct sock *sk, int level, int optname,
-			  	 char __user *optval, int optlen);
+				 char __user *optval, int optlen);
 #ifdef CONFIG_COMPAT
 extern int	compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
 					char __user *optval, int optlen);
@@ -24,7 +24,7 @@
 			      struct msghdr *msg, size_t len);
 extern int	udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
 			      struct msghdr *msg, size_t len,
-		  	      int noblock, int flags, int *addr_len);
+			      int noblock, int flags, int *addr_len);
 extern int	udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb);
 extern int	udpv6_destroy_sock(struct sock *sk);
 
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 5c8b7a5..31f651f 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -33,14 +33,15 @@
 	seq = 0;
 	if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
 		goto drop;
-	
+
 	do {
 		struct ipv6hdr *iph = skb->nh.ipv6h;
 
 		if (xfrm_nr == XFRM_MAX_DEPTH)
 			goto drop;
 
-		x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, nexthdr, AF_INET6);
+		x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
+				nexthdr != IPPROTO_IPIP ? nexthdr : IPPROTO_IPV6, AF_INET6);
 		if (x == NULL)
 			goto drop;
 		spin_lock(&x->lock);
@@ -115,7 +116,7 @@
 		__skb_push(skb, skb->data - skb->nh.raw);
 
 		NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
-		        ip6_rcv_finish);
+			ip6_rcv_finish);
 		return -1;
 #else
 		return 1;
@@ -142,12 +143,12 @@
 int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
 		     xfrm_address_t *saddr, u8 proto)
 {
- 	struct xfrm_state *x = NULL;
- 	int wildcard = 0;
+	struct xfrm_state *x = NULL;
+	int wildcard = 0;
 	struct in6_addr any;
 	xfrm_address_t *xany;
 	struct xfrm_state *xfrm_vec_one = NULL;
- 	int nh = 0;
+	int nh = 0;
 	int i = 0;
 
 	ipv6_addr_set(&any, 0, 0, 0, 0);
@@ -168,12 +169,12 @@
 			break;
 		case 2:
 		default:
- 			/* lookup state with wild-card addresses */
+			/* lookup state with wild-card addresses */
 			wildcard = 1; /* XXX */
 			dst = xany;
 			src = xany;
 			break;
- 		}
+		}
 
 		x = xfrm_state_lookup_byaddr(dst, src, proto, AF_INET6);
 		if (!x)
@@ -193,8 +194,8 @@
 		if (unlikely(x->km.state != XFRM_STATE_VALID)) {
 			spin_unlock(&x->lock);
 			xfrm_state_put(x);
- 			x = NULL;
- 			continue;
+			x = NULL;
+			continue;
 		}
 		if (xfrm_state_check_expire(x)) {
 			spin_unlock(&x->lock);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 5e7d8a7..0bc866c 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -25,6 +25,12 @@
 		IP6_ECN_set_ce(inner_iph);
 }
 
+static inline void ip6ip_ecn_decapsulate(struct sk_buff *skb)
+{
+	if (INET_ECN_is_ce(ipv6_get_dsfield(skb->nh.ipv6h)))
+			IP_ECN_set_ce(skb->h.ipiph);
+}
+
 /* Add encapsulation header.
  *
  * The top IP header will be constructed per RFC 2401.  The following fields
@@ -40,6 +46,7 @@
 static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb->dst;
+	struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
 	struct ipv6hdr *iph, *top_iph;
 	int dsfield;
 
@@ -52,16 +59,24 @@
 	skb->h.ipv6h = top_iph + 1;
 
 	top_iph->version = 6;
-	top_iph->priority = iph->priority;
-	top_iph->flow_lbl[0] = iph->flow_lbl[0];
-	top_iph->flow_lbl[1] = iph->flow_lbl[1];
-	top_iph->flow_lbl[2] = iph->flow_lbl[2];
+	if (xdst->route->ops->family == AF_INET6) {
+		top_iph->priority = iph->priority;
+		top_iph->flow_lbl[0] = iph->flow_lbl[0];
+		top_iph->flow_lbl[1] = iph->flow_lbl[1];
+		top_iph->flow_lbl[2] = iph->flow_lbl[2];
+		top_iph->nexthdr = IPPROTO_IPV6;
+	} else {
+		top_iph->priority = 0;
+		top_iph->flow_lbl[0] = 0;
+		top_iph->flow_lbl[1] = 0;
+		top_iph->flow_lbl[2] = 0;
+		top_iph->nexthdr = IPPROTO_IPIP;
+	}
 	dsfield = ipv6_get_dsfield(top_iph);
 	dsfield = INET_ECN_encapsulate(dsfield, dsfield);
 	if (x->props.flags & XFRM_STATE_NOECN)
 		dsfield &= ~INET_ECN_MASK;
 	ipv6_change_dsfield(top_iph, 0, dsfield);
-	top_iph->nexthdr = IPPROTO_IPV6; 
 	top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
 	ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
 	ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
@@ -72,7 +87,8 @@
 {
 	int err = -EINVAL;
 
-	if (skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPV6)
+	if (skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPV6
+	    && skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPIP)
 		goto out;
 	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
 		goto out;
@@ -81,10 +97,16 @@
 	    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
 		goto out;
 
-	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
-		ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
-	if (!(x->props.flags & XFRM_STATE_NOECN))
-		ipip6_ecn_decapsulate(skb);
+	if (skb->nh.raw[IP6CB(skb)->nhoff] == IPPROTO_IPV6) {
+		if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+			ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
+		if (!(x->props.flags & XFRM_STATE_NOECN))
+			ipip6_ecn_decapsulate(skb);
+	} else {
+		if (!(x->props.flags & XFRM_STATE_NOECN))
+			ip6ip_ecn_decapsulate(skb);
+		skb->protocol = htons(ETH_P_IP);
+	}
 	skb->mac.raw = memmove(skb->data - skb->mac_len,
 			       skb->mac.raw, skb->mac_len);
 	skb->nh.raw = skb->data;
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index c260ea1..d6d786b 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -2,7 +2,7 @@
  * xfrm6_output.c - Common IPsec encapsulation code for IPv6.
  * Copyright (C) 2002 USAGI/WIDE Project
  * Copyright (c) 2004 Herbert Xu <herbert@gondor.apana.org.au>
- * 
+ *
  * 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
@@ -46,7 +46,7 @@
 	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	int err;
-	
+
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		err = skb_checksum_help(skb);
 		if (err)
@@ -81,7 +81,7 @@
 		spin_unlock_bh(&x->lock);
 
 		skb->nh.raw = skb->data;
-		
+
 		if (!(skb->dst = dst_pop(dst))) {
 			err = -EHOSTUNREACH;
 			goto error_nolock;
@@ -108,7 +108,7 @@
 
 	while (likely((err = xfrm6_output_one(skb)) == 0)) {
 		nf_reset(skb);
-	
+
 		err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, &skb, NULL,
 			      skb->dst->dev, dst_output);
 		if (unlikely(err != 1))
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 8dffd4d..b1133f2 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -8,7 +8,7 @@
  * 		IPv6 support
  * 	YOSHIFUJI Hideaki
  * 		Split up af-specific portion
- * 
+ *
  */
 
 #include <linux/compiler.h>
@@ -131,13 +131,11 @@
 	struct dst_entry *dst, *dst_prev;
 	struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
 	struct rt6_info *rt  = rt0;
-	struct in6_addr *remote = &fl->fl6_dst;
-	struct in6_addr *local  = &fl->fl6_src;
 	struct flowi fl_tunnel = {
 		.nl_u = {
 			.ip6_u = {
-				.saddr = *local,
-				.daddr = *remote
+				.saddr = fl->fl6_src,
+				.daddr = fl->fl6_dst,
 			}
 		}
 	};
@@ -153,7 +151,6 @@
 	for (i = 0; i < nx; i++) {
 		struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
 		struct xfrm_dst *xdst;
-		int tunnel = 0;
 
 		if (unlikely(dst1 == NULL)) {
 			err = -ENOBUFS;
@@ -177,19 +174,29 @@
 
 		dst1->next = dst_prev;
 		dst_prev = dst1;
-		if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
-			remote = __xfrm6_bundle_addr_remote(xfrm[i], remote);
-			local  = __xfrm6_bundle_addr_local(xfrm[i], local);
-			tunnel = 1;
-		}
+
 		__xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
 		trailer_len += xfrm[i]->props.trailer_len;
 
-		if (tunnel) {
-			ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);
-			ipv6_addr_copy(&fl_tunnel.fl6_src, local);
+		if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL ||
+		    xfrm[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) {
+			unsigned short encap_family = xfrm[i]->props.family;
+			switch(encap_family) {
+			case AF_INET:
+				fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4;
+				fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4;
+				break;
+			case AF_INET6:
+				ipv6_addr_copy(&fl_tunnel.fl6_dst, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_dst));
+
+				ipv6_addr_copy(&fl_tunnel.fl6_src, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_src));
+				break;
+			default:
+				BUG_ON(1);
+			}
+
 			err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
-					      &fl_tunnel, AF_INET6);
+					      &fl_tunnel, encap_family);
 			if (err)
 				goto error;
 		} else
@@ -208,6 +215,7 @@
 	i = 0;
 	for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
 		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
+		struct xfrm_state_afinfo *afinfo;
 
 		dst_prev->xfrm = xfrm[i++];
 		dst_prev->dev = rt->u.dst.dev;
@@ -224,16 +232,26 @@
 		/* Copy neighbour for reachability confirmation */
 		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
 		dst_prev->input		= rt->u.dst.input;
-		dst_prev->output	= xfrm6_output;
+		/* XXX: When IPv4 is implemented as module and can be unloaded,
+		 * we should manage reference to xfrm4_output in afinfo->output.
+		 * Miyazawa
+		 */
+		afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family);
+		if (!afinfo) {
+			dst = *dst_p;
+			goto error;
+		};
+		dst_prev->output = afinfo->output;
+		xfrm_state_put_afinfo(afinfo);
 		/* Sheit... I remember I did this right. Apparently,
 		 * it was magically lost, so this code needs audit */
 		x->u.rt6.rt6i_flags    = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
 		x->u.rt6.rt6i_metric   = rt0->rt6i_metric;
 		x->u.rt6.rt6i_node     = rt0->rt6i_node;
 		x->u.rt6.rt6i_gateway  = rt0->rt6i_gateway;
-		memcpy(&x->u.rt6.rt6i_gateway, &rt0->rt6i_gateway, sizeof(x->u.rt6.rt6i_gateway)); 
+		memcpy(&x->u.rt6.rt6i_gateway, &rt0->rt6i_gateway, sizeof(x->u.rt6.rt6i_gateway));
 		x->u.rt6.rt6i_dst      = rt0->rt6i_dst;
-		x->u.rt6.rt6i_src      = rt0->rt6i_src;	
+		x->u.rt6.rt6i_src      = rt0->rt6i_src;
 		x->u.rt6.rt6i_idev     = rt0->rt6i_idev;
 		in6_dev_hold(rt0->rt6i_idev);
 		__xfrm6_bundle_len_dec(&header_len, &nfheader_len, x->u.dst.xfrm);
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index 9ddaa9d..baa461b 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -8,7 +8,7 @@
  * 		IPv6 support
  * 	YOSHIFUJI Hideaki @USAGI
  * 		Split up af-specific portion
- * 	
+ *
  */
 
 #include <net/xfrm.h>
@@ -171,6 +171,7 @@
 	.init_tempsel		= __xfrm6_init_tempsel,
 	.tmpl_sort		= __xfrm6_tmpl_sort,
 	.state_sort		= __xfrm6_state_sort,
+	.output			= xfrm6_output,
 };
 
 void __init xfrm6_state_init(void)
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 12e426b..ee4b84a 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -5,12 +5,12 @@
  * 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
@@ -32,7 +32,7 @@
 #include <linux/mutex.h>
 
 /*
- * xfrm_tunnel_spi things are for allocating unique id ("spi") 
+ * xfrm_tunnel_spi things are for allocating unique id ("spi")
  * per xfrm_address_t.
  */
 struct xfrm6_tunnel_spi {
@@ -155,8 +155,8 @@
 
 	for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) {
 		index = xfrm6_tunnel_spi_hash_byspi(spi);
-		hlist_for_each_entry(x6spi, pos, 
-				     &xfrm6_tunnel_spi_byspi[index], 
+		hlist_for_each_entry(x6spi, pos,
+				     &xfrm6_tunnel_spi_byspi[index],
 				     list_byspi) {
 			if (x6spi->spi == spi)
 				goto try_next_1;
@@ -167,8 +167,8 @@
 	}
 	for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) {
 		index = xfrm6_tunnel_spi_hash_byspi(spi);
-		hlist_for_each_entry(x6spi, pos, 
-				     &xfrm6_tunnel_spi_byspi[index], 
+		hlist_for_each_entry(x6spi, pos,
+				     &xfrm6_tunnel_spi_byspi[index],
 				     list_byspi) {
 			if (x6spi->spi == spi)
 				goto try_next_2;
@@ -222,7 +222,7 @@
 
 	write_lock_bh(&xfrm6_tunnel_spi_lock);
 
-	hlist_for_each_entry_safe(x6spi, pos, n, 
+	hlist_for_each_entry_safe(x6spi, pos, n,
 				  &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
 				  list_byaddr)
 	{
@@ -269,9 +269,9 @@
 {
 	/* xfrm6_tunnel native err handling */
 	switch (type) {
-	case ICMPV6_DEST_UNREACH: 
+	case ICMPV6_DEST_UNREACH:
 		switch (code) {
-		case ICMPV6_NOROUTE: 
+		case ICMPV6_NOROUTE:
 		case ICMPV6_ADM_PROHIBITED:
 		case ICMPV6_NOT_NEIGHBOUR:
 		case ICMPV6_ADDR_UNREACH:
@@ -287,7 +287,7 @@
 		case ICMPV6_EXC_HOPLIMIT:
 			break;
 		case ICMPV6_EXC_FRAGTIME:
-		default: 
+		default:
 			break;
 		}
 		break;
@@ -339,17 +339,29 @@
 	.priority	= 2,
 };
 
+static struct xfrm6_tunnel xfrm46_tunnel_handler = {
+	.handler	= xfrm6_tunnel_rcv,
+	.err_handler	= xfrm6_tunnel_err,
+	.priority	= 2,
+};
+
 static int __init xfrm6_tunnel_init(void)
 {
 	if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0)
 		return -EAGAIN;
 
-	if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) {
+	if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) {
+		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+		return -EAGAIN;
+	}
+	if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) {
+		xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
 		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
 		return -EAGAIN;
 	}
 	if (xfrm6_tunnel_spi_init() < 0) {
-		xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
+		xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
+		xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
 		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
 		return -EAGAIN;
 	}
@@ -359,7 +371,8 @@
 static void __exit xfrm6_tunnel_fini(void)
 {
 	xfrm6_tunnel_spi_fini();
-	xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
+	xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
+	xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
 	xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
 }
 
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 76c6615..cac35a7 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -11,7 +11,7 @@
  *	work I am currently employed to do there.
  *
  *	All the material in this file is subject to the Gnu license version 2.
- *	Neither Alan Cox nor the Swansea University Computer Society admit 
+ *	Neither Alan Cox nor the Swansea University Computer Society admit
  *	liability nor provide warranty for any of this software. This material
  *	is provided as is and at no charge.
  *
@@ -152,8 +152,8 @@
 	ipx_remove_socket(sk);
 	skb_queue_purge(&sk->sk_receive_queue);
 #ifdef IPX_REFCNT_DEBUG
-        atomic_dec(&ipx_sock_nr);
-        printk(KERN_DEBUG "IPX socket %p released, %d are still alive\n", sk,
+	atomic_dec(&ipx_sock_nr);
+	printk(KERN_DEBUG "IPX socket %p released, %d are still alive\n", sk,
 			atomic_read(&ipx_sock_nr));
 	if (atomic_read(&sk->sk_refcnt) != 1)
 		printk(KERN_DEBUG "Destruction sock ipx %p delayed, cnt=%d\n",
@@ -162,7 +162,7 @@
 	sock_put(sk);
 }
 
-/* 
+/*
  * The following code is used to support IPX Interfaces (IPXITF).  An
  * IPX interface is defined by a physical device and a frame type.
  */
@@ -369,7 +369,7 @@
 	struct ipx_interface *i, *tmp;
 
 	spin_lock_bh(&ipx_interfaces_lock);
-	list_for_each_entry_safe(i, tmp, &ipx_interfaces, node) 
+	list_for_each_entry_safe(i, tmp, &ipx_interfaces, node)
 		__ipxitf_put(i);
 	spin_unlock_bh(&ipx_interfaces_lock);
 }
@@ -446,10 +446,10 @@
 	 * You might call this a hack, but believe me, you do not want a
 	 * complete NCP layer in the kernel, and this is VERY fast as well. */
 	struct sock *sk = NULL;
- 	int connection = 0;
+	int connection = 0;
 	u8 *ncphdr = (u8 *)(ipx + 1);
 
- 	if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */
+	if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */
 		connection = (((int) *(ncphdr + 5)) << 8) | (int) *(ncphdr + 3);
 	else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77) /* BURST packet */
 		connection = (((int) *(ncphdr + 9)) << 8) | (int) *(ncphdr + 8);
@@ -482,7 +482,7 @@
 
 	if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451)
 		sock1 = ncp_connection_hack(intrfc, ipx);
-        if (!sock1)
+	if (!sock1)
 		/* No special socket found, forward the packet the normal way */
 		sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
 
@@ -607,22 +607,22 @@
 		*last_hop = IPX_SKB_CB(skb)->last_hop.netnum;
 		IPX_SKB_CB(skb)->last_hop.index = -1;
 	}
-	
-	/* 
+
+	/*
 	 * We need to know how many skbuffs it will take to send out this
 	 * packet to avoid unnecessary copies.
 	 */
-	 
-	if (!dl || !dev || dev->flags & IFF_LOOPBACK) 
+
+	if (!dl || !dev || dev->flags & IFF_LOOPBACK)
 		send_to_wire = 0;	/* No non looped */
 
 	/*
-	 * See if this should be demuxed to sockets on this interface 
+	 * See if this should be demuxed to sockets on this interface
 	 *
 	 * We want to ensure the original was eaten or that we only use
 	 * up clones.
 	 */
-	 
+
 	if (ipx->ipx_dest.net == intrfc->if_netnum) {
 		/*
 		 * To our own node, loop and free the original.
@@ -709,8 +709,8 @@
 
 	/* See if we should update our network number */
 	if (!intrfc->if_netnum) /* net number of intrfc not known yet */
- 		ipxitf_discover_netnum(intrfc, skb);
-	
+		ipxitf_discover_netnum(intrfc, skb);
+
 	IPX_SKB_CB(skb)->last_hop.index = -1;
 	if (ipx->ipx_type == IPX_TYPE_PPROP) {
 		rc = ipxitf_pprop(intrfc, skb);
@@ -756,7 +756,7 @@
 
 static void ipxitf_discover_netnum(struct ipx_interface *intrfc,
 				   struct sk_buff *skb)
-{ 
+{
 	const struct ipx_cb *cb = IPX_SKB_CB(skb);
 
 	/* see if this is an intra packet: source_net == dest_net */
@@ -793,7 +793,7 @@
  * it, not even processing it locally, if it has exact %IPX_MAX_PPROP_HOPS we
  * don't broadcast it, but process it locally. See chapter 5 of Novell's "IPX
  * RIP and SAP Router Specification", Part Number 107-000029-001.
- * 
+ *
  * If it is valid, check if we have pprop broadcasting enabled by the user,
  * if not, just return zero for local processing.
  *
@@ -820,7 +820,7 @@
 	 * tctrl <= 15, any data payload... */
 	if (IPX_SKB_CB(skb)->ipx_tctrl > IPX_MAX_PPROP_HOPS ||
 	    ntohs(ipx->ipx_pktsize) < sizeof(struct ipxhdr) +
-	    				IPX_MAX_PPROP_HOPS * sizeof(u32))
+					IPX_MAX_PPROP_HOPS * sizeof(u32))
 		goto out;
 	/* are we broadcasting this damn thing? */
 	rc = 0;
@@ -831,7 +831,7 @@
 	 * locally. */
 	if (IPX_SKB_CB(skb)->ipx_tctrl == IPX_MAX_PPROP_HOPS)
 		goto out;
-	
+
 	c = ((u8 *) ipx) + sizeof(struct ipxhdr);
 	l = (__be32 *) c;
 
@@ -851,7 +851,7 @@
 		/* Except unconfigured interfaces */
 		if (!ifcs->if_netnum)
 			continue;
-					
+
 		/* That aren't in the list */
 		if (ifcs == intrfc)
 			continue;
@@ -1003,7 +1003,7 @@
 			dlink_type 	= htons(ETH_P_IPX);
 			datalink 	= pEII_datalink;
 			break;
-		} else 
+		} else
 			printk(KERN_WARNING "IPX frame type EtherII over "
 					"token-ring is obsolete. Use SNAP "
 					"instead.\n");
@@ -1208,14 +1208,14 @@
 		rc = 0;
 		break;
 	}
-	case SIOCAIPXITFCRT: 
+	case SIOCAIPXITFCRT:
 		rc = -EFAULT;
 		if (get_user(val, (unsigned char __user *) arg))
 			break;
 		rc = 0;
 		ipxcfg_auto_create_interfaces = val;
 		break;
-	case SIOCAIPXPRISLT: 
+	case SIOCAIPXPRISLT:
 		rc = -EFAULT;
 		if (get_user(val, (unsigned char __user *) arg))
 			break;
@@ -1230,14 +1230,14 @@
 /*
  *	Checksum routine for IPX
  */
- 
+
 /* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */
 /* This functions should *not* mess with packet contents */
 
 __be16 ipx_cksum(struct ipxhdr *packet, int length)
 {
-	/* 
-	 *	NOTE: sum is a net byte order quantity, which optimizes the 
+	/*
+	 *	NOTE: sum is a net byte order quantity, which optimizes the
 	 *	loop. This only works on big and little endian machines. (I
 	 *	don't know of a machine that isn't.)
 	 */
@@ -1342,7 +1342,7 @@
 	rc = -EINVAL;
 	if(len < 0)
 		goto out;
-		
+
 	rc = -EFAULT;
 	if (put_user(len, optlen) || copy_to_user(optval, &val, len))
 		goto out;
@@ -1372,13 +1372,13 @@
 	if (sock->type != SOCK_DGRAM)
 		goto out;
 
-       	rc = -ENOMEM;
+	rc = -ENOMEM;
 	sk = sk_alloc(PF_IPX, GFP_KERNEL, &ipx_proto, 1);
 	if (!sk)
 		goto out;
 #ifdef IPX_REFCNT_DEBUG
-        atomic_inc(&ipx_sock_nr);
-        printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk,
+	atomic_inc(&ipx_sock_nr);
+	printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk,
 			atomic_read(&ipx_sock_nr));
 #endif
 	sock_init_data(sock, sk);
@@ -1561,7 +1561,7 @@
 			goto out;
 	}
 
-        /* We can either connect to primary network or somewhere
+	/* We can either connect to primary network or somewhere
 	 * we can route to */
 	rt = ipxrtr_lookup(addr->sipx_network);
 	rc = -ENETUNREACH;
@@ -1641,10 +1641,10 @@
 	struct ipxhdr *ipx;
 	u16 ipx_pktsize;
 	int rc = 0;
-		
-	/* Not ours */	
-        if (skb->pkt_type == PACKET_OTHERHOST)
-        	goto drop;
+
+	/* Not ours */
+	if (skb->pkt_type == PACKET_OTHERHOST)
+		goto drop;
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
 		goto out;
@@ -1653,12 +1653,12 @@
 		goto drop;
 
 	ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize);
-	
+
 	/* Too small or invalid header? */
 	if (ipx_pktsize < sizeof(struct ipxhdr) ||
 	    !pskb_may_pull(skb, ipx_pktsize))
 		goto drop;
-                        
+
 	ipx = ipx_hdr(skb);
 	if (ipx->ipx_checksum != IPX_NO_CHECKSUM &&
 	   ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize))
@@ -1786,7 +1786,7 @@
 		if (rc)
 			goto out;
 	}
-	
+
 	rc = -ENOTCONN;
 	if (sock_flag(sk, SOCK_ZAPPED))
 		goto out;
@@ -1875,15 +1875,15 @@
 		 * This socket wants to take care of the NCP connection
 		 * handed to us in arg.
 		 */
-        	rc = -EPERM;
-        	if (!capable(CAP_NET_ADMIN))
+		rc = -EPERM;
+		if (!capable(CAP_NET_ADMIN))
 			break;
 		rc = get_user(ipx_sk(sk)->ipx_ncp_conn,
 			      (const unsigned short __user *)argp);
 		break;
 	case SIOCGSTAMP:
 		rc = -EINVAL;
-		if (sk) 
+		if (sk)
 			rc = sock_get_timestamp(sk, argp);
 		break;
 	case SIOCGIFDSTADDR:
@@ -2035,19 +2035,27 @@
 
 	ipxitf_cleanup();
 
-	unregister_snap_client(pSNAP_datalink);
-	pSNAP_datalink = NULL;
+	if (pSNAP_datalink) {
+		unregister_snap_client(pSNAP_datalink);
+		pSNAP_datalink = NULL;
+	}
 
-	unregister_8022_client(p8022_datalink);
-	p8022_datalink = NULL;
+	if (p8022_datalink) {
+		unregister_8022_client(p8022_datalink);
+		p8022_datalink = NULL;
+	}
 
 	dev_remove_pack(&ipx_8023_packet_type);
-	destroy_8023_client(p8023_datalink);
-	p8023_datalink = NULL;
+	if (p8023_datalink) {
+		destroy_8023_client(p8023_datalink);
+		p8023_datalink = NULL;
+	}
 
 	dev_remove_pack(&ipx_dix_packet_type);
-	destroy_EII_client(pEII_datalink);
-	pEII_datalink = NULL;
+	if (pEII_datalink) {
+		destroy_EII_client(pEII_datalink);
+		pEII_datalink = NULL;
+	}
 
 	proto_unregister(&ipx_proto);
 	sock_unregister(ipx_family_ops.family);
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
index b7463df..db32ac8 100644
--- a/net/ipx/ipx_proc.c
+++ b/net/ipx/ipx_proc.c
@@ -322,7 +322,7 @@
 	return seq_open(file, &ipx_seq_socket_ops);
 }
 
-static struct file_operations ipx_seq_interface_fops = {
+static const struct file_operations ipx_seq_interface_fops = {
 	.owner		= THIS_MODULE,
 	.open           = ipx_seq_interface_open,
 	.read           = seq_read,
@@ -330,7 +330,7 @@
 	.release        = seq_release,
 };
 
-static struct file_operations ipx_seq_route_fops = {
+static const struct file_operations ipx_seq_route_fops = {
 	.owner		= THIS_MODULE,
 	.open           = ipx_seq_route_open,
 	.read           = seq_read,
@@ -338,7 +338,7 @@
 	.release        = seq_release,
 };
 
-static struct file_operations ipx_seq_socket_fops = {
+static const struct file_operations ipx_seq_socket_fops = {
 	.owner		= THIS_MODULE,
 	.open           = ipx_seq_socket_open,
 	.read           = seq_read,
@@ -352,7 +352,7 @@
 {
 	struct proc_dir_entry *p;
 	int rc = -ENOMEM;
-       
+
 	ipx_proc_dir = proc_mkdir("ipx", proc_net);
 
 	if (!ipx_proc_dir)
diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c
index 68560ee..8e1cad9 100644
--- a/net/ipx/ipx_route.c
+++ b/net/ipx/ipx_route.c
@@ -234,7 +234,7 @@
 	if (rc) {
 		kfree_skb(skb);
 		goto out_put;
-	}	
+	}
 
 	/* Apply checksum. Not allowed on 802.3 links. */
 	if (sk->sk_no_check || intrfc->if_dlink_type == htons(IPX_FRAME_8023))
@@ -242,7 +242,7 @@
 	else
 		ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
 
-	rc = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ? 
+	rc = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ?
 			 rt->ir_router_node : ipx->ipx_dest.node);
 out_put:
 	ipxitf_put(intrfc);
diff --git a/net/ipx/sysctl_net_ipx.c b/net/ipx/sysctl_net_ipx.c
index fa57473..0cf5264 100644
--- a/net/ipx/sysctl_net_ipx.c
+++ b/net/ipx/sysctl_net_ipx.c
@@ -34,7 +34,7 @@
 		.procname	= "ipx",
 		.mode		= 0555,
 		.child		= ipx_table,
-       	},
+	},
 	{ 0 },
 };
 
@@ -52,7 +52,7 @@
 
 void ipx_register_sysctl(void)
 {
-	ipx_table_header = register_sysctl_table(ipx_root_table, 1);
+	ipx_table_header = register_sysctl_table(ipx_root_table);
 }
 
 void ipx_unregister_sysctl(void)
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 7e1aea8..eabd683 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -138,7 +138,7 @@
 		sk->sk_shutdown |= SEND_SHUTDOWN;
 
 		sk->sk_state_change(sk);
-                sock_orphan(sk);
+		sock_orphan(sk);
 		release_sock(sk);
 
 		/* Close our TSAP.
@@ -158,7 +158,7 @@
 			irttp_close_tsap(self->tsap);
 			self->tsap = NULL;
 		}
-        }
+	}
 
 	/* Note : once we are there, there is not much you want to do
 	 * with the socket anymore, apart from closing it.
@@ -1211,7 +1211,7 @@
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
-        if (sk == NULL)
+	if (sk == NULL)
 		return 0;
 
 	lock_sock(sk);
@@ -1259,7 +1259,7 @@
 	 * memory leak is now gone... - Jean II
 	 */
 
-        return 0;
+	return 0;
 }
 
 /*
@@ -1312,7 +1312,7 @@
 		len = self->max_data_size;
 	}
 
-	skb = sock_alloc_send_skb(sk, len + self->max_header_size + 16, 
+	skb = sock_alloc_send_skb(sk, len + self->max_header_size + 16,
 				  msg->msg_flags & MSG_DONTWAIT, &err);
 	if (!skb)
 		return -ENOBUFS;
@@ -1714,7 +1714,7 @@
 	self->daddr = DEV_ADDR_ANY;	/* Until we get re-connected */
 	self->saddr = 0x0;		/* so IrLMP assign us any link */
 
-        return 0;
+	return 0;
 }
 
 /*
diff --git a/net/irda/discovery.c b/net/irda/discovery.c
index 89fd2a2..f097341 100644
--- a/net/irda/discovery.c
+++ b/net/irda/discovery.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      discovery.c
  * Version:       0.1
  * Description:   Routines for handling discoveries at the IrLMP layer
@@ -10,24 +10,24 @@
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Modified at:   Fri May 28  3:11 CST 1999
  * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
- * 
+ *
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     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, 
+ *
+ *     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/string.h>
@@ -65,9 +65,9 @@
 
 	spin_lock_irqsave(&cachelog->hb_spinlock, flags);
 
-	/* 
-	 * Remove all discoveries of devices that has previously been 
-	 * discovered on the same link with the same name (info), or the 
+	/*
+	 * Remove all discoveries of devices that has previously been
+	 * discovered on the same link with the same name (info), or the
 	 * same daddr. We do this since some devices (mostly PDAs) change
 	 * their device address between every discovery.
 	 */
@@ -79,10 +79,10 @@
 		discovery = (discovery_t *) hashbin_get_next(cachelog);
 
 		if ((node->data.saddr == new->data.saddr) &&
-		    ((node->data.daddr == new->data.daddr) || 
+		    ((node->data.daddr == new->data.daddr) ||
 		     (strcmp(node->data.info, new->data.info) == 0)))
 		{
-			/* This discovery is a previous discovery 
+			/* This discovery is a previous discovery
 			 * from the same device, so just remove it
 			 */
 			hashbin_remove_this(cachelog, (irda_queue_t *) node);
@@ -134,7 +134,7 @@
 
 		discovery = (discovery_t *) hashbin_remove_first(log);
 	}
-	
+
 	/* Delete the now empty log */
 	hashbin_delete(log, (FREE_FUNC) kfree);
 }
@@ -232,7 +232,7 @@
 	while (discovery != NULL) {
 		IRDA_DEBUG(0, "Discovery:\n");
 		IRDA_DEBUG(0, "  daddr=%08x\n", discovery->data.daddr);
-		IRDA_DEBUG(0, "  saddr=%08x\n", discovery->data.saddr); 
+		IRDA_DEBUG(0, "  saddr=%08x\n", discovery->data.saddr);
 		IRDA_DEBUG(0, "  nickname=%s\n", discovery->data.info);
 
 		discovery = (discovery_t *) hashbin_get_next(log);
@@ -321,26 +321,26 @@
 {
 	discovery_t *discovery;
 
-	for (discovery = (discovery_t *) hashbin_get_first(irlmp->cachelog); 
+	for (discovery = (discovery_t *) hashbin_get_first(irlmp->cachelog);
 	     discovery != NULL;
 	     discovery = (discovery_t *) hashbin_get_next(irlmp->cachelog)) {
 		if (pos-- == 0)
 			break;
 	}
-		
+
 	return discovery;
 }
 
 static void *discovery_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	spin_lock_irq(&irlmp->cachelog->hb_spinlock);
-        return *pos ? discovery_seq_idx(*pos - 1) : SEQ_START_TOKEN;
+	return *pos ? discovery_seq_idx(*pos - 1) : SEQ_START_TOKEN;
 }
 
 static void *discovery_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	++*pos;
-	return (v == SEQ_START_TOKEN) 
+	return (v == SEQ_START_TOKEN)
 		? (void *) hashbin_get_first(irlmp->cachelog)
 		: (void *) hashbin_get_next(irlmp->cachelog);
 }
@@ -357,9 +357,9 @@
 	else {
 		const discovery_t *discovery = v;
 
-		seq_printf(seq, "nickname: %s, hint: 0x%02x%02x", 
+		seq_printf(seq, "nickname: %s, hint: 0x%02x%02x",
 			   discovery->data.info,
-			   discovery->data.hints[0], 
+			   discovery->data.hints[0],
 			   discovery->data.hints[1]);
 #if 0
 		if ( discovery->data.hints[0] & HINT_PNP)
@@ -376,20 +376,20 @@
 			seq_puts(seq, "Fax ");
 		if ( discovery->data.hints[0] & HINT_LAN)
 			seq_puts(seq, "LAN Access ");
-		
+
 		if ( discovery->data.hints[1] & HINT_TELEPHONY)
 			seq_puts(seq, "Telephony ");
 		if ( discovery->data.hints[1] & HINT_FILE_SERVER)
-			seq_puts(seq, "File Server ");       
+			seq_puts(seq, "File Server ");
 		if ( discovery->data.hints[1] & HINT_COMM)
 			seq_puts(seq, "IrCOMM ");
 		if ( discovery->data.hints[1] & HINT_OBEX)
 			seq_puts(seq, "IrOBEX ");
-#endif		
+#endif
 		seq_printf(seq,", saddr: 0x%08x, daddr: 0x%08x\n\n",
 			       discovery->data.saddr,
 			       discovery->data.daddr);
-		
+
 		seq_putc(seq, '\n');
 	}
 	return 0;
@@ -409,7 +409,7 @@
 	return seq_open(file, &discovery_seq_ops);
 }
 
-struct file_operations discovery_seq_fops = {
+const struct file_operations discovery_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = discovery_seq_open,
 	.read           = seq_read,
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index ad6b6af..4749f8f 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      ircomm_core.c
  * Version:       1.0
  * Description:   IrCOMM service interface
@@ -8,29 +8,28 @@
  * Created at:    Sun Jun  6 20:37:34 1999
  * Modified at:   Tue Dec 21 13:26:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     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, 
+ *
+ *     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/module.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
@@ -49,14 +48,14 @@
 #include <net/irda/ircomm_core.h>
 
 static int __ircomm_close(struct ircomm_cb *self);
-static void ircomm_control_indication(struct ircomm_cb *self, 
+static void ircomm_control_indication(struct ircomm_cb *self,
 				      struct sk_buff *skb, int clen);
 
 #ifdef CONFIG_PROC_FS
 extern struct proc_dir_entry *proc_irda;
 static int ircomm_seq_open(struct inode *, struct file *);
 
-static struct file_operations ircomm_proc_fops = {
+static const struct file_operations ircomm_proc_fops = {
 	.owner		= THIS_MODULE,
 	.open           = ircomm_seq_open,
 	.read           = seq_read,
@@ -69,22 +68,22 @@
 
 static int __init ircomm_init(void)
 {
-	ircomm = hashbin_new(HB_LOCK); 
+	ircomm = hashbin_new(HB_LOCK);
 	if (ircomm == NULL) {
 		IRDA_ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
 		return -ENOMEM;
 	}
-	
+
 #ifdef CONFIG_PROC_FS
 	{ struct proc_dir_entry *ent;
 	ent = create_proc_entry("ircomm", 0, proc_irda);
-	if (ent) 
+	if (ent)
 		ent->proc_fops = &ircomm_proc_fops;
 	}
 #endif /* CONFIG_PROC_FS */
-	
+
 	IRDA_MESSAGE("IrCOMM protocol (Dag Brattli)\n");
-		
+
 	return 0;
 }
 
@@ -139,7 +138,7 @@
 
 	hashbin_insert(ircomm, (irda_queue_t *) self, line, NULL);
 
-	ircomm_next_state(self, IRCOMM_IDLE);	
+	ircomm_next_state(self, IRCOMM_IDLE);
 
 	return self;
 }
@@ -195,8 +194,8 @@
 	entry = hashbin_remove(ircomm, self->line, NULL);
 
 	IRDA_ASSERT(entry == self, return -1;);
-	
-        return __ircomm_close(self);
+
+	return __ircomm_close(self);
 }
 
 EXPORT_SYMBOL(ircomm_close);
@@ -206,9 +205,9 @@
  *
  *    Impl. of this function is differ from one of the reference. This
  *    function does discovery as well as sending connect request
- * 
+ *
  */
-int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel, 
+int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel,
 			   __u32 saddr, __u32 daddr, struct sk_buff *skb,
 			   __u8 service_type)
 {
@@ -243,20 +242,20 @@
 			       struct ircomm_info *info)
 {
 	int clen = 0;
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	/* Check if the packet contains data on the control channel */
 	if (skb->len > 0)
 		clen = skb->data[0];
-	
-	/* 
-	 * If there are any data hiding in the control channel, we must 
-	 * deliver it first. The side effect is that the control channel 
+
+	/*
+	 * If there are any data hiding in the control channel, we must
+	 * deliver it first. The side effect is that the control channel
 	 * will be removed from the skb
 	 */
 	if (self->notify.connect_indication)
-		self->notify.connect_indication(self->notify.instance, self, 
+		self->notify.connect_indication(self->notify.instance, self,
 						info->qos, info->max_data_size,
 						info->max_header_size, skb);
 	else {
@@ -282,7 +281,7 @@
 	ret = ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata, NULL);
 
 	return ret;
-}	
+}
 
 EXPORT_SYMBOL(ircomm_connect_response);
 
@@ -299,7 +298,7 @@
 
 	if (self->notify.connect_confirm )
 		self->notify.connect_confirm(self->notify.instance,
-					     self, info->qos, 
+					     self, info->qos,
 					     info->max_data_size,
 					     info->max_header_size, skb);
 	else {
@@ -322,7 +321,7 @@
 	IRDA_ASSERT(self != NULL, return -EFAULT;);
 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
 	IRDA_ASSERT(skb != NULL, return -EFAULT;);
-	
+
 	ret = ircomm_do_event(self, IRCOMM_DATA_REQUEST, skb, NULL);
 
 	return ret;
@@ -337,7 +336,7 @@
  *
  */
 void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
-{	
+{
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(skb->len > 0, return;);
@@ -363,9 +362,9 @@
 
 	clen = skb->data[0];
 
-	/* 
-	 * If there are any data hiding in the control channel, we must 
-	 * deliver it first. The side effect is that the control channel 
+	/*
+	 * If there are any data hiding in the control channel, we must
+	 * deliver it first. The side effect is that the control channel
 	 * will be removed from the skb
 	 */
 	if (clen > 0)
@@ -375,7 +374,7 @@
 	skb_pull(skb, clen+1);
 
 	if (skb->len)
-		ircomm_data_indication(self, skb);		
+		ircomm_data_indication(self, skb);
 	else {
 		IRDA_DEBUG(4, "%s(), data was control info only!\n",
 			   __FUNCTION__ );
@@ -391,13 +390,13 @@
 int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb)
 {
 	int ret;
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return -EFAULT;);
 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
 	IRDA_ASSERT(skb != NULL, return -EFAULT;);
-	
+
 	ret = ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb, NULL);
 
 	return ret;
@@ -411,10 +410,10 @@
  *    Data has arrived on the control channel
  *
  */
-static void ircomm_control_indication(struct ircomm_cb *self, 
+static void ircomm_control_indication(struct ircomm_cb *self,
 				      struct sk_buff *skb, int clen)
 {
-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	/* Use udata for delivering data on the control channel */
 	if (self->notify.udata_indication) {
@@ -427,8 +426,8 @@
 
 		/* Remove data channel from control channel */
 		skb_trim(ctrl_skb, clen+1);
-	
-		self->notify.udata_indication(self->notify.instance, self, 
+
+		self->notify.udata_indication(self->notify.instance, self,
 					      ctrl_skb);
 
 		/* Drop reference count -
@@ -455,7 +454,7 @@
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
 
-	ret = ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata, 
+	ret = ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata,
 			      &info);
 	return ret;
 }
@@ -472,7 +471,7 @@
 				  struct ircomm_info *info)
 {
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-       
+
 	IRDA_ASSERT(info != NULL, return;);
 
 	if (self->notify.disconnect_indication) {
@@ -486,7 +485,7 @@
 /*
  * Function ircomm_flow_request (self, flow)
  *
- *    
+ *
  *
  */
 void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow)
@@ -517,7 +516,7 @@
 	     self = (struct ircomm_cb *) hashbin_get_next(ircomm)) {
 		if (off++ == *pos)
 			break;
-		
+
 	}
 	return self;
 }
@@ -535,7 +534,7 @@
 }
 
 static int ircomm_seq_show(struct seq_file *seq, void *v)
-{ 	
+{
 	const struct ircomm_cb *self = v;
 
 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EINVAL; );
@@ -548,7 +547,7 @@
 	seq_printf(seq,
 		   " state: %s, slsap_sel: %#02x, dlsap_sel: %#02x, mode:",
 		   ircomm_state[ self->state],
-		   self->slsap_sel, self->dlsap_sel); 
+		   self->slsap_sel, self->dlsap_sel);
 
 	if(self->service_type & IRCOMM_3_WIRE_RAW)
 		seq_printf(seq, " 3-wire-raw");
diff --git a/net/irda/ircomm/ircomm_event.c b/net/irda/ircomm/ircomm_event.c
index 01f4e80..8ba4e59 100644
--- a/net/irda/ircomm/ircomm_event.c
+++ b/net/irda/ircomm/ircomm_event.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      ircomm_event.c
  * Version:       1.0
  * Description:   IrCOMM layer state machine
@@ -8,27 +8,26 @@
  * Created at:    Sun Jun  6 20:33:11 1999
  * Modified at:   Sun Dec 12 13:44:32 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     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, 
+ *
+ *     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/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 
@@ -41,13 +40,13 @@
 #include <net/irda/ircomm_core.h>
 #include <net/irda/ircomm_event.h>
 
-static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event,
 			     struct sk_buff *skb, struct ircomm_info *info);
-static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
 			      struct sk_buff *skb, struct ircomm_info *info);
-static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
 			      struct sk_buff *skb, struct ircomm_info *info);
-static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
 			     struct sk_buff *skb, struct ircomm_info *info);
 
 char *ircomm_state[] = {
@@ -60,26 +59,26 @@
 #ifdef CONFIG_IRDA_DEBUG
 static char *ircomm_event[] = {
 	"IRCOMM_CONNECT_REQUEST",
-        "IRCOMM_CONNECT_RESPONSE",
-        "IRCOMM_TTP_CONNECT_INDICATION",
+	"IRCOMM_CONNECT_RESPONSE",
+	"IRCOMM_TTP_CONNECT_INDICATION",
 	"IRCOMM_LMP_CONNECT_INDICATION",
-        "IRCOMM_TTP_CONNECT_CONFIRM",
+	"IRCOMM_TTP_CONNECT_CONFIRM",
 	"IRCOMM_LMP_CONNECT_CONFIRM",
 
-        "IRCOMM_LMP_DISCONNECT_INDICATION",
+	"IRCOMM_LMP_DISCONNECT_INDICATION",
 	"IRCOMM_TTP_DISCONNECT_INDICATION",
-        "IRCOMM_DISCONNECT_REQUEST",
+	"IRCOMM_DISCONNECT_REQUEST",
 
-        "IRCOMM_TTP_DATA_INDICATION",
+	"IRCOMM_TTP_DATA_INDICATION",
 	"IRCOMM_LMP_DATA_INDICATION",
-        "IRCOMM_DATA_REQUEST",
-        "IRCOMM_CONTROL_REQUEST",
-        "IRCOMM_CONTROL_INDICATION",
+	"IRCOMM_DATA_REQUEST",
+	"IRCOMM_CONTROL_REQUEST",
+	"IRCOMM_CONTROL_INDICATION",
 };
 #endif /* CONFIG_IRDA_DEBUG */
 
 static int (*state[])(struct ircomm_cb *self, IRCOMM_EVENT event,
-		      struct sk_buff *skb, struct ircomm_info *info) = 
+		      struct sk_buff *skb, struct ircomm_info *info) =
 {
 	ircomm_state_idle,
 	ircomm_state_waiti,
@@ -93,14 +92,14 @@
  *    IrCOMM is currently idle
  *
  */
-static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event,
 			     struct sk_buff *skb, struct ircomm_info *info)
 {
 	int ret = 0;
 
 	switch (event) {
 	case IRCOMM_CONNECT_REQUEST:
-		ircomm_next_state(self, IRCOMM_WAITI);		
+		ircomm_next_state(self, IRCOMM_WAITI);
 		ret = self->issue.connect_request(self, skb, info);
 		break;
 	case IRCOMM_TTP_CONNECT_INDICATION:
@@ -119,10 +118,10 @@
 /*
  * Function ircomm_state_waiti (self, event, skb)
  *
- *    The IrCOMM user has requested an IrCOMM connection to the remote 
+ *    The IrCOMM user has requested an IrCOMM connection to the remote
  *    device and is awaiting confirmation
  */
-static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
 			      struct sk_buff *skb, struct ircomm_info *info)
 {
 	int ret = 0;
@@ -152,8 +151,8 @@
  *    IrCOMM has received an incoming connection request and is awaiting
  *    response from the user
  */
-static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			      struct sk_buff *skb, struct ircomm_info *info) 
+static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
+			      struct sk_buff *skb, struct ircomm_info *info)
 {
 	int ret = 0;
 
@@ -185,7 +184,7 @@
  *    IrCOMM is connected to the peer IrCOMM device
  *
  */
-static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
 			     struct sk_buff *skb, struct ircomm_info *info)
 {
 	int ret = 0;
@@ -228,7 +227,7 @@
  *
  */
 int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event,
-		    struct sk_buff *skb, struct ircomm_info *info) 
+		    struct sk_buff *skb, struct ircomm_info *info)
 {
 	IRDA_DEBUG(4, "%s: state=%s, event=%s\n", __FUNCTION__ ,
 		   ircomm_state[self->state], ircomm_event[event]);
@@ -245,7 +244,7 @@
 void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state)
 {
 	self->state = state;
-	
-	IRDA_DEBUG(4, "%s: next state=%s, service type=%d\n", __FUNCTION__ , 
+
+	IRDA_DEBUG(4, "%s: next state=%s, service type=%d\n", __FUNCTION__ ,
 		   ircomm_state[self->state], self->service_type);
 }
diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c
index c8e0d89..55860ee 100644
--- a/net/irda/ircomm/ircomm_lmp.c
+++ b/net/irda/ircomm/ircomm_lmp.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      ircomm_lmp.c
  * Version:       1.0
  * Description:   Interface between IrCOMM and IrLMP
@@ -9,28 +9,27 @@
  * Modified at:   Sun Dec 12 13:44:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       Previous IrLPT work by Thomas Davis
- * 
+ *
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     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, 
+ *
+ *     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/sched.h>
 #include <linux/init.h>
 
 #include <net/irda/irda.h>
@@ -45,11 +44,11 @@
 /*
  * Function ircomm_lmp_connect_request (self, userdata)
  *
- *    
+ *
  *
  */
-static int ircomm_lmp_connect_request(struct ircomm_cb *self, 
-				      struct sk_buff *userdata, 
+static int ircomm_lmp_connect_request(struct ircomm_cb *self,
+				      struct sk_buff *userdata,
 				      struct ircomm_info *info)
 {
 	int ret = 0;
@@ -61,14 +60,14 @@
 		skb_get(userdata);
 
 	ret = irlmp_connect_request(self->lsap, info->dlsap_sel,
-				    info->saddr, info->daddr, NULL, userdata); 
+				    info->saddr, info->daddr, NULL, userdata);
 	return ret;
-}	
+}
 
 /*
  * Function ircomm_lmp_connect_response (self, skb)
  *
- *    
+ *
  *
  */
 static int ircomm_lmp_connect_response(struct ircomm_cb *self,
@@ -78,7 +77,7 @@
 	int ret;
 
 	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
-	
+
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
 		tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
@@ -88,8 +87,8 @@
 		/* Reserve space for MUX and LAP header */
 		skb_reserve(tx_skb, LMP_MAX_HEADER);
 	} else {
-		/*  
-		 *  Check that the client has reserved enough space for 
+		/*
+		 *  Check that the client has reserved enough space for
 		 *  headers
 		 */
 		IRDA_ASSERT(skb_headroom(userdata) >= LMP_MAX_HEADER,
@@ -105,22 +104,22 @@
 	return 0;
 }
 
-static int ircomm_lmp_disconnect_request(struct ircomm_cb *self, 
-					 struct sk_buff *userdata, 
+static int ircomm_lmp_disconnect_request(struct ircomm_cb *self,
+					 struct sk_buff *userdata,
 					 struct ircomm_info *info)
 {
-        struct sk_buff *tx_skb;
+	struct sk_buff *tx_skb;
 	int ret;
 
 	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
 
-        if (!userdata) {
+	if (!userdata) {
 		tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
 		if (!tx_skb)
 			return -ENOMEM;
-		
+
 		/*  Reserve space for MUX and LAP header */
-		skb_reserve(tx_skb, LMP_MAX_HEADER);		
+		skb_reserve(tx_skb, LMP_MAX_HEADER);
 		userdata = tx_skb;
 	} else {
 		/* Don't forget to refcount it - should be NULL anyway */
@@ -136,7 +135,7 @@
  * Function ircomm_lmp_flow_control (skb)
  *
  *    This function is called when a data frame we have sent to IrLAP has
- *    been deallocated. We do this to make sure we don't flood IrLAP with 
+ *    been deallocated. We do this to make sure we don't flood IrLAP with
  *    frames, since we are not using the IrTTP flow control mechanism
  */
 static void ircomm_lmp_flow_control(struct sk_buff *skb)
@@ -150,29 +149,29 @@
 	cb = (struct irda_skb_cb *) skb->cb;
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- 
-        line = cb->line;
+
+	line = cb->line;
 
 	self = (struct ircomm_cb *) hashbin_lock_find(ircomm, line, NULL);
-        if (!self) {
+	if (!self) {
 		IRDA_DEBUG(2, "%s(), didn't find myself\n", __FUNCTION__ );
-                return;
+		return;
 	}
 
-        IRDA_ASSERT(self != NULL, return;);
+	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
 
 	self->pkt_count--;
 
-        if ((self->pkt_count < 2) && (self->flow_status == FLOW_STOP)) {
-                IRDA_DEBUG(2, "%s(), asking TTY to start again!\n", __FUNCTION__ );
-                self->flow_status = FLOW_START;
-                if (self->notify.flow_indication)
-                        self->notify.flow_indication(self->notify.instance, 
+	if ((self->pkt_count < 2) && (self->flow_status == FLOW_STOP)) {
+		IRDA_DEBUG(2, "%s(), asking TTY to start again!\n", __FUNCTION__ );
+		self->flow_status = FLOW_START;
+		if (self->notify.flow_indication)
+			self->notify.flow_indication(self->notify.instance,
 						     self, FLOW_START);
-        }
+	}
 }
-    
+
 /*
  * Function ircomm_lmp_data_request (self, userdata)
  *
@@ -180,7 +179,7 @@
  *
  */
 static int ircomm_lmp_data_request(struct ircomm_cb *self,
-				   struct sk_buff *skb, 
+				   struct sk_buff *skb,
 				   int not_used)
 {
 	struct irda_skb_cb *cb;
@@ -189,8 +188,8 @@
 	IRDA_ASSERT(skb != NULL, return -1;);
 
 	cb = (struct irda_skb_cb *) skb->cb;
-	
-        cb->line = self->line;
+
+	cb->line = self->line;
 
 	IRDA_DEBUG(4, "%s(), sending frame\n", __FUNCTION__ );
 
@@ -199,13 +198,13 @@
 
 	skb->destructor = ircomm_lmp_flow_control;
 
-        if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) {
+	if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) {
 		IRDA_DEBUG(2, "%s(), asking TTY to slow down!\n", __FUNCTION__ );
-	        self->flow_status = FLOW_STOP;
-                if (self->notify.flow_indication)
-             	        self->notify.flow_indication(self->notify.instance, 
-				                     self, FLOW_STOP);
-        }
+		self->flow_status = FLOW_STOP;
+		if (self->notify.flow_indication)
+			self->notify.flow_indication(self->notify.instance,
+						     self, FLOW_STOP);
+	}
 	ret = irlmp_data_request(self->lsap, skb);
 	if (ret) {
 		IRDA_ERROR("%s(), failed\n", __FUNCTION__);
@@ -227,11 +226,11 @@
 	struct ircomm_cb *self = (struct ircomm_cb *) instance;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
 	IRDA_ASSERT(skb != NULL, return -1;);
-	
+
 	ircomm_do_event(self, IRCOMM_LMP_DATA_INDICATION, skb, NULL);
 
 	/* Drop reference count - see ircomm_tty_data_indication(). */
@@ -241,15 +240,15 @@
 }
 
 /*
- * Function ircomm_lmp_connect_confirm (instance, sap, qos, max_sdu_size, 
+ * Function ircomm_lmp_connect_confirm (instance, sap, qos, max_sdu_size,
  *                                       max_header_size, skb)
  *
  *    Connection has been confirmed by peer device
  *
  */
 static void ircomm_lmp_connect_confirm(void *instance, void *sap,
-				       struct qos_info *qos, 
-				       __u32 max_seg_size, 
+				       struct qos_info *qos,
+				       __u32 max_seg_size,
 				       __u8 max_header_size,
 				       struct sk_buff *skb)
 {
@@ -312,7 +311,7 @@
  *    Peer device has closed the connection, or the link went down for some
  *    other reason
  */
-static void ircomm_lmp_disconnect_indication(void *instance, void *sap, 
+static void ircomm_lmp_disconnect_indication(void *instance, void *sap,
 					     LM_REASON reason,
 					     struct sk_buff *skb)
 {
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c
index a39f573..01d7c9c 100644
--- a/net/irda/ircomm/ircomm_param.c
+++ b/net/irda/ircomm/ircomm_param.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      ircomm_param.c
  * Version:       1.0
  * Description:   Parameter handling for the IrCOMM protocol
@@ -8,27 +8,26 @@
  * Created at:    Mon Jun  7 10:25:11 1999
  * Modified at:   Sun Jan 30 14:32:03 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     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, 
+ *
+ *     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/sched.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 
@@ -41,23 +40,23 @@
 
 #include <net/irda/ircomm_param.h>
 
-static int ircomm_param_service_type(void *instance, irda_param_t *param, 
+static int ircomm_param_service_type(void *instance, irda_param_t *param,
 				     int get);
-static int ircomm_param_port_type(void *instance, irda_param_t *param, 
+static int ircomm_param_port_type(void *instance, irda_param_t *param,
 				  int get);
-static int ircomm_param_port_name(void *instance, irda_param_t *param, 
+static int ircomm_param_port_name(void *instance, irda_param_t *param,
 				  int get);
-static int ircomm_param_service_type(void *instance, irda_param_t *param, 
+static int ircomm_param_service_type(void *instance, irda_param_t *param,
 				     int get);
-static int ircomm_param_data_rate(void *instance, irda_param_t *param, 
+static int ircomm_param_data_rate(void *instance, irda_param_t *param,
 				  int get);
-static int ircomm_param_data_format(void *instance, irda_param_t *param, 
+static int ircomm_param_data_format(void *instance, irda_param_t *param,
 				    int get);
-static int ircomm_param_flow_control(void *instance, irda_param_t *param, 
+static int ircomm_param_flow_control(void *instance, irda_param_t *param,
 				     int get);
 static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get);
 static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get);
-static int ircomm_param_line_status(void *instance, irda_param_t *param, 
+static int ircomm_param_line_status(void *instance, irda_param_t *param,
 				    int get);
 static int ircomm_param_dte(void *instance, irda_param_t *param, int get);
 static int ircomm_param_dce(void *instance, irda_param_t *param, int get);
@@ -85,7 +84,7 @@
 static pi_major_info_t pi_major_call_table[] = {
 	{ pi_minor_call_table_common,  3 },
 	{ pi_minor_call_table_non_raw, 6 },
- 	{ pi_minor_call_table_9_wire,  3 }
+	{ pi_minor_call_table_9_wire,  3 }
 /* 	{ pi_minor_call_table_centronics }  */
 };
 
@@ -119,20 +118,20 @@
 
 	spin_lock_irqsave(&self->spinlock, flags);
 
-	skb = self->ctrl_skb;	
+	skb = self->ctrl_skb;
 	if (!skb) {
 		skb = alloc_skb(256, GFP_ATOMIC);
 		if (!skb) {
 			spin_unlock_irqrestore(&self->spinlock, flags);
 			return -ENOMEM;
 		}
-		
+
 		skb_reserve(skb, self->max_header_size);
 		self->ctrl_skb = skb;
 	}
-	/* 
+	/*
 	 * Inserting is a little bit tricky since we don't know how much
-	 * room we will need. But this should hopefully work OK 
+	 * room we will need. But this should hopefully work OK
 	 */
 	count = irda_param_insert(self, pi, skb->tail, skb_tailroom(skb),
 				  &ircomm_param_info);
@@ -162,7 +161,7 @@
  *    query and then the remote device sends its initial parameters
  *
  */
-static int ircomm_param_service_type(void *instance, irda_param_t *param, 
+static int ircomm_param_service_type(void *instance, irda_param_t *param,
 				     int get)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
@@ -179,7 +178,7 @@
 	/* Find all common service types */
 	service_type &= self->service_type;
 	if (!service_type) {
-		IRDA_DEBUG(2, 
+		IRDA_DEBUG(2,
 			   "%s(), No common service type to use!\n", __FUNCTION__ );
 		return -1;
 	}
@@ -198,12 +197,12 @@
 	else if (service_type & IRCOMM_3_WIRE_RAW)
 		self->settings.service_type = IRCOMM_3_WIRE_RAW;
 
-	IRDA_DEBUG(0, "%s(), resulting service type=0x%02x\n", __FUNCTION__ , 
+	IRDA_DEBUG(0, "%s(), resulting service type=0x%02x\n", __FUNCTION__ ,
 		   self->settings.service_type);
 
-	/* 
+	/*
 	 * Now the line is ready for some communication. Check if we are a
-         * server, and send over some initial parameters.
+	 * server, and send over some initial parameters.
 	 * Client do it in ircomm_tty_state_setup().
 	 * Note : we may get called from ircomm_tty_getvalue_confirm(),
 	 * therefore before we even have open any socket. And self->client
@@ -235,13 +234,13 @@
 
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
-	
+
 	if (get)
 		param->pv.i = IRCOMM_SERIAL;
 	else {
 		self->settings.port_type = (__u8) param->pv.i;
 
-		IRDA_DEBUG(0, "%s(), port type=%d\n", __FUNCTION__ , 
+		IRDA_DEBUG(0, "%s(), port type=%d\n", __FUNCTION__ ,
 			   self->settings.port_type);
 	}
 	return 0;
@@ -256,7 +255,7 @@
 static int ircomm_param_port_name(void *instance, irda_param_t *param, int get)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
@@ -279,7 +278,7 @@
 static int ircomm_param_data_rate(void *instance, irda_param_t *param, int get)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
@@ -287,7 +286,7 @@
 		param->pv.i = self->settings.data_rate;
 	else
 		self->settings.data_rate = param->pv.i;
-	
+
 	IRDA_DEBUG(2, "%s(), data rate = %d\n", __FUNCTION__ , param->pv.i);
 
 	return 0;
@@ -299,7 +298,7 @@
  *    Exchange data format to be used in this settings
  *
  */
-static int ircomm_param_data_format(void *instance, irda_param_t *param, 
+static int ircomm_param_data_format(void *instance, irda_param_t *param,
 				    int get)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
@@ -311,7 +310,7 @@
 		param->pv.i = self->settings.data_format;
 	else
 		self->settings.data_format = (__u8) param->pv.i;
-	
+
 	return 0;
 }
 
@@ -321,14 +320,14 @@
  *    Exchange flow control settings to be used in this settings
  *
  */
-static int ircomm_param_flow_control(void *instance, irda_param_t *param, 
+static int ircomm_param_flow_control(void *instance, irda_param_t *param,
 				     int get)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
 
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
-	
+
 	if (get)
 		param->pv.i = self->settings.flow_control;
 	else
@@ -351,7 +350,7 @@
 
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
-	
+
 	if (get) {
 		param->pv.i = self->settings.xonxoff[0];
 		param->pv.i |= self->settings.xonxoff[1] << 8;
@@ -360,7 +359,7 @@
 		self->settings.xonxoff[1] = (__u16) param->pv.i >> 8;
 	}
 
-	IRDA_DEBUG(0, "%s(), XON/XOFF = 0x%02x,0x%02x\n", __FUNCTION__ , 
+	IRDA_DEBUG(0, "%s(), XON/XOFF = 0x%02x,0x%02x\n", __FUNCTION__ ,
 		   param->pv.i & 0xff, param->pv.i >> 8);
 
 	return 0;
@@ -378,7 +377,7 @@
 
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
-	
+
 	if (get) {
 		param->pv.i = self->settings.enqack[0];
 		param->pv.i |= self->settings.enqack[1] << 8;
@@ -396,10 +395,10 @@
 /*
  * Function ircomm_param_line_status (self, param)
  *
- *    
+ *
  *
  */
-static int ircomm_param_line_status(void *instance, irda_param_t *param, 
+static int ircomm_param_line_status(void *instance, irda_param_t *param,
 				    int get)
 {
 	IRDA_DEBUG(2, "%s(), not impl.\n", __FUNCTION__ );
@@ -427,7 +426,7 @@
 		dte = (__u8) param->pv.i;
 
 		self->settings.dce = 0;
-				
+
 		if (dte & IRCOMM_DELTA_DTR)
 			self->settings.dce |= (IRCOMM_DELTA_DSR|
 					      IRCOMM_DELTA_RI |
@@ -436,7 +435,7 @@
 			self->settings.dce |= (IRCOMM_DSR|
 					      IRCOMM_RI |
 					      IRCOMM_CD);
-		
+
 		if (dte & IRCOMM_DELTA_RTS)
 			self->settings.dce |= IRCOMM_DELTA_CTS;
 		if (dte & IRCOMM_RTS)
@@ -455,7 +454,7 @@
 /*
  * Function ircomm_param_dce (instance, param)
  *
- *    
+ *
  *
  */
 static int ircomm_param_dce(void *instance, irda_param_t *param, int get)
diff --git a/net/irda/ircomm/ircomm_ttp.c b/net/irda/ircomm/ircomm_ttp.c
index d98bf35..712eafd 100644
--- a/net/irda/ircomm/ircomm_ttp.c
+++ b/net/irda/ircomm/ircomm_ttp.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      ircomm_ttp.c
  * Version:       1.0
  * Description:   Interface between IrCOMM and IrTTP
@@ -8,28 +8,27 @@
  * Created at:    Sun Jun  6 20:48:27 1999
  * Modified at:   Mon Dec 13 11:35:13 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     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, 
+ *
+ *     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/sched.h>
 #include <linux/init.h>
 
 #include <net/irda/irda.h>
@@ -43,8 +42,8 @@
 static int ircomm_ttp_data_indication(void *instance, void *sap,
 				      struct sk_buff *skb);
 static void ircomm_ttp_connect_confirm(void *instance, void *sap,
-				       struct qos_info *qos, 
-				       __u32 max_sdu_size, 
+				       struct qos_info *qos,
+				       __u32 max_sdu_size,
 				       __u8 max_header_size,
 				       struct sk_buff *skb);
 static void ircomm_ttp_connect_indication(void *instance, void *sap,
@@ -54,25 +53,25 @@
 					  struct sk_buff *skb);
 static void ircomm_ttp_flow_indication(void *instance, void *sap,
 				       LOCAL_FLOW cmd);
-static void ircomm_ttp_disconnect_indication(void *instance, void *sap, 
+static void ircomm_ttp_disconnect_indication(void *instance, void *sap,
 					     LM_REASON reason,
 					     struct sk_buff *skb);
 static int ircomm_ttp_data_request(struct ircomm_cb *self,
-				   struct sk_buff *skb, 
+				   struct sk_buff *skb,
 				   int clen);
-static int ircomm_ttp_connect_request(struct ircomm_cb *self, 
-				      struct sk_buff *userdata, 
+static int ircomm_ttp_connect_request(struct ircomm_cb *self,
+				      struct sk_buff *userdata,
 				      struct ircomm_info *info);
 static int ircomm_ttp_connect_response(struct ircomm_cb *self,
 				       struct sk_buff *userdata);
-static int ircomm_ttp_disconnect_request(struct ircomm_cb *self, 
-					 struct sk_buff *userdata, 
+static int ircomm_ttp_disconnect_request(struct ircomm_cb *self,
+					 struct sk_buff *userdata,
 					 struct ircomm_info *info);
 
 /*
  * Function ircomm_open_tsap (self)
  *
- *    
+ *
  *
  */
 int ircomm_open_tsap(struct ircomm_cb *self)
@@ -113,11 +112,11 @@
 /*
  * Function ircomm_ttp_connect_request (self, userdata)
  *
- *    
+ *
  *
  */
-static int ircomm_ttp_connect_request(struct ircomm_cb *self, 
-				      struct sk_buff *userdata, 
+static int ircomm_ttp_connect_request(struct ircomm_cb *self,
+				      struct sk_buff *userdata,
 				      struct ircomm_info *info)
 {
 	int ret = 0;
@@ -129,16 +128,16 @@
 		skb_get(userdata);
 
 	ret = irttp_connect_request(self->tsap, info->dlsap_sel,
-				    info->saddr, info->daddr, NULL, 
-				    TTP_SAR_DISABLE, userdata); 
+				    info->saddr, info->daddr, NULL,
+				    TTP_SAR_DISABLE, userdata);
 
 	return ret;
-}	
+}
 
 /*
  * Function ircomm_ttp_connect_response (self, skb)
  *
- *    
+ *
  *
  */
 static int ircomm_ttp_connect_response(struct ircomm_cb *self,
@@ -147,7 +146,7 @@
 	int ret;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	/* Don't forget to refcount it - should be NULL anyway */
 	if(userdata)
 		skb_get(userdata);
@@ -160,14 +159,14 @@
 /*
  * Function ircomm_ttp_data_request (self, userdata)
  *
- *    Send IrCOMM data to IrTTP layer. Currently we do not try to combine 
- *    control data with pure data, so they will be sent as separate frames. 
+ *    Send IrCOMM data to IrTTP layer. Currently we do not try to combine
+ *    control data with pure data, so they will be sent as separate frames.
  *    Should not be a big problem though, since control frames are rare. But
- *    some of them are sent after connection establishment, so this can 
+ *    some of them are sent after connection establishment, so this can
  *    increase the latency a bit.
  */
 static int ircomm_ttp_data_request(struct ircomm_cb *self,
-				   struct sk_buff *skb, 
+				   struct sk_buff *skb,
 				   int clen)
 {
 	int ret;
@@ -176,7 +175,7 @@
 
 	IRDA_DEBUG(2, "%s(), clen=%d\n", __FUNCTION__ , clen);
 
-	/* 
+	/*
 	 * Insert clen field, currently we either send data only, or control
 	 * only frames, to make things easier and avoid queueing
 	 */
@@ -210,7 +209,7 @@
 	struct ircomm_cb *self = (struct ircomm_cb *) instance;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
 	IRDA_ASSERT(skb != NULL, return -1;);
@@ -224,8 +223,8 @@
 }
 
 static void ircomm_ttp_connect_confirm(void *instance, void *sap,
-				       struct qos_info *qos, 
-				       __u32 max_sdu_size, 
+				       struct qos_info *qos,
+				       __u32 max_sdu_size,
 				       __u8 max_header_size,
 				       struct sk_buff *skb)
 {
@@ -261,7 +260,7 @@
  * Function ircomm_ttp_connect_indication (instance, sap, qos, max_sdu_size,
  *                                         max_header_size, skb)
  *
- *    
+ *
  *
  */
 static void ircomm_ttp_connect_indication(void *instance, void *sap,
@@ -301,11 +300,11 @@
 /*
  * Function ircomm_ttp_disconnect_request (self, userdata, info)
  *
- *    
+ *
  *
  */
-static int ircomm_ttp_disconnect_request(struct ircomm_cb *self, 
-					 struct sk_buff *userdata, 
+static int ircomm_ttp_disconnect_request(struct ircomm_cb *self,
+					 struct sk_buff *userdata,
 					 struct ircomm_info *info)
 {
 	int ret;
@@ -322,10 +321,10 @@
 /*
  * Function ircomm_ttp_disconnect_indication (instance, sap, reason, skb)
  *
- *    
+ *
  *
  */
-static void ircomm_ttp_disconnect_indication(void *instance, void *sap, 
+static void ircomm_ttp_disconnect_indication(void *instance, void *sap,
 					     LM_REASON reason,
 					     struct sk_buff *skb)
 {
@@ -361,7 +360,7 @@
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
-	
+
 	if (self->notify.flow_indication)
 		self->notify.flow_indication(self->notify.instance, self, cmd);
 }
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 262bda8..3d241e4 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      ircomm_tty.c
  * Version:       1.0
  * Description:   IrCOMM serial TTY driver
@@ -9,25 +9,25 @@
  * Modified at:   Wed Feb 23 00:09:02 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       serial.c and previous IrCOMM work by Takahide Higuchi
- * 
+ *
  *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     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, 
+ *
+ *     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/init.h>
@@ -69,7 +69,7 @@
 				      struct sk_buff *skb);
 static int ircomm_tty_control_indication(void *instance, void *sap,
 					 struct sk_buff *skb);
-static void ircomm_tty_flow_indication(void *instance, void *sap, 
+static void ircomm_tty_flow_indication(void *instance, void *sap,
 				       LOCAL_FLOW cmd);
 #ifdef CONFIG_PROC_FS
 static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
@@ -113,7 +113,7 @@
 	driver = alloc_tty_driver(IRCOMM_TTY_PORTS);
 	if (!driver)
 		return -ENOMEM;
-	ircomm_tty = hashbin_new(HB_LOCK); 
+	ircomm_tty = hashbin_new(HB_LOCK);
 	if (ircomm_tty == NULL) {
 		IRDA_ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
 		put_tty_driver(driver);
@@ -163,11 +163,11 @@
 {
 	int ret;
 
-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	
+	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	ret = tty_unregister_driver(driver);
-        if (ret) {
-                IRDA_ERROR("%s(), failed to unregister driver\n",
+	if (ret) {
+		IRDA_ERROR("%s(), failed to unregister driver\n",
 			   __FUNCTION__);
 		return;
 	}
@@ -179,7 +179,7 @@
 /*
  * Function ircomm_startup (self)
  *
- *    
+ *
  *
  */
 static int ircomm_tty_startup(struct ircomm_tty_cb *self)
@@ -203,17 +203,17 @@
 	/* These callbacks we must handle ourselves */
 	notify.data_indication       = ircomm_tty_data_indication;
 	notify.udata_indication      = ircomm_tty_control_indication;
- 	notify.flow_indication       = ircomm_tty_flow_indication;
+	notify.flow_indication       = ircomm_tty_flow_indication;
 
 	/* Use the ircomm_tty interface for these ones */
- 	notify.disconnect_indication = ircomm_tty_disconnect_indication;
+	notify.disconnect_indication = ircomm_tty_disconnect_indication;
 	notify.connect_confirm       = ircomm_tty_connect_confirm;
- 	notify.connect_indication    = ircomm_tty_connect_indication;
+	notify.connect_indication    = ircomm_tty_connect_indication;
 	strlcpy(notify.name, "ircomm_tty", sizeof(notify.name));
 	notify.instance = self;
 
 	if (!self->ircomm) {
-		self->ircomm = ircomm_open(&notify, self->service_type, 
+		self->ircomm = ircomm_open(&notify, self->service_type,
 					   self->line);
 	}
 	if (!self->ircomm)
@@ -237,10 +237,10 @@
 /*
  * Function ircomm_block_til_ready (self, filp)
  *
- *    
+ *
  *
  */
-static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, 
+static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
 				      struct file *filp)
 {
 	DECLARE_WAITQUEUE(wait, current);
@@ -248,7 +248,7 @@
 	int		do_clocal = 0, extra_count = 0;
 	unsigned long	flags;
 	struct tty_struct *tty;
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	tty = self->tty;
@@ -256,7 +256,7 @@
 	/*
 	 * If non-blocking mode is set, or the port is not enabled,
 	 * then make the check up front and then exit.
-	 */	
+	 */
 	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
 		/* nonblock mode is set or port is not enabled */
 		self->flags |= ASYNC_NORMAL_ACTIVE;
@@ -268,17 +268,17 @@
 		IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __FUNCTION__ );
 		do_clocal = 1;
 	}
-	
+
 	/* Wait for carrier detect and the line to become
 	 * free (i.e., not in use by the callout).  While we are in
 	 * this loop, self->open_count is dropped by one, so that
 	 * mgsl_close() knows when to free things.  We restore it upon
 	 * exit, either normal or abnormal.
 	 */
-	 
+
 	retval = 0;
 	add_wait_queue(&self->open_wait, &wait);
-	
+
 	IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
 	      __FILE__,__LINE__, tty->driver->name, self->open_count );
 
@@ -290,7 +290,7 @@
 	}
 	spin_unlock_irqrestore(&self->spinlock, flags);
 	self->blocked_open++;
-	
+
 	while (1) {
 		if (tty->termios->c_cflag & CBAUD) {
 			/* Here, we use to lock those two guys, but
@@ -298,45 +298,45 @@
 			 * I don't see the point (and I see the deadlock).
 			 * Jean II */
 			self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR;
-		 	
+
 			ircomm_param_request(self, IRCOMM_DTE, TRUE);
 		}
-		
+
 		current->state = TASK_INTERRUPTIBLE;
-		
+
 		if (tty_hung_up_p(filp) ||
 		    !test_bit(ASYNC_B_INITIALIZED, &self->flags)) {
 			retval = (self->flags & ASYNC_HUP_NOTIFY) ?
 					-EAGAIN : -ERESTARTSYS;
 			break;
 		}
-		
-		/*  
+
+		/*
 		 * Check if link is ready now. Even if CLOCAL is
 		 * specified, we cannot return before the IrCOMM link is
-		 * ready 
+		 * ready
 		 */
- 		if (!test_bit(ASYNC_B_CLOSING, &self->flags) &&
- 		    (do_clocal || (self->settings.dce & IRCOMM_CD)) &&
+		if (!test_bit(ASYNC_B_CLOSING, &self->flags) &&
+		    (do_clocal || (self->settings.dce & IRCOMM_CD)) &&
 		    self->state == IRCOMM_TTY_READY)
 		{
- 			break;
+			break;
 		}
-			
+
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
 			break;
 		}
-		
+
 		IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n",
 		      __FILE__,__LINE__, tty->driver->name, self->open_count );
-		
+
 		schedule();
 	}
-	
+
 	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&self->open_wait, &wait);
-	
+
 	if (extra_count) {
 		/* ++ is not atomic, so this should be protected - Jean II */
 		spin_lock_irqsave(&self->spinlock, flags);
@@ -344,14 +344,14 @@
 		spin_unlock_irqrestore(&self->spinlock, flags);
 	}
 	self->blocked_open--;
-	
+
 	IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
 	      __FILE__,__LINE__, tty->driver->name, self->open_count);
-			 
+
 	if (!retval)
 		self->flags |= ASYNC_NORMAL_ACTIVE;
-		
-	return retval;	
+
+	return retval;
 }
 
 /*
@@ -384,7 +384,7 @@
 			IRDA_ERROR("%s(), kmalloc failed!\n", __FUNCTION__);
 			return -ENOMEM;
 		}
-		
+
 		self->magic = IRCOMM_TTY_MAGIC;
 		self->flow = FLOW_STOP;
 
@@ -398,13 +398,13 @@
 		/* Init some important stuff */
 		init_timer(&self->watchdog_timer);
 		init_waitqueue_head(&self->open_wait);
- 		init_waitqueue_head(&self->close_wait);
+		init_waitqueue_head(&self->close_wait);
 		spin_lock_init(&self->spinlock);
 
-		/* 
+		/*
 		 * Force TTY into raw mode by default which is usually what
 		 * we want for IrCOMM and IrLPT. This way applications will
-		 * not have to twiddle with printcap etc.  
+		 * not have to twiddle with printcap etc.
 		 */
 		tty->termios->c_iflag = 0;
 		tty->termios->c_oflag = 0;
@@ -420,7 +420,7 @@
 	self->tty = tty;
 	spin_unlock_irqrestore(&self->spinlock, flags);
 
-	IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __FUNCTION__ , tty->driver->name, 
+	IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __FUNCTION__ , tty->driver->name,
 		   self->line, self->open_count);
 
 	/* Not really used by us, but lets do it anyway */
@@ -473,7 +473,7 @@
 
 	ret = ircomm_tty_block_til_ready(self, filp);
 	if (ret) {
-		IRDA_DEBUG(2, 
+		IRDA_DEBUG(2,
 		      "%s(), returning after block_til_ready with %d\n", __FUNCTION__ ,
 		      ret);
 
@@ -519,7 +519,7 @@
 		 * serial port won't be shutdown.
 		 */
 		IRDA_DEBUG(0, "%s(), bad serial port count; "
-			   "tty->count is 1, state->count is %d\n", __FUNCTION__ , 
+			   "tty->count is 1, state->count is %d\n", __FUNCTION__ ,
 			   self->open_count);
 		self->open_count = 1;
 	}
@@ -546,7 +546,7 @@
 	spin_unlock_irqrestore(&self->spinlock, flags);
 
 	/*
-	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * Now we wait for the transmit buffer to clear; and we notify
 	 * the line discipline to only process XON/XOFF characters.
 	 */
 	tty->closing = 1;
@@ -576,7 +576,7 @@
 /*
  * Function ircomm_tty_flush_buffer (tty)
  *
- *    
+ *
  *
  */
 static void ircomm_tty_flush_buffer(struct tty_struct *tty)
@@ -586,9 +586,9 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
-	/* 
-	 * Let do_softint() do this to avoid race condition with 
-	 * do_softint() ;-) 
+	/*
+	 * Let do_softint() do this to avoid race condition with
+	 * do_softint() ;-)
 	 */
 	schedule_work(&self->tqueue);
 }
@@ -597,7 +597,7 @@
  * Function ircomm_tty_do_softint (work)
  *
  *    We use this routine to give the write wakeup to the user at at a
- *    safe time (as fast as possible after write have completed). This 
+ *    safe time (as fast as possible after write have completed). This
  *    can be compared to the Tx interrupt.
  */
 static void ircomm_tty_do_softint(struct work_struct *work)
@@ -638,7 +638,7 @@
 
 	/* Unlink transmit buffer */
 	spin_lock_irqsave(&self->spinlock, flags);
-	
+
 	skb = self->tx_skb;
 	self->tx_skb = NULL;
 
@@ -650,9 +650,9 @@
 		/* Drop reference count - see ircomm_ttp_data_request(). */
 		dev_kfree_skb(skb);
 	}
-		
+
 	/* Check if user (still) wants to be waken up */
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && 
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 	    tty->ldisc.write_wakeup)
 	{
 		(tty->ldisc.write_wakeup)(tty);
@@ -717,12 +717,12 @@
 	/* Fetch current transmit buffer */
 	skb = self->tx_skb;
 
-	/*  
+	/*
 	 * Send out all the data we get, possibly as multiple fragmented
 	 * frames, but this will only happen if the data is larger than the
 	 * max data size. The normal case however is just the opposite, and
 	 * this function may be called multiple times, and will then actually
-	 * defragment the data and send it out as one packet as soon as 
+	 * defragment the data and send it out as one packet as soon as
 	 * possible, but at a safer point in time
 	 */
 	while (count) {
@@ -731,16 +731,16 @@
 		/* Adjust data size to the max data size */
 		if (size > self->max_data_size)
 			size = self->max_data_size;
-		
-		/* 
+
+		/*
 		 * Do we already have a buffer ready for transmit, or do
-		 * we need to allocate a new frame 
+		 * we need to allocate a new frame
 		 */
-		if (skb) {			
-			/* 
-			 * Any room for more data at the end of the current 
+		if (skb) {
+			/*
+			 * Any room for more data at the end of the current
 			 * transmit buffer? Cannot use skb_tailroom, since
-			 * dev_alloc_skb gives us a larger skb than we 
+			 * dev_alloc_skb gives us a larger skb than we
 			 * requested
 			 * Note : use tx_data_size, because max_data_size
 			 * may have changed and we don't want to overwrite
@@ -751,8 +751,8 @@
 				if (size > tailroom)
 					size = tailroom;
 			} else {
-				/* 
-				 * Current transmit frame is full, so break 
+				/*
+				 * Current transmit frame is full, so break
 				 * out, so we can send it as soon as possible
 				 */
 				break;
@@ -782,15 +782,15 @@
 
 	spin_unlock_irqrestore(&self->spinlock, flags);
 
-	/*     
+	/*
 	 * Schedule a new thread which will transmit the frame as soon
 	 * as possible, but at a safe point in time. We do this so the
 	 * "user" can give us data multiple times, as PPP does (because of
 	 * its 256 byte tx buffer). We will then defragment and send out
-	 * all this data as one single packet.  
+	 * all this data as one single packet.
 	 */
 	schedule_work(&self->tqueue);
-	
+
 	return len;
 }
 
@@ -846,7 +846,7 @@
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 	unsigned long orig_jiffies, poll_time;
 	unsigned long flags;
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return;);
@@ -876,7 +876,7 @@
  *
  *    This routine notifies the tty driver that input buffers for the line
  *    discipline are close to full, and it should somehow signal that no
- *    more characters should be sent to the tty.  
+ *    more characters should be sent to the tty.
  */
 static void ircomm_tty_throttle(struct tty_struct *tty)
 {
@@ -890,16 +890,16 @@
 	/* Software flow control? */
 	if (I_IXOFF(tty))
 		ircomm_tty_send_xchar(tty, STOP_CHAR(tty));
-	
+
 	/* Hardware flow control? */
 	if (tty->termios->c_cflag & CRTSCTS) {
 		self->settings.dte &= ~IRCOMM_RTS;
 		self->settings.dte |= IRCOMM_DELTA_RTS;
-	
+
 		ircomm_param_request(self, IRCOMM_DTE, TRUE);
 	}
 
-        ircomm_flow_request(self->ircomm, FLOW_STOP);
+	ircomm_flow_request(self->ircomm, FLOW_STOP);
 }
 
 /*
@@ -930,7 +930,7 @@
 		ircomm_param_request(self, IRCOMM_DTE, TRUE);
 		IRDA_DEBUG(1, "%s(), FLOW_START\n", __FUNCTION__ );
 	}
-        ircomm_flow_request(self->ircomm, FLOW_START);
+	ircomm_flow_request(self->ircomm, FLOW_START);
 }
 
 /*
@@ -975,7 +975,7 @@
 	spin_lock_irqsave(&self->spinlock, flags);
 
 	del_timer(&self->watchdog_timer);
-	
+
 	/* Free parameter buffer */
 	if (self->ctrl_skb) {
 		dev_kfree_skb(self->ctrl_skb);
@@ -1001,7 +1001,7 @@
  *
  *    This routine notifies the tty driver that it should hangup the tty
  *    device.
- * 
+ *
  */
 static void ircomm_tty_hangup(struct tty_struct *tty)
 {
@@ -1044,7 +1044,7 @@
  * Function ircomm_tty_start (tty)
  *
  *    This routine notifies the tty driver that it resume sending
- *    characters to the tty device.  
+ *    characters to the tty device.
  */
 void ircomm_tty_start(struct tty_struct *tty)
 {
@@ -1057,9 +1057,9 @@
  * Function ircomm_tty_stop (tty)
  *
  *     This routine notifies the tty driver that it should stop outputting
- *     characters to the tty device. 
+ *     characters to the tty device.
  */
-static void ircomm_tty_stop(struct tty_struct *tty) 
+static void ircomm_tty_stop(struct tty_struct *tty)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 
@@ -1094,14 +1094,14 @@
 		/*wake_up_interruptible(&self->delta_msr_wait);*/
 	}
 	if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
-		IRDA_DEBUG(2, 
+		IRDA_DEBUG(2,
 			   "%s(), ircomm%d CD now %s...\n", __FUNCTION__ , self->line,
 			   (status & IRCOMM_CD) ? "on" : "off");
 
 		if (status & IRCOMM_CD) {
 			wake_up_interruptible(&self->open_wait);
 		} else {
-			IRDA_DEBUG(2, 
+			IRDA_DEBUG(2,
 				   "%s(), Doing serial hangup..\n", __FUNCTION__ );
 			if (tty)
 				tty_hangup(tty);
@@ -1113,10 +1113,10 @@
 	if (self->flags & ASYNC_CTS_FLOW) {
 		if (tty->hw_stopped) {
 			if (status & IRCOMM_CTS) {
-				IRDA_DEBUG(2, 
+				IRDA_DEBUG(2,
 					   "%s(), CTS tx start...\n", __FUNCTION__ );
 				tty->hw_stopped = 0;
-				
+
 				/* Wake up processes blocked on open */
 				wake_up_interruptible(&self->open_wait);
 
@@ -1125,7 +1125,7 @@
 			}
 		} else {
 			if (!(status & IRCOMM_CTS)) {
-				IRDA_DEBUG(2, 
+				IRDA_DEBUG(2,
 					   "%s(), CTS tx stop...\n", __FUNCTION__ );
 				tty->hw_stopped = 1;
 			}
@@ -1145,7 +1145,7 @@
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 	IRDA_ASSERT(skb != NULL, return -1;);
@@ -1155,10 +1155,10 @@
 		return 0;
 	}
 
-	/* 
+	/*
 	 * If we receive data when hardware is stopped then something is wrong.
 	 * We try to poll the peers line settings to check if we are up todate.
-	 * Devices like WinCE can do this, and since they don't send any 
+	 * Devices like WinCE can do this, and since they don't send any
 	 * params, we can just as well declare the hardware for running.
 	 */
 	if (self->tty->hw_stopped && (self->flow == FLOW_START)) {
@@ -1170,9 +1170,9 @@
 		ircomm_tty_link_established(self);
 	}
 
-	/* 
+	/*
 	 * Just give it over to the line discipline. There is no need to
-	 * involve the flip buffers, since we are not running in an interrupt 
+	 * involve the flip buffers, since we are not running in an interrupt
 	 * handler
 	 */
 	self->tty->ldisc.receive_buf(self->tty, skb->data, NULL, skb->len);
@@ -1195,14 +1195,14 @@
 	int clen;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 	IRDA_ASSERT(skb != NULL, return -1;);
 
 	clen = skb->data[0];
 
-	irda_param_extract_all(self, skb->data+1, IRDA_MIN(skb->len-1, clen), 
+	irda_param_extract_all(self, skb->data+1, IRDA_MIN(skb->len-1, clen),
 			       &ircomm_param_info);
 
 	/* No need to kfree_skb - see ircomm_control_indication() */
@@ -1217,7 +1217,7 @@
  *    transmission of data. We just mark the hardware as stopped, and wait
  *    for IrTTP to notify us that things are OK again.
  */
-static void ircomm_tty_flow_indication(void *instance, void *sap, 
+static void ircomm_tty_flow_indication(void *instance, void *sap,
 				       LOCAL_FLOW cmd)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
@@ -1247,7 +1247,7 @@
 
 static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf)
 {
-        int  ret=0;
+	int  ret=0;
 
 	ret += sprintf(buf+ret, "State: %s\n", ircomm_tty_state[self->state]);
 
@@ -1260,37 +1260,37 @@
 		ret += sprintf(buf+ret, "3_WIRE_RAW");
 	else
 		ret += sprintf(buf+ret, "No common service type!\n");
-        ret += sprintf(buf+ret, "\n");
+	ret += sprintf(buf+ret, "\n");
 
 	ret += sprintf(buf+ret, "Port name: %s\n", self->settings.port_name);
 
-	ret += sprintf(buf+ret, "DTE status: ");	
-        if (self->settings.dte & IRCOMM_RTS)
-                ret += sprintf(buf+ret, "RTS|");
-        if (self->settings.dte & IRCOMM_DTR)
-                ret += sprintf(buf+ret, "DTR|");
+	ret += sprintf(buf+ret, "DTE status: ");
+	if (self->settings.dte & IRCOMM_RTS)
+		ret += sprintf(buf+ret, "RTS|");
+	if (self->settings.dte & IRCOMM_DTR)
+		ret += sprintf(buf+ret, "DTR|");
 	if (self->settings.dte)
 		ret--; /* remove the last | */
-        ret += sprintf(buf+ret, "\n");
+	ret += sprintf(buf+ret, "\n");
 
 	ret += sprintf(buf+ret, "DCE status: ");
-        if (self->settings.dce & IRCOMM_CTS)
-                ret += sprintf(buf+ret, "CTS|");
-        if (self->settings.dce & IRCOMM_DSR)
-                ret += sprintf(buf+ret, "DSR|");
-        if (self->settings.dce & IRCOMM_CD)
-                ret += sprintf(buf+ret, "CD|");
-        if (self->settings.dce & IRCOMM_RI) 
-                ret += sprintf(buf+ret, "RI|");
+	if (self->settings.dce & IRCOMM_CTS)
+		ret += sprintf(buf+ret, "CTS|");
+	if (self->settings.dce & IRCOMM_DSR)
+		ret += sprintf(buf+ret, "DSR|");
+	if (self->settings.dce & IRCOMM_CD)
+		ret += sprintf(buf+ret, "CD|");
+	if (self->settings.dce & IRCOMM_RI)
+		ret += sprintf(buf+ret, "RI|");
 	if (self->settings.dce)
 		ret--; /* remove the last | */
-        ret += sprintf(buf+ret, "\n");
+	ret += sprintf(buf+ret, "\n");
 
 	ret += sprintf(buf+ret, "Configuration: ");
 	if (!self->settings.null_modem)
 		ret += sprintf(buf+ret, "DTE <-> DCE\n");
 	else
-		ret += sprintf(buf+ret, 
+		ret += sprintf(buf+ret,
 			       "DTE <-> DTE (null modem emulation)\n");
 
 	ret += sprintf(buf+ret, "Data rate: %d\n", self->settings.data_rate);
@@ -1314,7 +1314,7 @@
 		ret += sprintf(buf+ret, "ENQ_ACK_OUT|");
 	if (self->settings.flow_control)
 		ret--; /* remove the last | */
-        ret += sprintf(buf+ret, "\n");
+	ret += sprintf(buf+ret, "\n");
 
 	ret += sprintf(buf+ret, "Flags: ");
 	if (self->flags & ASYNC_CTS_FLOW)
@@ -1333,25 +1333,25 @@
 		ret--; /* remove the last | */
 	ret += sprintf(buf+ret, "\n");
 
-	ret += sprintf(buf+ret, "Role: %s\n", self->client ? 
+	ret += sprintf(buf+ret, "Role: %s\n", self->client ?
 		       "client" : "server");
 	ret += sprintf(buf+ret, "Open count: %d\n", self->open_count);
 	ret += sprintf(buf+ret, "Max data size: %d\n", self->max_data_size);
 	ret += sprintf(buf+ret, "Max header size: %d\n", self->max_header_size);
-		
+
 	if (self->tty)
-		ret += sprintf(buf+ret, "Hardware: %s\n", 
+		ret += sprintf(buf+ret, "Hardware: %s\n",
 			       self->tty->hw_stopped ? "Stopped" : "Running");
 
-        ret += sprintf(buf+ret, "\n");
-        return ret;
+	ret += sprintf(buf+ret, "\n");
+	return ret;
 }
 
 
 /*
  * Function ircomm_tty_read_proc (buf, start, offset, len, eof, unused)
  *
- *    
+ *
  *
  */
 #ifdef CONFIG_PROC_FS
@@ -1359,8 +1359,8 @@
 				int *eof, void *unused)
 {
 	struct ircomm_tty_cb *self;
-        int count = 0, l;
-        off_t begin = 0;
+	int count = 0, l;
+	off_t begin = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&ircomm_tty->hb_spinlock, flags);
@@ -1370,25 +1370,25 @@
 		if (self->magic != IRCOMM_TTY_MAGIC)
 			break;
 
-                l = ircomm_tty_line_info(self, buf + count);
-                count += l;
-                if (count+begin > offset+len)
-                        goto done;
-                if (count+begin < offset) {
-                        begin += count;
-                        count = 0;
-                }
-				
+		l = ircomm_tty_line_info(self, buf + count);
+		count += l;
+		if (count+begin > offset+len)
+			goto done;
+		if (count+begin < offset) {
+			begin += count;
+			count = 0;
+		}
+
 		self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
-        }
-        *eof = 1;
+	}
+	*eof = 1;
 done:
 	spin_unlock_irqrestore(&ircomm_tty->hb_spinlock, flags);
 
-        if (offset >= count+begin)
-                return 0;
-        *start = buf + (offset-begin);
-        return ((len < begin+count-offset) ? len : begin+count-offset);
+	if (offset >= count+begin)
+		return 0;
+	*start = buf + (offset-begin);
+	return ((len < begin+count-offset) ? len : begin+count-offset);
 }
 #endif /* CONFIG_PROC_FS */
 
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index 99f5edd..824309d 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -1,35 +1,34 @@
 /*********************************************************************
- *                
+ *
  * Filename:      ircomm_tty_attach.c
- * Version:       
+ * Version:
  * Description:   Code for attaching the serial driver to IrCOMM
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Jun  5 17:42:00 1999
  * Modified at:   Tue Jan  4 14:20:49 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     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, 
+ *
+ *     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/sched.h>
 #include <linux/init.h>
 
 #include <net/irda/irda.h>
@@ -50,35 +49,35 @@
 static void ircomm_tty_discovery_indication(discinfo_t *discovery,
 					    DISCOVERY_MODE mode,
 					    void *priv);
-static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, 
+static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
 					struct ias_value *value, void *priv);
 static void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self,
 					    int timeout);
 static void ircomm_tty_watchdog_timer_expired(void *data);
 
-static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, 
-				 IRCOMM_TTY_EVENT event, 
-				 struct sk_buff *skb, 
+static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
+				 IRCOMM_TTY_EVENT event,
+				 struct sk_buff *skb,
 				 struct ircomm_tty_info *info);
-static int ircomm_tty_state_search(struct ircomm_tty_cb *self, 
-				   IRCOMM_TTY_EVENT event, 
-				   struct sk_buff *skb, 
+static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
+				   IRCOMM_TTY_EVENT event,
+				   struct sk_buff *skb,
 				   struct ircomm_tty_info *info);
-static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, 
-					     IRCOMM_TTY_EVENT event, 
-					     struct sk_buff *skb, 
+static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
+					     IRCOMM_TTY_EVENT event,
+					     struct sk_buff *skb,
 					     struct ircomm_tty_info *info);
-static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, 
-					   IRCOMM_TTY_EVENT event, 
-					   struct sk_buff *skb, 
+static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
+					   IRCOMM_TTY_EVENT event,
+					   struct sk_buff *skb,
 					   struct ircomm_tty_info *info);
-static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, 
-				  IRCOMM_TTY_EVENT event, 
-				  struct sk_buff *skb, 
+static int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
+				  IRCOMM_TTY_EVENT event,
+				  struct sk_buff *skb,
 				  struct ircomm_tty_info *info);
-static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, 
-				  IRCOMM_TTY_EVENT event, 
-				  struct sk_buff *skb, 
+static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
+				  IRCOMM_TTY_EVENT event,
+				  struct sk_buff *skb,
 				  struct ircomm_tty_info *info);
 
 char *ircomm_tty_state[] = {
@@ -111,7 +110,7 @@
 #endif /* CONFIG_IRDA_DEBUG */
 
 static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
-		      struct sk_buff *skb, struct ircomm_tty_info *info) = 
+		      struct sk_buff *skb, struct ircomm_tty_info *info) =
 {
 	ircomm_tty_state_idle,
 	ircomm_tty_state_search,
@@ -125,7 +124,7 @@
  * Function ircomm_tty_attach_cable (driver)
  *
  *    Try to attach cable (IrCOMM link). This function will only return
- *    when the link has been connected, or if an error condition occurs. 
+ *    when the link has been connected, or if an error condition occurs.
  *    If success, the return value is the resulting service type.
  */
 int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
@@ -135,7 +134,7 @@
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
-       	/* Check if somebody has already connected to us */
+	/* Check if somebody has already connected to us */
 	if (ircomm_is_connected(self->ircomm)) {
 		IRDA_DEBUG(0, "%s(), already connected!\n", __FUNCTION__ );
 		return 0;
@@ -177,7 +176,7 @@
 		self->skey = NULL;
 	}
 
-	if (self->iriap) { 
+	if (self->iriap) {
 		iriap_close(self->iriap);
 		self->iriap = NULL;
 	}
@@ -212,7 +211,7 @@
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
-	
+
 	/* Compute hint bits based on service */
 	hints = irlmp_service_to_hint(S_COMM);
 	if (self->service_type & IRCOMM_3_WIRE_RAW)
@@ -234,19 +233,19 @@
 	if (self->service_type & IRCOMM_3_WIRE_RAW) {
 		/* Register IrLPT with LM-IAS */
 		self->obj = irias_new_object("IrLPT", IAS_IRLPT_ID);
-		irias_add_integer_attrib(self->obj, "IrDA:IrLMP:LsapSel", 
+		irias_add_integer_attrib(self->obj, "IrDA:IrLMP:LsapSel",
 					 self->slsap_sel, IAS_KERNEL_ATTR);
 	} else {
 		/* Register IrCOMM with LM-IAS */
 		self->obj = irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID);
-		irias_add_integer_attrib(self->obj, "IrDA:TinyTP:LsapSel", 
+		irias_add_integer_attrib(self->obj, "IrDA:TinyTP:LsapSel",
 					 self->slsap_sel, IAS_KERNEL_ATTR);
-		
+
 		/* Code the parameters into the buffer */
-		irda_param_pack(oct_seq, "bbbbbb", 
+		irda_param_pack(oct_seq, "bbbbbb",
 				IRCOMM_SERVICE_TYPE, 1, self->service_type,
 				IRCOMM_PORT_TYPE,    1, IRCOMM_SERIAL);
-		
+
 		/* Register parameters with LM-IAS */
 		irias_add_octseq_attrib(self->obj, "Parameters", oct_seq, 6,
 					IAS_KERNEL_ATTR);
@@ -302,23 +301,23 @@
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
-	if (self->service_type & IRCOMM_3_WIRE_RAW) 
+	if (self->service_type & IRCOMM_3_WIRE_RAW)
 		return 0;
 
-	/* 
-	 * Set default values, but only if the application for some reason 
+	/*
+	 * Set default values, but only if the application for some reason
 	 * haven't set them already
 	 */
-	IRDA_DEBUG(2, "%s(), data-rate = %d\n", __FUNCTION__ , 
+	IRDA_DEBUG(2, "%s(), data-rate = %d\n", __FUNCTION__ ,
 		   self->settings.data_rate);
 	if (!self->settings.data_rate)
 		self->settings.data_rate = 9600;
-	IRDA_DEBUG(2, "%s(), data-format = %d\n", __FUNCTION__ , 
+	IRDA_DEBUG(2, "%s(), data-format = %d\n", __FUNCTION__ ,
 		   self->settings.data_format);
 	if (!self->settings.data_format)
 		self->settings.data_format = IRCOMM_WSIZE_8;  /* 8N1 */
 
-	IRDA_DEBUG(2, "%s(), flow-control = %d\n", __FUNCTION__ , 
+	IRDA_DEBUG(2, "%s(), flow-control = %d\n", __FUNCTION__ ,
 		   self->settings.flow_control);
 	/*self->settings.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/
 
@@ -330,7 +329,7 @@
 		ircomm_param_request(self, IRCOMM_SERVICE_TYPE, FALSE);
 	ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE);
 	ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE);
-	
+
 	/* For a 3 wire service, we just flush the last parameter and return */
 	if (self->settings.service_type == IRCOMM_3_WIRE) {
 		ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
@@ -342,10 +341,10 @@
 #if 0
 	ircomm_param_request(self, IRCOMM_XON_XOFF, FALSE);
 	ircomm_param_request(self, IRCOMM_ENQ_ACK, FALSE);
-#endif	
+#endif
 	/* Notify peer that we are ready to receive data */
 	ircomm_param_request(self, IRCOMM_DTE, TRUE);
-	
+
 	return 0;
 }
 
@@ -388,8 +387,8 @@
 	self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
 	while (self != NULL) {
 		IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
-		
-		ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION, 
+
+		ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION,
 				    NULL, &info);
 
 		self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
@@ -402,7 +401,7 @@
  *    Link disconnected
  *
  */
-void ircomm_tty_disconnect_indication(void *instance, void *sap, 
+void ircomm_tty_disconnect_indication(void *instance, void *sap,
 				      LM_REASON reason,
 				      struct sk_buff *skb)
 {
@@ -422,7 +421,7 @@
 	/* Stop data transfers */
 	self->tty->hw_stopped = 1;
 
-	ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL, 
+	ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL,
 			    NULL);
 }
 
@@ -432,8 +431,8 @@
  *    Got result from the IAS query we make
  *
  */
-static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, 
-					struct ias_value *value, 
+static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
+					struct ias_value *value,
 					void *priv)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) priv;
@@ -454,18 +453,18 @@
 	}
 
 	switch (value->type) {
- 	case IAS_OCT_SEQ:
+	case IAS_OCT_SEQ:
 		IRDA_DEBUG(2, "%s(), got octet sequence\n", __FUNCTION__ );
 
 		irda_param_extract_all(self, value->t.oct_seq, value->len,
 				       &ircomm_param_info);
 
-		ircomm_tty_do_event(self, IRCOMM_TTY_GOT_PARAMETERS, NULL, 
+		ircomm_tty_do_event(self, IRCOMM_TTY_GOT_PARAMETERS, NULL,
 				    NULL);
 		break;
 	case IAS_INTEGER:
-		/* Got LSAP selector */	
-		IRDA_DEBUG(2, "%s(), got lsapsel = %d\n", __FUNCTION__ , 
+		/* Got LSAP selector */
+		IRDA_DEBUG(2, "%s(), got lsapsel = %d\n", __FUNCTION__ ,
 			   value->t.integer);
 
 		if (value->t.integer == -1) {
@@ -491,10 +490,10 @@
  *    Connection confirmed
  *
  */
-void ircomm_tty_connect_confirm(void *instance, void *sap, 
-				struct qos_info *qos, 
-				__u32 max_data_size, 
-				__u8 max_header_size, 
+void ircomm_tty_connect_confirm(void *instance, void *sap,
+				struct qos_info *qos,
+				__u32 max_data_size,
+				__u8 max_header_size,
 				struct sk_buff *skb)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
@@ -515,16 +514,16 @@
 }
 
 /*
- * Function ircomm_tty_connect_indication (instance, sap, qos, max_sdu_size, 
+ * Function ircomm_tty_connect_indication (instance, sap, qos, max_sdu_size,
  *                                         skb)
  *
  *    we are discovered and being requested to connect by remote device !
  *
  */
-void ircomm_tty_connect_indication(void *instance, void *sap, 
-				   struct qos_info *qos, 
+void ircomm_tty_connect_indication(void *instance, void *sap,
+				   struct qos_info *qos,
 				   __u32 max_data_size,
-				   __u8 max_header_size, 
+				   __u8 max_header_size,
 				   struct sk_buff *skb)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
@@ -542,8 +541,8 @@
 
 	clen = skb->data[0];
 	if (clen)
-		irda_param_extract_all(self, skb->data+1, 
-				       IRDA_MIN(skb->len, clen), 
+		irda_param_extract_all(self, skb->data+1,
+				       IRDA_MIN(skb->len, clen),
 				       &ircomm_param_info);
 
 	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL);
@@ -566,14 +565,14 @@
 
 	if (!self->tty)
 		return;
-	
+
 	del_timer(&self->watchdog_timer);
 
-	/* 
+	/*
 	 * IrCOMM link is now up, and if we are not using hardware
 	 * flow-control, then declare the hardware as running. Otherwise we
 	 * will have to wait for the peer device (DCE) to raise the CTS
-	 * line.  
+	 * line.
 	 */
 	if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) {
 		IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __FUNCTION__ );
@@ -582,7 +581,7 @@
 		IRDA_DEBUG(1, "%s(), starting hardware!\n", __FUNCTION__ );
 
 		self->tty->hw_stopped = 0;
-	
+
 		/* Wake up processes blocked on open */
 		wake_up_interruptible(&self->open_wait);
 	}
@@ -593,8 +592,8 @@
 /*
  * Function ircomm_tty_start_watchdog_timer (self, timeout)
  *
- *    Start the watchdog timer. This timer is used to make sure that any 
- *    connection attempt is successful, and if not, we will retry after 
+ *    Start the watchdog timer. This timer is used to make sure that any
+ *    connection attempt is successful, and if not, we will retry after
  *    the timeout
  */
 static void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self,
@@ -616,7 +615,7 @@
 static void ircomm_tty_watchdog_timer_expired(void *data)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data;
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return;);
@@ -633,14 +632,14 @@
  *
  */
 int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
-			struct sk_buff *skb, struct ircomm_tty_info *info) 
+			struct sk_buff *skb, struct ircomm_tty_info *info)
 {
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
 	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
 		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
-	
+
 	return (*state[self->state])(self, event, skb, info);
 }
 
@@ -656,7 +655,7 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
-	IRDA_DEBUG(2, "%s: next state=%s, service type=%d\n", __FUNCTION__ , 
+	IRDA_DEBUG(2, "%s: next state=%s, service type=%d\n", __FUNCTION__ ,
 		   ircomm_tty_state[self->state], self->service_type);
 	*/
 	self->state = state;
@@ -668,9 +667,9 @@
  *    Just hanging around
  *
  */
-static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, 
-				 IRCOMM_TTY_EVENT event, 
-				 struct sk_buff *skb, 
+static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
+				 IRCOMM_TTY_EVENT event,
+				 struct sk_buff *skb,
 				 struct ircomm_tty_info *info)
 {
 	int ret = 0;
@@ -679,10 +678,10 @@
 		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
 	switch (event) {
 	case IRCOMM_TTY_ATTACH_CABLE:
-		/* Try to discover any remote devices */		
+		/* Try to discover any remote devices */
 		ircomm_tty_start_watchdog_timer(self, 3*HZ);
 		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
-		
+
 		irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
 		break;
 	case IRCOMM_TTY_DISCOVERY_INDICATION:
@@ -701,7 +700,7 @@
 		iriap_getvaluebyclass_request(self->iriap,
 					      self->saddr, self->daddr,
 					      "IrDA:IrCOMM", "Parameters");
-		
+
 		ircomm_tty_start_watchdog_timer(self, 3*HZ);
 		ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS);
 		break;
@@ -732,9 +731,9 @@
  *    Trying to discover an IrCOMM device
  *
  */
-static int ircomm_tty_state_search(struct ircomm_tty_cb *self, 
-				   IRCOMM_TTY_EVENT event, 
-				   struct sk_buff *skb, 
+static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
+				   IRCOMM_TTY_EVENT event,
+				   struct sk_buff *skb,
 				   struct ircomm_tty_info *info)
 {
 	int ret = 0;
@@ -752,19 +751,19 @@
 				     __FUNCTION__);
 			return -EBUSY;
 		}
-		
+
 		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
 					 ircomm_tty_getvalue_confirm);
-		
+
 		if (self->service_type == IRCOMM_3_WIRE_RAW) {
 			iriap_getvaluebyclass_request(self->iriap, self->saddr,
-						      self->daddr, "IrLPT", 
+						      self->daddr, "IrLPT",
 						      "IrDA:IrLMP:LsapSel");
 			ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL);
 		} else {
 			iriap_getvaluebyclass_request(self->iriap, self->saddr,
-						      self->daddr, 
-						      "IrDA:IrCOMM", 
+						      self->daddr,
+						      "IrDA:IrCOMM",
 						      "Parameters");
 
 			ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS);
@@ -783,7 +782,7 @@
 #if 1
 		/* Give up */
 #else
-		/* Try to discover any remote devices */		
+		/* Try to discover any remote devices */
 		ircomm_tty_start_watchdog_timer(self, 3*HZ);
 		irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
 #endif
@@ -805,9 +804,9 @@
  *    Querying the remote LM-IAS for IrCOMM parameters
  *
  */
-static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, 
-					     IRCOMM_TTY_EVENT event, 
-					     struct sk_buff *skb, 
+static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
+					     IRCOMM_TTY_EVENT event,
+					     struct sk_buff *skb,
 					     struct ircomm_tty_info *info)
 {
 	int ret = 0;
@@ -822,12 +821,12 @@
 				     __FUNCTION__);
 			return -EBUSY;
 		}
-		
+
 		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
 					 ircomm_tty_getvalue_confirm);
 
-		iriap_getvaluebyclass_request(self->iriap, self->saddr, 
-					      self->daddr, "IrDA:IrCOMM", 
+		iriap_getvaluebyclass_request(self->iriap, self->saddr,
+					      self->daddr, "IrDA:IrCOMM",
 					      "IrDA:TinyTP:LsapSel");
 
 		ircomm_tty_start_watchdog_timer(self, 3*HZ);
@@ -836,7 +835,7 @@
 	case IRCOMM_TTY_WD_TIMER_EXPIRED:
 		/* Go back to search mode */
 		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
-		ircomm_tty_start_watchdog_timer(self, 3*HZ); 
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
 		break;
 	case IRCOMM_TTY_CONNECT_INDICATION:
 		del_timer(&self->watchdog_timer);
@@ -863,9 +862,9 @@
  *    Query remote LM-IAS for the LSAP selector which we can connect to
  *
  */
-static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, 
-					   IRCOMM_TTY_EVENT event, 
-					   struct sk_buff *skb, 
+static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
+					   IRCOMM_TTY_EVENT event,
+					   struct sk_buff *skb,
 					   struct ircomm_tty_info *info)
 {
 	int ret = 0;
@@ -877,7 +876,7 @@
 	case IRCOMM_TTY_GOT_LSAPSEL:
 		/* Connect to remote device */
 		ret = ircomm_connect_request(self->ircomm, self->dlsap_sel,
-					     self->saddr, self->daddr, 
+					     self->saddr, self->daddr,
 					     NULL, self->service_type);
 		ircomm_tty_start_watchdog_timer(self, 3*HZ);
 		ircomm_tty_next_state(self, IRCOMM_TTY_SETUP);
@@ -912,9 +911,9 @@
  *    Trying to connect
  *
  */
-static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, 
-				  IRCOMM_TTY_EVENT event, 
-				  struct sk_buff *skb, 
+static int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
+				  IRCOMM_TTY_EVENT event,
+				  struct sk_buff *skb,
 				  struct ircomm_tty_info *info)
 {
 	int ret = 0;
@@ -926,10 +925,10 @@
 	case IRCOMM_TTY_CONNECT_CONFIRM:
 		del_timer(&self->watchdog_timer);
 		ircomm_tty_ias_unregister(self);
-		
-		/* 
+
+		/*
 		 * Send initial parameters. This will also send out queued
-		 * parameters waiting for the connection to come up 
+		 * parameters waiting for the connection to come up
 		 */
 		ircomm_tty_send_initial_parameters(self);
 		ircomm_tty_link_established(self);
@@ -938,7 +937,7 @@
 	case IRCOMM_TTY_CONNECT_INDICATION:
 		del_timer(&self->watchdog_timer);
 		ircomm_tty_ias_unregister(self);
-		
+
 		/* Accept connection */
 		ircomm_connect_response(self->ircomm, NULL);
 		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
@@ -966,9 +965,9 @@
  *    IrCOMM is now connected
  *
  */
-static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, 
-				  IRCOMM_TTY_EVENT event, 
-				  struct sk_buff *skb, 
+static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
+				  IRCOMM_TTY_EVENT event,
+				  struct sk_buff *skb,
 				  struct ircomm_tty_info *info)
 {
 	int ret = 0;
@@ -976,7 +975,7 @@
 	switch (event) {
 	case IRCOMM_TTY_DATA_REQUEST:
 		ret = ircomm_data_request(self->ircomm, skb);
-		break;		
+		break;
 	case IRCOMM_TTY_DETACH_CABLE:
 		ircomm_disconnect_request(self->ircomm, NULL);
 		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index 75e39ea..6030947 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -1,36 +1,35 @@
 /*********************************************************************
- *                
+ *
  * Filename:      ircomm_tty_ioctl.c
- * Version:       
- * Description:   
+ * Version:
+ * Description:
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Jun 10 14:39:09 1999
  * Modified at:   Wed Jan  5 14:45:43 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     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, 
+ *
+ *     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/init.h>
 #include <linux/fs.h>
-#include <linux/sched.h>
 #include <linux/termios.h>
 #include <linux/tty.h>
 #include <linux/serial.h>
@@ -75,7 +74,7 @@
 	}
 	if (cflag & CSTOPB)
 		cval |= IRCOMM_2_STOP_BIT;
-	
+
 	if (cflag & PARENB)
 		cval |= IRCOMM_PARITY_ENABLE;
 	if (!(cflag & PARODD))
@@ -88,7 +87,7 @@
 
 	self->settings.data_rate = baud;
 	ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE);
-	
+
 	/* CTS flow control flag and modem status interrupts */
 	if (cflag & CRTSCTS) {
 		self->flags |= ASYNC_CTS_FLOW;
@@ -104,7 +103,7 @@
 		self->flags &= ~ASYNC_CHECK_CD;
 	else
 		self->flags |= ASYNC_CHECK_CD;
-#if 0	
+#if 0
 	/*
 	 * Set up parity check flag
 	 */
@@ -113,7 +112,7 @@
 		driver->read_status_mask |= LSR_FE | LSR_PE;
 	if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty))
 		driver->read_status_mask |= LSR_BI;
-	
+
 	/*
 	 * Characters to ignore
 	 */
@@ -124,17 +123,17 @@
 	if (I_IGNBRK(self->tty)) {
 		self->ignore_status_mask |= LSR_BI;
 		/*
-		 * If we're ignore parity and break indicators, ignore 
+		 * If we're ignore parity and break indicators, ignore
 		 * overruns too. (For real raw support).
 		 */
-		if (I_IGNPAR(self->tty)) 
+		if (I_IGNPAR(self->tty))
 			self->ignore_status_mask |= LSR_OE;
 	}
 #endif
 	self->settings.data_format = cval;
 
 	ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE);
- 	ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
+	ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
 }
 
 /*
@@ -145,7 +144,7 @@
  *    should be prepared to accept the case where old == NULL, and try to
  *    do something rational.
  */
-void ircomm_tty_set_termios(struct tty_struct *tty, 
+void ircomm_tty_set_termios(struct tty_struct *tty,
 			    struct ktermios *old_termios)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
@@ -153,8 +152,8 @@
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
-	if ((cflag == old_termios->c_cflag) && 
-	    (RELEVANT_IFLAG(tty->termios->c_iflag) == 
+	if ((cflag == old_termios->c_cflag) &&
+	    (RELEVANT_IFLAG(tty->termios->c_iflag) ==
 	     RELEVANT_IFLAG(old_termios->c_iflag)))
 	{
 		return;
@@ -168,21 +167,21 @@
 		self->settings.dte &= ~(IRCOMM_DTR|IRCOMM_RTS);
 		ircomm_param_request(self, IRCOMM_DTE, TRUE);
 	}
-	
+
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) &&
 	    (cflag & CBAUD)) {
 		self->settings.dte |= IRCOMM_DTR;
-		if (!(tty->termios->c_cflag & CRTSCTS) || 
+		if (!(tty->termios->c_cflag & CRTSCTS) ||
 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
 			self->settings.dte |= IRCOMM_RTS;
 		}
 		ircomm_param_request(self, IRCOMM_DTE, TRUE);
 	}
-	
+
 	/* Handle turning off CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) 
+	    !(tty->termios->c_cflag & CRTSCTS))
 	{
 		tty->hw_stopped = 0;
 		ircomm_tty_start(tty);
@@ -192,7 +191,7 @@
 /*
  * Function ircomm_tty_tiocmget (tty, file)
  *
- *    
+ *
  *
  */
 int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file)
@@ -217,12 +216,12 @@
 /*
  * Function ircomm_tty_tiocmset (tty, file, set, clear)
  *
- *    
+ *
  *
  */
 int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
 			unsigned int set, unsigned int clear)
-{ 
+{
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
@@ -249,21 +248,21 @@
 		self->settings.dte |= IRCOMM_DELTA_DTR;
 
 	ircomm_param_request(self, IRCOMM_DTE, TRUE);
-	
+
 	return 0;
 }
 
 /*
  * Function get_serial_info (driver, retinfo)
  *
- *    
+ *
  *
  */
 static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
 				      struct serial_struct __user *retinfo)
 {
 	struct serial_struct info;
-   
+
 	if (!retinfo)
 		return -EFAULT;
 
@@ -277,11 +276,11 @@
 	info.closing_wait = self->closing_wait;
 
 	/* For compatibility  */
- 	info.type = PORT_16550A;
- 	info.port = 0;
- 	info.irq = 0;
+	info.type = PORT_16550A;
+	info.port = 0;
+	info.irq = 0;
 	info.xmit_fifo_size = 0;
-	info.hub6 = 0;   
+	info.hub6 = 0;
 	info.custom_divisor = 0;
 
 	if (copy_to_user(retinfo, &info, sizeof(*retinfo)))
@@ -293,7 +292,7 @@
 /*
  * Function set_serial_info (driver, new_info)
  *
- *    
+ *
  *
  */
 static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *self,
@@ -311,7 +310,7 @@
 
 	state = self
 	old_state = *self;
-  
+
 	if (!capable(CAP_SYS_ADMIN)) {
 		if ((new_serial.baud_base != state->settings.data_rate) ||
 		    (new_serial.close_delay != state->close_delay) ||
@@ -368,10 +367,10 @@
 /*
  * Function ircomm_tty_ioctl (tty, file, cmd, arg)
  *
- *    
+ *
  *
  */
-int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, 
+int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
@@ -416,7 +415,7 @@
 		    put_user(cnow.brk, &p_cuser->brk) ||
 		    put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
 			return -EFAULT;
-#endif		
+#endif
 		return 0;
 	default:
 		ret = -ENOIOCTLCMD;  /* ioctls which we must ignore */
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index 7e7a317..e717801 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -341,11 +341,11 @@
  */
 static void irda_device_setup(struct net_device *dev)
 {
-        dev->hard_header_len = 0;
-        dev->addr_len        = LAP_ALEN;
+	dev->hard_header_len = 0;
+	dev->addr_len        = LAP_ALEN;
 
-        dev->type            = ARPHRD_IRDA;
-        dev->tx_queue_len    = 8; /* Window size + 1 s-frame */
+	dev->type            = ARPHRD_IRDA;
+	dev->tx_queue_len    = 8; /* Window size + 1 s-frame */
 
 	memset(dev->broadcast, 0xff, LAP_ALEN);
 
@@ -354,7 +354,7 @@
 }
 
 /*
- * Funciton  alloc_irdadev 
+ * Funciton  alloc_irdadev
  * 	Allocates and sets up an IRDA device in a manner similar to
  * 	alloc_etherdev.
  */
@@ -386,9 +386,9 @@
 	/* Try to load the module needed */
 	if (!reg && capable(CAP_SYS_MODULE)) {
 		spin_unlock(&dongles->hb_spinlock);
-	
+
 		request_module("irda-dongle-%d", type);
-		
+
 		spin_lock(&dongles->hb_spinlock);
 		reg = hashbin_find(dongles, type, NULL);
 	}
@@ -438,15 +438,15 @@
 	spin_lock(&dongles->hb_spinlock);
 	/* Check if this dongle has been registered before */
 	if (hashbin_find(dongles, new->type, NULL)) {
-		IRDA_MESSAGE("%s: Dongle type %x already registered\n", 
+		IRDA_MESSAGE("%s: Dongle type %x already registered\n",
 			     __FUNCTION__, new->type);
-        } else {
+	} else {
 		/* Insert IrDA dongle into hashbin */
 		hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL);
 	}
 	spin_unlock(&dongles->hb_spinlock);
 
-        return 0;
+	return 0;
 }
 EXPORT_SYMBOL(irda_device_register_dongle);
 
@@ -462,7 +462,7 @@
 
 	spin_lock(&dongles->hb_spinlock);
 	node = hashbin_remove(dongles, dongle->type, NULL);
-	if (!node) 
+	if (!node)
 		IRDA_ERROR("%s: dongle not found!\n", __FUNCTION__);
 	spin_unlock(&dongles->hb_spinlock);
 }
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 8f1c6d6..915d938 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -79,10 +79,10 @@
 
 static void iriap_watchdog_timer_expired(void *data);
 
-static inline void iriap_start_watchdog_timer(struct iriap_cb *self, 
-					      int timeout) 
+static inline void iriap_start_watchdog_timer(struct iriap_cb *self,
+					      int timeout)
 {
-	irda_start_timer(&self->watchdog_timer, timeout, self, 
+	irda_start_timer(&self->watchdog_timer, timeout, self,
 			 iriap_watchdog_timer_expired);
 }
 
@@ -674,7 +674,7 @@
 	if (attrib == NULL) {
 		IRDA_DEBUG(2, "LM-IAS: Attribute %s not found\n", attr);
 		iriap_getvaluebyclass_response(self, obj->id,
-					       IAS_ATTRIB_UNKNOWN, 
+					       IAS_ATTRIB_UNKNOWN,
 					       &irias_missing);
 		return;
 	}
@@ -971,7 +971,7 @@
 	"IAS_STRING"
 };
 
-static inline struct ias_object *irias_seq_idx(loff_t pos) 
+static inline struct ias_object *irias_seq_idx(loff_t pos)
 {
 	struct ias_object *obj;
 
@@ -980,7 +980,7 @@
 		if (pos-- == 0)
 			break;
 	}
-		
+
 	return obj;
 }
 
@@ -995,7 +995,7 @@
 {
 	++*pos;
 
-	return (v == SEQ_START_TOKEN) 
+	return (v == SEQ_START_TOKEN)
 		? (void *) hashbin_get_first(irias_objects)
 		: (void *) hashbin_get_next(irias_objects);
 }
@@ -1027,7 +1027,7 @@
 		for (attrib = (struct ias_attrib *) hashbin_get_first(obj->attribs);
 		     attrib != NULL;
 		     attrib = (struct ias_attrib *) hashbin_get_next(obj->attribs)) {
-		     
+
 			IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC,
 				    goto outloop; );
 
@@ -1046,14 +1046,14 @@
 					   attrib->value->t.string);
 				break;
 			case IAS_OCT_SEQ:
-				seq_printf(seq, "octet sequence (%d bytes)\n", 
+				seq_printf(seq, "octet sequence (%d bytes)\n",
 					   attrib->value->len);
 				break;
 			case IAS_MISSING:
 				seq_puts(seq, "missing\n");
 				break;
 			default:
-				seq_printf(seq, "type %d?\n", 
+				seq_printf(seq, "type %d?\n",
 					   attrib->value->type);
 			}
 			seq_putc(seq, '\n');
@@ -1080,7 +1080,7 @@
 	return seq_open(file, &irias_seq_ops);
 }
 
-struct file_operations irias_seq_fops = {
+const struct file_operations irias_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = irias_seq_open,
 	.read           = seq_read,
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
index b1ee99a..4adaae2 100644
--- a/net/irda/irias_object.c
+++ b/net/irda/irias_object.c
@@ -57,8 +57,8 @@
 		len = max;
 
 	/* Allocate new string */
-        new_str = kmalloc(len + 1, GFP_ATOMIC);
-        if (new_str == NULL) {
+	new_str = kmalloc(len + 1, GFP_ATOMIC);
+	if (new_str == NULL) {
 		IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
 		return NULL;
 	}
@@ -78,7 +78,7 @@
  */
 struct ias_object *irias_new_object( char *name, int id)
 {
-        struct ias_object *obj;
+	struct ias_object *obj;
 
 	IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
 
@@ -91,6 +91,12 @@
 
 	obj->magic = IAS_OBJECT_MAGIC;
 	obj->name = strndup(name, IAS_MAX_CLASSNAME);
+	if (!obj->name) {
+		IRDA_WARNING("%s(), Unable to allocate name!\n",
+			     __FUNCTION__);
+		kfree(obj);
+		return NULL;
+	}
 	obj->id = id;
 
 	/* Locking notes : the attrib spinlock has lower precendence
@@ -101,6 +107,7 @@
 	if (obj->attribs == NULL) {
 		IRDA_WARNING("%s(), Unable to allocate attribs!\n",
 			     __FUNCTION__);
+		kfree(obj->name);
 		kfree(obj);
 		return NULL;
 	}
@@ -357,6 +364,15 @@
 
 	/* Insert value */
 	attrib->value = irias_new_integer_value(value);
+	if (!attrib->name || !attrib->value) {
+		IRDA_WARNING("%s: Unable to allocate attribute!\n",
+			     __FUNCTION__);
+		if (attrib->value)
+			irias_delete_value(attrib->value);
+		kfree(attrib->name);
+		kfree(attrib);
+		return;
+	}
 
 	irias_add_attrib(obj, attrib, owner);
 }
@@ -391,6 +407,15 @@
 	attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
 
 	attrib->value = irias_new_octseq_value( octets, len);
+	if (!attrib->name || !attrib->value) {
+		IRDA_WARNING("%s: Unable to allocate attribute!\n",
+			     __FUNCTION__);
+		if (attrib->value)
+			irias_delete_value(attrib->value);
+		kfree(attrib->name);
+		kfree(attrib);
+		return;
+	}
 
 	irias_add_attrib(obj, attrib, owner);
 }
@@ -424,6 +449,15 @@
 	attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
 
 	attrib->value = irias_new_string_value(value);
+	if (!attrib->name || !attrib->value) {
+		IRDA_WARNING("%s: Unable to allocate attribute!\n",
+			     __FUNCTION__);
+		if (attrib->value)
+			irias_delete_value(attrib->value);
+		kfree(attrib->name);
+		kfree(attrib);
+		return;
+	}
 
 	irias_add_attrib(obj, attrib, owner);
 }
@@ -473,6 +507,12 @@
 	value->type = IAS_STRING;
 	value->charset = CS_ASCII;
 	value->t.string = strndup(string, IAS_MAX_STRING);
+	if (!value->t.string) {
+		IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
+		kfree(value);
+		return NULL;
+	}
+
 	value->len = strlen(value->t.string);
 
 	return value;
diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
index 95cf123..a4c1c95 100644
--- a/net/irda/irlan/irlan_client.c
+++ b/net/irda/irlan/irlan_client.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irlan_client.c
  * Version:       0.9
  * Description:   IrDA LAN Access Protocol (IrLAN) Client
@@ -11,17 +11,17 @@
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
  *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
  *
  ********************************************************************/
@@ -54,35 +54,35 @@
 
 #undef CONFIG_IRLAN_GRATUITOUS_ARP
 
-static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap, 
-						    LM_REASON reason, 
+static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
+						    LM_REASON reason,
 						    struct sk_buff *);
-static int irlan_client_ctrl_data_indication(void *instance, void *sap, 
+static int irlan_client_ctrl_data_indication(void *instance, void *sap,
 					     struct sk_buff *skb);
-static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
-					      struct qos_info *qos, 
+static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
+					      struct qos_info *qos,
 					      __u32 max_sdu_size,
 					      __u8 max_header_size,
 					      struct sk_buff *);
-static void irlan_check_response_param(struct irlan_cb *self, char *param, 
+static void irlan_check_response_param(struct irlan_cb *self, char *param,
 				       char *value, int val_len);
 static void irlan_client_open_ctrl_tsap(struct irlan_cb *self);
 
 static void irlan_client_kick_timer_expired(void *data)
 {
 	struct irlan_cb *self = (struct irlan_cb *) data;
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
-	
-	/*  
+
+	/*
 	 * If we are in peer mode, the client may not have got the discovery
-	 * indication it needs to make progress. If the client is still in 
+	 * indication it needs to make progress. If the client is still in
 	 * IDLE state, we must kick it to, but only if the provider is not IDLE
- 	 */
-	if ((self->provider.access_type == ACCESS_PEER) && 
+	 */
+	if ((self->provider.access_type == ACCESS_PEER) &&
 	    (self->client.state == IRLAN_IDLE) &&
 	    (self->provider.state != IRLAN_IDLE)) {
 		irlan_client_wakeup(self, self->saddr, self->daddr);
@@ -92,8 +92,8 @@
 static void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
-	irda_start_timer(&self->client.kick_timer, timeout, (void *) self, 
+
+	irda_start_timer(&self->client.kick_timer, timeout, (void *) self,
 			 irlan_client_kick_timer_expired);
 }
 
@@ -110,11 +110,11 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	/* 
+	/*
 	 * Check if we are already awake, or if we are a provider in direct
 	 * mode (in that case we must leave the client idle
 	 */
-	if ((self->client.state != IRLAN_IDLE) || 
+	if ((self->client.state != IRLAN_IDLE) ||
 	    (self->provider.access_type == ACCESS_DIRECT))
 	{
 			IRDA_DEBUG(0, "%s(), already awake!\n", __FUNCTION__ );
@@ -135,7 +135,7 @@
 	irlan_open_data_tsap(self);
 
 	irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL);
-	
+
 	/* Start kick timer */
 	irlan_client_start_kick_timer(self, 2*HZ);
 }
@@ -148,11 +148,11 @@
  */
 void irlan_client_discovery_indication(discinfo_t *discovery,
 				       DISCOVERY_MODE mode,
-				       void *priv) 
+				       void *priv)
 {
 	struct irlan_cb *self;
 	__u32 saddr, daddr;
-	
+
 	IRDA_DEBUG(1, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(discovery != NULL, return;);
@@ -177,35 +177,35 @@
 
 		IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __FUNCTION__ ,
 		      daddr);
-		
+
 		irlan_client_wakeup(self, saddr, daddr);
 	}
 IRDA_ASSERT_LABEL(out:)
 	rcu_read_unlock();
 }
-	
+
 /*
  * Function irlan_client_data_indication (handle, skb)
  *
  *    This function gets the data that is received on the control channel
  *
  */
-static int irlan_client_ctrl_data_indication(void *instance, void *sap, 
+static int irlan_client_ctrl_data_indication(void *instance, void *sap,
 					     struct sk_buff *skb)
 {
 	struct irlan_cb *self;
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-	
+
 	self = (struct irlan_cb *) instance;
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
 	IRDA_ASSERT(skb != NULL, return -1;);
-	
-	irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb); 
 
-	/* Ready for a new command */	
+	irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
+
+	/* Ready for a new command */
 	IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __FUNCTION__ );
 	self->client.tx_busy = FALSE;
 
@@ -215,27 +215,27 @@
 	return 0;
 }
 
-static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap, 
-						    LM_REASON reason, 
-						    struct sk_buff *userdata) 
+static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
+						    LM_REASON reason,
+						    struct sk_buff *userdata)
 {
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
 	struct sk_buff *skb;
 
 	IRDA_DEBUG(4, "%s(), reason=%d\n", __FUNCTION__ , reason);
-	
+
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
 
 	IRDA_ASSERT(self != NULL, return;);
-	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	
+	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 	IRDA_ASSERT(tsap != NULL, return;);
 	IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
-	
+
 	IRDA_ASSERT(tsap == self->client.tsap_ctrl, return;);
 
-       	/* Remove frames queued on the control channel */
+	/* Remove frames queued on the control channel */
 	while ((skb = skb_dequeue(&self->client.txq)) != NULL) {
 		dev_kfree_skb(skb);
 	}
@@ -272,7 +272,7 @@
 	notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
 	notify.instance = self;
 	strlcpy(notify.name, "IrLAN ctrl (c)", sizeof(notify.name));
-	
+
 	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
 	if (!tsap) {
 		IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );
@@ -287,11 +287,11 @@
  *    Connection to peer IrLAN laye confirmed
  *
  */
-static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
-					      struct qos_info *qos, 
+static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
+					      struct qos_info *qos,
 					      __u32 max_sdu_size,
 					      __u8 max_header_size,
-					      struct sk_buff *skb) 
+					      struct sk_buff *skb)
 {
 	struct irlan_cb *self;
 
@@ -316,7 +316,7 @@
  *    Print return code of request to peer IrLAN layer.
  *
  */
-static void print_ret_code(__u8 code) 
+static void print_ret_code(__u8 code)
 {
 	switch(code) {
 	case 0:
@@ -358,7 +358,7 @@
 /*
  * Function irlan_client_parse_response (self, skb)
  *
- *    Extract all parameters from received buffer, then feed them to 
+ *    Extract all parameters from received buffer, then feed them to
  *    check_params for parsing
  */
 void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
@@ -369,30 +369,30 @@
 	int ret;
 	__u16 val_len;
 	int i;
-        char *name;
-        char *value;
+	char *name;
+	char *value;
 
-	IRDA_ASSERT(skb != NULL, return;);	
-	
+	IRDA_ASSERT(skb != NULL, return;);
+
 	IRDA_DEBUG(4, "%s() skb->len=%d\n", __FUNCTION__ , (int) skb->len);
-	
+
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
-	
+
 	if (!skb) {
 		IRDA_ERROR("%s(), Got NULL skb!\n", __FUNCTION__);
 		return;
 	}
 	frame = skb->data;
-	
-	/* 
-	 *  Check return code and print it if not success 
+
+	/*
+	 *  Check return code and print it if not success
 	 */
 	if (frame[0]) {
 		print_ret_code(frame[0]);
 		return;
 	}
-	
+
 	name = kmalloc(255, GFP_ATOMIC);
 	if (!name)
 		return;
@@ -406,11 +406,11 @@
 	count = frame[1];
 
 	IRDA_DEBUG(4, "%s(), got %d parameters\n", __FUNCTION__ , count);
-	
+
 	ptr = frame+2;
 
 	/* For all parameters */
- 	for (i=0; i<count;i++) {
+	for (i=0; i<count;i++) {
 		ret = irlan_extract_param(ptr, name, value, &val_len);
 		if (ret < 0) {
 			IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __FUNCTION__ );
@@ -418,7 +418,7 @@
 		}
 		ptr += ret;
 		irlan_check_response_param(self, name, value, val_len);
- 	}
+	}
 	/* Cleanup */
 	kfree(name);
 	kfree(value);
@@ -430,8 +430,8 @@
  *     Check which parameter is received and update local variables
  *
  */
-static void irlan_check_response_param(struct irlan_cb *self, char *param, 
-				       char *value, int val_len) 
+static void irlan_check_response_param(struct irlan_cb *self, char *param,
+				       char *value, int val_len)
 {
 	__u16 tmp_cpu; /* Temporary value in host order */
 	__u8 *bytes;
@@ -465,7 +465,7 @@
 			self->client.filter_type |= IRLAN_BROADCAST;
 		else if (strcmp(value, "IPX_SOCKET") == 0)
 			self->client.filter_type |= IRLAN_IPX_SOCKET;
-		
+
 	}
 	if (strcmp(param, "ACCESS_TYPE") == 0) {
 		if (strcmp(value, "DIRECT") == 0)
@@ -480,7 +480,7 @@
 	}
 	/* IRLAN version */
 	if (strcmp(param, "IRLAN_VER") == 0) {
-		IRDA_DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0], 
+		IRDA_DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0],
 		      (__u8) value[1]);
 
 		self->version[0] = value[0];
@@ -497,17 +497,17 @@
 		memcpy(&tmp_cpu, value, 2); /* Align value */
 		le16_to_cpus(&tmp_cpu);     /* Convert to host order */
 		self->client.recv_arb_val = tmp_cpu;
-		IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __FUNCTION__ , 
+		IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __FUNCTION__ ,
 			   self->client.recv_arb_val);
 	}
 	if (strcmp(param, "MAX_FRAME") == 0) {
 		memcpy(&tmp_cpu, value, 2); /* Align value */
 		le16_to_cpus(&tmp_cpu);     /* Convert to host order */
 		self->client.max_frame = tmp_cpu;
-		IRDA_DEBUG(4, "%s(), max frame=%d\n", __FUNCTION__ , 
+		IRDA_DEBUG(4, "%s(), max frame=%d\n", __FUNCTION__ ,
 			   self->client.max_frame);
 	}
-	 
+
 	/* RECONNECT_KEY, in case the link goes down! */
 	if (strcmp(param, "RECONNECT_KEY") == 0) {
 		IRDA_DEBUG(4, "Got reconnect key: ");
@@ -521,9 +521,9 @@
 	if (strcmp(param, "FILTER_ENTRY") == 0) {
 		bytes = value;
 		IRDA_DEBUG(4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n",
-		      bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 
+		      bytes[0], bytes[1], bytes[2], bytes[3], bytes[4],
 		      bytes[5]);
-		for (i = 0; i < 6; i++) 
+		for (i = 0; i < 6; i++)
 			self->dev->dev_addr[i] = bytes[i];
 	}
 }
@@ -534,11 +534,11 @@
  *    Got results from remote LM-IAS
  *
  */
-void irlan_client_get_value_confirm(int result, __u16 obj_id, 
-				    struct ias_value *value, void *priv) 
+void irlan_client_get_value_confirm(int result, __u16 obj_id,
+				    struct ias_value *value, void *priv)
 {
 	struct irlan_cb *self;
-	
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(priv != NULL, return;);
@@ -553,7 +553,7 @@
 	/* Check if request succeeded */
 	if (result != IAS_SUCCESS) {
 		IRDA_DEBUG(2, "%s(), got NULL value!\n", __FUNCTION__ );
-		irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, 
+		irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL,
 				      NULL);
 		return;
 	}
diff --git a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c
index ce943b6..843ab6f 100644
--- a/net/irda/irlan/irlan_client_event.c
+++ b/net/irda/irlan/irlan_client_event.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irlan_client_event.c
  * Version:       0.9
  * Description:   IrLAN client state machine
@@ -8,17 +8,17 @@
  * Created at:    Sun Aug 31 20:14:37 1997
  * Modified at:   Sun Dec 26 21:52:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
  *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
  *
  ********************************************************************/
@@ -36,31 +36,31 @@
 #include <net/irda/irlan_client.h>
 #include <net/irda/irlan_event.h>
 
-static int irlan_client_state_idle (struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_idle (struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
-static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
-static int irlan_client_state_conn (struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_conn (struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
-static int irlan_client_state_info (struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_info (struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
-static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
-static int irlan_client_state_open (struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_open (struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
-static int irlan_client_state_wait (struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_wait (struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
-static int irlan_client_state_arb  (struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_arb  (struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
-static int irlan_client_state_data (struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_data (struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
-static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
-static int irlan_client_state_sync (struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_client_state_sync (struct irlan_cb *self, IRLAN_EVENT event,
 				    struct sk_buff *skb);
 
 static int (*state[])(struct irlan_cb *, IRLAN_EVENT event, struct sk_buff *) =
-{ 
+{
 	irlan_client_state_idle,
 	irlan_client_state_query,
 	irlan_client_state_conn,
@@ -74,8 +74,8 @@
 	irlan_client_state_sync
 };
 
-void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event, 
-			   struct sk_buff *skb) 
+void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event,
+			   struct sk_buff *skb)
 {
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -89,14 +89,14 @@
  *    IDLE, We are waiting for an indication that there is a provider
  *    available.
  */
-static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event, 
-				   struct sk_buff *skb) 
+static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+				   struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
-	
+
 	switch (event) {
 	case IRLAN_DISCOVERY_INDICATION:
 		if (self->client.iriap) {
@@ -104,7 +104,7 @@
 				     __FUNCTION__);
 			return -EBUSY;
 		}
-		
+
 		self->client.iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
 						irlan_client_get_value_confirm);
 		/* Get some values from peer IAS */
@@ -120,7 +120,7 @@
 		IRDA_DEBUG(4, "%s(), Unknown event %d\n", __FUNCTION__ , event);
 		break;
 	}
-	if (skb) 
+	if (skb)
 		dev_kfree_skb(skb);
 
 	return 0;
@@ -133,23 +133,23 @@
  *    to provider, just waiting for the confirm.
  *
  */
-static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
+static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
+				    struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
-	
+
 	switch(event) {
 	case IRLAN_IAS_PROVIDER_AVAIL:
 		IRDA_ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
 
 		self->client.open_retries = 0;
-		
-		irttp_connect_request(self->client.tsap_ctrl, 
-				      self->dtsap_sel_ctrl, 
-				      self->saddr, self->daddr, NULL, 
+
+		irttp_connect_request(self->client.tsap_ctrl,
+				      self->dtsap_sel_ctrl,
+				      self->saddr, self->daddr, NULL,
 				      IRLAN_MTU, NULL);
 		irlan_next_client_state(self, IRLAN_CONN);
 		break;
@@ -158,7 +158,7 @@
 		irlan_next_client_state(self, IRLAN_IDLE);
 
 		/* Give the client a kick! */
-		if ((self->provider.access_type == ACCESS_PEER) && 
+		if ((self->provider.access_type == ACCESS_PEER) &&
 		    (self->provider.state != IRLAN_IDLE))
 			irlan_client_wakeup(self, self->saddr, self->daddr);
 		break;
@@ -175,7 +175,7 @@
 	}
 	if (skb)
 		dev_kfree_skb(skb);
-	
+
 	return 0;
 }
 
@@ -186,13 +186,13 @@
  *    commands yet.
  *
  */
-static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event, 
-				   struct sk_buff *skb) 
+static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
+				   struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
-	
+
 	switch (event) {
 	case IRLAN_CONNECT_COMPLETE:
 		/* Send getinfo cmd */
@@ -212,7 +212,7 @@
 	}
 	if (skb)
 		dev_kfree_skb(skb);
-	
+
 	return 0;
 }
 
@@ -221,24 +221,24 @@
  *
  *    INFO, We have issued a GetInfo command and is awaiting a reply.
  */
-static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
-				   struct sk_buff *skb) 
+static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+				   struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return -1;);
-	
+
 	switch (event) {
 	case IRLAN_DATA_INDICATION:
 		IRDA_ASSERT(skb != NULL, return -1;);
-	
+
 		irlan_client_parse_response(self, skb);
-		
+
 		irlan_next_client_state(self, IRLAN_MEDIA);
-		
+
 		irlan_get_media_char(self);
 		break;
-		
+
 	case IRLAN_LMP_DISCONNECT:
 	case IRLAN_LAP_DISCONNECT:
 		irlan_next_client_state(self, IRLAN_IDLE);
@@ -252,7 +252,7 @@
 	}
 	if (skb)
 		dev_kfree_skb(skb);
-	
+
 	return 0;
 }
 
@@ -263,11 +263,11 @@
  *    reply.
  *
  */
-static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
+static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
+				    struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 
 	switch(event) {
@@ -289,7 +289,7 @@
 	}
 	if (skb)
 		dev_kfree_skb(skb);
-	
+
 	return 0;
 }
 
@@ -300,47 +300,47 @@
  *    reply
  *
  */
-static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
-				   struct sk_buff *skb) 
+static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+				   struct sk_buff *skb)
 {
 	struct qos_info qos;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 
 	switch(event) {
 	case IRLAN_DATA_INDICATION:
 		irlan_client_parse_response(self, skb);
-		
+
 		/*
-		 *  Check if we have got the remote TSAP for data 
+		 *  Check if we have got the remote TSAP for data
 		 *  communications
 		 */
-	  	IRDA_ASSERT(self->dtsap_sel_data != 0, return -1;);
+		IRDA_ASSERT(self->dtsap_sel_data != 0, return -1;);
 
 		/* Check which access type we are dealing with */
 		switch (self->client.access_type) {
 		case ACCESS_PEER:
 		    if (self->provider.state == IRLAN_OPEN) {
-			    
+
 			    irlan_next_client_state(self, IRLAN_ARB);
-			    irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, 
+			    irlan_do_client_event(self, IRLAN_CHECK_CON_ARB,
 						  NULL);
 		    } else {
-			
+
 			    irlan_next_client_state(self, IRLAN_WAIT);
 		    }
 		    break;
 		case ACCESS_DIRECT:
 		case ACCESS_HOSTED:
 			qos.link_disc_time.bits = 0x01; /* 3 secs */
-			
-			irttp_connect_request(self->tsap_data, 
-					      self->dtsap_sel_data, 
-					      self->saddr, self->daddr, &qos, 
+
+			irttp_connect_request(self->tsap_data,
+					      self->dtsap_sel_data,
+					      self->saddr, self->daddr, &qos,
 					      IRLAN_MTU, NULL);
-			
+
 			irlan_next_client_state(self, IRLAN_DATA);
 			break;
 		default:
@@ -359,7 +359,7 @@
 		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
 		break;
 	}
-	
+
 	if (skb)
 		dev_kfree_skb(skb);
 
@@ -373,13 +373,13 @@
  *    provider OPEN state.
  *
  */
-static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event, 
-				   struct sk_buff *skb) 
+static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
+				   struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
-	
+
 	switch(event) {
 	case IRLAN_PROVIDER_SIGNAL:
 		irlan_next_client_state(self, IRLAN_ARB);
@@ -398,36 +398,36 @@
 	}
 	if (skb)
 		dev_kfree_skb(skb);
-	
+
 	return 0;
 }
 
-static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event, 
-				  struct sk_buff *skb) 
+static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
+				  struct sk_buff *skb)
 {
 	struct qos_info qos;
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return -1;);
-	
+
 	switch(event) {
 	case IRLAN_CHECK_CON_ARB:
 		if (self->client.recv_arb_val == self->provider.send_arb_val) {
 			irlan_next_client_state(self, IRLAN_CLOSE);
 			irlan_close_data_channel(self);
-		} else if (self->client.recv_arb_val < 
-			   self->provider.send_arb_val) 
+		} else if (self->client.recv_arb_val <
+			   self->provider.send_arb_val)
 		{
 			qos.link_disc_time.bits = 0x01; /* 3 secs */
 
 			irlan_next_client_state(self, IRLAN_DATA);
-			irttp_connect_request(self->tsap_data, 
-					      self->dtsap_sel_data, 
-					      self->saddr, self->daddr, &qos, 
+			irttp_connect_request(self->tsap_data,
+					      self->dtsap_sel_data,
+					      self->saddr, self->daddr, &qos,
 					      IRLAN_MTU, NULL);
 		} else if (self->client.recv_arb_val >
-			   self->provider.send_arb_val) 
+			   self->provider.send_arb_val)
 		{
 			IRDA_DEBUG(2, "%s(), lost the battle :-(\n", __FUNCTION__ );
 		}
@@ -448,7 +448,7 @@
 	}
 	if (skb)
 		dev_kfree_skb(skb);
-	
+
 	return 0;
 }
 
@@ -459,8 +459,8 @@
  *    the local and remote machines.
  *
  */
-static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
-				   struct sk_buff *skb) 
+static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+				   struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
@@ -470,7 +470,7 @@
 	switch(event) {
 	case IRLAN_DATA_INDICATION:
 		irlan_client_parse_response(self, skb);
-		break;		
+		break;
 	case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
 	case IRLAN_LAP_DISCONNECT:
 		irlan_next_client_state(self, IRLAN_IDLE);
@@ -481,18 +481,18 @@
 	}
 	if (skb)
 		dev_kfree_skb(skb);
-	
+
 	return 0;
 }
 
 /*
  * Function irlan_client_state_close (self, event, skb, info)
  *
- *    
+ *
  *
  */
-static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
+static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
+				    struct sk_buff *skb)
 {
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
@@ -505,17 +505,17 @@
 /*
  * Function irlan_client_state_sync (self, event, skb, info)
  *
- *    
+ *
  *
  */
-static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event, 
-				   struct sk_buff *skb) 
+static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event,
+				   struct sk_buff *skb)
 {
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-	
+
 	if (skb)
 		dev_kfree_skb(skb);
-	
+
 	return 0;
 }
 
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index 2bb04ac..fcf9d65 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irlan_common.c
  * Version:       0.9
  * Description:   IrDA LAN Access Protocol Implementation
@@ -8,17 +8,17 @@
  * Created at:    Sun Aug 31 20:14:37 1997
  * Modified at:   Sun Dec 26 21:53:10 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
+ *
+ *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
  *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
  *
  ********************************************************************/
@@ -49,12 +49,12 @@
 
 #include <net/irda/irlan_common.h>
 #include <net/irda/irlan_client.h>
-#include <net/irda/irlan_provider.h> 
+#include <net/irda/irlan_provider.h>
 #include <net/irda/irlan_eth.h>
 #include <net/irda/irlan_filter.h>
 
 
-/* 
+/*
  * Send gratuitous ARP when connected to a new AP or not. May be a clever
  * thing to do, but for some reason the machine crashes if you use DHCP. So
  * lets not use it by default.
@@ -93,7 +93,7 @@
 
 static int irlan_seq_open(struct inode *inode, struct file *file);
 
-static struct file_operations irlan_fops = {
+static const struct file_operations irlan_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = irlan_seq_open,
 	.read    = seq_read,
@@ -106,8 +106,8 @@
 
 static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr);
 static void __irlan_close(struct irlan_cb *self);
-static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
-				__u8 value_byte, __u16 value_short, 
+static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
+				__u8 value_byte, __u16 value_short,
 				__u8 *value_array, __u16 value_len);
 static void irlan_open_unicast_addr(struct irlan_cb *self);
 static void irlan_get_unicast_addr(struct irlan_cb *self);
@@ -144,12 +144,18 @@
 	/* Register with IrLMP as a client */
 	ckey = irlmp_register_client(hints, &irlan_client_discovery_indication,
 				     NULL, NULL);
-	
+	if (!ckey)
+		goto err_ckey;
+
 	/* Register with IrLMP as a service */
- 	skey = irlmp_register_service(hints);
+	skey = irlmp_register_service(hints);
+	if (!skey)
+		goto err_skey;
 
 	/* Start the master IrLAN instance (the only one for now) */
- 	new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY);
+	new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY);
+	if (!new)
+		goto err_open;
 
 	/* The master will only open its (listen) control TSAP */
 	irlan_provider_open_ctrl_tsap(new);
@@ -158,9 +164,20 @@
 	irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
 
 	return 0;
+
+err_open:
+	irlmp_unregister_service(skey);
+err_skey:
+	irlmp_unregister_client(ckey);
+err_ckey:
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("irlan", proc_irda);
+#endif /* CONFIG_PROC_FS */
+
+	return -ENOMEM;
 }
 
-static void __exit irlan_cleanup(void) 
+static void __exit irlan_cleanup(void)
 {
 	struct irlan_cb *self, *next;
 
@@ -184,7 +201,7 @@
 /*
  * Function irlan_open (void)
  *
- *    Open new instance of a client/provider, we should only register the 
+ *    Open new instance of a client/provider, we should only register the
  *    network device if this instance is ment for a particular client/provider
  */
 static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
@@ -212,9 +229,9 @@
 	/* Provider access can only be PEER, DIRECT, or HOSTED */
 	self->provider.access_type = access;
 	if (access == ACCESS_DIRECT) {
-		/*  
+		/*
 		 * Since we are emulating an IrLAN sever we will have to
-		 * give ourself an ethernet address!  
+		 * give ourself an ethernet address!
 		 */
 		dev->dev_addr[0] = 0x40;
 		dev->dev_addr[1] = 0x00;
@@ -228,15 +245,15 @@
 	self->disconnect_reason = LM_USER_REQUEST;
 	init_timer(&self->watchdog_timer);
 	init_timer(&self->client.kick_timer);
-	init_waitqueue_head(&self->open_wait);	
-	
+	init_waitqueue_head(&self->open_wait);
+
 	skb_queue_head_init(&self->client.txq);
-	
+
 	irlan_next_client_state(self, IRLAN_IDLE);
 	irlan_next_provider_state(self, IRLAN_IDLE);
 
 	if (register_netdev(dev)) {
-		IRDA_DEBUG(2, "%s(), register_netdev() failed!\n", 
+		IRDA_DEBUG(2, "%s(), register_netdev() failed!\n",
 			   __FUNCTION__ );
 		self = NULL;
 		free_netdev(dev);
@@ -251,14 +268,14 @@
 /*
  * Function __irlan_close (self)
  *
- *    This function closes and deallocates the IrLAN client instances. Be 
+ *    This function closes and deallocates the IrLAN client instances. Be
  *    aware that other functions which calls client_close() must
  *    remove self from irlans list first.
  */
 static void __irlan_close(struct irlan_cb *self)
 {
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-	
+
 	ASSERT_RTNL();
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -268,8 +285,8 @@
 
 	/* Close all open connections and remove TSAPs */
 	irlan_close_tsaps(self);
-	
-	if (self->client.iriap) 
+
+	if (self->client.iriap)
 		iriap_close(self->client.iriap);
 
 	/* Remove frames queued on the control channel */
@@ -299,17 +316,17 @@
 static void irlan_connect_indication(void *instance, void *sap,
 				     struct qos_info *qos,
 				     __u32 max_sdu_size,
-				     __u8 max_header_size, 
+				     __u8 max_header_size,
 				     struct sk_buff *skb)
 {
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-	
+
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
-	
+
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 	IRDA_ASSERT(tsap == self->tsap_data,return;);
@@ -332,9 +349,9 @@
 	irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, NULL);
 
 	if (self->provider.access_type == ACCESS_PEER) {
-		/* 
+		/*
 		 * Data channel is open, so we are now allowed to
-		 * configure the remote filter 
+		 * configure the remote filter
 		 */
 		irlan_get_unicast_addr(self);
 		irlan_open_unicast_addr(self);
@@ -344,10 +361,10 @@
 }
 
 static void irlan_connect_confirm(void *instance, void *sap,
-				  struct qos_info *qos, 
+				  struct qos_info *qos,
 				  __u32 max_sdu_size,
-				  __u8 max_header_size, 
-				  struct sk_buff *skb) 
+				  __u8 max_header_size,
+				  struct sk_buff *skb)
 {
 	struct irlan_cb *self;
 
@@ -364,16 +381,16 @@
 	IRDA_DEBUG(0, "%s: We are now connected!\n", __FUNCTION__);
 	del_timer(&self->watchdog_timer);
 
-	/* 
+	/*
 	 * Data channel is open, so we are now allowed to configure the remote
-	 * filter 
+	 * filter
 	 */
 	irlan_get_unicast_addr(self);
 	irlan_open_unicast_addr(self);
-	
+
 	/* Open broadcast and multicast filter by default */
- 	irlan_set_broadcast_filter(self, TRUE);
- 	irlan_set_multicast_filter(self, TRUE);
+	irlan_set_broadcast_filter(self, TRUE);
+	irlan_set_multicast_filter(self, TRUE);
 
 	/* Ready to transfer Ethernet frames */
 	netif_start_queue(self->dev);
@@ -391,29 +408,29 @@
  *    the specified connection (handle)
  */
 static void irlan_disconnect_indication(void *instance,
-					void *sap, LM_REASON reason, 
-					struct sk_buff *userdata) 
+					void *sap, LM_REASON reason,
+					struct sk_buff *userdata)
 {
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
 
 	IRDA_DEBUG(0, "%s(), reason=%d\n", __FUNCTION__ , reason);
-	
+
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
 
 	IRDA_ASSERT(self != NULL, return;);
-	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	
+	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 	IRDA_ASSERT(tsap != NULL, return;);
 	IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
-	
+
 	IRDA_ASSERT(tsap == self->tsap_data, return;);
 
 	IRDA_DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
 
 	/* Save reason so we know if we should try to reconnect or not */
 	self->disconnect_reason = reason;
-	
+
 	switch (reason) {
 	case LM_USER_REQUEST: /* User request */
 		IRDA_DEBUG(2, "%s(), User requested\n", __FUNCTION__ );
@@ -434,7 +451,7 @@
 		IRDA_ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__);
 		break;
 	}
-	
+
 	/* If you want to pass the skb to *both* state machines, you will
 	 * need to skb_clone() it, so that you don't free it twice.
 	 * As the state machines don't need it, git rid of it here...
@@ -444,7 +461,7 @@
 
 	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
 	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
-	
+
 	wake_up_interruptible(&self->open_wait);
 }
 
@@ -463,12 +480,12 @@
 		return;
 
 	irda_notify_init(&notify);
-	
+
 	notify.data_indication       = irlan_eth_receive;
 	notify.udata_indication      = irlan_eth_receive;
 	notify.connect_indication    = irlan_connect_indication;
 	notify.connect_confirm       = irlan_connect_confirm;
- 	notify.flow_indication       = irlan_eth_flow_indication;
+	notify.flow_indication       = irlan_eth_flow_indication;
 	notify.disconnect_indication = irlan_disconnect_indication;
 	notify.instance              = self;
 	strlcpy(notify.name, "IrLAN data", sizeof(notify.name));
@@ -480,7 +497,7 @@
 	}
 	self->tsap_data = tsap;
 
-	/* 
+	/*
 	 *  This is the data TSAP selector which we will pass to the client
 	 *  when the client ask for it.
 	 */
@@ -501,13 +518,13 @@
 		self->tsap_data = NULL;
 	}
 	if (self->client.tsap_ctrl) {
-		irttp_disconnect_request(self->client.tsap_ctrl, NULL, 
+		irttp_disconnect_request(self->client.tsap_ctrl, NULL,
 					 P_NORMAL);
 		irttp_close_tsap(self->client.tsap_ctrl);
 		self->client.tsap_ctrl = NULL;
 	}
 	if (self->provider.tsap_ctrl) {
-		irttp_disconnect_request(self->provider.tsap_ctrl, NULL, 
+		irttp_disconnect_request(self->provider.tsap_ctrl, NULL,
 					 P_NORMAL);
 		irttp_close_tsap(self->provider.tsap_ctrl);
 		self->provider.tsap_ctrl = NULL;
@@ -528,8 +545,8 @@
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
-	
-	/* 
+
+	/*
 	 * Check if object has already been registered by a previous provider.
 	 * If that is the case, we just change the value of the attribute
 	 */
@@ -543,9 +560,9 @@
 		irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
 					      new_value);
 	}
-	
-        /* Register PnP object only if not registered before */
-        if (!irias_find_object("PnP")) {
+
+	/* Register PnP object only if not registered before */
+	if (!irias_find_object("PnP")) {
 		obj = irias_new_object("PnP", IAS_PNP_ID);
 #if 0
 		irias_add_string_attrib(obj, "Name", sysctl_devname,
@@ -589,10 +606,10 @@
 		self->client.tx_busy = FALSE;
 		return 0;
 	}
-	
+
 	/* Check that it's really possible to send commands */
-	if ((self->client.tsap_ctrl == NULL) || 
-	    (self->client.state == IRLAN_IDLE)) 
+	if ((self->client.tsap_ctrl == NULL) ||
+	    (self->client.state == IRLAN_IDLE))
 	{
 		self->client.tx_busy = FALSE;
 		dev_kfree_skb(skb);
@@ -632,7 +649,7 @@
 	__u8 *frame;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 
@@ -644,12 +661,12 @@
 	/* Reserve space for TTP, LMP, and LAP header */
 	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
-	
+
 	frame = skb->data;
-	
- 	frame[0] = CMD_GET_PROVIDER_INFO;
+
+	frame[0] = CMD_GET_PROVIDER_INFO;
 	frame[1] = 0x00;                 /* Zero parameters */
-	
+
 	irlan_ctrl_data_request(self, skb);
 }
 
@@ -659,16 +676,16 @@
  *    Send an Open Data Command to provider
  *
  */
-void irlan_open_data_channel(struct irlan_cb *self) 
+void irlan_open_data_channel(struct irlan_cb *self)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
-	
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
-	
+
 	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
 			IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3") +
 			IRLAN_STRING_PARAMETER_LEN("ACCESS_TYPE", "DIRECT"),
@@ -678,11 +695,11 @@
 
 	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
-	
+
 	frame = skb->data;
-	
+
 	/* Build frame */
- 	frame[0] = CMD_OPEN_DATA_CHANNEL;
+	frame[0] = CMD_OPEN_DATA_CHANNEL;
 	frame[1] = 0x02; /* Two parameters */
 
 	irlan_insert_string_param(skb, "MEDIA", "802.3");
@@ -694,11 +711,11 @@
 	irlan_ctrl_data_request(self, skb);
 }
 
-void irlan_close_data_channel(struct irlan_cb *self) 
+void irlan_close_data_channel(struct irlan_cb *self)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
-	
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return;);
@@ -716,11 +733,11 @@
 
 	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
-	
+
 	frame = skb->data;
-	
+
 	/* Build frame */
- 	frame[0] = CMD_CLOSE_DATA_CHAN;
+	frame[0] = CMD_CLOSE_DATA_CHAN;
 	frame[1] = 0x01; /* One parameter */
 
 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
@@ -731,7 +748,7 @@
 /*
  * Function irlan_open_unicast_addr (self)
  *
- *    Make IrLAN provider accept ethernet frames addressed to the unicast 
+ *    Make IrLAN provider accept ethernet frames addressed to the unicast
  *    address.
  *
  */
@@ -739,12 +756,12 @@
 {
 	struct sk_buff *skb;
 	__u8 *frame;
-	
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return;);
-	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	
-	
+	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+
 	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
 			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
 			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
@@ -756,15 +773,15 @@
 	/* Reserve space for TTP, LMP, and LAP header */
 	skb_reserve(skb, self->max_header_size);
 	skb_put(skb, 2);
-	
+
 	frame = skb->data;
-	
- 	frame[0] = CMD_FILTER_OPERATION;
+
+	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);
- 	irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
- 	irlan_insert_string_param(skb, "FILTER_MODE", "FILTER"); 
-	
+	irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);
+	irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+	irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
+
 	irlan_ctrl_data_request(self, skb);
 }
 
@@ -777,17 +794,17 @@
  *    one but then _we_ have to initiate all communication with other
  *    hosts, since ARP request for this host will not be answered.
  */
-void irlan_set_broadcast_filter(struct irlan_cb *self, int status) 
+void irlan_set_broadcast_filter(struct irlan_cb *self, int status)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
-	
- 	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+
+	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
 			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
 			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "BROADCAST") +
 			/* We may waste one byte here...*/
@@ -799,17 +816,17 @@
 	/* Reserve space for TTP, LMP, and LAP header */
 	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
-	
+
 	frame = skb->data;
-	
- 	frame[0] = CMD_FILTER_OPERATION;
+
+	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
- 	irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
+	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+	irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
 	if (status)
-		irlan_insert_string_param(skb, "FILTER_MODE", "FILTER"); 
+		irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
 	else
-		irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); 
+		irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
 
 	irlan_ctrl_data_request(self, skb);
 }
@@ -818,14 +835,14 @@
  * Function irlan_set_multicast_filter (self, status)
  *
  *    Make IrLAN provider accept ethernet frames addressed to the multicast
- *    address. 
+ *    address.
  *
  */
-void irlan_set_multicast_filter(struct irlan_cb *self, int status) 
+void irlan_set_multicast_filter(struct irlan_cb *self, int status)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return;);
@@ -839,21 +856,21 @@
 			GFP_ATOMIC);
 	if (!skb)
 		return;
-	
+
 	/* Reserve space for TTP, LMP, and LAP header */
 	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
-	
+
 	frame = skb->data;
-	
- 	frame[0] = CMD_FILTER_OPERATION;
+
+	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
- 	irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
+	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+	irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
 	if (status)
-		irlan_insert_string_param(skb, "FILTER_MODE", "ALL"); 
+		irlan_insert_string_param(skb, "FILTER_MODE", "ALL");
 	else
-		irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); 
+		irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
 
 	irlan_ctrl_data_request(self, skb);
 }
@@ -870,12 +887,12 @@
 {
 	struct sk_buff *skb;
 	__u8 *frame;
-		
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
-	
+
 	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
 			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
 			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
@@ -888,34 +905,34 @@
 	/* Reserve space for TTP, LMP, and LAP header */
 	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
-	
+
 	frame = skb->data;
-	
- 	frame[0] = CMD_FILTER_OPERATION;
+
+	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
- 	irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
- 	irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC"); 
-	
+	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+	irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+	irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC");
+
 	irlan_ctrl_data_request(self, skb);
 }
 
 /*
  * Function irlan_get_media_char (self)
  *
- *    
+ *
  *
  */
-void irlan_get_media_char(struct irlan_cb *self) 
+void irlan_get_media_char(struct irlan_cb *self)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
-	
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
-	
+
 	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
 			IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3"),
 			GFP_ATOMIC);
@@ -926,13 +943,13 @@
 	/* Reserve space for TTP, LMP, and LAP header */
 	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
-	
+
 	frame = skb->data;
-	
+
 	/* Build frame */
- 	frame[0] = CMD_GET_MEDIA_CHAR;
+	frame[0] = CMD_GET_MEDIA_CHAR;
 	frame[1] = 0x01; /* One parameter */
-	
+
 	irlan_insert_string_param(skb, "MEDIA", "802.3");
 	irlan_ctrl_data_request(self, skb);
 }
@@ -963,7 +980,7 @@
 {
 	int string_len = strlen(string);
 
-	return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string, 
+	return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string,
 				    string_len);
 }
 
@@ -976,7 +993,7 @@
 int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *array,
 			     __u16 array_len)
 {
-	return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array, 
+	return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array,
 				    array_len);
 }
 
@@ -989,19 +1006,19 @@
  *    | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
  *    -----------------------------------------------------------------------
  */
-static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
-				__u8 value_byte, __u16 value_short, 
+static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
+				__u8 value_byte, __u16 value_short,
 				__u8 *value_array, __u16 value_len)
 {
 	__u8 *frame;
 	__u8 param_len;
 	__le16 tmp_le; /* Temporary value in little endian format */
 	int n=0;
-	
+
 	if (skb == NULL) {
 		IRDA_DEBUG(2, "%s(), Got NULL skb\n", __FUNCTION__ );
 		return 0;
-	}	
+	}
 
 	param_len = strlen(param);
 	switch (type) {
@@ -1020,7 +1037,7 @@
 		return 0;
 		break;
 	}
-	
+
 	/* Insert at end of sk-buffer */
 	frame = skb->tail;
 
@@ -1028,15 +1045,15 @@
 	if (skb_tailroom(skb) < (param_len+value_len+3)) {
 		IRDA_DEBUG(2, "%s(), No more space at end of skb\n", __FUNCTION__ );
 		return 0;
-	}	
+	}
 	skb_put(skb, param_len+value_len+3);
-	
+
 	/* Insert parameter length */
 	frame[n++] = param_len;
-	
+
 	/* Insert parameter */
 	memcpy(frame+n, param, param_len); n += param_len;
-	
+
 	/* Insert value length (2 byte little endian format, LSB first) */
 	tmp_le = cpu_to_le16(value_len);
 	memcpy(frame+n, &tmp_le, 2); n += 2; /* To avoid alignment problems */
@@ -1065,36 +1082,36 @@
  * Function irlan_extract_param (buf, name, value, len)
  *
  *    Extracts a single parameter name/value pair from buffer and updates
- *    the buffer pointer to point to the next name/value pair. 
+ *    the buffer pointer to point to the next name/value pair.
  */
 int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
 {
 	__u8 name_len;
 	__u16 val_len;
 	int n=0;
-	
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	/* get length of parameter name (1 byte) */
 	name_len = buf[n++];
-	
+
 	if (name_len > 254) {
 		IRDA_DEBUG(2, "%s(), name_len > 254\n", __FUNCTION__ );
 		return -RSP_INVALID_COMMAND_FORMAT;
 	}
-	
+
 	/* get parameter name */
 	memcpy(name, buf+n, name_len);
 	name[name_len] = '\0';
 	n+=name_len;
-	
-	/*  
-	 *  Get length of parameter value (2 bytes in little endian 
-	 *  format) 
+
+	/*
+	 *  Get length of parameter value (2 bytes in little endian
+	 *  format)
 	 */
 	memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
 	le16_to_cpus(&val_len); n+=2;
-	
+
 	if (val_len > 1016) {
 		IRDA_DEBUG(2, "%s(), parameter length to long\n", __FUNCTION__ );
 		return -RSP_INVALID_COMMAND_FORMAT;
@@ -1105,9 +1122,9 @@
 	memcpy(value, buf+n, val_len);
 	value[val_len] = '\0';
 	n+=val_len;
-	
-	IRDA_DEBUG(4, "Parameter: %s ", name); 
-	IRDA_DEBUG(4, "Value: %s\n", value); 
+
+	IRDA_DEBUG(4, "Parameter: %s ", name);
+	IRDA_DEBUG(4, "Value: %s\n", value);
 
 	return n;
 }
@@ -1116,7 +1133,7 @@
 
 /*
  * Start of reading /proc entries.
- * Return entry at pos, 
+ * Return entry at pos,
  *	or start_token to indicate print header line
  *	or NULL if end of file
  */
@@ -1130,7 +1147,7 @@
 		return SEQ_START_TOKEN;
 
 	list_for_each_entry(self, &irlans, dev_list) {
-		if (*pos == i) 
+		if (*pos == i)
 			return self;
 		++i;
 	}
@@ -1143,12 +1160,12 @@
 	struct list_head *nxt;
 
 	++*pos;
-	if (v == SEQ_START_TOKEN) 
+	if (v == SEQ_START_TOKEN)
 		nxt = irlans.next;
 	else
 		nxt = ((struct irlan_cb *)v)->dev_list.next;
 
-	return (nxt == &irlans) ? NULL 
+	return (nxt == &irlans) ? NULL
 		: list_entry(nxt, struct irlan_cb, dev_list);
 }
 
@@ -1168,7 +1185,7 @@
 		seq_puts(seq, "IrLAN instances:\n");
 	else {
 		struct irlan_cb *self = v;
-		
+
 		IRDA_ASSERT(self != NULL, return -1;);
 		IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
 
@@ -1184,17 +1201,17 @@
 			       self->daddr);
 		seq_printf(seq,"version: %d.%d,\n",
 			       self->version[1], self->version[0]);
-		seq_printf(seq,"access type: %s\n", 
+		seq_printf(seq,"access type: %s\n",
 			       irlan_access[self->client.access_type]);
-		seq_printf(seq,"media: %s\n", 
+		seq_printf(seq,"media: %s\n",
 			       irlan_media[self->media]);
-		
+
 		seq_printf(seq,"local filter:\n");
 		seq_printf(seq,"remote filter: ");
 		irlan_print_filter(seq, self->client.filter_type);
-		seq_printf(seq,"tx busy: %s\n", 
+		seq_printf(seq,"tx busy: %s\n",
 			       netif_queue_stopped(self->dev) ? "TRUE" : "FALSE");
-			
+
 		seq_putc(seq,'\n');
 	}
 	return 0;
@@ -1214,7 +1231,7 @@
 #endif
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
+MODULE_DESCRIPTION("The Linux IrDA LAN protocol");
 MODULE_LICENSE("GPL");
 
 module_param(eth, bool, 0);
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
index b0ccc45..672ab3f 100644
--- a/net/irda/irlan/irlan_eth.c
+++ b/net/irda/irlan/irlan_eth.c
@@ -1,8 +1,8 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irlan_eth.c
- * Version:       
- * Description:   
+ * Version:
+ * Description:
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:37:58 1998
@@ -11,18 +11,18 @@
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- * 
+ *
  *     Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
- *  
+ *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
- *     
+ *
  ********************************************************************/
 
 #include <linux/netdevice.h>
@@ -55,7 +55,7 @@
 {
 	dev->open               = irlan_eth_open;
 	dev->stop               = irlan_eth_close;
-	dev->hard_start_xmit    = irlan_eth_xmit; 
+	dev->hard_start_xmit    = irlan_eth_xmit;
 	dev->get_stats	        = irlan_eth_get_stats;
 	dev->set_multicast_list = irlan_eth_set_multicast_list;
 	dev->destructor		= free_netdev;
@@ -63,8 +63,8 @@
 	SET_MODULE_OWNER(dev);
 
 	ether_setup(dev);
-	
-	/* 
+
+	/*
 	 * Lets do all queueing in IrTTP instead of this device driver.
 	 * Queueing here as well can introduce some strange latency
 	 * problems, which we will avoid by setting the queue size to 0.
@@ -104,17 +104,17 @@
 static int irlan_eth_open(struct net_device *dev)
 {
 	struct irlan_cb *self = netdev_priv(dev);
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
 	/* Ready to play! */
- 	netif_stop_queue(dev); /* Wait until data link is ready */
+	netif_stop_queue(dev); /* Wait until data link is ready */
 
 	/* We are now open, so time to do some work */
 	self->disconnect_reason = 0;
 	irlan_client_wakeup(self, self->saddr, self->daddr);
 
-	/* Make sure we have a hardware address before we return, 
+	/* Make sure we have a hardware address before we return,
 	   so DHCP clients gets happy */
 	return wait_event_interruptible(self->open_wait,
 					!self->tsap_data->connected);
@@ -124,30 +124,30 @@
  * Function irlan_eth_close (dev)
  *
  *    Stop the ether network device, his function will usually be called by
- *    ifconfig down. We should now disconnect the link, We start the 
+ *    ifconfig down. We should now disconnect the link, We start the
  *    close timer, so that the instance will be removed if we are unable
  *    to discover the remote device after the disconnect.
  */
 static int irlan_eth_close(struct net_device *dev)
 {
 	struct irlan_cb *self = netdev_priv(dev);
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-	
+
 	/* Stop device */
 	netif_stop_queue(dev);
-	
+
 	irlan_close_data_channel(self);
 	irlan_close_tsaps(self);
 
 	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
-	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);	
-	
+	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
+
 	/* Remove frames queued on the control channel */
 	skb_queue_purge(&self->client.txq);
 
 	self->client.tx_busy = 0;
-	
+
 	return 0;
 }
 
@@ -164,7 +164,7 @@
 
 	/* skb headroom large enough to contain all IrDA-headers? */
 	if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) {
-		struct sk_buff *new_skb = 
+		struct sk_buff *new_skb =
 			skb_realloc_headroom(skb, self->max_header_size);
 
 		/*  We have to free the original skb anyway */
@@ -176,7 +176,7 @@
 
 		/* Use the new skb instead */
 		skb = new_skb;
-	} 
+	}
 
 	dev->trans_start = jiffies;
 
@@ -187,7 +187,7 @@
 		ret = irttp_data_request(self->tsap_data, skb);
 
 	if (ret < 0) {
-		/*   
+		/*
 		 * IrTTPs tx queue is full, so we just have to
 		 * drop the frame! You might think that we should
 		 * just return -1 and don't deallocate the frame,
@@ -195,15 +195,15 @@
 		 * we have replaced the original skb with a new
 		 * one with larger headroom, and that would really
 		 * confuse do_dev_queue_xmit() in dev.c! I have
-		 * tried :-) DB 
+		 * tried :-) DB
 		 */
 		/* irttp_data_request already free the packet */
 		self->stats.tx_dropped++;
 	} else {
 		self->stats.tx_packets++;
-		self->stats.tx_bytes += skb->len; 
+		self->stats.tx_bytes += skb->len;
 	}
-	
+
 	return 0;
 }
 
@@ -218,37 +218,37 @@
 	struct irlan_cb *self = instance;
 
 	if (skb == NULL) {
-		++self->stats.rx_dropped; 
+		++self->stats.rx_dropped;
 		return 0;
 	}
 	if (skb->len < ETH_HLEN) {
 		IRDA_DEBUG(0, "%s() : IrLAN frame too short (%d)\n",
 			   __FUNCTION__, skb->len);
-		++self->stats.rx_dropped; 
+		++self->stats.rx_dropped;
 		dev_kfree_skb(skb);
 		return 0;
 	}
-		
-	/* 
-	 * Adopt this frame! Important to set all these fields since they 
+
+	/*
+	 * Adopt this frame! Important to set all these fields since they
 	 * might have been previously set by the low level IrDA network
-	 * device driver 
+	 * device driver
 	 */
 	skb->dev = self->dev;
 	skb->protocol=eth_type_trans(skb, skb->dev); /* Remove eth header */
-	
+
 	self->stats.rx_packets++;
-	self->stats.rx_bytes += skb->len; 
+	self->stats.rx_bytes += skb->len;
 
 	netif_rx(skb);   /* Eat it! */
-	
+
 	return 0;
 }
 
 /*
  * Function irlan_eth_flow (status)
  *
- *    Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by 
+ *    Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by
  *    controlling the queue stop/start.
  *
  * The IrDA link layer has the advantage to have flow control, and
@@ -268,11 +268,11 @@
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
-	
+
 	dev = self->dev;
 
 	IRDA_ASSERT(dev != NULL, return;);
-	
+
 	IRDA_DEBUG(0, "%s() : flow %s ; running %d\n", __FUNCTION__,
 		   flow == FLOW_STOP ? "FLOW_STOP" : "FLOW_START",
 		   netif_running(dev));
@@ -301,10 +301,10 @@
 {
 	struct in_device *in_dev;
 
-	/* 
+	/*
 	 * When we get a new MAC address do a gratuitous ARP. This
 	 * is useful if we have changed access points on the same
-	 * subnet.  
+	 * subnet.
 	 */
 #ifdef CONFIG_INET
 	IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
@@ -313,10 +313,10 @@
 	if (in_dev == NULL)
 		goto out;
 	if (in_dev->ifa_list)
-		
-	arp_send(ARPOP_REQUEST, ETH_P_ARP, 
+
+	arp_send(ARPOP_REQUEST, ETH_P_ARP,
 		 in_dev->ifa_list->ifa_address,
-		 dev, 
+		 dev,
 		 in_dev->ifa_list->ifa_address,
 		 NULL, dev->dev_addr, NULL);
 out:
@@ -331,9 +331,9 @@
  *
  */
 #define HW_MAX_ADDRS 4 /* Must query to get it! */
-static void irlan_eth_set_multicast_list(struct net_device *dev) 
+static void irlan_eth_set_multicast_list(struct net_device *dev)
 {
- 	struct irlan_cb *self = netdev_priv(dev);
+	struct irlan_cb *self = netdev_priv(dev);
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
 
@@ -346,7 +346,7 @@
 	if (dev->flags & IFF_PROMISC) {
 		/* Enable promiscuous mode */
 		IRDA_WARNING("Promiscous mode not implemented by IrLAN!\n");
-	} 
+	}
 	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
 		/* Disable promiscuous mode, use normal mode. */
 		IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __FUNCTION__ );
@@ -378,7 +378,7 @@
  *    Get the current statistics for this device
  *
  */
-static struct net_device_stats *irlan_eth_get_stats(struct net_device *dev) 
+static struct net_device_stats *irlan_eth_get_stats(struct net_device *dev)
 {
 	struct irlan_cb *self = netdev_priv(dev);
 
diff --git a/net/irda/irlan/irlan_event.c b/net/irda/irlan/irlan_event.c
index 2778d8c..623e0fd 100644
--- a/net/irda/irlan/irlan_event.c
+++ b/net/irda/irlan/irlan_event.c
@@ -1,25 +1,25 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irlan_event.c
- * Version:       
- * Description:   
+ * Version:
+ * Description:
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Oct 20 09:10:16 1998
  * Modified at:   Sat Oct 30 12:59:01 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
- *  
+ *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
- *     
+ *
  ********************************************************************/
 
 #include <net/irda/irlan_event.h>
@@ -38,7 +38,7 @@
 	"IRLAN_SYNC",
 };
 
-void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state) 
+void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state)
 {
 	IRDA_DEBUG(2, "%s(), %s\n", __FUNCTION__ , irlan_state[state]);
 
@@ -48,7 +48,7 @@
 	self->client.state = state;
 }
 
-void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state) 
+void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state)
 {
 	IRDA_DEBUG(2, "%s(), %s\n", __FUNCTION__ , irlan_state[state]);
 
diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c
index ca7d358..e6346b8 100644
--- a/net/irda/irlan/irlan_filter.c
+++ b/net/irda/irlan/irlan_filter.c
@@ -1,25 +1,25 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irlan_filter.c
- * Version:       
- * Description:   
+ * Version:
+ * Description:
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Jan 29 11:16:38 1999
  * Modified at:   Sat Oct 30 12:58:45 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
- *  
+ *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
- *     
+ *
  ********************************************************************/
 
 #include <linux/skbuff.h>
@@ -40,7 +40,7 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+	if ((self->provider.filter_type == IRLAN_DIRECTED) &&
 	    (self->provider.filter_operation == DYNAMIC))
 	{
 		IRDA_DEBUG(0, "Giving peer a dynamic Ethernet address\n");
@@ -48,12 +48,12 @@
 		self->provider.mac_address[1] = 0x00;
 		self->provider.mac_address[2] = 0x00;
 		self->provider.mac_address[3] = 0x00;
-		
+
 		/* Use arbitration value to generate MAC address */
 		if (self->provider.access_type == ACCESS_PEER) {
-			self->provider.mac_address[4] = 
+			self->provider.mac_address[4] =
 				self->provider.send_arb_val & 0xff;
-			self->provider.mac_address[5] = 
+			self->provider.mac_address[5] =
 				(self->provider.send_arb_val >> 8) & 0xff;
 		} else {
 			/* Just generate something for now */
@@ -65,12 +65,12 @@
 		skb->data[1] = 0x03;
 		irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
 		irlan_insert_short_param(skb, "MAX_ENTRY", 0x0001);
-		irlan_insert_array_param(skb, "FILTER_ENTRY", 
+		irlan_insert_array_param(skb, "FILTER_ENTRY",
 					 self->provider.mac_address, 6);
 		return;
 	}
-	
-	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+
+	if ((self->provider.filter_type == IRLAN_DIRECTED) &&
 	    (self->provider.filter_mode == FILTER))
 	{
 		IRDA_DEBUG(0, "Directed filter on\n");
@@ -78,7 +78,7 @@
 		skb->data[1] = 0x00;
 		return;
 	}
-	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+	if ((self->provider.filter_type == IRLAN_DIRECTED) &&
 	    (self->provider.filter_mode == NONE))
 	{
 		IRDA_DEBUG(0, "Directed filter off\n");
@@ -87,7 +87,7 @@
 		return;
 	}
 
-	if ((self->provider.filter_type == IRLAN_BROADCAST) && 
+	if ((self->provider.filter_type == IRLAN_BROADCAST) &&
 	    (self->provider.filter_mode == FILTER))
 	{
 		IRDA_DEBUG(0, "Broadcast filter on\n");
@@ -95,7 +95,7 @@
 		skb->data[1] = 0x00;
 		return;
 	}
-	if ((self->provider.filter_type == IRLAN_BROADCAST) && 
+	if ((self->provider.filter_type == IRLAN_BROADCAST) &&
 	    (self->provider.filter_mode == NONE))
 	{
 		IRDA_DEBUG(0, "Broadcast filter off\n");
@@ -103,7 +103,7 @@
 		skb->data[1] = 0x00;
 		return;
 	}
-	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+	if ((self->provider.filter_type == IRLAN_MULTICAST) &&
 	    (self->provider.filter_mode == FILTER))
 	{
 		IRDA_DEBUG(0, "Multicast filter on\n");
@@ -111,7 +111,7 @@
 		skb->data[1] = 0x00;
 		return;
 	}
-	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+	if ((self->provider.filter_type == IRLAN_MULTICAST) &&
 	    (self->provider.filter_mode == NONE))
 	{
 		IRDA_DEBUG(0, "Multicast filter off\n");
@@ -119,7 +119,7 @@
 		skb->data[1] = 0x00;
 		return;
 	}
-	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+	if ((self->provider.filter_type == IRLAN_MULTICAST) &&
 	    (self->provider.filter_operation == GET))
 	{
 		IRDA_DEBUG(0, "Multicast filter get\n");
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
index 58efde9..aac6643 100644
--- a/net/irda/irlan/irlan_provider.c
+++ b/net/irda/irlan/irlan_provider.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irlan_provider.c
  * Version:       0.9
  * Description:   IrDA LAN Access Protocol Implementation
@@ -11,17 +11,17 @@
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
  *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
  *
  ********************************************************************/
@@ -52,8 +52,8 @@
 #include <net/irda/irlan_filter.h>
 #include <net/irda/irlan_client.h>
 
-static void irlan_provider_connect_indication(void *instance, void *sap, 
-					      struct qos_info *qos, 
+static void irlan_provider_connect_indication(void *instance, void *sap,
+					      struct qos_info *qos,
 					      __u32 max_sdu_size,
 					      __u8 max_header_size,
 					      struct sk_buff *skb);
@@ -64,14 +64,14 @@
  *    This function gets the data that is received on the control channel
  *
  */
-static int irlan_provider_data_indication(void *instance, void *sap, 
-					  struct sk_buff *skb) 
+static int irlan_provider_data_indication(void *instance, void *sap,
+					  struct sk_buff *skb)
 {
 	struct irlan_cb *self;
 	__u8 code;
-	
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	self = (struct irlan_cb *) instance;
 
 	IRDA_ASSERT(self != NULL, return -1;);
@@ -83,16 +83,16 @@
 	switch(code) {
 	case CMD_GET_PROVIDER_INFO:
 		IRDA_DEBUG(4, "Got GET_PROVIDER_INFO command!\n");
-		irlan_do_provider_event(self, IRLAN_GET_INFO_CMD, skb); 
+		irlan_do_provider_event(self, IRLAN_GET_INFO_CMD, skb);
 		break;
 
 	case CMD_GET_MEDIA_CHAR:
 		IRDA_DEBUG(4, "Got GET_MEDIA_CHAR command!\n");
-		irlan_do_provider_event(self, IRLAN_GET_MEDIA_CMD, skb); 
+		irlan_do_provider_event(self, IRLAN_GET_MEDIA_CMD, skb);
 		break;
 	case CMD_OPEN_DATA_CHANNEL:
 		IRDA_DEBUG(4, "Got OPEN_DATA_CHANNEL command!\n");
-		irlan_do_provider_event(self, IRLAN_OPEN_DATA_CMD, skb); 
+		irlan_do_provider_event(self, IRLAN_OPEN_DATA_CMD, skb);
 		break;
 	case CMD_FILTER_OPERATION:
 		IRDA_DEBUG(4, "Got FILTER_OPERATION command!\n");
@@ -119,9 +119,9 @@
  *    Got connection from peer IrLAN client
  *
  */
-static void irlan_provider_connect_indication(void *instance, void *sap, 
+static void irlan_provider_connect_indication(void *instance, void *sap,
 					      struct qos_info *qos,
-					      __u32 max_sdu_size, 
+					      __u32 max_sdu_size,
 					      __u8 max_header_size,
 					      struct sk_buff *skb)
 {
@@ -130,13 +130,13 @@
 	__u32 saddr, daddr;
 
 	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
-	
+
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
-	
+
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
-	
+
 	IRDA_ASSERT(tsap == self->provider.tsap_ctrl,return;);
 	IRDA_ASSERT(self->provider.state == IRLAN_IDLE, return;);
 
@@ -147,13 +147,13 @@
 
 	irlan_do_provider_event(self, IRLAN_CONNECT_INDICATION, NULL);
 
-	/*  
+	/*
 	 * If we are in peer mode, the client may not have got the discovery
-	 * indication it needs to make progress. If the client is still in 
-	 * IDLE state, we must kick it. 
+	 * indication it needs to make progress. If the client is still in
+	 * IDLE state, we must kick it.
 	 */
-	if ((self->provider.access_type == ACCESS_PEER) && 
-	    (self->client.state == IRLAN_IDLE)) 
+	if ((self->provider.access_type == ACCESS_PEER) &&
+	    (self->client.state == IRLAN_IDLE))
 	{
 		irlan_client_wakeup(self, self->saddr, self->daddr);
 	}
@@ -175,38 +175,38 @@
 	irttp_connect_response(tsap, IRLAN_MTU, NULL);
 }
 
-static void irlan_provider_disconnect_indication(void *instance, void *sap, 
-						 LM_REASON reason, 
-						 struct sk_buff *userdata) 
+static void irlan_provider_disconnect_indication(void *instance, void *sap,
+						 LM_REASON reason,
+						 struct sk_buff *userdata)
 {
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
 
 	IRDA_DEBUG(4, "%s(), reason=%d\n", __FUNCTION__ , reason);
-	
+
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
 
 	IRDA_ASSERT(self != NULL, return;);
-	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	
+	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 	IRDA_ASSERT(tsap != NULL, return;);
 	IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
-	
+
 	IRDA_ASSERT(tsap == self->provider.tsap_ctrl, return;);
-	
+
 	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
 }
 
 /*
  * Function irlan_parse_open_data_cmd (self, skb)
  *
- *    
+ *
  *
  */
 int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb)
 {
 	int ret;
-	
+
 	ret = irlan_provider_parse_command(self, CMD_OPEN_DATA_CHANNEL, skb);
 
 	/* Open data channel */
@@ -218,12 +218,12 @@
 /*
  * Function parse_command (skb)
  *
- *    Extract all parameters from received buffer, then feed them to 
+ *    Extract all parameters from received buffer, then feed them to
  *    check_params for parsing
  *
  */
 int irlan_provider_parse_command(struct irlan_cb *self, int cmd,
-				 struct sk_buff *skb) 
+				 struct sk_buff *skb)
 {
 	__u8 *frame;
 	__u8 *ptr;
@@ -231,16 +231,16 @@
 	__u16 val_len;
 	int i;
 	char *name;
-        char *value;
+	char *value;
 	int ret = RSP_SUCCESS;
-	
+
 	IRDA_ASSERT(skb != NULL, return -RSP_PROTOCOL_ERROR;);
-	
+
 	IRDA_DEBUG(4, "%s(), skb->len=%d\n", __FUNCTION__ , (int)skb->len);
 
 	IRDA_ASSERT(self != NULL, return -RSP_PROTOCOL_ERROR;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;);
-	
+
 	if (!skb)
 		return -RSP_PROTOCOL_ERROR;
 
@@ -259,11 +259,11 @@
 	count = frame[1];
 
 	IRDA_DEBUG(4, "Got %d parameters\n", count);
-	
+
 	ptr = frame+2;
-	
+
 	/* For all parameters */
- 	for (i=0; i<count;i++) {
+	for (i=0; i<count;i++) {
 		ret = irlan_extract_param(ptr, name, value, &val_len);
 		if (ret < 0) {
 			IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __FUNCTION__ );
@@ -286,7 +286,7 @@
  *    Send reply to query to peer IrLAN layer
  *
  */
-void irlan_provider_send_reply(struct irlan_cb *self, int command, 
+void irlan_provider_send_reply(struct irlan_cb *self, int command,
 			       int ret_code)
 {
 	struct sk_buff *skb;
@@ -310,7 +310,7 @@
 	/* Reserve space for TTP, LMP, and LAP header */
 	skb_reserve(skb, self->provider.max_header_size);
 	skb_put(skb, 2);
-       
+
 	switch (command) {
 	case CMD_GET_PROVIDER_INFO:
 		skb->data[0] = 0x00; /* Success */
@@ -356,7 +356,7 @@
 		skb->data[0] = 0x00; /* Success */
 		if (self->provider.send_arb_val) {
 			skb->data[1] = 0x03; /* 3 parameters */
-			irlan_insert_short_param(skb, "CON_ARB", 
+			irlan_insert_short_param(skb, "CON_ARB",
 						 self->provider.send_arb_val);
 		} else
 			skb->data[1] = 0x02; /* 2 parameters */
@@ -378,13 +378,13 @@
  * Function irlan_provider_register(void)
  *
  *    Register provider support so we can accept incoming connections.
- * 
+ *
  */
 int irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
 {
 	struct tsap_cb *tsap;
 	notify_t notify;
-	
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
 	IRDA_ASSERT(self != NULL, return -1;);
@@ -393,7 +393,7 @@
 	/* Check if already open */
 	if (self->provider.tsap_ctrl)
 		return -1;
-	
+
 	/*
 	 *  First register well known control TSAP
 	 */
diff --git a/net/irda/irlan/irlan_provider_event.c b/net/irda/irlan/irlan_provider_event.c
index 5a086f9..ef401bd 100644
--- a/net/irda/irlan/irlan_provider_event.c
+++ b/net/irda/irlan/irlan_provider_event.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irlan_provider_event.c
  * Version:       0.9
  * Description:   IrLAN provider state machine)
@@ -8,16 +8,16 @@
  * Created at:    Sun Aug 31 20:14:37 1997
  * Modified at:   Sat Oct 30 12:52:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
  *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
  *
  ********************************************************************/
@@ -30,18 +30,18 @@
 #include <net/irda/irlan_provider.h>
 #include <net/irda/irlan_event.h>
 
-static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
 				     struct sk_buff *skb);
-static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
 				     struct sk_buff *skb);
-static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
 				     struct sk_buff *skb);
-static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event,
 				     struct sk_buff *skb);
 
-static int (*state[])(struct irlan_cb *self, IRLAN_EVENT event, 
-		      struct sk_buff *skb) = 
-{ 
+static int (*state[])(struct irlan_cb *self, IRLAN_EVENT event,
+		      struct sk_buff *skb) =
+{
 	irlan_provider_state_idle,
 	NULL, /* Query */
 	NULL, /* Info */
@@ -55,8 +55,8 @@
 	NULL, /* Sync */
 };
 
-void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event, 
-			     struct sk_buff *skb) 
+void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event,
+			     struct sk_buff *skb)
 {
 	IRDA_ASSERT(*state[ self->provider.state] != NULL, return;);
 
@@ -73,9 +73,9 @@
 				     struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
-	
+
 	switch(event) {
 	case IRLAN_CONNECT_INDICATION:
 	     irlan_provider_connect_response( self, self->provider.tsap_ctrl);
@@ -96,13 +96,13 @@
  *
  *    INFO, We have issued a GetInfo command and is awaiting a reply.
  */
-static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
-				     struct sk_buff *skb) 
+static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+				     struct sk_buff *skb)
 {
 	int ret;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 
 	switch(event) {
@@ -110,7 +110,7 @@
 		/* Be sure to use 802.3 in case of peer mode */
 		if (self->provider.access_type == ACCESS_PEER) {
 			self->media = MEDIA_802_3;
-			
+
 			/* Check if client has started yet */
 			if (self->client.state == IRLAN_IDLE) {
 				/* This should get the client going */
@@ -118,15 +118,15 @@
 			}
 		}
 
-		irlan_provider_send_reply(self, CMD_GET_PROVIDER_INFO, 
+		irlan_provider_send_reply(self, CMD_GET_PROVIDER_INFO,
 					  RSP_SUCCESS);
 		/* Keep state */
 		break;
-	case IRLAN_GET_MEDIA_CMD: 
-		irlan_provider_send_reply(self, CMD_GET_MEDIA_CHAR, 
+	case IRLAN_GET_MEDIA_CMD:
+		irlan_provider_send_reply(self, CMD_GET_MEDIA_CHAR,
 					  RSP_SUCCESS);
 		/* Keep state */
-		break;		
+		break;
 	case IRLAN_OPEN_DATA_CMD:
 		ret = irlan_parse_open_data_cmd(self, skb);
 		if (self->provider.access_type == ACCESS_PEER) {
@@ -152,7 +152,7 @@
 	}
 	if (skb)
 		dev_kfree_skb(skb);
-	
+
 	return 0;
 }
 
@@ -163,7 +163,7 @@
  *    reply
  *
  */
-static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
 				     struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
@@ -173,11 +173,11 @@
 	switch(event) {
 	case IRLAN_FILTER_CONFIG_CMD:
 		irlan_provider_parse_command(self, CMD_FILTER_OPERATION, skb);
-		irlan_provider_send_reply(self, CMD_FILTER_OPERATION, 
+		irlan_provider_send_reply(self, CMD_FILTER_OPERATION,
 					  RSP_SUCCESS);
 		/* Keep state */
 		break;
-	case IRLAN_DATA_CONNECT_INDICATION: 
+	case IRLAN_DATA_CONNECT_INDICATION:
 		irlan_next_provider_state(self, IRLAN_DATA);
 		irlan_provider_connect_response(self, self->tsap_data);
 		break;
@@ -202,8 +202,8 @@
  *    the local and remote machines.
  *
  */
-static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
-				     struct sk_buff *skb) 
+static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+				     struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
@@ -213,7 +213,7 @@
 	switch(event) {
 	case IRLAN_FILTER_CONFIG_CMD:
 		irlan_provider_parse_command(self, CMD_FILTER_OPERATION, skb);
-		irlan_provider_send_reply(self, CMD_FILTER_OPERATION, 
+		irlan_provider_send_reply(self, CMD_FILTER_OPERATION,
 					  RSP_SUCCESS);
 		break;
 	case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
@@ -226,7 +226,7 @@
 	}
 	if (skb)
 		dev_kfree_skb(skb);
-	
+
 	return 0;
 }
 
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index e7852a0..d93ebd1 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -87,7 +87,7 @@
 	/* Allocate master array */
 	irlap = hashbin_new(HB_LOCK);
 	if (irlap == NULL) {
-	        IRDA_ERROR("%s: can't allocate irlap hashbin!\n",
+		IRDA_ERROR("%s: can't allocate irlap hashbin!\n",
 			   __FUNCTION__);
 		return -ENOMEM;
 	}
@@ -701,8 +701,8 @@
 	int count = 0;
 
 	/*
-         * Remove all the ack-ed frames from the window queue.
-         */
+	 * Remove all the ack-ed frames from the window queue.
+	 */
 
 	/*
 	 *  Optimize for the common case. It is most likely that the receiver
@@ -1109,13 +1109,13 @@
 	spin_lock_irq(&irlap->hb_spinlock);
 	iter->id = 0;
 
-	for (self = (struct irlap_cb *) hashbin_get_first(irlap); 
+	for (self = (struct irlap_cb *) hashbin_get_first(irlap);
 	     self; self = (struct irlap_cb *) hashbin_get_next(irlap)) {
 		if (iter->id == *pos)
 			break;
 		++iter->id;
 	}
-		
+
 	return self;
 }
 
@@ -1137,7 +1137,7 @@
 {
 	const struct irlap_iter_state *iter = seq->private;
 	const struct irlap_cb *self = v;
-	
+
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -EINVAL;);
 
 	seq_printf(seq, "irlap%d ", iter->id);
@@ -1222,7 +1222,7 @@
 	struct seq_file *seq;
 	int rc = -ENOMEM;
 	struct irlap_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
-       
+
 	if (!s)
 		goto out;
 
@@ -1244,7 +1244,7 @@
 	goto out;
 }
 
-struct file_operations irlap_seq_fops = {
+const struct file_operations irlap_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = irlap_seq_open,
 	.read           = seq_read,
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
index 99faff6..7b6433f 100644
--- a/net/irda/irlap_event.c
+++ b/net/irda/irlap_event.c
@@ -827,7 +827,7 @@
 		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
 		break;
 	default:
-		IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __FUNCTION__, 
+		IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __FUNCTION__,
 			   event, irlap_event[event]);
 
 		ret = -1;
@@ -864,7 +864,7 @@
  *  between 15 msecs and 45 msecs.
  */
 			irlap_start_backoff_timer(self, msecs_to_jiffies(20 +
-						        (jiffies % 30)));
+							(jiffies % 30)));
 		} else {
 			/* Always switch state before calling upper layers */
 			irlap_next_state(self, LAP_NDM);
@@ -1377,7 +1377,7 @@
 				/* Resend rejected frames */
 				irlap_resend_rejected_frames(self, CMD_FRAME);
 
-				/* Give peer some time to retransmit! 
+				/* Give peer some time to retransmit!
 				 * But account for our own Tx. */
 				irlap_start_final_timer(self, 2 * self->final_timeout);
 
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
index dba349c..0b04603 100644
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -414,7 +414,7 @@
 		IRDA_ERROR("%s: frame to short!\n", __FUNCTION__);
 		return;
 	}
-		
+
 	xid = (struct xid_frame *) skb->data;
 
 	info->daddr = le32_to_cpu(xid->saddr);
@@ -485,7 +485,7 @@
 		IRDA_ERROR("%s: frame to short!\n", __FUNCTION__);
 		return;
 	}
-	
+
 	xid = (struct xid_frame *) skb->data;
 
 	info->daddr = le32_to_cpu(xid->saddr);
@@ -524,7 +524,7 @@
 	 */
 	if (info->s == 0xff) {
 		/* Check if things are sane at this point... */
-		if((discovery_info == NULL) || 
+		if((discovery_info == NULL) ||
 		   !pskb_may_pull(skb, 3)) {
 			IRDA_ERROR("%s: discovery frame to short!\n",
 				   __FUNCTION__);
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 7e5d12a..9df0461 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -116,7 +116,7 @@
  *    Remove IrLMP layer
  *
  */
-void __exit irlmp_cleanup(void) 
+void __exit irlmp_cleanup(void)
 {
 	/* Check for main structure */
 	IRDA_ASSERT(irlmp != NULL, return;);
@@ -892,7 +892,7 @@
 
 	/*
 	 * Start a single discovery operation if discovery is not already
-         * running
+	 * running
 	 */
 	if (!sysctl_discovery) {
 		/* Check if user wants to override the default */
@@ -1528,12 +1528,12 @@
 
 	/* Refresh current hint bits */
 	spin_lock_irqsave(&irlmp->services->hb_spinlock, flags);
-        service = (irlmp_service_t *) hashbin_get_first(irlmp->services);
-        while (service) {
+	service = (irlmp_service_t *) hashbin_get_first(irlmp->services);
+	while (service) {
 		irlmp->hints.word |= service->hints.word;
 
-                service = (irlmp_service_t *)hashbin_get_next(irlmp->services);
-        }
+		service = (irlmp_service_t *)hashbin_get_next(irlmp->services);
+	}
 	spin_unlock_irqrestore(&irlmp->services->hb_spinlock, flags);
 	return 0;
 }
@@ -1861,7 +1861,7 @@
 
 	spin_lock_irq(&iter->hashbin->hb_spinlock);
 	for (element = hashbin_get_first(iter->hashbin);
-	     element != NULL; 
+	     element != NULL;
 	     element = hashbin_get_next(iter->hashbin)) {
 		if (!off || *off-- == 0) {
 			/* NB: hashbin left locked */
@@ -1918,7 +1918,7 @@
 	if (v == NULL) {			/* no more in this hash bin */
 		spin_unlock_irq(&iter->hashbin->hb_spinlock);
 
-		if (iter->hashbin == irlmp->unconnected_lsaps) 
+		if (iter->hashbin == irlmp->unconnected_lsaps)
 			v =  LINK_START_TOKEN;
 
 		iter->hashbin = NULL;
@@ -2026,7 +2026,7 @@
 	goto out;
 }
 
-struct file_operations irlmp_seq_fops = {
+const struct file_operations irlmp_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = irlmp_seq_open,
 	.read           = seq_read,
diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c
index 4c90dd1..65ffa98 100644
--- a/net/irda/irlmp_event.c
+++ b/net/irda/irlmp_event.c
@@ -615,7 +615,7 @@
 	default:
 		/* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
 		 * are *not* yet bound to the IrLAP link. Jean II */
-		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n", 
+		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
 			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
 		break;
 	}
diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c
index 39761a1..559302d 100644
--- a/net/irda/irlmp_frame.c
+++ b/net/irda/irlmp_frame.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irlmp_frame.c
  * Version:       0.9
  * Description:   IrLMP frame implementation
@@ -8,18 +8,18 @@
  * Created at:    Tue Aug 19 02:09:59 1997
  * Modified at:   Mon Dec 13 13:41:12 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
  *     All Rights Reserved.
  *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
  *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
  *
  ********************************************************************/
@@ -34,7 +34,7 @@
 #include <net/irda/irlmp_frame.h>
 #include <net/irda/discovery.h>
 
-static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap, 
+static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap,
 				       __u8 slsap, int status, hashbin_t *);
 
 inline void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
@@ -56,18 +56,18 @@
  *    Send Link Control Frame to IrLAP
  */
 void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
-			__u8 opcode, struct sk_buff *skb) 
+			__u8 opcode, struct sk_buff *skb)
 {
 	__u8 *frame;
-	
+
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	IRDA_ASSERT(skb != NULL, return;);
-	
+
 	frame = skb->data;
-	
+
 	frame[0] = dlsap | CONTROL_BIT;
 	frame[1] = slsap;
 
@@ -87,14 +87,14 @@
  *    Used by IrLAP to pass received data frames to IrLMP layer
  *
  */
-void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb, 
+void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
 				int unreliable)
 {
 	struct lsap_cb *lsap;
 	__u8   slsap_sel;   /* Source (this) LSAP address */
 	__u8   dlsap_sel;   /* Destination LSAP address */
 	__u8   *fp;
-	
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
 	IRDA_ASSERT(self != NULL, return;);
@@ -104,11 +104,11 @@
 	fp = skb->data;
 
 	/*
-	 *  The next statements may be confusing, but we do this so that 
+	 *  The next statements may be confusing, but we do this so that
 	 *  destination LSAP of received frame is source LSAP in our view
 	 */
-	slsap_sel = fp[0] & LSAP_MASK; 
-	dlsap_sel = fp[1];	
+	slsap_sel = fp[0] & LSAP_MASK;
+	dlsap_sel = fp[1];
 
 	/*
 	 *  Check if this is an incoming connection, since we must deal with
@@ -118,11 +118,11 @@
 		IRDA_DEBUG(3, "%s(), incoming connection, "
 			   "source LSAP=%d, dest LSAP=%d\n",
 			   __FUNCTION__, slsap_sel, dlsap_sel);
-		
+
 		/* Try to find LSAP among the unconnected LSAPs */
 		lsap = irlmp_find_lsap(self, dlsap_sel, slsap_sel, CONNECT_CMD,
 				       irlmp->unconnected_lsaps);
-		
+
 		/* Maybe LSAP was already connected, so try one more time */
 		if (!lsap) {
 			IRDA_DEBUG(1, "%s(), incoming connection for LSAP already connected\n", __FUNCTION__);
@@ -130,9 +130,9 @@
 					       self->lsaps);
 		}
 	} else
-		lsap = irlmp_find_lsap(self, dlsap_sel, slsap_sel, 0, 
+		lsap = irlmp_find_lsap(self, dlsap_sel, slsap_sel, 0,
 				       self->lsaps);
-	
+
 	if (lsap == NULL) {
 		IRDA_DEBUG(2, "IrLMP, Sorry, no LSAP for received frame!\n");
 		IRDA_DEBUG(2, "%s(), slsap_sel = %02x, dlsap_sel = %02x\n",
@@ -146,8 +146,8 @@
 		return;
 	}
 
-	/* 
-	 *  Check if we received a control frame? 
+	/*
+	 *  Check if we received a control frame?
 	 */
 	if (fp[0] & CONTROL_BIT) {
 		switch (fp[2]) {
@@ -161,7 +161,7 @@
 		case DISCONNECT:
 			IRDA_DEBUG(4, "%s(), Disconnect indication!\n",
 				   __FUNCTION__);
-			irlmp_do_lsap_event(lsap, LM_DISCONNECT_INDICATION, 
+			irlmp_do_lsap_event(lsap, LM_DISCONNECT_INDICATION,
 					    skb);
 			break;
 		case ACCESSMODE_CMD:
@@ -181,7 +181,7 @@
 			irlmp_udata_indication(lsap, skb);
 		else
 			irlmp_do_lsap_event(lsap, LM_UDATA_INDICATION, skb);
-	} else {	
+	} else {
 		/* Optimize and bypass the state machine if possible */
 		if (lsap->lsap_state == LSAP_DATA_TRANSFER_READY)
 			irlmp_data_indication(lsap, skb);
@@ -193,7 +193,7 @@
 /*
  * Function irlmp_link_unitdata_indication (self, skb)
  *
- *    
+ *
  *
  */
 #ifdef CONFIG_IRDA_ULTRA
@@ -205,7 +205,7 @@
 	__u8   pid;         /* Protocol identifier */
 	__u8   *fp;
 	unsigned long flags;
-	
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
 	IRDA_ASSERT(self != NULL, return;);
@@ -215,13 +215,13 @@
 	fp = skb->data;
 
 	/*
-	 *  The next statements may be confusing, but we do this so that 
+	 *  The next statements may be confusing, but we do this so that
 	 *  destination LSAP of received frame is source LSAP in our view
 	 */
-	slsap_sel = fp[0] & LSAP_MASK; 
+	slsap_sel = fp[0] & LSAP_MASK;
 	dlsap_sel = fp[1];
 	pid       = fp[2];
-	
+
 	if (pid & 0x80) {
 		IRDA_DEBUG(0, "%s(), extension in PID not supp!\n",
 			   __FUNCTION__);
@@ -233,7 +233,7 @@
 		IRDA_DEBUG(0, "%s(), dropping frame!\n", __FUNCTION__);
 		return;
 	}
-	
+
 	/* Search the connectionless LSAP */
 	spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
 	lsap = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
@@ -241,10 +241,10 @@
 		/*
 		 *  Check if source LSAP and dest LSAP selectors and PID match.
 		 */
-		if ((lsap->slsap_sel == slsap_sel) && 
-		    (lsap->dlsap_sel == dlsap_sel) && 
-		    (lsap->pid == pid)) 
-		{			
+		if ((lsap->slsap_sel == slsap_sel) &&
+		    (lsap->dlsap_sel == dlsap_sel) &&
+		    (lsap->pid == pid))
+		{
 			break;
 		}
 		lsap = (struct lsap_cb *) hashbin_get_next(irlmp->unconnected_lsaps);
@@ -262,12 +262,12 @@
 /*
  * Function irlmp_link_disconnect_indication (reason, userdata)
  *
- *    IrLAP has disconnected 
+ *    IrLAP has disconnected
  *
  */
-void irlmp_link_disconnect_indication(struct lap_cb *lap, 
-				      struct irlap_cb *irlap, 
-				      LAP_REASON reason, 
+void irlmp_link_disconnect_indication(struct lap_cb *lap,
+				      struct irlap_cb *irlap,
+				      LAP_REASON reason,
 				      struct sk_buff *skb)
 {
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
@@ -278,8 +278,8 @@
 	lap->reason = reason;
 	lap->daddr = DEV_ADDR_ANY;
 
-        /* FIXME: must do something with the skb if any */
-	
+	/* FIXME: must do something with the skb if any */
+
 	/*
 	 *  Inform station state machine
 	 */
@@ -292,9 +292,9 @@
  *    Incoming LAP connection!
  *
  */
-void irlmp_link_connect_indication(struct lap_cb *self, __u32 saddr, 
+void irlmp_link_connect_indication(struct lap_cb *self, __u32 saddr,
 				   __u32 daddr, struct qos_info *qos,
-				   struct sk_buff *skb) 
+				   struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
@@ -314,7 +314,7 @@
  *    LAP connection confirmed!
  *
  */
-void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos, 
+void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos,
 				struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
@@ -359,7 +359,7 @@
  *
  * Jean II
  */
-void irlmp_link_discovery_indication(struct lap_cb *self, 
+void irlmp_link_discovery_indication(struct lap_cb *self,
 				     discovery_t *discovery)
 {
 	IRDA_ASSERT(self != NULL, return;);
@@ -367,7 +367,7 @@
 
 	/* Add to main log, cleanup */
 	irlmp_add_discovery(irlmp->cachelog, discovery);
-	
+
 	/* Just handle it the same way as a discovery confirm,
 	 * bypass the LM_LAP state machine (see below) */
 	irlmp_discovery_confirm(irlmp->cachelog, DISCOVERY_PASSIVE);
@@ -387,7 +387,7 @@
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
-	
+
 	/* Add to main log, cleanup */
 	irlmp_add_discovery_log(irlmp->cachelog, log);
 
@@ -420,7 +420,7 @@
  *    Find handle associated with destination and source LSAP
  *
  * Any IrDA connection (LSAP/TSAP) is uniquely identified by
- * 3 parameters, the local lsap, the remote lsap and the remote address. 
+ * 3 parameters, the local lsap, the remote lsap and the remote address.
  * We may initiate multiple connections to the same remote service
  * (they will have different local lsap), a remote device may initiate
  * multiple connections to the same local service (they will have
@@ -433,20 +433,20 @@
  */
 static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
 				       __u8 slsap_sel, int status,
-				       hashbin_t *queue) 
+				       hashbin_t *queue)
 {
 	struct lsap_cb *lsap;
 	unsigned long flags;
-	
-	/* 
+
+	/*
 	 *  Optimize for the common case. We assume that the last frame
 	 *  received is in the same connection as the last one, so check in
 	 *  cache first to avoid the linear search
 	 */
 #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
-	if ((self->cache.valid) && 
-	    (self->cache.slsap_sel == slsap_sel) && 
-	    (self->cache.dlsap_sel == dlsap_sel)) 
+	if ((self->cache.valid) &&
+	    (self->cache.slsap_sel == slsap_sel) &&
+	    (self->cache.dlsap_sel == dlsap_sel))
 	{
 		return (self->cache.lsap);
 	}
@@ -456,14 +456,14 @@
 
 	lsap = (struct lsap_cb *) hashbin_get_first(queue);
 	while (lsap != NULL) {
-		/* 
-		 *  If this is an incoming connection, then the destination 
-		 *  LSAP selector may have been specified as LM_ANY so that 
+		/*
+		 *  If this is an incoming connection, then the destination
+		 *  LSAP selector may have been specified as LM_ANY so that
 		 *  any client can connect. In that case we only need to check
 		 *  if the source LSAP (in our view!) match!
 		 */
-		if ((status == CONNECT_CMD) && 
-		    (lsap->slsap_sel == slsap_sel) &&      
+		if ((status == CONNECT_CMD) &&
+		    (lsap->slsap_sel == slsap_sel) &&
 		    (lsap->dlsap_sel == LSAP_ANY)) {
 			/* This is where the dest lsap sel is set on incoming
 			 * lsaps */
@@ -473,8 +473,8 @@
 		/*
 		 *  Check if source LSAP and dest LSAP selectors match.
 		 */
-		if ((lsap->slsap_sel == slsap_sel) && 
-		    (lsap->dlsap_sel == dlsap_sel)) 
+		if ((lsap->slsap_sel == slsap_sel) &&
+		    (lsap->dlsap_sel == dlsap_sel))
 			break;
 
 		lsap = (struct lsap_cb *) hashbin_get_next(queue);
diff --git a/net/irda/irmod.c b/net/irda/irmod.c
index 2869b16..826e6c4c 100644
--- a/net/irda/irmod.c
+++ b/net/irda/irmod.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irmod.c
  * Version:       0.9
  * Description:   IrDA stack main entry points
@@ -8,19 +8,19 @@
  * Created at:    Mon Dec 15 13:55:39 1997
  * Modified at:   Wed Jan  5 15:12:41 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1997, 1999-2000 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 2000-2004 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
- *  
+ *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
- *     
+ *
  ********************************************************************/
 
 /*
@@ -52,7 +52,7 @@
 extern int  irsock_init(void);
 extern void irsock_cleanup(void);
 /* irlap_frame.c */
-extern int  irlap_driver_rcv(struct sk_buff *, struct net_device *, 
+extern int  irlap_driver_rcv(struct sk_buff *, struct net_device *,
 			     struct packet_type *, struct net_device *);
 
 /*
@@ -104,16 +104,16 @@
 	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
 
 	/* Lower layer of the stack */
- 	irlmp_init();
+	irlmp_init();
 	irlap_init();
-	
+
 	/* Higher layers of the stack */
 	iriap_init();
- 	irttp_init();
+	irttp_init();
 	irsock_init();
-	
+
 	/* Add IrDA packet type (Start receiving packets) */
-        dev_add_pack(&irda_packet_type);
+	dev_add_pack(&irda_packet_type);
 
 	/* External APIs */
 #ifdef CONFIG_PROC_FS
@@ -124,7 +124,7 @@
 #endif
 
 	/* Driver/dongle support */
- 	irda_device_init();
+	irda_device_init();
 
 	return 0;
 }
@@ -140,14 +140,14 @@
 	/* Remove External APIs */
 #ifdef CONFIG_SYSCTL
 	irda_sysctl_unregister();
-#endif	
+#endif
 #ifdef CONFIG_PROC_FS
 	irda_proc_unregister();
 #endif
 
 	/* Remove IrDA packet type (stop receiving packets) */
-        dev_remove_pack(&irda_packet_type);
-	
+	dev_remove_pack(&irda_packet_type);
+
 	/* Remove higher layers */
 	irsock_cleanup();
 	irttp_cleanup();
@@ -177,8 +177,8 @@
  */
 subsys_initcall(irda_init);
 module_exit(irda_cleanup);
- 
+
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no> & Jean Tourrilhes <jt@hpl.hp.com>");
-MODULE_DESCRIPTION("The Linux IrDA Protocol Stack"); 
+MODULE_DESCRIPTION("The Linux IrDA Protocol Stack");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NETPROTO(PF_IRDA);
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
index 8088752..873ae18 100644
--- a/net/irda/irnet/irnet.h
+++ b/net/irda/irnet/irnet.h
@@ -44,7 +44,7 @@
  * the generic Linux PPP driver. Because IrNET depend on recent
  * changes of the PPP driver interface, IrNET will work only with very
  * recent kernel (2.3.99-pre6 and up).
- * 
+ *
  * The present implementation offer the following features :
  *	o simple user interface using pppd
  *	o efficient implementation (interface directly to PPP and IrTTP)
@@ -327,7 +327,7 @@
 
 #define DEBUG_ASSERT		0	/* Verify all assertions */
 
-/* 
+/*
  * These are the macros we are using to actually print the debug
  * statements. Don't look at it, it's ugly...
  *
diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
index f65c7a8..c378e66 100644
--- a/net/irda/irnet/irnet_irda.c
+++ b/net/irda/irnet/irnet_irda.c
@@ -118,7 +118,7 @@
 
   /* Open an IrTTP instance */
   self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
-			       &notify);	
+			       &notify);
   DABORT(self->tsap == NULL, -ENOMEM,
 	 IRDA_SR_ERROR, "Unable to allocate TSAP !\n");
 
@@ -188,7 +188,7 @@
 	  if(value->t.integer != -1)
 	    /* Get the remote TSAP selector */
 	    dtsap_sel = value->t.integer;
-	  else 
+	  else
 	    self->errno = -EADDRNOTAVAIL;
 	  break;
 	default:
@@ -280,8 +280,8 @@
     }
 
   /* Connect to remote device */
-  err = irttp_connect_request(self->tsap, self->dtsap_sel, 
-			      self->rsaddr, self->daddr, NULL, 
+  err = irttp_connect_request(self->tsap, self->dtsap_sel,
+			      self->rsaddr, self->daddr, NULL,
 			      self->max_sdu_size_rx, NULL);
   if(err != 0)
     {
@@ -438,7 +438,7 @@
   if(discoveries == NULL)
     DRETURN(-ENETUNREACH, IRDA_SR_INFO, "Cachelog empty...\n");
 
-  /* 
+  /*
    * Now, check all discovered devices (if any), and connect
    * client only about the services that the client is
    * interested in...
@@ -627,7 +627,7 @@
 
   /* Unregister with LM-IAS */
   if(self->iriap)
-    { 
+    {
       iriap_close(self->iriap);
       self->iriap = NULL;
     }
@@ -945,7 +945,7 @@
 
   /* Register with LM-IAS (so that people can connect to us) */
   irnet_server.ias_obj = irias_new_object(IRNET_SERVICE_NAME, jiffies);
-  irias_add_integer_attrib(irnet_server.ias_obj, IRNET_IAS_VALUE, 
+  irias_add_integer_attrib(irnet_server.ias_obj, IRNET_IAS_VALUE,
 			   irnet_server.s.stsap_sel, IAS_KERNEL_ATTR);
   irias_insert_object(irnet_server.ias_obj);
 
@@ -1076,7 +1076,7 @@
  */
 static void
 irnet_disconnect_indication(void *	instance,
-			    void *	sap, 
+			    void *	sap,
 			    LM_REASON	reason,
 			    struct sk_buff *skb)
 {
@@ -1166,10 +1166,10 @@
  */
 static void
 irnet_connect_confirm(void *	instance,
-		      void *	sap, 
+		      void *	sap,
 		      struct qos_info *qos,
 		      __u32	max_sdu_size,
-		      __u8	max_header_size, 
+		      __u8	max_header_size,
 		      struct sk_buff *skb)
 {
   irnet_socket *	self = (irnet_socket *) instance;
@@ -1235,7 +1235,7 @@
 static void
 irnet_flow_indication(void *	instance,
 		      void *	sap,
-		      LOCAL_FLOW flow) 
+		      LOCAL_FLOW flow)
 {
   irnet_socket *	self = (irnet_socket *) instance;
   LOCAL_FLOW		oldflow = self->tx_flow;
@@ -1308,13 +1308,13 @@
  * Some other node is attempting to connect to the IrNET service, and has
  * sent a connection request on our server socket.
  * We just redirect the connection to the relevant IrNET socket.
- * 
+ *
  * Note : we also make sure that between 2 irnet nodes, there can
  * exist only one irnet connection.
  */
 static void
 irnet_connect_indication(void *		instance,
-			 void *		sap, 
+			 void *		sap,
 			 struct qos_info *qos,
 			 __u32		max_sdu_size,
 			 __u8		max_header_size,
@@ -1463,7 +1463,7 @@
  */
 static void
 irnet_getvalue_confirm(int	result,
-		       __u16	obj_id, 
+		       __u16	obj_id,
 		       struct ias_value *value,
 		       void *	priv)
 {
@@ -1526,7 +1526,7 @@
  */
 static void
 irnet_discovervalue_confirm(int		result,
-			    __u16	obj_id, 
+			    __u16	obj_id,
 			    struct ias_value *value,
 			    void *	priv)
 {
@@ -1645,7 +1645,7 @@
 			   void *		priv)
 {
   irnet_socket *	self = &irnet_server.s;
-	
+
   DENTER(IRDA_OCB_TRACE, "(self=0x%p)\n", self);
   DASSERT(priv == &irnet_server, , IRDA_OCB_ERROR,
 	  "Invalid instance (0x%p) !!!\n", priv);
@@ -1676,7 +1676,7 @@
 			void *		priv)
 {
   irnet_socket *	self = &irnet_server.s;
-	
+
   DENTER(IRDA_OCB_TRACE, "(self=0x%p)\n", self);
   DASSERT(priv == &irnet_server, , IRDA_OCB_ERROR,
 	  "Invalid instance (0x%p) !!!\n", priv);
@@ -1718,7 +1718,7 @@
   int			i = 0;
 
   len = 0;
-	
+
   /* Get the IrNET server information... */
   len += sprintf(buf+len, "IrNET server - ");
   len += sprintf(buf+len, "IrDA state: %s, ",
@@ -1811,7 +1811,7 @@
   memset(&irnet_server, 0, sizeof(struct irnet_root));
 
   /* Setup start of irnet instance list */
-  irnet_server.list = hashbin_new(HB_NOLOCK); 
+  irnet_server.list = hashbin_new(HB_NOLOCK);
   DABORT(irnet_server.list == NULL, -ENOMEM,
 	 MODULE_ERROR, "Can't allocate hashbin!\n");
   /* Init spinlock for instance list */
diff --git a/net/irda/irnet/irnet_irda.h b/net/irda/irnet/irnet_irda.h
index f2fecd3..0ba92d0 100644
--- a/net/irda/irnet/irnet_irda.h
+++ b/net/irda/irnet/irnet_irda.h
@@ -146,7 +146,7 @@
 			       void *);
 static void
 	irnet_discovervalue_confirm(int,
-				    __u16, 
+				    __u16,
 				    struct ias_value *,
 				    void *);
 #ifdef DISCOVERY_EVENTS
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c
index a1e502f..2f9f8dc 100644
--- a/net/irda/irnet/irnet_ppp.c
+++ b/net/irda/irnet/irnet_ppp.c
@@ -93,7 +93,7 @@
 
       /* Check if we recognised one of the known command
        * We can't use "switch" with strings, so hack with "continue" */
-      
+
       /* First command : name -> Requested IrDA nickname */
       if(!strncmp(start, "name", 4))
 	{
@@ -744,7 +744,7 @@
       break;
 
       /* Set DTR/RTS */
-    case TIOCMBIS: 
+    case TIOCMBIS:
     case TIOCMBIC:
       /* Set exclusive/non-exclusive mode */
     case TIOCEXCL:
@@ -941,7 +941,7 @@
   ret = irttp_data_request(self->tsap, skb);
   if(ret < 0)
     {
-      /*   
+      /*
        * > IrTTPs tx queue is full, so we just have to
        * > drop the frame! You might think that we should
        * > just return -1 and don't deallocate the frame,
@@ -949,7 +949,7 @@
        * > we have replaced the original skb with a new
        * > one with larger headroom, and that would really
        * > confuse do_dev_queue_xmit() in dev.c! I have
-       * > tried :-) DB 
+       * > tried :-) DB
        * Correction : we verify the flow control above (self->tx_flow),
        * so we come here only if IrTTP doesn't like the packet (empty,
        * too large, IrTTP not connected). In those rare cases, it's ok
@@ -1136,6 +1136,6 @@
 module_init(irnet_init);
 module_exit(irnet_cleanup);
 MODULE_AUTHOR("Jean Tourrilhes <jt@hpl.hp.com>");
-MODULE_DESCRIPTION("IrNET : Synchronous PPP over IrDA"); 
+MODULE_DESCRIPTION("IrNET : Synchronous PPP over IrDA");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV(10, 187);
diff --git a/net/irda/irproc.c b/net/irda/irproc.c
index 88b9c43..d6f9aba 100644
--- a/net/irda/irproc.c
+++ b/net/irda/irproc.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irproc.c
  * Version:       1.0
  * Description:   Various entries in the /proc file system
@@ -10,17 +10,17 @@
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *
  *     Copyright (c) 1998-1999, Dag Brattli <dagb@cs.uit.no>
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
+ *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
  *     All Rights Reserved.
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     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.
- *  
- *     I, Thomas Davis, provide no warranty for any of this software. 
- *     This material is provided "AS-IS" and at no charge. 
- *     
+ *
+ *     I, Thomas Davis, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
  ********************************************************************/
 
 #include <linux/miscdevice.h>
@@ -46,7 +46,7 @@
 
 struct proc_dir_entry *proc_irda;
 EXPORT_SYMBOL(proc_irda);
- 
+
 static struct irda_entry irda_dirs[] = {
 	{"discovery",	&discovery_seq_fops},
 	{"irttp",	&irttp_seq_fops},
@@ -61,7 +61,7 @@
  *    Register irda entry in /proc file system
  *
  */
-void __init irda_proc_register(void) 
+void __init irda_proc_register(void)
 {
 	int i;
 	struct proc_dir_entry *d;
@@ -73,7 +73,7 @@
 
 	for (i=0; i<ARRAY_SIZE(irda_dirs); i++) {
 		d = create_proc_entry(irda_dirs[i].name, 0, proc_irda);
-		if (d) 
+		if (d)
 			d->proc_fops = irda_dirs[i].fops;
 	}
 }
@@ -84,17 +84,17 @@
  *    Unregister irda entry in /proc file system
  *
  */
-void __exit irda_proc_unregister(void) 
+void __exit irda_proc_unregister(void)
 {
 	int i;
 
-        if (proc_irda) {
-                for (i=0; i<ARRAY_SIZE(irda_dirs); i++)
-                        remove_proc_entry(irda_dirs[i].name, proc_irda);
+	if (proc_irda) {
+		for (i=0; i<ARRAY_SIZE(irda_dirs); i++)
+			remove_proc_entry(irda_dirs[i].name, proc_irda);
 
-                remove_proc_entry("irda", proc_net);
-                proc_irda = NULL;
-        }
+		remove_proc_entry("irda", proc_net);
+		proc_irda = NULL;
+	}
 }
 
 
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
index 1d26cd3..9266233 100644
--- a/net/irda/irqueue.c
+++ b/net/irda/irqueue.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irqueue.c
  * Version:       0.3
  * Description:   General queue implementation
@@ -10,28 +10,28 @@
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Modified at:   Thu Jan  4 14:29:10 CET 2001
  * Modified by:   Marc Zyngier <mzyngier@freesurf.fr>
- * 
+ *
  *     Copyright (C) 1998-1999, Aage Kvalnes <aage@cs.uit.no>
- *     Copyright (C) 1998, Dag Brattli, 
+ *     Copyright (C) 1998, Dag Brattli,
  *     All Rights Reserved.
  *
  *     This code is taken from the Vortex Operating System written by Aage
  *     Kvalnes. Aage has agreed that this code can use the GPL licence,
  *     although he does not use that licence in his own code.
- *     
+ *
  *     This copyright does however _not_ include the ELF hash() function
  *     which I currently don't know which licence or copyright it
  *     has. Please inform me if you know.
- *      
- *     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 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
- *  
+ *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
- *     
+ *
  ********************************************************************/
 
 /*
@@ -213,7 +213,7 @@
 {
 	__u32 h = 0;
 	__u32 g;
-	
+
 	while(*name) {
 		h = (h<<4) + *name++;
 		if ((g = (h & 0xf0000000)))
@@ -231,7 +231,7 @@
  */
 static void enqueue_first(irda_queue_t **queue, irda_queue_t* element)
 {
-	
+
 	IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
 
 	/*
@@ -242,7 +242,7 @@
 		 * Queue is empty.  Insert one element into the queue.
 		 */
 		element->q_next = element->q_prev = *queue = element;
-		
+
 	} else {
 		/*
 		 * Queue is not empty.  Insert element into front of queue.
@@ -267,20 +267,20 @@
 	irda_queue_t *ret;
 
 	IRDA_DEBUG( 4, "dequeue_first()\n");
-	
+
 	/*
 	 * Set return value
 	 */
 	ret =  *queue;
-	
+
 	if ( *queue == NULL ) {
 		/*
 		 * Queue was empty.
 		 */
 	} else if ( (*queue)->q_next == *queue ) {
-		/* 
+		/*
 		 *  Queue only contained a single element. It will now be
-		 *  empty.  
+		 *  empty.
 		 */
 		*queue = NULL;
 	} else {
@@ -291,7 +291,7 @@
 		(*queue)->q_next->q_prev = (*queue)->q_prev;
 		*queue = (*queue)->q_next;
 	}
-	
+
 	/*
 	 * Return the removed entry (or NULL of queue was empty).
 	 */
@@ -306,25 +306,25 @@
 static irda_queue_t *dequeue_general(irda_queue_t **queue, irda_queue_t* element)
 {
 	irda_queue_t *ret;
-	
+
 	IRDA_DEBUG( 4, "dequeue_general()\n");
-	
+
 	/*
 	 * Set return value
 	 */
 	ret =  *queue;
-		
+
 	if ( *queue == NULL ) {
 		/*
 		 * Queue was empty.
 		 */
 	} else if ( (*queue)->q_next == *queue ) {
-		/* 
+		/*
 		 *  Queue only contained a single element. It will now be
-		 *  empty.  
+		 *  empty.
 		 */
 		*queue = NULL;
-		
+
 	} else {
 		/*
 		 *  Remove specific element.
@@ -334,7 +334,7 @@
 		if ( (*queue) == element)
 			(*queue) = element->q_next;
 	}
-	
+
 	/*
 	 * Return the removed entry (or NULL of queue was empty).
 	 */
@@ -352,7 +352,7 @@
 hashbin_t *hashbin_new(int type)
 {
 	hashbin_t* hashbin;
-	
+
 	/*
 	 * Allocate new hashbin
 	 */
@@ -380,8 +380,8 @@
 /*
  * Function hashbin_delete (hashbin, free_func)
  *
- *    Destroy hashbin, the free_func can be a user supplied special routine 
- *    for deallocating this structure if it's complex. If not the user can 
+ *    Destroy hashbin, the free_func can be a user supplied special routine
+ *    for deallocating this structure if it's complex. If not the user can
  *    just supply kfree, which should take care of the job.
  */
 int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
@@ -392,7 +392,7 @@
 
 	IRDA_ASSERT(hashbin != NULL, return -1;);
 	IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;);
-	
+
 	/* Synchronize */
 	if ( hashbin->hb_type & HB_LOCK ) {
 		spin_lock_irqsave(&hashbin->hb_spinlock, flags);
@@ -407,11 +407,11 @@
 		while (queue ) {
 			if (free_func)
 				(*free_func)(queue);
-			queue = dequeue_first( 
+			queue = dequeue_first(
 				(irda_queue_t**) &hashbin->hb_queue[i]);
 		}
 	}
-	
+
 	/* Cleanup local data */
 	hashbin->hb_current = NULL;
 	hashbin->magic = ~HB_MAGIC;
@@ -438,7 +438,7 @@
  *    Insert an entry into the hashbin
  *
  */
-void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, long hashv, 
+void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, long hashv,
 		    const char* name)
 {
 	unsigned long flags = 0;
@@ -460,14 +460,14 @@
 	if ( hashbin->hb_type & HB_LOCK ) {
 		spin_lock_irqsave(&hashbin->hb_spinlock, flags);
 	} /* Default is no-lock  */
-	
+
 	/*
 	 * Store name and key
 	 */
 	entry->q_hash = hashv;
 	if ( name )
 		strlcpy( entry->q_name, name, sizeof(entry->q_name));
-	
+
 	/*
 	 * Insert new entry first
 	 */
@@ -482,7 +482,7 @@
 }
 EXPORT_SYMBOL(hashbin_insert);
 
-/* 
+/*
  *  Function hashbin_remove_first (hashbin)
  *
  *    Remove first entry of the hashbin
@@ -537,7 +537,7 @@
 }
 
 
-/* 
+/*
  *  Function hashbin_remove (hashbin, hashv, name)
  *
  *    Remove entry with the given name
@@ -561,7 +561,7 @@
 
 	IRDA_ASSERT( hashbin != NULL, return NULL;);
 	IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
-	
+
 	/*
 	 * Locate hashbin
 	 */
@@ -601,7 +601,7 @@
 			entry = entry->q_next;
 		} while ( entry != hashbin->hb_queue[ bin ] );
 	}
-	
+
 	/*
 	 * If entry was found, dequeue it
 	 */
@@ -622,18 +622,18 @@
 	if ( hashbin->hb_type & HB_LOCK ) {
 		spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
 	} /* Default is no-lock  */
-       
-	
+
+
 	/* Return */
-	if ( found ) 
+	if ( found )
 		return entry;
 	else
 		return NULL;
-	
+
 }
 EXPORT_SYMBOL(hashbin_remove);
 
-/* 
+/*
  *  Function hashbin_remove_this (hashbin, entry)
  *
  *    Remove entry with the given name
@@ -655,7 +655,7 @@
 	IRDA_ASSERT( hashbin != NULL, return NULL;);
 	IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
 	IRDA_ASSERT( entry != NULL, return NULL;);
-	
+
 	/* Synchronize */
 	if ( hashbin->hb_type & HB_LOCK ) {
 		spin_lock_irqsave(&hashbin->hb_spinlock, flags);
@@ -722,7 +722,7 @@
 	if ( name )
 		hashv = hash( name );
 	bin = GET_HASHBIN( hashv );
-	
+
 	/*
 	 * Search for entry
 	 */
@@ -829,7 +829,7 @@
  *    called before any calls to hashbin_get_next()!
  *
  */
-irda_queue_t *hashbin_get_first( hashbin_t* hashbin) 
+irda_queue_t *hashbin_get_first( hashbin_t* hashbin)
 {
 	irda_queue_t *entry;
 	int i;
@@ -860,7 +860,7 @@
  *    Get next item in hashbin. A series of hashbin_get_next() calls must
  *    be started by a call to hashbin_get_first(). The function returns
  *    NULL when all items have been traversed
- * 
+ *
  * The context of the search is stored within the hashbin, so you must
  * protect yourself from concurrent enumerations. - Jean II
  */
@@ -876,13 +876,13 @@
 	if ( hashbin->hb_current == NULL) {
 		IRDA_ASSERT( hashbin->hb_current != NULL, return NULL;);
 		return NULL;
-	}	
+	}
 	entry = hashbin->hb_current->q_next;
 	bin = GET_HASHBIN( entry->q_hash);
 
-	/*  
+	/*
 	 *  Make sure that we are not back at the beginning of the queue
-	 *  again 
+	 *  again
 	 */
 	if ( entry != hashbin->hb_queue[ bin ]) {
 		hashbin->hb_current = entry;
@@ -895,7 +895,7 @@
 	 */
 	if ( bin >= HASHBIN_SIZE)
 		return NULL;
-	
+
 	/*
 	 *  Move to next queue in hashbin
 	 */
@@ -904,7 +904,7 @@
 		entry = hashbin->hb_queue[ i];
 		if ( entry) {
 			hashbin->hb_current = entry;
-			
+
 			return entry;
 		}
 	}
diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c
index 86805c3..2e968e7 100644
--- a/net/irda/irsysctl.c
+++ b/net/irda/irsysctl.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irsysctl.c
  * Version:       1.0
  * Description:   Sysctl interface for IrDA
@@ -8,19 +8,19 @@
  * Created at:    Sun May 24 22:12:06 1998
  * Modified at:   Fri Jun  4 02:50:15 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
- *  
+ *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
- *     
+ *
  ********************************************************************/
 
 #include <linux/mm.h>
@@ -111,7 +111,7 @@
 		.strategy	= &sysctl_string
 	},
 #ifdef CONFIG_IRDA_DEBUG
-        {
+	{
 		.ctl_name	= DEBUG,
 		.procname	= "debug",
 		.data		= &irda_debug,
@@ -121,7 +121,7 @@
 	},
 #endif
 #ifdef CONFIG_IRDA_FAST_RR
-        {
+	{
 		.ctl_name	= FAST_POLL,
 		.procname	= "fast_poll_increase",
 		.data		= &sysctl_fast_poll_increase,
@@ -274,7 +274,7 @@
  */
 int __init irda_sysctl_register(void)
 {
-	irda_table_header = register_sysctl_table(irda_root_table, 0);
+	irda_table_header = register_sysctl_table(irda_root_table);
 	if (!irda_table_header)
 		return -ENOMEM;
 
@@ -287,7 +287,7 @@
  *    Unregister our sysctl interface
  *
  */
-void __exit irda_sysctl_unregister(void) 
+void __exit irda_sysctl_unregister(void)
 {
 	unregister_sysctl_table(irda_table_header);
 }
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 03504f3..a7486b3 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      irttp.c
  * Version:       1.2
  * Description:   Tiny Transport Protocol (TTP) implementation
@@ -8,18 +8,18 @@
  * Created at:    Sun Aug 31 20:14:31 1997
  * Modified at:   Wed Jan  5 11:31:27 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
+ *
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
  *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
  *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
  *
  ********************************************************************/
@@ -42,17 +42,17 @@
 
 static void __irttp_close_tsap(struct tsap_cb *self);
 
-static int irttp_data_indication(void *instance, void *sap, 
+static int irttp_data_indication(void *instance, void *sap,
 				 struct sk_buff *skb);
-static int irttp_udata_indication(void *instance, void *sap, 
+static int irttp_udata_indication(void *instance, void *sap,
 				  struct sk_buff *skb);
-static void irttp_disconnect_indication(void *instance, void *sap,  
+static void irttp_disconnect_indication(void *instance, void *sap,
 					LM_REASON reason, struct sk_buff *);
-static void irttp_connect_indication(void *instance, void *sap, 
+static void irttp_connect_indication(void *instance, void *sap,
 				     struct qos_info *qos, __u32 max_sdu_size,
 				     __u8 header_size, struct sk_buff *skb);
-static void irttp_connect_confirm(void *instance, void *sap, 
-				  struct qos_info *qos, __u32 max_sdu_size, 
+static void irttp_connect_confirm(void *instance, void *sap,
+				  struct qos_info *qos, __u32 max_sdu_size,
 				  __u8 header_size, struct sk_buff *skb);
 static void irttp_run_tx_queue(struct tsap_cb *self);
 static void irttp_run_rx_queue(struct tsap_cb *self);
@@ -61,7 +61,7 @@
 static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
 static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
 static void irttp_todo_expired(unsigned long data);
-static int irttp_param_max_sdu_size(void *instance, irda_param_t *param, 
+static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
 				    int get);
 
 static void irttp_flow_indication(void *instance, void *sap, LOCAL_FLOW flow);
@@ -109,7 +109,7 @@
  *    Called by module destruction/cleanup code
  *
  */
-void __exit irttp_cleanup(void) 
+void __exit irttp_cleanup(void)
 {
 	/* Check for main structure */
 	IRDA_ASSERT(irttp->magic == TTP_MAGIC, return;);
@@ -865,7 +865,7 @@
 		err = self->notify.udata_indication(self->notify.instance,
 						    self,skb);
 		/* Same comment as in irttp_do_data_indication() */
-		if (!err) 
+		if (!err)
 			return 0;
 	}
 	/* Either no handler, or handler returns an error */
@@ -940,7 +940,7 @@
 
 	/*
 	 * If the peer device has given us some credits and we didn't have
-         * anyone from before, then we need to shedule the tx queue.
+	 * anyone from before, then we need to shedule the tx queue.
 	 * We need to do that because our Tx have stopped (so we may not
 	 * get any LAP flow indication) and the user may be stopped as
 	 * well. - Jean II
@@ -1798,14 +1798,14 @@
 	spin_lock_irq(&irttp->tsaps->hb_spinlock);
 	iter->id = 0;
 
-	for (self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps); 
+	for (self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
 	     self != NULL;
 	     self = (struct tsap_cb *) hashbin_get_next(irttp->tsaps)) {
 		if (iter->id == *pos)
 			break;
 		++iter->id;
 	}
-		
+
 	return self;
 }
 
@@ -1895,7 +1895,7 @@
 	goto out;
 }
 
-struct file_operations irttp_seq_fops = {
+const struct file_operations irttp_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = irttp_seq_open,
 	.read           = seq_read,
diff --git a/net/irda/parameters.c b/net/irda/parameters.c
index 1324942..75a72d2 100644
--- a/net/irda/parameters.c
+++ b/net/irda/parameters.c
@@ -563,7 +563,7 @@
  *    safe. Returns the number of bytes that was parsed
  *
  */
-int irda_param_extract_all(void *self, __u8 *buf, int len, 
+int irda_param_extract_all(void *self, __u8 *buf, int len,
 			   pi_param_info_t *info)
 {
 	int ret = -1;
diff --git a/net/irda/qos.c b/net/irda/qos.c
index 95a69c0..349012c 100644
--- a/net/irda/qos.c
+++ b/net/irda/qos.c
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                                
+ *
  * Filename:      qos.c
  * Version:       1.0
  * Description:   IrLAP QoS parameter negotiation
@@ -8,26 +8,26 @@
  * Created at:    Tue Sep  9 00:00:26 1997
  * Modified at:   Sun Jan 30 14:29:16 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
+ *
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
  *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     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, 
+ *
+ *     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/byteorder.h>
@@ -84,16 +84,16 @@
 unsigned sysctl_max_tx_window = 7;
 
 static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get);
-static int irlap_param_link_disconnect(void *instance, irda_param_t *parm, 
+static int irlap_param_link_disconnect(void *instance, irda_param_t *parm,
 				       int get);
-static int irlap_param_max_turn_time(void *instance, irda_param_t *param, 
+static int irlap_param_max_turn_time(void *instance, irda_param_t *param,
 				     int get);
 static int irlap_param_data_size(void *instance, irda_param_t *param, int get);
-static int irlap_param_window_size(void *instance, irda_param_t *param, 
+static int irlap_param_window_size(void *instance, irda_param_t *param,
 				   int get);
-static int irlap_param_additional_bofs(void *instance, irda_param_t *parm, 
+static int irlap_param_additional_bofs(void *instance, irda_param_t *parm,
 				       int get);
-static int irlap_param_min_turn_time(void *instance, irda_param_t *param, 
+static int irlap_param_min_turn_time(void *instance, irda_param_t *param,
 				     int get);
 
 #ifndef CONFIG_IRDA_DYNAMIC_WINDOW
@@ -101,7 +101,7 @@
 #endif
 
 static __u32 min_turn_times[]  = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */
-static __u32 baud_rates[]      = { 2400, 9600, 19200, 38400, 57600, 115200, 576000, 
+static __u32 baud_rates[]      = { 2400, 9600, 19200, 38400, 57600, 115200, 576000,
 				   1152000, 4000000, 16000000 };           /* bps */
 static __u32 data_sizes[]      = { 64, 128, 256, 512, 1024, 2048 };        /* bytes */
 static __u32 add_bofs[]        = { 48, 24, 12, 5, 3, 2, 1, 0 };            /* bytes */
@@ -165,7 +165,7 @@
 static inline int value_index(__u32 value, __u32 *array, int size)
 {
 	int i;
-	
+
 	for (i=0; i < size; i++)
 		if (array[i] == value)
 			break;
@@ -178,7 +178,7 @@
  *    Returns value to index in array, easy!
  *
  */
-static inline __u32 index_value(int index, __u32 *array) 
+static inline __u32 index_value(int index, __u32 *array)
 {
 	return array[index];
 }
@@ -189,7 +189,7 @@
  *    Returns index to most significant bit (MSB) in word
  *
  */
-static int msb_index (__u16 word) 
+static int msb_index (__u16 word)
 {
 	__u16 msb = 0x8000;
 	int index = 15;   /* Current MSB */
@@ -298,12 +298,12 @@
  *
  *    The purpose of this function is for layers and drivers to be able to
  *    set the maximum QoS possible and then "and in" their own limitations
- * 
+ *
  */
 void irda_init_max_qos_capabilies(struct qos_info *qos)
 {
 	int i;
-	/* 
+	/*
 	 *  These are the maximum supported values as specified on pages
 	 *  39-43 in IrLAP
 	 */
@@ -361,25 +361,25 @@
 		qos->min_turn_time.value = sysctl_min_tx_turn_time;
 	}
 
-	/* 
+	/*
 	 * Not allowed to use a max turn time less than 500 ms if the baudrate
 	 * is less than 115200
 	 */
-	if ((qos->baud_rate.value < 115200) && 
+	if ((qos->baud_rate.value < 115200) &&
 	    (qos->max_turn_time.value < 500))
 	{
-		IRDA_DEBUG(0, 
+		IRDA_DEBUG(0,
 			   "%s(), adjusting max turn time from %d to 500 ms\n",
 			   __FUNCTION__, qos->max_turn_time.value);
 		qos->max_turn_time.value = 500;
 	}
-	
+
 	/*
-	 * The data size must be adjusted according to the baud rate and max 
+	 * The data size must be adjusted according to the baud rate and max
 	 * turn time
 	 */
 	index = value_index(qos->data_size.value, data_sizes, 6);
-	line_capacity = irlap_max_line_capacity(qos->baud_rate.value, 
+	line_capacity = irlap_max_line_capacity(qos->baud_rate.value,
 						qos->max_turn_time.value);
 
 #ifdef CONFIG_IRDA_DYNAMIC_WINDOW
@@ -427,32 +427,32 @@
  *    We just set the QoS capabilities for the peer station
  *
  */
-int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb) 
+int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb)
 {
 	int ret;
-	
-	ret = irda_param_extract_all(self, skb->data, skb->len, 
+
+	ret = irda_param_extract_all(self, skb->data, skb->len,
 				     &irlap_param_info);
-	
+
 	/* Convert the negotiated bits to values */
 	irda_qos_bits_to_value(&self->qos_tx);
 	irda_qos_bits_to_value(&self->qos_rx);
 
 	irlap_adjust_qos_settings(&self->qos_tx);
 
-	IRDA_DEBUG(2, "Setting BAUD_RATE to %d bps.\n", 
+	IRDA_DEBUG(2, "Setting BAUD_RATE to %d bps.\n",
 		   self->qos_tx.baud_rate.value);
 	IRDA_DEBUG(2, "Setting DATA_SIZE to %d bytes\n",
 		   self->qos_tx.data_size.value);
-	IRDA_DEBUG(2, "Setting WINDOW_SIZE to %d\n", 
+	IRDA_DEBUG(2, "Setting WINDOW_SIZE to %d\n",
 		   self->qos_tx.window_size.value);
-	IRDA_DEBUG(2, "Setting XBOFS to %d\n", 
+	IRDA_DEBUG(2, "Setting XBOFS to %d\n",
 		   self->qos_tx.additional_bofs.value);
 	IRDA_DEBUG(2, "Setting MAX_TURN_TIME to %d ms.\n",
 		   self->qos_tx.max_turn_time.value);
 	IRDA_DEBUG(2, "Setting MIN_TURN_TIME to %d usecs.\n",
 		   self->qos_tx.min_turn_time.value);
-	IRDA_DEBUG(2, "Setting LINK_DISC to %d secs.\n", 
+	IRDA_DEBUG(2, "Setting LINK_DISC to %d secs.\n",
 		   self->qos_tx.link_disc_time.value);
 	return ret;
 }
@@ -463,55 +463,55 @@
  *    Insert QoS negotiaion pararameters into frame
  *
  */
-int irlap_insert_qos_negotiation_params(struct irlap_cb *self, 
+int irlap_insert_qos_negotiation_params(struct irlap_cb *self,
 					struct sk_buff *skb)
 {
 	int ret;
 
 	/* Insert data rate */
-	ret = irda_param_insert(self, PI_BAUD_RATE, skb->tail, 
+	ret = irda_param_insert(self, PI_BAUD_RATE, skb->tail,
 				skb_tailroom(skb), &irlap_param_info);
 	if (ret < 0)
 		return ret;
 	skb_put(skb, ret);
 
 	/* Insert max turnaround time */
-	ret = irda_param_insert(self, PI_MAX_TURN_TIME, skb->tail, 
+	ret = irda_param_insert(self, PI_MAX_TURN_TIME, skb->tail,
 				skb_tailroom(skb), &irlap_param_info);
 	if (ret < 0)
 		return ret;
 	skb_put(skb, ret);
 
 	/* Insert data size */
-	ret = irda_param_insert(self, PI_DATA_SIZE, skb->tail, 
+	ret = irda_param_insert(self, PI_DATA_SIZE, skb->tail,
 				skb_tailroom(skb), &irlap_param_info);
 	if (ret < 0)
 		return ret;
 	skb_put(skb, ret);
 
 	/* Insert window size */
-	ret = irda_param_insert(self, PI_WINDOW_SIZE, skb->tail, 
+	ret = irda_param_insert(self, PI_WINDOW_SIZE, skb->tail,
 				skb_tailroom(skb), &irlap_param_info);
 	if (ret < 0)
 		return ret;
 	skb_put(skb, ret);
 
 	/* Insert additional BOFs */
-	ret = irda_param_insert(self, PI_ADD_BOFS, skb->tail, 
+	ret = irda_param_insert(self, PI_ADD_BOFS, skb->tail,
 				skb_tailroom(skb), &irlap_param_info);
 	if (ret < 0)
 		return ret;
 	skb_put(skb, ret);
 
 	/* Insert minimum turnaround time */
-	ret = irda_param_insert(self, PI_MIN_TURN_TIME, skb->tail, 
+	ret = irda_param_insert(self, PI_MIN_TURN_TIME, skb->tail,
 				skb_tailroom(skb), &irlap_param_info);
 	if (ret < 0)
 		return ret;
 	skb_put(skb, ret);
 
 	/* Insert link disconnect/threshold time */
-	ret = irda_param_insert(self, PI_LINK_DISC, skb->tail, 
+	ret = irda_param_insert(self, PI_LINK_DISC, skb->tail,
 				skb_tailroom(skb), &irlap_param_info);
 	if (ret < 0)
 		return ret;
@@ -537,12 +537,12 @@
 
 	if (get) {
 		param->pv.i = self->qos_rx.baud_rate.bits;
-		IRDA_DEBUG(2, "%s(), baud rate = 0x%02x\n", 
-			   __FUNCTION__, param->pv.i);		
+		IRDA_DEBUG(2, "%s(), baud rate = 0x%02x\n",
+			   __FUNCTION__, param->pv.i);
 	} else {
-		/* 
+		/*
 		 *  Stations must agree on baud rate, so calculate
-		 *  intersection 
+		 *  intersection
 		 */
 		IRDA_DEBUG(2, "Requested BAUD_RATE: 0x%04x\n", (__u16) param->pv.i);
 		final = (__u16) param->pv.i & self->qos_rx.baud_rate.bits;
@@ -558,24 +558,24 @@
 /*
  * Function irlap_param_link_disconnect (instance, param, get)
  *
- *    Negotiate link disconnect/threshold time. 
+ *    Negotiate link disconnect/threshold time.
  *
  */
-static int irlap_param_link_disconnect(void *instance, irda_param_t *param, 
+static int irlap_param_link_disconnect(void *instance, irda_param_t *param,
 				       int get)
 {
 	__u16 final;
-	
+
 	struct irlap_cb *self = (struct irlap_cb *) instance;
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
-	
+
 	if (get)
 		param->pv.i = self->qos_rx.link_disc_time.bits;
 	else {
-		/*  
-		 *  Stations must agree on link disconnect/threshold 
+		/*
+		 *  Stations must agree on link disconnect/threshold
 		 *  time.
 		 */
 		IRDA_DEBUG(2, "LINK_DISC: %02x\n", (__u8) param->pv.i);
@@ -595,14 +595,14 @@
  *    will be negotiated independently for each station
  *
  */
-static int irlap_param_max_turn_time(void *instance, irda_param_t *param, 
+static int irlap_param_max_turn_time(void *instance, irda_param_t *param,
 				     int get)
 {
 	struct irlap_cb *self = (struct irlap_cb *) instance;
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
-	
+
 	if (get)
 		param->pv.i = self->qos_rx.max_turn_time.bits;
 	else
@@ -621,10 +621,10 @@
 static int irlap_param_data_size(void *instance, irda_param_t *param, int get)
 {
 	struct irlap_cb *self = (struct irlap_cb *) instance;
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
-	
+
 	if (get)
 		param->pv.i = self->qos_rx.data_size.bits;
 	else
@@ -640,14 +640,14 @@
  *    will be negotiated independently for each station
  *
  */
-static int irlap_param_window_size(void *instance, irda_param_t *param, 
+static int irlap_param_window_size(void *instance, irda_param_t *param,
 				   int get)
 {
 	struct irlap_cb *self = (struct irlap_cb *) instance;
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
-	
+
 	if (get)
 		param->pv.i = self->qos_rx.window_size.bits;
 	else
@@ -665,10 +665,10 @@
 static int irlap_param_additional_bofs(void *instance, irda_param_t *param, int get)
 {
 	struct irlap_cb *self = (struct irlap_cb *) instance;
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
-	
+
 	if (get)
 		param->pv.i = self->qos_rx.additional_bofs.bits;
 	else
@@ -683,14 +683,14 @@
  *    Negotiate the minimum turn around time. This is a type 1 parameter and
  *    will be negotiated independently for each station
  */
-static int irlap_param_min_turn_time(void *instance, irda_param_t *param, 
+static int irlap_param_min_turn_time(void *instance, irda_param_t *param,
 				     int get)
 {
 	struct irlap_cb *self = (struct irlap_cb *) instance;
-	
+
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
-	
+
 	if (get)
 		param->pv.i = self->qos_rx.min_turn_time.bits;
 	else
@@ -721,9 +721,9 @@
 
 	line_capacity = max_line_capacities[i][j];
 
-	IRDA_DEBUG(2, "%s(), line capacity=%d bytes\n", 
+	IRDA_DEBUG(2, "%s(), line capacity=%d bytes\n",
 		   __FUNCTION__, line_capacity);
-	
+
 	return line_capacity;
 }
 
@@ -749,7 +749,7 @@
 	int index;
 
 	IRDA_ASSERT(qos != NULL, return;);
-	
+
 	index = msb_index(qos->baud_rate.bits);
 	qos->baud_rate.value = baud_rates[index];
 
@@ -761,13 +761,13 @@
 
 	index = msb_index(qos->min_turn_time.bits);
 	qos->min_turn_time.value = min_turn_times[index];
-	
+
 	index = msb_index(qos->max_turn_time.bits);
 	qos->max_turn_time.value = max_turn_times[index];
 
 	index = msb_index(qos->link_disc_time.bits);
 	qos->link_disc_time.value = link_disc_times[index];
-	
+
 	index = msb_index(qos->additional_bofs.bits);
 	qos->additional_bofs.value = add_bofs[index];
 }
diff --git a/net/irda/timer.c b/net/irda/timer.c
index 3871a2b..d3a6ee8 100644
--- a/net/irda/timer.c
+++ b/net/irda/timer.c
@@ -1,25 +1,25 @@
 /*********************************************************************
- *                
+ *
  * Filename:      timer.c
- * Version:       
- * Description:   
+ * Version:
+ * Description:
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
  * Modified at:   Wed Dec  8 12:50:34 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
+ *
+ *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
  *     Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.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 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
  *
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
+ *     provide warranty for any of this software. This material is
  *     provided "AS-IS" and at no charge.
  *
  ********************************************************************/
@@ -40,11 +40,11 @@
 static void irlap_final_timer_expired(void* data);
 static void irlap_wd_timer_expired(void* data);
 static void irlap_backoff_timer_expired(void* data);
-static void irlap_media_busy_expired(void* data); 
+static void irlap_media_busy_expired(void* data);
 
 void irlap_start_slot_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer(&self->slot_timer, timeout, (void *) self, 
+	irda_start_timer(&self->slot_timer, timeout, (void *) self,
 			 irlap_slot_timer_expired);
 }
 
@@ -67,31 +67,31 @@
 	/* Set or re-set the timer. We reset the timer for each received
 	 * discovery query, which allow us to automatically adjust to
 	 * the speed of the peer discovery (faster or slower). Jean II */
-	irda_start_timer( &self->query_timer, timeout, (void *) self, 
+	irda_start_timer( &self->query_timer, timeout, (void *) self,
 			  irlap_query_timer_expired);
 }
 
 void irlap_start_final_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer(&self->final_timer, timeout, (void *) self, 
+	irda_start_timer(&self->final_timer, timeout, (void *) self,
 			 irlap_final_timer_expired);
 }
 
 void irlap_start_wd_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer(&self->wd_timer, timeout, (void *) self, 
+	irda_start_timer(&self->wd_timer, timeout, (void *) self,
 			 irlap_wd_timer_expired);
 }
 
 void irlap_start_backoff_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer(&self->backoff_timer, timeout, (void *) self, 
+	irda_start_timer(&self->backoff_timer, timeout, (void *) self,
 			 irlap_backoff_timer_expired);
 }
 
 void irlap_start_mbusy_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer(&self->media_busy_timer, timeout, 
+	irda_start_timer(&self->media_busy_timer, timeout,
 			 (void *) self, irlap_media_busy_expired);
 }
 
@@ -109,25 +109,25 @@
 		irlap_do_event(self, MEDIA_BUSY_TIMER_EXPIRED, NULL, NULL);
 }
 
-void irlmp_start_watchdog_timer(struct lsap_cb *self, int timeout) 
+void irlmp_start_watchdog_timer(struct lsap_cb *self, int timeout)
 {
 	irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
 			 irlmp_watchdog_timer_expired);
 }
 
-void irlmp_start_discovery_timer(struct irlmp_cb *self, int timeout) 
+void irlmp_start_discovery_timer(struct irlmp_cb *self, int timeout)
 {
 	irda_start_timer(&self->discovery_timer, timeout, (void *) self,
 			 irlmp_discovery_timer_expired);
 }
 
-void irlmp_start_idle_timer(struct lap_cb *self, int timeout) 
+void irlmp_start_idle_timer(struct lap_cb *self, int timeout)
 {
 	irda_start_timer(&self->idle_timer, timeout, (void *) self,
 			 irlmp_idle_timer_expired);
 }
 
-void irlmp_stop_idle_timer(struct lap_cb *self) 
+void irlmp_stop_idle_timer(struct lap_cb *self)
 {
 	/* If timer is activated, kill it! */
 	del_timer(&self->idle_timer);
@@ -147,7 +147,7 @@
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
 	irlap_do_event(self, SLOT_TIMER_EXPIRED, NULL, NULL);
-} 
+}
 
 /*
  * Function irlap_query_timer_expired (data)
@@ -163,12 +163,12 @@
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
 	irlap_do_event(self, QUERY_TIMER_EXPIRED, NULL, NULL);
-} 
+}
 
 /*
  * Function irda_final_timer_expired (data)
  *
- *    
+ *
  *
  */
 static void irlap_final_timer_expired(void *data)
@@ -184,32 +184,32 @@
 /*
  * Function irda_wd_timer_expired (data)
  *
- *    
+ *
  *
  */
 static void irlap_wd_timer_expired(void *data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
-	
+
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
-	
+
 	irlap_do_event(self, WD_TIMER_EXPIRED, NULL, NULL);
 }
 
 /*
  * Function irda_backoff_timer_expired (data)
  *
- *    
+ *
  *
  */
 static void irlap_backoff_timer_expired(void *data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
-	
+
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
-	
+
 	irlap_do_event(self, BACKOFF_TIMER_EXPIRED, NULL, NULL);
 }
 
@@ -217,7 +217,7 @@
 /*
  * Function irtty_media_busy_expired (data)
  *
- *    
+ *
  */
 void irlap_media_busy_expired(void* data)
 {
diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c
index 87130c1..5abfb71 100644
--- a/net/irda/wrapper.c
+++ b/net/irda/wrapper.c
@@ -295,7 +295,7 @@
 	case OUTSIDE_FRAME:
 	case BEGIN_FRAME:
 	default:
-		/* We may receive multiple BOF at the start of frame */ 
+		/* We may receive multiple BOF at the start of frame */
 		break;
 	}
 
diff --git a/net/iucv/Kconfig b/net/iucv/Kconfig
new file mode 100644
index 0000000..f8fcc3d
--- /dev/null
+++ b/net/iucv/Kconfig
@@ -0,0 +1,15 @@
+config IUCV
+	tristate "IUCV support (VM only)"
+	depends on S390
+	help
+	  Select this option if you want to use inter-user communication under
+	  VM or VIF sockets. If you run on z/VM, say "Y" to enable a fast
+	  communication link between VM guests.
+
+config AFIUCV
+	tristate "AF_IUCV support (VM only)"
+	depends on IUCV
+	help
+	  Select this option if you want to use inter-user communication under
+	  VM or VIF sockets. If you run on z/VM, say "Y" to enable a fast
+	  communication link between VM guests.
diff --git a/net/iucv/Makefile b/net/iucv/Makefile
new file mode 100644
index 0000000..7bfdc85
--- /dev/null
+++ b/net/iucv/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for IUCV
+#
+
+obj-$(CONFIG_IUCV)	+= iucv.o
+obj-$(CONFIG_AFIUCV)	+= af_iucv.o
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
new file mode 100644
index 0000000..acc9421
--- /dev/null
+++ b/net/iucv/af_iucv.c
@@ -0,0 +1,1077 @@
+/*
+ *  linux/net/iucv/af_iucv.c
+ *
+ *  IUCV protocol stack for Linux on zSeries
+ *
+ *  Copyright 2006 IBM Corporation
+ *
+ *  Author(s):	Jennifer Hunt <jenhunt@us.ibm.com>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <net/sock.h>
+#include <asm/ebcdic.h>
+#include <asm/cpcmd.h>
+#include <linux/kmod.h>
+
+#include <net/iucv/iucv.h>
+#include <net/iucv/af_iucv.h>
+
+#define CONFIG_IUCV_SOCK_DEBUG 1
+
+#define IPRMDATA 0x80
+#define VERSION "1.0"
+
+static char iucv_userid[80];
+
+static struct proto_ops iucv_sock_ops;
+
+static struct proto iucv_proto = {
+	.name		= "AF_IUCV",
+	.owner		= THIS_MODULE,
+	.obj_size	= sizeof(struct iucv_sock),
+};
+
+/* Call Back functions */
+static void iucv_callback_rx(struct iucv_path *, struct iucv_message *);
+static void iucv_callback_txdone(struct iucv_path *, struct iucv_message *);
+static void iucv_callback_connack(struct iucv_path *, u8 ipuser[16]);
+static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
+
+static struct iucv_sock_list iucv_sk_list = {
+	.lock = RW_LOCK_UNLOCKED,
+	.autobind_name = ATOMIC_INIT(0)
+};
+
+static struct iucv_handler af_iucv_handler = {
+	.path_pending	  = iucv_callback_connreq,
+	.path_complete	  = iucv_callback_connack,
+	.path_severed	  = iucv_callback_connrej,
+	.message_pending  = iucv_callback_rx,
+	.message_complete = iucv_callback_txdone
+};
+
+static inline void high_nmcpy(unsigned char *dst, char *src)
+{
+       memcpy(dst, src, 8);
+}
+
+static inline void low_nmcpy(unsigned char *dst, char *src)
+{
+       memcpy(&dst[8], src, 8);
+}
+
+/* Timers */
+static void iucv_sock_timeout(unsigned long arg)
+{
+	struct sock *sk = (struct sock *)arg;
+
+	bh_lock_sock(sk);
+	sk->sk_err = ETIMEDOUT;
+	sk->sk_state_change(sk);
+	bh_unlock_sock(sk);
+
+	iucv_sock_kill(sk);
+	sock_put(sk);
+}
+
+static void iucv_sock_clear_timer(struct sock *sk)
+{
+	sk_stop_timer(sk, &sk->sk_timer);
+}
+
+static void iucv_sock_init_timer(struct sock *sk)
+{
+	init_timer(&sk->sk_timer);
+	sk->sk_timer.function = iucv_sock_timeout;
+	sk->sk_timer.data = (unsigned long)sk;
+}
+
+static struct sock *__iucv_get_sock_by_name(char *nm)
+{
+	struct sock *sk;
+	struct hlist_node *node;
+
+	sk_for_each(sk, node, &iucv_sk_list.head)
+		if (!memcmp(&iucv_sk(sk)->src_name, nm, 8))
+			return sk;
+
+	return NULL;
+}
+
+static void iucv_sock_destruct(struct sock *sk)
+{
+	skb_queue_purge(&sk->sk_receive_queue);
+	skb_queue_purge(&sk->sk_write_queue);
+}
+
+/* Cleanup Listen */
+static void iucv_sock_cleanup_listen(struct sock *parent)
+{
+	struct sock *sk;
+
+	/* Close non-accepted connections */
+	while ((sk = iucv_accept_dequeue(parent, NULL))) {
+		iucv_sock_close(sk);
+		iucv_sock_kill(sk);
+	}
+
+	parent->sk_state = IUCV_CLOSED;
+	sock_set_flag(parent, SOCK_ZAPPED);
+}
+
+/* Kill socket */
+static void iucv_sock_kill(struct sock *sk)
+{
+	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
+		return;
+
+	iucv_sock_unlink(&iucv_sk_list, sk);
+	sock_set_flag(sk, SOCK_DEAD);
+	sock_put(sk);
+}
+
+/* Close an IUCV socket */
+static void iucv_sock_close(struct sock *sk)
+{
+	unsigned char user_data[16];
+	struct iucv_sock *iucv = iucv_sk(sk);
+	int err;
+
+	iucv_sock_clear_timer(sk);
+	lock_sock(sk);
+
+	switch(sk->sk_state) {
+	case IUCV_LISTEN:
+		iucv_sock_cleanup_listen(sk);
+		break;
+
+	case IUCV_CONNECTED:
+	case IUCV_DISCONN:
+		err = 0;
+		if (iucv->path) {
+			low_nmcpy(user_data, iucv->src_name);
+			high_nmcpy(user_data, iucv->dst_name);
+			ASCEBC(user_data, sizeof(user_data));
+			err = iucv_path_sever(iucv->path, user_data);
+			iucv_path_free(iucv->path);
+			iucv->path = NULL;
+		}
+
+		sk->sk_state = IUCV_CLOSED;
+		sk->sk_state_change(sk);
+		sk->sk_err = ECONNRESET;
+		sk->sk_state_change(sk);
+
+		skb_queue_purge(&iucv->send_skb_q);
+
+		sock_set_flag(sk, SOCK_ZAPPED);
+		break;
+
+	default:
+		sock_set_flag(sk, SOCK_ZAPPED);
+		break;
+	};
+
+	release_sock(sk);
+	iucv_sock_kill(sk);
+}
+
+static void iucv_sock_init(struct sock *sk, struct sock *parent)
+{
+	if (parent)
+		sk->sk_type = parent->sk_type;
+}
+
+static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio)
+{
+	struct sock *sk;
+
+	sk = sk_alloc(PF_IUCV, prio, &iucv_proto, 1);
+	if (!sk)
+		return NULL;
+
+	sock_init_data(sock, sk);
+	INIT_LIST_HEAD(&iucv_sk(sk)->accept_q);
+	skb_queue_head_init(&iucv_sk(sk)->send_skb_q);
+	iucv_sk(sk)->send_tag = 0;
+
+	sk->sk_destruct = iucv_sock_destruct;
+	sk->sk_sndtimeo = IUCV_CONN_TIMEOUT;
+	sk->sk_allocation = GFP_DMA;
+
+	sock_reset_flag(sk, SOCK_ZAPPED);
+
+	sk->sk_protocol = proto;
+	sk->sk_state	= IUCV_OPEN;
+
+	iucv_sock_init_timer(sk);
+
+	iucv_sock_link(&iucv_sk_list, sk);
+	return sk;
+}
+
+/* Create an IUCV socket */
+static int iucv_sock_create(struct socket *sock, int protocol)
+{
+	struct sock *sk;
+
+	if (sock->type != SOCK_STREAM)
+		return -ESOCKTNOSUPPORT;
+
+	sock->state = SS_UNCONNECTED;
+	sock->ops = &iucv_sock_ops;
+
+	sk = iucv_sock_alloc(sock, protocol, GFP_KERNEL);
+	if (!sk)
+		return -ENOMEM;
+
+	iucv_sock_init(sk, NULL);
+
+	return 0;
+}
+
+void iucv_sock_link(struct iucv_sock_list *l, struct sock *sk)
+{
+	write_lock_bh(&l->lock);
+	sk_add_node(sk, &l->head);
+	write_unlock_bh(&l->lock);
+}
+
+void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *sk)
+{
+	write_lock_bh(&l->lock);
+	sk_del_node_init(sk);
+	write_unlock_bh(&l->lock);
+}
+
+void iucv_accept_enqueue(struct sock *parent, struct sock *sk)
+{
+	sock_hold(sk);
+	list_add_tail(&iucv_sk(sk)->accept_q, &iucv_sk(parent)->accept_q);
+	iucv_sk(sk)->parent = parent;
+	parent->sk_ack_backlog++;
+}
+
+void iucv_accept_unlink(struct sock *sk)
+{
+	list_del_init(&iucv_sk(sk)->accept_q);
+	iucv_sk(sk)->parent->sk_ack_backlog--;
+	iucv_sk(sk)->parent = NULL;
+	sock_put(sk);
+}
+
+struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock)
+{
+	struct iucv_sock *isk, *n;
+	struct sock *sk;
+
+	list_for_each_entry_safe(isk, n, &iucv_sk(parent)->accept_q, accept_q){
+		sk = (struct sock *) isk;
+		lock_sock(sk);
+
+		if (sk->sk_state == IUCV_CLOSED) {
+			release_sock(sk);
+			iucv_accept_unlink(sk);
+			continue;
+		}
+
+		if (sk->sk_state == IUCV_CONNECTED ||
+		    sk->sk_state == IUCV_SEVERED ||
+		    !newsock) {
+			iucv_accept_unlink(sk);
+			if (newsock)
+				sock_graft(sk, newsock);
+
+			if (sk->sk_state == IUCV_SEVERED)
+				sk->sk_state = IUCV_DISCONN;
+
+			release_sock(sk);
+			return sk;
+		}
+
+		release_sock(sk);
+	}
+	return NULL;
+}
+
+int iucv_sock_wait_state(struct sock *sk, int state, int state2,
+			 unsigned long timeo)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int err = 0;
+
+	add_wait_queue(sk->sk_sleep, &wait);
+	while (sk->sk_state != state && sk->sk_state != state2) {
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (!timeo) {
+			err = -EAGAIN;
+			break;
+		}
+
+		if (signal_pending(current)) {
+			err = sock_intr_errno(timeo);
+			break;
+		}
+
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock(sk);
+
+		err = sock_error(sk);
+		if (err)
+			break;
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk->sk_sleep, &wait);
+	return err;
+}
+
+/* Bind an unbound socket */
+static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
+			  int addr_len)
+{
+	struct sockaddr_iucv *sa = (struct sockaddr_iucv *) addr;
+	struct sock *sk = sock->sk;
+	struct iucv_sock *iucv;
+	int err;
+
+	/* Verify the input sockaddr */
+	if (!addr || addr->sa_family != AF_IUCV)
+		return -EINVAL;
+
+	lock_sock(sk);
+	if (sk->sk_state != IUCV_OPEN) {
+		err = -EBADFD;
+		goto done;
+	}
+
+	write_lock_bh(&iucv_sk_list.lock);
+
+	iucv = iucv_sk(sk);
+	if (__iucv_get_sock_by_name(sa->siucv_name)) {
+		err = -EADDRINUSE;
+		goto done_unlock;
+	}
+	if (iucv->path) {
+		err = 0;
+		goto done_unlock;
+	}
+
+	/* Bind the socket */
+	memcpy(iucv->src_name, sa->siucv_name, 8);
+
+	/* Copy the user id */
+	memcpy(iucv->src_user_id, iucv_userid, 8);
+	sk->sk_state = IUCV_BOUND;
+	err = 0;
+
+done_unlock:
+	/* Release the socket list lock */
+	write_unlock_bh(&iucv_sk_list.lock);
+done:
+	release_sock(sk);
+	return err;
+}
+
+/* Automatically bind an unbound socket */
+static int iucv_sock_autobind(struct sock *sk)
+{
+	struct iucv_sock *iucv = iucv_sk(sk);
+	char query_buffer[80];
+	char name[12];
+	int err = 0;
+
+	/* Set the userid and name */
+	cpcmd("QUERY USERID", query_buffer, sizeof(query_buffer), &err);
+	if (unlikely(err))
+		return -EPROTO;
+
+	memcpy(iucv->src_user_id, query_buffer, 8);
+
+	write_lock_bh(&iucv_sk_list.lock);
+
+	sprintf(name, "%08x", atomic_inc_return(&iucv_sk_list.autobind_name));
+	while (__iucv_get_sock_by_name(name)) {
+		sprintf(name, "%08x",
+			atomic_inc_return(&iucv_sk_list.autobind_name));
+	}
+
+	write_unlock_bh(&iucv_sk_list.lock);
+
+	memcpy(&iucv->src_name, name, 8);
+
+	return err;
+}
+
+/* Connect an unconnected socket */
+static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
+			     int alen, int flags)
+{
+	struct sockaddr_iucv *sa = (struct sockaddr_iucv *) addr;
+	struct sock *sk = sock->sk;
+	struct iucv_sock *iucv;
+	unsigned char user_data[16];
+	int err;
+
+	if (addr->sa_family != AF_IUCV || alen < sizeof(struct sockaddr_iucv))
+		return -EINVAL;
+
+	if (sk->sk_state != IUCV_OPEN && sk->sk_state != IUCV_BOUND)
+		return -EBADFD;
+
+	if (sk->sk_type != SOCK_STREAM)
+		return -EINVAL;
+
+	iucv = iucv_sk(sk);
+
+	if (sk->sk_state == IUCV_OPEN) {
+		err = iucv_sock_autobind(sk);
+		if (unlikely(err))
+			return err;
+	}
+
+	lock_sock(sk);
+
+	/* Set the destination information */
+	memcpy(iucv_sk(sk)->dst_user_id, sa->siucv_user_id, 8);
+	memcpy(iucv_sk(sk)->dst_name, sa->siucv_name, 8);
+
+	high_nmcpy(user_data, sa->siucv_name);
+	low_nmcpy(user_data, iucv_sk(sk)->src_name);
+	ASCEBC(user_data, sizeof(user_data));
+
+	iucv = iucv_sk(sk);
+	/* Create path. */
+	iucv->path = iucv_path_alloc(IUCV_QUEUELEN_DEFAULT,
+				     IPRMDATA, GFP_KERNEL);
+	err = iucv_path_connect(iucv->path, &af_iucv_handler,
+				sa->siucv_user_id, NULL, user_data, sk);
+	if (err) {
+		iucv_path_free(iucv->path);
+		iucv->path = NULL;
+		err = -ECONNREFUSED;
+		goto done;
+	}
+
+	if (sk->sk_state != IUCV_CONNECTED) {
+		err = iucv_sock_wait_state(sk, IUCV_CONNECTED, IUCV_DISCONN,
+				sock_sndtimeo(sk, flags & O_NONBLOCK));
+	}
+
+	if (sk->sk_state == IUCV_DISCONN) {
+		release_sock(sk);
+		return -ECONNREFUSED;
+	}
+done:
+	release_sock(sk);
+	return err;
+}
+
+/* Move a socket into listening state. */
+static int iucv_sock_listen(struct socket *sock, int backlog)
+{
+	struct sock *sk = sock->sk;
+	int err;
+
+	lock_sock(sk);
+
+	err = -EINVAL;
+	if (sk->sk_state != IUCV_BOUND || sock->type != SOCK_STREAM)
+		goto done;
+
+	sk->sk_max_ack_backlog = backlog;
+	sk->sk_ack_backlog = 0;
+	sk->sk_state = IUCV_LISTEN;
+	err = 0;
+
+done:
+	release_sock(sk);
+	return err;
+}
+
+/* Accept a pending connection */
+static int iucv_sock_accept(struct socket *sock, struct socket *newsock,
+			    int flags)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct sock *sk = sock->sk, *nsk;
+	long timeo;
+	int err = 0;
+
+	lock_sock(sk);
+
+	if (sk->sk_state != IUCV_LISTEN) {
+		err = -EBADFD;
+		goto done;
+	}
+
+	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
+
+	/* Wait for an incoming connection */
+	add_wait_queue_exclusive(sk->sk_sleep, &wait);
+	while (!(nsk = iucv_accept_dequeue(sk, newsock))){
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (!timeo) {
+			err = -EAGAIN;
+			break;
+		}
+
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock(sk);
+
+		if (sk->sk_state != IUCV_LISTEN) {
+			err = -EBADFD;
+			break;
+		}
+
+		if (signal_pending(current)) {
+			err = sock_intr_errno(timeo);
+			break;
+		}
+	}
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk->sk_sleep, &wait);
+
+	if (err)
+		goto done;
+
+	newsock->state = SS_CONNECTED;
+
+done:
+	release_sock(sk);
+	return err;
+}
+
+static int iucv_sock_getname(struct socket *sock, struct sockaddr *addr,
+			     int *len, int peer)
+{
+	struct sockaddr_iucv *siucv = (struct sockaddr_iucv *) addr;
+	struct sock *sk = sock->sk;
+
+	addr->sa_family = AF_IUCV;
+	*len = sizeof(struct sockaddr_iucv);
+
+	if (peer) {
+		memcpy(siucv->siucv_user_id, iucv_sk(sk)->dst_user_id, 8);
+		memcpy(siucv->siucv_name, &iucv_sk(sk)->dst_name, 8);
+	} else {
+		memcpy(siucv->siucv_user_id, iucv_sk(sk)->src_user_id, 8);
+		memcpy(siucv->siucv_name, iucv_sk(sk)->src_name, 8);
+	}
+	memset(&siucv->siucv_port, 0, sizeof(siucv->siucv_port));
+	memset(&siucv->siucv_addr, 0, sizeof(siucv->siucv_addr));
+	memset(siucv->siucv_nodeid, 0, sizeof(siucv->siucv_nodeid));
+
+	return 0;
+}
+
+static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
+			     struct msghdr *msg, size_t len)
+{
+	struct sock *sk = sock->sk;
+	struct iucv_sock *iucv = iucv_sk(sk);
+	struct sk_buff *skb;
+	struct iucv_message txmsg;
+	int err;
+
+	err = sock_error(sk);
+	if (err)
+		return err;
+
+	if (msg->msg_flags & MSG_OOB)
+		return -EOPNOTSUPP;
+
+	lock_sock(sk);
+
+	if (sk->sk_shutdown & SEND_SHUTDOWN) {
+		err = -EPIPE;
+		goto out;
+	}
+
+	if (sk->sk_state == IUCV_CONNECTED){
+		if(!(skb = sock_alloc_send_skb(sk, len,
+				       msg->msg_flags & MSG_DONTWAIT,
+				       &err)))
+			return err;
+
+		if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)){
+			err = -EFAULT;
+			goto fail;
+		}
+
+		txmsg.class = 0;
+		txmsg.tag = iucv->send_tag++;
+		memcpy(skb->cb, &txmsg.tag, 4);
+		skb_queue_tail(&iucv->send_skb_q, skb);
+		err = iucv_message_send(iucv->path, &txmsg, 0, 0,
+					(void *) skb->data, skb->len);
+		if (err) {
+			if (err == 3)
+				printk(KERN_ERR "AF_IUCV msg limit exceeded\n");
+			skb_unlink(skb, &iucv->send_skb_q);
+			err = -EPIPE;
+			goto fail;
+		}
+
+	} else {
+		err = -ENOTCONN;
+		goto out;
+	}
+
+	release_sock(sk);
+	return len;
+
+fail:
+	kfree_skb(skb);
+out:
+	release_sock(sk);
+	return err;
+}
+
+static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+			     struct msghdr *msg, size_t len, int flags)
+{
+	int noblock = flags & MSG_DONTWAIT;
+	struct sock *sk = sock->sk;
+	int target, copied = 0;
+	struct sk_buff *skb;
+	int err = 0;
+
+	if (flags & (MSG_OOB))
+		return -EOPNOTSUPP;
+
+	target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
+
+	skb = skb_recv_datagram(sk, flags, noblock, &err);
+	if (!skb) {
+		if (sk->sk_shutdown & RCV_SHUTDOWN)
+			return 0;
+		return err;
+	}
+
+	copied = min_t(unsigned int, skb->len, len);
+
+	if (memcpy_toiovec(msg->msg_iov, skb->data, copied)) {
+		skb_queue_head(&sk->sk_receive_queue, skb);
+		if (copied == 0)
+			return -EFAULT;
+	}
+
+	len -= copied;
+
+	/* Mark read part of skb as used */
+	if (!(flags & MSG_PEEK)) {
+		skb_pull(skb, copied);
+
+		if (skb->len) {
+			skb_queue_head(&sk->sk_receive_queue, skb);
+			goto done;
+		}
+
+		kfree_skb(skb);
+	} else
+		skb_queue_head(&sk->sk_receive_queue, skb);
+
+done:
+	return err ? : copied;
+}
+
+static inline unsigned int iucv_accept_poll(struct sock *parent)
+{
+	struct iucv_sock *isk, *n;
+	struct sock *sk;
+
+	list_for_each_entry_safe(isk, n, &iucv_sk(parent)->accept_q, accept_q){
+		sk = (struct sock *) isk;
+
+		if (sk->sk_state == IUCV_CONNECTED)
+			return POLLIN | POLLRDNORM;
+	}
+
+	return 0;
+}
+
+unsigned int iucv_sock_poll(struct file *file, struct socket *sock,
+			    poll_table *wait)
+{
+	struct sock *sk = sock->sk;
+	unsigned int mask = 0;
+
+	poll_wait(file, sk->sk_sleep, wait);
+
+	if (sk->sk_state == IUCV_LISTEN)
+		return iucv_accept_poll(sk);
+
+	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+		mask |= POLLERR;
+
+	if (sk->sk_shutdown & RCV_SHUTDOWN)
+		mask |= POLLRDHUP;
+
+	if (sk->sk_shutdown == SHUTDOWN_MASK)
+		mask |= POLLHUP;
+
+	if (!skb_queue_empty(&sk->sk_receive_queue) ||
+			(sk->sk_shutdown & RCV_SHUTDOWN))
+		mask |= POLLIN | POLLRDNORM;
+
+	if (sk->sk_state == IUCV_CLOSED)
+		mask |= POLLHUP;
+
+	if (sock_writeable(sk))
+		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+	else
+		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
+
+	return mask;
+}
+
+static int iucv_sock_shutdown(struct socket *sock, int how)
+{
+	struct sock *sk = sock->sk;
+	struct iucv_sock *iucv = iucv_sk(sk);
+	struct iucv_message txmsg;
+	int err = 0;
+	u8 prmmsg[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
+
+	how++;
+
+	if ((how & ~SHUTDOWN_MASK) || !how)
+		return -EINVAL;
+
+	lock_sock(sk);
+	switch(sk->sk_state) {
+	case IUCV_CLOSED:
+		err = -ENOTCONN;
+		goto fail;
+
+	default:
+		sk->sk_shutdown |= how;
+		break;
+	}
+
+	if (how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) {
+		txmsg.class = 0;
+		txmsg.tag = 0;
+		err = iucv_message_send(iucv->path, &txmsg, IUCV_IPRMDATA, 0,
+					(void *) prmmsg, 8);
+		if (err) {
+			switch(err) {
+			case 1:
+				err = -ENOTCONN;
+				break;
+			case 2:
+				err = -ECONNRESET;
+				break;
+			default:
+				err = -ENOTCONN;
+				break;
+			}
+		}
+	}
+
+	if (how == RCV_SHUTDOWN || how == SHUTDOWN_MASK) {
+		err = iucv_path_quiesce(iucv_sk(sk)->path, NULL);
+		if (err)
+			err = -ENOTCONN;
+
+		skb_queue_purge(&sk->sk_receive_queue);
+	}
+
+	/* Wake up anyone sleeping in poll */
+	sk->sk_state_change(sk);
+
+fail:
+	release_sock(sk);
+	return err;
+}
+
+static int iucv_sock_release(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+	int err = 0;
+
+	if (!sk)
+		return 0;
+
+	iucv_sock_close(sk);
+
+	/* Unregister with IUCV base support */
+	if (iucv_sk(sk)->path) {
+		iucv_path_sever(iucv_sk(sk)->path, NULL);
+		iucv_path_free(iucv_sk(sk)->path);
+		iucv_sk(sk)->path = NULL;
+	}
+
+	if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime){
+		lock_sock(sk);
+		err = iucv_sock_wait_state(sk, IUCV_CLOSED, 0,
+					   sk->sk_lingertime);
+		release_sock(sk);
+	}
+
+	sock_orphan(sk);
+	iucv_sock_kill(sk);
+	return err;
+}
+
+/* Callback wrappers - called from iucv base support */
+static int iucv_callback_connreq(struct iucv_path *path,
+				 u8 ipvmid[8], u8 ipuser[16])
+{
+	unsigned char user_data[16];
+	unsigned char nuser_data[16];
+	unsigned char src_name[8];
+	struct hlist_node *node;
+	struct sock *sk, *nsk;
+	struct iucv_sock *iucv, *niucv;
+	int err;
+
+	memcpy(src_name, ipuser, 8);
+	EBCASC(src_name, 8);
+	/* Find out if this path belongs to af_iucv. */
+	read_lock(&iucv_sk_list.lock);
+	iucv = NULL;
+	sk_for_each(sk, node, &iucv_sk_list.head)
+		if (sk->sk_state == IUCV_LISTEN &&
+		    !memcmp(&iucv_sk(sk)->src_name, src_name, 8)) {
+			/*
+			 * Found a listening socket with
+			 * src_name == ipuser[0-7].
+			 */
+			iucv = iucv_sk(sk);
+			break;
+		}
+	read_unlock(&iucv_sk_list.lock);
+	if (!iucv)
+		/* No socket found, not one of our paths. */
+		return -EINVAL;
+
+	bh_lock_sock(sk);
+
+	/* Check if parent socket is listening */
+	low_nmcpy(user_data, iucv->src_name);
+	high_nmcpy(user_data, iucv->dst_name);
+	ASCEBC(user_data, sizeof(user_data));
+	if (sk->sk_state != IUCV_LISTEN) {
+		err = iucv_path_sever(path, user_data);
+		goto fail;
+	}
+
+	/* Check for backlog size */
+	if (sk_acceptq_is_full(sk)) {
+		err = iucv_path_sever(path, user_data);
+		goto fail;
+	}
+
+	/* Create the new socket */
+	nsk = iucv_sock_alloc(NULL, SOCK_STREAM, GFP_ATOMIC);
+	if (!nsk){
+		err = iucv_path_sever(path, user_data);
+		goto fail;
+	}
+
+	niucv = iucv_sk(nsk);
+	iucv_sock_init(nsk, sk);
+
+	/* Set the new iucv_sock */
+	memcpy(niucv->dst_name, ipuser + 8, 8);
+	EBCASC(niucv->dst_name, 8);
+	memcpy(niucv->dst_user_id, ipvmid, 8);
+	memcpy(niucv->src_name, iucv->src_name, 8);
+	memcpy(niucv->src_user_id, iucv->src_user_id, 8);
+	niucv->path = path;
+
+	/* Call iucv_accept */
+	high_nmcpy(nuser_data, ipuser + 8);
+	memcpy(nuser_data + 8, niucv->src_name, 8);
+	ASCEBC(nuser_data + 8, 8);
+
+	path->msglim = IUCV_QUEUELEN_DEFAULT;
+	err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk);
+	if (err){
+		err = iucv_path_sever(path, user_data);
+		goto fail;
+	}
+
+	iucv_accept_enqueue(sk, nsk);
+
+	/* Wake up accept */
+	nsk->sk_state = IUCV_CONNECTED;
+	sk->sk_data_ready(sk, 1);
+	err = 0;
+fail:
+	bh_unlock_sock(sk);
+	return 0;
+}
+
+static void iucv_callback_connack(struct iucv_path *path, u8 ipuser[16])
+{
+	struct sock *sk = path->private;
+
+	sk->sk_state = IUCV_CONNECTED;
+	sk->sk_state_change(sk);
+}
+
+static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg)
+{
+	struct sock *sk = path->private;
+	struct sk_buff *skb;
+	int rc;
+
+	if (sk->sk_shutdown & RCV_SHUTDOWN)
+		return;
+
+	skb = alloc_skb(msg->length, GFP_ATOMIC | GFP_DMA);
+	if (!skb) {
+		iucv_message_reject(path, msg);
+		return;
+	}
+
+	if (msg->flags & IPRMDATA) {
+		skb->data = NULL;
+		skb->len = 0;
+	} else {
+		rc = iucv_message_receive(path, msg, 0, skb->data,
+					  msg->length, NULL);
+		if (rc) {
+			kfree_skb(skb);
+			return;
+		}
+
+		skb->h.raw = skb->data;
+		skb->nh.raw = skb->data;
+		skb->len = msg->length;
+	}
+
+	if (sock_queue_rcv_skb(sk, skb))
+		kfree_skb(skb);
+}
+
+static void iucv_callback_txdone(struct iucv_path *path,
+				 struct iucv_message *msg)
+{
+	struct sock *sk = path->private;
+	struct sk_buff *this;
+	struct sk_buff_head *list = &iucv_sk(sk)->send_skb_q;
+	struct sk_buff *list_skb = list->next;
+	unsigned long flags;
+
+	spin_lock_irqsave(&list->lock, flags);
+
+	do {
+		this = list_skb;
+		list_skb = list_skb->next;
+	} while (memcmp(&msg->tag, this->cb, 4));
+
+	spin_unlock_irqrestore(&list->lock, flags);
+
+	skb_unlink(this, &iucv_sk(sk)->send_skb_q);
+	kfree_skb(this);
+}
+
+static void iucv_callback_connrej(struct iucv_path *path, u8 ipuser[16])
+{
+	struct sock *sk = path->private;
+
+	if (!list_empty(&iucv_sk(sk)->accept_q))
+		sk->sk_state = IUCV_SEVERED;
+	else
+		sk->sk_state = IUCV_DISCONN;
+
+	sk->sk_state_change(sk);
+}
+
+static struct proto_ops iucv_sock_ops = {
+	.family		= PF_IUCV,
+	.owner		= THIS_MODULE,
+	.release	= iucv_sock_release,
+	.bind		= iucv_sock_bind,
+	.connect	= iucv_sock_connect,
+	.listen		= iucv_sock_listen,
+	.accept		= iucv_sock_accept,
+	.getname	= iucv_sock_getname,
+	.sendmsg	= iucv_sock_sendmsg,
+	.recvmsg	= iucv_sock_recvmsg,
+	.poll		= iucv_sock_poll,
+	.ioctl		= sock_no_ioctl,
+	.mmap		= sock_no_mmap,
+	.socketpair	= sock_no_socketpair,
+	.shutdown	= iucv_sock_shutdown,
+	.setsockopt	= sock_no_setsockopt,
+	.getsockopt	= sock_no_getsockopt
+};
+
+static struct net_proto_family iucv_sock_family_ops = {
+	.family	= AF_IUCV,
+	.owner	= THIS_MODULE,
+	.create	= iucv_sock_create,
+};
+
+static int afiucv_init(void)
+{
+	int err;
+
+	if (!MACHINE_IS_VM) {
+		printk(KERN_ERR "AF_IUCV connection needs VM as base\n");
+		err = -EPROTONOSUPPORT;
+		goto out;
+	}
+	cpcmd("QUERY USERID", iucv_userid, sizeof(iucv_userid), &err);
+	if (unlikely(err)) {
+		printk(KERN_ERR "AF_IUCV needs the VM userid\n");
+		err = -EPROTONOSUPPORT;
+		goto out;
+	}
+
+	err = iucv_register(&af_iucv_handler, 0);
+	if (err)
+		goto out;
+	err = proto_register(&iucv_proto, 0);
+	if (err)
+		goto out_iucv;
+	err = sock_register(&iucv_sock_family_ops);
+	if (err)
+		goto out_proto;
+	printk(KERN_INFO "AF_IUCV lowlevel driver initialized\n");
+	return 0;
+
+out_proto:
+	proto_unregister(&iucv_proto);
+out_iucv:
+	iucv_unregister(&af_iucv_handler, 0);
+out:
+	return err;
+}
+
+static void __exit afiucv_exit(void)
+{
+	sock_unregister(PF_IUCV);
+	proto_unregister(&iucv_proto);
+	iucv_unregister(&af_iucv_handler, 0);
+
+	printk(KERN_INFO "AF_IUCV lowlevel driver unloaded\n");
+}
+
+module_init(afiucv_init);
+module_exit(afiucv_exit);
+
+MODULE_AUTHOR("Jennifer Hunt <jenhunt@us.ibm.com>");
+MODULE_DESCRIPTION("IUCV Sockets ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETPROTO(PF_IUCV);
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
new file mode 100644
index 0000000..1b10d57
--- /dev/null
+++ b/net/iucv/iucv.c
@@ -0,0 +1,1619 @@
+/*
+ * IUCV base infrastructure.
+ *
+ * Copyright 2001, 2006 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s):
+ *    Original source:
+ *	Alan Altmark (Alan_Altmark@us.ibm.com)	Sept. 2000
+ *	Xenia Tkatschow (xenia@us.ibm.com)
+ *    2Gb awareness and general cleanup:
+ *	Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
+ *    Rewritten for af_iucv:
+ *	Martin Schwidefsky <schwidefsky@de.ibm.com>
+ *
+ * Documentation used:
+ *    The original source
+ *    CP Programming Service, IBM document # SC24-5760
+ *
+ * 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.
+ *
+ * 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/moduleparam.h>
+
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/cpu.h>
+#include <net/iucv/iucv.h>
+#include <asm/atomic.h>
+#include <asm/ebcdic.h>
+#include <asm/io.h>
+#include <asm/s390_ext.h>
+#include <asm/s390_rdev.h>
+#include <asm/smp.h>
+
+/*
+ * FLAGS:
+ * All flags are defined in the field IPFLAGS1 of each function
+ * and can be found in CP Programming Services.
+ * IPSRCCLS - Indicates you have specified a source class.
+ * IPTRGCLS - Indicates you have specified a target class.
+ * IPFGPID  - Indicates you have specified a pathid.
+ * IPFGMID  - Indicates you have specified a message ID.
+ * IPNORPY  - Indicates a one-way message. No reply expected.
+ * IPALL    - Indicates that all paths are affected.
+ */
+#define IUCV_IPSRCCLS	0x01
+#define IUCV_IPTRGCLS	0x01
+#define IUCV_IPFGPID	0x02
+#define IUCV_IPFGMID	0x04
+#define IUCV_IPNORPY	0x10
+#define IUCV_IPALL	0x80
+
+static int iucv_bus_match (struct device *dev, struct device_driver *drv)
+{
+	return 0;
+}
+
+struct bus_type iucv_bus = {
+	.name = "iucv",
+	.match = iucv_bus_match,
+};
+
+struct device *iucv_root;
+static int iucv_available;
+
+/* General IUCV interrupt structure */
+struct iucv_irq_data {
+	u16 ippathid;
+	u8  ipflags1;
+	u8  iptype;
+	u32 res2[8];
+};
+
+struct iucv_work {
+	struct list_head list;
+	struct iucv_irq_data data;
+};
+
+static LIST_HEAD(iucv_work_queue);
+static DEFINE_SPINLOCK(iucv_work_lock);
+
+static struct iucv_irq_data *iucv_irq_data;
+static cpumask_t iucv_buffer_cpumask = CPU_MASK_NONE;
+static cpumask_t iucv_irq_cpumask = CPU_MASK_NONE;
+
+static void iucv_tasklet_handler(unsigned long);
+static DECLARE_TASKLET(iucv_tasklet, iucv_tasklet_handler,0);
+
+enum iucv_command_codes {
+	IUCV_QUERY = 0,
+	IUCV_RETRIEVE_BUFFER = 2,
+	IUCV_SEND = 4,
+	IUCV_RECEIVE = 5,
+	IUCV_REPLY = 6,
+	IUCV_REJECT = 8,
+	IUCV_PURGE = 9,
+	IUCV_ACCEPT = 10,
+	IUCV_CONNECT = 11,
+	IUCV_DECLARE_BUFFER = 12,
+	IUCV_QUIESCE = 13,
+	IUCV_RESUME = 14,
+	IUCV_SEVER = 15,
+	IUCV_SETMASK = 16,
+};
+
+/*
+ * Error messages that are used with the iucv_sever function. They get
+ * converted to EBCDIC.
+ */
+static char iucv_error_no_listener[16] = "NO LISTENER";
+static char iucv_error_no_memory[16] = "NO MEMORY";
+static char iucv_error_pathid[16] = "INVALID PATHID";
+
+/*
+ * iucv_handler_list: List of registered handlers.
+ */
+static LIST_HEAD(iucv_handler_list);
+
+/*
+ * iucv_path_table: an array of iucv_path structures.
+ */
+static struct iucv_path **iucv_path_table;
+static unsigned long iucv_max_pathid;
+
+/*
+ * iucv_lock: spinlock protecting iucv_handler_list and iucv_pathid_table
+ */
+static DEFINE_SPINLOCK(iucv_table_lock);
+
+/*
+ * iucv_tasklet_cpu: contains the number of the cpu executing the tasklet.
+ * Needed for iucv_path_sever called from tasklet.
+ */
+static int iucv_tasklet_cpu = -1;
+
+/*
+ * Mutex and wait queue for iucv_register/iucv_unregister.
+ */
+static DEFINE_MUTEX(iucv_register_mutex);
+
+/*
+ * Counter for number of non-smp capable handlers.
+ */
+static int iucv_nonsmp_handler;
+
+/*
+ * IUCV control data structure. Used by iucv_path_accept, iucv_path_connect,
+ * iucv_path_quiesce and iucv_path_sever.
+ */
+struct iucv_cmd_control {
+	u16 ippathid;
+	u8  ipflags1;
+	u8  iprcode;
+	u16 ipmsglim;
+	u16 res1;
+	u8  ipvmid[8];
+	u8  ipuser[16];
+	u8  iptarget[8];
+} __attribute__ ((packed,aligned(8)));
+
+/*
+ * Data in parameter list iucv structure. Used by iucv_message_send,
+ * iucv_message_send2way and iucv_message_reply.
+ */
+struct iucv_cmd_dpl {
+	u16 ippathid;
+	u8  ipflags1;
+	u8  iprcode;
+	u32 ipmsgid;
+	u32 iptrgcls;
+	u8  iprmmsg[8];
+	u32 ipsrccls;
+	u32 ipmsgtag;
+	u32 ipbfadr2;
+	u32 ipbfln2f;
+	u32 res;
+} __attribute__ ((packed,aligned(8)));
+
+/*
+ * Data in buffer iucv structure. Used by iucv_message_receive,
+ * iucv_message_reject, iucv_message_send, iucv_message_send2way
+ * and iucv_declare_cpu.
+ */
+struct iucv_cmd_db {
+	u16 ippathid;
+	u8  ipflags1;
+	u8  iprcode;
+	u32 ipmsgid;
+	u32 iptrgcls;
+	u32 ipbfadr1;
+	u32 ipbfln1f;
+	u32 ipsrccls;
+	u32 ipmsgtag;
+	u32 ipbfadr2;
+	u32 ipbfln2f;
+	u32 res;
+} __attribute__ ((packed,aligned(8)));
+
+/*
+ * Purge message iucv structure. Used by iucv_message_purge.
+ */
+struct iucv_cmd_purge {
+	u16 ippathid;
+	u8  ipflags1;
+	u8  iprcode;
+	u32 ipmsgid;
+	u8  ipaudit[3];
+	u8  res1[5];
+	u32 res2;
+	u32 ipsrccls;
+	u32 ipmsgtag;
+	u32 res3[3];
+} __attribute__ ((packed,aligned(8)));
+
+/*
+ * Set mask iucv structure. Used by iucv_enable_cpu.
+ */
+struct iucv_cmd_set_mask {
+	u8  ipmask;
+	u8  res1[2];
+	u8  iprcode;
+	u32 res2[9];
+} __attribute__ ((packed,aligned(8)));
+
+union iucv_param {
+	struct iucv_cmd_control ctrl;
+	struct iucv_cmd_dpl dpl;
+	struct iucv_cmd_db db;
+	struct iucv_cmd_purge purge;
+	struct iucv_cmd_set_mask set_mask;
+};
+
+/*
+ * Anchor for per-cpu IUCV command parameter block.
+ */
+static union iucv_param *iucv_param;
+
+/**
+ * iucv_call_b2f0
+ * @code: identifier of IUCV call to CP.
+ * @parm: pointer to a struct iucv_parm block
+ *
+ * Calls CP to execute IUCV commands.
+ *
+ * Returns the result of the CP IUCV call.
+ */
+static inline int iucv_call_b2f0(int command, union iucv_param *parm)
+{
+	register unsigned long reg0 asm ("0");
+	register unsigned long reg1 asm ("1");
+	int ccode;
+
+	reg0 = command;
+	reg1 = virt_to_phys(parm);
+	asm volatile(
+		"	.long 0xb2f01000\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
+		: "=d" (ccode), "=m" (*parm), "+d" (reg0), "+a" (reg1)
+		:  "m" (*parm) : "cc");
+	return (ccode == 1) ? parm->ctrl.iprcode : ccode;
+}
+
+/**
+ * iucv_query_maxconn
+ *
+ * Determines the maximum number of connections that may be established.
+ *
+ * Returns the maximum number of connections or -EPERM is IUCV is not
+ * available.
+ */
+static int iucv_query_maxconn(void)
+{
+	register unsigned long reg0 asm ("0");
+	register unsigned long reg1 asm ("1");
+	void *param;
+	int ccode;
+
+	param = kzalloc(sizeof(union iucv_param), GFP_KERNEL|GFP_DMA);
+	if (!param)
+		return -ENOMEM;
+	reg0 = IUCV_QUERY;
+	reg1 = (unsigned long) param;
+	asm volatile (
+		"	.long	0xb2f01000\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
+		: "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
+	if (ccode == 0)
+		iucv_max_pathid = reg0;
+	kfree(param);
+	return ccode ? -EPERM : 0;
+}
+
+/**
+ * iucv_allow_cpu
+ * @data: unused
+ *
+ * Allow iucv interrupts on this cpu.
+ */
+static void iucv_allow_cpu(void *data)
+{
+	int cpu = smp_processor_id();
+	union iucv_param *parm;
+
+	/*
+	 * Enable all iucv interrupts.
+	 * ipmask contains bits for the different interrupts
+	 *	0x80 - Flag to allow nonpriority message pending interrupts
+	 *	0x40 - Flag to allow priority message pending interrupts
+	 *	0x20 - Flag to allow nonpriority message completion interrupts
+	 *	0x10 - Flag to allow priority message completion interrupts
+	 *	0x08 - Flag to allow IUCV control interrupts
+	 */
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	parm->set_mask.ipmask = 0xf8;
+	iucv_call_b2f0(IUCV_SETMASK, parm);
+
+	/* Set indication that iucv interrupts are allowed for this cpu. */
+	cpu_set(cpu, iucv_irq_cpumask);
+}
+
+/**
+ * iucv_block_cpu
+ * @data: unused
+ *
+ * Block iucv interrupts on this cpu.
+ */
+static void iucv_block_cpu(void *data)
+{
+	int cpu = smp_processor_id();
+	union iucv_param *parm;
+
+	/* Disable all iucv interrupts. */
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	iucv_call_b2f0(IUCV_SETMASK, parm);
+
+	/* Clear indication that iucv interrupts are allowed for this cpu. */
+	cpu_clear(cpu, iucv_irq_cpumask);
+}
+
+/**
+ * iucv_declare_cpu
+ * @data: unused
+ *
+ * Declare a interupt buffer on this cpu.
+ */
+static void iucv_declare_cpu(void *data)
+{
+	int cpu = smp_processor_id();
+	union iucv_param *parm;
+	int rc;
+
+	if (cpu_isset(cpu, iucv_buffer_cpumask))
+		return;
+
+	/* Declare interrupt buffer. */
+	parm = percpu_ptr(iucv_param, cpu);
+	memset(parm, 0, sizeof(union iucv_param));
+	parm->db.ipbfadr1 = virt_to_phys(percpu_ptr(iucv_irq_data, cpu));
+	rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm);
+	if (rc) {
+		char *err = "Unknown";
+		switch(rc) {
+		case 0x03:
+			err = "Directory error";
+			break;
+		case 0x0a:
+			err = "Invalid length";
+			break;
+		case 0x13:
+			err = "Buffer already exists";
+			break;
+		case 0x3e:
+			err = "Buffer overlap";
+			break;
+		case 0x5c:
+			err = "Paging or storage error";
+			break;
+		}
+		printk(KERN_WARNING "iucv_register: iucv_declare_buffer "
+		       "on cpu %i returned error 0x%02x (%s)\n", cpu, rc, err);
+		return;
+	}
+
+	/* Set indication that an iucv buffer exists for this cpu. */
+	cpu_set(cpu, iucv_buffer_cpumask);
+
+	if (iucv_nonsmp_handler == 0 || cpus_empty(iucv_irq_cpumask))
+		/* Enable iucv interrupts on this cpu. */
+		iucv_allow_cpu(NULL);
+	else
+		/* Disable iucv interrupts on this cpu. */
+		iucv_block_cpu(NULL);
+}
+
+/**
+ * iucv_retrieve_cpu
+ * @data: unused
+ *
+ * Retrieve interrupt buffer on this cpu.
+ */
+static void iucv_retrieve_cpu(void *data)
+{
+	int cpu = smp_processor_id();
+	union iucv_param *parm;
+
+	if (!cpu_isset(cpu, iucv_buffer_cpumask))
+		return;
+
+	/* Block iucv interrupts. */
+	iucv_block_cpu(NULL);
+
+	/* Retrieve interrupt buffer. */
+	parm = percpu_ptr(iucv_param, cpu);
+	iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm);
+
+	/* Clear indication that an iucv buffer exists for this cpu. */
+	cpu_clear(cpu, iucv_buffer_cpumask);
+}
+
+/**
+ * iucv_setmask_smp
+ *
+ * Allow iucv interrupts on all cpus.
+ */
+static void iucv_setmask_mp(void)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu)
+		/* Enable all cpus with a declared buffer. */
+		if (cpu_isset(cpu, iucv_buffer_cpumask) &&
+		    !cpu_isset(cpu, iucv_irq_cpumask))
+			smp_call_function_on(iucv_allow_cpu, NULL, 0, 1, cpu);
+}
+
+/**
+ * iucv_setmask_up
+ *
+ * Allow iucv interrupts on a single cpus.
+ */
+static void iucv_setmask_up(void)
+{
+	cpumask_t cpumask;
+	int cpu;
+
+	/* Disable all cpu but the first in cpu_irq_cpumask. */
+	cpumask = iucv_irq_cpumask;
+	cpu_clear(first_cpu(iucv_irq_cpumask), cpumask);
+	for_each_cpu_mask(cpu, cpumask)
+		smp_call_function_on(iucv_block_cpu, NULL, 0, 1, cpu);
+}
+
+/**
+ * iucv_enable
+ *
+ * This function makes iucv ready for use. It allocates the pathid
+ * table, declares an iucv interrupt buffer and enables the iucv
+ * interrupts. Called when the first user has registered an iucv
+ * handler.
+ */
+static int iucv_enable(void)
+{
+	size_t alloc_size;
+	int cpu, rc;
+
+	rc = -ENOMEM;
+	alloc_size = iucv_max_pathid * sizeof(struct iucv_path);
+	iucv_path_table = kzalloc(alloc_size, GFP_KERNEL);
+	if (!iucv_path_table)
+		goto out;
+	/* Declare per cpu buffers. */
+	rc = -EIO;
+	for_each_online_cpu(cpu)
+		smp_call_function_on(iucv_declare_cpu, NULL, 0, 1, cpu);
+	if (cpus_empty(iucv_buffer_cpumask))
+		/* No cpu could declare an iucv buffer. */
+		goto out_path;
+	return 0;
+
+out_path:
+	kfree(iucv_path_table);
+out:
+	return rc;
+}
+
+/**
+ * iucv_disable
+ *
+ * This function shuts down iucv. It disables iucv interrupts, retrieves
+ * the iucv interrupt buffer and frees the pathid table. Called after the
+ * last user unregister its iucv handler.
+ */
+static void iucv_disable(void)
+{
+	on_each_cpu(iucv_retrieve_cpu, NULL, 0, 1);
+	kfree(iucv_path_table);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
+				     unsigned long action, void *hcpu)
+{
+	cpumask_t cpumask;
+	long cpu = (long) hcpu;
+
+	switch (action) {
+	case CPU_UP_PREPARE:
+		if (!percpu_populate(iucv_irq_data,
+				     sizeof(struct iucv_irq_data),
+				     GFP_KERNEL|GFP_DMA, cpu))
+			return NOTIFY_BAD;
+		if (!percpu_populate(iucv_param, sizeof(union iucv_param),
+				     GFP_KERNEL|GFP_DMA, cpu)) {
+			percpu_depopulate(iucv_irq_data, cpu);
+			return NOTIFY_BAD;
+		}
+		break;
+	case CPU_UP_CANCELED:
+	case CPU_DEAD:
+		percpu_depopulate(iucv_param, cpu);
+		percpu_depopulate(iucv_irq_data, cpu);
+		break;
+	case CPU_ONLINE:
+	case CPU_DOWN_FAILED:
+		smp_call_function_on(iucv_declare_cpu, NULL, 0, 1, cpu);
+		break;
+	case CPU_DOWN_PREPARE:
+		cpumask = iucv_buffer_cpumask;
+		cpu_clear(cpu, cpumask);
+		if (cpus_empty(cpumask))
+			/* Can't offline last IUCV enabled cpu. */
+			return NOTIFY_BAD;
+		smp_call_function_on(iucv_retrieve_cpu, NULL, 0, 1, cpu);
+		if (cpus_empty(iucv_irq_cpumask))
+			smp_call_function_on(iucv_allow_cpu, NULL, 0, 1,
+					     first_cpu(iucv_buffer_cpumask));
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block iucv_cpu_notifier = {
+	.notifier_call = iucv_cpu_notify,
+};
+#endif
+
+/**
+ * iucv_sever_pathid
+ * @pathid: path identification number.
+ * @userdata: 16-bytes of user data.
+ *
+ * Sever an iucv path to free up the pathid. Used internally.
+ */
+static int iucv_sever_pathid(u16 pathid, u8 userdata[16])
+{
+	union iucv_param *parm;
+
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	if (userdata)
+		memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
+	parm->ctrl.ippathid = pathid;
+	return iucv_call_b2f0(IUCV_SEVER, parm);
+}
+
+/**
+ * __iucv_cleanup_pathid
+ * @dummy: unused dummy argument
+ *
+ * Nop function called via smp_call_function to force work items from
+ * pending external iucv interrupts to the work queue.
+ */
+static void __iucv_cleanup_pathid(void *dummy)
+{
+}
+
+/**
+ * iucv_cleanup_pathid
+ * @pathid: 16 bit pathid
+ *
+ * Function called after a path has been severed to find all remaining
+ * work items for the now stale pathid. The caller needs to hold the
+ * iucv_table_lock.
+ */
+static void iucv_cleanup_pathid(u16 pathid)
+{
+	struct iucv_work *p, *n;
+
+	/*
+	 * Path is severed, the pathid can be reused immediatly on
+	 * a iucv connect or a connection pending interrupt.
+	 * iucv_path_connect and connection pending interrupt will
+	 * wait until the iucv_table_lock is released before the
+	 * recycled pathid enters the system.
+	 * Force remaining interrupts to the work queue, then
+	 * scan the work queue for items of this path.
+	 */
+	smp_call_function(__iucv_cleanup_pathid, NULL, 0, 1);
+	spin_lock_irq(&iucv_work_lock);
+	list_for_each_entry_safe(p, n, &iucv_work_queue, list) {
+		/* Remove work items for pathid except connection pending */
+		if (p->data.ippathid == pathid && p->data.iptype != 0x01) {
+			list_del(&p->list);
+			kfree(p);
+		}
+	}
+	spin_unlock_irq(&iucv_work_lock);
+}
+
+/**
+ * iucv_register:
+ * @handler: address of iucv handler structure
+ * @smp: != 0 indicates that the handler can deal with out of order messages
+ *
+ * Registers a driver with IUCV.
+ *
+ * Returns 0 on success, -ENOMEM if the memory allocation for the pathid
+ * table failed, or -EIO if IUCV_DECLARE_BUFFER failed on all cpus.
+ */
+int iucv_register(struct iucv_handler *handler, int smp)
+{
+	int rc;
+
+	if (!iucv_available)
+		return -ENOSYS;
+	mutex_lock(&iucv_register_mutex);
+	if (!smp)
+		iucv_nonsmp_handler++;
+	if (list_empty(&iucv_handler_list)) {
+		rc = iucv_enable();
+		if (rc)
+			goto out_mutex;
+	} else if (!smp && iucv_nonsmp_handler == 1)
+		iucv_setmask_up();
+	INIT_LIST_HEAD(&handler->paths);
+
+	spin_lock_irq(&iucv_table_lock);
+	list_add_tail(&handler->list, &iucv_handler_list);
+	spin_unlock_irq(&iucv_table_lock);
+	rc = 0;
+out_mutex:
+	mutex_unlock(&iucv_register_mutex);
+	return rc;
+}
+
+/**
+ * iucv_unregister
+ * @handler:  address of iucv handler structure
+ * @smp: != 0 indicates that the handler can deal with out of order messages
+ *
+ * Unregister driver from IUCV.
+ */
+void iucv_unregister(struct iucv_handler *handler, int smp)
+{
+	struct iucv_path *p, *n;
+
+	mutex_lock(&iucv_register_mutex);
+	spin_lock_bh(&iucv_table_lock);
+	/* Remove handler from the iucv_handler_list. */
+	list_del_init(&handler->list);
+	/* Sever all pathids still refering to the handler. */
+	list_for_each_entry_safe(p, n, &handler->paths, list) {
+		iucv_sever_pathid(p->pathid, NULL);
+		iucv_path_table[p->pathid] = NULL;
+		list_del(&p->list);
+		iucv_cleanup_pathid(p->pathid);
+		iucv_path_free(p);
+	}
+	spin_unlock_bh(&iucv_table_lock);
+	if (!smp)
+		iucv_nonsmp_handler--;
+	if (list_empty(&iucv_handler_list))
+		iucv_disable();
+	else if (!smp && iucv_nonsmp_handler == 0)
+		iucv_setmask_mp();
+	mutex_unlock(&iucv_register_mutex);
+}
+
+/**
+ * iucv_path_accept
+ * @path: address of iucv path structure
+ * @handler: address of iucv handler structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ * @private: private data passed to interrupt handlers for this path
+ *
+ * This function is issued after the user received a connection pending
+ * external interrupt and now wishes to complete the IUCV communication path.
+ *
+ * Returns the result of the CP IUCV call.
+ */
+int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
+		     u8 userdata[16], void *private)
+{
+	union iucv_param *parm;
+	int rc;
+
+	local_bh_disable();
+	/* Prepare parameter block. */
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	parm->ctrl.ippathid = path->pathid;
+	parm->ctrl.ipmsglim = path->msglim;
+	if (userdata)
+		memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
+	parm->ctrl.ipflags1 = path->flags;
+
+	rc = iucv_call_b2f0(IUCV_ACCEPT, parm);
+	if (!rc) {
+		path->private = private;
+		path->msglim = parm->ctrl.ipmsglim;
+		path->flags = parm->ctrl.ipflags1;
+	}
+	local_bh_enable();
+	return rc;
+}
+
+/**
+ * iucv_path_connect
+ * @path: address of iucv path structure
+ * @handler: address of iucv handler structure
+ * @userid: 8-byte user identification
+ * @system: 8-byte target system identification
+ * @userdata: 16 bytes of data reflected to the communication partner
+ * @private: private data passed to interrupt handlers for this path
+ *
+ * This function establishes an IUCV path. Although the connect may complete
+ * successfully, you are not able to use the path until you receive an IUCV
+ * Connection Complete external interrupt.
+ *
+ * Returns the result of the CP IUCV call.
+ */
+int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
+		      u8 userid[8], u8 system[8], u8 userdata[16],
+		      void *private)
+{
+	union iucv_param *parm;
+	int rc;
+
+	preempt_disable();
+	if (iucv_tasklet_cpu != smp_processor_id())
+		spin_lock_bh(&iucv_table_lock);
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	parm->ctrl.ipmsglim = path->msglim;
+	parm->ctrl.ipflags1 = path->flags;
+	if (userid) {
+		memcpy(parm->ctrl.ipvmid, userid, sizeof(parm->ctrl.ipvmid));
+		ASCEBC(parm->ctrl.ipvmid, sizeof(parm->ctrl.ipvmid));
+		EBC_TOUPPER(parm->ctrl.ipvmid, sizeof(parm->ctrl.ipvmid));
+	}
+	if (system) {
+		memcpy(parm->ctrl.iptarget, system,
+		       sizeof(parm->ctrl.iptarget));
+		ASCEBC(parm->ctrl.iptarget, sizeof(parm->ctrl.iptarget));
+		EBC_TOUPPER(parm->ctrl.iptarget, sizeof(parm->ctrl.iptarget));
+	}
+	if (userdata)
+		memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
+
+	rc = iucv_call_b2f0(IUCV_CONNECT, parm);
+	if (!rc) {
+		if (parm->ctrl.ippathid < iucv_max_pathid) {
+			path->pathid = parm->ctrl.ippathid;
+			path->msglim = parm->ctrl.ipmsglim;
+			path->flags = parm->ctrl.ipflags1;
+			path->handler = handler;
+			path->private = private;
+			list_add_tail(&path->list, &handler->paths);
+			iucv_path_table[path->pathid] = path;
+		} else {
+			iucv_sever_pathid(parm->ctrl.ippathid,
+					  iucv_error_pathid);
+			rc = -EIO;
+		}
+	}
+	if (iucv_tasklet_cpu != smp_processor_id())
+		spin_unlock_bh(&iucv_table_lock);
+	preempt_enable();
+	return rc;
+}
+
+/**
+ * iucv_path_quiesce:
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function temporarily suspends incoming messages on an IUCV path.
+ * You can later reactivate the path by invoking the iucv_resume function.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16])
+{
+	union iucv_param *parm;
+	int rc;
+
+	local_bh_disable();
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	if (userdata)
+		memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
+	parm->ctrl.ippathid = path->pathid;
+	rc = iucv_call_b2f0(IUCV_QUIESCE, parm);
+	local_bh_enable();
+	return rc;
+}
+
+/**
+ * iucv_path_resume:
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function resumes incoming messages on an IUCV path that has
+ * been stopped with iucv_path_quiesce.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_resume(struct iucv_path *path, u8 userdata[16])
+{
+	union iucv_param *parm;
+	int rc;
+
+	local_bh_disable();
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	if (userdata)
+		memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
+	parm->ctrl.ippathid = path->pathid;
+	rc = iucv_call_b2f0(IUCV_RESUME, parm);
+	local_bh_enable();
+	return rc;
+}
+
+/**
+ * iucv_path_sever
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function terminates an IUCV path.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
+{
+	int rc;
+
+
+	preempt_disable();
+	if (iucv_tasklet_cpu != smp_processor_id())
+		spin_lock_bh(&iucv_table_lock);
+	rc = iucv_sever_pathid(path->pathid, userdata);
+	if (!rc) {
+		iucv_path_table[path->pathid] = NULL;
+		list_del_init(&path->list);
+		iucv_cleanup_pathid(path->pathid);
+	}
+	if (iucv_tasklet_cpu != smp_processor_id())
+		spin_unlock_bh(&iucv_table_lock);
+	preempt_enable();
+	return rc;
+}
+
+/**
+ * iucv_message_purge
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @srccls: source class of message
+ *
+ * Cancels a message you have sent.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
+		       u32 srccls)
+{
+	union iucv_param *parm;
+	int rc;
+
+	local_bh_disable();
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	parm->purge.ippathid = path->pathid;
+	parm->purge.ipmsgid = msg->id;
+	parm->purge.ipsrccls = srccls;
+	parm->purge.ipflags1 = IUCV_IPSRCCLS | IUCV_IPFGMID | IUCV_IPFGPID;
+	rc = iucv_call_b2f0(IUCV_PURGE, parm);
+	if (!rc) {
+		msg->audit = (*(u32 *) &parm->purge.ipaudit) >> 8;
+		msg->tag = parm->purge.ipmsgtag;
+	}
+	local_bh_enable();
+	return rc;
+}
+
+/**
+ * iucv_message_receive
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the message is received (IUCV_IPBUFLST)
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of data buffer
+ * @residual:
+ *
+ * This function receives messages that are being sent to you over
+ * established paths. This function will deal with RMDATA messages
+ * embedded in struct iucv_message as well.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
+			 u8 flags, void *buffer, size_t size, size_t *residual)
+{
+	union iucv_param *parm;
+	struct iucv_array *array;
+	u8 *rmmsg;
+	size_t copy;
+	int rc;
+
+	if (msg->flags & IUCV_IPRMDATA) {
+		/*
+		 * Message is 8 bytes long and has been stored to the
+		 * message descriptor itself.
+		 */
+		rc = (size < 8) ? 5 : 0;
+		if (residual)
+			*residual = abs(size - 8);
+		rmmsg = msg->rmmsg;
+		if (flags & IUCV_IPBUFLST) {
+			/* Copy to struct iucv_array. */
+			size = (size < 8) ? size : 8;
+			for (array = buffer; size > 0; array++) {
+				copy = min_t(size_t, size, array->length);
+				memcpy((u8 *)(addr_t) array->address,
+				       rmmsg, copy);
+				rmmsg += copy;
+				size -= copy;
+			}
+		} else {
+			/* Copy to direct buffer. */
+			memcpy(buffer, rmmsg, min_t(size_t, size, 8));
+		}
+		return 0;
+	}
+
+	local_bh_disable();
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	parm->db.ipbfadr1 = (u32)(addr_t) buffer;
+	parm->db.ipbfln1f = (u32) size;
+	parm->db.ipmsgid = msg->id;
+	parm->db.ippathid = path->pathid;
+	parm->db.iptrgcls = msg->class;
+	parm->db.ipflags1 = (flags | IUCV_IPFGPID |
+			     IUCV_IPFGMID | IUCV_IPTRGCLS);
+	rc = iucv_call_b2f0(IUCV_RECEIVE, parm);
+	if (!rc || rc == 5) {
+		msg->flags = parm->db.ipflags1;
+		if (residual)
+			*residual = parm->db.ipbfln1f;
+	}
+	local_bh_enable();
+	return rc;
+}
+
+/**
+ * iucv_message_reject
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ *
+ * The reject function refuses a specified message. Between the time you
+ * are notified of a message and the time that you complete the message,
+ * the message may be rejected.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
+{
+	union iucv_param *parm;
+	int rc;
+
+	local_bh_disable();
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	parm->db.ippathid = path->pathid;
+	parm->db.ipmsgid = msg->id;
+	parm->db.iptrgcls = msg->class;
+	parm->db.ipflags1 = (IUCV_IPTRGCLS | IUCV_IPFGMID | IUCV_IPFGPID);
+	rc = iucv_call_b2f0(IUCV_REJECT, parm);
+	local_bh_enable();
+	return rc;
+}
+
+/**
+ * iucv_message_reply
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the reply is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
+ * @reply: address of reply data buffer or address of struct iucv_array
+ * @size: length of reply data buffer
+ *
+ * This function responds to the two-way messages that you receive. You
+ * must identify completely the message to which you wish to reply. ie,
+ * pathid, msgid, and trgcls. Prmmsg signifies the data is moved into
+ * the parameter list.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
+		       u8 flags, void *reply, size_t size)
+{
+	union iucv_param *parm;
+	int rc;
+
+	local_bh_disable();
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	if (flags & IUCV_IPRMDATA) {
+		parm->dpl.ippathid = path->pathid;
+		parm->dpl.ipflags1 = flags;
+		parm->dpl.ipmsgid = msg->id;
+		parm->dpl.iptrgcls = msg->class;
+		memcpy(parm->dpl.iprmmsg, reply, min_t(size_t, size, 8));
+	} else {
+		parm->db.ipbfadr1 = (u32)(addr_t) reply;
+		parm->db.ipbfln1f = (u32) size;
+		parm->db.ippathid = path->pathid;
+		parm->db.ipflags1 = flags;
+		parm->db.ipmsgid = msg->id;
+		parm->db.iptrgcls = msg->class;
+	}
+	rc = iucv_call_b2f0(IUCV_REPLY, parm);
+	local_bh_enable();
+	return rc;
+}
+
+/**
+ * iucv_message_send
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the message is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
+ * @srccls: source class of message
+ * @buffer: address of send buffer or address of struct iucv_array
+ * @size: length of send buffer
+ *
+ * This function transmits data to another application. Data to be
+ * transmitted is in a buffer and this is a one-way message and the
+ * receiver will not reply to the message.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
+		      u8 flags, u32 srccls, void *buffer, size_t size)
+{
+	union iucv_param *parm;
+	int rc;
+
+	local_bh_disable();
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	if (flags & IUCV_IPRMDATA) {
+		/* Message of 8 bytes can be placed into the parameter list. */
+		parm->dpl.ippathid = path->pathid;
+		parm->dpl.ipflags1 = flags | IUCV_IPNORPY;
+		parm->dpl.iptrgcls = msg->class;
+		parm->dpl.ipsrccls = srccls;
+		parm->dpl.ipmsgtag = msg->tag;
+		memcpy(parm->dpl.iprmmsg, buffer, 8);
+	} else {
+		parm->db.ipbfadr1 = (u32)(addr_t) buffer;
+		parm->db.ipbfln1f = (u32) size;
+		parm->db.ippathid = path->pathid;
+		parm->db.ipflags1 = flags | IUCV_IPNORPY;
+		parm->db.iptrgcls = msg->class;
+		parm->db.ipsrccls = srccls;
+		parm->db.ipmsgtag = msg->tag;
+	}
+	rc = iucv_call_b2f0(IUCV_SEND, parm);
+	if (!rc)
+		msg->id = parm->db.ipmsgid;
+	local_bh_enable();
+	return rc;
+}
+
+/**
+ * iucv_message_send2way
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the message is sent and the reply is received
+ *	   (IUCV_IPRMDATA, IUCV_IPBUFLST, IUCV_IPPRTY, IUCV_ANSLST)
+ * @srccls: source class of message
+ * @buffer: address of send buffer or address of struct iucv_array
+ * @size: length of send buffer
+ * @ansbuf: address of answer buffer or address of struct iucv_array
+ * @asize: size of reply buffer
+ *
+ * This function transmits data to another application. Data to be
+ * transmitted is in a buffer. The receiver of the send is expected to
+ * reply to the message and a buffer is provided into which IUCV moves
+ * the reply to this message.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
+			  u8 flags, u32 srccls, void *buffer, size_t size,
+			  void *answer, size_t asize, size_t *residual)
+{
+	union iucv_param *parm;
+	int rc;
+
+	local_bh_disable();
+	parm = percpu_ptr(iucv_param, smp_processor_id());
+	memset(parm, 0, sizeof(union iucv_param));
+	if (flags & IUCV_IPRMDATA) {
+		parm->dpl.ippathid = path->pathid;
+		parm->dpl.ipflags1 = path->flags;	/* priority message */
+		parm->dpl.iptrgcls = msg->class;
+		parm->dpl.ipsrccls = srccls;
+		parm->dpl.ipmsgtag = msg->tag;
+		parm->dpl.ipbfadr2 = (u32)(addr_t) answer;
+		parm->dpl.ipbfln2f = (u32) asize;
+		memcpy(parm->dpl.iprmmsg, buffer, 8);
+	} else {
+		parm->db.ippathid = path->pathid;
+		parm->db.ipflags1 = path->flags;	/* priority message */
+		parm->db.iptrgcls = msg->class;
+		parm->db.ipsrccls = srccls;
+		parm->db.ipmsgtag = msg->tag;
+		parm->db.ipbfadr1 = (u32)(addr_t) buffer;
+		parm->db.ipbfln1f = (u32) size;
+		parm->db.ipbfadr2 = (u32)(addr_t) answer;
+		parm->db.ipbfln2f = (u32) asize;
+	}
+	rc = iucv_call_b2f0(IUCV_SEND, parm);
+	if (!rc)
+		msg->id = parm->db.ipmsgid;
+	local_bh_enable();
+	return rc;
+}
+
+/**
+ * iucv_path_pending
+ * @data: Pointer to external interrupt buffer
+ *
+ * Process connection pending work item. Called from tasklet while holding
+ * iucv_table_lock.
+ */
+struct iucv_path_pending {
+	u16 ippathid;
+	u8  ipflags1;
+	u8  iptype;
+	u16 ipmsglim;
+	u16 res1;
+	u8  ipvmid[8];
+	u8  ipuser[16];
+	u32 res3;
+	u8  ippollfg;
+	u8  res4[3];
+} __attribute__ ((packed));
+
+static void iucv_path_pending(struct iucv_irq_data *data)
+{
+	struct iucv_path_pending *ipp = (void *) data;
+	struct iucv_handler *handler;
+	struct iucv_path *path;
+	char *error;
+
+	BUG_ON(iucv_path_table[ipp->ippathid]);
+	/* New pathid, handler found. Create a new path struct. */
+	error = iucv_error_no_memory;
+	path = iucv_path_alloc(ipp->ipmsglim, ipp->ipflags1, GFP_ATOMIC);
+	if (!path)
+		goto out_sever;
+	path->pathid = ipp->ippathid;
+	iucv_path_table[path->pathid] = path;
+	EBCASC(ipp->ipvmid, 8);
+
+	/* Call registered handler until one is found that wants the path. */
+	list_for_each_entry(handler, &iucv_handler_list, list) {
+		if (!handler->path_pending)
+			continue;
+		/*
+		 * Add path to handler to allow a call to iucv_path_sever
+		 * inside the path_pending function. If the handler returns
+		 * an error remove the path from the handler again.
+		 */
+		list_add(&path->list, &handler->paths);
+		path->handler = handler;
+		if (!handler->path_pending(path, ipp->ipvmid, ipp->ipuser))
+			return;
+		list_del(&path->list);
+		path->handler = NULL;
+	}
+	/* No handler wanted the path. */
+	iucv_path_table[path->pathid] = NULL;
+	iucv_path_free(path);
+	error = iucv_error_no_listener;
+out_sever:
+	iucv_sever_pathid(ipp->ippathid, error);
+}
+
+/**
+ * iucv_path_complete
+ * @data: Pointer to external interrupt buffer
+ *
+ * Process connection complete work item. Called from tasklet while holding
+ * iucv_table_lock.
+ */
+struct iucv_path_complete {
+	u16 ippathid;
+	u8  ipflags1;
+	u8  iptype;
+	u16 ipmsglim;
+	u16 res1;
+	u8  res2[8];
+	u8  ipuser[16];
+	u32 res3;
+	u8  ippollfg;
+	u8  res4[3];
+} __attribute__ ((packed));
+
+static void iucv_path_complete(struct iucv_irq_data *data)
+{
+	struct iucv_path_complete *ipc = (void *) data;
+	struct iucv_path *path = iucv_path_table[ipc->ippathid];
+
+	BUG_ON(!path || !path->handler);
+	if (path->handler->path_complete)
+		path->handler->path_complete(path, ipc->ipuser);
+}
+
+/**
+ * iucv_path_severed
+ * @data: Pointer to external interrupt buffer
+ *
+ * Process connection severed work item. Called from tasklet while holding
+ * iucv_table_lock.
+ */
+struct iucv_path_severed {
+	u16 ippathid;
+	u8  res1;
+	u8  iptype;
+	u32 res2;
+	u8  res3[8];
+	u8  ipuser[16];
+	u32 res4;
+	u8  ippollfg;
+	u8  res5[3];
+} __attribute__ ((packed));
+
+static void iucv_path_severed(struct iucv_irq_data *data)
+{
+	struct iucv_path_severed *ips = (void *) data;
+	struct iucv_path *path = iucv_path_table[ips->ippathid];
+
+	BUG_ON(!path || !path->handler);
+	if (path->handler->path_severed)
+		path->handler->path_severed(path, ips->ipuser);
+	else {
+		iucv_sever_pathid(path->pathid, NULL);
+		iucv_path_table[path->pathid] = NULL;
+		list_del_init(&path->list);
+		iucv_cleanup_pathid(path->pathid);
+		iucv_path_free(path);
+	}
+}
+
+/**
+ * iucv_path_quiesced
+ * @data: Pointer to external interrupt buffer
+ *
+ * Process connection quiesced work item. Called from tasklet while holding
+ * iucv_table_lock.
+ */
+struct iucv_path_quiesced {
+	u16 ippathid;
+	u8  res1;
+	u8  iptype;
+	u32 res2;
+	u8  res3[8];
+	u8  ipuser[16];
+	u32 res4;
+	u8  ippollfg;
+	u8  res5[3];
+} __attribute__ ((packed));
+
+static void iucv_path_quiesced(struct iucv_irq_data *data)
+{
+	struct iucv_path_quiesced *ipq = (void *) data;
+	struct iucv_path *path = iucv_path_table[ipq->ippathid];
+
+	BUG_ON(!path || !path->handler);
+	if (path->handler->path_quiesced)
+		path->handler->path_quiesced(path, ipq->ipuser);
+}
+
+/**
+ * iucv_path_resumed
+ * @data: Pointer to external interrupt buffer
+ *
+ * Process connection resumed work item. Called from tasklet while holding
+ * iucv_table_lock.
+ */
+struct iucv_path_resumed {
+	u16 ippathid;
+	u8  res1;
+	u8  iptype;
+	u32 res2;
+	u8  res3[8];
+	u8  ipuser[16];
+	u32 res4;
+	u8  ippollfg;
+	u8  res5[3];
+} __attribute__ ((packed));
+
+static void iucv_path_resumed(struct iucv_irq_data *data)
+{
+	struct iucv_path_resumed *ipr = (void *) data;
+	struct iucv_path *path = iucv_path_table[ipr->ippathid];
+
+	BUG_ON(!path || !path->handler);
+	if (path->handler->path_resumed)
+		path->handler->path_resumed(path, ipr->ipuser);
+}
+
+/**
+ * iucv_message_complete
+ * @data: Pointer to external interrupt buffer
+ *
+ * Process message complete work item. Called from tasklet while holding
+ * iucv_table_lock.
+ */
+struct iucv_message_complete {
+	u16 ippathid;
+	u8  ipflags1;
+	u8  iptype;
+	u32 ipmsgid;
+	u32 ipaudit;
+	u8  iprmmsg[8];
+	u32 ipsrccls;
+	u32 ipmsgtag;
+	u32 res;
+	u32 ipbfln2f;
+	u8  ippollfg;
+	u8  res2[3];
+} __attribute__ ((packed));
+
+static void iucv_message_complete(struct iucv_irq_data *data)
+{
+	struct iucv_message_complete *imc = (void *) data;
+	struct iucv_path *path = iucv_path_table[imc->ippathid];
+	struct iucv_message msg;
+
+	BUG_ON(!path || !path->handler);
+	if (path->handler->message_complete) {
+		msg.flags = imc->ipflags1;
+		msg.id = imc->ipmsgid;
+		msg.audit = imc->ipaudit;
+		memcpy(msg.rmmsg, imc->iprmmsg, 8);
+		msg.class = imc->ipsrccls;
+		msg.tag = imc->ipmsgtag;
+		msg.length = imc->ipbfln2f;
+		path->handler->message_complete(path, &msg);
+	}
+}
+
+/**
+ * iucv_message_pending
+ * @data: Pointer to external interrupt buffer
+ *
+ * Process message pending work item. Called from tasklet while holding
+ * iucv_table_lock.
+ */
+struct iucv_message_pending {
+	u16 ippathid;
+	u8  ipflags1;
+	u8  iptype;
+	u32 ipmsgid;
+	u32 iptrgcls;
+	union {
+		u32 iprmmsg1_u32;
+		u8  iprmmsg1[4];
+	} ln1msg1;
+	union {
+		u32 ipbfln1f;
+		u8  iprmmsg2[4];
+	} ln1msg2;
+	u32 res1[3];
+	u32 ipbfln2f;
+	u8  ippollfg;
+	u8  res2[3];
+} __attribute__ ((packed));
+
+static void iucv_message_pending(struct iucv_irq_data *data)
+{
+	struct iucv_message_pending *imp = (void *) data;
+	struct iucv_path *path = iucv_path_table[imp->ippathid];
+	struct iucv_message msg;
+
+	BUG_ON(!path || !path->handler);
+	if (path->handler->message_pending) {
+		msg.flags = imp->ipflags1;
+		msg.id = imp->ipmsgid;
+		msg.class = imp->iptrgcls;
+		if (imp->ipflags1 & IUCV_IPRMDATA) {
+			memcpy(msg.rmmsg, imp->ln1msg1.iprmmsg1, 8);
+			msg.length = 8;
+		} else
+			msg.length = imp->ln1msg2.ipbfln1f;
+		msg.reply_size = imp->ipbfln2f;
+		path->handler->message_pending(path, &msg);
+	}
+}
+
+/**
+ * iucv_tasklet_handler:
+ *
+ * This tasklet loops over the queue of irq buffers created by
+ * iucv_external_interrupt, calls the appropriate action handler
+ * and then frees the buffer.
+ */
+static void iucv_tasklet_handler(unsigned long ignored)
+{
+	typedef void iucv_irq_fn(struct iucv_irq_data *);
+	static iucv_irq_fn *irq_fn[] = {
+		[0x01] = iucv_path_pending,
+		[0x02] = iucv_path_complete,
+		[0x03] = iucv_path_severed,
+		[0x04] = iucv_path_quiesced,
+		[0x05] = iucv_path_resumed,
+		[0x06] = iucv_message_complete,
+		[0x07] = iucv_message_complete,
+		[0x08] = iucv_message_pending,
+		[0x09] = iucv_message_pending,
+	};
+	struct iucv_work *p;
+
+	/* Serialize tasklet, iucv_path_sever and iucv_path_connect. */
+	spin_lock(&iucv_table_lock);
+	iucv_tasklet_cpu = smp_processor_id();
+
+	spin_lock_irq(&iucv_work_lock);
+	while (!list_empty(&iucv_work_queue)) {
+		p = list_entry(iucv_work_queue.next, struct iucv_work, list);
+		list_del_init(&p->list);
+		spin_unlock_irq(&iucv_work_lock);
+		irq_fn[p->data.iptype](&p->data);
+		kfree(p);
+		spin_lock_irq(&iucv_work_lock);
+	}
+	spin_unlock_irq(&iucv_work_lock);
+
+	iucv_tasklet_cpu = -1;
+	spin_unlock(&iucv_table_lock);
+}
+
+/**
+ * iucv_external_interrupt
+ * @code: irq code
+ *
+ * Handles external interrupts coming in from CP.
+ * Places the interrupt buffer on a queue and schedules iucv_tasklet_handler().
+ */
+static void iucv_external_interrupt(u16 code)
+{
+	struct iucv_irq_data *p;
+	struct iucv_work *work;
+
+	p = percpu_ptr(iucv_irq_data, smp_processor_id());
+	if (p->ippathid >= iucv_max_pathid) {
+		printk(KERN_WARNING "iucv_do_int: Got interrupt with "
+		       "pathid %d > max_connections (%ld)\n",
+		       p->ippathid, iucv_max_pathid - 1);
+		iucv_sever_pathid(p->ippathid, iucv_error_no_listener);
+		return;
+	}
+	if (p->iptype  < 0x01 || p->iptype > 0x09) {
+		printk(KERN_ERR "iucv_do_int: unknown iucv interrupt\n");
+		return;
+	}
+	work = kmalloc(sizeof(struct iucv_work), GFP_ATOMIC);
+	if (!work) {
+		printk(KERN_WARNING "iucv_external_interrupt: out of memory\n");
+		return;
+	}
+	memcpy(&work->data, p, sizeof(work->data));
+	spin_lock(&iucv_work_lock);
+	list_add_tail(&work->list, &iucv_work_queue);
+	spin_unlock(&iucv_work_lock);
+	tasklet_schedule(&iucv_tasklet);
+}
+
+/**
+ * iucv_init
+ *
+ * Allocates and initializes various data structures.
+ */
+static int iucv_init(void)
+{
+	int rc;
+
+	if (!MACHINE_IS_VM) {
+		rc = -EPROTONOSUPPORT;
+		goto out;
+	}
+	rc = iucv_query_maxconn();
+	if (rc)
+		goto out;
+	rc = register_external_interrupt (0x4000, iucv_external_interrupt);
+	if (rc)
+		goto out;
+	rc = bus_register(&iucv_bus);
+	if (rc)
+		goto out_int;
+	iucv_root = s390_root_dev_register("iucv");
+	if (IS_ERR(iucv_root)) {
+		rc = PTR_ERR(iucv_root);
+		goto out_bus;
+	}
+	/* Note: GFP_DMA used used to get memory below 2G */
+	iucv_irq_data = percpu_alloc(sizeof(struct iucv_irq_data),
+				     GFP_KERNEL|GFP_DMA);
+	if (!iucv_irq_data) {
+		rc = -ENOMEM;
+		goto out_root;
+	}
+	/* Allocate parameter blocks. */
+	iucv_param = percpu_alloc(sizeof(union iucv_param),
+				  GFP_KERNEL|GFP_DMA);
+	if (!iucv_param) {
+		rc = -ENOMEM;
+		goto out_extint;
+	}
+	register_hotcpu_notifier(&iucv_cpu_notifier);
+	ASCEBC(iucv_error_no_listener, 16);
+	ASCEBC(iucv_error_no_memory, 16);
+	ASCEBC(iucv_error_pathid, 16);
+	iucv_available = 1;
+	return 0;
+
+out_extint:
+	percpu_free(iucv_irq_data);
+out_root:
+	s390_root_dev_unregister(iucv_root);
+out_bus:
+	bus_unregister(&iucv_bus);
+out_int:
+	unregister_external_interrupt(0x4000, iucv_external_interrupt);
+out:
+	return rc;
+}
+
+/**
+ * iucv_exit
+ *
+ * Frees everything allocated from iucv_init.
+ */
+static void iucv_exit(void)
+{
+	struct iucv_work *p, *n;
+
+	spin_lock_irq(&iucv_work_lock);
+	list_for_each_entry_safe(p, n, &iucv_work_queue, list)
+		kfree(p);
+	spin_unlock_irq(&iucv_work_lock);
+	unregister_hotcpu_notifier(&iucv_cpu_notifier);
+	percpu_free(iucv_param);
+	percpu_free(iucv_irq_data);
+	s390_root_dev_unregister(iucv_root);
+	bus_unregister(&iucv_bus);
+	unregister_external_interrupt(0x4000, iucv_external_interrupt);
+}
+
+subsys_initcall(iucv_init);
+module_exit(iucv_exit);
+
+/**
+ * Export all public stuff
+ */
+EXPORT_SYMBOL (iucv_bus);
+EXPORT_SYMBOL (iucv_root);
+EXPORT_SYMBOL (iucv_register);
+EXPORT_SYMBOL (iucv_unregister);
+EXPORT_SYMBOL (iucv_path_accept);
+EXPORT_SYMBOL (iucv_path_connect);
+EXPORT_SYMBOL (iucv_path_quiesce);
+EXPORT_SYMBOL (iucv_path_sever);
+EXPORT_SYMBOL (iucv_message_purge);
+EXPORT_SYMBOL (iucv_message_receive);
+EXPORT_SYMBOL (iucv_message_reject);
+EXPORT_SYMBOL (iucv_message_reply);
+EXPORT_SYMBOL (iucv_message_send);
+EXPORT_SYMBOL (iucv_message_send2way);
+
+MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
+MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver");
+MODULE_LICENSE("GPL");
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 5dd5094..1c58204 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -152,7 +152,7 @@
 	sk = sk_alloc(PF_KEY, GFP_KERNEL, &key_proto, 1);
 	if (sk == NULL)
 		goto out;
-	
+
 	sock->ops = &pfkey_ops;
 	sock_init_data(sock, sk);
 
@@ -487,7 +487,7 @@
 			    ext_type == SADB_X_EXT_NAT_T_OA) {
 				if (verify_address_len(p))
 					return -EINVAL;
-			}				
+			}
 			if (ext_type == SADB_X_EXT_SEC_CTX) {
 				if (verify_sec_ctx_len(p))
 					return -EINVAL;
@@ -556,12 +556,12 @@
 {
 	switch (((struct sockaddr*)(addr + 1))->sa_family) {
 	case AF_INET:
-		xaddr->a4 = 
+		xaddr->a4 =
 			((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr;
 		return AF_INET;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
-		memcpy(xaddr->a6, 
+		memcpy(xaddr->a6,
 		       &((struct sockaddr_in6 *)(addr + 1))->sin6_addr,
 		       sizeof(struct in6_addr));
 		return AF_INET6;
@@ -659,11 +659,11 @@
 
 	/* base, SA, (lifetime (HSC),) address(SD), (address(P),)
 	   key(AE), (identity(SD),) (sensitivity)> */
-	size = sizeof(struct sadb_msg) +sizeof(struct sadb_sa) + 
+	size = sizeof(struct sadb_msg) +sizeof(struct sadb_sa) +
 		sizeof(struct sadb_lifetime) +
 		((hsc & 1) ? sizeof(struct sadb_lifetime) : 0) +
 		((hsc & 2) ? sizeof(struct sadb_lifetime) : 0) +
-			sizeof(struct sadb_address)*2 + 
+			sizeof(struct sadb_address)*2 +
 				sockaddr_size*2 +
 					sizeof(struct sadb_x_sa2);
 
@@ -685,13 +685,13 @@
 
 	if (add_keys) {
 		if (x->aalg && x->aalg->alg_key_len) {
-			auth_key_size = 
-				PFKEY_ALIGN8((x->aalg->alg_key_len + 7) / 8); 
+			auth_key_size =
+				PFKEY_ALIGN8((x->aalg->alg_key_len + 7) / 8);
 			size += sizeof(struct sadb_key) + auth_key_size;
 		}
 		if (x->ealg && x->ealg->alg_key_len) {
-			encrypt_key_size = 
-				PFKEY_ALIGN8((x->ealg->alg_key_len+7) / 8); 
+			encrypt_key_size =
+				PFKEY_ALIGN8((x->ealg->alg_key_len+7) / 8);
 			size += sizeof(struct sadb_key) + encrypt_key_size;
 		}
 	}
@@ -758,7 +758,7 @@
 
 	/* hard time */
 	if (hsc & 2) {
-		lifetime = (struct sadb_lifetime *)  skb_put(skb, 
+		lifetime = (struct sadb_lifetime *)  skb_put(skb,
 							     sizeof(struct sadb_lifetime));
 		lifetime->sadb_lifetime_len =
 			sizeof(struct sadb_lifetime)/sizeof(uint64_t);
@@ -770,7 +770,7 @@
 	}
 	/* soft time */
 	if (hsc & 1) {
-		lifetime = (struct sadb_lifetime *)  skb_put(skb, 
+		lifetime = (struct sadb_lifetime *)  skb_put(skb,
 							     sizeof(struct sadb_lifetime));
 		lifetime->sadb_lifetime_len =
 			sizeof(struct sadb_lifetime)/sizeof(uint64_t);
@@ -791,16 +791,16 @@
 	lifetime->sadb_lifetime_addtime = x->curlft.add_time;
 	lifetime->sadb_lifetime_usetime = x->curlft.use_time;
 	/* src address */
-	addr = (struct sadb_address*) skb_put(skb, 
+	addr = (struct sadb_address*) skb_put(skb,
 					      sizeof(struct sadb_address)+sockaddr_size);
-	addr->sadb_address_len = 
+	addr->sadb_address_len =
 		(sizeof(struct sadb_address)+sockaddr_size)/
 			sizeof(uint64_t);
 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
-	/* "if the ports are non-zero, then the sadb_address_proto field, 
-	   normally zero, MUST be filled in with the transport 
+	/* "if the ports are non-zero, then the sadb_address_proto field,
+	   normally zero, MUST be filled in with the transport
 	   protocol's number." - RFC2367 */
-	addr->sadb_address_proto = 0; 
+	addr->sadb_address_proto = 0;
 	addr->sadb_address_reserved = 0;
 	if (x->props.family == AF_INET) {
 		addr->sadb_address_prefixlen = 32;
@@ -813,29 +813,29 @@
 	}
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	else if (x->props.family == AF_INET6) {
- 		addr->sadb_address_prefixlen = 128;
+		addr->sadb_address_prefixlen = 128;
 
 		sin6 = (struct sockaddr_in6 *) (addr + 1);
 		sin6->sin6_family = AF_INET6;
 		sin6->sin6_port = 0;
 		sin6->sin6_flowinfo = 0;
- 		memcpy(&sin6->sin6_addr, x->props.saddr.a6,
+		memcpy(&sin6->sin6_addr, x->props.saddr.a6,
 		       sizeof(struct in6_addr));
 		sin6->sin6_scope_id = 0;
- 	}
+	}
 #endif
 	else
 		BUG();
 
 	/* dst address */
-	addr = (struct sadb_address*) skb_put(skb, 
+	addr = (struct sadb_address*) skb_put(skb,
 					      sizeof(struct sadb_address)+sockaddr_size);
-	addr->sadb_address_len = 
+	addr->sadb_address_len =
 		(sizeof(struct sadb_address)+sockaddr_size)/
 			sizeof(uint64_t);
 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
-	addr->sadb_address_proto = 0; 
-	addr->sadb_address_prefixlen = 32; /* XXX */ 
+	addr->sadb_address_proto = 0;
+	addr->sadb_address_prefixlen = 32; /* XXX */
 	addr->sadb_address_reserved = 0;
 	if (x->props.family == AF_INET) {
 		sin = (struct sockaddr_in *) (addr + 1);
@@ -845,9 +845,9 @@
 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 
 		if (x->sel.saddr.a4 != x->props.saddr.a4) {
-			addr = (struct sadb_address*) skb_put(skb, 
+			addr = (struct sadb_address*) skb_put(skb,
 				sizeof(struct sadb_address)+sockaddr_size);
-			addr->sadb_address_len = 
+			addr->sadb_address_len =
 				(sizeof(struct sadb_address)+sockaddr_size)/
 				sizeof(uint64_t);
 			addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
@@ -876,9 +876,9 @@
 
 		if (memcmp (x->sel.saddr.a6, x->props.saddr.a6,
 			    sizeof(struct in6_addr))) {
-			addr = (struct sadb_address *) skb_put(skb, 
+			addr = (struct sadb_address *) skb_put(skb,
 				sizeof(struct sadb_address)+sockaddr_size);
-			addr->sadb_address_len = 
+			addr->sadb_address_len =
 				(sizeof(struct sadb_address)+sockaddr_size)/
 				sizeof(uint64_t);
 			addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
@@ -902,7 +902,7 @@
 
 	/* auth key */
 	if (add_keys && auth_key_size) {
-		key = (struct sadb_key *) skb_put(skb, 
+		key = (struct sadb_key *) skb_put(skb,
 						  sizeof(struct sadb_key)+auth_key_size);
 		key->sadb_key_len = (sizeof(struct sadb_key) + auth_key_size) /
 			sizeof(uint64_t);
@@ -913,14 +913,14 @@
 	}
 	/* encrypt key */
 	if (add_keys && encrypt_key_size) {
-		key = (struct sadb_key *) skb_put(skb, 
+		key = (struct sadb_key *) skb_put(skb,
 						  sizeof(struct sadb_key)+encrypt_key_size);
-		key->sadb_key_len = (sizeof(struct sadb_key) + 
+		key->sadb_key_len = (sizeof(struct sadb_key) +
 				     encrypt_key_size) / sizeof(uint64_t);
 		key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
 		key->sadb_key_bits = x->ealg->alg_key_len;
 		key->sadb_key_reserved = 0;
-		memcpy(key + 1, x->ealg->alg_key, 
+		memcpy(key + 1, x->ealg->alg_key,
 		       (x->ealg->alg_key_len+7)/8);
 	}
 
@@ -979,17 +979,17 @@
 	return skb;
 }
 
-static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, 
+static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
 						void **ext_hdrs)
 {
-	struct xfrm_state *x; 
+	struct xfrm_state *x;
 	struct sadb_lifetime *lifetime;
 	struct sadb_sa *sa;
 	struct sadb_key *key;
 	struct sadb_x_sec_ctx *sec_ctx;
 	uint16_t proto;
 	int err;
-	
+
 
 	sa = (struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];
 	if (!sa ||
@@ -1022,7 +1022,7 @@
    SADB_SASTATE_MATURE and the kernel MUST return an error if this is
    not true.
 
-           However, KAME setkey always uses SADB_SASTATE_LARVAL.
+	   However, KAME setkey always uses SADB_SASTATE_LARVAL.
 	   Hence, we have to _ignore_ sadb_sa_state, which is also reasonable.
 	 */
 	if (sa->sadb_sa_auth > SADB_AALG_MAX ||
@@ -1144,13 +1144,13 @@
 	}
 	/* x->algo.flags = sa->sadb_sa_flags; */
 
-	x->props.family = pfkey_sadb_addr2xfrm_addr((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_SRC-1], 
+	x->props.family = pfkey_sadb_addr2xfrm_addr((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 						    &x->props.saddr);
 	if (!x->props.family) {
 		err = -EAFNOSUPPORT;
 		goto out;
 	}
-	pfkey_sadb_addr2xfrm_addr((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1], 
+	pfkey_sadb_addr2xfrm_addr((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1],
 				  &x->id.daddr);
 
 	if (ext_hdrs[SADB_X_EXT_SA2-1]) {
@@ -1410,7 +1410,7 @@
 	struct km_event c;
 
 	xfrm_probe_algs();
-	
+
 	x = pfkey_msg2xfrm_state(hdr, ext_hdrs);
 	if (IS_ERR(x))
 		return PTR_ERR(x);
@@ -1530,13 +1530,13 @@
 		auth_len *= sizeof(struct sadb_alg);
 		auth_len += sizeof(struct sadb_supported);
 	}
-	
+
 	enc_len = xfrm_count_enc_supported();
 	if (enc_len) {
 		enc_len *= sizeof(struct sadb_alg);
 		enc_len += sizeof(struct sadb_supported);
 	}
-	
+
 	len = enc_len + auth_len + sizeof(struct sadb_msg);
 
 	skb = alloc_skb(len + 16, allocation);
@@ -1605,7 +1605,7 @@
 	}
 
 	xfrm_probe_algs();
-	
+
 	supp_skb = compose_sadb_supported(hdr, GFP_KERNEL);
 	if (!supp_skb) {
 		if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC)
@@ -1856,7 +1856,7 @@
 
 	return sizeof(struct sadb_msg) +
 		(sizeof(struct sadb_lifetime) * 3) +
-		(sizeof(struct sadb_address) * 2) + 
+		(sizeof(struct sadb_address) * 2) +
 		(sockaddr_size * 2) +
 		sizeof(struct sadb_x_policy) +
 		(xp->xfrm_nr * sizeof(struct sadb_x_ipsecrequest)) +
@@ -1904,9 +1904,9 @@
 	memset(hdr, 0, size);	/* XXX do we need this ? */
 
 	/* src address */
-	addr = (struct sadb_address*) skb_put(skb, 
+	addr = (struct sadb_address*) skb_put(skb,
 					      sizeof(struct sadb_address)+sockaddr_size);
-	addr->sadb_address_len = 
+	addr->sadb_address_len =
 		(sizeof(struct sadb_address)+sockaddr_size)/
 			sizeof(uint64_t);
 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
@@ -1936,14 +1936,14 @@
 		BUG();
 
 	/* dst address */
-	addr = (struct sadb_address*) skb_put(skb, 
+	addr = (struct sadb_address*) skb_put(skb,
 					      sizeof(struct sadb_address)+sockaddr_size);
 	addr->sadb_address_len =
 		(sizeof(struct sadb_address)+sockaddr_size)/
 			sizeof(uint64_t);
 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
 	addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto);
-	addr->sadb_address_prefixlen = xp->selector.prefixlen_d; 
+	addr->sadb_address_prefixlen = xp->selector.prefixlen_d;
 	addr->sadb_address_reserved = 0;
 	if (xp->family == AF_INET) {
 		sin = (struct sockaddr_in *) (addr + 1);
@@ -1967,7 +1967,7 @@
 		BUG();
 
 	/* hard time */
-	lifetime = (struct sadb_lifetime *)  skb_put(skb, 
+	lifetime = (struct sadb_lifetime *)  skb_put(skb,
 						     sizeof(struct sadb_lifetime));
 	lifetime->sadb_lifetime_len =
 		sizeof(struct sadb_lifetime)/sizeof(uint64_t);
@@ -1977,7 +1977,7 @@
 	lifetime->sadb_lifetime_addtime = xp->lft.hard_add_expires_seconds;
 	lifetime->sadb_lifetime_usetime = xp->lft.hard_use_expires_seconds;
 	/* soft time */
-	lifetime = (struct sadb_lifetime *)  skb_put(skb, 
+	lifetime = (struct sadb_lifetime *)  skb_put(skb,
 						     sizeof(struct sadb_lifetime));
 	lifetime->sadb_lifetime_len =
 		sizeof(struct sadb_lifetime)/sizeof(uint64_t);
@@ -1987,7 +1987,7 @@
 	lifetime->sadb_lifetime_addtime = xp->lft.soft_add_expires_seconds;
 	lifetime->sadb_lifetime_usetime = xp->lft.soft_use_expires_seconds;
 	/* current time */
-	lifetime = (struct sadb_lifetime *)  skb_put(skb, 
+	lifetime = (struct sadb_lifetime *)  skb_put(skb,
 						     sizeof(struct sadb_lifetime));
 	lifetime->sadb_lifetime_len =
 		sizeof(struct sadb_lifetime)/sizeof(uint64_t);
@@ -2019,8 +2019,8 @@
 		req_size = sizeof(struct sadb_x_ipsecrequest);
 		if (t->mode == XFRM_MODE_TUNNEL)
 			req_size += ((t->encap_family == AF_INET ?
-		       		     sizeof(struct sockaddr_in) :
-		       		     sizeof(struct sockaddr_in6)) * 2);
+				     sizeof(struct sockaddr_in) :
+				     sizeof(struct sockaddr_in6)) * 2);
 		else
 			size -= 2*socklen;
 		rq = (void*)skb_put(skb, req_size);
@@ -2150,7 +2150,7 @@
 		      XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);
 	xp->priority = pol->sadb_x_policy_priority;
 
-	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1], 
+	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 	xp->family = pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.saddr);
 	if (!xp->family) {
 		err = -EINVAL;
@@ -2163,7 +2163,7 @@
 	if (xp->selector.sport)
 		xp->selector.sport_mask = htons(0xffff);
 
-	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1], 
+	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1],
 	pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.daddr);
 	xp->selector.prefixlen_d = sa->sadb_address_prefixlen;
 
@@ -2224,7 +2224,7 @@
 
 	if (hdr->sadb_msg_type == SADB_X_SPDUPDATE)
 		c.event = XFRM_MSG_UPDPOLICY;
-	else 
+	else
 		c.event = XFRM_MSG_NEWPOLICY;
 
 	c.seq = hdr->sadb_msg_seq;
@@ -2261,7 +2261,7 @@
 
 	memset(&sel, 0, sizeof(sel));
 
-	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1], 
+	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 	sel.family = pfkey_sadb_addr2xfrm_addr(sa, &sel.saddr);
 	sel.prefixlen_s = sa->sadb_address_prefixlen;
 	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
@@ -2269,7 +2269,7 @@
 	if (sel.sport)
 		sel.sport_mask = htons(0xffff);
 
-	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1], 
+	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1],
 	pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);
 	sel.prefixlen_d = sa->sadb_address_prefixlen;
 	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
@@ -2297,16 +2297,17 @@
 				   &sel, tmp.security, 1);
 	security_xfrm_policy_free(&tmp);
 
-	xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
-		       AUDIT_MAC_IPSEC_DELSPD, (xp) ? 1 : 0, xp, NULL);
-
 	if (xp == NULL)
 		return -ENOENT;
 
-	err = 0;
+	err = security_xfrm_policy_delete(xp);
 
-	if ((err = security_xfrm_policy_delete(xp)))
+	xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+		       AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL);
+
+	if (err)
 		goto out;
+
 	c.seq = hdr->sadb_msg_seq;
 	c.pid = hdr->sadb_msg_pid;
 	c.event = XFRM_MSG_DELPOLICY;
@@ -2345,6 +2346,196 @@
 	return err;
 }
 
+#ifdef CONFIG_NET_KEY_MIGRATE
+static int pfkey_sockaddr_pair_size(sa_family_t family)
+{
+	switch (family) {
+	case AF_INET:
+		return PFKEY_ALIGN8(sizeof(struct sockaddr_in) * 2);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		return PFKEY_ALIGN8(sizeof(struct sockaddr_in6) * 2);
+#endif
+	default:
+		return 0;
+	}
+	/* NOTREACHED */
+}
+
+static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq,
+			       xfrm_address_t *saddr, xfrm_address_t *daddr,
+			       u16 *family)
+{
+	struct sockaddr *sa = (struct sockaddr *)(rq + 1);
+	if (rq->sadb_x_ipsecrequest_len <
+	    pfkey_sockaddr_pair_size(sa->sa_family))
+		return -EINVAL;
+
+	switch (sa->sa_family) {
+	case AF_INET:
+		{
+			struct sockaddr_in *sin;
+			sin = (struct sockaddr_in *)sa;
+			if ((sin+1)->sin_family != AF_INET)
+				return -EINVAL;
+			memcpy(&saddr->a4, &sin->sin_addr, sizeof(saddr->a4));
+			sin++;
+			memcpy(&daddr->a4, &sin->sin_addr, sizeof(daddr->a4));
+			*family = AF_INET;
+			break;
+		}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		{
+			struct sockaddr_in6 *sin6;
+			sin6 = (struct sockaddr_in6 *)sa;
+			if ((sin6+1)->sin6_family != AF_INET6)
+				return -EINVAL;
+			memcpy(&saddr->a6, &sin6->sin6_addr,
+			       sizeof(saddr->a6));
+			sin6++;
+			memcpy(&daddr->a6, &sin6->sin6_addr,
+			       sizeof(daddr->a6));
+			*family = AF_INET6;
+			break;
+		}
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
+				    struct xfrm_migrate *m)
+{
+	int err;
+	struct sadb_x_ipsecrequest *rq2;
+
+	if (len <= sizeof(struct sadb_x_ipsecrequest) ||
+	    len < rq1->sadb_x_ipsecrequest_len)
+		return -EINVAL;
+
+	/* old endoints */
+	err = parse_sockaddr_pair(rq1, &m->old_saddr, &m->old_daddr,
+				  &m->old_family);
+	if (err)
+		return err;
+
+	rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len);
+	len -= rq1->sadb_x_ipsecrequest_len;
+
+	if (len <= sizeof(struct sadb_x_ipsecrequest) ||
+	    len < rq2->sadb_x_ipsecrequest_len)
+		return -EINVAL;
+
+	/* new endpoints */
+	err = parse_sockaddr_pair(rq2, &m->new_saddr, &m->new_daddr,
+				  &m->new_family);
+	if (err)
+		return err;
+
+	if (rq1->sadb_x_ipsecrequest_proto != rq2->sadb_x_ipsecrequest_proto ||
+	    rq1->sadb_x_ipsecrequest_mode != rq2->sadb_x_ipsecrequest_mode ||
+	    rq1->sadb_x_ipsecrequest_reqid != rq2->sadb_x_ipsecrequest_reqid)
+		return -EINVAL;
+
+	m->proto = rq1->sadb_x_ipsecrequest_proto;
+	m->mode = rq1->sadb_x_ipsecrequest_mode - 1;
+	m->reqid = rq1->sadb_x_ipsecrequest_reqid;
+
+	return ((int)(rq1->sadb_x_ipsecrequest_len +
+		      rq2->sadb_x_ipsecrequest_len));
+}
+
+static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
+			 struct sadb_msg *hdr, void **ext_hdrs)
+{
+	int i, len, ret, err = -EINVAL;
+	u8 dir;
+	struct sadb_address *sa;
+	struct sadb_x_policy *pol;
+	struct sadb_x_ipsecrequest *rq;
+	struct xfrm_selector sel;
+	struct xfrm_migrate m[XFRM_MAX_DEPTH];
+
+	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC - 1],
+	    ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) ||
+	    !ext_hdrs[SADB_X_EXT_POLICY - 1]) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	pol = ext_hdrs[SADB_X_EXT_POLICY - 1];
+	if (!pol) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (pol->sadb_x_policy_dir >= IPSEC_DIR_MAX) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	dir = pol->sadb_x_policy_dir - 1;
+	memset(&sel, 0, sizeof(sel));
+
+	/* set source address info of selector */
+	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC - 1];
+	sel.family = pfkey_sadb_addr2xfrm_addr(sa, &sel.saddr);
+	sel.prefixlen_s = sa->sadb_address_prefixlen;
+	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
+	sel.sport = ((struct sockaddr_in *)(sa + 1))->sin_port;
+	if (sel.sport)
+		sel.sport_mask = ~0;
+
+	/* set destination address info of selector */
+	sa = ext_hdrs[SADB_EXT_ADDRESS_DST - 1],
+	pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);
+	sel.prefixlen_d = sa->sadb_address_prefixlen;
+	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
+	sel.dport = ((struct sockaddr_in *)(sa + 1))->sin_port;
+	if (sel.dport)
+		sel.dport_mask = ~0;
+
+	rq = (struct sadb_x_ipsecrequest *)(pol + 1);
+
+	/* extract ipsecrequests */
+	i = 0;
+	len = pol->sadb_x_policy_len * 8 - sizeof(struct sadb_x_policy);
+
+	while (len > 0 && i < XFRM_MAX_DEPTH) {
+		ret = ipsecrequests_to_migrate(rq, len, &m[i]);
+		if (ret < 0) {
+			err = ret;
+			goto out;
+		} else {
+			rq = (struct sadb_x_ipsecrequest *)((u8 *)rq + ret);
+			len -= ret;
+			i++;
+		}
+	}
+
+	if (!i || len > 0) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i);
+
+ out:
+	return err;
+}
+#else
+static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
+			 struct sadb_msg *hdr, void **ext_hdrs)
+{
+	return -ENOPROTOOPT;
+}
+#endif
+
+
 static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
 	unsigned int dir;
@@ -2473,6 +2664,7 @@
 	[SADB_X_SPDFLUSH]	= pfkey_spdflush,
 	[SADB_X_SPDSETIDX]	= pfkey_spdadd,
 	[SADB_X_SPDDELETE2]	= pfkey_spdget,
+	[SADB_X_MIGRATE]	= pfkey_migrate,
 };
 
 static int pfkey_process(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr)
@@ -2552,15 +2744,15 @@
 		struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
 		if (!ealg)
 			break;
-			
+
 		if (!(ealg_tmpl_set(t, ealg) && ealg->available))
 			continue;
-			
+
 		for (k = 1; ; k++) {
 			struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
 			if (!aalg)
 				break;
-				
+
 			if (aalg_tmpl_set(t, aalg) && aalg->available)
 				sz += sizeof(struct sadb_comb);
 		}
@@ -2615,10 +2807,10 @@
 		struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
 		if (!ealg)
 			break;
-	
+
 		if (!(ealg_tmpl_set(t, ealg) && ealg->available))
 			continue;
-			
+
 		for (k = 1; ; k++) {
 			struct sadb_comb *c;
 			struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
@@ -2750,7 +2942,7 @@
 	struct sadb_x_sec_ctx *sec_ctx;
 	struct xfrm_sec_ctx *xfrm_ctx;
 	int ctx_size = 0;
-	
+
 	sockaddr_size = pfkey_sockaddr_size(x->props.family);
 	if (!sockaddr_size)
 		return -EINVAL;
@@ -2759,7 +2951,7 @@
 		(sizeof(struct sadb_address) * 2) +
 		(sockaddr_size * 2) +
 		sizeof(struct sadb_x_policy);
-	
+
 	if (x->id.proto == IPPROTO_AH)
 		size += count_ah_combs(t);
 	else if (x->id.proto == IPPROTO_ESP)
@@ -2773,7 +2965,7 @@
 	skb =  alloc_skb(size + 16, GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
-	
+
 	hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));
 	hdr->sadb_msg_version = PF_KEY_V2;
 	hdr->sadb_msg_type = SADB_ACQUIRE;
@@ -2785,9 +2977,9 @@
 	hdr->sadb_msg_pid = 0;
 
 	/* src address */
-	addr = (struct sadb_address*) skb_put(skb, 
+	addr = (struct sadb_address*) skb_put(skb,
 					      sizeof(struct sadb_address)+sockaddr_size);
-	addr->sadb_address_len = 
+	addr->sadb_address_len =
 		(sizeof(struct sadb_address)+sockaddr_size)/
 			sizeof(uint64_t);
 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
@@ -2817,9 +3009,9 @@
 #endif
 	else
 		BUG();
-	
+
 	/* dst address */
-	addr = (struct sadb_address*) skb_put(skb, 
+	addr = (struct sadb_address*) skb_put(skb,
 					      sizeof(struct sadb_address)+sockaddr_size);
 	addr->sadb_address_len =
 		(sizeof(struct sadb_address)+sockaddr_size)/
@@ -2828,7 +3020,7 @@
 	addr->sadb_address_proto = 0;
 	addr->sadb_address_reserved = 0;
 	if (x->props.family == AF_INET) {
-		addr->sadb_address_prefixlen = 32; 
+		addr->sadb_address_prefixlen = 32;
 
 		sin = (struct sockaddr_in *) (addr + 1);
 		sin->sin_family = AF_INET;
@@ -2838,7 +3030,7 @@
 	}
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	else if (x->props.family == AF_INET6) {
-		addr->sadb_address_prefixlen = 128; 
+		addr->sadb_address_prefixlen = 128;
 
 		sin6 = (struct sockaddr_in6 *) (addr + 1);
 		sin6->sin6_family = AF_INET6;
@@ -2883,7 +3075,7 @@
 }
 
 static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
-                                                u8 *data, int len, int *dir)
+						u8 *data, int len, int *dir)
 {
 	struct xfrm_policy *xp;
 	struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
@@ -3002,17 +3194,17 @@
 	 * HDR | SA | ADDRESS_SRC (old addr) | NAT_T_SPORT (old port) |
 	 * ADDRESS_DST (new addr) | NAT_T_DPORT (new port)
 	 */
-	
+
 	size = sizeof(struct sadb_msg) +
 		sizeof(struct sadb_sa) +
 		(sizeof(struct sadb_address) * 2) +
 		(sockaddr_size * 2) +
 		(sizeof(struct sadb_x_nat_t_port) * 2);
-	
+
 	skb =  alloc_skb(size + 16, GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
-	
+
 	hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));
 	hdr->sadb_msg_version = PF_KEY_V2;
 	hdr->sadb_msg_type = SADB_X_NAT_T_NEW_MAPPING;
@@ -3037,7 +3229,7 @@
 	/* ADDRESS_SRC (old addr) */
 	addr = (struct sadb_address*)
 		skb_put(skb, sizeof(struct sadb_address)+sockaddr_size);
-	addr->sadb_address_len = 
+	addr->sadb_address_len =
 		(sizeof(struct sadb_address)+sockaddr_size)/
 			sizeof(uint64_t);
 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
@@ -3078,7 +3270,7 @@
 	/* ADDRESS_DST (new addr) */
 	addr = (struct sadb_address*)
 		skb_put(skb, sizeof(struct sadb_address)+sockaddr_size);
-	addr->sadb_address_len = 
+	addr->sadb_address_len =
 		(sizeof(struct sadb_address)+sockaddr_size)/
 			sizeof(uint64_t);
 	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
@@ -3118,6 +3310,236 @@
 	return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL);
 }
 
+#ifdef CONFIG_NET_KEY_MIGRATE
+static int set_sadb_address(struct sk_buff *skb, int sasize, int type,
+			    struct xfrm_selector *sel)
+{
+	struct sadb_address *addr;
+	struct sockaddr_in *sin;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	struct sockaddr_in6 *sin6;
+#endif
+	addr = (struct sadb_address *)skb_put(skb, sizeof(struct sadb_address) + sasize);
+	addr->sadb_address_len = (sizeof(struct sadb_address) + sasize)/8;
+	addr->sadb_address_exttype = type;
+	addr->sadb_address_proto = sel->proto;
+	addr->sadb_address_reserved = 0;
+
+	switch (type) {
+	case SADB_EXT_ADDRESS_SRC:
+		if (sel->family == AF_INET) {
+			addr->sadb_address_prefixlen = sel->prefixlen_s;
+			sin = (struct sockaddr_in *)(addr + 1);
+			sin->sin_family = AF_INET;
+			memcpy(&sin->sin_addr.s_addr, &sel->saddr,
+			       sizeof(sin->sin_addr.s_addr));
+			sin->sin_port = 0;
+			memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+		}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		else if (sel->family == AF_INET6) {
+			addr->sadb_address_prefixlen = sel->prefixlen_s;
+			sin6 = (struct sockaddr_in6 *)(addr + 1);
+			sin6->sin6_family = AF_INET6;
+			sin6->sin6_port = 0;
+			sin6->sin6_flowinfo = 0;
+			sin6->sin6_scope_id = 0;
+			memcpy(&sin6->sin6_addr.s6_addr, &sel->saddr,
+			       sizeof(sin6->sin6_addr.s6_addr));
+		}
+#endif
+		break;
+	case SADB_EXT_ADDRESS_DST:
+		if (sel->family == AF_INET) {
+			addr->sadb_address_prefixlen = sel->prefixlen_d;
+			sin = (struct sockaddr_in *)(addr + 1);
+			sin->sin_family = AF_INET;
+			memcpy(&sin->sin_addr.s_addr, &sel->daddr,
+			       sizeof(sin->sin_addr.s_addr));
+			sin->sin_port = 0;
+			memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+		}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		else if (sel->family == AF_INET6) {
+			addr->sadb_address_prefixlen = sel->prefixlen_d;
+			sin6 = (struct sockaddr_in6 *)(addr + 1);
+			sin6->sin6_family = AF_INET6;
+			sin6->sin6_port = 0;
+			sin6->sin6_flowinfo = 0;
+			sin6->sin6_scope_id = 0;
+			memcpy(&sin6->sin6_addr.s6_addr, &sel->daddr,
+			       sizeof(sin6->sin6_addr.s6_addr));
+		}
+#endif
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int set_ipsecrequest(struct sk_buff *skb,
+			    uint8_t proto, uint8_t mode, int level,
+			    uint32_t reqid, uint8_t family,
+			    xfrm_address_t *src, xfrm_address_t *dst)
+{
+	struct sadb_x_ipsecrequest *rq;
+	struct sockaddr_in *sin;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	struct sockaddr_in6 *sin6;
+#endif
+	int size_req;
+
+	size_req = sizeof(struct sadb_x_ipsecrequest) +
+		   pfkey_sockaddr_pair_size(family);
+
+	rq = (struct sadb_x_ipsecrequest *)skb_put(skb, size_req);
+	memset(rq, 0, size_req);
+	rq->sadb_x_ipsecrequest_len = size_req;
+	rq->sadb_x_ipsecrequest_proto = proto;
+	rq->sadb_x_ipsecrequest_mode = mode;
+	rq->sadb_x_ipsecrequest_level = level;
+	rq->sadb_x_ipsecrequest_reqid = reqid;
+
+	switch (family) {
+	case AF_INET:
+		sin = (struct sockaddr_in *)(rq + 1);
+		sin->sin_family = AF_INET;
+		memcpy(&sin->sin_addr.s_addr, src,
+		       sizeof(sin->sin_addr.s_addr));
+		sin++;
+		sin->sin_family = AF_INET;
+		memcpy(&sin->sin_addr.s_addr, dst,
+		       sizeof(sin->sin_addr.s_addr));
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		sin6 = (struct sockaddr_in6 *)(rq + 1);
+		sin6->sin6_family = AF_INET6;
+		sin6->sin6_port = 0;
+		sin6->sin6_flowinfo = 0;
+		sin6->sin6_scope_id = 0;
+		memcpy(&sin6->sin6_addr.s6_addr, src,
+		       sizeof(sin6->sin6_addr.s6_addr));
+		sin6++;
+		sin6->sin6_family = AF_INET6;
+		sin6->sin6_port = 0;
+		sin6->sin6_flowinfo = 0;
+		sin6->sin6_scope_id = 0;
+		memcpy(&sin6->sin6_addr.s6_addr, dst,
+		       sizeof(sin6->sin6_addr.s6_addr));
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_NET_KEY_MIGRATE
+static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+			      struct xfrm_migrate *m, int num_bundles)
+{
+	int i;
+	int sasize_sel;
+	int size = 0;
+	int size_pol = 0;
+	struct sk_buff *skb;
+	struct sadb_msg *hdr;
+	struct sadb_x_policy *pol;
+	struct xfrm_migrate *mp;
+
+	if (type != XFRM_POLICY_TYPE_MAIN)
+		return 0;
+
+	if (num_bundles <= 0 || num_bundles > XFRM_MAX_DEPTH)
+		return -EINVAL;
+
+	/* selector */
+	sasize_sel = pfkey_sockaddr_size(sel->family);
+	if (!sasize_sel)
+		return -EINVAL;
+	size += (sizeof(struct sadb_address) + sasize_sel) * 2;
+
+	/* policy info */
+	size_pol += sizeof(struct sadb_x_policy);
+
+	/* ipsecrequests */
+	for (i = 0, mp = m; i < num_bundles; i++, mp++) {
+		/* old locator pair */
+		size_pol += sizeof(struct sadb_x_ipsecrequest) +
+			    pfkey_sockaddr_pair_size(mp->old_family);
+		/* new locator pair */
+		size_pol += sizeof(struct sadb_x_ipsecrequest) +
+			    pfkey_sockaddr_pair_size(mp->new_family);
+	}
+
+	size += sizeof(struct sadb_msg) + size_pol;
+
+	/* alloc buffer */
+	skb = alloc_skb(size, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	hdr = (struct sadb_msg *)skb_put(skb, sizeof(struct sadb_msg));
+	hdr->sadb_msg_version = PF_KEY_V2;
+	hdr->sadb_msg_type = SADB_X_MIGRATE;
+	hdr->sadb_msg_satype = pfkey_proto2satype(m->proto);
+	hdr->sadb_msg_len = size / 8;
+	hdr->sadb_msg_errno = 0;
+	hdr->sadb_msg_reserved = 0;
+	hdr->sadb_msg_seq = 0;
+	hdr->sadb_msg_pid = 0;
+
+	/* selector src */
+	set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel);
+
+	/* selector dst */
+	set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_DST, sel);
+
+	/* policy information */
+	pol = (struct sadb_x_policy *)skb_put(skb, sizeof(struct sadb_x_policy));
+	pol->sadb_x_policy_len = size_pol / 8;
+	pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+	pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
+	pol->sadb_x_policy_dir = dir + 1;
+	pol->sadb_x_policy_id = 0;
+	pol->sadb_x_policy_priority = 0;
+
+	for (i = 0, mp = m; i < num_bundles; i++, mp++) {
+		/* old ipsecrequest */
+		if (set_ipsecrequest(skb, mp->proto, mp->mode + 1,
+				     (mp->reqid ?  IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE),
+				     mp->reqid, mp->old_family,
+				     &mp->old_saddr, &mp->old_daddr) < 0) {
+			return -EINVAL;
+		}
+
+		/* new ipsecrequest */
+		if (set_ipsecrequest(skb, mp->proto, mp->mode + 1,
+				     (mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE),
+				     mp->reqid, mp->new_family,
+				     &mp->new_saddr, &mp->new_daddr) < 0) {
+			return -EINVAL;
+		}
+	}
+
+	/* broadcast migrate message to sockets */
+	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL);
+
+	return 0;
+}
+#else
+static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+			      struct xfrm_migrate *m, int num_bundles)
+{
+	return -ENOPROTOOPT;
+}
+#endif
+
 static int pfkey_sendmsg(struct kiocb *kiocb,
 			 struct socket *sock, struct msghdr *msg, size_t len)
 {
@@ -3253,7 +3675,7 @@
 			       );
 
 		buffer[len++] = '\n';
-		
+
 		pos = begin + len;
 		if (pos < offset) {
 			len = 0;
@@ -3287,6 +3709,7 @@
 	.compile_policy	= pfkey_compile_policy,
 	.new_mapping	= pfkey_send_new_mapping,
 	.notify_policy	= pfkey_send_policy_notify,
+	.migrate	= pfkey_send_migrate,
 };
 
 static void __exit ipsec_pfkey_exit(void)
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
index 7e6bc41..a2e7aa6 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -14,7 +14,7 @@
  *	LAPB 002	Jonathan Naylor	New timer architecture.
  *	2000-10-29	Henner Eisen	lapb_data_indication() return status.
  */
- 
+
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -43,7 +43,7 @@
 static DEFINE_RWLOCK(lapb_list_lock);
 
 /*
- *	Free an allocated lapb control block. 
+ *	Free an allocated lapb control block.
  */
 static void lapb_free_cb(struct lapb_cb *lapb)
 {
@@ -407,7 +407,7 @@
 		return lapb->callbacks.data_indication(lapb->dev, skb);
 
 	kfree_skb(skb);
-	return NET_RX_CN_HIGH; /* For now; must be != NET_RX_DROP */ 
+	return NET_RX_CN_HIGH; /* For now; must be != NET_RX_DROP */
 }
 
 int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb)
diff --git a/net/lapb/lapb_in.c b/net/lapb/lapb_in.c
index b0f8713..6762e7c 100644
--- a/net/lapb/lapb_in.c
+++ b/net/lapb/lapb_in.c
@@ -20,7 +20,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/lapb/lapb_out.c b/net/lapb/lapb_out.c
index 49a761b..339cc5f 100644
--- a/net/lapb/lapb_out.c
+++ b/net/lapb/lapb_out.c
@@ -19,7 +19,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -34,7 +33,7 @@
 #include <linux/interrupt.h>
 #include <net/lapb.h>
 
-/* 
+/*
  *  This procedure is passed a buffer descriptor for an iframe. It builds
  *  the rest of the control part of the frame and then writes it out.
  */
@@ -66,7 +65,7 @@
 	       lapb->dev, lapb->state, poll_bit, lapb->vs, lapb->vr);
 #endif
 
-	lapb_transmit_buffer(lapb, skb, LAPB_COMMAND);	
+	lapb_transmit_buffer(lapb, skb, LAPB_COMMAND);
 }
 
 void lapb_kick(struct lapb_cb *lapb)
diff --git a/net/lapb/lapb_subr.c b/net/lapb/lapb_subr.c
index 8b5eefd..b827f47 100644
--- a/net/lapb/lapb_subr.c
+++ b/net/lapb/lapb_subr.c
@@ -18,7 +18,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -59,7 +58,7 @@
 	 */
 	if (lapb->va != nr)
 		while (skb_peek(&lapb->ack_queue) && lapb->va != nr) {
-		        skb = skb_dequeue(&lapb->ack_queue);
+			skb = skb_dequeue(&lapb->ack_queue);
 			kfree_skb(skb);
 			lapb->va = (lapb->va + 1) % modulus;
 		}
@@ -67,7 +66,7 @@
 
 void lapb_requeue_frames(struct lapb_cb *lapb)
 {
-        struct sk_buff *skb, *skb_prev = NULL;
+	struct sk_buff *skb, *skb_prev = NULL;
 
 	/*
 	 * Requeue all the un-ack-ed frames on the output queue to be picked
@@ -91,7 +90,7 @@
 {
 	unsigned short vc = lapb->va;
 	int modulus;
-	
+
 	modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS;
 
 	while (vc != lapb->vs) {
@@ -99,7 +98,7 @@
 			return 1;
 		vc = (vc + 1) % modulus;
 	}
-	
+
 	return nr == lapb->vs;
 }
 
@@ -149,7 +148,7 @@
 				frame->cr = LAPB_RESPONSE;
 		}
 	}
-		
+
 	skb_pull(skb, 1);
 
 	if (lapb->mode & LAPB_EXTENDED) {
@@ -220,9 +219,9 @@
 	return 0;
 }
 
-/* 
+/*
  *	This routine is called when the HDLC layer internally  generates a
- *	command or  response  for  the remote machine ( eg. RR, UA etc. ). 
+ *	command or  response  for  the remote machine ( eg. RR, UA etc. ).
  *	Only supervisory or unnumbered frames are processed, FRMRs are handled
  *	by lapb_transmit_frmr below.
  */
@@ -259,7 +258,7 @@
 	lapb_transmit_buffer(lapb, skb, type);
 }
 
-/* 
+/*
  *	This routine generates FRMRs based on information previously stored in
  *	the LAPB control block.
  */
diff --git a/net/lapb/lapb_timer.c b/net/lapb/lapb_timer.c
index 2c8f0f8..af6d14b 100644
--- a/net/lapb/lapb_timer.c
+++ b/net/lapb/lapb_timer.c
@@ -101,7 +101,7 @@
 		/*
 		 *	Awaiting connection state, send SABM(E), up to N2 times.
 		 */
-		case LAPB_STATE_1: 
+		case LAPB_STATE_1:
 			if (lapb->n2count == lapb->n2) {
 				lapb_clear_queues(lapb);
 				lapb->state = LAPB_STATE_0;
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 190bb3e..7d9fa38 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -67,7 +67,7 @@
 static inline __be16 llc_proto_type(u16 arphrd)
 {
 	return arphrd == ARPHRD_IEEE802_TR ?
-		         htons(ETH_P_TR_802_2) : htons(ETH_P_802_2);
+			 htons(ETH_P_TR_802_2) : htons(ETH_P_802_2);
 }
 
 /**
@@ -114,7 +114,7 @@
 	struct llc_sock* llc = llc_sk(sk);
 	int rc = 0;
 
-	if (unlikely(llc_data_accept_state(llc->state) || 
+	if (unlikely(llc_data_accept_state(llc->state) ||
 		     llc->remote_busy_flag ||
 		     llc->p_flag)) {
 		long timeout = sock_sndtimeo(sk, noblock);
@@ -602,7 +602,7 @@
 	int rc = -EOPNOTSUPP;
 
 	dprintk("%s: accepting on %02X\n", __FUNCTION__,
-	        llc_sk(sk)->laddr.lsap);
+		llc_sk(sk)->laddr.lsap);
 	lock_sock(sk);
 	if (unlikely(sk->sk_type != SOCK_STREAM))
 		goto out;
@@ -617,7 +617,7 @@
 			goto out;
 	}
 	dprintk("%s: got a new connection on %02X\n", __FUNCTION__,
-	        llc_sk(sk)->laddr.lsap);
+		llc_sk(sk)->laddr.lsap);
 	skb = skb_dequeue(&sk->sk_receive_queue);
 	rc = -EINVAL;
 	if (!skb->sk)
@@ -682,7 +682,7 @@
 	if (flags & MSG_PEEK) {
 		peek_seq = llc->copied_seq;
 		seq = &peek_seq;
- 	}
+	}
 
 	target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
 	copied = 0;
@@ -860,7 +860,7 @@
 		goto release;
 	skb->dev      = llc->dev;
 	skb->protocol = llc_proto_type(addr->sllc_arphrd);
-	skb_reserve(skb, hdrlen); 
+	skb_reserve(skb, hdrlen);
 	rc = memcpy_fromiovec(skb_put(skb, copied), msg->msg_iov, copied);
 	if (rc)
 		goto out;
@@ -1116,11 +1116,11 @@
 };
 
 static char llc_proc_err_msg[] __initdata =
-        KERN_CRIT "LLC: Unable to register the proc_fs entries\n";
+	KERN_CRIT "LLC: Unable to register the proc_fs entries\n";
 static char llc_sysctl_err_msg[] __initdata =
-        KERN_CRIT "LLC: Unable to register the sysctl entries\n";
+	KERN_CRIT "LLC: Unable to register the sysctl entries\n";
 static char llc_sock_err_msg[] __initdata =
-        KERN_CRIT "LLC: Unable to register the network family\n";
+	KERN_CRIT "LLC: Unable to register the network family\n";
 
 static int __init llc2_init(void)
 {
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index c761c15..3b8cfbe 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -854,7 +854,7 @@
 	llc->n2 = 2;   /* max retransmit */
 	llc->k  = 2;   /* tx win size, will adjust dynam */
 	llc->rw = 128; /* rx win size (opt and equal to
-		        * tx_win of remote LLC) */
+			* tx_win of remote LLC) */
 	skb_queue_head_init(&llc->pdu_unack_q);
 	sk->sk_backlog_rcv = llc_backlog_rcv;
 }
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index db82aff..b3f65d1 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -164,7 +164,7 @@
 	sap = llc_sap_find(pdu->dsap);
 	if (unlikely(!sap)) {/* unknown SAP */
 		dprintk("%s: llc_sap_find(%02X) failed!\n", __FUNCTION__,
-		        pdu->dsap);
+			pdu->dsap);
 		goto drop;
 	}
 	/*
@@ -173,9 +173,9 @@
 	 */
 	rcv = rcu_dereference(sap->rcv_func);
 	if (rcv) {
- 		struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
- 		if (cskb)
- 			rcv(cskb, dev, pt, orig_dev);
+		struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
+		if (cskb)
+			rcv(cskb, dev, pt, orig_dev);
 	}
 	dest = llc_pdu_type(skb);
 	if (unlikely(!dest || !llc_type_handlers[dest - 1]))
diff --git a/net/llc/llc_output.c b/net/llc/llc_output.c
index b4e668e..f4291f3 100644
--- a/net/llc/llc_output.c
+++ b/net/llc/llc_output.c
@@ -40,7 +40,7 @@
 	case ARPHRD_IEEE802_TR: {
 		struct net_device *dev = skb->dev;
 		struct trh_hdr *trh;
-		
+
 		skb->mac.raw = skb_push(skb, sizeof(*trh));
 		trh = tr_hdr(skb);
 		trh->ac = AC;
diff --git a/net/llc/llc_pdu.c b/net/llc/llc_pdu.c
index a28ce52..fa83243 100644
--- a/net/llc/llc_pdu.c
+++ b/net/llc/llc_pdu.c
@@ -39,7 +39,7 @@
 
 	llc_pdu_decode_pdu_type(skb, &pdu_type);
 	pdu = llc_pdu_sn_hdr(skb);
-	
+
 	switch (pdu_type) {
 	case LLC_PDU_TYPE_I:
 	case LLC_PDU_TYPE_S:
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c
index 19308fe..3ab9d9f 100644
--- a/net/llc/llc_proc.c
+++ b/net/llc/llc_proc.c
@@ -142,18 +142,18 @@
 }
 
 static char *llc_conn_state_names[] = {
-	[LLC_CONN_STATE_ADM] =        "adm", 
-	[LLC_CONN_STATE_SETUP] =      "setup", 
+	[LLC_CONN_STATE_ADM] =        "adm",
+	[LLC_CONN_STATE_SETUP] =      "setup",
 	[LLC_CONN_STATE_NORMAL] =     "normal",
-	[LLC_CONN_STATE_BUSY] =       "busy", 
-	[LLC_CONN_STATE_REJ] =        "rej", 
-	[LLC_CONN_STATE_AWAIT] =      "await", 
+	[LLC_CONN_STATE_BUSY] =       "busy",
+	[LLC_CONN_STATE_REJ] =        "rej",
+	[LLC_CONN_STATE_AWAIT] =      "await",
 	[LLC_CONN_STATE_AWAIT_BUSY] = "await_busy",
 	[LLC_CONN_STATE_AWAIT_REJ] =  "await_rej",
 	[LLC_CONN_STATE_D_CONN]	=     "d_conn",
-	[LLC_CONN_STATE_RESET] =      "reset", 
-	[LLC_CONN_STATE_ERROR] =      "error", 
-	[LLC_CONN_STATE_TEMP] =       "temp", 
+	[LLC_CONN_STATE_RESET] =      "reset",
+	[LLC_CONN_STATE_ERROR] =      "error",
+	[LLC_CONN_STATE_TEMP] =       "temp",
 };
 
 static int llc_seq_core_show(struct seq_file *seq, void *v)
@@ -208,7 +208,7 @@
 	return seq_open(file, &llc_seq_core_ops);
 }
 
-static struct file_operations llc_seq_socket_fops = {
+static const struct file_operations llc_seq_socket_fops = {
 	.owner		= THIS_MODULE,
 	.open		= llc_seq_socket_open,
 	.read		= seq_read,
@@ -216,7 +216,7 @@
 	.release	= seq_release,
 };
 
-static struct file_operations llc_seq_core_fops = {
+static const struct file_operations llc_seq_core_fops = {
 	.owner		= THIS_MODULE,
 	.open		= llc_seq_core_open,
 	.read		= seq_read,
diff --git a/net/llc/llc_s_st.c b/net/llc/llc_s_st.c
index 6a43201..135f7d8 100644
--- a/net/llc/llc_s_st.c
+++ b/net/llc/llc_s_st.c
@@ -175,7 +175,7 @@
 	[LLC_SAP_STATE_INACTIVE - 1] = {
 		.curr_state	= LLC_SAP_STATE_INACTIVE,
 		.transitions	= llc_sap_inactive_state_transitions,
-       	},
+	},
 	[LLC_SAP_STATE_ACTIVE - 1] = {
 		.curr_state	= LLC_SAP_STATE_ACTIVE,
 		.transitions	= llc_sap_active_state_transitions,
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index 61cb8cf..2615dc8 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -201,7 +201,7 @@
 			if (sock_queue_rcv_skb(skb->sk, skb))
 				kfree_skb(skb);
 		}
-	} 
+	}
 	kfree_skb(skb);
 }
 
@@ -215,7 +215,7 @@
  *	This function is called when upper layer wants to send a TEST pdu.
  *	Returns 0 for success, 1 otherwise.
  */
-void llc_build_and_send_test_pkt(struct llc_sap *sap, 
+void llc_build_and_send_test_pkt(struct llc_sap *sap,
 				 struct sk_buff *skb, u8 *dmac, u8 dsap)
 {
 	struct llc_sap_state_ev *ev = llc_sap_ev(skb);
@@ -224,7 +224,7 @@
 	ev->daddr.lsap = dsap;
 	memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
 	memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
-	
+
 	ev->type      = LLC_SAP_EV_TYPE_PRIM;
 	ev->prim      = LLC_TEST_PRIM;
 	ev->prim_type = LLC_PRIM_TYPE_REQ;
diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c
index 8275bd3..576355a 100644
--- a/net/llc/llc_station.c
+++ b/net/llc/llc_station.c
@@ -112,17 +112,17 @@
 
 static int llc_stat_ev_enable_with_dup_addr_check(struct sk_buff *skb)
 {
-	struct llc_station_state_ev *ev = llc_station_ev(skb);	
-	
+	struct llc_station_state_ev *ev = llc_station_ev(skb);
+
 	return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
 	       ev->prim_type ==
-	       		      LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1;
+			      LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1;
 }
 
 static int llc_stat_ev_enable_without_dup_addr_check(struct sk_buff *skb)
 {
-	struct llc_station_state_ev *ev = llc_station_ev(skb);	
-	
+	struct llc_station_state_ev *ev = llc_station_ev(skb);
+
 	return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
 	       ev->prim_type ==
 			LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1;
@@ -130,8 +130,8 @@
 
 static int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct sk_buff *skb)
 {
-	struct llc_station_state_ev *ev = llc_station_ev(skb);	
-	
+	struct llc_station_state_ev *ev = llc_station_ev(skb);
+
 	return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
 		llc_main_station.retry_count <
 		llc_main_station.maximum_retry ? 0 : 1;
@@ -139,8 +139,8 @@
 
 static int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct sk_buff *skb)
 {
-	struct llc_station_state_ev *ev = llc_station_ev(skb);	
-	
+	struct llc_station_state_ev *ev = llc_station_ev(skb);
+
 	return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
 		llc_main_station.retry_count ==
 		llc_main_station.maximum_retry ? 0 : 1;
@@ -148,7 +148,7 @@
 
 static int llc_stat_ev_rx_null_dsap_xid_c(struct sk_buff *skb)
 {
-	struct llc_station_state_ev *ev = llc_station_ev(skb);	
+	struct llc_station_state_ev *ev = llc_station_ev(skb);
 	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 
 	return ev->type == LLC_STATION_EV_TYPE_PDU &&
@@ -306,7 +306,7 @@
 	llc_pdu_decode_sa(skb, mac_da);
 	llc_pdu_decode_ssap(skb, &dsap);
 	llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
-       	llc_pdu_init_as_test_rsp(nskb, skb);
+	llc_pdu_init_as_test_rsp(nskb, skb);
 	rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da);
 	if (unlikely(rc))
 		goto free;
diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c
index 45d7dd9..46992d0 100644
--- a/net/llc/sysctl_net_llc.c
+++ b/net/llc/sysctl_net_llc.c
@@ -1,6 +1,6 @@
 /*
  * sysctl_net_llc.c: sysctl interface to LLC net subsystem.
- * 
+ *
  * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  */
 
@@ -72,7 +72,7 @@
 		.procname	= "timeout",
 		.mode		= 0555,
 		.child		= llc2_timeout_table,
-       	},
+	},
 	{ 0 },
 };
 
@@ -82,7 +82,7 @@
 		.procname	= "llc2",
 		.mode		= 0555,
 		.child		= llc2_dir_timeout_table,
-       	},
+	},
 	{
 		.ctl_name       = NET_LLC_STATION,
 		.procname       = "station",
@@ -98,7 +98,7 @@
 		.procname	= "llc",
 		.mode		= 0555,
 		.child		= llc_table,
-       	},
+	},
 	{ 0 },
 };
 
@@ -116,7 +116,7 @@
 
 int __init llc_sysctl_init(void)
 {
-	llc_table_header = register_sysctl_table(llc_root_table, 1);
+	llc_table_header = register_sysctl_table(llc_root_table);
 
 	return llc_table_header ? 0 : -ENOMEM;
 }
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 80107d4..253fce3 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -235,6 +235,19 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NF_CONNTRACK_SANE
+	tristate "SANE protocol support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && NF_CONNTRACK
+	help
+	  SANE is a protocol for remote access to scanners as implemented
+	  by the 'saned' daemon. Like FTP, it uses separate control and
+	  data connections.
+
+	  With this module you can support SANE on a connection tracking
+	  firewall.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NF_CONNTRACK_SIP
 	tristate "SIP protocol support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && NF_CONNTRACK
@@ -289,7 +302,9 @@
 	tristate  '"CONNMARK" target support'
 	depends on NETFILTER_XTABLES
 	depends on IP_NF_MANGLE || IP6_NF_MANGLE
-	depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK)
+	depends on IP_NF_CONNTRACK || NF_CONNTRACK
+	select IP_NF_CONNTRACK_MARK if IP_NF_CONNTRACK
+	select NF_CONNTRACK_MARK if NF_CONNTRACK
 	help
 	  This option adds a `CONNMARK' target, which allows one to manipulate
 	  the connection mark value.  Similar to the MARK target, but
@@ -382,6 +397,32 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_TARGET_TCPMSS
+	tristate '"TCPMSS" target support'
+	depends on NETFILTER_XTABLES && (IPV6 || IPV6=n)
+	---help---
+	  This option adds a `TCPMSS' target, which allows you to alter the
+	  MSS value of TCP SYN packets, to control the maximum size for that
+	  connection (usually limiting it to your outgoing interface's MTU
+	  minus 40).
+
+	  This is used to overcome criminally braindead ISPs or servers which
+	  block ICMP Fragmentation Needed packets.  The symptoms of this
+	  problem are that everything works fine from your Linux
+	  firewall/router, but machines behind it can never exchange large
+	  packets:
+	        1) Web browsers connect, then hang with no data received.
+	        2) Small mail works fine, but large emails hang.
+	        3) ssh works fine, but scp hangs after initial handshaking.
+
+	  Workaround: activate this option and add a rule to your firewall
+	  configuration like:
+
+	  iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
+	                 -j TCPMSS --clamp-mss-to-pmtu
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_COMMENT
 	tristate  '"comment" match support'
 	depends on NETFILTER_XTABLES
@@ -395,7 +436,9 @@
 config NETFILTER_XT_MATCH_CONNBYTES
 	tristate  '"connbytes" per-connection counter match support'
 	depends on NETFILTER_XTABLES
-	depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK)
+	depends on IP_NF_CONNTRACK || NF_CONNTRACK
+	select IP_NF_CT_ACCT if IP_NF_CONNTRACK
+	select NF_CT_ACCT if NF_CONNTRACK
 	help
 	  This option adds a `connbytes' match, which allows you to match the
 	  number of bytes and/or packets for each direction within a connection.
@@ -406,7 +449,9 @@
 config NETFILTER_XT_MATCH_CONNMARK
 	tristate  '"connmark" connection mark match support'
 	depends on NETFILTER_XTABLES
-	depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK)
+	depends on IP_NF_CONNTRACK || NF_CONNTRACK
+	select IP_NF_CONNTRACK_MARK if IP_NF_CONNTRACK
+	select NF_CONNTRACK_MARK if NF_CONNTRACK
 	help
 	  This option adds a `connmark' match, which allows you to match the
 	  connection mark value previously set for the session by `CONNMARK'. 
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 5dc5574..b2b5c75 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -29,6 +29,7 @@
 obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o
 obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o
 obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o
+obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o
 obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o
 obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
 
@@ -44,6 +45,7 @@
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
 
 # matches
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 291b8c6..c3ebdbd 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -1,4 +1,4 @@
-/* netfilter.c: look after the filters for various protocols. 
+/* netfilter.c: look after the filters for various protocols.
  * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
  *
  * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
@@ -22,29 +22,34 @@
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
 #include <linux/proc_fs.h>
+#include <linux/mutex.h>
 #include <net/sock.h>
 
 #include "nf_internals.h"
 
-static DEFINE_SPINLOCK(afinfo_lock);
+static DEFINE_MUTEX(afinfo_mutex);
 
 struct nf_afinfo *nf_afinfo[NPROTO] __read_mostly;
 EXPORT_SYMBOL(nf_afinfo);
 
 int nf_register_afinfo(struct nf_afinfo *afinfo)
 {
-	spin_lock(&afinfo_lock);
+	int err;
+
+	err = mutex_lock_interruptible(&afinfo_mutex);
+	if (err < 0)
+		return err;
 	rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo);
-	spin_unlock(&afinfo_lock);
+	mutex_unlock(&afinfo_mutex);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(nf_register_afinfo);
 
 void nf_unregister_afinfo(struct nf_afinfo *afinfo)
 {
-	spin_lock(&afinfo_lock);
+	mutex_lock(&afinfo_mutex);
 	rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);
-	spin_unlock(&afinfo_lock);
+	mutex_unlock(&afinfo_mutex);
 	synchronize_rcu();
 }
 EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
@@ -56,30 +61,31 @@
  * packets come back: if the hook is gone, the packet is discarded. */
 struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS] __read_mostly;
 EXPORT_SYMBOL(nf_hooks);
-static DEFINE_SPINLOCK(nf_hook_lock);
+static DEFINE_MUTEX(nf_hook_mutex);
 
 int nf_register_hook(struct nf_hook_ops *reg)
 {
 	struct list_head *i;
+	int err;
 
-	spin_lock_bh(&nf_hook_lock);
+	err = mutex_lock_interruptible(&nf_hook_mutex);
+	if (err < 0)
+		return err;
 	list_for_each(i, &nf_hooks[reg->pf][reg->hooknum]) {
 		if (reg->priority < ((struct nf_hook_ops *)i)->priority)
 			break;
 	}
 	list_add_rcu(&reg->list, i->prev);
-	spin_unlock_bh(&nf_hook_lock);
-
-	synchronize_net();
+	mutex_unlock(&nf_hook_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(nf_register_hook);
 
 void nf_unregister_hook(struct nf_hook_ops *reg)
 {
-	spin_lock_bh(&nf_hook_lock);
+	mutex_lock(&nf_hook_mutex);
 	list_del_rcu(&reg->list);
-	spin_unlock_bh(&nf_hook_lock);
+	mutex_unlock(&nf_hook_mutex);
 
 	synchronize_net();
 }
@@ -135,14 +141,14 @@
 			continue;
 
 		/* Optimization: we don't need to hold module
-                   reference here, since function can't sleep. --RR */
+		   reference here, since function can't sleep. --RR */
 		verdict = elem->hook(hook, skb, indev, outdev, okfn);
 		if (verdict != NF_ACCEPT) {
 #ifdef CONFIG_NETFILTER_DEBUG
 			if (unlikely((verdict & NF_VERDICT_MASK)
 							> NF_MAX_VERDICT)) {
 				NFDEBUG("Evil return from %p(%u).\n",
-				        elem->hook, hook);
+					elem->hook, hook);
 				continue;
 			}
 #endif
@@ -248,9 +254,12 @@
 {
 	void (*attach)(struct sk_buff *, struct sk_buff *);
 
-	if (skb->nfct && (attach = ip_ct_attach) != NULL) {
-		mb(); /* Just to be sure: must be read before executing this */
-		attach(new, skb);
+	if (skb->nfct) {
+		rcu_read_lock();
+		attach = rcu_dereference(ip_ct_attach);
+		if (attach)
+			attach(new, skb);
+		rcu_read_unlock();
 	}
 }
 EXPORT_SYMBOL(nf_ct_attach);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 9b02ec4..32891eb 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -318,6 +318,7 @@
 	struct nf_conn_help *help = nfct_help(ct);
 	struct nf_conntrack_l3proto *l3proto;
 	struct nf_conntrack_l4proto *l4proto;
+	typeof(nf_conntrack_destroyed) destroyed;
 
 	DEBUGP("destroy_conntrack(%p)\n", ct);
 	NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
@@ -332,16 +333,21 @@
 	/* To make sure we don't get any weird locking issues here:
 	 * destroy_conntrack() MUST NOT be called with a write lock
 	 * to nf_conntrack_lock!!! -HW */
+	rcu_read_lock();
 	l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num);
 	if (l3proto && l3proto->destroy)
 		l3proto->destroy(ct);
 
-	l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
+	l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num,
+				       ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
 	if (l4proto && l4proto->destroy)
 		l4proto->destroy(ct);
 
-	if (nf_conntrack_destroyed)
-		nf_conntrack_destroyed(ct);
+	destroyed = rcu_dereference(nf_conntrack_destroyed);
+	if (destroyed)
+		destroyed(ct);
+
+	rcu_read_unlock();
 
 	write_lock_bh(&nf_conntrack_lock);
 	/* Expectations will have been removed in clean_from_lists,
@@ -418,7 +424,7 @@
 
 static void __nf_conntrack_hash_insert(struct nf_conn *ct,
 				       unsigned int hash,
-				       unsigned int repl_hash) 
+				       unsigned int repl_hash)
 {
 	ct->id = ++nf_conntrack_next_id;
 	list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list,
@@ -560,7 +566,7 @@
 	if (del_timer(&ct->timeout)) {
 		death_by_timeout((unsigned long)ct);
 		dropped = 1;
-		NF_CT_STAT_INC(early_drop);
+		NF_CT_STAT_INC_ATOMIC(early_drop);
 	}
 	nf_ct_put(ct);
 	return dropped;
@@ -647,9 +653,14 @@
 				   const struct nf_conntrack_tuple *repl)
 {
 	struct nf_conntrack_l3proto *l3proto;
+	struct nf_conn *ct;
 
+	rcu_read_lock();
 	l3proto = __nf_ct_l3proto_find(orig->src.l3num);
-	return __nf_conntrack_alloc(orig, repl, l3proto, 0);
+	ct = __nf_conntrack_alloc(orig, repl, l3proto, 0);
+	rcu_read_unlock();
+
+	return ct;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
 
@@ -813,11 +824,13 @@
 
 	/* Previously seen (loopback or untracked)?  Ignore. */
 	if ((*pskb)->nfct) {
-		NF_CT_STAT_INC(ignore);
+		NF_CT_STAT_INC_ATOMIC(ignore);
 		return NF_ACCEPT;
 	}
 
+	/* rcu_read_lock()ed by nf_hook_slow */
 	l3proto = __nf_ct_l3proto_find((u_int16_t)pf);
+
 	if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) {
 		DEBUGP("not prepared to track yet or error occured\n");
 		return -ret;
@@ -830,8 +843,8 @@
 	 * core what to do with the packet. */
 	if (l4proto->error != NULL &&
 	    (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
-		NF_CT_STAT_INC(error);
-		NF_CT_STAT_INC(invalid);
+		NF_CT_STAT_INC_ATOMIC(error);
+		NF_CT_STAT_INC_ATOMIC(invalid);
 		return -ret;
 	}
 
@@ -839,13 +852,13 @@
 			       &set_reply, &ctinfo);
 	if (!ct) {
 		/* Not valid part of a connection */
-		NF_CT_STAT_INC(invalid);
+		NF_CT_STAT_INC_ATOMIC(invalid);
 		return NF_ACCEPT;
 	}
 
 	if (IS_ERR(ct)) {
 		/* Too stressed to deal. */
-		NF_CT_STAT_INC(drop);
+		NF_CT_STAT_INC_ATOMIC(drop);
 		return NF_DROP;
 	}
 
@@ -858,7 +871,7 @@
 		DEBUGP("nf_conntrack_in: Can't track with proto module\n");
 		nf_conntrack_put((*pskb)->nfct);
 		(*pskb)->nfct = NULL;
-		NF_CT_STAT_INC(invalid);
+		NF_CT_STAT_INC_ATOMIC(invalid);
 		return -ret;
 	}
 
@@ -872,10 +885,15 @@
 int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
 			 const struct nf_conntrack_tuple *orig)
 {
-	return nf_ct_invert_tuple(inverse, orig,
-				  __nf_ct_l3proto_find(orig->src.l3num),
-				  __nf_ct_l4proto_find(orig->src.l3num,
-						     orig->dst.protonum));
+	int ret;
+
+	rcu_read_lock();
+	ret = nf_ct_invert_tuple(inverse, orig,
+				 __nf_ct_l3proto_find(orig->src.l3num),
+				 __nf_ct_l4proto_find(orig->src.l3num,
+						      orig->dst.protonum));
+	rcu_read_unlock();
+	return ret;
 }
 EXPORT_SYMBOL_GPL(nf_ct_invert_tuplepr);
 
@@ -1048,7 +1066,7 @@
 			if (iter(ct, data))
 				goto found;
 		}
- 	}
+	}
 	list_for_each_entry(h, &unconfirmed, list) {
 		ct = nf_ct_tuplehash_to_ctrack(h);
 		if (iter(ct, data))
@@ -1089,7 +1107,7 @@
 	if (vmalloced)
 		vfree(hash);
 	else
-		free_pages((unsigned long)hash, 
+		free_pages((unsigned long)hash,
 			   get_order(sizeof(struct list_head) * size));
 }
 
@@ -1105,7 +1123,7 @@
 {
 	int i;
 
-	ip_ct_attach = NULL;
+	rcu_assign_pointer(ip_ct_attach, NULL);
 
 	/* This makes sure all current packets have passed through
 	   netfilter framework.  Roll on, two-stage module
@@ -1150,18 +1168,18 @@
 	struct list_head *hash;
 	unsigned int i;
 
-	*vmalloced = 0; 
-	hash = (void*)__get_free_pages(GFP_KERNEL, 
+	*vmalloced = 0;
+	hash = (void*)__get_free_pages(GFP_KERNEL,
 				       get_order(sizeof(struct list_head)
 						 * size));
-	if (!hash) { 
+	if (!hash) {
 		*vmalloced = 1;
 		printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n");
 		hash = vmalloc(sizeof(struct list_head) * size);
 	}
 
 	if (hash)
-		for (i = 0; i < size; i++) 
+		for (i = 0; i < size; i++)
 			INIT_LIST_HEAD(&hash[i]);
 
 	return hash;
@@ -1268,12 +1286,12 @@
 
 	/* Don't NEED lock here, but good form anyway. */
 	write_lock_bh(&nf_conntrack_lock);
-        for (i = 0; i < AF_MAX; i++)
+	for (i = 0; i < AF_MAX; i++)
 		nf_ct_l3protos[i] = &nf_conntrack_l3proto_generic;
-        write_unlock_bh(&nf_conntrack_lock);
+	write_unlock_bh(&nf_conntrack_lock);
 
 	/* For use by REJECT target */
-	ip_ct_attach = __nf_conntrack_attach;
+	rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach);
 
 	/* Set up fake conntrack:
 	    - to never be deleted, not in any hashes */
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 9cbf926..ce70a6f 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -130,7 +130,7 @@
 		if (i->master == ct && del_timer(&i->timeout)) {
 			nf_ct_unlink_expect(i);
 			nf_conntrack_expect_put(i);
- 		}
+		}
 	}
 }
 EXPORT_SYMBOL_GPL(nf_ct_remove_expectations);
@@ -435,7 +435,7 @@
 	return seq_open(file, &exp_seq_ops);
 }
 
-struct file_operations exp_file_ops = {
+const struct file_operations exp_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = exp_open,
 	.read    = seq_read,
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 92a9471..3089dfc 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -126,7 +126,7 @@
 }
 
 static int try_number(const char *data, size_t dlen, u_int32_t array[],
-                      int array_size, char sep, char term)
+		      int array_size, char sep, char term)
 {
 	u_int32_t i, len;
 
@@ -413,8 +413,8 @@
 		goto out_update_nl;
 	}
 
-        /* Initialize IP/IPv6 addr to expected address (it's not mentioned
-           in EPSV responses) */
+	/* Initialize IP/IPv6 addr to expected address (it's not mentioned
+	   in EPSV responses) */
 	cmd.l3num = ct->tuplehash[dir].tuple.src.l3num;
 	memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
 	       sizeof(cmd.u3.all));
@@ -466,11 +466,11 @@
 	    memcmp(&cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
 		     sizeof(cmd.u3.all))) {
 		/* Enrico Scholz's passive FTP to partially RNAT'd ftp
-                   server: it really wants us to connect to a
-                   different IP address.  Simply don't record it for
-                   NAT. */
+		   server: it really wants us to connect to a
+		   different IP address.  Simply don't record it for
+		   NAT. */
 		if (cmd.l3num == PF_INET) {
-                	DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n",
+			DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n",
 			       NIPQUAD(cmd.u3.ip),
 			       NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
 		} else {
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 6d85689..b284db7 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -49,7 +49,7 @@
 static int callforward_filter __read_mostly = 1;
 module_param(callforward_filter, bool, 0600);
 MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
-		                     "if both endpoints are on different sides "
+				     "if both endpoints are on different sides "
 				     "(determined by routing information)");
 
 /* Hooks for NAT */
@@ -300,7 +300,7 @@
 				 IPPROTO_UDP, NULL, &rtcp_port);
 
 	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
-	   	   &ct->tuplehash[!dir].tuple.dst.u3,
+		   &ct->tuplehash[!dir].tuple.dst.u3,
 		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
 		   (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) &&
 		   ct->status & IPS_NAT_MASK) {
@@ -743,7 +743,7 @@
 			rt2 = (struct rt6_info *)ip6_route_output(NULL, &fl2);
 			if (rt2) {
 				if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,
-				 	    sizeof(rt1->rt6i_gateway)) &&
+					    sizeof(rt1->rt6i_gateway)) &&
 				    rt1->u.dst.dev == rt2->u.dst.dev)
 					ret = 1;
 				dst_release(&rt2->u.dst);
@@ -780,7 +780,7 @@
 	 * we don't need to track the second call */
 	if (callforward_filter &&
 	    callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,
-	    			  ct->tuplehash[!dir].tuple.src.l3num)) {
+				  ct->tuplehash[!dir].tuple.src.l3num)) {
 		DEBUGP("nf_ct_q931: Call Forwarding not tracked\n");
 		return 0;
 	}
@@ -840,7 +840,7 @@
 	if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
 	    (set_h225_addr) && ct->status && IPS_NAT_MASK &&
 	    get_h225_addr(ct, *data, &setup->destCallSignalAddress,
-	    		  &addr, &port) &&
+			  &addr, &port) &&
 	    memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
 		DEBUGP("nf_ct_q931: set destCallSignalAddress "
 		       NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
@@ -858,7 +858,7 @@
 	if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
 	    (set_h225_addr) && ct->status & IPS_NAT_MASK &&
 	    get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
-	    		  &addr, &port) &&
+			  &addr, &port) &&
 	    memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
 		DEBUGP("nf_ct_q931: set sourceCallSignalAddress "
 		       NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
@@ -1282,7 +1282,7 @@
 	for (i = 0; i < count; i++) {
 		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
 		    memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3,
-		    	   sizeof(addr)) == 0 && port != 0)
+			   sizeof(addr)) == 0 && port != 0)
 			break;
 	}
 
@@ -1294,7 +1294,7 @@
 		return -1;
 	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
 				 gkrouted_only ? /* only accept calls from GK? */
-				 	&ct->tuplehash[!dir].tuple.src.u3 :
+					&ct->tuplehash[!dir].tuple.src.u3 :
 					NULL,
 				 &ct->tuplehash[!dir].tuple.dst.u3,
 				 IPPROTO_TCP, NULL, &port);
@@ -1513,7 +1513,7 @@
 	set_h225_addr = rcu_dereference(set_h225_addr_hook);
 	if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
 	    get_h225_addr(ct, *data, &arq->destCallSignalAddress,
-	    		  &addr, &port) &&
+			  &addr, &port) &&
 	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
 	    port == info->sig_port[dir] &&
 	    set_h225_addr && ct->status & IPS_NAT_MASK) {
@@ -1526,7 +1526,7 @@
 
 	if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
 	    get_h225_addr(ct, *data, &arq->srcCallSignalAddress,
-	    		  &addr, &port) &&
+			  &addr, &port) &&
 	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
 	    set_h225_addr && ct->status & IPS_NAT_MASK) {
 		/* Calling ARQ */
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index ed01db6..43ccd0e 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -57,7 +57,7 @@
 
 #if 0
 #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s:" format, \
-                                       __FILE__, __FUNCTION__ , ## args)
+				       __FILE__, __FUNCTION__ , ## args)
 #else
 #define DEBUGP(format, args...)
 #endif
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index a3d31c3..cbd96f3 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -77,7 +77,7 @@
 
 
 static u_int32_t generic_get_features(const struct nf_conntrack_tuple *tuple)
-				
+
 {
 	return NF_CT_F_BASIC;
 }
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index 2a48efd..bb26a65 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -43,7 +43,7 @@
 MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
 
 static int help(struct sk_buff **pskb, unsigned int protoff,
-                struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+		struct nf_conn *ct, enum ip_conntrack_info ctinfo)
 {
 	struct nf_conntrack_expect *exp;
 	struct iphdr *iph = (*pskb)->nh.iph;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index c64f029..48f0531 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -6,10 +6,10 @@
  * (C) 2003 by Patrick Mchardy <kaber@trash.net>
  * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
  *
- * I've reworked this stuff to use attributes instead of conntrack 
+ * I've reworked this stuff to use attributes instead of conntrack
  * structures. 5.44 am. I need more tea. --pablo 05/07/11.
  *
- * Initial connection tracking via netlink development funded and 
+ * Initial connection tracking via netlink development funded and
  * generally made possible by Network Robots, Inc. (www.networkrobots.com)
  *
  * Further development of this code funded by Astaro AG (http://www.astaro.com)
@@ -53,7 +53,7 @@
 static char __initdata version[] = "0.93";
 
 static inline int
-ctnetlink_dump_tuples_proto(struct sk_buff *skb, 
+ctnetlink_dump_tuples_proto(struct sk_buff *skb,
 			    const struct nf_conntrack_tuple *tuple,
 			    struct nf_conntrack_l4proto *l4proto)
 {
@@ -64,7 +64,7 @@
 
 	if (likely(l4proto->tuple_to_nfattr))
 		ret = l4proto->tuple_to_nfattr(skb, tuple);
-	
+
 	NFA_NEST_END(skb, nest_parms);
 
 	return ret;
@@ -135,7 +135,7 @@
 		timeout = 0;
 	else
 		timeout = htonl(timeout_l / HZ);
-	
+
 	NFA_PUT(skb, CTA_TIMEOUT, sizeof(timeout), &timeout);
 	return 0;
 
@@ -154,7 +154,7 @@
 		nf_ct_l4proto_put(l4proto);
 		return 0;
 	}
-	
+
 	nest_proto = NFA_NEST(skb, CTA_PROTOINFO);
 
 	ret = l4proto->to_nfattr(skb, nest_proto, ct);
@@ -178,7 +178,7 @@
 
 	if (!help || !help->helper)
 		return 0;
-		
+
 	nest_helper = NFA_NEST(skb, CTA_HELP);
 	NFA_PUT(skb, CTA_HELP_NAME, strlen(help->helper->name), help->helper->name);
 
@@ -250,7 +250,7 @@
 ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
 {
 	__be32 use = htonl(atomic_read(&ct->ct_general.use));
-	
+
 	NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
 	return 0;
 
@@ -262,7 +262,7 @@
 
 static int
 ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
-		    int event, int nowait, 
+		    int event, int nowait,
 		    const struct nf_conn *ct)
 {
 	struct nlmsghdr *nlh;
@@ -277,7 +277,7 @@
 	nfmsg  = NLMSG_DATA(nlh);
 
 	nlh->nlmsg_flags    = (nowait && pid) ? NLM_F_MULTI : 0;
-	nfmsg->nfgen_family = 
+	nfmsg->nfgen_family =
 		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
 	nfmsg->version      = NFNETLINK_V0;
 	nfmsg->res_id	    = 0;
@@ -286,7 +286,7 @@
 	if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
 		goto nfattr_failure;
 	NFA_NEST_END(skb, nest_parms);
-	
+
 	nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
 	if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
 		goto nfattr_failure;
@@ -314,7 +314,7 @@
 
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
 static int ctnetlink_conntrack_event(struct notifier_block *this,
-                                     unsigned long events, void *ptr)
+				     unsigned long events, void *ptr)
 {
 	struct nlmsghdr *nlh;
 	struct nfgenmsg *nfmsg;
@@ -364,7 +364,7 @@
 	if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
 		goto nfattr_failure;
 	NFA_NEST_END(skb, nest_parms);
-	
+
 	nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
 	if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
 		goto nfattr_failure;
@@ -383,16 +383,16 @@
 
 		if (events & IPCT_PROTOINFO
 		    && ctnetlink_dump_protoinfo(skb, ct) < 0)
-		    	goto nfattr_failure;
+			goto nfattr_failure;
 
 		if ((events & IPCT_HELPER || nfct_help(ct))
 		    && ctnetlink_dump_helpinfo(skb, ct) < 0)
-		    	goto nfattr_failure;
+			goto nfattr_failure;
 
 #ifdef CONFIG_NF_CONNTRACK_MARK
 		if ((events & IPCT_MARK || ct->mark)
 		    && ctnetlink_dump_mark(skb, ct) < 0)
-		    	goto nfattr_failure;
+			goto nfattr_failure;
 #endif
 
 		if (events & IPCT_COUNTER_FILLING &&
@@ -450,7 +450,7 @@
 				cb->args[1] = 0;
 			}
 			if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
-		                        	cb->nlh->nlmsg_seq,
+						cb->nlh->nlmsg_seq,
 						IPCTNL_MSG_CT_NEW,
 						1, ct) < 0) {
 				nf_conntrack_get(&ct->ct_general);
@@ -500,7 +500,7 @@
 };
 
 static inline int
-ctnetlink_parse_tuple_proto(struct nfattr *attr, 
+ctnetlink_parse_tuple_proto(struct nfattr *attr,
 			    struct nf_conntrack_tuple *tuple)
 {
 	struct nfattr *tb[CTA_PROTO_MAX];
@@ -522,7 +522,7 @@
 		ret = l4proto->nfattr_to_tuple(tb, tuple);
 
 	nf_ct_l4proto_put(l4proto);
-	
+
 	return ret;
 }
 
@@ -609,7 +609,7 @@
 	int err;
 
 	memset(range, 0, sizeof(*range));
-	
+
 	nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
 
 	if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
@@ -661,7 +661,7 @@
 };
 
 static int
-ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, 
+ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
 			struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
 {
 	struct nf_conntrack_tuple_hash *h;
@@ -692,14 +692,14 @@
 		return -ENOENT;
 
 	ct = nf_ct_tuplehash_to_ctrack(h);
-	
+
 	if (cda[CTA_ID-1]) {
 		u_int32_t id = ntohl(*(__be32 *)NFA_DATA(cda[CTA_ID-1]));
 		if (ct->id != id) {
 			nf_ct_put(ct);
 			return -ENOENT;
 		}
-	}	
+	}
 	if (del_timer(&ct->timeout))
 		ct->timeout.function((unsigned long)ct);
 
@@ -709,7 +709,7 @@
 }
 
 static int
-ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, 
+ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 			struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
 {
 	struct nf_conntrack_tuple_hash *h;
@@ -765,7 +765,7 @@
 		return -ENOMEM;
 	}
 
-	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 
+	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
 				  IPCTNL_MSG_CT_NEW, 1, ct);
 	nf_ct_put(ct);
 	if (err <= 0)
@@ -793,12 +793,12 @@
 	if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
 		/* unchangeable */
 		return -EINVAL;
-	
+
 	if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
 		/* SEEN_REPLY bit can only be set */
 		return -EINVAL;
 
-	
+
 	if (d & IPS_ASSURED && !(status & IPS_ASSURED))
 		/* ASSURED bit can only be set */
 		return -EINVAL;
@@ -877,7 +877,7 @@
 			memset(&help->help, 0, sizeof(help->help));
 		}
 	}
-	
+
 	help->helper = helper;
 
 	return 0;
@@ -887,7 +887,7 @@
 ctnetlink_change_timeout(struct nf_conn *ct, struct nfattr *cda[])
 {
 	u_int32_t timeout = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
-	
+
 	if (!del_timer(&ct->timeout))
 		return -ETIME;
 
@@ -955,7 +955,7 @@
 }
 
 static int
-ctnetlink_create_conntrack(struct nfattr *cda[], 
+ctnetlink_create_conntrack(struct nfattr *cda[],
 			   struct nf_conntrack_tuple *otuple,
 			   struct nf_conntrack_tuple *rtuple)
 {
@@ -965,7 +965,7 @@
 
 	ct = nf_conntrack_alloc(otuple, rtuple);
 	if (ct == NULL || IS_ERR(ct))
-		return -ENOMEM;	
+		return -ENOMEM;
 
 	if (!cda[CTA_TIMEOUT-1])
 		goto err;
@@ -1003,13 +1003,13 @@
 
 	return 0;
 
-err:	
+err:
 	nf_conntrack_free(ct);
 	return err;
 }
 
-static int 
-ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, 
+static int
+ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
 			struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
 {
 	struct nf_conntrack_tuple otuple, rtuple;
@@ -1065,9 +1065,9 @@
 	return err;
 }
 
-/*********************************************************************** 
- * EXPECT 
- ***********************************************************************/ 
+/***********************************************************************
+ * EXPECT
+ ***********************************************************************/
 
 static inline int
 ctnetlink_exp_dump_tuple(struct sk_buff *skb,
@@ -1075,7 +1075,7 @@
 			 enum ctattr_expect type)
 {
 	struct nfattr *nest_parms = NFA_NEST(skb, type);
-	
+
 	if (ctnetlink_dump_tuples(skb, tuple) < 0)
 		goto nfattr_failure;
 
@@ -1085,7 +1085,7 @@
 
 nfattr_failure:
 	return -1;
-}			
+}
 
 static inline int
 ctnetlink_exp_dump_mask(struct sk_buff *skb,
@@ -1120,7 +1120,7 @@
 
 static inline int
 ctnetlink_exp_dump_expect(struct sk_buff *skb,
-                          const struct nf_conntrack_expect *exp)
+			  const struct nf_conntrack_expect *exp)
 {
 	struct nf_conn *master = exp->master;
 	__be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ);
@@ -1134,20 +1134,20 @@
 				 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
 				 CTA_EXPECT_MASTER) < 0)
 		goto nfattr_failure;
-	
+
 	NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout);
 	NFA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id);
 
 	return 0;
-	
+
 nfattr_failure:
 	return -1;
 }
 
 static int
 ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
-		    int event, 
-		    int nowait, 
+		    int event,
+		    int nowait,
 		    const struct nf_conntrack_expect *exp)
 {
 	struct nlmsghdr *nlh;
@@ -1250,7 +1250,7 @@
 			goto out;
 		*id = exp->id;
 	}
-out:	
+out:
 	read_unlock_bh(&nf_conntrack_lock);
 
 	return skb->len;
@@ -1262,7 +1262,7 @@
 };
 
 static int
-ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, 
+ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
 		     struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
 {
 	struct nf_conntrack_tuple tuple;
@@ -1279,7 +1279,7 @@
 		u32 rlen;
 
 		if ((*errp = netlink_dump_start(ctnl, skb, nlh,
-		    				ctnetlink_exp_dump_table,
+						ctnetlink_exp_dump_table,
 						ctnetlink_done)) != 0)
 			return -EINVAL;
 		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
@@ -1307,14 +1307,14 @@
 			nf_conntrack_expect_put(exp);
 			return -ENOENT;
 		}
-	}	
+	}
 
 	err = -ENOMEM;
 	skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
 	if (!skb2)
 		goto out;
 
-	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, 
+	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
 				      nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
 				      1, exp);
 	if (err <= 0)
@@ -1332,7 +1332,7 @@
 }
 
 static int
-ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, 
+ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
 		     struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
 {
 	struct nf_conntrack_expect *exp, *tmp;
@@ -1366,7 +1366,7 @@
 
 		/* after list removal, usage count == 1 */
 		nf_conntrack_unexpect_related(exp);
-		/* have to put what we 'get' above. 
+		/* have to put what we 'get' above.
 		 * after this line usage count == 0 */
 		nf_conntrack_expect_put(exp);
 	} else if (cda[CTA_EXPECT_HELP_NAME-1]) {
@@ -1449,7 +1449,7 @@
 		err = -ENOMEM;
 		goto out;
 	}
-	
+
 	exp->expectfn = NULL;
 	exp->flags = 0;
 	exp->master = ct;
@@ -1460,7 +1460,7 @@
 	err = nf_conntrack_expect_related(exp);
 	nf_conntrack_expect_put(exp);
 
-out:	
+out:
 	nf_ct_put(nf_ct_tuplehash_to_ctrack(h));
 	return err;
 }
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index c59df3b..115bcb5 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -520,7 +520,7 @@
 	tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph);
 	BUG_ON(!tcph);
 	nexthdr_off += tcph->doff * 4;
- 	datalen = tcplen - tcph->doff * 4;
+	datalen = tcplen - tcph->doff * 4;
 
 	pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
 	if (!pptph) {
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 1a61b72..456155f 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -66,7 +66,7 @@
 	if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL))
 		return &nf_conntrack_l4proto_generic;
 
-	return nf_ct_protos[l3proto][l4proto];
+	return rcu_dereference(nf_ct_protos[l3proto][l4proto]);
 }
 EXPORT_SYMBOL_GPL(__nf_ct_l4proto_find);
 
@@ -77,11 +77,11 @@
 {
 	struct nf_conntrack_l4proto *p;
 
-	preempt_disable();
+	rcu_read_lock();
 	p = __nf_ct_l4proto_find(l3proto, l4proto);
 	if (!try_module_get(p->me))
 		p = &nf_conntrack_l4proto_generic;
-	preempt_enable();
+	rcu_read_unlock();
 
 	return p;
 }
@@ -98,11 +98,11 @@
 {
 	struct nf_conntrack_l3proto *p;
 
-	preempt_disable();
+	rcu_read_lock();
 	p = __nf_ct_l3proto_find(l3proto);
 	if (!try_module_get(p->me))
 		p = &nf_conntrack_l3proto_generic;
-	preempt_enable();
+	rcu_read_unlock();
 
 	return p;
 }
@@ -137,10 +137,8 @@
 {
 	struct nf_conntrack_l3proto *p;
 
-	preempt_disable();
+	/* rcu_read_lock not necessary since the caller holds a reference */
 	p = __nf_ct_l3proto_find(l3proto);
-	preempt_enable();
-
 	module_put(p->me);
 }
 EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);
@@ -202,7 +200,7 @@
 		ret = -EBUSY;
 		goto out_unlock;
 	}
-	nf_ct_l3protos[proto->l3proto] = proto;
+	rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto);
 	write_unlock_bh(&nf_conntrack_lock);
 
 	ret = nf_ct_l3proto_register_sysctl(proto);
@@ -217,35 +215,21 @@
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_register);
 
-int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
+void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
 {
-	int ret = 0;
-
-	if (proto->l3proto >= AF_MAX) {
-		ret = -EBUSY;
-		goto out;
-	}
+	BUG_ON(proto->l3proto >= AF_MAX);
 
 	write_lock_bh(&nf_conntrack_lock);
-	if (nf_ct_l3protos[proto->l3proto] != proto) {
-		write_unlock_bh(&nf_conntrack_lock);
-		ret = -EBUSY;
-		goto out;
-	}
-
-	nf_ct_l3protos[proto->l3proto] = &nf_conntrack_l3proto_generic;
+	BUG_ON(nf_ct_l3protos[proto->l3proto] != proto);
+	rcu_assign_pointer(nf_ct_l3protos[proto->l3proto],
+			   &nf_conntrack_l3proto_generic);
 	write_unlock_bh(&nf_conntrack_lock);
+	synchronize_rcu();
 
 	nf_ct_l3proto_unregister_sysctl(proto);
 
-	/* Somebody could be still looking at the proto in bh. */
-	synchronize_net();
-
 	/* Remove all contrack entries for this protocol */
 	nf_ct_iterate_cleanup(kill_l3proto, proto);
-
-out:
-	return ret;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister);
 
@@ -356,7 +340,7 @@
 		goto retry;
 	}
 
-	nf_ct_protos[l4proto->l3proto][l4proto->l4proto] = l4proto;
+	rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], l4proto);
 	write_unlock_bh(&nf_conntrack_lock);
 
 	ret = nf_ct_l4proto_register_sysctl(l4proto);
@@ -371,40 +355,25 @@
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register);
 
-int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
+void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
 {
-	int ret = 0;
-
-	if (l4proto->l3proto >= PF_MAX) {
-		ret = -EBUSY;
-		goto out;
-	}
+	BUG_ON(l4proto->l3proto >= PF_MAX);
 
 	if (l4proto == &nf_conntrack_l4proto_generic) {
 		nf_ct_l4proto_unregister_sysctl(l4proto);
-		goto out;
+		return;
 	}
 
 	write_lock_bh(&nf_conntrack_lock);
-	if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
-	    != l4proto) {
-		write_unlock_bh(&nf_conntrack_lock);
-		ret = -EBUSY;
-		goto out;
-	}
-	nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
-		= &nf_conntrack_l4proto_generic;
+	BUG_ON(nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != l4proto);
+	rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
+			   &nf_conntrack_l4proto_generic);
 	write_unlock_bh(&nf_conntrack_lock);
+	synchronize_rcu();
 
 	nf_ct_l4proto_unregister_sysctl(l4proto);
 
-	/* Somebody could be still looking at the proto in bh. */
-	synchronize_net();
-
 	/* Remove all contrack entries for this protocol */
 	nf_ct_iterate_cleanup(kill_l4proto, l4proto);
-
-out:
-	return ret;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister);
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 6990253..7c06993 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -12,7 +12,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
+#include <linux/jiffies.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 76e2636..3c80558 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -1,9 +1,9 @@
 /*
  * Connection tracking protocol helper module for SCTP.
- * 
- * SCTP is defined in RFC 2960. References to various sections in this code 
+ *
+ * SCTP is defined in RFC 2960. References to various sections in this code
  * are to this RFC.
- * 
+ *
  * 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.
@@ -19,7 +19,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/module.h>
@@ -45,7 +44,7 @@
 static DEFINE_RWLOCK(sctp_lock);
 
 /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
-   closely.  They're more complex. --RR 
+   closely.  They're more complex. --RR
 
    And so for me for SCTP :D -Kiran */
 
@@ -94,32 +93,32 @@
 #define	sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
 #define	sIV SCTP_CONNTRACK_MAX
 
-/* 
+/*
 	These are the descriptions of the states:
 
-NOTE: These state names are tantalizingly similar to the states of an 
+NOTE: These state names are tantalizingly similar to the states of an
 SCTP endpoint. But the interpretation of the states is a little different,
-considering that these are the states of the connection and not of an end 
+considering that these are the states of the connection and not of an end
 point. Please note the subtleties. -Kiran
 
 NONE              - Nothing so far.
-COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also 
-                    an INIT_ACK chunk in the reply direction.
+COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also
+		    an INIT_ACK chunk in the reply direction.
 COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.
 ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.
 SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.
 SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.
 SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
-                    to that of the SHUTDOWN chunk.
-CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 
-                    the SHUTDOWN chunk. Connection is closed.
+		    to that of the SHUTDOWN chunk.
+CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
+		    the SHUTDOWN chunk. Connection is closed.
 */
 
 /* TODO
- - I have assumed that the first INIT is in the original direction. 
+ - I have assumed that the first INIT is in the original direction.
  This messes things when an INIT comes in the reply direction in CLOSED
  state.
- - Check the error type in the reply dir before transitioning from 
+ - Check the error type in the reply dir before transitioning from
 cookie echoed to closed.
  - Sec 5.2.4 of RFC 2960
  - Multi Homing support.
@@ -237,7 +236,7 @@
 	for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
 		DEBUGP("Chunk Num: %d  Type: %d\n", count, sch->type);
 
-		if (sch->type == SCTP_CID_INIT 
+		if (sch->type == SCTP_CID_INIT
 			|| sch->type == SCTP_CID_INIT_ACK
 			|| sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
 			flag = 1;
@@ -277,42 +276,42 @@
 	DEBUGP("Chunk type: %d\n", chunk_type);
 
 	switch (chunk_type) {
-		case SCTP_CID_INIT: 
+		case SCTP_CID_INIT:
 			DEBUGP("SCTP_CID_INIT\n");
 			i = 0; break;
-		case SCTP_CID_INIT_ACK: 
+		case SCTP_CID_INIT_ACK:
 			DEBUGP("SCTP_CID_INIT_ACK\n");
 			i = 1; break;
-		case SCTP_CID_ABORT: 
+		case SCTP_CID_ABORT:
 			DEBUGP("SCTP_CID_ABORT\n");
 			i = 2; break;
-		case SCTP_CID_SHUTDOWN: 
+		case SCTP_CID_SHUTDOWN:
 			DEBUGP("SCTP_CID_SHUTDOWN\n");
 			i = 3; break;
-		case SCTP_CID_SHUTDOWN_ACK: 
+		case SCTP_CID_SHUTDOWN_ACK:
 			DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
 			i = 4; break;
-		case SCTP_CID_ERROR: 
+		case SCTP_CID_ERROR:
 			DEBUGP("SCTP_CID_ERROR\n");
 			i = 5; break;
-		case SCTP_CID_COOKIE_ECHO: 
+		case SCTP_CID_COOKIE_ECHO:
 			DEBUGP("SCTP_CID_COOKIE_ECHO\n");
 			i = 6; break;
-		case SCTP_CID_COOKIE_ACK: 
+		case SCTP_CID_COOKIE_ACK:
 			DEBUGP("SCTP_CID_COOKIE_ACK\n");
 			i = 7; break;
-		case SCTP_CID_SHUTDOWN_COMPLETE: 
+		case SCTP_CID_SHUTDOWN_COMPLETE:
 			DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
 			i = 8; break;
 		default:
 			/* Other chunks like DATA, SACK, HEARTBEAT and
 			its ACK do not cause a change in state */
-			DEBUGP("Unknown chunk type, Will stay in %s\n", 
+			DEBUGP("Unknown chunk type, Will stay in %s\n",
 						sctp_conntrack_names[cur_state]);
 			return cur_state;
 	}
 
-	DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 
+	DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n",
 			dir, sctp_conntrack_names[cur_state], chunk_type,
 			sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
 
@@ -377,7 +376,7 @@
 			/* Sec 8.5.1 (C) */
 			if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
 				&& !(sh->vtag == conntrack->proto.sctp.vtag
-							[1 - CTINFO2DIR(ctinfo)] 
+							[1 - CTINFO2DIR(ctinfo)]
 					&& (sch->flags & 1))) {
 				write_unlock_bh(&sctp_lock);
 				return -1;
@@ -402,17 +401,17 @@
 		}
 
 		/* If it is an INIT or an INIT ACK note down the vtag */
-		if (sch->type == SCTP_CID_INIT 
+		if (sch->type == SCTP_CID_INIT
 			|| sch->type == SCTP_CID_INIT_ACK) {
 			sctp_inithdr_t _inithdr, *ih;
 
 			ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
-			                        sizeof(_inithdr), &_inithdr);
+						sizeof(_inithdr), &_inithdr);
 			if (ih == NULL) {
 					write_unlock_bh(&sctp_lock);
 					return -1;
 			}
-			DEBUGP("Setting vtag %x for dir %d\n", 
+			DEBUGP("Setting vtag %x for dir %d\n",
 					ih->init_tag, !CTINFO2DIR(ctinfo));
 			conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag;
 		}
@@ -466,7 +465,7 @@
 	newconntrack = SCTP_CONNTRACK_MAX;
 	for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
 		/* Don't need lock here: this conntrack not in circulation yet */
-		newconntrack = new_state(IP_CT_DIR_ORIGINAL, 
+		newconntrack = new_state(IP_CT_DIR_ORIGINAL,
 					 SCTP_CONNTRACK_NONE, sch->type);
 
 		/* Invalid: delete conntrack */
@@ -481,14 +480,14 @@
 				sctp_inithdr_t _inithdr, *ih;
 
 				ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
-				                        sizeof(_inithdr), &_inithdr);
+							sizeof(_inithdr), &_inithdr);
 				if (ih == NULL)
 					return 0;
 
-				DEBUGP("Setting vtag %x for new conn\n", 
+				DEBUGP("Setting vtag %x for new conn\n",
 					ih->init_tag);
 
-				conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = 
+				conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
 								ih->init_tag;
 			} else {
 				/* Sec 8.5.1 (A) */
@@ -498,7 +497,7 @@
 		/* If it is a shutdown ack OOTB packet, we expect a return
 		   shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
 		else {
-			DEBUGP("Setting vtag %x for new conn OOTB\n", 
+			DEBUGP("Setting vtag %x for new conn OOTB\n",
 				sh->vtag);
 			conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
 		}
@@ -698,7 +697,7 @@
  cleanup_sctp4:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
  out:
-	DEBUGP("SCTP conntrack module loading %s\n", 
+	DEBUGP("SCTP conntrack module loading %s\n",
 					ret ? "failed": "succeeded");
 	return ret;
 }
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 626b001..069b85c 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -25,7 +25,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
 #include <linux/module.h>
@@ -55,22 +54,19 @@
 /* Protects conntrack->proto.tcp */
 static DEFINE_RWLOCK(tcp_lock);
 
-/* "Be conservative in what you do, 
-    be liberal in what you accept from others." 
+/* "Be conservative in what you do,
+    be liberal in what you accept from others."
     If it's non-zero, we mark only out of window RST segments as INVALID. */
-int nf_ct_tcp_be_liberal __read_mostly = 0;
+static int nf_ct_tcp_be_liberal __read_mostly = 0;
 
-/* When connection is picked up from the middle, how many packets are required
-   to pass in each direction when we assume we are in sync - if any side uses
-   window scaling, we lost the game. 
-   If it is set to zero, we disable picking up already established 
+/* If it is set to zero, we disable picking up already established
    connections. */
-int nf_ct_tcp_loose __read_mostly = 3;
+static int nf_ct_tcp_loose __read_mostly = 1;
 
-/* Max number of the retransmitted packets without receiving an (acceptable) 
-   ACK from the destination. If this number is reached, a shorter timer 
+/* Max number of the retransmitted packets without receiving an (acceptable)
+   ACK from the destination. If this number is reached, a shorter timer
    will be started. */
-int nf_ct_tcp_max_retrans __read_mostly = 3;
+static int nf_ct_tcp_max_retrans __read_mostly = 3;
 
   /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
      closely.  They're more complex. --RR */
@@ -87,7 +83,7 @@
 	"CLOSE",
 	"LISTEN"
 };
-  
+
 #define SECS * HZ
 #define MINS * 60 SECS
 #define HOURS * 60 MINS
@@ -103,10 +99,10 @@
 static unsigned int nf_ct_tcp_timeout_close __read_mostly =        10 SECS;
 
 /* RFC1122 says the R2 limit should be at least 100 seconds.
-   Linux uses 15 packets as limit, which corresponds 
+   Linux uses 15 packets as limit, which corresponds
    to ~13-30min depending on RTO. */
 static unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly =   5 MINS;
- 
+
 static unsigned int * tcp_timeouts[] = {
     NULL,                              /* TCP_CONNTRACK_NONE */
     &nf_ct_tcp_timeout_syn_sent,       /* TCP_CONNTRACK_SYN_SENT, */
@@ -119,7 +115,7 @@
     &nf_ct_tcp_timeout_close,          /* TCP_CONNTRACK_CLOSE, */
     NULL,                              /* TCP_CONNTRACK_LISTEN */
  };
- 
+
 #define sNO TCP_CONNTRACK_NONE
 #define sSS TCP_CONNTRACK_SYN_SENT
 #define sSR TCP_CONNTRACK_SYN_RECV
@@ -142,13 +138,13 @@
 	TCP_RST_SET,
 	TCP_NONE_SET,
 };
-  
+
 /*
  * The TCP state transition table needs a few words...
  *
  * We are the man in the middle. All the packets go through us
  * but might get lost in transit to the destination.
- * It is assumed that the destinations can't receive segments 
+ * It is assumed that the destinations can't receive segments
  * we haven't seen.
  *
  * The checked segment is in window, but our windows are *not*
@@ -158,11 +154,11 @@
  * The meaning of the states are:
  *
  * NONE:	initial state
- * SYN_SENT:	SYN-only packet seen 
+ * SYN_SENT:	SYN-only packet seen
  * SYN_RECV:	SYN-ACK packet seen
  * ESTABLISHED:	ACK packet seen
  * FIN_WAIT:	FIN packet seen
- * CLOSE_WAIT:	ACK seen (after FIN) 
+ * CLOSE_WAIT:	ACK seen (after FIN)
  * LAST_ACK:	FIN seen (after FIN)
  * TIME_WAIT:	last ACK seen
  * CLOSE:	closed connection
@@ -170,8 +166,8 @@
  * LISTEN state is not used.
  *
  * Packets marked as IGNORED (sIG):
- *	if they may be either invalid or valid 
- *	and the receiver may send back a connection 
+ *	if they may be either invalid or valid
+ *	and the receiver may send back a connection
  *	closing RST or a SYN/ACK.
  *
  * Packets marked as INVALID (sIV):
@@ -188,7 +184,7 @@
  *	sSS -> sSS	Retransmitted SYN
  *	sSR -> sIG	Late retransmitted SYN?
  *	sES -> sIG	Error: SYNs in window outside the SYN_SENT state
- *			are errors. Receiver will reply with RST 
+ *			are errors. Receiver will reply with RST
  *			and close the connection.
  *			Or we are not in sync and hold a dead connection.
  *	sFW -> sIG
@@ -201,10 +197,10 @@
 /*synack*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },
 /*
  * A SYN/ACK from the client is always invalid:
- *	- either it tries to set up a simultaneous open, which is 
+ *	- either it tries to set up a simultaneous open, which is
  *	  not supported;
  *	- or the firewall has just been inserted between the two hosts
- *	  during the session set-up. The SYN will be retransmitted 
+ *	  during the session set-up. The SYN will be retransmitted
  *	  by the true client (or it'll time out).
  */
 /* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
@@ -216,7 +212,7 @@
  *	sSR -> sFW	Close started.
  *	sES -> sFW
  *	sFW -> sLA	FIN seen in both directions, waiting for
- *			the last ACK. 
+ *			the last ACK.
  *			Migth be a retransmitted FIN as well...
  *	sCW -> sLA
  *	sLA -> sLA	Retransmitted FIN. Remain in the same state.
@@ -294,7 +290,7 @@
 /* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
 /*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },
 /*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
-  	}
+	}
 };
 
 static int tcp_pkt_to_tuple(const struct sk_buff *skb,
@@ -355,21 +351,21 @@
 
 /* TCP connection tracking based on 'Real Stateful TCP Packet Filtering
    in IP Filter' by Guido van Rooij.
-   
+
    http://www.nluug.nl/events/sane2000/papers.html
    http://www.iae.nl/users/guido/papers/tcp_filtering.ps.gz
-   
+
    The boundaries and the conditions are changed according to RFC793:
    the packet must intersect the window (i.e. segments may be
    after the right or before the left edge) and thus receivers may ACK
    segments after the right edge of the window.
 
-   	td_maxend = max(sack + max(win,1)) seen in reply packets
+	td_maxend = max(sack + max(win,1)) seen in reply packets
 	td_maxwin = max(max(win, 1)) + (sack - ack) seen in sent packets
 	td_maxwin += seq + len - sender.td_maxend
 			if seq + len > sender.td_maxend
 	td_end    = max(seq + len) seen in sent packets
-   
+
    I.   Upper bound for valid data:	seq <= sender.td_maxend
    II.  Lower bound for valid data:	seq + len >= sender.td_end - receiver.td_maxwin
    III.	Upper bound for valid ack:      sack <= receiver.td_end
@@ -377,8 +373,8 @@
 
    where sack is the highest right edge of sack block found in the packet.
 
-   The upper bound limit for a valid ack is not ignored - 
-   we doesn't have to deal with fragments. 
+   The upper bound limit for a valid ack is not ignored -
+   we doesn't have to deal with fragments.
 */
 
 static inline __u32 segment_seq_plus_len(__u32 seq,
@@ -391,19 +387,19 @@
 	return (seq + len - dataoff - tcph->doff*4
 		+ (tcph->syn ? 1 : 0) + (tcph->fin ? 1 : 0));
 }
-  
+
 /* Fixme: what about big packets? */
 #define MAXACKWINCONST			66000
 #define MAXACKWINDOW(sender)						\
 	((sender)->td_maxwin > MAXACKWINCONST ? (sender)->td_maxwin	\
 					      : MAXACKWINCONST)
-  
+
 /*
  * Simplified tcp_parse_options routine from tcp_input.c
  */
 static void tcp_options(const struct sk_buff *skb,
 			unsigned int dataoff,
-			struct tcphdr *tcph, 
+			struct tcphdr *tcph,
 			struct ip_ct_tcp_state *state)
 {
 	unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
@@ -417,7 +413,7 @@
 				 length, buff);
 	BUG_ON(ptr == NULL);
 
-	state->td_scale = 
+	state->td_scale =
 	state->flags = 0;
 
 	while (length > 0) {
@@ -437,7 +433,7 @@
 			if (opsize > length)
 				break;	/* don't parse partial options */
 
-			if (opcode == TCPOPT_SACK_PERM 
+			if (opcode == TCPOPT_SACK_PERM
 			    && opsize == TCPOLEN_SACK_PERM)
 				state->flags |= IP_CT_TCP_FLAG_SACK_PERM;
 			else if (opcode == TCPOPT_WINDOW
@@ -460,7 +456,7 @@
 static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
 		     struct tcphdr *tcph, __u32 *sack)
 {
-        unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
+	unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
 	unsigned char *ptr;
 	int length = (tcph->doff*4) - sizeof(struct tcphdr);
 	__u32 tmp;
@@ -475,10 +471,10 @@
 	/* Fast path for timestamp-only option */
 	if (length == TCPOLEN_TSTAMP_ALIGNED*4
 	    && *(__be32 *)ptr ==
-	        __constant_htonl((TCPOPT_NOP << 24)
-	        		 | (TCPOPT_NOP << 16)
-	        		 | (TCPOPT_TIMESTAMP << 8)
-	        		 | TCPOLEN_TIMESTAMP))
+		__constant_htonl((TCPOPT_NOP << 24)
+				 | (TCPOPT_NOP << 16)
+				 | (TCPOPT_TIMESTAMP << 8)
+				 | TCPOLEN_TIMESTAMP))
 		return;
 
 	while (length > 0) {
@@ -498,15 +494,15 @@
 			if (opsize > length)
 				break;	/* don't parse partial options */
 
-			if (opcode == TCPOPT_SACK 
-			    && opsize >= (TCPOLEN_SACK_BASE 
-			    		  + TCPOLEN_SACK_PERBLOCK)
-			    && !((opsize - TCPOLEN_SACK_BASE) 
-			    	 % TCPOLEN_SACK_PERBLOCK)) {
-			    	for (i = 0;
-			    	     i < (opsize - TCPOLEN_SACK_BASE);
-			    	     i += TCPOLEN_SACK_PERBLOCK) {
-				     	tmp = ntohl(*((__be32 *)(ptr+i)+1));
+			if (opcode == TCPOPT_SACK
+			    && opsize >= (TCPOLEN_SACK_BASE
+					  + TCPOLEN_SACK_PERBLOCK)
+			    && !((opsize - TCPOLEN_SACK_BASE)
+				 % TCPOLEN_SACK_PERBLOCK)) {
+				for (i = 0;
+				     i < (opsize - TCPOLEN_SACK_BASE);
+				     i += TCPOLEN_SACK_PERBLOCK) {
+					tmp = ntohl(*((__be32 *)(ptr+i)+1));
 
 					if (after(tmp, *sack))
 						*sack = tmp;
@@ -519,12 +515,12 @@
 	}
 }
 
-static int tcp_in_window(struct ip_ct_tcp *state, 
-                         enum ip_conntrack_dir dir,
-                         unsigned int index,
-                         const struct sk_buff *skb,
+static int tcp_in_window(struct ip_ct_tcp *state,
+			 enum ip_conntrack_dir dir,
+			 unsigned int index,
+			 const struct sk_buff *skb,
 			 unsigned int dataoff,
-                         struct tcphdr *tcph,
+			 struct tcphdr *tcph,
 			 int pf)
 {
 	struct ip_ct_tcp_state *sender = &state->seen[dir];
@@ -546,14 +542,14 @@
 	DEBUGP("tcp_in_window: START\n");
 	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
 	       "seq=%u ack=%u sack=%u win=%u end=%u\n",
-		NIPQUAD(iph->saddr), ntohs(tcph->source), 
+		NIPQUAD(iph->saddr), ntohs(tcph->source),
 		NIPQUAD(iph->daddr), ntohs(tcph->dest),
 		seq, ack, sack, win, end);
 	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
 	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
 		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale, 
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin, 
+		sender->td_scale,
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
 		receiver->td_scale);
 
 	if (sender->td_end == 0) {
@@ -564,26 +560,26 @@
 			/*
 			 * Outgoing SYN-ACK in reply to a SYN.
 			 */
-			sender->td_end = 
+			sender->td_end =
 			sender->td_maxend = end;
 			sender->td_maxwin = (win == 0 ? 1 : win);
 
 			tcp_options(skb, dataoff, tcph, sender);
-			/* 
+			/*
 			 * RFC 1323:
 			 * Both sides must send the Window Scale option
 			 * to enable window scaling in either direction.
 			 */
 			if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE
 			      && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE))
-				sender->td_scale = 
+				sender->td_scale =
 				receiver->td_scale = 0;
 		} else {
 			/*
 			 * We are in the middle of a connection,
 			 * its history is lost for us.
 			 * Let's try to use the data from the packet.
-		 	 */
+			 */
 			sender->td_end = end;
 			sender->td_maxwin = (win == 0 ? 1 : win);
 			sender->td_maxend = end + sender->td_maxwin;
@@ -595,7 +591,7 @@
 		   && after(end, sender->td_end)) {
 		/*
 		 * RFC 793: "if a TCP is reinitialized ... then it need
-		 * not wait at all; it must only be sure to use sequence 
+		 * not wait at all; it must only be sure to use sequence
 		 * numbers larger than those recently used."
 		 */
 		sender->td_end =
@@ -610,8 +606,8 @@
 		 * If there is no ACK, just pretend it was set and OK.
 		 */
 		ack = sack = receiver->td_end;
-	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) == 
-		    (TCP_FLAG_ACK|TCP_FLAG_RST)) 
+	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) ==
+		    (TCP_FLAG_ACK|TCP_FLAG_RST))
 		   && (ack == 0)) {
 		/*
 		 * Broken TCP stacks, that set ACK in RST packets as well
@@ -640,22 +636,21 @@
 	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
 	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
 		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale, 
+		sender->td_scale,
 		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
 		receiver->td_scale);
 
 	DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
 		before(seq, sender->td_maxend + 1),
 		after(end, sender->td_end - receiver->td_maxwin - 1),
-	    	before(sack, receiver->td_end + 1),
-	    	after(ack, receiver->td_end - MAXACKWINDOW(sender)));
+		before(sack, receiver->td_end + 1),
+		after(ack, receiver->td_end - MAXACKWINDOW(sender)));
 
-	if (sender->loose || receiver->loose ||
-	    (before(seq, sender->td_maxend + 1) &&
-	     after(end, sender->td_end - receiver->td_maxwin - 1) &&
-	     before(sack, receiver->td_end + 1) &&
-	     after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
-	    	/*
+	if (before(seq, sender->td_maxend + 1) &&
+	    after(end, sender->td_end - receiver->td_maxwin - 1) &&
+	    before(sack, receiver->td_end + 1) &&
+	    after(ack, receiver->td_end - MAXACKWINDOW(sender))) {
+		/*
 		 * Take into account window scaling (RFC 1323).
 		 */
 		if (!tcph->syn)
@@ -680,7 +675,7 @@
 				receiver->td_maxend++;
 		}
 
-		/* 
+		/*
 		 * Check retransmissions.
 		 */
 		if (index == TCP_ACK_SET) {
@@ -699,15 +694,13 @@
 				state->retrans = 0;
 			}
 		}
-		/*
-		 * Close the window of disabled window tracking :-)
-		 */
-		if (sender->loose)
-			sender->loose--;
-
 		res = 1;
 	} else {
-		if (LOG_INVALID(IPPROTO_TCP))
+		res = 0;
+		if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
+		    nf_ct_tcp_be_liberal)
+			res = 1;
+		if (!res && LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
 			"nf_ct_tcp: %s ",
 			before(seq, sender->td_maxend + 1) ?
@@ -718,13 +711,11 @@
 			: "ACK is over the upper bound (ACKed data not seen yet)"
 			: "SEQ is under the lower bound (already ACKed data retransmitted)"
 			: "SEQ is over the upper bound (over the window of the receiver)");
+	}
 
-		res = nf_ct_tcp_be_liberal;
-  	}
-  
 	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
 	       "receiver end=%u maxend=%u maxwin=%u\n",
-		res, sender->td_end, sender->td_maxend, sender->td_maxwin, 
+		res, sender->td_end, sender->td_maxend, sender->td_maxwin,
 		receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
 
 	return res;
@@ -735,7 +726,7 @@
 /* Caller must linearize skb at tcp header. */
 void nf_conntrack_tcp_update(struct sk_buff *skb,
 			     unsigned int dataoff,
-			     struct nf_conn *conntrack, 
+			     struct nf_conn *conntrack,
 			     int dir)
 {
 	struct tcphdr *tcph = (void *)skb->data + dataoff;
@@ -758,7 +749,7 @@
 	DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
 	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
 		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale, 
+		sender->td_scale,
 		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
 		receiver->td_scale);
 }
@@ -812,8 +803,8 @@
 			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
 				"nf_ct_tcp: short packet ");
 		return -NF_ACCEPT;
-  	}
-  
+	}
+
 	/* Not whole TCP header or malformed packet */
 	if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
 		if (LOG_INVALID(IPPROTO_TCP))
@@ -821,7 +812,7 @@
 				"nf_ct_tcp: truncated/malformed packet ");
 		return -NF_ACCEPT;
 	}
-  
+
 	/* Checksum invalid? Ignore.
 	 * We skip checking packets on the outgoing path
 	 * because the checksum is assumed to be correct.
@@ -878,28 +869,28 @@
 		 *
 		 * a) SYN in ORIGINAL
 		 * b) SYN/ACK in REPLY
-		 * c) ACK in reply direction after initial SYN in original. 
+		 * c) ACK in reply direction after initial SYN in original.
 		 */
 		if (index == TCP_SYNACK_SET
 		    && conntrack->proto.tcp.last_index == TCP_SYN_SET
 		    && conntrack->proto.tcp.last_dir != dir
 		    && ntohl(th->ack_seq) ==
-		    	     conntrack->proto.tcp.last_end) {
-			/* This SYN/ACK acknowledges a SYN that we earlier 
+			     conntrack->proto.tcp.last_end) {
+			/* This SYN/ACK acknowledges a SYN that we earlier
 			 * ignored as invalid. This means that the client and
 			 * the server are both in sync, while the firewall is
 			 * not. We kill this session and block the SYN/ACK so
-			 * that the client cannot but retransmit its SYN and 
+			 * that the client cannot but retransmit its SYN and
 			 * thus initiate a clean new session.
 			 */
-		    	write_unlock_bh(&tcp_lock);
+			write_unlock_bh(&tcp_lock);
 			if (LOG_INVALID(IPPROTO_TCP))
 				nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
 					  "nf_ct_tcp: killing out of sync session ");
-		    	if (del_timer(&conntrack->timeout))
-		    		conntrack->timeout.function((unsigned long)
-		    					    conntrack);
-		    	return -NF_DROP;
+			if (del_timer(&conntrack->timeout))
+				conntrack->timeout.function((unsigned long)
+							    conntrack);
+			return -NF_DROP;
 		}
 		conntrack->proto.tcp.last_index = index;
 		conntrack->proto.tcp.last_dir = dir;
@@ -929,13 +920,13 @@
 			IP_CT_TCP_FLAG_CLOSE_INIT)
 		    || after(ntohl(th->seq),
 			     conntrack->proto.tcp.seen[dir].td_end)) {
-		    	/* Attempt to reopen a closed connection.
-		    	* Delete this connection and look up again. */
-		    	write_unlock_bh(&tcp_lock);
-		    	if (del_timer(&conntrack->timeout))
-		    		conntrack->timeout.function((unsigned long)
-		    					    conntrack);
-		    	return -NF_REPEAT;
+			/* Attempt to reopen a closed connection.
+			* Delete this connection and look up again. */
+			write_unlock_bh(&tcp_lock);
+			if (del_timer(&conntrack->timeout))
+				conntrack->timeout.function((unsigned long)
+							    conntrack);
+			return -NF_REPEAT;
 		} else {
 			write_unlock_bh(&tcp_lock);
 			if (LOG_INVALID(IPPROTO_TCP))
@@ -946,9 +937,9 @@
 	case TCP_CONNTRACK_CLOSE:
 		if (index == TCP_RST_SET
 		    && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
-		         && conntrack->proto.tcp.last_index == TCP_SYN_SET)
-		        || (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
-		            && conntrack->proto.tcp.last_index == TCP_ACK_SET))
+			 && conntrack->proto.tcp.last_index == TCP_SYN_SET)
+			|| (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
+			    && conntrack->proto.tcp.last_index == TCP_ACK_SET))
 		    && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
 			/* RST sent to invalid SYN or ACK we had let through
 			 * at a) and c) above:
@@ -1013,8 +1004,8 @@
 		   && (old_state == TCP_CONNTRACK_SYN_RECV
 		       || old_state == TCP_CONNTRACK_ESTABLISHED)
 		   && new_state == TCP_CONNTRACK_ESTABLISHED) {
-		/* Set ASSURED if we see see valid ack in ESTABLISHED 
-		   after SYN_RECV or a valid answer for a picked up 
+		/* Set ASSURED if we see see valid ack in ESTABLISHED
+		   after SYN_RECV or a valid answer for a picked up
 		   connection. */
 		set_bit(IPS_ASSURED_BIT, &conntrack->status);
 		nf_conntrack_event_cache(IPCT_STATUS, skb);
@@ -1023,7 +1014,7 @@
 
 	return NF_ACCEPT;
 }
- 
+
 /* Called when a new connection for this protocol found. */
 static int tcp_new(struct nf_conn *conntrack,
 		   const struct sk_buff *skb,
@@ -1063,8 +1054,6 @@
 
 		tcp_options(skb, dataoff, th, &conntrack->proto.tcp.seen[0]);
 		conntrack->proto.tcp.seen[1].flags = 0;
-		conntrack->proto.tcp.seen[0].loose = 
-		conntrack->proto.tcp.seen[1].loose = 0;
 	} else if (nf_ct_tcp_loose == 0) {
 		/* Don't try to pick up connections. */
 		return 0;
@@ -1081,30 +1070,30 @@
 		if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
 			conntrack->proto.tcp.seen[0].td_maxwin = 1;
 		conntrack->proto.tcp.seen[0].td_maxend =
-			conntrack->proto.tcp.seen[0].td_end + 
+			conntrack->proto.tcp.seen[0].td_end +
 			conntrack->proto.tcp.seen[0].td_maxwin;
 		conntrack->proto.tcp.seen[0].td_scale = 0;
 
-		/* We assume SACK. Should we assume window scaling too? */
+		/* We assume SACK and liberal window checking to handle
+		 * window scaling */
 		conntrack->proto.tcp.seen[0].flags =
-		conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
-		conntrack->proto.tcp.seen[0].loose = 
-		conntrack->proto.tcp.seen[1].loose = nf_ct_tcp_loose;
+		conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM |
+						     IP_CT_TCP_FLAG_BE_LIBERAL;
 	}
-    
+
 	conntrack->proto.tcp.seen[1].td_end = 0;
 	conntrack->proto.tcp.seen[1].td_maxend = 0;
 	conntrack->proto.tcp.seen[1].td_maxwin = 1;
-	conntrack->proto.tcp.seen[1].td_scale = 0;      
+	conntrack->proto.tcp.seen[1].td_scale = 0;
 
 	/* tcp_packet will set them */
 	conntrack->proto.tcp.state = TCP_CONNTRACK_NONE;
 	conntrack->proto.tcp.last_index = TCP_NONE_SET;
-	 
+
 	DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
 	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
 		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale, 
+		sender->td_scale,
 		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
 		receiver->td_scale);
 	return 1;
@@ -1120,7 +1109,7 @@
 			 const struct nf_conn *ct)
 {
 	struct nfattr *nest_parms;
-	
+
 	read_lock_bh(&tcp_lock);
 	nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
 	NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
@@ -1150,7 +1139,7 @@
 	if (!attr)
 		return 0;
 
-        nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);
+	nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);
 
 	if (nfattr_bad_size(tb, CTA_PROTOINFO_TCP_MAX, cta_min_tcp))
 		return -EINVAL;
@@ -1159,7 +1148,7 @@
 		return -EINVAL;
 
 	write_lock_bh(&tcp_lock);
-	ct->proto.tcp.state = 
+	ct->proto.tcp.state =
 		*(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
 	write_unlock_bh(&tcp_lock);
 
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index e49cd25..d0a1cee 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/module.h>
 #include <linux/netfilter.h>
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
new file mode 100644
index 0000000..eb2d1dc
--- /dev/null
+++ b/net/netfilter/nf_conntrack_sane.c
@@ -0,0 +1,242 @@
+/* SANE connection tracking helper
+ * (SANE = Scanner Access Now Easy)
+ * For documentation about the SANE network protocol see
+ * http://www.sane-project.org/html/doc015.html
+ */
+
+/* Copyright (C) 2007 Red Hat, Inc.
+ * Author: Michal Schmidt <mschmidt@redhat.com>
+ * Based on the FTP conntrack helper (net/netfilter/nf_conntrack_ftp.c):
+ *  (C) 1999-2001 Paul `Rusty' Russell
+ *  (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ *  (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *  (C) 2003 Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ *
+ * 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/moduleparam.h>
+#include <linux/netfilter.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_sane.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michal Schmidt <mschmidt@redhat.com>");
+MODULE_DESCRIPTION("SANE connection tracking helper");
+
+static char *sane_buffer;
+
+static DEFINE_SPINLOCK(nf_sane_lock);
+
+#define MAX_PORTS 8
+static u_int16_t ports[MAX_PORTS];
+static unsigned int ports_c;
+module_param_array(ports, ushort, &ports_c, 0400);
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+struct sane_request {
+	__be32 RPC_code;
+#define SANE_NET_START      7   /* RPC code */
+
+	__be32 handle;
+};
+
+struct sane_reply_net_start {
+	__be32 status;
+#define SANE_STATUS_SUCCESS 0
+
+	__be16 zero;
+	__be16 port;
+	/* other fields aren't interesting for conntrack */
+};
+
+static int help(struct sk_buff **pskb,
+		unsigned int protoff,
+		struct nf_conn *ct,
+		enum ip_conntrack_info ctinfo)
+{
+	unsigned int dataoff, datalen;
+	struct tcphdr _tcph, *th;
+	char *sb_ptr;
+	int ret = NF_ACCEPT;
+	int dir = CTINFO2DIR(ctinfo);
+	struct nf_ct_sane_master *ct_sane_info;
+	struct nf_conntrack_expect *exp;
+	struct nf_conntrack_tuple *tuple;
+	struct sane_request *req;
+	struct sane_reply_net_start *reply;
+	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+
+	ct_sane_info = &nfct_help(ct)->help.ct_sane_info;
+	/* Until there's been traffic both ways, don't look in packets. */
+	if (ctinfo != IP_CT_ESTABLISHED &&
+	    ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY)
+		return NF_ACCEPT;
+
+	/* Not a full tcp header? */
+	th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
+	if (th == NULL)
+		return NF_ACCEPT;
+
+	/* No data? */
+	dataoff = protoff + th->doff * 4;
+	if (dataoff >= (*pskb)->len)
+		return NF_ACCEPT;
+
+	datalen = (*pskb)->len - dataoff;
+
+	spin_lock_bh(&nf_sane_lock);
+	sb_ptr = skb_header_pointer(*pskb, dataoff, datalen, sane_buffer);
+	BUG_ON(sb_ptr == NULL);
+
+	if (dir == IP_CT_DIR_ORIGINAL) {
+		if (datalen != sizeof(struct sane_request))
+			goto out;
+
+		req = (struct sane_request *)sb_ptr;
+		if (req->RPC_code != htonl(SANE_NET_START)) {
+			/* Not an interesting command */
+			ct_sane_info->state = SANE_STATE_NORMAL;
+			goto out;
+		}
+
+		/* We're interested in the next reply */
+		ct_sane_info->state = SANE_STATE_START_REQUESTED;
+		goto out;
+	}
+
+	/* Is it a reply to an uninteresting command? */
+	if (ct_sane_info->state != SANE_STATE_START_REQUESTED)
+		goto out;
+
+	/* It's a reply to SANE_NET_START. */
+	ct_sane_info->state = SANE_STATE_NORMAL;
+
+	if (datalen < sizeof(struct sane_reply_net_start)) {
+		DEBUGP("nf_ct_sane: NET_START reply too short\n");
+		goto out;
+	}
+
+	reply = (struct sane_reply_net_start *)sb_ptr;
+	if (reply->status != htonl(SANE_STATUS_SUCCESS)) {
+		/* saned refused the command */
+		DEBUGP("nf_ct_sane: unsuccessful SANE_STATUS = %u\n",
+			ntohl(reply->status));
+		goto out;
+	}
+
+	/* Invalid saned reply? Ignore it. */
+	if (reply->zero != 0)
+		goto out;
+
+	exp = nf_conntrack_expect_alloc(ct);
+	if (exp == NULL) {
+		ret = NF_DROP;
+		goto out;
+	}
+
+	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+	nf_conntrack_expect_init(exp, family,
+				 &tuple->src.u3, &tuple->dst.u3,
+				 IPPROTO_TCP,
+				 NULL, &reply->port);
+
+	DEBUGP("nf_ct_sane: expect: ");
+	NF_CT_DUMP_TUPLE(&exp->tuple);
+	NF_CT_DUMP_TUPLE(&exp->mask);
+
+	/* Can't expect this?  Best to drop packet now. */
+	if (nf_conntrack_expect_related(exp) != 0)
+		ret = NF_DROP;
+
+	nf_conntrack_expect_put(exp);
+
+out:
+	spin_unlock_bh(&nf_sane_lock);
+	return ret;
+}
+
+static struct nf_conntrack_helper sane[MAX_PORTS][2];
+static char sane_names[MAX_PORTS][2][sizeof("sane-65535")];
+
+/* don't make this __exit, since it's called from __init ! */
+static void nf_conntrack_sane_fini(void)
+{
+	int i, j;
+
+	for (i = 0; i < ports_c; i++) {
+		for (j = 0; j < 2; j++) {
+			DEBUGP("nf_ct_sane: unregistering helper for pf: %d "
+			       "port: %d\n",
+				sane[i][j].tuple.src.l3num, ports[i]);
+			nf_conntrack_helper_unregister(&sane[i][j]);
+		}
+	}
+
+	kfree(sane_buffer);
+}
+
+static int __init nf_conntrack_sane_init(void)
+{
+	int i, j = -1, ret = 0;
+	char *tmpname;
+
+	sane_buffer = kmalloc(65536, GFP_KERNEL);
+	if (!sane_buffer)
+		return -ENOMEM;
+
+	if (ports_c == 0)
+		ports[ports_c++] = SANE_PORT;
+
+	/* FIXME should be configurable whether IPv4 and IPv6 connections
+		 are tracked or not - YK */
+	for (i = 0; i < ports_c; i++) {
+		sane[i][0].tuple.src.l3num = PF_INET;
+		sane[i][1].tuple.src.l3num = PF_INET6;
+		for (j = 0; j < 2; j++) {
+			sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
+			sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
+			sane[i][j].mask.src.u.tcp.port = 0xFFFF;
+			sane[i][j].mask.dst.protonum = 0xFF;
+			sane[i][j].max_expected = 1;
+			sane[i][j].timeout = 5 * 60;	/* 5 Minutes */
+			sane[i][j].me = THIS_MODULE;
+			sane[i][j].help = help;
+			tmpname = &sane_names[i][j][0];
+			if (ports[i] == SANE_PORT)
+				sprintf(tmpname, "sane");
+			else
+				sprintf(tmpname, "sane-%d", ports[i]);
+			sane[i][j].name = tmpname;
+
+			DEBUGP("nf_ct_sane: registering helper for pf: %d "
+			       "port: %d\n",
+				sane[i][j].tuple.src.l3num, ports[i]);
+			ret = nf_conntrack_helper_register(&sane[i][j]);
+			if (ret) {
+				printk(KERN_ERR "nf_ct_sane: failed to "
+				       "register helper for pf: %d port: %d\n",
+					sane[i][j].tuple.src.l3num, ports[i]);
+				nf_conntrack_sane_fini();
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
+module_init(nf_conntrack_sane_init);
+module_exit(nf_conntrack_sane_fini);
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 9dec115..7aaa8c9 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -341,7 +341,7 @@
 			continue;
 		}
 		aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
-		                    ct_sip_lnlen(dptr, limit),
+				    ct_sip_lnlen(dptr, limit),
 				    hnfo->case_sensitive);
 		if (!aux) {
 			DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
@@ -451,12 +451,12 @@
 
 		/* We'll drop only if there are parse problems. */
 		if (!parse_addr(ct, dptr + matchoff, NULL, &addr,
-			        dptr + datalen)) {
+				dptr + datalen)) {
 			ret = NF_DROP;
 			goto out;
 		}
 		if (ct_sip_get_info(ct, dptr, datalen, &matchoff, &matchlen,
-		                    POS_MEDIA) > 0) {
+				    POS_MEDIA) > 0) {
 
 			port = simple_strtoul(dptr + matchoff, NULL, 10);
 			if (port < 1024) {
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index f1cb60f..b858636 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -229,7 +229,7 @@
 	return ret;
 }
 
-static struct file_operations ct_file_ops = {
+static const struct file_operations ct_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_open,
 	.read    = seq_read,
@@ -317,7 +317,7 @@
 	return seq_open(file, &ct_cpu_seq_ops);
 }
 
-static struct file_operations ct_cpu_seq_fops = {
+static const struct file_operations ct_cpu_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = ct_cpu_seq_open,
 	.read	 = seq_read,
@@ -445,7 +445,7 @@
 	proc_stat->owner = THIS_MODULE;
 #endif
 #ifdef CONFIG_SYSCTL
-	nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
+	nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table);
 	if (nf_ct_sysctl_header == NULL) {
 		printk("nf_conntrack: can't register to sysctl.\n");
 		ret = -ENOMEM;
@@ -472,7 +472,7 @@
 static void __exit nf_conntrack_standalone_fini(void)
 {
 #ifdef CONFIG_SYSCTL
- 	unregister_sysctl_table(nf_ct_sysctl_header);
+	unregister_sysctl_table(nf_ct_sysctl_header);
 #endif
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("nf_conntrack", proc_net_stat);
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
index f5bffe2..37c4542 100644
--- a/net/netfilter/nf_conntrack_tftp.c
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -31,7 +31,7 @@
 
 #if 0
 #define DEBUGP(format, args...) printk("%s:%s:" format, \
-                                       __FILE__, __FUNCTION__ , ## args)
+				       __FILE__, __FUNCTION__ , ## args)
 #else
 #define DEBUGP(format, args...)
 #endif
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
index a981971..0df7fff 100644
--- a/net/netfilter/nf_internals.h
+++ b/net/netfilter/nf_internals.h
@@ -24,7 +24,7 @@
 
 /* nf_queue.c */
 extern int nf_queue(struct sk_buff *skb,
-		    struct list_head *elem, 
+		    struct list_head *elem,
 		    int pf, unsigned int hook,
 		    struct net_device *indev,
 		    struct net_device *outdev,
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 8901b3a..91b220c 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -14,62 +14,63 @@
 
 #define NF_LOG_PREFIXLEN		128
 
-static struct nf_logger *nf_logging[NPROTO]; /* = NULL */
-static DEFINE_SPINLOCK(nf_log_lock);
+static struct nf_logger *nf_loggers[NPROTO];
+static DEFINE_MUTEX(nf_log_mutex);
 
 /* return EBUSY if somebody else is registered, EEXIST if the same logger
  * is registred, 0 on success. */
 int nf_log_register(int pf, struct nf_logger *logger)
 {
-	int ret = -EBUSY;
+	int ret;
 
 	if (pf >= NPROTO)
 		return -EINVAL;
 
 	/* Any setup of logging members must be done before
 	 * substituting pointer. */
-	spin_lock(&nf_log_lock);
-	if (!nf_logging[pf]) {
-		rcu_assign_pointer(nf_logging[pf], logger);
-		ret = 0;
-	} else if (nf_logging[pf] == logger)
-		ret = -EEXIST;
+	ret = mutex_lock_interruptible(&nf_log_mutex);
+	if (ret < 0)
+		return ret;
 
-	spin_unlock(&nf_log_lock);
+	if (!nf_loggers[pf])
+		rcu_assign_pointer(nf_loggers[pf], logger);
+	else if (nf_loggers[pf] == logger)
+		ret = -EEXIST;
+	else
+		ret = -EBUSY;
+
+	mutex_unlock(&nf_log_mutex);
 	return ret;
-}		
+}
 EXPORT_SYMBOL(nf_log_register);
 
-int nf_log_unregister_pf(int pf)
+void nf_log_unregister_pf(int pf)
 {
 	if (pf >= NPROTO)
-		return -EINVAL;
-
-	spin_lock(&nf_log_lock);
-	nf_logging[pf] = NULL;
-	spin_unlock(&nf_log_lock);
+		return;
+	mutex_lock(&nf_log_mutex);
+	rcu_assign_pointer(nf_loggers[pf], NULL);
+	mutex_unlock(&nf_log_mutex);
 
 	/* Give time to concurrent readers. */
-	synchronize_net();
-
-	return 0;
+	synchronize_rcu();
 }
 EXPORT_SYMBOL(nf_log_unregister_pf);
 
-void nf_log_unregister_logger(struct nf_logger *logger)
+void nf_log_unregister(struct nf_logger *logger)
 {
 	int i;
 
-	spin_lock(&nf_log_lock);
+	mutex_lock(&nf_log_mutex);
 	for (i = 0; i < NPROTO; i++) {
-		if (nf_logging[i] == logger)
-			nf_logging[i] = NULL;
+		if (nf_loggers[i] == logger)
+			rcu_assign_pointer(nf_loggers[i], NULL);
 	}
-	spin_unlock(&nf_log_lock);
+	mutex_unlock(&nf_log_mutex);
 
-	synchronize_net();
+	synchronize_rcu();
 }
-EXPORT_SYMBOL(nf_log_unregister_logger);
+EXPORT_SYMBOL(nf_log_unregister);
 
 void nf_log_packet(int pf,
 		   unsigned int hooknum,
@@ -82,9 +83,9 @@
 	va_list args;
 	char prefix[NF_LOG_PREFIXLEN];
 	struct nf_logger *logger;
-	
+
 	rcu_read_lock();
-	logger = rcu_dereference(nf_logging[pf]);
+	logger = rcu_dereference(nf_loggers[pf]);
 	if (logger) {
 		va_start(args, fmt);
 		vsnprintf(prefix, sizeof(prefix), fmt, args);
@@ -131,11 +132,11 @@
 	loff_t *pos = v;
 	const struct nf_logger *logger;
 
-	logger = rcu_dereference(nf_logging[*pos]);
+	logger = rcu_dereference(nf_loggers[*pos]);
 
 	if (!logger)
 		return seq_printf(s, "%2lld NONE\n", *pos);
-	
+
 	return seq_printf(s, "%2lld %s\n", *pos, logger->name);
 }
 
@@ -151,7 +152,7 @@
 	return seq_open(file, &nflog_seq_ops);
 }
 
-static struct file_operations nflog_file_ops = {
+static const struct file_operations nflog_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = nflog_open,
 	.read	 = seq_read,
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 4d8936e..b1f2ace 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -10,7 +10,7 @@
 
 #include "nf_internals.h"
 
-/* 
+/*
  * A queue handler may be registered for each protocol.  Each is protected by
  * long term mutex.  The handler must provide an an outfn() to accept packets
  * for queueing and must reinject all packets it receives, no matter what.
@@ -22,7 +22,7 @@
 /* return EBUSY when somebody else is registered, return EEXIST if the
  * same handler is registered, return 0 in case of success. */
 int nf_register_queue_handler(int pf, struct nf_queue_handler *qh)
-{      
+{
 	int ret;
 
 	if (pf >= NPROTO)
@@ -52,7 +52,7 @@
 	write_lock_bh(&queue_handler_lock);
 	queue_handler[pf] = NULL;
 	write_unlock_bh(&queue_handler_lock);
-	
+
 	return 0;
 }
 EXPORT_SYMBOL(nf_unregister_queue_handler);
@@ -70,8 +70,8 @@
 }
 EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
 
-/* 
- * Any packet that leaves via this function must come back 
+/*
+ * Any packet that leaves via this function must come back
  * through nf_reinject().
  */
 static int __nf_queue(struct sk_buff *skb,
@@ -115,7 +115,7 @@
 		return 1;
 	}
 
-	*info = (struct nf_info) { 
+	*info = (struct nf_info) {
 		(struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
 
 	/* If it's going away, ignore hook. */
@@ -226,10 +226,10 @@
 	module_put(info->elem->owner);
 
 	list_for_each_rcu(i, &nf_hooks[info->pf][info->hook]) {
-		if (i == elem) 
-  			break;
-  	}
-  
+		if (i == elem)
+			break;
+	}
+
 	if (i == &nf_hooks[info->pf][info->hook]) {
 		/* The module which sent it to userspace is gone. */
 		NFDEBUG("%s: module disappeared, dropping packet.\n",
@@ -252,7 +252,7 @@
 	if (verdict == NF_ACCEPT) {
 	next_hook:
 		verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
-				     &skb, info->hook, 
+				     &skb, info->hook,
 				     info->indev, info->outdev, &elem,
 				     info->okfn, INT_MIN);
 	}
@@ -331,7 +331,7 @@
 	return seq_open(file, &nfqueue_seq_ops);
 }
 
-static struct file_operations nfqueue_file_ops = {
+static const struct file_operations nfqueue_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = nfqueue_open,
 	.read	 = seq_read,
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index c2e44e9..8b8ece7 100644
--- a/net/netfilter/nf_sockopt.c
+++ b/net/netfilter/nf_sockopt.c
@@ -32,13 +32,13 @@
 	list_for_each(i, &nf_sockopts) {
 		struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
 		if (ops->pf == reg->pf
-		    && (overlap(ops->set_optmin, ops->set_optmax, 
+		    && (overlap(ops->set_optmin, ops->set_optmax,
 				reg->set_optmin, reg->set_optmax)
-			|| overlap(ops->get_optmin, ops->get_optmax, 
+			|| overlap(ops->get_optmin, ops->get_optmax,
 				   reg->get_optmin, reg->get_optmax))) {
 			NFDEBUG("nf_sock overlap: %u-%u/%u-%u v %u-%u/%u-%u\n",
-				ops->set_optmin, ops->set_optmax, 
-				ops->get_optmin, ops->get_optmax, 
+				ops->set_optmin, ops->set_optmax,
+				ops->get_optmin, ops->get_optmax,
 				reg->set_optmin, reg->set_optmax,
 				reg->get_optmin, reg->get_optmax);
 			ret = -EBUSY;
@@ -73,7 +73,7 @@
 EXPORT_SYMBOL(nf_unregister_sockopt);
 
 /* Call get/setsockopt() */
-static int nf_sockopt(struct sock *sk, int pf, int val, 
+static int nf_sockopt(struct sock *sk, int pf, int val,
 		      char __user *opt, int *len, int get)
 {
 	struct list_head *i;
@@ -107,7 +107,7 @@
 	}
 	mutex_unlock(&nf_sockopt_mutex);
 	return -ENOPROTOOPT;
-	
+
  out:
 	mutex_lock(&nf_sockopt_mutex);
 	ops->use--;
diff --git a/net/netfilter/nf_sysctl.c b/net/netfilter/nf_sysctl.c
index 06ddddb..ee34589 100644
--- a/net/netfilter/nf_sysctl.c
+++ b/net/netfilter/nf_sysctl.c
@@ -56,7 +56,7 @@
 	path = path_dup(path, table);
 	if (path == NULL)
 		return NULL;
-	header = register_sysctl_table(path, 0);
+	header = register_sysctl_table(path);
 	if (header == NULL)
 		path_free(path, table);
 	return header;
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 52fdfa2..11d504d 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -19,7 +19,6 @@
 #include <linux/socket.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -105,7 +104,7 @@
 nfnetlink_find_client(u_int16_t type, struct nfnetlink_subsystem *ss)
 {
 	u_int8_t cb_id = NFNL_MSG_TYPE(type);
-	
+
 	if (cb_id >= ss->cb_count) {
 		DEBUGP("msgtype %u >= %u, returning\n", type, ss->cb_count);
 		return NULL;
@@ -187,7 +186,7 @@
 	/* implicit: if nlmsg_len == min_len, we return 0, and an empty
 	 * (zeroed) cda[] array. The message is valid, but empty. */
 
-        return 0;
+	return 0;
 }
 
 int nfnetlink_has_listeners(unsigned int group)
@@ -268,12 +267,12 @@
 	}
 
 	{
-		u_int16_t attr_count = 
+		u_int16_t attr_count =
 			ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count;
 		struct nfattr *cda[attr_count];
 
 		memset(cda, 0, sizeof(struct nfattr *) * attr_count);
-		
+
 		err = nfnetlink_check_attributes(ss, nlh, cda);
 		if (err < 0)
 			goto err_inval;
@@ -357,7 +356,7 @@
 	printk("Netfilter messages via NETLINK v%s.\n", nfversion);
 
 	nfnl = netlink_kernel_create(NETLINK_NETFILTER, NFNLGRP_MAX,
-	                             nfnetlink_rcv, THIS_MODULE);
+				     nfnetlink_rcv, THIS_MODULE);
 	if (!nfnl) {
 		printk(KERN_ERR "cannot initialize nfnetlink!\n");
 		return -1;
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index d1505dd..b8eab0d 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -75,7 +75,7 @@
 	u_int32_t seq;			/* instance-local sequential counter */
 	u_int16_t group_num;		/* number of this queue */
 	u_int16_t flags;
-	u_int8_t copy_mode;	
+	u_int8_t copy_mode;
 };
 
 static DEFINE_RWLOCK(instances_lock);
@@ -146,7 +146,7 @@
 	UDEBUG("entering (group_num=%u, pid=%d)\n", group_num,
 		pid);
 
-	write_lock_bh(&instances_lock);	
+	write_lock_bh(&instances_lock);
 	if (__instance_lookup(group_num)) {
 		inst = NULL;
 		UDEBUG("aborting, instance already exists\n");
@@ -179,10 +179,10 @@
 	if (!try_module_get(THIS_MODULE))
 		goto out_free;
 
-	hlist_add_head(&inst->hlist, 
+	hlist_add_head(&inst->hlist,
 		       &instance_table[instance_hashfn(group_num)]);
 
-	UDEBUG("newly added node: %p, next=%p\n", &inst->hlist, 
+	UDEBUG("newly added node: %p, next=%p\n", &inst->hlist,
 		inst->hlist.next);
 
 	write_unlock_bh(&instances_lock);
@@ -251,14 +251,14 @@
 	int status = 0;
 
 	spin_lock_bh(&inst->lock);
-	
+
 	switch (mode) {
 	case NFULNL_COPY_NONE:
 	case NFULNL_COPY_META:
 		inst->copy_mode = mode;
 		inst->copy_range = 0;
 		break;
-		
+
 	case NFULNL_COPY_PACKET:
 		inst->copy_mode = mode;
 		/* we're using struct nfattr which has 16bit nfa_len */
@@ -267,7 +267,7 @@
 		else
 			inst->copy_range = range;
 		break;
-		
+
 	default:
 		status = -EINVAL;
 		break;
@@ -327,7 +327,7 @@
 	return 0;
 }
 
-static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, 
+static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size,
 					unsigned int pkt_size)
 {
 	struct sk_buff *skb;
@@ -387,7 +387,7 @@
 
 static void nfulnl_timer(unsigned long data)
 {
-	struct nfulnl_instance *inst = (struct nfulnl_instance *)data; 
+	struct nfulnl_instance *inst = (struct nfulnl_instance *)data;
 
 	UDEBUG("timer function called, flushing buffer\n");
 
@@ -399,9 +399,9 @@
 
 /* This is an inline function, we don't really care about a long
  * list of arguments */
-static inline int 
+static inline int
 __build_packet_message(struct nfulnl_instance *inst,
-			const struct sk_buff *skb, 
+			const struct sk_buff *skb,
 			unsigned int data_len,
 			unsigned int pf,
 			unsigned int hooknum,
@@ -417,9 +417,9 @@
 	__be32 tmp_uint;
 
 	UDEBUG("entered\n");
-		
+
 	old_tail = inst->skb->tail;
-	nlh = NLMSG_PUT(inst->skb, 0, 0, 
+	nlh = NLMSG_PUT(inst->skb, 0, 0,
 			NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET,
 			sizeof(struct nfgenmsg));
 	nfmsg = NLMSG_DATA(nlh);
@@ -457,7 +457,7 @@
 			NFA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
 				sizeof(tmp_uint), &tmp_uint);
 			if (skb->nf_bridge && skb->nf_bridge->physindev) {
-				tmp_uint = 
+				tmp_uint =
 				    htonl(skb->nf_bridge->physindev->ifindex);
 				NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
 					sizeof(tmp_uint), &tmp_uint);
@@ -488,7 +488,7 @@
 			NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
 				sizeof(tmp_uint), &tmp_uint);
 			if (skb->nf_bridge) {
-				tmp_uint = 
+				tmp_uint =
 				    htonl(skb->nf_bridge->physoutdev->ifindex);
 				NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
 					sizeof(tmp_uint), &tmp_uint);
@@ -558,7 +558,7 @@
 		if (skb_copy_bits(skb, 0, NFA_DATA(nfa), data_len))
 			BUG();
 	}
-		
+
 	nlh->nlmsg_len = inst->skb->tail - old_tail;
 	return 0;
 
@@ -599,7 +599,7 @@
 	unsigned int nlbufsiz;
 	unsigned int plen;
 
-	if (li_user && li_user->type == NF_LOG_TYPE_ULOG) 
+	if (li_user && li_user->type == NF_LOG_TYPE_ULOG)
 		li = li_user;
 	else
 		li = &default_loginfo;
@@ -648,24 +648,24 @@
 	/* per-rule qthreshold overrides per-instance */
 	if (qthreshold > li->u.ulog.qthreshold)
 		qthreshold = li->u.ulog.qthreshold;
-	
+
 	switch (inst->copy_mode) {
 	case NFULNL_COPY_META:
 	case NFULNL_COPY_NONE:
 		data_len = 0;
 		break;
-	
+
 	case NFULNL_COPY_PACKET:
-		if (inst->copy_range == 0 
+		if (inst->copy_range == 0
 		    || inst->copy_range > skb->len)
 			data_len = skb->len;
 		else
 			data_len = inst->copy_range;
-		
+
 		size += NFA_SPACE(data_len);
 		UDEBUG("copy_packet, therefore size now %u\n", size);
 		break;
-	
+
 	default:
 		spin_unlock_bh(&inst->lock);
 		instance_put(inst);
@@ -991,9 +991,9 @@
 {
 	const struct nfulnl_instance *inst = v;
 
-	return seq_printf(s, "%5d %6d %5d %1d %5d %6d %2d\n", 
+	return seq_printf(s, "%5d %6d %5d %1d %5d %6d %2d\n",
 			  inst->group_num,
-			  inst->peer_pid, inst->qlen, 
+			  inst->peer_pid, inst->qlen,
 			  inst->copy_mode, inst->copy_range,
 			  inst->flushtimeout, atomic_read(&inst->use));
 }
@@ -1025,7 +1025,7 @@
 	return ret;
 }
 
-static struct file_operations nful_file_ops = {
+static const struct file_operations nful_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = nful_open,
 	.read	 = seq_read,
@@ -1041,10 +1041,10 @@
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *proc_nful;
 #endif
-	
+
 	for (i = 0; i < INSTANCE_BUCKETS; i++)
 		INIT_HLIST_HEAD(&instance_table[i]);
-	
+
 	/* it's not really all that important to have a random value, so
 	 * we can do this from the init function, even if there hasn't
 	 * been that much entropy yet */
@@ -1077,7 +1077,7 @@
 
 static void __exit nfnetlink_log_fini(void)
 {
-	nf_log_unregister_logger(&nfulnl_logger);
+	nf_log_unregister(&nfulnl_logger);
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("nfnetlink_log", proc_net_netfilter);
 #endif
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index a88a017..d9ce4a7 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -129,7 +129,7 @@
 
 	QDEBUG("entering for queue_num=%u, pid=%d\n", queue_num, pid);
 
-	write_lock_bh(&instances_lock);	
+	write_lock_bh(&instances_lock);
 	if (__instance_lookup(queue_num)) {
 		inst = NULL;
 		QDEBUG("aborting, instance already exists\n");
@@ -154,7 +154,7 @@
 	if (!try_module_get(THIS_MODULE))
 		goto out_free;
 
-	hlist_add_head(&inst->hlist, 
+	hlist_add_head(&inst->hlist,
 		       &instance_table[instance_hashfn(queue_num)]);
 
 	write_unlock_bh(&instances_lock);
@@ -239,14 +239,14 @@
  * entry if cmpfn is NULL.
  */
 static inline struct nfqnl_queue_entry *
-__find_entry(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, 
+__find_entry(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn,
 		   unsigned long data)
 {
 	struct list_head *p;
 
 	list_for_each_prev(p, &queue->queue_list) {
 		struct nfqnl_queue_entry *entry = (struct nfqnl_queue_entry *)p;
-		
+
 		if (!cmpfn || cmpfn(entry, data))
 			return entry;
 	}
@@ -279,7 +279,7 @@
 __nfqnl_flush(struct nfqnl_instance *queue, int verdict)
 {
 	struct nfqnl_queue_entry *entry;
-	
+
 	while ((entry = __find_dequeue_entry(queue, NULL, 0)))
 		issue_verdict(entry, verdict);
 }
@@ -289,14 +289,14 @@
 		 unsigned char mode, unsigned int range)
 {
 	int status = 0;
-	
+
 	switch (mode) {
 	case NFQNL_COPY_NONE:
 	case NFQNL_COPY_META:
 		queue->copy_mode = mode;
 		queue->copy_range = 0;
 		break;
-		
+
 	case NFQNL_COPY_PACKET:
 		queue->copy_mode = mode;
 		/* we're using struct nfattr which has 16bit nfa_len */
@@ -305,7 +305,7 @@
 		else
 			queue->copy_range = range;
 		break;
-		
+
 	default:
 		status = -EINVAL;
 
@@ -318,7 +318,7 @@
 			 nfqnl_cmpfn cmpfn, unsigned long data)
 {
 	struct nfqnl_queue_entry *entry;
-	
+
 	spin_lock_bh(&queue->lock);
 	entry = __find_dequeue_entry(queue, cmpfn, data);
 	spin_unlock_bh(&queue->lock);
@@ -369,13 +369,13 @@
 	outdev = entinf->outdev;
 
 	spin_lock_bh(&queue->lock);
-	
+
 	switch (queue->copy_mode) {
 	case NFQNL_COPY_META:
 	case NFQNL_COPY_NONE:
 		data_len = 0;
 		break;
-	
+
 	case NFQNL_COPY_PACKET:
 		if ((entskb->ip_summed == CHECKSUM_PARTIAL ||
 		     entskb->ip_summed == CHECKSUM_COMPLETE) &&
@@ -383,15 +383,15 @@
 			spin_unlock_bh(&queue->lock);
 			return NULL;
 		}
-		if (queue->copy_range == 0 
+		if (queue->copy_range == 0
 		    || queue->copy_range > entskb->len)
 			data_len = entskb->len;
 		else
 			data_len = queue->copy_range;
-		
+
 		size += NFA_SPACE(data_len);
 		break;
-	
+
 	default:
 		*errp = -EINVAL;
 		spin_unlock_bh(&queue->lock);
@@ -403,9 +403,9 @@
 	skb = alloc_skb(size, GFP_ATOMIC);
 	if (!skb)
 		goto nlmsg_failure;
-		
+
 	old_tail= skb->tail;
-	nlh = NLMSG_PUT(skb, 0, 0, 
+	nlh = NLMSG_PUT(skb, 0, 0,
 			NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET,
 			sizeof(struct nfgenmsg));
 	nfmsg = NLMSG_DATA(nlh);
@@ -427,9 +427,9 @@
 #else
 		if (entinf->pf == PF_BRIDGE) {
 			/* Case 1: indev is physical input device, we need to
-			 * look for bridge group (when called from 
+			 * look for bridge group (when called from
 			 * netfilter_bridge) */
-			NFA_PUT(skb, NFQA_IFINDEX_PHYSINDEV, sizeof(tmp_uint), 
+			NFA_PUT(skb, NFQA_IFINDEX_PHYSINDEV, sizeof(tmp_uint),
 				&tmp_uint);
 			/* this is the bridge group "brX" */
 			tmp_uint = htonl(indev->br_port->br->dev->ifindex);
@@ -457,7 +457,7 @@
 #else
 		if (entinf->pf == PF_BRIDGE) {
 			/* Case 1: outdev is physical output device, we need to
-			 * look for bridge group (when called from 
+			 * look for bridge group (when called from
 			 * netfilter_bridge) */
 			NFA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV, sizeof(tmp_uint),
 				&tmp_uint);
@@ -490,7 +490,7 @@
 		struct nfqnl_msg_packet_hw phw;
 
 		int len = entskb->dev->hard_header_parse(entskb,
-			                                   phw.hw_addr);
+							   phw.hw_addr);
 		phw.hw_addrlen = htons(len);
 		NFA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw);
 	}
@@ -520,7 +520,7 @@
 		if (skb_copy_bits(entskb, 0, NFA_DATA(nfa), data_len))
 			BUG();
 	}
-		
+
 	nlh->nlmsg_len = skb->tail - old_tail;
 	return skb;
 
@@ -535,7 +535,7 @@
 }
 
 static int
-nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info, 
+nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
 		     unsigned int queuenum, void *data)
 {
 	int status = -EINVAL;
@@ -560,7 +560,7 @@
 	entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
 	if (entry == NULL) {
 		if (net_ratelimit())
-			printk(KERN_ERR 
+			printk(KERN_ERR
 				"nf_queue: OOM in nfqnl_enqueue_packet()\n");
 		status = -ENOMEM;
 		goto err_out_put;
@@ -573,18 +573,18 @@
 	nskb = nfqnl_build_packet_message(queue, entry, &status);
 	if (nskb == NULL)
 		goto err_out_free;
-		
+
 	spin_lock_bh(&queue->lock);
-	
+
 	if (!queue->peer_pid)
-		goto err_out_free_nskb; 
+		goto err_out_free_nskb;
 
 	if (queue->queue_total >= queue->queue_maxlen) {
-                queue->queue_dropped++;
+		queue->queue_dropped++;
 		status = -ENOSPC;
 		if (net_ratelimit())
-		          printk(KERN_WARNING "nf_queue: full at %d entries, "
-				 "dropping packets(s). Dropped: %d\n", 
+			  printk(KERN_WARNING "nf_queue: full at %d entries, "
+				 "dropping packets(s). Dropped: %d\n",
 				 queue->queue_total, queue->queue_dropped);
 		goto err_out_free_nskb;
 	}
@@ -592,7 +592,7 @@
 	/* nfnetlink_unicast will either free the nskb or add it to a socket */
 	status = nfnetlink_unicast(nskb, queue->peer_pid, MSG_DONTWAIT);
 	if (status < 0) {
-	        queue->queue_user_dropped++;
+		queue->queue_user_dropped++;
 		goto err_out_unlock;
 	}
 
@@ -603,8 +603,8 @@
 	return status;
 
 err_out_free_nskb:
-	kfree_skb(nskb); 
-	
+	kfree_skb(nskb);
+
 err_out_unlock:
 	spin_unlock_bh(&queue->lock);
 
@@ -629,11 +629,11 @@
 			return -EINVAL;
 		if (diff > skb_tailroom(e->skb)) {
 			struct sk_buff *newskb;
-			
+
 			newskb = skb_copy_expand(e->skb,
-			                         skb_headroom(e->skb),
-			                         diff,
-			                         GFP_ATOMIC);
+						 skb_headroom(e->skb),
+						 diff,
+						 GFP_ATOMIC);
 			if (newskb == NULL) {
 				printk(KERN_WARNING "nf_queue: OOM "
 				      "in mangle, dropping packet\n");
@@ -676,7 +676,7 @@
 dev_cmp(struct nfqnl_queue_entry *entry, unsigned long ifindex)
 {
 	struct nf_info *entinf = entry->info;
-	
+
 	if (entinf->indev)
 		if (entinf->indev->ifindex == ifindex)
 			return 1;
@@ -702,7 +702,7 @@
 nfqnl_dev_drop(int ifindex)
 {
 	int i;
-	
+
 	QDEBUG("entering for ifindex %u\n", ifindex);
 
 	/* this only looks like we have to hold the readlock for a way too long
@@ -717,7 +717,7 @@
 
 		hlist_for_each_entry(inst, tmp, head, hlist) {
 			struct nfqnl_queue_entry *entry;
-			while ((entry = find_dequeue_entry(inst, dev_cmp, 
+			while ((entry = find_dequeue_entry(inst, dev_cmp,
 							   ifindex)) != NULL)
 				issue_verdict(entry, NF_DROP);
 		}
@@ -835,8 +835,8 @@
 
 	if (nfqa[NFQA_MARK-1])
 		entry->skb->mark = ntohl(*(__be32 *)
-		                         NFA_DATA(nfqa[NFQA_MARK-1]));
-		
+					 NFA_DATA(nfqa[NFQA_MARK-1]));
+
 	issue_verdict(entry, verdict);
 	instance_put(queue);
 	return 0;
@@ -1077,7 +1077,7 @@
 	return ret;
 }
 
-static struct file_operations nfqnl_file_ops = {
+static const struct file_operations nfqnl_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = nfqnl_open,
 	.read	 = seq_read,
@@ -1093,7 +1093,7 @@
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *proc_nfqueue;
 #endif
-	
+
 	for (i = 0; i < INSTANCE_BUCKETS; i++)
 		INIT_HLIST_HEAD(&instance_table[i]);
 
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8996584..ec607a4 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -305,7 +305,7 @@
 EXPORT_SYMBOL_GPL(xt_find_revision);
 
 int xt_check_match(const struct xt_match *match, unsigned short family,
-                   unsigned int size, const char *table, unsigned int hook_mask,
+		   unsigned int size, const char *table, unsigned int hook_mask,
 		   unsigned short proto, int inv_proto)
 {
 	if (XT_ALIGN(match->matchsize) != size) {
@@ -377,7 +377,7 @@
 
 	if (copy_to_user(cm, m, sizeof(*cm)) ||
 	    put_user(msize, &cm->u.user.match_size))
-	    	return -EFAULT;
+		return -EFAULT;
 
 	if (match->compat_to_user) {
 		if (match->compat_to_user((void __user *)cm->data, m->data))
@@ -432,7 +432,7 @@
 EXPORT_SYMBOL_GPL(xt_compat_target_offset);
 
 void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
-			        int *size)
+				int *size)
 {
 	struct xt_target *target = t->u.kernel.target;
 	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
@@ -467,7 +467,7 @@
 
 	if (copy_to_user(ct, t, sizeof(*ct)) ||
 	    put_user(tsize, &ct->u.user.target_size))
-	    	return -EFAULT;
+		return -EFAULT;
 
 	if (target->compat_to_user) {
 		if (target->compat_to_user((void __user *)ct->data, t->data))
@@ -710,7 +710,7 @@
 
 	if (mutex_lock_interruptible(&xt[af].mutex) != 0)
 		return NULL;
-	
+
 	return xt_get_idx(list, seq, *pos);
 }
 
@@ -723,7 +723,7 @@
 
 	if (af >= NPROTO)
 		return NULL;
-	
+
 	list = type2list(af, type);
 	if (!list)
 		return NULL;
@@ -772,7 +772,7 @@
 	return ret;
 }
 
-static struct file_operations xt_file_ops = {
+static const struct file_operations xt_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = xt_tgt_open,
 	.read	 = seq_read,
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 50de965..3088483 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -15,6 +15,8 @@
 #include <linux/ip.h>
 #include <net/checksum.h>
 
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_CLASSIFY.h>
 
@@ -33,9 +35,7 @@
 {
 	const struct xt_classify_target_info *clinfo = targinfo;
 
-	if ((*pskb)->priority != clinfo->priority)
-		(*pskb)->priority = clinfo->priority;
-
+	(*pskb)->priority = clinfo->priority;
 	return XT_CONTINUE;
 }
 
@@ -48,7 +48,7 @@
 		.table		= "mangle",
 		.hooks		= (1 << NF_IP_LOCAL_OUT) |
 				  (1 << NF_IP_FORWARD) |
-			          (1 << NF_IP_POST_ROUTING),
+				  (1 << NF_IP_POST_ROUTING),
 		.me 		= THIS_MODULE,
 	},
 	{
@@ -57,9 +57,9 @@
 		.target 	= target,
 		.targetsize	= sizeof(struct xt_classify_target_info),
 		.table		= "mangle",
-		.hooks		= (1 << NF_IP_LOCAL_OUT) |
-				  (1 << NF_IP_FORWARD) |
-			          (1 << NF_IP_POST_ROUTING),
+		.hooks		= (1 << NF_IP6_LOCAL_OUT) |
+				  (1 << NF_IP6_FORWARD) |
+				  (1 << NF_IP6_POST_ROUTING),
 		.me 		= THIS_MODULE,
 	},
 };
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 0534bfa..795c058 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -61,7 +61,7 @@
 #else
 				nf_conntrack_event_cache(IPCT_MARK, *pskb);
 #endif
-		}
+			}
 			break;
 		case XT_CONNMARK_SAVE:
 			newmark = (*ctmark & ~markinfo->mask) |
@@ -78,8 +78,7 @@
 		case XT_CONNMARK_RESTORE:
 			mark = (*pskb)->mark;
 			diff = (*ctmark ^ mark) & markinfo->mask;
-			if (diff != 0)
-				(*pskb)->mark = mark ^ diff;
+			(*pskb)->mark = mark ^ diff;
 			break;
 		}
 	}
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index a3fe3c3..1ab0db6 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -41,8 +41,7 @@
 
 		connsecmark = nf_ct_get_secmark(skb, &ctinfo);
 		if (connsecmark && !*connsecmark)
-			if (*connsecmark != skb->secmark)
-				*connsecmark = skb->secmark;
+			*connsecmark = skb->secmark;
 	}
 }
 
@@ -58,8 +57,7 @@
 
 		connsecmark = nf_ct_get_secmark(skb, &ctinfo);
 		if (connsecmark && *connsecmark)
-			if (skb->secmark != *connsecmark)
-				skb->secmark = *connsecmark;
+			skb->secmark = *connsecmark;
 	}
 }
 
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 0b48547..4381780 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -31,9 +31,7 @@
 {
 	const struct xt_mark_target_info *markinfo = targinfo;
 
-	if((*pskb)->mark != markinfo->mark)
-		(*pskb)->mark = markinfo->mark;
-
+	(*pskb)->mark = markinfo->mark;
 	return XT_CONTINUE;
 }
 
@@ -52,19 +50,17 @@
 	case XT_MARK_SET:
 		mark = markinfo->mark;
 		break;
-		
+
 	case XT_MARK_AND:
 		mark = (*pskb)->mark & markinfo->mark;
 		break;
-		
+
 	case XT_MARK_OR:
 		mark = (*pskb)->mark | markinfo->mark;
 		break;
 	}
 
-	if((*pskb)->mark != mark)
-		(*pskb)->mark = mark;
-
+	(*pskb)->mark = mark;
 	return XT_CONTINUE;
 }
 
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 39e1175..201155b 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -3,9 +3,9 @@
  * (C) 2005 by Harald Welte <laforge@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 
+ * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- * 
+ *
  */
 
 #include <linux/module.h>
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index 6d00dca..b874a20 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -22,8 +22,8 @@
 	if ((*pskb)->nfct != NULL)
 		return XT_CONTINUE;
 
-	/* Attach fake conntrack entry. 
-	   If there is a real ct entry correspondig to this packet, 
+	/* Attach fake conntrack entry.
+	   If there is a real ct entry correspondig to this packet,
 	   it'll hang aroun till timing out. We don't deal with it
 	   for performance reasons. JK */
 	nf_ct_untrack(*pskb);
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index add7521..705f0e8 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -47,9 +47,7 @@
 		BUG();
 	}
 
-	if ((*pskb)->secmark != secmark)
-		(*pskb)->secmark = secmark;
-
+	(*pskb)->secmark = secmark;
 	return XT_CONTINUE;
 }
 
@@ -57,7 +55,7 @@
 {
 	int err;
 	struct xt_secmark_target_selinux_info *sel = &info->u.sel;
-	
+
 	sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0';
 
 	err = selinux_string_to_sid(sel->selctx, &sel->selsid);
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
new file mode 100644
index 0000000..db7e38c
--- /dev/null
+++ b/net/netfilter/xt_TCPMSS.c
@@ -0,0 +1,296 @@
+/*
+ * This is a module which is used for setting the MSS option in TCP packets.
+ *
+ * Copyright (C) 2000 Marc Boucher <marc@mbsi.ca>
+ *
+ * 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/tcp.h>
+#include <net/ipv6.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_tcpudp.h>
+#include <linux/netfilter/xt_TCPMSS.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
+MODULE_DESCRIPTION("x_tables TCP MSS modification module");
+MODULE_ALIAS("ipt_TCPMSS");
+MODULE_ALIAS("ip6t_TCPMSS");
+
+static inline unsigned int
+optlen(const u_int8_t *opt, unsigned int offset)
+{
+	/* Beware zero-length options: make finite progress */
+	if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0)
+		return 1;
+	else
+		return opt[offset+1];
+}
+
+static int
+tcpmss_mangle_packet(struct sk_buff **pskb,
+		     const struct xt_tcpmss_info *info,
+		     unsigned int tcphoff,
+		     unsigned int minlen)
+{
+	struct tcphdr *tcph;
+	unsigned int tcplen, i;
+	__be16 oldval;
+	u16 newmss;
+	u8 *opt;
+
+	if (!skb_make_writable(pskb, (*pskb)->len))
+		return -1;
+
+	tcplen = (*pskb)->len - tcphoff;
+	tcph = (struct tcphdr *)((*pskb)->nh.raw + tcphoff);
+
+	/* Since it passed flags test in tcp match, we know it is is
+	   not a fragment, and has data >= tcp header length.  SYN
+	   packets should not contain data: if they did, then we risk
+	   running over MTU, sending Frag Needed and breaking things
+	   badly. --RR */
+	if (tcplen != tcph->doff*4) {
+		if (net_ratelimit())
+			printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n",
+			       (*pskb)->len);
+		return -1;
+	}
+
+	if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
+		if (dst_mtu((*pskb)->dst) <= minlen) {
+			if (net_ratelimit())
+				printk(KERN_ERR "xt_TCPMSS: "
+				       "unknown or invalid path-MTU (%u)\n",
+				       dst_mtu((*pskb)->dst));
+			return -1;
+		}
+		newmss = dst_mtu((*pskb)->dst) - minlen;
+	} else
+		newmss = info->mss;
+
+	opt = (u_int8_t *)tcph;
+	for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) {
+		if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS &&
+		    opt[i+1] == TCPOLEN_MSS) {
+			u_int16_t oldmss;
+
+			oldmss = (opt[i+2] << 8) | opt[i+3];
+
+			if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
+			    oldmss <= newmss)
+				return 0;
+
+			opt[i+2] = (newmss & 0xff00) >> 8;
+			opt[i+3] = (newmss & 0x00ff);
+
+			nf_proto_csum_replace2(&tcph->check, *pskb,
+					       htons(oldmss), htons(newmss), 0);
+			return 0;
+		}
+	}
+
+	/*
+	 * MSS Option not found ?! add it..
+	 */
+	if (skb_tailroom((*pskb)) < TCPOLEN_MSS) {
+		struct sk_buff *newskb;
+
+		newskb = skb_copy_expand(*pskb, skb_headroom(*pskb),
+					 TCPOLEN_MSS, GFP_ATOMIC);
+		if (!newskb)
+			return -1;
+		kfree_skb(*pskb);
+		*pskb = newskb;
+		tcph = (struct tcphdr *)((*pskb)->nh.raw + tcphoff);
+	}
+
+	skb_put((*pskb), TCPOLEN_MSS);
+
+	opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
+	memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
+
+	nf_proto_csum_replace2(&tcph->check, *pskb,
+			       htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
+	opt[0] = TCPOPT_MSS;
+	opt[1] = TCPOLEN_MSS;
+	opt[2] = (newmss & 0xff00) >> 8;
+	opt[3] = (newmss & 0x00ff);
+
+	nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
+
+	oldval = ((__be16 *)tcph)[6];
+	tcph->doff += TCPOLEN_MSS/4;
+	nf_proto_csum_replace2(&tcph->check, *pskb,
+				oldval, ((__be16 *)tcph)[6], 0);
+	return TCPOLEN_MSS;
+}
+
+static unsigned int
+xt_tcpmss_target4(struct sk_buff **pskb,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  unsigned int hooknum,
+		  const struct xt_target *target,
+		  const void *targinfo)
+{
+	struct iphdr *iph = (*pskb)->nh.iph;
+	__be16 newlen;
+	int ret;
+
+	ret = tcpmss_mangle_packet(pskb, targinfo, iph->ihl * 4,
+				   sizeof(*iph) + sizeof(struct tcphdr));
+	if (ret < 0)
+		return NF_DROP;
+	if (ret > 0) {
+		iph = (*pskb)->nh.iph;
+		newlen = htons(ntohs(iph->tot_len) + ret);
+		nf_csum_replace2(&iph->check, iph->tot_len, newlen);
+		iph->tot_len = newlen;
+	}
+	return XT_CONTINUE;
+}
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+static unsigned int
+xt_tcpmss_target6(struct sk_buff **pskb,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  unsigned int hooknum,
+		  const struct xt_target *target,
+		  const void *targinfo)
+{
+	struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
+	u8 nexthdr;
+	int tcphoff;
+	int ret;
+
+	nexthdr = ipv6h->nexthdr;
+	tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr);
+	if (tcphoff < 0) {
+		WARN_ON(1);
+		return NF_DROP;
+	}
+	ret = tcpmss_mangle_packet(pskb, targinfo, tcphoff,
+				   sizeof(*ipv6h) + sizeof(struct tcphdr));
+	if (ret < 0)
+		return NF_DROP;
+	if (ret > 0) {
+		ipv6h = (*pskb)->nh.ipv6h;
+		ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret);
+	}
+	return XT_CONTINUE;
+}
+#endif
+
+#define TH_SYN 0x02
+
+/* Must specify -p tcp --syn */
+static inline int find_syn_match(const struct xt_entry_match *m)
+{
+	const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data;
+
+	if (strcmp(m->u.kernel.match->name, "tcp") == 0 &&
+	    tcpinfo->flg_cmp & TH_SYN &&
+	    !(tcpinfo->invflags & XT_TCP_INV_FLAGS))
+		return 1;
+
+	return 0;
+}
+
+static int
+xt_tcpmss_checkentry4(const char *tablename,
+		      const void *entry,
+		      const struct xt_target *target,
+		      void *targinfo,
+		      unsigned int hook_mask)
+{
+	const struct xt_tcpmss_info *info = targinfo;
+	const struct ipt_entry *e = entry;
+
+	if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
+	    (hook_mask & ~((1 << NF_IP_FORWARD) |
+			   (1 << NF_IP_LOCAL_OUT) |
+			   (1 << NF_IP_POST_ROUTING))) != 0) {
+		printk("xt_TCPMSS: path-MTU clamping only supported in "
+		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
+		return 0;
+	}
+	if (IPT_MATCH_ITERATE(e, find_syn_match))
+		return 1;
+	printk("xt_TCPMSS: Only works on TCP SYN packets\n");
+	return 0;
+}
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+static int
+xt_tcpmss_checkentry6(const char *tablename,
+		      const void *entry,
+		      const struct xt_target *target,
+		      void *targinfo,
+		      unsigned int hook_mask)
+{
+	const struct xt_tcpmss_info *info = targinfo;
+	const struct ip6t_entry *e = entry;
+
+	if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
+	    (hook_mask & ~((1 << NF_IP6_FORWARD) |
+			   (1 << NF_IP6_LOCAL_OUT) |
+			   (1 << NF_IP6_POST_ROUTING))) != 0) {
+		printk("xt_TCPMSS: path-MTU clamping only supported in "
+		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
+		return 0;
+	}
+	if (IP6T_MATCH_ITERATE(e, find_syn_match))
+		return 1;
+	printk("xt_TCPMSS: Only works on TCP SYN packets\n");
+	return 0;
+}
+#endif
+
+static struct xt_target xt_tcpmss_reg[] = {
+	{
+		.family		= AF_INET,
+		.name		= "TCPMSS",
+		.checkentry	= xt_tcpmss_checkentry4,
+		.target		= xt_tcpmss_target4,
+		.targetsize	= sizeof(struct xt_tcpmss_info),
+		.proto		= IPPROTO_TCP,
+		.me		= THIS_MODULE,
+	},
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+	{
+		.family		= AF_INET6,
+		.name		= "TCPMSS",
+		.checkentry	= xt_tcpmss_checkentry6,
+		.target		= xt_tcpmss_target6,
+		.targetsize	= sizeof(struct xt_tcpmss_info),
+		.proto		= IPPROTO_TCP,
+		.me		= THIS_MODULE,
+	},
+#endif
+};
+
+static int __init xt_tcpmss_init(void)
+{
+	return xt_register_targets(xt_tcpmss_reg, ARRAY_SIZE(xt_tcpmss_reg));
+}
+
+static void __exit xt_tcpmss_fini(void)
+{
+	xt_unregister_targets(xt_tcpmss_reg, ARRAY_SIZE(xt_tcpmss_reg));
+}
+
+module_init(xt_tcpmss_init);
+module_exit(xt_tcpmss_fini);
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 3dc2357..2885c37 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -51,10 +51,10 @@
 	if (ct == &ip_conntrack_untracked)
 		statebit = XT_CONNTRACK_STATE_UNTRACKED;
 	else if (ct)
- 		statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
- 	else
- 		statebit = XT_CONNTRACK_STATE_INVALID;
- 
+		statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
+	else
+		statebit = XT_CONNTRACK_STATE_INVALID;
+
 	if (sinfo->flags & XT_CONNTRACK_STATE) {
 		if (ct) {
 			if (test_bit(IPS_SRC_NAT_BIT, &ct->status))
@@ -77,7 +77,7 @@
 	    FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
 		  sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
 		  XT_CONNTRACK_PROTO))
-                return 0;
+		return 0;
 
 	if (sinfo->flags & XT_CONNTRACK_ORIGSRC &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip &
@@ -147,10 +147,10 @@
 	if (ct == &nf_conntrack_untracked)
 		statebit = XT_CONNTRACK_STATE_UNTRACKED;
 	else if (ct)
- 		statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
- 	else
- 		statebit = XT_CONNTRACK_STATE_INVALID;
- 
+		statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
+	else
+		statebit = XT_CONNTRACK_STATE_INVALID;
+
 	if (sinfo->flags & XT_CONNTRACK_STATE) {
 		if (ct) {
 			if (test_bit(IPS_SRC_NAT_BIT, &ct->status))
@@ -171,41 +171,41 @@
 
 	if (sinfo->flags & XT_CONNTRACK_PROTO &&
 	    FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
-	    	  sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
+		  sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
 		  XT_CONNTRACK_PROTO))
-                return 0;
+		return 0;
 
 	if (sinfo->flags & XT_CONNTRACK_ORIGSRC &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip &
-	    	   sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
+		   sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
 		  XT_CONNTRACK_ORIGSRC))
 		return 0;
 
 	if (sinfo->flags & XT_CONNTRACK_ORIGDST &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip &
-	    	   sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
+		   sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
 		  XT_CONNTRACK_ORIGDST))
 		return 0;
 
 	if (sinfo->flags & XT_CONNTRACK_REPLSRC &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip &
-	    	   sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) !=
+		   sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
 		  XT_CONNTRACK_REPLSRC))
 		return 0;
 
 	if (sinfo->flags & XT_CONNTRACK_REPLDST &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip &
-	    	   sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) !=
+		   sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
 		  XT_CONNTRACK_REPLDST))
 		return 0;
 
 	if (sinfo->flags & XT_CONNTRACK_STATUS &&
 	    FWINV((ct->status & sinfo->statusmask) == 0,
-	    	  XT_CONNTRACK_STATUS))
+		  XT_CONNTRACK_STATUS))
 		return 0;
 
 	if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 3e6cf43..2c9c0de 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -26,7 +26,7 @@
 MODULE_ALIAS("ipt_dccp");
 
 #define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
-		                  || (!!((invflag) & (option)) ^ (cond)))
+				  || (!!((invflag) & (option)) ^ (cond)))
 
 static unsigned char *dccp_optbuf;
 static DEFINE_SPINLOCK(dccp_buflock);
@@ -67,9 +67,9 @@
 			return 1;
 		}
 
-		if (op[i] < 2) 
+		if (op[i] < 2)
 			i++;
-		else 
+		else
 			i += op[i+1]?:1;
 	}
 
@@ -106,18 +106,18 @@
 
 	if (offset)
 		return 0;
-	
+
 	dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh);
 	if (dh == NULL) {
 		*hotdrop = 1;
 		return 0;
-       	}
+	}
 
-	return  DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) 
-			&& (ntohs(dh->dccph_sport) <= info->spts[1])), 
-		   	XT_DCCP_SRC_PORTS, info->flags, info->invflags)
-		&& DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) 
-			&& (ntohs(dh->dccph_dport) <= info->dpts[1])), 
+	return  DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0])
+			&& (ntohs(dh->dccph_sport) <= info->spts[1])),
+			XT_DCCP_SRC_PORTS, info->flags, info->invflags)
+		&& DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0])
+			&& (ntohs(dh->dccph_dport) <= info->dpts[1])),
 			XT_DCCP_DEST_PORTS, info->flags, info->invflags)
 		&& DCCHECK(match_types(dh, info->typemask),
 			   XT_DCCP_TYPE, info->flags, info->invflags)
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index f28bf69..9f37d59 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -37,7 +37,7 @@
 /* need to declare this at the top */
 static struct proc_dir_entry *hashlimit_procdir4;
 static struct proc_dir_entry *hashlimit_procdir6;
-static struct file_operations dl_file_ops;
+static const struct file_operations dl_file_ops;
 
 /* hash table crap */
 struct dsthash_dst {
@@ -208,7 +208,7 @@
 	spin_lock_init(&hinfo->lock);
 	hinfo->pde = create_proc_entry(minfo->name, 0,
 				       family == AF_INET ? hashlimit_procdir4 :
-				       			   hashlimit_procdir6);
+							   hashlimit_procdir6);
 	if (!hinfo->pde) {
 		vfree(hinfo);
 		return -1;
@@ -240,7 +240,7 @@
 }
 
 static void htable_selective_cleanup(struct xt_hashlimit_htable *ht,
-		 		int (*select)(struct xt_hashlimit_htable *ht,
+				int (*select)(struct xt_hashlimit_htable *ht,
 					      struct dsthash_ent *he))
 {
 	unsigned int i;
@@ -279,7 +279,7 @@
 	/* remove proc entry */
 	remove_proc_entry(hinfo->pde->name,
 			  hinfo->family == AF_INET ? hashlimit_procdir4 :
-			  			     hashlimit_procdir6);
+						     hashlimit_procdir6);
 	htable_selective_cleanup(hinfo, select_all);
 	vfree(hinfo);
 }
@@ -414,6 +414,7 @@
 	switch (nexthdr) {
 	case IPPROTO_TCP:
 	case IPPROTO_UDP:
+	case IPPROTO_UDPLITE:
 	case IPPROTO_SCTP:
 	case IPPROTO_DCCP:
 		ports = skb_header_pointer(skb, protoff, sizeof(_ports),
@@ -482,7 +483,7 @@
 		return 1;
 	}
 
-       	spin_unlock_bh(&hinfo->lock);
+	spin_unlock_bh(&hinfo->lock);
 
 	/* default case: we're overlimit, thus don't match */
 	return 0;
@@ -713,7 +714,7 @@
 	return ret;
 }
 
-static struct file_operations dl_file_ops = {
+static const struct file_operations dl_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = dl_proc_open,
 	.read    = seq_read,
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 04bc32b..407d1d5 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -53,7 +53,7 @@
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
 	int ret = info->invert;
-	
+
 	ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
 	if (!ct) {
 		DEBUGP("xt_helper: Eek! invalid conntrack?\n");
@@ -67,19 +67,19 @@
 
 	read_lock_bh(&ip_conntrack_lock);
 	if (!ct->master->helper) {
-		DEBUGP("xt_helper: master ct %p has no helper\n", 
+		DEBUGP("xt_helper: master ct %p has no helper\n",
 			exp->expectant);
 		goto out_unlock;
 	}
 
-	DEBUGP("master's name = %s , info->name = %s\n", 
+	DEBUGP("master's name = %s , info->name = %s\n",
 		ct->master->helper->name, info->name);
 
 	if (info->name[0] == '\0')
 		ret ^= 1;
 	else
-		ret ^= !strncmp(ct->master->helper->name, info->name, 
-		                strlen(ct->master->helper->name));
+		ret ^= !strncmp(ct->master->helper->name, info->name,
+				strlen(ct->master->helper->name));
 out_unlock:
 	read_unlock_bh(&ip_conntrack_lock);
 	return ret;
@@ -102,7 +102,7 @@
 	struct nf_conn_help *master_help;
 	enum ip_conntrack_info ctinfo;
 	int ret = info->invert;
-	
+
 	ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
 	if (!ct) {
 		DEBUGP("xt_helper: Eek! invalid conntrack?\n");
@@ -117,19 +117,19 @@
 	read_lock_bh(&nf_conntrack_lock);
 	master_help = nfct_help(ct->master);
 	if (!master_help || !master_help->helper) {
-		DEBUGP("xt_helper: master ct %p has no helper\n", 
+		DEBUGP("xt_helper: master ct %p has no helper\n",
 			exp->expectant);
 		goto out_unlock;
 	}
 
-	DEBUGP("master's name = %s , info->name = %s\n", 
+	DEBUGP("master's name = %s , info->name = %s\n",
 		ct->master->helper->name, info->name);
 
 	if (info->name[0] == '\0')
 		ret ^= 1;
 	else
 		ret ^= !strncmp(master_help->helper->name, info->name,
-		                strlen(master_help->helper->name));
+				strlen(master_help->helper->name));
 out_unlock:
 	read_unlock_bh(&nf_conntrack_lock);
 	return ret;
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 67fd30d..32fb998 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -32,7 +32,7 @@
 {
 	const struct xt_length_info *info = matchinfo;
 	u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);
-	
+
 	return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
 }
 
@@ -48,7 +48,7 @@
 {
 	const struct xt_length_info *info = matchinfo;
 	u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr);
-	
+
 	return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
 }
 
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index fda7b7d..6fd8347 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -89,7 +89,7 @@
 		return 1;
 	}
 
-       	spin_unlock_bh(&limit_lock);
+	spin_unlock_bh(&limit_lock);
 	return 0;
 }
 
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index 425fc21..d430d90 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -14,6 +14,7 @@
 #include <linux/etherdevice.h>
 
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
 #include <linux/netfilter/xt_mac.h>
 #include <linux/netfilter/x_tables.h>
 
@@ -59,9 +60,9 @@
 		.family		= AF_INET6,
 		.match		= match,
 		.matchsize	= sizeof(struct xt_mac_info),
-		.hooks		= (1 << NF_IP_PRE_ROUTING) |
-				  (1 << NF_IP_LOCAL_IN) |
-				  (1 << NF_IP_FORWARD),
+		.hooks		= (1 << NF_IP6_PRE_ROUTING) |
+				  (1 << NF_IP6_LOCAL_IN) |
+				  (1 << NF_IP6_FORWARD),
 		.me		= THIS_MODULE,
 	},
 };
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index dfa1ee6..39911dd 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -36,10 +36,10 @@
 
 static int
 checkentry(const char *tablename,
-           const void *entry,
+	   const void *entry,
 	   const struct xt_match *match,
-           void *matchinfo,
-           unsigned int hook_mask)
+	   void *matchinfo,
+	   unsigned int hook_mask)
 {
 	const struct xt_mark_info *minfo = matchinfo;
 
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index 1602086..4dce2a8 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -91,7 +91,7 @@
 		}
 	}
 
- 	return minfo->invert;
+	return minfo->invert;
 }
 
 static int
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index b9b3ffc..35a0fe2 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -117,7 +117,7 @@
 	    (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
 	     info->invert & XT_PHYSDEV_OP_BRIDGED) &&
 	    hook_mask & ((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
-	                 (1 << NF_IP_POST_ROUTING))) {
+			 (1 << NF_IP_POST_ROUTING))) {
 		printk(KERN_WARNING "physdev match: using --physdev-out in the "
 		       "OUTPUT, FORWARD and POSTROUTING chains for non-bridged "
 		       "traffic is not supported anymore.\n");
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 46bde2b..15b45a9 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -109,13 +109,13 @@
 }
 
 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)
+		 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)
 {
 	const struct xt_policy_info *info = matchinfo;
 	int ret;
@@ -134,27 +134,27 @@
 }
 
 static int checkentry(const char *tablename, const void *ip_void,
-                      const struct xt_match *match,
-                      void *matchinfo, unsigned int hook_mask)
+		      const struct xt_match *match,
+		      void *matchinfo, unsigned int hook_mask)
 {
 	struct xt_policy_info *info = matchinfo;
 
 	if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
 		printk(KERN_ERR "xt_policy: neither incoming nor "
-		                "outgoing policy selected\n");
+				"outgoing policy selected\n");
 		return 0;
 	}
 	/* hook values are equal for IPv4 and IPv6 */
 	if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
 	    && info->flags & XT_POLICY_MATCH_OUT) {
 		printk(KERN_ERR "xt_policy: output policy not valid in "
-		                "PRE_ROUTING and INPUT\n");
+				"PRE_ROUTING and INPUT\n");
 		return 0;
 	}
 	if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
 	    && info->flags & XT_POLICY_MATCH_IN) {
 		printk(KERN_ERR "xt_policy: input policy not valid in "
-		                "POST_ROUTING and OUTPUT\n");
+				"POST_ROUTING and OUTPUT\n");
 		return 0;
 	}
 	if (info->len > XT_POLICY_MAX_ELEM) {
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
index b75fa2c..bfdde06 100644
--- a/net/netfilter/xt_quota.c
+++ b/net/netfilter/xt_quota.c
@@ -30,8 +30,8 @@
 		q->quota -= skb->len;
 		ret ^= 1;
 	} else {
-	        /* we do not allow even small packets from now on */
-	        q->quota = 0;
+		/* we do not allow even small packets from now on */
+		q->quota = 0;
 	}
 	spin_unlock_bh(&quota_lock);
 
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index a80b7d13..97ffc2f 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -35,7 +35,7 @@
 {
 	const struct xt_realm_info *info = matchinfo;
 	struct dst_entry *dst = skb->dst;
-    
+
 	return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
 }
 
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index 71bf036..f86d8d7 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -66,9 +66,9 @@
 			duprintf("Dropping invalid SCTP packet.\n");
 			*hotdrop = 1;
 			return 0;
-        	}
+		}
 
-		duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", 
+		duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
 				++i, offset, sch->type, htons(sch->length), sch->flags);
 
 		offset += (ntohs(sch->length) + 3) & ~3;
@@ -78,21 +78,21 @@
 		if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch->type)) {
 			switch (chunk_match_type) {
 			case SCTP_CHUNK_MATCH_ANY:
-				if (match_flags(flag_info, flag_count, 
+				if (match_flags(flag_info, flag_count,
 					sch->type, sch->flags)) {
 					return 1;
 				}
 				break;
 
 			case SCTP_CHUNK_MATCH_ALL:
-				if (match_flags(flag_info, flag_count, 
+				if (match_flags(flag_info, flag_count,
 					sch->type, sch->flags)) {
 					SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type);
 				}
 				break;
 
 			case SCTP_CHUNK_MATCH_ONLY:
-				if (!match_flags(flag_info, flag_count, 
+				if (!match_flags(flag_info, flag_count,
 					sch->type, sch->flags)) {
 					return 0;
 				}
@@ -136,24 +136,24 @@
 		duprintf("Dropping non-first fragment.. FIXME\n");
 		return 0;
 	}
-	
+
 	sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh);
 	if (sh == NULL) {
 		duprintf("Dropping evil TCP offset=0 tinygram.\n");
 		*hotdrop = 1;
 		return 0;
-       	}
+	}
 	duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest));
 
-	return  SCCHECK(((ntohs(sh->source) >= info->spts[0]) 
-			&& (ntohs(sh->source) <= info->spts[1])), 
-		   	XT_SCTP_SRC_PORTS, info->flags, info->invflags)
-		&& SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) 
-			&& (ntohs(sh->dest) <= info->dpts[1])), 
+	return  SCCHECK(((ntohs(sh->source) >= info->spts[0])
+			&& (ntohs(sh->source) <= info->spts[1])),
+			XT_SCTP_SRC_PORTS, info->flags, info->invflags)
+		&& SCCHECK(((ntohs(sh->dest) >= info->dpts[0])
+			&& (ntohs(sh->dest) <= info->dpts[1])),
 			XT_SCTP_DEST_PORTS, info->flags, info->invflags)
 		&& SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t),
 					info->chunkmap, info->chunk_match_type,
- 					info->flag_info, info->flag_count, 
+					info->flag_info, info->flag_count,
 					hotdrop),
 			   XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
 }
@@ -170,9 +170,9 @@
 	return !(info->flags & ~XT_SCTP_VALID_FLAGS)
 		&& !(info->invflags & ~XT_SCTP_VALID_FLAGS)
 		&& !(info->invflags & ~info->flags)
-		&& ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || 
+		&& ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
 			(info->chunk_match_type &
-				(SCTP_CHUNK_MATCH_ALL 
+				(SCTP_CHUNK_MATCH_ALL
 				| SCTP_CHUNK_MATCH_ANY
 				| SCTP_CHUNK_MATCH_ONLY)));
 }
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 4453252..999a005 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -1,5 +1,5 @@
 /* String matching match for iptables
- * 
+ *
  * (C) 2005 Pablo Neira Ayuso <pablo@eurodev.net>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -35,8 +35,8 @@
 
 	memset(&state, 0, sizeof(struct ts_state));
 
-	return (skb_find_text((struct sk_buff *)skb, conf->from_offset, 
-			     conf->to_offset, conf->config, &state) 
+	return (skb_find_text((struct sk_buff *)skb, conf->from_offset,
+			     conf->to_offset, conf->config, &state)
 			     != UINT_MAX) ^ conf->invert;
 }
 
@@ -55,7 +55,7 @@
 	if (conf->from_offset > conf->to_offset)
 		return 0;
 	if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0')
-	    	return 0;
+		return 0;
 	if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE)
 		return 0;
 	ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index a3682fe..80571d0 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -64,9 +64,9 @@
 			u_int16_t mssval;
 
 			mssval = (op[i+2] << 8) | op[i+3];
-			
+
 			return (mssval >= info->mss_min &&
-			        mssval <= info->mss_max) ^ info->invert;
+				mssval <= info->mss_max) ^ info->invert;
 		}
 		if (op[i] < 2)
 			i++;
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index 73e0ff4..07e47db 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -292,7 +292,7 @@
 					}
 			}
 		doi_def->map.std->cat.local = kcalloc(
-			                      doi_def->map.std->cat.local_size,
+					      doi_def->map.std->cat.local_size,
 					      sizeof(u32),
 					      GFP_KERNEL);
 		if (doi_def->map.std->cat.local == NULL) {
@@ -300,7 +300,7 @@
 			goto add_std_failure;
 		}
 		doi_def->map.std->cat.cipso = kcalloc(
-			                      doi_def->map.std->cat.cipso_size,
+					      doi_def->map.std->cat.cipso_size,
 					      sizeof(u32),
 					      GFP_KERNEL);
 		if (doi_def->map.std->cat.cipso == NULL) {
@@ -325,10 +325,10 @@
 				if (cat_loc == NULL || cat_rem == NULL)
 					goto add_std_failure;
 				doi_def->map.std->cat.local[
-				                        nla_get_u32(cat_loc)] =
+							nla_get_u32(cat_loc)] =
 					nla_get_u32(cat_rem);
 				doi_def->map.std->cat.cipso[
-					                nla_get_u32(cat_rem)] =
+							nla_get_u32(cat_rem)] =
 					nla_get_u32(cat_loc);
 			}
 	}
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 383dd4e..e73d8f5 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -8,7 +8,7 @@
  *		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.
- * 
+ *
  * Tue Jun 26 14:36:48 MEST 2001 Herbert "herp" Rosmanith
  *                               added netlink_proto_exit
  * Tue Jan 22 18:32:44 BRST 2002 Arnaldo C. de Melo <acme@conectiva.com.br>
@@ -470,7 +470,7 @@
 					  };
 		atomic_notifier_call_chain(&netlink_chain,
 				NETLINK_URELEASE, &n);
-	}	
+	}
 
 	module_put(nlk->module);
 
@@ -528,11 +528,11 @@
 	return err;
 }
 
-static inline int netlink_capable(struct socket *sock, unsigned int flag) 
-{ 
+static inline int netlink_capable(struct socket *sock, unsigned int flag)
+{
 	return (nl_table[sock->sk->sk_protocol].nl_nonroot & flag) ||
 	       capable(CAP_NET_ADMIN);
-} 
+}
 
 static void
 netlink_update_subscriptions(struct sock *sk, unsigned int subscriptions)
@@ -574,7 +574,7 @@
 	struct netlink_sock *nlk = nlk_sk(sk);
 	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
 	int err;
-	
+
 	if (nladdr->nl_family != AF_NETLINK)
 		return -EINVAL;
 
@@ -605,9 +605,9 @@
 
 	netlink_table_grab();
 	netlink_update_subscriptions(sk, nlk->subscriptions +
-	                                 hweight32(nladdr->nl_groups) -
-	                                 hweight32(nlk->groups[0]));
-	nlk->groups[0] = (nlk->groups[0] & ~0xffffffffUL) | nladdr->nl_groups; 
+					 hweight32(nladdr->nl_groups) -
+					 hweight32(nlk->groups[0]));
+	nlk->groups[0] = (nlk->groups[0] & ~0xffffffffUL) | nladdr->nl_groups;
 	netlink_update_listeners(sk);
 	netlink_table_ungrab();
 
@@ -652,7 +652,7 @@
 	struct sock *sk = sock->sk;
 	struct netlink_sock *nlk = nlk_sk(sk);
 	struct sockaddr_nl *nladdr=(struct sockaddr_nl *)addr;
-	
+
 	nladdr->nl_family = AF_NETLINK;
 	nladdr->nl_pad = 0;
 	*addr_len = sizeof(*nladdr);
@@ -999,7 +999,7 @@
 }
 
 static int netlink_setsockopt(struct socket *sock, int level, int optname,
-                              char __user *optval, int optlen)
+			      char __user *optval, int optlen)
 {
 	struct sock *sk = sock->sk;
 	struct netlink_sock *nlk = nlk_sk(sk);
@@ -1054,7 +1054,7 @@
 }
 
 static int netlink_getsockopt(struct socket *sock, int level, int optname,
-                              char __user *optval, int __user *optlen)
+			      char __user *optval, int __user *optlen)
 {
 	struct sock *sk = sock->sk;
 	struct netlink_sock *nlk = nlk_sk(sk);
@@ -1257,15 +1257,15 @@
 }
 
 /*
- *	We export these functions to other modules. They provide a 
+ *	We export these functions to other modules. They provide a
  *	complete set of kernel non-blocking support for message
  *	queueing.
  */
 
 struct sock *
 netlink_kernel_create(int unit, unsigned int groups,
-                      void (*input)(struct sock *sk, int len),
-                      struct module *module)
+		      void (*input)(struct sock *sk, int len),
+		      struct module *module)
 {
 	struct socket *sock;
 	struct sock *sk;
@@ -1317,10 +1317,10 @@
 }
 
 void netlink_set_nonroot(int protocol, unsigned int flags)
-{ 
-	if ((unsigned int)protocol < MAX_LINKS) 
+{
+	if ((unsigned int)protocol < MAX_LINKS)
 		nl_table[protocol].nl_nonroot = flags;
-} 
+}
 
 static void netlink_destroy_callback(struct netlink_callback *cb)
 {
@@ -1341,7 +1341,7 @@
 	struct sk_buff *skb;
 	struct nlmsghdr *nlh;
 	int len, err = -ENOBUFS;
-	
+
 	skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL);
 	if (!skb)
 		goto errout;
@@ -1626,7 +1626,7 @@
 
 	if (v == SEQ_START_TOKEN)
 		return netlink_seq_socket_idx(seq, 0);
-		
+
 	s = sk_next(v);
 	if (s)
 		return s;
@@ -1713,7 +1713,7 @@
 	return 0;
 }
 
-static struct file_operations netlink_seq_fops = {
+static const struct file_operations netlink_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= netlink_seq_open,
 	.read		= seq_read,
@@ -1732,7 +1732,7 @@
 {
 	return atomic_notifier_chain_unregister(&netlink_chain, nb);
 }
-                
+
 static const struct proto_ops netlink_ops = {
 	.family =	PF_NETLINK,
 	.owner =	THIS_MODULE,
@@ -1808,7 +1808,7 @@
 #ifdef CONFIG_PROC_FS
 	proc_net_fops_create("netlink", 0, &netlink_seq_fops);
 #endif
-	/* The netlink device handler may be needed early. */ 
+	/* The netlink device handler may be needed early. */
 	rtnetlink_init();
 out:
 	return err;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 548e4e6..c299679 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -310,7 +310,7 @@
 	if (nlh->nlmsg_type < NLMSG_MIN_TYPE)
 		goto ignore;
 
-       	family = genl_family_find_byid(nlh->nlmsg_type);
+	family = genl_family_find_byid(nlh->nlmsg_type);
 	if (family == NULL) {
 		err = -ENOENT;
 		goto errout;
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 43bbe2c..bf9837d 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -110,7 +110,7 @@
 
 	nr_kill_by_device(dev);
 	nr_rt_device_down(dev);
-	
+
 	return NOTIFY_DONE;
 }
 
@@ -137,7 +137,7 @@
 	sk_for_each(s, node, &nr_list)
 		if (!ax25cmp(&nr_sk(s)->source_addr, addr) &&
 		    s->sk_state == TCP_LISTEN) {
-		    	bh_lock_sock(s);
+			bh_lock_sock(s);
 			goto found;
 		}
 	s = NULL;
@@ -157,7 +157,7 @@
 	spin_lock_bh(&nr_list_lock);
 	sk_for_each(s, node, &nr_list) {
 		struct nr_sock *nr = nr_sk(s);
-		
+
 		if (nr->my_index == index && nr->my_id == id) {
 			bh_lock_sock(s);
 			goto found;
@@ -181,10 +181,10 @@
 	spin_lock_bh(&nr_list_lock);
 	sk_for_each(s, node, &nr_list) {
 		struct nr_sock *nr = nr_sk(s);
-		
+
 		if (nr->your_index == index && nr->your_id == id &&
 		    !ax25cmp(&nr->dest_addr, dest)) {
-		    	bh_lock_sock(s);
+			bh_lock_sock(s);
 			goto found;
 		}
 	}
@@ -341,17 +341,17 @@
 	struct sock *sk = sock->sk;
 	struct nr_sock *nr = nr_sk(sk);
 	int val = 0;
-	int len; 
+	int len;
 
 	if (level != SOL_NETROM)
 		return -ENOPROTOOPT;
-	
+
 	if (get_user(len, optlen))
 		return -EFAULT;
 
 	if (len < 0)
 		return -EINVAL;
-		
+
 	switch (optname) {
 	case NETROM_T1:
 		val = nr->t1 / HZ;
@@ -537,7 +537,7 @@
 		break;
 	}
 
-	sock->sk   = NULL;	
+	sock->sk   = NULL;
 	release_sock(sk);
 	sock_put(sk);
 
@@ -644,7 +644,7 @@
 		return -EISCONN;	/* No reconnect on a seqpacket socket */
 	}
 
-	sk->sk_state   = TCP_CLOSE;	
+	sk->sk_state   = TCP_CLOSE;
 	sock->state = SS_UNCONNECTED;
 
 	if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) {
@@ -710,7 +710,7 @@
 		release_sock(sk);
 		return -EINPROGRESS;
 	}
-		
+
 	/*
 	 * A Connect Ack with Choke or timeout or failed routing will go to
 	 * closed.
@@ -848,7 +848,7 @@
 int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sock *sk;
-	struct sock *make;	
+	struct sock *make;
 	struct nr_sock *nr_make;
 	ax25_address *src, *dest, *user;
 	unsigned short circuit_index, circuit_id;
@@ -1258,10 +1258,10 @@
 {
 	++*pos;
 
-	return (v == SEQ_START_TOKEN) ? sk_head(&nr_list) 
+	return (v == SEQ_START_TOKEN) ? sk_head(&nr_list)
 		: sk_next((struct sock *)v);
 }
-	
+
 static void nr_info_stop(struct seq_file *seq, void *v)
 {
 	spin_unlock_bh(&nr_list_lock);
@@ -1291,7 +1291,7 @@
 
 		seq_printf(seq, "%-9s ", ax2asc(buf, &nr->user_addr));
 		seq_printf(seq, "%-9s ", ax2asc(buf, &nr->dest_addr));
-		seq_printf(seq, 
+		seq_printf(seq,
 "%-9s %-3s  %02X/%02X %02X/%02X %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3d %5d %5d %ld\n",
 			ax2asc(buf, &nr->source_addr),
 			devname,
@@ -1329,13 +1329,13 @@
 	.stop = nr_info_stop,
 	.show = nr_info_show,
 };
- 
+
 static int nr_info_open(struct inode *inode, struct file *file)
 {
 	return seq_open(file, &nr_info_seqops);
 }
- 
-static struct file_operations nr_info_fops = {
+
+static const struct file_operations nr_info_fops = {
 	.owner = THIS_MODULE,
 	.open = nr_info_open,
 	.read = seq_read,
@@ -1415,7 +1415,7 @@
 			printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n");
 			goto fail;
 		}
-		
+
 		dev->base_addr = i;
 		if (register_netdev(dev)) {
 			printk(KERN_ERR "NET/ROM: nr_proto_init - unable to register network device\n");
@@ -1430,7 +1430,7 @@
 		printk(KERN_ERR "NET/ROM: nr_proto_init - unable to register socket family\n");
 		goto fail;
 	}
-		
+
 	register_netdevice_notifier(&nr_dev_notifier);
 
 	ax25_register_pid(&nr_pid);
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c
index 4700d52..9a97ed6 100644
--- a/net/netrom/nr_dev.c
+++ b/net/netrom/nr_dev.c
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/fs.h>
 #include <linux/types.h>
diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c
index a7d88b5..5560acb 100644
--- a/net/netrom/nr_in.c
+++ b/net/netrom/nr_in.c
@@ -12,7 +12,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c
index 7939ded..0cbfb61 100644
--- a/net/netrom/nr_out.c
+++ b/net/netrom/nr_out.c
@@ -12,7 +12,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 8f88964..8e6bd4e 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -13,7 +13,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -781,8 +780,8 @@
 
 	if (ax25 != NULL) {
 		ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
-		                  ax25->ax25_dev->dev, 0,
-		                  sysctl_netrom_obsolescence_count_initialiser);
+				  ax25->ax25_dev->dev, 0,
+				  sysctl_netrom_obsolescence_count_initialiser);
 		if (ret)
 			return ret;
 	}
@@ -861,8 +860,8 @@
 	struct nr_node *nr_node;
 	struct hlist_node *node;
 	int i = 1;
- 
- 	spin_lock_bh(&nr_node_list_lock);
+
+	spin_lock_bh(&nr_node_list_lock);
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
@@ -879,8 +878,8 @@
 {
 	struct hlist_node *node;
 	++*pos;
-	
-	node = (v == SEQ_START_TOKEN)  
+
+	node = (v == SEQ_START_TOKEN)
 		? nr_node_list.first
 		: ((struct nr_node *)v)->node_node.next;
 
@@ -934,7 +933,7 @@
 	return seq_open(file, &nr_node_seqops);
 }
 
-struct file_operations nr_nodes_fops = {
+const struct file_operations nr_nodes_fops = {
 	.owner = THIS_MODULE,
 	.open = nr_node_info_open,
 	.read = seq_read,
@@ -963,8 +962,8 @@
 {
 	struct hlist_node *node;
 	++*pos;
-	
-	node = (v == SEQ_START_TOKEN)  
+
+	node = (v == SEQ_START_TOKEN)
 		? nr_neigh_list.first
 		: ((struct nr_neigh *)v)->neigh_node.next;
 
@@ -997,7 +996,7 @@
 
 		if (nr_neigh->digipeat != NULL) {
 			for (i = 0; i < nr_neigh->digipeat->ndigi; i++)
-				seq_printf(seq, " %s", 
+				seq_printf(seq, " %s",
 					   ax2asc(buf, &nr_neigh->digipeat->calls[i]));
 		}
 
@@ -1018,7 +1017,7 @@
 	return seq_open(file, &nr_neigh_seqops);
 }
 
-struct file_operations nr_neigh_fops = {
+const struct file_operations nr_neigh_fops = {
 	.owner = THIS_MODULE,
 	.open = nr_neigh_info_open,
 	.read = seq_read,
diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c
index bcb9946..07b694d 100644
--- a/net/netrom/nr_subr.c
+++ b/net/netrom/nr_subr.c
@@ -11,7 +11,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -57,7 +56,7 @@
 	 */
 	if (nrom->va != nr) {
 		while (skb_peek(&nrom->ack_queue) != NULL && nrom->va != nr) {
-		        skb = skb_dequeue(&nrom->ack_queue);
+			skb = skb_dequeue(&nrom->ack_queue);
 			kfree_skb(skb);
 			nrom->va = (nrom->va + 1) % NR_MODULUS;
 		}
diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
index ddba1c1..6cfaad9 100644
--- a/net/netrom/nr_timer.c
+++ b/net/netrom/nr_timer.c
@@ -43,7 +43,7 @@
 	init_timer(&nr->t1timer);
 	nr->t1timer.data     = (unsigned long)sk;
 	nr->t1timer.function = &nr_t1timer_expiry;
-	
+
 	init_timer(&nr->t2timer);
 	nr->t2timer.data     = (unsigned long)sk;
 	nr->t2timer.function = &nr_t2timer_expiry;
diff --git a/net/netrom/sysctl_net_netrom.c b/net/netrom/sysctl_net_netrom.c
index 6bb8dda..2ea68da 100644
--- a/net/netrom/sysctl_net_netrom.c
+++ b/net/netrom/sysctl_net_netrom.c
@@ -35,7 +35,7 @@
 static struct ctl_table_header *nr_table_header;
 
 static ctl_table nr_table[] = {
-        {
+	{
 		.ctl_name	= NET_NETROM_DEFAULT_PATH_QUALITY,
 		.procname	= "default_path_quality",
 		.data		= &sysctl_netrom_default_path_quality,
@@ -46,18 +46,18 @@
 		.extra1		= &min_quality,
 		.extra2		= &max_quality
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER,
 		.procname	= "obsolescence_count_initialiser",
 		.data		= &sysctl_netrom_obsolescence_count_initialiser,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
- 		.proc_handler	= &proc_dointvec_minmax,
+		.proc_handler	= &proc_dointvec_minmax,
 		.strategy	= &sysctl_intvec,
 		.extra1		= &min_obs,
 		.extra2		= &max_obs
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_NETWORK_TTL_INITIALISER,
 		.procname	= "network_ttl_initialiser",
 		.data		= &sysctl_netrom_network_ttl_initialiser,
@@ -68,7 +68,7 @@
 		.extra1		= &min_ttl,
 		.extra2		= &max_ttl
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_TRANSPORT_TIMEOUT,
 		.procname	= "transport_timeout",
 		.data		= &sysctl_netrom_transport_timeout,
@@ -79,7 +79,7 @@
 		.extra1		= &min_t1,
 		.extra2		= &max_t1
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_TRANSPORT_MAXIMUM_TRIES,
 		.procname	= "transport_maximum_tries",
 		.data		= &sysctl_netrom_transport_maximum_tries,
@@ -90,7 +90,7 @@
 		.extra1		= &min_n2,
 		.extra2		= &max_n2
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY,
 		.procname	= "transport_acknowledge_delay",
 		.data		= &sysctl_netrom_transport_acknowledge_delay,
@@ -101,7 +101,7 @@
 		.extra1		= &min_t2,
 		.extra2		= &max_t2
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_TRANSPORT_BUSY_DELAY,
 		.procname	= "transport_busy_delay",
 		.data		= &sysctl_netrom_transport_busy_delay,
@@ -112,7 +112,7 @@
 		.extra1		= &min_t4,
 		.extra2		= &max_t4
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE,
 		.procname	= "transport_requested_window_size",
 		.data		= &sysctl_netrom_transport_requested_window_size,
@@ -123,7 +123,7 @@
 		.extra1		= &min_window,
 		.extra2		= &max_window
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT,
 		.procname	= "transport_no_activity_timeout",
 		.data		= &sysctl_netrom_transport_no_activity_timeout,
@@ -134,7 +134,7 @@
 		.extra1		= &min_idle,
 		.extra2		= &max_idle
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_ROUTING_CONTROL,
 		.procname	= "routing_control",
 		.data		= &sysctl_netrom_routing_control,
@@ -145,7 +145,7 @@
 		.extra1		= &min_route,
 		.extra2		= &max_route
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_LINK_FAILS_COUNT,
 		.procname	= "link_fails_count",
 		.data		= &sysctl_netrom_link_fails_count,
@@ -156,7 +156,7 @@
 		.extra1		= &min_fails,
 		.extra2		= &max_fails
 	},
-        {
+	{
 		.ctl_name	= NET_NETROM_RESET,
 		.procname	= "reset",
 		.data		= &sysctl_netrom_reset_circuit,
@@ -192,7 +192,7 @@
 
 void __init nr_register_sysctl(void)
 {
-	nr_table_header = register_sysctl_table(nr_root_table, 1);
+	nr_table_header = register_sysctl_table(nr_root_table);
 }
 
 void nr_unregister_sysctl(void)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 6dc01bd..bf26990 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -11,7 +11,7 @@
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Alan Cox, <gw4pts@gw4pts.ampr.org>
  *
- * Fixes:	
+ * Fixes:
  *		Alan Cox	:	verify_area() now used correctly
  *		Alan Cox	:	new skbuff lists, look ma no backlogs!
  *		Alan Cox	:	tidied skbuff lists.
@@ -34,12 +34,12 @@
  *	Alexey Kuznetsov	:	Untied from IPv4 stack.
  *	Cyrus Durgin		:	Fixed kerneld for kmod.
  *	Michal Ostrowski        :       Module initialization cleanup.
- *         Ulises Alonso        :       Frame number limit removal and 
+ *         Ulises Alonso        :       Frame number limit removal and
  *                                      packet_set_ring memory leak.
  *		Eric Biederman	:	Allow for > 8 byte hardware addresses.
  *					The convention is that longer addresses
  *					will simply extend the hardware address
- *					byte arrays at the end of sockaddr_ll 
+ *					byte arrays at the end of sockaddr_ll
  *					and packet_mreq.
  *
  *		This program is free software; you can redistribute it and/or
@@ -48,9 +48,8 @@
  *		2 of the License, or (at your option) any later version.
  *
  */
- 
+
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/capability.h>
 #include <linux/fcntl.h>
@@ -60,6 +59,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_packet.h>
 #include <linux/wireless.h>
+#include <linux/kernel.h>
 #include <linux/kmod.h>
 #include <net/ip.h>
 #include <net/protocol.h>
@@ -123,7 +123,7 @@
 
 Incoming, dev->hard_header==NULL
    mac.raw -> UNKNOWN position. It is very likely, that it points to ll header.
-              PPP makes it, that is wrong, because introduce assymetry
+	      PPP makes it, that is wrong, because introduce assymetry
 	      between rx and tx paths.
    data    -> data
 
@@ -200,7 +200,8 @@
 #endif
 	struct packet_type	prot_hook;
 	spinlock_t		bind_lock;
-	char			running;	/* prot_hook is attached*/
+	unsigned int		running:1,	/* prot_hook is attached*/
+				auxdata:1;
 	int			ifindex;	/* bound device		*/
 	__be16			num;
 #ifdef CONFIG_PACKET_MULTICAST
@@ -214,6 +215,16 @@
 #endif
 };
 
+struct packet_skb_cb {
+	unsigned int origlen;
+	union {
+		struct sockaddr_pkt pkt;
+		struct sockaddr_ll ll;
+	} sa;
+};
+
+#define PACKET_SKB_CB(__skb)	((struct packet_skb_cb *)((__skb)->cb))
+
 #ifdef CONFIG_PACKET_MMAP
 
 static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position)
@@ -225,7 +236,7 @@
 	frame_offset = position % po->frames_per_block;
 
 	frame = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size);
-	
+
 	return frame;
 }
 #endif
@@ -268,7 +279,7 @@
 	 */
 
 	sk = pt->af_packet_priv;
-	
+
 	/*
 	 *	Yank back the headers [hope the device set this
 	 *	right or kerboom...]
@@ -293,7 +304,7 @@
 	/* drop conntrack reference */
 	nf_reset(skb);
 
-	spkt = (struct sockaddr_pkt*)skb->cb;
+	spkt = &PACKET_SKB_CB(skb)->sa.pkt;
 
 	skb_push(skb, skb->data-skb->mac.raw);
 
@@ -324,7 +335,7 @@
  *	Output a raw packet to a device layer. This bypasses all the other
  *	protocol layers and you must therefore supply it with a complete frame
  */
- 
+
 static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
 			       struct msghdr *msg, size_t len)
 {
@@ -334,9 +345,9 @@
 	struct net_device *dev;
 	__be16 proto=0;
 	int err;
-	
+
 	/*
-	 *	Get and verify the address. 
+	 *	Get and verify the address.
 	 */
 
 	if (saddr)
@@ -350,7 +361,7 @@
 		return(-ENOTCONN);	/* SOCK_PACKET must be sent giving an address */
 
 	/*
-	 *	Find the device first to size check it 
+	 *	Find the device first to size check it
 	 */
 
 	saddr->spkt_device[13] = 0;
@@ -358,7 +369,7 @@
 	err = -ENODEV;
 	if (dev == NULL)
 		goto out_unlock;
-	
+
 	err = -ENETDOWN;
 	if (!(dev->flags & IFF_UP))
 		goto out_unlock;
@@ -367,7 +378,7 @@
 	 *	You may not queue a frame bigger than the mtu. This is the lowest level
 	 *	raw protocol and you must do your own fragmentation at this level.
 	 */
-	 
+
 	err = -EMSGSIZE;
 	if (len > dev->mtu + dev->hard_header_len)
 		goto out_unlock;
@@ -380,14 +391,14 @@
 	 *	deal with the problem - do your own algorithmic backoffs. That's far
 	 *	more flexible.
 	 */
-	 
-	if (skb == NULL) 
+
+	if (skb == NULL)
 		goto out_unlock;
 
 	/*
-	 *	Fill it in 
+	 *	Fill it in
 	 */
-	 
+
 	/* FIXME: Save some space for broken drivers that write a
 	 * hard header at transmission time by themselves. PPP is the
 	 * notable one here. This should really be fixed at the driver level.
@@ -512,7 +523,10 @@
 		skb = nskb;
 	}
 
-	sll = (struct sockaddr_ll*)skb->cb;
+	BUILD_BUG_ON(sizeof(*PACKET_SKB_CB(skb)) + MAX_ADDR_LEN - 8 >
+		     sizeof(skb->cb));
+
+	sll = &PACKET_SKB_CB(skb)->sa.ll;
 	sll->sll_family = AF_PACKET;
 	sll->sll_hatype = dev->type;
 	sll->sll_protocol = skb->protocol;
@@ -523,6 +537,8 @@
 	if (dev->hard_header_parse)
 		sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
 
+	PACKET_SKB_CB(skb)->origlen = skb->len;
+
 	if (pskb_trim(skb, snaplen))
 		goto drop_n_acct;
 
@@ -582,11 +598,12 @@
 		else if (skb->pkt_type == PACKET_OUTGOING) {
 			/* Special case: outgoing packets have ll header at head */
 			skb_pull(skb, skb->nh.raw - skb->data);
-			if (skb->ip_summed == CHECKSUM_PARTIAL)
-				status |= TP_STATUS_CSUMNOTREADY;
 		}
 	}
 
+	if (skb->ip_summed == CHECKSUM_PARTIAL)
+		status |= TP_STATUS_CSUMNOTREADY;
+
 	snaplen = skb->len;
 
 	res = run_filter(skb, sk, snaplen);
@@ -623,7 +640,7 @@
 
 	spin_lock(&sk->sk_receive_queue.lock);
 	h = (struct tpacket_hdr *)packet_lookup_frame(po, po->head);
-	
+
 	if (h->tp_status)
 		goto ring_is_full;
 	po->head = po->head != po->frame_max ? po->head+1 : 0;
@@ -642,7 +659,7 @@
 	h->tp_snaplen = snaplen;
 	h->tp_mac = macoff;
 	h->tp_net = netoff;
-	if (skb->tstamp.off_sec == 0) { 
+	if (skb->tstamp.off_sec == 0) {
 		__net_timestamp(skb);
 		sock_enable_timestamp(sk);
 	}
@@ -682,7 +699,7 @@
 		skb->len = skb_len;
 	}
 drop:
-        kfree_skb(skb);
+	kfree_skb(skb);
 	return 0;
 
 ring_is_full:
@@ -710,9 +727,9 @@
 	int ifindex, err, reserve = 0;
 
 	/*
-	 *	Get and verify the address. 
+	 *	Get and verify the address.
 	 */
-	 
+
 	if (saddr == NULL) {
 		struct packet_sock *po = pkt_sk(sk);
 
@@ -921,11 +938,11 @@
 	char name[15];
 	struct net_device *dev;
 	int err = -ENODEV;
-	
+
 	/*
 	 *	Check legality
 	 */
-	 
+
 	if (addr_len != sizeof(struct sockaddr))
 		return -EINVAL;
 	strlcpy(name,uaddr->sa_data,sizeof(name));
@@ -950,7 +967,7 @@
 	/*
 	 *	Check legality
 	 */
-	 
+
 	if (addr_len < sizeof(struct sockaddr_ll))
 		return -EINVAL;
 	if (sll->sll_family != AF_PACKET)
@@ -977,7 +994,7 @@
 };
 
 /*
- *	Create a packet of type SOCK_PACKET. 
+ *	Create a packet of type SOCK_PACKET.
  */
 
 static int packet_create(struct socket *sock, int protocol)
@@ -1079,7 +1096,7 @@
 	skb=skb_recv_datagram(sk,flags,flags&MSG_DONTWAIT,&err);
 
 	/*
-	 *	An error occurred so return it. Because skb_recv_datagram() 
+	 *	An error occurred so return it. Because skb_recv_datagram()
 	 *	handles the blocking we don't see and worry about blocking
 	 *	retries.
 	 */
@@ -1092,7 +1109,7 @@
 	 *	it in now.
 	 */
 
-	sll = (struct sockaddr_ll*)skb->cb;
+	sll = &PACKET_SKB_CB(skb)->sa.ll;
 	if (sock->type == SOCK_PACKET)
 		msg->msg_namelen = sizeof(struct sockaddr_pkt);
 	else
@@ -1117,7 +1134,22 @@
 	sock_recv_timestamp(msg, sk, skb);
 
 	if (msg->msg_name)
-		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
+		memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa,
+		       msg->msg_namelen);
+
+	if (pkt_sk(sk)->auxdata) {
+		struct tpacket_auxdata aux;
+
+		aux.tp_status = TP_STATUS_USER;
+		if (skb->ip_summed == CHECKSUM_PARTIAL)
+			aux.tp_status |= TP_STATUS_CSUMNOTREADY;
+		aux.tp_len = PACKET_SKB_CB(skb)->origlen;
+		aux.tp_snaplen = skb->len;
+		aux.tp_mac = 0;
+		aux.tp_net = skb->nh.raw - skb->data;
+
+		put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);
+	}
 
 	/*
 	 *	Free or return the buffer as appropriate. Again this
@@ -1317,6 +1349,7 @@
 packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
 {
 	struct sock *sk = sock->sk;
+	struct packet_sock *po = pkt_sk(sk);
 	int ret;
 
 	if (level != SOL_PACKET)
@@ -1324,7 +1357,7 @@
 
 	switch(optname)	{
 #ifdef CONFIG_PACKET_MULTICAST
-	case PACKET_ADD_MEMBERSHIP:	
+	case PACKET_ADD_MEMBERSHIP:
 	case PACKET_DROP_MEMBERSHIP:
 	{
 		struct packet_mreq_max mreq;
@@ -1369,6 +1402,18 @@
 		return 0;
 	}
 #endif
+	case PACKET_AUXDATA:
+	{
+		int val;
+
+		if (optlen < sizeof(val))
+			return -EINVAL;
+		if (copy_from_user(&val, optval, sizeof(val)))
+			return -EFAULT;
+
+		po->auxdata = !!val;
+		return 0;
+	}
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -1378,8 +1423,11 @@
 			     char __user *optval, int __user *optlen)
 {
 	int len;
+	int val;
 	struct sock *sk = sock->sk;
 	struct packet_sock *po = pkt_sk(sk);
+	void *data;
+	struct tpacket_stats st;
 
 	if (level != SOL_PACKET)
 		return -ENOPROTOOPT;
@@ -1389,12 +1437,9 @@
 
 	if (len < 0)
 		return -EINVAL;
-		
+
 	switch(optname)	{
 	case PACKET_STATISTICS:
-	{
-		struct tpacket_stats st;
-
 		if (len > sizeof(struct tpacket_stats))
 			len = sizeof(struct tpacket_stats);
 		spin_lock_bh(&sk->sk_receive_queue.lock);
@@ -1403,16 +1448,23 @@
 		spin_unlock_bh(&sk->sk_receive_queue.lock);
 		st.tp_packets += st.tp_drops;
 
-		if (copy_to_user(optval, &st, len))
-			return -EFAULT;
+		data = &st;
 		break;
-	}
+	case PACKET_AUXDATA:
+		if (len > sizeof(int))
+			len = sizeof(int);
+		val = po->auxdata;
+
+		data = &val;
+		break;
 	default:
 		return -ENOPROTOOPT;
 	}
 
 	if (put_user(len, optlen))
 		return -EFAULT;
+	if (copy_to_user(optval, data, len))
+		return -EFAULT;
 	return 0;
 }
 
@@ -1494,7 +1546,7 @@
 		}
 		case SIOCGSTAMP:
 			return sock_get_timestamp(sk, (struct timeval __user *)arg);
-			
+
 #ifdef CONFIG_INET
 		case SIOCADDRT:
 		case SIOCDELRT:
@@ -1555,7 +1607,7 @@
 	struct file *file = vma->vm_file;
 	struct socket * sock = file->private_data;
 	struct sock *sk = sock->sk;
-	
+
 	if (sk)
 		atomic_inc(&pkt_sk(sk)->mapped);
 }
@@ -1565,7 +1617,7 @@
 	struct file *file = vma->vm_file;
 	struct socket * sock = file->private_data;
 	struct sock *sk = sock->sk;
-	
+
 	if (sk)
 		atomic_dec(&pkt_sk(sk)->mapped);
 }
@@ -1629,7 +1681,7 @@
 	int was_running, order = 0;
 	__be16 num;
 	int err = 0;
-	
+
 	if (req->tp_block_nr) {
 		int i, l;
 
@@ -1691,7 +1743,7 @@
 		__sock_put(sk);
 	}
 	spin_unlock(&po->bind_lock);
-		
+
 	synchronize_net();
 
 	err = -EBUSY;
@@ -1808,7 +1860,7 @@
 	.connect =	sock_no_connect,
 	.socketpair =	sock_no_socketpair,
 	.accept =	sock_no_accept,
-	.getname =	packet_getname, 
+	.getname =	packet_getname,
 	.poll =		packet_poll,
 	.ioctl =	packet_ioctl,
 	.listen =	sock_no_listen,
@@ -1853,17 +1905,17 @@
 static void *packet_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	++*pos;
-	return  (v == SEQ_START_TOKEN) 
-		? sk_head(&packet_sklist) 
+	return  (v == SEQ_START_TOKEN)
+		? sk_head(&packet_sklist)
 		: sk_next((struct sock*)v) ;
 }
 
 static void packet_seq_stop(struct seq_file *seq, void *v)
 {
-	read_unlock(&packet_sklist_lock);		
+	read_unlock(&packet_sklist_lock);
 }
 
-static int packet_seq_show(struct seq_file *seq, void *v) 
+static int packet_seq_show(struct seq_file *seq, void *v)
 {
 	if (v == SEQ_START_TOKEN)
 		seq_puts(seq, "sk       RefCnt Type Proto  Iface R Rmem   User   Inode\n");
@@ -1899,7 +1951,7 @@
 	return seq_open(file, &packet_seq_ops);
 }
 
-static struct file_operations packet_seq_fops = {
+static const struct file_operations packet_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= packet_seq_open,
 	.read		= seq_read,
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 9e27946..8c34f1c 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1351,7 +1351,7 @@
 	spin_lock_bh(&rose_list_lock);
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
-	
+
 	i = 1;
 	sk_for_each(s, node, &rose_list) {
 		if (i == *pos)
@@ -1365,10 +1365,10 @@
 {
 	++*pos;
 
-	return (v == SEQ_START_TOKEN) ? sk_head(&rose_list) 
+	return (v == SEQ_START_TOKEN) ? sk_head(&rose_list)
 		: sk_next((struct sock *)v);
 }
-	
+
 static void rose_info_stop(struct seq_file *seq, void *v)
 {
 	spin_unlock_bh(&rose_list_lock);
@@ -1379,7 +1379,7 @@
 	char buf[11];
 
 	if (v == SEQ_START_TOKEN)
-		seq_puts(seq, 
+		seq_puts(seq,
 			 "dest_addr  dest_call src_addr   src_call  dev   lci neigh st vs vr va   t  t1  t2  t3  hb    idle Snd-Q Rcv-Q inode\n");
 
 	else {
@@ -1392,7 +1392,7 @@
 			devname = "???";
 		else
 			devname = dev->name;
-		
+
 		seq_printf(seq, "%-10s %-9s ",
 			rose2asc(&rose->dest_addr),
 			ax2asc(buf, &rose->dest_call));
@@ -1440,7 +1440,7 @@
 	return seq_open(file, &rose_info_seqops);
 }
 
-static struct file_operations rose_info_fops = {
+static const struct file_operations rose_info_fops = {
 	.owner = THIS_MODULE,
 	.open = rose_info_open,
 	.read = seq_read,
@@ -1520,7 +1520,7 @@
 		char name[IFNAMSIZ];
 
 		sprintf(name, "rose%d", i);
-		dev = alloc_netdev(sizeof(struct net_device_stats), 
+		dev = alloc_netdev(sizeof(struct net_device_stats),
 				   name, rose_setup);
 		if (!dev) {
 			printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n");
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index 50824d3..8d88795 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/fs.h>
 #include <linux/types.h>
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index 8348d33..4ee0879 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -16,7 +16,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/rose/rose_out.c b/net/rose/rose_out.c
index 2965ffc..69820f9 100644
--- a/net/rose/rose_out.c
+++ b/net/rose/rose_out.c
@@ -11,7 +11,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 8028c0d..a1233e1 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -12,7 +12,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
@@ -66,7 +65,7 @@
 	while (rose_node != NULL) {
 		if ((rose_node->mask == rose_route->mask) &&
 		    (rosecmpm(&rose_route->address, &rose_node->address,
-		              rose_route->mask) == 0))
+			      rose_route->mask) == 0))
 			break;
 		rose_node = rose_node->next;
 	}
@@ -300,7 +299,7 @@
 	while (rose_node != NULL) {
 		if ((rose_node->mask == rose_route->mask) &&
 		    (rosecmpm(&rose_route->address, &rose_node->address,
-		              rose_route->mask) == 0))
+			      rose_route->mask) == 0))
 			break;
 		rose_node = rose_node->next;
 	}
@@ -1070,7 +1069,7 @@
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
-	for (rose_node = rose_node_list; rose_node && i < *pos; 
+	for (rose_node = rose_node_list; rose_node && i < *pos;
 	     rose_node = rose_node->next, ++i);
 
 	return (i == *pos) ? rose_node : NULL;
@@ -1079,8 +1078,8 @@
 static void *rose_node_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	++*pos;
-	
-	return (v == SEQ_START_TOKEN) ? rose_node_list 
+
+	return (v == SEQ_START_TOKEN) ? rose_node_list
 		: ((struct rose_node *)v)->next;
 }
 
@@ -1129,7 +1128,7 @@
 	return seq_open(file, &rose_node_seqops);
 }
 
-struct file_operations rose_nodes_fops = {
+const struct file_operations rose_nodes_fops = {
 	.owner = THIS_MODULE,
 	.open = rose_nodes_open,
 	.read = seq_read,
@@ -1146,7 +1145,7 @@
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
-	for (rose_neigh = rose_neigh_list; rose_neigh && i < *pos; 
+	for (rose_neigh = rose_neigh_list; rose_neigh && i < *pos;
 	     rose_neigh = rose_neigh->next, ++i);
 
 	return (i == *pos) ? rose_neigh : NULL;
@@ -1155,8 +1154,8 @@
 static void *rose_neigh_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	++*pos;
-	
-	return (v == SEQ_START_TOKEN) ? rose_neigh_list 
+
+	return (v == SEQ_START_TOKEN) ? rose_neigh_list
 		: ((struct rose_neigh *)v)->next;
 }
 
@@ -1171,7 +1170,7 @@
 	int i;
 
 	if (v == SEQ_START_TOKEN)
-		seq_puts(seq, 
+		seq_puts(seq,
 			 "addr  callsign  dev  count use mode restart  t0  tf digipeaters\n");
 	else {
 		struct rose_neigh *rose_neigh = v;
@@ -1211,7 +1210,7 @@
 	return seq_open(file, &rose_neigh_seqops);
 }
 
-struct file_operations rose_neigh_fops = {
+const struct file_operations rose_neigh_fops = {
 	.owner = THIS_MODULE,
 	.open = rose_neigh_open,
 	.read = seq_read,
@@ -1229,7 +1228,7 @@
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
-	for (rose_route = rose_route_list; rose_route && i < *pos; 
+	for (rose_route = rose_route_list; rose_route && i < *pos;
 	     rose_route = rose_route->next, ++i);
 
 	return (i == *pos) ? rose_route : NULL;
@@ -1238,8 +1237,8 @@
 static void *rose_route_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	++*pos;
-	
-	return (v == SEQ_START_TOKEN) ? rose_route_list 
+
+	return (v == SEQ_START_TOKEN) ? rose_route_list
 		: ((struct rose_route *)v)->next;
 }
 
@@ -1253,30 +1252,30 @@
 	char buf[11];
 
 	if (v == SEQ_START_TOKEN)
-		seq_puts(seq, 
+		seq_puts(seq,
 			 "lci  address     callsign   neigh  <-> lci  address     callsign   neigh\n");
 	else {
 		struct rose_route *rose_route = v;
 
-		if (rose_route->neigh1) 
+		if (rose_route->neigh1)
 			seq_printf(seq,
 				   "%3.3X  %-10s  %-9s  %05d      ",
 				   rose_route->lci1,
 				   rose2asc(&rose_route->src_addr),
 				   ax2asc(buf, &rose_route->src_call),
 				   rose_route->neigh1->number);
-		else 
-			seq_puts(seq, 
+		else
+			seq_puts(seq,
 				 "000  *           *          00000      ");
 
-		if (rose_route->neigh2) 
+		if (rose_route->neigh2)
 			seq_printf(seq,
 				   "%3.3X  %-10s  %-9s  %05d\n",
 				rose_route->lci2,
 				rose2asc(&rose_route->dest_addr),
 				ax2asc(buf, &rose_route->dest_call),
 				rose_route->neigh2->number);
-		 else 
+		 else
 			 seq_puts(seq,
 				  "000  *           *          00000\n");
 		}
@@ -1295,7 +1294,7 @@
 	return seq_open(file, &rose_route_seqops);
 }
 
-struct file_operations rose_routes_fops = {
+const struct file_operations rose_routes_fops = {
 	.owner = THIS_MODULE,
 	.open = rose_route_open,
 	.read = seq_read,
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c
index 36a7794..b05108f 100644
--- a/net/rose/rose_subr.c
+++ b/net/rose/rose_subr.c
@@ -11,7 +11,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
diff --git a/net/rose/sysctl_net_rose.c b/net/rose/sysctl_net_rose.c
index 8548c7c..455b055 100644
--- a/net/rose/sysctl_net_rose.c
+++ b/net/rose/sysctl_net_rose.c
@@ -25,7 +25,7 @@
 static struct ctl_table_header *rose_table_header;
 
 static ctl_table rose_table[] = {
-        {
+	{
 		.ctl_name	= NET_ROSE_RESTART_REQUEST_TIMEOUT,
 		.procname	= "restart_request_timeout",
 		.data		= &sysctl_rose_restart_request_timeout,
@@ -36,7 +36,7 @@
 		.extra1		= &min_timer,
 		.extra2		= &max_timer
 	},
-        {
+	{
 		.ctl_name	= NET_ROSE_CALL_REQUEST_TIMEOUT,
 		.procname	= "call_request_timeout",
 		.data		= &sysctl_rose_call_request_timeout,
@@ -47,7 +47,7 @@
 		.extra1		= &min_timer,
 		.extra2		= &max_timer
 	},
-        {
+	{
 		.ctl_name	= NET_ROSE_RESET_REQUEST_TIMEOUT,
 		.procname	= "reset_request_timeout",
 		.data		= &sysctl_rose_reset_request_timeout,
@@ -58,7 +58,7 @@
 		.extra1		= &min_timer,
 		.extra2		= &max_timer
 	},
-        {
+	{
 		.ctl_name	= NET_ROSE_CLEAR_REQUEST_TIMEOUT,
 		.procname	= "clear_request_timeout",
 		.data		= &sysctl_rose_clear_request_timeout,
@@ -69,7 +69,7 @@
 		.extra1		= &min_timer,
 		.extra2		= &max_timer
 	},
-        {
+	{
 		.ctl_name	= NET_ROSE_NO_ACTIVITY_TIMEOUT,
 		.procname	= "no_activity_timeout",
 		.data		= &sysctl_rose_no_activity_timeout,
@@ -80,7 +80,7 @@
 		.extra1		= &min_idle,
 		.extra2		= &max_idle
 	},
-        {
+	{
 		.ctl_name	= NET_ROSE_ACK_HOLD_BACK_TIMEOUT,
 		.procname	= "acknowledge_hold_back_timeout",
 		.data		= &sysctl_rose_ack_hold_back_timeout,
@@ -91,7 +91,7 @@
 		.extra1		= &min_timer,
 		.extra2		= &max_timer
 	},
-        {
+	{
 		.ctl_name	= NET_ROSE_ROUTING_CONTROL,
 		.procname	= "routing_control",
 		.data		= &sysctl_rose_routing_control,
@@ -102,7 +102,7 @@
 		.extra1		= &min_route,
 		.extra2		= &max_route
 	},
-        {
+	{
 		.ctl_name	= NET_ROSE_LINK_FAIL_TIMEOUT,
 		.procname	= "link_fail_timeout",
 		.data		= &sysctl_rose_link_fail_timeout,
@@ -113,7 +113,7 @@
 		.extra1		= &min_ftimer,
 		.extra2		= &max_ftimer
 	},
-        {
+	{
 		.ctl_name	= NET_ROSE_MAX_VCS,
 		.procname	= "maximum_virtual_circuits",
 		.data		= &sysctl_rose_maximum_vcs,
@@ -124,7 +124,7 @@
 		.extra1		= &min_maxvcs,
 		.extra2		= &max_maxvcs
 	},
-        {
+	{
 		.ctl_name	= NET_ROSE_WINDOW_SIZE,
 		.procname	= "window_size",
 		.data		= &sysctl_rose_window_size,
@@ -160,7 +160,7 @@
 
 void __init rose_register_sysctl(void)
 {
-	rose_table_header = register_sysctl_table(rose_root_table, 1);
+	rose_table_header = register_sysctl_table(rose_root_table);
 }
 
 void rose_unregister_sysctl(void)
diff --git a/net/rxrpc/connection.c b/net/rxrpc/connection.c
index 93d2c55..a7c929a 100644
--- a/net/rxrpc/connection.c
+++ b/net/rxrpc/connection.c
@@ -163,7 +163,7 @@
 		conn = list_entry(_p, struct rxrpc_connection, link);
 		if (conn->addr.sin_port	== candidate->addr.sin_port	&&
 		    conn->security_ix	== candidate->security_ix	&&
-		    conn->service_id	== candidate->service_id	&& 
+		    conn->service_id	== candidate->service_id	&&
 		    conn->in_clientflag	== 0)
 			goto found_in_graveyard;
 	}
@@ -247,13 +247,13 @@
 		    conn->in_epoch		== x_epoch	&&
 		    conn->conn_id		== x_connid	&&
 		    conn->security_ix		== x_secix	&&
-		    conn->service_id		== x_servid	&& 
+		    conn->service_id		== x_servid	&&
 		    conn->in_clientflag		== x_clflag)
 			goto found_active;
 	}
 	read_unlock(&peer->conn_lock);
 
-	/* [uncommon case] not active 
+	/* [uncommon case] not active
 	 * - create a candidate for a new record if an inbound connection
 	 * - only examine the graveyard for an outbound connection
 	 */
@@ -286,7 +286,7 @@
 		    conn->in_epoch		== x_epoch	&&
 		    conn->conn_id		== x_connid	&&
 		    conn->security_ix		== x_secix	&&
-		    conn->service_id		== x_servid	&& 
+		    conn->service_id		== x_servid	&&
 		    conn->in_clientflag		== x_clflag)
 			goto found_active_second_chance;
 	}
@@ -299,7 +299,7 @@
 		    conn->in_epoch		== x_epoch	&&
 		    conn->conn_id		== x_connid	&&
 		    conn->security_ix		== x_secix	&&
-		    conn->service_id		== x_servid	&& 
+		    conn->service_id		== x_servid	&&
 		    conn->in_clientflag		== x_clflag)
 			goto found_in_graveyard;
 	}
diff --git a/net/rxrpc/internal.h b/net/rxrpc/internal.h
index 70e52f6..cc0c579 100644
--- a/net/rxrpc/internal.h
+++ b/net/rxrpc/internal.h
@@ -14,7 +14,7 @@
  */
 #if 1
 #define __RXACCT_DECL(X) X
-#define __RXACCT(X) do { X; } while(0) 
+#define __RXACCT(X) do { X; } while(0)
 #else
 #define __RXACCT_DECL(X)
 #define __RXACCT(X) do { } while(0)
diff --git a/net/rxrpc/krxiod.c b/net/rxrpc/krxiod.c
index 49effd9..bbbcd6c 100644
--- a/net/rxrpc/krxiod.c
+++ b/net/rxrpc/krxiod.c
@@ -141,7 +141,7 @@
 
 		try_to_freeze();
 
-                /* discard pending signals */
+		/* discard pending signals */
 		rxrpc_discard_my_signals();
 
 	} while (!rxrpc_krxiod_die);
diff --git a/net/rxrpc/krxsecd.c b/net/rxrpc/krxsecd.c
index 3ab0f77..9a1e7f5 100644
--- a/net/rxrpc/krxsecd.c
+++ b/net/rxrpc/krxsecd.c
@@ -110,7 +110,7 @@
 
 		try_to_freeze();
 
-                /* discard pending signals */
+		/* discard pending signals */
 		rxrpc_discard_my_signals();
 
 	} while (!die);
diff --git a/net/rxrpc/main.c b/net/rxrpc/main.c
index 48cbd06..baec1f7 100644
--- a/net/rxrpc/main.c
+++ b/net/rxrpc/main.c
@@ -146,17 +146,17 @@
 void __cyg_profile_func_enter (void *this_fn, void *call_site)
 {
        asm volatile("  movl    %%esp,%%edi     \n"
-                    "  andl    %0,%%edi        \n"
-                    "  addl    %1,%%edi        \n"
-                    "  movl    %%esp,%%ecx     \n"
-                    "  subl    %%edi,%%ecx     \n"
-                    "  shrl    $2,%%ecx        \n"
-                    "  movl    $0xedededed,%%eax     \n"
-                    "  rep stosl               \n"
-                    :
-                    : "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info))
-                    : "eax", "ecx", "edi", "memory", "cc"
-                    );
+		    "  andl    %0,%%edi        \n"
+		    "  addl    %1,%%edi        \n"
+		    "  movl    %%esp,%%ecx     \n"
+		    "  subl    %%edi,%%ecx     \n"
+		    "  shrl    $2,%%ecx        \n"
+		    "  movl    $0xedededed,%%eax     \n"
+		    "  rep stosl               \n"
+		    :
+		    : "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info))
+		    : "eax", "ecx", "edi", "memory", "cc"
+		    );
 }
 
 void __cyg_profile_func_exit(void *this_fn, void *call_site)
@@ -165,16 +165,16 @@
 void __cyg_profile_func_exit(void *this_fn, void *call_site)
 {
        asm volatile("  movl    %%esp,%%edi     \n"
-                    "  andl    %0,%%edi        \n"
-                    "  addl    %1,%%edi        \n"
-                    "  movl    %%esp,%%ecx     \n"
-                    "  subl    %%edi,%%ecx     \n"
-                    "  shrl    $2,%%ecx        \n"
-                    "  movl    $0xdadadada,%%eax     \n"
-                    "  rep stosl               \n"
-                    :
-                    : "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info))
-                    : "eax", "ecx", "edi", "memory", "cc"
-                    );
+		    "  andl    %0,%%edi        \n"
+		    "  addl    %1,%%edi        \n"
+		    "  movl    %%esp,%%ecx     \n"
+		    "  subl    %%edi,%%ecx     \n"
+		    "  shrl    $2,%%ecx        \n"
+		    "  movl    $0xdadadada,%%eax     \n"
+		    "  rep stosl               \n"
+		    :
+		    : "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info))
+		    : "eax", "ecx", "edi", "memory", "cc"
+		    );
 }
 #endif
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index 29975d9..8551c87 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -37,7 +37,7 @@
 	.show	= rxrpc_proc_transports_show,
 };
 
-static struct file_operations rxrpc_proc_transports_fops = {
+static const struct file_operations rxrpc_proc_transports_fops = {
 	.open		= rxrpc_proc_transports_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -57,7 +57,7 @@
 	.show	= rxrpc_proc_peers_show,
 };
 
-static struct file_operations rxrpc_proc_peers_fops = {
+static const struct file_operations rxrpc_proc_peers_fops = {
 	.open		= rxrpc_proc_peers_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -77,7 +77,7 @@
 	.show	= rxrpc_proc_conns_show,
 };
 
-static struct file_operations rxrpc_proc_conns_fops = {
+static const struct file_operations rxrpc_proc_conns_fops = {
 	.open		= rxrpc_proc_conns_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -97,7 +97,7 @@
 	.show	= rxrpc_proc_calls_show,
 };
 
-static struct file_operations rxrpc_proc_calls_fops = {
+static const struct file_operations rxrpc_proc_calls_fops = {
 	.open		= rxrpc_proc_calls_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c
index 6374df7..8842907 100644
--- a/net/rxrpc/sysctl.c
+++ b/net/rxrpc/sysctl.c
@@ -27,7 +27,7 @@
 static struct ctl_table_header *rxrpc_sysctl = NULL;
 
 static ctl_table rxrpc_sysctl_table[] = {
-        {
+	{
 		.ctl_name	= 1,
 		.procname	= "kdebug",
 		.data		= &rxrpc_kdebug,
@@ -35,7 +35,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
-        {
+	{
 		.ctl_name	= 2,
 		.procname	= "ktrace",
 		.data		= &rxrpc_ktrace,
@@ -43,7 +43,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
-        {
+	{
 		.ctl_name	= 3,
 		.procname	= "kproto",
 		.data		= &rxrpc_kproto,
@@ -51,7 +51,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
-        {
+	{
 		.ctl_name	= 4,
 		.procname	= "knet",
 		.data		= &rxrpc_knet,
@@ -59,7 +59,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
-        {
+	{
 		.ctl_name	= 5,
 		.procname	= "peertimo",
 		.data		= &rxrpc_peer_timeout,
@@ -67,7 +67,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_doulongvec_minmax
 	},
-        {
+	{
 		.ctl_name	= 6,
 		.procname	= "conntimo",
 		.data		= &rxrpc_conn_timeout,
@@ -97,7 +97,7 @@
 int rxrpc_sysctl_init(void)
 {
 #ifdef CONFIG_SYSCTL
-	rxrpc_sysctl = register_sysctl_table(rxrpc_dir_sysctl_table, 0);
+	rxrpc_sysctl = register_sysctl_table(rxrpc_dir_sysctl_table);
 	if (!rxrpc_sysctl)
 		return -ENOMEM;
 #endif /* CONFIG_SYSCTL */
diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c
index 4268b38..8e57be2 100644
--- a/net/rxrpc/transport.c
+++ b/net/rxrpc/transport.c
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <rxrpc/transport.h>
@@ -330,10 +329,10 @@
 	msg->state = RXRPC_MSG_RECEIVED;
 	skb_get_timestamp(pkt, &msg->stamp);
 	if (msg->stamp.tv_sec == 0) {
-		do_gettimeofday(&msg->stamp); 
-		if (pkt->sk) 
+		do_gettimeofday(&msg->stamp);
+		if (pkt->sk)
 			sock_enable_timestamp(pkt->sk);
-	} 
+	}
 	msg->seq = ntohl(msg->hdr.seq);
 
 	/* attach the packet */
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 835070e..cb21617 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -16,7 +16,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -65,7 +64,7 @@
 			p->tcfc_bindcnt--;
 
 		p->tcfc_refcnt--;
-	       	if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) {
+		if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) {
 			tcf_hash_destroy(p, hinfo);
 			ret = 1;
 		}
@@ -362,7 +361,7 @@
 #endif
 
 int tcf_action_exec(struct sk_buff *skb, struct tc_action *act,
-                    struct tcf_result *res)
+		    struct tcf_result *res)
 {
 	struct tc_action *a;
 	int ret = -1;
@@ -473,7 +472,7 @@
 }
 
 struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
-                                    char *name, int ovr, int bind, int *err)
+				    char *name, int ovr, int bind, int *err)
 {
 	struct tc_action *a;
 	struct tc_action_ops *a_o;
@@ -553,7 +552,7 @@
 }
 
 struct tc_action *tcf_action_init(struct rtattr *rta, struct rtattr *est,
-                                  char *name, int ovr, int bind, int *err)
+				  char *name, int ovr, int bind, int *err)
 {
 	struct rtattr *tb[TCA_ACT_MAX_PRIO+1];
 	struct tc_action *head = NULL, *act, *act_prev = NULL;
@@ -590,7 +589,7 @@
 	int err = 0;
 	struct gnet_dump d;
 	struct tcf_act_hdr *h = a->priv;
-	
+
 	if (h == NULL)
 		goto errout;
 
@@ -632,7 +631,7 @@
 
 static int
 tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq,
-             u16 flags, int event, int bind, int ref)
+	     u16 flags, int event, int bind, int ref)
 {
 	struct tcamsg *t;
 	struct nlmsghdr *nlh;
@@ -645,7 +644,7 @@
 	t->tca_family = AF_UNSPEC;
 	t->tca__pad1 = 0;
 	t->tca__pad2 = 0;
-	
+
 	x = (struct rtattr*) skb->tail;
 	RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
 
@@ -653,7 +652,7 @@
 		goto rtattr_failure;
 
 	x->rta_len = skb->tail - (u8*)x;
-	
+
 	nlh->nlmsg_len = skb->tail - b;
 	return skb->len;
 
@@ -852,7 +851,7 @@
 		}
 
 		if (tca_get_fill(skb, head, pid, n->nlmsg_seq, 0, event,
-		                 0, 1) <= 0) {
+				 0, 1) <= 0) {
 			kfree_skb(skb);
 			ret = -EINVAL;
 			goto err;
@@ -861,7 +860,7 @@
 		/* now do the delete */
 		tcf_action_destroy(head, 0);
 		ret = rtnetlink_send(skb, pid, RTNLGRP_TC,
-		                     n->nlmsg_flags&NLM_F_ECHO);
+				     n->nlmsg_flags&NLM_F_ECHO);
 		if (ret > 0)
 			return 0;
 		return ret;
@@ -872,7 +871,7 @@
 }
 
 static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
-                          u16 flags)
+			  u16 flags)
 {
 	struct tcamsg *t;
 	struct nlmsghdr *nlh;
@@ -900,10 +899,10 @@
 		goto rtattr_failure;
 
 	x->rta_len = skb->tail - (u8*)x;
-	
+
 	nlh->nlmsg_len = skb->tail - b;
 	NETLINK_CB(skb).dst_group = RTNLGRP_TC;
-	
+
 	err = rtnetlink_send(skb, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
 	if (err > 0)
 		err = 0;
@@ -915,7 +914,7 @@
 	return -1;
 }
 
-	
+
 static int
 tcf_action_add(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int ovr)
 {
@@ -999,13 +998,13 @@
 		return NULL;
 
 	if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(tb1),
-	                 NLMSG_ALIGN(RTA_PAYLOAD(tb1))) < 0)
+			 NLMSG_ALIGN(RTA_PAYLOAD(tb1))) < 0)
 		return NULL;
 	if (tb[0] == NULL)
 		return NULL;
 
 	if (rtattr_parse(tb2, TCA_ACT_MAX, RTA_DATA(tb[0]),
-	                 RTA_PAYLOAD(tb[0])) < 0)
+			 RTA_PAYLOAD(tb[0])) < 0)
 		return NULL;
 	kind = tb2[TCA_ACT_KIND-1];
 
@@ -1043,7 +1042,7 @@
 	}
 
 	nlh = NLMSG_PUT(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
-	                cb->nlh->nlmsg_type, sizeof(*t));
+			cb->nlh->nlmsg_type, sizeof(*t));
 	t = NLMSG_DATA(nlh);
 	t->tca_family = AF_UNSPEC;
 	t->tca__pad1 = 0;
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 85de7ef..87d0faf 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -65,7 +64,7 @@
 #endif /* CONFIG_GACT_PROB */
 
 static int tcf_gact_init(struct rtattr *rta, struct rtattr *est,
-                         struct tc_action *a, int ovr, int bind)
+			 struct tc_action *a, int ovr, int bind)
 {
 	struct rtattr *tb[TCA_GACT_MAX];
 	struct tc_gact *parm;
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 01e6913..47f0b13 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -16,7 +16,6 @@
 #include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -52,7 +51,7 @@
 
 static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
 {
-	struct ipt_target *target;
+	struct xt_target *target;
 	int ret = 0;
 
 	target = xt_request_find_target(AF_INET, t->u.user.name,
@@ -70,7 +69,7 @@
 	}
 	if (t->u.kernel.target->checkentry
 	    && !t->u.kernel.target->checkentry(table, NULL,
-		    			       t->u.kernel.target, t->data,
+					       t->u.kernel.target, t->data,
 					       hook)) {
 		module_put(t->u.kernel.target->me);
 		ret = -EINVAL;
@@ -83,7 +82,7 @@
 {
 	if (t->u.kernel.target->destroy)
 		t->u.kernel.target->destroy(t->u.kernel.target, t->data);
-        module_put(t->u.kernel.target->me);
+	module_put(t->u.kernel.target->me);
 }
 
 static int tcf_ipt_release(struct tcf_ipt *ipt, int bind)
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 4838972..68f26cb 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -17,7 +17,6 @@
 #include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 8ac65c2..3d6a2fc 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -14,7 +14,6 @@
 #include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -153,8 +152,8 @@
 			if (tkey->offmask) {
 				if (skb->len > tkey->at) {
 					 char *j = pptr + tkey->at;
-					 offset += ((*j & tkey->offmask) >> 
-					           tkey->shift);
+					 offset += ((*j & tkey->offmask) >>
+						   tkey->shift);
 				} else {
 					goto bad;
 				}
@@ -176,7 +175,7 @@
 			*ptr = ((*ptr & tkey->mask) ^ tkey->val);
 			munged++;
 		}
-		
+
 		if (munged)
 			skb->tc_verd = SET_TC_MUNGED(skb->tc_verd);
 		goto done;
@@ -200,8 +199,8 @@
 	struct tcf_pedit *p = a->priv;
 	struct tc_pedit *opt;
 	struct tcf_t t;
-	int s; 
-		
+	int s;
+
 	s = sizeof(*opt) + p->tcfp_nkeys * sizeof(struct tc_pedit_key);
 
 	/* netlink spinlocks held above us - must use ATOMIC */
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index af68e1e..10a5a5c 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -62,7 +61,7 @@
 
 #ifdef CONFIG_NET_CLS_ACT
 static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
-                              int type, struct tc_action *a)
+			      int type, struct tc_action *a)
 {
 	struct tcf_common *p;
 	int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
@@ -112,7 +111,7 @@
 {
 	unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
 	struct tcf_common **p1p;
-	
+
 	for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->tcfc_next) {
 		if (*p1p == &p->common) {
 			write_lock_bh(&police_lock);
@@ -135,7 +134,7 @@
 
 #ifdef CONFIG_NET_CLS_ACT
 static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
-                                 struct tc_action *a, int ovr, int bind)
+				 struct tc_action *a, int ovr, int bind)
 {
 	unsigned h;
 	int ret = 0, err;
@@ -269,7 +268,7 @@
 }
 
 static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
-                          struct tcf_result *res)
+			  struct tcf_result *res)
 {
 	struct tcf_police *police = a->priv;
 	psched_time_t now;
@@ -606,12 +605,12 @@
 int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police)
 {
 	struct gnet_dump d;
-	
+
 	if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
 					 TCA_XSTATS, police->tcf_stats_lock,
 					 &d) < 0)
 		goto errout;
-	
+
 	if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 ||
 #ifdef CONFIG_NET_ESTIMATOR
 	    gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 ||
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 5fe8085..c797118 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -43,9 +43,9 @@
 	d->tcf_bstats.bytes += skb->len;
 	d->tcf_bstats.packets++;
 
-	/* print policy string followed by _ then packet count 
-	 * Example if this was the 3rd packet and the string was "hello" 
-	 * then it would look like "hello_3" (without quotes) 
+	/* print policy string followed by _ then packet count
+	 * Example if this was the 3rd packet and the string was "hello"
+	 * then it would look like "hello_3" (without quotes)
 	 **/
 	printk("simple: %s_%d\n",
 	       (char *)d->tcfd_defdata, d->tcf_bstats.packets);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index edb8fc9..5c6ffdb 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -286,7 +285,7 @@
 			goto errout;
 	} else {
 		switch (n->nlmsg_type) {
-		case RTM_NEWTFILTER:	
+		case RTM_NEWTFILTER:
 			err = -EEXIST;
 			if (n->nlmsg_flags&NLM_F_EXCL)
 				goto errout;
@@ -481,11 +480,11 @@
 
 int
 tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
-	          struct rtattr *rate_tlv, struct tcf_exts *exts,
-	          struct tcf_ext_map *map)
+		  struct rtattr *rate_tlv, struct tcf_exts *exts,
+		  struct tcf_ext_map *map)
 {
 	memset(exts, 0, sizeof(*exts));
-	
+
 #ifdef CONFIG_NET_CLS_ACT
 	{
 		int err;
@@ -511,7 +510,7 @@
 #elif defined CONFIG_NET_CLS_POLICE
 	if (map->police && tb[map->police-1]) {
 		struct tcf_police *p;
-		
+
 		p = tcf_police_locate(tb[map->police-1], rate_tlv);
 		if (p == NULL)
 			return -EINVAL;
@@ -530,7 +529,7 @@
 
 void
 tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
-	        struct tcf_exts *src)
+		struct tcf_exts *src)
 {
 #ifdef CONFIG_NET_CLS_ACT
 	if (src->action) {
@@ -597,7 +596,7 @@
 
 int
 tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
-	            struct tcf_ext_map *map)
+		    struct tcf_ext_map *map)
 {
 #ifdef CONFIG_NET_CLS_ACT
 	if (exts->action)
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 09fda68..fad08e5 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
@@ -98,7 +97,7 @@
 {
 	struct basic_head *head = (struct basic_head *) xchg(&tp->root, NULL);
 	struct basic_filter *f, *n;
-	
+
 	list_for_each_entry_safe(f, n, &head->flist, link) {
 		list_del(&f->link);
 		basic_delete_filter(tp, f);
@@ -157,7 +156,7 @@
 }
 
 static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
-		        struct rtattr **tca, unsigned long *arg)
+			struct rtattr **tca, unsigned long *arg)
 {
 	int err = -EINVAL;
 	struct basic_head *head = (struct basic_head *) tp->root;
@@ -292,7 +291,7 @@
 	return register_tcf_proto_ops(&cls_basic_ops);
 }
 
-static void __exit exit_basic(void) 
+static void __exit exit_basic(void)
 {
 	unregister_tcf_proto_ops(&cls_basic_ops);
 }
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index c797d6a..5dbb9d4 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -24,7 +24,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -91,7 +90,7 @@
 	else if (HTSIZE == 256) {
 		u8 *t = (u8 *) &handle;
 		return t[0] ^ t[1] ^ t[2] ^ t[3];
-	} else 
+	} else
 		return handle & (HTSIZE - 1);
 }
 
@@ -407,7 +406,7 @@
 	return register_tcf_proto_ops(&cls_fw_ops);
 }
 
-static void __exit exit_fw(void) 
+static void __exit exit_fw(void)
 {
 	unregister_tcf_proto_ops(&cls_fw_ops);
 }
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index d3aea73..e85df07 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
diff --git a/net/sched/cls_rsvp.c b/net/sched/cls_rsvp.c
index ad26137..1d4a1fb 100644
--- a/net/sched/cls_rsvp.c
+++ b/net/sched/cls_rsvp.c
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 587b9ad..7853621 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -130,7 +130,7 @@
 	else if (r > 0)					\
 		return r;				\
 }
-	
+
 static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp,
 			 struct tcf_result *res)
 {
@@ -347,7 +347,7 @@
 {
 	int n = data->tgenerator>>5;
 	u32 b = 1<<(data->tgenerator&0x1F);
-	
+
 	if (data->tmap[n]&b)
 		return 0;
 	data->tmap[n] |= b;
@@ -547,7 +547,7 @@
 	s->next = *sp;
 	wmb();
 	*sp = s;
-	
+
 	goto insert;
 
 errout:
@@ -654,7 +654,7 @@
 	return register_tcf_proto_ops(&RSVP_OPS);
 }
 
-static void __exit exit_rsvp(void) 
+static void __exit exit_rsvp(void)
 {
 	unregister_tcf_proto_ops(&RSVP_OPS);
 }
diff --git a/net/sched/cls_rsvp6.c b/net/sched/cls_rsvp6.c
index fde51f7..a2979d8 100644
--- a/net/sched/cls_rsvp6.c
+++ b/net/sched/cls_rsvp6.c
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 5af8a59e..040e2d2 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -222,7 +222,7 @@
 	err = tcf_exts_validate(tp, tb, est, &e, &tcindex_ext_map);
 	if (err < 0)
 		return err;
-	
+
 	memcpy(&cp, p, sizeof(cp));
 	memset(&new_filter_result, 0, sizeof(new_filter_result));
 
@@ -316,12 +316,12 @@
 		f = kzalloc(sizeof(*f), GFP_KERNEL);
 		if (!f)
 			goto errout_alloc;
- 	}
+	}
 
 	if (tb[TCA_TCINDEX_CLASSID-1]) {
 		cr.res.classid = *(u32 *) RTA_DATA(tb[TCA_TCINDEX_CLASSID-1]);
 		tcf_bind_filter(tp, &cr.res, base);
- 	}
+	}
 
 	tcf_exts_change(tp, &cr.exts, &e);
 
@@ -341,7 +341,7 @@
 		for (fp = p->h+(handle % p->hash); *fp; fp = &(*fp)->next)
 			/* nothing */;
 		*fp = f;
- 	}
+	}
 	tcf_tree_unlock(tp);
 
 	return 0;
@@ -491,7 +491,7 @@
 		if (tcf_exts_dump_stats(skb, &r->exts, &tcindex_ext_map) < 0)
 			goto rtattr_failure;
 	}
-	
+
 	return skb->len;
 
 rtattr_failure:
@@ -519,7 +519,7 @@
 	return register_tcf_proto_ops(&cls_tcindex_ops);
 }
 
-static void __exit exit_tcindex(void) 
+static void __exit exit_tcindex(void)
 {
 	unregister_tcf_proto_ops(&cls_tcindex_ops);
 }
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 8b51948..0bcb169 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -36,7 +36,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -760,7 +759,7 @@
 			RTA_PUT(skb, TCA_U32_INDEV, IFNAMSIZ, n->indev);
 #endif
 #ifdef CONFIG_CLS_U32_PERF
-		RTA_PUT(skb, TCA_U32_PCNT, 
+		RTA_PUT(skb, TCA_U32_PCNT,
 		sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(u64),
 			n->pf);
 #endif
@@ -810,7 +809,7 @@
 	return register_tcf_proto_ops(&cls_u32_ops);
 }
 
-static void __exit exit_u32(void) 
+static void __exit exit_u32(void)
 {
 	unregister_tcf_proto_ops(&cls_u32_ops);
 }
diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c
index 8ed93c3..8d6dacd 100644
--- a/net/sched/em_cmp.c
+++ b/net/sched/em_cmp.c
@@ -88,7 +88,7 @@
 	return tcf_em_register(&em_cmp_ops);
 }
 
-static void __exit exit_em_cmp(void) 
+static void __exit exit_em_cmp(void)
 {
 	tcf_em_unregister(&em_cmp_ops);
 }
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 45d47d3..60acf8c 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -9,7 +9,7 @@
  * Authors:	Thomas Graf <tgraf@suug.ch>
  *
  * ==========================================================================
- * 
+ *
  * 	The metadata ematch compares two meta objects where each object
  * 	represents either a meta value stored in the kernel or a static
  * 	value provided by userspace. The objects are not provided by
@@ -290,7 +290,7 @@
 		dst->len = 3;
 	 } else  {
 		struct net_device *dev;
-		
+
 		dev = dev_get_by_index(skb->sk->sk_bound_dev_if);
 		*err = var_dev(dev, dst);
 		if (dev)
@@ -671,7 +671,7 @@
  * Core
  **************************************************************************/
 
-static inline int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info, 
+static inline int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info,
 			   struct meta_value *v, struct meta_obj *dst)
 {
 	int err = 0;
@@ -753,7 +753,7 @@
 	struct rtattr *tb[TCA_EM_META_MAX];
 	struct tcf_meta_hdr *hdr;
 	struct meta_match *meta = NULL;
-	
+
 	if (rtattr_parse(tb, TCA_EM_META_MAX, data, len) < 0)
 		goto errout;
 
@@ -822,7 +822,7 @@
 
 rtattr_failure:
 	return -1;
-}		
+}
 
 static struct tcf_ematch_ops em_meta_ops = {
 	.kind	  = TCF_EM_META,
@@ -839,7 +839,7 @@
 	return tcf_em_register(&em_meta_ops);
 }
 
-static void __exit exit_em_meta(void) 
+static void __exit exit_em_meta(void)
 {
 	tcf_em_unregister(&em_meta_ops);
 }
diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c
index 005db40..b4b36ef 100644
--- a/net/sched/em_nbyte.c
+++ b/net/sched/em_nbyte.c
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/tc_ematch/tc_em_nbyte.h>
@@ -23,7 +22,7 @@
 	struct tcf_em_nbyte	hdr;
 	char			pattern[0];
 };
-	
+
 static int em_nbyte_change(struct tcf_proto *tp, void *data, int data_len,
 			   struct tcf_ematch *em)
 {
@@ -68,7 +67,7 @@
 	return tcf_em_register(&em_nbyte_ops);
 }
 
-static void __exit exit_em_nbyte(void) 
+static void __exit exit_em_nbyte(void)
 {
 	tcf_em_unregister(&em_nbyte_ops);
 }
diff --git a/net/sched/em_text.c b/net/sched/em_text.c
index aa17d8f..e8f4616 100644
--- a/net/sched/em_text.c
+++ b/net/sched/em_text.c
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/textsearch.h>
@@ -125,7 +124,7 @@
 
 rtattr_failure:
 	return -1;
-}		
+}
 
 static struct tcf_ematch_ops em_text_ops = {
 	.kind	  = TCF_EM_TEXT,
@@ -142,7 +141,7 @@
 	return tcf_em_register(&em_text_ops);
 }
 
-static void __exit exit_em_text(void) 
+static void __exit exit_em_text(void)
 {
 	tcf_em_unregister(&em_text_ops);
 }
diff --git a/net/sched/em_u32.c b/net/sched/em_u32.c
index e3ddfce..cd0600c 100644
--- a/net/sched/em_u32.c
+++ b/net/sched/em_u32.c
@@ -23,7 +23,7 @@
 {
 	struct tc_u32_key *key = (struct tc_u32_key *) em->data;
 	unsigned char *ptr = skb->nh.raw;
-	
+
 	if (info) {
 		if (info->ptr)
 			ptr = info->ptr;
@@ -34,7 +34,7 @@
 
 	if (!tcf_valid_offset(skb, ptr, sizeof(u32)))
 		return 0;
-	
+
 	return !(((*(u32*) ptr)  ^ key->val) & key->mask);
 }
 
@@ -51,7 +51,7 @@
 	return tcf_em_register(&em_u32_ops);
 }
 
-static void __exit exit_em_u32(void) 
+static void __exit exit_em_u32(void)
 {
 	tcf_em_unregister(&em_u32_ops);
 }
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 8f8a16d..959c306 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -37,12 +37,12 @@
  *                     --------<-POP---------
  *
  * where B is a virtual ematch referencing to sequence starting with B1.
- * 
+ *
  * ==========================================================================
  *
  * How to write an ematch in 60 seconds
  * ------------------------------------
- * 
+ *
  *   1) Provide a matcher function:
  *      static int my_match(struct sk_buff *skb, struct tcf_ematch *m,
  *                          struct tcf_pkt_info *info)
@@ -84,7 +84,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
@@ -115,7 +114,7 @@
 
 /**
  * tcf_em_register - register an extended match
- * 
+ *
  * @ops: ematch operations lookup table
  *
  * This function must be called by ematches to announce their presence.
@@ -211,7 +210,7 @@
 		if (ref <= idx)
 			goto errout;
 
-		
+
 		em->data = ref;
 	} else {
 		/* Note: This lookup will increase the module refcnt
@@ -327,7 +326,7 @@
 	/* We do not use rtattr_parse_nested here because the maximum
 	 * number of attributes is unknown. This saves us the allocation
 	 * for a tb buffer which would serve no purpose at all.
-	 * 
+	 *
 	 * The array of rt attributes is parsed in the order as they are
 	 * provided, their type must be incremental from 1 to n. Even
 	 * if it does not serve any real purpose, a failure of sticking
@@ -399,7 +398,7 @@
 			module_put(em->ops->owner);
 		}
 	}
-	
+
 	tree->hdr.nmatches = 0;
 	kfree(tree->matches);
 }
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 65825f4..ecc988a 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -18,7 +18,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -389,7 +388,7 @@
 	struct Qdisc *q = *old;
 
 
-	if (parent == NULL) { 
+	if (parent == NULL) {
 		if (q && q->flags&TCQ_F_INGRESS) {
 			*old = dev_graft_qdisc(dev, q);
 		} else {
@@ -596,7 +595,7 @@
 				q = qdisc_leaf(p, clid);
 			} else { /* ingress */
 				q = dev->qdisc_ingress;
-                        }
+			}
 		} else {
 			q = dev->qdisc_sleeping;
 		}
@@ -743,7 +742,7 @@
 		return -ENOENT;
 	if (clid == TC_H_INGRESS)
 		q = qdisc_create(dev, tcm->tcm_parent, tca, &err);
-        else
+	else
 		q = qdisc_create(dev, tcm->tcm_handle, tca, &err);
 	if (q == NULL) {
 		if (err == -EAGAIN)
@@ -808,10 +807,10 @@
 #endif
 	    gnet_stats_copy_queue(&d, &q->qstats) < 0)
 		goto rtattr_failure;
-	
+
 	if (gnet_stats_finish_copy(&d) < 0)
 		goto rtattr_failure;
-	
+
 	nlh->nlmsg_len = skb->tail - b;
 	return skb->len;
 
@@ -954,7 +953,7 @@
 	}
 
 	/* OK. Locate qdisc */
-	if ((q = qdisc_lookup(dev, qid)) == NULL) 
+	if ((q = qdisc_lookup(dev, qid)) == NULL)
 		return -ENOENT;
 
 	/* An check that it supports classes */
@@ -978,7 +977,7 @@
 			goto out;
 	} else {
 		switch (n->nlmsg_type) {
-		case RTM_NEWTCLASS:	
+		case RTM_NEWTCLASS:
 			err = -EEXIST;
 			if (n->nlmsg_flags&NLM_F_EXCL)
 				goto out;
@@ -1162,7 +1161,7 @@
 				skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd);
 				goto reclassify;
 			} else {
-				if (skb->tc_verd) 
+				if (skb->tc_verd)
 					skb->tc_verd = SET_TC_VERD(skb->tc_verd,0);
 				return err;
 			}
@@ -1194,13 +1193,13 @@
 	return single_open(file, psched_show, PDE(inode)->data);
 }
 
-static struct file_operations psched_fops = {
+static const struct file_operations psched_fops = {
 	.owner = THIS_MODULE,
 	.open = psched_open,
 	.read  = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
-};	
+};
 #endif
 
 #ifdef CONFIG_NET_SCH_CLK_CPU
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index edc7bb0..afb3bbd 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -107,7 +107,7 @@
 	struct atm_qdisc_data *p = PRIV(sch);
 	struct atm_flow_data *flow;
 
-        for (flow = p->flows; flow; flow = flow->next)
+	for (flow = p->flows; flow; flow = flow->next)
 		if (flow->classid == classid) break;
 	return flow;
 }
@@ -125,7 +125,7 @@
 	if (!new) new = &noop_qdisc;
 	*old = xchg(&flow->q,new);
 	if (*old) qdisc_reset(*old);
-        return 0;
+	return 0;
 }
 
 
@@ -145,7 +145,7 @@
 
 	DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
 	flow = lookup_flow(sch,classid);
-        if (flow) flow->ref++;
+	if (flow) flow->ref++;
 	DPRINTK("atm_tc_get: flow %p\n",flow);
 	return (unsigned long) flow;
 }
@@ -280,9 +280,9 @@
 	    opt->rta_type,RTA_PAYLOAD(opt),hdr_len);
 	if (!(sock = sockfd_lookup(fd,&error))) return error; /* f_count++ */
 	DPRINTK("atm_tc_change: f_count %d\n",file_count(sock->file));
-        if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) {
+	if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) {
 		error = -EPROTOTYPE;
-                goto err_out;
+		goto err_out;
 	}
 	/* @@@ should check if the socket is really operational or we'll crash
 	   on vcc->send */
@@ -320,9 +320,9 @@
 		flow->q = &noop_qdisc;
 	DPRINTK("atm_tc_change: qdisc %p\n",flow->q);
 	flow->sock = sock;
-        flow->vcc = ATM_SD(sock); /* speedup */
+	flow->vcc = ATM_SD(sock); /* speedup */
 	flow->vcc->user_back = flow;
-        DPRINTK("atm_tc_change: vcc %p\n",flow->vcc);
+	DPRINTK("atm_tc_change: vcc %p\n",flow->vcc);
 	flow->old_pop = flow->vcc->pop;
 	flow->parent = p;
 	flow->vcc->pop = sch_atm_pop;
@@ -391,7 +391,7 @@
 	struct atm_flow_data *flow = (struct atm_flow_data *) cl;
 
 	DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n",sch,p,flow);
-        return flow ? &flow->filter_list : &p->link.filter_list;
+	return flow ? &flow->filter_list : &p->link.filter_list;
 }
 
 
@@ -546,8 +546,8 @@
 	D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
 	ret = p->link.q->ops->requeue(skb,p->link.q);
 	if (!ret) {
-        sch->q.qlen++;
-        sch->qstats.requeues++;
+	sch->q.qlen++;
+	sch->qstats.requeues++;
     } else {
 		sch->qstats.drops++;
 		p->link.qstats.drops++;
@@ -726,7 +726,7 @@
 	return register_qdisc(&atm_qdisc_ops);
 }
 
-static void __exit atm_exit(void) 
+static void __exit atm_exit(void)
 {
 	unregister_qdisc(&atm_qdisc_ops);
 }
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index f79a4f3..76c92e7 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -16,7 +16,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -40,12 +39,12 @@
 	=======================================
 
 	Sources: [1] Sally Floyd and Van Jacobson, "Link-sharing and Resource
-	         Management Models for Packet Networks",
+		 Management Models for Packet Networks",
 		 IEEE/ACM Transactions on Networking, Vol.3, No.4, 1995
 
-	         [2] Sally Floyd, "Notes on CBQ and Guaranteed Service", 1995
+		 [2] Sally Floyd, "Notes on CBQ and Guaranteed Service", 1995
 
-	         [3] Sally Floyd, "Notes on Class-Based Queueing: Setting
+		 [3] Sally Floyd, "Notes on Class-Based Queueing: Setting
 		 Parameters", 1996
 
 		 [4] Sally Floyd and Michael Speer, "Experimental Results
@@ -59,12 +58,12 @@
 	the implementation is different. Particularly:
 
 	--- The WRR algorithm is different. Our version looks more
-        reasonable (I hope) and works when quanta are allowed to be
-        less than MTU, which is always the case when real time classes
-        have small rates. Note, that the statement of [3] is
-        incomplete, delay may actually be estimated even if class
-        per-round allotment is less than MTU. Namely, if per-round
-        allotment is W*r_i, and r_1+...+r_k = r < 1
+	reasonable (I hope) and works when quanta are allowed to be
+	less than MTU, which is always the case when real time classes
+	have small rates. Note, that the statement of [3] is
+	incomplete, delay may actually be estimated even if class
+	per-round allotment is less than MTU. Namely, if per-round
+	allotment is W*r_i, and r_1+...+r_k = r < 1
 
 	delay_i <= ([MTU/(W*r_i)]*W*r + W*r + k*MTU)/B
 
@@ -280,7 +279,7 @@
 #ifdef CONFIG_NET_CLS_ACT
 		switch (result) {
 		case TC_ACT_QUEUED:
-		case TC_ACT_STOLEN: 
+		case TC_ACT_STOLEN:
 			*qerr = NET_XMIT_SUCCESS;
 		case TC_ACT_SHOT:
 			return NULL;
@@ -479,7 +478,7 @@
 	if (!cl->delayed) {
 		delay += cl->offtime;
 
-		/* 
+		/*
 		   Class goes to sleep, so that it will have no
 		   chance to work avgidle. Let's forgive it 8)
 
@@ -717,7 +716,7 @@
 }
 #endif
 
-/* 
+/*
    It is mission critical procedure.
 
    We "regenerate" toplevel cutoff, if transmitting class
@@ -739,7 +738,7 @@
 				}
 			} while ((borrowed=borrowed->borrow) != NULL);
 		}
-#if 0	
+#if 0
 	/* It is not necessary now. Uncommenting it
 	   will save CPU cycles, but decrease fairness.
 	 */
@@ -768,7 +767,7 @@
 		   (now - last) is total time between packet right edges.
 		   (last_pktlen/rate) is "virtual" busy time, so that
 
-		         idle = (now - last) - last_pktlen/rate
+			 idle = (now - last) - last_pktlen/rate
 		 */
 
 		idle = PSCHED_TDIFF(q->now, cl->last);
@@ -907,7 +906,7 @@
 			skb = cl->q->dequeue(cl->q);
 
 			/* Class did not give us any skb :-(
-			   It could occur even if cl->q->q.qlen != 0 
+			   It could occur even if cl->q->q.qlen != 0
 			   f.e. if cl->q == "tbf"
 			 */
 			if (skb == NULL)
@@ -2131,7 +2130,7 @@
 {
 	return register_qdisc(&cbq_qdisc_ops);
 }
-static void __exit cbq_module_exit(void) 
+static void __exit cbq_module_exit(void)
 {
 	unregister_qdisc(&cbq_qdisc_ops);
 }
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index d542181..96324cf 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -68,7 +68,7 @@
 			return 0;
 		indices >>= 1;
 	}
- 
+
 	return 1;
 }
 
@@ -100,7 +100,7 @@
 	qdisc_reset(*old);
 	sch_tree_unlock(sch);
 
-        return 0;
+	return 0;
 }
 
 static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
@@ -151,7 +151,7 @@
 
 	if (tb[TCA_DSMARK_VALUE-1])
 		p->value[*arg-1] = RTA_GET_U8(tb[TCA_DSMARK_VALUE-1]);
-		
+
 	if (tb[TCA_DSMARK_MASK-1])
 		p->mask[*arg-1] = mask;
 
@@ -167,7 +167,7 @@
 
 	if (!dsmark_valid_index(p, arg))
 		return -EINVAL;
-	
+
 	p->mask[arg-1] = 0xff;
 	p->value[arg-1] = 0;
 
@@ -193,9 +193,9 @@
 				break;
 			}
 		}
-ignore:		
+ignore:
 		walker->count++;
-        }
+	}
 }
 
 static struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch,unsigned long cl)
@@ -338,7 +338,7 @@
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
 	unsigned int len;
-	
+
 	DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
 
 	if (p->q->ops->drop == NULL)
@@ -506,7 +506,7 @@
 	return register_qdisc(&dsmark_qdisc_ops);
 }
 
-static void __exit dsmark_module_exit(void) 
+static void __exit dsmark_module_exit(void)
 {
 	unregister_qdisc(&dsmark_qdisc_ops);
 }
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index bc116bd..52eb343 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -36,7 +36,7 @@
 
 /* Main transmission queue. */
 
-/* Main qdisc structure lock. 
+/* Main qdisc structure lock.
 
    However, modifications
    to data, participating in scheduling must be additionally
@@ -66,7 +66,7 @@
 	write_unlock(&qdisc_tree_lock);
 }
 
-/* 
+/*
    dev->queue_lock serializes queue accesses for this device
    AND dev->qdisc pointer itself.
 
@@ -82,7 +82,7 @@
    we do not check dev->tbusy flag here.
 
    Returns:  0  - queue is empty.
-            >0  - queue is not empty, but throttled.
+	    >0  - queue is not empty, but throttled.
 	    <0  - queue is not empty. Device is throttled, if dev->tbusy != 0.
 
    NOTE: Called under dev->queue_lock with locally disabled BH.
@@ -112,7 +112,7 @@
 			if (!netif_tx_trylock(dev)) {
 			collision:
 				/* So, someone grabbed the driver. */
-				
+
 				/* It may be transient configuration error,
 				   when hard_start_xmit() recurses. We detect
 				   it by checking xmit owner and drop the
@@ -128,7 +128,7 @@
 				goto requeue;
 			}
 		}
-		
+
 		{
 			/* And release queue */
 			spin_unlock(&dev->queue_lock);
@@ -137,7 +137,7 @@
 				int ret;
 
 				ret = dev_hard_start_xmit(skb, dev);
-				if (ret == NETDEV_TX_OK) { 
+				if (ret == NETDEV_TX_OK) {
 					if (!nolock) {
 						netif_tx_unlock(dev);
 					}
@@ -146,15 +146,15 @@
 				}
 				if (ret == NETDEV_TX_LOCKED && nolock) {
 					spin_lock(&dev->queue_lock);
-					goto collision; 
+					goto collision;
 				}
 			}
 
 			/* NETDEV_TX_BUSY - we need to requeue */
 			/* Release the driver */
-			if (!nolock) { 
+			if (!nolock) {
 				netif_tx_unlock(dev);
-			} 
+			}
 			spin_lock(&dev->queue_lock);
 			q = dev->qdisc;
 		}
@@ -209,7 +209,7 @@
 				       dev->name);
 				dev->tx_timeout(dev);
 			}
-			if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo))
+			if (!mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + dev->watchdog_timeo)))
 				dev_hold(dev);
 		}
 	}
@@ -300,7 +300,7 @@
 	.enqueue	=	noop_enqueue,
 	.dequeue	=	noop_dequeue,
 	.flags		=	TCQ_F_BUILTIN,
-	.ops		=	&noop_qdisc_ops,	
+	.ops		=	&noop_qdisc_ops,
 	.list		=	LIST_HEAD_INIT(noop_qdisc.list),
 };
 
@@ -454,7 +454,7 @@
 				 unsigned int parentid)
 {
 	struct Qdisc *sch;
-	
+
 	sch = qdisc_alloc(dev, ops);
 	if (IS_ERR(sch))
 		goto errout;
@@ -478,7 +478,7 @@
 		ops->reset(qdisc);
 }
 
-/* this is the rcu callback function to clean up a qdisc when there 
+/* this is the rcu callback function to clean up a qdisc when there
  * are no further references to it */
 
 static void __qdisc_destroy(struct rcu_head *head)
@@ -600,10 +600,10 @@
 	dev->qdisc_sleeping = &noop_qdisc;
 	qdisc_destroy(qdisc);
 #if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE)
-        if ((qdisc = dev->qdisc_ingress) != NULL) {
+	if ((qdisc = dev->qdisc_ingress) != NULL) {
 		dev->qdisc_ingress = NULL;
 		qdisc_destroy(qdisc);
-        }
+	}
 #endif
 	BUG_TRAP(!timer_pending(&dev->watchdog_timer));
 	qdisc_unlock_tree(dev);
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 18e81a8..fa1b4fe 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -335,7 +335,7 @@
 
 	qdisc_reset_queue(sch);
 
-        for (i = 0; i < t->DPs; i++) {
+	for (i = 0; i < t->DPs; i++) {
 		struct gred_sched_data *q = t->tab[i];
 
 		if (!q)
@@ -393,7 +393,7 @@
 			       "shadowed VQ 0x%x\n", i);
 			gred_destroy_vq(table->tab[i]);
 			table->tab[i] = NULL;
-  		}
+		}
 	}
 
 	return 0;
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 6eefa69..396deb7 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -71,8 +71,6 @@
 #include <asm/system.h>
 #include <asm/div64.h>
 
-#define HFSC_DEBUG 1
-
 /*
  * kernel internal service curve representation:
  *   coordinates are given by 64 bit unsigned integers.
@@ -211,17 +209,6 @@
 } while (0)
 #endif
 
-#if HFSC_DEBUG
-#define ASSERT(cond)							\
-do {									\
-	if (unlikely(!(cond)))						\
-		printk("assertion %s failed at %s:%i (%s)\n",		\
-		       #cond, __FILE__, __LINE__, __FUNCTION__);	\
-} while (0)
-#else
-#define ASSERT(cond)
-#endif /* HFSC_DEBUG */
-
 #define	HT_INFINITY	0xffffffffffffffffULL	/* infinite time value */
 
 
@@ -284,7 +271,7 @@
 eltree_get_minel(struct hfsc_sched *q)
 {
 	struct rb_node *n;
-	
+
 	n = rb_first(&q->eligible);
 	if (n == NULL)
 		return NULL;
@@ -773,7 +760,7 @@
 			/* update the virtual curve */
 			vt = cl->cl_vt + cl->cl_vtoff;
 			rtsc_min(&cl->cl_virtual, &cl->cl_fsc, vt,
-			                              cl->cl_total);
+						      cl->cl_total);
 			if (cl->cl_virtual.x == vt) {
 				cl->cl_virtual.x -= cl->cl_vtoff;
 				cl->cl_vtoff = 0;
@@ -796,10 +783,10 @@
 
 				/* update the ulimit curve */
 				rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time,
-				         cl->cl_total);
+					 cl->cl_total);
 				/* compute myf */
 				cl->cl_myf = rtsc_y2x(&cl->cl_ulimit,
-				                      cl->cl_total);
+						      cl->cl_total);
 				cl->cl_myfadj = 0;
 			}
 		}
@@ -853,7 +840,7 @@
 		 * update vt and f
 		 */
 		cl->cl_vt = rtsc_y2x(&cl->cl_virtual, cl->cl_total)
-		            - cl->cl_vtoff + cl->cl_vtadj;
+			    - cl->cl_vtoff + cl->cl_vtadj;
 
 		/*
 		 * if vt of the class is smaller than cvtmin,
@@ -870,7 +857,7 @@
 
 		if (cl->cl_flags & HFSC_USC) {
 			cl->cl_myf = cl->cl_myfadj + rtsc_y2x(&cl->cl_ulimit,
-			                                      cl->cl_total);
+							      cl->cl_total);
 #if 0
 			/*
 			 * This code causes classes to stay way under their
@@ -1001,7 +988,7 @@
 
 static void
 hfsc_change_rsc(struct hfsc_class *cl, struct tc_service_curve *rsc,
-                u64 cur_time)
+		u64 cur_time)
 {
 	sc2isc(rsc, &cl->cl_rsc);
 	rtsc_init(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul);
@@ -1023,7 +1010,7 @@
 
 static void
 hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
-                u64 cur_time)
+		u64 cur_time)
 {
 	sc2isc(usc, &cl->cl_usc);
 	rtsc_init(&cl->cl_ulimit, &cl->cl_usc, cur_time, cl->cl_total);
@@ -1032,7 +1019,7 @@
 
 static int
 hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
-                  struct rtattr **tca, unsigned long *arg)
+		  struct rtattr **tca, unsigned long *arg)
 {
 	struct hfsc_sched *q = qdisc_priv(sch);
 	struct hfsc_class *cl = (struct hfsc_class *)*arg;
@@ -1228,9 +1215,9 @@
 #ifdef CONFIG_NET_CLS_ACT
 		switch (result) {
 		case TC_ACT_QUEUED:
-		case TC_ACT_STOLEN: 
+		case TC_ACT_STOLEN:
 			*qerr = NET_XMIT_SUCCESS;
-		case TC_ACT_SHOT: 
+		case TC_ACT_SHOT:
 			return NULL;
 		}
 #elif defined(CONFIG_NET_CLS_POLICE)
@@ -1259,7 +1246,7 @@
 
 static int
 hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
-                 struct Qdisc **old)
+		 struct Qdisc **old)
 {
 	struct hfsc_class *cl = (struct hfsc_class *)arg;
 
@@ -1397,7 +1384,7 @@
 
 static int
 hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb,
-                struct tcmsg *tcm)
+		struct tcmsg *tcm)
 {
 	struct hfsc_class *cl = (struct hfsc_class *)arg;
 	unsigned char *b = skb->tail;
@@ -1492,7 +1479,7 @@
 		if (next_time == 0 || next_time > q->root.cl_cfmin)
 			next_time = q->root.cl_cfmin;
 	}
-	ASSERT(next_time != 0);
+	WARN_ON(next_time == 0);
 	delay = next_time - cur_time;
 	delay = PSCHED_US2JIFFIE(delay);
 
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 15f23c5..97cbb9a 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -11,7 +11,7 @@
  * Credits (in time order) for older HTB versions:
  *              Stef Coene <stef.coene@docum.org>
  *			HTB support at LARTC mailing list
- *		Ondrej Kraus, <krauso@barr.cz> 
+ *		Ondrej Kraus, <krauso@barr.cz>
  *			found missing INIT_QDISC(htb)
  *		Vladimir Smelhaus, Aamer Akhter, Bert Hubert
  *			helped a lot to locate nasty class stall bug
@@ -33,7 +33,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -59,11 +58,11 @@
     Author: devik@cdi.cz
     ========================================================================
     HTB is like TBF with multiple classes. It is also similar to CBQ because
-    it allows to assign priority to each class in hierarchy. 
+    it allows to assign priority to each class in hierarchy.
     In fact it is another implementation of Floyd's formal sharing.
 
     Levels:
-    Each class is assigned level. Leaf has ALWAYS level 0 and root 
+    Each class is assigned level. Leaf has ALWAYS level 0 and root
     classes have level TC_HTB_MAXDEPTH-1. Interior nodes has level
     one less than their parent.
 */
@@ -245,7 +244,7 @@
  * We allow direct class selection by classid in priority. The we examine
  * filters in qdisc and in inner nodes (if higher filter points to the inner
  * node). If we end up with classid MAJOR:0 we enqueue the skb into special
- * internal fifo (direct). These packets then go directly thru. If we still 
+ * internal fifo (direct). These packets then go directly thru. If we still
  * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull
  * then finish and return direct queue.
  */
@@ -433,7 +432,7 @@
  * htb_activate_prios - creates active classe's feed chain
  *
  * The class is connected to ancestors and/or appropriate rows
- * for priorities it is participating on. cl->cmode must be new 
+ * for priorities it is participating on. cl->cmode must be new
  * (activated) mode. It does nothing if cl->prio_activity == 0.
  */
 static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
@@ -466,7 +465,7 @@
 /**
  * htb_deactivate_prios - remove class from feed chain
  *
- * cl->cmode must represent old mode (before deactivation). It does 
+ * cl->cmode must represent old mode (before deactivation). It does
  * nothing if cl->prio_activity == 0. Class is removed from all feed
  * chains and rows.
  */
@@ -524,9 +523,9 @@
  *
  * It computes cl's mode at time cl->t_c+diff and returns it. If mode
  * is not HTB_CAN_SEND then cl->pq_key is updated to time difference
- * from now to time when cl will change its state. 
+ * from now to time when cl will change its state.
  * Also it is worth to note that class mode doesn't change simply
- * at cl->{c,}tokens == 0 but there can rather be hysteresis of 
+ * at cl->{c,}tokens == 0 but there can rather be hysteresis of
  * 0 .. -cl->{c,}buffer range. It is meant to limit number of
  * mode transitions per time unit. The speed gain is about 1/6.
  */
@@ -575,7 +574,7 @@
 }
 
 /**
- * htb_activate - inserts leaf cl into appropriate active feeds 
+ * htb_activate - inserts leaf cl into appropriate active feeds
  *
  * Routine learns (new) priority of leaf and activates feed chain
  * for the prio. It can be called on already active leaf safely.
@@ -594,7 +593,7 @@
 }
 
 /**
- * htb_deactivate - remove leaf cl from active feeds 
+ * htb_deactivate - remove leaf cl from active feeds
  *
  * Make sure that leaf is active. In the other words it can't be called
  * with non-active leaf. It also removes class from the drop list.
@@ -854,7 +853,7 @@
 
 	for (i = 0; i < 65535; i++) {
 		if (!*sp->pptr && *sp->pid) {
-			/* ptr was invalidated but id is valid - try to recover 
+			/* ptr was invalidated but id is valid - try to recover
 			   the original or next ptr */
 			*sp->pptr =
 			    htb_id_find_next_upper(prio, sp->root, *sp->pid);
@@ -906,7 +905,7 @@
 
 		/* class can be empty - it is unlikely but can be true if leaf
 		   qdisc drops packets in enqueue routine or if someone used
-		   graft operation on the leaf since last dequeue; 
+		   graft operation on the leaf since last dequeue;
 		   simply deactivate and skip such class */
 		if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
 			struct htb_class *next;
@@ -1229,7 +1228,7 @@
 	if (cl && !cl->level) {
 		if (new == NULL &&
 		    (new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
-		    			     cl->classid))
+					     cl->classid))
 		    == NULL)
 			return -ENOBUFS;
 		sch_tree_lock(sch);
@@ -1347,7 +1346,7 @@
 	del_timer_sync(&q->rttim);
 #endif
 	/* This line used to be after htb_destroy_class call below
-	   and surprisingly it worked in 2.4. But it must precede it 
+	   and surprisingly it worked in 2.4. But it must precede it
 	   because filter need its target class alive to be able to call
 	   unbind_filter on it (without Oops). */
 	htb_destroy_filters(&q->filter_list);
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index c3242f7..cfe070e 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -1,4 +1,4 @@
-/* net/sched/sch_ingress.c - Ingress qdisc 
+/* net/sched/sch_ingress.c - Ingress qdisc
  *              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
@@ -47,7 +47,7 @@
 */
 #ifndef CONFIG_NET_CLS_ACT
 #ifdef CONFIG_NETFILTER
-static int nf_registered; 
+static int nf_registered;
 #endif
 #endif
 
@@ -70,7 +70,7 @@
 	DPRINTK("ingress_graft(sch %p,[qdisc %p],new %p,old %p)\n",
 		sch, p, new, old);
 	DPRINTK("\n ingress_graft: You cannot add qdiscs to classes");
-        return 1;
+	return 1;
 }
 
 
@@ -162,7 +162,7 @@
 		case TC_ACT_QUEUED:
 			result = TC_ACT_STOLEN;
 			break;
-		case TC_ACT_RECLASSIFY: 
+		case TC_ACT_RECLASSIFY:
 		case TC_ACT_OK:
 		case TC_ACT_UNSPEC:
 		default:
@@ -172,7 +172,7 @@
 	};
 /* backward compat */
 #else
-#ifdef	CONFIG_NET_CLS_POLICE  
+#ifdef	CONFIG_NET_CLS_POLICE
 	switch (result) {
 		case TC_POLICE_SHOT:
 		result = NF_DROP;
@@ -232,14 +232,14 @@
 #ifdef CONFIG_NETFILTER
 static unsigned int
 ing_hook(unsigned int hook, struct sk_buff **pskb,
-                             const struct net_device *indev,
-                             const struct net_device *outdev,
-	                     int (*okfn)(struct sk_buff *))
+			     const struct net_device *indev,
+			     const struct net_device *outdev,
+			     int (*okfn)(struct sk_buff *))
 {
-	
+
 	struct Qdisc *q;
 	struct sk_buff *skb = *pskb;
-        struct net_device *dev = skb->dev;
+	struct net_device *dev = skb->dev;
 	int fwres=NF_ACCEPT;
 
 	DPRINTK("ing_hook: skb %s dev=%s len=%u\n",
@@ -247,7 +247,7 @@
 		skb->dev ? (*pskb)->dev->name : "(no dev)",
 		skb->len);
 
-/* 
+/*
 revisit later: Use a private since lock dev->queue_lock is also
 used on the egress (might slow things for an iota)
 */
@@ -257,8 +257,8 @@
 		if ((q = dev->qdisc_ingress) != NULL)
 			fwres = q->enqueue(skb, q);
 		spin_unlock(&dev->queue_lock);
-        }
-			
+	}
+
 	return fwres;
 }
 
@@ -296,7 +296,7 @@
 	printk("Ingress scheduler: Classifier actions prefered over netfilter\n");
 #endif
 #endif
-                                                                                
+
 #ifndef CONFIG_NET_CLS_ACT
 #ifdef CONFIG_NETFILTER
 	if (!nf_registered) {
@@ -417,7 +417,7 @@
 
 	return ret;
 }
-static void __exit ingress_module_exit(void) 
+static void __exit ingress_module_exit(void)
 {
 	unregister_qdisc(&ingress_qdisc_ops);
 #ifndef CONFIG_NET_CLS_ACT
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 79542af..1ccbfb5 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -7,7 +7,7 @@
  * 		2 of the License.
  *
  *  		Many of the algorithms and ideas for this came from
- *		NIST Net which is not copyrighted. 
+ *		NIST Net which is not copyrighted.
  *
  * Authors:	Stephen Hemminger <shemminger@osdl.org>
  *		Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
@@ -114,7 +114,7 @@
  * std deviation sigma.  Uses table lookup to approximate the desired
  * distribution, and a uniformly-distributed pseudo-random source.
  */
-static long tabledist(unsigned long mu, long sigma, 
+static long tabledist(unsigned long mu, long sigma,
 		      struct crndstate *state, const struct disttable *dist)
 {
 	long t, x;
@@ -126,7 +126,7 @@
 	rnd = get_crandom(state);
 
 	/* default uniform distribution */
-	if (dist == NULL) 
+	if (dist == NULL)
 		return (rnd % (2*sigma)) - sigma + mu;
 
 	t = dist->table[rnd % dist->size];
@@ -218,7 +218,7 @@
 		++q->counter;
 		ret = q->qdisc->enqueue(skb, q->qdisc);
 	} else {
-		/* 
+		/*
 		 * Do re-ordering by putting one out of N packets at the front
 		 * of the queue.
 		 */
@@ -323,7 +323,7 @@
 /* Pass size change message down to embedded FIFO */
 static int set_fifo_limit(struct Qdisc *q, int limit)
 {
-        struct rtattr *rta;
+	struct rtattr *rta;
 	int ret = -ENOMEM;
 
 	/* Hack to avoid sending change message to non-FIFO */
@@ -333,9 +333,9 @@
 	rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
 	if (rta) {
 		rta->rta_type = RTM_NEWQDISC;
-		rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); 
+		rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
 		((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
-		
+
 		ret = q->ops->change(q, rta);
 		kfree(rta);
 	}
@@ -364,7 +364,7 @@
 	d->size = n;
 	for (i = 0; i < n; i++)
 		d->table[i] = data[i];
-	
+
 	spin_lock_bh(&sch->dev->queue_lock);
 	d = xchg(&q->delay_dist, d);
 	spin_unlock_bh(&sch->dev->queue_lock);
@@ -419,7 +419,7 @@
 	struct netem_sched_data *q = qdisc_priv(sch);
 	struct tc_netem_qopt *qopt;
 	int ret;
-	
+
 	if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
 		return -EINVAL;
 
@@ -429,7 +429,7 @@
 		pr_debug("netem: can't set fifo limit\n");
 		return ret;
 	}
-	
+
 	q->latency = qopt->latency;
 	q->jitter = qopt->jitter;
 	q->limit = qopt->limit;
@@ -445,10 +445,10 @@
 
 	/* Handle nested options after initial queue options.
 	 * Should have put all options in nested format but too late now.
-	 */ 
+	 */
 	if (RTA_PAYLOAD(opt) > sizeof(*qopt)) {
 		struct rtattr *tb[TCA_NETEM_MAX];
-		if (rtattr_parse(tb, TCA_NETEM_MAX, 
+		if (rtattr_parse(tb, TCA_NETEM_MAX,
 				 RTA_DATA(opt) + sizeof(*qopt),
 				 RTA_PAYLOAD(opt) - sizeof(*qopt)))
 			return -EINVAL;
@@ -681,7 +681,7 @@
 {
 }
 
-static int netem_change_class(struct Qdisc *sch, u32 classid, u32 parentid, 
+static int netem_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 			    struct rtattr **tca, unsigned long *arg)
 {
 	return -ENOSYS;
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 2567b4c..de889f2 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -7,7 +7,7 @@
  *		2 of the License, or (at your option) any later version.
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
- * Fixes:       19990609: J Hadi Salim <hadi@nortelnetworks.com>: 
+ * Fixes:       19990609: J Hadi Salim <hadi@nortelnetworks.com>:
  *              Init --  EINVAL when opt undefined
  */
 
@@ -17,7 +17,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -105,7 +104,7 @@
 		return NET_XMIT_SUCCESS;
 	}
 	sch->qstats.drops++;
-	return ret; 
+	return ret;
 }
 
 
@@ -372,6 +371,20 @@
 	return 0;
 }
 
+static int prio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
+				 struct gnet_dump *d)
+{
+	struct prio_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *cl_q;
+
+	cl_q = q->queues[cl - 1];
+	if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 ||
+	    gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
+		return -1;
+
+	return 0;
+}
+
 static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
 {
 	struct prio_sched_data *q = qdisc_priv(sch);
@@ -414,6 +427,7 @@
 	.bind_tcf	=	prio_bind,
 	.unbind_tcf	=	prio_put,
 	.dump		=	prio_dump_class,
+	.dump_stats	=	prio_dump_class_stats,
 };
 
 static struct Qdisc_ops prio_qdisc_ops = {
@@ -438,7 +452,7 @@
 	return register_qdisc(&prio_qdisc_ops);
 }
 
-static void __exit prio_module_exit(void) 
+static void __exit prio_module_exit(void)
 {
 	unregister_qdisc(&prio_qdisc_ops);
 }
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index acddad0..00db53e 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -185,7 +185,7 @@
 			      TC_H_MAKE(sch->handle, 1));
 	if (q) {
 		rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)),
-		              GFP_KERNEL);
+			      GFP_KERNEL);
 		if (rta) {
 			rta->rta_type = RTM_NEWQDISC;
 			rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 459cda2..66f3205 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -53,7 +53,7 @@
 	Queuing using Deficit Round Robin", Proc. SIGCOMM 95.
 
 
-	This is not the thing that is usually called (W)FQ nowadays. 
+	This is not the thing that is usually called (W)FQ nowadays.
 	It does not use any timestamp mechanism, but instead
 	processes queues in round-robin order.
 
@@ -63,7 +63,7 @@
 
 	DRAWBACKS:
 
-	- "Stochastic" -> It is not 100% fair. 
+	- "Stochastic" -> It is not 100% fair.
 	When hash collisions occur, several flows are considered as one.
 
 	- "Round-robin" -> It introduces larger delays than virtual clock
@@ -143,6 +143,7 @@
 		if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
 		    (iph->protocol == IPPROTO_TCP ||
 		     iph->protocol == IPPROTO_UDP ||
+		     iph->protocol == IPPROTO_UDPLITE ||
 		     iph->protocol == IPPROTO_SCTP ||
 		     iph->protocol == IPPROTO_DCCP ||
 		     iph->protocol == IPPROTO_ESP))
@@ -156,6 +157,7 @@
 		h2 = iph->saddr.s6_addr32[3]^iph->nexthdr;
 		if (iph->nexthdr == IPPROTO_TCP ||
 		    iph->nexthdr == IPPROTO_UDP ||
+		    iph->nexthdr == IPPROTO_UDPLITE ||
 		    iph->nexthdr == IPPROTO_SCTP ||
 		    iph->nexthdr == IPPROTO_DCCP ||
 		    iph->nexthdr == IPPROTO_ESP)
@@ -499,7 +501,7 @@
 {
 	return register_qdisc(&sfq_qdisc_ops);
 }
-static void __exit sfq_module_exit(void) 
+static void __exit sfq_module_exit(void)
 {
 	unregister_qdisc(&sfq_qdisc_ops);
 }
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index ed9b6d9..85da8da 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -276,7 +276,7 @@
 static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit)
 {
 	struct Qdisc *q;
-        struct rtattr *rta;
+	struct rtattr *rta;
 	int ret;
 
 	q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops,
@@ -285,7 +285,7 @@
 		rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
 		if (rta) {
 			rta->rta_type = RTM_NEWQDISC;
-			rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); 
+			rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
 			((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
 
 			ret = q->ops->change(q, rta);
@@ -475,7 +475,7 @@
 {
 }
 
-static int tbf_change_class(struct Qdisc *sch, u32 classid, u32 parentid, 
+static int tbf_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 			    struct rtattr **tca, unsigned long *arg)
 {
 	return -ENOSYS;
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 4c16ad5..587123c 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -14,7 +14,6 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -178,7 +177,7 @@
 				teql_neigh_release(xchg(&dat->ncache, NULL));
 				break;
 			}
-				
+
 		} while ((prev = q) != master->slaves);
 	}
 }
@@ -292,7 +291,7 @@
 
 	do {
 		struct net_device *slave = q->dev;
-		
+
 		if (slave->qdisc_sleeping != q)
 			continue;
 		if (netif_queue_stopped(slave) || ! netif_running(slave)) {
@@ -425,7 +424,7 @@
 
 	master->dev	= dev;
 	ops->priv_size  = sizeof(struct teql_sched_data);
-	
+
 	ops->enqueue	=	teql_enqueue;
 	ops->dequeue	=	teql_dequeue;
 	ops->requeue	=	teql_requeue;
@@ -489,7 +488,7 @@
 	return i ? 0 : err;
 }
 
-static void __exit teql_exit(void) 
+static void __exit teql_exit(void)
 {
 	struct teql_master *master, *nxt;
 
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 5db95ca..fa82b73 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -52,7 +52,6 @@
 #include <linux/fcntl.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 
 #include <linux/slab.h>
 #include <linux/in.h>
@@ -158,14 +157,14 @@
 	 * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
 	 * recommended value of 5 times 'RTO.Max'.
 	 */
-        asoc->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
 		= 5 * asoc->rto_max;
 
 	asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
 	asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
 	asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
 		sp->autoclose * HZ;
-	
+
 	/* Initilizes the timers */
 	for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) {
 		init_timer(&asoc->timers[i]);
@@ -1334,8 +1333,8 @@
 				      asoc->ep->base.bind_addr.port, gfp);
 }
 
-/* Lookup laddr in the bind address list of an association. */ 
-int sctp_assoc_lookup_laddr(struct sctp_association *asoc, 
+/* Lookup laddr in the bind address list of an association. */
+int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
 			    const union sctp_addr *laddr)
 {
 	int found;
@@ -1343,7 +1342,7 @@
 	sctp_read_lock(&asoc->base.addr_lock);
 	if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) &&
 	    sctp_bind_addr_match(&asoc->base.bind_addr, laddr,
-			         sctp_sk(asoc->base.sk))) {
+				 sctp_sk(asoc->base.sk))) {
 		found = 1;
 		goto out;
 	}
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 0099415..fdb287a 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -43,7 +43,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/in.h>
 #include <net/sock.h>
 #include <net/ipv6.h>
@@ -62,7 +61,7 @@
 /* Copy 'src' to 'dest' taking 'scope' into account.  Omit addresses
  * in 'src' which have a broader scope than 'scope'.
  */
-int sctp_bind_addr_copy(struct sctp_bind_addr *dest, 
+int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
 			const struct sctp_bind_addr *src,
 			sctp_scope_t scope, gfp_t gfp,
 			int flags)
@@ -296,7 +295,7 @@
  ********************************************************************/
 
 /* Does this contain a specified address?  Allow wildcarding. */
-int sctp_bind_addr_match(struct sctp_bind_addr *bp, 
+int sctp_bind_addr_match(struct sctp_bind_addr *bp,
 			 const union sctp_addr *addr,
 			 struct sctp_sock *opt)
 {
@@ -306,7 +305,7 @@
 	list_for_each(pos, &bp->address_list) {
 		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		if (opt->pf->cmp_addr(&laddr->a, addr, opt))
- 			return 1;
+			return 1;
 	}
 
 	return 0;
@@ -329,12 +328,12 @@
 
 	list_for_each(pos, &bp->address_list) {
 		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
-		
+
 		addr_buf = (union sctp_addr *)addrs;
 		for (i = 0; i < addrcnt; i++) {
 			addr = (union sctp_addr *)addr_buf;
 			af = sctp_get_af_specific(addr->v4.sin_family);
-			if (!af) 
+			if (!af)
 				return NULL;
 
 			if (opt->pf->cmp_addr(&laddr->a, addr, opt))
@@ -350,7 +349,7 @@
 }
 
 /* Copy out addresses from the global local address list. */
-static int sctp_copy_one_addr(struct sctp_bind_addr *dest, 
+static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
 			      union sctp_addr *addr,
 			      sctp_scope_t scope, gfp_t gfp,
 			      int flags)
diff --git a/net/sctp/crc32c.c b/net/sctp/crc32c.c
index 31f05ec..59cf7b0 100644
--- a/net/sctp/crc32c.c
+++ b/net/sctp/crc32c.c
@@ -1,40 +1,40 @@
 /* SCTP kernel reference Implementation
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2003 International Business Machines, Corp.
- * 
+ *
  * This file is part of the SCTP kernel reference Implementation
- * 
+ *
  * SCTP Checksum functions
- * 
- * The SCTP reference implementation is free software; 
- * you can redistribute it and/or modify it under the terms of 
+ *
+ * The SCTP reference implementation 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.
- * 
- * The SCTP reference implementation is distributed in the hope that it 
+ *
+ * The SCTP reference implementation 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 GNU CC; see the file COPYING.  If not, write to
  * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.  
- * 
+ * Boston, MA 02111-1307, USA.
+ *
  * Please send any bug reports or fixes you make to the
  * email address(es):
  *    lksctp developers <lksctp-developers@lists.sourceforge.net>
- * 
+ *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
  *
- * Written or modified by: 
- *    Dinakaran Joseph 
+ * Written or modified by:
+ *    Dinakaran Joseph
  *    Jon Grimm <jgrimm@us.ibm.com>
  *    Sridhar Samudrala <sri@us.ibm.com>
- * 
+ *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
  */
@@ -135,10 +135,10 @@
 	0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
 	0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
 };
-     
+
 __u32 sctp_start_cksum(__u8 *buffer, __u16 length)
 {
-    	__u32 crc32 = ~(__u32) 0;
+	__u32 crc32 = ~(__u32) 0;
 	__u32 i;
 
 	/* Optimize this routine to be SCTP specific, knowing how
@@ -147,7 +147,7 @@
 
 	/* Calculate CRC up to the checksum. */
 	for (i = 0; i < (sizeof(struct sctphdr) - sizeof(__u32)); i++)
-      		CRC32C(crc32, buffer[i]);
+		CRC32C(crc32, buffer[i]);
 
 	/* Skip checksum field of the header. */
 	for (i = 0; i < sizeof(__u32); i++)
@@ -175,13 +175,13 @@
 	__u32 i;
 	__u32 *_to = (__u32 *)to;
 	__u32 *_from = (__u32 *)from;
-	
+
 	for (i = 0; i < (length/4); i++) {
 		_to[i] = _from[i];
 		CRC32C(crc32, from[i*4]);
 		CRC32C(crc32, from[i*4+1]);
 		CRC32C(crc32, from[i*4+2]);
-		CRC32C(crc32, from[i*4+3]);	
+		CRC32C(crc32, from[i*4+3]);
 	}
 
 	return crc32;
diff --git a/net/sctp/debug.c b/net/sctp/debug.c
index aa83403..5f5ab28 100644
--- a/net/sctp/debug.c
+++ b/net/sctp/debug.c
@@ -3,48 +3,48 @@
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
- * 
+ *
  * This file is part of the SCTP kernel reference Implementation
- * 
+ *
  * This file is part of the implementation of the add-IP extension,
  * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
  * for the SCTP kernel reference Implementation.
- * 
+ *
  * This file converts numerical ID value to alphabetical names for SCTP
  * terms such as chunk type, parameter time, event type, etc.
- * 
- * The SCTP reference implementation is free software; 
- * you can redistribute it and/or modify it under the terms of 
+ *
+ * The SCTP reference implementation 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.
- * 
- * The SCTP reference implementation is distributed in the hope that it 
+ *
+ * The SCTP reference implementation 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 GNU CC; see the file COPYING.  If not, write to
  * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.  
- * 
+ * Boston, MA 02111-1307, USA.
+ *
  * Please send any bug reports or fixes you make to the
  * email address(es):
  *    lksctp developers <lksctp-developers@lists.sourceforge.net>
- * 
+ *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
  *
- * Written or modified by: 
+ * Written or modified by:
  *    La Monte H.P. Yarroll <piggy@acm.org>
  *    Karl Knutson          <karl@athena.chicago.il.us>
  *    Xingang Guo           <xingang.guo@intel.com>
  *    Jon Grimm             <jgrimm@us.ibm.com>
  *    Daisy Chang	    <daisyc@us.ibm.com>
  *    Sridhar Samudrala	    <sri@us.ibm.com>
- * 
+ *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
  */
@@ -81,7 +81,7 @@
 		return "illegal chunk id";
 	if (cid.chunk <= SCTP_CID_BASE_MAX)
 		return sctp_cid_tbl[cid.chunk];
-	
+
 	switch (cid.chunk) {
 	case SCTP_CID_ASCONF:
 		return "ASCONF";
@@ -154,7 +154,7 @@
 
 static const char *sctp_other_tbl[] = {
 	"NO_PENDING_TSN",
-        "ICMP_PROTO_UNREACH",
+	"ICMP_PROTO_UNREACH",
 };
 
 /* Lookup "other" debug name. */
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 1297569..1404a9e 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -50,7 +50,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/random.h>	/* get_random_bytes() */
@@ -369,7 +368,7 @@
 			chunk->transport->last_time_heard = jiffies;
 
 		error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, state,
-                                   ep, asoc, chunk, GFP_ATOMIC);
+				   ep, asoc, chunk, GFP_ATOMIC);
 
 		if (error && chunk)
 			chunk->pdiscard = 1;
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 3311187..71db668 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -226,7 +226,7 @@
 	nf_reset(skb);
 
 	if (sk_filter(sk, skb))
-                goto discard_release;
+		goto discard_release;
 
 	/* Create an SCTP packet structure. */
 	chunk = sctp_chunkify(skb, asoc, sk);
@@ -293,11 +293,11 @@
 int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
- 	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
- 	struct sctp_ep_common *rcvr = NULL;
+	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
+	struct sctp_ep_common *rcvr = NULL;
 	int backloged = 0;
 
- 	rcvr = chunk->rcvr;
+	rcvr = chunk->rcvr;
 
 	/* If the rcvr is dead then the association or endpoint
 	 * has been deleted and we can safely drop the chunk
@@ -347,7 +347,7 @@
 	else
 		BUG();
 
-        return 0;
+	return 0;
 }
 
 static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
@@ -399,7 +399,7 @@
 	 * Normally, if PMTU discovery is disabled, an ICMP Fragmentation
 	 * Needed will never be sent, but if a message was sent before
 	 * PMTU discovery was disabled that was larger than the PMTU, it
-	 * would not be fragmented, so it must be re-transmitted fragmented.	 
+	 * would not be fragmented, so it must be re-transmitted fragmented.
 	 */
 	sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD);
 }
@@ -416,8 +416,8 @@
  *
  */
 void sctp_icmp_proto_unreachable(struct sock *sk,
-                           struct sctp_association *asoc,
-                           struct sctp_transport *t)
+			   struct sctp_association *asoc,
+			   struct sctp_transport *t)
 {
 	SCTP_DEBUG_PRINTK("%s\n",  __FUNCTION__);
 
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index 71b0746..c30629e 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -2,43 +2,43 @@
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2002 International Business Machines, Corp.
- * 
+ *
  * This file is part of the SCTP kernel reference Implementation
- * 
+ *
  * These functions are the methods for accessing the SCTP inqueue.
  *
  * An SCTP inqueue is a queue into which you push SCTP packets
  * (which might be bundles or fragments of chunks) and out of which you
  * pop SCTP whole chunks.
- * 
- * The SCTP reference implementation is free software; 
- * you can redistribute it and/or modify it under the terms of 
+ *
+ * The SCTP reference implementation 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.
- * 
- * The SCTP reference implementation is distributed in the hope that it 
+ *
+ * The SCTP reference implementation 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 GNU CC; see the file COPYING.  If not, write to
  * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.  
- * 
+ * Boston, MA 02111-1307, USA.
+ *
  * Please send any bug reports or fixes you make to the
  * email address(es):
  *    lksctp developers <lksctp-developers@lists.sourceforge.net>
- * 
+ *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
  *
- * Written or modified by: 
+ * Written or modified by:
  *    La Monte H.P. Yarroll <piggy@acm.org>
  *    Karl Knutson <karl@athena.chicago.il.us>
- * 
+ *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
  */
@@ -152,8 +152,8 @@
 		chunk->data_accepted = 0;
 	}
 
-        chunk->chunk_hdr = ch;
-        chunk->chunk_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+	chunk->chunk_hdr = ch;
+	chunk->chunk_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
 	/* In the unlikely case of an IP reassembly, the skb could be
 	 * non-linear. If so, update chunk_end so that it doesn't go past
 	 * the skb->tail.
@@ -169,11 +169,11 @@
 		/* This is not a singleton */
 		chunk->singleton = 0;
 	} else if (chunk->chunk_end > chunk->skb->tail) {
-                /* RFC 2960, Section 6.10  Bundling
+		/* RFC 2960, Section 6.10  Bundling
 		 *
 		 * Partial chunks MUST NOT be placed in an SCTP packet.
 		 * If the receiver detects a partial chunk, it MUST drop
-		 * the chunk.  
+		 * the chunk.
 		 *
 		 * Since the end of the chunk is past the end of our buffer
 		 * (which contains the whole packet, we can freely discard
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index ef36be07..63fe109 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -53,7 +53,6 @@
 #include <linux/socket.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
-#include <linux/sched.h>
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
@@ -236,7 +235,7 @@
 	ipv6_addr_copy(&fl.fl6_dst, &daddr->v6.sin6_addr);
 	if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
 		fl.oif = daddr->v6.sin6_scope_id;
-	
+
 
 	SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ",
 			  __FUNCTION__, NIP6(fl.fl6_dst));
diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c
index 8ff588f..fcfb9d8 100644
--- a/net/sctp/objcnt.c
+++ b/net/sctp/objcnt.c
@@ -1,39 +1,39 @@
 /* SCTP kernel reference Implementation
  * (C) Copyright IBM Corp. 2001, 2004
- * 
+ *
  * This file is part of the SCTP kernel reference Implementation
- * 
+ *
  * Support for memory object debugging.  This allows one to monitor the
- * object allocations/deallocations for types instrumented for this 
- * via the proc fs. 
- * 
- * The SCTP reference implementation is free software; 
- * you can redistribute it and/or modify it under the terms of 
+ * object allocations/deallocations for types instrumented for this
+ * via the proc fs.
+ *
+ * The SCTP reference implementation 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.
- * 
- * The SCTP reference implementation is distributed in the hope that it 
+ *
+ * The SCTP reference implementation 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 GNU CC; see the file COPYING.  If not, write to
  * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.  
- * 
+ * Boston, MA 02111-1307, USA.
+ *
  * Please send any bug reports or fixes you make to the
  * email address(es):
  *    lksctp developers <lksctp-developers@lists.sourceforge.net>
- * 
+ *
  * Or submit a bug report through the following website:
  *    http://www.sf.net/projects/lksctp
  *
- * Written or modified by: 
+ * Written or modified by:
  *    Jon Grimm             <jgrimm@us.ibm.com>
- * 
+ *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
  */
@@ -121,7 +121,7 @@
 	if (len > length)
 		len = length;
 
-  	return len;
+	return len;
 }
 
 /* Initialize the objcount in the proc filesystem.  */
@@ -131,7 +131,7 @@
 	ent = create_proc_read_entry("sctp_dbg_objcnt", 0, proc_net_sctp,
 			       sctp_dbg_objcnt_read, NULL);
 	if (!ent)
-		printk(KERN_WARNING 
+		printk(KERN_WARNING
 			"sctp_dbg_objcnt: Unable to create /proc entry.\n");
 }
 
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 3ef4351..f875fc3 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -85,8 +85,8 @@
 		chunk = sctp_get_ecne_prepend(packet->transport->asoc);
 
 		/* If there a is a prepend chunk stick it on the list before
-	 	 * any other chunks get appended.
-	 	 */
+		 * any other chunks get appended.
+		 */
 		if (chunk)
 			sctp_packet_append_chunk(packet, chunk);
 	}
@@ -110,8 +110,8 @@
 	packet->destination_port = dport;
 	INIT_LIST_HEAD(&packet->chunk_list);
 	if (asoc) {
-		struct sctp_sock *sp = sctp_sk(asoc->base.sk);	
-		overhead = sp->pf->af->net_header_len; 
+		struct sctp_sock *sp = sctp_sk(asoc->base.sk);
+		overhead = sp->pf->af->net_header_len;
 	} else {
 		overhead = sizeof(struct ipv6hdr);
 	}
@@ -442,7 +442,7 @@
 		 * acknowledged or have failed.
 		 */
 		if (!sctp_chunk_is_data(chunk))
-    			sctp_chunk_free(chunk);
+			sctp_chunk_free(chunk);
 	}
 
 	/* Perform final transformation on checksum. */
@@ -528,7 +528,7 @@
 	list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
 		list_del_init(&chunk->list);
 		if (!sctp_chunk_is_data(chunk))
-    			sctp_chunk_free(chunk);
+			sctp_chunk_free(chunk);
 	}
 	goto out;
 nomem:
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index fba567a..5c2ddd1 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -376,7 +376,7 @@
 		}
 	}
 	if (!done)
-		list_add_tail(new, head); 
+		list_add_tail(new, head);
 }
 
 /* Mark all the eligible packets on a transport for retransmission.  */
@@ -578,7 +578,7 @@
 			break;
 
 		case SCTP_XMIT_RWND_FULL:
-		        /* Send this packet. */
+			/* Send this packet. */
 			if ((error = sctp_packet_transmit(pkt)) == 0)
 				*start_timer = 1;
 
@@ -590,7 +590,7 @@
 			break;
 
 		case SCTP_XMIT_NAGLE_DELAY:
-		        /* Send this packet. */
+			/* Send this packet. */
 			if ((error = sctp_packet_transmit(pkt)) == 0)
 				*start_timer = 1;
 
@@ -605,7 +605,7 @@
 			 */
 			list_add_tail(lchunk, &transport->transmitted);
 
-			/* Mark the chunk as ineligible for fast retransmit 
+			/* Mark the chunk as ineligible for fast retransmit
 			 * after it is retransmitted.
 			 */
 			if (chunk->fast_retransmit > 0)
@@ -703,11 +703,11 @@
 			 * inactive.
 			 *
 			 * 3.3.6 Heartbeat Acknowledgement:
-			 * ...  
+			 * ...
 			 * A HEARTBEAT ACK is always sent to the source IP
 			 * address of the IP datagram containing the
 			 * HEARTBEAT chunk to which this ack is responding.
-			 * ...  
+			 * ...
 			 */
 			if (chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT &&
 			    chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT_ACK)
@@ -914,7 +914,7 @@
 				BUG();
 			}
 
-			/* BUG: We assume that the sctp_packet_transmit() 
+			/* BUG: We assume that the sctp_packet_transmit()
 			 * call below will succeed all the time and add the
 			 * chunk to the transmitted list and restart the
 			 * timers.
@@ -1266,7 +1266,7 @@
 				 * first instance of the packet or a later
 				 * instance).
 				 */
-			   	if (!tchunk->tsn_gap_acked &&
+				if (!tchunk->tsn_gap_acked &&
 				    !tchunk->resent &&
 				    tchunk->rtt_in_progress) {
 					tchunk->rtt_in_progress = 0;
@@ -1275,7 +1275,7 @@
 								  rtt);
 				}
 			}
-                        if (TSN_lte(tsn, sack_ctsn)) {
+			if (TSN_lte(tsn, sack_ctsn)) {
 				/* RFC 2960  6.3.2 Retransmission Timer Rules
 				 *
 				 * R3) Whenever a SACK is received
@@ -1590,7 +1590,7 @@
 		SCTP_DEBUG_PRINTK("%s: transport: %p, cwnd: %d, "
 				  "ssthresh: %d, flight_size: %d, pba: %d\n",
 				  __FUNCTION__, transport, transport->cwnd,
-			  	  transport->ssthresh, transport->flight_size,
+				  transport->ssthresh, transport->flight_size,
 				  transport->partial_bytes_acked);
 	}
 }
@@ -1603,7 +1603,7 @@
 	__u16 gap;
 	__u32 ctsn = ntohl(sack->cum_tsn_ack);
 
-        if (TSN_lte(tsn, ctsn))
+	if (TSN_lte(tsn, ctsn))
 		goto pass;
 
 	/* 3.3.4 Selective Acknowledgement (SACK) (3):
@@ -1657,7 +1657,7 @@
 
 	/* PR-SCTP C1) Let SackCumAck be the Cumulative TSN ACK carried in the
 	 * received SACK.
-	 * 
+	 *
 	 * If (Advanced.Peer.Ack.Point < SackCumAck), then update
 	 * Advanced.Peer.Ack.Point to be equal to SackCumAck.
 	 */
@@ -1671,7 +1671,7 @@
 	 *
 	 * Assuming that a SACK arrived with the Cumulative TSN ACK 102
 	 * and the Advanced.Peer.Ack.Point is updated to this value:
-	 * 
+	 *
 	 *   out-queue at the end of  ==>   out-queue after Adv.Ack.Point
 	 *   normal SACK processing           local advancement
 	 *                ...                           ...
@@ -1692,7 +1692,7 @@
 
 		/* Remove any chunks in the abandoned queue that are acked by
 		 * the ctsn.
-		 */ 
+		 */
 		if (TSN_lte(tsn, ctsn)) {
 			list_del_init(lchunk);
 			if (!chunk->tsn_gap_acked) {
@@ -1743,7 +1743,7 @@
 	 */
 	if (asoc->adv_peer_ack_point > ctsn)
 		ftsn_chunk = sctp_make_fwdtsn(asoc, asoc->adv_peer_ack_point,
-					      nskips, &ftsn_skip_arr[0]); 
+					      nskips, &ftsn_skip_arr[0]);
 
 	if (ftsn_chunk) {
 		list_add_tail(&ftsn_chunk->list, &q->control_chunk_list);
diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c
index 3a7ebfc..1b2976d 100644
--- a/net/sctp/primitive.c
+++ b/net/sctp/primitive.c
@@ -70,7 +70,7 @@
 	\
 	error = sctp_do_sm(event_type, subtype, state, ep, asoc, \
 			   arg, GFP_KERNEL); \
- 	return error; \
+	return error; \
 }
 
 /* 10.1 ULP-to-SCTP
@@ -207,7 +207,7 @@
 
 /* ADDIP
 * 3.1.1 Address Configuration Change Chunk (ASCONF)
-* 
+*
 * This chunk is used to communicate to the remote endpoint one of the
 * configuration change requests that MUST be acknowledged.  The
 * information carried in the ASCONF Chunk uses the form of a
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index b3493bd..2f12bf2 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -77,7 +77,7 @@
 
 /* Return the current value of a particular entry in the mib by adding its
  * per cpu counters.
- */ 
+ */
 static unsigned long
 fold_field(void *mib[], int nr)
 {
@@ -102,7 +102,7 @@
 
 	for (i = 0; sctp_snmp_list[i].name != NULL; i++)
 		seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
-			   fold_field((void **)sctp_statistics, 
+			   fold_field((void **)sctp_statistics,
 				      sctp_snmp_list[i].entry));
 
 	return 0;
@@ -114,7 +114,7 @@
 	return single_open(file, sctp_snmp_seq_show, NULL);
 }
 
-static struct file_operations sctp_snmp_seq_fops = {
+static const struct file_operations sctp_snmp_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = sctp_snmp_seq_open,
 	.read	 = seq_read,
@@ -264,7 +264,7 @@
 	return seq_open(file, &sctp_eps_ops);
 }
 
-static struct file_operations sctp_eps_seq_fops = {
+static const struct file_operations sctp_eps_seq_fops = {
 	.open	 = sctp_eps_seq_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
@@ -374,7 +374,7 @@
 	return seq_open(file, &sctp_assoc_ops);
 }
 
-static struct file_operations sctp_assocs_seq_fops = {
+static const struct file_operations sctp_assocs_seq_fops = {
 	.open	 = sctp_assocs_seq_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 0ef4812..e17a823 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -102,11 +102,11 @@
 	}
 
 	if (sctp_snmp_proc_init())
-		goto out_nomem;	
+		goto out_nomem;
 	if (sctp_eps_proc_init())
-		goto out_nomem;	
+		goto out_nomem;
 	if (sctp_assocs_proc_init())
-		goto out_nomem;	
+		goto out_nomem;
 
 	return 0;
 
@@ -114,7 +114,7 @@
 	return -ENOMEM;
 }
 
-/* Clean up the proc fs entry for the SCTP protocol. 
+/* Clean up the proc fs entry for the SCTP protocol.
  * Note: Do not make this __exit as it is used in the init error
  * path.
  */
@@ -286,7 +286,7 @@
 
 	param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;
 	param->v4.param_hdr.length = htons(length);
-	param->v4.addr.s_addr = addr->v4.sin_addr.s_addr;	
+	param->v4.addr.s_addr = addr->v4.sin_addr.s_addr;
 
 	return length;
 }
@@ -344,9 +344,9 @@
 	if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr))
 		return 0;
 
- 	/* Is this a broadcast address? */
- 	if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST)
- 		return 0;
+	/* Is this a broadcast address? */
+	if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST)
+		return 0;
 
 	return 1;
 }
@@ -494,7 +494,7 @@
 out:
 	if (dst)
 		SCTP_DEBUG_PRINTK("rt_dst:%u.%u.%u.%u, rt_src:%u.%u.%u.%u\n",
-			  	  NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_src));
+				  NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_src));
 	else
 		SCTP_DEBUG_PRINTK("NO ROUTE\n");
 
@@ -517,14 +517,14 @@
 	if (rt) {
 		saddr->v4.sin_family = AF_INET;
 		saddr->v4.sin_port = htons(asoc->base.bind_addr.port);
-		saddr->v4.sin_addr.s_addr = rt->rt_src; 
+		saddr->v4.sin_addr.s_addr = rt->rt_src;
 	}
 }
 
 /* What interface did this skb arrive on? */
 static int sctp_v4_skb_iif(const struct sk_buff *skb)
 {
-     	return ((struct rtable *)skb->dst)->rt_iif;
+	return ((struct rtable *)skb->dst)->rt_iif;
 }
 
 /* Was this packet marked by Explicit Congestion Notification? */
@@ -569,7 +569,7 @@
 	newinet->dport = htons(asoc->peer.port);
 	newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
 	newinet->pmtudisc = inet->pmtudisc;
-      	newinet->id = asoc->next_tsn ^ jiffies;
+	newinet->id = asoc->next_tsn ^ jiffies;
 
 	newinet->uc_ttl = -1;
 	newinet->mc_loop = 1;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 0b1ddb1..f7fb29d 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -118,7 +118,7 @@
 	int padlen;
 	__u16 len;
 
-        /* Cause code constants are now defined in network order.  */
+	/* Cause code constants are now defined in network order.  */
 	err.cause = cause_code;
 	len = sizeof(sctp_errhdr_t) + paylen;
 	padlen = len % 4;
@@ -295,11 +295,11 @@
 	 */
 	chunksize = sizeof(initack) + addrs_len + cookie_len + unkparam_len;
 
-        /* Tell peer that we'll do ECN only if peer advertised such cap.  */
+	/* Tell peer that we'll do ECN only if peer advertised such cap.  */
 	if (asoc->peer.ecn_capable)
 		chunksize += sizeof(ecap_param);
 
-        /* Tell peer that we'll do PR-SCTP only if peer advertised.  */
+	/* Tell peer that we'll do PR-SCTP only if peer advertised.  */
 	if (asoc->peer.prsctp_capable)
 		chunksize += sizeof(prsctp_param);
 
@@ -728,7 +728,7 @@
 	if (retval && chunk)
 		retval->transport = chunk->transport;
 
-        return retval;
+	return retval;
 }
 
 /* Create an ABORT.  Note that we set the T bit if we have no
@@ -844,7 +844,7 @@
 	return retval;
 }
 
-/* Make an ABORT chunk with a PROTOCOL VIOLATION cause code. */ 
+/* Make an ABORT chunk with a PROTOCOL VIOLATION cause code. */
 struct sctp_chunk *sctp_make_abort_violation(
 	const struct sctp_association *asoc,
 	const struct sctp_chunk *chunk,
@@ -979,11 +979,10 @@
 {
 	struct sctp_chunk *retval;
 
-	retval = kmem_cache_alloc(sctp_chunk_cachep, GFP_ATOMIC);
+	retval = kmem_cache_zalloc(sctp_chunk_cachep, GFP_ATOMIC);
 
 	if (!retval)
 		goto nodata;
-	memset(retval, 0, sizeof(struct sctp_chunk));
 
 	if (!sk) {
 		SCTP_DEBUG_PRINTK("chunkifying skb %p w/o an sk\n", skb);
@@ -1265,8 +1264,8 @@
 	/* Header size is static data prior to the actual cookie, including
 	 * any padding.
 	 */
-	headersize = sizeof(sctp_paramhdr_t) + 
-		     (sizeof(struct sctp_signed_cookie) - 
+	headersize = sizeof(sctp_paramhdr_t) +
+		     (sizeof(struct sctp_signed_cookie) -
 		      sizeof(struct sctp_cookie));
 	bodysize = sizeof(struct sctp_cookie)
 		+ ntohs(init_chunk->chunk_hdr->length) + addrs_len;
@@ -1315,7 +1314,7 @@
 	memcpy((__u8 *)&cookie->c.peer_init[0] +
 	       ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len);
 
-  	if (sctp_sk(ep->base.sk)->hmac) {
+	if (sctp_sk(ep->base.sk)->hmac) {
 		struct hash_desc desc;
 
 		/* Sign the message.  */
@@ -1324,8 +1323,8 @@
 		sg.length = bodysize;
 		keylen = SCTP_SECRET_SIZE;
 		key = (char *)ep->secret_key[ep->current_key];
-  		desc.tfm = sctp_sk(ep->base.sk)->hmac;
-  		desc.flags = 0;
+		desc.tfm = sctp_sk(ep->base.sk)->hmac;
+		desc.flags = 0;
 
 		if (crypto_hash_setkey(desc.tfm, key, keylen) ||
 		    crypto_hash_digest(&desc, &sg, bodysize, cookie->signature))
@@ -1365,7 +1364,7 @@
 	 * any padding.
 	 */
 	headersize = sizeof(sctp_chunkhdr_t) +
-		     (sizeof(struct sctp_signed_cookie) - 
+		     (sizeof(struct sctp_signed_cookie) -
 		      sizeof(struct sctp_cookie));
 	bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
 	fixed_size = headersize + sizeof(struct sctp_cookie);
@@ -1593,7 +1592,7 @@
 					struct sctp_chunk **errp)
 {
 	char		error[] = "The following parameter had invalid length:";
-	size_t		payload_len = WORD_ROUND(sizeof(error)) + 
+	size_t		payload_len = WORD_ROUND(sizeof(error)) +
 						sizeof(sctp_paramhdr_t);
 
 
@@ -1752,7 +1751,7 @@
 	case SCTP_PARAM_FWD_TSN_SUPPORT:
 		if (sctp_prsctp_enable)
 			break;
-		/* Fall Through */ 
+		/* Fall Through */
 	default:
 		SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
 				ntohs(param.p->type), cid);
@@ -1861,7 +1860,7 @@
 	sctp_walk_params(param, peer_init, init_hdr.params) {
 
 		if (!sctp_process_param(asoc, param, peer_addr, gfp))
-                        goto clean_up;
+			goto clean_up;
 	}
 
 	/* Walk list of transports, removing transports in the UNKNOWN state. */
@@ -1937,7 +1936,7 @@
 	 */
 
 	/* Allocate storage for the negotiated streams if it is not a temporary
- 	 * association.
+	 * association.
 	 */
 	if (!asoc->temp) {
 		int assoc_id;
@@ -2109,7 +2108,7 @@
 			asoc->peer.prsctp_capable = 1;
 			break;
 		}
-		/* Fall Through */ 
+		/* Fall Through */
 	default:
 		/* Any unrecognized parameters should have been caught
 		 * and handled by sctp_verify_param() which should be
@@ -2168,7 +2167,7 @@
  *     |                     ASCONF Parameter #N                       |
  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
- * Address Parameter and other parameter will not be wrapped in this function 
+ * Address Parameter and other parameter will not be wrapped in this function
  */
 static struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
 					   union sctp_addr *addr,
@@ -2290,7 +2289,7 @@
  *     |                       Address Parameter                       |
  *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
- * Create an ASCONF chunk with Set Primary IP address parameter. 
+ * Create an ASCONF chunk with Set Primary IP address parameter.
  */
 struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
 					     union sctp_addr *addr)
@@ -2339,7 +2338,7 @@
  *     |                 ASCONF Parameter Response#N                   |
  *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
- * Create an ASCONF_ACK chunk with enough space for the parameter responses. 
+ * Create an ASCONF_ACK chunk with enough space for the parameter responses.
  */
 static struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc,
 					       __u32 serial, int vparam_len)
@@ -2381,7 +2380,7 @@
 				 ntohs(asconf_param->param_hdr.length);
 	}
 
-	/* Add Success Indication or Error Cause Indication parameter. */ 
+	/* Add Success Indication or Error Cause Indication parameter. */
 	ack_param.param_hdr.type = response_type;
 	ack_param.param_hdr.length = htons(sizeof(ack_param) +
 					   err_param_len +
@@ -2424,11 +2423,11 @@
 	switch (asconf_param->param_hdr.type) {
 	case SCTP_PARAM_ADD_IP:
 		/* ADDIP 4.3 D9) If an endpoint receives an ADD IP address
-	 	 * request and does not have the local resources to add this
-	 	 * new address to the association, it MUST return an Error
-	 	 * Cause TLV set to the new error code 'Operation Refused
-	 	 * Due to Resource Shortage'.
-	 	 */
+		 * request and does not have the local resources to add this
+		 * new address to the association, it MUST return an Error
+		 * Cause TLV set to the new error code 'Operation Refused
+		 * Due to Resource Shortage'.
+		 */
 
 		peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED);
 		if (!peer)
@@ -2440,10 +2439,10 @@
 		break;
 	case SCTP_PARAM_DEL_IP:
 		/* ADDIP 4.3 D7) If a request is received to delete the
-	 	 * last remaining IP address of a peer endpoint, the receiver
-	 	 * MUST send an Error Cause TLV with the error cause set to the
-	 	 * new error code 'Request to Delete Last Remaining IP Address'.
-	 	 */
+		 * last remaining IP address of a peer endpoint, the receiver
+		 * MUST send an Error Cause TLV with the error cause set to the
+		 * new error code 'Request to Delete Last Remaining IP Address'.
+		 */
 		pos = asoc->peer.transport_addr_list.next;
 		if (pos->next == &asoc->peer.transport_addr_list)
 			return SCTP_ERROR_DEL_LAST_IP;
@@ -2475,7 +2474,7 @@
 	return SCTP_ERROR_NO_ERROR;
 }
 
-/* Process an incoming ASCONF chunk with the next expected serial no. and 
+/* Process an incoming ASCONF chunk with the next expected serial no. and
  * return an ASCONF_ACK chunk to be sent in response.
  */
 struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
@@ -2495,19 +2494,19 @@
 	hdr = (sctp_addiphdr_t *)asconf->skb->data;
 	serial = ntohl(hdr->serial);
 
-	/* Skip the addiphdr and store a pointer to address parameter.  */ 
+	/* Skip the addiphdr and store a pointer to address parameter.  */
 	length = sizeof(sctp_addiphdr_t);
 	addr_param = (union sctp_addr_param *)(asconf->skb->data + length);
 	chunk_len -= length;
 
 	/* Skip the address parameter and store a pointer to the first
 	 * asconf paramter.
-	 */ 
+	 */
 	length = ntohs(addr_param->v4.param_hdr.length);
 	asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
 	chunk_len -= length;
 
-	/* create an ASCONF_ACK chunk. 
+	/* create an ASCONF_ACK chunk.
 	 * Based on the definitions of parameters, we know that the size of
 	 * ASCONF_ACK parameters are less than or equal to the twice of ASCONF
 	 * paramters.
@@ -2538,7 +2537,7 @@
 		/* ADDIP 4.3 D11) When an endpoint receiving an ASCONF to add
 		 * an IP address sends an 'Out of Resource' in its response, it
 		 * MUST also fail any subsequent add or delete requests bundled
-		 * in the ASCONF. 
+		 * in the ASCONF.
 		 */
 		if (SCTP_ERROR_RSRC_LOW == err_code)
 			goto done;
@@ -2549,12 +2548,12 @@
 						      length);
 		chunk_len -= length;
 	}
-	
+
 done:
 	asoc->peer.addip_serial++;
 
 	/* If we are sending a new ASCONF_ACK hold a reference to it in assoc
-	 * after freeing the reference to old asconf ack if any. 
+	 * after freeing the reference to old asconf ack if any.
 	 */
 	if (asconf_ack) {
 		if (asoc->addip_last_asconf_ack)
@@ -2622,7 +2621,7 @@
 
 /* Get the corresponding ASCONF response error code from the ASCONF_ACK chunk
  * for the given asconf parameter.  If there is no response for this parameter,
- * return the error code based on the third argument 'no_err'. 
+ * return the error code based on the third argument 'no_err'.
  * ADDIP 4.1
  * A7) If an error response is received for a TLV parameter, all TLVs with no
  * response before the failed TLV are considered successful if not reported.
@@ -2646,7 +2645,7 @@
 
 	/* Skip the addiphdr from the asconf_ack chunk and store a pointer to
 	 * the first asconf_ack parameter.
-	 */ 
+	 */
 	length = sizeof(sctp_addiphdr_t);
 	asconf_ack_param = (sctp_addip_param_t *)(asconf_ack->skb->data +
 						  length);
@@ -2697,14 +2696,14 @@
 
 	/* Skip the chunkhdr and addiphdr from the last asconf sent and store
 	 * a pointer to address parameter.
-	 */ 
+	 */
 	length = sizeof(sctp_addip_chunk_t);
 	addr_param = (union sctp_addr_param *)(asconf->skb->data + length);
 	asconf_len -= length;
 
 	/* Skip the address parameter in the last asconf sent and store a
 	 * pointer to the first asconf paramter.
-	 */ 
+	 */
 	length = ntohs(addr_param->v4.param_hdr.length);
 	asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
 	asconf_len -= length;
@@ -2741,7 +2740,7 @@
 		case SCTP_ERROR_INV_PARAM:
 			/* Disable sending this type of asconf parameter in
 			 * future.
-			 */	
+			 */
 			asoc->peer.addip_disabled_mask |=
 				asconf_param->param_hdr.type;
 			break;
@@ -2755,7 +2754,7 @@
 
 		/* Skip the processed asconf parameter and move to the next
 		 * one.
-	 	 */ 
+		 */
 		length = ntohs(asconf_param->param_hdr.length);
 		asconf_param = (sctp_addip_param_t *)((void *)asconf_param +
 						      length);
@@ -2784,14 +2783,14 @@
 	return retval;
 }
 
-/* Make a FWD TSN chunk. */ 
+/* Make a FWD TSN chunk. */
 struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
 				    __u32 new_cum_tsn, size_t nstreams,
 				    struct sctp_fwdtsn_skip *skiplist)
 {
 	struct sctp_chunk *retval = NULL;
 	struct sctp_fwdtsn_chunk *ftsn_chunk;
-	struct sctp_fwdtsn_hdr ftsn_hdr; 
+	struct sctp_fwdtsn_hdr ftsn_hdr;
 	struct sctp_fwdtsn_skip skip;
 	size_t hint;
 	int i;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 6db77d1..1355674 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -61,7 +61,7 @@
 				struct sctp_endpoint *ep,
 				struct sctp_association *asoc,
 				void *event_arg,
-			 	sctp_disposition_t status,
+				sctp_disposition_t status,
 				sctp_cmd_seq_t *commands,
 				gfp_t gfp);
 static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
@@ -78,7 +78,7 @@
  ********************************************************************/
 
 /* A helper function for delayed processing of INET ECN CE bit. */
-static void sctp_do_ecn_ce_work(struct sctp_association *asoc, 
+static void sctp_do_ecn_ce_work(struct sctp_association *asoc,
 				__u32 lowest_tsn)
 {
 	/* Save the TSN away for comparison when we receive CWR */
@@ -160,7 +160,7 @@
 	struct sctp_transport *trans = asoc->peer.last_data_from;
 	int error = 0;
 
-	if (force || 
+	if (force ||
 	    (!trans && (asoc->param_flags & SPP_SACKDELAY_DISABLE)) ||
 	    (trans && (trans->param_flags & SPP_SACKDELAY_DISABLE)))
 		asoc->peer.sack_needed = 1;
@@ -178,7 +178,7 @@
 	 * [This is actually not mentioned in Section 6, but we
 	 * implement it here anyway. --piggy]
 	 */
-        if (max_tsn_seen != ctsn)
+	if (max_tsn_seen != ctsn)
 		asoc->peer.sack_needed = 1;
 
 	/* From 6.2  Acknowledgement on Reception of DATA Chunks:
@@ -199,10 +199,10 @@
 		 * for the association.
 		 */
 		if (trans)
-			asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = 
+			asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
 				trans->sackdelay;
 		else
-			asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = 
+			asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
 				asoc->sackdelay;
 
 		/* Restart the SACK timer. */
@@ -338,8 +338,8 @@
 
 static void sctp_generate_t5_shutdown_guard_event(unsigned long data)
 {
-        struct sctp_association *asoc = (struct sctp_association *)data;
-        sctp_generate_timeout_event(asoc,
+	struct sctp_association *asoc = (struct sctp_association *)data;
+	sctp_generate_timeout_event(asoc,
 				    SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD);
 
 } /* sctp_generate_t5_shutdown_guard_event() */
@@ -380,7 +380,7 @@
 			   asoc->state, asoc->ep, asoc,
 			   transport, GFP_ATOMIC);
 
-         if (error)
+	 if (error)
 		 asoc->base.sk->sk_err = -error;
 
 out_unlock:
@@ -570,7 +570,7 @@
 
 /* Helper function to stop any pending T3-RTX timers */
 static void sctp_cmd_t3_rtx_timers_stop(sctp_cmd_seq_t *cmds,
-				        struct sctp_association *asoc)
+					struct sctp_association *asoc)
 {
 	struct sctp_transport *t;
 	struct list_head *pos;
@@ -675,7 +675,7 @@
 /* Helper function to set the timeout value for T2-SHUTDOWN timer and to set
  * the transport for a shutdown chunk.
  */
-static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, 
+static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds,
 			      struct sctp_association *asoc,
 			      struct sctp_chunk *chunk)
 {
@@ -688,7 +688,7 @@
 }
 
 /* Helper function to change the state of an association. */
-static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, 
+static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds,
 			       struct sctp_association *asoc,
 			       sctp_state_t state)
 {
@@ -727,7 +727,7 @@
 	    sctp_state(asoc, SHUTDOWN_RECEIVED)) {
 		/* Wake up any processes waiting in the asoc's wait queue in
 		 * sctp_wait_for_connect() or sctp_wait_for_sndbuf().
-	 	 */
+		 */
 		if (waitqueue_active(&asoc->wait))
 			wake_up_interruptible(&asoc->wait);
 
@@ -749,9 +749,9 @@
 	struct sock *sk = asoc->base.sk;
 
 	/* If it is a non-temporary association belonging to a TCP-style
-	 * listening socket that is not closed, do not free it so that accept() 
+	 * listening socket that is not closed, do not free it so that accept()
 	 * can pick it up later.
-	 */ 
+	 */
 	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING) &&
 	    (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK))
 		return;
@@ -764,7 +764,7 @@
  * ADDIP Section 4.1 ASCONF Chunk Procedures
  * A4) Start a T-4 RTO timer, using the RTO value of the selected
  * destination address (we use active path instead of primary path just
- * because primary path may be inactive. 
+ * because primary path may be inactive.
  */
 static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds,
 				struct sctp_association *asoc,
@@ -777,7 +777,7 @@
 	chunk->transport = t;
 }
 
-/* Process an incoming Operation Error Chunk. */ 
+/* Process an incoming Operation Error Chunk. */
 static void sctp_cmd_process_operr(sctp_cmd_seq_t *cmds,
 				   struct sctp_association *asoc,
 				   struct sctp_chunk *chunk)
@@ -816,7 +816,7 @@
 }
 
 /* Process variable FWDTSN chunk information. */
-static void sctp_cmd_process_fwdtsn(struct sctp_ulpq *ulpq, 
+static void sctp_cmd_process_fwdtsn(struct sctp_ulpq *ulpq,
 				    struct sctp_chunk *chunk)
 {
 	struct sctp_fwdtsn_skip *skip;
@@ -828,9 +828,9 @@
 	return;
 }
 
-/* Helper function to remove the association non-primary peer 
+/* Helper function to remove the association non-primary peer
  * transports.
- */ 
+ */
 static void sctp_cmd_del_non_primary(struct sctp_association *asoc)
 {
 	struct sctp_transport *t;
@@ -840,7 +840,7 @@
 	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
 		t = list_entry(pos, struct sctp_transport, transports);
 		if (!sctp_cmp_addr_exact(&t->ipaddr,
-		                         &asoc->peer.primary_addr)) {
+					 &asoc->peer.primary_addr)) {
 			sctp_assoc_del_peer(asoc, &t->ipaddr);
 		}
 	}
@@ -915,7 +915,7 @@
 	DEBUG_POST;
 
 	error = sctp_side_effects(event_type, subtype, state,
-				  ep, asoc, event_arg, status, 
+				  ep, asoc, event_arg, status,
 				  &commands, gfp);
 	DEBUG_POST_SFX;
 
@@ -968,7 +968,7 @@
 		error = -ENOMEM;
 		break;
 
-        case SCTP_DISPOSITION_DELETE_TCB:
+	case SCTP_DISPOSITION_DELETE_TCB:
 		/* This should now be a command. */
 		break;
 
@@ -1021,7 +1021,7 @@
 				struct sctp_endpoint *ep,
 				struct sctp_association *asoc,
 				void *event_arg,
-			 	sctp_disposition_t status,
+				sctp_disposition_t status,
 				sctp_cmd_seq_t *commands,
 				gfp_t gfp)
 {
@@ -1057,7 +1057,7 @@
 		case SCTP_CMD_NEW_ASOC:
 			/* Register a new association.  */
 			if (local_cork) {
-				sctp_outq_uncork(&asoc->outqueue); 
+				sctp_outq_uncork(&asoc->outqueue);
 				local_cork = 0;
 			}
 			asoc = cmd->obj.ptr;
@@ -1074,7 +1074,7 @@
 		       sctp_outq_teardown(&asoc->outqueue);
 		       break;
 
-		case SCTP_CMD_DELETE_TCB:			
+		case SCTP_CMD_DELETE_TCB:
 			if (local_cork) {
 				sctp_outq_uncork(&asoc->outqueue);
 				local_cork = 0;
@@ -1104,7 +1104,7 @@
 
 		case SCTP_CMD_PROCESS_FWDTSN:
 			sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.ptr);
-                        break;
+			break;
 
 		case SCTP_CMD_GEN_SACK:
 			/* Generate a Selective ACK.
@@ -1162,12 +1162,12 @@
 						SCTP_CHUNK(cmd->obj.ptr));
 
 			/* FIXME - Eventually come up with a cleaner way to
-			 * enabling COOKIE-ECHO + DATA bundling during 
-			 * multihoming stale cookie scenarios, the following 
-			 * command plays with asoc->peer.retran_path to 
-			 * avoid the problem of sending the COOKIE-ECHO and 
-			 * DATA in different paths, which could result 
-			 * in the association being ABORTed if the DATA chunk 
+			 * enabling COOKIE-ECHO + DATA bundling during
+			 * multihoming stale cookie scenarios, the following
+			 * command plays with asoc->peer.retran_path to
+			 * avoid the problem of sending the COOKIE-ECHO and
+			 * DATA in different paths, which could result
+			 * in the association being ABORTed if the DATA chunk
 			 * is processed first by the server.  Checking the
 			 * init error counter simply causes this command
 			 * to be executed only during failed attempts of
@@ -1177,7 +1177,7 @@
 			     asoc->peer.primary_path) &&
 			    (asoc->init_err_counter > 0)) {
 				sctp_add_cmd_sf(commands,
-				                SCTP_CMD_FORCE_PRIM_RETRAN,
+						SCTP_CMD_FORCE_PRIM_RETRAN,
 						SCTP_NULL());
 			}
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index fbbc9e6..b3cad8a 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -189,7 +189,7 @@
 					     0, 0, 0, GFP_ATOMIC);
 	if (ev)
 		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
-			        SCTP_ULPEVENT(ev));
+				SCTP_ULPEVENT(ev));
 
 	/* Upon reception of the SHUTDOWN COMPLETE chunk the endpoint
 	 * will verify that it is in SHUTDOWN-ACK-SENT state, if it is
@@ -228,7 +228,7 @@
  *    Verification Tag field to Tag_A, and also provide its own
  *    Verification Tag (Tag_Z) in the Initiate Tag field.
  *
- * Verification Tag: Must be 0. 
+ * Verification Tag: Must be 0.
  *
  * Inputs
  * (endpoint, asoc, chunk)
@@ -256,7 +256,7 @@
 	/* 6.10 Bundling
 	 * An endpoint MUST NOT bundle INIT, INIT ACK or
 	 * SHUTDOWN COMPLETE with any other chunks.
-	 * 
+	 *
 	 * IG Section 2.11.2
 	 * Furthermore, we require that the receiver of an INIT chunk MUST
 	 * enforce these rules by silently discarding an arriving packet
@@ -282,7 +282,7 @@
 		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
 
 	/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
-	 * Tag. 
+	 * Tag.
 	 */
 	if (chunk->sctp_hdr->vtag != 0)
 		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
@@ -326,7 +326,7 @@
 		}
 	}
 
-        /* Grab the INIT header.  */
+	/* Grab the INIT header.  */
 	chunk->subh.init_hdr = (sctp_inithdr_t *)chunk->skb->data;
 
 	/* Tag the variable length parameters.  */
@@ -594,7 +594,7 @@
 	/* "Decode" the chunk.  We have no optional parameters so we
 	 * are in good shape.
 	 */
-        chunk->subh.cookie_hdr =
+	chunk->subh.cookie_hdr =
 		(struct sctp_signed_cookie *)chunk->skb->data;
 	if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
 					 sizeof(sctp_chunkhdr_t)))
@@ -665,7 +665,7 @@
 	if (!ev)
 		goto nomem_ev;
 
-	/* Sockets API Draft Section 5.3.1.6 	
+	/* Sockets API Draft Section 5.3.1.6
 	 * When a peer sends a Adaptation Layer Indication parameter , SCTP
 	 * delivers this notification to inform the application that of the
 	 * peers requested adaptation layer.
@@ -891,7 +891,7 @@
 	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE,
 			SCTP_TRANSPORT(transport));
 
-        return SCTP_DISPOSITION_CONSUME;
+	return SCTP_DISPOSITION_CONSUME;
 }
 
 /*
@@ -1280,7 +1280,7 @@
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
-	 * Tag. 
+	 * Tag.
 	 */
 	if (chunk->sctp_hdr->vtag != 0)
 		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
@@ -1548,7 +1548,7 @@
 	/* Per the above section, we'll discard the chunk if we have an
 	 * endpoint.  If this is an OOTB INIT-ACK, treat it as such.
 	 */
-        if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
+	if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
 		return sctp_sf_ootb(ep, asoc, type, arg, commands);
 	else
 		return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
@@ -1760,9 +1760,9 @@
 
 	/* Clarification from Implementor's Guide:
 	 * D) When both local and remote tags match the endpoint should
-         * enter the ESTABLISHED state, if it is in the COOKIE-ECHOED state.
-         * It should stop any cookie timer that may be running and send
-         * a COOKIE ACK.
+	 * enter the ESTABLISHED state, if it is in the COOKIE-ECHOED state.
+	 * It should stop any cookie timer that may be running and send
+	 * a COOKIE ACK.
 	 */
 
 	/* Don't accidentally move back into established state. */
@@ -1786,7 +1786,7 @@
 					     SCTP_COMM_UP, 0,
 					     asoc->c.sinit_num_ostreams,
 					     asoc->c.sinit_max_instreams,
-                                             GFP_ATOMIC);
+					     GFP_ATOMIC);
 		if (!ev)
 			goto nomem;
 
@@ -1870,7 +1870,7 @@
 	/* "Decode" the chunk.  We have no optional parameters so we
 	 * are in good shape.
 	 */
-        chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data;
+	chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data;
 	if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
 					sizeof(sctp_chunkhdr_t)))
 		goto nomem;
@@ -1936,7 +1936,7 @@
 	default: /* Discard packet for all others. */
 		retval = sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 		break;
-        };
+	};
 
 	/* Delete the tempory new association. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
@@ -2083,7 +2083,7 @@
 	 */
 	sctp_walk_errors(err, chunk->chunk_hdr) {
 		if (SCTP_ERROR_STALE_COOKIE == err->cause)
-			return sctp_sf_do_5_2_6_stale(ep, asoc, type, 
+			return sctp_sf_do_5_2_6_stale(ep, asoc, type,
 							arg, commands);
 	}
 
@@ -2185,10 +2185,10 @@
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
 
-	/* If we've sent any data bundled with COOKIE-ECHO we will need to 
-	 * resend 
+	/* If we've sent any data bundled with COOKIE-ECHO we will need to
+	 * resend
 	 */
-	sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, 
+	sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN,
 			SCTP_TRANSPORT(asoc->peer.primary_path));
 
 	/* Cast away the const modifier, as we want to just
@@ -2274,7 +2274,7 @@
 		error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
- 	/* ASSOC_FAILED will DELETE_TCB. */
+	/* ASSOC_FAILED will DELETE_TCB. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error));
 	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
 	SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
@@ -2439,7 +2439,7 @@
 	ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC);
 	if (!ev) {
 		disposition = SCTP_DISPOSITION_NOMEM;
-		goto out;	
+		goto out;
 	}
 	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
 
@@ -2553,7 +2553,7 @@
 	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_ecne_chunk_t)))
 		return sctp_sf_violation_chunklen(ep, asoc, type, arg,
 						  commands);
-		
+
 	cwr = (sctp_cwrhdr_t *) chunk->skb->data;
 	skb_pull(chunk->skb, sizeof(sctp_cwrhdr_t));
 
@@ -2661,7 +2661,7 @@
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
 				SCTP_NULL());
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-        }
+	}
 
 	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_data_chunk_t)))
 		return sctp_sf_violation_chunklen(ep, asoc, type, arg,
@@ -2743,7 +2743,7 @@
 	return SCTP_DISPOSITION_DISCARD;
 consume:
 	return SCTP_DISPOSITION_CONSUME;
-	
+
 }
 
 /*
@@ -2930,7 +2930,7 @@
 		/* Make an ABORT. The T bit will be set if the asoc
 		 * is NULL.
 		 */
-        	abort = sctp_make_abort(asoc, chunk, 0);
+		abort = sctp_make_abort(asoc, chunk, 0);
 		if (!abort) {
 			sctp_ootb_pkt_free(packet);
 			return SCTP_DISPOSITION_NOMEM;
@@ -2994,7 +2994,7 @@
 		}
 
 		sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
-				SCTP_CHUNK(chunk));	
+				SCTP_CHUNK(chunk));
 	}
 	return SCTP_DISPOSITION_CONSUME;
 
@@ -3128,7 +3128,7 @@
 		 */
 		if (SCTP_CID_ABORT == ch->type)
 			return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-			
+
 		ch = (sctp_chunkhdr_t *) ch_end;
 	} while (ch_end < skb->tail);
 
@@ -3175,8 +3175,8 @@
 
 	if (packet) {
 		/* Make an SHUTDOWN_COMPLETE.
-         	 * The T bit will be set if the asoc is NULL.
-         	 */
+		 * The T bit will be set if the asoc is NULL.
+		 */
 		shut = sctp_make_shutdown_complete(asoc, chunk);
 		if (!shut) {
 			sctp_ootb_pkt_free(packet);
@@ -3261,10 +3261,10 @@
 
 	/* ADDIP 4.2 C1) Compare the value of the serial number to the value
 	 * the endpoint stored in a new association variable
-	 * 'Peer-Serial-Number'. 
+	 * 'Peer-Serial-Number'.
 	 */
 	if (serial == asoc->peer.addip_serial + 1) {
-   		/* ADDIP 4.2 C2) If the value found in the serial number is
+		/* ADDIP 4.2 C2) If the value found in the serial number is
 		 * equal to the ('Peer-Serial-Number' + 1), the endpoint MUST
 		 * do V1-V5.
 		 */
@@ -3285,9 +3285,9 @@
 		else
 			return SCTP_DISPOSITION_DISCARD;
 	} else {
-		/* ADDIP 4.2 C4) Otherwise, the ASCONF Chunk is discarded since 
+		/* ADDIP 4.2 C4) Otherwise, the ASCONF Chunk is discarded since
 		 * it must be either a stale packet or from an attacker.
-		 */	
+		 */
 		return SCTP_DISPOSITION_DISCARD;
 	}
 
@@ -3296,7 +3296,7 @@
 	 * being responded to.
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(asconf_ack));
-	
+
 	return SCTP_DISPOSITION_CONSUME;
 }
 
@@ -3307,7 +3307,7 @@
  */
 sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
 					 const struct sctp_association *asoc,
-	 				 const sctp_subtype_t type, void *arg,
+					 const sctp_subtype_t type, void *arg,
 					 sctp_cmd_seq_t *commands)
 {
 	struct sctp_chunk	*asconf_ack = arg;
@@ -3359,7 +3359,7 @@
 				SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
 		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
 		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
-			        SCTP_ERROR(ECONNABORTED));
+				SCTP_ERROR(ECONNABORTED));
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
 		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -3387,7 +3387,7 @@
 		 */
 		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
 		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
-			        SCTP_ERROR(ECONNABORTED));
+				SCTP_ERROR(ECONNABORTED));
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
 		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -3451,17 +3451,17 @@
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn));
 	if (len > sizeof(struct sctp_fwdtsn_hdr))
-		sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, 
+		sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN,
 				SCTP_CHUNK(chunk));
-	
+
 	/* Count this as receiving DATA. */
 	if (asoc->autoclose) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
 				SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 	}
-	
+
 	/* FIXME: For now send a SACK, but DATA processing may
-	 * send another. 
+	 * send another.
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE());
 
@@ -3511,9 +3511,9 @@
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn));
 	if (len > sizeof(struct sctp_fwdtsn_hdr))
-		sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, 
+		sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN,
 				SCTP_CHUNK(chunk));
-	
+
 	/* Go a head and force a SACK, since we are shutting down. */
 gen_shutdown:
 	/* Implementor's Guide.
@@ -3527,7 +3527,7 @@
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
 
-        return SCTP_DISPOSITION_CONSUME;
+	return SCTP_DISPOSITION_CONSUME;
 }
 
 /*
@@ -3706,7 +3706,7 @@
  * if it's length is set to be smaller then the size of sctp_sack_chunk_t.
  *
  * We inform the other end by sending an ABORT with a Protocol Violation
- * error code. 
+ * error code.
  *
  * Section: Not specified
  * Verification Tag:  Nothing to do
@@ -3747,7 +3747,7 @@
 				SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
 	} else {
 		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
-			        SCTP_ERROR(ECONNABORTED));
+				SCTP_ERROR(ECONNABORTED));
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
 		SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
@@ -3756,7 +3756,7 @@
 	sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
 
 	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
-	
+
 	return SCTP_DISPOSITION_ABORT;
 
 nomem:
@@ -4437,7 +4437,7 @@
 	/* sctp-implguide 2.10 Issues with Heartbeating and failover
 	 *
 	 * HEARTBEAT ... is discontinued after sending either SHUTDOWN
-         * or SHUTDOWN-ACK.
+	 * or SHUTDOWN-ACK.
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL());
 
@@ -4515,7 +4515,7 @@
 	/* sctp-implguide 2.10 Issues with Heartbeating and failover
 	 *
 	 * HEARTBEAT ... is discontinued after sending either SHUTDOWN
-         * or SHUTDOWN-ACK.
+	 * or SHUTDOWN-ACK.
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL());
 
@@ -4874,7 +4874,7 @@
 	/* ADDIP 4.1 B4) Re-transmit the ASCONF Chunk last sent and if possible
 	 * choose an alternate destination address (please refer to RFC2960
 	 * [5] section 6.4.1). An endpoint MUST NOT add new parameters to this
-	 * chunk, it MUST be the same (including its serial number) as the last 
+	 * chunk, it MUST be the same (including its serial number) as the last
 	 * ASCONF sent.
 	 */
 	sctp_chunk_hold(asoc->addip_last_asconf);
@@ -4953,7 +4953,7 @@
 	/* sctpimpguide-05 Section 2.12.2
 	 * The sender of the SHUTDOWN MAY also start an overall guard timer
 	 * 'T5-shutdown-guard' to bound the overall time for shutdown sequence.
- 	 */
+	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
 	disposition = SCTP_DISPOSITION_CONSUME;
@@ -5127,7 +5127,7 @@
 			vtag = ntohl(init->init_hdr.init_tag);
 			break;
 		}
-		default:	
+		default:
 			vtag = ntohl(chunk->sctp_hdr->vtag);
 			break;
 		}
@@ -5176,7 +5176,7 @@
 			/* Override the OOTB vtag from the cookie. */
 			cookie = chunk->subh.cookie_hdr;
 			packet->vtag = cookie->c.peer_vtag;
-			
+
 			/* Set the skb to the belonging sock for accounting. */
 			err_chunk->skb->sk = ep->base.sk;
 			sctp_packet_append_chunk(packet, err_chunk);
@@ -5310,7 +5310,7 @@
 		sctp_add_cmd_sf(commands, SCTP_CMD_PART_DELIVER, SCTP_NULL());
 	}
 
-        /* Spill over rwnd a little bit.  Note: While allowed, this spill over
+	/* Spill over rwnd a little bit.  Note: While allowed, this spill over
 	 * seems a bit troublesome in that frag_point varies based on
 	 * PMTU.  In cases, such as loopback, this might be a rather
 	 * large spill over.
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 5f6cc7a..5e54b17 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -954,7 +954,7 @@
 	TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE,
 };
 
-static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, 
+static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
 							    sctp_state_t state)
 {
 	if (state > SCTP_STATE_MAX)
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 388d0fb..536298c 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -381,12 +381,12 @@
 
  /* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks
  *
- * R1) One and only one ASCONF Chunk MAY be in transit and unacknowledged 
+ * R1) One and only one ASCONF Chunk MAY be in transit and unacknowledged
  * at any one time.  If a sender, after sending an ASCONF chunk, decides
- * it needs to transfer another ASCONF Chunk, it MUST wait until the 
+ * it needs to transfer another ASCONF Chunk, it MUST wait until the
  * ASCONF-ACK Chunk returns from the previous ASCONF Chunk before sending a
- * subsequent ASCONF. Note this restriction binds each side, so at any 
- * time two ASCONF may be in-transit on any given association (one sent 
+ * subsequent ASCONF. Note this restriction binds each side, so at any
+ * time two ASCONF may be in-transit on any given association (one sent
  * from each endpoint).
  */
 static int sctp_send_asconf(struct sctp_association *asoc,
@@ -396,10 +396,10 @@
 
 	/* If there is an outstanding ASCONF chunk, queue it for later
 	 * transmission.
-	 */	
+	 */
 	if (asoc->addip_last_asconf) {
 		list_add_tail(&chunk->list, &asoc->addip_chunk_list);
-		goto out;	
+		goto out;
 	}
 
 	/* Hold the chunk until an ASCONF_ACK is received. */
@@ -449,7 +449,7 @@
 			goto err_bindx_add;
 		}
 
-		retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr, 
+		retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr,
 				      af->sockaddr_len);
 
 		addr_buf += af->sockaddr_len;
@@ -470,13 +470,13 @@
  * associations that are part of the endpoint indicating that a list of local
  * addresses are added to the endpoint.
  *
- * If any of the addresses is already in the bind address list of the 
+ * If any of the addresses is already in the bind address list of the
  * association, we do not send the chunk for that association.  But it will not
  * affect other associations.
  *
  * Only sctp_setsockopt_bindx() is supposed to call this function.
  */
-static int sctp_send_asconf_add_ip(struct sock		*sk, 
+static int sctp_send_asconf_add_ip(struct sock		*sk,
 				   struct sockaddr	*addrs,
 				   int 			addrcnt)
 {
@@ -517,8 +517,8 @@
 			continue;
 
 		/* Check if any address in the packed array of addresses is
-	         * in the bind address list of the association. If so, 
-		 * do not send the asconf chunk to its peer, but continue with 
+		 * in the bind address list of the association. If so,
+		 * do not send the asconf chunk to its peer, but continue with
 		 * other associations.
 		 */
 		addr_buf = addrs;
@@ -664,7 +664,7 @@
  * the associations that are part of the endpoint indicating that a list of
  * local addresses are removed from the endpoint.
  *
- * If any of the addresses is already in the bind address list of the 
+ * If any of the addresses is already in the bind address list of the
  * association, we do not send the chunk for that association.  But it will not
  * affect other associations.
  *
@@ -710,7 +710,7 @@
 			continue;
 
 		/* Check if any address in the packed array of addresses is
-	         * not present in the bind address list of the association.
+		 * not present in the bind address list of the association.
 		 * If so, do not send the asconf chunk to its peer, but
 		 * continue with other associations.
 		 */
@@ -898,7 +898,7 @@
 		return -EFAULT;
 	}
 
-	/* Walk through the addrs buffer and count the number of addresses. */ 
+	/* Walk through the addrs buffer and count the number of addresses. */
 	addr_buf = kaddrs;
 	while (walk_size < addrs_size) {
 		sa_addr = (struct sockaddr *)addr_buf;
@@ -906,7 +906,7 @@
 
 		/* If the address family is not supported or if this address
 		 * causes the address buffer to overflow return EINVAL.
-		 */ 
+		 */
 		if (!af || (walk_size + af->sockaddr_len) > addrs_size) {
 			kfree(kaddrs);
 			return -EINVAL;
@@ -935,7 +935,7 @@
 	default:
 		err = -EINVAL;
 		break;
-        };
+	};
 
 out:
 	kfree(kaddrs);
@@ -1035,10 +1035,10 @@
 				}
 			} else {
 				/*
-				 * If an unprivileged user inherits a 1-many 
-				 * style socket with open associations on a 
-				 * privileged port, it MAY be permitted to 
-				 * accept new associations, but it SHOULD NOT 
+				 * If an unprivileged user inherits a 1-many
+				 * style socket with open associations on a
+				 * privileged port, it MAY be permitted to
+				 * accept new associations, but it SHOULD NOT
 				 * be permitted to open new associations.
 				 */
 				if (ep->base.bind_addr.port < PROT_SOCK &&
@@ -1094,8 +1094,8 @@
 out_free:
 
 	SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p"
-		          " kaddrs: %p err: %d\n",
-	                  asoc, kaddrs, err);
+			  " kaddrs: %p err: %d\n",
+			  asoc, kaddrs, err);
 	if (asoc)
 		sctp_association_free(asoc);
 	return err;
@@ -1435,7 +1435,7 @@
 	 * length messages when SCTP_EOF|SCTP_ABORT is not set.
 	 * If SCTP_ABORT is set, the message length could be non zero with
 	 * the msg_iov set to the user abort reason.
- 	 */
+	 */
 	if (((sinfo_flags & SCTP_EOF) && (msg_len > 0)) ||
 	    (!(sinfo_flags & (SCTP_EOF|SCTP_ABORT)) && (msg_len == 0))) {
 		err = -EINVAL;
@@ -1599,7 +1599,7 @@
 					= sinit->sinit_max_attempts;
 			}
 			if (sinit->sinit_max_init_timeo) {
-				asoc->max_init_timeo = 
+				asoc->max_init_timeo =
 				 msecs_to_jiffies(sinit->sinit_max_init_timeo);
 			}
 		}
@@ -2298,7 +2298,7 @@
 	/* Get association, if assoc_id != 0 and the socket is a one
 	 * to many style socket, and an association was not found, then
 	 * the id was invalid.
- 	 */
+	 */
 	asoc = sctp_id2assoc(sk, params.assoc_id);
 	if (!asoc && params.assoc_id && sctp_style(sk, UDP))
 		return -EINVAL;
@@ -2307,22 +2307,22 @@
 		if (asoc) {
 			asoc->sackdelay =
 				msecs_to_jiffies(params.assoc_value);
-			asoc->param_flags = 
+			asoc->param_flags =
 				(asoc->param_flags & ~SPP_SACKDELAY) |
 				SPP_SACKDELAY_ENABLE;
 		} else {
 			sp->sackdelay = params.assoc_value;
-			sp->param_flags = 
+			sp->param_flags =
 				(sp->param_flags & ~SPP_SACKDELAY) |
 				SPP_SACKDELAY_ENABLE;
 		}
 	} else {
 		if (asoc) {
-			asoc->param_flags = 
+			asoc->param_flags =
 				(asoc->param_flags & ~SPP_SACKDELAY) |
 				SPP_SACKDELAY_DISABLE;
 		} else {
-			sp->param_flags = 
+			sp->param_flags =
 				(sp->param_flags & ~SPP_SACKDELAY) |
 				SPP_SACKDELAY_DISABLE;
 		}
@@ -2338,17 +2338,17 @@
 			if (params.assoc_value) {
 				trans->sackdelay =
 					msecs_to_jiffies(params.assoc_value);
-				trans->param_flags = 
+				trans->param_flags =
 					(trans->param_flags & ~SPP_SACKDELAY) |
 					SPP_SACKDELAY_ENABLE;
 			} else {
-				trans->param_flags = 
+				trans->param_flags =
 					(trans->param_flags & ~SPP_SACKDELAY) |
 					SPP_SACKDELAY_DISABLE;
 			}
 		}
 	}
- 
+
 	return 0;
 }
 
@@ -2374,13 +2374,13 @@
 		return -EFAULT;
 
 	if (sinit.sinit_num_ostreams)
-		sp->initmsg.sinit_num_ostreams = sinit.sinit_num_ostreams;	
+		sp->initmsg.sinit_num_ostreams = sinit.sinit_num_ostreams;
 	if (sinit.sinit_max_instreams)
-		sp->initmsg.sinit_max_instreams = sinit.sinit_max_instreams;	
+		sp->initmsg.sinit_max_instreams = sinit.sinit_max_instreams;
 	if (sinit.sinit_max_attempts)
-		sp->initmsg.sinit_max_attempts = sinit.sinit_max_attempts;	
+		sp->initmsg.sinit_max_attempts = sinit.sinit_max_attempts;
 	if (sinit.sinit_max_init_timeo)
-		sp->initmsg.sinit_max_init_timeo = sinit.sinit_max_init_timeo;	
+		sp->initmsg.sinit_max_init_timeo = sinit.sinit_max_init_timeo;
 
 	return 0;
 }
@@ -2511,7 +2511,7 @@
 
 	if (asoc) {
 		if (rtoinfo.srto_initial != 0)
-			asoc->rto_initial = 
+			asoc->rto_initial =
 				msecs_to_jiffies(rtoinfo.srto_initial);
 		if (rtoinfo.srto_max != 0)
 			asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max);
@@ -2665,7 +2665,7 @@
 	/* Update the frag_point of the existing associations. */
 	list_for_each(pos, &(sp->ep->asocs)) {
 		asoc = list_entry(pos, struct sctp_association, asocs);
-		asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu); 
+		asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
 	}
 
 	return 0;
@@ -2703,7 +2703,7 @@
 		return -EFAULT;
 
 	asoc = sctp_id2assoc(sk, prim.sspp_assoc_id);
-	if (!asoc) 
+	if (!asoc)
 		return -EINVAL;
 
 	if (!asoc->peer.asconf_capable)
@@ -3015,7 +3015,7 @@
 
 out:
 	sctp_release_sock(sk);
- 	*err = error;
+	*err = error;
 	return newsk;
 }
 
@@ -3087,7 +3087,7 @@
 	sp->assocparams.sasoc_cookie_life = sctp_valid_cookie_life;
 
 	/* Initialize default event subscriptions. By default, all the
-	 * options are off. 
+	 * options are off.
 	 */
 	memset(&sp->subscribe, 0, sizeof(struct sctp_event_subscribe));
 
@@ -3099,8 +3099,8 @@
 	sp->pathmtu     = 0; // allow default discovery
 	sp->sackdelay   = sctp_sack_timeout;
 	sp->param_flags = SPP_HB_ENABLE |
-	                  SPP_PMTUD_ENABLE |
-	                  SPP_SACKDELAY_ENABLE;
+			  SPP_PMTUD_ENABLE |
+			  SPP_SACKDELAY_ENABLE;
 
 	/* If enabled no SCTP message fragmentation will be performed.
 	 * Configure through SCTP_DISABLE_FRAGMENTS socket option.
@@ -3680,7 +3680,7 @@
 	/* Get association, if assoc_id != 0 and the socket is a one
 	 * to many style socket, and an association was not found, then
 	 * the id was invalid.
- 	 */
+	 */
 	asoc = sctp_id2assoc(sk, params.assoc_id);
 	if (!asoc && params.assoc_id && sctp_style(sk, UDP))
 		return -EINVAL;
@@ -3756,7 +3756,7 @@
 	return cnt;
 }
 
-/* 
+/*
  * Old API for getting list of peer addresses. Does not work for 32-bit
  * programs running on a 64-bit kernel
  */
@@ -3833,7 +3833,7 @@
 		return -EINVAL;
 
 	to = optval + offsetof(struct sctp_getaddrs,addrs);
-	space_left = len - sizeof(struct sctp_getaddrs) - 
+	space_left = len - sizeof(struct sctp_getaddrs) -
 			offsetof(struct sctp_getaddrs,addrs);
 
 	list_for_each(pos, &asoc->peer.transport_addr_list) {
@@ -3907,7 +3907,7 @@
 				addr = list_entry(pos,
 						  struct sctp_sockaddr_entry,
 						  list);
-				if ((PF_INET == sk->sk_family) && 
+				if ((PF_INET == sk->sk_family) &&
 				    (AF_INET6 == addr->a.sa.sa_family))
 					continue;
 				cnt++;
@@ -3941,7 +3941,7 @@
 
 	list_for_each_safe(pos, next, &sctp_local_addr_list) {
 		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
-		if ((PF_INET == sk->sk_family) && 
+		if ((PF_INET == sk->sk_family) &&
 		    (AF_INET6 == addr->a.sa.sa_family))
 			continue;
 		memcpy(&temp, &addr->a, sizeof(temp));
@@ -3970,7 +3970,7 @@
 
 	list_for_each_safe(pos, next, &sctp_local_addr_list) {
 		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
-		if ((PF_INET == sk->sk_family) && 
+		if ((PF_INET == sk->sk_family) &&
 		    (AF_INET6 == addr->a.sa.sa_family))
 			continue;
 		memcpy(&temp, &addr->a, sizeof(temp));
@@ -4051,7 +4051,7 @@
 				err = cnt;
 				goto unlock;
 			}
-			goto copy_getaddrs;		
+			goto copy_getaddrs;
 		}
 	}
 
@@ -4139,7 +4139,7 @@
 				err = cnt;
 				goto unlock;
 			}
-			goto copy_getaddrs;		
+			goto copy_getaddrs;
 		}
 	}
 
@@ -4196,7 +4196,7 @@
 
 	if (!asoc->peer.primary_path)
 		return -ENOTCONN;
-	
+
 	memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr,
 		asoc->peer.primary_path->af_specific->sockaddr_len);
 
@@ -4864,7 +4864,7 @@
 	if (!backlog) {
 		if (sctp_sstate(sk, CLOSED))
 			return 0;
-		
+
 		sctp_unhash_endpoint(ep);
 		sk->sk_state = SCTP_SS_CLOSED;
 	}
@@ -4872,7 +4872,7 @@
 	/* Return if we are already listening. */
 	if (sctp_sstate(sk, LISTENING))
 		return 0;
-		
+
 	/*
 	 * If a bind() or sctp_bindx() is not called prior to a listen()
 	 * call that allows new associations to be accepted, the system
@@ -4907,7 +4907,7 @@
 	if (!backlog) {
 		if (sctp_sstate(sk, CLOSED))
 			return 0;
-		
+
 		sctp_unhash_endpoint(ep);
 		sk->sk_state = SCTP_SS_CLOSED;
 	}
@@ -5010,7 +5010,7 @@
 	 */
 	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
 		return (!list_empty(&sp->ep->asocs)) ?
-		       	(POLLIN | POLLRDNORM) : 0;
+			(POLLIN | POLLRDNORM) : 0;
 
 	mask = 0;
 
@@ -5430,7 +5430,7 @@
 	DEFINE_WAIT(wait);
 
 	SCTP_DEBUG_PRINTK("wait_for_sndbuf: asoc=%p, timeo=%ld, msg_len=%zu\n",
-	                  asoc, (long)(*timeo_p), msg_len);
+			  asoc, (long)(*timeo_p), msg_len);
 
 	/* Increment the association's refcnt.  */
 	sctp_association_hold(asoc);
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 633cd17..e2c679b 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -254,7 +254,7 @@
 /* Sysctl registration.  */
 void sctp_sysctl_register(void)
 {
-	sctp_sysctl_header = register_sysctl_table(sctp_root_table, 0);
+	sctp_sysctl_header = register_sysctl_table(sctp_root_table);
 }
 
 /* Sysctl deregistration.  */
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 3e5936a..a596f53 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -130,9 +130,9 @@
 struct sctp_transport *sctp_transport_new(const union sctp_addr *addr,
 					  gfp_t gfp)
 {
-        struct sctp_transport *transport;
+	struct sctp_transport *transport;
 
-        transport = t_new(struct sctp_transport, gfp);
+	transport = t_new(struct sctp_transport, gfp);
 	if (!transport)
 		goto fail;
 
@@ -185,7 +185,7 @@
 	if (transport->asoc)
 		sctp_association_put(transport->asoc);
 
-        sctp_packet_free(&transport->packet);
+	sctp_packet_free(&transport->packet);
 
 	dst_release(transport->dst);
 	kfree(transport);
@@ -268,7 +268,7 @@
 
 		/* Initialize sk->sk_rcv_saddr, if the transport is the
 		 * association's active path for getsockname().
-		 */ 
+		 */
 		if (asoc && (transport == asoc->peer.active_path))
 			opt->pf->af->to_sk_saddr(&transport->saddr,
 						 asoc->base.sk);
@@ -459,8 +459,8 @@
 		 * destination address(es) to which the missing DATA chunks
 		 * were last sent, according to the formula described in
 		 * Section 7.2.3.
-	 	 *
-	 	 * RFC 2960 7.2.3, sctpimpguide Upon detection of packet
+		 *
+		 * RFC 2960 7.2.3, sctpimpguide Upon detection of packet
 		 * losses from SACK (see Section 7.2.4), An endpoint
 		 * should do the following:
 		 *      ssthresh = max(cwnd/2, 4*MTU)
@@ -488,7 +488,7 @@
 		if ((jiffies - transport->last_time_ecne_reduced) >
 		    transport->rtt) {
 			transport->ssthresh = max(transport->cwnd/2,
-					  	  4*transport->asoc->pathmtu);
+						  4*transport->asoc->pathmtu);
 			transport->cwnd = transport->ssthresh;
 			transport->last_time_ecne_reduced = jiffies;
 		}
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
index 42d9498..d3192a1 100644
--- a/net/sctp/tsnmap.c
+++ b/net/sctp/tsnmap.c
@@ -277,7 +277,7 @@
 			/* Now tsn_map must have been all '1's,
 			 * so we swap the map and check the overflow table
 			 */
-        		__u8 *tmp = map->tsn_map;
+			__u8 *tmp = map->tsn_map;
 			memset(tmp, 0, map->len);
 			map->tsn_map = map->overflow_map;
 			map->overflow_map = tmp;
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 445e07a..2e11bc8 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -749,7 +749,7 @@
 	 */
 	pd->pdapi_length = sizeof(struct sctp_pdapi_event);
 
-        /*  pdapi_indication: 32 bits (unsigned integer)
+	/*  pdapi_indication: 32 bits (unsigned integer)
 	 *
 	 * This field holds the indication being sent to the application.
 	 */
@@ -790,13 +790,13 @@
 		return;
 
 	/* Sockets API Extensions for SCTP
- 	 * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
- 	 *
- 	 * sinfo_stream: 16 bits (unsigned integer)
- 	 *
- 	 * For recvmsg() the SCTP stack places the message's stream number in
- 	 * this value.
- 	*/
+	 * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
+	 *
+	 * sinfo_stream: 16 bits (unsigned integer)
+	 *
+	 * For recvmsg() the SCTP stack places the message's stream number in
+	 * this value.
+	*/
 	sinfo.sinfo_stream = event->stream;
 	/* sinfo_ssn: 16 bits (unsigned integer)
 	 *
@@ -828,7 +828,7 @@
 	sinfo.sinfo_flags = event->flags;
 	/* sinfo_tsn: 32 bit (unsigned integer)
 	 *
-	 * For the receiving side, this field holds a TSN that was 
+	 * For the receiving side, this field holds a TSN that was
 	 * assigned to one of the SCTP Data Chunks.
 	 */
 	sinfo.sinfo_tsn = event->tsn;
@@ -879,7 +879,7 @@
 	 * fragment of the real event.  However, we still need to do rwnd
 	 * accounting.
 	 * In general, the skb passed from IP can have only 1 level of
-	 * fragments. But we allow multiple levels of fragments. 
+	 * fragments. But we allow multiple levels of fragments.
 	 */
 	for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {
 		sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc);
@@ -888,7 +888,7 @@
 
 /* Do accounting for bytes just read by user and release the references to
  * the association.
- */ 
+ */
 static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
 {
 	struct sk_buff *skb, *frag;
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index e1d1442..f4759a9 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -191,7 +191,7 @@
 		queue = &sk->sk_receive_queue;
 	} else if (ulpq->pd_mode) {
 		if (event->msg_flags & MSG_NOTIFICATION)
-		       	queue = &sctp_sk(sk)->pd_lobby;
+			queue = &sctp_sk(sk)->pd_lobby;
 		else {
 			clear_pd = event->msg_flags & MSG_EOR;
 			queue = &sk->sk_receive_queue;
@@ -298,32 +298,32 @@
 	 */
 	if (last)
 		last->next = pos;
- 	else {
- 		if (skb_cloned(f_frag)) {
- 			/* This is a cloned skb, we can't just modify
- 			 * the frag_list.  We need a new skb to do that.
- 			 * Instead of calling skb_unshare(), we'll do it
- 			 * ourselves since we need to delay the free.
- 			 */
- 			new = skb_copy(f_frag, GFP_ATOMIC);
- 			if (!new)
- 				return NULL;	/* try again later */
+	else {
+		if (skb_cloned(f_frag)) {
+			/* This is a cloned skb, we can't just modify
+			 * the frag_list.  We need a new skb to do that.
+			 * Instead of calling skb_unshare(), we'll do it
+			 * ourselves since we need to delay the free.
+			 */
+			new = skb_copy(f_frag, GFP_ATOMIC);
+			if (!new)
+				return NULL;	/* try again later */
 
- 			sctp_skb_set_owner_r(new, f_frag->sk);
+			sctp_skb_set_owner_r(new, f_frag->sk);
 
- 			skb_shinfo(new)->frag_list = pos;
- 		} else
- 			skb_shinfo(f_frag)->frag_list = pos;
- 	}
+			skb_shinfo(new)->frag_list = pos;
+		} else
+			skb_shinfo(f_frag)->frag_list = pos;
+	}
 
 	/* Remove the first fragment from the reassembly queue.  */
 	__skb_unlink(f_frag, queue);
 
- 	/* if we did unshare, then free the old skb and re-assign */
- 	if (new) {
- 		kfree_skb(f_frag);
- 		f_frag = new;
- 	}
+	/* if we did unshare, then free the old skb and re-assign */
+	if (new) {
+		kfree_skb(f_frag);
+		f_frag = new;
+	}
 
 	while (pos) {
 
@@ -335,7 +335,7 @@
 
 		/* Remove the fragment from the reassembly queue.  */
 		__skb_unlink(pos, queue);
-	
+
 		/* Break if we have reached the last fragment.  */
 		if (pos == l_frag)
 			break;
@@ -624,7 +624,7 @@
 
 	sid = event->stream;
 	ssn = event->ssn;
-	
+
 	cevent = (struct sctp_ulpevent *) pos->cb;
 	csid = cevent->stream;
 	cssn = cevent->ssn;
@@ -718,11 +718,11 @@
 		if (cssn != sctp_ssn_peek(in, csid))
 			break;
 
-		/* Found it, so mark in the ssnmap. */	       
+		/* Found it, so mark in the ssnmap. */
 		sctp_ssn_next(in, csid);
 
 		__skb_unlink(pos, &ulpq->lobby);
-		if (!event) {						
+		if (!event) {
 			/* Create a temporary list to collect chunks on.  */
 			event = sctp_skb2event(pos);
 			__skb_queue_tail(&temp, sctp_event2skb(event));
@@ -755,7 +755,7 @@
 	sctp_ssn_skip(in, sid, ssn);
 
 	/* Go find any other chunks that were waiting for
-	 * ordering and deliver them if needed. 
+	 * ordering and deliver them if needed.
 	 */
 	sctp_ulpq_reap_ordered(ulpq);
 	return;
@@ -849,7 +849,7 @@
 	if (chunk) {
 		needed = ntohs(chunk->chunk_hdr->length);
 		needed -= sizeof(sctp_data_chunk_t);
-	} else 
+	} else
 		needed = SCTP_DEFAULT_MAXWINDOW;
 
 	freed = 0;
@@ -866,7 +866,7 @@
 		tsn = ntohl(chunk->subh.data_hdr->tsn);
 		sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn);
 		sctp_ulpq_tail_data(ulpq, chunk, gfp);
-		
+
 		sctp_ulpq_partial_delivery(ulpq, chunk, gfp);
 	}
 
diff --git a/net/socket.c b/net/socket.c
index 4e39631..9566e57 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -117,7 +117,7 @@
  *	in the operation structures but are done directly via the socketcall() multiplexor.
  */
 
-static struct file_operations socket_file_ops = {
+static const struct file_operations socket_file_ops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.aio_read =	sock_aio_read,
@@ -407,24 +407,11 @@
 
 static struct socket *sock_from_file(struct file *file, int *err)
 {
-	struct inode *inode;
-	struct socket *sock;
-
 	if (file->f_op == &socket_file_ops)
 		return file->private_data;	/* set in sock_map_fd */
 
-	inode = file->f_path.dentry->d_inode;
-	if (!S_ISSOCK(inode->i_mode)) {
-		*err = -ENOTSOCK;
-		return NULL;
-	}
-
-	sock = SOCKET_I(inode);
-	if (sock->file != file) {
-		printk(KERN_ERR "socki_lookup: socket file changed!\n");
-		sock->file = file;
-	}
-	return sock;
+	*err = -ENOTSOCK;
+	return NULL;
 }
 
 /**
@@ -1207,6 +1194,7 @@
 {
 	struct socket *sock1, *sock2;
 	int fd1, fd2, err;
+	struct file *newfile1, *newfile2;
 
 	/*
 	 * Obtain the first socket and check if the underlying protocol
@@ -1225,18 +1213,37 @@
 	if (err < 0)
 		goto out_release_both;
 
-	fd1 = fd2 = -1;
-
-	err = sock_map_fd(sock1);
-	if (err < 0)
+	fd1 = sock_alloc_fd(&newfile1);
+	if (unlikely(fd1 < 0))
 		goto out_release_both;
-	fd1 = err;
 
-	err = sock_map_fd(sock2);
-	if (err < 0)
-		goto out_close_1;
-	fd2 = err;
+	fd2 = sock_alloc_fd(&newfile2);
+	if (unlikely(fd2 < 0)) {
+		put_filp(newfile1);
+		put_unused_fd(fd1);
+		goto out_release_both;
+	}
 
+	err = sock_attach_fd(sock1, newfile1);
+	if (unlikely(err < 0)) {
+		goto out_fd2;
+	}
+
+	err = sock_attach_fd(sock2, newfile2);
+	if (unlikely(err < 0)) {
+		fput(newfile1);
+		goto out_fd1;
+	}
+
+	err = audit_fd_pair(fd1, fd2);
+	if (err < 0) {
+		fput(newfile1);
+		fput(newfile2);
+		goto out_fd;
+	}
+
+	fd_install(fd1, newfile1);
+	fd_install(fd2, newfile2);
 	/* fd1 and fd2 may be already another descriptors.
 	 * Not kernel problem.
 	 */
@@ -1251,17 +1258,23 @@
 	sys_close(fd1);
 	return err;
 
-out_close_1:
-	sock_release(sock2);
-	sys_close(fd1);
-	return err;
-
 out_release_both:
 	sock_release(sock2);
 out_release_1:
 	sock_release(sock1);
 out:
 	return err;
+
+out_fd2:
+	put_filp(newfile1);
+	sock_release(sock1);
+out_fd1:
+	put_filp(newfile2);
+	sock_release(sock2);
+out_fd:
+	put_unused_fd(fd1);
+	put_unused_fd(fd2);
+	goto out;
 }
 
 /*
@@ -1527,8 +1540,9 @@
 	struct file *sock_file;
 
 	sock_file = fget_light(fd, &fput_needed);
+	err = -EBADF;
 	if (!sock_file)
-		return -EBADF;
+		goto out;
 
 	sock = sock_from_file(sock_file, &err);
 	if (!sock)
@@ -1555,6 +1569,7 @@
 
 out_put:
 	fput_light(sock_file, fput_needed);
+out:
 	return err;
 }
 
@@ -1586,12 +1601,13 @@
 	int fput_needed;
 
 	sock_file = fget_light(fd, &fput_needed);
+	err = -EBADF;
 	if (!sock_file)
-		return -EBADF;
+		goto out;
 
 	sock = sock_from_file(sock_file, &err);
 	if (!sock)
-		goto out;
+		goto out_put;
 
 	msg.msg_control = NULL;
 	msg.msg_controllen = 0;
@@ -1610,8 +1626,9 @@
 		if (err2 < 0)
 			err = err2;
 	}
-out:
+out_put:
 	fput_light(sock_file, fput_needed);
+out:
 	return err;
 }
 
@@ -2189,7 +2206,7 @@
 }
 
 int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
-                   int flags)
+		   int flags)
 {
 	return sock->ops->connect(sock, addr, addrlen, flags);
 }
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 993ff1a..9527f2b 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -181,7 +181,7 @@
 	struct rpc_cred	*cred;
 	int		i;
 
-	dprintk("RPC: gc'ing RPC credentials for auth %p\n", auth);
+	dprintk("RPC:       gc'ing RPC credentials for auth %p\n", auth);
 	for (i = 0; i < RPC_CREDCACHE_NR; i++) {
 		hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
 			cred = hlist_entry(pos, struct rpc_cred, cr_hash);
@@ -213,7 +213,7 @@
 		rpcauth_gc_credcache(auth, &free);
 	hlist_for_each_safe(pos, next, &cache->hashtable[nr]) {
 		struct rpc_cred *entry;
-	       	entry = hlist_entry(pos, struct rpc_cred, cr_hash);
+		entry = hlist_entry(pos, struct rpc_cred, cr_hash);
 		if (entry->cr_ops->crmatch(acred, entry, flags)) {
 			hlist_del(&entry->cr_hash);
 			cred = entry;
@@ -267,7 +267,7 @@
 	};
 	struct rpc_cred *ret;
 
-	dprintk("RPC:     looking up %s cred\n",
+	dprintk("RPC:       looking up %s cred\n",
 		auth->au_ops->au_name);
 	get_group_info(acred.group_info);
 	ret = auth->au_ops->lookup_cred(auth, &acred, flags);
@@ -287,7 +287,7 @@
 	struct rpc_cred *ret;
 	int flags = 0;
 
-	dprintk("RPC: %4d looking up %s cred\n",
+	dprintk("RPC: %5u looking up %s cred\n",
 		task->tk_pid, task->tk_auth->au_ops->au_name);
 	get_group_info(acred.group_info);
 	if (task->tk_flags & RPC_TASK_ROOTCREDS)
@@ -304,8 +304,9 @@
 void
 rpcauth_holdcred(struct rpc_task *task)
 {
-	dprintk("RPC: %4d holding %s cred %p\n",
-		task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
+	dprintk("RPC: %5u holding %s cred %p\n",
+		task->tk_pid, task->tk_auth->au_ops->au_name,
+		task->tk_msg.rpc_cred);
 	if (task->tk_msg.rpc_cred)
 		get_rpccred(task->tk_msg.rpc_cred);
 }
@@ -324,7 +325,7 @@
 {
 	struct rpc_cred	*cred = task->tk_msg.rpc_cred;
 
-	dprintk("RPC: %4d releasing %s cred %p\n",
+	dprintk("RPC: %5u releasing %s cred %p\n",
 		task->tk_pid, task->tk_auth->au_ops->au_name, cred);
 
 	put_rpccred(cred);
@@ -336,7 +337,7 @@
 {
 	struct rpc_cred	*cred = task->tk_msg.rpc_cred;
 
-	dprintk("RPC: %4d marshaling %s cred %p\n",
+	dprintk("RPC: %5u marshaling %s cred %p\n",
 		task->tk_pid, task->tk_auth->au_ops->au_name, cred);
 
 	return cred->cr_ops->crmarshal(task, p);
@@ -347,7 +348,7 @@
 {
 	struct rpc_cred	*cred = task->tk_msg.rpc_cred;
 
-	dprintk("RPC: %4d validating %s cred %p\n",
+	dprintk("RPC: %5u validating %s cred %p\n",
 		task->tk_pid, task->tk_auth->au_ops->au_name, cred);
 
 	return cred->cr_ops->crvalidate(task, p);
@@ -359,7 +360,7 @@
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
-	dprintk("RPC: %4d using %s cred %p to wrap rpc data\n",
+	dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
 			task->tk_pid, cred->cr_ops->cr_name, cred);
 	if (cred->cr_ops->crwrap_req)
 		return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
@@ -373,7 +374,7 @@
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
-	dprintk("RPC: %4d using %s cred %p to unwrap rpc data\n",
+	dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
 			task->tk_pid, cred->cr_ops->cr_name, cred);
 	if (cred->cr_ops->crunwrap_resp)
 		return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
@@ -388,7 +389,7 @@
 	struct rpc_cred	*cred = task->tk_msg.rpc_cred;
 	int err;
 
-	dprintk("RPC: %4d refreshing %s cred %p\n",
+	dprintk("RPC: %5u refreshing %s cred %p\n",
 		task->tk_pid, task->tk_auth->au_ops->au_name, cred);
 
 	err = cred->cr_ops->crrefresh(task);
@@ -400,7 +401,7 @@
 void
 rpcauth_invalcred(struct rpc_task *task)
 {
-	dprintk("RPC: %4d invalidating %s cred %p\n",
+	dprintk("RPC: %5u invalidating %s cred %p\n",
 		task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
 	spin_lock(&rpc_credcache_lock);
 	if (task->tk_msg.rpc_cred)
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index e1a104a..4e4ccc5 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -2,7 +2,7 @@
  * linux/net/sunrpc/auth_gss/auth_gss.c
  *
  * RPCSEC_GSS client authentication.
- * 
+ *
  *  Copyright (c) 2000 The Regents of the University of Michigan.
  *  All rights reserved.
  *
@@ -74,7 +74,7 @@
 * as it is passed to gssd to signal the use of
 * machine creds should be part of the shared rpc interface */
 
-#define CA_RUN_AS_MACHINE  0x00000200 
+#define CA_RUN_AS_MACHINE  0x00000200
 
 /* dump the buffer in `emacs-hexl' style */
 #define isprint(c)      ((c > 0x1f) && (c < 0x7f))
@@ -241,7 +241,7 @@
 	}
 	return q;
 err:
-	dprintk("RPC:      gss_fill_context returning %ld\n", -PTR_ERR(p));
+	dprintk("RPC:       gss_fill_context returning %ld\n", -PTR_ERR(p));
 	return p;
 }
 
@@ -276,10 +276,10 @@
 		if (pos->uid != uid)
 			continue;
 		atomic_inc(&pos->count);
-		dprintk("RPC:      gss_find_upcall found msg %p\n", pos);
+		dprintk("RPC:       gss_find_upcall found msg %p\n", pos);
 		return pos;
 	}
-	dprintk("RPC:      gss_find_upcall found nothing\n");
+	dprintk("RPC:       gss_find_upcall found nothing\n");
 	return NULL;
 }
 
@@ -393,7 +393,8 @@
 	struct gss_upcall_msg *gss_msg;
 	int err = 0;
 
-	dprintk("RPC: %4u gss_refresh_upcall for uid %u\n", task->tk_pid, cred->cr_uid);
+	dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
+								cred->cr_uid);
 	gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
 	if (IS_ERR(gss_msg)) {
 		err = PTR_ERR(gss_msg);
@@ -413,8 +414,8 @@
 	spin_unlock(&gss_auth->lock);
 	gss_release_msg(gss_msg);
 out:
-	dprintk("RPC: %4u gss_refresh_upcall for uid %u result %d\n", task->tk_pid,
-			cred->cr_uid, err);
+	dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n",
+			task->tk_pid, cred->cr_uid, err);
 	return err;
 }
 
@@ -426,7 +427,7 @@
 	DEFINE_WAIT(wait);
 	int err = 0;
 
-	dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid);
+	dprintk("RPC:       gss_upcall for uid %u\n", cred->cr_uid);
 	gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
 	if (IS_ERR(gss_msg)) {
 		err = PTR_ERR(gss_msg);
@@ -454,7 +455,8 @@
 	finish_wait(&gss_msg->waitqueue, &wait);
 	gss_release_msg(gss_msg);
 out:
-	dprintk("RPC: gss_create_upcall for uid %u result %d\n", cred->cr_uid, err);
+	dprintk("RPC:       gss_create_upcall for uid %u result %d\n",
+			cred->cr_uid, err);
 	return err;
 }
 
@@ -546,14 +548,14 @@
 	}
 	gss_put_ctx(ctx);
 	kfree(buf);
-	dprintk("RPC:      gss_pipe_downcall returning length %Zu\n", mlen);
+	dprintk("RPC:       gss_pipe_downcall returning length %Zu\n", mlen);
 	return mlen;
 err_put_ctx:
 	gss_put_ctx(ctx);
 err:
 	kfree(buf);
 out:
-	dprintk("RPC:      gss_pipe_downcall returning %d\n", err);
+	dprintk("RPC:       gss_pipe_downcall returning %d\n", err);
 	return err;
 }
 
@@ -591,7 +593,7 @@
 	static unsigned long ratelimit;
 
 	if (msg->errno < 0) {
-		dprintk("RPC:      gss_pipe_destroy_msg releasing msg %p\n",
+		dprintk("RPC:       gss_pipe_destroy_msg releasing msg %p\n",
 				gss_msg);
 		atomic_inc(&gss_msg->count);
 		gss_unhash_msg(gss_msg);
@@ -607,8 +609,8 @@
 	}
 }
 
-/* 
- * NOTE: we have the opportunity to use different 
+/*
+ * NOTE: we have the opportunity to use different
  * parameters based on the input flavor (which must be a pseudoflavor)
  */
 static struct rpc_auth *
@@ -618,7 +620,7 @@
 	struct rpc_auth * auth;
 	int err = -ENOMEM; /* XXX? */
 
-	dprintk("RPC:      creating GSS authenticator for client %p\n",clnt);
+	dprintk("RPC:       creating GSS authenticator for client %p\n", clnt);
 
 	if (!try_module_get(THIS_MODULE))
 		return ERR_PTR(err);
@@ -670,8 +672,8 @@
 {
 	struct gss_auth *gss_auth;
 
-	dprintk("RPC:      destroying GSS authenticator %p flavor %d\n",
-		auth, auth->au_flavor);
+	dprintk("RPC:       destroying GSS authenticator %p flavor %d\n",
+			auth, auth->au_flavor);
 
 	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
 	rpc_unlink(gss_auth->dentry);
@@ -689,7 +691,7 @@
 static void
 gss_destroy_ctx(struct gss_cl_ctx *ctx)
 {
-	dprintk("RPC:      gss_destroy_ctx\n");
+	dprintk("RPC:       gss_destroy_ctx\n");
 
 	if (ctx->gc_gss_ctx)
 		gss_delete_sec_context(&ctx->gc_gss_ctx);
@@ -703,7 +705,7 @@
 {
 	struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);
 
-	dprintk("RPC:      gss_destroy_cred \n");
+	dprintk("RPC:       gss_destroy_cred \n");
 
 	if (cred->gc_ctx)
 		gss_put_ctx(cred->gc_ctx);
@@ -726,7 +728,7 @@
 	struct gss_cred	*cred = NULL;
 	int err = -ENOMEM;
 
-	dprintk("RPC:      gss_create_cred for uid %d, flavor %d\n",
+	dprintk("RPC:       gss_create_cred for uid %d, flavor %d\n",
 		acred->uid, auth->au_flavor);
 
 	if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL)))
@@ -745,7 +747,7 @@
 	return &cred->gc_base;
 
 out_err:
-	dprintk("RPC:      gss_create_cred failed with error %d\n", err);
+	dprintk("RPC:       gss_create_cred failed with error %d\n", err);
 	return ERR_PTR(err);
 }
 
@@ -799,7 +801,7 @@
 	struct kvec	iov;
 	struct xdr_buf	verf_buf;
 
-	dprintk("RPC: %4u gss_marshal\n", task->tk_pid);
+	dprintk("RPC: %5u gss_marshal\n", task->tk_pid);
 
 	*p++ = htonl(RPC_AUTH_GSS);
 	cred_len = p++;
@@ -865,11 +867,11 @@
 	u32		flav,len;
 	u32		maj_stat;
 
-	dprintk("RPC: %4u gss_validate\n", task->tk_pid);
+	dprintk("RPC: %5u gss_validate\n", task->tk_pid);
 
 	flav = ntohl(*p++);
 	if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE)
-                goto out_bad;
+		goto out_bad;
 	if (flav != RPC_AUTH_GSS)
 		goto out_bad;
 	seq = htonl(task->tk_rqstp->rq_seqno);
@@ -888,12 +890,12 @@
 	 * calculate the length of the verifier: */
 	task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2;
 	gss_put_ctx(ctx);
-	dprintk("RPC: %4u GSS gss_validate: gss_verify_mic succeeded.\n",
+	dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n",
 			task->tk_pid);
 	return p + XDR_QUADLEN(len);
 out_bad:
 	gss_put_ctx(ctx);
-	dprintk("RPC: %4u gss_validate failed.\n", task->tk_pid);
+	dprintk("RPC: %5u gss_validate failed.\n", task->tk_pid);
 	return NULL;
 }
 
@@ -925,7 +927,7 @@
 	*integ_len = htonl(integ_buf.len);
 
 	/* guess whether we're in the head or the tail: */
-	if (snd_buf->page_len || snd_buf->tail[0].iov_len) 
+	if (snd_buf->page_len || snd_buf->tail[0].iov_len)
 		iov = snd_buf->tail;
 	else
 		iov = snd_buf->head;
@@ -1030,7 +1032,7 @@
 	maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages);
 	/* RPC_SLACK_SPACE should prevent this ever happening: */
 	BUG_ON(snd_buf->len > snd_buf->buflen);
-        status = -EIO;
+	status = -EIO;
 	/* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
 	 * done anyway, so it's safe to put the request on the wire: */
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
@@ -1063,7 +1065,7 @@
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
 	int             status = -EIO;
 
-	dprintk("RPC: %4u gss_wrap_req\n", task->tk_pid);
+	dprintk("RPC: %5u gss_wrap_req\n", task->tk_pid);
 	if (ctx->gc_proc != RPC_GSS_PROC_DATA) {
 		/* The spec seems a little ambiguous here, but I think that not
 		 * wrapping context destruction requests makes the most sense.
@@ -1079,14 +1081,14 @@
 			status = gss_wrap_req_integ(cred, ctx, encode,
 								rqstp, p, obj);
 			break;
-       		case RPC_GSS_SVC_PRIVACY:
+		case RPC_GSS_SVC_PRIVACY:
 			status = gss_wrap_req_priv(cred, ctx, encode,
 					rqstp, p, obj);
 			break;
 	}
 out:
 	gss_put_ctx(ctx);
-	dprintk("RPC: %4u gss_wrap_req returning %d\n", task->tk_pid, status);
+	dprintk("RPC: %5u gss_wrap_req returning %d\n", task->tk_pid, status);
 	return status;
 }
 
@@ -1179,7 +1181,7 @@
 			if (status)
 				goto out;
 			break;
-       		case RPC_GSS_SVC_PRIVACY:
+		case RPC_GSS_SVC_PRIVACY:
 			status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p);
 			if (status)
 				goto out;
@@ -1192,11 +1194,11 @@
 	status = decode(rqstp, p, obj);
 out:
 	gss_put_ctx(ctx);
-	dprintk("RPC: %4u gss_unwrap_resp returning %d\n", task->tk_pid,
+	dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid,
 			status);
 	return status;
 }
-  
+
 static struct rpc_authops authgss_ops = {
 	.owner		= THIS_MODULE,
 	.au_flavor	= RPC_AUTH_GSS,
diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
index 826df44..ea8c92e 100644
--- a/net/sunrpc/auth_gss/gss_generic_token.c
+++ b/net/sunrpc/auth_gss/gss_generic_token.c
@@ -11,7 +11,7 @@
 
 /*
  * Copyright 1993 by OpenVision Technologies, Inc.
- * 
+ *
  * Permission to use, copy, modify, distribute, and sell this software
  * and its documentation for any purpose is hereby granted without fee,
  * provided that the above copyright notice appears in all copies and
@@ -21,7 +21,7 @@
  * without specific, written prior permission. OpenVision makes no
  * representations about the suitability of this software for any
  * purpose.  It is provided "as is" without express or implied warranty.
- * 
+ *
  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
@@ -201,7 +201,7 @@
 		return(G_BAD_TOK_HEADER);
 	if (*buf++ != 0x06)
 		return(G_BAD_TOK_HEADER);
- 
+
 	if ((toksize-=1) < 0)
 		return(G_BAD_TOK_HEADER);
 	toid.len = *buf++;
@@ -211,9 +211,9 @@
 	toid.data = buf;
 	buf+=toid.len;
 
-	if (! g_OID_equal(&toid, mech)) 
+	if (! g_OID_equal(&toid, mech))
 		ret = G_WRONG_MECH;
- 
+
    /* G_WRONG_MECH is not returned immediately because it's more important
       to return G_BAD_TOK_HEADER if the token header is in fact bad */
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index d926cda..f441aa0 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -58,7 +58,7 @@
 	int length)
 {
 	u32 ret = -EINVAL;
-        struct scatterlist sg[1];
+	struct scatterlist sg[1];
 	u8 local_iv[16] = {0};
 	struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
 
@@ -66,7 +66,7 @@
 		goto out;
 
 	if (crypto_blkcipher_ivsize(tfm) > 16) {
-		dprintk("RPC:      gss_k5encrypt: tfm iv size to large %d\n",
+		dprintk("RPC:       gss_k5encrypt: tfm iv size to large %d\n",
 		         crypto_blkcipher_ivsize(tfm));
 		goto out;
 	}
@@ -79,7 +79,7 @@
 
 	ret = crypto_blkcipher_encrypt_iv(&desc, sg, sg, length);
 out:
-	dprintk("RPC:      krb5_encrypt returns %d\n",ret);
+	dprintk("RPC:       krb5_encrypt returns %d\n", ret);
 	return ret;
 }
 
@@ -102,7 +102,7 @@
 		goto out;
 
 	if (crypto_blkcipher_ivsize(tfm) > 16) {
-		dprintk("RPC:      gss_k5decrypt: tfm iv size to large %d\n",
+		dprintk("RPC:       gss_k5decrypt: tfm iv size to large %d\n",
 			crypto_blkcipher_ivsize(tfm));
 		goto out;
 	}
@@ -114,7 +114,7 @@
 
 	ret = crypto_blkcipher_decrypt_iv(&desc, sg, sg, length);
 out:
-	dprintk("RPC:      gss_k5decrypt returns %d\n",ret);
+	dprintk("RPC:       gss_k5decrypt returns %d\n",ret);
 	return ret;
 }
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 05d4bee..7b19432 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -175,7 +175,8 @@
 	}
 
 	ctx_id->internal_ctx_id = ctx;
-	dprintk("RPC:      Successfully imported new context.\n");
+
+	dprintk("RPC:       Successfully imported new context.\n");
 	return 0;
 
 out_err_free_key2:
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index d0bb506..a0d9faa 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -83,7 +83,7 @@
 	s32			now;
 	u32			seq_send;
 
-	dprintk("RPC:     gss_krb5_seal\n");
+	dprintk("RPC:       gss_krb5_seal\n");
 
 	now = get_seconds();
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
index c604baf..43f3421 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
@@ -11,7 +11,7 @@
 
 /*
  * Copyright 1993 by OpenVision Technologies, Inc.
- * 
+ *
  * Permission to use, copy, modify, distribute, and sell this software
  * and its documentation for any purpose is hereby granted without fee,
  * provided that the above copyright notice appears in all copies and
@@ -21,7 +21,7 @@
  * without specific, written prior permission. OpenVision makes no
  * representations about the suitability of this software for any
  * purpose.  It is provided "as is" without express or implied warranty.
- * 
+ *
  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
@@ -70,7 +70,7 @@
 	s32 code;
 	unsigned char plain[8];
 
-	dprintk("RPC:      krb5_get_seq_num:\n");
+	dprintk("RPC:       krb5_get_seq_num:\n");
 
 	if ((code = krb5_decrypt(key, cksum, buf, plain, 8)))
 		return code;
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 87f8977..e30a993 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -86,7 +86,7 @@
 	unsigned char		*ptr = (unsigned char *)read_token->data;
 	int			bodysize;
 
-	dprintk("RPC:      krb5_read_token\n");
+	dprintk("RPC:       krb5_read_token\n");
 
 	if (g_verify_token_header(&ctx->mech_used, &bodysize, &ptr,
 					read_token->len))
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index fe25b3d..42b3220 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -129,7 +129,7 @@
 	struct page		**tmp_pages;
 	u32			seq_send;
 
-	dprintk("RPC:     gss_wrap_kerberos\n");
+	dprintk("RPC:       gss_wrap_kerberos\n");
 
 	now = get_seconds();
 
@@ -215,7 +215,7 @@
 	int			data_len;
 	int			blocksize;
 
-	dprintk("RPC:      gss_unwrap_kerberos\n");
+	dprintk("RPC:       gss_unwrap_kerberos\n");
 
 	ptr = (u8 *)buf->head[0].iov_base + offset;
 	if (g_verify_token_header(&kctx->mech_used, &bodysize, &ptr,
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 3db7453..2687251 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -6,14 +6,14 @@
  *
  *  J. Bruce Fields   <bfields@umich.edu>
  *
- *  Redistribution and use in source and binary forms, with or without 
+ *  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 
+ *     notice, this list of conditions and the following disclaimer in the
  *     documentation and/or other materials provided with the distribution.
  *  3. Neither the name of the University nor the names of its
  *     contributors may be used to endorse or promote products derived
@@ -113,7 +113,7 @@
 	spin_lock(&registered_mechs_lock);
 	list_add(&gm->gm_list, &registered_mechs);
 	spin_unlock(&registered_mechs_lock);
-	dprintk("RPC:      registered gss mechanism %s\n", gm->gm_name);
+	dprintk("RPC:       registered gss mechanism %s\n", gm->gm_name);
 	return 0;
 }
 
@@ -125,7 +125,7 @@
 	spin_lock(&registered_mechs_lock);
 	list_del(&gm->gm_list);
 	spin_unlock(&registered_mechs_lock);
-	dprintk("RPC:      unregistered gss mechanism %s\n", gm->gm_name);
+	dprintk("RPC:       unregistered gss mechanism %s\n", gm->gm_name);
 	gss_mech_free(gm);
 }
 
@@ -298,7 +298,7 @@
 u32
 gss_delete_sec_context(struct gss_ctx	**context_handle)
 {
-	dprintk("RPC:      gss_delete_sec_context deleting %p\n",
+	dprintk("RPC:       gss_delete_sec_context deleting %p\n",
 			*context_handle);
 
 	if (!*context_handle)
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 8ef3f1c..7e15aa6 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -97,7 +97,8 @@
 	if (IS_ERR(p))
 		goto out_err_free_ctx;
 	if (version != 1) {
-		dprintk("RPC: unknown spkm3 token format: obsolete nfs-utils?\n");
+		dprintk("RPC:       unknown spkm3 token format: "
+				"obsolete nfs-utils?\n");
 		goto out_err_free_ctx;
 	}
 
@@ -138,7 +139,7 @@
 
 	ctx_id->internal_ctx_id = ctx;
 
-	dprintk("Successfully imported new spkm context.\n");
+	dprintk("RPC:       Successfully imported new spkm context.\n");
 	return 0;
 
 out_err_free_intg_key:
@@ -183,7 +184,7 @@
 
 	maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
 
-	dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat);
+	dprintk("RPC:       gss_verify_mic_spkm3 returning %d\n", maj_stat);
 	return maj_stat;
 }
 
@@ -197,7 +198,7 @@
 
 	err = spkm3_make_token(sctx, message_buffer,
 				message_token, SPKM_MIC_TOK);
-	dprintk("RPC: gss_get_mic_spkm3 returning %d\n", err);
+	dprintk("RPC:       gss_get_mic_spkm3 returning %d\n", err);
 	return err;
 }
 
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
index b179d58..104cbf4 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
@@ -75,20 +75,21 @@
 	now = jiffies;
 
 	if (ctx->ctx_id.len != 16) {
-		dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n",
+		dprintk("RPC:       spkm3_make_token BAD ctx_id.len %d\n",
 				ctx->ctx_id.len);
 		goto out_err;
 	}
 
 	if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) {
-		dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm."
-				"only support hmac-md5 I-ALG.\n");
+		dprintk("RPC:       gss_spkm3_seal: unsupported I-ALG "
+				"algorithm.  only support hmac-md5 I-ALG.\n");
 		goto out_err;
 	} else
 		checksum_type = CKSUMTYPE_HMAC_MD5;
 
 	if (!g_OID_equal(&ctx->conf_alg, &cast5_cbc_oid)) {
-		dprintk("RPC: gss_spkm3_seal: unsupported C-ALG algorithm\n");
+		dprintk("RPC:       gss_spkm3_seal: unsupported C-ALG "
+				"algorithm\n");
 		goto out_err;
 	}
 
@@ -113,7 +114,8 @@
 
 		spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit);
 	} else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */
-		dprintk("RPC: gss_spkm3_seal: SPKM_WRAP_TOK not supported\n");
+		dprintk("RPC:       gss_spkm3_seal: SPKM_WRAP_TOK "
+				"not supported\n");
 		goto out_err;
 	}
 
@@ -153,7 +155,7 @@
 			cksumname = "md5";
 			break;
 		default:
-			dprintk("RPC:      spkm3_make_checksum:"
+			dprintk("RPC:       spkm3_make_checksum:"
 					" unsupported checksum %d", cksumtype);
 			return GSS_S_FAILURE;
 	}
diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c
index 35188b6..6cdd241a 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_token.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_token.c
@@ -59,7 +59,7 @@
 
 	/* count trailing 0's */
 	for(i = in->len; i > 0; i--) {
-		if (*ptr == 0) { 
+		if (*ptr == 0) {
 			ptr--;
 			elen--;
 		} else
@@ -82,7 +82,7 @@
 
 /*
  * decode_asn1_bitstring()
- * 
+ *
  * decode a bitstring into a buffer of the expected length.
  * enclen = bit string length
  * explen = expected length (define in rfc)
@@ -97,9 +97,9 @@
 	return 1;
 }
 
-/* 
+/*
  * SPKMInnerContextToken choice SPKM_MIC asn1 token layout
- * 
+ *
  * contextid is always 16 bytes plain data. max asn1 bitstring len = 17.
  *
  * tokenlen = pos[0] to end of token (max pos[45] with MD5 cksum)
@@ -107,21 +107,21 @@
  * pos  value
  * ----------
  * [0]	a4  SPKM-MIC tag
- * [1]	??  innertoken length  (max 44) 
- * 
- * 
- * tok_hdr piece of checksum data starts here 
+ * [1]	??  innertoken length  (max 44)
  *
- * the maximum mic-header len = 9 + 17 = 26 
+ *
+ * tok_hdr piece of checksum data starts here
+ *
+ * the maximum mic-header len = 9 + 17 = 26
  *	mic-header
  *	----------
- * [2]	30      SEQUENCE tag  
- * [3]	??	mic-header length: (max 23) = TokenID + ContextID 
+ * [2]	30      SEQUENCE tag
+ * [3]	??	mic-header length: (max 23) = TokenID + ContextID
  *
  *		TokenID  - all fields constant and can be hardcoded
  *		-------
  * [4]	  02	Type 2
- * [5]	  02	Length 2 
+ * [5]	  02	Length 2
  * [6][7] 01 01	TokenID (SPKM_MIC_TOK)
  *
  *		ContextID  - encoded length not constant, calculated
@@ -131,17 +131,17 @@
  * [10]	??	ctxzbit
  * [11]	 	contextid
  *
- * mic_header piece of checksum data ends here. 
+ * mic_header piece of checksum data ends here.
  *
  *	int-cksum - encoded length not constant, calculated
  *	---------
  * [??]	03	Type 3
- * [??]	??	encoded length 
- * [??]	??	md5zbit		
+ * [??]	??	encoded length
+ * [??]	??	md5zbit
  * [??]	 	int-cksum (NID_md5 = 16)
  *
- * maximum SPKM-MIC innercontext token length = 
- *	 10 + encoded contextid_size(17 max) + 2 + encoded  
+ * maximum SPKM-MIC innercontext token length =
+ *	 10 + encoded contextid_size(17 max) + 2 + encoded
  *       cksum_size (17 maxfor NID_md5) = 46
  */
 
@@ -178,8 +178,8 @@
 /*
  * spkm3_mic_innercontext_token()
  *
- * *tokp points to the beginning of the SPKM_MIC token  described 
- * in rfc 2025, section 3.2.1: 
+ * *tokp points to the beginning of the SPKM_MIC token  described
+ * in rfc 2025, section 3.2.1:
  *
  * toklen is the inner token length
  */
@@ -209,7 +209,7 @@
 
 	/* spkm3 innercontext token preamble */
 	if ((ptr[0] != 0xa4) || (ptr[2] != 0x30)) {
-		dprintk("RPC: BAD SPKM ictoken preamble\n"); 
+		dprintk("RPC:       BAD SPKM ictoken preamble\n");
 		goto out;
 	}
 
@@ -217,25 +217,25 @@
 
 	/* token type */
 	if ((ptr[4] != 0x02) || (ptr[5] != 0x02)) {
-		dprintk("RPC: BAD asn1 SPKM3 token type\n");
+		dprintk("RPC:       BAD asn1 SPKM3 token type\n");
 		goto out;
 	}
 
 	/* only support SPKM_MIC_TOK */
 	if((ptr[6] != 0x01) || (ptr[7] != 0x01)) {
-		dprintk("RPC: ERROR unsupported SPKM3 token \n");
+		dprintk("RPC:       ERROR unsupported SPKM3 token \n");
 		goto out;
 	}
 
 	/* contextid */
 	if (ptr[8] != 0x03) {
-		dprintk("RPC: BAD SPKM3 asn1 context-id type\n");
+		dprintk("RPC:       BAD SPKM3 asn1 context-id type\n");
 		goto out;
 	}
 
 	ctxelen = ptr[9];
 	if (ctxelen > 17) {  /* length includes asn1 zbit octet */
-		dprintk("RPC: BAD SPKM3 contextid len %d\n", ctxelen);
+		dprintk("RPC:       BAD SPKM3 contextid len %d\n", ctxelen);
 		goto out;
 	}
 
@@ -245,17 +245,19 @@
 		goto out;
 
 	/*
-	* in the current implementation: the optional int-alg is not present 
-	* so the default int-alg (md5) is used the optional snd-seq field is 
-	* also not present 
+	* in the current implementation: the optional int-alg is not present
+	* so the default int-alg (md5) is used the optional snd-seq field is
+	* also not present
 	*/
 
 	if (*mic_hdrlen != 6 + ctxelen) {
-		dprintk("RPC: BAD SPKM_ MIC_TOK header len %d: we only support default int-alg (should be absent) and do not support snd-seq\n", *mic_hdrlen);
+		dprintk("RPC:       BAD SPKM_ MIC_TOK header len %d: we only "
+				"support default int-alg (should be absent) "
+				"and do not support snd-seq\n", *mic_hdrlen);
 		goto out;
 	}
 	/* checksum */
-        *cksum = (&ptr[10] + ctxelen); /* ctxelen includes ptr[10] */
+	*cksum = (&ptr[10] + ctxelen); /* ctxelen includes ptr[10] */
 
 	ret = GSS_S_COMPLETE;
 out:
diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
index e54581c..cc21ee8 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
@@ -45,7 +45,7 @@
 
 /*
  * spkm3_read_token()
- * 
+ *
  * only SPKM_MIC_TOK with md5 intg-alg is supported
  */
 u32
@@ -72,7 +72,7 @@
 	/* decode the token */
 
 	if (toktype != SPKM_MIC_TOK) {
-		dprintk("RPC: BAD SPKM3 token type: %d\n", toktype);
+		dprintk("RPC:       BAD SPKM3 token type: %d\n", toktype);
 		goto out;
 	}
 
@@ -80,7 +80,7 @@
 		goto out;
 
 	if (*cksum++ != 0x03) {
-		dprintk("RPC: spkm3_read_token BAD checksum type\n");
+		dprintk("RPC:       spkm3_read_token BAD checksum type\n");
 		goto out;
 	}
 	md5elen = *cksum++;
@@ -97,7 +97,8 @@
 	 */
 	ret = GSS_S_DEFECTIVE_TOKEN;
 	if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) {
-		dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm\n");
+		dprintk("RPC:       gss_spkm3_seal: unsupported I-ALG "
+				"algorithm\n");
 		goto out;
 	}
 
@@ -113,7 +114,7 @@
 	ret = GSS_S_BAD_SIG;
 	code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len);
 	if (code) {
-		dprintk("RPC: bad MIC checksum\n");
+		dprintk("RPC:       bad MIC checksum\n");
 		goto out;
 	}
 
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 066c64a..db298b5 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -172,8 +172,8 @@
 }
 
 static void rsi_request(struct cache_detail *cd,
-                       struct cache_head *h,
-                       char **bpp, int *blen)
+		       struct cache_head *h,
+		       char **bpp, int *blen)
 {
 	struct rsi *rsii = container_of(h, struct rsi, h);
 
@@ -184,7 +184,7 @@
 
 
 static int rsi_parse(struct cache_detail *cd,
-                    char *mesg, int mlen)
+		    char *mesg, int mlen)
 {
 	/* context token expiry major minor context token */
 	char *buf = mesg;
@@ -669,14 +669,14 @@
 	}
 
 	if (gc->gc_seq > MAXSEQ) {
-		dprintk("RPC:      svcauth_gss: discarding request with large sequence number %d\n",
-				gc->gc_seq);
+		dprintk("RPC:       svcauth_gss: discarding request with "
+				"large sequence number %d\n", gc->gc_seq);
 		*authp = rpcsec_gsserr_ctxproblem;
 		return SVC_DENIED;
 	}
 	if (!gss_check_seq_num(rsci, gc->gc_seq)) {
-		dprintk("RPC:      svcauth_gss: discarding request with old sequence number %d\n",
-				gc->gc_seq);
+		dprintk("RPC:       svcauth_gss: discarding request with "
+				"old sequence number %d\n", gc->gc_seq);
 		return SVC_DROP;
 	}
 	return SVC_OK;
@@ -958,7 +958,8 @@
 	__be32		*reject_stat = resv->iov_base + resv->iov_len;
 	int		ret;
 
-	dprintk("RPC:      svcauth_gss: argv->iov_len = %zd\n",argv->iov_len);
+	dprintk("RPC:       svcauth_gss: argv->iov_len = %zd\n",
+			argv->iov_len);
 
 	*authp = rpc_autherr_badcred;
 	if (!svcdata)
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 3be257d..3df9fcc 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 #include <linux/utsname.h>
 #include <linux/sunrpc/clnt.h>
-#include <linux/sched.h>
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY	RPCDBG_AUTH
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index f7f990c..4e7733a 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -39,7 +39,8 @@
 static struct rpc_auth *
 unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
 {
-	dprintk("RPC: creating UNIX authenticator for client %p\n", clnt);
+	dprintk("RPC:       creating UNIX authenticator for client %p\n",
+			clnt);
 	if (atomic_inc_return(&unix_auth.au_count) == 0)
 		unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1);
 	return &unix_auth;
@@ -48,7 +49,7 @@
 static void
 unx_destroy(struct rpc_auth *auth)
 {
-	dprintk("RPC: destroying UNIX authenticator %p\n", auth);
+	dprintk("RPC:       destroying UNIX authenticator %p\n", auth);
 	rpcauth_free_credcache(auth);
 }
 
@@ -67,8 +68,8 @@
 	struct unx_cred	*cred;
 	int		i;
 
-	dprintk("RPC:      allocating UNIX cred for uid %d gid %d\n",
-				acred->uid, acred->gid);
+	dprintk("RPC:       allocating UNIX cred for uid %d gid %d\n",
+			acred->uid, acred->gid);
 
 	if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))
 		return ERR_PTR(-ENOMEM);
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 1427449..f02f24a 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -215,7 +215,8 @@
 		if (rv == -EAGAIN)
 			rv = -ENOENT;
 	} else if (rv == -EAGAIN || age > refresh_age/2) {
-		dprintk("Want update, refage=%ld, age=%ld\n", refresh_age, age);
+		dprintk("RPC:       Want update, refage=%ld, age=%ld\n",
+				refresh_age, age);
 		if (!test_and_set_bit(CACHE_PENDING, &h->flags)) {
 			switch (cache_make_upcall(detail, h)) {
 			case -EINVAL:
@@ -274,7 +275,7 @@
  *
  * A table is then only scanned if the current time is at least
  * the nextcheck time.
- * 
+ *
  */
 
 static LIST_HEAD(cache_list);
@@ -282,9 +283,9 @@
 static struct cache_detail *current_detail;
 static int current_index;
 
-static struct file_operations cache_file_operations;
-static struct file_operations content_file_operations;
-static struct file_operations cache_flush_operations;
+static const struct file_operations cache_file_operations;
+static const struct file_operations content_file_operations;
+static const struct file_operations cache_flush_operations;
 
 static void do_cache_clean(struct work_struct *work);
 static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean);
@@ -296,16 +297,16 @@
 		struct proc_dir_entry *p;
 		cd->proc_ent->owner = cd->owner;
 		cd->channel_ent = cd->content_ent = NULL;
-		
- 		p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR,
- 				      cd->proc_ent);
+
+		p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR,
+				      cd->proc_ent);
 		cd->flush_ent =  p;
- 		if (p) {
- 			p->proc_fops = &cache_flush_operations;
- 			p->owner = cd->owner;
- 			p->data = cd;
- 		}
- 
+		if (p) {
+			p->proc_fops = &cache_flush_operations;
+			p->owner = cd->owner;
+			p->data = cd;
+		}
+
 		if (cd->cache_request || cd->cache_parse) {
 			p = create_proc_entry("channel", S_IFREG|S_IRUSR|S_IWUSR,
 					      cd->proc_ent);
@@ -316,16 +317,16 @@
 				p->data = cd;
 			}
 		}
- 		if (cd->cache_show) {
- 			p = create_proc_entry("content", S_IFREG|S_IRUSR|S_IWUSR,
- 					      cd->proc_ent);
+		if (cd->cache_show) {
+			p = create_proc_entry("content", S_IFREG|S_IRUSR|S_IWUSR,
+					      cd->proc_ent);
 			cd->content_ent = p;
- 			if (p) {
- 				p->proc_fops = &content_file_operations;
- 				p->owner = cd->owner;
- 				p->data = cd;
- 			}
- 		}
+			if (p) {
+				p->proc_fops = &content_file_operations;
+				p->owner = cd->owner;
+				p->data = cd;
+			}
+		}
 	}
 	rwlock_init(&cd->hash_lock);
 	INIT_LIST_HEAD(&cd->queue);
@@ -417,15 +418,15 @@
 		current_index++;
 
 	/* find a cleanable entry in the bucket and clean it, or set to next bucket */
-	
+
 	if (current_detail && current_index < current_detail->hash_size) {
 		struct cache_head *ch, **cp;
 		struct cache_detail *d;
-		
+
 		write_lock(&current_detail->hash_lock);
 
 		/* Ok, now to clean this strand */
-			
+
 		cp = & current_detail->hash_table[current_index];
 		ch = *cp;
 		for (; ch; cp= & ch->next, ch= *cp) {
@@ -477,9 +478,9 @@
 }
 
 
-/* 
+/*
  * Clean all caches promptly.  This just calls cache_clean
- * repeatedly until we are sure that every cache has had a chance to 
+ * repeatedly until we are sure that every cache has had a chance to
  * be fully cleaned
  */
 void cache_flush(void)
@@ -508,7 +509,7 @@
  * All deferred requests are stored in a hash table,
  * indexed by "struct cache_head *".
  * As it may be wasteful to store a whole request
- * structure, we allow the request to provide a 
+ * structure, we allow the request to provide a
  * deferred form, which must contain a
  * 'struct cache_deferred_req'
  * This cache_deferred_req contains a method to allow
@@ -584,7 +585,7 @@
 
 	INIT_LIST_HEAD(&pending);
 	spin_lock(&cache_defer_lock);
-	
+
 	lp = cache_defer_hash[hash].next;
 	if (lp) {
 		while (lp != &cache_defer_hash[hash]) {
@@ -614,7 +615,7 @@
 
 	INIT_LIST_HEAD(&pending);
 	spin_lock(&cache_defer_lock);
-	
+
 	list_for_each_entry_safe(dreq, tmp, &cache_defer_list, recent) {
 		if (dreq->owner == owner) {
 			list_del(&dreq->hash);
@@ -639,7 +640,7 @@
  * On write, an update request is processed
  * Poll works if anything to read, and always allows write
  *
- * Implemented by linked list of requests.  Each open file has 
+ * Implemented by linked list of requests.  Each open file has
  * a ->private that also exists in this list.  New request are added
  * to the end and may wakeup and preceding readers.
  * New readers are added to the head.  If, on read, an item is found with
@@ -887,7 +888,7 @@
 
 
 
-static struct file_operations cache_file_operations = {
+static const struct file_operations cache_file_operations = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= cache_read,
@@ -1059,10 +1060,10 @@
  * Messages are, like requests, separated into fields by
  * spaces and dequotes as \xHEXSTRING or embedded \nnn octal
  *
- * Message is 
+ * Message is
  *   reply cachename expiry key ... content....
  *
- * key and content are both parsed by cache 
+ * key and content are both parsed by cache
  */
 
 #define isodigit(c) (isdigit(c) && c <= '7')
@@ -1132,7 +1133,7 @@
 	unsigned hash, entry;
 	struct cache_head *ch;
 	struct cache_detail *cd = ((struct handle*)m->private)->cd;
-	
+
 
 	read_lock(&cd->hash_lock);
 	if (!n--)
@@ -1147,7 +1148,7 @@
 	do {
 		hash++;
 		n += 1LL<<32;
-	} while(hash < cd->hash_size && 
+	} while(hash < cd->hash_size &&
 		cd->hash_table[hash]==NULL);
 	if (hash >= cd->hash_size)
 		return NULL;
@@ -1245,7 +1246,7 @@
 	return seq_release(inode, file);
 }
 
-static struct file_operations content_file_operations = {
+static const struct file_operations content_file_operations = {
 	.open		= content_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -1297,7 +1298,7 @@
 	return count;
 }
 
-static struct file_operations cache_flush_operations = {
+static const struct file_operations cache_flush_operations = {
 	.open		= nonseekable_open,
 	.read		= read_flush,
 	.write		= write_flush,
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 16c9fbc..6d7221f 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -42,6 +42,10 @@
 # define RPCDBG_FACILITY	RPCDBG_CALL
 #endif
 
+#define dprint_status(t)					\
+	dprintk("RPC: %5u %s (status %d)\n", t->tk_pid,		\
+			__FUNCTION__, t->tk_status)
+
 static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);
 
 
@@ -106,8 +110,8 @@
 	int err;
 	int len;
 
-	dprintk("RPC: creating %s client for %s (xprt %p)\n",
-		program->name, servname, xprt);
+	dprintk("RPC:       creating %s client for %s (xprt %p)\n",
+			program->name, servname, xprt);
 
 	err = -EINVAL;
 	if (!xprt)
@@ -220,7 +224,7 @@
 		xprt->resvport = 0;
 
 	dprintk("RPC:       creating %s client for %s (xprt %p)\n",
-		args->program->name, args->servername, xprt);
+			args->program->name, args->servername, xprt);
 
 	clnt = rpc_new_client(xprt, args->servername, args->program,
 				args->version, args->authflavor);
@@ -245,6 +249,8 @@
 		clnt->cl_autobind = 1;
 	if (args->flags & RPC_CLNT_CREATE_ONESHOT)
 		clnt->cl_oneshot = 1;
+	if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
+		clnt->cl_discrtry = 1;
 
 	return clnt;
 }
@@ -288,7 +294,7 @@
 out_no_stats:
 	kfree(new);
 out_no_clnt:
-	dprintk("RPC: %s returned error %d\n", __FUNCTION__, err);
+	dprintk("RPC:       %s: returned error %d\n", __FUNCTION__, err);
 	return ERR_PTR(err);
 }
 
@@ -301,7 +307,7 @@
 int
 rpc_shutdown_client(struct rpc_clnt *clnt)
 {
-	dprintk("RPC: shutting down %s client for %s, tasks=%d\n",
+	dprintk("RPC:       shutting down %s client for %s, tasks=%d\n",
 			clnt->cl_protname, clnt->cl_server,
 			atomic_read(&clnt->cl_users));
 
@@ -336,7 +342,7 @@
 		return 1;
 	BUG_ON(atomic_read(&clnt->cl_users) != 0);
 
-	dprintk("RPC: destroying %s client for %s\n",
+	dprintk("RPC:       destroying %s client for %s\n",
 			clnt->cl_protname, clnt->cl_server);
 	if (clnt->cl_auth) {
 		rpcauth_destroy(clnt->cl_auth);
@@ -366,8 +372,8 @@
 void
 rpc_release_client(struct rpc_clnt *clnt)
 {
-	dprintk("RPC:      rpc_release_client(%p, %d)\n",
-				clnt, atomic_read(&clnt->cl_users));
+	dprintk("RPC:       rpc_release_client(%p, %d)\n",
+			clnt, atomic_read(&clnt->cl_users));
 
 	if (!atomic_dec_and_test(&clnt->cl_users))
 		return;
@@ -410,7 +416,7 @@
 		rpc_shutdown_client(clnt);
 		clnt = ERR_PTR(err);
 	}
-out:	
+out:
 	return clnt;
 }
 
@@ -431,7 +437,7 @@
  *	sleeps on RPC calls
  */
 #define RPC_INTR_SIGNALS (sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTERM))
- 
+
 static void rpc_save_sigmask(sigset_t *oldset, int intr)
 {
 	unsigned long	sigallow = sigmask(SIGKILL);
@@ -474,7 +480,7 @@
 	int		status;
 
 	/* If this client is slain all further I/O fails */
-	if (clnt->cl_dead) 
+	if (clnt->cl_dead)
 		return -EIO;
 
 	BUG_ON(flags & RPC_TASK_ASYNC);
@@ -486,17 +492,13 @@
 	/* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
 	rpc_task_sigmask(task, &oldset);
 
-	rpc_call_setup(task, msg, 0);
-
 	/* Set up the call info struct and execute the task */
+	rpc_call_setup(task, msg, 0);
+	if (task->tk_status == 0) {
+		atomic_inc(&task->tk_count);
+		rpc_execute(task);
+	}
 	status = task->tk_status;
-	if (status != 0)
-		goto out;
-	atomic_inc(&task->tk_count);
-	status = rpc_execute(task);
-	if (status == 0)
-		status = task->tk_status;
-out:
 	rpc_put_task(task);
 	rpc_restore_sigmask(&oldset);
 	return status;
@@ -515,7 +517,7 @@
 
 	/* If this client is slain all further I/O fails */
 	status = -EIO;
-	if (clnt->cl_dead) 
+	if (clnt->cl_dead)
 		goto out_release;
 
 	flags |= RPC_TASK_ASYNC;
@@ -526,7 +528,7 @@
 		goto out_release;
 
 	/* Mask signals on GSS_AUTH upcalls */
-	rpc_task_sigmask(task, &oldset);		
+	rpc_task_sigmask(task, &oldset);
 
 	rpc_call_setup(task, msg, 0);
 
@@ -537,7 +539,7 @@
 	else
 		rpc_put_task(task);
 
-	rpc_restore_sigmask(&oldset);		
+	rpc_restore_sigmask(&oldset);
 	return status;
 out_release:
 	rpc_release_calldata(tk_ops, data);
@@ -658,9 +660,10 @@
 {
 	struct rpc_clnt	*clnt = task->tk_client;
 
-	dprintk("RPC: %4d call_start %s%d proc %d (%s)\n", task->tk_pid,
-		clnt->cl_protname, clnt->cl_vers, task->tk_msg.rpc_proc->p_proc,
-		(RPC_IS_ASYNC(task) ? "async" : "sync"));
+	dprintk("RPC: %5u call_start %s%d proc %d (%s)\n", task->tk_pid,
+			clnt->cl_protname, clnt->cl_vers,
+			task->tk_msg.rpc_proc->p_proc,
+			(RPC_IS_ASYNC(task) ? "async" : "sync"));
 
 	/* Increment call count */
 	task->tk_msg.rpc_proc->p_count++;
@@ -674,7 +677,7 @@
 static void
 call_reserve(struct rpc_task *task)
 {
-	dprintk("RPC: %4d call_reserve\n", task->tk_pid);
+	dprint_status(task);
 
 	if (!rpcauth_uptodatecred(task)) {
 		task->tk_action = call_refresh;
@@ -694,8 +697,7 @@
 {
 	int status = task->tk_status;
 
-	dprintk("RPC: %4d call_reserveresult (status %d)\n",
-				task->tk_pid, task->tk_status);
+	dprint_status(task);
 
 	/*
 	 * After a call to xprt_reserve(), we must have either
@@ -749,8 +751,8 @@
 	struct rpc_xprt *xprt = task->tk_xprt;
 	unsigned int	bufsiz;
 
-	dprintk("RPC: %4d call_allocate (status %d)\n", 
-				task->tk_pid, task->tk_status);
+	dprint_status(task);
+
 	task->tk_action = call_bind;
 	if (req->rq_buffer)
 		return;
@@ -761,7 +763,8 @@
 
 	if (xprt->ops->buf_alloc(task, bufsiz << 1) != NULL)
 		return;
-	printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task); 
+
+	dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid);
 
 	if (RPC_IS_ASYNC(task) || !signalled()) {
 		xprt_release(task);
@@ -798,8 +801,7 @@
 	kxdrproc_t	encode;
 	__be32		*p;
 
-	dprintk("RPC: %4d call_encode (status %d)\n", 
-				task->tk_pid, task->tk_status);
+	dprint_status(task);
 
 	/* Default buffer setup */
 	bufsiz = req->rq_bufsize >> 1;
@@ -845,8 +847,7 @@
 {
 	struct rpc_xprt *xprt = task->tk_xprt;
 
-	dprintk("RPC: %4d call_bind (status %d)\n",
-				task->tk_pid, task->tk_status);
+	dprint_status(task);
 
 	task->tk_action = call_connect;
 	if (!xprt_bound(xprt)) {
@@ -865,8 +866,7 @@
 	int status = -EACCES;
 
 	if (task->tk_status >= 0) {
-		dprintk("RPC: %4d call_bind_status (status %d)\n",
-					task->tk_pid, task->tk_status);
+		dprint_status(task);
 		task->tk_status = 0;
 		task->tk_action = call_connect;
 		return;
@@ -874,24 +874,24 @@
 
 	switch (task->tk_status) {
 	case -EACCES:
-		dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n",
-				task->tk_pid);
+		dprintk("RPC: %5u remote rpcbind: RPC program/version "
+				"unavailable\n", task->tk_pid);
 		rpc_delay(task, 3*HZ);
 		goto retry_timeout;
 	case -ETIMEDOUT:
-		dprintk("RPC: %4d rpcbind request timed out\n",
+		dprintk("RPC: %5u rpcbind request timed out\n",
 				task->tk_pid);
 		goto retry_timeout;
 	case -EPFNOSUPPORT:
-		dprintk("RPC: %4d remote rpcbind service unavailable\n",
+		dprintk("RPC: %5u remote rpcbind service unavailable\n",
 				task->tk_pid);
 		break;
 	case -EPROTONOSUPPORT:
-		dprintk("RPC: %4d remote rpcbind version 2 unavailable\n",
+		dprintk("RPC: %5u remote rpcbind version 2 unavailable\n",
 				task->tk_pid);
 		break;
 	default:
-		dprintk("RPC: %4d unrecognized rpcbind error (%d)\n",
+		dprintk("RPC: %5u unrecognized rpcbind error (%d)\n",
 				task->tk_pid, -task->tk_status);
 		status = -EIO;
 	}
@@ -911,7 +911,7 @@
 {
 	struct rpc_xprt *xprt = task->tk_xprt;
 
-	dprintk("RPC: %4d call_connect xprt %p %s connected\n",
+	dprintk("RPC: %5u call_connect xprt %p %s connected\n",
 			task->tk_pid, xprt,
 			(xprt_connected(xprt) ? "is" : "is not"));
 
@@ -933,8 +933,7 @@
 	struct rpc_clnt *clnt = task->tk_client;
 	int status = task->tk_status;
 
-	dprintk("RPC: %5u call_connect_status (status %d)\n", 
-				task->tk_pid, task->tk_status);
+	dprint_status(task);
 
 	task->tk_status = 0;
 	if (status >= 0) {
@@ -966,8 +965,7 @@
 static void
 call_transmit(struct rpc_task *task)
 {
-	dprintk("RPC: %4d call_transmit (status %d)\n", 
-				task->tk_pid, task->tk_status);
+	dprint_status(task);
 
 	task->tk_action = call_status;
 	if (task->tk_status < 0)
@@ -1028,8 +1026,7 @@
 	if (req->rq_received > 0 && !req->rq_bytes_sent)
 		task->tk_status = req->rq_received;
 
-	dprintk("RPC: %4d call_status (status %d)\n", 
-				task->tk_pid, task->tk_status);
+	dprint_status(task);
 
 	status = task->tk_status;
 	if (status >= 0) {
@@ -1080,11 +1077,11 @@
 	struct rpc_clnt	*clnt = task->tk_client;
 
 	if (xprt_adjust_timeout(task->tk_rqstp) == 0) {
-		dprintk("RPC: %4d call_timeout (minor)\n", task->tk_pid);
+		dprintk("RPC: %5u call_timeout (minor)\n", task->tk_pid);
 		goto retry;
 	}
 
-	dprintk("RPC: %4d call_timeout (major)\n", task->tk_pid);
+	dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid);
 	task->tk_timeouts++;
 
 	if (RPC_IS_SOFT(task)) {
@@ -1118,8 +1115,8 @@
 	kxdrproc_t	decode = task->tk_msg.rpc_proc->p_decode;
 	__be32		*p;
 
-	dprintk("RPC: %4d call_decode (status %d)\n", 
-				task->tk_pid, task->tk_status);
+	dprintk("RPC: %5u call_decode (status %d)\n",
+			task->tk_pid, task->tk_status);
 
 	if (task->tk_flags & RPC_CALL_MAJORSEEN) {
 		printk(KERN_NOTICE "%s: server %s OK\n",
@@ -1133,8 +1130,8 @@
 			clnt->cl_stats->rpcretrans++;
 			goto out_retry;
 		}
-		dprintk("%s: too small RPC reply size (%d bytes)\n",
-			clnt->cl_protname, task->tk_status);
+		dprintk("RPC:       %s: too small RPC reply size (%d bytes)\n",
+				clnt->cl_protname, task->tk_status);
 		task->tk_action = call_timeout;
 		goto out_retry;
 	}
@@ -1166,8 +1163,8 @@
 						      task->tk_msg.rpc_resp);
 		unlock_kernel();
 	}
-	dprintk("RPC: %4d call_decode result %d\n", task->tk_pid,
-					task->tk_status);
+	dprintk("RPC: %5u call_decode result %d\n", task->tk_pid,
+			task->tk_status);
 	return;
 out_retry:
 	req->rq_received = req->rq_private_buf.len = 0;
@@ -1180,7 +1177,7 @@
 static void
 call_refresh(struct rpc_task *task)
 {
-	dprintk("RPC: %4d call_refresh\n", task->tk_pid);
+	dprint_status(task);
 
 	xprt_release(task);	/* Must do to obtain new XID */
 	task->tk_action = call_refreshresult;
@@ -1196,8 +1193,8 @@
 call_refreshresult(struct rpc_task *task)
 {
 	int status = task->tk_status;
-	dprintk("RPC: %4d call_refreshresult (status %d)\n", 
-				task->tk_pid, task->tk_status);
+
+	dprint_status(task);
 
 	task->tk_status = 0;
 	task->tk_action = call_reserve;
@@ -1275,11 +1272,15 @@
 			case RPC_AUTH_ERROR:
 				break;
 			case RPC_MISMATCH:
-				dprintk("%s: RPC call version mismatch!\n", __FUNCTION__);
+				dprintk("RPC: %5u %s: RPC call version "
+						"mismatch!\n",
+						task->tk_pid, __FUNCTION__);
 				error = -EPROTONOSUPPORT;
 				goto out_err;
 			default:
-				dprintk("%s: RPC call rejected, unknown error: %x\n", __FUNCTION__, n);
+				dprintk("RPC: %5u %s: RPC call rejected, "
+						"unknown error: %x\n",
+						task->tk_pid, __FUNCTION__, n);
 				goto out_eio;
 		}
 		if (--len < 0)
@@ -1292,8 +1293,8 @@
 			if (!task->tk_cred_retry)
 				break;
 			task->tk_cred_retry--;
-			dprintk("RPC: %4d call_verify: retry stale creds\n",
-							task->tk_pid);
+			dprintk("RPC: %5u %s: retry stale creds\n",
+					task->tk_pid, __FUNCTION__);
 			rpcauth_invalcred(task);
 			task->tk_action = call_refresh;
 			goto out_retry;
@@ -1303,8 +1304,8 @@
 			if (!task->tk_garb_retry)
 				break;
 			task->tk_garb_retry--;
-			dprintk("RPC: %4d call_verify: retry garbled creds\n",
-							task->tk_pid);
+			dprintk("RPC: %5u %s: retry garbled creds\n",
+					task->tk_pid, __FUNCTION__);
 			task->tk_action = call_bind;
 			goto out_retry;
 		case RPC_AUTH_TOOWEAK:
@@ -1315,8 +1316,8 @@
 			printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n);
 			error = -EIO;
 		}
-		dprintk("RPC: %4d call_verify: call rejected %d\n",
-						task->tk_pid, n);
+		dprintk("RPC: %5u %s: call rejected %d\n",
+				task->tk_pid, __FUNCTION__, n);
 		goto out_err;
 	}
 	if (!(p = rpcauth_checkverf(task, p))) {
@@ -1330,20 +1331,24 @@
 	case RPC_SUCCESS:
 		return p;
 	case RPC_PROG_UNAVAIL:
-		dprintk("RPC: call_verify: program %u is unsupported by server %s\n",
+		dprintk("RPC: %5u %s: program %u is unsupported by server %s\n",
+				task->tk_pid, __FUNCTION__,
 				(unsigned int)task->tk_client->cl_prog,
 				task->tk_client->cl_server);
 		error = -EPFNOSUPPORT;
 		goto out_err;
 	case RPC_PROG_MISMATCH:
-		dprintk("RPC: call_verify: program %u, version %u unsupported by server %s\n",
+		dprintk("RPC: %5u %s: program %u, version %u unsupported by "
+				"server %s\n", task->tk_pid, __FUNCTION__,
 				(unsigned int)task->tk_client->cl_prog,
 				(unsigned int)task->tk_client->cl_vers,
 				task->tk_client->cl_server);
 		error = -EPROTONOSUPPORT;
 		goto out_err;
 	case RPC_PROC_UNAVAIL:
-		dprintk("RPC: call_verify: proc %p unsupported by program %u, version %u on server %s\n",
+		dprintk("RPC: %5u %s: proc %p unsupported by program %u, "
+				"version %u on server %s\n",
+				task->tk_pid, __FUNCTION__,
 				task->tk_msg.rpc_proc,
 				task->tk_client->cl_prog,
 				task->tk_client->cl_vers,
@@ -1351,7 +1356,8 @@
 		error = -EOPNOTSUPP;
 		goto out_err;
 	case RPC_GARBAGE_ARGS:
-		dprintk("RPC: %4d %s: server saw garbage\n", task->tk_pid, __FUNCTION__);
+		dprintk("RPC: %5u %s: server saw garbage\n",
+				task->tk_pid, __FUNCTION__);
 		break;			/* retry */
 	default:
 		printk(KERN_WARNING "call_verify: server accept status: %x\n", n);
@@ -1362,7 +1368,8 @@
 	task->tk_client->cl_stats->rpcgarbage++;
 	if (task->tk_garb_retry) {
 		task->tk_garb_retry--;
-		dprintk("RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid);
+		dprintk("RPC: %5u %s: retrying\n",
+				task->tk_pid, __FUNCTION__);
 		task->tk_action = call_bind;
 out_retry:
 		return ERR_PTR(-EAGAIN);
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 3946ec3..d9f7653 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -62,7 +62,10 @@
 
 static void pmap_map_release(void *data)
 {
-	pmap_map_free(data);
+	struct portmap_args *map = data;
+
+	xprt_put(map->pm_xprt);
+	pmap_map_free(map);
 }
 
 static const struct rpc_call_ops pmap_getport_ops = {
@@ -94,7 +97,7 @@
 	struct rpc_task *child;
 	int status;
 
-	dprintk("RPC: %4d rpc_getport(%s, %u, %u, %d)\n",
+	dprintk("RPC: %5u rpc_getport(%s, %u, %u, %d)\n",
 			task->tk_pid, clnt->cl_server,
 			clnt->cl_prog, clnt->cl_vers, xprt->prot);
 
@@ -133,7 +136,7 @@
 	status = -EIO;
 	child = rpc_run_task(pmap_clnt, RPC_TASK_ASYNC, &pmap_getport_ops, map);
 	if (IS_ERR(child))
-		goto bailout;
+		goto bailout_nofree;
 	rpc_put_task(child);
 
 	task->tk_xprt->stat.bind_count++;
@@ -175,7 +178,7 @@
 	char		hostname[32];
 	int		status;
 
-	dprintk("RPC:      rpc_getport_external(%u.%u.%u.%u, %u, %u, %d)\n",
+	dprintk("RPC:       rpc_getport_external(%u.%u.%u.%u, %u, %u, %d)\n",
 			NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
 
 	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
@@ -218,11 +221,10 @@
 		status = 0;
 	}
 
-	dprintk("RPC: %4d pmap_getport_done(status %d, port %u)\n",
+	dprintk("RPC: %5u pmap_getport_done(status %d, port %u)\n",
 			child->tk_pid, status, map->pm_port);
 
 	pmap_wake_portmap_waiters(xprt, status);
-	xprt_put(xprt);
 }
 
 /**
@@ -255,13 +257,14 @@
 	struct rpc_clnt		*pmap_clnt;
 	int error = 0;
 
-	dprintk("RPC: registering (%u, %u, %d, %u) with portmapper.\n",
+	dprintk("RPC:       registering (%u, %u, %d, %u) with portmapper.\n",
 			prog, vers, prot, port);
 
 	pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1);
 	if (IS_ERR(pmap_clnt)) {
 		error = PTR_ERR(pmap_clnt);
-		dprintk("RPC: couldn't create pmap client. Error = %d\n", error);
+		dprintk("RPC:       couldn't create pmap client. Error = %d\n",
+				error);
 		return error;
 	}
 
@@ -272,7 +275,7 @@
 			"RPC: failed to contact portmap (errno %d).\n",
 			error);
 	}
-	dprintk("RPC: registration status %d/%d\n", error, *okay);
+	dprintk("RPC:       registration status %d/%d\n", error, *okay);
 
 	/* Client deleted automatically because cl_oneshot == 1 */
 	return error;
@@ -303,8 +306,9 @@
  */
 static int xdr_encode_mapping(struct rpc_rqst *req, __be32 *p, struct portmap_args *map)
 {
-	dprintk("RPC: xdr_encode_mapping(%u, %u, %u, %u)\n",
-		map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port);
+	dprintk("RPC:       xdr_encode_mapping(%u, %u, %u, %u)\n",
+			map->pm_prog, map->pm_vers,
+			map->pm_prot, map->pm_port);
 	*p++ = htonl(map->pm_prog);
 	*p++ = htonl(map->pm_vers);
 	*p++ = htonl(map->pm_prot);
@@ -329,7 +333,7 @@
 static struct rpc_procinfo	pmap_procedures[] = {
 [PMAP_SET] = {
 	  .p_proc		= PMAP_SET,
-	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,	
+	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,
 	  .p_decode		= (kxdrproc_t) xdr_decode_bool,
 	  .p_bufsiz		= 4,
 	  .p_count		= 1,
@@ -338,7 +342,7 @@
 	},
 [PMAP_UNSET] = {
 	  .p_proc		= PMAP_UNSET,
-	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,	
+	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,
 	  .p_decode		= (kxdrproc_t) xdr_decode_bool,
 	  .p_bufsiz		= 4,
 	  .p_count		= 1,
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 89273d3..9b9ea50 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -309,7 +309,7 @@
 	}
 }
 
-static struct file_operations rpc_pipe_fops = {
+static const struct file_operations rpc_pipe_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= rpc_pipe_read,
@@ -366,7 +366,7 @@
 	return single_release(inode, file);
 }
 
-static struct file_operations rpc_info_operations = {
+static const struct file_operations rpc_info_operations = {
 	.owner		= THIS_MODULE,
 	.open		= rpc_info_open,
 	.read		= seq_read,
@@ -589,7 +589,7 @@
 {
 	struct inode *inode;
 
-	inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR);
+	inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO);
 	if (!inode)
 		goto out_err;
 	inode->i_ino = iunique(dir->i_sb, 100);
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index fc083f0..6d87320 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -4,7 +4,7 @@
  * Scheduling for synchronous and asynchronous RPC requests.
  *
  * Copyright (C) 1996 Olaf Kirch, <okir@monad.swb.de>
- * 
+ *
  * TCP NFS related read + write fixes
  * (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied@linux.ie>
  */
@@ -74,7 +74,7 @@
 static inline void
 __rpc_disable_timer(struct rpc_task *task)
 {
-	dprintk("RPC: %4d disabling timer\n", task->tk_pid);
+	dprintk("RPC: %5u disabling timer\n", task->tk_pid);
 	task->tk_timeout_fn = NULL;
 	task->tk_timeout = 0;
 }
@@ -93,7 +93,7 @@
 	callback = task->tk_timeout_fn;
 	task->tk_timeout_fn = NULL;
 	if (callback && RPC_IS_QUEUED(task)) {
-		dprintk("RPC: %4d running timer\n", task->tk_pid);
+		dprintk("RPC: %5u running timer\n", task->tk_pid);
 		callback(task);
 	}
 	smp_mb__before_clear_bit();
@@ -110,7 +110,7 @@
 	if (!task->tk_timeout)
 		return;
 
-	dprintk("RPC: %4d setting alarm for %lu ms\n",
+	dprintk("RPC: %5u setting alarm for %lu ms\n",
 			task->tk_pid, task->tk_timeout * 1000 / HZ);
 
 	if (timer)
@@ -132,7 +132,7 @@
 		return;
 	if (test_and_clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate)) {
 		del_singleshot_timer_sync(&task->tk_timer);
-		dprintk("RPC: %4d deleting timer\n", task->tk_pid);
+		dprintk("RPC: %5u deleting timer\n", task->tk_pid);
 	}
 }
 
@@ -179,8 +179,8 @@
 	queue->qlen++;
 	rpc_set_queued(task);
 
-	dprintk("RPC: %4d added to queue %p \"%s\"\n",
-				task->tk_pid, queue, rpc_qname(queue));
+	dprintk("RPC: %5u added to queue %p \"%s\"\n",
+			task->tk_pid, queue, rpc_qname(queue));
 }
 
 /*
@@ -212,8 +212,8 @@
 	else
 		list_del(&task->u.tk_wait.list);
 	queue->qlen--;
-	dprintk("RPC: %4d removed from queue %p \"%s\"\n",
-				task->tk_pid, queue, rpc_qname(queue));
+	dprintk("RPC: %5u removed from queue %p \"%s\"\n",
+			task->tk_pid, queue, rpc_qname(queue));
 }
 
 static inline void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority)
@@ -307,7 +307,7 @@
 /*
  * Make an RPC task runnable.
  *
- * Note: If the task is ASYNC, this must be called with 
+ * Note: If the task is ASYNC, this must be called with
  * the spinlock held to protect the wait queue operation.
  */
 static void rpc_make_runnable(struct rpc_task *task)
@@ -344,8 +344,8 @@
 static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
 			rpc_action action, rpc_action timer)
 {
-	dprintk("RPC: %4d sleep_on(queue \"%s\" time %ld)\n", task->tk_pid,
-				rpc_qname(q), jiffies);
+	dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n",
+			task->tk_pid, rpc_qname(q), jiffies);
 
 	if (!RPC_IS_ASYNC(task) && !RPC_IS_ACTIVATED(task)) {
 		printk(KERN_ERR "RPC: Inactive synchronous task put to sleep!\n");
@@ -381,7 +381,8 @@
  */
 static void __rpc_do_wake_up_task(struct rpc_task *task)
 {
-	dprintk("RPC: %4d __rpc_wake_up_task (now %ld)\n", task->tk_pid, jiffies);
+	dprintk("RPC: %5u __rpc_wake_up_task (now %lu)\n",
+			task->tk_pid, jiffies);
 
 #ifdef RPC_DEBUG
 	BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID);
@@ -397,7 +398,7 @@
 
 	rpc_make_runnable(task);
 
-	dprintk("RPC:      __rpc_wake_up_task done\n");
+	dprintk("RPC:       __rpc_wake_up_task done\n");
 }
 
 /*
@@ -418,7 +419,7 @@
 static void
 __rpc_default_timer(struct rpc_task *task)
 {
-	dprintk("RPC: %d timeout (default timer)\n", task->tk_pid);
+	dprintk("RPC: %5u timeout (default timer)\n", task->tk_pid);
 	task->tk_status = -ETIMEDOUT;
 	rpc_wake_up_task(task);
 }
@@ -502,7 +503,8 @@
 {
 	struct rpc_task	*task = NULL;
 
-	dprintk("RPC:      wake_up_next(%p \"%s\")\n", queue, rpc_qname(queue));
+	dprintk("RPC:       wake_up_next(%p \"%s\")\n",
+			queue, rpc_qname(queue));
 	rcu_read_lock_bh();
 	spin_lock(&queue->lock);
 	if (RPC_IS_PRIORITY(queue))
@@ -625,12 +627,12 @@
 /*
  * This is the RPC `scheduler' (or rather, the finite state machine).
  */
-static int __rpc_execute(struct rpc_task *task)
+static void __rpc_execute(struct rpc_task *task)
 {
 	int		status = 0;
 
-	dprintk("RPC: %4d rpc_execute flgs %x\n",
-				task->tk_pid, task->tk_flags);
+	dprintk("RPC: %5u __rpc_execute flags=0x%x\n",
+			task->tk_pid, task->tk_flags);
 
 	BUG_ON(RPC_IS_QUEUED(task));
 
@@ -646,8 +648,8 @@
 		if (RPC_DO_CALLBACK(task)) {
 			/* Define a callback save pointer */
 			void (*save_callback)(struct rpc_task *);
-	
-			/* 
+
+			/*
 			 * If a callback exists, save it, reset it,
 			 * call it.
 			 * The save is needed to stop from resetting
@@ -679,14 +681,14 @@
 		if (RPC_IS_ASYNC(task)) {
 			/* Careful! we may have raced... */
 			if (RPC_IS_QUEUED(task))
-				return 0;
+				return;
 			if (rpc_test_and_set_running(task))
-				return 0;
+				return;
 			continue;
 		}
 
 		/* sync task: sleep here */
-		dprintk("RPC: %4d sync task going to sleep\n", task->tk_pid);
+		dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid);
 		/* Note: Caller should be using rpc_clnt_sigmask() */
 		status = out_of_line_wait_on_bit(&task->tk_runstate,
 				RPC_TASK_QUEUED, rpc_wait_bit_interruptible,
@@ -698,19 +700,19 @@
 			 * clean up after sleeping on some queue, we don't
 			 * break the loop here, but go around once more.
 			 */
-			dprintk("RPC: %4d got signal\n", task->tk_pid);
+			dprintk("RPC: %5u got signal\n", task->tk_pid);
 			task->tk_flags |= RPC_TASK_KILLED;
 			rpc_exit(task, -ERESTARTSYS);
 			rpc_wake_up_task(task);
 		}
 		rpc_set_running(task);
-		dprintk("RPC: %4d sync task resuming\n", task->tk_pid);
+		dprintk("RPC: %5u sync task resuming\n", task->tk_pid);
 	}
 
-	dprintk("RPC: %4d, return %d, status %d\n", task->tk_pid, status, task->tk_status);
+	dprintk("RPC: %5u return %d, status %d\n", task->tk_pid, status,
+			task->tk_status);
 	/* Release all resources associated with the task */
 	rpc_release_task(task);
-	return status;
 }
 
 /*
@@ -722,12 +724,11 @@
  *	 released. In particular note that tk_release() will have
  *	 been called, so your task memory may have been freed.
  */
-int
-rpc_execute(struct rpc_task *task)
+void rpc_execute(struct rpc_task *task)
 {
 	rpc_set_active(task);
 	rpc_set_running(task);
-	return __rpc_execute(task);
+	__rpc_execute(task);
 }
 
 static void rpc_async_schedule(struct work_struct *work)
@@ -826,7 +827,7 @@
 	/* starting timestamp */
 	task->tk_start = jiffies;
 
-	dprintk("RPC: %4d new task procpid %d\n", task->tk_pid,
+	dprintk("RPC:       new task initialized, procpid %u\n",
 				current->pid);
 }
 
@@ -839,7 +840,7 @@
 static void rpc_free_task(struct rcu_head *rcu)
 {
 	struct rpc_task *task = container_of(rcu, struct rpc_task, u.tk_rcu);
-	dprintk("RPC: %4d freeing task\n", task->tk_pid);
+	dprintk("RPC: %5u freeing task\n", task->tk_pid);
 	mempool_free(task, rpc_task_mempool);
 }
 
@@ -858,7 +859,7 @@
 
 	rpc_init_task(task, clnt, flags, tk_ops, calldata);
 
-	dprintk("RPC: %4d allocated task\n", task->tk_pid);
+	dprintk("RPC:       allocated task %p\n", task);
 	task->tk_flags |= RPC_TASK_DYNAMIC;
 out:
 	return task;
@@ -902,7 +903,7 @@
 #ifdef RPC_DEBUG
 	BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID);
 #endif
-	dprintk("RPC: %4d release task\n", task->tk_pid);
+	dprintk("RPC: %5u release task\n", task->tk_pid);
 
 	/* Remove from global task list */
 	spin_lock(&rpc_sched_lock);
@@ -955,7 +956,7 @@
 	struct rpc_task	*rovr;
 	struct list_head *le;
 
-	dprintk("RPC:      killing all tasks for client %p\n", clnt);
+	dprintk("RPC:       killing all tasks for client %p\n", clnt);
 
 	/*
 	 * Spin lock all_tasks to prevent changes...
@@ -984,7 +985,8 @@
 		rpc_killall_tasks(NULL);
 		flush_workqueue(rpciod_workqueue);
 		if (!list_empty(&all_tasks)) {
-			dprintk("rpciod_killall: waiting for tasks to exit\n");
+			dprintk("RPC:       rpciod_killall: waiting for tasks "
+					"to exit\n");
 			yield();
 		}
 	}
@@ -1004,7 +1006,7 @@
 	int error = 0;
 
 	mutex_lock(&rpciod_mutex);
-	dprintk("rpciod_up: users %d\n", rpciod_users);
+	dprintk("RPC:       rpciod_up: users %u\n", rpciod_users);
 	rpciod_users++;
 	if (rpciod_workqueue)
 		goto out;
@@ -1012,7 +1014,7 @@
 	 * If there's no pid, we should be the first user.
 	 */
 	if (rpciod_users > 1)
-		printk(KERN_WARNING "rpciod_up: no workqueue, %d users??\n", rpciod_users);
+		printk(KERN_WARNING "rpciod_up: no workqueue, %u users??\n", rpciod_users);
 	/*
 	 * Create the rpciod thread and wait for it to start.
 	 */
@@ -1034,7 +1036,7 @@
 rpciod_down(void)
 {
 	mutex_lock(&rpciod_mutex);
-	dprintk("rpciod_down sema %d\n", rpciod_users);
+	dprintk("RPC:       rpciod_down sema %u\n", rpciod_users);
 	if (rpciod_users) {
 		if (--rpciod_users)
 			goto out;
@@ -1042,7 +1044,7 @@
 		printk(KERN_WARNING "rpciod_down: no users??\n");
 
 	if (!rpciod_workqueue) {
-		dprintk("rpciod_down: Nothing to do!\n");
+		dprintk("RPC:       rpciod_down: Nothing to do!\n");
 		goto out;
 	}
 	rpciod_killall();
@@ -1072,7 +1074,7 @@
 		if (RPC_IS_QUEUED(t))
 			rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
 
-		printk("%05d %04d %04x %06d %8p %6d %8p %08ld %8s %8p %8p\n",
+		printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
 			t->tk_pid,
 			(t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
 			t->tk_flags, t->tk_status,
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index bd98124..74ba7d4 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -16,7 +16,6 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/sunrpc/clnt.h>
@@ -66,7 +65,7 @@
 	return single_open(file, rpc_proc_show, PDE(inode)->data);
 }
 
-static struct file_operations rpc_proc_fops = {
+static const struct file_operations rpc_proc_fops = {
 	.owner = THIS_MODULE,
 	.open = rpc_proc_open,
 	.read  = seq_read,
@@ -226,7 +225,7 @@
 	struct proc_dir_entry *ent;
 
 	rpc_proc_init();
-	dprintk("RPC: registering /proc/net/rpc/%s\n", name);
+	dprintk("RPC:       registering /proc/net/rpc/%s\n", name);
 
 	ent = create_proc_entry(name, 0, proc_net_rpc);
 	if (ent) {
@@ -263,7 +262,7 @@
 void
 rpc_proc_init(void)
 {
-	dprintk("RPC: registering /proc/net/rpc\n");
+	dprintk("RPC:       registering /proc/net/rpc\n");
 	if (!proc_net_rpc) {
 		struct proc_dir_entry *ent;
 		ent = proc_mkdir("rpc", proc_net);
@@ -277,7 +276,7 @@
 void
 rpc_proc_exit(void)
 {
-	dprintk("RPC: unregistering /proc/net/rpc\n");
+	dprintk("RPC:       unregistering /proc/net/rpc\n");
 	if (proc_net_rpc) {
 		proc_net_rpc = NULL;
 		remove_proc_entry("net/rpc", NULL);
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index d85fdde..43ecf62 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/uio.h>
 #include <linux/unistd.h>
 #include <linux/init.h>
@@ -137,7 +136,7 @@
 
 extern int register_rpc_pipefs(void);
 extern void unregister_rpc_pipefs(void);
-extern struct cache_detail ip_map_cache;
+extern struct cache_detail ip_map_cache, unix_gid_cache;
 extern int init_socket_xprt(void);
 extern void cleanup_socket_xprt(void);
 
@@ -157,6 +156,7 @@
 	rpc_proc_init();
 #endif
 	cache_register(&ip_map_cache);
+	cache_register(&unix_gid_cache);
 	init_socket_xprt();
 out:
 	return err;
@@ -170,6 +170,8 @@
 	rpc_destroy_mempool();
 	if (cache_unregister(&ip_map_cache))
 		printk(KERN_ERR "sunrpc: failed to unregister ip_map cache\n");
+	if (cache_unregister(&unix_gid_cache))
+	      printk(KERN_ERR "sunrpc: failed to unregister unix_gid cache\n");
 #ifdef RPC_DEBUG
 	rpc_unregister_sysctl();
 #endif
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 4c16112..8353829 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -115,7 +115,7 @@
 static int
 svc_pool_map_init_percpu(struct svc_pool_map *m)
 {
-	unsigned int maxpools = highest_possible_processor_id()+1;
+	unsigned int maxpools = nr_cpu_ids;
 	unsigned int pidx = 0;
 	unsigned int cpu;
 	int err;
@@ -143,7 +143,7 @@
 static int
 svc_pool_map_init_pernode(struct svc_pool_map *m)
 {
-	unsigned int maxpools = highest_possible_node_id()+1;
+	unsigned int maxpools = nr_node_ids;
 	unsigned int pidx = 0;
 	unsigned int node;
 	int err;
@@ -317,7 +317,7 @@
 	for (i = 0; i < serv->sv_nrpools; i++) {
 		struct svc_pool *pool = &serv->sv_pools[i];
 
-		dprintk("initialising pool %u for %s\n",
+		dprintk("svc: initialising pool %u for %s\n",
 				i, serv->sv_name);
 
 		pool->sp_id = i;
@@ -368,7 +368,7 @@
 {
 	struct svc_sock	*svsk;
 
-	dprintk("RPC: svc_destroy(%s, %d)\n",
+	dprintk("svc: svc_destroy(%s, %d)\n",
 				serv->sv_program->pg_name,
 				serv->sv_nrthreads);
 
@@ -386,7 +386,7 @@
 		svsk = list_entry(serv->sv_tempsocks.next,
 				  struct svc_sock,
 				  sk_list);
-		svc_delete_socket(svsk);
+		svc_close_socket(svsk);
 	}
 	if (serv->sv_shutdown)
 		serv->sv_shutdown(serv);
@@ -395,9 +395,9 @@
 		svsk = list_entry(serv->sv_permsocks.next,
 				  struct svc_sock,
 				  sk_list);
-		svc_delete_socket(svsk);
+		svc_close_socket(svsk);
 	}
-	
+
 	cache_clean_deferred(serv);
 
 	/* Unregister service with the portmapper */
@@ -415,7 +415,7 @@
 {
 	int pages;
 	int arghi;
-	
+
 	pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply.
 				       * We assume one is at most one page
 				       */
@@ -514,7 +514,7 @@
 	if (pool != NULL)
 		return pool;
 
- 	return &serv->sv_pools[(*state)++ % serv->sv_nrpools];
+	return &serv->sv_pools[(*state)++ % serv->sv_nrpools];
 }
 
 /*
@@ -530,13 +530,13 @@
 		spin_lock_bh(&pool->sp_lock);
 	} else {
 		/* choose a pool in round-robin fashion */
- 		for (i = 0; i < serv->sv_nrpools; i++) {
- 			pool = &serv->sv_pools[--(*state) % serv->sv_nrpools];
+		for (i = 0; i < serv->sv_nrpools; i++) {
+			pool = &serv->sv_pools[--(*state) % serv->sv_nrpools];
 			spin_lock_bh(&pool->sp_lock);
- 			if (!list_empty(&pool->sp_all_threads))
- 				goto found_pool;
+			if (!list_empty(&pool->sp_all_threads))
+				goto found_pool;
 			spin_unlock_bh(&pool->sp_lock);
- 		}
+		}
 		return NULL;
 	}
 
@@ -551,7 +551,7 @@
 		rqstp = list_entry(pool->sp_all_threads.next, struct svc_rqst, rq_all);
 		list_del_init(&rqstp->rq_all);
 		task = rqstp->rq_task;
-    	}
+	}
 	spin_unlock_bh(&pool->sp_lock);
 
 	return task;
@@ -636,7 +636,7 @@
 
 /*
  * Register an RPC service with the local portmapper.
- * To unregister a service, call this routine with 
+ * To unregister a service, call this routine with
  * proto and port == 0.
  */
 int
@@ -654,7 +654,7 @@
 			if (progp->pg_vers[i] == NULL)
 				continue;
 
-			dprintk("RPC: svc_register(%s, %s, %d, %d)%s\n",
+			dprintk("svc: svc_register(%s, %s, %d, %d)%s\n",
 					progp->pg_name,
 					proto == IPPROTO_UDP?  "udp" : "tcp",
 					port,
@@ -709,7 +709,7 @@
 		goto err_short_len;
 
 	/* setup response xdr_buf.
-	 * Initially it has just one page 
+	 * Initially it has just one page
 	 */
 	rqstp->rq_resused = 1;
 	resv->iov_base = page_address(rqstp->rq_respages[0]);
@@ -811,7 +811,7 @@
 	memset(rqstp->rq_argp, 0, procp->pc_argsize);
 	memset(rqstp->rq_resp, 0, procp->pc_ressize);
 
-	/* un-reserve some of the out-queue now that we have a 
+	/* un-reserve some of the out-queue now that we have a
 	 * better idea of reply size
 	 */
 	if (procp->pc_xdrressize)
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index c7bb5f7..f5c3808 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -2,7 +2,7 @@
  * linux/net/sunrpc/svcauth.c
  *
  * The generic interface for RPC authentication on the server side.
- * 
+ *
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  *
  * CHANGES
@@ -10,7 +10,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
@@ -74,7 +73,7 @@
 	int rv = 0;
 
 	rqstp->rq_authop = NULL;
-	
+
 	if (aops) {
 		rv = aops->release(rqstp);
 		module_put(aops->owner);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 0d1e8fb..9bae409 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -151,7 +151,7 @@
 	char text_addr[20];
 	struct ip_map *im = container_of(h, struct ip_map, h);
 	__be32 addr = im->m_addr.s_addr;
-	
+
 	snprintf(text_addr, 20, "%u.%u.%u.%u",
 		 ntohl(addr) >> 24 & 0xff,
 		 ntohl(addr) >> 16 & 0xff,
@@ -198,7 +198,7 @@
 
 	if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
 		return -EINVAL;
-	
+
 	expiry = get_expiry(&mesg);
 	if (expiry ==0)
 		return -EINVAL;
@@ -248,7 +248,7 @@
 	/* class addr domain */
 	addr = im->m_addr;
 
-	if (test_bit(CACHE_VALID, &h->flags) && 
+	if (test_bit(CACHE_VALID, &h->flags) &&
 	    !test_bit(CACHE_NEGATIVE, &h->flags))
 		dom = im->m_client->h.name;
 
@@ -262,7 +262,7 @@
 		   );
 	return 0;
 }
-	
+
 
 struct cache_detail ip_map_cache = {
 	.owner		= THIS_MODULE,
@@ -343,7 +343,7 @@
 int auth_unix_forget_old(struct auth_domain *dom)
 {
 	struct unix_domain *udom;
-	
+
 	if (dom->flavour != &svcauth_unix)
 		return -EINVAL;
 	udom = container_of(dom, struct unix_domain, h);
@@ -418,9 +418,218 @@
 	cache_put(&ipm->h, &ip_map_cache);
 }
 
+/****************************************************************************
+ * auth.unix.gid cache
+ * simple cache to map a UID to a list of GIDs
+ * because AUTH_UNIX aka AUTH_SYS has a max of 16
+ */
+#define	GID_HASHBITS	8
+#define	GID_HASHMAX	(1<<GID_HASHBITS)
+#define	GID_HASHMASK	(GID_HASHMAX - 1)
+
+struct unix_gid {
+	struct cache_head	h;
+	uid_t			uid;
+	struct group_info	*gi;
+};
+static struct cache_head	*gid_table[GID_HASHMAX];
+
+static void unix_gid_put(struct kref *kref)
+{
+	struct cache_head *item = container_of(kref, struct cache_head, ref);
+	struct unix_gid *ug = container_of(item, struct unix_gid, h);
+	if (test_bit(CACHE_VALID, &item->flags) &&
+	    !test_bit(CACHE_NEGATIVE, &item->flags))
+		put_group_info(ug->gi);
+	kfree(ug);
+}
+
+static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
+{
+	struct unix_gid *orig = container_of(corig, struct unix_gid, h);
+	struct unix_gid *new = container_of(cnew, struct unix_gid, h);
+	return orig->uid == new->uid;
+}
+static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem)
+{
+	struct unix_gid *new = container_of(cnew, struct unix_gid, h);
+	struct unix_gid *item = container_of(citem, struct unix_gid, h);
+	new->uid = item->uid;
+}
+static void unix_gid_update(struct cache_head *cnew, struct cache_head *citem)
+{
+	struct unix_gid *new = container_of(cnew, struct unix_gid, h);
+	struct unix_gid *item = container_of(citem, struct unix_gid, h);
+
+	get_group_info(item->gi);
+	new->gi = item->gi;
+}
+static struct cache_head *unix_gid_alloc(void)
+{
+	struct unix_gid *g = kmalloc(sizeof(*g), GFP_KERNEL);
+	if (g)
+		return &g->h;
+	else
+		return NULL;
+}
+
+static void unix_gid_request(struct cache_detail *cd,
+			     struct cache_head *h,
+			     char **bpp, int *blen)
+{
+	char tuid[20];
+	struct unix_gid *ug = container_of(h, struct unix_gid, h);
+
+	snprintf(tuid, 20, "%u", ug->uid);
+	qword_add(bpp, blen, tuid);
+	(*bpp)[-1] = '\n';
+}
+
+static struct unix_gid *unix_gid_lookup(uid_t uid);
+extern struct cache_detail unix_gid_cache;
+
+static int unix_gid_parse(struct cache_detail *cd,
+			char *mesg, int mlen)
+{
+	/* uid expiry Ngid gid0 gid1 ... gidN-1 */
+	int uid;
+	int gids;
+	int rv;
+	int i;
+	int err;
+	time_t expiry;
+	struct unix_gid ug, *ugp;
+
+	if (mlen <= 0 || mesg[mlen-1] != '\n')
+		return -EINVAL;
+	mesg[mlen-1] = 0;
+
+	rv = get_int(&mesg, &uid);
+	if (rv)
+		return -EINVAL;
+	ug.uid = uid;
+
+	expiry = get_expiry(&mesg);
+	if (expiry == 0)
+		return -EINVAL;
+
+	rv = get_int(&mesg, &gids);
+	if (rv || gids < 0 || gids > 8192)
+		return -EINVAL;
+
+	ug.gi = groups_alloc(gids);
+	if (!ug.gi)
+		return -ENOMEM;
+
+	for (i = 0 ; i < gids ; i++) {
+		int gid;
+		rv = get_int(&mesg, &gid);
+		err = -EINVAL;
+		if (rv)
+			goto out;
+		GROUP_AT(ug.gi, i) = gid;
+	}
+
+	ugp = unix_gid_lookup(uid);
+	if (ugp) {
+		struct cache_head *ch;
+		ug.h.flags = 0;
+		ug.h.expiry_time = expiry;
+		ch = sunrpc_cache_update(&unix_gid_cache,
+					 &ug.h, &ugp->h,
+					 hash_long(uid, GID_HASHBITS));
+		if (!ch)
+			err = -ENOMEM;
+		else {
+			err = 0;
+			cache_put(ch, &unix_gid_cache);
+		}
+	} else
+		err = -ENOMEM;
+ out:
+	if (ug.gi)
+		put_group_info(ug.gi);
+	return err;
+}
+
+static int unix_gid_show(struct seq_file *m,
+			 struct cache_detail *cd,
+			 struct cache_head *h)
+{
+	struct unix_gid *ug;
+	int i;
+	int glen;
+
+	if (h == NULL) {
+		seq_puts(m, "#uid cnt: gids...\n");
+		return 0;
+	}
+	ug = container_of(h, struct unix_gid, h);
+	if (test_bit(CACHE_VALID, &h->flags) &&
+	    !test_bit(CACHE_NEGATIVE, &h->flags))
+		glen = ug->gi->ngroups;
+	else
+		glen = 0;
+
+	seq_printf(m, "%d %d:", ug->uid, glen);
+	for (i = 0; i < glen; i++)
+		seq_printf(m, " %d", GROUP_AT(ug->gi, i));
+	seq_printf(m, "\n");
+	return 0;
+}
+
+struct cache_detail unix_gid_cache = {
+	.owner		= THIS_MODULE,
+	.hash_size	= GID_HASHMAX,
+	.hash_table	= gid_table,
+	.name		= "auth.unix.gid",
+	.cache_put	= unix_gid_put,
+	.cache_request	= unix_gid_request,
+	.cache_parse	= unix_gid_parse,
+	.cache_show	= unix_gid_show,
+	.match		= unix_gid_match,
+	.init		= unix_gid_init,
+	.update		= unix_gid_update,
+	.alloc		= unix_gid_alloc,
+};
+
+static struct unix_gid *unix_gid_lookup(uid_t uid)
+{
+	struct unix_gid ug;
+	struct cache_head *ch;
+
+	ug.uid = uid;
+	ch = sunrpc_cache_lookup(&unix_gid_cache, &ug.h,
+				 hash_long(uid, GID_HASHBITS));
+	if (ch)
+		return container_of(ch, struct unix_gid, h);
+	else
+		return NULL;
+}
+
+static int unix_gid_find(uid_t uid, struct group_info **gip,
+			 struct svc_rqst *rqstp)
+{
+	struct unix_gid *ug = unix_gid_lookup(uid);
+	if (!ug)
+		return -EAGAIN;
+	switch (cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle)) {
+	case -ENOENT:
+		*gip = NULL;
+		return 0;
+	case 0:
+		*gip = ug->gi;
+		get_group_info(*gip);
+		return 0;
+	default:
+		return -EAGAIN;
+	}
+}
+
 static int
 svcauth_unix_set_client(struct svc_rqst *rqstp)
 {
+	struct sockaddr_in *sin = svc_addr_in(rqstp);
 	struct ip_map *ipm;
 
 	rqstp->rq_client = NULL;
@@ -430,7 +639,7 @@
 	ipm = ip_map_cached_get(rqstp);
 	if (ipm == NULL)
 		ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
-				    rqstp->rq_addr.sin_addr);
+				    sin->sin_addr);
 
 	if (ipm == NULL)
 		return SVC_DENIED;
@@ -465,7 +674,7 @@
 	if (argv->iov_len < 3*4)
 		return SVC_GARBAGE;
 
-	if (svc_getu32(argv) != 0) { 
+	if (svc_getu32(argv) != 0) {
 		dprintk("svc: bad null cred\n");
 		*authp = rpc_autherr_badcred;
 		return SVC_DENIED;
@@ -542,12 +751,19 @@
 	slen = svc_getnl(argv);			/* gids length */
 	if (slen > 16 || (len -= (slen + 2)*4) < 0)
 		goto badcred;
-	cred->cr_group_info = groups_alloc(slen);
-	if (cred->cr_group_info == NULL)
+	if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp)
+	    == -EAGAIN)
 		return SVC_DROP;
-	for (i = 0; i < slen; i++)
-		GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
-
+	if (cred->cr_group_info == NULL) {
+		cred->cr_group_info = groups_alloc(slen);
+		if (cred->cr_group_info == NULL)
+			return SVC_DROP;
+		for (i = 0; i < slen; i++)
+			GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
+	} else {
+		for (i = 0; i < slen ; i++)
+			svc_getnl(argv);
+	}
 	if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
 		*authp = rpc_autherr_badverf;
 		return SVC_DENIED;
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index ff1f8bf..63ae947 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -36,11 +36,13 @@
 #include <net/sock.h>
 #include <net/checksum.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
 #include <linux/sunrpc/types.h>
+#include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/stats.h>
@@ -58,10 +60,16 @@
  *	providing that certain rules are followed:
  *
  *	SK_CONN, SK_DATA, can be set or cleared at any time.
- *		after a set, svc_sock_enqueue must be called.	
+ *		after a set, svc_sock_enqueue must be called.
  *		after a clear, the socket must be read/accepted
  *		 if this succeeds, it must be set again.
  *	SK_CLOSE can set at any time. It is never cleared.
+ *      sk_inuse contains a bias of '1' until SK_DEAD is set.
+ *             so when sk_inuse hits zero, we know the socket is dead
+ *             and no-one is using it.
+ *      SK_DEAD can only be set while SK_BUSY is held which ensures
+ *             no other thread will be using the socket or will try to
+ *	       set SK_DEAD.
  *
  */
 
@@ -69,7 +77,8 @@
 
 
 static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
-					 int *errp, int pmap_reg);
+					 int *errp, int flags);
+static void		svc_delete_socket(struct svc_sock *svsk);
 static void		svc_udp_data_ready(struct sock *, int);
 static int		svc_udp_recvfrom(struct svc_rqst *);
 static int		svc_udp_sendto(struct svc_rqst *);
@@ -114,6 +123,41 @@
 }
 #endif
 
+static char *__svc_print_addr(struct sockaddr *addr, char *buf, size_t len)
+{
+	switch (addr->sa_family) {
+	case AF_INET:
+		snprintf(buf, len, "%u.%u.%u.%u, port=%u",
+			NIPQUAD(((struct sockaddr_in *) addr)->sin_addr),
+			htons(((struct sockaddr_in *) addr)->sin_port));
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x, port=%u",
+			NIP6(((struct sockaddr_in6 *) addr)->sin6_addr),
+			htons(((struct sockaddr_in6 *) addr)->sin6_port));
+		break;
+#endif
+	default:
+		snprintf(buf, len, "unknown address type: %d", addr->sa_family);
+		break;
+	}
+	return buf;
+}
+
+/**
+ * svc_print_addr - Format rq_addr field for printing
+ * @rqstp: svc_rqst struct containing address to print
+ * @buf: target buffer for formatted address
+ * @len: length of target buffer
+ *
+ */
+char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len)
+{
+	return __svc_print_addr(svc_addr(rqstp), buf, len);
+}
+EXPORT_SYMBOL_GPL(svc_print_addr);
+
 /*
  * Queue up an idle server thread.  Must have pool->sp_lock held.
  * Note: this is really a stack rather than a queue, so that we only
@@ -245,7 +289,7 @@
 			svsk->sk_sk, rqstp);
 		svc_thread_dequeue(pool, rqstp);
 		if (rqstp->rq_sock)
-			printk(KERN_ERR 
+			printk(KERN_ERR
 				"svc_sock_enqueue: server %p, rq_sock=%p!\n",
 				rqstp, rqstp->rq_sock);
 		rqstp->rq_sock = svsk;
@@ -329,8 +373,9 @@
 static inline void
 svc_sock_put(struct svc_sock *svsk)
 {
-	if (atomic_dec_and_test(&svsk->sk_inuse) &&
-			test_bit(SK_DEAD, &svsk->sk_flags)) {
+	if (atomic_dec_and_test(&svsk->sk_inuse)) {
+		BUG_ON(! test_bit(SK_DEAD, &svsk->sk_flags));
+
 		dprintk("svc: releasing dead socket\n");
 		if (svsk->sk_sock->file)
 			sockfd_put(svsk->sk_sock);
@@ -402,6 +447,43 @@
 	}
 }
 
+union svc_pktinfo_u {
+	struct in_pktinfo pkti;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	struct in6_pktinfo pkti6;
+#endif
+};
+
+static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
+{
+	switch (rqstp->rq_sock->sk_sk->sk_family) {
+	case AF_INET: {
+			struct in_pktinfo *pki = CMSG_DATA(cmh);
+
+			cmh->cmsg_level = SOL_IP;
+			cmh->cmsg_type = IP_PKTINFO;
+			pki->ipi_ifindex = 0;
+			pki->ipi_spec_dst.s_addr = rqstp->rq_daddr.addr.s_addr;
+			cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
+		}
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6: {
+			struct in6_pktinfo *pki = CMSG_DATA(cmh);
+
+			cmh->cmsg_level = SOL_IPV6;
+			cmh->cmsg_type = IPV6_PKTINFO;
+			pki->ipi6_ifindex = 0;
+			ipv6_addr_copy(&pki->ipi6_addr,
+					&rqstp->rq_daddr.addr6);
+			cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
+		}
+		break;
+#endif
+	}
+	return;
+}
+
 /*
  * Generic sendto routine
  */
@@ -411,9 +493,8 @@
 	struct svc_sock	*svsk = rqstp->rq_sock;
 	struct socket	*sock = svsk->sk_sock;
 	int		slen;
-	char 		buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
+	char 		buffer[CMSG_SPACE(sizeof(union svc_pktinfo_u))];
 	struct cmsghdr *cmh = (struct cmsghdr *)buffer;
-	struct in_pktinfo *pki = (struct in_pktinfo *)CMSG_DATA(cmh);
 	int		len = 0;
 	int		result;
 	int		size;
@@ -421,25 +502,20 @@
 	size_t		base = xdr->page_base;
 	unsigned int	pglen = xdr->page_len;
 	unsigned int	flags = MSG_MORE;
+	char		buf[RPC_MAX_ADDRBUFLEN];
 
 	slen = xdr->len;
 
 	if (rqstp->rq_prot == IPPROTO_UDP) {
-		/* set the source and destination */
-		struct msghdr	msg;
-		msg.msg_name    = &rqstp->rq_addr;
-		msg.msg_namelen = sizeof(rqstp->rq_addr);
-		msg.msg_iov     = NULL;
-		msg.msg_iovlen  = 0;
-		msg.msg_flags	= MSG_MORE;
+		struct msghdr msg = {
+			.msg_name	= &rqstp->rq_addr,
+			.msg_namelen	= rqstp->rq_addrlen,
+			.msg_control	= cmh,
+			.msg_controllen	= sizeof(buffer),
+			.msg_flags	= MSG_MORE,
+		};
 
-		msg.msg_control = cmh;
-		msg.msg_controllen = sizeof(buffer);
-		cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
-		cmh->cmsg_level = SOL_IP;
-		cmh->cmsg_type = IP_PKTINFO;
-		pki->ipi_ifindex = 0;
-		pki->ipi_spec_dst.s_addr = rqstp->rq_daddr;
+		svc_set_cmsg_data(rqstp, cmh);
 
 		if (sock_sendmsg(sock, &msg, 0) < 0)
 			goto out;
@@ -476,16 +552,16 @@
 	if (xdr->tail[0].iov_len) {
 		result = kernel_sendpage(sock, rqstp->rq_respages[0],
 					     ((unsigned long)xdr->tail[0].iov_base)
-					        & (PAGE_SIZE-1),
+						& (PAGE_SIZE-1),
 					     xdr->tail[0].iov_len, 0);
 
 		if (result > 0)
 			len += result;
 	}
 out:
-	dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %x)\n",
-			rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len, xdr->len, len,
-		rqstp->rq_addr.sin_addr.s_addr);
+	dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %s)\n",
+		rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len,
+		xdr->len, len, svc_print_addr(rqstp, buf, sizeof(buf)));
 
 	return len;
 }
@@ -520,7 +596,7 @@
 
 	if (!serv)
 		return 0;
-	spin_lock(&serv->sv_lock);
+	spin_lock_bh(&serv->sv_lock);
 	list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) {
 		int onelen = one_sock_name(buf+len, svsk);
 		if (toclose && strcmp(toclose, buf+len) == 0)
@@ -528,12 +604,12 @@
 		else
 			len += onelen;
 	}
-	spin_unlock(&serv->sv_lock);
+	spin_unlock_bh(&serv->sv_lock);
 	if (closesk)
 		/* Should unregister with portmap, but you cannot
 		 * unregister just one protocol...
 		 */
-		svc_delete_socket(closesk);
+		svc_close_socket(closesk);
 	else if (toclose)
 		return -ENOENT;
 	return len;
@@ -560,31 +636,22 @@
 static int
 svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
 {
-	struct msghdr	msg;
-	struct socket	*sock;
-	int		len, alen;
+	struct svc_sock *svsk = rqstp->rq_sock;
+	struct msghdr msg = {
+		.msg_flags	= MSG_DONTWAIT,
+	};
+	int len;
 
-	rqstp->rq_addrlen = sizeof(rqstp->rq_addr);
-	sock = rqstp->rq_sock->sk_sock;
-
-	msg.msg_name    = &rqstp->rq_addr;
-	msg.msg_namelen = sizeof(rqstp->rq_addr);
-	msg.msg_control = NULL;
-	msg.msg_controllen = 0;
-
-	msg.msg_flags	= MSG_DONTWAIT;
-
-	len = kernel_recvmsg(sock, &msg, iov, nr, buflen, MSG_DONTWAIT);
+	len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
+				msg.msg_flags);
 
 	/* sock_recvmsg doesn't fill in the name/namelen, so we must..
-	 * possibly we should cache this in the svc_sock structure
-	 * at accept time. FIXME
 	 */
-	alen = sizeof(rqstp->rq_addr);
-	kernel_getpeername(sock, (struct sockaddr *)&rqstp->rq_addr, &alen);
+	memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen);
+	rqstp->rq_addrlen = svsk->sk_remotelen;
 
 	dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
-		rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
+		svsk, iov[0].iov_base, iov[0].iov_len, len);
 
 	return len;
 }
@@ -654,6 +721,47 @@
 	}
 }
 
+static void svc_udp_get_sender_address(struct svc_rqst *rqstp,
+					struct sk_buff *skb)
+{
+	switch (rqstp->rq_sock->sk_sk->sk_family) {
+	case AF_INET: {
+		/* this seems to come from net/ipv4/udp.c:udp_recvmsg */
+			struct sockaddr_in *sin = svc_addr_in(rqstp);
+
+			sin->sin_family = AF_INET;
+			sin->sin_port = skb->h.uh->source;
+			sin->sin_addr.s_addr = skb->nh.iph->saddr;
+			rqstp->rq_addrlen = sizeof(struct sockaddr_in);
+			/* Remember which interface received this request */
+			rqstp->rq_daddr.addr.s_addr = skb->nh.iph->daddr;
+		}
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6: {
+		/* this is derived from net/ipv6/udp.c:udpv6_recvmesg */
+			struct sockaddr_in6 *sin6 = svc_addr_in6(rqstp);
+
+			sin6->sin6_family = AF_INET6;
+			sin6->sin6_port = skb->h.uh->source;
+			sin6->sin6_flowinfo = 0;
+			sin6->sin6_scope_id = 0;
+			if (ipv6_addr_type(&sin6->sin6_addr) &
+							IPV6_ADDR_LINKLOCAL)
+				sin6->sin6_scope_id = IP6CB(skb)->iif;
+			ipv6_addr_copy(&sin6->sin6_addr,
+							&skb->nh.ipv6h->saddr);
+			rqstp->rq_addrlen = sizeof(struct sockaddr_in);
+			/* Remember which interface received this request */
+			ipv6_addr_copy(&rqstp->rq_daddr.addr6,
+							&skb->nh.ipv6h->saddr);
+		}
+		break;
+#endif
+	}
+	return;
+}
+
 /*
  * Receive a datagram from a UDP socket.
  */
@@ -683,6 +791,11 @@
 		return svc_deferred_recv(rqstp);
 	}
 
+	if (test_bit(SK_CLOSE, &svsk->sk_flags)) {
+		svc_delete_socket(svsk);
+		return 0;
+	}
+
 	clear_bit(SK_DATA, &svsk->sk_flags);
 	while ((skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) {
 		if (err == -EAGAIN) {
@@ -698,7 +811,7 @@
 		tv.tv_sec = xtime.tv_sec;
 		tv.tv_usec = xtime.tv_nsec / NSEC_PER_USEC;
 		skb_set_timestamp(skb, &tv);
-		/* Don't enable netstamp, sunrpc doesn't 
+		/* Don't enable netstamp, sunrpc doesn't
 		   need that much accuracy */
 	}
 	skb_get_timestamp(skb, &svsk->sk_sk->sk_stamp);
@@ -712,13 +825,9 @@
 	len  = skb->len - sizeof(struct udphdr);
 	rqstp->rq_arg.len = len;
 
-	rqstp->rq_prot        = IPPROTO_UDP;
+	rqstp->rq_prot = IPPROTO_UDP;
 
-	/* Get sender address */
-	rqstp->rq_addr.sin_family = AF_INET;
-	rqstp->rq_addr.sin_port = skb->h.uh->source;
-	rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr;
-	rqstp->rq_daddr = skb->nh.iph->daddr;
+	svc_udp_get_sender_address(rqstp, skb);
 
 	if (skb_is_nonlinear(skb)) {
 		/* we have to copy */
@@ -730,7 +839,7 @@
 			return 0;
 		}
 		local_bh_enable();
-		skb_free_datagram(svsk->sk_sk, skb); 
+		skb_free_datagram(svsk->sk_sk, skb);
 	} else {
 		/* we can use it in-place */
 		rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr);
@@ -781,7 +890,7 @@
 	svsk->sk_sendto = svc_udp_sendto;
 
 	/* initialise setting must have enough space to
-	 * receive and respond to one request.  
+	 * receive and respond to one request.
 	 * svc_udp_recvfrom will re-adjust if necessary
 	 */
 	svc_sock_setbufsize(svsk->sk_sock,
@@ -862,18 +971,36 @@
 		wake_up_interruptible(sk->sk_sleep);
 }
 
+static inline int svc_port_is_privileged(struct sockaddr *sin)
+{
+	switch (sin->sa_family) {
+	case AF_INET:
+		return ntohs(((struct sockaddr_in *)sin)->sin_port)
+			< PROT_SOCK;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		return ntohs(((struct sockaddr_in6 *)sin)->sin6_port)
+			< PROT_SOCK;
+#endif
+	default:
+		return 0;
+	}
+}
+
 /*
  * Accept a TCP connection
  */
 static void
 svc_tcp_accept(struct svc_sock *svsk)
 {
-	struct sockaddr_in sin;
+	struct sockaddr_storage addr;
+	struct sockaddr	*sin = (struct sockaddr *) &addr;
 	struct svc_serv	*serv = svsk->sk_server;
 	struct socket	*sock = svsk->sk_sock;
 	struct socket	*newsock;
 	struct svc_sock	*newsvsk;
 	int		err, slen;
+	char		buf[RPC_MAX_ADDRBUFLEN];
 
 	dprintk("svc: tcp_accept %p sock %p\n", svsk, sock);
 	if (!sock)
@@ -894,8 +1021,7 @@
 	set_bit(SK_CONN, &svsk->sk_flags);
 	svc_sock_enqueue(svsk);
 
-	slen = sizeof(sin);
-	err = kernel_getpeername(newsock, (struct sockaddr *) &sin, &slen);
+	err = kernel_getpeername(newsock, sin, &slen);
 	if (err < 0) {
 		if (net_ratelimit())
 			printk(KERN_WARNING "%s: peername failed (err %d)!\n",
@@ -904,27 +1030,30 @@
 	}
 
 	/* Ideally, we would want to reject connections from unauthorized
-	 * hosts here, but when we get encription, the IP of the host won't
-	 * tell us anything. For now just warn about unpriv connections.
+	 * hosts here, but when we get encryption, the IP of the host won't
+	 * tell us anything.  For now just warn about unpriv connections.
 	 */
-	if (ntohs(sin.sin_port) >= 1024) {
+	if (!svc_port_is_privileged(sin)) {
 		dprintk(KERN_WARNING
-			"%s: connect from unprivileged port: %u.%u.%u.%u:%d\n",
-			serv->sv_name, 
-			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+			"%s: connect from unprivileged port: %s\n",
+			serv->sv_name,
+			__svc_print_addr(sin, buf, sizeof(buf)));
 	}
-
-	dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
-			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+	dprintk("%s: connect from %s\n", serv->sv_name,
+		__svc_print_addr(sin, buf, sizeof(buf)));
 
 	/* make sure that a write doesn't block forever when
 	 * low on memory
 	 */
 	newsock->sk->sk_sndtimeo = HZ*30;
 
-	if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
+	if (!(newsvsk = svc_setup_socket(serv, newsock, &err,
+				 (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY))))
 		goto failed;
+	memcpy(&newsvsk->sk_remote, sin, slen);
+	newsvsk->sk_remotelen = slen;
 
+	svc_sock_received(newsvsk);
 
 	/* make sure that we don't have too many active connections.
 	 * If we have, something must be dropped.
@@ -947,11 +1076,9 @@
 					"sockets, consider increasing the "
 					"number of nfsd threads\n",
 						   serv->sv_name);
-				printk(KERN_NOTICE "%s: last TCP connect from "
-					"%u.%u.%u.%u:%d\n",
-					serv->sv_name,
-					NIPQUAD(sin.sin_addr.s_addr),
-					ntohs(sin.sin_port));
+				printk(KERN_NOTICE
+				       "%s: last TCP connect from %s\n",
+				       serv->sv_name, buf);
 			}
 			/*
 			 * Always select the oldest socket. It's not fair,
@@ -1025,7 +1152,7 @@
 		 * on the number of threads which will access the socket.
 		 *
 		 * rcvbuf just needs to be able to hold a few requests.
-		 * Normally they will be removed from the queue 
+		 * Normally they will be removed from the queue
 		 * as soon a a complete request arrives.
 		 */
 		svc_sock_setbufsize(svsk->sk_sock,
@@ -1050,7 +1177,7 @@
 
 		if (len < want) {
 			dprintk("svc: short recvfrom while reading record length (%d of %lu)\n",
-			        len, want);
+				len, want);
 			svc_sock_received(svsk);
 			return -EAGAIN; /* record header not complete */
 		}
@@ -1176,7 +1303,8 @@
 		       rqstp->rq_sock->sk_server->sv_name,
 		       (sent<0)?"got error":"sent only",
 		       sent, xbufp->len);
-		svc_delete_socket(rqstp->rq_sock);
+		set_bit(SK_CLOSE, &rqstp->rq_sock->sk_flags);
+		svc_sock_enqueue(rqstp->rq_sock);
 		sent = -EAGAIN;
 	}
 	return sent;
@@ -1207,7 +1335,7 @@
 		tp->nonagle = 1;        /* disable Nagle's algorithm */
 
 		/* initialise setting must have enough space to
-		 * receive and respond to one request.  
+		 * receive and respond to one request.
 		 * svc_tcp_recvfrom will re-adjust if necessary
 		 */
 		svc_sock_setbufsize(svsk->sk_sock,
@@ -1216,7 +1344,7 @@
 
 		set_bit(SK_CHNGBUF, &svsk->sk_flags);
 		set_bit(SK_DATA, &svsk->sk_flags);
-		if (sk->sk_state != TCP_ESTABLISHED) 
+		if (sk->sk_state != TCP_ESTABLISHED)
 			set_bit(SK_CLOSE, &svsk->sk_flags);
 	}
 }
@@ -1232,7 +1360,7 @@
 
 	spin_lock_bh(&serv->sv_lock);
 	list_for_each(le, &serv->sv_permsocks) {
-		struct svc_sock *svsk = 
+		struct svc_sock *svsk =
 			list_entry(le, struct svc_sock, sk_list);
 		set_bit(SK_CHNGBUF, &svsk->sk_flags);
 	}
@@ -1252,7 +1380,7 @@
 int
 svc_recv(struct svc_rqst *rqstp, long timeout)
 {
-	struct svc_sock		*svsk =NULL;
+	struct svc_sock		*svsk = NULL;
 	struct svc_serv		*serv = rqstp->rq_server;
 	struct svc_pool		*pool = rqstp->rq_pool;
 	int			len, i;
@@ -1264,11 +1392,11 @@
 		rqstp, timeout);
 
 	if (rqstp->rq_sock)
-		printk(KERN_ERR 
+		printk(KERN_ERR
 			"svc_recv: service %p, socket not NULL!\n",
 			 rqstp);
 	if (waitqueue_active(&rqstp->rq_wait))
-		printk(KERN_ERR 
+		printk(KERN_ERR
 			"svc_recv: service %p, wait queue active!\n",
 			 rqstp);
 
@@ -1349,7 +1477,7 @@
 	svsk->sk_lastrecv = get_seconds();
 	clear_bit(SK_OLD, &svsk->sk_flags);
 
-	rqstp->rq_secure  = ntohs(rqstp->rq_addr.sin_port) < 1024;
+	rqstp->rq_secure = svc_port_is_privileged(svc_addr(rqstp));
 	rqstp->rq_chandle.defer = svc_defer;
 
 	if (serv->sv_stats)
@@ -1357,7 +1485,7 @@
 	return len;
 }
 
-/* 
+/*
  * Drop request
  */
 void
@@ -1462,12 +1590,14 @@
  * Initialize socket for RPC use and create svc_sock struct
  * XXX: May want to setsockopt SO_SNDBUF and SO_RCVBUF.
  */
-static struct svc_sock *
-svc_setup_socket(struct svc_serv *serv, struct socket *sock,
-					int *errp, int pmap_register)
+static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
+						struct socket *sock,
+						int *errp, int flags)
 {
 	struct svc_sock	*svsk;
 	struct sock	*inet;
+	int		pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
+	int		is_temporary = flags & SVC_SOCK_TEMPORARY;
 
 	dprintk("svc: svc_setup_socket %p\n", sock);
 	if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
@@ -1495,7 +1625,7 @@
 	svsk->sk_odata = inet->sk_data_ready;
 	svsk->sk_owspace = inet->sk_write_space;
 	svsk->sk_server = serv;
-	atomic_set(&svsk->sk_inuse, 0);
+	atomic_set(&svsk->sk_inuse, 1);
 	svsk->sk_lastrecv = get_seconds();
 	spin_lock_init(&svsk->sk_defer_lock);
 	INIT_LIST_HEAD(&svsk->sk_deferred);
@@ -1509,7 +1639,7 @@
 		svc_tcp_init(svsk);
 
 	spin_lock_bh(&serv->sv_lock);
-	if (!pmap_register) {
+	if (is_temporary) {
 		set_bit(SK_TEMP, &svsk->sk_flags);
 		list_add(&svsk->sk_list, &serv->sv_tempsocks);
 		serv->sv_tmpcnt++;
@@ -1529,8 +1659,6 @@
 	dprintk("svc: svc_setup_socket created %p (inet %p)\n",
 				svsk, svsk->sk_sk);
 
-	clear_bit(SK_BUSY, &svsk->sk_flags);
-	svc_sock_enqueue(svsk);
 	return svsk;
 }
 
@@ -1553,9 +1681,11 @@
 	else if (so->state > SS_UNCONNECTED)
 		err = -EISCONN;
 	else {
-		svsk = svc_setup_socket(serv, so, &err, 1);
-		if (svsk)
+		svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS);
+		if (svsk) {
+			svc_sock_received(svsk);
 			err = 0;
+		}
 	}
 	if (err) {
 		sockfd_put(so);
@@ -1569,18 +1699,18 @@
 /*
  * Create socket for RPC service.
  */
-static int
-svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
+static int svc_create_socket(struct svc_serv *serv, int protocol,
+				struct sockaddr *sin, int len, int flags)
 {
 	struct svc_sock	*svsk;
 	struct socket	*sock;
 	int		error;
 	int		type;
+	char		buf[RPC_MAX_ADDRBUFLEN];
 
-	dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n",
-				serv->sv_program->pg_name, protocol,
-				NIPQUAD(sin->sin_addr.s_addr),
-				ntohs(sin->sin_port));
+	dprintk("svc: svc_create_socket(%s, %d, %s)\n",
+			serv->sv_program->pg_name, protocol,
+			__svc_print_addr(sin, buf, sizeof(buf)));
 
 	if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
 		printk(KERN_WARNING "svc: only UDP and TCP "
@@ -1589,15 +1719,15 @@
 	}
 	type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
 
-	if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
+	error = sock_create_kern(sin->sa_family, type, protocol, &sock);
+	if (error < 0)
 		return error;
 
 	svc_reclassify_socket(sock);
 
 	if (type == SOCK_STREAM)
-		sock->sk->sk_reuse = 1; /* allow address reuse */
-	error = kernel_bind(sock, (struct sockaddr *) sin,
-					sizeof(*sin));
+		sock->sk->sk_reuse = 1;		/* allow address reuse */
+	error = kernel_bind(sock, sin, len);
 	if (error < 0)
 		goto bummer;
 
@@ -1606,8 +1736,10 @@
 			goto bummer;
 	}
 
-	if ((svsk = svc_setup_socket(serv, sock, &error, 1)) != NULL)
-		return 0;
+	if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) {
+		svc_sock_received(svsk);
+		return ntohs(inet_sk(svsk->sk_sk)->sport);
+	}
 
 bummer:
 	dprintk("svc: svc_create_socket error = %d\n", -error);
@@ -1618,7 +1750,7 @@
 /*
  * Remove a dead socket
  */
-void
+static void
 svc_delete_socket(struct svc_sock *svsk)
 {
 	struct svc_serv	*serv;
@@ -1637,43 +1769,60 @@
 
 	if (!test_and_set_bit(SK_DETACHED, &svsk->sk_flags))
 		list_del_init(&svsk->sk_list);
-    	/*
+	/*
 	 * We used to delete the svc_sock from whichever list
 	 * it's sk_ready node was on, but we don't actually
 	 * need to.  This is because the only time we're called
 	 * while still attached to a queue, the queue itself
 	 * is about to be destroyed (in svc_destroy).
 	 */
-	if (!test_and_set_bit(SK_DEAD, &svsk->sk_flags))
+	if (!test_and_set_bit(SK_DEAD, &svsk->sk_flags)) {
+		BUG_ON(atomic_read(&svsk->sk_inuse)<2);
+		atomic_dec(&svsk->sk_inuse);
 		if (test_bit(SK_TEMP, &svsk->sk_flags))
 			serv->sv_tmpcnt--;
+	}
 
-	/* This atomic_inc should be needed - svc_delete_socket
-	 * should have the semantic of dropping a reference.
-	 * But it doesn't yet....
-	 */
-	atomic_inc(&svsk->sk_inuse);
 	spin_unlock_bh(&serv->sv_lock);
+}
+
+void svc_close_socket(struct svc_sock *svsk)
+{
+	set_bit(SK_CLOSE, &svsk->sk_flags);
+	if (test_and_set_bit(SK_BUSY, &svsk->sk_flags))
+		/* someone else will have to effect the close */
+		return;
+
+	atomic_inc(&svsk->sk_inuse);
+	svc_delete_socket(svsk);
+	clear_bit(SK_BUSY, &svsk->sk_flags);
 	svc_sock_put(svsk);
 }
 
-/*
- * Make a socket for nfsd and lockd
+/**
+ * svc_makesock - Make a socket for nfsd and lockd
+ * @serv: RPC server structure
+ * @protocol: transport protocol to use
+ * @port: port to use
+ * @flags: requested socket characteristics
+ *
  */
-int
-svc_makesock(struct svc_serv *serv, int protocol, unsigned short port)
+int svc_makesock(struct svc_serv *serv, int protocol, unsigned short port,
+			int flags)
 {
-	struct sockaddr_in	sin;
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+		.sin_addr.s_addr	= INADDR_ANY,
+		.sin_port		= htons(port),
+	};
 
 	dprintk("svc: creating socket proto = %d\n", protocol);
-	sin.sin_family      = AF_INET;
-	sin.sin_addr.s_addr = INADDR_ANY;
-	sin.sin_port        = htons(port);
-	return svc_create_socket(serv, protocol, &sin);
+	return svc_create_socket(serv, protocol, (struct sockaddr *) &sin,
+							sizeof(sin), flags);
 }
 
 /*
- * Handle defer and revisit of requests 
+ * Handle defer and revisit of requests
  */
 
 static void svc_revisit(struct cache_deferred_req *dreq, int too_many)
@@ -1718,7 +1867,8 @@
 
 		dr->handle.owner = rqstp->rq_server;
 		dr->prot = rqstp->rq_prot;
-		dr->addr = rqstp->rq_addr;
+		memcpy(&dr->addr, &rqstp->rq_addr, rqstp->rq_addrlen);
+		dr->addrlen = rqstp->rq_addrlen;
 		dr->daddr = rqstp->rq_daddr;
 		dr->argslen = rqstp->rq_arg.len >> 2;
 		memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2);
@@ -1742,7 +1892,8 @@
 	rqstp->rq_arg.page_len = 0;
 	rqstp->rq_arg.len = dr->argslen<<2;
 	rqstp->rq_prot        = dr->prot;
-	rqstp->rq_addr        = dr->addr;
+	memcpy(&rqstp->rq_addr, &dr->addr, dr->addrlen);
+	rqstp->rq_addrlen     = dr->addrlen;
 	rqstp->rq_daddr       = dr->daddr;
 	rqstp->rq_respages    = rqstp->rq_pages;
 	return dr->argslen<<2;
@@ -1752,7 +1903,7 @@
 static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk)
 {
 	struct svc_deferred_req *dr = NULL;
-	
+
 	if (!test_bit(SK_DEFERRED, &svsk->sk_flags))
 		return NULL;
 	spin_lock_bh(&svsk->sk_defer_lock);
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index 82b2752..738db32 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -35,14 +35,8 @@
 void
 rpc_register_sysctl(void)
 {
-	if (!sunrpc_table_header) {
-		sunrpc_table_header = register_sysctl_table(sunrpc_table, 1);
-#ifdef CONFIG_PROC_FS
-		if (sunrpc_table[0].de)
-			sunrpc_table[0].de->owner = THIS_MODULE;
-#endif
-	}
-			
+	if (!sunrpc_table_header)
+		sunrpc_table_header = register_sysctl_table(sunrpc_table);
 }
 
 void
@@ -126,7 +120,7 @@
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dodebug
-	}, 
+	},
 	{
 		.ctl_name	= CTL_NFSDEBUG,
 		.procname	= "nfs_debug",
@@ -134,7 +128,7 @@
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dodebug
-	}, 
+	},
 	{
 		.ctl_name	= CTL_NFSDDEBUG,
 		.procname	= "nfsd_debug",
@@ -142,7 +136,7 @@
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dodebug
-	}, 
+	},
 	{
 		.ctl_name	= CTL_NLMDEBUG,
 		.procname	= "nlm_debug",
@@ -150,7 +144,7 @@
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dodebug
-	}, 
+	},
 	{ .ctl_name = 0 }
 };
 
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index a0af250..6a59180 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -302,7 +302,7 @@
  * @buf: xdr_buf
  * @len: bytes to remove from buf->head[0]
  *
- * Shrinks XDR buffer's header kvec buf->head[0] by 
+ * Shrinks XDR buffer's header kvec buf->head[0] by
  * 'len' bytes. The extra data is not lost, but is instead
  * moved into the inlined pages and/or the tail.
  */
@@ -375,7 +375,7 @@
  * @buf: xdr_buf
  * @len: bytes to remove from buf->pages
  *
- * Shrinks XDR buffer's page array buf->pages by 
+ * Shrinks XDR buffer's page array buf->pages by
  * 'len' bytes. The extra data is not lost, but is instead
  * moved into the tail.
  */
@@ -1024,7 +1024,7 @@
 
 int
 xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len,
-                int (*actor)(struct scatterlist *, void *), void *data)
+		int (*actor)(struct scatterlist *, void *), void *data)
 {
 	int i, ret = 0;
 	unsigned page_len, thislen, page_offset;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 7a3999f..ee6ffa0 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -108,7 +108,7 @@
 	return 1;
 
 out_sleep:
-	dprintk("RPC: %4d failed to lock transport %p\n",
+	dprintk("RPC: %5u failed to lock transport %p\n",
 			task->tk_pid, xprt);
 	task->tk_timeout = 0;
 	task->tk_status = -EAGAIN;
@@ -158,7 +158,7 @@
 	}
 	xprt_clear_locked(xprt);
 out_sleep:
-	dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt);
+	dprintk("RPC: %5u failed to lock transport %p\n", task->tk_pid, xprt);
 	task->tk_timeout = 0;
 	task->tk_status = -EAGAIN;
 	if (req && req->rq_ntrans)
@@ -281,7 +281,7 @@
 
 	if (req->rq_cong)
 		return 1;
-	dprintk("RPC: %4d xprt_cwnd_limited cong = %ld cwnd = %ld\n",
+	dprintk("RPC: %5u xprt_cwnd_limited cong = %lu cwnd = %lu\n",
 			task->tk_pid, xprt->cong, xprt->cwnd);
 	if (RPCXPRT_CONGESTED(xprt))
 		return 0;
@@ -340,7 +340,7 @@
 		if (cwnd < RPC_CWNDSCALE)
 			cwnd = RPC_CWNDSCALE;
 	}
-	dprintk("RPC:      cong %ld, cwnd was %ld, now %ld\n",
+	dprintk("RPC:       cong %ld, cwnd was %ld, now %ld\n",
 			xprt->cong, xprt->cwnd, cwnd);
 	xprt->cwnd = cwnd;
 	__xprt_put_cong(xprt, req);
@@ -387,8 +387,8 @@
 
 	spin_lock_bh(&xprt->transport_lock);
 	if (xprt->snd_task) {
-		dprintk("RPC:      write space: waking waiting task on xprt %p\n",
-				xprt);
+		dprintk("RPC:       write space: waking waiting task on "
+				"xprt %p\n", xprt);
 		rpc_wake_up_task(xprt->snd_task);
 	}
 	spin_unlock_bh(&xprt->transport_lock);
@@ -410,7 +410,7 @@
 /*
  * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout
  * @task: task whose timeout is to be set
- * 
+ *
  * Set a request's retransmit timeout using the RTT estimator.
  */
 void xprt_set_retrans_timeout_rtt(struct rpc_task *task)
@@ -494,7 +494,7 @@
  */
 void xprt_disconnect(struct rpc_xprt *xprt)
 {
-	dprintk("RPC:      disconnected transport %p\n", xprt);
+	dprintk("RPC:       disconnected transport %p\n", xprt);
 	spin_lock_bh(&xprt->transport_lock);
 	xprt_clear_connected(xprt);
 	xprt_wake_pending_tasks(xprt, -ENOTCONN);
@@ -530,7 +530,7 @@
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 
-	dprintk("RPC: %4d xprt_connect xprt %p %s connected\n", task->tk_pid,
+	dprintk("RPC: %5u xprt_connect xprt %p %s connected\n", task->tk_pid,
 			xprt, (xprt_connected(xprt) ? "is" : "is not"));
 
 	if (!xprt_bound(xprt)) {
@@ -560,7 +560,7 @@
 	if (task->tk_status >= 0) {
 		xprt->stat.connect_count++;
 		xprt->stat.connect_time += (long)jiffies - xprt->stat.connect_start;
-		dprintk("RPC: %4d xprt_connect_status: connection established\n",
+		dprintk("RPC: %5u xprt_connect_status: connection established\n",
 				task->tk_pid);
 		return;
 	}
@@ -568,20 +568,22 @@
 	switch (task->tk_status) {
 	case -ECONNREFUSED:
 	case -ECONNRESET:
-		dprintk("RPC: %4d xprt_connect_status: server %s refused connection\n",
-				task->tk_pid, task->tk_client->cl_server);
+		dprintk("RPC: %5u xprt_connect_status: server %s refused "
+				"connection\n", task->tk_pid,
+				task->tk_client->cl_server);
 		break;
 	case -ENOTCONN:
-		dprintk("RPC: %4d xprt_connect_status: connection broken\n",
+		dprintk("RPC: %5u xprt_connect_status: connection broken\n",
 				task->tk_pid);
 		break;
 	case -ETIMEDOUT:
-		dprintk("RPC: %4d xprt_connect_status: connect attempt timed out\n",
-				task->tk_pid);
+		dprintk("RPC: %5u xprt_connect_status: connect attempt timed "
+				"out\n", task->tk_pid);
 		break;
 	default:
-		dprintk("RPC: %4d xprt_connect_status: error %d connecting to server %s\n",
-				task->tk_pid, -task->tk_status, task->tk_client->cl_server);
+		dprintk("RPC: %5u xprt_connect_status: error %d connecting to "
+				"server %s\n", task->tk_pid, -task->tk_status,
+				task->tk_client->cl_server);
 		xprt_release_write(xprt, task);
 		task->tk_status = -EIO;
 	}
@@ -602,6 +604,9 @@
 		if (entry->rq_xid == xid)
 			return entry;
 	}
+
+	dprintk("RPC:       xprt_lookup_rqst did not find xid %08x\n",
+			ntohl(xid));
 	xprt->stat.bad_xids++;
 	return NULL;
 }
@@ -654,7 +659,7 @@
 	struct rpc_rqst *req = task->tk_rqstp;
 	struct rpc_xprt *xprt = req->rq_xprt;
 
-	dprintk("RPC: %4d xprt_timer\n", task->tk_pid);
+	dprintk("RPC: %5u xprt_timer\n", task->tk_pid);
 
 	spin_lock(&xprt->transport_lock);
 	if (!req->rq_received) {
@@ -678,7 +683,7 @@
 	struct rpc_xprt	*xprt = req->rq_xprt;
 	int err = 0;
 
-	dprintk("RPC: %4d xprt_prepare_transmit\n", task->tk_pid);
+	dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid);
 
 	spin_lock_bh(&xprt->transport_lock);
 	if (req->rq_received && !req->rq_bytes_sent) {
@@ -716,7 +721,7 @@
 	struct rpc_xprt	*xprt = req->rq_xprt;
 	int status;
 
-	dprintk("RPC: %4d xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
+	dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
 
 	if (!req->rq_received) {
 		if (list_empty(&req->rq_list)) {
@@ -730,13 +735,23 @@
 			xprt_reset_majortimeo(req);
 			/* Turn off autodisconnect */
 			del_singleshot_timer_sync(&xprt->timer);
+		} else {
+			/* If all request bytes have been sent,
+			 * then we must be retransmitting this one */
+			if (!req->rq_bytes_sent) {
+				if (task->tk_client->cl_discrtry) {
+					xprt_disconnect(xprt);
+					task->tk_status = -ENOTCONN;
+					return;
+				}
+			}
 		}
 	} else if (!req->rq_bytes_sent)
 		return;
 
 	status = xprt->ops->send_request(task);
 	if (status == 0) {
-		dprintk("RPC: %4d xmit complete\n", task->tk_pid);
+		dprintk("RPC: %5u xmit complete\n", task->tk_pid);
 		spin_lock_bh(&xprt->transport_lock);
 
 		xprt->ops->set_retrans_timeout(task);
@@ -777,7 +792,7 @@
 		xprt_request_init(task, xprt);
 		return;
 	}
-	dprintk("RPC:      waiting for request slot\n");
+	dprintk("RPC:       waiting for request slot\n");
 	task->tk_status = -EAGAIN;
 	task->tk_timeout = 0;
 	rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
@@ -822,7 +837,7 @@
 	req->rq_xid     = xprt_alloc_xid(xprt);
 	req->rq_release_snd_buf = NULL;
 	xprt_reset_majortimeo(req);
-	dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid,
+	dprintk("RPC: %5u reserved req %p xid %08x\n", task->tk_pid,
 			req, ntohl(req->rq_xid));
 }
 
@@ -856,7 +871,7 @@
 		req->rq_release_snd_buf(req);
 	memset(req, 0, sizeof(*req));	/* mark unused */
 
-	dprintk("RPC: %4d release request %p\n", task->tk_pid, req);
+	dprintk("RPC: %5u release request %p\n", task->tk_pid, req);
 
 	spin_lock(&xprt->reserve_lock);
 	list_add(&req->rq_list, &xprt->free);
@@ -873,7 +888,7 @@
  */
 void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
 {
-	to->to_initval   = 
+	to->to_initval   =
 	to->to_increment = incr;
 	to->to_maxval    = to->to_initval + (incr * retr);
 	to->to_retries   = retr;
@@ -906,7 +921,7 @@
 		return ERR_PTR(-EIO);
 	}
 	if (IS_ERR(xprt)) {
-		dprintk("RPC:      xprt_create_transport: failed, %ld\n",
+		dprintk("RPC:       xprt_create_transport: failed, %ld\n",
 				-PTR_ERR(xprt));
 		return xprt;
 	}
@@ -936,7 +951,7 @@
 
 	xprt_init_xid(xprt);
 
-	dprintk("RPC:      created transport %p with %u slots\n", xprt,
+	dprintk("RPC:       created transport %p with %u slots\n", xprt,
 			xprt->max_reqs);
 
 	return xprt;
@@ -951,7 +966,7 @@
 {
 	struct rpc_xprt *xprt = container_of(kref, struct rpc_xprt, kref);
 
-	dprintk("RPC:      destroying transport %p\n", xprt);
+	dprintk("RPC:       destroying transport %p\n", xprt);
 	xprt->shutdown = 1;
 	del_timer_sync(&xprt->timer);
 
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 49cabff..a5a3202 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -18,7 +18,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/capability.h>
-#include <linux/sched.h>
 #include <linux/pagemap.h>
 #include <linux/errno.h>
 #include <linux/socket.h>
@@ -192,7 +191,7 @@
 	u8 *buf = (u8 *) packet;
 	int j;
 
-	dprintk("RPC:      %s\n", msg);
+	dprintk("RPC:       %s\n", msg);
 	for (j = 0; j < count && j < 128; j += 4) {
 		if (!(j & 31)) {
 			if (j)
@@ -418,7 +417,7 @@
 	struct rpc_xprt *xprt = req->rq_xprt;
 	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
 
-	dprintk("RPC: %4d xmit incomplete (%u left of %u)\n",
+	dprintk("RPC: %5u xmit incomplete (%u left of %u)\n",
 			task->tk_pid, req->rq_slen - req->rq_bytes_sent,
 			req->rq_slen);
 
@@ -467,7 +466,7 @@
 			      xprt->addrlen, xdr,
 			      req->rq_bytes_sent);
 
-	dprintk("RPC:      xs_udp_send_request(%u) = %d\n",
+	dprintk("RPC:       xs_udp_send_request(%u) = %d\n",
 			xdr->len - req->rq_bytes_sent, status);
 
 	if (likely(status >= (int) req->rq_slen))
@@ -488,7 +487,7 @@
 		xs_nospace(task);
 		break;
 	default:
-		dprintk("RPC:      sendmsg returned unrecognized error %d\n",
+		dprintk("RPC:       sendmsg returned unrecognized error %d\n",
 			-status);
 		break;
 	}
@@ -539,7 +538,7 @@
 		status = xs_sendpages(transport->sock,
 					NULL, 0, xdr, req->rq_bytes_sent);
 
-		dprintk("RPC:      xs_tcp_send_request(%u) = %d\n",
+		dprintk("RPC:       xs_tcp_send_request(%u) = %d\n",
 				xdr->len - req->rq_bytes_sent, status);
 
 		if (unlikely(status < 0))
@@ -570,7 +569,7 @@
 		status = -ENOTCONN;
 		break;
 	default:
-		dprintk("RPC:      sendmsg returned unrecognized error %d\n",
+		dprintk("RPC:       sendmsg returned unrecognized error %d\n",
 			-status);
 		xprt_disconnect(xprt);
 		break;
@@ -622,7 +621,7 @@
 	if (!sk)
 		goto clear_close_wait;
 
-	dprintk("RPC:      xs_close xprt %p\n", xprt);
+	dprintk("RPC:       xs_close xprt %p\n", xprt);
 
 	write_lock_bh(&sk->sk_callback_lock);
 	transport->inet = NULL;
@@ -652,7 +651,7 @@
 {
 	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
 
-	dprintk("RPC:      xs_destroy xprt %p\n", xprt);
+	dprintk("RPC:       xs_destroy xprt %p\n", xprt);
 
 	cancel_delayed_work(&transport->connect_worker);
 	flush_scheduled_work();
@@ -686,7 +685,7 @@
 	__be32 *xp;
 
 	read_lock(&sk->sk_callback_lock);
-	dprintk("RPC:      xs_udp_data_ready...\n");
+	dprintk("RPC:       xs_udp_data_ready...\n");
 	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
 
@@ -698,7 +697,7 @@
 
 	repsize = skb->len - sizeof(struct udphdr);
 	if (repsize < 4) {
-		dprintk("RPC:      impossible RPC reply size %d!\n", repsize);
+		dprintk("RPC:       impossible RPC reply size %d!\n", repsize);
 		goto dropit;
 	}
 
@@ -762,11 +761,11 @@
 
 	/* Sanity check of the record length */
 	if (unlikely(transport->tcp_reclen < 4)) {
-		dprintk("RPC:      invalid TCP record fragment length\n");
+		dprintk("RPC:       invalid TCP record fragment length\n");
 		xprt_disconnect(xprt);
 		return;
 	}
-	dprintk("RPC:      reading TCP record fragment of length %d\n",
+	dprintk("RPC:       reading TCP record fragment of length %d\n",
 			transport->tcp_reclen);
 }
 
@@ -789,7 +788,7 @@
 	char *p;
 
 	len = sizeof(transport->tcp_xid) - transport->tcp_offset;
-	dprintk("RPC:      reading XID (%Zu bytes)\n", len);
+	dprintk("RPC:       reading XID (%Zu bytes)\n", len);
 	p = ((char *) &transport->tcp_xid) + transport->tcp_offset;
 	used = xdr_skb_read_bits(desc, p, len);
 	transport->tcp_offset += used;
@@ -798,7 +797,7 @@
 	transport->tcp_flags &= ~TCP_RCV_COPY_XID;
 	transport->tcp_flags |= TCP_RCV_COPY_DATA;
 	transport->tcp_copied = 4;
-	dprintk("RPC:      reading reply for XID %08x\n",
+	dprintk("RPC:       reading reply for XID %08x\n",
 			ntohl(transport->tcp_xid));
 	xs_tcp_check_fraghdr(transport);
 }
@@ -816,7 +815,7 @@
 	req = xprt_lookup_rqst(xprt, transport->tcp_xid);
 	if (!req) {
 		transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
-		dprintk("RPC:      XID %08x request not found!\n",
+		dprintk("RPC:       XID %08x request not found!\n",
 				ntohl(transport->tcp_xid));
 		spin_unlock(&xprt->transport_lock);
 		return;
@@ -853,19 +852,20 @@
 		 * be discarded.
 		 */
 		transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
-		dprintk("RPC:      XID %08x truncated request\n",
+		dprintk("RPC:       XID %08x truncated request\n",
 				ntohl(transport->tcp_xid));
-		dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
-				xprt, transport->tcp_copied, transport->tcp_offset,
-					transport->tcp_reclen);
+		dprintk("RPC:       xprt = %p, tcp_copied = %lu, "
+				"tcp_offset = %u, tcp_reclen = %u\n",
+				xprt, transport->tcp_copied,
+				transport->tcp_offset, transport->tcp_reclen);
 		goto out;
 	}
 
-	dprintk("RPC:      XID %08x read %Zd bytes\n",
+	dprintk("RPC:       XID %08x read %Zd bytes\n",
 			ntohl(transport->tcp_xid), r);
-	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
-			xprt, transport->tcp_copied, transport->tcp_offset,
-				transport->tcp_reclen);
+	dprintk("RPC:       xprt = %p, tcp_copied = %lu, tcp_offset = %u, "
+			"tcp_reclen = %u\n", xprt, transport->tcp_copied,
+			transport->tcp_offset, transport->tcp_reclen);
 
 	if (transport->tcp_copied == req->rq_private_buf.buflen)
 		transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
@@ -891,7 +891,7 @@
 	desc->count -= len;
 	desc->offset += len;
 	transport->tcp_offset += len;
-	dprintk("RPC:      discarded %Zu bytes\n", len);
+	dprintk("RPC:       discarded %Zu bytes\n", len);
 	xs_tcp_check_fraghdr(transport);
 }
 
@@ -905,7 +905,7 @@
 		.count	= len,
 	};
 
-	dprintk("RPC:      xs_tcp_data_recv started\n");
+	dprintk("RPC:       xs_tcp_data_recv started\n");
 	do {
 		/* Read in a new fragment marker if necessary */
 		/* Can we ever really expect to get completely empty fragments? */
@@ -926,7 +926,7 @@
 		/* Skip over any trailing bytes on short reads */
 		xs_tcp_read_discard(transport, &desc);
 	} while (desc.count);
-	dprintk("RPC:      xs_tcp_data_recv done\n");
+	dprintk("RPC:       xs_tcp_data_recv done\n");
 	return len - desc.count;
 }
 
@@ -941,8 +941,9 @@
 	struct rpc_xprt *xprt;
 	read_descriptor_t rd_desc;
 
+	dprintk("RPC:       xs_tcp_data_ready...\n");
+
 	read_lock(&sk->sk_callback_lock);
-	dprintk("RPC:      xs_tcp_data_ready...\n");
 	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
 	if (xprt->shutdown)
@@ -968,11 +969,11 @@
 	read_lock(&sk->sk_callback_lock);
 	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
-	dprintk("RPC:      xs_tcp_state_change client %p...\n", xprt);
-	dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
-				sk->sk_state, xprt_connected(xprt),
-				sock_flag(sk, SOCK_DEAD),
-				sock_flag(sk, SOCK_ZAPPED));
+	dprintk("RPC:       xs_tcp_state_change client %p...\n", xprt);
+	dprintk("RPC:       state %x conn %d dead %d zapped %d\n",
+			sk->sk_state, xprt_connected(xprt),
+			sock_flag(sk, SOCK_DEAD),
+			sock_flag(sk, SOCK_ZAPPED));
 
 	switch (sk->sk_state) {
 	case TCP_ESTABLISHED:
@@ -1140,7 +1141,7 @@
 {
 	struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr;
 
-	dprintk("RPC:      setting port for xprt %p to %u\n", xprt, port);
+	dprintk("RPC:       setting port for xprt %p to %u\n", xprt, port);
 
 	sap->sin_port = htons(port);
 }
@@ -1159,7 +1160,7 @@
 						sizeof(myaddr));
 		if (err == 0) {
 			transport->port = port;
-			dprintk("RPC:      xs_bindresvport bound to port %u\n",
+			dprintk("RPC:       xs_bindresvport bound to port %u\n",
 					port);
 			return 0;
 		}
@@ -1169,7 +1170,7 @@
 			port--;
 	} while (err == -EADDRINUSE && port != transport->port);
 
-	dprintk("RPC:      can't bind to reserved port (%d).\n", -err);
+	dprintk("RPC:       can't bind to reserved port (%d).\n", -err);
 	return err;
 }
 
@@ -1223,7 +1224,7 @@
 	xs_close(xprt);
 
 	if ((err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
-		dprintk("RPC:      can't create UDP transport socket (%d).\n", -err);
+		dprintk("RPC:       can't create UDP transport socket (%d).\n", -err);
 		goto out;
 	}
 	xs_reclassify_socket(sock);
@@ -1233,7 +1234,7 @@
 		goto out;
 	}
 
-	dprintk("RPC:      worker connecting xprt %p to address: %s\n",
+	dprintk("RPC:       worker connecting xprt %p to address: %s\n",
 			xprt, xprt->address_strings[RPC_DISPLAY_ALL]);
 
 	if (!transport->inet) {
@@ -1275,7 +1276,7 @@
 	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
 	struct sockaddr any;
 
-	dprintk("RPC:      disconnecting xprt %p to reuse port\n", xprt);
+	dprintk("RPC:       disconnecting xprt %p to reuse port\n", xprt);
 
 	/*
 	 * Disconnect the transport socket by doing a connect operation
@@ -1285,7 +1286,7 @@
 	any.sa_family = AF_UNSPEC;
 	result = kernel_connect(transport->sock, &any, sizeof(any), 0);
 	if (result)
-		dprintk("RPC:      AF_UNSPEC connect return code %d\n",
+		dprintk("RPC:       AF_UNSPEC connect return code %d\n",
 				result);
 }
 
@@ -1309,7 +1310,8 @@
 	if (!sock) {
 		/* start from scratch */
 		if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
-			dprintk("RPC:      can't create TCP transport socket (%d).\n", -err);
+			dprintk("RPC:       can't create TCP transport "
+					"socket (%d).\n", -err);
 			goto out;
 		}
 		xs_reclassify_socket(sock);
@@ -1322,7 +1324,7 @@
 		/* "close" the socket, preserving the local port */
 		xs_tcp_reuse_connection(xprt);
 
-	dprintk("RPC:      worker connecting xprt %p to address: %s\n",
+	dprintk("RPC:       worker connecting xprt %p to address: %s\n",
 			xprt, xprt->address_strings[RPC_DISPLAY_ALL]);
 
 	if (!transport->inet) {
@@ -1359,8 +1361,9 @@
 	xprt->stat.connect_start = jiffies;
 	status = kernel_connect(sock, (struct sockaddr *) &xprt->addr,
 			xprt->addrlen, O_NONBLOCK);
-	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
-			xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
+	dprintk("RPC:       %p connect status %d connected %d sock state %d\n",
+			xprt, -status, xprt_connected(xprt),
+			sock->sk->sk_state);
 	if (status < 0) {
 		switch (status) {
 			case -EINPROGRESS:
@@ -1404,7 +1407,8 @@
 		return;
 
 	if (transport->sock != NULL) {
-		dprintk("RPC:      xs_connect delayed xprt %p for %lu seconds\n",
+		dprintk("RPC:       xs_connect delayed xprt %p for %lu "
+				"seconds\n",
 				xprt, xprt->reestablish_timeout / HZ);
 		schedule_delayed_work(&transport->connect_worker,
 					xprt->reestablish_timeout);
@@ -1412,7 +1416,7 @@
 		if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
 			xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
 	} else {
-		dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
+		dprintk("RPC:       xs_connect scheduled xprt %p\n", xprt);
 		schedule_delayed_work(&transport->connect_worker, 0);
 
 		/* flush_scheduled_work can sleep... */
@@ -1507,13 +1511,14 @@
 	struct sock_xprt *new;
 
 	if (addrlen > sizeof(xprt->addr)) {
-		dprintk("RPC:      xs_setup_xprt: address too large\n");
+		dprintk("RPC:       xs_setup_xprt: address too large\n");
 		return ERR_PTR(-EBADF);
 	}
 
 	new = kzalloc(sizeof(*new), GFP_KERNEL);
 	if (new == NULL) {
-		dprintk("RPC:      xs_setup_xprt: couldn't allocate rpc_xprt\n");
+		dprintk("RPC:       xs_setup_xprt: couldn't allocate "
+				"rpc_xprt\n");
 		return ERR_PTR(-ENOMEM);
 	}
 	xprt = &new->xprt;
@@ -1522,7 +1527,8 @@
 	xprt->slot = kcalloc(xprt->max_reqs, sizeof(struct rpc_rqst), GFP_KERNEL);
 	if (xprt->slot == NULL) {
 		kfree(xprt);
-		dprintk("RPC:      xs_setup_xprt: couldn't allocate slot table\n");
+		dprintk("RPC:       xs_setup_xprt: couldn't allocate slot "
+				"table\n");
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -1572,7 +1578,7 @@
 		xprt_set_timeout(&xprt->timeout, 5, 5 * HZ);
 
 	xs_format_peer_addresses(xprt);
-	dprintk("RPC:      set up transport to address %s\n",
+	dprintk("RPC:       set up transport to address %s\n",
 			xprt->address_strings[RPC_DISPLAY_ALL]);
 
 	return xprt;
@@ -1616,7 +1622,7 @@
 		xprt_set_timeout(&xprt->timeout, 2, 60 * HZ);
 
 	xs_format_peer_addresses(xprt);
-	dprintk("RPC:      set up transport to address %s\n",
+	dprintk("RPC:       set up transport to address %s\n",
 			xprt->address_strings[RPC_DISPLAY_ALL]);
 
 	return xprt;
@@ -1629,13 +1635,8 @@
 int init_socket_xprt(void)
 {
 #ifdef RPC_DEBUG
-	if (!sunrpc_table_header) {
-		sunrpc_table_header = register_sysctl_table(sunrpc_table, 1);
-#ifdef CONFIG_PROC_FS
-		if (sunrpc_table[0].de)
-			sunrpc_table[0].de->owner = THIS_MODULE;
-#endif
-	}
+	if (!sunrpc_table_header)
+		sunrpc_table_header = register_sysctl_table(sunrpc_table);
 #endif
 
 	return 0;
diff --git a/net/tipc/addr.c b/net/tipc/addr.c
index 0be25e1..e5207a1 100644
--- a/net/tipc/addr.c
+++ b/net/tipc/addr.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/addr.c: TIPC address utility routines
- *     
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2004-2005, Wind River Systems
  * All rights reserved.
@@ -48,10 +48,10 @@
 
 /**
  * tipc_addr_domain_valid - validates a network domain address
- * 
- * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>, 
+ *
+ * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>,
  * where Z, C, and N are non-zero and do not exceed the configured limits.
- * 
+ *
  * Returns 1 if domain address is valid, otherwise 0
  */
 
@@ -80,10 +80,10 @@
 
 /**
  * tipc_addr_node_valid - validates a proposed network address for this node
- * 
- * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed 
+ *
+ * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed
  * the configured limits.
- * 
+ *
  * Returns 1 if address can be used, otherwise 0
  */
 
diff --git a/net/tipc/addr.h b/net/tipc/addr.h
index bcfebb3..e4bd533 100644
--- a/net/tipc/addr.h
+++ b/net/tipc/addr.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/addr.h: Include file for TIPC address utility routines
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2004-2005, Wind River Systems
  * All rights reserved.
@@ -100,8 +100,8 @@
 
 /**
  * addr_domain - convert 2-bit scope value to equivalent message lookup domain
- *  
- * Needed when address of a named message must be looked up a second time 
+ *
+ * Needed when address of a named message must be looked up a second time
  * after a network hop.
  */
 
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 730c5c4..e788017 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/bcast.c: TIPC broadcast code
- *     
+ *
  * Copyright (c) 2004-2006, Ericsson AB
  * Copyright (c) 2004, Intel Corporation.
  * Copyright (c) 2005, Wind River Systems
@@ -59,15 +59,15 @@
  * Loss rate for incoming broadcast frames; used to test retransmission code.
  * Set to N to cause every N'th frame to be discarded; 0 => don't discard any.
  */
- 
+
 #define TIPC_BCAST_LOSS_RATE 0
 
 /**
  * struct bcbearer_pair - a pair of bearers used by broadcast link
  * @primary: pointer to primary bearer
  * @secondary: pointer to secondary bearer
- * 
- * Bearers must have same priority and same set of reachable destinations 
+ *
+ * Bearers must have same priority and same set of reachable destinations
  * to be paired.
  */
 
@@ -84,7 +84,7 @@
  * @bpairs_temp: temporary array of bearer pairs used by tipc_bcbearer_sort()
  * @remains: temporary node map used by tipc_bcbearer_send()
  * @remains_new: temporary node map used tipc_bcbearer_send()
- * 
+ *
  * Note: The fields labelled "temporary" are incorporated into the bearer
  * to avoid consuming potentially limited stack space through the use of
  * large local variables within multicast routines.  Concurrent access is
@@ -104,7 +104,7 @@
  * struct bclink - link used for broadcast messages
  * @link: (non-standard) broadcast link structure
  * @node: (non-standard) node structure representing b'cast link's peer node
- * 
+ *
  * Handles sequence numbering, fragmentation, bundling, etc.
  */
 
@@ -125,7 +125,7 @@
 static u32 buf_seqno(struct sk_buff *buf)
 {
 	return msg_seqno(buf_msg(buf));
-} 
+}
 
 static u32 bcbuf_acks(struct sk_buff *buf)
 {
@@ -143,9 +143,9 @@
 }
 
 
-/** 
+/**
  * bclink_set_gap - set gap according to contents of current deferred pkt queue
- * 
+ *
  * Called with 'node' locked, bc_lock unlocked
  */
 
@@ -159,14 +159,14 @@
 		n_ptr->bclink.gap_to = mod(buf_seqno(buf) - 1);
 }
 
-/** 
+/**
  * bclink_ack_allowed - test if ACK or NACK message can be sent at this moment
- * 
+ *
  * This mechanism endeavours to prevent all nodes in network from trying
  * to ACK or NACK at the same time.
- * 
+ *
  * Note: TIPC uses a different trigger to distribute ACKs than it does to
- *       distribute NACKs, but tries to use the same spacing (divide by 16). 
+ *       distribute NACKs, but tries to use the same spacing (divide by 16).
  */
 
 static int bclink_ack_allowed(u32 n)
@@ -175,11 +175,11 @@
 }
 
 
-/** 
+/**
  * bclink_retransmit_pkt - retransmit broadcast packets
  * @after: sequence number of last packet to *not* retransmit
  * @to: sequence number of last packet to retransmit
- * 
+ *
  * Called with bc_lock locked
  */
 
@@ -189,16 +189,16 @@
 
 	buf = bcl->first_out;
 	while (buf && less_eq(buf_seqno(buf), after)) {
-		buf = buf->next;                
+		buf = buf->next;
 	}
 	tipc_link_retransmit(bcl, buf, mod(to - after));
 }
 
-/** 
+/**
  * tipc_bclink_acknowledge - handle acknowledgement of broadcast packets
  * @n_ptr: node that sent acknowledgement info
  * @acked: broadcast sequence # that has been acknowledged
- * 
+ *
  * Node is locked, bc_lock unlocked.
  */
 
@@ -244,9 +244,9 @@
 	spin_unlock_bh(&bc_lock);
 }
 
-/** 
+/**
  * bclink_send_ack - unicast an ACK msg
- * 
+ *
  * tipc_net_lock and node lock set
  */
 
@@ -258,9 +258,9 @@
 		tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
 }
 
-/** 
+/**
  * bclink_send_nack- broadcast a NACK msg
- * 
+ *
  * tipc_net_lock and node lock set
  */
 
@@ -278,7 +278,7 @@
 		msg_init(msg, BCAST_PROTOCOL, STATE_MSG,
 			 TIPC_OK, INT_H_SIZE, n_ptr->addr);
 		msg_set_mc_netid(msg, tipc_net_id);
-		msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); 
+		msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in));
 		msg_set_bcgap_after(msg, n_ptr->bclink.gap_after);
 		msg_set_bcgap_to(msg, n_ptr->bclink.gap_to);
 		msg_set_bcast_tag(msg, tipc_own_tag);
@@ -292,17 +292,17 @@
 			bcl->stats.bearer_congs++;
 		}
 
-		/* 
+		/*
 		 * Ensure we doesn't send another NACK msg to the node
 		 * until 16 more deferred messages arrive from it
 		 * (i.e. helps prevent all nodes from NACK'ing at same time)
 		 */
-		
+
 		n_ptr->bclink.nack_sync = tipc_own_tag;
 	}
 }
 
-/** 
+/**
  * tipc_bclink_check_gap - send a NACK if a sequence gap exists
  *
  * tipc_net_lock and node lock set
@@ -320,9 +320,9 @@
 	bclink_send_nack(n_ptr);
 }
 
-/** 
+/**
  * tipc_bclink_peek_nack - process a NACK msg meant for another node
- * 
+ *
  * Only tipc_net_lock set.
  */
 
@@ -349,7 +349,7 @@
 		if (less_eq(my_to, gap_to))
 			n_ptr->bclink.gap_to = gap_after;
 	} else {
-		/* 
+		/*
 		 * Expand gap if missing bufs not in deferred queue:
 		 */
 		struct sk_buff *buf = n_ptr->bclink.deferred_head;
@@ -371,7 +371,7 @@
 	}
 	/*
 	 * Some nodes may send a complementary NACK now:
-	 */ 
+	 */
 	if (bclink_ack_allowed(sender_tag + 1)) {
 		if (n_ptr->bclink.gap_to != n_ptr->bclink.gap_after) {
 			bclink_send_nack(n_ptr);
@@ -408,7 +408,7 @@
 
 /**
  * tipc_bclink_recv_pkt - receive a broadcast packet, and deliver upwards
- * 
+ *
  * tipc_net_lock is read_locked, no other locks set
  */
 
@@ -425,7 +425,7 @@
 
 	msg_dbg(msg, "<BC<<<");
 
-	if (unlikely(!node || !tipc_node_is_up(node) || !node->bclink.supported || 
+	if (unlikely(!node || !tipc_node_is_up(node) || !node->bclink.supported ||
 		     (msg_mc_netid(msg) != tipc_net_id))) {
 		buf_discard(buf);
 		return;
@@ -443,7 +443,7 @@
 			bclink_retransmit_pkt(msg_bcgap_after(msg),
 					      msg_bcgap_to(msg));
 			bcl->owner->next = NULL;
-			spin_unlock_bh(&bc_lock);              
+			spin_unlock_bh(&bc_lock);
 		} else {
 			tipc_bclink_peek_nack(msg_destnode(msg),
 					      msg_bcast_tag(msg),
@@ -547,10 +547,10 @@
 
 /**
  * tipc_bcbearer_send - send a packet through the broadcast pseudo-bearer
- * 
+ *
  * Send through as many bearers as necessary to reach all nodes
  * that support TIPC multicasting.
- * 
+ *
  * Returns 0 if packet sent successfully, non-zero if not
  */
 
@@ -581,7 +581,7 @@
 		send_count = 0;
 
 	/* Send buffer over bearers until all targets reached */
-	
+
 	bcbearer->remains = tipc_cltr_bcast_nodes;
 
 	for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
@@ -615,7 +615,7 @@
 
 		bcbearer->remains = bcbearer->remains_new;
 	}
-	
+
 	/* Unable to reach all targets */
 
 	bcbearer->bearer.publ.blocked = 1;
@@ -682,7 +682,7 @@
 
 /**
  * tipc_bcbearer_push - resolve bearer congestion
- * 
+ *
  * Forces bclink to push out any unsent packets, until all packets are gone
  * or congestion reoccurs.
  * No locks set when function called
@@ -714,27 +714,27 @@
 	spin_lock_bh(&bc_lock);
 
 	tipc_printf(&pb, "Link <%s>\n"
-		         "  Window:%u packets\n", 
+			 "  Window:%u packets\n",
 		    bcl->name, bcl->queue_limit[0]);
-	tipc_printf(&pb, "  RX packets:%u fragments:%u/%u bundles:%u/%u\n", 
+	tipc_printf(&pb, "  RX packets:%u fragments:%u/%u bundles:%u/%u\n",
 		    bcl->stats.recv_info,
 		    bcl->stats.recv_fragments,
 		    bcl->stats.recv_fragmented,
 		    bcl->stats.recv_bundles,
 		    bcl->stats.recv_bundled);
-	tipc_printf(&pb, "  TX packets:%u fragments:%u/%u bundles:%u/%u\n", 
+	tipc_printf(&pb, "  TX packets:%u fragments:%u/%u bundles:%u/%u\n",
 		    bcl->stats.sent_info,
 		    bcl->stats.sent_fragments,
-		    bcl->stats.sent_fragmented, 
+		    bcl->stats.sent_fragmented,
 		    bcl->stats.sent_bundles,
 		    bcl->stats.sent_bundled);
-	tipc_printf(&pb, "  RX naks:%u defs:%u dups:%u\n", 
+	tipc_printf(&pb, "  RX naks:%u defs:%u dups:%u\n",
 		    bcl->stats.recv_nacks,
-		    bcl->stats.deferred_recv, 
+		    bcl->stats.deferred_recv,
 		    bcl->stats.duplicates);
-	tipc_printf(&pb, "  TX naks:%u acks:%u dups:%u\n", 
-		    bcl->stats.sent_nacks, 
-		    bcl->stats.sent_acks, 
+	tipc_printf(&pb, "  TX naks:%u acks:%u dups:%u\n",
+		    bcl->stats.sent_nacks,
+		    bcl->stats.sent_acks,
 		    bcl->stats.retransmitted);
 	tipc_printf(&pb, "  Congestion bearer:%u link:%u  Send queue max:%u avg:%u\n",
 		    bcl->stats.bearer_congs,
@@ -778,7 +778,7 @@
 	bclink = kzalloc(sizeof(*bclink), GFP_ATOMIC);
 	if (!bcbearer || !bclink) {
  nomem:
-	 	warn("Multicast link creation failed, no memory\n");
+		warn("Multicast link creation failed, no memory\n");
 		kfree(bcbearer);
 		bcbearer = NULL;
 		kfree(bclink);
@@ -796,7 +796,7 @@
 	bcl->next_out_no = 1;
 	spin_lock_init(&bclink->node.lock);
 	bcl->owner = &bclink->node;
-        bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
+	bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
 	tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
 	bcl->b_ptr = &bcbearer->bearer;
 	bcl->state = WORKING_WORKING;
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index b243d9d..f910ed2 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/bcast.h: Include file for TIPC broadcast code
- * 
+ *
  * Copyright (c) 2003-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -102,7 +102,7 @@
 	}
 }
 
-/** 
+/**
  * nmap_remove - remove a node from a node map
  */
 
@@ -190,7 +190,7 @@
 
 /**
  * port_list_free - free dynamically created entries in port_list chain
- * 
+ *
  * Note: First item is on stack, so it doesn't need to be released
  */
 
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 39744a3..271a375 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/bearer.c: TIPC bearer code
- * 
+ *
  * Copyright (c) 1996-2006, Ericsson AB
  * Copyright (c) 2004-2006, Wind River Systems
  * All rights reserved.
@@ -52,7 +52,7 @@
 
 /**
  * media_name_valid - validate media name
- * 
+ *
  * Returns 1 if media name is valid, otherwise 0.
  */
 
@@ -84,17 +84,17 @@
 
 /**
  * tipc_register_media - register a media type
- * 
+ *
  * Bearers for this media type must be activated separately at a later stage.
  */
 
 int  tipc_register_media(u32 media_type,
-			 char *name, 
-			 int (*enable)(struct tipc_bearer *), 
-			 void (*disable)(struct tipc_bearer *), 
-			 int (*send_msg)(struct sk_buff *, 
+			 char *name,
+			 int (*enable)(struct tipc_bearer *),
+			 void (*disable)(struct tipc_bearer *),
+			 int (*send_msg)(struct sk_buff *,
 					 struct tipc_bearer *,
-					 struct tipc_media_addr *), 
+					 struct tipc_media_addr *),
 			 char *(*addr2str)(struct tipc_media_addr *a,
 					   char *str_buf, int str_size),
 			 struct tipc_media_addr *bcast_addr,
@@ -121,11 +121,11 @@
 	}
 	if ((bearer_priority < TIPC_MIN_LINK_PRI) &&
 	    (bearer_priority > TIPC_MAX_LINK_PRI)) {
-		warn("Media <%s> rejected, illegal priority (%u)\n", name, 
+		warn("Media <%s> rejected, illegal priority (%u)\n", name,
 		     bearer_priority);
 		goto exit;
 	}
-	if ((link_tolerance < TIPC_MIN_LINK_TOL) || 
+	if ((link_tolerance < TIPC_MIN_LINK_TOL) ||
 	    (link_tolerance > TIPC_MAX_LINK_TOL)) {
 		warn("Media <%s> rejected, illegal tolerance (%u)\n", name,
 		     link_tolerance);
@@ -219,7 +219,7 @@
 
 	read_lock_bh(&tipc_net_lock);
 	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
-		tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name, 
+		tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name,
 				    strlen(m_ptr->name) + 1);
 	}
 	read_unlock_bh(&tipc_net_lock);
@@ -230,11 +230,11 @@
  * bearer_name_validate - validate & (optionally) deconstruct bearer name
  * @name - ptr to bearer name string
  * @name_parts - ptr to area for bearer name components (or NULL if not needed)
- * 
+ *
  * Returns 1 if bearer name is valid, otherwise 0.
  */
 
-static int bearer_name_validate(const char *name, 
+static int bearer_name_validate(const char *name,
 				struct bearer_name *name_parts)
 {
 	char name_copy[TIPC_MAX_BEARER_NAME];
@@ -262,8 +262,8 @@
 
 	/* validate component parts of bearer name */
 
-	if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) || 
-	    (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) || 
+	if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) ||
+	    (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) ||
 	    (strspn(media_name, tipc_alphabet) != (media_len - 1)) ||
 	    (strspn(if_name, tipc_alphabet) != (if_len - 1)))
 		return 0;
@@ -336,8 +336,8 @@
 		for (j = 0; j < MAX_BEARERS; j++) {
 			b_ptr = &tipc_bearers[j];
 			if (b_ptr->active && (b_ptr->media == m_ptr)) {
-				tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, 
-						    b_ptr->publ.name, 
+				tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
+						    b_ptr->publ.name,
 						    strlen(b_ptr->publ.name) + 1);
 			}
 		}
@@ -401,8 +401,8 @@
 
 
 /*
- * Interrupt enabling new requests after bearer congestion or blocking:    
- * See bearer_send().   
+ * Interrupt enabling new requests after bearer congestion or blocking:
+ * See bearer_send().
  */
 void tipc_continue(struct tipc_bearer *tb_ptr)
 {
@@ -417,9 +417,9 @@
 }
 
 /*
- * Schedule link for sending of messages after the bearer 
- * has been deblocked by 'continue()'. This method is called 
- * when somebody tries to send a message via this link while 
+ * Schedule link for sending of messages after the bearer
+ * has been deblocked by 'continue()'. This method is called
+ * when somebody tries to send a message via this link while
  * the bearer is congested. 'tipc_net_lock' is in read_lock here
  * bearer.lock is busy
  */
@@ -430,9 +430,9 @@
 }
 
 /*
- * Schedule link for sending of messages after the bearer 
- * has been deblocked by 'continue()'. This method is called 
- * when somebody tries to send a message via this link while 
+ * Schedule link for sending of messages after the bearer
+ * has been deblocked by 'continue()'. This method is called
+ * when somebody tries to send a message via this link while
  * the bearer is congested. 'tipc_net_lock' is in read_lock here,
  * bearer.lock is free
  */
@@ -468,7 +468,7 @@
 
 /**
  * tipc_enable_bearer - enable bearer with the given name
- */              
+ */
 
 int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
 {
@@ -490,7 +490,7 @@
 		warn("Bearer <%s> rejected, illegal name\n", name);
 		return -EINVAL;
 	}
-	if (!tipc_addr_domain_valid(bcast_scope) || 
+	if (!tipc_addr_domain_valid(bcast_scope) ||
 	    !in_scope(bcast_scope, tipc_own_addr)) {
 		warn("Bearer <%s> rejected, illegal broadcast scope\n", name);
 		return -EINVAL;
@@ -539,7 +539,7 @@
 		}
 	}
 	if (bearer_id >= MAX_BEARERS) {
-		warn("Bearer <%s> rejected, bearer limit reached (%u)\n", 
+		warn("Bearer <%s> rejected, bearer limit reached (%u)\n",
 		     name, MAX_BEARERS);
 		goto failed;
 	}
@@ -612,7 +612,7 @@
 
 /**
  * bearer_disable -
- * 
+ *
  * Note: This routine assumes caller holds tipc_net_lock.
  */
 
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index c4e7c1c..6a36b66 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/bearer.h: Include file for TIPC bearer code
- * 
+ *
  * Copyright (c) 1996-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -58,14 +58,14 @@
  * @type_id: TIPC media identifier [defined in tipc_bearer.h]
  * @name: media name
  */
- 
+
 struct media {
-	int (*send_msg)(struct sk_buff *buf, 
+	int (*send_msg)(struct sk_buff *buf,
 			struct tipc_bearer *b_ptr,
 			struct tipc_media_addr *dest);
 	int (*enable_bearer)(struct tipc_bearer *b_ptr);
 	void (*disable_bearer)(struct tipc_bearer *b_ptr);
-	char *(*addr2str)(struct tipc_media_addr *a, 
+	char *(*addr2str)(struct tipc_media_addr *a,
 			  char *str_buf, int str_size);
 	struct tipc_media_addr bcast_addr;
 	int bcast;
@@ -91,7 +91,7 @@
  * @net_plane: network plane ('A' through 'H') currently associated with bearer
  * @nodes: indicates which nodes in cluster can be reached through bearer
  */
- 
+
 struct bearer {
 	struct tipc_bearer publ;
 	struct media *media;
@@ -131,21 +131,21 @@
 
 
 /**
- * tipc_bearer_send- sends buffer to destination over bearer 
- * 
+ * tipc_bearer_send- sends buffer to destination over bearer
+ *
  * Returns true (1) if successful, or false (0) if unable to send
- * 
+ *
  * IMPORTANT:
  * The media send routine must not alter the buffer being passed in
  * as it may be needed for later retransmission!
- * 
- * If the media send routine returns a non-zero value (indicating that 
+ *
+ * If the media send routine returns a non-zero value (indicating that
  * it was unable to send the buffer), it must:
  *   1) mark the bearer as blocked,
  *   2) call tipc_continue() once the bearer is able to send again.
  * Media types that are unable to meet these two critera must ensure their
  * send routine always returns success -- even if the buffer was not sent --
- * and let TIPC's link code deal with the undelivered message. 
+ * and let TIPC's link code deal with the undelivered message.
  */
 
 static inline int tipc_bearer_send(struct bearer *b_ptr, struct sk_buff *buf,
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c
index b46b518..95b3739 100644
--- a/net/tipc/cluster.c
+++ b/net/tipc/cluster.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/cluster.c: TIPC cluster management routines
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -56,7 +56,7 @@
 {
 	struct _zone *z_ptr;
 	struct cluster *c_ptr;
-	int max_nodes; 
+	int max_nodes;
 
 	c_ptr = kzalloc(sizeof(*c_ptr), GFP_ATOMIC);
 	if (c_ptr == NULL) {
@@ -81,7 +81,7 @@
 		tipc_local_nodes = c_ptr->nodes;
 	c_ptr->highest_slave = LOWEST_SLAVE - 1;
 	c_ptr->highest_node = 0;
-	
+
 	z_ptr = tipc_zone_find(tipc_zone(addr));
 	if (!z_ptr) {
 		z_ptr = tipc_zone_create(addr);
@@ -150,7 +150,7 @@
 
 /**
  * tipc_cltr_select_router - select router to a cluster
- * 
+ *
  * Uses deterministic and fair algorithm.
  */
 
@@ -192,7 +192,7 @@
 
 /**
  * tipc_cltr_select_node - select destination node within a remote cluster
- * 
+ *
  * Uses deterministic and fair algorithm.
  */
 
@@ -295,7 +295,7 @@
 		msg_set_remote_node(msg, c_ptr->addr);
 		msg_set_type(msg, SLAVE_ROUTING_TABLE);
 		for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) {
-			if (c_ptr->nodes[n_num] && 
+			if (c_ptr->nodes[n_num] &&
 			    tipc_node_has_active_links(c_ptr->nodes[n_num])) {
 				send = 1;
 				msg_set_dataoctet(msg, n_num);
@@ -329,7 +329,7 @@
 		msg_set_remote_node(msg, c_ptr->addr);
 		msg_set_type(msg, EXT_ROUTING_TABLE);
 		for (n_num = 1; n_num <= highest; n_num++) {
-			if (c_ptr->nodes[n_num] && 
+			if (c_ptr->nodes[n_num] &&
 			    tipc_node_has_active_links(c_ptr->nodes[n_num])) {
 				send = 1;
 				msg_set_dataoctet(msg, n_num);
@@ -360,7 +360,7 @@
 		msg_set_remote_node(msg, c_ptr->addr);
 		msg_set_type(msg, LOCAL_ROUTING_TABLE);
 		for (n_num = 1; n_num <= highest; n_num++) {
-			if (c_ptr->nodes[n_num] && 
+			if (c_ptr->nodes[n_num] &&
 			    tipc_node_has_active_links(c_ptr->nodes[n_num])) {
 				send = 1;
 				msg_set_dataoctet(msg, n_num);
@@ -492,7 +492,7 @@
 }
 
 /**
- * tipc_cltr_multicast - multicast message to local nodes 
+ * tipc_cltr_multicast - multicast message to local nodes
  */
 
 static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
@@ -554,9 +554,9 @@
 					buf_copy = skb_copy(buf, GFP_ATOMIC);
 					if (buf_copy == NULL)
 						goto exit;
-					msg_set_destnode(buf_msg(buf_copy), 
+					msg_set_destnode(buf_msg(buf_copy),
 							 n_ptr->addr);
-					tipc_link_send(buf_copy, n_ptr->addr, 
+					tipc_link_send(buf_copy, n_ptr->addr,
 						       n_ptr->addr);
 				}
 			}
diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h
index 1b4cd30..62df074 100644
--- a/net/tipc/cluster.h
+++ b/net/tipc/cluster.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/cluster.h: Include file for TIPC cluster management routines
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -50,7 +50,7 @@
  * @highest_node: id of highest numbered node within cluster
  * @highest_slave: (used for secondary node support)
  */
- 
+
 struct cluster {
 	u32 addr;
 	struct _zone *owner;
diff --git a/net/tipc/config.c b/net/tipc/config.c
index baf55c4..14789a8 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/config.c: TIPC configuration management code
- * 
+ *
  * Copyright (c) 2002-2006, Ericsson AB
  * Copyright (c) 2004-2006, Wind River Systems
  * All rights reserved.
@@ -86,7 +86,7 @@
 	return buf;
 }
 
-int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, 
+int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
 			void *tlv_data, int tlv_data_size)
 {
 	struct tlv_desc *tlv = (struct tlv_desc *)buf->tail;
@@ -112,7 +112,7 @@
 	buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value)));
 	if (buf) {
 		value_net = htonl(value);
-		tipc_cfg_append_tlv(buf, tlv_type, &value_net, 
+		tipc_cfg_append_tlv(buf, tlv_type, &value_net,
 				    sizeof(value_net));
 	}
 	return buf;
@@ -182,7 +182,7 @@
 
 static void cfg_cmd_event(struct tipc_cmd_msg *msg,
 			  char *data,
-			  u32 sz,        
+			  u32 sz,
 			  struct tipc_portid const *orig)
 {
 	int rv = -EINVAL;
@@ -192,7 +192,7 @@
 
 	msg->cmd = ntohl(msg->cmd);
 
-	cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect, 
+	cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect,
 			    data, 0);
 	if (ntohl(msg->magic) != TIPC_MAGIC)
 		goto exit;
@@ -295,7 +295,7 @@
 						   " (cannot change node address once assigned)");
 	tipc_own_addr = addr;
 
-	/* 
+	/*
 	 * Must release all spinlocks before calling start_net() because
 	 * Linux version of TIPC calls eth_media_start() which calls
 	 * register_netdevice_notifier() which may block!
@@ -619,7 +619,7 @@
 				struct sk_buff **buf,
 				const unchar *msg,
 				u32 size,
-				u32 importance, 
+				u32 importance,
 				struct tipc_portid const *orig,
 				struct tipc_name_seq const *dest)
 {
@@ -640,7 +640,7 @@
 	/* Generate reply for request (if can't, return request) */
 
 	rep_buf = tipc_cfg_do_cmd(orig->node,
-				  ntohs(req_hdr->tcm_type), 
+				  ntohs(req_hdr->tcm_type),
 				  msg + sizeof(*req_hdr),
 				  size - sizeof(*req_hdr),
 				  BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr));
diff --git a/net/tipc/config.h b/net/tipc/config.h
index 7a728f95..5cd7cc5 100644
--- a/net/tipc/config.h
+++ b/net/tipc/config.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/config.h: Include file for TIPC configuration service code
- * 
+ *
  * Copyright (c) 2003-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -43,7 +43,7 @@
 #include "link.h"
 
 struct sk_buff *tipc_cfg_reply_alloc(int payload_size);
-int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, 
+int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
 			void *tlv_data, int tlv_data_size);
 struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value);
 struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string);
@@ -68,8 +68,8 @@
 	return tipc_cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string);
 }
 
-struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, 
-				const void *req_tlv_area, int req_tlv_space, 
+struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd,
+				const void *req_tlv_area, int req_tlv_space,
 				int headroom);
 
 void tipc_cfg_link_event(u32 addr, char *name, int up);
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 6f5b7ee..d2d7d32 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -89,7 +89,7 @@
 int tipc_random;
 atomic_t tipc_user_count = ATOMIC_INIT(0);
 
-const char tipc_alphabet[] = 
+const char tipc_alphabet[] =
 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";
 
 /* configurable TIPC parameters */
@@ -171,13 +171,13 @@
 	get_random_bytes(&tipc_random, sizeof(tipc_random));
 	tipc_mode = TIPC_NODE_MODE;
 
-	if ((res = tipc_handler_start()) || 
+	if ((res = tipc_handler_start()) ||
 	    (res = tipc_ref_table_init(tipc_max_ports + tipc_max_subscriptions,
 				       tipc_random)) ||
 	    (res = tipc_reg_start()) ||
 	    (res = tipc_nametbl_init()) ||
-            (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) ||
-	    (res = tipc_k_signal((Handler)tipc_cfg_init, 0)) || 
+	    (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) ||
+	    (res = tipc_k_signal((Handler)tipc_cfg_init, 0)) ||
 	    (res = tipc_netlink_start()) ||
 	    (res = tipc_socket_init())) {
 		tipc_core_stop();
@@ -191,7 +191,7 @@
 	int res;
 
 	tipc_log_reinit(CONFIG_TIPC_LOG);
-	info("Activated (version " TIPC_MOD_VER 
+	info("Activated (version " TIPC_MOD_VER
 	     " compiled " __DATE__ " " __TIME__ ")\n");
 
 	tipc_own_addr = 0;
@@ -207,9 +207,9 @@
 
 	if ((res = tipc_core_start()))
 		err("Unable to start in single node mode\n");
-	else	
+	else
 		info("Started in single node mode\n");
-        return res;
+	return res;
 }
 
 static void __exit tipc_exit(void)
@@ -268,11 +268,11 @@
 /* TIPC API for external bearers (see tipc_bearer.h) */
 
 EXPORT_SYMBOL(tipc_block_bearer);
-EXPORT_SYMBOL(tipc_continue); 
+EXPORT_SYMBOL(tipc_continue);
 EXPORT_SYMBOL(tipc_disable_bearer);
 EXPORT_SYMBOL(tipc_enable_bearer);
 EXPORT_SYMBOL(tipc_recv_msg);
-EXPORT_SYMBOL(tipc_register_media); 
+EXPORT_SYMBOL(tipc_register_media);
 
 /* TIPC API for external APIs (see tipc_port.h) */
 
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 4638947c..e40ada9 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/core.h: Include file for TIPC global declarations
- * 
+ *
  * Copyright (c) 2005-2006, Ericsson AB
  * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
@@ -54,7 +54,7 @@
 #include <asm/atomic.h>
 #include <asm/hardirq.h>
 #include <linux/netdevice.h>
-#include <linux/in.h>	
+#include <linux/in.h>
 #include <linux/list.h>
 #include <linux/vmalloc.h>
 
@@ -88,7 +88,7 @@
 #define dump(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
 
 
-/*	
+/*
  * By default, TIPC_OUTPUT is defined to be system console and TIPC log buffer,
  * while DBG_OUTPUT is the null print buffer.  These defaults can be changed
  * here, or on a per .c file basis, by redefining these symbols.  The following
@@ -126,9 +126,9 @@
 #define dump(fmt,arg...) do {} while (0)
 
 
-/*	
+/*
  * TIPC_OUTPUT is defined to be the system console, while DBG_OUTPUT is
- * the null print buffer.  Thes ensures that any system or debug messages 
+ * the null print buffer.  Thes ensures that any system or debug messages
  * that are generated without using the above macros are handled correctly.
  */
 
@@ -138,10 +138,10 @@
 #undef  DBG_OUTPUT
 #define DBG_OUTPUT TIPC_NULL
 
-#endif			  
+#endif
 
 
-/* 
+/*
  * TIPC-specific error codes
  */
 
@@ -204,11 +204,11 @@
  * @timer: pointer to timer structure
  * @routine: pointer to routine to invoke when timer expires
  * @argument: value to pass to routine when timer expires
- * 
+ *
  * Timer must be initialized before use (and terminated when no longer needed).
  */
 
-static inline void k_init_timer(struct timer_list *timer, Handler routine, 
+static inline void k_init_timer(struct timer_list *timer, Handler routine,
 				unsigned long argument)
 {
 	dbg("initializing timer %p\n", timer);
@@ -221,13 +221,13 @@
  * k_start_timer - start a timer
  * @timer: pointer to timer structure
  * @msec: time to delay (in ms)
- * 
+ *
  * Schedules a previously initialized timer for later execution.
  * If timer is already running, the new timeout overrides the previous request.
- * 
+ *
  * To ensure the timer doesn't expire before the specified delay elapses,
  * the amount of delay is rounded up when converting to the jiffies
- * then an additional jiffy is added to account for the fact that 
+ * then an additional jiffy is added to account for the fact that
  * the starting time may be in the middle of the current jiffy.
  */
 
@@ -240,10 +240,10 @@
 /**
  * k_cancel_timer - cancel a timer
  * @timer: pointer to timer structure
- * 
- * Cancels a previously initialized timer.  
+ *
+ * Cancels a previously initialized timer.
  * Can be called safely even if the timer is already inactive.
- * 
+ *
  * WARNING: Must not be called when holding locks required by the timer's
  *          timeout routine, otherwise deadlock can occur on SMP systems!
  */
@@ -257,11 +257,11 @@
 /**
  * k_term_timer - terminate a timer
  * @timer: pointer to timer structure
- * 
+ *
  * Prevents further use of a previously initialized timer.
- * 
+ *
  * WARNING: Caller must ensure timer isn't currently running.
- * 
+ *
  * (Do not "enhance" this routine to automatically cancel an active timer,
  * otherwise deadlock can arise when a timeout routine calls k_term_timer.)
  */
@@ -302,7 +302,7 @@
  * @size: message size (including TIPC header)
  *
  * Returns a new buffer with data pointers set to the specified size.
- * 
+ *
  * NOTE: Headroom is reserved to allow prepending of a data link header.
  *       There may also be unrequested tailroom present at the buffer's end.
  */
@@ -334,4 +334,4 @@
 		kfree_skb(skb);
 }
 
-#endif			
+#endif
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index 627f99b7..e809d2a 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/dbg.c: TIPC print buffer routines for debugging
- * 
+ *
  * Copyright (c) 1996-2006, Ericsson AB
  * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
@@ -123,34 +123,34 @@
 /**
  * tipc_printbuf_validate - check for print buffer overflow
  * @pb: pointer to print buffer structure
- * 
- * Verifies that a print buffer has captured all data written to it. 
+ *
+ * Verifies that a print buffer has captured all data written to it.
  * If data has been lost, linearize buffer and prepend an error message
- * 
+ *
  * Returns length of print buffer data string (including trailing NUL)
  */
 
 int tipc_printbuf_validate(struct print_buf *pb)
 {
-        char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n";
-        char *cp_buf;
-        struct print_buf cb;
+	char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n";
+	char *cp_buf;
+	struct print_buf cb;
 
 	if (!pb->buf)
 		return 0;
 
 	if (pb->buf[pb->size - 1] == 0) {
-                cp_buf = kmalloc(pb->size, GFP_ATOMIC);
-                if (cp_buf != NULL){
-                        tipc_printbuf_init(&cb, cp_buf, pb->size);
-                        tipc_printbuf_move(&cb, pb);
-                        tipc_printbuf_move(pb, &cb);
-                        kfree(cp_buf);
-                        memcpy(pb->buf, err, strlen(err));
-                } else {
-                        tipc_printbuf_reset(pb);
-                        tipc_printf(pb, err);
-                }
+		cp_buf = kmalloc(pb->size, GFP_ATOMIC);
+		if (cp_buf != NULL){
+			tipc_printbuf_init(&cb, cp_buf, pb->size);
+			tipc_printbuf_move(&cb, pb);
+			tipc_printbuf_move(pb, &cb);
+			kfree(cp_buf);
+			memcpy(pb->buf, err, strlen(err));
+		} else {
+			tipc_printbuf_reset(pb);
+			tipc_printf(pb, err);
+		}
 	}
 	return (pb->crs - pb->buf + 1);
 }
@@ -159,7 +159,7 @@
  * tipc_printbuf_move - move print buffer contents to another print buffer
  * @pb_to: pointer to destination print buffer structure
  * @pb_from: pointer to source print buffer structure
- * 
+ *
  * Current contents of destination print buffer (if any) are discarded.
  * Source print buffer becomes empty if a successful move occurs.
  */
@@ -234,13 +234,13 @@
 				pb->crs = pb->buf + pb->size - 1;
 			} else {
 				strcpy(pb->buf, print_string + chars_left);
-                                save_char = print_string[chars_left];
-                                print_string[chars_left] = 0;
-                                strcpy(pb->crs, print_string);
-                                print_string[chars_left] = save_char;
-                                pb->crs = pb->buf + chars_to_add - chars_left;
-                        }
-                }
+				save_char = print_string[chars_left];
+				print_string[chars_left] = 0;
+				strcpy(pb->crs, print_string);
+				print_string[chars_left] = save_char;
+				pb->crs = pb->buf + chars_to_add - chars_left;
+			}
+		}
 		pb_next = pb->next;
 		pb->next = NULL;
 		pb = pb_next;
@@ -249,7 +249,7 @@
 }
 
 /**
- * TIPC_TEE - perform next output operation on both print buffers  
+ * TIPC_TEE - perform next output operation on both print buffers
  * @b0: pointer to chain of print buffers (may be NULL)
  * @b1: pointer to print buffer to add to chain
  *
@@ -350,7 +350,7 @@
 }
 
 /**
- * tipc_log_stop - free up TIPC log print buffer 
+ * tipc_log_stop - free up TIPC log print buffer
  */
 
 void tipc_log_stop(void)
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h
index 467c0bc7..c01b085 100644
--- a/net/tipc/dbg.h
+++ b/net/tipc/dbg.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/dbg.h: Include file for TIPC print buffer routines
- * 
+ *
  * Copyright (c) 1997-2006, Ericsson AB
  * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 3b0cd12..5d643e5 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/discover.c
- * 
+ *
  * Copyright (c) 2003-2006, Ericsson AB
  * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
@@ -56,10 +56,10 @@
 #define  CHECK_LINK_COUNT      306
 #endif
 
-/* 
+/*
  * TODO: Most of the inter-cluster setup stuff should be
  * rewritten, and be made conformant with specification.
- */ 
+ */
 
 
 /**
@@ -80,10 +80,10 @@
 
 
 #if 0
-int disc_create_link(const struct tipc_link_create *argv) 
+int disc_create_link(const struct tipc_link_create *argv)
 {
-	/* 
-	 * Code for inter cluster link setup here 
+	/*
+	 * Code for inter cluster link setup here
 	 */
 	return TIPC_OK;
 }
@@ -93,16 +93,16 @@
  * disc_lost_link(): A link has lost contact
  */
 
-void tipc_disc_link_event(u32 addr, char *name, int up) 
+void tipc_disc_link_event(u32 addr, char *name, int up)
 {
 	if (in_own_cluster(addr))
 		return;
-	/* 
-	 * Code for inter cluster link setup here 
+	/*
+	 * Code for inter cluster link setup here
 	 */
 }
 
-/** 
+/**
  * tipc_disc_init_msg - initialize a link setup message
  * @type: message type (request or response)
  * @req_links: number of links associated with message
@@ -210,7 +210,7 @@
 			dbg("creating link\n");
 			link = tipc_link_create(b_ptr, orig, &media_addr);
 			if (!link) {
-				spin_unlock_bh(&n_ptr->lock);                
+				spin_unlock_bh(&n_ptr->lock);
 				return;
 			}
 		}
@@ -224,10 +224,10 @@
 			warn("Resetting link <%s>, peer interface address changed\n",
 			     link->name);
 			memcpy(addr, &media_addr, sizeof(*addr));
-			tipc_link_reset(link);     
+			tipc_link_reset(link);
 		}
 		link_fully_up = (link->state == WORKING_WORKING);
-		spin_unlock_bh(&n_ptr->lock);                
+		spin_unlock_bh(&n_ptr->lock);
 		if ((type == DSC_RESP_MSG) || link_fully_up)
 			return;
 		rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
@@ -244,23 +244,23 @@
  * @req: ptr to link request structure
  */
 
-void tipc_disc_stop_link_req(struct link_req *req) 
+void tipc_disc_stop_link_req(struct link_req *req)
 {
 	if (!req)
 		return;
-		
+
 	k_cancel_timer(&req->timer);
 	k_term_timer(&req->timer);
 	buf_discard(req->buf);
 	kfree(req);
-} 
+}
 
 /**
  * tipc_disc_update_link_req - update frequency of periodic link setup requests
  * @req: ptr to link request structure
  */
 
-void tipc_disc_update_link_req(struct link_req *req) 
+void tipc_disc_update_link_req(struct link_req *req)
 {
 	if (!req)
 		return;
@@ -278,16 +278,16 @@
 	} else {
 		/* leave timer "as is" if haven't yet reached a "normal" rate */
 	}
-} 
+}
 
 /**
  * disc_timeout - send a periodic link setup request
  * @req: ptr to link request structure
- * 
+ *
  * Called whenever a link setup request timer associated with a bearer expires.
  */
 
-static void disc_timeout(struct link_req *req) 
+static void disc_timeout(struct link_req *req)
 {
 	spin_lock_bh(&req->bearer->publ.lock);
 
@@ -300,7 +300,7 @@
 		req->timer_intv *= 2;
 		if (req->timer_intv > TIPC_LINK_REQ_FAST)
 			req->timer_intv = TIPC_LINK_REQ_FAST;
-		if ((req->timer_intv == TIPC_LINK_REQ_FAST) && 
+		if ((req->timer_intv == TIPC_LINK_REQ_FAST) &&
 		    (req->bearer->nodes.count))
 			req->timer_intv = TIPC_LINK_REQ_SLOW;
 	}
@@ -315,14 +315,14 @@
  * @dest: destination address for request messages
  * @dest_domain: network domain of node(s) which should respond to message
  * @req_links: max number of desired links
- * 
+ *
  * Returns pointer to link request structure, or NULL if unable to create.
  */
 
-struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, 
+struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
 					 const struct tipc_media_addr *dest,
 					 u32 dest_domain,
-					 u32 req_links) 
+					 u32 req_links)
 {
 	struct link_req *req;
 
@@ -342,5 +342,5 @@
 	k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
 	k_start_timer(&req->timer, req->timer_intv);
 	return req;
-} 
+}
 
diff --git a/net/tipc/discover.h b/net/tipc/discover.h
index 0454fd1..9fd7587 100644
--- a/net/tipc/discover.h
+++ b/net/tipc/discover.h
@@ -41,7 +41,7 @@
 
 struct link_req;
 
-struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, 
+struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
 					 const struct tipc_media_addr *dest,
 					 u32 dest_domain,
 					 u32 req_links);
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 682da4a..9be4839 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/eth_media.c: Ethernet bearer support for TIPC
- * 
+ *
  * Copyright (c) 2001-2006, Ericsson AB
  * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
@@ -50,7 +50,7 @@
  * @dev: ptr to associated Ethernet network device
  * @tipc_packet_type: used in binding TIPC to Ethernet driver
  */
- 
+
 struct eth_bearer {
 	struct tipc_bearer *bearer;
 	struct net_device *dev;
@@ -62,10 +62,10 @@
 static struct notifier_block notifier;
 
 /**
- * send_msg - send a TIPC message out over an Ethernet interface 
+ * send_msg - send a TIPC message out over an Ethernet interface
  */
 
-static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, 
+static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
 		    struct tipc_media_addr *dest)
 {
 	struct sk_buff *clone;
@@ -76,7 +76,7 @@
 		clone->nh.raw = clone->data;
 		dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev;
 		clone->dev = dev;
-		dev->hard_header(clone, dev, ETH_P_TIPC, 
+		dev->hard_header(clone, dev, ETH_P_TIPC,
 				 &dest->dev_addr.eth_addr,
 				 dev->dev_addr, clone->len);
 		dev_queue_xmit(clone);
@@ -86,12 +86,12 @@
 
 /**
  * recv_msg - handle incoming TIPC message from an Ethernet interface
- * 
+ *
  * Routine truncates any Ethernet padding/CRC appended to the message,
  * and ensures message size matches actual length
  */
 
-static int recv_msg(struct sk_buff *buf, struct net_device *dev, 
+static int recv_msg(struct sk_buff *buf, struct net_device *dev,
 		    struct packet_type *pt, struct net_device *orig_dev)
 {
 	struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
@@ -99,14 +99,14 @@
 
 	if (likely(eb_ptr->bearer)) {
 	       if (likely(!dev->promiscuity) ||
-	           !memcmp(buf->mac.raw,dev->dev_addr,ETH_ALEN) ||
-	           !memcmp(buf->mac.raw,dev->broadcast,ETH_ALEN)) {
-		        size = msg_size((struct tipc_msg *)buf->data);
-	                skb_trim(buf, size);
-	        	if (likely(buf->len == size)) {
-		        	buf->next = NULL;
-			        tipc_recv_msg(buf, eb_ptr->bearer);
-			        return TIPC_OK;
+		   !memcmp(buf->mac.raw,dev->dev_addr,ETH_ALEN) ||
+		   !memcmp(buf->mac.raw,dev->broadcast,ETH_ALEN)) {
+			size = msg_size((struct tipc_msg *)buf->data);
+			skb_trim(buf, size);
+			if (likely(buf->len == size)) {
+				buf->next = NULL;
+				tipc_recv_msg(buf, eb_ptr->bearer);
+				return TIPC_OK;
 			}
 		}
 	}
@@ -115,7 +115,7 @@
 }
 
 /**
- * enable_bearer - attach TIPC bearer to an Ethernet interface 
+ * enable_bearer - attach TIPC bearer to an Ethernet interface
  */
 
 static int enable_bearer(struct tipc_bearer *tb_ptr)
@@ -127,7 +127,7 @@
 
 	/* Find device with specified name */
 
-	while (dev && dev->name && strncmp(dev->name, driver_name, IFNAMSIZ)) {	
+	while (dev && dev->name && strncmp(dev->name, driver_name, IFNAMSIZ)) {
 		dev = dev->next;
 	}
 	if (!dev)
@@ -154,14 +154,14 @@
 	eb_ptr->bearer = tb_ptr;
 	tb_ptr->usr_handle = (void *)eb_ptr;
 	tb_ptr->mtu = dev->mtu;
-	tb_ptr->blocked = 0; 
+	tb_ptr->blocked = 0;
 	tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH);
 	memcpy(&tb_ptr->addr.dev_addr, &dev->dev_addr, ETH_ALEN);
 	return 0;
 }
 
 /**
- * disable_bearer - detach TIPC bearer from an Ethernet interface 
+ * disable_bearer - detach TIPC bearer from an Ethernet interface
  *
  * We really should do dev_remove_pack() here, but this function can not be
  * called at tasklet level. => Use eth_bearer->bearer as a flag to throw away
@@ -176,11 +176,11 @@
 /**
  * recv_notification - handle device updates from OS
  *
- * Change the state of the Ethernet bearer (if any) associated with the 
+ * Change the state of the Ethernet bearer (if any) associated with the
  * specified device.
  */
 
-static int recv_notification(struct notifier_block *nb, unsigned long evt, 
+static int recv_notification(struct notifier_block *nb, unsigned long evt,
 			     void *dv)
 {
 	struct net_device *dev = (struct net_device *)dv;
@@ -194,7 +194,7 @@
 	if (!eb_ptr->bearer)
 		return NOTIFY_DONE;		/* bearer had been disabled */
 
-        eb_ptr->bearer->mtu = dev->mtu;
+	eb_ptr->bearer->mtu = dev->mtu;
 
 	switch (evt) {
 	case NETDEV_CHANGE:
@@ -210,12 +210,12 @@
 		tipc_block_bearer(eb_ptr->bearer->name);
 		break;
 	case NETDEV_CHANGEMTU:
-        case NETDEV_CHANGEADDR:
+	case NETDEV_CHANGEADDR:
 		tipc_block_bearer(eb_ptr->bearer->name);
-                tipc_continue(eb_ptr->bearer);
+		tipc_continue(eb_ptr->bearer);
 		break;
 	case NETDEV_UNREGISTER:
-        case NETDEV_CHANGENAME:
+	case NETDEV_CHANGENAME:
 		tipc_disable_bearer(eb_ptr->bearer->name);
 		break;
 	}
@@ -227,7 +227,7 @@
  */
 
 static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
-{                       
+{
 	unchar *addr = (unchar *)&a->dev_addr;
 
 	if (str_size < 18)
@@ -246,7 +246,7 @@
  */
 
 int tipc_eth_media_start(void)
-{                       
+{
 	struct tipc_media_addr bcast_addr;
 	int res;
 
@@ -259,8 +259,8 @@
 	memset(eth_bearers, 0, sizeof(eth_bearers));
 
 	res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth",
-				  enable_bearer, disable_bearer, send_msg, 
-				  eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY, 
+				  enable_bearer, disable_bearer, send_msg,
+				  eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY,
 				  ETH_LINK_TOLERANCE, ETH_LINK_WINDOW);
 	if (res)
 		return res;
diff --git a/net/tipc/handler.c b/net/tipc/handler.c
index eb80778..e1dcf66 100644
--- a/net/tipc/handler.c
+++ b/net/tipc/handler.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/handler.c: TIPC signal handling
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -95,7 +95,7 @@
 
 int tipc_handler_start(void)
 {
-	tipc_queue_item_cache = 
+	tipc_queue_item_cache =
 		kmem_cache_create("tipc_queue_items", sizeof(struct queue_item),
 				  0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 	if (!tipc_queue_item_cache)
@@ -110,7 +110,7 @@
 void tipc_handler_stop(void)
 {
 	struct list_head *l, *n;
-	struct queue_item *item; 
+	struct queue_item *item;
 
 	if (!handler_enabled)
 		return;
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 1bb983c..71c2f2f 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/link.c: TIPC link code
- * 
+ *
  * Copyright (c) 1996-2006, Ericsson AB
  * Copyright (c) 2004-2006, Wind River Systems
  * All rights reserved.
@@ -50,29 +50,29 @@
 #include "bcast.h"
 
 
-/* 
- * Limit for deferred reception queue: 
+/*
+ * Limit for deferred reception queue:
  */
 
 #define DEF_QUEUE_LIMIT 256u
 
-/* 
- * Link state events: 
+/*
+ * Link state events:
  */
 
 #define  STARTING_EVT    856384768	/* link processing trigger */
 #define  TRAFFIC_MSG_EVT 560815u	/* rx'd ??? */
 #define  TIMEOUT_EVT     560817u	/* link timer expired */
 
-/*   
- * The following two 'message types' is really just implementation 
- * data conveniently stored in the message header. 
+/*
+ * The following two 'message types' is really just implementation
+ * data conveniently stored in the message header.
  * They must not be considered part of the protocol
  */
 #define OPEN_MSG   0
 #define CLOSED_MSG 1
 
-/* 
+/*
  * State value stored in 'exp_msg_count'
  */
 
@@ -97,7 +97,7 @@
 
 /* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */
 
-/** 
+/**
  * struct link_event - link up/down event notification
  */
 
@@ -121,7 +121,7 @@
 static void link_check_defragm_bufs(struct link *l_ptr);
 static void link_state_event(struct link *l_ptr, u32 event);
 static void link_reset_statistics(struct link *l_ptr);
-static void link_print(struct link *l_ptr, struct print_buf *buf, 
+static void link_print(struct link *l_ptr, struct print_buf *buf,
 		       const char *str);
 
 /*
@@ -136,13 +136,13 @@
  *
  * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size
  * of the print buffer used by each link.  If LINK_LOG_BUF_SIZE is set to 0,
- * the dbg_link_XXX() routines simply send their output to the standard 
+ * the dbg_link_XXX() routines simply send their output to the standard
  * debug print buffer (DBG_OUTPUT), if it has been defined; this can be useful
  * when there is only a single link in the system being debugged.
  *
  * Notes:
  * - When enabled, LINK_LOG_BUF_SIZE should be set to at least TIPC_PB_MIN_SIZE
- * - "l_ptr" must be valid when using dbg_link_XXX() macros  
+ * - "l_ptr" must be valid when using dbg_link_XXX() macros
  */
 
 #define LINK_LOG_BUF_SIZE 0
@@ -222,18 +222,18 @@
 static void link_init_max_pkt(struct link *l_ptr)
 {
 	u32 max_pkt;
-	
+
 	max_pkt = (l_ptr->b_ptr->publ.mtu & ~3);
 	if (max_pkt > MAX_MSG_SIZE)
 		max_pkt = MAX_MSG_SIZE;
 
-        l_ptr->max_pkt_target = max_pkt;
+	l_ptr->max_pkt_target = max_pkt;
 	if (l_ptr->max_pkt_target < MAX_PKT_DEFAULT)
 		l_ptr->max_pkt = l_ptr->max_pkt_target;
-	else 
+	else
 		l_ptr->max_pkt = MAX_PKT_DEFAULT;
 
-        l_ptr->max_pkt_probes = 0;
+	l_ptr->max_pkt_probes = 0;
 }
 
 static u32 link_next_sent(struct link *l_ptr)
@@ -269,7 +269,7 @@
  * link_name_validate - validate & (optionally) deconstruct link name
  * @name - ptr to link name string
  * @name_parts - ptr to area for link name components (or NULL if not needed)
- * 
+ *
  * Returns 1 if link name is valid, otherwise 0.
  */
 
@@ -317,8 +317,8 @@
 		    &z_peer, &c_peer, &n_peer, &dummy) != 3) ||
 	    (z_local > 255) || (c_local > 4095) || (n_local > 4095) ||
 	    (z_peer  > 255) || (c_peer  > 4095) || (n_peer  > 4095) ||
-	    (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) || 
-	    (if_peer_len  <= 1) || (if_peer_len  > TIPC_MAX_IF_NAME) || 
+	    (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) ||
+	    (if_peer_len  <= 1) || (if_peer_len  > TIPC_MAX_IF_NAME) ||
 	    (strspn(if_local, tipc_alphabet) != (if_local_len - 1)) ||
 	    (strspn(if_peer, tipc_alphabet) != (if_peer_len - 1)))
 		return 0;
@@ -337,7 +337,7 @@
 /**
  * link_timeout - handle expiration of link timer
  * @l_ptr: pointer to link
- * 
+ *
  * This routine must not grab "tipc_net_lock" to avoid a potential deadlock conflict
  * with tipc_link_delete().  (There is no risk that the node will be deleted by
  * another thread because tipc_link_delete() always cancels the link timer before
@@ -406,7 +406,7 @@
  * @b_ptr: pointer to associated bearer
  * @peer: network address of node at other end of link
  * @media_addr: media address to use when sending messages over link
- * 
+ *
  * Returns pointer to link.
  */
 
@@ -427,7 +427,7 @@
 	if_name = strchr(b_ptr->publ.name, ':') + 1;
 	sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:",
 		tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
-		tipc_node(tipc_own_addr), 
+		tipc_node(tipc_own_addr),
 		if_name,
 		tipc_zone(peer), tipc_cluster(peer), tipc_node(peer));
 		/* note: peer i/f is appended to link name by reset/activate */
@@ -478,17 +478,17 @@
 
 	dbg("tipc_link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n",
 	    l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit);
-	
+
 	return l_ptr;
 }
 
-/** 
+/**
  * tipc_link_delete - delete a link
  * @l_ptr: pointer to link
- * 
+ *
  * Note: 'tipc_net_lock' is write_locked, bearer is locked.
  * This routine must not grab the node lock until after link timer cancellation
- * to avoid a potential deadlock situation.  
+ * to avoid a potential deadlock situation.
  */
 
 void tipc_link_delete(struct link *l_ptr)
@@ -501,7 +501,7 @@
 	dbg("tipc_link_delete()\n");
 
 	k_cancel_timer(&l_ptr->timer);
-	
+
 	tipc_node_lock(l_ptr->owner);
 	tipc_link_reset(l_ptr);
 	tipc_node_detach_link(l_ptr->owner, l_ptr);
@@ -521,12 +521,12 @@
 }
 
 /**
- * link_schedule_port - schedule port for deferred sending 
+ * link_schedule_port - schedule port for deferred sending
  * @l_ptr: pointer to link
  * @origport: reference to sending port
  * @sz: amount of data to be sent
- * 
- * Schedules port for renewed sending of messages after link congestion 
+ *
+ * Schedules port for renewed sending of messages after link congestion
  * has abated.
  */
 
@@ -567,7 +567,7 @@
 		return;
 	if (link_congested(l_ptr))
 		goto exit;
-	list_for_each_entry_safe(p_ptr, temp_p_ptr, &l_ptr->waiting_ports, 
+	list_for_each_entry_safe(p_ptr, temp_p_ptr, &l_ptr->waiting_ports,
 				 wait_list) {
 		if (win <= 0)
 			break;
@@ -584,7 +584,7 @@
 	spin_unlock_bh(&tipc_port_list_lock);
 }
 
-/** 
+/**
  * link_release_outqueue - purge link's outbound message queue
  * @l_ptr: pointer to link
  */
@@ -621,7 +621,7 @@
 	l_ptr->defragm_buf = NULL;
 }
 
-/** 
+/**
  * tipc_link_stop - purge all inbound and outbound messages associated with link
  * @l_ptr: pointer to link
  */
@@ -665,7 +665,7 @@
 			    struct link *l_ptr, int up)
 {
 	struct link_event *ev;
-	
+
 	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
 	if (!ev) {
 		warn("Link event allocation failure\n");
@@ -690,15 +690,15 @@
 	u32 prev_state = l_ptr->state;
 	u32 checkpoint = l_ptr->next_in_no;
 	int was_active_link = tipc_link_is_active(l_ptr);
-	
+
 	msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1);
 
-        /* Link is down, accept any session: */
+	/* Link is down, accept any session: */
 	l_ptr->peer_session = 0;
 
-        /* Prepare for max packet size negotiation */
+	/* Prepare for max packet size negotiation */
 	link_init_max_pkt(l_ptr);
-	
+
 	l_ptr->state = RESET_UNKNOWN;
 	dbg_link_state("Resetting Link\n");
 
@@ -770,7 +770,7 @@
 
 static void link_state_event(struct link *l_ptr, unsigned event)
 {
-	struct link *other; 
+	struct link *other;
 	u32 cont_intv = l_ptr->continuity_interval;
 
 	if (!l_ptr->started && (event != STARTING_EVT))
@@ -799,11 +799,11 @@
 			if (l_ptr->next_in_no != l_ptr->checkpoint) {
 				l_ptr->checkpoint = l_ptr->next_in_no;
 				if (tipc_bclink_acks_missing(l_ptr->owner)) {
-					tipc_link_send_proto_msg(l_ptr, STATE_MSG, 
+					tipc_link_send_proto_msg(l_ptr, STATE_MSG,
 								 0, 0, 0, 0, 0);
 					l_ptr->fsm_msg_cnt++;
 				} else if (l_ptr->max_pkt < l_ptr->max_pkt_target) {
-					tipc_link_send_proto_msg(l_ptr, STATE_MSG, 
+					tipc_link_send_proto_msg(l_ptr, STATE_MSG,
 								 1, 0, 0, 0, 0);
 					l_ptr->fsm_msg_cnt++;
 				}
@@ -819,7 +819,7 @@
 			break;
 		case RESET_MSG:
 			dbg_link("RES -> RR\n");
-			info("Resetting link <%s>, requested by peer\n", 
+			info("Resetting link <%s>, requested by peer\n",
 			     l_ptr->name);
 			tipc_link_reset(l_ptr);
 			l_ptr->state = RESET_RESET;
@@ -871,7 +871,7 @@
 				dbg_link("Probing %u/%u,timer = %u ms)\n",
 					 l_ptr->fsm_msg_cnt, l_ptr->abort_limit,
 					 cont_intv / 4);
-				tipc_link_send_proto_msg(l_ptr, STATE_MSG, 
+				tipc_link_send_proto_msg(l_ptr, STATE_MSG,
 							 1, 0, 0, 0, 0);
 				l_ptr->fsm_msg_cnt++;
 				link_set_timer(l_ptr, cont_intv / 4);
@@ -977,11 +977,11 @@
 
 /*
  * link_bundle_buf(): Append contents of a buffer to
- * the tail of an existing one. 
+ * the tail of an existing one.
  */
 
 static int link_bundle_buf(struct link *l_ptr,
-			   struct sk_buff *bundler, 
+			   struct sk_buff *bundler,
 			   struct sk_buff *buf)
 {
 	struct tipc_msg *bundler_msg = buf_msg(bundler);
@@ -1030,8 +1030,8 @@
 	l_ptr->out_queue_size++;
 }
 
-/* 
- * tipc_link_send_buf() is the 'full path' for messages, called from 
+/*
+ * tipc_link_send_buf() is the 'full path' for messages, called from
  * inside TIPC when the 'fast path' in tipc_send_buf
  * has failed, and from link_send()
  */
@@ -1074,7 +1074,7 @@
 	if (queue_size > l_ptr->stats.max_queue_sz)
 		l_ptr->stats.max_queue_sz = queue_size;
 
-	if (likely(!tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && 
+	if (likely(!tipc_bearer_congested(l_ptr->b_ptr, l_ptr) &&
 		   !link_congested(l_ptr))) {
 		link_add_to_outqueue(l_ptr, buf, msg);
 
@@ -1094,7 +1094,7 @@
 
 		/* Try adding message to an existing bundle */
 
-		if (l_ptr->next_out && 
+		if (l_ptr->next_out &&
 		    link_bundle_buf(l_ptr, l_ptr->last_out, buf)) {
 			tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
 			return dsz;
@@ -1109,7 +1109,7 @@
 			if (bundler) {
 				msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG,
 					 TIPC_OK, INT_H_SIZE, l_ptr->addr);
-				memcpy(bundler->data, (unchar *)&bundler_hdr, 
+				memcpy(bundler->data, (unchar *)&bundler_hdr,
 				       INT_H_SIZE);
 				skb_trim(bundler, INT_H_SIZE);
 				link_bundle_buf(l_ptr, bundler, buf);
@@ -1126,8 +1126,8 @@
 	return dsz;
 }
 
-/* 
- * tipc_link_send(): same as tipc_link_send_buf(), but the link to use has 
+/*
+ * tipc_link_send(): same as tipc_link_send_buf(), but the link to use has
  * not been selected yet, and the the owner node is not locked
  * Called by TIPC internal users, e.g. the name distributor
  */
@@ -1161,8 +1161,8 @@
 	return res;
 }
 
-/* 
- * link_send_buf_fast: Entry for data messages where the 
+/*
+ * link_send_buf_fast: Entry for data messages where the
  * destination link is known and the header is complete,
  * inclusive total message length. Very time critical.
  * Link is locked. Returns user data length.
@@ -1197,8 +1197,8 @@
 	return tipc_link_send_buf(l_ptr, buf);  /* All other cases */
 }
 
-/* 
- * tipc_send_buf_fast: Entry for data messages where the 
+/*
+ * tipc_send_buf_fast: Entry for data messages where the
  * destination node is known and the header is complete,
  * inclusive total message length.
  * Returns user data length.
@@ -1236,15 +1236,15 @@
 }
 
 
-/* 
- * tipc_link_send_sections_fast: Entry for messages where the 
+/*
+ * tipc_link_send_sections_fast: Entry for messages where the
  * destination processor is known and the header is complete,
- * except for total message length. 
+ * except for total message length.
  * Returns user data length or errno.
  */
-int tipc_link_send_sections_fast(struct port *sender, 
+int tipc_link_send_sections_fast(struct port *sender,
 				 struct iovec const *msg_sect,
-				 const u32 num_sect, 
+				 const u32 num_sect,
 				 u32 destaddr)
 {
 	struct tipc_msg *hdr = &sender->publ.phdr;
@@ -1287,14 +1287,14 @@
 
 			/* Exit if link (or bearer) is congested */
 
-			if (link_congested(l_ptr) || 
+			if (link_congested(l_ptr) ||
 			    !list_empty(&l_ptr->b_ptr->cong_links)) {
 				res = link_schedule_port(l_ptr,
 							 sender->publ.ref, res);
 				goto exit;
 			}
 
-			/* 
+			/*
 			 * Message size exceeds max_pkt hint; update hint,
 			 * then re-try fast path or fragment the message
 			 */
@@ -1324,10 +1324,10 @@
 	return res;
 }
 
-/* 
- * link_send_sections_long(): Entry for long messages where the 
+/*
+ * link_send_sections_long(): Entry for long messages where the
  * destination node is known and the header is complete,
- * inclusive total message length. 
+ * inclusive total message length.
  * Link and bearer congestion status have been checked to be ok,
  * and are ignored if they change.
  *
@@ -1357,9 +1357,9 @@
 
 again:
 	fragm_no = 1;
-	max_pkt = sender->max_pkt - INT_H_SIZE;  
+	max_pkt = sender->max_pkt - INT_H_SIZE;
 		/* leave room for tunnel header in case of link changeover */
-	fragm_sz = max_pkt - INT_H_SIZE; 
+	fragm_sz = max_pkt - INT_H_SIZE;
 		/* leave room for fragmentation header in each fragment */
 	rest = dsz;
 	fragm_crs = 0;
@@ -1440,7 +1440,7 @@
 			if (!buf)
 				goto error;
 
-			buf->next = NULL;                                
+			buf->next = NULL;
 			prev->next = buf;
 			memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE);
 			fragm_crs = INT_H_SIZE;
@@ -1450,7 +1450,7 @@
 	}
 	while (rest > 0);
 
-	/* 
+	/*
 	 * Now we have a buffer chain. Select a link and check
 	 * that packet size is still OK
 	 */
@@ -1506,7 +1506,7 @@
 	return dsz;
 }
 
-/* 
+/*
  * tipc_link_push_packet: Push one unsent packet to the media
  */
 u32 tipc_link_push_packet(struct link *l_ptr)
@@ -1519,7 +1519,7 @@
 	/* consider that buffers may have been released in meantime */
 
 	if (r_q_size && buf) {
-		u32 last = lesser(mod(r_q_head + r_q_size), 
+		u32 last = lesser(mod(r_q_head + r_q_size),
 				  link_last_sent(l_ptr));
 		u32 first = msg_seqno(buf_msg(buf));
 
@@ -1535,7 +1535,7 @@
 
 	if (r_q_size && buf && !skb_cloned(buf)) {
 		msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
-		msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); 
+		msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
 		if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
 			msg_dbg(buf_msg(buf), ">DEF-RETR>");
 			l_ptr->retransm_queue_head = mod(++r_q_head);
@@ -1554,7 +1554,7 @@
 	buf = l_ptr->proto_msg_queue;
 	if (buf) {
 		msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
-		msg_set_bcast_ack(buf_msg(buf),l_ptr->owner->bclink.last_in); 
+		msg_set_bcast_ack(buf_msg(buf),l_ptr->owner->bclink.last_in);
 		if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
 			msg_dbg(buf_msg(buf), ">DEF-PROT>");
 			l_ptr->unacked_window = 0;
@@ -1578,7 +1578,7 @@
 
 		if (mod(next - first) < l_ptr->queue_limit[0]) {
 			msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
-			msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 
+			msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
 			if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
 				if (msg_user(msg) == MSG_BUNDLER)
 					msg_set_type(msg, CLOSED_MSG);
@@ -1629,12 +1629,12 @@
 
 	tipc_node_lock(n_ptr);
 
-	warn("Resetting all links to %s\n", 
+	warn("Resetting all links to %s\n",
 	     addr_string_fill(addr_string, n_ptr->addr));
 
 	for (i = 0; i < MAX_BEARERS; i++) {
 		if (n_ptr->links[i]) {
-			link_print(n_ptr->links[i], TIPC_OUTPUT, 
+			link_print(n_ptr->links[i], TIPC_OUTPUT,
 				   "Resetting link\n");
 			tipc_link_reset(n_ptr->links[i]);
 		}
@@ -1689,7 +1689,7 @@
 	}
 }
 
-void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, 
+void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf,
 			  u32 retransmits)
 {
 	struct tipc_msg *msg;
@@ -1698,7 +1698,7 @@
 		return;
 
 	msg = buf_msg(buf);
-	
+
 	dbg("Retransmitting %u in link %x\n", retransmits, l_ptr);
 
 	if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
@@ -1728,7 +1728,7 @@
 	while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) {
 		msg = buf_msg(buf);
 		msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
-		msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 
+		msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
 		if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
 			msg_dbg(buf_msg(buf), ">RETR>");
 			buf = buf->next;
@@ -1746,7 +1746,7 @@
 	l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0;
 }
 
-/* 
+/*
  * link_recv_non_seq: Receive packets which are outside
  *                    the link sequence flow
  */
@@ -1761,11 +1761,11 @@
 		tipc_bclink_recv_pkt(buf);
 }
 
-/** 
+/**
  * link_insert_deferred_queue - insert deferred messages back into receive chain
  */
 
-static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr, 
+static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr,
 						  struct sk_buff *buf)
 {
 	u32 seq_no;
@@ -1813,11 +1813,11 @@
 			link_recv_non_seq(buf);
 			continue;
 		}
-		
+
 		if (unlikely(!msg_short(msg) &&
 			     (msg_destnode(msg) != tipc_own_addr)))
 			goto cont;
-		
+
 		n_ptr = tipc_node_find(msg_prevnode(msg));
 		if (unlikely(!n_ptr))
 			goto cont;
@@ -1828,8 +1828,8 @@
 			tipc_node_unlock(n_ptr);
 			goto cont;
 		}
-		/* 
-		 * Release acked messages 
+		/*
+		 * Release acked messages
 		 */
 		if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) {
 			if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported)
@@ -1837,7 +1837,7 @@
 		}
 
 		crs = l_ptr->first_out;
-		while ((crs != l_ptr->next_out) && 
+		while ((crs != l_ptr->next_out) &&
 		       less_eq(msg_seqno(buf_msg(crs)), ackd)) {
 			struct sk_buff *next = crs->next;
 
@@ -1875,7 +1875,7 @@
 					switch (msg_user(msg)) {
 					case MSG_BUNDLER:
 						l_ptr->stats.recv_bundles++;
-						l_ptr->stats.recv_bundled += 
+						l_ptr->stats.recv_bundled +=
 							msg_msgcnt(msg);
 						tipc_node_unlock(n_ptr);
 						tipc_link_recv_bundle(buf);
@@ -1894,7 +1894,7 @@
 						continue;
 					case MSG_FRAGMENTER:
 						l_ptr->stats.recv_fragments++;
-						if (tipc_link_recv_fragment(&l_ptr->defragm_buf, 
+						if (tipc_link_recv_fragment(&l_ptr->defragm_buf,
 									    &buf, &msg)) {
 							l_ptr->stats.recv_fragmented++;
 							goto deliver;
@@ -1905,7 +1905,7 @@
 						if (link_recv_changeover_msg(&l_ptr, &buf)) {
 							msg = buf_msg(buf);
 							seq_no = msg_seqno(msg);
-							TIPC_SKB_CB(buf)->handle 
+							TIPC_SKB_CB(buf)->handle
 								= b_ptr;
 							if (type == ORIGINAL_MSG)
 								goto deliver;
@@ -1948,8 +1948,8 @@
 	read_unlock_bh(&tipc_net_lock);
 }
 
-/* 
- * link_defer_buf(): Sort a received out-of-sequence packet 
+/*
+ * link_defer_buf(): Sort a received out-of-sequence packet
  *                   into the deferred reception queue.
  * Returns the increase of the queue length,i.e. 0 or 1
  */
@@ -1986,7 +1986,7 @@
 			if (prev)
 				prev->next = buf;
 			else
-				*head = buf;   
+				*head = buf;
 			return 1;
 		}
 		if (seq_no == msg_seqno(msg)) {
@@ -2003,11 +2003,11 @@
 	return 0;
 }
 
-/** 
+/**
  * link_handle_out_of_seq_msg - handle arrival of out-of-sequence packet
  */
 
-static void link_handle_out_of_seq_msg(struct link *l_ptr, 
+static void link_handle_out_of_seq_msg(struct link *l_ptr,
 				       struct sk_buff *buf)
 {
 	u32 seq_no = msg_seqno(buf_msg(buf));
@@ -2017,14 +2017,14 @@
 		return;
 	}
 
-	dbg("rx OOS msg: seq_no %u, expecting %u (%u)\n", 
+	dbg("rx OOS msg: seq_no %u, expecting %u (%u)\n",
 	    seq_no, mod(l_ptr->next_in_no), l_ptr->next_in_no);
 
 	/* Record OOS packet arrival (force mismatch on next timeout) */
 
 	l_ptr->checkpoint--;
 
-	/* 
+	/*
 	 * Discard packet if a duplicate; otherwise add it to deferred queue
 	 * and notify peer of gap as per protocol specification
 	 */
@@ -2053,13 +2053,13 @@
 {
 	struct sk_buff *buf = NULL;
 	struct tipc_msg *msg = l_ptr->pmsg;
-        u32 msg_size = sizeof(l_ptr->proto_msg);
+	u32 msg_size = sizeof(l_ptr->proto_msg);
 
 	if (link_blocked(l_ptr))
 		return;
 	msg_set_type(msg, msg_typ);
 	msg_set_net_plane(msg, l_ptr->b_ptr->net_plane);
-	msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); 
+	msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in));
 	msg_set_last_bcast(msg, tipc_bclink_get_last_sent());
 
 	if (msg_typ == STATE_MSG) {
@@ -2082,23 +2082,23 @@
 		msg_set_max_pkt(msg, ack_mtu);
 		msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
 		msg_set_probe(msg, probe_msg != 0);
-		if (probe_msg) { 
+		if (probe_msg) {
 			u32 mtu = l_ptr->max_pkt;
 
-                        if ((mtu < l_ptr->max_pkt_target) &&
+			if ((mtu < l_ptr->max_pkt_target) &&
 			    link_working_working(l_ptr) &&
 			    l_ptr->fsm_msg_cnt) {
 				msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3;
-                                if (l_ptr->max_pkt_probes == 10) {
-                                        l_ptr->max_pkt_target = (msg_size - 4);
-                                        l_ptr->max_pkt_probes = 0;
+				if (l_ptr->max_pkt_probes == 10) {
+					l_ptr->max_pkt_target = (msg_size - 4);
+					l_ptr->max_pkt_probes = 0;
 					msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3;
-                                }
+				}
 				l_ptr->max_pkt_probes++;
-                        }
+			}
 
 			l_ptr->stats.sent_probes++;
-                }
+		}
 		l_ptr->stats.sent_states++;
 	} else {		/* RESET_MSG or ACTIVATE_MSG */
 		msg_set_ack(msg, mod(l_ptr->reset_checkpoint - 1));
@@ -2144,7 +2144,7 @@
 		return;
 
 	memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg));
-        msg_set_size(buf_msg(buf), msg_size);
+	msg_set_size(buf_msg(buf), msg_size);
 
 	if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
 		l_ptr->unacked_window = 0;
@@ -2160,15 +2160,15 @@
 
 /*
  * Receive protocol message :
- * Note that network plane id propagates through the network, and may 
- * change at any time. The node with lowest address rules    
+ * Note that network plane id propagates through the network, and may
+ * change at any time. The node with lowest address rules
  */
 
 static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf)
 {
 	u32 rec_gap = 0;
 	u32 max_pkt_info;
-        u32 max_pkt_ack;
+	u32 max_pkt_ack;
 	u32 msg_tol;
 	struct tipc_msg *msg = buf_msg(buf);
 
@@ -2188,12 +2188,12 @@
 	l_ptr->owner->permit_changeover = msg_redundant_link(msg);
 
 	switch (msg_type(msg)) {
-	
+
 	case RESET_MSG:
 		if (!link_working_unknown(l_ptr) && l_ptr->peer_session) {
 			if (msg_session(msg) == l_ptr->peer_session) {
 				dbg("Duplicate RESET: %u<->%u\n",
-				    msg_session(msg), l_ptr->peer_session);                                     
+				    msg_session(msg), l_ptr->peer_session);
 				break; /* duplicate: ignore */
 			}
 		}
@@ -2211,13 +2211,13 @@
 			l_ptr->priority = msg_linkprio(msg);
 
 		max_pkt_info = msg_max_pkt(msg);
-                if (max_pkt_info) {
+		if (max_pkt_info) {
 			if (max_pkt_info < l_ptr->max_pkt_target)
 				l_ptr->max_pkt_target = max_pkt_info;
 			if (l_ptr->max_pkt > l_ptr->max_pkt_target)
 				l_ptr->max_pkt = l_ptr->max_pkt_target;
 		} else {
-                        l_ptr->max_pkt = l_ptr->max_pkt_target;
+			l_ptr->max_pkt = l_ptr->max_pkt_target;
 		}
 		l_ptr->owner->bclink.supported = (max_pkt_info != 0);
 
@@ -2235,8 +2235,8 @@
 
 		if ((msg_tol = msg_link_tolerance(msg)))
 			link_set_supervision_props(l_ptr, msg_tol);
-		
-		if (msg_linkprio(msg) && 
+
+		if (msg_linkprio(msg) &&
 		    (msg_linkprio(msg) != l_ptr->priority)) {
 			warn("Resetting link <%s>, priority change %u->%u\n",
 			     l_ptr->name, l_ptr->priority, msg_linkprio(msg));
@@ -2250,25 +2250,25 @@
 			break;
 
 		if (less_eq(mod(l_ptr->next_in_no), msg_next_sent(msg))) {
-			rec_gap = mod(msg_next_sent(msg) - 
+			rec_gap = mod(msg_next_sent(msg) -
 				      mod(l_ptr->next_in_no));
 		}
 
 		max_pkt_ack = msg_max_pkt(msg);
-                if (max_pkt_ack > l_ptr->max_pkt) {
-                        dbg("Link <%s> updated MTU %u -> %u\n",
-                            l_ptr->name, l_ptr->max_pkt, max_pkt_ack);
-                        l_ptr->max_pkt = max_pkt_ack;
-                        l_ptr->max_pkt_probes = 0;
-                }
+		if (max_pkt_ack > l_ptr->max_pkt) {
+			dbg("Link <%s> updated MTU %u -> %u\n",
+			    l_ptr->name, l_ptr->max_pkt, max_pkt_ack);
+			l_ptr->max_pkt = max_pkt_ack;
+			l_ptr->max_pkt_probes = 0;
+		}
 
 		max_pkt_ack = 0;
-                if (msg_probe(msg)) {
+		if (msg_probe(msg)) {
 			l_ptr->stats.recv_probes++;
-                        if (msg_size(msg) > sizeof(l_ptr->proto_msg)) {
-                                max_pkt_ack = msg_size(msg);
-                        }
-                }
+			if (msg_size(msg) > sizeof(l_ptr->proto_msg)) {
+				max_pkt_ack = msg_size(msg);
+			}
+		}
 
 		/* Protocol message before retransmits, reduce loss risk */
 
@@ -2294,11 +2294,11 @@
 
 
 /*
- * tipc_link_tunnel(): Send one message via a link belonging to 
+ * tipc_link_tunnel(): Send one message via a link belonging to
  * another bearer. Owner node is locked.
  */
-void tipc_link_tunnel(struct link *l_ptr, 
-		      struct tipc_msg *tunnel_hdr, 
+void tipc_link_tunnel(struct link *l_ptr,
+		      struct tipc_msg *tunnel_hdr,
 		      struct tipc_msg  *msg,
 		      u32 selector)
 {
@@ -2374,7 +2374,7 @@
 		return;
 	}
 
-	split_bundles = (l_ptr->owner->active_links[0] != 
+	split_bundles = (l_ptr->owner->active_links[0] !=
 			 l_ptr->owner->active_links[1]);
 
 	while (crs) {
@@ -2418,7 +2418,7 @@
 		if (msg_user(msg) == MSG_BUNDLER)
 			msg_set_type(msg, CLOSED_MSG);
 		msg_set_ack(msg, mod(l_ptr->next_in_no - 1));	/* Update */
-		msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 
+		msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
 		msg_set_size(&tunnel_hdr, length + INT_H_SIZE);
 		outbuf = buf_acquire(length + INT_H_SIZE);
 		if (outbuf == NULL) {
@@ -2445,7 +2445,7 @@
  * @skb: encapsulating message buffer
  * @from_pos: offset to extract from
  *
- * Returns a new message buffer containing an embedded message.  The 
+ * Returns a new message buffer containing an embedded message.  The
  * encapsulating message itself is left unchanged.
  */
 
@@ -2461,7 +2461,7 @@
 	return eb;
 }
 
-/* 
+/*
  *  link_recv_changeover_msg(): Receive tunneled packet sent
  *  via other link. Node is locked. Return extracted buffer.
  */
@@ -2482,7 +2482,7 @@
 		goto exit;
 	}
 	if (dest_link == *l_ptr) {
-		err("Unexpected changeover message on link <%s>\n", 
+		err("Unexpected changeover message on link <%s>\n",
 		    (*l_ptr)->name);
 		goto exit;
 	}
@@ -2582,9 +2582,9 @@
  */
 
 
-/* 
+/*
  * tipc_link_send_long_buf: Entry for buffers needing fragmentation.
- * The buffer is complete, inclusive total message length. 
+ * The buffer is complete, inclusive total message length.
  * Returns user data length.
  */
 int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
@@ -2650,9 +2650,9 @@
 	return dsz;
 }
 
-/* 
- * A pending message being re-assembled must store certain values 
- * to handle subsequent fragments correctly. The following functions 
+/*
+ * A pending message being re-assembled must store certain values
+ * to handle subsequent fragments correctly. The following functions
  * help storing these values in unused, available fields in the
  * pending message. This makes dynamic memory allocation unecessary.
  */
@@ -2692,11 +2692,11 @@
 	msg_incr_reroute_cnt(buf_msg(buf));
 }
 
-/* 
- * tipc_link_recv_fragment(): Called with node lock on. Returns 
+/*
+ * tipc_link_recv_fragment(): Called with node lock on. Returns
  * the reassembled buffer if message is complete.
  */
-int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, 
+int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
 			    struct tipc_msg **m)
 {
 	struct sk_buff *prev = NULL;
@@ -2737,9 +2737,9 @@
 
 			/*  Prepare buffer for subsequent fragments. */
 
-			set_long_msg_seqno(pbuf, long_msg_seq_no); 
-			set_fragm_size(pbuf,fragm_sz); 
-			set_expected_frags(pbuf,exp_fragm_cnt - 1); 
+			set_long_msg_seqno(pbuf, long_msg_seq_no);
+			set_fragm_size(pbuf,fragm_sz);
+			set_expected_frags(pbuf,exp_fragm_cnt - 1);
 		} else {
 			warn("Link unable to reassemble fragmented message\n");
 		}
@@ -2765,7 +2765,7 @@
 			*m = buf_msg(pbuf);
 			return 1;
 		}
-		set_expected_frags(pbuf,exp_frags);     
+		set_expected_frags(pbuf,exp_frags);
 		return 0;
 	}
 	dbg(" Discarding orphan fragment %x\n",fbuf);
@@ -2849,10 +2849,10 @@
  * link_find_link - locate link by name
  * @name - ptr to link name string
  * @node - ptr to area to be filled with ptr to associated node
- * 
+ *
  * Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted;
  * this also prevents link deletion.
- * 
+ *
  * Returns pointer to link (or 0 if invalid link name).
  */
 
@@ -2860,7 +2860,7 @@
 {
 	struct link_name link_name_parts;
 	struct bearer *b_ptr;
-	struct link *l_ptr; 
+	struct link *l_ptr;
 
 	if (!link_name_validate(name, &link_name_parts))
 		return NULL;
@@ -2869,7 +2869,7 @@
 	if (!b_ptr)
 		return NULL;
 
-	*node = tipc_node_find(link_name_parts.addr_peer); 
+	*node = tipc_node_find(link_name_parts.addr_peer);
 	if (!*node)
 		return NULL;
 
@@ -2880,14 +2880,14 @@
 	return l_ptr;
 }
 
-struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, 
+struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space,
 				     u16 cmd)
 {
 	struct tipc_link_config *args;
-        u32 new_value;
+	u32 new_value;
 	struct link *l_ptr;
 	struct node *node;
-        int res;
+	int res;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG))
 		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -2899,40 +2899,40 @@
 		if ((cmd == TIPC_CMD_SET_LINK_WINDOW) &&
 		    (tipc_bclink_set_queue_limits(new_value) == 0))
 			return tipc_cfg_reply_none();
-	       	return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
 						   " (cannot change setting on broadcast link)");
 	}
 
 	read_lock_bh(&tipc_net_lock);
-	l_ptr = link_find_link(args->name, &node); 
+	l_ptr = link_find_link(args->name, &node);
 	if (!l_ptr) {
 		read_unlock_bh(&tipc_net_lock);
-	       	return tipc_cfg_reply_error_string("link not found");
+		return tipc_cfg_reply_error_string("link not found");
 	}
 
 	tipc_node_lock(node);
 	res = -EINVAL;
 	switch (cmd) {
-	case TIPC_CMD_SET_LINK_TOL: 
-		if ((new_value >= TIPC_MIN_LINK_TOL) && 
+	case TIPC_CMD_SET_LINK_TOL:
+		if ((new_value >= TIPC_MIN_LINK_TOL) &&
 		    (new_value <= TIPC_MAX_LINK_TOL)) {
 			link_set_supervision_props(l_ptr, new_value);
-			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 
+			tipc_link_send_proto_msg(l_ptr, STATE_MSG,
 						 0, 0, new_value, 0, 0);
 			res = TIPC_OK;
 		}
 		break;
-	case TIPC_CMD_SET_LINK_PRI: 
+	case TIPC_CMD_SET_LINK_PRI:
 		if ((new_value >= TIPC_MIN_LINK_PRI) &&
 		    (new_value <= TIPC_MAX_LINK_PRI)) {
 			l_ptr->priority = new_value;
-			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 
+			tipc_link_send_proto_msg(l_ptr, STATE_MSG,
 						 0, 0, 0, new_value, 0);
 			res = TIPC_OK;
 		}
 		break;
-	case TIPC_CMD_SET_LINK_WINDOW: 
-		if ((new_value >= TIPC_MIN_LINK_WIN) && 
+	case TIPC_CMD_SET_LINK_WINDOW:
+		if ((new_value >= TIPC_MIN_LINK_WIN) &&
 		    (new_value <= TIPC_MAX_LINK_WIN)) {
 			tipc_link_set_queue_limits(l_ptr, new_value);
 			res = TIPC_OK;
@@ -2943,7 +2943,7 @@
 
 	read_unlock_bh(&tipc_net_lock);
 	if (res)
-	       	return tipc_cfg_reply_error_string("cannot change link setting");
+		return tipc_cfg_reply_error_string("cannot change link setting");
 
 	return tipc_cfg_reply_none();
 }
@@ -2963,7 +2963,7 @@
 struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space)
 {
 	char *link_name;
-	struct link *l_ptr; 
+	struct link *l_ptr;
 	struct node *node;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
@@ -2977,7 +2977,7 @@
 	}
 
 	read_lock_bh(&tipc_net_lock);
-	l_ptr = link_find_link(link_name, &node); 
+	l_ptr = link_find_link(link_name, &node);
 	if (!l_ptr) {
 		read_unlock_bh(&tipc_net_lock);
 		return tipc_cfg_reply_error_string("link not found");
@@ -3004,14 +3004,14 @@
  * @name: link name
  * @buf: print buffer area
  * @buf_size: size of print buffer area
- * 
+ *
  * Returns length of print buffer data string (or 0 if error)
  */
 
 static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
 {
 	struct print_buf pb;
-	struct link *l_ptr; 
+	struct link *l_ptr;
 	struct node *node;
 	char *status;
 	u32 profile_total = 0;
@@ -3022,7 +3022,7 @@
 	tipc_printbuf_init(&pb, buf, buf_size);
 
 	read_lock_bh(&tipc_net_lock);
-	l_ptr = link_find_link(name, &node); 
+	l_ptr = link_find_link(name, &node);
 	if (!l_ptr) {
 		read_unlock_bh(&tipc_net_lock);
 		return 0;
@@ -3036,28 +3036,28 @@
 	else
 		status = "DEFUNCT";
 	tipc_printf(&pb, "Link <%s>\n"
-		         "  %s  MTU:%u  Priority:%u  Tolerance:%u ms"
-		         "  Window:%u packets\n", 
-		    l_ptr->name, status, link_max_pkt(l_ptr), 
+			 "  %s  MTU:%u  Priority:%u  Tolerance:%u ms"
+			 "  Window:%u packets\n",
+		    l_ptr->name, status, link_max_pkt(l_ptr),
 		    l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]);
-	tipc_printf(&pb, "  RX packets:%u fragments:%u/%u bundles:%u/%u\n", 
+	tipc_printf(&pb, "  RX packets:%u fragments:%u/%u bundles:%u/%u\n",
 		    l_ptr->next_in_no - l_ptr->stats.recv_info,
 		    l_ptr->stats.recv_fragments,
 		    l_ptr->stats.recv_fragmented,
 		    l_ptr->stats.recv_bundles,
 		    l_ptr->stats.recv_bundled);
-	tipc_printf(&pb, "  TX packets:%u fragments:%u/%u bundles:%u/%u\n", 
+	tipc_printf(&pb, "  TX packets:%u fragments:%u/%u bundles:%u/%u\n",
 		    l_ptr->next_out_no - l_ptr->stats.sent_info,
 		    l_ptr->stats.sent_fragments,
-		    l_ptr->stats.sent_fragmented, 
+		    l_ptr->stats.sent_fragmented,
 		    l_ptr->stats.sent_bundles,
 		    l_ptr->stats.sent_bundled);
 	profile_total = l_ptr->stats.msg_length_counts;
 	if (!profile_total)
 		profile_total = 1;
 	tipc_printf(&pb, "  TX profile sample:%u packets  average:%u octets\n"
-		         "  0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
-		         "-16354:%u%% -32768:%u%% -66000:%u%%\n",
+			 "  0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
+			 "-16354:%u%% -32768:%u%% -66000:%u%%\n",
 		    l_ptr->stats.msg_length_counts,
 		    l_ptr->stats.msg_lengths_total / profile_total,
 		    percent(l_ptr->stats.msg_length_profile[0], profile_total),
@@ -3067,21 +3067,21 @@
 		    percent(l_ptr->stats.msg_length_profile[4], profile_total),
 		    percent(l_ptr->stats.msg_length_profile[5], profile_total),
 		    percent(l_ptr->stats.msg_length_profile[6], profile_total));
-	tipc_printf(&pb, "  RX states:%u probes:%u naks:%u defs:%u dups:%u\n", 
+	tipc_printf(&pb, "  RX states:%u probes:%u naks:%u defs:%u dups:%u\n",
 		    l_ptr->stats.recv_states,
 		    l_ptr->stats.recv_probes,
 		    l_ptr->stats.recv_nacks,
-		    l_ptr->stats.deferred_recv, 
+		    l_ptr->stats.deferred_recv,
 		    l_ptr->stats.duplicates);
-	tipc_printf(&pb, "  TX states:%u probes:%u naks:%u acks:%u dups:%u\n", 
-		    l_ptr->stats.sent_states, 
-		    l_ptr->stats.sent_probes, 
-		    l_ptr->stats.sent_nacks, 
-		    l_ptr->stats.sent_acks, 
+	tipc_printf(&pb, "  TX states:%u probes:%u naks:%u acks:%u dups:%u\n",
+		    l_ptr->stats.sent_states,
+		    l_ptr->stats.sent_probes,
+		    l_ptr->stats.sent_nacks,
+		    l_ptr->stats.sent_acks,
 		    l_ptr->stats.retransmitted);
 	tipc_printf(&pb, "  Congestion bearer:%u link:%u  Send queue max:%u avg:%u\n",
 		    l_ptr->stats.bearer_congs,
-		    l_ptr->stats.link_congs, 
+		    l_ptr->stats.link_congs,
 		    l_ptr->stats.max_queue_sz,
 		    l_ptr->stats.queue_sz_counts
 		    ? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts)
@@ -3113,7 +3113,7 @@
 				  (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO);
 	if (!str_len) {
 		buf_discard(buf);
-	       	return tipc_cfg_reply_error_string("link not found");
+		return tipc_cfg_reply_error_string("link not found");
 	}
 
 	skb_put(buf, TLV_SPACE(str_len));
@@ -3164,7 +3164,7 @@
  * tipc_link_get_max_pkt - get maximum packet size to use when sending to destination
  * @dest: network address of destination node
  * @selector: used to select from set of active links
- * 
+ *
  * If no active link can be found, uses default maximum packet size.
  */
 
@@ -3173,11 +3173,11 @@
 	struct node *n_ptr;
 	struct link *l_ptr;
 	u32 res = MAX_PKT_DEFAULT;
-	
+
 	if (dest == tipc_own_addr)
 		return MAX_MSG_SIZE;
 
-	read_lock_bh(&tipc_net_lock);        
+	read_lock_bh(&tipc_net_lock);
 	n_ptr = tipc_node_select(dest, selector);
 	if (n_ptr) {
 		tipc_node_lock(n_ptr);
@@ -3186,7 +3186,7 @@
 			res = link_max_pkt(l_ptr);
 		tipc_node_unlock(n_ptr);
 	}
-	read_unlock_bh(&tipc_net_lock);       
+	read_unlock_bh(&tipc_net_lock);
 	return res;
 }
 
@@ -3244,8 +3244,8 @@
 		tipc_printf(buf, "%u]",
 			    msg_seqno(buf_msg
 				      (l_ptr->last_out)), l_ptr->out_queue_size);
-		if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) - 
-			 msg_seqno(buf_msg(l_ptr->first_out))) 
+		if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) -
+			 msg_seqno(buf_msg(l_ptr->first_out)))
 		     != (l_ptr->out_queue_size - 1))
 		    || (l_ptr->last_out->next != 0)) {
 			tipc_printf(buf, "\nSend queue inconsistency\n");
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 2d3c157..52f3e7c 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/link.h: Include file for TIPC link code
- * 
+ *
  * Copyright (c) 1995-2006, Ericsson AB
  * Copyright (c) 2004-2005, Wind River Systems
  * All rights reserved.
@@ -45,8 +45,8 @@
 #define PUSH_FAILED   1
 #define PUSH_FINISHED 2
 
-/* 
- * Link states 
+/*
+ * Link states
  */
 
 #define WORKING_WORKING 560810u
@@ -54,7 +54,7 @@
 #define RESET_UNKNOWN   560812u
 #define RESET_RESET     560813u
 
-/* 
+/*
  * Starting value for maximum packet size negotiation on unicast links
  * (unless bearer MTU is less)
  */
@@ -74,7 +74,7 @@
  * @peer_session: link session # being used by peer end of link
  * @peer_bearer_id: bearer id used by link's peer endpoint
  * @b_ptr: pointer to bearer used by link
- * @tolerance: minimum link continuity loss needed to reset link [in ms] 
+ * @tolerance: minimum link continuity loss needed to reset link [in ms]
  * @continuity_interval: link continuity testing interval [in ms]
  * @abort_limit: # of unacknowledged continuity probes needed to reset link
  * @state: current state of link FSM
@@ -110,7 +110,7 @@
  * @stats: collects statistics regarding link activity
  * @print_buf: print buffer used to log link activity
  */
- 
+
 struct link {
 	u32 addr;
 	char name[TIPC_MAX_LINK_NAME];
@@ -143,18 +143,18 @@
 	u32 exp_msg_count;
 	u32 reset_checkpoint;
 
-        /* Max packet negotiation */
-        u32 max_pkt;
-        u32 max_pkt_target;
-        u32 max_pkt_probes;
+	/* Max packet negotiation */
+	u32 max_pkt;
+	u32 max_pkt_target;
+	u32 max_pkt_probes;
 
 	/* Sending */
 	u32 out_queue_size;
 	struct sk_buff *first_out;
 	struct sk_buff *last_out;
 	u32 next_out_no;
-        u32 last_retransmitted;
-        u32 stale_count;
+	u32 last_retransmitted;
+	u32 stale_count;
 
 	/* Reception */
 	u32 next_in_no;
@@ -174,7 +174,7 @@
 	u32 long_msg_seq_no;
 	struct sk_buff *defragm_buf;
 
-        /* Statistics */
+	/* Statistics */
 	struct {
 		u32 sent_info;		/* used in counting # sent packets */
 		u32 recv_info;		/* used in counting # recv'd packets */
@@ -239,9 +239,9 @@
 int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector);
 int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf);
 u32 tipc_link_get_max_pkt(u32 dest,u32 selector);
-int tipc_link_send_sections_fast(struct port* sender, 
+int tipc_link_send_sections_fast(struct port* sender,
 				 struct iovec const *msg_sect,
-				 const u32 num_sect, 
+				 const u32 num_sect,
 				 u32 destnode);
 int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf);
 void tipc_link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr,
@@ -250,7 +250,7 @@
 int  tipc_link_recv_fragment(struct sk_buff **pending,
 			     struct sk_buff **fb,
 			     struct tipc_msg **msg);
-void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap, 
+void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap,
 			      u32 tolerance, u32 priority, u32 acked_mtu);
 void tipc_link_push_queue(struct link *l_ptr);
 u32 tipc_link_defer_pkt(struct sk_buff **head, struct sk_buff **tail,
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 3bd345a..7824854 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/msg.c: TIPC message header routines
- *     
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 6699aaf..62d5490 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/msg.h: Include file for TIPC message header routines
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -56,10 +56,10 @@
 
 /*
 		TIPC user data message header format, version 2
-		
+
 	- Fundamental definitions available to privileged TIPC users
 	  are located in tipc_msg.h.
-	- Remaining definitions available to TIPC internal users appear below. 
+	- Remaining definitions available to TIPC internal users appear below.
 */
 
 
@@ -75,7 +75,7 @@
 	msg_set_word(m, w, (word |= (val << pos)));
 }
 
-/* 
+/*
  * Word 0
  */
 
@@ -84,7 +84,7 @@
 	return msg_bits(m, 0, 29, 7);
 }
 
-static inline void msg_set_version(struct tipc_msg *m) 
+static inline void msg_set_version(struct tipc_msg *m)
 {
 	msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION);
 }
@@ -99,47 +99,47 @@
 	return (msg_user(m) <= DATA_CRITICAL);
 }
 
-static inline void msg_set_user(struct tipc_msg *m, u32 n) 
+static inline void msg_set_user(struct tipc_msg *m, u32 n)
 {
 	msg_set_bits(m, 0, 25, 0xf, n);
 }
 
-static inline void msg_set_importance(struct tipc_msg *m, u32 i) 
+static inline void msg_set_importance(struct tipc_msg *m, u32 i)
 {
 	msg_set_user(m, i);
 }
 
-static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n) 
+static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n)
 {
 	msg_set_bits(m, 0, 21, 0xf, n>>2);
 }
 
-static inline int msg_non_seq(struct tipc_msg *m) 
+static inline int msg_non_seq(struct tipc_msg *m)
 {
 	return msg_bits(m, 0, 20, 1);
 }
 
-static inline void msg_set_non_seq(struct tipc_msg *m) 
+static inline void msg_set_non_seq(struct tipc_msg *m)
 {
 	msg_set_bits(m, 0, 20, 1, 1);
 }
 
-static inline int msg_dest_droppable(struct tipc_msg *m) 
+static inline int msg_dest_droppable(struct tipc_msg *m)
 {
 	return msg_bits(m, 0, 19, 1);
 }
 
-static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d) 
+static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d)
 {
 	msg_set_bits(m, 0, 19, 1, d);
 }
 
-static inline int msg_src_droppable(struct tipc_msg *m) 
+static inline int msg_src_droppable(struct tipc_msg *m)
 {
 	return msg_bits(m, 0, 18, 1);
 }
 
-static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d) 
+static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d)
 {
 	msg_set_bits(m, 0, 18, 1, d);
 }
@@ -150,31 +150,31 @@
 }
 
 
-/* 
+/*
  * Word 1
  */
 
-static inline void msg_set_type(struct tipc_msg *m, u32 n) 
+static inline void msg_set_type(struct tipc_msg *m, u32 n)
 {
 	msg_set_bits(m, 1, 29, 0x7, n);
 }
 
-static inline void msg_set_errcode(struct tipc_msg *m, u32 err) 
+static inline void msg_set_errcode(struct tipc_msg *m, u32 err)
 {
 	msg_set_bits(m, 1, 25, 0xf, err);
 }
 
-static inline u32 msg_reroute_cnt(struct tipc_msg *m) 
+static inline u32 msg_reroute_cnt(struct tipc_msg *m)
 {
 	return msg_bits(m, 1, 21, 0xf);
 }
 
-static inline void msg_incr_reroute_cnt(struct tipc_msg *m) 
+static inline void msg_incr_reroute_cnt(struct tipc_msg *m)
 {
 	msg_set_bits(m, 1, 21, 0xf, msg_reroute_cnt(m) + 1);
 }
 
-static inline void msg_reset_reroute_cnt(struct tipc_msg *m) 
+static inline void msg_reset_reroute_cnt(struct tipc_msg *m)
 {
 	msg_set_bits(m, 1, 21, 0xf, 0);
 }
@@ -184,12 +184,12 @@
 	return msg_bits(m, 1, 19, 0x3);
 }
 
-static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n) 
+static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n)
 {
 	msg_set_bits(m, 1, 19, 0x3, n);
 }
 
-static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz) 
+static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz)
 {
 	u32 hsz = msg_hdr_sz(m);
 	char *to = (char *)&m->hdr[hsz/4];
@@ -206,13 +206,13 @@
 	return msg_bits(m, 1, 0, 0xffff);
 }
 
-static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) 
+static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n)
 {
 	msg_set_bits(m, 1, 0, 0xffff, n);
 }
 
 
-/* 
+/*
  * Word 2
  */
 
@@ -221,7 +221,7 @@
 	return msg_bits(m, 2, 16, 0xffff);
 }
 
-static inline void msg_set_ack(struct tipc_msg *m, u32 n) 
+static inline void msg_set_ack(struct tipc_msg *m, u32 n)
 {
 	msg_set_bits(m, 2, 16, 0xffff, n);
 }
@@ -231,48 +231,48 @@
 	return msg_bits(m, 2, 0, 0xffff);
 }
 
-static inline void msg_set_seqno(struct tipc_msg *m, u32 n) 
+static inline void msg_set_seqno(struct tipc_msg *m, u32 n)
 {
 	msg_set_bits(m, 2, 0, 0xffff, n);
 }
 
 
-/* 
+/*
  * Words 3-10
  */
 
 
-static inline void msg_set_prevnode(struct tipc_msg *m, u32 a) 
+static inline void msg_set_prevnode(struct tipc_msg *m, u32 a)
 {
 	msg_set_word(m, 3, a);
 }
 
-static inline void msg_set_origport(struct tipc_msg *m, u32 p) 
+static inline void msg_set_origport(struct tipc_msg *m, u32 p)
 {
 	msg_set_word(m, 4, p);
 }
 
-static inline void msg_set_destport(struct tipc_msg *m, u32 p) 
+static inline void msg_set_destport(struct tipc_msg *m, u32 p)
 {
 	msg_set_word(m, 5, p);
 }
 
-static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p) 
+static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p)
 {
 	msg_set_word(m, 5, p);
 }
 
-static inline void msg_set_orignode(struct tipc_msg *m, u32 a) 
+static inline void msg_set_orignode(struct tipc_msg *m, u32 a)
 {
 	msg_set_word(m, 6, a);
 }
 
-static inline void msg_set_destnode(struct tipc_msg *m, u32 a) 
+static inline void msg_set_destnode(struct tipc_msg *m, u32 a)
 {
 	msg_set_word(m, 7, a);
 }
 
-static inline int msg_is_dest(struct tipc_msg *m, u32 d) 
+static inline int msg_is_dest(struct tipc_msg *m, u32 d)
 {
 	return(msg_short(m) || (msg_destnode(m) == d));
 }
@@ -284,7 +284,7 @@
 	return(msg_destnode(m) ^ msg_orignode(m)) >> 11;
 }
 
-static inline void msg_set_nametype(struct tipc_msg *m, u32 n) 
+static inline void msg_set_nametype(struct tipc_msg *m, u32 n)
 {
 	msg_set_word(m, 8, n);
 }
@@ -309,17 +309,17 @@
 	msg_set_word(m, 8, n);
 }
 
-static inline void msg_set_namelower(struct tipc_msg *m, u32 n) 
+static inline void msg_set_namelower(struct tipc_msg *m, u32 n)
 {
 	msg_set_word(m, 9, n);
 }
 
-static inline void msg_set_nameinst(struct tipc_msg *m, u32 n) 
+static inline void msg_set_nameinst(struct tipc_msg *m, u32 n)
 {
 	msg_set_namelower(m, n);
 }
 
-static inline void msg_set_nameupper(struct tipc_msg *m, u32 n) 
+static inline void msg_set_nameupper(struct tipc_msg *m, u32 n)
 {
 	msg_set_word(m, 10, n);
 }
@@ -329,7 +329,7 @@
 	return (struct tipc_msg *)msg_data(m);
 }
 
-static inline void msg_expand(struct tipc_msg *m, u32 destnode) 
+static inline void msg_expand(struct tipc_msg *m, u32 destnode)
 {
 	if (!msg_short(m))
 		return;
@@ -344,7 +344,7 @@
 /*
 		TIPC internal message header format, version 2
 
-       1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 
+       1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    w0:|vers |msg usr|hdr sz |n|resrv|            packet size          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -372,9 +372,9 @@
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
       NB: CONN_MANAGER use data message format. LINK_CONFIG has own format.
-*/   
+*/
 
-/* 
+/*
  * Internal users
  */
 
@@ -390,7 +390,7 @@
 #define  INT_H_SIZE           40
 #define  DSC_H_SIZE           40
 
-/* 
+/*
  *  Connection management protocol messages
  */
 
@@ -398,7 +398,7 @@
 #define CONN_PROBE_REPLY  1
 #define CONN_ACK          2
 
-/* 
+/*
  * Name distributor messages
  */
 
@@ -406,7 +406,7 @@
 #define WITHDRAWAL        1
 
 
-/* 
+/*
  * Word 1
  */
 
@@ -425,13 +425,13 @@
 	return msg_bits(m, 1, 16, 0xfff);
 }
 
-static inline void msg_set_req_links(struct tipc_msg *m, u32 n) 
+static inline void msg_set_req_links(struct tipc_msg *m, u32 n)
 {
 	msg_set_bits(m, 1, 16, 0xfff, n);
 }
 
 
-/* 
+/*
  * Word 2
  */
 
@@ -440,7 +440,7 @@
 	return msg_word(m, 2);
 }
 
-static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n) 
+static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n)
 {
 	msg_set_word(m, 2, n);
 }
@@ -460,13 +460,13 @@
 	return msg_bits(m, 2, 0, 0xffff);
 }
 
-static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n) 
+static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n)
 {
 	msg_set_bits(m, 2, 0, 0xffff, n);
 }
 
 
-/* 
+/*
  * Word 4
  */
 
@@ -533,7 +533,7 @@
 	msg_set_bits(m, 4, 0, 1, (n & 1));
 }
 
-/* 
+/*
  * Word 5
  */
 
@@ -603,7 +603,7 @@
 }
 
 
-/* 
+/*
  * Word 9
  */
 
@@ -627,12 +627,12 @@
 	msg_set_bits(m, 9, 16, 0xffff, n);
 }
 
-static inline u32 msg_max_pkt(struct tipc_msg *m) 
+static inline u32 msg_max_pkt(struct tipc_msg *m)
 {
 	return (msg_bits(m, 9, 16, 0xffff) * 4);
 }
 
-static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n) 
+static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n)
 {
 	msg_set_bits(m, 9, 16, 0xffff, (n / 4));
 }
@@ -647,7 +647,7 @@
 	msg_set_bits(m, 9, 0, 0xffff, n);
 }
 
-/* 
+/*
  * Routing table message data
  */
 
@@ -672,7 +672,7 @@
 	msg_data(m)[pos + 4] = 1;
 }
 
-/* 
+/*
  * Segmentation message types
  */
 
@@ -680,7 +680,7 @@
 #define FRAGMENT           1
 #define LAST_FRAGMENT      2
 
-/* 
+/*
  * Link management protocol message types
  */
 
@@ -688,13 +688,13 @@
 #define RESET_MSG       1
 #define ACTIVATE_MSG    2
 
-/* 
+/*
  * Changeover tunnel message types
  */
 #define DUPLICATE_MSG    0
 #define ORIGINAL_MSG     1
 
-/* 
+/*
  * Routing table message types
  */
 #define EXT_ROUTING_TABLE    0
@@ -703,7 +703,7 @@
 #define ROUTE_ADDITION       3
 #define ROUTE_REMOVAL        4
 
-/* 
+/*
  * Config protocol message types
  */
 
@@ -724,7 +724,7 @@
 }
 
 
-static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, 
+static inline void msg_init(struct tipc_msg *m, u32 user, u32 type,
 			    u32 err, u32 hsize, u32 destnode)
 {
 	memset(m, 0, hsize);
@@ -741,7 +741,7 @@
 	}
 }
 
-/** 
+/**
  * msg_calc_data_size - determine total data size for message
  */
 
@@ -755,15 +755,15 @@
 	return dsz;
 }
 
-/** 
+/**
  * msg_build - create message using specified header and data
- * 
+ *
  * Note: Caller must not hold any locks in case copy_from_user() is interrupted!
- * 
+ *
  * Returns message data size or errno
  */
 
-static inline int msg_build(struct tipc_msg *hdr, 
+static inline int msg_build(struct tipc_msg *hdr,
 			    struct iovec const *msg_sect, u32 num_sect,
 			    int max_size, int usrmem, struct sk_buff** buf)
 {
@@ -789,11 +789,11 @@
 	memcpy((*buf)->data, (unchar *)hdr, hsz);
 	for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) {
 		if (likely(usrmem))
-			res = !copy_from_user((*buf)->data + pos, 
-					      msg_sect[cnt].iov_base, 
+			res = !copy_from_user((*buf)->data + pos,
+					      msg_sect[cnt].iov_base,
 					      msg_sect[cnt].iov_len);
 		else
-			memcpy((*buf)->data + pos, msg_sect[cnt].iov_base, 
+			memcpy((*buf)->data + pos, msg_sect[cnt].iov_base,
 			       msg_sect[cnt].iov_len);
 		pos += msg_sect[cnt].iov_len;
 	}
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 7bf87cb..39fd161 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/name_distr.c: TIPC name distribution code
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -53,15 +53,15 @@
  * @upper: name sequence upper bound
  * @ref: publishing port reference
  * @key: publication key
- * 
+ *
  * ===> All fields are stored in network byte order. <===
- * 
+ *
  * First 3 fields identify (name or) name sequence being published.
  * Reference field uniquely identifies port that published name sequence.
  * Key field uniquely identifies publication, in the event a port has
  * multiple publications of the same name sequence.
- * 
- * Note: There is no field that identifies the publishing node because it is 
+ *
+ * Note: There is no field that identifies the publishing node because it is
  * the same for all items contained within a publication message.
  */
 
@@ -74,12 +74,12 @@
 };
 
 /**
- * List of externally visible publications by this node -- 
+ * List of externally visible publications by this node --
  * that is, all publications having scope > TIPC_NODE_SCOPE.
  */
 
 static LIST_HEAD(publ_root);
-static u32 publ_cnt = 0;		
+static u32 publ_cnt = 0;
 
 /**
  * publ_to_item - add publication info to a publication message
@@ -101,12 +101,12 @@
 
 static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest)
 {
-	struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size);  
+	struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size);
 	struct tipc_msg *msg;
 
 	if (buf != NULL) {
 		msg = buf_msg(buf);
-		msg_init(msg, NAME_DISTRIBUTOR, type, TIPC_OK, 
+		msg_init(msg, NAME_DISTRIBUTOR, type, TIPC_OK,
 			 LONG_H_SIZE, dest);
 		msg_set_size(msg, LONG_H_SIZE + size);
 	}
@@ -174,7 +174,7 @@
 	u32 rest;
 	u32 max_item_buf;
 
-	read_lock_bh(&tipc_nametbl_lock); 
+	read_lock_bh(&tipc_nametbl_lock);
 	max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE;
 	max_item_buf *= ITEM_SIZE;
 	rest = publ_cnt * ITEM_SIZE;
@@ -183,7 +183,7 @@
 		if (!buf) {
 			left = (rest <= max_item_buf) ? rest : max_item_buf;
 			rest -= left;
-			buf = named_prepare_buf(PUBLICATION, left, node);       
+			buf = named_prepare_buf(PUBLICATION, left, node);
 			if (!buf) {
 				warn("Bulk publication distribution failure\n");
 				goto exit;
@@ -196,20 +196,20 @@
 		if (!left) {
 			msg_set_link_selector(buf_msg(buf), node);
 			dbg("tipc_named_node_up: sending publish msg to "
-			    "<%u.%u.%u>\n", tipc_zone(node), 
+			    "<%u.%u.%u>\n", tipc_zone(node),
 			    tipc_cluster(node), tipc_node(node));
 			tipc_link_send(buf, node, node);
 			buf = NULL;
 		}
 	}
 exit:
-	read_unlock_bh(&tipc_nametbl_lock); 
+	read_unlock_bh(&tipc_nametbl_lock);
 }
 
 /**
  * node_is_down - remove publication associated with a failed node
- * 
- * Invoked for each publication issued by a newly failed node.  
+ *
+ * Invoked for each publication issued by a newly failed node.
  * Removes publication structure from name table & deletes it.
  * In rare cases the link may have come back up again when this
  * function is called, and we have two items representing the same
@@ -221,15 +221,15 @@
 {
 	struct publication *p;
 
-        write_lock_bh(&tipc_nametbl_lock);
-	dbg("node_is_down: withdrawing %u, %u, %u\n", 
+	write_lock_bh(&tipc_nametbl_lock);
+	dbg("node_is_down: withdrawing %u, %u, %u\n",
 	    publ->type, publ->lower, publ->upper);
-        publ->key += 1222345;
-	p = tipc_nametbl_remove_publ(publ->type, publ->lower, 
+	publ->key += 1222345;
+	p = tipc_nametbl_remove_publ(publ->type, publ->lower,
 				     publ->node, publ->ref, publ->key);
 	write_unlock_bh(&tipc_nametbl_lock);
 
-        if (p != publ) {
+	if (p != publ) {
 		err("Unable to remove publication from failed node\n"
 		    "(type=%u, lower=%u, node=0x%x, ref=%u, key=%u)\n",
 		    publ->type, publ->lower, publ->node, publ->ref, publ->key);
@@ -251,27 +251,27 @@
 	struct distr_item *item = (struct distr_item *)msg_data(msg);
 	u32 count = msg_data_sz(msg) / ITEM_SIZE;
 
-	write_lock_bh(&tipc_nametbl_lock); 
+	write_lock_bh(&tipc_nametbl_lock);
 	while (count--) {
 		if (msg_type(msg) == PUBLICATION) {
-			dbg("tipc_named_recv: got publication for %u, %u, %u\n", 
+			dbg("tipc_named_recv: got publication for %u, %u, %u\n",
 			    ntohl(item->type), ntohl(item->lower),
 			    ntohl(item->upper));
-			publ = tipc_nametbl_insert_publ(ntohl(item->type), 
+			publ = tipc_nametbl_insert_publ(ntohl(item->type),
 							ntohl(item->lower),
 							ntohl(item->upper),
 							TIPC_CLUSTER_SCOPE,
-							msg_orignode(msg), 
+							msg_orignode(msg),
 							ntohl(item->ref),
 							ntohl(item->key));
 			if (publ) {
-				tipc_nodesub_subscribe(&publ->subscr, 
-						       msg_orignode(msg), 
+				tipc_nodesub_subscribe(&publ->subscr,
+						       msg_orignode(msg),
 						       publ,
 						       (net_ev_handler)node_is_down);
 			}
 		} else if (msg_type(msg) == WITHDRAWAL) {
-			dbg("tipc_named_recv: got withdrawl for %u, %u, %u\n", 
+			dbg("tipc_named_recv: got withdrawl for %u, %u, %u\n",
 			    ntohl(item->type), ntohl(item->lower),
 			    ntohl(item->upper));
 			publ = tipc_nametbl_remove_publ(ntohl(item->type),
@@ -282,7 +282,7 @@
 
 			if (publ) {
 				tipc_nodesub_unsubscribe(&publ->subscr);
-        			kfree(publ);
+				kfree(publ);
 			} else {
 				err("Unable to remove publication by node 0x%x\n"
 				    "(type=%u, lower=%u, ref=%u, key=%u)\n",
@@ -295,13 +295,13 @@
 		}
 		item++;
 	}
-	write_unlock_bh(&tipc_nametbl_lock); 
+	write_unlock_bh(&tipc_nametbl_lock);
 	buf_discard(buf);
 }
 
 /**
  * tipc_named_reinit - re-initialize local publication list
- * 
+ *
  * This routine is called whenever TIPC networking is (re)enabled.
  * All existing publications by this node that have "cluster" or "zone" scope
  * are updated to reflect the node's current network address.
@@ -312,11 +312,11 @@
 {
 	struct publication *publ;
 
-	write_lock_bh(&tipc_nametbl_lock); 
+	write_lock_bh(&tipc_nametbl_lock);
 	list_for_each_entry(publ, &publ_root, local_list) {
 		if (publ->node == tipc_own_addr)
 			break;
 		publ->node = tipc_own_addr;
 	}
-	write_unlock_bh(&tipc_nametbl_lock); 
+	write_unlock_bh(&tipc_nametbl_lock);
 }
diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h
index 843da01..1e41bdd 100644
--- a/net/tipc/name_distr.h
+++ b/net/tipc/name_distr.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/name_distr.h: Include file for TIPC name distribution code
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 049242e..9dfc912 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/name_table.c: TIPC name table code
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2004-2005, Wind River Systems
  * All rights reserved.
@@ -65,7 +65,7 @@
 	struct publication *zone_list;
 };
 
-/** 
+/**
  * struct name_seq - container for all published instances of a name type
  * @type: 32 bit 'type' value for name sequence
  * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
@@ -89,7 +89,7 @@
 
 /**
  * struct name_table - table containing all existing port name publications
- * @types: pointer to fixed-sized array of name sequence lists, 
+ * @types: pointer to fixed-sized array of name sequence lists,
  *         accessed via hashing on 'type'; name sequence lists are *not* sorted
  * @local_publ_count: number of publications issued by this node
  */
@@ -113,8 +113,8 @@
  * publ_create - create a publication structure
  */
 
-static struct publication *publ_create(u32 type, u32 lower, u32 upper, 
-				       u32 scope, u32 node, u32 port_ref,   
+static struct publication *publ_create(u32 type, u32 lower, u32 upper,
+				       u32 scope, u32 node, u32 port_ref,
 				       u32 key)
 {
 	struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC);
@@ -148,7 +148,7 @@
 
 /**
  * tipc_nameseq_create - create a name sequence structure for the specified 'type'
- * 
+ *
  * Allocates a single sub-sequence structure and sets it to all 0's.
  */
 
@@ -178,7 +178,7 @@
 
 /**
  * nameseq_find_subseq - find sub-sequence (if any) matching a name instance
- *  
+ *
  * Very time-critical, so binary searches through sub-sequence array.
  */
 
@@ -204,7 +204,7 @@
 
 /**
  * nameseq_locate_subseq - determine position of name instance in sub-sequence
- * 
+ *
  * Returns index in sub-sequence array of the entry that contains the specified
  * instance value; if no entry contains that value, returns the position
  * where a new entry for it would be inserted in the array.
@@ -232,7 +232,7 @@
 }
 
 /**
- * tipc_nameseq_insert_publ - 
+ * tipc_nameseq_insert_publ -
  */
 
 static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
@@ -343,8 +343,8 @@
 		}
 	}
 
-	/* 
-	 * Any subscriptions waiting for notification? 
+	/*
+	 * Any subscriptions waiting for notification?
 	 */
 	list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
 		dbg("calling report_overlap()\n");
@@ -352,7 +352,7 @@
 					   publ->lower,
 					   publ->upper,
 					   TIPC_PUBLISHED,
-					   publ->ref, 
+					   publ->ref,
 					   publ->node,
 					   created_subseq);
 	}
@@ -361,7 +361,7 @@
 
 /**
  * tipc_nameseq_remove_publ -
- * 
+ *
  * NOTE: There may be cases where TIPC is asked to remove a publication
  * that is not in the name table.  For example, if another node issues a
  * publication for a name sequence that overlaps an existing name sequence
@@ -392,12 +392,12 @@
 
 	prev = sseq->zone_list;
 	publ = sseq->zone_list->zone_list_next;
-	while ((publ->key != key) || (publ->ref != ref) || 
+	while ((publ->key != key) || (publ->ref != ref) ||
 	       (publ->node && (publ->node != node))) {
 		prev = publ;
 		publ = publ->zone_list_next;
 		if (prev == sseq->zone_list) {
-			
+
 			/* Prevent endless loop if publication not found */
 
 			return NULL;
@@ -426,7 +426,7 @@
 
 				err("Unable to de-list cluster publication\n"
 				    "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
-				    publ->type, publ->lower, publ->node, 
+				    publ->type, publ->lower, publ->node,
 				    publ->ref, publ->key);
 				goto end_cluster;
 			}
@@ -456,7 +456,7 @@
 
 				err("Unable to de-list node publication\n"
 				    "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
-				    publ->type, publ->lower, publ->node, 
+				    publ->type, publ->lower, publ->node,
 				    publ->ref, publ->key);
 				goto end_node;
 			}
@@ -486,8 +486,8 @@
 		tipc_subscr_report_overlap(s,
 					   publ->lower,
 					   publ->upper,
-					   TIPC_WITHDRAWN, 
-					   publ->ref, 
+					   TIPC_WITHDRAWN,
+					   publ->ref,
 					   publ->node,
 					   removed_subseq);
 	}
@@ -517,8 +517,8 @@
 			int must_report = 1;
 
 			do {
-				tipc_subscr_report_overlap(s, 
-							   sseq->lower, 
+				tipc_subscr_report_overlap(s,
+							   sseq->lower,
 							   sseq->upper,
 							   TIPC_PUBLISHED,
 							   crs->ref,
@@ -576,7 +576,7 @@
 					scope, node, port, key);
 }
 
-struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, 
+struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
 					     u32 node, u32 ref, u32 key)
 {
 	struct publication *publ;
@@ -676,14 +676,14 @@
 
 /**
  * tipc_nametbl_mc_translate - find multicast destinations
- * 
+ *
  * Creates list of all local ports that overlap the given multicast address;
  * also determines if any off-node ports overlap.
  *
  * Note: Publications with a scope narrower than 'limit' are ignored.
  * (i.e. local node-scope publications mustn't receive messages arriving
  * from another node, even if the multcast link brought it here)
- * 
+ *
  * Returns non-zero if any off-node ports overlap
  */
 
@@ -730,7 +730,7 @@
  * tipc_nametbl_publish_rsv - publish port name using a reserved name type
  */
 
-int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope, 
+int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope,
 			struct tipc_name_seq const *seq)
 {
 	int res;
@@ -745,13 +745,13 @@
  * tipc_nametbl_publish - add name publication to network name tables
  */
 
-struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, 
+struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
 				    u32 scope, u32 port_ref, u32 key)
 {
 	struct publication *publ;
 
 	if (table.local_publ_count >= tipc_max_publications) {
-		warn("Publication failed, local publication limit reached (%u)\n", 
+		warn("Publication failed, local publication limit reached (%u)\n",
 		     tipc_max_publications);
 		return NULL;
 	}
@@ -808,22 +808,22 @@
 	u32 type = s->seq.type;
 	struct name_seq *seq;
 
-        write_lock_bh(&tipc_nametbl_lock);
+	write_lock_bh(&tipc_nametbl_lock);
 	seq = nametbl_find_seq(type);
 	if (!seq) {
 		seq = tipc_nameseq_create(type, &table.types[hash(type)]);
 	}
-        if (seq){
-                spin_lock_bh(&seq->lock);
-                dbg("tipc_nametbl_subscribe:found %p for {%u,%u,%u}\n",
-                    seq, type, s->seq.lower, s->seq.upper);
-                tipc_nameseq_subscribe(seq, s);
-                spin_unlock_bh(&seq->lock);
-        } else {
+	if (seq){
+		spin_lock_bh(&seq->lock);
+		dbg("tipc_nametbl_subscribe:found %p for {%u,%u,%u}\n",
+		    seq, type, s->seq.lower, s->seq.upper);
+		tipc_nameseq_subscribe(seq, s);
+		spin_unlock_bh(&seq->lock);
+	} else {
 		warn("Failed to create subscription for {%u,%u,%u}\n",
 		     s->seq.type, s->seq.lower, s->seq.upper);
-        }
-        write_unlock_bh(&tipc_nametbl_lock);
+	}
+	write_unlock_bh(&tipc_nametbl_lock);
 }
 
 /**
@@ -834,19 +834,19 @@
 {
 	struct name_seq *seq;
 
-        write_lock_bh(&tipc_nametbl_lock);
-        seq = nametbl_find_seq(s->seq.type);
+	write_lock_bh(&tipc_nametbl_lock);
+	seq = nametbl_find_seq(s->seq.type);
 	if (seq != NULL){
-                spin_lock_bh(&seq->lock);
-                list_del_init(&s->nameseq_list);
-                spin_unlock_bh(&seq->lock);
-                if ((seq->first_free == 0) && list_empty(&seq->subscriptions)) {
-                        hlist_del_init(&seq->ns_list);
-                        kfree(seq->sseqs);
-                        kfree(seq);
-                }
-        }
-        write_unlock_bh(&tipc_nametbl_lock);
+		spin_lock_bh(&seq->lock);
+		list_del_init(&s->nameseq_list);
+		spin_unlock_bh(&seq->lock);
+		if ((seq->first_free == 0) && list_empty(&seq->subscriptions)) {
+			hlist_del_init(&seq->ns_list);
+			kfree(seq->sseqs);
+			kfree(seq);
+		}
+	}
+	write_unlock_bh(&tipc_nametbl_lock);
 }
 
 
@@ -952,7 +952,7 @@
  * nametbl_list - print specified name table contents into the given buffer
  */
 
-static void nametbl_list(struct print_buf *buf, u32 depth_info, 
+static void nametbl_list(struct print_buf *buf, u32 depth_info,
 			 u32 type, u32 lowbound, u32 upbound)
 {
 	struct hlist_head *seq_head;
@@ -976,7 +976,7 @@
 		for (i = 0; i < tipc_nametbl_size; i++) {
 			seq_head = &table.types[i];
 			hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
-				nameseq_list(seq, buf, depth, seq->type, 
+				nameseq_list(seq, buf, depth, seq->type,
 					     lowbound, upbound, i);
 			}
 		}
@@ -991,7 +991,7 @@
 		seq_head = &table.types[i];
 		hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
 			if (seq->type == type) {
-				nameseq_list(seq, buf, depth, type, 
+				nameseq_list(seq, buf, depth, type,
 					     lowbound, upbound, i);
 				break;
 			}
@@ -1030,7 +1030,7 @@
 	tipc_printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY);
 	argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
 	read_lock_bh(&tipc_nametbl_lock);
-	nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type), 
+	nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type),
 		     ntohl(argv->lowbound), ntohl(argv->upbound));
 	read_unlock_bh(&tipc_nametbl_lock);
 	str_len = tipc_printbuf_validate(&b);
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index e8a3d71..b9e7cd3 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/name_table.h: Include file for TIPC name table code
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2004-2005, Wind River Systems
  * All rights reserved.
@@ -64,7 +64,7 @@
  * @node_list: next matching name seq publication with >= node scope
  * @cluster_list: next matching name seq publication with >= cluster scope
  * @zone_list: next matching name seq publication with >= zone scope
- * 
+ *
  * Note that the node list, cluster list, and zone list are circular lists.
  */
 
@@ -89,16 +89,16 @@
 
 struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space);
 u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node);
-int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, 
+int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
 			 struct port_list *dports);
-int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope, 
+int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope,
 			struct tipc_name_seq const *seq);
 struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
 				    u32 scope, u32 port_ref, u32 key);
 int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key);
 struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
 					u32 scope, u32 node, u32 ref, u32 key);
-struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, 
+struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
 					u32 node, u32 ref, u32 key);
 void tipc_nametbl_subscribe(struct subscription *s);
 void tipc_nametbl_unsubscribe(struct subscription *s);
diff --git a/net/tipc/net.c b/net/tipc/net.c
index a991bf8..c39c762 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/net.c: TIPC network routing code
- * 
+ *
  * Copyright (c) 1995-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -49,63 +49,63 @@
 #include "discover.h"
 #include "config.h"
 
-/* 
+/*
  * The TIPC locking policy is designed to ensure a very fine locking
  * granularity, permitting complete parallel access to individual
- * port and node/link instances. The code consists of three major 
+ * port and node/link instances. The code consists of three major
  * locking domains, each protected with their own disjunct set of locks.
  *
  * 1: The routing hierarchy.
- *    Comprises the structures 'zone', 'cluster', 'node', 'link' 
- *    and 'bearer'. The whole hierarchy is protected by a big 
- *    read/write lock, tipc_net_lock, to enssure that nothing is added 
- *    or removed while code is accessing any of these structures. 
- *    This layer must not be called from the two others while they 
+ *    Comprises the structures 'zone', 'cluster', 'node', 'link'
+ *    and 'bearer'. The whole hierarchy is protected by a big
+ *    read/write lock, tipc_net_lock, to enssure that nothing is added
+ *    or removed while code is accessing any of these structures.
+ *    This layer must not be called from the two others while they
  *    hold any of their own locks.
  *    Neither must it itself do any upcalls to the other two before
  *    it has released tipc_net_lock and other protective locks.
  *
- *   Within the tipc_net_lock domain there are two sub-domains;'node' and 
+ *   Within the tipc_net_lock domain there are two sub-domains;'node' and
  *   'bearer', where local write operations are permitted,
  *   provided that those are protected by individual spin_locks
- *   per instance. Code holding tipc_net_lock(read) and a node spin_lock 
+ *   per instance. Code holding tipc_net_lock(read) and a node spin_lock
  *   is permitted to poke around in both the node itself and its
- *   subordinate links. I.e, it can update link counters and queues, 
- *   change link state, send protocol messages, and alter the 
- *   "active_links" array in the node; but it can _not_ remove a link 
+ *   subordinate links. I.e, it can update link counters and queues,
+ *   change link state, send protocol messages, and alter the
+ *   "active_links" array in the node; but it can _not_ remove a link
  *   or a node from the overall structure.
- *   Correspondingly, individual bearers may change status within a 
- *   tipc_net_lock(read), protected by an individual spin_lock ber bearer 
+ *   Correspondingly, individual bearers may change status within a
+ *   tipc_net_lock(read), protected by an individual spin_lock ber bearer
  *   instance, but it needs tipc_net_lock(write) to remove/add any bearers.
- *     
  *
- *  2: The transport level of the protocol. 
- *     This consists of the structures port, (and its user level 
- *     representations, such as user_port and tipc_sock), reference and 
- *     tipc_user (port.c, reg.c, socket.c). 
+ *
+ *  2: The transport level of the protocol.
+ *     This consists of the structures port, (and its user level
+ *     representations, such as user_port and tipc_sock), reference and
+ *     tipc_user (port.c, reg.c, socket.c).
  *
  *     This layer has four different locks:
  *     - The tipc_port spin_lock. This is protecting each port instance
- *       from parallel data access and removal. Since we can not place 
- *       this lock in the port itself, it has been placed in the 
+ *       from parallel data access and removal. Since we can not place
+ *       this lock in the port itself, it has been placed in the
  *       corresponding reference table entry, which has the same life
- *       cycle as the module. This entry is difficult to access from 
- *       outside the TIPC core, however, so a pointer to the lock has 
- *       been added in the port instance, -to be used for unlocking 
+ *       cycle as the module. This entry is difficult to access from
+ *       outside the TIPC core, however, so a pointer to the lock has
+ *       been added in the port instance, -to be used for unlocking
  *       only.
- *     - A read/write lock to protect the reference table itself (teg.c). 
- *       (Nobody is using read-only access to this, so it can just as 
+ *     - A read/write lock to protect the reference table itself (teg.c).
+ *       (Nobody is using read-only access to this, so it can just as
  *       well be changed to a spin_lock)
  *     - A spin lock to protect the registry of kernel/driver users (reg.c)
- *     - A global spin_lock (tipc_port_lock), which only task is to ensure 
+ *     - A global spin_lock (tipc_port_lock), which only task is to ensure
  *       consistency where more than one port is involved in an operation,
  *       i.e., whe a port is part of a linked list of ports.
  *       There are two such lists; 'port_list', which is used for management,
  *       and 'wait_list', which is used to queue ports during congestion.
- *     
+ *
  *  3: The name table (name_table.c, name_distr.c, subscription.c)
- *     - There is one big read/write-lock (tipc_nametbl_lock) protecting the 
- *       overall name table structure. Nothing must be added/removed to 
+ *     - There is one big read/write-lock (tipc_nametbl_lock) protecting the
+ *       overall name table structure. Nothing must be added/removed to
  *       this structure without holding write access to it.
  *     - There is one local spin_lock per sub_sequence, which can be seen
  *       as a sub-domain to the tipc_nametbl_lock domain. It is used only
@@ -118,7 +118,7 @@
 DEFINE_RWLOCK(tipc_net_lock);
 struct network tipc_net = { NULL };
 
-struct node *tipc_net_select_remote_node(u32 addr, u32 ref) 
+struct node *tipc_net_select_remote_node(u32 addr, u32 ref)
 {
 	return tipc_zone_select_remote_node(tipc_net.zones[tipc_zone(addr)], addr, ref);
 }
@@ -224,7 +224,7 @@
 			buf_discard(buf);
 		} else {
 			msg_dbg(msg, "NET>REJ>:");
-			tipc_reject_msg(buf, msg_destport(msg) ? 
+			tipc_reject_msg(buf, msg_destport(msg) ?
 					TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME);
 		}
 		return;
@@ -236,7 +236,7 @@
 	dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg);
 	if (in_scope(dnode, tipc_own_addr)) {
 		if (msg_isdata(msg)) {
-			if (msg_mcast(msg)) 
+			if (msg_mcast(msg))
 				tipc_port_recv_mcast(buf, NULL);
 			else if (msg_destport(msg))
 				tipc_port_recv_msg(buf);
@@ -284,7 +284,7 @@
 	    (res = tipc_bclink_init())) {
 		return res;
 	}
-        tipc_subscr_stop();
+	tipc_subscr_stop();
 	tipc_cfg_stop();
 	tipc_k_signal((Handler)tipc_subscr_start, 0);
 	tipc_k_signal((Handler)tipc_cfg_init, 0);
@@ -298,12 +298,12 @@
 {
 	if (tipc_mode != TIPC_NET_MODE)
 		return;
-        write_lock_bh(&tipc_net_lock);
+	write_lock_bh(&tipc_net_lock);
 	tipc_bearer_stop();
 	tipc_mode = TIPC_NODE_MODE;
 	tipc_bclink_stop();
 	net_stop();
-        write_unlock_bh(&tipc_net_lock);
+	write_unlock_bh(&tipc_net_lock);
 	info("Left network mode \n");
 }
 
diff --git a/net/tipc/net.h b/net/tipc/net.h
index f3e0b85..a6a0e99 100644
--- a/net/tipc/net.h
+++ b/net/tipc/net.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/net.h: Include file for TIPC network routing code
- * 
+ *
  * Copyright (c) 1995-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -43,7 +43,7 @@
  * struct network - TIPC network structure
  * @zones: array of pointers to all zones within network
  */
- 
+
 struct network {
 	struct _zone **zones;
 };
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index eb1bb4d..b8e1edc 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/netlink.c: TIPC configuration handling
- * 
+ *
  * Copyright (c) 2005-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -63,15 +63,15 @@
 		genlmsg_unicast(rep_buf, req_nlh->nlmsg_pid);
 	}
 
-        return 0;
+	return 0;
 }
 
 static struct genl_family family = {
-        .id		= GENL_ID_GENERATE,
-        .name		= TIPC_GENL_NAME,
-        .version	= TIPC_GENL_VERSION,
-        .hdrsize	= TIPC_GENL_HDRLEN,
-        .maxattr	= 0,
+	.id		= GENL_ID_GENERATE,
+	.name		= TIPC_GENL_NAME,
+	.version	= TIPC_GENL_VERSION,
+	.hdrsize	= TIPC_GENL_HDRLEN,
+	.maxattr	= 0,
 };
 
 static struct genl_ops ops = {
@@ -93,7 +93,7 @@
 	if (genl_register_ops(&family, &ops))
 		goto err_unregister;
 
-        return 0;
+	return 0;
 
  err_unregister:
 	genl_unregister_family(&family);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 4111a31..e2e452a 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/node.c: TIPC node management routines
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
@@ -58,7 +58,7 @@
 {
 	struct cluster *c_ptr;
 	struct node *n_ptr;
-        struct node **curr_node;
+	struct node **curr_node;
 
 	n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC);
 	if (!n_ptr) {
@@ -74,16 +74,16 @@
 		kfree(n_ptr);
 		return NULL;
 	}
-		
+
 	n_ptr->addr = addr;
-                spin_lock_init(&n_ptr->lock);
+		spin_lock_init(&n_ptr->lock);
 	INIT_LIST_HEAD(&n_ptr->nsub);
 	n_ptr->owner = c_ptr;
 	tipc_cltr_attach_node(c_ptr, n_ptr);
 	n_ptr->last_router = -1;
 
 	/* Insert node into ordered list */
-	for (curr_node = &tipc_nodes; *curr_node; 
+	for (curr_node = &tipc_nodes; *curr_node;
 	     curr_node = &(*curr_node)->next) {
 		if (addr < (*curr_node)->addr) {
 			n_ptr->next = *curr_node;
@@ -116,7 +116,7 @@
 
 /**
  * tipc_node_link_up - handle addition of link
- * 
+ *
  * Link becomes active (alone or shared) or standby, depending on its priority.
  */
 
@@ -128,19 +128,19 @@
 
 	info("Established link <%s> on network plane %c\n",
 	     l_ptr->name, l_ptr->b_ptr->net_plane);
-	
+
 	if (!active[0]) {
 		dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]);
 		active[0] = active[1] = l_ptr;
 		node_established_contact(n_ptr);
 		return;
 	}
-	if (l_ptr->priority < active[0]->priority) { 
+	if (l_ptr->priority < active[0]->priority) {
 		info("New link <%s> becomes standby\n", l_ptr->name);
 		return;
 	}
 	tipc_link_send_duplicate(active[0], l_ptr);
-	if (l_ptr->priority == active[0]->priority) { 
+	if (l_ptr->priority == active[0]->priority) {
 		active[0] = l_ptr;
 		return;
 	}
@@ -160,17 +160,17 @@
 	u32 i;
 	u32 highest_prio = 0;
 
-        active[0] = active[1] = NULL;
+	active[0] = active[1] = NULL;
 
 	for (i = 0; i < MAX_BEARERS; i++) {
-                struct link *l_ptr = n_ptr->links[i];
+		struct link *l_ptr = n_ptr->links[i];
 
 		if (!l_ptr || !tipc_link_is_up(l_ptr) ||
 		    (l_ptr->priority < highest_prio))
 			continue;
 
 		if (l_ptr->priority > highest_prio) {
-                        highest_prio = l_ptr->priority;
+			highest_prio = l_ptr->priority;
 			active[0] = active[1] = l_ptr;
 		} else {
 			active[1] = l_ptr;
@@ -203,15 +203,15 @@
 		active[1] = active[0];
 	if (active[0] == l_ptr)
 		node_select_active_links(n_ptr);
-	if (tipc_node_is_up(n_ptr)) 
+	if (tipc_node_is_up(n_ptr))
 		tipc_link_changeover(l_ptr);
-	else 
+	else
 		node_lost_contact(n_ptr);
 }
 
 int tipc_node_has_active_links(struct node *n_ptr)
 {
-	return (n_ptr && 
+	return (n_ptr &&
 		((n_ptr->active_links[0]) || (n_ptr->active_links[1])));
 }
 
@@ -236,28 +236,28 @@
 
 	if (!n_ptr)
 		n_ptr = tipc_node_create(l_ptr->addr);
-        if (n_ptr) {
+	if (n_ptr) {
 		u32 bearer_id = l_ptr->b_ptr->identity;
 		char addr_string[16];
 
-                if (n_ptr->link_cnt >= 2) {
+		if (n_ptr->link_cnt >= 2) {
 			char addr_string[16];
 
-                        err("Attempt to create third link to %s\n",
+			err("Attempt to create third link to %s\n",
 			    addr_string_fill(addr_string, n_ptr->addr));
-                        return NULL;
-                }
+			return NULL;
+		}
 
-                if (!n_ptr->links[bearer_id]) {
-                        n_ptr->links[bearer_id] = l_ptr;
-                        tipc_net.zones[tipc_zone(l_ptr->addr)]->links++;
-                        n_ptr->link_cnt++;
-                        return n_ptr;
-                }
-                err("Attempt to establish second link on <%s> to %s \n",
-                    l_ptr->b_ptr->publ.name, 
+		if (!n_ptr->links[bearer_id]) {
+			n_ptr->links[bearer_id] = l_ptr;
+			tipc_net.zones[tipc_zone(l_ptr->addr)]->links++;
+			n_ptr->link_cnt++;
+			return n_ptr;
+		}
+		err("Attempt to establish second link on <%s> to %s \n",
+		    l_ptr->b_ptr->publ.name,
 		    addr_string_fill(addr_string, l_ptr->addr));
-        }
+	}
 	return NULL;
 }
 
@@ -272,17 +272,17 @@
  * Routing table management - five cases to handle:
  *
  * 1: A link towards a zone/cluster external node comes up.
- *    => Send a multicast message updating routing tables of all 
- *    system nodes within own cluster that the new destination 
- *    can be reached via this node. 
+ *    => Send a multicast message updating routing tables of all
+ *    system nodes within own cluster that the new destination
+ *    can be reached via this node.
  *    (node.establishedContact()=>cluster.multicastNewRoute())
  *
  * 2: A link towards a slave node comes up.
- *    => Send a multicast message updating routing tables of all 
- *    system nodes within own cluster that the new destination 
- *    can be reached via this node. 
+ *    => Send a multicast message updating routing tables of all
+ *    system nodes within own cluster that the new destination
+ *    can be reached via this node.
  *    (node.establishedContact()=>cluster.multicastNewRoute())
- *    => Send a  message to the slave node about existence 
+ *    => Send a  message to the slave node about existence
  *    of all system nodes within cluster:
  *    (node.establishedContact()=>cluster.sendLocalRoutes())
  *
@@ -292,13 +292,13 @@
  *     nodes which can be reached via this node.
  *    (node.establishedContact()==>network.sendExternalRoutes())
  *    (node.establishedContact()==>network.sendSlaveRoutes())
- *    => Send messages to all directly connected slave nodes 
+ *    => Send messages to all directly connected slave nodes
  *    containing information about the existence of the new node
  *    (node.establishedContact()=>cluster.multicastNewRoute())
- *    
+ *
  * 4: The link towards a zone/cluster external node or slave
  *    node goes down.
- *    => Send a multcast message updating routing tables of all 
+ *    => Send a multcast message updating routing tables of all
  *    nodes within cluster that the new destination can not any
  *    longer be reached via this node.
  *    (node.lostAllLinks()=>cluster.bcastLostRoute())
@@ -308,7 +308,7 @@
  *    routing tables. Note: This is a completely node
  *    local operation.
  *    (node.lostAllLinks()=>network.removeAsRouter())
- *    => Send messages to all directly connected slave nodes 
+ *    => Send messages to all directly connected slave nodes
  *    containing information about loss of the node
  *    (node.establishedContact()=>cluster.multicastLostRoute())
  *
@@ -319,12 +319,12 @@
 	struct cluster *c_ptr;
 
 	dbg("node_established_contact:-> %x\n", n_ptr->addr);
-	if (!tipc_node_has_active_routes(n_ptr) && in_own_cluster(n_ptr->addr)) { 
+	if (!tipc_node_has_active_routes(n_ptr) && in_own_cluster(n_ptr->addr)) {
 		tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
 	}
 
-        /* Syncronize broadcast acks */
-        n_ptr->bclink.acked = tipc_bclink_get_last_sent();
+	/* Syncronize broadcast acks */
+	n_ptr->bclink.acked = tipc_bclink_get_last_sent();
 
 	if (is_slave(tipc_own_addr))
 		return;
@@ -333,11 +333,11 @@
 		c_ptr = tipc_cltr_find(tipc_own_addr);
 		if (!c_ptr)
 			c_ptr = tipc_cltr_create(tipc_own_addr);
-                if (c_ptr)
-                        tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, 
+		if (c_ptr)
+			tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1,
 						  tipc_max_nodes);
 		return;
-	} 
+	}
 
 	c_ptr = n_ptr->owner;
 	if (is_slave(n_ptr->addr)) {
@@ -367,26 +367,26 @@
 	char addr_string[16];
 	u32 i;
 
-        /* Clean up broadcast reception remains */
-        n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0;
-        while (n_ptr->bclink.deferred_head) {
-                struct sk_buff* buf = n_ptr->bclink.deferred_head;
-                n_ptr->bclink.deferred_head = buf->next;
-                buf_discard(buf);
-        }
-        if (n_ptr->bclink.defragm) {
-                buf_discard(n_ptr->bclink.defragm);  
-                n_ptr->bclink.defragm = NULL;
-        }            
-        if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { 
-                tipc_bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000));
-        }
+	/* Clean up broadcast reception remains */
+	n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0;
+	while (n_ptr->bclink.deferred_head) {
+		struct sk_buff* buf = n_ptr->bclink.deferred_head;
+		n_ptr->bclink.deferred_head = buf->next;
+		buf_discard(buf);
+	}
+	if (n_ptr->bclink.defragm) {
+		buf_discard(n_ptr->bclink.defragm);
+		n_ptr->bclink.defragm = NULL;
+	}
+	if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) {
+		tipc_bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000));
+	}
 
-        /* Update routing tables */
+	/* Update routing tables */
 	if (is_slave(tipc_own_addr)) {
 		tipc_net_remove_as_router(n_ptr->addr);
 	} else {
-		if (!in_own_cluster(n_ptr->addr)) { 
+		if (!in_own_cluster(n_ptr->addr)) {
 			/* Case 4 (see above) */
 			c_ptr = tipc_cltr_find(tipc_own_addr);
 			tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1,
@@ -399,7 +399,7 @@
 							   tipc_max_nodes);
 			} else {
 				if (n_ptr->bclink.supported) {
-					tipc_nmap_remove(&tipc_cltr_bcast_nodes, 
+					tipc_nmap_remove(&tipc_cltr_bcast_nodes,
 							 n_ptr->addr);
 					if (n_ptr->addr < tipc_own_addr)
 						tipc_own_tag--;
@@ -414,13 +414,13 @@
 	if (tipc_node_has_active_routes(n_ptr))
 		return;
 
-	info("Lost contact with %s\n", 
+	info("Lost contact with %s\n",
 	     addr_string_fill(addr_string, n_ptr->addr));
 
 	/* Abort link changeover */
 	for (i = 0; i < MAX_BEARERS; i++) {
 		struct link *l_ptr = n_ptr->links[i];
-		if (!l_ptr) 
+		if (!l_ptr)
 			continue;
 		l_ptr->reset_checkpoint = l_ptr->next_in_no;
 		l_ptr->exp_msg_count = 0;
@@ -429,7 +429,7 @@
 
 	/* Notify subscribers */
 	list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) {
-                ns->node = NULL;
+		ns->node = NULL;
 		list_del_init(&ns->nodesub_list);
 		tipc_k_signal((Handler)ns->handle_node_down,
 			      (unsigned long)ns->usr_handle);
@@ -438,7 +438,7 @@
 
 /**
  * tipc_node_select_next_hop - find the next-hop node for a message
- * 
+ *
  * Called by when cluster local lookup has failed.
  */
 
@@ -447,13 +447,13 @@
 	struct node *n_ptr;
 	u32 router_addr;
 
-        if (!tipc_addr_domain_valid(addr))
-                return NULL;
+	if (!tipc_addr_domain_valid(addr))
+		return NULL;
 
 	/* Look for direct link to destination processsor */
 	n_ptr = tipc_node_find(addr);
 	if (n_ptr && tipc_node_has_active_links(n_ptr))
-                return n_ptr;
+		return n_ptr;
 
 	/* Cluster local system nodes *must* have direct links */
 	if (!is_slave(addr) && in_own_cluster(addr))
@@ -461,10 +461,10 @@
 
 	/* Look for cluster local router with direct link to node */
 	router_addr = tipc_node_select_router(n_ptr, selector);
-	if (router_addr) 
-                return tipc_node_select(router_addr, selector);
+	if (router_addr)
+		return tipc_node_select(router_addr, selector);
 
-	/* Slave nodes can only be accessed within own cluster via a 
+	/* Slave nodes can only be accessed within own cluster via a
 	   known router with direct link -- if no router was found,give up */
 	if (is_slave(addr))
 		return NULL;
@@ -473,20 +473,20 @@
 	addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
 	n_ptr = tipc_net_select_remote_node(addr, selector);
 	if (n_ptr && tipc_node_has_active_links(n_ptr))
-                return n_ptr;
+		return n_ptr;
 
 	/* Last resort -- look for any router to anywhere in remote zone */
 	router_addr =  tipc_net_select_router(addr, selector);
-	if (router_addr) 
-                return tipc_node_select(router_addr, selector);
+	if (router_addr)
+		return tipc_node_select(router_addr, selector);
 
-        return NULL;
+	return NULL;
 }
 
 /**
  * tipc_node_select_router - select router to reach specified node
- * 
- * Uses a deterministic and fair algorithm for selecting router node. 
+ *
+ * Uses a deterministic and fair algorithm for selecting router node.
  */
 
 u32 tipc_node_select_router(struct node *n_ptr, u32 ref)
@@ -496,8 +496,8 @@
 	u32 start;
 	u32 r;
 
-        if (!n_ptr)
-                return 0;
+	if (!n_ptr)
+		return 0;
 
 	if (n_ptr->last_router < 0)
 		return 0;
@@ -531,10 +531,10 @@
 {
 	u32 r_num = tipc_node(router);
 
-	n_ptr->routers[r_num / 32] = 
+	n_ptr->routers[r_num / 32] =
 		((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]);
 	n_ptr->last_router = tipc_max_nodes / 32;
-	while ((--n_ptr->last_router >= 0) && 
+	while ((--n_ptr->last_router >= 0) &&
 	       !n_ptr->routers[n_ptr->last_router]);
 }
 
@@ -548,7 +548,7 @@
 	n_ptr->routers[r_num / 32] =
 		((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32]));
 	n_ptr->last_router = tipc_max_nodes / 32;
-	while ((--n_ptr->last_router >= 0) && 
+	while ((--n_ptr->last_router >= 0) &&
 	       !n_ptr->routers[n_ptr->last_router]);
 
 	if (!tipc_node_is_up(n_ptr))
@@ -562,7 +562,7 @@
 
 	tipc_printf(buf, "\n\n%s", str);
 	for (i = 0; i < MAX_BEARERS; i++) {
-		if (!n_ptr->links[i]) 
+		if (!n_ptr->links[i])
 			continue;
 		tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]);
 	}
@@ -590,7 +590,7 @@
 	u32 domain;
 	struct sk_buff *buf;
 	struct node *n_ptr;
-        struct tipc_node_info node_info;
+	struct tipc_node_info node_info;
 	u32 payload_size;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
@@ -601,10 +601,10 @@
 		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 						   " (network address)");
 
-        if (!tipc_nodes)
-                return tipc_cfg_reply_none();
+	if (!tipc_nodes)
+		return tipc_cfg_reply_none();
 
-	/* For now, get space for all other nodes 
+	/* For now, get space for all other nodes
 	   (will need to modify this when slave nodes are supported */
 
 	payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1);
@@ -620,9 +620,9 @@
 	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
 		if (!in_scope(domain, n_ptr->addr))
 			continue;
-                node_info.addr = htonl(n_ptr->addr);
-                node_info.up = htonl(tipc_node_is_up(n_ptr));
-		tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, 
+		node_info.addr = htonl(n_ptr->addr);
+		node_info.up = htonl(tipc_node_is_up(n_ptr));
+		tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO,
 				    &node_info, sizeof(node_info));
 	}
 
@@ -634,7 +634,7 @@
 	u32 domain;
 	struct sk_buff *buf;
 	struct node *n_ptr;
-        struct tipc_link_info link_info;
+	struct tipc_link_info link_info;
 	u32 payload_size;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
@@ -645,9 +645,9 @@
 		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 						   " (network address)");
 
-        if (tipc_mode != TIPC_NET_MODE)
-                return tipc_cfg_reply_none();
-	
+	if (tipc_mode != TIPC_NET_MODE)
+		return tipc_cfg_reply_none();
+
 	/* Get space for all unicast links + multicast link */
 
 	payload_size = TLV_SPACE(sizeof(link_info)) *
@@ -661,27 +661,27 @@
 
 	/* Add TLV for broadcast link */
 
-        link_info.dest = htonl(tipc_own_addr & 0xfffff00);
-        link_info.up = htonl(1);
-        sprintf(link_info.str, tipc_bclink_name);
+	link_info.dest = htonl(tipc_own_addr & 0xfffff00);
+	link_info.up = htonl(1);
+	sprintf(link_info.str, tipc_bclink_name);
 	tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
 
 	/* Add TLVs for any other links in scope */
 
 	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
-                u32 i;
+		u32 i;
 
 		if (!in_scope(domain, n_ptr->addr))
 			continue;
-                for (i = 0; i < MAX_BEARERS; i++) {
-                        if (!n_ptr->links[i]) 
-                                continue;
-                        link_info.dest = htonl(n_ptr->addr);
-                        link_info.up = htonl(tipc_link_is_up(n_ptr->links[i]));
-                        strcpy(link_info.str, n_ptr->links[i]->name);
-			tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, 
+		for (i = 0; i < MAX_BEARERS; i++) {
+			if (!n_ptr->links[i])
+				continue;
+			link_info.dest = htonl(n_ptr->addr);
+			link_info.up = htonl(tipc_link_is_up(n_ptr->links[i]));
+			strcpy(link_info.str, n_ptr->links[i]->name);
+			tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO,
 					    &link_info, sizeof(link_info));
-                }
+		}
 	}
 
 	return buf;
diff --git a/net/tipc/node.h b/net/tipc/node.h
index a07cc79..cd18826 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/node.h: Include file for TIPC node management routines
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -67,7 +67,7 @@
  *    @deferred_tail: newest OOS b'cast message received from node
  *    @defragm: list of partially reassembled b'cast message fragments from node
  */
- 
+
 struct node {
 	u32 addr;
 	spinlock_t lock;
@@ -85,8 +85,8 @@
 		int supported;
 		u32 acked;
 		u32 last_in;
-		u32 gap_after; 
-		u32 gap_to; 
+		u32 gap_after;
+		u32 gap_to;
 		u32 nack_sync;
 		struct sk_buff *deferred_head;
 		struct sk_buff *deferred_tail;
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
index cc3fff3..8ecbd0f 100644
--- a/net/tipc/node_subscr.c
+++ b/net/tipc/node_subscr.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/node_subscr.c: TIPC "node down" subscription handling
- * 
+ *
  * Copyright (c) 1995-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -44,14 +44,14 @@
  * tipc_nodesub_subscribe - create "node down" subscription for specified node
  */
 
-void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr, 
+void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
 		       void *usr_handle, net_ev_handler handle_down)
 {
 	if (addr == tipc_own_addr) {
 		node_sub->node = NULL;
 		return;
 	}
-	
+
 	node_sub->node = tipc_node_find(addr);
 	if (!node_sub->node) {
 		warn("Node subscription rejected, unknown node 0x%x\n", addr);
diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h
index 01751c4..5f3f585 100644
--- a/net/tipc/node_subscr.h
+++ b/net/tipc/node_subscr.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling
- * 
+ *
  * Copyright (c) 1995-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
diff --git a/net/tipc/port.c b/net/tipc/port.c
index b7f3199..5f8217d 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/port.c: TIPC port code
- * 
+ *
  * Copyright (c) 1992-2006, Ericsson AB
  * Copyright (c) 2004-2005, Wind River Systems
  * All rights reserved.
@@ -126,8 +126,8 @@
 
 	ext_targets = tipc_nametbl_mc_translate(seq->type, seq->lower, seq->upper,
 						TIPC_NODE_SCOPE, &dports);
-	
-	/* Send message to destinations (duplicate it only if necessary) */ 
+
+	/* Send message to destinations (duplicate it only if necessary) */
 
 	if (ext_targets) {
 		if (dports.count != 0) {
@@ -157,7 +157,7 @@
 
 /**
  * tipc_port_recv_mcast - deliver multicast message to all destination ports
- * 
+ *
  * If there is no port list, perform a lookup to create one
  */
 
@@ -213,7 +213,7 @@
 
 /**
  * tipc_createport_raw - create a native TIPC port
- * 
+ *
  * Returns local port reference
  */
 
@@ -273,7 +273,7 @@
 
 	tipc_withdraw(ref, 0, NULL);
 	p_ptr = tipc_port_lock(ref);
-	if (!p_ptr) 
+	if (!p_ptr)
 		return -EINVAL;
 
 	tipc_ref_discard(ref);
@@ -302,7 +302,7 @@
 
 /**
  * tipc_get_port() - return port associated with 'ref'
- * 
+ *
  * Note: Port is not locked.
  */
 
@@ -336,7 +336,7 @@
 int tipc_portunreliable(u32 ref, unsigned int *isunreliable)
 {
 	struct port *p_ptr;
-	
+
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
@@ -348,7 +348,7 @@
 int tipc_set_portunreliable(u32 ref, unsigned int isunreliable)
 {
 	struct port *p_ptr;
-	
+
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
@@ -365,7 +365,7 @@
 int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable)
 {
 	struct port *p_ptr;
-	
+
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
@@ -377,7 +377,7 @@
 int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable)
 {
 	struct port *p_ptr;
-	
+
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
@@ -386,19 +386,19 @@
 	return TIPC_OK;
 }
 
-/* 
- * port_build_proto_msg(): build a port level protocol 
- * or a connection abortion message. Called with 
+/*
+ * port_build_proto_msg(): build a port level protocol
+ * or a connection abortion message. Called with
  * tipc_port lock on.
  */
 static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
 					    u32 origport, u32 orignode,
-					    u32 usr, u32 type, u32 err, 
+					    u32 usr, u32 type, u32 err,
 					    u32 seqno, u32 ack)
 {
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
-	
+
 	buf = buf_acquire(LONG_H_SIZE);
 	if (buf) {
 		msg = buf_msg(buf);
@@ -461,7 +461,7 @@
 		msg_set_orignode(rmsg, tipc_own_addr);
 	else
 		msg_set_orignode(rmsg, msg_destnode(msg));
-	msg_set_size(rmsg, data_sz + hdr_sz); 
+	msg_set_size(rmsg, data_sz + hdr_sz);
 	msg_set_nametype(rmsg, msg_nametype(msg));
 	msg_set_nameinst(rmsg, msg_nameinst(msg));
 	memcpy(rbuf->data + hdr_sz, msg_data(msg), data_sz);
@@ -492,7 +492,7 @@
 	struct sk_buff *buf;
 	int res;
 
-	res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, 
+	res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,
 			!p_ptr->user_port, &buf);
 	if (!buf)
 		return res;
@@ -523,7 +523,7 @@
 					   tipc_own_addr,
 					   CONN_MANAGER,
 					   CONN_PROBE,
-					   TIPC_OK, 
+					   TIPC_OK,
 					   port_out_seqno(p_ptr),
 					   0);
 		port_incr_out_seqno(p_ptr);
@@ -562,7 +562,7 @@
 				    port_peernode(p_ptr),
 				    imp,
 				    TIPC_CONN_MSG,
-				    err, 
+				    err,
 				    p_ptr->last_in_seqno + 1,
 				    0);
 }
@@ -582,7 +582,7 @@
 				    tipc_own_addr,
 				    imp,
 				    TIPC_CONN_MSG,
-				    err, 
+				    err,
 				    port_out_seqno(p_ptr),
 				    0);
 }
@@ -613,7 +613,7 @@
 			}
 		}
 		if (msg_type(msg) == CONN_ACK) {
-			int wakeup = tipc_port_congested(p_ptr) && 
+			int wakeup = tipc_port_congested(p_ptr) &&
 				     p_ptr->publ.congested &&
 				     p_ptr->wakeup;
 			p_ptr->acked += msg_msgcnt(msg);
@@ -630,8 +630,8 @@
 	}
 	if (err) {
 		r_buf = port_build_proto_msg(msg_origport(msg),
-					     msg_orignode(msg), 
-					     msg_destport(msg), 
+					     msg_orignode(msg),
+					     msg_destport(msg),
 					     tipc_own_addr,
 					     DATA_HIGH,
 					     TIPC_CONN_MSG,
@@ -643,10 +643,10 @@
 
 	/* All is fine */
 	if (msg_type(msg) == CONN_PROBE) {
-		r_buf = port_build_proto_msg(msg_origport(msg), 
-					     msg_orignode(msg), 
-					     msg_destport(msg), 
-					     tipc_own_addr, 
+		r_buf = port_build_proto_msg(msg_origport(msg),
+					     msg_orignode(msg),
+					     msg_destport(msg),
+					     tipc_own_addr,
 					     CONN_MANAGER,
 					     CONN_PROBE_REPLY,
 					     TIPC_OK,
@@ -665,39 +665,39 @@
 
 static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id)
 {
-        struct publication *publ;
+	struct publication *publ;
 
 	if (full_id)
-		tipc_printf(buf, "<%u.%u.%u:%u>:", 
+		tipc_printf(buf, "<%u.%u.%u:%u>:",
 			    tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
-                            tipc_node(tipc_own_addr), p_ptr->publ.ref);
+			    tipc_node(tipc_own_addr), p_ptr->publ.ref);
 	else
 		tipc_printf(buf, "%-10u:", p_ptr->publ.ref);
 
-        if (p_ptr->publ.connected) {
-                u32 dport = port_peerport(p_ptr);
-                u32 destnode = port_peernode(p_ptr);
+	if (p_ptr->publ.connected) {
+		u32 dport = port_peerport(p_ptr);
+		u32 destnode = port_peernode(p_ptr);
 
-                tipc_printf(buf, " connected to <%u.%u.%u:%u>",
-                            tipc_zone(destnode), tipc_cluster(destnode),
-                            tipc_node(destnode), dport);
-                if (p_ptr->publ.conn_type != 0)
-                        tipc_printf(buf, " via {%u,%u}",
-                                    p_ptr->publ.conn_type,
-                                    p_ptr->publ.conn_instance);
-        }
-        else if (p_ptr->publ.published) {
-                tipc_printf(buf, " bound to");
-                list_for_each_entry(publ, &p_ptr->publications, pport_list) {
+		tipc_printf(buf, " connected to <%u.%u.%u:%u>",
+			    tipc_zone(destnode), tipc_cluster(destnode),
+			    tipc_node(destnode), dport);
+		if (p_ptr->publ.conn_type != 0)
+			tipc_printf(buf, " via {%u,%u}",
+				    p_ptr->publ.conn_type,
+				    p_ptr->publ.conn_instance);
+	}
+	else if (p_ptr->publ.published) {
+		tipc_printf(buf, " bound to");
+		list_for_each_entry(publ, &p_ptr->publications, pport_list) {
 			if (publ->lower == publ->upper)
 				tipc_printf(buf, " {%u,%u}", publ->type,
 					    publ->lower);
 			else
-				tipc_printf(buf, " {%u,%u,%u}", publ->type, 
+				tipc_printf(buf, " {%u,%u,%u}", publ->type,
 					    publ->lower, publ->upper);
-                }
-        }
-        tipc_printf(buf, "\n");
+		}
+	}
+	tipc_printf(buf, "\n");
 }
 
 #define MAX_PORT_QUERY 32768
@@ -818,7 +818,7 @@
 		struct sk_buff *next = buf->next;
 		struct tipc_msg *msg = buf_msg(buf);
 		u32 dref = msg_destport(msg);
-		
+
 		message_type = msg_type(msg);
 		if (message_type > TIPC_DIRECT_MSG)
 			goto reject;	/* Unsupported message type */
@@ -838,7 +838,7 @@
 			goto err;
 
 		switch (message_type) {
-		
+
 		case TIPC_CONN_MSG:{
 				tipc_conn_msg_event cb = up_ptr->conn_msg_cb;
 				u32 peer_port = port_peerport(p_ptr);
@@ -856,9 +856,9 @@
 					goto reject;
 				if (unlikely(!cb))
 					goto reject;
-				if (unlikely(++p_ptr->publ.conn_unacked >= 
+				if (unlikely(++p_ptr->publ.conn_unacked >=
 					     TIPC_FLOW_CONTROL_WIN))
-					tipc_acknowledge(dref, 
+					tipc_acknowledge(dref,
 							 p_ptr->publ.conn_unacked);
 				skb_pull(buf, msg_hdr_sz(msg));
 				cb(usr_handle, dref, &buf, msg_data(msg),
@@ -874,7 +874,7 @@
 				if (unlikely(!cb))
 					goto reject;
 				skb_pull(buf, msg_hdr_sz(msg));
-				cb(usr_handle, dref, &buf, msg_data(msg), 
+				cb(usr_handle, dref, &buf, msg_data(msg),
 				   msg_data_sz(msg), msg_importance(msg),
 				   &orig);
 				break;
@@ -895,7 +895,7 @@
 				dseq.upper = (message_type == TIPC_NAMED_MSG)
 					? dseq.lower : msg_nameupper(msg);
 				skb_pull(buf, msg_hdr_sz(msg));
-				cb(usr_handle, dref, &buf, msg_data(msg), 
+				cb(usr_handle, dref, &buf, msg_data(msg),
 				   msg_data_sz(msg), msg_importance(msg),
 				   &orig, &dseq);
 				break;
@@ -907,9 +907,9 @@
 		continue;
 err:
 		switch (message_type) {
-		
+
 		case TIPC_CONN_MSG:{
-				tipc_conn_shutdown_event cb = 
+				tipc_conn_shutdown_event cb =
 					up_ptr->conn_err_cb;
 				u32 peer_port = port_peerport(p_ptr);
 				u32 peer_node = port_peernode(p_ptr);
@@ -940,7 +940,7 @@
 			}
 		case TIPC_MCAST_MSG:
 		case TIPC_NAMED_MSG:{
-				tipc_named_msg_err_event cb = 
+				tipc_named_msg_err_event cb =
 					up_ptr->named_err_cb;
 
 				spin_unlock_bh(p_ptr->publ.lock);
@@ -951,7 +951,7 @@
 				dseq.upper = (message_type == TIPC_NAMED_MSG)
 					? dseq.lower : msg_nameupper(msg);
 				skb_pull(buf, msg_hdr_sz(msg));
-				cb(usr_handle, dref, &buf, msg_data(msg), 
+				cb(usr_handle, dref, &buf, msg_data(msg),
 				   msg_data_sz(msg), msg_errcode(msg), &dseq);
 				break;
 			}
@@ -986,9 +986,9 @@
 	return TIPC_OK;
 }
 
-/* 
+/*
  * Wake up port after congestion: Called with port locked,
- *                                
+ *
  */
 
 static void port_wakeup_sh(unsigned long ref)
@@ -1033,7 +1033,7 @@
 					   tipc_own_addr,
 					   CONN_MANAGER,
 					   CONN_ACK,
-					   TIPC_OK, 
+					   TIPC_OK,
 					   port_out_seqno(p_ptr),
 					   ack);
 	}
@@ -1046,20 +1046,20 @@
  *                    registry if non-zero user_ref.
  */
 
-int tipc_createport(u32 user_ref, 
-		    void *usr_handle, 
-		    unsigned int importance, 
-		    tipc_msg_err_event error_cb, 
-		    tipc_named_msg_err_event named_error_cb, 
-		    tipc_conn_shutdown_event conn_error_cb, 
-		    tipc_msg_event msg_cb, 
-		    tipc_named_msg_event named_msg_cb, 
-		    tipc_conn_msg_event conn_msg_cb, 
+int tipc_createport(u32 user_ref,
+		    void *usr_handle,
+		    unsigned int importance,
+		    tipc_msg_err_event error_cb,
+		    tipc_named_msg_err_event named_error_cb,
+		    tipc_conn_shutdown_event conn_error_cb,
+		    tipc_msg_event msg_cb,
+		    tipc_named_msg_event named_msg_cb,
+		    tipc_conn_msg_event conn_msg_cb,
 		    tipc_continue_event continue_event_cb,/* May be zero */
 		    u32 *portref)
 {
 	struct user_port *up_ptr;
-	struct port *p_ptr; 
+	struct port *p_ptr;
 	u32 ref;
 
 	up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
@@ -1088,7 +1088,7 @@
 	INIT_LIST_HEAD(&up_ptr->uport_list);
 	tipc_reg_add_port(up_ptr);
 	*portref = p_ptr->publ.ref;
-	dbg(" tipc_createport: %x with ref %u\n", p_ptr, p_ptr->publ.ref);        
+	dbg(" tipc_createport: %x with ref %u\n", p_ptr, p_ptr->publ.ref);
 	tipc_port_unlock(p_ptr);
 	return TIPC_OK;
 }
@@ -1103,7 +1103,7 @@
 int tipc_portimportance(u32 ref, unsigned int *importance)
 {
 	struct port *p_ptr;
-	
+
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
@@ -1172,19 +1172,19 @@
 	struct publication *publ;
 	struct publication *tpubl;
 	int res = -EINVAL;
-	
+
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 	if (!seq) {
-		list_for_each_entry_safe(publ, tpubl, 
+		list_for_each_entry_safe(publ, tpubl,
 					 &p_ptr->publications, pport_list) {
-			tipc_nametbl_withdraw(publ->type, publ->lower, 
+			tipc_nametbl_withdraw(publ->type, publ->lower,
 					      publ->ref, publ->key);
 		}
 		res = TIPC_OK;
 	} else {
-		list_for_each_entry_safe(publ, tpubl, 
+		list_for_each_entry_safe(publ, tpubl,
 					 &p_ptr->publications, pport_list) {
 			if (publ->scope != scope)
 				continue;
@@ -1194,7 +1194,7 @@
 				continue;
 			if (publ->upper != seq->upper)
 				break;
-			tipc_nametbl_withdraw(publ->type, publ->lower, 
+			tipc_nametbl_withdraw(publ->type, publ->lower,
 					      publ->ref, publ->key);
 			res = TIPC_OK;
 			break;
@@ -1292,7 +1292,7 @@
 					   tipc_own_addr,
 					   imp,
 					   TIPC_CONN_MSG,
-					   TIPC_CONN_SHUTDOWN, 
+					   TIPC_CONN_SHUTDOWN,
 					   port_out_seqno(p_ptr),
 					   0);
 	}
@@ -1304,7 +1304,7 @@
 int tipc_isconnected(u32 ref, int *isconnected)
 {
 	struct port *p_ptr;
-	
+
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
@@ -1317,7 +1317,7 @@
 {
 	struct port *p_ptr;
 	int res;
-	 
+
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
@@ -1348,7 +1348,7 @@
 {
 	struct sk_buff *buf;
 	int res;
-	 
+
 	res = msg_build(&sender->publ.phdr, msg_sect, num_sect,
 			MAX_MSG_SIZE, !sender->user_port, &buf);
 	if (likely(buf))
@@ -1394,7 +1394,7 @@
 	return -ELINKCONG;
 }
 
-/** 
+/**
  * tipc_send_buf - send message buffer on connection
  */
 
@@ -1406,7 +1406,7 @@
 	u32 hsz;
 	u32 sz;
 	u32 res;
-	 
+
 	p_ptr = tipc_port_deref(ref);
 	if (!p_ptr || !p_ptr->publ.connected)
 		return -EINVAL;
@@ -1447,12 +1447,12 @@
  * tipc_forward2name - forward message sections to port name
  */
 
-int tipc_forward2name(u32 ref, 
-		      struct tipc_name const *name, 
+int tipc_forward2name(u32 ref,
+		      struct tipc_name const *name,
 		      u32 domain,
-		      u32 num_sect, 
+		      u32 num_sect,
 		      struct iovec const *msg_sect,
-		      struct tipc_portid const *orig, 
+		      struct tipc_portid const *orig,
 		      unsigned int importance)
 {
 	struct port *p_ptr;
@@ -1483,7 +1483,7 @@
 		p_ptr->sent++;
 		if (likely(destnode == tipc_own_addr))
 			return tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
-		res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, 
+		res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect,
 						   destnode);
 		if (likely(res != -ELINKCONG))
 			return res;
@@ -1493,7 +1493,7 @@
 		}
 		return -ELINKCONG;
 	}
-	return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, 
+	return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect,
 					 TIPC_ERR_NO_NAME);
 }
 
@@ -1501,10 +1501,10 @@
  * tipc_send2name - send message sections to port name
  */
 
-int tipc_send2name(u32 ref, 
+int tipc_send2name(u32 ref,
 		   struct tipc_name const *name,
-		   unsigned int domain, 
-		   unsigned int num_sect, 
+		   unsigned int domain,
+		   unsigned int num_sect,
 		   struct iovec const *msg_sect)
 {
 	struct tipc_portid orig;
@@ -1515,7 +1515,7 @@
 				 TIPC_PORT_IMPORTANCE);
 }
 
-/** 
+/**
  * tipc_forward_buf2name - forward message buffer to port name
  */
 
@@ -1571,14 +1571,14 @@
 	return tipc_reject_msg(buf, TIPC_ERR_NO_NAME);
 }
 
-/** 
+/**
  * tipc_send_buf2name - send message buffer to port name
  */
 
-int tipc_send_buf2name(u32 ref, 
-		       struct tipc_name const *dest, 
+int tipc_send_buf2name(u32 ref,
+		       struct tipc_name const *dest,
 		       u32 domain,
-		       struct sk_buff *buf, 
+		       struct sk_buff *buf,
 		       unsigned int dsz)
 {
 	struct tipc_portid orig;
@@ -1589,15 +1589,15 @@
 				     TIPC_PORT_IMPORTANCE);
 }
 
-/** 
+/**
  * tipc_forward2port - forward message sections to port identity
  */
 
 int tipc_forward2port(u32 ref,
 		      struct tipc_portid const *dest,
-		      unsigned int num_sect, 
+		      unsigned int num_sect,
 		      struct iovec const *msg_sect,
-		      struct tipc_portid const *orig, 
+		      struct tipc_portid const *orig,
 		      unsigned int importance)
 {
 	struct port *p_ptr;
@@ -1630,24 +1630,24 @@
 	return -ELINKCONG;
 }
 
-/** 
- * tipc_send2port - send message sections to port identity 
+/**
+ * tipc_send2port - send message sections to port identity
  */
 
-int tipc_send2port(u32 ref, 
+int tipc_send2port(u32 ref,
 		   struct tipc_portid const *dest,
-		   unsigned int num_sect, 
+		   unsigned int num_sect,
 		   struct iovec const *msg_sect)
 {
 	struct tipc_portid orig;
 
 	orig.ref = ref;
 	orig.node = tipc_own_addr;
-	return tipc_forward2port(ref, dest, num_sect, msg_sect, &orig, 
+	return tipc_forward2port(ref, dest, num_sect, msg_sect, &orig,
 				 TIPC_PORT_IMPORTANCE);
 }
 
-/** 
+/**
  * tipc_forward_buf2port - forward message buffer to port identity
  */
 int tipc_forward_buf2port(u32 ref,
@@ -1692,20 +1692,20 @@
 	return -ELINKCONG;
 }
 
-/** 
+/**
  * tipc_send_buf2port - send message buffer to port identity
  */
 
-int tipc_send_buf2port(u32 ref, 
+int tipc_send_buf2port(u32 ref,
 		       struct tipc_portid const *dest,
-		       struct sk_buff *buf, 
+		       struct sk_buff *buf,
 		       unsigned int dsz)
 {
 	struct tipc_portid orig;
 
 	orig.ref = ref;
 	orig.node = tipc_own_addr;
-	return tipc_forward_buf2port(ref, dest, buf, dsz, &orig, 
+	return tipc_forward_buf2port(ref, dest, buf, dsz, &orig,
 				     TIPC_PORT_IMPORTANCE);
 }
 
diff --git a/net/tipc/port.h b/net/tipc/port.h
index 839f100..7ef4d64 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/port.h: Include file for TIPC port code
- * 
+ *
  * Copyright (c) 1994-2006, Ericsson AB
  * Copyright (c) 2004-2005, Wind River Systems
  * All rights reserved.
@@ -52,17 +52,17 @@
  * <various callback routines>
  * @uport_list: adjacent user ports in list of ports held by user
  */
- 
+
 struct user_port {
 	u32 user_ref;
-	void *usr_handle; 
+	void *usr_handle;
 	u32 ref;
-	tipc_msg_err_event err_cb; 
-	tipc_named_msg_err_event named_err_cb; 
-	tipc_conn_shutdown_event conn_err_cb; 
-	tipc_msg_event msg_cb; 
-	tipc_named_msg_event named_msg_cb; 
-	tipc_conn_msg_event conn_msg_cb; 
+	tipc_msg_err_event err_cb;
+	tipc_named_msg_err_event named_err_cb;
+	tipc_conn_shutdown_event conn_err_cb;
+	tipc_msg_event msg_cb;
+	tipc_named_msg_event named_msg_cb;
+	tipc_conn_msg_event conn_msg_cb;
 	tipc_continue_event continue_event_cb;
 	struct list_head uport_list;
 };
@@ -113,7 +113,7 @@
 extern spinlock_t tipc_port_list_lock;
 struct port_list;
 
-int tipc_port_recv_sections(struct port *p_ptr, u32 num_sect, 
+int tipc_port_recv_sections(struct port *p_ptr, u32 num_sect,
 			    struct iovec const *msg_sect);
 int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
 			      struct iovec const *msg_sect, u32 num_sect,
@@ -133,9 +133,9 @@
 	return (struct port *)tipc_ref_lock(ref);
 }
 
-/** 
+/**
  * tipc_port_unlock - unlock a port instance
- * 
+ *
  * Can use pointer instead of tipc_ref_unlock() since port is already locked.
  */
 
@@ -164,7 +164,7 @@
 	return((p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2));
 }
 
-/** 
+/**
  * tipc_port_recv_msg - receive message from lower layer and deliver to port user
  */
 
@@ -175,7 +175,7 @@
 	u32 destport = msg_destport(msg);
 	u32 dsz = msg_data_sz(msg);
 	u32 err;
-	
+
 	/* forward unresolved named message */
 	if (unlikely(!destport)) {
 		tipc_net_route_msg(buf);
diff --git a/net/tipc/ref.c b/net/tipc/ref.c
index e6d6ae22..6704a58 100644
--- a/net/tipc/ref.c
+++ b/net/tipc/ref.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/ref.c: TIPC object registry code
- * 
+ *
  * Copyright (c) 1991-2006, Ericsson AB
  * Copyright (c) 2004-2005, Wind River Systems
  * All rights reserved.
@@ -50,11 +50,11 @@
  * Object reference table consists of 2**N entries.
  *
  * A used entry has object ptr != 0, reference == XXXX|own index
- *				     (XXXX changes each time entry is acquired) 
+ *				     (XXXX changes each time entry is acquired)
  * A free entry has object ptr == 0, reference == YYYY|next free index
  *				     (YYYY is one more than last used XXXX)
  *
- * Free list is initially chained from entry (2**N)-1 to entry 1. 
+ * Free list is initially chained from entry (2**N)-1 to entry 1.
  * Entry 0 is not used to allow index 0 to indicate the end of the free list.
  *
  * Note: Any accidental reference of the form XXXX|0--0 won't match entry 0
@@ -113,9 +113,9 @@
 
 /**
  * tipc_ref_acquire - create reference to an object
- * 
+ *
  * Return a unique reference value which can be translated back to the pointer
- * 'object' at a later time.  Also, pass back a pointer to the lock protecting 
+ * 'object' at a later time.  Also, pass back a pointer to the lock protecting
  * the object, but without locking it.
  */
 
@@ -141,15 +141,15 @@
 		index = tipc_ref_table.first_free;
 		entry = &(tipc_ref_table.entries[index]);
 		index_mask = tipc_ref_table.index_mask;
-		/* take lock in case a previous user of entry still holds it */ 
-		spin_lock_bh(&entry->lock);  
+		/* take lock in case a previous user of entry still holds it */
+		spin_lock_bh(&entry->lock);
 		next_plus_upper = entry->data.next_plus_upper;
 		tipc_ref_table.first_free = next_plus_upper & index_mask;
 		reference = (next_plus_upper & ~index_mask) + index;
 		entry->data.reference = reference;
 		entry->object = object;
-                if (lock != 0)
-                        *lock = &entry->lock;
+		if (lock != 0)
+			*lock = &entry->lock;
 		spin_unlock_bh(&entry->lock);
 	}
 	write_unlock_bh(&ref_table_lock);
@@ -158,7 +158,7 @@
 
 /**
  * tipc_ref_discard - invalidate references to an object
- * 
+ *
  * Disallow future references to an object and free up the entry for re-use.
  * Note: The entry's spin_lock may still be busy after discard
  */
@@ -166,7 +166,7 @@
 void tipc_ref_discard(u32 ref)
 {
 	struct reference *entry;
-	u32 index; 
+	u32 index;
 	u32 index_mask;
 
 	if (!ref) {
@@ -198,7 +198,7 @@
 		tipc_ref_table.first_free = index;
 	else
 		/* next_plus_upper is always XXXX|0--0 for last free entry */
-		tipc_ref_table.entries[tipc_ref_table.last_free].data.next_plus_upper 
+		tipc_ref_table.entries[tipc_ref_table.last_free].data.next_plus_upper
 			|= index;
 	tipc_ref_table.last_free = index;
 
diff --git a/net/tipc/ref.h b/net/tipc/ref.h
index 6d20006..38f3a7f 100644
--- a/net/tipc/ref.h
+++ b/net/tipc/ref.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/ref.h: Include file for TIPC object registry code
- * 
+ *
  * Copyright (c) 1991-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -43,7 +43,7 @@
  * @lock: spinlock controlling access to object
  * @data: reference value associated with object (or link to next unused entry)
  */
- 
+
 struct reference {
 	void *object;
 	spinlock_t lock;
@@ -96,7 +96,7 @@
 }
 
 /**
- * tipc_ref_unlock - unlock referenced object 
+ * tipc_ref_unlock - unlock referenced object
  */
 
 static inline void tipc_ref_unlock(u32 ref)
@@ -119,7 +119,7 @@
 static inline void *tipc_ref_deref(u32 ref)
 {
 	if (likely(tipc_ref_table.entries)) {
-		struct reference *r = 
+		struct reference *r =
 			&tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
 
 		if (likely(r->data.reference == ref))
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 2a6a5a6..b71739f 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/socket.c: TIPC socket API
- * 
+ *
  * Copyright (c) 2001-2006, Ericsson AB
  * Copyright (c) 2004-2006, Wind River Systems
  * All rights reserved.
@@ -82,29 +82,29 @@
 static atomic_t tipc_queue_size = ATOMIC_INIT(0);
 
 
-/* 
- * sock_lock(): Lock a port/socket pair. lock_sock() can 
- * not be used here, since the same lock must protect ports 
+/*
+ * sock_lock(): Lock a port/socket pair. lock_sock() can
+ * not be used here, since the same lock must protect ports
  * with non-socket interfaces.
  * See net.c for description of locking policy.
  */
 static void sock_lock(struct tipc_sock* tsock)
 {
-        spin_lock_bh(tsock->p->lock);       
+	spin_lock_bh(tsock->p->lock);
 }
 
-/* 
+/*
  * sock_unlock(): Unlock a port/socket pair
  */
 static void sock_unlock(struct tipc_sock* tsock)
 {
-        spin_unlock_bh(tsock->p->lock);
+	spin_unlock_bh(tsock->p->lock);
 }
 
 /**
  * pollmask - determine the current set of poll() events for a socket
  * @sock: socket structure
- * 
+ *
  * TIPC sets the returned events as follows:
  * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
  *    or if a connection-oriented socket is does not have an active connection
@@ -115,7 +115,7 @@
  *
  * IMPORTANT: The fact that a read or write operation will not block does NOT
  * imply that the operation will succeed!
- * 
+ *
  * Returns pollmask value
  */
 
@@ -130,7 +130,7 @@
 	else
 		mask = 0;
 
-	if (sock->state == SS_DISCONNECTING) 
+	if (sock->state == SS_DISCONNECTING)
 		mask |= POLLHUP;
 	else
 		mask |= POLLOUT;
@@ -146,9 +146,9 @@
 
 static void advance_queue(struct tipc_sock *tsock)
 {
-        sock_lock(tsock);
+	sock_lock(tsock);
 	buf_discard(skb_dequeue(&tsock->sk.sk_receive_queue));
-        sock_unlock(tsock);
+	sock_unlock(tsock);
 	atomic_dec(&tipc_queue_size);
 }
 
@@ -156,7 +156,7 @@
  * tipc_create - create a TIPC socket
  * @sock: pre-allocated socket structure
  * @protocol: protocol indicator (must be 0)
- * 
+ *
  * This routine creates and attaches a 'struct sock' to the 'struct socket',
  * then create and attaches a TIPC port to the 'struct sock' part.
  *
@@ -167,7 +167,7 @@
 	struct tipc_sock *tsock;
 	struct tipc_port *port;
 	struct sock *sk;
-        u32 ref;
+	u32 ref;
 
 	if (unlikely(protocol != 0))
 		return -EPROTONOSUPPORT;
@@ -232,7 +232,7 @@
  * For SEQPACKET and STREAM socket types, the first message is rejected
  * and any others are discarded.  (If the first message on a STREAM socket
  * is partially-read, it is discarded and the next one is rejected instead.)
- * 
+ *
  * NOTE: Rejected messages are not necessarily returned to the sender!  They
  * are returned or discarded according to the "destination droppable" setting
  * specified for the message by the sender.
@@ -247,7 +247,7 @@
 	int res = TIPC_OK;
 	struct sk_buff *buf;
 
-        dbg("sock_delete: %x\n",tsock);
+	dbg("sock_delete: %x\n",tsock);
 	if (!tsock)
 		return 0;
 	down_interruptible(&tsock->sem);
@@ -255,7 +255,7 @@
 		up(&tsock->sem);
 		return 0;
 	}
-	
+
 	/* Reject unreceived messages, unless no longer connected */
 
 	while (sock->state != SS_DISCONNECTING) {
@@ -289,7 +289,7 @@
 
 	sock_put(sk);
 
-        atomic_dec(&tipc_user_count);
+	atomic_dec(&tipc_user_count);
 	return res;
 }
 
@@ -298,11 +298,11 @@
  * @sock: socket structure
  * @uaddr: socket address describing name(s) and desired operation
  * @uaddr_len: size of socket address data structure
- * 
+ *
  * Name and name sequence binding is indicated using a positive scope value;
  * a negative scope value unbinds the specified name.  Specifying no name
  * (i.e. a socket address length of 0) unbinds all names from the socket.
- * 
+ *
  * Returns 0 on success, errno otherwise
  */
 
@@ -314,7 +314,7 @@
 
 	if (down_interruptible(&tsock->sem))
 		return -ERESTARTSYS;
-	
+
 	if (unlikely(!uaddr_len)) {
 		res = tipc_withdraw(tsock->p->ref, 0, NULL);
 		goto exit;
@@ -335,8 +335,8 @@
 		res = -EAFNOSUPPORT;
 		goto exit;
 	}
-        
-       	if (addr->scope > 0)
+
+	if (addr->scope > 0)
 		res = tipc_publish(tsock->p->ref, addr->scope,
 				   &addr->addr.nameseq);
 	else
@@ -347,17 +347,17 @@
 	return res;
 }
 
-/** 
+/**
  * get_name - get port ID of socket or peer socket
  * @sock: socket structure
  * @uaddr: area for returned socket address
  * @uaddr_len: area for returned length of socket address
  * @peer: 0 to obtain socket name, 1 to obtain peer socket name
- * 
+ *
  * Returns 0 on success, errno otherwise
  */
 
-static int get_name(struct socket *sock, struct sockaddr *uaddr, 
+static int get_name(struct socket *sock, struct sockaddr *uaddr,
 		    int *uaddr_len, int peer)
 {
 	struct tipc_sock *tsock = tipc_sk(sock->sk);
@@ -390,7 +390,7 @@
  * Returns the pollmask
  */
 
-static unsigned int poll(struct file *file, struct socket *sock, 
+static unsigned int poll(struct file *file, struct socket *sock,
 			 poll_table *wait)
 {
 	poll_wait(file, sock->sk->sk_sleep, wait);
@@ -398,14 +398,14 @@
 	return pollmask(sock);
 }
 
-/** 
+/**
  * dest_name_check - verify user is permitted to send to specified port name
  * @dest: destination address
  * @m: descriptor for message to be sent
- * 
+ *
  * Prevents restricted configuration commands from being issued by
  * unauthorized users.
- * 
+ *
  * Returns 0 if permission is granted, otherwise errno
  */
 
@@ -413,19 +413,19 @@
 {
 	struct tipc_cfg_msg_hdr hdr;
 
-        if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES))
-                return 0;
-        if (likely(dest->addr.name.name.type == TIPC_TOP_SRV))
-                return 0;
+	if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES))
+		return 0;
+	if (likely(dest->addr.name.name.type == TIPC_TOP_SRV))
+		return 0;
 
-        if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
-                return -EACCES;
+	if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
+		return -EACCES;
 
-        if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr)))
+	if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr)))
 		return -EFAULT;
 	if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN)))
 		return -EACCES;
-        
+
 	return 0;
 }
 
@@ -435,12 +435,12 @@
  * @sock: socket structure
  * @m: message to send
  * @total_len: length of message
- * 
+ *
  * Message must have an destination specified explicitly.
- * Used for SOCK_RDM and SOCK_DGRAM messages, 
+ * Used for SOCK_RDM and SOCK_DGRAM messages,
  * and for 'SYN' messages on SOCK_SEQPACKET and SOCK_STREAM connections.
  * (Note: 'SYN+' is prohibited on SOCK_STREAM.)
- * 
+ *
  * Returns the number of bytes sent on success, or errno otherwise
  */
 
@@ -448,7 +448,7 @@
 		    struct msghdr *m, size_t total_len)
 {
 	struct tipc_sock *tsock = tipc_sk(sock->sk);
-        struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
+	struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
 	struct sk_buff *buf;
 	int needs_conn;
 	int res = -EINVAL;
@@ -489,61 +489,61 @@
 		sock->state = SS_CONNECTING;
 	}
 
-        do {
-                if (dest->addrtype == TIPC_ADDR_NAME) {
-                        if ((res = dest_name_check(dest, m)))
-                                goto exit;
-                        res = tipc_send2name(tsock->p->ref,
-                                             &dest->addr.name.name,
-                                             dest->addr.name.domain, 
-                                             m->msg_iovlen,
-                                             m->msg_iov);
-                }
-                else if (dest->addrtype == TIPC_ADDR_ID) {
-                        res = tipc_send2port(tsock->p->ref,
-                                             &dest->addr.id,
-                                             m->msg_iovlen,
-                                             m->msg_iov);
-                }
-                else if (dest->addrtype == TIPC_ADDR_MCAST) {
+	do {
+		if (dest->addrtype == TIPC_ADDR_NAME) {
+			if ((res = dest_name_check(dest, m)))
+				goto exit;
+			res = tipc_send2name(tsock->p->ref,
+					     &dest->addr.name.name,
+					     dest->addr.name.domain,
+					     m->msg_iovlen,
+					     m->msg_iov);
+		}
+		else if (dest->addrtype == TIPC_ADDR_ID) {
+			res = tipc_send2port(tsock->p->ref,
+					     &dest->addr.id,
+					     m->msg_iovlen,
+					     m->msg_iov);
+		}
+		else if (dest->addrtype == TIPC_ADDR_MCAST) {
 			if (needs_conn) {
 				res = -EOPNOTSUPP;
 				goto exit;
 			}
-                        if ((res = dest_name_check(dest, m)))
-                                goto exit;
-                        res = tipc_multicast(tsock->p->ref,
-                                             &dest->addr.nameseq,
-                                             0,
-                                             m->msg_iovlen,
-                                             m->msg_iov);
-                }
-                if (likely(res != -ELINKCONG)) {
-exit:                                
-                        up(&tsock->sem);
-                        return res;
-                }
+			if ((res = dest_name_check(dest, m)))
+				goto exit;
+			res = tipc_multicast(tsock->p->ref,
+					     &dest->addr.nameseq,
+					     0,
+					     m->msg_iovlen,
+					     m->msg_iov);
+		}
+		if (likely(res != -ELINKCONG)) {
+exit:
+			up(&tsock->sem);
+			return res;
+		}
 		if (m->msg_flags & MSG_DONTWAIT) {
 			res = -EWOULDBLOCK;
 			goto exit;
 		}
-                if (wait_event_interruptible(*sock->sk->sk_sleep,
-                                             !tsock->p->congested)) {
-                    res = -ERESTARTSYS;
-                    goto exit;
-                }
-        } while (1);
+		if (wait_event_interruptible(*sock->sk->sk_sleep,
+					     !tsock->p->congested)) {
+		    res = -ERESTARTSYS;
+		    goto exit;
+		}
+	} while (1);
 }
 
-/** 
+/**
  * send_packet - send a connection-oriented message
  * @iocb: (unused)
  * @sock: socket structure
  * @m: message to send
  * @total_len: length of message
- * 
+ *
  * Used for SOCK_SEQPACKET messages and SOCK_STREAM data.
- * 
+ *
  * Returns the number of bytes sent on success, or errno otherwise
  */
 
@@ -551,7 +551,7 @@
 		       struct msghdr *m, size_t total_len)
 {
 	struct tipc_sock *tsock = tipc_sk(sock->sk);
-        struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
+	struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
 	int res;
 
 	/* Handle implied connection establishment */
@@ -561,45 +561,45 @@
 
 	if (down_interruptible(&tsock->sem)) {
 		return -ERESTARTSYS;
-        }
+	}
 
-        do {
+	do {
 		if (unlikely(sock->state != SS_CONNECTED)) {
 			if (sock->state == SS_DISCONNECTING)
-				res = -EPIPE;   
+				res = -EPIPE;
 			else
 				res = -ENOTCONN;
 			goto exit;
 		}
 
-                res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov);
-                if (likely(res != -ELINKCONG)) {
+		res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov);
+		if (likely(res != -ELINKCONG)) {
 exit:
-                        up(&tsock->sem);
-                        return res;
-                }
+			up(&tsock->sem);
+			return res;
+		}
 		if (m->msg_flags & MSG_DONTWAIT) {
 			res = -EWOULDBLOCK;
 			goto exit;
 		}
-                if (wait_event_interruptible(*sock->sk->sk_sleep,
-                                             !tsock->p->congested)) {
-                    res = -ERESTARTSYS;
-                    goto exit;
-                }
-        } while (1);
+		if (wait_event_interruptible(*sock->sk->sk_sleep,
+					     !tsock->p->congested)) {
+		    res = -ERESTARTSYS;
+		    goto exit;
+		}
+	} while (1);
 }
 
-/** 
+/**
  * send_stream - send stream-oriented data
  * @iocb: (unused)
  * @sock: socket structure
  * @m: data to send
  * @total_len: total length of data to be sent
- * 
+ *
  * Used for SOCK_STREAM data.
- * 
- * Returns the number of bytes sent on success (or partial success), 
+ *
+ * Returns the number of bytes sent on success (or partial success),
  * or errno if no data sent
  */
 
@@ -616,26 +616,26 @@
 	int bytes_to_send;
 	int bytes_sent;
 	int res;
-	
+
 	if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE))
 		return send_packet(iocb, sock, m, total_len);
 
 	/* Can only send large data streams if already connected */
 
-        if (unlikely(sock->state != SS_CONNECTED)) {
-                if (sock->state == SS_DISCONNECTING)
-                        return -EPIPE;   
-                else
-                        return -ENOTCONN;
-        }
+	if (unlikely(sock->state != SS_CONNECTED)) {
+		if (sock->state == SS_DISCONNECTING)
+			return -EPIPE;
+		else
+			return -ENOTCONN;
+	}
 
 	if (unlikely(m->msg_name))
 		return -EISCONN;
 
-	/* 
+	/*
 	 * Send each iovec entry using one or more messages
 	 *
-	 * Note: This algorithm is good for the most likely case 
+	 * Note: This algorithm is good for the most likely case
 	 * (i.e. one large iovec entry), but could be improved to pass sets
 	 * of small iovec entries into send_packet().
 	 */
@@ -657,7 +657,7 @@
 				? curr_left : TIPC_MAX_USER_MSG_SIZE;
 			my_iov.iov_base = curr_start;
 			my_iov.iov_len = bytes_to_send;
-                        if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) {
+			if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) {
 				return bytes_sent ? bytes_sent : res;
 			}
 			curr_left -= bytes_to_send;
@@ -676,11 +676,11 @@
  * @sock: socket structure
  * @tsock: TIPC-specific socket structure
  * @msg: peer's response message
- * 
+ *
  * Returns 0 on success, errno otherwise
  */
 
-static int auto_connect(struct socket *sock, struct tipc_sock *tsock, 
+static int auto_connect(struct socket *sock, struct tipc_sock *tsock,
 			struct tipc_msg *msg)
 {
 	struct tipc_portid peer;
@@ -702,15 +702,15 @@
  * set_orig_addr - capture sender's address for received message
  * @m: descriptor for message info
  * @msg: received message header
- * 
+ *
  * Note: Address is not captured if not requested by receiver.
  */
 
 static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
 {
-        struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name;
+	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name;
 
-        if (addr) {
+	if (addr) {
 		addr->family = AF_TIPC;
 		addr->addrtype = TIPC_ADDR_ID;
 		addr->addr.id.ref = msg_origport(msg);
@@ -722,13 +722,13 @@
 }
 
 /**
- * anc_data_recv - optionally capture ancillary data for received message 
+ * anc_data_recv - optionally capture ancillary data for received message
  * @m: descriptor for message info
  * @msg: received message header
  * @tport: TIPC port associated with message
- * 
+ *
  * Note: Ancillary data is not captured if not requested by receiver.
- * 
+ *
  * Returns 0 if successful, otherwise errno
  */
 
@@ -753,7 +753,7 @@
 		if ((res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data)))
 			return res;
 		if (anc_data[1] &&
-		    (res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], 
+		    (res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1],
 				    msg_data(msg))))
 			return res;
 	}
@@ -790,13 +790,13 @@
 	return 0;
 }
 
-/** 
+/**
  * recv_msg - receive packet-oriented message
  * @iocb: (unused)
  * @m: descriptor for message info
  * @buf_len: total size of user buffer area
  * @flags: receive flags
- * 
+ *
  * Used for SOCK_DGRAM, SOCK_RDM, and SOCK_SEQPACKET messages.
  * If the complete message doesn't fit in user area, truncate it.
  *
@@ -827,9 +827,9 @@
 	if (sock->type == SOCK_SEQPACKET) {
 		if (unlikely(sock->state == SS_UNCONNECTED))
 			return -ENOTCONN;
-		if (unlikely((sock->state == SS_DISCONNECTING) && 
+		if (unlikely((sock->state == SS_DISCONNECTING) &&
 			     (skb_queue_len(&sock->sk->sk_receive_queue) == 0)))
-		       	return -ENOTCONN;
+			return -ENOTCONN;
 	}
 
 	/* Look for a message in receive queue; wait if necessary */
@@ -845,7 +845,7 @@
 	}
 
 	if ((res = wait_event_interruptible(
-		*sock->sk->sk_sleep, 
+		*sock->sk->sk_sleep,
 		((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
 		 (sock->state == SS_DISCONNECTING))) )) {
 		goto exit;
@@ -890,7 +890,7 @@
 		goto exit;
 
 	/* Capture message data (if valid) & compute return value (always) */
-	
+
 	if (!err) {
 		if (unlikely(buf_len < sz)) {
 			sz = buf_len;
@@ -913,23 +913,23 @@
 	/* Consume received message (optional) */
 
 	if (likely(!(flags & MSG_PEEK))) {
-                if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
-                        tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
+		if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
+			tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
 		advance_queue(tsock);
-        }
+	}
 exit:
 	up(&tsock->sem);
 	return res;
 }
 
-/** 
+/**
  * recv_stream - receive stream-oriented data
  * @iocb: (unused)
  * @m: descriptor for message info
  * @buf_len: total size of user buffer area
  * @flags: receive flags
- * 
- * Used for SOCK_STREAM messages only.  If not enough data is available 
+ *
+ * Used for SOCK_STREAM messages only.  If not enough data is available
  * will optionally wait for more; never truncates data.
  *
  * Returns size of returned message data, errno otherwise
@@ -980,7 +980,7 @@
 	}
 
 	if ((res = wait_event_interruptible(
-		*sock->sk->sk_sleep, 
+		*sock->sk->sk_sleep,
 		((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
 		 (sock->state == SS_DISCONNECTING))) )) {
 		goto exit;
@@ -1017,7 +1017,7 @@
 	}
 
 	/* Capture message data (if valid) & compute return value (always) */
-	
+
 	if (!err) {
 		buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
 		sz = buf->tail - buf_crs;
@@ -1050,14 +1050,14 @@
 	/* Consume received message (optional) */
 
 	if (likely(!(flags & MSG_PEEK))) {
-                if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
-                        tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
+		if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
+			tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
 		advance_queue(tsock);
-        }
+	}
 
 	/* Loop around if more data is required */
 
-	if ((sz_copied < buf_len)    /* didn't get all requested data */ 
+	if ((sz_copied < buf_len)    /* didn't get all requested data */
 	    && (flags & MSG_WAITALL) /* ... and need to wait for more */
 	    && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */
 	    && (!err)                /* ... and haven't reached a FIN */
@@ -1074,7 +1074,7 @@
  * @queue_size: current size of queue
  * @base: nominal maximum size of queue
  * @msg: message to be added to queue
- * 
+ *
  * Returns 1 if queue is currently overloaded, 0 otherwise
  */
 
@@ -1098,7 +1098,7 @@
 	return (queue_size > threshold);
 }
 
-/** 
+/**
  * async_disconnect - wrapper function used to disconnect port
  * @portref: TIPC port reference (passed as pointer-sized value)
  */
@@ -1108,13 +1108,13 @@
 	tipc_disconnect((u32)portref);
 }
 
-/** 
+/**
  * dispatch - handle arriving message
  * @tport: TIPC port that received message
  * @buf: message
- * 
+ *
  * Called with port locked.  Must not take socket lock to avoid deadlock risk.
- * 
+ *
  * Returns TIPC error status code (TIPC_OK if message is not to be rejected)
  */
 
@@ -1159,13 +1159,13 @@
 				msg_dbg(msg, "dispatch filter 4\n");
 				return TIPC_ERR_NO_PORT;
 			}
-		} 
+		}
 		else if (sock->state == SS_LISTENING) {
 			if (msg_connected(msg) || msg_errcode(msg)) {
 				msg_dbg(msg, "dispatch filter 5\n");
 				return TIPC_ERR_NO_PORT;
 			}
-		} 
+		}
 		else if (sock->state == SS_DISCONNECTING) {
 			msg_dbg(msg, "dispatch filter 6\n");
 			return TIPC_ERR_NO_PORT;
@@ -1180,18 +1180,18 @@
 
 	/* Reject message if there isn't room to queue it */
 
-	if (unlikely((u32)atomic_read(&tipc_queue_size) > 
+	if (unlikely((u32)atomic_read(&tipc_queue_size) >
 		     OVERLOAD_LIMIT_BASE)) {
-		if (queue_overloaded(atomic_read(&tipc_queue_size), 
+		if (queue_overloaded(atomic_read(&tipc_queue_size),
 				     OVERLOAD_LIMIT_BASE, msg))
 			return TIPC_ERR_OVERLOAD;
-        }
+	}
 	recv_q_len = skb_queue_len(&tsock->sk.sk_receive_queue);
 	if (unlikely(recv_q_len > (OVERLOAD_LIMIT_BASE / 2))) {
-		if (queue_overloaded(recv_q_len, 
-				     OVERLOAD_LIMIT_BASE / 2, msg)) 
+		if (queue_overloaded(recv_q_len,
+				     OVERLOAD_LIMIT_BASE / 2, msg))
 			return TIPC_ERR_OVERLOAD;
-        }
+	}
 
 	/* Initiate connection termination for an incoming 'FIN' */
 
@@ -1213,10 +1213,10 @@
 	return TIPC_OK;
 }
 
-/** 
+/**
  * wakeupdispatch - wake up port after congestion
  * @tport: port to wakeup
- * 
+ *
  * Called with port lock on.
  */
 
@@ -1238,7 +1238,7 @@
  * Returns 0 on success, errno otherwise
  */
 
-static int connect(struct socket *sock, struct sockaddr *dest, int destlen, 
+static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
 		   int flags)
 {
    struct tipc_sock *tsock = tipc_sk(sock->sk);
@@ -1260,7 +1260,7 @@
    if (sock->state == SS_CONNECTING)
 	   return -EALREADY;
    if (sock->state != SS_UNCONNECTED)
-           return -EISCONN;
+	   return -EISCONN;
 
    /*
     * Reject connection attempt using multicast address
@@ -1270,7 +1270,7 @@
     */
 
    if (dst->addrtype == TIPC_ADDR_MCAST)
-           return -EINVAL;
+	   return -EINVAL;
 
    /* Send a 'SYN-' to destination */
 
@@ -1281,19 +1281,19 @@
 	   return res;
    }
 
-   if (down_interruptible(&tsock->sem)) 
-           return -ERESTARTSYS;
-	
+   if (down_interruptible(&tsock->sem))
+	   return -ERESTARTSYS;
+
    /* Wait for destination's 'ACK' response */
 
    res = wait_event_interruptible_timeout(*sock->sk->sk_sleep,
-                                          skb_queue_len(&sock->sk->sk_receive_queue),
+					  skb_queue_len(&sock->sk->sk_receive_queue),
 					  sock->sk->sk_rcvtimeo);
    buf = skb_peek(&sock->sk->sk_receive_queue);
    if (res > 0) {
 	   msg = buf_msg(buf);
-           res = auto_connect(sock, tsock, msg);
-           if (!res) {
+	   res = auto_connect(sock, tsock, msg);
+	   if (!res) {
 		   if (!msg_data_sz(msg))
 			   advance_queue(tsock);
 	   }
@@ -1301,7 +1301,7 @@
 	   if (res == 0) {
 		   res = -ETIMEDOUT;
 	   } else
-	           { /* leave "res" unchanged */ }
+		   { /* leave "res" unchanged */ }
 	   sock->state = SS_DISCONNECTING;
    }
 
@@ -1309,11 +1309,11 @@
    return res;
 }
 
-/** 
+/**
  * listen - allow socket to listen for incoming connections
  * @sock: socket structure
  * @len: (unused)
- * 
+ *
  * Returns 0 on success, errno otherwise
  */
 
@@ -1326,15 +1326,15 @@
 	if (sock->state != SS_UNCONNECTED)
 		return -EINVAL;
 	sock->state = SS_LISTENING;
-        return 0;
+	return 0;
 }
 
-/** 
+/**
  * accept - wait for connection request
  * @sock: listening socket
  * @newsock: new socket that is to be connected
  * @flags: file-related flags associated with socket
- * 
+ *
  * Returns 0 on success, errno otherwise
  */
 
@@ -1348,15 +1348,15 @@
 		return -EOPNOTSUPP;
 	if (sock->state != SS_LISTENING)
 		return -EINVAL;
-	
-	if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && 
+
+	if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
 		     (flags & O_NONBLOCK)))
 		return -EWOULDBLOCK;
 
 	if (down_interruptible(&tsock->sem))
 		return -ERESTARTSYS;
 
-	if (wait_event_interruptible(*sock->sk->sk_sleep, 
+	if (wait_event_interruptible(*sock->sk->sk_sleep,
 				     skb_queue_len(&sock->sk->sk_receive_queue))) {
 		res = -ERESTARTSYS;
 		goto exit;
@@ -1381,18 +1381,18 @@
 			new_tsock->p->conn_instance = msg_nameinst(msg);
 		}
 
-               /* 
+	       /*
 		 * Respond to 'SYN-' by discarding it & returning 'ACK'-.
 		 * Respond to 'SYN+' by queuing it on new socket.
 		 */
 
 		msg_dbg(msg,"<ACC<: ");
-                if (!msg_data_sz(msg)) {
-                        struct msghdr m = {NULL,};
+		if (!msg_data_sz(msg)) {
+			struct msghdr m = {NULL,};
 
-                        send_packet(NULL, newsock, &m, 0);
-                        advance_queue(tsock);
-                } else {
+			send_packet(NULL, newsock, &m, 0);
+			advance_queue(tsock);
+		} else {
 			sock_lock(tsock);
 			skb_dequeue(&sock->sk->sk_receive_queue);
 			sock_unlock(tsock);
@@ -1410,7 +1410,7 @@
  * @how: direction to close (unused; always treated as read + write)
  *
  * Terminates connection (if necessary), then purges socket's receive queue.
- * 
+ *
  * Returns 0 on success, errno otherwise
  */
 
@@ -1483,32 +1483,32 @@
  * @opt: option identifier
  * @ov: pointer to new option value
  * @ol: length of option value
- * 
- * For stream sockets only, accepts and ignores all IPPROTO_TCP options 
+ *
+ * For stream sockets only, accepts and ignores all IPPROTO_TCP options
  * (to ease compatibility).
- * 
+ *
  * Returns 0 on success, errno otherwise
  */
 
-static int setsockopt(struct socket *sock, 
+static int setsockopt(struct socket *sock,
 		      int lvl, int opt, char __user *ov, int ol)
 {
 	struct tipc_sock *tsock = tipc_sk(sock->sk);
 	u32 value;
 	int res;
 
-        if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
-                return 0;
+	if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
+		return 0;
 	if (lvl != SOL_TIPC)
 		return -ENOPROTOOPT;
 	if (ol < sizeof(value))
 		return -EINVAL;
-        if ((res = get_user(value, (u32 __user *)ov)))
+	if ((res = get_user(value, (u32 __user *)ov)))
 		return res;
 
-	if (down_interruptible(&tsock->sem)) 
+	if (down_interruptible(&tsock->sem))
 		return -ERESTARTSYS;
-	
+
 	switch (opt) {
 	case TIPC_IMPORTANCE:
 		res = tipc_set_portimportance(tsock->p->ref, value);
@@ -1516,7 +1516,7 @@
 	case TIPC_SRC_DROPPABLE:
 		if (sock->type != SOCK_STREAM)
 			res = tipc_set_portunreliable(tsock->p->ref, value);
-		else 
+		else
 			res = -ENOPROTOOPT;
 		break;
 	case TIPC_DEST_DROPPABLE:
@@ -1540,29 +1540,29 @@
  * @opt: option identifier
  * @ov: receptacle for option value
  * @ol: receptacle for length of option value
- * 
- * For stream sockets only, returns 0 length result for all IPPROTO_TCP options 
+ *
+ * For stream sockets only, returns 0 length result for all IPPROTO_TCP options
  * (to ease compatibility).
- * 
+ *
  * Returns 0 on success, errno otherwise
  */
 
-static int getsockopt(struct socket *sock, 
+static int getsockopt(struct socket *sock,
 		      int lvl, int opt, char __user *ov, int __user *ol)
 {
 	struct tipc_sock *tsock = tipc_sk(sock->sk);
-        int len;
+	int len;
 	u32 value;
-        int res;
+	int res;
 
-        if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
-                return put_user(0, ol);
+	if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
+		return put_user(0, ol);
 	if (lvl != SOL_TIPC)
 		return -ENOPROTOOPT;
-        if ((res = get_user(len, ol)))
-                return res;
+	if ((res = get_user(len, ol)))
+		return res;
 
-	if (down_interruptible(&tsock->sem)) 
+	if (down_interruptible(&tsock->sem))
 		return -ERESTARTSYS;
 
 	switch (opt) {
@@ -1595,30 +1595,30 @@
 		res = put_user(sizeof(value), ol);
 	}
 
-        up(&tsock->sem);
+	up(&tsock->sem);
 	return res;
 }
 
 /**
  * Placeholders for non-implemented functionality
- * 
+ *
  * Returns error code (POSIX-compliant where defined)
  */
 
 static int ioctl(struct socket *s, u32 cmd, unsigned long arg)
 {
-        return -EINVAL;
+	return -EINVAL;
 }
 
 static int no_mmap(struct file *file, struct socket *sock,
-                   struct vm_area_struct *vma)
+		   struct vm_area_struct *vma)
 {
-        return -EINVAL;
+	return -EINVAL;
 }
 static ssize_t no_sendpage(struct socket *sock, struct page *page,
-                           int offset, size_t size, int flags)
+			   int offset, size_t size, int flags)
 {
-        return -EINVAL;
+	return -EINVAL;
 }
 
 static int no_skpair(struct socket *s1, struct socket *s2)
@@ -1647,8 +1647,8 @@
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_msg,
 	.recvmsg	= recv_msg,
-        .mmap		= no_mmap,
-        .sendpage	= no_sendpage
+	.mmap		= no_mmap,
+	.sendpage	= no_sendpage
 };
 
 static struct proto_ops packet_ops = {
@@ -1668,8 +1668,8 @@
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_packet,
 	.recvmsg	= recv_msg,
-        .mmap		= no_mmap,
-        .sendpage	= no_sendpage
+	.mmap		= no_mmap,
+	.sendpage	= no_sendpage
 };
 
 static struct proto_ops stream_ops = {
@@ -1689,8 +1689,8 @@
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_stream,
 	.recvmsg	= recv_stream,
-        .mmap		= no_mmap,
-        .sendpage	= no_sendpage
+	.mmap		= no_mmap,
+	.sendpage	= no_sendpage
 };
 
 static struct net_proto_family tipc_family_ops = {
@@ -1707,14 +1707,14 @@
 
 /**
  * tipc_socket_init - initialize TIPC socket interface
- * 
+ *
  * Returns 0 on success, errno otherwise
  */
 int tipc_socket_init(void)
 {
 	int res;
 
-        res = proto_register(&tipc_proto, 1);
+	res = proto_register(&tipc_proto, 1);
 	if (res) {
 		err("Failed to register TIPC protocol type\n");
 		goto out;
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index ddade73..8c01ccd 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/subscr.c: TIPC subscription service
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -49,10 +49,10 @@
  * @port_ref: object reference to port used to communicate with subscriber
  * @swap: indicates if subscriber uses opposite endianness in its messages
  */
- 
+
 struct subscriber {
 	u32 ref;
-        spinlock_t *lock;
+	spinlock_t *lock;
 	struct list_head subscriber_list;
 	struct list_head subscription_list;
 	u32 port_ref;
@@ -82,7 +82,7 @@
  * htohl - convert value to endianness used by destination
  * @in: value to convert
  * @swap: non-zero if endianness must be reversed
- * 
+ *
  * Returns converted value
  */
 
@@ -97,11 +97,11 @@
  * subscr_send_event - send a message containing a tipc_event to the subscriber
  */
 
-static void subscr_send_event(struct subscription *sub, 
-			      u32 found_lower, 
+static void subscr_send_event(struct subscription *sub,
+			      u32 found_lower,
 			      u32 found_upper,
-			      u32 event, 
-			      u32 port_ref, 
+			      u32 event,
+			      u32 port_ref,
 			      u32 node)
 {
 	struct iovec msg_sect;
@@ -123,8 +123,8 @@
  * Returns 1 if there is overlap, otherwise 0.
  */
 
-int tipc_subscr_overlap(struct subscription *sub, 
-			u32 found_lower, 
+int tipc_subscr_overlap(struct subscription *sub,
+			u32 found_lower,
 			u32 found_upper)
 
 {
@@ -139,15 +139,15 @@
 
 /**
  * tipc_subscr_report_overlap - issue event if there is subscription overlap
- * 
+ *
  * Protected by nameseq.lock in name_table.c
  */
 
-void tipc_subscr_report_overlap(struct subscription *sub, 
-				u32 found_lower, 
+void tipc_subscr_report_overlap(struct subscription *sub,
+				u32 found_lower,
 				u32 found_upper,
-				u32 event, 
-				u32 port_ref, 
+				u32 event,
+				u32 port_ref,
 				u32 node,
 				int must)
 {
@@ -189,11 +189,11 @@
 
 	/* Notify subscriber of timeout, then unlink subscription */
 
-	subscr_send_event(sub, 
-			  sub->evt.s.seq.lower, 
+	subscr_send_event(sub,
+			  sub->evt.s.seq.lower,
 			  sub->evt.s.seq.upper,
-			  TIPC_SUBSCR_TIMEOUT, 
-			  0, 
+			  TIPC_SUBSCR_TIMEOUT,
+			  0,
 			  0);
 	list_del(&sub->subscription_list);
 
@@ -221,11 +221,11 @@
 
 /**
  * subscr_terminate - terminate communication with a subscriber
- * 
+ *
  * Called with subscriber locked.  Routine must temporarily release this lock
- * to enable subscription timeout routine(s) to finish without deadlocking; 
+ * to enable subscription timeout routine(s) to finish without deadlocking;
  * the lock is then reclaimed to allow caller to release it upon return.
- * (This should work even in the unlikely event some other thread creates 
+ * (This should work even in the unlikely event some other thread creates
  * a new object reference in the interim that uses this lock; this routine will
  * simply wait for it to be released, then claim it.)
  */
@@ -241,7 +241,7 @@
 	spin_unlock_bh(subscriber->lock);
 
 	/* Destroy any existing subscriptions for subscriber */
-	
+
 	list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
 				 subscription_list) {
 		if (sub->timeout != TIPC_WAIT_FOREVER) {
@@ -315,7 +315,7 @@
 
 /**
  * subscr_subscribe - create subscription for subscriber
- * 
+ *
  * Called with subscriber locked
  */
 
@@ -431,7 +431,7 @@
 		subscr_terminate(subscriber);
 	else
 		subscr_subscribe((struct tipc_subscr *)data, subscriber);
-	
+
 	spin_unlock_bh(subscriber_lock);
 }
 
@@ -444,7 +444,7 @@
 				   struct sk_buff **buf,
 				   const unchar *data,
 				   u32 size,
-				   u32 importance, 
+				   u32 importance,
 				   struct tipc_portid const *orig,
 				   struct tipc_name_seq const *dest)
 {
@@ -534,22 +534,22 @@
 		return res;
 	}
 
- 	res = tipc_createport(topsrv.user_ref,
- 			      NULL,
- 			      TIPC_CRITICAL_IMPORTANCE,
- 			      NULL,
- 			      NULL,
- 			      NULL,
- 			      NULL,
- 			      subscr_named_msg_event,
- 			      NULL,
- 			      NULL,
- 			      &topsrv.setup_port);
- 	if (res)
+	res = tipc_createport(topsrv.user_ref,
+			      NULL,
+			      TIPC_CRITICAL_IMPORTANCE,
+			      NULL,
+			      NULL,
+			      NULL,
+			      NULL,
+			      subscr_named_msg_event,
+			      NULL,
+			      NULL,
+			      &topsrv.setup_port);
+	if (res)
 		goto failed;
 
- 	res = tipc_nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq);
- 	if (res)
+	res = tipc_nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq);
+	if (res)
 		goto failed;
 
 	spin_unlock_bh(&topsrv.lock);
@@ -571,7 +571,7 @@
 
 	if (topsrv.user_ref) {
 		tipc_deleteport(topsrv.setup_port);
-		list_for_each_entry_safe(subscriber, subscriber_temp, 
+		list_for_each_entry_safe(subscriber, subscriber_temp,
 					 &topsrv.subscriber_list,
 					 subscriber_list) {
 			tipc_ref_lock(subscriber->ref);
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h
index 1e50904..93a8e67 100644
--- a/net/tipc/subscr.h
+++ b/net/tipc/subscr.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/subscr.h: Include file for TIPC subscription service
- * 
+ *
  * Copyright (c) 2003-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -48,7 +48,7 @@
  * @timer_ref: reference to timer governing subscription duration (may be NULL)
  * @owner: pointer to subscriber object associated with this subscription
  */
- 
+
 struct subscription {
 	struct tipc_name_seq seq;
 	u32 timeout;
@@ -60,15 +60,15 @@
 	struct subscriber *owner;
 };
 
-int tipc_subscr_overlap(struct subscription * sub, 
-			u32 found_lower, 
+int tipc_subscr_overlap(struct subscription * sub,
+			u32 found_lower,
 			u32 found_upper);
 
-void tipc_subscr_report_overlap(struct subscription * sub, 
-				u32 found_lower, 
+void tipc_subscr_report_overlap(struct subscription * sub,
+				u32 found_lower,
 				u32 found_upper,
-				u32 event, 
-				u32 port_ref, 
+				u32 event,
+				u32 port_ref,
 				u32 node,
 				int must_report);
 
diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c
index 04d1b9b..4146c40 100644
--- a/net/tipc/user_reg.c
+++ b/net/tipc/user_reg.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/user_reg.c: TIPC user registry code
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2004-2005, Wind River Systems
  * All rights reserved.
@@ -40,7 +40,7 @@
 /*
  * TIPC user registry keeps track of users of the tipc_port interface.
  *
- * The registry utilizes an array of "TIPC user" entries; 
+ * The registry utilizes an array of "TIPC user" entries;
  * a user's ID is the index of their associated array entry.
  * Array entry 0 is not used, so userid 0 is not valid;
  * TIPC sometimes uses this value to denote an anonymous user.
@@ -51,7 +51,7 @@
  * struct tipc_user - registered TIPC user info
  * @next: index of next free registry entry (or -1 for an allocated entry)
  * @callback: ptr to routine to call when TIPC mode changes (NULL if none)
- * @usr_handle: user-defined value passed to callback routine 
+ * @usr_handle: user-defined value passed to callback routine
  * @ports: list of user ports owned by the user
  */
 
@@ -71,7 +71,7 @@
 
 /**
  * reg_init - create TIPC user registry (but don't activate it)
- * 
+ *
  * If registry has been pre-initialized it is left "as is".
  * NOTE: This routine may be called when TIPC is inactive.
  */
@@ -79,7 +79,7 @@
 static int reg_init(void)
 {
 	u32 i;
-	
+
 	spin_lock_bh(&reg_lock);
 	if (!users) {
 		users = kzalloc(USER_LIST_SIZE, GFP_ATOMIC);
@@ -137,7 +137,7 @@
  */
 
 void tipc_reg_stop(void)
-{               
+{
 	int id;
 
 	if (!users)
@@ -174,14 +174,14 @@
 	user_ptr = &users[next_free_user];
 	*userid = next_free_user;
 	next_free_user = user_ptr->next;
-	user_ptr->next = -1; 
+	user_ptr->next = -1;
 	spin_unlock_bh(&reg_lock);
 
 	user_ptr->callback = cb;
 	user_ptr->usr_handle = usr_handle;
 	INIT_LIST_HEAD(&user_ptr->ports);
 	atomic_inc(&tipc_user_count);
-	
+
 	if (cb && (tipc_mode != TIPC_NOT_RUNNING))
 		tipc_k_signal((Handler)reg_callback, (unsigned long)user_ptr);
 	return TIPC_OK;
@@ -207,16 +207,16 @@
 	}
 
 	user_ptr = &users[userid];
-        user_ptr->callback = NULL;              
+	user_ptr->callback = NULL;
 	INIT_LIST_HEAD(&ports_temp);
-        list_splice(&user_ptr->ports, &ports_temp);
+	list_splice(&user_ptr->ports, &ports_temp);
 	user_ptr->next = next_free_user;
 	next_free_user = userid;
 	spin_unlock_bh(&reg_lock);
 
 	atomic_dec(&tipc_user_count);
 
-        list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) {
+	list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) {
 		tipc_deleteport(up_ptr->ref);
 	}
 }
diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h
index d0e8879..81dc12e 100644
--- a/net/tipc/user_reg.h
+++ b/net/tipc/user_reg.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/user_reg.h: Include file for TIPC user registry code
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
diff --git a/net/tipc/zone.c b/net/tipc/zone.c
index f5b00ea..114e173 100644
--- a/net/tipc/zone.c
+++ b/net/tipc/zone.c
@@ -1,6 +1,6 @@
 /*
  * net/tipc/zone.c: TIPC zone management routines
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005, Wind River Systems
  * All rights reserved.
@@ -92,7 +92,7 @@
 
 	for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
 		if (z_ptr->clusters[c_num]) {
-			tipc_cltr_remove_as_router(z_ptr->clusters[c_num], 
+			tipc_cltr_remove_as_router(z_ptr->clusters[c_num],
 						   router);
 		}
 	}
diff --git a/net/tipc/zone.h b/net/tipc/zone.h
index 5ab3d08..6e7a08d 100644
--- a/net/tipc/zone.h
+++ b/net/tipc/zone.h
@@ -1,6 +1,6 @@
 /*
  * net/tipc/zone.h: Include file for TIPC zone management routines
- * 
+ *
  * Copyright (c) 2000-2006, Ericsson AB
  * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
@@ -47,7 +47,7 @@
  * @clusters: array of pointers to all clusters within zone
  * @links: number of (unicast) links to zone
  */
- 
+
 struct _zone {
 	u32 addr;
 	struct cluster *clusters[2]; /* currently limited to just 1 cluster */
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 2f208c7..6069716 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -195,7 +195,7 @@
  *	        - if started by not zero, should be NULL terminated (FS object)
  *		- if started by zero, it is abstract name.
  */
- 
+
 static int unix_mkname(struct sockaddr_un * sunaddr, int len, unsigned *hashp)
 {
 	if (len <= sizeof(short) || len > sizeof(*sunaddr))
@@ -432,7 +432,7 @@
 	 */
 
 	if (atomic_read(&unix_tot_inflight))
-		unix_gc();		/* Garbage collect fds */	
+		unix_gc();		/* Garbage collect fds */
 
 	return 0;
 }
@@ -698,7 +698,7 @@
 	struct sock *u;
 	struct nameidata nd;
 	int err = 0;
-	
+
 	if (sunname->sun_path[0]) {
 		err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd);
 		if (err)
@@ -915,7 +915,7 @@
 		unix_peer(sk)=other;
 		unix_state_wunlock(sk);
 	}
- 	return 0;
+	return 0;
 
 out_unlock:
 	unix_state_wunlock(sk);
@@ -1021,7 +1021,7 @@
 			goto out;
 		sock_put(other);
 		goto restart;
-        }
+	}
 
 	/* Latch our state.
 
@@ -1415,7 +1415,7 @@
 	return err;
 }
 
-		
+
 static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 			       struct msghdr *msg, size_t len)
 {
@@ -1467,11 +1467,11 @@
 
 		if (size > SKB_MAX_ALLOC)
 			size = SKB_MAX_ALLOC;
-			
+
 		/*
 		 *	Grab a buffer
 		 */
-		 
+
 		skb=sock_alloc_send_skb(sk,size,msg->msg_flags&MSG_DONTWAIT, &err);
 
 		if (skb==NULL)
@@ -1530,7 +1530,7 @@
 {
 	int err;
 	struct sock *sk = sock->sk;
-	
+
 	err = sock_error(sk);
 	if (err)
 		return err;
@@ -1543,7 +1543,7 @@
 
 	return unix_dgram_sendmsg(kiocb, sock, msg, len);
 }
-                                                                                            
+
 static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
 {
 	struct unix_sock *u = unix_sk(sk);
@@ -1605,7 +1605,7 @@
 		if (UNIXCB(skb).fp)
 			unix_detach_fds(siocb->scm, skb);
 	}
-	else 
+	else
 	{
 		/* It is questionable: on PEEK we could:
 		   - do not return fds - good, but too simple 8)
@@ -1613,11 +1613,11 @@
 		     apparently wrong)
 		   - clone fds (I chose it for now, it is the most universal
 		     solution)
-		
-	           POSIX 1003.1g does not actually define this clearly
-	           at all. POSIX 1003.1g doesn't define a lot of things
-	           clearly however!		     
-		   
+
+		   POSIX 1003.1g does not actually define this clearly
+		   at all. POSIX 1003.1g doesn't define a lot of things
+		   clearly however!
+
 		*/
 		if (UNIXCB(skb).fp)
 			siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
@@ -1637,7 +1637,7 @@
 /*
  *	Sleep until data has arrive. But check for races..
  */
- 
+
 static long unix_stream_data_wait(struct sock * sk, long timeo)
 {
 	DEFINE_WAIT(wait);
@@ -1721,7 +1721,7 @@
 			/*
 			 *	POSIX 1003.1g mandates this order.
 			 */
-			 
+
 			if ((err = sock_error(sk)) != 0)
 				break;
 			if (sk->sk_shutdown & RCV_SHUTDOWN)
@@ -1937,7 +1937,7 @@
 	struct sock *s;
 
 	for (s = first_unix_socket(iter); s; s = next_unix_socket(iter, s)) {
-		if (off == pos) 
+		if (off == pos)
 			return s;
 		++off;
 	}
@@ -1955,7 +1955,7 @@
 {
 	++*pos;
 
-	if (v == (void *)1) 
+	if (v == (void *)1)
 		return first_unix_socket(seq->private);
 	return next_unix_socket(seq->private, v);
 }
@@ -1967,7 +1967,7 @@
 
 static int unix_seq_show(struct seq_file *seq, void *v)
 {
-	
+
 	if (v == (void *)1)
 		seq_puts(seq, "Num       RefCount Protocol Flags    Type St "
 			 "Inode Path\n");
@@ -2040,7 +2040,7 @@
 	goto out;
 }
 
-static struct file_operations unix_seq_fops = {
+static const struct file_operations unix_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= unix_seq_open,
 	.read		= seq_read,
@@ -2064,8 +2064,8 @@
 	BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb));
 
 	rc = proto_register(&unix_proto, 1);
-        if (rc != 0) {
-                printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
+	if (rc != 0) {
+		printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
 		       __FUNCTION__);
 		goto out;
 	}
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index f14ad66..f20b7ea 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -63,9 +63,8 @@
  *		Damn. Added missing check for ->dead in listen queues scanning.
  *
  */
- 
+
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/socket.h>
 #include <linux/un.h>
@@ -118,7 +117,7 @@
  *	Keep the number of times in flight count for the file
  *	descriptor if it is for an AF_UNIX socket.
  */
- 
+
 void unix_inflight(struct file *fp)
 {
 	struct sock *s = unix_get_socket(fp);
@@ -190,7 +189,7 @@
 		unix_sk(s)->gc_tree = GC_ORPHAN;
 	}
 	/*
-	 *	Everything is now marked 
+	 *	Everything is now marked
 	 */
 
 	/* Invariant to be maintained:
@@ -227,7 +226,7 @@
 	}
 
 	/*
-	 *	Mark phase 
+	 *	Mark phase
 	 */
 
 	while (!empty_stack())
@@ -237,11 +236,11 @@
 
 		spin_lock(&x->sk_receive_queue.lock);
 		skb = skb_peek(&x->sk_receive_queue);
-		
+
 		/*
-		 *	Loop through all but first born 
+		 *	Loop through all but first born
 		 */
-		
+
 		while (skb && skb != (struct sk_buff *)&x->sk_receive_queue) {
 			/*
 			 *	Do we have file descriptors ?
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index 690ffa5..eb0bd57 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -50,7 +50,7 @@
 
 void unix_sysctl_register(void)
 {
-	unix_sysctl_header = register_sysctl_table(unix_root_table, 0);
+	unix_sysctl_header = register_sysctl_table(unix_root_table);
 }
 
 void unix_sysctl_unregister(void)
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index c205973..41d7e32 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -11,11 +11,11 @@
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
 * Due Credit:
-*               Wanpipe socket layer is based on Packet and 
-*               the X25 socket layers. The above sockets were 
-*               used for the specific use of Sangoma Technologies 
-*               API programs. 
-*               Packet socket Authors: Ross Biro, Fred N. van Kempen and 
+*               Wanpipe socket layer is based on Packet and
+*               the X25 socket layers. The above sockets were
+*               used for the specific use of Sangoma Technologies
+*               API programs.
+*               Packet socket Authors: Ross Biro, Fred N. van Kempen and
 *                                      Alan Cox.
 *               X25 socket Author: Jonathan Naylor.
 * ============================================================================
@@ -28,7 +28,7 @@
 * Feb 29, 2000  Nenad Corbic     o Added support for PVC protocols, such as
 *                                  CHDLC, Frame Relay and HDLC API.
 * Jan 17, 2000 	Nenad Corbic	 o Initial version, based on AF_PACKET socket.
-*			           X25API support only. 
+*			           X25API support only.
 *
 ******************************************************************************/
 
@@ -71,33 +71,33 @@
 	#define DBG_PRINTK(format, a...) printk(format, ## a)
 #else
 	#define DBG_PRINTK(format, a...)
-#endif      
+#endif
 
 
-/* SECURE SOCKET IMPLEMENTATION 
- * 
+/* SECURE SOCKET IMPLEMENTATION
+ *
  *   TRANSMIT:
  *
  *      When the user sends a packet via send() system call
- *      the wanpipe_sendmsg() function is executed.  
- *      
+ *      the wanpipe_sendmsg() function is executed.
+ *
  *      Each packet is enqueud into sk->sk_write_queue transmit
  *      queue. When the packet is enqueued, a delayed transmit
- *      timer is triggerd which acts as a Bottom Half hander. 
+ *      timer is triggerd which acts as a Bottom Half hander.
  *
  *      wanpipe_delay_transmit() function (BH), dequeues packets
- *      from the sk->sk_write_queue transmit queue and sends it 
- *      to the deriver via dev->hard_start_xmit(skb, dev) function.  
+ *      from the sk->sk_write_queue transmit queue and sends it
+ *      to the deriver via dev->hard_start_xmit(skb, dev) function.
  *      Note, this function is actual a function pointer of if_send()
  *      routine in the wanpipe driver.
  *
  *      X25API GUARANTEED DELIVERY:
  *
- *         In order to provide 100% guaranteed packet delivery, 
- *         an atomic 'packet_sent' counter is implemented.  Counter 
- *         is incremented for each packet enqueued 
+ *         In order to provide 100% guaranteed packet delivery,
+ *         an atomic 'packet_sent' counter is implemented.  Counter
+ *         is incremented for each packet enqueued
  *         into sk->sk_write_queue.  Counter is decremented each
- *         time wanpipe_delayed_transmit() function successfuly 
+ *         time wanpipe_delayed_transmit() function successfuly
  *         passes the packet to the driver. Before each send(), a poll
  *         routine checks the sock resources The maximum value of
  *         packet sent counter is 1, thus if one packet is queued, the
@@ -110,11 +110,11 @@
  *      function, wanpipe_rcv() to queue the incoming packets
  *      into an AF_WANPIPE socket queue.  Based on wanpipe_rcv()
  *      return code, the driver knows whether the packet was
- *      successfully queued.  If the socket queue is full, 
- *      protocol flow control is used by the driver, if any, 
+ *      successfully queued.  If the socket queue is full,
+ *      protocol flow control is used by the driver, if any,
  *      to slow down the traffic until the sock queue is free.
  *
- *      Every time a packet arrives into a socket queue the 
+ *      Every time a packet arrives into a socket queue the
  *      socket wakes up processes which are waiting to receive
  *      data.
  *
@@ -122,12 +122,12 @@
  *      bit which signals the socket to kick the wanpipe driver
  *      bottom half hander when the socket queue is partialy
  *      empty. wanpipe_recvmsg() function performs this action.
- * 
+ *
  *      In case of x25api, packets will never be dropped, since
- *      flow control is available. 
- *      
- *      In case of streaming protocols like CHDLC, packets will 
- *      be dropped but the statistics will be generated. 
+ *      flow control is available.
+ *
+ *      In case of streaming protocols like CHDLC, packets will
+ *      be dropped but the statistics will be generated.
  */
 
 
@@ -170,11 +170,11 @@
 	struct net_device *dev;	/* Bounded device */
 	unsigned short lcn;	/* Binded LCN */
 	unsigned char  svc;	/* 0=pvc, 1=svc */
-	unsigned char  timer;   /* flag for delayed transmit*/	
+	unsigned char  timer;   /* flag for delayed transmit*/
 	struct timer_list tx_timer;
 	unsigned poll_cnt;
 	unsigned char force;	/* Used to force sock release */
-	atomic_t packet_sent;   
+	atomic_t packet_sent;
 };
 #endif
 
@@ -215,8 +215,8 @@
  *
  *	Wanpipe socket bottom half handler.  This function
  *      is called by the WANPIPE device drivers to queue a
- *      incoming packet into the socket receive queue. 
- *      Once the packet is queued, all processes waiting to 
+ *      incoming packet into the socket receive queue.
+ *      Once the packet is queued, all processes waiting to
  *      read are woken up.
  *
  *      During socket bind, this function is bounded into
@@ -245,13 +245,13 @@
 	if (dev->hard_header_parse)
 		sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
 
-	/* 
+	/*
 	 * WAN_PACKET_DATA : Data which should be passed up the receive queue.
-         * WAN_PACKET_ASYC : Asynchronous data like place call, which should
-         *                   be passed up the listening sock.
-         * WAN_PACKET_ERR  : Asynchronous data like clear call or restart 
-         *                   which should go into an error queue.
-         */
+	 * WAN_PACKET_ASYC : Asynchronous data like place call, which should
+	 *                   be passed up the listening sock.
+	 * WAN_PACKET_ERR  : Asynchronous data like clear call or restart
+	 *                   which should go into an error queue.
+	 */
 	switch (skb->pkt_type){
 
 		case WAN_PACKET_DATA:
@@ -261,10 +261,10 @@
 			break;
 		case WAN_PACKET_CMD:
 			sk->sk_state = chan->state;
-			/* Bug fix: update Mar6. 
-                         * Do not set the sock lcn number here, since
-         		 * cmd is not guaranteed to be executed on the
-                         * board, thus Lcn could be wrong */
+			/* Bug fix: update Mar6.
+			 * Do not set the sock lcn number here, since
+			 * cmd is not guaranteed to be executed on the
+			 * board, thus Lcn could be wrong */
 			sk->sk_data_ready(sk, skb->len);
 			kfree_skb(skb);
 			break;
@@ -276,7 +276,7 @@
 			break;
 		default:
 			printk(KERN_INFO "wansock: BH Illegal Packet Type Dropping\n");
-			kfree_skb(skb); 
+			kfree_skb(skb);
 			break;
 	}
 
@@ -297,20 +297,20 @@
  *
  *	Wanpipe LISTEN socket bottom half handler.  This function
  *      is called by the WANPIPE device drivers to queue an
- *      incoming call into the socket listening queue. 
- *      Once the packet is queued, the waiting accept() process 
+ *      incoming call into the socket listening queue.
+ *      Once the packet is queued, the waiting accept() process
  *      is woken up.
  *
  *      During socket bind, this function is bounded into
- *      WANPIPE driver private. 
- * 
+ *      WANPIPE driver private.
+ *
  *      IMPORTANT NOTE:
  *          The accept call() is waiting for an skb packet
  *          which contains a pointer to a device structure.
  *
- *          When we do a bind to a device structre, we 
- *          bind a newly created socket into "chan->sk".  Thus, 
- *          when accept receives the skb packet, it will know 
+ *          When we do a bind to a device structre, we
+ *          bind a newly created socket into "chan->sk".  Thus,
+ *          when accept receives the skb packet, it will know
  *          from which dev it came form, and in turn it will know
  *          the address of the new sock.
  *
@@ -322,31 +322,31 @@
 	wanpipe_opt *wp = wp_sk(sk), *newwp;
 	struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)skb->cb;
 	struct sock *newsk;
-	struct net_device *dev; 
+	struct net_device *dev;
 	sdla_t *card;
 	mbox_cmd_t *mbox_ptr;
 	wanpipe_common_t *chan;
 
-	/* Find a free device, if none found, all svc's are busy 
-         */
+	/* Find a free device, if none found, all svc's are busy
+	 */
 
 	card = (sdla_t*)wp->card;
 	if (!card){
 		printk(KERN_INFO "wansock: LISTEN ERROR, No Card\n");
 		return -ENODEV;
 	}
-	
+
 	dev = wanpipe_find_free_dev(card);
 	if (!dev){
 		printk(KERN_INFO "wansock: LISTEN ERROR, No Free Device\n");
 		return -ENODEV;
 	}
 
-	chan=dev->priv;	
+	chan=dev->priv;
 	chan->state = WANSOCK_CONNECTING;
 
 	/* Allocate a new sock, which accept will bind
-         * and pass up to the user 
+	 * and pass up to the user
 	 */
 	if ((newsk = wanpipe_make_new(sk)) == NULL){
 		release_device(dev);
@@ -354,33 +354,33 @@
 	}
 
 
-	/* Initialize the new sock structure 
+	/* Initialize the new sock structure
 	 */
 	newsk->sk_bound_dev_if = dev->ifindex;
 	newwp = wp_sk(newsk);
 	newwp->card = wp->card;
 
 	/* Insert the sock into the main wanpipe
-         * sock list.
-         */
+	 * sock list.
+	 */
 	atomic_inc(&wanpipe_socks_nr);
 
 	/* Allocate and fill in the new Mail Box. Then
-         * bind the mail box to the sock. It will be 
-         * used by the ioctl call to read call information
-         * and to execute commands. 
-         */	
+	 * bind the mail box to the sock. It will be
+	 * used by the ioctl call to read call information
+	 * and to execute commands.
+	 */
 	if ((mbox_ptr = kzalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL) {
 		wanpipe_kill_sock_irq (newsk);
-		release_device(dev);		
+		release_device(dev);
 		return -ENOMEM;
 	}
 	memcpy(mbox_ptr,skb->data,skb->len);
 
 	/* Register the lcn on which incoming call came
-         * from. Thus, if we have to clear it, we know
-         * which lcn to clear
-	 */ 
+	 * from. Thus, if we have to clear it, we know
+	 * which lcn to clear
+	 */
 
 	newwp->lcn = mbox_ptr->cmd.lcn;
 	newwp->mbox = (void *)mbox_ptr;
@@ -416,20 +416,20 @@
 
 	/* We must do this manually, since the sock_queue_rcv_skb()
 	 * function sets the skb->dev to NULL.  However, we use
-	 * the dev field in the accept function.*/ 
-	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= 
+	 * the dev field in the accept function.*/
+	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
 	    (unsigned)sk->sk_rcvbuf) {
 
-         	wanpipe_unlink_driver(newsk);
+		wanpipe_unlink_driver(newsk);
 		wanpipe_kill_sock_irq (newsk);
 		--sk->sk_ack_backlog;
 		return -ENOMEM;
-	}	
+	}
 
 	skb_set_owner_r(skb, sk);
 	skb_queue_tail(&sk->sk_receive_queue, skb);
 	sk->sk_data_ready(sk, skb->len);
-	
+
 	return 0;
 }
 
@@ -474,7 +474,7 @@
 	return sk;
 }
 
-/* 
+/*
  * FIXME: wanpipe_opt has to include a sock in its definition and stop using
  * sk_protinfo, but this code is not even compilable now, so lets leave it for
  * later.
@@ -489,12 +489,12 @@
  * wanpipe_make_new
  *
  *	Allocate memory for the a new sock, and sock
- *      private data.  
- *	
+ *      private data.
+ *
  *	Increment the module use count.
- *       	
- *      This function is used by wanpipe_create() and 
- *      wanpipe_make_new() functions. 
+ *
+ *      This function is used by wanpipe_create() and
+ *      wanpipe_make_new() functions.
  *
  *===========================================================*/
 
@@ -514,7 +514,7 @@
 	wp_sk(sk) = wan_opt;
 
 	/* Use timer to send data to the driver. This will act
-         * as a BH handler for sendmsg functions */
+	 * as a BH handler for sendmsg functions */
 	init_timer(&wan_opt->tx_timer);
 	wan_opt->tx_timer.data	   = (unsigned long)sk;
 	wan_opt->tx_timer.function = wanpipe_delayed_transmit;
@@ -528,14 +528,14 @@
  * wanpipe_sendmsg
  *
  *	This function implements a sendto() system call,
- *      for AF_WANPIPE socket family. 
+ *      for AF_WANPIPE socket family.
  *      During socket bind() sk->sk_bound_dev_if is initialized
  *      to a correct network device. This number is used
  *      to find a network device to which the packet should
  *      be passed to.
  *
- *      Each packet is queued into sk->sk_write_queue and 
- *      delayed transmit bottom half handler is marked for 
+ *      Each packet is queued into sk->sk_write_queue and
+ *      delayed transmit bottom half handler is marked for
  *      execution.
  *
  *      A socket must be in WANSOCK_CONNECTED state before
@@ -554,18 +554,18 @@
 	unsigned char *addr;
 	int ifindex, err, reserve = 0;
 
-	
+
 	if (!sock_flag(sk, SOCK_ZAPPED))
 		return -ENETDOWN;
 
 	if (sk->sk_state != WANSOCK_CONNECTED)
-		return -ENOTCONN;	
+		return -ENOTCONN;
 
-	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) 
+	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
 		return(-EINVAL);
 
 	/* it was <=, now one can send
-         * zero length packets */
+	 * zero length packets */
 	if (len < sizeof(x25api_hdr_t))
 		return -EINVAL;
 
@@ -577,7 +577,7 @@
 		addr	= NULL;
 
 	}else{
-		if (msg->msg_namelen < sizeof(struct wan_sockaddr_ll)){ 
+		if (msg->msg_namelen < sizeof(struct wan_sockaddr_ll)){
 			return -EINVAL;
 		}
 
@@ -592,12 +592,12 @@
 		return -ENXIO;
 	}
 	dev_put(dev);
-	
+
 	if (sock->type == SOCK_RAW)
 		reserve = dev->hard_header_len;
 
 	if (len > dev->mtu+reserve){
-  		return -EMSGSIZE;
+		return -EMSGSIZE;
 	}
 
 	skb = sock_alloc_send_skb(sk, len + LL_RESERVED_SPACE(dev),
@@ -606,7 +606,7 @@
 	if (skb==NULL){
 		goto out_unlock;
 	}
-		
+
 	skb_reserve(skb, LL_RESERVED_SPACE(dev));
 	skb->nh.raw = skb->data;
 
@@ -645,7 +645,7 @@
 
 	if (!(test_and_set_bit(0, &wp->timer)))
 		mod_timer(&wp->tx_timer, jiffies + 1);
-	
+
 	return(len);
 
 out_free:
@@ -658,12 +658,12 @@
  * wanpipe_delayed_tarnsmit
  *
  *	Transmit bottom half handler. It dequeues packets
- *      from sk->sk_write_queue and passes them to the 
- *      driver.  If the driver is busy, the packet is 
- *      re-enqueued.  
+ *      from sk->sk_write_queue and passes them to the
+ *      driver.  If the driver is busy, the packet is
+ *      re-enqueued.
  *
  *      Packet Sent counter is decremented on successful
- *      transmission. 
+ *      transmission.
  *===========================================================*/
 
 
@@ -680,17 +680,17 @@
 		DBG_PRINTK(KERN_INFO "wansock: Transmit delay, no dev or card\n");
 		return;
 	}
-	
+
 	if (sk->sk_state != WANSOCK_CONNECTED || !sock_flag(sk, SOCK_ZAPPED)) {
 		clear_bit(0, &wp->timer);
 		DBG_PRINTK(KERN_INFO "wansock: Tx Timer, State not CONNECTED\n");
 		return;
 	}
-	
+
 	/* If driver is executing command, we must offload
-         * the board by not sending data. Otherwise a 
-         * pending command will never get a free buffer
-         * to execute */ 	
+	 * the board by not sending data. Otherwise a
+	 * pending command will never get a free buffer
+	 * to execute */
 	if (atomic_read(&card->u.x.command_busy)){
 		wp->tx_timer.expires = jiffies + SLOW_BACKOFF;
 		add_timer(&wp->tx_timer);
@@ -698,30 +698,30 @@
 		return;
 	}
 
-	
+
 	if (test_and_set_bit(0,&wanpipe_tx_critical)){
 		printk(KERN_INFO "WanSock: Tx timer critical %s\n",dev->name);
 		wp->tx_timer.expires = jiffies + SLOW_BACKOFF;
 		add_timer(&wp->tx_timer);
 		return;
-	}	
-	
+	}
+
 	/* Check for a packet in the fifo and send */
 	if ((skb = skb_dequeue(&sk->sk_write_queue)) != NULL){
 
-		if (dev->hard_start_xmit(skb, dev) != 0){			
+		if (dev->hard_start_xmit(skb, dev) != 0){
 
 			/* Driver failed to transmit, re-enqueue
-                         * the packet and retry again later */
+			 * the packet and retry again later */
 			skb_queue_head(&sk->sk_write_queue,skb);
 			clear_bit(0,&wanpipe_tx_critical);
 			return;
 		}else{
 
 			/* Packet Sent successful. Check for more packets
-                         * if more packets, re-trigger the transmit routine 
-                         * other wise exit
-                         */
+			 * if more packets, re-trigger the transmit routine
+			 * other wise exit
+			 */
 			atomic_dec(&wp->packet_sent);
 
 			if (skb_peek(&sk->sk_write_queue) == NULL) {
@@ -741,18 +741,18 @@
 }
 
 /*============================================================
- * execute_command 
+ * execute_command
  *
  *	Execute x25api commands.  The atomic variable
  *      chan->command is used to indicate to the driver that
  *      command is pending for execution.  The acutal command
- *      structure is placed into a sock mbox structure 
+ *      structure is placed into a sock mbox structure
  *      (wp_sk(sk)->mbox).
  *
  *      The sock private structure, mbox is
  *      used as shared memory between sock and the driver.
  *      Driver uses the sock mbox to execute the command
- *      and return the result.  
+ *      and return the result.
  *
  *      For all command except PLACE CALL, the function
  *      waits for the result.  PLACE CALL can be ether
@@ -768,7 +768,7 @@
 	wanpipe_common_t *chan=NULL;
 	int err=0;
 	DECLARE_WAITQUEUE(wait, current);
-	
+
 	dev = dev_get_by_index(sk->sk_bound_dev_if);
 	if (dev == NULL){
 		printk(KERN_INFO "wansock: Exec failed no dev %i\n",
@@ -793,7 +793,7 @@
 		return -EINVAL;
 	}
 
-	((mbox_cmd_t*)wp->mbox)->cmd.command = cmd;	
+	((mbox_cmd_t*)wp->mbox)->cmd.command = cmd;
 	((mbox_cmd_t*)wp->mbox)->cmd.lcn     = wp->lcn;
 	((mbox_cmd_t*)wp->mbox)->cmd.result  = 0x7F;
 
@@ -820,12 +820,12 @@
 	}
 	current->state = TASK_RUNNING;
 	remove_wait_queue(sk->sk_sleep,&wait);
-	
+
 	return err;
 }
 
 /*============================================================
- * wanpipe_destroy_timer 
+ * wanpipe_destroy_timer
  *
  *	Used by wanpipe_release, to delay release of
  *      the socket.
@@ -846,7 +846,7 @@
 
 		kfree(wp);
 		wp_sk(sk) = NULL;
-		
+
 		if (atomic_read(&sk->sk_refcnt) != 1) {
 			atomic_set(&sk->sk_refcnt, 1);
 			DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :delay.\n",
@@ -865,9 +865,9 @@
 /*============================================================
  * wanpipe_unlink_driver
  *
- * 	When the socket is released, this function is 
+ * 	When the socket is released, this function is
  *      used to remove links that bind the sock and the
- *      driver together.  
+ *      driver together.
  *===========================================================*/
 static void wanpipe_unlink_driver (struct sock *sk)
 {
@@ -882,7 +882,7 @@
 	if (!dev){
 		printk(KERN_INFO "wansock: No dev on release\n");
 		return;
-	}			
+	}
 	dev_put(dev);
 
 	if ((chan = dev->priv) == NULL){
@@ -897,7 +897,7 @@
 	chan->tx_timer=NULL;
 	clear_bit(0,&chan->common_critical);
 	release_device(dev);
-	
+
 	return;
 }
 
@@ -931,7 +931,7 @@
 /*============================================================
  * release_device
  *
- *   	During sock release, clear a critical bit, which 
+ *   	During sock release, clear a critical bit, which
  *      marks the device a being taken.
  *===========================================================*/
 
@@ -945,8 +945,8 @@
 /*============================================================
  * wanpipe_release
  *
- *	Close a PACKET socket. This is fairly simple. We 
- *      immediately go to 'closed' state and remove our 
+ *	Close a PACKET socket. This is fairly simple. We
+ *      immediately go to 'closed' state and remove our
  *      protocol entry in the device list.
  *===========================================================*/
 
@@ -954,7 +954,7 @@
 {
 	wanpipe_opt *wp;
 	struct sock *sk = sock->sk;
-	
+
 	if (!sk)
 		return 0;
 
@@ -962,9 +962,9 @@
 	check_write_queue(sk);
 
 	/* Kill the tx timer, if we don't kill it now, the timer
-         * will run after we kill the sock.  Timer code will 
-         * try to access the sock which has been killed and cause
-         * kernel panic */
+	 * will run after we kill the sock.  Timer code will
+	 * try to access the sock which has been killed and cause
+	 * kernel panic */
 
 	del_timer(&wp->tx_timer);
 
@@ -982,7 +982,7 @@
 			DBG_PRINTK(KERN_INFO "wansock: Sending Clear Indication %i\n",
 					sk->sk_state);
 			dev_put(dev);
-		}	
+		}
 	}
 
 	set_bit(1,&wanpipe_tx_critical);
@@ -992,10 +992,10 @@
 	clear_bit(1,&wanpipe_tx_critical);
 
 
-	
+
 	release_driver(sk);
 
-	
+
 	/*
 	 *	Now the socket is dead. No more input will appear.
 	 */
@@ -1040,9 +1040,9 @@
 /*============================================================
  * check_write_queue
  *
- *  	During sock shutdown, if the sock state is 
- *      WANSOCK_CONNECTED and there is transmit data 
- *      pending. Wait until data is released 
+ *  	During sock shutdown, if the sock state is
+ *      WANSOCK_CONNECTED and there is transmit data
+ *      pending. Wait until data is released
  *      before proceeding.
  *===========================================================*/
 
@@ -1062,7 +1062,7 @@
 /*============================================================
  * release_driver
  *
- *	This function is called during sock shutdown, to 
+ *	This function is called during sock shutdown, to
  *      release any resources and links that bind the sock
  *      to the driver.  It also changes the state of the
  *      sock to WANSOCK_DISCONNECTED
@@ -1105,7 +1105,7 @@
  *  start_cleanup_timer
  *
  *  	If new incoming call's are pending but the socket
- *      is being released, start the timer which will 
+ *      is being released, start the timer which will
  *      envoke the kill routines for pending socks.
  *===========================================================*/
 
@@ -1125,7 +1125,7 @@
  *
  *	This is a function which performs actual killing
  *      of the sock.  It releases socket resources,
- *      and unlinks the sock from the driver. 
+ *      and unlinks the sock from the driver.
  *===========================================================*/
 
 static void wanpipe_kill_sock_timer (unsigned long data)
@@ -1139,13 +1139,13 @@
 
 	/* This function can be called from interrupt. We must use
 	 * appropriate locks */
-	
+
 	if (test_bit(1,&wanpipe_tx_critical)){
 		sk->sk_timer.expires = jiffies + 10;
 		add_timer(&sk->sk_timer);
 		return;
 	}
-	
+
 	write_lock(&wanpipe_sklist_lock);
 	sk_del_node_init(sk);
 	write_unlock(&wanpipe_sklist_lock);
@@ -1159,7 +1159,7 @@
 			chan=dev->priv;
 			atomic_set(&chan->disconnect,1);
 			dev_put(dev);
-		}	
+		}
 	}
 
 	release_driver(sk);
@@ -1170,7 +1170,7 @@
 	skb_queue_purge(&sk->sk_receive_queue);
 	skb_queue_purge(&sk->sk_write_queue);
 	skb_queue_purge(&sk->sk_error_queue);
-	
+
 	if (atomic_read(&sk->sk_rmem_alloc) ||
 	    atomic_read(&sk->sk_wmem_alloc)) {
 		del_timer(&sk->sk_timer);
@@ -1205,7 +1205,7 @@
 
 	/* This function can be called from interrupt. We must use
 	 * appropriate locks */
-	
+
 	write_lock(&wanpipe_sklist_lock);
 	sk_del_node_init(sk);
 	write_unlock(&wanpipe_sklist_lock);
@@ -1282,10 +1282,10 @@
 			chan=dev->priv;
 			sk->sk_state = chan->state;
 
-			if (wp->num == htons(X25_PROT) && 
-			    sk->sk_state != WANSOCK_DISCONNECTED && 
+			if (wp->num == htons(X25_PROT) &&
+			    sk->sk_state != WANSOCK_DISCONNECTED &&
 			    sk->sk_state != WANSOCK_CONNECTING) {
-				DBG_PRINTK(KERN_INFO 
+				DBG_PRINTK(KERN_INFO
 					"wansock: Binding to Device not DISCONNECTED %i\n",
 						sk->sk_state);
 				release_device(dev);
@@ -1338,7 +1338,7 @@
 	/*
 	 *	Check legality
 	 */
-	 
+
 	if (addr_len < sizeof(struct wan_sockaddr_ll)){
 		printk(KERN_INFO "wansock: Address length error\n");
 		return -EINVAL;
@@ -1358,12 +1358,12 @@
 
 	if (!strcmp(sll->sll_device,"svc_listen")){
 
-		/* Bind a sock to a card structure for listening 
-		 */		
-		int err=0; 
+		/* Bind a sock to a card structure for listening
+		 */
+		int err=0;
 
 		/* This is x25 specific area if protocol doesn't
-                 * match, return error */
+		 * match, return error */
 		if (sll->sll_protocol != htons(X25_PROT))
 			return -EINVAL;
 
@@ -1376,14 +1376,14 @@
 		sk->sk_state = WANSOCK_BIND_LISTEN;
 		return 0;
 
-	}else if (!strcmp(sll->sll_device,"svc_connect")){ 
+	}else if (!strcmp(sll->sll_device,"svc_connect")){
 
 		/* This is x25 specific area if protocol doesn't
-                 * match, return error */
+		 * match, return error */
 		if (sll->sll_protocol != htons(X25_PROT))
 			return -EINVAL;
 
-		/* Find a free device 
+		/* Find a free device
 		 */
 		dev = wanpipe_find_free_dev(card);
 		if (dev == NULL){
@@ -1392,9 +1392,9 @@
 			return -EINVAL;
 		}
 	}else{
-		/* Bind a socket to a interface name 
-                 * This is used by PVC mostly
-                 */
+		/* Bind a socket to a interface name
+		 * This is used by PVC mostly
+		 */
 		strlcpy(name,sll->sll_device,sizeof(name));
 		dev = dev_get_by_name(name);
 		if (dev == NULL){
@@ -1419,8 +1419,8 @@
 
 /*============================================================
  * get_atomic_device
- *	
- *	Sets a bit atomically which indicates that 
+ *
+ *	Sets a bit atomically which indicates that
  *      the interface is taken. This avoids race conditions.
  *===========================================================*/
 
@@ -1436,7 +1436,7 @@
 
 /*============================================================
  * check_dev
- *	
+ *
  *  	Check that device name belongs to a particular card.
  *===========================================================*/
 
@@ -1446,8 +1446,8 @@
 
 	for (tmp_dev = card->wandev.dev; tmp_dev;
 	     tmp_dev = *((struct net_device **)tmp_dev->priv)) {
-		if (tmp_dev->ifindex == dev->ifindex){ 
-			return 0;	
+		if (tmp_dev->ifindex == dev->ifindex){
+			return 0;
 		}
 	}
 	return 1;
@@ -1455,7 +1455,7 @@
 
 /*============================================================
  *  wanpipe_find_free_dev
- *	
+ *
  *	Find a free network interface. If found set atomic
  *      bit indicating that the interface is taken.
  *      X25API Specific.
@@ -1468,12 +1468,12 @@
 
 	if (test_and_set_bit(0,&find_free_critical)){
 		printk(KERN_INFO "CRITICAL in Find Free\n");
-	}	
+	}
 
 	for (dev = card->wandev.dev; dev;
 	     dev = *((struct net_device **)dev->priv)) {
 		chan = dev->priv;
-		if (!chan) 
+		if (!chan)
 			continue;
 		if (chan->usedby == API && chan->svc){
 			if (!get_atomic_device (dev)){
@@ -1492,16 +1492,16 @@
 
 /*============================================================
  *  wanpipe_create
- *	
+ *
  * 	SOCKET() System call.  It allocates a sock structure
- *      and adds the socket to the wanpipe_sk_list. 
+ *      and adds the socket to the wanpipe_sk_list.
  *      Crates AF_WANPIPE socket.
  *===========================================================*/
 
 static int wanpipe_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
-	
+
 	//FIXME: This checks for root user, SECURITY ?
 	//if (!capable(CAP_NET_RAW))
 	//	return -EPERM;
@@ -1526,7 +1526,7 @@
 	sk->sk_bound_dev_if = 0;
 
 	atomic_inc(&wanpipe_socks_nr);
-	
+
 	/* We must disable interrupts because the ISR
 	 * can also change the list */
 	set_bit(1,&wanpipe_tx_critical);
@@ -1541,8 +1541,8 @@
 
 /*============================================================
  *  wanpipe_recvmsg
- *	
- *	Pull a packet from our receive queue and hand it 
+ *
+ *	Pull a packet from our receive queue and hand it
  *      to the user. If necessary we block.
  *===========================================================*/
 
@@ -1570,13 +1570,13 @@
 	 *	but then it will block.
 	 */
 
-	if (flags & MSG_OOB){	
+	if (flags & MSG_OOB){
 		skb = skb_dequeue(&sk->sk_error_queue);
 	}else{
 		skb=skb_recv_datagram(sk,flags,1,&err);
 	}
 	/*
-	 *	An error occurred so return it. Because skb_recv_datagram() 
+	 *	An error occurred so return it. Because skb_recv_datagram()
 	 *	handles the blocking we don't see and worry about blocking
 	 *	retries.
 	 */
@@ -1602,9 +1602,9 @@
 	err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
 	if (err)
 		goto out_free;
-	
+
 	sock_recv_timestamp(msg, sk, skb);
-	
+
 	if (msg->msg_name)
 		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
 
@@ -1623,13 +1623,13 @@
 
 /*============================================================
  *  wanpipe_wakeup_driver
- *	
+ *
  * 	If socket receive buffer is full and driver cannot
  *      pass data up the sock, it sets a packet_block flag.
- *      This function check that flag and if sock receive 
- *      queue has room it kicks the driver BH handler. 
+ *      This function check that flag and if sock receive
+ *      queue has room it kicks the driver BH handler.
  *
- * 	This way, driver doesn't have to poll the sock 
+ * 	This way, driver doesn't have to poll the sock
  *      receive queue.
  *===========================================================*/
 
@@ -1646,8 +1646,8 @@
 
 	if ((chan = dev->priv) == NULL)
 		return;
-	
-	if (atomic_read(&chan->receive_block)){  
+
+	if (atomic_read(&chan->receive_block)){
 		if (atomic_read(&sk->sk_rmem_alloc) <
 		    ((unsigned)sk->sk_rcvbuf * 0.9)) {
 			printk(KERN_INFO "wansock: Queuing task for wanpipe\n");
@@ -1655,13 +1655,13 @@
 			wanpipe_queue_tq(&chan->wanpipe_task);
 			wanpipe_mark_bh();
 		}
-	}	
-}	
+	}
+}
 
 /*============================================================
  *  wanpipe_getname
- *	
- * 	I don't know what to do with this yet. 
+ *
+ * 	I don't know what to do with this yet.
  *      User can use this function to get sock address
  *      information. Not very useful for Sangoma's purposes.
  *===========================================================*/
@@ -1687,17 +1687,17 @@
 		sll->sll_halen = 0;
 	}
 	*uaddr_len = sizeof(*sll);
-	
+
 	dev_put(dev);
-	
+
 	return 0;
 }
 
 /*============================================================
  *  wanpipe_notifier
- *	
+ *
  *	If driver turns off network interface, this function
- *      will be envoked. Currently I treate it as a 
+ *      will be envoked. Currently I treate it as a
  *      call disconnect. More thought should go into this
  *      function.
  *
@@ -1718,7 +1718,7 @@
 			continue;
 		if (dev == NULL)
 			continue;
-		
+
 		switch (msg) {
 		case NETDEV_DOWN:
 		case NETDEV_UNREGISTER:
@@ -1732,7 +1732,7 @@
 
 				if (msg == NETDEV_UNREGISTER) {
 					printk(KERN_INFO "wansock: Unregistering Device: %s\n",
-						 	  dev->name);
+							  dev->name);
 					wanpipe_unlink_driver(sk);
 					sk->sk_bound_dev_if = 0;
 				}
@@ -1753,7 +1753,7 @@
 
 /*============================================================
  *  wanpipe_ioctl
- *	
+ *
  * 	Execute a user commands, and set socket options.
  *
  * FIXME: More thought should go into this function.
@@ -1765,7 +1765,7 @@
 	struct sock *sk = sock->sk;
 	int err;
 
-	switch(cmd) 
+	switch(cmd)
 	{
 		case SIOCGSTAMP:
 			return sock_get_timestamp(sk, (struct timeval __user *)arg);
@@ -1778,7 +1778,7 @@
 
 			if (sk->sk_state == WANSOCK_CONNECTED)
 				return 0;
-			
+
 			return 1;
 
 
@@ -1804,7 +1804,7 @@
 		case SIOC_WANPIPE_DEBUG:
 
 			return wanpipe_debug(sk,(void*)arg);
-	
+
 		case SIOC_WANPIPE_SET_NONBLOCK:
 
 			if (sk->sk_state != WANSOCK_DISCONNECTED)
@@ -1812,7 +1812,7 @@
 
 			sock->file->f_flags |= O_NONBLOCK;
 			return 0;
-	
+
 #ifdef CONFIG_INET
 		case SIOCADDRT:
 		case SIOCDELRT:
@@ -1842,7 +1842,7 @@
 
 /*============================================================
  *  wanpipe_debug
- *	
+ *
  *	This function will pass up information about all
  *      active sockets.
  *
@@ -1893,49 +1893,49 @@
 
 		if (sk->sk_bound_dev_if) {
 			dev = dev_get_by_index(sk->sk_bound_dev_if);
-			if (!dev)	
+			if (!dev)
 				continue;
 
 			chan=dev->priv;
 			dev_put(dev);
-	
+
 			if ((err=put_user(chan->state, &dbg_data->debug[cnt].d_state)))
 				return err;
 			if ((err=put_user(chan->svc, &dbg_data->debug[cnt].svc)))
 				return err;
 
-			if ((err=put_user(atomic_read(&chan->command), 
+			if ((err=put_user(atomic_read(&chan->command),
 						&dbg_data->debug[cnt].command)))
 				return err;
 
 
 			if (wp){
-				sdla_t *card = (sdla_t*)wp->card;			
-	
+				sdla_t *card = (sdla_t*)wp->card;
+
 				if (card){
-					if ((err=put_user(atomic_read(&card->u.x.command_busy), 
+					if ((err=put_user(atomic_read(&card->u.x.command_busy),
 								&dbg_data->debug[cnt].cmd_busy)))
 						return err;
 				}
 
-				if ((err=put_user(wp->lcn, 
+				if ((err=put_user(wp->lcn,
 						  &dbg_data->debug[cnt].lcn)))
 					return err;
-				
+
 				if (wp->mbox) {
 					if ((err=put_user(1, &dbg_data->debug[cnt].mbox)))
 						return err;
 				}
 			}
 
-			if ((err=put_user(atomic_read(&chan->receive_block), 
+			if ((err=put_user(atomic_read(&chan->receive_block),
 								&dbg_data->debug[cnt].rblock)))
 				return err;
 
 			if (copy_to_user(dbg_data->debug[cnt].name, dev->name, strlen(dev->name)))
 				return -EFAULT;
 		}
-	
+
 		if (++cnt == MAX_NUM_DEBUG)
 			break;
 	}
@@ -1944,7 +1944,7 @@
 
 /*============================================================
  *  get_ioctl_cmd
- *	
+ *
  *	Pass up the contents of socket MBOX to the user.
  *===========================================================*/
 
@@ -1974,7 +1974,7 @@
 	if ((err=put_user(mbox_ptr->cmd.result, &usr_data->hdr.result)))
 		return err;
 	if ((err=put_user(mbox_ptr->cmd.lcn, &usr_data->hdr.lcn)))
-		return err;	
+		return err;
 
 	if (mbox_ptr->cmd.length > 0){
 		if (mbox_ptr->cmd.length > X25_MAX_DATA)
@@ -1986,13 +1986,13 @@
 		}
 	}
 	return 0;
-} 
+}
 
 /*============================================================
  *  set_ioctl_cmd
- *	
+ *
  *	Before command can be execute, socket MBOX must
- *      be created, and initialized with user data.	
+ *      be created, and initialized with user data.
  *===========================================================*/
 
 static int set_ioctl_cmd (struct sock *sk, void *arg)
@@ -2008,7 +2008,7 @@
 			return -ENODEV;
 
 		dev_put(dev);
-		
+
 		if ((mbox_ptr = kzalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL)
 			return -ENOMEM;
 
@@ -2092,12 +2092,12 @@
 		return mask;
 	}
 
-	/* This check blocks the user process if there is   
+	/* This check blocks the user process if there is
 	 * a packet already queued in the socket write queue.
-         * This option is only for X25API protocol, for other
-         * protocol like chdlc enable streaming mode, 
-         * where multiple packets can be pending in the socket 
-         * transmit queue */
+	 * This option is only for X25API protocol, for other
+	 * protocol like chdlc enable streaming mode,
+	 * where multiple packets can be pending in the socket
+	 * transmit queue */
 
 	if (wp_sk(sk)->num == htons(X25_PROT)) {
 		if (atomic_read(&wp_sk(sk)->packet_sent))
@@ -2110,7 +2110,7 @@
 	}else{
 		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
 	}
-		
+
 	return mask;
 }
 
@@ -2125,8 +2125,8 @@
 {
 	struct sock *sk = sock->sk;
 
- 	/* This is x25 specific area if protocol doesn't
-         * match, return error */
+	/* This is x25 specific area if protocol doesn't
+	 * match, return error */
 	if (wp_sk(sk)->num != htons(X25_PROT))
 		return -EINVAL;
 
@@ -2163,7 +2163,7 @@
 	card->sk=sk;
 	card->func=wanpipe_listen_rcv;
 	sock_set_flag(sk, SOCK_ZAPPED);
- 
+
 	return 0;
 }
 
@@ -2176,7 +2176,7 @@
 
 static void wanpipe_unlink_card (struct sock *sk)
 {
-	sdla_t *card = (sdla_t*)wp_sk(sk)->card; 
+	sdla_t *card = (sdla_t*)wp_sk(sk)->card;
 
 	if (card){
 		card->sk=NULL;
@@ -2202,9 +2202,9 @@
 		printk(KERN_INFO "NO MBOX PTR !!!!!\n");
 		return -EINVAL;
 	}
-	
+
 	/* This is x25 specific area if protocol doesn't
-         * match, return error */
+	 * match, return error */
 	if (wp->num != htons(X25_PROT))
 		return -EINVAL;
 
@@ -2217,17 +2217,17 @@
 				err = -EHOSTDOWN;
 				break;
 			}
-			
+
 			err = execute_command(sk,X25_ACCEPT_CALL,0);
 			if (err < 0)
 				break;
 
-			/* Update. Mar6 2000. 
-                         * Do not set the sock lcn number here, since
-                         * it is done in wanpipe_listen_rcv(). 
-                         */ 
-		 	if (sk->sk_state == WANSOCK_CONNECTED) {
-				wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn;	
+			/* Update. Mar6 2000.
+			 * Do not set the sock lcn number here, since
+			 * it is done in wanpipe_listen_rcv().
+			 */
+			if (sk->sk_state == WANSOCK_CONNECTED) {
+				wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn;
 				DBG_PRINTK(KERN_INFO "\nwansock: Accept OK %i\n",
 					wp->lcn);
 				err = 0;
@@ -2249,15 +2249,15 @@
 
 
 			/* Check if data buffers are pending for transmission,
-                         * if so, check whether user wants to wait until data
-                         * is transmitted, or clear a call and drop packets */
-                          
+			 * if so, check whether user wants to wait until data
+			 * is transmitted, or clear a call and drop packets */
+
 			if (atomic_read(&sk->sk_wmem_alloc) ||
 			    check_driver_busy(sk)) {
-			  	mbox_cmd_t *mbox = wp->mbox;
+				mbox_cmd_t *mbox = wp->mbox;
 				if (mbox->cmd.qdm & 0x80){
 					mbox->cmd.result = 0x35;
-					err = -EAGAIN;	
+					err = -EAGAIN;
 					break;
 				}
 			}
@@ -2286,15 +2286,15 @@
 
 
 			/* Check if data buffers are pending for transmission,
-                         * if so, check whether user wants to wait until data
-                         * is transmitted, or reset a call and drop packets */
-                          
+			 * if so, check whether user wants to wait until data
+			 * is transmitted, or reset a call and drop packets */
+
 			if (atomic_read(&sk->sk_wmem_alloc) ||
 			    check_driver_busy(sk)) {
-			  	mbox_cmd_t *mbox = wp->mbox;
+				mbox_cmd_t *mbox = wp->mbox;
 				if (mbox->cmd.qdm & 0x80){
 					mbox->cmd.result = 0x35;
-					err = -EAGAIN;	
+					err = -EAGAIN;
 					break;
 				}
 			}
@@ -2316,7 +2316,7 @@
 
 			if (sk->sk_state == WANSOCK_CONNECTED) {
 
-				wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn;	
+				wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn;
 
 				DBG_PRINTK(KERN_INFO "\nwansock: PLACE CALL OK %i\n",
 					wp->lcn);
@@ -2337,7 +2337,7 @@
 
 			break;
 
-		default: 
+		default:
 			return -EINVAL;
 	}
 
@@ -2364,9 +2364,9 @@
 /*======================================================================
  * wanpipe_accept
  *
- *	ACCEPT() System call.	X25API Specific function. 
- *	For each incoming call, create a new socket and 
- *      return it to the user.	
+ *	ACCEPT() System call.	X25API Specific function.
+ *	For each incoming call, create a new socket and
+ *      return it to the user.
  *=====================================================================*/
 
 static int wanpipe_accept(struct socket *sock, struct socket *newsock, int flags)
@@ -2378,10 +2378,10 @@
 	int err=0;
 
 	if (newsock->sk != NULL){
-		wanpipe_kill_sock_accept(newsock->sk);	
+		wanpipe_kill_sock_accept(newsock->sk);
 		newsock->sk=NULL;
 	}
-	
+
 	if ((sk = sock->sk) == NULL)
 		return -EINVAL;
 
@@ -2410,10 +2410,10 @@
 	}
 	current->state = TASK_RUNNING;
 	remove_wait_queue(sk->sk_sleep,&wait);
-	
+
 	if (err != 0)
 		return err;
-	
+
 	newsk = get_newsk_from_skb(skb);
 	if (!newsk){
 		return -EINVAL;
@@ -2431,7 +2431,7 @@
 	/* Now attach up the new socket */
 	sk->sk_ack_backlog--;
 	newsock->sk = newsk;
-	
+
 	kfree_skb(skb);
 
 	DBG_PRINTK(KERN_INFO "\nwansock: ACCEPT Got LCN %i\n",
@@ -2449,16 +2449,16 @@
 struct sock * get_newsk_from_skb (struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dev;
-	wanpipe_common_t *chan;	
+	wanpipe_common_t *chan;
 
 	if (!dev){
 		return NULL;
 	}
-		
+
 	if ((chan = dev->priv) == NULL){
 		return NULL;
 	}
-		
+
 	if (!chan->sk){
 		return NULL;
 	}
@@ -2470,7 +2470,7 @@
  *
  *  	CONNECT() System Call. X25API specific function
  * 	Check the state of the sock, and execute PLACE_CALL command.
- *      Connect can ether block or return without waiting for connection, 
+ *      Connect can ether block or return without waiting for connection,
  *      if specified by user.
  *=====================================================================*/
 
@@ -2492,7 +2492,7 @@
 		return -ECONNREFUSED;
 	}
 
-	sk->sk_state = WANSOCK_DISCONNECTED;	
+	sk->sk_state = WANSOCK_DISCONNECTED;
 	sock->state  = SS_UNCONNECTED;
 
 	if (addr_len != sizeof(struct wan_sockaddr_ll))
@@ -2505,7 +2505,7 @@
 		return -ENETUNREACH;
 
 	dev_put(dev);
-	
+
 	if (!sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
 		return -EINVAL;
 
@@ -2534,7 +2534,7 @@
 
 	if (sk->sk_state != WANSOCK_CONNECTED) {
 		sock->state = SS_UNCONNECTED;
-		return -ECONNREFUSED; 
+		return -ECONNREFUSED;
 	}
 
 	sock->state = SS_CONNECTED;
@@ -2549,10 +2549,10 @@
 	.connect = 	wanpipe_connect,
 	.socketpair = 	sock_no_socketpair,
 	.accept = 	wanpipe_accept,
-	.getname = 	wanpipe_getname, 
+	.getname = 	wanpipe_getname,
 	.poll = 	wanpipe_poll,
 	.ioctl = 	wanpipe_ioctl,
-	.listen = 	wanpipe_listen, 
+	.listen = 	wanpipe_listen,
 	.shutdown = 	sock_no_shutdown,
 	.setsockopt = 	sock_no_setsockopt,
 	.getsockopt = 	sock_no_getsockopt,
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index 769cdd6..5d2d93d 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -86,8 +86,8 @@
 
 static struct wan_device *wanrouter_find_device(char *name);
 static int wanrouter_delete_interface(struct wan_device *wandev, char *name);
-void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
-void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
+static void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
+static void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
 
 
 
@@ -104,8 +104,8 @@
  *	Organize Unique Identifiers for encapsulation/decapsulation
  */
 
-static unsigned char wanrouter_oui_ether[] = { 0x00, 0x00, 0x00 };
 #if 0
+static unsigned char wanrouter_oui_ether[] = { 0x00, 0x00, 0x00 };
 static unsigned char wanrouter_oui_802_2[] = { 0x00, 0x80, 0xC2 };
 #endif
 
@@ -246,6 +246,8 @@
 	return 0;
 }
 
+#if 0
+
 /*
  *	Encapsulate packet.
  *
@@ -312,10 +314,10 @@
 		cnt += 1;
 		break;
 
-        case NLPID_SNAP:	/* SNAP encapsulation */
+	case NLPID_SNAP:	/* SNAP encapsulation */
 		if (memcmp(&skb->data[cnt + 1], wanrouter_oui_ether,
 			   sizeof(wanrouter_oui_ether))){
-          		printk(KERN_INFO
+			printk(KERN_INFO
 				"%s: unsupported SNAP OUI %02X-%02X-%02X "
 				"on interface %s!\n", wanrouter_modname,
 				skb->data[cnt+1], skb->data[cnt+2],
@@ -341,6 +343,7 @@
 	return ethertype;
 }
 
+#endif  /*  0  */
 
 /*
  *	WAN device IOCTL.
@@ -447,7 +450,7 @@
 		kfree(conf);
 		printk(KERN_INFO "%s: ERROR, Invalid MAGIC Number\n",
 				wandev->name);
-	        return -EINVAL;
+		return -EINVAL;
 	}
 
 	if (conf->data_size && conf->data) {
@@ -456,13 +459,13 @@
 			    "%s: ERROR, Invalid firmware data size %i !\n",
 					wandev->name, conf->data_size);
 			kfree(conf);
-		        return -EINVAL;
+			return -EINVAL;
 		}
 
 		data = vmalloc(conf->data_size);
 		if (!data) {
 			printk(KERN_INFO
-			 	"%s: ERROR, Faild allocate kernel memory !\n",
+				"%s: ERROR, Faild allocate kernel memory !\n",
 				wandev->name);
 			kfree(conf);
 			return -ENOBUFS;
@@ -683,7 +686,7 @@
 static int wanrouter_device_del_if(struct wan_device *wandev, char __user *u_name)
 {
 	char name[WAN_IFNAME_SZ + 1];
-        int err = 0;
+	int err = 0;
 
 	if (wandev->state == WAN_UNCONFIGURED)
 		return -ENODEV;
@@ -706,8 +709,8 @@
 	 * interfaces are deleted and the link irrecoverably disconnected.
 	 */
 
-        if (!wandev->ndev && wandev->shutdown)
-                err = wandev->shutdown(wandev);
+	if (!wandev->ndev && wandev->shutdown)
+		err = wandev->shutdown(wandev);
 
 	return err;
 }
@@ -799,23 +802,19 @@
 	return 0;
 }
 
-void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags)
+static void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags)
 {
-       	spin_lock_irqsave(lock, *smp_flags);
+	spin_lock_irqsave(lock, *smp_flags);
 }
 
 
-void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags)
+static void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags)
 {
 	spin_unlock_irqrestore(lock, *smp_flags);
 }
 
 EXPORT_SYMBOL(register_wan_device);
 EXPORT_SYMBOL(unregister_wan_device);
-EXPORT_SYMBOL(wanrouter_encapsulate);
-EXPORT_SYMBOL(wanrouter_type_trans);
-EXPORT_SYMBOL(lock_adapter_irq);
-EXPORT_SYMBOL(unlock_adapter_irq);
 
 MODULE_LICENSE("GPL");
 
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c
index 930ea59..2051065 100644
--- a/net/wanrouter/wanproc.c
+++ b/net/wanrouter/wanproc.c
@@ -37,10 +37,10 @@
 
 #define PROT_DECODE(prot) ((prot == WANCONFIG_FR) ? " FR" :\
 			      (prot == WANCONFIG_X25) ? " X25" : \
-			         (prot == WANCONFIG_PPP) ? " PPP" : \
+				 (prot == WANCONFIG_PPP) ? " PPP" : \
 				    (prot == WANCONFIG_CHDLC) ? " CHDLC": \
 				       (prot == WANCONFIG_MPPP) ? " MPPP" : \
-				           " Unknown" )
+					   " Unknown" )
 
 /****** Function Prototypes *************************************************/
 
@@ -188,7 +188,7 @@
 	return seq_open(file, &status_op);
 }
 
-static struct file_operations config_fops = {
+static const struct file_operations config_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = config_open,
 	.read	 = seq_read,
@@ -196,7 +196,7 @@
 	.release = seq_release,
 };
 
-static struct file_operations status_fops = {
+static const struct file_operations status_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = status_open,
 	.read	 = seq_read,
@@ -271,7 +271,7 @@
 	return single_open(file, wandev_show, PDE(inode)->data);
 }
 
-static struct file_operations wandev_fops = {
+static const struct file_operations wandev_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = wandev_open,
 	.read	 = seq_read,
diff --git a/net/x25/Makefile b/net/x25/Makefile
index 587a71a..a2c34ab 100644
--- a/net/x25/Makefile
+++ b/net/x25/Makefile
@@ -6,5 +6,5 @@
 
 x25-y			:= af_x25.o x25_dev.o x25_facilities.o x25_in.o \
 			   x25_link.o x25_out.o x25_route.o x25_subr.o \
-			   x25_timer.o x25_proc.o
+			   x25_timer.o x25_proc.o x25_forward.o
 x25-$(CONFIG_SYSCTL)	+= sysctl_net_x25.o
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index b5c80b1..e62ba41 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -3,7 +3,7 @@
  *
  *	This is ALPHA test software. This code may break your machine,
  *	randomly fail to work with new releases, misbehave and/or generally
- *	screw up. It might even work. 
+ *	screw up. It might even work.
  *
  *	This code REQUIRES 2.1.15 or higher
  *
@@ -18,11 +18,11 @@
  *	X.25 002	Jonathan Naylor	Centralised disconnect handling.
  *					New timer architecture.
  *	2000-03-11	Henner Eisen	MSG_EOR handling more POSIX compliant.
- *	2000-03-22	Daniela Squassoni Allowed disabling/enabling of 
- *					  facilities negotiation and increased 
+ *	2000-03-22	Daniela Squassoni Allowed disabling/enabling of
+ *					  facilities negotiation and increased
  *					  the throughput upper limit.
  *	2000-08-27	Arnaldo C. Melo s/suser/capable/ + micro cleanups
- *	2000-09-04	Henner Eisen	Set sock->state in x25_accept(). 
+ *	2000-09-04	Henner Eisen	Set sock->state in x25_accept().
  *					Fixed x25_output() related skb leakage.
  *	2000-10-02	Henner Eisen	Made x25_kick() single threaded per socket.
  *	2000-10-27	Henner Eisen    MSG_DONTWAIT for fragment allocation.
@@ -63,6 +63,7 @@
 int sysctl_x25_reset_request_timeout   = X25_DEFAULT_T22;
 int sysctl_x25_clear_request_timeout   = X25_DEFAULT_T23;
 int sysctl_x25_ack_holdback_timeout    = X25_DEFAULT_T2;
+int sysctl_x25_forward                 = 0;
 
 HLIST_HEAD(x25_list);
 DEFINE_RWLOCK(x25_list_lock);
@@ -255,8 +256,8 @@
 			 * call user data vs this sockets call user data
 			 */
 			if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) {
-			 	if((memcmp(x25_sk(s)->calluserdata.cuddata,
-			 		skb->data,
+				if((memcmp(x25_sk(s)->calluserdata.cuddata,
+					skb->data,
 					x25_sk(s)->cudmatchlength)) == 0) {
 					sock_hold(s);
 					goto found;
@@ -420,7 +421,7 @@
 {
 	struct sock *sk = sock->sk;
 	int val, len, rc = -ENOPROTOOPT;
-	
+
 	if (level != SOL_X25 || optname != X25_QBITINCL)
 		goto out;
 
@@ -433,7 +434,7 @@
 	rc = -EINVAL;
 	if (len < 0)
 		goto out;
-		
+
 	rc = -EFAULT;
 	if (put_user(len, optlen))
 		goto out;
@@ -522,12 +523,12 @@
 	x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
 	x25->facilities.throughput  = X25_DEFAULT_THROUGHPUT;
 	x25->facilities.reverse     = X25_DEFAULT_REVERSE;
- 	x25->dte_facilities.calling_len = 0;
- 	x25->dte_facilities.called_len = 0;
- 	memset(x25->dte_facilities.called_ae, '\0',
-		 	sizeof(x25->dte_facilities.called_ae));
- 	memset(x25->dte_facilities.calling_ae, '\0',
-		 	sizeof(x25->dte_facilities.calling_ae));
+	x25->dte_facilities.calling_len = 0;
+	x25->dte_facilities.called_len = 0;
+	memset(x25->dte_facilities.called_ae, '\0',
+			sizeof(x25->dte_facilities.called_ae));
+	memset(x25->dte_facilities.calling_ae, '\0',
+			sizeof(x25->dte_facilities.calling_ae));
 
 	rc = 0;
 out:
@@ -607,7 +608,7 @@
 			break;
 	}
 
-	sock->sk	= NULL;	
+	sock->sk	= NULL;
 	sk->sk_socket	= NULL;	/* Not used, but we should do this */
 out:
 	return 0;
@@ -634,7 +635,7 @@
 static int x25_wait_for_connection_establishment(struct sock *sk)
 {
 	DECLARE_WAITQUEUE(wait, current);
-        int rc;
+	int rc;
 
 	add_wait_queue_exclusive(sk->sk_sleep, &wait);
 	for (;;) {
@@ -685,7 +686,7 @@
 	if (sk->sk_state == TCP_ESTABLISHED)
 		goto out;
 
-	sk->sk_state   = TCP_CLOSE;	
+	sk->sk_state   = TCP_CLOSE;
 	sock->state = SS_UNCONNECTED;
 
 	rc = -EINVAL;
@@ -777,7 +778,7 @@
 	remove_wait_queue(sk->sk_sleep, &wait);
 	return rc;
 }
-	
+
 static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
 {
 	struct sock *sk = sock->sk;
@@ -836,7 +837,7 @@
 
 	return 0;
 }
- 
+
 int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
 			unsigned int lci)
 {
@@ -846,7 +847,7 @@
 	struct x25_address source_addr, dest_addr;
 	struct x25_facilities facilities;
 	struct x25_dte_facilities dte_facilities;
-	int len, rc;
+	int len, addr_len, rc;
 
 	/*
 	 *	Remove the LCI and frame type.
@@ -857,7 +858,8 @@
 	 *	Extract the X.25 addresses and convert them to ASCII strings,
 	 *	and remove them.
 	 */
-	skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
+	addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr);
+	skb_pull(skb, addr_len);
 
 	/*
 	 *	Get the length of the facilities, skip past them for the moment
@@ -873,11 +875,28 @@
 	sk = x25_find_listener(&source_addr,skb);
 	skb_push(skb,len);
 
+	if (sk != NULL && sk_acceptq_is_full(sk)) {
+		goto out_sock_put;
+	}
+
 	/*
-	 *	We can't accept the Call Request.
+	 *	We dont have any listeners for this incoming call.
+	 *	Try forwarding it.
 	 */
-	if (sk == NULL || sk_acceptq_is_full(sk))
-		goto out_clear_request;
+	if (sk == NULL) {
+		skb_push(skb, addr_len + X25_STD_MIN_LEN);
+		if (sysctl_x25_forward &&
+				x25_forward_call(&dest_addr, nb, skb, lci) > 0)
+		{
+			/* Call was forwarded, dont process it any more */
+			kfree_skb(skb);
+			rc = 1;
+			goto out;
+		} else {
+			/* No listeners, can't forward, clear the call */
+			goto out_clear_request;
+		}
+	}
 
 	/*
 	 *	Try to reach a compromise on the requested facilities.
@@ -1101,7 +1120,7 @@
 	if (msg->msg_flags & MSG_OOB)
 		skb_queue_tail(&x25->interrupt_out_queue, skb);
 	else {
-	        len = x25_output(sk, skb);
+		len = x25_output(sk, skb);
 		if (len < 0)
 			kfree_skb(skb);
 		else if (x25->qbitincl)
@@ -1200,7 +1219,7 @@
 		msg->msg_flags |= MSG_TRUNC;
 	}
 
-	/* Currently, each datagram always contains a complete record */ 
+	/* Currently, each datagram always contains a complete record */
 	msg->msg_flags |= MSG_EOR;
 
 	rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
@@ -1258,8 +1277,8 @@
 		case SIOCGSTAMP:
 			rc = -EINVAL;
 			if (sk)
-				rc = sock_get_timestamp(sk, 
-						(struct timeval __user *)argp); 
+				rc = sock_get_timestamp(sk,
+						(struct timeval __user *)argp);
 			break;
 		case SIOCGIFADDR:
 		case SIOCSIFADDR:
@@ -1327,17 +1346,17 @@
 		}
 
 		case SIOCX25GDTEFACILITIES: {
- 			rc = copy_to_user(argp, &x25->dte_facilities,
+			rc = copy_to_user(argp, &x25->dte_facilities,
 						sizeof(x25->dte_facilities));
 			if (rc)
 				rc = -EFAULT;
- 			break;
- 		}
+			break;
+		}
 
-	 	case SIOCX25SDTEFACILITIES: {
-	 		struct x25_dte_facilities dtefacs;
-	 		rc = -EFAULT;
-		 	if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
+		case SIOCX25SDTEFACILITIES: {
+			struct x25_dte_facilities dtefacs;
+			rc = -EFAULT;
+			if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
 				break;
 			rc = -EINVAL;
 			if (sk->sk_state != TCP_LISTEN &&
@@ -1395,7 +1414,7 @@
 			if (copy_from_user(&sub_addr, argp,
 					sizeof(sub_addr)))
 				break;
-		 	rc = -EINVAL;
+			rc = -EINVAL;
 			if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
 				break;
 			x25->cudmatchlength = sub_addr.cudmatchlength;
@@ -1424,7 +1443,7 @@
 			break;
 		}
 
- 		default:
+		default:
 			rc = -ENOIOCTLCMD;
 			break;
 	}
@@ -1598,6 +1617,9 @@
 			x25_disconnect(s, ENETUNREACH, 0, 0);
 
 	write_unlock_bh(&x25_list_lock);
+
+	/* Remove any related forwards */
+	x25_clear_forward_by_dev(nb->dev);
 }
 
 static int __init x25_init(void)
diff --git a/net/x25/sysctl_net_x25.c b/net/x25/sysctl_net_x25.c
index aabda59..a59b77f 100644
--- a/net/x25/sysctl_net_x25.c
+++ b/net/x25/sysctl_net_x25.c
@@ -18,7 +18,7 @@
 static struct ctl_table_header *x25_table_header;
 
 static struct ctl_table x25_table[] = {
-        {
+	{
 		.ctl_name =	NET_X25_RESTART_REQUEST_TIMEOUT,
 		.procname =	"restart_request_timeout",
 		.data =		&sysctl_x25_restart_request_timeout,
@@ -29,7 +29,7 @@
 		.extra1 =	&min_timer,
 		.extra2 =	&max_timer,
 	},
-        {
+	{
 		.ctl_name =	NET_X25_CALL_REQUEST_TIMEOUT,
 		.procname =	"call_request_timeout",
 		.data =		&sysctl_x25_call_request_timeout,
@@ -40,7 +40,7 @@
 		.extra1 =	&min_timer,
 		.extra2 =	&max_timer,
 	},
-        {
+	{
 		.ctl_name =	NET_X25_RESET_REQUEST_TIMEOUT,
 		.procname =	"reset_request_timeout",
 		.data =		&sysctl_x25_reset_request_timeout,
@@ -51,7 +51,7 @@
 		.extra1 =	&min_timer,
 		.extra2 =	&max_timer,
 	},
-        {
+	{
 		.ctl_name =	NET_X25_CLEAR_REQUEST_TIMEOUT,
 		.procname =	"clear_request_timeout",
 		.data =		&sysctl_x25_clear_request_timeout,
@@ -62,7 +62,7 @@
 		.extra1 =	&min_timer,
 		.extra2 =	&max_timer,
 	},
-        {
+	{
 		.ctl_name =	NET_X25_ACK_HOLD_BACK_TIMEOUT,
 		.procname =	"acknowledgement_hold_back_timeout",
 		.data =		&sysctl_x25_ack_holdback_timeout,
@@ -73,6 +73,14 @@
 		.extra1 =	&min_timer,
 		.extra2 =	&max_timer,
 	},
+	{
+		.ctl_name =	NET_X25_FORWARD,
+		.procname =	"x25_forward",
+		.data = 	&sysctl_x25_forward,
+		.maxlen = 	sizeof(int),
+		.mode = 	0644,
+		.proc_handler = &proc_dointvec,
+	},
 	{ 0, },
 };
 
@@ -98,7 +106,7 @@
 
 void __init x25_register_sysctl(void)
 {
-	x25_table_header = register_sysctl_table(x25_root_table, 1);
+	x25_table_header = register_sysctl_table(x25_root_table);
 }
 
 void x25_unregister_sysctl(void)
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index 328d80f..c7221de 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -1,8 +1,8 @@
 /*
  *	X.25 Packet Layer release 002
  *
- *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
- *	releases, misbehave and/or generally screw up. It might even work. 
+ *	This is ALPHA test software. This code may break your machine, randomly fail to work with new
+ *	releases, misbehave and/or generally screw up. It might even work.
  *
  *	This code REQUIRES 2.1.15 or higher
  *
@@ -31,7 +31,7 @@
 	unsigned int lci;
 
 	frametype = skb->data[2];
-        lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
+	lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
 
 	/*
 	 *	LCI of zero is always for us, and its always a link control
@@ -67,9 +67,18 @@
 		return x25_rx_call_request(skb, nb, lci);
 
 	/*
-	 *	Its not a Call Request, nor is it a control frame.
-	 *      Let caller throw it away.
+	 * 	Its not a Call Request, nor is it a control frame.
+	 *	Can we forward it?
 	 */
+
+	if (x25_forward_data(lci, nb, skb)) {
+		if (frametype == X25_CLEAR_CONFIRMATION) {
+			x25_clear_forward_by_lci(lci);
+		}
+		kfree_skb(skb);
+		return 1;
+	}
+
 /*
 	x25_transmit_clear_request(nb, lci, 0x0D);
 */
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index 27f5cc7..dec404a 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -3,7 +3,7 @@
  *
  *	This is ALPHA test software. This code may break your machine,
  *	randomly fail to work with new releases, misbehave and/or generally
- *	screw up. It might even work. 
+ *	screw up. It might even work.
  *
  *	This code REQUIRES 2.1.15 or higher
  *
@@ -15,7 +15,7 @@
  *
  *	History
  *	X.25 001	Split from x25_subr.c
- *	mar/20/00	Daniela Squassoni Disabling/enabling of facilities 
+ *	mar/20/00	Daniela Squassoni Disabling/enabling of facilities
  *					  negotiation.
  *	apr/14/05	Shaun Pereira - Allow fast select with no restriction
  *					on response.
@@ -125,8 +125,8 @@
 			break;
 		case X25_FAC_CLASS_D:
 			switch (*p) {
-	 		case X25_FAC_CALLING_AE:
-	 			if (p[1] > X25_MAX_DTE_FACIL_LEN)
+			case X25_FAC_CALLING_AE:
+				if (p[1] > X25_MAX_DTE_FACIL_LEN)
 					break;
 				dte_facs->calling_len = p[2];
 				memcpy(dte_facs->calling_ae, &p[3], p[1] - 1);
@@ -293,7 +293,7 @@
 }
 
 /*
- *	Limit values of certain facilities according to the capability of the 
+ *	Limit values of certain facilities according to the capability of the
  *      currently attached x25 link.
  */
 void x25_limit_facilities(struct x25_facilities *facilities,
diff --git a/net/x25/x25_forward.c b/net/x25/x25_forward.c
new file mode 100644
index 0000000..d339e0c
--- /dev/null
+++ b/net/x25/x25_forward.c
@@ -0,0 +1,163 @@
+/*
+ *	This module:
+ *		This module 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.
+ *
+ *	History
+ *	03-01-2007	Added forwarding for x.25	Andrew Hendry
+ */
+#include <linux/if_arp.h>
+#include <linux/init.h>
+#include <net/x25.h>
+
+struct list_head x25_forward_list = LIST_HEAD_INIT(x25_forward_list);
+DEFINE_RWLOCK(x25_forward_list_lock);
+
+int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from,
+			struct sk_buff *skb, int lci)
+{
+	struct x25_route *rt;
+	struct x25_neigh *neigh_new = NULL;
+	struct list_head *entry;
+	struct x25_forward *x25_frwd, *new_frwd;
+	struct sk_buff *skbn;
+	short same_lci = 0;
+	int rc = 0;
+
+	if ((rt = x25_get_route(dest_addr)) != NULL) {
+
+		if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) {
+			/* This shouldnt happen, if it occurs somehow
+			 * do something sensible
+			 */
+			goto out_put_route;
+		}
+
+		/* Avoid a loop. This is the normal exit path for a
+		 * system with only one x.25 iface and default route
+		 */
+		if (rt->dev == from->dev) {
+			goto out_put_nb;
+		}
+
+		/* Remote end sending a call request on an already
+		 * established LCI? It shouldnt happen, just in case..
+		 */
+		read_lock_bh(&x25_forward_list_lock);
+		list_for_each(entry, &x25_forward_list) {
+			x25_frwd = list_entry(entry, struct x25_forward, node);
+			if (x25_frwd->lci == lci) {
+				printk(KERN_WARNING "X.25: call request for lci which is already registered!, transmitting but not registering new pair\n");
+				same_lci = 1;
+			}
+		}
+		read_unlock_bh(&x25_forward_list_lock);
+
+		/* Save the forwarding details for future traffic */
+		if (!same_lci){
+			if ((new_frwd = kmalloc(sizeof(struct x25_forward),
+							GFP_ATOMIC)) == NULL){
+				rc = -ENOMEM;
+				goto out_put_nb;
+			}
+			new_frwd->lci = lci;
+			new_frwd->dev1 = rt->dev;
+			new_frwd->dev2 = from->dev;
+			write_lock_bh(&x25_forward_list_lock);
+			list_add(&new_frwd->node, &x25_forward_list);
+			write_unlock_bh(&x25_forward_list_lock);
+		}
+
+		/* Forward the call request */
+		if ( (skbn = skb_clone(skb, GFP_ATOMIC)) == NULL){
+			goto out_put_nb;
+		}
+		x25_transmit_link(skbn, neigh_new);
+		rc = 1;
+	}
+
+
+out_put_nb:
+	x25_neigh_put(neigh_new);
+
+out_put_route:
+	x25_route_put(rt);
+	return rc;
+}
+
+
+int x25_forward_data(int lci, struct x25_neigh *from, struct sk_buff *skb) {
+
+	struct x25_forward *frwd;
+	struct list_head *entry;
+	struct net_device *peer = NULL;
+	struct x25_neigh *nb;
+	struct sk_buff *skbn;
+	int rc = 0;
+
+	read_lock_bh(&x25_forward_list_lock);
+	list_for_each(entry, &x25_forward_list) {
+		frwd = list_entry(entry, struct x25_forward, node);
+		if (frwd->lci == lci) {
+			/* The call is established, either side can send */
+			if (from->dev == frwd->dev1) {
+				peer = frwd->dev2;
+			} else {
+				peer = frwd->dev1;
+			}
+			break;
+		}
+	}
+	read_unlock_bh(&x25_forward_list_lock);
+
+	if ( (nb = x25_get_neigh(peer)) == NULL)
+		goto out;
+
+	if ( (skbn = pskb_copy(skb, GFP_ATOMIC)) == NULL){
+		goto out;
+
+	}
+	x25_transmit_link(skbn, nb);
+
+	x25_neigh_put(nb);
+	rc = 1;
+out:
+	return rc;
+}
+
+void x25_clear_forward_by_lci(unsigned int lci)
+{
+	struct x25_forward *fwd;
+	struct list_head *entry, *tmp;
+
+	write_lock_bh(&x25_forward_list_lock);
+
+	list_for_each_safe(entry, tmp, &x25_forward_list) {
+		fwd = list_entry(entry, struct x25_forward, node);
+		if (fwd->lci == lci) {
+			list_del(&fwd->node);
+			kfree(fwd);
+		}
+	}
+	write_unlock_bh(&x25_forward_list_lock);
+}
+
+
+void x25_clear_forward_by_dev(struct net_device *dev)
+{
+	struct x25_forward *fwd;
+	struct list_head *entry, *tmp;
+
+	write_lock_bh(&x25_forward_list_lock);
+
+	list_for_each_safe(entry, tmp, &x25_forward_list) {
+		fwd = list_entry(entry, struct x25_forward, node);
+		if ((fwd->dev1 == dev) || (fwd->dev2 == dev)){
+			list_del(&fwd->node);
+			kfree(fwd);
+		}
+	}
+	write_unlock_bh(&x25_forward_list_lock);
+}
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index eed50e1..c5239fc 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -3,7 +3,7 @@
  *
  *	This is ALPHA test software. This code may break your machine,
  *	randomly fail to work with new releases, misbehave and/or generally
- *	screw up. It might even work. 
+ *	screw up. It might even work.
  *
  *	This code REQUIRES 2.1.15 or higher
  *
@@ -17,7 +17,7 @@
  *	X.25 001	Jonathan Naylor	  Started coding.
  *	X.25 002	Jonathan Naylor	  Centralised disconnection code.
  *					  New timer architecture.
- *	2000-03-20	Daniela Squassoni Disabling/enabling of facilities 
+ *	2000-03-20	Daniela Squassoni Disabling/enabling of facilities
  *					  negotiation.
  *	2000-11-10	Henner Eisen	  Check and reset for out-of-sequence
  *					  i-frames.
@@ -67,7 +67,7 @@
 			kfree_skb(skbo);
 		}
 
-		x25->fraglen = 0;		
+		x25->fraglen = 0;
 	}
 
 	skb_set_owner_r(skbn, sk);
@@ -167,7 +167,7 @@
 	int queued = 0;
 	int modulus;
 	struct x25_sock *x25 = x25_sk(sk);
-	
+
 	modulus = (x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS;
 
 	switch (frametype) {
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index 0a760fe..741ce95 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -3,7 +3,7 @@
  *
  *	This is ALPHA test software. This code may break your machine,
  *	randomly fail to work with new releases, misbehave and/or generally
- *	screw up. It might even work. 
+ *	screw up. It might even work.
  *
  *	This code REQUIRES 2.1.15 or higher
  *
@@ -16,7 +16,7 @@
  *	History
  *	X.25 001	Jonathan Naylor	  Started coding.
  *	X.25 002	Jonathan Naylor	  New timer architecture.
- *	mar/20/00	Daniela Squassoni Disabling/enabling of facilities 
+ *	mar/20/00	Daniela Squassoni Disabling/enabling of facilities
  *					  negotiation.
  *	2000-09-04	Henner Eisen	  dev_hold() / dev_put() for x25_neigh.
  */
@@ -94,7 +94,7 @@
 			       skb->data[3], skb->data[4],
 			       skb->data[5], skb->data[6]);
 			break;
-			
+
 		default:
 			printk(KERN_WARNING "x25: received unknown %02X "
 			       "with LCI 000\n", frametype);
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c
index a2e62ce..6f57378 100644
--- a/net/x25/x25_out.c
+++ b/net/x25/x25_out.c
@@ -3,7 +3,7 @@
  *
  *	This is ALPHA test software. This code may break your machine,
  *	randomly fail to work with new releases, misbehave and/or generally
- *	screw up. It might even work. 
+ *	screw up. It might even work.
  *
  *	This code REQUIRES 2.1.15 or higher
  *
@@ -78,7 +78,7 @@
 					       "sent\n", err, sent);
 				return err;
 			}
-				
+
 			skb_reserve(skbn, frontlen);
 
 			len = max_len > skb->len ? skb->len : max_len;
@@ -101,7 +101,7 @@
 			skb_queue_tail(&sk->sk_write_queue, skbn);
 			sent += len;
 		}
-		
+
 		kfree_skb(skb);
 	} else {
 		skb_queue_tail(&sk->sk_write_queue, skb);
@@ -110,7 +110,7 @@
 	return sent;
 }
 
-/* 
+/*
  *	This procedure is passed a buffer descriptor for an iframe. It builds
  *	the rest of the control part of the frame and then writes it out.
  */
@@ -131,7 +131,7 @@
 		skb->data[2] |= (x25->vr << 5) & 0xE0;
 	}
 
-	x25_transmit_link(skb, x25->neighbour);	
+	x25_transmit_link(skb, x25->neighbour);
 }
 
 void x25_kick(struct sock *sk)
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c
index a11837d..96001f0 100644
--- a/net/x25/x25_proc.c
+++ b/net/x25/x25_proc.c
@@ -3,7 +3,7 @@
  *
  *	This is ALPHA test software. This code may break your machine,
  *	randomly fail to work with new releases, misbehave and/or generally
- *	screw up. It might even work. 
+ *	screw up. It might even work.
  *
  *	This code REQUIRES 2.4 with seq_file support
  *
@@ -62,7 +62,7 @@
 	rt = v;
 	if (rt->node.next != &x25_route_list)
 		rt = list_entry(rt->node.next, struct x25_route, node);
-	else 
+	else
 		rt = NULL;
 out:
 	return rt;
@@ -88,7 +88,7 @@
 		   rt->dev ? rt->dev->name : "???");
 out:
 	return 0;
-} 
+}
 
 static __inline__ struct sock *x25_get_socket_idx(loff_t pos)
 {
@@ -163,7 +163,76 @@
 		   s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L);
 out:
 	return 0;
-} 
+}
+
+static __inline__ struct x25_forward *x25_get_forward_idx(loff_t pos)
+{
+	struct x25_forward *f;
+	struct list_head *entry;
+
+	list_for_each(entry, &x25_forward_list) {
+		f = list_entry(entry, struct x25_forward, node);
+		if (!pos--)
+			goto found;
+	}
+
+	f = NULL;
+found:
+	return f;
+}
+
+static void *x25_seq_forward_start(struct seq_file *seq, loff_t *pos)
+{
+	loff_t l = *pos;
+
+	read_lock_bh(&x25_forward_list_lock);
+	return l ? x25_get_forward_idx(--l) : SEQ_START_TOKEN;
+}
+
+static void *x25_seq_forward_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct x25_forward *f;
+
+	++*pos;
+	if (v == SEQ_START_TOKEN) {
+		f = NULL;
+		if (!list_empty(&x25_forward_list))
+			f = list_entry(x25_forward_list.next,
+					struct x25_forward, node);
+		goto out;
+	}
+	f = v;
+	if (f->node.next != &x25_forward_list)
+		f = list_entry(f->node.next, struct x25_forward, node);
+	else
+		f = NULL;
+out:
+	return f;
+
+}
+
+static void x25_seq_forward_stop(struct seq_file *seq, void *v)
+{
+	read_unlock_bh(&x25_forward_list_lock);
+}
+
+static int x25_seq_forward_show(struct seq_file *seq, void *v)
+{
+	struct x25_forward *f;
+
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "lci dev1       dev2\n");
+		goto out;
+	}
+
+	f = v;
+
+	seq_printf(seq, "%d %-10s %-10s\n",
+			f->lci, f->dev1->name, f->dev2->name);
+
+out:
+	return 0;
+}
 
 static struct seq_operations x25_seq_route_ops = {
 	.start  = x25_seq_route_start,
@@ -179,6 +248,13 @@
 	.show   = x25_seq_socket_show,
 };
 
+static struct seq_operations x25_seq_forward_ops = {
+	.start  = x25_seq_forward_start,
+	.next   = x25_seq_forward_next,
+	.stop   = x25_seq_forward_stop,
+	.show   = x25_seq_forward_show,
+};
+
 static int x25_seq_socket_open(struct inode *inode, struct file *file)
 {
 	return seq_open(file, &x25_seq_socket_ops);
@@ -189,7 +265,12 @@
 	return seq_open(file, &x25_seq_route_ops);
 }
 
-static struct file_operations x25_seq_socket_fops = {
+static int x25_seq_forward_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &x25_seq_forward_ops);
+}
+
+static const struct file_operations x25_seq_socket_fops = {
 	.owner		= THIS_MODULE,
 	.open		= x25_seq_socket_open,
 	.read		= seq_read,
@@ -197,7 +278,7 @@
 	.release	= seq_release,
 };
 
-static struct file_operations x25_seq_route_fops = {
+static const struct file_operations x25_seq_route_fops = {
 	.owner		= THIS_MODULE,
 	.open		= x25_seq_route_open,
 	.read		= seq_read,
@@ -205,6 +286,14 @@
 	.release	= seq_release,
 };
 
+static struct file_operations x25_seq_forward_fops = {
+	.owner		= THIS_MODULE,
+	.open		= x25_seq_forward_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static struct proc_dir_entry *x25_proc_dir;
 
 int __init x25_proc_init(void)
@@ -225,9 +314,17 @@
 	if (!p)
 		goto out_socket;
 	p->proc_fops = &x25_seq_socket_fops;
+
+	p = create_proc_entry("forward", S_IRUGO, x25_proc_dir);
+	if (!p)
+		goto out_forward;
+	p->proc_fops = &x25_seq_forward_fops;
 	rc = 0;
+
 out:
 	return rc;
+out_forward:
+	remove_proc_entry("socket", x25_proc_dir);
 out_socket:
 	remove_proc_entry("route", x25_proc_dir);
 out_route:
@@ -237,6 +334,7 @@
 
 void __exit x25_proc_exit(void)
 {
+	remove_proc_entry("forward", x25_proc_dir);
 	remove_proc_entry("route", x25_proc_dir);
 	remove_proc_entry("socket", x25_proc_dir);
 	remove_proc_entry("x25", proc_net);
diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c
index 2a3fe98..060fcfa 100644
--- a/net/x25/x25_route.c
+++ b/net/x25/x25_route.c
@@ -3,7 +3,7 @@
  *
  *	This is ALPHA test software. This code may break your machine,
  *	randomly fail to work with new releases, misbehave and/or generally
- *	screw up. It might even work. 
+ *	screw up. It might even work.
  *
  *	This code REQUIRES 2.1.15 or higher
  *
@@ -119,6 +119,9 @@
 			__x25_remove_route(rt);
 	}
 	write_unlock_bh(&x25_route_list_lock);
+
+	/* Remove any related forwarding */
+	x25_clear_forward_by_dev(dev);
 }
 
 /*
diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c
index 71ff308..2af190d 100644
--- a/net/x25/x25_timer.c
+++ b/net/x25/x25_timer.c
@@ -3,7 +3,7 @@
  *
  *	This is ALPHA test software. This code may break your machine,
  *	randomly fail to work with new releases, misbehave and/or generally
- *	screw up. It might even work. 
+ *	screw up. It might even work.
  *
  *	This code REQUIRES 2.1.15 or higher
  *
@@ -99,8 +99,8 @@
 {
 	struct sock *sk = (struct sock *)param;
 
-        bh_lock_sock(sk);
-        if (sock_owned_by_user(sk)) /* can currently only occur in state 3 */ 
+	bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) /* can currently only occur in state 3 */
 		goto restart_heartbeat;
 
 	switch (x25_sk(sk)->state) {
diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig
index 0faab63..577a4f82 100644
--- a/net/xfrm/Kconfig
+++ b/net/xfrm/Kconfig
@@ -24,6 +24,17 @@
 
 	  If unsure, say N.
 
+config XFRM_MIGRATE
+	bool "Transformation migrate database (EXPERIMENTAL)"
+	depends on XFRM && EXPERIMENTAL
+	---help---
+	  A feature to update locator(s) of a given IPsec security
+	  association dynamically.  This feature is required, for
+	  instance, in a Mobile IPv6 environment with IPsec configuration
+	  where mobile nodes change their attachment point to the Internet.
+
+	  If unsure, say N.
+
 config NET_KEY
 	tristate "PF_KEY sockets"
 	select XFRM
@@ -34,4 +45,19 @@
 
 	  Say Y unless you know what you are doing.
 
+config NET_KEY_MIGRATE
+	bool "PF_KEY MIGRATE (EXPERIMENTAL)"
+	depends on NET_KEY && EXPERIMENTAL
+	select XFRM_MIGRATE
+	---help---
+	  Add a PF_KEY MIGRATE message to PF_KEYv2 socket family.
+	  The PF_KEY MIGRATE message is used to dynamically update
+	  locator(s) of a given IPsec security association.
+	  This feature is required, for instance, in a Mobile IPv6
+	  environment with IPsec configuration where mobile nodes
+	  change their attachment point to the Internet.  Detail
+	  information can be found in the internet-draft
+	  <draft-sugimoto-mip6-pfkey-migrate>.
+
+	  If unsure, say N.
 
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index f1cf340..f373a8a 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -1,11 +1,11 @@
-/* 
+/*
  * xfrm algorithm interface
  *
  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
  *
  * 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) 
+ * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  */
 
@@ -32,14 +32,14 @@
 {
 	.name = "hmac(digest_null)",
 	.compat = "digest_null",
-	
+
 	.uinfo = {
 		.auth = {
 			.icv_truncbits = 0,
 			.icv_fullbits = 0,
 		}
 	},
-	
+
 	.desc = {
 		.sadb_alg_id = SADB_X_AALG_NULL,
 		.sadb_alg_ivlen = 0,
@@ -57,7 +57,7 @@
 			.icv_fullbits = 128,
 		}
 	},
-	
+
 	.desc = {
 		.sadb_alg_id = SADB_AALG_MD5HMAC,
 		.sadb_alg_ivlen = 0,
@@ -142,14 +142,14 @@
 {
 	.name = "ecb(cipher_null)",
 	.compat = "cipher_null",
-	
+
 	.uinfo = {
 		.encr = {
 			.blockbits = 8,
 			.defkeybits = 0,
 		}
 	},
-	
+
 	.desc = {
 		.sadb_alg_id =	SADB_EALG_NULL,
 		.sadb_alg_ivlen = 0,
@@ -248,40 +248,57 @@
 	}
 },
 {
-        .name = "cbc(serpent)",
-        .compat = "serpent",
+	.name = "cbc(serpent)",
+	.compat = "serpent",
 
-        .uinfo = {
-                .encr = {
-                        .blockbits = 128,
-                        .defkeybits = 128,
-                }
-        },
+	.uinfo = {
+		.encr = {
+			.blockbits = 128,
+			.defkeybits = 128,
+		}
+	},
 
-        .desc = {
-                .sadb_alg_id = SADB_X_EALG_SERPENTCBC,
-                .sadb_alg_ivlen = 8,
-                .sadb_alg_minbits = 128,
-                .sadb_alg_maxbits = 256,
-        }
+	.desc = {
+		.sadb_alg_id = SADB_X_EALG_SERPENTCBC,
+		.sadb_alg_ivlen = 8,
+		.sadb_alg_minbits = 128,
+		.sadb_alg_maxbits = 256,
+	}
 },
 {
-        .name = "cbc(twofish)",
-        .compat = "twofish",
-                 
-        .uinfo = {
-                .encr = {
-                        .blockbits = 128,
-                        .defkeybits = 128,
-                }
-        },
+	.name = "cbc(camellia)",
 
-        .desc = {
-                .sadb_alg_id = SADB_X_EALG_TWOFISHCBC,
-                .sadb_alg_ivlen = 8,
-                .sadb_alg_minbits = 128,
-                .sadb_alg_maxbits = 256
-        }
+	.uinfo = {
+		.encr = {
+			.blockbits = 128,
+			.defkeybits = 128,
+		}
+	},
+
+	.desc = {
+		.sadb_alg_id = SADB_X_EALG_CAMELLIACBC,
+		.sadb_alg_ivlen = 8,
+		.sadb_alg_minbits = 128,
+		.sadb_alg_maxbits = 256
+	}
+},
+{
+	.name = "cbc(twofish)",
+	.compat = "twofish",
+
+	.uinfo = {
+		.encr = {
+			.blockbits = 128,
+			.defkeybits = 128,
+		}
+	},
+
+	.desc = {
+		.sadb_alg_id = SADB_X_EALG_TWOFISHCBC,
+		.sadb_alg_ivlen = 8,
+		.sadb_alg_minbits = 128,
+		.sadb_alg_maxbits = 256
+	}
 },
 };
 
@@ -461,7 +478,7 @@
 {
 #ifdef CONFIG_CRYPTO
 	int i, status;
-	
+
 	BUG_ON(in_softirq());
 
 	for (i = 0; i < aalg_entries(); i++) {
@@ -470,14 +487,14 @@
 		if (aalg_list[i].available != status)
 			aalg_list[i].available = status;
 	}
-	
+
 	for (i = 0; i < ealg_entries(); i++) {
 		status = crypto_has_blkcipher(ealg_list[i].name, 0,
 					      CRYPTO_ALG_ASYNC);
 		if (ealg_list[i].available != status)
 			ealg_list[i].available = status;
 	}
-	
+
 	for (i = 0; i < calg_entries(); i++) {
 		status = crypto_has_comp(calg_list[i].name, 0,
 					 CRYPTO_ALG_ASYNC);
@@ -524,15 +541,15 @@
 	if (copy > 0) {
 		if (copy > len)
 			copy = len;
-		
+
 		sg.page = virt_to_page(skb->data + offset);
 		sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
 		sg.length = copy;
-		
+
 		err = icv_update(desc, &sg, copy);
 		if (unlikely(err))
 			return err;
-		
+
 		if ((len -= copy) == 0)
 			return 0;
 		offset += copy;
@@ -549,11 +566,11 @@
 
 			if (copy > len)
 				copy = len;
-			
+
 			sg.page = frag->page;
 			sg.offset = frag->page_offset + offset-start;
 			sg.length = copy;
-			
+
 			err = icv_update(desc, &sg, copy);
 			if (unlikely(err))
 				return err;
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 414f890..ee15bda 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -4,7 +4,7 @@
  * Changes:
  * 	YOSHIFUJI Hideaki @USAGI
  * 		Split up af-specific portion
- * 	
+ *
  */
 
 #include <linux/slab.h>
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b7e537f..946b715 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * xfrm_policy.c
  *
  * Changes:
@@ -151,7 +151,7 @@
 	return type;
 }
 
-int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, 
+int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl,
 		    unsigned short family)
 {
 	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
@@ -262,7 +262,7 @@
 	if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
 		return MAX_SCHEDULE_TIMEOUT-1;
 	else
-	        return secs*HZ;
+		return secs*HZ;
 }
 
 static void xfrm_policy_timer(unsigned long data)
@@ -1024,17 +1024,17 @@
 static inline int policy_to_flow_dir(int dir)
 {
 	if (XFRM_POLICY_IN == FLOW_DIR_IN &&
- 	    XFRM_POLICY_OUT == FLOW_DIR_OUT &&
- 	    XFRM_POLICY_FWD == FLOW_DIR_FWD)
- 		return dir;
- 	switch (dir) {
- 	default:
- 	case XFRM_POLICY_IN:
- 		return FLOW_DIR_IN;
- 	case XFRM_POLICY_OUT:
- 		return FLOW_DIR_OUT;
- 	case XFRM_POLICY_FWD:
- 		return FLOW_DIR_FWD;
+	    XFRM_POLICY_OUT == FLOW_DIR_OUT &&
+	    XFRM_POLICY_FWD == FLOW_DIR_FWD)
+		return dir;
+	switch (dir) {
+	default:
+	case XFRM_POLICY_IN:
+		return FLOW_DIR_IN;
+	case XFRM_POLICY_OUT:
+		return FLOW_DIR_OUT;
+	case XFRM_POLICY_FWD:
+		return FLOW_DIR_FWD;
 	};
 }
 
@@ -1044,9 +1044,9 @@
 
 	read_lock_bh(&xfrm_policy_lock);
 	if ((pol = sk->sk_policy[dir]) != NULL) {
- 		int match = xfrm_selector_match(&pol->selector, fl,
+		int match = xfrm_selector_match(&pol->selector, fl,
 						sk->sk_family);
- 		int err = 0;
+		int err = 0;
 
 		if (match) {
 			err = security_xfrm_policy_lookup(pol, fl->secid,
@@ -1511,7 +1511,7 @@
 	}
 	*dst_p = dst;
 	dst_release(dst_orig);
- 	xfrm_pols_put(pols, npols);
+	xfrm_pols_put(pols, npols);
 	return 0;
 
 error:
@@ -1546,11 +1546,11 @@
  */
 
 static inline int
-xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x, 
+xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x,
 	      unsigned short family)
 {
 	if (xfrm_state_kern(x))
-		return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, family);
+		return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, tmpl->encap_family);
 	return	x->id.proto == tmpl->id.proto &&
 		(x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
 		(x->props.reqid == tmpl->reqid || !tmpl->reqid) &&
@@ -1619,7 +1619,7 @@
 	return 0;
 }
 
-int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, 
+int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
 			unsigned short family)
 {
 	struct xfrm_policy *pol;
@@ -1997,9 +1997,14 @@
 	if (audit_enabled == 0)
 		return;
 
+	BUG_ON((type == AUDIT_MAC_IPSEC_ADDSA ||
+		type == AUDIT_MAC_IPSEC_DELSA) && !x);
+	BUG_ON((type == AUDIT_MAC_IPSEC_ADDSPD ||
+		type == AUDIT_MAC_IPSEC_DELSPD) && !xp);
+
 	audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type);
 	if (audit_buf == NULL)
-	return;
+		return;
 
 	switch(type) {
 	case AUDIT_MAC_IPSEC_ADDSA:
@@ -2236,3 +2241,234 @@
 	xfrm_input_init();
 }
 
+#ifdef CONFIG_XFRM_MIGRATE
+static int xfrm_migrate_selector_match(struct xfrm_selector *sel_cmp,
+				       struct xfrm_selector *sel_tgt)
+{
+	if (sel_cmp->proto == IPSEC_ULPROTO_ANY) {
+		if (sel_tgt->family == sel_cmp->family &&
+		    xfrm_addr_cmp(&sel_tgt->daddr, &sel_cmp->daddr,
+				  sel_cmp->family) == 0 &&
+		    xfrm_addr_cmp(&sel_tgt->saddr, &sel_cmp->saddr,
+				  sel_cmp->family) == 0 &&
+		    sel_tgt->prefixlen_d == sel_cmp->prefixlen_d &&
+		    sel_tgt->prefixlen_s == sel_cmp->prefixlen_s) {
+			return 1;
+		}
+	} else {
+		if (memcmp(sel_tgt, sel_cmp, sizeof(*sel_tgt)) == 0) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static struct xfrm_policy * xfrm_migrate_policy_find(struct xfrm_selector *sel,
+						     u8 dir, u8 type)
+{
+	struct xfrm_policy *pol, *ret = NULL;
+	struct hlist_node *entry;
+	struct hlist_head *chain;
+	u32 priority = ~0U;
+
+	read_lock_bh(&xfrm_policy_lock);
+	chain = policy_hash_direct(&sel->daddr, &sel->saddr, sel->family, dir);
+	hlist_for_each_entry(pol, entry, chain, bydst) {
+		if (xfrm_migrate_selector_match(sel, &pol->selector) &&
+		    pol->type == type) {
+			ret = pol;
+			priority = ret->priority;
+			break;
+		}
+	}
+	chain = &xfrm_policy_inexact[dir];
+	hlist_for_each_entry(pol, entry, chain, bydst) {
+		if (xfrm_migrate_selector_match(sel, &pol->selector) &&
+		    pol->type == type &&
+		    pol->priority < priority) {
+			ret = pol;
+			break;
+		}
+	}
+
+	if (ret)
+		xfrm_pol_hold(ret);
+
+	read_unlock_bh(&xfrm_policy_lock);
+
+	return ret;
+}
+
+static int migrate_tmpl_match(struct xfrm_migrate *m, struct xfrm_tmpl *t)
+{
+	int match = 0;
+
+	if (t->mode == m->mode && t->id.proto == m->proto &&
+	    (m->reqid == 0 || t->reqid == m->reqid)) {
+		switch (t->mode) {
+		case XFRM_MODE_TUNNEL:
+		case XFRM_MODE_BEET:
+			if (xfrm_addr_cmp(&t->id.daddr, &m->old_daddr,
+					  m->old_family) == 0 &&
+			    xfrm_addr_cmp(&t->saddr, &m->old_saddr,
+					  m->old_family) == 0) {
+				match = 1;
+			}
+			break;
+		case XFRM_MODE_TRANSPORT:
+			/* in case of transport mode, template does not store
+			   any IP addresses, hence we just compare mode and
+			   protocol */
+			match = 1;
+			break;
+		default:
+			break;
+		}
+	}
+	return match;
+}
+
+/* update endpoint address(es) of template(s) */
+static int xfrm_policy_migrate(struct xfrm_policy *pol,
+			       struct xfrm_migrate *m, int num_migrate)
+{
+	struct xfrm_migrate *mp;
+	struct dst_entry *dst;
+	int i, j, n = 0;
+
+	write_lock_bh(&pol->lock);
+	if (unlikely(pol->dead)) {
+		/* target policy has been deleted */
+		write_unlock_bh(&pol->lock);
+		return -ENOENT;
+	}
+
+	for (i = 0; i < pol->xfrm_nr; i++) {
+		for (j = 0, mp = m; j < num_migrate; j++, mp++) {
+			if (!migrate_tmpl_match(mp, &pol->xfrm_vec[i]))
+				continue;
+			n++;
+			if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL)
+				continue;
+			/* update endpoints */
+			memcpy(&pol->xfrm_vec[i].id.daddr, &mp->new_daddr,
+			       sizeof(pol->xfrm_vec[i].id.daddr));
+			memcpy(&pol->xfrm_vec[i].saddr, &mp->new_saddr,
+			       sizeof(pol->xfrm_vec[i].saddr));
+			pol->xfrm_vec[i].encap_family = mp->new_family;
+			/* flush bundles */
+			while ((dst = pol->bundles) != NULL) {
+				pol->bundles = dst->next;
+				dst_free(dst);
+			}
+		}
+	}
+
+	write_unlock_bh(&pol->lock);
+
+	if (!n)
+		return -ENODATA;
+
+	return 0;
+}
+
+static int xfrm_migrate_check(struct xfrm_migrate *m, int num_migrate)
+{
+	int i, j;
+
+	if (num_migrate < 1 || num_migrate > XFRM_MAX_DEPTH)
+		return -EINVAL;
+
+	for (i = 0; i < num_migrate; i++) {
+		if ((xfrm_addr_cmp(&m[i].old_daddr, &m[i].new_daddr,
+				   m[i].old_family) == 0) &&
+		    (xfrm_addr_cmp(&m[i].old_saddr, &m[i].new_saddr,
+				   m[i].old_family) == 0))
+			return -EINVAL;
+		if (xfrm_addr_any(&m[i].new_daddr, m[i].new_family) ||
+		    xfrm_addr_any(&m[i].new_saddr, m[i].new_family))
+			return -EINVAL;
+
+		/* check if there is any duplicated entry */
+		for (j = i + 1; j < num_migrate; j++) {
+			if (!memcmp(&m[i].old_daddr, &m[j].old_daddr,
+				    sizeof(m[i].old_daddr)) &&
+			    !memcmp(&m[i].old_saddr, &m[j].old_saddr,
+				    sizeof(m[i].old_saddr)) &&
+			    m[i].proto == m[j].proto &&
+			    m[i].mode == m[j].mode &&
+			    m[i].reqid == m[j].reqid &&
+			    m[i].old_family == m[j].old_family)
+				return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+		 struct xfrm_migrate *m, int num_migrate)
+{
+	int i, err, nx_cur = 0, nx_new = 0;
+	struct xfrm_policy *pol = NULL;
+	struct xfrm_state *x, *xc;
+	struct xfrm_state *x_cur[XFRM_MAX_DEPTH];
+	struct xfrm_state *x_new[XFRM_MAX_DEPTH];
+	struct xfrm_migrate *mp;
+
+	if ((err = xfrm_migrate_check(m, num_migrate)) < 0)
+		goto out;
+
+	/* Stage 1 - find policy */
+	if ((pol = xfrm_migrate_policy_find(sel, dir, type)) == NULL) {
+		err = -ENOENT;
+		goto out;
+	}
+
+	/* Stage 2 - find and update state(s) */
+	for (i = 0, mp = m; i < num_migrate; i++, mp++) {
+		if ((x = xfrm_migrate_state_find(mp))) {
+			x_cur[nx_cur] = x;
+			nx_cur++;
+			if ((xc = xfrm_state_migrate(x, mp))) {
+				x_new[nx_new] = xc;
+				nx_new++;
+			} else {
+				err = -ENODATA;
+				goto restore_state;
+			}
+		}
+	}
+
+	/* Stage 3 - update policy */
+	if ((err = xfrm_policy_migrate(pol, m, num_migrate)) < 0)
+		goto restore_state;
+
+	/* Stage 4 - delete old state(s) */
+	if (nx_cur) {
+		xfrm_states_put(x_cur, nx_cur);
+		xfrm_states_delete(x_cur, nx_cur);
+	}
+
+	/* Stage 5 - announce */
+	km_migrate(sel, dir, type, m, num_migrate);
+
+	xfrm_pol_put(pol);
+
+	return 0;
+out:
+	return err;
+
+restore_state:
+	if (pol)
+		xfrm_pol_put(pol);
+	if (nx_cur)
+		xfrm_states_put(x_cur, nx_cur);
+	if (nx_new)
+		xfrm_states_delete(x_new, nx_new);
+
+	return err;
+}
+EXPORT_SYMBOL(xfrm_migrate);
+#endif
+
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index fdb08d9..a35f9e4 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -183,9 +183,6 @@
 
 int __xfrm_state_delete(struct xfrm_state *x);
 
-static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
-static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
-
 int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
 void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
 
@@ -230,7 +227,7 @@
 	if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
 		return MAX_SCHEDULE_TIMEOUT-1;
 	else
-	        return secs*HZ;
+		return secs*HZ;
 }
 
 static void xfrm_timer_handler(unsigned long data)
@@ -526,7 +523,7 @@
 }
 
 struct xfrm_state *
-xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 
+xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
 		struct flowi *fl, struct xfrm_tmpl *tmpl,
 		struct xfrm_policy *pol, int *err,
 		unsigned short family)
@@ -537,7 +534,7 @@
 	int acquire_in_progress = 0;
 	int error = 0;
 	struct xfrm_state *best = NULL;
-	
+
 	spin_lock_bh(&xfrm_state_lock);
 	hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
 		if (x->props.family == family &&
@@ -573,7 +570,7 @@
 				acquire_in_progress = 1;
 			} else if (x->km.state == XFRM_STATE_ERROR ||
 				   x->km.state == XFRM_STATE_EXPIRED) {
- 				if (xfrm_selector_match(&x->sel, fl, family) &&
+				if (xfrm_selector_match(&x->sel, fl, family) &&
 				    security_xfrm_state_pol_flow_match(x, pol, fl))
 					error = -ESRCH;
 			}
@@ -831,6 +828,160 @@
 }
 EXPORT_SYMBOL(xfrm_state_add);
 
+#ifdef CONFIG_XFRM_MIGRATE
+struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
+{
+	int err = -ENOMEM;
+	struct xfrm_state *x = xfrm_state_alloc();
+	if (!x)
+		goto error;
+
+	memcpy(&x->id, &orig->id, sizeof(x->id));
+	memcpy(&x->sel, &orig->sel, sizeof(x->sel));
+	memcpy(&x->lft, &orig->lft, sizeof(x->lft));
+	x->props.mode = orig->props.mode;
+	x->props.replay_window = orig->props.replay_window;
+	x->props.reqid = orig->props.reqid;
+	x->props.family = orig->props.family;
+	x->props.saddr = orig->props.saddr;
+
+	if (orig->aalg) {
+		x->aalg = xfrm_algo_clone(orig->aalg);
+		if (!x->aalg)
+			goto error;
+	}
+	x->props.aalgo = orig->props.aalgo;
+
+	if (orig->ealg) {
+		x->ealg = xfrm_algo_clone(orig->ealg);
+		if (!x->ealg)
+			goto error;
+	}
+	x->props.ealgo = orig->props.ealgo;
+
+	if (orig->calg) {
+		x->calg = xfrm_algo_clone(orig->calg);
+		if (!x->calg)
+			goto error;
+	}
+	x->props.calgo = orig->props.calgo;
+
+	if (orig->encap) {
+		x->encap = kmemdup(orig->encap, sizeof(*x->encap), GFP_KERNEL);
+		if (!x->encap)
+			goto error;
+	}
+
+	if (orig->coaddr) {
+		x->coaddr = kmemdup(orig->coaddr, sizeof(*x->coaddr),
+				    GFP_KERNEL);
+		if (!x->coaddr)
+			goto error;
+	}
+
+	err = xfrm_init_state(x);
+	if (err)
+		goto error;
+
+	x->props.flags = orig->props.flags;
+
+	x->curlft.add_time = orig->curlft.add_time;
+	x->km.state = orig->km.state;
+	x->km.seq = orig->km.seq;
+
+	return x;
+
+ error:
+	if (errp)
+		*errp = err;
+	if (x) {
+		kfree(x->aalg);
+		kfree(x->ealg);
+		kfree(x->calg);
+		kfree(x->encap);
+		kfree(x->coaddr);
+	}
+	kfree(x);
+	return NULL;
+}
+EXPORT_SYMBOL(xfrm_state_clone);
+
+/* xfrm_state_lock is held */
+struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m)
+{
+	unsigned int h;
+	struct xfrm_state *x;
+	struct hlist_node *entry;
+
+	if (m->reqid) {
+		h = xfrm_dst_hash(&m->old_daddr, &m->old_saddr,
+				  m->reqid, m->old_family);
+		hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
+			if (x->props.mode != m->mode ||
+			    x->id.proto != m->proto)
+				continue;
+			if (m->reqid && x->props.reqid != m->reqid)
+				continue;
+			if (xfrm_addr_cmp(&x->id.daddr, &m->old_daddr,
+					  m->old_family) ||
+			    xfrm_addr_cmp(&x->props.saddr, &m->old_saddr,
+					  m->old_family))
+				continue;
+			xfrm_state_hold(x);
+			return x;
+		}
+	} else {
+		h = xfrm_src_hash(&m->old_daddr, &m->old_saddr,
+				  m->old_family);
+		hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) {
+			if (x->props.mode != m->mode ||
+			    x->id.proto != m->proto)
+				continue;
+			if (xfrm_addr_cmp(&x->id.daddr, &m->old_daddr,
+					  m->old_family) ||
+			    xfrm_addr_cmp(&x->props.saddr, &m->old_saddr,
+					  m->old_family))
+				continue;
+			xfrm_state_hold(x);
+			return x;
+		}
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(xfrm_migrate_state_find);
+
+struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
+				       struct xfrm_migrate *m)
+{
+	struct xfrm_state *xc;
+	int err;
+
+	xc = xfrm_state_clone(x, &err);
+	if (!xc)
+		return NULL;
+
+	memcpy(&xc->id.daddr, &m->new_daddr, sizeof(xc->id.daddr));
+	memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr));
+
+	/* add state */
+	if (!xfrm_addr_cmp(&x->id.daddr, &m->new_daddr, m->new_family)) {
+		/* a care is needed when the destination address of the
+		   state is to be updated as it is a part of triplet */
+		xfrm_state_insert(xc);
+	} else {
+		if ((err = xfrm_state_add(xc)) < 0)
+			goto error;
+	}
+
+	return xc;
+error:
+	kfree(xc);
+	return NULL;
+}
+EXPORT_SYMBOL(xfrm_state_migrate);
+#endif
+
 int xfrm_state_update(struct xfrm_state *x)
 {
 	struct xfrm_state *x1;
@@ -970,8 +1121,8 @@
 EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
 
 struct xfrm_state *
-xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 
-	      xfrm_address_t *daddr, xfrm_address_t *saddr, 
+xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
+	      xfrm_address_t *daddr, xfrm_address_t *saddr,
 	      int create, unsigned short family)
 {
 	struct xfrm_state *x;
@@ -1345,6 +1496,26 @@
 }
 EXPORT_SYMBOL(km_policy_expired);
 
+int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+	       struct xfrm_migrate *m, int num_migrate)
+{
+	int err = -EINVAL;
+	int ret;
+	struct xfrm_mgr *km;
+
+	read_lock(&xfrm_km_lock);
+	list_for_each_entry(km, &xfrm_km_list, list) {
+		if (km->migrate) {
+			ret = km->migrate(sel, dir, type, m, num_migrate);
+			if (!ret)
+				err = ret;
+		}
+	}
+	read_unlock(&xfrm_km_lock);
+	return err;
+}
+EXPORT_SYMBOL(km_migrate);
+
 int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr)
 {
 	int err = -EINVAL;
@@ -1458,7 +1629,7 @@
 }
 EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
 
-static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
+struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
 {
 	struct xfrm_state_afinfo *afinfo;
 	if (unlikely(family >= NPROTO))
@@ -1470,11 +1641,14 @@
 	return afinfo;
 }
 
-static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
+void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
 {
 	read_unlock(&xfrm_state_afinfo_lock);
 }
 
+EXPORT_SYMBOL(xfrm_state_get_afinfo);
+EXPORT_SYMBOL(xfrm_state_put_afinfo);
+
 /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
 void xfrm_state_delete_tunnel(struct xfrm_state *x)
 {
@@ -1564,7 +1738,7 @@
 }
 
 EXPORT_SYMBOL(xfrm_init_state);
- 
+
 void __init xfrm_state_init(void)
 {
 	unsigned int sz;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 82f36d3..2567453 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -48,7 +48,7 @@
 
 	algp = RTA_DATA(rt);
 
-	len -= (algp->alg_key_len + 7U) / 8; 
+	len -= (algp->alg_key_len + 7U) / 8;
 	if (len < 0)
 		return -EINVAL;
 
@@ -1107,7 +1107,7 @@
 	uctx->ctx_alg = s->ctx_alg;
 	uctx->ctx_len = s->ctx_len;
 	memcpy(uctx + 1, s->ctx_str, s->ctx_len);
- 	return 0;
+	return 0;
 
  rtattr_failure:
 	return -1;
@@ -1273,10 +1273,6 @@
 		xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete);
 		security_xfrm_policy_free(&tmp);
 	}
-	if (delete)
-		xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
-			       AUDIT_MAC_IPSEC_DELSPD, (xp) ? 1 : 0, xp, NULL);
-
 	if (xp == NULL)
 		return -ENOENT;
 
@@ -1292,8 +1288,14 @@
 					      MSG_DONTWAIT);
 		}
 	} else {
-		if ((err = security_xfrm_policy_delete(xp)) != 0)
+		err = security_xfrm_policy_delete(xp);
+
+		xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+			       AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL);
+
+		if (err != 0)
 			goto out;
+
 		c.data.byid = p->index;
 		c.event = nlh->nlmsg_type;
 		c.seq = nlh->nlmsg_seq;
@@ -1632,6 +1634,176 @@
 	return 0;
 }
 
+#ifdef CONFIG_XFRM_MIGRATE
+static int verify_user_migrate(struct rtattr **xfrma)
+{
+	struct rtattr *rt = xfrma[XFRMA_MIGRATE-1];
+	struct xfrm_user_migrate *um;
+
+	if (!rt)
+		return -EINVAL;
+
+	if ((rt->rta_len - sizeof(*rt)) < sizeof(*um))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int copy_from_user_migrate(struct xfrm_migrate *ma,
+				  struct rtattr **xfrma, int *num)
+{
+	struct rtattr *rt = xfrma[XFRMA_MIGRATE-1];
+	struct xfrm_user_migrate *um;
+	int i, num_migrate;
+
+	um = RTA_DATA(rt);
+	num_migrate = (rt->rta_len - sizeof(*rt)) / sizeof(*um);
+
+	if (num_migrate <= 0 || num_migrate > XFRM_MAX_DEPTH)
+		return -EINVAL;
+
+	for (i = 0; i < num_migrate; i++, um++, ma++) {
+		memcpy(&ma->old_daddr, &um->old_daddr, sizeof(ma->old_daddr));
+		memcpy(&ma->old_saddr, &um->old_saddr, sizeof(ma->old_saddr));
+		memcpy(&ma->new_daddr, &um->new_daddr, sizeof(ma->new_daddr));
+		memcpy(&ma->new_saddr, &um->new_saddr, sizeof(ma->new_saddr));
+
+		ma->proto = um->proto;
+		ma->mode = um->mode;
+		ma->reqid = um->reqid;
+
+		ma->old_family = um->old_family;
+		ma->new_family = um->new_family;
+	}
+
+	*num = i;
+	return 0;
+}
+
+static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
+			   struct rtattr **xfrma)
+{
+	struct xfrm_userpolicy_id *pi = NLMSG_DATA(nlh);
+	struct xfrm_migrate m[XFRM_MAX_DEPTH];
+	u8 type;
+	int err;
+	int n = 0;
+
+	err = verify_user_migrate((struct rtattr **)xfrma);
+	if (err)
+		return err;
+
+	err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
+	if (err)
+		return err;
+
+	err = copy_from_user_migrate((struct xfrm_migrate *)m,
+				     (struct rtattr **)xfrma, &n);
+	if (err)
+		return err;
+
+	if (!n)
+		return 0;
+
+	xfrm_migrate(&pi->sel, pi->dir, type, m, n);
+
+	return 0;
+}
+#else
+static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
+			   struct rtattr **xfrma)
+{
+	return -ENOPROTOOPT;
+}
+#endif
+
+#ifdef CONFIG_XFRM_MIGRATE
+static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb)
+{
+	struct xfrm_user_migrate um;
+
+	memset(&um, 0, sizeof(um));
+	um.proto = m->proto;
+	um.mode = m->mode;
+	um.reqid = m->reqid;
+	um.old_family = m->old_family;
+	memcpy(&um.old_daddr, &m->old_daddr, sizeof(um.old_daddr));
+	memcpy(&um.old_saddr, &m->old_saddr, sizeof(um.old_saddr));
+	um.new_family = m->new_family;
+	memcpy(&um.new_daddr, &m->new_daddr, sizeof(um.new_daddr));
+	memcpy(&um.new_saddr, &m->new_saddr, sizeof(um.new_saddr));
+
+	RTA_PUT(skb, XFRMA_MIGRATE, sizeof(um), &um);
+	return 0;
+
+rtattr_failure:
+	return -1;
+}
+
+static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m,
+			 int num_migrate, struct xfrm_selector *sel,
+			 u8 dir, u8 type)
+{
+	struct xfrm_migrate *mp;
+	struct xfrm_userpolicy_id *pol_id;
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
+	int i;
+
+	nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_MIGRATE, sizeof(*pol_id));
+	pol_id = NLMSG_DATA(nlh);
+	nlh->nlmsg_flags = 0;
+
+	/* copy data from selector, dir, and type to the pol_id */
+	memset(pol_id, 0, sizeof(*pol_id));
+	memcpy(&pol_id->sel, sel, sizeof(pol_id->sel));
+	pol_id->dir = dir;
+
+	if (copy_to_user_policy_type(type, skb) < 0)
+		goto nlmsg_failure;
+
+	for (i = 0, mp = m ; i < num_migrate; i++, mp++) {
+		if (copy_to_user_migrate(mp, skb) < 0)
+			goto nlmsg_failure;
+	}
+
+	nlh->nlmsg_len = skb->tail - b;
+	return skb->len;
+nlmsg_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+			     struct xfrm_migrate *m, int num_migrate)
+{
+	struct sk_buff *skb;
+	size_t len;
+
+	len = RTA_SPACE(sizeof(struct xfrm_user_migrate) * num_migrate);
+	len += NLMSG_SPACE(sizeof(struct xfrm_userpolicy_id));
+#ifdef CONFIG_XFRM_SUB_POLICY
+	len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
+#endif
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	/* build migrate */
+	if (build_migrate(skb, m, num_migrate, sel, dir, type) < 0)
+		BUG();
+
+	NETLINK_CB(skb).dst_group = XFRMNLGRP_MIGRATE;
+	return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE,
+				 GFP_ATOMIC);
+}
+#else
+static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+			     struct xfrm_migrate *m, int num_migrate)
+{
+	return -ENOPROTOOPT;
+}
+#endif
 
 #define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type))
 
@@ -1653,6 +1825,7 @@
 	[XFRM_MSG_NEWAE       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
 	[XFRM_MSG_GETAE       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
 	[XFRM_MSG_REPORT      - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report),
+	[XFRM_MSG_MIGRATE     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),
 };
 
 #undef XMSGSIZE
@@ -1679,6 +1852,7 @@
 	[XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy  },
 	[XFRM_MSG_NEWAE       - XFRM_MSG_BASE] = { .doit = xfrm_new_ae  },
 	[XFRM_MSG_GETAE       - XFRM_MSG_BASE] = { .doit = xfrm_get_ae  },
+	[XFRM_MSG_MIGRATE     - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate    },
 };
 
 static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
@@ -2285,6 +2459,7 @@
 	.compile_policy	= xfrm_compile_policy,
 	.notify_policy	= xfrm_send_policy_notify,
 	.report		= xfrm_send_report,
+	.migrate	= xfrm_send_migrate,
 };
 
 static int __init xfrm_user_init(void)
@@ -2294,7 +2469,7 @@
 	printk(KERN_INFO "Initializing XFRM netlink socket\n");
 
 	nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
-	                             xfrm_netlink_rcv, THIS_MODULE);
+				     xfrm_netlink_rcv, THIS_MODULE);
 	if (nlsk == NULL)
 		return -ENOMEM;
 	rcu_assign_pointer(xfrm_nl, nlsk);
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index a1880e8..06c1a37 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -1,7 +1,7 @@
 ####
 # kbuild: Generic definitions
 
-# Convenient constants
+# Convenient variables
 comma   := ,
 squote  := '
 empty   :=
@@ -56,44 +56,48 @@
 # gcc support functions
 # See documentation in Documentation/kbuild/makefiles.txt
 
-# checker-shell
-# Usage: option = $(call checker-shell,$(CC)...-o $$OUT,option-ok,otherwise)
-# Exit code chooses option. $$OUT is safe location for needless output.
-define checker-shell
-$(shell set -e; \
-  DIR=$(KBUILD_EXTMOD); \
-  cd $${DIR:-$(objtree)}; \
-  OUT=$$PWD/.$$$$.null; \
-  if $(1) >/dev/null 2>&1; \
-    then echo "$(2)"; \
-    else echo "$(3)"; \
-  fi; \
-  rm -f $$OUT)
-endef
+# output directory for tests below
+TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
+
+# try-run
+# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
+# Exit code chooses option. "$$TMP" is can be used as temporary file and
+# is automatically cleaned up.
+try-run = $(shell set -e;		\
+	TMP="$(TMPOUT).$$$$.tmp";	\
+	if ($(1)) >/dev/null 2>&1;	\
+	then echo "$(2)";		\
+	else echo "$(3)";		\
+	fi;				\
+	rm -f "$$TMP")
 
 # as-option
 # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
-as-option = $(call checker-shell,\
-   $(CC) $(CFLAGS) $(1) -c -xassembler /dev/null -o $$OUT,$(1),$(2))
+
+as-option = $(call try-run,\
+	$(CC) $(CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2))
 
 # as-instr
 # Usage: cflags-y += $(call as-instr,instr,option1,option2)
-as-instr = $(call checker-shell,\
-   printf "$(1)" | $(CC) $(AFLAGS) -c -xassembler -o $$OUT -,$(2),$(3))
+
+as-instr = $(call try-run,\
+	echo -e "$(1)" | $(CC) $(AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
 
 # cc-option
 # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
-cc-option = $(call checker-shell,\
-   $(CC) $(CFLAGS) $(if $(3),$(3),$(1)) -S -xc /dev/null -o $$OUT,$(1),$(2))
+
+cc-option = $(call try-run,\
+	$(CC) $(CFLAGS) $(1) -S -xc /dev/null -o "$$TMP",$(1),$(2))
 
 # cc-option-yn
 # Usage: flag := $(call cc-option-yn,-march=winchip-c6)
-cc-option-yn = $(call cc-option,"y","n",$(1))
+cc-option-yn = $(call try-run,\
+	$(CC) $(CFLAGS) $(1) -S -xc /dev/null -o "$$TMP",y,n)
 
 # cc-option-align
 # Prefix align with either -falign or -malign
 cc-option-align = $(subst -functions=0,,\
-   $(call cc-option,-falign-functions=0,-malign-functions=0))
+	$(call cc-option,-falign-functions=0,-malign-functions=0))
 
 # cc-version
 # Usage gcc-ver := $(call cc-version,$(CC))
@@ -105,24 +109,22 @@
 
 # ld-option
 # Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both)
-ld-option = $(call checker-shell,\
-   $(CC) $(1) -nostdlib -xc /dev/null -o $$OUT,$(1),$(2))
+ld-option = $(call try-run,\
+	$(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2))
 
 ######
 
+###
 # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
 # Usage:
 # $(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,
-# add original to the end
-addtree = $(if \
-	$(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
+# 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)))
+flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
 
 # echo command.
 # Short version is used, if $(quiet) equals `quiet_', otherwise full one.
@@ -144,7 +146,7 @@
 # See Documentation/kbuild/makefiles.txt for more info
 
 ifneq ($(KBUILD_NOCMDDEP),1)
-# Check if both arguments has same arguments. Result is empty string, if equal.
+# Check if both arguments has same arguments. Result is empty string if equal.
 # User may override this check using make KBUILD_NOCMDDEP=1
 arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
                     $(filter-out $(cmd_$@),   $(cmd_$(1))) )
@@ -168,7 +170,6 @@
 	echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
 
 # Execute the command and also postprocess generated .d dependencies file.
-#
 if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ),                  \
 	@set -e;                                                             \
 	$(echo-cmd) $(cmd_$(1));                                             \
@@ -176,10 +177,9 @@
 	rm -f $(depfile);                                                    \
 	mv -f $(dot-target).tmp $(dot-target).cmd)
 
-# Will check if $(cmd_foo) changed, or any of the prerequisites changed,
-# and if so will execute $(rule_foo).
 # Usage: $(call if_changed_rule,foo)
-#
+# Will check if $(cmd_foo) or any of the prerequisites changed,
+# and if so will execute $(rule_foo).
 if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ),                 \
 	@set -e;                                                             \
 	$(rule_$(1)))
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index c0ae0a7..512c2f5 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -89,6 +89,7 @@
 {
 	Parent::okRename(col);
 	sym_set_string_value(menu->sym, text(dataColIdx).latin1());
+	listView()->updateList(this);
 }
 #endif
 
@@ -605,6 +606,8 @@
 
 		visible = menu_is_visible(child);
 		if (showAll || visible) {
+			if (!child->sym && !child->list && !child->prompt)
+				continue;
 			if (!item || item->menu != child)
 				item = new ConfigItem(parent, last, child, visible);
 			else
@@ -1247,6 +1250,7 @@
 
 	free(result);
 	list->list->clear();
+	info->clear();
 
 	result = sym_re_search(editField->text().latin1());
 	if (!result)
@@ -1316,7 +1320,7 @@
 	conf_changed();
 	QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
 	  connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
-	QAction *searchAction = new QAction("Search", "&Search", CTRL+Key_F, this);
+	QAction *searchAction = new QAction("Find", "&Find", CTRL+Key_F, this);
 	  connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
 	QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
 	  connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
@@ -1373,10 +1377,13 @@
 	saveAction->addTo(config);
 	saveAsAction->addTo(config);
 	config->insertSeparator();
-	searchAction->addTo(config);
-	config->insertSeparator();
 	quitAction->addTo(config);
 
+	// create edit menu
+	QPopupMenu* editMenu = new QPopupMenu(this);
+	menu->insertItem("&Edit", editMenu);
+	searchAction->addTo(editMenu);
+
 	// create options menu
 	QPopupMenu* optionMenu = new QPopupMenu(this);
 	menu->insertItem("&Option", optionMenu);
@@ -1467,7 +1474,10 @@
 void ConfigMainWindow::changeMenu(struct menu *menu)
 {
 	configList->setRootMenu(menu);
-	backAction->setEnabled(TRUE);
+	if (configList->rootEntry->parent == &rootmenu)
+		backAction->setEnabled(FALSE);
+	else
+		backAction->setEnabled(TRUE);
 }
 
 void ConfigMainWindow::setMenuLink(struct menu *menu)
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index f50a70f..fb43c64 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -83,7 +83,7 @@
 #  * my_function
 #  **/
 #
-# If the Description: header tag is ommitted, then there must be a blank line
+# If the Description: header tag is omitted, then there must be a blank line
 # after the last parameter specification.
 # e.g.
 # /**
@@ -265,7 +265,7 @@
 my $doc_end = '\*/';
 my $doc_com = '\s*\*\s*';
 my $doc_decl = $doc_com.'(\w+)';
-my $doc_sect = $doc_com.'(['.$doc_special.']?[\w ]+):(.*)';
+my $doc_sect = $doc_com.'(['.$doc_special.']?[\w\s]+):(.*)';
 my $doc_content = $doc_com.'(.*)';
 my $doc_block = $doc_com.'DOC:\s*(.*)?';
 
@@ -365,7 +365,7 @@
 #  parameterlist => @list of parameters
 #  parameterdescs => %parameter descriptions
 #  sectionlist => @list of sections
-#  sections => %descriont descriptions
+#  sections => %section descriptions
 #
 
 sub output_highlight {
@@ -452,7 +452,7 @@
     my %args = %{$_[0]};
     my ($parameter);
 
-    print "<h2>".$args{'type'}." ".$args{'struct'}."</h2>\n";
+    print "<h2>".$args{'type'}." ".$args{'struct'}. " - " .$args{'purpose'}."</h2>\n";
     print "<b>".$args{'type'}." ".$args{'struct'}."</b> {<br>\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
 	if ($parameter =~ /^#/) {
@@ -498,8 +498,8 @@
     my %args = %{$_[0]};
     my ($parameter, $section);
     my $count;
-    print "<h2>Function</h2>\n";
 
+    print "<h2>" .$args{'function'}." - ".$args{'purpose'}."</h2>\n";
     print "<i>".$args{'functiontype'}."</i>\n";
     print "<b>".$args{'function'}."</b>\n";
     print "(";
@@ -583,14 +583,14 @@
     $id = "API-".$args{'function'};
     $id =~ s/[^A-Za-z0-9]/-/g;
 
-    print "<refentry>\n";
+    print "<refentry id=\"$id\">\n";
     print "<refentryinfo>\n";
     print " <title>LINUX</title>\n";
     print " <productname>Kernel Hackers Manual</productname>\n";
     print " <date>$man_date</date>\n";
     print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print " <refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase>".$args{'function'}."</phrase></refentrytitle>\n";
     print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
@@ -659,14 +659,14 @@
     $id = "API-struct-".$args{'struct'};
     $id =~ s/[^A-Za-z0-9]/-/g;
 
-    print "<refentry>\n";
+    print "<refentry id=\"$id\">\n";
     print "<refentryinfo>\n";
     print " <title>LINUX</title>\n";
     print " <productname>Kernel Hackers Manual</productname>\n";
     print " <date>$man_date</date>\n";
     print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print " <refentrytitle><phrase id=\"$id\">".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase>".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
     print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
@@ -743,14 +743,14 @@
     $id = "API-enum-".$args{'enum'};
     $id =~ s/[^A-Za-z0-9]/-/g;
 
-    print "<refentry>\n";
+    print "<refentry id=\"$id\">\n";
     print "<refentryinfo>\n";
     print " <title>LINUX</title>\n";
     print " <productname>Kernel Hackers Manual</productname>\n";
     print " <date>$man_date</date>\n";
     print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print " <refentrytitle><phrase id=\"$id\">enum ".$args{'enum'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase>enum ".$args{'enum'}."</phrase></refentrytitle>\n";
     print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
@@ -809,14 +809,14 @@
     $id = "API-typedef-".$args{'typedef'};
     $id =~ s/[^A-Za-z0-9]/-/g;
 
-    print "<refentry>\n";
+    print "<refentry id=\"$id\">\n";
     print "<refentryinfo>\n";
     print " <title>LINUX</title>\n";
     print " <productname>Kernel Hackers Manual</productname>\n";
     print " <date>$man_date</date>\n";
     print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print " <refentrytitle><phrase id=\"$id\">typedef ".$args{'typedef'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase>typedef ".$args{'typedef'}."</phrase></refentrytitle>\n";
     print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
@@ -953,7 +953,11 @@
     print $args{'function'}." \\- ".$args{'purpose'}."\n";
 
     print ".SH SYNOPSIS\n";
-    print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n";
+    if ($args{'functiontype'} ne "") {
+	print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n";
+    } else {
+	print ".B \"".$args{'function'}."\n";
+    }
     $count = 0;
     my $parenth = "(";
     my $post = ",";
@@ -1118,13 +1122,19 @@
 sub output_function_text(%) {
     my %args = %{$_[0]};
     my ($parameter, $section);
+    my $start;
 
     print "Name:\n\n";
     print $args{'function'}." - ".$args{'purpose'}."\n";
 
     print "\nSynopsis:\n\n";
-    my $start=$args{'functiontype'}." ".$args{'function'}." (";
+    if ($args{'functiontype'} ne "") {
+	$start = $args{'functiontype'}." ".$args{'function'}." (";
+    } else {
+	$start = $args{'function'}." (";
+    }
     print $start;
+
     my $count = 0;
     foreach my $parameter (@{$args{'parameterlist'}}) {
 	$type = $args{'parametertypes'}{$parameter};
@@ -1433,7 +1443,7 @@
 	} elsif ($arg =~ m/\(.*\*/) {
 	    # pointer-to-function
 	    $arg =~ tr/#/,/;
-	    $arg =~ m/[^\(]+\(\*([^\)]+)\)/;
+	    $arg =~ m/[^\(]+\(\*\s*([^\)]+)\)/;
 	    $param = $1;
 	    $type = $arg;
 	    $type =~ s/([^\(]+\(\*)$param/$1/;
@@ -1536,7 +1546,7 @@
     $prototype =~ s/^__always_inline +//;
     $prototype =~ s/^noinline +//;
     $prototype =~ s/__devinit +//;
-    $prototype =~ s/^#define +//; #ak added
+    $prototype =~ s/^#define\s+//; #ak added
     $prototype =~ s/__attribute__ \(\([a-z,]*\)\)//;
 
     # Yes, this truly is vile.  We are looking for:
@@ -1570,7 +1580,8 @@
 	$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
 	$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
 	$prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
-	$prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
+	$prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+	$prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
 	$return_type = $1;
 	$declaration_name = $2;
 	my $args = $3;
@@ -1710,6 +1721,7 @@
     my $file;
     my $identifier;
     my $func;
+    my $descr;
     my $initial_section_counter = $section_counter;
 
     if (defined($ENV{'SRCTREE'})) {
@@ -1753,7 +1765,12 @@
 
 		$state = 2;
 		if (/-(.*)/) {
-		    $declaration_purpose = xml_escape($1);
+		    # strip leading/trailing/multiple spaces #RDD:T:
+		    $descr= $1;
+		    $descr =~ s/^\s*//;
+		    $descr =~ s/\s*$//;
+		    $descr =~ s/\s+/ /;
+		    $declaration_purpose = xml_escape($descr);
 		} else {
 		    $declaration_purpose = "";
 		}
diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h
index d7b8a38..82d0af4 100755
--- a/scripts/mkcompile_h
+++ b/scripts/mkcompile_h
@@ -58,7 +58,7 @@
     echo \#define LINUX_COMPILE_DOMAIN
   fi
 
-  echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | tail -n 1`\"
+  echo \#define LINUX_COMPILER \"`LC_ALL=C LANG=C $CC -v 2>&1 | tail -n 1`\"
 ) > .tmpcompile
 
 # Only replace the real compile.h if the new one is different,
diff --git a/scripts/mkuboot.sh b/scripts/mkuboot.sh
index 52a17ab..4b06c5e 100755
--- a/scripts/mkuboot.sh
+++ b/scripts/mkuboot.sh
@@ -4,12 +4,15 @@
 # Build U-Boot image when `mkimage' tool is available.
 #
 
-MKIMAGE=$(type -path mkimage)
+MKIMAGE=$(type -path ${CROSS_COMPILE}mkimage)
 
 if [ -z "${MKIMAGE}" ]; then
-	# Doesn't exist
-	echo '"mkimage" command not found - U-Boot images will not be built' >&2
-	exit 0;
+	MKIMAGE=$(type -path mkimage)
+	if [ -z "${MKIMAGE}" ]; then
+		# Doesn't exist
+		echo '"mkimage" command not found - U-Boot images will not be built' >&2
+		exit 0;
+	fi
 fi
 
 # Call "mkimage" to create U-Boot image
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 2aa4762..c4b5398 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -641,12 +641,20 @@
 	if (f1 && f2)
 		return 1;
 
-	/* Whitelist all references from .pci_fixup section if vmlinux */
+	/* Whitelist all references from .pci_fixup section if vmlinux
+	 * Whitelist all refereces from .text.head to .init.data if vmlinux
+	 * Whitelist all refereces from .text.head to .init.text if vmlinux
+	 */
 	if (is_vmlinux(modname)) {
 		if ((strcmp(fromsec, ".pci_fixup") == 0) &&
 		    (strcmp(tosec, ".init.text") == 0))
 		return 1;
 
+		if ((strcmp(fromsec, ".text.head") == 0) &&
+			((strcmp(tosec, ".init.data") == 0) ||
+			(strcmp(tosec, ".init.text") == 0)))
+		return 1;
+
 		/* Check for pattern 3 */
 		for (s = pat3refsym; *s; s++)
 			if (strcmp(refsymname, *s) == 0)
@@ -678,6 +686,30 @@
 	return NULL;
 }
 
+static inline int is_arm_mapping_symbol(const char *str)
+{
+	return str[0] == '$' && strchr("atd", str[1])
+	       && (str[2] == '\0' || str[2] == '.');
+}
+
+/*
+ * If there's no name there, ignore it; likewise, ignore it if it's
+ * one of the magic symbols emitted used by current ARM tools.
+ *
+ * Otherwise if find_symbols_between() returns those symbols, they'll
+ * fail the whitelist tests and cause lots of false alarms ... fixable
+ * only by merging __exit and __init sections into __text, bloating
+ * the kernel (which is especially evil on embedded platforms).
+ */
+static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
+{
+	const char *name = elf->strtab + sym->st_name;
+
+	if (!name || !strlen(name))
+		return 0;
+	return !is_arm_mapping_symbol(name);
+}
+
 /*
  * Find symbols before or equal addr and after addr - in the section sec.
  * If we find two symbols with equal offset prefer one with a valid name.
@@ -706,16 +738,15 @@
 		symsec = secstrings + elf->sechdrs[sym->st_shndx].sh_name;
 		if (strcmp(symsec, sec) != 0)
 			continue;
+		if (!is_valid_name(elf, sym))
+			continue;
 		if (sym->st_value <= addr) {
 			if ((addr - sym->st_value) < beforediff) {
 				beforediff = addr - sym->st_value;
 				*before = sym;
 			}
 			else if ((addr - sym->st_value) == beforediff) {
-				/* equal offset, valid name? */
-				const char *name = elf->strtab + sym->st_name;
-				if (name && strlen(name))
-					*before = sym;
+				*before = sym;
 			}
 		}
 		else
@@ -725,10 +756,7 @@
 				*after = sym;
 			}
 			else if ((sym->st_value - addr) == afterdiff) {
-				/* equal offset, valid name? */
-				const char *name = elf->strtab + sym->st_name;
-				if (name && strlen(name))
-					*after = sym;
+				*after = sym;
 			}
 		}
 	}
diff --git a/security/inode.c b/security/inode.c
index 9b16e14..d7ecf89 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -50,7 +50,7 @@
 	return 0;
 }
 
-static struct file_operations default_file_ops = {
+static const struct file_operations default_file_ops = {
 	.read =		default_read_file,
 	.write =	default_write_file,
 	.open =		default_open,
@@ -215,7 +215,7 @@
  */
 struct dentry *securityfs_create_file(const char *name, mode_t mode,
 				   struct dentry *parent, void *data,
-				   struct file_operations *fops)
+				   const struct file_operations *fops)
 {
 	struct dentry *dentry = NULL;
 	int error;
diff --git a/security/keys/compat.c b/security/keys/compat.c
index bcdb285..e10ec99 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/sched.h>
 #include <linux/syscalls.h>
 #include <linux/keyctl.h>
 #include <linux/compat.h>
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 686a9ee..3e0d0a6 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -33,7 +33,7 @@
 	.show	= proc_keys_show,
 };
 
-static struct file_operations proc_keys_fops = {
+static const struct file_operations proc_keys_fops = {
 	.open		= proc_keys_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -54,7 +54,7 @@
 	.show	= proc_key_users_show,
 };
 
-static struct file_operations proc_key_users_fops = {
+static const struct file_operations proc_key_users_fops = {
 	.open		= proc_key_users_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 5bbfdeb..7c687d5 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
diff --git a/security/security.c b/security/security.c
index ee4e070..fc8601b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/security.h>
 
 #define SECURITY_FRAMEWORK_VERSION	"1.0.0"
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index e7c0b5e..da8caf1 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -332,11 +332,10 @@
 {
 	struct avc_node *node;
 
-	node = kmem_cache_alloc(avc_node_cachep, GFP_ATOMIC);
+	node = kmem_cache_zalloc(avc_node_cachep, GFP_ATOMIC);
 	if (!node)
 		goto out;
 
-	memset(node, 0, sizeof(*node));
 	INIT_RCU_HEAD(&node->rhead);
 	INIT_LIST_HEAD(&node->list);
 	atomic_set(&node->ae.used, 1);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 65fb5e8..b1ac22d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -181,11 +181,10 @@
 	struct task_security_struct *tsec = current->security;
 	struct inode_security_struct *isec;
 
-	isec = kmem_cache_alloc(sel_inode_cache, GFP_KERNEL);
+	isec = kmem_cache_zalloc(sel_inode_cache, GFP_KERNEL);
 	if (!isec)
 		return -ENOMEM;
 
-	memset(isec, 0, sizeof(*isec));
 	mutex_init(&isec->lock);
 	INIT_LIST_HEAD(&isec->list);
 	isec->inode = inode;
@@ -1078,6 +1077,9 @@
 	struct inode_security_struct *isec;
 	struct avc_audit_data ad;
 
+	if (unlikely (IS_PRIVATE (inode)))
+		return 0;
+
 	tsec = tsk->security;
 	isec = inode->i_security;
 
@@ -1424,6 +1426,47 @@
 	return task_has_capability(tsk,cap);
 }
 
+static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
+{
+	int buflen, rc;
+	char *buffer, *path, *end;
+
+	rc = -ENOMEM;
+	buffer = (char*)__get_free_page(GFP_KERNEL);
+	if (!buffer)
+		goto out;
+
+	buflen = PAGE_SIZE;
+	end = buffer+buflen;
+	*--end = '\0';
+	buflen--;
+	path = end-1;
+	*path = '/';
+	while (table) {
+		const char *name = table->procname;
+		size_t namelen = strlen(name);
+		buflen -= namelen + 1;
+		if (buflen < 0)
+			goto out_free;
+		end -= namelen;
+		memcpy(end, name, namelen);
+		*--end = '/';
+		path = end;
+		table = table->parent;
+	}
+	buflen -= 4;
+	if (buflen < 0)
+		goto out_free;
+	end -= 4;
+	memcpy(end, "/sys", 4);
+	path = end;
+	rc = security_genfs_sid("proc", path, tclass, sid);
+out_free:
+	free_page((unsigned long)buffer);
+out:
+	return rc;
+}
+
 static int selinux_sysctl(ctl_table *table, int op)
 {
 	int error = 0;
@@ -1438,8 +1481,8 @@
 
 	tsec = current->security;
 
-	rc = selinux_proc_get_sid(table->de, (op == 001) ?
-	                          SECCLASS_DIR : SECCLASS_FILE, &tsid);
+	rc = selinux_sysctl_get_sid(table, (op == 0001) ?
+				    SECCLASS_DIR : SECCLASS_FILE, &tsid);
 	if (rc) {
 		/* Default to the well-defined sysctl SID. */
 		tsid = SECINITSID_SYSCTL;
@@ -2655,7 +2698,7 @@
 	struct file_security_struct *fsec;
 
 	/* struct fown_struct is never outside the context of a struct file */
-        file = (struct file *)((long)fown - offsetof(struct file,f_owner));
+        file = container_of(fown, struct file, f_owner);
 
 	tsec = tsk->security;
 	fsec = file->f_security;
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index c8bf6e1..93b3177 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -161,7 +161,7 @@
 #define sel_write_enforce NULL
 #endif
 
-static struct file_operations sel_enforce_ops = {
+static const struct file_operations sel_enforce_ops = {
 	.read		= sel_read_enforce,
 	.write		= sel_write_enforce,
 };
@@ -211,7 +211,7 @@
 #define sel_write_disable NULL
 #endif
 
-static struct file_operations sel_disable_ops = {
+static const struct file_operations sel_disable_ops = {
 	.write		= sel_write_disable,
 };
 
@@ -225,7 +225,7 @@
 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
-static struct file_operations sel_policyvers_ops = {
+static const struct file_operations sel_policyvers_ops = {
 	.read		= sel_read_policyvers,
 };
 
@@ -242,7 +242,7 @@
 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
-static struct file_operations sel_mls_ops = {
+static const struct file_operations sel_mls_ops = {
 	.read		= sel_read_mls,
 };
 
@@ -294,7 +294,7 @@
 	return length;
 }
 
-static struct file_operations sel_load_ops = {
+static const struct file_operations sel_load_ops = {
 	.write		= sel_write_load,
 };
 
@@ -374,7 +374,7 @@
 	free_page((unsigned long) page);
 	return length;
 }
-static struct file_operations sel_checkreqprot_ops = {
+static const struct file_operations sel_checkreqprot_ops = {
 	.read		= sel_read_checkreqprot,
 	.write		= sel_write_checkreqprot,
 };
@@ -423,7 +423,7 @@
 	free_page((unsigned long) page);
 	return length;
 }
-static struct file_operations sel_compat_net_ops = {
+static const struct file_operations sel_compat_net_ops = {
 	.read		= sel_read_compat_net,
 	.write		= sel_write_compat_net,
 };
@@ -467,7 +467,7 @@
 	return rv;
 }
 
-static struct file_operations transaction_ops = {
+static const struct file_operations transaction_ops = {
 	.write		= selinux_transaction_write,
 	.read		= simple_transaction_read,
 	.release	= simple_transaction_release,
@@ -875,7 +875,7 @@
 	return length;
 }
 
-static struct file_operations sel_bool_ops = {
+static const struct file_operations sel_bool_ops = {
 	.read           = sel_read_bool,
 	.write          = sel_write_bool,
 };
@@ -932,7 +932,7 @@
 	return length;
 }
 
-static struct file_operations sel_commit_bools_ops = {
+static const struct file_operations sel_commit_bools_ops = {
 	.write          = sel_commit_bools_write,
 };
 
@@ -1131,12 +1131,12 @@
 	return ret;
 }
 
-static struct file_operations sel_avc_cache_threshold_ops = {
+static const struct file_operations sel_avc_cache_threshold_ops = {
 	.read		= sel_read_avc_cache_threshold,
 	.write		= sel_write_avc_cache_threshold,
 };
 
-static struct file_operations sel_avc_hash_stats_ops = {
+static const struct file_operations sel_avc_hash_stats_ops = {
 	.read		= sel_read_avc_hash_stats,
 };
 
@@ -1198,7 +1198,7 @@
 	return seq_open(file, &sel_avc_cache_stats_seq_ops);
 }
 
-static struct file_operations sel_avc_cache_stats_ops = {
+static const struct file_operations sel_avc_cache_stats_ops = {
 	.open		= sel_open_avc_cache_stats,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index ebb993c..9142073 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -36,10 +36,9 @@
 		  struct avtab_key *key, struct avtab_datum *datum)
 {
 	struct avtab_node * newnode;
-	newnode = kmem_cache_alloc(avtab_node_cachep, GFP_KERNEL);
+	newnode = kmem_cache_zalloc(avtab_node_cachep, GFP_KERNEL);
 	if (newnode == NULL)
 		return NULL;
-	memset(newnode, 0, sizeof(struct avtab_node));
 	newnode->key = *key;
 	newnode->datum = *datum;
 	if (prev) {
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index 871c33b..d78f9ff 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -7,7 +7,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include "flask.h"
 #include "security.h"
 #include "sidtab.h"
diff --git a/sound/Kconfig b/sound/Kconfig
index 9d77300..97532bb 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -76,6 +76,8 @@
 
 source "sound/parisc/Kconfig"
 
+source "sound/soc/Kconfig"
+
 endmenu
 
 menu "Open Sound System"
diff --git a/sound/Makefile b/sound/Makefile
index 9aee54c..b7c7fb7 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -5,7 +5,7 @@
 obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o
 obj-$(CONFIG_SOUND_PRIME) += oss/
 obj-$(CONFIG_DMASOUND) += oss/
-obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/
+obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ soc/
 obj-$(CONFIG_SND_AOA) += aoa/
 
 # This one must be compilable even if sound is configured out
diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c
index 66de2c2..7fa37e1 100644
--- a/sound/ac97_bus.c
+++ b/sound/ac97_bus.c
@@ -26,6 +26,7 @@
 	return 1;
 }
 
+#ifdef CONFIG_PM
 static int ac97_bus_suspend(struct device *dev, pm_message_t state)
 {
 	int ret = 0;
@@ -45,12 +46,15 @@
 
 	return ret;
 }
+#endif /* CONFIG_PM */
 
 struct bus_type ac97_bus_type = {
 	.name		= "ac97",
 	.match		= ac97_bus_match,
+#ifdef CONFIG_PM
 	.suspend	= ac97_bus_suspend,
 	.resume		= ac97_bus_resume,
+#endif /* CONFIG_PM */
 };
 
 static int __init ac97_bus_init(void)
diff --git a/sound/aoa/aoa.h b/sound/aoa/aoa.h
index 378ef1e..541b908 100644
--- a/sound/aoa/aoa.h
+++ b/sound/aoa/aoa.h
@@ -99,7 +99,7 @@
  * that are not assigned yet are passed to the fabric
  * again for reconsideration. */
 extern int
-aoa_fabric_register(struct aoa_fabric *fabric);
+aoa_fabric_register(struct aoa_fabric *fabric, struct device *dev);
 
 /* it is vital to call this when the fabric exits!
  * When calling, the remove_codec will be called
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c
index 0b76507..b00fc48 100644
--- a/sound/aoa/codecs/snd-aoa-codec-onyx.c
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c
@@ -825,7 +825,16 @@
 	int err = -ENXIO;
 
 	mutex_lock(&onyx->mutex);
-	/* take codec out of suspend */
+
+	/* reset codec */
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
+	msleep(1);
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
+	msleep(1);
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
+	msleep(1);
+
+	/* take codec out of suspend (if it still is after reset) */
 	if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
 		goto out_unlock;
 	onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV));
diff --git a/sound/aoa/core/snd-aoa-alsa.c b/sound/aoa/core/snd-aoa-alsa.c
index b42fdea..17fe689 100644
--- a/sound/aoa/core/snd-aoa-alsa.c
+++ b/sound/aoa/core/snd-aoa-alsa.c
@@ -14,7 +14,7 @@
 
 static struct aoa_card *aoa_card;
 
-int aoa_alsa_init(char *name, struct module *mod)
+int aoa_alsa_init(char *name, struct module *mod, struct device *dev)
 {
 	struct snd_card *alsa_card;
 	int err;
@@ -28,6 +28,7 @@
 		return -ENOMEM;
 	aoa_card = alsa_card->private_data;
 	aoa_card->alsa_card = alsa_card;
+	alsa_card->dev = dev;
 	strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
 	strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
 	strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname));
@@ -59,7 +60,7 @@
 }
 
 int aoa_snd_device_new(snd_device_type_t type,
-        void * device_data, struct snd_device_ops * ops)
+		       void * device_data, struct snd_device_ops * ops)
 {
 	struct snd_card *card = aoa_get_card();
 	int err;
diff --git a/sound/aoa/core/snd-aoa-alsa.h b/sound/aoa/core/snd-aoa-alsa.h
index 660d2f1..9669e44 100644
--- a/sound/aoa/core/snd-aoa-alsa.h
+++ b/sound/aoa/core/snd-aoa-alsa.h
@@ -10,7 +10,7 @@
 #define __SND_AOA_ALSA_H
 #include "../aoa.h"
 
-extern int aoa_alsa_init(char *name, struct module *mod);
+extern int aoa_alsa_init(char *name, struct module *mod, struct device *dev);
 extern void aoa_alsa_cleanup(void);
 
 #endif /* __SND_AOA_ALSA_H */
diff --git a/sound/aoa/core/snd-aoa-core.c b/sound/aoa/core/snd-aoa-core.c
index ecd2d82..19fdae4 100644
--- a/sound/aoa/core/snd-aoa-core.c
+++ b/sound/aoa/core/snd-aoa-core.c
@@ -82,7 +82,7 @@
 }
 EXPORT_SYMBOL_GPL(aoa_codec_unregister);
 
-int aoa_fabric_register(struct aoa_fabric *new_fabric)
+int aoa_fabric_register(struct aoa_fabric *new_fabric, struct device *dev)
 {
 	struct aoa_codec *c;
 	int err;
@@ -98,7 +98,7 @@
 	if (!new_fabric)
 		return -EINVAL;
 
-	err = aoa_alsa_init(new_fabric->name, new_fabric->owner);
+	err = aoa_alsa_init(new_fabric->name, new_fabric->owner, dev);
 	if (err)
 		return err;
 
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
index 172eb95..1b94ba6 100644
--- a/sound/aoa/fabrics/snd-aoa-fabric-layout.c
+++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
@@ -1014,7 +1014,7 @@
 
 	ldev->gpio.methods->init(&ldev->gpio);
 
-	err = aoa_fabric_register(&layout_fabric);
+	err = aoa_fabric_register(&layout_fabric, &sdev->ofdev.dev);
 	if (err && err != -EALREADY) {
 		printk(KERN_INFO "snd-aoa-fabric-layout: can't use,"
 				 " another fabric is active!\n");
@@ -1034,9 +1034,9 @@
 	list_del(&ldev->list);
 	layouts_list_items--;
  outnodev:
- 	if (sound) of_node_put(sound);
+ 	of_node_put(sound);
  	layout_device = NULL;
- 	if (ldev) kfree(ldev);
+ 	kfree(ldev);
 	return -ENODEV;
 }
 
@@ -1077,8 +1077,6 @@
 {
 	struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
 
-	printk("aoa_fabric_layout_suspend()\n");
-
 	if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
 		ldev->gpio.methods->all_amps_off(&ldev->gpio);
 
@@ -1089,8 +1087,6 @@
 {
 	struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
 
-	printk("aoa_fabric_layout_resume()\n");
-
 	if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
 		ldev->gpio.methods->all_amps_restore(&ldev->gpio);
 
@@ -1107,6 +1103,9 @@
 	.suspend = aoa_fabric_layout_suspend,
 	.resume = aoa_fabric_layout_resume,
 #endif
+	.driver = {
+		.owner = THIS_MODULE,
+	}
 };
 
 static int __init aoa_fabric_layout_init(void)
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
index e593a13..e36f6aa 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-core.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
@@ -41,8 +41,8 @@
 				       struct dbdma_command_mem *r,
 				       int numcmds)
 {
-	/* one more for rounding */
-	r->size = (numcmds+1) * sizeof(struct dbdma_cmd);
+	/* one more for rounding, one for branch back, one for stop command */
+	r->size = (numcmds + 3) * sizeof(struct dbdma_cmd);
 	/* We use the PCI APIs for now until the generic one gets fixed
 	 * enough or until we get some macio-specific versions
 	 */
@@ -377,11 +377,8 @@
 		if (i2sdev->sound.pcm) {
 			/* Suspend PCM streams */
 			snd_pcm_suspend_all(i2sdev->sound.pcm);
-			/* Probably useless as we handle
-			 * power transitions ourselves */
-			snd_power_change_state(i2sdev->sound.pcm->card,
-					       SNDRV_CTL_POWER_D3hot);
 		}
+
 		/* Notify codecs */
 		list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
 			err = 0;
@@ -390,7 +387,11 @@
 			if (err)
 				ret = err;
 		}
+
+		/* wait until streams are stopped */
+		i2sbus_wait_for_stop_both(i2sdev);
 	}
+
 	return ret;
 }
 
@@ -402,6 +403,9 @@
 	int err, ret = 0;
 
 	list_for_each_entry(i2sdev, &control->list, item) {
+		/* reset i2s bus format etc. */
+		i2sbus_pcm_prepare_both(i2sdev);
+
 		/* Notify codecs so they can re-initialize */
 		list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
 			err = 0;
@@ -410,12 +414,6 @@
 			if (err)
 				ret = err;
 		}
-		/* Notify Alsa */
-		if (i2sdev->sound.pcm) {
-			/* Same comment as above, probably useless */
-			snd_power_change_state(i2sdev->sound.pcm->card,
-					       SNDRV_CTL_POWER_D0);
-		}
 	}
 
 	return ret;
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
index 5eff30b..c6b42f9 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
@@ -125,7 +125,8 @@
 	}
 	/* bus dependent stuff */
 	hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-		   SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME;
+		   SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME |
+		   SNDRV_PCM_INFO_JOINT_DUPLEX;
 
 	CHECK_RATE(5512);
 	CHECK_RATE(8000);
@@ -245,18 +246,78 @@
 	return err;
 }
 
+static void i2sbus_wait_for_stop(struct i2sbus_dev *i2sdev,
+				 struct pcm_info *pi)
+{
+	unsigned long flags;
+	struct completion done;
+	long timeout;
+
+	spin_lock_irqsave(&i2sdev->low_lock, flags);
+	if (pi->dbdma_ring.stopping) {
+		init_completion(&done);
+		pi->stop_completion = &done;
+		spin_unlock_irqrestore(&i2sdev->low_lock, flags);
+		timeout = wait_for_completion_timeout(&done, HZ);
+		spin_lock_irqsave(&i2sdev->low_lock, flags);
+		pi->stop_completion = NULL;
+		if (timeout == 0) {
+			/* timeout expired, stop dbdma forcefully */
+			printk(KERN_ERR "i2sbus_wait_for_stop: timed out\n");
+			/* make sure RUN, PAUSE and S0 bits are cleared */
+			out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
+			pi->dbdma_ring.stopping = 0;
+			timeout = 10;
+			while (in_le32(&pi->dbdma->status) & ACTIVE) {
+				if (--timeout <= 0)
+					break;
+				udelay(1);
+			}
+		}
+	}
+	spin_unlock_irqrestore(&i2sdev->low_lock, flags);
+}
+
+#ifdef CONFIG_PM
+void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev)
+{
+	struct pcm_info *pi;
+
+	get_pcm_info(i2sdev, 0, &pi, NULL);
+	i2sbus_wait_for_stop(i2sdev, pi);
+	get_pcm_info(i2sdev, 1, &pi, NULL);
+	i2sbus_wait_for_stop(i2sdev, pi);
+}
+#endif
+
 static int i2sbus_hw_params(struct snd_pcm_substream *substream,
 			    struct snd_pcm_hw_params *params)
 {
 	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
 }
 
-static int i2sbus_hw_free(struct snd_pcm_substream *substream)
+static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
 {
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+	struct pcm_info *pi;
+
+	get_pcm_info(i2sdev, in, &pi, NULL);
+	if (pi->dbdma_ring.stopping)
+		i2sbus_wait_for_stop(i2sdev, pi);
 	snd_pcm_lib_free_pages(substream);
 	return 0;
 }
 
+static int i2sbus_playback_hw_free(struct snd_pcm_substream *substream)
+{
+	return i2sbus_hw_free(substream, 0);
+}
+
+static int i2sbus_record_hw_free(struct snd_pcm_substream *substream)
+{
+	return i2sbus_hw_free(substream, 1);
+}
+
 static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
 {
 	/* whee. Hard work now. The user has selected a bitrate
@@ -264,7 +325,7 @@
 	 * I2S controller appropriately. */
 	struct snd_pcm_runtime *runtime;
 	struct dbdma_cmd *command;
-	int i, periodsize;
+	int i, periodsize, nperiods;
 	dma_addr_t offset;
 	struct bus_info bi;
 	struct codec_info_item *cii;
@@ -274,6 +335,7 @@
 	struct pcm_info *pi, *other;
 	int cnt;
 	int result = 0;
+	unsigned int cmd, stopaddr;
 
 	mutex_lock(&i2sdev->lock);
 
@@ -283,6 +345,13 @@
 		result = -EBUSY;
 		goto out_unlock;
 	}
+	if (pi->dbdma_ring.stopping)
+		i2sbus_wait_for_stop(i2sdev, pi);
+
+	if (!pi->substream || !pi->substream->runtime) {
+		result = -EINVAL;
+		goto out_unlock;
+	}
 
 	runtime = pi->substream->runtime;
 	pi->active = 1;
@@ -297,24 +366,43 @@
 	i2sdev->rate = runtime->rate;
 
 	periodsize = snd_pcm_lib_period_bytes(pi->substream);
+	nperiods = pi->substream->runtime->periods;
 	pi->current_period = 0;
 
 	/* generate dbdma command ring first */
 	command = pi->dbdma_ring.cmds;
+	memset(command, 0, (nperiods + 2) * sizeof(struct dbdma_cmd));
+
+	/* commands to DMA to/from the ring */
+	/*
+	 * For input, we need to do a graceful stop; if we abort
+	 * the DMA, we end up with leftover bytes that corrupt
+	 * the next recording.  To do this we set the S0 status
+	 * bit and wait for the DMA controller to stop.  Each
+	 * command has a branch condition to
+	 * make it branch to a stop command if S0 is set.
+	 * On input we also need to wait for the S7 bit to be
+	 * set before turning off the DMA controller.
+	 * In fact we do the graceful stop for output as well.
+	 */
 	offset = runtime->dma_addr;
-	for (i = 0; i < pi->substream->runtime->periods;
-	     i++, command++, offset += periodsize) {
-		memset(command, 0, sizeof(struct dbdma_cmd));
-		command->command =
-		    cpu_to_le16((in ? INPUT_MORE : OUTPUT_MORE) | INTR_ALWAYS);
+	cmd = (in? INPUT_MORE: OUTPUT_MORE) | BR_IFSET | INTR_ALWAYS;
+	stopaddr = pi->dbdma_ring.bus_cmd_start +
+		(nperiods + 1) * sizeof(struct dbdma_cmd);
+	for (i = 0; i < nperiods; i++, command++, offset += periodsize) {
+		command->command = cpu_to_le16(cmd);
+		command->cmd_dep = cpu_to_le32(stopaddr);
 		command->phy_addr = cpu_to_le32(offset);
 		command->req_count = cpu_to_le16(periodsize);
-		command->xfer_status = cpu_to_le16(0);
 	}
-	/* last one branches back to first */
-	command--;
-	command->command |= cpu_to_le16(BR_ALWAYS);
+
+	/* branch back to beginning of ring */
+	command->command = cpu_to_le16(DBDMA_NOP | BR_ALWAYS);
 	command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start);
+	command++;
+
+	/* set stop command */
+	command->command = cpu_to_le16(DBDMA_STOP);
 
 	/* ok, let's set the serial format and stuff */
 	switch (runtime->format) {
@@ -435,16 +523,18 @@
 	return result;
 }
 
-static struct dbdma_cmd STOP_CMD = {
-	.command = __constant_cpu_to_le16(DBDMA_STOP),
-};
+#ifdef CONFIG_PM
+void i2sbus_pcm_prepare_both(struct i2sbus_dev *i2sdev)
+{
+	i2sbus_pcm_prepare(i2sdev, 0);
+	i2sbus_pcm_prepare(i2sdev, 1);
+}
+#endif
 
 static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
 {
 	struct codec_info_item *cii;
 	struct pcm_info *pi;
-	int timeout;
-	struct dbdma_cmd tmp;
 	int result = 0;
 	unsigned long flags;
 
@@ -464,92 +554,50 @@
 				cii->codec->start(cii, pi->substream);
 		pi->dbdma_ring.running = 1;
 
-		/* reset dma engine */
-		out_le32(&pi->dbdma->control,
-			 0 | (RUN | PAUSE | FLUSH | WAKE) << 16);
-		timeout = 100;
-		while (in_le32(&pi->dbdma->status) & RUN && timeout--)
-			udelay(1);
-		if (timeout <= 0) {
-			printk(KERN_ERR
-			       "i2sbus: error waiting for dma reset\n");
-			result = -ENXIO;
-			goto out_unlock;
+		if (pi->dbdma_ring.stopping) {
+			/* Clear the S0 bit, then see if we stopped yet */
+			out_le32(&pi->dbdma->control, 1 << 16);
+			if (in_le32(&pi->dbdma->status) & ACTIVE) {
+				/* possible race here? */
+				udelay(10);
+				if (in_le32(&pi->dbdma->status) & ACTIVE) {
+					pi->dbdma_ring.stopping = 0;
+					goto out_unlock; /* keep running */
+				}
+			}
 		}
 
+		/* make sure RUN, PAUSE and S0 bits are cleared */
+		out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
+
+		/* set branch condition select register */
+		out_le32(&pi->dbdma->br_sel, (1 << 16) | 1);
+
 		/* write dma command buffer address to the dbdma chip */
 		out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
-		/* post PCI write */
-		mb();
-		(void)in_le32(&pi->dbdma->status);
 
-		/* change first command to STOP */
-		tmp = *pi->dbdma_ring.cmds;
-		*pi->dbdma_ring.cmds = STOP_CMD;
-
-		/* set running state, remember that the first command is STOP */
-		out_le32(&pi->dbdma->control, RUN | (RUN << 16));
-		timeout = 100;
-		/* wait for STOP to be executed */
-		while (in_le32(&pi->dbdma->status) & ACTIVE && timeout--)
-			udelay(1);
-		if (timeout <= 0) {
-			printk(KERN_ERR "i2sbus: error waiting for dma stop\n");
-			result = -ENXIO;
-			goto out_unlock;
-		}
-		/* again, write dma command buffer address to the dbdma chip,
-		 * this time of the first real command */
-		*pi->dbdma_ring.cmds = tmp;
-		out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
-		/* post write */
-		mb();
-		(void)in_le32(&pi->dbdma->status);
-
-		/* reset dma engine again */
-		out_le32(&pi->dbdma->control,
-			 0 | (RUN | PAUSE | FLUSH | WAKE) << 16);
-		timeout = 100;
-		while (in_le32(&pi->dbdma->status) & RUN && timeout--)
-			udelay(1);
-		if (timeout <= 0) {
-			printk(KERN_ERR
-			       "i2sbus: error waiting for dma reset\n");
-			result = -ENXIO;
-			goto out_unlock;
-		}
-
-		/* wake up the chip with the next descriptor */
-		out_le32(&pi->dbdma->control,
-			 (RUN | WAKE) | ((RUN | WAKE) << 16));
-		/* get the frame count  */
+		/* initialize the frame count and current period */
+		pi->current_period = 0;
 		pi->frame_count = in_le32(&i2sdev->intfregs->frame_count);
 
+		/* set the DMA controller running */
+		out_le32(&pi->dbdma->control, (RUN << 16) | RUN);
+
 		/* off you go! */
 		break;
+
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 		if (!pi->dbdma_ring.running) {
 			result = -EALREADY;
 			goto out_unlock;
 		}
-
-		/* turn off all relevant bits */
-		out_le32(&pi->dbdma->control,
-			 (RUN | WAKE | FLUSH | PAUSE) << 16);
-		{
-			/* FIXME: move to own function */
-			int timeout = 5000;
-			while ((in_le32(&pi->dbdma->status) & RUN)
-			       && --timeout > 0)
-				udelay(1);
-			if (!timeout)
-				printk(KERN_ERR
-				       "i2sbus: timed out turning "
-				       "off dbdma engine!\n");
-		}
-
 		pi->dbdma_ring.running = 0;
+
+		/* Set the S0 bit to make the DMA branch to the stop cmd */
+		out_le32(&pi->dbdma->control, (1 << 16) | 1);
+		pi->dbdma_ring.stopping = 1;
+
 		list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
 			if (cii->codec->stop)
 				cii->codec->stop(cii, pi->substream);
@@ -574,70 +622,82 @@
 	fc = in_le32(&i2sdev->intfregs->frame_count);
 	fc = fc - pi->frame_count;
 
-	return (bytes_to_frames(pi->substream->runtime,
-			pi->current_period *
-			snd_pcm_lib_period_bytes(pi->substream))
-		+ fc) % pi->substream->runtime->buffer_size;
+	if (fc >= pi->substream->runtime->buffer_size)
+		fc %= pi->substream->runtime->buffer_size;
+	return fc;
 }
 
 static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in)
 {
 	struct pcm_info *pi;
-	u32 fc;
-	u32 delta;
+	u32 fc, nframes;
+	u32 status;
+	int timeout, i;
+	int dma_stopped = 0;
+	struct snd_pcm_runtime *runtime;
 
 	spin_lock(&i2sdev->low_lock);
 	get_pcm_info(i2sdev, in, &pi, NULL);
-
-	if (!pi->dbdma_ring.running) {
-		/* there was still an interrupt pending
-		 * while we stopped. or maybe another
-		 * processor (not the one that was stopping
-		 * the DMA engine) was spinning above
-		 * waiting for the lock. */
+	if (!pi->dbdma_ring.running && !pi->dbdma_ring.stopping)
 		goto out_unlock;
-	}
 
-	fc = in_le32(&i2sdev->intfregs->frame_count);
-	/* a counter overflow does not change the calculation. */
-	delta = fc - pi->frame_count;
+	i = pi->current_period;
+	runtime = pi->substream->runtime;
+	while (pi->dbdma_ring.cmds[i].xfer_status) {
+		if (le16_to_cpu(pi->dbdma_ring.cmds[i].xfer_status) & BT)
+			/*
+			 * BT is the branch taken bit.  If it took a branch
+			 * it is because we set the S0 bit to make it
+			 * branch to the stop command.
+			 */
+			dma_stopped = 1;
+		pi->dbdma_ring.cmds[i].xfer_status = 0;
 
-	/* update current_period */
-	while (delta >= pi->substream->runtime->period_size) {
-		pi->current_period++;
-		delta = delta - pi->substream->runtime->period_size;
-	}
-
-	if (unlikely(delta)) {
-		/* Some interrupt came late, so check the dbdma.
-		 * This special case exists to syncronize the frame_count with
-		 * the dbdma transfer, but is hit every once in a while. */
-		int period;
-
-		period = (in_le32(&pi->dbdma->cmdptr)
-		        - pi->dbdma_ring.bus_cmd_start)
-				/ sizeof(struct dbdma_cmd);
-		pi->current_period = pi->current_period
-					% pi->substream->runtime->periods;
-
-		while (pi->current_period != period) {
-			pi->current_period++;
-			pi->current_period %= pi->substream->runtime->periods;
-			/* Set delta to zero, as the frame_count value is too
-			 * high (otherwise the code path will not be executed).
-			 * This corrects the fact that the frame_count is too
-			 * low at the beginning due to buffering. */
-			delta = 0;
+		if (++i >= runtime->periods) {
+			i = 0;
+			pi->frame_count += runtime->buffer_size;
 		}
+		pi->current_period = i;
+
+		/*
+		 * Check the frame count.  The DMA tends to get a bit
+		 * ahead of the frame counter, which confuses the core.
+		 */
+		fc = in_le32(&i2sdev->intfregs->frame_count);
+		nframes = i * runtime->period_size;
+		if (fc < pi->frame_count + nframes)
+			pi->frame_count = fc - nframes;
 	}
 
-	pi->frame_count = fc - delta;
-	pi->current_period %= pi->substream->runtime->periods;
+	if (dma_stopped) {
+		timeout = 1000;
+		for (;;) {
+			status = in_le32(&pi->dbdma->status);
+			if (!(status & ACTIVE) && (!in || (status & 0x80)))
+				break;
+			if (--timeout <= 0) {
+				printk(KERN_ERR "i2sbus: timed out "
+				       "waiting for DMA to stop!\n");
+				break;
+			}
+			udelay(1);
+		}
 
+		/* Turn off DMA controller, clear S0 bit */
+		out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
+
+		pi->dbdma_ring.stopping = 0;
+		if (pi->stop_completion)
+			complete(pi->stop_completion);
+	}
+
+	if (!pi->dbdma_ring.running)
+		goto out_unlock;
 	spin_unlock(&i2sdev->low_lock);
 	/* may call _trigger again, hence needs to be unlocked */
 	snd_pcm_period_elapsed(pi->substream);
 	return;
+
  out_unlock:
 	spin_unlock(&i2sdev->low_lock);
 }
@@ -718,7 +778,7 @@
 	.close =	i2sbus_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	i2sbus_hw_params,
-	.hw_free =	i2sbus_hw_free,
+	.hw_free =	i2sbus_playback_hw_free,
 	.prepare =	i2sbus_playback_prepare,
 	.trigger =	i2sbus_playback_trigger,
 	.pointer =	i2sbus_playback_pointer,
@@ -788,7 +848,7 @@
 	.close =	i2sbus_record_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	i2sbus_hw_params,
-	.hw_free =	i2sbus_hw_free,
+	.hw_free =	i2sbus_record_hw_free,
 	.prepare =	i2sbus_record_prepare,
 	.trigger =	i2sbus_record_trigger,
 	.pointer =	i2sbus_record_pointer,
@@ -812,7 +872,6 @@
 	module_put(THIS_MODULE);
 }
 
-/* FIXME: this function needs an error handling strategy with labels */
 int
 i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
 		    struct codec_info *ci, void *data)
@@ -880,41 +939,31 @@
 	if (!cii->sdev) {
 		printk(KERN_DEBUG
 		       "i2sbus: failed to get soundbus dev reference\n");
-		kfree(cii);
-		return -ENODEV;
+		err = -ENODEV;
+		goto out_free_cii;
 	}
 
 	if (!try_module_get(THIS_MODULE)) {
 		printk(KERN_DEBUG "i2sbus: failed to get module reference!\n");
-		soundbus_dev_put(dev);
-		kfree(cii);
-		return -EBUSY;
+		err = -EBUSY;
+		goto out_put_sdev;
 	}
 
 	if (!try_module_get(ci->owner)) {
 		printk(KERN_DEBUG
 		       "i2sbus: failed to get module reference to codec owner!\n");
-		module_put(THIS_MODULE);
-		soundbus_dev_put(dev);
-		kfree(cii);
-		return -EBUSY;
+		err = -EBUSY;
+		goto out_put_this_module;
 	}
 
 	if (!dev->pcm) {
-		err = snd_pcm_new(card,
-				  dev->pcmname,
-				  dev->pcmid,
-				  0,
-				  0,
+		err = snd_pcm_new(card, dev->pcmname, dev->pcmid, 0, 0,
 				  &dev->pcm);
 		if (err) {
 			printk(KERN_DEBUG "i2sbus: failed to create pcm\n");
-			kfree(cii);
-			module_put(ci->owner);
-			soundbus_dev_put(dev);
-			module_put(THIS_MODULE);
-			return err;
+			goto out_put_ci_module;
 		}
+		dev->pcm->dev = &dev->ofdev.dev;
 	}
 
 	/* ALSA yet again sucks.
@@ -926,20 +975,12 @@
 			/* eh? */
 			printk(KERN_ERR
 			       "Can't attach same bus to different cards!\n");
-			module_put(ci->owner);
-			kfree(cii);
-			soundbus_dev_put(dev);
-			module_put(THIS_MODULE);
-			return -EINVAL;
+			err = -EINVAL;
+			goto out_put_ci_module;
 		}
-		if ((err =
-		     snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1))) {
-			module_put(ci->owner);
-			kfree(cii);
-			soundbus_dev_put(dev);
-			module_put(THIS_MODULE);
-			return err;
-		}
+		err = snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1);
+		if (err)
+			goto out_put_ci_module;
 		snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK,
 				&i2sbus_playback_ops);
 		i2sdev->out.created = 1;
@@ -949,20 +990,11 @@
 		if (dev->pcm->card != card) {
 			printk(KERN_ERR
 			       "Can't attach same bus to different cards!\n");
-			module_put(ci->owner);
-			kfree(cii);
-			soundbus_dev_put(dev);
-			module_put(THIS_MODULE);
-			return -EINVAL;
+			goto out_put_ci_module;
 		}
-		if ((err =
-		     snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1))) {
-			module_put(ci->owner);
-			kfree(cii);
-			soundbus_dev_put(dev);
-			module_put(THIS_MODULE);
-			return err;
-		}
+		err = snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1);
+		if (err)
+			goto out_put_ci_module;
 		snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE,
 				&i2sbus_record_ops);
 		i2sdev->in.created = 1;
@@ -977,11 +1009,7 @@
 	err = snd_device_register(card, dev->pcm);
 	if (err) {
 		printk(KERN_ERR "i2sbus: error registering new pcm\n");
-		module_put(ci->owner);
-		kfree(cii);
-		soundbus_dev_put(dev);
-		module_put(THIS_MODULE);
-		return err;
+		goto out_put_ci_module;
 	}
 	/* no errors any more, so let's add this to our list */
 	list_add(&cii->list, &dev->codec_list);
@@ -996,6 +1024,15 @@
 		64 * 1024, 64 * 1024);
 
 	return 0;
+ out_put_ci_module:
+	module_put(ci->owner);
+ out_put_this_module:
+	module_put(THIS_MODULE);
+ out_put_sdev:
+	soundbus_dev_put(dev);
+ out_free_cii:
+	kfree(cii);
+	return err;
 }
 
 void i2sbus_detach_codec(struct soundbus_dev *dev, void *data)
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
index ec20ee6..ff29654 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus.h
+++ b/sound/aoa/soundbus/i2sbus/i2sbus.h
@@ -10,6 +10,7 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
+#include <linux/completion.h>
 
 #include <sound/pcm.h>
 
@@ -34,6 +35,7 @@
 	void *space;
 	int size;
 	u32 running:1;
+	u32 stopping:1;
 };
 
 struct pcm_info {
@@ -45,6 +47,7 @@
 	u32 frame_count;
 	struct dbdma_command_mem dbdma_ring;
 	volatile struct dbdma_regs __iomem *dbdma;
+	struct completion *stop_completion;
 };
 
 enum {
@@ -101,6 +104,9 @@
 extern irqreturn_t
 i2sbus_rx_intr(int irq, void *devid);
 
+extern void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev);
+extern void i2sbus_pcm_prepare_both(struct i2sbus_dev *i2sdev);
+
 /* control specific functions */
 extern int i2sbus_control_init(struct macio_dev* dev,
 			       struct i2sbus_control **c);
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 53675cf..b9eca9f 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -65,10 +65,12 @@
  *  SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
  *  register.
  */
-static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
+static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+			    unsigned short val)
 {
 	struct aaci *aaci = ac97->private_data;
 	u32 v;
+	int timeout = 5000;
 
 	if (ac97->num >= 4)
 		return;
@@ -89,7 +91,11 @@
 	 */
 	do {
 		v = readl(aaci->base + AACI_SLFR);
-	} while (v & (SLFR_1TXB|SLFR_2TXB));
+	} while ((v & (SLFR_1TXB|SLFR_2TXB)) && timeout--);
+
+	if (!timeout)
+		dev_err(&aaci->dev->dev,
+			"timeout waiting for write to complete\n");
 
 	mutex_unlock(&aaci->ac97_sem);
 }
@@ -101,6 +107,8 @@
 {
 	struct aaci *aaci = ac97->private_data;
 	u32 v;
+	int timeout = 5000;
+	int retries = 10;
 
 	if (ac97->num >= 4)
 		return ~0;
@@ -119,7 +127,13 @@
 	 */
 	do {
 		v = readl(aaci->base + AACI_SLFR);
-	} while (v & SLFR_1TXB);
+	} while ((v & SLFR_1TXB) && timeout--);
+
+	if (!timeout) {
+		dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n");
+		v = ~0;
+		goto out;
+	}
 
 	/*
 	 * Give the AC'97 codec more than enough time
@@ -130,21 +144,35 @@
 	/*
 	 * Wait for slot 2 to indicate data.
 	 */
+	timeout = 5000;
 	do {
 		cond_resched();
 		v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
-	} while (v != (SLFR_1RXV|SLFR_2RXV));
+	} while ((v != (SLFR_1RXV|SLFR_2RXV)) && timeout--);
 
-	v = readl(aaci->base + AACI_SL1RX) >> 12;
-	if (v == reg) {
-		v = readl(aaci->base + AACI_SL2RX) >> 4;
-	} else {
-		dev_err(&aaci->dev->dev,
-			"wrong ac97 register read back (%x != %x)\n",
-			v, reg);
+	if (!timeout) {
+		dev_err(&aaci->dev->dev, "timeout on RX valid\n");
 		v = ~0;
+		goto out;
 	}
 
+	do {
+		v = readl(aaci->base + AACI_SL1RX) >> 12;
+		if (v == reg) {
+			v = readl(aaci->base + AACI_SL2RX) >> 4;
+			break;
+		} else if (--retries) {
+			dev_warn(&aaci->dev->dev,
+				 "ac97 read back fail.  retry\n");
+			continue;
+		} else {
+			dev_warn(&aaci->dev->dev,
+				"wrong ac97 register read back (%x != %x)\n",
+				v, reg);
+			v = ~0;
+		}
+	} while (retries);
+ out:
 	mutex_unlock(&aaci->ac97_sem);
 	return v;
 }
@@ -164,10 +192,70 @@
 /*
  * Interrupt support.
  */
-static void aaci_fifo_irq(struct aaci *aaci, u32 mask)
+static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
 {
+	if (mask & ISR_ORINTR) {
+		dev_warn(&aaci->dev->dev, "RX overrun on chan %d\n", channel);
+		writel(ICLR_RXOEC1 << channel, aaci->base + AACI_INTCLR);
+	}
+
+	if (mask & ISR_RXTOINTR) {
+		dev_warn(&aaci->dev->dev, "RX timeout on chan %d\n", channel);
+		writel(ICLR_RXTOFEC1 << channel, aaci->base + AACI_INTCLR);
+	}
+
+	if (mask & ISR_RXINTR) {
+		struct aaci_runtime *aacirun = &aaci->capture;
+		void *ptr;
+
+		if (!aacirun->substream || !aacirun->start) {
+			dev_warn(&aaci->dev->dev, "RX interrupt???");
+			writel(0, aacirun->base + AACI_IE);
+			return;
+		}
+		ptr = aacirun->ptr;
+
+		do {
+			unsigned int len = aacirun->fifosz;
+			u32 val;
+
+			if (aacirun->bytes <= 0) {
+				aacirun->bytes += aacirun->period;
+				aacirun->ptr = ptr;
+				spin_unlock(&aaci->lock);
+				snd_pcm_period_elapsed(aacirun->substream);
+				spin_lock(&aaci->lock);
+			}
+			if (!(aacirun->cr & CR_EN))
+				break;
+
+			val = readl(aacirun->base + AACI_SR);
+			if (!(val & SR_RXHF))
+				break;
+			if (!(val & SR_RXFF))
+				len >>= 1;
+
+			aacirun->bytes -= len;
+
+			/* reading 16 bytes at a time */
+			for( ; len > 0; len -= 16) {
+				asm(
+					"ldmia	%1, {r0, r1, r2, r3}\n\t"
+					"stmia	%0!, {r0, r1, r2, r3}"
+					: "+r" (ptr)
+					: "r" (aacirun->fifo)
+					: "r0", "r1", "r2", "r3", "cc");
+
+				if (ptr >= aacirun->end)
+					ptr = aacirun->start;
+			}
+		} while(1);
+		aacirun->ptr = ptr;
+	}
+
 	if (mask & ISR_URINTR) {
-		writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR);
+		dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel);
+		writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR);
 	}
 
 	if (mask & ISR_TXINTR) {
@@ -192,7 +280,7 @@
 				snd_pcm_period_elapsed(aacirun->substream);
 				spin_lock(&aaci->lock);
 			}
-			if (!(aacirun->cr & TXCR_TXEN))
+			if (!(aacirun->cr & CR_EN))
 				break;
 
 			val = readl(aacirun->base + AACI_SR);
@@ -233,7 +321,7 @@
 		u32 m = mask;
 		for (i = 0; i < 4; i++, m >>= 7) {
 			if (m & 0x7f) {
-				aaci_fifo_irq(aaci, m);
+				aaci_fifo_irq(aaci, i, m);
 			}
 		}
 	}
@@ -330,8 +418,9 @@
 	.periods_max		= PAGE_SIZE / 16,
 };
 
-static int aaci_pcm_open(struct aaci *aaci, struct snd_pcm_substream *substream,
-			 struct aaci_runtime *aacirun)
+static int __aaci_pcm_open(struct aaci *aaci,
+			   struct snd_pcm_substream *substream,
+			   struct aaci_runtime *aacirun)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int ret;
@@ -380,7 +469,7 @@
 	struct aaci *aaci = substream->private_data;
 	struct aaci_runtime *aacirun = substream->runtime->private_data;
 
-	WARN_ON(aacirun->cr & TXCR_TXEN);
+	WARN_ON(aacirun->cr & CR_EN);
 
 	aacirun->substream = NULL;
 	free_irq(aaci->dev->irq[0], aaci);
@@ -395,7 +484,7 @@
 	/*
 	 * This must not be called with the device enabled.
 	 */
-	WARN_ON(aacirun->cr & TXCR_TXEN);
+	WARN_ON(aacirun->cr & CR_EN);
 
 	if (aacirun->pcm_open)
 		snd_ac97_pcm_close(aacirun->pcm);
@@ -422,9 +511,15 @@
 	if (err < 0)
 		goto out;
 
-	err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
-				params_channels(params),
-				aacirun->pcm->r[0].slots);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
+					params_channels(params),
+					aacirun->pcm->r[0].slots);
+	else
+		err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
+					params_channels(params),
+					aacirun->pcm->r[1].slots);
+
 	if (err)
 		goto out;
 
@@ -467,9 +562,9 @@
  * Playback specific ALSA stuff
  */
 static const u32 channels_to_txmask[] = {
-	[2] = TXCR_TX3 | TXCR_TX4,
-	[4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8,
-	[6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9,
+	[2] = CR_SL3 | CR_SL4,
+	[4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
+	[6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
 };
 
 /*
@@ -504,7 +599,7 @@
 				 chan_mask);
 }
 
-static int aaci_pcm_playback_open(struct snd_pcm_substream *substream)
+static int aaci_pcm_open(struct snd_pcm_substream *substream)
 {
 	struct aaci *aaci = substream->private_data;
 	int ret;
@@ -519,7 +614,12 @@
 	if (ret)
 		return ret;
 
-	return aaci_pcm_open(aaci, substream, &aaci->playback);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ret = __aaci_pcm_open(aaci, substream, &aaci->playback);
+	} else {
+		ret = __aaci_pcm_open(aaci, substream, &aaci->capture);
+	}
+	return ret;
 }
 
 static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
@@ -540,11 +640,11 @@
 	 * FIXME: double rate slots?
 	 */
 	if (ret >= 0) {
-		aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16;
+		aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
 		aacirun->cr |= channels_to_txmask[channels];
 
 		aacirun->fifosz	= aaci->fifosize * 4;
-		if (aacirun->cr & TXCR_COMPACT)
+		if (aacirun->cr & CR_COMPACT)
 			aacirun->fifosz >>= 1;
 	}
 	return ret;
@@ -557,7 +657,7 @@
 	ie = readl(aacirun->base + AACI_IE);
 	ie &= ~(IE_URIE|IE_TXIE);
 	writel(ie, aacirun->base + AACI_IE);
-	aacirun->cr &= ~TXCR_TXEN;
+	aacirun->cr &= ~CR_EN;
 	aaci_chan_wait_ready(aacirun);
 	writel(aacirun->cr, aacirun->base + AACI_TXCR);
 }
@@ -567,7 +667,7 @@
 	u32 ie;
 
 	aaci_chan_wait_ready(aacirun);
-	aacirun->cr |= TXCR_TXEN;
+	aacirun->cr |= CR_EN;
 
 	ie = readl(aacirun->base + AACI_IE);
 	ie |= IE_URIE | IE_TXIE;
@@ -615,7 +715,7 @@
 }
 
 static struct snd_pcm_ops aaci_playback_ops = {
-	.open		= aaci_pcm_playback_open,
+	.open		= aaci_pcm_open,
 	.close		= aaci_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= aaci_pcm_playback_hw_params,
@@ -626,7 +726,133 @@
 	.mmap		= aaci_pcm_mmap,
 };
 
+static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream,
+				      struct snd_pcm_hw_params *params)
+{
+	struct aaci *aaci = substream->private_data;
+	struct aaci_runtime *aacirun = substream->runtime->private_data;
+	int ret;
 
+	ret = aaci_pcm_hw_params(substream, aacirun, params);
+
+	if (ret >= 0) {
+		aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
+
+		/* Line in record: slot 3 and 4 */
+		aacirun->cr |= CR_SL3 | CR_SL4;
+
+		aacirun->fifosz = aaci->fifosize * 4;
+
+		if (aacirun->cr & CR_COMPACT)
+			aacirun->fifosz >>= 1;
+	}
+	return ret;
+}
+
+static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)
+{
+	u32 ie;
+
+	aaci_chan_wait_ready(aacirun);
+
+	ie = readl(aacirun->base + AACI_IE);
+	ie &= ~(IE_ORIE | IE_RXIE);
+	writel(ie, aacirun->base+AACI_IE);
+
+	aacirun->cr &= ~CR_EN;
+
+	writel(aacirun->cr, aacirun->base + AACI_RXCR);
+}
+
+static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
+{
+	u32 ie;
+
+	aaci_chan_wait_ready(aacirun);
+
+#ifdef DEBUG
+	/* RX Timeout value: bits 28:17 in RXCR */
+	aacirun->cr |= 0xf << 17;
+#endif
+
+	aacirun->cr |= CR_EN;
+	writel(aacirun->cr, aacirun->base + AACI_RXCR);
+
+	ie = readl(aacirun->base + AACI_IE);
+	ie |= IE_ORIE |IE_RXIE; // overrun and rx interrupt -- half full
+	writel(ie, aacirun->base + AACI_IE);
+}
+
+static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct aaci *aaci = substream->private_data;
+	struct aaci_runtime *aacirun = substream->runtime->private_data;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&aaci->lock, flags);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		aaci_pcm_capture_start(aacirun);
+		break;
+
+	case SNDRV_PCM_TRIGGER_RESUME:
+		aaci_pcm_capture_start(aacirun);
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+		aaci_pcm_capture_stop(aacirun);
+		break;
+
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		aaci_pcm_capture_stop(aacirun);
+		break;
+
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		break;
+
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	spin_unlock_irqrestore(&aaci->lock, flags);
+
+	return ret;
+}
+
+static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct aaci *aaci = substream->private_data;
+
+	aaci_pcm_prepare(substream);
+
+	/* allow changing of sample rate */
+	aaci_ac97_write(aaci->ac97, AC97_EXTENDED_STATUS, 0x0001); /* VRA */
+	aaci_ac97_write(aaci->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
+	aaci_ac97_write(aaci->ac97, AC97_PCM_MIC_ADC_RATE, runtime->rate);
+
+	/* Record select: Mic: 0, Aux: 3, Line: 4 */
+	aaci_ac97_write(aaci->ac97, AC97_REC_SEL, 0x0404);
+
+	return 0;
+}
+
+static struct snd_pcm_ops aaci_capture_ops = {
+	.open		= aaci_pcm_open,
+	.close		= aaci_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= aaci_pcm_capture_hw_params,
+	.hw_free	= aaci_pcm_hw_free,
+	.prepare	= aaci_pcm_capture_prepare,
+	.trigger	= aaci_pcm_capture_trigger,
+	.pointer	= aaci_pcm_pointer,
+	.mmap		= aaci_pcm_mmap,
+};
 
 /*
  * Power Management.
@@ -666,7 +892,7 @@
 
 
 static struct ac97_pcm ac97_defs[] __devinitdata = {
-	[0] = {		/* Front PCM */
+	[0] = {	/* Front PCM */
 		.exclusive = 1,
 		.r = {
 			[0] = {
@@ -740,6 +966,7 @@
 	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
 	if (ret)
 		goto out;
+	aaci->ac97 = ac97;
 
 	/*
 	 * Disable AC97 PC Beep input on audio codecs.
@@ -752,6 +979,7 @@
 		goto out;
 
 	aaci->playback.pcm = &ac97_bus->pcms[0];
+	aaci->capture.pcm  = &ac97_bus->pcms[1];
 
  out:
 	return ret;
@@ -801,7 +1029,7 @@
 	struct snd_pcm *pcm;
 	int ret;
 
-	ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm);
+	ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 1, &pcm);
 	if (ret == 0) {
 		aaci->pcm = pcm;
 		pcm->private_data = aaci;
@@ -810,6 +1038,7 @@
 		strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
 
 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
 	}
 
 	return ret;
@@ -817,15 +1046,15 @@
 
 static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
 {
-	void __iomem *base = aaci->base + AACI_CSCH1;
+	struct aaci_runtime *aacirun = &aaci->playback;
 	int i;
 
-	writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
+	writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR);
 
-	for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++)
-		writel(0, aaci->base + AACI_DR1);
+	for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++)
+		writel(0, aacirun->fifo);
 
-	writel(0, base + AACI_TXCR);
+	writel(0, aacirun->base + AACI_TXCR);
 
 	/*
 	 * Re-initialise the AACI after the FIFO depth test, to
@@ -872,6 +1101,12 @@
 	aaci->playback.base = aaci->base + AACI_CSCH1;
 	aaci->playback.fifo = aaci->base + AACI_DR1;
 
+	/*
+	 * Capture uses AACI channel 0
+	 */
+	aaci->capture.base = aaci->base + AACI_CSCH1;
+	aaci->capture.fifo = aaci->base + AACI_DR1;
+
 	for (i = 0; i < 4; i++) {
 		void __iomem *base = aaci->base + i * 0x14;
 
@@ -907,7 +1142,7 @@
 	ret = snd_card_register(aaci->card);
 	if (ret == 0) {
 		dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
-			aaci->fifosize);
+			 aaci->fifosize);
 		amba_set_drvdata(dev, aaci->card);
 		return ret;
 	}
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h
index 0629519..924f69c 100644
--- a/sound/arm/aaci.h
+++ b/sound/arm/aaci.h
@@ -49,27 +49,27 @@
 #define AACI_DR4	0x0f0	/* data read/written fifo 4 */
 
 /*
- * transmit fifo control register. P48
+ * TX/RX fifo control register (CR). P48
  */
-#define TXCR_FEN	(1 << 16)	/* fifo enable */
-#define TXCR_COMPACT	(1 << 15)	/* compact mode */
-#define TXCR_TSZ16	(0 << 13)	/* 16 bits */
-#define TXCR_TSZ18	(1 << 13)	/* 18 bits */
-#define TXCR_TSZ20	(2 << 13)	/* 20 bits */
-#define TXCR_TSZ12	(3 << 13)	/* 12 bits */
-#define TXCR_TX12	(1 << 12)	/* transmits slot 12 */
-#define TXCR_TX11	(1 << 11)	/* transmits slot 12 */
-#define TXCR_TX10	(1 << 10)	/* transmits slot 12 */
-#define TXCR_TX9	(1 << 9)	/* transmits slot 12 */
-#define TXCR_TX8	(1 << 8)	/* transmits slot 12 */
-#define TXCR_TX7	(1 << 7)	/* transmits slot 12 */
-#define TXCR_TX6	(1 << 6)	/* transmits slot 12 */
-#define TXCR_TX5	(1 << 5)	/* transmits slot 12 */
-#define TXCR_TX4	(1 << 4)	/* transmits slot 12 */
-#define TXCR_TX3	(1 << 3)	/* transmits slot 12 */
-#define TXCR_TX2	(1 << 2)	/* transmits slot 12 */
-#define TXCR_TX1	(1 << 1)	/* transmits slot 12 */
-#define TXCR_TXEN	(1 << 0)	/* transmit enable */
+#define CR_FEN		(1 << 16)	/* fifo enable */
+#define CR_COMPACT	(1 << 15)	/* compact mode */
+#define CR_SZ16		(0 << 13)	/* 16 bits */
+#define CR_SZ18		(1 << 13)	/* 18 bits */
+#define CR_SZ20		(2 << 13)	/* 20 bits */
+#define CR_SZ12		(3 << 13)	/* 12 bits */
+#define CR_SL12		(1 << 12)
+#define CR_SL11		(1 << 11)
+#define CR_SL10		(1 << 10)
+#define CR_SL9		(1 << 9)
+#define CR_SL8		(1 << 8)
+#define CR_SL7		(1 << 7)
+#define CR_SL6		(1 << 6)
+#define CR_SL5		(1 << 5)
+#define CR_SL4		(1 << 4)
+#define CR_SL3		(1 << 3)
+#define CR_SL2		(1 << 2)
+#define CR_SL1		(1 << 1)
+#define CR_EN		(1 << 0)	/* transmit enable */
 
 /*
  * status register bits. P49
@@ -228,7 +228,8 @@
 
 	/* AC'97 */
 	struct mutex		ac97_sem;
-	ac97_bus_t		*ac97_bus;
+	struct snd_ac97_bus	*ac97_bus;
+	struct snd_ac97		*ac97;
 
 	u32			maincr;
 	spinlock_t		lock;
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index dede954..28db4be 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -305,7 +305,7 @@
 #define pxa2xx_ac97_resume	NULL
 #endif
 
-static int pxa2xx_ac97_probe(struct platform_device *dev)
+static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
 {
 	struct snd_card *card;
 	struct snd_ac97_bus *ac97_bus;
@@ -369,7 +369,7 @@
 	return ret;
 }
 
-static int pxa2xx_ac97_remove(struct platform_device *dev)
+static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
 {
 	struct snd_card *card = platform_get_drvdata(dev);
 
@@ -386,7 +386,7 @@
 
 static struct platform_driver pxa2xx_ac97_driver = {
 	.probe		= pxa2xx_ac97_probe,
-	.remove		= pxa2xx_ac97_remove,
+	.remove		= __devexit_p(pxa2xx_ac97_remove),
 	.suspend	= pxa2xx_ac97_suspend,
 	.resume		= pxa2xx_ac97_resume,
 	.driver		= {
diff --git a/sound/core/control.c b/sound/core/control.c
index 0c7bcd6..86de725 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -108,7 +108,6 @@
 static int snd_ctl_release(struct inode *inode, struct file *file)
 {
 	unsigned long flags;
-	struct list_head *list;
 	struct snd_card *card;
 	struct snd_ctl_file *ctl;
 	struct snd_kcontrol *control;
@@ -122,12 +121,10 @@
 	list_del(&ctl->list);
 	write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
 	down_write(&card->controls_rwsem);
-	list_for_each(list, &card->controls) {
-		control = snd_kcontrol(list);
+	list_for_each_entry(control, &card->controls, list)
 		for (idx = 0; idx < control->count; idx++)
 			if (control->vd[idx].owner == ctl)
 				control->vd[idx].owner = NULL;
-	}
 	up_write(&card->controls_rwsem);
 	snd_ctl_empty_read_queue(ctl);
 	kfree(ctl);
@@ -140,7 +137,6 @@
 		    struct snd_ctl_elem_id *id)
 {
 	unsigned long flags;
-	struct list_head *flist;
 	struct snd_ctl_file *ctl;
 	struct snd_kctl_event *ev;
 	
@@ -149,14 +145,11 @@
 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
 	card->mixer_oss_change_count++;
 #endif
-	list_for_each(flist, &card->ctl_files) {
-		struct list_head *elist;
-		ctl = snd_ctl_file(flist);
+	list_for_each_entry(ctl, &card->ctl_files, list) {
 		if (!ctl->subscribed)
 			continue;
 		spin_lock_irqsave(&ctl->read_lock, flags);
-		list_for_each(elist, &ctl->events) {
-			ev = snd_kctl_event(elist);
+		list_for_each_entry(ev, &ctl->events, list) {
 			if (ev->id.numid == id->numid) {
 				ev->mask |= mask;
 				goto _found;
@@ -190,7 +183,8 @@
  *
  * Returns the pointer of the new instance, or NULL on failure.
  */
-struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, unsigned int access)
+static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
+					unsigned int access)
 {
 	struct snd_kcontrol *kctl;
 	unsigned int idx;
@@ -208,8 +202,6 @@
 	return kctl;
 }
 
-EXPORT_SYMBOL(snd_ctl_new);
-
 /**
  * snd_ctl_new1 - create a control instance from the template
  * @ncontrol: the initialization record
@@ -277,11 +269,9 @@
 static unsigned int snd_ctl_hole_check(struct snd_card *card,
 				       unsigned int count)
 {
-	struct list_head *list;
 	struct snd_kcontrol *kctl;
 
-	list_for_each(list, &card->controls) {
-		kctl = snd_kcontrol(list);
+	list_for_each_entry(kctl, &card->controls, list) {
 		if ((kctl->id.numid <= card->last_numid &&
 		     kctl->id.numid + kctl->count > card->last_numid) ||
 		    (kctl->id.numid <= card->last_numid + count - 1 &&
@@ -498,12 +488,10 @@
  */
 struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid)
 {
-	struct list_head *list;
 	struct snd_kcontrol *kctl;
 
 	snd_assert(card != NULL && numid != 0, return NULL);
-	list_for_each(list, &card->controls) {
-		kctl = snd_kcontrol(list);
+	list_for_each_entry(kctl, &card->controls, list) {
 		if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid)
 			return kctl;
 	}
@@ -527,14 +515,12 @@
 struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
 				     struct snd_ctl_elem_id *id)
 {
-	struct list_head *list;
 	struct snd_kcontrol *kctl;
 
 	snd_assert(card != NULL && id != NULL, return NULL);
 	if (id->numid != 0)
 		return snd_ctl_find_numid(card, id->numid);
-	list_for_each(list, &card->controls) {
-		kctl = snd_kcontrol(list);
+	list_for_each_entry(kctl, &card->controls, list) {
 		if (kctl->id.iface != id->iface)
 			continue;
 		if (kctl->id.device != id->device)
@@ -1182,7 +1168,6 @@
 {
 	struct snd_ctl_file *ctl;
 	struct snd_card *card;
-	struct list_head *list;
 	struct snd_kctl_ioctl *p;
 	void __user *argp = (void __user *)arg;
 	int __user *ip = argp;
@@ -1232,8 +1217,7 @@
 #endif
 	}
 	down_read(&snd_ioctl_rwsem);
-	list_for_each(list, &snd_control_ioctls) {
-		p = list_entry(list, struct snd_kctl_ioctl, list);
+	list_for_each_entry(p, &snd_control_ioctls, list) {
 		err = p->fioctl(card, ctl, cmd, arg);
 		if (err != -ENOIOCTLCMD) {
 			up_read(&snd_ioctl_rwsem);
@@ -1357,13 +1341,11 @@
 static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn,
 				     struct list_head *lists)
 {
-	struct list_head *list;
 	struct snd_kctl_ioctl *p;
 
 	snd_assert(fcn != NULL, return -EINVAL);
 	down_write(&snd_ioctl_rwsem);
-	list_for_each(list, lists) {
-		p = list_entry(list, struct snd_kctl_ioctl, list);
+	list_for_each_entry(p, lists, list) {
 		if (p->fioctl == fcn) {
 			list_del(&p->list);
 			up_write(&snd_ioctl_rwsem);
@@ -1416,7 +1398,7 @@
  *  INIT PART
  */
 
-static struct file_operations snd_ctl_f_ops =
+static const struct file_operations snd_ctl_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		snd_ctl_read,
@@ -1453,7 +1435,6 @@
 static int snd_ctl_dev_disconnect(struct snd_device *device)
 {
 	struct snd_card *card = device->device_data;
-	struct list_head *flist;
 	struct snd_ctl_file *ctl;
 	int err, cardnum;
 
@@ -1462,8 +1443,7 @@
 	snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
 
 	down_read(&card->controls_rwsem);
-	list_for_each(flist, &card->ctl_files) {
-		ctl = snd_ctl_file(flist);
+	list_for_each_entry(ctl, &card->ctl_files, list) {
 		wake_up(&ctl->change_sleep);
 		kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
 	}
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index ab48962..9311ca3 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -392,7 +392,7 @@
 static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct snd_ctl_file *ctl;
-	struct list_head *list;
+	struct snd_kctl_ioctl *p;
 	void __user *argp = compat_ptr(arg);
 	int err;
 
@@ -427,8 +427,7 @@
 	}
 
 	down_read(&snd_ioctl_rwsem);
-	list_for_each(list, &snd_control_compat_ioctls) {
-		struct snd_kctl_ioctl *p = list_entry(list, struct snd_kctl_ioctl, list);
+	list_for_each_entry(p, &snd_control_compat_ioctls, list) {
 		if (p->fioctl) {
 			err = p->fioctl(ctl->card, ctl, cmd, arg);
 			if (err != -ENOIOCTLCMD) {
diff --git a/sound/core/device.c b/sound/core/device.c
index ccb2581..5858b02 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -79,13 +79,11 @@
  */
 int snd_device_free(struct snd_card *card, void *device_data)
 {
-	struct list_head *list;
 	struct snd_device *dev;
 	
 	snd_assert(card != NULL, return -ENXIO);
 	snd_assert(device_data != NULL, return -ENXIO);
-	list_for_each(list, &card->devices) {
-		dev = snd_device(list);
+	list_for_each_entry(dev, &card->devices, list) {
 		if (dev->device_data != device_data)
 			continue;
 		/* unlink */
@@ -124,13 +122,11 @@
  */
 int snd_device_disconnect(struct snd_card *card, void *device_data)
 {
-	struct list_head *list;
 	struct snd_device *dev;
 
 	snd_assert(card != NULL, return -ENXIO);
 	snd_assert(device_data != NULL, return -ENXIO);
-	list_for_each(list, &card->devices) {
-		dev = snd_device(list);
+	list_for_each_entry(dev, &card->devices, list) {
 		if (dev->device_data != device_data)
 			continue;
 		if (dev->state == SNDRV_DEV_REGISTERED &&
@@ -161,14 +157,12 @@
  */
 int snd_device_register(struct snd_card *card, void *device_data)
 {
-	struct list_head *list;
 	struct snd_device *dev;
 	int err;
 
 	snd_assert(card != NULL, return -ENXIO);
 	snd_assert(device_data != NULL, return -ENXIO);
-	list_for_each(list, &card->devices) {
-		dev = snd_device(list);
+	list_for_each_entry(dev, &card->devices, list) {
 		if (dev->device_data != device_data)
 			continue;
 		if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
@@ -192,13 +186,11 @@
  */
 int snd_device_register_all(struct snd_card *card)
 {
-	struct list_head *list;
 	struct snd_device *dev;
 	int err;
 	
 	snd_assert(card != NULL, return -ENXIO);
-	list_for_each(list, &card->devices) {
-		dev = snd_device(list);
+	list_for_each_entry(dev, &card->devices, list) {
 		if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
 			if ((err = dev->ops->dev_register(dev)) < 0)
 				return err;
@@ -215,12 +207,10 @@
 int snd_device_disconnect_all(struct snd_card *card)
 {
 	struct snd_device *dev;
-	struct list_head *list;
 	int err = 0;
 
 	snd_assert(card != NULL, return -ENXIO);
-	list_for_each(list, &card->devices) {
-		dev = snd_device(list);
+	list_for_each_entry(dev, &card->devices, list) {
 		if (snd_device_disconnect(card, dev->device_data) < 0)
 			err = -ENXIO;
 	}
@@ -234,7 +224,6 @@
 int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd)
 {
 	struct snd_device *dev;
-	struct list_head *list;
 	int err;
 	unsigned int range_low, range_high;
 
@@ -242,8 +231,7 @@
 	range_low = cmd * SNDRV_DEV_TYPE_RANGE_SIZE;
 	range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1;
       __again:
-	list_for_each(list, &card->devices) {
-		dev = snd_device(list);		
+	list_for_each_entry(dev, &card->devices, list) {
 		if (dev->type >= range_low && dev->type <= range_high) {
 			if ((err = snd_device_free(card, dev->device_data)) < 0)
 				return err;
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 46b4768..96ffdf1 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -47,14 +47,11 @@
 
 static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device)
 {
-	struct list_head *p;
 	struct snd_hwdep *hwdep;
 
-	list_for_each(p, &snd_hwdep_devices) {
-		hwdep = list_entry(p, struct snd_hwdep, list);
+	list_for_each_entry(hwdep, &snd_hwdep_devices, list)
 		if (hwdep->card == card && hwdep->device == device)
 			return hwdep;
-	}
 	return NULL;
 }
 
@@ -159,15 +156,16 @@
 	int err = -ENXIO;
 	struct snd_hwdep *hw = file->private_data;
 	struct module *mod = hw->card->module;
+
 	mutex_lock(&hw->open_mutex);
-	if (hw->ops.release) {
+	if (hw->ops.release)
 		err = hw->ops.release(hw, file);
-		wake_up(&hw->open_wait);
-	}
 	if (hw->used > 0)
 		hw->used--;
-	snd_card_file_remove(hw->card, file);
 	mutex_unlock(&hw->open_mutex);
+	wake_up(&hw->open_wait);
+
+	snd_card_file_remove(hw->card, file);
 	module_put(mod);
 	return err;
 }
@@ -319,7 +317,7 @@
 
  */
 
-static struct file_operations snd_hwdep_f_ops =
+static const struct file_operations snd_hwdep_f_ops =
 {
 	.owner = 	THIS_MODULE,
 	.llseek =	snd_hwdep_llseek,
@@ -468,15 +466,12 @@
 static void snd_hwdep_proc_read(struct snd_info_entry *entry,
 				struct snd_info_buffer *buffer)
 {
-	struct list_head *p;
 	struct snd_hwdep *hwdep;
 
 	mutex_lock(&register_mutex);
-	list_for_each(p, &snd_hwdep_devices) {
-		hwdep = list_entry(p, struct snd_hwdep, list);
+	list_for_each_entry(hwdep, &snd_hwdep_devices, list)
 		snd_iprintf(buffer, "%02i-%02i: %s\n",
 			    hwdep->card->number, hwdep->device, hwdep->name);
-	}
 	mutex_unlock(&register_mutex);
 }
 
diff --git a/sound/core/info.c b/sound/core/info.c
index 54591e2..bf6dbf9 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -507,7 +507,7 @@
 	return -ENXIO;
 }
 
-static struct file_operations snd_info_entry_operations =
+static const struct file_operations snd_info_entry_operations =
 {
 	.owner =		THIS_MODULE,
 	.llseek =		snd_info_entry_llseek,
diff --git a/sound/core/init.c b/sound/core/init.c
index a4cc6b1..4a431e3 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -36,7 +36,7 @@
 static DEFINE_SPINLOCK(shutdown_lock);
 static LIST_HEAD(shutdown_files);
 
-static struct file_operations snd_shutdown_f_ops;
+static const struct file_operations snd_shutdown_f_ops;
 
 static unsigned int snd_cards_lock;	/* locked for registering/using */
 struct snd_card *snd_cards[SNDRV_CARDS];
@@ -114,22 +114,28 @@
 	if (idx < 0) {
 		int idx2;
 		for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
+			/* idx == -1 == 0xffff means: take any free slot */
 			if (~snd_cards_lock & idx & 1<<idx2) {
 				idx = idx2;
 				if (idx >= snd_ecards_limit)
 					snd_ecards_limit = idx + 1;
 				break;
 			}
-	} else if (idx < snd_ecards_limit) {
-		if (snd_cards_lock & (1 << idx))
-			err = -ENODEV;	/* invalid */
-	} else if (idx < SNDRV_CARDS)
-		snd_ecards_limit = idx + 1; /* increase the limit */
-	else
-		err = -ENODEV;
+	} else {
+		 if (idx < snd_ecards_limit) {
+			if (snd_cards_lock & (1 << idx))
+				err = -EBUSY;	/* invalid */
+		} else {
+			if (idx < SNDRV_CARDS)
+				snd_ecards_limit = idx + 1; /* increase the limit */
+			else
+				err = -ENODEV;
+		}
+	}
 	if (idx < 0 || err < 0) {
 		mutex_unlock(&snd_card_mutex);
-		snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i)\n", idx, snd_ecards_limit - 1);
+		snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",
+			 idx, snd_ecards_limit - 1, err);
 		goto __error;
 	}
 	snd_cards_lock |= 1 << idx;		/* lock it */
@@ -238,7 +244,7 @@
 	return -ENODEV;
 }
 
-static struct file_operations snd_shutdown_f_ops =
+static const struct file_operations snd_shutdown_f_ops =
 {
 	.owner = 	THIS_MODULE,
 	.llseek =	snd_disconnect_llseek,
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index bc0bd09..f057430 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -406,19 +406,17 @@
  */
 size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
 {
-	struct list_head *p;
 	struct snd_mem_list *mem;
 
 	snd_assert(dmab, return 0);
 
 	mutex_lock(&list_mutex);
-	list_for_each(p, &mem_list_head) {
-		mem = list_entry(p, struct snd_mem_list, list);
+	list_for_each_entry(mem, &mem_list_head, list) {
 		if (mem->id == id &&
 		    (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
 		     ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
 			struct device *dev = dmab->dev.dev;
-			list_del(p);
+			list_del(&mem->list);
 			*dmab = mem->buffer;
 			if (dmab->dev.dev == NULL)
 				dmab->dev.dev = dev;
@@ -488,7 +486,6 @@
 {
 	int len = 0;
 	long pages = snd_allocated_pages >> (PAGE_SHIFT-12);
-	struct list_head *p;
 	struct snd_mem_list *mem;
 	int devno;
 	static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" };
@@ -498,8 +495,7 @@
 			"pages  : %li bytes (%li pages per %likB)\n",
 			pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
 	devno = 0;
-	list_for_each(p, &mem_list_head) {
-		mem = list_entry(p, struct snd_mem_list, list);
+	list_for_each_entry(mem, &mem_list_head, list) {
 		devno++;
 		len += snprintf(page + len, count - len,
 				"buffer %d : ID %08x : type %s\n",
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 03fc711..f78cd00 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -21,7 +21,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/ioport.h>
 #include <sound/core.h>
@@ -78,3 +77,31 @@
 
 EXPORT_SYMBOL(snd_verbose_printd);
 #endif
+
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+/**
+ * snd_pci_quirk_lookup - look up a PCI SSID quirk list
+ * @pci: pci_dev handle
+ * @list: quirk list, terminated by a null entry
+ *
+ * Look through the given quirk list and finds a matching entry
+ * with the same PCI SSID.  When subdevice is 0, all subdevice
+ * values may match.
+ *
+ * Returns the matched entry pointer, or NULL if nothing matched.
+ */
+const struct snd_pci_quirk *
+snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list)
+{
+	const struct snd_pci_quirk *q;
+
+	for (q = list; q->subvendor; q++)
+		if (q->subvendor == pci->subsystem_vendor &&
+		    (!q->subdevice || q->subdevice == pci->subsystem_device))
+			return q;
+	return NULL;
+}
+
+EXPORT_SYMBOL(snd_pci_quirk_lookup);
+#endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 3391f2a9..74a2923 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -390,7 +390,7 @@
  *  REGISTRATION PART
  */
 
-static struct file_operations snd_mixer_oss_f_ops =
+static const struct file_operations snd_mixer_oss_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.open =		snd_mixer_oss_open,
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 786a82e..c4744bb 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2889,7 +2889,7 @@
  *  ENTRY functions
  */
 
-static struct file_operations snd_pcm_oss_f_reg =
+static const struct file_operations snd_pcm_oss_f_reg =
 {
 	.owner =	THIS_MODULE,
 	.read =		snd_pcm_oss_read,
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 8e01898..2743414 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -45,11 +45,9 @@
 
 static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
 {
-	struct list_head *p;
 	struct snd_pcm *pcm;
 
-	list_for_each(p, &snd_pcm_devices) {
-		pcm = list_entry(p, struct snd_pcm, list);
+	list_for_each_entry(pcm, &snd_pcm_devices, list) {
 		if (pcm->card == card && pcm->device == device)
 			return pcm;
 	}
@@ -782,7 +780,6 @@
 	struct snd_pcm_runtime *runtime;
 	struct snd_ctl_file *kctl;
 	struct snd_card *card;
-	struct list_head *list;
 	int prefer_subdevice = -1;
 	size_t size;
 
@@ -795,8 +792,7 @@
 
 	card = pcm->card;
 	down_read(&card->controls_rwsem);
-	list_for_each(list, &card->ctl_files) {
-		kctl = snd_ctl_file(list);
+	list_for_each_entry(kctl, &card->ctl_files, list) {
 		if (kctl->pid == current->pid) {
 			prefer_subdevice = kctl->prefer_pcm_subdevice;
 			if (prefer_subdevice != -1)
@@ -941,9 +937,10 @@
 {
 	int cidx, err;
 	struct snd_pcm_substream *substream;
-	struct list_head *list;
+	struct snd_pcm_notify *notify;
 	char str[16];
 	struct snd_pcm *pcm = device->device_data;
+	struct device *dev;
 
 	snd_assert(pcm != NULL && device != NULL, return -ENXIO);
 	mutex_lock(&register_mutex);
@@ -966,11 +963,18 @@
 			devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
 			break;
 		}
-		if ((err = snd_register_device(devtype, pcm->card,
-					       pcm->device,
-					       &snd_pcm_f_ops[cidx],
-					       pcm, str)) < 0)
-		{
+		/* device pointer to use, pcm->dev takes precedence if
+		 * it is assigned, otherwise fall back to card's device
+		 * if possible */
+		dev = pcm->dev;
+		if (!dev)
+			dev = snd_card_get_device_link(pcm->card);
+		/* register pcm */
+		err = snd_register_device_for_dev(devtype, pcm->card,
+						  pcm->device,
+						  &snd_pcm_f_ops[cidx],
+						  pcm, str, dev);
+		if (err < 0) {
 			list_del(&pcm->list);
 			mutex_unlock(&register_mutex);
 			return err;
@@ -980,11 +984,10 @@
 		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
 			snd_pcm_timer_init(substream);
 	}
-	list_for_each(list, &snd_pcm_notify_list) {
-		struct snd_pcm_notify *notify;
-		notify = list_entry(list, struct snd_pcm_notify, list);
+
+	list_for_each_entry(notify, &snd_pcm_notify_list, list)
 		notify->n_register(pcm);
-	}
+
 	mutex_unlock(&register_mutex);
 	return 0;
 }
@@ -1027,7 +1030,7 @@
 
 int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
 {
-	struct list_head *p;
+	struct snd_pcm *pcm;
 
 	snd_assert(notify != NULL &&
 		   notify->n_register != NULL &&
@@ -1036,13 +1039,12 @@
 	mutex_lock(&register_mutex);
 	if (nfree) {
 		list_del(&notify->list);
-		list_for_each(p, &snd_pcm_devices)
-			notify->n_unregister(list_entry(p,
-							struct snd_pcm, list));
+		list_for_each_entry(pcm, &snd_pcm_devices, list)
+			notify->n_unregister(pcm);
 	} else {
 		list_add_tail(&notify->list, &snd_pcm_notify_list);
-		list_for_each(p, &snd_pcm_devices)
-			notify->n_register(list_entry(p, struct snd_pcm, list));
+		list_for_each_entry(pcm, &snd_pcm_devices, list)
+			notify->n_register(pcm);
 	}
 	mutex_unlock(&register_mutex);
 	return 0;
@@ -1058,12 +1060,10 @@
 static void snd_pcm_proc_read(struct snd_info_entry *entry,
 			      struct snd_info_buffer *buffer)
 {
-	struct list_head *p;
 	struct snd_pcm *pcm;
 
 	mutex_lock(&register_mutex);
-	list_for_each(p, &snd_pcm_devices) {
-		pcm = list_entry(p, struct snd_pcm, list);
+	list_for_each_entry(pcm, &snd_pcm_devices, list) {
 		snd_iprintf(buffer, "%02i-%02i: %s : %s",
 			    pcm->card->number, pcm->device, pcm->id, pcm->name);
 		if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index b336797..9fefcaa 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -781,6 +781,11 @@
 {
         unsigned int k;
 	int changed = 0;
+
+	if (!count) {
+		i->empty = 1;
+		return -EINVAL;
+	}
         for (k = 0; k < count; k++) {
 		if (mask && !(mask & (1 << k)))
 			continue;
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index be030cb..95b1b2f 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -101,6 +101,8 @@
 {
 	snd_pcm_lib_preallocate_dma_free(substream);
 #ifdef CONFIG_SND_VERBOSE_PROCFS
+	snd_info_free_entry(substream->proc_prealloc_max_entry);
+	substream->proc_prealloc_max_entry = NULL;
 	snd_info_free_entry(substream->proc_prealloc_entry);
 	substream->proc_prealloc_entry = NULL;
 #endif
@@ -142,6 +144,18 @@
 }
 
 /*
+ * read callback for prealloc_max proc file
+ *
+ * prints the maximum allowed size in kB.
+ */
+static void snd_pcm_lib_preallocate_max_proc_read(struct snd_info_entry *entry,
+						  struct snd_info_buffer *buffer)
+{
+	struct snd_pcm_substream *substream = entry->private_data;
+	snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_max / 1024);
+}
+
+/*
  * write callback for prealloc proc file
  *
  * accepts the preallocation size in kB.
@@ -203,6 +217,15 @@
 		}
 	}
 	substream->proc_prealloc_entry = entry;
+	if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max", substream->proc_root)) != NULL) {
+		entry->c.text.read = snd_pcm_lib_preallocate_max_proc_read;
+		entry->private_data = substream;
+		if (snd_info_register(entry) < 0) {
+			snd_info_free_entry(entry);
+			entry = NULL;
+		}
+	}
+	substream->proc_prealloc_max_entry = entry;
 }
 
 #else /* !CONFIG_SND_VERBOSE_PROCFS */
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index b52e893..3e276fc 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3424,7 +3424,7 @@
  *  Register section
  */
 
-struct file_operations snd_pcm_f_ops[2] = {
+const struct file_operations snd_pcm_f_ops[2] = {
 	{
 		.owner =		THIS_MODULE,
 		.write =		snd_pcm_write,
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 0f055bf..d14dcbb 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -61,14 +61,11 @@
 
 static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
 {
-	struct list_head *p;
 	struct snd_rawmidi *rawmidi;
 
-	list_for_each(p, &snd_rawmidi_devices) {
-		rawmidi = list_entry(p, struct snd_rawmidi, list);
+	list_for_each_entry(rawmidi, &snd_rawmidi_devices, list)
 		if (rawmidi->card == card && rawmidi->device == device)
 			return rawmidi;
-	}
 	return NULL;
 }
 
@@ -389,7 +386,6 @@
 	struct snd_rawmidi *rmidi;
 	struct snd_rawmidi_file *rawmidi_file;
 	wait_queue_t wait;
-	struct list_head *list;
 	struct snd_ctl_file *kctl;
 
 	if (maj == snd_major) {
@@ -426,8 +422,7 @@
 	while (1) {
 		subdevice = -1;
 		down_read(&card->controls_rwsem);
-		list_for_each(list, &card->ctl_files) {
-			kctl = snd_ctl_file(list);
+		list_for_each_entry(kctl, &card->ctl_files, list) {
 			if (kctl->pid == current->pid) {
 				subdevice = kctl->prefer_rawmidi_subdevice;
 				if (subdevice != -1)
@@ -575,7 +570,6 @@
 	struct snd_rawmidi *rmidi;
 	struct snd_rawmidi_str *pstr;
 	struct snd_rawmidi_substream *substream;
-	struct list_head *list;
 
 	mutex_lock(&register_mutex);
 	rmidi = snd_rawmidi_search(card, info->device);
@@ -589,8 +583,7 @@
 		return -ENOENT;
 	if (info->subdevice >= pstr->substream_count)
 		return -ENXIO;
-	list_for_each(list, &pstr->substreams) {
-		substream = list_entry(list, struct snd_rawmidi_substream, list);
+	list_for_each_entry(substream, &pstr->substreams, list) {
 		if ((unsigned int)substream->number == info->subdevice)
 			return snd_rawmidi_info(substream, info);
 	}
@@ -1313,14 +1306,14 @@
 	struct snd_rawmidi *rmidi;
 	struct snd_rawmidi_substream *substream;
 	struct snd_rawmidi_runtime *runtime;
-	struct list_head *list;
 
 	rmidi = entry->private_data;
 	snd_iprintf(buffer, "%s\n\n", rmidi->name);
 	mutex_lock(&rmidi->open_mutex);
 	if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) {
-		list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
-			substream = list_entry(list, struct snd_rawmidi_substream, list);
+		list_for_each_entry(substream,
+				    &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
+				    list) {
 			snd_iprintf(buffer,
 				    "Output %d\n"
 				    "  Tx bytes     : %lu\n",
@@ -1339,8 +1332,9 @@
 		}
 	}
 	if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT) {
-		list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
-			substream = list_entry(list, struct snd_rawmidi_substream, list);
+		list_for_each_entry(substream,
+				    &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams,
+				    list) {
 			snd_iprintf(buffer,
 				    "Input %d\n"
 				    "  Rx bytes     : %lu\n",
@@ -1365,7 +1359,7 @@
  *  Register functions
  */
 
-static struct file_operations snd_rawmidi_f_ops =
+static const struct file_operations snd_rawmidi_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		snd_rawmidi_read,
@@ -1625,13 +1619,10 @@
 void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,
 			 struct snd_rawmidi_ops *ops)
 {
-	struct list_head *list;
 	struct snd_rawmidi_substream *substream;
 	
-	list_for_each(list, &rmidi->streams[stream].substreams) {
-		substream = list_entry(list, struct snd_rawmidi_substream, list);
+	list_for_each_entry(substream, &rmidi->streams[stream].substreams, list)
 		substream->ops = ops;
-	}
 }
 
 /*
diff --git a/sound/core/seq/instr/ainstr_fm.c b/sound/core/seq/instr/ainstr_fm.c
index b09babf..f80fab8 100644
--- a/sound/core/seq/instr/ainstr_fm.c
+++ b/sound/core/seq/instr/ainstr_fm.c
@@ -20,7 +20,6 @@
  
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <sound/core.h>
 #include <sound/ainstr_fm.h>
 #include <sound/initval.h>
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c
index 3c31038..c640e1cf 100644
--- a/sound/core/seq/instr/ainstr_gf1.c
+++ b/sound/core/seq/instr/ainstr_gf1.c
@@ -20,7 +20,6 @@
  
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/ainstr_gf1.h>
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c
index 7f8df19..5367bae 100644
--- a/sound/core/seq/instr/ainstr_iw.c
+++ b/sound/core/seq/instr/ainstr_iw.c
@@ -20,7 +20,6 @@
  
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/ainstr_iw.h>
diff --git a/sound/core/seq/instr/ainstr_simple.c b/sound/core/seq/instr/ainstr_simple.c
index 6d6ffec..ac717be 100644
--- a/sound/core/seq/instr/ainstr_simple.c
+++ b/sound/core/seq/instr/ainstr_simple.c
@@ -20,7 +20,6 @@
  
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/ainstr_simple.h>
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 92858cf..2eb9873 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -208,7 +208,7 @@
  * registration of sequencer minor device
  */
 
-static struct file_operations seq_oss_f_ops =
+static const struct file_operations seq_oss_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		odev_read,
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 532a660..694efe8 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -659,7 +659,6 @@
 	int err = 0, num_ev = 0;
 	struct snd_seq_event event_saved;
 	struct snd_seq_client_port *src_port;
-	struct list_head *p;
 	struct snd_seq_port_subs_info *grp;
 
 	src_port = snd_seq_port_use_ptr(client, event->source.port);
@@ -674,8 +673,7 @@
 		read_lock(&grp->list_lock);
 	else
 		down_read(&grp->list_mutex);
-	list_for_each(p, &grp->list_head) {
-		subs = list_entry(p, struct snd_seq_subscribers, src_list);
+	list_for_each_entry(subs, &grp->list_head, src_list) {
 		event->dest = subs->info.dest;
 		if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
 			/* convert time according to flag with subscription */
@@ -709,15 +707,14 @@
 {
 	int num_ev = 0, err = 0;
 	struct snd_seq_client *dest_client;
-	struct list_head *p;
+	struct snd_seq_client_port *port;
 
 	dest_client = get_event_dest_client(event, SNDRV_SEQ_FILTER_BROADCAST);
 	if (dest_client == NULL)
 		return 0; /* no matching destination */
 
 	read_lock(&dest_client->ports_lock);
-	list_for_each(p, &dest_client->ports_list_head) {
-		struct snd_seq_client_port *port = list_entry(p, struct snd_seq_client_port, list);
+	list_for_each_entry(port, &dest_client->ports_list_head, list) {
 		event->dest.port = port->addr.port;
 		/* pass NULL as source client to avoid error bounce */
 		err = snd_seq_deliver_single_event(NULL, event,
@@ -2473,11 +2470,10 @@
 static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
 				    struct snd_seq_client *client)
 {
-	struct list_head *l;
+	struct snd_seq_client_port *p;
 
 	mutex_lock(&client->ports_mutex);
-	list_for_each(l, &client->ports_list_head) {
-		struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
+	list_for_each_entry(p, &client->ports_list_head, list) {
 		snd_iprintf(buffer, "  Port %3d : \"%s\" (%c%c%c%c)\n",
 			    p->addr.port, p->name,
 			    FLAG_PERM_RD(p->capability),
@@ -2542,7 +2538,7 @@
  *  REGISTRATION PART
  */
 
-static struct file_operations snd_seq_f_ops =
+static const struct file_operations snd_seq_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		snd_seq_read,
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index b79d011..37852cd 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -106,11 +106,10 @@
 static void snd_seq_device_info(struct snd_info_entry *entry,
 				struct snd_info_buffer *buffer)
 {
-	struct list_head *head;
+	struct ops_list *ops;
 
 	mutex_lock(&ops_mutex);
-	list_for_each(head, &opslist) {
-		struct ops_list *ops = list_entry(head, struct ops_list, list);
+	list_for_each_entry(ops, &opslist, list) {
 		snd_iprintf(buffer, "snd-%s%s%s%s,%d\n",
 				ops->id,
 				ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""),
@@ -143,7 +142,7 @@
 void snd_seq_device_load_drivers(void)
 {
 #ifdef CONFIG_KMOD
-	struct list_head *head;
+	struct ops_list *ops;
 
 	/* Calling request_module during module_init()
 	 * may cause blocking.
@@ -155,8 +154,7 @@
 		return;
 
 	mutex_lock(&ops_mutex);
-	list_for_each(head, &opslist) {
-		struct ops_list *ops = list_entry(head, struct ops_list, list);
+	list_for_each_entry(ops, &opslist, list) {
 		if (! (ops->driver & DRIVER_LOADED) &&
 		    ! (ops->driver & DRIVER_REQUESTED)) {
 			ops->used++;
@@ -314,8 +312,8 @@
 int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
 				   int argsize)
 {
-	struct list_head *head;
 	struct ops_list *ops;
+	struct snd_seq_device *dev;
 
 	if (id == NULL || entry == NULL ||
 	    entry->init_device == NULL || entry->free_device == NULL)
@@ -341,8 +339,7 @@
 	ops->argsize = argsize;
 
 	/* initialize existing devices if necessary */
-	list_for_each(head, &ops->dev_list) {
-		struct snd_seq_device *dev = list_entry(head, struct snd_seq_device, list);
+	list_for_each_entry(dev, &ops->dev_list, list) {
 		init_device(dev, ops);
 	}
 	mutex_unlock(&ops->reg_mutex);
@@ -394,8 +391,8 @@
  */
 int snd_seq_device_unregister_driver(char *id)
 {
-	struct list_head *head;
 	struct ops_list *ops;
+	struct snd_seq_device *dev;
 
 	ops = find_driver(id, 0);
 	if (ops == NULL)
@@ -411,8 +408,7 @@
 	/* close and release all devices associated with this driver */
 	mutex_lock(&ops->reg_mutex);
 	ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */
-	list_for_each(head, &ops->dev_list) {
-		struct snd_seq_device *dev = list_entry(head, struct snd_seq_device, list);
+	list_for_each_entry(dev, &ops->dev_list, list) {
 		free_device(dev, ops);
 	}
 
@@ -512,11 +508,10 @@
  */
 static struct ops_list * find_driver(char *id, int create_if_empty)
 {
-	struct list_head *head;
+	struct ops_list *ops;
 
 	mutex_lock(&ops_mutex);
-	list_for_each(head, &opslist) {
-		struct ops_list *ops = list_entry(head, struct ops_list, list);
+	list_for_each_entry(ops, &opslist, list) {
 		if (strcmp(ops->id, id) == 0) {
 			ops->used++;
 			mutex_unlock(&ops_mutex);
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 8c64b58..eefd1cf 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -59,14 +59,12 @@
 struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client,
 						 int num)
 {
-	struct list_head *p;
 	struct snd_seq_client_port *port;
 
 	if (client == NULL)
 		return NULL;
 	read_lock(&client->ports_lock);
-	list_for_each(p, &client->ports_list_head) {
-		port = list_entry(p, struct snd_seq_client_port, list);
+	list_for_each_entry(port, &client->ports_list_head, list) {
 		if (port->addr.port == num) {
 			if (port->closing)
 				break; /* deleting now */
@@ -85,14 +83,12 @@
 						       struct snd_seq_port_info *pinfo)
 {
 	int num;
-	struct list_head *p;
 	struct snd_seq_client_port *port, *found;
 
 	num = pinfo->addr.port;
 	found = NULL;
 	read_lock(&client->ports_lock);
-	list_for_each(p, &client->ports_list_head) {
-		port = list_entry(p, struct snd_seq_client_port, list);
+	list_for_each_entry(port, &client->ports_list_head, list) {
 		if (port->addr.port < num)
 			continue;
 		if (port->addr.port == num) {
@@ -131,8 +127,7 @@
 						int port)
 {
 	unsigned long flags;
-	struct snd_seq_client_port *new_port;
-	struct list_head *l;
+	struct snd_seq_client_port *new_port, *p;
 	int num = -1;
 	
 	/* sanity check */
@@ -161,15 +156,14 @@
 	num = port >= 0 ? port : 0;
 	mutex_lock(&client->ports_mutex);
 	write_lock_irqsave(&client->ports_lock, flags);
-	list_for_each(l, &client->ports_list_head) {
-		struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
+	list_for_each_entry(p, &client->ports_list_head, list) {
 		if (p->addr.port > num)
 			break;
 		if (port < 0) /* auto-probe mode */
 			num = p->addr.port + 1;
 	}
 	/* insert the new port */
-	list_add_tail(&new_port->list, l);
+	list_add_tail(&new_port->list, &p->list);
 	client->num_ports++;
 	new_port->addr.port = num;	/* store the port number in the port */
 	write_unlock_irqrestore(&client->ports_lock, flags);
@@ -251,9 +245,9 @@
 				list_del(&subs->dest_list);
 			else
 				list_del(&subs->src_list);
+			up_write(&agrp->list_mutex);
 			unsubscribe_port(c, aport, agrp, &subs->info, 1);
 			kfree(subs);
-			up_write(&agrp->list_mutex);
 			snd_seq_port_unlock(aport);
 			snd_seq_client_unlock(c);
 		}
@@ -287,16 +281,14 @@
 int snd_seq_delete_port(struct snd_seq_client *client, int port)
 {
 	unsigned long flags;
-	struct list_head *l;
-	struct snd_seq_client_port *found = NULL;
+	struct snd_seq_client_port *found = NULL, *p;
 
 	mutex_lock(&client->ports_mutex);
 	write_lock_irqsave(&client->ports_lock, flags);
-	list_for_each(l, &client->ports_list_head) {
-		struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
+	list_for_each_entry(p, &client->ports_list_head, list) {
 		if (p->addr.port == port) {
 			/* ok found.  delete from the list at first */
-			list_del(l);
+			list_del(&p->list);
 			client->num_ports--;
 			found = p;
 			break;
@@ -314,7 +306,8 @@
 int snd_seq_delete_all_ports(struct snd_seq_client *client)
 {
 	unsigned long flags;
-	struct list_head deleted_list, *p, *n;
+	struct list_head deleted_list;
+	struct snd_seq_client_port *port, *tmp;
 	
 	/* move the port list to deleted_list, and
 	 * clear the port list in the client data.
@@ -331,9 +324,8 @@
 	write_unlock_irqrestore(&client->ports_lock, flags);
 
 	/* remove each port in deleted_list */
-	list_for_each_safe(p, n, &deleted_list) {
-		struct snd_seq_client_port *port = list_entry(p, struct snd_seq_client_port, list);
-		list_del(p);
+	list_for_each_entry_safe(port, tmp, &deleted_list, list) {
+		list_del(&port->list);
 		snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port);
 		port_delete(client, port);
 	}
@@ -500,8 +492,7 @@
 {
 	struct snd_seq_port_subs_info *src = &src_port->c_src;
 	struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
-	struct snd_seq_subscribers *subs;
-	struct list_head *p;
+	struct snd_seq_subscribers *subs, *s;
 	int err, src_called = 0;
 	unsigned long flags;
 	int exclusive;
@@ -525,13 +516,11 @@
 		if (src->exclusive || dest->exclusive)
 			goto __error;
 		/* check whether already exists */
-		list_for_each(p, &src->list_head) {
-			struct snd_seq_subscribers *s = list_entry(p, struct snd_seq_subscribers, src_list);
+		list_for_each_entry(s, &src->list_head, src_list) {
 			if (match_subs_info(info, &s->info))
 				goto __error;
 		}
-		list_for_each(p, &dest->list_head) {
-			struct snd_seq_subscribers *s = list_entry(p, struct snd_seq_subscribers, dest_list);
+		list_for_each_entry(s, &dest->list_head, dest_list) {
 			if (match_subs_info(info, &s->info))
 				goto __error;
 		}
@@ -582,7 +571,6 @@
 	struct snd_seq_port_subs_info *src = &src_port->c_src;
 	struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
 	struct snd_seq_subscribers *subs;
-	struct list_head *p;
 	int err = -ENOENT;
 	unsigned long flags;
 
@@ -590,8 +578,7 @@
 	down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
 
 	/* look for the connection */
-	list_for_each(p, &src->list_head) {
-		subs = list_entry(p, struct snd_seq_subscribers, src_list);
+	list_for_each_entry(subs, &src->list_head, src_list) {
 		if (match_subs_info(info, &subs->info)) {
 			write_lock_irqsave(&src->list_lock, flags);
 			// write_lock(&dest->list_lock);  // no lock yet
@@ -620,12 +607,10 @@
 struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
 							  struct snd_seq_addr *dest_addr)
 {
-	struct list_head *p;
 	struct snd_seq_subscribers *s, *found = NULL;
 
 	down_read(&src_grp->list_mutex);
-	list_for_each(p, &src_grp->list_head) {
-		s = list_entry(p, struct snd_seq_subscribers, src_list);
+	list_for_each_entry(s, &src_grp->list_head, src_list) {
 		if (addr_match(dest_addr, &s->info.dest)) {
 			found = s;
 			break;
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 0cfa06c..061a7c6 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -38,7 +38,6 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/wait.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/rawmidi.h>
@@ -81,13 +80,11 @@
 					 struct snd_seq_event *ev)
 {
 	struct snd_virmidi *vmidi;
-	struct list_head *list;
 	unsigned char msg[4];
 	int len;
 
 	read_lock(&rdev->filelist_lock);
-	list_for_each(list, &rdev->filelist) {
-		vmidi = list_entry(list, struct snd_virmidi, list);
+	list_for_each_entry(vmidi, &rdev->filelist, list) {
 		if (!vmidi->trigger)
 			continue;
 		if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 82a61c6..70600df 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -168,7 +168,7 @@
 	return err;
 }
 
-static struct file_operations snd_fops =
+static const struct file_operations snd_fops =
 {
 	.owner =	THIS_MODULE,
 	.open =		snd_open
@@ -219,26 +219,27 @@
 #endif
 
 /**
- * snd_register_device - Register the ALSA device file for the card
+ * snd_register_device_for_dev - Register the ALSA device file for the card
  * @type: the device type, SNDRV_DEVICE_TYPE_XXX
  * @card: the card instance
  * @dev: the device index
  * @f_ops: the file operations
  * @private_data: user pointer for f_ops->open()
  * @name: the device file name
+ * @device: the &struct device to link this new device to
  *
  * Registers an ALSA device file for the given card.
  * The operators have to be set in reg parameter.
  *
- * Retrurns zero if successful, or a negative error code on failure.
+ * Returns zero if successful, or a negative error code on failure.
  */
-int snd_register_device(int type, struct snd_card *card, int dev,
-			const struct file_operations *f_ops, void *private_data,
-			const char *name)
+int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
+				const struct file_operations *f_ops,
+				void *private_data,
+				const char *name, struct device *device)
 {
 	int minor;
 	struct snd_minor *preg;
-	struct device *device = snd_card_get_device_link(card);
 
 	snd_assert(name, return -EINVAL);
 	preg = kmalloc(sizeof *preg, GFP_KERNEL);
@@ -272,7 +273,7 @@
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_register_device);
+EXPORT_SYMBOL(snd_register_device_for_dev);
 
 /* find the matching minor record
  * return the index of snd_minor, or -1 if not found
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 10a79ae..160e40e 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -35,9 +35,6 @@
 #include <sound/minors.h>
 #include <sound/initval.h>
 #include <linux/kmod.h>
-#ifdef CONFIG_KERNELD
-#include <linux/kerneld.h>
-#endif
 
 #if defined(CONFIG_SND_HPET) || defined(CONFIG_SND_HPET_MODULE)
 #define DEFAULT_TIMER_LIMIT 3
@@ -130,11 +127,8 @@
 static struct snd_timer *snd_timer_find(struct snd_timer_id *tid)
 {
 	struct snd_timer *timer = NULL;
-	struct list_head *p;
 
-	list_for_each(p, &snd_timer_list) {
-		timer = list_entry(p, struct snd_timer, device_list);
-
+	list_for_each_entry(timer, &snd_timer_list, device_list) {
 		if (timer->tmr_class != tid->dev_class)
 			continue;
 		if ((timer->tmr_class == SNDRV_TIMER_CLASS_CARD ||
@@ -184,13 +178,10 @@
 {
 	struct snd_timer *timer;
 	struct snd_timer_instance *master;
-	struct list_head *p, *q;
 
 	/* FIXME: it's really dumb to look up all entries.. */
-	list_for_each(p, &snd_timer_list) {
-		timer = list_entry(p, struct snd_timer, device_list);
-		list_for_each(q, &timer->open_list_head) {
-			master = list_entry(q, struct snd_timer_instance, open_list);
+	list_for_each_entry(timer, &snd_timer_list, device_list) {
+		list_for_each_entry(master, &timer->open_list_head, open_list) {
 			if (slave->slave_class == master->slave_class &&
 			    slave->slave_id == master->slave_id) {
 				list_del(&slave->open_list);
@@ -214,16 +205,13 @@
  */
 static void snd_timer_check_master(struct snd_timer_instance *master)
 {
-	struct snd_timer_instance *slave;
-	struct list_head *p, *n;
+	struct snd_timer_instance *slave, *tmp;
 
 	/* check all pending slaves */
-	list_for_each_safe(p, n, &snd_timer_slave_list) {
-		slave = list_entry(p, struct snd_timer_instance, open_list);
+	list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) {
 		if (slave->slave_class == master->slave_class &&
 		    slave->slave_id == master->slave_id) {
-			list_del(p);
-			list_add_tail(p, &master->slave_list_head);
+			list_move_tail(&slave->open_list, &master->slave_list_head);
 			spin_lock_irq(&slave_active_lock);
 			slave->master = master;
 			slave->timer = master->timer;
@@ -317,8 +305,7 @@
 int snd_timer_close(struct snd_timer_instance *timeri)
 {
 	struct snd_timer *timer = NULL;
-	struct list_head *p, *n;
-	struct snd_timer_instance *slave;
+	struct snd_timer_instance *slave, *tmp;
 
 	snd_assert(timeri != NULL, return -ENXIO);
 
@@ -353,12 +340,11 @@
 		    timer->hw.close)
 			timer->hw.close(timer);
 		/* remove slave links */
-		list_for_each_safe(p, n, &timeri->slave_list_head) {
-			slave = list_entry(p, struct snd_timer_instance, open_list);
+		list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
+					 open_list) {
 			spin_lock_irq(&slave_active_lock);
 			_snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
-			list_del(p);
-			list_add_tail(p, &snd_timer_slave_list);
+			list_move_tail(&slave->open_list, &snd_timer_slave_list);
 			slave->master = NULL;
 			slave->timer = NULL;
 			spin_unlock_irq(&slave_active_lock);
@@ -394,7 +380,6 @@
 	unsigned long flags;
 	unsigned long resolution = 0;
 	struct snd_timer_instance *ts;
-	struct list_head *n;
 	struct timespec tstamp;
 
 	getnstimeofday(&tstamp);
@@ -413,11 +398,9 @@
 	if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
 		return;
 	spin_lock_irqsave(&timer->lock, flags);
-	list_for_each(n, &ti->slave_active_head) {
-		ts = list_entry(n, struct snd_timer_instance, active_list);
+	list_for_each_entry(ts, &ti->slave_active_head, active_list)
 		if (ts->ccallback)
 			ts->ccallback(ti, event + 100, &tstamp, resolution);
-	}
 	spin_unlock_irqrestore(&timer->lock, flags);
 }
 
@@ -593,10 +576,8 @@
 {
 	struct snd_timer_instance *ti;
 	unsigned long ticks = ~0UL;
-	struct list_head *p;
 
-	list_for_each(p, &timer->active_list_head) {
-		ti = list_entry(p, struct snd_timer_instance, active_list);
+	list_for_each_entry(ti, &timer->active_list_head, active_list) {
 		if (ti->flags & SNDRV_TIMER_IFLG_START) {
 			ti->flags &= ~SNDRV_TIMER_IFLG_START;
 			ti->flags |= SNDRV_TIMER_IFLG_RUNNING;
@@ -661,9 +642,9 @@
  */
 void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
 {
-	struct snd_timer_instance *ti, *ts;
+	struct snd_timer_instance *ti, *ts, *tmp;
 	unsigned long resolution, ticks;
-	struct list_head *p, *q, *n, *ack_list_head;
+	struct list_head *p, *ack_list_head;
 	unsigned long flags;
 	int use_tasklet = 0;
 
@@ -679,12 +660,12 @@
 		resolution = timer->hw.resolution;
 
 	/* loop for all active instances
-	 * Here we cannot use list_for_each because the active_list of a
+	 * Here we cannot use list_for_each_entry because the active_list of a
 	 * processed instance is relinked to done_list_head before the callback
 	 * is called.
 	 */
-	list_for_each_safe(p, n, &timer->active_list_head) {
-		ti = list_entry(p, struct snd_timer_instance, active_list);
+	list_for_each_entry_safe(ti, tmp, &timer->active_list_head,
+				 active_list) {
 		if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING))
 			continue;
 		ti->pticks += ticks_left;
@@ -700,7 +681,7 @@
 		} else {
 			ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
 			if (--timer->running)
-				list_del(p);
+				list_del(&ti->active_list);
 		}
 		if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
 		    (ti->flags & SNDRV_TIMER_IFLG_FAST))
@@ -709,8 +690,7 @@
 			ack_list_head = &timer->sack_list_head;
 		if (list_empty(&ti->ack_list))
 			list_add_tail(&ti->ack_list, ack_list_head);
-		list_for_each(q, &ti->slave_active_head) {
-			ts = list_entry(q, struct snd_timer_instance, active_list);
+		list_for_each_entry(ts, &ti->slave_active_head, active_list) {
 			ts->pticks = ti->pticks;
 			ts->resolution = resolution;
 			if (list_empty(&ts->ack_list))
@@ -844,7 +824,6 @@
 {
 	struct snd_timer *timer = dev->device_data;
 	struct snd_timer *timer1;
-	struct list_head *p;
 
 	snd_assert(timer != NULL && timer->hw.start != NULL &&
 		   timer->hw.stop != NULL, return -ENXIO);
@@ -853,8 +832,7 @@
 	    	return -EINVAL;
 
 	mutex_lock(&register_mutex);
-	list_for_each(p, &snd_timer_list) {
-		timer1 = list_entry(p, struct snd_timer, device_list);
+	list_for_each_entry(timer1, &snd_timer_list, device_list) {
 		if (timer1->tmr_class > timer->tmr_class)
 			break;
 		if (timer1->tmr_class < timer->tmr_class)
@@ -877,7 +855,7 @@
 		mutex_unlock(&register_mutex);
 		return -EBUSY;
 	}
-	list_add_tail(&timer->device_list, p);
+	list_add_tail(&timer->device_list, &timer1->device_list);
 	mutex_unlock(&register_mutex);
 	return 0;
 }
@@ -896,7 +874,6 @@
 	unsigned long flags;
 	unsigned long resolution = 0;
 	struct snd_timer_instance *ti, *ts;
-	struct list_head *p, *n;
 
 	if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE))
 		return;
@@ -911,15 +888,12 @@
 		else
 			resolution = timer->hw.resolution;
 	}
-	list_for_each(p, &timer->active_list_head) {
-		ti = list_entry(p, struct snd_timer_instance, active_list);
+	list_for_each_entry(ti, &timer->active_list_head, active_list) {
 		if (ti->ccallback)
 			ti->ccallback(ti, event, tstamp, resolution);
-		list_for_each(n, &ti->slave_active_head) {
-			ts = list_entry(n, struct snd_timer_instance, active_list);
+		list_for_each_entry(ts, &ti->slave_active_head, active_list)
 			if (ts->ccallback)
 				ts->ccallback(ts, event, tstamp, resolution);
-		}
 	}
 	spin_unlock_irqrestore(&timer->lock, flags);
 }
@@ -1057,11 +1031,9 @@
 {
 	struct snd_timer *timer;
 	struct snd_timer_instance *ti;
-	struct list_head *p, *q;
 
 	mutex_lock(&register_mutex);
-	list_for_each(p, &snd_timer_list) {
-		timer = list_entry(p, struct snd_timer, device_list);
+	list_for_each_entry(timer, &snd_timer_list, device_list) {
 		switch (timer->tmr_class) {
 		case SNDRV_TIMER_CLASS_GLOBAL:
 			snd_iprintf(buffer, "G%i: ", timer->tmr_device);
@@ -1088,14 +1060,12 @@
 		if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
 			snd_iprintf(buffer, " SLAVE");
 		snd_iprintf(buffer, "\n");
-		list_for_each(q, &timer->open_list_head) {
-			ti = list_entry(q, struct snd_timer_instance, open_list);
+		list_for_each_entry(ti, &timer->open_list_head, open_list)
 			snd_iprintf(buffer, "  Client %s : %s\n",
 				    ti->owner ? ti->owner : "unknown",
 				    ti->flags & (SNDRV_TIMER_IFLG_START |
 						 SNDRV_TIMER_IFLG_RUNNING)
 				    ? "running" : "stopped");
-		}
 	}
 	mutex_unlock(&register_mutex);
 }
@@ -1931,7 +1901,7 @@
 #define snd_timer_user_ioctl_compat	NULL
 #endif
 
-static struct file_operations snd_timer_f_ops =
+static const struct file_operations snd_timer_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		snd_timer_user_read,
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 40ebd2f..83529b0 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -109,4 +109,15 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-mpu401.
 
+config SND_PORTMAN2X4
+	tristate "Portman 2x4 driver"
+	depends on SND && PARPORT
+	select SND_RAWMIDI
+	help
+	  Say Y here to include support for Midiman Portman 2x4 parallel
+	  port MIDI device.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-portman2x4.
+
 endmenu
diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile
index c9bad6d..0411264 100644
--- a/sound/drivers/Makefile
+++ b/sound/drivers/Makefile
@@ -6,6 +6,7 @@
 snd-dummy-objs := dummy.o
 snd-mtpav-objs := mtpav.o
 snd-mts64-objs := mts64.o
+snd-portman2x4-objs := portman2x4.o
 snd-serial-u16550-objs := serial-u16550.o
 snd-virmidi-objs := virmidi.o
 
@@ -15,5 +16,6 @@
 obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o
 obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o
 obj-$(CONFIG_SND_MTS64) += snd-mts64.o
+obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o
 
 obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 42001ef..a0f28f5 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -423,7 +423,8 @@
 	.pointer =		snd_card_dummy_pcm_pointer,
 };
 
-static int __init snd_card_dummy_pcm(struct snd_dummy *dummy, int device, int substreams)
+static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
+					int substreams)
 {
 	struct snd_pcm *pcm;
 	int err;
@@ -501,7 +502,7 @@
 	return change;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0);
 
 #define DUMMY_CAPSRC(xname, xindex, addr) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -562,7 +563,7 @@
 DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD)
 };
 
-static int __init snd_card_dummy_new_mixer(struct snd_dummy *dummy)
+static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
 {
 	struct snd_card *card = dummy->card;
 	unsigned int idx;
@@ -579,7 +580,7 @@
 	return 0;
 }
 
-static int __init snd_dummy_probe(struct platform_device *devptr)
+static int __devinit snd_dummy_probe(struct platform_device *devptr)
 {
 	struct snd_card *card;
 	struct snd_dummy *dummy;
@@ -617,7 +618,7 @@
 	return err;
 }
 
-static int snd_dummy_remove(struct platform_device *devptr)
+static int __devexit snd_dummy_remove(struct platform_device *devptr)
 {
 	snd_card_free(platform_get_drvdata(devptr));
 	platform_set_drvdata(devptr, NULL);
@@ -648,7 +649,7 @@
 
 static struct platform_driver snd_dummy_driver = {
 	.probe		= snd_dummy_probe,
-	.remove		= snd_dummy_remove,
+	.remove		= __devexit_p(snd_dummy_remove),
 #ifdef CONFIG_PM
 	.suspend	= snd_dummy_suspend,
 	.resume		= snd_dummy_resume,
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index a9ff391..40eb026 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -583,7 +583,7 @@
 /*
  * get ISA resources
  */
-static int __init snd_mtpav_get_ISA(struct mtpav * mcard)
+static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard)
 {
 	if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
 		snd_printk("MTVAP port 0x%lx is busy\n", port);
@@ -619,7 +619,7 @@
  * get RAWMIDI resources
  */
 
-static void __init snd_mtpav_set_name(struct mtpav *chip,
+static void __devinit snd_mtpav_set_name(struct mtpav *chip,
 				      struct snd_rawmidi_substream *substream)
 {
 	if (substream->number >= 0 && substream->number < chip->num_ports)
@@ -634,7 +634,7 @@
 		strcpy(substream->name, "MTP broadcast");
 }
 
-static int __init snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
+static int __devinit snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
 {
 	int rval;
 	struct snd_rawmidi *rawmidi;
@@ -691,7 +691,7 @@
 
 /*
  */
-static int __init snd_mtpav_probe(struct platform_device *dev)
+static int __devinit snd_mtpav_probe(struct platform_device *dev)
 {
 	struct snd_card *card;
 	int err;
@@ -745,7 +745,7 @@
 	return err;
 }
 
-static int snd_mtpav_remove(struct platform_device *devptr)
+static int __devexit snd_mtpav_remove(struct platform_device *devptr)
 {
 	snd_card_free(platform_get_drvdata(devptr));
 	platform_set_drvdata(devptr, NULL);
@@ -756,7 +756,7 @@
 
 static struct platform_driver snd_mtpav_driver = {
 	.probe		= snd_mtpav_probe,
-	.remove		= snd_mtpav_remove,
+	.remove		= __devexit_p(snd_mtpav_remove),
 	.driver		= {
 		.name	= SND_MTPAV_DRIVER
 	},
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index 5327c6f..6c9f4c9 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -1026,7 +1026,7 @@
 	return err;
 }
 
-static int snd_mts64_remove(struct platform_device *pdev)
+static int __devexit snd_mts64_remove(struct platform_device *pdev)
 {
 	struct snd_card *card = platform_get_drvdata(pdev);
 
@@ -1039,7 +1039,7 @@
 
 static struct platform_driver snd_mts64_driver = {
 	.probe  = snd_mts64_probe,
-	.remove = snd_mts64_remove,
+	.remove = __devexit_p(snd_mts64_remove),
 	.driver = {
 		.name = PLATFORM_DRIVER
 	}
@@ -1048,7 +1048,7 @@
 /*********************************************************************
  * module init stuff
  *********************************************************************/
-static void snd_mts64_unregister_all(void)
+static void __init_or_module snd_mts64_unregister_all(void)
 {
 	int i;
 
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
new file mode 100644
index 0000000..b2d0ba4
--- /dev/null
+++ b/sound/drivers/portman2x4.c
@@ -0,0 +1,876 @@
+/*
+ *   Driver for Midiman Portman2x4 parallel port midi interface
+ *
+ *   Copyright (c) by Levent Guendogdu <levon@feature-it.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * ChangeLog
+ * Jan 24 2007 Matthias Koenig <mkoenig@suse.de>
+ *      - cleanup and rewrite
+ * Sep 30 2004 Tobias Gehrig <tobias@gehrig.tk>
+ *      - source code cleanup
+ * Sep 03 2004 Tobias Gehrig <tobias@gehrig.tk>
+ *      - fixed compilation problem with alsa 1.0.6a (removed MODULE_CLASSES,
+ *        MODULE_PARM_SYNTAX and changed MODULE_DEVICES to
+ *        MODULE_SUPPORTED_DEVICE)
+ * Mar 24 2004 Tobias Gehrig <tobias@gehrig.tk>
+ *      - added 2.6 kernel support
+ * Mar 18 2004 Tobias Gehrig <tobias@gehrig.tk>
+ *      - added parport_unregister_driver to the startup routine if the driver fails to detect a portman
+ *      - added support for all 4 output ports in portman_putmidi
+ * Mar 17 2004 Tobias Gehrig <tobias@gehrig.tk>
+ *      - added checks for opened input device in interrupt handler
+ * Feb 20 2004 Tobias Gehrig <tobias@gehrig.tk>
+ *      - ported from alsa 0.5 to 1.0
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/parport.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+#include <sound/control.h>
+
+#define CARD_NAME "Portman 2x4"
+#define DRIVER_NAME "portman"
+#define PLATFORM_DRIVER "snd_portman2x4"
+
+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;
+
+static struct platform_device *platform_devices[SNDRV_CARDS]; 
+static int device_count;
+
+module_param_array(index, int, NULL, S_IRUGO);
+MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
+module_param_array(id, charp, NULL, S_IRUGO);
+MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
+module_param_array(enable, bool, NULL, S_IRUGO);
+MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
+
+MODULE_AUTHOR("Levent Guendogdu, Tobias Gehrig, Matthias Koenig");
+MODULE_DESCRIPTION("Midiman Portman2x4");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Midiman,Portman2x4}}");
+
+/*********************************************************************
+ * Chip specific
+ *********************************************************************/
+#define PORTMAN_NUM_INPUT_PORTS 2
+#define PORTMAN_NUM_OUTPUT_PORTS 4
+
+struct portman {
+	spinlock_t reg_lock;
+	struct snd_card *card;
+	struct snd_rawmidi *rmidi;
+	struct pardevice *pardev;
+	int pardev_claimed;
+
+	int open_count;
+	int mode[PORTMAN_NUM_INPUT_PORTS];
+	struct snd_rawmidi_substream *midi_input[PORTMAN_NUM_INPUT_PORTS];
+};
+
+static int portman_free(struct portman *pm)
+{
+	kfree(pm);
+	return 0;
+}
+
+static int __devinit portman_create(struct snd_card *card, 
+				    struct pardevice *pardev, 
+				    struct portman **rchip)
+{
+	struct portman *pm;
+
+	*rchip = NULL;
+
+	pm = kzalloc(sizeof(struct portman), GFP_KERNEL);
+	if (pm == NULL) 
+		return -ENOMEM;
+
+	/* Init chip specific data */
+	spin_lock_init(&pm->reg_lock);
+	pm->card = card;
+	pm->pardev = pardev;
+
+	*rchip = pm;
+
+	return 0;
+}
+
+/*********************************************************************
+ * HW related constants
+ *********************************************************************/
+
+/* Standard PC parallel port status register equates. */
+#define	PP_STAT_BSY   	0x80	/* Busy status.  Inverted. */
+#define	PP_STAT_ACK   	0x40	/* Acknowledge.  Non-Inverted. */
+#define	PP_STAT_POUT  	0x20	/* Paper Out.    Non-Inverted. */
+#define	PP_STAT_SEL   	0x10	/* Select.       Non-Inverted. */
+#define	PP_STAT_ERR   	0x08	/* Error.        Non-Inverted. */
+
+/* Standard PC parallel port command register equates. */
+#define	PP_CMD_IEN  	0x10	/* IRQ Enable.   Non-Inverted. */
+#define	PP_CMD_SELI 	0x08	/* Select Input. Inverted. */
+#define	PP_CMD_INIT 	0x04	/* Init Printer. Non-Inverted. */
+#define	PP_CMD_FEED 	0x02	/* Auto Feed.    Inverted. */
+#define	PP_CMD_STB      0x01	/* Strobe.       Inverted. */
+
+/* Parallel Port Command Register as implemented by PCP2x4. */
+#define	INT_EN	 	PP_CMD_IEN	/* Interrupt enable. */
+#define	STROBE	        PP_CMD_STB	/* Command strobe. */
+
+/* The parallel port command register field (b1..b3) selects the 
+ * various "registers" within the PC/P 2x4.  These are the internal
+ * address of these "registers" that must be written to the parallel
+ * port command register.
+ */
+#define	RXDATA0		(0 << 1)	/* PCP RxData channel 0. */
+#define	RXDATA1		(1 << 1)	/* PCP RxData channel 1. */
+#define	GEN_CTL		(2 << 1)	/* PCP General Control Register. */
+#define	SYNC_CTL 	(3 << 1)	/* PCP Sync Control Register. */
+#define	TXDATA0		(4 << 1)	/* PCP TxData channel 0. */
+#define	TXDATA1		(5 << 1)	/* PCP TxData channel 1. */
+#define	TXDATA2		(6 << 1)	/* PCP TxData channel 2. */
+#define	TXDATA3		(7 << 1)	/* PCP TxData channel 3. */
+
+/* Parallel Port Status Register as implemented by PCP2x4. */
+#define	ESTB		PP_STAT_POUT	/* Echoed strobe. */
+#define	INT_REQ         PP_STAT_ACK	/* Input data int request. */
+#define	BUSY            PP_STAT_ERR	/* Interface Busy. */
+
+/* Parallel Port Status Register BUSY and SELECT lines are multiplexed
+ * between several functions.  Depending on which 2x4 "register" is
+ * currently selected (b1..b3), the BUSY and SELECT lines are
+ * assigned as follows:
+ *
+ *   SELECT LINE:                                                    A3 A2 A1
+ *                                                                   --------
+ */
+#define	RXAVAIL		PP_STAT_SEL	/* Rx Available, channel 0.   0 0 0 */
+//  RXAVAIL1    PP_STAT_SEL             /* Rx Available, channel 1.   0 0 1 */
+#define	SYNC_STAT	PP_STAT_SEL	/* Reserved - Sync Status.    0 1 0 */
+//                                      /* Reserved.                  0 1 1 */
+#define	TXEMPTY		PP_STAT_SEL	/* Tx Empty, channel 0.       1 0 0 */
+//      TXEMPTY1        PP_STAT_SEL     /* Tx Empty, channel 1.       1 0 1 */
+//  TXEMPTY2    PP_STAT_SEL             /* Tx Empty, channel 2.       1 1 0 */
+//  TXEMPTY3    PP_STAT_SEL             /* Tx Empty, channel 3.       1 1 1 */
+
+/*   BUSY LINE:                                                      A3 A2 A1
+ *                                                                   --------
+ */
+#define	RXDATA		PP_STAT_BSY	/* Rx Input Data, channel 0.  0 0 0 */
+//      RXDATA1         PP_STAT_BSY     /* Rx Input Data, channel 1.  0 0 1 */
+#define	SYNC_DATA       PP_STAT_BSY	/* Reserved - Sync Data.      0 1 0 */
+					/* Reserved.                  0 1 1 */
+#define	DATA_ECHO       PP_STAT_BSY	/* Parallel Port Data Echo.   1 0 0 */
+#define	A0_ECHO         PP_STAT_BSY	/* Address 0 Echo.            1 0 1 */
+#define	A1_ECHO         PP_STAT_BSY	/* Address 1 Echo.            1 1 0 */
+#define	A2_ECHO         PP_STAT_BSY	/* Address 2 Echo.            1 1 1 */
+
+#define PORTMAN2X4_MODE_INPUT_TRIGGERED	 0x01
+
+/*********************************************************************
+ * Hardware specific functions
+ *********************************************************************/
+static inline void portman_write_command(struct portman *pm, u8 value)
+{
+	parport_write_control(pm->pardev->port, value);
+}
+
+static inline u8 portman_read_command(struct portman *pm)
+{
+	return parport_read_control(pm->pardev->port);
+}
+
+static inline u8 portman_read_status(struct portman *pm)
+{
+	return parport_read_status(pm->pardev->port);
+}
+
+static inline u8 portman_read_data(struct portman *pm)
+{
+	return parport_read_data(pm->pardev->port);
+}
+
+static inline void portman_write_data(struct portman *pm, u8 value)
+{
+	parport_write_data(pm->pardev->port, value);
+}
+
+static void portman_write_midi(struct portman *pm, 
+			       int port, u8 mididata)
+{
+	int command = ((port + 4) << 1);
+
+	/* Get entering data byte and port number in BL and BH respectively.
+	 * Set up Tx Channel address field for use with PP Cmd Register.
+	 * Store address field in BH register.
+	 * Inputs:      AH = Output port number (0..3).
+	 *              AL = Data byte.
+	 *    command = TXDATA0 | INT_EN;
+	 * Align port num with address field (b1...b3),
+	 * set address for TXDatax, Strobe=0
+	 */
+	command |= INT_EN;
+
+	/* Disable interrupts so that the process is not interrupted, then 
+	 * write the address associated with the current Tx channel to the 
+	 * PP Command Reg.  Do not set the Strobe signal yet.
+	 */
+
+	do {
+		portman_write_command(pm, command);
+
+		/* While the address lines settle, write parallel output data to 
+		 * PP Data Reg.  This has no effect until Strobe signal is asserted.
+		 */
+
+		portman_write_data(pm, mididata);
+		
+		/* If PCP channel's TxEmpty is set (TxEmpty is read through the PP
+		 * Status Register), then go write data.  Else go back and wait.
+		 */
+	} while ((portman_read_status(pm) & TXEMPTY) != TXEMPTY);
+
+	/* TxEmpty is set.  Maintain PC/P destination address and assert
+	 * Strobe through the PP Command Reg.  This will Strobe data into
+	 * the PC/P transmitter and set the PC/P BUSY signal.
+	 */
+
+	portman_write_command(pm, command | STROBE);
+
+	/* Wait for strobe line to settle and echo back through hardware.
+	 * Once it has echoed back, assume that the address and data lines
+	 * have settled!
+	 */
+
+	while ((portman_read_status(pm) & ESTB) == 0)
+		cpu_relax();
+
+	/* Release strobe and immediately re-allow interrupts. */
+	portman_write_command(pm, command);
+
+	while ((portman_read_status(pm) & ESTB) == ESTB)
+		cpu_relax();
+
+	/* PC/P BUSY is now set.  We must wait until BUSY resets itself.
+	 * We'll reenable ints while we're waiting.
+	 */
+
+	while ((portman_read_status(pm) & BUSY) == BUSY)
+		cpu_relax();
+
+	/* Data sent. */
+}
+
+
+/*
+ *  Read MIDI byte from port
+ *  Attempt to read input byte from specified hardware input port (0..).
+ *  Return -1 if no data
+ */
+static int portman_read_midi(struct portman *pm, int port)
+{
+	unsigned char midi_data = 0;
+	unsigned char cmdout;	/* Saved address+IE bit. */
+
+	/* Make sure clocking edge is down before starting... */
+	portman_write_data(pm, 0);	/* Make sure edge is down. */
+
+	/* Set destination address to PCP. */
+	cmdout = (port << 1) | INT_EN;	/* Address + IE + No Strobe. */
+	portman_write_command(pm, cmdout);
+
+	while ((portman_read_status(pm) & ESTB) == ESTB)
+		cpu_relax();	/* Wait for strobe echo. */
+
+	/* After the address lines settle, check multiplexed RxAvail signal.
+	 * If data is available, read it.
+	 */
+	if ((portman_read_status(pm) & RXAVAIL) == 0)
+		return -1;	/* No data. */
+
+	/* Set the Strobe signal to enable the Rx clocking circuitry. */
+	portman_write_command(pm, cmdout | STROBE);	/* Write address+IE+Strobe. */
+
+	while ((portman_read_status(pm) & ESTB) == 0)
+		cpu_relax(); /* Wait for strobe echo. */
+
+	/* The first data bit (msb) is already sitting on the input line. */
+	midi_data = (portman_read_status(pm) & 128);
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
+
+	/* Data bit 6. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 1) & 64;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
+
+	/* Data bit 5. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 2) & 32;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
+
+	/* Data bit 4. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 3) & 16;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
+
+	/* Data bit 3. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 4) & 8;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
+
+	/* Data bit 2. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 5) & 4;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
+
+	/* Data bit 1. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 6) & 2;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
+
+	/* Data bit 0. */
+	portman_write_data(pm, 0);	/* Cause falling edge while data settles. */
+	midi_data |= (portman_read_status(pm) >> 7) & 1;
+	portman_write_data(pm, 1);	/* Cause rising edge, which shifts data. */
+	portman_write_data(pm, 0);	/* Return data clock low. */
+
+
+	/* De-assert Strobe and return data. */
+	portman_write_command(pm, cmdout);	/* Output saved address+IE. */
+
+	/* Wait for strobe echo. */
+	while ((portman_read_status(pm) & ESTB) == ESTB)
+		cpu_relax();
+
+	return (midi_data & 255);	/* Shift back and return value. */
+}
+
+/*
+ *  Checks if any input data on the given channel is available
+ *  Checks RxAvail 
+ */
+static int portman_data_avail(struct portman *pm, int channel)
+{
+	int command = INT_EN;
+	switch (channel) {
+	case 0:
+		command |= RXDATA0;
+		break;
+	case 1:
+		command |= RXDATA1;
+		break;
+	}
+	/* Write hardware (assumme STROBE=0) */
+	portman_write_command(pm, command);
+	/* Check multiplexed RxAvail signal */
+	if ((portman_read_status(pm) & RXAVAIL) == RXAVAIL)
+		return 1;	/* Data available */
+
+	/* No Data available */
+	return 0;
+}
+
+
+/*
+ *  Flushes any input
+ */
+static void portman_flush_input(struct portman *pm, unsigned char port)
+{
+	/* Local variable for counting things */
+	unsigned int i = 0;
+	unsigned char command = 0;
+
+	switch (port) {
+	case 0:
+		command = RXDATA0;
+		break;
+	case 1:
+		command = RXDATA1;
+		break;
+	default:
+		snd_printk(KERN_WARNING
+			   "portman_flush_input() Won't flush port %i\n",
+			   port);
+		return;
+	}
+
+	/* Set address for specified channel in port and allow to settle. */
+	portman_write_command(pm, command);
+
+	/* Assert the Strobe and wait for echo back. */
+	portman_write_command(pm, command | STROBE);
+
+	/* Wait for ESTB */
+	while ((portman_read_status(pm) & ESTB) == 0)
+		cpu_relax();
+
+	/* Output clock cycles to the Rx circuitry. */
+	portman_write_data(pm, 0);
+
+	/* Flush 250 bits... */
+	for (i = 0; i < 250; i++) {
+		portman_write_data(pm, 1);
+		portman_write_data(pm, 0);
+	}
+
+	/* Deassert the Strobe signal of the port and wait for it to settle. */
+	portman_write_command(pm, command | INT_EN);
+
+	/* Wait for settling */
+	while ((portman_read_status(pm) & ESTB) == ESTB)
+		cpu_relax();
+}
+
+static int portman_probe(struct parport *p)
+{
+	/* Initialize the parallel port data register.  Will set Rx clocks
+	 * low in case we happen to be addressing the Rx ports at this time.
+	 */
+	/* 1 */
+	parport_write_data(p, 0);
+
+	/* Initialize the parallel port command register, thus initializing
+	 * hardware handshake lines to midi box:
+	 *
+	 *                                  Strobe = 0
+	 *                                  Interrupt Enable = 0            
+	 */
+	/* 2 */
+	parport_write_control(p, 0);
+
+	/* Check if Portman PC/P 2x4 is out there. */
+	/* 3 */
+	parport_write_control(p, RXDATA0);	/* Write Strobe=0 to command reg. */
+
+	/* Check for ESTB to be clear */
+	/* 4 */
+	if ((parport_read_status(p) & ESTB) == ESTB)
+		return 1;	/* CODE 1 - Strobe Failure. */
+
+	/* Set for RXDATA0 where no damage will be done. */
+	/* 5 */
+	parport_write_control(p, RXDATA0 + STROBE);	/* Write Strobe=1 to command reg. */
+
+	/* 6 */
+	if ((parport_read_status(p) & ESTB) != ESTB)
+		return 1;	/* CODE 1 - Strobe Failure. */
+
+	/* 7 */
+	parport_write_control(p, 0);	/* Reset Strobe=0. */
+
+	/* Check if Tx circuitry is functioning properly.  If initialized 
+	 * unit TxEmpty is false, send out char and see if if goes true.
+	 */
+	/* 8 */
+	parport_write_control(p, TXDATA0);	/* Tx channel 0, strobe off. */
+
+	/* If PCP channel's TxEmpty is set (TxEmpty is read through the PP
+	 * Status Register), then go write data.  Else go back and wait.
+	 */
+	/* 9 */
+	if ((parport_read_status(p) & TXEMPTY) == 0)
+		return 2;
+
+	/* Return OK status. */
+	return 0;
+}
+
+static int portman_device_init(struct portman *pm)
+{
+	portman_flush_input(pm, 0);
+	portman_flush_input(pm, 1);
+
+	return 0;
+}
+
+/*********************************************************************
+ * Rawmidi
+ *********************************************************************/
+static int snd_portman_midi_open(struct snd_rawmidi_substream *substream)
+{
+	return 0;
+}
+
+static int snd_portman_midi_close(struct snd_rawmidi_substream *substream)
+{
+	return 0;
+}
+
+static void snd_portman_midi_input_trigger(struct snd_rawmidi_substream *substream,
+					   int up)
+{
+	struct portman *pm = substream->rmidi->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pm->reg_lock, flags);
+	if (up)
+		pm->mode[substream->number] |= PORTMAN2X4_MODE_INPUT_TRIGGERED;
+	else
+		pm->mode[substream->number] &= ~PORTMAN2X4_MODE_INPUT_TRIGGERED;
+	spin_unlock_irqrestore(&pm->reg_lock, flags);
+}
+
+static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *substream,
+					    int up)
+{
+	struct portman *pm = substream->rmidi->private_data;
+	unsigned long flags;
+	unsigned char byte;
+
+	spin_lock_irqsave(&pm->reg_lock, flags);
+	if (up) {
+		while ((snd_rawmidi_transmit(substream, &byte, 1) == 1))
+			portman_write_midi(pm, substream->number, byte);
+	}
+	spin_unlock_irqrestore(&pm->reg_lock, flags);
+}
+
+static struct snd_rawmidi_ops snd_portman_midi_output = {
+	.open =		snd_portman_midi_open,
+	.close =	snd_portman_midi_close,
+	.trigger =	snd_portman_midi_output_trigger,
+};
+
+static struct snd_rawmidi_ops snd_portman_midi_input = {
+	.open =		snd_portman_midi_open,
+	.close =	snd_portman_midi_close,
+	.trigger =	snd_portman_midi_input_trigger,
+};
+
+/* Create and initialize the rawmidi component */
+static int __devinit snd_portman_rawmidi_create(struct snd_card *card)
+{
+	struct portman *pm = card->private_data;
+	struct snd_rawmidi *rmidi;
+	struct snd_rawmidi_substream *substream;
+	int err;
+	
+	err = snd_rawmidi_new(card, CARD_NAME, 0, 
+			      PORTMAN_NUM_OUTPUT_PORTS, 
+			      PORTMAN_NUM_INPUT_PORTS, 
+			      &rmidi);
+	if (err < 0) 
+		return err;
+
+	rmidi->private_data = pm;
+	strcpy(rmidi->name, CARD_NAME);
+	rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+		            SNDRV_RAWMIDI_INFO_INPUT |
+                            SNDRV_RAWMIDI_INFO_DUPLEX;
+
+	pm->rmidi = rmidi;
+
+	/* register rawmidi ops */
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 
+			    &snd_portman_midi_output);
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 
+			    &snd_portman_midi_input);
+
+	/* name substreams */
+	/* output */
+	list_for_each_entry(substream,
+			    &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
+			    list) {
+		sprintf(substream->name,
+			"Portman2x4 %d", substream->number+1);
+	}
+	/* input */
+	list_for_each_entry(substream,
+			    &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams,
+			    list) {
+		pm->midi_input[substream->number] = substream;
+		sprintf(substream->name,
+			"Portman2x4 %d", substream->number+1);
+	}
+
+	return err;
+}
+
+/*********************************************************************
+ * parport stuff
+ *********************************************************************/
+static void snd_portman_interrupt(int irq, void *userdata)
+{
+	unsigned char midivalue = 0;
+	struct portman *pm = ((struct snd_card*)userdata)->private_data;
+
+	spin_lock(&pm->reg_lock);
+
+	/* While any input data is waiting */
+	while ((portman_read_status(pm) & INT_REQ) == INT_REQ) {
+		/* If data available on channel 0, 
+		   read it and stuff it into the queue. */
+		if (portman_data_avail(pm, 0)) {
+			/* Read Midi */
+			midivalue = portman_read_midi(pm, 0);
+			/* put midi into queue... */
+			if (pm->mode[0] & PORTMAN2X4_MODE_INPUT_TRIGGERED)
+				snd_rawmidi_receive(pm->midi_input[0],
+						    &midivalue, 1);
+
+		}
+		/* If data available on channel 1, 
+		   read it and stuff it into the queue. */
+		if (portman_data_avail(pm, 1)) {
+			/* Read Midi */
+			midivalue = portman_read_midi(pm, 1);
+			/* put midi into queue... */
+			if (pm->mode[1] & PORTMAN2X4_MODE_INPUT_TRIGGERED)
+				snd_rawmidi_receive(pm->midi_input[1],
+						    &midivalue, 1);
+		}
+
+	}
+
+	spin_unlock(&pm->reg_lock);
+}
+
+static int __devinit snd_portman_probe_port(struct parport *p)
+{
+	struct pardevice *pardev;
+	int res;
+
+	pardev = parport_register_device(p, DRIVER_NAME,
+					 NULL, NULL, NULL,
+					 0, NULL);
+	if (!pardev)
+		return -EIO;
+	
+	if (parport_claim(pardev)) {
+		parport_unregister_device(pardev);
+		return -EIO;
+	}
+
+	res = portman_probe(p);
+
+	parport_release(pardev);
+	parport_unregister_device(pardev);
+
+	return res;
+}
+
+static void __devinit snd_portman_attach(struct parport *p)
+{
+	struct platform_device *device;
+
+	device = platform_device_alloc(PLATFORM_DRIVER, device_count);
+	if (!device) 
+		return;
+
+	/* Temporary assignment to forward the parport */
+	platform_set_drvdata(device, p);
+
+	if (platform_device_register(device) < 0) {
+		platform_device_put(device);
+		return;
+	}
+
+	/* Since we dont get the return value of probe
+	 * We need to check if device probing succeeded or not */
+	if (!platform_get_drvdata(device)) {
+		platform_device_unregister(device);
+		return;
+	}
+
+	/* register device in global table */
+	platform_devices[device_count] = device;
+	device_count++;
+}
+
+static void snd_portman_detach(struct parport *p)
+{
+	/* nothing to do here */
+}
+
+static struct parport_driver portman_parport_driver = {
+	.name   = "portman2x4",
+	.attach = snd_portman_attach,
+	.detach = snd_portman_detach
+};
+
+/*********************************************************************
+ * platform stuff
+ *********************************************************************/
+static void snd_portman_card_private_free(struct snd_card *card)
+{
+	struct portman *pm = card->private_data;
+	struct pardevice *pardev = pm->pardev;
+
+	if (pardev) {
+		if (pm->pardev_claimed)
+			parport_release(pardev);
+		parport_unregister_device(pardev);
+	}
+
+	portman_free(pm);
+}
+
+static int __devinit snd_portman_probe(struct platform_device *pdev)
+{
+	struct pardevice *pardev;
+	struct parport *p;
+	int dev = pdev->id;
+	struct snd_card *card = NULL;
+	struct portman *pm = NULL;
+	int err;
+
+	p = platform_get_drvdata(pdev);
+	platform_set_drvdata(pdev, NULL);
+
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[dev]) 
+		return -ENOENT;
+
+	if ((err = snd_portman_probe_port(p)) < 0)
+		return err;
+
+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	if (card == NULL) {
+		snd_printd("Cannot create card\n");
+		return -ENOMEM;
+	}
+	strcpy(card->driver, DRIVER_NAME);
+	strcpy(card->shortname, CARD_NAME);
+	sprintf(card->longname,  "%s at 0x%lx, irq %i", 
+		card->shortname, p->base, p->irq);
+
+	pardev = parport_register_device(p,                     /* port */
+					 DRIVER_NAME,           /* name */
+					 NULL,                  /* preempt */
+					 NULL,                  /* wakeup */
+					 snd_portman_interrupt, /* ISR */
+					 PARPORT_DEV_EXCL,      /* flags */
+					 (void *)card);         /* private */
+	if (pardev == NULL) {
+		snd_printd("Cannot register pardevice\n");
+		err = -EIO;
+		goto __err;
+	}
+
+	if ((err = portman_create(card, pardev, &pm)) < 0) {
+		snd_printd("Cannot create main component\n");
+		parport_unregister_device(pardev);
+		goto __err;
+	}
+	card->private_data = pm;
+	card->private_free = snd_portman_card_private_free;
+	
+	if ((err = snd_portman_rawmidi_create(card)) < 0) {
+		snd_printd("Creating Rawmidi component failed\n");
+		goto __err;
+	}
+
+	/* claim parport */
+	if (parport_claim(pardev)) {
+		snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base);
+		err = -EIO;
+		goto __err;
+	}
+	pm->pardev_claimed = 1;
+
+	/* init device */
+	if ((err = portman_device_init(pm)) < 0)
+		goto __err;
+
+	platform_set_drvdata(pdev, card);
+
+	/* At this point card will be usable */
+	if ((err = snd_card_register(card)) < 0) {
+		snd_printd("Cannot register card\n");
+		goto __err;
+	}
+
+	snd_printk(KERN_INFO "Portman 2x4 on 0x%lx\n", p->base);
+	return 0;
+
+__err:
+	snd_card_free(card);
+	return err;
+}
+
+static int __devexit snd_portman_remove(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+
+	if (card)
+		snd_card_free(card);
+
+	return 0;
+}
+
+
+static struct platform_driver snd_portman_driver = {
+	.probe  = snd_portman_probe,
+	.remove = __devexit_p(snd_portman_remove),
+	.driver = {
+		.name = PLATFORM_DRIVER
+	}
+};
+
+/*********************************************************************
+ * module init stuff
+ *********************************************************************/
+static void __init_or_module snd_portman_unregister_all(void)
+{
+	int i;
+
+	for (i = 0; i < SNDRV_CARDS; ++i) {
+		if (platform_devices[i]) {
+			platform_device_unregister(platform_devices[i]);
+			platform_devices[i] = NULL;
+		}
+	}		
+	platform_driver_unregister(&snd_portman_driver);
+	parport_unregister_driver(&portman_parport_driver);
+}
+
+static int __init snd_portman_module_init(void)
+{
+	int err;
+
+	if ((err = platform_driver_register(&snd_portman_driver)) < 0)
+		return err;
+
+	if (parport_register_driver(&portman_parport_driver) != 0) {
+		platform_driver_unregister(&snd_portman_driver);
+		return -EIO;
+	}
+
+	if (device_count == 0) {
+		snd_portman_unregister_all();
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit snd_portman_module_exit(void)
+{
+	snd_portman_unregister_all();
+}
+
+module_init(snd_portman_module_init);
+module_exit(snd_portman_module_exit);
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 74028b2..838a427 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -117,13 +117,13 @@
 #define SERIAL_MODE_INPUT_TRIGGERED	(1 << 2)
 #define SERIAL_MODE_OUTPUT_TRIGGERED	(1 << 3)
 
-typedef struct _snd_uart16550 {
+struct snd_uart16550 {
 	struct snd_card *card;
 	struct snd_rawmidi *rmidi;
 	struct snd_rawmidi_substream *midi_output[SNDRV_SERIAL_MAX_OUTS];
 	struct snd_rawmidi_substream *midi_input[SNDRV_SERIAL_MAX_INS];
 
-	int filemode;		//open status of file
+	int filemode;		/* open status of file */
 
 	spinlock_t open_lock;
 
@@ -140,39 +140,39 @@
 	unsigned char old_divisor_msb;
 	unsigned char old_line_ctrl_reg;
 
-	// parameter for using of write loop
-	short int fifo_limit;	//used in uart16550
-        short int fifo_count;	//used in uart16550
+	/* parameter for using of write loop */
+	short int fifo_limit;	/* used in uart16550 */
+        short int fifo_count;	/* used in uart16550 */
 
-	// type of adaptor
+	/* type of adaptor */
 	int adaptor;
 
-	// inputs
+	/* inputs */
 	int prev_in;
 	unsigned char rstatus;
 
-	// outputs
+	/* outputs */
 	int prev_out;
 	unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS];
 
-	// write buffer and its writing/reading position
+	/* write buffer and its writing/reading position */
 	unsigned char tx_buff[TX_BUFF_SIZE];
 	int buff_in_count;
         int buff_in;
         int buff_out;
         int drop_on_full;
 
-	// wait timer
+	/* wait timer */
 	unsigned int timer_running:1;
 	struct timer_list buffer_timer;
 
-} snd_uart16550_t;
+};
 
 static struct platform_device *devices[SNDRV_CARDS];
 
-static inline void snd_uart16550_add_timer(snd_uart16550_t *uart)
+static inline void snd_uart16550_add_timer(struct snd_uart16550 *uart)
 {
-	if (! uart->timer_running) {
+	if (!uart->timer_running) {
 		/* timer 38600bps * 10bit * 16byte */
 		uart->buffer_timer.expires = jiffies + (HZ+255)/256;
 		uart->timer_running = 1;
@@ -180,7 +180,7 @@
 	}
 }
 
-static inline void snd_uart16550_del_timer(snd_uart16550_t *uart)
+static inline void snd_uart16550_del_timer(struct snd_uart16550 *uart)
 {
 	if (uart->timer_running) {
 		del_timer(&uart->buffer_timer);
@@ -189,10 +189,10 @@
 }
 
 /* This macro is only used in snd_uart16550_io_loop */
-static inline void snd_uart16550_buffer_output(snd_uart16550_t *uart)
+static inline void snd_uart16550_buffer_output(struct snd_uart16550 *uart)
 {
 	unsigned short buff_out = uart->buff_out;
-	if( uart->buff_in_count > 0 ) {
+	if (uart->buff_in_count > 0) {
 		outb(uart->tx_buff[buff_out], uart->base + UART_TX);
 		uart->fifo_count++;
 		buff_out++;
@@ -206,7 +206,7 @@
  * We don't want to interrupt this, 
  * as we're already handling an interrupt 
  */
-static void snd_uart16550_io_loop(snd_uart16550_t * uart)
+static void snd_uart16550_io_loop(struct snd_uart16550 * uart)
 {
 	unsigned char c, status;
 	int substream;
@@ -220,9 +220,8 @@
 		c = inb(uart->base + UART_RX);
 
 		/* keep track of last status byte */
-		if (c & 0x80) {
+		if (c & 0x80)
 			uart->rstatus = c;
-		}
 
 		/* handle stream switch */
 		if (uart->adaptor == SNDRV_SERIAL_GENERIC) {
@@ -230,14 +229,16 @@
 				if (c <= SNDRV_SERIAL_MAX_INS && c > 0)
 					substream = c - 1;
 				if (c != 0xf5)
-					uart->rstatus = 0; /* prevent future bytes from being interpreted as streams */
-			}
-			else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) {
-				snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
-			}
-		} else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) {
+					/* prevent future bytes from being
+					   interpreted as streams */
+					uart->rstatus = 0;
+			} else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN)
+				   && uart->midi_input[substream])
+				snd_rawmidi_receive(uart->midi_input[substream],
+						    &c, 1);
+		} else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) &&
+			   uart->midi_input[substream])
 			snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
-		}
 
 		if (status & UART_LSR_OE)
 			snd_printk("%s: Overrun on device at 0x%lx\n",
@@ -250,21 +251,20 @@
 	/* no need of check SERIAL_MODE_OUTPUT_OPEN because if not,
 	   buffer is never filled. */
 	/* Check write status */
-	if (status & UART_LSR_THRE) {
+	if (status & UART_LSR_THRE)
 		uart->fifo_count = 0;
-	}
 	if (uart->adaptor == SNDRV_SERIAL_MS124W_SA
 	   || uart->adaptor == SNDRV_SERIAL_GENERIC) {
 		/* Can't use FIFO, must send only when CTS is true */
 		status = inb(uart->base + UART_MSR);
-		while( (uart->fifo_count == 0) && (status & UART_MSR_CTS) &&
-		      (uart->buff_in_count > 0) ) {
+		while (uart->fifo_count == 0 && (status & UART_MSR_CTS) &&
+		       uart->buff_in_count > 0) {
 		       snd_uart16550_buffer_output(uart);
-		       status = inb( uart->base + UART_MSR );
+		       status = inb(uart->base + UART_MSR);
 		}
 	} else {
 		/* Write loop */
-		while (uart->fifo_count < uart->fifo_limit	/* Can we write ? */
+		while (uart->fifo_count < uart->fifo_limit /* Can we write ? */
 		       && uart->buff_in_count > 0)	/* Do we want to? */
 			snd_uart16550_buffer_output(uart);
 	}
@@ -294,15 +294,16 @@
  */
 static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id)
 {
-	snd_uart16550_t *uart;
+	struct snd_uart16550 *uart;
 
-	uart = (snd_uart16550_t *) dev_id;
+	uart = dev_id;
 	spin_lock(&uart->open_lock);
 	if (uart->filemode == SERIAL_MODE_NOT_OPENED) {
 		spin_unlock(&uart->open_lock);
 		return IRQ_NONE;
 	}
-	inb(uart->base + UART_IIR);		/* indicate to the UART that the interrupt has been serviced */
+	/* indicate to the UART that the interrupt has been serviced */
+	inb(uart->base + UART_IIR);
 	snd_uart16550_io_loop(uart);
 	spin_unlock(&uart->open_lock);
 	return IRQ_HANDLED;
@@ -312,9 +313,9 @@
 static void snd_uart16550_buffer_timer(unsigned long data)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart;
+	struct snd_uart16550 *uart;
 
-	uart = (snd_uart16550_t *)data;
+	uart = (struct snd_uart16550 *)data;
 	spin_lock_irqsave(&uart->open_lock, flags);
 	snd_uart16550_del_timer(uart);
 	snd_uart16550_io_loop(uart);
@@ -326,7 +327,7 @@
  *  return 0 if found
  *  return negative error if not found
  */
-static int __init snd_uart16550_detect(snd_uart16550_t *uart)
+static int __devinit snd_uart16550_detect(struct snd_uart16550 *uart)
 {
 	unsigned long io_base = uart->base;
 	int ok;
@@ -343,7 +344,8 @@
 		return -EBUSY;
 	}
 
-	ok = 1;			/* uart detected unless one of the following tests should fail */
+	/* uart detected unless one of the following tests should fail */
+	ok = 1;
 	/* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */
 	outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */
 	c = inb(io_base + UART_IER);
@@ -368,7 +370,7 @@
 	return ok;
 }
 
-static void snd_uart16550_do_open(snd_uart16550_t * uart)
+static void snd_uart16550_do_open(struct snd_uart16550 * uart)
 {
 	char byte;
 
@@ -460,7 +462,7 @@
 	inb(uart->base + UART_RX);	/* Clear any pre-existing receive interrupt */
 }
 
-static void snd_uart16550_do_close(snd_uart16550_t * uart)
+static void snd_uart16550_do_close(struct snd_uart16550 * uart)
 {
 	if (uart->irq < 0)
 		snd_uart16550_del_timer(uart);
@@ -514,7 +516,7 @@
 static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = substream->rmidi->private_data;
+	struct snd_uart16550 *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	if (uart->filemode == SERIAL_MODE_NOT_OPENED)
@@ -528,7 +530,7 @@
 static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = substream->rmidi->private_data;
+	struct snd_uart16550 *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	uart->filemode &= ~SERIAL_MODE_INPUT_OPEN;
@@ -539,24 +541,24 @@
 	return 0;
 }
 
-static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream, int up)
+static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream,
+					int up)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = substream->rmidi->private_data;
+	struct snd_uart16550 *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
-	if (up) {
+	if (up)
 		uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED;
-	} else {
+	else
 		uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED;
-	}
 	spin_unlock_irqrestore(&uart->open_lock, flags);
 }
 
 static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = substream->rmidi->private_data;
+	struct snd_uart16550 *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	if (uart->filemode == SERIAL_MODE_NOT_OPENED)
@@ -570,7 +572,7 @@
 static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = substream->rmidi->private_data;
+	struct snd_uart16550 *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN;
@@ -581,18 +583,20 @@
 	return 0;
 };
 
-static inline int snd_uart16550_buffer_can_write( snd_uart16550_t *uart, int Num )
+static inline int snd_uart16550_buffer_can_write(struct snd_uart16550 *uart,
+						 int Num)
 {
-	if( uart->buff_in_count + Num < TX_BUFF_SIZE )
+	if (uart->buff_in_count + Num < TX_BUFF_SIZE)
 		return 1;
 	else
 		return 0;
 }
 
-static inline int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned char byte)
+static inline int snd_uart16550_write_buffer(struct snd_uart16550 *uart,
+					     unsigned char byte)
 {
 	unsigned short buff_in = uart->buff_in;
-	if( uart->buff_in_count < TX_BUFF_SIZE ) {
+	if (uart->buff_in_count < TX_BUFF_SIZE) {
 		uart->tx_buff[buff_in] = byte;
 		buff_in++;
 		buff_in &= TX_BUFF_MASK;
@@ -605,12 +609,14 @@
 		return 0;
 }
 
-static int snd_uart16550_output_byte(snd_uart16550_t *uart, struct snd_rawmidi_substream *substream, unsigned char midi_byte)
+static int snd_uart16550_output_byte(struct snd_uart16550 *uart,
+				     struct snd_rawmidi_substream *substream,
+				     unsigned char midi_byte)
 {
-	if (uart->buff_in_count == 0                            /* Buffer empty? */
+	if (uart->buff_in_count == 0                    /* Buffer empty? */
 	    && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA &&
 	    uart->adaptor != SNDRV_SERIAL_GENERIC) ||
-		(uart->fifo_count == 0                               /* FIFO empty? */
+		(uart->fifo_count == 0                  /* FIFO empty? */
 		 && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */
 
 	        /* Tx Buffer Empty - try to write immediately */
@@ -623,12 +629,13 @@
 			        uart->fifo_count++;
 				outb(midi_byte, uart->base + UART_TX);
 			} else {
-			        /* Cannot write (buffer empty) - put char in buffer */
+			        /* Cannot write (buffer empty) -
+				 * put char in buffer */
 				snd_uart16550_write_buffer(uart, midi_byte);
 			}
 		}
 	} else {
-		if( !snd_uart16550_write_buffer(uart, midi_byte) ) {
+		if (!snd_uart16550_write_buffer(uart, midi_byte)) {
 			snd_printk("%s: Buffer overrun on device at 0x%lx\n",
 				   uart->rmidi->name, uart->base);
 			return 0;
@@ -642,9 +649,9 @@
 {
 	unsigned long flags;
 	unsigned char midi_byte, addr_byte;
-	snd_uart16550_t *uart = substream->rmidi->private_data;
+	struct snd_uart16550 *uart = substream->rmidi->private_data;
 	char first;
-	static unsigned long lasttime=0;
+	static unsigned long lasttime = 0;
 	
 	/* Interupts are disabled during the updating of the tx_buff,
 	 * since it is 'bad' to have two processes updating the same
@@ -653,7 +660,7 @@
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 
-	if (uart->irq < 0)	//polling
+	if (uart->irq < 0)	/* polling */
 		snd_uart16550_io_loop(uart);
 
 	if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) {
@@ -671,7 +678,8 @@
 			/* select any combination of the four ports */
 			addr_byte = (substream->number << 4) | 0x08;
 			/* ...except none */
-			if (addr_byte == 0x08) addr_byte = 0xf8;
+			if (addr_byte == 0x08)
+				addr_byte = 0xf8;
 #endif
 			snd_uart16550_output_byte(uart, substream, addr_byte);
 			/* send midi byte */
@@ -679,31 +687,42 @@
 		}
 	} else {
 		first = 0;
-		while( 1 == snd_rawmidi_transmit_peek(substream, &midi_byte, 1) ) {
-			/* Also send F5 after 3 seconds with no data to handle device disconnect */
-			if (first == 0 && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS ||
-				uart->adaptor == SNDRV_SERIAL_GENERIC) &&
-			   (uart->prev_out != substream->number || jiffies-lasttime > 3*HZ)) {
+		while (snd_rawmidi_transmit_peek(substream, &midi_byte, 1) == 1) {
+			/* Also send F5 after 3 seconds with no data
+			 * to handle device disconnect */
+			if (first == 0 &&
+			    (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS ||
+			     uart->adaptor == SNDRV_SERIAL_GENERIC) &&
+			    (uart->prev_out != substream->number ||
+			     jiffies-lasttime > 3*HZ)) {
 
-				if( snd_uart16550_buffer_can_write( uart, 3 ) ) {
+				if (snd_uart16550_buffer_can_write(uart, 3)) {
 					/* Roland Soundcanvas part selection */
-					/* If this substream of the data is different previous
-					   substream in this uart, send the change part event */
+					/* If this substream of the data is
+					 * different previous substream
+					 * in this uart, send the change part
+					 * event
+					 */
 					uart->prev_out = substream->number;
 					/* change part */
-					snd_uart16550_output_byte(uart, substream, 0xf5);
+					snd_uart16550_output_byte(uart, substream,
+								  0xf5);
 					/* data */
-					snd_uart16550_output_byte(uart, substream, uart->prev_out + 1);
-					/* If midi_byte is a data byte, send the previous status byte */
-					if ((midi_byte < 0x80) && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS))
+					snd_uart16550_output_byte(uart, substream,
+								  uart->prev_out + 1);
+					/* If midi_byte is a data byte,
+					 * send the previous status byte */
+					if (midi_byte < 0x80 &&
+					    uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS)
 						snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]);
-				} else if( !uart->drop_on_full )
+				} else if (!uart->drop_on_full)
 					break;
 
 			}
 
 			/* send midi byte */
-			if( !snd_uart16550_output_byte(uart, substream, midi_byte) && !uart->drop_on_full )
+			if (!snd_uart16550_output_byte(uart, substream, midi_byte) &&
+			    !uart->drop_on_full )
 				break;
 
 			if (midi_byte >= 0x80 && midi_byte < 0xf0)
@@ -717,17 +736,17 @@
 	spin_unlock_irqrestore(&uart->open_lock, flags);
 }
 
-static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream, int up)
+static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream,
+					 int up)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = substream->rmidi->private_data;
+	struct snd_uart16550 *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
-	if (up) {
+	if (up)
 		uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED;
-	} else {
+	else
 		uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED;
-	}
 	spin_unlock_irqrestore(&uart->open_lock, flags);
 	if (up)
 		snd_uart16550_output_write(substream);
@@ -747,10 +766,10 @@
 	.trigger =	snd_uart16550_input_trigger,
 };
 
-static int snd_uart16550_free(snd_uart16550_t *uart)
+static int snd_uart16550_free(struct snd_uart16550 *uart)
 {
 	if (uart->irq >= 0)
-		free_irq(uart->irq, (void *)uart);
+		free_irq(uart->irq, uart);
 	release_and_free_resource(uart->res_base);
 	kfree(uart);
 	return 0;
@@ -758,23 +777,23 @@
 
 static int snd_uart16550_dev_free(struct snd_device *device)
 {
-	snd_uart16550_t *uart = device->device_data;
+	struct snd_uart16550 *uart = device->device_data;
 	return snd_uart16550_free(uart);
 }
 
-static int __init snd_uart16550_create(struct snd_card *card,
+static int __devinit snd_uart16550_create(struct snd_card *card,
 				       unsigned long iobase,
 				       int irq,
 				       unsigned int speed,
 				       unsigned int base,
 				       int adaptor,
 				       int droponfull,
-				       snd_uart16550_t **ruart)
+				       struct snd_uart16550 **ruart)
 {
 	static struct snd_device_ops ops = {
 		.dev_free =	snd_uart16550_dev_free,
 	};
-	snd_uart16550_t *uart;
+	struct snd_uart16550 *uart;
 	int err;
 
 
@@ -795,7 +814,7 @@
 
 	if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
 		if (request_irq(irq, snd_uart16550_interrupt,
-				IRQF_DISABLED, "Serial MIDI", (void *) uart)) {
+				IRQF_DISABLED, "Serial MIDI", uart)) {
 			snd_printk("irq %d busy. Using Polling.\n", irq);
 		} else {
 			uart->irq = irq;
@@ -841,25 +860,30 @@
 	return 0;
 }
 
-static void __init snd_uart16550_substreams(struct snd_rawmidi_str *stream)
+static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream)
 {
-	struct list_head *list;
+	struct snd_rawmidi_substream *substream;
 
-	list_for_each(list, &stream->substreams) {
-		struct snd_rawmidi_substream *substream = list_entry(list, struct snd_rawmidi_substream, list);
+	list_for_each_entry(substream, &stream->substreams, list) {
 		sprintf(substream->name, "Serial MIDI %d", substream->number + 1);
 	}
 }
 
-static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, struct snd_rawmidi **rmidi)
+static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
+				      int outs, int ins,
+				      struct snd_rawmidi **rmidi)
 {
 	struct snd_rawmidi *rrawmidi;
 	int err;
 
-	if ((err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, outs, ins, &rrawmidi)) < 0)
+	err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device,
+			      outs, ins, &rrawmidi);
+	if (err < 0)
 		return err;
-	snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input);
-	snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output);
+	snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+			    &snd_uart16550_input);
+	snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+			    &snd_uart16550_output);
 	strcpy(rrawmidi->name, "Serial MIDI");
 	snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);
 	snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);
@@ -872,10 +896,10 @@
 	return 0;
 }
 
-static int __init snd_serial_probe(struct platform_device *devptr)
+static int __devinit snd_serial_probe(struct platform_device *devptr)
 {
 	struct snd_card *card;
-	snd_uart16550_t *uart;
+	struct snd_uart16550 *uart;
 	int err;
 	int dev = devptr->id;
 
@@ -929,7 +953,8 @@
 					&uart)) < 0)
 		goto _err;
 
-	if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0)
+	err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi);
+	if (err < 0)
 		goto _err;
 
 	sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d",
@@ -956,7 +981,7 @@
 	return err;
 }
 
-static int snd_serial_remove(struct platform_device *devptr)
+static int __devexit snd_serial_remove(struct platform_device *devptr)
 {
 	snd_card_free(platform_get_drvdata(devptr));
 	platform_set_drvdata(devptr, NULL);
@@ -967,7 +992,7 @@
 
 static struct platform_driver snd_serial_driver = {
 	.probe		= snd_serial_probe,
-	.remove		= snd_serial_remove,
+	.remove		= __devexit_p( snd_serial_remove),
 	.driver		= {
 		.name	= SND_SERIAL_DRIVER
 	},
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 59171f8..46f3d34 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -44,7 +44,6 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/wait.h>
-#include <linux/sched.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/moduleparam.h>
@@ -85,7 +84,7 @@
 static struct platform_device *devices[SNDRV_CARDS];
 
 
-static int __init snd_virmidi_probe(struct platform_device *devptr)
+static int __devinit snd_virmidi_probe(struct platform_device *devptr)
 {
 	struct snd_card *card;
 	struct snd_card_virmidi *vmidi;
@@ -129,7 +128,7 @@
 	return err;
 }
 
-static int snd_virmidi_remove(struct platform_device *devptr)
+static int __devexit snd_virmidi_remove(struct platform_device *devptr)
 {
 	snd_card_free(platform_get_drvdata(devptr));
 	platform_set_drvdata(devptr, NULL);
@@ -140,7 +139,7 @@
 
 static struct platform_driver snd_virmidi_driver = {
 	.probe		= snd_virmidi_probe,
-	.remove		= snd_virmidi_remove,
+	.remove		= __devexit_p(snd_virmidi_remove),
 	.driver		= {
 		.name	= SND_VIRMIDI_DRIVER
 	},
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
index 1613ed8..f63152a 100644
--- a/sound/drivers/vx/vx_mixer.c
+++ b/sound/drivers/vx/vx_mixer.c
@@ -716,7 +716,7 @@
 	return 0;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0);
 
 static struct snd_kcontrol_new vx_control_audio_gain = {
 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
diff --git a/sound/i2c/Makefile b/sound/i2c/Makefile
index 816a2e7..45902d4 100644
--- a/sound/i2c/Makefile
+++ b/sound/i2c/Makefile
@@ -16,3 +16,4 @@
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o
 obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o
+obj-$(CONFIG_SND_ICE1724) += snd-i2c.o
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile
index 2fe023ef..77a8a7c 100644
--- a/sound/i2c/other/Makefile
+++ b/sound/i2c/other/Makefile
@@ -6,11 +6,11 @@
 snd-ak4114-objs := ak4114.o
 snd-ak4117-objs := ak4117.o
 snd-ak4xxx-adda-objs := ak4xxx-adda.o
+snd-pt2258-objs := pt2258.o
 snd-tea575x-tuner-objs := tea575x-tuner.o
 
 # Module Dependency
 obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
 obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
-obj-$(CONFIG_SND_ICE1724) += snd-ak4xxx-adda.o
-obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o
+obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4xxx-adda.o snd-pt2258.o
 obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index d2f2c50..adbfd58 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -42,8 +42,8 @@
 	ak4114->write(ak4114->private_data, reg, val);
 	if (reg <= AK4114_REG_INT1_MASK)
 		ak4114->regmap[reg] = val;
-	else if (reg >= AK4114_REG_RXCSB0 && reg <= AK4114_REG_TXCSB4)
-		ak4114->txcsb[reg-AK4114_REG_RXCSB0] = val;
+	else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4)
+		ak4114->txcsb[reg-AK4114_REG_TXCSB0] = val;
 }
 
 static inline unsigned char reg_read(struct ak4114 *ak4114, unsigned char reg)
@@ -66,10 +66,8 @@
 {
 	chip->init = 1;	/* don't schedule new work */
 	mb();
-	if (chip->workqueue != NULL) {
-		flush_workqueue(chip->workqueue);
-		destroy_workqueue(chip->workqueue);
-	}
+	cancel_delayed_work(&chip->work);
+	flush_scheduled_work();
 	kfree(chip);
 }
 
@@ -82,7 +80,7 @@
 
 int snd_ak4114_create(struct snd_card *card,
 		      ak4114_read_t *read, ak4114_write_t *write,
-		      unsigned char pgm[7], unsigned char txcsb[5],
+		      const unsigned char pgm[7], const unsigned char txcsb[5],
 		      void *private_data, struct ak4114 **r_ak4114)
 {
 	struct ak4114 *chip;
@@ -100,18 +98,13 @@
 	chip->read = read;
 	chip->write = write;
 	chip->private_data = private_data;
+	INIT_DELAYED_WORK(&chip->work, ak4114_stats);
 
 	for (reg = 0; reg < 7; reg++)
 		chip->regmap[reg] = pgm[reg];
 	for (reg = 0; reg < 5; reg++)
 		chip->txcsb[reg] = txcsb[reg];
 
-	chip->workqueue = create_workqueue("snd-ak4114");
-	if (chip->workqueue == NULL) {
-		kfree(chip);
-		return -ENOMEM;
-	}
-
 	snd_ak4114_reinit(chip);
 
 	chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT);
@@ -134,7 +127,8 @@
 	if (reg <= AK4114_REG_INT1_MASK)
 		reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val);
 	else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4)
-		reg_write(chip, reg, (chip->txcsb[reg] & ~mask) | val);
+		reg_write(chip, reg,
+			  (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val);
 }
 
 void snd_ak4114_reinit(struct ak4114 *chip)
@@ -143,7 +137,7 @@
 
 	chip->init = 1;
 	mb();
-	flush_workqueue(chip->workqueue);
+	flush_scheduled_work();
 	/* bring the chip to reset state and powerdown state */
 	reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN));
 	udelay(200);
@@ -158,8 +152,7 @@
 	reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN);
 	/* bring up statistics / event queing */
 	chip->init = 0;
-	INIT_DELAYED_WORK(&chip->work, ak4114_stats);
-	queue_delayed_work(chip->workqueue, &chip->work, HZ / 10);
+	schedule_delayed_work(&chip->work, HZ / 10);
 }
 
 static unsigned int external_rate(unsigned char rcs1)
@@ -568,7 +561,7 @@
 	if (chip->init)
 		return;
 	snd_ak4114_check_rate_and_errors(chip, 0);
-	queue_delayed_work(chip->workqueue, &chip->work, HZ / 10);
+	schedule_delayed_work(&chip->work, HZ / 10);
 }
 
 EXPORT_SYMBOL(snd_ak4114_create);
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index 4e45952..c022f29 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -74,7 +74,7 @@
 }
 
 int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write,
-		      unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117)
+		      const unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117)
 {
 	struct ak4117 *chip;
 	int err = 0;
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 5da49e2..8805110 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -140,7 +140,7 @@
  * Used for AK4524 input/ouput attenuation, AK4528, and
  * AK5365 input attenuation
  */
-static unsigned char vol_cvt_datt[128] = {
+static const unsigned char vol_cvt_datt[128] = {
 	0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04,
 	0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06,
 	0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a,
@@ -162,17 +162,17 @@
 /*
  * dB tables
  */
-static DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1);
-static DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1);
-static DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1);
-static DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1);
+static const DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0);
 
 /*
  * initialize all the ak4xxx chips
  */
 void snd_akm4xxx_init(struct snd_akm4xxx *ak)
 {
-	static unsigned char inits_ak4524[] = {
+	static const unsigned char inits_ak4524[] = {
 		0x00, 0x07, /* 0: all power up */
 		0x01, 0x00, /* 1: ADC/DAC reset */
 		0x02, 0x60, /* 2: 24bit I2S */
@@ -184,7 +184,7 @@
 		0x07, 0x00, /* 7: DAC right muted */
 		0xff, 0xff
 	};
-	static unsigned char inits_ak4528[] = {
+	static const unsigned char inits_ak4528[] = {
 		0x00, 0x07, /* 0: all power up */
 		0x01, 0x00, /* 1: ADC/DAC reset */
 		0x02, 0x60, /* 2: 24bit I2S */
@@ -194,7 +194,7 @@
 		0x05, 0x00, /* 5: ADC right muted */
 		0xff, 0xff
 	};
-	static unsigned char inits_ak4529[] = {
+	static const unsigned char inits_ak4529[] = {
 		0x09, 0x01, /* 9: ATS=0, RSTN=1 */
 		0x0a, 0x3f, /* A: all power up, no zero/overflow detection */
 		0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */
@@ -210,7 +210,7 @@
 		0x08, 0x55, /* 8: deemphasis all off */
 		0xff, 0xff
 	};
-	static unsigned char inits_ak4355[] = {
+	static const unsigned char inits_ak4355[] = {
 		0x01, 0x02, /* 1: reset and soft-mute */
 		0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect,
 			     * disable DZF, sharp roll-off, RSTN#=0 */
@@ -227,7 +227,7 @@
 		0x01, 0x01, /* 1: un-reset, unmute */
 		0xff, 0xff
 	};
-	static unsigned char inits_ak4358[] = {
+	static const unsigned char inits_ak4358[] = {
 		0x01, 0x02, /* 1: reset and soft-mute */
 		0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect,
 			     * disable DZF, sharp roll-off, RSTN#=0 */
@@ -246,7 +246,7 @@
 		0x01, 0x01, /* 1: un-reset, unmute */
 		0xff, 0xff
 	};
-	static unsigned char inits_ak4381[] = {
+	static const unsigned char inits_ak4381[] = {
 		0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */
 		0x01, 0x02, /* 1: de-emphasis off, normal speed,
 			     * sharp roll-off, DZF off */
@@ -259,7 +259,8 @@
 	};
 
 	int chip, num_chips;
-	unsigned char *ptr, reg, data, *inits;
+	const unsigned char *ptr, *inits;
+	unsigned char reg, data;
 
 	memset(ak->images, 0, sizeof(ak->images));
 	memset(ak->volumes, 0, sizeof(ak->volumes));
@@ -513,6 +514,66 @@
 	return change;
 }
 
+#define AK5365_NUM_INPUTS 5
+
+static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_info *uinfo)
+{
+	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
+	int mixer_ch = AK_GET_SHIFT(kcontrol->private_value);
+	const char **input_names;
+	int  num_names, idx;
+
+	input_names = ak->adc_info[mixer_ch].input_names;
+
+	num_names = 0;
+	while (num_names < AK5365_NUM_INPUTS && input_names[num_names])
+		++num_names;
+	
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = num_names;
+	idx = uinfo->value.enumerated.item;
+	if (idx >= num_names)
+		return -EINVAL;
+	strncpy(uinfo->value.enumerated.name, input_names[idx],
+		sizeof(uinfo->value.enumerated.name));
+	return 0;
+}
+
+static int ak4xxx_capture_source_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
+	int chip = AK_GET_CHIP(kcontrol->private_value);
+	int addr = AK_GET_ADDR(kcontrol->private_value);
+	int mask = AK_GET_MASK(kcontrol->private_value);
+	unsigned char val;
+
+	val = snd_akm4xxx_get(ak, chip, addr) & mask;
+	ucontrol->value.enumerated.item[0] = val;
+	return 0;
+}
+
+static int ak4xxx_capture_source_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
+	int chip = AK_GET_CHIP(kcontrol->private_value);
+	int addr = AK_GET_ADDR(kcontrol->private_value);
+	int mask = AK_GET_MASK(kcontrol->private_value);
+	unsigned char oval, val;
+
+	oval = snd_akm4xxx_get(ak, chip, addr);
+	val = oval & ~mask;
+	val |= ucontrol->value.enumerated.item[0] & mask;
+	if (val != oval) {
+		snd_akm4xxx_write(ak, chip, addr, val);
+		return 1;
+	}
+	return 0;
+}
+
 /*
  * build AK4xxx controls
  */
@@ -647,9 +708,10 @@
 
 		if (ak->type == SND_AK5365 && (idx % 2) == 0) {
 			if (! ak->adc_info || 
-			    ! ak->adc_info[mixer_ch].switch_name)
+			    ! ak->adc_info[mixer_ch].switch_name) {
 				knew.name = "Capture Switch";
-			else
+				knew.index = mixer_ch + ak->idx_offset * 2;
+			} else
 				knew.name = ak->adc_info[mixer_ch].switch_name;
 			knew.info = ak4xxx_switch_info;
 			knew.get = ak4xxx_switch_get;
@@ -662,6 +724,26 @@
 			err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
 			if (err < 0)
 				return err;
+
+			memset(&knew, 0, sizeof(knew));
+			knew.name = ak->adc_info[mixer_ch].selector_name;
+			if (!knew.name) {
+				knew.name = "Capture Channel";
+				knew.index = mixer_ch + ak->idx_offset * 2;
+			}
+
+			knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+			knew.info = ak4xxx_capture_source_info;
+			knew.get = ak4xxx_capture_source_get;
+			knew.put = ak4xxx_capture_source_put;
+			knew.access = 0;
+			/* input selector control: reg. 1, bits 0-2.
+			 * mis-use 'shift' to pass mixer_ch */
+			knew.private_value
+				= AK_COMPOSE(idx/2, 1, mixer_ch, 0x07);
+			err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
+			if (err < 0)
+				return err;
 		}
 
 		idx += num_stereo;
diff --git a/sound/i2c/other/pt2258.c b/sound/i2c/other/pt2258.c
new file mode 100644
index 0000000..e91cc3b
--- /dev/null
+++ b/sound/i2c/other/pt2258.c
@@ -0,0 +1,233 @@
+/*
+ *   ALSA Driver for the PT2258 volume controller.
+ *
+ *	Copyright (c) 2006  Jochen Voss <voss@seehuhn.de>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */      
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include <sound/i2c.h>
+#include <sound/pt2258.h>
+
+MODULE_AUTHOR("Jochen Voss <voss@seehuhn.de>");
+MODULE_DESCRIPTION("PT2258 volume controller (Princeton Technology Corp.)");
+MODULE_LICENSE("GPL");
+
+#define PT2258_CMD_RESET 0xc0
+#define PT2258_CMD_UNMUTE 0xf8
+#define PT2258_CMD_MUTE 0xf9
+
+static const unsigned char pt2258_channel_code[12] = {
+	0x80, 0x90,		/* channel 1: -10dB, -1dB */
+	0x40, 0x50,		/* channel 2: -10dB, -1dB */
+	0x00, 0x10,		/* channel 3: -10dB, -1dB */
+	0x20, 0x30,		/* channel 4: -10dB, -1dB */
+	0x60, 0x70,		/* channel 5: -10dB, -1dB */
+	0xa0, 0xb0		/* channel 6: -10dB, -1dB */
+};
+
+int snd_pt2258_reset(struct snd_pt2258 *pt)
+{
+	unsigned char bytes[2];
+	int i;
+
+	/* reset chip */
+	bytes[0] = PT2258_CMD_RESET;
+	snd_i2c_lock(pt->i2c_bus);
+	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
+		goto __error;
+	snd_i2c_unlock(pt->i2c_bus);
+
+	/* mute all channels */
+	pt->mute = 1;
+	bytes[0] = PT2258_CMD_MUTE;
+	snd_i2c_lock(pt->i2c_bus);
+	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
+		goto __error;
+	snd_i2c_unlock(pt->i2c_bus);
+
+	/* set all channels to 0dB */
+	for (i = 0; i < 6; ++i)
+		pt->volume[i] = 0;
+	bytes[0] = 0xd0;
+	bytes[1] = 0xe0;
+	snd_i2c_lock(pt->i2c_bus);
+	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
+		goto __error;
+	snd_i2c_unlock(pt->i2c_bus);
+
+	return 0;
+
+      __error:
+	snd_i2c_unlock(pt->i2c_bus);
+	snd_printk(KERN_ERR "PT2258 reset failed\n");
+	return -EIO;
+}
+
+static int pt2258_stereo_volume_info(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 79;
+	return 0;
+}
+
+static int pt2258_stereo_volume_get(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pt2258 *pt = kcontrol->private_data;
+	int base = kcontrol->private_value;
+
+	/* chip does not support register reads */
+	ucontrol->value.integer.value[0] = 79 - pt->volume[base];
+	ucontrol->value.integer.value[1] = 79 - pt->volume[base + 1];
+	return 0;
+}
+
+static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pt2258 *pt = kcontrol->private_data;
+	int base = kcontrol->private_value;
+	unsigned char bytes[2];
+	int val0, val1;
+
+	val0 = 79 - ucontrol->value.integer.value[0];
+	val1 = 79 - ucontrol->value.integer.value[1];
+	if (val0 == pt->volume[base] && val1 == pt->volume[base + 1])
+		return 0;
+
+	pt->volume[base] = val0;
+	bytes[0] = pt2258_channel_code[2 * base] | (val0 / 10);
+	bytes[1] = pt2258_channel_code[2 * base + 1] | (val0 % 10);
+	snd_i2c_lock(pt->i2c_bus);
+	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
+		goto __error;
+	snd_i2c_unlock(pt->i2c_bus);
+
+	pt->volume[base + 1] = val1;
+	bytes[0] = pt2258_channel_code[2 * base + 2] | (val1 / 10);
+	bytes[1] = pt2258_channel_code[2 * base + 3] | (val1 % 10);
+	snd_i2c_lock(pt->i2c_bus);
+	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
+		goto __error;
+	snd_i2c_unlock(pt->i2c_bus);
+
+	return 1;
+
+      __error:
+	snd_i2c_unlock(pt->i2c_bus);
+	snd_printk(KERN_ERR "PT2258 access failed\n");
+	return -EIO;
+}
+
+static int pt2258_switch_info(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int pt2258_switch_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pt2258 *pt = kcontrol->private_data;
+
+	ucontrol->value.integer.value[0] = !pt->mute;
+	return 0;
+}
+
+static int pt2258_switch_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pt2258 *pt = kcontrol->private_data;
+	unsigned char bytes[2];
+	int val;
+
+	val = !ucontrol->value.integer.value[0];
+	if (pt->mute == val)
+		return 0;
+
+	pt->mute = val;
+	bytes[0] = val ? PT2258_CMD_MUTE : PT2258_CMD_UNMUTE;
+	snd_i2c_lock(pt->i2c_bus);
+	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
+		goto __error;
+	snd_i2c_unlock(pt->i2c_bus);
+
+	return 1;
+
+      __error:
+	snd_i2c_unlock(pt->i2c_bus);
+	snd_printk(KERN_ERR "PT2258 access failed 2\n");
+	return -EIO;
+}
+
+static const DECLARE_TLV_DB_SCALE(pt2258_db_scale, -7900, 100, 0);
+
+int snd_pt2258_build_controls(struct snd_pt2258 *pt)
+{
+	struct snd_kcontrol_new knew;
+	char *names[3] = {
+		"Mic Loopback Playback Volume",
+		"Line Loopback Playback Volume",
+		"CD Loopback Playback Volume"
+	};
+	int i, err;
+
+	for (i = 0; i < 3; ++i) {
+		memset(&knew, 0, sizeof(knew));
+		knew.name = names[i];
+		knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+		knew.count = 1;
+		knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+		    SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+		knew.private_value = 2 * i;
+		knew.info = pt2258_stereo_volume_info;
+		knew.get = pt2258_stereo_volume_get;
+		knew.put = pt2258_stereo_volume_put;
+		knew.tlv.p = pt2258_db_scale;
+
+		err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt));
+		if (err < 0)
+			return err;
+	}
+
+	memset(&knew, 0, sizeof(knew));
+	knew.name = "Loopback Switch";
+	knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	knew.info = pt2258_switch_info;
+	knew.get = pt2258_switch_get;
+	knew.put = pt2258_switch_put;
+	knew.access = 0;
+	err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt));
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(snd_pt2258_reset);
+EXPORT_SYMBOL(snd_pt2258_build_controls);
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 57371f1..4e3a972 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -358,6 +358,7 @@
 config SND_SB16_CSP
 	bool "Sound Blaster 16/AWE CSP support"
 	depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC)
+	select FW_LOADER
 	help
 	  Say Y here to include support for the CSP core.  This special
 	  coprocessor can do variable tasks like various compression and
@@ -390,6 +391,7 @@
 config SND_WAVEFRONT
 	tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
 	depends on SND
+	select FW_LOADER
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_CS4231_LIB
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index b524e0d..ec9209c 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -906,11 +906,11 @@
 	return change;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
 
 static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = {
 AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 99908e4..74e501d 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -65,7 +65,7 @@
 static struct platform_device *devices[SNDRV_CARDS];
 
 
-static int __init snd_ad1848_probe(struct platform_device *pdev)
+static int __devinit snd_ad1848_probe(struct platform_device *pdev)
 {
 	int dev = pdev->id;
 	struct snd_card *card;
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index 666b3bc..8094282 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -1223,9 +1223,9 @@
 
 EXPORT_SYMBOL(snd_ad1848_add_ctl_elem);
 
-static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
 
 static struct ad1848_mix_elem snd_ad1848_controls[] = {
 AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index d1f6dfc..c09a800 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -574,7 +574,7 @@
 	return 0;
 }
 
-static int snd_cmi8330_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_cmi8330_nonpnp_remove(struct platform_device *devptr)
 {
 	snd_card_free(platform_get_drvdata(devptr));
 	platform_set_drvdata(devptr, NULL);
@@ -597,7 +597,7 @@
 
 static struct platform_driver snd_cmi8330_driver = {
 	.probe		= snd_cmi8330_nonpnp_probe,
-	.remove		= snd_cmi8330_nonpnp_remove,
+	.remove		= __devexit_p(snd_cmi8330_nonpnp_remove),
 #ifdef CONFIG_PM
 	.suspend	= snd_cmi8330_nonpnp_suspend,
 	.resume		= snd_cmi8330_nonpnp_resume,
diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c
index c20a4b1..ce57d52 100644
--- a/sound/isa/dt019x.c
+++ b/sound/isa/dt019x.c
@@ -23,7 +23,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/pnp.h>
 #include <linux/moduleparam.h>
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 7f29f56..65f97ff 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -73,7 +73,7 @@
 
 #define PFX	"es1688: "
 
-static int __init snd_es1688_probe(struct platform_device *pdev)
+static int __devinit snd_es1688_probe(struct platform_device *pdev)
 {
 	int dev = pdev->id;
 	static int possible_irqs[] = {5, 9, 10, 7, -1};
@@ -171,7 +171,7 @@
 	return err;
 }
 
-static int snd_es1688_remove(struct platform_device *devptr)
+static int __devexit snd_es1688_remove(struct platform_device *devptr)
 {
 	snd_card_free(platform_get_drvdata(devptr));
 	platform_set_drvdata(devptr, NULL);
@@ -182,7 +182,7 @@
 
 static struct platform_driver snd_es1688_driver = {
 	.probe		= snd_es1688_probe,
-	.remove		= snd_es1688_remove,
+	.remove		= __devexit_p(snd_es1688_remove),
 	/* FIXME: suspend/resume */
 	.driver		= {
 		.name	= ES1688_DRIVER
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index b680fdd..8ced5e8 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -294,10 +294,10 @@
 		gus->mix_cntrl_reg |= 4;	/* enable MIC */
 	}
 	dma1 = gus->gf1.dma1;
-	dma1 = dma1 < 0 ? -dma1 : dma1;
+	dma1 = abs(dma1);
 	dma1 = dmas[dma1 & 7];
 	dma2 = gus->gf1.dma2;
-	dma2 = dma2 < 0 ? -dma2 : dma2;
+	dma2 = abs(dma2);
 	dma2 = dmas[dma2 & 7];
 	dma1 |= gus->equal_dma ? 0x40 : (dma2 << 3);
 
@@ -306,7 +306,7 @@
 		return -EINVAL;
 	}
 	irq = gus->gf1.irq;
-	irq = irq < 0 ? -irq : irq;
+	irq = abs(irq);
 	irq = irqs[irq & 0x0f];
 	if (irq == 0) {
 		snd_printk(KERN_ERR "Error! IRQ isn't defined.\n");
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 37057a3..0395e2e 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -76,7 +76,7 @@
 
 #define PFX	"gusclassic: "
 
-static int __init snd_gusclassic_detect(struct snd_gus_card * gus)
+static int __devinit snd_gusclassic_detect(struct snd_gus_card * gus)
 {
 	unsigned char d;
 
@@ -95,7 +95,7 @@
 	return 0;
 }
 
-static void __init snd_gusclassic_init(int dev, struct snd_gus_card * gus)
+static void __devinit snd_gusclassic_init(int dev, struct snd_gus_card * gus)
 {
 	gus->equal_irq = 0;
 	gus->codec_flag = 0;
@@ -103,7 +103,7 @@
 	gus->joystick_dac = joystick_dac[dev];
 }
 
-static int __init snd_gusclassic_probe(struct platform_device *pdev)
+static int __devinit snd_gusclassic_probe(struct platform_device *pdev)
 {
 	int dev = pdev->id;
 	static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
@@ -211,7 +211,7 @@
 	return err;
 }
 
-static int snd_gusclassic_remove(struct platform_device *devptr)
+static int __devexit snd_gusclassic_remove(struct platform_device *devptr)
 {
 	snd_card_free(platform_get_drvdata(devptr));
 	platform_set_drvdata(devptr, NULL);
@@ -222,7 +222,7 @@
 
 static struct platform_driver snd_gusclassic_driver = {
 	.probe		= snd_gusclassic_probe,
-	.remove		= snd_gusclassic_remove,
+	.remove		= __devexit_p(snd_gusclassic_remove),
 	/* FIXME: suspend/resume */
 	.driver		= {
 		.name	= GUSCLASSIC_DRIVER
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index 532c56e..4f55fc3 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -92,7 +92,7 @@
 
 #define PFX	"gusextreme: "
 
-static int __init snd_gusextreme_detect(int dev,
+static int __devinit snd_gusextreme_detect(int dev,
 					struct snd_card *card,
 					struct snd_gus_card * gus,
 					struct snd_es1688 *es1688)
@@ -142,12 +142,12 @@
 	return 0;
 }
 
-static void __init snd_gusextreme_init(int dev, struct snd_gus_card * gus)
+static void __devinit snd_gusextreme_init(int dev, struct snd_gus_card * gus)
 {
 	gus->joystick_dac = joystick_dac[dev];
 }
 
-static int __init snd_gusextreme_mixer(struct snd_es1688 *chip)
+static int __devinit snd_gusextreme_mixer(struct snd_es1688 *chip)
 {
 	struct snd_card *card = chip->card;
 	struct snd_ctl_elem_id id1, id2;
@@ -169,7 +169,7 @@
 	return 0;
 }
 
-static int __init snd_gusextreme_probe(struct platform_device *pdev)
+static int __devinit snd_gusextreme_probe(struct platform_device *pdev)
 {
 	int dev = pdev->id;
 	static int possible_ess_irqs[] = {5, 9, 10, 7, -1};
@@ -321,7 +321,7 @@
 	return err;
 }
 
-static int snd_gusextreme_remove(struct platform_device *devptr)
+static int __devexit snd_gusextreme_remove(struct platform_device *devptr)
 {
 	snd_card_free(platform_get_drvdata(devptr));
 	platform_set_drvdata(devptr, NULL);
@@ -332,7 +332,7 @@
 
 static struct platform_driver snd_gusextreme_driver = {
 	.probe		= snd_gusextreme_probe,
-	.remove		= snd_gusextreme_remove,
+	.remove		= __devexit_p(snd_gusextreme_remove),
 	/* FIXME: suspend/resume */
 	.driver		= {
 		.name	= GUSEXTREME_DRIVER
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index c1c69e3..d1ad90c 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -85,7 +85,7 @@
 
 #define PFX	"gusmax: "
 
-static int __init snd_gusmax_detect(struct snd_gus_card * gus)
+static int __devinit snd_gusmax_detect(struct snd_gus_card * gus)
 {
 	unsigned char d;
 
@@ -127,7 +127,8 @@
 	return IRQ_RETVAL(handled);
 }
 
-static void __init snd_gusmax_init(int dev, struct snd_card *card, struct snd_gus_card * gus)
+static void __devinit snd_gusmax_init(int dev, struct snd_card *card,
+				      struct snd_gus_card * gus)
 {
 	gus->equal_irq = 1;
 	gus->codec_flag = 1;
@@ -145,7 +146,7 @@
 #define CS4231_PRIVATE( left, right, shift, mute ) \
 			((left << 24)|(right << 16)|(shift<<8)|mute)
 
-static int __init snd_gusmax_mixer(struct snd_cs4231 *chip)
+static int __devinit snd_gusmax_mixer(struct snd_cs4231 *chip)
 {
 	struct snd_card *card = chip->card;
 	struct snd_ctl_elem_id id1, id2;
@@ -204,7 +205,7 @@
 		free_irq(maxcard->irq, (void *)maxcard);
 }
 
-static int __init snd_gusmax_probe(struct platform_device *pdev)
+static int __devinit snd_gusmax_probe(struct platform_device *pdev)
 {
 	int dev = pdev->id;
 	static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
@@ -348,7 +349,7 @@
 	return err;
 }
 
-static int snd_gusmax_remove(struct platform_device *devptr)
+static int __devexit snd_gusmax_remove(struct platform_device *devptr)
 {
 	snd_card_free(platform_get_drvdata(devptr));
 	platform_set_drvdata(devptr, NULL);
@@ -359,7 +360,7 @@
 
 static struct platform_driver snd_gusmax_driver = {
 	.probe		= snd_gusmax_probe,
-	.remove		= snd_gusmax_remove,
+	.remove		= __devexit_p(snd_gusmax_remove),
 	/* FIXME: suspend/resume */
 	.driver		= {
 		.name	= GUSMAX_DRIVER
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 419b4eb..f3db686 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -486,8 +486,8 @@
 	return change;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_master, -3000, 200, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_master, -3000, 200, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
 
 static struct snd_kcontrol_new snd_opl3sa2_controls[] = {
 OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1),
@@ -919,7 +919,7 @@
 	return 0;
 }
 
-static int snd_opl3sa2_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_opl3sa2_nonpnp_remove(struct platform_device *devptr)
 {
 	snd_card_free(platform_get_drvdata(devptr));
 	platform_set_drvdata(devptr, NULL);
@@ -942,7 +942,7 @@
 
 static struct platform_driver snd_opl3sa2_nonpnp_driver = {
 	.probe		= snd_opl3sa2_nonpnp_probe,
-	.remove		= snd_opl3sa2_nonpnp_remove,
+	.remove		= __devexit( snd_opl3sa2_nonpnp_remove),
 #ifdef CONFIG_PM
 	.suspend	= snd_opl3sa2_nonpnp_suspend,
 	.resume		= snd_opl3sa2_nonpnp_resume,
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index fcd6380..3d9d7e0 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -161,10 +161,13 @@
  */
 static void snd_sb_csp_free(struct snd_hwdep *hwdep)
 {
+	int i;
 	struct snd_sb_csp *p = hwdep->private_data;
 	if (p) {
 		if (p->running & SNDRV_SB_CSP_ST_RUNNING)
 			snd_sb_csp_stop(p);
+		for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i)
+			release_firmware(p->csp_programs[i]);
 		kfree(p);
 	}
 }
@@ -687,8 +690,50 @@
 	return err;
 }
 
+#define FIRMWARE_IN_THE_KERNEL
+
+#ifdef FIRMWARE_IN_THE_KERNEL
 #include "sb16_csp_codecs.h"
 
+static const struct firmware snd_sb_csp_static_programs[] = {
+	{ .data = mulaw_main, .size = sizeof mulaw_main },
+	{ .data = alaw_main, .size = sizeof alaw_main },
+	{ .data = ima_adpcm_init, .size = sizeof ima_adpcm_init },
+	{ .data = ima_adpcm_playback, .size = sizeof ima_adpcm_playback },
+	{ .data = ima_adpcm_capture, .size = sizeof ima_adpcm_capture },
+};
+#endif
+
+static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags)
+{
+	static const char *const names[] = {
+		"sb16/mulaw_main.csp",
+		"sb16/alaw_main.csp",
+		"sb16/ima_adpcm_init.csp",
+		"sb16/ima_adpcm_playback.csp",
+		"sb16/ima_adpcm_capture.csp",
+	};
+	const struct firmware *program;
+	int err;
+
+	BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT);
+	program = p->csp_programs[index];
+	if (!program) {
+		err = request_firmware(&program, names[index],
+				       p->chip->card->dev);
+		if (err >= 0)
+			p->csp_programs[index] = program;
+		else {
+#ifdef FIRMWARE_IN_THE_KERNEL
+			program = &snd_sb_csp_static_programs[index];
+#else
+			return err;
+#endif
+		}
+	}
+	return snd_sb_csp_load(p, program->data, program->size, flags);
+}
+
 /*
  * autoload hardware codec if necessary
  * return 0 if CSP is loaded and ready to run (p->running != 0)
@@ -708,27 +753,27 @@
 	} else {
 		switch (pcm_sfmt) {
 		case SNDRV_PCM_FORMAT_MU_LAW:
-			err = snd_sb_csp_load(p, &mulaw_main[0], sizeof(mulaw_main), 0);
+			err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_MULAW, 0);
 			p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW;
 			p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE;
 			break;
 		case SNDRV_PCM_FORMAT_A_LAW:
-			err = snd_sb_csp_load(p, &alaw_main[0], sizeof(alaw_main), 0);
+			err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ALAW, 0);
 			p->acc_format = SNDRV_PCM_FMTBIT_A_LAW;
 			p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE;
 			break;
 		case SNDRV_PCM_FORMAT_IMA_ADPCM:
-			err = snd_sb_csp_load(p, &ima_adpcm_init[0], sizeof(ima_adpcm_init),
-					      SNDRV_SB_CSP_LOAD_INITBLOCK);
+			err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ADPCM_INIT,
+						       SNDRV_SB_CSP_LOAD_INITBLOCK);
 			if (err)
 				break;
 			if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) {
-				err = snd_sb_csp_load(p, &ima_adpcm_playback[0],
-						      sizeof(ima_adpcm_playback), 0);
+				err = snd_sb_csp_firmware_load
+					(p, CSP_PROGRAM_ADPCM_PLAYBACK, 0);
 				p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE;
 			} else {
-				err = snd_sb_csp_load(p, &ima_adpcm_capture[0],
-						      sizeof(ima_adpcm_capture), 0);
+				err = snd_sb_csp_firmware_load
+					(p, CSP_PROGRAM_ADPCM_CAPTURE, 0);
 				p->mode = SNDRV_SB_CSP_MODE_DSP_READ;
 			}
 			p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM;
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 268ebd3..be1e83e 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -83,7 +83,7 @@
 	release_and_free_resource(acard->fm_res);
 }
 
-static int __init snd_sb8_probe(struct platform_device *pdev)
+static int __devinit snd_sb8_probe(struct platform_device *pdev)
 {
 	int dev = pdev->id;
 	struct snd_sb *chip;
@@ -193,7 +193,7 @@
 	return err;
 }
 
-static int snd_sb8_remove(struct platform_device *pdev)
+static int __devexit snd_sb8_remove(struct platform_device *pdev)
 {
 	snd_card_free(platform_get_drvdata(pdev));
 	platform_set_drvdata(pdev, NULL);
@@ -230,7 +230,7 @@
 
 static struct platform_driver snd_sb8_driver = {
 	.probe		= snd_sb8_probe,
-	.remove		= snd_sb8_remove,
+	.remove		= __devexit_p(snd_sb8_remove),
 #ifdef CONFIG_PM
 	.suspend	= snd_sb8_suspend,
 	.resume		= snd_sb8_resume,
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 85db535..e2fdd5f 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -402,6 +402,7 @@
 	init_waitqueue_head(&acard->wavefront.interrupt_sleeper);
 	spin_lock_init(&acard->wavefront.midi.open);
 	spin_lock_init(&acard->wavefront.midi.virtual);
+	acard->wavefront.card = card;
 	card->private_free = snd_wavefront_free;
 
 	return card;
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index 4f0846f..15331ed 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/time.h>
 #include <linux/wait.h>
+#include <linux/firmware.h>
 #include <sound/core.h>
 #include <sound/snd_wavefront.h>
 #include <sound/initval.h>
@@ -32,325 +33,17 @@
 #define FX_MSB_TRANSFER 0x02    /* transfer after DSP MSB byte written */
 #define FX_AUTO_INCR    0x04    /* auto-increment DSP address after transfer */
 
-/* weird stuff, derived from port I/O tracing with dosemu */
+#define WAIT_IDLE	0xff
 
-static unsigned char page_zero[] __devinitdata = {
-0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00,
-0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00,
-0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x19,
-0x01, 0x1a, 0x01, 0x20, 0x01, 0x40, 0x01, 0x17, 0x00, 0x00, 0x01,
-0x80, 0x01, 0x20, 0x00, 0x10, 0x01, 0xa0, 0x03, 0xd1, 0x00, 0x00,
-0x01, 0xf2, 0x02, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf4, 0x02,
-0xe0, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17,
-0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x00, 0x00,
-0x40, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x60, 0x00, 0x00,
-0x00, 0x92, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb3, 0x02,
-0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x40,
-0x00, 0x80, 0x00, 0xf5, 0x00, 0x20, 0x00, 0x70, 0x00, 0xa0, 0x02,
-0x11, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
-0x02, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x17, 0x00, 0x1b, 0x00,
-0x1d, 0x02, 0xdf
-};
+#define FIRMWARE_IN_THE_KERNEL
 
-static unsigned char page_one[] __devinitdata = {
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
-0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00,
-0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01,
-0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x02, 0x60,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x80, 0x00,
-0x00, 0x02, 0xfb, 0x02, 0xa0, 0x00, 0x00, 0x00, 0x1b, 0x02, 0xd7,
-0x00, 0x00, 0x02, 0xf7, 0x03, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x1c, 0x03, 0x3c, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x03, 0xc0,
-0x00, 0x00, 0x03, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5d, 0x00,
-0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x03, 0xc0,
-0x00, 0x00, 0x03, 0x9e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03,
-0xbe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-0xdb, 0x00, 0x00, 0x02, 0xdb, 0x00, 0x00, 0x02, 0xe0, 0x00, 0x00,
-0x02, 0xfb, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x40, 0x02, 0xfb, 0x02,
-0x60, 0x00, 0x1b
+#ifdef FIRMWARE_IN_THE_KERNEL
+#include "yss225.c"
+static const struct firmware yss225_registers_firmware = {
+	.data = (u8 *)yss225_registers,
+	.size = sizeof yss225_registers
 };
-
-static unsigned char page_two[] __devinitdata = {
-0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4,
-0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x07,
-0x05, 0x05, 0x05, 0x04, 0x07, 0x05, 0x04, 0x07, 0x05, 0x44, 0x46,
-0x44, 0x46, 0x46, 0x07, 0x05, 0x44, 0x46, 0x05, 0x46, 0x05, 0x46,
-0x05, 0x46, 0x05, 0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07,
-0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07, 0x44, 0x05, 0x05,
-0x05, 0x44, 0x05, 0x05, 0x05, 0x46, 0x05, 0x46, 0x05, 0x46, 0x05,
-0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44
-};
-
-static unsigned char page_three[] __devinitdata = {
-0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06,
-0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
-0xc0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00,
-0x60, 0x00, 0x70, 0x00, 0x40, 0x00, 0x40, 0x00, 0x42, 0x00, 0x40,
-0x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
-0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
-0x00, 0x42, 0x00, 0x40, 0x00, 0x42, 0x00, 0x02, 0x00, 0x02, 0x00,
-0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40
-};
-
-static unsigned char page_four[] __devinitdata = {
-0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02,
-0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
-0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, 0x00,
-0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60,
-0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00,
-0x20, 0x00, 0x22, 0x02, 0x22, 0x02, 0x20, 0x00, 0x60, 0x00, 0x22,
-0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01
-};
-
-static unsigned char page_six[] __devinitdata = {
-0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00,
-0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e,
-0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00,
-0x16, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1c, 0x00,
-0x00, 0x1e, 0x00, 0x00, 0x20, 0x00, 0x00, 0x22, 0x00, 0x00, 0x24,
-0x00, 0x00, 0x26, 0x00, 0x00, 0x28, 0x00, 0x00, 0x2a, 0x00, 0x00,
-0x2c, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x30, 0x00, 0x00, 0x32, 0x00,
-0x00, 0x34, 0x00, 0x00, 0x36, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3a,
-0x00, 0x00, 0x3c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x40, 0x00, 0x00,
-0x42, 0x03, 0x00, 0x44, 0x01, 0x00, 0x46, 0x0a, 0x21, 0x48, 0x0d,
-0x23, 0x4a, 0x23, 0x1b, 0x4c, 0x37, 0x8f, 0x4e, 0x45, 0x77, 0x50,
-0x52, 0xe2, 0x52, 0x1c, 0x92, 0x54, 0x1c, 0x52, 0x56, 0x07, 0x00,
-0x58, 0x2f, 0xc6, 0x5a, 0x0b, 0x00, 0x5c, 0x30, 0x06, 0x5e, 0x17,
-0x00, 0x60, 0x3d, 0xda, 0x62, 0x29, 0x00, 0x64, 0x3e, 0x41, 0x66,
-0x39, 0x00, 0x68, 0x4c, 0x48, 0x6a, 0x49, 0x00, 0x6c, 0x4c, 0x6c,
-0x6e, 0x11, 0xd2, 0x70, 0x16, 0x0c, 0x72, 0x00, 0x00, 0x74, 0x00,
-0x80, 0x76, 0x0f, 0x00, 0x78, 0x00, 0x80, 0x7a, 0x13, 0x00, 0x7c,
-0x80, 0x00, 0x7e, 0x80, 0x80
-};
-
-static unsigned char page_seven[] __devinitdata = {
-0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
-0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f,
-0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff,
-0x0f, 0xff, 0x0f, 0xff, 0x02, 0xe9, 0x06, 0x8c, 0x06, 0x8c, 0x0f,
-0xff, 0x1a, 0x75, 0x0d, 0x8b, 0x04, 0xe9, 0x0b, 0x16, 0x1a, 0x38,
-0x0d, 0xc8, 0x04, 0x6f, 0x0b, 0x91, 0x0f, 0xff, 0x06, 0x40, 0x06,
-0x40, 0x02, 0x8f, 0x0f, 0xff, 0x06, 0x62, 0x06, 0x62, 0x02, 0x7b,
-0x0f, 0xff, 0x06, 0x97, 0x06, 0x97, 0x02, 0x52, 0x0f, 0xff, 0x06,
-0xf6, 0x06, 0xf6, 0x02, 0x19, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55,
-0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x14,
-0xda, 0x0d, 0x93, 0x04, 0xda, 0x05, 0x93, 0x14, 0xda, 0x0d, 0x93,
-0x04, 0xda, 0x05, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x02, 0x00
-};
-
-static unsigned char page_zero_v2[] __devinitdata = {
-0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static unsigned char page_one_v2[] __devinitdata = {
-0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static unsigned char page_two_v2[] __devinitdata = {
-0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00
-};
-static unsigned char page_three_v2[] __devinitdata = {
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00
-};
-static unsigned char page_four_v2[] __devinitdata = {
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00
-};
-
-static unsigned char page_seven_v2[] __devinitdata = {
-0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static unsigned char mod_v2[] __devinitdata = {
-0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02,
-0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05,
-0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0,
-0x20, 0xb1, 0x20, 0xb2, 0x20, 0xb3, 0x20, 0xb4, 0x20, 0xb5, 0x20,
-0xb6, 0x20, 0xb7, 0x20, 0xf0, 0x20, 0xf1, 0x20, 0xf2, 0x20, 0xf3,
-0x20, 0xf4, 0x20, 0xf5, 0x20, 0xf6, 0x20, 0xf7, 0x20, 0x10, 0xff,
-0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0xff, 0x15, 0xff, 0x16,
-0xff, 0x17, 0xff, 0x20, 0xff, 0x21, 0xff, 0x22, 0xff, 0x23, 0xff,
-0x24, 0xff, 0x25, 0xff, 0x26, 0xff, 0x27, 0xff, 0x30, 0x00, 0x31,
-0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00,
-0x37, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44,
-0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x50, 0x00, 0x51, 0x00,
-0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57,
-0x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00,
-0x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x70, 0xc0, 0x71, 0xc0, 0x72,
-0xc0, 0x73, 0xc0, 0x74, 0xc0, 0x75, 0xc0, 0x76, 0xc0, 0x77, 0xc0,
-0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85,
-0x00, 0x86, 0x00, 0x87, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00,
-0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0xa0,
-0x00, 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00,
-0xa6, 0x00, 0xa7, 0x00, 0xc0, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
-0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xd0, 0x00,
-0xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6,
-0x00, 0xd7, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe2, 0x00, 0xe3, 0x00,
-0xe4, 0x00, 0xe5, 0x00, 0xe6, 0x00, 0xe7, 0x00, 0x01, 0x00, 0x02,
-0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03,
-0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01,
-0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01
-};
-static unsigned char coefficients[] __devinitdata = {
-0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03,
-0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49,
-0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01,
-0x40, 0x02, 0x40, 0x01, 0x41, 0x02, 0x60, 0x07, 0x40, 0x00, 0x00,
-0x07, 0x41, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, 0x07, 0x4a, 0x00,
-0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x20, 0x07, 0x47,
-0x00, 0x00, 0x07, 0x4a, 0x00, 0x00, 0x07, 0x7c, 0x00, 0x00, 0x07,
-0x7e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x07, 0x7c, 0x00, 0x00,
-0x07, 0x7e, 0x00, 0x00, 0x07, 0x44, 0x00, 0x00, 0x00, 0x44, 0x01,
-0x00, 0x07, 0x44, 0x00, 0x00, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43,
-0x00, 0x00, 0x00, 0x42, 0x01, 0x1a, 0x00, 0x43, 0x01, 0x20, 0x07,
-0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00,
-0x07, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0x40, 0x01, 0x41, 0x02,
-0x60, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x44,
-0x0f, 0xff, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07,
-0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x51, 0x06, 0x40,
-0x07, 0x50, 0x06, 0x40, 0x07, 0x4f, 0x03, 0x81, 0x07, 0x53, 0x1a,
-0x76, 0x07, 0x54, 0x0d, 0x8b, 0x07, 0x55, 0x04, 0xe9, 0x07, 0x56,
-0x0b, 0x17, 0x07, 0x57, 0x1a, 0x38, 0x07, 0x58, 0x0d, 0xc9, 0x07,
-0x59, 0x04, 0x6f, 0x07, 0x5a, 0x0b, 0x91, 0x07, 0x73, 0x14, 0xda,
-0x07, 0x74, 0x0d, 0x93, 0x07, 0x75, 0x04, 0xd9, 0x07, 0x76, 0x05,
-0x93, 0x07, 0x77, 0x14, 0xda, 0x07, 0x78, 0x0d, 0x93, 0x07, 0x79,
-0x04, 0xd9, 0x07, 0x7a, 0x05, 0x93, 0x07, 0x5e, 0x03, 0x68, 0x07,
-0x5c, 0x04, 0x31, 0x07, 0x5d, 0x04, 0x31, 0x07, 0x62, 0x03, 0x52,
-0x07, 0x60, 0x04, 0x76, 0x07, 0x61, 0x04, 0x76, 0x07, 0x66, 0x03,
-0x2e, 0x07, 0x64, 0x04, 0xda, 0x07, 0x65, 0x04, 0xda, 0x07, 0x6a,
-0x02, 0xf6, 0x07, 0x68, 0x05, 0x62, 0x07, 0x69, 0x05, 0x62, 0x06,
-0x46, 0x0a, 0x22, 0x06, 0x48, 0x0d, 0x24, 0x06, 0x6e, 0x11, 0xd3,
-0x06, 0x70, 0x15, 0xcb, 0x06, 0x52, 0x20, 0x93, 0x06, 0x54, 0x20,
-0x54, 0x06, 0x4a, 0x27, 0x1d, 0x06, 0x58, 0x2f, 0xc8, 0x06, 0x5c,
-0x30, 0x07, 0x06, 0x4c, 0x37, 0x90, 0x06, 0x60, 0x3d, 0xdb, 0x06,
-0x64, 0x3e, 0x42, 0x06, 0x4e, 0x45, 0x78, 0x06, 0x68, 0x4c, 0x48,
-0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02,
-0xba
-};
-static unsigned char coefficients2[] __devinitdata = {
-0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f,
-0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d,
-0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07,
-0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00,
-0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00
-};
-static unsigned char coefficients3[] __devinitdata = {
-0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00,
-0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc,
-0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01,
-0x47, 0x01, 0x47, 0x01, 0x70, 0x01, 0x70, 0x01, 0x99, 0x01, 0x99,
-0x01, 0xc2, 0x01, 0xc2, 0x01, 0xeb, 0x01, 0xeb, 0x02, 0x14, 0x02,
-0x14, 0x02, 0x3d, 0x02, 0x3d, 0x02, 0x66, 0x02, 0x66, 0x02, 0x8f,
-0x02, 0x8f, 0x02, 0xb8, 0x02, 0xb8, 0x02, 0xe1, 0x02, 0xe1, 0x03,
-0x0a, 0x03, 0x0a, 0x03, 0x33, 0x03, 0x33, 0x03, 0x5c, 0x03, 0x5c,
-0x03, 0x85, 0x03, 0x85, 0x03, 0xae, 0x03, 0xae, 0x03, 0xd7, 0x03,
-0xd7, 0x04, 0x00, 0x04, 0x00, 0x04, 0x28, 0x04, 0x28, 0x04, 0x51,
-0x04, 0x51, 0x04, 0x7a, 0x04, 0x7a, 0x04, 0xa3, 0x04, 0xa3, 0x04,
-0xcc, 0x04, 0xcc, 0x04, 0xf5, 0x04, 0xf5, 0x05, 0x1e, 0x05, 0x1e,
-0x05, 0x47, 0x05, 0x47, 0x05, 0x70, 0x05, 0x70, 0x05, 0x99, 0x05,
-0x99, 0x05, 0xc2, 0x05, 0xc2, 0x05, 0xeb, 0x05, 0xeb, 0x06, 0x14,
-0x06, 0x14, 0x06, 0x3d, 0x06, 0x3d, 0x06, 0x66, 0x06, 0x66, 0x06,
-0x8f, 0x06, 0x8f, 0x06, 0xb8, 0x06, 0xb8, 0x06, 0xe1, 0x06, 0xe1,
-0x07, 0x0a, 0x07, 0x0a, 0x07, 0x33, 0x07, 0x33, 0x07, 0x5c, 0x07,
-0x5c, 0x07, 0x85, 0x07, 0x85, 0x07, 0xae, 0x07, 0xae, 0x07, 0xd7,
-0x07, 0xd7, 0x08, 0x00, 0x08, 0x00, 0x08, 0x28, 0x08, 0x28, 0x08,
-0x51, 0x08, 0x51, 0x08, 0x7a, 0x08, 0x7a, 0x08, 0xa3, 0x08, 0xa3,
-0x08, 0xcc, 0x08, 0xcc, 0x08, 0xf5, 0x08, 0xf5, 0x09, 0x1e, 0x09,
-0x1e, 0x09, 0x47, 0x09, 0x47, 0x09, 0x70, 0x09, 0x70, 0x09, 0x99,
-0x09, 0x99, 0x09, 0xc2, 0x09, 0xc2, 0x09, 0xeb, 0x09, 0xeb, 0x0a,
-0x14, 0x0a, 0x14, 0x0a, 0x3d, 0x0a, 0x3d, 0x0a, 0x66, 0x0a, 0x66,
-0x0a, 0x8f, 0x0a, 0x8f, 0x0a, 0xb8, 0x0a, 0xb8, 0x0a, 0xe1, 0x0a,
-0xe1, 0x0b, 0x0a, 0x0b, 0x0a, 0x0b, 0x33, 0x0b, 0x33, 0x0b, 0x5c,
-0x0b, 0x5c, 0x0b, 0x85, 0x0b, 0x85, 0x0b, 0xae, 0x0b, 0xae, 0x0b,
-0xd7, 0x0b, 0xd7, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x28, 0x0c, 0x28,
-0x0c, 0x51, 0x0c, 0x51, 0x0c, 0x7a, 0x0c, 0x7a, 0x0c, 0xa3, 0x0c,
-0xa3, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xf5, 0x0c, 0xf5, 0x0d, 0x1e,
-0x0d, 0x1e, 0x0d, 0x47, 0x0d, 0x47, 0x0d, 0x70, 0x0d, 0x70, 0x0d,
-0x99, 0x0d, 0x99, 0x0d, 0xc2, 0x0d, 0xc2, 0x0d, 0xeb, 0x0d, 0xeb,
-0x0e, 0x14, 0x0e, 0x14, 0x0e, 0x3d, 0x0e, 0x3d, 0x0e, 0x66, 0x0e,
-0x66, 0x0e, 0x8f, 0x0e, 0x8f, 0x0e, 0xb8, 0x0e, 0xb8, 0x0e, 0xe1,
-0x0e, 0xe1, 0x0f, 0x0a, 0x0f, 0x0a, 0x0f, 0x33, 0x0f, 0x33, 0x0f,
-0x5c, 0x0f, 0x5c, 0x0f, 0x85, 0x0f, 0x85, 0x0f, 0xae, 0x0f, 0xae,
-0x0f, 0xd7, 0x0f, 0xd7, 0x0f, 0xff, 0x0f, 0xff
-};
+#endif
 
 static int
 wavefront_fx_idle (snd_wavefront_t *dev)
@@ -555,465 +248,56 @@
    of the port I/O done, using the Yamaha faxback document as a guide
    to add more logic to the code. Its really pretty weird.
 
-   There was an alternative approach of just dumping the whole I/O
+   This is the approach of just dumping the whole I/O
    sequence as a series of port/value pairs and a simple loop
-   that output it. However, I hope that eventually I'll get more
-   control over what this code does, and so I tried to stick with
-   a somewhat "algorithmic" approach.
+   that outputs it.
 */
 
-
 int __devinit
 snd_wavefront_fx_start (snd_wavefront_t *dev)
-
 {
-	unsigned int i, j;
+	unsigned int i;
+	int err;
+	const struct firmware *firmware;
 
-	/* Set all bits for all channels on the MOD unit to zero */
-	/* XXX But why do this twice ? */
+	if (dev->fx_initialized)
+		return 0;
 
-	for (j = 0; j < 2; j++) {
-		for (i = 0x10; i <= 0xff; i++) {
-	    
-			if (!wavefront_fx_idle (dev)) {
-				return (-1);
+	err = request_firmware(&firmware, "yamaha/yss225_registers.bin",
+			       dev->card->dev);
+	if (err < 0) {
+#ifdef FIRMWARE_IN_THE_KERNEL
+		firmware = &yss225_registers_firmware;
+#else
+		err = -1;
+		goto out;
+#endif
+	}
+
+	for (i = 0; i + 1 < firmware->size; i += 2) {
+		if (firmware->data[i] >= 8 && firmware->data[i] < 16) {
+			outb(firmware->data[i + 1],
+			     dev->base + firmware->data[i]);
+		} else if (firmware->data[i] == WAIT_IDLE) {
+			if (!wavefront_fx_idle(dev)) {
+				err = -1;
+				goto out;
 			}
-	    
-			outb (i, dev->fx_mod_addr);
-			outb (0x0, dev->fx_mod_data);
+		} else {
+			snd_printk(KERN_ERR "invalid address"
+				   " in register data\n");
+			err = -1;
+			goto out;
 		}
 	}
 
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x02, dev->fx_op);                        /* mute on */
+	dev->fx_initialized = 1;
+	err = 0;
 
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x44, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x42, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x43, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x7c, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x7e, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x46, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x49, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x47, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x4a, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-
-	/* either because of stupidity by TB's programmers, or because it
-	   actually does something, rezero the MOD page.
-	*/
-	for (i = 0x10; i <= 0xff; i++) {
-	
-		if (!wavefront_fx_idle (dev)) {
-			return (-1);
-		}
-	
-		outb (i, dev->fx_mod_addr);
-		outb (0x0, dev->fx_mod_data);
-	}
-	/* load page zero */
-
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x00, dev->fx_dsp_page);
-	outb (0x00, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_zero); i += 2) {
-		outb (page_zero[i], dev->fx_dsp_msb);
-		outb (page_zero[i+1], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	/* Now load page one */
-
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x01, dev->fx_dsp_page);
-	outb (0x00, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_one); i += 2) {
-		outb (page_one[i], dev->fx_dsp_msb);
-		outb (page_one[i+1], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-    
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x02, dev->fx_dsp_page);
-	outb (0x00, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_two); i++) {
-		outb (page_two[i], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-    
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x03, dev->fx_dsp_page);
-	outb (0x00, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_three); i++) {
-		outb (page_three[i], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-    
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x04, dev->fx_dsp_page);
-	outb (0x00, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_four); i++) {
-		outb (page_four[i], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	/* Load memory area (page six) */
-    
-	outb (FX_LSB_TRANSFER, dev->fx_lcr); 
-	outb (0x06, dev->fx_dsp_page); 
-
-	for (i = 0; i < sizeof (page_six); i += 3) {
-		outb (page_six[i], dev->fx_dsp_addr);
-		outb (page_six[i+1], dev->fx_dsp_msb);
-		outb (page_six[i+2], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-    
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x00, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_seven); i += 2) {
-		outb (page_seven[i], dev->fx_dsp_msb);
-		outb (page_seven[i+1], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	/* Now setup the MOD area. We do this algorithmically in order to
-	   save a little data space. It could be done in the same fashion
-	   as the "pages".
-	*/
-
-	for (i = 0x00; i <= 0x0f; i++) {
-		outb (0x01, dev->fx_mod_addr);
-		outb (i, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-		outb (0x02, dev->fx_mod_addr);
-		outb (0x00, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	for (i = 0xb0; i <= 0xbf; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0x20, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	for (i = 0xf0; i <= 0xff; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0x20, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	for (i = 0x10; i <= 0x1d; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0xff, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	outb (0x1e, dev->fx_mod_addr);
-	outb (0x40, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-
-	for (i = 0x1f; i <= 0x2d; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0xff, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	outb (0x2e, dev->fx_mod_addr);
-	outb (0x00, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-
-	for (i = 0x2f; i <= 0x3e; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0x00, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	outb (0x3f, dev->fx_mod_addr);
-	outb (0x20, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-
-	for (i = 0x40; i <= 0x4d; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0x00, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	outb (0x4e, dev->fx_mod_addr);
-	outb (0x0e, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x4f, dev->fx_mod_addr);
-	outb (0x0e, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-
-
-	for (i = 0x50; i <= 0x6b; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0x00, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	outb (0x6c, dev->fx_mod_addr);
-	outb (0x40, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-
-	outb (0x6d, dev->fx_mod_addr);
-	outb (0x00, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-
-	outb (0x6e, dev->fx_mod_addr);
-	outb (0x40, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-
-	outb (0x6f, dev->fx_mod_addr);
-	outb (0x40, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-
-	for (i = 0x70; i <= 0x7f; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0xc0, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-    
-	for (i = 0x80; i <= 0xaf; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0x00, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	for (i = 0xc0; i <= 0xdd; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0x00, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	outb (0xde, dev->fx_mod_addr);
-	outb (0x10, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0xdf, dev->fx_mod_addr);
-	outb (0x10, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-
-	for (i = 0xe0; i <= 0xef; i++) {
-		outb (i, dev->fx_mod_addr);
-		outb (0x00, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	for (i = 0x00; i <= 0x0f; i++) {
-		outb (0x01, dev->fx_mod_addr);
-		outb (i, dev->fx_mod_data);
-		outb (0x02, dev->fx_mod_addr);
-		outb (0x01, dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	outb (0x02, dev->fx_op); /* mute on */
-
-	/* Now set the coefficients and so forth for the programs above */
-
-	for (i = 0; i < sizeof (coefficients); i += 4) {
-		outb (coefficients[i], dev->fx_dsp_page);
-		outb (coefficients[i+1], dev->fx_dsp_addr);
-		outb (coefficients[i+2], dev->fx_dsp_msb);
-		outb (coefficients[i+3], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	/* Some settings (?) that are too small to bundle into loops */
-
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x1e, dev->fx_mod_addr);
-	outb (0x14, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0xde, dev->fx_mod_addr);
-	outb (0x20, dev->fx_mod_data);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0xdf, dev->fx_mod_addr);
-	outb (0x20, dev->fx_mod_data);
-    
-	/* some more coefficients */
-
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x06, dev->fx_dsp_page);
-	outb (0x78, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x40, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x03, dev->fx_dsp_addr);
-	outb (0x0f, dev->fx_dsp_msb);
-	outb (0xff, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x0b, dev->fx_dsp_addr);
-	outb (0x0f, dev->fx_dsp_msb);
-	outb (0xff, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x02, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x0a, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x46, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-	if (!wavefront_fx_idle (dev)) return (-1);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x49, dev->fx_dsp_addr);
-	outb (0x00, dev->fx_dsp_msb);
-	outb (0x00, dev->fx_dsp_lsb);
-    
-	/* Now, for some strange reason, lets reload every page
-	   and all the coefficients over again. I have *NO* idea
-	   why this is done. I do know that no sound is produced
-	   is this phase is omitted.
-	*/
-
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x00, dev->fx_dsp_page);  
-	outb (0x10, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_zero_v2); i += 2) {
-		outb (page_zero_v2[i], dev->fx_dsp_msb);
-		outb (page_zero_v2[i+1], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-    
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x01, dev->fx_dsp_page);
-	outb (0x10, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_one_v2); i += 2) {
-		outb (page_one_v2[i], dev->fx_dsp_msb);
-		outb (page_one_v2[i+1], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-    
-	if (!wavefront_fx_idle (dev)) return (-1);
-	if (!wavefront_fx_idle (dev)) return (-1);
-    
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x02, dev->fx_dsp_page);
-	outb (0x10, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_two_v2); i++) {
-		outb (page_two_v2[i], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x03, dev->fx_dsp_page);
-	outb (0x10, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_three_v2); i++) {
-		outb (page_three_v2[i], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-    
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x04, dev->fx_dsp_page);
-	outb (0x10, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_four_v2); i++) {
-		outb (page_four_v2[i], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-    
-	outb (FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x06, dev->fx_dsp_page);
-
-	/* Page six v.2 is algorithmic */
-    
-	for (i = 0x10; i <= 0x3e; i += 2) {
-		outb (i, dev->fx_dsp_addr);
-		outb (0x00, dev->fx_dsp_msb);
-		outb (0x00, dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
-	outb (0x07, dev->fx_dsp_page);
-	outb (0x10, dev->fx_dsp_addr);
-
-	for (i = 0; i < sizeof (page_seven_v2); i += 2) {
-		outb (page_seven_v2[i], dev->fx_dsp_msb);
-		outb (page_seven_v2[i+1], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	for (i = 0x00; i < sizeof(mod_v2); i += 2) {
-		outb (mod_v2[i], dev->fx_mod_addr);
-		outb (mod_v2[i+1], dev->fx_mod_data);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	for (i = 0; i < sizeof (coefficients2); i += 4) {
-		outb (coefficients2[i], dev->fx_dsp_page);
-		outb (coefficients2[i+1], dev->fx_dsp_addr);
-		outb (coefficients2[i+2], dev->fx_dsp_msb);
-		outb (coefficients2[i+3], dev->fx_dsp_lsb);
-		if (!wavefront_fx_idle (dev)) return (-1);
-	}
-
-	for (i = 0; i < sizeof (coefficients3); i += 2) {
-		int x;
-
-		outb (0x07, dev->fx_dsp_page);
-		x = (i % 4) ? 0x4e : 0x4c;
-		outb (x, dev->fx_dsp_addr);
-		outb (coefficients3[i], dev->fx_dsp_msb);
-		outb (coefficients3[i+1], dev->fx_dsp_lsb);
-	}
-
-	outb (0x00, dev->fx_op); /* mute off */
-	if (!wavefront_fx_idle (dev)) return (-1);
-
-	return (0);
+out:
+#ifdef FIRMWARE_IN_THE_KERNEL
+	if (firmware != &yss225_registers_firmware)
+#endif
+		release_firmware(firmware);
+	return err;
 }
diff --git a/sound/isa/wavefront/yss225.c b/sound/isa/wavefront/yss225.c
new file mode 100644
index 0000000..9f6be3f
--- /dev/null
+++ b/sound/isa/wavefront/yss225.c
@@ -0,0 +1,2739 @@
+/*
+ *  Copyright (c) 1998-2002 by Paul Davis <pbd@op.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
+ */
+
+/* weird stuff, derived from port I/O tracing with dosemu */
+
+static const struct {
+	unsigned char addr;
+	unsigned char data;
+} yss225_registers[] __devinitdata = {
+/* Set all bits for all channels on the MOD unit to zero */
+{ WAIT_IDLE }, { 0xe, 0x10 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x11 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x12 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x13 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x14 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x15 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x16 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x17 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x18 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x19 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x20 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x21 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x22 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x23 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x24 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x25 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x26 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x27 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x28 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x29 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x30 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x31 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x32 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x33 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x34 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x35 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x36 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x37 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x38 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x39 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x40 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x41 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x42 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x43 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x44 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x45 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x46 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x47 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x48 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x49 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x50 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x51 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x52 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x53 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x54 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x55 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x56 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x57 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x58 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x59 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x60 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x61 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x62 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x63 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x64 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x65 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x66 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x67 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x68 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x69 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x70 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x71 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x72 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x73 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x74 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x75 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x76 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x77 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x78 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x79 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x80 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x81 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x82 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x83 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x84 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x85 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x86 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x87 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x88 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x89 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x90 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x91 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x92 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x93 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x94 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x95 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x96 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x97 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x98 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x99 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xaa }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xab }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xac }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xad }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xae }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xaf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xba }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbe }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xca }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xce }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xda }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xea }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xeb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xec }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xed }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xee }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xef }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfa }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfe }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xff }, { 0xf, 0x00 },
+
+/* XXX But why do this twice? */
+{ WAIT_IDLE }, { 0xe, 0x10 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x11 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x12 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x13 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x14 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x15 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x16 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x17 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x18 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x19 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x20 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x21 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x22 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x23 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x24 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x25 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x26 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x27 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x28 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x29 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x30 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x31 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x32 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x33 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x34 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x35 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x36 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x37 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x38 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x39 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x40 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x41 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x42 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x43 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x44 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x45 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x46 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x47 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x48 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x49 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x50 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x51 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x52 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x53 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x54 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x55 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x56 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x57 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x58 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x59 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x60 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x61 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x62 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x63 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x64 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x65 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x66 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x67 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x68 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x69 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x70 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x71 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x72 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x73 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x74 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x75 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x76 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x77 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x78 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x79 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x80 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x81 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x82 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x83 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x84 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x85 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x86 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x87 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x88 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x89 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x90 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x91 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x92 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x93 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x94 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x95 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x96 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x97 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x98 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x99 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xaa }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xab }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xac }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xad }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xae }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xaf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xba }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbe }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xca }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xce }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xda }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xea }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xeb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xec }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xed }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xee }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xef }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfa }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfe }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xff }, { 0xf, 0x00 },
+
+/* mute on */
+{ WAIT_IDLE }, { 0x8, 0x02 },
+
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 },
+
+/* either because of stupidity by TB's programmers, or because it
+   actually does something, rezero the MOD page. */
+{ WAIT_IDLE }, { 0xe, 0x10 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x11 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x12 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x13 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x14 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x15 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x16 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x17 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x18 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x19 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x1f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x20 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x21 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x22 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x23 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x24 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x25 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x26 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x27 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x28 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x29 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x2f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x30 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x31 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x32 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x33 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x34 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x35 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x36 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x37 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x38 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x39 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x3f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x40 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x41 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x42 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x43 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x44 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x45 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x46 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x47 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x48 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x49 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x4f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x50 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x51 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x52 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x53 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x54 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x55 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x56 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x57 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x58 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x59 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x5f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x60 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x61 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x62 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x63 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x64 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x65 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x66 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x67 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x68 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x69 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x6f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x70 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x71 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x72 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x73 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x74 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x75 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x76 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x77 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x78 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x79 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x7f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x80 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x81 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x82 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x83 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x84 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x85 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x86 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x87 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x88 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x89 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x8f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x90 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x91 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x92 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x93 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x94 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x95 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x96 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x97 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x98 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x99 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9a }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9b }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9c }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9d }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9e }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0x9f }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xa9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xaa }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xab }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xac }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xad }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xae }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xaf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xb9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xba }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbe }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xbf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xc9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xca }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xce }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xcf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xd9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xda }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xe9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xea }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xeb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xec }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xed }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xee }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xef }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf0 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf1 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf2 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf3 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf4 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf5 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf6 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf7 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf8 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xf9 }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfa }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfb }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfc }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfd }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xfe }, { 0xf, 0x00 },
+{ WAIT_IDLE }, { 0xe, 0xff }, { 0xf, 0x00 },
+
+/* load page zero */
+{ 0x9, 0x05 }, { 0xb, 0x00 }, { 0xa, 0x00 },
+
+{ 0xd, 0x01 }, { 0xc, 0x7c }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x1e }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0xf5 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x11 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x32 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x13 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x14 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x76 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x18 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x19 }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0x1a }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0x17 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0x80 }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x10 }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0xa0 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0xd1 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0xf2 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x13 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0xf4 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xe0 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x15 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x16 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x17 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x50 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x71 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x92 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0xb3 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0xa0 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0xd4 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0xf5 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x70 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0xa0 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x11 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x16 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x10 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x17 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x1d }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xdf }, { WAIT_IDLE },
+
+/* Now load page one */
+{ 0x9, 0x05 }, { 0xb, 0x01 }, { 0xa, 0x00 },
+
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x19 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x1f }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0xd8 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x19 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x18 }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0xfa }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x1a }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x80 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xfb }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xa0 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xd7 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xf7 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x1c }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0x3c }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0x3f }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0xdf }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0x5d }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0x7d }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0x9e }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0xbe }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xdb }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xdb }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xe0 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xfb }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xfb }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE },
+
+{ 0x9, 0x05 }, { 0xb, 0x02 }, { 0xa, 0x00 },
+
+{ 0xc, 0xc4 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x25 }, { WAIT_IDLE },
+{ 0xc, 0x01 }, { WAIT_IDLE },
+{ 0xc, 0x06 }, { WAIT_IDLE },
+{ 0xc, 0xc4 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x25 }, { WAIT_IDLE },
+{ 0xc, 0x01 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x04 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x04 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x05 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x44 }, { WAIT_IDLE },
+
+{ 0x9, 0x05 }, { 0xb, 0x03 }, { 0xa, 0x00 },
+
+{ 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x47 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x06 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x80 }, { WAIT_IDLE },
+{ 0xc, 0x80 }, { WAIT_IDLE },
+{ 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x70 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x42 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x42 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x42 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x42 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x40 }, { WAIT_IDLE },
+
+{ 0x9, 0x05 }, { 0xb, 0x04 }, { 0xa, 0x00 },
+
+{ 0xc, 0x63 }, { WAIT_IDLE },
+{ 0xc, 0x03 }, { WAIT_IDLE },
+{ 0xc, 0x26 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x2c }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x24 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x2e }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x01 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x22 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x22 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x22 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x62 }, { WAIT_IDLE },
+{ 0xc, 0x02 }, { WAIT_IDLE },
+{ 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xc, 0x01 }, { WAIT_IDLE },
+{ 0xc, 0x21 }, { WAIT_IDLE },
+{ 0xc, 0x01 }, { WAIT_IDLE },
+
+/* Load memory area (page six) */
+{ 0x9, 0x01 }, { 0xb, 0x06 },
+
+{ 0xa, 0x00 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x02 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x04 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x06 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x08 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x0a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x0c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x0e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x10 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x12 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x14 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x16 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x18 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x1a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x1c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x1e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x20 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x22 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x24 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x26 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x28 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x2a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x2c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x2e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x30 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x32 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x34 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x36 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x38 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x3a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x3c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x3e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x42 }, { 0xd, 0x03 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x44 }, { 0xd, 0x01 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x46 }, { 0xd, 0x0a }, { 0xc, 0x21 }, { WAIT_IDLE },
+{ 0xa, 0x48 }, { 0xd, 0x0d }, { 0xc, 0x23 }, { WAIT_IDLE },
+{ 0xa, 0x4a }, { 0xd, 0x23 }, { 0xc, 0x1b }, { WAIT_IDLE },
+{ 0xa, 0x4c }, { 0xd, 0x37 }, { 0xc, 0x8f }, { WAIT_IDLE },
+{ 0xa, 0x4e }, { 0xd, 0x45 }, { 0xc, 0x77 }, { WAIT_IDLE },
+{ 0xa, 0x50 }, { 0xd, 0x52 }, { 0xc, 0xe2 }, { WAIT_IDLE },
+{ 0xa, 0x52 }, { 0xd, 0x1c }, { 0xc, 0x92 }, { WAIT_IDLE },
+{ 0xa, 0x54 }, { 0xd, 0x1c }, { 0xc, 0x52 }, { WAIT_IDLE },
+{ 0xa, 0x56 }, { 0xd, 0x07 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x58 }, { 0xd, 0x2f }, { 0xc, 0xc6 }, { WAIT_IDLE },
+{ 0xa, 0x5a }, { 0xd, 0x0b }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x5c }, { 0xd, 0x30 }, { 0xc, 0x06 }, { WAIT_IDLE },
+{ 0xa, 0x5e }, { 0xd, 0x17 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x60 }, { 0xd, 0x3d }, { 0xc, 0xda }, { WAIT_IDLE },
+{ 0xa, 0x62 }, { 0xd, 0x29 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x64 }, { 0xd, 0x3e }, { 0xc, 0x41 }, { WAIT_IDLE },
+{ 0xa, 0x66 }, { 0xd, 0x39 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x68 }, { 0xd, 0x4c }, { 0xc, 0x48 }, { WAIT_IDLE },
+{ 0xa, 0x6a }, { 0xd, 0x49 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x6c }, { 0xd, 0x4c }, { 0xc, 0x6c }, { WAIT_IDLE },
+{ 0xa, 0x6e }, { 0xd, 0x11 }, { 0xc, 0xd2 }, { WAIT_IDLE },
+{ 0xa, 0x70 }, { 0xd, 0x16 }, { 0xc, 0x0c }, { WAIT_IDLE },
+{ 0xa, 0x72 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x74 }, { 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE },
+{ 0xa, 0x76 }, { 0xd, 0x0f }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x78 }, { 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE },
+{ 0xa, 0x7a }, { 0xd, 0x13 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x7c }, { 0xd, 0x80 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x7e }, { 0xd, 0x80 }, { 0xc, 0x80 }, { WAIT_IDLE },
+
+{ 0x9, 0x05 }, { 0xb, 0x07 }, { 0xa, 0x00 },
+
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0xe9 }, { WAIT_IDLE },
+{ 0xd, 0x06 }, { 0xc, 0x8c }, { WAIT_IDLE },
+{ 0xd, 0x06 }, { 0xc, 0x8c }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x1a }, { 0xc, 0x75 }, { WAIT_IDLE },
+{ 0xd, 0x0d }, { 0xc, 0x8b }, { WAIT_IDLE },
+{ 0xd, 0x04 }, { 0xc, 0xe9 }, { WAIT_IDLE },
+{ 0xd, 0x0b }, { 0xc, 0x16 }, { WAIT_IDLE },
+{ 0xd, 0x1a }, { 0xc, 0x38 }, { WAIT_IDLE },
+{ 0xd, 0x0d }, { 0xc, 0xc8 }, { WAIT_IDLE },
+{ 0xd, 0x04 }, { 0xc, 0x6f }, { WAIT_IDLE },
+{ 0xd, 0x0b }, { 0xc, 0x91 }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x8f }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x06 }, { 0xc, 0x62 }, { WAIT_IDLE },
+{ 0xd, 0x06 }, { 0xc, 0x62 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x7b }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x06 }, { 0xc, 0x97 }, { WAIT_IDLE },
+{ 0xd, 0x06 }, { 0xc, 0x97 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x52 }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x06 }, { 0xc, 0xf6 }, { WAIT_IDLE },
+{ 0xd, 0x06 }, { 0xc, 0xf6 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x19 }, { WAIT_IDLE },
+{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
+{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
+{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
+{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
+{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
+{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
+{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
+{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
+{ 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE },
+{ 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE },
+{ 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE },
+{ 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE },
+{ 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE },
+{ 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE },
+{ 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE },
+{ 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
+
+/* Now setup the MOD area. */
+{ 0xe, 0x01 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x02 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x03 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x04 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x05 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x06 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x07 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x08 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x09 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0a }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0b }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0c }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0d }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0e }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0f }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+
+{ 0xe, 0xb0 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb1 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb2 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb3 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb4 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb5 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb6 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb7 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb8 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb9 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xba }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xbb }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xbc }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xbd }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xbe }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xbf }, { 0xf, 0x20 }, { WAIT_IDLE },
+
+{ 0xe, 0xf0 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf1 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf2 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf3 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf4 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf5 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf6 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf7 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf8 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf9 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xfa }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xfb }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xfc }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xfd }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xfe }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xff }, { 0xf, 0x20 }, { WAIT_IDLE },
+
+{ 0xe, 0x10 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x11 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x12 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x13 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x14 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x15 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x16 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x17 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x18 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x19 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x1a }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x1b }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x1c }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x1d }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x1e }, { 0xf, 0x40 }, { WAIT_IDLE },
+{ 0xe, 0x1f }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x20 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x21 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x22 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x23 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x24 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x25 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x26 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x27 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x28 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x29 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x2a }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x2b }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x2c }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x2d }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x2e }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x2f }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x30 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x31 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x32 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x33 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x34 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x35 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x36 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x37 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x38 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x39 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x3a }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x3b }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x3c }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x3d }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x3e }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x3f }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0x40 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x41 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x42 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x43 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x44 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x45 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x46 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x47 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x48 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x49 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x4a }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x4b }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x4c }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x4d }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x4e }, { 0xf, 0x0e }, { WAIT_IDLE },
+{ 0xe, 0x4f }, { 0xf, 0x0e }, { WAIT_IDLE },
+{ 0xe, 0x50 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x51 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x52 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x53 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x54 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x55 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x56 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x57 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x58 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x59 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x5a }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x5b }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x5c }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x5d }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x5e }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x5f }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x60 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x61 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x62 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x63 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x64 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x65 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x66 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x67 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x68 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x69 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x6a }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x6b }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x6c }, { 0xf, 0x40 }, { WAIT_IDLE },
+{ 0xe, 0x6d }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x6e }, { 0xf, 0x40 }, { WAIT_IDLE },
+{ 0xe, 0x6f }, { 0xf, 0x40 }, { WAIT_IDLE },
+{ 0xe, 0x70 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x71 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x72 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x73 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x74 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x75 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x76 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x77 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x78 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x79 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x7a }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x7b }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x7c }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x7d }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x7e }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x7f }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x80 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x81 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x82 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x83 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x84 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x85 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x86 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x87 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x88 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x89 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x8a }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x8b }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x8c }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x8d }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x8e }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x8f }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x90 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x91 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x92 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x93 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x94 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x95 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x96 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x97 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x98 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x99 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x9a }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x9b }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x9c }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x9d }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x9e }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x9f }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa0 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa1 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa2 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa3 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa4 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa5 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa6 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa7 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa8 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa9 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xaa }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xab }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xac }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xad }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xae }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xaf }, { 0xf, 0x00 }, { WAIT_IDLE },
+
+{ 0xe, 0xc0 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc1 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc2 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc3 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc4 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc5 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc6 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc7 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc8 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc9 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xca }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xcb }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xcc }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xcd }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xce }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xcf }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd0 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd1 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd2 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd3 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd4 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd5 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd6 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd7 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd8 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd9 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xda }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xdb }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xdc }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xdd }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xde }, { 0xf, 0x10 }, { WAIT_IDLE },
+{ 0xe, 0xdf }, { 0xf, 0x10 }, { WAIT_IDLE },
+{ 0xe, 0xe0 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe1 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe2 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe3 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe4 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe5 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe6 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe7 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe8 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe9 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xea }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xeb }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xec }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xed }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xee }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xef }, { 0xf, 0x00 }, { WAIT_IDLE },
+
+{ 0xe, 0x01 }, { 0xf, 0x00 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x01 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x02 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x03 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x04 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x05 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x06 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x07 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x08 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x09 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0a }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0b }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0c }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0d }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0e }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x0f }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+
+/* mute on */
+{ 0x8, 0x02 },
+
+/* Now set the coefficients and so forth for the programs above */
+{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x00 }, { 0xa, 0x4b }, { 0xd, 0x03 }, { 0xc, 0x11 }, { WAIT_IDLE },
+{ 0xb, 0x00 }, { 0xa, 0x4d }, { 0xd, 0x01 }, { 0xc, 0x32 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x01 }, { 0xa, 0x40 }, { 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xb, 0x01 }, { 0xa, 0x41 }, { 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x00 }, { 0xa, 0x47 }, { 0xd, 0x01 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x00 }, { 0xa, 0x4a }, { 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x00 }, { 0xa, 0x00 }, { 0xd, 0x01 }, { 0xc, 0x1c }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x00 }, { 0xa, 0x44 }, { 0xd, 0x01 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x00 }, { 0xa, 0x42 }, { 0xd, 0x01 }, { 0xc, 0x1a }, { WAIT_IDLE },
+{ 0xb, 0x00 }, { 0xa, 0x43 }, { 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x01 }, { 0xa, 0x40 }, { 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xb, 0x01 }, { 0xa, 0x41 }, { 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x51 }, { 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x50 }, { 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x4f }, { 0xd, 0x03 }, { 0xc, 0x81 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x53 }, { 0xd, 0x1a }, { 0xc, 0x76 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x54 }, { 0xd, 0x0d }, { 0xc, 0x8b }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x55 }, { 0xd, 0x04 }, { 0xc, 0xe9 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x56 }, { 0xd, 0x0b }, { 0xc, 0x17 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x57 }, { 0xd, 0x1a }, { 0xc, 0x38 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x58 }, { 0xd, 0x0d }, { 0xc, 0xc9 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x59 }, { 0xd, 0x04 }, { 0xc, 0x6f }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x5a }, { 0xd, 0x0b }, { 0xc, 0x91 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x73 }, { 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x74 }, { 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x75 }, { 0xd, 0x04 }, { 0xc, 0xd9 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x76 }, { 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x77 }, { 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x78 }, { 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x79 }, { 0xd, 0x04 }, { 0xc, 0xd9 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x7a }, { 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x5e }, { 0xd, 0x03 }, { 0xc, 0x68 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x5c }, { 0xd, 0x04 }, { 0xc, 0x31 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x5d }, { 0xd, 0x04 }, { 0xc, 0x31 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x62 }, { 0xd, 0x03 }, { 0xc, 0x52 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x60 }, { 0xd, 0x04 }, { 0xc, 0x76 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x61 }, { 0xd, 0x04 }, { 0xc, 0x76 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x66 }, { 0xd, 0x03 }, { 0xc, 0x2e }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x64 }, { 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x65 }, { 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x6a }, { 0xd, 0x02 }, { 0xc, 0xf6 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x68 }, { 0xd, 0x05 }, { 0xc, 0x62 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x69 }, { 0xd, 0x05 }, { 0xc, 0x62 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x46 }, { 0xd, 0x0a }, { 0xc, 0x22 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x48 }, { 0xd, 0x0d }, { 0xc, 0x24 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x6e }, { 0xd, 0x11 }, { 0xc, 0xd3 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x70 }, { 0xd, 0x15 }, { 0xc, 0xcb }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x52 }, { 0xd, 0x20 }, { 0xc, 0x93 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x54 }, { 0xd, 0x20 }, { 0xc, 0x54 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x4a }, { 0xd, 0x27 }, { 0xc, 0x1d }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x58 }, { 0xd, 0x2f }, { 0xc, 0xc8 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x5c }, { 0xd, 0x30 }, { 0xc, 0x07 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x4c }, { 0xd, 0x37 }, { 0xc, 0x90 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x60 }, { 0xd, 0x3d }, { 0xc, 0xdb }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x64 }, { 0xd, 0x3e }, { 0xc, 0x42 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x4e }, { 0xd, 0x45 }, { 0xc, 0x78 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x68 }, { 0xd, 0x4c }, { 0xc, 0x48 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x6c }, { 0xd, 0x4c }, { 0xc, 0x6c }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x50 }, { 0xd, 0x52 }, { 0xc, 0xe2 }, { WAIT_IDLE },
+{ 0xb, 0x06 }, { 0xa, 0x42 }, { 0xd, 0x02 }, { 0xc, 0xba }, { WAIT_IDLE },
+
+/* Some settings (?) */
+{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x14 },
+{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x20 },
+{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x20 },
+
+/* some more coefficients */
+{ WAIT_IDLE }, { 0xb, 0x06 }, { 0xa, 0x78 }, { 0xd, 0x00 }, { 0xc, 0x40 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x03 }, { 0xd, 0x0f }, { 0xc, 0xff },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x0b }, { 0xd, 0x0f }, { 0xc, 0xff },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x02 }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x0a }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 },
+
+/* Now, for some strange reason, lets reload every page
+   and all the coefficients over again. I have *NO* idea
+   why this is done. I do know that no sound is produced
+   is this phase is omitted. */
+{ 0x9, 0x05 }, { 0xb, 0x00 }, { 0xa, 0x10 },
+
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+
+{ 0x9, 0x05 }, { 0xb, 0x01 }, { 0xa, 0x10 },
+
+{ 0xd, 0x01 }, { 0xc, 0xc0 }, { WAIT_IDLE },
+{ 0xd, 0x01 }, { 0xc, 0xfa }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x1a }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+
+{ WAIT_IDLE }, { WAIT_IDLE },
+
+{ 0x9, 0x05 }, { 0xb, 0x02 }, { 0xa, 0x10 },
+
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x46 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+
+{ 0x9, 0x05 }, { 0xb, 0x03 }, { 0xa, 0x10 },
+
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+
+{ 0x9, 0x05 }, { 0xb, 0x04 }, { 0xa, 0x10 },
+
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xc, 0x00 }, { WAIT_IDLE },
+
+/* Page six v.2 */
+{ 0x9, 0x01 }, { 0xb, 0x06 },
+
+{ 0xa, 0x10 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x12 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x14 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x16 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x18 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x1a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x1c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x1e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x20 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x22 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x24 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x26 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x28 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x2a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x2c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x2e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x30 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x32 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x34 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x36 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x38 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x3a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x3c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xa, 0x3e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+
+{ 0x9, 0x05 }, { 0xb, 0x07 }, { 0xa, 0x10 },
+
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+
+{ 0xe, 0x01 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x02 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x03 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x04 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x05 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x06 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x07 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xb0 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb1 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb2 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb3 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb4 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb5 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb6 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xb7 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf0 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf1 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf2 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf3 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf4 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf5 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf6 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0xf7 }, { 0xf, 0x20 }, { WAIT_IDLE },
+{ 0xe, 0x10 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x11 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x12 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x13 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x14 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x15 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x16 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x17 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x20 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x21 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x22 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x23 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x24 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x25 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x26 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x27 }, { 0xf, 0xff }, { WAIT_IDLE },
+{ 0xe, 0x30 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x31 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x32 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x33 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x34 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x35 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x36 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x37 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x40 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x41 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x42 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x43 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x44 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x45 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x46 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x47 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x50 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x51 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x52 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x53 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x54 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x55 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x56 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x57 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x60 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x61 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x62 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x63 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x64 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x65 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x66 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x67 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x70 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x71 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x72 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x73 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x74 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x75 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x76 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x77 }, { 0xf, 0xc0 }, { WAIT_IDLE },
+{ 0xe, 0x80 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x81 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x82 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x83 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x84 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x85 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x86 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x87 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x90 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x91 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x92 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x93 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x94 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x95 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x96 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x97 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa0 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa1 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa2 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa3 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa4 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa5 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa6 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xa7 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc0 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc1 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc2 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc3 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc4 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc5 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc6 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xc7 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd0 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd1 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd2 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd3 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd4 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd5 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd6 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xd7 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe0 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe1 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe2 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe3 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe4 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe5 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe6 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0xe7 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x00 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x02 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x03 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x04 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x05 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x06 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+{ 0xe, 0x01 }, { 0xf, 0x07 }, { WAIT_IDLE },
+{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
+
+{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x45 }, { 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x48 }, { 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x7b }, { 0xd, 0x04 }, { 0xc, 0xcc }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x7d }, { 0xd, 0x04 }, { 0xc, 0xcc }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
+
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x00 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x28 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x28 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x51 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x51 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x7a },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x7a },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0xa3 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0xa3 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0xcc },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0xcc },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0xf5 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0xf5 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x1e },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x1e },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x47 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x47 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x70 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x70 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x99 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x99 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0xc2 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0xc2 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0xeb },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0xeb },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x14 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x14 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x3d },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x3d },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x66 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x66 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x8f },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x8f },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0xb8 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0xb8 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0xe1 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0xe1 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x0a },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x0a },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x33 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x33 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x5c },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x5c },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x85 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x85 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0xae },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0xae },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0xd7 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0xd7 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x00 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x00 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x28 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x28 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x51 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x51 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x7a },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x7a },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0xa3 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0xa3 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0xcc },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0xcc },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0xf5 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0xf5 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x1e },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x1e },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x47 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x47 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x70 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x70 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x99 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x99 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0xc2 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0xc2 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0xeb },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0xeb },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x14 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x14 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x3d },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x3d },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x66 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x66 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x8f },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x8f },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0xb8 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0xb8 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0xe1 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0xe1 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x0a },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x0a },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x33 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x33 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x5c },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x5c },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x85 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x85 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0xae },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0xae },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0xd7 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0xd7 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x00 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x00 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x28 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x28 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x51 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x51 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x7a },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x7a },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0xa3 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0xa3 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0xcc },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0xcc },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0xf5 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0xf5 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x1e },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x1e },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x47 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x47 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x70 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x70 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x99 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x99 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0xc2 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0xc2 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0xeb },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0xeb },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x14 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x14 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x3d },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x3d },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x66 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x66 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x8f },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x8f },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0xb8 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0xb8 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0xe1 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0xe1 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x0a },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x0a },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x33 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x33 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x5c },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x5c },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x85 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x85 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0xae },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0xae },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0xd7 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0xd7 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x00 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x00 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x28 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x28 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x51 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x51 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x7a },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x7a },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0xa3 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0xa3 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0xcc },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0xcc },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0xf5 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0xf5 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x1e },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x1e },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x47 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x47 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x70 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x70 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x99 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x99 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0xc2 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0xc2 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0xeb },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0xeb },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x14 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x14 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x3d },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x3d },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x66 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x66 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x8f },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x8f },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0xb8 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0xb8 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0xe1 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0xe1 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x0a },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x0a },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x33 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x33 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x5c },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x5c },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x85 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x85 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0xae },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0xae },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0xd7 },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0xd7 },
+{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0xff },
+{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0xff },
+
+/* mute off */
+{ 0x8, 0x00 }, { WAIT_IDLE }
+};
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index a0588c2..4c41930 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -5,6 +5,20 @@
 #
 # Prompt user for primary drivers.
 
+config OBSOLETE_OSS
+	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
@@ -33,7 +47,7 @@
 
 config SOUND_ES1371
 	tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
-	depends on SOUND_PRIME && PCI
+	depends on SOUND_PRIME && PCI && OBSOLETE_OSS
 	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
@@ -705,18 +719,6 @@
 
 endchoice
 
-config AEDSP16_MPU401
-	bool "Audio Excel DSP 16 (MPU401 emulation)"
-	depends on SOUND_AEDSP16 && SOUND_MPU401
-	help
-	  Answer Y if you want your audio card to emulate the MPU-401 midi
-	  interface. You should then also say Y to "MPU-401 support".
-
-	  Note that the I/O base for MPU-401 support of aedsp16 is the same
-	  you have selected for "MPU-401 support". If you are using this
-	  driver as a module you have to specify the MPU I/O base address with
-	  the parameter 'mpu_base=0xNNN'.
-
 config SOUND_VIDC
 	tristate "VIDC 16-bit sound"
 	depends on ARM && (ARCH_ACORN || ARCH_CLPS7500) && SOUND_OSS
diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
index 602db49..fef56ca 100644
--- a/sound/oss/ac97_codec.c
+++ b/sound/oss/ac97_codec.c
@@ -744,11 +744,10 @@
  
 struct ac97_codec *ac97_alloc_codec(void)
 {
-	struct ac97_codec *codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL);
+	struct ac97_codec *codec = kzalloc(sizeof(struct ac97_codec), GFP_KERNEL);
 	if(!codec)
 		return NULL;
 
-	memset(codec, 0, sizeof(*codec));
 	spin_lock_init(&codec->lock);
 	INIT_LIST_HEAD(&codec->list);
 	return codec;
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
index 09263d7..c0730a3 100644
--- a/sound/oss/ad1889.c
+++ b/sound/oss/ad1889.c
@@ -230,9 +230,8 @@
 	struct dmabuf *dmabuf;
 	int i;
 
-	if ((dev = kmalloc(sizeof(ad1889_dev_t), GFP_KERNEL)) == NULL) 
+	if ((dev = kzalloc(sizeof(ad1889_dev_t), GFP_KERNEL)) == NULL)
 		return NULL;
-	memset(dev, 0, sizeof(ad1889_dev_t));
 	spin_lock_init(&dev->lock);
 	dev->pci = pci;
 
@@ -778,7 +777,7 @@
 	return 0;
 }
 
-static struct file_operations ad1889_fops = {
+static const struct file_operations ad1889_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= ad1889_read,
@@ -812,7 +811,7 @@
 	return codec->mixer_ioctl(codec, cmd, arg);
 }
 
-static struct file_operations ad1889_mixer_fops = {
+static const struct file_operations ad1889_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.ioctl		= ad1889_mixer_ioctl,
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
index 2197951..a339f0c 100644
--- a/sound/oss/au1550_ac97.c
+++ b/sound/oss/au1550_ac97.c
@@ -1354,11 +1354,11 @@
 		((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
 
 #ifdef DEBUG
-	for (count=0; count<sizeof(ioctl_str)/sizeof(ioctl_str[0]); count++) {
+	for (count = 0; count < ARRAY_SIZE(ioctl_str); count++) {
 		if (ioctl_str[count].cmd == cmd)
 			break;
 	}
-	if (count < sizeof(ioctl_str) / sizeof(ioctl_str[0]))
+	if (count < ARRAY_SIZE(ioctl_str))
 		pr_debug("ioctl %s, arg=0x%lxn", ioctl_str[count].str, arg);
 	else
 		pr_debug("ioctl 0x%x unknown, arg=0x%lx\n", cmd, arg);
diff --git a/sound/oss/btaudio.c b/sound/oss/btaudio.c
index ad7210a..f813ae9 100644
--- a/sound/oss/btaudio.c
+++ b/sound/oss/btaudio.c
@@ -429,7 +429,7 @@
 	return 0;
 }
 
-static struct file_operations btaudio_mixer_fops = {
+static const struct file_operations btaudio_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.open		= btaudio_mixer_open,
@@ -796,7 +796,7 @@
 	return mask;
 }
 
-static struct file_operations btaudio_digital_dsp_fops = {
+static const struct file_operations btaudio_digital_dsp_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.open		= btaudio_dsp_open_digital,
@@ -807,7 +807,7 @@
 	.poll		= btaudio_dsp_poll,
 };
 
-static struct file_operations btaudio_analog_dsp_fops = {
+static const struct file_operations btaudio_analog_dsp_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.open		= btaudio_dsp_open_analog,
@@ -915,12 +915,11 @@
 		return -EBUSY;
 	}
 
-	bta = kmalloc(sizeof(*bta),GFP_ATOMIC);
+	bta = kzalloc(sizeof(*bta),GFP_ATOMIC);
 	if (!bta) {
 		rc = -ENOMEM;
 		goto fail0;
 	}
-	memset(bta,0,sizeof(*bta));
 
 	bta->pci  = pci_dev;
 	bta->irq  = pci_dev->irq;
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
index 147c8a9..2a1f0d9 100644
--- a/sound/oss/cs46xx.c
+++ b/sound/oss/cs46xx.c
@@ -3048,10 +3048,9 @@
 		CS_DBGOUT(CS_WAVE_READ, 2, printk("cs46xx: cs_open() FMODE_READ\n") );
 		if (card->states[0] == NULL) {
 			state = card->states[0] =
-				kmalloc(sizeof(struct cs_state), GFP_KERNEL);
+				kzalloc(sizeof(struct cs_state), GFP_KERNEL);
 			if (state == NULL)
 				return -ENOMEM;
-			memset(state, 0, sizeof(struct cs_state));
 			mutex_init(&state->sem);
 			dmabuf = &state->dmabuf;
 			dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -3114,10 +3113,9 @@
 		CS_DBGOUT(CS_OPEN, 2, printk("cs46xx: cs_open() FMODE_WRITE\n") );
 		if (card->states[1] == NULL) {
 			state = card->states[1] =
-				kmalloc(sizeof(struct cs_state), GFP_KERNEL);
+				kzalloc(sizeof(struct cs_state), GFP_KERNEL);
 			if (state == NULL)
 				return -ENOMEM;
-			memset(state, 0, sizeof(struct cs_state));
 			mutex_init(&state->sem);
 			dmabuf = &state->dmabuf;
 			dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -5075,11 +5073,10 @@
 	pci_read_config_word(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
 	pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &ss_card);
 
-	if ((card = kmalloc(sizeof(struct cs_card), GFP_KERNEL)) == NULL) {
+	if ((card = kzalloc(sizeof(struct cs_card), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "cs46xx: out of memory\n");
 		return -ENOMEM;
 	}
-	memset(card, 0, sizeof(*card));
 	card->ba0_addr = RSRCADDRESS(pci_dev, 0);
 	card->ba1_addr = RSRCADDRESS(pci_dev, 1);
 	card->pci_dev = pci_dev;
diff --git a/sound/oss/dmasound/Kconfig b/sound/oss/dmasound/Kconfig
index cb84558..18e149f 100644
--- a/sound/oss/dmasound/Kconfig
+++ b/sound/oss/dmasound/Kconfig
@@ -14,7 +14,7 @@
 
 config DMASOUND_PMAC
 	tristate "PowerMac DMA sound support"
-	depends on PPC32 && PPC_PMAC && SOUND && I2C
+	depends on PPC32 && PPC_PMAC && SOUND && I2C && OBSOLETE_OSS
  	select DMASOUND
 	help
 	  If you want to use the internal audio of your PowerMac in Linux,
diff --git a/sound/oss/dmasound/dac3550a.c b/sound/oss/dmasound/dac3550a.c
index 7360d89..0f0d03a 100644
--- a/sound/oss/dmasound/dac3550a.c
+++ b/sound/oss/dmasound/dac3550a.c
@@ -163,10 +163,9 @@
 	struct i2c_client *new_client;
 	int rc = -ENODEV;
 
-	new_client = kmalloc(sizeof(*new_client), GFP_KERNEL);
+	new_client = kzalloc(sizeof(*new_client), GFP_KERNEL);
 	if (!new_client)
 		return -ENOMEM;
-	memset(new_client, 0, sizeof(*new_client));
 
 	new_client->addr = address;
 	new_client->adapter = adapter;
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index 80b836e..a0ec886 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -371,7 +371,7 @@
 	return -EINVAL;
 }
 
-static struct file_operations mixer_fops =
+static const struct file_operations mixer_fops =
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
@@ -1337,7 +1337,7 @@
 	return -EINVAL;
 }
 
-static struct file_operations sq_fops =
+static const struct file_operations sq_fops =
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
@@ -1561,7 +1561,7 @@
 	return n;
 }
 
-static struct file_operations state_fops = {
+static const struct file_operations state_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= state_read,
diff --git a/sound/oss/dmasound/tas3001c.c b/sound/oss/dmasound/tas3001c.c
index 2f21a3c..4b7dbdd 100644
--- a/sound/oss/dmasound/tas3001c.c
+++ b/sound/oss/dmasound/tas3001c.c
@@ -807,10 +807,9 @@
 	size_t sz = sizeof(*self) + (TAS3001C_REG_MAX*sizeof(tas_shadow_t));
 	int i, j;
 
-	self = kmalloc(sz, GFP_KERNEL);
+	self = kzalloc(sz, GFP_KERNEL);
 	if (!self)
 		return -ENOMEM;
-	memset(self, 0, sz);
 
 	self->super.client = client;
 	self->super.shadow = (tas_shadow_t *)(self+1);
diff --git a/sound/oss/dmasound/tas3004.c b/sound/oss/dmasound/tas3004.c
index af34fb3..678bf0f 100644
--- a/sound/oss/dmasound/tas3004.c
+++ b/sound/oss/dmasound/tas3004.c
@@ -1092,10 +1092,9 @@
 	char mcr2 = 0;
 	int i, j;
 
-	self = kmalloc(sz, GFP_KERNEL);
+	self = kzalloc(sz, GFP_KERNEL);
 	if (!self)
 		return -ENOMEM;
-	memset(self, 0, sz);
 
 	self->super.client = client;
 	self->super.shadow = (tas_shadow_t *)(self+1);
diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c
index 882ae98..665e85b 100644
--- a/sound/oss/dmasound/tas_common.c
+++ b/sound/oss/dmasound/tas_common.c
@@ -135,10 +135,9 @@
 		return -ENODEV;
 	}
 	
-	new_client = kmalloc(sizeof(*new_client), GFP_KERNEL);
+	new_client = kzalloc(sizeof(*new_client), GFP_KERNEL);
 	if (!new_client)
 		return -ENOMEM;
-	memset(new_client, 0, sizeof(*new_client));
 
 	new_client->addr = address;
 	new_client->adapter = adapter;
diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c
index efcf589..e75ea21 100644
--- a/sound/oss/emu10k1/audio.c
+++ b/sound/oss/emu10k1/audio.c
@@ -1582,7 +1582,7 @@
 	return;
 }
 
-struct file_operations emu10k1_audio_fops = {
+const struct file_operations emu10k1_audio_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= emu10k1_audio_read,
diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
index 6c59df7..16ac025 100644
--- a/sound/oss/emu10k1/main.c
+++ b/sound/oss/emu10k1/main.c
@@ -455,15 +455,13 @@
 {
 	int ret;
 
-	card->mpuout = kmalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL);
+	card->mpuout = kzalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL);
 	if (card->mpuout == NULL) {
 		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuout: out of memory\n");
 		ret = -ENOMEM;
 		goto err_out1;
 	}
 
-	memset(card->mpuout, 0, sizeof(struct emu10k1_mpuout));
-
 	card->mpuout->intr = 1;
 	card->mpuout->status = FLAGS_AVAILABLE;
 	card->mpuout->state = CARDMIDIOUT_STATE_DEFAULT;
@@ -472,15 +470,13 @@
 
 	spin_lock_init(&card->mpuout->lock);
 
-	card->mpuin = kmalloc(sizeof(struct emu10k1_mpuin), GFP_KERNEL);
+	card->mpuin = kzalloc(sizeof(struct emu10k1_mpuin), GFP_KERNEL);
 	if (card->mpuin == NULL) {
 		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuin: out of memory\n");
 		ret = -ENOMEM;
                 goto err_out2;
 	}
 
-	memset(card->mpuin, 0, sizeof(struct emu10k1_mpuin));
-
 	card->mpuin->status = FLAGS_AVAILABLE;
 
 	tasklet_init(&card->mpuin->tasklet, emu10k1_mpuin_bh, (unsigned long) card->mpuin);
@@ -1280,11 +1276,10 @@
 
 	pci_set_master(pci_dev);
 
-	if ((card = kmalloc(sizeof(struct emu10k1_card), GFP_KERNEL)) == NULL) {
+	if ((card = kzalloc(sizeof(struct emu10k1_card), GFP_KERNEL)) == NULL) {
                 printk(KERN_ERR "emu10k1: out of memory\n");
                 return -ENOMEM;
         }
-        memset(card, 0, sizeof(struct emu10k1_card));
 
 	card->iobase = pci_resource_start(pci_dev, 0);
 	card->length = pci_resource_len(pci_dev, 0); 
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
index cca3dad..df1e990 100644
--- a/sound/oss/emu10k1/midi.c
+++ b/sound/oss/emu10k1/midi.c
@@ -458,7 +458,7 @@
 }
 
 /* MIDI file operations */
-struct file_operations emu10k1_midi_fops = {
+const struct file_operations emu10k1_midi_fops = {
 	.owner		= THIS_MODULE,
 	.read		= emu10k1_midi_read,
 	.write		= emu10k1_midi_write,
diff --git a/sound/oss/emu10k1/mixer.c b/sound/oss/emu10k1/mixer.c
index 6419796..bc3805f 100644
--- a/sound/oss/emu10k1/mixer.c
+++ b/sound/oss/emu10k1/mixer.c
@@ -681,7 +681,7 @@
 	return 0;
 }
 
-struct file_operations emu10k1_mixer_fops = {
+const struct file_operations emu10k1_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.ioctl		= emu10k1_mixer_ioctl,
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c
index cc282a0..974dd73 100644
--- a/sound/oss/es1371.c
+++ b/sound/oss/es1371.c
@@ -131,6 +131,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/mutex.h>
 #include <linux/mm.h>
+#include <linux/kernel.h>
 
 #include <asm/io.h>
 #include <asm/page.h>
@@ -2870,11 +2871,10 @@
 		printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n");
 		return i;
 	}
-	if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
+	if (!(s = kzalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
 		printk(KERN_WARNING PFX "out of memory\n");
 		return -ENOMEM;
 	}
-	memset(s, 0, sizeof(struct es1371_state));
 	
 	s->codec = ac97_alloc_codec();
 	if(s->codec == NULL)
@@ -2998,7 +2998,7 @@
 	set_fs(KERNEL_DS);
 	val = SOUND_MASK_LINE;
 	mixdev_ioctl(s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
-	for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(initvol); i++) {
 		val = initvol[i].vol;
 		mixdev_ioctl(s->codec, initvol[i].mixch, (unsigned long)&val);
 	}
diff --git a/sound/oss/hal2.c b/sound/oss/hal2.c
index d18286c..a94b9df 100644
--- a/sound/oss/hal2.c
+++ b/sound/oss/hal2.c
@@ -1377,7 +1377,7 @@
 	return 0;
 }
 
-static struct file_operations hal2_audio_fops = {
+static const struct file_operations hal2_audio_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= hal2_read,
@@ -1388,7 +1388,7 @@
 	.release	= hal2_release,
 };
 
-static struct file_operations hal2_mixer_fops = {
+static const struct file_operations hal2_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.ioctl		= hal2_ioctl_mixdev,
@@ -1435,10 +1435,9 @@
 	int ret = 0;
 	struct hal2_card *hal2;
 
-	hal2 = kmalloc(sizeof(struct hal2_card), GFP_KERNEL);
+	hal2 = kzalloc(sizeof(struct hal2_card), GFP_KERNEL);
 	if (!hal2)
 		return -ENOMEM;
-	memset(hal2, 0, sizeof(struct hal2_card));
 
 	hal2->ctl_regs = (struct hal2_ctl_regs *)hpc3->pbus_extregs[0];
 	hal2->aes_regs = (struct hal2_aes_regs *)hpc3->pbus_extregs[1];
diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
index c3c8a72..f5e31f1 100644
--- a/sound/oss/i810_audio.c
+++ b/sound/oss/i810_audio.c
@@ -2580,10 +2580,9 @@
 		for (i = 0; i < NR_HW_CH && card && !card->initializing; i++) {
 			if (card->states[i] == NULL) {
 				state = card->states[i] = (struct i810_state *)
-					kmalloc(sizeof(struct i810_state), GFP_KERNEL);
+					kzalloc(sizeof(struct i810_state), GFP_KERNEL);
 				if (state == NULL)
 					return -ENOMEM;
-				memset(state, 0, sizeof(struct i810_state));
 				dmabuf = &state->dmabuf;
 				goto found_virt;
 			}
@@ -3205,10 +3204,9 @@
 	 */
 	if(card != NULL) {
 		state = card->states[0] = (struct i810_state *)
-					kmalloc(sizeof(struct i810_state), GFP_KERNEL);
+					kzalloc(sizeof(struct i810_state), GFP_KERNEL);
 		if (state == NULL)
 			return;
-		memset(state, 0, sizeof(struct i810_state));
 		dmabuf = &state->dmabuf;
 
 		dmabuf->write_channel = card->alloc_pcm_channel(card);
@@ -3273,11 +3271,10 @@
 		return -ENODEV;
 	}
 	
-	if ((card = kmalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) {
+	if ((card = kzalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "i810_audio: out of memory\n");
 		return -ENOMEM;
 	}
-	memset(card, 0, sizeof(*card));
 
 	card->initializing = 1;
 	card->pci_dev = pci_dev;
diff --git a/sound/oss/kahlua.c b/sound/oss/kahlua.c
index 12e7b30..dfe670f 100644
--- a/sound/oss/kahlua.c
+++ b/sound/oss/kahlua.c
@@ -139,13 +139,12 @@
 	printk(KERN_INFO "kahlua: XpressAudio on IRQ %d, DMA %d, %d\n",
 		irq, dma8, dma16);
 	
-	hw_config = kmalloc(sizeof(struct address_info), GFP_KERNEL);
+	hw_config = kzalloc(sizeof(struct address_info), GFP_KERNEL);
 	if(hw_config == NULL)
 	{
 		printk(KERN_ERR "kahlua: out of memory.\n");
 		return 1;
 	}
-	memset(hw_config, 0, sizeof(*hw_config));
 	
 	pci_set_drvdata(pdev, hw_config);
 	
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index 24110d6..f1f49eb 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -1106,7 +1106,7 @@
 	return IRQ_HANDLED;
 }
 
-static struct file_operations dev_fileops = {
+static const struct file_operations dev_fileops = {
 	.owner		= THIS_MODULE,
 	.read		= dev_read,
 	.write		= dev_write,
diff --git a/sound/oss/nec_vrc5477.c b/sound/oss/nec_vrc5477.c
index da9728e..27b4ba3 100644
--- a/sound/oss/nec_vrc5477.c
+++ b/sound/oss/nec_vrc5477.c
@@ -1381,11 +1381,11 @@
 	int val, ret;
 
 #ifdef VRC5477_AC97_DEBUG
-	for (count=0; count<sizeof(ioctl_str)/sizeof(ioctl_str[0]); count++) {
+	for (count = 0; count < ARRAY_SIZE(ioctl_str); count++) {
 		if (ioctl_str[count].cmd == cmd)
 			break;
 	}
-	if (count < sizeof(ioctl_str)/sizeof(ioctl_str[0]))
+	if (count < ARRAY_SIZE(ioctl_str))
 		printk(KERN_INFO PFX "ioctl %s\n", ioctl_str[count].str);
 	else
 		printk(KERN_INFO PFX "ioctl unknown, 0x%x\n", cmd);
@@ -1860,11 +1860,10 @@
 	if (pcidev->irq == 0) 
 		return -1;
 
-	if (!(s = kmalloc(sizeof(struct vrc5477_ac97_state), GFP_KERNEL))) {
+	if (!(s = kzalloc(sizeof(struct vrc5477_ac97_state), GFP_KERNEL))) {
 		printk(KERN_ERR PFX "alloc of device struct failed\n");
 		return -1;
 	}
-	memset(s, 0, sizeof(struct vrc5477_ac97_state));
 
 	init_waitqueue_head(&s->dma_adc.wait);
 	init_waitqueue_head(&s->dma_dac.wait);
diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c
index 2e8cfa5..fc273e5 100644
--- a/sound/oss/opl3.c
+++ b/sound/oss/opl3.c
@@ -166,7 +166,7 @@
 		return 0;
 	}
 
-	devc = kmalloc(sizeof(*devc), GFP_KERNEL);
+	devc = kzalloc(sizeof(*devc), GFP_KERNEL);
 
 	if (devc == NULL)
 	{
@@ -175,7 +175,6 @@
 		return 0;
 	}
 
-	memset(devc, 0, sizeof(*devc));
 	strcpy(devc->fm_info.name, "OPL2");
 
 	if (!request_region(ioaddr, 4, devc->fm_info.name)) {
diff --git a/sound/oss/os.h b/sound/oss/os.h
index 0490562..a1a962d 100644
--- a/sound/oss/os.h
+++ b/sound/oss/os.h
@@ -43,4 +43,4 @@
 #undef PSEUDO_DMA_AUTOINIT
 #define ALLOW_BUFFER_MAPPING
 
-extern struct file_operations oss_sound_fops;
+extern const struct file_operations oss_sound_fops;
diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c
index 8666291..27acd6f 100644
--- a/sound/oss/sb_card.c
+++ b/sound/oss/sb_card.c
@@ -137,11 +137,10 @@
 {
 	struct sb_module_options sbmo = {0};
 
-	if((legacy = kmalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
+	if((legacy = kzalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "sb: Error: Could not allocate memory\n");
 		return -ENOMEM;
 	}
-	memset(legacy, 0, sizeof(struct sb_card_config));
 
 	legacy->conf.io_base      = io;
 	legacy->conf.irq          = irq;
@@ -247,11 +246,10 @@
 		return -EBUSY;
 	}
 
-	if((scc = kmalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
+	if((scc = kzalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "sb: Error: Could not allocate memory\n");
 		return -ENOMEM;
 	}
-	memset(scc, 0, sizeof(struct sb_card_config));
 
 	printk(KERN_INFO "sb: PnP: Found Card Named = \"%s\", Card PnP id = " \
 	       "%s, Device PnP id = %s\n", card->card->name, card_id->id,
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
index 51f5541..7ea9acc 100644
--- a/sound/oss/sh_dac_audio.c
+++ b/sound/oss/sh_dac_audio.c
@@ -255,7 +255,7 @@
 	return 0;
 }
 
-struct file_operations dac_audio_fops = {
+const struct file_operations dac_audio_fops = {
       .read =		dac_audio_read,
       .write =	dac_audio_write,
       .ioctl =	dac_audio_ioctl,
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index a89108c..dcd8d6d 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -32,6 +32,7 @@
 #include <linux/ctype.h>
 #include <linux/stddef.h>
 #include <linux/kmod.h>
+#include <linux/kernel.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <linux/wait.h>
@@ -482,7 +483,7 @@
 	return 0;
 }
 
-struct file_operations oss_sound_fops = {
+const struct file_operations oss_sound_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= sound_read,
@@ -557,7 +558,7 @@
 	/* Protecting the innocent */
 	sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 
-	for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
+	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
 		device_create(sound_class, NULL,
 			      MKDEV(SOUND_MAJOR, dev_list[i].minor),
 			      "%s", dev_list[i].name);
@@ -581,7 +582,7 @@
 {
 	int i, j;
 
-	for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
+	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
 		device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
 		if (!dev_list[i].num)
 			continue;
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
index 471c274..016b918 100644
--- a/sound/oss/swarm_cs4297a.c
+++ b/sound/oss/swarm_cs4297a.c
@@ -77,6 +77,7 @@
 #include <linux/poll.h>
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
+#include <linux/kernel.h>
 
 #include <asm/byteorder.h>
 #include <asm/dma.h>
@@ -615,25 +616,23 @@
 
         /* Descriptors */
         dma->ringsz = DMA_DESCR;
-        dma->descrtab = kmalloc(dma->ringsz * sizeof(serdma_descr_t), GFP_KERNEL);
+        dma->descrtab = kzalloc(dma->ringsz * sizeof(serdma_descr_t), GFP_KERNEL);
         if (!dma->descrtab) {
-                printk(KERN_ERR "cs4297a: kmalloc descrtab failed\n");
+                printk(KERN_ERR "cs4297a: kzalloc descrtab failed\n");
                 return -1;
         }
-        memset(dma->descrtab, 0, dma->ringsz * sizeof(serdma_descr_t));
         dma->descrtab_end = dma->descrtab + dma->ringsz;
 	/* XXX bloddy mess, use proper DMA API here ...  */
 	dma->descrtab_phys = CPHYSADDR((long)dma->descrtab);
         dma->descr_add = dma->descr_rem = dma->descrtab;
 
         /* Frame buffer area */
-        dma->dma_buf = kmalloc(DMA_BUF_SIZE, GFP_KERNEL);
+        dma->dma_buf = kzalloc(DMA_BUF_SIZE, GFP_KERNEL);
         if (!dma->dma_buf) {
-                printk(KERN_ERR "cs4297a: kmalloc dma_buf failed\n");
+                printk(KERN_ERR "cs4297a: kzalloc dma_buf failed\n");
                 kfree(dma->descrtab);
                 return -1;
         }
-        memset(dma->dma_buf, 0, DMA_BUF_SIZE);
         dma->dma_buf_phys = CPHYSADDR((long)dma->dma_buf);
 
         /* Samples buffer area */
@@ -2618,12 +2617,11 @@
         udelay(100);
 #endif
 
-	if (!(s = kmalloc(sizeof(struct cs4297a_state), GFP_KERNEL))) {
+	if (!(s = kzalloc(sizeof(struct cs4297a_state), GFP_KERNEL))) {
 		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
 		      "cs4297a: probe() no memory for state struct.\n"));
 		return -1;
 	}
-	memset(s, 0, sizeof(struct cs4297a_state));
         s->magic = CS4297a_MAGIC;
 	init_waitqueue_head(&s->dma_adc.wait);
 	init_waitqueue_head(&s->dma_dac.wait);
@@ -2676,7 +2674,7 @@
 #if 0
                 val = SOUND_MASK_LINE;
                 mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val);
-                for (i = 0; i < sizeof(initvol) / sizeof(initvol[0]); i++) {
+                for (i = 0; i < ARRAY_SIZE(initvol); i++) {
                         val = initvol[i].vol;
                         mixer_ioctl(s, initvol[i].mixch, (unsigned long) &val);
                 }
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 6b1f8c9..72a8a0e 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -2729,12 +2729,11 @@
 		}
 		for (i = 0; i < NR_HW_CH; i++) {
 			if (card->states[i] == NULL) {
-				state = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL);
+				state = card->states[i] = kzalloc(sizeof(*state), GFP_KERNEL);
 				if (state == NULL) {
 					mutex_unlock(&card->open_mutex);
 					return -ENOMEM;
 				}
-				memset(state, 0, sizeof(*state));
 				mutex_init(&state->sem);
 				dmabuf = &state->dmabuf;
 				goto found_virt;
@@ -3618,7 +3617,7 @@
 			}
 			return -EBUSY;
 		}
-		s = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL);
+		s = card->states[i] = kzalloc(sizeof(*state), GFP_KERNEL);
 		if (!s) {
 			num = ali_multi_channels_5_1[state_count];
 			ali_free_pcm_channel(card, num);
@@ -3630,7 +3629,6 @@
 			}
 			return -ENOMEM;
 		}
-		memset(s, 0, sizeof(*state));
 
 		s->dmabuf.channel = channel;
 		s->dmabuf.ossfragshift = s->dmabuf.ossmaxfrags =
@@ -4399,11 +4397,10 @@
 	}
 
 	rc = -ENOMEM;
-	if ((card = kmalloc(sizeof(*card), GFP_KERNEL)) == NULL) {
+	if ((card = kzalloc(sizeof(*card), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "trident: out of memory\n");
 		goto out_release_region;
 	}
-	memset(card, 0, sizeof (*card));
 
 	init_timer(&card->timer);
 	card->iobase = iobase;
diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c
index c96cc8c..7ab3a73 100644
--- a/sound/oss/via82cxxx_audio.c
+++ b/sound/oss/via82cxxx_audio.c
@@ -1619,7 +1619,7 @@
 }
 
 
-static struct file_operations via_mixer_fops = {
+static const struct file_operations via_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.open		= via_mixer_open,
 	.llseek		= no_llseek,
@@ -2042,7 +2042,7 @@
  *
  */
 
-static struct file_operations via_dsp_fops = {
+static const struct file_operations via_dsp_fops = {
 	.owner		= THIS_MODULE,
 	.open		= via_dsp_open,
 	.release	= via_dsp_release,
diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c
index 6dfb9f4..d25249a 100644
--- a/sound/oss/vwsnd.c
+++ b/sound/oss/vwsnd.c
@@ -3035,7 +3035,7 @@
 	return err;
 }
 
-static struct file_operations vwsnd_audio_fops = {
+static const struct file_operations vwsnd_audio_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.read =		vwsnd_audio_read,
@@ -3225,7 +3225,7 @@
 	return retval;
 }
 
-static struct file_operations vwsnd_mixer_fops = {
+static const struct file_operations vwsnd_mixer_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.ioctl =	vwsnd_mixer_ioctl,
diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c
index 26a7c6a..b48c729 100644
--- a/sound/oss/waveartist.c
+++ b/sound/oss/waveartist.c
@@ -1267,12 +1267,10 @@
 	conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq,
 		     devc->hw.dma, devc->hw.dma2);
 
-	portc = kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
+	portc = kzalloc(sizeof(wavnc_port_info), GFP_KERNEL);
 	if (portc == NULL)
 		goto nomem;
 
-	memset(portc, 0, sizeof(wavnc_port_info));
-
 	my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name,
 			&waveartist_audio_driver, sizeof(struct audio_driver),
 			devc->audio_flags, AFMT_U8 | AFMT_S16_LE | AFMT_S8,
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 8a6b180..1bcfb3a 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -236,7 +236,7 @@
 config SND_DARLA20
 	tristate "(Echoaudio) Darla20"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_PCM
 	help
 	  Say 'Y' or 'M' to include support for Echoaudio Darla.
@@ -247,7 +247,7 @@
 config SND_GINA20
 	tristate "(Echoaudio) Gina20"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_PCM
 	help
 	  Say 'Y' or 'M' to include support for Echoaudio Gina.
@@ -258,7 +258,7 @@
 config SND_LAYLA20
 	tristate "(Echoaudio) Layla20"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_RAWMIDI
 	select SND_PCM
 	help
@@ -270,7 +270,7 @@
 config SND_DARLA24
 	tristate "(Echoaudio) Darla24"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_PCM
 	help
 	  Say 'Y' or 'M' to include support for Echoaudio Darla24.
@@ -281,7 +281,7 @@
 config SND_GINA24
 	tristate "(Echoaudio) Gina24"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_PCM
 	help
 	  Say 'Y' or 'M' to include support for Echoaudio Gina24.
@@ -292,7 +292,7 @@
 config SND_LAYLA24
 	tristate "(Echoaudio) Layla24"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_RAWMIDI
 	select SND_PCM
 	help
@@ -304,7 +304,7 @@
 config SND_MONA
 	tristate "(Echoaudio) Mona"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_RAWMIDI
 	select SND_PCM
 	help
@@ -316,7 +316,7 @@
 config SND_MIA
 	tristate "(Echoaudio) Mia"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_RAWMIDI
 	select SND_PCM
 	help
@@ -328,7 +328,7 @@
 config SND_ECHO3G
 	tristate "(Echoaudio) 3G cards"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_RAWMIDI
 	select SND_PCM
 	help
@@ -340,7 +340,7 @@
 config SND_INDIGO
 	tristate "(Echoaudio) Indigo"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_PCM
 	help
 	  Say 'Y' or 'M' to include support for Echoaudio Indigo.
@@ -351,7 +351,7 @@
 config SND_INDIGOIO
 	tristate "(Echoaudio) Indigo IO"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_PCM
 	help
 	  Say 'Y' or 'M' to include support for Echoaudio Indigo IO.
@@ -362,7 +362,7 @@
 config SND_INDIGODJ
 	tristate "(Echoaudio) Indigo DJ"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_PCM
 	help
 	  Say 'Y' or 'M' to include support for Echoaudio Indigo DJ.
@@ -373,6 +373,7 @@
 config SND_EMU10K1
 	tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)"
 	depends on SND
+	select FW_LOADER
 	select SND_HWDEP
 	select SND_RAWMIDI
 	select SND_AC97_CODEC
@@ -575,6 +576,7 @@
 config SND_KORG1212
 	tristate "Korg 1212 IO"
 	depends on SND
+	select FW_LOADER
 	select SND_PCM
 	help
 	  Say Y here to include support for Korg 1212IO soundcards.
@@ -585,6 +587,7 @@
 config SND_MAESTRO3
 	tristate "ESS Allegro/Maestro3"
 	depends on SND
+	select FW_LOADER
 	select SND_AC97_CODEC
 	help
 	  Say Y here to include support for soundcards based on ESS Maestro 3
@@ -629,7 +632,7 @@
 config SND_RIPTIDE
 	tristate "Conexant Riptide"
 	depends on SND
-	depends on FW_LOADER
+	select FW_LOADER
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
@@ -734,6 +737,7 @@
 config SND_YMFPCI
 	tristate "Yamaha YMF724/740/744/754"
 	depends on SND
+	select FW_LOADER
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index d2994cb..a9eec2a 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -111,7 +111,7 @@
 { 0x41445372, 0xffffffff, "AD1981A",		patch_ad1981a,	NULL },
 { 0x41445374, 0xffffffff, "AD1981B",		patch_ad1981b,	NULL },
 { 0x41445375, 0xffffffff, "AD1985",		patch_ad1985,	NULL },
-{ 0x41445378, 0xffffffff, "AD1986",		patch_ad1985,	NULL },
+{ 0x41445378, 0xffffffff, "AD1986",		patch_ad1986,	NULL },
 { 0x414c4300, 0xffffff00, "ALC100,100P", 	NULL,		NULL },
 { 0x414c4710, 0xfffffff0, "ALC200,200P",	NULL,		NULL },
 { 0x414c4721, 0xffffffff, "ALC650D",		NULL,	NULL }, /* already patched */
@@ -143,6 +143,7 @@
 { 0x43525970, 0xfffffff8, "CS4202",		NULL,		NULL },
 { 0x43585421, 0xffffffff, "HSD11246",		NULL,		NULL },	// SmartMC II
 { 0x43585428, 0xfffffff8, "Cx20468",		patch_conexant,	NULL }, // SmartAMC fixme: the mask might be different
+{ 0x43585431, 0xffffffff, "Cx20551",           patch_cx20551,  NULL },
 { 0x44543031, 0xfffffff0, "DT0398",		NULL,		NULL },
 { 0x454d4328, 0xffffffff, "EM28028",		NULL,		NULL },  // same as TR28028?
 { 0x45838308, 0xffffffff, "ESS1988",		NULL,		NULL },
@@ -194,6 +195,13 @@
 
 
 static void update_power_regs(struct snd_ac97 *ac97);
+#ifdef CONFIG_SND_AC97_POWER_SAVE
+#define ac97_is_power_save_mode(ac97) \
+	((ac97->scaps & AC97_SCAP_POWER_SAVE) && power_save)
+#else
+#define ac97_is_power_save_mode(ac97) 0
+#endif
+
 
 /*
  *  I/O routines
@@ -982,8 +990,8 @@
 {
 	if (ac97) {
 #ifdef CONFIG_SND_AC97_POWER_SAVE
-		if (ac97->power_workq)
-			destroy_workqueue(ac97->power_workq);
+		cancel_delayed_work(&ac97->power_work);
+		flush_scheduled_work();
 #endif
 		snd_ac97_proc_done(ac97);
 		if (ac97->bus)
@@ -1184,13 +1192,13 @@
 /*
  * set dB information
  */
-static DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
 
-static unsigned int *find_db_scale(unsigned int maxval)
+static const unsigned int *find_db_scale(unsigned int maxval)
 {
 	switch (maxval) {
 	case 0x0f: return db_scale_4bit;
@@ -1200,8 +1208,8 @@
 	return NULL;
 }
 
-static void set_tlv_db_scale(struct snd_kcontrol *kctl, unsigned int *tlv)
-{	
+static void set_tlv_db_scale(struct snd_kcontrol *kctl, const unsigned int *tlv)
+{
 	kctl->tlv.p = tlv;
 	if (tlv)
 		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
@@ -1989,7 +1997,6 @@
 	mutex_init(&ac97->reg_mutex);
 	mutex_init(&ac97->page_mutex);
 #ifdef CONFIG_SND_AC97_POWER_SAVE
-	ac97->power_workq = create_workqueue("ac97");
 	INIT_DELAYED_WORK(&ac97->power_work, do_update_power);
 #endif
 
@@ -2275,15 +2282,13 @@
 	udelay(100);
 	power |= AC97_PD_PR2 | AC97_PD_PR3;	/* Analog Mixer powerdown */
 	snd_ac97_write(ac97, AC97_POWERDOWN, power);
-#ifdef CONFIG_SND_AC97_POWER_SAVE
-	if (power_save) {
+	if (ac97_is_power_save_mode(ac97)) {
 		udelay(100);
 		/* AC-link powerdown, internal Clk disable */
 		/* FIXME: this may cause click noises on some boards */
 		power |= AC97_PD_PR4 | AC97_PD_PR5;
 		snd_ac97_write(ac97, AC97_POWERDOWN, power);
 	}
-#endif
 }
 
 
@@ -2337,14 +2342,16 @@
 		}
 	}
 
-	if (power_save && !powerup && ac97->power_workq)
+	if (ac97_is_power_save_mode(ac97) && !powerup)
 		/* adjust power-down bits after two seconds delay
 		 * (for avoiding loud click noises for many (OSS) apps
 		 *  that open/close frequently)
 		 */
-		queue_delayed_work(ac97->power_workq, &ac97->power_work, HZ*2);
-	else
+		schedule_delayed_work(&ac97->power_work, HZ*2);
+	else {
+		cancel_delayed_work(&ac97->power_work);
 		update_power_regs(ac97);
+	}
 
 	return 0;
 }
@@ -2357,19 +2364,15 @@
 	unsigned int power_up, bits;
 	int i;
 
+	power_up = (1 << PWIDX_FRONT) | (1 << PWIDX_ADC);
+	power_up |= (1 << PWIDX_MIC);
+	if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
+		power_up |= (1 << PWIDX_SURR);
+	if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
+		power_up |= (1 << PWIDX_CLFE);
 #ifdef CONFIG_SND_AC97_POWER_SAVE
-	if (power_save)
+	if (ac97_is_power_save_mode(ac97))
 		power_up = ac97->power_up;
-	else {
-#endif
-		power_up = (1 << PWIDX_FRONT) | (1 << PWIDX_ADC);
-		power_up |= (1 << PWIDX_MIC);
-		if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
-			power_up |= (1 << PWIDX_SURR);
-		if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
-			power_up |= (1 << PWIDX_CLFE);
-#ifdef CONFIG_SND_AC97_POWER_SAVE
-	}
 #endif
 	if (power_up) {
 		if (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2) {
@@ -2414,6 +2417,10 @@
 		return;
 	if (ac97->build_ops->suspend)
 		ac97->build_ops->suspend(ac97);
+#ifdef CONFIG_SND_AC97_POWER_SAVE
+	cancel_delayed_work(&ac97->power_work);
+	flush_scheduled_work();
+#endif
 	snd_ac97_powerdown(ac97);
 }
 
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index e813968..bfc2fed 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -54,7 +54,7 @@
 
 /* replace with a new TLV */
 static void reset_tlv(struct snd_ac97 *ac97, const char *name,
-		      unsigned int *tlv)
+		      const unsigned int *tlv)
 {
 	struct snd_ctl_elem_id sid;
 	struct snd_kcontrol *kctl;
@@ -190,14 +190,28 @@
 	return ac97->channel_mode >= 2;
 }
 
-static inline int is_shared_linein(struct snd_ac97 *ac97)
+/* system has shared jacks with surround out enabled */
+static inline int is_shared_surrout(struct snd_ac97 *ac97)
 {
-	return ! ac97->indep_surround && is_surround_on(ac97);
+	return !ac97->indep_surround && is_surround_on(ac97);
 }
 
+/* system has shared jacks with center/lfe out enabled */
+static inline int is_shared_clfeout(struct snd_ac97 *ac97)
+{
+	return !ac97->indep_surround && is_clfe_on(ac97);
+}
+
+/* system has shared jacks with line in enabled */
+static inline int is_shared_linein(struct snd_ac97 *ac97)
+{
+	return !ac97->indep_surround && !is_surround_on(ac97);
+}
+
+/* system has shared jacks with mic in enabled */
 static inline int is_shared_micin(struct snd_ac97 *ac97)
 {
-	return ! ac97->indep_surround && is_clfe_on(ac97);
+	return !ac97->indep_surround && !is_clfe_on(ac97);
 }
 
 
@@ -941,6 +955,9 @@
 {
 	int err;
 
+	/* the register bit is writable, but the function is not implemented: */
+	snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL);
+
 	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
 	if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0)
 		return err;
@@ -1321,6 +1338,12 @@
 	return 0;
 }
 
+int patch_cx20551(struct snd_ac97 *ac97)
+{
+	snd_ac97_update_bits(ac97, 0x5c, 0x01, 0x01);
+	return 0;
+}
+
 /*
  * Analog Device AD18xx, AD19xx codecs
  */
@@ -1552,7 +1575,7 @@
 	AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
 };
 
-static DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
 
 static int patch_ad1885_specific(struct snd_ac97 * ac97)
 {
@@ -1609,19 +1632,22 @@
 	return 0;
 }
 
-/* MISC bits */
+/* MISC bits (AD1888/AD1980/AD1985 register 0x76) */
 #define AC97_AD198X_MBC		0x0003	/* mic boost */
 #define AC97_AD198X_MBC_20	0x0000	/* +20dB */
 #define AC97_AD198X_MBC_10	0x0001	/* +10dB */
 #define AC97_AD198X_MBC_30	0x0002	/* +30dB */
 #define AC97_AD198X_VREFD	0x0004	/* VREF high-Z */
-#define AC97_AD198X_VREFH	0x0008	/* 2.25V, 3.7V */
-#define AC97_AD198X_VREF_0	0x000c	/* 0V */
+#define AC97_AD198X_VREFH	0x0008	/* 0=2.25V, 1=3.7V */
+#define AC97_AD198X_VREF_0	0x000c	/* 0V (AD1985 only) */
+#define AC97_AD198X_VREF_MASK	(AC97_AD198X_VREFH | AC97_AD198X_VREFD)
+#define AC97_AD198X_VREF_SHIFT	2
 #define AC97_AD198X_SRU		0x0010	/* sample rate unlock */
 #define AC97_AD198X_LOSEL	0x0020	/* LINE_OUT amplifiers input select */
 #define AC97_AD198X_2MIC	0x0040	/* 2-channel mic select */
 #define AC97_AD198X_SPRD	0x0080	/* SPREAD enable */
-#define AC97_AD198X_DMIX0	0x0100	/* downmix mode: 0 = 6-to-4, 1 = 6-to-2 downmix */
+#define AC97_AD198X_DMIX0	0x0100	/* downmix mode: */
+					/*  0 = 6-to-4, 1 = 6-to-2 downmix */
 #define AC97_AD198X_DMIX1	0x0200	/* downmix mode: 1 = enabled */
 #define AC97_AD198X_HPSEL	0x0400	/* headphone amplifier input select */
 #define AC97_AD198X_CLDIS	0x0800	/* center/lfe disable */
@@ -1630,6 +1656,83 @@
 #define AC97_AD198X_AC97NC	0x4000	/* AC97 no compatible mode */
 #define AC97_AD198X_DACZ	0x8000	/* DAC zero-fill mode */
 
+/* MISC 1 bits (AD1986 register 0x76) */
+#define AC97_AD1986_MBC		0x0003	/* mic boost */
+#define AC97_AD1986_MBC_20	0x0000	/* +20dB */
+#define AC97_AD1986_MBC_10	0x0001	/* +10dB */
+#define AC97_AD1986_MBC_30	0x0002	/* +30dB */
+#define AC97_AD1986_LISEL0	0x0004	/* LINE_IN select bit 0 */
+#define AC97_AD1986_LISEL1	0x0008	/* LINE_IN select bit 1 */
+#define AC97_AD1986_LISEL_MASK	(AC97_AD1986_LISEL1 | AC97_AD1986_LISEL0)
+#define AC97_AD1986_LISEL_LI	0x0000  /* LINE_IN pins as LINE_IN source */
+#define AC97_AD1986_LISEL_SURR	0x0004  /* SURROUND pins as LINE_IN source */
+#define AC97_AD1986_LISEL_MIC	0x0008  /* MIC_1/2 pins as LINE_IN source */
+#define AC97_AD1986_SRU		0x0010	/* sample rate unlock */
+#define AC97_AD1986_SOSEL	0x0020	/* SURROUND_OUT amplifiers input sel */
+#define AC97_AD1986_2MIC	0x0040	/* 2-channel mic select */
+#define AC97_AD1986_SPRD	0x0080	/* SPREAD enable */
+#define AC97_AD1986_DMIX0	0x0100	/* downmix mode: */
+					/*  0 = 6-to-4, 1 = 6-to-2 downmix */
+#define AC97_AD1986_DMIX1	0x0200	/* downmix mode: 1 = enabled */
+#define AC97_AD1986_CLDIS	0x0800	/* center/lfe disable */
+#define AC97_AD1986_SODIS	0x1000	/* SURROUND_OUT disable */
+#define AC97_AD1986_MSPLT	0x2000	/* mute split (read only 1) */
+#define AC97_AD1986_AC97NC	0x4000	/* AC97 no compatible mode (r/o 1) */
+#define AC97_AD1986_DACZ	0x8000	/* DAC zero-fill mode */
+
+/* MISC 2 bits (AD1986 register 0x70) */
+#define AC97_AD_MISC2		0x70	/* Misc Control Bits 2 (AD1986) */
+
+#define AC97_AD1986_CVREF0	0x0004	/* C/LFE VREF_OUT 2.25V */
+#define AC97_AD1986_CVREF1	0x0008	/* C/LFE VREF_OUT 0V */
+#define AC97_AD1986_CVREF2	0x0010	/* C/LFE VREF_OUT 3.7V */
+#define AC97_AD1986_CVREF_MASK \
+	(AC97_AD1986_CVREF2 | AC97_AD1986_CVREF1 | AC97_AD1986_CVREF0)
+#define AC97_AD1986_JSMAP	0x0020	/* Jack Sense Mapping 1 = alternate */
+#define AC97_AD1986_MMDIS	0x0080	/* Mono Mute Disable */
+#define AC97_AD1986_MVREF0	0x0400	/* MIC VREF_OUT 2.25V */
+#define AC97_AD1986_MVREF1	0x0800	/* MIC VREF_OUT 0V */
+#define AC97_AD1986_MVREF2	0x1000	/* MIC VREF_OUT 3.7V */
+#define AC97_AD1986_MVREF_MASK \
+	(AC97_AD1986_MVREF2 | AC97_AD1986_MVREF1 | AC97_AD1986_MVREF0)
+
+/* MISC 3 bits (AD1986 register 0x7a) */
+#define AC97_AD_MISC3		0x7a	/* Misc Control Bits 3 (AD1986) */
+
+#define AC97_AD1986_MMIX	0x0004	/* Mic Mix, left/right */
+#define AC97_AD1986_GPO		0x0008	/* General Purpose Out */
+#define AC97_AD1986_LOHPEN	0x0010	/* LINE_OUT headphone drive */
+#define AC97_AD1986_LVREF0	0x0100	/* LINE_OUT VREF_OUT 2.25V */
+#define AC97_AD1986_LVREF1	0x0200	/* LINE_OUT VREF_OUT 0V */
+#define AC97_AD1986_LVREF2	0x0400	/* LINE_OUT VREF_OUT 3.7V */
+#define AC97_AD1986_LVREF_MASK \
+	(AC97_AD1986_LVREF2 | AC97_AD1986_LVREF1 | AC97_AD1986_LVREF0)
+#define AC97_AD1986_JSINVA	0x0800	/* Jack Sense Invert SENSE_A */
+#define AC97_AD1986_LOSEL	0x1000	/* LINE_OUT amplifiers input select */
+#define AC97_AD1986_HPSEL0	0x2000	/* Headphone amplifiers */
+					/*   input select Surround DACs */
+#define AC97_AD1986_HPSEL1	0x4000	/* Headphone amplifiers input */
+					/*   select C/LFE DACs */
+#define AC97_AD1986_JSINVB	0x8000	/* Jack Sense Invert SENSE_B */
+
+/* Serial Config bits (AD1986 register 0x74) (incomplete) */
+#define AC97_AD1986_OMS0	0x0100	/* Optional Mic Selector bit 0 */
+#define AC97_AD1986_OMS1	0x0200	/* Optional Mic Selector bit 1 */
+#define AC97_AD1986_OMS2	0x0400	/* Optional Mic Selector bit 2 */
+#define AC97_AD1986_OMS_MASK \
+	(AC97_AD1986_OMS2 | AC97_AD1986_OMS1 | AC97_AD1986_OMS0)
+#define AC97_AD1986_OMS_M	0x0000  /* MIC_1/2 pins are MIC sources */
+#define AC97_AD1986_OMS_L	0x0100  /* LINE_IN pins are MIC sources */
+#define AC97_AD1986_OMS_C	0x0200  /* Center/LFE pins are MCI sources */
+#define AC97_AD1986_OMS_MC	0x0400  /* Mix of MIC and C/LFE pins */
+					/*   are MIC sources */
+#define AC97_AD1986_OMS_ML	0x0500  /* MIX of MIC and LINE_IN pins */
+					/*   are MIC sources */
+#define AC97_AD1986_OMS_LC	0x0600  /* MIX of LINE_IN and C/LFE pins */
+					/*   are MIC sources */
+#define AC97_AD1986_OMS_MLC	0x0700  /* MIX of MIC, LINE_IN, C/LFE pins */
+					/*   are MIC sources */
+
 
 static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
@@ -1952,8 +2055,80 @@
 	return 0;
 }
 
+static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[4] = {"High-Z", "3.7 V", "2.25 V", "0 V"};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 4;
+	if (uinfo->value.enumerated.item > 3)
+		uinfo->value.enumerated.item = 3;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	static const int reg2ctrl[4] = {2, 0, 1, 3};
+	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned short val;
+	val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK)
+	      >> AC97_AD198X_VREF_SHIFT;
+	ucontrol->value.enumerated.item[0] = reg2ctrl[val];
+	return 0;
+}
+
+static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol, 
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	static const int ctrl2reg[4] = {1, 2, 0, 3};
+	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned short val;
+
+	if (ucontrol->value.enumerated.item[0] > 3
+	    || ucontrol->value.enumerated.item[0] < 0)
+		return -EINVAL;
+	val = ctrl2reg[ucontrol->value.enumerated.item[0]]
+	      << AC97_AD198X_VREF_SHIFT;
+	return snd_ac97_update_bits(ac97, AC97_AD_MISC,
+				    AC97_AD198X_VREF_MASK, val);
+}
+
 static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
-	AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0)
+	AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Exchange Front/Surround",
+		.info = snd_ac97_ad1888_lohpsel_info,
+		.get = snd_ac97_ad1888_lohpsel_get,
+		.put = snd_ac97_ad1888_lohpsel_put
+	},
+	AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
+	AC97_SINGLE("Spread Front to Surround and Center/LFE",
+		    AC97_AD_MISC, 7, 1, 0),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Downmix",
+		.info = snd_ac97_ad1888_downmix_info,
+		.get = snd_ac97_ad1888_downmix_get,
+		.put = snd_ac97_ad1888_downmix_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "V_REFOUT",
+		.info = snd_ac97_ad1985_vrefout_info,
+		.get = snd_ac97_ad1985_vrefout_get,
+		.put = snd_ac97_ad1985_vrefout_put
+	},
+	AC97_SURROUND_JACK_MODE_CTL,
+	AC97_CHANNEL_MODE_CTL,
+
+	AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
+	AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
 };
 
 static void ad1985_update_jacks(struct snd_ac97 *ac97)
@@ -1967,9 +2142,16 @@
 {
 	int err;
 
-	if ((err = patch_ad1980_specific(ac97)) < 0)
+	/* rename 0x04 as "Master" and 0x02 as "Master Surround" */
+	snd_ac97_rename_vol_ctl(ac97, "Master Playback",
+				"Master Surround Playback");
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
+
+	if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
 		return err;
-	return patch_build_controls(ac97, snd_ac97_ad1985_controls, ARRAY_SIZE(snd_ac97_ad1985_controls));
+
+	return patch_build_controls(ac97, snd_ac97_ad1985_controls,
+				    ARRAY_SIZE(snd_ac97_ad1985_controls));
 }
 
 static struct snd_ac97_build_ops patch_ad1985_build_ops = {
@@ -1989,24 +2171,311 @@
 	ac97->build_ops = &patch_ad1985_build_ops;
 	misc = snd_ac97_read(ac97, AC97_AD_MISC);
 	/* switch front/surround line-out/hp-out */
-	/* center/LFE, mic in 3.75V mode */
 	/* AD-compatible mode */
 	/* Stereo mutes enabled */
-	/* in accordance with ADI driver: misc | 0x5c28 */
 	snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
-			     AC97_AD198X_VREFH |
 			     AC97_AD198X_LOSEL |
 			     AC97_AD198X_HPSEL |
-			     AC97_AD198X_CLDIS |
-			     AC97_AD198X_LODIS |
 			     AC97_AD198X_MSPLT |
 			     AC97_AD198X_AC97NC);
 	ac97->flags |= AC97_STEREO_MUTES;
+
+	/* update current jack configuration */
+	ad1985_update_jacks(ac97);
+
 	/* on AD1985 rev. 3, AC'97 revision bits are zero */
 	ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
 	return 0;
 }
 
+static int snd_ac97_ad1986_bool_info(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned short val;
+
+	val = ac97->regs[AC97_AD_MISC3];
+	ucontrol->value.integer.value[0] = (val & AC97_AD1986_LOSEL) != 0;
+	return 0;
+}
+
+static int snd_ac97_ad1986_lososel_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+	int ret0;
+	int ret1;
+	int sprd = (ac97->regs[AC97_AD_MISC] & AC97_AD1986_SPRD) != 0;
+
+	ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC3, AC97_AD1986_LOSEL,
+					ucontrol->value.integer.value[0] != 0
+				    ? AC97_AD1986_LOSEL : 0);
+	if (ret0 < 0)
+		return ret0;
+
+	/* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
+	ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
+				    (ucontrol->value.integer.value[0] != 0
+				     || sprd)
+				    ? AC97_AD1986_SOSEL : 0);
+	if (ret1 < 0)
+		return ret1;
+
+	return (ret0 > 0 || ret1 > 0) ? 1 : 0;
+}
+
+static int snd_ac97_ad1986_spread_get(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned short val;
+
+	val = ac97->regs[AC97_AD_MISC];
+	ucontrol->value.integer.value[0] = (val & AC97_AD1986_SPRD) != 0;
+	return 0;
+}
+
+static int snd_ac97_ad1986_spread_put(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+	int ret0;
+	int ret1;
+	int sprd = (ac97->regs[AC97_AD_MISC3] & AC97_AD1986_LOSEL) != 0;
+
+	ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SPRD,
+					ucontrol->value.integer.value[0] != 0
+				    ? AC97_AD1986_SPRD : 0);
+	if (ret0 < 0)
+		return ret0;
+
+	/* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
+	ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
+				    (ucontrol->value.integer.value[0] != 0
+				     || sprd)
+				    ? AC97_AD1986_SOSEL : 0);
+	if (ret1 < 0)
+		return ret1;
+
+	return (ret0 > 0 || ret1 > 0) ? 1 : 0;
+}
+
+static int snd_ac97_ad1986_miclisel_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = ac97->spec.ad18xx.swap_mic_linein;
+	return 0;
+}
+
+static int snd_ac97_ad1986_miclisel_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned char swap = ucontrol->value.integer.value[0] != 0;
+
+	if (swap != ac97->spec.ad18xx.swap_mic_linein) {
+		ac97->spec.ad18xx.swap_mic_linein = swap;
+		if (ac97->build_ops->update_jacks)
+			ac97->build_ops->update_jacks(ac97);
+		return 1;
+	}
+	return 0;
+}
+
+static int snd_ac97_ad1986_vrefout_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	/* Use MIC_1/2 V_REFOUT as the "get" value */
+	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned short val;
+	unsigned short reg = ac97->regs[AC97_AD_MISC2];
+	if ((reg & AC97_AD1986_MVREF0) != 0)
+		val = 2;
+	else if ((reg & AC97_AD1986_MVREF1) != 0)
+		val = 3;
+	else if ((reg & AC97_AD1986_MVREF2) != 0)
+		val = 1;
+	else
+		val = 0;
+	ucontrol->value.enumerated.item[0] = val;
+	return 0;
+}
+
+static int snd_ac97_ad1986_vrefout_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned short cval;
+	unsigned short lval;
+	unsigned short mval;
+	int cret;
+	int lret;
+	int mret;
+
+	switch (ucontrol->value.enumerated.item[0])
+	{
+	case 0: /* High-Z */
+		cval = 0;
+		lval = 0;
+		mval = 0;
+		break;
+	case 1: /* 3.7 V */
+		cval = AC97_AD1986_CVREF2;
+		lval = AC97_AD1986_LVREF2;
+		mval = AC97_AD1986_MVREF2;
+		break;
+	case 2: /* 2.25 V */
+		cval = AC97_AD1986_CVREF0;
+		lval = AC97_AD1986_LVREF0;
+		mval = AC97_AD1986_MVREF0;
+		break;
+	case 3: /* 0 V */
+		cval = AC97_AD1986_CVREF1;
+		lval = AC97_AD1986_LVREF1;
+		mval = AC97_AD1986_MVREF1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
+				    AC97_AD1986_CVREF_MASK, cval);
+	if (cret < 0)
+		return cret;
+	lret = snd_ac97_update_bits(ac97, AC97_AD_MISC3,
+				    AC97_AD1986_LVREF_MASK, lval);
+	if (lret < 0)
+		return lret;
+	mret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
+				    AC97_AD1986_MVREF_MASK, mval);
+	if (mret < 0)
+		return mret;
+
+	return (cret > 0 || lret > 0 || mret > 0) ? 1 : 0;
+}
+
+static const struct snd_kcontrol_new snd_ac97_ad1986_controls[] = {
+	AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Exchange Front/Surround",
+		.info = snd_ac97_ad1986_bool_info,
+		.get = snd_ac97_ad1986_lososel_get,
+		.put = snd_ac97_ad1986_lososel_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Exchange Mic/Line In",
+		.info = snd_ac97_ad1986_bool_info,
+		.get = snd_ac97_ad1986_miclisel_get,
+		.put = snd_ac97_ad1986_miclisel_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Spread Front to Surround and Center/LFE",
+		.info = snd_ac97_ad1986_bool_info,
+		.get = snd_ac97_ad1986_spread_get,
+		.put = snd_ac97_ad1986_spread_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Downmix",
+		.info = snd_ac97_ad1888_downmix_info,
+		.get = snd_ac97_ad1888_downmix_get,
+		.put = snd_ac97_ad1888_downmix_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "V_REFOUT",
+		.info = snd_ac97_ad1985_vrefout_info,
+		.get = snd_ac97_ad1986_vrefout_get,
+		.put = snd_ac97_ad1986_vrefout_put
+	},
+	AC97_SURROUND_JACK_MODE_CTL,
+	AC97_CHANNEL_MODE_CTL,
+
+	AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
+	AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0)
+};
+
+static void ad1986_update_jacks(struct snd_ac97 *ac97)
+{
+	unsigned short misc_val = 0;
+	unsigned short ser_val;
+
+	/* disable SURROUND and CENTER/LFE if not surround mode */
+	if (! is_surround_on(ac97))
+		misc_val |= AC97_AD1986_SODIS;
+	if (! is_clfe_on(ac97))
+		misc_val |= AC97_AD1986_CLDIS;
+
+	/* select line input (default=LINE_IN, SURROUND or MIC_1/2) */
+	if (is_shared_linein(ac97))
+		misc_val |= AC97_AD1986_LISEL_SURR;
+	else if (ac97->spec.ad18xx.swap_mic_linein != 0)
+		misc_val |= AC97_AD1986_LISEL_MIC;
+	snd_ac97_update_bits(ac97, AC97_AD_MISC,
+			     AC97_AD1986_SODIS | AC97_AD1986_CLDIS |
+			     AC97_AD1986_LISEL_MASK,
+			     misc_val);
+
+	/* select microphone input (MIC_1/2, Center/LFE or LINE_IN) */
+	if (is_shared_micin(ac97))
+		ser_val = AC97_AD1986_OMS_C;
+	else if (ac97->spec.ad18xx.swap_mic_linein != 0)
+		ser_val = AC97_AD1986_OMS_L;
+	else
+		ser_val = AC97_AD1986_OMS_M;
+	snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG,
+			     AC97_AD1986_OMS_MASK,
+			     ser_val);
+}
+
+static int patch_ad1986_specific(struct snd_ac97 *ac97)
+{
+	int err;
+
+	if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
+		return err;
+
+	return patch_build_controls(ac97, snd_ac97_ad1986_controls,
+				    ARRAY_SIZE(snd_ac97_ad1985_controls));
+}
+
+static struct snd_ac97_build_ops patch_ad1986_build_ops = {
+	.build_post_spdif = patch_ad198x_post_spdif,
+	.build_specific = patch_ad1986_specific,
+#ifdef CONFIG_PM
+	.resume = ad18xx_resume,
+#endif
+	.update_jacks = ad1986_update_jacks,
+};
+
+int patch_ad1986(struct snd_ac97 * ac97)
+{
+	patch_ad1881(ac97);
+	ac97->build_ops = &patch_ad1986_build_ops;
+	ac97->flags |= AC97_STEREO_MUTES;
+
+	/* update current jack configuration */
+	ad1986_update_jacks(ac97);
+
+	return 0;
+}
+
+
 /*
  * realtek ALC65x/850 codecs
  */
@@ -2014,12 +2483,12 @@
 {
 	int shared;
 	
-	/* shared Line-In */
-	shared = is_shared_linein(ac97);
+	/* shared Line-In / Surround Out */
+	shared = is_shared_surrout(ac97);
 	snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
 			     shared ? (1 << 9) : 0);
-	/* update shared Mic */
-	shared = is_shared_micin(ac97);
+	/* update shared Mic In / Center/LFE Out */
+	shared = is_shared_clfeout(ac97);
 	/* disable/enable vref */
 	snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
 			     shared ? (1 << 12) : 0);
@@ -2064,7 +2533,7 @@
 	/* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
 };
 
-static DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
 
 static int patch_alc650_specific(struct snd_ac97 * ac97)
 {
@@ -2149,12 +2618,12 @@
 {
 	int shared;
 	
-	/* shared Line-In */
-	shared = is_shared_linein(ac97);
+	/* shared Line-In / Surround Out */
+	shared = is_shared_surrout(ac97);
 	ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
 			      shared ? (1 << 9) : 0, 0);
-	/* update shared mic */
-	shared = is_shared_micin(ac97);
+	/* update shared Mic In / Center/LFE Out */
+	shared = is_shared_clfeout(ac97);
 	/* misc control; vrefout disable */
 	snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
 			     shared ? (1 << 12) : 0);
@@ -2264,7 +2733,8 @@
 		if (ac97->subsystem_vendor == 0x1462 &&
 		    (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */
 		     ac97->subsystem_device == 0x0161 || /* LG K1 Express */
-		     ac97->subsystem_device == 0x0351))  /* MSI L725 laptop */
+		     ac97->subsystem_device == 0x0351 || /* MSI L725 laptop */
+		     ac97->subsystem_device == 0x0061))  /* MSI S250 laptop */
 			val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
 		else
 			val |= (1 << 1); /* Pin 47 is spdif input pin */
@@ -2297,16 +2767,16 @@
 {
 	int shared;
 	
-	/* shared Line-In */
-	shared = is_shared_linein(ac97);
+	/* shared Line-In / Surround Out */
+	shared = is_shared_surrout(ac97);
 	/* SURR 1kOhm (bit4), Amp (bit5) */
 	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
 			     shared ? (1<<5) : (1<<4));
 	/* LINE-IN = 0, SURROUND = 2 */
 	snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
 			     shared ? (2<<12) : (0<<12));
-	/* update shared mic */
-	shared = is_shared_micin(ac97);
+	/* update shared Mic In / Center/LFE Out */
+	shared = is_shared_clfeout(ac97);
 	/* Vref disable (bit12), 1kOhm (bit13) */
 	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
 			     shared ? (1<<12) : (1<<13));
@@ -2379,9 +2849,9 @@
  */
 static void cm9738_update_jacks(struct snd_ac97 *ac97)
 {
-	/* shared Line-In */
+	/* shared Line-In / Surround Out */
 	snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
-			     is_shared_linein(ac97) ? (1 << 10) : 0);
+			     is_shared_surrout(ac97) ? (1 << 10) : 0);
 }
 
 static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = {
@@ -2463,12 +2933,12 @@
 
 static void cm9739_update_jacks(struct snd_ac97 *ac97)
 {
-	/* shared Line-In */
+	/* shared Line-In / Surround Out */
 	snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
-			     is_shared_linein(ac97) ? (1 << 10) : 0);
-	/* shared Mic */
+			     is_shared_surrout(ac97) ? (1 << 10) : 0);
+	/* shared Mic In / Center/LFE Out **/
 	snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
-			     is_shared_micin(ac97) ? 0x1000 : 0x2000);
+			     is_shared_clfeout(ac97) ? 0x1000 : 0x2000);
 }
 
 static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = {
@@ -2580,8 +3050,8 @@
 
 	val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)];
 	val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)];
-	val |= surr_shared[ac97->spec.dev_flags][is_shared_linein(ac97)];
-	val |= clfe_shared[ac97->spec.dev_flags][is_shared_micin(ac97)];
+	val |= surr_shared[ac97->spec.dev_flags][is_shared_surrout(ac97)];
+	val |= clfe_shared[ac97->spec.dev_flags][is_shared_clfeout(ac97)];
 
 	snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
 }
@@ -2821,6 +3291,7 @@
 	snd_ac97_write_cache(ac97, 0x5c, 0x20);
 	ac97->ext_id |= AC97_EI_SPDIF;	/* force the detection of spdif */
 	ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
+	ac97->build_ops = &patch_vt1616_ops;
 	return 0;
 }
 
@@ -2828,12 +3299,12 @@
  */
 static void it2646_update_jacks(struct snd_ac97 *ac97)
 {
-	/* shared Line-In */
+	/* shared Line-In / Surround Out */
 	snd_ac97_update_bits(ac97, 0x76, 1 << 9,
-			     is_shared_linein(ac97) ? (1<<9) : 0);
-	/* shared Mic */
+			     is_shared_surrout(ac97) ? (1<<9) : 0);
+	/* shared Mic / Center/LFE Out */
 	snd_ac97_update_bits(ac97, 0x76, 1 << 10,
-			     is_shared_micin(ac97) ? (1<<10) : 0);
+			     is_shared_clfeout(ac97) ? (1<<10) : 0);
 }
 
 static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = {
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index 7419792..555d1c9 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -39,6 +39,7 @@
 int patch_cirrus_cs4299(struct snd_ac97 * ac97);
 int patch_cirrus_spdif(struct snd_ac97 * ac97);
 int patch_conexant(struct snd_ac97 * ac97);
+int patch_cx20551(struct snd_ac97 * ac97);
 int patch_ad1819(struct snd_ac97 * ac97);
 int patch_ad1881(struct snd_ac97 * ac97);
 int patch_ad1885(struct snd_ac97 * ac97);
@@ -48,6 +49,7 @@
 int patch_ad1981a(struct snd_ac97 * ac97);
 int patch_ad1981b(struct snd_ac97 * ac97);
 int patch_ad1985(struct snd_ac97 * ac97);
+int patch_ad1986(struct snd_ac97 * ac97);
 int patch_alc650(struct snd_ac97 * ac97);
 int patch_alc655(struct snd_ac97 * ac97);
 int patch_alc850(struct snd_ac97 * ac97);
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
index c153cb7..dc26820 100644
--- a/sound/pci/ac97/ak4531_codec.c
+++ b/sound/pci/ac97/ak4531_codec.c
@@ -267,9 +267,9 @@
 	return change;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
 
 static struct snd_kcontrol_new snd_ak4531_controls[] = {
 
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 9f406fb..8afcb98 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -444,7 +444,7 @@
 }
 
 static int snd_als300_pcm_hw_params(struct snd_pcm_substream *substream,
-					snd_pcm_hw_params_t * hw_params)
+				    struct snd_pcm_hw_params *hw_params)
 {
 	return snd_pcm_lib_malloc_pages(substream,
 					params_buffer_bytes(hw_params));
@@ -673,7 +673,7 @@
 	snd_als300_dbgcallleave();
 }
 
-static int __devinit snd_als300_create(snd_card_t *card,
+static int __devinit snd_als300_create(struct snd_card *card,
 				       struct pci_dev *pci, int chip_type,
 				       struct snd_als300 **rchip)
 {
@@ -681,7 +681,7 @@
 	void *irq_handler;
 	int err;
 
-	static snd_device_ops_t ops = {
+	static struct snd_device_ops ops = {
 		.dev_free = snd_als300_dev_free,
 	};
 	*rchip = NULL;
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 476c343..7d8053b 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -45,6 +45,7 @@
 static int ac97_clock = 48000;
 static char *ac97_quirk;
 static int spdif_aclink = 1;
+static int ac97_codec = -1;
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for ATI IXP controller.");
@@ -54,6 +55,8 @@
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
 module_param(ac97_quirk, charp, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
+module_param(ac97_codec, int, 0444);
+MODULE_PARM_DESC(ac97_codec, "Specify codec instead of probing.");
 module_param(spdif_aclink, bool, 0444);
 MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
 
@@ -293,6 +296,10 @@
 
 MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
 
+static struct snd_pci_quirk atiixp_quirks[] __devinitdata = {
+	SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0),
+	{ } /* terminator */
+};
 
 /*
  * lowlevel functions
@@ -553,11 +560,33 @@
 	     ATI_REG_ISR_CODEC2_NOT_READY)
 #define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME)
 
+static int ac97_probing_bugs(struct pci_dev *pci)
+{
+	const struct snd_pci_quirk *q;
+
+	q = snd_pci_quirk_lookup(pci, atiixp_quirks);
+	if (q) {
+		snd_printdd(KERN_INFO "Atiixp quirk for %s.  "
+			    "Forcing codec %d\n", q->name, q->value);
+		return q->value;
+	}
+	/* this hardware doesn't need workarounds.  Probe for codec */
+	return -1;
+}
+
 static int snd_atiixp_codec_detect(struct atiixp *chip)
 {
 	int timeout;
 
 	chip->codec_not_ready_bits = 0;
+	if (ac97_codec == -1)
+		ac97_codec = ac97_probing_bugs(chip->pci);
+	if (ac97_codec >= 0) {
+		chip->codec_not_ready_bits |= 
+			CODEC_CHECK_BITS ^ (1 << (ac97_codec + 10));
+		return 0;
+	}
+
 	atiixp_write(chip, IER, CODEC_CHECK_BITS);
 	/* wait for the interrupts */
 	timeout = 50;
@@ -1396,7 +1425,7 @@
 		ac97.private_data = chip;
 		ac97.pci = chip->pci;
 		ac97.num = i;
-		ac97.scaps = AC97_SCAP_SKIP_MODEM;
+		ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;
 		if (! chip->spdif_over_aclink)
 			ac97.scaps |= AC97_SCAP_NO_SPDIF;
 		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index cc2e6b9..904023f 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1090,7 +1090,7 @@
 		ac97.private_data = chip;
 		ac97.pci = chip->pci;
 		ac97.num = i;
-		ac97.scaps = AC97_SCAP_SKIP_AUDIO;
+		ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
 		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
 			chip->ac97[i] = NULL; /* to be sure */
 			snd_printdd("atiixp-modem: codec %d not available for modem\n", i);
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index c3f3da2..e9b029e 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -804,6 +804,7 @@
 	{0x1822, 0x0001}, /* Twinhan VisionPlus DVB-T */
 	{0x18ac, 0xd500}, /* DVICO FusionHDTV 5 Lite */
 	{0x18ac, 0xdb10}, /* DVICO FusionHDTV DVB-T Lite */
+	{0x18ac, 0xdb11}, /* Ultraview DVB-T Lite */
 	{0x270f, 0xfc00}, /* Chaintech Digitop DST-1000 DVB-S */
 	{0x7063, 0x2000}, /* pcHDTV HD-2000 TV */
 };
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index f61f052..ea6712b 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1382,7 +1382,6 @@
 	snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
 	snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
 	chip->spdif_enable = 0; /* Set digital SPDIF output off */
-	chip->capture_source = 3; /* Set CAPTURE_SOURCE */
 	//snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
 	//snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
 
@@ -1402,8 +1401,22 @@
 		snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
 		snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
 	}
-        snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
-	chip->capture_source = 3; /* Set CAPTURE_SOURCE */
+	if (chip->details->i2c_adc == 1) {
+	        /* Select MIC, Line in, TAD in, AUX in */
+	        snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
+		/* Default to CAPTURE_SOURCE to i2s in */
+		chip->capture_source = 3;
+	} else if (chip->details->ac97 == 1) {
+	        /* Default to AC97 in */
+	        snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4);
+		/* Default to CAPTURE_SOURCE to AC97 in */
+		chip->capture_source = 4;
+	} else {
+	        /* Select MIC, Line in, TAD in, AUX in */
+	        snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
+		/* Default to Set CAPTURE_SOURCE to i2s in */
+		chip->capture_source = 3;
+	}
 
         if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
 		/* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
@@ -1605,6 +1618,8 @@
 	snd_ca0106_proc_init(chip);
 #endif
 
+	snd_card_set_dev(card, &pci->dev);
+
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
 		return err;
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 9855f52..b913a1f 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -74,8 +74,8 @@
 
 #include "ca0106.h"
 
-static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
-static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
+static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
+static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
 
 static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_info *uinfo)
@@ -482,19 +482,6 @@
 	.private_value = ((chid) << 8) | (reg)			\
 }
 
-#define I2C_VOLUME(xname,chid) \
-{								\
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
-	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |		\
-	          SNDRV_CTL_ELEM_ACCESS_TLV_READ,		\
-	.info =  snd_ca0106_i2c_volume_info,			\
-	.get =   snd_ca0106_i2c_volume_get,			\
-	.put =   snd_ca0106_i2c_volume_put,			\
-	.tlv = { .p = snd_ca0106_db_scale2 },			\
-	.private_value = chid					\
-}
-
-
 static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
 	CA_VOLUME("Analog Front Playback Volume",
 		  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
@@ -517,11 +504,6 @@
         CA_VOLUME("CAPTURE feedback Playback Volume",
 		  1, CAPTURE_CONTROL),
 
-        I2C_VOLUME("Phone Capture Volume", 0),
-        I2C_VOLUME("Mic Capture Volume", 1),
-        I2C_VOLUME("Line in Capture Volume", 2),
-        I2C_VOLUME("Aux Capture Volume", 3),
-
 	{
 		.access =	SNDRV_CTL_ELEM_ACCESS_READ,
 		.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -539,14 +521,14 @@
 	},
 	{
 		.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name =		"Digital Capture Source",
+		.name =		"Digital Source Capture Enum",
 		.info =		snd_ca0106_capture_source_info,
 		.get =		snd_ca0106_capture_source_get,
 		.put =		snd_ca0106_capture_source_put
 	},
 	{
 		.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name =		"Capture Source",
+		.name =		"Analog Source Capture Enum",
 		.info =		snd_ca0106_i2c_capture_source_info,
 		.get =		snd_ca0106_i2c_capture_source_get,
 		.put =		snd_ca0106_i2c_capture_source_put
@@ -561,6 +543,25 @@
 	},
 };
 
+#define I2C_VOLUME(xname,chid) \
+{								\
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |		\
+	          SNDRV_CTL_ELEM_ACCESS_TLV_READ,		\
+	.info =  snd_ca0106_i2c_volume_info,			\
+	.get =   snd_ca0106_i2c_volume_get,			\
+	.put =   snd_ca0106_i2c_volume_put,			\
+	.tlv = { .p = snd_ca0106_db_scale2 },			\
+	.private_value = chid					\
+}
+
+static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = {
+        I2C_VOLUME("Phone Capture Volume", 0),
+        I2C_VOLUME("Mic Capture Volume", 1),
+        I2C_VOLUME("Line in Capture Volume", 2),
+        I2C_VOLUME("Aux Capture Volume", 3),
+};
+
 static int __devinit remove_ctl(struct snd_card *card, const char *name)
 {
 	struct snd_ctl_elem_id id;
@@ -645,6 +646,11 @@
 			return err;
 	}
 	if (emu->details->i2c_adc == 1) {
+		for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_i2c_adc_ctls); i++) {
+			err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_i2c_adc_ctls[i], emu));
+			if (err < 0)
+				return err;
+		}
 		if (emu->details->gpio_type == 1)
 			err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
 		else  /* gpio_type == 2 */
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 8e5519d..44cf546 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1055,7 +1055,7 @@
 	return change;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_dsp, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -4650, 150, 0);
 
 static struct snd_kcontrol_new snd_cs4281_fm_vol = 
 {
diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c
index b7108e2..8e7fe03 100644
--- a/sound/pci/echoaudio/darla20.c
+++ b/sound/pci/echoaudio/darla20.c
@@ -47,6 +47,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c
index e59a982..a13c623 100644
--- a/sound/pci/echoaudio/darla24.c
+++ b/sound/pci/echoaudio/darla24.c
@@ -51,6 +51,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c
index 12099fe..8fb1582 100644
--- a/sound/pci/echoaudio/echo3g.c
+++ b/sound/pci/echoaudio/echo3g.c
@@ -58,6 +58,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/echo3g_dsp.c b/sound/pci/echoaudio/echo3g_dsp.c
index d26a1d1..48eb7c5 100644
--- a/sound/pci/echoaudio/echo3g_dsp.c
+++ b/sound/pci/echoaudio/echo3g_dsp.c
@@ -39,7 +39,7 @@
 static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq,
 			     char force);
 
-#include <linux/irq.h>
+#include <linux/interrupt.h>
 
 static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
 {
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 047e0b5..6a428b8 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -34,6 +34,7 @@
 MODULE_PARM_DESC(enable, "Enable " ECHOCARD_NAME " soundcard.");
 
 static unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999};
+static const DECLARE_TLV_DB_SCALE(db_scale_output_gain, -12800, 100, 1);
 
 static int get_firmware(const struct firmware **fw_entry,
 			const struct firmware *frm, struct echoaudio *chip)
@@ -1011,17 +1012,21 @@
 static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
 	.name = "Line Playback Volume",
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
 	.info = snd_echo_output_gain_info,
 	.get = snd_echo_output_gain_get,
 	.put = snd_echo_output_gain_put,
+	.tlv = {.p = db_scale_output_gain},
 };
 #else
 static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = {
 	.name = "PCM Playback Volume",
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
 	.info = snd_echo_output_gain_info,
 	.get = snd_echo_output_gain_get,
 	.put = snd_echo_output_gain_put,
+	.tlv = {.p = db_scale_output_gain},
 };
 #endif
 
@@ -1080,12 +1085,16 @@
 	return changed;
 }
 
+static const DECLARE_TLV_DB_SCALE(db_scale_input_gain, -2500, 50, 0);
+
 static struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = {
 	.name = "Line Capture Volume",
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
 	.info = snd_echo_input_gain_info,
 	.get = snd_echo_input_gain_get,
 	.put = snd_echo_input_gain_put,
+	.tlv = {.p = db_scale_input_gain},
 };
 
 #endif /* ECHOCARD_HAS_INPUT_GAIN */
@@ -1277,9 +1286,11 @@
 static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = {
 	.name = "Monitor Mixer Volume",
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
 	.info = snd_echo_mixer_info,
 	.get = snd_echo_mixer_get,
 	.put = snd_echo_mixer_put,
+	.tlv = {.p = db_scale_output_gain},
 };
 
 #endif /* ECHOCARD_HAS_MONITOR */
@@ -1343,9 +1354,11 @@
 static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = {
 	.name = "VMixer Volume",
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
 	.info = snd_echo_vmixer_info,
 	.get = snd_echo_vmixer_get,
 	.put = snd_echo_vmixer_put,
+	.tlv = {.p = db_scale_output_gain},
 };
 
 #endif /* ECHOCARD_HAS_VMIXER */
@@ -1753,9 +1766,12 @@
 static struct snd_kcontrol_new snd_echo_vumeters __devinitdata = {
 	.name = "VU-meters",
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.access = SNDRV_CTL_ELEM_ACCESS_READ |
+		  SNDRV_CTL_ELEM_ACCESS_VOLATILE |
+		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
 	.info = snd_echo_vumeters_info,
 	.get = snd_echo_vumeters_get,
+	.tlv = {.p = db_scale_output_gain},
 };
 
 
diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c
index 29d6d12..af4d320 100644
--- a/sound/pci/echoaudio/gina20.c
+++ b/sound/pci/echoaudio/gina20.c
@@ -51,6 +51,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c
index e464d72..9ff454a 100644
--- a/sound/pci/echoaudio/gina24.c
+++ b/sound/pci/echoaudio/gina24.c
@@ -57,6 +57,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c
index bfd2467..37eb726 100644
--- a/sound/pci/echoaudio/indigo.c
+++ b/sound/pci/echoaudio/indigo.c
@@ -49,6 +49,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c
index 8ed7ff1..dc8b918 100644
--- a/sound/pci/echoaudio/indigodj.c
+++ b/sound/pci/echoaudio/indigodj.c
@@ -49,6 +49,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c
index a8788e9..eadf326 100644
--- a/sound/pci/echoaudio/indigoio.c
+++ b/sound/pci/echoaudio/indigoio.c
@@ -50,6 +50,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c
index e503d74..6cede49 100644
--- a/sound/pci/echoaudio/layla20.c
+++ b/sound/pci/echoaudio/layla20.c
@@ -56,6 +56,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c
index d4581fd..44f7354 100644
--- a/sound/pci/echoaudio/layla24.c
+++ b/sound/pci/echoaudio/layla24.c
@@ -58,6 +58,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c
index be40c64..dc172d0 100644
--- a/sound/pci/echoaudio/mia.c
+++ b/sound/pci/echoaudio/mia.c
@@ -56,6 +56,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c
index 5dc512a..c856ed5 100644
--- a/sound/pci/echoaudio/mona.c
+++ b/sound/pci/echoaudio/mona.c
@@ -55,6 +55,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 972ec40..80aa585 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -3,8 +3,10 @@
  *                   Creative Labs, Inc.
  *  Routines for control of EMU10K1 chips
  *
- *  Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
  *      Added support for Audigy 2 Value.
+ *  	Added EMU 1010 support.
+ *  	General bug fixes and enhancements.
  *
  *
  *  BUGS:
@@ -41,8 +43,10 @@
 
 #include <sound/core.h>
 #include <sound/emu10k1.h>
+#include <linux/firmware.h>
 #include "p16v.h"
 #include "tina2.h"
+#include "p17v.h"
 
 
 /*************************************************************************
@@ -117,11 +121,28 @@
 		0x0622,
 		0x1400,
 };
+
+static unsigned int i2c_adc_init[][2] = {
+	{ 0x17, 0x00 }, /* Reset */
+	{ 0x07, 0x00 }, /* Timeout */
+	{ 0x0b, 0x22 },  /* Interface control */
+	{ 0x0c, 0x22 },  /* Master mode control */
+	{ 0x0d, 0x08 },  /* Powerdown control */
+	{ 0x0e, 0xcf },  /* Attenuation Left  0x01 = -103dB, 0xff = 24dB */
+	{ 0x0f, 0xcf },  /* Attenuation Right 0.5dB steps */
+	{ 0x10, 0x7b },  /* ALC Control 1 */
+	{ 0x11, 0x00 },  /* ALC Control 2 */
+	{ 0x12, 0x32 },  /* ALC Control 3 */
+	{ 0x13, 0x00 },  /* Noise gate control */
+	{ 0x14, 0xa6 },  /* Limiter control */
+	{ 0x15, ADC_MUX_2 },  /* ADC Mixer control. Mic for Audigy 2 ZS Notebook */
+};
 	
 static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
 {
 	unsigned int silent_page;
 	int ch;
+	u32 tmp;
 
 	/* disable audio and lock cache */
 	outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
@@ -160,8 +181,6 @@
 
 	if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
 		/* Hacks for Alice3 to work independent of haP16V driver */
-		u32 tmp;
-
 		//Setup SRCMulti_I2S SamplingRate
 		tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
 		tmp &= 0xfffff1ff;
@@ -181,8 +200,6 @@
 	}
 	if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */
 		/* Hacks for Alice3 to work independent of haP16V driver */
-		u32 tmp;
-
 		snd_printk(KERN_INFO "Audigy2 value: Special config.\n");
 		//Setup SRCMulti_I2S SamplingRate
 		tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
@@ -211,7 +228,7 @@
 		int size, n;
 
 		size = ARRAY_SIZE(spi_dac_init);
-		for (n=0; n < size; n++)
+		for (n = 0; n < size; n++)
 			snd_emu10k1_spi_write(emu, spi_dac_init[n]);
 
 		snd_emu10k1_ptr20_write(emu, 0x60, 0, 0x10);
@@ -228,6 +245,23 @@
 		outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */
 
 	}
+	if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */
+		int size, n;
+
+		snd_emu10k1_ptr20_write(emu, P17V_I2S_SRC_SEL, 0, 0x2020205f);
+		tmp = inl(emu->port + A_IOCFG);
+		outl(tmp | 0x4, emu->port + A_IOCFG);  /* Set bit 2 for mic input */
+		tmp = inl(emu->port + A_IOCFG);
+		size = ARRAY_SIZE(i2c_adc_init);
+		for (n = 0; n < size; n++)
+			snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]);
+		for (n=0; n < 4; n++) {
+			emu->i2c_capture_volume[n][0]= 0xcf;
+			emu->i2c_capture_volume[n][1]= 0xcf;
+		}
+
+	}
+
 	
 	snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr);
 	snd_emu10k1_ptr_write(emu, TCB, 0, 0);	/* taken from original driver */
@@ -239,6 +273,10 @@
 		snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page);
 	}
 
+	if (emu->card_capabilities->emu1010) {
+		outl(HCFG_AUTOMUTE_ASYNC |
+			HCFG_EMU32_SLAVE |
+			HCFG_AUDIOENABLE, emu->port + HCFG);
 	/*
 	 *  Hokay, setup HCFG
 	 *   Mute Disable Audio = 0
@@ -246,7 +284,7 @@
 	 *   Lock Sound Memory = 0
 	 *   Auto Mute = 1
 	 */
-	if (emu->audigy) {
+	} else if (emu->audigy) {
 		if (emu->revision == 4) /* audigy2 */
 			outl(HCFG_AUDIOENABLE |
 			     HCFG_AC3ENABLE_CDSPDIF |
@@ -265,8 +303,10 @@
 		outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
 
 	if (enable_ir) {	/* enable IR for SB Live */
-		if ( emu->card_capabilities->emu1212m) {
-			;  /* Disable all access to A_IOCFG for the emu1212m */
+		if (emu->card_capabilities->emu1010) {
+			;  /* Disable all access to A_IOCFG for the emu1010 */
+		} else if (emu->card_capabilities->i2c_adc) {
+			;  /* Disable A_IOCFG for Audigy 2 ZS Notebook */
 		} else if (emu->audigy) {
 			unsigned int reg = inl(emu->port + A_IOCFG);
 			outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
@@ -284,8 +324,10 @@
  		}
 	}
 	
-	if ( emu->card_capabilities->emu1212m) {
-		;  /* Disable all access to A_IOCFG for the emu1212m */
+	if (emu->card_capabilities->emu1010) {
+		;  /* Disable all access to A_IOCFG for the emu1010 */
+	} else if (emu->card_capabilities->i2c_adc) {
+		;  /* Disable A_IOCFG for Audigy 2 ZS Notebook */
 	} else if (emu->audigy) {	/* enable analog output */
 		unsigned int reg = inl(emu->port + A_IOCFG);
 		outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
@@ -302,8 +344,10 @@
 	outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG);
 
 	/* Enable analog/digital outs on audigy */
-	if ( emu->card_capabilities->emu1212m) {
-		;  /* Disable all access to A_IOCFG for the emu1212m */
+	if (emu->card_capabilities->emu1010) {
+		;  /* Disable all access to A_IOCFG for the emu1010 */
+	} else if (emu->card_capabilities->i2c_adc) {
+		;  /* Disable A_IOCFG for Audigy 2 ZS Notebook */
 	} else if (emu->audigy) {
 		outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
  
@@ -596,133 +640,423 @@
 	return 0;
 }
 
-static int snd_emu1212m_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
+static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * filename)
 {
-	if (reg<0 || reg>0x3f)
-		return 1;
-	reg+=0x40; /* 0x40 upwards are registers. */
-	if (value<0 || value>0x3f) /* 0 to 0x3f are values */
-		return 1;
-	outl(reg, emu->port + A_IOCFG);
-	outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
-	outl(value, emu->port + A_IOCFG);
-	outl(value | 0x80 , emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
+	int err;
+	int n, i;
+	int reg;
+	int value;
+	const struct firmware *fw_entry;
 
+	if ((err = request_firmware(&fw_entry, filename, &emu->pci->dev)) != 0) {
+		snd_printk(KERN_ERR "firmware: %s not found. Err=%d\n",filename, err);
+		return err;
+	}
+	snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size);
+	if (fw_entry->size != 0x133a4) {
+		snd_printk(KERN_ERR "firmware: %s wrong size.\n",filename);
+		return -EINVAL;
+	}
+
+	/* The FPGA is a Xilinx Spartan IIE XC2S50E */
+	/* GPIO7 -> FPGA PGMN
+	 * GPIO6 -> FPGA CCLK
+	 * GPIO5 -> FPGA DIN
+	 * FPGA CONFIG OFF -> FPGA PGMN
+	 */
+	outl(0x00, emu->port + A_IOCFG); /* Set PGMN low for 1uS. */
+	udelay(1);
+	outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */
+	udelay(100); /* Allow FPGA memory to clean */
+	for(n = 0; n < fw_entry->size; n++) {
+		value=fw_entry->data[n];	
+		for(i = 0; i < 8; i++) {
+			reg = 0x80;
+			if (value & 0x1)
+				reg = reg | 0x20;
+			value = value >> 1;   
+			outl(reg, emu->port + A_IOCFG);
+			outl(reg | 0x40, emu->port + A_IOCFG);
+		}
+	}
+	/* After programming, set GPIO bit 4 high again. */
+	outl(0x10, emu->port + A_IOCFG);
+	
+
+        release_firmware(fw_entry);
 	return 0;
 }
 
-static int snd_emu1212m_fpga_read(struct snd_emu10k1 * emu, int reg, int *value)
-{
-	if (reg<0 || reg>0x3f)
-		return 1;
-	reg+=0x40; /* 0x40 upwards are registers. */
-	outl(reg, emu->port + A_IOCFG);
-	outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
-	*value = inl(emu->port + A_IOCFG);
-
-	return 0;
-}
-
-static int snd_emu1212m_fpga_netlist_write(struct snd_emu10k1 * emu, int reg, int value)
-{
-	snd_emu1212m_fpga_write(emu, 0x00, ((reg >> 8) & 0x3f) );
-	snd_emu1212m_fpga_write(emu, 0x01, (reg & 0x3f) );
-	snd_emu1212m_fpga_write(emu, 0x02, ((value >> 8) & 0x3f) );
-	snd_emu1212m_fpga_write(emu, 0x03, (value & 0x3f) );
-
-	return 0;
-}
-
-static int snd_emu10k1_emu1212m_init(struct snd_emu10k1 * emu)
+static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
 {
 	unsigned int i;
-	int tmp;
+	int tmp,tmp2;
+	int reg;
+	int err;
+	const char *hana_filename = "emu/hana.fw";
+	const char *dock_filename = "emu/audio_dock.fw";
 
-	snd_printk(KERN_ERR "emu1212m: Special config.\n");
+	snd_printk(KERN_INFO "emu1010: Special config.\n");
+	/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
+	 * Lock Sound Memory Cache, Lock Tank Memory Cache,
+	 * Mute all codecs.
+	 */
 	outl(0x0005a00c, emu->port + HCFG);
-	outl(0x0005a004, emu->port + HCFG);
+	/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
+	 * Lock Tank Memory Cache,
+	 * Mute all codecs.
+	 */
+	outl(0x0005a004, emu->port + HCFG); 
+	/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
+	 * Mute all codecs.
+	 */
 	outl(0x0005a000, emu->port + HCFG);
+	/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
+	 * Mute all codecs.
+	 */
 	outl(0x0005a000, emu->port + HCFG);
 
-	snd_emu1212m_fpga_read(emu, 0x22, &tmp );
-	snd_emu1212m_fpga_read(emu, 0x23, &tmp );
-	snd_emu1212m_fpga_read(emu, 0x24, &tmp );
-	snd_emu1212m_fpga_write(emu, 0x04, 0x01 );
-	snd_emu1212m_fpga_read(emu, 0x0b, &tmp );
-	snd_emu1212m_fpga_write(emu, 0x0b, 0x01 );
-	snd_emu1212m_fpga_read(emu, 0x10, &tmp );
-	snd_emu1212m_fpga_write(emu, 0x10, 0x00 );
-	snd_emu1212m_fpga_read(emu, 0x11, &tmp );
-	snd_emu1212m_fpga_write(emu, 0x11, 0x30 );
-	snd_emu1212m_fpga_read(emu, 0x13, &tmp );
-	snd_emu1212m_fpga_write(emu, 0x13, 0x0f );
-	snd_emu1212m_fpga_read(emu, 0x11, &tmp );
-	snd_emu1212m_fpga_write(emu, 0x11, 0x30 );
-	snd_emu1212m_fpga_read(emu, 0x0a, &tmp );
-	snd_emu1212m_fpga_write(emu, 0x0a, 0x10 );
-	snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
-	snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
-	snd_emu1212m_fpga_write(emu, 0x09, 0x0f );
-	snd_emu1212m_fpga_write(emu, 0x06, 0x00 );
-	snd_emu1212m_fpga_write(emu, 0x05, 0x00 );
-	snd_emu1212m_fpga_write(emu, 0x0e, 0x12 );
-	snd_emu1212m_fpga_netlist_write(emu, 0x0000, 0x0200);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0001, 0x0201);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0002, 0x0500);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0003, 0x0501);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0004, 0x0400);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0005, 0x0401);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0006, 0x0402);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0007, 0x0403);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0008, 0x0404);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0009, 0x0405);
-	snd_emu1212m_fpga_netlist_write(emu, 0x000a, 0x0406);
-	snd_emu1212m_fpga_netlist_write(emu, 0x000b, 0x0407);
-	snd_emu1212m_fpga_netlist_write(emu, 0x000c, 0x0100);
-	snd_emu1212m_fpga_netlist_write(emu, 0x000d, 0x0104);
-	snd_emu1212m_fpga_netlist_write(emu, 0x000e, 0x0200);
-	snd_emu1212m_fpga_netlist_write(emu, 0x000f, 0x0201);
-	for (i=0;i < 0x20;i++) {
-		snd_emu1212m_fpga_netlist_write(emu, 0x0100+i, 0x0000);
-	}
-	for (i=0;i < 4;i++) {
-		snd_emu1212m_fpga_netlist_write(emu, 0x0200+i, 0x0000);
-	}
-	for (i=0;i < 7;i++) {
-		snd_emu1212m_fpga_netlist_write(emu, 0x0300+i, 0x0000);
-	}
-	for (i=0;i < 7;i++) {
-		snd_emu1212m_fpga_netlist_write(emu, 0x0400+i, 0x0000);
-	}
-	snd_emu1212m_fpga_netlist_write(emu, 0x0500, 0x0108);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0501, 0x010c);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0600, 0x0110);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0601, 0x0114);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0700, 0x0118);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0701, 0x011c);
-	snd_emu1212m_fpga_write(emu, 0x07, 0x01 );
+	/* Disable 48Volt power to Audio Dock */
+	snd_emu1010_fpga_write(emu,  EMU_HANA_DOCK_PWR,  0 );
 
-	snd_emu1212m_fpga_read(emu, 0x21, &tmp );
+	/* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */
+	snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+	snd_printdd("reg1=0x%x\n",reg);
+	if (reg == 0x55) {
+		/* FPGA netlist already present so clear it */
+		/* Return to programming mode */
 
-	outl(0x0000a000, emu->port + HCFG);
+		snd_emu1010_fpga_write(emu,  EMU_HANA_FPGA_CONFIG, 0x02 );
+	}
+	snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+	snd_printdd("reg2=0x%x\n",reg);
+	if (reg == 0x55) {
+		/* FPGA failed to return to programming mode */
+		return -ENODEV;
+	}
+	snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg);
+	if ((err = snd_emu1010_load_firmware(emu, hana_filename)) != 0) {
+		snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", hana_filename);
+		return err;
+	}
+
+	/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
+	snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+	if (reg != 0x55) {
+		/* FPGA failed to be programmed */
+		snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg);
+		return -ENODEV;
+	}
+
+	snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n");
+	snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp );
+	snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2 );
+	snd_printk("Hana ver:%d.%d\n",tmp ,tmp2);
+	/* Enable 48Volt power to Audio Dock */
+	snd_emu1010_fpga_write(emu,  EMU_HANA_DOCK_PWR,  EMU_HANA_DOCK_PWR_ON );
+
+	snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
+	snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
+	snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
+	snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
+	snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp ); 
+	/* ADAT input. */
+	snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x01 );
+	snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp );
+	/* Set no attenuation on Audio Dock pads. */
+	snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 );
+	emu->emu1010.adc_pads = 0x00;
+	snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp );
+	/* Unmute Audio dock DACs, Headphone source DAC-4. */
+	snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 );
+	snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 );
+	snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp );
+	/* DAC PADs. */
+	snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f );
+	emu->emu1010.dac_pads = 0x0f;
+	snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp );
+	snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 );
+	snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp );
+	/* SPDIF Format. Set Consumer mode, 24bit, copy enable */
+	snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 );
+	/* MIDI routing */
+	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 );
+	/* Unknown. */
+	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c );
+	/* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); // IRQ Enable: All on */
+	/* IRQ Enable: All off */
+	snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00 );
+
+	snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
+	snd_printk(KERN_INFO "emu1010: Card options3=0x%x\n",reg);
+	/* Default WCLK set to 48kHz. */
+	snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00 );
+	/* Word Clock source, Internal 48kHz x1 */
+	snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K );
+	//snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X );
+	/* Audio Dock LEDs. */
+	snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 );
+
+#if 0
+	/* For 96kHz */
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_0, EMU_SRC_HAMOA_ADC_LEFT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_1, EMU_SRC_HAMOA_ADC_RIGHT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_4, EMU_SRC_HAMOA_ADC_LEFT2);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_5, EMU_SRC_HAMOA_ADC_RIGHT2);
+#endif
+#if 0
+	/* For 192kHz */
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_0, EMU_SRC_HAMOA_ADC_LEFT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_1, EMU_SRC_HAMOA_ADC_RIGHT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_2, EMU_SRC_HAMOA_ADC_LEFT2);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_3, EMU_SRC_HAMOA_ADC_RIGHT2);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_4, EMU_SRC_HAMOA_ADC_LEFT3);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_5, EMU_SRC_HAMOA_ADC_RIGHT3);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_6, EMU_SRC_HAMOA_ADC_LEFT4);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_7, EMU_SRC_HAMOA_ADC_RIGHT4);
+#endif
+#if 1
+	/* For 48kHz */
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_0, EMU_SRC_DOCK_MIC_A1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_1, EMU_SRC_DOCK_MIC_B1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_2, EMU_SRC_HAMOA_ADC_LEFT2);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_3, EMU_SRC_HAMOA_ADC_LEFT2);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_4, EMU_SRC_DOCK_ADC1_LEFT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_5, EMU_SRC_DOCK_ADC1_RIGHT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_6, EMU_SRC_DOCK_ADC2_LEFT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_7, EMU_SRC_DOCK_ADC2_RIGHT1);
+#endif
+#if 0
+	/* Original */
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_4, EMU_SRC_HANA_ADAT);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_5, EMU_SRC_HANA_ADAT + 1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_6, EMU_SRC_HANA_ADAT + 2);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_7, EMU_SRC_HANA_ADAT + 3);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_8, EMU_SRC_HANA_ADAT + 4);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_9, EMU_SRC_HANA_ADAT + 5);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_A, EMU_SRC_HANA_ADAT + 6);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_B, EMU_SRC_HANA_ADAT + 7);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_MIC_A1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_MIC_B1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_E, EMU_SRC_HAMOA_ADC_LEFT2);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE2_EMU32_F, EMU_SRC_HAMOA_ADC_LEFT2);
+#endif
+	for (i = 0;i < 0x20; i++ ) {
+		/* AudioDock Elink <-  Silence */
+		snd_emu1010_fpga_link_dst_src_write(emu, 0x0100+i, EMU_SRC_SILENCE);
+	}
+	for (i = 0;i < 4; i++) {
+		/* Hana SPDIF Out <- Silence */
+		snd_emu1010_fpga_link_dst_src_write(emu, 0x0200+i, EMU_SRC_SILENCE);
+	}
+	for (i = 0;i < 7; i++) {
+		/* Hamoa DAC <- Silence */
+		snd_emu1010_fpga_link_dst_src_write(emu, 0x0300+i, EMU_SRC_SILENCE);
+	}
+	for (i = 0;i < 7; i++) {
+		/* Hana ADAT Out <- Silence */
+		snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HANA_ADAT + i, EMU_SRC_SILENCE);
+	}
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE_I2S0_LEFT, EMU_SRC_DOCK_ADC1_LEFT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE_I2S0_RIGHT, EMU_SRC_DOCK_ADC1_RIGHT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE_I2S1_LEFT, EMU_SRC_DOCK_ADC2_LEFT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE_I2S1_RIGHT, EMU_SRC_DOCK_ADC2_RIGHT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE_I2S2_LEFT, EMU_SRC_DOCK_ADC3_LEFT1);
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1);
+	snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01 ); // Unmute all
+
+	snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp );
+	
+	/* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
+	 * Lock Sound Memory Cache, Lock Tank Memory Cache,
+	 * Mute all codecs.
+	 */
+	outl(0x0000a000, emu->port + HCFG); 
+	/* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
+	 * Lock Sound Memory Cache, Lock Tank Memory Cache,
+	 * Un-Mute all codecs.
+	 */
 	outl(0x0000a001, emu->port + HCFG);
+ 
 	/* Initial boot complete. Now patches */
 
-	snd_emu1212m_fpga_read(emu, 0x21, &tmp );
-	snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
-	snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
-	snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
-	snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
-	snd_emu1212m_fpga_read(emu, 0x0a, &tmp );
-	snd_emu1212m_fpga_write(emu, 0x0a, 0x10 );
+	snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp );
+	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */
+	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */
+	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */
+	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */
+	snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp ); 
+	snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif  (or 0x11 for aes/ebu) */
 
-	snd_emu1212m_fpga_read(emu, 0x20, &tmp );
-	snd_emu1212m_fpga_read(emu, 0x21, &tmp );
+	/* Delay to allow Audio Dock to settle */
+	msleep(100);
+	snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */
+	snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg ); /* OPTIONS: Which cards are attached to the EMU */
+	/* FIXME: The loading of this should be able to happen any time,
+	 * as the user can plug/unplug it at any time
+	 */
+	if (reg & (EMU_HANA_OPTION_DOCK_ONLINE | EMU_HANA_OPTION_DOCK_OFFLINE) ) {
+		/* Audio Dock attached */
+		/* Return to Audio Dock programming mode */
+		snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
+		snd_emu1010_fpga_write(emu,  EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK );
+		if ((err = snd_emu1010_load_firmware(emu, dock_filename)) != 0) {
+			return err;
+		}
+		snd_emu1010_fpga_write(emu,  EMU_HANA_FPGA_CONFIG, 0 );
+		snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg );
+		snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg);
+		/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
+		snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+		snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg);
+		if (reg != 0x55) {
+			/* FPGA failed to be programmed */
+			snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg);
+			return 0;
+			return -ENODEV;
+		}
+		snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n");
+		snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp );
+		snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 );
+		snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2);
+	}
+#if 0
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32B + 3); /* ALICE2 bus 0xa3 */
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 2); /* ALICE2 bus 0xb2 */
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); /* ALICE2 bus 0xb3 */
+#endif
+	/* Default outputs */
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+	emu->emu1010.output_source[0] = 21;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
+	emu->emu1010.output_source[1] = 22;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2);
+	emu->emu1010.output_source[2] = 23;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3);
+	emu->emu1010.output_source[3] = 24;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4);
+	emu->emu1010.output_source[4] = 25;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5);
+	emu->emu1010.output_source[5] = 26;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_DAC4_LEFT1, EMU_SRC_ALICE_EMU32A + 6);
+	emu->emu1010.output_source[6] = 27;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_DAC4_RIGHT1, EMU_SRC_ALICE_EMU32A + 7);
+	emu->emu1010.output_source[7] = 28;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_PHONES_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+	emu->emu1010.output_source[8] = 21;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_PHONES_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
+	emu->emu1010.output_source[9] = 22;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+	emu->emu1010.output_source[10] = 21;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_DOCK_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
+	emu->emu1010.output_source[11] = 22;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+	emu->emu1010.output_source[12] = 21;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
+	emu->emu1010.output_source[13] = 22;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+	emu->emu1010.output_source[14] = 21;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
+	emu->emu1010.output_source[15] = 22;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_ADAT, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
+	emu->emu1010.output_source[16] = 21;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_ADAT + 1, EMU_SRC_ALICE_EMU32A + 1);
+	emu->emu1010.output_source[17] = 22;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_ADAT + 2, EMU_SRC_ALICE_EMU32A + 2);
+	emu->emu1010.output_source[18] = 23;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_ADAT + 3, EMU_SRC_ALICE_EMU32A + 3);
+	emu->emu1010.output_source[19] = 24;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_ADAT + 4, EMU_SRC_ALICE_EMU32A + 4);
+	emu->emu1010.output_source[20] = 25;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_ADAT + 5, EMU_SRC_ALICE_EMU32A + 5);
+	emu->emu1010.output_source[21] = 26;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_ADAT + 6, EMU_SRC_ALICE_EMU32A + 6);
+	emu->emu1010.output_source[22] = 27;
+	snd_emu1010_fpga_link_dst_src_write(emu,
+		EMU_DST_HANA_ADAT + 7, EMU_SRC_ALICE_EMU32A + 7);
+	emu->emu1010.output_source[23] = 28;
 
-	snd_emu1212m_fpga_netlist_write(emu, 0x0300, 0x0312);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0301, 0x0313);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0200, 0x0302);
-	snd_emu1212m_fpga_netlist_write(emu, 0x0201, 0x0303);
+	/* TEMP: Select SPDIF in/out */
+	snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */
+
+	/* TEMP: Select 48kHz SPDIF out */
+	snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */
+	snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */
+	/* Word Clock source, Internal 48kHz x1 */
+	snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K );
+	//snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X );
+	emu->emu1010.internal_clock = 1; /* 48000 */
+	snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);/* Set LEDs on Audio Dock */
+	snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */
+	//snd_emu1010_fpga_write(emu, 0x7, 0x0); /* Mute all */
+	//snd_emu1010_fpga_write(emu, 0x7, 0x1); /* Unmute all */
+	//snd_emu1010_fpga_write(emu, 0xe, 0x12); /* Set LEDs on Audio Dock */
 
 	return 0;
 }
@@ -747,6 +1081,10 @@
 		}
 		snd_emu10k1_free_efx(emu);
        	}
+	if (emu->card_capabilities->emu1010) {
+		/* Disable 48Volt power to Audio Dock */
+		snd_emu1010_fpga_write(emu,  EMU_HANA_DOCK_PWR,  0 );
+	}
 	if (emu->memhdr)
 		snd_util_memhdr_free(emu->memhdr);
 	if (emu->silent_page.area)
@@ -838,10 +1176,11 @@
 	 .adc_1361t = 1,  /* 24 bit capture instead of 16bit */
 	 .ac97_chip = 1} ,
 	/* Audigy 2 ZS Notebook Cardbus card.*/
-	/* Tested by James@superbug.co.uk 22th December 2005 */
+	/* Tested by James@superbug.co.uk 6th November 2006 */
 	/* Audio output 7.1/Headphones working.
 	 * Digital output working. (AC3 not checked, only PCM)
-	 * Audio inputs not tested.
+	 * Audio Mic/Line inputs working.
+	 * Digital input not tested.
 	 */ 
 	/* DSP: Tina2
 	 * DAC: Wolfson WM8768/WM8568
@@ -849,6 +1188,25 @@
 	 * AC97: None
 	 * CA0151: None
 	 */
+	/* Tested by James@superbug.co.uk 4th April 2006 */
+	/* A_IOCFG bits
+	 * Output
+	 * 0: Not Used
+	 * 1: 0 = Mute all the 7.1 channel out. 1 = unmute.
+	 * 2: Analog input 0 = line in, 1 = mic in
+	 * 3: Not Used
+	 * 4: Digital output 0 = off, 1 = on.
+	 * 5: Not Used
+	 * 6: Not Used
+	 * 7: Not Used
+	 * Input
+	 *      All bits 1 (0x3fxx) means nothing plugged in.
+	 * 8-9: 0 = Line in/Mic, 2 = Optical in, 3 = Nothing.
+	 * A-B: 0 = Headphones, 2 = Optical out, 3 = Nothing.
+	 * C-D: 2 = Front/Rear/etc, 3 = nothing.
+	 * E-F: Always 0
+	 *
+	 */
 	{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
 	 .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]", 
 	 .id = "Audigy2",
@@ -856,6 +1214,7 @@
 	 .ca0108_chip = 1,
 	 .ca_cardbus_chip = 1,
 	 .spi_dac = 1,
+	 .i2c_adc = 1,
 	 .spk71 = 1} ,
 	{.vendor = 0x1102, .device = 0x0008, 
 	 .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", 
@@ -865,11 +1224,12 @@
 	 .ac97_chip = 1} ,
 	/* Tested by James@superbug.co.uk 8th July 2005. No sound available yet. */
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
-	 .driver = "Audigy2", .name = "E-mu 1212m [4001]", 
-	 .id = "EMU1212m",
+	 .driver = "Audigy2", .name = "E-mu 1010 [4001]", 
+	 .id = "EMU1010",
 	 .emu10k2_chip = 1,
 	 .ca0102_chip = 1,
-	 .emu1212m = 1} ,
+	 .spk71 = 1,
+	 .emu1010 = 1} ,
 	/* Tested by James@superbug.co.uk 3rd July 2005 */
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
 	 .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", 
@@ -1297,8 +1657,8 @@
 	} else if (emu->card_capabilities->ca_cardbus_chip) {
 		if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
 			goto error;
- 	} else if (emu->card_capabilities->emu1212m) {
- 		if ((err = snd_emu10k1_emu1212m_init(emu)) < 0) {
+ 	} else if (emu->card_capabilities->emu1010) {
+ 		if ((err = snd_emu10k1_emu1010_init(emu)) < 0) {
  			snd_emu10k1_free(emu);
  			return err;
  		}
@@ -1446,8 +1806,8 @@
 		snd_emu10k1_ecard_init(emu);
 	else if (emu->card_capabilities->ca_cardbus_chip)
 		snd_emu10k1_cardbus_init(emu);
-	else if (emu->card_capabilities->emu1212m)
- 		snd_emu10k1_emu1212m_init(emu);
+	else if (emu->card_capabilities->emu1010)
+ 		snd_emu10k1_emu1010_init(emu);
 	else
 		snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
 	snd_emu10k1_init(emu, emu->enable_ir, 1);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 2199b42..bb0fec7 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -460,7 +460,7 @@
 	u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
 	int i;
 	
-	for(i=0; i < runtime->periods; i++) {
+	for(i = 0; i < runtime->periods; i++) {
 		*table_base++=runtime->dma_addr+(i*period_size_bytes);
 		*table_base++=period_size_bytes<<16;
 	}
@@ -1042,8 +1042,8 @@
 		if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
 			continue;
 
-		if ((reg < 0x49) && (reg >=0) && (val <= 0xffffffff) 
-		    && (channel_id >=0) && (channel_id <= 2) )
+		if ((reg < 0x49) && (reg >= 0) && (val <= 0xffffffff) 
+		    && (channel_id >= 0) && (channel_id <= 2) )
 			snd_emu10k1x_ptr_write(emu, reg, channel_id, val);
 	}
 }
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 13cd6ce..c02012c 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -3,6 +3,9 @@
  *                   Creative Labs, Inc.
  *  Routines for effect processor FX8010
  *
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
+ *  	Added EMU 1010 support.
+ *
  *  BUGS:
  *    --
  *
@@ -293,7 +296,7 @@
 };
 
 /* EMU10k1/EMU10k2 DSP control db gain */
-static DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1);
+static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1);
 
 static const u32 onoff_table[2] = {
 	0x00000000, 0x00000001
@@ -652,13 +655,66 @@
 	return NULL;
 }
 
+#define MAX_TLV_SIZE	256
+
+static unsigned int *copy_tlv(const unsigned int __user *_tlv)
+{
+	unsigned int data[2];
+	unsigned int *tlv;
+
+	if (!_tlv)
+		return NULL;
+	if (copy_from_user(data, _tlv, sizeof(data)))
+		return NULL;
+	if (data[1] >= MAX_TLV_SIZE)
+		return NULL;
+	tlv = kmalloc(data[1] * 4 + sizeof(data), GFP_KERNEL);
+	if (!tlv)
+		return NULL;
+	memcpy(tlv, data, sizeof(data));
+	if (copy_from_user(tlv + 2, _tlv + 2, data[1])) {
+		kfree(tlv);
+		return NULL;
+	}
+	return tlv;
+}
+
+static int copy_gctl(struct snd_emu10k1 *emu,
+		     struct snd_emu10k1_fx8010_control_gpr *gctl,
+		     struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
+		     int idx)
+{
+	struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
+
+	if (emu->support_tlv)
+		return copy_from_user(gctl, &_gctl[idx], sizeof(*gctl));
+	octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
+	if (copy_from_user(gctl, &octl[idx], sizeof(*octl)))
+		return -EFAULT;
+	gctl->tlv = NULL;
+	return 0;
+}
+
+static int copy_gctl_to_user(struct snd_emu10k1 *emu,
+		     struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
+		     struct snd_emu10k1_fx8010_control_gpr *gctl,
+		     int idx)
+{
+	struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
+
+	if (emu->support_tlv)
+		return copy_to_user(&_gctl[idx], gctl, sizeof(*gctl));
+	
+	octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
+	return copy_to_user(&octl[idx], gctl, sizeof(*octl));
+}
+
 static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
 				       struct snd_emu10k1_fx8010_code *icode)
 {
 	unsigned int i;
 	struct snd_ctl_elem_id __user *_id;
 	struct snd_ctl_elem_id id;
-	struct snd_emu10k1_fx8010_control_gpr __user *_gctl;
 	struct snd_emu10k1_fx8010_control_gpr *gctl;
 	int err;
 	
@@ -673,9 +729,8 @@
 	if (! gctl)
 		return -ENOMEM;
 	err = 0;
-	for (i = 0, _gctl = icode->gpr_add_controls;
-	     i < icode->gpr_add_control_count; i++, _gctl++) {
-		if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
+	for (i = 0; i < icode->gpr_add_control_count; i++) {
+		if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) {
 			err = -EFAULT;
 			goto __error;
 		}
@@ -694,10 +749,9 @@
 			goto __error;
 		}
 	}
-	for (i = 0, _gctl = icode->gpr_list_controls;
-	     i < icode->gpr_list_control_count; i++, _gctl++) {
+	for (i = 0; i < icode->gpr_list_control_count; i++) {
 	     	/* FIXME: we need to check the WRITE access */
-		if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
+		if (copy_gctl(emu, gctl, icode->gpr_list_controls, i)) {
 			err = -EFAULT;
 			goto __error;
 		}
@@ -715,13 +769,14 @@
 	kctl->private_value = 0;
 	list_del(&ctl->list);
 	kfree(ctl);
+	if (kctl->tlv.p)
+		kfree(kctl->tlv.p);
 }
 
 static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
 				    struct snd_emu10k1_fx8010_code *icode)
 {
 	unsigned int i, j;
-	struct snd_emu10k1_fx8010_control_gpr __user *_gctl;
 	struct snd_emu10k1_fx8010_control_gpr *gctl;
 	struct snd_emu10k1_fx8010_ctl *ctl, *nctl;
 	struct snd_kcontrol_new knew;
@@ -737,9 +792,8 @@
 		goto __error;
 	}
 
-	for (i = 0, _gctl = icode->gpr_add_controls;
-	     i < icode->gpr_add_control_count; i++, _gctl++) {
-		if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
+	for (i = 0; i < icode->gpr_add_control_count; i++) {
+		if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) {
 			err = -EFAULT;
 			goto __error;
 		}
@@ -760,11 +814,10 @@
 		knew.device = gctl->id.device;
 		knew.subdevice = gctl->id.subdevice;
 		knew.info = snd_emu10k1_gpr_ctl_info;
-		if (gctl->tlv.p) {
-			knew.tlv.p = gctl->tlv.p;
+		knew.tlv.p = copy_tlv(gctl->tlv);
+		if (knew.tlv.p)
 			knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
 				SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-		} 
 		knew.get = snd_emu10k1_gpr_ctl_get;
 		knew.put = snd_emu10k1_gpr_ctl_put;
 		memset(nctl, 0, sizeof(*nctl));
@@ -782,12 +835,14 @@
 			ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
 			if (ctl == NULL) {
 				err = -ENOMEM;
+				kfree(knew.tlv.p);
 				goto __error;
 			}
 			knew.private_value = (unsigned long)ctl;
 			*ctl = *nctl;
 			if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) {
 				kfree(ctl);
+				kfree(knew.tlv.p);
 				goto __error;
 			}
 			kctl->private_free = snd_emu10k1_ctl_private_free;
@@ -838,7 +893,6 @@
 	unsigned int i = 0, j;
 	unsigned int total = 0;
 	struct snd_emu10k1_fx8010_control_gpr *gctl;
-	struct snd_emu10k1_fx8010_control_gpr __user *_gctl;
 	struct snd_emu10k1_fx8010_ctl *ctl;
 	struct snd_ctl_elem_id *id;
 	struct list_head *list;
@@ -847,11 +901,11 @@
 	if (! gctl)
 		return -ENOMEM;
 
-	_gctl = icode->gpr_list_controls;	
 	list_for_each(list, &emu->fx8010.gpr_ctl) {
 		ctl = emu10k1_gpr_ctl(list);
 		total++;
-		if (_gctl && i < icode->gpr_list_control_count) {
+		if (icode->gpr_list_controls &&
+		    i < icode->gpr_list_control_count) {
 			memset(gctl, 0, sizeof(*gctl));
 			id = &ctl->kcontrol->id;
 			gctl->id.iface = id->iface;
@@ -868,11 +922,11 @@
 			gctl->min = ctl->min;
 			gctl->max = ctl->max;
 			gctl->translation = ctl->translation;
-			if (copy_to_user(_gctl, gctl, sizeof(*gctl))) {
+			if (copy_gctl_to_user(emu, icode->gpr_list_controls,
+					      gctl, i)) {
 				kfree(gctl);
 				return -EFAULT;
 			}
-			_gctl++;
 			i++;
 		}
 	}
@@ -1023,7 +1077,7 @@
 	ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
 	ctl->min = 0;
 	ctl->max = 100;
-	ctl->tlv.p = snd_emu10k1_db_scale1;
+	ctl->tlv = snd_emu10k1_db_scale1;
 	ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;	
 }
 
@@ -1038,7 +1092,7 @@
 	ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
 	ctl->min = 0;
 	ctl->max = 100;
-	ctl->tlv.p = snd_emu10k1_db_scale1;
+	ctl->tlv = snd_emu10k1_db_scale1;
 	ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
 }
 
@@ -1069,6 +1123,21 @@
 	ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
 }
 
+static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
+				struct snd_emu10k1_fx8010_code *icode,
+				u32 *ptr, int tmp, int bit_shifter16,
+				int reg_in, int reg_out)
+{
+	A_OP(icode, ptr, iACC3, A_GPR(tmp + 1), reg_in, A_C_00000000, A_C_00000000);
+	A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp + 1), A_GPR(bit_shifter16 - 1), A_C_00000000);
+	A_OP(icode, ptr, iTSTNEG, A_GPR(tmp + 2), A_GPR(tmp), A_C_80000000, A_GPR(bit_shifter16 - 2));
+	A_OP(icode, ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_C_80000000, A_C_00000000);
+	A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp), A_GPR(bit_shifter16 - 3), A_C_00000000);
+	A_OP(icode, ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A_GPR(tmp), A_C_00010000);
+	A_OP(icode, ptr, iANDXOR, reg_out, A_GPR(tmp), A_C_ffffffff, A_GPR(tmp + 2));
+	A_OP(icode, ptr, iACC3, reg_out + 1, A_GPR(tmp + 1), A_C_00000000, A_C_00000000);
+	return 1;
+}
 
 /*
  * initial DSP configuration for Audigy
@@ -1077,6 +1146,7 @@
 static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
 {
 	int err, i, z, gpr, nctl;
+	int bit_shifter16;
 	const int playback = 10;
 	const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
 	const int stereo_mix = capture + 2;
@@ -1114,17 +1184,14 @@
 	ptr = 0;
 	nctl = 0;
 	gpr = stereo_mix + 10;
+	gpr_map[gpr++] = 0x00007fff;
+	gpr_map[gpr++] = 0x00008000;
+	gpr_map[gpr++] = 0x0000ffff;
+	bit_shifter16 = gpr;
 
 	/* stop FX processor */
 	snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
 
-#if 0
-	/* FIX: jcd test */
-	for (z = 0; z < 80; z=z+2) {
-		A_OP(icode, &ptr, iACC3, A_EXTOUT(z), A_FXBUS(FXBUS_PCM_LEFT_FRONT), A_C_00000000, A_C_00000000); /* left */
-		A_OP(icode, &ptr, iACC3, A_EXTOUT(z+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT), A_C_00000000, A_C_00000000); /* right */
-	}
-#endif /* jcd test */
 #if 1
 	/* PCM front Playback Volume (independent from stereo mix) */
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
@@ -1182,13 +1249,20 @@
 	A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
 	snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0);
 	gpr += 2;
-
+      
 	/*
 	 * inputs
 	 */
 #define A_ADD_VOLUME_IN(var,vol,input) \
 A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
 
+	/* emu1212 DSP 0 and DSP 1 Capture */
+	if (emu->card_capabilities->emu1010) {
+		A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0));
+		A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1));
+		snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0);
+		gpr += 2;
+	}
 	/* AC'97 Playback Volume - used only for mic (renamed later) */
 	A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L);
 	A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R);
@@ -1429,6 +1503,13 @@
 
 	/* digital outputs */
 	/* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
+	if (emu->card_capabilities->emu1010) {
+		/* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */
+		snd_printk("EMU outputs on\n");
+		for (z = 0; z < 8; z++) {
+			A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
+		}
+	}
 
 	/* IEC958 Optical Raw Playback Switch */ 
 	gpr_map[gpr++] = 0;
@@ -1466,9 +1547,57 @@
 	A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
 #endif
 
-	/* EFX capture - capture the 16 EXTINs */
-	for (z = 0; z < 16; z++) {
-		A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
+	if (emu->card_capabilities->emu1010) {
+		snd_printk("EMU inputs on\n");
+		/* Capture 8 channels of S32_LE sound */
+		
+		/* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */
+		/* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
+		/* A_P16VIN(0) is delayed by one sample,
+		 * so all other A_P16VIN channels will need to also be delayed
+		 */
+		/* Left ADC in. 1 of 2 */
+		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
+		/* Right ADC in 1 of 2 */
+		gpr_map[gpr++] = 0x00000000;
+		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
+		gpr_map[gpr++] = 0x00000000;
+		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) );
+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000);
+		gpr_map[gpr++] = 0x00000000;
+		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) );
+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000);
+		/* For 96kHz mode */
+		/* Left ADC in. 2 of 2 */
+		gpr_map[gpr++] = 0x00000000;
+		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) );
+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000);
+		/* Right ADC in 2 of 2 */
+		gpr_map[gpr++] = 0x00000000;
+		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) );
+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000);
+		gpr_map[gpr++] = 0x00000000;
+		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) );
+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000);
+		gpr_map[gpr++] = 0x00000000;
+		snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
+		A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
+
+#if 0
+		for (z = 4; z < 8; z++) {
+			A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
+		}
+		for (z = 0xc; z < 0x10; z++) {
+			A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
+		}
+#endif
+	} else {
+		/* EFX capture - capture the 16 EXTINs */
+		/* Capture 16 channels of S16_LE sound */
+		for (z = 0; z < 16; z++) {
+			A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
+		}
 	}
 	
 #endif /* JCD test */
@@ -1488,7 +1617,9 @@
 	seg = snd_enter_user();
 	icode->gpr_add_control_count = nctl;
 	icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
+	emu->support_tlv = 1; /* support TLV */
 	err = snd_emu10k1_icode_poke(emu, icode);
+	emu->support_tlv = 0; /* clear again */
 	snd_leave_user(seg);
 
  __err:
@@ -2105,7 +2236,9 @@
 	seg = snd_enter_user();
 	icode->gpr_add_control_count = i;
 	icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
+	emu->support_tlv = 1; /* support TLV */
 	err = snd_emu10k1_icode_poke(emu, icode);
+	emu->support_tlv = 0; /* clear again */
 	snd_leave_user(seg);
 	if (err >= 0)
 		err = snd_emu10k1_ipcm_poke(emu, ipcm);
@@ -2138,7 +2271,7 @@
 		snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP);
 }
 
-#if 0 // FIXME: who use them?
+#if 0 /* FIXME: who use them? */
 int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output)
 {
 	if (output < 0 || output >= 6)
@@ -2249,6 +2382,9 @@
 	int res;
 	
 	switch (cmd) {
+	case SNDRV_EMU10K1_IOCTL_PVERSION:
+		emu->support_tlv = 1;
+		return put_user(SNDRV_EMU10K1_VERSION, (int __user *)argp);
 	case SNDRV_EMU10K1_IOCTL_INFO:
 		info = kmalloc(sizeof(*info), GFP_KERNEL);
 		if (!info)
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index c31f3d0..4db6e1c 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -5,6 +5,9 @@
  *  Routines for control of EMU10K1 chips / mixer routines
  *  Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
  *
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
+ *  	Added EMU 1010 support.
+ *
  *  BUGS:
  *    --
  *
@@ -32,9 +35,15 @@
 #include <linux/init.h>
 #include <sound/core.h>
 #include <sound/emu10k1.h>
+#include <linux/delay.h>
+#include <sound/tlv.h>
+
+#include "p17v.h"
 
 #define AC97_ID_STAC9758	0x83847658
 
+static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */
+
 static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -68,6 +77,669 @@
 	return 0;
 }
 
+static char *emu1010_src_texts[] = { 
+	"Silence",
+	"Dock Mic A",
+	"Dock Mic B",
+	"Dock ADC1 Left",
+	"Dock ADC1 Right",
+	"Dock ADC2 Left",
+	"Dock ADC2 Right",
+	"Dock ADC3 Left",
+	"Dock ADC3 Right",
+	"0202 ADC Left",
+	"0202 ADC Right",
+	"0202 SPDIF Left",
+	"0202 SPDIF Right",
+	"ADAT 0",
+	"ADAT 1",
+	"ADAT 2",
+	"ADAT 3",
+	"ADAT 4",
+	"ADAT 5",
+	"ADAT 6",
+	"ADAT 7",
+	"DSP 0",
+	"DSP 1",
+	"DSP 2",
+	"DSP 3",
+	"DSP 4",
+	"DSP 5",
+	"DSP 6",
+	"DSP 7",
+	"DSP 8",
+	"DSP 9",
+	"DSP 10",
+	"DSP 11",
+	"DSP 12",
+	"DSP 13",
+	"DSP 14",
+	"DSP 15",
+	"DSP 16",
+	"DSP 17",
+	"DSP 18",
+	"DSP 19",
+	"DSP 20",
+	"DSP 21",
+	"DSP 22",
+	"DSP 23",
+	"DSP 24",
+	"DSP 25",
+	"DSP 26",
+	"DSP 27",
+	"DSP 28",
+	"DSP 29",
+	"DSP 30",
+	"DSP 31",
+};
+
+static unsigned int emu1010_src_regs[] = {
+	EMU_SRC_SILENCE,/* 0 */
+	EMU_SRC_DOCK_MIC_A1, /* 1 */
+	EMU_SRC_DOCK_MIC_B1, /* 2 */
+	EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */
+	EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */
+	EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */
+	EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */
+	EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */
+	EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */
+	EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */
+	EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */
+	EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */
+	EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */
+	EMU_SRC_HANA_ADAT, /* 13 */
+	EMU_SRC_HANA_ADAT+1, /* 14 */
+	EMU_SRC_HANA_ADAT+2, /* 15 */
+	EMU_SRC_HANA_ADAT+3, /* 16 */
+	EMU_SRC_HANA_ADAT+4, /* 17 */
+	EMU_SRC_HANA_ADAT+5, /* 18 */
+	EMU_SRC_HANA_ADAT+6, /* 19 */
+	EMU_SRC_HANA_ADAT+7, /* 20 */
+	EMU_SRC_ALICE_EMU32A, /* 21 */
+	EMU_SRC_ALICE_EMU32A+1, /* 22 */
+	EMU_SRC_ALICE_EMU32A+2, /* 23 */
+	EMU_SRC_ALICE_EMU32A+3, /* 24 */
+	EMU_SRC_ALICE_EMU32A+4, /* 25 */
+	EMU_SRC_ALICE_EMU32A+5, /* 26 */
+	EMU_SRC_ALICE_EMU32A+6, /* 27 */
+	EMU_SRC_ALICE_EMU32A+7, /* 28 */
+	EMU_SRC_ALICE_EMU32A+8, /* 29 */
+	EMU_SRC_ALICE_EMU32A+9, /* 30 */
+	EMU_SRC_ALICE_EMU32A+0xa, /* 31 */
+	EMU_SRC_ALICE_EMU32A+0xb, /* 32 */
+	EMU_SRC_ALICE_EMU32A+0xc, /* 33 */
+	EMU_SRC_ALICE_EMU32A+0xd, /* 34 */
+	EMU_SRC_ALICE_EMU32A+0xe, /* 35 */
+	EMU_SRC_ALICE_EMU32A+0xf, /* 36 */
+	EMU_SRC_ALICE_EMU32B, /* 37 */
+	EMU_SRC_ALICE_EMU32B+1, /* 38 */
+	EMU_SRC_ALICE_EMU32B+2, /* 39 */
+	EMU_SRC_ALICE_EMU32B+3, /* 40 */
+	EMU_SRC_ALICE_EMU32B+4, /* 41 */
+	EMU_SRC_ALICE_EMU32B+5, /* 42 */
+	EMU_SRC_ALICE_EMU32B+6, /* 43 */
+	EMU_SRC_ALICE_EMU32B+7, /* 44 */
+	EMU_SRC_ALICE_EMU32B+8, /* 45 */
+	EMU_SRC_ALICE_EMU32B+9, /* 46 */
+	EMU_SRC_ALICE_EMU32B+0xa, /* 47 */
+	EMU_SRC_ALICE_EMU32B+0xb, /* 48 */
+	EMU_SRC_ALICE_EMU32B+0xc, /* 49 */
+	EMU_SRC_ALICE_EMU32B+0xd, /* 50 */
+	EMU_SRC_ALICE_EMU32B+0xe, /* 51 */
+	EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
+};
+
+static unsigned int emu1010_output_dst[] = {
+	EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
+	EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
+	EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
+	EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */
+	EMU_DST_DOCK_DAC3_LEFT1, /* 4 */
+	EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */
+	EMU_DST_DOCK_DAC4_LEFT1, /* 6 */
+	EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */
+	EMU_DST_DOCK_PHONES_LEFT1, /* 8 */
+	EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */
+	EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */
+	EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */
+	EMU_DST_HANA_SPDIF_LEFT1, /* 12 */
+	EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */
+	EMU_DST_HAMOA_DAC_LEFT1, /* 14 */
+	EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */
+	EMU_DST_HANA_ADAT, /* 16 */
+	EMU_DST_HANA_ADAT+1, /* 17 */
+	EMU_DST_HANA_ADAT+2, /* 18 */
+	EMU_DST_HANA_ADAT+3, /* 19 */
+	EMU_DST_HANA_ADAT+4, /* 20 */
+	EMU_DST_HANA_ADAT+5, /* 21 */
+	EMU_DST_HANA_ADAT+6, /* 22 */
+	EMU_DST_HANA_ADAT+7, /* 23 */
+};
+
+static unsigned int emu1010_input_dst[] = {
+	EMU_DST_ALICE2_EMU32_0,
+	EMU_DST_ALICE2_EMU32_1,
+	EMU_DST_ALICE2_EMU32_2,
+	EMU_DST_ALICE2_EMU32_3,
+	EMU_DST_ALICE2_EMU32_4,
+	EMU_DST_ALICE2_EMU32_5,
+	EMU_DST_ALICE2_EMU32_6,
+	EMU_DST_ALICE2_EMU32_7,
+	EMU_DST_ALICE2_EMU32_8,
+	EMU_DST_ALICE2_EMU32_9,
+	EMU_DST_ALICE2_EMU32_A,
+	EMU_DST_ALICE2_EMU32_B,
+	EMU_DST_ALICE2_EMU32_C,
+	EMU_DST_ALICE2_EMU32_D,
+	EMU_DST_ALICE2_EMU32_E,
+	EMU_DST_ALICE2_EMU32_F,
+	EMU_DST_ALICE_I2S0_LEFT,
+	EMU_DST_ALICE_I2S0_RIGHT,
+	EMU_DST_ALICE_I2S1_LEFT,
+	EMU_DST_ALICE_I2S1_RIGHT,
+	EMU_DST_ALICE_I2S2_LEFT,
+	EMU_DST_ALICE_I2S2_RIGHT,
+};
+
+static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 53;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	int channel;
+
+	channel = (kcontrol->private_value) & 0xff;
+	ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
+	return 0;
+}
+
+static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	int change = 0;
+	unsigned int val;
+	int channel;
+
+	channel = (kcontrol->private_value) & 0xff;
+	if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) {
+		val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0];
+		change = 1;
+		snd_emu1010_fpga_link_dst_src_write(emu,
+			emu1010_output_dst[channel], emu1010_src_regs[val]);
+	}
+	return change;
+}
+
+static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	int channel;
+
+	channel = (kcontrol->private_value) & 0xff;
+	ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
+	return 0;
+}
+
+static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	int change = 0;
+	unsigned int val;
+	int channel;
+
+	channel = (kcontrol->private_value) & 0xff;
+	if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) {
+		val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0];
+		change = 1;
+		snd_emu1010_fpga_link_dst_src_write(emu,
+			emu1010_input_dst[channel], emu1010_src_regs[val]);
+	}
+	return change;
+}
+
+#define EMU1010_SOURCE_OUTPUT(xname,chid) \
+{								\
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,		\
+	.info =  snd_emu1010_input_output_source_info,		\
+	.get =   snd_emu1010_output_source_get,			\
+	.put =   snd_emu1010_output_source_put,			\
+	.private_value = chid					\
+}
+
+static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
+	EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
+	EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
+	EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
+	EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),
+	EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),
+	EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),
+	EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6),
+	EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7),
+	EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8),
+	EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9),
+	EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa),
+	EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb),
+	EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc),
+	EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd),
+	EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe),
+	EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf),
+	EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10),
+	EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11),
+	EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12),
+	EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13),
+	EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14),
+	EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15),
+	EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16),
+	EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17),
+};
+
+#define EMU1010_SOURCE_INPUT(xname,chid) \
+{								\
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,		\
+	.info =  snd_emu1010_input_output_source_info,		\
+	.get =   snd_emu1010_input_source_get,			\
+	.put =   snd_emu1010_input_source_put,			\
+	.private_value = chid					\
+}
+
+static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
+	EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
+	EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
+	EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
+	EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3),
+	EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4),
+	EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5),
+	EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6),
+	EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7),
+	EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8),
+	EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9),
+	EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa),
+	EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb),
+	EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc),
+	EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd),
+	EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe),
+	EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf),
+	EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10),
+	EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11),
+	EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12),
+	EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13),
+	EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14),
+	EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15),
+};
+
+
+
+
+static int snd_emu1010_adc_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int mask = kcontrol->private_value & 0xff;
+	ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
+	return 0;
+}
+
+static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int mask = kcontrol->private_value & 0xff;
+	unsigned int val, cache;
+	val = ucontrol->value.integer.value[0];
+	cache = emu->emu1010.adc_pads;
+	if (val == 1) 
+		cache = cache | mask;
+	else
+		cache = cache & ~mask;
+	if (cache != emu->emu1010.adc_pads) {
+		snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
+	        emu->emu1010.adc_pads = cache;
+	}
+
+	return 0;
+}
+
+
+
+#define EMU1010_ADC_PADS(xname,chid) \
+{								\
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,		\
+	.info =  snd_emu1010_adc_pads_info,			\
+	.get =   snd_emu1010_adc_pads_get,			\
+	.put =   snd_emu1010_adc_pads_put,			\
+	.private_value = chid					\
+}
+
+static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
+	EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
+	EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
+	EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
+	EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
+};
+
+static int snd_emu1010_dac_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int mask = kcontrol->private_value & 0xff;
+	ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
+	return 0;
+}
+
+static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int mask = kcontrol->private_value & 0xff;
+	unsigned int val, cache;
+	val = ucontrol->value.integer.value[0];
+	cache = emu->emu1010.dac_pads;
+	if (val == 1) 
+		cache = cache | mask;
+	else
+		cache = cache & ~mask;
+	if (cache != emu->emu1010.dac_pads) {
+		snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
+	        emu->emu1010.dac_pads = cache;
+	}
+
+	return 0;
+}
+
+
+
+#define EMU1010_DAC_PADS(xname,chid) \
+{								\
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,		\
+	.info =  snd_emu1010_dac_pads_info,			\
+	.get =   snd_emu1010_dac_pads_get,			\
+	.put =   snd_emu1010_dac_pads_put,			\
+	.private_value = chid					\
+}
+
+static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
+	EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
+	EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
+	EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
+	EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
+	EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
+};
+
+
+static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[2] = {
+		"44100", "48000"
+	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+                uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
+	return 0;
+}
+
+static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int val;
+	int change = 0;
+
+	val = ucontrol->value.enumerated.item[0] ;
+	change = (emu->emu1010.internal_clock != val);
+	if (change) {
+		emu->emu1010.internal_clock = val;
+		switch (val) {
+		case 0:
+			/* 44100 */
+			/* Mute all */
+			snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
+			/* Default fallback clock 48kHz */
+			snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
+			/* Word Clock source, Internal 44.1kHz x1 */
+			snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
+			EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
+			/* Set LEDs on Audio Dock */
+			snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
+				EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
+			/* Allow DLL to settle */
+			msleep(10);
+			/* Unmute all */
+			snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
+			break;
+		case 1:
+			/* 48000 */
+			/* Mute all */
+			snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
+			/* Default fallback clock 48kHz */
+			snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
+			/* Word Clock source, Internal 48kHz x1 */
+			snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
+				EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
+			/* Set LEDs on Audio Dock */
+			snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
+				EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
+			/* Allow DLL to settle */
+			msleep(10);
+			/* Unmute all */
+			snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
+			break;
+		}
+	}
+        return change;
+}
+
+static struct snd_kcontrol_new snd_emu1010_internal_clock =
+{
+	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =         "Clock Internal Rate",
+	.count =	1,
+	.info =         snd_emu1010_internal_clock_info,
+	.get =          snd_emu1010_internal_clock_get,
+	.put =          snd_emu1010_internal_clock_put
+};
+
+static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_info *uinfo)
+{
+#if 0
+	static char *texts[4] = {
+		"Unknown1", "Unknown2", "Mic", "Line"
+	};
+#endif
+	static char *texts[2] = {
+		"Mic", "Line"
+	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+                uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
+	return 0;
+}
+
+static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int source_id;
+	unsigned int ngain, ogain;
+	u32 gpio;
+	int change = 0;
+	unsigned long flags;
+	u32 source;
+	/* If the capture source has changed,
+	 * update the capture volume from the cached value
+	 * for the particular source.
+	 */
+	source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */
+	change = (emu->i2c_capture_source != source_id);
+	if (change) {
+		snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
+		spin_lock_irqsave(&emu->emu_lock, flags);
+		gpio = inl(emu->port + A_IOCFG);
+		if (source_id==0)
+			outl(gpio | 0x4, emu->port + A_IOCFG);
+		else
+			outl(gpio & ~0x4, emu->port + A_IOCFG);
+		spin_unlock_irqrestore(&emu->emu_lock, flags);
+
+		ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
+		ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
+		if (ngain != ogain)
+			snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
+		ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
+		ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
+		if (ngain != ogain)
+			snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
+
+		source = 1 << (source_id + 2);
+		snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
+		emu->i2c_capture_source = source_id;
+	}
+        return change;
+}
+
+static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
+{
+		.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name =		"Capture Source",
+		.info =		snd_audigy_i2c_capture_source_info,
+		.get =		snd_audigy_i2c_capture_source_get,
+		.put =		snd_audigy_i2c_capture_source_put
+};
+
+static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 255;
+	return 0;
+}
+
+static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	int source_id;
+
+	source_id = kcontrol->private_value;
+
+	ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
+	ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
+	return 0;
+}
+
+static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int ogain;
+	unsigned int ngain;
+	int source_id;
+	int change = 0;
+
+	source_id = kcontrol->private_value;
+	ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
+	ngain = ucontrol->value.integer.value[0];
+	if (ngain > 0xff)
+		return 0;
+	if (ogain != ngain) {
+		if (emu->i2c_capture_source == source_id)
+			snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
+		emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
+		change = 1;
+	}
+	ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
+	ngain = ucontrol->value.integer.value[1];
+	if (ngain > 0xff)
+		return 0;
+	if (ogain != ngain) {
+		if (emu->i2c_capture_source == source_id)
+			snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
+		emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
+		change = 1;
+	}
+
+	return change;
+}
+
+#define I2C_VOLUME(xname,chid) \
+{								\
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |		\
+	          SNDRV_CTL_ELEM_ACCESS_TLV_READ,		\
+	.info =  snd_audigy_i2c_volume_info,			\
+	.get =   snd_audigy_i2c_volume_get,			\
+	.put =   snd_audigy_i2c_volume_put,			\
+	.tlv = { .p = snd_audigy_db_scale2 },			\
+	.private_value = chid					\
+}
+
+
+static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
+	I2C_VOLUME("Mic Capture Volume", 0),
+	I2C_VOLUME("Line Capture Volume", 0)
+};
+
 #if 0
 static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
@@ -668,7 +1340,9 @@
 	int change = 0;
 
 	spin_lock_irqsave(&emu->reg_lock, flags);
-	if (emu->audigy) {
+	if ( emu->card_capabilities->i2c_adc) {
+		/* Do nothing for Audigy 2 ZS Notebook */
+	} else if (emu->audigy) {
 		reg = inl(emu->port + A_IOCFG);
 		val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
 		change = (reg & A_IOCFG_GPOUT0) != val;
@@ -806,6 +1480,24 @@
 		"AMic Playback Volume", "Mic Playback Volume",
 		NULL
 	};
+	static char *audigy_rename_ctls_i2c_adc[] = {
+		//"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
+		"Line Capture Volume", "Analog Mix Capture Volume",
+		"Wave Playback Volume", "OLD PCM Playback Volume",
+		"Wave Master Playback Volume", "Master Playback Volume",
+		"AMic Playback Volume", "Old Mic Playback Volume",
+		"CD Capture Volume", "IEC958 Optical Capture Volume",
+		NULL
+	};
+	static char *audigy_remove_ctls_i2c_adc[] = {
+		/* On the Audigy2 ZS Notebook
+		 * Capture via WM8775  */
+		"Mic Capture Volume",
+		"Analog Mix Capture Volume",
+		"Aux Capture Volume",
+		"IEC958 Optical Capture Volume",
+		NULL
+	};
 	static char *audigy_remove_ctls_1361t_adc[] = {
 		/* On the Audigy2 the AC97 playback is piped into
 		 * the Philips ADC for 24bit capture */
@@ -890,6 +1582,7 @@
 			if (emu->ac97->id == AC97_ID_STAC9758) {
 				emu->rear_ac97 = 1;
 				snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
+				snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
 			}
 			/* remove unused AC97 controls */
 			snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
@@ -898,6 +1591,10 @@
 		}
 		for (; *c; c++)
 			remove_ctl(card, *c);
+	} else if (emu->card_capabilities->i2c_adc) {
+		c = audigy_remove_ctls_i2c_adc;
+		for (; *c; c++)
+			remove_ctl(card, *c);
 	} else {
 	no_ac97:
 		if (emu->card_capabilities->ecard)
@@ -911,6 +1608,8 @@
 	if (emu->audigy)
 		if (emu->card_capabilities->adc_1361t)
 			c = audigy_rename_ctls_1361t_adc;
+		else if (emu->card_capabilities->i2c_adc)
+			c = audigy_rename_ctls_i2c_adc;
 		else
 			c = audigy_rename_ctls;
 	else
@@ -1021,7 +1720,7 @@
 			return err;
 	}
 
-	if ( emu->card_capabilities->emu1212m) {
+	if ( emu->card_capabilities->emu1010) {
 		;  /* Disable the snd_audigy_spdif_shared_spdif */
 	} else if (emu->audigy) {
 		if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
@@ -1045,6 +1744,48 @@
 		if ((err = snd_p16v_mixer(emu)))
 			return err;
 	}
+
+	if ( emu->card_capabilities->emu1010) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
+			err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
+			if (err < 0)
+				return err;
+		}
+		for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
+			err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
+			if (err < 0)
+				return err;
+		}
+		for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
+			err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
+			if (err < 0)
+				return err;
+		}
+		for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
+			err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
+			if (err < 0)
+				return err;
+		}
+		err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu));
+		if (err < 0)
+			return err;
+	}
+
+	if ( emu->card_capabilities->i2c_adc) {
+		int i;
+
+		err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
+		if (err < 0)
+			return err;
+
+		for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
+			err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
+			if (err < 0)
+				return err;
+		}
+	}
 		
 	return 0;
 }
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 717e92e..ab4f5df 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -147,7 +147,7 @@
 					      1,
 					      &epcm->extra);
 		if (err < 0) {
-			// printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame);
+			/* printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame); */
 			for (i = 0; i < voices; i++) {
 				snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
 				epcm->voices[i] = NULL;
@@ -339,7 +339,7 @@
 		}
 	}
 
-	// setup routing
+	/* setup routing */
 	if (emu->audigy) {
 		snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
 				      snd_emu10k1_compose_audigy_fxrt1(send_routing));
@@ -353,12 +353,15 @@
 	} else
 		snd_emu10k1_ptr_write(emu, FXRT, voice,
 				      snd_emu10k1_compose_send_routing(send_routing));
-	// Stop CA
-	// Assumption that PT is already 0 so no harm overwriting
+	/* Stop CA */
+	/* Assumption that PT is already 0 so no harm overwriting */
 	snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
 	snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
 	snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
-	pitch_target = emu10k1_calc_pitch_target(runtime->rate);
+	if (emu->card_capabilities->emu1010)
+		pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
+	else 
+		pitch_target = emu10k1_calc_pitch_target(runtime->rate);
 	if (extra)
 		snd_emu10k1_ptr_write(emu, CCCA, voice, start_addr |
 			      emu10k1_select_interprom(pitch_target) |
@@ -367,14 +370,14 @@
 		snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) |
 			      emu10k1_select_interprom(pitch_target) |
 			      (w_16 ? 0 : CCCA_8BITSELECT));
-	// Clear filter delay memory
+	/* Clear filter delay memory */
 	snd_emu10k1_ptr_write(emu, Z1, voice, 0);
 	snd_emu10k1_ptr_write(emu, Z2, voice, 0);
-	// invalidate maps
+	/* invalidate maps */
 	silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
 	snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page);
 	snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page);
-	// modulation envelope
+	/* modulation envelope */
 	snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff);
 	snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff);
 	snd_emu10k1_ptr_write(emu, ATKHLDM, voice, 0);
@@ -385,12 +388,12 @@
 	snd_emu10k1_ptr_write(emu, TREMFRQ, voice, 0);
 	snd_emu10k1_ptr_write(emu, FM2FRQ2, voice, 0);
 	snd_emu10k1_ptr_write(emu, ENVVAL, voice, 0x8000);
-	// volume envelope
+	/* volume envelope */
 	snd_emu10k1_ptr_write(emu, ATKHLDV, voice, 0x7f7f);
 	snd_emu10k1_ptr_write(emu, ENVVOL, voice, 0x0000);
-	// filter envelope
+	/* filter envelope */
 	snd_emu10k1_ptr_write(emu, PEFE_FILTERAMOUNT, voice, 0x7f);
-	// pitch envelope
+	/* pitch envelope */
 	snd_emu10k1_ptr_write(emu, PEFE_PITCHAMOUNT, voice, 0);
 
 	spin_unlock_irqrestore(&emu->reg_lock, flags);
@@ -468,7 +471,7 @@
 		snd_emu10k1_voice_free(epcm->emu, epcm->extra);
 		epcm->extra = NULL;
 	}
-	for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+	for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
 		if (epcm->voices[i]) {
 			snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
 			epcm->voices[i] = NULL;
@@ -637,7 +640,7 @@
 	stereo = (!extra && runtime->channels == 2);
 	sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080;
 	ccis = emu10k1_ccis(stereo, sample == 0);
-	// set cs to 2 * number of cache registers beside the invalidated
+	/* set cs to 2 * number of cache registers beside the invalidated */
 	cs = (sample == 0) ? (32-ccis) : (64-ccis+1) >> 1;
 	if (cs > 16) cs = 16;
 	for (i = 0; i < cs; i++) {
@@ -646,14 +649,14 @@
 			snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample);
 		}
 	}
-	// reset cache
+	/* reset cache */
 	snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0);
 	snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);
 	if (stereo) {
 		snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0);
 		snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra);
 	}
-	// fill cache
+	/* fill cache */
 	snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis);
 	if (stereo) {
 		snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis);
@@ -698,7 +701,10 @@
 	voice = evoice->number;
 
 	pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8;
-	pitch_target = emu10k1_calc_pitch_target(runtime->rate);
+	if (emu->card_capabilities->emu1010)
+		pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
+	else 
+		pitch_target = emu10k1_calc_pitch_target(runtime->rate);
 	snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target);
 	if (master || evoice->epcm->type == PLAYBACK_EFX)
 		snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target);
@@ -732,7 +738,7 @@
 	struct snd_emu10k1_pcm_mixer *mix;
 	int result = 0;
 
-	// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
+	/* printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)); */
 	spin_lock(&emu->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -778,10 +784,10 @@
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
-		// hmm this should cause full and half full interrupt to be raised?  
+		/* hmm this should cause full and half full interrupt to be raised? */
 		outl(epcm->capture_ipr, emu->port + IPR);
 		snd_emu10k1_intr_enable(emu, epcm->capture_inte);
-		// printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs);
+		/* printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); */
 		switch (epcm->type) {
 		case CAPTURE_AC97ADC:
 			snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
@@ -790,6 +796,7 @@
 			if (emu->audigy) {
 				snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val);
 				snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2);
+				snd_printdd("cr_val=0x%x, cr_val2=0x%x\n", epcm->capture_cr_val, epcm->capture_cr_val2);
 			} else
 				snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
 			break;
@@ -851,7 +858,7 @@
 			ptr -= runtime->buffer_size;
 	}
 #endif
-	// printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size);
+	/* printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size); */
 	return ptr;
 }
 
@@ -868,7 +875,7 @@
 	spin_lock(&emu->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-		// prepare voices
+		/* prepare voices */
 		for (i = 0; i < NUM_EFX_PLAYBACK; i++) {	
 			snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]);
 		}
@@ -917,7 +924,7 @@
 	if (!epcm->running)
 		return 0;
 	if (epcm->first_ptr) {
-		udelay(50);	// hack, it takes awhile until capture is started
+		udelay(50);	/* hack, it takes awhile until capture is started */
 		epcm->first_ptr = 0;
 	}
 	ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff;
@@ -972,6 +979,28 @@
 	.fifo_size =		0,
 };
 
+static struct snd_pcm_hardware snd_emu10k1_capture_efx =
+{
+	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_RESUME |
+				 SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =		SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 
+				 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | 
+				 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
+	.rate_min =		44100,
+	.rate_max =		192000,
+	.channels_min =		8,
+	.channels_max =		8,
+	.buffer_bytes_max =	(64*1024),
+	.period_bytes_min =	384,
+	.period_bytes_max =	(64*1024),
+	.periods_min =		2,
+	.periods_max =		2,
+	.fifo_size =		0,
+};
+
 /*
  *
  */
@@ -1016,7 +1045,7 @@
 	struct snd_emu10k1_pcm_mixer *mix;
 	int i;
 
-	for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+	for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
 		mix = &emu->efx_pcm_mixer[i];
 		mix->epcm = NULL;
 		snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0);
@@ -1045,7 +1074,7 @@
 	runtime->private_free = snd_emu10k1_pcm_free_substream;
 	runtime->hw = snd_emu10k1_efx_playback;
 	
-	for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+	for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
 		mix = &emu->efx_pcm_mixer[i];
 		mix->send_routing[0][0] = i;
 		memset(&mix->send_volume, 0, sizeof(mix->send_volume));
@@ -1199,15 +1228,69 @@
 	epcm->capture_idx_reg = FXIDX;
 	substream->runtime->private_data = epcm;
 	substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
-	runtime->hw = snd_emu10k1_capture;
+	runtime->hw = snd_emu10k1_capture_efx;
 	runtime->hw.rates = SNDRV_PCM_RATE_48000;
 	runtime->hw.rate_min = runtime->hw.rate_max = 48000;
 	spin_lock_irq(&emu->reg_lock);
-	runtime->hw.channels_min = runtime->hw.channels_max = 0;
-	for (idx = 0; idx < nefx; idx++) {
-		if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
-			runtime->hw.channels_min++;
-			runtime->hw.channels_max++;
+	if (emu->card_capabilities->emu1010) {
+		/* TODO 
+		 * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE
+		 * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+		 * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+		 * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000
+		 * rate_min = 44100,
+		 * rate_max = 192000,
+		 * channels_min = 8,
+		 * channels_max = 8,
+		 * Need to add mixer control to fix sample rate
+		 *                 
+		 * There are 16 mono channels of 16bits each.
+		 * 24bit Audio uses 2x channels over 16bit
+		 * 96kHz uses 2x channels over 48kHz
+		 * 192kHz uses 4x channels over 48kHz
+		 * So, for 48kHz 24bit, one has 8 channels
+		 * for 96kHz 24bit, one has 4 channels
+		 * for 192kHz 24bit, one has 2 channels
+		 */
+#if 1
+		switch (emu->emu1010.internal_clock) {
+		case 0:
+			/* For 44.1kHz */
+			runtime->hw.rates = SNDRV_PCM_RATE_44100;
+			runtime->hw.rate_min = runtime->hw.rate_max = 44100;
+			runtime->hw.channels_min = runtime->hw.channels_max = 8;
+			break;
+		case 1:
+			/* For 48kHz */
+			runtime->hw.rates = SNDRV_PCM_RATE_48000;
+			runtime->hw.rate_min = runtime->hw.rate_max = 48000;
+			runtime->hw.channels_min = runtime->hw.channels_max = 8;
+			break;
+		};
+#endif
+#if 0
+		/* For 96kHz */
+		runtime->hw.rates = SNDRV_PCM_RATE_96000;
+		runtime->hw.rate_min = runtime->hw.rate_max = 96000;
+		runtime->hw.channels_min = runtime->hw.channels_max = 4;
+#endif
+#if 0
+		/* For 192kHz */
+		runtime->hw.rates = SNDRV_PCM_RATE_192000;
+		runtime->hw.rate_min = runtime->hw.rate_max = 192000;
+		runtime->hw.channels_min = runtime->hw.channels_max = 2;
+#endif
+		runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+		/* efx_voices_mask[0] is expected to be zero
+ 		 * efx_voices_mask[1] is expected to have 16bits set
+		 */
+	} else {
+		runtime->hw.channels_min = runtime->hw.channels_max = 0;
+		for (idx = 0; idx < nefx; idx++) {
+			if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
+				runtime->hw.channels_min++;
+				runtime->hw.channels_max++;
+			}
 		}
 	}
 	epcm->capture_cr_val = emu->efx_voices_mask[0];
@@ -1460,7 +1543,7 @@
 						   unsigned int count,
 						   unsigned int tram_shift)
 {
-	// printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
+	/* printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count); */
 	if ((tram_shift & 1) == 0) {
 		while (count--) {
 			*dst_left-- = *src++;
@@ -1537,7 +1620,7 @@
 	struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
 	unsigned int i;
 	
-	// printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
+	/* printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2); */
 	memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
 	pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
 	pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index b939e03..2c15859 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -3,6 +3,9 @@
  *                   Creative Labs, Inc.
  *  Routines for control of EMU10K1 chips / proc interface routines
  *
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
+ *  	Added EMU 1010 support.
+ *
  *  BUGS:
  *    --
  *
@@ -255,7 +258,7 @@
 	unsigned int val, tmp, n;
 	val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
 	tmp = (val >> 16) & 0x8;
-	for (n=0;n<4;n++) {
+	for (n = 0; n < 4; n++) {
 		tmp = val >> (16 + (n*4));
 		if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]);
 		else snd_iprintf(buffer, "Channel %d: No input\n", n);
@@ -372,6 +375,27 @@
 }
 
 #ifdef CONFIG_SND_DEBUG
+static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
+				     struct snd_info_buffer *buffer)
+{
+	struct snd_emu10k1 *emu = entry->private_data;
+	unsigned long value;
+	unsigned long flags;
+	unsigned long regs;
+	int i;
+	snd_iprintf(buffer, "EMU1010 Registers:\n\n");
+
+	for(i = 0; i < 0x30; i+=1) {
+		spin_lock_irqsave(&emu->emu_lock, flags);
+		regs=i+0x40; /* 0x40 upwards are registers. */
+		outl(regs, emu->port + A_IOCFG);
+		outl(regs | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
+		value = inl(emu->port + A_IOCFG);
+		spin_unlock_irqrestore(&emu->emu_lock, flags);
+		snd_iprintf(buffer, "%02X: %08lX, %02lX\n", i, value, (value >> 8) & 0x7f);
+	}
+}
+
 static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry,
 				     struct snd_info_buffer *buffer)
 {
@@ -398,7 +422,7 @@
 	while (!snd_info_get_line(buffer, line, sizeof(line))) {
 		if (sscanf(line, "%x %x", &reg, &val) != 2)
 			continue;
-		if ((reg < 0x40) && (reg >=0) && (val <= 0xffffffff) ) {
+		if ((reg < 0x40) && (reg >= 0) && (val <= 0xffffffff) ) {
 			spin_lock_irqsave(&emu->emu_lock, flags);
 			outl(val, emu->port + (reg & 0xfffffffc));
 			spin_unlock_irqrestore(&emu->emu_lock, flags);
@@ -474,7 +498,7 @@
 	while (!snd_info_get_line(buffer, line, sizeof(line))) {
 		if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
 			continue;
-		if ((reg < 0xa0) && (reg >=0) && (val <= 0xffffffff) && (channel_id >=0) && (channel_id <= 3) )
+		if ((reg < 0xa0) && (reg >= 0) && (val <= 0xffffffff) && (channel_id >= 0) && (channel_id <= 3) )
 			snd_ptr_write(emu, iobase, reg, channel_id, val);
 	}
 }
@@ -531,6 +555,10 @@
 {
 	struct snd_info_entry *entry;
 #ifdef CONFIG_SND_DEBUG
+	if ((emu->card_capabilities->emu1010) &&
+	     snd_card_proc_new(emu->card, "emu1010_regs", &entry)) {
+		snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read);
+	}
 	if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
 		snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read);
 		entry->c.text.write = snd_emu_proc_io_reg_write;
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index 029e785..116e1c8 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -30,6 +30,7 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 #include <linux/delay.h>
+#include "p17v.h"
 
 unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
 {
@@ -167,6 +168,109 @@
 	return 0;
 }
 
+/* The ADC does not support i2c read, so only write is implemented */
+int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
+				u32 reg,
+				u32 value)
+{
+	u32 tmp;
+	int timeout = 0;
+	int status;
+	int retry;
+	if ((reg > 0x7f) || (value > 0x1ff)) {
+		snd_printk(KERN_ERR "i2c_write: invalid values.\n");
+		return -EINVAL;
+	}
+
+	tmp = reg << 25 | value << 16;
+	// snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
+	/* Not sure what this I2C channel controls. */
+	/* snd_emu10k1_ptr_write(emu, P17V_I2C_0, 0, tmp); */
+
+	/* This controls the I2C connected to the WM8775 ADC Codec */
+	snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);
+	tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */
+
+	for (retry = 0; retry < 10; retry++) {
+		/* Send the data to i2c */
+		//tmp = snd_emu10k1_ptr_read(emu, P17V_I2C_ADDR, 0);
+		//tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
+		tmp = 0;
+		tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
+		snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp);
+
+		/* Wait till the transaction ends */
+		while (1) {
+			udelay(10);
+			status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);
+                	// snd_printk("I2C:status=0x%x\n", status);
+			timeout++;
+			if ((status & I2C_A_ADC_START) == 0)
+				break;
+
+			if (timeout > 1000) {
+                		snd_printk("emu10k1:I2C:timeout status=0x%x\n", status);
+				break;
+			}
+		}
+		//Read back and see if the transaction is successful
+		if ((status & I2C_A_ADC_ABORT) == 0)
+			break;
+	}
+
+	if (retry == 10) {
+		snd_printk(KERN_ERR "Writing to ADC failed!\n");
+		return -EINVAL;
+	}
+    
+    	return 0;
+}
+
+int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
+{
+	if (reg < 0 || reg > 0x3f)
+		return 1;
+	reg += 0x40; /* 0x40 upwards are registers. */
+	if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */
+		return 1;
+	outl(reg, emu->port + A_IOCFG);
+	udelay(10);
+	outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
+	udelay(10);
+	outl(value, emu->port + A_IOCFG);
+	udelay(10);
+	outl(value | 0x80 , emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
+
+	return 0;
+}
+
+int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value)
+{
+	if (reg < 0 || reg > 0x3f)
+		return 1;
+	reg += 0x40; /* 0x40 upwards are registers. */
+	outl(reg, emu->port + A_IOCFG);
+	udelay(10);
+	outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
+	udelay(10);
+	*value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f);
+
+	return 0;
+}
+
+/* Each Destination has one and only one Source,
+ * but one Source can feed any number of Destinations simultaneously.
+ */
+int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src)
+{
+	snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) );
+	snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) );
+	snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) );
+	snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) );
+
+	return 0;
+}
+
 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
 {
 	unsigned long flags;
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index 4e0f954..465f8d5 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -253,7 +253,7 @@
 	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
 	//struct snd_pcm_runtime *runtime = substream->runtime;
 	//struct snd_emu10k1_pcm *epcm = runtime->private_data;
-	emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
+	emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0;
 	/* FIXME: maybe zero others */
 	return 0;
 }
@@ -264,7 +264,7 @@
 	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
 	//struct snd_pcm_runtime *runtime = substream->runtime;
 	//struct snd_emu10k1_pcm *epcm = runtime->private_data;
-	emu->p16v_capture_voice.use=0;
+	emu->p16v_capture_voice.use = 0;
 	/* FIXME: maybe zero others */
 	return 0;
 }
@@ -349,7 +349,7 @@
 	  break;
 	}
 	/* FIXME: Check emu->buffer.size before actually writing to it. */
-	for(i=0; i < runtime->periods; i++) {
+	for(i = 0; i < runtime->periods; i++) {
 		table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
 		table_base[(i*2)+1]=period_size_bytes<<16;
 	}
@@ -394,7 +394,7 @@
 	/* FIXME: Check emu->buffer.size before actually writing to it. */
 	snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
 	snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
-	snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
+	snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size) << 16); // buffer size in bytes
 	snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
 	//snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
 	//snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
@@ -437,7 +437,7 @@
         struct snd_pcm_substream *s;
 	u32 basic = 0;
 	u32 inte = 0;
-	int running=0;
+	int running = 0;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -445,7 +445,7 @@
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	default:
-		running=0;
+		running = 0;
 		break;
 	}
         snd_pcm_group_for_each(pos, substream) {
@@ -785,7 +785,7 @@
 	}
         return change;
 }
-static DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
+static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
 
 #define P16V_VOL(xname,xreg,xhl) { \
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
diff --git a/sound/pci/emu10k1/p17v.h b/sound/pci/emu10k1/p17v.h
index 7ddb5be..4ef5f68 100644
--- a/sound/pci/emu10k1/p17v.h
+++ b/sound/pci/emu10k1/p17v.h
@@ -43,6 +43,53 @@
 #define P17V_I2C_ADDR		0x3d	/* I2C Address */
 #define P17V_I2C_0		0x3e	/* I2C Data */
 #define P17V_I2C_1		0x3f	/* I2C Data */
+/* I2C values */
+#define I2C_A_ADC_ADD_MASK	0x000000fe	/*The address is a 7 bit address */
+#define I2C_A_ADC_RW_MASK	0x00000001	/*bit mask for R/W */
+#define I2C_A_ADC_TRANS_MASK	0x00000010  	/*Bit mask for I2c address DAC value  */
+#define I2C_A_ADC_ABORT_MASK	0x00000020	/*Bit mask for I2C transaction abort flag */
+#define I2C_A_ADC_LAST_MASK	0x00000040	/*Bit mask for Last word transaction */
+#define I2C_A_ADC_BYTE_MASK	0x00000080	/*Bit mask for Byte Mode */
+
+#define I2C_A_ADC_ADD		0x00000034	/*This is the Device address for ADC  */
+#define I2C_A_ADC_READ		0x00000001	/*To perform a read operation */
+#define I2C_A_ADC_START		0x00000100	/*Start I2C transaction */
+#define I2C_A_ADC_ABORT		0x00000200	/*I2C transaction abort */
+#define I2C_A_ADC_LAST		0x00000400	/*I2C last transaction */
+#define I2C_A_ADC_BYTE		0x00000800	/*I2C one byte mode */
+
+#define I2C_D_ADC_REG_MASK	0xfe000000  	/*ADC address register */ 
+#define I2C_D_ADC_DAT_MASK	0x01ff0000  	/*ADC data register */
+
+#define ADC_TIMEOUT		0x00000007	/*ADC Timeout Clock Disable */
+#define ADC_IFC_CTRL		0x0000000b	/*ADC Interface Control */
+#define ADC_MASTER		0x0000000c	/*ADC Master Mode Control */
+#define ADC_POWER		0x0000000d	/*ADC PowerDown Control */
+#define ADC_ATTEN_ADCL		0x0000000e	/*ADC Attenuation ADCL */
+#define ADC_ATTEN_ADCR		0x0000000f	/*ADC Attenuation ADCR */
+#define ADC_ALC_CTRL1		0x00000010	/*ADC ALC Control 1 */
+#define ADC_ALC_CTRL2		0x00000011	/*ADC ALC Control 2 */
+#define ADC_ALC_CTRL3		0x00000012	/*ADC ALC Control 3 */
+#define ADC_NOISE_CTRL		0x00000013	/*ADC Noise Gate Control */
+#define ADC_LIMIT_CTRL		0x00000014	/*ADC Limiter Control */
+#define ADC_MUX			0x00000015  	/*ADC Mux offset */
+#if 0
+/* FIXME: Not tested yet. */
+#define ADC_GAIN_MASK		0x000000ff	//Mask for ADC Gain
+#define ADC_ZERODB		0x000000cf	//Value to set ADC to 0dB
+#define ADC_MUTE_MASK		0x000000c0	//Mask for ADC mute
+#define ADC_MUTE		0x000000c0	//Value to mute ADC
+#define ADC_OSR			0x00000008	//Mask for ADC oversample rate select
+#define ADC_TIMEOUT_DISABLE	0x00000008	//Value and mask to disable Timeout clock
+#define ADC_HPF_DISABLE		0x00000100	//Value and mask to disable High pass filter
+#define ADC_TRANWIN_MASK	0x00000070	//Mask for Length of Transient Window
+#endif
+
+#define ADC_MUX_MASK		0x0000000f	//Mask for ADC Mux
+#define ADC_MUX_0		0x00000001	//Value to select Unknown at ADC Mux (Not used)
+#define ADC_MUX_1		0x00000002	//Value to select Unknown at ADC Mux (Not used)
+#define ADC_MUX_2		0x00000004	//Value to select Mic at ADC Mux
+#define ADC_MUX_3		0x00000008	//Value to select Line-In at ADC Mux
 
 #define P17V_START_AUDIO	0x40	/* Start Audio bit */
 /* 41 - 47: Reserved */
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
index 94eca82..1db50fe 100644
--- a/sound/pci/emu10k1/voice.c
+++ b/sound/pci/emu10k1/voice.c
@@ -83,7 +83,7 @@
 	if (first_voice == last_voice)
 		return -ENOMEM;
 	
-	for (i=0; i < number; i++) {
+	for (i = 0; i < number; i++) {
 		voice = &emu->voices[(first_voice + i) % NUM_G];
 		// printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number);
 		voice->use = 1;
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index a84f6b2..425b167 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -413,8 +413,6 @@
 	} u;
 
 	struct pci_dev *pci;
-	unsigned short subsystem_vendor_id;
-	unsigned short subsystem_device_id;
 	struct snd_card *card;
 	struct snd_pcm *pcm1;	/* DAC1/ADC PCM */
 	struct snd_pcm *pcm2;	/* DAC2 PCM */
@@ -1607,11 +1605,26 @@
 	ensoniq->u.es1371.ac97 = NULL;
 }
 
-static struct {
+struct es1371_quirk {
 	unsigned short vid;		/* vendor ID */
 	unsigned short did;		/* device ID */
 	unsigned char rev;		/* revision */
-} es1371_spdif_present[] __devinitdata = {
+};
+
+static int __devinit es1371_quirk_lookup(struct ensoniq *ensoniq,
+					 struct es1371_quirk *list)
+{
+	while (list->vid != (unsigned short)PCI_ANY_ID) {
+		if (ensoniq->pci->vendor == list->vid &&
+		    ensoniq->pci->device == list->did &&
+		    ensoniq->rev == list->rev)
+			return 1;
+		list++;
+	}
+	return 0;
+}
+
+static struct es1371_quirk es1371_spdif_present[] __devinitdata = {
 	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
 	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
 	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@@ -1620,12 +1633,19 @@
 	{ .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
 };
 
-static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int has_line)
+static struct snd_pci_quirk ens1373_line_quirk[] __devinitdata = {
+	SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */
+	SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */
+	{ } /* end */
+};
+
+static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
+					    int has_spdif, int has_line)
 {
 	struct snd_card *card = ensoniq->card;
 	struct snd_ac97_bus *pbus;
 	struct snd_ac97_template ac97;
-	int err, idx;
+	int err;
 	static struct snd_ac97_bus_ops ops = {
 		.write = snd_es1371_codec_write,
 		.read = snd_es1371_codec_read,
@@ -1641,33 +1661,28 @@
 	ac97.scaps = AC97_SCAP_AUDIO;
 	if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0)
 		return err;
-	for (idx = 0; es1371_spdif_present[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
-		if ((ensoniq->pci->vendor == es1371_spdif_present[idx].vid &&
-		     ensoniq->pci->device == es1371_spdif_present[idx].did &&
-		     ensoniq->rev == es1371_spdif_present[idx].rev) || has_spdif > 0) {
-		    	struct snd_kcontrol *kctl;
-			int i, index = 0; 
+	if (has_spdif > 0 ||
+	    (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) {
+		struct snd_kcontrol *kctl;
+		int i, index = 0;
 
-                        if (has_spdif < 0)
-                                break;
+		ensoniq->spdif_default = ensoniq->spdif_stream =
+			SNDRV_PCM_DEFAULT_CON_SPDIF;
+		outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
 
-			ensoniq->spdif_default = ensoniq->spdif_stream =
-				SNDRV_PCM_DEFAULT_CON_SPDIF;
-			outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
+		if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
+			index++;
 
-		    	if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
-			    	index++;
-
-			for (i = 0; i < (int)ARRAY_SIZE(snd_es1371_mixer_spdif); i++) {
-				kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq);
-				if (! kctl)
-					return -ENOMEM;
-				kctl->id.index = index;
-				if ((err = snd_ctl_add(card, kctl)) < 0)
-					return err;
-			}
-			break;
+		for (i = 0; i < ARRAY_SIZE(snd_es1371_mixer_spdif); i++) {
+			kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq);
+			if (!kctl)
+				return -ENOMEM;
+			kctl->id.index = index;
+			err = snd_ctl_add(card, kctl);
+			if (err < 0)
+				return err;
 		}
+	}
 	if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SDAC) {
 		/* mirror rear to front speakers */
 		ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT24);
@@ -1676,12 +1691,10 @@
 		if (err < 0)
 			return err;
 	}
-	if (((ensoniq->subsystem_vendor_id == 0x1274) &&
-	    (ensoniq->subsystem_device_id == 0x2000)) || /* GA-7DXR */
-	    ((ensoniq->subsystem_vendor_id == 0x1458) &&
-	    (ensoniq->subsystem_device_id == 0xa000)) || /* GA-8IEXP */
-	    has_line > 0) {
-		 err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line, ensoniq));
+	if (has_line > 0 ||
+	    snd_pci_quirk_lookup(ensoniq->pci, ens1373_line_quirk)) {
+		 err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line,
+						      ensoniq));
 		 if (err < 0)
 			 return err;
 	}
@@ -1956,21 +1969,15 @@
 }
 
 #ifdef CHIP1371
-static struct {
-	unsigned short svid;		/* subsystem vendor ID */
-	unsigned short sdid;		/* subsystem device ID */
-} es1371_amplifier_hack[] = {
-	{ .svid = 0x107b, .sdid = 0x2150 },	/* Gateway Solo 2150 */
-	{ .svid = 0x13bd, .sdid = 0x100c },	/* EV1938 on Mebius PC-MJ100V */
-	{ .svid = 0x1102, .sdid = 0x5938 },	/* Targa Xtender300 */
-	{ .svid = 0x1102, .sdid = 0x8938 },	/* IPC Topnote G notebook */
-	{ .svid = PCI_ANY_ID, .sdid = PCI_ANY_ID }
+static struct snd_pci_quirk es1371_amplifier_hack[] __devinitdata = {
+	SND_PCI_QUIRK_ID(0x107b, 0x2150),	/* Gateway Solo 2150 */
+	SND_PCI_QUIRK_ID(0x13bd, 0x100c),	/* EV1938 on Mebius PC-MJ100V */
+	SND_PCI_QUIRK_ID(0x1102, 0x5938),	/* Targa Xtender300 */
+	SND_PCI_QUIRK_ID(0x1102, 0x8938),	/* IPC Topnote G notebook */
+	{ } /* end */
 };
-static struct {
-	unsigned short vid;		/* vendor ID */
-	unsigned short did;		/* device ID */
-	unsigned char rev;		/* revision */
-} es1371_ac97_reset_hack[] = {
+
+static struct es1371_quirk es1371_ac97_reset_hack[] = {
 	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
 	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
 	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@@ -1984,7 +1991,6 @@
 {
 #ifdef CHIP1371
 	int idx;
-	struct pci_dev *pci = ensoniq->pci;
 #endif
 	/* this code was part of snd_ensoniq_create before intruduction
 	  * of suspend/resume
@@ -1999,16 +2005,12 @@
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
 	outl(0, ES_REG(ensoniq, 1371_LEGACY));
-	for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
-		if (pci->vendor == es1371_ac97_reset_hack[idx].vid &&
-		    pci->device == es1371_ac97_reset_hack[idx].did &&
-		    ensoniq->rev == es1371_ac97_reset_hack[idx].rev) {
-			outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
-			/* need to delay around 20ms(bleech) to give
-			some CODECs enough time to wakeup */
-			msleep(20);
-			break;
-		}
+	if (es1371_quirk_lookup(ensoniq, es1371_ac97_reset_hack)) {
+	    outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
+	    /* need to delay around 20ms(bleech) to give
+	       some CODECs enough time to wakeup */
+	    msleep(20);
+	}
 	/* AC'97 warm reset to start the bitclk */
 	outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL));
 	inl(ES_REG(ensoniq, CONTROL));
@@ -2112,11 +2114,7 @@
 				     struct ensoniq ** rensoniq)
 {
 	struct ensoniq *ensoniq;
-	unsigned short cmdw;
 	unsigned char cmdb;
-#ifdef CHIP1371
-	int idx;
-#endif
 	int err;
 	static struct snd_device_ops ops = {
 		.dev_free =	snd_ensoniq_dev_free,
@@ -2159,10 +2157,6 @@
 	pci_set_master(pci);
 	pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb);
 	ensoniq->rev = cmdb;
-	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &cmdw);
-	ensoniq->subsystem_vendor_id = cmdw;
-	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &cmdw);
-	ensoniq->subsystem_device_id = cmdw;
 #ifdef CHIP1370
 #if 0
 	ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE |
@@ -2175,19 +2169,11 @@
 	ensoniq->ctrl = 0;
 	ensoniq->sctrl = 0;
 	ensoniq->cssr = 0;
-	for (idx = 0; es1371_amplifier_hack[idx].svid != (unsigned short)PCI_ANY_ID; idx++)
-		if (ensoniq->subsystem_vendor_id == es1371_amplifier_hack[idx].svid &&
-		    ensoniq->subsystem_device_id == es1371_amplifier_hack[idx].sdid) {
-			ensoniq->ctrl |= ES_1371_GPIO_OUT(1);	/* turn amplifier on */
-			break;
-		}
-	for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
-		if (pci->vendor == es1371_ac97_reset_hack[idx].vid &&
-		    pci->device == es1371_ac97_reset_hack[idx].did &&
-		    ensoniq->rev == es1371_ac97_reset_hack[idx].rev) {
-			ensoniq->cssr |= ES_1371_ST_AC97_RST;
-			break;
-		}
+	if (snd_pci_quirk_lookup(pci, es1371_amplifier_hack))
+		ensoniq->ctrl |= ES_1371_GPIO_OUT(1);	/* turn amplifier on */
+
+	if (es1371_quirk_lookup(ensoniq, es1371_ac97_reset_hack))
+		ensoniq->cssr |= ES_1371_ST_AC97_RST;
 #endif
 
 	snd_ensoniq_chip_init(ensoniq);
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 66ac26c..fec29a1 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1344,7 +1344,7 @@
 	8, 15, TLV_DB_SCALE_ITEM(-750, 150, 0),
 };
 
-static DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0);
 
 static struct snd_kcontrol_new snd_es1938_controls[] = {
 ES1938_DOUBLE_TLV("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0,
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index b7b361c..6dc578b 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1157,7 +1157,7 @@
 	return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val);
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0);
 
 #define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls)
 
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index dbacba6..60d7b05 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,5 +1,14 @@
 snd-hda-intel-objs := hda_intel.o
-snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o patch_atihdmi.o
+snd-hda-codec-objs := hda_codec.o \
+	hda_generic.o \
+	patch_realtek.o \
+	patch_cmedia.o \
+	patch_analog.o \
+	patch_sigmatel.o \
+	patch_si3054.o \
+	patch_atihdmi.o \
+	patch_conexant.o \
+	patch_via.o
 ifdef CONFIG_PROC_FS
 snd-hda-codec-objs += hda_proc.o
 endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 18bbc87..8f34fb4 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -52,6 +52,7 @@
 static struct hda_vendor_id hda_vendor_ids[] = {
 	{ 0x10ec, "Realtek" },
 	{ 0x1057, "Motorola" },
+	{ 0x1106, "VIA" },
 	{ 0x11d4, "Analog Devices" },
 	{ 0x13f6, "C-Media" },
 	{ 0x14f1, "Conexant" },
@@ -262,7 +263,7 @@
 	unsol->queue[wp] = res;
 	unsol->queue[wp + 1] = res_ex;
 
-	queue_work(unsol->workq, &unsol->work);
+	schedule_work(&unsol->work);
 
 	return 0;
 }
@@ -309,12 +310,6 @@
 		snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
 		return -ENOMEM;
 	}
-	unsol->workq = create_singlethread_workqueue("hda_codec");
-	if (! unsol->workq) {
-		snd_printk(KERN_ERR "hda_codec: can't create workqueue\n");
-		kfree(unsol);
-		return -ENOMEM;
-	}
 	INIT_WORK(&unsol->work, process_unsol_events);
 	unsol->bus = bus;
 	bus->unsol = unsol;
@@ -333,7 +328,7 @@
 	if (! bus)
 		return 0;
 	if (bus->unsol) {
-		destroy_workqueue(bus->unsol->workq);
+		flush_scheduled_work();
 		kfree(bus->unsol);
 	}
 	list_for_each_safe(p, n, &bus->codec_list) {
@@ -1714,6 +1709,8 @@
 /**
  * snd_hda_check_board_config - compare the current codec with the config table
  * @codec: the HDA codec
+ * @num_configs: number of config enums
+ * @models: array of model name strings
  * @tbl: configuration table, terminated by null entries
  *
  * Compares the modelname or PCI subsystem id of the current codec with the
@@ -1722,33 +1719,44 @@
  *
  * If no entries are matching, the function returns a negative value.
  */
-int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl)
+int snd_hda_check_board_config(struct hda_codec *codec,
+			       int num_configs, const char **models,
+			       const struct snd_pci_quirk *tbl)
 {
-	const struct hda_board_config *c;
-
-	if (codec->bus->modelname) {
-		for (c = tbl; c->modelname || c->pci_subvendor; c++) {
-			if (c->modelname &&
-			    ! strcmp(codec->bus->modelname, c->modelname)) {
-				snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname);
-				return c->config;
+	if (codec->bus->modelname && models) {
+		int i;
+		for (i = 0; i < num_configs; i++) {
+			if (models[i] &&
+			    !strcmp(codec->bus->modelname, models[i])) {
+				snd_printd(KERN_INFO "hda_codec: model '%s' is "
+					   "selected\n", models[i]);
+				return i;
 			}
 		}
 	}
 
-	if (codec->bus->pci) {
-		u16 subsystem_vendor, subsystem_device;
-		pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
-		pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device);
-		for (c = tbl; c->modelname || c->pci_subvendor; c++) {
-			if (c->pci_subvendor == subsystem_vendor &&
-			    (! c->pci_subdevice /* all match */||
-			     (c->pci_subdevice == subsystem_device))) {
-				snd_printdd(KERN_INFO "hda_codec: PCI %x:%x, codec config %d is selected\n",
-					    subsystem_vendor, subsystem_device, c->config);
-				return c->config;
-			}
+	if (!codec->bus->pci || !tbl)
+		return -1;
+
+	tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
+	if (!tbl)
+		return -1;
+	if (tbl->value >= 0 && tbl->value < num_configs) {
+#ifdef CONFIG_SND_DEBUG_DETECT
+		char tmp[10];
+		const char *model = NULL;
+		if (models)
+			model = models[tbl->value];
+		if (!model) {
+			sprintf(tmp, "#%d", tbl->value);
+			model = tmp;
 		}
+		snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
+			    "for config %x:%x (%s)\n",
+			    model, tbl->subvendor, tbl->subdevice,
+			    (tbl->name ? tbl->name : "Unknown device"));
+#endif
+		return tbl->value;
 	}
 	return -1;
 }
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 1a7e821..b9a8e23 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -199,7 +199,7 @@
 
 /* STATESTS int mask: SD2,SD1,SD0 */
 #define STATESTS_INT_MASK	0x07
-#define AZX_MAX_CODECS		4
+#define AZX_MAX_CODECS		3
 
 /* SD_CTL bits */
 #define SD_CTL_STREAM_RESET	0x01	/* stream reset bit */
@@ -1285,7 +1285,7 @@
 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci),
-					      1024 * 64, 1024 * 128);
+					      1024 * 64, 1024 * 1024);
 	chip->pcm[pcm_dev] = pcm;
 	if (chip->pcm_devs < pcm_dev + 1)
 		chip->pcm_devs = pcm_dev + 1;
@@ -1391,6 +1391,7 @@
 		return -1;
 	}
 	chip->irq = chip->pci->irq;
+	pci_intx(chip->pci, !chip->msi);
 	return 0;
 }
 
@@ -1502,6 +1503,31 @@
 }
 
 /*
+ * white/black-listing for position_fix
+ */
+static const struct snd_pci_quirk position_fix_list[] __devinitdata = {
+	SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
+	{}
+};
+
+static int __devinit check_position_fix(struct azx *chip, int fix)
+{
+	const struct snd_pci_quirk *q;
+
+	if (fix == POS_FIX_AUTO) {
+		q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
+		if (q) {
+			snd_printdd(KERN_INFO
+				    "hda_intel: position_fix set to %d "
+				    "for device %04x:%04x\n",
+				    q->value, q->subvendor, q->subdevice);
+			return q->value;
+		}
+	}
+	return fix;
+}
+
+/*
  * constructor
  */
 static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
@@ -1535,7 +1561,8 @@
 	chip->driver_type = driver_type;
 	chip->msi = enable_msi;
 
-	chip->position_fix = position_fix;
+	chip->position_fix = check_position_fix(chip, position_fix);
+
 	chip->single_cmd = single_cmd;
 
 #if BITS_PER_LONG != 64
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 9ca1baf..39718d6 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -173,14 +173,9 @@
 /*
  * Misc
  */
-struct hda_board_config {
-	const char *modelname;
-	int config;
-	unsigned short pci_subvendor;
-	unsigned short pci_subdevice;
-};
-
-int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl);
+int snd_hda_check_board_config(struct hda_codec *codec, int num_configs,
+			       const char **modelnames,
+			       const struct snd_pci_quirk *pci_list);
 int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew);
 
 /*
@@ -204,7 +199,6 @@
 	unsigned int rp, wp;
 
 	/* workqueue */
-	struct workqueue_struct *workq;
 	struct work_struct work;
 	struct hda_bus *bus;
 };
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index 0b66879..9f9e9ae 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -14,6 +14,10 @@
 extern struct hda_codec_preset snd_hda_preset_si3054[];
 /* ATI HDMI codecs */
 extern struct hda_codec_preset snd_hda_preset_atihdmi[];
+/* Conexant audio codec */
+extern struct hda_codec_preset snd_hda_preset_conexant[];
+/* VIA codecs */
+extern struct hda_codec_preset snd_hda_preset_via[];
 
 static const struct hda_codec_preset *hda_preset_tables[] = {
 	snd_hda_preset_realtek,
@@ -22,5 +26,7 @@
 	snd_hda_preset_sigmatel,
 	snd_hda_preset_si3054,
 	snd_hda_preset_atihdmi,
+	snd_hda_preset_conexant,
+	snd_hda_preset_via,
 	NULL
 };
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 076365b..38977bc 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -782,54 +782,63 @@
 
 /* eapd initialization */
 static struct hda_verb ad1986a_eapd_init_verbs[] = {
-	{0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00},
+	{0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
 	{}
 };
 
-/* models */
-enum { AD1986A_6STACK, AD1986A_3STACK, AD1986A_LAPTOP, AD1986A_LAPTOP_EAPD };
+/* Ultra initialization */
+static struct hda_verb ad1986a_ultra_init[] = {
+	/* eapd initialization */
+	{ 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
+	/* CLFE -> Mic in */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
+	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	{ 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+	{ } /* end */
+};
 
-static struct hda_board_config ad1986a_cfg_tbl[] = {
-	{ .modelname = "6stack",	.config = AD1986A_6STACK },
-	{ .modelname = "3stack",	.config = AD1986A_3STACK },
-	{ .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84,
-	  .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x817f,
-	  .config = AD1986A_3STACK }, /* ASUS P5P-L2 */
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3,
-	  .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x81cb,
-	  .config = AD1986A_3STACK }, /* ASUS M2NPV-VM */
-	{ .modelname = "laptop",	.config = AD1986A_LAPTOP },
-	{ .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e,
-	  .config = AD1986A_LAPTOP }, /* FSC V2060 */
-	{ .pci_subvendor = 0x17c0, .pci_subdevice = 0x2017,
-	  .config = AD1986A_LAPTOP }, /* Samsung M50 */
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x818f,
-	  .config = AD1986A_LAPTOP }, /* ASUS P5GV-MX */
-	{ .modelname = "laptop-eapd",	.config = AD1986A_LAPTOP_EAPD },
-	{ .pci_subvendor = 0x144d, .pci_subdevice = 0xc023,
-	  .config = AD1986A_LAPTOP_EAPD }, /* Samsung X60 Chane */
-	{ .pci_subvendor = 0x144d, .pci_subdevice = 0xc024,
-	  .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */
-	{ .pci_subvendor = 0x144d, .pci_subdevice = 0xc026,
-	  .config = AD1986A_LAPTOP_EAPD }, /* Samsung X11-T2300 Culesa */
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1153,
-	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */
-	{ .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 = 0x1043, .pci_subdevice = 0x1263,
-	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5F */
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1297,
-	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x12b3,
-	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS V1j */
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x30af,
-	  .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */
-	{ .pci_subvendor = 0x17aa, .pci_subdevice = 0x2066,
-	  .config = AD1986A_LAPTOP_EAPD }, /* Lenovo 3000 N100-07684JU */
+/* models */
+enum {
+	AD1986A_6STACK,
+	AD1986A_3STACK,
+	AD1986A_LAPTOP,
+	AD1986A_LAPTOP_EAPD,
+	AD1986A_ULTRA,
+	AD1986A_MODELS
+};
+
+static const char *ad1986a_models[AD1986A_MODELS] = {
+	[AD1986A_6STACK]	= "6stack",
+	[AD1986A_3STACK]	= "3stack",
+	[AD1986A_LAPTOP]	= "laptop",
+	[AD1986A_LAPTOP_EAPD]	= "laptop-eapd",
+	[AD1986A_ULTRA]		= "ultra",
+};
+
+static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
+	SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
+	SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
+	SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
+	SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
+	SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
+	SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
+	SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
+	SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
+	SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
+	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
 	{}
 };
 
@@ -861,7 +870,9 @@
 	codec->patch_ops = ad198x_patch_ops;
 
 	/* override some parameters */
-	board_config = snd_hda_check_board_config(codec, ad1986a_cfg_tbl);
+	board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
+						  ad1986a_models,
+						  ad1986a_cfg_tbl);
 	switch (board_config) {
 	case AD1986A_3STACK:
 		spec->num_mixers = 2;
@@ -891,6 +902,15 @@
 		spec->multiout.dig_out_nid = 0;
 		spec->input_mux = &ad1986a_laptop_eapd_capture_source;
 		break;
+	case AD1986A_ULTRA:
+		spec->mixers[0] = ad1986a_laptop_eapd_mixers;
+		spec->num_init_verbs = 2;
+		spec->init_verbs[1] = ad1986a_ultra_init;
+		spec->multiout.max_channels = 2;
+		spec->multiout.num_dacs = 1;
+		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
+		spec->multiout.dig_out_nid = 0;
+		break;
 	}
 
 	return 0;
@@ -1391,20 +1411,27 @@
 };
 
 /* models */
-enum { AD1981_BASIC, AD1981_HP, AD1981_THINKPAD };
+enum {
+	AD1981_BASIC,
+	AD1981_HP,
+	AD1981_THINKPAD,
+	AD1981_MODELS
+};
 
-static struct hda_board_config ad1981_cfg_tbl[] = {
-	{ .modelname = "hp", .config = AD1981_HP },
+static const char *ad1981_models[AD1981_MODELS] = {
+	[AD1981_HP]		= "hp",
+	[AD1981_THINKPAD]	= "thinkpad",
+	[AD1981_BASIC]		= "basic",
+};
+
+static struct snd_pci_quirk ad1981_cfg_tbl[] = {
 	/* All HP models */
-	{ .pci_subvendor = 0x103c, .config = AD1981_HP },
-	{ .pci_subvendor = 0x30b0, .pci_subdevice = 0x103c,
-	  .config = AD1981_HP }, /* HP nx6320 (reversed SSID, H/W bug) */
-	{ .modelname = "thinkpad", .config = AD1981_THINKPAD },
+	SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP),
+	/* HP nx6320 (reversed SSID, H/W bug) */
+	SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
 	/* Lenovo Thinkpad T60/X60/Z6xx */
-	{ .pci_subvendor = 0x17aa, .config = AD1981_THINKPAD },
-	{ .pci_subvendor = 0x1014, .pci_subdevice = 0x0597,
-	  .config = AD1981_THINKPAD }, /* Z60m/t */
-	{ .modelname = "basic", .config = AD1981_BASIC },
+	SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD),
+	SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
 	{}
 };
 
@@ -1437,7 +1464,9 @@
 	codec->patch_ops = ad198x_patch_ops;
 
 	/* override some parameters */
-	board_config = snd_hda_check_board_config(codec, ad1981_cfg_tbl);
+	board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
+						  ad1981_models,
+						  ad1981_cfg_tbl);
 	switch (board_config) {
 	case AD1981_HP:
 		spec->mixers[0] = ad1981_hp_mixers;
@@ -2565,15 +2594,14 @@
 /*
  */
 
-static struct hda_board_config ad1988_cfg_tbl[] = {
-	{ .modelname = "6stack",	.config = AD1988_6STACK },
-	{ .modelname = "6stack-dig",	.config = AD1988_6STACK_DIG },
-	{ .modelname = "3stack",	.config = AD1988_3STACK },
-	{ .modelname = "3stack-dig",	.config = AD1988_3STACK_DIG },
-	{ .modelname = "laptop",	.config = AD1988_LAPTOP },
-	{ .modelname = "laptop-dig",	.config = AD1988_LAPTOP_DIG },
-	{ .modelname = "auto",		.config = AD1988_AUTO },
-	{}
+static const char *ad1988_models[AD1988_MODEL_LAST] = {
+	[AD1988_6STACK]		= "6stack",
+	[AD1988_6STACK_DIG]	= "6stack-dig",
+	[AD1988_3STACK]		= "3stack",
+	[AD1988_3STACK_DIG]	= "3stack-dig",
+	[AD1988_LAPTOP]		= "laptop",
+	[AD1988_LAPTOP_DIG]	= "laptop-dig",
+	[AD1988_AUTO]		= "auto",
 };
 
 static int patch_ad1988(struct hda_codec *codec)
@@ -2591,8 +2619,9 @@
 	if (is_rev2(codec))
 		snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
 
-	board_config = snd_hda_check_board_config(codec, ad1988_cfg_tbl);
-	if (board_config < 0 || board_config >= AD1988_MODEL_LAST) {
+	board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
+						  ad1988_models, NULL);
+	if (board_config < 0) {
 		printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
 		board_config = AD1988_AUTO;
 	}
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index d38ce22..5b9d3a3 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -40,6 +40,7 @@
 	CMI_FULL_DIG,	/* back 6-jack + front-panel 2-jack + digital I/O */
 	CMI_ALLOUT,	/* back 5-jack + front-panel 2-jack + digital out */
 	CMI_AUTO,	/* let driver guess it */
+	CMI_MODELS
 };
 
 struct cmi_spec {
@@ -603,14 +604,17 @@
 /*
  */
 
-static struct hda_board_config cmi9880_cfg_tbl[] = {
-	{ .modelname = "minimal", .config = CMI_MINIMAL },
-	{ .modelname = "min_fp", .config = CMI_MIN_FP },
-	{ .modelname = "full", .config = CMI_FULL },
-	{ .modelname = "full_dig", .config = CMI_FULL_DIG },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x813d, .config = CMI_FULL_DIG }, /* ASUS P5AD2 */
-	{ .modelname = "allout", .config = CMI_ALLOUT },
-	{ .modelname = "auto", .config = CMI_AUTO },
+static const char *cmi9880_models[CMI_MODELS] = {
+	[CMI_MINIMAL]	= "minimal",
+	[CMI_MIN_FP]	= "min_fp",
+	[CMI_FULL]	= "full",
+	[CMI_FULL_DIG]	= "full_dig",
+	[CMI_ALLOUT]	= "allout",
+	[CMI_AUTO]	= "auto",
+};
+
+static struct snd_pci_quirk cmi9880_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG),
 	{} /* terminator */
 };
 
@@ -633,7 +637,9 @@
 		return -ENOMEM;
 
 	codec->spec = spec;
-	spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl);
+	spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS,
+							cmi9880_models,
+							cmi9880_cfg_tbl);
 	if (spec->board_config < 0) {
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
 		spec->board_config = CMI_AUTO; /* try everything */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
new file mode 100644
index 0000000..23a1c75
--- /dev/null
+++ b/sound/pci/hda/patch_conexant.c
@@ -0,0 +1,1410 @@
+/*
+ * HD audio interface patch for Conexant HDA audio codec
+ *
+ * Copyright (c) 2006 Pototskiy Akex <alex.pototskiy@gmail.com>
+ * 		      Takashi Iwai <tiwai@suse.de>
+ * 		      Tobin Davis  <tdavis@dsl-only.net>
+ *
+ *  This driver 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 driver 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/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+#define CXT_PIN_DIR_IN              0x00
+#define CXT_PIN_DIR_OUT             0x01
+#define CXT_PIN_DIR_INOUT           0x02
+#define CXT_PIN_DIR_IN_NOMICBIAS    0x03
+#define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04
+
+#define CONEXANT_HP_EVENT	0x37
+#define CONEXANT_MIC_EVENT	0x38
+
+
+
+struct conexant_spec {
+
+	struct snd_kcontrol_new *mixers[5];
+	int num_mixers;
+
+	const struct hda_verb *init_verbs[5];	/* initialization verbs
+						 * don't forget NULL
+						 * termination!
+						 */
+	unsigned int num_init_verbs;
+
+	/* playback */
+	struct hda_multi_out multiout;	/* playback set-up
+					 * max_channels, dacs must be set
+					 * dig_out_nid and hp_nid are optional
+					 */
+	unsigned int cur_eapd;
+	unsigned int hp_present;
+	unsigned int need_dac_fix;
+
+	/* capture */
+	unsigned int num_adc_nids;
+	hda_nid_t *adc_nids;
+	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
+
+	/* capture source */
+	const struct hda_input_mux *input_mux;
+	hda_nid_t *capsrc_nids;
+	unsigned int cur_mux[3];
+
+	/* channel model */
+	const struct hda_channel_mode *channel_mode;
+	int num_channel_mode;
+
+	/* PCM information */
+	struct hda_pcm pcm_rec[2];	/* used in build_pcms() */
+
+	struct mutex amp_mutex;	/* PCM volume/mute control mutex */
+	unsigned int spdif_route;
+
+	/* dynamic controls, init_verbs and input_mux */
+	struct auto_pin_cfg autocfg;
+	unsigned int num_kctl_alloc, num_kctl_used;
+	struct snd_kcontrol_new *kctl_alloc;
+	struct hda_input_mux private_imux;
+	hda_nid_t private_dac_nids[4];
+
+};
+
+static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      struct snd_pcm_substream *substream)
+{
+	struct conexant_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					 struct hda_codec *codec,
+					 unsigned int stream_tag,
+					 unsigned int format,
+					 struct snd_pcm_substream *substream)
+{
+	struct conexant_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
+						stream_tag,
+						format, substream);
+}
+
+static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					 struct hda_codec *codec,
+					 struct snd_pcm_substream *substream)
+{
+	struct conexant_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+					  struct hda_codec *codec,
+					  struct snd_pcm_substream *substream)
+{
+	struct conexant_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+					 struct hda_codec *codec,
+					 struct snd_pcm_substream *substream)
+{
+	struct conexant_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      unsigned int stream_tag,
+				      unsigned int format,
+				      struct snd_pcm_substream *substream)
+{
+	struct conexant_spec *spec = codec->spec;
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+				   stream_tag, 0, format);
+	return 0;
+}
+
+static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      struct snd_pcm_substream *substream)
+{
+	struct conexant_spec *spec = codec->spec;
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+				   0, 0, 0);
+	return 0;
+}
+
+
+
+static struct hda_pcm_stream conexant_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0, /* fill later */
+	.ops = {
+		.open = conexant_playback_pcm_open,
+		.prepare = conexant_playback_pcm_prepare,
+		.cleanup = conexant_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream conexant_pcm_analog_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0, /* fill later */
+	.ops = {
+		.prepare = conexant_capture_pcm_prepare,
+		.cleanup = conexant_capture_pcm_cleanup
+	},
+};
+
+
+static struct hda_pcm_stream conexant_pcm_digital_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0, /* fill later */
+	.ops = {
+		.open = conexant_dig_playback_pcm_open,
+		.close = conexant_dig_playback_pcm_close
+	},
+};
+
+static struct hda_pcm_stream conexant_pcm_digital_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in alc_build_pcms */
+};
+
+static int conexant_build_pcms(struct hda_codec *codec)
+{
+	struct conexant_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+
+	codec->num_pcms = 1;
+	codec->pcm_info = info;
+
+	info->name = "CONEXANT Analog";
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback;
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
+		spec->multiout.max_channels;
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+		spec->multiout.dac_nids[0];
+	info->stream[SNDRV_PCM_STREAM_CAPTURE] = conexant_pcm_analog_capture;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
+
+	if (spec->multiout.dig_out_nid) {
+		info++;
+		codec->num_pcms++;
+		info->name = "Conexant Digital";
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+			conexant_pcm_digital_playback;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+			spec->multiout.dig_out_nid;
+		if (spec->dig_in_nid) {
+			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+				conexant_pcm_digital_capture;
+			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
+				spec->dig_in_nid;
+		}
+	}
+
+	return 0;
+}
+
+static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol,
+	       			  struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct conexant_spec *spec = codec->spec;
+
+	return snd_hda_input_mux_info(spec->input_mux, uinfo);
+}
+
+static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct conexant_spec *spec = codec->spec;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+	return 0;
+}
+
+static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct conexant_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,
+				     spec->capsrc_nids[adc_idx],
+				     &spec->cur_mux[adc_idx]);
+}
+
+static int conexant_init(struct hda_codec *codec)
+{
+	struct conexant_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < spec->num_init_verbs; i++)
+		snd_hda_sequence_write(codec, spec->init_verbs[i]);
+	return 0;
+}
+
+static void conexant_free(struct hda_codec *codec)
+{
+        struct conexant_spec *spec = codec->spec;
+        unsigned int i;
+
+        if (spec->kctl_alloc) {
+                for (i = 0; i < spec->num_kctl_used; i++)
+                        kfree(spec->kctl_alloc[i].name);
+                kfree(spec->kctl_alloc);
+        }
+
+	kfree(codec->spec);
+}
+
+#ifdef CONFIG_PM
+static int conexant_resume(struct hda_codec *codec)
+{
+	struct conexant_spec *spec = codec->spec;
+	int i;
+
+	codec->patch_ops.init(codec);
+	for (i = 0; i < spec->num_mixers; i++)
+		snd_hda_resume_ctls(codec, spec->mixers[i]);
+	if (spec->multiout.dig_out_nid)
+		snd_hda_resume_spdif_out(codec);
+	if (spec->dig_in_nid)
+		snd_hda_resume_spdif_in(codec);
+	return 0;
+}
+#endif
+
+static int conexant_build_controls(struct hda_codec *codec)
+{
+	struct conexant_spec *spec = codec->spec;
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < spec->num_mixers; i++) {
+		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
+		if (err < 0)
+			return err;
+	}
+	if (spec->multiout.dig_out_nid) {
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid);
+		if (err < 0)
+			return err;
+	} 
+	if (spec->dig_in_nid) {
+		err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+static struct hda_codec_ops conexant_patch_ops = {
+	.build_controls = conexant_build_controls,
+	.build_pcms = conexant_build_pcms,
+	.init = conexant_init,
+	.free = conexant_free,
+#ifdef CONFIG_PM
+	.resume = conexant_resume,
+#endif
+};
+
+/*
+ * EAPD control
+ * the private value = nid | (invert << 8)
+ */
+
+static int cxt_eapd_info(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int cxt_eapd_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct conexant_spec *spec = codec->spec;
+	int invert = (kcontrol->private_value >> 8) & 1;
+	if (invert)
+		ucontrol->value.integer.value[0] = !spec->cur_eapd;
+	else
+		ucontrol->value.integer.value[0] = spec->cur_eapd;
+	return 0;
+
+}
+
+static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct conexant_spec *spec = codec->spec;
+	int invert = (kcontrol->private_value >> 8) & 1;
+	hda_nid_t nid = kcontrol->private_value & 0xff;
+	unsigned int eapd;
+
+	eapd = ucontrol->value.integer.value[0];
+	if (invert)
+		eapd = !eapd;
+	if (eapd == spec->cur_eapd && !codec->in_resume)
+		return 0;
+	
+	spec->cur_eapd = eapd;
+	snd_hda_codec_write(codec, nid,
+			    0, AC_VERB_SET_EAPD_BTLENABLE,
+			    eapd ? 0x02 : 0x00);
+	return 1;
+}
+
+/* controls for test mode */
+#ifdef CONFIG_SND_DEBUG
+
+#define CXT_EAPD_SWITCH(xname, nid, mask) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+	  .info = cxt_eapd_info, \
+	  .get = cxt_eapd_get, \
+	  .put = cxt_eapd_put, \
+	  .private_value = nid | (mask<<16) }
+
+
+
+static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct conexant_spec *spec = codec->spec;
+	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
+				    spec->num_channel_mode);
+}
+
+static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct conexant_spec *spec = codec->spec;
+	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
+				   spec->num_channel_mode,
+				   spec->multiout.max_channels);
+}
+
+static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct conexant_spec *spec = codec->spec;
+	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
+				      spec->num_channel_mode,
+				      &spec->multiout.max_channels);
+	if (err >= 0 && spec->need_dac_fix)
+		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
+	return err;
+}
+
+#define CXT_PIN_MODE(xname, nid, dir) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+	  .info = conexant_ch_mode_info, \
+	  .get = conexant_ch_mode_get, \
+	  .put = conexant_ch_mode_put, \
+	  .private_value = nid | (dir<<16) }
+
+static int cxt_gpio_data_info(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}                                
+
+static int cxt_gpio_data_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
+	long *valp = ucontrol->value.integer.value;
+	unsigned int val = snd_hda_codec_read(codec, nid, 0,
+					      AC_VERB_GET_GPIO_DATA, 0x00);
+
+	*valp = (val & mask) != 0;
+	return 0;
+}
+
+static int cxt_gpio_data_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
+	long val = *ucontrol->value.integer.value;
+	unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
+						    AC_VERB_GET_GPIO_DATA,
+						    0x00);
+	unsigned int old_data = gpio_data;
+
+	/* Set/unset the masked GPIO bit(s) as needed */
+	if (val == 0)
+		gpio_data &= ~mask;
+	else
+		gpio_data |= mask;
+	if (gpio_data == old_data && !codec->in_resume)
+		return 0;
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
+	return 1;
+}
+
+#define CXT_GPIO_DATA_SWITCH(xname, nid, mask) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+	  .info = cxt_gpio_data_info, \
+	  .get = cxt_gpio_data_get, \
+	  .put = cxt_gpio_data_put, \
+	  .private_value = nid | (mask<<16) }
+#if 0
+static int cxt_spdif_ctrl_info(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}                                
+
+static int cxt_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
+	long *valp = ucontrol->value.integer.value;
+	unsigned int val = snd_hda_codec_read(codec, nid, 0,
+					      AC_VERB_GET_DIGI_CONVERT, 0x00);
+
+	*valp = (val & mask) != 0;
+	return 0;
+}
+
+static int cxt_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
+	long val = *ucontrol->value.integer.value;
+	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
+						    AC_VERB_GET_DIGI_CONVERT,
+						    0x00);
+	unsigned int old_data = ctrl_data;
+
+	/* Set/unset the masked control bit(s) as needed */
+	if (val == 0)
+		ctrl_data &= ~mask;
+	else
+		ctrl_data |= mask;
+	if (ctrl_data == old_data && !codec->in_resume)
+		return 0;
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+			    ctrl_data);
+	return 1;
+}
+
+#define CXT_SPDIF_CTRL_SWITCH(xname, nid, mask) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+	  .info = cxt_spdif_ctrl_info, \
+	  .get = cxt_spdif_ctrl_get, \
+	  .put = cxt_spdif_ctrl_put, \
+	  .private_value = nid | (mask<<16) }
+#endif
+#endif /* CONFIG_SND_DEBUG */
+
+/* Conexant 5045 specific */
+
+static hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
+static hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
+static hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
+#define CXT5045_SPDIF_OUT	0x13
+
+static struct hda_channel_mode cxt5045_modes[1] = {
+	{ 2, NULL },
+};
+
+static struct hda_input_mux cxt5045_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "IntMic", 0x1 },
+		{ "LineIn", 0x2 },
+	}
+};
+
+/* turn on/off EAPD (+ mute HP) as a master switch */
+static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct conexant_spec *spec = codec->spec;
+	unsigned int bits;
+
+	if (!cxt_eapd_put(kcontrol, ucontrol))
+		return 0;
+
+	/* toggle internal speakers mute depending of presence of
+	 * the headphone jack
+	 */
+	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80;
+	snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
+	bits = spec->cur_eapd ? 0 : 0x80;
+	snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits);
+	return 1;
+}
+
+/* bind volumes of both NID 0x10 and 0x11 */
+static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	long *valp = ucontrol->value.integer.value;
+	int change;
+
+	change = snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0,
+					  0x7f, valp[0] & 0x7f);
+	change |= snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0,
+					   0x7f, valp[1] & 0x7f);
+	snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0,
+				 0x7f, valp[0] & 0x7f);
+	snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0,
+				 0x7f, valp[1] & 0x7f);
+	return change;
+}
+
+
+/* mute internal speaker if HP is plugged */
+static void cxt5045_hp_automute(struct hda_codec *codec)
+{
+	struct conexant_spec *spec = codec->spec;
+	unsigned int bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0;
+
+	spec->hp_present = snd_hda_codec_read(codec, 0x11, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
+}
+
+/* unsolicited event for HP jack sensing */
+static void cxt5045_hp_unsol_event(struct hda_codec *codec,
+				   unsigned int res)
+{
+	res >>= 26;
+	switch (res) {
+	case CONEXANT_HP_EVENT:
+		cxt5045_hp_automute(codec);
+		break;
+	}
+}
+
+static struct snd_kcontrol_new cxt5045_mixers[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = conexant_mux_enum_info,
+		.get = conexant_mux_enum_get,
+		.put = conexant_mux_enum_put
+	},
+	HDA_CODEC_VOLUME("Int Mic Volume", 0x17, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Switch", 0x17, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Ext Mic Volume", 0x17, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Ext Mic Switch", 0x17, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.info = snd_hda_mixer_amp_volume_info,
+		.get = snd_hda_mixer_amp_volume_get,
+		.put = cxt5045_hp_master_vol_put,
+		.private_value = HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = cxt_eapd_info,
+		.get = cxt_eapd_get,
+		.put = cxt5045_hp_master_sw_put,
+		.private_value = 0x10,
+	},
+
+	{}
+};
+
+static struct hda_verb cxt5045_init_verbs[] = {
+	/* Line in, Mic */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
+	/* HP, Amp  */
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+	{0x17, AC_VERB_SET_CONNECT_SEL,0x01},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x01},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x02},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04},
+	/* Record selector: Int mic */
+	{0x1a, AC_VERB_SET_CONNECT_SEL,0x0},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
+	/* SPDIF route: PCM */
+	{ 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 },
+	/* pin sensing on HP and Mic jacks */
+	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
+	/* EAPD */
+	{0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ 
+	{ } /* end */
+};
+
+#ifdef CONFIG_SND_DEBUG
+/* Test configuration for debugging, modelled after the ALC260 test
+ * configuration.
+ */
+static struct hda_input_mux cxt5045_test_capture_source = {
+	.num_items = 5,
+	.items = {
+		{ "MIXER", 0x0 },
+		{ "MIC1 pin", 0x1 },
+		{ "LINE1 pin", 0x2 },
+		{ "HP-OUT pin", 0x3 },
+		{ "CD pin", 0x4 },
+        },
+};
+
+static struct snd_kcontrol_new cxt5045_test_mixer[] = {
+
+	/* Output controls */
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+	
+	/* Modes for retasking pin widgets */
+	CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT),
+	CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT),
+
+	/* EAPD Switch Control */
+	CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0),
+
+	/* Loopback mixer controls */
+	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x17, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x17, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("LINE loopback Playback Volume", 0x17, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("LINE loopback Playback Switch", 0x17, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x17, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x17, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x04, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Capture-1 Volume", 0x17, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture-1 Switch", 0x17, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture-2 Volume", 0x17, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture-2 Switch", 0x17, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture-3 Volume", 0x17, 0x2, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture-3 Switch", 0x17, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture-4 Volume", 0x17, 0x3, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture-4 Switch", 0x17, 0x3, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture-5 Volume", 0x17, 0x4, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture-5 Switch", 0x17, 0x4, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Input Source",
+		.info = conexant_mux_enum_info,
+		.get = conexant_mux_enum_get,
+		.put = conexant_mux_enum_put,
+	},
+
+	{ } /* end */
+};
+
+static struct hda_verb cxt5045_test_init_verbs[] = {
+	/* Enable retasking pins as output, initially without power amp */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+
+	/* Disable digital (SPDIF) pins initially, but users can enable
+	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
+	 * payload also sets the generation to 0, output to be in "consumer"
+	 * PCM format, copyright asserted, no pre-emphasis and no validity
+	 * control.
+	 */
+	{0x13, AC_VERB_SET_DIGI_CONVERT_1, 0},
+
+	/* Start with output sum widgets muted and their output gains at min */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+	/* Unmute retasking pin widget output buffers since the default
+	 * state appears to be output.  As the pin mode is changed by the
+	 * user the pin mode control will take care of enabling the pin's
+	 * input/output buffers as needed.
+	 */
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Mute capture amp left and right */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+
+	/* Set ADC connection select to match default mixer setting (mic1
+	 * pin)
+	 */
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Mute all inputs to mixer widget (even unconnected ones) */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
+
+	{ }
+};
+#endif
+
+
+/* initialize jack-sensing, too */
+static int cxt5045_init(struct hda_codec *codec)
+{
+	conexant_init(codec);
+	cxt5045_hp_automute(codec);
+	return 0;
+}
+
+
+enum {
+	CXT5045_LAPTOP,	/* Laptops w/ EAPD support */
+#ifdef CONFIG_SND_DEBUG
+	CXT5045_TEST,
+#endif
+	CXT5045_MODELS
+};
+
+static const char *cxt5045_models[CXT5045_MODELS] = {
+	[CXT5045_LAPTOP]	= "laptop",
+#ifdef CONFIG_SND_DEBUG
+	[CXT5045_TEST]		= "test",
+#endif
+};
+
+static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP),
+	SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP),
+	SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP),
+	{}
+};
+
+static int patch_cxt5045(struct hda_codec *codec)
+{
+	struct conexant_spec *spec;
+	int board_config;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (!spec)
+		return -ENOMEM;
+	mutex_init(&spec->amp_mutex);
+	codec->spec = spec;
+
+	spec->multiout.max_channels = 2;
+	spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids);
+	spec->multiout.dac_nids = cxt5045_dac_nids;
+	spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT;
+	spec->num_adc_nids = 1;
+	spec->adc_nids = cxt5045_adc_nids;
+	spec->capsrc_nids = cxt5045_capsrc_nids;
+	spec->input_mux = &cxt5045_capture_source;
+	spec->num_mixers = 1;
+	spec->mixers[0] = cxt5045_mixers;
+	spec->num_init_verbs = 1;
+	spec->init_verbs[0] = cxt5045_init_verbs;
+	spec->spdif_route = 0;
+	spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes),
+	spec->channel_mode = cxt5045_modes,
+
+
+	codec->patch_ops = conexant_patch_ops;
+	codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
+
+	board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
+						  cxt5045_models,
+						  cxt5045_cfg_tbl);
+	switch (board_config) {
+	case CXT5045_LAPTOP:
+		spec->input_mux = &cxt5045_capture_source;
+		spec->num_init_verbs = 2;
+		spec->init_verbs[1] = cxt5045_init_verbs;
+		spec->mixers[0] = cxt5045_mixers;
+		codec->patch_ops.init = cxt5045_init;
+		break;
+#ifdef CONFIG_SND_DEBUG
+	case CXT5045_TEST:
+		spec->input_mux = &cxt5045_test_capture_source;
+		spec->mixers[0] = cxt5045_test_mixer;
+		spec->init_verbs[0] = cxt5045_test_init_verbs;
+#endif	
+	}
+	return 0;
+}
+
+
+/* Conexant 5047 specific */
+#define CXT5047_SPDIF_OUT	0x11
+
+static hda_nid_t cxt5047_dac_nids[2] = { 0x10, 0x1c };
+static hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
+static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
+
+static struct hda_channel_mode cxt5047_modes[1] = {
+	{ 2, NULL },
+};
+
+static struct hda_input_mux cxt5047_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "ExtMic", 0x0 },
+		{ "IntMic", 0x1 },
+	}
+};
+
+static struct hda_input_mux cxt5047_hp_capture_source = {
+	.num_items = 1,
+	.items = {
+		{ "ExtMic", 0x2 },
+	}
+};
+
+static struct hda_input_mux cxt5047_toshiba_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "ExtMic", 0x2 },
+		{ "Line-In", 0x1 },
+	}
+};
+
+/* turn on/off EAPD (+ mute HP) as a master switch */
+static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct conexant_spec *spec = codec->spec;
+	unsigned int bits;
+
+	if (!cxt_eapd_put(kcontrol, ucontrol))
+		return 0;
+
+	/* toggle internal speakers mute depending of presence of
+	 * the headphone jack
+	 */
+	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80;
+	snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
+	bits = spec->cur_eapd ? 0 : 0x80;
+	snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0, 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0, 0x80, bits);
+	return 1;
+}
+
+/* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */
+static int cxt5047_hp_master_vol_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	long *valp = ucontrol->value.integer.value;
+	int change;
+
+	change = snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0,
+					  0x7f, valp[0] & 0x7f);
+	change |= snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0,
+					   0x7f, valp[1] & 0x7f);
+	snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0,
+				 0x7f, valp[0] & 0x7f);
+	snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0,
+				 0x7f, valp[1] & 0x7f);
+	return change;
+}
+
+/* mute internal speaker if HP is plugged */
+static void cxt5047_hp_automute(struct hda_codec *codec)
+{
+	struct conexant_spec *spec = codec->spec;
+	unsigned int bits = spec->hp_present || !spec->cur_eapd ? 0x80 : 0;
+
+	spec->hp_present = snd_hda_codec_read(codec, 0x13, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
+	/* Mute/Unmute PCM 2 for good measure - some systems need this */
+	snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits);
+}
+
+/* toggle input of built-in and mic jack appropriately */
+static void cxt5047_hp_automic(struct hda_codec *codec)
+{
+	static struct hda_verb mic_jack_on[] = {
+		{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+		{0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+		{}
+	};
+	static struct hda_verb mic_jack_off[] = {
+		{0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+		{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+		{}
+	};
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x08, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	if (present)
+		snd_hda_sequence_write(codec, mic_jack_on);
+	else
+		snd_hda_sequence_write(codec, mic_jack_off);
+}
+
+/* unsolicited event for HP jack sensing */
+static void cxt5047_hp_unsol_event(struct hda_codec *codec,
+				  unsigned int res)
+{
+	res >>= 26;
+	switch (res) {
+	case CONEXANT_HP_EVENT:
+		cxt5047_hp_automute(codec);
+		break;
+	case CONEXANT_MIC_EVENT:
+		cxt5047_hp_automic(codec);
+		break;
+	}
+}
+
+static struct snd_kcontrol_new cxt5047_mixers[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = conexant_mux_enum_info,
+		.get = conexant_mux_enum_get,
+		.put = conexant_mux_enum_put
+	},
+	HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.info = snd_hda_mixer_amp_volume_info,
+		.get = snd_hda_mixer_amp_volume_get,
+		.put = cxt5047_hp_master_vol_put,
+		.private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT),
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = cxt_eapd_info,
+		.get = cxt_eapd_get,
+		.put = cxt5047_hp_master_sw_put,
+		.private_value = 0x13,
+	},
+
+	{}
+};
+
+static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = conexant_mux_enum_info,
+		.get = conexant_mux_enum_get,
+		.put = conexant_mux_enum_put
+	},
+	HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.info = snd_hda_mixer_amp_volume_info,
+		.get = snd_hda_mixer_amp_volume_get,
+		.put = cxt5047_hp_master_vol_put,
+		.private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT),
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = cxt_eapd_info,
+		.get = cxt_eapd_get,
+		.put = cxt5047_hp_master_sw_put,
+		.private_value = 0x13,
+	},
+
+	{}
+};
+
+static struct snd_kcontrol_new cxt5047_hp_mixers[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = conexant_mux_enum_info,
+		.get = conexant_mux_enum_get,
+		.put = conexant_mux_enum_put
+	},
+	HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19,0x02,HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = cxt_eapd_info,
+		.get = cxt_eapd_get,
+		.put = cxt5047_hp_master_sw_put,
+		.private_value = 0x13,
+	},
+	{ } /* end */
+};
+
+static struct hda_verb cxt5047_init_verbs[] = {
+	/* Line in, Mic, Built-in Mic */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
+	/* HP, Amp, Speaker  */
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{0x1A, AC_VERB_SET_CONNECT_SEL,0x00},
+	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
+	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
+	{0x1d, AC_VERB_SET_CONNECT_SEL,0x0},
+	/* Record selector: Front mic */
+	{0x12, AC_VERB_SET_CONNECT_SEL,0x03},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
+	/* SPDIF route: PCM */
+	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 },
+	/* Enable unsolicited events */
+	{0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
+	{ } /* end */
+};
+
+/* configuration for Toshiba Laptops */
+static struct hda_verb cxt5047_toshiba_init_verbs[] = {
+	{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0 }, /* default on */
+	/* pin sensing on HP and Mic jacks */
+	{0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
+	/* Speaker routing */
+	{0x1d, AC_VERB_SET_CONNECT_SEL,0x1},
+	/* Change default to ExtMic for recording */
+	{0x1a, AC_VERB_SET_CONNECT_SEL,0x2},
+	{}
+};
+
+/* configuration for HP Laptops */
+static struct hda_verb cxt5047_hp_init_verbs[] = {
+	/* pin sensing on HP jack */
+	{0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
+	/* Record selector: Ext Mic */
+	{0x12, AC_VERB_SET_CONNECT_SEL,0x03},
+	{0x1a, AC_VERB_SET_CONNECT_SEL,0x02},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
+	/* Speaker routing */
+	{0x1d, AC_VERB_SET_CONNECT_SEL,0x1},
+	{}
+};
+
+/* Test configuration for debugging, modelled after the ALC260 test
+ * configuration.
+ */
+#ifdef CONFIG_SND_DEBUG
+static struct hda_input_mux cxt5047_test_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "LINE1 pin", 0x0 },
+		{ "MIC1 pin", 0x1 },
+		{ "MIC2 pin", 0x2 },
+		{ "CD pin", 0x3 },
+        },
+};
+
+static struct snd_kcontrol_new cxt5047_test_mixer[] = {
+
+	/* Output only controls */
+	HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+
+	/* Modes for retasking pin widgets */
+	CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT),
+	CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT),
+
+	/* EAPD Switch Control */
+	CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0),
+
+	/* Loopback mixer controls */
+	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Input Source",
+		.info = conexant_mux_enum_info,
+		.get = conexant_mux_enum_get,
+		.put = conexant_mux_enum_put,
+	},
+       /* Controls for GPIO pins, assuming they exist and are configured
+	* as outputs
+	*/
+	CXT_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
+	CXT_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
+	CXT_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
+	CXT_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
+
+	{ } /* end */
+};
+
+static struct hda_verb cxt5047_test_init_verbs[] = {
+	/* Enable retasking pins as output, initially without power amp */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	/* Disable digital (SPDIF) pins initially, but users can enable
+	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
+	 * payload also sets the generation to 0, output to be in "consumer"
+	 * PCM format, copyright asserted, no pre-emphasis and no validity
+	 * control.
+	 */
+	{0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
+
+	/* Ensure mic1, mic2, line1 pin widgets take input from the 
+	 * OUT1 sum bus when acting as an output.
+	 */
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0},
+
+	/* Start with output sum widgets muted and their output gains at min */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+	/* Unmute retasking pin widget output buffers since the default
+	 * state appears to be output.  As the pin mode is changed by the
+	 * user the pin mode control will take care of enabling the pin's
+	 * input/output buffers as needed.
+	 */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Mute capture amp left and right */
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+
+	/* Set ADC connection select to match default mixer setting (mic1
+	 * pin)
+	 */
+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Mute all inputs to mixer widget (even unconnected ones) */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
+
+	{ }
+};
+#endif
+
+
+/* initialize jack-sensing, too */
+static int cxt5047_hp_init(struct hda_codec *codec)
+{
+	conexant_init(codec);
+	cxt5047_hp_automute(codec);
+	return 0;
+}
+
+
+enum {
+	CXT5047_LAPTOP,		/* Laptops w/o EAPD support */
+	CXT5047_LAPTOP_HP,	/* Some HP laptops */
+	CXT5047_LAPTOP_EAPD,	/* Laptops with EAPD support */
+#ifdef CONFIG_SND_DEBUG
+	CXT5047_TEST,
+#endif
+	CXT5047_MODELS
+};
+
+static const char *cxt5047_models[CXT5047_MODELS] = {
+	[CXT5047_LAPTOP]	= "laptop",
+	[CXT5047_LAPTOP_HP]	= "laptop-hp",
+	[CXT5047_LAPTOP_EAPD]	= "laptop-eapd",
+#ifdef CONFIG_SND_DEBUG
+	[CXT5047_TEST]		= "test",
+#endif
+};
+
+static struct snd_pci_quirk cxt5047_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x30a0, "HP DV1000", CXT5047_LAPTOP),
+	SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV2000T/DV3000T", CXT5047_LAPTOP),
+	SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2000Z", CXT5047_LAPTOP),
+	SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
+	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD),
+	{}
+};
+
+static int patch_cxt5047(struct hda_codec *codec)
+{
+	struct conexant_spec *spec;
+	int board_config;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (!spec)
+		return -ENOMEM;
+	mutex_init(&spec->amp_mutex);
+	codec->spec = spec;
+
+	spec->multiout.max_channels = 2;
+	spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids);
+	spec->multiout.dac_nids = cxt5047_dac_nids;
+	spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT;
+	spec->num_adc_nids = 1;
+	spec->adc_nids = cxt5047_adc_nids;
+	spec->capsrc_nids = cxt5047_capsrc_nids;
+	spec->input_mux = &cxt5047_capture_source;
+	spec->num_mixers = 1;
+	spec->mixers[0] = cxt5047_mixers;
+	spec->num_init_verbs = 1;
+	spec->init_verbs[0] = cxt5047_init_verbs;
+	spec->spdif_route = 0;
+	spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes),
+	spec->channel_mode = cxt5047_modes,
+
+	codec->patch_ops = conexant_patch_ops;
+	codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
+
+	board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
+						  cxt5047_models,
+						  cxt5047_cfg_tbl);
+	switch (board_config) {
+	case CXT5047_LAPTOP:
+		break;
+	case CXT5047_LAPTOP_HP:
+		spec->input_mux = &cxt5047_hp_capture_source;
+		spec->num_init_verbs = 2;
+		spec->init_verbs[1] = cxt5047_hp_init_verbs;
+		spec->mixers[0] = cxt5047_hp_mixers;
+		codec->patch_ops.init = cxt5047_hp_init;
+		break;
+	case CXT5047_LAPTOP_EAPD:
+		spec->input_mux = &cxt5047_toshiba_capture_source;
+		spec->num_init_verbs = 2;
+		spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
+		spec->mixers[0] = cxt5047_toshiba_mixers;
+		break;
+#ifdef CONFIG_SND_DEBUG
+	case CXT5047_TEST:
+		spec->input_mux = &cxt5047_test_capture_source;
+		spec->mixers[0] = cxt5047_test_mixer;
+		spec->init_verbs[0] = cxt5047_test_init_verbs;
+#endif	
+	}
+	return 0;
+}
+
+struct hda_codec_preset snd_hda_preset_conexant[] = {
+	{ .id = 0x14f15045, .name = "CX20549 (Venice)",
+	  .patch = patch_cxt5045 },
+	{ .id = 0x14f15047, .name = "CX20551 (Waikiki)",
+	  .patch = patch_cxt5047 },
+	{} /* terminator */
+};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4e0c3c1..145682b 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -32,6 +32,10 @@
 #include "hda_codec.h"
 #include "hda_local.h"
 
+#define ALC880_FRONT_EVENT		0x01
+#define ALC880_DCVOL_EVENT		0x02
+#define ALC880_HP_EVENT			0x04
+#define ALC880_MIC_EVENT		0x08
 
 /* ALC880 board config type */
 enum {
@@ -48,7 +52,10 @@
 	ALC880_ASUS_DIG,
 	ALC880_ASUS_W1V,
 	ALC880_ASUS_DIG2,
+	ALC880_FUJITSU,
 	ALC880_UNIWILL_DIG,
+	ALC880_UNIWILL,
+	ALC880_UNIWILL_P53,
 	ALC880_CLEVO,
 	ALC880_TCL_S700,
 	ALC880_LG,
@@ -77,8 +84,12 @@
 /* ALC262 models */
 enum {
 	ALC262_BASIC,
+	ALC262_HIPPO,
+	ALC262_HIPPO_1,
 	ALC262_FUJITSU,
 	ALC262_HP_BPC,
+	ALC262_HP_BPC_D7000_WL,
+	ALC262_HP_BPC_D7000_WF,
 	ALC262_BENQ_ED8,
 	ALC262_AUTO,
 	ALC262_MODEL_LAST /* last tag */
@@ -91,16 +102,30 @@
 	ALC861_3ST_DIG,
 	ALC861_6ST_DIG,
 	ALC861_UNIWILL_M31,
+	ALC861_TOSHIBA,
+	ALC861_ASUS,
+	ALC861_ASUS_LAPTOP,
 	ALC861_AUTO,
 	ALC861_MODEL_LAST,
 };
 
+/* ALC861-VD models */
+enum {
+	ALC660VD_3ST,
+	ALC861VD_3ST,
+	ALC861VD_3ST_DIG,
+	ALC861VD_6ST_DIG,
+	ALC861VD_AUTO,
+	ALC861VD_MODEL_LAST,
+};
+
 /* ALC882 models */
 enum {
 	ALC882_3ST_DIG,
 	ALC882_6ST_DIG,
 	ALC882_ARIMA,
 	ALC882_AUTO,
+	ALC885_MACPRO,
 	ALC882_MODEL_LAST,
 };
 
@@ -110,8 +135,12 @@
 	ALC883_3ST_6ch_DIG,
 	ALC883_3ST_6ch,
 	ALC883_6ST_DIG,
+	ALC883_TARGA_DIG,
+	ALC883_TARGA_2ch_DIG,
 	ALC888_DEMO_BOARD,
 	ALC883_ACER,
+	ALC883_MEDION,
+	ALC883_LAPTOP_EAPD,
 	ALC883_AUTO,
 	ALC883_MODEL_LAST,
 };
@@ -1015,6 +1044,60 @@
 	{ } /* end */
 };
 
+/* Uniwill */
+static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
+	HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, 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("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
+	HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
 /*
  * build control elements
  */
@@ -1248,6 +1331,159 @@
 	{ }
 };
 
+/*
+ * Uniwill pin configuration:
+ * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
+ * line = 0x1a
+ */
+static struct hda_verb alc880_uniwill_init_verbs[] = {
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
+	/* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+
+	{ }
+};
+
+/*
+* Uniwill P53
+* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19, 
+ */
+static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
+
+	{ }
+};
+
+static struct hda_verb alc880_beep_init_verbs[] = {
+	{ 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
+	{ }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc880_uniwill_automute(struct hda_codec *codec)
+{
+ 	unsigned int present;
+
+ 	present = snd_hda_codec_read(codec, 0x14, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
+				 0x80, present ? 0x80 : 0);
+	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
+				 0x80, present ? 0x80 : 0);
+	snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0,
+				 0x80, present ? 0x80 : 0);
+	snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0,
+				 0x80, present ? 0x80 : 0);
+
+	present = snd_hda_codec_read(codec, 0x18, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_write(codec, 0x0b, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+			    0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
+}
+
+static void alc880_uniwill_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) == ALC880_HP_EVENT ||
+	    (res >> 28) == ALC880_MIC_EVENT)
+		alc880_uniwill_automute(codec);
+}
+
+static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
+{
+ 	unsigned int present;
+
+ 	present = snd_hda_codec_read(codec, 0x14, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+
+	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0,
+				 0x80, present ? 0x80 : 0);
+	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0,
+				 0x80, present ? 0x80 : 0);
+}
+
+static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+	
+	present = snd_hda_codec_read(codec, 0x21, 0,
+				     AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f;
+
+	snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
+				 0x7f, present);
+	snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
+				 0x7f,  present);
+
+	snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
+				 0x7f,  present);
+	snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
+				 0x7f, present);
+
+}
+static void alc880_uniwill_p53_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) == ALC880_HP_EVENT)
+		alc880_uniwill_p53_hp_automute(codec);
+	if ((res >> 28) == ALC880_DCVOL_EVENT) 
+		alc880_uniwill_p53_dcvol_automute(codec);
+}
+
 /* FIXME! */
 /*
  * F1734 pin configuration:
@@ -2125,159 +2361,112 @@
 /*
  */
 
-static struct hda_board_config alc880_cfg_tbl[] = {
-	/* Back 3 jack, front 2 jack */
-	{ .modelname = "3stack", .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe212, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe213, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe234, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
-	/* TCL S700 */
-	{ .modelname = "tcl", .config = ALC880_TCL_S700 },
-	{ .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 },
-
-	/* Back 3 jack, front 2 jack (Internal add Aux-In) */
-	{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
-	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST }, 
-	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST },
-
-	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
-	{ .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
-	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG },
-
-	/* Clevo laptops */
-	{ .modelname = "clevo", .config = ALC880_CLEVO },
-	{ .pci_subvendor = 0x1558, .pci_subdevice = 0x0520,
-	  .config = ALC880_CLEVO }, /* Clevo m520G NB */
-	{ .pci_subvendor = 0x1558, .pci_subdevice = 0x0660,
-	  .config = ALC880_CLEVO }, /* Clevo m665n */
-
-	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
-	{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
-
-	/* Back 5 jack, front 2 jack */
-	{ .modelname = "5stack", .config = ALC880_5ST },
-	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
-	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
-	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
-
-	/* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
-	{ .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
-	{ .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
-	{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
-	{ .pci_subvendor = 0xa0a0, .pci_subdevice = 0x0560,
-	  .config = ALC880_5ST_DIG }, /* Aopen i915GMm-HFS */
-	/* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */
-	{ .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
-	/* note subvendor = 0 below */
-	/* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */
-
-	{ .modelname = "w810", .config = ALC880_W810 },
-	{ .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
-
-	{ .modelname = "z71v", .config = ALC880_Z71V },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
-
-	{ .modelname = "6stack", .config = ALC880_6ST },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x8196, .config = ALC880_6ST }, /* ASUS P5GD1-HVM */
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x81b4, .config = ALC880_6ST },
-	{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
-	{ .pci_subvendor = 0x1458, .pci_subdevice = 0xa102, .config = ALC880_6ST }, /* Gigabyte K8N51 */
-
-	{ .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
-	{ .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
-	{ .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
-	{ .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
-	{ .pci_subvendor = 0x1039, .pci_subdevice = 0x1234, .config = ALC880_6ST_DIG },
-	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0077, .config = ALC880_6ST_DIG },
-	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0078, .config = ALC880_6ST_DIG },
-	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG },
-	{ .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */
-	{ .pci_subvendor = 0x1509, .pci_subdevice = 0x925d, .config = ALC880_6ST_DIG }, /* FIC P4M-915GD1 */
-	{ .pci_subvendor = 0x1695, .pci_subdevice = 0x4012, .config = ALC880_5ST_DIG }, /* Epox EP-5LDA+ GLi */
-
-	{ .modelname = "asus", .config = ALC880_ASUS },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10c2, .config = ALC880_ASUS_DIG }, /* Asus W6A */
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
-	{ .modelname = "asus-w1v", .config = ALC880_ASUS_W1V },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
-	{ .modelname = "asus-dig", .config = ALC880_ASUS_DIG },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x8181, .config = ALC880_ASUS_DIG }, /* ASUS P4GPL-X */
-	{ .modelname = "asus-dig2", .config = ALC880_ASUS_DIG2 },
-	{ .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 },
-
-	{ .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
-	{ .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },	
-
-	{ .modelname = "F1734", .config = ALC880_F1734 },
-	{ .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
-	{ .pci_subvendor = 0x1584, .pci_subdevice = 0x9054, .config = ALC880_F1734 },
-
-	{ .modelname = "lg", .config = ALC880_LG },
-	{ .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG },
-	{ .pci_subvendor = 0x1854, .pci_subdevice = 0x0068, .config = ALC880_LG },
-
-	{ .modelname = "lg-lw", .config = ALC880_LG_LW },
-	{ .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW },
-	{ .pci_subvendor = 0x1854, .pci_subdevice = 0x0077, .config = ALC880_LG_LW },
-
+static const char *alc880_models[ALC880_MODEL_LAST] = {
+	[ALC880_3ST]		= "3stack",
+	[ALC880_TCL_S700]	= "tcl",
+	[ALC880_3ST_DIG]	= "3stack-digout",
+	[ALC880_CLEVO]		= "clevo",
+	[ALC880_5ST]		= "5stack",
+	[ALC880_5ST_DIG]	= "5stack-digout",
+	[ALC880_W810]		= "w810",
+	[ALC880_Z71V]		= "z71v",
+	[ALC880_6ST]		= "6stack",
+	[ALC880_6ST_DIG]	= "6stack-digout",
+	[ALC880_ASUS]		= "asus",
+	[ALC880_ASUS_W1V]	= "asus-w1v",
+	[ALC880_ASUS_DIG]	= "asus-dig",
+	[ALC880_ASUS_DIG2]	= "asus-dig2",
+	[ALC880_UNIWILL_DIG]	= "uniwill",
+	[ALC880_UNIWILL_P53]	= "uniwill-p53",
+	[ALC880_FUJITSU]	= "fujitsu",
+	[ALC880_F1734]		= "F1734",
+	[ALC880_LG]		= "lg",
+	[ALC880_LG_LW]		= "lg-lw",
 #ifdef CONFIG_SND_DEBUG
-	{ .modelname = "test", .config = ALC880_TEST },
+	[ALC880_TEST]		= "test",
 #endif
-	{ .modelname = "auto", .config = ALC880_AUTO },
+	[ALC880_AUTO]		= "auto",
+};
+
+static struct snd_pci_quirk alc880_cfg_tbl[] = {
+	/* Broken BIOS configuration */
+	SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
+
+	SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
+	SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
+	SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
+
+	SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
+
+	SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
+	SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
+	/* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
+	SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS),
+	SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
+	SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
+	SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS),
+
+	SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
+	SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
+	SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
+	SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
+	SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
+	SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
+	SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
+	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
+	SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
+	SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
+
+	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
+	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
+	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
+	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),
+
+	SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),
+	SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
+	SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
+
+	SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
+	SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
+	SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
+	SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
+
+	SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST),
 
 	{}
 };
@@ -2438,7 +2627,8 @@
 	},
 	[ALC880_UNIWILL_DIG] = {
 		.mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_asus_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
 		.dac_nids = alc880_asus_dac_nids,
 		.dig_out_nid = ALC880_DIGOUT_NID,
@@ -2447,6 +2637,46 @@
 		.need_dac_fix = 1,
 		.input_mux = &alc880_capture_source,
 	},
+	[ALC880_UNIWILL] = {
+		.mixers = { alc880_uniwill_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_uniwill_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+		.channel_mode = alc880_threestack_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_capture_source,
+		.unsol_event = alc880_uniwill_unsol_event,
+		.init_hook = alc880_uniwill_automute,
+	},
+	[ALC880_UNIWILL_P53] = {
+		.mixers = { alc880_uniwill_p53_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_uniwill_p53_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
+		.channel_mode = alc880_threestack_modes,
+		.input_mux = &alc880_capture_source,
+		.unsol_event = alc880_uniwill_p53_unsol_event,
+		.init_hook = alc880_uniwill_p53_hp_automute,
+	},
+	[ALC880_FUJITSU] = {
+		.mixers = { alc880_fujitsu_mixer, 
+			    alc880_pcbeep_mixer, },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_uniwill_p53_init_verbs,
+	       			alc880_beep_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+		.channel_mode = alc880_2_jack_modes,
+		.input_mux = &alc880_capture_source,
+		.unsol_event = alc880_uniwill_p53_unsol_event,
+		.init_hook = alc880_uniwill_p53_hp_automute,
+	},
 	[ALC880_CLEVO] = {
 		.mixers = { alc880_three_stack_mixer },
 		.init_verbs = { alc880_volume_init_verbs,
@@ -2841,8 +3071,10 @@
 
 	codec->spec = spec;
 
-	board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
-	if (board_config < 0 || board_config >= ALC880_MODEL_LAST) {
+	board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
+						  alc880_models,
+						  alc880_cfg_tbl);
+	if (board_config < 0) {
 		printk(KERN_INFO "hda_codec: Unknown model for ALC880, "
 		       "trying auto-probe from BIOS...\n");
 		board_config = ALC880_AUTO;
@@ -3090,11 +3322,20 @@
  * 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.
+ *
+ * The C20x Tablet series have a mono internal speaker which is controlled
+ * via the chip's Mono sum widget and pin complex, so include the necessary
+ * controls for such models.  On models without a "mono speaker" the control
+ * won't do anything.
  */
 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_MONO("Mono Speaker Playback Volume", 0x0a, 1, 0x0,
+			      HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Mono Speaker Playback Switch", 0x0a, 1, 2,
+			   HDA_INPUT),
 	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),
@@ -3409,11 +3650,11 @@
 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
 	/* Line In jack is connected to Line1 pin */
 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	/* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 	/* Ensure all other unused pins are disabled and muted. */
 	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
 	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
@@ -3441,6 +3682,8 @@
 
 	/* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */
 	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Unmute mono pin widget amp output (no equiv mixer ctrl) */
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
 	 * inputs. If the pin mode is changed by the user the pin mode control
 	 * will take care of enabling the pin's input/output buffers as needed.
@@ -3928,33 +4171,33 @@
 /*
  * ALC260 configurations
  */
-static struct hda_board_config alc260_cfg_tbl[] = {
-	{ .modelname = "basic", .config = ALC260_BASIC },
-	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb,
-	  .config = ALC260_BASIC }, /* Sony VAIO */
-	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81cc,
-	  .config = ALC260_BASIC }, /* Sony VAIO VGN-S3HP */
-	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81cd,
-	  .config = ALC260_BASIC }, /* Sony VAIO */
-	{ .pci_subvendor = 0x152d, .pci_subdevice = 0x0729,
-	  .config = ALC260_BASIC }, /* CTL Travel Master U553W */
-	{ .modelname = "hp", .config = ALC260_HP },
-	{ .modelname = "hp-3013", .config = ALC260_HP_3013 },
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP_3013 },
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 },
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 },
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP },
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP },
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP },
-	{ .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X },
-	{ .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X },
-	{ .modelname = "acer", .config = ALC260_ACER },
-	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x008f, .config = ALC260_ACER },
+static const char *alc260_models[ALC260_MODEL_LAST] = {
+	[ALC260_BASIC]		= "basic",
+	[ALC260_HP]		= "hp",
+	[ALC260_HP_3013]	= "hp-3013",
+	[ALC260_FUJITSU_S702X]	= "fujitsu",
+	[ALC260_ACER]		= "acer",
 #ifdef CONFIG_SND_DEBUG
-	{ .modelname = "test", .config = ALC260_TEST },
+	[ALC260_TEST]		= "test",
 #endif
-	{ .modelname = "auto", .config = ALC260_AUTO },
+	[ALC260_AUTO]		= "auto",
+};
+
+static struct snd_pci_quirk alc260_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
+	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
+	SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
+	SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP),
+	SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013),
+	SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
+	SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
+	SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
+	SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
+	SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
+	SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
+	SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
+	SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
+	SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
 	{}
 };
 
@@ -4053,8 +4296,10 @@
 
 	codec->spec = spec;
 
-	board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
-	if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
+	board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
+						  alc260_models,
+						  alc260_cfg_tbl);
+	if (board_config < 0) {
 		snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, "
 			   "trying auto-probe from BIOS...\n");
 		board_config = ALC260_AUTO;
@@ -4207,8 +4452,10 @@
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
 	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
@@ -4313,6 +4560,100 @@
 	{ } 
 };
 
+/* Mac Pro test */
+static struct snd_kcontrol_new alc882_macpro_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	{ } /* end */
+};
+
+static struct hda_verb alc882_macpro_init_verbs[] = {
+	/* Front mixer: unmute input/output amp left and right (volume = 0) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Front Pin: output 0 (0x0c) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Speaker:  output */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
+	/* Headphone output (output 0 - 0x0c) */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* Input mixer2 */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* Input mixer3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* ADC1: mute amp left and right */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* ADC2: mute amp left and right */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* ADC3: mute amp left and right */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{ }
+};
+static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
+{
+	unsigned int gpiostate, gpiomask, gpiodir;
+
+	gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
+				       AC_VERB_GET_GPIO_DATA, 0);
+
+	if (!muted)
+		gpiostate |= (1 << pin);
+	else
+		gpiostate &= ~(1 << pin);
+
+	gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
+				      AC_VERB_GET_GPIO_MASK, 0);
+	gpiomask |= (1 << pin);
+
+	gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
+				     AC_VERB_GET_GPIO_DIRECTION, 0);
+	gpiodir |= (1 << pin);
+
+
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_MASK, gpiomask);
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_DIRECTION, gpiodir);
+
+	msleep(1);
+
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_DATA, gpiostate);
+}
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -4435,19 +4776,20 @@
 /*
  * configuration and preset
  */
-static struct hda_board_config alc882_cfg_tbl[] = {
-	{ .modelname = "3stack-dig", .config = ALC882_3ST_DIG },
-	{ .modelname = "6stack-dig", .config = ALC882_6ST_DIG },
-	{ .pci_subvendor = 0x1462, .pci_subdevice = 0x6668,
-	  .config = ALC882_6ST_DIG }, /* MSI  */
-	{ .pci_subvendor = 0x105b, .pci_subdevice = 0x6668,
-	  .config = ALC882_6ST_DIG }, /* Foxconn */
-	{ .pci_subvendor = 0x1019, .pci_subdevice = 0x6668,
-	  .config = ALC882_6ST_DIG }, /* ECS to Intel*/
-	{ .modelname = "arima", .config = ALC882_ARIMA },
-	{ .pci_subvendor = 0x161f, .pci_subdevice = 0x2054,
-	  .config = ALC882_ARIMA }, /* Arima W820Di1 */
-	{ .modelname = "auto", .config = ALC882_AUTO },
+static const char *alc882_models[ALC882_MODEL_LAST] = {
+	[ALC882_3ST_DIG]	= "3stack-dig",
+	[ALC882_6ST_DIG]	= "6stack-dig",
+	[ALC882_ARIMA]		= "arima",
+	[ALC885_MACPRO]		= "macpro",
+	[ALC882_AUTO]		= "auto",
+};
+
+static struct snd_pci_quirk alc882_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
+	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
+	SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA),
+	SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
 	{}
 };
 
@@ -4484,6 +4826,17 @@
 		.channel_mode = alc882_sixstack_modes,
 		.input_mux = &alc882_capture_source,
 	},
+	[ALC885_MACPRO] = {
+		.mixers = { alc882_macpro_mixer },
+		.init_verbs = { alc882_macpro_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.dig_in_nid = ALC882_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
+		.channel_mode = alc882_ch_modes,
+		.input_mux = &alc882_capture_source,
+	},
 };
 
 
@@ -4584,7 +4937,9 @@
 
 	codec->spec = spec;
 
-	board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl);
+	board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
+						  alc882_models,
+						  alc882_cfg_tbl);
 
 	if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
 		printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
@@ -4609,6 +4964,11 @@
 	if (board_config != ALC882_AUTO)
 		setup_preset(spec, &alc882_presets[board_config]);
 
+	if (board_config == ALC885_MACPRO) {
+		alc882_gpio_mute(codec, 0, 0);
+		alc882_gpio_mute(codec, 1, 0);
+	}
+
 	spec->stream_name_analog = "ALC882 Analog";
 	spec->stream_analog_playback = &alc882_pcm_analog_playback;
 	spec->stream_analog_capture = &alc882_pcm_analog_capture;
@@ -4767,6 +5127,13 @@
 	{ 8, alc883_sixstack_ch8_init },
 };
 
+static struct hda_verb alc883_medion_eapd_verbs[] = {
+        /* eanable EAPD on medion laptop */
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x20, AC_VERB_SET_PROC_COEF, 0x3070},
+	{ }
+};
+
 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
  *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
  */
@@ -4788,8 +5155,10 @@
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
 	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
@@ -4818,8 +5187,10 @@
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
 	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
@@ -4854,8 +5225,10 @@
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
 	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
@@ -4875,6 +5248,101 @@
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 1,
+		.info = alc883_mux_enum_info,
+		.get = alc883_mux_enum_get,
+		.put = alc883_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new alc883_tagra_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 2,
+		.info = alc883_mux_enum_info,
+		.get = alc883_mux_enum_get,
+		.put = alc883_mux_enum_put,
+	},
+	{ } /* end */
+};	
+
+static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 2,
+		.info = alc883_mux_enum_info,
+		.get = alc883_mux_enum_get,
+		.put = alc883_mux_enum_put,
+	},
+	{ } /* end */
+};	
+
 static struct snd_kcontrol_new alc883_chmode_mixer[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -4963,6 +5431,45 @@
 	{ }
 };
 
+static struct hda_verb alc883_tagra_verbs[] = {
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 
+
+	{ } /* end */
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_tagra_automute(struct hda_codec *codec)
+{
+ 	unsigned int present;
+
+ 	present = snd_hda_codec_read(codec, 0x14, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
+				 0x80, present ? 0x80 : 0);
+	snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
+				 0x80, present ? 0x80 : 0);
+	snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3);
+}
+
+static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	if ((res >> 26) == ALC880_HP_EVENT)
+		alc883_tagra_automute(codec);
+}
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -5057,32 +5564,42 @@
 /*
  * configuration and preset
  */
-static struct hda_board_config alc883_cfg_tbl[] = {
-	{ .modelname = "3stack-dig", .config = ALC883_3ST_2ch_DIG },
-	{ .modelname = "3stack-6ch-dig", .config = ALC883_3ST_6ch_DIG },
-	{ .pci_subvendor = 0x1019, .pci_subdevice = 0x6668,
-	  .config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/
-	{ .modelname = "3stack-6ch", .config = ALC883_3ST_6ch },
-	{ .pci_subvendor = 0x108e, .pci_subdevice = 0x534d,
-	  .config = ALC883_3ST_6ch },
-        { .pci_subvendor = 0x8086, .pci_subdevice = 0xd601,
-          .config = ALC883_3ST_6ch }, /* D102GGC */
-	{ .modelname = "6stack-dig", .config = ALC883_6ST_DIG },
-	{ .pci_subvendor = 0x1462, .pci_subdevice = 0x6668,
-	  .config = ALC883_6ST_DIG }, /* MSI  */
-	{ .pci_subvendor = 0x1462, .pci_subdevice = 0x7280,
-	  .config = ALC883_6ST_DIG }, /* MSI K9A Platinum (MS-7280) */
-	{ .pci_subvendor = 0x105b, .pci_subdevice = 0x6668,
-	  .config = ALC883_6ST_DIG }, /* Foxconn */
-	{ .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD },
-	{ .modelname = "acer", .config = ALC883_ACER },
-	{ .pci_subvendor = 0x1025, .pci_subdevice = 0/*0x0102*/,
-	  .config = ALC883_ACER },
-	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0102,
-	  .config = ALC883_ACER },
-	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x009f,
-	  .config = ALC883_ACER },
-	{ .modelname = "auto", .config = ALC883_AUTO },
+static const char *alc883_models[ALC883_MODEL_LAST] = {
+	[ALC883_3ST_2ch_DIG]	= "3stack-dig",
+	[ALC883_3ST_6ch_DIG]	= "3stack-6ch-dig",
+	[ALC883_3ST_6ch]	= "3stack-6ch",
+	[ALC883_6ST_DIG]	= "6stack-dig",
+	[ALC883_TARGA_DIG]	= "targa-dig",
+	[ALC883_TARGA_2ch_DIG]	= "targa-2ch-dig",
+	[ALC888_DEMO_BOARD]	= "6stack-dig-demo",
+	[ALC883_ACER]		= "acer",
+	[ALC883_MEDION]		= "medion",
+	[ALC883_LAPTOP_EAPD]	= "laptop-eapd",
+	[ALC883_AUTO]		= "auto",
+};
+
+static struct snd_pci_quirk alc883_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),
+	SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
+	SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER),
+	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
+	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
 	{}
 };
 
@@ -5139,6 +5656,35 @@
 		.channel_mode = alc883_sixstack_modes,
 		.input_mux = &alc883_capture_source,
 	},
+	[ALC883_TARGA_DIG] = {
+		.mixers = { alc883_tagra_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+		.adc_nids = alc883_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+		.channel_mode = alc883_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc883_tagra_unsol_event,
+		.init_hook = alc883_tagra_automute,
+	},
+	[ALC883_TARGA_2ch_DIG] = {
+		.mixers = { alc883_tagra_2ch_mixer},
+		.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+		.adc_nids = alc883_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc883_tagra_unsol_event,
+		.init_hook = alc883_tagra_automute,
+	},
 	[ALC888_DEMO_BOARD] = {
 		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
 		.init_verbs = { alc883_init_verbs },
@@ -5169,6 +5715,31 @@
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
 	},
+	[ALC883_MEDION] = {
+		.mixers = { alc883_fivestack_mixer,
+			    alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs,
+				alc883_medion_eapd_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+		.adc_nids = alc883_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+		.channel_mode = alc883_sixstack_modes,
+		.input_mux = &alc883_capture_source,
+	},
+	[ALC883_LAPTOP_EAPD] = {
+		.mixers = { alc883_base_mixer,
+			    alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+		.adc_nids = alc883_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+	},
 };
 
 
@@ -5277,8 +5848,10 @@
 
 	codec->spec = spec;
 
-	board_config = snd_hda_check_board_config(codec, alc883_cfg_tbl);
-	if (board_config < 0 || board_config >= ALC883_MODEL_LAST) {
+	board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,
+						  alc883_models,
+						  alc883_cfg_tbl);
+	if (board_config < 0) {
 		printk(KERN_INFO "hda_codec: Unknown model for ALC883, "
 		       "trying auto-probe from BIOS...\n");
 		board_config = ALC883_AUTO;
@@ -5355,6 +5928,24 @@
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, 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("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	/* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	   HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
+	/*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
 static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -5377,6 +5968,30 @@
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
+	HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
 #define alc262_capture_mixer		alc882_capture_mixer
 #define alc262_capture_alt_mixer	alc882_capture_alt_mixer
 
@@ -5459,6 +6074,103 @@
 	{ }
 };
 
+static struct hda_verb alc262_hippo_unsol_verbs[] = {
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{}
+};
+
+static struct hda_verb alc262_hippo1_unsol_verbs[] = {
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{}
+};
+
+/* mute/unmute internal speaker according to the hp jack and mute state */
+static void alc262_hippo_automute(struct hda_codec *codec, int force)
+{
+	struct alc_spec *spec = codec->spec;
+	unsigned int mute;
+
+	if (force || ! spec->sense_updated) {
+		unsigned int present;
+		/* need to execute and sync at first */
+		snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
+		present = snd_hda_codec_read(codec, 0x15, 0,
+				    	 AC_VERB_GET_PIN_SENSE, 0);
+		spec->jack_present = (present & 0x80000000) != 0;
+		spec->sense_updated = 1;
+	}
+	if (spec->jack_present) {
+		/* mute internal speaker */
+		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+					 0x80, 0x80);
+		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+					 0x80, 0x80);
+	} else {
+		/* unmute internal speaker if necessary */
+		mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
+		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+					 0x80, mute & 0x80);
+		mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0);
+		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+					 0x80, mute & 0x80);
+	}
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc262_hippo_unsol_event(struct hda_codec *codec,
+				       unsigned int res)
+{
+	if ((res >> 26) != ALC880_HP_EVENT)
+		return;
+	alc262_hippo_automute(codec, 1);
+}
+
+static void alc262_hippo1_automute(struct hda_codec *codec, int force)
+{
+	struct alc_spec *spec = codec->spec;
+	unsigned int mute;
+
+	if (force || ! spec->sense_updated) {
+		unsigned int present;
+		/* need to execute and sync at first */
+		snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
+		present = snd_hda_codec_read(codec, 0x1b, 0,
+				    	 AC_VERB_GET_PIN_SENSE, 0);
+		spec->jack_present = (present & 0x80000000) != 0;
+		spec->sense_updated = 1;
+	}
+	if (spec->jack_present) {
+		/* mute internal speaker */
+		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+					 0x80, 0x80);
+		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+					 0x80, 0x80);
+	} else {
+		/* unmute internal speaker if necessary */
+		mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
+		snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+					 0x80, mute & 0x80);
+		mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0);
+		snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+					 0x80, mute & 0x80);
+	}
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc262_hippo1_unsol_event(struct hda_codec *codec,
+				       unsigned int res)
+{
+	if ((res >> 26) != ALC880_HP_EVENT)
+		return;
+	alc262_hippo1_automute(codec, 1);
+}
+
 /*
  * fujitsu model
  *  0x14 = headphone/spdif-out, 0x15 = internal speaker
@@ -5809,6 +6521,100 @@
 	{ }
 };
 
+static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
+	/*
+	 * Unmute ADC0-2 and set the default input to mic-in
+	 */
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+	 * mixer widget
+	 * Note: PASD motherboards uses the Line In 2 as the input for front
+	 * panel mic (mic 2)
+	 */
+	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
+	/*
+	 * Set up output mixers (0x0c - 0x0e)
+	 */
+	/* set vol=0 to output mixers */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },	/* HP */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Mono */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* rear MIC */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },	/* Line in */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* Front MIC */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Line out */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },	/* CD in */
+
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+
+	/* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
+	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
+        /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))},  */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
+	/* Input mixer2 */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+        /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
+	/* Input mixer3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+        /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
+
+	{ }
+};
+
 /* pcm configuration: identiacal with ALC880 */
 #define alc262_pcm_analog_playback	alc880_pcm_analog_playback
 #define alc262_pcm_analog_capture	alc880_pcm_analog_capture
@@ -5866,26 +6672,35 @@
 /*
  * configuration and preset
  */
-static struct hda_board_config alc262_cfg_tbl[] = {
-	{ .modelname = "basic", .config = ALC262_BASIC },
-	{ .modelname = "fujitsu", .config = ALC262_FUJITSU },
-	{ .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397,
-	  .config = ALC262_FUJITSU },
-	{ .modelname = "hp-bpc", .config = ALC262_HP_BPC },
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x280c,
-	  .config = ALC262_HP_BPC }, /* xw4400 */
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x2801,
-	  .config = ALC262_HP_BPC }, /* q965 */
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3014,
-	  .config = ALC262_HP_BPC }, /* xw6400 */
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3015,
-	  .config = ALC262_HP_BPC }, /* xw8400 */
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x12fe,
-	  .config = ALC262_HP_BPC }, /* xw9400 */
-	{ .modelname = "benq", .config = ALC262_BENQ_ED8 },
-	{ .pci_subvendor = 0x17ff, .pci_subdevice = 0x0560,
-	  .config = ALC262_BENQ_ED8 },
-	{ .modelname = "auto", .config = ALC262_AUTO },
+static const char *alc262_models[ALC262_MODEL_LAST] = {
+	[ALC262_BASIC]		= "basic",
+	[ALC262_HIPPO]		= "hippo",
+	[ALC262_HIPPO_1]	= "hippo_1",
+	[ALC262_FUJITSU]	= "fujitsu",
+	[ALC262_HP_BPC]		= "hp-bpc",
+	[ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
+	[ALC262_BENQ_ED8]	= "benq",
+	[ALC262_AUTO]		= "auto",
+};
+
+static struct snd_pci_quirk alc262_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
+	SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC),
+	SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
+	SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
+	SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
+	SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
+	SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
+	SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
+	SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
+	SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
+	SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
+	SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
+	SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
+	SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
+	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
+	SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
+	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
 	{}
 };
 
@@ -5900,6 +6715,30 @@
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_capture_source,
 	},
+	[ALC262_HIPPO] = {
+		.mixers = { alc262_base_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.dig_out_nid = ALC262_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+		.unsol_event = alc262_hippo_unsol_event,
+	},
+	[ALC262_HIPPO_1] = {
+		.mixers = { alc262_hippo1_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x02,
+		.dig_out_nid = ALC262_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+		.unsol_event = alc262_hippo1_unsol_event,
+	},
 	[ALC262_FUJITSU] = {
 		.mixers = { alc262_fujitsu_mixer },
 		.init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs },
@@ -5922,6 +6761,27 @@
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_HP_capture_source,
 	},	
+	[ALC262_HP_BPC_D7000_WF] = {
+		.mixers = { alc262_HP_BPC_WildWest_mixer },
+		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_HP_capture_source,
+	},	
+	[ALC262_HP_BPC_D7000_WL] = {
+		.mixers = { alc262_HP_BPC_WildWest_mixer,
+			    alc262_HP_BPC_WildWest_option_mixer },
+		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_HP_capture_source,
+	},	
 	[ALC262_BENQ_ED8] = {
 		.mixers = { alc262_base_mixer },
 		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
@@ -5940,7 +6800,7 @@
 	int board_config;
 	int err;
 
-	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
@@ -5956,9 +6816,11 @@
 	}
 #endif
 
-	board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl);
-	
-	if (board_config < 0 || board_config >= ALC262_MODEL_LAST) {
+	board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
+						  alc262_models,
+						  alc262_cfg_tbl);
+
+	if (board_config < 0) {
 		printk(KERN_INFO "hda_codec: Unknown model for ALC262, "
 		       "trying auto-probe from BIOS...\n");
 		board_config = ALC262_AUTO;
@@ -6078,6 +6940,44 @@
 	{ 4, alc861_uniwill_m31_ch4_init },
 };
 
+/* Set mic1 and line-in as input and unmute the mixer */
+static struct hda_verb alc861_asus_ch2_init[] = {
+	/* set pin widget 1Ah (line in) for input */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
+#if 0
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
+#endif
+	{ } /* end */
+};
+/* Set mic1 nad line-in as output and mute mixer */
+static struct hda_verb alc861_asus_ch6_init[] = {
+	/* set pin widget 1Ah (line in) for output (Back Surround)*/
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
+	/* set pin widget 18h (mic1) for output (CLFE)*/
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
+	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
+
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+#if 0
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
+#endif
+	{ } /* end */
+};
+
+static struct hda_channel_mode alc861_asus_modes[2] = {
+	{ 2, alc861_asus_ch2_init },
+	{ 6, alc861_asus_ch6_init },
+};
+
 /* patch-ALC861 */
 
 static struct snd_kcontrol_new alc861_base_mixer[] = {
@@ -6154,7 +7054,29 @@
                 .private_value = ARRAY_SIZE(alc861_threestack_modes),
 	},
 	{ } /* end */
-};			
+};
+
+static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
+        /* output mixer control */
+	HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+	
+        /*Capture mixer control */
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.count = 1,
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+
+	{ } /* end */
+};	
+
 static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
         /* output mixer control */
 	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
@@ -6196,7 +7118,58 @@
 	},
 	{ } /* end */
 };			
-	
+
+static struct snd_kcontrol_new alc861_asus_mixer[] = {
+        /* output mixer control */
+	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
+
+	/* Input mixer control */
+	HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), /* was HDA_INPUT (why?) */
+ 
+	/* Capture mixer control */
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.count = 1,
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+                .private_value = ARRAY_SIZE(alc861_asus_modes),
+	},
+	{ }
+};
+
+/* additional mixer */
+static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT),
+	{ }
+};
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -6217,7 +7190,7 @@
 	/* port-E for HP out (front panel) */
 	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
 	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	/* port-F for mic-in (front panel) with vref */
 	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
 	/* port-G for CLFE (rear panel) */
@@ -6281,7 +7254,7 @@
 	/* port-E for HP out (front panel) */
 	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
 	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	/* port-F for mic-in (front panel) with vref */
 	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
 	/* port-G for CLFE (rear panel) */
@@ -6341,7 +7314,7 @@
 	/* port-E for HP out (front panel) */
 	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, // this has to be set to VREF80
 	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	/* port-F for mic-in (front panel) with vref */
 	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
 	/* port-G for CLFE (rear panel) */
@@ -6385,6 +7358,74 @@
 	{ }
 };
 
+static struct hda_verb alc861_asus_init_verbs[] = {
+	/*
+	 * Unmute ADC0 and set the default input to mic-in
+	 */
+	/* port-A for surround (rear panel) | according to codec#0 this is the HP jack*/
+	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
+	/* route front PCM to HP */
+	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	/* port-B for mic-in (rear panel) with vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-C for line-in (rear panel) */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* port-D for Front */
+	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-E for HP out (front panel) */
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* this has to be set to VREF80 */
+	/* route front PCM to HP */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-F for mic-in (front panel) with vref */
+	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-G for CLFE (rear panel) */
+	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* port-H for side (rear panel) */
+	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* CD-in */
+	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* route front mic to ADC1*/
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* Unmute DAC0~3 & spdif out*/
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Unmute Mixer 14 (mic) 1c (Line in)*/
+	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	
+	/* Unmute Stereo Mixer 15 */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, /* Output 0~12 step */
+
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, /* hp used DAC 3 (Front) */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{ }
+};
+
+/* additional init verbs for ASUS laptops */
+static struct hda_verb alc861_asus_laptop_init_verbs[] = {
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
+	{ }
+};
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -6437,6 +7478,39 @@
 	{ }
 };
 
+static struct hda_verb alc861_toshiba_init_verbs[] = {
+	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+        
+	{ }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc861_toshiba_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x0f, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0,
+				 0x80, present ? 0x80 : 0);
+	snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0,
+				 0x80, present ? 0x80 : 0);
+	snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3,
+				 0x80, present ? 0 : 0x80);
+	snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3,
+				 0x80, present ? 0 : 0x80);
+}
+
+static void alc861_toshiba_unsol_event(struct hda_codec *codec,
+				       unsigned int res)
+{
+	/* Looks like the unsol event is incompatible with the standard
+	 * definition.  6bit tag is placed at 26 bit!
+	 */
+	if ((res >> 26) == ALC880_HP_EVENT)
+		alc861_toshiba_automute(codec);
+}
+
 /* pcm configuration: identiacal with ALC880 */
 #define alc861_pcm_analog_playback	alc880_pcm_analog_playback
 #define alc861_pcm_analog_capture	alc880_pcm_analog_capture
@@ -6710,19 +7784,29 @@
 /*
  * configuration and preset
  */
-static struct hda_board_config alc861_cfg_tbl[] = {
-	{ .modelname = "3stack", .config = ALC861_3ST },
-	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd600,
-	  .config = ALC861_3ST },
-	{ .modelname = "3stack-660", .config = ALC660_3ST },
-	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x81e7,
-	  .config = ALC660_3ST },
-	{ .modelname = "3stack-dig", .config = ALC861_3ST_DIG },
-	{ .modelname = "6stack-dig", .config = ALC861_6ST_DIG },
-	{ .modelname = "uniwill-m31", .config = ALC861_UNIWILL_M31},
-	{ .pci_subvendor = 0x1584, .pci_subdevice = 0x9072,
-	  .config = ALC861_UNIWILL_M31 },
-	{ .modelname = "auto", .config = ALC861_AUTO },
+static const char *alc861_models[ALC861_MODEL_LAST] = {
+	[ALC861_3ST]		= "3stack",
+	[ALC660_3ST]		= "3stack-660",
+	[ALC861_3ST_DIG]	= "3stack-dig",
+	[ALC861_6ST_DIG]	= "6stack-dig",
+	[ALC861_UNIWILL_M31]	= "uniwill-m31",
+	[ALC861_TOSHIBA]	= "toshiba",
+	[ALC861_ASUS]		= "asus",
+	[ALC861_ASUS_LAPTOP]	= "asus-laptop",
+	[ALC861_AUTO]		= "auto",
+};
+
+static struct snd_pci_quirk alc861_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
+	SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
+	SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
+	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
+	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660_3ST),
+	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
+	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA),
+	SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
+	SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
+	SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
 	{}
 };
 
@@ -6789,8 +7873,48 @@
 		.adc_nids = alc861_adc_nids,
 		.input_mux = &alc861_capture_source,
 	},
-
-};	
+	[ALC861_TOSHIBA] = {
+		.mixers = { alc861_toshiba_mixer },
+		.init_verbs = { alc861_base_init_verbs, alc861_toshiba_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
+		.dac_nids = alc861_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+		.unsol_event = alc861_toshiba_unsol_event,
+		.init_hook = alc861_toshiba_automute,
+	},
+	[ALC861_ASUS] = {
+		.mixers = { alc861_asus_mixer },
+		.init_verbs = { alc861_asus_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
+		.dac_nids = alc861_dac_nids,
+		.dig_out_nid = ALC861_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
+		.channel_mode = alc861_asus_modes,
+		.need_dac_fix = 1,
+		.hp_nid = 0x06,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+	},
+	[ALC861_ASUS_LAPTOP] = {
+		.mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
+		.init_verbs = { alc861_asus_init_verbs,
+				alc861_asus_laptop_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
+		.dac_nids = alc861_dac_nids,
+		.dig_out_nid = ALC861_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.need_dac_fix = 1,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+	},
+};
 
 
 static int patch_alc861(struct hda_codec *codec)
@@ -6799,15 +7923,17 @@
 	int board_config;
 	int err;
 
-	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
 	codec->spec = spec;	
 
-        board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl);
+        board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
+						  alc861_models,
+						  alc861_cfg_tbl);
 
-	if (board_config < 0 || board_config >= ALC861_MODEL_LAST) {
+	if (board_config < 0) {
 		printk(KERN_INFO "hda_codec: Unknown model for ALC861, "
 		       "trying auto-probe from BIOS...\n");
 		board_config = ALC861_AUTO;
@@ -6846,19 +7972,706 @@
 }
 
 /*
+ * ALC861-VD support
+ *
+ * Based on ALC882
+ *
+ * In addition, an independent DAC
+ */
+#define ALC861VD_DIGOUT_NID	0x06
+
+static hda_nid_t alc861vd_dac_nids[4] = {
+	/* front, surr, clfe, side surr */
+	0x02, 0x03, 0x04, 0x05
+};
+
+/* dac_nids for ALC660vd are in a different order - according to
+ * Realtek's driver.
+ * This should probably tesult in a different mixer for 6stack models
+ * of ALC660vd codecs, but for now there is only 3stack mixer
+ * - and it is the same as in 861vd.
+ * adc_nids in ALC660vd are (is) the same as in 861vd
+ */
+static hda_nid_t alc660vd_dac_nids[3] = {
+	/* front, rear, clfe, rear_surr */
+	0x02, 0x04, 0x03
+};
+
+static hda_nid_t alc861vd_adc_nids[1] = {
+	/* ADC0 */
+	0x09,
+};
+
+/* input MUX */
+/* FIXME: should be a matrix-type input source selection */
+static struct hda_input_mux alc861vd_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+#define alc861vd_mux_enum_info alc_mux_enum_info
+#define alc861vd_mux_enum_get alc_mux_enum_get
+
+static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	const struct hda_input_mux *imux = spec->input_mux;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	static hda_nid_t capture_mixers[1] = { 0x22 };
+	hda_nid_t nid = capture_mixers[adc_idx];
+	unsigned int *cur_val = &spec->cur_mux[adc_idx];
+	unsigned int i, idx;
+
+	idx = ucontrol->value.enumerated.item[0];
+	if (idx >= imux->num_items)
+		idx = imux->num_items - 1;
+	if (*cur_val == idx && ! codec->in_resume)
+		return 0;
+	for (i = 0; i < imux->num_items; i++) {
+		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				    v | (imux->items[i].index << 8));
+	}
+	*cur_val = idx;
+	return 1;
+}
+
+/*
+ * 2ch mode
+ */
+static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
+	{ 2, NULL }
+};
+
+/*
+ * 6ch mode
+ */
+static struct hda_verb alc861vd_6stack_ch6_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+/*
+ * 8ch mode
+ */
+static struct hda_verb alc861vd_6stack_ch8_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+static struct hda_channel_mode alc861vd_6stack_modes[2] = {
+	{ 6, alc861vd_6stack_ch6_init },
+	{ 8, alc861vd_6stack_ch8_init },
+};
+
+static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new alc861vd_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 *FIXME: the controls appear in the "playback" view!
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 1,
+		.info = alc861vd_mux_enum_info,
+		.get = alc861vd_mux_enum_get,
+		.put = alc861vd_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
+ *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
+ */
+static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
+				HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
+				HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, 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("Front Mic Boost", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, 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("Front Mic Boost", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+
+	{ } /* end */
+};
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc861vd_volume_init_verbs[] = {
+	/*
+	 * Unmute ADC0 and set the default input to mic-in
+	 */
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
+	 * the analog-loopback mixer widget
+	 */
+	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+	/* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(8)},
+
+	/*
+	 * Set up output mixers (0x02 - 0x05)
+	 */
+	/* set vol=0 to output mixers */
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+	{ }
+};
+
+/*
+ * 3-stack pin configuration:
+ * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
+ */
+static struct hda_verb alc861vd_3stack_init_verbs[] = {
+	/*
+	 * Set pin mode and muting
+	 */
+	/* set front pin widgets 0x14 for output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Mic (rear) pin: input vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin: input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line-2 In: Headphone output (output 0 - 0x0c) */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+/*
+ * 6-stack pin configuration:
+ */
+static struct hda_verb alc861vd_6stack_init_verbs[] = {
+	/*
+	 * Set pin mode and muting
+	 */
+	/* set front pin widgets 0x14 for output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Rear Pin: output 1 (0x0d) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	/* CLFE Pin: output 2 (0x0e) */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* Side Pin: output 3 (0x0f) */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+
+	/* Mic (rear) pin: input vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin: input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line-2 In: Headphone output (output 0 - 0x0c) */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+/* pcm configuration: identiacal with ALC880 */
+#define alc861vd_pcm_analog_playback	alc880_pcm_analog_playback
+#define alc861vd_pcm_analog_capture	alc880_pcm_analog_capture
+#define alc861vd_pcm_digital_playback	alc880_pcm_digital_playback
+#define alc861vd_pcm_digital_capture	alc880_pcm_digital_capture
+
+/*
+ * configuration and preset
+ */
+static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
+	[ALC660VD_3ST]		= "3stack-660",
+	[ALC861VD_3ST]		= "3stack",
+	[ALC861VD_3ST_DIG]	= "3stack-digout",
+	[ALC861VD_6ST_DIG]	= "6stack-digout",
+	[ALC861VD_AUTO]		= "auto",
+};
+
+static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
+	SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
+	SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
+
+	SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_3ST),
+	{}
+};
+
+static struct alc_config_preset alc861vd_presets[] = {
+	[ALC660VD_3ST] = {
+		.mixers = { alc861vd_3st_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+				 alc861vd_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+		.dac_nids = alc660vd_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+		.adc_nids = alc861vd_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_capture_source,
+	},
+	[ALC861VD_3ST] = {
+		.mixers = { alc861vd_3st_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+				 alc861vd_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+		.dac_nids = alc861vd_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_capture_source,
+	},
+	[ALC861VD_3ST_DIG] = {
+		.mixers = { alc861vd_3st_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+		 		 alc861vd_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+		.dac_nids = alc861vd_dac_nids,
+		.dig_out_nid = ALC861VD_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_capture_source,
+	},
+	[ALC861VD_6ST_DIG] = {
+		.mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+				alc861vd_6stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+		.dac_nids = alc861vd_dac_nids,
+		.dig_out_nid = ALC861VD_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
+		.channel_mode = alc861vd_6stack_modes,
+		.input_mux = &alc861vd_capture_source,
+	},
+};
+
+/*
+ * BIOS auto configuration
+ */
+static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
+				hda_nid_t nid, int pin_type, int dac_idx)
+{
+	/* set as output */
+	snd_hda_codec_write(codec, nid, 0,
+				AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+	snd_hda_codec_write(codec, nid, 0,
+				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+}
+
+static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i <= HDA_SIDE; i++) {
+		hda_nid_t nid = spec->autocfg.line_out_pins[i];
+		if (nid)
+			alc861vd_auto_set_output_and_unmute(codec, nid,
+								PIN_OUT, i);
+	}
+}
+
+
+static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t pin;
+
+	pin = spec->autocfg.hp_pins[0];
+	if (pin) /* connect to front and  use dac 0 */
+		alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+}
+
+#define alc861vd_is_input_pin(nid)	alc880_is_input_pin(nid)
+#define ALC861VD_PIN_CD_NID		ALC880_PIN_CD_NID
+
+static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < AUTO_PIN_LAST; i++) {
+		hda_nid_t nid = spec->autocfg.input_pins[i];
+		if (alc861vd_is_input_pin(nid)) {
+			snd_hda_codec_write(codec, nid, 0,
+					AC_VERB_SET_PIN_WIDGET_CONTROL,
+					i <= AUTO_PIN_FRONT_MIC ?
+							PIN_VREF80 : PIN_IN);
+			if (nid != ALC861VD_PIN_CD_NID)
+				snd_hda_codec_write(codec, nid, 0,
+						AC_VERB_SET_AMP_GAIN_MUTE,
+						AMP_OUT_MUTE);
+		}
+	}
+}
+
+#define alc861vd_idx_to_mixer_vol(nid)		((nid) + 0x02)
+#define alc861vd_idx_to_mixer_switch(nid)	((nid) + 0x0c)
+
+/* add playback controls from the parsed DAC table */
+/* Based on ALC880 version. But ALC861VD has separate,
+ * different NIDs for mute/unmute switch and volume control */
+static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
+					     const struct auto_pin_cfg *cfg)
+{
+	char name[32];
+	static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
+	hda_nid_t nid_v, nid_s;
+	int i, err;
+
+	for (i = 0; i < cfg->line_outs; i++) {
+		if (! spec->multiout.dac_nids[i])
+			continue;
+		nid_v = alc861vd_idx_to_mixer_vol(
+				alc880_dac_to_idx(
+					spec->multiout.dac_nids[i]));
+		nid_s = alc861vd_idx_to_mixer_switch(
+				alc880_dac_to_idx(
+					spec->multiout.dac_nids[i]));
+
+		if (i == 2) {
+			/* Center/LFE */
+			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL,
+						"Center Playback Volume",
+						HDA_COMPOSE_AMP_VAL(nid_v, 1,
+							0, HDA_OUTPUT))) < 0)
+				return err;
+			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL,
+						"LFE Playback Volume",
+						HDA_COMPOSE_AMP_VAL(nid_v, 2,
+							0, HDA_OUTPUT))) < 0)
+				return err;
+			if ((err = add_control(spec, ALC_CTL_BIND_MUTE,
+						"Center Playback Switch",
+						HDA_COMPOSE_AMP_VAL(nid_s, 1,
+						2, HDA_INPUT))) < 0)
+				return err;
+			if ((err = add_control(spec, ALC_CTL_BIND_MUTE,
+						"LFE Playback Switch",
+						HDA_COMPOSE_AMP_VAL(nid_s, 2,
+						2, HDA_INPUT))) < 0)
+				return err;
+		} else {
+			sprintf(name, "%s Playback Volume", chname[i]);
+			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+						HDA_COMPOSE_AMP_VAL(nid_v, 3,
+							0, HDA_OUTPUT))) < 0)
+				return err;
+			sprintf(name, "%s Playback Switch", chname[i]);
+			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+						HDA_COMPOSE_AMP_VAL(nid_v, 3,
+							2, HDA_INPUT))) < 0)
+				return err;
+		}
+	}
+	return 0;
+}
+
+/* add playback controls for speaker and HP outputs */
+/* Based on ALC880 version. But ALC861VD has separate,
+ * different NIDs for mute/unmute switch and volume control */
+static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
+					hda_nid_t pin, const char *pfx)
+{
+	hda_nid_t nid_v, nid_s;
+	int err;
+	char name[32];
+
+	if (! pin)
+		return 0;
+
+	if (alc880_is_fixed_pin(pin)) {
+		nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
+		/* specify the DAC as the extra output */
+		if (! spec->multiout.hp_nid)
+			spec->multiout.hp_nid = nid_v;
+		else
+			spec->multiout.extra_out_nid[0] = nid_v;
+		/* control HP volume/switch on the output mixer amp */
+		nid_v = alc861vd_idx_to_mixer_vol(
+				alc880_fixed_pin_idx(pin));
+		nid_s = alc861vd_idx_to_mixer_switch(
+				alc880_fixed_pin_idx(pin));
+
+		sprintf(name, "%s Playback Volume", pfx);
+		if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+				HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
+							HDA_OUTPUT))) < 0)
+			return err;
+		sprintf(name, "%s Playback Switch", pfx);
+		if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+				HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
+							HDA_INPUT))) < 0)
+			return err;
+	} else if (alc880_is_multi_pin(pin)) {
+		/* set manual connection */
+		/* we have only a switch on HP-out PIN */
+		sprintf(name, "%s Playback Switch", pfx);
+		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+				HDA_COMPOSE_AMP_VAL(pin, 3, 0,
+							HDA_OUTPUT))) < 0)
+			return err;
+	}
+	return 0;
+}
+
+/* parse the BIOS configuration and set up the alc_spec
+ * return 1 if successful, 0 if the proper config is not found,
+ * or a negative error code
+ * Based on ALC880 version - had to change it to override
+ * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
+static int alc861vd_parse_auto_config(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int err;
+	static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
+
+	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+						alc861vd_ignore)) < 0)
+		return err;
+	if (! spec->autocfg.line_outs)
+		return 0; /* can't find valid BIOS pin config */
+
+	if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
+		(err = alc861vd_auto_create_multi_out_ctls(spec,
+			&spec->autocfg)) < 0 ||
+		(err = alc861vd_auto_create_extra_out(spec,
+			spec->autocfg.speaker_pins[0], "Speaker")) < 0 ||
+		(err = alc861vd_auto_create_extra_out(spec,
+			spec->autocfg.hp_pins[0], "Headphone")) < 0 ||
+		(err = alc880_auto_create_analog_input_ctls(spec,
+			&spec->autocfg)) < 0)
+		return err;
+
+	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+
+	if (spec->autocfg.dig_out_pin)
+		spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
+
+	if (spec->kctl_alloc)
+		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
+	spec->init_verbs[spec->num_init_verbs++]
+		= alc861vd_volume_init_verbs;
+
+	spec->num_mux_defs = 1;
+	spec->input_mux = &spec->private_imux;
+
+	return 1;
+}
+
+/* additional initialization for auto-configuration model */
+static void alc861vd_auto_init(struct hda_codec *codec)
+{
+	alc861vd_auto_init_multi_out(codec);
+	alc861vd_auto_init_hp_out(codec);
+	alc861vd_auto_init_analog_input(codec);
+}
+
+static int patch_alc861vd(struct hda_codec *codec)
+{
+	struct alc_spec *spec;
+	int err, board_config;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
+						  alc861vd_models,
+						  alc861vd_cfg_tbl);
+
+	if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
+		printk(KERN_INFO "hda_codec: Unknown model for ALC660VD/"
+			"ALC861VD, trying auto-probe from BIOS...\n");
+		board_config = ALC861VD_AUTO;
+	}
+
+	if (board_config == ALC861VD_AUTO) {
+		/* automatic parse from the BIOS config */
+		err = alc861vd_parse_auto_config(codec);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		} else if (! err) {
+			printk(KERN_INFO
+			       "hda_codec: Cannot set up configuration "
+			       "from BIOS.  Using base mode...\n");
+			board_config = ALC861VD_3ST;
+		}
+	}
+
+	if (board_config != ALC861VD_AUTO)
+		setup_preset(spec, &alc861vd_presets[board_config]);
+
+	spec->stream_name_analog = "ALC861VD Analog";
+	spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
+	spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
+
+	spec->stream_name_digital = "ALC861VD Digital";
+	spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
+	spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
+
+	spec->adc_nids = alc861vd_adc_nids;
+	spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
+
+	spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
+	spec->num_mixers++;
+
+	codec->patch_ops = alc_patch_ops;
+
+	if (board_config == ALC861VD_AUTO)
+		spec->init_hook = alc861vd_auto_init;
+
+	return 0;
+}
+
+/*
  * patch entries
  */
 struct hda_codec_preset snd_hda_preset_realtek[] = {
 	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
 	{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
- 	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
+	{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
+		.patch = patch_alc861 },
+	{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
+	{ .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
+	{ .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
+	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
 	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
 	{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
 	{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
 	{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
-	{ .id = 0x10ec0861, .rev = 0x100300, .name = "ALC861",
-	  .patch = patch_alc861 },
-        { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
-	  .patch = patch_alc861 },
 	{} /* terminator */
 };
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index fe51ef3..f7ef9c5 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -37,14 +37,37 @@
 #define NUM_CONTROL_ALLOC	32
 #define STAC_HP_EVENT		0x37
 
-#define STAC_REF		0
-#define STAC_D945GTP3		1
-#define STAC_D945GTP5		2
-#define STAC_MACMINI		3
-#define STAC_922X_MODELS	4	/* number of 922x models */
-#define STAC_D965_3ST		4
-#define STAC_D965_5ST		5
-#define STAC_927X_MODELS	6	/* number of 922x models */
+enum {
+	STAC_REF,
+	STAC_9200_MODELS
+};
+
+enum {
+	STAC_9205_REF,
+	STAC_9205_MODELS
+};
+
+enum {
+	STAC_925x_REF,
+	STAC_M2_2,
+	STAC_MA6,
+	STAC_925x_MODELS
+};
+
+enum {
+	STAC_D945_REF,
+	STAC_D945GTP3,
+	STAC_D945GTP5,
+	STAC_MACMINI,
+	STAC_922X_MODELS
+};
+
+enum {
+	STAC_D965_REF,
+	STAC_D965_3ST,
+	STAC_D965_5ST,
+	STAC_927X_MODELS
+};
 
 struct sigmatel_spec {
 	struct snd_kcontrol_new *mixers[4];
@@ -67,6 +90,9 @@
 	unsigned int num_adcs;
 	hda_nid_t *mux_nids;
 	unsigned int num_muxes;
+	hda_nid_t *dmic_nids;
+	unsigned int num_dmics;
+	hda_nid_t dmux_nid;
 	hda_nid_t dig_in_nid;
 
 	/* pin widgets */
@@ -80,6 +106,8 @@
 	struct snd_kcontrol_new *mixer;
 
 	/* capture source */
+	struct hda_input_mux *dinput_mux;
+	unsigned int cur_dmux;
 	struct hda_input_mux *input_mux;
 	unsigned int cur_mux[3];
 
@@ -92,6 +120,7 @@
 	struct auto_pin_cfg autocfg;
 	unsigned int num_kctl_alloc, num_kctl_used;
 	struct snd_kcontrol_new *kctl_alloc;
+	struct hda_input_mux private_dimux;
 	struct hda_input_mux private_imux;
 };
 
@@ -107,6 +136,18 @@
         0x02,
 };
 
+static hda_nid_t stac925x_adc_nids[1] = {
+        0x03,
+};
+
+static hda_nid_t stac925x_mux_nids[1] = {
+        0x0f,
+};
+
+static hda_nid_t stac925x_dac_nids[1] = {
+        0x02,
+};
+
 static hda_nid_t stac922x_adc_nids[2] = {
         0x06, 0x07,
 };
@@ -131,11 +172,20 @@
         0x19, 0x1a
 };
 
+static hda_nid_t stac9205_dmic_nids[3] = {
+        0x17, 0x18, 0
+};
+
 static hda_nid_t stac9200_pin_nids[8] = {
 	0x08, 0x09, 0x0d, 0x0e, 
 	0x0f, 0x10, 0x11, 0x12,
 };
 
+static hda_nid_t stac925x_pin_nids[8] = {
+	0x07, 0x08, 0x0a, 0x0b, 
+	0x0c, 0x0d, 0x10, 0x11,
+};
+
 static hda_nid_t stac922x_pin_nids[10] = {
 	0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
 	0x0f, 0x10, 0x11, 0x15, 0x1b,
@@ -154,6 +204,34 @@
 	
 };
 
+static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sigmatel_spec *spec = codec->spec;
+	return snd_hda_input_mux_info(spec->dinput_mux, uinfo);
+}
+
+static int stac92xx_dmux_enum_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sigmatel_spec *spec = codec->spec;
+
+	ucontrol->value.enumerated.item[0] = spec->cur_dmux;
+	return 0;
+}
+
+static int stac92xx_dmux_enum_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sigmatel_spec *spec = codec->spec;
+
+	return snd_hda_input_mux_put(codec, spec->dinput_mux, ucontrol,
+				     spec->dmux_nid, &spec->cur_dmux);
+}
+
 static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -187,6 +265,12 @@
 	{}
 };
 
+static struct hda_verb stac925x_core_init[] = {
+	/* set dac0mux for dac converter */
+	{ 0x06, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{}
+};
+
 static struct hda_verb stac922x_core_init[] = {
 	/* set master volume and direct control */	
 	{ 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
@@ -232,6 +316,23 @@
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new stac925x_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Input Source",
+		.count = 1,
+		.info = stac92xx_mux_enum_info,
+		.get = stac92xx_mux_enum_get,
+		.put = stac92xx_mux_enum_put,
+	},
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT),
+	{ } /* end */
+};
+
 /* This needs to be generated dynamically based on sequence */
 static struct snd_kcontrol_new stac922x_mixer[] = {
 	{
@@ -263,7 +364,7 @@
 	{ } /* end */
 };
 
-static snd_kcontrol_new_t stac927x_mixer[] = {
+static struct snd_kcontrol_new stac927x_mixer[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Input Source",
@@ -278,7 +379,15 @@
 	{ } /* end */
 };
 
-static snd_kcontrol_new_t stac9205_mixer[] = {
+static struct snd_kcontrol_new stac9205_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Digital Input Source",
+		.count = 1,
+		.info = stac92xx_dmux_enum_info,
+		.get = stac92xx_dmux_enum_get,
+		.put = stac92xx_dmux_enum_put,
+	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Input Source",
@@ -327,22 +436,68 @@
 	0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
 };
 
-static unsigned int *stac9200_brd_tbl[] = {
-	ref9200_pin_configs,
+static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
+	[STAC_REF] = ref9200_pin_configs,
 };
 
-static struct hda_board_config stac9200_cfg_tbl[] = {
-	{ .modelname = "ref",
-	  .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2668,	/* DFI LanParty */
-	  .config = STAC_REF },
+static const char *stac9200_models[STAC_9200_MODELS] = {
+	[STAC_REF] = "ref",
+};
+
+static struct snd_pci_quirk stac9200_cfg_tbl[] = {
+	/* SigmaTel reference board */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
+		      "DFI LanParty", STAC_REF),
 	/* Dell laptops have BIOS problem */
-	{ .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01b5,
-	  .config = STAC_REF },	/* Dell Inspiron 630m */
-	{ .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01c2,
-	  .config = STAC_REF },	/* Dell Latitude D620 */
-	{ .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01cb,
-	  .config = STAC_REF },	/* Dell Latitude 120L */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5,
+		      "Dell Inspiron 630m", STAC_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2,
+		      "Dell Latitude D620", STAC_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb,
+		      "Dell Latitude 120L", STAC_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc,
+		      "Dell Latitude D820", STAC_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd,
+		      "Dell Inspiron E1705/9400", STAC_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce,
+		      "Dell XPS M1710", STAC_REF),
+	{} /* terminator */
+};
+
+static unsigned int ref925x_pin_configs[8] = {
+	0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,
+	0x90a70320, 0x02214210, 0x400003f1, 0x9033032e,
+};
+
+static unsigned int stac925x_MA6_pin_configs[8] = {
+	0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,
+	0x90a70320, 0x90100211, 0x400003f1, 0x9033032e,
+};
+
+static unsigned int stac925xM2_2_pin_configs[8] = {
+	0x40c003f3, 0x424503f2, 0x041800f4, 0x02a19020,
+	0x50a103F0, 0x90100210, 0x400003f1, 0x9033032e,
+};
+
+static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {
+	[STAC_REF] = ref925x_pin_configs,
+	[STAC_M2_2] = stac925xM2_2_pin_configs,
+	[STAC_MA6] = stac925x_MA6_pin_configs,
+};
+
+static const char *stac925x_models[STAC_925x_MODELS] = {
+	[STAC_REF] = "ref",
+	[STAC_M2_2] = "m2-2",
+	[STAC_MA6] = "m6",
+};
+
+static struct snd_pci_quirk stac925x_cfg_tbl[] = {
+	/* SigmaTel reference board */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),
+	SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_REF),
+	SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_REF),
+	SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_MA6),
+	SND_PCI_QUIRK(0x1002, 0x437b, "Gateway MX6453", STAC_M2_2),
 	{} /* terminator */
 };
 
@@ -365,100 +520,80 @@
 };
 
 static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
-	[STAC_REF] =	ref922x_pin_configs,
+	[STAC_D945_REF] = ref922x_pin_configs,
 	[STAC_D945GTP3] = d945gtp3_pin_configs,
 	[STAC_D945GTP5] = d945gtp5_pin_configs,
 	[STAC_MACMINI] = d945gtp5_pin_configs,
 };
 
-static struct hda_board_config stac922x_cfg_tbl[] = {
-	{ .modelname = "5stack", .config = STAC_D945GTP5 },
-	{ .modelname = "3stack", .config = STAC_D945GTP3 },
-	{ .modelname = "ref",
-	  .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2668,	/* DFI LanParty */
-	  .config = STAC_REF },		/* SigmaTel reference board */
-         /* Intel 945G based systems */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0101,
-	  .config = STAC_D945GTP3 },	/* Intel D945GTP - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0202,
-	  .config = STAC_D945GTP3 },	/* Intel D945GNT - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0606,
-	  .config = STAC_D945GTP3 },	/* Intel D945GTP - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0601,
-	  .config = STAC_D945GTP3 },	/* Intel D945GTP - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0111,
-	  .config = STAC_D945GTP3 },	/* Intel D945GZP - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x1115,
-	  .config = STAC_D945GTP3 },	/* Intel D945GPM - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x1116,
-	  .config = STAC_D945GTP3 },	/* Intel D945GBO - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x1117,
-	  .config = STAC_D945GTP3 },	/* Intel D945GPM - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x1118,
-	  .config = STAC_D945GTP3 },	/* Intel D945GPM - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x1119,
-	  .config = STAC_D945GTP3 },	/* Intel D945GPM - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x8826,
-	  .config = STAC_D945GTP3 },	/* Intel D945GPM - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x5049,
-	  .config = STAC_D945GTP3 },	/* Intel D945GCZ - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x5055,
-	  .config = STAC_D945GTP3 },	/* Intel D945GCZ - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x5048,
-	  .config = STAC_D945GTP3 },	/* Intel D945GPB - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0110,
-	  .config = STAC_D945GTP3 },	/* Intel D945GLR - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0404,
-	  .config = STAC_D945GTP5 },	/* Intel D945GTP - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0303,
-	  .config = STAC_D945GTP5 },	/* Intel D945GNT - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0013,
-	  .config = STAC_D945GTP5 },	/* Intel D955XBK - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0417,
-	  .config = STAC_D945GTP5 },	/* Intel D975XBK - 5 Stack */
-	  /* Intel 945P based systems */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0b0b,
-	  .config = STAC_D945GTP3 },	/* Intel D945PSN - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0112,
-	  .config = STAC_D945GTP3 },	/* Intel D945PLN - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0d0d,
-	  .config = STAC_D945GTP3 },	/* Intel D945PLM - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0909,
-	  .config = STAC_D945GTP3 },	/* Intel D945PAW - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0505,
-	  .config = STAC_D945GTP3 },	/* Intel D945PLM - 3 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x0707,
-	  .config = STAC_D945GTP5 },	/* Intel D945PSV - 5 Stack */
-	  /* other systems  */
-	{ .pci_subvendor = 0x8384,
-	  .pci_subdevice = 0x7680,
-	  .config = STAC_MACMINI },	/* Apple Mac Mini (early 2006) */
+static const char *stac922x_models[STAC_922X_MODELS] = {
+	[STAC_D945_REF]	= "ref",
+	[STAC_D945GTP5]	= "5stack",
+	[STAC_D945GTP3]	= "3stack",
+	[STAC_MACMINI]	= "macmini",
+};
+
+static struct snd_pci_quirk stac922x_cfg_tbl[] = {
+	/* SigmaTel reference board */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
+		      "DFI LanParty", STAC_D945_REF),
+	/* Intel 945G based systems */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0202,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0606,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0601,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0111,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1115,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1116,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1117,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1118,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1119,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x8826,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5049,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5055,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5048,
+		      "Intel D945G", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0110,
+		      "Intel D945G", STAC_D945GTP3),
+	/* Intel D945G 5-stack systems */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0404,
+		      "Intel D945G", STAC_D945GTP5),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0303,
+		      "Intel D945G", STAC_D945GTP5),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0013,
+		      "Intel D945G", STAC_D945GTP5),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0417,
+		      "Intel D945G", STAC_D945GTP5),
+	/* Intel 945P based systems */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0b0b,
+		      "Intel D945P", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0112,
+		      "Intel D945P", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0d0d,
+		      "Intel D945P", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0909,
+		      "Intel D945P", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0505,
+		      "Intel D945P", STAC_D945GTP3),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707,
+		      "Intel D945P", STAC_D945GTP5),
+	/* other systems  */
+	/* Apple Mac Mini (early 2006) */
+	SND_PCI_QUIRK(0x8384, 0x7680,
+		      "Mac Mini", STAC_MACMINI),
 	{} /* terminator */
 };
 
@@ -484,120 +619,72 @@
 };
 
 static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
-	[STAC_REF] =	ref927x_pin_configs,
+	[STAC_D965_REF] = ref927x_pin_configs,
 	[STAC_D965_3ST] = d965_3st_pin_configs,
 	[STAC_D965_5ST] = d965_5st_pin_configs,
 };
 
-static struct hda_board_config stac927x_cfg_tbl[] = {
-	{ .modelname = "5stack", .config = STAC_D965_5ST },
-	{ .modelname = "3stack", .config = STAC_D965_3ST },
-	{ .modelname = "ref",
-	  .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2668,	/* DFI LanParty */
-	  .config = STAC_REF },		/* SigmaTel reference board */
+static const char *stac927x_models[STAC_927X_MODELS] = {
+	[STAC_D965_REF]	= "ref",
+	[STAC_D965_3ST]	= "3stack",
+	[STAC_D965_5ST] = "5stack",
+};
+
+static struct snd_pci_quirk stac927x_cfg_tbl[] = {
+	/* SigmaTel reference board */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
+		      "DFI LanParty", STAC_D965_REF),
 	 /* Intel 946 based systems */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x3d01,
-	  .config = STAC_D965_3ST }, /* D946  configuration */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0xa301,
-	  .config = STAC_D965_3ST }, /* Intel D946GZT - 3 stack  */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST),
 	/* 965 based 3 stack systems */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2116,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2115,
-	  .config = STAC_D965_3ST }, /* Intel DQ965WC - 3 Stack  */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2114,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2113,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2112,
-	  .config = STAC_D965_3ST }, /* Intel DG965MS - 3 Stack  */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2111,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2110,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2009,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2008,
-	  .config = STAC_D965_3ST }, /* Intel DQ965GF - 3 Stack  */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2007,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2006,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2005,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2004,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2003,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2002,
-	  .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2001,
-	  .config = STAC_D965_3ST }, /* Intel DQ965GF - 3 Stack */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2116, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2115, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2114, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2113, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2112, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2111, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2110, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2009, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2008, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2007, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2006, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2005, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2004, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST),
 	/* 965 based 5 stack systems */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2301,
-	  .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2302,
-	  .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2303,
-	  .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2304,
-	  .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2305,
-	  .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2501,
-	  .config = STAC_D965_5ST }, /* Intel DG965MQ - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2502,
-	  .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2503,
-	  .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
-	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2504,
-	  .config = STAC_D965_5ST }, /* Intel DQ965GF - 5 Stack */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2304, "Intel D965", STAC_D965_5ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2305, "Intel D965", STAC_D965_5ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2501, "Intel D965", STAC_D965_5ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2502, "Intel D965", STAC_D965_5ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2503, "Intel D965", STAC_D965_5ST),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2504, "Intel D965", STAC_D965_5ST),
 	{} /* terminator */
 };
 
 static unsigned int ref9205_pin_configs[12] = {
 	0x40000100, 0x40000100, 0x01016011, 0x01014010,
-	0x01813122, 0x01a19021, 0x40000100, 0x40000100, 
-	0x40000100, 0x40000100, 0x01441030, 0x01c41030
+	0x01813122, 0x01a19021, 0x40000100, 0x40000100,
+	0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030
 };
 
-static unsigned int *stac9205_brd_tbl[] = {
+static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
 	ref9205_pin_configs,
 };
 
-static struct hda_board_config stac9205_cfg_tbl[] = {
-	{ .modelname = "ref",
-	  .pci_subvendor = PCI_VENDOR_ID_INTEL,
-	  .pci_subdevice = 0x2668,	/* DFI LanParty */
-	  .config = STAC_REF },		/* SigmaTel reference board */
+static const char *stac9205_models[STAC_9205_MODELS] = {
+	[STAC_9205_REF] = "ref",
+};
+
+static struct snd_pci_quirk stac9205_cfg_tbl[] = {
+	/* SigmaTel reference board */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
+		      "DFI LanParty", STAC_9205_REF),
 	{} /* terminator */
 };
 
@@ -1154,6 +1241,58 @@
 	return 0;
 }
 
+/* labels for dmic mux inputs */
+static const char *stac92xx_dmic_labels[5] = {
+	"Analog Inputs", "Digital Mic 1", "Digital Mic 2",
+	"Digital Mic 3", "Digital Mic 4"
+};
+
+/* create playback/capture controls for input pins on dmic capable codecs */
+static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
+						const struct auto_pin_cfg *cfg)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	struct hda_input_mux *dimux = &spec->private_dimux;
+	hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];
+	int i, j;
+
+	dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0];
+	dimux->items[dimux->num_items].index = 0;
+	dimux->num_items++;
+
+	for (i = 0; i < spec->num_dmics; i++) {
+		int index;
+		int num_cons;
+		unsigned int def_conf;
+
+		def_conf = snd_hda_codec_read(codec,
+					      spec->dmic_nids[i],
+					      0,
+					      AC_VERB_GET_CONFIG_DEFAULT,
+					      0);
+		if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
+			continue;
+
+		num_cons = snd_hda_get_connections(codec,
+				spec->dmux_nid,
+				con_lst,
+				HDA_MAX_NUM_INPUTS);
+		for (j = 0; j < num_cons; j++)
+			if (con_lst[j] == spec->dmic_nids[i]) {
+				index = j;
+				goto found;
+			}
+		continue;
+found:
+		dimux->items[dimux->num_items].label =
+			stac92xx_dmic_labels[dimux->num_items];
+		dimux->items[dimux->num_items].index = index;
+		dimux->num_items++;
+	}
+
+	return 0;
+}
+
 /* create playback/capture controls for input pins */
 static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
 {
@@ -1238,7 +1377,9 @@
 	struct sigmatel_spec *spec = codec->spec;
 	int err;
 
-	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
+	if ((err = snd_hda_parse_pin_def_config(codec,
+						&spec->autocfg,
+						spec->dmic_nids)) < 0)
 		return err;
 	if (! spec->autocfg.line_outs)
 		return 0; /* can't find valid pin config */
@@ -1254,6 +1395,11 @@
 	    (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
 		return err;
 
+	if (spec->num_dmics > 0)
+		if ((err = stac92xx_auto_create_dmic_input_ctls(codec,
+						&spec->autocfg)) < 0)
+			return err;
+
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 	if (spec->multiout.max_channels > 2)
 		spec->surr_switch = 1;
@@ -1267,6 +1413,7 @@
 		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
 
 	spec->input_mux = &spec->private_imux;
+	spec->dinput_mux = &spec->private_dimux;
 
 	return 1;
 }
@@ -1366,6 +1513,7 @@
 		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
 
 	spec->input_mux = &spec->private_imux;
+	spec->dinput_mux = &spec->private_dimux;
 
 	return 1;
 }
@@ -1448,6 +1596,11 @@
 			stac92xx_auto_set_pinctl(codec, nid, pinctl);
 		}
 	}
+	if (spec->num_dmics > 0)
+		for (i = 0; i < spec->num_dmics; i++)
+			stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
+						 AC_PINCTL_IN_EN);
+
 	if (cfg->dig_out_pin)
 		stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
 					 AC_PINCTL_OUT_EN);
@@ -1598,7 +1751,9 @@
 	codec->spec = spec;
 	spec->num_pins = 8;
 	spec->pin_nids = stac9200_pin_nids;
-	spec->board_config = snd_hda_check_board_config(codec, stac9200_cfg_tbl);
+	spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
+							stac9200_models,
+							stac9200_cfg_tbl);
 	if (spec->board_config < 0) {
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
 		err = stac92xx_save_bios_config_regs(codec);
@@ -1618,6 +1773,7 @@
 	spec->adc_nids = stac9200_adc_nids;
 	spec->mux_nids = stac9200_mux_nids;
 	spec->num_muxes = 1;
+	spec->num_dmics = 0;
 
 	spec->init = stac9200_core_init;
 	spec->mixer = stac9200_mixer;
@@ -1633,6 +1789,66 @@
 	return 0;
 }
 
+static int patch_stac925x(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec;
+	int err;
+
+	spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+	spec->num_pins = 8;
+	spec->pin_nids = stac925x_pin_nids;
+	spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS,
+							stac925x_models,
+							stac925x_cfg_tbl);
+ again:
+	if (spec->board_config < 0) {
+		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x, using BIOS defaults\n");
+		err = stac92xx_save_bios_config_regs(codec);
+		if (err < 0) {
+			stac92xx_free(codec);
+			return err;
+		}
+		spec->pin_configs = spec->bios_pin_configs;
+	} else if (stac925x_brd_tbl[spec->board_config] != NULL){
+		spec->pin_configs = stac925x_brd_tbl[spec->board_config];
+		stac92xx_set_config_regs(codec);
+	}
+
+	spec->multiout.max_channels = 2;
+	spec->multiout.num_dacs = 1;
+	spec->multiout.dac_nids = stac925x_dac_nids;
+	spec->adc_nids = stac925x_adc_nids;
+	spec->mux_nids = stac925x_mux_nids;
+	spec->num_muxes = 1;
+	spec->num_dmics = 0;
+
+	spec->init = stac925x_core_init;
+	spec->mixer = stac925x_mixer;
+
+	err = stac92xx_parse_auto_config(codec, 0x8, 0x7);
+	if (!err) {
+		if (spec->board_config < 0) {
+			printk(KERN_WARNING "hda_codec: No auto-config is "
+			       "available, default to model=ref\n");
+			spec->board_config = STAC_925x_REF;
+			goto again;
+		}
+		err = -EINVAL;
+	}
+	if (err < 0) {
+		stac92xx_free(codec);
+		return err;
+	}
+
+	codec->patch_ops = stac92xx_patch_ops;
+
+	return 0;
+}
+
 static int patch_stac922x(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec;
@@ -1645,7 +1861,10 @@
 	codec->spec = spec;
 	spec->num_pins = 10;
 	spec->pin_nids = stac922x_pin_nids;
-	spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl);
+	spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
+							stac922x_models,
+							stac922x_cfg_tbl);
+ again:
 	if (spec->board_config < 0) {
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
 			"using BIOS defaults\n");
@@ -1663,6 +1882,7 @@
 	spec->adc_nids = stac922x_adc_nids;
 	spec->mux_nids = stac922x_mux_nids;
 	spec->num_muxes = 2;
+	spec->num_dmics = 0;
 
 	spec->init = stac922x_core_init;
 	spec->mixer = stac922x_mixer;
@@ -1670,6 +1890,15 @@
 	spec->multiout.dac_nids = spec->dac_nids;
 	
 	err = stac92xx_parse_auto_config(codec, 0x08, 0x09);
+	if (!err) {
+		if (spec->board_config < 0) {
+			printk(KERN_WARNING "hda_codec: No auto-config is "
+			       "available, default to model=ref\n");
+			spec->board_config = STAC_D945_REF;
+			goto again;
+		}
+		err = -EINVAL;
+	}
 	if (err < 0) {
 		stac92xx_free(codec);
 		return err;
@@ -1695,7 +1924,10 @@
 	codec->spec = spec;
 	spec->num_pins = 14;
 	spec->pin_nids = stac927x_pin_nids;
-	spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl);
+	spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
+							stac927x_models,
+							stac927x_cfg_tbl);
+ again:
 	if (spec->board_config < 0) {
                 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n");
 		err = stac92xx_save_bios_config_regs(codec);
@@ -1714,6 +1946,7 @@
 		spec->adc_nids = stac927x_adc_nids;
 		spec->mux_nids = stac927x_mux_nids;
 		spec->num_muxes = 3;
+		spec->num_dmics = 0;
 		spec->init = d965_core_init;
 		spec->mixer = stac9227_mixer;
 		break;
@@ -1721,6 +1954,7 @@
 		spec->adc_nids = stac927x_adc_nids;
 		spec->mux_nids = stac927x_mux_nids;
 		spec->num_muxes = 3;
+		spec->num_dmics = 0;
 		spec->init = d965_core_init;
 		spec->mixer = stac9227_mixer;
 		break;
@@ -1728,6 +1962,7 @@
 		spec->adc_nids = stac927x_adc_nids;
 		spec->mux_nids = stac927x_mux_nids;
 		spec->num_muxes = 3;
+		spec->num_dmics = 0;
 		spec->init = stac927x_core_init;
 		spec->mixer = stac927x_mixer;
 	}
@@ -1735,6 +1970,15 @@
 	spec->multiout.dac_nids = spec->dac_nids;
 
 	err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
+	if (!err) {
+		if (spec->board_config < 0) {
+			printk(KERN_WARNING "hda_codec: No auto-config is "
+			       "available, default to model=ref\n");
+			spec->board_config = STAC_D965_REF;
+			goto again;
+		}
+		err = -EINVAL;
+	}
 	if (err < 0) {
 		stac92xx_free(codec);
 		return err;
@@ -1757,7 +2001,10 @@
 	codec->spec = spec;
 	spec->num_pins = 14;
 	spec->pin_nids = stac9205_pin_nids;
-	spec->board_config = snd_hda_check_board_config(codec, stac9205_cfg_tbl);
+	spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
+							stac9205_models,
+							stac9205_cfg_tbl);
+ again:
 	if (spec->board_config < 0) {
 		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
 		err = stac92xx_save_bios_config_regs(codec);
@@ -1773,14 +2020,38 @@
 
 	spec->adc_nids = stac9205_adc_nids;
 	spec->mux_nids = stac9205_mux_nids;
-	spec->num_muxes = 3;
+	spec->num_muxes = 2;
+	spec->dmic_nids = stac9205_dmic_nids;
+	spec->num_dmics = 2;
+	spec->dmux_nid = 0x1d;
 
 	spec->init = stac9205_core_init;
 	spec->mixer = stac9205_mixer;
 
 	spec->multiout.dac_nids = spec->dac_nids;
 
+	/* Configure GPIO0 as EAPD output */
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_DIRECTION, 0x00000001);
+	/* Configure GPIO0 as CMOS */
+	snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000);
+	/* Assert GPIO0 high */
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_DATA, 0x00000001);
+	/* Enable GPIO0 */
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_MASK, 0x00000001);
+
 	err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);
+	if (!err) {
+		if (spec->board_config < 0) {
+			printk(KERN_WARNING "hda_codec: No auto-config is "
+			       "available, default to model=ref\n");
+			spec->board_config = STAC_9205_REF;
+			goto again;
+		}
+		err = -EINVAL;
+	}
 	if (err < 0) {
 		stac92xx_free(codec);
 		return err;
@@ -1963,18 +2234,19 @@
        /* Unknown. id=0x83847661 and subsys=0x104D1200. */
        STAC9872K_VAIO,
        /* AR Series. id=0x83847664 and subsys=104D1300 */
-       CXD9872AKD_VAIO 
-     };
+       CXD9872AKD_VAIO,
+       STAC_9872_MODELS,
+};
 
-static struct hda_board_config stac9872_cfg_tbl[] = {
-	{ .modelname = "vaio", .config = CXD9872RD_VAIO },
-	{ .modelname = "vaio-ar", .config = CXD9872AKD_VAIO },
-	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81e6,
-	  .config = CXD9872RD_VAIO },
-	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81ef,
-	  .config = CXD9872RD_VAIO },
-	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81fd,
-	  .config = CXD9872AKD_VAIO },
+static const char *stac9872_models[STAC_9872_MODELS] = {
+	[CXD9872RD_VAIO]	= "vaio",
+	[CXD9872AKD_VAIO]	= "vaio-ar",
+};
+
+static struct snd_pci_quirk stac9872_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO),
+	SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO),
+	SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO),
 	{}
 };
 
@@ -1983,7 +2255,9 @@
 	struct sigmatel_spec *spec;
 	int board_config;
 
-	board_config = snd_hda_check_board_config(codec, stac9872_cfg_tbl);
+	board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
+						  stac9872_models,
+						  stac9872_cfg_tbl);
 	if (board_config < 0)
 		/* unknown config, let generic-parser do its job... */
 		return snd_hda_parse_generic_codec(codec);
@@ -2055,6 +2329,12 @@
  	{ .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x },
  	{ .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x },
  	{ .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x },
+	{ .id = 0x83847632, .name = "STAC9202",  .patch = patch_stac925x },
+	{ .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac925x },
+	{ .id = 0x83847634, .name = "STAC9250", .patch = patch_stac925x },
+	{ .id = 0x83847635, .name = "STAC9250D", .patch = patch_stac925x },
+	{ .id = 0x83847636, .name = "STAC9251", .patch = patch_stac925x },
+	{ .id = 0x83847637, .name = "STAC9250D", .patch = patch_stac925x },
  	/* The following does not take into account .id=0x83847661 when subsys =
  	 * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are
  	 * currently not fully supported.
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
new file mode 100644
index 0000000..4c839b0
--- /dev/null
+++ b/sound/pci/hda/patch_via.c
@@ -0,0 +1,1396 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for VIA VT1708 codec
+ *
+ * Copyright (c) 2006 Lydia Wang <lydiawang@viatech.com>
+ *                    Takashi Iwai <tiwai@suse.de>
+ *
+ *  This driver 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 driver 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
+ */
+
+/* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
+/*                                                                           */
+/* 2006-03-03  Lydia Wang  Create the basic patch to support VT1708 codec    */
+/* 2006-03-14  Lydia Wang  Modify hard code for some pin widget nid          */
+/* 2006-08-02  Lydia Wang  Add support to VT1709 codec                       */
+/* 2006-09-08  Lydia Wang  Fix internal loopback recording source select bug */
+/*                                                                           */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+
+/* amp values */
+#define AMP_VAL_IDX_SHIFT	19
+#define AMP_VAL_IDX_MASK	(0x0f<<19)
+
+#define NUM_CONTROL_ALLOC	32
+#define NUM_VERB_ALLOC		32
+
+/* Pin Widget NID */
+#define VT1708_HP_NID		0x13
+#define VT1708_DIGOUT_NID	0x14
+#define VT1708_DIGIN_NID	0x16
+
+#define VT1709_HP_DAC_NID	0x28
+#define VT1709_DIGOUT_NID	0x13
+#define VT1709_DIGIN_NID	0x17
+
+#define IS_VT1708_VENDORID(x)		((x) >= 0x11061708 && (x) <= 0x1106170b)
+#define IS_VT1709_10CH_VENDORID(x)	((x) >= 0x1106e710 && (x) <= 0x1106e713)
+#define IS_VT1709_6CH_VENDORID(x)	((x) >= 0x1106e714 && (x) <= 0x1106e717)
+
+
+enum {
+	VIA_CTL_WIDGET_VOL,
+	VIA_CTL_WIDGET_MUTE,
+};
+
+enum {
+	AUTO_SEQ_FRONT,
+	AUTO_SEQ_SURROUND,
+	AUTO_SEQ_CENLFE,
+	AUTO_SEQ_SIDE
+};
+
+static struct snd_kcontrol_new vt1708_control_templates[] = {
+	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
+	HDA_CODEC_MUTE(NULL, 0, 0, 0),
+};
+
+
+struct via_spec {
+	/* codec parameterization */
+	struct snd_kcontrol_new *mixers[3];
+	unsigned int num_mixers;
+
+	struct hda_verb *init_verbs;
+
+	char *stream_name_analog;
+	struct hda_pcm_stream *stream_analog_playback;
+	struct hda_pcm_stream *stream_analog_capture;
+
+	char *stream_name_digital;
+	struct hda_pcm_stream *stream_digital_playback;
+	struct hda_pcm_stream *stream_digital_capture;
+
+	/* playback */
+	struct hda_multi_out multiout;
+
+	/* capture */
+	unsigned int num_adc_nids;
+	hda_nid_t *adc_nids;
+	hda_nid_t dig_in_nid;
+
+	/* capture source */
+	const struct hda_input_mux *input_mux;
+	unsigned int cur_mux[3];
+
+	/* PCM information */
+	struct hda_pcm pcm_rec[2];
+
+	/* dynamic controls, init_verbs and input_mux */
+	struct auto_pin_cfg autocfg;
+	unsigned int num_kctl_alloc, num_kctl_used;
+	struct snd_kcontrol_new *kctl_alloc;
+	struct hda_input_mux private_imux;
+	hda_nid_t private_dac_nids[4];	
+};
+
+static hda_nid_t vt1708_adc_nids[2] = {
+	/* ADC1-2 */
+	0x15, 0x27
+};
+
+static hda_nid_t vt1709_adc_nids[3] = {
+	/* ADC1-2 */
+	0x14, 0x15, 0x16
+};
+
+/* add dynamic controls */
+static int via_add_control(struct via_spec *spec, int type, const char *name,
+			   unsigned long val)
+{
+	struct snd_kcontrol_new *knew;
+
+	if (spec->num_kctl_used >= spec->num_kctl_alloc) {
+		int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
+
+		/* array + terminator */
+		knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
+		if (!knew)
+			return -ENOMEM;
+		if (spec->kctl_alloc) {
+			memcpy(knew, spec->kctl_alloc,
+			       sizeof(*knew) * spec->num_kctl_alloc);
+			kfree(spec->kctl_alloc);
+		}
+		spec->kctl_alloc = knew;
+		spec->num_kctl_alloc = num;
+	}
+
+	knew = &spec->kctl_alloc[spec->num_kctl_used];
+	*knew = vt1708_control_templates[type];
+	knew->name = kstrdup(name, GFP_KERNEL);
+
+	if (!knew->name)
+		return -ENOMEM;
+	knew->private_value = val;
+	spec->num_kctl_used++;
+	return 0;
+}
+
+/* create input playback/capture controls for the given pin */
+static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
+				const char *ctlname, int idx, int mix_nid)
+{
+	char name[32];
+	int err;
+
+	sprintf(name, "%s Playback Volume", ctlname);
+	err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+			      HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
+	if (err < 0)
+		return err;
+	sprintf(name, "%s Playback Switch", ctlname);
+	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
+			      HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+static void via_auto_set_output_and_unmute(struct hda_codec *codec,
+					   hda_nid_t nid, int pin_type,
+					   int dac_idx)
+{
+	/* set as output */
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    pin_type);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+			    AMP_OUT_UNMUTE);
+}
+
+
+static void via_auto_init_multi_out(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
+		hda_nid_t nid = spec->autocfg.line_out_pins[i];
+		if (nid)
+			via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
+	}
+}
+
+static void via_auto_init_hp_out(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	hda_nid_t pin;
+
+	pin = spec->autocfg.hp_pins[0];
+	if (pin) /* connect to front */
+		via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+}
+
+static void via_auto_init_analog_input(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < AUTO_PIN_LAST; i++) {
+		hda_nid_t nid = spec->autocfg.input_pins[i];
+
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL,
+				    (i <= AUTO_PIN_FRONT_MIC ?
+				     PIN_VREF50 : PIN_IN));
+
+	}
+}
+/*
+ * input MUX handling
+ */
+static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct via_spec *spec = codec->spec;
+	return snd_hda_input_mux_info(spec->input_mux, uinfo);
+}
+
+static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct via_spec *spec = codec->spec;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+	return 0;
+}
+
+static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct via_spec *spec = codec->spec;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	unsigned int vendor_id = codec->vendor_id;
+
+	/* AIW0  lydia 060801 add for correct sw0 input select */
+	if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
+		return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+					     0x18, &spec->cur_mux[adc_idx]);
+	else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
+		  IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0) )
+		return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+					     0x19, &spec->cur_mux[adc_idx]);
+	else
+		return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+					     spec->adc_nids[adc_idx],
+					     &spec->cur_mux[adc_idx]);
+}
+
+/* capture mixer elements */
+static struct snd_kcontrol_new vt1708_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 * FIXME: the controls appear in the "playback" view!
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 1,
+		.info = via_mux_enum_info,
+		.get = via_mux_enum_get,
+		.put = via_mux_enum_put,
+	},
+	{ } /* end */
+};
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb vt1708_volume_init_verbs[] = {
+	/*
+	 * Unmute ADC0-1 and set the default input to mic-in
+	 */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+	 * mixer widget
+	 */
+	/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+	/*
+	 * Set up output mixers (0x19 - 0x1b)
+	 */
+	/* set vol=0 to output mixers */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	
+	/* Setup default input to PW4 */
+	{0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
+	/* Set mic as default input of sw0 */
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x2},
+	/* PW9 Output enable */
+	{0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+};
+
+static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
+				 struct hda_codec *codec,
+				 struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+				    struct hda_codec *codec,
+				    unsigned int stream_tag,
+				    unsigned int format,
+				    struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
+						stream_tag, format, substream);
+}
+
+static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				    struct hda_codec *codec,
+				    struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+				     struct hda_codec *codec,
+				     struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+				   struct hda_codec *codec,
+				   unsigned int stream_tag,
+				   unsigned int format,
+				   struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+				   stream_tag, 0, format);
+	return 0;
+}
+
+static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				   struct hda_codec *codec,
+				   struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+				   0, 0, 0);
+	return 0;
+}
+
+static struct hda_pcm_stream vt1708_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 8,
+	.nid = 0x10, /* NID to query formats and rates */
+	.ops = {
+		.open = via_playback_pcm_open,
+		.prepare = via_playback_pcm_prepare,
+		.cleanup = via_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream vt1708_pcm_analog_capture = {
+	.substreams = 2,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0x15, /* NID to query formats and rates */
+	.ops = {
+		.prepare = via_capture_pcm_prepare,
+		.cleanup = via_capture_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream vt1708_pcm_digital_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in via_build_pcms */
+	.ops = {
+		.open = via_dig_playback_pcm_open,
+		.close = via_dig_playback_pcm_close
+	},
+};
+
+static struct hda_pcm_stream vt1708_pcm_digital_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+};
+
+static int via_build_controls(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int err;
+	int i;
+
+	for (i = 0; i < spec->num_mixers; i++) {
+		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
+		if (err < 0)
+			return err;
+	}
+
+	if (spec->multiout.dig_out_nid) {
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid);
+		if (err < 0)
+			return err;
+	}
+	if (spec->dig_in_nid) {
+		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+static int via_build_pcms(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+
+	codec->num_pcms = 1;
+	codec->pcm_info = info;
+
+	info->name = spec->stream_name_analog;
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
+	info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
+	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
+
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
+		spec->multiout.max_channels;
+
+	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+		codec->num_pcms++;
+		info++;
+		info->name = spec->stream_name_digital;
+		if (spec->multiout.dig_out_nid) {
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+				*(spec->stream_digital_playback);
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+				spec->multiout.dig_out_nid;
+		}
+		if (spec->dig_in_nid) {
+			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+				*(spec->stream_digital_capture);
+			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
+				spec->dig_in_nid;
+		}
+	}
+
+	return 0;
+}
+
+static void via_free(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	unsigned int i;
+
+	if (!spec)
+		return;
+
+	if (spec->kctl_alloc) {
+		for (i = 0; i < spec->num_kctl_used; i++)
+			kfree(spec->kctl_alloc[i].name);
+		kfree(spec->kctl_alloc);
+	}
+
+	kfree(codec->spec);
+}
+
+static int via_init(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	snd_hda_sequence_write(codec, spec->init_verbs);
+ 	return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * resume
+ */
+static int via_resume(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int i;
+
+	via_init(codec);
+	for (i = 0; i < spec->num_mixers; i++)
+		snd_hda_resume_ctls(codec, spec->mixers[i]);
+	if (spec->multiout.dig_out_nid)
+		snd_hda_resume_spdif_out(codec);
+	if (spec->dig_in_nid)
+		snd_hda_resume_spdif_in(codec);
+
+	return 0;
+}
+#endif
+
+/*
+ */
+static struct hda_codec_ops via_patch_ops = {
+	.build_controls = via_build_controls,
+	.build_pcms = via_build_pcms,
+	.init = via_init,
+	.free = via_free,
+#ifdef CONFIG_PM
+	.resume = via_resume,
+#endif
+};
+
+/* fill in the dac_nids table from the parsed pin configuration */
+static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
+				     const struct auto_pin_cfg *cfg)
+{
+	int i;
+	hda_nid_t nid;
+
+	spec->multiout.num_dacs = cfg->line_outs;
+
+	spec->multiout.dac_nids = spec->private_dac_nids;
+ 	
+	for(i = 0; i < 4; i++) {
+		nid = cfg->line_out_pins[i];
+		if (nid) {
+			/* config dac list */
+			switch (i) {
+			case AUTO_SEQ_FRONT:
+				spec->multiout.dac_nids[i] = 0x10;
+				break;
+			case AUTO_SEQ_CENLFE:
+				spec->multiout.dac_nids[i] = 0x12;
+				break;
+			case AUTO_SEQ_SURROUND:
+				spec->multiout.dac_nids[i] = 0x13;
+				break;
+			case AUTO_SEQ_SIDE:
+				spec->multiout.dac_nids[i] = 0x11;
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/* add playback controls from the parsed DAC table */
+static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
+					     const struct auto_pin_cfg *cfg)
+{
+	char name[32];
+	static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+	hda_nid_t nid, nid_vol = 0;
+	int i, err;
+
+	for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
+		nid = cfg->line_out_pins[i];
+
+		if (!nid)
+			continue;
+		
+		if (i != AUTO_SEQ_FRONT)
+			nid_vol = 0x1b - i + 1;
+
+		if (i == AUTO_SEQ_CENLFE) {
+			/* Center/LFE */
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
+					      "Center Playback Volume",
+					      HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
+					      "LFE Playback Volume",
+					      HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
+					      "Center Playback Switch",
+					      HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
+					      "LFE Playback Switch",
+					      HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+		} else if (i == AUTO_SEQ_FRONT){
+			/* add control to mixer index 0 */
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
+					      "Master Front Playback Volume",
+					      HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
+			if (err < 0)
+				return err;
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
+					      "Master Front Playback Switch",
+					      HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
+			if (err < 0)
+				return err;
+			
+			/* add control to PW3 */
+			sprintf(name, "%s Playback Volume", chname[i]);
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+					      HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			sprintf(name, "%s Playback Switch", chname[i]);
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
+					      HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+		} else {
+			sprintf(name, "%s Playback Volume", chname[i]);
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			sprintf(name, "%s Playback Switch", chname[i]);
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
+					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
+{
+	int err;
+
+	if (!pin)
+		return 0;
+
+	spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
+
+	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
+			      "Headphone Playback Volume",
+			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+	if (err < 0)
+		return err;
+	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
+			      "Headphone Playback Switch",
+			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+/* create playback/capture controls for input pins */
+static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
+						const struct auto_pin_cfg *cfg)
+{
+	static char *labels[] = {
+		"Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
+	};
+	struct hda_input_mux *imux = &spec->private_imux;
+	int i, err, idx = 0;
+
+	/* for internal loopback recording select */
+	imux->items[imux->num_items].label = "Stereo Mixer";
+	imux->items[imux->num_items].index = idx;
+	imux->num_items++;
+
+	for (i = 0; i < AUTO_PIN_LAST; i++) {
+		if (!cfg->input_pins[i])
+			continue;
+
+		switch (cfg->input_pins[i]) {
+		case 0x1d: /* Mic */
+			idx = 2;
+			break;
+				
+		case 0x1e: /* Line In */
+			idx = 3;
+			break;
+
+		case 0x21: /* Front Mic */
+			idx = 4;
+			break;
+
+		case 0x24: /* CD */
+			idx = 1;
+			break;
+		}
+		err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
+					   idx, 0x17);
+		if (err < 0)
+			return err;
+		imux->items[imux->num_items].label = labels[i];
+		imux->items[imux->num_items].index = idx;
+		imux->num_items++;
+	}
+	return 0;
+}
+
+static int vt1708_parse_auto_config(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int err;
+
+	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
+	if (err < 0)
+		return err;
+	err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
+		return 0; /* can't find valid BIOS pin config */
+
+	err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
+	if (err < 0)
+		return err;
+	err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+
+	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+
+	if (spec->autocfg.dig_out_pin)
+		spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
+	if (spec->autocfg.dig_in_pin)
+		spec->dig_in_nid = VT1708_DIGIN_NID;
+
+	if (spec->kctl_alloc)
+		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
+	spec->init_verbs = vt1708_volume_init_verbs;	
+
+	spec->input_mux = &spec->private_imux;
+
+	return 1;
+}
+
+/* init callback for auto-configuration model -- overriding the default init */
+static int via_auto_init(struct hda_codec *codec)
+{
+	via_init(codec);
+	via_auto_init_multi_out(codec);
+	via_auto_init_hp_out(codec);
+	via_auto_init_analog_input(codec);
+	return 0;
+}
+
+static int patch_vt1708(struct hda_codec *codec)
+{
+	struct via_spec *spec;
+	int err;
+
+	/* create a codec specific record */
+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	/* automatic parse from the BIOS config */
+	err = vt1708_parse_auto_config(codec);
+	if (err < 0) {
+		via_free(codec);
+		return err;
+	} else if (!err) {
+		printk(KERN_INFO "hda_codec: Cannot set up configuration "
+		       "from BIOS.  Using genenic mode...\n");
+	}
+
+	
+	spec->stream_name_analog = "VT1708 Analog";
+	spec->stream_analog_playback = &vt1708_pcm_analog_playback;
+	spec->stream_analog_capture = &vt1708_pcm_analog_capture;
+
+	spec->stream_name_digital = "VT1708 Digital";
+	spec->stream_digital_playback = &vt1708_pcm_digital_playback;
+	spec->stream_digital_capture = &vt1708_pcm_digital_capture;
+
+	
+	if (!spec->adc_nids && spec->input_mux) {
+		spec->adc_nids = vt1708_adc_nids;
+		spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
+		spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
+		spec->num_mixers++;
+	}
+
+	codec->patch_ops = via_patch_ops;
+
+	codec->patch_ops.init = via_auto_init;
+
+	return 0;
+}
+
+/* capture mixer elements */
+static struct snd_kcontrol_new vt1709_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 * FIXME: the controls appear in the "playback" view!
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 1,
+		.info = via_mux_enum_info,
+		.get = via_mux_enum_get,
+		.put = via_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
+	/*
+	 * Unmute ADC0-2 and set the default input to mic-in
+	 */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+	 * mixer widget
+	 */
+	/* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+	/*
+	 * Set up output selector (0x1a, 0x1b, 0x29)
+	 */
+	/* set vol=0 to output mixers */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/*
+	 *  Unmute PW3 and PW4
+	 */
+	{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* Set input of PW4 as AOW4 */
+	{0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
+	/* Set mic as default input of sw0 */
+	{0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
+	/* PW9 Output enable */
+	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	{ }
+};
+
+static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 10,
+	.nid = 0x10, /* NID to query formats and rates */
+	.ops = {
+		.open = via_playback_pcm_open,
+		.prepare = via_playback_pcm_prepare,
+		.cleanup = via_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 6,
+	.nid = 0x10, /* NID to query formats and rates */
+	.ops = {
+		.open = via_playback_pcm_open,
+		.prepare = via_playback_pcm_prepare,
+		.cleanup = via_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream vt1709_pcm_analog_capture = {
+	.substreams = 2,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0x14, /* NID to query formats and rates */
+	.ops = {
+		.prepare = via_capture_pcm_prepare,
+		.cleanup = via_capture_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream vt1709_pcm_digital_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in via_build_pcms */
+	.ops = {
+		.open = via_dig_playback_pcm_open,
+		.close = via_dig_playback_pcm_close
+	},
+};
+
+static struct hda_pcm_stream vt1709_pcm_digital_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+};
+
+static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
+				     const struct auto_pin_cfg *cfg)
+{
+	int i;
+	hda_nid_t nid;
+
+	if (cfg->line_outs == 4)  /* 10 channels */
+		spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
+	else if (cfg->line_outs == 3) /* 6 channels */
+		spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
+
+	spec->multiout.dac_nids = spec->private_dac_nids;
+
+	if (cfg->line_outs == 4) { /* 10 channels */
+		for (i = 0; i < cfg->line_outs; i++) {
+			nid = cfg->line_out_pins[i];
+			if (nid) {
+				/* config dac list */
+				switch (i) {
+				case AUTO_SEQ_FRONT:
+					/* AOW0 */
+					spec->multiout.dac_nids[i] = 0x10;
+					break;
+				case AUTO_SEQ_CENLFE:
+					/* AOW2 */
+					spec->multiout.dac_nids[i] = 0x12;
+					break;
+				case AUTO_SEQ_SURROUND:
+					/* AOW3 */
+					spec->multiout.dac_nids[i] = 0x27;
+					break;
+				case AUTO_SEQ_SIDE:
+					/* AOW1 */
+					spec->multiout.dac_nids[i] = 0x11;
+					break;
+				default:
+					break;
+				}
+			}
+		}
+		spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
+
+	} else if (cfg->line_outs == 3) { /* 6 channels */
+		for(i = 0; i < cfg->line_outs; i++) {
+			nid = cfg->line_out_pins[i];
+			if (nid) {
+				/* config dac list */
+				switch(i) {
+				case AUTO_SEQ_FRONT:
+					/* AOW0 */
+					spec->multiout.dac_nids[i] = 0x10;
+					break;
+				case AUTO_SEQ_CENLFE:
+					/* AOW2 */
+					spec->multiout.dac_nids[i] = 0x12;
+					break;
+				case AUTO_SEQ_SURROUND:
+					/* AOW1 */
+					spec->multiout.dac_nids[i] = 0x11;
+					break;
+				default:
+					break;
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+/* add playback controls from the parsed DAC table */
+static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
+					     const struct auto_pin_cfg *cfg)
+{
+	char name[32];
+	static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+	hda_nid_t nid = 0;
+	int i, err;
+
+	for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
+		nid = cfg->line_out_pins[i];
+
+		if (!nid)	
+			continue;
+
+		if (i == AUTO_SEQ_CENLFE) {
+			/* Center/LFE */
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
+					      "Center Playback Volume",
+					      HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
+					      "LFE Playback Volume",
+					      HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
+					      "Center Playback Switch",
+					      HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
+					      "LFE Playback Switch",
+					      HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+		} else if (i == AUTO_SEQ_FRONT){
+			/* add control to mixer index 0 */
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
+					      "Master Front Playback Volume",
+					      HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
+			if (err < 0)
+				return err;
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
+					      "Master Front Playback Switch",
+					      HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
+			if (err < 0)
+				return err;
+			
+			/* add control to PW3 */
+			sprintf(name, "%s Playback Volume", chname[i]);
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+					      HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			sprintf(name, "%s Playback Switch", chname[i]);
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
+					      HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+		} else if (i == AUTO_SEQ_SURROUND) {
+			sprintf(name, "%s Playback Volume", chname[i]);
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+					      HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			sprintf(name, "%s Playback Switch", chname[i]);
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
+					      HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+		} else if (i == AUTO_SEQ_SIDE) {
+			sprintf(name, "%s Playback Volume", chname[i]);
+			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+					      HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			sprintf(name, "%s Playback Switch", chname[i]);
+			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
+					      HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
+			if (err < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
+{
+	int err;
+
+	if (!pin)
+		return 0;
+
+	if (spec->multiout.num_dacs == 5) /* 10 channels */
+		spec->multiout.hp_nid = VT1709_HP_DAC_NID;
+	else if (spec->multiout.num_dacs == 3) /* 6 channels */
+		spec->multiout.hp_nid = 0;
+
+	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
+			      "Headphone Playback Volume",
+			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+	if (err < 0)
+		return err;
+	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
+			      "Headphone Playback Switch",
+			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+/* create playback/capture controls for input pins */
+static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
+						const struct auto_pin_cfg *cfg)
+{
+	static char *labels[] = {
+		"Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
+	};
+	struct hda_input_mux *imux = &spec->private_imux;
+	int i, err, idx = 0;
+
+	/* for internal loopback recording select */
+	imux->items[imux->num_items].label = "Stereo Mixer";
+	imux->items[imux->num_items].index = idx;
+	imux->num_items++;
+
+	for (i = 0; i < AUTO_PIN_LAST; i++) {
+		if (!cfg->input_pins[i])
+			continue;
+
+		switch (cfg->input_pins[i]) {
+		case 0x1d: /* Mic */
+			idx = 2;
+			break;
+				
+		case 0x1e: /* Line In */
+			idx = 3;
+			break;
+
+		case 0x21: /* Front Mic */
+			idx = 4;
+			break;
+
+		case 0x23: /* CD */
+			idx = 1;
+			break;
+		}
+		err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
+					   idx, 0x18);
+		if (err < 0)
+			return err;
+		imux->items[imux->num_items].label = labels[i];
+		imux->items[imux->num_items].index = idx;
+		imux->num_items++;
+	}
+	return 0;
+}
+
+static int vt1709_parse_auto_config(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int err;
+
+	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
+	if (err < 0)
+		return err;
+	err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
+		return 0; /* can't find valid BIOS pin config */
+
+	err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
+	if (err < 0)
+		return err;
+	err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+
+	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+
+	if (spec->autocfg.dig_out_pin)
+		spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
+	if (spec->autocfg.dig_in_pin)
+		spec->dig_in_nid = VT1709_DIGIN_NID;
+
+	if (spec->kctl_alloc)
+		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
+	spec->input_mux = &spec->private_imux;
+
+	return 1;
+}
+
+static int patch_vt1709_10ch(struct hda_codec *codec)
+{
+	struct via_spec *spec;
+	int err;
+
+	/* create a codec specific record */
+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	err = vt1709_parse_auto_config(codec);
+	if (err < 0) {
+		via_free(codec);
+		return err;
+	} else if (!err) {
+		printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
+		       "Using genenic mode...\n");
+	}
+
+	spec->init_verbs = vt1709_10ch_volume_init_verbs;	
+
+	spec->stream_name_analog = "VT1709 Analog";
+	spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
+	spec->stream_analog_capture = &vt1709_pcm_analog_capture;
+
+	spec->stream_name_digital = "VT1709 Digital";
+	spec->stream_digital_playback = &vt1709_pcm_digital_playback;
+	spec->stream_digital_capture = &vt1709_pcm_digital_capture;
+
+	
+	if (!spec->adc_nids && spec->input_mux) {
+		spec->adc_nids = vt1709_adc_nids;
+		spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
+		spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
+		spec->num_mixers++;
+	}
+
+	codec->patch_ops = via_patch_ops;
+
+	codec->patch_ops.init = via_auto_init;
+
+	return 0;
+}
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
+	/*
+	 * Unmute ADC0-2 and set the default input to mic-in
+	 */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+	 * mixer widget
+	 */
+	/* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+	/*
+	 * Set up output selector (0x1a, 0x1b, 0x29)
+	 */
+	/* set vol=0 to output mixers */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/*
+	 *  Unmute PW3 and PW4
+	 */
+	{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* Set input of PW4 as MW0 */
+	{0x20, AC_VERB_SET_CONNECT_SEL, 0},
+	/* Set mic as default input of sw0 */
+	{0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
+	/* PW9 Output enable */
+	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	{ }
+};
+
+static int patch_vt1709_6ch(struct hda_codec *codec)
+{
+	struct via_spec *spec;
+	int err;
+
+	/* create a codec specific record */
+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	err = vt1709_parse_auto_config(codec);
+	if (err < 0) {
+		via_free(codec);
+		return err;
+	} else if (!err) {
+		printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
+		       "Using genenic mode...\n");
+	}
+
+	spec->init_verbs = vt1709_6ch_volume_init_verbs;	
+
+	spec->stream_name_analog = "VT1709 Analog";
+	spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
+	spec->stream_analog_capture = &vt1709_pcm_analog_capture;
+
+	spec->stream_name_digital = "VT1709 Digital";
+	spec->stream_digital_playback = &vt1709_pcm_digital_playback;
+	spec->stream_digital_capture = &vt1709_pcm_digital_capture;
+
+	
+	if (!spec->adc_nids && spec->input_mux) {
+		spec->adc_nids = vt1709_adc_nids;
+		spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
+		spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
+		spec->num_mixers++;
+	}
+
+	codec->patch_ops = via_patch_ops;
+
+	codec->patch_ops.init = via_auto_init;
+
+	return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_via[] = {
+	{ .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
+	{ .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
+	{ .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
+	{ .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
+	{ .id = 0x1106E710, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
+	{ .id = 0x1106E711, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
+	{ .id = 0x1106E712, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
+	{ .id = 0x1106E713, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
+	{ .id = 0x1106E714, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
+	{ .id = 0x1106E715, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
+	{ .id = 0x1106E716, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
+	{ .id = 0x1106E717, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
+	{} /* terminator */
+};
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
index 7837cef..6efdd62 100644
--- a/sound/pci/ice1712/Makefile
+++ b/sound/pci/ice1712/Makefile
@@ -5,7 +5,7 @@
 
 snd-ice17xx-ak4xxx-objs := ak4xxx.o
 snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
-snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o
+snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o wtm.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
index 59c4078..6e22d32 100644
--- a/sound/pci/ice1712/amp.c
+++ b/sound/pci/ice1712/amp.c
@@ -42,7 +42,7 @@
 
 static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
 {
-	static unsigned short wm_inits[] = {
+	static const unsigned short wm_inits[] = {
 		WM_ATTEN_L,	0x0000,	/* 0 db */
 		WM_ATTEN_R,	0x0000,	/* 0 db */
 		WM_DAC_CTRL,	0x0008,	/* 24bit I2S */
@@ -75,7 +75,7 @@
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_AV710,
 		.name = "Chaintech AV-710",
diff --git a/sound/pci/ice1712/amp.h b/sound/pci/ice1712/amp.h
index a0fc89b..7b667ba 100644
--- a/sound/pci/ice1712/amp.h
+++ b/sound/pci/ice1712/amp.h
@@ -42,7 +42,7 @@
 #define WM_DAC_CTRL	0x02
 #define WM_INT_CTRL	0x03
 
-extern struct snd_ice1712_card_info  snd_vt1724_amp_cards[];
+extern const struct snd_ice1712_card_info  snd_vt1724_amp_cards[];
 
 
 #endif /* __SOUND_AMP_H */
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 9e76ceb..6941d85 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -294,7 +294,7 @@
 static int aureon_ac97_init (struct snd_ice1712 *ice)
 {
 	int i;
-	static unsigned short ac97_defaults[] = {
+	static const unsigned short ac97_defaults[] = {
 		0x00, 0x9640,
 		0x02, 0x8000,
 		0x04, 0x8000,
@@ -474,7 +474,8 @@
 
 	tmp = snd_ice1712_gpio_read(ice);
 
-	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT) {
+	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
+	    ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
 		snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
 		mosi = PRODIGY_SPI_MOSI;
 		clk = PRODIGY_SPI_CLK;
@@ -601,7 +602,9 @@
 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
 {
 	aureon_spi_write(ice,
-			(ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ? PRODIGY_WM_CS : AUREON_WM_CS),
+			 ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
+			   ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
+			 PRODIGY_WM_CS : AUREON_WM_CS),
 			(reg << 9) | (val & 0x1ff), 16);
 }
 
@@ -661,17 +664,17 @@
 	return change;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
-static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
-static DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
 
 /*
  * Logarithmic volume values for WM8770
  * Computed as 20 * Log10(255 / x)
  */
-static unsigned char wm_vol[256] = {
+static const unsigned char wm_vol[256] = {
 	127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
 	23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
 	17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
@@ -1064,14 +1067,14 @@
  */
 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = {
+	static const char * const texts[] = {
 		"CD",		//AIN1
 		"Aux",		//AIN2
 		"Line",		//AIN3
 		"Mic",		//AIN4
 		"AC97"		//AIN5
 	};
-	static char *universe_texts[] = {
+	static const char * const universe_texts[] = {
 		"Aux1",		//AIN1
 		"CD",		//AIN2
 		"Phono",	//AIN3
@@ -1137,11 +1140,11 @@
 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-	static char *aureon_texts[] = {
+	static const char * const aureon_texts[] = {
 		"CD",		//RXP0
 		"Optical"	//RXP1
 	};
-	static char *prodigy_texts[] = {
+	static const char * const prodigy_texts[] = {
 		"CD",
 		"Coax"
 	};
@@ -1288,12 +1291,14 @@
 
 	tmp2 = tmp = snd_ice1712_gpio_read(ice);
 	if (enable)
-		if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT)
+		if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
+		    ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
 			tmp |= AUREON_HP_SEL;
 		else
 			tmp |= PRODIGY_HP_SEL;
 	else
-		if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT)
+		if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
+		    ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
 			tmp &= ~ AUREON_HP_SEL;
 		else
 			tmp &= ~ PRODIGY_HP_SEL;
@@ -1363,7 +1368,7 @@
  */
 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[2] = { "128x", "64x"	};
+	static const char * const texts[2] = { "128x", "64x"	};
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1406,7 +1411,7 @@
  * mixers
  */
 
-static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
+static const struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
@@ -1521,7 +1526,7 @@
 	}
 };
 
-static struct snd_kcontrol_new wm_controls[] __devinitdata = {
+static const struct snd_kcontrol_new wm_controls[] __devinitdata = {
  	{
  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "PCM Playback Switch",
@@ -1587,7 +1592,7 @@
 	}
 };
 
-static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
+static const struct snd_kcontrol_new ac97_controls[] __devinitdata = {
  	{
  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "AC97 Playback Switch",
@@ -1692,7 +1697,7 @@
  	}
 };
 
-static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
+static const struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
  	{
  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "AC97 Playback Switch",
@@ -1824,8 +1829,7 @@
 
 };
 
-	
-static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
+static const struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
@@ -1870,7 +1874,6 @@
 	}
 };
 
- 
 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
 {
 	unsigned int i, counts;
@@ -1898,7 +1901,8 @@
 				return err;
 		}
 	}
-	else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
+	else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
+		 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
 		for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
 			err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
 			if (err < 0)
@@ -1906,7 +1910,8 @@
 		}
 	}
 
-	if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
+	if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
+	    ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
 		unsigned char id;
 		snd_ice1712_save_gpio_status(ice);
 		id = aureon_cs8415_get(ice, CS8415_ID);
@@ -1936,7 +1941,7 @@
  */
 static int __devinit aureon_init(struct snd_ice1712 *ice)
 {
-	static unsigned short wm_inits_aureon[] = {
+	static const unsigned short wm_inits_aureon[] = {
 		/* These come first to reduce init pop noise */
 		0x1b, 0x044,		/* ADC Mux (AC'97 source) */
 		0x1c, 0x00B,		/* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
@@ -1972,7 +1977,7 @@
 		0x1a, 0x000,		/* -12dB ADC/R */
 		(unsigned short)-1
 	};
-	static unsigned short wm_inits_prodigy[] = {
+	static const unsigned short wm_inits_prodigy[] = {
 
 		/* These come first to reduce init pop noise */
 		0x1b, 0x000,		/* ADC Mux */
@@ -2014,7 +2019,7 @@
 		(unsigned short)-1
 
 	};
-	static unsigned short cs_inits[] = {
+	static const unsigned short cs_inits[] = {
 		0x0441, /* RUN */
 		0x0180, /* no mute, OMCK output on RMCK pin */
 		0x0201, /* S/PDIF source on RXP1 */
@@ -2022,7 +2027,7 @@
 		(unsigned short)-1
 	};
 	unsigned int tmp;
-	unsigned short *p;
+	const unsigned short *p;
 	int err, i;
 
 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
@@ -2062,7 +2067,8 @@
 
 	/* initialize WM8770 codec */
 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
-		ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT)
+		ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
+	        ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
 		p = wm_inits_prodigy;
 	else
 		p = wm_inits_aureon;
@@ -2070,7 +2076,8 @@
 		wm_put(ice, p[0], p[1]);
 
 	/* initialize CS8415A codec */
-	if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) {
+	if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
+	    ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
 		for (p = cs_inits; *p != (unsigned short)-1; p++)
 			aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
 		ice->spec.aureon.cs8415_mux = 1;
@@ -2100,73 +2107,58 @@
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char aureon51_eeprom[] __devinitdata = {
-	0x0a,	/* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
-	0x80,	/* ACLINK: I2S */
-	0xfc,	/* I2S: vol, 96k, 24bit, 192k */
-	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
-	0xff,	/* GPIO_DIR */
-	0xff,	/* GPIO_DIR1 */
-	0x5f,	/* GPIO_DIR2 */
-	0x00,	/* GPIO_MASK */
-	0x00,	/* GPIO_MASK1 */
-	0x00,	/* GPIO_MASK2 */
-	0x00,	/* GPIO_STATE */
-	0x00,	/* GPIO_STATE1 */
-	0x00,	/* GPIO_STATE2 */
+static const unsigned char aureon51_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x0a,	/* clock 512, spdif-in/ADC, 3DACs */
+	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
+	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
+	[ICE_EEP2_GPIO_DIR]    = 0xff,
+	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+	[ICE_EEP2_GPIO_DIR2]   = 0x5f,
+	[ICE_EEP2_GPIO_MASK]   = 0x00,
+	[ICE_EEP2_GPIO_MASK1]  = 0x00,
+	[ICE_EEP2_GPIO_MASK2]  = 0x00,
+	[ICE_EEP2_GPIO_STATE]  = 0x00,
+	[ICE_EEP2_GPIO_STATE1] = 0x00,
+	[ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-static unsigned char aureon71_eeprom[] __devinitdata = {
-	0x0b,	/* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
-	0x80,	/* ACLINK: I2S */
-	0xfc,	/* I2S: vol, 96k, 24bit, 192k */
-	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
-	0xff,	/* GPIO_DIR */
-	0xff,	/* GPIO_DIR1 */
-	0x5f,	/* GPIO_DIR2 */
-	0x00,	/* GPIO_MASK */
-	0x00,	/* GPIO_MASK1 */
-	0x00,	/* GPIO_MASK2 */
-	0x00,	/* GPIO_STATE */
-	0x00,	/* GPIO_STATE1 */
-	0x00,	/* GPIO_STATE2 */
+static const unsigned char aureon71_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x0b,	/* clock 512, spdif-in/ADC, 4DACs */
+	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
+	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
+	[ICE_EEP2_GPIO_DIR]    = 0xff,
+	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+	[ICE_EEP2_GPIO_DIR2]   = 0x5f,
+	[ICE_EEP2_GPIO_MASK]   = 0x00,
+	[ICE_EEP2_GPIO_MASK1]  = 0x00,
+	[ICE_EEP2_GPIO_MASK2]  = 0x00,
+	[ICE_EEP2_GPIO_STATE]  = 0x00,
+	[ICE_EEP2_GPIO_STATE1] = 0x00,
+	[ICE_EEP2_GPIO_STATE2] = 0x00,
 };
+#define prodigy71_eeprom aureon71_eeprom
 
-static unsigned char prodigy71_eeprom[] __devinitdata = {
-	0x0b,	/* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
-	0x80,	/* ACLINK: I2S */
-	0xfc,	/* I2S: vol, 96k, 24bit, 192k */
-	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
-	0xff,	/* GPIO_DIR */
-	0xff,	/* GPIO_DIR1 */
-	0x5f,	/* GPIO_DIR2 */
-	0x00,	/* GPIO_MASK */
-	0x00,	/* GPIO_MASK1 */
-	0x00,	/* GPIO_MASK2 */
-	0x00,	/* GPIO_STATE */
-	0x00,	/* GPIO_STATE1 */
-	0x00,	/* GPIO_STATE2 */
+static const unsigned char prodigy71lt_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x4b,	/* clock 384, spdif-in/ADC, 4DACs */
+	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
+	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
+	[ICE_EEP2_GPIO_DIR]    = 0xff,
+	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+	[ICE_EEP2_GPIO_DIR2]   = 0x5f,
+	[ICE_EEP2_GPIO_MASK]   = 0x00,
+	[ICE_EEP2_GPIO_MASK1]  = 0x00,
+	[ICE_EEP2_GPIO_MASK2]  = 0x00,
+	[ICE_EEP2_GPIO_STATE]  = 0x00,
+	[ICE_EEP2_GPIO_STATE1] = 0x00,
+	[ICE_EEP2_GPIO_STATE2] = 0x00,
 };
-
-static unsigned char prodigy71lt_eeprom[] __devinitdata = {
-	0x4b,	/* SYSCINF: clock 512, spdif-in/ADC, 4DACs */
-	0x80,	/* ACLINK: I2S */
-	0xfc,	/* I2S: vol, 96k, 24bit, 192k */
-	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
-	0xff,	/* GPIO_DIR */
-	0xff,	/* GPIO_DIR1 */
-	0x5f,	/* GPIO_DIR2 */
-	0x00,	/* GPIO_MASK */
-	0x00,	/* GPIO_MASK1 */
-	0x00,	/* GPIO_MASK2 */
-	0x00,	/* GPIO_STATE */
-	0x00,	/* GPIO_STATE1 */
-	0x00,	/* GPIO_STATE2 */
-};
-	
+#define prodigy71xt_eeprom prodigy71lt_eeprom
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
 		.name = "Terratec Aureon 5.1-Sky",
@@ -2217,5 +2209,15 @@
 		.eeprom_data = prodigy71lt_eeprom,
 		.driver = "Prodigy71LT",
 	},
+	{
+		.subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
+		.name = "Audiotrak Prodigy 7.1 XT",
+		.model = "prodigy71xt",
+		.chip_init = aureon_init,
+		.build_controls = aureon_add_controls,
+		.eeprom_size = sizeof(prodigy71xt_eeprom),
+		.eeprom_data = prodigy71xt_eeprom,
+		.driver = "Prodigy71LT",
+	},
 	{ } /* terminator */
 };
diff --git a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h
index 3b7bea6..79e58e8 100644
--- a/sound/pci/ice1712/aureon.h
+++ b/sound/pci/ice1712/aureon.h
@@ -28,15 +28,17 @@
 				       "{Terratec,Aureon 7.1 Space},"\
 				       "{Terratec,Aureon 7.1 Universe}," \
 					"{AudioTrak,Prodigy 7.1}," \
-					"{AudioTrak,Prodigy 7.1 LT},"
+					"{AudioTrak,Prodigy 7.1 LT},"\
+					"{AudioTrak,Prodigy 7.1 XT},"
 
 #define VT1724_SUBDEVICE_AUREON51_SKY	0x3b154711	/* Aureon 5.1 Sky */
 #define VT1724_SUBDEVICE_AUREON71_SPACE	0x3b154511	/* Aureon 7.1 Space */
 #define VT1724_SUBDEVICE_AUREON71_UNIVERSE	0x3b155311	/* Aureon 7.1 Universe */
 #define VT1724_SUBDEVICE_PRODIGY71	0x33495345	/* PRODIGY 7.1 */
 #define VT1724_SUBDEVICE_PRODIGY71LT	0x32315441	/* PRODIGY 7.1 LT */
+#define VT1724_SUBDEVICE_PRODIGY71XT	0x36315441	/* PRODIGY 7.1 XT*/
 
-extern struct snd_ice1712_card_info  snd_vt1724_aureon_cards[];
+extern const struct snd_ice1712_card_info  snd_vt1724_aureon_cards[];
 
 /* GPIO bits */
 #define AUREON_CS8415_CS	(1 << 22)
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index af65980..3eeb36c 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -416,7 +416,7 @@
 	return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata =
+static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata =
 {
 	.access =	(SNDRV_CTL_ELEM_ACCESS_READ),
 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -429,7 +429,7 @@
  * initialize the chips on M-Audio cards
  */
 
-static struct snd_akm4xxx akm_audiophile __devinitdata = {
+static const struct snd_akm4xxx akm_audiophile __devinitdata = {
 	.type = SND_AK4528,
 	.num_adcs = 2,
 	.num_dacs = 2,
@@ -438,7 +438,7 @@
 	}
 };
 
-static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0,
 	.data_mask = ICE1712_DELTA_AP_DOUT,
@@ -450,7 +450,7 @@
 	.mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_delta410 __devinitdata = {
+static const struct snd_akm4xxx akm_delta410 __devinitdata = {
 	.type = SND_AK4529,
 	.num_adcs = 2,
 	.num_dacs = 8,
@@ -459,7 +459,7 @@
 	}
 };
 
-static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
 	.caddr = 0,
 	.cif = 0,
 	.data_mask = ICE1712_DELTA_AP_DOUT,
@@ -471,7 +471,7 @@
 	.mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_delta1010lt __devinitdata = {
+static const struct snd_akm4xxx akm_delta1010lt __devinitdata = {
 	.type = SND_AK4524,
 	.num_adcs = 8,
 	.num_dacs = 8,
@@ -481,7 +481,7 @@
 	}
 };
 
-static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0, /* the default level of the CIF pin from AK4524 */
 	.data_mask = ICE1712_DELTA_1010LT_DOUT,
@@ -493,7 +493,7 @@
 	.mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_delta44 __devinitdata = {
+static const struct snd_akm4xxx akm_delta44 __devinitdata = {
 	.type = SND_AK4524,
 	.num_adcs = 4,
 	.num_dacs = 4,
@@ -503,7 +503,7 @@
 	}
 };
 
-static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0, /* the default level of the CIF pin from AK4524 */
 	.data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA,
@@ -515,7 +515,7 @@
 	.mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_vx442 __devinitdata = {
+static const struct snd_akm4xxx akm_vx442 __devinitdata = {
 	.type = SND_AK4524,
 	.num_adcs = 4,
 	.num_dacs = 4,
@@ -525,7 +525,7 @@
 	}
 };
 
-static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0,
 	.data_mask = ICE1712_VX442_DOUT,
@@ -650,15 +650,15 @@
  * additional controls for M-Audio cards
  */
 
-static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata =
+static const struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0);
-static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata =
+static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0);
-static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata =
+static const struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
-static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
+static const struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0);
-static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata =
+static const struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
 
 
@@ -735,7 +735,7 @@
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
 	{
 		.subvendor = ICE1712_SUBDEVICE_DELTA1010,
 		.name = "M Audio Delta 1010",
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
index 746ebde..e65d669 100644
--- a/sound/pci/ice1712/delta.h
+++ b/sound/pci/ice1712/delta.h
@@ -46,7 +46,7 @@
 #define ICE1712_SUBDEVICE_MEDIASTATION	0x694c0100
 
 /* entry point */
-extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
+extern const struct snd_ice1712_card_info snd_ice1712_delta_cards[];
 
 
 /*
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index b135389..9b7ff30 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -332,7 +332,7 @@
 
 /*
  */
-static struct snd_akm4xxx akm_ews88mt __devinitdata = {
+static const struct snd_akm4xxx akm_ews88mt __devinitdata = {
 	.num_adcs = 8,
 	.num_dacs = 8,
 	.type = SND_AK4524,
@@ -342,7 +342,7 @@
 	}
 };
 
-static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 1, /* CIF high */
 	.data_mask = ICE1712_EWS88_SERIAL_DATA,
@@ -354,7 +354,7 @@
 	.mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_ewx2496 __devinitdata = {
+static const struct snd_akm4xxx akm_ewx2496 __devinitdata = {
 	.num_adcs = 2,
 	.num_dacs = 2,
 	.type = SND_AK4524,
@@ -363,7 +363,7 @@
 	}
 };
 
-static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 1, /* CIF high */
 	.data_mask = ICE1712_EWS88_SERIAL_DATA,
@@ -375,7 +375,7 @@
 	.mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_6fire __devinitdata = {
+static const struct snd_akm4xxx akm_6fire __devinitdata = {
 	.num_adcs = 6,
 	.num_dacs = 6,
 	.type = SND_AK4524,
@@ -384,7 +384,7 @@
 	}
 };
 
-static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 1, /* CIF high */
 	.data_mask = ICE1712_6FIRE_SERIAL_DATA,
@@ -578,7 +578,7 @@
 	return val != nval;
 }
 
-static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Input Sensitivity Switch",
@@ -678,7 +678,7 @@
 	return ndata != data;
 }
 
-static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Input Sensitivity Switch",
 	.info = snd_ice1712_ewx_io_sense_info,
@@ -687,7 +687,7 @@
 	.count = 8,
 };
 
-static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Output Sensitivity Switch",
 	.info = snd_ice1712_ewx_io_sense_info,
@@ -769,7 +769,7 @@
   .private_value = xshift | (xinvert << 8),\
 }
 
-static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = {
 	EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */
 	EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0),
 	EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0),
@@ -909,7 +909,7 @@
   .private_value = xshift | (xinvert << 8),\
 }
 
-static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Analog Input Select",
@@ -989,7 +989,7 @@
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
 	{
 		.subvendor = ICE1712_SUBDEVICE_EWX2496,
 		.name = "TerraTec EWX24/96",
diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h
index a12a0b0..df449b4 100644
--- a/sound/pci/ice1712/ews.h
+++ b/sound/pci/ice1712/ews.h
@@ -40,7 +40,7 @@
 #define ICE1712_SUBDEVICE_PHASE88	0x3b155111
 
 /* entry point */
-extern struct snd_ice1712_card_info snd_ice1712_ews_cards[];
+extern const struct snd_ice1712_card_info snd_ice1712_ews_cards[];
 
 
 /* TerraTec EWX 24/96 configuration definitions */
diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
index 3f27d04..df97313 100644
--- a/sound/pci/ice1712/hoontech.c
+++ b/sound/pci/ice1712/hoontech.c
@@ -239,7 +239,7 @@
 static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
 {
 	/* Hoontech STDSP24 with modified hardware */
-	static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
+	static const struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
 		.num_adcs = 2,
 		.num_dacs = 2,
 		.type = SND_AK4524,
@@ -248,7 +248,7 @@
 		}
 	};
 
-	static struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = {
+	static const struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = {
 		.caddr = 2,
 		.cif = 1, /* CIF high */
 		.data_mask = ICE1712_STDSP24_SERIAL_DATA,
@@ -298,7 +298,7 @@
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
 	{
 		.subvendor = ICE1712_SUBDEVICE_STDSP24,
 		.name = "Hoontech SoundTrack Audio DSP24",
@@ -325,4 +325,3 @@
 	},
 	{ } /* terminator */
 };
-
diff --git a/sound/pci/ice1712/hoontech.h b/sound/pci/ice1712/hoontech.h
index 1ee538b..b62d6e4 100644
--- a/sound/pci/ice1712/hoontech.h
+++ b/sound/pci/ice1712/hoontech.h
@@ -35,7 +35,7 @@
 #define ICE1712_SUBDEVICE_STDSP24_MEDIA7_1	0x16141217	/* Hoontech ST Audio DSP24 Media 7.1 */
 #define ICE1712_SUBDEVICE_EVENT_EZ8		0x00010001	/* A dummy id for EZ8 */
 
-extern struct snd_ice1712_card_info snd_ice1712_hoontech_cards[];
+extern const struct snd_ice1712_card_info snd_ice1712_hoontech_cards[];
 
 
 /* Hoontech SoundTrack Audio DSP 24 GPIO definitions */
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 8ba31cf..830a1bb 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -107,7 +107,7 @@
 MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE.");
 
 
-static struct pci_device_id snd_ice1712_ids[] = {
+static const struct pci_device_id snd_ice1712_ids[] = {
 	{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },   /* ICE1712 */
 	{ 0, }
 };
@@ -287,7 +287,7 @@
 	return val != nval;
 }
 
-static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Digital Mixer To AC97",
 	.info = snd_ice1712_digmix_route_ac97_info,
@@ -719,7 +719,7 @@
 	return bytes_to_frames(substream->runtime, ptr);
 }
 
-static struct snd_pcm_hardware snd_ice1712_playback =
+static const struct snd_pcm_hardware snd_ice1712_playback =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -739,7 +739,7 @@
 	.fifo_size =		0,
 };
 
-static struct snd_pcm_hardware snd_ice1712_playback_ds =
+static const struct snd_pcm_hardware snd_ice1712_playback_ds =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -759,7 +759,7 @@
 	.fifo_size =		0,
 };
 
-static struct snd_pcm_hardware snd_ice1712_capture =
+static const struct snd_pcm_hardware snd_ice1712_capture =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1133,7 +1133,7 @@
 	return bytes_to_frames(substream->runtime, ptr);
 }
 
-static struct snd_pcm_hardware snd_ice1712_playback_pro =
+static const struct snd_pcm_hardware snd_ice1712_playback_pro =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1153,7 +1153,7 @@
 	.fifo_size =		0,
 };
 
-static struct snd_pcm_hardware snd_ice1712_capture_pro =
+static const struct snd_pcm_hardware snd_ice1712_capture_pro =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1378,9 +1378,9 @@
 	return change;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0);
 
-static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Multi Playback Switch",
@@ -1404,7 +1404,7 @@
 	},
 };
 
-static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "H/W Multi Capture Switch",
 	.info = snd_ice1712_pro_mixer_switch_info,
@@ -1413,7 +1413,7 @@
 	.private_value = 10,
 };
 
-static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,SWITCH),
 	.info = snd_ice1712_pro_mixer_switch_info,
@@ -1423,7 +1423,7 @@
 	.count = 2,
 };
 
-static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -1435,7 +1435,7 @@
 	.tlv = { .p = db_scale_playback }
 };
 
-static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,VOLUME),
 	.info = snd_ice1712_pro_mixer_volume_info,
@@ -1627,7 +1627,7 @@
 	return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
 	.name = "ICE1712 EEPROM",
 	.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1663,7 +1663,7 @@
 	return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata =
+static const struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata =
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1714,7 +1714,7 @@
 	return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
+static const struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
 {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1723,7 +1723,7 @@
 	.get =		snd_ice1712_spdif_maskc_get,
 };
 
-static struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata =
+static const struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata =
 {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1750,7 +1750,7 @@
 	return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata =
+static const struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata =
 {
 	.access =	(SNDRV_CTL_ELEM_ACCESS_READWRITE |
 			 SNDRV_CTL_ELEM_ACCESS_INACTIVE),
@@ -1811,7 +1811,7 @@
 static int snd_ice1712_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
 					       struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = {
+	static const char * const texts[] = {
 		"8000",		/* 0: 6 */
 		"9600",		/* 1: 3 */
 		"11025",	/* 2: 10 */
@@ -1840,7 +1840,7 @@
 					      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-	static unsigned char xlate[16] = {
+	static const unsigned char xlate[16] = {
 		9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 255, 255, 255, 10
 	};
 	unsigned char val;
@@ -1864,7 +1864,7 @@
 					      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-	static unsigned int xrate[13] = {
+	static const unsigned int xrate[13] = {
 		8000, 9600, 11025, 12000, 16000, 22050, 24000,
 		32000, 44100, 48000, 64000, 88200, 96000
 	};
@@ -1891,7 +1891,7 @@
 	return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Internal Clock",
 	.info = snd_ice1712_pro_internal_clock_info,
@@ -1902,7 +1902,7 @@
 static int snd_ice1712_pro_internal_clock_default_info(struct snd_kcontrol *kcontrol,
 						       struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = {
+	static const char * const texts[] = {
 		"8000",		/* 0: 6 */
 		"9600",		/* 1: 3 */
 		"11025",	/* 2: 10 */
@@ -1931,7 +1931,7 @@
 						      struct snd_ctl_elem_value *ucontrol)
 {
 	int val;
-	static unsigned int xrate[13] = {
+	static const unsigned int xrate[13] = {
 		8000, 9600, 11025, 12000, 16000, 22050, 24000,
 		32000, 44100, 48000, 64000, 88200, 96000
 	};
@@ -1948,7 +1948,7 @@
 static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcontrol,
 						      struct snd_ctl_elem_value *ucontrol)
 {
-	static unsigned int xrate[13] = {
+	static const unsigned int xrate[13] = {
 		8000, 9600, 11025, 12000, 16000, 22050, 24000,
 		32000, 44100, 48000, 64000, 88200, 96000
 	};
@@ -1962,7 +1962,7 @@
 	return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Internal Clock Default",
 	.info = snd_ice1712_pro_internal_clock_default_info,
@@ -2001,7 +2001,7 @@
 	return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Rate Locking",
 	.info = snd_ice1712_pro_rate_locking_info,
@@ -2040,7 +2040,7 @@
 	return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Rate Reset",
 	.info = snd_ice1712_pro_rate_reset_info,
@@ -2054,7 +2054,7 @@
 static int snd_ice1712_pro_route_info(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = {
+	static const char * const texts[] = {
 		"PCM Out", /* 0 */
 		"H/W In 0", "H/W In 1", "H/W In 2", "H/W In 3", /* 1-4 */
 		"H/W In 4", "H/W In 5", "H/W In 6", "H/W In 7", /* 5-8 */
@@ -2207,7 +2207,7 @@
 	return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "H/W Playback Route",
 	.info = snd_ice1712_pro_route_info,
@@ -2215,7 +2215,7 @@
 	.put = snd_ice1712_pro_route_analog_put,
 };
 
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
 	.info = snd_ice1712_pro_route_info,
@@ -2257,7 +2257,7 @@
 	return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Volume Rate",
 	.info = snd_ice1712_pro_volume_rate_info,
@@ -2290,7 +2290,7 @@
 	return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
+static const struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Peak",
 	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -2305,7 +2305,7 @@
 /*
  * list of available boards
  */
-static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
+static const struct snd_ice1712_card_info *card_tables[] __devinitdata = {
 	snd_ice1712_hoontech_cards,
 	snd_ice1712_delta_cards,
 	snd_ice1712_ews_cards,
@@ -2329,7 +2329,7 @@
 {
 	int dev = 0xa0;		/* EEPROM device address */
 	unsigned int i, size;
-	struct snd_ice1712_card_info **tbl, *c;
+	const struct snd_ice1712_card_info **tbl, *c;
 
 	if (! modelname || ! *modelname) {
 		ice->eeprom.subvendor = 0;
@@ -2658,7 +2658,7 @@
  *
  */
 
-static struct snd_ice1712_card_info no_matched __devinitdata;
+static const struct snd_ice1712_card_info no_matched __devinitdata;
 
 static int __devinit snd_ice1712_probe(struct pci_dev *pci,
 				       const struct pci_device_id *pci_id)
@@ -2667,7 +2667,7 @@
 	struct snd_card *card;
 	struct snd_ice1712 *ice;
 	int pcm_dev = 0, err;
-	struct snd_ice1712_card_info **tbl, *c;
+	const struct snd_ice1712_card_info **tbl, *c;
 
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index ce27eac..c3d9fea 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -28,6 +28,7 @@
 #include <sound/i2c.h>
 #include <sound/ak4xxx-adda.h>
 #include <sound/ak4114.h>
+#include <sound/pt2258.h>
 #include <sound/pcm.h>
 #include <sound/mpu401.h>
 
@@ -381,6 +382,11 @@
 			unsigned short master[2];
 			unsigned short vol[8];
 		} phase28;
+		/* a non-standard I2C device for revo51 */
+		struct revo51_spec {
+			struct snd_i2c_device *dev;
+			struct snd_pt2258 *pt2258;
+		} revo51;
 		/* Hoontech-specific setting */
 		struct hoontech_spec {
 			unsigned char boxbits[4];
@@ -462,6 +468,14 @@
 	snd_ice1712_gpio_write(ice, mask & bits);
 }
 
+static inline int snd_ice1712_gpio_read_bits(struct snd_ice1712 *ice,
+					      unsigned int mask)
+{
+	ice->gpio.direction &= ~mask;
+	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+	return  (snd_ice1712_gpio_read(ice) & mask);
+}
+
 int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice);
 
 int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *template,
@@ -500,8 +514,8 @@
 	unsigned int mpu401_2_info_flags;
 	const char *mpu401_1_name;
 	const char *mpu401_2_name;
-	unsigned int eeprom_size;
-	unsigned char *eeprom_data;
+	const unsigned int eeprom_size;
+	const unsigned char *eeprom_data;
 };
 
 
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 3e3a102..1127ebd 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -50,7 +50,7 @@
 #include "prodigy192.h"
 #include "juli.h"
 #include "phase.h"
-
+#include "wtm.h"
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
@@ -64,6 +64,7 @@
 	       PRODIGY192_DEVICE_DESC
 	       JULI_DEVICE_DESC
 	       PHASE_DEVICE_DESC
+	       WTM_DEVICE_DESC
 		"{VIA,VT1720},"
 		"{VIA,VT1724},"
 		"{ICEnsemble,Generic ICE1724},"
@@ -86,7 +87,7 @@
 
 
 /* Both VT1720 and VT1724 have the same PCI IDs */
-static struct pci_device_id snd_vt1724_ids[] = {
+static const struct pci_device_id snd_vt1724_ids[] = {
 	{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_VT1724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ 0, }
 };
@@ -341,7 +342,7 @@
 
 	what = 0;
 	snd_pcm_group_for_each(pos, substream) {
-		struct vt1724_pcm_reg *reg;
+		const struct vt1724_pcm_reg *reg;
 		s = snd_pcm_group_substream_entry(pos);
 		reg = s->runtime->private_data;
 		what |= reg->start;
@@ -605,7 +606,7 @@
 static int snd_vt1724_pcm_prepare(struct snd_pcm_substream *substream)
 {
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
-	struct vt1724_pcm_reg *reg = substream->runtime->private_data;
+	const struct vt1724_pcm_reg *reg = substream->runtime->private_data;
 
 	spin_lock_irq(&ice->reg_lock);
 	outl(substream->runtime->dma_addr, ice->profi_port + reg->addr);
@@ -620,7 +621,7 @@
 static snd_pcm_uframes_t snd_vt1724_pcm_pointer(struct snd_pcm_substream *substream)
 {
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
-	struct vt1724_pcm_reg *reg = substream->runtime->private_data;
+	const struct vt1724_pcm_reg *reg = substream->runtime->private_data;
 	size_t ptr;
 
 	if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & reg->start))
@@ -646,21 +647,21 @@
 #endif
 }
 
-static struct vt1724_pcm_reg vt1724_playback_pro_reg = {
+static const struct vt1724_pcm_reg vt1724_playback_pro_reg = {
 	.addr = VT1724_MT_PLAYBACK_ADDR,
 	.size = VT1724_MT_PLAYBACK_SIZE,
 	.count = VT1724_MT_PLAYBACK_COUNT,
 	.start = VT1724_PDMA0_START,
 };
 
-static struct vt1724_pcm_reg vt1724_capture_pro_reg = {
+static const struct vt1724_pcm_reg vt1724_capture_pro_reg = {
 	.addr = VT1724_MT_CAPTURE_ADDR,
 	.size = VT1724_MT_CAPTURE_SIZE,
 	.count = VT1724_MT_CAPTURE_COUNT,
 	.start = VT1724_RDMA0_START,
 };
 
-static struct snd_pcm_hardware snd_vt1724_playback_pro =
+static const struct snd_pcm_hardware snd_vt1724_playback_pro =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -679,7 +680,7 @@
 	.periods_max =		1024,
 };
 
-static struct snd_pcm_hardware snd_vt1724_spdif =
+static const struct snd_pcm_hardware snd_vt1724_spdif =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -701,7 +702,7 @@
 	.periods_max =		1024,
 };
 
-static struct snd_pcm_hardware snd_vt1724_2ch_stereo =
+static const struct snd_pcm_hardware snd_vt1724_2ch_stereo =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -773,7 +774,7 @@
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 	int chs;
 
-	runtime->private_data = &vt1724_playback_pro_reg;
+	runtime->private_data = (void *)&vt1724_playback_pro_reg;
 	ice->playback_pro_substream = substream;
 	runtime->hw = snd_vt1724_playback_pro;
 	snd_pcm_set_sync(substream);
@@ -802,7 +803,7 @@
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	runtime->private_data = &vt1724_capture_pro_reg;
+	runtime->private_data = (void *)&vt1724_capture_pro_reg;
 	ice->capture_pro_substream = substream;
 	runtime->hw = snd_vt1724_2ch_stereo;
 	snd_pcm_set_sync(substream);
@@ -888,14 +889,14 @@
  * SPDIF PCM
  */
 
-static struct vt1724_pcm_reg vt1724_playback_spdif_reg = {
+static const struct vt1724_pcm_reg vt1724_playback_spdif_reg = {
 	.addr = VT1724_MT_PDMA4_ADDR,
 	.size = VT1724_MT_PDMA4_SIZE,
 	.count = VT1724_MT_PDMA4_COUNT,
 	.start = VT1724_PDMA4_START,
 };
 
-static struct vt1724_pcm_reg vt1724_capture_spdif_reg = {
+static const struct vt1724_pcm_reg vt1724_capture_spdif_reg = {
 	.addr = VT1724_MT_RDMA1_ADDR,
 	.size = VT1724_MT_RDMA1_SIZE,
 	.count = VT1724_MT_RDMA1_COUNT,
@@ -953,7 +954,7 @@
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	runtime->private_data = &vt1724_playback_spdif_reg;
+	runtime->private_data = (void *)&vt1724_playback_spdif_reg;
 	ice->playback_con_substream = substream;
 	if (ice->force_pdma4) {
 		runtime->hw = snd_vt1724_2ch_stereo;
@@ -985,7 +986,7 @@
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	runtime->private_data = &vt1724_capture_spdif_reg;
+	runtime->private_data = (void *)&vt1724_capture_spdif_reg;
 	ice->capture_con_substream = substream;
 	if (ice->force_rdma1) {
 		runtime->hw = snd_vt1724_2ch_stereo;
@@ -1090,7 +1091,7 @@
  * independent surround PCMs
  */
 
-static struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = {
+static const struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = {
 	{
 		.addr = VT1724_MT_PDMA1_ADDR,
 		.size = VT1724_MT_PDMA1_SIZE,
@@ -1136,7 +1137,7 @@
 		return -EBUSY; /* FIXME: should handle blocking mode properly */
 	}
 	mutex_unlock(&ice->open_mutex);
-	runtime->private_data = &vt1724_playback_dma_regs[substream->number];
+	runtime->private_data = (void *)&vt1724_playback_dma_regs[substream->number];
 	ice->playback_con_substream_ds[substream->number] = substream;
 	runtime->hw = snd_vt1724_2ch_stereo;
 	snd_pcm_set_sync(substream);
@@ -1317,7 +1318,7 @@
 	return 0;
 }
 
-static struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = {
+static const struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
 	.name = "ICE1724 EEPROM",
 	.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1430,7 +1431,7 @@
 	return (val != old);
 }
 
-static struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata =
+static const struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata =
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1462,7 +1463,7 @@
 	return 0;
 }
 
-static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
+static const struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
 {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1471,7 +1472,7 @@
 	.get =		snd_vt1724_spdif_maskc_get,
 };
 
-static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata =
+static const struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata =
 {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1516,7 +1517,7 @@
 	return old != val;
 }
 
-static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata =
+static const struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata =
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
 	/* FIXME: the following conflict with IEC958 Playback Route */
@@ -1584,7 +1585,7 @@
 static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
 					      struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts_1724[] = {
+	static const char * const texts_1724[] = {
 		"8000",		/* 0: 6 */
 		"9600",		/* 1: 3 */
 		"11025",	/* 2: 10 */
@@ -1602,7 +1603,7 @@
 		"192000",	/* 14: 14 */
 		"IEC958 Input",	/* 15: -- */
 	};
-	static char *texts_1720[] = {
+	static const char * const texts_1720[] = {
 		"8000",		/* 0: 6 */
 		"9600",		/* 1: 3 */
 		"11025",	/* 2: 10 */
@@ -1635,7 +1636,7 @@
 					     struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-	static unsigned char xlate[16] = {
+	static const unsigned char xlate[16] = {
 		9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10
 	};
 	unsigned char val;
@@ -1694,7 +1695,7 @@
 	return change;
 }
 
-static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
+static const struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Internal Clock",
 	.info = snd_vt1724_pro_internal_clock_info,
@@ -1733,7 +1734,7 @@
 	return change;
 }
 
-static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = {
+static const struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Rate Locking",
 	.info = snd_vt1724_pro_rate_locking_info,
@@ -1772,7 +1773,7 @@
 	return change;
 }
 
-static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
+static const struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Rate Reset",
 	.info = snd_vt1724_pro_rate_reset_info,
@@ -1816,7 +1817,7 @@
 {
 	unsigned long val;
 	unsigned char eitem;
-	static unsigned char xlate[8] = {
+	static const unsigned char xlate[8] = {
 		0, 255, 1, 2, 255, 255, 3, 4,
 	};
 
@@ -1835,7 +1836,7 @@
 {
 	unsigned int old_val, nval;
 	int change;
-	static unsigned char xroute[8] = {
+	static const unsigned char xroute[8] = {
 		0, /* PCM */
 		2, /* PSDIN0 Left */
 		3, /* PSDIN0 Right */
@@ -1891,7 +1892,7 @@
 			     digital_route_shift(idx));
 }
 
-static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = {
+static const struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "H/W Playback Route",
 	.info = snd_vt1724_pro_route_info,
@@ -1899,7 +1900,7 @@
 	.put = snd_vt1724_pro_route_analog_put,
 };
 
-static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = {
+static const struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
 	.info = snd_vt1724_pro_route_info,
@@ -1935,7 +1936,7 @@
 	return 0;
 }
 
-static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
+static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Peak",
 	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -1947,9 +1948,9 @@
  *
  */
 
-static struct snd_ice1712_card_info no_matched __devinitdata;
+static const struct snd_ice1712_card_info no_matched __devinitdata;
 
-static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
+static const struct snd_ice1712_card_info *card_tables[] __devinitdata = {
 	snd_vt1724_revo_cards,
 	snd_vt1724_amp_cards, 
 	snd_vt1724_aureon_cards,
@@ -1958,6 +1959,7 @@
 	snd_vt1724_prodigy192_cards,
 	snd_vt1724_juli_cards,
 	snd_vt1724_phase_cards,
+	snd_vt1724_wtm_cards,
 	NULL,
 };
 
@@ -2007,7 +2009,7 @@
 {
 	const int dev = 0xa0;		/* EEPROM device address */
 	unsigned int i, size;
-	struct snd_ice1712_card_info **tbl, *c;
+	const struct snd_ice1712_card_info **tbl, *c;
 
 	if (! modelname || ! *modelname) {
 		ice->eeprom.subvendor = 0;
@@ -2306,7 +2308,7 @@
 	struct snd_card *card;
 	struct snd_ice1712 *ice;
 	int pcm_dev = 0, err;
-	struct snd_ice1712_card_info **tbl, *c;
+	const struct snd_ice1712_card_info **tbl, *c;
 
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index 5176b41..d88172f 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -125,7 +125,7 @@
 	snd_akm4xxx_reset(ak, 0);
 }
 
-static struct snd_akm4xxx akm_juli_dac __devinitdata = {
+static const struct snd_akm4xxx akm_juli_dac __devinitdata = {
 	.type = SND_AK4358,
 	.num_dacs = 2,
 	.ops = {
@@ -146,7 +146,7 @@
  */
 static int __devinit juli_init(struct snd_ice1712 *ice)
 {
-	static unsigned char ak4114_init_vals[] = {
+	static const unsigned char ak4114_init_vals[] = {
 		/* AK4117_REG_PWRDN */	AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
 		/* AK4114_REQ_FORMAT */	AK4114_DIF_I24I2S,
 		/* AK4114_REG_IO0 */	AK4114_TX1E,
@@ -154,7 +154,7 @@
 		/* AK4114_REG_INT0_MASK */ 0,
 		/* AK4114_REG_INT1_MASK */ 0
 	};
-	static unsigned char ak4114_init_txcsb[] = {
+	static const unsigned char ak4114_init_txcsb[] = {
 		0x41, 0x02, 0x2c, 0x00, 0x00
 	};
 	int err;
@@ -206,24 +206,24 @@
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char juli_eeprom[] __devinitdata = {
-	0x20,	/* SYSCONF: clock 512, mpu401, 1xADC, 1xDACs */
-	0x80,	/* ACLINK: I2S */
-	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
-	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
-	0x9f,	/* GPIO_DIR */
-	0xff,	/* GPIO_DIR1 */
-	0x7f,	/* GPIO_DIR2 */
-	0x9f,	/* GPIO_MASK */
-	0xff,	/* GPIO_MASK1 */
-	0x7f,	/* GPIO_MASK2 */
-	0x16,	/* GPIO_STATE: internal clock, multiple 1x, 48kHz */
-	0x80,	/* GPIO_STATE1: mute */
-	0x00,	/* GPIO_STATE2 */
+static const unsigned char juli_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x20,	/* clock 512, mpu401, 1xADC, 1xDACs */
+	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit, 192k */
+	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
+	[ICE_EEP2_GPIO_DIR]    = 0x9f,
+	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+	[ICE_EEP2_GPIO_DIR2]   = 0x7f,
+	[ICE_EEP2_GPIO_MASK]   = 0x9f,
+	[ICE_EEP2_GPIO_MASK1]  = 0xff,
+	[ICE_EEP2_GPIO_MASK2]  = 0x7f,
+	[ICE_EEP2_GPIO_STATE]  = 0x16,	/* internal clock, multiple 1x, 48kHz */
+	[ICE_EEP2_GPIO_STATE1] = 0x80,	/* mute */
+	[ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_JULI,
 		.name = "ESI Juli@",
diff --git a/sound/pci/ice1712/juli.h b/sound/pci/ice1712/juli.h
index d9f8534..1b9294f 100644
--- a/sound/pci/ice1712/juli.h
+++ b/sound/pci/ice1712/juli.h
@@ -5,6 +5,6 @@
 
 #define VT1724_SUBDEVICE_JULI		0x31305345	/* Juli@ */
 
-extern struct snd_ice1712_card_info  snd_vt1724_juli_cards[];
+extern const struct snd_ice1712_card_info  snd_vt1724_juli_cards[];
 
 #endif	/* __SOUND_JULI_H */
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index e08d73f..0751718 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -71,7 +71,7 @@
  * Logarithmic volume values for WM8770
  * Computed as 20 * Log10(255 / x)
  */
-static unsigned char wm_vol[256] = {
+static const unsigned char wm_vol[256] = {
 	127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
 	23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
 	17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
@@ -89,13 +89,13 @@
 #define WM_VOL_MAX	(sizeof(wm_vol) - 1)
 #define WM_VOL_MUTE	0x8000
 
-static struct snd_akm4xxx akm_phase22 __devinitdata = {
+static const struct snd_akm4xxx akm_phase22 __devinitdata = {
 	.type = SND_AK4524,
 	.num_dacs = 2,
 	.num_adcs = 2,
 };
 
-static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
 	.caddr =	2,
 	.cif =		1,
 	.data_mask =	1 << 4,
@@ -152,36 +152,36 @@
 	return 0;
 }
 
-static unsigned char phase22_eeprom[] __devinitdata = {
-	0x00,	/* SYSCONF: 1xADC, 1xDACs */
-	0x80,	/* ACLINK: I2S */
-	0xf8,	/* I2S: vol, 96k, 24bit*/
-	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
-	0xFF,	/* GPIO_DIR */
-	0xFF,	/* GPIO_DIR1 */
-	0xFF,	/* GPIO_DIR2 */
-	0x00,	/* GPIO_MASK */
-	0x00,	/* GPIO_MASK1 */
-	0x00,	/* GPIO_MASK2 */
-	0x00,	/* GPIO_STATE: */
-	0x00,	/* GPIO_STATE1: */
-	0x00,	/* GPIO_STATE2 */
+static const unsigned char phase22_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x00,	/* 1xADC, 1xDACs */
+	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit */
+	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
+	[ICE_EEP2_GPIO_DIR]    = 0xff,
+	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+	[ICE_EEP2_GPIO_DIR2]   = 0xff,
+	[ICE_EEP2_GPIO_MASK]   = 0x00,
+	[ICE_EEP2_GPIO_MASK1]  = 0x00,
+	[ICE_EEP2_GPIO_MASK2]  = 0x00,
+	[ICE_EEP2_GPIO_STATE]  = 0x00,
+	[ICE_EEP2_GPIO_STATE1] = 0x00,
+	[ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-static unsigned char phase28_eeprom[] __devinitdata = {
-	0x0b,	/* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
-	0x80,	/* ACLINK: I2S */
-	0xfc,	/* I2S: vol, 96k, 24bit, 192k */
-	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
-	0xff,	/* GPIO_DIR */
-	0xff,	/* GPIO_DIR1 */
-	0x5f,	/* GPIO_DIR2 */
-	0x00,	/* GPIO_MASK */
-	0x00,	/* GPIO_MASK1 */
-	0x00,	/* GPIO_MASK2 */
-	0x00,	/* GPIO_STATE */
-	0x00,	/* GPIO_STATE1 */
-	0x00,	/* GPIO_STATE2 */
+static const unsigned char phase28_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x0b,	/* clock 512, spdif-in/ADC, 4DACs */
+	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
+	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
+	[ICE_EEP2_GPIO_DIR]    = 0xff,
+	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+	[ICE_EEP2_GPIO_DIR2]   = 0x5f,
+	[ICE_EEP2_GPIO_MASK]   = 0x00,
+	[ICE_EEP2_GPIO_MASK1]  = 0x00,
+	[ICE_EEP2_GPIO_MASK2]  = 0x00,
+	[ICE_EEP2_GPIO_STATE]  = 0x00,
+	[ICE_EEP2_GPIO_STATE1] = 0x00,
+	[ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
 /*
@@ -343,7 +343,7 @@
 
 static int __devinit phase28_init(struct snd_ice1712 *ice)
 {
-	static unsigned short wm_inits_phase28[] = {
+	static const unsigned short wm_inits_phase28[] = {
 		/* These come first to reduce init pop noise */
 		0x1b, 0x044,		/* ADC Mux (AC'97 source) */
 		0x1c, 0x00B,		/* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
@@ -382,7 +382,7 @@
 
 	unsigned int tmp;
 	struct snd_akm4xxx *ak;
-	unsigned short *p;
+	const unsigned short *p;
 	int i;
 
 	ice->num_total_dacs = 8;
@@ -697,10 +697,10 @@
 	return 0;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
-static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
 
-static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
+static const struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
@@ -815,7 +815,7 @@
 	}
 };
 
-static struct snd_kcontrol_new wm_controls[] __devinitdata = {
+static const struct snd_kcontrol_new wm_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "PCM Playback Switch",
@@ -870,7 +870,7 @@
 	return 0;
 }
 
-struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_PHASE22,
 		.name = "Terratec PHASE 22",
diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h
index 13e841b..ad379a9 100644
--- a/sound/pci/ice1712/phase.h
+++ b/sound/pci/ice1712/phase.h
@@ -31,7 +31,7 @@
 #define VT1724_SUBDEVICE_PHASE28	0x3b154911
 
 /* entry point */
-extern struct snd_ice1712_card_info snd_vt1724_phase_cards[];
+extern const struct snd_ice1712_card_info snd_vt1724_phase_cards[];
 
 /* PHASE28 GPIO bits */
 #define PHASE28_SPI_MISO	(1 << 21)
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 6c74c2d..9552497 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -434,7 +434,7 @@
  */
 static int cs_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = {
+	static const char * const texts[] = {
 		"Coax",		/* RXP0 */
 		"Optical",	/* RXP1 */
 		"CD",		/* RXP2 */
@@ -565,13 +565,13 @@
 	return changed;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1);
 
 /*
  * mixers
  */
 
-static struct snd_kcontrol_new pontis_controls[] __devinitdata = {
+static const struct snd_kcontrol_new pontis_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -741,7 +741,7 @@
  */
 static int __devinit pontis_init(struct snd_ice1712 *ice)
 {
-	static unsigned short wm_inits[] = {
+	static const unsigned short wm_inits[] = {
 		/* These come first to reduce init pop noise */
 		WM_ADC_MUX,	0x00c0,	/* ADC mute */
 		WM_DAC_MUTE,	0x0001,	/* DAC softmute */
@@ -750,7 +750,7 @@
 		WM_POWERDOWN,	0x0008,	/* All power-up except HP */
 		WM_RESET,	0x0000,	/* reset */
 	};
-	static unsigned short wm_inits2[] = {
+	static const unsigned short wm_inits2[] = {
 		WM_MASTER_CTRL,	0x0022,	/* 256fs, slave mode */
 		WM_DAC_INT,	0x0022,	/* I2S, normal polarity, 24bit */
 		WM_ADC_INT,	0x0022,	/* I2S, normal polarity, 24bit */
@@ -776,7 +776,7 @@
 		WM_DAC_MUTE,	0x0000,	/* DAC unmute */
 		WM_ADC_MUX,	0x0003,	/* ADC unmute, both CD/Line On */
 	};
-	static unsigned char cs_inits[] = {
+	static const unsigned char cs_inits[] = {
 		0x04,	0x80,	/* RUN, RXP0 */
 		0x05,	0x05,	/* slave, 24bit */
 		0x01,	0x00,
@@ -826,24 +826,24 @@
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char pontis_eeprom[] __devinitdata = {
-	0x08,	/* SYSCONF: clock 256, mpu401, spdif-in/ADC, 1DAC */
-	0x80,	/* ACLINK: I2S */
-	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
-	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
-	0x07,	/* GPIO_DIR */
-	0x00,	/* GPIO_DIR1 */
-	0x00,	/* GPIO_DIR2 (ignored) */
-	0x0f,	/* GPIO_MASK (4-7 reserved for CS8416) */
-	0xff,	/* GPIO_MASK1 */
-	0x00,	/* GPIO_MASK2 (ignored) */
-	0x06,	/* GPIO_STATE (0-low, 1-high, 2-high) */
-	0x00,	/* GPIO_STATE1 */
-	0x00,	/* GPIO_STATE2 (ignored) */
+static const unsigned char pontis_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x08,	/* clock 256, mpu401, spdif-in/ADC, 1DAC */
+	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit, 192k */
+	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
+	[ICE_EEP2_GPIO_DIR]    = 0x07,
+	[ICE_EEP2_GPIO_DIR1]   = 0x00,
+	[ICE_EEP2_GPIO_DIR2]   = 0x00,	/* ignored */
+	[ICE_EEP2_GPIO_MASK]   = 0x0f,	/* 4-7 reserved for CS8416 */
+	[ICE_EEP2_GPIO_MASK1]  = 0xff,
+	[ICE_EEP2_GPIO_MASK2]  = 0x00,	/* ignored */
+	[ICE_EEP2_GPIO_STATE]  = 0x06,	/* 0-low, 1-high, 2-high */
+	[ICE_EEP2_GPIO_STATE1] = 0x00,
+	[ICE_EEP2_GPIO_STATE2] = 0x00,	/* ignored */
 };
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
 	{
 		.subvendor = VT1720_SUBDEVICE_PONTIS_MS300,
 		.name = "Pontis MS300",
diff --git a/sound/pci/ice1712/pontis.h b/sound/pci/ice1712/pontis.h
index d0d1378..1a41825 100644
--- a/sound/pci/ice1712/pontis.h
+++ b/sound/pci/ice1712/pontis.h
@@ -28,6 +28,6 @@
 
 #define VT1720_SUBDEVICE_PONTIS_MS300	0x00020002	/* a dummy id for MS300 */
 
-extern struct snd_ice1712_card_info  snd_vt1720_pontis_cards[];
+extern const struct snd_ice1712_card_info  snd_vt1720_pontis_cards[];
 
 #endif /* __SOUND_PONTIS_H */
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 41b2605..31cc66e 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -357,14 +357,14 @@
 }
 #endif
 
-static DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
 
 /*
  * mixers
  */
 
-static struct snd_kcontrol_new stac_controls[] __devinitdata = {
+static const struct snd_kcontrol_new stac_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
@@ -475,7 +475,7 @@
  */
 static int __devinit prodigy192_init(struct snd_ice1712 *ice)
 {
-	static unsigned short stac_inits_prodigy[] = {
+	static const unsigned short stac_inits_prodigy[] = {
 		STAC946X_RESET, 0,
 /*		STAC946X_MASTER_VOLUME, 0,
 		STAC946X_LF_VOLUME, 0,
@@ -486,7 +486,7 @@
 		STAC946X_LFE_VOLUME, 0,*/
 		(unsigned short)-1
 	};
-	unsigned short *p;
+	const unsigned short *p;
 
 	/* prodigy 192 */
 	ice->num_total_dacs = 6;
@@ -506,25 +506,25 @@
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char prodigy71_eeprom[] __devinitdata = {
-	0x2b,	/* SYSCONF: clock 512, mpu401, spdif-in/ADC, 4DACs */
-	0x80,	/* ACLINK: I2S */
-	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
-	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
-	0xff,	/* GPIO_DIR */
-	0xff,	/* GPIO_DIR1 */
-	0xbf,	/* GPIO_DIR2 */
-	0x00,	/* GPIO_MASK */
-	0x00,	/* GPIO_MASK1 */
-	0x00,	/* GPIO_MASK2 */
-	0x00,	/* GPIO_STATE */
-	0x00,	/* GPIO_STATE1 */
-	0x00,	/* GPIO_STATE2 */
+static const unsigned char prodigy71_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x2b,	/* clock 512, mpu401, spdif-in/ADC, 4DACs */
+	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit, 192k */
+	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
+	[ICE_EEP2_GPIO_DIR]    = 0xff,
+	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+	[ICE_EEP2_GPIO_DIR2]   = 0xbf,
+	[ICE_EEP2_GPIO_MASK]   = 0x00,
+	[ICE_EEP2_GPIO_MASK1]  = 0x00,
+	[ICE_EEP2_GPIO_MASK2]  = 0x00,
+	[ICE_EEP2_GPIO_STATE]  = 0x00,
+	[ICE_EEP2_GPIO_STATE1] = 0x00,
+	[ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_PRODIGY192VE,
 		.name = "Audiotrak Prodigy 192",
diff --git a/sound/pci/ice1712/prodigy192.h b/sound/pci/ice1712/prodigy192.h
index 94c824e..2fa2e62 100644
--- a/sound/pci/ice1712/prodigy192.h
+++ b/sound/pci/ice1712/prodigy192.h
@@ -6,6 +6,6 @@
 
 #define VT1724_SUBDEVICE_PRODIGY192VE	 0x34495345	/* PRODIGY 192 VE */
 
-extern struct snd_ice1712_card_info  snd_vt1724_prodigy192_cards[];
+extern const struct snd_ice1712_card_info  snd_vt1724_prodigy192_cards[];
 
 #endif	/* __SOUND_PRODIGY192_H */
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index bf98ea3..025a7e8 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -84,38 +84,142 @@
 }
 
 /*
+ * I2C access to the PT2258 volume controller on GPIO 6/7 (Revolution 5.1)
+ */
+
+static void revo_i2c_start(struct snd_i2c_bus *bus)
+{
+	struct snd_ice1712 *ice = bus->private_data;
+	snd_ice1712_save_gpio_status(ice);
+}
+
+static void revo_i2c_stop(struct snd_i2c_bus *bus)
+{
+	struct snd_ice1712 *ice = bus->private_data;
+	snd_ice1712_restore_gpio_status(ice);
+}
+
+static void revo_i2c_direction(struct snd_i2c_bus *bus, int clock, int data)
+{
+	struct snd_ice1712 *ice = bus->private_data;
+	unsigned int mask, val;
+
+	val = 0;
+	if (clock)
+		val |= VT1724_REVO_I2C_CLOCK;	/* write SCL */
+	if (data)
+		val |= VT1724_REVO_I2C_DATA;	/* write SDA */
+	mask = VT1724_REVO_I2C_CLOCK | VT1724_REVO_I2C_DATA;
+	ice->gpio.direction &= ~mask;
+	ice->gpio.direction |= val;
+	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+	snd_ice1712_gpio_set_mask(ice, ~mask);
+}
+
+static void revo_i2c_setlines(struct snd_i2c_bus *bus, int clk, int data)
+{
+	struct snd_ice1712 *ice = bus->private_data;
+	unsigned int val = 0;
+
+	if (clk)
+		val |= VT1724_REVO_I2C_CLOCK;
+	if (data)
+		val |= VT1724_REVO_I2C_DATA;
+	snd_ice1712_gpio_write_bits(ice,
+				    VT1724_REVO_I2C_DATA |
+				    VT1724_REVO_I2C_CLOCK, val);
+	udelay(5);
+}
+
+static int revo_i2c_getdata(struct snd_i2c_bus *bus, int ack)
+{
+	struct snd_ice1712 *ice = bus->private_data;
+	int bit;
+
+	if (ack)
+		udelay(5);
+	bit = snd_ice1712_gpio_read_bits(ice, VT1724_REVO_I2C_DATA) ? 1 : 0;
+	return bit;
+}
+
+static struct snd_i2c_bit_ops revo51_bit_ops = {
+	.start = revo_i2c_start,
+	.stop = revo_i2c_stop,
+	.direction = revo_i2c_direction,
+	.setlines = revo_i2c_setlines,
+	.getdata = revo_i2c_getdata,
+};
+
+static int revo51_i2c_init(struct snd_ice1712 *ice,
+			   struct snd_pt2258 *pt)
+{
+	int err;
+
+	/* create the I2C bus */
+	err = snd_i2c_bus_create(ice->card, "ICE1724 GPIO6", NULL, &ice->i2c);
+	if (err < 0)
+		return err;
+
+	ice->i2c->private_data = ice;
+	ice->i2c->hw_ops.bit = &revo51_bit_ops;
+
+	/* create the I2C device */
+	err = snd_i2c_device_create(ice->i2c, "PT2258", 0x40,
+				    &ice->spec.revo51.dev);
+	if (err < 0)
+		return err;
+
+	pt->card = ice->card;
+	pt->i2c_bus = ice->i2c;
+	pt->i2c_dev = ice->spec.revo51.dev;
+	ice->spec.revo51.pt2258 = pt;
+
+	snd_pt2258_reset(pt);
+
+	return 0;
+}
+
+/*
  * initialize the chips on M-Audio Revolution cards
  */
 
 #define AK_DAC(xname,xch) { .name = xname, .num_channels = xch }
 
-static struct snd_akm4xxx_dac_channel revo71_front[] = {
+static const struct snd_akm4xxx_dac_channel revo71_front[] = {
 	AK_DAC("PCM Playback Volume", 2)
 };
 
-static struct snd_akm4xxx_dac_channel revo71_surround[] = {
+static const struct snd_akm4xxx_dac_channel revo71_surround[] = {
 	AK_DAC("PCM Center Playback Volume", 1),
 	AK_DAC("PCM LFE Playback Volume", 1),
 	AK_DAC("PCM Side Playback Volume", 2),
 	AK_DAC("PCM Rear Playback Volume", 2),
 };
 
-static struct snd_akm4xxx_dac_channel revo51_dac[] = {
+static const struct snd_akm4xxx_dac_channel revo51_dac[] = {
 	AK_DAC("PCM Playback Volume", 2),
 	AK_DAC("PCM Center Playback Volume", 1),
 	AK_DAC("PCM LFE Playback Volume", 1),
 	AK_DAC("PCM Rear Playback Volume", 2),
 };
 
-static struct snd_akm4xxx_adc_channel revo51_adc[] = {
+static const char *revo51_adc_input_names[] = {
+	"Mic",
+	"Line",
+	"CD",
+	NULL
+};
+
+static const struct snd_akm4xxx_adc_channel revo51_adc[] = {
 	{
 		.name = "PCM Capture Volume",
 		.switch_name = "PCM Capture Switch",
-		.num_channels = 2
+		.num_channels = 2,
+		.input_names = revo51_adc_input_names
 	},
 };
 
-static struct snd_akm4xxx akm_revo_front __devinitdata = {
+static const struct snd_akm4xxx akm_revo_front __devinitdata = {
 	.type = SND_AK4381,
 	.num_dacs = 2,
 	.ops = {
@@ -124,7 +228,7 @@
 	.dac_info = revo71_front,
 };
 
-static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
 	.caddr = 1,
 	.cif = 0,
 	.data_mask = VT1724_REVO_CDOUT,
@@ -136,7 +240,7 @@
 	.mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_revo_surround __devinitdata = {
+static const struct snd_akm4xxx akm_revo_surround __devinitdata = {
 	.type = SND_AK4355,
 	.idx_offset = 1,
 	.num_dacs = 6,
@@ -146,7 +250,7 @@
 	.dac_info = revo71_surround,
 };
 
-static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
 	.caddr = 3,
 	.cif = 0,
 	.data_mask = VT1724_REVO_CDOUT,
@@ -158,7 +262,7 @@
 	.mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_revo51 __devinitdata = {
+static const struct snd_akm4xxx akm_revo51 __devinitdata = {
 	.type = SND_AK4358,
 	.num_dacs = 6,
 	.ops = {
@@ -167,36 +271,213 @@
 	.dac_info = revo51_dac,
 };
 
-static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0,
 	.data_mask = VT1724_REVO_CDOUT,
 	.clk_mask = VT1724_REVO_CCLK,
-	.cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2,
-	.cs_addr = VT1724_REVO_CS1 | VT1724_REVO_CS2,
-	.cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2,
+	.cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
+	.cs_addr = VT1724_REVO_CS1,
+	.cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
 	.add_flags = VT1724_REVO_CCLK, /* high at init */
 	.mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_revo51_adc __devinitdata = {
+static const struct snd_akm4xxx akm_revo51_adc __devinitdata = {
 	.type = SND_AK5365,
 	.num_adcs = 2,
 	.adc_info = revo51_adc,
 };
 
-static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = {
+static const struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0,
 	.data_mask = VT1724_REVO_CDOUT,
 	.clk_mask = VT1724_REVO_CCLK,
-	.cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2,
-	.cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS2,
-	.cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2,
+	.cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
+	.cs_addr = VT1724_REVO_CS0,
+	.cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
 	.add_flags = VT1724_REVO_CCLK, /* high at init */
 	.mask_flags = 0,
 };
 
+static struct snd_pt2258 ptc_revo51_volume;
+
+/* AK4358 for AP192 DAC, AK5385A for ADC */
+static void ap192_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
+{
+	struct snd_ice1712 *ice = ak->private_data[0];
+
+	revo_set_rate_val(ak, rate);
+
+#if 1 /* FIXME: do we need this procedure? */
+	/* reset DFS pin of AK5385A for ADC, too */
+	/* DFS0 (pin 18) -- GPIO10 pin 77 */
+	snd_ice1712_save_gpio_status(ice);
+	snd_ice1712_gpio_write_bits(ice, 1 << 10,
+				    rate > 48000 ? (1 << 10) : 0);
+	snd_ice1712_restore_gpio_status(ice);
+#endif
+}
+
+static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
+	AK_DAC("PCM Playback Volume", 2)
+};
+
+static const struct snd_akm4xxx akm_ap192 __devinitdata = {
+	.type = SND_AK4358,
+	.num_dacs = 2,
+	.ops = {
+		.set_rate_val = ap192_set_rate_val
+	},
+	.dac_info = ap192_dac,
+};
+
+static const struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
+	.caddr = 2,
+	.cif = 0,
+	.data_mask = VT1724_REVO_CDOUT,
+	.clk_mask = VT1724_REVO_CCLK,
+	.cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS3,
+	.cs_addr = VT1724_REVO_CS3,
+	.cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS3,
+	.add_flags = VT1724_REVO_CCLK, /* high at init */
+	.mask_flags = 0,
+};
+
+#if 0
+/* FIXME: ak4114 makes the sound much lower due to some confliction,
+ *        so let's disable it right now...
+ */
+#define BUILD_AK4114_AP192
+#endif
+
+#ifdef BUILD_AK4114_AP192
+/* AK4114 support on Audiophile 192 */
+/* CDTO (pin 32) -- GPIO2 pin 52
+ * CDTI (pin 33) -- GPIO3 pin 53 (shared with AK4358)
+ * CCLK (pin 34) -- GPIO1 pin 51 (shared with AK4358)
+ * CSN  (pin 35) -- GPIO7 pin 59
+ */
+#define AK4114_ADDR	0x00
+
+static void write_data(struct snd_ice1712 *ice, unsigned int gpio,
+		       unsigned int data, int idx)
+{
+	for (; idx >= 0; idx--) {
+		/* drop clock */
+		gpio &= ~VT1724_REVO_CCLK;
+		snd_ice1712_gpio_write(ice, gpio);
+		udelay(1);
+		/* set data */
+		if (data & (1 << idx))
+			gpio |= VT1724_REVO_CDOUT;
+		else
+			gpio &= ~VT1724_REVO_CDOUT;
+		snd_ice1712_gpio_write(ice, gpio);
+		udelay(1);
+		/* raise clock */
+		gpio |= VT1724_REVO_CCLK;
+		snd_ice1712_gpio_write(ice, gpio);
+		udelay(1);
+	}
+}
+
+static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio,
+			       int idx)
+{
+	unsigned char data = 0;
+
+	for (; idx >= 0; idx--) {
+		/* drop clock */
+		gpio &= ~VT1724_REVO_CCLK;
+		snd_ice1712_gpio_write(ice, gpio);
+		udelay(1);
+		/* read data */
+		if (snd_ice1712_gpio_read(ice) & VT1724_REVO_CDIN)
+			data |= (1 << idx);
+		udelay(1);
+		/* raise clock */
+		gpio |= VT1724_REVO_CCLK;
+		snd_ice1712_gpio_write(ice, gpio);
+		udelay(1);
+	}
+	return data;
+}
+
+static unsigned char ap192_4wire_start(struct snd_ice1712 *ice)
+{
+	unsigned int tmp;
+
+	snd_ice1712_save_gpio_status(ice);
+	tmp = snd_ice1712_gpio_read(ice);
+	tmp |= VT1724_REVO_CCLK; /* high at init */
+	tmp |= VT1724_REVO_CS0;
+	tmp &= ~VT1724_REVO_CS3;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(1);
+	return tmp;
+}
+
+static void ap192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)
+{
+	tmp |= VT1724_REVO_CS3;
+	tmp |= VT1724_REVO_CS0;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(1);
+	snd_ice1712_restore_gpio_status(ice);
+}
+
+static void ap192_ak4114_write(void *private_data, unsigned char addr,
+			       unsigned char data)
+{
+	struct snd_ice1712 *ice = private_data;
+	unsigned int tmp, addrdata;
+
+	tmp = ap192_4wire_start(ice);
+	addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f);
+	addrdata = (addrdata << 8) | data;
+	write_data(ice, tmp, addrdata, 15);
+	ap192_4wire_finish(ice, tmp);
+}
+
+static unsigned char ap192_ak4114_read(void *private_data, unsigned char addr)
+{
+	struct snd_ice1712 *ice = private_data;
+	unsigned int tmp;
+	unsigned char data;
+
+	tmp = ap192_4wire_start(ice);
+	write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7);
+	data = read_data(ice, tmp, 7);
+	ap192_4wire_finish(ice, tmp);
+	return data;
+}
+
+static int ap192_ak4114_init(struct snd_ice1712 *ice)
+{
+	static const unsigned char ak4114_init_vals[] = {
+		AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
+		AK4114_DIF_I24I2S,
+		AK4114_TX1E,
+		AK4114_EFH_1024 | AK4114_DIT | AK4114_IPS(1),
+		0,
+		0
+	};
+	static const unsigned char ak4114_init_txcsb[] = {
+		0x41, 0x02, 0x2c, 0x00, 0x00
+	};
+	struct ak4114 *ak;
+	int err;
+
+	return snd_ak4114_create(ice->card,
+				 ap192_ak4114_read,
+				 ap192_ak4114_write,
+				 ak4114_init_vals, ak4114_init_txcsb,
+				 ice, &ak);
+}
+#endif /* BUILD_AK4114_AP192 */
+
 static int __devinit revo_init(struct snd_ice1712 *ice)
 {
 	struct snd_akm4xxx *ak;
@@ -213,6 +494,10 @@
 		ice->num_total_dacs = 6;
 		ice->num_total_adcs = 2;
 		break;
+	case VT1724_SUBDEVICE_AUDIOPHILE192:
+		ice->num_total_dacs = 2;
+		ice->num_total_adcs = 2;
+		break;
 	default:
 		snd_BUG();
 		return -EINVAL;
@@ -235,14 +520,28 @@
 		break;
 	case VT1724_SUBDEVICE_REVOLUTION51:
 		ice->akm_codecs = 2;
-		if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo51, &akm_revo51_priv, ice)) < 0)
+		err = snd_ice1712_akm4xxx_init(ak, &akm_revo51,
+					       &akm_revo51_priv, ice);
+		if (err < 0)
 			return err;
-		err = snd_ice1712_akm4xxx_init(ak + 1, &akm_revo51_adc,
+		err = snd_ice1712_akm4xxx_init(ak+1, &akm_revo51_adc,
 					       &akm_revo51_adc_priv, ice);
 		if (err < 0)
 			return err;
-		/* unmute all codecs - needed! */
-		snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE);
+		err = revo51_i2c_init(ice, &ptc_revo51_volume);
+		if (err < 0)
+			return err;
+		/* unmute all codecs */
+		snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE,
+					    VT1724_REVO_MUTE);
+		break;
+	case VT1724_SUBDEVICE_AUDIOPHILE192:
+		ice->akm_codecs = 1;
+		err = snd_ice1712_akm4xxx_init(ak, &akm_ap192, &akm_ap192_priv,
+					       ice);
+		if (err < 0)
+			return err;
+		
 		break;
 	}
 
@@ -256,16 +555,34 @@
 
 	switch (ice->eeprom.subvendor) {
 	case VT1724_SUBDEVICE_REVOLUTION71:
+		err = snd_ice1712_akm4xxx_build_controls(ice);
+		if (err < 0)
+			return err;
+		break;
 	case VT1724_SUBDEVICE_REVOLUTION51:
 		err = snd_ice1712_akm4xxx_build_controls(ice);
 		if (err < 0)
 			return err;
+		err = snd_pt2258_build_controls(ice->spec.revo51.pt2258);
+		if (err < 0)
+			return err;
+		break;
+	case VT1724_SUBDEVICE_AUDIOPHILE192:
+		err = snd_ice1712_akm4xxx_build_controls(ice);
+		if (err < 0)
+			return err;
+#ifdef BUILD_AK4114_AP192
+		err = ap192_ak4114_init(ice);
+		if (err < 0)
+			return err;
+#endif
+		break;
 	}
 	return 0;
 }
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_REVOLUTION71,
 		.name = "M Audio Revolution-7.1",
@@ -280,5 +597,12 @@
 		.chip_init = revo_init,
 		.build_controls = revo_add_controls,
 	},
+	{
+		.subvendor = VT1724_SUBDEVICE_AUDIOPHILE192,
+		.name = "M Audio Audiophile192",
+		.model = "ap192",
+		.chip_init = revo_init,
+		.build_controls = revo_add_controls,
+	},
 	{ } /* terminator */
 };
diff --git a/sound/pci/ice1712/revo.h b/sound/pci/ice1712/revo.h
index efbb86e..2a24488 100644
--- a/sound/pci/ice1712/revo.h
+++ b/sound/pci/ice1712/revo.h
@@ -26,13 +26,15 @@
 
 #define REVO_DEVICE_DESC \
 		"{MidiMan M Audio,Revolution 7.1},"\
-		"{MidiMan M Audio,Revolution 5.1},"
+		"{MidiMan M Audio,Revolution 5.1},"\
+		"{MidiMan M Audio,Audiophile 192},"
 
 #define VT1724_SUBDEVICE_REVOLUTION71	0x12143036
 #define VT1724_SUBDEVICE_REVOLUTION51	0x12143136
+#define VT1724_SUBDEVICE_AUDIOPHILE192	0x12143236
 
 /* entry point */
-extern struct snd_ice1712_card_info snd_vt1724_revo_cards[];
+extern const struct snd_ice1712_card_info snd_vt1724_revo_cards[];
 
 
 /*
@@ -42,9 +44,12 @@
 #define VT1724_REVO_CCLK	0x02
 #define VT1724_REVO_CDIN	0x04	/* not used */
 #define VT1724_REVO_CDOUT	0x08
-#define VT1724_REVO_CS0		0x10	/* AK5365 chipselect for Rev. 5.1 */
+#define VT1724_REVO_CS0		0x10	/* AK5365 chipselect for (revo51) */
 #define VT1724_REVO_CS1		0x20	/* front AKM4381 chipselect */
-#define VT1724_REVO_CS2		0x40	/* surround AKM4355 chipselect */
+#define VT1724_REVO_CS2		0x40	/* surround AKM4355 CS (revo71) */
+#define VT1724_REVO_I2C_DATA    0x40    /* I2C: PT 2258 SDA (on revo51) */
+#define VT1724_REVO_I2C_CLOCK   0x80    /* I2C: PT 2258 SCL (on revo51) */
+#define VT1724_REVO_CS3		0x80	/* AK4114 for AP192 */
 #define VT1724_REVO_MUTE	(1<<22)	/* 0 = all mute, 1 = normal operation */
 
 #endif /* __SOUND_REVO_H */
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
index 7ca263c1..72b060d 100644
--- a/sound/pci/ice1712/vt1720_mobo.c
+++ b/sound/pci/ice1712/vt1720_mobo.c
@@ -30,6 +30,7 @@
 #include <sound/core.h>
 
 #include "ice1712.h"
+#include "envy24ht.h"
 #include "vt1720_mobo.h"
 
 
@@ -55,41 +56,41 @@
 
 /* EEPROM image */
 
-static unsigned char k8x800_eeprom[] __devinitdata = {
-	0x01,	/* SYSCONF: clock 256, 1ADC, 2DACs */
-	0x02,	/* ACLINK: ACLINK, packed */
-	0x00,	/* I2S: - */
-	0x00,	/* SPDIF: - */
-	0xff,	/* GPIO_DIR */
-	0xff,	/* GPIO_DIR1 */
-	0x00,	/* - */
-	0xff,	/* GPIO_MASK */
-	0xff,	/* GPIO_MASK1 */
-	0x00,	/* - */
-	0x00,	/* GPIO_STATE */
-	0x00,	/* GPIO_STATE1 */
-	0x00,	/* - */
+static const unsigned char k8x800_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x01,	/* clock 256, 1ADC, 2DACs */
+	[ICE_EEP2_ACLINK]      = 0x02,	/* ACLINK, packed */
+	[ICE_EEP2_I2S]         = 0x00,	/* - */
+	[ICE_EEP2_SPDIF]       = 0x00,	/* - */
+	[ICE_EEP2_GPIO_DIR]    = 0xff,
+	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+	[ICE_EEP2_GPIO_DIR2]   = 0x00,	/* - */
+	[ICE_EEP2_GPIO_MASK]   = 0xff,
+	[ICE_EEP2_GPIO_MASK1]  = 0xff,
+	[ICE_EEP2_GPIO_MASK2]  = 0x00,	/* - */
+	[ICE_EEP2_GPIO_STATE]  = 0x00,
+	[ICE_EEP2_GPIO_STATE1] = 0x00,
+	[ICE_EEP2_GPIO_STATE2] = 0x00,	/* - */
 };
 
-static unsigned char sn25p_eeprom[] __devinitdata = {
-	0x01,	/* SYSCONF: clock 256, 1ADC, 2DACs */
-	0x02,	/* ACLINK: ACLINK, packed */
-	0x00,	/* I2S: - */
-	0x41,	/* SPDIF: - */
-	0xff,	/* GPIO_DIR */
-	0xff,	/* GPIO_DIR1 */
-	0x00,	/* - */
-	0xff,	/* GPIO_MASK */
-	0xff,	/* GPIO_MASK1 */
-	0x00,	/* - */
-	0x00,	/* GPIO_STATE */
-	0x00,	/* GPIO_STATE1 */
-	0x00,	/* - */
+static const unsigned char sn25p_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x01,	/* clock 256, 1ADC, 2DACs */
+	[ICE_EEP2_ACLINK]      = 0x02,	/* ACLINK, packed */
+	[ICE_EEP2_I2S]         = 0x00,	/* - */
+	[ICE_EEP2_SPDIF]       = 0x41,	/* - */
+	[ICE_EEP2_GPIO_DIR]    = 0xff,
+	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+	[ICE_EEP2_GPIO_DIR2]   = 0x00,	/* - */
+	[ICE_EEP2_GPIO_MASK]   = 0xff,
+	[ICE_EEP2_GPIO_MASK1]  = 0xff,
+	[ICE_EEP2_GPIO_MASK2]  = 0x00,	/* - */
+	[ICE_EEP2_GPIO_STATE]  = 0x00,
+	[ICE_EEP2_GPIO_STATE1] = 0x00,
+	[ICE_EEP2_GPIO_STATE2] = 0x00,	/* - */
 };
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
+const struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
 	{
 		.subvendor = VT1720_SUBDEVICE_K8X800,
 		.name = "Albatron K8X800 Pro II",
diff --git a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h
index 0b1b0ee..70af3ad 100644
--- a/sound/pci/ice1712/vt1720_mobo.h
+++ b/sound/pci/ice1712/vt1720_mobo.h
@@ -36,6 +36,6 @@
 #define VT1720_SUBDEVICE_9CJS		0x0f272327
 #define VT1720_SUBDEVICE_SN25P		0x97123650
 
-extern struct snd_ice1712_card_info  snd_vt1720_mobo_cards[];
+extern const struct snd_ice1712_card_info  snd_vt1720_mobo_cards[];
 
 #endif /* __SOUND_VT1720_MOBO_H */
diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c
new file mode 100644
index 0000000..4a706b1
--- /dev/null
+++ b/sound/pci/ice1712/wtm.c
@@ -0,0 +1,542 @@
+/*
+ *	ALSA driver for ICEnsemble VT1724 (Envy24HT)
+ *	
+ *	Lowlevel functions for Ego Sys Waveterminal 192M
+ *
+ *		Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com>
+ *		Some functions are taken from the Prodigy192 driver
+ *		source
+ *		
+ *	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 <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "wtm.h"
+#include "stac946x.h"
+
+
+/*
+ *	2*ADC 6*DAC no1 ringbuffer r/w on i2c bus 
+ */
+static inline void stac9460_put(struct snd_ice1712 *ice, int reg, 
+						unsigned char val)
+{
+	snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
+}
+
+static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
+{
+	return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
+}
+
+/*
+ *	2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
+ */
+static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
+						unsigned char val)
+{
+	snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
+}
+
+static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
+{
+	return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
+}
+
+
+/*
+ *	DAC mute control
+ */
+static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	return 0;
+}
+
+static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char val;
+	int idx, id;
+
+	if (kcontrol->private_value) {
+		idx = STAC946X_MASTER_VOLUME;
+		id = 0;
+	} else {
+		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+		idx = id + STAC946X_LF_VOLUME;
+	}
+	if (id < 6)
+		val = stac9460_get(ice, idx);
+	else 
+		val = stac9460_2_get(ice,idx - 6);
+	ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
+	return 0;
+}
+
+static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char new, old;
+	int id, idx;
+	int change;
+
+	if (kcontrol->private_value) {
+		idx = STAC946X_MASTER_VOLUME;
+		old = stac9460_get(ice, idx);
+		new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
+		       					(old & ~0x80);
+		change = (new != old);
+		if (change) {
+			stac9460_put(ice, idx, new);
+			stac9460_2_put(ice, idx, new);
+		}
+	} else {
+		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+		idx = id + STAC946X_LF_VOLUME;
+		if (id < 6)
+			old = stac9460_get(ice, idx);
+		else 
+			old = stac9460_2_get(ice, idx - 6);
+		new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
+							(old & ~0x80);
+		change = (new != old);
+		if (change) {
+			if (id < 6)
+			       	stac9460_put(ice, idx, new);
+			else
+			       	stac9460_2_put(ice, idx - 6, new);
+		}
+	}
+	return change;
+}
+
+/*
+ * 	DAC volume attenuation mixer control
+ */
+static int stac9460_dac_vol_info(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;			/* mute */
+	uinfo->value.integer.max = 0x7f;		/* 0dB */
+	return 0;
+}
+
+static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	int idx, id;
+	unsigned char vol;
+
+	if (kcontrol->private_value) {
+		idx = STAC946X_MASTER_VOLUME;
+		id = 0;
+	} else {
+		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+		idx = id + STAC946X_LF_VOLUME;
+	}
+	if (id < 6)
+		vol = stac9460_get(ice, idx) & 0x7f;
+	else 
+		vol = stac9460_2_get(ice, idx - 6) & 0x7f;
+	ucontrol->value.integer.value[0] = 0x7f - vol;
+	return 0;
+}
+
+static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	int idx, id;
+	unsigned char tmp, ovol, nvol;
+	int change;
+
+	if (kcontrol->private_value) {
+		idx = STAC946X_MASTER_VOLUME;
+		nvol = ucontrol->value.integer.value[0];
+		tmp = stac9460_get(ice, idx);
+		ovol = 0x7f - (tmp & 0x7f);
+		change = (ovol != nvol);
+		if (change) {
+			 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
+			 stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
+		}
+	} else {
+		id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+		idx = id + STAC946X_LF_VOLUME;
+		nvol = ucontrol->value.integer.value[0];
+		if (id < 6)
+			tmp = stac9460_get(ice, idx);
+		else 
+			tmp = stac9460_2_get(ice, idx - 6);
+		ovol = 0x7f - (tmp & 0x7f);
+		change = (ovol != nvol);
+		if (change) {
+			if (id < 6)
+				stac9460_put(ice, idx, (0x7f - nvol) |
+					       		(tmp & 0x80));
+			else 
+				stac9460_2_put(ice, idx-6, (0x7f - nvol) |
+					       			(tmp & 0x80));
+		}
+	}
+	return change;
+}
+
+/*
+ * ADC mute control
+ */
+static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char val;
+	int i, id;
+	
+	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	if (id == 0) {
+		for (i = 0; i < 2; ++i) {
+			val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
+			ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
+		}
+	} else {
+		for (i = 0; i < 2; ++i) {
+			val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);
+			ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
+		}
+	}
+	return 0;
+}
+
+static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char new, old;
+	int i, reg, id;
+	int change;
+	
+	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	if (id == 0) {
+		for (i = 0; i < 2; ++i) {
+			reg = STAC946X_MIC_L_VOLUME + i;
+			old = stac9460_get(ice, reg);
+			new = (~ucontrol->value.integer.value[i]<<7&0x80) |
+			       					(old&~0x80);
+			change = (new != old);
+			if (change)
+				stac9460_put(ice, reg, new);
+		}
+	} else {
+		for (i = 0; i < 2; ++i) {
+			reg = STAC946X_MIC_L_VOLUME + i;
+			old = stac9460_2_get(ice, reg);
+			new = (~ucontrol->value.integer.value[i]<<7&0x80) |
+			       					(old&~0x80);
+			change = (new != old);
+			if (change)
+				stac9460_2_put(ice, reg, new);
+		}
+	}
+	return change;
+}
+
+/*
+ *ADC gain mixer control
+ */
+static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;		/* 0dB */
+	uinfo->value.integer.max = 0x0f;	/* 22.5dB */
+	return 0;
+}
+
+static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	int i, reg, id;
+	unsigned char vol;
+	
+	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	if (id == 0) {
+		for (i = 0; i < 2; ++i) {
+			reg = STAC946X_MIC_L_VOLUME + i;
+			vol = stac9460_get(ice, reg) & 0x0f;
+			ucontrol->value.integer.value[i] = 0x0f - vol;
+		}
+	} else {
+		for (i = 0; i < 2; ++i) {
+			reg = STAC946X_MIC_L_VOLUME + i;
+			vol = stac9460_2_get(ice, reg) & 0x0f;
+			ucontrol->value.integer.value[i] = 0x0f - vol;
+		}
+	}
+	return 0;
+}
+
+static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
+	       		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	int i, reg, id;
+	unsigned char ovol, nvol;
+	int change;
+	
+	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	if (id == 0) {
+		for (i = 0; i < 2; ++i) {
+			reg = STAC946X_MIC_L_VOLUME + i;
+			nvol = ucontrol->value.integer.value[i];
+			ovol = 0x0f - stac9460_get(ice, reg);
+			change = ((ovol & 0x0f) != nvol);
+			if (change)
+				stac9460_put(ice, reg, (0x0f - nvol) |
+					       		(ovol & ~0x0f));
+		}
+	} else {
+		for (i = 0; i < 2; ++i) {
+			reg = STAC946X_MIC_L_VOLUME + i;
+			nvol = ucontrol->value.integer.value[i];
+			ovol = 0x0f - stac9460_2_get(ice, reg);
+			change = ((ovol & 0x0f) != nvol);
+			if (change)
+				stac9460_2_put(ice, reg, (0x0f - nvol) |
+					       		(ovol & ~0x0f));
+		}
+	}
+	return change;
+}
+
+/*
+ * MIC / LINE switch fonction
+ */
+
+static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
+	       		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char val;
+	int id;
+		
+	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	if (id == 0)
+	       	val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
+	else
+	       	val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
+	ucontrol->value.integer.value[0] = ~val>>7 & 0x1;
+	return 0;
+}
+
+static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
+	       		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char new, old;
+	int change, id;
+
+	id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	if (id == 0)
+	       	old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
+	else
+	       	old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
+	new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80);
+	change = (new != old);
+	if (change) {
+		if (id == 0)
+		       	stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
+		else
+		       	stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
+	}
+	return change;
+}
+
+/*
+ * Control tabs
+ */
+static const struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = stac9460_dac_mute_info,
+		.get = stac9460_dac_mute_get,
+		.put = stac9460_dac_mute_put,
+		.private_value = 1
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.info = stac9460_dac_vol_info,
+		.get = stac9460_dac_vol_get,
+		.put = stac9460_dac_vol_put,
+		.private_value = 1,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "MIC/Line switch",
+		.count = 2,
+		.info = stac9460_mic_sw_info,
+		.get = stac9460_mic_sw_get,
+		.put = stac9460_mic_sw_put,
+
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "DAC Switch",
+		.count = 8,
+		.info = stac9460_dac_mute_info,
+		.get = stac9460_dac_mute_get,
+		.put = stac9460_dac_mute_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "DAC Volume",
+		.count = 8,
+		.info = stac9460_dac_vol_info,
+		.get = stac9460_dac_vol_get,
+		.put = stac9460_dac_vol_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "ADC Switch",
+		.count = 2,
+		.info = stac9460_adc_mute_info,
+		.get = stac9460_adc_mute_get,
+		.put = stac9460_adc_mute_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "ADC Volume",
+		.count = 2,
+		.info = stac9460_adc_vol_info,
+		.get = stac9460_adc_vol_get,
+		.put = stac9460_adc_vol_put,
+
+	}	
+};
+
+
+
+/*INIT*/
+static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
+{
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {
+		err = snd_ctl_add(ice->card,
+				snd_ctl_new1(&stac9640_controls[i], ice));
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+static int __devinit wtm_init(struct snd_ice1712 *ice)
+{
+	static unsigned short stac_inits_prodigy[] = {
+		STAC946X_RESET, 0,
+		(unsigned short)-1
+	};
+	unsigned short *p;
+		
+	/*WTM 192M*/
+	ice->num_total_dacs = 8;
+	ice->num_total_adcs = 4;
+	ice->force_rdma1 = 1;
+
+	/*initialize codec*/
+	p = stac_inits_prodigy;
+	for (; *p != (unsigned short)-1; p += 2) {
+		stac9460_put(ice, p[0], p[1]);
+		stac9460_2_put(ice, p[0], p[1]);
+	}
+	return 0;
+}
+
+
+static unsigned char wtm_eeprom[] __devinitdata = {
+	0x47,	/*SYSCONF: clock 192KHz, 4ADC, 8DAC */
+	0x80,	/* ACLINK : I2S */
+	0xf8,	/* I2S: vol; 96k, 24bit, 192k */
+	0xc1	/*SPDIF: out-en, spidf ext out*/,
+	0x9f,	/* GPIO_DIR */
+	0xff,	/* GPIO_DIR1 */
+	0x7f,	/* GPIO_DIR2 */
+	0x9f,	/* GPIO_MASK */
+	0xff,	/* GPIO_MASK1 */
+	0x7f,	/* GPIO_MASK2 */
+	0x16,	/* GPIO_STATE */
+	0x80,	/* GPIO_STATE1 */
+	0x00,	/* GPIO_STATE2 */
+};
+
+
+/*entry point*/
+struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
+	{
+		.subvendor = VT1724_SUBDEVICE_WTM,
+		.name = "ESI Waveterminal 192M",
+		.model = "WT192M",
+		.chip_init = wtm_init,
+		.build_controls = wtm_add_controls,
+		.eeprom_size = sizeof(wtm_eeprom),
+		.eeprom_data = wtm_eeprom,
+	},
+	{} /*terminator*/
+};
diff --git a/sound/pci/ice1712/wtm.h b/sound/pci/ice1712/wtm.h
new file mode 100644
index 0000000..03a394e
--- /dev/null
+++ b/sound/pci/ice1712/wtm.h
@@ -0,0 +1,20 @@
+#ifndef __SOUND_WTM_H
+#define __SOUND_WTM_H
+
+/* ID */
+#define WTM_DEVICE_DESC		"{EGO SYS INC,WaveTerminal 192M},"
+#define VT1724_SUBDEVICE_WTM	0x36495345	/* WT192M ver1.0 */
+
+/*
+ *chip addresses on I2C bus
+ */
+
+#define	AK4114_ADDR		0x20	/*S/PDIF receiver*/
+#define STAC9460_I2C_ADDR	0x54	/* ADC*2 | DAC*6 */	
+#define STAC9460_2_I2C_ADDR	0x56	/* ADC|DAC *2 */	
+
+
+extern struct snd_ice1712_card_info snd_vt1724_wtm_cards[];
+
+#endif /* __SOUND_WTM_H */
+
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 30aaa60..a289abf 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -71,6 +71,7 @@
 static int buggy_semaphore;
 static int buggy_irq = -1; /* auto-check */
 static int xbox;
+static int spdif_aclink = -1;
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
@@ -86,6 +87,8 @@
 MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
 module_param(xbox, bool, 0444);
 MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
+module_param(spdif_aclink, int, 0444);
+MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
 
 /* just for backward compatibility */
 static int enable;
@@ -368,12 +371,8 @@
 
 	int irq;
 
-	unsigned int mmio;
-	unsigned long addr;
-	void __iomem *remap_addr;
-	unsigned int bm_mmio;
-	unsigned long bmaddr;
-	void __iomem *remap_bmaddr;
+	void __iomem *addr;
+	void __iomem *bmaddr;
 
 	struct pci_dev *pci;
 	struct snd_card *card;
@@ -446,72 +445,48 @@
  *  Lowlevel I/O - busmaster
  */
 
-static u8 igetbyte(struct intel8x0 *chip, u32 offset)
+static inline u8 igetbyte(struct intel8x0 *chip, u32 offset)
 {
-	if (chip->bm_mmio)
-		return readb(chip->remap_bmaddr + offset);
-	else
-		return inb(chip->bmaddr + offset);
+	return ioread8(chip->bmaddr + offset);
 }
 
-static u16 igetword(struct intel8x0 *chip, u32 offset)
+static inline u16 igetword(struct intel8x0 *chip, u32 offset)
 {
-	if (chip->bm_mmio)
-		return readw(chip->remap_bmaddr + offset);
-	else
-		return inw(chip->bmaddr + offset);
+	return ioread16(chip->bmaddr + offset);
 }
 
-static u32 igetdword(struct intel8x0 *chip, u32 offset)
+static inline u32 igetdword(struct intel8x0 *chip, u32 offset)
 {
-	if (chip->bm_mmio)
-		return readl(chip->remap_bmaddr + offset);
-	else
-		return inl(chip->bmaddr + offset);
+	return ioread32(chip->bmaddr + offset);
 }
 
-static void iputbyte(struct intel8x0 *chip, u32 offset, u8 val)
+static inline void iputbyte(struct intel8x0 *chip, u32 offset, u8 val)
 {
-	if (chip->bm_mmio)
-		writeb(val, chip->remap_bmaddr + offset);
-	else
-		outb(val, chip->bmaddr + offset);
+	iowrite8(val, chip->bmaddr + offset);
 }
 
-static void iputword(struct intel8x0 *chip, u32 offset, u16 val)
+static inline void iputword(struct intel8x0 *chip, u32 offset, u16 val)
 {
-	if (chip->bm_mmio)
-		writew(val, chip->remap_bmaddr + offset);
-	else
-		outw(val, chip->bmaddr + offset);
+	iowrite16(val, chip->bmaddr + offset);
 }
 
-static void iputdword(struct intel8x0 *chip, u32 offset, u32 val)
+static inline void iputdword(struct intel8x0 *chip, u32 offset, u32 val)
 {
-	if (chip->bm_mmio)
-		writel(val, chip->remap_bmaddr + offset);
-	else
-		outl(val, chip->bmaddr + offset);
+	iowrite32(val, chip->bmaddr + offset);
 }
 
 /*
  *  Lowlevel I/O - AC'97 registers
  */
 
-static u16 iagetword(struct intel8x0 *chip, u32 offset)
+static inline u16 iagetword(struct intel8x0 *chip, u32 offset)
 {
-	if (chip->mmio)
-		return readw(chip->remap_addr + offset);
-	else
-		return inw(chip->addr + offset);
+	return ioread16(chip->addr + offset);
 }
 
-static void iaputword(struct intel8x0 *chip, u32 offset, u16 val)
+static inline void iaputword(struct intel8x0 *chip, u32 offset, u16 val)
 {
-	if (chip->mmio)
-		writew(val, chip->remap_addr + offset);
-	else
-		outw(val, chip->addr + offset);
+	iowrite16(val, chip->addr + offset);
 }
 
 /*
@@ -1606,10 +1581,14 @@
 	case DEVICE_INTEL_ICH4:
 		tbl = intel_pcms;
 		tblsize = ARRAY_SIZE(intel_pcms);
+		if (spdif_aclink)
+			tblsize--;
 		break;
 	case DEVICE_NFORCE:
 		tbl = nforce_pcms;
 		tblsize = ARRAY_SIZE(nforce_pcms);
+		if (spdif_aclink)
+			tblsize--;
 		break;
 	case DEVICE_ALI:
 		tbl = ali_pcms;
@@ -2068,24 +2047,26 @@
 	};
 
 	chip->spdif_idx = -1; /* use PCMOUT (or disabled) */
-	switch (chip->device_type) {
-	case DEVICE_NFORCE:
-		chip->spdif_idx = NVD_SPBAR;
-		break;
-	case DEVICE_ALI:
-		chip->spdif_idx = ALID_AC97SPDIFOUT;
-		break;
-	case DEVICE_INTEL_ICH4:
-		chip->spdif_idx = ICHD_SPBAR;
-		break;
-	};
+	if (!spdif_aclink) {
+		switch (chip->device_type) {
+		case DEVICE_NFORCE:
+			chip->spdif_idx = NVD_SPBAR;
+			break;
+		case DEVICE_ALI:
+			chip->spdif_idx = ALID_AC97SPDIFOUT;
+			break;
+		case DEVICE_INTEL_ICH4:
+			chip->spdif_idx = ICHD_SPBAR;
+			break;
+		};
+	}
 
 	chip->in_ac97_init = 1;
 	
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
 	ac97.private_free = snd_intel8x0_mixer_free_ac97;
-	ac97.scaps = AC97_SCAP_SKIP_MODEM;
+	ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;
 	if (chip->xbox)
 		ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR;
 	if (chip->device_type != DEVICE_ALI) {
@@ -2201,11 +2182,11 @@
 		if ((igetdword(chip, ICHREG(GLOB_STA)) & ICH_SAMPLE_CAP) == ICH_SAMPLE_16_20)
 			chip->smp20bit = 1;
 	}
-	if (chip->device_type == DEVICE_NFORCE) {
+	if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) {
 		/* 48kHz only */
 		chip->ichd[chip->spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000;
 	}
-	if (chip->device_type == DEVICE_INTEL_ICH4) {
+	if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) {
 		/* use slot 10/11 for SPDIF */
 		u32 val;
 		val = igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK;
@@ -2333,7 +2314,7 @@
 		/* unmute the output on SIS7012 */
 		iputword(chip, 0x4c, igetword(chip, 0x4c) | 1);
 	}
-	if (chip->device_type == DEVICE_NFORCE) {
+	if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) {
 		/* enable SPDIF interrupt */
 		unsigned int val;
 		pci_read_config_dword(chip->pci, 0x4c, &val);
@@ -2426,7 +2407,7 @@
 	/* reset channels */
 	for (i = 0; i < chip->bdbars_count; i++)
 		iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);
-	if (chip->device_type == DEVICE_NFORCE) {
+	if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) {
 		/* stop the spdif interrupt */
 		unsigned int val;
 		pci_read_config_dword(chip->pci, 0x4c, &val);
@@ -2443,10 +2424,10 @@
 			fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 0);
 		snd_dma_free_pages(&chip->bdbars);
 	}
-	if (chip->remap_addr)
-		iounmap(chip->remap_addr);
-	if (chip->remap_bmaddr)
-		iounmap(chip->remap_bmaddr);
+	if (chip->addr)
+		pci_iounmap(chip->pci, chip->addr);
+	if (chip->bmaddr)
+		pci_iounmap(chip->pci, chip->bmaddr);
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 	kfree(chip);
@@ -2520,7 +2501,7 @@
 	snd_intel8x0_chip_init(chip, 0);
 
 	/* re-initialize mixer stuff */
-	if (chip->device_type == DEVICE_INTEL_ICH4) {
+	if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) {
 		/* enable separate SDINs for ICH4 */
 		iputbyte(chip, ICHREG(SDM), chip->sdm_saved);
 		/* use slot 10/11 for SPDIF */
@@ -2793,35 +2774,27 @@
 
 	if (device_type == DEVICE_ALI) {
 		/* ALI5455 has no ac97 region */
-		chip->bmaddr = pci_resource_start(pci, 0);
+		chip->bmaddr = pci_iomap(pci, 0, 0);
 		goto port_inited;
 	}
 
-	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) {	/* ICH4 and Nforce */
-		chip->mmio = 1;
-		chip->addr = pci_resource_start(pci, 2);
-		chip->remap_addr = ioremap_nocache(chip->addr,
-						   pci_resource_len(pci, 2));
-		if (chip->remap_addr == NULL) {
-			snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
-			snd_intel8x0_free(chip);
-			return -EIO;
-		}
-	} else {
-		chip->addr = pci_resource_start(pci, 0);
+	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
+		chip->addr = pci_iomap(pci, 2, 0);
+	else
+		chip->addr = pci_iomap(pci, 0, 0);
+	if (!chip->addr) {
+		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
+		snd_intel8x0_free(chip);
+		return -EIO;
 	}
-	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) {	/* ICH4 */
-		chip->bm_mmio = 1;
-		chip->bmaddr = pci_resource_start(pci, 3);
-		chip->remap_bmaddr = ioremap_nocache(chip->bmaddr,
-						     pci_resource_len(pci, 3));
-		if (chip->remap_bmaddr == NULL) {
-			snd_printk(KERN_ERR "Controller space ioremap problem\n");
-			snd_intel8x0_free(chip);
-			return -EIO;
-		}
-	} else {
-		chip->bmaddr = pci_resource_start(pci, 1);
+	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
+		chip->bmaddr = pci_iomap(pci, 3, 0);
+	else
+		chip->bmaddr = pci_iomap(pci, 1, 0);
+	if (!chip->bmaddr) {
+		snd_printk(KERN_ERR "Controller space ioremap problem\n");
+		snd_intel8x0_free(chip);
+		return -EIO;
 	}
 
  port_inited:
@@ -2964,6 +2937,29 @@
 	{ 0, NULL },
 };
 
+static struct snd_pci_quirk spdif_aclink_defaults[] __devinitdata = {
+	SND_PCI_QUIRK(0x147b, 0x1c1a, "ASUS KN8", 1),
+	{ } /* end */
+};
+
+/* look up white/black list for SPDIF over ac-link */
+static int __devinit check_default_spdif_aclink(struct pci_dev *pci)
+{
+	const struct snd_pci_quirk *w;
+
+	w = snd_pci_quirk_lookup(pci, spdif_aclink_defaults);
+	if (w) {
+		if (w->value)
+			snd_printdd(KERN_INFO "intel8x0: Using SPDIF over "
+				    "AC-Link for %s\n", w->name);
+		else
+			snd_printdd(KERN_INFO "intel8x0: Using integrated "
+				    "SPDIF DMA for %s\n", w->name);
+		return w->value;
+	}
+	return 0;
+}
+
 static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
 					const struct pci_device_id *pci_id)
 {
@@ -2976,16 +2972,18 @@
 	if (card == NULL)
 		return -ENOMEM;
 
-	switch (pci_id->driver_data) {
-	case DEVICE_NFORCE:
-		strcpy(card->driver, "NFORCE");
-		break;
-	case DEVICE_INTEL_ICH4:
-		strcpy(card->driver, "ICH4");
-		break;
-	default:
-		strcpy(card->driver, "ICH");
-		break;
+	if (spdif_aclink < 0)
+		spdif_aclink = check_default_spdif_aclink(pci);
+
+	strcpy(card->driver, "ICH");
+	if (!spdif_aclink) {
+		switch (pci_id->driver_data) {
+		case DEVICE_NFORCE:
+			strcpy(card->driver, "NFORCE");
+			break;
+		case DEVICE_INTEL_ICH4:
+			strcpy(card->driver, "ICH4");
+		}
 	}
 
 	strcpy(card->shortname, "Intel ICH");
@@ -3025,8 +3023,8 @@
 	snd_intel8x0_proc_init(chip);
 
 	snprintf(card->longname, sizeof(card->longname),
-		 "%s with %s at %#lx, irq %i", card->shortname,
-		 snd_ac97_get_short_name(chip->ac97[0]), chip->addr, chip->irq);
+		 "%s with %s at irq %i", card->shortname,
+		 snd_ac97_get_short_name(chip->ac97[0]), chip->irq);
 
 	if (! ac97_clock)
 		intel8x0_measure_ac97_clock(chip);
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 09dcf92..c155e1f 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -196,12 +196,8 @@
 
 	int irq;
 
-	unsigned int mmio;
-	unsigned long addr;
-	void __iomem *remap_addr;
-	unsigned int bm_mmio;
-	unsigned long bmaddr;
-	void __iomem *remap_bmaddr;
+	void __iomem *addr;
+	void __iomem *bmaddr;
 
 	struct pci_dev *pci;
 	struct snd_card *card;
@@ -253,72 +249,48 @@
  *  Lowlevel I/O - busmaster
  */
 
-static u8 igetbyte(struct intel8x0m *chip, u32 offset)
+static inline u8 igetbyte(struct intel8x0m *chip, u32 offset)
 {
-	if (chip->bm_mmio)
-		return readb(chip->remap_bmaddr + offset);
-	else
-		return inb(chip->bmaddr + offset);
+	return ioread8(chip->bmaddr + offset);
 }
 
-static u16 igetword(struct intel8x0m *chip, u32 offset)
+static inline u16 igetword(struct intel8x0m *chip, u32 offset)
 {
-	if (chip->bm_mmio)
-		return readw(chip->remap_bmaddr + offset);
-	else
-		return inw(chip->bmaddr + offset);
+	return ioread16(chip->bmaddr + offset);
 }
 
-static u32 igetdword(struct intel8x0m *chip, u32 offset)
+static inline u32 igetdword(struct intel8x0m *chip, u32 offset)
 {
-	if (chip->bm_mmio)
-		return readl(chip->remap_bmaddr + offset);
-	else
-		return inl(chip->bmaddr + offset);
+	return ioread32(chip->bmaddr + offset);
 }
 
-static void iputbyte(struct intel8x0m *chip, u32 offset, u8 val)
+static inline void iputbyte(struct intel8x0m *chip, u32 offset, u8 val)
 {
-	if (chip->bm_mmio)
-		writeb(val, chip->remap_bmaddr + offset);
-	else
-		outb(val, chip->bmaddr + offset);
+	iowrite8(val, chip->bmaddr + offset);
 }
 
-static void iputword(struct intel8x0m *chip, u32 offset, u16 val)
+static inline void iputword(struct intel8x0m *chip, u32 offset, u16 val)
 {
-	if (chip->bm_mmio)
-		writew(val, chip->remap_bmaddr + offset);
-	else
-		outw(val, chip->bmaddr + offset);
+	iowrite16(val, chip->bmaddr + offset);
 }
 
-static void iputdword(struct intel8x0m *chip, u32 offset, u32 val)
+static inline void iputdword(struct intel8x0m *chip, u32 offset, u32 val)
 {
-	if (chip->bm_mmio)
-		writel(val, chip->remap_bmaddr + offset);
-	else
-		outl(val, chip->bmaddr + offset);
+	iowrite32(val, chip->bmaddr + offset);
 }
 
 /*
  *  Lowlevel I/O - AC'97 registers
  */
 
-static u16 iagetword(struct intel8x0m *chip, u32 offset)
+static inline u16 iagetword(struct intel8x0m *chip, u32 offset)
 {
-	if (chip->mmio)
-		return readw(chip->remap_addr + offset);
-	else
-		return inw(chip->addr + offset);
+	return ioread16(chip->addr + offset);
 }
 
-static void iaputword(struct intel8x0m *chip, u32 offset, u16 val)
+static inline void iaputword(struct intel8x0m *chip, u32 offset, u16 val)
 {
-	if (chip->mmio)
-		writew(val, chip->remap_addr + offset);
-	else
-		outw(val, chip->addr + offset);
+	iowrite16(val, chip->addr + offset);
 }
 
 /*
@@ -858,7 +830,7 @@
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
 	ac97.private_free = snd_intel8x0_mixer_free_ac97;
-	ac97.scaps = AC97_SCAP_SKIP_AUDIO;
+	ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
 
 	glob_sta = igetdword(chip, ICHREG(GLOB_STA));
 
@@ -1019,10 +991,10 @@
       __hw_end:
 	if (chip->bdbars.area)
 		snd_dma_free_pages(&chip->bdbars);
-	if (chip->remap_addr)
-		iounmap(chip->remap_addr);
-	if (chip->remap_bmaddr)
-		iounmap(chip->remap_bmaddr);
+	if (chip->addr)
+		pci_iounmap(chip->pci, chip->addr);
+	if (chip->bmaddr)
+		pci_iounmap(chip->pci, chip->bmaddr);
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
 	pci_release_regions(chip->pci);
@@ -1173,35 +1145,27 @@
 
 	if (device_type == DEVICE_ALI) {
 		/* ALI5455 has no ac97 region */
-		chip->bmaddr = pci_resource_start(pci, 0);
+		chip->bmaddr = pci_iomap(pci, 0, 0);
 		goto port_inited;
 	}
 
-	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) {	/* ICH4 and Nforce */
-		chip->mmio = 1;
-		chip->addr = pci_resource_start(pci, 2);
-		chip->remap_addr = ioremap_nocache(chip->addr,
-						   pci_resource_len(pci, 2));
-		if (chip->remap_addr == NULL) {
-			snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
-			snd_intel8x0_free(chip);
-			return -EIO;
-		}
-	} else {
-		chip->addr = pci_resource_start(pci, 0);
+	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
+		chip->addr = pci_iomap(pci, 2, 0);
+	else
+		chip->addr = pci_iomap(pci, 0, 0);
+	if (!chip->addr) {
+		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
+		snd_intel8x0_free(chip);
+		return -EIO;
 	}
-	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) {	/* ICH4 */
-		chip->bm_mmio = 1;
-		chip->bmaddr = pci_resource_start(pci, 3);
-		chip->remap_bmaddr = ioremap_nocache(chip->bmaddr,
-						     pci_resource_len(pci, 3));
-		if (chip->remap_bmaddr == NULL) {
-			snd_printk(KERN_ERR "Controller space ioremap problem\n");
-			snd_intel8x0_free(chip);
-			return -EIO;
-		}
-	} else {
-		chip->bmaddr = pci_resource_start(pci, 1);
+	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
+		chip->bmaddr = pci_iomap(pci, 3, 0);
+	else
+		chip->bmaddr = pci_iomap(pci, 1, 0);
+	if (!chip->bmaddr) {
+		snd_printk(KERN_ERR "Controller space ioremap problem\n");
+		snd_intel8x0_free(chip);
+		return -EIO;
 	}
 
  port_inited:
@@ -1339,8 +1303,8 @@
 	
 	snd_intel8x0m_proc_init(chip);
 
-	sprintf(card->longname, "%s at 0x%lx, irq %i",
-		card->shortname, chip->addr, chip->irq);
+	sprintf(card->longname, "%s at irq %i",
+		card->shortname, chip->irq);
 
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 345eefe..21d0899a 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -28,6 +28,7 @@
 #include <linux/wait.h>
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
+#include <linux/firmware.h>
 
 #include <sound/core.h>
 #include <sound/info.h>
@@ -263,7 +264,15 @@
 #define COMMAND_ACK_DELAY   13         // number of RTC ticks to wait for an acknowledgement
                                        //    from the card after sending a command.
 
+#define FIRMWARE_IN_THE_KERNEL
+
+#ifdef FIRMWARE_IN_THE_KERNEL
 #include "korg1212-firmware.h"
+static const struct firmware static_dsp_code = {
+	.data = (u8 *)dspCode,
+	.size = sizeof dspCode
+};
+#endif
 
 enum ClockSourceIndex {
    K1212_CLKIDX_AdatAt44_1K = 0,    // selects source as ADAT at 44.1 kHz
@@ -345,8 +354,6 @@
         struct snd_dma_buffer dma_rec;
 	struct snd_dma_buffer dma_shared;
 
-        u32 dspCodeSize;
-
 	u32 DataBufsSize;
 
         struct KorgAudioBuffer  * playDataBufsPtr;
@@ -1223,8 +1230,6 @@
 
         snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_IN_PROCESS);
 
-        memcpy(korg1212->dma_dsp.area, dspCode, korg1212->dspCodeSize);
-
         rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_StartDSPDownload,
                                      UpperWordSwap(korg1212->dma_dsp.addr),
                                      0, 0, 0);
@@ -2156,6 +2161,7 @@
         unsigned int i;
 	unsigned ioport_size, iomem_size, iomem2_size;
         struct snd_korg1212 * korg1212;
+	const struct firmware *dsp_code;
 
         static struct snd_device_ops ops = {
                 .dev_free = snd_korg1212_dev_free,
@@ -2329,8 +2335,6 @@
 
 #endif // K1212_LARGEALLOC
 
-        korg1212->dspCodeSize = sizeof (dspCode);
-
         korg1212->VolumeTablePhy = korg1212->sharedBufferPhy +
 		offsetof(struct KorgSharedBuffer, volumeData);
         korg1212->RoutingTablePhy = korg1212->sharedBufferPhy +
@@ -2338,17 +2342,40 @@
         korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy +
 		offsetof(struct KorgSharedBuffer, AdatTimeCode);
 
+	err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev);
+	if (err < 0) {
+		release_firmware(dsp_code);
+#ifdef FIRMWARE_IN_THE_KERNEL
+		dsp_code = &static_dsp_code;
+#else
+		snd_printk(KERN_ERR "firmware not available\n");
+		snd_korg1212_free(korg1212);
+		return err;
+#endif
+	}
+
 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-				korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) {
-		snd_printk(KERN_ERR "korg1212: can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize);
+				dsp_code->size, &korg1212->dma_dsp) < 0) {
+		snd_printk(KERN_ERR "korg1212: cannot allocate dsp code memory (%zd bytes)\n", dsp_code->size);
                 snd_korg1212_free(korg1212);
+#ifdef FIRMWARE_IN_THE_KERNEL
+		if (dsp_code != &static_dsp_code)
+#endif
+			release_firmware(dsp_code);
                 return -ENOMEM;
         }
 
         K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n",
-		   korg1212->dma_dsp.area, korg1212->dma_dsp.addr, korg1212->dspCodeSize,
+		   korg1212->dma_dsp.area, korg1212->dma_dsp.addr, dsp_code->size,
 		   stateName[korg1212->cardState]);
 
+	memcpy(korg1212->dma_dsp.area, dsp_code->data, dsp_code->size);
+
+#ifdef FIRMWARE_IN_THE_KERNEL
+	if (dsp_code != &static_dsp_code)
+#endif
+		release_firmware(dsp_code);
+
 	rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_RebootCard, 0, 0, 0, 0);
 
 	if (rc)
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 6efe6d5..4526904 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -41,6 +41,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/moduleparam.h>
+#include <linux/firmware.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -48,6 +49,7 @@
 #include <sound/mpu401.h>
 #include <sound/ac97_codec.h>
 #include <sound/initval.h>
+#include <asm/byteorder.h>
 
 MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ESS Maestro3 PCI");
@@ -768,21 +770,6 @@
 /*
  */
 
-/* quirk lists */
-struct m3_quirk {
-	const char *name;	/* device name */
-	u16 vendor, device;	/* subsystem ids */
-	int amp_gpio;		/* gpio pin #  for external amp, -1 = default */
-	int irda_workaround;	/* non-zero if avoid to touch 0x10 on GPIO_DIRECTION
-				   (e.g. for IrDA on Dell Inspirons) */
-};
-
-struct m3_hv_quirk {
-	u16 vendor, device, subsystem_vendor, subsystem_device;
-	u32 config;		/* ALLEGRO_CONFIG hardware volume bits */
-	int is_omnibook;	/* Do HP OmniBook GPIO magic? */
-};
-
 struct m3_list {
 	int curlen;
 	int mem_addr;
@@ -830,8 +817,6 @@
 	struct snd_pcm *pcm;
 
 	struct pci_dev *pci;
-	const struct m3_quirk *quirk;
-	const struct m3_hv_quirk *hv_quirk;
 
 	int dacs_active;
 	int timer_users;
@@ -845,7 +830,11 @@
 	u8 reset_state;
 
 	int external_amp;
-	int amp_gpio;
+	int amp_gpio;	/* gpio pin #  for external amp, -1 = default */
+	unsigned int hv_config;		/* hardware-volume config bits */
+	unsigned irda_workaround :1;	/* avoid to touch 0x10 on GPIO_DIRECTION
+					   (e.g. for IrDA on Dell Inspirons) */
+	unsigned is_omnibook :1;	/* Do HP OmniBook GPIO magic? */
 
 	/* midi */
 	struct snd_rawmidi *rmidi;
@@ -864,6 +853,9 @@
 #ifdef CONFIG_PM
 	u16 *suspend_mem;
 #endif
+
+	const struct firmware *assp_kernel_image;
+	const struct firmware *assp_minisrc_image;
 };
 
 /*
@@ -891,127 +883,104 @@
 
 MODULE_DEVICE_TABLE(pci, snd_m3_ids);
 
-static const struct m3_quirk m3_quirk_list[] = {
-	/* panasonic CF-28 "toughbook" */
-	{
-		.name = "Panasonic CF-28",
-		.vendor = 0x10f7,
-		.device = 0x833e,
-		.amp_gpio = 0x0d,
-	},
-	/* panasonic CF-72 "toughbook" */
-	{
-		.name = "Panasonic CF-72",
-		.vendor = 0x10f7,
-		.device = 0x833d,
-		.amp_gpio = 0x0d,
-	},
-	/* Dell Inspiron 4000 */
-	{
-		.name = "Dell Inspiron 4000",
-		.vendor = 0x1028,
-		.device = 0x00b0,
-		.amp_gpio = -1,
-		.irda_workaround = 1,
-	},
-	/* Dell Inspiron 8000 */
-	{
-		.name = "Dell Inspiron 8000",
-		.vendor = 0x1028,
-		.device = 0x00a4,
-		.amp_gpio = -1,
-		.irda_workaround = 1,
-	},
-	/* Dell Inspiron 8100 */
-	{
-		.name = "Dell Inspiron 8100",
-		.vendor = 0x1028,
-		.device = 0x00e6,
-		.amp_gpio = -1,
-		.irda_workaround = 1,
-	},
-	/* NEC LM800J/7 */
-	{
-		.name = "NEC LM800J/7",
-		.vendor = 0x1033,
-		.device = 0x80f1,
-		.amp_gpio = 0x03,
-	},
-	/* LEGEND ZhaoYang 3100CF */
-	{
-		.name = "LEGEND ZhaoYang 3100CF",
-		.vendor = 0x1509,
-		.device = 0x1740,
-		.amp_gpio = 0x03,
-	},
-	/* END */
-	{ NULL }
+static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = {
+	SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d),
+	SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d),
+	SND_PCI_QUIRK(0x1033, 0x80f1, "NEC LM800J/7", 0x03),
+	SND_PCI_QUIRK(0x1509, 0x1740, "LEGEND ZhaoYang 3100CF", 0x03),
+	{ } /* END */
 };
 
-/* These values came from the Windows driver. */
-static const struct m3_hv_quirk m3_hv_quirk_list[] = {
+static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = {
+	SND_PCI_QUIRK(0x1028, 0x00b0, "Dell Inspiron 4000", 1),
+	SND_PCI_QUIRK(0x1028, 0x00a4, "Dell Inspiron 8000", 1),
+	SND_PCI_QUIRK(0x1028, 0x00e6, "Dell Inspiron 8100", 1),
+	{ } /* END */
+};
+
+/* hardware volume quirks */
+static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = {
 	/* 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 },
-	{ 0x125D, 0x1988, 0x0E11, 0xB112, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x0E11, 0xB114, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x103C, 0x0012, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x103C, 0x0018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x103C, 0x001C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x103C, 0x001D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x103C, 0x001E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x107B, 0x3350, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x10F7, 0x8338, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x10F7, 0x833C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x10F7, 0x833D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x10F7, 0x833E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x10F7, 0x833F, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x13BD, 0x1018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x13BD, 0x1019, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x13BD, 0x101A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x14FF, 0x0F03, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x14FF, 0x0F04, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x14FF, 0x0F05, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x156D, 0xB400, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x156D, 0xB795, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x156D, 0xB797, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x156D, 0xC700, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
-	{ 0x125D, 0x1988, 0x1033, 0x80F1, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x103C, 0x001A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, /* HP OmniBook 6100 */
-	{ 0x125D, 0x1988, 0x107B, 0x340A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x107B, 0x3450, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x109F, 0x3134, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x109F, 0x3161, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x144D, 0x3280, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x144D, 0x3281, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x144D, 0xC002, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x144D, 0xC003, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x1509, 0x1740, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x1610, 0x0010, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x1988, 0x1042, 0x1042, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1988, 0x107B, 0x9500, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1988, 0x14FF, 0x0F06, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1988, 0x1558, 0x8586, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1988, 0x161F, 0x2011, HV_CTRL_ENABLE, 0 },
+	SND_PCI_QUIRK(0x0E11, 0x002E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x0E11, 0x0094, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x0E11, 0xB112, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x0E11, 0xB114, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x103C, 0x0012, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x103C, 0x0018, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x103C, 0x001C, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x103C, 0x001D, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x103C, 0x001E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x107B, 0x3350, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x10F7, 0x8338, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x10F7, 0x833C, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x10F7, 0x833D, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x10F7, 0x833E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x10F7, 0x833F, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x13BD, 0x1018, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x13BD, 0x1019, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x13BD, 0x101A, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x14FF, 0x0F03, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x14FF, 0x0F04, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x14FF, 0x0F05, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x156D, 0xB400, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x156D, 0xB795, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x156D, 0xB797, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x156D, 0xC700, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+	SND_PCI_QUIRK(0x1033, 0x80F1, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x103C, 0x001A, NULL, /* HP OmniBook 6100 */
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x107B, 0x340A, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x107B, 0x3450, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x109F, 0x3134, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x109F, 0x3161, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x144D, 0x3280, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x144D, 0x3281, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x144D, 0xC002, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x144D, 0xC003, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x1509, 0x1740, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x1610, 0x0010, NULL,
+		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x1042, 0x1042, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x107B, 0x9500, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x14FF, 0x0F06, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x1558, 0x8586, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x161F, 0x2011, NULL, HV_CTRL_ENABLE),
 	/* Maestro3 chips */
-	{ 0x125D, 0x1998, 0x103C, 0x000E, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1998, 0x103C, 0x0010, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 6000 */
-	{ 0x125D, 0x1998, 0x103C, 0x0011, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 500 */
-	{ 0x125D, 0x1998, 0x103C, 0x001B, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1998, 0x104D, 0x80A6, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1998, 0x104D, 0x80AA, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1998, 0x107B, 0x5300, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1998, 0x110A, 0x1998, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1998, 0x13BD, 0x1015, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1998, 0x13BD, 0x101C, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1998, 0x13BD, 0x1802, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1998, 0x1599, 0x0715, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x1998, 0x5643, 0x5643, HV_CTRL_ENABLE, 0 },
-	{ 0x125D, 0x199A, 0x144D, 0x3260, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x199A, 0x144D, 0x3261, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x199A, 0x144D, 0xC000, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
-	{ 0x125D, 0x199A, 0x144D, 0xC001, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
-	{ 0 }
+	SND_PCI_QUIRK(0x103C, 0x000E, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x103C, 0x0010, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x103C, 0x0011, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x103C, 0x001B, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x104D, 0x80A6, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x104D, 0x80AA, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x107B, 0x5300, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x110A, 0x1998, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x13BD, 0x1015, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x13BD, 0x101C, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x13BD, 0x1802, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x1599, 0x0715, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x5643, 0x5643, NULL, HV_CTRL_ENABLE),
+	SND_PCI_QUIRK(0x144D, 0x3260, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x144D, 0x3261, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x144D, 0xC000, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),
+	SND_PCI_QUIRK(0x144D, 0xC001, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),
+	{ } /* END */
+};
+
+/* HP Omnibook quirks */
+static struct snd_pci_quirk m3_omnibook_quirk_list[] __devinitdata = {
+	SND_PCI_QUIRK_ID(0x103c, 0x0010), /* HP OmniBook 6000 */
+	SND_PCI_QUIRK_ID(0x103c, 0x0011), /* HP OmniBook 500 */
+	{ } /* END */
 };
 
 /*
@@ -2050,7 +2019,7 @@
 
 	for (i = 0; i < 5; i++) {
 		dir = inw(io + GPIO_DIRECTION);
-		if (! chip->quirk || ! chip->quirk->irda_workaround)
+		if (!chip->irda_workaround)
 			dir |= 0x10; /* assuming pci bus master? */
 
 		snd_m3_remote_codec_config(io, 0);
@@ -2132,6 +2101,10 @@
 }
 
 
+#define FIRMWARE_IN_THE_KERNEL
+
+#ifdef FIRMWARE_IN_THE_KERNEL
+
 /*
  * DSP Code images
  */
@@ -2260,6 +2233,30 @@
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
 };
 
+static const struct firmware assp_kernel = {
+	.data = (u8 *)assp_kernel_image,
+	.size = sizeof assp_kernel_image
+};
+static const struct firmware assp_minisrc = {
+	.data = (u8 *)assp_minisrc_image,
+	.size = sizeof assp_minisrc_image
+};
+
+#endif /* FIRMWARE_IN_THE_KERNEL */
+
+#ifdef __LITTLE_ENDIAN
+static inline void snd_m3_convert_from_le(const struct firmware *fw) { }
+#else
+static void snd_m3_convert_from_le(const struct firmware *fw)
+{
+	int i;
+	u16 *data = (u16 *)fw->data;
+
+	for (i = 0; i < fw->size / 2; ++i)
+		le16_to_cpus(&data[i]);
+}
+#endif
+
 
 /*
  * initialize ASSP
@@ -2274,6 +2271,7 @@
 static void snd_m3_assp_init(struct snd_m3 *chip)
 {
 	unsigned int i;
+	u16 *data;
 
 	/* zero kernel data */
 	for (i = 0; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++)
@@ -2291,10 +2289,10 @@
 			  KDATA_DMA_XFER0);
 
 	/* write kernel into code memory.. */
-	for (i = 0 ; i < ARRAY_SIZE(assp_kernel_image); i++) {
+	data = (u16 *)chip->assp_kernel_image->data;
+	for (i = 0 ; i * 2 < chip->assp_kernel_image->size; i++) {
 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 
-				  REV_B_CODE_MEMORY_BEGIN + i, 
-				  assp_kernel_image[i]);
+				  REV_B_CODE_MEMORY_BEGIN + i, data[i]);
 	}
 
 	/*
@@ -2303,10 +2301,10 @@
 	 * drop it there.  It seems that the minisrc doesn't
 	 * need vectors, so we won't bother with them..
 	 */
-	for (i = 0; i < ARRAY_SIZE(assp_minisrc_image); i++) {
+	data = (u16 *)chip->assp_minisrc_image->data;
+	for (i = 0; i * 2 < chip->assp_minisrc_image->size; i++) {
 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 
-				  0x400 + i, 
-				  assp_minisrc_image[i]);
+				  0x400 + i, data[i]);
 	}
 
 	/*
@@ -2444,7 +2442,7 @@
 	       DISABLE_LEGACY);
 	pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w);
 
-	if (chip->hv_quirk && chip->hv_quirk->is_omnibook) {
+	if (chip->is_omnibook) {
 		/*
 		 * Volume buttons on some HP OmniBook laptops don't work
 		 * correctly. This makes them work for the most part.
@@ -2461,8 +2459,7 @@
 	}
 	pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
 	n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD);
-	if (chip->hv_quirk)
-		n |= chip->hv_quirk->config;
+	n |= chip->hv_config;
 	/* For some reason we must always use reduced debounce. */
 	n |= REDUCED_DEBOUNCE;
 	n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
@@ -2510,7 +2507,7 @@
 
 	/* TODO: MPU401 not supported yet */
 	val = ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/;
-	if (chip->hv_quirk && (chip->hv_quirk->config & HV_CTRL_ENABLE))
+	if (chip->hv_config & HV_CTRL_ENABLE)
 		val |= HV_INT_ENABLE;
 	outw(val, io + HOST_INT_CTRL);
 	outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE,
@@ -2553,6 +2550,15 @@
 	if (chip->iobase)
 		pci_release_regions(chip->pci);
 
+#ifdef FIRMWARE_IN_THE_KERNEL
+	if (chip->assp_kernel_image != &assp_kernel)
+#endif
+		release_firmware(chip->assp_kernel_image);
+#ifdef FIRMWARE_IN_THE_KERNEL
+	if (chip->assp_minisrc_image != &assp_minisrc)
+#endif
+		release_firmware(chip->assp_minisrc_image);
+
 	pci_disable_device(chip->pci);
 	kfree(chip);
 	return 0;
@@ -2665,8 +2671,7 @@
 {
 	struct snd_m3 *chip;
 	int i, err;
-	const struct m3_quirk *quirk;
-	const struct m3_hv_quirk *hv_quirk;
+	const struct snd_pci_quirk *quirk;
 	static struct snd_device_ops ops = {
 		.dev_free =	snd_m3_dev_free,
 	};
@@ -2706,34 +2711,32 @@
 	chip->pci = pci;
 	chip->irq = -1;
 
-	for (quirk = m3_quirk_list; quirk->vendor; quirk++) {
-		if (pci->subsystem_vendor == quirk->vendor &&
-		    pci->subsystem_device == quirk->device) {
-			printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name);
-			chip->quirk = quirk;
-			break;
-		}
-	}
-
-	for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) {
-		if (pci->vendor == hv_quirk->vendor &&
-		    pci->device == hv_quirk->device &&
-		    pci->subsystem_vendor == hv_quirk->subsystem_vendor &&
-		    pci->subsystem_device == hv_quirk->subsystem_device) {
-			chip->hv_quirk = hv_quirk;
-			break;
-		}
-	}
-
 	chip->external_amp = enable_amp;
 	if (amp_gpio >= 0 && amp_gpio <= 0x0f)
 		chip->amp_gpio = amp_gpio;
-	else if (chip->quirk && chip->quirk->amp_gpio >= 0)
-		chip->amp_gpio = chip->quirk->amp_gpio;
-	else if (chip->allegro_flag)
-		chip->amp_gpio = GPO_EXT_AMP_ALLEGRO;
-	else /* presumably this is for all 'maestro3's.. */
-		chip->amp_gpio = GPO_EXT_AMP_M3;
+	else {
+		quirk = snd_pci_quirk_lookup(pci, m3_amp_quirk_list);
+		if (quirk) {
+			snd_printdd(KERN_INFO "maestro3: set amp-gpio "
+				    "for '%s'\n", quirk->name);
+			chip->amp_gpio = quirk->value;
+		} else if (chip->allegro_flag)
+			chip->amp_gpio = GPO_EXT_AMP_ALLEGRO;
+		else /* presumably this is for all 'maestro3's.. */
+			chip->amp_gpio = GPO_EXT_AMP_M3;
+	}
+
+	quirk = snd_pci_quirk_lookup(pci, m3_irda_quirk_list);
+	if (quirk) {
+		snd_printdd(KERN_INFO "maestro3: enabled irda workaround "
+			    "for '%s'\n", quirk->name);
+		chip->irda_workaround = 1;
+	}
+	quirk = snd_pci_quirk_lookup(pci, m3_hv_quirk_list);
+	if (quirk)
+		chip->hv_config = quirk->value;
+	if (snd_pci_quirk_lookup(pci, m3_omnibook_quirk_list))
+		chip->is_omnibook = 1;
 
 	chip->num_substreams = NR_DSPS;
 	chip->substreams = kcalloc(chip->num_substreams, sizeof(struct m3_dma),
@@ -2744,6 +2747,30 @@
 		return -ENOMEM;
 	}
 
+	err = request_firmware(&chip->assp_kernel_image,
+			       "ess/maestro3_assp_kernel.fw", &pci->dev);
+	if (err < 0) {
+#ifdef FIRMWARE_IN_THE_KERNEL
+		chip->assp_kernel_image = &assp_kernel;
+#else
+		snd_m3_free(chip);
+		return err;
+#endif
+	} else
+		snd_m3_convert_from_le(chip->assp_kernel_image);
+
+	err = request_firmware(&chip->assp_minisrc_image,
+			       "ess/maestro3_assp_minisrc.fw", &pci->dev);
+	if (err < 0) {
+#ifdef FIRMWARE_IN_THE_KERNEL
+		chip->assp_minisrc_image = &assp_minisrc;
+#else
+		snd_m3_free(chip);
+		return err;
+#endif
+	} else
+		snd_m3_convert_from_le(chip->assp_minisrc_image);
+
 	if ((err = pci_request_regions(pci, card->driver)) < 0) {
 		snd_m3_free(chip);
 		return err;
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c
index 13de0f7..d7d15c0 100644
--- a/sound/pci/mixart/mixart_mixer.c
+++ b/sound/pci/mixart/mixart_mixer.c
@@ -389,7 +389,7 @@
 	return changed;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0);
 
 static struct snd_kcontrol_new mixart_control_analog_level = {
 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -872,7 +872,7 @@
 	return changed;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0);
 
 static struct snd_kcontrol_new snd_mixart_pcm_vol =
 {
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 879e31a..03b3a47 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1628,23 +1628,15 @@
 }
 
 
-struct nm256_quirk {
-	unsigned short vendor;
-	unsigned short device;
-	int type;
-};
-
 enum { NM_BLACKLISTED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 };
 
-static struct nm256_quirk nm256_quirks[] __devinitdata = {
+static struct snd_pci_quirk nm256_quirks[] __devinitdata = {
 	/* HP omnibook 4150 has cs4232 codec internally */
-	{ .vendor = 0x103c, .device = 0x0007, .type = NM_BLACKLISTED },
-	/* Sony PCG-F305 */
-	{ .vendor = 0x104d, .device = 0x8041, .type = NM_RESET_WORKAROUND },
-	/* Dell Latitude LS */
-	{ .vendor = 0x1028, .device = 0x0080, .type = NM_RESET_WORKAROUND },
-	/* Dell Latitude CSx */
-	{ .vendor = 0x1028, .device = 0x0091, .type = NM_RESET_WORKAROUND_2 },
+	SND_PCI_QUIRK(0x103c, 0x0007, "HP omnibook 4150", NM_BLACKLISTED),
+	/* Reset workarounds to avoid lock-ups */
+	SND_PCI_QUIRK(0x104d, 0x8041, "Sony PCG-F305", NM_RESET_WORKAROUND),
+	SND_PCI_QUIRK(0x1028, 0x0080, "Dell Latitude LS", NM_RESET_WORKAROUND),
+	SND_PCI_QUIRK(0x1028, 0x0091, "Dell Latitude CSx", NM_RESET_WORKAROUND_2),
 	{ } /* terminator */
 };
 
@@ -1655,26 +1647,22 @@
 	struct snd_card *card;
 	struct nm256 *chip;
 	int err;
-	struct nm256_quirk *q;
-	u16 subsystem_vendor, subsystem_device;
+	const struct snd_pci_quirk *q;
 
-	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
-	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
-
-	for (q = nm256_quirks; q->vendor; q++) {
-		if (q->vendor == subsystem_vendor && q->device == subsystem_device) {
-			switch (q->type) {
-			case NM_BLACKLISTED:
-				printk(KERN_INFO "nm256: The device is blacklisted. "
-				       "Loading stopped\n");
-				return -ENODEV;
-			case NM_RESET_WORKAROUND_2:
-				reset_workaround_2 = 1;
-				/* Fall-through */
-			case NM_RESET_WORKAROUND:
-				reset_workaround = 1;
-				break;
-			}
+	q = snd_pci_quirk_lookup(pci, nm256_quirks);
+	if (q) {
+		snd_printdd(KERN_INFO "nm256: Enabled quirk for %s.\n", q->name);
+		switch (q->value) {
+		case NM_BLACKLISTED:
+			printk(KERN_INFO "nm256: The device is blacklisted. "
+			       "Loading stopped\n");
+			return -ENODEV;
+		case NM_RESET_WORKAROUND_2:
+			reset_workaround_2 = 1;
+			/* Fall-through */
+		case NM_RESET_WORKAROUND:
+			reset_workaround = 1;
+			break;
 		}
 	}
 
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c
index b133ad9..d9cc8d2 100644
--- a/sound/pci/pcxhr/pcxhr_mixer.c
+++ b/sound/pci/pcxhr/pcxhr_mixer.c
@@ -44,8 +44,8 @@
 #define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX  128	/*    0.0 dB */
 #define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104	/*  -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */
 
-static DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -12800, 100, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -12800, 100, 0);
 
 static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel)
 {
@@ -195,7 +195,7 @@
 #define PCXHR_DIGITAL_LEVEL_MAX		0x1ff	/* +18 dB */
 #define PCXHR_DIGITAL_ZERO_LEVEL	0x1b7	/*  0 dB */
 
-static DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0);
 
 #define MORE_THAN_ONE_STREAM_LEVEL	0x000001
 #define VALID_STREAM_PAN_LEVEL_MASK	0x800000
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 6383987..89b3c7ff 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -80,6 +80,7 @@
 /* Write registers. These are defined as byte-offsets from the iobase value.
  */
 #define HDSP_resetPointer               0
+#define HDSP_freqReg			0
 #define HDSP_outputBufferAddress	32
 #define HDSP_inputBufferAddress		36
 #define HDSP_controlRegister		64
@@ -469,6 +470,7 @@
 	struct pci_dev       *pci;
 	struct snd_kcontrol *spdif_ctl;
         unsigned short        mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
+	unsigned int          dds_value; /* last value written to freq register */
 };
 
 /* These tables map the ALSA channels 1..N to the channels that we
@@ -598,6 +600,7 @@
 		return (64 * out) + (32 + (in));
 	case 0x96:
 	case 0x97:
+	case 0x98:
 		return (32 * out) + (16 + (in));
 	default:
 		return (52 * out) + (26 + (in));
@@ -611,6 +614,7 @@
 		return (64 * out) + in;
 	case 0x96:
 	case 0x97:
+	case 0x98:
 		return (32 * out) + in;
 	default:
 		return (52 * out) + in;
@@ -938,6 +942,11 @@
 static void hdsp_reset_hw_pointer(struct hdsp *hdsp)
 {
 	hdsp_write (hdsp, HDSP_resetPointer, 0);
+	if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
+		/* HDSP_resetPointer = HDSP_freqReg, which is strange and
+		 * requires (?) to write again DDS value after a reset pointer
+		 * (at least, it works like this) */
+		hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value);
 }
 
 static void hdsp_start_audio(struct hdsp *s)
@@ -982,6 +991,30 @@
 	return 0;
 }
 
+static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
+{
+	u64 n;
+	u32 r;
+	
+	if (rate >= 112000)
+		rate /= 4;
+	else if (rate >= 56000)
+		rate /= 2;
+
+	/* RME says n = 104857600000000, but in the windows MADI driver, I see:
+//	return 104857600000000 / rate; // 100 MHz
+	return 110100480000000 / rate; // 105 MHz
+        */	   
+	n = 104857600000000ULL;  /*  =  2^20 * 10^8 */
+	div64_32(&n, rate, &r);
+	/* n should be less than 2^32 for being written to FREQ register */
+	snd_assert((n >> 32) == 0);
+	/* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS
+	   value to write it after a reset */
+	hdsp->dds_value = n;
+	hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value);
+}
+
 static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
 {
 	int reject_if_open = 0;
@@ -1090,6 +1123,10 @@
 	hdsp->control_register |= rate_bits;
 	hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
 
+	/* For HDSP9632 rev 152, need to set DDS value in FREQ register */
+	if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
+		hdsp_set_dds_value(hdsp, rate);
+
 	if (rate >= 128000) {
 		hdsp->channel_map = channel_map_H9632_qs;
 	} else if (rate > 48000) {
@@ -4943,6 +4980,7 @@
 	hdsp->irq = pci->irq;
 	hdsp->precise_ptr = 0;
 	hdsp->use_midi_tasklet = 1;
+	hdsp->dds_value = 0;
 
 	if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
 		return err;
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 0547f6f..e0215ac 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6,6 +6,8 @@
  *      code based on hdsp.c   Paul Davis
  *                             Marcus Andersson
  *                             Thomas Charbonnel
+ *      Modified 2006-06-01 for AES32 support by Remy Bruno
+ *                                               <remy.bruno@trinnov.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
@@ -77,7 +79,8 @@
 
 MODULE_AUTHOR
       ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, "
-       "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
+       "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
+       "Remy Bruno <remy.bruno@trinnov.com>");
 MODULE_DESCRIPTION("RME HDSPM");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
@@ -107,7 +110,12 @@
 /* --- Read registers. ---
    These are defined as byte-offsets from the iobase value */
 #define HDSPM_statusRegister    0
-#define HDSPM_statusRegister2  96
+/*#define HDSPM_statusRegister2  96 */
+/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
+ * offset 192, for AES32 *and* MADI
+ * => need to check that offset 192 is working on MADI */
+#define HDSPM_statusRegister2  192
+#define HDSPM_timecodeRegister 128
 
 #define HDSPM_midiDataIn0     360
 #define HDSPM_midiDataIn1     364
@@ -140,37 +148,50 @@
 #define HDSPM_Frequency0  (1<<6)  /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
 #define HDSPM_Frequency1  (1<<7)  /* 0=32kHz/64kHz */
 #define HDSPM_DoubleSpeed (1<<8)  /* 0=normal speed, 1=double speed */
-#define HDSPM_QuadSpeed   (1<<31) /* quad speed bit, not implemented now */
+#define HDSPM_QuadSpeed   (1<<31) /* quad speed bit */
 
+#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
 #define HDSPM_TX_64ch     (1<<10) /* Output 64channel MODE=1,
-				     56channelMODE=0 */
+				     56channelMODE=0 */ /* MADI ONLY*/
+#define HDSPM_Emphasis    (1<<10) /* Emphasis */ /* AES32 ONLY */
 
 #define HDSPM_AutoInp     (1<<11) /* Auto Input (takeover) == Safe Mode, 
-                                     0=off, 1=on  */
+                                     0=off, 1=on  */ /* MADI ONLY */
+#define HDSPM_Dolby       (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
 
-#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */
+#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ /* MADI ONLY*/
 #define HDSPM_InputSelect1 (1<<15) /* should be 0 */
 
 #define HDSPM_SyncRef0     (1<<16) /* 0=WOrd, 1=MADI */
-#define HDSPM_SyncRef1     (1<<17) /* should be 0 */
+#define HDSPM_SyncRef1     (1<<17) /* for AES32: SyncRefN codes the AES # */
+#define HDSPM_SyncRef2     (1<<13)
+#define HDSPM_SyncRef3     (1<<25)
 
+#define HDSPM_SMUX         (1<<18) /* Frame ??? */ /* MADI ONY */
 #define HDSPM_clr_tms      (1<<19) /* clear track marker, do not use 
                                       AES additional bits in
 				      lower 5 Audiodatabits ??? */
+#define HDSPM_taxi_reset   (1<<20) /* ??? */ /* MADI ONLY ? */
+#define HDSPM_WCK48        (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
 
 #define HDSPM_Midi0InterruptEnable (1<<22)
 #define HDSPM_Midi1InterruptEnable (1<<23)
 
 #define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
 
+#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
+#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
+#define HDSPM_QS_QuadWire   (1<<28) /* AES32 ONLY */
+
+#define HDSPM_wclk_sel (1<<30)
 
 /* --- bit helper defines */
 #define HDSPM_LatencyMask    (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
-#define HDSPM_FrequencyMask  (HDSPM_Frequency0|HDSPM_Frequency1)
+#define HDSPM_FrequencyMask  (HDSPM_Frequency0|HDSPM_Frequency1|HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
 #define HDSPM_InputMask      (HDSPM_InputSelect0|HDSPM_InputSelect1)
 #define HDSPM_InputOptical   0
 #define HDSPM_InputCoaxial   (HDSPM_InputSelect0)
-#define HDSPM_SyncRefMask    (HDSPM_SyncRef0|HDSPM_SyncRef1)
+#define HDSPM_SyncRefMask    (HDSPM_SyncRef0|HDSPM_SyncRef1|HDSPM_SyncRef2|HDSPM_SyncRef3)
 #define HDSPM_SyncRef_Word   0
 #define HDSPM_SyncRef_MADI   (HDSPM_SyncRef0)
 
@@ -183,6 +204,9 @@
 #define HDSPM_Frequency64KHz   (HDSPM_DoubleSpeed|HDSPM_Frequency0)
 #define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
 #define HDSPM_Frequency96KHz   (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
+#define HDSPM_Frequency128KHz   (HDSPM_QuadSpeed|HDSPM_Frequency0)
+#define HDSPM_Frequency176_4KHz   (HDSPM_QuadSpeed|HDSPM_Frequency1)
+#define HDSPM_Frequency192KHz   (HDSPM_QuadSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
 
 /* --- for internal discrimination */
 #define HDSPM_CLOCK_SOURCE_AUTOSYNC          0	/* Sample Clock Sources */
@@ -229,7 +253,8 @@
 #define HDSPM_BIGENDIAN_MODE  (1<<9)
 #define HDSPM_RD_MULTIPLE     (1<<10)
 
-/* --- Status Register bits --- */
+/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
+     that do not conflict with specific bits for AES32 seem to be valid also for the AES32 */
 #define HDSPM_audioIRQPending    (1<<0)	/* IRQ is high and pending */
 #define HDSPM_RX_64ch            (1<<1)	/* Input 64chan. MODE=1, 56chn. MODE=0 */
 #define HDSPM_AB_int             (1<<2)	/* InputChannel Opt=0, Coax=1 (like inp0) */
@@ -263,7 +288,7 @@
 #define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
 #define HDSPM_madiFreq192   (HDSPM_madiFreq3|HDSPM_madiFreq0)
 
-/* Status2 Register bits */
+/* Status2 Register bits */ /* MADI ONLY */
 
 #define HDSPM_version0 (1<<0)	/* not realy defined but I guess */
 #define HDSPM_version1 (1<<1)	/* in former cards it was ??? */
@@ -297,6 +322,56 @@
 #define HDSPM_SelSyncRef_MADI      (HDSPM_SelSyncRef0)
 #define HDSPM_SelSyncRef_NVALID    (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
 
+/*
+   For AES32, bits for status, status2 and timecode are different
+*/
+/* status */
+#define HDSPM_AES32_wcLock	0x0200000
+#define HDSPM_AES32_wcFreq_bit  22
+/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function 
+  HDSPM_bit2freq */
+#define HDSPM_AES32_syncref_bit  16
+/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
+
+#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
+#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
+#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
+#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
+#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
+#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
+#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
+#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
+#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
+#define HDSPM_AES32_AUTOSYNC_FROM_NONE -1
+
+/*  status2 */
+/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
+#define HDSPM_LockAES   0x80
+#define HDSPM_LockAES1  0x80
+#define HDSPM_LockAES2  0x40
+#define HDSPM_LockAES3  0x20
+#define HDSPM_LockAES4  0x10
+#define HDSPM_LockAES5  0x8
+#define HDSPM_LockAES6  0x4
+#define HDSPM_LockAES7  0x2
+#define HDSPM_LockAES8  0x1
+/*
+   Timecode
+   After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
+   AES i+1
+ bits 3210
+      0001  32kHz
+      0010  44.1kHz
+      0011  48kHz
+      0100  64kHz
+      0101  88.2kHz
+      0110  96kHz
+      0111  128kHz
+      1000  176.4kHz
+      1001  192kHz
+  NB: Timecode register doesn't seem to work on AES32 card revision 230
+*/
+
 /* Mixer Values */
 #define UNITY_GAIN          32768	/* = 65536/2 */
 #define MINUS_INFINITY_GAIN 0
@@ -314,10 +389,14 @@
    size is the same regardless of the number of channels, and
    also the latency to use. 
    for one direction !!!
+   => need to mupltiply by 2!!
 */
-#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
+#define HDSPM_DMA_AREA_BYTES (2 * HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
 #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
 
+/* revisions >= 230 indicate AES32 card */
+#define HDSPM_AESREVISION 230
+
 struct hdspm_midi {
 	struct hdspm *hdspm;
 	int id;
@@ -336,7 +415,9 @@
         struct snd_pcm_substream *playback_substream; /* and/or capture stream */
 
 	char *card_name;	     /* for procinfo */
-	unsigned short firmware_rev; /* dont know if relevant */
+	unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
+
+	unsigned char is_aes32;    /* indicates if card is AES32 */
 
 	int precise_ptr;	/* use precise pointers, to be tested */
 	int monitor_outs;	/* set up monitoring outs init flag */
@@ -453,6 +534,15 @@
 static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
 			     unsigned int reg, int channels);
 
+static inline int HDSPM_bit2freq(int n)
+{
+	static int bit2freq_tab[] = { 0, 32000, 44100, 48000, 64000, 88200,
+		96000, 128000, 176400, 192000 };
+	if (n < 1 || n > 9)
+		return 0;
+	return bit2freq_tab[n];
+}
+
 /* Write/read to/from HDSPM with Adresses in Bytes
    not words but only 32Bit writes are allowed */
 
@@ -544,86 +634,105 @@
 /* check for external sample rate */
 static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
 {
-	unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
-	unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
-	unsigned int rate_bits;
-	int rate = 0;
+	if (hdspm->is_aes32) {
+		unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+		unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
+		unsigned int timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
 
-	/* if wordclock has synced freq and wordclock is valid */
-	if ((status2 & HDSPM_wcLock) != 0 &&
-	    (status & HDSPM_SelSyncRef0) == 0) {
+		int syncref = hdspm_autosync_ref(hdspm);
 
-		rate_bits = status2 & HDSPM_wcFreqMask;
+		if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
+				status & HDSPM_AES32_wcLock)
+			return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
+		if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
+			syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
+			status2 & (HDSPM_LockAES >>
+			          (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
+			return HDSPM_bit2freq((timecode >>
+			  (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
+		return 0;
+	} else {
+		unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+		unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
+		unsigned int rate_bits;
+		int rate = 0;
 
-		switch (rate_bits) {
-		case HDSPM_wcFreq32:
-			rate = 32000;
-			break;
-		case HDSPM_wcFreq44_1:
-			rate = 44100;
-			break;
-		case HDSPM_wcFreq48:
-			rate = 48000;
-			break;
-		case HDSPM_wcFreq64:
-			rate = 64000;
-			break;
-		case HDSPM_wcFreq88_2:
-			rate = 88200;
-			break;
-		case HDSPM_wcFreq96:
-			rate = 96000;
-			break;
-			/* Quadspeed Bit missing ???? */
-		default:
-			rate = 0;
-			break;
+		/* if wordclock has synced freq and wordclock is valid */
+		if ((status2 & HDSPM_wcLock) != 0 &&
+				(status & HDSPM_SelSyncRef0) == 0) {
+
+			rate_bits = status2 & HDSPM_wcFreqMask;
+
+			switch (rate_bits) {
+			case HDSPM_wcFreq32:
+				rate = 32000;
+				break;
+			case HDSPM_wcFreq44_1:
+				rate = 44100;
+				break;
+			case HDSPM_wcFreq48:
+				rate = 48000;
+				break;
+			case HDSPM_wcFreq64:
+				rate = 64000;
+				break;
+			case HDSPM_wcFreq88_2:
+				rate = 88200;
+				break;
+			case HDSPM_wcFreq96:
+				rate = 96000;
+				break;
+				/* Quadspeed Bit missing ???? */
+			default:
+				rate = 0;
+				break;
+			}
 		}
-	}
 
-	/* if rate detected and Syncref is Word than have it, word has priority to MADI */
-	if (rate != 0
-	    && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
+		/* if rate detected and Syncref is Word than have it, word has priority to MADI */
+		if (rate != 0 &&
+	            (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
+			return rate;
+
+		/* maby a madi input (which is taken if sel sync is madi) */
+		if (status & HDSPM_madiLock) {
+			rate_bits = status & HDSPM_madiFreqMask;
+
+			switch (rate_bits) {
+			case HDSPM_madiFreq32:
+				rate = 32000;
+				break;
+			case HDSPM_madiFreq44_1:
+				rate = 44100;
+				break;
+			case HDSPM_madiFreq48:
+				rate = 48000;
+				break;
+			case HDSPM_madiFreq64:
+				rate = 64000;
+				break;
+			case HDSPM_madiFreq88_2:
+				rate = 88200;
+				break;
+			case HDSPM_madiFreq96:
+				rate = 96000;
+				break;
+			case HDSPM_madiFreq128:
+				rate = 128000;
+				break;
+			case HDSPM_madiFreq176_4:
+				rate = 176400;
+				break;
+			case HDSPM_madiFreq192:
+				rate = 192000;
+				break;
+			default:
+				rate = 0;
+				break;
+			}
+		}
 		return rate;
-
-	/* maby a madi input (which is taken if sel sync is madi) */
-	if (status & HDSPM_madiLock) {
-		rate_bits = status & HDSPM_madiFreqMask;
-
-		switch (rate_bits) {
-		case HDSPM_madiFreq32:
-			rate = 32000;
-			break;
-		case HDSPM_madiFreq44_1:
-			rate = 44100;
-			break;
-		case HDSPM_madiFreq48:
-			rate = 48000;
-			break;
-		case HDSPM_madiFreq64:
-			rate = 64000;
-			break;
-		case HDSPM_madiFreq88_2:
-			rate = 88200;
-			break;
-		case HDSPM_madiFreq96:
-			rate = 96000;
-			break;
-		case HDSPM_madiFreq128:
-			rate = 128000;
-			break;
-		case HDSPM_madiFreq176_4:
-			rate = 176400;
-			break;
-		case HDSPM_madiFreq192:
-			rate = 192000;
-			break;
-		default:
-			rate = 0;
-			break;
-		}
 	}
-	return rate;
 }
 
 /* Latency function */
@@ -676,7 +785,8 @@
 	int n = hdspm->period_bytes;
 	void *buf = hdspm->playback_buffer;
 
-	snd_assert(buf != NULL, return);
+	if (buf == NULL)
+		return;
 
 	for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
 		memset(buf, 0, n);
@@ -716,6 +826,7 @@
 	int current_rate;
 	int rate_bits;
 	int not_set = 0;
+	int is_single, is_double, is_quad;
 
 	/* ASSUMPTION: hdspm->lock is either set, or there is no need for
 	   it (e.g. during module initialization).
@@ -766,43 +877,56 @@
 	   changes in the read/write routines.  
 	 */
 
+	is_single = (current_rate <= 48000);
+	is_double = (current_rate > 48000 && current_rate <= 96000);
+	is_quad = (current_rate > 96000);
+
 	switch (rate) {
 	case 32000:
-		if (current_rate > 48000) {
+		if (!is_single)
 			reject_if_open = 1;
-		}
 		rate_bits = HDSPM_Frequency32KHz;
 		break;
 	case 44100:
-		if (current_rate > 48000) {
+		if (!is_single)
 			reject_if_open = 1;
-		}
 		rate_bits = HDSPM_Frequency44_1KHz;
 		break;
 	case 48000:
-		if (current_rate > 48000) {
+		if (!is_single)
 			reject_if_open = 1;
-		}
 		rate_bits = HDSPM_Frequency48KHz;
 		break;
 	case 64000:
-		if (current_rate <= 48000) {
+		if (!is_double)
 			reject_if_open = 1;
-		}
 		rate_bits = HDSPM_Frequency64KHz;
 		break;
 	case 88200:
-		if (current_rate <= 48000) {
+		if (!is_double)
 			reject_if_open = 1;
-		}
 		rate_bits = HDSPM_Frequency88_2KHz;
 		break;
 	case 96000:
-		if (current_rate <= 48000) {
+		if (!is_double)
 			reject_if_open = 1;
-		}
 		rate_bits = HDSPM_Frequency96KHz;
 		break;
+	case 128000:
+		if (!is_quad)
+			reject_if_open = 1;
+		rate_bits = HDSPM_Frequency128KHz;
+		break;
+	case 176400:
+		if (!is_quad)
+			reject_if_open = 1;
+		rate_bits = HDSPM_Frequency176_4KHz;
+		break;
+	case 192000:
+		if (!is_quad)
+			reject_if_open = 1;
+		rate_bits = HDSPM_Frequency192KHz;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -819,7 +943,7 @@
 	hdspm->control_register |= rate_bits;
 	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
 
-	if (rate > 64000)
+	if (rate > 96000 /* 64000*/)
 		hdspm->channel_map = channel_map_madi_qs;
 	else if (rate > 48000)
 		hdspm->channel_map = channel_map_madi_ds;
@@ -1455,11 +1579,27 @@
 	/* Notice that this looks at the requested sync source,
 	   not the one actually in use.
 	 */
-	switch (hdspm->control_register & HDSPM_SyncRefMask) {
-	case HDSPM_SyncRef_Word:
-		return HDSPM_SYNC_FROM_WORD;
-	case HDSPM_SyncRef_MADI:
-		return HDSPM_SYNC_FROM_MADI;
+	if (hdspm->is_aes32) {
+		switch (hdspm->control_register & HDSPM_SyncRefMask) {
+		/* number gives AES index, except for 0 which
+		   corresponds to WordClock */
+		case 0: return 0;
+		case HDSPM_SyncRef0: return 1;
+		case HDSPM_SyncRef1: return 2;
+		case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3;
+		case HDSPM_SyncRef2: return 4;
+		case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5;
+		case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6;
+		case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7;
+		case HDSPM_SyncRef3: return 8;
+		}
+	} else {
+		switch (hdspm->control_register & HDSPM_SyncRefMask) {
+		case HDSPM_SyncRef_Word:
+			return HDSPM_SYNC_FROM_WORD;
+		case HDSPM_SyncRef_MADI:
+			return HDSPM_SYNC_FROM_MADI;
+		}
 	}
 
 	return HDSPM_SYNC_FROM_WORD;
@@ -1469,15 +1609,49 @@
 {
 	hdspm->control_register &= ~HDSPM_SyncRefMask;
 
-	switch (pref) {
-	case HDSPM_SYNC_FROM_MADI:
-		hdspm->control_register |= HDSPM_SyncRef_MADI;
-		break;
-	case HDSPM_SYNC_FROM_WORD:
-		hdspm->control_register |= HDSPM_SyncRef_Word;
-		break;
-	default:
-		return -1;
+	if (hdspm->is_aes32) {
+		switch (pref) {
+		case 0:
+		       hdspm->control_register |= 0;
+		       break;
+		case 1:
+		       hdspm->control_register |= HDSPM_SyncRef0;
+		       break;
+		case 2:
+		       hdspm->control_register |= HDSPM_SyncRef1;
+		       break;
+		case 3:
+		       hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0;
+		       break;
+		case 4:
+		       hdspm->control_register |= HDSPM_SyncRef2;
+		       break;
+		case 5:
+		       hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0;
+		       break;
+		case 6:
+		       hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1;
+		       break;
+		case 7:
+		       hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
+		       break;
+		case 8:
+		       hdspm->control_register |= HDSPM_SyncRef3;
+		       break;
+		default:
+		       return -1;
+		}
+	} else {
+		switch (pref) {
+		case HDSPM_SYNC_FROM_MADI:
+			hdspm->control_register |= HDSPM_SyncRef_MADI;
+			break;
+		case HDSPM_SYNC_FROM_WORD:
+			hdspm->control_register |= HDSPM_SyncRef_Word;
+			break;
+		default:
+			return -1;
+		}
 	}
 	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
 	return 0;
@@ -1486,18 +1660,36 @@
 static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "Word", "MADI" };
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
+	if (hdspm->is_aes32) {
+		static char *texts[] = { "Word", "AES1", "AES2", "AES3",
+			"AES4", "AES5",	"AES6", "AES7", "AES8" };
 
-	uinfo->value.enumerated.items = 2;
+		uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+		uinfo->count = 1;
 
-	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]);
+		uinfo->value.enumerated.items = 9;
+
+		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]);
+	} else {
+		static char *texts[] = { "Word", "MADI" };
+
+		uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+		uinfo->count = 1;
+
+		uinfo->value.enumerated.items = 2;
+
+		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;
 }
 
@@ -1517,7 +1709,7 @@
 	int change, max;
 	unsigned int val;
 
-	max = 2;
+	max = hdspm->is_aes32 ? 9 : 2;
 
 	if (!snd_hdspm_use_is_exclusive(hdspm))
 		return -EBUSY;
@@ -1542,40 +1734,64 @@
 
 static int hdspm_autosync_ref(struct hdspm * hdspm)
 {
-	/* This looks at the autosync selected sync reference */
-	unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+	if (hdspm->is_aes32) {
+		unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
+		unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF;
+		if (syncref == 0)
+			return HDSPM_AES32_AUTOSYNC_FROM_WORD;
+		if (syncref <= 8)
+			return syncref;
+		return HDSPM_AES32_AUTOSYNC_FROM_NONE;
+	} else {
+		/* This looks at the autosync selected sync reference */
+		unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
 
-	switch (status2 & HDSPM_SelSyncRefMask) {
+		switch (status2 & HDSPM_SelSyncRefMask) {
+		case HDSPM_SelSyncRef_WORD:
+			return HDSPM_AUTOSYNC_FROM_WORD;
+		case HDSPM_SelSyncRef_MADI:
+			return HDSPM_AUTOSYNC_FROM_MADI;
+		case HDSPM_SelSyncRef_NVALID:
+			return HDSPM_AUTOSYNC_FROM_NONE;
+		default:
+			return 0;
+		}
 
-	case HDSPM_SelSyncRef_WORD:
-		return HDSPM_AUTOSYNC_FROM_WORD;
-
-	case HDSPM_SelSyncRef_MADI:
-		return HDSPM_AUTOSYNC_FROM_MADI;
-
-	case HDSPM_SelSyncRef_NVALID:
-		return HDSPM_AUTOSYNC_FROM_NONE;
-
-	default:
 		return 0;
 	}
-
-	return 0;
 }
 
 static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "WordClock", "MADI", "None" };
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-	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]);
+	if (hdspm->is_aes32) {
+		static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
+			"AES4",	"AES5", "AES6", "AES7", "AES8", "None"};
+
+		uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+		uinfo->count = 1;
+		uinfo->value.enumerated.items = 10;
+		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]);
+	}
+	else
+	{
+		static char *texts[] = { "WordClock", "MADI", "None" };
+
+		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;
 }
 
@@ -1841,6 +2057,195 @@
 	return change;
 }
 
+#define HDSPM_EMPHASIS(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_emphasis, \
+  .get = snd_hdspm_get_emphasis, \
+  .put = snd_hdspm_put_emphasis \
+}
+
+static int hdspm_emphasis(struct hdspm * hdspm)
+{
+	return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
+}
+
+static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
+{
+	if (emp)
+		hdspm->control_register |= HDSPM_Emphasis;
+	else
+		hdspm->control_register &= ~HDSPM_Emphasis;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_emphasis(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0] & 1;
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_emphasis(hdspm);
+	hdspm_set_emphasis(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+#define HDSPM_DOLBY(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_dolby, \
+  .get = snd_hdspm_get_dolby, \
+  .put = snd_hdspm_put_dolby \
+}
+
+static int hdspm_dolby(struct hdspm * hdspm)
+{
+	return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
+}
+
+static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
+{
+	if (dol)
+		hdspm->control_register |= HDSPM_Dolby;
+	else
+		hdspm->control_register &= ~HDSPM_Dolby;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_dolby(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0] & 1;
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_dolby(hdspm);
+	hdspm_set_dolby(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+#define HDSPM_PROFESSIONAL(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_professional, \
+  .get = snd_hdspm_get_professional, \
+  .put = snd_hdspm_put_professional \
+}
+
+static int hdspm_professional(struct hdspm * hdspm)
+{
+	return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
+}
+
+static int hdspm_set_professional(struct hdspm * hdspm, int dol)
+{
+	if (dol)
+		hdspm->control_register |= HDSPM_Professional;
+	else
+		hdspm->control_register &= ~HDSPM_Professional;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_professional(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0] & 1;
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_professional(hdspm);
+	hdspm_set_professional(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
 #define HDSPM_INPUT_SELECT(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -1912,6 +2317,163 @@
 	return change;
 }
 
+#define HDSPM_DS_WIRE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_ds_wire, \
+  .get = snd_hdspm_get_ds_wire, \
+  .put = snd_hdspm_put_ds_wire \
+}
+
+static int hdspm_ds_wire(struct hdspm * hdspm)
+{
+	return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
+}
+
+static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
+{
+	if (ds)
+		hdspm->control_register |= HDSPM_DS_DoubleWire;
+	else
+		hdspm->control_register &= ~HDSPM_DS_DoubleWire;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[] = { "Single", "Double" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+
+	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 snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0] & 1;
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_ds_wire(hdspm);
+	hdspm_set_ds_wire(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+#define HDSPM_QS_WIRE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_qs_wire, \
+  .get = snd_hdspm_get_qs_wire, \
+  .put = snd_hdspm_put_qs_wire \
+}
+
+static int hdspm_qs_wire(struct hdspm * hdspm)
+{
+	if (hdspm->control_register & HDSPM_QS_DoubleWire)
+		return 1;
+	if (hdspm->control_register & HDSPM_QS_QuadWire)
+		return 2;
+	return 0;
+}
+
+static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
+{
+	hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
+	switch (mode) {
+	case 0:
+		break;
+	case 1:
+		hdspm->control_register |= HDSPM_QS_DoubleWire;
+		break;
+	case 2:
+		hdspm->control_register |= HDSPM_QS_QuadWire;
+		break;
+	}
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[] = { "Single", "Double", "Quad" };
+
+	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 snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0];
+	if (val < 0)
+		val = 0;
+	if (val > 2)
+		val = 2;
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_qs_wire(hdspm);
+	hdspm_set_qs_wire(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
 /*           Simple Mixer
   deprecated since to much faders ???
   MIXER interface says output (source, destination, value)
@@ -2135,14 +2697,24 @@
 
 static int hdspm_wc_sync_check(struct hdspm * hdspm)
 {
-	int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
-	if (status2 & HDSPM_wcLock) {
-		if (status2 & HDSPM_wcSync)
+	if (hdspm->is_aes32) {
+		int status = hdspm_read(hdspm, HDSPM_statusRegister);
+		if (status & HDSPM_AES32_wcLock) {
+			/* I don't know how to differenciate sync from lock.
+			   Doing as if sync for now */
 			return 2;
-		else
-			return 1;
+		}
+		return 0;
+	} else {
+		int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+		if (status2 & HDSPM_wcLock) {
+			if (status2 & HDSPM_wcSync)
+				return 2;
+			else
+				return 1;
+		}
+		return 0;
 	}
-	return 0;
 }
 
 static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol,
@@ -2188,9 +2760,43 @@
 }
 
 
+#define HDSPM_AES_SYNC_CHECK(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+  .info = snd_hdspm_info_sync_check, \
+  .get = snd_hdspm_get_aes_sync_check \
+}
+
+static int hdspm_aes_sync_check(struct hdspm * hdspm, int idx)
+{
+	int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+	if (status2 & (HDSPM_LockAES >> idx)) {
+		/* I don't know how to differenciate sync from lock.
+		   Doing as if sync for now */
+		return 2;
+	}
+	return 0;
+}
+
+static int snd_hdspm_get_aes_sync_check(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int offset;
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	offset = ucontrol->id.index - 1;
+	if (offset < 0 || offset >= 8)
+		return -EINVAL;
+
+	ucontrol->value.enumerated.item[0] =
+		hdspm_aes_sync_check(hdspm, offset);
+	return 0;
+}
 
 
-static struct snd_kcontrol_new snd_hdspm_controls[] = {
+static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
 
 	HDSPM_MIXER("Mixer", 0),
 /* 'Sample Clock Source' complies with the alsa control naming scheme */
@@ -2211,6 +2817,29 @@
 	HDSPM_INPUT_SELECT("Input Select", 0),
 };
 
+static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
+
+	HDSPM_MIXER("Mixer", 0),
+/* 'Sample Clock Source' complies with the alsa control naming scheme */
+	HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
+
+	HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
+	HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
+	HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
+	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+/* 'External Rate' complies with the alsa control naming scheme */
+	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
+	HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
+/*	HDSPM_AES_SYNC_CHECK("AES Lock Status", 0),*/ /* created in snd_hdspm_create_controls() */
+	HDSPM_LINE_OUT("Line Out", 0),
+	HDSPM_EMPHASIS("Emphasis", 0),
+	HDSPM_DOLBY("Non Audio", 0),
+	HDSPM_PROFESSIONAL("Professional", 0),
+	HDSPM_C_TMS("Clear Track Marker", 0),
+	HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
+	HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
+};
+
 static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
 
 
@@ -2245,20 +2874,40 @@
 	struct snd_kcontrol *kctl;
 
 	/* add control list first */
+	if (hdspm->is_aes32) {
+		struct snd_kcontrol_new aes_sync_ctl =
+			HDSPM_AES_SYNC_CHECK("AES Lock Status", 0);
 
-	for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) {
-		if ((err =
-		     snd_ctl_add(card, kctl =
-				 snd_ctl_new1(&snd_hdspm_controls[idx],
-					      hdspm))) < 0) {
-			return err;
+		for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_aes32);
+		     idx++) {
+			err = snd_ctl_add(card,
+					  snd_ctl_new1(&snd_hdspm_controls_aes32[idx],
+						       hdspm));
+			if (err < 0)
+				return err;
+		}
+		for (idx = 1; idx <= 8; idx++) {
+			aes_sync_ctl.index = idx;
+			err = snd_ctl_add(card,
+					  snd_ctl_new1(&aes_sync_ctl, hdspm));
+			if (err < 0)
+				return err;
+		}
+	} else {
+		for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_madi);
+		     idx++) {
+			err = snd_ctl_add(card,
+					  snd_ctl_new1(&snd_hdspm_controls_madi[idx],
+						       hdspm));
+			if (err < 0)
+				return err;
 		}
 	}
 
 	/* Channel playback mixer as default control 
-	   Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer
-	   they are accesible via special IOCTL on hwdep
-	   and the mixer 2dimensional mixer control */
+Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer
+they are accesible via special IOCTL on hwdep
+and the mixer 2dimensional mixer control */
 
 	snd_hdspm_playback_mixer.name = "Chn";
 	limit = HDSPM_MAX_CHANNELS;
@@ -2289,7 +2938,8 @@
  ------------------------------------------------------------*/
 
 static void
-snd_hdspm_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer)
+snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
+			 struct snd_info_buffer *buffer)
 {
 	struct hdspm *hdspm = (struct hdspm *) entry->private_data;
 	unsigned int status;
@@ -2420,11 +3070,10 @@
 		clock_source = "Error";
 	}
 	snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
-	if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
+	if (!(hdspm->control_register & HDSPM_ClockModeMaster))
 		system_clock_mode = "Slave";
-	} else {
+	else
 		system_clock_mode = "Master";
-	}
 	snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
 
 	switch (hdspm_pref_sync_ref(hdspm)) {
@@ -2484,13 +3133,213 @@
 	snd_iprintf(buffer, "\n");
 }
 
+static void
+snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
+			  struct snd_info_buffer *buffer)
+{
+	struct hdspm *hdspm = (struct hdspm *) entry->private_data;
+	unsigned int status;
+	unsigned int status2;
+	unsigned int timecode;
+	int pref_syncref;
+	char *autosync_ref;
+	char *system_clock_mode;
+	char *clock_source;
+	int x;
+
+	status = hdspm_read(hdspm, HDSPM_statusRegister);
+	status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+	timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
+
+	snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
+		    hdspm->card_name, hdspm->card->number + 1,
+		    hdspm->firmware_rev);
+
+	snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
+		    hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
+
+	snd_iprintf(buffer, "--- System ---\n");
+
+	snd_iprintf(buffer,
+		    "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
+		    status & HDSPM_audioIRQPending,
+		    (status & HDSPM_midi0IRQPending) ? 1 : 0,
+		    (status & HDSPM_midi1IRQPending) ? 1 : 0,
+		    hdspm->irq_count);
+	snd_iprintf(buffer,
+		    "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
+		    ((status & HDSPM_BufferID) ? 1 : 0),
+		    (status & HDSPM_BufferPositionMask),
+		    (status & HDSPM_BufferPositionMask) % (2 *
+							   (int)hdspm->
+							   period_bytes),
+		    ((status & HDSPM_BufferPositionMask) -
+		     64) % (2 * (int)hdspm->period_bytes),
+		    (long) hdspm_hw_pointer(hdspm) * 4);
+
+	snd_iprintf(buffer,
+		    "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
+		    hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
+		    hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
+		    hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
+		    hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
+	snd_iprintf(buffer,
+		    "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n",
+		    hdspm->control_register, hdspm->control2_register,
+		    status, status2, timecode);
+
+	snd_iprintf(buffer, "--- Settings ---\n");
+
+	x = 1 << (6 +
+		  hdspm_decode_latency(hdspm->
+				       control_register &
+				       HDSPM_LatencyMask));
+
+	snd_iprintf(buffer,
+		    "Size (Latency): %d samples (2 periods of %lu bytes)\n",
+		    x, (unsigned long) hdspm->period_bytes);
+
+	snd_iprintf(buffer, "Line out: %s,   Precise Pointer: %s\n",
+		    (hdspm->
+		     control_register & HDSPM_LineOut) ? "on " : "off",
+		    (hdspm->precise_ptr) ? "on" : "off");
+
+	snd_iprintf(buffer,
+		    "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
+		    (hdspm->
+		     control_register & HDSPM_clr_tms) ? "on" : "off",
+		    (hdspm->
+		     control_register & HDSPM_Emphasis) ? "on" : "off",
+		    (hdspm->
+		     control_register & HDSPM_Dolby) ? "on" : "off");
+
+	switch (hdspm_clock_source(hdspm)) {
+	case HDSPM_CLOCK_SOURCE_AUTOSYNC:
+		clock_source = "AutoSync";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
+		clock_source = "Internal 32 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
+		clock_source = "Internal 44.1 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
+		clock_source = "Internal 48 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
+		clock_source = "Internal 64 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
+		clock_source = "Internal 88.2 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
+		clock_source = "Internal 96 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
+		clock_source = "Internal 128 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
+		clock_source = "Internal 176.4 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
+		clock_source = "Internal 192 kHz";
+		break;
+	default:
+		clock_source = "Error";
+	}
+	snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
+	if (!(hdspm->control_register & HDSPM_ClockModeMaster))
+		system_clock_mode = "Slave";
+	else
+		system_clock_mode = "Master";
+	snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
+
+	pref_syncref = hdspm_pref_sync_ref(hdspm);
+	if (pref_syncref == 0)
+		snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
+	else
+		snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
+				pref_syncref);
+
+	snd_iprintf(buffer, "System Clock Frequency: %d\n",
+		    hdspm->system_sample_rate);
+
+	snd_iprintf(buffer, "Double speed: %s\n",
+			hdspm->control_register & HDSPM_DS_DoubleWire?
+			"Double wire" : "Single wire");
+	snd_iprintf(buffer, "Quad speed: %s\n",
+			hdspm->control_register & HDSPM_QS_DoubleWire?
+			"Double wire" :
+			hdspm->control_register & HDSPM_QS_QuadWire?
+			"Quad wire" : "Single wire");
+
+	snd_iprintf(buffer, "--- Status:\n");
+
+	snd_iprintf(buffer, "Word: %s  Frequency: %d\n",
+			(status & HDSPM_AES32_wcLock)? "Sync   " : "No Lock",
+			HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
+
+	for (x = 0; x < 8; x++) {
+		snd_iprintf(buffer, "AES%d: %s  Frequency: %d\n",
+				x+1,
+				(status2 & (HDSPM_LockAES >> x))? "Sync   ": "No Lock",
+				HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
+	}
+
+	switch (hdspm_autosync_ref(hdspm)) {
+	case HDSPM_AES32_AUTOSYNC_FROM_NONE: autosync_ref="None"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_WORD: autosync_ref="Word Clock"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES1: autosync_ref="AES1"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES2: autosync_ref="AES2"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES3: autosync_ref="AES3"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES4: autosync_ref="AES4"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES5: autosync_ref="AES5"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES6: autosync_ref="AES6"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES7: autosync_ref="AES7"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES8: autosync_ref="AES8"; break;
+	default: autosync_ref = "---"; break;
+	}
+	snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
+
+	snd_iprintf(buffer, "\n");
+}
+
+#ifdef CONFIG_SND_DEBUG
+static void
+snd_hdspm_proc_read_debug(struct snd_info_entry * entry,
+			  struct snd_info_buffer *buffer)
+{
+	struct hdspm *hdspm = (struct hdspm *)entry->private_data;
+
+	int j,i;
+
+	for (i = 0; i < 256 /* 1024*64 */; i += j)
+	{
+		snd_iprintf(buffer, "0x%08X: ", i);
+		for (j = 0; j < 16; j += 4)
+			snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
+		snd_iprintf(buffer, "\n");
+	}
+}
+#endif
+
+
+
 static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
 {
 	struct snd_info_entry *entry;
 
 	if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
 		snd_info_set_text_ops(entry, hdspm,
-				      snd_hdspm_proc_read);
+				      hdspm->is_aes32 ?
+				      snd_hdspm_proc_read_aes32 :
+				      snd_hdspm_proc_read_madi);
+#ifdef CONFIG_SND_DEBUG
+	/* debug file to read all hdspm registers */
+	if (!snd_card_proc_new(hdspm->card, "debug", &entry))
+		snd_info_set_text_ops(entry, hdspm,
+				snd_hdspm_proc_read_debug);
+#endif
 }
 
 /*------------------------------------------------------------
@@ -2507,13 +3356,20 @@
 
 	/* set defaults:       */
 
-	hdspm->control_register = HDSPM_ClockModeMaster |	/* Master Cloack Mode on */
-	    hdspm_encode_latency(7) |	/* latency maximum = 8192 samples */
-	    HDSPM_InputCoaxial |	/* Input Coax not Optical */
-	    HDSPM_SyncRef_MADI |	/* Madi is syncclock */
-	    HDSPM_LineOut |	/* Analog output in */
-	    HDSPM_TX_64ch |	/* transmit in 64ch mode */
-	    HDSPM_AutoInp;	/* AutoInput chossing (takeover) */
+	if (hdspm->is_aes32)
+		hdspm->control_register = HDSPM_ClockModeMaster |	/* Master Cloack Mode on */
+			hdspm_encode_latency(7) |	/* latency maximum = 8192 samples */
+			HDSPM_SyncRef0 |	/* AES1 is syncclock */
+			HDSPM_LineOut |	/* Analog output in */
+			HDSPM_Professional;  /* Professional mode */
+	else
+		hdspm->control_register = HDSPM_ClockModeMaster |	/* Master Cloack Mode on */
+			hdspm_encode_latency(7) |	/* latency maximum = 8192 samples */
+			HDSPM_InputCoaxial |	/* Input Coax not Optical */
+			HDSPM_SyncRef_MADI |	/* Madi is syncclock */
+			HDSPM_LineOut |	/* Analog output in */
+			HDSPM_TX_64ch |	/* transmit in 64ch mode */
+			HDSPM_AutoInp;	/* AutoInput chossing (takeover) */
 
 	/* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
 	/* !  HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
@@ -2822,6 +3678,8 @@
 
 		hdspm->playback_buffer =
 		    (unsigned char *) substream->runtime->dma_area;
+		snd_printdd("Allocated sample buffer for playback at %p\n",
+				hdspm->playback_buffer);
 	} else {
 		hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
 				params_channels(params));
@@ -2831,7 +3689,15 @@
 
 		hdspm->capture_buffer =
 		    (unsigned char *) substream->runtime->dma_area;
+		snd_printdd("Allocated sample buffer for capture at %p\n",
+				hdspm->capture_buffer);
 	}
+	/*
+	   snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
+	   substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+	   "playback" : "capture",
+	   snd_pcm_sgbuf_get_addr(sgbuf, 0));
+	 */
 	return 0;
 }
 
@@ -2982,9 +3848,10 @@
 		  SNDRV_PCM_RATE_44100 |
 		  SNDRV_PCM_RATE_48000 |
 		  SNDRV_PCM_RATE_64000 |
-		  SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
+		  SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+		  SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
 	.rate_min = 32000,
-	.rate_max = 96000,
+	.rate_max = 192000,
 	.channels_min = 1,
 	.channels_max = HDSPM_MAX_CHANNELS,
 	.buffer_bytes_max =
@@ -3006,9 +3873,10 @@
 		  SNDRV_PCM_RATE_44100 |
 		  SNDRV_PCM_RATE_48000 |
 		  SNDRV_PCM_RATE_64000 |
-		  SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
+		  SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+		  SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
 	.rate_min = 32000,
-	.rate_max = 96000,
+	.rate_max = 192000,
 	.channels_min = 1,
 	.channels_max = HDSPM_MAX_CHANNELS,
 	.buffer_bytes_max =
@@ -3315,7 +4183,8 @@
 
 	pcm = hdspm->pcm;
 
-	wanted = HDSPM_DMA_AREA_BYTES + 4096;	/* dont know why, but it works */
+/*	wanted = HDSPM_DMA_AREA_BYTES + 4096;*/	/* dont know why, but it works */
+	wanted = HDSPM_DMA_AREA_BYTES;
 
 	if ((err =
 	     snd_pcm_lib_preallocate_pages_for_all(pcm,
@@ -3467,9 +4336,16 @@
 	pci_read_config_word(hdspm->pci,
 			     PCI_CLASS_REVISION, &hdspm->firmware_rev);
 
-	strcpy(card->driver, "HDSPM");
+	hdspm->is_aes32 = (hdspm->firmware_rev >= HDSPM_AESREVISION);
+
 	strcpy(card->mixername, "Xilinx FPGA");
-	hdspm->card_name = "RME HDSPM MADI";
+	if (hdspm->is_aes32) {
+		strcpy(card->driver, "HDSPAES32");
+		hdspm->card_name = "RME HDSPM AES32";
+	} else {
+		strcpy(card->driver, "HDSPM");
+		hdspm->card_name = "RME HDSPM MADI";
+	}
 
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 474f2d4..3bff321 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -2627,7 +2627,7 @@
 	return 0;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0);
 
 static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_value *ucontrol)
@@ -2844,7 +2844,7 @@
 	return change;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1);
 
 static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata =
 {
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index a572b01..a289922 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -1699,7 +1699,7 @@
 	return change;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_dxs, -9450, 150, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -9450, 150, 1);
 
 static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = {
 	.name = "PCM Playback Volume",
@@ -1823,7 +1823,7 @@
 	ac97.private_data = chip;
 	ac97.private_free = snd_via82xx_mixer_free_ac97;
 	ac97.pci = chip->pci;
-	ac97.scaps = AC97_SCAP_SKIP_MODEM;
+	ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;
 	if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)
 		return err;
 
@@ -2357,93 +2357,59 @@
 /*
  * auto detection of DXS channel supports.
  */
-struct dxs_whitelist {
-	unsigned short subvendor;
-	unsigned short subdevice; 
-	unsigned short mask; 
-	short action;	/* new dxs_support value */
+
+static struct snd_pci_quirk dxs_whitelist[] __devinitdata = {
+	SND_PCI_QUIRK(0x1005, 0x4710, "Avance Logic Mobo", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K),
+	SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK(0x1019, 0x0a85, "ECS L7VMM2", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK(0x1019, 0, "ESC K8", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x1019, 0xaa01, "ESC K8T890-A", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x1025, 0x0033, "Acer Inspire 1353LM", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK(0x1025, 0x0046, "Acer Aspire 1524 WLMi", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x1043, 0, "ASUS A7/A8", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK(0x1071, 0, "Diverse Notebook", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1106, 0, "ASRock", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte GA-7VAXP", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1462, 0x3800, "MSI KT266", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1462, 0x7120, "MSI KT4V", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1462, 0x7142, "MSI K8MM-V", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1462, 0, "MSI Mobo", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x147b, 0x1401, "ABIT KD7(-RAID)", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x147b, 0x1411, "ABIT VA-20", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x147b, 0x1413, "ABIT KV8 Pro", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x147b, 0x1415, "ABIT AV8", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK(0x14ff, 0x0403, "Twinhead mobo", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x14ff, 0x0408, "Twinhead laptop", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x1558, 0x4701, "Clevo D470", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x1584, 0x8120, "Diverse Laptop", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1584, 0x8123, "Targa/Uniwill", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK(0x161f, 0x202b, "Amira Notebook", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK(0x161f, 0x2032, "m680x machines", VIA_DXS_48K),
+	SND_PCI_QUIRK(0x1631, 0xe004, "PB EasyNote 3174", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1695, 0x3005, "EPoX EP-8K9A", VIA_DXS_ENABLE),
+	SND_PCI_QUIRK(0x1695, 0, "EPoX mobo", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x16f3, 0, "Jetway K8", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x1734, 0, "FSC Laptop", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x1849, 0x3059, "ASRock K7VM2", VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK(0x1849, 0, "ASRock mobo", VIA_DXS_SRC),
+	SND_PCI_QUIRK(0x1919, 0x200a, "Soltek SL-K8",  VIA_DXS_NO_VRA),
+	SND_PCI_QUIRK(0x4005, 0x4710, "MSI K7T266", VIA_DXS_SRC),
+	{ } /* terminator */
 };
 
 static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
 {
-	static struct dxs_whitelist whitelist[] __devinitdata = {
-		{ .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
-		{ .subvendor = 0x1019, .subdevice = 0x0996, .action = VIA_DXS_48K },
-		{ .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?)*/
-		{ .subvendor = 0x1043, .subdevice = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
-		{ .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ 
-		{ .subvendor = 0x1043, .subdevice = 0x810d, .action = VIA_DXS_SRC }, /* ASUS */
-		{ .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC    }, /* ASUS A8V Deluxe */ 
-		{ .subvendor = 0x1043, .subdevice = 0x8174, .action = VIA_DXS_SRC    }, /* ASUS */
-		{ .subvendor = 0x1043, .subdevice = 0x81b9, .action = VIA_DXS_SRC    }, /* ASUS A8V-MX */
-		{ .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
-		{ .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */
-		{ .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
-		{ .subvendor = 0x1106, .subdevice = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
-		{ .subvendor = 0x1106, .subdevice = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
-		{ .subvendor = 0x1106, .subdevice = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
-		{ .subvendor = 0x1106, .subdevice = 0xc001, .action = VIA_DXS_SRC }, /* Insight P4-ITX */
-		{ .subvendor = 0x1297, .subdevice = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
-		{ .subvendor = 0x1297, .subdevice = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
-		{ .subvendor = 0x1458, .subdevice = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
-		{ .subvendor = 0x1462, .subdevice = 0x0080, .action = VIA_DXS_SRC }, /* MSI K8T Neo-FIS2R */
-		{ .subvendor = 0x1462, .subdevice = 0x0430, .action = VIA_DXS_SRC }, /* MSI 7142 (K8MM-V) */
-		{ .subvendor = 0x1462, .subdevice = 0x0470, .action = VIA_DXS_SRC }, /* MSI KT880 Delta-FSR */
-		{ .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
-		{ .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
-		{ .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_SRC }, /* MSI K8T Neo2-FI */
-		{ .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
-		{ .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */
-		{ .subvendor = 0x1462, .subdevice = 0xb012, .action = VIA_DXS_SRC }, /* P4M800/VIA8237R */
-		{ .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
-		{ .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
-		{ .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
-		{ .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
-		{ .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
-		{ .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_SRC }, /* Twinhead laptop */
-		{ .subvendor = 0x1558, .subdevice = 0x4701, .action = VIA_DXS_SRC }, /* Clevo D470 */
-		{ .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
-		{ .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
-		{ .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
-		{ .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 */
-		{ .subvendor = 0x1734, .subdevice = 0x1093, .action = VIA_DXS_SRC }, /* FSC */
-		{ .subvendor = 0x1734, .subdevice = 0x10ab, .action = VIA_DXS_SRC }, /* FSC */
-		{ .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
-		{ .subvendor = 0x1849, .subdevice = 0x9739, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */
-		{ .subvendor = 0x1849, .subdevice = 0x9761, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */
-		{ .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */
-		{ .subvendor = 0x4005, .subdevice = 0x4710, .action = VIA_DXS_SRC },	/* MSI K7T266 Pro2 (MS-6380 V2.0) BIOS 3.7 */
-		{ } /* terminator */
-	};
-	const struct dxs_whitelist *w;
-	unsigned short subsystem_vendor;
-	unsigned short subsystem_device;
+	const struct snd_pci_quirk *w;
 
-	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
-	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
-
-	for (w = whitelist; w->subvendor; w++) {
-		if (w->subvendor != subsystem_vendor)
-			continue;
-		if (w->mask) {
-			if ((w->mask & subsystem_device) == w->subdevice)
-				return w->action;
-		} else {
-			if (subsystem_device == w->subdevice)
-				return w->action;
-		}
+	w = snd_pci_quirk_lookup(pci, dxs_whitelist);
+	if (w) {
+		snd_printdd(KERN_INFO "via82xx: DXS white list for %s found\n",
+			    w->name);
+		return w->value;
 	}
 
 	/* for newer revision, default to DXS_SRC */
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 17d6b84..b338e15 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -900,7 +900,7 @@
 	ac97.private_data = chip;
 	ac97.private_free = snd_via82xx_mixer_free_ac97;
 	ac97.pci = chip->pci;
-	ac97.scaps = AC97_SCAP_SKIP_AUDIO;
+	ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
 	ac97.num = chip->ac97_secondary;
 
 	if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 89f58ea..474eac9 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -73,8 +73,8 @@
 /*
  */
 
-static DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0);
-static DECLARE_TLV_DB_SCALE(db_scale_akm, -7350, 50, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_akm, -7350, 50, 0);
 
 static struct snd_vx_hardware vx222_old_hw = {
 
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index 5e51950..55558be 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -846,7 +846,7 @@
 
 #define MIC_LEVEL_MAX	0xff
 
-static DECLARE_TLV_DB_SCALE(db_scale_mic, -6450, 50, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_mic, -6450, 50, 0);
 
 /*
  * controls API for input levels
diff --git a/sound/pci/ymfpci/ymfpci_image.h b/sound/pci/ymfpci/ymfpci_image.h
index 1b07469..112f2ff 100644
--- a/sound/pci/ymfpci/ymfpci_image.h
+++ b/sound/pci/ymfpci/ymfpci_image.h
@@ -1,7 +1,7 @@
 #ifndef _HWMCODE_
 #define _HWMCODE_
 
-static unsigned long DspInst[YDSXG_DSPLENGTH / 4] = {
+static u32 DspInst[YDSXG_DSPLENGTH / 4] = {
 	0x00000081, 0x000001a4, 0x0000000a, 0x0000002f,
 	0x00080253, 0x01800317, 0x0000407b, 0x0000843f,
 	0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c,
@@ -12,7 +12,7 @@
 	0x00000000, 0x00000000, 0x00000000, 0x00000000
 };
 
-static unsigned long CntrlInst[YDSXG_CTRLLENGTH / 4] = {
+static u32 CntrlInst[YDSXG_CTRLLENGTH / 4] = {
 	0x000007, 0x240007, 0x0C0007, 0x1C0007,
 	0x060007, 0x700002, 0x000020, 0x030040,
 	0x007104, 0x004286, 0x030040, 0x000F0D,
@@ -791,7 +791,7 @@
 // 04/09  creat
 // 04/12  stop nise fix
 // 06/21  WorkingOff timming
-static unsigned long CntrlInst1E[YDSXG_CTRLLENGTH / 4] = {
+static u32 CntrlInst1E[YDSXG_CTRLLENGTH / 4] = {
 	0x000007, 0x240007, 0x0C0007, 0x1C0007,
 	0x060007, 0x700002, 0x000020, 0x030040,
 	0x007104, 0x004286, 0x030040, 0x000F0D,
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 7881944..fd12674 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2,12 +2,6 @@
  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
  *  Routines for control of YMF724/740/744/754 chips
  *
- *  BUGS:
- *    --
- *
- *  TODO:
- *    --
- *
  *   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
@@ -26,6 +20,7 @@
 
 #include <sound/driver.h>
 #include <linux/delay.h>
+#include <linux/firmware.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
@@ -42,10 +37,7 @@
 #include <sound/mpu401.h>
 
 #include <asm/io.h>
-
-/*
- *  constants
- */
+#include <asm/byteorder.h>
 
 /*
  *  common I/O routines
@@ -179,6 +171,17 @@
 	return val[0];
 }
 
+static void snd_ymfpci_pcm_441_volume_set(struct snd_ymfpci_pcm *ypcm)
+{
+	unsigned int value;
+	struct snd_ymfpci_pcm_mixer *mixer;
+	
+	mixer = &ypcm->chip->pcm_mixer[ypcm->substream->number];
+	value = min_t(unsigned int, mixer->left, 0x7fff) >> 1;
+	value |= (min_t(unsigned int, mixer->right, 0x7fff) >> 1) << 16;
+	snd_ymfpci_writel(ypcm->chip, YDSXGR_BUF441OUTVOL, value);
+}
+
 /*
  *  Hardware start management
  */
@@ -290,6 +293,10 @@
 	snd_assert(pvoice != NULL, return -EINVAL);
 	snd_ymfpci_hw_stop(chip);
 	spin_lock_irqsave(&chip->voice_lock, flags);
+	if (pvoice->number == chip->src441_used) {
+		chip->src441_used = -1;
+		pvoice->ypcm->use_441_slot = 0;
+	}
 	pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
 	pvoice->ypcm = NULL;
 	pvoice->interrupt = NULL;
@@ -394,7 +401,7 @@
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 	case SNDRV_PCM_TRIGGER_RESUME:
 		chip->ctrl_playback[ypcm->voices[0]->number + 1] = cpu_to_le32(ypcm->voices[0]->bank_addr);
-		if (ypcm->voices[1] != NULL)
+		if (ypcm->voices[1] != NULL && !ypcm->use_441_slot)
 			chip->ctrl_playback[ypcm->voices[1]->number + 1] = cpu_to_le32(ypcm->voices[1]->bank_addr);
 		ypcm->running = 1;
 		break;
@@ -402,7 +409,7 @@
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 		chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0;
-		if (ypcm->voices[1] != NULL)
+		if (ypcm->voices[1] != NULL && !ypcm->use_441_slot)
 			chip->ctrl_playback[ypcm->voices[1]->number + 1] = 0;
 		ypcm->running = 0;
 		break;
@@ -489,6 +496,7 @@
 	unsigned int nbank;
 	u32 vol_left, vol_right;
 	u8 use_left, use_right;
+	unsigned long flags;
 
 	snd_assert(voice != NULL, return);
 	if (runtime->channels == 1) {
@@ -507,11 +515,27 @@
 		vol_left = cpu_to_le32(0x40000000);
 		vol_right = cpu_to_le32(0x40000000);
 	}
+	spin_lock_irqsave(&ypcm->chip->voice_lock, flags);
 	format = runtime->channels == 2 ? 0x00010000 : 0;
 	if (snd_pcm_format_width(runtime->format) == 8)
 		format |= 0x80000000;
+	else if (ypcm->chip->device_id == PCI_DEVICE_ID_YAMAHA_754 &&
+		 runtime->rate == 44100 && runtime->channels == 2 &&
+		 voiceidx == 0 && (ypcm->chip->src441_used == -1 ||
+				   ypcm->chip->src441_used == voice->number)) {
+		ypcm->chip->src441_used = voice->number;
+		ypcm->use_441_slot = 1;
+		format |= 0x10000000;
+		snd_ymfpci_pcm_441_volume_set(ypcm);
+	}
+	if (ypcm->chip->src441_used == voice->number &&
+	    (format & 0x10000000) == 0) {
+		ypcm->chip->src441_used = -1;
+		ypcm->use_441_slot = 0;
+	}
 	if (runtime->channels == 2 && (voiceidx & 1) != 0)
 		format |= 1;
+	spin_unlock_irqrestore(&ypcm->chip->voice_lock, flags);
 	for (nbank = 0; nbank < 2; nbank++) {
 		bank = &voice->bank[nbank];
 		memset(bank, 0, sizeof(*bank));
@@ -1480,7 +1504,7 @@
 	return change;
 }
 
-static DECLARE_TLV_DB_LINEAR(db_scale_native, TLV_DB_GAIN_MUTE, 0);
+static const DECLARE_TLV_DB_LINEAR(db_scale_native, TLV_DB_GAIN_MUTE, 0);
 
 #define YMFPCI_DOUBLE(xname, xindex, reg) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -1722,7 +1746,10 @@
 		spin_lock_irqsave(&chip->voice_lock, flags);
 		if (substream->runtime && substream->runtime->private_data) {
 			struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
-			ypcm->update_pcm_vol = 2;
+			if (!ypcm->use_441_slot)
+				ypcm->update_pcm_vol = 2;
+			else
+				snd_ymfpci_pcm_441_volume_set(ypcm);
 		}
 		spin_unlock_irqrestore(&chip->voice_lock, flags);
 		return 1;
@@ -1971,13 +1998,94 @@
 	}
 }
 
+#define FIRMWARE_IN_THE_KERNEL
+
+#ifdef FIRMWARE_IN_THE_KERNEL
+
 #include "ymfpci_image.h"
 
+static struct firmware snd_ymfpci_dsp_microcode = {
+	.size = YDSXG_DSPLENGTH,
+	.data = (u8 *)DspInst,
+};
+static struct firmware snd_ymfpci_controller_microcode = {
+	.size = YDSXG_CTRLLENGTH,
+	.data = (u8 *)CntrlInst,
+};
+static struct firmware snd_ymfpci_controller_1e_microcode = {
+	.size = YDSXG_CTRLLENGTH,
+	.data = (u8 *)CntrlInst1E,
+};
+#endif
+
+#ifdef __LITTLE_ENDIAN
+static inline void snd_ymfpci_convert_from_le(const struct firmware *fw) { }
+#else
+static void snd_ymfpci_convert_from_le(const struct firmware *fw)
+{
+	int i;
+	u32 *data = (u32 *)fw->data;
+
+	for (i = 0; i < fw->size / 4; ++i)
+		le32_to_cpus(&data[i]);
+}
+#endif
+
+static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip)
+{
+	int err, is_1e;
+	const char *name;
+
+	err = request_firmware(&chip->dsp_microcode, "yamaha/ds1_dsp.fw",
+			       &chip->pci->dev);
+	if (err >= 0) {
+		if (chip->dsp_microcode->size == YDSXG_DSPLENGTH)
+			snd_ymfpci_convert_from_le(chip->dsp_microcode);
+		else {
+			snd_printk(KERN_ERR "DSP microcode has wrong size\n");
+			err = -EINVAL;
+		}
+	}
+	if (err < 0) {
+#ifdef FIRMWARE_IN_THE_KERNEL
+		chip->dsp_microcode = &snd_ymfpci_dsp_microcode;
+#else
+		return err;
+#endif
+	}
+	is_1e = chip->device_id == PCI_DEVICE_ID_YAMAHA_724F ||
+		chip->device_id == PCI_DEVICE_ID_YAMAHA_740C ||
+		chip->device_id == PCI_DEVICE_ID_YAMAHA_744 ||
+		chip->device_id == PCI_DEVICE_ID_YAMAHA_754;
+	name = is_1e ? "yamaha/ds1e_ctrl.fw" : "yamaha/ds1_ctrl.fw";
+	err = request_firmware(&chip->controller_microcode, name,
+			       &chip->pci->dev);
+	if (err >= 0) {
+		if (chip->controller_microcode->size == YDSXG_CTRLLENGTH)
+			snd_ymfpci_convert_from_le(chip->controller_microcode);
+		else {
+			snd_printk(KERN_ERR "controller microcode"
+				   " has wrong size\n");
+			err = -EINVAL;
+		}
+	}
+	if (err < 0) {
+#ifdef FIRMWARE_IN_THE_KERNEL
+		chip->controller_microcode =
+			is_1e ? &snd_ymfpci_controller_1e_microcode
+			      : &snd_ymfpci_controller_microcode;
+#else
+		return err;
+#endif
+	}
+	return 0;
+}
+
 static void snd_ymfpci_download_image(struct snd_ymfpci *chip)
 {
 	int i;
 	u16 ctrl;
-	unsigned long *inst;
+	u32 *inst;
 
 	snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x00000000);
 	snd_ymfpci_disable_dsp(chip);
@@ -1992,21 +2100,12 @@
 	snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
 
 	/* setup DSP instruction code */
+	inst = (u32 *)chip->dsp_microcode->data;
 	for (i = 0; i < YDSXG_DSPLENGTH / 4; i++)
-		snd_ymfpci_writel(chip, YDSXGR_DSPINSTRAM + (i << 2), DspInst[i]);
+		snd_ymfpci_writel(chip, YDSXGR_DSPINSTRAM + (i << 2), inst[i]);
 
 	/* setup control instruction code */
-	switch (chip->device_id) {
-	case PCI_DEVICE_ID_YAMAHA_724F:
-	case PCI_DEVICE_ID_YAMAHA_740C:
-	case PCI_DEVICE_ID_YAMAHA_744:
-	case PCI_DEVICE_ID_YAMAHA_754:
-		inst = CntrlInst1E;
-		break;
-	default:
-		inst = CntrlInst;
-		break;
-	}
+	inst = (u32 *)chip->controller_microcode->data;
 	for (i = 0; i < YDSXG_CTRLLENGTH / 4; i++)
 		snd_ymfpci_writel(chip, YDSXGR_CTRLINSTRAM + (i << 2), inst[i]);
 
@@ -2160,6 +2259,15 @@
 	pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
 	
 	pci_disable_device(chip->pci);
+#ifdef FIRMWARE_IN_THE_KERNEL
+	if (chip->dsp_microcode != &snd_ymfpci_dsp_microcode)
+#endif
+		release_firmware(chip->dsp_microcode);
+#ifdef FIRMWARE_IN_THE_KERNEL
+	if (chip->controller_microcode != &snd_ymfpci_controller_microcode &&
+	    chip->controller_microcode != &snd_ymfpci_controller_1e_microcode)
+#endif
+		release_firmware(chip->controller_microcode);
 	kfree(chip);
 	return 0;
 }
@@ -2180,7 +2288,7 @@
 	YDSXGR_PRIADCLOOPVOL,
 	YDSXGR_NATIVEDACINVOL,
 	YDSXGR_NATIVEDACOUTVOL,
-	// YDSXGR_BUF441OUTVOL,
+	YDSXGR_BUF441OUTVOL,
 	YDSXGR_NATIVEADCINVOL,
 	YDSXGR_SPDIFLOOPVOL,
 	YDSXGR_SPDIFOUTVOL,
@@ -2295,6 +2403,7 @@
 	chip->reg_area_phys = pci_resource_start(pci, 0);
 	chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000);
 	pci_set_master(pci);
+	chip->src441_used = -1;
 
 	if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) {
 		snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1);
@@ -2315,6 +2424,12 @@
 		return -EIO;
 	}
 
+	err = snd_ymfpci_request_firmware(chip);
+	if (err < 0) {
+		snd_printk(KERN_ERR "firmware request failed: %d\n", err);
+		snd_ymfpci_free(chip);
+		return err;
+	}
 	snd_ymfpci_download_image(chip);
 
 	udelay(100); /* seems we need a delay after downloading image.. */
diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c
index bced7b6..2b1f996 100644
--- a/sound/pcmcia/vx/vxp_mixer.c
+++ b/sound/pcmcia/vx/vxp_mixer.c
@@ -64,7 +64,7 @@
 	return 0;
 }
 
-static DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0);
 
 static struct snd_kcontrol_new vx_control_mic_level = {
 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index d7df59e..363bcb5 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -91,7 +91,7 @@
  * Only output levels can be modified
  */
 
-static DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0);
 
 static struct snd_vx_hardware vxpocket_hw = {
 	.name = "VXPocket",
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
new file mode 100644
index 0000000..ec821a5
--- /dev/null
+++ b/sound/soc/Kconfig
@@ -0,0 +1,32 @@
+#
+# SoC audio configuration
+#
+
+menu "SoC audio support"
+	depends on SND!=n
+
+config SND_SOC_AC97_BUS
+	bool
+
+config SND_SOC
+	tristate "SoC audio support"
+	---help---
+
+	  If you want SoC support, you should say Y here and also to the
+	  specific driver for your SoC below. You will also need to select the
+	  specific codec(s) attached to the SoC
+
+	  This SoC audio support can also be built as a module.  If so, the module
+	  will be called snd-soc-core.
+
+# All the supported Soc's
+menu "SoC Platforms"
+depends on SND_SOC
+source "sound/soc/at91/Kconfig"
+source "sound/soc/pxa/Kconfig"
+endmenu
+
+# Supported codecs
+source "sound/soc/codecs/Kconfig"
+
+endmenu
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
new file mode 100644
index 0000000..98e6f49
--- /dev/null
+++ b/sound/soc/Makefile
@@ -0,0 +1,4 @@
+snd-soc-core-objs := soc-core.o soc-dapm.o
+
+obj-$(CONFIG_SND_SOC)	+= snd-soc-core.o
+obj-$(CONFIG_SND_SOC)	+= codecs/ at91/ pxa/
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
new file mode 100644
index 0000000..5bcf08b
--- /dev/null
+++ b/sound/soc/at91/Kconfig
@@ -0,0 +1,32 @@
+menu "SoC Audio for the Atmel AT91"
+
+config SND_AT91_SOC
+	tristate "SoC Audio for the Atmel AT91 System-on-Chip"
+	depends on ARCH_AT91 && SND
+	select SND_PCM
+	help
+	  Say Y or M if you want to add support for codecs attached to
+	  the AT91 SSC interface. You will also need
+	  to select the audio interfaces to support below.
+
+config SND_AT91_SOC_I2S
+	tristate
+
+config SND_AT91_SOC_ETI_B1_WM8731
+	tristate "SoC I2S Audio support for WM8731-based Endrelia ETI-B1 boards"
+	depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1)
+	select SND_AT91_SOC_I2S
+	select SND_SOC_WM8731
+	help
+	  Say Y if you want to add support for SoC audio on WM8731-based
+	  Endrelia Technologies Inc ETI-B1 or ETI-C1 boards.
+
+config SND_AT91_SOC_ETI_SLAVE
+	bool "Run codec in slave Mode on Endrelia boards"
+	depends on SND_AT91_SOC_ETI_B1_WM8731
+	default n
+	help
+	  Say Y if you want to run with the AT91 SSC generating the BCLK
+	  and LRC signals on Endrelia boards.
+
+endmenu
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
new file mode 100644
index 0000000..b77b01a
--- /dev/null
+++ b/sound/soc/at91/Makefile
@@ -0,0 +1,11 @@
+# AT91 Platform Support
+snd-soc-at91-objs := at91-pcm.o
+snd-soc-at91-i2s-objs := at91-i2s.o
+
+obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
+obj-$(CONFIG_SND_AT91_SOC_I2S) += snd-soc-at91-i2s.o
+
+# AT91 Machine Support
+snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o
+
+obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o
diff --git a/sound/soc/at91/at91-i2s.c b/sound/soc/at91/at91-i2s.c
new file mode 100644
index 0000000..9fc0c03
--- /dev/null
+++ b/sound/soc/at91/at91-i2s.c
@@ -0,0 +1,721 @@
+/*
+ * at91-i2s.c  --  ALSA SoC I2S Audio Layer Platform driver
+ *
+ * Author: Frank Mandarino <fmandarino@endrelia.com>
+ *         Endrelia Technologies Inc.
+ *
+ * Based on pxa2xx Platform drivers by
+ * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/atmel_pdc.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_ssc.h>
+
+#include "at91-pcm.h"
+#include "at91-i2s.h"
+
+#if 0
+#define	DBG(x...)	printk(KERN_DEBUG "at91-i2s:" x)
+#else
+#define	DBG(x...)
+#endif
+
+#if defined(CONFIG_ARCH_AT91SAM9260)
+#define NUM_SSC_DEVICES		1
+#else
+#define NUM_SSC_DEVICES		3
+#endif
+
+
+/*
+ * SSC PDC registers required by the PCM DMA engine.
+ */
+static struct at91_pdc_regs pdc_tx_reg = {
+	.xpr		= ATMEL_PDC_TPR,
+	.xcr		= ATMEL_PDC_TCR,
+	.xnpr		= ATMEL_PDC_TNPR,
+	.xncr		= ATMEL_PDC_TNCR,
+};
+
+static struct at91_pdc_regs pdc_rx_reg = {
+	.xpr		= ATMEL_PDC_RPR,
+	.xcr		= ATMEL_PDC_RCR,
+	.xnpr		= ATMEL_PDC_RNPR,
+	.xncr		= ATMEL_PDC_RNCR,
+};
+
+/*
+ * SSC & PDC status bits for transmit and receive.
+ */
+static struct at91_ssc_mask ssc_tx_mask = {
+	.ssc_enable	= AT91_SSC_TXEN,
+	.ssc_disable	= AT91_SSC_TXDIS,
+	.ssc_endx	= AT91_SSC_ENDTX,
+	.ssc_endbuf	= AT91_SSC_TXBUFE,
+	.pdc_enable	= ATMEL_PDC_TXTEN,
+	.pdc_disable	= ATMEL_PDC_TXTDIS,
+};
+
+static struct at91_ssc_mask ssc_rx_mask = {
+	.ssc_enable	= AT91_SSC_RXEN,
+	.ssc_disable	= AT91_SSC_RXDIS,
+	.ssc_endx	= AT91_SSC_ENDRX,
+	.ssc_endbuf	= AT91_SSC_RXBUFF,
+	.pdc_enable	= ATMEL_PDC_RXTEN,
+	.pdc_disable	= ATMEL_PDC_RXTDIS,
+};
+
+
+/*
+ * DMA parameters.
+ */
+static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
+	{{
+	.name		= "SSC0/I2S PCM Stereo out",
+	.pdc		= &pdc_tx_reg,
+	.mask		= &ssc_tx_mask,
+	},
+	{
+	.name		= "SSC0/I2S PCM Stereo in",
+	.pdc		= &pdc_rx_reg,
+	.mask		= &ssc_rx_mask,
+	}},
+#if NUM_SSC_DEVICES == 3
+	{{
+	.name		= "SSC1/I2S PCM Stereo out",
+	.pdc		= &pdc_tx_reg,
+	.mask		= &ssc_tx_mask,
+	},
+	{
+	.name		= "SSC1/I2S PCM Stereo in",
+	.pdc		= &pdc_rx_reg,
+	.mask		= &ssc_rx_mask,
+	}},
+	{{
+	.name		= "SSC2/I2S PCM Stereo out",
+	.pdc		= &pdc_tx_reg,
+	.mask		= &ssc_tx_mask,
+	},
+	{
+	.name		= "SSC1/I2S PCM Stereo in",
+	.pdc		= &pdc_rx_reg,
+	.mask		= &ssc_rx_mask,
+	}},
+#endif
+};
+
+struct at91_ssc_state {
+	u32	ssc_cmr;
+	u32	ssc_rcmr;
+	u32	ssc_rfmr;
+	u32	ssc_tcmr;
+	u32	ssc_tfmr;
+	u32	ssc_sr;
+	u32	ssc_imr;
+};
+
+static struct at91_ssc_info {
+	char		*name;
+	struct at91_ssc_periph ssc;
+	spinlock_t 	lock;		/* lock for dir_mask */
+	unsigned short	dir_mask;	/* 0=unused, 1=playback, 2=capture */
+	unsigned short	initialized;	/* 1=SSC has been initialized */
+	unsigned short	daifmt;
+	unsigned short	cmr_div;
+	unsigned short	tcmr_period;
+	unsigned short	rcmr_period;
+	struct at91_pcm_dma_params *dma_params[2];
+	struct at91_ssc_state ssc_state;
+
+} ssc_info[NUM_SSC_DEVICES] = {
+	{
+	.name		= "ssc0",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.dir_mask	= 0,
+	.initialized	= 0,
+	},
+#if NUM_SSC_DEVICES == 3
+	{
+	.name		= "ssc1",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.dir_mask	= 0,
+	.initialized	= 0,
+	},
+	{
+	.name		= "ssc2",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.dir_mask	= 0,
+	.initialized	= 0,
+	},
+#endif
+};
+
+static unsigned int at91_i2s_sysclk;
+
+/*
+ * SSC interrupt handler.  Passes PDC interrupts to the DMA
+ * interrupt handler in the PCM driver.
+ */
+static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id)
+{
+	struct at91_ssc_info *ssc_p = dev_id;
+	struct at91_pcm_dma_params *dma_params;
+	u32 ssc_sr;
+	int i;
+
+	ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)
+			& at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
+
+	/*
+	 * Loop through the substreams attached to this SSC.  If
+	 * a DMA-related interrupt occurred on that substream, call
+	 * the DMA interrupt handler function, if one has been
+	 * registered in the dma_params structure by the PCM driver.
+	 */
+	for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
+		dma_params = ssc_p->dma_params[i];
+
+		if (dma_params != NULL && dma_params->dma_intr_handler != NULL &&
+			(ssc_sr &
+			(dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf)))
+
+			dma_params->dma_intr_handler(ssc_sr, dma_params->substream);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Startup.  Only that one substream allowed in each direction.
+ */
+static int at91_i2s_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+	int dir_mask;
+
+	DBG("i2s_startup: SSC_SR=0x%08lx\n",
+			at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
+	dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
+
+	spin_lock_irq(&ssc_p->lock);
+	if (ssc_p->dir_mask & dir_mask) {
+		spin_unlock_irq(&ssc_p->lock);
+		return -EBUSY;
+	}
+	ssc_p->dir_mask |= dir_mask;
+	spin_unlock_irq(&ssc_p->lock);
+
+	return 0;
+}
+
+/*
+ * Shutdown.  Clear DMA parameters and shutdown the SSC if there
+ * are no other substreams open.
+ */
+static void at91_i2s_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+	struct at91_pcm_dma_params *dma_params;
+	int dir, dir_mask;
+
+	dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
+	dma_params = ssc_p->dma_params[dir];
+
+	if (dma_params != NULL) {
+		at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
+				dma_params->mask->ssc_disable);
+		DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"),
+			at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
+
+		dma_params->ssc_base = NULL;
+		dma_params->substream = NULL;
+		ssc_p->dma_params[dir] = NULL;
+	}
+
+	dir_mask = 1 << dir;
+
+	spin_lock_irq(&ssc_p->lock);
+	ssc_p->dir_mask &= ~dir_mask;
+	if (!ssc_p->dir_mask) {
+		/* Shutdown the SSC clock. */
+		DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
+		at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
+
+		if (ssc_p->initialized) {
+			free_irq(ssc_p->ssc.pid, ssc_p);
+			ssc_p->initialized = 0;
+		}
+
+		/* Reset the SSC */
+		at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
+
+		/* Clear the SSC dividers */
+		ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
+	}
+	spin_unlock_irq(&ssc_p->lock);
+}
+
+/*
+ * Record the SSC system clock rate.
+ */
+static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	/*
+	 * The only clock supplied to the SSC is the AT91 master clock,
+	 * which is only used if the SSC is generating BCLK and/or
+	 * LRC clocks.
+	 */
+	switch (clk_id) {
+	case AT91_SYSCLK_MCK:
+		at91_i2s_sysclk = freq;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Record the DAI format for use in hw_params().
+ */
+static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+		unsigned int fmt)
+{
+	struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S)
+		return -EINVAL;
+
+	ssc_p->daifmt = fmt;
+	return 0;
+}
+
+/*
+ * Record SSC clock dividers for use in hw_params().
+ */
+static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+	int div_id, int div)
+{
+	struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+	switch (div_id) {
+	case AT91SSC_CMR_DIV:
+		/*
+		 * The same master clock divider is used for both
+		 * transmit and receive, so if a value has already
+		 * been set, it must match this value.
+		 */
+		if (ssc_p->cmr_div == 0)
+			ssc_p->cmr_div = div;
+		else
+			if (div != ssc_p->cmr_div)
+				return -EBUSY;
+		break;
+
+	case AT91SSC_TCMR_PERIOD:
+		ssc_p->tcmr_period = div;
+		break;
+
+	case AT91SSC_RCMR_PERIOD:
+		ssc_p->rcmr_period = div;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Configure the SSC.
+ */
+static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	int id = rtd->dai->cpu_dai->id;
+	struct at91_ssc_info *ssc_p = &ssc_info[id];
+	struct at91_pcm_dma_params *dma_params;
+	int dir, channels, bits;
+	u32 tfmr, rfmr, tcmr, rcmr;
+	int start_event;
+	int ret;
+
+	/*
+	 * Currently, there is only one set of dma params for
+	 * each direction.  If more are added, this code will
+	 * have to be changed to select the proper set.
+	 */
+	dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
+
+	dma_params = &ssc_dma_params[id][dir];
+	dma_params->ssc_base = ssc_p->ssc.base;
+	dma_params->substream = substream;
+
+	ssc_p->dma_params[dir] = dma_params;
+
+	/*
+	 * The cpu_dai->dma_data field is only used to communicate the
+	 * appropriate DMA parameters to the pcm driver hw_params()
+	 * function.  It should not be used for other purposes
+	 * as it is common to all substreams.
+	 */
+	rtd->dai->cpu_dai->dma_data = dma_params;
+
+	channels = params_channels(params);
+
+	/*
+	 * The SSC only supports up to 16-bit samples in I2S format, due
+	 * to the size of the Frame Mode Register FSLEN field.  Also, I2S
+	 * implies signed data.
+	 */
+	bits = 16;
+	dma_params->pdc_xfer_size = 2;
+
+	/*
+	 * Compute SSC register settings.
+	 */
+	switch (ssc_p->daifmt) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		/*
+		 * SSC provides BCLK and LRC clocks.
+		 *
+		 * The SSC transmit and receive clocks are generated from the
+		 * MCK divider, and the BCLK signal is output on the SSC TK line.
+		 */
+		rcmr =	  (( ssc_p->rcmr_period		<< 24) & AT91_SSC_PERIOD)
+			| (( 1				<< 16) & AT91_SSC_STTDLY)
+			| (( AT91_SSC_START_FALLING_RF	     ) & AT91_SSC_START)
+			| (( AT91_SSC_CK_RISING		     ) & AT91_SSC_CKI)
+			| (( AT91_SSC_CKO_NONE		     ) & AT91_SSC_CKO)
+			| (( AT91_SSC_CKS_DIV		     ) & AT91_SSC_CKS);
+
+		rfmr =	  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
+			| (( AT91_SSC_FSOS_NEGATIVE	     ) & AT91_SSC_FSOS)
+			| (((bits - 1)			<< 16) & AT91_SSC_FSLEN)
+			| (((channels - 1)		<<  8) & AT91_SSC_DATNB)
+			| (( 1				<<  7) & AT91_SSC_MSBF)
+			| (( 0				<<  5) & AT91_SSC_LOOP)
+			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
+
+		tcmr =	  (( ssc_p->tcmr_period		<< 24) & AT91_SSC_PERIOD)
+			| (( 1				<< 16) & AT91_SSC_STTDLY)
+			| (( AT91_SSC_START_FALLING_RF       ) & AT91_SSC_START)
+			| (( AT91_SSC_CKI_FALLING	     ) & AT91_SSC_CKI)
+			| (( AT91_SSC_CKO_CONTINUOUS	     ) & AT91_SSC_CKO)
+			| (( AT91_SSC_CKS_DIV		     ) & AT91_SSC_CKS);
+
+		tfmr =	  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
+			| (( 0				<< 23) & AT91_SSC_FSDEN)
+			| (( AT91_SSC_FSOS_NEGATIVE	     ) & AT91_SSC_FSOS)
+			| (((bits - 1)			<< 16) & AT91_SSC_FSLEN)
+			| (((channels - 1)		<<  8) & AT91_SSC_DATNB)
+			| (( 1				<<  7) & AT91_SSC_MSBF)
+			| (( 0				<<  5) & AT91_SSC_DATDEF)
+			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
+		break;
+
+	case SND_SOC_DAIFMT_CBM_CFM:
+
+		/*
+		 * CODEC supplies BCLK and LRC clocks.
+		 *
+		 * The SSC transmit clock is obtained from the BCLK signal on
+		 * on the TK line, and the SSC receive clock is generated from the
+		 * transmit clock.
+		 *
+		 * For single channel data, one sample is transferred on the falling
+		 * edge of the LRC clock.  For two channel data, one sample is
+		 * transferred on both edges of the LRC clock.
+		 */
+		start_event = channels == 1
+				? AT91_SSC_START_FALLING_RF
+				: AT91_SSC_START_EDGE_RF;
+
+		rcmr =	  (( 0				<< 24) & AT91_SSC_PERIOD)
+			| (( 1				<< 16) & AT91_SSC_STTDLY)
+			| (( start_event		     ) & AT91_SSC_START)
+			| (( AT91_SSC_CK_RISING		     ) & AT91_SSC_CKI)
+			| (( AT91_SSC_CKO_NONE		     ) & AT91_SSC_CKO)
+			| (( AT91_SSC_CKS_CLOCK		     ) & AT91_SSC_CKS);
+
+		rfmr =	  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
+			| (( AT91_SSC_FSOS_NONE		     ) & AT91_SSC_FSOS)
+			| (( 0				<< 16) & AT91_SSC_FSLEN)
+			| (( 0				<<  8) & AT91_SSC_DATNB)
+			| (( 1				<<  7) & AT91_SSC_MSBF)
+			| (( 0				<<  5) & AT91_SSC_LOOP)
+			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
+
+		tcmr =	  (( 0				<< 24) & AT91_SSC_PERIOD)
+			| (( 1				<< 16) & AT91_SSC_STTDLY)
+			| (( start_event		     ) & AT91_SSC_START)
+			| (( AT91_SSC_CKI_FALLING	     ) & AT91_SSC_CKI)
+			| (( AT91_SSC_CKO_NONE		     ) & AT91_SSC_CKO)
+			| (( AT91_SSC_CKS_PIN		     ) & AT91_SSC_CKS);
+
+		tfmr =	  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
+			| (( 0				<< 23) & AT91_SSC_FSDEN)
+			| (( AT91_SSC_FSOS_NONE		     ) & AT91_SSC_FSOS)
+			| (( 0				<< 16) & AT91_SSC_FSLEN)
+			| (( 0				<<  8) & AT91_SSC_DATNB)
+			| (( 1				<<  7) & AT91_SSC_MSBF)
+			| (( 0				<<  5) & AT91_SSC_DATDEF)
+			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
+		break;
+
+	case SND_SOC_DAIFMT_CBS_CFM:
+	case SND_SOC_DAIFMT_CBM_CFS:
+	default:
+		printk(KERN_WARNING "at91-i2s: unsupported DAI format 0x%x.\n",
+			ssc_p->daifmt);
+		return -EINVAL;
+		break;
+	}
+	DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr);
+
+	if (!ssc_p->initialized) {
+
+		/* Enable PMC peripheral clock for this SSC */
+		DBG("Starting pid %d clock\n", ssc_p->ssc.pid);
+		at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
+
+		/* Reset the SSC and its PDC registers */
+		at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
+
+		at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RPR, 0);
+		at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RCR, 0);
+		at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNPR, 0);
+		at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNCR, 0);
+		at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TPR, 0);
+		at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TCR, 0);
+		at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0);
+		at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0);
+
+		if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt,
+					0, ssc_p->name, ssc_p)) < 0) {
+			printk(KERN_WARNING "at91-i2s: request_irq failure\n");
+
+			DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
+			at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
+			return ret;
+		}
+
+		ssc_p->initialized = 1;
+	}
+
+	/* set SSC clock mode register */
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div);
+
+	/* set receive clock mode and format */
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr);
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr);
+
+	/* set transmit clock mode and format */
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr);
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr);
+
+	DBG("hw_params: SSC initialized\n");
+	return 0;
+}
+
+
+static int at91_i2s_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+	struct at91_pcm_dma_params *dma_params;
+	int dir;
+
+	dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
+	dma_params = ssc_p->dma_params[dir];
+
+	at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
+			dma_params->mask->ssc_enable);
+
+	DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit",
+		at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR));
+	return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int at91_i2s_suspend(struct platform_device *pdev,
+	struct snd_soc_cpu_dai *cpu_dai)
+{
+	struct at91_ssc_info *ssc_p;
+
+	if(!cpu_dai->active)
+		return 0;
+
+	ssc_p = &ssc_info[cpu_dai->id];
+
+	/* Save the status register before disabling transmit and receive. */
+	ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR);
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
+			AT91_SSC_TXDIS | AT91_SSC_RXDIS);
+
+	/* Save the current interrupt mask, then disable unmasked interrupts. */
+	ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr);
+
+	ssc_p->ssc_state.ssc_cmr  = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR);
+	ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR);
+	ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR);
+	ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR);
+	ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR);
+
+	return 0;
+}
+
+static int at91_i2s_resume(struct platform_device *pdev,
+	struct snd_soc_cpu_dai *cpu_dai)
+{
+	struct at91_ssc_info *ssc_p;
+
+	if(!cpu_dai->active)
+		return 0;
+
+	ssc_p = &ssc_info[cpu_dai->id];
+
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr);
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr);
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr);
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr);
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR,  ssc_p->ssc_state.ssc_cmr);
+
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER,  ssc_p->ssc_state.ssc_imr);
+
+	at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
+		((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
+		((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
+
+	return 0;
+}
+
+#else
+#define at91_i2s_suspend	NULL
+#define at91_i2s_resume		NULL
+#endif
+
+#define AT91_I2S_RATES (SNDRV_PCM_RATE_8000  | SNDRV_PCM_RATE_11025 |\
+			SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
+			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
+			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
+			SNDRV_PCM_RATE_96000)
+
+struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = {
+	{	.name = "at91_ssc0/i2s",
+		.id = 0,
+		.type = SND_SOC_DAI_I2S,
+		.suspend = at91_i2s_suspend,
+		.resume = at91_i2s_resume,
+		.playback = {
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = AT91_I2S_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+		.capture = {
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = AT91_I2S_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+		.ops = {
+			.startup = at91_i2s_startup,
+			.shutdown = at91_i2s_shutdown,
+			.prepare = at91_i2s_prepare,
+			.hw_params = at91_i2s_hw_params,},
+		.dai_ops = {
+			.set_sysclk = at91_i2s_set_dai_sysclk,
+			.set_fmt = at91_i2s_set_dai_fmt,
+			.set_clkdiv = at91_i2s_set_dai_clkdiv,},
+		.private_data = &ssc_info[0].ssc,
+	},
+#if NUM_SSC_DEVICES == 3
+	{	.name = "at91_ssc1/i2s",
+		.id = 1,
+		.type = SND_SOC_DAI_I2S,
+		.suspend = at91_i2s_suspend,
+		.resume = at91_i2s_resume,
+		.playback = {
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = AT91_I2S_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+		.capture = {
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = AT91_I2S_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+		.ops = {
+			.startup = at91_i2s_startup,
+			.shutdown = at91_i2s_shutdown,
+			.prepare = at91_i2s_prepare,
+			.hw_params = at91_i2s_hw_params,},
+		.dai_ops = {
+			.set_sysclk = at91_i2s_set_dai_sysclk,
+			.set_fmt = at91_i2s_set_dai_fmt,
+			.set_clkdiv = at91_i2s_set_dai_clkdiv,},
+		.private_data = &ssc_info[1].ssc,
+	},
+	{	.name = "at91_ssc2/i2s",
+		.id = 2,
+		.type = SND_SOC_DAI_I2S,
+		.suspend = at91_i2s_suspend,
+		.resume = at91_i2s_resume,
+		.playback = {
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = AT91_I2S_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+		.capture = {
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = AT91_I2S_RATES,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+		.ops = {
+			.startup = at91_i2s_startup,
+			.shutdown = at91_i2s_shutdown,
+			.prepare = at91_i2s_prepare,
+			.hw_params = at91_i2s_hw_params,},
+		.dai_ops = {
+			.set_sysclk = at91_i2s_set_dai_sysclk,
+			.set_fmt = at91_i2s_set_dai_fmt,
+			.set_clkdiv = at91_i2s_set_dai_clkdiv,},
+		.private_data = &ssc_info[2].ssc,
+	},
+#endif
+};
+
+EXPORT_SYMBOL_GPL(at91_i2s_dai);
+
+/* Module information */
+MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
+MODULE_DESCRIPTION("AT91 I2S ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-i2s.h b/sound/soc/at91/at91-i2s.h
new file mode 100644
index 0000000..f8a875b
--- /dev/null
+++ b/sound/soc/at91/at91-i2s.h
@@ -0,0 +1,27 @@
+/*
+ * at91-i2s.h - ALSA I2S interface for the Atmel AT91 SoC
+ *
+ * Author:	Frank Mandarino <fmandarino@endrelia.com>
+ *		Endrelia Technologies Inc.
+ * Created:	Jan 9, 2007
+ *
+ * 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 _AT91_I2S_H
+#define _AT91_I2S_H
+
+/* I2S system clock ids */
+#define AT91_SYSCLK_MCK		0 /* SSC uses AT91 MCK as system clock */
+
+/* I2S divider ids */
+#define AT91SSC_CMR_DIV		0 /* MCK divider for BCLK */
+#define AT91SSC_TCMR_PERIOD	1 /* BCLK divider for transmit FS */
+#define AT91SSC_RCMR_PERIOD	2 /* BCLK divider for receive FS */
+
+extern struct snd_soc_cpu_dai at91_i2s_dai[];
+
+#endif /* _AT91_I2S_H */
+
diff --git a/sound/soc/at91/at91-pcm.c b/sound/soc/at91/at91-pcm.c
new file mode 100644
index 0000000..b39b95a
--- /dev/null
+++ b/sound/soc/at91/at91-pcm.c
@@ -0,0 +1,432 @@
+/*
+ * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC
+ *
+ * Author:	Frank Mandarino <fmandarino@endrelia.com>
+ *		Endrelia Technologies Inc.
+ * Created:	Mar 3, 2006
+ *
+ * Based on pxa2xx-pcm.c by:
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Nov 30, 2004
+ * Copyright:	(C) 2004 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/atmel_pdc.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_ssc.h>
+
+#include "at91-pcm.h"
+
+#if 0
+#define	DBG(x...)	printk(KERN_INFO "at91-pcm: " x)
+#else
+#define	DBG(x...)
+#endif
+
+static const struct snd_pcm_hardware at91_pcm_hardware = {
+	.info			= SNDRV_PCM_INFO_MMAP |
+				  SNDRV_PCM_INFO_MMAP_VALID |
+				  SNDRV_PCM_INFO_INTERLEAVED |
+				  SNDRV_PCM_INFO_PAUSE,
+	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
+	.period_bytes_min	= 32,
+	.period_bytes_max	= 8192,
+	.periods_min		= 2,
+	.periods_max		= 1024,
+	.buffer_bytes_max	= 32 * 1024,
+};
+
+struct at91_runtime_data {
+	struct at91_pcm_dma_params *params;
+	dma_addr_t dma_buffer;			/* physical address of dma buffer */
+	dma_addr_t dma_buffer_end;		/* first address beyond DMA buffer */
+	size_t period_size;
+	dma_addr_t period_ptr;			/* physical address of next period */
+	u32 pdc_xpr_save;			/* PDC register save */
+	u32 pdc_xcr_save;
+	u32 pdc_xnpr_save;
+	u32 pdc_xncr_save;
+};
+
+static void at91_pcm_dma_irq(u32 ssc_sr,
+	struct snd_pcm_substream *substream)
+{
+	struct at91_runtime_data *prtd = substream->runtime->private_data;
+	struct at91_pcm_dma_params *params = prtd->params;
+	static int count = 0;
+
+	count++;
+
+	if (ssc_sr & params->mask->ssc_endbuf) {
+
+		printk(KERN_WARNING
+			"at91-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
+			substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+				? "underrun" : "overrun",
+			params->name, ssc_sr, count);
+
+		/* re-start the PDC */
+		at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
+
+		prtd->period_ptr += prtd->period_size;
+		if (prtd->period_ptr >= prtd->dma_buffer_end) {
+			prtd->period_ptr = prtd->dma_buffer;
+		}
+
+		at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
+		at91_ssc_write(params->ssc_base + params->pdc->xcr,
+				prtd->period_size / params->pdc_xfer_size);
+
+		at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
+	}
+
+	if (ssc_sr & params->mask->ssc_endx) {
+
+		/* Load the PDC next pointer and counter registers */
+		prtd->period_ptr += prtd->period_size;
+		if (prtd->period_ptr >= prtd->dma_buffer_end) {
+			prtd->period_ptr = prtd->dma_buffer;
+		}
+		at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
+		at91_ssc_write(params->ssc_base + params->pdc->xncr,
+				prtd->period_size / params->pdc_xfer_size);
+	}
+
+	snd_pcm_period_elapsed(substream);
+}
+
+static int at91_pcm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct at91_runtime_data *prtd = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	/* this may get called several times by oss emulation
+	 * with different params */
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+	runtime->dma_bytes = params_buffer_bytes(params);
+
+	prtd->params = rtd->dai->cpu_dai->dma_data;
+	prtd->params->dma_intr_handler = at91_pcm_dma_irq;
+
+	prtd->dma_buffer = runtime->dma_addr;
+	prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
+	prtd->period_size = params_period_bytes(params);
+
+	DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n",
+		prtd->params->name, runtime->dma_bytes, prtd->period_size);
+	return 0;
+}
+
+static int at91_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct at91_runtime_data *prtd = substream->runtime->private_data;
+	struct at91_pcm_dma_params *params = prtd->params;
+
+	if (params != NULL) {
+		at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
+		prtd->params->dma_intr_handler = NULL;
+	}
+
+	return 0;
+}
+
+static int at91_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct at91_runtime_data *prtd = substream->runtime->private_data;
+	struct at91_pcm_dma_params *params = prtd->params;
+
+	at91_ssc_write(params->ssc_base + AT91_SSC_IDR,
+			params->mask->ssc_endx | params->mask->ssc_endbuf);
+
+	at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
+	return 0;
+}
+
+static int at91_pcm_trigger(struct snd_pcm_substream *substream,
+	int cmd)
+{
+	struct at91_runtime_data *prtd = substream->runtime->private_data;
+	struct at91_pcm_dma_params *params = prtd->params;
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		prtd->period_ptr = prtd->dma_buffer;
+
+		at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
+		at91_ssc_write(params->ssc_base + params->pdc->xcr,
+				prtd->period_size / params->pdc_xfer_size);
+
+		prtd->period_ptr += prtd->period_size;
+		at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
+		at91_ssc_write(params->ssc_base + params->pdc->xncr,
+				prtd->period_size / params->pdc_xfer_size);
+
+		DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n",
+			(unsigned long) prtd->period_ptr,
+			at91_ssc_read(params->ssc_base + params->pdc->xpr),
+			at91_ssc_read(params->ssc_base + params->pdc->xcr),
+			at91_ssc_read(params->ssc_base + params->pdc->xnpr),
+			at91_ssc_read(params->ssc_base + params->pdc->xncr));
+
+		at91_ssc_write(params->ssc_base + AT91_SSC_IER,
+			params->mask->ssc_endx | params->mask->ssc_endbuf);
+
+		at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
+
+		DBG("sr=%lx imr=%lx\n", at91_ssc_read(params->ssc_base + AT91_SSC_SR),
+					at91_ssc_read(params->ssc_base + AT91_SSC_IER));
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
+		break;
+
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static snd_pcm_uframes_t at91_pcm_pointer(
+	struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct at91_runtime_data *prtd = runtime->private_data;
+	struct at91_pcm_dma_params *params = prtd->params;
+	dma_addr_t ptr;
+	snd_pcm_uframes_t x;
+
+	ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr);
+	x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
+
+	if (x == runtime->buffer_size)
+		x = 0;
+	return x;
+}
+
+static int at91_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct at91_runtime_data *prtd;
+	int ret = 0;
+
+	snd_soc_set_runtime_hwparams(substream, &at91_pcm_hardware);
+
+	/* ensure that buffer size is a multiple of period size */
+	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		goto out;
+
+	prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL);
+	if (prtd == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	runtime->private_data = prtd;
+
+ out:
+	return ret;
+}
+
+static int at91_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct at91_runtime_data *prtd = substream->runtime->private_data;
+
+	kfree(prtd);
+	return 0;
+}
+
+static int at91_pcm_mmap(struct snd_pcm_substream *substream,
+	struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+				     runtime->dma_area,
+				     runtime->dma_addr,
+				     runtime->dma_bytes);
+}
+
+struct snd_pcm_ops at91_pcm_ops = {
+	.open		= at91_pcm_open,
+	.close		= at91_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= at91_pcm_hw_params,
+	.hw_free	= at91_pcm_hw_free,
+	.prepare	= at91_pcm_prepare,
+	.trigger	= at91_pcm_trigger,
+	.pointer	= at91_pcm_pointer,
+	.mmap		= at91_pcm_mmap,
+};
+
+static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
+	int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size = at91_pcm_hardware.buffer_bytes_max;
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+					   &buf->addr, GFP_KERNEL);
+
+	DBG("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
+		(void *) buf->area,
+		(void *) buf->addr,
+		size);
+
+	if (!buf->area)
+		return -ENOMEM;
+
+	buf->bytes = size;
+	return 0;
+}
+
+static u64 at91_pcm_dmamask = 0xffffffff;
+
+static int at91_pcm_new(struct snd_card *card,
+	struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
+{
+	int ret = 0;
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &at91_pcm_dmamask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = 0xffffffff;
+
+	if (dai->playback.channels_min) {
+		ret = at91_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret)
+			goto out;
+	}
+
+	if (dai->capture.channels_min) {
+		ret = at91_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_CAPTURE);
+		if (ret)
+			goto out;
+	}
+ out:
+	return ret;
+}
+
+static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+	int stream;
+
+	for (stream = 0; stream < 2; stream++) {
+		substream = pcm->streams[stream].substream;
+		if (!substream)
+			continue;
+
+		buf = &substream->dma_buffer;
+		if (!buf->area)
+			continue;
+
+		dma_free_writecombine(pcm->card->dev, buf->bytes,
+				      buf->area, buf->addr);
+		buf->area = NULL;
+	}
+}
+
+#ifdef CONFIG_PM
+static int at91_pcm_suspend(struct platform_device *pdev,
+	struct snd_soc_cpu_dai *dai)
+{
+	struct snd_pcm_runtime *runtime = dai->runtime;
+	struct at91_runtime_data *prtd;
+	struct at91_pcm_dma_params *params;
+
+	if (!runtime)
+		return 0;
+
+	prtd = runtime->private_data;
+	params = prtd->params;
+
+	/* disable the PDC and save the PDC registers */
+
+	at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
+
+	prtd->pdc_xpr_save  = at91_ssc_read(params->ssc_base + params->pdc->xpr);
+	prtd->pdc_xcr_save  = at91_ssc_read(params->ssc_base + params->pdc->xcr);
+	prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr);
+	prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr);
+
+	return 0;
+}
+
+static int at91_pcm_resume(struct platform_device *pdev,
+	struct snd_soc_cpu_dai *dai)
+{
+	struct snd_pcm_runtime *runtime = dai->runtime;
+	struct at91_runtime_data *prtd;
+	struct at91_pcm_dma_params *params;
+
+	if (!runtime)
+		return 0;
+
+	prtd = runtime->private_data;
+	params = prtd->params;
+
+	/* restore the PDC registers and enable the PDC */
+	at91_ssc_write(params->ssc_base + params->pdc->xpr,  prtd->pdc_xpr_save);
+	at91_ssc_write(params->ssc_base + params->pdc->xcr,  prtd->pdc_xcr_save);
+	at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save);
+	at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save);
+
+	at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
+	return 0;
+}
+#else
+#define at91_pcm_suspend	NULL
+#define at91_pcm_resume		NULL
+#endif
+
+struct snd_soc_platform at91_soc_platform = {
+	.name		= "at91-audio",
+	.pcm_ops 	= &at91_pcm_ops,
+	.pcm_new	= at91_pcm_new,
+	.pcm_free	= at91_pcm_free_dma_buffers,
+	.suspend	= at91_pcm_suspend,
+	.resume		= at91_pcm_resume,
+};
+
+EXPORT_SYMBOL_GPL(at91_soc_platform);
+
+MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
+MODULE_DESCRIPTION("Atmel AT91 PCM module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-pcm.h b/sound/soc/at91/at91-pcm.h
new file mode 100644
index 0000000..58d0f00
--- /dev/null
+++ b/sound/soc/at91/at91-pcm.h
@@ -0,0 +1,72 @@
+/*
+ * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC
+ *
+ * Author:	Frank Mandarino <fmandarino@endrelia.com>
+ *		Endrelia Technologies Inc.
+ * Created:	Mar 3, 2006
+ *
+ * Based on pxa2xx-pcm.h by:
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Nov 30, 2004
+ * Copyright:	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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _AT91_PCM_H
+#define _AT91_PCM_H
+
+#include <asm/arch/hardware.h>
+
+struct at91_ssc_periph {
+	void __iomem	*base;
+	u32		pid;
+};
+
+/*
+ * Registers and status bits that are required by the PCM driver.
+ */
+struct at91_pdc_regs {
+	unsigned int	xpr;		/* PDC recv/trans pointer */
+	unsigned int	xcr;		/* PDC recv/trans counter */
+	unsigned int	xnpr;		/* PDC next recv/trans pointer */
+	unsigned int	xncr;		/* PDC next recv/trans counter */
+	unsigned int	ptcr;		/* PDC transfer control */
+};
+
+struct at91_ssc_mask {
+	u32	ssc_enable;		/* SSC recv/trans enable */
+	u32	ssc_disable;		/* SSC recv/trans disable */
+	u32	ssc_endx;		/* SSC ENDTX or ENDRX */
+	u32	ssc_endbuf;		/* SSC TXBUFE or RXBUFF */
+	u32	pdc_enable;		/* PDC recv/trans enable */
+	u32	pdc_disable;		/* PDC recv/trans disable */
+};
+
+/*
+ * This structure, shared between the PCM driver and the interface,
+ * contains all information required by the PCM driver to perform the
+ * PDC DMA operation.  All fields except dma_intr_handler() are initialized
+ * by the interface.  The dms_intr_handler() pointer is set by the PCM
+ * driver and called by the interface SSC interrupt handler if it is
+ * non-NULL.
+ */
+struct at91_pcm_dma_params {
+	char *name;			/* stream identifier */
+	int pdc_xfer_size;		/* PDC counter increment in bytes */
+	void __iomem *ssc_base;		/* SSC base address */
+	struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */
+	struct at91_ssc_mask *mask;/* SSC & PDC status bits */
+	struct snd_pcm_substream *substream;
+	void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
+};
+
+extern struct snd_soc_platform at91_soc_platform;
+
+#define at91_ssc_read(a)	((unsigned long) __raw_readl(a))
+#define at91_ssc_write(a,v)	__raw_writel((v),(a))
+
+#endif /* _AT91_PCM_H */
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
new file mode 100644
index 0000000..8179df3
--- /dev/null
+++ b/sound/soc/at91/eti_b1_wm8731.c
@@ -0,0 +1,375 @@
+/*
+ * eti_b1_wm8731  --  SoC audio for AT91RM9200-based Endrelia ETI_B1 board.
+ *
+ * Author:	Frank Mandarino <fmandarino@endrelia.com>
+ *		Endrelia Technologies Inc.
+ * Created:	Mar 29, 2006
+ *
+ * Based on corgi.c by:
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *          Richard Purdie <richard@openedhand.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pio.h>
+#include <asm/arch/gpio.h>
+
+#include "../codecs/wm8731.h"
+#include "at91-pcm.h"
+#include "at91-i2s.h"
+
+#if 0
+#define	DBG(x...)	printk(KERN_INFO "eti_b1_wm8731: " x)
+#else
+#define	DBG(x...)
+#endif
+
+#define AT91_PIO_TF1	(1 << (AT91_PIN_PB6 - PIN_BASE) % 32)
+#define AT91_PIO_TK1	(1 << (AT91_PIN_PB7 - PIN_BASE) % 32)
+#define AT91_PIO_TD1	(1 << (AT91_PIN_PB8 - PIN_BASE) % 32)
+#define AT91_PIO_RD1	(1 << (AT91_PIN_PB9 - PIN_BASE) % 32)
+#define AT91_PIO_RK1	(1 << (AT91_PIN_PB10 - PIN_BASE) % 32)
+#define AT91_PIO_RF1	(1 << (AT91_PIN_PB11 - PIN_BASE) % 32)
+
+static struct clk *pck1_clk;
+static struct clk *pllb_clk;
+
+
+static int eti_b1_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	int ret;
+
+	/* cpu clock is the AT91 master clock sent to the SSC */
+	ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
+		60000000, SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	/* codec system clock is supplied by PCK1, set to 12MHz */
+	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK,
+		12000000, SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	/* Start PCK1 clock. */
+	clk_enable(pck1_clk);
+	DBG("pck1 started\n");
+
+	return 0;
+}
+
+static void eti_b1_shutdown(struct snd_pcm_substream *substream)
+{
+	/* Stop PCK1 clock. */
+	clk_disable(pck1_clk);
+	DBG("pck1 stopped\n");
+}
+
+static int eti_b1_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	int ret;
+
+#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
+	unsigned int rate;
+	int cmr_div, period;
+
+	/* set codec DAI configuration */
+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* set cpu DAI configuration */
+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * The SSC clock dividers depend on the sample rate.  The CMR.DIV
+	 * field divides the system master clock MCK to drive the SSC TK
+	 * signal which provides the codec BCLK.  The TCMR.PERIOD and
+	 * RCMR.PERIOD fields further divide the BCLK signal to drive
+	 * the SSC TF and RF signals which provide the codec DACLRC and
+	 * ADCLRC clocks.
+	 *
+	 * The dividers were determined through trial and error, where a
+	 * CMR.DIV value is chosen such that the resulting BCLK value is
+	 * divisible, or almost divisible, by (2 * sample rate), and then
+	 * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
+	 */
+	rate = params_rate(params);
+
+	switch (rate) {
+	case 8000:
+		cmr_div = 25;	/* BCLK = 60MHz/(2*25) = 1.2MHz */
+		period = 74;	/* LRC = BCLK/(2*(74+1)) = 8000Hz */
+		break;
+	case 32000:
+		cmr_div = 7;	/* BCLK = 60MHz/(2*7) ~= 4.28571428MHz */
+		period = 66;	/* LRC = BCLK/(2*(66+1)) = 31982.942Hz */
+		break;
+	case 48000:
+		cmr_div = 13;	/* BCLK = 60MHz/(2*13) ~= 2.3076923MHz */
+		period = 23;	/* LRC = BCLK/(2*(23+1)) = 48076.923Hz */
+		break;
+	default:
+		printk(KERN_WARNING "unsupported rate %d on ETI-B1 board\n", rate);
+		return -EINVAL;
+	}
+
+	/* set the MCK divider for BCLK */
+	ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
+	if (ret < 0)
+		return ret;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* set the BCLK divider for DACLRC */
+		ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai,
+						AT91SSC_TCMR_PERIOD, period);
+	} else {
+		/* set the BCLK divider for ADCLRC */
+		ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai,
+						AT91SSC_RCMR_PERIOD, period);
+	}
+	if (ret < 0)
+		return ret;
+
+#else /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
+	/*
+	 * Codec in Master Mode.
+	 */
+
+	/* set codec DAI configuration */
+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+	if (ret < 0)
+		return ret;
+
+	/* set cpu DAI configuration */
+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+	if (ret < 0)
+		return ret;
+
+#endif /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
+
+	return 0;
+}
+
+static struct snd_soc_ops eti_b1_ops = {
+	.startup = eti_b1_startup,
+	.hw_params = eti_b1_hw_params,
+	.shutdown = eti_b1_shutdown,
+};
+
+
+static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Int Mic", NULL),
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static const char *intercon[][3] = {
+
+	/* speaker connected to LHPOUT */
+	{"Ext Spk", NULL, "LHPOUT"},
+
+	/* mic is connected to Mic Jack, with WM8731 Mic Bias */
+	{"MICIN", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Int Mic"},
+
+	/* terminator */
+	{NULL, NULL, NULL},
+};
+
+/*
+ * Logic for a wm8731 as connected on a Endrelia ETI-B1 board.
+ */
+static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
+{
+	int i;
+
+	DBG("eti_b1_wm8731_init() called\n");
+
+	/* Add specific widgets */
+	for(i = 0; i < ARRAY_SIZE(eti_b1_dapm_widgets); i++) {
+		snd_soc_dapm_new_control(codec, &eti_b1_dapm_widgets[i]);
+	}
+
+	/* Set up specific audio path interconnects */
+	for(i = 0; intercon[i][0] != NULL; i++) {
+		snd_soc_dapm_connect_input(codec, intercon[i][0],
+			intercon[i][1], intercon[i][2]);
+	}
+
+	/* not connected */
+	snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
+	snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
+
+	/* always connected */
+	snd_soc_dapm_set_endpoint(codec, "Int Mic", 1);
+	snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
+
+	snd_soc_dapm_sync_endpoints(codec);
+
+	return 0;
+}
+
+static struct snd_soc_dai_link eti_b1_dai = {
+	.name = "WM8731",
+	.stream_name = "WM8731",
+	.cpu_dai = &at91_i2s_dai[1],
+	.codec_dai = &wm8731_dai,
+	.init = eti_b1_wm8731_init,
+	.ops = &eti_b1_ops,
+};
+
+static struct snd_soc_machine snd_soc_machine_eti_b1 = {
+	.name = "ETI_B1",
+	.dai_link = &eti_b1_dai,
+	.num_links = 1,
+};
+
+static struct wm8731_setup_data eti_b1_wm8731_setup = {
+	.i2c_address = 0x1a,
+};
+
+static struct snd_soc_device eti_b1_snd_devdata = {
+	.machine = &snd_soc_machine_eti_b1,
+	.platform = &at91_soc_platform,
+	.codec_dev = &soc_codec_dev_wm8731,
+	.codec_data = &eti_b1_wm8731_setup,
+};
+
+static struct platform_device *eti_b1_snd_device;
+
+static int __init eti_b1_init(void)
+{
+	int ret;
+	u32 ssc_pio_lines;
+	struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
+
+	if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
+		DBG("SSC1 memory region is busy\n");
+		return -EBUSY;
+	}
+
+	ssc->base = ioremap(AT91RM9200_BASE_SSC1, SZ_16K);
+	if (!ssc->base) {
+		DBG("SSC1 memory ioremap failed\n");
+		ret = -ENOMEM;
+		goto fail_release_mem;
+	}
+
+	ssc->pid = AT91RM9200_ID_SSC1;
+
+	eti_b1_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!eti_b1_snd_device) {
+		DBG("platform device allocation failed\n");
+		ret = -ENOMEM;
+		goto fail_io_unmap;
+	}
+
+	platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata);
+	eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev;
+
+	ret = platform_device_add(eti_b1_snd_device);
+	if (ret) {
+		DBG("platform device add failed\n");
+		platform_device_put(eti_b1_snd_device);
+		goto fail_io_unmap;
+	}
+
+ 	ssc_pio_lines = AT91_PIO_TF1 | AT91_PIO_TK1 | AT91_PIO_TD1
+			| AT91_PIO_RD1 /* | AT91_PIO_RK1 */ | AT91_PIO_RF1;
+
+	/* Reset all PIO registers and assign lines to peripheral A */
+ 	at91_sys_write(AT91_PIOB + PIO_PDR,  ssc_pio_lines);
+ 	at91_sys_write(AT91_PIOB + PIO_ODR,  ssc_pio_lines);
+ 	at91_sys_write(AT91_PIOB + PIO_IFDR, ssc_pio_lines);
+ 	at91_sys_write(AT91_PIOB + PIO_CODR, ssc_pio_lines);
+ 	at91_sys_write(AT91_PIOB + PIO_IDR,  ssc_pio_lines);
+ 	at91_sys_write(AT91_PIOB + PIO_MDDR, ssc_pio_lines);
+ 	at91_sys_write(AT91_PIOB + PIO_PUDR, ssc_pio_lines);
+ 	at91_sys_write(AT91_PIOB + PIO_ASR,  ssc_pio_lines);
+ 	at91_sys_write(AT91_PIOB + PIO_OWDR, ssc_pio_lines);
+
+	/*
+	 * Set PCK1 parent to PLLB and its rate to 12 Mhz.
+	 */
+	pllb_clk = clk_get(NULL, "pllb");
+	pck1_clk = clk_get(NULL, "pck1");
+
+	clk_set_parent(pck1_clk, pllb_clk);
+	clk_set_rate(pck1_clk, 12000000);
+
+	DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk));
+
+	/* assign the GPIO pin to PCK1 */
+	at91_set_B_periph(AT91_PIN_PA24, 0);
+
+#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
+	printk(KERN_INFO "eti_b1_wm8731: Codec in Slave Mode\n");
+#else
+	printk(KERN_INFO "eti_b1_wm8731: Codec in Master Mode\n");
+#endif
+	return ret;
+
+fail_io_unmap:
+	iounmap(ssc->base);
+fail_release_mem:
+	release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
+	return ret;
+}
+
+static void __exit eti_b1_exit(void)
+{
+	struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
+
+	clk_put(pck1_clk);
+	clk_put(pllb_clk);
+
+	platform_device_unregister(eti_b1_snd_device);
+
+	iounmap(ssc->base);
+	release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
+}
+
+module_init(eti_b1_init);
+module_exit(eti_b1_exit);
+
+/* Module information */
+MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
+MODULE_DESCRIPTION("ALSA SoC ETI-B1-WM8731");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
new file mode 100644
index 0000000..ec2a278
--- /dev/null
+++ b/sound/soc/codecs/Kconfig
@@ -0,0 +1,15 @@
+config SND_SOC_AC97_CODEC
+	tristate
+	depends on SND_SOC
+
+config SND_SOC_WM8731
+	tristate
+	depends on SND_SOC
+
+config SND_SOC_WM8750
+	tristate
+	depends on SND_SOC
+
+config SND_SOC_WM9712
+	tristate
+	depends on SND_SOC
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
new file mode 100644
index 0000000..3249a6e
--- /dev/null
+++ b/sound/soc/codecs/Makefile
@@ -0,0 +1,9 @@
+snd-soc-ac97-objs := ac97.o
+snd-soc-wm8731-objs := wm8731.o
+snd-soc-wm8750-objs := wm8750.o
+snd-soc-wm9712-objs := wm9712.o
+
+obj-$(CONFIG_SND_SOC_AC97_CODEC)	+= snd-soc-ac97.o
+obj-$(CONFIG_SND_SOC_WM8731)	+= snd-soc-wm8731.o
+obj-$(CONFIG_SND_SOC_WM8750)	+= snd-soc-wm8750.o
+obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
new file mode 100644
index 0000000..55bc55e
--- /dev/null
+++ b/sound/soc/codecs/ac97.c
@@ -0,0 +1,156 @@
+/*
+ * ac97.c  --  ALSA Soc AC97 codec support
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.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.
+ *
+ *  Revision history
+ *    17th Oct 2005   Initial version.
+ *
+ * Generic AC97 support.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#define AC97_VERSION "0.6"
+
+static int ac97_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+
+	int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+		  AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
+	return snd_ac97_set_rate(codec->ac97, reg, runtime->rate);
+}
+
+#define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+static struct snd_soc_codec_dai ac97_dai = {
+	.name = "AC97 HiFi",
+	.playback = {
+		.stream_name = "AC97 Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = STD_AC97_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.capture = {
+		.stream_name = "AC97 Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = STD_AC97_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.prepare = ac97_prepare,},
+};
+
+static unsigned int ac97_read(struct snd_soc_codec *codec,
+	unsigned int reg)
+{
+	return soc_ac97_ops.read(codec->ac97, reg);
+}
+
+static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int val)
+{
+	soc_ac97_ops.write(codec->ac97, reg, val);
+	return 0;
+}
+
+static int ac97_soc_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec;
+	struct snd_ac97_bus *ac97_bus;
+	struct snd_ac97_template ac97_template;
+	int ret = 0;
+
+	printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
+
+	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (socdev->codec == NULL)
+		return -ENOMEM;
+	codec = socdev->codec;
+	mutex_init(&codec->mutex);
+
+	codec->name = "AC97";
+	codec->owner = THIS_MODULE;
+	codec->dai = &ac97_dai;
+	codec->num_dai = 1;
+	codec->write = ac97_write;
+	codec->read = ac97_read;
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if(ret < 0)
+		goto err;
+
+	/* add codec as bus device for standard ac97 */
+	ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
+	if(ret < 0)
+		goto bus_err;
+
+	memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
+	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
+	if(ret < 0)
+		goto bus_err;
+
+	ret = snd_soc_register_card(socdev);
+	if (ret < 0)
+		goto bus_err;
+	return 0;
+
+bus_err:
+	snd_soc_free_pcms(socdev);
+
+err:
+	kfree(socdev->codec->reg_cache);
+	kfree(socdev->codec);
+	socdev->codec = NULL;
+	return ret;
+}
+
+static int ac97_soc_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	if(codec == NULL)
+		return 0;
+
+	snd_soc_free_pcms(socdev);
+	kfree(socdev->codec->reg_cache);
+	kfree(socdev->codec);
+
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_ac97= {
+	.probe = 	ac97_soc_probe,
+	.remove = 	ac97_soc_remove,
+};
+
+EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
+
+MODULE_DESCRIPTION("Soc Generic AC97 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h
new file mode 100644
index 0000000..930ddfc
--- /dev/null
+++ b/sound/soc/codecs/ac97.h
@@ -0,0 +1,18 @@
+/*
+ * linux/sound/codecs/ac97.h -- ALSA SoC Layer
+ *
+ * Author:		Liam Girdwood
+ * Created:		Dec 1st 2005
+ * Copyright:	Wolfson Microelectronics. PLC.
+ *
+ * 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 __LINUX_SND_SOC_AC97_H
+#define __LINUX_SND_SOC_AC97_H
+
+extern struct snd_soc_codec_device soc_codec_dev_ac97;
+
+#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
new file mode 100644
index 0000000..7ca0b52
--- /dev/null
+++ b/sound/soc/codecs/wm8731.c
@@ -0,0 +1,758 @@
+/*
+ * wm8731.c  --  WM8731 ALSA SoC Audio driver
+ *
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <richard@openedhand.com>
+ *
+ * Based on wm8753.c by Liam Girdwood
+ *
+ * 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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include "wm8731.h"
+
+#define AUDIO_NAME "wm8731"
+#define WM8731_VERSION "0.13"
+
+/*
+ * Debug
+ */
+
+#define WM8731_DEBUG 0
+
+#ifdef WM8731_DEBUG
+#define dbg(format, arg...) \
+	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+#define err(format, arg...) \
+	printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
+#define info(format, arg...) \
+	printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
+#define warn(format, arg...) \
+	printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
+
+struct snd_soc_codec_device soc_codec_dev_wm8731;
+
+/* codec private data */
+struct wm8731_priv {
+	unsigned int sysclk;
+};
+
+/*
+ * wm8731 register cache
+ * We can't read the WM8731 register space when we are
+ * using 2 wire for device control, so we cache them instead.
+ * There is no point in caching the reset register
+ */
+static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
+    0x0097, 0x0097, 0x0079, 0x0079,
+    0x000a, 0x0008, 0x009f, 0x000a,
+    0x0000, 0x0000
+};
+
+/*
+ * read wm8731 register cache
+ */
+static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec,
+	unsigned int reg)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg == WM8731_RESET)
+		return 0;
+	if (reg >= WM8731_CACHEREGNUM)
+		return -1;
+	return cache[reg];
+}
+
+/*
+ * write wm8731 register cache
+ */
+static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec,
+	u16 reg, unsigned int value)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg >= WM8731_CACHEREGNUM)
+		return;
+	cache[reg] = value;
+}
+
+/*
+ * write to the WM8731 register space
+ */
+static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int value)
+{
+	u8 data[2];
+
+	/* data is
+	 *   D15..D9 WM8731 register offset
+	 *   D8...D0 register data
+	 */
+	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+	data[1] = value & 0x00ff;
+
+	wm8731_write_reg_cache (codec, reg, value);
+	if (codec->hw_write(codec->control_data, data, 2) == 2)
+		return 0;
+	else
+		return -EIO;
+}
+
+#define wm8731_reset(c)	wm8731_write(c, WM8731_RESET, 0)
+
+static const char *wm8731_input_select[] = {"Line In", "Mic"};
+static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
+
+static const struct soc_enum wm8731_enum[] = {
+	SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select),
+	SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph),
+};
+
+static const struct snd_kcontrol_new wm8731_snd_controls[] = {
+
+SOC_DOUBLE_R("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V,
+	0, 127, 0),
+SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V,
+	7, 1, 0),
+
+SOC_DOUBLE_R("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0),
+SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1),
+
+SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
+SOC_SINGLE("Capture Mic Switch", WM8731_APANA, 1, 1, 1),
+
+SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1),
+
+SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
+SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
+
+SOC_ENUM("Playback De-emphasis", wm8731_enum[1]),
+};
+
+/* add non dapm controls */
+static int wm8731_add_controls(struct snd_soc_codec *codec)
+{
+	int err, i;
+
+	for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) {
+		if ((err = snd_ctl_add(codec->card,
+				snd_soc_cnew(&wm8731_snd_controls[i],codec, NULL))) < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+/* Output Mixer */
+static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = {
+SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
+SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
+SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
+};
+
+/* Input mux */
+static const struct snd_kcontrol_new wm8731_input_mux_controls =
+SOC_DAPM_ENUM("Input Select", wm8731_enum[0]);
+
+static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
+SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1,
+	&wm8731_output_mixer_controls[0],
+	ARRAY_SIZE(wm8731_output_mixer_controls)),
+SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8731_PWR, 3, 1),
+SND_SOC_DAPM_OUTPUT("LOUT"),
+SND_SOC_DAPM_OUTPUT("LHPOUT"),
+SND_SOC_DAPM_OUTPUT("ROUT"),
+SND_SOC_DAPM_OUTPUT("RHPOUT"),
+SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8731_PWR, 2, 1),
+SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &wm8731_input_mux_controls),
+SND_SOC_DAPM_PGA("Line Input", WM8731_PWR, 0, 1, NULL, 0),
+SND_SOC_DAPM_MICBIAS("Mic Bias", WM8731_PWR, 1, 1),
+SND_SOC_DAPM_INPUT("MICIN"),
+SND_SOC_DAPM_INPUT("RLINEIN"),
+SND_SOC_DAPM_INPUT("LLINEIN"),
+};
+
+static const char *intercon[][3] = {
+	/* output mixer */
+	{"Output Mixer", "Line Bypass Switch", "Line Input"},
+	{"Output Mixer", "HiFi Playback Switch", "DAC"},
+	{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
+
+	/* outputs */
+	{"RHPOUT", NULL, "Output Mixer"},
+	{"ROUT", NULL, "Output Mixer"},
+	{"LHPOUT", NULL, "Output Mixer"},
+	{"LOUT", NULL, "Output Mixer"},
+
+	/* input mux */
+	{"Input Mux", "Line In", "Line Input"},
+	{"Input Mux", "Mic", "Mic Bias"},
+	{"ADC", NULL, "Input Mux"},
+
+	/* inputs */
+	{"Line Input", NULL, "LLINEIN"},
+	{"Line Input", NULL, "RLINEIN"},
+	{"Mic Bias", NULL, "MICIN"},
+
+	/* terminator */
+	{NULL, NULL, NULL},
+};
+
+static int wm8731_add_widgets(struct snd_soc_codec *codec)
+{
+	int i;
+
+	for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
+		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+	}
+
+	/* set up audio path interconnects */
+	for(i = 0; intercon[i][0] != NULL; i++) {
+		snd_soc_dapm_connect_input(codec, intercon[i][0],
+			intercon[i][1], intercon[i][2]);
+	}
+
+	snd_soc_dapm_new_widgets(codec);
+	return 0;
+}
+
+struct _coeff_div {
+	u32 mclk;
+	u32 rate;
+	u16 fs;
+	u8 sr:4;
+	u8 bosr:1;
+	u8 usb:1;
+};
+
+/* codec mclk clock divider coefficients */
+static const struct _coeff_div coeff_div[] = {
+	/* 48k */
+	{12288000, 48000, 256, 0x0, 0x0, 0x0},
+	{18432000, 48000, 384, 0x0, 0x1, 0x0},
+	{12000000, 48000, 250, 0x0, 0x0, 0x1},
+
+	/* 32k */
+	{12288000, 32000, 384, 0x6, 0x0, 0x0},
+	{18432000, 32000, 576, 0x6, 0x1, 0x0},
+	{12000000, 32000, 375, 0x6, 0x0, 0x1},
+
+	/* 8k */
+	{12288000, 8000, 1536, 0x3, 0x0, 0x0},
+	{18432000, 8000, 2304, 0x3, 0x1, 0x0},
+	{11289600, 8000, 1408, 0xb, 0x0, 0x0},
+	{16934400, 8000, 2112, 0xb, 0x1, 0x0},
+	{12000000, 8000, 1500, 0x3, 0x0, 0x1},
+
+	/* 96k */
+	{12288000, 96000, 128, 0x7, 0x0, 0x0},
+	{18432000, 96000, 192, 0x7, 0x1, 0x0},
+	{12000000, 96000, 125, 0x7, 0x0, 0x1},
+
+	/* 44.1k */
+	{11289600, 44100, 256, 0x8, 0x0, 0x0},
+	{16934400, 44100, 384, 0x8, 0x1, 0x0},
+	{12000000, 44100, 272, 0x8, 0x1, 0x1},
+
+	/* 88.2k */
+	{11289600, 88200, 128, 0xf, 0x0, 0x0},
+	{16934400, 88200, 192, 0xf, 0x1, 0x0},
+	{12000000, 88200, 136, 0xf, 0x1, 0x1},
+};
+
+static inline int get_coeff(int mclk, int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+		if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
+			return i;
+	}
+	return 0;
+}
+
+static int wm8731_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+	struct wm8731_priv *wm8731 = codec->private_data;
+	u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3;
+	int i = get_coeff(wm8731->sysclk, params_rate(params));
+	u16 srate = (coeff_div[i].sr << 2) |
+		(coeff_div[i].bosr << 1) | coeff_div[i].usb;
+
+	wm8731_write(codec, WM8731_SRATE, srate);
+
+	/* bit size */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		iface |= 0x0004;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		iface |= 0x0008;
+		break;
+	}
+
+	wm8731_write(codec, WM8731_IFACE, iface);
+	return 0;
+}
+
+static int wm8731_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+
+	/* set active */
+	wm8731_write(codec, WM8731_ACTIVE, 0x0001);
+
+	return 0;
+}
+
+static void wm8731_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+
+	/* deactivate */
+	if (!codec->active) {
+		udelay(50);
+		wm8731_write(codec, WM8731_ACTIVE, 0x0);
+	}
+}
+
+static int wm8731_mute(struct snd_soc_codec_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7;
+
+	if (mute)
+		wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8);
+	else
+		wm8731_write(codec, WM8731_APDIGI, mute_reg);
+	return 0;
+}
+
+static int wm8731_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct wm8731_priv *wm8731 = codec->private_data;
+
+	switch (freq) {
+	case 11289600:
+	case 12000000:
+	case 12288000:
+	case 16934400:
+	case 18432000:
+		wm8731->sysclk = freq;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+
+static int wm8731_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 iface = 0;
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		iface |= 0x0040;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		iface |= 0x0002;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iface |= 0x0001;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		iface |= 0x0003;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		iface |= 0x0013;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		iface |= 0x0090;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		iface |= 0x0080;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		iface |= 0x0010;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set iface */
+	wm8731_write(codec, WM8731_IFACE, iface);
+	return 0;
+}
+
+static int wm8731_dapm_event(struct snd_soc_codec *codec, int event)
+{
+	u16 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f;
+
+	switch (event) {
+	case SNDRV_CTL_POWER_D0: /* full On */
+		/* vref/mid, osc on, dac unmute */
+		wm8731_write(codec, WM8731_PWR, reg);
+		break;
+	case SNDRV_CTL_POWER_D1: /* partial On */
+	case SNDRV_CTL_POWER_D2: /* partial On */
+		break;
+	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+		/* everything off except vref/vmid, */
+		wm8731_write(codec, WM8731_PWR, reg | 0x0040);
+		break;
+	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+		/* everything off, dac mute, inactive */
+		wm8731_write(codec, WM8731_ACTIVE, 0x0);
+		wm8731_write(codec, WM8731_PWR, 0xffff);
+		break;
+	}
+	codec->dapm_state = event;
+	return 0;
+}
+
+#define WM8731_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
+		SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
+		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
+		SNDRV_PCM_RATE_96000)
+
+#define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+	SNDRV_PCM_FMTBIT_S24_LE)
+
+struct snd_soc_codec_dai wm8731_dai = {
+	.name = "WM8731",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8731_RATES,
+		.formats = WM8731_FORMATS,},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8731_RATES,
+		.formats = WM8731_FORMATS,},
+	.ops = {
+		.prepare = wm8731_pcm_prepare,
+		.hw_params = wm8731_hw_params,
+		.shutdown = wm8731_shutdown,
+	},
+	.dai_ops = {
+		.digital_mute = wm8731_mute,
+		.set_sysclk = wm8731_set_dai_sysclk,
+		.set_fmt = wm8731_set_dai_fmt,
+	}
+};
+EXPORT_SYMBOL_GPL(wm8731_dai);
+
+static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	wm8731_write(codec, WM8731_ACTIVE, 0x0);
+	wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+	return 0;
+}
+
+static int wm8731_resume(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+	int i;
+	u8 data[2];
+	u16 *cache = codec->reg_cache;
+
+	/* Sync reg_cache with the hardware */
+	for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
+		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
+		data[1] = cache[i] & 0x00ff;
+		codec->hw_write(codec->control_data, data, 2);
+	}
+	wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+	wm8731_dapm_event(codec, codec->suspend_dapm_state);
+	return 0;
+}
+
+/*
+ * initialise the WM8731 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int wm8731_init(struct snd_soc_device *socdev)
+{
+	struct snd_soc_codec *codec = socdev->codec;
+	int reg, ret = 0;
+
+	codec->name = "WM8731";
+	codec->owner = THIS_MODULE;
+	codec->read = wm8731_read_reg_cache;
+	codec->write = wm8731_write;
+	codec->dapm_event = wm8731_dapm_event;
+	codec->dai = &wm8731_dai;
+	codec->num_dai = 1;
+	codec->reg_cache_size = sizeof(wm8731_reg);
+	codec->reg_cache = kmemdup(wm8731_reg, sizeof(wm8731_reg), GFP_KERNEL);
+	if (codec->reg_cache == NULL)
+		return -ENOMEM;
+
+	wm8731_reset(codec);
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0) {
+		printk(KERN_ERR "wm8731: failed to create pcms\n");
+		goto pcm_err;
+	}
+
+	/* power on device */
+	wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+	/* set the update bits */
+	reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
+	wm8731_write(codec, WM8731_LOUT1V, reg | 0x0100);
+	reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V);
+	wm8731_write(codec, WM8731_ROUT1V, reg | 0x0100);
+	reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
+	wm8731_write(codec, WM8731_LINVOL, reg | 0x0100);
+	reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
+	wm8731_write(codec, WM8731_RINVOL, reg | 0x0100);
+
+	wm8731_add_controls(codec);
+	wm8731_add_widgets(codec);
+	ret = snd_soc_register_card(socdev);
+	if (ret < 0) {
+		printk(KERN_ERR "wm8731: failed to register card\n");
+		goto card_err;
+	}
+
+	return ret;
+
+card_err:
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+pcm_err:
+	kfree(codec->reg_cache);
+	return ret;
+}
+
+static struct snd_soc_device *wm8731_socdev;
+
+#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+
+/*
+ * WM8731 2 wire address is determined by GPIO5
+ * state during powerup.
+ *    low  = 0x1a
+ *    high = 0x1b
+ */
+static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver wm8731_i2c_driver;
+static struct i2c_client client_template;
+
+/* If the i2c layer weren't so broken, we could pass this kind of data
+   around */
+
+static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct snd_soc_device *socdev = wm8731_socdev;
+	struct wm8731_setup_data *setup = socdev->codec_data;
+	struct snd_soc_codec *codec = socdev->codec;
+	struct i2c_client *i2c;
+	int ret;
+
+	if (addr != setup->i2c_address)
+		return -ENODEV;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+
+	i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
+	if (i2c == NULL) {
+		kfree(codec);
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(i2c, codec);
+	codec->control_data = i2c;
+
+	ret = i2c_attach_client(i2c);
+	if (ret < 0) {
+		err("failed to attach codec at addr %x\n", addr);
+		goto err;
+	}
+
+	ret = wm8731_init(socdev);
+	if (ret < 0) {
+		err("failed to initialise WM8731\n");
+		goto err;
+	}
+	return ret;
+
+err:
+	kfree(codec);
+	kfree(i2c);
+	return ret;
+}
+
+static int wm8731_i2c_detach(struct i2c_client *client)
+{
+	struct snd_soc_codec* codec = i2c_get_clientdata(client);
+	i2c_detach_client(client);
+	kfree(codec->reg_cache);
+	kfree(client);
+	return 0;
+}
+
+static int wm8731_i2c_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, wm8731_codec_probe);
+}
+
+/* corgi i2c codec control layer */
+static struct i2c_driver wm8731_i2c_driver = {
+	.driver = {
+		.name = "WM8731 I2C Codec",
+		.owner = THIS_MODULE,
+	},
+	.id =             I2C_DRIVERID_WM8731,
+	.attach_adapter = wm8731_i2c_attach,
+	.detach_client =  wm8731_i2c_detach,
+	.command =        NULL,
+};
+
+static struct i2c_client client_template = {
+	.name =   "WM8731",
+	.driver = &wm8731_i2c_driver,
+};
+#endif
+
+static int wm8731_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct wm8731_setup_data *setup;
+	struct snd_soc_codec *codec;
+	struct wm8731_priv *wm8731;
+	int ret = 0;
+
+	info("WM8731 Audio Codec %s", WM8731_VERSION);
+
+	setup = socdev->codec_data;
+	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (codec == NULL)
+		return -ENOMEM;
+
+	wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
+	if (wm8731 == NULL) {
+		kfree(codec);
+		return -ENOMEM;
+	}
+
+	codec->private_data = wm8731;
+	socdev->codec = codec;
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	wm8731_socdev = socdev;
+#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+	if (setup->i2c_address) {
+		normal_i2c[0] = setup->i2c_address;
+		codec->hw_write = (hw_write_t)i2c_master_send;
+		ret = i2c_add_driver(&wm8731_i2c_driver);
+		if (ret != 0)
+			printk(KERN_ERR "can't add i2c driver");
+	}
+#else
+	/* Add other interfaces here */
+#endif
+	return ret;
+}
+
+/* power down chip */
+static int wm8731_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	if (codec->control_data)
+		wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+	i2c_del_driver(&wm8731_i2c_driver);
+#endif
+	kfree(codec->private_data);
+	kfree(codec);
+
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8731 = {
+	.probe = 	wm8731_probe,
+	.remove = 	wm8731_remove,
+	.suspend = 	wm8731_suspend,
+	.resume =	wm8731_resume,
+};
+
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
+
+MODULE_DESCRIPTION("ASoC WM8731 driver");
+MODULE_AUTHOR("Richard Purdie");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h
new file mode 100644
index 0000000..5bcab6a
--- /dev/null
+++ b/sound/soc/codecs/wm8731.h
@@ -0,0 +1,44 @@
+/*
+ * wm8731.h  --  WM8731 Soc Audio driver
+ *
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <richard@openedhand.com>
+ *
+ * Based on wm8753.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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8731_H
+#define _WM8731_H
+
+/* WM8731 register space */
+
+#define WM8731_LINVOL   0x00
+#define WM8731_RINVOL   0x01
+#define WM8731_LOUT1V   0x02
+#define WM8731_ROUT1V   0x03
+#define WM8731_APANA    0x04
+#define WM8731_APDIGI   0x05
+#define WM8731_PWR      0x06
+#define WM8731_IFACE    0x07
+#define WM8731_SRATE    0x08
+#define WM8731_ACTIVE   0x09
+#define WM8731_RESET	0x0f
+
+#define WM8731_CACHEREGNUM 	10
+
+#define WM8731_SYSCLK	0
+#define WM8731_DAI		0
+
+struct wm8731_setup_data {
+	unsigned short i2c_address;
+};
+
+extern struct snd_soc_codec_dai wm8731_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8731;
+
+#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
new file mode 100644
index 0000000..7073e8e
--- /dev/null
+++ b/sound/soc/codecs/wm8750.c
@@ -0,0 +1,1049 @@
+/*
+ * wm8750.c -- WM8750 ALSA SoC audio driver
+ *
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <richard@openedhand.com>
+ *
+ * Based on WM8753.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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include "wm8750.h"
+
+#define AUDIO_NAME "WM8750"
+#define WM8750_VERSION "0.12"
+
+/*
+ * Debug
+ */
+
+#define WM8750_DEBUG 0
+
+#ifdef WM8750_DEBUG
+#define dbg(format, arg...) \
+	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+#define err(format, arg...) \
+	printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
+#define info(format, arg...) \
+	printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
+#define warn(format, arg...) \
+	printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
+
+/* codec private data */
+struct wm8750_priv {
+	unsigned int sysclk;
+};
+
+/*
+ * wm8750 register cache
+ * We can't read the WM8750 register space when we
+ * are using 2 wire for device control, so we cache them instead.
+ */
+static const u16 wm8750_reg[] = {
+	0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
+	0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
+	0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
+	0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
+	0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
+	0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
+	0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
+	0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
+	0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
+	0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
+	0x0079, 0x0079, 0x0079,          /* 40 */
+};
+
+/*
+ * read wm8750 register cache
+ */
+static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec *codec,
+	unsigned int reg)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg > WM8750_CACHE_REGNUM)
+		return -1;
+	return cache[reg];
+}
+
+/*
+ * write wm8750 register cache
+ */
+static inline void wm8750_write_reg_cache(struct snd_soc_codec *codec,
+	unsigned int reg, unsigned int value)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg > WM8750_CACHE_REGNUM)
+		return;
+	cache[reg] = value;
+}
+
+static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int value)
+{
+	u8 data[2];
+
+	/* data is
+	 *   D15..D9 WM8753 register offset
+	 *   D8...D0 register data
+	 */
+	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+	data[1] = value & 0x00ff;
+
+	wm8750_write_reg_cache (codec, reg, value);
+	if (codec->hw_write(codec->control_data, data, 2) == 2)
+		return 0;
+	else
+		return -EIO;
+}
+
+#define wm8750_reset(c)	wm8750_write(c, WM8750_RESET, 0)
+
+/*
+ * WM8750 Controls
+ */
+static const char *wm8750_bass[] = {"Linear Control", "Adaptive Boost"};
+static const char *wm8750_bass_filter[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
+static const char *wm8750_treble[] = {"8kHz", "4kHz"};
+static const char *wm8750_3d_lc[] = {"200Hz", "500Hz"};
+static const char *wm8750_3d_uc[] = {"2.2kHz", "1.5kHz"};
+static const char *wm8750_3d_func[] = {"Capture", "Playback"};
+static const char *wm8750_alc_func[] = {"Off", "Right", "Left", "Stereo"};
+static const char *wm8750_ng_type[] = {"Constant PGA Gain",
+	"Mute ADC Output"};
+static const char *wm8750_line_mux[] = {"Line 1", "Line 2", "Line 3", "PGA",
+	"Differential"};
+static const char *wm8750_pga_sel[] = {"Line 1", "Line 2", "Line 3",
+	"Differential"};
+static const char *wm8750_out3[] = {"VREF", "ROUT1 + Vol", "MonoOut",
+	"ROUT1"};
+static const char *wm8750_diff_sel[] = {"Line 1", "Line 2"};
+static const char *wm8750_adcpol[] = {"Normal", "L Invert", "R Invert",
+	"L + R Invert"};
+static const char *wm8750_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
+static const char *wm8750_mono_mux[] = {"Stereo", "Mono (Left)",
+	"Mono (Right)", "Digital Mono"};
+
+static const struct soc_enum wm8750_enum[] = {
+SOC_ENUM_SINGLE(WM8750_BASS, 7, 2, wm8750_bass),
+SOC_ENUM_SINGLE(WM8750_BASS, 6, 2, wm8750_bass_filter),
+SOC_ENUM_SINGLE(WM8750_TREBLE, 6, 2, wm8750_treble),
+SOC_ENUM_SINGLE(WM8750_3D, 5, 2, wm8750_3d_lc),
+SOC_ENUM_SINGLE(WM8750_3D, 6, 2, wm8750_3d_uc),
+SOC_ENUM_SINGLE(WM8750_3D, 7, 2, wm8750_3d_func),
+SOC_ENUM_SINGLE(WM8750_ALC1, 7, 4, wm8750_alc_func),
+SOC_ENUM_SINGLE(WM8750_NGATE, 1, 2, wm8750_ng_type),
+SOC_ENUM_SINGLE(WM8750_LOUTM1, 0, 5, wm8750_line_mux),
+SOC_ENUM_SINGLE(WM8750_ROUTM1, 0, 5, wm8750_line_mux),
+SOC_ENUM_SINGLE(WM8750_LADCIN, 6, 4, wm8750_pga_sel), /* 10 */
+SOC_ENUM_SINGLE(WM8750_RADCIN, 6, 4, wm8750_pga_sel),
+SOC_ENUM_SINGLE(WM8750_ADCTL2, 7, 4, wm8750_out3),
+SOC_ENUM_SINGLE(WM8750_ADCIN, 8, 2, wm8750_diff_sel),
+SOC_ENUM_SINGLE(WM8750_ADCDAC, 5, 4, wm8750_adcpol),
+SOC_ENUM_SINGLE(WM8750_ADCDAC, 1, 4, wm8750_deemph),
+SOC_ENUM_SINGLE(WM8750_ADCIN, 6, 4, wm8750_mono_mux), /* 16 */
+
+};
+
+static const struct snd_kcontrol_new wm8750_snd_controls[] = {
+
+SOC_DOUBLE_R("Capture Volume", WM8750_LINVOL, WM8750_RINVOL, 0, 63, 0),
+SOC_DOUBLE_R("Capture ZC Switch", WM8750_LINVOL, WM8750_RINVOL, 6, 1, 0),
+SOC_DOUBLE_R("Capture Switch", WM8750_LINVOL, WM8750_RINVOL, 7, 1, 1),
+
+SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8750_LOUT1V,
+	WM8750_ROUT1V, 7, 1, 0),
+SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8750_LOUT2V,
+	WM8750_ROUT2V, 7, 1, 0),
+
+SOC_ENUM("Playback De-emphasis", wm8750_enum[15]),
+
+SOC_ENUM("Capture Polarity", wm8750_enum[14]),
+SOC_SINGLE("Playback 6dB Attenuate", WM8750_ADCDAC, 7, 1, 0),
+SOC_SINGLE("Capture 6dB Attenuate", WM8750_ADCDAC, 8, 1, 0),
+
+SOC_DOUBLE_R("PCM Volume", WM8750_LDAC, WM8750_RDAC, 0, 255, 0),
+
+SOC_ENUM("Bass Boost", wm8750_enum[0]),
+SOC_ENUM("Bass Filter", wm8750_enum[1]),
+SOC_SINGLE("Bass Volume", WM8750_BASS, 0, 15, 1),
+
+SOC_SINGLE("Treble Volume", WM8750_TREBLE, 0, 15, 0),
+SOC_ENUM("Treble Cut-off", wm8750_enum[2]),
+
+SOC_SINGLE("3D Switch", WM8750_3D, 0, 1, 0),
+SOC_SINGLE("3D Volume", WM8750_3D, 1, 15, 0),
+SOC_ENUM("3D Lower Cut-off", wm8750_enum[3]),
+SOC_ENUM("3D Upper Cut-off", wm8750_enum[4]),
+SOC_ENUM("3D Mode", wm8750_enum[5]),
+
+SOC_SINGLE("ALC Capture Target Volume", WM8750_ALC1, 0, 7, 0),
+SOC_SINGLE("ALC Capture Max Volume", WM8750_ALC1, 4, 7, 0),
+SOC_ENUM("ALC Capture Function", wm8750_enum[6]),
+SOC_SINGLE("ALC Capture ZC Switch", WM8750_ALC2, 7, 1, 0),
+SOC_SINGLE("ALC Capture Hold Time", WM8750_ALC2, 0, 15, 0),
+SOC_SINGLE("ALC Capture Decay Time", WM8750_ALC3, 4, 15, 0),
+SOC_SINGLE("ALC Capture Attack Time", WM8750_ALC3, 0, 15, 0),
+SOC_SINGLE("ALC Capture NG Threshold", WM8750_NGATE, 3, 31, 0),
+SOC_ENUM("ALC Capture NG Type", wm8750_enum[4]),
+SOC_SINGLE("ALC Capture NG Switch", WM8750_NGATE, 0, 1, 0),
+
+SOC_SINGLE("Left ADC Capture Volume", WM8750_LADC, 0, 255, 0),
+SOC_SINGLE("Right ADC Capture Volume", WM8750_RADC, 0, 255, 0),
+
+SOC_SINGLE("ZC Timeout Switch", WM8750_ADCTL1, 0, 1, 0),
+SOC_SINGLE("Playback Invert Switch", WM8750_ADCTL1, 1, 1, 0),
+
+SOC_SINGLE("Right Speaker Playback Invert Switch", WM8750_ADCTL2, 4, 1, 0),
+
+/* Unimplemented */
+/* ADCDAC Bit 0 - ADCHPD */
+/* ADCDAC Bit 4 - HPOR */
+/* ADCTL1 Bit 2,3 - DATSEL */
+/* ADCTL1 Bit 4,5 - DMONOMIX */
+/* ADCTL1 Bit 6,7 - VSEL */
+/* ADCTL2 Bit 2 - LRCM */
+/* ADCTL2 Bit 3 - TRI */
+/* ADCTL3 Bit 5 - HPFLREN */
+/* ADCTL3 Bit 6 - VROI */
+/* ADCTL3 Bit 7,8 - ADCLRM */
+/* ADCIN Bit 4 - LDCM */
+/* ADCIN Bit 5 - RDCM */
+
+SOC_DOUBLE_R("Mic Boost", WM8750_LADCIN, WM8750_RADCIN, 4, 3, 0),
+
+SOC_DOUBLE_R("Bypass Left Playback Volume", WM8750_LOUTM1,
+	WM8750_LOUTM2, 4, 7, 1),
+SOC_DOUBLE_R("Bypass Right Playback Volume", WM8750_ROUTM1,
+	WM8750_ROUTM2, 4, 7, 1),
+SOC_DOUBLE_R("Bypass Mono Playback Volume", WM8750_MOUTM1,
+	WM8750_MOUTM2, 4, 7, 1),
+
+SOC_SINGLE("Mono Playback ZC Switch", WM8750_MOUTV, 7, 1, 0),
+
+SOC_DOUBLE_R("Headphone Playback Volume", WM8750_LOUT1V, WM8750_ROUT1V,
+	0, 127, 0),
+SOC_DOUBLE_R("Speaker Playback Volume", WM8750_LOUT2V, WM8750_ROUT2V,
+	0, 127, 0),
+
+SOC_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0),
+
+};
+
+/* add non dapm controls */
+static int wm8750_add_controls(struct snd_soc_codec *codec)
+{
+	int err, i;
+
+	for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) {
+		err = snd_ctl_add(codec->card,
+				snd_soc_cnew(&wm8750_snd_controls[i],codec, NULL));
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+/*
+ * DAPM Controls
+ */
+
+/* Left Mixer */
+static const struct snd_kcontrol_new wm8750_left_mixer_controls[] = {
+SOC_DAPM_SINGLE("Playback Switch", WM8750_LOUTM1, 8, 1, 0),
+SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_LOUTM1, 7, 1, 0),
+SOC_DAPM_SINGLE("Right Playback Switch", WM8750_LOUTM2, 8, 1, 0),
+SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_LOUTM2, 7, 1, 0),
+};
+
+/* Right Mixer */
+static const struct snd_kcontrol_new wm8750_right_mixer_controls[] = {
+SOC_DAPM_SINGLE("Left Playback Switch", WM8750_ROUTM1, 8, 1, 0),
+SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_ROUTM1, 7, 1, 0),
+SOC_DAPM_SINGLE("Playback Switch", WM8750_ROUTM2, 8, 1, 0),
+SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_ROUTM2, 7, 1, 0),
+};
+
+/* Mono Mixer */
+static const struct snd_kcontrol_new wm8750_mono_mixer_controls[] = {
+SOC_DAPM_SINGLE("Left Playback Switch", WM8750_MOUTM1, 8, 1, 0),
+SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_MOUTM1, 7, 1, 0),
+SOC_DAPM_SINGLE("Right Playback Switch", WM8750_MOUTM2, 8, 1, 0),
+SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_MOUTM2, 7, 1, 0),
+};
+
+/* Left Line Mux */
+static const struct snd_kcontrol_new wm8750_left_line_controls =
+SOC_DAPM_ENUM("Route", wm8750_enum[8]);
+
+/* Right Line Mux */
+static const struct snd_kcontrol_new wm8750_right_line_controls =
+SOC_DAPM_ENUM("Route", wm8750_enum[9]);
+
+/* Left PGA Mux */
+static const struct snd_kcontrol_new wm8750_left_pga_controls =
+SOC_DAPM_ENUM("Route", wm8750_enum[10]);
+
+/* Right PGA Mux */
+static const struct snd_kcontrol_new wm8750_right_pga_controls =
+SOC_DAPM_ENUM("Route", wm8750_enum[11]);
+
+/* Out 3 Mux */
+static const struct snd_kcontrol_new wm8750_out3_controls =
+SOC_DAPM_ENUM("Route", wm8750_enum[12]);
+
+/* Differential Mux */
+static const struct snd_kcontrol_new wm8750_diffmux_controls =
+SOC_DAPM_ENUM("Route", wm8750_enum[13]);
+
+/* Mono ADC Mux */
+static const struct snd_kcontrol_new wm8750_monomux_controls =
+SOC_DAPM_ENUM("Route", wm8750_enum[16]);
+
+static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
+	SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
+		&wm8750_left_mixer_controls[0],
+		ARRAY_SIZE(wm8750_left_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
+		&wm8750_right_mixer_controls[0],
+		ARRAY_SIZE(wm8750_right_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Mono Mixer", WM8750_PWR2, 2, 0,
+		&wm8750_mono_mixer_controls[0],
+		ARRAY_SIZE(wm8750_mono_mixer_controls)),
+
+	SND_SOC_DAPM_PGA("Right Out 2", WM8750_PWR2, 3, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Left Out 2", WM8750_PWR2, 4, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Right Out 1", WM8750_PWR2, 5, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Left Out 1", WM8750_PWR2, 6, 0, NULL, 0),
+	SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8750_PWR2, 7, 0),
+	SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8750_PWR2, 8, 0),
+
+	SND_SOC_DAPM_MICBIAS("Mic Bias", WM8750_PWR1, 1, 0),
+	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8750_PWR1, 2, 0),
+	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8750_PWR1, 3, 0),
+
+	SND_SOC_DAPM_MUX("Left PGA Mux", WM8750_PWR1, 5, 0,
+		&wm8750_left_pga_controls),
+	SND_SOC_DAPM_MUX("Right PGA Mux", WM8750_PWR1, 4, 0,
+		&wm8750_right_pga_controls),
+	SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
+		&wm8750_left_line_controls),
+	SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
+		&wm8750_right_line_controls),
+
+	SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &wm8750_out3_controls),
+	SND_SOC_DAPM_PGA("Out 3", WM8750_PWR2, 1, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Mono Out 1", WM8750_PWR2, 2, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
+		&wm8750_diffmux_controls),
+	SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
+		&wm8750_monomux_controls),
+	SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
+		&wm8750_monomux_controls),
+
+	SND_SOC_DAPM_OUTPUT("LOUT1"),
+	SND_SOC_DAPM_OUTPUT("ROUT1"),
+	SND_SOC_DAPM_OUTPUT("LOUT2"),
+	SND_SOC_DAPM_OUTPUT("ROUT2"),
+	SND_SOC_DAPM_OUTPUT("MONO"),
+	SND_SOC_DAPM_OUTPUT("OUT3"),
+
+	SND_SOC_DAPM_INPUT("LINPUT1"),
+	SND_SOC_DAPM_INPUT("LINPUT2"),
+	SND_SOC_DAPM_INPUT("LINPUT3"),
+	SND_SOC_DAPM_INPUT("RINPUT1"),
+	SND_SOC_DAPM_INPUT("RINPUT2"),
+	SND_SOC_DAPM_INPUT("RINPUT3"),
+};
+
+static const char *audio_map[][3] = {
+	/* left mixer */
+	{"Left Mixer", "Playback Switch", "Left DAC"},
+	{"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
+	{"Left Mixer", "Right Playback Switch", "Right DAC"},
+	{"Left Mixer", "Right Bypass Switch", "Right Line Mux"},
+
+	/* right mixer */
+	{"Right Mixer", "Left Playback Switch", "Left DAC"},
+	{"Right Mixer", "Left Bypass Switch", "Left Line Mux"},
+	{"Right Mixer", "Playback Switch", "Right DAC"},
+	{"Right Mixer", "Right Bypass Switch", "Right Line Mux"},
+
+	/* left out 1 */
+	{"Left Out 1", NULL, "Left Mixer"},
+	{"LOUT1", NULL, "Left Out 1"},
+
+	/* left out 2 */
+	{"Left Out 2", NULL, "Left Mixer"},
+	{"LOUT2", NULL, "Left Out 2"},
+
+	/* right out 1 */
+	{"Right Out 1", NULL, "Right Mixer"},
+	{"ROUT1", NULL, "Right Out 1"},
+
+	/* right out 2 */
+	{"Right Out 2", NULL, "Right Mixer"},
+	{"ROUT2", NULL, "Right Out 2"},
+
+	/* mono mixer */
+	{"Mono Mixer", "Left Playback Switch", "Left DAC"},
+	{"Mono Mixer", "Left Bypass Switch", "Left Line Mux"},
+	{"Mono Mixer", "Right Playback Switch", "Right DAC"},
+	{"Mono Mixer", "Right Bypass Switch", "Right Line Mux"},
+
+	/* mono out */
+	{"Mono Out 1", NULL, "Mono Mixer"},
+	{"MONO1", NULL, "Mono Out 1"},
+
+	/* out 3 */
+	{"Out3 Mux", "VREF", "VREF"},
+	{"Out3 Mux", "ROUT1 + Vol", "ROUT1"},
+	{"Out3 Mux", "ROUT1", "Right Mixer"},
+	{"Out3 Mux", "MonoOut", "MONO1"},
+	{"Out 3", NULL, "Out3 Mux"},
+	{"OUT3", NULL, "Out 3"},
+
+	/* Left Line Mux */
+	{"Left Line Mux", "Line 1", "LINPUT1"},
+	{"Left Line Mux", "Line 2", "LINPUT2"},
+	{"Left Line Mux", "Line 3", "LINPUT3"},
+	{"Left Line Mux", "PGA", "Left PGA Mux"},
+	{"Left Line Mux", "Differential", "Differential Mux"},
+
+	/* Right Line Mux */
+	{"Right Line Mux", "Line 1", "RINPUT1"},
+	{"Right Line Mux", "Line 2", "RINPUT2"},
+	{"Right Line Mux", "Line 3", "RINPUT3"},
+	{"Right Line Mux", "PGA", "Right PGA Mux"},
+	{"Right Line Mux", "Differential", "Differential Mux"},
+
+	/* Left PGA Mux */
+	{"Left PGA Mux", "Line 1", "LINPUT1"},
+	{"Left PGA Mux", "Line 2", "LINPUT2"},
+	{"Left PGA Mux", "Line 3", "LINPUT3"},
+	{"Left PGA Mux", "Differential", "Differential Mux"},
+
+	/* Right PGA Mux */
+	{"Right PGA Mux", "Line 1", "RINPUT1"},
+	{"Right PGA Mux", "Line 2", "RINPUT2"},
+	{"Right PGA Mux", "Line 3", "RINPUT3"},
+	{"Right PGA Mux", "Differential", "Differential Mux"},
+
+	/* Differential Mux */
+	{"Differential Mux", "Line 1", "LINPUT1"},
+	{"Differential Mux", "Line 1", "RINPUT1"},
+	{"Differential Mux", "Line 2", "LINPUT2"},
+	{"Differential Mux", "Line 2", "RINPUT2"},
+
+	/* Left ADC Mux */
+	{"Left ADC Mux", "Stereo", "Left PGA Mux"},
+	{"Left ADC Mux", "Mono (Left)", "Left PGA Mux"},
+	{"Left ADC Mux", "Digital Mono", "Left PGA Mux"},
+
+	/* Right ADC Mux */
+	{"Right ADC Mux", "Stereo", "Right PGA Mux"},
+	{"Right ADC Mux", "Mono (Right)", "Right PGA Mux"},
+	{"Right ADC Mux", "Digital Mono", "Right PGA Mux"},
+
+	/* ADC */
+	{"Left ADC", NULL, "Left ADC Mux"},
+	{"Right ADC", NULL, "Right ADC Mux"},
+
+	/* terminator */
+	{NULL, NULL, NULL},
+};
+
+static int wm8750_add_widgets(struct snd_soc_codec *codec)
+{
+	int i;
+
+	for(i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
+		snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
+	}
+
+	/* set up audio path audio_mapnects */
+	for(i = 0; audio_map[i][0] != NULL; i++) {
+		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+			audio_map[i][1], audio_map[i][2]);
+	}
+
+	snd_soc_dapm_new_widgets(codec);
+	return 0;
+}
+
+struct _coeff_div {
+	u32 mclk;
+	u32 rate;
+	u16 fs;
+	u8 sr:5;
+	u8 usb:1;
+};
+
+/* codec hifi mclk clock divider coefficients */
+static const struct _coeff_div coeff_div[] = {
+	/* 8k */
+	{12288000, 8000, 1536, 0x6, 0x0},
+	{11289600, 8000, 1408, 0x16, 0x0},
+	{18432000, 8000, 2304, 0x7, 0x0},
+	{16934400, 8000, 2112, 0x17, 0x0},
+	{12000000, 8000, 1500, 0x6, 0x1},
+
+	/* 11.025k */
+	{11289600, 11025, 1024, 0x18, 0x0},
+	{16934400, 11025, 1536, 0x19, 0x0},
+	{12000000, 11025, 1088, 0x19, 0x1},
+
+	/* 16k */
+	{12288000, 16000, 768, 0xa, 0x0},
+	{18432000, 16000, 1152, 0xb, 0x0},
+	{12000000, 16000, 750, 0xa, 0x1},
+
+	/* 22.05k */
+	{11289600, 22050, 512, 0x1a, 0x0},
+	{16934400, 22050, 768, 0x1b, 0x0},
+	{12000000, 22050, 544, 0x1b, 0x1},
+
+	/* 32k */
+	{12288000, 32000, 384, 0xc, 0x0},
+	{18432000, 32000, 576, 0xd, 0x0},
+	{12000000, 32000, 375, 0xa, 0x1},
+
+	/* 44.1k */
+	{11289600, 44100, 256, 0x10, 0x0},
+	{16934400, 44100, 384, 0x11, 0x0},
+	{12000000, 44100, 272, 0x11, 0x1},
+
+	/* 48k */
+	{12288000, 48000, 256, 0x0, 0x0},
+	{18432000, 48000, 384, 0x1, 0x0},
+	{12000000, 48000, 250, 0x0, 0x1},
+
+	/* 88.2k */
+	{11289600, 88200, 128, 0x1e, 0x0},
+	{16934400, 88200, 192, 0x1f, 0x0},
+	{12000000, 88200, 136, 0x1f, 0x1},
+
+	/* 96k */
+	{12288000, 96000, 128, 0xe, 0x0},
+	{18432000, 96000, 192, 0xf, 0x0},
+	{12000000, 96000, 125, 0xe, 0x1},
+};
+
+static inline int get_coeff(int mclk, int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+		if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
+			return i;
+	}
+
+	printk(KERN_ERR "wm8750: could not get coeff for mclk %d @ rate %d\n",
+		mclk, rate);
+	return -EINVAL;
+}
+
+static int wm8750_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct wm8750_priv *wm8750 = codec->private_data;
+
+	switch (freq) {
+	case 11289600:
+	case 12000000:
+	case 12288000:
+	case 16934400:
+	case 18432000:
+		wm8750->sysclk = freq;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int wm8750_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 iface = 0;
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		iface = 0x0040;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		iface |= 0x0002;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iface |= 0x0001;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		iface |= 0x0003;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		iface |= 0x0013;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		iface |= 0x0090;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		iface |= 0x0080;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		iface |= 0x0010;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	wm8750_write(codec, WM8750_IFACE, iface);
+	return 0;
+}
+
+static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+	struct wm8750_priv *wm8750 = codec->private_data;
+	u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3;
+	u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0;
+	int coeff = get_coeff(wm8750->sysclk, params_rate(params));
+
+	/* bit size */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		iface |= 0x0004;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		iface |= 0x0008;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		iface |= 0x000c;
+		break;
+	}
+
+	/* set iface & srate */
+	wm8750_write(codec, WM8750_IFACE, iface);
+	if (coeff >= 0)
+		wm8750_write(codec, WM8750_SRATE, srate |
+			(coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
+
+	return 0;
+}
+
+static int wm8750_mute(struct snd_soc_codec_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7;
+
+	if (mute)
+		wm8750_write(codec, WM8750_ADCDAC, mute_reg | 0x8);
+	else
+		wm8750_write(codec, WM8750_ADCDAC, mute_reg);
+	return 0;
+}
+
+static int wm8750_dapm_event(struct snd_soc_codec *codec, int event)
+{
+	u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e;
+
+	switch (event) {
+	case SNDRV_CTL_POWER_D0: /* full On */
+		/* set vmid to 50k and unmute dac */
+		wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
+		break;
+	case SNDRV_CTL_POWER_D1: /* partial On */
+	case SNDRV_CTL_POWER_D2: /* partial On */
+		/* set vmid to 5k for quick power up */
+		wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
+		break;
+	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+		/* mute dac and set vmid to 500k, enable VREF */
+		wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
+		break;
+	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+		wm8750_write(codec, WM8750_PWR1, 0x0001);
+		break;
+	}
+	codec->dapm_state = event;
+	return 0;
+}
+
+#define WM8750_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
+		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+
+#define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+	SNDRV_PCM_FMTBIT_S24_LE)
+
+struct snd_soc_codec_dai wm8750_dai = {
+	.name = "WM8750",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8750_RATES,
+		.formats = WM8750_FORMATS,},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8750_RATES,
+		.formats = WM8750_FORMATS,},
+	.ops = {
+		.hw_params = wm8750_pcm_hw_params,
+	},
+	.dai_ops = {
+		.digital_mute = wm8750_mute,
+		.set_fmt = wm8750_set_dai_fmt,
+		.set_sysclk = wm8750_set_dai_sysclk,
+	},
+};
+EXPORT_SYMBOL_GPL(wm8750_dai);
+
+static void wm8750_work(struct work_struct *work)
+{
+	struct snd_soc_codec *codec =
+		container_of(work, struct snd_soc_codec, delayed_work.work);
+	wm8750_dapm_event(codec, codec->dapm_state);
+}
+
+static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+	return 0;
+}
+
+static int wm8750_resume(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+	int i;
+	u8 data[2];
+	u16 *cache = codec->reg_cache;
+
+	/* Sync reg_cache with the hardware */
+	for (i = 0; i < ARRAY_SIZE(wm8750_reg); i++) {
+		if (i == WM8750_RESET)
+			continue;
+		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
+		data[1] = cache[i] & 0x00ff;
+		codec->hw_write(codec->control_data, data, 2);
+	}
+
+	wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+	/* charge wm8750 caps */
+	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
+		wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
+		codec->dapm_state = SNDRV_CTL_POWER_D0;
+		schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
+	}
+
+	return 0;
+}
+
+/*
+ * initialise the WM8750 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int wm8750_init(struct snd_soc_device *socdev)
+{
+	struct snd_soc_codec *codec = socdev->codec;
+	int reg, ret = 0;
+
+	codec->name = "WM8750";
+	codec->owner = THIS_MODULE;
+	codec->read = wm8750_read_reg_cache;
+	codec->write = wm8750_write;
+	codec->dapm_event = wm8750_dapm_event;
+	codec->dai = &wm8750_dai;
+	codec->num_dai = 1;
+	codec->reg_cache_size = sizeof(wm8750_reg);
+	codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KRENEL);
+	if (codec->reg_cache == NULL)
+		return -ENOMEM;
+
+	wm8750_reset(codec);
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0) {
+		printk(KERN_ERR "wm8750: failed to create pcms\n");
+		goto pcm_err;
+	}
+
+	/* charge output caps */
+	wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
+	codec->dapm_state = SNDRV_CTL_POWER_D3hot;
+	schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
+
+	/* set the update bits */
+	reg = wm8750_read_reg_cache(codec, WM8750_LDAC);
+	wm8750_write(codec, WM8750_LDAC, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_RDAC);
+	wm8750_write(codec, WM8750_RDAC, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V);
+	wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V);
+	wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V);
+	wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V);
+	wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_LINVOL);
+	wm8750_write(codec, WM8750_LINVOL, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_RINVOL);
+	wm8750_write(codec, WM8750_RINVOL, reg | 0x0100);
+
+	wm8750_add_controls(codec);
+	wm8750_add_widgets(codec);
+	ret = snd_soc_register_card(socdev);
+	if (ret < 0) {
+		printk(KERN_ERR "wm8750: failed to register card\n");
+		goto card_err;
+	}
+	return ret;
+
+card_err:
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+pcm_err:
+	kfree(codec->reg_cache);
+	return ret;
+}
+
+/* If the i2c layer weren't so broken, we could pass this kind of data
+   around */
+static struct snd_soc_device *wm8750_socdev;
+
+#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+
+/*
+ * WM8731 2 wire address is determined by GPIO5
+ * state during powerup.
+ *    low  = 0x1a
+ *    high = 0x1b
+ */
+static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver wm8750_i2c_driver;
+static struct i2c_client client_template;
+
+static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct snd_soc_device *socdev = wm8750_socdev;
+	struct wm8750_setup_data *setup = socdev->codec_data;
+	struct snd_soc_codec *codec = socdev->codec;
+	struct i2c_client *i2c;
+	int ret;
+
+	if (addr != setup->i2c_address)
+		return -ENODEV;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+
+	i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
+	if (i2c == NULL) {
+		kfree(codec);
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(i2c, codec);
+	codec->control_data = i2c;
+
+	ret = i2c_attach_client(i2c);
+	if (ret < 0) {
+		err("failed to attach codec at addr %x\n", addr);
+		goto err;
+	}
+
+	ret = wm8750_init(socdev);
+	if (ret < 0) {
+	err("failed to initialise WM8750\n");
+		goto err;
+	}
+	return ret;
+
+err:
+	kfree(codec);
+	kfree(i2c);
+	return ret;
+}
+
+static int wm8750_i2c_detach(struct i2c_client *client)
+{
+	struct snd_soc_codec *codec = i2c_get_clientdata(client);
+	i2c_detach_client(client);
+	kfree(codec->reg_cache);
+	kfree(client);
+	return 0;
+}
+
+static int wm8750_i2c_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, wm8750_codec_probe);
+}
+
+/* corgi i2c codec control layer */
+static struct i2c_driver wm8750_i2c_driver = {
+	.driver = {
+		.name = "WM8750 I2C Codec",
+		.owner = THIS_MODULE,
+	},
+	.id =             I2C_DRIVERID_WM8750,
+	.attach_adapter = wm8750_i2c_attach,
+	.detach_client =  wm8750_i2c_detach,
+	.command =        NULL,
+};
+
+static struct i2c_client client_template = {
+	.name =   "WM8750",
+	.driver = &wm8750_i2c_driver,
+};
+#endif
+
+static int wm8750_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct wm8750_setup_data *setup = socdev->codec_data;
+	struct snd_soc_codec *codec;
+	struct wm8750_priv *wm8750;
+	int ret = 0;
+
+	info("WM8750 Audio Codec %s", WM8750_VERSION);
+	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (codec == NULL)
+		return -ENOMEM;
+
+	wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
+	if (wm8750 == NULL) {
+		kfree(codec);
+		return -ENOMEM;
+	}
+
+	codec->private_data = wm8750;
+	socdev->codec = codec;
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+	wm8750_socdev = socdev;
+	INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
+	
+#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+	if (setup->i2c_address) {
+		normal_i2c[0] = setup->i2c_address;
+		codec->hw_write = (hw_write_t)i2c_master_send;
+		ret = i2c_add_driver(&wm8750_i2c_driver);
+		if (ret != 0)
+			printk(KERN_ERR "can't add i2c driver");
+	}
+#else
+		/* Add other interfaces here */
+#endif
+
+	return ret;
+}
+
+/*
+ * This function forces any delayed work to be queued and run.
+ */
+static int run_delayed_work(struct delayed_work *dwork)
+{
+	int ret;
+
+	/* cancel any work waiting to be queued. */
+	ret = cancel_delayed_work(dwork);
+
+	/* if there was any work waiting then we run it now and
+	 * wait for it's completion */
+	if (ret) {
+		schedule_delayed_work(dwork, 0);
+		flush_scheduled_work();
+	}
+	return ret;
+}
+
+/* power down chip */
+static int wm8750_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	if (codec->control_data)
+		wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+	run_delayed_work(&codec->delayed_work);
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+	i2c_del_driver(&wm8750_i2c_driver);
+#endif
+	kfree(codec->private_data);
+	kfree(codec);
+
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8750 = {
+	.probe = 	wm8750_probe,
+	.remove = 	wm8750_remove,
+	.suspend = 	wm8750_suspend,
+	.resume =	wm8750_resume,
+};
+
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
+
+MODULE_DESCRIPTION("ASoC WM8750 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h
new file mode 100644
index 0000000..a97a54a
--- /dev/null
+++ b/sound/soc/codecs/wm8750.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <richard@openedhand.com>
+ *
+ * Based on WM8753.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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _WM8750_H
+#define _WM8750_H
+
+/* WM8750 register space */
+
+#define WM8750_LINVOL    0x00
+#define WM8750_RINVOL    0x01
+#define WM8750_LOUT1V    0x02
+#define WM8750_ROUT1V    0x03
+#define WM8750_ADCDAC    0x05
+#define WM8750_IFACE     0x07
+#define WM8750_SRATE     0x08
+#define WM8750_LDAC      0x0a
+#define WM8750_RDAC      0x0b
+#define WM8750_BASS      0x0c
+#define WM8750_TREBLE    0x0d
+#define WM8750_RESET     0x0f
+#define WM8750_3D        0x10
+#define WM8750_ALC1      0x11
+#define WM8750_ALC2      0x12
+#define WM8750_ALC3      0x13
+#define WM8750_NGATE     0x14
+#define WM8750_LADC      0x15
+#define WM8750_RADC      0x16
+#define WM8750_ADCTL1    0x17
+#define WM8750_ADCTL2    0x18
+#define WM8750_PWR1      0x19
+#define WM8750_PWR2      0x1a
+#define WM8750_ADCTL3    0x1b
+#define WM8750_ADCIN     0x1f
+#define WM8750_LADCIN    0x20
+#define WM8750_RADCIN    0x21
+#define WM8750_LOUTM1    0x22
+#define WM8750_LOUTM2    0x23
+#define WM8750_ROUTM1    0x24
+#define WM8750_ROUTM2    0x25
+#define WM8750_MOUTM1    0x26
+#define WM8750_MOUTM2    0x27
+#define WM8750_LOUT2V    0x28
+#define WM8750_ROUT2V    0x29
+#define WM8750_MOUTV     0x2a
+
+#define WM8750_CACHE_REGNUM 0x2a
+
+#define WM8750_SYSCLK	0
+
+struct wm8750_setup_data {
+	unsigned short i2c_address;
+};
+
+extern struct snd_soc_codec_dai wm8750_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8750;
+
+#endif
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
new file mode 100644
index 0000000..92a6487
--- /dev/null
+++ b/sound/soc/codecs/wm9712.c
@@ -0,0 +1,771 @@
+/*
+ * wm9712.c  --  ALSA Soc WM9712 codec support
+ *
+ * Copyright 2006 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.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.
+ *
+ *  Revision history
+ *    4th Feb 2006   Initial version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#define WM9712_VERSION "0.4"
+
+static unsigned int ac97_read(struct snd_soc_codec *codec,
+	unsigned int reg);
+static int ac97_write(struct snd_soc_codec *codec,
+	unsigned int reg, unsigned int val);
+
+/*
+ * WM9712 register cache
+ */
+static const u16 wm9712_reg[] = {
+	0x6174, 0x8000, 0x8000, 0x8000, // 6
+	0xf0f0, 0xaaa0, 0xc008, 0x6808, // e
+	0xe808, 0xaaa0, 0xad00, 0x8000, // 16
+	0xe808, 0x3000, 0x8000, 0x0000, // 1e
+	0x0000, 0x0000, 0x0000, 0x000f, // 26
+	0x0405, 0x0410, 0xbb80, 0xbb80, // 2e
+	0x0000, 0xbb80, 0x0000, 0x0000, // 36
+	0x0000, 0x2000, 0x0000, 0x0000, // 3e
+	0x0000, 0x0000, 0x0000, 0x0000, // 46
+	0x0000, 0x0000, 0xf83e, 0xffff, // 4e
+	0x0000, 0x0000, 0x0000, 0xf83e, // 56
+	0x0008, 0x0000, 0x0000, 0x0000, // 5e
+	0xb032, 0x3e00, 0x0000, 0x0000, // 66
+	0x0000, 0x0000, 0x0000, 0x0000, // 6e
+	0x0000, 0x0000, 0x0000, 0x0006, // 76
+	0x0001, 0x0000, 0x574d, 0x4c12, // 7e
+	0x0000, 0x0000 // virtual hp mixers
+};
+
+/* virtual HP mixers regs */
+#define HPL_MIXER	0x80
+#define HPR_MIXER	0x82
+
+static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"};
+static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"};
+static const char *wm9712_out3_src[] = {"Left", "VREF", "Left + Right",
+	"Mono"};
+static const char *wm9712_spk_src[] = {"Speaker Mix", "Headphone Mix"};
+static const char *wm9712_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
+static const char *wm9712_base[] = {"Linear Control", "Adaptive Boost"};
+static const char *wm9712_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
+static const char *wm9712_mic[] = {"Mic 1", "Differential", "Mic 2",
+	"Stereo"};
+static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer",
+	"Line", "Headphone Mixer", "Phone Mixer", "Phone"};
+static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"};
+static const char *wm9712_diff_sel[] = {"Mic", "Line"};
+
+static const struct soc_enum wm9712_enum[] = {
+SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select),
+SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux),
+SOC_ENUM_SINGLE(AC97_AUX, 9, 4, wm9712_out3_src),
+SOC_ENUM_SINGLE(AC97_AUX, 8, 2, wm9712_spk_src),
+SOC_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9712_rec_adc),
+SOC_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9712_base),
+SOC_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9712_rec_gain),
+SOC_ENUM_SINGLE(AC97_MIC, 5, 4, wm9712_mic),
+SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9712_rec_sel),
+SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9712_rec_sel),
+SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9712_ng_type),
+SOC_ENUM_SINGLE(0x5c, 8, 2, wm9712_diff_sel),
+};
+
+static const struct snd_kcontrol_new wm9712_snd_ac97_controls[] = {
+SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
+SOC_SINGLE("Speaker Playback Switch", AC97_MASTER, 15, 1, 1),
+SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
+SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE,15, 1, 1),
+
+SOC_SINGLE("Speaker Playback ZC Switch", AC97_MASTER, 7, 1, 0),
+SOC_SINGLE("Speaker Playback Invert Switch", AC97_MASTER, 6, 1, 0),
+SOC_SINGLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 7, 1, 0),
+SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
+SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 0),
+
+SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
+SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
+SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
+SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
+SOC_ENUM("ALC Function", wm9712_enum[0]),
+SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
+SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
+SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
+SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
+SOC_ENUM("ALC NG Type", wm9712_enum[10]),
+SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
+
+SOC_SINGLE("Mic Headphone  Volume", AC97_VIDEO, 12, 7, 1),
+SOC_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
+
+SOC_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
+SOC_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1),
+SOC_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
+
+SOC_SINGLE("PCBeep Bypass Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
+SOC_SINGLE("PCBeep Bypass Speaker Volume", AC97_PC_BEEP, 8, 7, 1),
+SOC_SINGLE("PCBeep Bypass Phone Volume", AC97_PC_BEEP, 4, 7, 1),
+
+SOC_SINGLE("Aux Playback Headphone Volume", AC97_CD, 12, 7, 1),
+SOC_SINGLE("Aux Playback Speaker Volume", AC97_CD, 8, 7, 1),
+SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1),
+
+SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 0),
+SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1),
+
+SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
+SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
+
+SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
+SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
+SOC_SINGLE("3D Playback Volume", AC97_3D_CONTROL, 0, 15, 0),
+
+SOC_ENUM("Bass Control", wm9712_enum[5]),
+SOC_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
+SOC_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
+SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
+SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 0),
+SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 0),
+
+SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1),
+SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
+SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
+SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
+
+SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
+SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
+SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
+};
+
+/* add non dapm controls */
+static int wm9712_add_controls(struct snd_soc_codec *codec)
+{
+	int err, i;
+
+	for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) {
+		err = snd_ctl_add(codec->card,
+				snd_soc_cnew(&wm9712_snd_ac97_controls[i],codec, NULL));
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+/* We have to create a fake left and right HP mixers because
+ * the codec only has a single control that is shared by both channels.
+ * This makes it impossible to determine the audio path.
+ */
+static int mixer_event (struct snd_soc_dapm_widget *w, int event)
+{
+	u16 l, r, beep, line, phone, mic, pcm, aux;
+
+	l = ac97_read(w->codec, HPL_MIXER);
+	r = ac97_read(w->codec, HPR_MIXER);
+	beep = ac97_read(w->codec, AC97_PC_BEEP);
+	mic = ac97_read(w->codec, AC97_VIDEO);
+	phone = ac97_read(w->codec, AC97_PHONE);
+	line = ac97_read(w->codec, AC97_LINE);
+	pcm = ac97_read(w->codec, AC97_PCM);
+	aux = ac97_read(w->codec, AC97_CD);
+
+	if (l & 0x1 || r & 0x1)
+		ac97_write(w->codec, AC97_VIDEO, mic & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_VIDEO, mic | 0x8000);
+
+	if (l & 0x2 || r & 0x2)
+		ac97_write(w->codec, AC97_PCM, pcm & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
+
+	if (l & 0x4 || r & 0x4)
+		ac97_write(w->codec, AC97_LINE, line & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_LINE, line | 0x8000);
+
+	if (l & 0x8 || r & 0x8)
+		ac97_write(w->codec, AC97_PHONE, phone & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
+
+	if (l & 0x10 || r & 0x10)
+		ac97_write(w->codec, AC97_CD, aux & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_CD, aux | 0x8000);
+
+	if (l & 0x20 || r & 0x20)
+		ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000);
+
+	return 0;
+}
+
+/* Left Headphone Mixers */
+static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = {
+	SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPL_MIXER, 5, 1, 0),
+	SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 4, 1, 0),
+	SOC_DAPM_SINGLE("Phone Bypass Switch", HPL_MIXER, 3, 1, 0),
+	SOC_DAPM_SINGLE("Line Bypass Switch", HPL_MIXER, 2, 1, 0),
+	SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 1, 1, 0),
+	SOC_DAPM_SINGLE("Mic Sidetone Switch", HPL_MIXER, 0, 1, 0),
+};
+
+/* Right Headphone Mixers */
+static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = {
+	SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPR_MIXER, 5, 1, 0),
+	SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 4, 1, 0),
+	SOC_DAPM_SINGLE("Phone Bypass Switch", HPR_MIXER, 3, 1, 0),
+	SOC_DAPM_SINGLE("Line Bypass Switch", HPR_MIXER, 2, 1, 0),
+	SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 1, 1, 0),
+	SOC_DAPM_SINGLE("Mic Sidetone Switch", HPR_MIXER, 0, 1, 0),
+};
+
+/* Speaker Mixer */
+static const struct snd_kcontrol_new wm9712_speaker_mixer_controls[] = {
+	SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 11, 1, 1),
+	SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 11, 1, 1),
+	SOC_DAPM_SINGLE("Phone Bypass Switch", AC97_PHONE, 14, 1, 1),
+	SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 14, 1, 1),
+	SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 14, 1, 1),
+};
+
+/* Phone Mixer */
+static const struct snd_kcontrol_new wm9712_phone_mixer_controls[] = {
+	SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 7, 1, 1),
+	SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 7, 1, 1),
+	SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 13, 1, 1),
+	SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 13, 1, 1),
+	SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_MIC, 14, 1, 1),
+	SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_MIC, 13, 1, 1),
+};
+
+/* ALC headphone mux */
+static const struct snd_kcontrol_new wm9712_alc_mux_controls =
+SOC_DAPM_ENUM("Route", wm9712_enum[1]);
+
+/* out 3 mux */
+static const struct snd_kcontrol_new wm9712_out3_mux_controls =
+SOC_DAPM_ENUM("Route", wm9712_enum[2]);
+
+/* spk mux */
+static const struct snd_kcontrol_new wm9712_spk_mux_controls =
+SOC_DAPM_ENUM("Route", wm9712_enum[3]);
+
+/* Capture to Phone mux */
+static const struct snd_kcontrol_new wm9712_capture_phone_mux_controls =
+SOC_DAPM_ENUM("Route", wm9712_enum[4]);
+
+/* Capture left select */
+static const struct snd_kcontrol_new wm9712_capture_selectl_controls =
+SOC_DAPM_ENUM("Route", wm9712_enum[8]);
+
+/* Capture right select */
+static const struct snd_kcontrol_new wm9712_capture_selectr_controls =
+SOC_DAPM_ENUM("Route", wm9712_enum[9]);
+
+/* Mic select */
+static const struct snd_kcontrol_new wm9712_mic_src_controls =
+SOC_DAPM_ENUM("Route", wm9712_enum[7]);
+
+/* diff select */
+static const struct snd_kcontrol_new wm9712_diff_sel_controls =
+SOC_DAPM_ENUM("Route", wm9712_enum[11]);
+
+static const struct snd_soc_dapm_widget wm9712_dapm_widgets[] = {
+SND_SOC_DAPM_MUX("ALC Sidetone Mux", SND_SOC_NOPM, 0, 0,
+	&wm9712_alc_mux_controls),
+SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0,
+	&wm9712_out3_mux_controls),
+SND_SOC_DAPM_MUX("Speaker Mux", SND_SOC_NOPM, 0, 0,
+	&wm9712_spk_mux_controls),
+SND_SOC_DAPM_MUX("Capture Phone Mux", SND_SOC_NOPM, 0, 0,
+	&wm9712_capture_phone_mux_controls),
+SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0,
+	&wm9712_capture_selectl_controls),
+SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0,
+	&wm9712_capture_selectr_controls),
+SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0,
+	&wm9712_mic_src_controls),
+SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0,
+	&wm9712_diff_sel_controls),
+SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_INT_PAGING, 9, 1,
+	&wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls),
+	mixer_event, SND_SOC_DAPM_POST_REG),
+SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_INT_PAGING, 8, 1,
+	&wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls),
+	 mixer_event, SND_SOC_DAPM_POST_REG),
+SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1,
+	&wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)),
+SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1,
+	&wm9712_speaker_mixer_controls[0],
+	ARRAY_SIZE(wm9712_speaker_mixer_controls)),
+SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_INT_PAGING, 14, 1),
+SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_INT_PAGING, 13, 1),
+SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_INT_PAGING, 12, 1),
+SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_INT_PAGING, 11, 1),
+SND_SOC_DAPM_PGA("Headphone PGA", AC97_INT_PAGING, 4, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Speaker PGA", AC97_INT_PAGING, 3, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0),
+SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1),
+SND_SOC_DAPM_OUTPUT("MONOOUT"),
+SND_SOC_DAPM_OUTPUT("HPOUTL"),
+SND_SOC_DAPM_OUTPUT("HPOUTR"),
+SND_SOC_DAPM_OUTPUT("LOUT2"),
+SND_SOC_DAPM_OUTPUT("ROUT2"),
+SND_SOC_DAPM_OUTPUT("OUT3"),
+SND_SOC_DAPM_INPUT("LINEINL"),
+SND_SOC_DAPM_INPUT("LINEINR"),
+SND_SOC_DAPM_INPUT("PHONE"),
+SND_SOC_DAPM_INPUT("PCBEEP"),
+SND_SOC_DAPM_INPUT("MIC1"),
+SND_SOC_DAPM_INPUT("MIC2"),
+};
+
+static const char *audio_map[][3] = {
+	/* virtual mixer - mixes left & right channels for spk and mono */
+	{"AC97 Mixer", NULL, "Left DAC"},
+	{"AC97 Mixer", NULL, "Right DAC"},
+
+	/* Left HP mixer */
+	{"Left HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
+	{"Left HP Mixer", "Aux Playback Switch",  "Aux DAC"},
+	{"Left HP Mixer", "Phone Bypass Switch",  "Phone PGA"},
+	{"Left HP Mixer", "Line Bypass Switch",   "Line PGA"},
+	{"Left HP Mixer", "PCM Playback Switch",  "Left DAC"},
+	{"Left HP Mixer", "Mic Sidetone Switch",  "Mic PGA"},
+	{"Left HP Mixer", NULL,  "ALC Sidetone Mux"},
+	//{"Right HP Mixer", NULL, "HP Mixer"},
+
+	/* Right HP mixer */
+	{"Right HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
+	{"Right HP Mixer", "Aux Playback Switch",  "Aux DAC"},
+	{"Right HP Mixer", "Phone Bypass Switch",  "Phone PGA"},
+	{"Right HP Mixer", "Line Bypass Switch",   "Line PGA"},
+	{"Right HP Mixer", "PCM Playback Switch",  "Right DAC"},
+	{"Right HP Mixer", "Mic Sidetone Switch",  "Mic PGA"},
+	{"Right HP Mixer", NULL,  "ALC Sidetone Mux"},
+
+	/* speaker mixer */
+	{"Speaker Mixer", "PCBeep Bypass Switch", "PCBEEP"},
+	{"Speaker Mixer", "Line Bypass Switch",   "Line PGA"},
+	{"Speaker Mixer", "PCM Playback Switch",  "AC97 Mixer"},
+	{"Speaker Mixer", "Phone Bypass Switch",  "Phone PGA"},
+	{"Speaker Mixer", "Aux Playback Switch",  "Aux DAC"},
+
+	/* Phone mixer */
+	{"Phone Mixer", "PCBeep Bypass Switch",  "PCBEEP"},
+	{"Phone Mixer", "Line Bypass Switch",    "Line PGA"},
+	{"Phone Mixer", "Aux Playback Switch",   "Aux DAC"},
+	{"Phone Mixer", "PCM Playback Switch",   "AC97 Mixer"},
+	{"Phone Mixer", "Mic 1 Sidetone Switch", "Mic PGA"},
+	{"Phone Mixer", "Mic 2 Sidetone Switch", "Mic PGA"},
+
+	/* inputs */
+	{"Line PGA", NULL, "LINEINL"},
+	{"Line PGA", NULL, "LINEINR"},
+	{"Phone PGA", NULL, "PHONE"},
+	{"Mic PGA", NULL, "MIC1"},
+	{"Mic PGA", NULL, "MIC2"},
+
+	/* left capture selector */
+	{"Left Capture Select", "Mic", "MIC1"},
+	{"Left Capture Select", "Speaker Mixer", "Speaker Mixer"},
+	{"Left Capture Select", "Line", "LINEINL"},
+	{"Left Capture Select", "Headphone Mixer", "Left HP Mixer"},
+	{"Left Capture Select", "Phone Mixer", "Phone Mixer"},
+	{"Left Capture Select", "Phone", "PHONE"},
+
+	/* right capture selector */
+	{"Right Capture Select", "Mic", "MIC2"},
+	{"Right Capture Select", "Speaker Mixer", "Speaker Mixer"},
+	{"Right Capture Select", "Line", "LINEINR"},
+	{"Right Capture Select", "Headphone Mixer", "Right HP Mixer"},
+	{"Right Capture Select", "Phone Mixer", "Phone Mixer"},
+	{"Right Capture Select", "Phone", "PHONE"},
+
+	/* ALC Sidetone */
+	{"ALC Sidetone Mux", "Stereo", "Left Capture Select"},
+	{"ALC Sidetone Mux", "Stereo", "Right Capture Select"},
+	{"ALC Sidetone Mux", "Left", "Left Capture Select"},
+	{"ALC Sidetone Mux", "Right", "Right Capture Select"},
+
+	/* ADC's */
+	{"Left ADC", NULL, "Left Capture Select"},
+	{"Right ADC", NULL, "Right Capture Select"},
+
+	/* outputs */
+	{"MONOOUT", NULL, "Phone Mixer"},
+	{"HPOUTL", NULL, "Headphone PGA"},
+	{"Headphone PGA", NULL, "Left HP Mixer"},
+	{"HPOUTR", NULL, "Headphone PGA"},
+	{"Headphone PGA", NULL, "Right HP Mixer"},
+
+	/* mono hp mixer */
+	{"Mono HP Mixer", NULL, "Left HP Mixer"},
+	{"Mono HP Mixer", NULL, "Right HP Mixer"},
+
+	/* Out3 Mux */
+	{"Out3 Mux", "Left", "Left HP Mixer"},
+	{"Out3 Mux", "Mono", "Phone Mixer"},
+	{"Out3 Mux", "Left + Right", "Mono HP Mixer"},
+	{"Out 3 PGA", NULL, "Out3 Mux"},
+	{"OUT3", NULL, "Out 3 PGA"},
+
+	/* speaker Mux */
+	{"Speaker Mux", "Speaker Mix", "Speaker Mixer"},
+	{"Speaker Mux", "Headphone Mix", "Mono HP Mixer"},
+	{"Speaker PGA", NULL, "Speaker Mux"},
+	{"LOUT2", NULL, "Speaker PGA"},
+	{"ROUT2", NULL, "Speaker PGA"},
+
+	{NULL, NULL, NULL},
+};
+
+static int wm9712_add_widgets(struct snd_soc_codec *codec)
+{
+	int i;
+
+	for(i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++) {
+		snd_soc_dapm_new_control(codec, &wm9712_dapm_widgets[i]);
+	}
+
+	/* set up audio path audio_mapnects */
+	for(i = 0; audio_map[i][0] != NULL; i++) {
+		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+			audio_map[i][1], audio_map[i][2]);
+	}
+
+	snd_soc_dapm_new_widgets(codec);
+	return 0;
+}
+
+static unsigned int ac97_read(struct snd_soc_codec *codec,
+	unsigned int reg)
+{
+	u16 *cache = codec->reg_cache;
+
+	if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
+		reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
+		reg == AC97_REC_GAIN)
+		return soc_ac97_ops.read(codec->ac97, reg);
+	else {
+		reg = reg >> 1;
+
+		if (reg > (ARRAY_SIZE(wm9712_reg)))
+			return -EIO;
+
+		return cache[reg];
+	}
+}
+
+static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int val)
+{
+	u16 *cache = codec->reg_cache;
+
+	soc_ac97_ops.write(codec->ac97, reg, val);
+	reg = reg >> 1;
+	if (reg <= (ARRAY_SIZE(wm9712_reg)))
+		cache[reg] = val;
+
+	return 0;
+}
+
+static int ac97_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+	int reg;
+	u16 vra;
+
+	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
+	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		reg = AC97_PCM_FRONT_DAC_RATE;
+	else
+		reg = AC97_PCM_LR_ADC_RATE;
+
+	return ac97_write(codec, reg, runtime->rate);
+}
+
+static int ac97_aux_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+	u16 vra, xsle;
+
+	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
+	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
+	xsle = ac97_read(codec, AC97_PCI_SID);
+	ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
+
+	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+		return -ENODEV;
+
+	return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
+}
+
+#define WM9712_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+struct snd_soc_codec_dai wm9712_dai[] = {
+{
+	.name = "AC97 HiFi",
+	.playback = {
+		.stream_name = "HiFi Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM9712_AC97_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.capture = {
+		.stream_name = "HiFi Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM9712_AC97_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.prepare = ac97_prepare,},
+},
+{
+	.name = "AC97 Aux",
+	.playback = {
+		.stream_name = "Aux Playback",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = WM9712_AC97_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.prepare = ac97_aux_prepare,},
+}
+};
+EXPORT_SYMBOL_GPL(wm9712_dai);
+
+static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
+{
+	u16 reg;
+
+	switch (event) {
+	case SNDRV_CTL_POWER_D0: /* full On */
+		/* liam - maybe enable thermal shutdown */
+		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xdfff;
+		ac97_write(codec, AC97_EXTENDED_MID, reg);
+		break;
+	case SNDRV_CTL_POWER_D1: /* partial On */
+	case SNDRV_CTL_POWER_D2: /* partial On */
+		break;
+	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+		/* enable master bias and vmid */
+		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xbbff;
+		ac97_write(codec, AC97_EXTENDED_MID, reg);
+		ac97_write(codec, AC97_POWERDOWN, 0x0000);
+		break;
+	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+		/* disable everything including AC link */
+		ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
+		ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
+		ac97_write(codec, AC97_POWERDOWN, 0xffff);
+		break;
+	}
+	codec->dapm_state = event;
+	return 0;
+}
+
+static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
+{
+	if (try_warm && soc_ac97_ops.warm_reset) {
+		soc_ac97_ops.warm_reset(codec->ac97);
+		if (!(ac97_read(codec, 0) & 0x8000))
+			return 1;
+	}
+
+	soc_ac97_ops.reset(codec->ac97);
+	if (ac97_read(codec, 0) & 0x8000)
+		goto err;
+	return 0;
+
+err:
+	printk(KERN_ERR "WM9712 AC97 reset failed\n");
+	return -EIO;
+}
+
+static int wm9712_soc_suspend(struct platform_device *pdev,
+	pm_message_t state)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+	return 0;
+}
+
+static int wm9712_soc_resume(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+	int i, ret;
+	u16 *cache = codec->reg_cache;
+
+	ret = wm9712_reset(codec, 1);
+	if (ret < 0){
+		printk(KERN_ERR "could not reset AC97 codec\n");
+		return ret;
+	}
+
+	wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+	if (ret == 0) {
+		/* Sync reg_cache with the hardware after cold reset */
+		for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i+=2) {
+			if (i == AC97_INT_PAGING || i == AC97_POWERDOWN ||
+				(i > 0x58 && i != 0x5c))
+				continue;
+			soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
+		}
+	}
+
+	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
+		wm9712_dapm_event(codec, SNDRV_CTL_POWER_D0);
+
+	return ret;
+}
+
+static int wm9712_soc_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec;
+	int ret = 0;
+
+	printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
+
+	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (socdev->codec == NULL)
+		return -ENOMEM;
+	codec = socdev->codec;
+	mutex_init(&codec->mutex);
+
+	codec->reg_cache =
+		kzalloc(sizeof(u16) * ARRAY_SIZE(wm9712_reg), GFP_KERNEL);
+	if (codec->reg_cache == NULL) {
+		ret = -ENOMEM;
+		goto cache_err;
+	}
+	memcpy(codec->reg_cache, wm9712_reg, sizeof(u16) * ARRAY_SIZE(wm9712_reg));
+	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm9712_reg);
+	codec->reg_cache_step = 2;
+
+	codec->name = "WM9712";
+	codec->owner = THIS_MODULE;
+	codec->dai = wm9712_dai;
+	codec->num_dai = ARRAY_SIZE(wm9712_dai);
+	codec->write = ac97_write;
+	codec->read = ac97_read;
+	codec->dapm_event = wm9712_dapm_event;
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
+	if (ret < 0) {
+		printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
+		goto codec_err;
+	}
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0)
+		goto pcm_err;
+
+	ret = wm9712_reset(codec, 0);
+	if (ret < 0) {
+		printk(KERN_ERR "AC97 link error\n");
+		goto reset_err;
+	}
+
+	/* set alc mux to none */
+	ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
+
+	wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+	wm9712_add_controls(codec);
+	wm9712_add_widgets(codec);
+	ret = snd_soc_register_card(socdev);
+	if (ret < 0) {
+		printk(KERN_ERR "wm9712: failed to register card\n");
+		goto reset_err;
+	}
+
+	return 0;
+
+reset_err:
+	snd_soc_free_pcms(socdev);
+
+pcm_err:
+	snd_soc_free_ac97_codec(codec);
+
+codec_err:
+	kfree(codec->reg_cache);
+
+cache_err:
+	kfree(socdev->codec);
+	socdev->codec = NULL;
+	return ret;
+}
+
+static int wm9712_soc_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	if (codec == NULL)
+		return 0;
+
+	snd_soc_dapm_free(socdev);
+	snd_soc_free_pcms(socdev);
+	snd_soc_free_ac97_codec(codec);
+	kfree(codec->reg_cache);
+	kfree(codec);
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm9712 = {
+	.probe = 	wm9712_soc_probe,
+	.remove = 	wm9712_soc_remove,
+	.suspend =	wm9712_soc_suspend,
+	.resume =	wm9712_soc_resume,
+};
+
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712);
+
+MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm9712.h b/sound/soc/codecs/wm9712.h
new file mode 100644
index 0000000..719105d
--- /dev/null
+++ b/sound/soc/codecs/wm9712.h
@@ -0,0 +1,14 @@
+/*
+ * wm9712.h  --  WM9712 Soc Audio driver
+ */
+
+#ifndef _WM9712_H
+#define _WM9712_H
+
+#define WM9712_DAI_AC97_HIFI	0
+#define WM9712_DAI_AC97_AUX		1
+
+extern struct snd_soc_codec_dai wm9712_dai[2];
+extern struct snd_soc_codec_device soc_codec_dev_wm9712;
+
+#endif
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
new file mode 100644
index 0000000..579e1c8
--- /dev/null
+++ b/sound/soc/pxa/Kconfig
@@ -0,0 +1,60 @@
+menu "SoC Audio for the Intel PXA2xx"
+
+config SND_PXA2XX_SOC
+	tristate "SoC Audio for the Intel PXA2xx chip"
+	depends on ARCH_PXA && SND
+	select SND_PCM
+	help
+	  Say Y or M if you want to add support for codecs attached to
+	  the PXA2xx AC97, I2S or SSP interface. You will also need
+	  to select the audio interfaces to support below.
+
+config SND_PXA2XX_AC97
+	tristate
+	select SND_AC97_CODEC
+
+config SND_PXA2XX_SOC_AC97
+	tristate
+	select AC97_BUS
+	select SND_SOC_AC97_BUS
+
+config SND_PXA2XX_SOC_I2S
+	tristate
+
+config SND_PXA2XX_SOC_CORGI
+	tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
+	depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx
+	select SND_PXA2XX_SOC_I2S
+	select SND_SOC_WM8731
+	help
+	  Say Y if you want to add support for SoC audio on Sharp
+	  Zaurus SL-C7x0 models (Corgi, Shepherd, Husky).
+
+config SND_PXA2XX_SOC_SPITZ
+	tristate "SoC Audio support for Sharp Zaurus SL-Cxx00"
+	depends on SND_PXA2XX_SOC && PXA_SHARP_Cxx00
+	select SND_PXA2XX_SOC_I2S
+	select SND_SOC_WM8750
+	help
+	  Say Y if you want to add support for SoC audio on Sharp
+	  Zaurus SL-Cxx00 models (Spitz, Borzoi and Akita).
+
+config SND_PXA2XX_SOC_POODLE
+	tristate "SoC Audio support for Poodle"
+	depends on SND_PXA2XX_SOC && MACH_POODLE
+	select SND_PXA2XX_SOC_I2S
+	select SND_SOC_WM8731
+	help
+	  Say Y if you want to add support for SoC audio on Sharp
+	  Zaurus SL-5600 model (Poodle).
+
+config SND_PXA2XX_SOC_TOSA
+	tristate "SoC AC97 Audio support for Tosa"
+	depends on SND_PXA2XX_SOC && MACH_TOSA
+	select SND_PXA2XX_SOC_AC97
+	select SND_SOC_WM9712
+	help
+	  Say Y if you want to add support for SoC audio on Sharp
+	  Zaurus SL-C6000x models (Tosa).
+
+endmenu
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
new file mode 100644
index 0000000..78e0d6b
--- /dev/null
+++ b/sound/soc/pxa/Makefile
@@ -0,0 +1,20 @@
+# PXA Platform Support
+snd-soc-pxa2xx-objs := pxa2xx-pcm.o
+snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
+snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
+
+obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o
+obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
+obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
+
+# PXA Machine Support
+snd-soc-corgi-objs := corgi.o
+snd-soc-poodle-objs := poodle.o
+snd-soc-tosa-objs := tosa.o
+snd-soc-spitz-objs := spitz.o
+
+obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
+obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
+obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
+obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
+
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
new file mode 100644
index 0000000..5ee51a9
--- /dev/null
+++ b/sound/soc/pxa/corgi.c
@@ -0,0 +1,383 @@
+/*
+ * corgi.c  --  SoC audio for Corgi
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *          Richard Purdie <richard@openedhand.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.
+ *
+ *  Revision history
+ *    30th Nov 2005   Initial version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware/scoop.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/corgi.h>
+#include <asm/arch/audio.h>
+
+#include "../codecs/wm8731.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-i2s.h"
+
+#define CORGI_HP        0
+#define CORGI_MIC       1
+#define CORGI_LINE      2
+#define CORGI_HEADSET   3
+#define CORGI_HP_OFF    4
+#define CORGI_SPK_ON    0
+#define CORGI_SPK_OFF   1
+
+ /* audio clock in Hz - rounded from 12.235MHz */
+#define CORGI_AUDIO_CLOCK 12288000
+
+static int corgi_jack_func;
+static int corgi_spk_func;
+
+static void corgi_ext_control(struct snd_soc_codec *codec)
+{
+	int spk = 0, mic = 0, line = 0, hp = 0, hs = 0;
+
+	/* set up jack connection */
+	switch (corgi_jack_func) {
+	case CORGI_HP:
+		hp = 1;
+		/* set = unmute headphone */
+		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
+		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
+		break;
+	case CORGI_MIC:
+		mic = 1;
+		/* reset = mute headphone */
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
+		break;
+	case CORGI_LINE:
+		line = 1;
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
+		break;
+	case CORGI_HEADSET:
+		hs = 1;
+		mic = 1;
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
+		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
+		break;
+	}
+
+	if (corgi_spk_func == CORGI_SPK_ON)
+		spk = 1;
+
+	/* set the enpoints to their new connetion states */
+	snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
+	snd_soc_dapm_set_endpoint(codec, "Mic Jack", mic);
+	snd_soc_dapm_set_endpoint(codec, "Line Jack", line);
+	snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
+	snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
+
+	/* signal a DAPM event */
+	snd_soc_dapm_sync_endpoints(codec);
+}
+
+static int corgi_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->socdev->codec;
+
+	/* check the jack status at stream startup */
+	corgi_ext_control(codec);
+	return 0;
+}
+
+/* we need to unmute the HP at shutdown as the mute burns power on corgi */
+static int corgi_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->socdev->codec;
+
+	/* set = unmute headphone */
+	set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
+	set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
+	return 0;
+}
+
+static int corgi_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	unsigned int clk = 0;
+	int ret = 0;
+
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 48000:
+	case 96000:
+		clk = 12288000;
+		break;
+	case 11025:
+	case 22050:
+	case 44100:
+		clk = 11289600;
+		break;
+	}
+
+	/* set codec DAI configuration */
+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* set cpu DAI configuration */
+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* set the codec system clock for DAC and ADC */
+	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk,
+		SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	/* set the I2S system clock as input (unused) */
+	ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
+		SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct snd_soc_ops corgi_ops = {
+	.startup = corgi_startup,
+	.hw_params = corgi_hw_params,
+	.shutdown = corgi_shutdown,
+};
+
+static int corgi_get_jack(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = corgi_jack_func;
+	return 0;
+}
+
+static int corgi_set_jack(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	if (corgi_jack_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	corgi_jack_func = ucontrol->value.integer.value[0];
+	corgi_ext_control(codec);
+	return 1;
+}
+
+static int corgi_get_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = corgi_spk_func;
+	return 0;
+}
+
+static int corgi_set_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+	if (corgi_spk_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	corgi_spk_func = ucontrol->value.integer.value[0];
+	corgi_ext_control(codec);
+	return 1;
+}
+
+static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
+	else
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
+
+	return 0;
+}
+
+static int corgi_mic_event(struct snd_soc_dapm_widget *w, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
+	else
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
+
+	return 0;
+}
+
+/* corgi machine dapm widgets */
+static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
+SND_SOC_DAPM_HP("Headphone Jack", NULL),
+SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event),
+SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event),
+SND_SOC_DAPM_LINE("Line Jack", NULL),
+SND_SOC_DAPM_HP("Headset Jack", NULL),
+};
+
+/* Corgi machine audio map (connections to the codec pins) */
+static const char *audio_map[][3] = {
+
+	/* headset Jack  - in = micin, out = LHPOUT*/
+	{"Headset Jack", NULL, "LHPOUT"},
+
+	/* headphone connected to LHPOUT1, RHPOUT1 */
+	{"Headphone Jack", NULL, "LHPOUT"},
+	{"Headphone Jack", NULL, "RHPOUT"},
+
+	/* speaker connected to LOUT, ROUT */
+	{"Ext Spk", NULL, "ROUT"},
+	{"Ext Spk", NULL, "LOUT"},
+
+	/* mic is connected to MICIN (via right channel of headphone jack) */
+	{"MICIN", NULL, "Mic Jack"},
+
+	/* Same as the above but no mic bias for line signals */
+	{"MICIN", NULL, "Line Jack"},
+
+	{NULL, NULL, NULL},
+};
+
+static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
+	"Off"};
+static const char *spk_function[] = {"On", "Off"};
+static const struct soc_enum corgi_enum[] = {
+	SOC_ENUM_SINGLE_EXT(5, jack_function),
+	SOC_ENUM_SINGLE_EXT(2, spk_function),
+};
+
+static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
+	SOC_ENUM_EXT("Jack Function", corgi_enum[0], corgi_get_jack,
+		corgi_set_jack),
+	SOC_ENUM_EXT("Speaker Function", corgi_enum[1], corgi_get_spk,
+		corgi_set_spk),
+};
+
+/*
+ * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
+ */
+static int corgi_wm8731_init(struct snd_soc_codec *codec)
+{
+	int i, err;
+
+	snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
+	snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
+
+	/* Add corgi specific controls */
+	for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
+		err = snd_ctl_add(codec->card,
+			snd_soc_cnew(&wm8731_corgi_controls[i],codec, NULL));
+		if (err < 0)
+			return err;
+	}
+
+	/* Add corgi specific widgets */
+	for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
+		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+	}
+
+	/* Set up corgi specific audio path audio_map */
+	for(i = 0; audio_map[i][0] != NULL; i++) {
+		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+			audio_map[i][1], audio_map[i][2]);
+	}
+
+	snd_soc_dapm_sync_endpoints(codec);
+	return 0;
+}
+
+/* corgi digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link corgi_dai = {
+	.name = "WM8731",
+	.stream_name = "WM8731",
+	.cpu_dai = &pxa_i2s_dai,
+	.codec_dai = &wm8731_dai,
+	.init = corgi_wm8731_init,
+	.ops = &corgi_ops,
+};
+
+/* corgi audio machine driver */
+static struct snd_soc_machine snd_soc_machine_corgi = {
+	.name = "Corgi",
+	.dai_link = &corgi_dai,
+	.num_links = 1,
+};
+
+/* corgi audio private data */
+static struct wm8731_setup_data corgi_wm8731_setup = {
+	.i2c_address = 0x1b,
+};
+
+/* corgi audio subsystem */
+static struct snd_soc_device corgi_snd_devdata = {
+	.machine = &snd_soc_machine_corgi,
+	.platform = &pxa2xx_soc_platform,
+	.codec_dev = &soc_codec_dev_wm8731,
+	.codec_data = &corgi_wm8731_setup,
+};
+
+static struct platform_device *corgi_snd_device;
+
+static int __init corgi_init(void)
+{
+	int ret;
+
+	if (!(machine_is_corgi() || machine_is_shepherd() || machine_is_husky()))
+		return -ENODEV;
+
+	corgi_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!corgi_snd_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(corgi_snd_device, &corgi_snd_devdata);
+	corgi_snd_devdata.dev = &corgi_snd_device->dev;
+	ret = platform_device_add(corgi_snd_device);
+
+	if (ret)
+		platform_device_put(corgi_snd_device);
+
+	return ret;
+}
+
+static void __exit corgi_exit(void)
+{
+	platform_device_unregister(corgi_snd_device);
+}
+
+module_init(corgi_init);
+module_exit(corgi_exit);
+
+/* Module information */
+MODULE_AUTHOR("Richard Purdie");
+MODULE_DESCRIPTION("ALSA SoC Corgi");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
new file mode 100644
index 0000000..0915cf7
--- /dev/null
+++ b/sound/soc/pxa/poodle.c
@@ -0,0 +1,352 @@
+/*
+ * poodle.c  --  SoC audio for Poodle
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *          Richard Purdie <richard@openedhand.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware/locomo.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/poodle.h>
+#include <asm/arch/audio.h>
+
+#include "../codecs/wm8731.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-i2s.h"
+
+#define POODLE_HP        1
+#define POODLE_HP_OFF    0
+#define POODLE_SPK_ON    1
+#define POODLE_SPK_OFF   0
+
+ /* audio clock in Hz - rounded from 12.235MHz */
+#define POODLE_AUDIO_CLOCK 12288000
+
+static int poodle_jack_func;
+static int poodle_spk_func;
+
+static void poodle_ext_control(struct snd_soc_codec *codec)
+{
+	int spk = 0;
+
+	/* set up jack connection */
+	if (poodle_jack_func == POODLE_HP) {
+		/* set = unmute headphone */
+		locomo_gpio_write(&poodle_locomo_device.dev,
+			POODLE_LOCOMO_GPIO_MUTE_L, 1);
+		locomo_gpio_write(&poodle_locomo_device.dev,
+			POODLE_LOCOMO_GPIO_MUTE_R, 1);
+		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
+	} else {
+		locomo_gpio_write(&poodle_locomo_device.dev,
+			POODLE_LOCOMO_GPIO_MUTE_L, 0);
+		locomo_gpio_write(&poodle_locomo_device.dev,
+			POODLE_LOCOMO_GPIO_MUTE_R, 0);
+		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
+	}
+
+	if (poodle_spk_func == POODLE_SPK_ON)
+		spk = 1;
+
+	/* set the enpoints to their new connetion states */
+	snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
+
+	/* signal a DAPM event */
+	snd_soc_dapm_sync_endpoints(codec);
+}
+
+static int poodle_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->socdev->codec;
+
+	/* check the jack status at stream startup */
+	poodle_ext_control(codec);
+	return 0;
+}
+
+/* we need to unmute the HP at shutdown as the mute burns power on poodle */
+static int poodle_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->socdev->codec;
+
+	/* set = unmute headphone */
+	locomo_gpio_write(&poodle_locomo_device.dev,
+		POODLE_LOCOMO_GPIO_MUTE_L, 1);
+	locomo_gpio_write(&poodle_locomo_device.dev,
+		POODLE_LOCOMO_GPIO_MUTE_R, 1);
+	return 0;
+}
+
+static int poodle_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	unsigned int clk = 0;
+	int ret = 0;
+
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 48000:
+	case 96000:
+		clk = 12288000;
+		break;
+	case 11025:
+	case 22050:
+	case 44100:
+		clk = 11289600;
+		break;
+	}
+
+	/* set codec DAI configuration */
+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* set cpu DAI configuration */
+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* set the codec system clock for DAC and ADC */
+	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk,
+		SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	/* set the I2S system clock as input (unused) */
+	ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
+		SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct snd_soc_ops poodle_ops = {
+	.startup = poodle_startup,
+	.hw_params = poodle_hw_params,
+	.shutdown = poodle_shutdown,
+};
+
+static int poodle_get_jack(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = poodle_jack_func;
+	return 0;
+}
+
+static int poodle_set_jack(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+	if (poodle_jack_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	poodle_jack_func = ucontrol->value.integer.value[0];
+	poodle_ext_control(codec);
+	return 1;
+}
+
+static int poodle_get_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = poodle_spk_func;
+	return 0;
+}
+
+static int poodle_set_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+	if (poodle_spk_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	poodle_spk_func = ucontrol->value.integer.value[0];
+	poodle_ext_control(codec);
+	return 1;
+}
+
+static int poodle_amp_event(struct snd_soc_dapm_widget *w, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		locomo_gpio_write(&poodle_locomo_device.dev,
+			POODLE_LOCOMO_GPIO_AMP_ON, 0);
+	else
+		locomo_gpio_write(&poodle_locomo_device.dev,
+			POODLE_LOCOMO_GPIO_AMP_ON, 1);
+
+	return 0;
+}
+
+/* poodle machine dapm widgets */
+static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
+SND_SOC_DAPM_HP("Headphone Jack", NULL),
+SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event),
+};
+
+/* Corgi machine audio_mapnections to the codec pins */
+static const char *audio_map[][3] = {
+
+	/* headphone connected to LHPOUT1, RHPOUT1 */
+	{"Headphone Jack", NULL, "LHPOUT"},
+	{"Headphone Jack", NULL, "RHPOUT"},
+
+	/* speaker connected to LOUT, ROUT */
+	{"Ext Spk", NULL, "ROUT"},
+	{"Ext Spk", NULL, "LOUT"},
+
+	{NULL, NULL, NULL},
+};
+
+static const char *jack_function[] = {"Off", "Headphone"};
+static const char *spk_function[] = {"Off", "On"};
+static const struct soc_enum poodle_enum[] = {
+	SOC_ENUM_SINGLE_EXT(2, jack_function),
+	SOC_ENUM_SINGLE_EXT(2, spk_function),
+};
+
+static const snd_kcontrol_new_t wm8731_poodle_controls[] = {
+	SOC_ENUM_EXT("Jack Function", poodle_enum[0], poodle_get_jack,
+		poodle_set_jack),
+	SOC_ENUM_EXT("Speaker Function", poodle_enum[1], poodle_get_spk,
+		poodle_set_spk),
+};
+
+/*
+ * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
+ */
+static int poodle_wm8731_init(struct snd_soc_codec *codec)
+{
+	int i, err;
+
+	snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
+	snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
+	snd_soc_dapm_set_endpoint(codec, "MICIN", 1);
+
+	/* Add poodle specific controls */
+	for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
+		err = snd_ctl_add(codec->card,
+			snd_soc_cnew(&wm8731_poodle_controls[i],codec, NULL));
+		if (err < 0)
+			return err;
+	}
+
+	/* Add poodle specific widgets */
+	for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
+		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+	}
+
+	/* Set up poodle specific audio path audio_map */
+	for (i = 0; audio_map[i][0] != NULL; i++) {
+		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+			audio_map[i][1], audio_map[i][2]);
+	}
+
+	snd_soc_dapm_sync_endpoints(codec);
+	return 0;
+}
+
+/* poodle digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link poodle_dai = {
+	.name = "WM8731",
+	.stream_name = "WM8731",
+	.cpu_dai = &pxa_i2s_dai,
+	.codec_dai = &wm8731_dai,
+	.init = poodle_wm8731_init,
+	.ops = &poodle_ops,
+};
+
+/* poodle audio machine driver */
+static struct snd_soc_machine snd_soc_machine_poodle = {
+	.name = "Poodle",
+	.dai_link = &poodle_dai,
+	.num_links = 1,
+};
+
+/* poodle audio private data */
+static struct wm8731_setup_data poodle_wm8731_setup = {
+	.i2c_address = 0x1b,
+};
+
+/* poodle audio subsystem */
+static struct snd_soc_device poodle_snd_devdata = {
+	.machine = &snd_soc_machine_poodle,
+	.platform = &pxa2xx_soc_platform,
+	.codec_dev = &soc_codec_dev_wm8731,
+	.codec_data = &poodle_wm8731_setup,
+};
+
+static struct platform_device *poodle_snd_device;
+
+static int __init poodle_init(void)
+{
+	int ret;
+
+	if (!machine_is_poodle())
+		return -ENODEV;
+
+	locomo_gpio_set_dir(&poodle_locomo_device.dev,
+		POODLE_LOCOMO_GPIO_AMP_ON, 0);
+	/* should we mute HP at startup - burning power ?*/
+	locomo_gpio_set_dir(&poodle_locomo_device.dev,
+		POODLE_LOCOMO_GPIO_MUTE_L, 0);
+	locomo_gpio_set_dir(&poodle_locomo_device.dev,
+		POODLE_LOCOMO_GPIO_MUTE_R, 0);
+
+	poodle_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!poodle_snd_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(poodle_snd_device, &poodle_snd_devdata);
+	poodle_snd_devdata.dev = &poodle_snd_device->dev;
+	ret = platform_device_add(poodle_snd_device);
+
+	if (ret)
+		platform_device_put(poodle_snd_device);
+
+	return ret;
+}
+
+static void __exit poodle_exit(void)
+{
+	platform_device_unregister(poodle_snd_device);
+}
+
+module_init(poodle_init);
+module_exit(poodle_exit);
+
+/* Module information */
+MODULE_AUTHOR("Richard Purdie");
+MODULE_DESCRIPTION("ALSA SoC Poodle");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
new file mode 100644
index 0000000..1bbbeff
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -0,0 +1,431 @@
+/*
+ * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip.
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Dec 02, 2004
+ * Copyright:	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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <asm/irq.h>
+#include <linux/mutex.h>
+#include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/audio.h>
+
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+
+static DEFINE_MUTEX(car_mutex);
+static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
+static volatile long gsr_bits;
+
+/*
+ * Beware PXA27x bugs:
+ *
+ *   o Slot 12 read from modem space will hang controller.
+ *   o CDONE, SDONE interrupt fails after any slot 12 IO.
+ *
+ * We therefore have an hybrid approach for waiting on SDONE (interrupt or
+ * 1 jiffy timeout if interrupt never comes).
+ */
+
+static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
+	unsigned short reg)
+{
+	unsigned short val = -1;
+	volatile u32 *reg_addr;
+
+	mutex_lock(&car_mutex);
+
+	/* set up primary or secondary codec/modem space */
+#ifdef CONFIG_PXA27x
+	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+#else
+	if (reg == AC97_GPIO_STATUS)
+		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
+	else
+		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+#endif
+	reg_addr += (reg >> 1);
+
+#ifndef CONFIG_PXA27x
+	if (reg == AC97_GPIO_STATUS) {
+		/* read from controller cache */
+		val = *reg_addr;
+		goto out;
+	}
+#endif
+
+	/* start read access across the ac97 link */
+	GSR = GSR_CDONE | GSR_SDONE;
+	gsr_bits = 0;
+	val = *reg_addr;
+
+	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
+	if (!((GSR | gsr_bits) & GSR_SDONE)) {
+		printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
+				__FUNCTION__, reg, GSR | gsr_bits);
+		val = -1;
+		goto out;
+	}
+
+	/* valid data now */
+	GSR = GSR_CDONE | GSR_SDONE;
+	gsr_bits = 0;
+	val = *reg_addr;
+	/* but we've just started another cycle... */
+	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
+
+out:	mutex_unlock(&car_mutex);
+	return val;
+}
+
+static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+	unsigned short val)
+{
+	volatile u32 *reg_addr;
+
+	mutex_lock(&car_mutex);
+
+	/* set up primary or secondary codec/modem space */
+#ifdef CONFIG_PXA27x
+	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+#else
+	if (reg == AC97_GPIO_STATUS)
+		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
+	else
+		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+#endif
+	reg_addr += (reg >> 1);
+
+	GSR = GSR_CDONE | GSR_SDONE;
+	gsr_bits = 0;
+	*reg_addr = val;
+	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
+	if (!((GSR | gsr_bits) & GSR_CDONE))
+		printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
+				__FUNCTION__, reg, GSR | gsr_bits);
+
+	mutex_unlock(&car_mutex);
+}
+
+static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
+{
+	gsr_bits = 0;
+
+#ifdef CONFIG_PXA27x
+	/* warm reset broken on Bulverde,
+	   so manually keep AC97 reset high */
+	pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
+	udelay(10);
+	GCR |= GCR_WARM_RST;
+	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+	udelay(500);
+#else
+	GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
+	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
+#endif
+
+	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
+		printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
+				 __FUNCTION__, gsr_bits);
+
+	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
+}
+
+static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
+{
+	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
+	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
+
+	gsr_bits = 0;
+#ifdef CONFIG_PXA27x
+	/* PXA27x Developers Manual section 13.5.2.2.1 */
+	pxa_set_cken(1 << 31, 1);
+	udelay(5);
+	pxa_set_cken(1 << 31, 0);
+	GCR = GCR_COLD_RST;
+	udelay(50);
+#else
+	GCR = GCR_COLD_RST;
+	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
+	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
+#endif
+
+	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
+		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
+				 __FUNCTION__, gsr_bits);
+
+	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
+}
+
+static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
+{
+	long status;
+
+	status = GSR;
+	if (status) {
+		GSR = status;
+		gsr_bits |= status;
+		wake_up(&gsr_wq);
+
+#ifdef CONFIG_PXA27x
+		/* Although we don't use those we still need to clear them
+		   since they tend to spuriously trigger when MMC is used
+		   (hardware bug? go figure)... */
+		MISR = MISR_EOC;
+		PISR = PISR_EOC;
+		MCSR = MCSR_EOC;
+#endif
+
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+struct snd_ac97_bus_ops soc_ac97_ops = {
+	.read	= pxa2xx_ac97_read,
+	.write	= pxa2xx_ac97_write,
+	.warm_reset	= pxa2xx_ac97_warm_reset,
+	.reset	= pxa2xx_ac97_cold_reset,
+};
+
+static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
+	.name			= "AC97 PCM Stereo out",
+	.dev_addr		= __PREG(PCDR),
+	.drcmr			= &DRCMRTXPCDR,
+	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
+				  DCMD_BURST32 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
+	.name			= "AC97 PCM Stereo in",
+	.dev_addr		= __PREG(PCDR),
+	.drcmr			= &DRCMRRXPCDR,
+	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
+				  DCMD_BURST32 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
+	.name			= "AC97 Aux PCM (Slot 5) Mono out",
+	.dev_addr		= __PREG(MODR),
+	.drcmr			= &DRCMRTXMODR,
+	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
+				  DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
+	.name			= "AC97 Aux PCM (Slot 5) Mono in",
+	.dev_addr		= __PREG(MODR),
+	.drcmr			= &DRCMRRXMODR,
+	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
+				  DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
+	.name			= "AC97 Mic PCM (Slot 6) Mono in",
+	.dev_addr		= __PREG(MCDR),
+	.drcmr			= &DRCMRRXMCDR,
+	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
+				  DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+#ifdef CONFIG_PM
+static int pxa2xx_ac97_suspend(struct platform_device *pdev,
+	struct snd_soc_cpu_dai *dai)
+{
+	GCR |= GCR_ACLINK_OFF;
+	pxa_set_cken(CKEN2_AC97, 0);
+	return 0;
+}
+
+static int pxa2xx_ac97_resume(struct platform_device *pdev,
+	struct snd_soc_cpu_dai *dai)
+{
+	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
+	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
+	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
+	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
+#ifdef CONFIG_PXA27x
+	/* Use GPIO 113 as AC97 Reset on Bulverde */
+	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+#endif
+	pxa_set_cken(CKEN2_AC97, 1);
+	return 0;
+}
+
+#else
+#define pxa2xx_ac97_suspend	NULL
+#define pxa2xx_ac97_resume	NULL
+#endif
+
+static int pxa2xx_ac97_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL);
+	if (ret < 0)
+		goto err;
+
+	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
+	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
+	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
+	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
+#ifdef CONFIG_PXA27x
+	/* Use GPIO 113 as AC97 Reset on Bulverde */
+	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+#endif
+	pxa_set_cken(CKEN2_AC97, 1);
+	return 0;
+
+ err:
+	if (CKEN & CKEN2_AC97) {
+		GCR |= GCR_ACLINK_OFF;
+		free_irq(IRQ_AC97, NULL);
+		pxa_set_cken(CKEN2_AC97, 0);
+	}
+	return ret;
+}
+
+static void pxa2xx_ac97_remove(struct platform_device *pdev)
+{
+	GCR |= GCR_ACLINK_OFF;
+	free_irq(IRQ_AC97, NULL);
+	pxa_set_cken(CKEN2_AC97, 0);
+}
+
+static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
+	else
+		cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in;
+
+	return 0;
+}
+
+static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
+	else
+		cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
+
+	return 0;
+}
+
+static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		return -ENODEV;
+	else
+		cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in;
+
+	return 0;
+}
+
+#define PXA2XX_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
+		SNDRV_PCM_RATE_48000)
+
+/*
+ * There is only 1 physical AC97 interface for pxa2xx, but it
+ * has extra fifo's that can be used for aux DACs and ADCs.
+ */
+struct snd_soc_cpu_dai pxa_ac97_dai[] = {
+{
+	.name = "pxa2xx-ac97",
+	.id = 0,
+	.type = SND_SOC_DAI_AC97,
+	.probe = pxa2xx_ac97_probe,
+	.remove = pxa2xx_ac97_remove,
+	.suspend = pxa2xx_ac97_suspend,
+	.resume = pxa2xx_ac97_resume,
+	.playback = {
+		.stream_name = "AC97 Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = PXA2XX_AC97_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.capture = {
+		.stream_name = "AC97 Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = PXA2XX_AC97_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.hw_params = pxa2xx_ac97_hw_params,},
+},
+{
+	.name = "pxa2xx-ac97-aux",
+	.id = 1,
+	.type = SND_SOC_DAI_AC97,
+	.playback = {
+		.stream_name = "AC97 Aux Playback",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = PXA2XX_AC97_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.capture = {
+		.stream_name = "AC97 Aux Capture",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = PXA2XX_AC97_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.hw_params = pxa2xx_ac97_hw_aux_params,},
+},
+{
+	.name = "pxa2xx-ac97-mic",
+	.id = 2,
+	.type = SND_SOC_DAI_AC97,
+	.capture = {
+		.stream_name = "AC97 Mic Capture",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = PXA2XX_AC97_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.hw_params = pxa2xx_ac97_hw_mic_params,},
+},
+};
+
+EXPORT_SYMBOL_GPL(pxa_ac97_dai);
+EXPORT_SYMBOL_GPL(soc_ac97_ops);
+
+MODULE_AUTHOR("Nicolas Pitre");
+MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-ac97.h b/sound/soc/pxa/pxa2xx-ac97.h
new file mode 100644
index 0000000..4c4b882
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-ac97.h
@@ -0,0 +1,22 @@
+/*
+ * linux/sound/arm/pxa2xx-ac97.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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _PXA2XX_AC97_H
+#define _PXA2XX_AC97_H
+
+/* pxa2xx DAI ID's */
+#define PXA2XX_DAI_AC97_HIFI	0
+#define PXA2XX_DAI_AC97_AUX		1
+#define PXA2XX_DAI_AC97_MIC		2
+
+extern struct snd_soc_cpu_dai pxa_ac97_dai[3];
+
+/* platform data */
+extern struct snd_ac97_bus_ops pxa2xx_ac97_ops;
+
+#endif
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
new file mode 100644
index 0000000..575a613
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -0,0 +1,318 @@
+/*
+ * pxa2xx-i2s.c  --  ALSA Soc Audio Layer
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.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.
+ *
+ *  Revision history
+ *    12th Aug 2005   Initial version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/audio.h>
+
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-i2s.h"
+
+struct pxa_i2s_port {
+	u32 sadiv;
+	u32 sacr0;
+	u32 sacr1;
+	u32 saimr;
+	int master;
+	u32 fmt;
+};
+static struct pxa_i2s_port pxa_i2s;
+
+static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
+	.name			= "I2S PCM Stereo out",
+	.dev_addr		= __PREG(SADR),
+	.drcmr			= &DRCMRTXSADR,
+	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
+				  DCMD_BURST32 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
+	.name			= "I2S PCM Stereo in",
+	.dev_addr		= __PREG(SADR),
+	.drcmr			= &DRCMRRXSADR,
+	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
+				  DCMD_BURST32 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_gpio gpio_bus[] = {
+	{ /* I2S SoC Slave */
+		.rx = GPIO29_SDATA_IN_I2S_MD,
+		.tx = GPIO30_SDATA_OUT_I2S_MD,
+		.clk = GPIO28_BITCLK_IN_I2S_MD,
+		.frm = GPIO31_SYNC_I2S_MD,
+	},
+	{ /* I2S SoC Master */
+#ifdef CONFIG_PXA27x
+		.sys = GPIO113_I2S_SYSCLK_MD,
+#else
+		.sys = GPIO32_SYSCLK_I2S_MD,
+#endif
+		.rx = GPIO29_SDATA_IN_I2S_MD,
+		.tx = GPIO30_SDATA_OUT_I2S_MD,
+		.clk = GPIO28_BITCLK_OUT_I2S_MD,
+		.frm = GPIO31_SYNC_I2S_MD,
+	},
+};
+
+static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+
+	if (!cpu_dai->active) {
+		SACR0 |= SACR0_RST;
+		SACR0 = 0;
+	}
+
+	return 0;
+}
+
+/* wait for I2S controller to be ready */
+static int pxa_i2s_wait(void)
+{
+	int i;
+
+	/* flush the Rx FIFO */
+	for(i = 0; i < 16; i++)
+		SADR;
+	return 0;
+}
+
+static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+		unsigned int fmt)
+{
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		pxa_i2s.fmt = 0;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		pxa_i2s.fmt = SACR1_AMSL;
+		break;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		pxa_i2s.master = 1;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		pxa_i2s.master = 0;
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	if (clk_id != PXA2XX_I2S_SYSCLK)
+		return -ENODEV;
+
+	if (pxa_i2s.master && dir == SND_SOC_CLOCK_OUT)
+		pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
+
+	return 0;
+}
+
+static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
+	pxa_set_cken(CKEN8_I2S, 1);
+	pxa_i2s_wait();
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
+	else
+		cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in;
+
+	/* is port used by another stream */
+	if (!(SACR0 & SACR0_ENB)) {
+
+		SACR0 = 0;
+		SACR1 = 0;
+		if (pxa_i2s.master)
+			SACR0 |= SACR0_BCKD;
+
+		SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
+		SACR1 |= pxa_i2s.fmt;
+	}
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		SAIMR |= SAIMR_TFS;
+	else
+		SAIMR |= SAIMR_RFS;
+
+	switch (params_rate(params)) {
+	case 8000:
+		SADIV = 0x48;
+		break;
+	case 11025:
+		SADIV = 0x34;
+		break;
+	case 16000:
+		SADIV = 0x24;
+		break;
+	case 22050:
+		SADIV = 0x1a;
+		break;
+	case 44100:
+		SADIV = 0xd;
+		break;
+	case 48000:
+		SADIV = 0xc;
+		break;
+	case 96000: /* not in manual and possibly slightly inaccurate */
+		SADIV = 0x6;
+		break;
+	}
+
+	return 0;
+}
+
+static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		SACR0 |= SACR0_ENB;
+		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
+{
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		SACR1 |= SACR1_DRPL;
+		SAIMR &= ~SAIMR_TFS;
+	} else {
+		SACR1 |= SACR1_DREC;
+		SAIMR &= ~SAIMR_RFS;
+	}
+
+	if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
+		SACR0 &= ~SACR0_ENB;
+		pxa_i2s_wait();
+		pxa_set_cken(CKEN8_I2S, 0);
+	}
+}
+
+#ifdef CONFIG_PM
+static int pxa2xx_i2s_suspend(struct platform_device *dev,
+	struct snd_soc_cpu_dai *dai)
+{
+	if (!dai->active)
+		return 0;
+
+	/* store registers */
+	pxa_i2s.sacr0 = SACR0;
+	pxa_i2s.sacr1 = SACR1;
+	pxa_i2s.saimr = SAIMR;
+	pxa_i2s.sadiv = SADIV;
+
+	/* deactivate link */
+	SACR0 &= ~SACR0_ENB;
+	pxa_i2s_wait();
+	return 0;
+}
+
+static int pxa2xx_i2s_resume(struct platform_device *pdev,
+	struct snd_soc_cpu_dai *dai)
+{
+	if (!dai->active)
+		return 0;
+
+	pxa_i2s_wait();
+
+	SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB;
+	SACR1 = pxa_i2s.sacr1;
+	SAIMR = pxa_i2s.saimr;
+	SADIV = pxa_i2s.sadiv;
+	SACR0 |= SACR0_ENB;
+
+	return 0;
+}
+
+#else
+#define pxa2xx_i2s_suspend	NULL
+#define pxa2xx_i2s_resume	NULL
+#endif
+
+#define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
+		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
+
+struct snd_soc_cpu_dai pxa_i2s_dai = {
+	.name = "pxa2xx-i2s",
+	.id = 0,
+	.type = SND_SOC_DAI_I2S,
+	.suspend = pxa2xx_i2s_suspend,
+	.resume = pxa2xx_i2s_resume,
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = PXA2XX_I2S_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = PXA2XX_I2S_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.startup = pxa2xx_i2s_startup,
+		.shutdown = pxa2xx_i2s_shutdown,
+		.trigger = pxa2xx_i2s_trigger,
+		.hw_params = pxa2xx_i2s_hw_params,},
+	.dai_ops = {
+		.set_fmt = pxa2xx_i2s_set_dai_fmt,
+		.set_sysclk = pxa2xx_i2s_set_dai_sysclk,
+	},
+};
+
+EXPORT_SYMBOL_GPL(pxa_i2s_dai);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-i2s.h b/sound/soc/pxa/pxa2xx-i2s.h
new file mode 100644
index 0000000..a2484f0
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-i2s.h
@@ -0,0 +1,20 @@
+/*
+ * linux/sound/arm/pxa2xx-i2s.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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _PXA2XX_I2S_H
+#define _PXA2XX_I2S_H
+
+/* pxa2xx DAI ID's */
+#define PXA2XX_DAI_I2S			0
+
+/* I2S clock */
+#define PXA2XX_I2S_SYSCLK		0
+
+extern struct snd_soc_cpu_dai pxa_i2s_dai;
+
+#endif
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
new file mode 100644
index 0000000..35e8fa3
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -0,0 +1,372 @@
+/*
+ * linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Nov 30, 2004
+ * Copyright:	(C) 2004 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/dma.h>
+#include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/audio.h>
+
+#include "pxa2xx-pcm.h"
+
+static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
+	.info			= SNDRV_PCM_INFO_MMAP |
+				  SNDRV_PCM_INFO_MMAP_VALID |
+				  SNDRV_PCM_INFO_INTERLEAVED |
+				  SNDRV_PCM_INFO_PAUSE |
+				  SNDRV_PCM_INFO_RESUME,
+	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
+					SNDRV_PCM_FMTBIT_S24_LE |
+					SNDRV_PCM_FMTBIT_S32_LE,
+	.period_bytes_min	= 32,
+	.period_bytes_max	= 8192 - 32,
+	.periods_min		= 1,
+	.periods_max		= PAGE_SIZE/sizeof(pxa_dma_desc),
+	.buffer_bytes_max	= 128 * 1024,
+	.fifo_size		= 32,
+};
+
+struct pxa2xx_runtime_data {
+	int dma_ch;
+	struct pxa2xx_pcm_dma_params *params;
+	pxa_dma_desc *dma_desc_array;
+	dma_addr_t dma_desc_array_phys;
+};
+
+static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
+{
+	struct snd_pcm_substream *substream = dev_id;
+	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
+	int dcsr;
+
+	dcsr = DCSR(dma_ch);
+	DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
+
+	if (dcsr & DCSR_ENDINTR) {
+		snd_pcm_period_elapsed(substream);
+	} else {
+		printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
+			prtd->params->name, dma_ch, dcsr );
+	}
+}
+
+static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct pxa2xx_runtime_data *prtd = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
+	size_t totsize = params_buffer_bytes(params);
+	size_t period = params_period_bytes(params);
+	pxa_dma_desc *dma_desc;
+	dma_addr_t dma_buff_phys, next_desc_phys;
+	int ret;
+
+	/* return if this is a bufferless transfer e.g.
+	 * codec <--> BT codec or GSM modem -- lg FIXME */
+	 if (!dma)
+	 	return 0;
+
+	/* this may get called several times by oss emulation
+	 * with different params */
+	if (prtd->params == NULL) {
+		prtd->params = dma;
+		ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
+			      pxa2xx_pcm_dma_irq, substream);
+		if (ret < 0)
+			return ret;
+		prtd->dma_ch = ret;
+	} else if (prtd->params != dma) {
+		pxa_free_dma(prtd->dma_ch);
+		prtd->params = dma;
+		ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
+			      pxa2xx_pcm_dma_irq, substream);
+		if (ret < 0)
+			return ret;
+		prtd->dma_ch = ret;
+	}
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+	runtime->dma_bytes = totsize;
+
+	dma_desc = prtd->dma_desc_array;
+	next_desc_phys = prtd->dma_desc_array_phys;
+	dma_buff_phys = runtime->dma_addr;
+	do {
+		next_desc_phys += sizeof(pxa_dma_desc);
+		dma_desc->ddadr = next_desc_phys;
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			dma_desc->dsadr = dma_buff_phys;
+			dma_desc->dtadr = prtd->params->dev_addr;
+		} else {
+			dma_desc->dsadr = prtd->params->dev_addr;
+			dma_desc->dtadr = dma_buff_phys;
+		}
+		if (period > totsize)
+			period = totsize;
+		dma_desc->dcmd = prtd->params->dcmd | period | DCMD_ENDIRQEN;
+		dma_desc++;
+		dma_buff_phys += period;
+	} while (totsize -= period);
+	dma_desc[-1].ddadr = prtd->dma_desc_array_phys;
+
+	return 0;
+}
+
+static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
+
+	if (prtd && prtd->params)
+		*prtd->params->drcmr = 0;
+
+	if (prtd->dma_ch) {
+		snd_pcm_set_runtime_buffer(substream, NULL);
+		pxa_free_dma(prtd->dma_ch);
+		prtd->dma_ch = 0;
+	}
+
+	return 0;
+}
+
+static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
+
+	DCSR(prtd->dma_ch) &= ~DCSR_RUN;
+	DCSR(prtd->dma_ch) = 0;
+	DCMD(prtd->dma_ch) = 0;
+	*prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD;
+
+	return 0;
+}
+
+static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
+		DCSR(prtd->dma_ch) = DCSR_RUN;
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		DCSR(prtd->dma_ch) &= ~DCSR_RUN;
+		break;
+
+	case SNDRV_PCM_TRIGGER_RESUME:
+		DCSR(prtd->dma_ch) |= DCSR_RUN;
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
+		DCSR(prtd->dma_ch) |= DCSR_RUN;
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static snd_pcm_uframes_t
+pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct pxa2xx_runtime_data *prtd = runtime->private_data;
+
+	dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+			 DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch);
+	snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+
+	if (x == runtime->buffer_size)
+		x = 0;
+	return x;
+}
+
+static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct pxa2xx_runtime_data *prtd;
+	int ret;
+
+	snd_soc_set_runtime_hwparams(substream, &pxa2xx_pcm_hardware);
+
+	/*
+	 * For mysterious reasons (and despite what the manual says)
+	 * playback samples are lost if the DMA count is not a multiple
+	 * of the DMA burst size.  Let's add a rule to enforce that.
+	 */
+	ret = snd_pcm_hw_constraint_step(runtime, 0,
+		SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
+	if (ret)
+		goto out;
+
+	ret = snd_pcm_hw_constraint_step(runtime, 0,
+		SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
+	if (ret)
+		goto out;
+
+	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		goto out;
+
+	prtd = kzalloc(sizeof(struct pxa2xx_runtime_data), GFP_KERNEL);
+	if (prtd == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	prtd->dma_desc_array =
+		dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
+				       &prtd->dma_desc_array_phys, GFP_KERNEL);
+	if (!prtd->dma_desc_array) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	runtime->private_data = prtd;
+	return 0;
+
+ err1:
+	kfree(prtd);
+ out:
+	return ret;
+}
+
+static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct pxa2xx_runtime_data *prtd = runtime->private_data;
+
+	dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
+			      prtd->dma_desc_array, prtd->dma_desc_array_phys);
+	kfree(prtd);
+	return 0;
+}
+
+static int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
+	struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+				     runtime->dma_area,
+				     runtime->dma_addr,
+				     runtime->dma_bytes);
+}
+
+struct snd_pcm_ops pxa2xx_pcm_ops = {
+	.open		= pxa2xx_pcm_open,
+	.close		= pxa2xx_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= pxa2xx_pcm_hw_params,
+	.hw_free	= pxa2xx_pcm_hw_free,
+	.prepare	= pxa2xx_pcm_prepare,
+	.trigger	= pxa2xx_pcm_trigger,
+	.pointer	= pxa2xx_pcm_pointer,
+	.mmap		= pxa2xx_pcm_mmap,
+};
+
+static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+					   &buf->addr, GFP_KERNEL);
+	if (!buf->area)
+		return -ENOMEM;
+	buf->bytes = size;
+	return 0;
+}
+
+static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+	int stream;
+
+	for (stream = 0; stream < 2; stream++) {
+		substream = pcm->streams[stream].substream;
+		if (!substream)
+			continue;
+
+		buf = &substream->dma_buffer;
+		if (!buf->area)
+			continue;
+
+		dma_free_writecombine(pcm->card->dev, buf->bytes,
+				      buf->area, buf->addr);
+		buf->area = NULL;
+	}
+}
+
+static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK;
+
+int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
+	struct snd_pcm *pcm)
+{
+	int ret = 0;
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &pxa2xx_pcm_dmamask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_32BIT_MASK;
+
+	if (dai->playback.channels_min) {
+		ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret)
+			goto out;
+	}
+
+	if (dai->capture.channels_min) {
+		ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_CAPTURE);
+		if (ret)
+			goto out;
+	}
+ out:
+	return ret;
+}
+
+struct snd_soc_platform pxa2xx_soc_platform = {
+	.name		= "pxa2xx-audio",
+	.pcm_ops 	= &pxa2xx_pcm_ops,
+	.pcm_new	= pxa2xx_pcm_new,
+	.pcm_free	= pxa2xx_pcm_free_dma_buffers,
+};
+
+EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
+
+MODULE_AUTHOR("Nicolas Pitre");
+MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h
new file mode 100644
index 0000000..54c9c75
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-pcm.h
@@ -0,0 +1,34 @@
+/*
+ * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Nov 30, 2004
+ * Copyright:	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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _PXA2XX_PCM_H
+#define _PXA2XX_PCM_H
+
+struct pxa2xx_pcm_dma_params {
+	char *name;			/* stream identifier */
+	u32 dcmd;			/* DMA descriptor dcmd field */
+	volatile u32 *drcmr;		/* the DMA request channel to use */
+	u32 dev_addr;			/* device physical address for DMA */
+};
+
+struct pxa2xx_gpio {
+	u32 sys;
+	u32	rx;
+	u32 tx;
+	u32 clk;
+	u32 frm;
+};
+
+/* platform data */
+extern struct snd_soc_platform pxa2xx_soc_platform;
+
+#endif
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
new file mode 100644
index 0000000..80e8210
--- /dev/null
+++ b/sound/soc/pxa/spitz.c
@@ -0,0 +1,394 @@
+/*
+ * spitz.c  --  SoC audio for Sharp SL-Cxx00 models Spitz, Borzoi and Akita
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *          Richard Purdie <richard@openedhand.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.
+ *
+ *  Revision history
+ *    30th Nov 2005   Initial version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware/scoop.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/akita.h>
+#include <asm/arch/spitz.h>
+#include <asm/mach-types.h>
+#include "../codecs/wm8750.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-i2s.h"
+
+#define SPITZ_HP        0
+#define SPITZ_MIC       1
+#define SPITZ_LINE      2
+#define SPITZ_HEADSET   3
+#define SPITZ_HP_OFF    4
+#define SPITZ_SPK_ON    0
+#define SPITZ_SPK_OFF   1
+
+ /* audio clock in Hz - rounded from 12.235MHz */
+#define SPITZ_AUDIO_CLOCK 12288000
+
+static int spitz_jack_func;
+static int spitz_spk_func;
+
+static void spitz_ext_control(struct snd_soc_codec *codec)
+{
+	if (spitz_spk_func == SPITZ_SPK_ON)
+		snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
+	else
+		snd_soc_dapm_set_endpoint(codec, "Ext Spk", 0);
+
+	/* set up jack connection */
+	switch (spitz_jack_func) {
+	case SPITZ_HP:
+		/* enable and unmute hp jack, disable mic bias */
+		snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
+		set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
+		set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
+		break;
+	case SPITZ_MIC:
+		/* enable mic jack and bias, mute hp */
+		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
+		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
+		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
+		break;
+	case SPITZ_LINE:
+		/* enable line jack, disable mic bias and mute hp */
+		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Line Jack", 1);
+		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
+		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
+		break;
+	case SPITZ_HEADSET:
+		/* enable and unmute headset jack enable mic bias, mute L hp */
+		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
+		snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Headset Jack", 1);
+		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
+		set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
+		break;
+	case SPITZ_HP_OFF:
+
+		/* jack removed, everything off */
+		snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
+		snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
+		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
+		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
+		break;
+	}
+	snd_soc_dapm_sync_endpoints(codec);
+}
+
+static int spitz_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->socdev->codec;
+
+	/* check the jack status at stream startup */
+	spitz_ext_control(codec);
+	return 0;
+}
+
+static int spitz_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	unsigned int clk = 0;
+	int ret = 0;
+
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 48000:
+	case 96000:
+		clk = 12288000;
+		break;
+	case 11025:
+	case 22050:
+	case 44100:
+		clk = 11289600;
+		break;
+	}
+
+	/* set codec DAI configuration */
+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* set cpu DAI configuration */
+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* set the codec system clock for DAC and ADC */
+	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8750_SYSCLK, clk,
+		SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	/* set the I2S system clock as input (unused) */
+	ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
+		SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct snd_soc_ops spitz_ops = {
+	.startup = spitz_startup,
+	.hw_params = spitz_hw_params,
+};
+
+static int spitz_get_jack(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = spitz_jack_func;
+	return 0;
+}
+
+static int spitz_set_jack(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	if (spitz_jack_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	spitz_jack_func = ucontrol->value.integer.value[0];
+	spitz_ext_control(codec);
+	return 1;
+}
+
+static int spitz_get_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = spitz_spk_func;
+	return 0;
+}
+
+static int spitz_set_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+	if (spitz_spk_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	spitz_spk_func = ucontrol->value.integer.value[0];
+	spitz_ext_control(codec);
+	return 1;
+}
+
+static int spitz_mic_bias(struct snd_soc_dapm_widget *w, int event)
+{
+	if (machine_is_borzoi() || machine_is_spitz()) {
+		if (SND_SOC_DAPM_EVENT_ON(event))
+			set_scoop_gpio(&spitzscoop2_device.dev,
+				SPITZ_SCP2_MIC_BIAS);
+		else
+			reset_scoop_gpio(&spitzscoop2_device.dev,
+				SPITZ_SCP2_MIC_BIAS);
+	}
+
+	if (machine_is_akita()) {
+		if (SND_SOC_DAPM_EVENT_ON(event))
+			akita_set_ioexp(&akitaioexp_device.dev,
+				AKITA_IOEXP_MIC_BIAS);
+		else
+			akita_reset_ioexp(&akitaioexp_device.dev,
+				AKITA_IOEXP_MIC_BIAS);
+	}
+	return 0;
+}
+
+/* spitz machine dapm widgets */
+static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+	SND_SOC_DAPM_LINE("Line Jack", NULL),
+
+	/* headset is a mic and mono headphone */
+	SND_SOC_DAPM_HP("Headset Jack", NULL),
+};
+
+/* Spitz machine audio_map */
+static const char *audio_map[][3] = {
+
+	/* headphone connected to LOUT1, ROUT1 */
+	{"Headphone Jack", NULL, "LOUT1"},
+	{"Headphone Jack", NULL, "ROUT1"},
+
+	/* headset connected to ROUT1 and LINPUT1 with bias (def below) */
+	{"Headset Jack", NULL, "ROUT1"},
+
+	/* ext speaker connected to LOUT2, ROUT2  */
+	{"Ext Spk", NULL , "ROUT2"},
+	{"Ext Spk", NULL , "LOUT2"},
+
+	/* mic is connected to input 1 - with bias */
+	{"LINPUT1", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Mic Jack"},
+
+	/* line is connected to input 1 - no bias */
+	{"LINPUT1", NULL, "Line Jack"},
+
+	{NULL, NULL, NULL},
+};
+
+static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
+	"Off"};
+static const char *spk_function[] = {"On", "Off"};
+static const struct soc_enum spitz_enum[] = {
+	SOC_ENUM_SINGLE_EXT(5, jack_function),
+	SOC_ENUM_SINGLE_EXT(2, spk_function),
+};
+
+static const struct snd_kcontrol_new wm8750_spitz_controls[] = {
+	SOC_ENUM_EXT("Jack Function", spitz_enum[0], spitz_get_jack,
+		spitz_set_jack),
+	SOC_ENUM_EXT("Speaker Function", spitz_enum[1], spitz_get_spk,
+		spitz_set_spk),
+};
+
+/*
+ * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device
+ */
+static int spitz_wm8750_init(struct snd_soc_codec *codec)
+{
+	int i, err;
+
+	/* NC codec pins */
+	snd_soc_dapm_set_endpoint(codec, "RINPUT1", 0);
+	snd_soc_dapm_set_endpoint(codec, "LINPUT2", 0);
+	snd_soc_dapm_set_endpoint(codec, "RINPUT2", 0);
+	snd_soc_dapm_set_endpoint(codec, "LINPUT3", 0);
+	snd_soc_dapm_set_endpoint(codec, "RINPUT3", 0);
+	snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
+	snd_soc_dapm_set_endpoint(codec, "MONO", 0);
+
+	/* Add spitz specific controls */
+	for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
+		err = snd_ctl_add(codec->card,
+			snd_soc_cnew(&wm8750_spitz_controls[i], codec, NULL));
+		if (err < 0)
+			return err;
+	}
+
+	/* Add spitz specific widgets */
+	for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
+		snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
+	}
+
+	/* Set up spitz specific audio path audio_map */
+	for (i = 0; audio_map[i][0] != NULL; i++) {
+		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+			audio_map[i][1], audio_map[i][2]);
+	}
+
+	snd_soc_dapm_sync_endpoints(codec);
+	return 0;
+}
+
+/* spitz digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link spitz_dai = {
+	.name = "wm8750",
+	.stream_name = "WM8750",
+	.cpu_dai = &pxa_i2s_dai,
+	.codec_dai = &wm8750_dai,
+	.init = spitz_wm8750_init,
+	.ops = &spitz_ops,
+};
+
+/* spitz audio machine driver */
+static struct snd_soc_machine snd_soc_machine_spitz = {
+	.name = "Spitz",
+	.dai_link = &spitz_dai,
+	.num_links = 1,
+};
+
+/* spitz audio private data */
+static struct wm8750_setup_data spitz_wm8750_setup = {
+	.i2c_address = 0x1b,
+};
+
+/* spitz audio subsystem */
+static struct snd_soc_device spitz_snd_devdata = {
+	.machine = &snd_soc_machine_spitz,
+	.platform = &pxa2xx_soc_platform,
+	.codec_dev = &soc_codec_dev_wm8750,
+	.codec_data = &spitz_wm8750_setup,
+};
+
+static struct platform_device *spitz_snd_device;
+
+static int __init spitz_init(void)
+{
+	int ret;
+
+	if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita()))
+		return -ENODEV;
+
+	spitz_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!spitz_snd_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(spitz_snd_device, &spitz_snd_devdata);
+	spitz_snd_devdata.dev = &spitz_snd_device->dev;
+	ret = platform_device_add(spitz_snd_device);
+
+	if (ret)
+		platform_device_put(spitz_snd_device);
+
+	return ret;
+}
+
+static void __exit spitz_exit(void)
+{
+	platform_device_unregister(spitz_snd_device);
+}
+
+module_init(spitz_init);
+module_exit(spitz_exit);
+
+MODULE_AUTHOR("Richard Purdie");
+MODULE_DESCRIPTION("ALSA SoC Spitz");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
new file mode 100644
index 0000000..5504e30
--- /dev/null
+++ b/sound/soc/pxa/tosa.c
@@ -0,0 +1,289 @@
+/*
+ * tosa.c  --  SoC audio for Tosa
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *          Richard Purdie <richard@openedhand.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.
+ *
+ *  Revision history
+ *    30th Nov 2005   Initial version.
+ *
+ * GPIO's
+ *  1 - Jack Insertion
+ *  5 - Hookswitch (headset answer/hang up switch)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware/tmio.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/audio.h>
+#include <asm/arch/tosa.h>
+
+#include "../codecs/wm9712.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+
+static struct snd_soc_machine tosa;
+
+#define TOSA_HP        0
+#define TOSA_MIC_INT   1
+#define TOSA_HEADSET   2
+#define TOSA_HP_OFF    3
+#define TOSA_SPK_ON    0
+#define TOSA_SPK_OFF   1
+
+static int tosa_jack_func;
+static int tosa_spk_func;
+
+static void tosa_ext_control(struct snd_soc_codec *codec)
+{
+	int spk = 0, mic_int = 0, hp = 0, hs = 0;
+
+	/* set up jack connection */
+	switch (tosa_jack_func) {
+	case TOSA_HP:
+		hp = 1;
+		break;
+	case TOSA_MIC_INT:
+		mic_int = 1;
+		break;
+	case TOSA_HEADSET:
+		hs = 1;
+		break;
+	}
+
+	if (tosa_spk_func == TOSA_SPK_ON)
+		spk = 1;
+
+	snd_soc_dapm_set_endpoint(codec, "Speaker", spk);
+	snd_soc_dapm_set_endpoint(codec, "Mic (Internal)", mic_int);
+	snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
+	snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
+	snd_soc_dapm_sync_endpoints(codec);
+}
+
+static int tosa_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->socdev->codec;
+
+	/* check the jack status at stream startup */
+	tosa_ext_control(codec);
+	return 0;
+}
+
+static struct snd_soc_ops tosa_ops = {
+	.startup = tosa_startup,
+};
+
+static int tosa_get_jack(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = tosa_jack_func;
+	return 0;
+}
+
+static int tosa_set_jack(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+	if (tosa_jack_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	tosa_jack_func = ucontrol->value.integer.value[0];
+	tosa_ext_control(codec);
+	return 1;
+}
+
+static int tosa_get_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = tosa_spk_func;
+	return 0;
+}
+
+static int tosa_set_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+	if (tosa_spk_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	tosa_spk_func = ucontrol->value.integer.value[0];
+	tosa_ext_control(codec);
+	return 1;
+}
+
+/* tosa dapm event handlers */
+static int tosa_hp_event(struct snd_soc_dapm_widget *w, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
+	else
+		reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
+	return 0;
+}
+
+/* tosa machine dapm widgets */
+static const struct snd_soc_dapm_widget tosa_dapm_widgets[] = {
+SND_SOC_DAPM_HP("Headphone Jack", tosa_hp_event),
+SND_SOC_DAPM_HP("Headset Jack", NULL),
+SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
+SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+/* tosa audio map */
+static const char *audio_map[][3] = {
+
+	/* headphone connected to HPOUTL, HPOUTR */
+	{"Headphone Jack", NULL, "HPOUTL"},
+	{"Headphone Jack", NULL, "HPOUTR"},
+
+	/* ext speaker connected to LOUT2, ROUT2 */
+	{"Speaker", NULL, "LOUT2"},
+	{"Speaker", NULL, "ROUT2"},
+
+	/* internal mic is connected to mic1, mic2 differential - with bias */
+	{"MIC1", NULL, "Mic Bias"},
+	{"MIC2", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Mic (Internal)"},
+
+	/* headset is connected to HPOUTR, and LINEINR with bias */
+	{"Headset Jack", NULL, "HPOUTR"},
+	{"LINEINR", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Headset Jack"},
+
+	{NULL, NULL, NULL},
+};
+
+static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
+	"Off"};
+static const char *spk_function[] = {"On", "Off"};
+static const struct soc_enum tosa_enum[] = {
+	SOC_ENUM_SINGLE_EXT(5, jack_function),
+	SOC_ENUM_SINGLE_EXT(2, spk_function),
+};
+
+static const struct snd_kcontrol_new tosa_controls[] = {
+	SOC_ENUM_EXT("Jack Function", tosa_enum[0], tosa_get_jack,
+		tosa_set_jack),
+	SOC_ENUM_EXT("Speaker Function", tosa_enum[1], tosa_get_spk,
+		tosa_set_spk),
+};
+
+static int tosa_ac97_init(struct snd_soc_codec *codec)
+{
+	int i, err;
+
+	snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
+	snd_soc_dapm_set_endpoint(codec, "MONOOUT", 0);
+
+	/* add tosa specific controls */
+	for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
+		err = snd_ctl_add(codec->card,
+				snd_soc_cnew(&tosa_controls[i],codec, NULL));
+		if (err < 0)
+			return err;
+	}
+
+	/* add tosa specific widgets */
+	for (i = 0; i < ARRAY_SIZE(tosa_dapm_widgets); i++) {
+		snd_soc_dapm_new_control(codec, &tosa_dapm_widgets[i]);
+	}
+
+	/* set up tosa specific audio path audio_map */
+	for (i = 0; audio_map[i][0] != NULL; i++) {
+		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+			audio_map[i][1], audio_map[i][2]);
+	}
+
+	snd_soc_dapm_sync_endpoints(codec);
+	return 0;
+}
+
+static struct snd_soc_dai_link tosa_dai[] = {
+{
+	.name = "AC97",
+	.stream_name = "AC97 HiFi",
+	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+	.init = tosa_ac97_init,
+	.ops = &tosa_ops,
+},
+{
+	.name = "AC97 Aux",
+	.stream_name = "AC97 Aux",
+	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
+	.ops = &tosa_ops,
+},
+};
+
+static struct snd_soc_machine tosa = {
+	.name = "Tosa",
+	.dai_link = tosa_dai,
+	.num_links = ARRAY_SIZE(tosa_dai),
+};
+
+static struct snd_soc_device tosa_snd_devdata = {
+	.machine = &tosa,
+	.platform = &pxa2xx_soc_platform,
+	.codec_dev = &soc_codec_dev_wm9712,
+};
+
+static struct platform_device *tosa_snd_device;
+
+static int __init tosa_init(void)
+{
+	int ret;
+
+	if (!machine_is_tosa())
+		return -ENODEV;
+
+	tosa_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!tosa_snd_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata);
+	tosa_snd_devdata.dev = &tosa_snd_device->dev;
+	ret = platform_device_add(tosa_snd_device);
+
+	if (ret)
+		platform_device_put(tosa_snd_device);
+
+	return ret;
+}
+
+static void __exit tosa_exit(void)
+{
+	platform_device_unregister(tosa_snd_device);
+}
+
+module_init(tosa_init);
+module_exit(tosa_exit);
+
+/* Module information */
+MODULE_AUTHOR("Richard Purdie");
+MODULE_DESCRIPTION("ALSA SoC Tosa");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
new file mode 100644
index 0000000..36519ae
--- /dev/null
+++ b/sound/soc/soc-core.c
@@ -0,0 +1,1587 @@
+/*
+ * soc-core.c  --  ALSA SoC Audio Layer
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *         with code, comments and ideas from :-
+ *         Richard Purdie <richard@openedhand.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.
+ *
+ *  Revision history
+ *    12th Aug 2005   Initial version.
+ *    25th Oct 2005   Working Codec, Interface and Platform registration.
+ *
+ *  TODO:
+ *   o Add hw rules to enforce rates, etc.
+ *   o More testing with other codecs/machines.
+ *   o Add more codecs and platforms to ensure good API coverage.
+ *   o Support TDM on PCM and I2S
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+/* debug */
+#define SOC_DEBUG 0
+#if SOC_DEBUG
+#define dbg(format, arg...) printk(format, ## arg)
+#else
+#define dbg(format, arg...)
+#endif
+
+static DEFINE_MUTEX(pcm_mutex);
+static DEFINE_MUTEX(io_mutex);
+static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
+
+/*
+ * This is a timeout to do a DAPM powerdown after a stream is closed().
+ * It can be used to eliminate pops between different playback streams, e.g.
+ * between two audio tracks.
+ */
+static int pmdown_time = 5000;
+module_param(pmdown_time, int, 0);
+MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
+
+/*
+ * This function forces any delayed work to be queued and run.
+ */
+static int run_delayed_work(struct delayed_work *dwork)
+{
+	int ret;
+
+	/* cancel any work waiting to be queued. */
+	ret = cancel_delayed_work(dwork);
+
+	/* if there was any work waiting then we run it now and
+	 * wait for it's completion */
+	if (ret) {
+		schedule_delayed_work(dwork, 0);
+		flush_scheduled_work();
+	}
+	return ret;
+}
+
+#ifdef CONFIG_SND_SOC_AC97_BUS
+/* unregister ac97 codec */
+static int soc_ac97_dev_unregister(struct snd_soc_codec *codec)
+{
+	if (codec->ac97->dev.bus)
+		device_unregister(&codec->ac97->dev);
+	return 0;
+}
+
+/* stop no dev release warning */
+static void soc_ac97_device_release(struct device *dev){}
+
+/* register ac97 codec to bus */
+static int soc_ac97_dev_register(struct snd_soc_codec *codec)
+{
+	int err;
+
+	codec->ac97->dev.bus = &ac97_bus_type;
+	codec->ac97->dev.parent = NULL;
+	codec->ac97->dev.release = soc_ac97_device_release;
+
+	snprintf(codec->ac97->dev.bus_id, BUS_ID_SIZE, "%d-%d:%s",
+		 codec->card->number, 0, codec->name);
+	err = device_register(&codec->ac97->dev);
+	if (err < 0) {
+		snd_printk(KERN_ERR "Can't register ac97 bus\n");
+		codec->ac97->dev.bus = NULL;
+		return err;
+	}
+	return 0;
+}
+#endif
+
+static inline const char* get_dai_name(int type)
+{
+	switch(type) {
+	case SND_SOC_DAI_AC97:
+		return "AC97";
+	case SND_SOC_DAI_I2S:
+		return "I2S";
+	case SND_SOC_DAI_PCM:
+		return "PCM";
+	}
+	return NULL;
+}
+
+/*
+ * Called by ALSA when a PCM substream is opened, the runtime->hw record is
+ * then initialized and any private data can be allocated. This also calls
+ * startup for the cpu DAI, platform, machine and codec DAI.
+ */
+static int soc_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_dai_link *machine = rtd->dai;
+	struct snd_soc_platform *platform = socdev->platform;
+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+	int ret = 0;
+
+	mutex_lock(&pcm_mutex);
+
+	/* startup the audio subsystem */
+	if (cpu_dai->ops.startup) {
+		ret = cpu_dai->ops.startup(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't open interface %s\n",
+				cpu_dai->name);
+			goto out;
+		}
+	}
+
+	if (platform->pcm_ops->open) {
+		ret = platform->pcm_ops->open(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
+			goto platform_err;
+		}
+	}
+
+	if (codec_dai->ops.startup) {
+		ret = codec_dai->ops.startup(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't open codec %s\n",
+				codec_dai->name);
+			goto codec_dai_err;
+		}
+	}
+
+	if (machine->ops && machine->ops->startup) {
+		ret = machine->ops->startup(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: %s startup failed\n", machine->name);
+			goto machine_err;
+		}
+	}
+
+	/* Check that the codec and cpu DAI's are compatible */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		runtime->hw.rate_min =
+			max(codec_dai->playback.rate_min, cpu_dai->playback.rate_min);
+		runtime->hw.rate_max =
+			min(codec_dai->playback.rate_max, cpu_dai->playback.rate_max);
+		runtime->hw.channels_min =
+			max(codec_dai->playback.channels_min,
+				cpu_dai->playback.channels_min);
+		runtime->hw.channels_max =
+			min(codec_dai->playback.channels_max,
+				cpu_dai->playback.channels_max);
+		runtime->hw.formats =
+			codec_dai->playback.formats & cpu_dai->playback.formats;
+		runtime->hw.rates =
+			codec_dai->playback.rates & cpu_dai->playback.rates;
+	} else {
+		runtime->hw.rate_min =
+			max(codec_dai->capture.rate_min, cpu_dai->capture.rate_min);
+		runtime->hw.rate_max =
+			min(codec_dai->capture.rate_max, cpu_dai->capture.rate_max);
+		runtime->hw.channels_min =
+			max(codec_dai->capture.channels_min,
+				cpu_dai->capture.channels_min);
+		runtime->hw.channels_max =
+			min(codec_dai->capture.channels_max,
+				cpu_dai->capture.channels_max);
+		runtime->hw.formats =
+			codec_dai->capture.formats & cpu_dai->capture.formats;
+		runtime->hw.rates =
+			codec_dai->capture.rates & cpu_dai->capture.rates;
+	}
+
+	snd_pcm_limit_hw_rates(runtime);
+	if (!runtime->hw.rates) {
+		printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
+			codec_dai->name, cpu_dai->name);
+		goto machine_err;
+	}
+	if (!runtime->hw.formats) {
+		printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
+			codec_dai->name, cpu_dai->name);
+		goto machine_err;
+	}
+	if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
+		printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
+			codec_dai->name, cpu_dai->name);
+		goto machine_err;
+	}
+
+	dbg("asoc: %s <-> %s info:\n",codec_dai->name, cpu_dai->name);
+	dbg("asoc: rate mask 0x%x\n", runtime->hw.rates);
+	dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
+		runtime->hw.channels_max);
+	dbg("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
+		runtime->hw.rate_max);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		cpu_dai->playback.active = codec_dai->playback.active = 1;
+	else
+		cpu_dai->capture.active = codec_dai->capture.active = 1;
+	cpu_dai->active = codec_dai->active = 1;
+	cpu_dai->runtime = runtime;
+	socdev->codec->active++;
+	mutex_unlock(&pcm_mutex);
+	return 0;
+
+machine_err:
+	if (machine->ops && machine->ops->shutdown)
+		machine->ops->shutdown(substream);
+
+codec_dai_err:
+	if (platform->pcm_ops->close)
+		platform->pcm_ops->close(substream);
+
+platform_err:
+	if (cpu_dai->ops.shutdown)
+		cpu_dai->ops.shutdown(substream);
+out:
+	mutex_unlock(&pcm_mutex);
+	return ret;
+}
+
+/*
+ * Power down the audio subsytem pmdown_time msecs after close is called.
+ * This is to ensure there are no pops or clicks in between any music tracks
+ * due to DAPM power cycling.
+ */
+static void close_delayed_work(struct work_struct *work)
+{
+	struct snd_soc_device *socdev =
+		container_of(work, struct snd_soc_device, delayed_work.work);
+	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec_dai *codec_dai;
+	int i;
+
+	mutex_lock(&pcm_mutex);
+	for(i = 0; i < codec->num_dai; i++) {
+		codec_dai = &codec->dai[i];
+
+		dbg("pop wq checking: %s status: %s waiting: %s\n",
+			codec_dai->playback.stream_name,
+			codec_dai->playback.active ? "active" : "inactive",
+			codec_dai->pop_wait ? "yes" : "no");
+
+		/* are we waiting on this codec DAI stream */
+		if (codec_dai->pop_wait == 1) {
+
+			codec_dai->pop_wait = 0;
+			snd_soc_dapm_stream_event(codec, codec_dai->playback.stream_name,
+				SND_SOC_DAPM_STREAM_STOP);
+
+			/* power down the codec power domain if no longer active */
+			if (codec->active == 0) {
+				dbg("pop wq D3 %s %s\n", codec->name,
+					codec_dai->playback.stream_name);
+		 		if (codec->dapm_event)
+					codec->dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+			}
+		}
+	}
+	mutex_unlock(&pcm_mutex);
+}
+
+/*
+ * Called by ALSA when a PCM substream is closed. Private data can be
+ * freed here. The cpu DAI, codec DAI, machine and platform are also
+ * shutdown.
+ */
+static int soc_codec_close(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_dai_link *machine = rtd->dai;
+	struct snd_soc_platform *platform = socdev->platform;
+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+	struct snd_soc_codec *codec = socdev->codec;
+
+	mutex_lock(&pcm_mutex);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		cpu_dai->playback.active = codec_dai->playback.active = 0;
+	else
+		cpu_dai->capture.active = codec_dai->capture.active = 0;
+
+	if (codec_dai->playback.active == 0 &&
+		codec_dai->capture.active == 0) {
+		cpu_dai->active = codec_dai->active = 0;
+	}
+	codec->active--;
+
+	if (cpu_dai->ops.shutdown)
+		cpu_dai->ops.shutdown(substream);
+
+	if (codec_dai->ops.shutdown)
+		codec_dai->ops.shutdown(substream);
+
+	if (machine->ops && machine->ops->shutdown)
+		machine->ops->shutdown(substream);
+
+	if (platform->pcm_ops->close)
+		platform->pcm_ops->close(substream);
+	cpu_dai->runtime = NULL;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* start delayed pop wq here for playback streams */
+		codec_dai->pop_wait = 1;
+		schedule_delayed_work(&socdev->delayed_work,
+			msecs_to_jiffies(pmdown_time));
+	} else {
+		/* capture streams can be powered down now */
+		snd_soc_dapm_stream_event(codec,
+			codec_dai->capture.stream_name, SND_SOC_DAPM_STREAM_STOP);
+
+		if (codec->active == 0 && codec_dai->pop_wait == 0){
+			if (codec->dapm_event)
+				codec->dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+		}
+	}
+
+	mutex_unlock(&pcm_mutex);
+	return 0;
+}
+
+/*
+ * Called by ALSA when the PCM substream is prepared, can set format, sample
+ * rate, etc.  This function is non atomic and can be called multiple times,
+ * it can refer to the runtime info.
+ */
+static int soc_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_dai_link *machine = rtd->dai;
+	struct snd_soc_platform *platform = socdev->platform;
+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+	struct snd_soc_codec *codec = socdev->codec;
+	int ret = 0;
+
+	mutex_lock(&pcm_mutex);
+
+	if (machine->ops && machine->ops->prepare) {
+		ret = machine->ops->prepare(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: machine prepare error\n");
+			goto out;
+		}
+	}
+
+	if (platform->pcm_ops->prepare) {
+		ret = platform->pcm_ops->prepare(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: platform prepare error\n");
+			goto out;
+		}
+	}
+
+	if (codec_dai->ops.prepare) {
+		ret = codec_dai->ops.prepare(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: codec DAI prepare error\n");
+			goto out;
+		}
+	}
+
+	if (cpu_dai->ops.prepare) {
+		ret = cpu_dai->ops.prepare(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: cpu DAI prepare error\n");
+			goto out;
+		}
+	}
+
+	/* we only want to start a DAPM playback stream if we are not waiting
+	 * on an existing one stopping */
+	if (codec_dai->pop_wait) {
+		/* we are waiting for the delayed work to start */
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+				snd_soc_dapm_stream_event(socdev->codec,
+					codec_dai->capture.stream_name,
+					SND_SOC_DAPM_STREAM_START);
+		else {
+			codec_dai->pop_wait = 0;
+			cancel_delayed_work(&socdev->delayed_work);
+			if (codec_dai->dai_ops.digital_mute)
+				codec_dai->dai_ops.digital_mute(codec_dai, 0);
+		}
+	} else {
+		/* no delayed work - do we need to power up codec */
+		if (codec->dapm_state != SNDRV_CTL_POWER_D0) {
+
+			if (codec->dapm_event)
+				codec->dapm_event(codec, SNDRV_CTL_POWER_D1);
+
+			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+				snd_soc_dapm_stream_event(codec,
+					codec_dai->playback.stream_name,
+					SND_SOC_DAPM_STREAM_START);
+			else
+				snd_soc_dapm_stream_event(codec,
+					codec_dai->capture.stream_name,
+					SND_SOC_DAPM_STREAM_START);
+
+			if (codec->dapm_event)
+				codec->dapm_event(codec, SNDRV_CTL_POWER_D0);
+			if (codec_dai->dai_ops.digital_mute)
+				codec_dai->dai_ops.digital_mute(codec_dai, 0);
+
+		} else {
+			/* codec already powered - power on widgets */
+			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+				snd_soc_dapm_stream_event(codec,
+					codec_dai->playback.stream_name,
+					SND_SOC_DAPM_STREAM_START);
+			else
+				snd_soc_dapm_stream_event(codec,
+					codec_dai->capture.stream_name,
+					SND_SOC_DAPM_STREAM_START);
+			if (codec_dai->dai_ops.digital_mute)
+				codec_dai->dai_ops.digital_mute(codec_dai, 0);
+		}
+	}
+
+out:
+	mutex_unlock(&pcm_mutex);
+	return ret;
+}
+
+/*
+ * Called by ALSA when the hardware params are set by application. This
+ * function can also be called multiple times and can allocate buffers
+ * (using snd_pcm_lib_* ). It's non-atomic.
+ */
+static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_dai_link *machine = rtd->dai;
+	struct snd_soc_platform *platform = socdev->platform;
+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+	int ret = 0;
+
+	mutex_lock(&pcm_mutex);
+
+	if (machine->ops && machine->ops->hw_params) {
+		ret = machine->ops->hw_params(substream, params);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: machine hw_params failed\n");
+			goto out;
+		}
+	}
+
+	if (codec_dai->ops.hw_params) {
+		ret = codec_dai->ops.hw_params(substream, params);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't set codec %s hw params\n",
+				codec_dai->name);
+			goto codec_err;
+		}
+	}
+
+	if (cpu_dai->ops.hw_params) {
+		ret = cpu_dai->ops.hw_params(substream, params);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't set interface %s hw params\n",
+				cpu_dai->name);
+			goto interface_err;
+		}
+	}
+
+	if (platform->pcm_ops->hw_params) {
+		ret = platform->pcm_ops->hw_params(substream, params);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't set platform %s hw params\n",
+				platform->name);
+			goto platform_err;
+		}
+	}
+
+out:
+	mutex_unlock(&pcm_mutex);
+	return ret;
+
+platform_err:
+	if (cpu_dai->ops.hw_free)
+		cpu_dai->ops.hw_free(substream);
+
+interface_err:
+	if (codec_dai->ops.hw_free)
+		codec_dai->ops.hw_free(substream);
+
+codec_err:
+	if(machine->ops && machine->ops->hw_free)
+		machine->ops->hw_free(substream);
+
+	mutex_unlock(&pcm_mutex);
+	return ret;
+}
+
+/*
+ * Free's resources allocated by hw_params, can be called multiple times
+ */
+static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_dai_link *machine = rtd->dai;
+	struct snd_soc_platform *platform = socdev->platform;
+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+	struct snd_soc_codec *codec = socdev->codec;
+
+	mutex_lock(&pcm_mutex);
+
+	/* apply codec digital mute */
+	if (!codec->active && codec_dai->dai_ops.digital_mute)
+		codec_dai->dai_ops.digital_mute(codec_dai, 1);
+
+	/* free any machine hw params */
+	if (machine->ops && machine->ops->hw_free)
+		machine->ops->hw_free(substream);
+
+	/* free any DMA resources */
+	if (platform->pcm_ops->hw_free)
+		platform->pcm_ops->hw_free(substream);
+
+	/* now free hw params for the DAI's  */
+	if (codec_dai->ops.hw_free)
+		codec_dai->ops.hw_free(substream);
+
+	if (cpu_dai->ops.hw_free)
+		cpu_dai->ops.hw_free(substream);
+
+	mutex_unlock(&pcm_mutex);
+	return 0;
+}
+
+static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_dai_link *machine = rtd->dai;
+	struct snd_soc_platform *platform = socdev->platform;
+	struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
+	struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+	int ret;
+
+	if (codec_dai->ops.trigger) {
+		ret = codec_dai->ops.trigger(substream, cmd);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (platform->pcm_ops->trigger) {
+		ret = platform->pcm_ops->trigger(substream, cmd);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (cpu_dai->ops.trigger) {
+		ret = cpu_dai->ops.trigger(substream, cmd);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+/* ASoC PCM operations */
+static struct snd_pcm_ops soc_pcm_ops = {
+	.open		= soc_pcm_open,
+	.close		= soc_codec_close,
+	.hw_params	= soc_pcm_hw_params,
+	.hw_free	= soc_pcm_hw_free,
+	.prepare	= soc_pcm_prepare,
+	.trigger	= soc_pcm_trigger,
+};
+
+#ifdef CONFIG_PM
+/* powers down audio subsystem for suspend */
+static int soc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ 	struct snd_soc_machine *machine = socdev->machine;
+ 	struct snd_soc_platform *platform = socdev->platform;
+ 	struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
+	struct snd_soc_codec *codec = socdev->codec;
+	int i;
+
+	/* mute any active DAC's */
+	for(i = 0; i < machine->num_links; i++) {
+		struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
+		if (dai->dai_ops.digital_mute && dai->playback.active)
+			dai->dai_ops.digital_mute(dai, 1);
+	}
+
+	if (machine->suspend_pre)
+		machine->suspend_pre(pdev, state);
+
+	for(i = 0; i < machine->num_links; i++) {
+		struct snd_soc_cpu_dai  *cpu_dai = machine->dai_link[i].cpu_dai;
+		if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97)
+			cpu_dai->suspend(pdev, cpu_dai);
+		if (platform->suspend)
+			platform->suspend(pdev, cpu_dai);
+	}
+
+	/* close any waiting streams and save state */
+	run_delayed_work(&socdev->delayed_work);
+	codec->suspend_dapm_state = codec->dapm_state;
+
+	for(i = 0; i < codec->num_dai; i++) {
+		char *stream = codec->dai[i].playback.stream_name;
+		if (stream != NULL)
+			snd_soc_dapm_stream_event(codec, stream,
+				SND_SOC_DAPM_STREAM_SUSPEND);
+		stream = codec->dai[i].capture.stream_name;
+		if (stream != NULL)
+			snd_soc_dapm_stream_event(codec, stream,
+				SND_SOC_DAPM_STREAM_SUSPEND);
+	}
+
+	if (codec_dev->suspend)
+		codec_dev->suspend(pdev, state);
+
+	for(i = 0; i < machine->num_links; i++) {
+		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+		if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97)
+			cpu_dai->suspend(pdev, cpu_dai);
+	}
+
+	if (machine->suspend_post)
+		machine->suspend_post(pdev, state);
+
+	return 0;
+}
+
+/* powers up audio subsystem after a suspend */
+static int soc_resume(struct platform_device *pdev)
+{
+ 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ 	struct snd_soc_machine *machine = socdev->machine;
+ 	struct snd_soc_platform *platform = socdev->platform;
+ 	struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
+	struct snd_soc_codec *codec = socdev->codec;
+	int i;
+
+	if (machine->resume_pre)
+		machine->resume_pre(pdev);
+
+	for(i = 0; i < machine->num_links; i++) {
+		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+		if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97)
+			cpu_dai->resume(pdev, cpu_dai);
+	}
+
+	if (codec_dev->resume)
+		codec_dev->resume(pdev);
+
+	for(i = 0; i < codec->num_dai; i++) {
+		char* stream = codec->dai[i].playback.stream_name;
+		if (stream != NULL)
+			snd_soc_dapm_stream_event(codec, stream,
+				SND_SOC_DAPM_STREAM_RESUME);
+		stream = codec->dai[i].capture.stream_name;
+		if (stream != NULL)
+			snd_soc_dapm_stream_event(codec, stream,
+				SND_SOC_DAPM_STREAM_RESUME);
+	}
+
+	/* unmute any active DAC's */
+	for(i = 0; i < machine->num_links; i++) {
+		struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
+		if (dai->dai_ops.digital_mute && dai->playback.active)
+			dai->dai_ops.digital_mute(dai, 0);
+	}
+
+	for(i = 0; i < machine->num_links; i++) {
+		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+		if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97)
+			cpu_dai->resume(pdev, cpu_dai);
+		if (platform->resume)
+			platform->resume(pdev, cpu_dai);
+	}
+
+	if (machine->resume_post)
+		machine->resume_post(pdev);
+
+	return 0;
+}
+
+#else
+#define soc_suspend	NULL
+#define soc_resume	NULL
+#endif
+
+/* probes a new socdev */
+static int soc_probe(struct platform_device *pdev)
+{
+	int ret = 0, i;
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_machine *machine = socdev->machine;
+	struct snd_soc_platform *platform = socdev->platform;
+	struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
+
+	if (machine->probe) {
+		ret = machine->probe(pdev);
+		if(ret < 0)
+			return ret;
+	}
+
+	for (i = 0; i < machine->num_links; i++) {
+		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+		if (cpu_dai->probe) {
+			ret = cpu_dai->probe(pdev);
+			if(ret < 0)
+				goto cpu_dai_err;
+		}
+	}
+
+	if (codec_dev->probe) {
+		ret = codec_dev->probe(pdev);
+		if(ret < 0)
+			goto cpu_dai_err;
+	}
+
+	if (platform->probe) {
+		ret = platform->probe(pdev);
+		if(ret < 0)
+			goto platform_err;
+	}
+
+	/* DAPM stream work */
+	INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work);
+	return 0;
+
+platform_err:
+	if (codec_dev->remove)
+		codec_dev->remove(pdev);
+
+cpu_dai_err:
+	for (i--; i >= 0; i--) {
+		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+		if (cpu_dai->remove)
+			cpu_dai->remove(pdev);
+	}
+
+	if (machine->remove)
+		machine->remove(pdev);
+
+	return ret;
+}
+
+/* removes a socdev */
+static int soc_remove(struct platform_device *pdev)
+{
+	int i;
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_machine *machine = socdev->machine;
+	struct snd_soc_platform *platform = socdev->platform;
+	struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
+
+	run_delayed_work(&socdev->delayed_work);
+
+	if (platform->remove)
+		platform->remove(pdev);
+
+	if (codec_dev->remove)
+		codec_dev->remove(pdev);
+
+	for (i = 0; i < machine->num_links; i++) {
+		struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+		if (cpu_dai->remove)
+			cpu_dai->remove(pdev);
+	}
+
+	if (machine->remove)
+		machine->remove(pdev);
+
+	return 0;
+}
+
+/* ASoC platform driver */
+static struct platform_driver soc_driver = {
+	.driver		= {
+		.name		= "soc-audio",
+	},
+	.probe		= soc_probe,
+	.remove		= soc_remove,
+	.suspend	= soc_suspend,
+	.resume		= soc_resume,
+};
+
+/* create a new pcm */
+static int soc_new_pcm(struct snd_soc_device *socdev,
+	struct snd_soc_dai_link *dai_link, int num)
+{
+	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_codec_dai *codec_dai = dai_link->codec_dai;
+	struct snd_soc_cpu_dai *cpu_dai = dai_link->cpu_dai;
+	struct snd_soc_pcm_runtime *rtd;
+	struct snd_pcm *pcm;
+	char new_name[64];
+	int ret = 0, playback = 0, capture = 0;
+
+	rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL);
+	if (rtd == NULL)
+		return -ENOMEM;
+
+	rtd->dai = dai_link;
+	rtd->socdev = socdev;
+	codec_dai->codec = socdev->codec;
+
+	/* check client and interface hw capabilities */
+	sprintf(new_name, "%s %s-%s-%d",dai_link->stream_name, codec_dai->name,
+		get_dai_name(cpu_dai->type), num);
+
+	if (codec_dai->playback.channels_min)
+		playback = 1;
+	if (codec_dai->capture.channels_min)
+		capture = 1;
+
+	ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback,
+		capture, &pcm);
+	if (ret < 0) {
+		printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
+		kfree(rtd);
+		return ret;
+	}
+
+	pcm->private_data = rtd;
+	soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap;
+	soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer;
+	soc_pcm_ops.ioctl = socdev->platform->pcm_ops->ioctl;
+	soc_pcm_ops.copy = socdev->platform->pcm_ops->copy;
+	soc_pcm_ops.silence = socdev->platform->pcm_ops->silence;
+	soc_pcm_ops.ack = socdev->platform->pcm_ops->ack;
+	soc_pcm_ops.page = socdev->platform->pcm_ops->page;
+
+	if (playback)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
+
+	if (capture)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
+
+	ret = socdev->platform->pcm_new(codec->card, codec_dai, pcm);
+	if (ret < 0) {
+		printk(KERN_ERR "asoc: platform pcm constructor failed\n");
+		kfree(rtd);
+		return ret;
+	}
+
+	pcm->private_free = socdev->platform->pcm_free;
+	printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
+		cpu_dai->name);
+	return ret;
+}
+
+/* codec register dump */
+static ssize_t codec_reg_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct snd_soc_device *devdata = dev_get_drvdata(dev);
+	struct snd_soc_codec *codec = devdata->codec;
+	int i, step = 1, count = 0;
+
+	if (!codec->reg_cache_size)
+		return 0;
+
+	if (codec->reg_cache_step)
+		step = codec->reg_cache_step;
+
+	count += sprintf(buf, "%s registers\n", codec->name);
+	for(i = 0; i < codec->reg_cache_size; i += step)
+		count += sprintf(buf + count, "%2x: %4x\n", i, codec->read(codec, i));
+
+	return count;
+}
+static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
+
+/**
+ * snd_soc_new_ac97_codec - initailise AC97 device
+ * @codec: audio codec
+ * @ops: AC97 bus operations
+ * @num: AC97 codec number
+ *
+ * Initialises AC97 codec resources for use by ad-hoc devices only.
+ */
+int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
+	struct snd_ac97_bus_ops *ops, int num)
+{
+	mutex_lock(&codec->mutex);
+
+	codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
+	if (codec->ac97 == NULL) {
+		mutex_unlock(&codec->mutex);
+		return -ENOMEM;
+	}
+
+	codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL);
+	if (codec->ac97->bus == NULL) {
+		kfree(codec->ac97);
+		codec->ac97 = NULL;
+		mutex_unlock(&codec->mutex);
+		return -ENOMEM;
+	}
+
+	codec->ac97->bus->ops = ops;
+	codec->ac97->num = num;
+	mutex_unlock(&codec->mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
+
+/**
+ * snd_soc_free_ac97_codec - free AC97 codec device
+ * @codec: audio codec
+ *
+ * Frees AC97 codec device resources.
+ */
+void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)
+{
+	mutex_lock(&codec->mutex);
+	kfree(codec->ac97->bus);
+	kfree(codec->ac97);
+	codec->ac97 = NULL;
+	mutex_unlock(&codec->mutex);
+}
+EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
+
+/**
+ * snd_soc_update_bits - update codec register bits
+ * @codec: audio codec
+ * @reg: codec register
+ * @mask: register mask
+ * @value: new value
+ *
+ * Writes new register value.
+ *
+ * Returns 1 for change else 0.
+ */
+int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
+				unsigned short mask, unsigned short value)
+{
+	int change;
+	unsigned short old, new;
+
+	mutex_lock(&io_mutex);
+	old = snd_soc_read(codec, reg);
+	new = (old & ~mask) | value;
+	change = old != new;
+	if (change)
+		snd_soc_write(codec, reg, new);
+
+	mutex_unlock(&io_mutex);
+	return change;
+}
+EXPORT_SYMBOL_GPL(snd_soc_update_bits);
+
+/**
+ * snd_soc_test_bits - test register for change
+ * @codec: audio codec
+ * @reg: codec register
+ * @mask: register mask
+ * @value: new value
+ *
+ * Tests a register with a new value and checks if the new value is
+ * different from the old value.
+ *
+ * Returns 1 for change else 0.
+ */
+int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
+				unsigned short mask, unsigned short value)
+{
+	int change;
+	unsigned short old, new;
+
+	mutex_lock(&io_mutex);
+	old = snd_soc_read(codec, reg);
+	new = (old & ~mask) | value;
+	change = old != new;
+	mutex_unlock(&io_mutex);
+
+	return change;
+}
+EXPORT_SYMBOL_GPL(snd_soc_test_bits);
+
+/**
+ * snd_soc_new_pcms - create new sound card and pcms
+ * @socdev: the SoC audio device
+ *
+ * Create a new sound card based upon the codec and interface pcms.
+ *
+ * Returns 0 for success, else error.
+ */
+int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
+{
+	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_machine *machine = socdev->machine;
+	int ret = 0, i;
+
+	mutex_lock(&codec->mutex);
+
+	/* register a sound card */
+	codec->card = snd_card_new(idx, xid, codec->owner, 0);
+	if (!codec->card) {
+		printk(KERN_ERR "asoc: can't create sound card for codec %s\n",
+			codec->name);
+		mutex_unlock(&codec->mutex);
+		return -ENODEV;
+	}
+
+	codec->card->dev = socdev->dev;
+	codec->card->private_data = codec;
+	strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
+
+	/* create the pcms */
+	for(i = 0; i < machine->num_links; i++) {
+		ret = soc_new_pcm(socdev, &machine->dai_link[i], i);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't create pcm %s\n",
+				machine->dai_link[i].stream_name);
+			mutex_unlock(&codec->mutex);
+			return ret;
+		}
+	}
+
+	mutex_unlock(&codec->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
+
+/**
+ * snd_soc_register_card - register sound card
+ * @socdev: the SoC audio device
+ *
+ * Register a SoC sound card. Also registers an AC97 device if the
+ * codec is AC97 for ad hoc devices.
+ *
+ * Returns 0 for success, else error.
+ */
+int snd_soc_register_card(struct snd_soc_device *socdev)
+{
+	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_machine *machine = socdev->machine;
+	int ret = 0, i, ac97 = 0, err = 0;
+
+	mutex_lock(&codec->mutex);
+	for(i = 0; i < machine->num_links; i++) {
+		if (socdev->machine->dai_link[i].init) {
+			err = socdev->machine->dai_link[i].init(codec);
+			if (err < 0) {
+				printk(KERN_ERR "asoc: failed to init %s\n",
+					socdev->machine->dai_link[i].stream_name);
+				continue;
+			}
+		}
+		if (socdev->machine->dai_link[i].cpu_dai->type == SND_SOC_DAI_AC97)
+			ac97 = 1;
+	}
+	snprintf(codec->card->shortname, sizeof(codec->card->shortname),
+		 "%s", machine->name);
+	snprintf(codec->card->longname, sizeof(codec->card->longname),
+		 "%s (%s)", machine->name, codec->name);
+
+	ret = snd_card_register(codec->card);
+	if (ret < 0) {
+		printk(KERN_ERR "asoc: failed to register soundcard for codec %s\n",
+				codec->name);
+		goto out;
+	}
+
+#ifdef CONFIG_SND_SOC_AC97_BUS
+	if (ac97) {
+		ret = soc_ac97_dev_register(codec);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: AC97 device register failed\n");
+			snd_card_free(codec->card);
+			goto out;
+		}
+	}
+#endif
+
+	err = snd_soc_dapm_sys_add(socdev->dev);
+	if (err < 0)
+		printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
+
+	err = device_create_file(socdev->dev, &dev_attr_codec_reg);
+	if (err < 0)
+		printk(KERN_WARNING "asoc: failed to add codec sysfs entries\n");
+out:
+	mutex_unlock(&codec->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_card);
+
+/**
+ * snd_soc_free_pcms - free sound card and pcms
+ * @socdev: the SoC audio device
+ *
+ * Frees sound card and pcms associated with the socdev.
+ * Also unregister the codec if it is an AC97 device.
+ */
+void snd_soc_free_pcms(struct snd_soc_device *socdev)
+{
+	struct snd_soc_codec *codec = socdev->codec;
+
+	mutex_lock(&codec->mutex);
+#ifdef CONFIG_SND_SOC_AC97_BUS
+	if (codec->ac97)
+		soc_ac97_dev_unregister(codec);
+#endif
+
+	if (codec->card)
+		snd_card_free(codec->card);
+	device_remove_file(socdev->dev, &dev_attr_codec_reg);
+	mutex_unlock(&codec->mutex);
+}
+EXPORT_SYMBOL_GPL(snd_soc_free_pcms);
+
+/**
+ * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
+ * @substream: the pcm substream
+ * @hw: the hardware parameters
+ *
+ * Sets the substream runtime hardware parameters.
+ */
+int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
+	const struct snd_pcm_hardware *hw)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	runtime->hw.info = hw->info;
+	runtime->hw.formats = hw->formats;
+	runtime->hw.period_bytes_min = hw->period_bytes_min;
+	runtime->hw.period_bytes_max = hw->period_bytes_max;
+	runtime->hw.periods_min = hw->periods_min;
+	runtime->hw.periods_max = hw->periods_max;
+	runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
+	runtime->hw.fifo_size = hw->fifo_size;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
+
+/**
+ * snd_soc_cnew - create new control
+ * @_template: control template
+ * @data: control private data
+ * @lnng_name: control long name
+ *
+ * Create a new mixer control from a template control.
+ *
+ * Returns 0 for success, else error.
+ */
+struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
+	void *data, char *long_name)
+{
+	struct snd_kcontrol_new template;
+
+	memcpy(&template, _template, sizeof(template));
+	if (long_name)
+		template.name = long_name;
+	template.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+	template.index = 0;
+
+	return snd_ctl_new1(&template, data);
+}
+EXPORT_SYMBOL_GPL(snd_soc_cnew);
+
+/**
+ * snd_soc_info_enum_double - enumerated double mixer info callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a double enumerated
+ * mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
+	uinfo->value.enumerated.items = e->mask;
+
+	if (uinfo->value.enumerated.item > e->mask - 1)
+		uinfo->value.enumerated.item = e->mask - 1;
+	strcpy(uinfo->value.enumerated.name,
+		e->texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
+
+/**
+ * snd_soc_get_enum_double - enumerated double mixer get callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to get the value of a double enumerated mixer.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned short val, bitmask;
+
+	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+		;
+	val = snd_soc_read(codec, e->reg);
+	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
+	if (e->shift_l != e->shift_r)
+		ucontrol->value.enumerated.item[1] =
+			(val >> e->shift_r) & (bitmask - 1);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
+
+/**
+ * snd_soc_put_enum_double - enumerated double mixer put callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to set the value of a double enumerated mixer.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned short val;
+	unsigned short mask, bitmask;
+
+	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+		;
+	if (ucontrol->value.enumerated.item[0] > e->mask - 1)
+		return -EINVAL;
+	val = ucontrol->value.enumerated.item[0] << e->shift_l;
+	mask = (bitmask - 1) << e->shift_l;
+	if (e->shift_l != e->shift_r) {
+		if (ucontrol->value.enumerated.item[1] > e->mask - 1)
+			return -EINVAL;
+		val |= ucontrol->value.enumerated.item[1] << e->shift_r;
+		mask |= (bitmask - 1) << e->shift_r;
+	}
+
+	return snd_soc_update_bits(codec, e->reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
+
+/**
+ * snd_soc_info_enum_ext - external enumerated single mixer info callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about an external enumerated
+ * single mixer.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = e->mask;
+
+	if (uinfo->value.enumerated.item > e->mask - 1)
+		uinfo->value.enumerated.item = e->mask - 1;
+	strcpy(uinfo->value.enumerated.name,
+		e->texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext);
+
+/**
+ * snd_soc_info_volsw_ext - external single mixer info callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a single external mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	int mask = kcontrol->private_value;
+
+	uinfo->type =
+		mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = mask;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
+
+/**
+ * snd_soc_info_bool_ext - external single boolean mixer info callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a single boolean external mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_bool_ext(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_bool_ext);
+
+/**
+ * snd_soc_info_volsw - single mixer info callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a single mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	int mask = (kcontrol->private_value >> 16) & 0xff;
+	int shift = (kcontrol->private_value >> 8) & 0x0f;
+	int rshift = (kcontrol->private_value >> 12) & 0x0f;
+
+	uinfo->type =
+		mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = shift == rshift ? 1 : 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = mask;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
+
+/**
+ * snd_soc_get_volsw - single mixer get callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to get the value of a single mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int reg = kcontrol->private_value & 0xff;
+	int shift = (kcontrol->private_value >> 8) & 0x0f;
+	int rshift = (kcontrol->private_value >> 12) & 0x0f;
+	int mask = (kcontrol->private_value >> 16) & 0xff;
+	int invert = (kcontrol->private_value >> 24) & 0x01;
+
+	ucontrol->value.integer.value[0] =
+		(snd_soc_read(codec, reg) >> shift) & mask;
+	if (shift != rshift)
+		ucontrol->value.integer.value[1] =
+			(snd_soc_read(codec, reg) >> rshift) & mask;
+	if (invert) {
+		ucontrol->value.integer.value[0] =
+			mask - ucontrol->value.integer.value[0];
+		if (shift != rshift)
+			ucontrol->value.integer.value[1] =
+				mask - ucontrol->value.integer.value[1];
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
+
+/**
+ * snd_soc_put_volsw - single mixer put callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to set the value of a single mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int reg = kcontrol->private_value & 0xff;
+	int shift = (kcontrol->private_value >> 8) & 0x0f;
+	int rshift = (kcontrol->private_value >> 12) & 0x0f;
+	int mask = (kcontrol->private_value >> 16) & 0xff;
+	int invert = (kcontrol->private_value >> 24) & 0x01;
+	int err;
+	unsigned short val, val2, val_mask;
+
+	val = (ucontrol->value.integer.value[0] & mask);
+	if (invert)
+		val = mask - val;
+	val_mask = mask << shift;
+	val = val << shift;
+	if (shift != rshift) {
+		val2 = (ucontrol->value.integer.value[1] & mask);
+		if (invert)
+			val2 = mask - val2;
+		val_mask |= mask << rshift;
+		val |= val2 << rshift;
+	}
+	err = snd_soc_update_bits(codec, reg, val_mask, val);
+	return err;
+}
+EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
+
+/**
+ * snd_soc_info_volsw_2r - double mixer info callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a double mixer control that
+ * spans 2 codec registers.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	int mask = (kcontrol->private_value >> 12) & 0xff;
+
+	uinfo->type =
+		mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = mask;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
+
+/**
+ * snd_soc_get_volsw_2r - double mixer get callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to get the value of a double mixer control that spans 2 registers.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int reg = kcontrol->private_value & 0xff;
+	int reg2 = (kcontrol->private_value >> 24) & 0xff;
+	int shift = (kcontrol->private_value >> 8) & 0x0f;
+	int mask = (kcontrol->private_value >> 12) & 0xff;
+	int invert = (kcontrol->private_value >> 20) & 0x01;
+
+	ucontrol->value.integer.value[0] =
+		(snd_soc_read(codec, reg) >> shift) & mask;
+	ucontrol->value.integer.value[1] =
+		(snd_soc_read(codec, reg2) >> shift) & mask;
+	if (invert) {
+		ucontrol->value.integer.value[0] =
+			mask - ucontrol->value.integer.value[0];
+		ucontrol->value.integer.value[1] =
+			mask - ucontrol->value.integer.value[1];
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);
+
+/**
+ * snd_soc_put_volsw_2r - double mixer set callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to set the value of a double mixer control that spans 2 registers.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int reg = kcontrol->private_value & 0xff;
+	int reg2 = (kcontrol->private_value >> 24) & 0xff;
+	int shift = (kcontrol->private_value >> 8) & 0x0f;
+	int mask = (kcontrol->private_value >> 12) & 0xff;
+	int invert = (kcontrol->private_value >> 20) & 0x01;
+	int err;
+	unsigned short val, val2, val_mask;
+
+	val_mask = mask << shift;
+	val = (ucontrol->value.integer.value[0] & mask);
+	val2 = (ucontrol->value.integer.value[1] & mask);
+
+	if (invert) {
+		val = mask - val;
+		val2 = mask - val2;
+	}
+
+	val = val << shift;
+	val2 = val2 << shift;
+
+	if ((err = snd_soc_update_bits(codec, reg, val_mask, val)) < 0)
+		return err;
+
+	err = snd_soc_update_bits(codec, reg2, val_mask, val2);
+	return err;
+}
+EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
+
+static int __devinit snd_soc_init(void)
+{
+	printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);
+	return platform_driver_register(&soc_driver);
+}
+
+static void snd_soc_exit(void)
+{
+ 	platform_driver_unregister(&soc_driver);
+}
+
+module_init(snd_soc_init);
+module_exit(snd_soc_exit);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_DESCRIPTION("ALSA SoC Core");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
new file mode 100644
index 0000000..7caf8c7
--- /dev/null
+++ b/sound/soc/soc-dapm.c
@@ -0,0 +1,1323 @@
+/*
+ * soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.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.
+ *
+ *  Revision history
+ *    12th Aug 2005   Initial version.
+ *    25th Oct 2005   Implemented path power domain.
+ *    18th Dec 2005   Implemented machine and stream level power domain.
+ *
+ *  Features:
+ *    o Changes power status of internal codec blocks depending on the
+ *      dynamic configuration of codec internal audio paths and active
+ *      DAC's/ADC's.
+ *    o Platform power domain - can support external components i.e. amps and
+ *      mic/meadphone insertion events.
+ *    o Automatic Mic Bias support
+ *    o Jack insertion power event initiation - e.g. hp insertion will enable
+ *      sinks, dacs, etc
+ *    o Delayed powerdown of audio susbsytem to reduce pops between a quick
+ *      device reopen.
+ *
+ *  Todo:
+ *    o DAPM power change sequencing - allow for configurable per
+ *      codec sequences.
+ *    o Support for analogue bias optimisation.
+ *    o Support for reduced codec oversampling rates.
+ *    o Support for reduced codec bias currents.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+/* debug */
+#define DAPM_DEBUG 0
+#if DAPM_DEBUG
+#define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
+#define dbg(format, arg...) printk(format, ## arg)
+#else
+#define dump_dapm(codec, action)
+#define dbg(format, arg...)
+#endif
+
+#define POP_DEBUG 0
+#if POP_DEBUG
+#define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */
+#define pop_wait(time) schedule_timeout_interruptible(msecs_to_jiffies(time))
+#define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME)
+#else
+#define pop_dbg(format, arg...)
+#define pop_wait(time)
+#endif
+
+/* dapm power sequences - make this per codec in the future */
+static int dapm_up_seq[] = {
+	snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
+	snd_soc_dapm_mux, snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_pga,
+	snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
+};
+static int dapm_down_seq[] = {
+	snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
+	snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic,
+	snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_post
+};
+
+static int dapm_status = 1;
+module_param(dapm_status, int, 0);
+MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
+
+/* create a new dapm widget */
+static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
+	const struct snd_soc_dapm_widget *_widget)
+{
+	return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
+}
+
+/* set up initial codec paths */
+static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
+	struct snd_soc_dapm_path *p, int i)
+{
+	switch (w->id) {
+	case snd_soc_dapm_switch:
+	case snd_soc_dapm_mixer: {
+		int val;
+		int reg = w->kcontrols[i].private_value & 0xff;
+		int shift = (w->kcontrols[i].private_value >> 8) & 0x0f;
+		int mask = (w->kcontrols[i].private_value >> 16) & 0xff;
+		int invert = (w->kcontrols[i].private_value >> 24) & 0x01;
+
+		val = snd_soc_read(w->codec, reg);
+		val = (val >> shift) & mask;
+
+		if ((invert && !val) || (!invert && val))
+			p->connect = 1;
+		else
+			p->connect = 0;
+	}
+	break;
+	case snd_soc_dapm_mux: {
+		struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value;
+		int val, item, bitmask;
+
+		for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+		;
+		val = snd_soc_read(w->codec, e->reg);
+		item = (val >> e->shift_l) & (bitmask - 1);
+
+		p->connect = 0;
+		for (i = 0; i < e->mask; i++) {
+			if (!(strcmp(p->name, e->texts[i])) && item == i)
+				p->connect = 1;
+		}
+	}
+	break;
+	/* does not effect routing - always connected */
+	case snd_soc_dapm_pga:
+	case snd_soc_dapm_output:
+	case snd_soc_dapm_adc:
+	case snd_soc_dapm_input:
+	case snd_soc_dapm_dac:
+	case snd_soc_dapm_micbias:
+	case snd_soc_dapm_vmid:
+		p->connect = 1;
+	break;
+	/* does effect routing - dynamically connected */
+	case snd_soc_dapm_hp:
+	case snd_soc_dapm_mic:
+	case snd_soc_dapm_spk:
+	case snd_soc_dapm_line:
+	case snd_soc_dapm_pre:
+	case snd_soc_dapm_post:
+		p->connect = 0;
+	break;
+	}
+}
+
+/* connect mux widget to it's interconnecting audio paths */
+static int dapm_connect_mux(struct snd_soc_codec *codec,
+	struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
+	struct snd_soc_dapm_path *path, const char *control_name,
+	const struct snd_kcontrol_new *kcontrol)
+{
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int i;
+
+	for (i = 0; i < e->mask; i++) {
+		if (!(strcmp(control_name, e->texts[i]))) {
+			list_add(&path->list, &codec->dapm_paths);
+			list_add(&path->list_sink, &dest->sources);
+			list_add(&path->list_source, &src->sinks);
+			path->name = (char*)e->texts[i];
+			dapm_set_path_status(dest, path, 0);
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
+/* connect mixer widget to it's interconnecting audio paths */
+static int dapm_connect_mixer(struct snd_soc_codec *codec,
+	struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
+	struct snd_soc_dapm_path *path, const char *control_name)
+{
+	int i;
+
+	/* search for mixer kcontrol */
+	for (i = 0; i < dest->num_kcontrols; i++) {
+		if (!strcmp(control_name, dest->kcontrols[i].name)) {
+			list_add(&path->list, &codec->dapm_paths);
+			list_add(&path->list_sink, &dest->sources);
+			list_add(&path->list_source, &src->sinks);
+			path->name = dest->kcontrols[i].name;
+			dapm_set_path_status(dest, path, i);
+			return 0;
+		}
+	}
+	return -ENODEV;
+}
+
+/* update dapm codec register bits */
+static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
+{
+	int change, power;
+	unsigned short old, new;
+	struct snd_soc_codec *codec = widget->codec;
+
+	/* check for valid widgets */
+	if (widget->reg < 0 || widget->id == snd_soc_dapm_input ||
+		widget->id == snd_soc_dapm_output ||
+		widget->id == snd_soc_dapm_hp ||
+		widget->id == snd_soc_dapm_mic ||
+		widget->id == snd_soc_dapm_line ||
+		widget->id == snd_soc_dapm_spk)
+		return 0;
+
+	power = widget->power;
+	if (widget->invert)
+		power = (power ? 0:1);
+
+	old = snd_soc_read(codec, widget->reg);
+	new = (old & ~(0x1 << widget->shift)) | (power << widget->shift);
+
+	change = old != new;
+	if (change) {
+		pop_dbg("pop test %s : %s in %d ms\n", widget->name,
+			widget->power ? "on" : "off", POP_TIME);
+		snd_soc_write(codec, widget->reg, new);
+		pop_wait(POP_TIME);
+	}
+	dbg("reg old %x new %x change %d\n", old, new, change);
+	return change;
+}
+
+/* ramps the volume up or down to minimise pops before or after a
+ * DAPM power event */
+static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
+{
+	const struct snd_kcontrol_new *k = widget->kcontrols;
+
+	if (widget->muted && !power)
+		return 0;
+	if (!widget->muted && power)
+		return 0;
+
+	if (widget->num_kcontrols && k) {
+		int reg = k->private_value & 0xff;
+		int shift = (k->private_value >> 8) & 0x0f;
+		int mask = (k->private_value >> 16) & 0xff;
+		int invert = (k->private_value >> 24) & 0x01;
+
+		if (power) {
+			int i;
+			/* power up has happended, increase volume to last level */
+			if (invert) {
+				for (i = mask; i > widget->saved_value; i--)
+					snd_soc_update_bits(widget->codec, reg, mask, i);
+			} else {
+				for (i = 0; i < widget->saved_value; i++)
+					snd_soc_update_bits(widget->codec, reg, mask, i);
+			}
+			widget->muted = 0;
+		} else {
+			/* power down is about to occur, decrease volume to mute */
+			int val = snd_soc_read(widget->codec, reg);
+			int i = widget->saved_value = (val >> shift) & mask;
+			if (invert) {
+				for (; i < mask; i++)
+					snd_soc_update_bits(widget->codec, reg, mask, i);
+			} else {
+				for (; i > 0; i--)
+					snd_soc_update_bits(widget->codec, reg, mask, i);
+			}
+			widget->muted = 1;
+		}
+	}
+	return 0;
+}
+
+/* create new dapm mixer control */
+static int dapm_new_mixer(struct snd_soc_codec *codec,
+	struct snd_soc_dapm_widget *w)
+{
+	int i, ret = 0;
+	char name[32];
+	struct snd_soc_dapm_path *path;
+
+	/* add kcontrol */
+	for (i = 0; i < w->num_kcontrols; i++) {
+
+		/* match name */
+		list_for_each_entry(path, &w->sources, list_sink) {
+
+			/* mixer/mux paths name must match control name */
+			if (path->name != (char*)w->kcontrols[i].name)
+				continue;
+
+			/* add dapm control with long name */
+			snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
+			path->long_name = kstrdup (name, GFP_KERNEL);
+			if (path->long_name == NULL)
+				return -ENOMEM;
+
+			path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
+				path->long_name);
+			ret = snd_ctl_add(codec->card, path->kcontrol);
+			if (ret < 0) {
+				printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n",
+						path->long_name);
+				kfree(path->long_name);
+				path->long_name = NULL;
+				return ret;
+			}
+		}
+	}
+	return ret;
+}
+
+/* create new dapm mux control */
+static int dapm_new_mux(struct snd_soc_codec *codec,
+	struct snd_soc_dapm_widget *w)
+{
+	struct snd_soc_dapm_path *path = NULL;
+	struct snd_kcontrol *kcontrol;
+	int ret = 0;
+
+	if (!w->num_kcontrols) {
+		printk(KERN_ERR "asoc: mux %s has no controls\n", w->name);
+		return -EINVAL;
+	}
+
+	kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
+	ret = snd_ctl_add(codec->card, kcontrol);
+	if (ret < 0)
+		goto err;
+
+	list_for_each_entry(path, &w->sources, list_sink)
+		path->kcontrol = kcontrol;
+
+	return ret;
+
+err:
+	printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
+	return ret;
+}
+
+/* create new dapm volume control */
+static int dapm_new_pga(struct snd_soc_codec *codec,
+	struct snd_soc_dapm_widget *w)
+{
+	struct snd_kcontrol *kcontrol;
+	int ret = 0;
+
+	if (!w->num_kcontrols)
+		return -EINVAL;
+
+	kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
+	ret = snd_ctl_add(codec->card, kcontrol);
+	if (ret < 0) {
+		printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
+		return ret;
+	}
+
+	return ret;
+}
+
+/* reset 'walked' bit for each dapm path */
+static inline void dapm_clear_walk(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_path *p;
+
+	list_for_each_entry(p, &codec->dapm_paths, list)
+		p->walked = 0;
+}
+
+/*
+ * Recursively check for a completed path to an active or physically connected
+ * output widget. Returns number of complete paths.
+ */
+static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
+{
+	struct snd_soc_dapm_path *path;
+	int con = 0;
+
+	if (widget->id == snd_soc_dapm_adc && widget->active)
+		return 1;
+
+	if (widget->connected) {
+		/* connected pin ? */
+		if (widget->id == snd_soc_dapm_output && !widget->ext)
+			return 1;
+
+		/* connected jack or spk ? */
+		if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
+			widget->id == snd_soc_dapm_line)
+			return 1;
+	}
+
+	list_for_each_entry(path, &widget->sinks, list_source) {
+		if (path->walked)
+			continue;
+
+		if (path->sink && path->connect) {
+			path->walked = 1;
+			con += is_connected_output_ep(path->sink);
+		}
+	}
+
+	return con;
+}
+
+/*
+ * Recursively check for a completed path to an active or physically connected
+ * input widget. Returns number of complete paths.
+ */
+static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
+{
+	struct snd_soc_dapm_path *path;
+	int con = 0;
+
+	/* active stream ? */
+	if (widget->id == snd_soc_dapm_dac && widget->active)
+		return 1;
+
+	if (widget->connected) {
+		/* connected pin ? */
+		if (widget->id == snd_soc_dapm_input && !widget->ext)
+			return 1;
+
+		/* connected VMID/Bias for lower pops */
+		if (widget->id == snd_soc_dapm_vmid)
+			return 1;
+
+		/* connected jack ? */
+		if (widget->id == snd_soc_dapm_mic || widget->id == snd_soc_dapm_line)
+			return 1;
+	}
+
+	list_for_each_entry(path, &widget->sources, list_sink) {
+		if (path->walked)
+			continue;
+
+		if (path->source && path->connect) {
+			path->walked = 1;
+			con += is_connected_input_ep(path->source);
+		}
+	}
+
+	return con;
+}
+
+/*
+ * Scan each dapm widget for complete audio path.
+ * A complete path is a route that has valid endpoints i.e.:-
+ *
+ *  o DAC to output pin.
+ *  o Input Pin to ADC.
+ *  o Input pin to Output pin (bypass, sidetone)
+ *  o DAC to ADC (loopback).
+ */
+static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
+{
+	struct snd_soc_dapm_widget *w;
+	int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power;
+
+	/* do we have a sequenced stream event */
+	if (event == SND_SOC_DAPM_STREAM_START) {
+		c = ARRAY_SIZE(dapm_up_seq);
+		seq = dapm_up_seq;
+	} else if (event == SND_SOC_DAPM_STREAM_STOP) {
+		c = ARRAY_SIZE(dapm_down_seq);
+		seq = dapm_down_seq;
+	}
+
+	for(i = 0; i < c; i++) {
+		list_for_each_entry(w, &codec->dapm_widgets, list) {
+
+			/* is widget in stream order */
+			if (seq && seq[i] && w->id != seq[i])
+				continue;
+
+			/* vmid - no action */
+			if (w->id == snd_soc_dapm_vmid)
+				continue;
+
+			/* active ADC */
+			if (w->id == snd_soc_dapm_adc && w->active) {
+				in = is_connected_input_ep(w);
+				dapm_clear_walk(w->codec);
+				w->power = (in != 0) ? 1 : 0;
+				dapm_update_bits(w);
+				continue;
+			}
+
+			/* active DAC */
+			if (w->id == snd_soc_dapm_dac && w->active) {
+				out = is_connected_output_ep(w);
+				dapm_clear_walk(w->codec);
+				w->power = (out != 0) ? 1 : 0;
+				dapm_update_bits(w);
+				continue;
+			}
+
+			/* programmable gain/attenuation */
+			if (w->id == snd_soc_dapm_pga) {
+				int on;
+				in = is_connected_input_ep(w);
+				dapm_clear_walk(w->codec);
+				out = is_connected_output_ep(w);
+				dapm_clear_walk(w->codec);
+				w->power = on = (out != 0 && in != 0) ? 1 : 0;
+
+				if (!on)
+					dapm_set_pga(w, on); /* lower volume to reduce pops */
+				dapm_update_bits(w);
+				if (on)
+					dapm_set_pga(w, on); /* restore volume from zero */
+
+				continue;
+			}
+
+			/* pre and post event widgets */
+			if (w->id == snd_soc_dapm_pre) {
+				if (!w->event)
+					continue;
+
+				if (event == SND_SOC_DAPM_STREAM_START) {
+					ret = w->event(w, SND_SOC_DAPM_PRE_PMU);
+					if (ret < 0)
+						return ret;
+				} else if (event == SND_SOC_DAPM_STREAM_STOP) {
+					ret = w->event(w, SND_SOC_DAPM_PRE_PMD);
+					if (ret < 0)
+						return ret;
+				}
+				continue;
+			}
+			if (w->id == snd_soc_dapm_post) {
+				if (!w->event)
+					continue;
+
+				if (event == SND_SOC_DAPM_STREAM_START) {
+					ret = w->event(w, SND_SOC_DAPM_POST_PMU);
+					if (ret < 0)
+						return ret;
+				} else if (event == SND_SOC_DAPM_STREAM_STOP) {
+					ret = w->event(w, SND_SOC_DAPM_POST_PMD);
+					if (ret < 0)
+						return ret;
+				}
+				continue;
+			}
+
+			/* all other widgets */
+			in = is_connected_input_ep(w);
+			dapm_clear_walk(w->codec);
+			out = is_connected_output_ep(w);
+			dapm_clear_walk(w->codec);
+			power = (out != 0 && in != 0) ? 1 : 0;
+			power_change = (w->power == power) ? 0: 1;
+			w->power = power;
+
+			/* call any power change event handlers */
+			if (power_change) {
+				if (w->event) {
+					dbg("power %s event for %s flags %x\n",
+						w->power ? "on" : "off", w->name, w->event_flags);
+					if (power) {
+						/* power up event */
+						if (w->event_flags & SND_SOC_DAPM_PRE_PMU) {
+							ret = w->event(w, SND_SOC_DAPM_PRE_PMU);
+							if (ret < 0)
+								return ret;
+						}
+						dapm_update_bits(w);
+						if (w->event_flags & SND_SOC_DAPM_POST_PMU){
+							ret = w->event(w, SND_SOC_DAPM_POST_PMU);
+							if (ret < 0)
+								return ret;
+						}
+					} else {
+						/* power down event */
+						if (w->event_flags & SND_SOC_DAPM_PRE_PMD) {
+							ret = w->event(w, SND_SOC_DAPM_PRE_PMD);
+							if (ret < 0)
+								return ret;
+						}
+						dapm_update_bits(w);
+						if (w->event_flags & SND_SOC_DAPM_POST_PMD) {
+							ret = w->event(w, SND_SOC_DAPM_POST_PMD);
+							if (ret < 0)
+								return ret;
+						}
+					}
+				} else
+					/* no event handler */
+					dapm_update_bits(w);
+			}
+		}
+	}
+
+	return ret;
+}
+
+#if DAPM_DEBUG
+static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
+{
+	struct snd_soc_dapm_widget *w;
+	struct snd_soc_dapm_path *p = NULL;
+	int in, out;
+
+	printk("DAPM %s %s\n", codec->name, action);
+
+	list_for_each_entry(w, &codec->dapm_widgets, list) {
+
+		/* only display widgets that effect routing */
+		switch (w->id) {
+		case snd_soc_dapm_pre:
+		case snd_soc_dapm_post:
+		case snd_soc_dapm_vmid:
+			continue;
+		case snd_soc_dapm_mux:
+		case snd_soc_dapm_output:
+		case snd_soc_dapm_input:
+		case snd_soc_dapm_switch:
+		case snd_soc_dapm_hp:
+		case snd_soc_dapm_mic:
+		case snd_soc_dapm_spk:
+		case snd_soc_dapm_line:
+		case snd_soc_dapm_micbias:
+		case snd_soc_dapm_dac:
+		case snd_soc_dapm_adc:
+		case snd_soc_dapm_pga:
+		case snd_soc_dapm_mixer:
+			if (w->name) {
+				in = is_connected_input_ep(w);
+				dapm_clear_walk(w->codec);
+				out = is_connected_output_ep(w);
+				dapm_clear_walk(w->codec);
+				printk("%s: %s  in %d out %d\n", w->name,
+					w->power ? "On":"Off",in, out);
+
+				list_for_each_entry(p, &w->sources, list_sink) {
+					if (p->connect)
+						printk(" in  %s %s\n", p->name ? p->name : "static",
+							p->source->name);
+				}
+				list_for_each_entry(p, &w->sinks, list_source) {
+					if (p->connect)
+						printk(" out %s %s\n", p->name ? p->name : "static",
+							p->sink->name);
+				}
+			}
+		break;
+		}
+	}
+}
+#endif
+
+/* test and update the power status of a mux widget */
+static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+				 struct snd_kcontrol *kcontrol, int mask,
+				 int val, struct soc_enum* e)
+{
+	struct snd_soc_dapm_path *path;
+	int found = 0;
+
+	if (widget->id != snd_soc_dapm_mux)
+		return -ENODEV;
+
+	if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
+		return 0;
+
+	/* find dapm widget path assoc with kcontrol */
+	list_for_each_entry(path, &widget->codec->dapm_paths, list) {
+		if (path->kcontrol != kcontrol)
+			continue;
+
+		if (!path->name || ! e->texts[val])
+			continue;
+
+		found = 1;
+		/* we now need to match the string in the enum to the path */
+		if (!(strcmp(path->name, e->texts[val])))
+			path->connect = 1; /* new connection */
+		else
+			path->connect = 0; /* old connection must be powered down */
+	}
+
+	if (found)
+		dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
+
+	return 0;
+}
+
+/* test and update the power status of a mixer widget */
+static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+				   struct snd_kcontrol *kcontrol, int reg,
+				   int val_mask, int val, int invert)
+{
+	struct snd_soc_dapm_path *path;
+	int found = 0;
+
+	if (widget->id != snd_soc_dapm_mixer)
+		return -ENODEV;
+
+	if (!snd_soc_test_bits(widget->codec, reg, val_mask, val))
+		return 0;
+
+	/* find dapm widget path assoc with kcontrol */
+	list_for_each_entry(path, &widget->codec->dapm_paths, list) {
+		if (path->kcontrol != kcontrol)
+			continue;
+
+		/* found, now check type */
+		found = 1;
+		if (val)
+			/* new connection */
+			path->connect = invert ? 0:1;
+		else
+			/* old connection must be powered down */
+			path->connect = invert ? 1:0;
+		break;
+	}
+
+	if (found)
+		dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
+
+	return 0;
+}
+
+/* show dapm widget status in sys fs */
+static ssize_t dapm_widget_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct snd_soc_device *devdata = dev_get_drvdata(dev);
+	struct snd_soc_codec *codec = devdata->codec;
+	struct snd_soc_dapm_widget *w;
+	int count = 0;
+	char *state = "not set";
+
+	list_for_each_entry(w, &codec->dapm_widgets, list) {
+
+		/* only display widgets that burnm power */
+		switch (w->id) {
+		case snd_soc_dapm_hp:
+		case snd_soc_dapm_mic:
+		case snd_soc_dapm_spk:
+		case snd_soc_dapm_line:
+		case snd_soc_dapm_micbias:
+		case snd_soc_dapm_dac:
+		case snd_soc_dapm_adc:
+		case snd_soc_dapm_pga:
+		case snd_soc_dapm_mixer:
+			if (w->name)
+				count += sprintf(buf + count, "%s: %s\n",
+					w->name, w->power ? "On":"Off");
+		break;
+		default:
+		break;
+		}
+	}
+
+	switch(codec->dapm_state){
+	case SNDRV_CTL_POWER_D0:
+		state = "D0";
+		break;
+	case SNDRV_CTL_POWER_D1:
+		state = "D1";
+		break;
+	case SNDRV_CTL_POWER_D2:
+		state = "D2";
+		break;
+	case SNDRV_CTL_POWER_D3hot:
+		state = "D3hot";
+		break;
+	case SNDRV_CTL_POWER_D3cold:
+		state = "D3cold";
+		break;
+	}
+	count += sprintf(buf + count, "PM State: %s\n", state);
+
+	return count;
+}
+
+static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
+
+int snd_soc_dapm_sys_add(struct device *dev)
+{
+	int ret = 0;
+
+	if (dapm_status)
+		ret = device_create_file(dev, &dev_attr_dapm_widget);
+
+	return ret;
+}
+
+static void snd_soc_dapm_sys_remove(struct device *dev)
+{
+	if (dapm_status)
+		device_remove_file(dev, &dev_attr_dapm_widget);
+}
+
+/* free all dapm widgets and resources */
+static void dapm_free_widgets(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_widget *w, *next_w;
+	struct snd_soc_dapm_path *p, *next_p;
+
+	list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) {
+		list_del(&w->list);
+		kfree(w);
+	}
+
+	list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) {
+		list_del(&p->list);
+		kfree(p->long_name);
+		kfree(p);
+	}
+}
+
+/**
+ * snd_soc_dapm_sync_endpoints - scan and power dapm paths
+ * @codec: audio codec
+ *
+ * Walks all dapm audio paths and powers widgets according to their
+ * stream or path usage.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec)
+{
+	return dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_endpoints);
+
+/**
+ * snd_soc_dapm_connect_input - connect dapm widgets
+ * @codec: audio codec
+ * @sink: name of target widget
+ * @control: mixer control name
+ * @source: name of source name
+ *
+ * Connects 2 dapm widgets together via a named audio path. The sink is
+ * the widget receiving the audio signal, whilst the source is the sender
+ * of the audio signal.
+ *
+ * Returns 0 for success else error.
+ */
+int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
+	const char * control, const char *source)
+{
+	struct snd_soc_dapm_path *path;
+	struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
+	int ret = 0;
+
+	/* find src and dest widgets */
+	list_for_each_entry(w, &codec->dapm_widgets, list) {
+
+		if (!wsink && !(strcmp(w->name, sink))) {
+			wsink = w;
+			continue;
+		}
+		if (!wsource && !(strcmp(w->name, source))) {
+			wsource = w;
+		}
+	}
+
+	if (wsource == NULL || wsink == NULL)
+		return -ENODEV;
+
+	path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
+	if (!path)
+		return -ENOMEM;
+
+	path->source = wsource;
+	path->sink = wsink;
+	INIT_LIST_HEAD(&path->list);
+	INIT_LIST_HEAD(&path->list_source);
+	INIT_LIST_HEAD(&path->list_sink);
+
+	/* check for external widgets */
+	if (wsink->id == snd_soc_dapm_input) {
+		if (wsource->id == snd_soc_dapm_micbias ||
+			wsource->id == snd_soc_dapm_mic ||
+			wsink->id == snd_soc_dapm_line)
+			wsink->ext = 1;
+	}
+	if (wsource->id == snd_soc_dapm_output) {
+		if (wsink->id == snd_soc_dapm_spk ||
+			wsink->id == snd_soc_dapm_hp ||
+			wsink->id == snd_soc_dapm_line)
+			wsource->ext = 1;
+	}
+
+	/* connect static paths */
+	if (control == NULL) {
+		list_add(&path->list, &codec->dapm_paths);
+		list_add(&path->list_sink, &wsink->sources);
+		list_add(&path->list_source, &wsource->sinks);
+		path->connect = 1;
+		return 0;
+	}
+
+	/* connect dynamic paths */
+	switch(wsink->id) {
+	case snd_soc_dapm_adc:
+	case snd_soc_dapm_dac:
+	case snd_soc_dapm_pga:
+	case snd_soc_dapm_input:
+	case snd_soc_dapm_output:
+	case snd_soc_dapm_micbias:
+	case snd_soc_dapm_vmid:
+	case snd_soc_dapm_pre:
+	case snd_soc_dapm_post:
+		list_add(&path->list, &codec->dapm_paths);
+		list_add(&path->list_sink, &wsink->sources);
+		list_add(&path->list_source, &wsource->sinks);
+		path->connect = 1;
+		return 0;
+	case snd_soc_dapm_mux:
+		ret = dapm_connect_mux(codec, wsource, wsink, path, control,
+			&wsink->kcontrols[0]);
+		if (ret != 0)
+			goto err;
+		break;
+	case snd_soc_dapm_switch:
+	case snd_soc_dapm_mixer:
+		ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
+		if (ret != 0)
+			goto err;
+		break;
+	case snd_soc_dapm_hp:
+	case snd_soc_dapm_mic:
+	case snd_soc_dapm_line:
+	case snd_soc_dapm_spk:
+		list_add(&path->list, &codec->dapm_paths);
+		list_add(&path->list_sink, &wsink->sources);
+		list_add(&path->list_source, &wsource->sinks);
+		path->connect = 0;
+		return 0;
+	}
+	return 0;
+
+err:
+	printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source,
+		control, sink);
+	kfree(path);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
+
+/**
+ * snd_soc_dapm_new_widgets - add new dapm widgets
+ * @codec: audio codec
+ *
+ * Checks the codec for any new dapm widgets and creates them if found.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_widget *w;
+
+	mutex_lock(&codec->mutex);
+	list_for_each_entry(w, &codec->dapm_widgets, list)
+	{
+		if (w->new)
+			continue;
+
+		switch(w->id) {
+		case snd_soc_dapm_switch:
+		case snd_soc_dapm_mixer:
+			dapm_new_mixer(codec, w);
+			break;
+		case snd_soc_dapm_mux:
+			dapm_new_mux(codec, w);
+			break;
+		case snd_soc_dapm_adc:
+		case snd_soc_dapm_dac:
+		case snd_soc_dapm_pga:
+			dapm_new_pga(codec, w);
+			break;
+		case snd_soc_dapm_input:
+		case snd_soc_dapm_output:
+		case snd_soc_dapm_micbias:
+		case snd_soc_dapm_spk:
+		case snd_soc_dapm_hp:
+		case snd_soc_dapm_mic:
+		case snd_soc_dapm_line:
+		case snd_soc_dapm_vmid:
+		case snd_soc_dapm_pre:
+		case snd_soc_dapm_post:
+			break;
+		}
+		w->new = 1;
+	}
+
+	dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
+	mutex_unlock(&codec->mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
+
+/**
+ * snd_soc_dapm_get_volsw - dapm mixer get callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to get the value of a dapm mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
+	int reg = kcontrol->private_value & 0xff;
+	int shift = (kcontrol->private_value >> 8) & 0x0f;
+	int rshift = (kcontrol->private_value >> 12) & 0x0f;
+	int mask = (kcontrol->private_value >> 16) & 0xff;
+	int invert = (kcontrol->private_value >> 24) & 0x01;
+
+	/* return the saved value if we are powered down */
+	if (widget->id == snd_soc_dapm_pga && !widget->power) {
+		ucontrol->value.integer.value[0] = widget->saved_value;
+		return 0;
+	}
+
+	ucontrol->value.integer.value[0] =
+		(snd_soc_read(widget->codec, reg) >> shift) & mask;
+	if (shift != rshift)
+		ucontrol->value.integer.value[1] =
+			(snd_soc_read(widget->codec, reg) >> rshift) & mask;
+	if (invert) {
+		ucontrol->value.integer.value[0] =
+			mask - ucontrol->value.integer.value[0];
+		if (shift != rshift)
+			ucontrol->value.integer.value[1] =
+				mask - ucontrol->value.integer.value[1];
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
+
+/**
+ * snd_soc_dapm_put_volsw - dapm mixer set callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to set the value of a dapm mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
+	int reg = kcontrol->private_value & 0xff;
+	int shift = (kcontrol->private_value >> 8) & 0x0f;
+	int rshift = (kcontrol->private_value >> 12) & 0x0f;
+	int mask = (kcontrol->private_value >> 16) & 0xff;
+	int invert = (kcontrol->private_value >> 24) & 0x01;
+	unsigned short val, val2, val_mask;
+	int ret;
+
+	val = (ucontrol->value.integer.value[0] & mask);
+
+	if (invert)
+		val = mask - val;
+	val_mask = mask << shift;
+	val = val << shift;
+	if (shift != rshift) {
+		val2 = (ucontrol->value.integer.value[1] & mask);
+		if (invert)
+			val2 = mask - val2;
+		val_mask |= mask << rshift;
+		val |= val2 << rshift;
+	}
+
+	mutex_lock(&widget->codec->mutex);
+	widget->value = val;
+
+	/* save volume value if the widget is powered down */
+	if (widget->id == snd_soc_dapm_pga && !widget->power) {
+		widget->saved_value = val;
+		mutex_unlock(&widget->codec->mutex);
+		return 1;
+	}
+
+	dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert);
+	if (widget->event) {
+		if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
+			ret = widget->event(widget, SND_SOC_DAPM_PRE_REG);
+			if (ret < 0)
+				goto out;
+		}
+		ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
+		if (widget->event_flags & SND_SOC_DAPM_POST_REG)
+			ret = widget->event(widget, SND_SOC_DAPM_POST_REG);
+	} else
+		ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
+
+out:
+	mutex_unlock(&widget->codec->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
+
+/**
+ * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to get the value of a dapm enumerated double mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned short val, bitmask;
+
+	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+		;
+	val = snd_soc_read(widget->codec, e->reg);
+	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
+	if (e->shift_l != e->shift_r)
+		ucontrol->value.enumerated.item[1] =
+			(val >> e->shift_r) & (bitmask - 1);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
+
+/**
+ * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to set the value of a dapm enumerated double mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned short val, mux;
+	unsigned short mask, bitmask;
+	int ret = 0;
+
+	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+		;
+	if (ucontrol->value.enumerated.item[0] > e->mask - 1)
+		return -EINVAL;
+	mux = ucontrol->value.enumerated.item[0];
+	val = mux << e->shift_l;
+	mask = (bitmask - 1) << e->shift_l;
+	if (e->shift_l != e->shift_r) {
+		if (ucontrol->value.enumerated.item[1] > e->mask - 1)
+			return -EINVAL;
+		val |= ucontrol->value.enumerated.item[1] << e->shift_r;
+		mask |= (bitmask - 1) << e->shift_r;
+	}
+
+	mutex_lock(&widget->codec->mutex);
+	widget->value = val;
+	dapm_mux_update_power(widget, kcontrol, mask, mux, e);
+	if (widget->event) {
+		if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
+			ret = widget->event(widget, SND_SOC_DAPM_PRE_REG);
+			if (ret < 0)
+				goto out;
+		}
+		ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
+		if (widget->event_flags & SND_SOC_DAPM_POST_REG)
+			ret = widget->event(widget, SND_SOC_DAPM_POST_REG);
+	} else
+		ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
+
+out:
+	mutex_unlock(&widget->codec->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
+
+/**
+ * snd_soc_dapm_new_control - create new dapm control
+ * @codec: audio codec
+ * @widget: widget template
+ *
+ * Creates a new dapm control based upon the template.
+ *
+ * Returns 0 for success else error.
+ */
+int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
+	const struct snd_soc_dapm_widget *widget)
+{
+	struct snd_soc_dapm_widget *w;
+
+	if ((w = dapm_cnew_widget(widget)) == NULL)
+		return -ENOMEM;
+
+	w->codec = codec;
+	INIT_LIST_HEAD(&w->sources);
+	INIT_LIST_HEAD(&w->sinks);
+	INIT_LIST_HEAD(&w->list);
+	list_add(&w->list, &codec->dapm_widgets);
+
+	/* machine layer set ups unconnected pins and insertions */
+	w->connected = 1;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
+
+/**
+ * snd_soc_dapm_stream_event - send a stream event to the dapm core
+ * @codec: audio codec
+ * @stream: stream name
+ * @event: stream event
+ *
+ * Sends a stream event to the dapm core. The core then makes any
+ * necessary widget power changes.
+ *
+ * Returns 0 for success else error.
+ */
+int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
+	char *stream, int event)
+{
+	struct snd_soc_dapm_widget *w;
+
+	if (stream == NULL)
+		return 0;
+
+	mutex_lock(&codec->mutex);
+	list_for_each_entry(w, &codec->dapm_widgets, list)
+	{
+		if (!w->sname)
+			continue;
+		dbg("widget %s\n %s stream %s event %d\n", w->name, w->sname,
+			stream, event);
+		if (strstr(w->sname, stream)) {
+			switch(event) {
+			case SND_SOC_DAPM_STREAM_START:
+				w->active = 1;
+				break;
+			case SND_SOC_DAPM_STREAM_STOP:
+				w->active = 0;
+				break;
+			case SND_SOC_DAPM_STREAM_SUSPEND:
+				if (w->active)
+					w->suspend = 1;
+				w->active = 0;
+				break;
+			case SND_SOC_DAPM_STREAM_RESUME:
+				if (w->suspend) {
+					w->active = 1;
+					w->suspend = 0;
+				}
+				break;
+			case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
+				break;
+			case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
+				break;
+			}
+		}
+	}
+	mutex_unlock(&codec->mutex);
+
+	dapm_power_widgets(codec, event);
+	dump_dapm(codec, __FUNCTION__);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
+
+/**
+ * snd_soc_dapm_set_endpoint - set audio endpoint status
+ * @codec: audio codec
+ * @endpoint: audio signal endpoint (or start point)
+ * @status: point status
+ *
+ * Set audio endpoint status - connected or disconnected.
+ *
+ * Returns 0 for success else error.
+ */
+int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
+	char *endpoint, int status)
+{
+	struct snd_soc_dapm_widget *w;
+
+	list_for_each_entry(w, &codec->dapm_widgets, list) {
+		if (!strcmp(w->name, endpoint)) {
+			w->connected = status;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
+
+/**
+ * snd_soc_dapm_free - free dapm resources
+ * @socdev: SoC device
+ *
+ * Free all dapm widgets and resources.
+ */
+void snd_soc_dapm_free(struct snd_soc_device *socdev)
+{
+	struct snd_soc_codec *codec = socdev->codec;
+
+	snd_soc_dapm_sys_remove(socdev->dev);
+	dapm_free_widgets(codec);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
+MODULE_LICENSE("GPL");
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 8f1ced4..46daca1 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -436,7 +436,7 @@
 
 static int soundcore_open(struct inode *, struct file *);
 
-static struct file_operations soundcore_fops=
+static const struct file_operations soundcore_fops=
 {
 	/* We must have an owner or the module locking fails */
 	.owner	= THIS_MODULE,
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 4ceb09d..25a2a73 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -678,7 +678,7 @@
  * The JUMP cmd points to the new cmd string.
  * It also releases the cmdlock spinlock.
  *
- * Lock must not be held before calling this.
+ * Lock must be held before calling this.
  */
 static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len)
 {
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index 573e370..ebcac13 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -20,7 +20,6 @@
 
 #include <sound/driver.h>
 #include <linux/wait.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <sound/core.h>
diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c
index 59144ec..680f2b7 100644
--- a/sound/synth/emux/emux_proc.c
+++ b/sound/synth/emux/emux_proc.c
@@ -20,7 +20,6 @@
 
 #include <sound/driver.h>
 #include <linux/wait.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/emux_synth.h>
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 19bdcc7..b6d8863 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -186,6 +186,7 @@
 	u64 formats;			/* format bitmasks (all or'ed) */
 	unsigned int num_formats;		/* number of supported audio formats (list) */
 	struct list_head fmt_list;	/* format list */
+	struct snd_pcm_hw_constraint_list rate_list;	/* limited rates */
 	spinlock_t lock;
 
 	struct snd_urb_ops ops;		/* callbacks (must be filled at init) */
@@ -253,7 +254,7 @@
 				    struct urb *urb)
 {
 	unsigned char *cp = urb->transfer_buffer;
-	struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
+	struct snd_urb_ctx *ctx = urb->context;
 
 	urb->dev = ctx->subs->dev; /* we need to set this at each time */
 	urb->iso_frame_desc[0].length = 3;
@@ -275,7 +276,7 @@
 				       struct urb *urb)
 {
 	unsigned char *cp = urb->transfer_buffer;
-	struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
+	struct snd_urb_ctx *ctx = urb->context;
 
 	urb->dev = ctx->subs->dev; /* we need to set this at each time */
 	urb->iso_frame_desc[0].length = 4;
@@ -313,7 +314,7 @@
 			       struct urb *urb)
 {
 	int i, offs;
-	struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
+	struct snd_urb_ctx *ctx = urb->context;
 
 	offs = 0;
 	urb->dev = ctx->subs->dev; /* we need to set this at each time */
@@ -324,16 +325,6 @@
 	}
 	urb->transfer_buffer_length = offs;
 	urb->number_of_packets = ctx->packets;
-#if 0 // for check
-	if (! urb->bandwidth) {
-		int bustime;
-		bustime = usb_check_bandwidth(urb->dev, urb);
-		if (bustime < 0)
-			return bustime;
-		printk("urb %d: bandwidth = %d (packets = %d)\n", ctx->index, bustime, urb->number_of_packets);
-		usb_claim_bandwidth(urb->dev, urb, bustime, 1);
-	}
-#endif // for check
 	return 0;
 }
 
@@ -391,6 +382,16 @@
 	return 0;
 }
 
+/*
+ * Process after capture complete when paused.  Nothing to do.
+ */
+static int retire_paused_capture_urb(struct snd_usb_substream *subs,
+				     struct snd_pcm_runtime *runtime,
+				     struct urb *urb)
+{
+	return 0;
+}
+
 
 /*
  * prepare urb for full speed playback sync pipe
@@ -402,7 +403,7 @@
 				     struct snd_pcm_runtime *runtime,
 				     struct urb *urb)
 {
-	struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
+	struct snd_urb_ctx *ctx = urb->context;
 
 	urb->dev = ctx->subs->dev; /* we need to set this at each time */
 	urb->iso_frame_desc[0].length = 3;
@@ -420,7 +421,7 @@
 					struct snd_pcm_runtime *runtime,
 					struct urb *urb)
 {
-	struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
+	struct snd_urb_ctx *ctx = urb->context;
 
 	urb->dev = ctx->subs->dev; /* we need to set this at each time */
 	urb->iso_frame_desc[0].length = 4;
@@ -493,13 +494,13 @@
 }
 
 /*
- * Prepare urb for streaming before playback starts.
+ * Prepare urb for streaming before playback starts or when paused.
  *
- * We don't yet have data, so we send a frame of silence.
+ * We don't have any data, so we send a frame of silence.
  */
-static int prepare_startup_playback_urb(struct snd_usb_substream *subs,
-					struct snd_pcm_runtime *runtime,
-					struct urb *urb)
+static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
+				       struct snd_pcm_runtime *runtime,
+				       struct urb *urb)
 {
 	unsigned int i, offs, counts;
 	struct snd_urb_ctx *ctx = urb->context;
@@ -537,7 +538,7 @@
 	unsigned int counts;
 	unsigned long flags;
 	int period_elapsed = 0;
-	struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
+	struct snd_urb_ctx *ctx = urb->context;
 
 	stride = runtime->frame_bits >> 3;
 
@@ -622,7 +623,7 @@
  */
 static struct snd_urb_ops audio_urb_ops[2] = {
 	{
-		.prepare =	prepare_startup_playback_urb,
+		.prepare =	prepare_nodata_playback_urb,
 		.retire =	retire_playback_urb,
 		.prepare_sync =	prepare_playback_sync_urb,
 		.retire_sync =	retire_playback_sync_urb,
@@ -637,7 +638,7 @@
 
 static struct snd_urb_ops audio_urb_ops_high_speed[2] = {
 	{
-		.prepare =	prepare_startup_playback_urb,
+		.prepare =	prepare_nodata_playback_urb,
 		.retire =	retire_playback_urb,
 		.prepare_sync =	prepare_playback_sync_urb_hs,
 		.retire_sync =	retire_playback_sync_urb_hs,
@@ -655,7 +656,7 @@
  */
 static void snd_complete_urb(struct urb *urb)
 {
-	struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
+	struct snd_urb_ctx *ctx = urb->context;
 	struct snd_usb_substream *subs = ctx->subs;
 	struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
 	int err = 0;
@@ -678,7 +679,7 @@
  */
 static void snd_complete_sync_urb(struct urb *urb)
 {
-	struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
+	struct snd_urb_ctx *ctx = urb->context;
 	struct snd_usb_substream *subs = ctx->subs;
 	struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
 	int err = 0;
@@ -925,10 +926,14 @@
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		subs->ops.prepare = prepare_playback_urb;
 		return 0;
 	case SNDRV_PCM_TRIGGER_STOP:
 		return deactivate_urbs(subs, 0, 0);
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		subs->ops.prepare = prepare_nodata_playback_urb;
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -944,9 +949,16 @@
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
+		subs->ops.retire = retire_capture_urb;
 		return start_urbs(subs, substream->runtime);
 	case SNDRV_PCM_TRIGGER_STOP:
 		return deactivate_urbs(subs, 0, 0);
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		subs->ops.retire = retire_paused_capture_urb;
+		return 0;
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		subs->ops.retire = retire_capture_urb;
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -1408,7 +1420,7 @@
 static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *hw_params)
 {
-	struct snd_usb_substream *subs = (struct snd_usb_substream *)substream->runtime->private_data;
+	struct snd_usb_substream *subs = substream->runtime->private_data;
 	struct audioformat *fmt;
 	unsigned int channels, rate, format;
 	int ret, changed;
@@ -1464,7 +1476,7 @@
  */
 static int snd_usb_hw_free(struct snd_pcm_substream *substream)
 {
-	struct snd_usb_substream *subs = (struct snd_usb_substream *)substream->runtime->private_data;
+	struct snd_usb_substream *subs = substream->runtime->private_data;
 
 	subs->cur_audiofmt = NULL;
 	subs->cur_rate = 0;
@@ -1505,33 +1517,20 @@
 	/* for playback, submit the URBs now; otherwise, the first hwptr_done
 	 * updates for all URBs would happen at the same time when starting */
 	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
-		subs->ops.prepare = prepare_startup_playback_urb;
+		subs->ops.prepare = prepare_nodata_playback_urb;
 		return start_urbs(subs, runtime);
 	} else
 		return 0;
 }
 
-static struct snd_pcm_hardware snd_usb_playback =
+static struct snd_pcm_hardware snd_usb_hardware =
 {
 	.info =			SNDRV_PCM_INFO_MMAP |
 				SNDRV_PCM_INFO_MMAP_VALID |
 				SNDRV_PCM_INFO_BATCH |
 				SNDRV_PCM_INFO_INTERLEAVED |
-				SNDRV_PCM_INFO_BLOCK_TRANSFER,
-	.buffer_bytes_max =	1024 * 1024,
-	.period_bytes_min =	64,
-	.period_bytes_max =	512 * 1024,
-	.periods_min =		2,
-	.periods_max =		1024,
-};
-
-static struct snd_pcm_hardware snd_usb_capture =
-{
-	.info =			SNDRV_PCM_INFO_MMAP |
-				SNDRV_PCM_INFO_MMAP_VALID |
-				SNDRV_PCM_INFO_BATCH |
-				SNDRV_PCM_INFO_INTERLEAVED |
-				SNDRV_PCM_INFO_BLOCK_TRANSFER,
+				SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				SNDRV_PCM_INFO_PAUSE,
 	.buffer_bytes_max =	1024 * 1024,
 	.period_bytes_min =	64,
 	.period_bytes_max =	512 * 1024,
@@ -1810,28 +1809,33 @@
 static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
 				  struct snd_usb_substream *subs)
 {
-	struct list_head *p;
-	struct snd_pcm_hw_constraint_list constraints_rates;
+	struct audioformat *fp;
+	int count = 0, needs_knot = 0;
 	int err;
 
-	list_for_each(p, &subs->fmt_list) {
-		struct audioformat *fp;
-		fp = list_entry(p, struct audioformat, list);
-
-		if (!fp->needs_knot)
-			continue;
-
-		constraints_rates.count = fp->nr_rates;
-		constraints_rates.list = fp->rate_table;
-		constraints_rates.mask = 0;
-
-		err = snd_pcm_hw_constraint_list(runtime, 0,
-			SNDRV_PCM_HW_PARAM_RATE,
-			&constraints_rates);
-
-		if (err < 0)
-			return err;
+	list_for_each_entry(fp, &subs->fmt_list, list) {
+		if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
+			return 0;
+		count += fp->nr_rates;
+		if (fp->needs_knot)
+			needs_knot = 1;
 	}
+	if (!needs_knot)
+		return 0;
+
+	subs->rate_list.count = count;
+	subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL);
+	subs->rate_list.mask = 0;
+	count = 0;
+	list_for_each_entry(fp, &subs->fmt_list, list) {
+		int i;
+		for (i = 0; i < fp->nr_rates; i++)
+			subs->rate_list.list[count++] = fp->rate_table[i];
+	}
+	err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+					 &subs->rate_list);
+	if (err < 0)
+		return err;
 
 	return 0;
 }
@@ -1904,8 +1908,7 @@
 	return 0;
 }
 
-static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction,
-			    struct snd_pcm_hardware *hw)
+static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
 {
 	struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1913,7 +1916,7 @@
 
 	subs->interface = -1;
 	subs->format = 0;
-	runtime->hw = *hw;
+	runtime->hw = snd_usb_hardware;
 	runtime->private_data = subs;
 	subs->pcm_substream = substream;
 	return setup_hw_info(runtime, subs);
@@ -1934,7 +1937,7 @@
 
 static int snd_usb_playback_open(struct snd_pcm_substream *substream)
 {
-	return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK, &snd_usb_playback);
+	return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK);
 }
 
 static int snd_usb_playback_close(struct snd_pcm_substream *substream)
@@ -1944,7 +1947,7 @@
 
 static int snd_usb_capture_open(struct snd_pcm_substream *substream)
 {
-	return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE, &snd_usb_capture);
+	return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE);
 }
 
 static int snd_usb_capture_close(struct snd_pcm_substream *substream)
@@ -2231,6 +2234,7 @@
 		kfree(fp->rate_table);
 		kfree(fp);
 	}
+	kfree(subs->rate_list.list);
 }
 
 
@@ -2456,6 +2460,7 @@
 		 * build the rate table and bitmap flags
 		 */
 		int r, idx, c;
+		unsigned int nonzero_rates = 0;
 		/* this table corresponds to the SNDRV_PCM_RATE_XXX bit */
 		static unsigned int conv_rates[] = {
 			5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
@@ -2478,6 +2483,7 @@
 			    fp->altsetting == 5 && fp->maxpacksize == 392)
 				rate = 96000;
 			fp->rate_table[r] = rate;
+			nonzero_rates |= rate;
 			if (rate < fp->rate_min)
 				fp->rate_min = rate;
 			else if (rate > fp->rate_max)
@@ -2493,6 +2499,10 @@
 			if (!found)
 				fp->needs_knot = 1;
 		}
+		if (!nonzero_rates) {
+			hwc_debug("All rates were zero. Skipping format!\n");
+			return -1;
+		}
 		if (fp->needs_knot)
 			fp->rates |= SNDRV_PCM_RATE_KNOT;
 	} else {
@@ -3057,6 +3067,58 @@
 	return 0;
 }
 
+/*
+ * Create a stream for an Edirol UA-101 interface.
+ * Copy, paste and modify from Edirol UA-1000
+ */
+static int create_ua101_quirk(struct snd_usb_audio *chip,
+			       struct usb_interface *iface,
+			       const struct snd_usb_audio_quirk *quirk)
+{
+	static const struct audioformat ua101_format = {
+		.format = SNDRV_PCM_FORMAT_S32_LE,
+		.fmt_type = USB_FORMAT_TYPE_I,
+		.altsetting = 1,
+		.altset_idx = 1,
+		.attributes = 0,
+		.rates = SNDRV_PCM_RATE_CONTINUOUS,
+	};
+	struct usb_host_interface *alts;
+	struct usb_interface_descriptor *altsd;
+	struct audioformat *fp;
+	int stream, err;
+
+	if (iface->num_altsetting != 2)
+		return -ENXIO;
+	alts = &iface->altsetting[1];
+	altsd = get_iface_desc(alts);
+	if (alts->extralen != 18 || alts->extra[1] != USB_DT_CS_INTERFACE ||
+	    altsd->bNumEndpoints != 1)
+		return -ENXIO;
+
+	fp = kmemdup(&ua101_format, sizeof(*fp), GFP_KERNEL);
+	if (!fp)
+		return -ENOMEM;
+
+	fp->channels = alts->extra[11];
+	fp->iface = altsd->bInterfaceNumber;
+	fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
+	fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+	fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
+	fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]);
+
+	stream = (fp->endpoint & USB_DIR_IN)
+		? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+	err = add_audio_endpoint(chip, stream, fp);
+	if (err < 0) {
+		kfree(fp);
+		return err;
+	}
+	/* FIXME: playback must be synchronized to capture */
+	usb_set_interface(chip->dev, fp->iface, 0);
+	return 0;
+}
+
 static int snd_usb_create_quirk(struct snd_usb_audio *chip,
 				struct usb_interface *iface,
 				const struct snd_usb_audio_quirk *quirk);
@@ -3238,6 +3300,7 @@
 		[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
 		[QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk,
 		[QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
+		[QUIRK_AUDIO_EDIROL_UA101] = create_ua101_quirk,
 	};
 
 	if (quirk->type < QUIRK_TYPE_COUNT) {
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 0f4b2b8..2272f45 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -159,6 +159,7 @@
 	QUIRK_AUDIO_FIXED_ENDPOINT,
 	QUIRK_AUDIO_EDIROL_UA700_UA25,
 	QUIRK_AUDIO_EDIROL_UA1000,
+	QUIRK_AUDIO_EDIROL_UA101,
 
 	QUIRK_TYPE_COUNT
 };
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index a7e9563..8582620 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -948,6 +948,29 @@
 },
 	/* TODO: add Edirol M-100FX support */
 {
+	/* has ID 0x004e when not in "Advanced Driver" mode */
+	USB_DEVICE(0x0582, 0x004c),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		.vendor_name = "EDIROL",
+		.product_name = "PCR-A",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 1,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
+{
 	/* has ID 0x004f when not in "Advanced Driver" mode */
 	USB_DEVICE(0x0582, 0x004d),
 	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
@@ -1098,7 +1121,37 @@
 		}
 	}
 },
-	/* TODO: add Edirol UA-101 support */
+/* Roland UA-101 in High-Speed Mode only */
+{
+	USB_DEVICE(0x0582, 0x007d),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		.vendor_name = "Roland",
+		.product_name = "UA-101",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_AUDIO_EDIROL_UA101
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_AUDIO_EDIROL_UA101
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const struct snd_usb_midi_endpoint_info) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 {
 	/* has ID 0x0081 when not in "Advanced Driver" mode */
 	USB_DEVICE(0x0582, 0x0080),
diff --git a/usr/Makefile b/usr/Makefile
index 382702a..201f27f 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -7,7 +7,7 @@
 
 
 # Generate builtin.o based on initramfs_data.o
-obj-y := initramfs_data.o
+obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data.o
 
 # initramfs_data.o contains the initramfs_data.cpio.gz image.
 # The image is included using .incbin, a dependency which is not
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index 83acd6c..8365db6 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -14,6 +14,7 @@
  * Original work by Jeff Garzik
  *
  * External file lists, symlink, pipe and fifo support by Thayne Harbaugh
+ * Hard link support by Luciano Rocha
  */
 
 #define xstr(s) #s
@@ -286,16 +287,19 @@
 	return rc;
 }
 
-/* Not marked static to keep the compiler quiet, as no one uses this yet... */
 static int cpio_mkfile(const char *name, const char *location,
-			unsigned int mode, uid_t uid, gid_t gid)
+			unsigned int mode, uid_t uid, gid_t gid,
+			unsigned int nlinks)
 {
 	char s[256];
 	char *filebuf = NULL;
 	struct stat buf;
+	long size;
 	int file = -1;
 	int retval;
 	int rc = -1;
+	int namesize;
+	int i;
 
 	mode |= S_IFREG;
 
@@ -323,29 +327,41 @@
 		goto error;
 	}
 
-	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
-	       "%08X%08X%08X%08X%08X%08X%08X",
-		"070701",		/* magic */
-		ino++,			/* ino */
-		mode,			/* mode */
-		(long) uid,		/* uid */
-		(long) gid,		/* gid */
-		1,			/* nlink */
-		(long) buf.st_mtime,	/* mtime */
-		(int) buf.st_size,	/* filesize */
-		3,			/* major */
-		1,			/* minor */
-		0,			/* rmajor */
-		0,			/* rminor */
-		(unsigned)strlen(name) + 1,/* namesize */
-		0);			/* chksum */
-	push_hdr(s);
-	push_string(name);
-	push_pad();
+	size = 0;
+	for (i = 1; i <= nlinks; i++) {
+		/* data goes on last link */
+		if (i == nlinks) size = buf.st_size;
 
-	fwrite(filebuf, buf.st_size, 1, stdout);
-	offset += buf.st_size;
-	push_pad();
+		namesize = strlen(name) + 1;
+		sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
+		       "%08lX%08X%08X%08X%08X%08X%08X",
+			"070701",		/* magic */
+			ino,			/* ino */
+			mode,			/* mode */
+			(long) uid,		/* uid */
+			(long) gid,		/* gid */
+			nlinks,			/* nlink */
+			(long) buf.st_mtime,	/* mtime */
+			size,			/* filesize */
+			3,			/* major */
+			1,			/* minor */
+			0,			/* rmajor */
+			0,			/* rminor */
+			namesize,		/* namesize */
+			0);			/* chksum */
+		push_hdr(s);
+		push_string(name);
+		push_pad();
+
+		if (size) {
+			fwrite(filebuf, size, 1, stdout);
+			offset += size;
+			push_pad();
+		}
+
+		name += namesize;
+	}
+	ino++;
 	rc = 0;
 	
 error:
@@ -357,18 +373,51 @@
 static int cpio_mkfile_line(const char *line)
 {
 	char name[PATH_MAX + 1];
+	char *dname = NULL; /* malloc'ed buffer for hard links */
 	char location[PATH_MAX + 1];
 	unsigned int mode;
 	int uid;
 	int gid;
+	int nlinks = 1;
+	int end = 0, dname_len = 0;
 	int rc = -1;
 
-	if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, location, &mode, &uid, &gid)) {
+	if (5 > sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX)
+				"s %o %d %d %n",
+				name, location, &mode, &uid, &gid, &end)) {
 		fprintf(stderr, "Unrecognized file format '%s'", line);
 		goto fail;
 	}
-	rc = cpio_mkfile(name, location, mode, uid, gid);
+	if (end && isgraph(line[end])) {
+		int len;
+		int nend;
+
+		dname = malloc(strlen(line));
+		if (!dname) {
+			fprintf (stderr, "out of memory (%d)\n", dname_len);
+			goto fail;
+		}
+
+		dname_len = strlen(name) + 1;
+		memcpy(dname, name, dname_len);
+
+		do {
+			nend = 0;
+			if (sscanf(line + end, "%" str(PATH_MAX) "s %n",
+					name, &nend) < 1)
+				break;
+			len = strlen(name) + 1;
+			memcpy(dname + dname_len, name, len);
+			dname_len += len;
+			nlinks++;
+			end += nend;
+		} while (isgraph(line[end]));
+	} else {
+		dname = name;
+	}
+	rc = cpio_mkfile(dname, location, mode, uid, gid, nlinks);
  fail:
+	if (dname_len) free(dname);
 	return rc;
 }
 
@@ -381,22 +430,23 @@
 		"describe the files to be included in the initramfs archive:\n"
 		"\n"
 		"# a comment\n"
-		"file <name> <location> <mode> <uid> <gid>\n"
+		"file <name> <location> <mode> <uid> <gid> [<hard links>]\n"
 		"dir <name> <mode> <uid> <gid>\n"
 		"nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n"
 		"slink <name> <target> <mode> <uid> <gid>\n"
 		"pipe <name> <mode> <uid> <gid>\n"
 		"sock <name> <mode> <uid> <gid>\n"
 		"\n"
-		"<name>      name of the file/dir/nod/etc in the archive\n"
-		"<location>  location of the file in the current filesystem\n"
-		"<target>    link target\n"
-		"<mode>      mode/permissions of the file\n"
-		"<uid>       user id (0=root)\n"
-		"<gid>       group id (0=root)\n"
-		"<dev_type>  device type (b=block, c=character)\n"
-		"<maj>       major number of nod\n"
-		"<min>       minor number of nod\n"
+		"<name>       name of the file/dir/nod/etc in the archive\n"
+		"<location>   location of the file in the current filesystem\n"
+		"<target>     link target\n"
+		"<mode>       mode/permissions of the file\n"
+		"<uid>        user id (0=root)\n"
+		"<gid>        group id (0=root)\n"
+		"<dev_type>   device type (b=block, c=character)\n"
+		"<maj>        major number of nod\n"
+		"<min>        minor number of nod\n"
+		"<hard links> space separated list of other links to file\n"
 		"\n"
 		"example:\n"
 		"# A simple initramfs\n"